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