PyTorch:构建线性回归模型

写在前面

之前写过一篇博客,是不基于任何深度学习框架的纯numpy实现,其实整个过程比较繁琐。而深度学习框架能够提供给很多便利,避免一些重复性的工作,也使得代码变得更加简洁。本文主要是基于Pytorch框架实现一个线性回归模型。

基于numpy的线性回归模型构建:波士顿房价预测——线性模型(numpy实现)

代码

import依赖库

import torch
import torch.nn as nn
from time import time
import matplotlib.pyplot as plt
import random
import numpy as np
from mpl_toolkits.mplot3d import Axes3D 
%matplotlib inline

数据生成

人为地生成一批数据,基于y=2x1 - 3.4x2 + 4.2加上一些高斯噪声,从而生成一批数据(1000个)。

# 数据生成
true_w = [2, -3.4]
true_b = 4.2
features = torch.randn((1000, 2), dtype=torch.float32)  # x的shape为[1000, 2]
labels = true_w[0]*features[:,0] + true_w[1]*features[:,1] + true_b 
labels += torch.tensor(np.random.normal(0, 0.01, size=labels.size()), dtype=torch.float32) # label为Wx+b+噪声
features.shape, labels.shape 

(torch.Size([1000, 2]), torch.Size([1000]))

# 绘制三维散点图
fig = plt.figure()
ax = Axes3D(fig)
ax.scatter(features[:,0], features[:,1], labels)
plt.show()

在这里插入图片描述

导入数据

使用torch.utils.data构造Dataset,然后导入

import torch.utils.data as Data  # 导入data包

# 定义batchsize
batch_size = 10
# 利用TensorDataset封装为一个torch的Dataset
dataset = Data.TensorDataset(features, labels)
# 使用DataLoader加载数据
data_iter = Data.DataLoader(dataset, batch_size=batch_size, shuffle=True)
构建模型

nn意为neural network,torch的nn模块提供了很多可直接调用的API用于构建网络模型。
nn的核心数据结构是Module,它是一个抽象概念,既可以表示神经网络中的某个层(layer),也可以表示一个包含很多层的神经网络。在实际使用中,最常见的做法是继承nn.Module,撰写自己的网络/层。一个nn.Module实例应该包含一些层以及返回输出的前向传播(forward)方法。

# 构建模型
class LinearNet(nn.Module):
    def __init__(self, n_feature):
        super().__init__()
        self.linear = nn.Linear(n_feature, 1)	# Linear层 传入input sample、output的size
        self.initialize_weight()  # 初始化权重
    
    def forward(self, x):
        z = self.linear(x)
        return z
    
    def initialize_weight(self):  # 参数初始化
        for m in self.modules(): 
            if isinstance(m, nn.Linear): # isinstance() 函数来判断一个对象是否是一个已知的类型
                nn.init.normal_(m.weight, 0, 0.01)
                nn.init.constant_(m.bias, 0)
                
net = LinearNet(2) # 实例化模型
print(net) # 打印网络结构
for name,param in net.named_parameters():  # 通过named_parameters()来查看网络的参数和对应的name
    print(name,param)
定义优化器和损失函数

使用torch.optim定义优化器,nn定义损失函数

# 定义优化器以及loss function
import torch.optim as optim

criterion = nn.MSELoss()  ## nn中提供了很多损失函数,这里使用MSE
optimizer = optim.SGD(net.parameters(), lr=0.03)  # optim提供了许多优化器选择 使用简单的SGD

还可以为不同子网络(层)设置不同的学习率,这在finetune时经常用到,下例与Linear Model无关,因为线性回归只有层。

optimizer = optim.SGD([
    # 如果对某个参数不指定学习率,就使用最外层的默认学习率
    {'params': net.subnet1.parameters()}, # lr=0.03
    {'params': net.subnet2.parameters(), 'lr':0.01}
], lr=0.03)

有时候对于学习率的调整,我们也不希望是一成不变的,希望是随着训练轮次的增加动态调整的。
这主要有两种做法:一种是修改optimizer.param_groups中对应的学习率,另一种是更简单也是较为推荐的做法——新建优化器,由于optimizer十分轻量级,构建开销很小,故而可以构建新的optimizer。

# 调整学习率
for param_group in optimizer.param_groups:
    param_group['lr'] *= 0.1 # 学习率为之前的0.1倍

但是后者对于使用动量的优化器(如Adam),会丢失动量等状态信息,可能会造成损失函数的收敛出现震荡等情况。

模型训练
epochs = 3
for epoch in range(epochs):
    epoch_loss = 0.
    for (x, y) in data_iter:
        optimizer.zero_grad()	# 梯度清零
        z = net(x) 	# 前向传递
        loss = criterion(z, y.view(-1,1)) # 求loss
        epoch_loss += loss.item()
        loss.backward()  # loss反向传播
        optimizer.step()	# 更新参数
    if (epoch+1)%1==0:
        print("epoch{} loss: {}".format(epoch+1, epoch_loss))

epoch1 loss: 94.01486129091427
epoch2 loss: 0.010219457717539626
epoch3 loss: 0.010239769631880336

检验

对比模型参数与标准设置参数:

for param in net.parameters():
    print(param)

for param in net.parameters():
print(param)

可以看到结果还是很不错的

参考

[1] https://github.com/ShusenTang/Dive-into-DL-PyTorch/blob/master/docs/chapter03_DL-basics/3.3_linear-regression-pytorch.md 《Dive-into-DL-PyTorch》
[2] https://zh.gluon.ai/chapter_deep-learning-basics/linear-regression-gluon.html 李沐《动手学深度学习》

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值