这个结构其实不难,但是它里面训练的一些东西我还没有搞清楚,打算把昨天写的代码传上来,方便日后来看,发现了一个很有意思的库叫TF-slim打算哪天看看有没有好用的东西
from datetime import datetime import math import time import tensorflow as tf import numpy as np """ create a function to construct a convLayer and put the parameters of this layer into the convlayer input_op:input tensor name:layer name kh:kernel height kw:kernal width n_out:number of filters,the output channels dh:stride of height dw:stride of width p:parameter list """ def conv_op(input_op,name,kh,kw,n_out,dh,dw,p): #用来获取通道数,-1代表tensor的最后一个维度即通道 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], initializer=tf.contrib.layers.xavier_initializer_conv2d) #用来定义卷积操作,其中第三个参数是strides步长,第四个参数是填充方式 conv=tf.nn.conv2d(input_op,kernel,(1,dh,dw,1),padding='SAME') bias_init_values=tf.constant(0.0,shape=[n_out],dtype=tf.float32) biases=tf.Variable(bias_init_values,trainable=True,name='b') z=tf.nn.bias_add(conv,biases) activation=tf.nn.relu(z,name=scope) #将创建卷积时用到的参数添加到参数列表p中 p+=[kernel,biases] #将激活后的结果返回,使用激活函数是为了让模型具有非线性的表达,其实这个结果是要传递到下一层去 return activation #创建池化层的构造函数 def max_pool_op(input_op,name,kw,kh,dw,dh): return tf.nn.max_pool(input_op, ksize=[1,kh,kw,1], strides=[1,dh,dw,1], padding='SAME', name=name) #创建建立全连接层的函数 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_val=tf.constant(0.1,shape=[n_out],dtype=tf.float32) biases=tf.Variable(biases_val,name='b') activation=tf.nn.relu_layer(input_op,kernel,biases,name='scope') p+=[kernel,biases] return activation #下面开始构造VGG的网络结构 """ 正常的VGG有五层的卷积结构 第一个是两个卷积层,一层最大池化 第二个是两个卷积层一个最大池化 第三个是三个卷积层一个最大池化 第四个是三个卷积层一个最大池化 第五个是三个卷积层一个最大池化 之后是三层全连接层,最后一个全链接层的输出进入softmax进行分类预测 input_op是输入的tensor,keep_prob是神经元的保留率 """ def vgg_structure(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=max_pool_op(conv1_2,name="pool1",kw=2,kh=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=2,kw=2,n_out=128,dh=1,dw=1,p=p) pool2=max_pool_op(conv2_2,name="pool2",kw=2,kh=2,dw=2,dh=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=max_pool_op(conv3_3,name="pool3",kw=2,kh=2,dw=2,dh=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=max_pool_op(conv4_3,name="pool4",kw=2,kh=2,dw=2,dh=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=max_pool_op(conv5_3,name="pool5",kw=2,kh=2,dw=2,dh=2) #将最后一个池化层的输出扁平化,最后输出的是7*7*512的matrix shp=pool5.get_shape() total_demension=shp[1].value*shp[2].value*shp[3].value #因为不知道一次输入的batch_size是多少,不知道转化成多少行,只知道列数 resh1=tf.reshape(pool5,[-1,total_demension],name="resh1") #现在将最后一个池化层的输出拿出来当作第一个全连接层的输入,全连接层后面加一个drop_out,在训练时节点保留率是0.5,测试时为1 fc6=fc_op(resh1,name="fc6",n_out=4096,p=p) fc6_drop=tf.nn.dropout(fc6,keep_prob,name="fc6_deop") #定义第二个全连接层 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中进行分类 softmax=tf.nn.softmax(fc8) #返回列方向上softmax预测概率的最大值的下标,就是模型的预测结果 predictions=tf.argmax(softmax,1) return softmax,fc8,predictions #这样我们的vgg初步的模型就定义结束了
然后之后想试试如何划分训练集测试集和验证集,这个是一直不太会的东西,嗯就酱