交叉熵损失公式与手动计算

1、交叉熵损失函数
交叉熵的公式有多种形式,一般写作
loss=−1n∑j=1nyjlnaj(∗∗) loss=-\frac{1}{n}\sum_{j=1}^{n}y_jlna_j (**) loss=n1j=1nyjlnaj
lossj=−yjlnaj(1) loss_j=-y_jlna_j (1) lossj=yjlnaj1

lossjloss_jlossj表示第j个样本的损失。aja_jaj表示softmax函数输出。yjy_jyj表示第j个样本的真实标签,为one-hot形式,所以上式可以变为
lossj=−yjlnexp(zj)∑exp(zm)=−yjzj+yjln∑exp(zm)=−zj+ln∑exp(zm) loss_j=-y_jln\frac{exp(z_j)}{\sum{exp(z_m)}} \\=-y_jz_j+y_jln\sum{exp(z_m)}\\ =-z_j+ln\sum{exp(z_m)} lossj=yjlnexp(zm)exp(zj)=yjzj+yjlnexp(zm)=zj+lnexp(zm)
其中yjy_jyj选取1所在的位置,所以有另一种表示:
lossi=−x[class]+ln∑j=1nexp(x[j])(2) loss_i=-x[class]+ln\sum_{j=1}^{n}exp(x[j]) (2) lossi=x[class]+lnj=1nexp(x[j])2
实际计算如下:
真实标签,label:[1, 0, 0]
预测标签,pred:[ [-0.7715, -0.6205, -0.2562]]
利用公式(2),
loss=−x[0]+log∑jexp(x[j])=0.7715+log[exp(−0.7715)+exp(−0.6205)+exp(−0.2562)]=1.344726 loss=-x[0]+log\sum_{j}exp(x[j])\\=0.7715+log[exp(-0.7715)+exp(-0.6205)+exp(-0.2562)]\\=1.344726 loss=x[0]+logjexp(x[j])=0.7715+log[exp(0.7715)+exp(0.6205)+exp(0.2562)]=1.344726
利用公式(1),
pred_softmax=softmax(pred)=[[0.2606,0.3031,0.4363]]pred_log=[[−1.3447,−1.1937,−0.8294]]res=label∗pred_log=[1,0,0]∗[[−1.3447,−1.1937,−0.8294]]=[[−1.3447,0,0]]=−1.3447 pred\_softmax=softmax(pred)=[[0.2606,0.3031,0.4363]] \\ pred\_log = [[-1.3447,-1.1937,-0.8294]]\\ res=label*pred\_log=[1,0,0]*[[-1.3447,-1.1937,-0.8294]]\\=[[-1.3447,0,0]]=-1.3447 pred_softmax=softmax(pred)=[[0.2606,0.3031,0.4363]]pred_log=[[1.3447,1.1937,0.8294]]res=labelpred_log=[1,0,0][[1.3447,1.1937,0.8294]]=[[1.3447,0,0]]=1.3447
所以有loss=−res=1.3447loss=-res=1.3447loss=res=1.3447。可以看到,两种方法的计算结果相同。
2、Pytorch中的使用
Pytorch中使用交叉熵损失有三种方法,分别为nn.CrossEntropy、nn.NLLLoss、手动写。

y_pred = torch.tensor([[-0.7715, -0.6205, -0.2562], [-0.7627, -0.6284, -0.2547]]) # [B, num_labels]
y_label = torch.tensor([[1, 0, 0], [1, 0, 0]])  # [B, num_labels]
y_label_1 = torch.tensor([0, 0])  #


y_pred_softmax = nn.Softmax(dim=-1)(y_pred)
y_pred_log=torch.log(y_pred_softmax)

loss_1 = nn.NLLLoss()(y_pred_log, y_label_1)
print('NLLLoss计算出的loss:{}'.format(loss_1)) # 1.3406

loss_2 = nn.CrossEntropyLoss()(y_pred, y_label_1)
print('CrossEntropy计算出的loss:{}'.format(loss_2)) # 1.3406

loss_3 = -torch.mean(torch.sum(y_pred_log*y_label.float(), dim=-1))  # [-1.3447, -1.3365]
print('手动写计算出的loss:{}'.format(loss_3))  # 1.3406

由上面代码可以得到,loss_1=loss_2=loss_3。
上面计算了两个样本,loss_3在求-mean之前的结果为[-1.3447, -1.3365],1.3447即为在第一部分求得的loss结果,同样可以看出,最终的loss=1.3446,是由多个样本求-mean得到的,对应公式(**)。

### 交叉熵损失函数的数学公式及其解析 #### 数学公式的定义 交叉熵损失函数是一种广泛应用于分类任务中的损失函数,其核心目标是最小化预测分布 \( q \) 和真实分布 \( p \) 之间的差异。对于单个样本而言,交叉熵损失函数的形式如下: \[ L = -\sum_{i=1}^{C} y_i \cdot \log(\hat{y}_i) \] 其中: - \( C \) 表示类别总数; - \( y_i \in \{0, 1\} \) 是第 \( i \) 类的真实标签(即 one-hot 编码),如果该类为目标类别,则取值为 1,否则为 0; - \( \hat{y}_i \) 是模型对该类别的预测概率。 当扩展到多个样本时,通常会计算所有样本上的平均损失,因此最终形式为: \[ Loss = -\frac{1}{N}\sum_{n=1}^{N}\sum_{i=1}^{C} y_i^n \cdot \log(\hat{y}_i^n) \] 这里 \( N \) 表示样本数量,\( n \) 遍历每一个样本[^1]。 --- #### 公式解析 ##### 1. **信息量的概念** 在信息论中,事件发生的不确定性可以通过信息量来描述。假设某个事件的发生概率为 \( P(x) \),那么它的信息量可以用下述公式表示: \[ I(x) = -\log(P(x)) \] 这意味着越不可能发生的事情携带的信息越多,而几乎必然会发生的事情几乎没有额外信息[^2]。 ##### 2. **交叉熵的核心意义** 交叉熵本质上是对两个概率分布之间距离的一种度量方式。具体来说,在机器学习领域中,它用来衡量模型预测的概率分布 \( q \) 和真实分布 \( p \) 的差距。通过最小化这个差距,可以让模型更好地拟合数据。 给定真实的分布 \( p \) 和预测的分布 \( q \),它们之间的交叉熵可以写成: \[ H(p, q) = -\sum_{x} p(x)\log(q(x)) \] 这正是前面提到的单样本情况下交叉熵损失函数的基础形式[^4]。 ##### 3. **为什么选择交叉熵?** 相比其他可能的选择(比如均方误差 MSE 或者绝对误差 MAE),交叉熵具有以下几个优点: - 它能够更有效地捕捉离散型随机变量间的差异。 - 当结合激活函数如 Softmax 使用时,它可以加速收敛速度,并缓解梯度消失问题。 --- #### 实现代码示例 以下是基于 Python 的简单实现,展示如何手动计算交叉熵损失值。 ```python import numpy as np def cross_entropy_loss(y_true, y_pred): """ 计算交叉熵损失 参数: y_true (numpy array): 真实标签向量 (one-hot编码), 形状为 [batch_size, num_classes] y_pred (numpy array): 模型输出的概率分布, 形状为 [batch_size, num_classes] 返回: float: 平均交叉熵损失 """ epsilon = 1e-15 # 添加一个小常数防止 log(0) y_pred_clipped = np.clip(y_pred, epsilon, 1 - epsilon) # 将预测值裁剪至有效范围 loss = -np.sum(y_true * np.log(y_pred_clipped)) / len(y_true) return loss # 测试例子 true_labels = np.array([[1, 0, 0], [0, 1, 0]]) # two samples with true labels being class 0 and 1 respectively predicted_probs = np.array([[0.8, 0.1, 0.1], [0.2, 0.7, 0.1]]) loss_value = cross_entropy_loss(true_labels, predicted_probs) print(f"Cross Entropy Loss: {loss_value}") ``` --- #### 总结 综上所述,交叉熵不仅是一个理论工具,也是实践过程中不可或缺的一部分。通过对数运算以及加权求和的方式构建而成,使得它非常适合处理涉及概率估计的任务,特别是监督学习下的分类场景[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值