您的位置:首页 > 其它

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))
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐