000动手从0实现线性回归
0. 背景介绍
我们构造一个简单的人工训练数据集,它可以使我们能够直观比较学到的参数和真实的模型参数的区别。
设训练数据集样本数为1000,输入个数(特征数)为2。给定随机生成的批量样本特征 X∈R1000×2
X∈R 1000×2 ,我们使用线性回归模型真实权重 w=[2,−3.4]⊤ 和偏差 b=4.2以及一个随机噪声项 ϵϵ 来生成标签
# 需要导入的包
import numpy as np
import torch
import random
from d2l import torch as d2l
from IPython import display
from matplotlib import pyplot as plt
1. 生成数据集合(待拟合)
使用python生成待拟合的数据
num_input = 2
num_example = 1000
w_true = [2,-3.4]
b_true = 4.2
features = torch.randn(num_example,num_input)
print('features.shape = '+ str(features.shape) )
labels = w_true[0] * features[:,0] + w_true[1] * features[:,1] + b_true
labels += torch.tensor(np.random.normal(0,0.01 , size = labels.size() ),dtype = torch.float32)
print(features[0],labels[0])
2.数据的分批量处理
def data_iter(batch_size, features, labels):
num_example = len(labels)
indices = list(range(num_example))
random.shuffle(indices)
for i in range(0, num_example, batch_size):
j = torch.tensor( indices[i:min(i+ batch_size,num_example)])
yield features.index_select(0,j) ,labels.index_select(0,j)
3. 模型构建及训练
3.1 定义模型:
def linreg(X, w, b):
return torch.mm(X,w)+b
3.2 定义损失函数
def square_loss(y, y_hat):
return (y_hat - y.view(y_hat.size()))**2/2
3.3 定义优化算法
def sgd(params , lr ,batch_size):
for param in params:
param.data -= lr * param.grad / batch_size
3.4 模型训练
# 设置超参数
lr = 0.03
num_epochs =5
net = linreg
loss = square_loss
batch_size = 10
for epoch in range(num_epochs):
for X,y in data_iter(batch_size= batch_size,features=features,labels= labels):
l = loss(net(X,w,b),y).sum()
l.backward()
sgd([w,b],lr,batch_size=batch_size)
#梯度清零避免梯度累加
w.grad.data.zero_()
b.grad.data.zero_()
train_l = loss(net(features,w,b),labels)
print('epoch %d, loss %f' %(epoch +1 ,train_l.mean().item()))
epoch 1, loss 0.032550
epoch 2, loss 0.000133
epoch 3, loss 0.000053
epoch 4, loss 0.000053
epoch 5, loss 0.000053
基于pytorch的线性模型的实现
- 相关数据和初始化与上面构建相同
- 定义模型
import torch
from torch import nn
class LinearNet(nn.Module):
def __init__(self, n_feature):
# 调用父类的初始化
super(LinearNet,self).__init__()
# Linear(输入特征数,输出特征的数量,是否含有偏置项)
self.linera = nn.Linear(n_feature,1)
def forward(self,x):
y = self.linera(x)
return y
#打印模型的结构:
net = LinearNet(num_input)
print(net)
# LinearNet( (linera): Linear(in_features=2, out_features=1, bias=True)
)
- 初始化模型的参数
from torch.nn import init
init.normal_(net.linera.weight,mean=0,std= 0.1)
init.constant_(net.linera.bias ,val=0)
- 定义损失函数
loss = nn.MSELoss()
5.定义优化算法
import torch.optim as optim
optimizer = optim.SGD(net.parameters(),lr = 0.03)
print(optimizer)
- 训练模型:
num_epochs = 3
for epoch in range(1,num_epochs+1):
for X,y in data_iter(batch_size= batch_size,features=features,labels= labels):
output= net(X)
l = loss(output,y.view(-1,1))
optimizer.zero_grad()
l.backward()
optimizer.step()
print('epoch %d ,loss: %f' %(epoch,l.item()) )
epoch 1 ,loss: 0.000159
epoch 2 ,loss: 0.000089
epoch 3 ,loss: 0.000066