卷积神经网络
Convolutional Neural Networks (CNN)卷积神经网络是近些年逐步兴起的一种人工神经网络结构, 因为利用卷积神经网络在图像和语音识别方面能够给出更优预测结果, 这一种技术也被广泛的传播可应用. 卷积神经网络最常被应用的方面是计算机的图像识别, 不过因为不断地创新, 它也被应用在视频分析, 自然语言处理, 药物发现, 等等.
卷积神经网络包含输入层、隐藏层和输出层,隐藏层又包含卷积层和pooling
层,图像输入到卷积神经网络后通过卷积来不断的提取特征,每提取一个特征就会增加一个feature map
.
定义卷积层 weight bias
首先导入
import tensorflow as tf
采用的数据集依然是tensorflow
里面的mnist
数据集,需要先导入它
python from tensorflow.examples.tutorials.mnist import input_data
mnist=input_data.read_data_sets('MNIST_data',one_hot=true)
接着,定义Weight
变量,输入shape
,返回变量的参数。使用tf.truncted_normal
产生随机变量来进行初始化:
def weight_variable(shape):
inital=tf.truncted_normal(shape,stddev=0.1)
return tf.Variable(initial)
同样的定义biase
变量,输入shape
,返回变量的一些参数。使用tf.constant
常量函数来进行初始化:
def bias_variable(shape):
initial=tf.constant(0.1,shape=shape)
return tf.Variable(initial)
定义卷积,tf.nn.conv2d
函数是tensoflow
里面的二维的卷积函数,x
是图片的所有参数,W
是此卷积层的权重,然后定义步长strides=[1,1,1,1]
值,strides[0]
和strides[3]
的两个1是默认值,中间两个1代表padding时在x方向运动一步,y方向运动一步,padding采用的方式是SAME
。
def conv2d(x,W):
return tf.nn.conv2d(x,W,strides=[1,1,1,1],padding='SAME')
定义pooling
接着定义池化pooling
,为了得到更多的图片信息,padding时我们选的是一次一步,也就是strides[1]=strides[2]=1
,这样得到的图片尺寸没有变化,而我们希望压缩一下图片也就是参数能少一些从而减小系统的复杂度,因此采用pooling
来稀疏化参数,也就是卷积神经网络中所谓的下采样层。
pooling
有两种,一种是最大值池化,一种是平均值池化,这里采用的是最大值池化tf.max_pool()
。池化的核函数大小为2x2,因此ksize=[1,2,2,1]
,步长为2,因此strides=[1,2,2,1]
:
def max_poo_2x2(x):
return tf.nn.max_pool(x,ksize=[1,2,2,1],strides=[1,2,2,1])
构建网络
图片处理
定义一下输入的placeholder
xs=tf.placeholder(tf.float32,[None,784])
ys=tf.placeholder(tf.float32,[None,10])
定义dropout
的placeholder
,它是解决过拟合的有效手段
keep_prob=tf.placeholder(tf.float32)
接着需要处理xs
,把xs
的形状变成[-1,28,28,1]
,-1代表先不考虑输入的图片例子多少这个维度,后面的1是channel的数量,因为输入的图片是黑白的,因此channel是1,例如如果是RGB图像,那么channel就是3。
x_image=tf.reshape(xs,[-1,28,28,1])
建立卷积层
定义第一层卷积,先定义本层的Weight
,本层的卷积核patch的大小是5x5,因为黑白图片channel是1所以输入是1,输出是32个featuremap
W_conv1=weight_variable([5,5,1,32])
定义bias
,它的大小是32个长度,因此传入它的shape
为[32]
b_conv1=bias_variable([32])
定义好了Weight
和bias
,就可以定义卷积神经网络的第一个卷积层h_conv1=conv2d(x_image,W_conv1)+b_conv1
,同时对h_conv1
进行非线性处理,也就是激活函数来处理,这里用的是tf.nn.relu
(修正线性单元)来处理,要注意的是,因为采用了SAME
的padding方式,输出图片的大小没有变化依然是28x28,只是厚度变厚了,因此现在的输出大小就变成了28x28x32
h_conv1=tf.nn.relu(conv2d(x_image,W_conv1)+b_conv1)
最后进行pooling
的处理,经过pooling
的处理,输出大小就变为了14x14x32
h_pool=max_pool_2x2(h_conv1)
接着定义第二层卷积,本层的输入就是上一层的输出,本层我们的卷积核patch的大小是5x5,有32个featuremap所以输入就是32,输出定为64
W_conv2=weight_variable([5,5,32,64])
b_conv2=bias_variable([64])
定义卷积神经网络的第二个卷积层,输出的大小就是14x14x64
h_conv2=tf.nn.relu(conv2d(h_pool1,W_conv2)+b_conv2)
最后也是一个pooling处理,输出大小为7x7x64
h_pool2=max_pool_2x2(h_conv2)
建立全连接层
定义 fully connected layer,进入全连接层时, 通过tf.reshape()
将h_pool2
的输出值从一个三维的变为一维的数据,
-1表示先不考虑输入图片例子维度, 将上一个输出结果展平.
#[n_samples,7,7,64]->>[n_samples,7*7*64]
h_pool2_flat=tf.reshape(h_pool2,[-1,7*7*64])
此时weight_variable
的shape
输入就是第二个卷积层展平了的输出大小: 7x7x64,
后面的输出size我们继续扩大,定为1024
W_fc1=weight_variable([7*7*64,1024])
b_fc1=bias_variable([1024])
然后将展平后的h_pool2_flat
与本层的W_fc1
相乘(注意这个时候不是卷积了)
h_fc1=tf.nn.relu(tf.matmul(h_pool2_flat,W_fc1)+b_fc1)
如果考虑过拟合问题,可以加一个dropout的处理
h_fc1_drop=tf.nn.dropout(h_fc1,keep_drop)
接下来进行最后一层的构建了,输入是1024,最后的输出是10个
(因为mnist数据集就是[0-9]十个类),prediction就是最后的预测值
W_fc2=weight_variable([1024,10]) b_fc2=bias_variable([10])
用softmax分类器(多分类,输出是各个类的概率),对输出进行分类
prediction=tf.nn.softmax(tf.matmul(h_fc1_dropt,W_fc2),b_fc2)
选优化方法
利用交叉熵损失函数来定义cost function
cross_entropy=tf.reduce_mean(
-tf.reduce_sum(ys*tf.log(prediction),
reduction_indices=[1]))
用tf.train.AdamOptimizer()
作为优化器进行优化,使cross_entropy
最小
train_step=tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
定义Session
sess=tf.Session()
初始化变量
# tf.initialize_all_variables() 这种写法马上就要被废弃
# 替换成下面的写法:
sess.run(tf.global_variables_initializer())
接着就是训练数据.假定训练1000
步,每50
步输出一下准确率.