理解交叉熵损失(Cross-Entropy)

理解交叉熵损失

字符集编码

字符集编码的意义在于将数据集进行有效压缩。
假设在一个文档中只出现了a、b、c、d、e 5种字符,其占比如下表:

字符abcde
占比0.10.10.20.20.4

最容易想到的编码方式,5个字符,需要3个bit位,故:

字符abcde单个字符编码长度期望值
编码0000010100111003

但是这并不是最优的编码方式,例如:

字符abcde单个字符编码长度期望值
编码111111101101002.2

这种编码方式的特点就在于,占比高的字符编码长度尽可能短,同时要满足不能出现歧义的限制条件。
那么给定一个数据集之后,究竟每个字符编码是什么,编码应该多长呢?
给定字符集 X={x} , 满足 p(x) 的概率分布,设字符x的最优编码长度为 l(x) ,设 H(X) 为字符编码长度期望,则根据香农信息理论,最优编码情况下有以下结论:

l(x)=log1p(x)

H(X)=xp(x)log1p(x)

字符集编码先介绍这么多,一会儿会用到。

相对熵

相对熵是一种用来评价两种概率分布差异程度的方法。
给定字符集 X={x} ,你通过某种方法预测其概率分布为 q(x) ,但是其真实的概率分布为 p(x) ,那么怎么评价二者的差异呢?如何评价 q(x) 偏离真实分布 p(x) 的程度呢?
可以通过字符集编码长度与最优编码方案下的编码长度的差来度量。
最优编码方案下的字符编码长度为:

l(x)=log1p(x)

根据预测概率分布 q(x) 进行编码,字符编码长度为:
l(x)=log1q(x)

最优编码方案下字符编码长度期望为:
H(X)=xp(x)log1p(x)

根据预测概率分布 q(x) 进行编码,实际获得的编码长度期望为:
H(X)=xp(x)log1q(x)

很显然:
H(X)>H(X)

因为最优编码是编码长度期望最短的;
定义:
DKL(P||Q)=H(X)H(X)

可得:
DKL(P||Q)=xp(x)log(p(x))xp(x)log(q(x))

DKL(P||Q) 就是相对熵,从公式可以看出,相对熵是不对称的。

交叉熵

交叉熵是从相对熵而来的。
在机器学习领域,多分类问题很常见,在很多深度学习模型当中,网络的输出层就是一个 softmax 层,对于 N 分类问题,输出是一个N维的向量,向量元素介于 [0,1] 之间,且元素累加和为1(这是 softmax 性质所决定的);
softmax 层输出向量视为预测类别的概率分布 q(x) ,用真实类别标签构造真实的类别概率分布 p(x) (例如,令真实类别概率为1,其余类别概率为0),那么相对熵 DKL(P||Q) 就可以评价预测结果 q(x) 的好坏了,我们只需要最小化它就好了。
既然可以用相对熵作为代价函数,那为什么还要引出交叉熵?
因为在 DKL(P||Q) 的公式中:

DKL(P||Q)=xp(x)log(p(x))xp(x)log(q(x))

xp(x)log(p(x)) 不涉及预测结果 q(x) ,是一个常数项,可以把这一项去掉简化模型。
于是只剩下:
xp(x)logq(x)

其实就是:
H(X)=xp(x)log1q(x)

也就是说,交叉熵等于基于预测概率分布 q(x) 对符合 p(x) 分布的字符集进行编码之后的平均字符编码长度,通过最小化交叉熵可以使 q(x) 逼近真实分布 p(x) ,也就使得预测模型更优。

延伸

既然是让预测概率分布 q(x) 逼近真实概率分布 p(x) ,你可能马上就想到,直接让代价函数等于 (q(x)p(x))2 不就好了,为什么搞得这么复杂?
因为二次代价函数有一个缺点,而交叉熵损失代价函数没有,请看传送门

说明

如有错误,敬请指正。

### 交叉熵损失函数定义 交叉熵损失函数是一种常用的机器学习目标函数,用于衡量模型预测的概率分布与真实标签之间的差异。其核心思想是通过最小化预测概率分布与真实分布之间的距离来优化模型性能。 #### 数学公式 假设 \( y \) 是真实的概率分布向量,\( p \) 是模型预测的概率分布向量,则交叉熵损失可以表示为: \[ H(y, p) = -\sum_{i} y_i \cdot \log(p_i) \] 其中: - \( i \) 表示类别索引; - \( y_i \) 是第 \( i \) 类的真实标签值(通常是一个 one-hot 编码); - \( p_i \) 是模型对第 \( i \) 类别的预测概率[^1]。 当应用于分类问题时,通常会结合 softmax 函数一起使用以将原始输出转换成有效的概率分布。 --- ### PyTorch 中的实现 在 PyTorch 中,`torch.nn.CrossEntropyLoss()` 方法封装了交叉熵损失函数的功能。它内部自动应用 `log_softmax` 和负对数似然 (NLL) 损失计算。以下是其实现方式的一个简化版本: ```python import torch import torch.nn as nn # 假设输入数据和目标标签 input_tensor = torch.randn(3, 5, requires_grad=True) # 输入张量形状为 [batch_size, num_classes] target_tensor = torch.empty(3, dtype=torch.long).random_(5) # 目标张量形状为 [batch_size] # 创建交叉熵损失实例 loss_function = nn.CrossEntropyLoss() # 计算损失 output_loss = loss_function(input_tensor, target_tensor) print(output_loss.item()) ``` 上述代码中,`input_tensor` 的每一行代表样本属于各个类别的未归一化的分数(即 logits),而 `target_tensor` 则存储对应的真实类别索引[^3]。 --- ### TensorFlow/Keras 中的实现 在 TensorFlow 或 Keras 中,可以通过 `tf.keras.losses.CategoricalCrossentropy` 来实现类似的交叉熵损失功能。如果使用的是稀疏形式的目标标签,则可以选择 `SparseCategoricalCrossentropy`。下面展示了一个简单的例子: ```python import tensorflow as tf # 构造模拟数据 y_true = [[0, 1, 0], [0, 0, 1]] # 真实标签采用 one-hot 编码 y_pred = [[0.05, 0.95, 0], [0.1, 0.8, 0.1]] # 预测概率分布 # 初始化损失对象 cce = tf.keras.losses.CategoricalCrossentropy() loss_value = cce(y_true, y_pred) print('Categorical Cross Entropy:', loss_value.numpy()) # 如果目标是以整数值给出的情况 sparse_cce = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False) s_y_true = [1, 2] # 对应于上面的 one-hot 形式 s_loss_value = sparse_cce(s_y_true, y_pred) print('Sparse Categorical Cross Entropy:', s_loss_value.numpy()) ``` 这里需要注意的一点是参数 `from_logits` 是否设置为 True 将决定是否需要手动调用 softmax 进行预处理[^2]。 --- ### Numpy 手动实现 为了更清楚理解整个流程,还可以借助 NumPy 提供的手动实现方案作为参考: ```python import numpy as np def cross_entropy(y_true, y_pred): """ :param y_true: 真实标签矩阵 shape=(m_samples, n_classes),one-hot 编码 :param y_pred: 预测概率矩阵 shape=(m_samples, n_classes) :return: 平均交叉熵损失 """ m = y_true.shape[0] log_likelihood = -np.log(y_pred[np.arange(m), np.argmax(y_true, axis=1)] + 1e-8) loss = np.sum(log_likelihood) / m return loss # 测试案例 y_t = np.array([[0, 1, 0], [0, 0, 1]]) y_p = np.array([[0.05, 0.95, 0], [0.1, 0.8, 0.1]]) result = cross_entropy(y_t, y_p) print("Manual Cross Entropy:", result) ``` 此段脚本展示了如何利用基本运算构建完整的交叉熵评估逻辑。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值