PyTorch深度学习实践——5 用PyTorch实现线性回归(课堂记录)

UP:B站-刘二大人

原视频链接:  05.用PyTorch实现线性回归_哔哩哔哩_bilibili

'''
一个小知识点:
当我们不知道传入的参数会有几个的时候,可以采用下面这种参数定义形式:
def func(*args,**kwargs): # 其中参数*args代表把前面n个参数变成元组的形式,**kwargs会把参数变成一个词典
   print(args)
   print(args[1])
   print(kwargs)

func(1,2,3,4,x=3,y=5)

输入结果:
(1,2,3,4)
2
{‘x’:3,‘y’:5}
'''

'''
第一步:准备数据
第二步:设计模型
第三步:构造损失函数与优化器(用pytorch接口)
第四步:训练周期(前馈、反馈、更新)

代码大致思路:
(1)铺垫:创建数据集、构建计算模型、定义损失函数和优化方式
(2)训练:通过forward函数进行前馈、loss记录损失值、清除上一次的梯度值、反向传播并记录梯度值grad、借助梯度值更新权重、循环上述过程
(3)测试:检测最终权重值是否符合预期
'''

import torch
import matplotlib.pyplot as plt

# 准备数据
# x,y是矩阵,3行1列 行表示样本,列表示维度,也就是说总共有3个数据,每个数据只有1个维度
x_data = torch.tensor([[1.0], [2.0], [3.0]])
y_data = torch.tensor([[2.0], [4.0], [6.0]])

# 设计模型,用class把模型定义成一个类
class LinearModel(torch.nn.Module): # 继承自Module,类中必须包含__init__和forward函数

    def __init__(self): # 构造函数
        super(LinearModel, self).__init__() # 必须要有这一步
        # torch.nn.Linear是pytorch里面的一个类,类后面加()表示构造一个对象
        # torch.nn.Linear构造的对象包含w和b两个tensor
        # torch.nn.Linear的参数:(in_features(输入样本维度),out_features(输出样本维度),bias=True(默认为true,表示用到偏置参数b))
        self.linear = torch.nn.Linear(1, 1) # 获取w和b的方式分别是linear.weight和linear.bias

# Module中实现了forward,因此下方需要重写forward函数覆盖掉Module中的forward,因此LinearModel必须重写forward
    def forward(self, x): #必须命名成forward(),前馈执行计算函数
        y_pred = self.linear(x) # 在对象后面加()意味着实现了一个可调用对象,输入参数x,计算y = w * x + b
        return y_pred

model = LinearModel() # 实例化模型

'''
torch.nn.MSELoss(size_average=None, reduce=None, reduction=‘mean’)
三个参数介绍:
如果同时给出了reduce、size_average、reduction三个参数,则首先看前两个参数。如果前两个参数均为None,则函数的返回值由reduction参数决定。
如果前两个参数不全为None,则函数的返回值由前两个参数决定,在这种情况下,为None的那个参数默认为True。

当reduce=True时,若size_average=True,则返回一个batch中所有样本损失的均值,结果为标量。
当reduce=True时,若size_average=False,则返回一个batch中所有样本损失的和,结果为标量。
当reduce=False时,则size_average参数失效,即无论size_average参数为False还是True,效果都是一样的。此时,函数返回的是一个batch中每个样本的损失,结果为向量。

reduction参数包含了reduce和size_average参数的双重含义。
即,当reduction=‘none’时,相当于reduce=False;当reduction=‘sum’时,相当于reduce=True且size_average=False;当reduction=‘mean’时,相当于reduce=True且size_average=True;
这也是为什么reduce和size_average参数将在后续版本中被弃用的原因。
'''

criterion = torch.nn.MSELoss(reduction='sum') # 损失函数,需要传入的参数即预测值y_pred和实际值y

'''
class torch.optim.SGD(params, lr= , momentum=0, dampening=0, weight_decay=0, nesterov=False)
各参数含义:
params (iterable) – 待优化参数的iterable或者是定义了参数组的dict,指定什么参数应当被优化
lr (float) – 学习率
momentum (float, 可选) – 动量因子(默认:0)
weight_decay (float, 可选) – 权重衰减(L2惩罚)(默认:0)
dampening (float, 可选) – 动量的抑制因子(默认:0)
nesterov (bool, 可选) – 使用Nesterov动量(默认:False)
更多用法参考:https://pytorch-cn.readthedocs.io/zh/latest/package_references/torch-optim/

torch中的其他优化器:torch.optim.Adagrad、torch.optim.Adam、torch.optim.Adamax、
torch.optim.ASGD、torch.optim.LBFGS、torch.optim.RMSprop、torch.optim.Rprop、torch.optim.SGD...
'''
optimizer = torch.optim.SGD(model.parameters(), lr = 0.01) # model.parameters()可以把model中所有需要训练的权重找出来

epoch_list = []
loss_list = []
w_list = []
b_list = []

for epoch in range(1000):
    y_pred = model(x_data) # 第一步,计算y_pred,把x_data输入到forward函数里
    loss = criterion(y_pred, y_data) # 第二步,计算损失
    print("epoch:", epoch, "loss:", loss.data.item())

    epoch_list.append(epoch)
    loss_list.append(loss.data.item())
    w_list.append(model.linear.weight.item())
    b_list.append(model.linear.bias.item())

    optimizer.zero_grad() # 清除上一次的梯度值
    loss.backward() # loss.backward()函数执行之后,grad值才开始更新,所以应该写在optimizer.zero_grad()函数之后,意思是先把上次的权重清零,再通过backward得到新的权重

    # 所有的optimizer都实现了step()方法,这个方法会更新所有的参数.一旦梯度被如backward()之类的函数计算好后,我们就可以调用这个函数。
    optimizer.step() # 通过梯度值对权重进行更新

print('w = ', model.linear.weight.item()) # 因为weight和bias都是张量,加item提取里面的值
print('b = ', model.linear.bias.item())

x_test = torch.tensor([[4.0]])
y_test = model(x_test) # 测试:用训练完成的权重进行预测
print('y_pred = ', y_test.data.item()) # 因为x_test是张量,所以y_test.data也是一个张量,如果需要输出数字,则加一个.item()

# 二维曲线图
plt.plot(epoch_list, loss_list)
plt.xlabel("epoch")
plt.ylabel("loss")
plt.show()

# 三维散点图
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(w_list, b_list, loss_list, c='r') # C即color,散点的颜色
#设置坐标轴
ax.set_xlabel('weight')
ax.set_ylabel('bias')
ax.set_zlabel('loss')
plt.show()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值