-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmnist3x3.py
291 lines (217 loc) · 10.9 KB
/
mnist3x3.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
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
# -*- coding: utf-8 -*-
"""mnist3x3.ipynb
Automatically generated by Colaboratory.
MNIST digits classification using 3x3 pixels basis function.
Environment
*Google Colaboratory (GPU) with Microsoft Edge 87.0.664.47
*Python 3.6.9
*tensorflow 2.3.0
*tensorboard 2.3.0
*numpy 1.18.5
*matplotlib 3.2.2
"""
# Commented out IPython magic to ensure Python compatibility.
# magic command in google colaboratory to Load the TensorBoard notebook extension
# %load_ext tensorboard
# Commented out IPython magic to ensure Python compatibility.
# magic command in google colaboratory to run tensorboard
# %tensorboard --logdir logs
#coding:utf-8
# START MAIN PROGRAM HERE !
import tensorflow as tf
import numpy as np
import os
from tensorflow.keras.layers import Dense, Conv2D, Input, Lambda, Flatten
from tensorflow.keras.layers import Add, Reshape, MaxPooling2D
from tensorflow.keras.models import Model
from tensorflow.keras import backend as K
from tensorflow.keras.datasets import mnist
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.callbacks import TensorBoard
def SabunModel(r_s3, s3=3, lout=128):
xin = Input(shape = (s3, s3, lout)) # (s3,s3,lout)
out = Lambda(lambda x: K.abs( x - K.reshape(r_s3,(s3,s3,1))) , output_shape=(s3,s3,lout))(xin) # compute absolute value of difference
out = Lambda(lambda x: K.mean(x, axis=-2,keepdims=False), output_shape=(s3,lout))(out) # compute average step1
out = Lambda(lambda x: K.mean(x, axis=-2,keepdims=True), output_shape=(1,lout))(out) # compute average step2
return Model(inputs=[xin], outputs=out)
if __name__ == '__main__':
nb_classes = 10 # digits numebr, that are 0,1,2,3,4,5,6,7,8,9
# Load MNIST dataset
(X_train, y_train), (X_test, y_test) = mnist.load_data()
print("X_train original shape", X_train.shape)
print("y_train original shape", y_train.shape)
X_train = X_train.reshape(60000, 28,28,1) # train dataset (60000 samples, 28x28 pixels, color 1)
X_test = X_test.reshape(10000, 28,28,1) # validation dataset (10000 samples, 28x28 pixels, color 1)
# transform from grayscale integer value to float 0.0-1.0
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255
X_test /= 255
print("Training matrix shape", X_train.shape)
print("Testing matrix shape", X_test.shape)
# transform from label integer to one-hot vector ex: [0,0,1,0,0]
Y_train = to_categorical(y_train, nb_classes)
Y_test = to_categorical(y_test, nb_classes)
# eleven 3x3 pixels basis functions definition
s3=3 # size of pixel
# 1st
r1_s3 = tf.constant([[0, 1, 0], \
[0, 1, 0], \
[0, 1, 0]], dtype='float32')
# 2nd
r2_s3 = tf.constant([[0, 0, 1], \
[0, 0, 1], \
[0, 0, 1]], dtype='float32')
# 3rd
r3_s3 = tf.constant([[1, 0, 0], \
[1, 0, 0], \
[1, 0, 0]], dtype='float32')
# 4th
r4_s3 = tf.constant([[0, 0, 0], \
[0, 0, 0], \
[1, 1, 1]], dtype='float32')
# 5th
r5_s3 = tf.constant([[0, 0, 0], \
[1, 1, 1], \
[0, 0, 0]], dtype='float32')
# 6yh
r6_s3 = tf.constant([[1, 1, 1], \
[0, 0, 0], \
[0, 0, 0]], dtype='float32')
# 7th
r7_s3 = tf.constant([[1, 1, 1], \
[0, 0, 1], \
[1, 1, 1]], dtype='float32')
# 8th
r8_s3 = tf.constant([[1, 1, 1], \
[1, 0, 0], \
[1, 1, 1]], dtype='float32')
# 9th
r9_s3 = tf.constant([[1, 1, 1], \
[1, 0, 1], \
[1, 1, 1]], dtype='float32')
# 10th
r10_s3 = tf.constant([[0, 0, 1], \
[0, 1, 0], \
[1, 0, 0]], dtype='float32')
# 11th
r11_s3 = tf.constant([[1, 0, 0], \
[0, 1, 0], \
[0, 0, 1]], dtype='float32')
# number of output layer
lout=128
# input image 28x28 pixels 1 color
inp = Input(shape = (28,28,1))
# downsize input image from 28x28 pixels to 3x3 pixels using CNN and MaxPooling
x = Conv2D(32,(2,2),activation='relu', padding='same')(inp) # (28,28,32)
x = MaxPooling2D(pool_size=(2, 2), strides=(2,2), padding='valid' )(x) # (14,14,32)
x = Conv2D(lout,(2,2),activation='relu')(x) # (13,13,128)
x = MaxPooling2D(pool_size=(2, 2), strides=(2,2), padding='valid')(x) # (6,6,128)
x = Conv2D(lout,(2,2),activation='relu')(x) # (5,5,128)
x = MaxPooling2D(pool_size=(2, 2), strides=(1,1), padding='valid')(x) # (4,4,128)
x3 = Conv2D(lout,(2,2),activation='sigmoid')(x) # (3,3,128) # use sigmoid to output range in 0-1.0
if True:
# compute absolute value of difference from 3x3 pixels basis function
sabun1= SabunModel(r1_s3, s3=s3, lout=lout)
x31 = sabun1([x3]) # (1,128)
sabun2= SabunModel(r2_s3, s3=s3, lout=lout)
x32 = sabun2([x3])
sabun3= SabunModel(r3_s3, s3=s3, lout=lout)
x33 = sabun3([x3])
sabun4= SabunModel(r4_s3, s3=s3, lout=lout)
x34 = sabun4([x3])
sabun5= SabunModel(r5_s3, s3=s3, lout=lout)
x35 = sabun5([x3])
sabun6= SabunModel(r6_s3, s3=s3, lout=lout)
x36 = sabun6([x3])
sabun7= SabunModel(r7_s3, s3=s3, lout=lout)
x37 = sabun7([x3])
sabun8= SabunModel(r8_s3, s3=s3, lout=lout)
x38 = sabun8([x3])
sabun9= SabunModel(r9_s3, s3=s3, lout=lout)
x39 = sabun9([x3])
sabun10= SabunModel(r10_s3, s3=s3, lout=lout)
x310 = sabun10([x3])
sabun11= SabunModel(r11_s3, s3=s3, lout=lout)
x311 = sabun11([x3])
# concatenate all eleven difference
x3 = Lambda(lambda x: K.concatenate([x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10]], axis=-1),\
output_shape=(1,lout*11))([x31,x32,x33,x34,x35,x36,x37,x38,x39,x310,x311]) # (1,1408)
# in case of use nine basis functions except 1st and 10th
#x3 = Lambda(lambda x: K.concatenate([x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8]], axis=-1),\
# output_shape=(1,lout*9))([x32,x33,x34,x35,x36,x37,x38,x39,x311]) # (1,1152)
# flatten to Dense input
x = Flatten()(x3) # (1408)
# transform (1408) to 10 digits probability using one fully-connected layer
x = Dense(10, activation='softmax')(x) # softmax
# sequential model definition
model = Model(inputs=inp, outputs=x)
print(model.summary()) # show model summary
# model compile
model.compile(loss='categorical_crossentropy', optimizer='adam',metrics=['accuracy'])
# set tensorboard as callback. output will be save in log_dir
tbCallBack = TensorBoard(log_dir='logs', histogram_freq=0, write_graph=True, write_images=True)
# weight file
F_name='mnist_model1_weights.h5' # file name
if True: # load weight if previous weight file exists
if os.path.exists(F_name):
model.load_weights(F_name)
print ('load weights from ', F_name)
# set number of epoch !
N_epoch=100
#
model.fit(X_train, Y_train, # train dataset
batch_size=128, # batch seze
epochs= N_epoch, # epoch
verbose=1, # show progress
validation_data=(X_test, Y_test), # validation dataset
callbacks=[tbCallBack] # callback
)
# save weight, at last
model.save_weights( F_name )
# show incorrect prediction image with binarization
if True:
# set maximum number how many show incorrect prediction image from the beginning
show_max_number=20
# compute prediction at once
predict = model.predict(X_test, batch_size=32,verbose=1) # predict of validation data
indexes = np.argmax(predict, axis=1) # get predict label index
incorrect_indexes=np.arange(len(y_test))[indexes != y_test] # get incorrect indexes
print ('number of incorrect image', len(incorrect_indexes))
predict_value= np.amax(predict,axis=1) # get predict value of predict label
true_value=np.choose(y_test, predict.T) # get predict value of true label
for i, id in enumerate(incorrect_indexes):
print ('id ', id)
print ('true_label', y_test[id], ' predict_label', indexes[id])
print ('value_of_true_label', true_value[id], ' value_of_predict_label', predict_value[id])
# show incorrect digit binarization image
for y in range(28):
for x in range(28):
if X_test[id,y,x] > 0.0:
print ( '1', end='')
else:
print ( '0', end='')
print('')
if i >= show_max_number :
break # show stop
# import matplotlib to draw heat map
import matplotlib.pyplot as plt
# Commented out IPython magic to ensure Python compatibility.
# magic command in google colaboratory to use matplotlib
# %matplotlib inline
# show heat map of weights of last fully-connected layer, Dense(10, ...
if True:
dense10 = model.layers[-1] # get weights of last fully-connected layer, Dense(10, ...
print(dense10.get_weights()[0]) # print out weights value
# draw heat map
fig = plt.figure(figsize=(9, 3))
ax = fig.add_subplot(1,1,1)
d10_weights= np.abs(dense10.get_weights()[0]).T
ax.pcolor(d10_weights, cmap=plt.cm.Reds) # set color map to draw heat map
ax.set_title(' heat map of weights of last fully-connected layer')
ax.set_ylabel('digits')
ax.set_xlabel('Dense inputs')
ax.set_xticks(np.arange(int(dense10.get_weights()[0].shape[0]/lout))*lout) # auxiliary scale per one basis function
ax.set_yticks(np.arange(10)) # auxiliary scale per digit
plt.tight_layout()
plt.show()