在前面,我们已经学习了线性回归的基本原理,以及模型训练的基本要素和流程。本节我们就来完成线性回归模型的代码实现
1 从零实现线性回归
首先,我们来导入需要的包
import matplotlib_inline
import random
import torch
from d2l import torch as d2l
生成训练样本
对于模型
y
=
w
1
x
1
+
w
2
x
2
+
b
y=w_1 x_1+w_2 x_2+b
y=w1x1+w2x2+b,我们自己来创建一些数据来作为模型的样本,通过
def synthetic_data(w, b, num_examples):
"""
人工生成训练数据
:param w: 真实的权重
:param b: 真实的偏置
:param num_examples:数据个数
:return: 生成的X、y训练数据
"""
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
w_true=torch.tensor([2,-3.4])
b_true=4.2
features,labels=synthetic_data(w_true,b_true,100)
批量打包数据
前面我们提到过,深度学习不会直接使用所有数据来训练计算损失函数,那会带来极大的成本,所以会采用批处理的方式
此时我们就按指定的batch_size大小产生数据
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):
bathIndides=torch.tensor(Indices[i:min(i+batch_size,num_examples)])
yield features[bathIndides],labels[bathIndides]
batch_size=10
for X,y in data_iter(batch_size,features,labels):
print(X,"\n",y)
break
tensor([[ 0.3174, 0.8440],
[-0.1825, 0.6330],
[ 0.6303, -0.6279],
[-0.1898, -0.3718],
[ 1.4762, -2.3725],
[-1.0628, -0.2374],
[-1.4689, -1.6751],
[-0.5215, 0.8446],
[ 1.0405, 0.3750],
[ 0.1340, 0.7184]])
tensor([ 1.9422, 1.6872, 7.5901, 5.0734, 15.2126, 2.9003, 6.9655, 0.2776,
5.0088, 2.0295])
定义模型
下面我们来实现线性回归模型的定义:包括网络架构和参数权重
#参数权重随机初始化
w=torch.normal(0,0.01,(2,1),requires_grad=True)
b=torch.zero(1,requires_grad=True)
#定义模型架构
def linreg(X,w,b):
return torch.matmul(X,w)+b
下面我们进行模型的训练
本模块包含损失函数和优化算法的定义,以及训练过程的实现
#定义损失函数
def squred_loss(y_hat,y):
return (y_hat-y.reshape(y_hat.shape))**2
#定义优化算法
def SGD(params,lr,batch_size):
with torch.nograd():
for param in params:
param-=params.grad*lr/batch_size
params.grad.zero_()
##定义训练过程
lr=0.05
net=linreg
epoches=5
loss_function=squred_loss
for epoch in epoches:
for X,y in data_iter(batch_size,features,labels):
y_hat=net(X,w,b)
loss=loss_function(y_hat,y)
loss.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}')
2 快捷线性回归
前面我们从零实现了线性回归,现在我们通过框架来简洁实现线性回归
import numpy as np
import torch
from d2l import torch as d2l
from torch.utils import data
from torch import nn
def synthetic_data(w, b, num_examples):
"""
人工生成训练数据
:param w: 真实的权重
:param b: 真实的偏置
:param num_examples:数据个数
:return: 生成的X、y训练数据
"""
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)
w_true=torch.tensor([2,-3.4])
b_true=4.2
features,labels=synthetic_data(w_true,b_true,100)
def load_array(data_arrays,batch_size,is_train=True):
"""
分批次读取数据
:param data_arrays: 源数据
:param batch_size: 批大小
:param is_train: 是否为训练数据,若是,则打乱后再分批
:return: 一个迭代器,可以迭代获取数据
"""
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))
net=nn.Sequential(nn.Linear(2,1))
net[0].weight.data.normal_(0,00.1)
net[0].bias.data.fill_(0)
loss = nn.MSELoss()
trainer = torch.optim.SGD(net.parameters(), lr=0.03)
num_epochs = 3
for epoch in range(num_epochs):
for X, y in data_iter:
l = loss(net(X), y)
trainer.zero_grad()
l.backward()
trainer.step()
l = loss(net(features), labels)
print(f'epoch{num_epochs + 1}:loss={l:f}')
epoch4:loss=9.925650
epoch4:loss=3.212693
epoch4:loss=1.054000