动手学人工智能-线性神经网络3-线性回归的简洁实现

251 阅读2分钟

1. 生成数据集

在构建模型之前,我们需要生成一个合适的数据集。我们可以用已知参数生成样本数据,从而在训练结束时检查模型是否能够有效逼近这些参数。

# d2l.py
def synthetic_data(w, b, num_examples):
    """生成y=Xw+b+噪声"""
    X = torch.normal(0, 1, (num_examples, len(w)), requires_grad=True)
    y = torch.matmul(X, w) + b
    y += torch.normal(0, 0.01, y.shape)
    return X, y.reshape((-1, 1))
w=[23.4],b=4.2\mathbf{w} = \begin{bmatrix} 2 \\ -3.4 \end{bmatrix}, \quad b = 4.2
import torch
import d2l

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

2. 读取数据集

我们可以通过 DataLoader 轻松创建一个数据迭代器,用于从数据集中逐批量提取数据。

# d2l.py
from torch.utils import data

def load_array(data_arrays, batch_size, is_train=True):
    """构造一个PyTorch数据迭代器"""
    dataset = data.TensorDataset(*data_arrays)
    return data.DataLoader(dataset, batch_size, shuffle=is_train)
batch_size = 10
data_iter = d2l.load_array((features, labels), batch_size)

这样我们可以在训练时分批读取数据,大大提高数据处理效率。

3. 定义模型

在 PyTorch 中,我们可以直接使用 nn.Sequential 类来快速构建一个全连接层的线性回归模型。

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

这行代码创建了一个包含一个输出节点的线性层。这里,输入形状为 22,输出形状为 11

y=wx+by = \mathbf{w}^\top \mathbf{x} + b

4. 初始化模型参数

我们用 normal_ 方法将权重参数从均值为 0、标准差为 0.01 的正态分布中随机采样,并将偏置初始化为零。

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

这一步有助于避免初始值相同导致的参数收敛过慢。

5. 定义损失函数

这里我们选择均方误差(MSE)作为损失函数。

loss = nn.MSELoss()

均方误差的公式为:

L(y^,y)=1ni=1n(y^(i)y(i))2L(\hat{y}, y) = \frac{1}{n} \sum_{i=1}^n (\hat{y}^{(i)} - y^{(i)})^2

6. 定义优化算法

PyTorch 提供了多种优化算法,我们这里使用小批量随机梯度下降(SGD)。

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

7. 训练

训练过程包括生成预测、计算损失、反向传播梯度和更新参数。每个周期结束后,我们都会打印损失。

num_epochs = 3
for epoch in range(num_epochs):
    for X, y in data_iter:
        y_hat = net(X)
        l = loss(y_hat, y)
        trainer.zero_grad()
        l.backward(retain_graph=True)
        trainer.step()

    l = loss(net(features), labels)
    print(f'epoch {epoch + 1}, loss {l:f}')
epoch 1, loss 0.000208
epoch 2, loss 0.000096
epoch 3, loss 0.000095

总结

通过以上步骤,我们用 PyTorch 框架高效地完成了线性回归的实现。这种方法不仅简化了模型定义和训练过程,也为后续更复杂的深度学习模型提供了基础。

import torch
from torch import nn
import d2l

num_examples = 1000  # 样本数
true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = d2l.synthetic_data(true_w, true_b, num_examples)

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

net = nn.Sequential(nn.Linear(2, 1))  # 定义线性模型

net[0].weight.data.normal_(0, 0.01)  # 初始化权重参数
net[0].bias.data.fill_(0)  # 初始化偏置参数

loss = nn.MSELoss()  # 均方差损失函数

# 小批量随机梯度下降(SGD)
trainer = torch.optim.SGD(net.parameters(), lr=0.03)

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(retain_graph=True)  # 反向传播
        trainer.step()  # 更新梯度

    l = loss(net(features), labels)
    print(f'epoch {epoch + 1}, loss {l:f}')