1.5损失函数

部署运行你感兴趣的模型镜像

思维引导

上一节你已经通过前向传播让网络输出了 “预测结果”(比如判断一张图是数字 3),但怎么知道这个预测 “准不准”?损失函数就是解决这个问题的 “误差尺子”—— 这一节会带你搞懂 “不同任务该用哪把尺子”(比如分类用交叉熵、回归用均方误差)、“尺子怎么量误差”(计算逻辑),以及在 Pytorch 里怎么用代码实现,这是后续 “通过反向传播调参” 的核心依据。

# 小节详细内容

1. 损失函数的定义:衡量误差的 “量化工具”

损失函数(Loss Function)的核心作用是 “计算网络预测结果与真实标签的差距”,输出的 “损失值”(Loss Value)是一个数字:
在这里插入图片描述

模型通过最小化损失函数的值来调整参数,使其输出更接近真实值。

  • 损失值越小:说明预测结果和真实情况越接近(比如预测是 3,真实也是 3,损失值会很小);

  • 损失值越大:说明预测结果和真实情况差距越大(比如预测是 3,真实是 8,损失值会很大)。

    简单说,损失函数就是给网络的 “预测表现” 打分,分数越低越好,而后续的反向传播就是 “根据这个分数调整参数,争取下次考更高分”。

2. 常用损失函数:按任务类型分类(实战重点)

全连接网络主要用于 “分类任务”(如手写数字识别、图片分类)和 “回归任务”(如预测房价、气温),不同任务对应不同的损失函数,视频里重点讲了 2 种最常用的:

(1)交叉熵损失(Cross-Entropy Loss):多分类任务专用

在多分类任务通常使用softmax(softmax是激活函数)将logits转换为概率的形式,所以多分类的交叉熵损失也叫做softmax损失,它的计算方法是:

在这里插入图片描述

其中:

  • yiy_iyi是样本x属于某一个类别的真实概率
  • 而f(x)是样本属于某一类别的预测分数
  • S是softmax激活函数,将属于某一类别的预测分数转换成概率
  • L用来衡量真实值y和预测值f(x)之间差异性的损失结果

例子:

在这里插入图片描述

上图中的交叉熵损失为:

在这里插入图片描述

从概率角度理解,我们的目的是最小化正确类别所对应的预测概率的对数的负值(损失值最小),如下图所示:

在这里插入图片描述

在PyTorch中使用nn.CrossEntropyLoss()实现,如下所示:

import torch
from torch import nn


# 分类损失函数:交叉熵损失使用nn.CrossEntropyLoss()实现。nn.CrossEntropyLoss()=softmax+损失计算
def test01():
	# 设置真实值: 可以是热编码后的结果也可以不进行热编码
	# y_true = torch.tensor([[0, 1, 0], [0, 0, 1]], dtype=torch.float32)
	# 注意:类型必须是64位整型数据
	y_true = torch.tensor([1, 2], dtype=torch.int64)
	y_pred = torch.tensor([[0.2, 0.6, 0.2], [0.1, 0.8, 0.1]], requires_grad=True, dtype=torch.float32)
	# 实例化交叉熵损失,默认求平均损失
	# reduction='sum':总损失
	loss = nn.CrossEntropyLoss()
	# 计算损失结果
	my_loss = loss(y_pred, y_true).detach().numpy()
	print('loss:', my_loss)
(2)交叉熵损失(Cross-Entropy Loss)—二分类专用

在处理二分类任务时,我们不再使用softmax激活函数,而是使用sigmoid激活函数,那损失函数也相应的进行调整,使用二分类的交叉熵损失函数:

L=−ylog⁡y^−(1−y)log⁡(1−y^) L = -y \log \hat{y} - (1 - y) \log(1 - \hat{y}) L=ylogy^(1y)log(1y^)

其中:

  • y是样本x属于某一个类别的真实概率

  • y^\hat{y}y^是样本属于某一类别的预测概率

    • L用来衡量真实值y与预测值y^\hat{y}y^之间差异性的损失结果。

    在这里插入图片描述

在PyTorch中实现时使用nn.BCELoss() 实现,如下所示:

import torch
from torch import nn


def test02():
    # 1 设置真实值和预测值
    y_true = torch.tensor([0, 1, 0], dtype=torch.float32)
    # 预测值是sigmoid输出的结果
    y_pred = torch.tensor([0.6901, 0.5459, 0.2469], requires_grad=True)
    # 2 实例化二分类交叉熵损失
    loss = nn.BCELoss()
    # 3 计算损失
    my_loss = loss(y_pred, y_true).detach().numpy()
    print('loss:', my_loss)
(3)均方误差损失(Mean Squared Error, MSE):回归任务专用
  • Mean Squared Loss/ Quadratic Loss(MSE loss):也被称为L2 loss,或欧氏距离,它以误差的平方和的均值作为距离

  • 适用场景:回归任务(预测连续值),比如预测房价(100 万、150 万)、预测气温(25℃、30℃)、预测股票价格等 —— 这些任务的 “真实标签” 不是离散的类别,而是连续的数字。

  • 核心逻辑:通过 “预测值与真实值的平方差的平均值” 来计算损失,平方的作用是 “放大较大误差”(比如预测值和真实值差 10,平方后是 100;差 1,平方后是 1),让网络更关注大误差的样本。

  • 公式MSE=1N∑i=1N(yi−y^i)2 \text{MSE} = \frac{1}{N} \sum_{i=1}^{N} (y_i - \hat{y}_i)^2 MSE=N1i=1N(yiy^i)2

函数图像:

在这里插入图片描述

其中:

- yi​:第 i 个样本的真实值;
- y^​i​:第 i 个样本的预测值;
- n:样本总数。

特点是:

  • L2 loss也常常作为正则项,对于离群点(outliers)敏感,因为平方项会放大大误差

  • 当预测值与目标值相差很大时, 梯度容易爆炸

    • 梯度爆炸:网络层之间的梯度(值大于1.0)重复相乘导致的指数级增长会产生梯度爆炸
  • 适用于大多数标准回归问题,如房价预测、温度预测等

  • Pytorch 实现与示例:Pytorch 提供nn.MSELoss()类,使用时直接传入 “预测值” 和 “真实值” 即可,无需处理数据类型(默认torch.float)。

    • 代码示例(预测 “房屋面积→房价” 的回归任务):
import torch
import torch.nn as nn

# 1. 定义回归用的全连接网络(输出层1个神经元,预测连续值)
class RegNet(nn.Module):
	def __init__(self):
		super(RegNet, self).__init__()
		self.fc1 = nn.Linear(1, 16)  # 输入层1个特征(房屋面积,如100㎡)
		self.fc2 = nn.Linear(16, 1)   # 输出层1个值(预测房价,如120万)
		self.relu = nn.ReLU()
	
	def forward(self, x):
		x = self.fc1(x)
		x = self.relu(x)
		x = self.fc2(x)
		return x

# 2. 创建网络、损失函数实例
net = RegNet()
criterion = nn.MSELoss()  # 初始化均方误差损失

# 3. 模拟数据:输入(房屋面积)+ 真实标签(房价)
input_area = torch.tensor([[100.0], [120.0]], dtype=torch.float)  # 2个样本,面积100㎡、120㎡
true_price = torch.tensor([[120.0], [150.0]], dtype=torch.float)  # 真实房价120万、150万

# 4. 计算损失
outputs = net(input_area)  # 网络输出预测房价,维度(2,1)
loss = criterion(outputs, true_price)  # 计算MSE损失
print("MSE损失值:", loss.item())  # 输出示例:500.0(初始参数随机,损失值可能较大,合理)
(4)MAE损失函数

**mean absolute loss(MAE)**也被称为L1 Loss,是以绝对误差作为距离

损失函数公式:

MAE=1N∑i=1N∣yi−y^i∣ \text{MAE} = \frac{1}{N} \sum_{i=1}^{N} \left| y_i - \hat{y}_i \right| MAE=N1i=1Nyiy^i

曲线如下图所示:

在这里插入图片描述

特点是:

  • 由于L1 loss具有稀疏性,为了惩罚较大的值,因此常常将其作为正则项添加到其他loss中作为约束。(0点不可导, 产生稀疏矩阵)
  • L1 loss的最大问题是梯度在零点不平滑,导致会跳过极小值
  • 适用于回归问题中存在异常值或噪声数据时,可以减少对离群点的敏感性

在PyTorch中使用nn.L1Loss()实现,如下所示:

import torch
from torch import nn


# 计算inputs与target之差的绝对值
def test03():
    # 1 设置真实值和预测值
    y_pred = torch.tensor([1.0, 1.0, 1.9], requires_grad=True)
    y_true = torch.tensor([2.0, 2.0, 2.0], dtype=torch.float32)
    # 2 实例MAE损失对象
    loss = nn.L1Loss()
    # 3 计算损失
    my_loss = loss(y_pred, y_true).detach().numpy()
    print('loss:', my_loss)
(5)Smooth L1损失函数

smooth L1说的是光滑之后的L1,是一种结合了均方误差(MSE)和平均绝对误差(MAE)优点的损失函数。它在误差较小时表现得像 MSE,在误差较大时则更像 MAE。

Smooth L1损失函数如下式所示:

在这里插入图片描述

其中:𝑥=f(x)−y 为真实值和预测值的差值。

在这里插入图片描述

从上图中可以看出,该函数实际上就是一个分段函数

  • 在[-1,1]之间实际上就是L2损失,这样解决了L1的不光滑问题
  • 在[-1,1]区间外,实际上就是L1损失,这样就解决了离群点梯度爆炸的问题

特点是:

  • 对离群点更加鲁棒:当误差较大时,损失函数会线性增加(而不是像MSE那样平方增加),因此它对离群点的惩罚更小,避免了MSE对离群点过度敏感的问题

  • 计算梯度时更加平滑:与MAE相比,Smooth L1在小误差时表现得像MSE,避免了在训练过程中因使用绝对误差而导致的梯度不连续问题

在PyTorch中使用nn.SmoothL1Loss()计算该损失,如下所示:

import torch
from torch import nn


def test05():
    # 1 设置真实值和预测值
    y_true = torch.tensor([0, 3])
    y_pred = torch.tensor([0.6, 0.4], requires_grad=True)
    # 2 实例smmothL1损失对象
    loss = nn.SmoothL1Loss()
    # 3 计算损失
    my_loss = loss(y_pred, y_true).detach().numpy()
    print('loss:', my_loss)

3. 损失值的 “合理范围” 与注意事项

  • 没有 “固定标准”:损失值的大小取决于任务和数据(比如分类任务初始损失约 2-3,回归任务可能从几百到几万不等),关键看 “训练过程中损失值是否持续下降”—— 只要损失在逐步降低,说明网络在学习;如果损失不下降甚至上升,说明训练有问题(如参数初始化错、学习率太高)。
  • 避免 “只看损失值”:损失小不代表模型 “好用”,比如分类任务损失很小,但在新样本上预测不准(过拟合),这时候需要结合 “准确率” 等指标判断;回归任务则要结合 “真实场景的误差可接受范围”(比如预测房价误差 5 万以内可接受,即使损失值还有 10)。

您可能感兴趣的与本文相关的镜像

PyTorch 2.6

PyTorch 2.6

PyTorch
Cuda

PyTorch 是一个开源的 Python 机器学习库,基于 Torch 库,底层由 C++ 实现,应用于人工智能领域,如计算机视觉和自然语言处理

<think>我们面对的问题是:损失函数值为1.5,准确率只有0.3(即30%),这表明模型性能非常差。我们需要分析原因并采取改善措施。 根据给定的指标,我们可以初步判断模型存在严重问题。损失函数值高(1.5)且准确率低(0.3)通常意味着模型在训练数据上都没有学好,可能处于欠拟合状态,但也可能是其他问题。 步骤1:分析可能的原因 1. **数据问题**:数据量不足、数据质量差(噪声多、特征与标签无关)、数据预处理不当(如缺失值处理不当、特征缩放不一致)或标签错误等。 2. **模型问题**:模型过于简单(欠拟合),或者模型复杂但训练不充分(如训练轮次太少、学习率设置不当)。 3. **损失函数选择不当**:例如,在分类问题中错误地使用了回归的损失函数,或者在多分类问题中二分类的损失函数。 4. **优化问题**:优化器选择不当,学习率设置不合理(过高或过低),导致模型无法收敛。 步骤2:检查数据 - 检查数据预处理:确保数据已经正确清洗(处理缺失值、异常值)、特征工程(特征选择、特征缩放)和划分(训练集、验证集、测试集)。 - 检查特征与标签的关系:通过可视化或相关性分析,确认特征与标签是否存在关联。 - 检查类别分布:如果是分类问题,查看目标类别是否平衡。如果不平衡(如某一类占90%),那么30%的准确率可能比随机猜测还差(随机猜测准确率可能是10%或更低,取决于类别分布)。 步骤3:检查模型和训练过程 - **模型结构**:如果模型过于简单(如线性模型处理非线性问题),则无法捕捉复杂模式,导致欠拟合。 - **损失函数**:确认损失函数是否适合任务。例如: - 二分类问题通常使用二元交叉熵(binary crossentropy)。 - 多分类问题通常使用分类交叉熵(categorical crossentropy)。 - 回归问题使用均方误差(MSE)或平均绝对误差(MAE)。 引用[3]提到,在XGBoost中,二分类的逻辑回归(binary:logistic)返回预测的概率。因此,确保损失函数与任务匹配。 - **优化器和学习率**:检查优化器(如Adam、SGD)和学习率。如果学习率太大,可能导致震荡不收敛;太小则收敛缓慢。可以尝试学习率搜索。 步骤4:改善模型性能 1. **增加模型复杂度**:如果模型太简单,考虑: - 增加神经网络层数或每层的神经元数。 - 使用更复杂的模型(如决策树、随机森林、梯度提升机XGBoost等)。引用[1]提到,集成学习(如XGBoost)可以组合多个模型减少偏差和方差[^1]。 - 添加非线性激活函数(如ReLU)或使用核方法。 2. **调整训练过程**: - 增加训练轮次(epochs),确保模型充分训练。 - 调整学习率:使用学习率调度(如指数衰减)或自适应优化器(如Adam)。 - 检查批量大小(batch size):过小的批量可能导致训练不稳定,过大的批量可能降低收敛速度。一般使用32、64、128等。 3. **特征工程**: - 增加新特征:通过特征组合、多项式特征等提高特征的表现力。 - 特征选择:移除无关特征,减少噪声。但注意,在欠拟合情况下,通常需要增加特征而不是减少。 4. **处理数据问题**: - 收集更多数据。 - 处理类别不平衡:使用过采样(如SMOTE)或欠采样,或在损失函数中引入类别权重。 - 数据增强:如图像分类中的旋转、裁剪等(如果适用)。 5. **尝试不同的模型**: - 如果当前模型是线性模型,尝试非线性模型(如SVM with RBF kernel、随机森林)。 - 引用[2]提供了使用XGBoost的示例代码,我们可以尝试使用XGBoost,并调整其参数[^2]。 - 使用集成方法(如Bagging、Boosting)提高性能。 6. **正则化调整**:如果模型有正则化(如L1、L2),且我们怀疑欠拟合,可以尝试降低正则化强度(如减小正则化系数λ),甚至移除正则化。 步骤5:监控与调试 - 在训练过程中监控训练集和验证集的损失和准确率。如果训练集上的损失不下降,则可能是欠拟合;如果训练集损失下降但验证集不降,则可能是过拟合。 - 使用交叉验证评估模型性能。 - 进行超参数调优:使用网格搜索或随机搜索调整关键参数。 示例改进步骤(以神经网络为例): 1. 将单层神经网络改为多层(如3层)并加入非线性激活函数。 2. 将学习率设置为0.001,使用Adam优化器。 3. 训练更多轮次(如100轮),并监控训练集和验证集的损失。 4. 如果训练集损失下降但验证集不降,则添加Dropout层或L2正则化防止过拟合。 对于损失函数值为1.5且准确率0.3的极端情况,我们首先应检查数据预处理和损失函数是否正确。例如,一个常见的错误是在多分类问题中使用了二分类的损失函数。 总结:从简单到复杂逐步调整,确保每一步都有评估。如果经过上述调整,模型性能仍然很差,可能需要重新审视问题定义或数据收集过程。 §§相关问题§§ 1. 如何选择合适的损失函数用于分类任务? 2. 在训练过程中如何监控和诊断模型的性能? 3. 处理类别不平衡有哪些常用方法? 4. 如何调整学习率以优化模型训练? 5. 特征工程有哪些技巧可以提升模型性能?</think>### 模型性能分析与改进方案(损失值1.5,准确率0.3) #### 问题诊断 当损失函数值为1.5且准确率仅0.3时,表明模型存在严重性能问题: 1. **损失值过高**:交叉熵损失的理论下限为0(完美预测),1.5远高于合理范围(正常值应<0.5)[^3] 2. **准确率过低**:0.3甚至可能低于随机猜测(二分类随机猜测基准为0.5) 3. **核心问题**:模型完全未学习到数据规律,属于**严重欠拟合** #### 根本原因分析 ```mermaid graph LR A[高损失+低准确率] --> B[数据问题] A --> C[模型问题] A --> D[训练问题] B --> B1[特征与标签无关] B --> B2[数据预处理错误] C --> C1[模型过于简单] C --> C2[损失函数选择错误] D --> D1[训练轮次不足] D --> D2[学习率设置不当] ``` #### 改进方案(按优先级排序) 1. **验证数据质量**(首要步骤) - 检查特征与标签相关性:计算特征重要性(XGBoost的`feature_importances_`) - 确认数据预处理: - 分类任务中标签需为整数编码(非one-hot) - 连续特征需标准化(`StandardScaler`) ```python from sklearn.preprocessing import StandardScaler scaler = StandardScaler() X_train = scaler.fit_transform(X_train) ``` 2. **调整损失函数**(关键) - 确认任务类型与损失函数匹配: - **二分类**:使用`binary:logistic`(返回概率)[^3] - **多分类**:使用`multi:softmax` + 设置`num_class` - 示例修正: ```python # 错误示例(多分类用二分类损失) model = xgb.XGBClassifier(objective='binary:logistic') # 正确示例(假设10分类) model = xgb.XGBClassifier(objective='multi:softmax', num_class=10) ``` 3. **增加模型复杂度** - 提升树模型能力: ```python model = xgb.XGBClassifier( max_depth=8, # 增加深度(默认6) n_estimators=200, # 增加树数量(默认100) learning_rate=0.1 # 适当提高学习率 ) ``` - 切换到更复杂模型: - 使用深度学习框架(如PyTorch构建3层神经网络) - 集成方法(如随机森林+XGBoost融合)[^1] 4. **优化训练过程** - 延长训练轮次(epochs≥100) - 动态学习率调整(XGBoost示例): ```python model = xgb.XGBClassifier( learning_rate=0.01, subsample=0.8, colsample_bytree=0.8, early_stopping_rounds=10 # 防止过拟合 ) model.fit(X_train, y_train, eval_set=[(X_test, y_test)]) ``` 5. **特征工程增强** - 创建交互特征:`PolynomialFeatures(degree=2)` - 添加统计特征:滑动窗口均值/方差 - 领域知识特征:如时间序列的周期性特征 #### 验证改进效果 使用交叉验证监控指标: ```python from sklearn.model_selection import cross_val_score scores = cross_val_score(model, X, y, cv=5, scoring='accuracy') print(f"交叉验证准确率: {scores.mean():.2f}±{scores.std():.2f}") ``` 目标:**损失值降至0.5以下,准确率提升至0.7以上** > **关键检查点**:若改进后训练集准确率仍低于0.5,表明数据本身存在根本问题,需重新检查数据收集和标注过程[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Peter_Monster

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值