-
Notifications
You must be signed in to change notification settings - Fork 38
/
conviz.py
286 lines (223 loc) · 8.88 KB
/
conviz.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
from __future__ import print_function
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import os
import utils
# Import MNIST data
from tensorflow.examples.tutorials.mnist import input_data
PLOT_DIR = './out/plots'
def plot_conv_weights(weights, name, channels_all=True):
"""
Plots convolutional filters
:param weights: numpy array of rank 4
:param name: string, name of convolutional layer
:param channels_all: boolean, optional
:return: nothing, plots are saved on the disk
"""
# make path to output folder
plot_dir = os.path.join(PLOT_DIR, 'conv_weights')
plot_dir = os.path.join(plot_dir, name)
# create directory if does not exist, otherwise empty it
utils.prepare_dir(plot_dir, empty=True)
w_min = np.min(weights)
w_max = np.max(weights)
channels = [0]
# make a list of channels if all are plotted
if channels_all:
channels = range(weights.shape[2])
# get number of convolutional filters
num_filters = weights.shape[3]
# get number of grid rows and columns
grid_r, grid_c = utils.get_grid_dim(num_filters)
# create figure and axes
fig, axes = plt.subplots(min([grid_r, grid_c]),
max([grid_r, grid_c]))
# iterate channels
for channel in channels:
# iterate filters inside every channel
for l, ax in enumerate(axes.flat):
# get a single filter
img = weights[:, :, channel, l]
# put it on the grid
ax.imshow(img, vmin=w_min, vmax=w_max, interpolation='nearest', cmap='seismic')
# remove any labels from the axes
ax.set_xticks([])
ax.set_yticks([])
# save figure
plt.savefig(os.path.join(plot_dir, '{}-{}.png'.format(name, channel)), bbox_inches='tight')
def plot_conv_output(conv_img, name):
"""
Makes plots of results of performing convolution
:param conv_img: numpy array of rank 4
:param name: string, name of convolutional layer
:return: nothing, plots are saved on the disk
"""
# make path to output folder
plot_dir = os.path.join(PLOT_DIR, 'conv_output')
plot_dir = os.path.join(plot_dir, name)
# create directory if does not exist, otherwise empty it
utils.prepare_dir(plot_dir, empty=True)
w_min = np.min(conv_img)
w_max = np.max(conv_img)
# get number of convolutional filters
num_filters = conv_img.shape[3]
# get number of grid rows and columns
grid_r, grid_c = utils.get_grid_dim(num_filters)
# create figure and axes
fig, axes = plt.subplots(min([grid_r, grid_c]),
max([grid_r, grid_c]))
# iterate filters
for l, ax in enumerate(axes.flat):
# get a single image
img = conv_img[0, :, :, l]
# put it on the grid
ax.imshow(img, vmin=w_min, vmax=w_max, interpolation='bicubic', cmap='Greys')
# remove any labels from the axes
ax.set_xticks([])
ax.set_yticks([])
# save figure
plt.savefig(os.path.join(plot_dir, '{}.png'.format(name)), bbox_inches='tight')
mnist = input_data.read_data_sets("/tmp/data/", one_hot=True)
# Parameters
learning_rate = 0.001
training_iters = 10000
batch_size = 128
display_step = 10
# Network Parameters
n_input = 784 # MNIST data input (img shape: 28*28)
n_classes = 10 # MNIST total classes (0-9 digits)
dropout = 0.75 # Dropout, probability to keep units
# tf Graph input
x = tf.placeholder(tf.float32, [None, n_input])
y = tf.placeholder(tf.float32, [None, n_classes])
keep_prob = tf.placeholder(tf.float32) # dropout (keep probability)
def conv2d(x_, filter_size, filter_num, stride=1):
"""
Wrapper of a convolutional layer
:param x_: tensor, input to convolutional layer
:param filter_size: int, size of a convolutional kernel
:param filter_num: int, number of convolutional kernels
:param stride: int, optional, stride
:return: tensor
"""
# get number of channels in input
channels = x_.get_shape()[3].value
# create weights tensor
weights = tf.Variable(tf.random_normal([filter_size, filter_size, channels, filter_num]))
# add weights tensor to collection
tf.add_to_collection('conv_weights', weights)
# create bias tensor
bias = tf.Variable(tf.random_normal([filter_num]))
# apply weights and biases
preactivations = tf.nn.conv2d(x_, weights, strides=[1, stride, stride, 1], padding='SAME')
preactivations = tf.nn.bias_add(preactivations, bias)
# apply activation function, this is layer output
activations = tf.nn.relu(preactivations)
# add output to collection
tf.add_to_collection('conv_output', activations)
return activations
def fc(x_, nodes, keep_prob_=1, act=tf.nn.relu):
"""
Wrapper for fully-connected layer
:param x_: tensor, input to fully-connected alyer
:param nodes: int, number of nodes in layer
:param keep_prob_: float, optional, keep probability for dropout operation
:param act: tf.nn method, optional, activation function
:return: tensor
"""
shape = x_.get_shape()
# if rank of input tensor is greater than 2
# we need to reshape it
if shape.ndims > 2:
n = 1
for s in shape[1:]:
n *= s.value
x_ = tf.reshape(x_, tf.pack([-1, n]))
x_.set_shape([None, n])
# get number of column in input tensor
n = x_.get_shape()[1].value
# create weights
weights = tf.Variable(tf.random_normal([n, nodes]))
# create biases
bias = tf.Variable(tf.random_normal([nodes]))
# apply weights and bias
preactivate = tf.add(tf.matmul(x_, weights), bias)
out = preactivate
# apply activation function if not None
if act is not None:
out = act(preactivate)
# apply dropout
out = tf.nn.dropout(out, keep_prob_)
return out
def maxpool(x_, size, stride):
"""
Wrapper for max-pooling layer
:param x_: tensor, input to max-pooling layer
:param size: int
:param stride: int
:return: tensor
"""
return tf.nn.max_pool(x_,
ksize=[1, size, size, 1],
strides=[1, stride, stride, 1],
padding='SAME')
# Reshape inputs
x_reshaped = tf.reshape(x, shape=[-1, 28, 28, 1])
# First convolutional layer
predictions = conv2d(x_reshaped, filter_size=5, filter_num=32)
# First max-pooling layer
predictions = maxpool(predictions, 2, 2)
# Second convolutional layer
predictions = conv2d(predictions, filter_size=5, filter_num=64)
# Second max-pooling layer
predictions = maxpool(predictions, 2, 2)
# First fully-connected layer
predictions = fc(predictions, 1024, keep_prob)
# Output layer, no activation function
# This layer returns logits
predictions = fc(predictions, n_classes, keep_prob, act=None)
# Define loss operation
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(predictions, y))
# Define optimizer
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)
# Define accuracy operation
correct_predictions = tf.equal(tf.argmax(predictions, 1), tf.argmax(y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_predictions, tf.float32))
# Initializing the variables
init = tf.initialize_all_variables()
# Launch the graph
with tf.Session() as sess:
sess.run(init)
step = 1
# Keep training until reach max iterations
while step * batch_size < training_iters:
batch_x, batch_y = mnist.train.next_batch(batch_size)
# Run optimization op (backprop)
sess.run(optimizer, feed_dict={x: batch_x, y: batch_y,
keep_prob: dropout})
if step % display_step == 0:
# Calculate batch loss and accuracy
loss, acc = sess.run([cost, accuracy], feed_dict={x: batch_x,
y: batch_y,
keep_prob: 1.})
print("\rIter " + str(step*batch_size) + ", Minibatch Loss= " +
"{:.6f}".format(loss) + ", Training Accuracy= " +
"{:.5f}".format(acc), end='')
step += 1
print("\rOptimization Finished!")
# Calculate accuracy for 256 mnist test images
print("Testing Accuracy:",
sess.run(accuracy, feed_dict={x: mnist.test.images[:256],
y: mnist.test.labels[:256],
keep_prob: 1.}))
# get weights of all convolutional layers
# no need for feed dictionary here
conv_weights = sess.run([tf.get_collection('conv_weights')])
for i, c in enumerate(conv_weights[0]):
plot_conv_weights(c, 'conv{}'.format(i))
# get output of all convolutional layers
# here we need to provide an input image
conv_out = sess.run([tf.get_collection('conv_output')], feed_dict={x: mnist.test.images[:1]})
for i, c in enumerate(conv_out[0]):
plot_conv_output(c, 'conv{}'.format(i))