使用Pytorch主要是为了它十分便利的库函数,不然和自己写又有什么区别呢,那么它最实用的两个库就是nn 和optim
nn是模型库,optim是优化器库,我们接下来就要用这两个库解决一个简单的线性回归问题
具体的实现过程可以分为三个步骤:
- 模型构建
- 训练器配置
- 循环迭代
模型训练
建立模型 —— 线性模型
class linearModel(torch.nn.Module):
# 构造函数
def __init__(self):
super().__init__() #super方法调用了父类Module的构造函数
#使用nn.Linear(1,1)建立单输入单输出的线性模型
# y = w * x + b
self.model = torch.nn.Linear(1, 1)
# 重载父类的forward函数,以供__call__函数调用
# 需要注意的是,传入forward的tensor必须是2阶tensor
# 如果是向量(1阶tensor),则需要使用tensor.view(100,1)方法转换成2阶
def forward(self, x):
return self.model(x)
配置模型训练器 —— 随机梯度下降 + 均方误差
class Train():
#构造函数,传入构造的模型
def __init__(self, model) -> None:
#定义模型
self.model = model
#定义优化器 —— SGD(随机梯度下降), 设置学习率lr
self.opt = torch.optim.SGD(model.parameters(), lr=1e-3)
#定义损失函数类型 —— MSELoss(均方误差)
self.loss = torch.nn.MSELoss()
训练循环
#设置了10000次迭代
for i in range(10000):
y = T.model(x1) # 正向预测,即套用模型,计算结果作为预测值
loss = T.loss(yreal, y) # 计算损失,即计算预测值与实际值的偏差
T.opt.zero_grad() # 将优化器中储存的权重weight和偏置bias置零,否则会不断累加
loss.backward() # 反向传播,根据模型的计算图,计算节点的梯度
T.opt.step() # 使用优化器更新参数
# 每1000次迭代,打印一次参数结果
if i % 1000 == 0:
print('grad w %f and r is %f' % (T.model.model.weight, T.model.model.bias))
# 定义额外跳出条件
# if not (abs(T.model.model.weight) > 1e-3 or abs(T.model.model.bias) > 1e-3) :
# break
需要注意的是:整个计算过程中的数据类型需要保持一致,默认的tensor类型为
dtype = tensor.float32
如果使用tensor(numpy())转化而来的tensor类型可能是double,需要在转化时进行类型指定
t = tensor(numpy.linspace(1,10,100), dtype = tensor.float32)
样例程序
from turtle import forward
import torch
import numpy as np
import time
import matplotlib.pyplot as plt
class linearModel(torch.nn.Module):
def __init__(self):
super().__init__()
self.model = torch.nn.Linear(1, 1)
def forward(self, x):
return self.model(x)
class Train():
def __init__(self, model) -> None:
self.model = model
self.opt = torch.optim.SGD(model.parameters(), lr=1e-3)
self.loss = torch.nn.MSELoss()
T = Train(linearModel())
x = torch.tensor(np.linspace(1,10,100), dtype=torch.float32).view(100,1)
x1 = torch.rand([50,1])
x1 = x
yreal = x1 * 3.24 - 4.21112 + torch.randn(x1.size())
for i in range(10000):
y = T.model(x1)
loss = T.loss(yreal, y)
T.opt.zero_grad()
loss.backward()
T.opt.step()
# 打印
if i % 1000 == 0:
print('grad w %f and r is %f' % (T.model.model.weight, T.model.model.bias))
# 跳出条件
# if not (abs(wt.grad) > 1e-3 or abs(bt.grad) > 1e-3) :
# break
y = T.model(x1)
plt.plot(x.data.numpy(),y.data.numpy())
plt.scatter(x.data.numpy(), yreal.data.numpy())
plt.show()