第三十七天打卡

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

过拟合判断

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  # 导入tqdm库用于进度条显示
import warnings
warnings.filterwarnings("ignore")  # 忽略警告信息

# 设置GPU设备
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print(f"使用设备: {device}")

# 加载鸢尾花数据集
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
X_train = torch.FloatTensor(X_train).to(device)
y_train = torch.LongTensor(y_train).to(device)
X_test = torch.FloatTensor(X_test).to(device)
y_test = torch.LongTensor(y_test).to(device)

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)

# 训练模型
num_epochs = 20000  # 训练的轮数

# 用于存储每200个epoch的损失值和对应的epoch数
train_losses = [] # 存储训练集损失
test_losses = [] # 新增:存储测试集损失
epochs = []

start_time = time.time()  # 记录开始时间

# 创建tqdm进度条
with tqdm(total=num_epochs, desc="训练进度", unit="epoch") as pbar:
    # 训练模型
    for epoch in range(num_epochs):
        # 前向传播
        outputs = model(X_train)  # 隐式调用forward函数
        train_loss = criterion(outputs, y_train)

        # 反向传播和优化
        optimizer.zero_grad()
        train_loss.backward()
        optimizer.step()

        # 记录损失值并更新进度条
        if (epoch + 1) % 200 == 0:
            # 计算测试集损失,新增代码
            model.eval()
            with torch.no_grad():
                test_outputs = model(X_test)
                test_loss = criterion(test_outputs, y_test)
            model.train()
            
            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}'})

        # 每1000个epoch更新一次进度条
        if (epoch + 1) % 1000 == 0:
            pbar.update(1000)  # 更新进度条

    # 确保进度条达到100%
    if pbar.n < num_epochs:
        pbar.update(num_epochs - pbar.n)  # 计算剩余的进度并更新

time_all = time.time() - start_time  # 计算训练时间
print(f'Training time: {time_all:.2f} seconds')

# 可视化损失曲线
plt.figure(figsize=(10, 6))
plt.plot(epochs, train_losses, label='Train Loss') # 原始代码已有
plt.plot(epochs, test_losses, label='Test Loss')  # 新增:测试集损失曲线
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.title('Training and Test Loss over Epochs')
plt.legend() # 新增:显示图例
plt.grid(True)
plt.show()

# 在测试集上评估模型,此时model内部已经是训练好的参数了
# 评估模型
model.eval() # 设置模型为评估模式
with torch.no_grad(): # torch.no_grad()的作用是禁用梯度计算,可以提高模型推理速度
    outputs = model(X_test)  # 对测试数据进行前向传播,获得预测结果
    _, predicted = torch.max(outputs, 1) # torch.max(outputs, 1)返回每行的最大值和对应的索引
    correct = (predicted == y_test).sum().item() # 计算预测正确的样本数
    accuracy = correct / y_test.size(0)
    print(f'测试集准确率: {accuracy * 100:.2f}%')  

早停法

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  # 导入tqdm库用于进度条显示
import warnings
warnings.filterwarnings("ignore")  # 忽略警告信息

# 设置GPU设备
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print(f"使用设备: {device}")

# 加载鸢尾花数据集
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
X_train = torch.FloatTensor(X_train).to(device)
y_train = torch.LongTensor(y_train).to(device)
X_test = torch.FloatTensor(X_test).to(device)
y_test = torch.LongTensor(y_test).to(device)

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)

# 训练模型
num_epochs = 20000  # 训练的轮数

# 用于存储每200个epoch的损失值和对应的epoch数
train_losses = []  # 存储训练集损失
test_losses = []   # 存储测试集损失
epochs = []

# ===== 新增早停相关参数 =====
best_test_loss = float('inf')  # 记录最佳测试集损失
best_epoch = 0                 # 记录最佳epoch
patience = 50                # 早停耐心值(连续多少轮测试集损失未改善时停止训练)
counter = 0                    # 早停计数器
early_stopped = False          # 是否早停标志
# ==========================

start_time = time.time()  # 记录开始时间

# 创建tqdm进度条
with tqdm(total=num_epochs, desc="训练进度", unit="epoch") as pbar:
    # 训练模型
    for epoch in range(num_epochs):
        # 前向传播
        outputs = model(X_train)  # 隐式调用forward函数
        train_loss = criterion(outputs, y_train)

        # 反向传播和优化
        optimizer.zero_grad()
        train_loss.backward()
        optimizer.step()

        # 记录损失值并更新进度条
        if (epoch + 1) % 200 == 0:
            # 计算测试集损失
            model.eval()
            with torch.no_grad():
                test_outputs = model(X_test)
                test_loss = criterion(test_outputs, y_test)
            model.train()
            
            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 # 更新最佳epoch
                counter = 0 # 重置计数器
                # 保存最佳模型
                torch.save(model.state_dict(), 'best_model.pth')
            else:
                counter += 1
                if counter >= patience:
                    print(f"早停触发!在第{epoch+1}轮,测试集损失已有{patience}轮未改善。")
                    print(f"最佳测试集损失出现在第{best_epoch}轮,损失值为{best_test_loss:.4f}")
                    early_stopped = True
                    break  # 终止训练循环
            # ======================

        # 每1000个epoch更新一次进度条
        if (epoch + 1) % 1000 == 0:
            pbar.update(1000)  # 更新进度条

    # 确保进度条达到100%
    if pbar.n < num_epochs:
        pbar.update(num_epochs - pbar.n)  # 计算剩余的进度并更新

time_all = time.time() - start_time  # 计算训练时间
print(f'Training time: {time_all:.2f} seconds')

# ===== 新增:加载最佳模型用于最终评估 =====
if early_stopped:
    print(f"加载第{best_epoch}轮的最佳模型进行最终评估...")
    model.load_state_dict(torch.load('best_model.pth'))
# ================================

# 可视化损失曲线
plt.figure(figsize=(10, 6))
plt.plot(epochs, train_losses, label='Train Loss')
plt.plot(epochs, test_losses, label='Test Loss')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.title('Training and Test Loss over Epochs')
plt.legend()
plt.grid(True)
plt.show()

# 在测试集上评估模型
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}%')    

@浙大疏锦行

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2394790.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[春秋云镜] CVE-2023-23752 writeup

首先奉上大佬的wp表示尊敬&#xff1a;&#xff08;很详细&#xff09;[ 漏洞复现篇 ] Joomla未授权访问Rest API漏洞(CVE-2023-23752)_joomla未授权访问漏洞(cve-2023-23752)-CSDN博客 知识点 Joomla版本为4.0.0 到 4.2.7 存在未授权访问漏洞 Joomla是一套全球知名的内容管理…

CSS专题之水平垂直居中

前言 石匠敲击石头的第 16 次 在日常开发中&#xff0c;经常会遇到水平垂直居中的布局&#xff0c;虽然现在基本上都用 Flex 可以轻松实现&#xff0c;但是在某些无法使用 Flex 的情况下&#xff0c;又应该如何让元素水平垂直居中呢&#xff1f;这也是一道面试的必考题&#xf…

(新)MQ高级-MQ的可靠性

消息到达MQ以后&#xff0c;如果MQ不能及时保存&#xff0c;也会导致消息丢失&#xff0c;所以MQ的可靠性也非常重要。 一、数据持久化 为了提升性能&#xff0c;默认情况下MQ的数据都是在内存存储的临时数据&#xff0c;重启后就会消失。为了保证数据的可靠性&#xff0c;必须…

Leetcode 3231. 要删除的递增子序列的最小数量

1.题目基本信息 1.1.题目描述 给定一个整数数组 nums&#xff0c;你可以执行任意次下面的操作&#xff1a; 从数组删除一个 严格递增 的 子序列。 您的任务是找到使数组为 空 所需的 最小 操作数。 1.2.题目地址 https://leetcode.cn/problems/minimum-number-of-increas…

4.2.5 Spark SQL 分区自动推断

在本节实战中&#xff0c;我们学习了Spark SQL的分区自动推断功能&#xff0c;这是一种提升查询性能的有效手段。通过创建具有不同分区的目录结构&#xff0c;并在这些目录中放置JSON文件&#xff0c;我们模拟了一个分区表的环境。使用Spark SQL读取这些数据时&#xff0c;Spar…

【图像处理入门】2. Python中OpenCV与Matplotlib的图像操作指南

一、环境准备 import cv2 import numpy as np import matplotlib.pyplot as plt# 配置中文字体显示&#xff08;可选&#xff09; plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False二、图像的基本操作 1. 图像读取、显示与保存 使用OpenCV…

Spring Boot微服务架构(九):设计哲学是什么?

一、Spring Boot设计哲学是什么&#xff1f; Spring Boot 的设计哲学可以概括为 ​​“约定优于配置”​​ 和 ​​“开箱即用”​​&#xff0c;其核心目标是​​极大地简化基于 Spring 框架的生产级应用的初始搭建和开发过程​​&#xff0c;让开发者能够快速启动并运行项目…

TC/BC/OC P2P/E2E有啥区别?-PTP协议基础概念介绍

前言 时间同步网络中的每个节点&#xff0c;都被称为时钟&#xff0c;PTP协议定义了三种基本时钟节点。本文将介绍这三种类型的时钟&#xff0c;以及gPTP在同步机制上与其他机制的区别 本系列文章将由浅入深的带你了解gPTP&#xff0c;欢迎关注 时钟类型 在PTP中我们将各节…

Kafka数据怎么保障不丢失

在分布式消息系统中&#xff0c;数据不丢失是核心可靠性需求之一。Apache Kafka 通过生产者配置、副本机制、持久化策略、消费者偏移量管理等多层机制保障数据可靠性。以下从不同维度解析 Kafka 数据不丢失的核心策略&#xff0c;并附示意图辅助理解。 一、生产者端&#xff1a…

AI书签管理工具开发全记录(八):Ai创建书签功能实现

文章目录 AI书签管理工具开发全记录&#xff08;八&#xff09;&#xff1a;AI智能创建书签功能深度解析前言 &#x1f4dd;1. AI功能设计思路 &#x1f9e0;1.1 传统书签创建的痛点1.2 AI解决方案设计 2. 后端API实现 ⚙️2.1 新增url相关工具方法2.1 创建后端api2.2 创建crea…

X-plore v4.43.05 强大的安卓文件管理器-MOD解锁高级版 手机平板/电视TV通用

X-plore v4.43.05 强大的安卓文件管理器-MOD解锁高级版 手机平板/电视TV通用 应用简介&#xff1a; X-plore 是一款强大的安卓端文件管理器&#xff0c;它可以在电视或者手机上管理大量媒体文件、应用程序。…

使用多Agent进行海报生成的技术方案及评估套件-P2P、paper2poster

最近字节、滑铁卢大学相关团队同时放出了他们使用Agent进行海报生成的技术方案&#xff0c;P2P和Paper2Poster&#xff0c;传统方案如类似ppt生成等思路&#xff0c;基本上采用固定的模版&#xff0c;提取相关的关键元素进行模版填充&#xff0c;因此&#xff0c;海报生成的质量…

Redis--缓存工具封装

经过前面的学习&#xff0c;发现缓存中的问题&#xff0c;无论是缓存穿透&#xff0c;缓存雪崩&#xff0c;还是缓存击穿&#xff0c;这些问题的解决方案业务代码逻辑都很复杂&#xff0c;我们也不应该每次都来重写这些逻辑&#xff0c;我们可以将其封装成工具。而在封装的时候…

python:在 PyMOL 中如何查看和使用内置示例文件?

参阅&#xff1a;开源版PyMol安装保姆级教程 百度网盘下载 提取码&#xff1a;csub pip show pymol 简介: PyMOL是一个Python增强的分子图形工具。它擅长蛋白质、小分子、密度、表面和轨迹的3D可视化。它还包括分子编辑、射线追踪和动画。 可视化示例‌&#xff1a;打开 PyM…

SpringCloud——Docker

1.命令解读 docker run -d 解释&#xff1a;创建并运行一个容器&#xff0c;-d则是让容器以后台进程运行 --name mysql 解释&#xff1a; 给容器起个名字叫mysql -p 3306:3306 解释&#xff1a;-p 宿主机端口:容器内端口&#xff0c;设置端口映射 注意&#xff1a; 1、…

机器学习:欠拟合、过拟合、正则化

本文目录&#xff1a; 一、欠拟合二、过拟合三、拟合问题原因及解决办法四、正则化&#xff1a;尽量减少高次幂特征的影响&#xff08;一&#xff09;L1正则化&#xff08;二&#xff09;L2正则化&#xff08;三&#xff09;L1正则化与L2正则化的对比 五、正好拟合代码&#xf…

运用集合知识做斗地主案例

方法中可变参数 一种特殊形参&#xff0c;定义在方法&#xff0c;构造器的形参列表里&#xff0c;格式&#xff1a;数据类型...参数名称&#xff1b; 可变参数的特点和好处 特点&#xff1a;可以不传数据给它&#xff1b;可以传一个或者同时传多个数据给它&#xff1b;也可以…

《HelloGitHub》第 110 期

兴趣是最好的老师&#xff0c;HelloGitHub 让你对开源感兴趣&#xff01; 简介 HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。 github.com/521xueweihan/HelloGitHub 这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等&#xff0c;涵盖多种编程语言 Python、…

使用 Shell 脚本实现 Spring Boot 项目自动化部署到 Docker(Ubuntu 服务器)

使用 Shell 脚本实现 Spring Boot 项目自动化部署到 Docker&#xff08;Ubuntu 服务器&#xff09; 在日常项目开发中&#xff0c;我们经常会将 Spring Boot 项目打包并部署到服务器上的 Docker 环境中。为了提升效率、减少重复操作&#xff0c;我们可以通过 Shell 脚本实现自动…

day023-网络基础与OSI七层模型

文章目录 1. 网络基础知识点1.1 网络中的单位1.2 查看实时网速&#xff1a;iftop1.3 交换机、路由器 2. 路由表2.1 查看路由表的命令2.2 路由追踪命令 3. 通用网站网络架构4. 局域网上网原理-NAT5. 虚拟机上网原理6. 虚拟机的网络模式6.1 NAT模式6.2 桥接模式6.3 仅主机模式 7.…