-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathcifar100.py
253 lines (187 loc) · 8.02 KB
/
cifar100.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# -*- coding:utf-8 -*-
########################################################################
#
# Functions for downloading the CIFAR-100 data-set from the internet
# and loading it into memory.
#
# Implemented in Python 3.5
#
# Usage:
# 1) Set the variable data_path with the desired storage path.
# 2) Call maybe_download_and_extract() to download the data-set
# if it is not already located in the given data_path.
# 3) Call load_class_names() to get an array of the class-names.
# 4) Call load_training_data() and load_test_data() to get
# the images, class-numbers and one-hot encoded class-labels
# for the training-set and test-set.
# 5) Use the returned data in your own program.
#
# Format:
# The images for the training- and test-sets are returned as 4-dim numpy
# arrays each with the shape: [image_number, height, width, channel]
# where the individual pixels are floats between 0.0 and 1.0.
#
########################################################################
#
# This file is part of the TensorFlow Tutorials available at:
#
# https://github.com/Hvass-Labs/TensorFlow-Tutorials
#
# Published under the MIT License. See the file LICENSE for details.
#
# Copyright 2016 by Magnus Erik Hvass Pedersen
#
########################################################################
import numpy as np
import pickle
import os
########################################################################
# Directory where you want to download and save the data-set.
# Set this before you start calling any of the functions below.
data_path = "./"
# URL for the data-set on the internet.
data_url = "https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz"
########################################################################
# Various constants for the size of the images.
# Use these constants in your own program.
# Width and height of each image.
img_size = 32
# Number of channels in each image, 3 channels: Red, Green, Blue.
num_channels = 3
# Length of an image when flattened to a 1-dim array.
img_size_flat = img_size * img_size * num_channels
# Number of classes.
num_classes = 100
########################################################################
# Various constants used to allocate arrays of the correct size.
# Total number of images in the training-set.
# This is used to pre-allocate arrays for efficiency.
_num_images_train = 50000
########################################################################
# Private functions for downloading, unpacking and loading data-files.
def _get_file_path(filename=""):
"""
Return the full path of a data-file for the data-set.
If filename=="" then return the directory of the files.
"""
return os.path.join(data_path, "cifar-100-python/", filename)
def _unpickle(filename):
"""
Unpickle the given file and return the data.
Note that the appropriate dir-name is prepended the filename.
"""
# Create full path for the file.
file_path = _get_file_path(filename)
print("Loading data: " + file_path)
import sys
if sys.version_info <= (3, 3):
with open(file_path, mode='rb') as file:
# In Python 3.X it is important to set the encoding,
# otherwise an exception is raised here.
data = pickle.load(file)
else:
with open(file_path, mode='rb') as file:
# In Python 3.X it is important to set the encoding,
# otherwise an exception is raised here.
data = pickle.load(file, encoding='bytes')
return data
def _convert_images(raw):
"""
Convert images from the CIFAR-10 format and
return a 4-dim array with shape: [image_number, height, width, channel]
where the pixels are floats between 0.0 and 1.0.
"""
# Convert the raw images from the data-files to floating-points.
raw_float = np.array(raw, dtype=float) / 255.0
# Reshape the array to 4-dimensions.
images = raw_float.reshape([-1, num_channels, img_size, img_size])
# Reorder the indices of the array.
images = images.transpose([0, 2, 3, 1])
return images
def convert_images(raw, pixel_mean=None):
images = _convert_images(raw)
if pixel_mean is not None:
images = images - pixel_mean
return images
def _load_data(filename):
"""
Load a pickled data-file from the CIFAR-10 data-set
and return the converted images (see above) and the class-number
for each image.
"""
# Load the pickled data-file.
data = _unpickle(filename)
# Get the raw images.
raw_images = data[b'data']
# Get the class-numbers for each image. Convert to numpy-array.
cls = np.array(data[b'fine_labels'])
# Convert the images.
images = _convert_images(raw_images)
return images, cls, raw_images
########################################################################
# Public functions that you may call to download the data-set from
# the internet and load the data into memory.
def load_class_names():
"""
Load the names for the classes in the CIFAR-10 data-set.
Returns a list with the names. Example: names[3] is the name
associated with class-number 3.
"""
# Load the class-names from the pickled file.
raw = _unpickle(filename="meta")[b'fine_label_names']
# Convert from binary strings.
names = [x.decode('utf-8') for x in raw]
return names
def load_data(order, mean_subtraction=True):
images_train, cls_train, one_hot_encoded_cls_train, raw_images_train = load_training_data(order)
images_test, cls_test, one_hot_encoded_cls_test, raw_images_test = load_test_data(order)
pixel_mean = np.mean(images_train, axis=0)
if mean_subtraction:
images_train = images_train - pixel_mean
images_test = images_test - pixel_mean
return images_train, cls_train, one_hot_encoded_cls_train, \
images_test, cls_test, one_hot_encoded_cls_test, \
raw_images_train, raw_images_test, pixel_mean
def change_order(cls, order):
order_dict = dict()
for i in range(len(order)):
order_dict[order[i]] = i
reordered_cls = np.array([order_dict[cls[i]] for i in range(len(cls))])
return reordered_cls
def load_training_data(order):
"""
Load all the training-data for the CIFAR-10 data-set.
The data-set is split into 5 data-files which are merged here.
Returns the images, class-numbers and one-hot encoded class-labels.
"""
# Load the images and class-numbers from the data-file.
images, cls, raw_images = _load_data(filename="train")
cls = change_order(cls, order)
return images, cls, one_hot_encoded(class_numbers=cls, num_classes=num_classes), raw_images
def load_test_data(order):
"""
Load all the test-data for the CIFAR-10 data-set.
Returns the images, class-numbers and one-hot encoded class-labels.
"""
images, cls, raw_images = _load_data(filename="test")
cls = change_order(cls, order)
return images, cls, one_hot_encoded(class_numbers=cls, num_classes=num_classes), raw_images
def one_hot_encoded(class_numbers, num_classes=None):
"""
Generate the One-Hot encoded class-labels from an array of integers.
For example, if class_number=2 and num_classes=4 then
the one-hot encoded label is the float array: [0. 0. 1. 0.]
:param class_numbers:
Array of integers with class-numbers.
Assume the integers are from zero to num_classes-1 inclusive.
:param num_classes:
Number of classes. If None then use max(class_numbers)+1.
:return:
2-dim array of shape: [len(class_numbers), num_classes]
"""
# Find the number of classes if None is provided.
# Assumes the lowest class-number is zero.
if num_classes is None:
num_classes = np.max(class_numbers) + 1
return np.eye(num_classes, dtype=float)[class_numbers]
########################################################################