1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
| import matplotlib.pyplot as plt import random import torch import pandas as pd import numpy as np
def synthetic_data(w, b, num_examples): """生成y = wX+b+噪声""" X = torch.normal(0, 1, (num_examples, len(w))) """X是一个均值为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))
true_w = torch.tensor([2, -3.4]) true_b = 4.2 features, labels = synthetic_data(true_w, true_b, 1000) """以房价为例:label是真实售价;feature是预测label的两个因素。""" print(features[0], labels[0])
plt.scatter(features[:, 1], labels, 1) plt.show()
def data_iter(batch_size, features, labels): """定义一个data_iter函数,该函数接受批量大小,特征矩阵features和标签向量labels作为输入,生成大小为batch_size的小批量""" num_example = len(features) indices = list(range(num_example)) """随机读取数据""" random.shuffle(indices) for i in range(0, num_example, batch_size): batch_indices = torch.tensor(indices[i:min(i + batch_size, num_example)]) 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
"""定义初始化模型""" w = torch.normal(0, 0.01, size=(2, 1), requires_grad=True) """requires_grad=True 的作用是让 backward 可以追踪这个参数并且计算它的梯度""" 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): """params是一个参数里面包含了w和d,lr为学习率""" """小批量梯度下降""" with torch.no_grad(): for params in params: params -= lr * params.grad / batch_size params.grad.zero_()
print('_____________________________________________________________________________')
"""训练过程""" lr = 0.01 num_epochs = 10 net = linreg loss = squared_loss
for epoch in range(num_epochs): """先把数据扫一遍""" for X, y in data_iter(batch_size, features, labels): """再拿出一个批量大小的x和y""" l = loss(net(X,w,b),y) """把下x,w,b放在模型中做预测,把预测值与真实值y来做损失""" """x,y是小批量损失,l的形状是(batch_size,1),而不是一个标量""" l.sum().backward() sgd([w,b],lr,batch_size)
with torch.no_grad(): train_l = loss(net(features,w,b),labels) print(f'epoch{epoch + 1},loss {float(train_l.mean()):f}')
print(f'w的误差值:{true_w-w.reshape(true_w.shape)}') print(f'b的误差值:{true_b-b}')
|