什么是交叉熵?
交叉熵是信息论中的一个概念,在机器学习中,它通常被用作损失函数,用来衡量模型预测的概率分布与真实标签分布之间的“差距”。

- 分类任务:真实标签通常是独热编码的(猫是
[1, 0, 0],狗是[0, 1, 0]),模型的输出是每个类别的预测概率(猫9,狗08,鸟02)。 - 目标:我们希望模型的预测概率尽可能接近真实标签,交叉熵越小,代表模型预测得越准。
在 scikit-learn 中的用法
scikit-learn 主要用于传统的机器学习模型,其交叉熵实现通常被称为 对数损失,它与交叉熵在数学上是等价的。
1 log_loss 函数
这是 sklearn.metrics 中的核心函数,用于计算模型的预测概率与真实标签之间的对数损失。
函数签名:
from sklearn.metrics import log_loss log_loss(y_true, y_pred, eps=1e-15, normalize=True, sample_weight=None)
参数解释:

y_true: 真实标签,可以是整数数组(如[0, 2, 1, 2])或独热编码数组(如[[1,0,0], [0,0,1], [0,1,0], [0,0,1]])。y_pred: 模型预测的概率矩阵,形状必须为(n_samples, n_classes)。注意:必须是概率值,不能是硬标签(如0或1)。eps: 一个很小的数,用于防止预测概率为0时导致log(0)出现负无穷。normalize: 如果为True(默认),返回的是平均损失,如果为False,返回的是总损失。
2 代码示例
假设我们有一个三分类问题(猫、狗、鸟)。
import numpy as np
from sklearn.metrics import log_loss
# 1. 准备数据
# 真实标签: 0代表猫, 1代表狗, 2代表鸟
y_true = np.array([0, 2, 1, 2])
# 模型预测的概率矩阵
# 每一行代表一个样本,每一列代表对应类别的预测概率
# 第一个样本[0.9, 0.05, 0.05]表示模型有90%的把握认为是猫
y_pred = np.array([
[0.9, 0.05, 0.05], # 样本1,预测为猫
[0.2, 0.1, 0.7], # 样本2,预测为鸟
[0.3, 0.6, 0.1], # 样本3,预测为狗
[0.05, 0.1, 0.85] # 样本4,预测为鸟
])
# 2. 计算交叉熵(对数损失)
loss = log_loss(y_true, y_pred)
print(f"模型的对数损失: {loss:.4f}")
# 解释计算过程(以第一个样本为例)
# 真实标签是0(猫),所以关注模型预测猫的概率0.9
# 该样本的损失 = -log(0.9) ≈ 0.1054
# log_loss函数会对所有样本的损失求平均
输出:
模型的对数损失: 0.2162
在深度学习框架中的用法
在深度学习(如 TensorFlow/Keras 或 PyTorch)中,交叉熵不仅是评估指标,更是模型在训练过程中直接优化的目标函数。
1 TensorFlow / Keras 中的用法
Keras 提供了多种交叉熵损失函数,以适应不同的场景。

A. BinaryCrossentropy (二元交叉熵)
用于二分类问题。
适用场景:
- 真实标签是
0或1。 - 模型最后一层使用
sigmoid激活函数,输出一个 0 到 1 之间的概率。
代码示例:
import tensorflow as tf
import numpy as np
# 1. 定义损失函数
bce_loss = tf.keras.losses.BinaryCrossentropy()
# 2. 准备数据
# 真实标签
y_true = np.array([0, 1, 1, 0], dtype=float)
# 模型预测的概率 (通过sigmoid激活得到)
y_pred = np.array([0.1, 0.9, 0.8, 0.2], dtype=float)
# 3. 计算损失
loss = bce_loss(y_true, y_pred)
print(f"Keras 二元交叉熵损失: {loss.numpy():.4f}")
B. CategoricalCrossentropy (分类交叉熵)
用于多分类问题,要求标签是独热编码形式。
适用场景:
- 真实标签是独热编码(如
[1, 0, 0])。 - 模型最后一层使用
softmax激活函数,输出一个概率分布(所有类别的概率和为1)。
代码示例:
import tensorflow as tf
import numpy as np
# 1. 定义损失函数
cce_loss = tf.keras.losses.CategoricalCrossentropy()
# 2. 准备数据
# 真实标签 (独热编码)
y_true = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
# 模型预测的概率 (通过softmax激活得到)
y_pred = np.array([
[0.9, 0.05, 0.05],
[0.2, 0.7, 0.1],
[0.1, 0.2, 0.7]
])
# 3. 计算损失
loss = cce_loss(y_true, y_pred)
print(f"Keras 分类交叉熵损失: {loss.numpy():.4f}")
C. SparseCategoricalCrossentropy (稀疏分类交叉熵)
用于多分类问题,但真实标签是整数形式(如 0, 1, 2),无需独热编码,这在实践中更常用,因为它更节省内存。
适用场景:
- 真实标签是整数(如
2代表第三个类别)。 - 模型最后一层使用
softmax激活函数。
代码示例:
import tensorflow as tf
import numpy as np
# 1. 定义损失函数
# from_logits=False 表示y_pred已经是概率分布
# 如果y_pred是未经softmax的原始输出(logits),则设置from_logits=True,数值上更稳定
scce_loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False)
# 2. 准备数据
# 真实标签 (整数形式)
y_true = np.array([0, 1, 2])
# 模型预测的概率 (通过softmax激活得到)
y_pred = np.array([
[0.9, 0.05, 0.05],
[0.2, 0.7, 0.1],
[0.1, 0.2, 0.7]
])
# 3. 计算损失
loss = scce_loss(y_true, y_pred)
print(f"Keras 稀疏分类交叉熵损失: {loss.numpy():.4f}")
2 PyTorch 中的用法
PyTorch 的交叉熵损失函数通常将 Softmax 和 Log-NLLLoss 合二为一,称为 CrossEntropyLoss。
重要特性:
- 它内部已经包含了
LogSoftmax操作。 - 你不需要在模型最后一层手动添加
Softmax。 - 它期望模型的原始输出(称为 logits),而不是概率。
- 真实标签也应该是整数形式(类似 Keras 的
SparseCategoricalCrossentropy)。
函数签名:
torch.nn.CrossEntropyLoss(weight=None, size_average=None, ignore_index=-100, reduce=None, reduction='mean')
reduction: 指定如何聚合单个样本的损失,可以是'mean'(默认,求平均)、`'sum'
