Tensorflow学习笔记:基础篇(5)——Mnist手写集改进版(交叉熵代价函数)
2018-01-03 21:45
459 查看
Tensorflow学习笔记:基础篇(5)——Mnist手写集改进版(交叉熵代价函数)
前序
— 前文中,我们的改进版本实现了一个三层(不包括输入层)全连接神经网络来完成MNIST数据的分类问题,输入层784个神经元,隐藏层500和300个神经元,输出层10个神经元,最终迭代计算20次,准确率接近0.96,本文我们在此基础上继续修改,将方差代价函数(二次代价函数)替换成交叉熵函数,看看有什么效果~~Reference:
前文博客:Mnist手写集改进版
交叉熵代价函数
方差代价函数&交叉熵代价函数
C 表示代价函数,为简单起见,以一个样本为例进行说明,此时二次代价函数为:其中,y是我们期望的输出,a为神经元的实际输出:a=σ(z),z=wx+b
假如我们使用梯度下降法(Gradient descent)来调整权值参数的大小,权值w和偏置b的梯度推导如下:
其中,z表示神经元的输入,σ表示激活函数。w和b的梯度跟激活函数的梯度成正比,激活函数的梯度越大,w和b的大小调整得越快,训练收敛得就越快。
假设我们的激活函数是sigmoid函数:
因为sigmoid函数的性质,导致σ′(z)在z取大部分值时会很小(如上图标出来的B点,几近于平坦),这样会使得w和b更新非常慢(因为σ′(z)这一项接近于0)。
为了克服这个缺点,换一个思路,我们不改变激活函数,而是改变代价函数,改用交叉熵代价函数:
其中,y为期望的输出,a为神经元实际输出:a=σ(z), z=∑Wj*Xj+b
同样,权值w和偏置b的梯度推导如下:
从上式中可看出w、b的调整与σ′(z)无关,σ(z)-y 表示输出值与实际值的误差,当其误差越大时,梯度越大,w、b调整的越快,训练速度也越快,反之,则亦然,符合预期。
特别说明一点:交叉熵函数通常与s型函数(sigmoid函数与tanh函数)组合使用。
代码示例
1、数据准备
import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data # 载入数据集 mnist = input_data.read_data_sets("MNIST_data", one_hot=True) # 每个批次送100张图片 batch_size = 100 # 计算一共有多少个批次 n_batch = mnist.train.num_examples // batch_size
2、准备好placeholder
x = tf.placeholder(tf.float32, [None, 784]) y = tf.placeholder(tf.float32, [None, 10])
3、初始化参数/权重
W1 = tf.Variable(tf.truncated_normal([784, 500], stddev=0.1), name='W1') b1 = tf.Variable(tf.zeros([500]) + 0.1, name='b1') L1 = tf.nn.tanh(tf.matmul(x, W1) + b1, name='L1') W2 = tf.Variable(tf.truncated_normal([500, 300], stddev=0.1), name='W2') b2 = tf.Variable(tf.zeros([300]) + 0.1, name='b2') L2 = tf.nn.tanh(tf.matmul(L1, W2) + b2, name='L2') W3 = tf.Variable(tf.truncated_normal([300, 10], stddev=0.1), name='W3') b3 = tf.Variable(tf.zeros([10]) + 0.1, name='b3')
4、计算预测结果
prediction = tf.nn.softmax(tf.matmul(L2, W3) + b3)
5、计算损失值
这里我们使用交叉熵函数替代二次代价函数# 二次代价函数 # loss = tf.reduce_mean(tf.square(y - prediction)) # 交叉熵代价函数 loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y, logits=prediction))
6、初始化optimizer
learning_rate = 0.2 optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss) # 结果存放在一个布尔型列表中 correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(prediction, 1)) # 求准确率 accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
7、指定迭代次数,并在session执行graph
init = tf.global_variables_initializer() with tf.Session() as sess: sess.run(init) for epoch in range(21): for batch in range(n_batch): batch_xs, batch_ys = mnist.train< 4000 /span>.next_batch(batch_size) sess.run(optimizer, feed_dict={x: batch_xs, y: batch_ys}) test_acc = sess.run(accuracy, feed_dict={x: mnist.test.images, y: mnist.test.labels}) if epoch % 2 == 0: print("Iter" + str(epoch) + ", Testing accuracy:" + str(test_acc))
运行结果
迭代计算20次,准确率已经上升到了0.97以上,如果想要准确率达到0.98以上,我们该如何继续修改呢~~~请读者思考并尝试,完整代码
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data", one_hot=True)
# 每个批次的大小
batch_size = 100
# 计算一共有多少个批次
n_batch = mnist.train.num_examples // batch_size
x = tf.placeholder(tf.float32, [None, 784], name='x_input')
y = tf.placeholder(tf.float32, [None, 10], name='y_input')
W1 = tf.Variable(tf.truncated_normal([784, 500], stddev=0.1), name='W1') b1 = tf.Variable(tf.zeros([500]) + 0.1, name='b1') L1 = tf.nn.tanh(tf.matmul(x, W1) + b1, name='L1') W2 = tf.Variable(tf.truncated_normal([500, 300], stddev=0.1), name='W2') b2 = tf.Variable(tf.zeros([300]) + 0.1, name='b2') L2 = tf.nn.tanh(tf.matmul(L1, W2) + b2, name='L2') W3 = tf.Variable(tf.truncated_normal([300, 10], stddev=0.1), name='W3') b3 = tf.Variable(tf.zeros([10]) + 0.1, name='b3')
prediction = tf.nn.softmax(tf.matmul(L2, W3) + b3)
# 二次代价函数 # loss = tf.reduce_mean(tf.square(y - prediction)) # 交叉熵代价函数 loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y, logits=prediction))
# 梯度下降
optimizer = tf.train.GradientDescentOptimizer(0.2).minimize(loss)
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(prediction, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
for epoch in range(21):
for batch in range(n_batch):
batch_xs, batch_ys = mnist.train.next_batch(batch_size)
sess.run(optimizer, feed_dict={x: batch_xs, y: batch_ys})
test_acc = sess.run(accuracy, feed_dict={x: mnist.test.images, y: mnist.test.labels})
if epoch % 2 == 0:
print("Iter" + str(epoch) + ", Testing accuracy:" + str(test_acc))
相关文章推荐
- Tensorflow学习笔记:基础篇(7)——Mnist手写集改进版(Tensorboard可视化)
- Tensorflow学习笔记:基础篇(6)——Mnist手写集改进版(Optimizer与Tensorboard)
- Tensorflow学习笔记:基础篇(3)——Mnist手写集初始版本
- Tensorflow学习笔记:基础篇(8)——Mnist手写集改进版(过拟合与Dropout)
- Tensorflow学习笔记:基础篇(4)——Mnist手写集改进版(添加隐藏层)
- tensorflow 学习笔记7 普通神经网络实现mnist手写识别
- 学习笔记(五)Tensorflow实现Soft Regression简单识别MNIST手写数字
- tensorflow 学习笔记9 卷积神经网络(CNN)实现mnist手写识别
- 零基础深度学习笔记6——Keras-CNN-MNIST 手写数字辨识资料集
- tensorflow 学习笔记12 循环神经网络RNN LSTM结构实现MNIST手写识别
- [TensorFlow]入门学习笔记(2)-卷积神经网络mnist手写识别
- Tensorflow学习笔记:基础篇(9)——Mnist手写集完结版(Embedding Visualization)
- caffe学习笔记4-- 手写数字mnist训练过程
- 【深度学习】Tensorflow学习笔记--MNIST
- TensorFlow官方教程学习笔记之3-用于机器学习专家学习的MNIST数据集(MNIST For ML Beginners)
- TensorFlow学习---实现mnist手写数字识别
- TensorFlow官方教程学习笔记(三)——MNIST入门(续)
- tensorflow学习笔记之使用tensorflow进行MNIST分类(1)
- tensorflow 学习笔记(四) - mnist实例--用简单的神经网络来训练和测试
- TensorFlow学习笔记之源码分析(2)----手写数字识别mnist example