• 《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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    注意:

    • 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)
    
    • 1
    • 2
    • 3
    • 4
    • 5

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

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    上面的代码表示我们输入会经过两层神经网络,如果你想在第二次使用激活函数,加入我们使用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
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    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
    • 2
    • 3
    • 4

    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.更新参数的值
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    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()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    在这里插入图片描述

    注意:

    • model.eva1表示设置模型为评估模式,即预测模式
    • 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运算")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 2.把模型参数和input数据转化为cuda的支持类型
    model.to(device)
    x_true.to(device)
    
    • 1
    • 2
    • 3.在GPU上计算结果也为cuda的数据类型,需要转化为numpy或者torch的cpu的tensor类型
    predict=pridict.cpu().detach().numpy()
    
    • 1

    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()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

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

  • 相关阅读:
    深度学习在图像识别领域还有哪些应用?
    NX二次开发-通过获取窗口句柄方式来设置类型过滤器EnumChildWindows
    molecular-graph-bert(一)
    记liunx服务器java程序无法访问的问题处理
    leetcode 47. 全排列 II(46题变形)
    【计算机视觉 | 目标检测】arxiv 计算机视觉关于目标检测的学术速递(8 月 24 日论文合集)
    Aviation turbofan starting model
    使用bloodyAD对域属性进行查询与修改
    html css3 旋转
    MobileSAM论文笔记
  • 原文地址:https://blog.csdn.net/zhiyikeji/article/details/126039854