概述
卷积神经网络经常被使用在图像识别中,可以有效提升图像的识别效率。某种程度上来说卷积神经网络做的也是特征工程的工作,不管是池化还是卷积都是为了将图片中的隐藏信息转变成特征向量传入神经网络中。
代码
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
# 权重初始化
def weight_value(shape):
inital=tf.truncated_normal(shape,stddev=0.1)
return tf.Variable(inital)
# 偏置初始化
def bias_value(shape):
inital=tf.constant(0.1,shape=shape)
return tf.Variable(inital)
# 卷积设置
def conv2d(x,W):
return tf.nn.conv2d(x,W,[1,1,1,1],padding='SAME')
# 设置池化
def max_pool_2X2(x):
return tf.nn.max_pool(x,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
if __name__="__main__":
#载入数据集
mnist=input_data.read_data_sets("MNIST.data",one_hot=True)
#定义每个批次的大小
batch_size=100
#计算一共有多少个批次
n_batch=mnist.train.num_examples//batch_size
# 定义两个placeholder
x=tf.placeholder(tf.float32,[None,784])
y=tf.placeholder(tf.float32,[None,10])
# 改变x的格式转为4D向量[batch,in_heigh,in_width,in_channel]
x_image=tf.reshape(x,[-1,28,28,1])#功能和numpy里面的reshape函数对象是类似的
# 初始化第一个卷积层的权重和偏置
w_conv1=weight_value([5,5,1,32])#5*5的采样窗口,32个卷积核从一个平面抽取特征
b_conv1=bias_value([32])#每个卷积核一个偏置
# 把x_image的权重向量进行卷积再加上偏置值,然后用relu激活函数
h_conv1=tf.nn.relu(conv2d(x_image,w_conv1)+b_conv1)
h_pool1=max_pool_2X2(h_conv1)
# 初始化第二个卷积层的权重和偏置
w_conv2=weight_value([5,5,32,64])#5*5的采样窗口,64个卷积核从32个平面抽取特征
b_conv2=bias_value([64])#每个卷积核一个骗置
# 把x_image的权重向量进行卷积再加上偏置值,然后用rule激活函数
h_conv2=tf.nn.relu(conv2d(h_pool1,w_conv2)+b_conv2)
h_pool2=max_pool_2X2(h_conv2)
# 28x28的图片第一次卷积后还是28x28,池化后变成了14x14
# 第二次卷积后是14x14,池化后变成了7x7
# 进行上述操作后得到64张7x7的平面
# 初始化第一个全连接层的权重
W_fc1=weight_value([7*7*64,1024])# 上一层有7*7*64个神经元,全连接层有1024个神经元
b_fc1=bias_value([1024])
# 把池化层2的输出扁平化为1维
h_pool2_flat=tf.reshape(h_pool2,[-1,7*7*64])
# 求第一个全连接层的输出
h_fc1=tf.nn.relu(tf.matmul(h_pool2_flat,W_fc1)+b_fc1)
#keep_prob用来表示神经元输出概率
keep_prob=tf.placeholder(tf.float32)
h_fc1_drop=tf.nn.dropout(h_fc1,keep_prob)
#初始化第二个全连接层
W_fc2=weight_value([1024,10])
b_fc2=bias_value([10])
#计算输出
prediction=tf.nn.softmax(tf.matmul(h_fc1_drop,W_fc2)+b_fc2)
# 交叉熵代价函数
cross_entropy=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y,logits=prediction))
#使用AdamOptimizer优化器
train_step=tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
#测试模型准确率,结果存放在一个bool型列表中
correct_prediction=tf.equal(tf.argmax(prediction,1),tf.argmax(y,1))#argmax返回一维张量中最大值所在的位置
#求准确率
accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32))#cast函数是转化类型
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for epoch in range(21):
for batch in range(n_batch):
batch_xs,bathc_ys=mnist.train.next_batch(batch_size)
sess.run(train_step,feed_dict={x:batch_xs,y:bathc_ys,keep_prob:0.7})
acc=sess.run(accuracy,feed_dict={x:mnist.test.images,y:mnist.test.labels,keep_prob:1.0})
print("Iter"+str(epoch)+"accurency"+str(acc))
代码说明
接下来我们从main的判断位置开始说明:
代码中使用了手写数字图片集合,定义每次放入100个图片进行训练;
使用**tensorflow.placeholder()**函数对象定义了x和y占位符;
使用**tensorflow.reshape()**函数对象将图像的输入维度转为4D向量,这是为了后面模型训练做准备的,这个功能和numpy中的reshape函数对象基本一样;
调用自定义的权重初始化函数weight_value(),使用函数对象;
**tensorflow.truncated_normal()**生成指定大小范围内指定均值和标准差的随机数,这里是定义了一个5*5窗口的卷积核,一共定义了32个卷积核,也就是通过原图像生成了32个通过卷积核操作的图像;
随后调用自定义偏置函数bias_value(),为每次卷积操作添加偏置量;
调用**tensorflow.nn.relu()**函数处理卷积后的图片矩阵,将非0数据抹除;
使用**tensorflow.nn.max_pool()**函数对象将卷积后的图像矩阵进行池化处理;
重复上述卷积核池化操作,最后得到64张7x7的平面图片矩阵;
将这些图片矩阵作为特征输入1024个神经元中,使用softmax激活函数进行处理,最后得到输出值。