​     在机器学习领域中的大多数任务通常都与预测有关。 当我们想预测一个数值时,就会涉及到回归问题。 常见的例子包括:预测价格(房屋、股票等)、预测住院时间(针对住院病人等)、 预测需求(零售销量等)。 本篇文章将深入讨论线性回归的原理,并动手实现一个线性回归模型。

1、线性回归的定义

​     回归(regression)是能为一个或多个自变量与因变量之间关系建模的一类方法。 在自然科学和社会科学领域,回归经常用来表示输入和输出之间的关系。线性则代表自变量与因变量之间存在着线性关系。

​     在回归分析中,只包括一个自变量和一个因变量,且二者的关系可用一条直线近似表示,这种回归分析称为一元线性回归分析。如果回归分析中包括两个或两个以上的自变量,且因变量和自变量之间是线性关系,则称为多元线性回归分析。

2、线性回归的基本元素

​     线性回归是机器学习领域中最基础的算法模型,为了更好地解释线性回归,我们举一个实际的例子: 我们希望根据房屋的面积(平方英尺)和房龄(年)来估算房屋价格(美元)。 为了开发一个能预测房价的模型,我们需要收集一个真实的数据集。 这个数据集包括了房屋的销售价格、面积和房龄。在机器学习的术语中,该数据集称为训练数据集(training data set) 或训练集(training set)。 每行数据(比如一次房屋交易相对应的数据)称为样本(sample), 也可以称为数据点(data point)或数据样本(data instance)。 我们把试图预测的目标(比如预测房屋价格)称为标签(label)或目标(target)。 预测所依据的自变量(面积和房龄)称为特征(feature)或协变量(covariate)。

3、线性回归模型

​     线性回归基于几个简单的假设: 首先,假设自变量x和因变量y之间的关系是线性的, 即y可以表示为x中元素的加权和,这里通常允许包含观测值的一些噪声; 其次,我们假设任何噪声都比较正常,如噪声遵循正态分布。

​     线性假设是指目标(房屋价格)可以表示为特征(面积和房龄)的加权和,如下面的式子:
price=warea⋅area+wage⋅age+b.(1)price=w_{area}·area+w_{age}·age+b.\tag{1} price=warea​⋅area+wage​⋅age+b.(1)
​     公式(1)中的wareaw_{area}warea​和wagew_{age}wage​被称为权重(weight),决定每个特征对最终预测值的影响。bbb称为偏置(bias)、偏移量(offset)。偏移量可以增强我们模型的表达能力,使其能够拟合更多的模型。

​     在机器学习领域,我们通常使用的是高维的数据集,因此采用线性代数的方式来建模会很方便。我们将所有的特征放在向量x∈Rd\pmb{x}\in ℝ^dxx∈Rd中,并将所有权重放在向量w∈Rd\pmb{w}\in ℝ^dww∈Rd中,其中ddd是特征维度,并用y^\hat yy^​来表示模型的预测结果,从而我们可以用点积形式来简洁地表达模型:
y^=wTx+b.(2)\hat y=\pmb{w}^T\pmb{x}+b.\tag{2} y^​=wwTxx+b.(2)
​     在公式(2)中,向量x\pmb{x}xx对应单个数据样本的特征,此时我们用矩阵X∈Rn×d\pmb{X}\inℝ^{n×d}XX∈Rn×d来引用整个数据集的nnn个样本的特征,X\pmb{X}XX的每一行是一个样本,每一列是一种特征。

​     那么对于特征集合X\pmb{X}XX,预测值y^∈Rn\hat y\inℝ^ny^​∈Rn可以通过矩阵-向量乘法来表示:
y^=Xw+b.(3)\hat y=\pmb{X}\pmb{w}+b.\tag{3} y^​=XXww+b.(3)
​     预测房价模型的公式就可以用(3)来进行表示,我们通过该模型就可以根据面积和房龄等信息来预测房价,但问题在于我们无法确定www和bbb的值,线性回归就是寻找出一组权重www和偏置bbb,当给定来自X\pmb{X}XX中取样的独立同分布的新样本特征时,这组权重和偏置可以使得最终的预测值y^\hat yy^​与真实值yyy之间的误差尽可能小。

4、损失函数

​     在开始寻找最好的模型参数(model parameters)w和b之前, 我们还需要两个东西: (1)衡量模型的质量:衡量预测值与真实值之间的误差(2)一种能够更新模型以提高模型预测质量的方法。

​     如何去衡量预测值与真实值之间的误差?在回归问题中,常使用最小二乘法来衡量模型的质量,其定义为:
l(i)(w,b)=12(y^(i)−y(i))2.(4)l^{(i)}(\pmb{w},b)=\frac{1}{2}(\hat y^{(i)}-y^{(i)})^2.\tag{4} l(i)(ww,b)=21​(y^​(i)−y(i))2.(4)
​     (4)也就是该模型的损失函数,其中iii代表第iii个样本,l(i)(w,b)l^{(i)}(\pmb{w},b)l(i)(ww,b)就是第iii个样本的预测误差。

​     上述只是对于每一条样本的预测误差,而我们最终的目的是为了去拟合整个数据集上的样本,因此为了度量模型在整个数据集上的质量,我们需要计算在训练集nnn个样本上的损失均值:
L(w,b)=1n∑i=1nl(i)(wT,b)=1n∑i=1n12[(wTx(i)+b)−y(i)]2.(5)L(w,b)=\frac{1}{n}\sum_{i=1}^{n}l^{(i)}(\pmb{w}^T,b)\\ \quad\quad\quad\quad\quad\quad\quad\quad\quad =\frac{1}{n}\sum_{i=1}^{n}\frac{1}{2} [(\pmb{w}^Tx^{(i)}+b)-y^{(i)}]^2.\tag{5} L(w,b)=n1​i=1∑n​l(i)(wwT,b)=n1​i=1∑n​21​[(wwTx(i)+b)−y(i)]2.(5)
​     训练模型也就是去寻找一组参数(w∗,b∗\pmb{w}^*,b^*ww∗,b∗)来最小化在所有训练样本上总损失的过程:
w∗,b∗=argminw,bL(w,b).(6)\pmb{w}^*,b^*=\mathop{argmin}_{\pmb{w},b}\,L(\pmb{w},b).\tag{6} ww∗,b∗=argminww,b​L(ww,b).(6)

5、梯度下降

​     在第4节中我们提出用最小二乘法的损失函数来衡量模型的质量,那怎么去更新模型的参数来提高模型的质量?

​     我们将(5)继续化简:
L=12n∑i=1nb2+2(wTx(i)−y(i))b+(y(i)−wTx(i))2.(7)L=\frac{1}{2n}\sum_{i=1}^{n}b^2+2(\pmb{w}^Tx^{(i)}-y^{(i)})b+(y^{(i)}-\pmb{w}^Tx^{(i)})^2.\tag{7} L=2n1​i=1∑n​b2+2(wwTx(i)−y(i))b+(y(i)−wwTx(i))2.(7)
​     可以从(7)得出:损失函数是关于bbb的二次函数。

图1:损失函数关于b的二次函数

​     我们的目标是找到损失函数的极小值(最优值),但直接求最优解是一件很难的事情,并且只有线性回归模型才能最有值,在其他复杂的模型中,我们都只能无限逼近最优解,因此我们换一种思路来求解:

图2:损失函数对参数b的偏导

​     我们求当前损失函数LLL对bbb的偏导,就可以得出函数值的变化趋势。导数为正,则代表函数值呈上升趋势;导数为负,则代表函数值呈下降趋势。我们需要求函数的最小值,因此沿着导数的反方向就能逐渐靠近最优值:
b←b−ϵ∂L∂b.(8)b\leftarrow\,b\,-\,\epsilon\frac{\partial\,L}{\partial\,b}.\tag{8} b←b−ϵ∂b∂L​.(8)
​     (8)中的ϵ\epsilonϵ是学习率,可以理解为沿着当前方向走多少“步”。

​     由上可推,w\pmb{w}ww的更新与bbb类似,因此:
(w,b)←(w,b)−ϵ∂(w,b)l(i)(w,b).(9)(\pmb w,b)\leftarrow(\pmb{w},b)-\epsilon\,\partial_{(\pmb{w},b)}l^{(i)}(\pmb{w},b).\tag{9} (ww,b)←(ww,b)−ϵ∂(ww,b)​l(i)(ww,b).(9)
​     但上述,我们想要更新参数就必须计算所有的样本的梯度,然后根据梯度更新参数,计算量太多,模型的拟合速度慢,因此我们引入批量随机梯度下降来更新参数。所谓的批量随机梯度下降计算梯度下降和随机梯度下降的结合,每一次随机从样本集中抽取β\betaβ个样本来进行训练,然后计算这β\betaβ个样本的平均梯度来更新参数:
(w,b)←(w,b)−ϵ∣β∣∑i∈β∂(w,b)l(i)(w,b).(9)(\pmb w,b)\leftarrow(\pmb{w},b)-\frac{\epsilon}{|\beta|} \sum_{i\in\beta}\partial_{(\pmb{w},b)}l^{(i)}(\pmb{w},b).\tag{9} (ww,b)←(ww,b)−∣β∣ϵ​i∈β∑​∂(ww,b)​l(i)(ww,b).(9)
​     (9)中的∣β∣|\beta|∣β∣是小批量样本的个数,被称为批量大小(batch size);ϵ\epsilonϵ是学习率,是在模型训练前预先手动指定的参数,而不是训练得到的,因此也被称为超参数(hyperparameter)。

​     总结一下算法的步骤如下:(1)初始化模型参数的值,如随机初始化;(2)从数据集中随机抽取小批量样本且在梯度的反方向上更新参数,不断迭代这一步骤。

6、从线性回归到神经网络

​     神经网络中包括了各种的模型,本节我们用神经网络的方式来描述线性回归模型:

图3:线性回归是一个单层神经网络

​     (图3)中只显示了输入层与输出层之间的连接,隐去了权重和偏置,我们可以看出线性回归模型其实就是一个单层的神经网络模型,且只有一个输出。

7、从零开始实现线性回归模型

import random
import torch
from d2l import torch as d2l

​     为了简单起见,我们将根据带有噪声的线性模型构造⼀个数据集。在下面的代码中,我们使用线性模型参数w=[2,−3.4]T\pmb{w}=[2,-3.4]^Tww=[2,−3.4]T、b=4.2b=4.2b=4.2和噪声项ϵ\epsilonϵ生成一个包含1000个样本的数据集及其标签,每个样本包含从标准正态分布中采样的2个特征,该数据集是一个矩阵X∈R1000×2\pmb{X}\inℝ^{1000×2}XX∈R1000×2,标签y∈R1000\pmb{y}\inℝ^{1000}yy∈R1000:
y=Xw+b+ϵ.(10)\pmb{y}=\pmb{Xw}+b+\epsilon.\tag{10} yy=XwXw+b+ϵ.(10)
​     将ϵ视为模型预测和标签时的潜在观测误差。我们认为标准假设成立,即ϵ服从均值为0的正态分布。为了简化问题,我们将标准差设为0.01。生成数据集和标签的函数:

def synthetic_data(w, b, num_examples): #@save"""⽣成y=Xw+b+噪声"""X = torch.normal(0, 1, (num_examples, len(w)))y = torch.matmul(X, w) + by += torch.normal(0, 0.01, y.shape)return X, y.reshape((-1, 1))

​     设定正确的参数值www和bbb,并调用函数生成数据集和标签:

true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)

​     features里面的每一个样本都是包含二维特征的向量,labels的每一行都是一维标签值:

for i in range(0, len(features)):print('features:', features[i],'\nlabel:', labels[i])

图4:特征向量和标签值

​     我们采用小批量随机梯度下降来训练模型,每次抽取一小批量的数据集,并使用它们来更新我们的模型。在下面的代码中,我们定义⼀个data_iter函数,该函数接收批量大小、特征矩阵和标签向量作为输入,生成大小为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):batch_indices = torch.tensor(indices[i: min(i + batch_size, num_examples)])yield features[batch_indices], labels[batch_indices]

​     为了更加直观地去观察小批量抽取数据集的过程,我们打印小批量:

batch_size = 10
for X, y in data_iter(batch_size, features, labels):print(X, '\n', y)break

图5:小批量特征和标签值

​     在我们开始训练模型之前,我们需要初始化模型的参数。在下面的代码中,我们通过从均值为0、标准差为0.01的正态分布中采样随机数来初始化权重,并将偏置初始化为0:

w = torch.normal(0, 0.01, size=(2,1), requires_grad=True)
b = torch.zeros(1, requires_grad=True)

​     我们在初始化参数时,为参数开启了梯度,有了这个梯度,我们就可以向减小损失的方向更新每个参数。因为手动计算梯度很枯燥而且容易出错,所以没有人会手动计算梯度。

​     接下来就是定义我们的线性回归模型:

def linreg(X, w, b): #@save"""线性回归模型"""return torch.matmul(X, w) + b

​     用平方损失函数来评估模型质量:

def squared_loss(y_hat, y): #@save"""均⽅损失"""return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2

​     定义模型优化算法。在每一次更新模型参数之前,我们会使用从数据集中随机抽取的一个小批量来计算损失的梯度,然后向梯度的反方向来更新参数。下面的函数实现了小批量随机梯度下降更新,该函数接收模型参数集合、学习速率和批量大小作为输入,每一步的更新大小由学习率lrlrlr决定。由于我们计算的是一个批量样本的总和损失,因此需要用批量大小(batch_size)来规范化步长,这样步长大小就不会依赖于我们对批量大小的选择:

def sgd(params, lr, batch_size): #@save"""⼩批量随机梯度下降"""with torch.no_grad():for param in params:param -= lr * param.grad / batch_sizeparam.grad.zero_()

​     在开始训练模型之前,我们先设置超参数:

lr = 0.03
num_epochs = 5
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),⽽不是⼀个标量。l中的所有元素被加到⼀起,# 并以此计算关于[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}')

图6:训练过程

​     因为数据集是根据我们自己设定的参数来生成的,真实参数已知,所以我们可以用真实参数与训练更新的参数来进行对比,可以看出偏差是非常小的:

print(f'w的估计误差: {true_w - w.reshape(true_w.shape)}')
print(f'b的估计误差: {true_b - b}')

图7:训练更新的参数与真实参数的偏差值

8、总结

​     本篇文章通过房价预测问题来引入线性回归模型,然后利用平方损失函数来衡量模型的质量并用小批量随机梯度下降来优化模型质量。在最后,我们从零开始用pytorch实现了一个简单的线性回归模型。

参考资料

1、动手学深度学习 Release2.0.0-beta0

2、梯度下降算法_哔哩哔哩

3、反向传播算法_哔哩哔哩

4、“神经网络”是什么?如何直观理解它的能力极限?它是如何无限逼近真理的?_哔哩哔哩_bilibili

深度学习:线性回归模型相关推荐

  1. 深度学习CTR模型最全演化图谱 [王喆观点]

    毕业于清华大学计算机系的王喆学长回顾了近3年来的所有主流深度学习CTR (click through rate) 模型,并梳理推荐系统.计算广告领域在深度学习方面的前沿进展.内容来源:https:// ...

  2. 深度学习推荐模型-NFM

    深度学习推荐模型-NFM 本文参考链接,仅供个人学习: https://github.com/datawhalechina/team-learning-rs/tree/master/DeepRecom ...

  3. 深度学习CTR模型粗略记录

    深度学习CTR模型粗略记录 RoadMap FM:Factorization Machines DNN:Embedding+MLP WND:Wide & Deep Learning for R ...

  4. 【深度学习】模型过拟合的原因以及解决办法

    [深度学习]模型过拟合的原因以及解决办法 1.背景 2.模型拟合 3.简述原因 4.欠拟合解决办法 5.过拟合解决办法 1.背景 所谓模型过拟合现象: 在训练网络模型的时候,会发现模型在训练集上表现很 ...

  5. NVIDIA GPUs上深度学习推荐模型的优化

    NVIDIA GPUs上深度学习推荐模型的优化 Optimizing the Deep Learning Recommendation Model on NVIDIA GPUs 推荐系统帮助人在成倍增 ...

  6. 谷歌、阿里们的杀手锏:三大领域,十大深度学习CTR模型演化图谱

    作者 | 王喆 来源 | 转载自知乎专栏王喆的机器学习笔记 今天我们一起回顾一下近3年来的所有主流深度学习CTR模型,也是我工作之余的知识总结,希望能帮大家梳理推荐系统.计算广告领域在深度学习方面的前 ...

  7. 谷歌、阿里们的杀手锏:3大领域,10大深度学习CTR模型演化图谱(附论文)

    来源:知乎 作者:王喆 本文约4000字,建议阅读8分钟. 本文为你介绍近3年来的所有主流深度学习CTR模型. 今天我们一起回顾一下近3年来的所有主流深度学习CTR模型,也是我工作之余的知识总结,希望 ...

  8. 【深度学习】模型训练过程可视化思路(可视化工具TensorBoard)

    [深度学习]模型训练过程可视化思路(可视化工具TensorBoard) 文章目录 1 TensorBoard的工作原理 2 TensorFlow中生成log文件 3 启动TensorBoard,读取l ...

  9. DL之模型调参:深度学习算法模型优化参数之对LSTM算法进行超参数调优

    DL之模型调参:深度学习算法模型优化参数之对LSTM算法进行超参数调优 目录 基于keras对LSTM算法进行超参数调优 1.可视化LSTM模型的loss和acc曲线

  10. DL之模型调参:深度学习算法模型优化参数之对深度学习模型的超参数采用网格搜索进行模型调优(建议收藏)

    DL之模型调参:深度学习算法模型优化参数之对深度学习模型的超参数采用网格搜索进行模型调优(建议收藏) 目录 神经网络的参数调优 1.神经网络的通病-各种参数随机性 2.评估模型学习能力

最新文章

  1. python计算多次_Python – 只计算一次属性并多次使用结果(不同的方法)
  2. 大型网站后台架构的演变
  3. SAP SD里CDS view对status的设计
  4. 非常不错的Nodejs工具:http-console
  5. P4357-[CQOI2016]K远点对【K-Dtree】
  6. AtCoder Beginner Contest 084(AB)
  7. tcp报文解析工具_15 张图,了解一下 TCP/IP 必知也必会的 10个要点
  8. android sdk 8.1.0,OneAPM版本更新:Android SDK 1.0.8
  9. 做游戏,学编程(C语言) 18 瑞克快跑
  10. 通过iLO进行Zabbix监控——针对HP服务器集成
  11. Android现学现用第十二天
  12. XJOI 3864 农村连接城市
  13. cad管线交叉怎么画_CAD命令:打断(BREAK)命令的使用技巧
  14. python斗地主游戏源码_Java写的斗地主游戏源码
  15. MAPGIS K9基础平台培训讲义——数据管理
  16. 下载C语言标准库源码
  17. php右侧弹窗QQ客服,网页右侧悬浮滚动在线qq客服代码示例_javascript技巧
  18. HTML5----响应式(自适应)网页设计
  19. 小甲鱼——编程初学者的救赎
  20. 中大新华计算机科学与技术,专业评估|信息科学学院电子信息科学与技术、计算机科学与技术、软件工程、数字媒体技术专业评估考察会议举行...

热门文章

  1. linux下发送hex数据的串口调试软件,linux下模拟串口向计算机发送数据
  2. HTML学习(二):关于几种简单的标签(下)
  3. 微信开发平台账号权限申请过程
  4. 《VLSI数字信号处理系统设计与实现》(1)
  5. python正则表达式提取电话号码区号_python中的正则表达式,用于从剪贴板中提取特定格式的电话号码...
  6. 《中英双解》leetCode Jump Game(跳跃游戏)
  7. 【语言-c#】显示设置-设置了缩放比列后,如何处理鼠标光标位置和屏幕大小
  8. 哈佛大学公开课《公平与正义》全12集115网盘下载
  9. PCB线宽、过孔、载流能力整理
  10. 树莓派(Raspberry Pi 3) - 树莓派打造无线路由器