《nlp入门+实战:第五章:使用pytorch中的API实现线性回归》


上一篇: 《nlp入门+实战:第四章:使用pytorch手动实现线性回归 》

本章代码链接:

1.Pytorch完成模型常用的API

在前一部分。我们自己实现了通过torch的相关方法完成反向传播和参数更新,在pytorch中预设—些更加灵活简单的对象,让我们来构造模型、定义损失,优化损失等。

那么接下来,我们一起来了解一下其中常用的API

1.1 nn.Module

nn .Modul是torch.nn提供的一个类,是pytorch中我们自定义网络的一个基类,在这个类中定了很多有用的方法,让我们在继承这个类定义网络的时候非常简单。

当我们自定义网络的时候,有两个方法需要特别注意:

  • 1.__init__需要调用super方法,继承父类的属性和方法
  • 2.farward方法必须实现,用来定义我们的网络的向前计算的过程

用前面的y = wx+b的模型举例如下:

from torch import nn
import torch


class Lr(nn.Module):
    def __init__(self):
        super(Lr, self).__init__()  # 继承父类的init参数
        self.linear = nn.Linear(1, 1)  # 第一个参数:输入的形状 第二个参数:输出的形状 1:代表维度(也称为列数)

    def forward(self, x):
        out = self.linear(x)
        return out

注意:

  • 1.nn.Linear为torch预定义好的线性模型,也被称为全链接层,传入的参数为输入的数量,输出的数量(in_features, out_features),是(batch_size的列数)
  • 2.nn.Nodule定义了__ca11_方法,实现的就是调用forward方法。即Lr的实例,能够直接被传入参数调用,实际上调用的是forward方法并传入参数
# 实例化模型
model = Lr()
# 传入数据,计算结果
x = torch.rand([500, 1])  # 1阶,50行1列
predict = model(x)

拓展:上面的模型隐藏层只有一层,如果我们还想在加一层,只需像下面那样:

class Lr(nn.Module):
    def __init__(self):
        super(Lr, self).__init__()  # 继承父类的init参数
        # linear=nn.Linear(input的特征数量,输出的特征数量)
        self.linear = nn.Linear(1, 1)  # 第一个参数:输入的形状 第二个参数:输出的形状 1:代表维度(也称为列数)
        self.fcl = nn.Linear(1, 1)

    def forward(self, x):
        out = self.linear(x)
        out = self.fcl(out)
        return out

上面的代码表示我们输入会经过两层神经网络,如果你想在第二次使用激活函数,加入我们使用relu激活函数,可以像这样:

class Lr(nn.Module):
    def __init__(self):
        super(Lr, self).__init__()  # 继承父类的init参数
        # linear=nn.Linear(input的特征数量,输出的特征数量)
        self.linear = nn.Linear(1, 1)  # 第一个参数:输入的形状 第二个参数:输出的形状 1:代表维度(也称为列数)
        self.fcl = nn.Linear(1, 1)

    def forward(self, x):
        out = self.linear(x)
        out = self.fcl(out)
        out=nn.ReLU(out)
        return out

1.2 优化器类

优化器( optimizer),可以理解为torch为我们封装的用来进行更新参数的方法,比如常见的随机梯度下隆(stochastic gradient descent,SGD )

优化器类都是由torch.optim提供的,例如

  • 1.torch.optim.sGD(参数,学习率)
  • 2.torch.optim.Adam(参数,学习率)

注意:

  • 1.参数可以使用model.parameters()来获取,获取模型中所有requires_grad=True的参数
  • 2.优化类的使用方法
    • 1.实例化
    • 2所有参数的梯度,将其值置为0
    • 3.反向传播计算梯度
    • 4.更新参数值

示例如下:

optimizer = optim.SGD(model.parameters(), lr=le - 3)
optimizer.zero_gard()  # 梯度置0
loss.backward()  # 计算梯度
optimizer.step()  # 更新参数值

1.3损失函数

前面的例子是一个回归问题,torch中也预测了很多损失函数

  • 1.均方误差:nn.MSELoss(),常用于分类问题
  • 2.交叉嫡损失:nn.crossEntropyLoss(),常用语逻辑回归

使用方法:

# 传入数据,计算结果
x = torch.rand([500, 1])  # 1阶,50行1列
predict = model(x)
y = 3 * x + 0.8
model = Lr()  # 1.实例化模型
criterion = nn.MSELoss()  # 2.实例化损失函数
optimizer = optim.SGD(model.parameters(), lr=x.le - 3)  # 3.实例化优化器
for i in range(100):
    y_predict = model(x)  # 4.向前传播
    loss = criterion(y, y_predict)  # 5.调用损失函数传入真实值和预测值,得到损失结果
    optimizer.zero_grad()  # 5.当前循环参数梯度置为0
    loss.backward()  # 6.计算梯度
    optimizer.step()  # 7.更新参数的值

2.使用pytorch中的API实现线性回归

import torch
import torch.nn as nn
from torch.optim import SGD
from matplotlib import pyplot as plt

# 1.定义数据
x = torch.rand([500, 1], dtype=torch.float32)  # 1阶,50行1列
y = 3 * x + 0.8


# 2.定义模型
class Lr(nn.Module):
    def __init__(self):
        super(Lr, self).__init__()  # 继承父类的init参数
        # linear=nn.Linear(input的特征数量,输出的特征数量)
        self.linear = nn.Linear(1, 1)  # 第一个参数:输入的形状 第二个参数:输出的形状 1:代表维度(也称为列数)
        # self.fcl = nn.Linear(1, 1)

    def forward(self, x):
        out = self.linear(x)
        # out = self.fcl(out)
        # out=nn.ReLU(out)
        return out


# 3.实例化模型,loss和优化器
model = Lr()
loss_fn = nn.MSELoss()
optimizer = SGD(model.parameters(), 0.001)
# 4.训练模型
for i in range(30000):
    y_predict = model(x)  # 获取预测值
    loss = loss_fn(y, y_predict)  # 计算损失
    optimizer.zero_grad()  # 参数梯度置0
    loss.backward()  # 回归计算梯度
    optimizer.step()  # 更新梯度
    print("损失:{}".format(loss.data))
# 5.模型评估
model.eval()  # 设置模型为评估模式,即预测模式
predict = model(x)
predict = predict.data.numpy()
plt.scatter(x.data.numpy(), y.data.numpy(), c='b')
plt.plot(x.data.numpy(), predict, c='r')
plt.show()

在这里插入图片描述

注意:

  • model.eval表示设置模型为评估模式,即预测模式
  • model.train(mode=True)表示设置模型为训练模式

在当前的线性回归中,上述并无区别

但是在其他的一些模型中,训练的参数和预测的参数会不相同,到时候就需要具体告诉程序我们在进行训练还是预测,比如模型中存在Dropout,BatchNorm的时候

2.1 在GPU上运行代码

当模型太大,或者参数太多的情况下,为了加快训练速度,经常会使用GPU来进行训练此时我们的代码需要稍作调整:

  • 1.判断GPU是否可用torch.cuda.is_avai1able()
if torch.cuda.is_available():
    device = torch.device("cuda:0")  # cuda device对象,如果有多个GPU,取第一个
    y = torch.ones_like(t19, device=device)  # 创建一个cuda的tensor
    x = t19.to(device)  # 使用方法把t19转化为cuda的tensor
    z = x + y
    print(z.to("cpu", torch.double))  # .to方法也能够同时设置类型
else:
    print("您的设备不支持gpu运算")
  • 2.把模型参数和input数据转化为cuda的支持类型
model.to(device)
x_true.to(device)
  • 3.在GPU上计算结果也为cuda的数据类型,需要转化为numpy或者torch的cpu的tensor类型
predict=pridict.cpu().detach().numpy()

detach()的效果和data的相似,但是detach()是深拷贝,data是取值,是浅拷贝

修改之后的代码如下:

import torch
import torch.nn as nn
from torch.optim import SGD
from matplotlib import pyplot as plt

# 1.定义数据
x = torch.rand([500, 1], dtype=torch.float32)  # 1阶,50行1列
y = 3 * x + 0.8


# 2.定义模型
class Lr(nn.Module):
    def __init__(self):
        super(Lr, self).__init__()  # 继承父类的init参数
        # linear=nn.Linear(input的特征数量,输出的特征数量)
        self.linear = nn.Linear(1, 1)  # 第一个参数:输入的形状 第二个参数:输出的形状 1:代表维度(也称为列数)
        # self.fcl = nn.Linear(1, 1)

    def forward(self, x):
        out = self.linear(x)
        # out = self.fcl(out)
        # out=nn.ReLU(out)
        return out


# 3.实例化模型,loss和优化器
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
x, y = x.to(device), y.to(device)
model = Lr().to(device)
loss_fn = nn.MSELoss()
optimizer = SGD(model.parameters(), 0.001)
# 4.训练模型
for i in range(30000):
    y_predict = model(x)  # 获取预测值
    loss = loss_fn(y, y_predict)  # 计算损失
    optimizer.zero_grad()  # 参数梯度置0
    loss.backward()  # 回归计算梯度
    optimizer.step()  # 更新梯度
    print("损失:{}".format(loss.data))
# 5.模型评估
model.eval()  # 设置模型为评估模式,即预测模式
predict = model(x)
predict = predict.cpu().detach().numpy()
plt.scatter(x.cpu().detach().numpy(), y.cpu().detach().numpy(), c='b')
plt.plot(x.cpu().detach().numpy(), predict, c='r')
plt.show()

下一篇:《nlp入门+实战:第六章:常见优化器算法的介绍》

猜你喜欢

转载自blog.csdn.net/zhiyikeji/article/details/126039854