杰瑞科技汇

Python中crossentropy怎么用?

什么是交叉熵?

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

Python中crossentropy怎么用?-图1
(图片来源网络,侵删)
  • 分类任务:真实标签通常是独热编码的(猫是 [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)

参数解释:

Python中crossentropy怎么用?-图2
(图片来源网络,侵删)
  • 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 提供了多种交叉熵损失函数,以适应不同的场景。

Python中crossentropy怎么用?-图3
(图片来源网络,侵删)

A. BinaryCrossentropy (二元交叉熵)

用于二分类问题。

适用场景:

  • 真实标签是 01
  • 模型最后一层使用 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 的交叉熵损失函数通常将 SoftmaxLog-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'
分享:
扫描分享到社交APP
上一篇
下一篇