线性回归
线性回归是对n维输入的加权,外加偏差
使用平方损失来衡量预测值和真是值得差异
线性回归有显示解
线性回归可以看做是单层神经网络
从0开始
构造数据 根据带有噪声的线性模型构造一个人造数据集,我们使用线性模型参数 w=[2,-3.4]T、b=4.2 和噪声项€生成数据集及其标签 y=Xw+b+€
1 2 3 4 5 6 7 8 9 10 11 12
| def synthetic_data(w,b,num_examples): """生成y=Xw+b+噪声。""" #均值为0 方差为1的随机数 行数列数 X=torch.normal(0,1,(num_examples,len(w))) #X*w y=torch.matmul(X,w)+b y+=torch.normal(0,0.01,y.shape) #将y变成列向量 return X,y.reshape((-1,1)) true_w=torch.tensor([2,-3.1]) true_b=4.2 features,labels=synthetic_data(true_w,true_b,1000)
|
选取样本 定义一个data_iter函数,该函数接受批量大小,特征矩阵和标签向量作为输入,生成大小为batch_size的小批量¶
1 2 3 4 5 6 7 8 9 10 11 12 13
| def data_iter(batch_size,features,labels): num_examples=len(features) indices=list(range(num_examples)) #这些样本是随机读取的,没有特定的顺序 打乱下标 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是返回 和return不一样的是只要有结果就会返回 并不是返回一次 yield features[batch_indices],labels[batch_indices] batch_size=10 for X,y in data_iter(batch_size,features,labels): print(X,'\n',y)
|
定义初始化模型参数
1 2 3
| #均值为0,方差为0.01,两行一列 w=torch.normal(0,0.01,size=(2,1),requires_grad=True) b=torch.zeros(1,requires_grad=True)
|
定义模型
1 2 3
| def linreg(X,w,b): """线性回归模型。""" return torch.matmul(X,w)+b
|
定义损失函数
1 2 3
| def squared_loss(y_hat,y): """均方损失。""" return (y_hat-y.reshape(y_hat.shape))**2 / 2
|
定义优化算法
1 2 3 4 5 6
| def sgd(params,lr,batch_size): """小批量随机梯度下降。""" with torch.no_grad(): for param in params: param -=lr*param.grad/batch_size param.grad.zero_()
|
训练
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| lr=0.03 num_epochs=3 net=linreg loss=squared_loss for epoch in range(num_epochs): for X,y in data_iter(batch_size,features,labels): l=loss(net(X,w,b),y) #X和y的小批量损失 #因为l的形状是 batch_size 1而不是一个标量 #并以此计算关于w b的梯度 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}')
|
比较真实参数和通过训练学到的参数来评估训练的成功程度
1 2 3 4
| print(f'w的误差值:{ true_w-w.reshape(true_w.shape)}') print(f'b的误差值:{ true_b-b}')
|
简洁实现
引用
1 2 3 4 5 6 7 8
| import numpy as np import torch from torch.utils import data from d2l import torch as d2l
true_w=torch.tensor([2,-3.4]) true_b=4.2 features,labels=d2l.synthetic_data(true_w,true_b,1000)
|
调用框架中现有的API来读取数据
1 2 3 4 5 6 7 8 9
| def load_array(data_arrays ,batch_size,is_train=True): """构造一个pytorch的数据迭代器""" dataset=data.TensorDataset(*data_arrays) return data.DataLoader(dataset,batch_size,shuffle=is_train)
batch_size=10 data_iter=load_array((features,labels),batch_size)
next(iter(data_iter))
|
使用框架的预定义好的层
1 2 3 4
| ##nn是神经网络的缩写 from torch import nn
net=nn.Sequential(nn.Linear(2,1))
|
初始化模型参数
1 2
| net[0].weight.data.normal_(0,0.01) net[0].bias.data.fill_(0)
|
计算均方误差使用MSELoss 也称为平方范数
实例化SGD
1
| trainer=torch.optim.SGD(net.parameters(),lr=0.03)
|
训练
1 2 3 4 5 6 7 8 9 10 11 12
| lr=0.03 num_epochs=3 for epoch in range(num_epochs): for X,y in data_iter: l=loss(net(X),y) #X和y的小批量损失 trainer.zero_grad() l.backward() trainer.step() l=loss(net(features),labels) print(f'epoch { epoch+1},loss{ l:f}')
|
作者声明