Python Day37

article/2025/9/7 15:02:18

Task:
1.过拟合的判断:测试集和训练集同步打印指标
2.模型的保存和加载
a.仅保存权重
b.保存权重和模型
c.保存全部信息checkpoint,还包含训练状态
3.早停策略

在这里插入图片描述
在这里插入图片描述

1. 过拟合的判断:测试集和训练集同步打印指标

过拟合是指模型在训练数据上表现良好,但在未见过的新数据(测试数据)上表现较差。 判断过拟合的关键在于比较训练集和测试集的性能。

  • 训练集指标: 准确率、损失等。 训练集指标通常会随着训练的进行而持续提高(准确率)或降低(损失)。
  • 测试集指标: 准确率、损失等。 测试集指标一开始可能会随着训练的进行而提高,但当模型开始过拟合时,测试集指标会停止提高甚至开始下降。

判断标准:

  • 训练集性能远好于测试集性能: 这是过拟合的典型迹象。
  • 训练集损失持续下降,但测试集损失开始上升: 这表明模型正在记住训练数据,而不是学习泛化能力。
  • 训练集准确率接近 100%,但测试集准确率较低: 也是过拟合的信号。

代码示例 (PyTorch):

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
import numpy as np# 1. 创建一些模拟数据
np.random.seed(42)
X = np.random.rand(100, 10)  # 100个样本,每个样本10个特征
y = np.random.randint(0, 2, 100)  # 二分类问题# 将数据分成训练集和测试集
train_size = int(0.8 * len(X))
X_train, X_test = X[:train_size], X[train_size:]
y_train, y_test = y[:train_size], y[train_size:]# 转换为 PyTorch tensors
X_train = torch.tensor(X_train, dtype=torch.float32)
X_test = torch.tensor(X_test, dtype=torch.float32)
y_train = torch.tensor(y_train, dtype=torch.long)
y_test = torch.tensor(y_test, dtype=torch.long)# 创建 DataLoader
train_dataset = TensorDataset(X_train, y_train)
test_dataset = TensorDataset(X_test, y_test)
train_loader = DataLoader(train_dataset, batch_size=16, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=16, shuffle=False)# 2. 定义一个简单的模型
class SimpleNN(nn.Module):def __init__(self, input_size, hidden_size, num_classes):super(SimpleNN, self).__init__()self.fc1 = nn.Linear(input_size, hidden_size)self.relu = nn.ReLU()self.fc2 = nn.Linear(hidden_size, num_classes)def forward(self, x):out = self.fc1(x)out = self.relu(out)out = self.fc2(out)return outinput_size = 10
hidden_size = 20
num_classes = 2
model = SimpleNN(input_size, hidden_size, num_classes)# 3. 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.01)# 4. 训练循环
num_epochs = 100
for epoch in range(num_epochs):# 训练model.train()train_loss = 0.0correct_train = 0total_train = 0for inputs, labels in train_loader:optimizer.zero_grad()outputs = model(inputs)loss = criterion(outputs, labels)loss.backward()optimizer.step()train_loss += loss.item()_, predicted = torch.max(outputs.data, 1)total_train += labels.size(0)correct_train += (predicted == labels).sum().item()train_accuracy = 100 * correct_train / total_traintrain_loss /= len(train_loader)# 评估model.eval()test_loss = 0.0correct_test = 0total_test = 0with torch.no_grad():for inputs, labels in test_loader:outputs = model(inputs)loss = criterion(outputs, labels)test_loss += loss.item()_, predicted = torch.max(outputs.data, 1)total_test += labels.size(0)correct_test += (predicted == labels).sum().item()test_accuracy = 100 * correct_test / total_testtest_loss /= len(test_loader)# 打印指标print(f'Epoch [{epoch+1}/{num_epochs}], 'f'Train Loss: {train_loss:.4f}, Train Acc: {train_accuracy:.2f}%, 'f'Test Loss: {test_loss:.4f}, Test Acc: {test_accuracy:.2f}%')# 观察训练集和测试集的损失和准确率,判断是否过拟合。

关键点:

  • 在每个 epoch 结束后,同时打印训练集和测试集的损失和准确率。
  • 观察这些指标的变化趋势。 如果训练集损失持续下降,但测试集损失开始上升,或者训练集准确率远高于测试集准确率,则表明模型正在过拟合。

2. 模型的保存和加载

在 PyTorch 中,有几种保存和加载模型的方法:

a. 仅保存权重 (推荐):

这是最常见和推荐的方法。 它只保存模型的参数(权重和偏置),而不保存模型的结构。 这种方法更轻量级,更灵活,因为你可以将权重加载到任何具有相同结构的模型的实例中。

  • 保存: torch.save(model.state_dict(), 'model_weights.pth')
  • 加载:
    1. 首先,创建一个与保存时具有相同结构的模型的实例。
    2. 然后,使用 model.load_state_dict(torch.load('model_weights.pth')) 加载权重。
# 保存权重
torch.save(model.state_dict(), 'model_weights.pth')# 加载权重
model = SimpleNN(input_size, hidden_size, num_classes)  # 创建模型实例
model.load_state_dict(torch.load('model_weights.pth'))
model.eval()  # 设置为评估模式

b. 保存权重和模型结构:

这种方法保存整个模型对象,包括模型的结构和权重。 它更简单,但不如仅保存权重灵活。

  • 保存: torch.save(model, 'model.pth')
  • 加载: model = torch.load('model.pth')
# 保存整个模型
torch.save(model, 'model.pth')# 加载整个模型
model = torch.load('model.pth')
model.eval()  # 设置为评估模式

c. 保存全部信息 (Checkpoint):

这种方法保存模型的全部信息,包括模型的结构、权重、优化器的状态、epoch 数等。 这对于恢复训练非常有用。

  • 保存:
checkpoint = {'epoch': epoch,'model_state_dict': model.state_dict(),'optimizer_state_dict': optimizer.state_dict(),'loss': train_loss,
}
torch.save(checkpoint, 'checkpoint.pth')
  • 加载:
checkpoint = torch.load('checkpoint.pth')
model = SimpleNN(input_size, hidden_size, num_classes)
optimizer = optim.Adam(model.parameters(), lr=0.01)model.load_state_dict(checkpoint['model_state_dict'])
optimizer.load_state_dict(checkpoint['optimizer_state_dict'])
epoch = checkpoint['epoch']
loss = checkpoint['loss']model.eval() # or model.train() depending on your needs
# - or -
model.train()

3. 早停策略 (Early Stopping)

早停是一种正则化技术,用于防止过拟合。 它的基本思想是:在训练过程中,如果测试集上的性能在一定时间内没有提高,就提前停止训练。

实现步骤:

  1. 监控指标: 选择一个在测试集上监控的指标(例如,测试集损失或准确率)。
  2. 耐心 (Patience): 定义一个“耐心”值,表示在测试集指标没有提高的情况下,允许训练继续进行的 epoch 数。
  3. 最佳模型: 在训练过程中,保存测试集上性能最佳的模型。
  4. 停止训练: 如果测试集指标在“耐心”个 epoch 内没有提高,则停止训练,并加载保存的最佳模型。

代码示例 (PyTorch):

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
import numpy as np# 1. 创建一些模拟数据
np.random.seed(42)
X = np.random.rand(100, 10)  # 100个样本,每个样本10个特征
y = np.random.randint(0, 2, 100)  # 二分类问题# 将数据分成训练集和测试集
train_size = int(0.8 * len(X))
X_train, X_test = X[:train_size], X[train_size:]
y_train, y_test = y[:train_size], y[train_size:]# 转换为 PyTorch tensors
X_train = torch.tensor(X_train, dtype=torch.float32)
X_test = torch.tensor(X_test, dtype=torch.float32)
y_train = torch.tensor(y_train, dtype=torch.long)
y_test = torch.tensor(y_test, dtype=torch.long)# 创建 DataLoader
train_dataset = TensorDataset(X_train, y_train)
test_dataset = TensorDataset(X_test, y_test)
train_loader = DataLoader(train_dataset, batch_size=16, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=16, shuffle=False)# 2. 定义一个简单的模型
class SimpleNN(nn.Module):def __init__(self, input_size, hidden_size, num_classes):super(SimpleNN, self).__init__()self.fc1 = nn.Linear(input_size, hidden_size)self.relu = nn.ReLU()self.fc2 = nn.Linear(hidden_size, num_classes)def forward(self, x):out = self.fc1(x)out = self.relu(out)out = self.fc2(out)return outinput_size = 10
hidden_size = 20
num_classes = 2
model = SimpleNN(input_size, hidden_size, num_classes)# 3. 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.01)# 4. 早停策略
patience = 10  # 如果10个epoch测试集损失没有下降,就停止训练
best_loss = np.inf  # 初始最佳损失设置为无穷大
counter = 0  # 计数器,记录测试集损失没有下降的epoch数
best_model_state = None # 保存最佳模型的状态# 5. 训练循环
num_epochs = 100
for epoch in range(num_epochs):# 训练model.train()train_loss = 0.0correct_train = 0total_train = 0for inputs, labels in train_loader:optimizer.zero_grad()outputs = model(inputs)loss = criterion(outputs, labels)loss.backward()optimizer.step()train_loss += loss.item()_, predicted = torch.max(outputs.data, 1)total_train += labels.size(0)correct_train += (predicted == labels).sum().item()train_accuracy = 100 * correct_train / total_traintrain_loss /= len(train_loader)# 评估model.eval()test_loss = 0.0correct_test = 0total_test = 0with torch.no_grad():for inputs, labels in test_loader:outputs = model(inputs)loss = criterion(outputs, labels)test_loss += loss.item()_, predicted = torch.max(outputs.data, 1)total_test += labels.size(0)correct_test += (predicted == labels).sum().item()test_accuracy = 100 * correct_test / total_testtest_loss /= len(test_loader)# 打印指标print(f'Epoch [{epoch+1}/{num_epochs}], 'f'Train Loss: {train_loss:.4f}, Train Acc: {train_accuracy:.2f}%, 'f'Test Loss: {test_loss:.4f}, Test Acc: {test_accuracy:.2f}%')# 早停逻辑if test_loss < best_loss:best_loss = test_losscounter = 0best_model_state = model.state_dict() # 保存最佳模型的状态else:counter += 1if counter >= patience:print("Early stopping!")model.load_state_dict(best_model_state)  # 加载最佳模型breakprint(f"Best Test Loss: {best_loss:.4f}")

关键点:

  • patience:控制早停的敏感度。 较小的 patience 值会导致更早的停止,可能导致欠拟合。 较大的 patience 值允许训练继续进行更长时间,可能导致过拟合。
  • best_loss:跟踪测试集上的最佳损失。
  • counter:跟踪测试集损失没有下降的 epoch 数。
  • 在早停后,加载保存的最佳模型。

总结:

  • 通过同步打印训练集和测试集的指标,可以有效地判断过拟合。
  • 仅保存权重是保存模型的推荐方法,因为它更轻量级和灵活。
  • 早停是一种有效的正则化技术,可以防止过拟合。

http://www.hkcw.cn/article/GkECuFVebf.shtml

相关文章

2025年全国青少年信息素养大赛 scratch图形化编程挑战赛 小低组初赛 内部集训模拟题解析

2025年信息素养大赛初赛scratch模拟题解析 博主推荐 所有考级比赛学习相关资料合集【推荐收藏】 scratch资料 Scratch3.0系列视频课程资料零基础学习scratch3.0【入门教学 免费】零基础学习scratch3.0【视频教程 114节 免费】 历届蓝桥杯scratch国赛真题解析历届蓝桥杯scr…

Linux环境基础开发工具->gcc/g++

引入&#xff1a;gcc/g是什么&#xff1f; 在上篇博客我们知道&#xff0c;vim是一个编辑器&#xff0c;vim负责的是代码的编辑&#xff1b;而gcc/g是一个编译器&#xff0c;负责的就是代码的编译&#xff01;gcc负责C语言代码的编译&#xff0c;而g负责c代码的编译&#xff0…

云原生与DevOps融合实践:加速企业数字化转型的加速器

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 一、引言&#xff1a;为什么“云原生DevOps”是当下最强组合&#xff1f; 在传统软件交付模式逐步被淘汰的当下&#xff0c;越来…

孙颖莎王曼昱出战WTT美国站女双 拉斯维加斯再携手

2025年WTT美国大满贯将于7月3日至13日在拉斯维加斯奥尔良体育馆及美高梅大酒店会议中心举行。孙颖莎和王曼昱将搭档出战女双正赛。在不久前结束的多哈世乒赛女单决赛中,孙颖莎以4比3的大比分险胜王曼昱,成功卫冕。责任编辑:zx0176

基于51单片机和8X8点阵屏、独立按键的射击消除类小游戏

目录 系列文章目录前言一、效果展示二、原理分析三、各模块代码1、8X8点阵屏2、独立按键3、定时器04、定时器1 四、主函数总结 系列文章目录 前言 使用的是普中A2开发板。 【单片机】STC89C52RC 【频率】12T11.0592MHz 【外设】8X8点阵屏、独立按键 效果查看/操作演示&#x…

ubuntu22.04安装docker

1. 准备工作 更新系统软件包索引 sudo apt update2. 卸载旧版本 Docker&#xff08;可选&#xff09; 清理旧版 Docker 及相关依赖 sudo apt-get remove docker docker-engine docker.io containerd runc3. 设置 Docker 仓库 安装依赖工具 (apt-transport-https, ca-certi…

burpsuit抓包完整示例

1.确保浏览器&#xff08;这里使用的是火狐浏览器&#xff09;和burpsuit配置完整&#xff08;有需要留言&#xff09;&#xff0c;配置完整包括jdk安装&#xff0c;配置环境变量&#xff0c;下载burp,下载并导入证书&#xff0c;ip端口一致&#xff0c;代理能正常打开。 2.注意…

其他 | 边缘端应用的轻量级优化调研

1.调研目标 由于边缘计算场景的性能受限&#xff0c;无法提供与常规服务器相同或略低的环境&#xff0c;因此对我们的上层业务应用有着较高的资源要求。 目前我们的应用程序基于 Oracle JDK&#xff08;开发者端&#xff09;与 OpenJDK&#xff08;生产环境&#xff09;进行开…

Shell 脚本常用命令笔记

一、系统配置命令 1. 主机名设置 文件方式 修改文件&#xff1a;vim /etc/hostname&#xff0c;写入新主机名&#xff08;如czg.easylee.org&#xff09;。生效方式&#xff1a;需重新打开 Shell 或重启系统。 命令方式 即时生效命令&#xff1a;hostnamectl set-hostname 新…

不规则瀑布流布局拖拽重排序

因为业务&#xff0c;所以需要用flutter去实现一种不规则图形的瀑布流&#xff0c;但是同时需要支持拖拽并重新排序。效果类似如下。 查询过现有的插件&#xff0c;要么是仅支持同样大小的组件进行排序&#xff0c;要么就是动画效果不是很满意&#xff0c;有点死板&#xff0c;…

线程de安全性备忘

文章仅供学习参考 线程安全的本质定义 public class Counter {private int value 0; // 共享资源// 线程安全方法public synchronized void increment() {value; // 原子操作} }原子性&#xff08;Atomicity&#xff09;&#xff1a;操作不可分割&#xff08;如 synchroniz…

进行性核上性麻痹健康护理全指南:从症状管理到生活照护

进行性核上性麻痹&#xff08;PSP&#xff09;是一种罕见的神经退行性疾病&#xff0c;主要影响运动、平衡及眼球运动功能&#xff0c;常表现为步态不稳、吞咽困难、眼球上视受限、情绪改变等。由于目前尚无根治方法&#xff0c;科学的健康护理对延缓病情进展、提升患者生活质量…

[智能算法]蚁群算法原理与TSP问题示例

目录 ​编辑 一、生物行为启发的智能优化算法 1.1 自然界的群体智能现象 1.2 人工蚁群算法核心思想 二、算法在组合优化中的应用演进 2.1 经典TSP问题建模 2.2 算法流程优化 三、TSP问题实战:Python实现与可视化 3.1 算法核心类设计 3.2 参数敏感性实验 3.3 可视化…

安卓学习笔记-数据存储

阅读说明 本文是基于上一篇文章《安卓学习笔记-声明式UI》的后续。上篇文章实现了UI层以及业务逻辑层ViewModel的解耦。本篇关注的是数据存储层与业务逻辑层的解耦。 补充知识StateFlow 在 MVVM 架构中如何使用 Kotlin 协程的 StateFlow 来管理和暴露 UI 状态。 private va…

cutlass学习教程

一 接口 1.1 内存类 1.1.1 DeviceAllocation 1 位置 2 内置函数 &#xff08;a&#xff09;reset /// Deletes the managed object and resets capacity to zero void reset() {capacity 0;smart_ptr.reset(); } &#xff08;b&#xff09;get /// Returns a pointer to t…

自定义异常小练习

在开始之前,让我们高喊我们的口号&#xff1a; ​​​​​​​ 键盘敲烂,年薪百万&#xff01; 目录 键盘敲烂,年薪百万&#xff01; 异常综合练习&#xff1a; 自定义异常 异常综合练习&#xff1a; 自定义异常&#xff1a; 定义异常类写继承关系空参构造带参构造 自定…

计算机网络

OSI七层模型 应用层&#xff1a;直接为用户提供网络服务&#xff0c;例如网页浏览、邮件收发表示层&#xff1a;处理数据格式&#xff0c;如加密、解密、压缩、编码等会话层&#xff1a;利用传输层提供的服务&#xff0c;在应用程序之间建立和维持会话&#xff0c;并能使会话获…

【循环神经网络RNN第一期】循环神经网络RNN原理概述

目录 &#x1f9e0; 什么是循环神经网络&#xff08;RNN&#xff09;&#xff1f;&#x1f501; RNN 的结构图&#x1f504; RNN 的“记忆”与问题RNN梯度推导 &#x1f9ec; LSTM&#xff1a;解决长期依赖问题&#x1f9f1; LSTM 的核心结构LSTM总结 参考 人类在思考的时候&am…

自动驾驶与智能交通:构建未来出行的智能引擎

随着人工智能、物联网、5G和大数据等前沿技术的发展&#xff0c;自动驾驶汽车和智能交通系统正以前所未有的速度改变人类的出行方式。这一变革不仅是技术的融合创新&#xff0c;更是推动城市可持续发展的关键支撑。 一、自动驾驶与智能交通的定义 1. 自动驾驶&#xff08;Auto…

5.3.1_2二叉树的层次遍历

遍历过程&#xff1a; 从根节点开始&#xff0c;从左到右一层一层遍历&#xff0c;如下&#xff1a;ABCDEFGHIJKL 初始化一个辅助队列&#xff0c;让根节点先入队&#xff0c;每次判断队列是否为空&#xff0c;不空则让队头节点出队访问该节点让该节点左右孩子入队尾(先左孩子…