-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutils.py
237 lines (199 loc) · 9.46 KB
/
utils.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
import time
import numpy as np
import random
import matplotlib.pyplot as plt
def load_csv(path):
"""
Load the CSV form of MNIST data without any external library
:param path: the path of the csv file
:return:
data: A list of list where each sub-list with 28x28 elements
corresponding to the pixels in each image
labels: A list containing labels of images
"""
data = []
labels = []
with open(path, 'r') as fp:
images = fp.readlines()
images = [img.rstrip() for img in images]
for img in images:
img_as_list = img.split(',')
y = int(img_as_list[0]) # first entry as label
x = img_as_list[1:]
x = [int(px) / 255 for px in x]
data.append(x)
labels.append(y)
return data, labels
def load_mnist_trainval():
"""
Load MNIST training data with labels
:return:
train_data: A list of list containing the training data
train_label: A list containing the labels of training data
val_data: A list of list containing the validation data
val_label: A list containing the labels of validation data
"""
# Load training data
print("Loading training data...")
data, label = load_csv('./data/mnist_train.csv')
assert len(data) == len(label)
print("Training data loaded with {count} images".format(count=len(data)))
# split training/validation data
train_data = None
train_label = None
val_data = None
val_label = None
#############################################################################
# TODO: #
# 1) Split the entire training set to training data and validation #
# data. Use 80% of your data for training and 20% of your data for #
# validation. Note: Don't shuffle here. #
#############################################################################
train_size = int(.8 * len(data))
train_data, val_data = data[:train_size], data[train_size:]
train_label, val_label = label[:train_size], label[train_size:]
#############################################################################
# END OF YOUR CODE #
#############################################################################
return train_data, train_label, val_data, val_label
def load_mnist_test():
"""
Load MNIST testing data with labels
:return:
data: A list of list containing the testing data
label: A list containing the labels of testing data
"""
# Load training data
print("Loading testing data...")
data, label = load_csv('./data/mnist_test.csv')
assert len(data) == len(label)
print("Testing data loaded with {count} images".format(count=len(data)))
return data, label
def generate_batched_data(data, label, batch_size=32, shuffle=False, seed=None):
"""
Turn raw data into batched forms
:param data: A list of list containing the data where each inner list contains 28x28
elements corresponding to pixel values in images: [[pix1, ..., pix784], ..., [pix1, ..., pix784]]
:param label: A list containing the labels of data
:param batch_size: required batch size
:param shuffle: Whether to shuffle the data: true for training and False for testing
:return:
batched_data: (List[np.ndarray]) A list whose elements are batches of images.
batched_label: (List[np.ndarray]) A list whose elements are batches of labels.
"""
batched_data = []
batched_label = []
if seed:
random.seed(seed)
np.random.seed(seed)
#############################################################################
# TODO: #
# 1) Shuffle data and label if shuffle=True #
# In order to match expected output use random.shuffle(), not numpy #
# 2) Generate batches of images with the required batch size #
# It's okay if the size of your last batch is smaller than the required #
# batch size #
#############################################################################
# indices = list(range(len(data)))
# if shuffle:
# random.shuffle(indices)
# equal = len(indices) - (len(indices) % batch_size)
# batched_indices = np.array_split(indices[:equal], equal//batch_size)
# batched_indices.append(indices[equal:])
# for index_batch in batched_indices:
# batched_data.append(np.take(data, index_batch))
# batched_label.append(np.take(label, index_batch))
data_label = list(zip(data,label))
if shuffle:
random.shuffle(data_label)
data,label = list(zip(*data_label))
data = np.array(data)
label = np.array(label)
num_batches = int(len(label) / batch_size)
for i in range(num_batches):
batched_data.append(data[i*batch_size:i*batch_size+batch_size])
batched_label.append(label[i*batch_size:i*batch_size+batch_size])
# idx = np.random.choice(data.shape[0], batch_size)
# batched_data,batched_label = data[idx],label[idx]
#############################################################################
# END OF YOUR CODE #
#############################################################################
return batched_data, batched_label
def train(epoch, batched_train_data, batched_train_label, model, optimizer, debug=True):
"""
A training function that trains the model for one epoch
:param epoch: The index of current epoch
:param batched_train_data: A list containing batches of images
:param batched_train_label: A list containing batches of labels
:param model: The model to be trained
:param optimizer: The optimizer that updates the network weights
:return:
epoch_loss: The average loss of current epoch
epoch_acc: The overall accuracy of current epoch
"""
epoch_loss = 0.0
hits = 0
count_samples = 0.0
for idx, (input, target) in enumerate(zip(batched_train_data, batched_train_label)):
start_time = time.time()
loss, accuracy = model.forward(input, target)
optimizer.update(model)
epoch_loss += loss
hits += accuracy * input.shape[0]
count_samples += input.shape[0]
forward_time = time.time() - start_time
if idx % 10 == 0 and debug:
print(('Epoch: [{0}][{1}/{2}]\t'
'Batch Time {batch_time:.3f} \t'
'Batch Loss {loss:.4f}\t'
'Train Accuracy ' + "{accuracy:.4f}" '\t').format(
epoch, idx, len(batched_train_data), batch_time=forward_time,
loss=loss, accuracy=accuracy))
epoch_loss /= len(batched_train_data)
epoch_acc = hits / count_samples
if debug:
print("* Average Accuracy of Epoch {} is: {:.4f}".format(epoch, epoch_acc))
return epoch_loss, epoch_acc
def evaluate(batched_test_data, batched_test_label, model, debug=True):
"""
Evaluate the model on test data
:param batched_test_data: A list containing batches of test images
:param batched_test_label: A list containing batches of labels
:param model: A pre-trained model
:return:
epoch_loss: The average loss of current epoch
epoch_acc: The overall accuracy of current epoch
"""
epoch_loss = 0.0
hits = 0
count_samples = 0.0
for idx, (input, target) in enumerate(zip(batched_test_data, batched_test_label)):
loss, accuracy = model.forward(input, target, mode='valid')
epoch_loss += loss
hits += accuracy * input.shape[0]
count_samples += input.shape[0]
if debug:
print(('Evaluate: [{0}/{1}]\t'
'Batch Accuracy ' + "{accuracy:.4f}" '\t').format(
idx, len(batched_test_data), accuracy=accuracy))
epoch_loss /= len(batched_test_data)
epoch_acc = hits / count_samples
return epoch_loss, epoch_acc
def plot_curves(train_loss_history, train_acc_history, valid_loss_history, valid_acc_history):
"""
Plot learning curves with matplotlib. Make sure training loss and validation loss are plot in the same figure and
training accuracy and validation accuracy are plot in the same figure too.
:param train_loss_history: training loss history of epochs
:param train_acc_history: training accuracy history of epochs
:param valid_loss_history: validation loss history of epochs
:param valid_acc_history: validation accuracy history of epochs
:return: None, save two figures in the current directory
"""
#############################################################################
# TODO: #
# 1) Plot learning curves of training and validation loss #
# 2) Plot learning curves of training and validation accuracy #
#############################################################################
#############################################################################
# END OF YOUR CODE #
#############################################################################