Pytorch实现线性回归

线性回归
#以 \(y = w_1x_1 + w_2x_2 + b\)模型为例

生成数据集
import numpy as np
import torch

true_w = torch.tensor([2, -3.4])
true_b = 4.2
number = 1000 #数据集大小

#依照y = Xw + b +噪声项随机生成,噪声项服从正态分布
def synthetic_data(w, b, number):
X = torch.normal(mean=torch.zeros(number, len(w)), std=torch.ones(number,len(w))) #随机生成数据集的自变量X
y = torch.matmul(X, w) + b #y = Xw + b
y += torch.normal(0, 0.01, y.shape) #随机生成噪声项
print(X.shape, y.shape)
print(X[0], y[0])
return X, y

features, labels = synthetic_data(true_w, true_b, number)
import matplotlib.pyplot as plt
plt.scatter(features[:,1], labels, 5)
plt.show()

读取数据集
#训练模型需要遍历数据集,每次抽取一小批量样本
import random
def data_iter(batch_size, features, labels):
num = len(features)
indices = list(range(num)) #生成索引
random.shuffle(indices) #索引随机排序
for i in range(0, num, batch_size):
batch_indices = np.array(indices[i: min(i + batch_size, num)]) #截取下一段数据,注意索引不要越界
yield features[batch_indices], labels[batch_indices] #将这一段加入迭代器中

batch_size = 10 #设定每次选取的数据集大小

初始化模型参数
#随机生成即可
w = torch.normal(0, 0.01, size=(2,1), requires_grad=True)
b = torch.zeros(1, requires_grad=True)

定义模型
def net(X, w, b):
return torch.matmul(X, w) + b

定义损失函数
#依照均方损失定义
def loss(y_hat, y):
return (y_hat - y.reshape(y_hat.shape))**2 /2 #除以2是为了使梯度的系数为1
设模型参数\(w=[w_1,w_2,b]^T.\) 则损失函数为\[l(w)=\frac{1}{2n}|\hat{y}-y|^2.\]

定义优化算法
#抽取小批量数据,计算梯度损失,按照减少损失的方向更新参数
def sgd(params, lr, batch_size):
with torch.no_grad(): #被包装起来的部分不会追踪梯度
for param in params:
param -= lr * param.grad / batch_size
param.grad.zero_()
写出表达式是\[w\leftarrow w - \frac{lr}{n}\sum\nabla_w l^{(i)}(w).\]
#若调用torch库,可以直接trainer = torch.optim.SGD(net.parameters(), lr=0.03)

训练
#调整参数
lr = 0.03 #定义学习量
num_epoches = 3 #定义迭代周期数

for epoch in range(num_epoches):
for X, y in data_iter(batch_size, features, labels):
l = loss(net(X, w, b), y)
l.sum().backward() #对损失函数l求梯度
sgd([w, b], lr, batch_size) #更新参数w,b
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}')

    所属分类:机器学习     发表于2022-01-31