PyTorch-24h 01_PyTorch深度学习流程
2023-06-13 09:17:15 时间
以学习一条直线y=ax+b为例演示PyTorch深度学习流程。末尾(第6节)有完整代码。笔记写的比较简单,详细的Notebook见24小时入门PyTorch深度学习。
1. 准备数据
- • 加载数据:加载数据通常要实现自定义的Dataset和DataLoader。本章是直接用了一条直线的数据。
- • 划分训练集、测试集、验证集(如果需要):通常,训练集占比60% ~ 80%, 测试集占比10% ~ 20%,验证集占比10% ~ 20%
2. 创建模型
torch中的重要模块:
- • torch.nn:计算图相关
- • torch.nn.Parameter: 存储 tensors 可用于 nn.Module. 如果 requires_grad=True ,梯度会自动计算, 通常称为"自动求导(autograd)".
- • torch.nn.Module:所有神经网络模块的基类。如果你在PyTorch中构造自己的神经网络模型, 你的模型需要继承 nn.Module,并实现forward()方法
#2. 创建模型
#通过继承 nn.Module 来创建自己的模型
class LinearRegressionModelV2(nn.Module):
def __init__(self):
super().__init__()
# Use nn.Linear() for creating the model parameters
self.linear_layer = nn.Linear(in_features=1,
out_features=1)
# 定义forward函数(也就是计算过程)
def forward(self, x: torch.Tensor) -> torch.Tensor:
return self.linear_layer(x)
3. 训练:模型拟合数据
- • loss:计算模型预测和真实值的误差。
torch.nn
.有许多内置损失函数例如:loss_fn = nn.L1Loss() # MAE loss is same as L1Loss
- • Optimizer 告诉模型如何更新其内部参数以降低loss。
torch.optim
有很多优化器,如torch.optim.SGD()
、torch.optim.Adam()
optimizer = torch.optim.SGD(params=model_0.parameters(), # parameters of target model to optimize
lr=0.01) # learning rate
- • 优化循环
- • training loop
1.forward 进行预测:
y_pred = model(x_train)
- 2.计算loss:
loss = loss_fn(y_pred, y_train)
- 3. 梯度清零:
optimizer.zero_grad()
- 4. 在loss上反向传播:
loss.backward()
- 5.通过优化器更新模型参数:
optimizer.step()
- 2.计算loss:
- • testing loop
- 1. forward
y_pred = model(x_test)
- 2. loss
loss = loss_fn(y_pred, y_test)
- 3. 计算评价指标(可选)
- 1. forward
- • training loop
1.forward 进行预测:
4. 使用模型推理(inference)
推理时不需要模型计算梯度,通过下面操作实现推理:
设置模型为评估模式:model.eval()
.
使用推理上下文管理器: with torch.inference_mode():
注意:PyTorch1.10 之后才有推理模式。之前的版本可以用
with torch.no_grad()
预测时,所有对象(数据和模型)应该在同一个设备上
推理示例:
model_0.eval()
with torch.inference_mode():
y_preds = model_0(X_test)
5. 保存/加载模型
5.1 保存模型
通过torch.save(状态字典,保存路径)
保存模型的状态字典(state_dict())。
state_dict
保存了模型的参数。
5.2 加载模型
模型加载之前保存的状态字典:
model_0.load_state_dict(torch.load(f=MODEL_SAVE_PATH))
6. 完整流程
将上面5个步骤组合起来,就得到一个完整的学习流程。
# 通过线性模型学习直线 y = w*x + b的w和b参数
import torch
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Using device: {device}")
#1. 准备数据
weight,bias = 0.7, 0.3
# Create X and y (features and labels)
start, end, step = 0, 1, 0.02
X = torch.arange(start, end, step).unsqueeze(dim=1)
y = weight * X + bias
# Split data
train_split = int(0.8 * len(X))
X_train, y_train = X[:train_split], y[:train_split]
X_test, y_test = X[train_split:], y[train_split:]
len(X_train), len(y_train), len(X_test), len(y_test)
#2. 创建模型
#通过继承 nn.Module 来创建自己的模型
class LinearRegressionModelV2(nn.Module):
def __init__(self):
super().__init__()
# Use nn.Linear() for creating the model parameters
self.linear_layer = nn.Linear(in_features=1,
out_features=1)
# 定义forward函数(也就是计算过程)
def forward(self, x: torch.Tensor) -> torch.Tensor:
return self.linear_layer(x)
torch.manual_seed(42) # 设置随机种子
model_1 = LinearRegressionModelV2()
model_1.to(device)
# 可以print model_1, model_1.state_dict()
# 3. 训练
# loss 函数
loss_fn = nn.L1Loss()
# optimizer
optimizer = torch.optim.SGD(params=model_1.parameters(),
lr=0.01)
# 设置epochs (训练次数)
epochs = 1000
# to device
X_train = X_train.to(device)
X_test = X_test.to(device)
y_train = y_train.to(device)
y_test = y_test.to(device)
# 训练epochs 次
for epoch in range(epochs):
### Training
model_1.train()
y_pred = model_1(X_train) # 1. Forward pass
loss = loss_fn(y_pred, y_train) # 2. Calculate loss
optimizer.zero_grad() # 3. Zero grad optimizer
loss.backward() # 4. Loss backward
optimizer.step() # 5. Step the optimizer
### Testing
model_1.eval() # 将模型设置为eval(评估)模式,不需要计算梯度
with torch.inference_mode():
test_pred = model_1(X_test)
test_loss = loss_fn(test_pred, y_test)
if epoch % 100 == 0:
print(f"Epoch: {epoch} | Train loss: {loss} | Test loss: {test_loss}")
# 4. 推理
# 查看模型参数
from pprint import pprint # pprint = pretty print, see: https://docs.python.org/3/library/pprint.html
print("The model learned the following values for weights and bias:")
pprint(model_1.state_dict())
print("\nAnd the original values for weights and bias are:")
print(f"weights: {weight}, bias: {bias}")
#
model_1.eval()
# Make predictions on the test data
with torch.inference_mode():
y_preds = model_1(X_test)
print(f"y_preds={y_preds}")
# 5. 保存模型参数
from pathlib import Path
# 创建models目录
MODEL_PATH = Path("models")
MODEL_PATH.mkdir(parents=True, exist_ok=True)
# 创建保存路径
MODEL_NAME = "01_pytorch_workflow_model_1.pth"
MODEL_SAVE_PATH = MODEL_PATH / MODEL_NAME
# 保存参数字典
print(f"Saving model to: {MODEL_SAVE_PATH}")
torch.save(obj=model_1.state_dict(),
f=MODEL_SAVE_PATH)
loaded_model_1 = LinearRegressionModelV2()
loaded_model_1.load_state_dict(torch.load(MODEL_SAVE_PATH))
loaded_model_1.to(device)
print(f"Loaded model:\n{loaded_model_1}")
print(f"Model on device:\n{next(loaded_model_1.parameters()).device}")
# 评估加载字典后的模型
loaded_model_1.eval()
with torch.inference_mode():
loaded_model_1_preds = loaded_model_1(X_test)
print(y_preds == loaded_model_1_preds)
相关文章
- 后端框架的学习流程[通俗易懂]
- hostapd中beacon流程
- Android系统启动流程 -- 学习笔记
- py学习(流程控制语句和组合数据类型)
- 构造流程源码分析:ApplicationListener加载
- Java的学习笔记(03)控制流程
- 【设计模式】适配器模式 ( 概念 | 适用场景 | 优缺点 | 外观模式对比 | 适配器模式相关角色 | 类适配器 | 对象适配器 | 实现流程 )
- 【计算机网络】数据链路层 : 差错控制 ( 纠错编码 | 海明码 | “海明码“ 原理 | “海明码“ 工作流程 | 确定校验啊位数 | 确定校验码和数据位置 | 求校验码值 | 检错纠错 )★
- 【2023新书】可信机器学习实战:透明和公平的AI流程
- 【Android 启动过程】Activity 启动源码分析 ( ActivityThread 流程分析 一 )
- Python流程控制语句有哪几种?流程控制语句详解
- RabbitMQ学习之(一)_初步了解RabbitMQ、RabbitMQ的使用流程、为什么要使用RabbitMQ、RabbitMQ的应用场景详解程序员
- servlet处理用户请求的完整流程
- SQLMAP源码分析Part1.流程篇
- Linux 学习之路:入门指南及基础流程(linux学习流程)
- 「Linux软件开发教程」:学习Linux基础知识与开发技巧,掌握软件开发流程,增强编程实践能力,提高编程效率。(linux软件开发教程)
- 命令行连接外网MySQL数据库流程与指南(cmd连接外网mysql)
- BNET与MySQL连接,学习双方流程(bnet连接mysql)
- Oracle安装流程从图解更易懂(oracle下载图解)
- Nginx学习笔记之事件驱动框架处理流程