%matplotlib inline
import random
import torch
from d2l import torch as d2l
```python
根据带有噪声的线性模型构造一个人造数据集。 我们使用线性模型参数w=[2,−3.4]⊤、b=4.2和噪声项ϵ生成数据集及其标签:\
def synthetic_data(w, b, num_examples):
"""生成 y = Xw + b + 噪声。"""
X = torch.normal(0, 1, (num_examples, len(w)))
# 返回一个张量,包含从给定参数means,std的离散正态分布中抽取随机数
# 行数是样本数量,列是w的长度
y = torch.matmul(X, w) + b
# 两个张量矩阵相乘
y += torch.normal(0, 0.01, y.shape)
# 随机噪声,均值为0,方差为0.01
return X, y.reshape((-1, 1))
# 返回构造的X和y
true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)
# 构造了1000个训练数据
print('features:', features[0], '\nlabel:', labels[0])
features: tensor([ 1.2445, -0.1673])
label: tensor([7.2539])
d2l.set_figsize()
d2l.plt.scatter(features[:, 1].detach().numpy(),
labels.detach().numpy(), 1);
d2l.set_figsize()
d2l.plt.scatter(features[:, 0].detach().numpy(),
labels.detach().numpy(), 1);
```python
# 定义一个data_iter 函数, 该函数接收批量大小、特征矩阵和标签向量作为输入,生成大小为batch_size的小批量
def data_iter(batch_size, features, labels):
num_examples = len(features)
# 训练数据总量。其中len函数返回矩阵的行数
indices = list(range(num_examples))
# 对所有的数据进行标号
random.shuffle(indices)
# shuffle() 方法将序列的所有元素随机排序。
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
for X, y in data_iter(batch_size, features, labels):
print(X, '\n', y)
break
tensor([[-0.6489, -1.2992],
[-1.4567, 0.6944],
[ 0.6492, 0.5349],
[ 0.6975, 0.7926],
[-0.0284, -0.3099],
[ 0.0941, -0.3360],
[ 0.0608, 0.4613],
[-0.8575, -0.3315],
[ 0.6550, -0.9486],
[ 0.1608, -0.1536]])
tensor([[ 7.3299],
[-1.0834],
[ 3.6786],
[ 2.8856],
[ 5.2030],
[ 5.5153],
[ 2.7383],
[ 3.6112],
[ 8.7448],
[ 5.0419]])
# 定义 初始化模型参数
w = torch.normal(0, 0.01, size=(2, 1), requires_grad=True)
b = torch.zeros(1, requires_grad=True)
# 定义模型
def linreg(X, w, b):
"""线性回归模型。"""
return torch.matmul(X, w) + b
# 定义损失函数
def squared_loss(y_hat, y):
"""均方损失。"""
return (y_hat - y.reshape(y_hat.shape))**2 / 2
# 定义优化算法
def sgd(params, lr, batch_size):
"""小批量随机梯度下降。"""
with torch.no_grad():
for param in params:
param -= lr * param.grad / batch_size
param.grad.zero_()
# 训练过程
lr = 1
num_epochs =10
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)
# 一个epoch迭代完成后,算损失
print(f'epoch {epoch + 1}, loss {float(train_l.mean()):f}')
epoch 1, loss 0.000062
epoch 2, loss 0.000078
epoch 3, loss 0.000049
epoch 4, loss 0.000055
epoch 5, loss 0.000059
epoch 6, loss 0.000116
epoch 7, loss 0.000087
epoch 8, loss 0.000059
epoch 9, loss 0.000054
epoch 10, loss 0.000078
```python
print(f'w的估计误差: {true_w - w.reshape(true_w.shape)}')
print(f'b的估计误差: {true_b - b}')
w的估计误差: tensor([-0.0005, -0.0034], grad_fn=)
b的估计误差: tensor([0.0078], grad_fn=)