人工智能概念之三:常见的损失函数(交叉熵损失、Hinge损失、0-1损失、MSE、MAE、RMSE、最小二乘法、焦点损失、Dice损失、三元组损失)

损失函数是模型训练和优化的核心度量,其本质是为梯度下降算法提供明确的优化目标 —— 通过计算预测值与真实值的差异,损失函数的梯度(导数)为模型参数更新指明方向(梯度反方向为损失下降最快路径)。不同损失函数的数学形态(如交叉熵的平滑曲线、MSE 的抛物线、MAE 的 V 型结构)决定了梯度特性,进而影响优化效率:线性梯度推动快速收敛,常数梯度导致后期优化放缓,而动态权重设计(如焦点损失)则能自适应调整优化重点,这些特性共同塑造了模型学习的行为模式。

梯度下降介绍网页连接

一、分类任务的损失函数

1.1 交叉熵损失(Cross-Entropy Loss)

数学公式

  • 基础公式:
    L = − ∑ k = 1 K y k ⋅ log ⁡ y ^ L = -\sum_{k=1}^K y_k \cdot \log\hat{y} L=k=1Kyklogy^
    其中 y k y_k yk 是真实标签(one-hot 编码), y ^ \hat{y} y^ 是模型预测的概率。

  • 二分类:
    L = − [ y ⋅ log ⁡ p ^ + ( 1 − y ) ⋅ log ⁡ ( 1 − p ^ ) ] L = -[y \cdot \log\hat{p} + (1-y) \cdot \log(1-\hat{p})] L=[ylogp^+(1y)log(1p^)]
    其中 y y y 是真实标签(0 或 1), p ^ \hat{p} p^ 是模型预测为正类的概率。

  • 多分类(Softmax交叉熵):
    L = − ∑ k = 1 K y k ⋅ log ⁡ ( e z k ∑ i = 1 K e z i ) L = -\sum_{k=1}^K y_k \cdot \log\left(\frac{e^{z_k}}{\sum_{i=1}^K e^{z_i}}\right) L=k=1Kyklog(i=1Keziezk)
    其中 z k z_k zk为模型对第 k k k类的原始输出, y k y_k yk为one-hot标签。

数学原理

  • 信息论基础:交叉熵 H ( p , q ) = − ∑ p ( x ) log ⁡ q ( x ) H(p,q) = -\sum p(x)\log q(x) H(p,q)=p(x)logq(x)衡量两个概率分布 p p p(真实)与 q q q(预测)的差异,当 p = q p=q p=q时交叉熵等于信息熵 H ( p ) H(p) H(p),差异越大交叉熵越大。
  • 最大似然等价性:假设样本服从伯努利分布(二分类)或多项分布(多分类),最大化似然函数等价于最小化交叉熵。以二分类为例,似然函数为:
    L ( θ ) = ∏ p ^ y ( 1 − p ^ ) 1 − y L(\theta) = \prod \hat{p}^y(1-\hat{p})^{1-y} L(θ)=p^y(1p^)1y
    取对数后:
    log ⁡ L ( θ ) = ∑ [ y log ⁡ p ^ + ( 1 − y ) log ⁡ ( 1 − p ^ ) ] = − n ⋅ L C E \log L(\theta) = \sum [y\log\hat{p} + (1-y)\log(1-\hat{p})] = -n \cdot L_{CE} logL(θ)=[ylogp^+(1y)log(1p^)]=nLCE
    因此最小化交叉熵等价于最大化对数似然。

数学图像
二分类损失函数图像
在这里插入图片描述
绘图代码:

import numpy as np  # 导入 NumPy 库,用于数值计算(如数组、矩阵运算等)
import matplotlib.pyplot as plt  # 导入 Matplotlib 的 pyplot 模块,用于绘图
from matplotlib.ticker import FormatStrFormatter  # 导入格式化坐标轴刻度的工具

# 设置中文字体
plt.rcParams["font.family"] = ["SimHei"]  # 设置默认字体为黑体,以支持中文显示
plt.rcParams["axes.unicode_minus"] = False  # 禁用 Unicode 负号显示,使用正常减号 '-' 显示负数

# 定义二分类交叉熵损失函数
def cross_entropy_loss(p_hat, y):
    """
    计算二分类交叉熵损失值。

    参数:
        p_hat (float): 模型预测的概率值,范围在 [0,1]
        y (int): 真实标签,取值为 0 或 1

    返回:
        float: 交叉熵损失值
    """
    epsilon = 1e-10  # 防止对数输入为 0
    p_hat = np.clip(p_hat, epsilon, 1 - epsilon)  # 将概率限制在 [epsilon, 1 - epsilon] 范围内
    return - (y * np.log(p_hat) + (1 - y) * np.log(1 - p_hat))  # 二分类交叉熵公式

# 计算交叉熵损失的导数
def cross_entropy_derivative(p_hat, y):
    """
    计算二分类交叉熵损失对预测概率 p_hat 的导数。

    参数:
        p_hat (float): 模型预测的概率值
        y (int): 真实标签,0 或 1

    返回:
        float: 损失对 p_hat 的导数值
    """
    return p_hat - y  # 二分类交叉熵的导数形式

# Softmax 函数
def softmax(z):
    """
    计算 Softmax 函数值,将 logits 转换为概率分布。

    参数:
        z (np.ndarray): 输入的一维数组,表示各类别的 logit 值

    返回:
        np.ndarray: 各类别对应的概率分布
    """
    exp_z = np.exp(z - np.max(z))  # 减去最大值避免指数爆炸
    return exp_z / exp_z.sum()  # 归一化得到概率分布

# 多分类交叉熵损失函数
def categorical_cross_entropy(y_true, y_pred):
    """
    计算多分类交叉熵损失值。

    参数:
        y_true (np.ndarray): one-hot 编码的真实标签向量
        y_pred (np.ndarray): 模型预测的概率向量(Softmax 输出)

    返回:
        float: 多分类交叉熵损失值
    """
    epsilon = 1e-10
    y_pred = np.clip(y_pred, epsilon, 1 - epsilon)  # 防止 log(0)
    return -np.sum(y_true * np.log(y_pred))  # 多分类交叉熵公式

# 多分类交叉熵损失的导数
def categorical_cross_entropy_derivative(y_true, y_pred):
    """
    计算多分类交叉熵损失对模型输出(logits)的导数。

    参数:
        y_true (np.ndarray): one-hot 编码的真实标签向量
        y_pred (np.ndarray): 模型预测的概率向量(Softmax 输出)

    返回:
        np.ndarray: 损失对 logits 的导数(梯度)
    """
    return y_pred - y_true  # 多分类交叉熵导数形式

# 生成预测概率数据
p_hat = np.linspace(0.01, 0.99, 1000)  # 生成从 0.01 到 0.99 的 1000 个预测概率值

# 计算二分类损失和导数
loss_y0 = cross_entropy_loss(p_hat, y=0)  # y=0 时的损失值
loss_y1 = cross_entropy_loss(p_hat, y=1)  # y=1 时的损失值
derivative_y0 = cross_entropy_derivative(p_hat, y=0)  # y=0 时的导数值
derivative_y1 = cross_entropy_derivative(p_hat, y=1)  # y=1 时的导数值

# 多分类损失和导数计算(固定真实标签为 [1, 0, 0])
z_values = np.linspace(-5, 5, 1000)  # 生成从 -5 到 5 的 1000 个 logit 值
cce_losses = []  # 存储每个 logit 对应的多分类交叉熵损失
cce_derivatives = []  # 存储每个 logit 对应的导数值

for z in z_values:
    logits = np.array([z, 0.0, 0.0])  # 固定其他两个类别的 logit 为 0
    probs = softmax(logits)  # 使用 Softmax 转换为概率分布
    loss = categorical_cross_entropy(y_true=np.array([1, 0, 0]), y_pred=probs)  # 计算损失
    grad = categorical_cross_entropy_derivative(y_true=np.array([1, 0, 0]), y_pred=probs)  # 计算导数
    cce_losses.append(loss)  # 添加到损失列表
    cce_derivatives.append(grad[0])  # 只取第一个 logit 对应的梯度值添加到导数列表

# 创建图像(新增一列用于绘制多分类导数)
fig1, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))  # 创建第一个图形窗口,包含两个子图

# 绘制二分类损失图像
ax1.plot(p_hat, loss_y0, label='y=0时的损失', color='#5DA5DA', linewidth=2)  # 绘制 y=0 的损失曲线
ax1.plot(p_hat, loss_y1, label='y=1时的损失', color='#FAA43A', linewidth=2)  # 绘制 y=1 的损失曲线
ax1.set_xlabel(r'预测概率 $\hat{p}$', fontsize=12)  # 设置 x 轴标签
ax1.set_ylabel('损失值 L', fontsize=12)  # 设置 y 轴标签
ax1.set_title('二分类交叉熵损失函数图像', fontsize=14)  # 设置图像标题
ax1.legend(fontsize=12)  # 添加图例
ax1.grid(True, linestyle='--', alpha=0.7)  # 添加网格线
ax1.xaxis.set_major_formatter(FormatStrFormatter('%.1f'))  # 格式化 x 轴刻度为一位小数

# 绘制二分类导数图像
ax2.plot(p_hat, derivative_y0, label='y=0时的导数', color='#5DA5DA', linewidth=2)  # 绘制 y=0 的导数曲线
ax2.plot(p_hat, derivative_y1, label='y=1时的导数', color='#FAA43A', linewidth=2)  # 绘制 y=1 的导数曲线
ax2.axhline(y=0, color='k', linestyle='--', alpha=0.5)  # 绘制 y=0 的参考线
ax2.set_xlabel(r'预测概率 $\hat{p}$', fontsize=12)  # 设置 x 轴标签
ax2.set_ylabel(r'导数 $\partial L/\partial\hat{p}$', fontsize=12)  # 设置 y 轴标签
ax2.set_title('二分类交叉熵损失函数的导数图像', fontsize=14)  # 设置图像标题
ax2.legend(fontsize=12)  # 添加图例
ax2.grid(True, linestyle='--', alpha=0.7)  # 添加网格线
ax2.xaxis.set_major_formatter(FormatStrFormatter('%.1f'))  # 格式化 x 轴刻度为一位小数

# 创建第二个图形窗口,包含两个子图
fig2, (ax3, ax4) = plt.subplots(1, 2, figsize=(14, 6))

# 绘制多分类交叉熵损失图像
ax3.plot(z_values, cce_losses, label='多分类交叉熵损失', color='#60BD68', linewidth=2)  # 绘制损失曲线
ax3.set_xlabel(r'logit $z_1$', fontsize=12)  # 设置 x 轴标签
ax3.set_ylabel('损失值 L', fontsize=12)  # 设置 y 轴标签
ax3.set_title('多分类交叉熵损失函数图像', fontsize=14)  # 设置图像标题
ax3.legend(fontsize=12)  # 添加图例
ax3.grid(True, linestyle='--', alpha=0.7)  # 添加网格线
ax3.xaxis.set_major_formatter(FormatStrFormatter('%.1f'))  # 格式化 x 轴刻度为一位小数

# 绘制多分类交叉熵损失的导数图像
ax4.plot(z_values, cce_derivatives, label='多分类损失导数', color='#F15854', linewidth=2)  # 绘制导数曲线
ax4.axhline(y=0, color='k', linestyle='--', alpha=0.5)  # 绘制 y=0 的参考线
ax4.set_xlabel(r'logit $z_1$', fontsize=12)  # 设置 x 轴标签
ax4.set_ylabel(r'导数 $\partial L/\partial z_1$', fontsize=12)  # 设置 y 轴标签
ax4.set_title('多分类交叉熵损失函数的导数图像', fontsize=14)  # 设置图像标题
ax4.legend(fontsize=12)  # 添加图例
ax4.grid(True, linestyle='--', alpha=0.7)  # 添加网格线
ax4.xaxis.set_major_formatter(FormatStrFormatter('%.1f'))  # 格式化 x 轴刻度为一位小数

# 调整布局
plt.tight_layout()  # 自动调整子图参数,防止重叠
plt.show()  # 显示所有图形

1.2 Hinge损失(Hinge Loss)

数学公式

  • 二分类:
    L = max ⁡ ( 0 , 1 − y ⋅ y ^ ) L = \max(0, 1 - y \cdot \hat{y}) L=max(0,1yy^)
    其中 y ∈ { − 1 , 1 } y \in \{-1, 1\} y{ 1,1} y ^ \hat{y} y^为模型输出分数。

  • 多分类扩展(One-vs-Rest):
    L = max ⁡ ( 0 , 1 + max ⁡ k ≠ y y ^ k − y ^ y ) L = \max(0, 1 + \max_{k\neq y}\hat{y}_k - \hat{y}_y) L=max(0,1+k=ymaxy^ky^y)

数学原理

  • 几何解释:Hinge损失追求"分类间隔"最大化,当样本分类正确且间隔 y ⋅ y ^ ≥ 1 y \cdot \hat{y} \geq 1 yy^1时损失为0,否则惩罚大小为 1 − y ⋅ y ^ 1 - y \cdot \hat{y} 1yy^
  • 优化目标:对应SVM的优化问题:
    min ⁡ w , b 1 2 ∥ w ∥ 2 + C ∑ max ⁡ ( 0 , 1 − y i ( w T x i + b ) ) \min_{w,b} \frac{1}{2}\|w\|^2 + C\sum \max(0, 1 - y_i(w^Tx_i + b)) w,bmin21w2+Cmax(0,1yi(wTxi+b))
    其中第一项为L2正则化,第二项为Hinge损失, C C C
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值