这节开始VGGNet讲解
先附上代码,后期补充
# coding=utf-8# 载入常用的库import tensorflow as tfimport mathimport timefrom datetime import datetime# 先定义一个函数conv_op,用来创建卷积层并把本层的参数存入参数列表"""使用get_shape()[-1].value获取输入input_op的通道数,使用tf.name_scope(name)设置scope。使用tf.get_variable()创建kernel(即卷积核参数),shape=[kh, kw, n_in, n_out]即[卷积核的高, 卷积核的宽, 输入通道数, 输出通道数],使用tf.contrib.layers.xavier_initilizer_conv2d()做参数初始化。"""# tf.Variable(tensor, trianable, name)def conv_op(input_op, name, kh, kw, n_in, n_out): n_in = input_op.get_shape()[-1].value # 获得输入的通道数 with tf.name_scope(name) as scope: kernel = tf.get_variable(scope+"w", shape=[kh, kw, n_in, n_out], dtype=tf.float32, initializer=tf.contrib.layers.xavire_initilizer_conv2d()) conv = tf.nn.conv2d(input_op, kernel, (1, kh, kw, 1), padding='SAME') bias_init_val = tf.constant(0.0, shape=[n_out], dtype=tf.float32) biases = tf.Variable(bias_init_val, trainable=True, name='b') z = tf.nn.bias_add(conv, biases) activation = tf.nn.relu(z) p += [kernel, biases] return activation# 定义全连接层的创建函数fc_op"""一样是先获取输入input_op的通道数,然后使用tf.get_variable创建全连接层的参数,只不过参数的维度只有两个,第一个维度为输入的通道数n_in,第二个维度为输出的通道数n_out。同样,参数初始化方法也使用xavier_initializer。这里bias不再为0,而是赋予一个较小的值为0.1以避免deadneuron。然后使用tf.nn.relu_layer对输入变量input_op与kernel做矩阵乘法加上bias,再做RELU非线性变换得到activation。最后将这个全连接层用到参数kernel,biases添加到参数表p,并将activation作为函数结果返回。"""def fc_op(input_op, name, n_out, p): n_in = input_op.get_shape()[-1].value() with tf.name_scope(name) as scope: kernel = tf.get_variable(scope+"w", shape=[n_in, n_out], dtype=tf.float32, initializer=tf.contrib.layers.xavire_initilizer()) biases = tf.Variable(tf.constant(0.1, shape=[n_out], dtype=tf.float32, name='b')) activation = tf.nn.relu_layer(input_op, kernel, biases, name=scope) p += [kernel, biases] return activation# 定义最大池化层的创建函数mpool_opdef mpool_op(input_op, name, kh, kw, dh, dw): return tf.nn.max_pool(input_op, ksize=[1, kh, kw, 1], strides=[1, dh, dw, 1], padding='SAME', name=name)# 创建VGGNet-16的网络结构# VGGNet-19主要分为6部分,前5段为卷积函数,最后一层为全连接网络def inference_op(input_op, keep_PRob): p = [] # 第一段卷积 conv1_1 = conv_op(input_op, name='conv1_1', kh=3, kw=3, n_out=64, dh=1, dw=1, p=p) conv1_2 = conv_op(conv1_1, name='conv1_2', kh=3, kw=3, n_out=64, dh=1, dw=1, p=p) pool1 = mpool_op(conv1_2, name="pool1", kh=2, kw=2, dw=2, dh=2) # 第二段卷积 conv2_1 = conv_op(pool1, name='conv2_1', kh=3, kw=3, n_out=128, dh=1, dw=1, p=p) conv2_2 = conv_op(conv2_1, name='conv2_2', kh=3, kw=3, n_out=128, dh=1, dw=1, p=p) pool2 = mpool_op(conv2_2, name="pool2", kw=2, kh=2, dh=2, dw=2) # 第三段卷积 conv3_1 = conv_op(pool2, name="conv3_1", kh=3, kw=3, n_out=256, dh=1, dw=1, p=p) conv3_2 = conv_op(conv3_1, name="conv3_2", kh=3, kw=3, n_out=256, dh=1, dw=1, p=p) conv3_3 = conv_op(conv3_2, name="conv3_3", kh=3, kw=3, n_out=256, dh=1, dw=1, p=p) pool3 = mpool_op(conv3_3, name="pool3", kw=2, kh=2, dh=2, dw=2) # 第四段卷积 conv4_1 = conv_op(pool3, name="conv4_1", kh=3, kw=3, n_out=512, dh=1, dw=1, p=p) conv4_2 = conv_op(conv4_1, name="conv4_2", kh=3, kw=3, n_out=512, dh=1, dw=1, p=p) conv4_3 = conv_op(conv4_2, name="conv4_3", kh=3, kw=3, n_out=512, dh=1, dw=1, p=p) pool4 = mpool_op(conv4_3, name="pool4", kw=2, kh=2, dh=2, dw=2) # 第五段卷积 conv5_1 = conv_op(pool4, name="conv5_1", kh=3, kw=3, n_out=512, dh=1, dw=1, p=p) conv5_2 = conv_op(conv5_1, name="conv5_2", kh=3, kw=3, n_out=512, dh=1, dw=1, p=p) conv5_3 = conv_op(conv5_2, name="conv5_3", kh=3, kw=3, n_out=512, dh=1, dw=1, p=p) pool5 = mpool_op(conv5_3, name="pool5", kw=2, kh=2, dh=2, dw=2) # 将第5段卷积网络的输出结果进行扁平化,使用tf.reshape函数将每个样本化为长度为7×7×512=25088的一维向量 shp = pool5.get_shape() flattened_shape = shp[1].value*shp[2].value*shp[3].value resh1 = tf.reshape(pool5, [-1, flattened_shape], name="resh1") # 连接一个隐含节点数为4096的全连接层,激活函数为RELU。 # 然后连接一个Droput层,在训练时节点保留率为0.5,预测时为1.0 fc6 = fc_op(resh1, name="fc6", n_out=4096, p=p) fc6_drop = tf.nn.dropout(fc6, keep_prob, name="fc6_drop") fc7 = fc_op(fc6_drop, name="fc7", n_out=4096, p=p) fc7_drop = tf.nn.dropout(fc7, keep_prob, name="fc7") """ 最后连接一个有1000个输出节点的全连接层,并使用softmax进行处理得到分类输出概率。 这里使用tf.argmax求输出概率最大的类别。 最后将fc8,softmax,prediction和参数列表p一起返回。 """ fc8 = fc_op(fc7_drop, name="fc8", n_out=1000, p=p) softmax = tf.nn.softmax(fc8) prediction = tf.argmax(softmax, 1) return prediction, softmax, fc8, p# 评测函数time_tensorflow_rundef time_tensorflow_run(session, target, feed, info_string): num_step_burn_in = 10 total_duration = 0.0 total_duration_squared = 0.0 """ 进行num_batches + num_step_burn_in次迭代计算,使用time.time()记录时间,每次迭代通过session.run(target)执行。 在初始热身的num_step_burn_in次迭代后,每10轮迭代显示当前所需要的时间。 同时每轮total_duration和total_duration_squared累加,以便后面计算每轮耗时的均值和标准差。 """ for i in range(num_batches + num_step_burn_in): start_time = time.time() _ = session.run(target, feed_dict=feed) duration = time.time() - start_time if i >= num_step_burn_in: if not i % 10: print('%s: step %d, duration = %.3f' % (datatime.now(), i - num_step_burn_in, duration)) total_duration += duration total_duration_squared += duration * duration # 在循环结束后,计算每轮迭代的平均耗时mm和标准差sd,最后将结果显示出来。 # 这样就完成来计算每轮迭代耗时的评测函数time_tensorflow_run. mn = total_duration / num_batches vr = total_duration_squared / num_batches - mn * mn sd = math.sqrt(vr) print('%s: %s across %d step, %.3f +/- %.3f sec / batch' % (datatime.now(), info_string, num_batches, mn, sd)) # 主函数run_benchmark"""首先使用with tf.Graph().as_default()定义默认的Graph方便后面使用。"""def run_benchmark(): with tf.Graph().as_default(): image_size = 224 # 构造正态分布的随机tensor,第一维度是batch_size,即每轮迭代的样本数目, # 第二个和第三个维度是图片的尺寸image_size,第四个维度是图片的颜色通道数目。 images = tf.Variable(tf.random_normal([batch_size, image_size, image_size, 3], dtype=tf.float32, stddev=1e-1)) # 创建keep_prob的placeholder,并调用inference_op函数构建VGGNet-16的网络结构, # 获得prediction。softmax,fc8和参数列表p keep_prob = tf.placeholder(tf.float32) prediction, softmax, fc8, p = inference_op(images, keep_prob) # 创建session并初始化全局参数 init = tf.global_variables_initializer() sess = tf.Sessin() sess.run(init) # 通过将keep_prob设为1.0来执行,并使用time_tensorflow_run评测forward运算时间。 # 再计算VGGNet-16最后的全连接层的输出fc8的l2_loss, # 并使用tf.gradients求相对于这个loss的所有模型参数的梯度。 # 最后使用time_tensorflow_run评测backward运算时间, # 这里target为求解梯度的操作grad,keep_prob为0.5。 time_tensorflow_run(sess, prediction, {keep_prob: 1.0}, "Forward") objective = tf.nn.l2_loss(fc8) grad = tf.gradients(objective, p) time_tensorflow_run(sess, grad, {keep_prob: 0.5}, "Forward-backward")batch_size = 32num_batches = 100run_benchmark()
新闻热点
疑难解答