TensorFlow实战7——TensorFlow实现Google_Inception_V3

  1 #coding=utf-8
  2 import tensorflow as tf
  3 from datetime import  datetime
  4 import math
  5 import time
  6 slim = tf.contrib.slim
  7 trunc_normal = lambda stddev: tf.truncated_normal_initializer(0.0, stddev)
  8 
  9 def inception_v3_arg_scope(weight_decay=0.00004, stddev=0.1,batch_norm_var_collection='moving_vars'):
 10 
 11     '''作用:生成网络中经常用到的默认参数。
 12     weight_decay:L2正则,设为默认0.00004
 13     stddev:标准差'''
 14     #batch_normalization参数字典
 15     batch_norm_params = {
 16         'decay':0.9997,#衰减系数
 17         'epsilon':0.001,
 18         'updates_collections':tf.GraphKeys.UPDATE_OPS,
 19         'variables_collections':{
 20             'beta':None,
 21             'gamma':None,
 22             'moving_mean':[batch_norm_var_collection],
 23             'moving_variance':[batch_norm_var_collection],
 24         }
 25     }
 26     #slim.arg_scope给函数参数自动赋予默认值
 27     with slim.arg_scope([slim.conv2d, slim.fully_connected],
 28                         weights_regularizer=slim.l2_regularizer(weight_decay)):
 29         #嵌套slim.arg_scope
 30         with slim.arg_scope(
 31                 [slim.conv2d],
 32                 weights_initializer=tf.truncated_normal_initializer(stddev=stddev),
 33                 activation_fn=tf.nn.relu,
 34                 normalizer_fn=slim.batch_norm,
 35                 normalizer_params=batch_norm_params) as sc:
 36             return sc
 37 
 38 def inception_v3_base(input, scope=None):
 39     '''作用生成v3网络的卷积部分
 40     input:输入图片数据的tensor
 41     scope:函数默认的参数环境'''
 42 
 43     end_points = {}#保存关键节点
 44 
 45     with tf.variable_scope(scope, 'InceptionsV3', [inputs]):
 46 
 47         with slim.arg_scope([slim.conv2d, slim.max_pool2d, slim.avg_pool2d],
 48                             stride=1, padding='VALID'):
 49             '''定义5个卷积层和2个最大池化层, 输入尺寸为299x299x3,输出尺寸为35x35x192
 50             输入:tensor,32:输出的通道数,[3, 3]:卷积核尺寸,stride:步长'''
 51             net = slim.conv2d(inputs, 32, [3, 3], stride=2, scope='Conv2d_1a_3x3')
 52             net = slim.conv2d(net, 32, [3, 3], scope='Conv2d_2a_3x3')
 53             net = slim.conv2d(net, 64, [3, 3], padding='SAME', scope='Conv2d_2b_3x3')
 54             net = slim.max_pool2d(net, [3, 3], stride=2, scope='MaxPool_3a_3x3' )
 55             net = slim.conv2d(net, 80, [1, 1], scope='Conv2d_3b_1x1')
 56             net = slim.conv2d(net, 192, [3, 3], scope='Conv2d_4a_3x3')
 57             net = slim.max_pool2d(net, [3, 3], stride=2, scope='MaxPool_5a_3x3')
 58 
 59         with slim.arg_scope([slim.conv2d, slim.max_pool2d, slim.avg_pool2d], stride=1, padding='SAME'):
 60             '''定义3个连续的Inception模块组'''
 61 
 62             with tf.variable_scope('Mixed_5b'):
 63 
 64                 with tf.variable_scope('Branch_0'):
 65                     '''64:输出通道 1x1的卷积核'''
 66                     branch_0 = slim.conv2d(net, 64, [1, 1], scope='Conv2d_0a_1x1')
 67                 with tf.variable_scope('Branch_1'):
 68                     '''48输出通道的1x1卷积核连接64输出通道的5x5卷积核'''
 69                     branch_1 = slim.conv2d(net, 48, [1, 1], scope='Conv2d_0a_1x1')
 70                     branch_1 = slim.conv2d(branch_1, 64, [5, 5], scope='Conv2d_0b_5x5')
 71                 with tf.variable_scope('Branch_2'):
 72                     '''64输出通道的1x1卷积核连接2个96输出通道的3x3卷积核'''
 73                     branch_2 = slim.conv2d(net, 64, [1, 1], scope='Conv2d_0a_1x1')
 74                     branch_2 = slim.conv2d(branch_2, 96, [3, 3], scope='Conv2d_0b_3x3')
 75                     branch_2 = slim.conv2d(branch_2, 96, [3, 3], scope='Conv2d_0c_3x3')
 76                 with tf.variable_scope('Branch_3'):
 77                     '''3x3的平均池化连接32输出通道的1x1卷积核'''
 78                     branch_3 = slim.avg_pool2d(net, [3, 3], scope='AvgPool_0a_3x3')
 79                     branch_3 = slim.conv2d(branch_3, 32, [1, 1], scope='Conv2d_0b_1x1')
 80                 '''tf.concat将4分支合并在一起,形成module的最终输出35x35x(64+64+96+32)'''
 81                 net = tf.concat([branch_0, branch_1, branch_2, branch_3], 3)
 82 
 83 
 84             with tf.variable_scope('Mixed_5c'):
 85                 with tf.variable_scope('Branch_0'):
 86                     '''64:输出通道 1x1的卷积核'''
 87                     branch_0 = slim.conv2d(net, 64, [1, 1], scope='Conv2d_0a_1x1')
 88                 with tf.variable_scope('Branch_1'):
 89                     '''48输出通道的1x1卷积核连接64输出通道的5x5卷积核'''
 90                     branch_1 = slim.conv2d(net, 48, [1, 1], scope='Conv2d_0b_1x1')
 91                     branch_1 = slim.conv2d(branch_1, 64, [5, 5], scope='Conv2d_0c_5x5')
 92                 with tf.variable_scope('Branch_2'):
 93                     '''64输出通道的1x1卷积核连接2个96输出通道的3x3卷积核'''
 94                     branch_2 = slim.conv2d(net, 64, [1, 1], scope='Conv2d_0a_1x1')
 95                     branch_2 = slim.conv2d(branch_2, 96, [3, 3], scope='Conv2d_0b_3x3')
 96                     branch_2 = slim.conv2d(branch_2, 96, [3, 3], scope='Conv2d_0c_3x3')
 97                 with tf.variable_scope('Branch_3'):
 98                     '''3x3的平均池化连接32输出通道的1x1卷积核'''
 99                     branch_3 = slim.avg_pool2d(net, [3, 3], scope='AvgPool_0a_3x3')
100                     branch_3 = slim.conv2d(branch_3, 64, [1, 1], scope='Conv2d_0b_1x1')
101                 '''tf.concat将4分支合并在一起,形成module的最终输出35x35x(64+64+96+64)'''
102                 net = tf.concat([branch_0, branch_1, branch_2, branch_3], 3)
103 
104 
105             with tf.variable_scope('Mixed_5d'):
106 
107                 with tf.variable_scope('Branch_0'):
108                     '''64:输出通道 1x1的卷积核'''
109                     branch_0 = slim.conv2d(net, 64, [1, 1], scope='Conv2d_0a_1x1')
110                 with tf.variable_scope('Branch_1'):
111                     '''48输出通道的1x1卷积核连接64输出通道的5x5卷积核'''
112                     branch_1 = slim.conv2d(net, 48, [1, 1], scope='Conv2d_0b_1x1')
113                     branch_1 = slim.conv2d(branch_1, 64, [5, 5], scope='Conv2d_0c_5x5')
114                 with tf.variable_scope('Branch_2'):
115                     '''64输出通道的1x1卷积核连接2个96输出通道的3x3卷积核'''
116                     branch_2 = slim.conv2d(net, 64, [1, 1], scope='Conv2d_0a_1x1')
117                     branch_2 = slim.conv2d(branch_2, 96, [3, 3], scope='Conv2d_0b_3x3')
118                     branch_2 = slim.conv2d(branch_2, 96, [3, 3], scope='Conv2d_0c_3x3')
119                 with tf.variable_scope('Branch_3'):
120                     '''3x3的平均池化连接32输出通道的1x1卷积核'''
121                     branch_3 = slim.avg_pool2d(net, [3, 3], scope='AvgPool_0a_3x3')
122                     branch_3 = slim.conv2d(branch_3, 64, [1, 1], scope='Conv2d_0b_1x1')
123                 '''tf.concat将4分支合并在一起,形成module的最终输出35x35x(64+64+96+64)'''
124                 net = tf.concat([branch_0, branch_1, branch_2, branch_3], 3)
125 
126             with tf.variable_scope('Mixed_6a'):
127 
128                 with tf.variable_scope('Branch_0'):
129                     '''384:输出通道 3x3的卷积核 由于步长为2,输出尺寸为17x17x384'''
130                     branch_0 = slim.conv2d(net, 384, [3, 3], stride=2,
131                                            padding='VALID', scope='Conv2d_1a_1x1')
132                 with tf.variable_scope('Branch_1'):
133                     '''64输出通道的1x1卷积核连接2个96输出通道的3x3卷积核,输出尺寸为17x17x96 '''
134                     branch_1 = slim.conv2d(net, 64, [1, 1], scope='Conv2d_0a_1x1')
135                     branch_1 = slim.conv2d(branch_1, 96, [3, 3],
136                                            scope='Conv2d_0b_3x3')
137                     branch_1 = slim.conv2d(branch_1, 96, [3, 3], stride=2,
138                                            padding='VALID', scope='Conv2d_1a_3x3')
139                 with tf.variable_scope('Branch_2'):
140                     '''3x3最大池化层, 输出尺寸为17x17x256'''
141                     branch_2 = slim.max_pool2d(net, [3, 3], stride=2,
142                                            padding='VALID', scope='MaxPool_1a_3x3')
143 
144                 '''tf.concat将3分支合并在一起,形成module的最终输出17x17x(384+48+64)'''
145                 net = tf.concat([branch_0, branch_1, branch_2], 3)
146 
147             with tf.variable_scope('Mixed_6b'):
148 
149                 with tf.variable_scope('Branch_0'):
150                     '''192:输出通道 1x1的卷积核 '''
151                     branch_0 = slim.conv2d(net, 192, [1, 1], scope='Conv2d_0a_1x1')
152 
153                 with tf.variable_scope('Branch_1'):
154                     '''第一层:128输出通道的1x1的卷积
155                        第二层:128输出通道的1x7的卷积
156                        第三层:192输出通道的7x1的卷积'''
157                     branch_1 = slim.conv2d(net, 128, [1, 1], scope='Conv2d_0a_1x1')
158                     branch_1 = slim.conv2d(branch_1, 128, [1, 7], scope='Conv2d_0b_1x7')
159                     branch_1 = slim.conv2d(branch_1, 192, [7, 1], scope='Conv2d_0c_7x1')
160 
161                 with tf.variable_scope('Branch_2'):
162                     '''第一层:128输出通道的1x1的卷积
163                        第二层:128输出通道的7x1的卷积
164                        第三层:128输出通道的1x7的卷积
165                        第四层:128输出通道的7x1的卷积
166                        第五层:192输出通道的1x7的卷积'''
167                     branch_2 = slim.conv2d(net, 128, [1, 1], scope='Conv2d_0a_1x1')
168                     branch_2 = slim.conv2d(branch_2, 128, [7, 1], scope='Conv2d_0b_7x1')
169                     branch_2 = slim.conv2d(branch_2, 128, [1, 7], scope='Conv2d_0c_1x1')
170                     branch_2 = slim.conv2d(branch_2, 128, [7, 1], scope='Conv2d_0d_7x1')
171                     branch_2 = slim.conv2d(branch_2, 192, [1, 7], scope='Conv2d_0e_7x1')
172 
173                 with tf.variable_scope('Branch_3'):
174                     '''3x3的平均池化连接192输出通道的1x1卷积核'''
175                     branch_3 = slim.avg_pool2d(net, [3, 3], scope='AvgPool_0a_3x3')
176                     branch_3 = slim.conv2d(branch_3, 192, [1, 1], scope='Conv2d_0b_1x1')
177 
178                 '''tf.concat将4分支合并在一起,形成module的最终输出17x17x(192+192+192+192)'''
179                 net = tf.concat([branch_0, branch_1, branch_2, branch_3], 3)
180 
181             with tf.variable_scope('Mixed_6c'):
182                 with tf.variable_scope('Branch_0'):
183                     '''192:输出通道 1x1的卷积核 '''
184                     branch_0 = slim.conv2d(net, 192, [1, 1], scope='Conv2d_0a_1x1')
185 
186                 with tf.variable_scope('Branch_1'):
187                     '''第一层:160输出通道的1x1的卷积
188                        第二层:160输出通道的1x7的卷积
189                        第三层:192输出通道的7x1的卷积'''
190                     branch_1 = slim.conv2d(net, 160, [1, 1], scope='Conv2d_0a_1x1')
191                     branch_1 = slim.conv2d(branch_1, 160, [1, 7], scope='Conv2d_0b_1x7')
192                     branch_1 = slim.conv2d(branch_1, 192, [7, 1], scope='Conv2d_0c_7x1')
193 
194                 with tf.variable_scope('Branch_2'):
195                     '''第一层:160输出通道的1x1的卷积
196                        第二层:160输出通道的7x1的卷积
197                        第三层:160输出通道的1x7的卷积
198                        第四层:160输出通道的7x1的卷积
199                        第五层:192输出通道的1x7的卷积'''
200                     branch_2 = slim.conv2d(net, 160, [1, 1], scope='Conv2d_0a_1x1')
201                     branch_2 = slim.conv2d(branch_2, 160, [7, 1], scope='Conv2d_0b_7x1')
202                     branch_2 = slim.conv2d(branch_2, 160, [1, 7], scope='Conv2d_0c_1x1')
203                     branch_2 = slim.conv2d(branch_2, 160, [7, 1], scope='Conv2d_0d_7x1')
204                     branch_2 = slim.conv2d(branch_2, 192, [1, 7], scope='Conv2d_0e_7x1')
205 
206                 with tf.variable_scope('Branch_3'):
207                     '''3x3的平均池化连接192输出通道的1x1卷积核'''
208                     branch_3 = slim.avg_pool2d(net, [3, 3], scope='AvgPool_0a_3x3')
209                     branch_3 = slim.conv2d(branch_3, 192, [1, 1], scope='Conv2d_0b_1x1')
210 
211                 '''tf.concat将4分支合并在一起,形成module的最终输出17x17x(192+192+192+192)'''
212                 net = tf.concat([branch_0, branch_1, branch_2, branch_3], 3)
213 
214 
215             with tf.variable_scope('Mixed_6e'):
216                 with tf.variable_scope('Branch_0'):
217                     '''192:输出通道 1x1的卷积核 '''
218                     branch_0 = slim.conv2d(net, 192, [1, 1], scope='Conv2d_0a_1x1')
219 
220                 with tf.variable_scope('Branch_1'):
221                     '''第一层:160输出通道的1x1的卷积
222                        第二层:160输出通道的1x7的卷积
223                        第三层:192输出通道的7x1的卷积'''
224                     branch_1 = slim.conv2d(net, 160, [1, 1], scope='Conv2d_0a_1x1')
225                     branch_1 = slim.conv2d(branch_1, 160, [1, 7], scope='Conv2d_0b_1x7')
226                     branch_1 = slim.conv2d(branch_1, 192, [7, 1], scope='Conv2d_0c_7x1')
227 
228                 with tf.variable_scope('Branch_2'):
229                     '''第一层:160输出通道的1x1的卷积
230                        第二层:160输出通道的7x1的卷积
231                        第三层:160输出通道的1x7的卷积
232                        第四层:160输出通道的7x1的卷积
233                        第五层:192输出通道的1x7的卷积'''
234                     branch_2 = slim.conv2d(net, 160, [1, 1], scope='Conv2d_0a_1x1')
235                     branch_2 = slim.conv2d(branch_2, 160, [7, 1], scope='Conv2d_0b_7x1')
236                     branch_2 = slim.conv2d(branch_2, 160, [1, 7], scope='Conv2d_0c_1x1')
237                     branch_2 = slim.conv2d(branch_2, 160, [7, 1], scope='Conv2d_0d_7x1')
238                     branch_2 = slim.conv2d(branch_2, 192, [1, 7], scope='Conv2d_0e_7x1')
239 
240                 with tf.variable_scope('Branch_3'):
241                     '''3x3的平均池化连接192输出通道的1x1卷积核'''
242                     branch_3 = slim.avg_pool2d(net, [3, 3], scope='AvgPool_0a_3x3')
243                     branch_3 = slim.conv2d(branch_3, 192, [1, 1], scope='Conv2d_0b_1x1')
244 
245                 '''tf.concat将4分支合并在一起,形成module的最终输出17x17x(192+192+192+192)'''
246                 net = tf.concat([branch_0, branch_1, branch_2, branch_3], 3)
247 
248             with tf.variable_scope('Mixed_6d'):
249                 with tf.variable_scope('Branch_0'):
250                     '''192:输出通道 1x1的卷积核 '''
251                     branch_0 = slim.conv2d(net, 192, [1, 1], scope='Conv2d_0a_1x1')
252 
253                 with tf.variable_scope('Branch_1'):
254                     '''第一层:160输出通道的1x1的卷积
255                        第二层:160输出通道的1x7的卷积
256                        第三层:192输出通道的7x1的卷积'''
257                     branch_1 = slim.conv2d(net, 160, [1, 1], scope='Conv2d_0a_1x1')
258                     branch_1 = slim.conv2d(branch_1, 160, [1, 7], scope='Conv2d_0b_1x7')
259                     branch_1 = slim.conv2d(branch_1, 192, [7, 1], scope='Conv2d_0c_7x1')
260 
261                 with tf.variable_scope('Branch_2'):
262                     '''第一层:160输出通道的1x1的卷积
263                        第二层:160输出通道的7x1的卷积
264                        第三层:160输出通道的1x7的卷积
265                        第四层:160输出通道的7x1的卷积
266                        第五层:192输出通道的1x7的卷积'''
267                     branch_2 = slim.conv2d(net, 160, [1, 1], scope='Conv2d_0a_1x1')
268                     branch_2 = slim.conv2d(branch_2, 160, [7, 1], scope='Conv2d_0b_7x1')
269                     branch_2 = slim.conv2d(branch_2, 160, [1, 7], scope='Conv2d_0c_1x1')
270                     branch_2 = slim.conv2d(branch_2, 160, [7, 1], scope='Conv2d_0d_7x1')
271                     branch_2 = slim.conv2d(branch_2, 192, [1, 7], scope='Conv2d_0e_7x1')
272 
273                 with tf.variable_scope('Branch_3'):
274                     '''3x3的平均池化连接192输出通道的1x1卷积核'''
275                     branch_3 = slim.avg_pool2d(net, [3, 3], scope='AvgPool_0a_3x3')
276                     branch_3 = slim.conv2d(branch_3, 192, [1, 1], scope='Conv2d_0b_1x1')
277 
278                 '''tf.concat将4分支合并在一起,形成module的最终输出17x17x(192+192+192+192)'''
279                 net = tf.concat([branch_0, branch_1, branch_2, branch_3], 3)
280             '''将Mixed_6e存储于end_points中,作为Auxiliary Classifier 辅助模型的分类'''
281             end_points['Mixed_6e'] = net
282 
283             with tf.variable_scope('Mixed_7a'):
284                 with tf.variable_scope('Branch_0'):
285                     '''192:输出通道 1x1的卷积核再连接320输出通道数的3x3的卷积,步长为2,
286                     由于padding为VALID, 图片尺寸压缩为8x8'''
287                     branch_0 = slim.conv2d(net, 192, [1, 1], scope='Conv2d_0a_1x1')
288                     branch_0 = slim.conv2d(branch_0, 320, [3, 3], stride=2,
289                                            padding='VALID', scope='Conv2d_1a_3x3')
290 
291                 with tf.variable_scope('Branch_1'):
292                     '''第一层:192输出通道的1x1的卷积
293                        第二层:192输出通道的1x7的卷积
294                        第三层:192输出通道的7x1的卷积
295                        第四层:192输出通道的3x3的卷积
296                        tensor输出尺寸为8x8x192'''
297                     branch_1 = slim.conv2d(net, 192, [1, 1], scope='Conv2d_0a_1x1')
298                     branch_1 = slim.conv2d(branch_1, 192, [1, 7], scope='Conv2d_0b_1x7')
299                     branch_1 = slim.conv2d(branch_1, 192, [7, 1], scope='Conv2d_0c_7x1')
300                     branch_1 = slim.conv2d(branch_1, 192, [3, 3], stride=2,
301                                        padding='VALID', scope='Conv2d_1a_3x3')
302                 with tf.variable_scope('Branch_2'):
303                     '''3x3的最大池化层,步长为2,padding为VALID,由于池化层对输出通道不会产生改变
304                     故输出尺寸为8x8x768'''
305                     branch_2 = slim.max_pool2d(net, [3, 3], stride=2,
306                                            padding='VALID', scope='MaxPool_1a_3x3')
307                 '''tf.concat将3分支合并在一起,形成module的最终输出8x8x(320+192+768)'''
308                 net = tf.concat([branch_0, branch_1, branch_2], 3)
309 
310             with tf.variable_scope('Mixed_7b'):
311 
312                 with tf.variable_scope('Branch_0'):
313                     '''320输出通道的1x1的卷积'''
314                     branch_0 = slim.conv2d(net, 320, [1, 1], scope='Conv2d_0a_1x1')
315 
316                 with tf.variable_scope('Branch_1'):
317                     '''第一层:1个384输出通道的1x1卷积
318                        第二层:由384输出通道的1x3的卷积和384输出通道的3x1的卷积合并
319                        tensor输出尺寸为:8x8x(384+384)=8x8x768'''
320                     branch_1 = slim.conv2d(net, 384, [1, 1], scope='Conv2d_0a_1x1')
321                     branch_1 = tf.concat([
322                         slim.conv2d(branch_1, 384, [1, 3], scope='Conv2d_0b_1x3'),
323                         slim.conv2d(branch_1, 384, [3, 1], scope='Conv2d_0c_3x1'),], 3)
324 
325 
326                 with tf.variable_scope('Branch_2'):
327                     '''第一层:1个448输出通道的1x1卷积
328                        第二层:384输出通道的3x3的卷积分支内拆成两个分支分别是:
329                        384输出通道的1x3的卷积和384输出通道的3x1的卷积最后合并
330                        tensor输出尺寸为:8x8x(384+384)=8x8x768'''
331                     branch_2 = slim.conv2d(net, 448, [1, 1], scope='Conv2d_0a_1x1')
332                     branch_2 = slim.conv2d(branch_2, 448, [3, 3], scope='Conv2d_0b_3x3')
333                     branch_2 = tf.concat([
334                         slim.conv2d(branch_2, 384, [1, 3], scope='Conv2d_0c_1x3'),
335                         slim.conv2d(branch_2, 384, [3, 1], scope='Conv2d_0d_3x1'),], 3)
336 
337                 with tf.variable_scope('Branch_3'):
338                     '''3x3平均池化层后接一个192输出通道的1x1卷积
339                     tensor输出尺寸为:8x8x192'''
340                     branch_3 = slim.avg_pool2d(net, [3, 3], scope='AvgPool_0a_3x3')
341                     branch_3 = slim.conv2d(branch_3, 192, [1, 1], scope='Conv2d_0b_1x1')
342 
343                 '''tf.concat将3分支合并在一起,形成module的最终输出8x8x(320+768+768+192)'''
344                 net = tf.concat([branch_0, branch_1, branch_2, branch_3], 3)
345 
346             with tf.variable_scope('Mixed_7c'):
347                 with tf.variable_scope('Branch_0'):
348                     '''320输出通道的1x1的卷积'''
349                     branch_0 = slim.conv2d(net, 320, [1, 1], scope='Conv2d_0a_1x1')
350 
351                 with tf.variable_scope('Branch_1'):
352                     '''第一层:1个384输出通道的1x1卷积
353                        第二层:由384输出通道的1x3的卷积和384输出通道的3x1的卷积合并
354                        tensor输出尺寸为:8x8x(384+384)=8x8x768'''
355                     branch_1 = slim.conv2d(net, 384, [1, 1], scope='Conv2d_0a_1x1')
356                     branch_1 = tf.concat([
357                         slim.conv2d(branch_1, 384, [1, 3], scope='Conv2d_0b_1x3'),
358                         slim.conv2d(branch_1, 384, [3, 1], scope='Conv2d_0c_3x1'), ], 3)
359 
360                 with tf.variable_scope('Branch_2'):
361                     '''第一层:1个448输出通道的1x1卷积
362                        第二层:384输出通道的3x3的卷积分支内拆成两个分支分别是:
363                        384输出通道的1x3的卷积和384输出通道的3x1的卷积最后合并
364                        tensor输出尺寸为:8x8x(384+384)=8x8x768'''
365                     branch_2 = slim.conv2d(net, 448, [1, 1], scope='Conv2d_0a_1x1')
366                     branch_2 = slim.conv2d(branch_2, 448, [3, 3], scope='Conv2d_0b_3x3')
367                     branch_2 = tf.concat([
368                         slim.conv2d(branch_2, 384, [1, 3], scope='Conv2d_0c_1x3'),
369                         slim.conv2d(branch_2, 384, [3, 1], scope='Conv2d_0d_3x1'), ], 3)
370 
371                 with tf.variable_scope('Branch_3'):
372                     '''3x3平均池化层后接一个192输出通道的1x1卷积
373                     tensor输出尺寸为:8x8x192'''
374                     branch_3 = slim.avg_pool2d(net, [3, 3], scope='AvgPool_0a_3x3')
375                     branch_3 = slim.conv2d(branch_3, 192, [1, 1], scope='Conv2d_0b_1x1')
376 
377                 '''tf.concat将3分支合并在一起,形成module的最终输出8x8x(320+768+768+192)'''
378                 net = tf.concat([branch_0, branch_1, branch_2, branch_3], 3)
379 
380             return net, end_points
381 
382 
383 def inception_v3(inputs,
384                  num_classes=1000,
385                  is_training=True,
386                  dropout_keep_prob=0.8,
387                  prediction_fn=slim.softmax,
388                  spatial_squeeze=True,
389                  reuse=None,
390                  scope='Inceptionv3'):
391     '''作用:全局平均池化、softmax、Auxiliary Logits
392     num_classes:最后需要分类的数量
393     is_training:是否是训练过程标志
394     dropout_keep_prob:Dropout所需保留节点的比例
395     prediction_fn:最后用来分类的函数
396     spatial_squeeze:是否进行squeeze标志,(去除维数的操作5x3x1->5x3)
397     reuse:是否对网络和Variable进行重复使用的标志
398     scope:包含默认参数的环境'''
399 
400     '''使用tf.variable_scope定义网络name、 reuse等参数'''
401     with tf.variable_scope(scope, 'InceptionV3', [inputs, num_classes], reuse=reuse) as scope:
402         '''使用slim.arg_scope定义Batch Normalization和Dropout的is_training标志的默认值'''
403         with slim.arg_scope([slim.batch_norm, slim.dropout], is_training=is_training):
404             #获取最后一层输出net,end_points
405             net, end_points = inception_v3_base(inputs, scope=scope)
406 
407             with slim.arg_scope([slim.conv2d, slim.max_pool2d, slim.avg_pool2d],
408                                 stride=1, padding='SAME'):
409                 '''处理Auxiliary Logits部分的逻辑:
410                 使用slim.avg_pool2d将卷积、最大池化、
411                 平均池化的默认步长设为3,padding设为VALID,end_points获取Mixed_6e'''
412 
413                 aux_logits = end_points['Mixed_6e']
414 
415                 with tf.variable_scope('AuxLogits'):
416                     '''Mixed_6e接5x5平均池化,步长为3,padding为VALID
417                     输出尺寸:17x17x768->5x5x768((17-5+1)/3=5)'''
418 
419                     aux_logits = slim.avg_pool2d(
420                         aux_logits, [5, 5], stride=3, padding='VALID',
421                         scope='AvgPool_1a_5x5')
422                     '''128输出通道的1x1卷积'''
423                     aux_logits = slim.conv2d(
424                         aux_logits, 128, [1, 1], scope = 'Conv2d_1b_1x1')
425                     '''768输出通道的5x5卷积,
426                        输出尺寸变为1x1x768'''
427                     aux_logits = slim.conv2d(
428                         aux_logits, 768, [5, 5],
429                         weights_initializer=trunc_normal(0.01),
430                         padding='VALID', scope='Conv2d_2a_5x5')
431                     '''输出通道为num_classes的1x1的卷积,
432                        输出尺寸变为1x1x1000'''
433                     aux_logits = slim.conv2d(
434                         aux_logits, num_classes, [1, 1], activation_fn=None,
435                         normalizer_fn=None, weights_initializer=trunc_normal(0.01),
436                         scope='Conv2d_2b_1x1')
437 
438                     if spatial_squeeze:
439                         '''将1x1x1000通过tf.squeeze变为1000存储到end_points'''
440                         aux_logits = tf.squeeze(aux_logits, [1, 2],
441                                                name='SpatialSqueeze')
442                     end_points['AuxLogits'] = aux_logits
443 
444                 with tf.variable_scope('Logits'):
445                     '''处理正常分类预测的逻辑:
446                     对Mixed_7e最后一个卷积层的输出进行8x8全局平均化池化,padding为VALID
447                     输出尺寸:8x8x2048->1x1x2048
448                     '''
449                     net = slim.avg_pool2d(net, [8, 8], padding='VALID', scope='AvgPool_1a_8x8')
450                     '''连接一个Dropout层,节点保留率:dropout_keep_prob'''
451                     net = slim.dropout(net, keep_prob=dropout_keep_prob, scope='Dropout_1b')
452 
453                     end_points['PreLogits'] = net
454                     '''1000输出通道1x1的卷积'''
455                     logits = slim.conv2d(net, num_classes, [1, 1], activation_fn=None,
456                                          normalizer_fn=None, scope='Conv2d_1c_1x1')
457 
458                     if spatial_squeeze:
459                         '''tf.sqeeze去一维'''
460                         logits = tf.squeeze(logits, [1, 2], name='SpatialSqueeze')
461 
462                 end_points['Logits'] = logits
463                 '''接softmax对结果进行分类预测'''
464                 end_points['Predictions'] = prediction_fn(logits, scope='Predictions')
465             '''返回结果logits,包含辅助节点的end_points'''
466             return logits, end_points
467 
468 def time_tensorflow_run(session, target, info_string):
469 
470     num_steps_burn_in = 10
471     total_duration = 0.0
472     total_duration_squared = 0.0
473     for i in range(num_batches+num_steps_burn_in):
474         start_time = time.time()
475         _ = session.run(target)
476         duration = time.time()-start_time
477 
478         if i >= num_steps_burn_in:
479             if not i % 10:
480                 print('%s: step %d, duration = %.3f' %(datetime.now(), i-num_steps_burn_in, duration))
481                 total_duration += duration
482                 total_duration_squared += duration*duration
483 
484     mn = total_duration/num_batches
485     vr = total_duration_squared/num_batches-mn*mn
486     sd = math.sqrt(vr)
487 
488     print('%s: %s across %d steps, %.3f +/- %3.3f sec/batch' %(datetime.now(), info_string, num_batches, mn, sd))
489 
490 batch_size = 32
491 height, width = 299, 299
492 
493 inputs = tf.random_uniform((batch_size, height, width, 3))
494 
495 with slim.arg_scope(inception_v3_arg_scope()):
496     logits, end_points = inception_v3(inputs, is_training=False)
497 
498 init = tf.global_variables_initializer()
499 sess = tf.Session()
500 sess.run(init)
501 num_batches = 100
502 time_tensorflow_run(sess, logits, "Forward")
 1 2017-12-23 23:46:17.904100: step 0, duration = 0.467
 2 2017-12-23 23:46:22.557100: step 10, duration = 0.464
 3 2017-12-23 23:46:27.201100: step 20, duration = 0.463
 4 2017-12-23 23:46:31.848100: step 30, duration = 0.466
 5 2017-12-23 23:46:36.495100: step 40, duration = 0.464
 6 2017-12-23 23:46:41.148100: step 50, duration = 0.464
 7 2017-12-23 23:46:45.795100: step 60, duration = 0.464
 8 2017-12-23 23:46:50.458100: step 70, duration = 0.467
 9 2017-12-23 23:46:55.098100: step 80, duration = 0.464
10 2017-12-23 23:46:59.741100: step 90, duration = 0.463
11 2017-12-23 23:47:03.926100: Forward across 100 steps, 0.046 +/- 0.139 sec/batch

 

posted @ 2017-12-23 23:52  yoyoball9999  阅读(503)  评论(0编辑  收藏  举报