原文链接: https://blog.csdn.net/weixin_53765658/article/details/136360033
CSDN账号: Purepisces
github账号: purepisces
希望大家可以Star Machine Learning Blog https://github.com/purepisces/Wenqing-Machine_Learning_Blog

损失函数

根据您使用的神经网络类型和数据类型,不同的损失函数可能会变得有用,例如分类问题的交叉熵损失,回归问题的均方误差。了解这些损失函数是如何计算的,以及它们将如何用于更新您的网络是很重要的。

损失类

类属性:

  • A A A:存储模型预测以计算反向传播。
  • Y Y Y:存储期望输出以计算反向传播。

类方法:

  • f o r w a r d forward forward

    • 参数: A A A(模型预测), Y Y Y(期望输出)
    • 返回值:损失值 L L L
    • 描述:计算并返回标量损失值 L L L,量化网络输出和期望输出之间的不匹配。
  • b a c k w a r d backward backward

    • 返回值: d L d A dLdA dLdA(模型输出变化如何影响损失 L L L
    • 描述:计算并返回 d L d A dLdA dLdA,表示模型输出 A A A 的变化如何影响损失 L L L。它使得可以进行反向传播的下游计算。

请考虑以下类结构:

class Loss:
        def forward(self, A, Y):
            self.A = A
            self.Y = Y
            self.    # todo(根据需要存储额外的属性)
            N      = # todo,这是 A 和 Y 的第一维度
            C      = # todo,这是 A 和 Y 的第二维度
            # todo
            
            return L

        def backward(self):
            dLdA = # 待办事项

            return dLdA
代码名称数学符号类型形状含义
N N N N标量-批量大小
C C C C标量-类别数目
A A A A矩阵 N × C N \times C N×C模型输出
Y Y Y Y矩阵 N × C N \times C N×C真实值
L L L L标量-损失值
dLdA ∂ L ∂ A \frac{\partial L}{\partial A} AL矩阵 N × C N \times C N×C模型输出变化如何影响损失

注意:在回归任务的上下文中,对应于类别数目的维度 C C C 简化为 1。这是因为回归问题涉及预测单个连续变量,而不是从多个类别中选择。相反,在分类场景中, C C C 代表每个输入可以被分类的不同类别或类别的总数,因此可以根据具体问题而变化。

损失函数拓扑在下图中可视化:

在这里插入图片描述

示例

在此示例中,我们将演示如何在具有3个类别的分类任务中使用 L o s s Loss Loss 类。假设我们的批量大小( N N N)为2,这意味着我们一次处理两个示例。

模型输出(Logits)

模型输出,表示为 A A A,是每个类别的logits。对于我们的示例,批量大小为2且有3个类别, A A A 可能如下所示:

A = [ 5 1 − 1 − 2 6 0 ] A = \begin{bmatrix} 5 & 1 & -1\\ -2 & 6 & 0 \end{bmatrix} A=[521610]

这些logits代表每个类别的原始分数,在应用softmax函数之前。

真实值(Y)

真实值 Y Y Y 以独热编码(one-hot encoded)格式表示:

Y = [ 1 0 0 0 0 1 ] Y = \begin{bmatrix} 1 & 0 & 0\\ 0 & 0 & 1 \end{bmatrix} Y=[100001]

这里,第一行 [ 1 , 0 , 0 ] [1, 0, 0] [1,0,0] 表示第一个示例属于第1类,第二行 [ 0 , 0 , 1 ] [0, 0, 1] [0,0,1] 表示第二个示例属于第3类。

在损失计算中使用 A A A Y Y Y

损失函数使用logits A A A 和真实值 Y Y Y 来计算损失值 L L L。例如,使用交叉熵损失函数会首先对logits应用softmax函数以获得概率,然后通过将这些预测概率与 Y Y Y 中的实际标签进行比较来计算每个单独示例的损失。随后,这些单独的损失在批次中的所有示例上平均,以产生损失的单一标量值, L L L

L o s s Loss Loss 类中的 f o r w a r d forward forward 方法负责使用 A A A(作为logits)和 Y Y Y 来计算这个标量损失值 L L L。接着, b a c k w a r d backward backward 方法计算损失对于logits的梯度,表示为 ∂ L ∂ A \frac{\partial L}{\partial A} AL。这个梯度对于反向传播过程至关重要,使得在训练期间可以更新模型参数。

详解均方误差损失函数:

均方误差(MSE,Mean Squared Error)是回归问题中评估预测误差的一种广泛使用的指标。在回归中,目标是预测连续值,例如根据房屋的特征(如面积、位置、卧室数量等)估计房屋的价格。

MSE 损失前向方程

计算从计算模型预测( A A A)与实际真值( Y Y Y)之间的平方误差( S E SE SE)开始:

S E ( A , Y ) = ( A − Y ) ⊙ ( A − Y ) SE(A, Y) = (A - Y) \odot (A - Y) SE(A,Y)=(AY)(AY)

接下来,我们确定平方误差之和( S S E SSE SSE)。这里, ι N \iota_N ιN ι C \iota_C ιC 分别表示大小为 N N N C C C 的、填充有 1 的列向量:

S S E ( A , Y ) = ι N T ⋅ S E ( A , Y ) ⋅ ι C SSE(A,Y) = \iota_{N}^{T} \cdot SE(A,Y) \cdot \iota_{C} SSE(A,Y)=ιNTSE(A,Y)ιC

这个操作将 S E ( A , Y ) SE(A, Y) SE(A,Y) 矩阵中的所有元素求和,该矩阵的维度为 N × C N \times C N×C。通过 ι N T \iota_{N}^{T} ιNT 的乘法在行间聚合错误,随后通过 ι C \iota_{C} ιC 的乘法将这些在列间求和,产生一个单一标量的总误差。

然后计算每个组件的均方误差( M S E MSE MSE)损失:

M S E L o s s ( A , Y ) = S S E ( A , Y ) N ⋅ C MSELoss(A, Y) = \frac{SSE(A, Y)}{N \cdot C} MSELoss(A,Y)=NCSSE(A,Y)

MSE 损失反向方程

在反向传播过程中,需要计算 MSE 损失相对于模型输出( A A A)的梯度,以更新模型参数:

M S E L o s s . b a c k w a r d ( ) = 2 ⋅ ( A − Y ) N ⋅ C MSELoss.backward() = 2 \cdot \frac{(A - Y)}{N \cdot C} MSELoss.backward()=2NC(AY)

MSE 损失的导数

MSE 损失函数定义为:

M S E L o s s ( A , Y ) = 1 N ⋅ C ∑ i = 1 N ∑ j = 1 C ( A i j − Y i j ) 2 MSELoss(A, Y) = \frac{1}{N \cdot C} \sum\limits_{i=1}^{N} \sum\limits_{j=1}^{C} (A_{ij} - Y_{ij})^2 MSELoss(A,Y)=NC1i=1Nj=1C(AijYij)2

其中:

A A A:模型预测值。

Y Y Y:真实值。

N N N:批次中的样本数量。

C C C:每个样本的输出维度,回归任务中通常为 1。

为了更新模型参数(在这个例子中,通过反向传播),我们需要知道 A A A 的变化如何影响损失。这由损失函数相对于 A A A 的导数给出,表示为 ∂ M S E L o s s ∂ A \frac{\partial MSELoss}{\partial A} AMSELoss

∂ M S E L o s s ∂ A = 2 ⋅ ( A − Y ) N ⋅ C \frac{\partial MSELoss}{\partial A} = 2 \cdot \frac{(A - Y)}{N \cdot C} AMSELoss=2NC(AY)

梯度 ∂ M S E L o s s ∂ A \frac{\partial MSELoss}{\partial A} AMSELoss 指向损失函数最陡增加的方向。通过向相反方向移动(即,从预测 A A A 中减去这个梯度),我们可以减少损失,这是训练模型的目标。

总之, M S E L o s s . b a c k w a r d ( ) MSELoss.backward() MSELoss.backward() 2 ⋅ ( A − Y ) N ⋅ C 2 \cdot \frac{(A - Y)}{N \cdot C} 2NC(AY) 公式是通过对预测 A A A 求 MSE 损失函数的导数得到的,考虑了平方误差和平均操作。这个梯度在优化过程中被用来调整模型参数,以最小化损失。

import numpy as np

class MSELoss:
    def forward(self, A, Y):
        # 为反向计算存储预测值(A)和真实值(Y)
        self.A = A
        self.Y = Y
        # 计算预测值和真实值之间的平方误差
        se = (A - Y) ** 2
        # 对平方误差求和以得到总的平方误差
        sse = np.sum(se)
        # 通过将总的平方误差除以元素数量来计算均方误差
        mse = sse / (A.shape[0] * A.shape[1])
        return mse

    def backward(self):
        # 计算损失相对于预测值(A)的梯度
        dLdA = 2 * (self.A - self.Y) / (self.A.shape[0] * self.A.shape[1])
        return dLdA

示例

让我们通过一个具体的例子来了解在回归场景中如何应用均方误差(MSE)损失。假设我们正试图基于一些特征来预测房屋价格。为了简单起见,我们将考虑一个案例,其中我们的模型基于多个特征(例如平方英尺面积和卧室数量)来预测两栋房屋的价格,因此我们的批量大小 N N N 为 2,特征数量 C C C 也为 2。

给定数据:

  • 模型输出 ( A A A):预测的两栋房屋的价格和卧室数量。假设模型对每栋房屋的预测如下(价格以美元计,卧室以数量计)。这可以表示为一个 2x2 矩阵(因为 N = 2 N=2 N=2 C = 2 C=2 C=2):

A = [ 300 , 000 3 500 , 000 4 ] A = \begin{bmatrix} 300,000 & 3 \\ 500,000 & 4 \end{bmatrix} A=[300,000500,00034]

这里,第一列代表两栋房屋的预测价格,第二列代表预测的卧室数量。

  • 真实值 ( Y Y Y):两栋房屋的实际价格和卧室数量。这也是一个 2x2 矩阵:

Y = [ 350 , 000 4 450 , 000 3 ] Y = \begin{bmatrix} 350,000 & 4 \\ 450,000 & 3 \end{bmatrix} Y=[350,000450,00043]

正向传播(计算 MSE 损失):

  1. 计算平方误差 ( S E SE SE):

S E ( A , Y ) = ( A − Y ) ⊙ ( A − Y ) = [ ( 300 , 000 − 350 , 000 ) 2 ( 3 − 4 ) 2 ( 500 , 000 − 450 , 000 ) 2 ( 4 − 3 ) 2 ] = [ 2500 × 1 0 6 1 2500 × 1 0 6 1 ] \begin{align} SE(A, Y) &= (A - Y) \odot (A - Y) \\ &= \begin{bmatrix} (300,000 - 350,000)^2 & (3 - 4)^2 \\ (500,000 - 450,000)^2 & (4 - 3)^2 \end{bmatrix} \\ &= \begin{bmatrix} 2500 \times 10^6 & 1 \\ 2500 \times 10^6 & 1 \end{bmatrix} \end{align} SE(A,Y)=(AY)(AY)=[(300,000350,000)2(500,000450,000)2(34)2(43)2]=[2500×1062500×10611]

  1. 平方误差之和 ( S S E SSE SSE):
    S E SE SE 中的所有元素相加:

S S E ( A , Y ) = ∑ S E ( A , Y ) = 2 × ( 2500 × 1 0 6 ) + 2 × 1 = 5000 × 1 0 6 + 2 SSE(A, Y) = \sum SE(A, Y) = 2 \times (2500 \times 10^6) + 2 \times 1 = 5000 \times 10^6 + 2 SSE(A,Y)=SE(A,Y)=2×(2500×106)+2×1=5000×106+2

  1. 均方误差 ( M S E MSE MSE):

M S E L o s s ( A , Y ) = S S E ( A , Y ) N ⋅ C = 5000 × 1 0 6 + 2 2 × 2 = 2500 × 1 0 6 + 1 2 MSELoss(A, Y) = \frac{SSE(A, Y)}{N \cdot C} = \frac{5000 \times 10^6 + 2}{2 \times 2} = \frac{2500 \times 10^6 + 1}{2} MSELoss(A,Y)=NCSSE(A,Y)=2×25000×106+2=22500×106+1

反向传播(计算梯度):

可以计算损失相对于预测值 ( A A A) 的梯度:

∂ M S E L o s s ∂ A = 2 ⋅ ( A − Y ) N ⋅ C = 2 ⋅ [ 300 , 000 − 350 , 000 3 − 4 500 , 000 − 450 , 000 4 − 3 ] 2 × 2 = 1 2 [ − 50 , 000 − 1 50 , 000 1 ] \begin{align} \frac{\partial MSELoss}{\partial A} &= 2 \cdot \frac{(A - Y)}{N \cdot C} \\ &= 2 \cdot \frac{\begin{bmatrix} 300,000 - 350,000 & 3 - 4 \\ 500,000 - 450,000 & 4 - 3 \end{bmatrix}}{2 \times 2} \\ &= \frac{1}{2} \begin{bmatrix} -50,000 & -1 \\ 50,000 & 1 \end{bmatrix} \end{align} AMSELoss=2NC(AY)=22×2[300,000350,000500,000450,0003443]=21[50,00050,00011]

这个梯度矩阵提供了如何调整每个预测(价格和卧室数量)以最小化损失的指导。负值表示需要增加预测值,正值表明需要减少预测值以减少误差。

详解交叉熵损失函数:

交叉熵损失是用于基于概率的分类问题最常用的损失函数之一。

交叉熵损失前向方程

首先,我们使用softmax函数将原始模型输出 A A A转换成由输入数值的指数决定的 C C C类的概率分布。

ι N \iota_N ιN ι C \iota_C ιC是大小为 N N N C C C的列向量,包含全部为1的值。

softmax ( A ) = σ ( A ) = exp ⁡ ( A ) ∑ j = 1 C exp ⁡ ( A i j ) \text{softmax}(A) = \sigma(A) = \frac{\exp(A)}{\sum\limits_{j=1}^{C} \exp(A_{ij})} softmax(A)=σ(A)=j=1Cexp(Aij)exp(A)

现在,A的每一行代表模型对概率分布的预测,而Y的每一行代表一个输入的目标分布。
然后,我们计算分布Ai相对于目标分布Yi的交叉熵H(A,Y),对于i = 1,…,N:

crossentropy = H ( A , Y ) = ( − Y ⊙ log ⁡ ( σ ( A ) ) ) ⋅ ι C \text{crossentropy} = H(A, Y) = (-Y \odot \log(\sigma(A))) \cdot \mathbf{\iota}_C crossentropy=H(A,Y)=(Ylog(σ(A)))ιC

记住,损失函数的输出是一个标量,但现在我们有一个大小为N的列矩阵。要将其转换为标量,我们可以使用所有交叉熵的和或平均值。

这里,我们选择使用平均交叉熵作为交叉熵损失,这也是PyTorch的默认设置:

sumcrossentropyloss : = ι N T ⋅ H ( A , Y ) = S C E ( A , Y ) \text{sumcrossentropyloss} := \mathbf{\iota}_N^T \cdot H(A, Y) = SCE(A, Y) sumcrossentropyloss:=ιNTH(A,Y)=SCE(A,Y)

meancrossentropyloss : = S C E ( A , Y ) N \text{meancrossentropyloss} := \frac{SCE(A, Y)}{N} meancrossentropyloss:=NSCE(A,Y)
在这里插入图片描述

交叉熵损失反向方程

xent.backward ( ) = σ ( A ) − Y N \text{xent.backward}() = \frac{\sigma(A) - Y}{N} xent.backward()=Nσ(A)Y

梯度的推导(我的证明)

要找到交叉熵损失相对于对数几率 A i A_i Ai的梯度,我们需要计算导数 ∂ H ∂ A i \frac{\partial H}{\partial A_i} AiH。这涉及到应用链式法则到对数和softmax函数的复合中。

注意对于一个对数几率 A i c A_{ic} Aic,softmax函数定义为:

σ ( A i c ) = e A i c ∑ j = 1 C e A i j \sigma(A_{ic}) = \frac{e^{A_{ic}}}{\sum\limits_{j=1}^{C} e^{A_{ij}}} σ(Aic)=j=1CeAijeAic

步骤1:应用链式法则

首先,注意我们需要对一个复合函数的导数应用链式法则,这个复合函数是softmax输出的对数:

H ( A i , Y i ) = − ∑ c = 1 C Y i c log ⁡ ( σ ( A i c ) ) H(A_i, Y_i) = -\sum_{c=1}^{C} Y_{ic} \log(\sigma(A_{ic})) H(Ai,Yi)=c=1CYiclog(σ(Aic))

∂ H ∂ A i c = ∂ ( − Y i 1 log ⁡ ( σ ( A i 1 ) ) − Y i 2 log ⁡ ( σ ( A i 2 ) ) − . . . − Y i C log ⁡ ( σ ( A i C ) ) ) ∂ A i c = ∂ ( − Y i 1 log ⁡ ( σ ( A i 1 ) ) ) ∂ A i c + ∂ ( − Y i 2 log ⁡ ( σ ( A i 2 ) ) ) ∂ A i c + . . . + ∂ ( − Y i C log ⁡ ( σ ( A i C ) ) ) ∂ A i c = − Y i 1 ∂ log ⁡ ( σ ( A i 1 ) ) ∂ A i c − Y i 2 ∂ log ⁡ ( σ ( A i 2 ) ) ∂ A i c − . . . − Y i C ∂ log ⁡ ( σ ( A i C ) ) ∂ A i c = − ∑ k = 1 C Y i k ∂ log ⁡ ( σ ( A i k ) ) ∂ A i c \begin{align*} \frac{\partial H}{\partial A_{ic}} &= \frac{\partial (-Y_{i1}\log(\sigma(A_{i1})) -Y_{i2}\log(\sigma(A_{i2}))-...-Y_{iC}\log(\sigma(A_{iC})))}{\partial A_{ic}} \\ &= \frac{\partial (-Y_{i1}\log(\sigma(A_{i1})))}{\partial A_{ic}} + \frac{\partial (-Y_{i2}\log(\sigma(A_{i2})))}{\partial A_{ic}} + ...+ \frac{\partial (-Y_{iC}\log(\sigma(A_{iC})))}{\partial A_{ic}} \\ &=-Y_{i1}\frac{\partial \log(\sigma(A_{i1}))}{\partial A_{ic}} -Y_{i2}\frac{\partial \log(\sigma(A_{i2}))}{\partial A_{ic}} -...-Y_{iC}\frac{\partial \log(\sigma(A_{iC}))}{\partial A_{ic}} \\ &=- \sum_{k=1}^{C} Y_{ik} \frac{\partial \log(\sigma(A_{ik}))}{\partial A_{ic}}\\ \end{align*} AicH=Aic(Yi1log(σ(Ai1))Yi2log(σ(Ai2))...YiClog(σ(AiC)))=Aic(Yi1log(σ(Ai1)))+Aic(Yi2log(σ(Ai2)))+...+Aic(YiClog(σ(AiC)))=Yi1Aiclog(σ(Ai1))Yi2Aiclog(σ(Ai2))...YiCAiclog(σ(AiC))=k=1CYikAiclog(σ(Aik))

∂ H ∂ A i c = − ∑ k = 1 C Y i k ∂ log ⁡ ( σ ( A i k ) ) ∂ A i c \frac{\partial H}{\partial A_{ic}} = - \sum_{k=1}^{C} Y_{ik} \frac{\partial \log(\sigma(A_{ik}))}{\partial A_{ic}} AicH=k=1CYikAiclog(σ(Aik))

步骤2:Softmax的对数的导数

log ⁡ ( σ ( A i k ) ) \log(\sigma(A_{ik})) log(σ(Aik))关于 A i c A_{ic} Aic的导数涉及两种情况:当 k = c k=c k=c和当 k ≠ c k \neq c k=c时。

k = c k=c k=c时,使用对数的导数 ∂ log ⁡ ( x ) ∂ x = 1 x \frac{\partial \log(x)}{\partial x} = \frac{1}{x} xlog(x)=x1和softmax的定义,我们得到:

∂ log ⁡ ( σ ( A i k ) ) ∂ A i c = ∂ log ⁡ ( σ ( A i c ) ) ∂ σ ( A i c ) ⋅ ∂ σ ( A i c ) ∂ A i c = 1 σ ( A i c ) ⋅ σ ( A i c ) ⋅ ( 1 − σ ( A i c ) ) = 1 − σ ( A i c ) \begin{align*} \frac{\partial \log(\sigma(A_{ik}))}{\partial A_{ic}} &= \frac{\partial \log(\sigma(A_{ic}))}{\partial \sigma(A_{ic})} \cdot \frac{\partial \sigma(A_{ic})}{\partial A_{ic}} \\ &= \frac{1}{\sigma(A_{ic})} \cdot \sigma(A_{ic}) \cdot (1 - \sigma(A_{ic})) \\ &= 1 - \sigma(A_{ic}) \end{align*} Aiclog(σ(Aik))=σ(Aic)log(σ(Aic))Aicσ(Aic)=σ(Aic)1σ(Aic)(1σ(Aic))=1σ(Aic)

k ≠ c k\neq c k=c时,导数涉及不同类的softmax函数,结果是:

∂ log ⁡ ( σ ( A i k ) ) ∂ A i c = ∂ log ⁡ ( σ ( A i k ) ) ∂ σ ( A i c ) ⋅ ∂ σ ( A i c ) ∂ A i c = 1 σ ( A i k ) ⋅ − σ ( A i k ) ⋅ σ ( A i c ) = − σ ( A i c ) \begin{align*} \frac{\partial \log(\sigma(A_{ik}))}{\partial A_{ic}} &= \frac{\partial \log(\sigma(A_{ik}))}{\partial \sigma(A_{ic})} \cdot \frac{\partial \sigma(A_{ic})}{\partial A_{ic}} \\ &= \frac{1}{\sigma(A_{ik})} \cdot -\sigma(A_{ik}) \cdot \sigma(A_{ic}) \\ &= -\sigma(A_{ic}) \end{align*} Aiclog(σ(Aik))=σ(Aic)log(σ(Aik))Aicσ(Aic)=σ(Aik)1σ(Aik)σ(Aic)=σ(Aic)

步骤3:合并情况

由于 Y i Y_i Yi对于真实类别只能为1,否则为0,这简化为:

∂ H ∂ A i c = − ∑ k = 1 C Y i k ∂ log ⁡ ( σ ( A i k ) ) ∂ A i c = o r { − 1 ( 1 − σ ( A i c ) ) = σ ( A i c ) − 1 , for  Y i c = 0 − 1 ( − σ ( A i c ) ) = σ ( A i c ) − 0 , for  Y i c = 1 = σ ( A i c ) − Y i c \begin{align*} \frac{\partial H}{\partial A_{ic}} &= - \sum_{k=1}^{C} Y_{ik} \frac{\partial \log(\sigma(A_{ik}))}{\partial A_{ic}} \\ &= or\begin{cases} -1 (1 - \sigma(A_{ic})) = \sigma(A_{ic}) - 1, & \text{for } Y_{ic} = 0 \\ -1(-\sigma(A_{ic})) = \sigma(A_{ic}) - 0, & \text{for } Y_{ic} = 1 \end{cases} \\ &= \sigma(A_{ic}) - Y_{ic} \end{align*} AicH=k=1CYikAiclog(σ(Aik))=or{1(1σ(Aic))=σ(Aic)1,1(σ(Aic))=σ(Aic)0,for Yic=0for Yic=1=σ(Aic)Yic

示例

让我给出一个具体的例子来说明它:

示例 1

考虑这个案例 Y = [ 1 , 0 , 0 ] Y = [1,0,0] Y=[1,0,0] A = [ 2 , 1 , − 1 ] A = [2, 1, -1] A=[2,1,1]

Y 11 = 1 , Y 12 = 0 , Y 13 = 0 Y_{11} = 1, Y_{12} = 0, Y_{13} = 0 Y11=1,Y12=0,Y13=0
A 11 = 2 , A 12 = 1 , A 13 = − 1 A_{11} = 2, A_{12} = 1, A_{13} = -1 A11=2,A12=1,A13=1

然后当计算

∂ H ∂ A 13 = − ∑ k = 1 C Y 1 k ∂ log ⁡ ( σ ( A 1 k ) ) ∂ A 13 = − Y 11 ∂ log ⁡ ( σ ( A 11 ) ) ∂ A 13 − Y 12 ∂ log ⁡ ( σ ( A 12 ) ) ∂ A 13 − Y 13 ∂ log ⁡ ( σ ( A 13 ) ) ∂ A 13 = − 1 ( − σ ( A 13 ) ) − 0 − 0 = σ ( A 13 ) − 0 = σ ( A 13 ) − Y 13 \begin{align*} \frac{\partial H}{\partial A_{13}} &= - \sum\limits_{k=1}^{C} Y_{1k} \frac{\partial \log(\sigma(A_{1k}))}{\partial A_{13}}\\ &=-Y_{11}\frac{\partial \log(\sigma(A_{11}))}{\partial A_{13}}-Y_{12}\frac{\partial \log(\sigma(A_{12}))}{\partial A_{13}}-Y_{13}\frac{\partial \log(\sigma(A_{13}))}{\partial A_{13}}\\ &= -1(-\sigma(A_{13}))-0-0 \\ &= \sigma(A_{13}) - 0 \\ &= \sigma(A_{13}) - Y _{13}\\ \end{align*} A13H=k=1CY1kA13log(σ(A1k))=Y11A13log(σ(A11))Y12A13log(σ(A12))Y13A13log(σ(A13))=1(σ(A13))00=σ(A13)0=σ(A13)Y13

示例 2

考虑这个案例 Y = [ 0 , 0 , 1 ] Y = [0,0,1] Y=[0,0,1] A = [ 2 , 1 , − 1 ] A = [2, 1, -1] A=[2,1,1]

Y 11 = 0 , Y 12 = 0 , Y 13 = 1 Y_{11} = 0, Y_{12} = 0, Y_{13} = 1 Y11=0,Y12=0,Y13=1
A 11 = 2 , A 12 = 1 , A 13 = − 1 A_{11} = 2, A_{12} = 1, A_{13} = -1 A11=2,A12=1,A13=1

然后当计算

∂ H ∂ A 13 = − ∑ k = 1 C Y 1 k ∂ log ⁡ ( σ ( A 1 k ) ) ∂ A 13 = − Y 11 ∂ log ⁡ ( σ ( A 11 ) ) ∂ A 13 − Y 12 ∂ log ⁡ ( σ ( A 12 ) ) ∂ A 13 − Y 13 ∂ log ⁡ ( σ ( A 13 ) ) ∂ A 13 = − 0 − 0 − 1 ( 1 − σ ( A 13 ) ) = σ ( A 13 ) − 1 = σ ( A 13 ) − Y 13 \begin{align*} \frac{\partial H}{\partial A_{13}} &= - \sum\limits_{k=1}^{C} Y_{1k} \frac{\partial \log(\sigma(A_{1k}))}{\partial A_{13}}\\ &=-Y_{11}\frac{\partial \log(\sigma(A_{11}))}{\partial A_{13}}-Y_{12}\frac{\partial \log(\sigma(A_{12}))}{\partial A_{13}}-Y_{13}\frac{\partial \log(\sigma(A_{13}))}{\partial A_{13}}\\ &= -0-0-1(1 - \sigma(A_{13})) \\ &= \sigma(A_{13}) - 1 \\ &= \sigma(A_{13}) - Y _{13}\\ \end{align*} A13H=k=1CY1kA13log(σ(A1k))=Y11A13log(σ(A11))Y12A13log(σ(A12))Y13A13log(σ(A13))=001(1σ(A13))=σ(A13)1=σ(A13)Y13

梯度的推导(YouTube的证明)
  • Softmax函数是一个向量。
  • 每个元素 e z k ∑ c = 1 C e z c \frac{e^{z_k}}{\sum\limits_{c=1}^{C} e^{z_c}} c=1Cezcezk由于分母的原因依赖于所有输入元素。
  • 向量关于向量的梯度是一个矩阵。
  • 为了简化和巩固这个概念,让我们通过查看一个大小为 3 3 3的向量来使其更具体:

( z 1 z 2 z 3 ) → ( e z 1 e z 1 + e z 2 + e z 3 e z 2 e z 1 + e z 2 + e z 3 e z 3 e z 1 + e z 2 + e z 3 ) = ( a 1 a 2 a 3 ) = ( y 1 ^ y 2 ^ y 3 ^ ) \begin{pmatrix} z_1\\ z_2\\ z_3 \end{pmatrix} \rightarrow \begin{pmatrix} \frac{e^{z_1}}{e^{z_1} + e^{z_2} + e^{z_3}}\\ \frac{e^{z_2}}{e^{z_1} + e^{z_2} + e^{z_3}}\\ \frac{e^{z_3}}{e^{z_1} + e^{z_2} + e^{z_3}} \end{pmatrix} = \begin{pmatrix} a_1\\ a_2\\ a_3 \end{pmatrix} = \begin{pmatrix} \hat{y_1}\\ \hat{y_2}\\ \hat{y_3} \end{pmatrix} z1z2z3 ez1+ez2+ez3ez1ez1+ez2+ez3ez2ez1+ez2+ez3ez3 = a1a2a3 = y1^y2^y3^

矩阵的对角元素会发生什么?我们有导数关于分子中相同元素。例如,对于 ∂ a 1 ∂ z 1 \frac{\partial a_1}{\partial z_1} z1a1我们得到:

∂ a 1 ∂ z 1 = e z 1 ( e z 1 + e z 2 + e z 3 ) − e z 1 e z 1 ( e z 1 + e z 2 + e z 3 ) ( e z 1 + e z 2 + e z 3 ) = e z 1 e z 1 + e z 2 + e z 3 ⋅ e z 1 + e z 2 + e z 3 − e z 1 e z 1 + e z 2 + e z 3 = a 1 ( 1 − a 1 ) \frac{\partial a_1}{\partial z_1} = \frac{e^{z_1}(e^{z_1} + e^{z_2} + e^{z_3}) - e^{z_1}e^{z_1}}{(e^{z_1} + e^{z_2} + e^{z_3})(e^{z_1} + e^{z_2} + e^{z_3})} = \frac{e^{z_1}}{e^{z_1} + e^{z_2} + e^{z_3}} \cdot \frac{e^{z_1}+e^{z_2}+e^{z_3}-e^{z_1}}{e^{z_1} + e^{z_2} + e^{z_3}} = a_1(1 - a_1) z1a1=(ez1+ez2+ez3)(ez1+ez2+ez3)ez1(ez1+ez2+ez3)ez1ez1=ez1+ez2+ez3ez1ez1+ez2+ez3ez1+ez2+ez3ez1=a1(1a1)

所以我们得到了非常接近于sigmoid导数的东西。

对角线元素以外的元素会发生什么?例如,对于 ∂ a 1 ∂ z 2 \frac{\partial a_1}{\partial z_2} z2a1我们得到:

∂ a 1 ∂ z 2 = 0 ⋅ ( e z 1 + e z 2 + e z 3 ) − e z 1 e z 2 ( e z 1 + e z 2 + e z 3 ) 2 = − e z 1 e z 1 + e z 2 + e z 3 ⋅ e z 2 e z 1 + e z 2 + e z 3 = − a 1 a 2 \frac{\partial a_1}{\partial z_2} = \frac{0 \cdot (e^{z_1} + e^{z_2} + e^{z_3}) - e^{z_1}e^{z_2}}{(e^{z_1} + e^{z_2} + e^{z_3})^2} = -\frac{e^{z_1}}{e^{z_1} + e^{z_2} + e^{z_3}} \cdot \frac{e^{z_2}}{e^{z_1} + e^{z_2} + e^{z_3}} = -a_1a_2 z2a1=(ez1+ez2+ez3)20(ez1+ez2+ez3)ez1ez2=ez1+ez2+ez3ez1ez1+ez2+ez3ez2=a1a2

对于我们的3x3矩阵,我们将得到:

∂ a ∂ z = ( a 1 ( 1 − a 1 ) − a 1 a 2 − a 1 a 3 − a 2 a 1 a 2 ( 1 − a 2 ) − a 2 a 3 − a 3 a 1 − a 3 a 2 a 3 ( 1 − a 3 ) ) \frac{\partial \mathbf{a}}{\partial \mathbf{z}} = \begin{pmatrix} a_1(1 - a_1) & -a_1a_2 & -a_1a_3 \\ -a_2a_1 & a_2(1 - a_2) & -a_2a_3 \\ -a_3a_1 & -a_3a_2 & a_3(1 - a_3) \end{pmatrix} za= a1(1a1)a2a1a3a1a1a2a2(1a2)a3a2a1a3a2a3a3(1a3)

对于损失相对于最终输出的导数 - 我们有一个标量相对于向量的导数,所以结果也将是一个向量:

∂ L ∂ a L = [ ∂ ∂ a L 1 ( − ∑ c = 1 C y c log ⁡ a L c ) ⋮ ∂ ∂ a L C ( − ∑ c = 1 C y c log ⁡ a L c ) ] = − [ y 1 a L 1 ⋮ y C a L C ] \frac{\partial \mathcal{L}}{\partial a_L} = \begin{bmatrix} \frac{\partial}{\partial a_{L1}} \left(-\sum\limits_{c=1}^{C} y_c \log a_{Lc}\right) \\ \vdots \\ \frac{\partial}{\partial a_{LC}} \left(-\sum\limits_{c=1}^{C} y_c \log a_{Lc}\right) \end{bmatrix} = - \begin{bmatrix} \frac{y_1}{a_{L1}} \\ \vdots \\ \frac{y_C}{a_{LC}} \end{bmatrix} aLL= aL1(c=1CyclogaLc)aLC(c=1CyclogaLc) = aL1y1aLCyC

记住对于每个1-hot向量 y y y,我们只有一个元素等于1,其余都是0。

回到我们具体的 3 × 3 3 \times 3 3×3例子,并把所有东西放在一起,我们得到:

∂ L ∂ z L = ∂ L ∂ a L ∂ a L ∂ z L = − [ y 1 a 1 y 2 a 2 y 3 a 3 ] ( a 1 ( 1 − a 1 ) − a 1 a 2 − a 1 a 3 − a 2 a 1 a 2 ( 1 − a 2 ) − a 2 a 3 − a 3 a 1 − a 3 a 2 a 3 ( 1 − a 3 ) ) = − [ y 1 − a 1 ( y 1 + y 2 + y 3 ) y 2 − a 2 ( y 1 + y 2 + y 3 ) y 3 − a 3 ( y 1 + y 2 + y 3 ) ] = a − y \begin{align} \frac{\partial \mathcal{L}}{\partial z_L} &= \frac{\partial \mathcal{L}}{\partial a_L} \frac{\partial a_L}{\partial z_L} \\ &= -\begin{bmatrix} \frac{y_1}{a_1} \\ \frac{y_2}{a_2} \\ \frac{y_3}{a_3} \end{bmatrix} \begin{pmatrix} a_1(1 - a_1) & -a_1a_2 & -a_1a_3 \\ -a_2a_1 & a_2(1 - a_2) & -a_2a_3 \\ -a_3a_1 & -a_3a_2 & a_3(1 - a_3) \end{pmatrix} \\ &= -\begin{bmatrix} y_1 - a_1(y_1 + y_2 + y_3) & y_2 - a_2(y_1 + y_2 + y_3) & y_3 - a_3(y_1 + y_2 + y_3) \end{bmatrix} \\ &= \mathbf{a} - \mathbf{y} \end{align} zLL=aLLzLaL= a1y1a2y2a3y3 a1(1a1)a2a1a3a1a1a2a2(1a2)a3a2a1a3a2a3a3(1a3) =[y1a1(y1+y2+y3)y2a2(y1+y2+y3)y3a3(y1+y2+y3)]=ay

注意这里的 a \mathbf{a} a y \mathbf{y} y是向量,而不是标量。

交叉熵损失的示例

为了说明交叉熵损失,让我们考虑一个具体的例子,用一个小数据集。假设我们有一个简单的分类问题,有三个类别(C=3),我们正在处理两个样本的批次( N = 2 N=2 N=2)。这两个样本的模型原始输出分数( A A A)和相应的真实标签( Y Y Y)可能如下所示:

  • 两个样本的原始模型输出( A A A):

    • 样本 1: [ 2.0 , 1.0 , 0.1 ] [2.0, 1.0, 0.1] [2.0,1.0,0.1]
    • 样本 2: [ 0.1 , 2.0 , 1.9 ] [0.1, 2.0, 1.9] [0.1,2.0,1.9]
  • 真实类别分布( Y Y Y,独热编码):

    • 样本 1: [ 0 , 1 , 0 ] [0, 1, 0] [0,1,0] (类别 2 是真实类别)
    • 样本 2: [ 1 , 0 , 0 ] [1, 0, 0] [1,0,0] (类别 1 是真实类别)

让我们逐步计算这个例子的交叉熵损失:

1. 应用 Softmax

首先,我们对原始输出应用 softmax 函数,以获得每个类别的预测概率。

对于样本 1,softmax 计算如下:
σ ( A 1 ) = [ e 2.0 e 2.0 + e 1.0 + e 0.1 , e 1.0 e 2.0 + e 1.0 + e 0.1 , e 0.1 e 2.0 + e 1.0 + e 0.1 ] \sigma(A_1) = \left[\frac{e^{2.0}}{e^{2.0} + e^{1.0} + e^{0.1}}, \frac{e^{1.0}}{e^{2.0} + e^{1.0} + e^{0.1}}, \frac{e^{0.1}}{e^{2.0} + e^{1.0} + e^{0.1}}\right] σ(A1)=[e2.0+e1.0+e0.1e2.0,e2.0+e1.0+e0.1e1.0,e2.0+e1.0+e0.1e0.1]

对于样本 2,类似地:
σ ( A 2 ) = [ e 0.1 e 0.1 + e 2.0 + e 1.9 , e 2.0 e 0.1 + e 2.0 + e 1.9 , e 1.9 e 0.1 + e 2.0 + e 1.9 ] \sigma(A_2) = \left[\frac{e^{0.1}}{e^{0.1} + e^{2.0} + e^{1.9}}, \frac{e^{2.0}}{e^{0.1} + e^{2.0} + e^{1.9}}, \frac{e^{1.9}}{e^{0.1} + e^{2.0} + e^{1.9}}\right] σ(A2)=[e0.1+e2.0+e1.9e0.1,e0.1+e2.0+e1.9e2.0,e0.1+e2.0+e1.9e1.9]

2. 计算交叉熵损失

接下来,我们计算每个样本的交叉熵损失。单个样本的损失由下式给出:
H ( A i , Y i ) = − ∑ c = 1 C Y i c log ⁡ ( σ ( A i c ) ) H(A_i, Y_i) = -\sum_{c=1}^{C} Y_{ic} \log(\sigma(A_{ic})) H(Ai,Yi)=c=1CYiclog(σ(Aic))

对于样本 1:
H ( A 1 , Y 1 ) = − [ 0 × log ⁡ ( σ ( A 11 ) ) + 1 × log ⁡ ( σ ( A 12 ) ) + 0 × log ⁡ ( σ ( A 13 ) ) ] H(A_1, Y_1) = -[0 \times \log(\sigma(A_{11})) + 1 \times \log(\sigma(A_{12})) + 0 \times \log(\sigma(A_{13}))] H(A1,Y1)=[0×log(σ(A11))+1×log(σ(A12))+0×log(σ(A13))]

对于样本 2:
H ( A 2 , Y 2 ) = − [ 1 × log ⁡ ( σ ( A 21 ) ) + 0 × log ⁡ ( σ ( A 22 ) ) + 0 × log ⁡ ( σ ( A 23 ) ) ] H(A_2, Y_2) = -[1 \times \log(\sigma(A_{21})) + 0 \times \log(\sigma(A_{22})) + 0 \times \log(\sigma(A_{23}))] H(A2,Y2)=[1×log(σ(A21))+0×log(σ(A22))+0×log(σ(A23))]

3. 计算平均交叉熵损失

最后,我们计算这些损失的平均值,以得到批次的平均交叉熵损失:
meancrossentropyloss = H ( A 1 , Y 1 ) + H ( A 2 , Y 2 ) 2 \text{meancrossentropyloss} = \frac{H(A_1, Y_1) + H(A_2, Y_2)}{2} meancrossentropyloss=2H(A1,Y1)+H(A2,Y2)

4. 交叉熵损失的反向传播

对于反向传播,交叉熵损失相对于应用 softmax 之前的原始模型输出的梯度由下式给出:
∂ Loss ∂ A = σ ( A ) − Y N \frac{\partial \text{Loss}}{\partial A} = \frac{\sigma(A) - Y}{N} ALoss=Nσ(A)Y

对于批次中的每个样本,我们计算:

  • 对于样本 1: σ ( A 1 ) − Y 1 2 \frac{\sigma(A_1) - Y_1}{2} 2σ(A1)Y1
  • 对于样本 2: σ ( A 2 ) − Y 2 2 \frac{\sigma(A_2) - Y_2}{2} 2σ(A2)Y2

这给了我们需要通过网络反向传播的梯度。

基于计算:

  • 两个样本的 softmax 概率大约为:

    • 样本 1: [ 0.659 , 0.242 , 0.099 ] [0.659, 0.242, 0.099] [0.659,0.242,0.099]
    • 样本 2: [ 0.073 , 0.487 , 0.440 ] [0.073, 0.487, 0.440] [0.073,0.487,0.440]
  • 两个样本的交叉熵损失为:

    • 样本 1: 1.417
    • 样本 2: 2.620
  • 这个批次的平均交叉熵损失大约为 2.019。

  • 损失相对于原始模型输出( A A A)的梯度为:

    • 对于样本 1: [ 0.330 , − 0.379 , 0.049 ] [0.330, -0.379, 0.049] [0.330,0.379,0.049]
    • 对于样本 2: [ − 0.464 , 0.243 , 0.220 ] [-0.464, 0.243, 0.220] [0.464,0.243,0.220]

这些结果给出了我们使用 softmax 函数得到的每个类别的预测概率,每个样本的个别交叉熵损失,批次的整体平均交叉熵损失,以及反向传播所需的梯度。梯度中的负值指示了我们应该调整模型参数以减少损失的方向,而正值则建议相反的方向。

class CrossEntropyLoss:
    def softmax(self, x):
        # 通过在每个输入向量中减去最大值来改善 softmax 的数值稳定性。
        # 这通过指数化大的正数来防止潜在的溢出。
        e_x = np.exp(x - np.max(x, axis=1, keepdims=True))
        return e_x / e_x.sum(axis=1, keepdims=True)

    def forward(self, A, Y):
        self.A = A
        self.Y = Y
        self.softmax = self.softmax(A)
        crossentropy = -Y * np.log(self.softmax)
        # 在批次上平均损失
        L = np.sum(crossentropy) / A.shape[0]
        return L

    def backward(self):
        # 计算损失相对于对数(预 softmax 激活)A的梯度
        # 这个梯度还包括在批次上的平均
        dLdA = (self.softmax - self.Y) / self.A.shape[0]
        return dLdA

参考资料:

Logo

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

更多推荐