PyTorch 底子学习(17)- 过拟合

  金牌会员 | 2024-8-31 17:16:51 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 993|帖子 993|积分 2979

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
系列文章:
《PyTorch 底子学习》文章索引
先容

在深度学习中,过拟合是一个常见的题目,它会导致模型在练习数据上体现很好,但在新数据上的体现却很差。为了进步模型的泛化能力,防止过拟合是至关重要的。本教程将详细先容过拟合的概念、常用的防止过拟合的方法,并展示怎样在 PyTorch 中实施这些方法。
什么是过拟合?

过拟合发生在模型过于复杂时,即模型包罗的参数数目远凌驾练习数据的量。当模型在练习数据上体现得非常好时,它可能只是“记着”了这些数据的噪声或细节,而不是学到了数据的普遍规律。这会导致模型在遇到新数据时无法很好地猜测,从而体现不佳。
典型的过拟合体现:


  • 练习集上的损失很低:模型在练习集上体现得很好。
  • 验证集上的损失较高:模型在验证集或测试集上的体现不如练习集。
防止过拟合的常用方法

防止过拟合的方法有许多,以下是一些常用的技能:


  • 正则化(Regularization):通过在损失函数中添加额外的惩罚项,限制模型的复杂度。
  • Dropout:在练习过程中随机丢弃部分神经元,淘汰模型对某些特征的依赖。
  • 数据加强(Data Augmentation):通过对练习数据进行变换,增加数据的多样性。
  • 提前停止(Early Stopping):在验证集上监控模型的性能,当性能不再提升时停止练习。
  • 淘汰模型复杂度:通过淘汰参数数目或层数来简化模型。
在 PyTorch 中防止过拟合的方法与实例

我们将分别解说怎样在 PyTorch 中利用这些技能,并提供具体的代码示例。
L2 正则化(权重衰减)

L2 正则化通过在损失函数中加入所有权重的平方和的惩罚项,鼓励模型参数的巨细趋向于零,从而防止模型变得过于复杂。在 PyTorch 中,可以通过在优化器中设置 weight_decay 参数来实现。
  1. import torch.optim as optim
  2. # 在优化器中设置 weight_decay 来进行 L2 正则化
  3. optimizer = optim.SGD(model.parameters(), lr=0.01, weight_decay=1e-4)
复制代码
参数阐明


  • weight_decay:L2 正则化的系数,值越大,正则化效果越强。
Dropout

Dropout 是一种防止过拟合的技能,通过在练习过程中随机丢弃部分神经元,使得模型不会对某些特定路径过度依赖。PyTorch 中通过 torch.nn.Dropout 层来实现 Dropout。
  1. import torch.nn as nn
  2. import torch.nn.functional as F
  3. class DropoutModel(nn.Module):
  4.     def __init__(self):
  5.         super(DropoutModel, self).__init__()
  6.         self.fc1 = nn.Linear(10, 50)
  7.         self.dropout = nn.Dropout(p=0.5)
  8.         self.fc2 = nn.Linear(50, 1)
  9.    
  10.     def forward(self, x):
  11.         x = F.relu(self.fc1(x))
  12.         x = self.dropout(x)  # 在训练时以0.5的概率丢弃神经元
  13.         x = self.fc2(x)
  14.         return x
复制代码
参数阐明


  • p:Dropout的概率,表示每个神经元被丢弃的概率。
数据加强(Data Augmentation)

数据加强通过对练习数据进行随机变换,增加数据的多样性,从而使模型在差别的数据上体现更好。PyTorch 中通常利用 torchvision.transforms 来进行数据加强。
  1. import torchvision.transforms as transforms
  2. from torchvision.datasets import CIFAR10
  3. from torch.utils.data import DataLoader
  4. # 定义数据增强操作
  5. transform = transforms.Compose([
  6.     transforms.RandomHorizontalFlip(),
  7.     transforms.RandomRotation(10),
  8.     transforms.ToTensor()
  9. ])
  10. # 应用数据增强到训练数据
  11. train_dataset = CIFAR10(root='./data', train=True, download=True, transform=transform)
  12. train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
复制代码
常见的数据加强操作


  • RandomHorizontalFlip():随机程度翻转图片。
  • RandomRotation(degrees):随机旋转图片一定角度。
提前停止(Early Stopping)

提前停止是在练习过程中监控验证集上的损失,当损失不再下降时停止练习,以制止过拟合。这通常通过手动实现,监控模型在验证集上的体现。
  1. best_loss = float('inf')
  2. patience = 10  # 在没有提升的情况下等待的轮数
  3. counter = 0
  4. for epoch in range(100):
  5.     model.train()
  6.     optimizer.zero_grad()
  7.     output = model(train_data)
  8.     loss = criterion(output, train_labels)
  9.     loss.backward()
  10.     optimizer.step()
  11.    
  12.     # 验证阶段
  13.     model.eval()
  14.     val_output = model(val_data)
  15.     val_loss = criterion(val_output, val_labels)
  16.     if val_loss < best_loss:
  17.         best_loss = val_loss
  18.         counter = 0  # 重置计数器
  19.         torch.save(model.state_dict(), 'best_model.pth')  # 保存最佳模型
  20.     else:
  21.         counter += 1
  22.    
  23.     if counter >= patience:
  24.         print("Early stopping!")
  25.         break
复制代码
参数阐明


  • patience:当验证集上的损失不再改善时,允许的最大等候轮数。
淘汰模型复杂度

淘汰模型复杂度是最直接的防止过拟合的方法之一。这可以通过淘汰模型的层数、每层的神经元数目或淘汰模型参数的数目来实现。
  1. class SimpleModel(nn.Module):
  2.     def __init__(self):
  3.         super(SimpleModel, self).__init__()
  4.         self.fc1 = nn.Linear(10, 20)  # 减少神经元数量
  5.         self.fc2 = nn.Linear(20, 1)
  6.    
  7.     def forward(self, x):
  8.         x = F.relu(self.fc1(x))
  9.         x = self.fc2(x)
  10.         return x
复制代码
思路


  • 在设计模型时,根据数据的复杂度合理设计网络布局,制止利用过于复杂的模型。
神经网络防备过拟合

我们可以通过一个更复杂的神经网络示例,结合多种防止过拟合的方法来进行演示。以下是一个包罗 L2 正则化、Dropout 和淘汰复杂度的神经网络实例。
  1. import torch
  2. import torch.nn as nn
  3. import torch.optim as optim
  4. import torch.nn.functional as F
  5. class ComplexModel(nn.Module):
  6.     def __init__(self):
  7.         super(ComplexModel, self).__init__()
  8.         self.fc1 = nn.Linear(100, 50)
  9.         self.fc2 = nn.Linear(50, 20)
  10.         self.fc3 = nn.Linear(20, 10)
  11.         self.dropout = nn.Dropout(p=0.5)  # Dropout
  12.         self.output = nn.Linear(10, 1)
  13.    
  14.     def forward(self, x):
  15.         x = F.relu(self.fc1(x))
  16.         x = self.dropout(F.relu(self.fc2(x)))  # 使用 Dropout
  17.         x = F.relu(self.fc3(x))
  18.         x = self.output(x)
  19.         return x
  20. # 初始化模型
  21. model = ComplexModel()
  22. # 使用 L2 正则化的优化器
  23. optimizer = optim.Adam(model.parameters(), lr=0.001, weight_decay=1e-4)
  24. # 损失函数
  25. criterion = nn.MSELoss()
  26. # 模拟训练
  27. for epoch in range(100):
  28.     optimizer.zero_grad()
  29.     output = model(torch.randn(64, 100))
  30.     loss = criterion(output, torch.randn(64, 1))
  31.     loss.backward()
  32.     optimizer.step()
复制代码
在这个示例中,我们利用了一个多层神经网络模型,并结合了 L2 正则化(通过 weight_decay)、Dropout 层和适度淘汰神经元数目标策略来防止过拟合。
PyTorch 自带模型中利用防止过拟合

PyTorch 自带了一些预练习的模型(如 torchvision.models),你可以在这些模型中利用上述技巧来防止过拟合。
示例:在 ResNet 中利用 L2 正则化和 Dropout
  1. import torchvision.models as models
  2. # 加载预训练的 ResNet 模型
  3. model = models.resnet18(pretrained=True)
  4. # 替换最后一层,以适应你的任务
  5. model.fc = nn.Sequential(
  6.     nn.Dropout(p=0.5),  # 添加 Dropout 层
  7.     nn.Linear(model.fc.in_features, 10)  # 假设有10个类别
  8. )
  9. # 使用 L2 正则化
  10. optimizer = optim.SGD(model.parameters(), lr=0.001, weight_decay=1e-4)
复制代码
在这个示例中,我们利用了预练习的 ResNet 模型,并在最后一层添加了 Dropout
层,同时利用了 L2 正则化来练习模型。
总结

防止过拟合是深度学习中的关键题目,通过合理利用正则化、Dropout、数据加强、提前停止等技能,可以明显提升模型的泛化能力。PyTorch 提供了机动的接口,可以很方便地将这些技能应用到你的模型中。把握这些技巧,将资助你在现实项目中练习出更加妥当和高效的模型。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表