VGGNet-16网络结构构造

来源:互联网 发布:外贸大数据分析 编辑:程序博客网 时间:2024/06/07 04:05
from datetime import datetimeimport mathimport timeimport tensorflow as tf

   首先构建conv_op函数,用于创建卷积层并把本层的参数存入参数列表;

def conv_op(input_op, name, kh,kw, n_out, dh, dw, p):    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.xavier_initializer_conv2d())
input_op是输入的tensor,

name是这一层的名称,

kh是kernel height即为卷积核的高,

kw是卷积核的宽,

n_out是卷积核数量即为输出通道,

dh是步长的高,

dw是步长的宽,

p是参数列表。
通过get_shape()[-1].value获取输入的tensor的通道数;

通过tf.name_scope(name)设置scope;

通过get_variable创建卷积核参数。

shape为[kh,kw,n_in,n_out]即为卷积核的高,卷积核的宽,输入通道数,输出通道数;

使用tf.contrib.layers.xavier_initializer_conv2d()进行参数初始化。

    conv = tf.nn.conv2d(input_op, kernel, (1, dh, dw, 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,name=scope)    p+=[kernel,biases]    return activation
通过tf.nn.conv2d对input_op进行卷积处理,卷积核为kernel,步长为dh*dw,padding模式设为SAME.

biases通过tf.constant赋值为0,

再通过tf.Variable将其转换为可训练的参数,

通过tf.nn.bias_add将卷积结果conv与bias相加,

再通过tf.nn.relu对其进行非线性处理得到activation,

最后将创建卷积层时用到的参数kernel和biases添加到参数列表p中,

将卷积层的输出activation作为函数结果返回。

接下来定义fc_op函数为全连接层中的创建函数

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.xavier_initializer())        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
首先获取输入input_op的通道数,

再通过tf.get_variable创建全连接层的参数,参数维度为两个,一个为输入的通道数n_in,另一个为输出的通道数n_out,

通过xavier_initializer实现参数初始化,

使用tf.nn.relu_layer对输入变量input_op,kernel进行矩阵乘法并加上biases,

再进行ReLU非线性变换得到activation,

最后将全连接层用到的参数kernel、biases添加到参数列表p,

并将activation作为函数结果返回。

定义最大池化层函数mpool_op

def 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)

使用tf.nn.max_pool,

输入为input_op,

池化尺寸为kh*kw,

步长为dh*dw,

padding模式设为SAME

接下来构建VGGNet—16的第一层卷积网络

def inference_op(input_op, keep_prob):    p=[]    conv1_1 = conv_op(input, 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,dw2,dh=2)
首先初始化参数列表p,

keep_prob为控制dropout比率的一个placeholder,

创建第一段卷积网络,由两个卷积层和一个最大池化层构成,

通过conv_op、mpool_op创建卷积网络和最大池化层.

在VGGNet中这一层的卷积核的大小为3*3,卷积核数量为64(输出通道),步长为1*1,全像素扫描。

第一个卷积层的输入input_op的尺寸为224*224*3,输出尺寸为224*224*64;
第二个卷积层的输入尺寸为224*224*64,

最大池化层为2*2,将输出结果尺寸变为了112*112*64

再构建VGGNet—16的第二段卷积网络

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,name="pool2",kh=2,kw=2,dh=2,dw=2)
两个卷积层的卷积核尺寸为3*3,

输出通道为128,

最大池化层与前面保持一致,

输出尺寸变为56*56*128.

构建VGGNet—16的第三段卷积网络

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",kh=2,kw=2,dh=2,dw=2)
第三段卷积网络中够建了3个卷积层和1个最大池化层,

3个卷积层的卷积核大小伟3*3,

输出通道为256,

最大池化层不变,

输出的尺寸为28*28*256.

够建VGGNet—16的第四段卷积网络

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",kh=2,kw=2,dh=2,dw=2)
这一段卷积网络为3个卷积层和1个最大池化层,

每一段卷积网络将图像的边长缩小一半,卷积输出通道数翻倍。

因为图像面积缩小到1/4,输出通道数变为2倍,因此输出tensor的总尺寸每一次缩小一半。

输出通道数增加到512,图像缩小为14*14.

构建VGGNet—16的最后一段卷积网络

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",kh=2,kw=2,dh=2,dw=2)
3个卷积层和一个最大池化层,

卷积核尺寸为3*3,

步长为1*1,

池化层尺寸为2*2,

步长为2*2

输出的尺寸变为7*7*512

对第5段卷积网络的输出结果进行扁平化

shp = pool5.get_shape()flattened_shape = shp[1].value*shp[2].value*shp[3].valueresh1 = tf.reshape(pool5,[-1, flattened_shape],name="resh1")
使用tf.reshape函数将每个样本转化为一维向量,长度为7*7*512=25088
再连接一个隐含结点为4096的全连接层
fc6 = fc_op(resh1, name="fc6", n_out=4096, p=p)fc6_drop = tf.nn.dropout(fc6, keep_prob, name="fc6_drop")
再连接一个全连接层,同样连接一个Dropout层
fc7 = fc_op(fc6_drop, name="fc7", n_out=4096, p=p)fc7_drop = tf.nn.dropout(fc7, keep_prob, name="fc7_drop")
最后连接一个全连接层
fc8 = fc_op(fc7_drop,name="fc8",n_out=1000,p=p)softmax = tf.nn.softmax(fc8)predictions = tf.argmax(softmax,1)return predictions,softmax,fc8,p
使用SoftMax进行处理得到分类输出的概率。
通过tf.argmax求处处概率最大的类别,
最后将fc8,predictions,softmax 和参数p一起返回。
####VGGNet—16的网络结构全部构建完成。###