目标
我们想通过随机初始化的参数 ω , b \omega ,b ω,b能在迭代过程中使预测值和目标值能无限接近
y = ω x + b y=\omega x+b y=ωx+b
定义数据
x = torch.rand([60, 1])*10
y = x*2 + torch.randn(60,1)
构建模型
利用pytorch中的nn.Module
想要构建模型时,继承这个类即可
一些重写nn.Module类时的注意事项
(1)一般把网络中具有可学习参数的层(如全连接层、卷积层等)放在构造函数__init__()中;
(2)一般把不具有可学习参数的层(如ReLU、dropout、BatchNormanation层)可放在构造函数中,也可不放在构造函数中,如果不放在构造函数__init__里面,则在forward方法里面可以使用nn.functional来代替
(3)forward方法是必须要重写的,它是实现模型的功能,实现各个层之间的连接关系的核心。
from torch import nn
class Lr(nn.Module):def __init__(self):super(Lr, self).__init__() #继承父类init的参数self.linear = nn.Linear(1, 1) #只有线性层(全链接层)def forward(self, x):out = self.linear(x)#输出return out
输出的数量nn.Linear(in_features, out_features);nn.Linear(1, 1)这里的参数易知我们通过方程得到的最终是一列数
# 实例化模型
model = Lr()
# 传入数据,计算结果
predict = model(x)
优化器
1、优化器主要是在模型训练阶段对模型可学习参数进行更新, 常用优化器有 SGD,RMSprop,Adam等
2、优化器初始化时传入传入模型的可学习参数,以及其他超参数如 lr,momentum等
3、在训练过程中先调用 optimizer.zero_grad() 清空梯度,再调用 loss.backward() 反向传播,最后调用 optimizer.step()更新模型参数
4、参数可以使用model.parameters()来获取,获取模型中所有requires_grad=True的参数
optimizer = optim.SGD(model.parameters(), lr=1e-3) #1. 实例化,1e-3也可以写成0.001
optimizer.zero_grad() #2. 梯度置为0
loss.backward() #3. 计算梯度
optimizer.step() #4. 更新参数的值
损失函数
torch中有很多损失函数
1、均方误差:nn.MSELoss(),常用于回归问题
2、交叉熵损失:nn.CrossEntropyLoss(),常用于分类问题
criterion = nn.MSELoss() # 实例化损失函数
训练模型
1、定义一个epoch,代表需要将所有数据训练epoch个轮次
2、数据传入模型,获取预测值
3、将预测值和目标值传入损失函数,计算损失
4、优化器的梯度归零,在每次更新参数中必须进行此步骤,否则梯度会一直累加
5、计算梯度,此步骤在4之后进行
6、更新梯度,参数随之更新
7、(可选)在训练过程中每隔一段时间打印下损失,观察收敛速度
#训练模型
for i in range(30000):out = model(x) # 3.1 获取预测值loss = criterion(y, out) # 3.2 计算损失optimizer.zero_grad() # 3.3 梯度归零loss.backward() # 3.4 计算梯度optimizer.step() # 3.5 更新梯度if i % 300 == 0:print('Epoch[{}/{}], loss: {:.6f}'.format(i, 30000, loss.data))
模型测试
在模型的测试中,我们一般会使用测试集来评估训练得到的模型,这时候我们不需要梯度相关的操作,只需要将数据通过模型,得到损失、精确率等即可。测试中有以下需要注意:
model.eval() # 设置模型为评估模式,即预测模式
predict = model(x)
绘图
predict = predict.data.numpy()
plt.scatter(x.data.numpy(), y.data.numpy(), c="r")
plt.plot(x.data.numpy(), predict)
plt.show()
在GPU上运行
判断GPU是否可用torch.cuda.is_available()
1、torch.device(“cuda:0” if torch.cuda.is_available() else “cpu”)
device(type=‘cuda’, index=0) #使用gpu
device(type=‘cpu’) #使用cpu
2、把模型参数和input数据转化为cuda的支持类型
model.to(device)
x_true.to(device)
3、在GPU上计算结果也为cuda的数据类型,需要转化为numpy或者torch的cpu的tensor类型
predict = predict.cpu().detach().numpy()
detach()的效果和data的相似,但是detach()是深拷贝,data是取值,是浅拷贝
完整代码
import torch
from torch import nn
from torch import optim
import numpy as np
from matplotlib import pyplot as plt# 1. 定义数据
x = torch.rand([60, 1])*10
y = x*2 + torch.randn(60,1)# 2 .定义模型
class Lr(nn.Module):def __init__(self):super(Lr, self).__init__()self.linear = nn.Linear(1, 1)def forward(self, x):out = self.linear(x)return out# 2. 实例化模型,loss,和优化器
model = Lr()
# 损失函数
criterion = nn.MSELoss()
# 优化器
optimizer = optim.SGD(model.parameters(), lr=1e-3)
# 3. 训练模型
for i in range(30000):out = model(x) # 3.1 获取预测值loss = criterion(y, out) # 3.2 计算损失optimizer.zero_grad() # 3.3 梯度归零loss.backward() # 3.4 计算梯度optimizer.step() # 3.5 更新梯度if i % 300 == 0:print('Epoch[{}/{}], loss: {:.6f}'.format(i, 30000, loss.data))# 4. 模型评估
model.eval() # 设置模型为评估模式,即预测模式
predict = model(x)
predict = predict.data.numpy()
plt.scatter(x.data.numpy(), y.data.numpy(), c="r")
plt.plot(x.data.numpy(), predict)
plt.show()