汐月教育之理解TensorFlow(三.1)构建简单的BP神经网络+softmax多分类进行MNIST识别

  • Post author:
  • Post category:其他











作者:JUDGE_MENT



邮箱:gao19920804@126.com

CSDN博客:http://blog.csdn.net/sinat_23137713

最后编辑时间:2016.12.5  V1.1

声明:

1)该资料结合官方文档及网上大牛的博客进行撰写,如有参考会在最后列出引用列表。

2)本文仅供学术交流,非商用。如果不小心侵犯了大家的利益,还望海涵,并联系博主删除。

3)转载请注明出处。


4)

本文主要是用来记录本人初学Tensorflow时遇到的问题,特此记录下来,因此并不是所有的方法(如安装方法)都会全面介绍。希望后人看到可以引以为鉴,避免走弯路。同时毕竟水平有限,希望有饱含学识之士看到其中的问题之后,可以悉心指出,本人感激不尽。




整体步骤:导入tensorflow–>启动交互式session–>构建图–>运行图–>输出图。运行普通session很难实时调试,上文也介绍了可以使用交互式的intersession进行交互式的使用。本文主要是实战演练交互式session中,构建简单的BP神经网络+softmax多分类,具体步骤如下:


注意,交互式session中,使用 InteractiveSession 代替 Session 类(), 使用 Tensor.eval()和 Operation.run() 方法代替 Session.run(). 这样可以避免使用一个变量来持有会话。上一话中使用的sess.run( ), 而这里变成了优化参数函数.run( )。








一. 导入tensorflow包


import tensorflow as tf








二. 启动交互式session


sess = tf.InteractiveSession()








三.


模型输入





from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)








四. 构建图–推理(inference)–模型预测









1.创建输入输出占位符






输入节点:

x=tf.placeholder("float",shape=[None,784])





输出节点:

y_ = tf.placeholder("float", shape=[None, 10])





  • 输入图片x是一个2维的浮点数张量。这里,分配给它的shape为[None, 784],其中784是一张展平的MNIST图片的维度。None表示其值大小不定,在这里作为第一个维度值,用以指代batch的大小

    (批量训练)

    ,意即x的数量不定。

  • 输出类别值y_也是一个2维张量,其中每一行为一个10维的one-hot向量,用于代表对应某一MNIST图片的类别。

  • 虽然placeholder的shape参数(shape是每一阶有多少维)是可选的,但有了它,TensorFlow能够自动捕捉因数据维度不一致导致的错误。




2.第一层创建变量


<1> 变量太多,自己建立个函数来建立权重矩阵和偏置矩阵。




def weight_variable(shape):
  initial = tf.truncated_normal(shape, stddev=0.1)
  return tf.Variable(initial)
def bias_variable(shape):
  initial = tf.constant(0.1, shape=shape)
  return tf.Variable(initial)


<2> 卷积+池化。对于卷积从5*5到像素块–>输入1个通道–>输出32个通道

W_conv1 = weight_variable([5, 5, 1, 32])
b_conv1 = bias_variable([32])










3.第一层写出输出函数






卷积函数在tf.nn.conv2d(),;四个参数:输入第一个参数为输入变量,第二个参数为权重,第三,第四略。




下采样函数在tf.nn.max_pool();同样资格参数



<1>

因为这两个函数某些参数一直保持默认值就可以,所以为了简洁,把这两个封装成函数。

def conv2d(x, W):
  return tf.nn.conv2d(x, W, strides=[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')


<2>  写出输出函数




输入的x需要变形称conv2d接受的形式(上面softmax把数据当成一个向量了,这里要把图片当成矩阵),

变成一个4d向量,其第2、第3维对应图片的宽、高,最后一维代表图片的颜色通道数(因为是灰度图所以这里的通道数为1,如果是rgb彩色图,则为3

)。




x_image = tf.reshape(x, [-1,28,28,1])


我们把x_image和权值向量进行卷积,加上偏置项,然后应用ReLU激活函数,最后进行maxpooling。

h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)










4.第二层创建变量



W_conv2 = weight_variable([5, 5, 32, 64])
b_conv2 = bias_variable([64])




5.第二层写出输出函数

h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)





6.密集连接层创建变量


W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])





7.密集连接层写出输出函数


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)


加入一个有1024个神经元的全连接层





8.Dropout




就是hilton发明的一个防止过拟合的装置,原理其实很简单,就是一部分不输出。训练的时候开启,输出时不开启。


keep_prob = tf.placeholder("float")
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)








9.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)








五. 构建图–损失(Loss)+训练参数选择–模型训练




1.损失函数选择


损失函数使用交叉熵:


cross_entropy = -tf.reduce_sum(y_*tf.log(y_conv))





2.


优化算法和步长选择设置


train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)

这里步长设置为1e-4,优化算法使用AdamOptimizer,来最优化损失函数


3.评估模型结果指标

correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))

tf.argmax:  给出某个tensor对象在某一维上的其数据最大值所在的索引值,由于标签向量是由0,1组成,因此最大值1所在的索引位置就是类别标签.

这里返回一个布尔数组。为了计算我们分类的准确率,我们将布尔值转换为浮点数来代表对、错,然后取平均值。例如:[True, False, True, True]变为[1,0,1,1],计算出平均值为0.75。

accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))








六. 运行图–训练



1.变量全都初始化


这一步是训练前必经之路

sess.run(tf.initialize_all_variables())


2.循环训练

for i in range(20000):				                           #训练20000次
  batch = mnist.train.next_batch(50)		                           #这里是训练数据每次抽取50个
  if i%100 == 0:				                           #每训练100次输出这么一个训练准确率
    train_accuracy = accuracy.eval(feed_dict={x:batch[0], y_: batch[1], keep_prob: 1.0})
    print "step %d, training accuracy %g"%(i, train_accuracy)
  train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})    #这里train_step.run就用来更新权重了







七. 输出结果


print "test accuracy %g"%accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0})



经过20000次的迭代修正权值,最终在测试集上准确率达到99.06%的准确率。



版权声明:本文为sinat_23137713原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。