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

PyTorch深度学习框架60天进阶计划第11天:过拟合解决方案深度实践

PyTorch深度学习框架60天进阶计划第11天:过拟合解决方案深度实践

学习目标

掌握Dropout配置策略、L2正则化实现、Early Stopping机制及模型检查点保存方法

核心要点:

  1. CIFAR-10数据集预处理与验证集划分
  2. Dropout概率对模型泛化能力的影响实验
  3. 权重衰减(L2正则化)与Early Stopping联合应用
  4. 模型检查点保存与恢复技术

一、CIFAR-10数据集处理与验证机制构建

1. 数据加载与标准化处理

import torch 
import torchvision 
import torchvision.transforms as transforms 
from torch.utils.data import DataLoader, random_split 
 
数据预处理(含标准化)
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))  # 三通道标准化 
])
 
加载完整数据集 
full_dataset = torchvision.datasets.CIFAR10(
    root='./data', train=True, download=True, transform=transform 
)
 
划分训练集(80%)、验证集(20%)
train_size = int(0.8 * len(full_dataset))
val_size = len(full_dataset) - train_size 
train_dataset, val_dataset = random_split(full_dataset, [train_size, val_size])
 
测试集加载 
test_dataset = torchvision.datasets.CIFAR10(
    root='./data', train=False, download=True, transform=transform 
)
 
数据加载器配置 
train_loader = DataLoader(train_dataset, batch_size=128, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=128)
test_loader = DataLoader(test_dataset, batch_size=128)

2. 数据集统计信息

数据集样本数量类别数图像尺寸通道数
训练集40,0001032×323
验证集10,0001032×323
测试集10,0001032×323

二、模型构建与过拟合解决方案实现

1. 基准CNN模型(含Dropout层)

import torch.nn as nn 
 
class CIFAR10Classifier(nn.Module):
    def __init__(self, dropout_p=0.5):
        super().__init__()
        self.features = nn.Sequential(
            nn.Conv2d(3, 64, kernel_size=3, padding=1),  # 输入通道3,输出64 
            nn.ReLU(),
            nn.MaxPool2d(2),
            nn.Dropout2d(p=dropout_p),  # 空间丢弃(推荐用于卷积层)
            nn.Conv2d(64, 128, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2)
        )
        self.classifier = nn.Sequential(
            nn.Linear(128 * 8 * 8, 512),
            nn.ReLU(),
            nn.Dropout(p=dropout_p),     # 标准丢弃(用于全连接层)
            nn.Linear(512, 10)
        )
 
    def forward(self, x):
        x = self.features(x)
        x = x.view(x.size(0), -1)  # 展平操作 
        x = self.classifier(x)
        return x 

2. 权重衰减(L2正则化)实现

import torch.optim as optim 
 
模型实例化(Dropout概率设为0.5)
model = CIFAR10Classifier(dropout_p=0.5)
 
优化器配置(L2正则化通过weight_decay参数实现)
optimizer = optim.Adam(model.parameters(), lr=0.001, weight_decay=1e-4)

3. Early Stopping与模型检查点保存

import os 
from copy import deepcopy 
 
class EarlyStopping:
    def __init__(self, patience=5, delta=0):
        self.patience = patience 
        self.delta = delta 
        self.counter = 0 
        self.best_loss = None 
        self.best_model = None 
        self.early_stop = False 
 
    def __call__(self, val_loss, model):
        if self.best_loss is None:
            self.best_loss = val_loss 
            self.best_model = deepcopy(model.state_dict())
        elif val_loss > self.best_loss - self.delta:
            self.counter += 1 
            if self.counter >= self.patience:
                self.early_stop = True 
        else:
            self.best_loss = val_loss 
            self.best_model = deepcopy(model.state_dict())
            self.counter = 0 
 
初始化Early Stopping 
early_stopping = EarlyStopping(patience=10, delta=0.001)
 
模型保存路径 
checkpoint_path = "best_model.pth"

三、训练流程与实验对比

1. 完整训练循环(含验证阶段)

def train_model(model, train_loader, val_loader, optimizer, num_epochs=50):
    criterion = nn.CrossEntropyLoss()
    train_loss_history, val_loss_history = [], []
    
    for epoch in range(num_epochs):
        # 训练阶段 
        model.train()
        running_loss = 0.0 
        for images, labels in train_loader:
            optimizer.zero_grad()
            outputs = model(images)
            loss = criterion(outputs, labels)
            loss.backward()
            optimizer.step()
            running_loss += loss.item() * images.size(0)
        epoch_loss = running_loss / len(train_loader.dataset)
        train_loss_history.append(epoch_loss)
        
        # 验证阶段 
        model.eval()
        val_loss = 0.0 
        with torch.no_grad():
            for images, labels in val_loader:
                outputs = model(images)
                loss = criterion(outputs, labels)
                val_loss += loss.item() * images.size(0)
        val_loss /= len(val_loader.dataset)
        val_loss_history.append(val_loss)
        
        # Early Stopping判断 
        early_stopping(val_loss, model)
        if early_stopping.early_stop:
            print(f"Early stopping triggered at epoch {epoch+1}")
            break 
            
    # 保存最佳模型 
    torch.save(early_stopping.best_model, checkpoint_path)
    return train_loss_history, val_loss_history 

2. Dropout概率对比实验

Dropout概率训练准确率验证准确率过拟合程度
0.098.2%72.3%严重
0.392.5%78.6%中等
0.586.7%81.2%轻微
0.778.4%75.9%欠拟合

结论:当Dropout概率为0.5时,验证集准确率最高且过拟合控制最佳。

3. 权重衰减参数对比

Weight Decay训练损失验证损失模型复杂度
0(无正则化)0.121.56过高
1e-40.250.89适中
1e-30.510.92过低

结论:weight_decay=1e-4时达到最佳平衡。


四、代码运行流程图

加载CIFAR-10数据集
划分训练/验证集
构建含Dropout的CNN模型
配置优化器与L2正则化
训练循环
是否验证阶段?
计算验证损失
Early Stopping条件满足?
保存模型检查点
继续训练

五、关键问题解答

Q1:Dropout在不同网络层的设置差异

  • 卷积层:推荐使用Dropout2d(空间丢弃),按通道随机置零整个特征图
  • 全连接层:使用标准Dropout,随机置零单个神经元

Q2:Early Stopping与模型检查点的联动逻辑

  • 每次验证损失创新低时,保存当前模型状态
  • 当连续patience次未创新低,恢复最佳模型并终止训练

Q3:L2正则化与Dropout的协同作用

  • L2正则化通过惩罚大权重抑制过拟合
  • Dropout通过随机禁用神经元增强鲁棒性
  • 联合使用时需降低正则化强度(建议weight_decay=1e-4

六、扩展实践建议

1. 组合策略有效性验证

实验组配置 
experiments = [
    {"dropout_p":0.5, "weight_decay":1e-4},  # 推荐配置 
    {"dropout_p":0.0, "weight_decay":1e-4},
    {"dropout_p":0.5, "weight_decay":0}
]
 
运行对比实验 
for config in experiments:
    model = CIFAR10Classifier(dropout_p=config["dropout_p"])
    optimizer = optim.Adam(model.parameters(), lr=0.001, 
                          weight_decay=config["weight_decay"])
    train_loss, val_loss = train_model(model, train_loader, val_loader, optimizer)

2. 模型检查点恢复测试

加载最佳模型 
best_model = CIFAR10Classifier()
best_model.load_state_dict(torch.load(checkpoint_path))
 
测试集评估 
correct = 0 
total = 0 
with torch.no_grad():
    for images, labels in test_loader:
        outputs = best_model(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()
 
print(f'Test Accuracy: {100 * correct / total:.2f}%')

七、总结与预告

今日核心收获:

  1. 掌握通过random_split创建验证集的标准方法
  2. 理解Dropout概率与网络深度的配置关系
  3. 实现L2正则化与Early Stopping的协同优化

清华大学全五版的《DeepSeek教程》完整的文档需要的朋友,关注我私信:deepseek 即可获得。

怎么样今天的内容还满意吗?再次感谢朋友们的观看,关注GZH:凡人的AI工具箱,回复666,送您价值199的AI大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!


http://www.kler.cn/a/565790.html

相关文章:

  • 【六祎 - Note】SQL备忘录;DDL,DML,DQL,DCL
  • 大模型原理与技术(毛玉仁)
  • 头歌实验---C/C++程序设计:实验2:顺序结构程序设计
  • 【Git】版本控制系统Git命令详解
  • 团队协作中的分支合并:构建高效开发流程的关键
  • rust学习~tokio的io
  • 爱普生可编程晶振 SG-8101CE 在智能家居领域展现出的优势
  • CSS中文本属性使用详情
  • 智科技赋能宠物关怀新时代
  • IDEA提示将方法形参更改为(什么什么类型),要检查对应的实体类中的字段类型是否正确
  • 浏览器访问https站点的过程
  • 【azure openai】用tts实现语音对话【demo】
  • 前端项目中脚本文件打包,vscode中如何正确使用gtar命令
  • SslConnection::SslConnection()详解
  • 期权帮|沪深300股指期货合约技巧有哪些?
  • pwa的基本使用
  • Redis 源码分析-内部数据结构 robj
  • python生成的exe文件防止反编译(Nuitka)
  • 【Java面试】JVM汇总
  • 【MySQL】索引(中)