PyTorch实现线性回归

用PyTorch实现线性回归(刘二大人pytorch第五讲)

用PyTorch学习框架写深度学习代码可以分为以下几个步骤:
步骤1,准备数据集,转换为tensor
步骤2,设计模型(构造计算图,用来计算\hat{y}
步骤3,选择损失和优化器
步骤4,写训练周期:前馈(算损失)、反馈(算梯度)、更新(使用梯度下降算法更新权重)

  1. 数据准备
    输入数据需要转换成tensor张量。
    在Mini_batch训练方式中,要使用张量(tensor)形式,而非直接使用数字作为输入。其原因有:(1)张量是多维数组,存储时可以利用GPU的内存空间,提高存储效率。在PyTorch中针对张量运算进行了高度优化,可以利用GPU的并行计算能力快速对张量进行各种数学运算,而数字无法利用GPU的并行计算能力;(2)在深度学习中,张量可以作为一种统一的数据结构来表示图片、音频、文本等不同类型的数据;(3)当使用张量进行计算时,深度学习框架会自动构建一个计算图,记录张量之间的运算关系,在反向传播过程中,框架可以根据间计算图自动计算每个张量的梯度,从而实现自动求导。如果直接使用数字作为输入,无法计算图。
  2. 设计模型(构造计算图)
    定义模型的模板:
# python
class LinearModel(torch.nn.Module):
    # 构造函数,用来存储需要用到的全局变量
    def __init__(self):  
        super(LinearModel, self).__init__()     # 调用父类的__init__方法。固定写法,必须有
        self.linear = torch.nn.Linear(1,1)   # 构造对象,Linear对象包含了权重、偏置
     # 自定义前向传播函数(函数重写)
     def forward(self,x):
        y_pred = self.linear(x)
        return y_pred    

不定义反向传播的原因:使用Module构造出来的对象,会自动根据计算图实现backward的过程。
自定义前向传播:因为Module类中对forward有定义,我们需要根据我们模型的需要对forward重写。

  1. 构造损失函数和优化器
criterion = torch.nn.MSELoss(size_average=False)  #需要的参数(y_pred,y)
optimizer = torch.optim.SGD(model.parameters(),lr=0.01) 

MSELoss继承自nn.Module,当输入的y\hat{y} 是 PyTorch 的 Tensor 且其 requires_grad 属性为 True 时,torch.nn.MSELoss 会构建计算图。
优化器SGD 不是Module,不会构建计算图。
model.parameters():parameters()会检查model里所有成员,如果成员里有相应的权重,就把权重都加在要训练的参数集合上。

  1. 训练单元
for epoch in range(1000):
    optimizer.zero_grad()   # 梯度清零
    y_pred = model(x_data)  # 前馈,计算预测值y_pred
    loss = criterion(y_pred, y_data)   # 计算损失。
    loss.backward()  # 损失反向传播
    optimizer.step()  # 梯度更新

注:在训练过程中,有可能看到,在训练集上随着epoch增加loss会逐渐减小,但在测试集上可能会出现随着epoch增加loss先增加后减小,这是因为过度训练造成过拟合了。所有在真正训练时,epoch的选定不仅要观察loss在训练集上的趋势,也要观察在测试集上的趋势。


整体代码:

# !usr/bin/env python
# -*- conding:utf-8 -*-
# 刘二大人第五讲(用PyTorch实现线性回归)


import torch
import matplotlib.pyplot as plt

# 准备数据
x_data = torch.Tensor([[1.0],[2.0],[3.0]])
y_data = torch.Tensor([[2.0],[4.0],[6.0]])

# 定义模型
class LinearModel(torch.nn.Module):
    def __init__(self):
        super(LinearModel, self).__init__()
        self.linear = torch.nn.Linear(1,1)
    
    def forward(self,x):
        y_pred = self.linear(x)
        return y_pred
# 模型实例化
model = LinearModel()

# 损失实例化 ,对torch.nn.MSELoss实例化后,得到一个可调用对象(即一个函数对象)criterion
criterion = torch.nn.MSELoss(size_average=False)
# 优化函数实例化
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

epoches=[]
losses=[]
for epoch in range(100):
    optimizer.zero_grad()
    y_pred = model(x_data)
    # 当调用criterion(y_pred,y_data) 时,y_pred,y_data会作为参数传递给criterion的__call__方法
    loss = criterion(y_pred,y_data)  # 计算损失
    print(epoch, loss.item())
    loss.backward()   # loss反向传播
    optimizer.step()   # 梯度更新

    epoches.append(epoch)
    losses.append(loss.item())
   
print('w=', model.linear.weight.item())
print('b=', model.linear.bias.item())

    
x_test = torch.Tensor([[4.0]])
y_test = model(x_test)
print('y_pred = ', y_test.data)
      
plt.figure(figsize=(10, 5))
plt.plot(epoches, losses)
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.title('Loss vs Epoch')
plt.show()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容