原文链接: 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 = Aself.Y = Yself. # todo(根据需要存储额外的属性)N = # todo,这是 A 和 Y 的第一维度C = # todo,这是 A 和 Y 的第二维度# todoreturn Ldef 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} ∂A∂L | 矩阵 | 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=[5−216−10]
这些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} ∂A∂L。这个梯度对于反向传播过程至关重要,使得在训练期间可以更新模型参数。
详解均方误差损失函数:
均方误差(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)=(A−Y)⊙(A−Y)
接下来,我们确定平方误差之和( 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)=ιNT⋅SE(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)=N⋅CSSE(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()=2⋅N⋅C(A−Y)
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)=N⋅C1i=1∑Nj=1∑C(Aij−Yij)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} ∂A∂MSELoss。
∂ 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} ∂A∂MSELoss=2⋅N⋅C(A−Y)
梯度 ∂ M S E L o s s ∂ A \frac{\partial MSELoss}{\partial A} ∂A∂MSELoss 指向损失函数最陡增加的方向。通过向相反方向移动(即,从预测 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} 2⋅N⋅C(A−Y) 公式是通过对预测 A A A 求 MSE 损失函数的导数得到的,考虑了平方误差和平均操作。这个梯度在优化过程中被用来调整模型参数,以最小化损失。
import numpy as npclass MSELoss:def forward(self, A, Y):# 为反向计算存储预测值(A)和真实值(Y)self.A = Aself.Y = Y# 计算预测值和真实值之间的平方误差se = (A - Y) ** 2# 对平方误差求和以得到总的平方误差sse = np.sum(se)# 通过将总的平方误差除以元素数量来计算均方误差mse = sse / (A.shape[0] * A.shape[1])return msedef 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 损失):
- 计算平方误差 ( 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)=(A−Y)⊙(A−Y)=[(300,000−350,000)2(500,000−450,000)2(3−4)2(4−3)2]=[2500×1062500×10611]
- 平方误差之和 ( 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
- 均方误差 ( 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)=N⋅CSSE(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} ∂A∂MSELoss=2⋅N⋅C(A−Y)=2⋅2×2[300,000−350,000500,000−450,0003−44−3]=21[−50,00050,000−11]
这个梯度矩阵提供了如何调整每个预测(价格和卧室数量)以最小化损失的指导。负值表示需要增加预测值,正值表明需要减少预测值以减少误差。
详解交叉熵损失函数:
交叉熵损失是用于基于概率的分类问题最常用的损失函数之一。
交叉熵损失前向方程
首先,我们使用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=1∑Cexp(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)=(−Y⊙log(σ(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:=ιNT⋅H(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} ∂Ai∂H。这涉及到应用链式法则到对数和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=1∑CeAijeAic
步骤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=1∑CYiclog(σ(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*} ∂Aic∂H=∂Aic∂(−Yi1log(σ(Ai1))−Yi2log(σ(Ai2))−...−YiClog(σ(AiC)))=∂Aic∂(−Yi1log(σ(Ai1)))+∂Aic∂(−Yi2log(σ(Ai2)))+...+∂Aic∂(−YiClog(σ(AiC)))=−Yi1∂Aic∂log(σ(Ai1))−Yi2∂Aic∂log(σ(Ai2))−...−YiC∂Aic∂log(σ(AiC))=−k=1∑CYik∂Aic∂log(σ(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}} ∂Aic∂H=−k=1∑CYik∂Aic∂log(σ(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} ∂x∂log(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*} ∂Aic∂log(σ(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*} ∂Aic∂log(σ(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*} ∂Aic∂H=−k=1∑CYik∂Aic∂log(σ(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*} ∂A13∂H=−k=1∑CY1k∂A13∂log(σ(A1k))=−Y11∂A13∂log(σ(A11))−Y12∂A13∂log(σ(A12))−Y13∂A13∂log(σ(A13))=−1(−σ(A13))−0−0=σ(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*} ∂A13∂H=−k=1∑CY1k∂A13∂log(σ(A1k))=−Y11∂A13∂log(σ(A11))−Y12∂A13∂log(σ(A12))−Y13∂A13∂log(σ(A13))=−0−0−1(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=1∑Cezcezk由于分母的原因依赖于所有输入元素。
- 向量关于向量的梯度是一个矩阵。
- 为了简化和巩固这个概念,让我们通过查看一个大小为 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} ∂z1∂a1我们得到:
∂ 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) ∂z1∂a1=(ez1+ez2+ez3)(ez1+ez2+ez3)ez1(ez1+ez2+ez3)−ez1ez1=ez1+ez2+ez3ez1⋅ez1+ez2+ez3ez1+ez2+ez3−ez1=a1(1−a1)
所以我们得到了非常接近于sigmoid导数的东西。
对角线元素以外的元素会发生什么?例如,对于 ∂ a 1 ∂ z 2 \frac{\partial a_1}{\partial z_2} ∂z2∂a1我们得到:
∂ 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 ∂z2∂a1=(ez1+ez2+ez3)20⋅(ez1+ez2+ez3)−ez1ez2=−ez1+ez2+ez3ez1⋅ez1+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} ∂z∂a= a1(1−a1)−a2a1−a3a1−a1a2a2(1−a2)−a3a2−a1a3−a2a3a3(1−a3)
对于损失相对于最终输出的导数 - 我们有一个标量相对于向量的导数,所以结果也将是一个向量:
∂ 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} ∂aL∂L= ∂aL1∂(−c=1∑CyclogaLc)⋮∂aLC∂(−c=1∑CyclogaLc) =− aL1y1⋮aLCyC
记住对于每个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} ∂zL∂L=∂aL∂L∂zL∂aL=− a1y1a2y2a3y3 a1(1−a1)−a2a1−a3a1−a1a2a2(1−a2)−a3a2−a1a3−a2a3a3(1−a3) =−[y1−a1(y1+y2+y3)y2−a2(y1+y2+y3)y3−a3(y1+y2+y3)]=a−y
注意这里的 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=1∑CYiclog(σ(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} ∂A∂Loss=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 = Aself.Y = Yself.softmax = self.softmax(A)crossentropy = -Y * np.log(self.softmax)# 在批次上平均损失L = np.sum(crossentropy) / A.shape[0]return Ldef backward(self):# 计算损失相对于对数(预 softmax 激活)A的梯度# 这个梯度还包括在批次上的平均dLdA = (self.softmax - self.Y) / self.A.shape[0]return dLdA
参考资料:
- 在YouTube上观看视频
- CMU_11785_深度学习导论