基于TensorFlow实现卷积神经网络 3
2017-08-28 16:15
531 查看
TensorFlow实现CNN
搭建TensorFlow环境
一、实验介绍
1.1 实验内容
上节实验我们使用TensorFlow实现了一个简单的神经网络,本节实验我们将使用自己的图片数据,学习如何使用 TensorFlow 实现一个卷积神经网络(
Convolutional Neural Networks, CNN)。
关于 CNN 的理论基础请学习
861 基于卷积神经网络实现图片风格的迁移.
卷积神经网络详解章节
1.2 实验知识点
什么是卷积神经网络TensorFlow 实现 CNN
1.3 实验环境
python2.7Tensorflow 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 tf import 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.shape print Y_data.shape
在终端运行
myCNN.py
$ python myCNN.py
输出为
#输入和输出数据格式 (1797, 64) (1797, 1)
继续编辑
myCNN.py
#数据的标准化(normalization)是将数据按比例缩放, #使之落入一个小的特定区间。这样去除数据的单位限制, #将其转化为无量纲的纯数值,便于不同单位或量级的指标能够进行比较和加权。 from sklearn.preprocessing import MinMaxScaler scaler = MinMaxScaler() X_data = scaler.fit_transform(X_data) print X_data from sklearn.preprocessing import OneHotEncoder Y = 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为8 def 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_b2 print 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-3 BN_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_out relu_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实现卷积神经网络 1
- 基于TensorFlow实现卷积神经网络 2
- 卷积神经网络LeNet5,基于TensorFlow的实现
- tensorflow(4)---mnist问题的深度卷积神经网络(基于官网文档的实现)
- 基于字符的卷积神经网络实现文本分类(char-level CNN)-论文详解及tensorflow实现
- Chinese-Text-Classification,用卷积神经网络基于 Tensorflow 实现的中文文本分类。
- [置顶] 基于 TensorFlow 的图像识别(R实现)
- 如何基于TensorFlow使用LSTM和CNN实现时序分类任务
- 我用 tensorflow 实现的“一个神经聊天模型”:一个基于深度学习的聊天机器人
- TensorFlow - 手写数字识别 (卷积神经网络实现)
- TensorFlow上实现卷积神经网络CNN
- Tensorflow实战( 四)经典卷积神经网络之实现AlexNet
- deeplearning.ai 第四课第一周, 卷积神经网络的tensorflow实现
- python tensorflow基于cnn实现手写数字识别
- 基于 TensorFlow 在手机端实现文档检测
- TensorFlow 实战之实现卷积神经网络
- 基于tensorflow实现的简单卷积网络(CNN)
- 手把手教你如何用 TensorFlow 实现基于 DNN 的文本分类
- 【强化学习实战】基于gym和tensorflow的强化学习算法实现
- 基于循环神经网络实现基于字符的语言模型(char-level RNN Language Model)-tensorflow实现