刘二大人 《PyTorch深度学习实践》P5 用PyTorch实现线性回归

用PyTorch实现线性回归

线性回归的基本概念

概念:只具有一个神经元的最简单的神经网络

步骤:

  1. 构建数据集
  2. 设计模型,前馈,用来计算预测 y ˉ \bar{y} yˉ
  3. 构造损失函数和优化器,使用PyTorch的API
  4. 训练周期,前馈(算损失) =》 反馈(算梯度)=》更新(更新权重)

numpy有一种机制,称为广播机制

如下例:3 * 3 + 3 * 1自动广播为3 * 3 + 3 * 3

在这里插入图片描述

设计模型:

输入数据都是矩阵。必须确定x和 y ˉ \bar{y} yˉ的维度,我们才能够得出w(权重)、b(偏执量)的维度

loss最终需要是一个标量,如果是一个向量是无法进行backward的,但经过上述矩阵计算我们得到的还是一个矩阵,因此对所有loss求平均值,在进行backward()。

在这里插入图片描述

有时需要做转置拼维度,目的都是为了把矩阵拼出来

在这里插入图片描述

torch.nn.Linear类的介绍

在这里插入图片描述

torch.nn.Linear类实现了魔术方法__call()__,这使得该类的实例可以像函数一样被调用,通常forward()会被调用。

class Foobar:
	def __init__(self):
		super().__init__()
		print('__init__函数被调用了')
		pass
  
    def __call__(self, *args, **kwargs):
        # *args 可变长参数(无名参数) 把前面n个参数变成n元组
        # **kwargs 把参数变成词典词典 x=2, y=3 ==> {x:2, y:3}
        print('__call__函数被调用了')
        print('Hello:' + str(args[0]))
        print('Hello:' + str(kwargs))
        self.forward()

    def forward(self):
        print('forward函数被调用了')
        
foobar = Foobar()
foobar(1, 2, 3, x = 1, y = 2)

运算结果:

__init__函数被调用了
__call__函数被调用了
Hello:1
Hello:{'x': 1, 'y': 2}
forward函数被调用了

线性回归代码实现:

import torch
import matplotlib.pyplot as plt

# 数据集 3行1列的矩阵
x_data = torch.tensor([[1.0], [2.0], [3.0]])
y_data = torch.tensor([[2.0], [4.0], [6.0]])


# 模型定义成一个类,将来可以扩展模型,以适应于各种各样的任务
# 所有类都要继承Module,里面有好多方法可以直接使用
# nn 是 Netural Network的缩写
class LinearModel(torch.nn.Module):
    # 类中至少要实现两个函数
    # 1. 构造函数:用来初始化对象
    def __init__(self):
        # 调用父类的构造函数 LinearModel:模型名称
        super(LinearModel, self).__init__()

        # torch.nn.Linear是PyTorch里面的一个类
        # torch.nn.Linear(1, 1) 在构造一个对象,包含了权重和偏置两个tensor
        # 可以自动来完成 x*w + b的计算
        # Linear(1, 1)也是继承自Module,也可以自动进行backward计算
        self.linear = torch.nn.Linear(1, 1)

    # 参数:in_features 输入纬度 out_features 输出纬度 bias 默认为True

    # 2. 前馈函数:进行前馈需要执行的计算
    # pytorch在nn.Module中,实现了__call__方法,而在__call__方法中调用了forward函数
    # 因此新写的类中需要重写forward()以覆盖掉父类中的forward()
    # 该函数的另一个作用是可以直接在对象后面加()
    # 例如实例化的model对象,和实例化的linear对象
    # pytorch也是按照__init__, __call__, forward三个函数实现网络层之间的架构的
    def forward(self, x):
        y_pred = self.linear(x)  # 对象后面加(),说明实现了一个可调用的对象
        return y_pred


# 用Module构造出来的对象,会根据计算图自动进行backward()的计算
# 如果自己定义的模型,没办法进行求倒数
# 方法一:模块由PyTorch基本计算封装成类,实例化Module,调用即可
# 方法二:自己有更快的计算方式,可以在Functions类里构造计算块,进行继承
# 当然,直接用Module里面的模块算是最简单的

# 模型实例化
model = LinearModel()

criterion = torch.nn.MSELoss(reduction='sum')
# size_average = False 损失是否求均值 没啥用 python新版本改成了 ==》reduction='sum'
# reduction-三个值,none: 不使用约简;mean:返回loss和的平均值;sum:返回loss的和。默认:mean。
# 做mini batch 可以设置为True 不过影响也不是很大
# reduce 用来确定是否降维 不考虑

optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
# 优化器与Module无关,不会构建计算图
# 传入数据为单个,为随机梯度下降
# 传入数据为batch,为批量梯度下降,此处为SGD
# 类SGD model.parameters() 把linear里的w都拿出来
# lr 学习率

# 1.先算y_pred
# 2. loss 梯度清0
# 3. backward
# 4. update

epoch_list = []
loss_list = []

for epoch in range(100):
    y_pred = model(x_data)  # forward 计算y_pred
    loss = criterion(y_pred, y_data)  # 计算损失
    # print(type(loss))
    print(epoch, loss.item())

    epoch_list.append(epoch)
    loss_list.append(loss.item())

    optimizer.zero_grad()  # 梯度归0
    loss.backward()  # backward 计算梯度
    optimizer.step()  # update w, b

# 输出权重和偏置
print('w=', model.linear.weight.item())
# weight是一个矩阵,item()才是值
print('b=', model.linear.bias.item())

# Test Model
x_test = torch.tensor([[4.0]])
y_test = model(x_test)
print('y_pred=', y_test.item())

# 画图
figure = plt.figure("线性回归")
ax = figure.add_subplot()
ax.plot(epoch_list, loss_list)
plt.show()

作业:使用不同优化器查看其区别

  • torch.optim.Adagrad
  • torch.optim.Adam
  • torch.optim.Adamax
  • torch.optim.ASGD
  • torch.optim.LBFGS
  • torch.optim.RMSprop
  • torch.optim.Rprop
  • torch.optim.SGD

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李闪火

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值