首页 > 学院 > 开发设计 > 正文

【tensorflow1.0学习笔记】(12)实现经典的CNN卷积神经网络之二--VGGNet

2019-11-06 06:44:09
字体:
来源:转载
供稿:网友

这节开始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()


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表