神经网络学习中的SoftMax与交叉熵
简 介: 对于在深度学习中的两个常见的函数SoftMax,交叉熵进行的探讨。在利用paddle平台中的反向求微分进行验证的过程中,发现结果 与数学定义有差别。具体原因还需要之后进行查找。
关键词
: 交叉熵,SoftMax
Contents
在深度学习网络中,SoftMax 以及Cross Entropy(交叉熵)是最常见到神经网络输出级的数据处理以及计算损失函数。
§01 定 义
1.1 函数
SoftMax函数往往使用在分类神经网络的最后一层的处理中,它将分类神经网络的输出转换成网络对于输入样本所属类别的概率。
1.1.1 类别概率
如果神经网络N(φ;X)N\left( {\varphi ;X} \right)N(φ;X)在输入样品xix_ixi的作用下,输出输出向量为[z1,z2,⋯,zM]\left[ {z_1 ,z_2 , \cdots ,z_M } \right][z1,z2,⋯,zM]。分别表示该样本属于 1 ~ M 个类别的概率。但属于概率必须满足:
- zi≥0,i=1,2,⋯,Mz_i \ge 0,\,\,i = 1,2, \cdots ,Mzi≥0,i=1,2,⋯,M
- ∑i=1Mzi=1\sum\limits_{i = 1}^M {z_i } = 1i=1∑Mzi=1
为了达到概率条件,需要进行处理。SoftMax处理方式是其中一种。
▲ 图1.1.1 神经网络输入输出示意图
1.1.2 SoftMax
在 详解softmax函数以及相关求导过程 中,给出了SoftMax的定义:
yi=ezi∑i=1Meziy_i = {{e^{z_i } } \over {\sum\limits_{i = 1}^M {e^{z_i } } }}yi=i=1∑Meziezi
数据计算过程中的流程图参见下图:
▲ 图1.1.2 SoftMax结构示意图
可以看到输出的yi,i=1,2,⋯,My_i ,i = 1,2, \cdots ,Myi,i=1,2,⋯,M满足:
- yi≥0,i=1,2,⋯,My_i \ge 0,\,\,i = 1,2, \cdots ,Myi≥0,i=1,2,⋯,M
- ∑i=1Myi=1\sum\limits_{i = 1}^M {y_i } = 1i=1∑Myi=1
(1)举例
a = [0.1,0.2,0.3,-1,5]
b = sum([exp(aa) for aa in a])
c = [exp(aa)/b for aa in a]
print("a: {}".format(a), "b: {:0.2f}".format(b), "c: {}".format(c))
a: [0.1, 0.2, 0.3, -1, 5]
b: 152.46
c: [0.007249044016189045, 0.008011432630542426, 0.008854002355397775, 0.0024129971374439265, 0.9734725238604267]
1.2 交叉熵
根据 一文搞懂熵(Entropy),交叉熵(Cross-Entropy)中的定义,对于一组样本所出现的概率分布:pi,i=1,2,⋯,Mp_i ,\,\,i = 1,2, \cdots ,Mpi,i=1,2,⋯,M,所对应的信息熵为:
Eentropy(P)=E(P)=−∑i=1Mpilog(pi)E_{entropy} \left( P \right) = E\left( P \right) = - \sum\limits_{i = 1}^M {p_i \log \left( {p_i } \right)}Eentropy(P)=E(P)=−i=1∑Mpilog(pi)
1.2.1 交叉熵定义
如果有两个相同长度的概率分布:P={p1,p2,⋯,pM}P = \left\{ {p_1 ,p_2 , \cdots ,p_M } \right\}P={p1,p2,⋯,pM}Q={q1,q2,⋯,qM}Q = \left\{ {q_1 ,q_2 , \cdots ,q_M } \right\}Q={q1,q2,⋯,qM}。他们两者之间的交叉熵有两种定义:
在神经网络应用中,P,Q两个概率通常情况下:一个是网络输出SoftMax对应的样本类别概率;另外一个是样本期望类别概率。
从上面定义来看,对于两个概率分布,这两个交叉熵的取值是不同的,除非两个概率分布是相同的,或者相差一个系数。
1.2.2 举例
比如对于MNIST分类问题,期望值为:
P: [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
网络输出为:
Q: [0.29213776 0.03122202 0.03394387 0.01968607 0.13676823 0.005762330.32953807 0.02688782 0.07919548 0.04485835]
H(P,Q)H\left( {P,Q} \right)H(P,Q)对应的交叉熵为:
H(P,Q)=−∑i=09p(i)⋅log[q(i)]=−log(0.03394)=3.383H\left( {P,Q} \right) = - \sum\limits_{i = 0}^9 {p\left( i \right) \cdot \log \left[ {q\left( i \right)} \right] = - \log \left( {0.03394} \right) = 3.383}H(P,Q)=−i=0∑9p(i)⋅log[q(i)]=−log(0.03394)=3.383
从这里可以看到,由于 log 函数要求输入 x 必须是大于0,所以在计算上面的交叉熵的时候,往往使用 H(Q,P)H\left( {Q,P} \right)H(Q,P)的定义,而不是反过来。
这个交叉熵只是反应了网络输出中,对应样本正确类别的神经元输出距离“1”还相差多少,至于其他网络输出对于交叉熵是没有影响的。
§02 求 导
通常情况下,对于用于分类神经网络的最后一层的输出往往采用线性传递函数,再加上SoftMax,通过交叉熵计算损失函数Loss。在进行损失函数反向传播的过程中,需要计算反向传播的梯度方向。
▲ 图2.2 网络输出对应的交叉熵
Loss(zi,ti)=−∑i=Mtilog(ezi∑j=MMezj)Loss\left( {z_i ,t_i } \right) = - \sum\limits_{i = }^M {t_i \log \left( {{{e^{z_i } } \over {\sum\limits_{j = M}^M {e^{z_j } } }}} \right)}Loss(zi,ti)=−i=∑Mtilog⎝⎜⎜⎜⎛j=M∑Mezjezi⎠⎟⎟⎟⎞
2.1 梯度求解
为了方便梯度求解,假设样本属于第 c 个种类,也就是:tC=1,tm=0,m≠ct_C = 1,\,\,t_m = 0,m \ne ctC=1,tm=0,m=c。那么此时交叉熵为:
Loss(zi,ti)=−logezc∑j=1Mezj=log(∑j=1Mezj)−zcLoss\left( {z_i ,t_i } \right) = - \log {{e^{z_c } } \over {\sum\limits_{j = 1}^M {e^{z_j } } }} = \log \left( {\sum\limits_{j = 1}^M {e^{z_j } } } \right) - z_cLoss(zi,ti)=−logj=1∑Mezjezc=log(j=1∑Mezj)−zc
求此时损失函数 LossLossLoss对于网络输出ziz_izi 的梯度下降方向:
−∂Loss∂zi=dzcdzi−1∑j=1Mezj⋅ezi=dzcdzi−yi- {{\partial Loss} \over {\partial z_i }} = {{dz_c } \over {dz_i }} - {1 \over {\sum\limits_{j = 1}^M {e^{z_j } } }} \cdot e^{z_i } = {{dz_c } \over {dz_i }} - y_i−∂zi∂Loss=dzidzc−j=1∑Mezj1⋅ezi=dzidzc−yi
情况分为两种:
第一种情况: i=ci = ci=c
−∂Loss∂zc=1−yc-{{\partial Loss} \over {\partial z_c }} = 1 - y_c−∂zc∂Loss=1−yc
第二种情况: i≠ci \ne ci=c
−∂Loss∂zi=−yi-{{\partial Loss} \over {\partial z_i }} = - y_i−∂zi∂Loss=−yi
2.2 对比MSE
如果损失函数使用MSE,即:
Loss=1M∑i=1M(ti−zi)2Loss = {1 \over M}\sum\limits_{i = 1}^M {\left( {t_i - z_i } \right)^2 }Loss=M1i=1∑M(ti−zi)2
那么它针对于所有输出的负梯度方向:
−∂Loss∂zi=(ti−zi)M- {{\partial Loss} \over {\partial z_i }} = {{\left( {t_i - z_i } \right)} \over M}−∂zi∂Loss=M(ti−zi)
对比前面对于SoftMax以及交叉熵求解来看,除了相差一个常量系数 1/M1/M1/M之外,梯度的方向是相同的。
▲ 图2.2.1 交叉熵在分类问题
2.3 对比Sigmoid
如果网络最后一层传递函数采用Sigmoid函数:
f(x)=11+e−xf\left( x \right) = {1 \over {1 + e^{ - x} }}f(x)=1+e−x1
Sigmoid函数曲线:
▲ 图2.3.1 Sigmoid函数曲线
x = linspace(-10, 10, 200)
smt = 1/(1+exp(-x))plt.figure(figsize=(10,5))
plt.plot(t, smt)
plt.xlabel("x")
plt.ylabel("sigmoid(x)")
plt.grid(True)
plt.title("Sigmoid Active Function")
plt.tight_layout()
plt.show()
这个函数虽然不能够保证网络的输出zi,i=1,2,⋯,Mz_i ,i = 1,2, \cdots ,Mzi,i=1,2,⋯,M满足概率分布归一化要求,但可以保证输出值zi>0,i=1,2,⋯,Mz_i > 0,\,\,i = 1,2, \cdots ,Mzi>0,i=1,2,⋯,M。这种情况也称为 logistic回归。
▲ 图2.3.2 最后一级采用Sigmoid函数输出
如果在此基础上仍然利用交叉熵作为损失函数,那么交叉熵对于zi,i=1,2,⋯,Mz_i ,i = 1,2, \cdots ,Mzi,i=1,2,⋯,M的负梯度为:
−∂Loss∂zi=−∑i=1Mtilog(11+e−zi)- {{\partial Loss} \over {\partial z_i }} = - \sum\limits_{i = 1}^M {t_i \log \left( {{1 \over {1 + e^{ - z_i } }}} \right)}−∂zi∂Loss=−i=1∑Mtilog(1+e−zi1)
同样,假设当前样本对应第ccc类,也就是:tc=1,ti=0,i≠ct_c = 1,\,\,t_i = 0,\,i \ne ctc=1,ti=0,i=c。
第一种情况: i=ci = ci=c
−∂Loss∂zc=∂∂zclog(1+e−zi)=−e−zc1+e−zc=(1−yc)- {{\partial Loss} \over {\partial z_c }} = {\partial \over {\partial z_c }}\log \left( {1 + e^{ - z_i } } \right) = {{ - e^{ - z_c } } \over {1 + e^{ - z_c } }} = \left( {1 - y_c } \right)−∂zc∂Loss=∂zc∂log(1+e−zi)=1+e−zc−e−zc=(1−yc)
第二种情况: i≠ci \ne ci=c
−∂Loss∂zi=0- {{\partial Loss} \over {\partial z_i }} = 0−∂zi∂Loss=0
通过上面对比,可以看到使用Sigmoid函数作为网络的最后一级输出的传递函数,然后使用交叉熵来作为损失函数的时候存在的问题:
- 它只对于该样本对应的类别所属的神经元反向有梯度,对于其它输出神经元反向没有梯度;
- 当神经元输出接近于1的时候,反向梯度数值会下降;
上面会使得网络在收敛的时候速度变慢。
§03 实验验证
3.1 对比SoftMax与MSE
根据前面推导,可以看到在网络输出传递函数为线性函数的时候,通过SoftMax以及交叉熵对应的损失函数,与MSE对应的损失函数所对网络输出节点的损失函数负梯度数值是一样的。下面在paddle平台下,测试一下这方面的内容。
3.1.1 建立softmax网络
搭建一个仅仅由softmax组成的网络。
class netmodel(paddle.nn.Layer):def __init__(self, ):super(netmodel, self).__init__()def forward(self, x):x = paddle.nn.functional.softmax(x)return x
3.1.2 求解SoftMax梯度
(1)求SoftMax输出
Ⅰ.使用net求解SoftMax输出
定义一个向量z,代表网络的实际输出。然后经过上面定义的SoftMax,获得实际输出y。
net = netmodel()
z = TT(array([0,0.1,-2,3])[newaxis,:], dtype='float64')
z.stop_gradient = False
y = paddle.nn.functional.softmax(z)
print("z: {}".format(z), "y: {}".format(y))
z: Tensor(shape=[1, 4], dtype=float64, place=CPUPlace, stop_gradient=False,[[ 0. , 0.10000000, -2. , 3. ]])
y: Tensor(shape=[1, 4], dtype=float64, place=CPUPlace, stop_gradient=False,[[0.04479074, 0.04950142, 0.00606177, 0.89964607]])
Ⅱ.使用numpy求SoftMax
通过Numpy函数计算SoftMax,对比paddle中的 SoftMax函数数值:
zz = z.numpy()
yy = exp(zz)/sum(exp(zz))
print("zz: {}".format(zz), "yy: {}".format(yy))
zz: [[ 0. 0.1 -2. 3. ]]
yy: [[0.04479074 0.04950142 0.00606177 0.89964607]]
对比一下,上面的数值是一样的。
(2)反向梯度计算
上面利用paddle中的loss求解机制,自动完成对z的梯度求解。
net = netmodel()
optimizer = paddle.optimizer.SGD(learning_rate=0.1, parameters=net.parameters())z = TT(array([0,0.1,-2,3])[newaxis,:], dtype='float64')
z.stop_gradient = False
y = paddle.nn.functional.softmax(z)t = TT(array([[1]]))
loss = paddle.nn.functional.cross_entropy(y, t)
loss.backward()print("loss.numpy(): {}".format(loss.numpy()), "y: {}".format(y), "y.grad: {}".format(y.grad), "z.grad: {}".format(z.grad))
loss.numpy(): [1.66634288]
y: Tensor(shape=[1, 4], dtype=float64, place=CPUPlace, stop_gradient=False,[[0.04479074, 0.04950142, 0.00606177, 0.89964607]])
y.grad: Tensor(shape=[1, 4], dtype=float64, place=CPUPlace, stop_gradient=False,[[ 0.18804884, -0.81106323, 0.18090513, 0.44210926]])
z.grad: Tensor(shape=[1, 4], dtype=float64, place=CPUPlace, stop_gradient=False,[[-0.00802040, -0.05832138, -0.00112875, 0.06747052]])
观察 z 变量的反向梯度,下面进行验证一下。
首先,关于 Loss的计算数值,它应该等于:
Loss=−log(y1)=−log(0.0495)=3.006Loss = - \log \left( {y_1 } \right) = - \log \left( {0.0495} \right) = 3.006Loss=−log(y1)=−log(0.0495)=3.006
但上面给出的数值:
print("loss.numpy(): {}".format(loss.numpy()))
loss.numpy(): [1.66634288]
这与定义不同?那么问题出现在哪里了呢?
再检查y[1]的梯度:
print(1+log(0.0495)*y[0][1])
Tensor(shape=[1], dtype=float64, place=CPUPlace, stop_gradient=False,[0.85120948])
可以看到这与上面计算出的数值也不一样。
※ 总 结 ※
对于在深度学习中的两个常见的函数SoftMax,交叉熵进行的探讨。在利用paddle平台中的反向求微分进行验证的过程中,发现结果 与数学定义有差别。具体原因还需要之后进行查找。
■ 相关文献链接:
- 详解softmax函数以及相关求导过程
- 一文搞懂熵(Entropy),交叉熵(Cross-Entropy)
● 相关图表链接:
- 图1.1.1 神经网络输入输出示意图
- 图1.1.2 SoftMax结构示意图
- 图2.2 网络输出对应的交叉熵
- 图2.2.1 交叉熵在分类问题
- 图2.3.1 Sigmoid函数曲线
- 图2.3.2 最后一级采用Sigmoid函数输出
神经网络学习中的SoftMax与交叉熵相关推荐
- 神经网络适用于分类问题的最后一层-Softmax和交叉熵损失介绍及梯度推导
前言 传统机器学习中两大经典任务就是回归与分类.分类在深度学习中也很常见,令我印象最深的是图像分类.当然,在NLP中,分类也无处不在.从RNN与其变体,到Transformer.Bert等预训练模型, ...
- pytoch人工神经网络基础:最简单的分类(softmax回归+交叉熵分类)
softmax回归分类原理 对于回归问题,可以用模型预测值与真实值比较,用均方误差这样的损失函数表示误差,迭代使误差最小训练模型. 那么分类问题是否可以用线性回归模型预测呢.最简单的方法就是用soft ...
- 度量学习(Metric learning)—— 基于分类损失函数(softmax、交叉熵、cosface、arcface)
概述 首先,我们把loss归为两类:一类是本篇讲述的基于softmax的,一类是基于pair对的(如对比损失.三元损失等). 基于pair对的,参考我的另一篇博客: https://blog.csdn ...
- 人脸识别-Loss-2010:Softmax Loss(Softmax激活函数 + “交叉熵损失函数”)【样本3真实标签为c_5,则样本3的损失:loss_3=-log(\hat{y}_5^3)】
一般一个CNN网络主要包含卷积层,池化层(pooling),全连接层,损失层等. 全连接层:等号左边部分就是全连接层做的事, W W W 是全连接层的参数,我们也称为权值, X X X 是全连接层的输 ...
- 深度学习基础入门篇[五]:交叉熵损失函数、MSE、CTC损失适用于字识别语音等序列问题、Balanced L1 Loss适用于目标检测
[深度学习入门到进阶]必看系列,含激活函数.优化策略.损失函数.模型调优.归一化算法.卷积模型.序列模型.预训练模型.对抗神经网络等 专栏详细介绍:[深度学习入门到进阶]必看系列,含激活函数.优化策略 ...
- softmax与交叉熵损失
softmax基本形式 softmax是一个将实数域上取值的N维向量转化为[0,1]范围内的函数,常用用于分类问题中,接在神经网络最后一层,将输出值映射到概率区间上,其基本形式如下所示 pi=eai∑ ...
- 图示Softmax及交叉熵损失函数
Softmax函数 Softmax是将神经网络得到的多个值,进行归一化处理,使得到的值在之间,让结果变得可解释.即可以将结果看作是概率,某个类别概率越大,将样本归为该类别的可能性也就越高.Softma ...
- tensoflow随笔——softmax和交叉熵
softmax函数 softmax函数接收一个N维向量作为输入,然后把每一维的值转换到(0, 1)之间的一个实数.假设模型全连接网络输出为a,有C个类别,则输出为a1,a2,...,aC,对于每个样本 ...
- 动手学深度学习——softmax回归之OneHot、softmax与交叉熵
目录 一.从回归到多类分类 1. 回归估计一个连续值 2. 分类预测一个离散类别 二.独热编码OneHot 三.校验比例--激活函数softmax 四.损失函数--交叉熵 五.总结 回归可以用于预测多 ...
最新文章
- 【高性价比】AIO-3288C四核高性能主板
- Wallop下蛋送邀请。
- 解决在使用numpy.polyfit 时出现的 raise LinAlgError(“SVD did not converge in Linear Least Squares“)错误
- nacos 怎么配置 里的配置ip_Nacos-服务注册地址为内网IP的解决办法
- Azkaban安装部署,配置文件配置,启动等
- java lock代码写法_java Lock接口详解及实例代码
- 通信系统的同步技术归纳
- python 文件加密_python实现文件快照加密保护的方法
- 左移右移位运算_计算机硬件技术基础M2——计算机运算基础(二)
- Azure IoT Edge on Windows 10 IoT Core
- iOS 拼音 Swift K3Pinyin
- 生成对抗网络发展及其主要工程应用综述
- 现代控制理论6——能控、能观及其对偶原理、线性变换、结构分解
- 实现人生梦想,共同创造人生辉煌!
- 微软中国裁员计划曝光:年底前裁完!补偿不变!
- 室内定位导航系统源码php,UWB室内定位系统方案_室内精确定位DEMO搭建
- Mono及MonoDevelop安装
- 软件测试究竟发挥什么作用?
- VM15 虚拟机下载及安装CentOS7.6
- linux+scp+失败_Linux scp 命令卡住的原因
热门文章
- 【码云周刊第 68 期】数据可视化:商业智能的未来!
- Banner长得丑,网站没朋友
- 看看C# 6.0中那些语法糖都干了些什么(终结篇)
- 安卓v7支持包下的ListView替代品————RecyclerView
- 20145129 课程总结
- 新一轮光伏电站产能过剩隐忧初显
- 《CCNP ROUTE 300-101学习指南》——2.6节复习题
- Picasso fit() centerCrip() centerInside()
- nodejs使用带用户和密码的Mongo示例
- CLLocationCoordinate2D 用法 和一个最隐蔽的错误