欢迎Star我的Machine Learning Blog:https://github.com/purepisces/Wenqing-Machine_Learning_Blog

Softmax

Softmax激活函数是一种向量激活函数,主要应用于神经网络的末端,将向量或原始输出转换为概率分布,其中输出元素总和为1。但是,它也可以像前面讨论过的其他激活函数一样应用在神经网络的中间。

Softmax前向方程

给定一个 C C C维输入向量 Z Z Z,其第 m m m个元素表示为 z m z_m zm s o f t m a x . f o r w a r d ( Z ) softmax.forward(Z) softmax.forward(Z)将给出一个向量 A A A,其第 m m m个元素 a m a_m am由以下方程给出:

a m = exp ⁡ ( z m ) ∑ k = 1 C exp ⁡ ( z k ) a_m = \frac{\exp(z_m)}{\sum\limits_{k=1}^{C} \exp(z_k)} am=k=1Cexp(zk)exp(zm)

这里 Z Z Z是一个单一向量。类似的计算可以用于大小为 N N N的向量批次。

对于向量批次,输出矩阵 A A A中每个元素的公式(大小也为 N × C N \times C N×C)可以表示为:

A i j = exp ⁡ ( Z i j ) ∑ k = 1 C exp ⁡ ( Z i k ) A_{ij} = \frac{\exp(Z_{ij})}{\sum\limits_{k=1}^{C} \exp(Z_{ik})} Aij=k=1Cexp(Zik)exp(Zij)

这里, A i j A_{ij} Aij表示批次中第 i i i个输入向量对应的Softmax输出的第 j j j个元素。 Z i j Z_{ij} Zij是批次中第 i i i个向量的第 j j j个元素。分母是对第 i i i个输入向量中的所有元素求和,确保对于批次中的每个输入向量,Softmax输出的总和为1。

Softmax反向方程

如前面章节中对向量激活函数的反向方法的描述所讨论的,反向传播导数的第一步是为批次中的每个向量计算Jacobian矩阵。让我们以输入向量 Z Z Z(输入数据矩阵的一行)和相应输出向量 A A A(通过softmax.forward计算得到的输出矩阵的一行)为例。Jacobian矩阵 J J J是一个 C × C C \times C C×C矩阵。其第 m m m行第 n n n列的元素由以下公式给出:

J m n = { a m ( 1 − a m ) 如果 m = n − a m a n 如果 m ≠ n J_{mn} = \begin{cases} a_m(1 - a_m) & \text{如果} m = n \\ -a_m a_n & \text{如果} m \neq n \end{cases} Jmn={am(1am)aman如果m=n如果m=n

这里 a m a_m am指的是向量 A A A的第 m m m个元素。

现在,相对于该输入向量的损失的导数,即 d L d Z dLdZ dLdZ是一个 1 × C 1 \times C 1×C向量,计算如下:

d L d Z = d L d A ⋅ J \frac{dL}{dZ} = \frac{dL}{dA} \cdot J dZdL=dAdLJ

类似的导数计算可以应用于批次中的所有 N N N个向量,并将结果向量垂直堆叠以得到最终的 N × C N \times C N×C导数矩阵。

注意: J m n J_{mn} Jmn表示Softmax函数的Jacobian矩阵的元素,对应于第 m m m个输出 a m a_m am相对于第 n n n个输入 z n z_n zn的偏导数。Jacobian矩阵 J J J由这些偏导数组成,捕捉每个输入维度 z n z_n zn如何影响每个输出维度 a m a_m am J J J的元素定义如下:
J m n = ∂ a m ∂ z n J_{mn} = \frac{\partial a_m}{\partial z_n} Jmn=znam
对于Softmax函数,这个微分有两种形式,取决于是否 m = n m = n m=n m ≠ n m \neq n m=n

m = n m=n m=n时: J m n = ∂ a m ∂ z m = a m ( 1 − a m ) J_{mn} = \frac{\partial a_m}{\partial z_m} = a_m (1 - a_m) Jmn=zmam=am(1am)

m ≠ n m \neq n m=n时: J m n = ∂ a m ∂ z n = − a m a n J_{mn} = \frac{\partial a_m}{\partial z_n} = -a_m a_n Jmn=znam=aman

class Softmax:
    """
    On same lines as above:
    Define 'forward' function
    Define 'backward' function
    Read the writeup for further details on Softmax.
    """

    def forward(self, Z):
        """
        Remember that Softmax does not act element-wise.
        It will use an entire row of Z to compute an output element.
        """
        exp_z = np.exp(Z)
        self.A = exp_z / np.sum(exp_z, axis=1, keepdims=True)
        return self.A

    def backward(self, dLdA):

        # Calculate the batch size and number of features
        N, C = dLdA.shape

        # Initialize the final output dLdZ with all zeros. Refer to the writeup and think about the shape.
        dLdZ = np.zeros_like(dLdA)

        # Fill dLdZ one data point (row) at a time
        for i in range(N):

            # Initialize the Jacobian with all zeros.
            J = np.zeros((C, C))

            # Fill the Jacobian matrix according to the conditions described in the writeup
            for m in range(C):
                for n in range(C):
                    if m == n:
                        J[m, n] = self.A[i, m] * (1 - self.A[i, m])
                    else:
                        J[m, n] = -self.A[i, m] * self.A[i, n]

            # Calculate the derivative of the loss with respect to the i-th input
            dLdZ[i, :] = np.dot(dLdA[i, :], J)

        return dLdZ

在神经网络中使用Softmax激活函数的示例

考虑一个神经网络层,其中批次中有2个样本( N = 2 N=2 N=2),每个样本有3个特征( C = 3 C=3 C=3)。这个设置可以代表分类问题中3个类别的logits。

我们的输入向量批次 Z Z Z给定如下:

Z = ( Z ( 1 ) Z ( 2 ) ) = ( 1 2 3 2 2 1 ) Z = \begin{pmatrix} Z^{(1)} & Z^{(2)} \end{pmatrix} = \begin{pmatrix} 1 & 2 & 3 \\ 2 & 2 & 1 \end{pmatrix} Z=(Z(1)Z(2))=(122231)

应用Softmax激活

Softmax被应用于每个样本 Z ( i ) Z^{(i)} Z(i),以产生输出向量 A ( i ) A^{(i)} A(i)。向量 Z ( i ) Z^{(i)} Z(i)中的元素 z j z_j zj的Softmax函数定义如下:

Softmax ( z j ) = e z j ∑ k = 1 C e z k \text{Softmax}(z_j) = \frac{e^{z_j}}{\sum\limits_{k=1}^{C} e^{z_k}} Softmax(zj)=k=1Cezkezj

应用Softmax到 Z Z Z的每一行后,我们得到:

A = ( A ( 1 ) A ( 2 ) ) = ( 0.09 0.24 0.67 0.42 0.42 0.16 ) A = \begin{pmatrix} A^{(1)} & A^{(2)} \end{pmatrix} = \begin{pmatrix} 0.09 & 0.24 & 0.67 \\ 0.42 & 0.42 & 0.16 \end{pmatrix} A=(A(1)A(2))=(0.090.420.240.420.670.16)

Softmax的Jacobian矩阵

对于Softmax,单个样本 A ( i ) A^{(i)} A(i)的Jacobian矩阵 J ( i ) J^{(i)} J(i)的元素为:

J j k ( i ) = { A j ( i ) ( 1 − A j ( i ) ) 如果 j = k − A j ( i ) A k ( i ) 否则 J^{(i)}_{jk} = \begin{cases} A^{(i)}_j (1 - A^{(i)}_j) & \text{如果} j = k \\ -A^{(i)}_j A^{(i)}_k & \text{否则} \end{cases} Jjk(i)={Aj(i)(1Aj(i))Aj(i)Ak(i)如果j=k否则

对于我们的第一个样本 A ( 1 ) A^{(1)} A(1),Jacobian矩阵 J ( 1 ) J^{(1)} J(1)是一个3x3矩阵,其中每个元素都使用上述规则计算。

计算 J ( 1 ) J^{(1)} J(1)

对于第一个样本, A ( 1 ) = [ 0.09 , 0.24 , 0.67 ] A^{(1)} = [0.09, 0.24, 0.67] A(1)=[0.09,0.24,0.67]

使用Softmax导数公式:

当   j = k : J j j ( 1 ) = A j ( 1 ) ( 1 − A j ( 1 ) ) 当 \ \ j = k: J^{(1)}_{jj} = A^{(1)}_j (1 - A^{(1)}_j)   j=k:Jjj(1)=Aj(1)(1Aj(1))

当   j ≠ k : J j k ( 1 ) = − A j ( 1 ) A k ( 1 ) 当 \ \ j \neq k: J^{(1)}_{jk} = -A^{(1)}_j A^{(1)}_k   j=k:Jjk(1)=Aj(1)Ak(1)

因此,我们有:

J 11 ( 1 ) = 0.09 × ( 1 − 0.09 ) = 0.0819 J^{(1)}_{11} = 0.09 \times (1 - 0.09) = 0.0819 J11(1)=0.09×(10.09)=0.0819

J 22 ( 1 ) = 0.24 × ( 1 − 0.24 ) = 0.1824 J^{(1)}_{22} = 0.24 \times (1 - 0.24) = 0.1824 J22(1)=0.24×(10.24)=0.1824

J 33 ( 1 ) = 0.67 × ( 1 − 0.67 ) = 0.2211 J^{(1)}_{33} = 0.67 \times (1 - 0.67) = 0.2211 J33(1)=0.67×(10.67)=0.2211

以及对于

j ≠ k j \neq k j=k

J 12 ( 1 ) = J ( 1 ) 21 = − 0.09 × 0.24 = − 0.0216 J^{(1)}_{12} = J^{(1)}{21} = -0.09 \times 0.24 = -0.0216 J12(1)=J(1)21=0.09×0.24=0.0216

J 13 ( 1 ) = J ( 1 ) 31 = − 0.09 × 0.67 = − 0.0603 J^{(1)}_{13} = J^{(1)}{31} = -0.09 \times 0.67 = -0.0603 J13(1)=J(1)31=0.09×0.67=0.0603

J 23 ( 1 ) = J ( 1 ) 32 = − 0.24 × 0.67 = − 0.1608 J^{(1)}_{23} = J^{(1)}{32} = -0.24 \times 0.67 = -0.1608 J23(1)=J(1)32=0.24×0.67=0.1608

所以, J ( 1 ) J^{(1)} J(1)

J ( 1 ) = ( 0.0819 − 0.0216 − 0.0603 − 0.0216 0.1824 − 0.1608 − 0.0603 − 0.1608 0.2211 ) J^{(1)} = \begin{pmatrix} 0.0819 &-0.0216 & -0.0603 \\ -0.0216 &0.1824 & -0.1608 \\ -0.0603 &-0.1608 &0.2211 \end{pmatrix} J(1)= 0.08190.02160.06030.02160.18240.16080.06030.16080.2211

类似地

J ( 2 ) = ( 0.2436 − 0.1764 − 0.0672 − 0.1764 0.2436 − 0.0672 − 0.0672 − 0.0672 0.1344 ) J^{(2)} = \begin{pmatrix} 0.2436 & -0.1764 & -0.0672 \\ -0.1764 & 0.2436 & -0.0672 \\ -0.0672 & -0.0672 & 0.1344 \end{pmatrix} J(2)= 0.24360.17640.06720.17640.24360.06720.06720.06720.1344

计算梯度 d L d Z ( i ) dLdZ^{(i)} dLdZ(i)
假设我们有相对于批次的激活输出 d L d A dLdA dLdA的损失梯度如下:

d L d A = ( 0.1 − 0.2 0.1 − 0.1 0.3 − 0.2 ) dLdA= \begin{pmatrix} 0.1 & -0.2 & 0.1\\ -0.1 & 0.3 & -0.2 \end{pmatrix} dLdA=(0.10.10.20.30.10.2)

每个样本的梯度 d L d Z ( i ) dLdZ^{(i)} dLdZ(i)通过将相应的 d L d A dLdA dLdA的行与 J ( i ) J^{(i)} J(i)相乘来计算:

d L d Z ( i ) = d L d A ( i ) ⋅ J ( i ) dLdZ^{(i)} =dLdA^{(i)} \cdot J^{(i)} dLdZ(i)=dLdA(i)J(i)

这个操作将对每个样本执行,并将得到的向量 d L d Z ( 1 ) dLdZ^{(1)} dLdZ(1) d L d Z ( 2 ) dLdZ^{(2)} dLdZ(2)垂直堆叠以形成整个批次的最终梯度矩阵 d L d Z dLdZ dLdZ

具体计算

由于Softmax导数的复杂性,为简洁起见,这里省略了对 J ( 1 ) J^{(1)} J(1) J ( 2 ) J^{(2)} J(2)每个元素的详细计算。然而,一般的过程涉及:

使用 A ( 1 ) A^{(1)} A(1) A ( 2 ) A^{(2)} A(2)计算 J ( 1 ) J^{(1)} J(1) J ( 2 ) J^{(2)} J(2)

d L d A ( 1 ) = [ 0.1 , − 0.2 , 0.1 ] dLdA^{(1)} = [0.1, -0.2, 0.1] dLdA(1)=[0.1,0.2,0.1]乘以 J ( 1 ) J^{(1)} J(1)以得到 d L d Z ( 1 ) dLdZ^{(1)} dLdZ(1)

d L d A ( 2 ) = [ − 0.1 , 0.3 , − 0.2 ] dLdA^{(2)} = [-0.1, 0.3, -0.2] dLdA(2)=[0.1,0.3,0.2]乘以 J ( 2 ) J^{(2)} J(2)以得到 d L d Z ( 2 ) dLdZ^{(2)} dLdZ(2)

垂直堆叠 d L d Z ( 1 ) dLdZ^{(1)} dLdZ(1) d L d Z ( 2 ) dLdZ^{(2)} dLdZ(2)以形成 d L d Z dLdZ dLdZ

这个例子说明了使用向量激活函数计算层输入的损失梯度的过程,其中输入在产生输出时的相互依赖性要求为每个样本计算完整的Jacobian矩阵。

注意:在反向传播中使用 d L d Z dLdZ dLdZ,因为它直接将损失与我们想要优化的参数(权重和偏置)通过 Z Z Z联系起来,因为 Z = W ⋅ A p r e v + b Z = W \cdot A_{prev} + b Z=WAprev+b,接着是 A = f ( Z ) A = f(Z) A=f(Z),其中 f f f是激活函数。
对于标量激活, d L d Z dLdZ dLdZ的计算如下:
d L d Z = d L d A ⊙ ∂ A ∂ Z dLdZ = dLdA \odot \frac{\partial A}{\partial Z} dLdZ=dLdAZA
对于向量激活函数, d L d Z dLdZ dLdZ的计算如下:对于大小为 1 × C 1 \times C 1×C的每个输入向量 Z ( i ) Z^{(i)} Z(i)及其对应的输出向量 A ( i ) A^{(i)} A(i)(也是批次中的 1 × C 1 \times C 1×C),必须分别计算Jacobian矩阵 J ( i ) J^{(i)} J(i)。该矩阵具有维度 C × C C \times C C×C。因此,批次中每个样本的梯度 d L d Z ( i ) dLdZ^{(i)} dLdZ(i)由以下方式确定:
d L d Z ( i ) = d L d A ( i ) ⋅ J ( i ) dLdZ^{(i)} = dLdA^{(i)} \cdot J^{(i)} dLdZ(i)=dLdA(i)J(i)

m = n m = n m=n时, J m n J_{mn} Jmn的推导, ∂ a m ∂ z m = a m ( 1 − a m ) \frac{\partial a_m}{\partial z_m} = a_m (1 - a_m) zmam=am(1am)

为了推导在Softmax函数的背景下 m = n m=n m=n的情况下表达式 ∂ a m ∂ z m = a m ( 1 − a m ) \frac{\partial a_m}{\partial z_m} = a_m (1 - a_m) zmam=am(1am),我们将从Softmax函数对特定输出 a m a_m am的定义开始,然后应用链式法则来对其相应的输入 z m z_m zm进行微分。对于输出 a m a_m am的Softmax函数的定义如下:

a m = e z m ∑ k = 1 C e z k a_m = \frac{e^{z_m}}{\sum\limits_{k=1}^{C} e^{z_k}} am=k=1Cezkezm

步骤1:应用商规则

由于 a m a_m am是一个分数,我们将使用商规则进行微分,即:

( f g ) ′ = f ′ g − f g ′ g 2 \left( \frac{f}{g} \right)' = \frac{f'g - fg'}{g^2} (gf)=g2fgfg

这里, f = e z m f=e^{z_m} f=ezmKaTeX parse error: Limit controls must follow a math operator at position 8: g=\\sum\̲l̲i̲m̲i̲t̲s̲_{k=1}^{C} e^{z…。因此, f ′ = e z m f' = e^{z_m} f=ezm,因为对 z m z_m zm微分的 e z m e^{z_m} ezm的导数是 e z m e^{z_m} ezm g ′ = e z m g' = e^{z_m} g=ezm,因为在对求和进行微分时,求和中只有一个非零导数的项 e z m e^{z_m} ezm

步骤2:代入和简化

f f f g g g f ′ f' f g ′ g' g代入商规则得到:

∂ a m ∂ z m = e z m ∑ k = 1 C e z k − e z m e z m ( ∑ k = 1 C e z k ) 2 \frac{\partial a_m}{\partial z_m} = \frac{e^{z_m} \sum\limits_{k=1}^{C} e^{z_k} - e^{z_m} e^{z_m}}{\left( \sum\limits_{k=1}^{C} e^{z_k} \right)^2} zmam=(k=1Cezk)2ezmk=1Cezkezmezm

简化分子,我们得到:

e z m ∑ k = 1 C e z k − e z m e z m = e z m ( ∑ k = 1 C e z k − e z m ) e^{z_m} \sum\limits_{k=1}^{C} e^{z_k} - e^{z_m} e^{z_m} = e^{z_m} \left( \sum\limits_{k=1}^{C} e^{z_k} - e^{z_m} \right) ezmk=1Cezkezmezm=ezm(k=1Cezkezm)

步骤3:因式分解和重新排列

我们可以因式分解 e z m e^{z_m} ezm,并将括号中的项识别为Softmax函数的分母减去第 m m m个项,这给出了:

∂ a m ∂ z m = e z m ( ∑ k = 1 C e z k − e z m ) ( ∑ k = 1 C e z k ) 2 \frac{\partial a_m}{\partial z_m} = \frac{e^{z_m} \left( \sum\limits_{k=1}^{C} e^{z_k} - e^{z_m} \right)}{\left( \sum\limits_{k=1}^{C} e^{z_k} \right)^2} zmam=(k=1Cezk)2ezm(k=1Cezkezm)

现在,观察到 e z m ∑ k = 1 C e z k = a m \frac{e^{z_m}}{\sum\limits_{k=1}^{C} e^{z_k}} = a_m k=1Cezkezm=am,以及 ∑ k = 1 C e z k − e z m ∑ k = 1 C e z k = 1 − a m \frac{\sum\limits_{k=1}^{C} e^{z_k} - e^{z_m}}{\sum_{k=1}^{C} e^{z_k}} = 1 - a_m k=1Cezkk=1Cezkezm=1am,因为从分母的总和中减去 e z m e^{z_m} ezm,然后除以同样的总和给出除 a m a_m am外所有其他 e z k e^{z_k} ezk的比例,这个比例补充到了1。

步骤4:最终表达式

将所有这些放在一起,我们得到:

∂ a m ∂ z m = a m ( 1 − a m ) \frac{\partial a_m}{\partial z_m} = a_m (1 - a_m) zmam=am(1am)

这个表达式显示了 a m a_m am相对于 z m z_m zm的变化速率取决于 a m a_m am本身以及 a m a_m am相对于所有 e z k e^{z_k} ezk总和的比例,这反映了增加 z m z_m zm不仅直接增加 a m a_m am,而且间接影响了所有类别概率分布的方式。

m ≠ n m \neq n m=n时, J m n J_{mn} Jmn的推导, ∂ a m ∂ z n = − a m a n \frac{\partial a_m}{\partial z_n} = -a_m a_n znam=aman

为了在Softmax函数的背景下推导表达式 ∂ a m ∂ z n = − a m a n \frac{\partial a_m}{\partial z_n} = -a_m a_n znam=aman,我们将从Softmax函数对特定输出 a m a_m am的定义开始,分析改变输入 z n z_n zn对不同输出 a m a_m am的影响。对于输出 a m a_m am的Softmax函数的定义如下:

a m = e z m ∑ k = 1 C e z k a_m = \frac{e^{z_m}}{\sum\limits_{k=1}^{C} e^{z_k}} am=k=1Cezkezm

步骤1:分析 z n z_n zn a m a_m am的影响

当对 a m a_m am相对于 z n z_n zn m ≠ n m \neq n m=n)进行微分时,Softmax函数的分子 e z m e^{z_m} ezm不依赖于 z n z_n zn。因此, z n z_n zn a m a_m am的唯一影响来自分母,导致微分如下:

∂ a m ∂ z n = − e z m e z n ( ∑ k = 1 C e z k ) 2 \frac{\partial a_m}{\partial z_n} = -\frac{e^{z_m} e^{z_n}}{\left( \sum\limits_{k=1}^{C} e^{z_k} \right)^2} znam=(k=1Cezk)2ezmezn

这个导数的出现是因为分母相对于 z n z_n zn的导数引入了一个负号(由于链式法则),并且包括 e z n e^{z_n} ezn,反映了 z n z_n zn对总和的影响。

步骤2:简化表达式

识别到 a m = e z m ∑ k = 1 C e z k a_m = \frac{e^{z_m}}{\sum\limits_{k=1}^{C} e^{z_k}} am=k=1Cezkezm a n = e z n ∑ k = 1 C e z k a_n = \frac{e^{z_n}}{\sum\limits_{k=1}^{C} e^{z_k}} an=k=1Cezkezn,我们将它们代入步骤1的表达式中,得到:

∂ a m ∂ z n = − e z m ∑ k = 1 C e z k ⋅ e z n ∑ k = 1 C e z k = − a m a n \frac{\partial a_m}{\partial z_n} = -\frac{e^{z_m}}{\sum\limits_{k=1}^{C} e^{z_k}} \cdot \frac{e^{z_n}}{\sum\limits_{k=1}^{C} e^{z_k}} = -a_m a_n znam=k=1Cezkezmk=1Cezkezn=aman

结论

m ≠ n m \neq n m=n时,导数 ∂ a m ∂ z n = − a m a n \frac{\partial a_m}{\partial z_n} = -a_m a_n znam=aman体现了Softmax函数的竞争性质,其中一个输入 z n z_n zn的增加导致不相关的输出 a m a_m am按比例减少。这种反向关系是由于总概率的守恒(必须总和为1),并且表示随着 z n z_n zn的增加,导致 a n a_n an增加,必须对 a m a_m am进行补偿性减少,因此导数中出现了负号。

参考资料:

  • CMU_11785_Introduction_To_Deep_Learning
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐