[Pytorch]机器学习入门项目笔记:手动实现线性回归(3)

发布于 2022-09-02  327 次阅读


这是一个项目实践,通过自动微分、反向传播的方式来实现一个线性回归算法。

引入torch库

# 实现简单线性回归
import torch

定义超参数

# 定义超参数
learning_rate = 0.0007
times = 10000 * 8  # 训练次数

超参数就是在训练开始前需要预设的一些参数,这些参数会很大程度影响训练的速度和质量。

加载数据

这里随机生成一些点就可以了,根据函数表达式y = 3 * x + 0.8来构建x和y,定义域为[0, 1]。

x和y都是一个大小为[500, 1]的矩阵。

# 加载数据
x = torch.rand([500, 1])
y = 3 * x + 0.8

设置参数

这两个参数\(w, b\)就是我们要更新的两个值。

# 设置参数
w = torch.rand([1, 1], requires_grad=True, dtype=torch.float32)
b = torch.rand([1, 1], requires_grad=True, dtype=torch.float32)

在经过许多轮的训练后,计算机可以算出最好的w和b。

计算预测值和loss误差

我们要不断地修改\(w, b\),但是往那个方向修改呢?就是往loss减少的方向,也就是w和b的在loss上的导数的方向(也叫梯度下降的方向)。

loss的计算公式为\(loss = mean((y - y_{pre})^2)\),这里\(y\)和\(y_{pre}\)都是一个向量(一维矩阵)。

y_predict = torch.matmul(x, w) + b  # 因为是标量所以w * x + b也可以。
loss = (y - y_predict).pow(2).mean()

梯度下降更新w和b

注意前面的w和b有一个特殊的参数requires_grad=True,这表明w和b会被跟踪记录他们的梯度。

此时需要将loss反向传播,即可计算出w和b在loss上的梯度。

但是在前面一篇文章讲过《[Pytorch]机器学习入门项目笔记:自动微分(2) (eriktse.com)》,多次的backward一般是不允许的,因为这里的梯度是叠加上去算的,所以我们需要在每次训练开始将梯度初始化为0。

# 将梯度数据清空
    if w.grad is not None:
        w.grad.data.zero_()
    if b.grad is not None:
        b.grad.data.zero_()

    loss.backward()  # 反向传播
    w.data = w.data - w.grad * learning_rate  # 梯度下降
    b.data = b.data - b.grad * learning_rate
    if i % 50 == 0: print(w.item(), b.item(), loss.item())

完整代码

# 实现简单线性回归
import torch


# 定义超参数
learning_rate = 0.0007
times = 10000 * 8


# 加载数据
x = torch.rand([500, 1])
y = 3 * x + 0.8

# 设置参数
w = torch.rand([1, 1], requires_grad=True, dtype=torch.float32)
b = torch.rand([1, 1], requires_grad=True, dtype=torch.float32)

for i in range(times):
    y_predict = torch.matmul(x, w) + b
    loss = (y - y_predict).pow(2).mean()

    # 将梯度数据清空
    if w.grad is not None:
        w.grad.data.zero_()
    if b.grad is not None:
        b.grad.data.zero_()

    loss.backward()  # 反向传播
    w.data = w.data - w.grad * learning_rate  # 梯度下降
    b.data = b.data - b.grad * learning_rate
    if i % 50 == 0: print(w.item(), b.item(), loss.item())