基于TensorFlow实现卷积神经网络 3
来源:互联网 发布:建站影响以后的优化吗 编辑:程序博客网 时间:2024/05/18 00:07
TensorFlow实现CNN
搭建TensorFlow环境
一、实验介绍
1.1 实验内容
上节实验我们使用 TensorFlow
实现了一个简单的神经网络,本节实验我们将使用自己的图片数据,学习如何使用 TensorFlow 实现一个卷积神经网络(Convolutional Neural Networks, CNN
)。
关于 CNN 的理论基础请学习 861 基于卷积神经网络实现图片风格的迁移. 卷积神经网络详解章节
1.2 实验知识点
- 什么是卷积神经网络
- TensorFlow 实现 CNN
1.3 实验环境
- python2.7
- Tensorflow 0.8
- Xfce终端
1.4 先修课程
- 861 基于卷积神经网络实现图片风格的迁移
卷积神经网络详解章节
二、 卷积神经网络
有了神经网络,我们就可以对输入的信息进行特征提取,但是图像包含的信息量巨大,一般的神经网络并不能准确的提取图像的特征,这时 卷积神经网络(Convolutional Neural Networks, CNN)
就是计算机处理图像的助推器,有了它,计算机理解图像就会更准确.
注意:CNN 并不是只用来处理图片,也可以用于处理文本及语音数据等具有部分层级特征的信息。
卷积神经网络包含输入层、隐藏层和输出层,隐藏层又包含 卷积层(conv)
和 池化层(pooling)
。
下图展示了,卷积层处理图像的基本过程:
从图上我们可以看出,立方体不断的增加厚度,这是因为图像输入到卷积神经网络后通过 卷积核
来不断的提取特征,每提取一个特征就会增加一个feature map
。那么为什么厚度增加了但是却越来越瘦了呢,这是因为 pooling层
的作用,pooling层本质是下采样,通常采用的是最大值pooling和平均值pooling,因为参数太多会导致计算越来越复杂,所以通过pooling
来稀疏参数,使我们的网络不至于太复杂。
现在我们对卷积神经网络已经有了大概的了解,下节我们将通过代码来实现一个简单的卷积神经网络。
三、实现 CNN
3.1 基本流程
通过搭建卷积神经网络来实现sklearn库中的手写数字识别,搭建的卷积神经网络结构如下图所示:
3.2 开始搭建
3.2.1 准备
打开终端
#激活TensorFlow环境$ cd /home/shiyanlou/tensorflow$ source bin/activate
下载Python中的机器学习包 sklearn
sudo apt-get install python-sklearn
我们将卷积神经网络写在 myCNN.py
中
$ sudo gedit myCNN.py
如果你需要添加注释,请在文件头部加入
# -*- coding: utf-8 -*-
导入 TensorFlow 和 Numpy:
import tensorflow as tfimport numpy as np
3.2.2 数据预处理
from sklearn.datasets import load_digits #sklearn 为我们提供的手写数字数据集#数据预处理digits = load_digits()X_data = digits.data.astype(np.float32)Y_data = digits.target.astype(np.float32).reshape(-1,1)print X_data.shapeprint Y_data.shape
在终端运行 myCNN.py
$ python myCNN.py
输出为
#输入和输出数据格式(1797, 64)(1797, 1)
继续编辑 myCNN.py
#数据的标准化(normalization)是将数据按比例缩放,#使之落入一个小的特定区间。这样去除数据的单位限制,#将其转化为无量纲的纯数值,便于不同单位或量级的指标能够进行比较和加权。from sklearn.preprocessing import MinMaxScalerscaler = MinMaxScaler()X_data = scaler.fit_transform(X_data)print X_datafrom sklearn.preprocessing import OneHotEncoderY = OneHotEncoder().fit_transform(Y_data).todense() #one-hot编码print Y
在终端运行 myCNN.py
$ python myCNN.py
输出为
#标准化后的数据[[ 0. 0. 0.3125 ..., 0. 0. 0. ] [ 0. 0. 0. ..., 0.625 0. 0. ] [ 0. 0. 0. ..., 1. 0.5625 0. ] ..., [ 0. 0. 0.0625 ..., 0.375 0. 0. ] [ 0. 0. 0.125 ..., 0.75 0. 0. ] [ 0. 0. 0.625 ..., 0.75 0.0625 0. ]]#独热编码[[ 1. 0. 0. ..., 0. 0. 0.] [ 0. 1. 0. ..., 0. 0. 0.] [ 0. 0. 1. ..., 0. 0. 0.] ..., [ 0. 0. 0. ..., 0. 1. 0.] [ 0. 0. 0. ..., 0. 0. 1.] [ 0. 0. 0. ..., 0. 1. 0.]]
继续编辑 myCNN.py
# 转换为图片的格式 (batch,height,width,channels)X = X_data.reshape(-1,8,8,1)batch_size = 8 # 使用MBGD算法,设定batch_size为8def generatebatch(X,Y,n_examples, batch_size): for batch_i in range(n_examples // batch_size): start = batch_i*batch_size end = start + batch_size batch_xs = X[start:end] batch_ys = Y[start:end] yield batch_xs, batch_ys # 生成每一个batch
清除默认图的堆栈,并设置全局图为默认图
tf.reset_default_graph()
3.2.3 layer
实现
输入层
tf_X = tf.placeholder(tf.float32,[None,8,8,1])tf_Y = tf.placeholder(tf.float32,[None,10])
卷积层 conv1 + 激活层
conv_filter_w1 = tf.Variable(tf.random_normal([3, 3, 1, 10]))conv_filter_b1 = tf.Variable(tf.random_normal([10]))relu_feature_maps1 = tf.nn.relu(\ tf.nn.conv2d(tf_X, conv_filter_w1,strides=[1, 1, 1, 1], padding='SAME') + conv_filter_b1)'''参数说明:- data_format:表示输入的格式,有两种分别为:“NHWC”和“NCHW”,默认为“NHWC”- input:输入是一个4维格式的(图像)数据,数据的 shape 由 data_format 决定:当 data_format 为“NHWC”输入数据的shape表示为[batch, in_height, in_width, in_channels],分别表示训练时一个batch的图片数量、图片高度、 图片宽度、 图像通道数。当 data_format 为“NHWC”输入数据的shape表示为[batch, in_channels, in_height, in_width]- filter:卷积核是一个4维格式的数据:shape表示为:[height,width,in_channels, out_channels],分别表示卷积核的高、宽、深度(与输入的in_channels应相同)、输出 feature map的个数(即卷积核的个数)。- strides:表示步长:一个长度为4的一维列表,每个元素跟data_format互相对应,表示在data_format每一维上的移动步长。当输入的默认格式为:“NHWC”,则 strides = [batch , in_height , in_width, in_channels]。其中 batch 和 in_channels 要求一定为1,即只能在一个样本的一个通道上的特征图上进行移动,in_height , in_width表示卷积核在特征图的高度和宽度上移动的布长,即 strideheight 和 stridewidth 。-padding:表示填充方式:“SAME”表示采用填充的方式,简单地理解为以0填充边缘,当stride为1时,输入和输出的维度相同;“VALID”表示采用不填充的方式,多余地进行丢弃。具体公式:“SAME”: output_spatial_shape[i]=⌈(input_spatial_shape[i] / strides[i])⌉“VALID”: output_spatial_shape[i]=⌈((input_spatial_shape[i]−(spatial_filter_shape[i]−1)/strides[i])⌉'''
池化层
max_pool1 = tf.nn.max_pool(relu_feature_maps1,ksize=[1,3,3,1],strides=[1,2,2,1],padding='SAME')'''- value:表示池化的输入:一个4维格式的数据,数据的 shape 由 data_format 决定,默认情况下shape 为[batch, height, width, channels]其他参数与 tf.nn.cov2d 类型- ksize:表示池化窗口的大小:一个长度为4的一维列表,一般为[1, height, width, 1],因不想在batch和channels上做池化,则将其值设为1。'''print max_pool1
卷积层 conv2
conv_filter_w2 = tf.Variable(tf.random_normal([3, 3, 10, 5]))conv_filter_b2 = tf.Variable(tf.random_normal([5]))conv_out2 = tf.nn.conv2d(relu_feature_maps1, conv_filter_w2,strides=[1, 2, 2, 1], padding='SAME') + conv_filter_b2print conv_out2
BN归一化层+激活层
batch_mean, batch_var = tf.nn.moments(conv_out2, [0, 1, 2], keep_dims=True)shift = tf.Variable(tf.zeros([5]))scale = tf.Variable(tf.ones([5]))epsilon = 1e-3BN_out = tf.nn.batch_normalization(conv_out2, batch_mean, batch_var, shift, scale, epsilon)'''参数说明:- mean 和 variance 通过 tf.nn.moments 来进行计算: batch_mean, batch_var = tf.nn.moments(x, axes = [0, 1, 2], keep_dims=True),注意axes的输入。对于以feature map 为维度的全局归一化,若feature map 的shape 为[batch, height, width, depth],则将axes赋值为[0, 1, 2]- x 为输入的feature map 四维数据,offset、scale为一维Tensor数据,shape 等于 feature map 的深度depth。'''print BN_outrelu_BN_maps2 = tf.nn.relu(BN_out)
池化层
max_pool2 = tf.nn.max_pool(relu_BN_maps2,ksize=[1,3,3,1],strides=[1,2,2,1],padding='SAME')print max_pool2
将特征图进行展开
max_pool2_flat = tf.reshape(max_pool2, [-1, 2*2*5])
全连接层
fc_w1 = tf.Variable(tf.random_normal([2*2*5,50]))fc_b1 = tf.Variable(tf.random_normal([50]))fc_out1 = tf.nn.relu(tf.matmul(max_pool2_flat, fc_w1) + fc_b1)
输出层
out_w1 = tf.Variable(tf.random_normal([50,10]))out_b1 = tf.Variable(tf.random_normal([10]))pred = tf.nn.softmax(tf.matmul(fc_out1,out_w1)+out_b1)
3.3.4 开始训练
loss = -tf.reduce_mean(tf_Y*tf.log(tf.clip_by_value(pred,1e-11,1.0)))# Adam优化算法:是一个寻找全局最优点的优化算法,引入了二次方梯度校正。# 相比于基础SGD算法,1.不容易陷于局部优点。2.速度更快train_step = tf.train.AdamOptimizer(1e-3).minimize(loss)y_pred = tf.arg_max(pred,1)bool_pred = tf.equal(tf.arg_max(tf_Y,1),y_pred)accuracy = tf.reduce_mean(tf.cast(bool_pred,tf.float32)) # 准确率with tf.Session() as sess: sess.run(tf.initialize_all_variables()) for epoch in range(100): # 迭代100个周期 for batch_xs,batch_ys in generatebatch(X,Y,Y.shape[0],batch_size): # 每个周期进行MBGD算法 sess.run(train_step,feed_dict={tf_X:batch_xs,tf_Y:batch_ys}) res = sess.run(accuracy,feed_dict={tf_X:X,tf_Y:Y}) print (epoch,res)//打印每次迭代的准确率 res_ypred = y_pred.eval(feed_dict={tf_X:X,tf_Y:Y}).flatten() # 只能预测一批样本,不能预测一个样本 print res_ypred
保存 myCNN.py
,重新回到终端
$ python myCNN.py
如果你的程序开始训练了,那么恭喜你搭建了一个简单的 CNN。
完整代码获取:
$ cd /home/shiyanlou/tensorflow$ wget http://labfile.oss.aliyuncs.com/courses/893/myCNN.py
四、实验总结
至此,本次实验结束,我们对所进行的工作进行总结:
- 首先,我们学习了TensorFlow 的基本用法,亲自动手搭建了
TensorFlow 0.8
的环境 - 第二次实验,我们通过搭建神经网络学习如何使用 TensorFlow
- 最后我们搭建了卷积神经网络
CNN是我们学习深度学习的基础之一,它非常的强大,与高科技息息相关,只有充分的理解卷积神经网络,才能在深入深度学习的过程中披荆斩棘。后续课程我们将介绍另一个经典的网络模型RNN与LSTM模型
。
五、课后习题
- 请你完成训练完成之后训练模型的保存。
- [理解归一化层]我们在第100次个batch size 迭代时,准确率就快速接近收敛了,这得归功于
Batch Normalization
的作用!如果模型应用于单个样本,请你观察预测效果,是否发现我们会得到相反的预测效果,请思考原因。
六、参考链接
- TensorFlow 英文官方网站
- TensorFlow 官方GitHub仓库
- 基于TensorFlow实现卷积神经网络 3
- 卷积神经网络LeNet5,基于TensorFlow的实现
- 基于TensorFlow实现卷积神经网络 1
- 基于TensorFlow实现卷积神经网络 2
- TensorFlow实现卷积神经网络
- Tensorflow实现卷积神经网络
- Tensorflow实现卷积神经网络
- Tensorflow实现卷积神经网络
- TensorFlow实现卷积神经网络
- Tensorflow实现卷积神经网络
- Tensorflow实现卷积神经网络
- TensorFlow实现卷积神经网络
- tensorflow 卷积神经网络实现
- Tensorflow实现卷积神经网络
- 卷积神经网络之tensorflow实现
- Tensorflow实现卷积神经网络模型
- TensorFlow实现卷积神经网络CNN
- TensorFlow实现卷积神经网络CNN
- django 数据库模型映射
- 如何使用memcache
- 嵌套select语句
- 三大框架知识点之 Spring的Bean的基本概念
- easyui demo 事例
- 基于TensorFlow实现卷积神经网络 3
- TCP/IP协议
- jieba(结巴)分词种词性简介
- string类学习字符串中的子串出现次数与替换的问题
- POJ2676 DFS
- ASp.net判断文件或文件夹是否存在
- 经验分享 |【PDF下载】双11技术峰会之面对双11的前端“极限挑战”
- scala中的reduceLeft,reduceRight,foldLeft,foldRight方法
- Android-onCreate与virtual function