沐神《动手学深度学习》之3.3线性回归简单实现
前言
上一节代码没看懂无所谓,但是这章的要看懂。搞懂这个,大概就能明白训练是怎么回事了,其他的无非是换个模型的事。好了,现在我们开始。
一、生成数据集
这里我仍然没用d2l包,所以直接用了上一节的数据生成代码。
import numpy as np
import torch
from torch.utils import data
# 真实参数
true_w = torch.tensor([2, -3.4])
true_b = 4.2
# 生成合成数据(替代d2l.synthetic_data)
def synthetic_data(w, b, num_examples):
"""生成y = Xw + b + 噪声的数据"""
X = torch.normal(0, 1, (num_examples, len(w))) # 生成特征矩阵
y = torch.matmul(X, w) + b # 计算线性模型
y += torch.normal(0, 0.01, y.shape) # 添加噪声
return X, y.reshape((-1, 1))
# 生成数据
features, labels = synthetic_data(true_w, true_b, 1000)
二、读取数据集
def load_array(data_arrays, batch_size, is_train=True): #@save
"""构造一个PyTorch数据迭代器"""
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)
之前我们需要了根据特征数量创建索引列表,这里我们只用Tensordataset自动建立特征和标签的对应关系。之前我们还要手写for循环,把数据按批次打包,这里我们只要用DataLoader方法就可以实现。
1. TensorDataset
-
将特征和标签打包成一个数据集
-
*data_arrays解包元组,假设data_arrays = (features, labels) -
相当于创建了
(特征, 标签)的配对数据集
2. DataLoader
-
从数据集中按批次加载数据
-
batch_size=10:每批10个样本 -
shuffle=is_train:训练时打乱数据顺序(避免模型记忆样本顺序)
三、定义模型
实际上,标题用调用模型更加合适,线性回归模型不复杂,可以手搓。但是如果是特别复杂的通用模型,使用别人写好的模型符合编程的思想。
from torch import nn
net = nn.Sequential(nn.Linear(2, 1))
第一个指定输入特征形状,即2,第二个指定输出特征形状,输出特征形状为单个标量,因此为1。
这是Linear类的介绍,翻译以下就是“对传入数据应用仿射线性变换,x = xA^T + b”

nn.Sequential是PyTorch中的一个顺序容器,用于将多个网络层按顺序组合在一起。它将多个层按顺序连接起来,数据会依次通过容器中的每个层。只不过,这里只有一个线性回归层。
四、初始化模型参数
net[0].weight.data.normal_(0, 0.01) # 权重初始化
net[0].bias.data.fill_(0) # 偏置初始化
net[0]访问Sequential容器中的第一层,在代码中就是nn.Linear(2,1)层。
net[0].weight获取线性层的权重,初始值是PyTorch随即初始化的值。
net[0].weight.data获取权重参数的张量数据(不包含梯度信息)。
net[0].weight.data.normal_(0,0.01)从均值为0,标准差为0.01的正态分布中采样,替换当前权重值。
net[0].bias.data获取偏置参数的张量数据。
net[0].bias.data.fill_(0)把获取的张量数据设置成0
五、定义损失函数
loss = nn.MSELoss()#MSELoss类,也称为平方L2范数.默认情况下,它返回所有样本损失的平均值。
六、定义优化算法
trainer = torch.optim.SGD(net.parameters(), lr=0.03)
原书上面有写: PyTorch在optim模块中实现了该算法的许多变种。 当我们实例化一个SGD实例时,我们要指定优化的参数 (可通过net.parameters()从我们的模型中获得)以及优化算法所需的超参数字典。
小批量随机梯度下降只需要设置lr值,这里设置为0.03。
七、训练
num_epochs = 3
for epoch in range(num_epochs):#训练num_epochs次
for X, y in data_iter:#遍历数据加载器中的所有批次
l = loss(net(X) ,y)#net(X):神经网络前向传播,得到预测值
#loss(net(X), y):计算预测值与真实值的损失
trainer.zero_grad()#将之前计算的梯度清零,避免累加到当前批次
l.backward()#反向传播,自动计算损失相对于所有可训练参数的梯度
trainer.step()#根据梯度更新模型参数
l = loss(net(features), labels)#在整个数据集(不是批次)上计算损失
print(f'epoch {epoch + 1}, loss {l:f}')
w = net[0].weight.data
print('w的估计误差:', true_w - w.reshape(true_w.shape))
b = net[0].bias.data
print('b的估计误差:', true_b - b)
运行结果:
epoch 1, loss 0.000246
epoch 2, loss 0.000104
epoch 3, loss 0.000104
w的估计误差: tensor([-0.0006, 0.0003])
b的估计误差: tensor([-0.0008])
更多推荐



所有评论(0)