通俗易懂!详解Softmax及求导过程、Python实现、交叉熵


前言

本文是对一篇国外的讲解Softmax的文章的翻译。


Softmax函数的输入是一个N维的向量,向量元素是任意实数,输出也是一个N维的向量,但是有如下性质:

  1. 输出向量元素取值范围是(0, 1)
  2. 对输出向量的所有元素求和时,和为1

Softmax函数是这样一个映射 S ( a ) : R N → R N S(a): \mathbb{R}^N \xrightarrow{} \mathbb{R}^N S(a):RN RN

S ( a ) : [ a 1 a 2 . . . a N ] → [ S 1 S 2 . . . S N ] S(a): \begin{bmatrix} a_1 \\ a_2 \\ ... \\ a_N\end{bmatrix} \xrightarrow{} \begin{bmatrix} S_1 \\ S_2 \\ ... \\ S_N \end{bmatrix} S(a):a1a2...aN S1S2...SN
并且对于每个元素,用的是如下公式
S j = e a j ∑ i = 1 N e a k , ∀ j ∈ 1... N S_j= \frac{e^{a_j}}{\sum_{i=1}^N e^{a_k}}, \forall_j \in 1...N Sj=i=1Neakeaj,j1...N
我们很容易看到, S j S_j Sj永远是正数(因为式中全是对 e e e求幂),并且由于在分母中包含了分子与其它正数求和,所以 0 < S j < 1 0<S_j<1 0<Sj<1

举个例子,向量[1.0, 2.0, 3.0]通过Softmax变成了[0.09, 0.24, 0.67]。元素顺序不变,并且和为1。假如是[1.0, 2.0, 5.0]通过Softmax变成了[0.02, 0.05, 0.93],同样是顺序不变,且和为1。可以注意到,0.93比另外2个数字大很多,而且在和为1的情况下,0.93已经占了绝大多数。直观地来讲,Softmax函数是“温柔”版的最大值函数,不同的是,Softmax没有直接取一个最大值,而是将所有元素变成各自占 100 % 100\% 100% 的不同比例,元素占比越大,Softmax最终的输出值就越大,当然其他元素得出的值就越小。[1]

一、概率学解释

Softmax的两个性质使得它非常适合用概率来解释,这也让Softmax在机器学习领域大有用途。在多分类任务中,我们希望给每个输入做一个标注,标注它属于每个类的概率是多大。

如果我们有N个类别,目标就是找到一个N维向量,每个元素代表这个样本是此类别的概率,这个向量元素求和是1。听起来是不是比较熟悉?

我们可以把Softmax解释成如下所示:
S j = P ( y = j ∣ a ) S_j=P(y=j|a) Sj=P(y=ja)
其中, y y y代表输出的类别,范围是 1... N 1...N 1...N a a a是一个N维向量。有一个最基础的例子就是在多分类逻辑回归中,我们会把一个输入向量 x x x和一个权重向量 w w w点积,然后这个点积被输入到Softmax中去计算概率。这种结构后面会讲到

我们可以发现,从概率学角度看,Softmax用于模型参数的最大似然估计是最优的,但是这超出了本文范围,具体可以看Deep Learning的第5章。

二、Softmax求导

1.向量微积分

在开始对Softmax进行求导之前,我们先看看如何对向量求导。

Softmax本质上是一个向量函数,输入输出都是向量,换句话说,Softmax有多个输入和多个输出,所以我们不能直接就问“Softmax的导数是什么”,我们应该这么问:

  1. 在Softmax输出的向量中,我们要计算的是哪个元素的导数值?
  2. 别忘了Softmax的输入也是向量,有多个元素,所以我们是在关于哪个变量在求偏导呢?

如果你觉得这个听起来很复杂,不要担心,向量微积分就是用来干这事的!我们要找的是这些偏导数:

  ∂ S i ∂ a j ~\\ \frac{\partial{S_i}}{\partial{a_j}}\\  ajSi

这是 第 i 个 输 出 关 于 第 j 个 输 入 求 偏 导 第i个输出关于第j个输入求偏导 ij,我们把这个记作: D j S i D_jS_i DjSi

由于Softmax是 R N → R N \mathbb{R}^N \xrightarrow{} \mathbb{R}^N RN RN的函数,如果整体求导,我们实际上求的是一个 雅 可 比 矩 阵 ( J a c o b i a n   M a t r i x ) 雅可比矩阵(Jacobian \ Matrix) Jacobian Matrix

D S = [ D 1 S 1 ⋯ D N S 1 ⋮ ⋱ ⋮ D N S 1 ⋯ D N S N ] DS= \begin{bmatrix} D_1 S_1 & \cdots & D_N S_1 & \\ \vdots & \ddots & \vdots \\ D_N S_1 & \cdots & D_N S_N \end{bmatrix} DS=D1S1DNS1DNS1DNSN

在机器学习的文章中,“梯度”常被用来代替“导数”。严格地说,“梯度”是仅针对于标量而定义的(比如机器学习中的损失函数),但对于像Softmax这样的向量函数来说,用“梯度”是不准确的,“雅可比矩阵”才是对向量函数的导数的名称,但是为了方便描述,大多数场合我也直接用“导数”来描述。

2.Softmax的导数

让我们开始计算 D j S i ( 任 意 i 和 j ) D_jS_i(任意i和j) DjSiij

D j S i = ∂ S i ∂ a j = ∂ e a j ∑ k = 1 N e a k ∂ a j \begin{aligned} D_jS_i &= \frac{\partial{S_i}}{\partial{a_j}} \\ &= \frac{\partial{ \frac{e^{a_j}}{\sum_{k=1}^N e^{a_k}}{} }}{\partial{a_j}} \end{aligned} DjSi=ajSi=ajk=1Neakeaj

我们使用一下分式函数求导公式:
对 于 f ( x ) = g ( x ) h ( x )   f ′ ( x ) = g ′ ( x ) h ( x ) − h ′ ( x ) g ( x ) h 2 ( x ) 对于f(x)=\frac{g(x)}{h(x)} \\ ~\\ f'(x)=\frac{g'(x)h(x) - h'(x)g(x)}{h^2(x)} \\ f(x)=h(x)g(x) f(x)=h2(x)g(x)h(x)h(x)g(x)

我们让 g i = e a i , h i = ∑ k = 1 N e a k g_i=e^{a_i},h_i=\sum_{k=1}^Ne^{a_k} gi=eaihi=k=1Neak ,注意无论 h i h_i hi 关于哪个 a j a_j aj 求偏导结果都是 e a j e^{a_j} ea

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
交叉熵损失函数是深度学习中常用的一个损失函数,它是用来衡量实际输出与期望输出之间的差异的。在分类问题中,如果使用softmax作为输出层的激活函数,那么就可以使用交叉熵损失函数来计算误差。因此,采用softmax交叉熵损失函数是指在使用softmax作为输出层激活函数时所使用的损失函数。 而交叉熵损失函数是一种广义的损失函数,它可以用于多种深度学习任务,不仅仅局限于分类任务。在分类问题中,我们通常使用softmax作为输出层的激活函数,从而使得交叉熵损失函数成为了常用的损失函数之一。但是,在其他任务中,我们可能需要使用其他的输出层激活函数,例如sigmoid、tanh等,这时候我们仍然可以使用交叉熵损失函数来计算误差。 下面是使用Python实现采用softmax交叉熵损失函数和交叉熵损失函数的代码: ``` import numpy as np # 采用softmax交叉熵损失函数 def softmax_cross_entropy_loss(y, y_hat): n = y.shape loss = -np.sum(y * np.log(y_hat + 1e-12)) / n return loss # 交叉熵损失函数 def cross_entropy_loss(y, y_hat): n = y.shape loss = -np.sum(y * np.log(y_hat + 1e-12) + (1 - y) * np.log(1 - y_hat + 1e-12)) / n return loss # 测试代码 y = np.array([0, 1, 0, 0]) y_hat = np.array([0.1, 0.7, 0.1, 0.1]) print("采用softmax交叉熵损失函数:", softmax_cross_entropy_loss(y, y_hat)) print("交叉熵损失函数:", cross_entropy_loss(y, y_hat)) ``` 其中,y表示实际输出,y_hat表示模型预测输出。采用softmax交叉熵损失函数只需要计算实际输出和预测输出之间的差异,而交叉熵损失函数还需要考虑实际输出和预测输出都为0或1时的情况。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值