1 #coding = utf-8
2 from datetime import datetime
3 import tensorflow as tf
4 import time
5 import math
6
7 def conv_op(input_op, name, kh, kw, n_out, dh, dw, p):
8 n_in = input_op.get_shape()[-1].value
9
10 '''创建卷积层并把本层的参数存入参数列表
11 input_op:tensor
12 name:层名
13 kh:kernel height
14 kw:kernel width
15 n_out:卷积核数量即输出通道数
16 dh:步长的高
17 dw: 步长的宽
18 p: 参数列表'''
19 with tf.name_scope(name) as scope:
20
21 kernel = tf.get_variable(scope+"w",
22 shape=[kh, kw, n_in, n_out], dtype=tf.float32,
23 initializer=tf.contrib.layers.xavier_initializer_conv2d())
24
25 conv = tf.nn.conv2d(input_op, kernel, (1, dh, dw, 1),
26 padding = 'SAME')
27 bias_init_val = tf.constant(0.0, shape=[n_out], dtype=tf.float32)
28 biases = tf.Variable(bias_init_val, trainable=True, name='b')
29 z = tf.nn.bias_add(conv, biases)
30 activation = tf.nn.relu(z, name=scope)
31 p += [kernel, biases]
32 return activation
33
34
35 def fc_op(input_op, name, n_out, p):
36 '''定义创建全连接层函数:'''
37 n_in = input_op.get_shape()[-1].value#获取输入input_op的通道数
38
39 with tf.name_scope(name) as scope:
40 #创建全连接层参数,维度为2:n_in, n_out
41 kernel = tf.get_variable(scope+"w",
42 shape=[n_in, n_out], dtype=tf.float32,
43 initializer=tf.contrib.layers.xavier_initializer())
44 #偏置初始化为0.1,避免dead neoron
45 biases = tf.Variable(tf.constant(0.1, shape=[n_out],
46 dtype=tf.float32), name="b")
47 #激活:relu非线性变换得到
48 activation = tf.nn.relu_layer(input_op, kernel, biases, name=scope)
49 #添加全连接参数kernel和biases到参数列表p
50 p += [kernel, biases]
51
52 return activation
53
54
55 def mpool_op(input_op, name, kh, kw, dh, dw):
56 '''定义maxpool层
57 input:input_op
58 池化尺寸:khxkw
59 步长:dhxdw
60 padding:SAME
61 padding="SAME" 输出尺寸为W/S(其中W为输入尺寸,S为stride)
62 padding="VALID" 输出尺寸为(W-F+1)/S(其中F为卷积核尺寸)
63 '''
64
65 return tf.nn.max_pool(input_op,
66 ksize=[1, kh, kw, 1],
67 strides=[1, dh, dw, 1],
68 padding='SAME',
69 name=name)
70
71 def inference_op(input_op, keep_prob):
72
73 p = []
74 '''第一层卷积神经网络:2个卷积层和一个最大池化层,
75 2个卷积层卷积核大小为3x3,卷积核数量(输出通道数):64,步长为1x1
76 输出尺寸:112x112x64'''
77 conv1_1 = conv_op(input_op, name="conv1_1", kh=3, kw=3, n_out=64, dh=1,
78 dw=1, p=p)
79 conv1_2 = conv_op(conv1_1, name="conv1_2", kh=3, kw=3, n_out=64, dh=1,
80 dw=1, p=p)
81 pool1 = mpool_op(conv1_2, name="pool1", kh=2, kw=2, dw=2, dh=2)
82
83 '''第二层卷积神经网络:2个卷积层和一个最大池化层,
84 2个卷积层卷积核大小为:3x3,输出通道数为:128
85 输出尺寸为56x56x128'''
86 conv2_1 = conv_op(pool1, name="conv2_1", kh=3, kw=3, n_out=128, dh=1,
87 dw=1, p=p)
88 conv2_2 = conv_op(conv2_1, name="conv2_2", kh=3, kw=3, n_out=128, dh=1,
89 dw=1, p=p)
90 pool2 = mpool_op(conv2_2, name="pool2", kh=2, kw=2, dh=2, dw=2)
91
92 '''第三层卷积神经网络:3个卷积层和一个最大池化层。
93 3个卷积层的卷积核大小均为:3X3,输出通道数为:256
94 输出尺寸为28x28x256'''
95 conv3_1 = conv_op(pool2, name="conv3_1", kh=3, kw=3, n_out=256, dh=1,
96 dw=1, p=p)
97 conv3_2 = conv_op(conv3_1, name="conv3_2", kh=3, kw=3, n_out=256, dh=1,
98 dw=1, p=p)
99 conv3_3 = conv_op(conv3_2, name="conv3_3", kh=3, kw=3, n_out=256, dh=1,
100 dw=1, p=p)
101 pool3 = mpool_op(conv3_3, name="pool3", kh=2, kw=2, dh=2, dw=2)
102 '''第四层卷积神经网络:3个卷积层和一个最大池化层。
103 3个卷积层的卷积核大小均为3x3,输出通道为512,
104 输出尺寸为14x14x512'''
105 conv4_1 = conv_op(pool3, name="conv3_1", kh=3, kw=3, n_out=512, dh=1,
106 dw=1, p=p)
107 conv4_2 = conv_op(conv4_1, name="conv4_2", kh=3, kw=3, n_out=512, dh=1,
108 dw=1, p=p)
109 conv4_3 = conv_op(conv4_2, name="conv4_3", kh=3, kw=3, n_out=512, dh=1,
110 dw=1, p=p)
111 pool4 =mpool_op(conv4_3, name="pool4", kh=2, kw=2, dh=2, dw=2)
112
113 '''第五层卷积神经网络:3个卷积层和一个最大池化层。
114 3个卷积层的卷积核大小均为3x3,输出通道仍然为512,
115 输出尺寸为7x7x512'''
116 conv5_1 = conv_op(pool4, name="conv5_1", kh=3, kw=3, n_out=512, dh=1,
117 dw=1, p=p)
118 conv5_2 = conv_op(conv5_1, name="conv4_2", kh=3, kw=3, n_out=512, dh=1,
119 dw=1, p=p)
120 conv5_3 = conv_op(conv5_2, name="conv4_3", kh=3, kw=3, n_out=512, dh=1,
121 dw=1, p=p)
122 pool5 =mpool_op(conv5_3, name="pool5", kh=2, kw=2, dh=2, dw=2)
123
124
125 '''输出结果扁平化,用tf.reshape将各个样本转化为7x7x512=25088的一维向量'''
126 shp = pool5.get_shape()
127 flattened_shape = shp[1].value*shp[2].value*shp[3].value
128 resh1 = tf.reshape(pool5, [-1, flattened_shape], name="resh1")
129
130 '''隐含节点数为4096的Fully connection,activation function:ReLu,
131 再连接Dropout层,训练时节点保留率为0.5,预测时为1.0'''
132 fc6 = fc_op(resh1, name="fc6", n_out=4096, p=p)
133 fc6_drop = tf.nn.dropout(fc6, keep_prob, name="fc_drop")
134
135 fc7 = fc_op(fc6_drop, name="fc7", n_out=4096, p=p)
136 fc7_drop = tf.nn.dropout(fc7, keep_prob, name="fc7_drop")
137
138 '''输出节点为1000的全连接层,并使用softmax进行分类得到分类输出概率'''
139 fc8 = fc_op(fc7_drop, name="fc8", n_out=1000, p=p)
140 softmax = tf.nn.softmax(fc8)
141 #tf.argmax()求出输出概率的最大类别
142 predictions = tf.argmax(softmax, 1)
143 return predictions, softmax, fc8, p
144
145
146 def time_tensorflow_run(session, target, feed, info_string):
147
148 n_steps_burn_in = 10
149 total_duration = 0.0
150 total_duration_squared = 0.0
151 for i in range(num_batches+n_steps_burn_in):
152 start_time = time.time()
153 _ = session.run(target, feed_dict=feed)
154 duration = time.time()-start_time
155
156 if i>=n_steps_burn_in:
157 if not i%10:
158 print('%s: step %d, duration = %.3f' %
159 (datetime.now(), i-n_steps_burn_in, duration))
160 total_duration += duration
161 total_duration_squared +=duration*duration
162
163 mn = total_duration/num_batches
164 vr = total_duration_squared/num_batches-mn*mn
165 sd = math.sqrt(vr)
166
167 print('%s: %s across %d steps, %.3f +/- %3.3f sec/batch' %
168 (datetime.now(), info_string, num_batches, mn, sd))
169
170 def run_benchmark():
171
172 with tf.Graph().as_default():
173 '''定义图片尺寸224,利用tf.random_normal函数生成标准差为0.1的正态分布
174 的随机数来构建224x224的随机图片'''
175 image_size = 64#GPU空间不够,改为64
176 images = tf.Variable(tf.random_normal([batch_size,
177 image_size,
178 image_size, 3],
179 dtype=tf.float32,
180 stddev=1e-1))
181 #构建keep_prob的placeholder
182 keep_prob = tf.placeholder(tf.float32)
183 #调用inference_op构建VGGNET-16网络结构,赋值给相应参数
184 predictions, softmax, fc8, p = inference_op(images, keep_prob)
185 init = tf.global_variables_initializer()
186 sess = tf.Session()
187 sess.run(init)
188 #设置keep_prob为1.0,运用time_tensorflow_run来评测forward运算随机
189 time_tensorflow_run(sess, predictions, {keep_prob:1.0}, "Forward")
190 #计算fc8输出的loss
191 objective = tf.nn.l2_loss(fc8)
192 #求相对于loss的所有模型的梯度
193 grad = tf.gradients(objective, p)
194 #评测backward运算时间
195 time_tensorflow_run(sess, grad, {keep_prob:0.5}, "Forward-backward")
196
197
198 batch_size = 32
199 num_batches = 100
200 run_benchmark()
1 2017-12-21 20:27:00.788000: step 0, duration = 0.055
2 2017-12-21 20:27:01.343000: step 10, duration = 0.055
3 2017-12-21 20:27:01.897000: step 20, duration = 0.055
4 2017-12-21 20:27:02.451000: step 30, duration = 0.055
5 2017-12-21 20:27:03.008000: step 40, duration = 0.055
6 2017-12-21 20:27:03.566000: step 50, duration = 0.056
7 2017-12-21 20:27:04.123000: step 60, duration = 0.056
8 2017-12-21 20:27:04.679000: step 70, duration = 0.056
9 2017-12-21 20:27:05.236000: step 80, duration = 0.056
10 2017-12-21 20:27:05.793000: step 90, duration = 0.056
11 2017-12-21 20:27:06.295000: Forward across 100 steps, 0.006 +/- 0.017 sec/batch
12
13 2017-12-21 20:27:09.294000: step 0, duration = 0.188
14 2017-12-21 20:27:11.173000: step 10, duration = 0.187
15 2017-12-21 20:27:13.053000: step 20, duration = 0.188
16 2017-12-21 20:27:14.934000: step 30, duration = 0.188
17 2017-12-21 20:27:16.814000: step 40, duration = 0.188
18 2017-12-21 20:27:18.695000: step 50, duration = 0.188
19 2017-12-21 20:27:20.575000: step 60, duration = 0.188
20 2017-12-21 20:27:22.456000: step 70, duration = 0.188
21 2017-12-21 20:27:24.337000: step 80, duration = 0.188
22 2017-12-21 20:27:26.217000: step 90, duration = 0.187
23 2017-12-21 20:27:27.911000: Forward-backward across 100 steps, 0.019 +/- 0.056 sec/batch