import torch import random # 1. 数据生成 def synthetic_data(w, b, num_examples): x torch.normal(0, 1, (num_examples, len(w))) #生成正态分布数据均值为0 方差为1 形状(数据条数, 特征数) y torch.matmul(x, w) b #计算y wxb torch.matmul(x, w) 矩阵乘法 y torch.normal(0, 0.01, y.shape) #噪声的影响 均值为0 标准差为0.01 让数据更像真实世界的数据不是完美直线 return x, y.reshape((-1, 1)) # 2. 数据迭代器 def data_iter(batch_size, features, labels): num_examples len(features) #特征总数 indices list(range(num_examples)) #0-num 转换成list random.shuffle(indices) #把indices打乱随机 for i in range(0, num_examples, batch_size): #从0 开始 num结束 每次加batch_size batch_indices torch.tensor(indices[i: min(ibatch_size, num_examples)]) #把indices[i]-indices[min] 取当前批次的索引转成张量用于索引 yield features[batch_indices], labels[batch_indices] # yield 生成器每次返回一个批次的特征和标签 # 3. 线性回归模型 def linreg(X, w, b): return torch.matmul(X, w) b #yxw b # 4. 平方损失函数 def squared_loss(y_hat, y): return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2 # 5. 小批量随机梯度下降 def sgd(params, lr, batch_size): with torch.no_grad(): #不计算t度 for param in params: param - lr * param.grad / batch_size #t度下降 param.grad.zero_() #t度清0 # 6. 初始化参数 true_w torch.tensor([2., -3., 4.]) true_b 4.2 features, labels synthetic_data(true_w, true_b, 1000) batch_size 10 w torch.normal(0, 0.01, size(3, 1), requires_gradTrue) # requires_gradTrue需要计算t度 b torch.zeros(1, requires_gradTrue) # 7. 超参数设置 lr 0.03 num_epochs 3 net linreg loss squared_loss # 8. 训练循环 for epoch in range(num_epochs): for x, y in data_iter(batch_size, features, labels): l loss(net(x, w, b), y) #netlinerg l平方损失 l.sum().backward() #求导 把 10 个误差加起来变成一个数字 PyTorch 自动算出 wb 要怎么变才能让损失变小 sgd([w, b], lr, batch_size) #小批量t度下降 with torch.no_grad(): #不求t度 train_l loss(net(features, w, b), labels) print(fepoch {epoch 1}, loss {float(train_l.mean()):f}) # 9. 打印学习到的参数和真实值对比 print(f学习到的w: {w.reshape(true_w.shape)}真实w: {true_w}) print(f学习到的b: {b.item()}真实b: {true_b})