文章目录
1. 模型与代码实现
1.1. 模型
y ^ = w 1 x 1 + . . . + w d x d + b = w ⊤ x + b . \hat{y} = w_1 x_1 + ... + w_d x_d + b = \mathbf{w}^\top \mathbf{x} + b. y^=w1x1+...+wdxd+b=w⊤x+b.
1.2. 代码实现
import torch
from torch import nn
from torch.utils import data
from d2l import torch as d2l
# 全局参数设置
batch_size = 10
num_epochs = 3
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
# 生成数据集
true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = d2l.synthetic_data(true_w, true_b, 1000)
features, labels = features.to(device), labels.to(device)
# 加载数据集
dataset = data.TensorDataset(features, labels)
dataloader = data.DataLoader(dataset, batch_size, shuffle=True)
# 创建神经网络
net = nn.Linear(2, 1).to(device)
# 初始化模型参数
nn.init.normal_(net.weight, mean=0, std=0.01)
nn.init.constant_(net.bias, val=0)
# 设置损失函数
criterion = nn.MSELoss()
# 设置优化器
optimizer = torch.optim.SGD(net.parameters(), lr=0.03)
# 训练模型
for epoch in range(num_epochs):
for X, y in dataloader:
X, y = X.to(device), y.to(device)
loss = criterion(net(X) ,y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
loss = criterion(net(features), labels)
print(f'epoch {epoch + 1}, loss {loss:f}')
# 评估训练结果
w = net.weight.data.cpu()
print('w的估计误差:', true_w - w.reshape(true_w.shape))
b = net.bias.data.cpu()
print('b的估计误差:', true_b - b)
输出结果
epoch 1, loss 0.000211
epoch 2, loss 0.000099
epoch 3, loss 0.000099
w的估计误差: tensor([ 4.2558e-04, -5.3167e-05])
b的估计误差: tensor([0.0005])
2. Q&A
2.1. 如何安装d2l模块?
pip install d2l
2.2. 为什么模型参数初始化时要将偏置设为0?
在机器学习中,我们通常会使用非常小的学习率来进行梯度下降,以防止在更新参数时发生剧烈的波动。如果偏置项的初始值不为0,那么在开始训练模型时,可能会因为偏置的影响,导致权重更新的方向出现偏差。
2.3. 为什么选择均方损失作为线性回归模型的损失函数?
因为在高斯噪声的假设下,最小化均方误差 ⇔ \Leftrightarrow ⇔对给定 x \mathbf{x} x观测 y y y的极大似然估计 ⇔ w , b \Leftrightarrow \mathbf{w},b ⇔w,b取最优值。详细推导。均方误差函数如下: M S E = 1 n ∑ i = 1 n ( y i − y i ^ ) 2 \mathbf{MSE}=\frac{1}{n}\sum_{i=1}^{n}{(y_i-\hat{y_i})^2} MSE=n1i=1∑n(yi−yi^)2其中 y i y_i yi是真实数据, y i ^ \hat{y_i} yi^是拟合数据。
2.4. 如何理解模型训练过程?
for epoch in range(num_epochs):
for X, y in dataloader:
X, y = X.to(device), y.to(device)
# 计算网络输出结果与预期结果的误差
loss = criterion(net(X) ,y)
# 清空参数梯度缓存值,否则梯度会与上一个batch的数据相关
optimizer.zero_grad()
# 误差反向传播计算参数梯度值
loss.backward()
# 更新模型参数
optimizer.step()
# 计算在整个训练集上的误差
loss = criterion(net(features), labels)
print(f'epoch {epoch + 1}, loss {loss:f}')