李沐动手学深度学习6——线性回归
李沐动手学深度学习,有视频、有中文电子书(含配套代码),推荐!
主要内容是:随机生成数据功能,批量读取数据功能,模型、损失、优化算法的定义,模型训练
以下是代码:
import random import torch import matplotlib.pyplot as plt # 生成y=Xw+b+噪声 def synthetic_data(w, b, num_examples): 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)) # 批量获取数据 def data_iter(batch_size, features, labels): num_examples = len(features) indices = list(range(num_examples)) # 原地打乱可变序列,shuffle是洗牌的意思 random.shuffle(indices) 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] # 定义模型 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): # no_grad是pytorch的用于禁用梯度计算的上下文管理器 with torch.no_grad(): for param in params: # 除以batch_size的意义在于: # 因为计算的损失是一个批量样本的总和,所以用批量大小来规范化步长,这样步长大小就不会取决于我们对批量大小的选择 param -= lr * param.grad / batch_size param.grad.zero_() if __name__=="__main__": true_w = torch.tensor([2, -3.4]) true_b = 4.2 features, labels = synthetic_data(true_w, true_b, 1000) print('features:', features[0], '\nlabel:', labels[0]) # 查看数据 fig, ax = plt.subplots(figsize=(12, 8)) ax.scatter(features[:, 1].detach().numpy(), labels.detach().numpy(), s=10) plt.show() # 测试数据集批量读取函数 batch_size = 10 for X, y in data_iter(batch_size, features, labels): print(X, '\n', y) break # 初始化模型参数,w为一个0上下的小数值,b设为0 # 若将权重全部初始化为0:所有神经元在反向传播时会获得相同的梯度更新,导致网络无法学习不同的特征 # 若初始数值过大,会导致前向传播的输出值过大,经过激活函数(如Sigmoid、Tanh)后容易饱和,使梯度接近0 w = torch.normal(0, 0.01, size=(2, 1), requires_grad=True) b = torch.zeros(1, requires_grad=True) lr = 0.03 num_epochs = 3 net = linreg loss = squared_loss