当前位置: 首页 > news >正文

深度学习4月22笔记

1、过拟合与欠拟合

在训练深层神经网络时,由于模型参数较多,在数据量不足时很容易过拟合。而正则化技术主要就是用于防止过拟合,提升模型的泛化能力(对新数据表现良好)和鲁棒性(对异常数据表现良好)。

1. 概念认知

这里我们简单的回顾下过拟合和欠拟合的基本概念~

1.1 过拟合

过拟合是指模型对训练数据拟合能力很强并表现很好,但在测试数据上表现较差。

过拟合常见原因有:

  1. 数据量不足:当训练数据较少时,模型可能会过度学习数据中的噪声和细节。

  2. 模型太复杂:如果模型很复杂,也会过度学习训练数据中的细节和噪声。

  3. 正则化强度不足:如果正则化强度不足,可能会导致模型过度学习训练数据中的细节和噪声

1.2 欠拟合

欠拟合是由于模型学习能力不足,无法充分捕捉数据中的复杂关系。

1.3 如何判断

那如何判断一个错误的结果是过拟合还是欠拟合呢?

过拟合

训练误差低,但验证时误差高。模型在训练数据上表现很好,但在验证数据上表现不佳,说明模型可能过度拟合了训练数据中的噪声或特定模式。

欠拟合

训练误差和测试误差都高。模型在训练数据和测试数据上的表现都不好,说明模型可能太简单,无法捕捉到数据中的复杂模式。

2. 解决欠拟合

欠拟合的解决思路比较直接:

  1. 增加模型复杂度:引入更多的参数、增加神经网络的层数或节点数量,使模型能够捕捉到数据中的复杂模式。

  2. 增加特征:通过特征工程添加更多有意义的特征,使模型能够更好地理解数据。

  3. 减少正则化强度:适当减小 L1、L2 正则化强度,允许模型有更多自由度来拟合数据。

  4. 训练更长时间:如果是因为训练不足导致的欠拟合,可以增加训练的轮数或时间.

避免模型参数过大是防止过拟合的关键步骤之一。

模型的复杂度主要由权重w决定,而不是偏置b。偏置只是对模型输出的平移,不会导致模型过度拟合数据。

怎么控制权重w,使w在比较小的范围内?

考虑损失函数,损失函数的目的是使预测值与真实值无限接近,如果在原来的损失函数上添加一个非0的变量

 L_1(\hat{y},y) = L(\hat{y},y) + f(w)

其中f(w)是关于权重w的函数,f(w)>0

要使L1变小,就要使L变小的同时,也要使f(w)变小。从而控制权重w在较小的范围内。

2正则化

L2 正则化通过在损失函数中添加权重参数的平方和来实现,目标是惩罚过大的参数值

设损失函数为 L(\theta),其中 \theta 表示权重参数,加入L2正则化后的损失函数表示为:

L_{\text{total}}(\theta) = L(\theta) + \lambda \cdot \frac{1}{2} \sum_{i} \theta_i^2

其中:

  • L(\theta) 是原始损失函数(比如均方误差、交叉熵等)。

  • \lambda是正则化强度,控制正则化的力度。

  • \theta_i 是模型的第 i 个权重参数。

  • \frac{1}{2} \sum_{i} \theta_i^2 是所有权重参数的平方和,称为 L2 正则化项。

L2 正则化会惩罚权重参数过大的情况,通过参数平方值对损失函数进行约束。

为什么是\frac{\lambda}{2}

假设没有1/2,则对L2 正则化项\theta_i的梯度为:2\lambda\theta_i,会引入一个额外的系数 2,使梯度计算和更新公式变得复杂。

添加1/2后,对2\lambda\theta_i的梯度为:\lambda\theta_i

梯度更新

在 L2 正则化下,梯度更新时,不仅要考虑原始损失函数的梯度,还要考虑正则化项的影响。更新规则为:

\theta_{t+1} = \theta_t - \eta \left( \nabla L(\theta_t) + \lambda \theta_t \right)

其中:

  • \eta是学习率。

  • \nabla L(\theta_t)是损失函数关于参数 \theta_t 的梯度。

  • \lambda \theta_t 是 L2 正则化项的梯度,对应的是参数值本身的衰减。

很明显,参数越大惩罚力度就越大,从而让参数逐渐趋向于较小值,避免出现过大的参数。

权重就会趋向于较小的值

早停

早停是一种在训练过程中监控模型在验证集上的表现,并在验证误差不再改善时停止训练的技术。这样可避免训练过度,防止模型过拟合。pytorch没有现成的API,需要自己写代码实现。

早停法的实现步骤

  1. 将数据集分为训练集和验证集。

  2. 在训练过程中,定期(例如每个 epoch)在验证集上评估模型的性能(如损失或准确率)。

  3. 记录验证集的最佳性能(如最低损失或最高准确率)。

  4. 如果验证集的性能在连续若干次评估中没有改善(即达到预设的“耐心值”),则停止训练。

  5. 返回验证集性能最佳时的模型参数。

早停法的关键参数

  1. 耐心值(Patience):

    • 允许验证集性能不提升的连续次数。

    • 例如,如果耐心值为 5,则当验证集损失连续 5 次没有下降时,停止训练。

  2. 最小改善值(Min Delta):

    • 定义“性能提升”的最小阈值。

    • 例如,如果验证集损失的变化小于该值,则认为性能没有提升。

  3. 恢复最佳权重(Restore Best Weights):

    • 是否在早停时恢复验证集性能最佳时的模型权重。

import torch
import torch.nn as nn
from torch import optim
from torch.utils.data import Dataset, DataLoader, TensorDataset
from sklearn.model_selection import train_test_split
import numpy as np# 1.定义一个简单的神经网络
class simple_net(nn.Module):def __init__(self):super(simple_net, self).__init__()self.fc1 = nn.Linear(20, 10)self.fc2 = nn.Linear(10, 1)self.relu = nn.ReLU()def forward(self, x):x = self.relu(self.fc1(x))x = self.fc2(x)return x# 早停法类
class Early_Stopping():def __init__(self, patience=10, min_delta=0.0):self.patience = patienceself.min_delta = min_deltaself.counter = 0self.best_loss = Noneself.early_stop = Falsedef __call__(self, val_loss):# 如果best_loss 为空,,把损失赋值给最佳if self.best_loss is None:self.best_loss = val_loss# 新损失减少大于最少损失,耐心加一elif val_loss > self.best_loss - self.min_delta:self.counter += 1# 耐心大于等于设定的阈值,把flag置为trueif self.counter >= self.patience:self.early_stop = True# 其他情况,更新最佳损失,计数器置0else:self.best_loss = val_lossself.counter = 0# 生成随机数据
np.random.seed(0)
torch.manual_seed(0)x = torch.randn(1000, 20)
y = torch.randn(1000, 1)x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=0)
# 转换为张量# 创建Dataloader
train_set = TensorDataset(x_train, y_train)
train_loader = DataLoader(train_set, batch_size=32, shuffle=True)
test_set = TensorDataset(x_test, y_test)
test_loader = DataLoader(test_set, batch_size=32, shuffle=True)# 初始化模型、损失函数和优化器
model = simple_net()
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)# 初始化早停
early_stopping = Early_Stopping(patience=10, min_delta=0.001)# 循环次数epochs
epochs = 100
train_losses = []
test_losses = []
for epoch in range(epochs):model.train()epoch_loss = 0for x_batch, y_batch in train_loader:y_pred = model(x_batch)loss = criterion(y_pred, y_batch)optimizer.zero_grad()loss.backward()optimizer.step()epoch_loss += loss.item()train_losses.append(epoch_loss/len(train_loader))# 验证阶段model.eval()epoch_test_loss = 0for x_batch, y_batch in test_loader:y_pred = model(x_batch)loss = criterion(y_pred, y_batch)epoch_test_loss += loss.item()test_losses.append(epoch_test_loss/len(test_loader))if epoch % 5 == 0:print(f'Epoch {epoch}: train_Loss {train_losses[-1]:.4f} test_Loss {test_losses[-1]:.4f}')# 早停法检测early_stopping(test_losses[-1])if early_stopping.early_stop:print('Early stopping')breakprint('Training complete')

 

相关文章:

  • 【Spring】单例作用域下多次访问同一个接口
  • iostat指令介绍
  • go-Casbin使用
  • 游戏引擎学习第239天:通过 OpenGL 渲染游戏
  • Unity Paint In 3D 入门
  • Python线程全面详解:从基础概念到高级应用
  • 鸿蒙生态新利器:华为ArkUI-X混合开发框架深度解析
  • android contentProvider 踩坑日记
  • uniapp 上传二进制流图片
  • 鸿蒙生态:鸿蒙生态校园行心得
  • Windows下Golang与Nuxt项目宝塔部署指南
  • L1-4、如何写出清晰有目标的 Prompt
  • vscode python 代码无法函数跳转的问题
  • 55、Spring Boot 详细讲义(十一 项目实战)springboot应用的登录功能和权限认证
  • 小刚说C语言刷题——1031 温度转化
  • Ubuntu-Linux中vi / vim编辑文件,保存并退出
  • 云账号安全事件分析:黑客利用RAM子账户发起ECS命令执行攻击
  • 联易融科技:以科技赋能驱动经营反转与价值重估
  • 可吸收聚合物:医疗科技与绿色未来的交汇点
  • K8s:概念、特点、核心组件与简单应用
  • 朱守科已任西藏自治区政府党组成员、自治区公安厅党委书记
  • 最高检:去年共受理审查逮捕侵犯知识产权犯罪13486人
  • 经济日报刊文:如何破除“内卷式”竞争
  • 建行深圳市分行原副行长李华峰一审被判15年
  • 中国全国政协-越南祖国阵线中央暨边境省份组织第三次友好交流活动在南宁开幕
  • 湖南平江发生一起意外翻船事件,6人不幸溺亡