深度学习笔记5-tensorflow实现卷积神经网络

深度学习笔记5-tensorflow实现卷积神经网络

在股票等预测模型中,可以从原始数据提取金融因子等特征。而图像则无有效特征,只能借助SIFT、HOG等提取有效特征,再集合SVM等机器学习算法进行图像识别。卷积神经网络(CNN)提取的特征则可以达到更好的效果,同时它不需要将特征提取和分类训练两个过程分开,它在训练时就自动提取了最有效的特征。CNN可以直接使用图像的原始像素作为输入,而不必先使用SIFT等算法提取特征,减轻了使用传统算法如SVM时必需要做的大量重复、烦琐的数据预处理工作。和SIFT等算法类似,CNN训练的模型同样对缩放、平移、旋转等畸变具有不变性,有着很强的泛化性。CNN的最大特点在于卷积的权值共享结构,可以大幅减少神经网络的参数量,防止过拟合的同时又降低了神经网络模型的复杂度。

一般的卷积神经网络由多个卷积层构成,每个卷积层中通常会进行如下几个操作:
(1)图像通过多个不同的卷积核的滤波,并加偏置(bias),提取出局部特征,每一个卷积核会映射出一个新的2D图像。
(2)将前面卷积核的滤波输出结果,进行非线性的激活函数处理。目前最常见的是使用ReLU函数(ReLU函数可参见深度学习笔记2-激活函数
(3)对激活函数的结果再进行池化操作(即降采样,比如将2×2的图片降为1×1的图片),目前一般是使用最大池化,保留最显著的特征,并提升模型的畸变容忍能力。
(4)为了提升训练速度、加快收敛过程、降低参数初始化的要求,可在每一个卷积层后加上BatchNomalization层

TensorFlow实现简单的卷积网络

import tensorflow as tf
import input_data
#载入MNIST数据集
mnist=input_data.read_data_sets("MNIST_data/",one_hot=True)

#对于权重制造一些随机的噪声来打破完全对称,比如截断的正态分布噪声,标准差设为0.1。
def weight_variable(shape):
    initial=tf.truncated_normal(shape,stddev=0.1)
    return tf.Variable(initial)
    
#因为我们使用ReLU,也给偏置增加一些小的正值(0.1)用来避免死亡节点。
def bias_variable(shape):
    initial=tf.constant(0.1,shape=shape)
    return tf.Variable(initial)

#x是输入,W是卷积的参数,比如[5,5,1,32]:前面两个数字代表卷积核的尺寸;
#W的第三个数字代表有多少个channel,对于灰度图应设置为1,对于彩色图应设置为3
#W的第四个数字代表卷积核的数量,也就是这个卷积层会提取多少类的特征。
#Strides代表卷积模板移动的步长,都是1代表会不遗漏地划过图片的每一个点。
#Padding代表边界的处理方式,这里的SAME代表给边界加上Padding让卷积的输出和输入保持同样(SAME)的尺寸。
def conv2d(x,W):
    return tf.nn.conv2d(x,W,strides=[1,1,1,1],padding='SAME')

#这里使用2×2的最大池化,即将一个2×2的像素块降为1×1的像素。最大池化会保留原始像素块中灰度值最高的那一个像素,即保留最显著的特征。
#因为希望整体上缩小图片尺寸,因此池化层的strides也设为横竖两个方向以2为步长。如果步长还是1,那么我们会得到一个尺寸不变的图片。
def max_pool_2x2(x):
    return tf.nn.max_pool(x,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')

#开始构建图
x=tf.placeholder("float",shape=[None,784])
#将1D的输入向量转为2D的图片结构,即从1×784的形式转为原始的28×28的结构。
#同时因为只有一个颜色通道,故最终尺寸为[-1,28,28,1],前面的-1代表样本数量不固定,最后的1代表颜色通道数量。
#注意图片格式和卷积格式的各个维度的定义是不一样的
x_image=tf.reshape(x,[-1,28,28,1])
y_=tf.placeholder("float",shape=[None,10])

#构建第一个卷积层
W_conv1=weight_variable([5,5,1,32])
b_conv1=bias_variable([32])
h_conv1=tf.nn.relu(conv2d(x_image,W_conv1)+b_conv1)
h_pool1=max_pool_2x2(h_conv1)

#构建第二个卷积层
W_conv2=weight_variable([5,5,32,64])     #卷积核变成64个了
b_conv2=bias_variable([64])
h_conv2=tf.nn.relu(conv2d(h_pool1,W_conv2)+b_conv2)
h_pool2=max_pool_2x2(h_conv2)

#构建全连接层
W_fc1=weight_variable([7*7*64,1024])
b_fc1=bias_variable([1024])
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)

#为了减轻过拟合,下面使用一个Dropout层
#通过一个placeholder传入keep_prob比率来控制遗弃率
#注意,在训练时,会随机丢弃一部分节点的数据来减轻过拟合,预测时则保留全部数据来追求最好的预测性能。
keep_prob=tf.placeholder("float")
h_fc1_drop=tf.nn.dropout(h_fc1,keep_prob)

#构建第二个全连接层,将输出连接一个Softmax层,得到最后的概率输出。
W_fc2=weight_variable([1024,10])
b_fc2=bias_variable([10])
y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop,W_fc2)+b_fc2)

#定义损失函数
cross_entropy=-tf.reduce_sum(y_*tf.log(y_conv))

#优化函数选为Adam函数
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)

#定义准确率用以评测
correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

#下面开始训练过程,采用默认的Interactive Session
sess=tf.InteractiveSession()
sess.run(tf.global_variables_initializer())   #初始化所有参数
#使用大小为50的mini-batch,共进行1000次训练迭代。每100次训练后,会对准确率进行一次评测
for i in range(1000):
    batch=mnist.train.next_batch(50)
    if i%100==0:
        train_accuracy=accuracy.eval(feed_dict={x: batch[0], y_: batch[1],keep_prob:0.5})
        print('step %d, training accuracy %g'%(i,train_accuracy))
    train_step.run(feed_dict={x:batch[0],y_:batch[1],keep_prob:0.5})
#全部训练完成后,在最终的测试集上进行测试,得到整体的分类准确率。
print('test accuracy %g'%accuracy.eval(feed_dict={x:mnist.test.images,y_:mnist.test.labels,keep_prob:1.0}))
    
sess.close()

基本上,以上程序已经包括了构建神经网络的流程:
(1)定义图,也就是神经网络forward时的计算
(2)定义loss,选定优化器,并指定优化器优化loss
(3)迭代地对数据进行训练
(4)在测试集上对准确率进行评测

参考:
黄文坚《Tensorflow实战》

猜你喜欢

转载自blog.csdn.net/zhennang1427/article/details/85679176
今日推荐