🍔 模型定义方法
学习目标
🍀 掌握PyTorch构建线性回归相关api
💘 使用PyTorch构建线性回归
前面我们使用手动的方式来构建了一个简单的线性回归模型,如果碰到一些较大的网络设计,手动构建过于繁琐。所以,我们需要学会使用 PyTorch 的各个组件来搭建网络。
接下来,我们使用 PyTorch 提供的接口来定义线性回归:
🍭 使用 PyTorch 的 nn.MSELoss() 代替自定义的平方损失函数
🍭 使用 PyTorch 的 data.DataLoader 代替自定义的数据加载器
🍭 使用 PyTorch 的 optim.SGD 代替自定义的优化器
🍭 使用 PyTorch 的 nn.Linear 代替自定义的假设函数
使用 PyTorch 来构建线性回归,直接上代码演示💯 :
import torch from torch.utils.data import TensorDataset from torch.utils.data import DataLoader import torch.nn as nn import torch.optim as optim from sklearn.datasets import make_regression import matplotlib.pyplot as plt # 构建数据集 def create_dataset(): x, y, coef = make_regression(n_samples=100, n_features=1, noise=10, coef=True, bias=14.5, random_state=0) # 将构建数据转换为张量类型 x = torch.tensor(x) y = torch.tensor(y) return x, y, coef def train(): # 构建数据集 x, y, coef = create_dataset() # 构建数据集对象 dataset = TensorDataset(x, y) # 构建数据加载器 dataloader = DataLoader(dataset, batch_size=16, shuffle=True) # 构建模型 model = nn.Linear(in_features=1, out_features=1) # 构建损失函数 criterion = nn.MSELoss() # 优化方法 optimizer = optim.SGD(model.parameters(), lr=1e-2) # 初始化训练参数 epochs = 100 for _ in range(epochs): for train_x, train_y in dataloader: # 将一个batch的训练数据送入模型 y_pred = model(train_x.type(torch.float32)) # 计算损失值 loss = criterion(y_pred, train_y.reshape(-1, 1).type(torch.float32)) # 梯度清零 optimizer.zero_grad() # 自动微分(反向传播) loss.backward() # 更新参数 optimizer.step() # 绘制拟合直线 plt.scatter(x, y) x = torch.linspace(x.min(), x.max(), 1000) y1 = torch.tensor([v * model.weight + model.bias for v in x]) y2 = torch.tensor([v * coef + 14.5 for v in x]) plt.plot(x, y1, label='训练') plt.plot(x, y1, label='真实') plt.grid() plt.legend() plt.show() if __name__ == '__main__': train()
程序运行结果:
从程序运行结果来看,我们绘制一条拟合的直线,和原始数据的直线基本吻合,说明我们训练的还不错。
🍔 模型的保存方法
学习目标
🍀 掌握PyTorch保存模型的方法
神经网络的训练有时需要几天、几周、甚至几个月,为了在每次使用模型时避免高代价的重复训练,我们就需要将模型序列化到磁盘中,使用的时候反序列化到内存中。
PyTorch 提供了两种保存模型的方法:
🐼 直接序列化模型对象
🐼 存储模型的网络参数
💘 直接序列化模型对象
import torch import torch.nn as nn import pickle class Model(nn.Module): def __init__(self, input_size, output_size): super(Model, self).__init__() self.linear1 = nn.Linear(input_size, input_size * 2) self.linear2 = nn.Linear(input_size * 2, output_size) def forward(self, inputs): inputs = self.linear1(inputs) output = self.linear2(inputs) return output def test01(): model = Model(128, 10) # 第一个参数: 存储的模型 # 第二个参数: 存储的路径 # 第三个参数: 使用的模块 # 第四个参数: 存储的协议 torch.save(model, 'model/test_model_save.pth', pickle_module=pickle, pickle_protocol=2) def test02(): # 第一个参数: 加载的路径 # 第二个参数: 模型加载的设备 # 第三个参数: 加载的模块 model = torch.load('model/test_model_save.pth', map_location='cpu', pickle_module=pickle) if __name__ == '__main__': test01() test02()
Python 的 Pickle 序列化协议有多种,详细可查看官网: Welcome to Python.org
注意: 当我们训练的模型在 GPU 中时,torch.save 函数将其存储到磁盘中。当再次加载该模型时,会将该模型从磁盘先加载到 CPU 中,再移动到指定的 GPU 中,例如: cuda:0、cuda:1。但是,当重新加载的机器不存在 GPU 时,模型加载可能会出错,这时,可通过 map_localtion=’CPU’ 将其加载到 CPU 中。
💘 存储模型的网络参数
import torch import torch.nn as nn import torch.optim as optim class Model(nn.Module): def __init__(self, input_size, output_size): super(Model, self).__init__() self.linear1 = nn.Linear(input_size, input_size * 2) self.linear2 = nn.Linear(input_size * 2, output_size) def forward(self, inputs): inputs = self.linear1(inputs) output = self.linear2(inputs) return output def test01(): model = Model(128, 10) optimizer = optim.Adam(model.parameters(), lr=1e-3) # 定义存储参数 save_params = { 'init_params': { 'input_size': 128, 'output_size': 10 }, 'acc_score': 0.98, 'avg_loss': 0.86, 'iter_numbers': 100, 'optim_params': optimizer.state_dict(), 'model_params': model.state_dict() } # 存储模型参数 torch.save(save_params, 'model/model_params.pth') def test02(): # 加载模型参数 model_params = torch.load('model/model_params.pth') # 初始化模型 model = Model(model_params['init_params']['input_size'], model_params['init_params']['output_size']) # 初始化优化器 optimizer = optim.Adam(model.parameters()) optimizer.load_state_dict(model_params['optim_params']) # 显示其他参数 print('迭代次数:', model_params['iter_numbers']) print('准确率:', model_params['acc_score']) print('平均损失:', model_params['avg_loss']) if __name__ == '__main__': test01() test02()
在上面代码中,我们把模型的一些初始化参数、模型的权重参数、训练的迭代次数、以及优化器的参数等都进行了存储。
💘 小节
本小节主要学习了如何定义和保存网络模型。我们可以直接存储模型对象,但是该方法依赖于 PyTorch 的实现,而存储模型参数与 PyTorch 的实现关系较弱,建议使用第二种方法来存储模型。
文章知识点与官方知识档案匹配,可进一步学习相关知识