news 2026/10/13 12:26:30

Day40 早停策略和模型权重的保存

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Day40 早停策略和模型权重的保存

@浙大疏锦行

作业:对信贷数据集进行训练后保持权重,后继续训练50次,采取早停策略

import torch import torch.nn as nn import torch.optim as optim from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.preprocessing import MinMaxScaler import time import matplotlib.pyplot as plt from tqdm import tqdm import warnings warnings.filterwarnings("ignore") # 检查GPU是否可用,优先使用GPU device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") print(f"使用设备: {device}") # 若有多个GPU,可指定具体GPU,例如cuda:1 # 验证GPU是否真的在使用(可选) if torch.cuda.is_available(): print(f"GPU名称: {torch.cuda.get_device_name(0)}") torch.cuda.empty_cache() # 清空GPU缓存 # 加载信贷数据集 iris = load_iris() X = iris.data # 特征数据 y = iris.target # 标签数据 # 划分训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 归一化数据 scaler = MinMaxScaler() X_train = scaler.fit_transform(X_train) X_test = scaler.transform(X_test) # 转换为PyTorch张量并强制移至指定设备(GPU/CPU) X_train = torch.FloatTensor(X_train).to(device, non_blocking=True) y_train = torch.LongTensor(y_train).to(device, non_blocking=True) X_test = torch.FloatTensor(X_test).to(device, non_blocking=True) y_test = torch.LongTensor(y_test).to(device, non_blocking=True) class MLP(nn.Module): def __init__(self): super(MLP, self).__init__() self.fc1 = nn.Linear(4, 10) # 输入层(信贷数据集需修改输入维度) self.relu = nn.ReLU() self.fc2 = nn.Linear(10, 3) # 输出层(信贷数据集需修改输出维度) def forward(self, x): out = self.fc1(x) out = self.relu(out) out = self.fc2(out) return out # 实例化模型并移至GPU model = MLP().to(device) criterion = nn.CrossEntropyLoss() # 分类损失函数 optimizer = optim.SGD(model.parameters(), lr=0.01) # 优化器 # 首次训练参数 first_train_epochs = 20000 train_losses = [] # 首次训练损失 test_losses = [] epochs = [] # 早停参数(首次训练和继续训练共用相同策略) best_test_loss = float('inf') best_epoch = 0 patience = 50 counter = 0 early_stopped = False print("\n===== 开始首次训练 =====") start_time = time.time() with tqdm(total=first_train_epochs, desc="首次训练进度", unit="epoch") as pbar: for epoch in range(first_train_epochs): model.train() # 前向传播 outputs = model(X_train) train_loss = criterion(outputs, y_train) # 反向传播和优化 optimizer.zero_grad() train_loss.backward() optimizer.step() # 每200轮记录损失并检查早停 if (epoch + 1) % 200 == 0: model.eval() with torch.no_grad(): test_outputs = model(X_test) test_loss = criterion(test_outputs, y_test) train_losses.append(train_loss.item()) test_losses.append(test_loss.item()) epochs.append(epoch + 1) # 更新进度条 pbar.set_postfix({'Train Loss': f'{train_loss.item():.4f}', 'Test Loss': f'{test_loss.item():.4f}'}) # 早停逻辑 if test_loss.item() < best_test_loss: best_test_loss = test_loss.item() best_epoch = epoch + 1 counter = 0 # 保存最佳模型 torch.save(model.state_dict(), 'best_model.pth') else: counter += 1 if counter >= patience: print(f"\n首次训练早停触发!在第{epoch+1}轮,测试集损失已有{patience}轮未改善。") print(f"最佳测试集损失出现在第{best_epoch}轮,损失值为{best_test_loss:.4f}") early_stopped = True break # 更新进度条 if (epoch + 1) % 1000 == 0: pbar.update(1000) # 补全进度条 if pbar.n < first_train_epochs: pbar.update(first_train_epochs - pbar.n) # 保存首次训练结束后的模型权重(核心修改点1) torch.save({ 'model_state_dict': model.state_dict(), 'optimizer_state_dict': optimizer.state_dict(), 'epoch': epoch + 1, 'best_loss': best_test_loss }, 'trained_model.pth') print(f"\n首次训练完成,权重已保存至 trained_model.pth") print(f"首次训练总耗时: {time.time() - start_time:.2f} 秒") print("\n===== 加载权重并开始继续训练 =====") # 加载保存的权重(核心修改点2) checkpoint = torch.load('trained_model.pth', map_location=device) model.load_state_dict(checkpoint['model_state_dict']) print(f"加载了首次训练至第{checkpoint['epoch']}轮的权重,最佳损失: {checkpoint['best_loss']:.4f}") # 重新初始化优化器(核心修改点3:继续训练必须重置优化器) optimizer = optim.SGD(model.parameters(), lr=0.01) # 若需要延续优化器状态,可取消下面注释(视场景选择) # optimizer.load_state_dict(checkpoint['optimizer_state_dict']) # 继续训练的参数 continue_train_epochs = 50 # 目标继续训练50轮 continue_train_losses = [] # 继续训练损失 continue_test_losses = [] continue_epochs = [] # 重置早停参数(针对继续训练) continue_best_loss = checkpoint['best_loss'] continue_counter = 0 continue_early_stop = False start_continue_time = time.time() with tqdm(total=continue_train_epochs, desc="继续训练进度", unit="epoch") as pbar: for epoch in range(continue_train_epochs): model.train() # 前向传播 outputs = model(X_train) train_loss = criterion(outputs, y_train) # 反向传播和优化 optimizer.zero_grad() train_loss.backward() optimizer.step() # 每1轮就检查损失和早停(继续训练轮数少,无需间隔) model.eval() with torch.no_grad(): test_outputs = model(X_test) test_loss = criterion(test_outputs, y_test) continue_train_losses.append(train_loss.item()) continue_test_losses.append(test_loss.item()) continue_epochs.append(epoch + 1) # 更新进度条 pbar.set_postfix({'Train Loss': f'{train_loss.item():.4f}', 'Test Loss': f'{test_loss.item():.4f}'}) pbar.update(1) # 继续训练的早停逻辑 if test_loss.item() < continue_best_loss: continue_best_loss = test_loss.item() continue_counter = 0 # 保存继续训练后的最佳模型 torch.save(model.state_dict(), 'continue_best_model.pth') else: continue_counter += 1 if continue_counter >= patience: print(f"\n继续训练早停触发!在第{epoch+1}轮,测试集损失已有{patience}轮未改善。") print(f"继续训练最佳损失: {continue_best_loss:.4f}") continue_early_stop = True break print(f"继续训练完成,总耗时: {time.time() - start_continue_time:.2f} 秒") print(f"继续训练实际轮数: {len(continue_epochs)} 轮(早停触发则少于50轮)") print("\n===== 最终模型评估 =====") model.load_state_dict(torch.load('continue_best_model.pth', map_location=device)) model.eval() with torch.no_grad(): outputs = model(X_test) _, predicted = torch.max(outputs, 1) correct = (predicted == y_test).sum().item() accuracy = correct / y_test.size(0) print(f'测试集最终准确率: {accuracy * 100:.2f}%') # ====================== 8. 可视化 ====================== plt.figure(figsize=(12, 6)) # 绘制首次训练损失 plt.subplot(1, 2, 1) plt.plot(epochs, train_losses, label='Train Loss') plt.plot(epochs, test_losses, label='Test Loss') plt.xlabel('Epoch') plt.ylabel('Loss') plt.title('首次训练损失曲线') plt.legend() plt.grid(True) # 绘制继续训练损失 plt.subplot(1, 2, 2) plt.plot(continue_epochs, continue_train_losses, label='Train Loss') plt.plot(continue_epochs, continue_test_losses, label='Test Loss') plt.xlabel('Continue Epoch') plt.ylabel('Loss') plt.title('继续训练50轮损失曲线') plt.legend() plt.grid(True) plt.tight_layout() plt.show()
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/8 18:13:36

Z-Image-Turbo GPU利用率提升秘籍:参数调优与资源分配实战

Z-Image-Turbo GPU利用率提升秘籍&#xff1a;参数调优与资源分配实战 Z-Image-Turbo 是一款基于深度学习的图像生成模型&#xff0c;具备高效推理和高质量输出能力。其核心优势之一在于可通过 UI 界面进行直观操作&#xff0c;极大降低了使用门槛。本文将围绕如何在实际部署中…

作者头像 李华
网站建设 2026/10/10 20:46:36

实测对比bfloat16与float8:麦橘超然精度模式选哪个好

实测对比bfloat16与float8&#xff1a;麦橘超然精度模式选哪个好 1. 引言&#xff1a;当AI绘画遇上低显存挑战 你有没有遇到过这样的情况&#xff1a;兴致勃勃想用最新的AI模型画一张高质量图像&#xff0c;结果刚点下“生成”按钮&#xff0c;显存就爆了&#xff1f;尤其是像…

作者头像 李华
网站建设 2026/10/11 14:44:32

AI语音转文字实战:用Fun-ASR-MLT-Nano搭建多语言转录系统

AI语音转文字实战&#xff1a;用Fun-ASR-MLT-Nano搭建多语言转录系统 你有没有遇到过这样的场景&#xff1f;一段长达半小时的会议录音&#xff0c;需要整理成文字纪要&#xff1b;一段海外视频没有字幕&#xff0c;想快速获取内容&#xff1b;或者客户来电录音堆积如山&#…

作者头像 李华
网站建设 2026/10/12 21:17:37

如何高效识别语音并提取情感标签?试试SenseVoice Small镜像

如何高效识别语音并提取情感标签&#xff1f;试试SenseVoice Small镜像 在日常开发和实际应用中&#xff0c;我们常常需要从一段语音中获取信息——不仅仅是“说了什么”&#xff0c;还有“以什么样的情绪说的”以及“周围环境发生了什么”。传统的语音识别工具大多只关注文字…

作者头像 李华
网站建设 2026/10/13 5:40:55

效果展示:Qwen3-Reranker-4B打造的智能文档排序案例

效果展示&#xff1a;Qwen3-Reranker-4B打造的智能文档排序案例 在信息爆炸的时代&#xff0c;如何从海量文档中快速找到最相关的内容&#xff0c;是搜索、推荐和知识管理系统的共同挑战。传统检索系统往往依赖关键词匹配&#xff0c;容易忽略语义层面的相关性&#xff0c;导致…

作者头像 李华
网站建设 2026/10/13 10:11:43

从模型加载到结果导出|FunASR语音识别全流程操作手册

从模型加载到结果导出&#xff5c;FunASR语音识别全流程操作手册 1. 引言&#xff1a;为什么你需要这套语音识别方案&#xff1f; 你有没有遇到过这样的场景&#xff1a;会议录音长达一小时&#xff0c;却要手动整理成文字&#xff1f;视频剪辑时想加字幕&#xff0c;但逐句听…

作者头像 李华