线性回归Pytorch底层+简洁实现【初学者】

1. 内容来源

 08 线性回归 + 基础优化算法【动手学深度学习v2】_哔哩哔哩_bilibili08 线性回归 + 基础优化算法【动手学深度学习v2】共计5条视频,包括:线性回归、基础优化算法、线性回归的从零开始实现等,UP主更多精彩视频,请关注UP账号。https://www.bilibili.com/video/BV1PX4y1g7KC/?spm_id_from=333.999.0.0&vd_source=f94822d3eca79b8e245bb58bbced6b77

2. 底层实现

2.1 数据生成

本文使用以下公式加上噪声生成训练及测试数据:

2x_1 - 3.4x_2 + 4.2

代码实现:

import random
import torch

def synthetic_data(w, b, num_examples):
    x = torch.normal(0, 1, (num_examples, len(w)))
    y = torch.matmul(x, w) + b
    y += torch.normal(0, 0.001, y.shape)
    return x, y.reshape((-1, 1))

true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)

2.2 数据集生成

为之后代码可以直接迭代获取批量数据,自定义dataset生成函数

代码实现:

# Dataset Generation
def data_iter(batch_size, features, labels):
    num_examples = len(features)
    indices = list(range(num_examples))
    random.shuffle(indices)
    for i in range(0, num_examples, batch_size):
        batch_indices = torch.tensor(
            indices[i:min(i+batch_size, num_examples)])
        yield features[batch_indices], labels[batch_indices]

batch_size = 10

2.3 模型参数初始化

由于回归目标有三个参数,可与单层神经网络对应,故使用1层、2神经元的网络训练,则使用如下代码初始化参数并注明需要梯度(方便后续自动求解梯度进行反向传播优化)

代码实现:

# Parameters Initialization
w = torch.normal(0, 0.01, size=(2, 1), requires_grad=True)
b = torch.zeros(1, requires_grad=True)

2.4 模型构建

在单层神经网络中,前向运算即y = w*x + b

代码实现:

# Linear Regression Model
def linreg(X, w, b):
    return torch.matmul(X, w) + b

Loss函数使用均方误差

代码实现:

def squared_Loss(yhat, y):
    return (yhat - y.reshape(yhat.shape)) ** 2 / 2

优化方法使用随机梯度下降,前面参数初始化时已注明需要梯度,这里.grad可以直接获取当前参数的梯度,则当前参数减去learning rate * grad即为随机梯度下降(由于torch的grad会自动累加,每次更新完参数需要手动.grad.zero_()置零)

代码实现:

def sgd(params, lr, batch_size):
    with torch.no_grad():
        for param in params:
            param -= lr * param.grad / batch_size
            param.grad.zero_()

2.5 模型训练

learning rate和epochs总数设置为0.03和10。

每次优化循环中使用data_iter取出数据,使用loss计算损失序列,loss求和后使用.backward()更新每个参数的梯度,使用sgd利用梯度更新参数。

代码实现:

# Training
lr = 0.03
num_epochs = 3
net = linreg
loss = squared_Loss

for epoch in range(num_epochs):
    for X, y in data_iter(batch_size, features, labels):
        l = loss(net(X, w, b), y)
        l.sum().backward()
        sgd([w, b], lr, batch_size)
    with torch.no_grad():
        train_l = loss(net(features, w, b), labels)
        print(f'epoch {epoch + 1}, loss {float(train_l.mean()):f}')

结果:

epoch 1, loss 0.033998
epoch 2, loss 0.000075
epoch 3, loss 0.000001

3 简洁实现

3.1 数据生成

同第2节

代码实现:

import numpy as np
import torch
from torch.utils import data

true_w = torch.tensor([2, -3.4])
true_b = 4.2

features, labels =utils.synthetic_data(true_w, true_b, 1000)

def load_array(data_arrays, batch_size, is_train=True):
    dataset = data.TensorDataset(*data_arrays)
    return data.DataLoader(dataset, batch_size, shuffle=is_train)

batch_size = 10
data_iter = load_array((features, labels), batch_size)

3.2 模型构建

使用torch.nn.Linear(2, 1)代替第2节中手写的单层网络

代码实现:

# Model
from torch import nn

net = nn.Sequential(nn.Linear(2, 1))

使用net[0].weight.data/net[0].bias.data分别取出线性层的w和b,分别进行初始化

# Parameters

net[0].weight.data.normal_(0, 0.01)
net[0].bias.data.fill_(0)

Loss函数和SGD使用torch.nn.MSELoss()和torch.optim.SGD()

代码实现:

loss = nn.MSELoss()
trainer = torch.optim.SGD(net.parameters(), lr=0.03)

3.3 模型训练

与手写模型不同,使用trainer.zero_grad()将模型参数梯度置零,loss.backward()计算参数梯度,step()更新模型参数。

代码实现:

# Training
num_epochs = 3
for epoch in range(num_epochs):
    for X, y in data_iter:
        l = loss(net(X), y)
        trainer.zero_grad()
        l.backward()
        trainer.step() # Model parameters update
    
    l = loss(net(features), labels)
    print(f'epoch {epoch + 1}, loss {l:f}')

结果:

epoch 1, loss 0.000295
epoch 2, loss 0.000001
epoch 3, loss 0.000001

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

云龙弓手

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

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

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

打赏作者

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

抵扣说明:

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

余额充值