本文是学习线性回归模型的总结,主要分享线性回归模型的技术原理,以及用代码实现验证,供大家参考。
一、任务描述
假设手上有一份数据集,每一行数据表示一个物品的价格影响因素(k个)和对应价格。
序号 | 影响因素1 | 影响因素2 | 影响因素k | 价格(y) |
---|---|---|---|---|
1 | 1.23 | 3.23 | 1.56 | 7.23 |
2 | 0.23 | 1.60 | 2.56 | 8.33 |
... | ... | ... | ... | ... |
n | xx | xx | xx | xx |
现在获得了该物品的k个影响因素,要求根据k个影响因素求取该物品的价格。
二、任务分析
2.1、目标
假设物品价格y与影响因素x(1-k)成线性关系,即y可以表示为x中元素的加权和,即构建线性回归模型
写成向量形式为:
那么我们的任务就是寻找一组参数W和b,使得根据线性回归模型做出的价格预测尽可能接近数据里的真实价格。
2.2、评估
如何评估找到的一组参数W和b,就是使得根据线性回归模型做出的价格预测尽可能接近数据里的真实价格。
在深度学习中,损失函数(loss function)能够量化目标的实际值与预测值之间的差距。回归问题中最常用的损失函数是平方误差函数,那么第i个样本的损失为:
加上1/2为了求导时使得常数系数为1。为了度量模型在整个数据集上的质量,我们需计算在训练集上n个样本上的损失均值。
因此,在训练模型时,我们希望寻找一组参数(W,b),使得L(W,b)在所有训练样本上的损失均值越小越好。
2.3、求解
在深度学习中,求解参数(W,b),一般用梯度下降法。梯度下降算法的步骤如下:
(1)初始化模型参数的值;(2)从数据集中随机抽取小批量样本且在负梯度的方向上更新参数,并不断迭代这一步骤,直到迭代次数达到设定阈值或损失小于某个阈值。
W和b的更新表达式如下:
总的表达式:
W和b分开表示:
三、代码验证
整个代码验证过程包括如下主要流程:
3.1、获取训练数据
为验证线性回归模型,我们定义一个线性函数,生成一个数据集。
python
import numpy as np
import torch
from torch.utils import data
from d2l import torch as d2l
from torch import nn
"""
生成(X,y)数据集,y=Xw+b+e
"""
num_examples =2000 # 样本为2000个
true_w = torch.tensor([3, -1.2, 1.7]) # 定义y=Xw+b+e中的w
# true_w = torch.tensor([2, -3.4]) # 定义y=Xw+b+e中的w
true_b = 4.2 # 定义y=Xw+b+噪声中的b
# torch.normal()函数:从一个均值0,方差1的正态分布中抽取随机数,生成一个(num_examples, len(w))的张量。
X = torch.normal(0, 1, (num_examples, len(true_w))) # 定义X
y = torch.matmul(X, true_w) + true_b # 定义y=Xw+b,得到的y为一维行向量。
# 在生成y=Xw+b的基础上,加上一个随机噪声e,该噪声从一个均值0,方差0.01的正态分布中抽取随机数,生成一个y.shape的张量。
y += torch.normal(0, 0.01, y.shape)
y = y.reshape(-1, 1) # y为行向量,需要转为二维矩阵向量,便于后面与y_pred计算损失
为从n个样本数据中抽取小批量数据,定义个批量数据迭代器
ini
# 定义一个批量数据迭代器,用于从(X,y)数据集中抽取batch_size的数据。
def load_array(data_arrays, batch, is_train=True):
dataset = data.TensorDataset(*data_arrays)
return data.DataLoader(dataset, batch, shuffle=is_train)
batch_size = 20
data_iter = load_array((X, y), batch_size)
3.2、定义模型
根据上述表达式定义线性回归模型。
python
"""
定义线性回归模型
"""
# 根据权重参数true_w判断输入参数维度,这里是输入参数维度为len(true_w)=3,即每个样本由3个影响因素
Linear_net = nn.Sequential(nn.Linear(len(true_w), 1))
3.3、定义损失函数
根据上述表达式定义损失函数。
python
"""
定义损失函数
"""
loss = nn.MSELoss() # 默认情况下返回所有样本损失的平均值
3.4、定义优化算法
,根据上述表达式定义优化算法。
python
"""
定义优化算法
"""
optimization = torch.optim.SGD(Linear_net.parameters(), lr=0.02)
3.5、初始化训练参数
首先初始化模型参数。
python
"""
初始化模型参数
"""
# 从一个均值0,方差0.01的正态分布中抽取随机数正并用这些随机数初始化权重参数w。
Linear_net[0].weight.data.normal_(0, 0.01)
# 初始化偏置参数b。
Linear_net[0].bias.data.fill_(0)
3.6、开始训练
python
"""
开始训练
"""
num_epochs = 3
for epoch in range(num_epochs):
for features, labels in data_iter:
l = loss(Linear_net(X), y)
optimization.zero_grad()
l.backward()
optimization.step()
y_pred = Linear_net(X) # y_pred为2000*1的二维矩阵
l = loss(y_pred, y)
print(f'epoch {epoch + 1}, loss {l:f}')
训练结束后,可以查看W和b的参数,以及与真实值W和b的差异
参考资料
1、李沐《动手学深度学习》第二版,地址: zh.d2l.ai/index.html