Pytorch-Lighting使用教程(MNIST为例)

2024-06-02 07:12

本文主要是介绍Pytorch-Lighting使用教程(MNIST为例),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、pytorch-lighting简介

1.1 pytorch-lighting是什么

pytorch-lighting(简称pl),基于 PyTorch 的框架。它的核心思想是,将学术代码模型定义、前向 / 反向、优化器、验证等)与工程代码for-loop,保存、tensorboard 日志、训练策略等)解耦开来,使得代码更为简洁清晰。

工程代码经常会出现在深度学习代码中,PyTorch Lightning 对这部分逻辑进行了封装,只需要在 Trainer 类中简单设置即可调用,无需重复造轮子。

1.2 pytorch-lighting优势

  • 通过抽象出样板工程代码,可以更容易地识别和理解ML代码;
  • Lightning的统一结构使得在现有项目的基础上进行构建和理解变得非常容易;
  • Lightning 自动化的代码是用经过全面测试、定期维护并遵循ML最佳实践的高质量代码构建的;

pytorch-lighting最大的好处:

(1)是摆脱了硬件依赖,不需要在程序中显式设置.cuda() 等,PyTorch Lightning 会自动将模型、张量的设备放置在合适的设备;移除.train() 等代码,这也会自动切换

(2)支持分布式训练,自动分配资源,能够很好的进行大规模的DL训练

(3)代码量较少,只需要关心关键的逻辑代码,而框架性的东西,pytorch-lighting已经帮你解决(如自动训练,自动debug)


二、基于Pytorch-Lighting框架训练MNIST模型

1、仅仅训练

下载的所有的数据集都用于训练(没有评估和测试过程,不清楚模型的好与坏)。

# 1. 导入所需的模块
import os
import torch
from torch import nn
import torch.nn.functional as F
from torchvision import transforms
from torchvision.datasets import MNIST
from torch.utils.data import DataLoader
import lightning.pytorch as pl# 2. 定义编码器和解码器
# 2.1 定义基础编码器Encoder
class Encoder(nn.Module):def __init__(self):super().__init__()self.l1 = nn.Sequential(nn.Linear(28 * 28, 64), nn.ReLU(), nn.Linear(64, 3))def forward(self, x):return self.l1(x)# 2.2 定义基础解码器Decoder
class Decoder(nn.Module):def __init__(self):super().__init__()self.l1 = nn.Sequential(nn.Linear(3, 64), nn.ReLU(), nn.Linear(64, 28 * 28))def forward(self, x):return self.l1(x)# 3. 定义LightningModule
class LitAutoEncoder(pl.LightningModule):# 3.1 加载基础模型def __init__(self, encoder, decoder):super().__init__()self.encoder = encoderself.decoder = decoder# 3.2 训练过程设置def training_step(self, batch, batch_idx):  # 每一个batch数据运算计算loss# training_step defines the train loop.x, y = batchx = x.view(x.size(0), -1)z = self.encoder(x)x_hat = self.decoder(z)loss = F.mse_loss(x_hat, x)return loss# 3.3 优化器设置def configure_optimizers(self):optimizer = torch.optim.Adam(self.parameters(), lr=1e-3)return optimizer# 4. 定义训练数据
dataset = MNIST(os.getcwd(), download=True, transform=transforms.ToTensor())
train_loader = DataLoader(dataset)# 5. 实例化模型
autoencoder = LitAutoEncoder(Encoder(), Decoder())# 6. 开始训练
trainer = pl.Trainer(max_epochs=10)
trainer.fit(model=autoencoder, train_dataloaders=train_loader)

class LitAutoEncoder(pl.LightningModule):

  • 将模型定义代码写在__init__
  • 定义前向传播逻辑
  • 将优化器代码写在 configure_optimizers 钩子中
  • 训练代码写在 training_step 钩子中,可使用 self.log 随时记录变量的值,会保存在 tensorboard 中
  • 验证代码写在 validation_step 钩子中
  • 移除硬件调用.cuda() 等,PyTorch Lightning 会自动将模型、张量的设备放置在合适的设备;移除.train() 等代码,这也会自动切换
  • 根据需要,重写其他钩子函数,例如 validation_epoch_end,对 validation_step 的结果进行汇总;train_dataloader,定义训练数据的加载逻辑
  • 实例化 Lightning Module 和 Trainer 对象,传入数据集
  • 定义训练参数和回调函数,例如训练设备、数量、保存策略,Early Stop、半精度等

运行结果:

2、添加验证和测试模块

在训练之后,加入了测试和评估功能,能更好的指导模型的性能。

# 1. 导入所需的模块
import os
import torch
from torch import nn
import torch.nn.functional as F
from torchvision import transforms
from torchvision.datasets import MNIST
from torch.utils.data import DataLoader
import lightning.pytorch as plimport torch.utils.data as data
from torchvision import datasets
import torchvision.transforms as transformsfrom torch.utils.data import DataLoader# 2. 定义编码器和解码器
# 2.1 定义基础编码器Encoder
class Encoder(nn.Module):def __init__(self):super().__init__()self.l1 = nn.Sequential(nn.Linear(28 * 28, 64), nn.ReLU(), nn.Linear(64, 3))def forward(self, x):return self.l1(x)# 2.2 定义基础解码器Decoder
class Decoder(nn.Module):def __init__(self):super().__init__()self.l1 = nn.Sequential(nn.Linear(3, 64), nn.ReLU(), nn.Linear(64, 28 * 28))def forward(self, x):return self.l1(x)# 3. 定义LightningModule
class LitAutoEncoder(pl.LightningModule):# 3.1 加载基础模型def __init__(self, encoder, decoder):super().__init__()self.encoder = encoderself.decoder = decoder# 3.2 训练过程设置def training_step(self, batch, batch_idx):  # 每一个batch数据运算计算loss# training_step defines the train loop.x, y = batchx = x.view(x.size(0), -1)z = self.encoder(x)x_hat = self.decoder(z)loss = F.mse_loss(x_hat, x)return loss# 3.3 测试过程设置def test_step(self, batch, batch_idx):# this is the test loopx, y = batchx = x.view(x.size(0), -1)z = self.encoder(x)x_hat = self.decoder(z)test_loss = F.mse_loss(x_hat, x)self.log("test_loss", test_loss)# 3.4 验证过程设置def validation_step(self, batch, batch_idx):# this is the validation loopx, y = batchx = x.view(x.size(0), -1)z = self.encoder(x)x_hat = self.decoder(z)val_loss = F.mse_loss(x_hat, x)self.log("val_loss", val_loss)# 3.5 优化器设置def configure_optimizers(self):optimizer = torch.optim.Adam(self.parameters(), lr=1e-3)return optimizer# 4. 定义训练数据
'''
dataset = MNIST(os.getcwd(), download=True, transform=transforms.ToTensor())
train_loader = DataLoader(dataset)
'''# 4.1 分别下载并加载训练集和测试集
transform = transforms.ToTensor()
train_set = datasets.MNIST(os.getcwd(), download=False, train=True, transform=transform)
test_set = datasets.MNIST(os.getcwd(), download=False, train=False, transform=transform)# 4.2 将训练集中的20%用于验证集
train_set_size = int(len(train_set) * 0.8)
valid_set_size = len(train_set) - train_set_size# 4.3 设置种子
seed = torch.Generator().manual_seed(42)# 4.4 从训练集中随机拿到80%的测试集和20%的验证集
train_set, valid_set = data.random_split(train_set, [train_set_size, valid_set_size], generator=seed)# 4.5 分别加载训练集和测试集
train_loader = DataLoader(train_set)
valid_loader = DataLoader(valid_set)# 5. 实例化模型
autoencoder = LitAutoEncoder(Encoder(), Decoder())# 6. 实例化Trainer
trainer = pl.Trainer(max_epochs=10)# 7. 开始训练和评估
trainer.fit(autoencoder, train_loader, valid_loader)# 8.开始测试
trainer.test(model=autoencoder, dataloaders=DataLoader(test_set))

3、权重 & 超参的保存和加载

当模型正在训练时,性能会随着它继续看到更多数据而发生变化。

1)训练完成后,使用在训练过程中发现的最佳性能相对应的权重;

2)权重可以让训练在训练过程中断的情况下从原来的位置恢复。

保存权重:Lightning 会自动为你在当前工作目录下保存一个权重,其中包含上一次训练的状态。这能确保在训练中断的情况下恢复训练。

3.1 自动在当前目录下保存checkpoint

# simply by using the Trainer you get automatic checkpointing
trainer = Trainer()

3.2 指定checkpoint保存的目录

# saves checkpoints to 'some/path/' at every epoch end
trainer = Trainer(default_root_dir="some/path/")

3.3 加载checkpoint

# trainer.fit(autoencoder, train_loader, valid_loader, ckpt_path="/home/gvlib_ljh/class/Lightning_mnist/lightning_logs/version_25/checkpoints/epoch=9-step=160000.ckpt")

4、可视化

在模型开发中,我们跟踪感兴趣的值,例如validation_loss,以可视化模型的学习过程。模型开发就像驾驶一辆没有窗户的汽车,图表和日志提供了了解汽车行驶方向的窗口。借助 Lightning,可以可视化任何您能想到的东西:数字、文本、图像、音频。

要跟踪指标,只需使用 LightningModule 内可用的 self.log 方法。

class LitModel(pl.LightningModule):def training_step(self, batch, batch_idx):value = ...self.log("some_value", value)

同时记录多个指标:

values = {"loss": loss, "acc": acc, "metric_n": metric_n}  # add more items if needed
self.log_dict(values)

4.1 命令行查看

要在命令行进度栏中查看指标,请将 prog_bar 参数设置为 True。

self.log(..., prog_bar=True)

4.2 浏览器查看

默认情况下,Lightning 使用 Tensorboard(如果可用)和一个简单的 CSV 记录器

在命令行中输入(注意:一定是lightning_logs所在的目录):

tensorboard --logdir=lightning_logs/

Tensorboard界面:

Tensorboard输出分析:

完整的代码:

# 1. 导入所需的模块
import os
import torch
from torch import nn
import torch.nn.functional as F
from torchvision import transforms
from torchvision.datasets import MNIST
from torch.utils.data import DataLoader
import lightning.pytorch as plimport torch.utils.data as data
from torchvision import datasets
import torchvision.transforms as transformsfrom torch.utils.data import DataLoaderfrom pytorch_lightning.loggers import TensorBoardLogger# 设置浮点矩阵乘法精度为 'medium'
torch.set_float32_matmul_precision('medium')# 2. 定义编码器和解码器
# 2.1 定义基础编码器Encoder
class Encoder(nn.Module):def __init__(self):super().__init__()self.l1 = nn.Sequential(nn.Linear(28 * 28, 64), nn.ReLU(), nn.Linear(64, 3))def forward(self, x):return self.l1(x)# 2.2 定义基础解码器Decoder
class Decoder(nn.Module):def __init__(self):super().__init__()self.l1 = nn.Sequential(nn.Linear(3, 64), nn.ReLU(), nn.Linear(64, 28 * 28))def forward(self, x):return self.l1(x)# 3. 定义LightningModule
class LitAutoEncoder(pl.LightningModule):# 3.1 加载基础模型def __init__(self, encoder, decoder):super().__init__()self.encoder = encoderself.decoder = decoder# 3.2 训练过程设置def training_step(self, batch, batch_idx):  # 每一个batch数据运算计算loss# training_step defines the train loop.x, y = batchx = x.view(x.size(0), -1)z = self.encoder(x)x_hat = self.decoder(z)loss = F.mse_loss(x_hat, x)batch_idx_value = batch_idx + 1print(" ")values = {"loss": loss, "batch_idx_value": batch_idx_value}  # add more items if neededself.log_dict(values)# 在命令行界面显示log'''sync_dist=True:分布式计算,数据同步标志prog_bar=True:在控制台上显示'''self.log("train_loss", loss, sync_dist=True, prog_bar=True)return loss# 3.3 测试过程设置def test_step(self, batch, batch_idx):x, y = batchx = x.view(x.size(0), -1)z = self.encoder(x)x_hat = self.decoder(z)test_loss = F.mse_loss(x_hat, x)self.log("test_loss", test_loss, sync_dist=True, prog_bar=True)# 3.4 验证过程设置def validation_step(self, batch, batch_idx):# this is the validation loopx, y = batchx = x.view(x.size(0), -1)z = self.encoder(x)x_hat = self.decoder(z)val_loss = F.mse_loss(x_hat, x)self.log("val_loss", val_loss, sync_dist=True, prog_bar=True)# 3.5 优化器设置def configure_optimizers(self):optimizer = torch.optim.Adam(self.parameters(), lr=1e-3)return optimizer# 4. 定义训练数据
'''
dataset = MNIST(os.getcwd(), download=True, transform=transforms.ToTensor())
train_loader = DataLoader(dataset)
'''# 4.1 分别下载并加载训练集和测试集
transform = transforms.ToTensor()
train_set = datasets.MNIST(os.getcwd(), download=False, train=True, transform=transform)
test_set = datasets.MNIST(os.getcwd(), download=False, train=False, transform=transform)# 4.2 将训练集中的20%用于验证集
train_set_size = int(len(train_set) * 0.8)
valid_set_size = len(train_set) - train_set_size# 4.3 设置种子
seed = torch.Generator().manual_seed(42)# 4.4 从训练集中随机拿到80%的测试集和20%的验证集
train_set, valid_set = data.random_split(train_set, [train_set_size, valid_set_size], generator=seed)# 4.5 分别加载训练集和测试集
train_loader = DataLoader(train_set, batch_size=256, num_workers=5)
valid_loader = DataLoader(valid_set, batch_size=128, num_workers=5)# 5. 实例化模型
autoencoder = LitAutoEncoder(Encoder(), Decoder())# 6. 实例化Trainer
trainer = pl.Trainer(max_epochs=1000)# 7. 开始训练和评估
trainer.fit(autoencoder, train_loader, valid_loader)
# 7. 从checkpoint恢复状态
# trainer.fit(autoencoder, train_loader, valid_loader, ckpt_path="/home/gvlib_ljh/class/Lightning_mnist/lightning_logs/version_25/checkpoints/epoch=9-step=160000.ckpt")# 8.开始测试
trainer.test(model=autoencoder, dataloaders=DataLoader(test_set))

参考:

https://zhuanlan.zhihu.com/p/659631467

这篇关于Pytorch-Lighting使用教程(MNIST为例)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1023290

相关文章

如何为Yarn配置国内源的详细教程

《如何为Yarn配置国内源的详细教程》在使用Yarn进行项目开发时,由于网络原因,直接使用官方源可能会导致下载速度慢或连接失败,配置国内源可以显著提高包的下载速度和稳定性,本文将详细介绍如何为Yarn... 目录一、查询当前使用的镜像源二、设置国内源1. 设置为淘宝镜像源2. 设置为其他国内源三、还原为官方

Python使用getopt处理命令行参数示例解析(最佳实践)

《Python使用getopt处理命令行参数示例解析(最佳实践)》getopt模块是Python标准库中一个简单但强大的命令行参数处理工具,它特别适合那些需要快速实现基本命令行参数解析的场景,或者需要... 目录为什么需要处理命令行参数?getopt模块基础实际应用示例与其他参数处理方式的比较常见问http

C 语言中enum枚举的定义和使用小结

《C语言中enum枚举的定义和使用小结》在C语言里,enum(枚举)是一种用户自定义的数据类型,它能够让你创建一组具名的整数常量,下面我会从定义、使用、特性等方面详细介绍enum,感兴趣的朋友一起看... 目录1、引言2、基本定义3、定义枚举变量4、自定义枚举常量的值5、枚举与switch语句结合使用6、枚

使用Python从PPT文档中提取图片和图片信息(如坐标、宽度和高度等)

《使用Python从PPT文档中提取图片和图片信息(如坐标、宽度和高度等)》PPT是一种高效的信息展示工具,广泛应用于教育、商务和设计等多个领域,PPT文档中常常包含丰富的图片内容,这些图片不仅提升了... 目录一、引言二、环境与工具三、python 提取PPT背景图片3.1 提取幻灯片背景图片3.2 提取

使用Python实现图像LBP特征提取的操作方法

《使用Python实现图像LBP特征提取的操作方法》LBP特征叫做局部二值模式,常用于纹理特征提取,并在纹理分类中具有较强的区分能力,本文给大家介绍了如何使用Python实现图像LBP特征提取的操作方... 目录一、LBP特征介绍二、LBP特征描述三、一些改进版本的LBP1.圆形LBP算子2.旋转不变的LB

Maven的使用和配置国内源的保姆级教程

《Maven的使用和配置国内源的保姆级教程》Maven是⼀个项目管理工具,基于POM(ProjectObjectModel,项目对象模型)的概念,Maven可以通过一小段描述信息来管理项目的构建,报告... 目录1. 什么是Maven?2.创建⼀个Maven项目3.Maven 核心功能4.使用Maven H

Python中__init__方法使用的深度解析

《Python中__init__方法使用的深度解析》在Python的面向对象编程(OOP)体系中,__init__方法如同建造房屋时的奠基仪式——它定义了对象诞生时的初始状态,下面我们就来深入了解下_... 目录一、__init__的基因图谱二、初始化过程的魔法时刻继承链中的初始化顺序self参数的奥秘默认

SpringBoot使用GZIP压缩反回数据问题

《SpringBoot使用GZIP压缩反回数据问题》:本文主要介绍SpringBoot使用GZIP压缩反回数据问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录SpringBoot使用GZIP压缩反回数据1、初识gzip2、gzip是什么,可以干什么?3、Spr

Spring Boot 集成 Quartz并使用Cron 表达式实现定时任务

《SpringBoot集成Quartz并使用Cron表达式实现定时任务》本篇文章介绍了如何在SpringBoot中集成Quartz进行定时任务调度,并通过Cron表达式控制任务... 目录前言1. 添加 Quartz 依赖2. 创建 Quartz 任务3. 配置 Quartz 任务调度4. 启动 Sprin

Linux下如何使用C++获取硬件信息

《Linux下如何使用C++获取硬件信息》这篇文章主要为大家详细介绍了如何使用C++实现获取CPU,主板,磁盘,BIOS信息等硬件信息,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录方法获取CPU信息:读取"/proc/cpuinfo"文件获取磁盘信息:读取"/proc/diskstats"文