博主使用库版本:
- python == 3.6
- tensorflow == 2.0
在搭建完模型结构后,下一步就是选择合适的误差函数来计算误差。 常见的误差函数有均方差、 交叉熵、 KL 散度、 Hinge Loss 函数等,其中均方差函数和交叉熵函数在深度学习中比较常见,均方差函数主要用于回归问题,交叉熵函数主要用于分类问题
均方差误差函数
均方差(Mean Squared Error,简称 MSE)误差函数把输出向量和真实向量映射到笛卡尔坐标系的两个点上,通过计算这两个点之间的欧式距离(准确地说是欧式距离的平方)来衡量两个向量之间的距离:
M
S
E
(
y
,
o
)
=
1
d
o
u
t
∑
i
=
1
d
o
u
t
(
y
i
−
o
i
)
2
MSE(y, o) = \frac{1}{d_{out}}\sum_{i=1}^{d_{out}}(y_{i}-o_{i})^{2}
MSE(y,o)=dout1i=1∑dout(yi−oi)2
MSE 误差函数的值总是大于等于 0,当 MSE 函数达到最小值 0 时, 输出等于真实标签,此时神经网络的参数达到最优状态。均方差误差函数广泛应用在回归问题中, 实际上, 分类问题中也可以应用均方差误差函数。
第一种实现方式
tensorflow代码实现如下:
o = tf.random.normal([2,10]) # 构造网络输出
y_onehot = tf.constant([1,3]) # 构造真实值
y_onehot = tf.one_hot(y_onehot, depth=10)
loss = keras.losses.MSE(y_onehot, o) # 计算均方差
loss
输出
<tf.Tensor: id=72, shape=(2,), dtype=float32, numpy=array([1.4416579, 1.633992 ], dtype=float32)>
特别要注意的是, MSE 函数返回的是每个样本的均方差,需要在样本维度上再次平均来获得平均样本的均方差,实现如下:
loss = tf.reduce_mean(loss) # 计算 batch 均方差
loss
输出
<tf.Tensor: id=74, shape=(), dtype=float32, numpy=1.5378249>
第二种实现方式
通过层方式实现:
loss = keras.losses.MeanSquaredError()(y_onehot,o) # 计算 batch 均方差
loss
输出
<tf.Tensor: id=95, shape=(), dtype=float32, numpy=1.5378249>
两种实现结果相同,计算得到的均方误差为1.5378249
交叉熵误差函数
熵在信息学科中也叫信息熵,或者香农熵。 熵越大,代表不确定性越大,信息量也就越大。 某个
分布𝑃(𝑖)的熵定义为
H
(
p
)
=
−
∑
i
p
(
i
)
log
2
p
(
i
)
H(p) = - \sum_{i} p(i) \log_{2} p(i)
H(p)=−i∑p(i)log2p(i)
交叉熵(Cross Entropy)的定义:
H
(
p
∣
q
)
=
−
∑
i
p
(
i
)
l
o
g
2
q
(
i
)
H(p|q) = - \sum_{i} p(i) log_{2}q(i)
H(p∣q)=−i∑p(i)log2q(i)
代码实现
基础计算
import tensorflow as tf
import numpy as np
#logits代表wx+b的输出,并没有进行softmax(因为softmax后是一个和为1的概率)
logits = np.array([[1, 2, 7], [3, 5, 2], [6, 1, 3], [8, 2, 0],
[3, 6, 1]], dtype=np.float32)
#labels是[2,1,0,0,1]的ont-hot编码形式
labels = np.array([[0, 0, 1], [0, 1, 0], [1, 0, 0], [1, 0, 0],
[0, 1, 0]], dtype=np.float32)
# 公式计算,-np.log(y*softmax_out)
# y=n*c,softmax_out是n*c,相当于将每个样本softmax的c个特征中最大的取出来,再取负就是求最小
softmax_out=tf.nn.softmax(logits)
cross_entropy1 = -tf.reduce_sum(labels * tf.math.log(softmax_out), axis=1) #对应元素相乘,非矩阵乘法
print(softmax_out.numpy())
print(cross_entropy1.numpy())
输出
[[2.4561151e-03 6.6764127e-03 9.9086750e-01]
[1.1419519e-01 8.4379470e-01 4.2010065e-02]
[9.4649917e-01 6.3774614e-03 4.7123417e-02]
[9.9719369e-01 2.4717962e-03 3.3452120e-04]
[4.7123417e-02 9.4649917e-01 6.3774614e-03]]
[0.00917446 0.16984606 0.05498519 0.00281025 0.05498519]
tf.nn.softmax_cross_entropy_with_logits 实现
import tensorflow as tf
import numpy as np
logits = [[4.0, 2.0, 1.0], [0.0, 5.0, 1.0]]
labels = [[1.0, 0.0, 0.0], [0.0, 0.8, 0.2]]
loss = tf.nn.softmax_cross_entropy_with_logits(labels=labels, logits=logits)
print(loss.numpy())
输出
[0.16984604 0.82474494]
TensorFlow针对分类问题,实现了四个交叉熵函数,分别是
tf.nn.sigmoid_cross_entropy_with_logits、
tf.nn.softmax_cross_entropy_with_logits、
tf.nn.sparse_softmax_cross_entropy_with_logits、
tf.nn.weighted_cross_entropy_with_logits
详细内容参考API文档,这里不过多举例:
https://www.tensorflow.org/versions/master/api_docs/python/nn.html#sparse_softmax_cross_entropy_with_logits
参考文献: