tensorflow:1)简单的神经网络

来源:互联网 发布:钢筋笼计算软件 编辑:程序博客网 时间:2024/06/17 18:48

菜鸟的感慨:如今很少碰到像tensorflow这样有心体贴的官方文档,基础的知识文档解释非常清晰,这里只总结笔者在学习时的一些疑惑、

本篇对应的官网文档章节:MNIST For ML Beginners,中间没有隐藏层,确切来说这节属于softmax回归范畴,不过它是神经网络的基础噢

首先把这节的完整代码贴下-softmax回归

# encoding:utf-8import tensorflow as tf#加载mnist数据from tensorflow.examples.tutorials.mnist import input_datamnist = input_data.read_data_sets("MNIST_data/", one_hot=True)#定义输入的变量的占位符x,None表示这一维可以是任意长度(图片的张数)x = tf.placeholder(tf.float32, [None, 784])#初始化权重W和偏置b都为0W = tf.Variable(tf.zeros([784, 10]))b = tf.Variable(tf.zeros([10]))#使用softmax激活函数获得计算的值yy = tf.nn.softmax(tf.matmul(x, W) + b)#y_为训练数据对于的结果标签y_ = tf.placeholder(tf.float32, [None, 10])#使用交叉熵获得损失函数cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))#使用梯度下降法最小化损失函数 0.5为学习速率train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)#获得可交互sessionsess = tf.InteractiveSession()#初始化定义的变量tf.global_variables_initializer().run()#进行1000次迭代训练for _ in range(1000):    #随机从训练集中抽取100个样本作为一个批次进行训练    batch_xs, batch_ys = mnist.train.next_batch(100)    #为占位变量赋值    sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})#计算模型的准确度correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))#最后的结果 0.9143


接下来,在上面的代码上进行修改,添加了一个隐藏层(包含128个神经元)的神经网络。

先把修改的代码贴出来-神经网络

# encoding:utf-8import tensorflow as tf# 加载mnist数据from tensorflow.examples.tutorials.mnist import input_datamnist = input_data.read_data_sets("MNIST_data/", one_hot=True)# 定义输入的变量的占位符x,None表示这一维可以是任意长度(图片的张数)x = tf.placeholder(tf.float32, [None, 784])#隐藏层神经元个数num_hidden=128#使用正态分布初始化WW = tf.Variable(tf.truncated_normal([784, num_hidden], stddev=0.1))b = tf.Variable(tf.zeros([num_hidden]))# 使用relu激活函数获得计算的值x1x1 =tf.nn.relu(tf.matmul(x, W) + b)W1 = tf.Variable(tf.truncated_normal([num_hidden, 10], stddev=0.1))b1 = tf.Variable(tf.zeros([10]))# 使用softmax激活函数获得计算的值yy= tf.nn.softmax(tf.matmul(x1, W1) + b1)# y_为训练数据对于的结果标签y_ = tf.placeholder(tf.float32, [None, 10])# 使用交叉熵获得损失函数cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))# 使用梯度下降法最小化损失函数 0.5为学习速率train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)# 获得可交互sessionsess = tf.InteractiveSession()# 初始化定义的变量tf.global_variables_initializer().run()# 进行1000次迭代训练for i in range(1000):    # 随机从训练集中抽取100个样本作为一个批次进行训练    batch_xs, batch_ys = mnist.train.next_batch(100)    # 为占位变量赋值    sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})# 计算模型的准确度correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))# 最后的结果 0.9687

较softmax回归准确度提升了不少,这里我们修改了2个地方:

(1)把之前W和b的作用激活函数换成了relu,看下它的公式,relu=max(x,0),非常简单并且解决了梯度消失的问题

(2)W的初始化值为随机正态分布样本,如果还是使用之前的0初始化,可能会导致0梯度,虽然训练1000次,但准确度只有0.10左右


问题1:

下面这行代码的意思是把y_和y的第二维的元素对应相乘,因为y是xW=[n,784]x[784,10]=[n,10]即nx10的矩阵(2维的tensor),reduction_indices=[1],就是取第1维对应相乘(reduction_indices从0开始)

cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))
问题2:

依然还是上面那行代码,文档说它不够稳定,推荐我们使用下面的函数代替,可以提高效率

tf.nn.softmax_cross_entropy_with_logits
但是文档只说了we call softmax_cross_entropy_with_logits on tf.matmul(x, W) + b

经过测试发现下面的这行代码

cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))

可以替换成下面这行代码

# 注意reduce_mean这个函数不能省略cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=tf.matmul(x, W) + b))
对应的参数在API中是这样解释的:
labels: Each row `labels[i]` must be a valid probability distribution.(就是测试集对应的标签)
logits: Unscaled log probabilities.(z=Wx+b)

这次的测试结果为:0.9201,感觉仅仅只是速度快了点- -

参考:http://blog.csdn.net/mao_xiao_feng/article/details/53382790

问题3:

第一次对tf.argmax(y, 1)的理解不是很明白,下面贴出其API

def arg_max(input, dimension, name=None):  r"""Returns the index with the largest value across dimensions of a tensor.  Args:    input: A `Tensor`. Must be one of the following types: `float32`, `float64`, `int64`, `int32`, `uint8`, `uint16`, `int16`, `int8`, `complex64`, `complex128`, `qint8`, `quint8`, `qint32`, `half`.    dimension: A `Tensor`. Must be one of the following types: `int32`, `int64`.      int32, 0 <= dimension < rank(input).  Describes which dimension      of the input Tensor to reduce across. For vectors, use dimension = 0.    name: A name for the operation (optional).

argmax表示在tensor的特定维数上获得最大元素的下标,这里可以简单认为0表示按列取,1表示按行取,或这样理解:比如这里批次大小为100,而y和y_都是2维的tensor对应shape为[100,10],0表示在第0维即100个取最大的,这样一共有10个;同理1表示在第1维即10个数里面取最大的,这样一共100个。然后具体在看下tf.argmax(y, 1),y是一个2维tensor对应shape为[n,10],n表示训练集的大小。tf.argmax(y, 1)就是取每行中最大的数所在的位置,最后和对应的y_比较看计算的结果和label是否一样。

问题4:

对于文档中提交到的softmax激活函数和对数似然代价函数,文档给出了不错的介绍和相关的链接说明。对于simoid函数的softmax函数的不同,这篇文章介绍得非常到位:http://ufldl.stanford.edu/wiki/index.php/Softmax%E5%9B%9E%E5%BD%92


原创粉丝点击