Tensorflow 1.0 第二集:交叉熵代价函数
周六还要坐班是真的困,摸鱼都困的那种困,是个困困的打工人。
二次代价函数(quadratic)
C
=
1
2
n
∑
x
∣
∣
y
(
x
)
−
a
L
(
x
)
∣
∣
2
C = \frac{1}{2n} \sum_{x} ||y(x) - a^{L}(x)||^{2}
C=2n1x∑∣∣y(x)−aL(x)∣∣2
其中
C
C
C表示代价函数,
x
x
x表示样本,
y
y
y表示实际值,
a
a
a表示输出值,
n
n
n表示样本的总数。
为简单起见,以一个样本为例作为说明,此时代价函数为
C
=
(
y
−
a
)
2
2
C = \frac{(y-a)^{2}}{2}
C=2(y−a)2
其中
a
=
σ
(
z
)
,
z
=
∑
W
j
∗
X
j
+
b
a = \sigma(z), z=\sum W_{j}*X_{j} + b
a=σ(z),z=∑Wj∗Xj+b,
σ
(
⋅
)
\sigma(\cdot)
σ(⋅)是激活函数。
用梯度下降法的话,权值
w
w
w和
b
b
b的梯度推导如下:
∂
C
∂
w
=
(
a
−
y
)
σ
′
(
z
)
x
\frac{\partial C}{\partial w} = (a-y)\sigma'(z)x
∂w∂C=(a−y)σ′(z)x
∂
C
∂
b
=
(
a
−
y
)
σ
′
(
z
)
\frac{\partial C}{\partial b} = (a-y)\sigma'(z)
∂b∂C=(a−y)σ′(z)
其中
z
z
z表示神经元的输入,
σ
\sigma
σ表示激活函数,
w
w
w和
b
b
b的梯度跟激活函数的梯度成正比,激活函数的梯度越大,
w
w
w和
b
b
b的大小调整得越快,训练收敛得就越快。
sigmoid 函数:
这里二次代价函数+sigmoid激活函数存在的问题是如果真值在1附近,那他的训练收敛速度就很慢。于是思考不改变激活函数,改变代价函数,改用
交叉熵代价函数(cross-entropy):
C
=
−
1
n
∑
x
[
y
ln
a
+
(
1
−
y
)
ln
(
1
−
a
)
]
C = -\frac{1}{n}\sum_{x}[y\ln a + (1-y)\ln (1-a)]
C=−n1x∑[ylna+(1−y)ln(1−a)]
其中
C
C
C为代价函数,
x
x
x为样本,
y
y
y为实际值,
a
a
a为输出值,
n
n
n表示样本总体。
a
=
σ
(
z
)
,
z
=
∑
W
j
∗
X
j
+
b
a=\sigma(z),\quad z=\sum W_{j}*X_{j}+b
a=σ(z),z=∑Wj∗Xj+b
σ
′
(
z
)
=
σ
(
z
)
(
1
−
σ
(
z
)
)
\sigma'(z) = \sigma(z)(1-\sigma(z))
σ′(z)=σ(z)(1−σ(z))
求偏导的过程为:
∂
C
∂
w
j
=
−
1
n
∑
x
(
y
σ
(
z
)
−
1
−
y
1
−
σ
(
z
)
)
∂
σ
∂
w
j
=
−
1
n
∑
x
(
y
σ
(
z
)
−
1
−
y
1
−
σ
(
z
)
)
σ
′
(
z
)
x
j
=
1
n
∑
x
σ
′
(
z
)
x
j
σ
(
z
)
(
1
−
σ
(
z
)
)
(
σ
(
z
)
−
y
)
=
1
n
∑
x
x
j
(
σ
(
z
)
−
y
)
\frac{\partial C}{\partial w_{j}} = -\frac{1}{n}\sum_{x}(\frac{y}{\sigma(z)} - \frac{1-y}{1-\sigma(z)})\frac{\partial \sigma}{\partial w_{j}} \\ = -\frac{1}{n}\sum_{x}(\frac{y}{\sigma(z)} - \frac{1-y}{1-\sigma(z)})\sigma'(z)x_{j} \\ = \frac{1}{n}\sum_{x}\frac{\sigma'(z)x_{j}}{\sigma(z)(1-\sigma(z))}(\sigma(z) - y) \\ = \frac{1}{n}\sum_{x} x_{j}(\sigma(z) - y)
∂wj∂C=−n1x∑(σ(z)y−1−σ(z)1−y)∂wj∂σ=−n1x∑(σ(z)y−1−σ(z)1−y)σ′(z)xj=n1x∑σ(z)(1−σ(z))σ′(z)xj(σ(z)−y)=n1x∑xj(σ(z)−y)
∂
C
∂
b
=
1
n
∑
x
(
σ
(
z
)
−
y
)
\frac{\partial C}{\partial b} = \frac{1}{n}\sum_{x}(\sigma(z) - y)
∂b∂C=n1x∑(σ(z)−y)
于是,权重和偏置值的调整与
σ
′
(
z
)
\sigma'(z)
σ′(z)无关。
如果输出神经元是线性的,那么二次代价函数就是一种合适的选择;如果输出神经元是S型函数,那么比较适合用交叉熵代价函数。
对数似然代价函数(log- likelihood cost):
对数似然函数通产作为softmax回归的代价函数,如果输出层神经元是sigmoid函数,可以采用交叉熵代价函数。
深度学习中普遍将softmax作为最后一层,此时常用的代价函数是对数似然代价函数。
对数似然代价函数与softmax的组合和交叉熵与sigmoid函数的组合非常相似。对数似然代价函数在二分类问题时可以化简为交叉熵代价函数的形式。
在上一次的基础上,把二次代价函数变成交叉熵函数的python代码:
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 = 50
# 计算一共有多少个批次
n_batch = mnist.train.num_examples // batch_size
x = tf.placeholder(tf.float32, [None, 784]) #每张图像有784个像素块 28*28的
y = tf.placeholder(tf.float32, [None, 10])
# 一个简单的神经网络
W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([1, 10]))
# L = tf.nn.tanh(tf.matmul(x, W) + b)
# W1 = tf.Variable(tf.random_normal([100, 10]))
# b1 = tf.Variable(tf.zeros([1, 10]))
prediction = tf.nn.softmax(tf.nn.tanh(tf.matmul(x, W) + b))
# loss = tf.reduce_mean(tf.square(prediction - y))
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y, logits=prediction))
train_step = tf.train.GradientDescentOptimizer(learning_rate=0.2).minimize(loss)
init = tf.global_variables_initializer()
# 求准确率
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(prediction, 1)) #布尔型列表
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) #tf.cast 把布尔型转换为浮点型
with tf.Session() as sess:
sess.run(init)
for epoch in range(30):
for batch in range(n_batch):
batch_xs, batch_ys = mnist.train.next_batch(batch_size)
sess.run(train_step, feed_dict={x: batch_xs, y: batch_ys})
acc = sess.run(accuracy, feed_dict={x: mnist.test.images, y: mnist.test.labels})
print("Iter: " + str(epoch) + ", Testing Accuracy:" + str(acc))