从0了解机器学习:2——线性回归

本文章将介绍监督学习中的线性回归算法,以及一些其他有关概念

(如果文章中的公式不能正常显示,请刷新该页面。如果还不能解决,请邮箱联系我,谢谢...)

线性回归(Linear Regression)

在上图中展示了线性回归模型,我们发现它有一些特点:

  • 预测数字
  • 数据都有标签“正确答案”
  • 输出数据无限

而对比分类来说:

  • 预测类型:
    • 类别
    • 离散类别
  • 输出数据有限

在进行线性回归之前,我们一般得到了数据需要进行一些可视化,而对于线性回归或者说监督学习的数据来说,我们一般使用以下方式进行可视化:

  • 数据表格
  • 数据图

在了解算法过程时,我们也需要了解一些术语:

训练:使用数据去训练机器学习模型

数据:对于监督学习来说,一般都是输入x与标签y一一对应的数据,例如:

\(x\):房屋面积(\(m^2\) \(y\):房屋价格(w)
(1)651 400
(2)426 232
(3)507 315
(4)275 178
... ...
(47)1065 870

x:输入变量/特征

y:输出变量/目标变量

m:训练数据的个数

(x,y):一对训练数据

\(x^{(1)}=651 \quad y^{(1)}=400\)

\((x^{(1)},y^{(1)})=(651,400)\)

\((x^{(i)},y^{(i)})\) 第 i 个训练数据

线性回归过程

在线性回归中,怎么代表 \(f\) 呢: \[ f_{w,b}(x)=w\cdot x+b \quad \Leftrightarrow \quad f(x)=w\cdot x+b \] \[ f_{w,b}(x)=f(x)=w\cdot x+b\qquad 线性函数 \] 对于上述的 \(f_{w,b}(x)\) 只有一个特征 \(x\)

我们称其为:单变量线性回归

梯度下降(Gradient descent)

在之前的机器学习入门数学原理中,我们讲到了线性回归的目标函数:\(\frac{1}{2}\sum_{i=1}^n(f(x^{(i)})-y^{(i)})^2\)

在这里我们将其改进为: \[ J(w,b)=\frac{1}{2m}\sum_{i=1}^m(f_{w,b}(x)-y^{(i)})^2 \] Q:为什么在分母加了 m 呢?

A:原来的函数求的是所有数据的误差之和,在机器学习算法中,我们需要除以总的样本数,求取平均误差,有利于减少数据膨胀,导致目标函数为很高的值

这就是均方差函数(MSE)

我们要做的,就是使得这个函数最小,也就是让误差变小,这样就能用直线拟合数据了

梯度下降过程:

  • 初始化 \(w,b\) (设置 \(w,b=0\) 或者其他随机的值)
  • 修改 \(w,b\) 以降低 \(J(w,b)\) 的值
  • 直到 \(J(w,b)\) 落在最小值或者最小值附近

但是,函数 \(J(w,b)\) 可能不仅仅有一个最小值,就像下图:

图中的函数图像不是均方差函数,也不是线性回归模型,图只是展示局部最小值(local minima)的情况

根据我们机器学习入门数学原理那篇文章,均方差函数只有一个最小值

梯度下降算法: \[ \begin{gather} w=w-lr\cdot\frac{\partial J(w,b)}{\partial w} \\ b=b-lr\cdot\frac{\partial J(w,b)}{\partial b} \\ lr\;为学习率 \end{gather} \] 在实际代码编写梯度下降算法时,要注意:

以下是错误的代码:

1
2
3
4
tmp_w = w - lr * grad(w, b) // grad(w,b)这里代表对 J(w,b) 求对应的偏导
w = tmp_w <--- error
tmp_b = b - lr * grad(w, b)
b = tmp_b

上述代码错在:

在还没有对 b 更新时,就将更新后的 w 赋值,导致在更新 b 时,对 b 求偏导时,函数 J(w, b) 中的 w 已经被更新过了,导致 w,b没有同步更新

正确的代码:

1
2
3
4
tmp_w = w - lr * grad(w, b) // grad(w,b)这里代表对 J(w,b) 求对应的偏导
tmp_b = b - lr * grad(w, b)
w = tmp_w
b = tmp_b

在对 w,b 求完偏导后再将他们一起更新

学习率(Learning rate)

如果设置学习率时,设置得太小,那么梯度下降的速度就会非常缓慢

当然,如果设置过大,那么在更新参数时,参数会“左右横跳”,导致无法到达最小值

以上我们在数学原理中讲过

当你在观察梯度下降的过程时,你会发现,当目标函数接近最小值的时候,梯度会越来越小,同样的,参数的更新速度也会越来越慢,这是由函数图像和参数更新公式决定的

批梯度下降(Batch gradient descent): 每一步梯度下降都将用到所有的训练数据

(与小批量梯度下降不同,小批量梯度下降只会使用一部分的数据)

多特征(Multiple features/variables)

之前的房价-面积数据,只有一个特征:面积

而现实中,使用机器学习时我们一般都会遇到多特征的数据,例如:

房屋面积:x1 卧室数量:x2 房屋层数:x3 房屋年龄:x4 房价(W):y
(1)651 5 1 45 460
(2)426 3 2 40 232
(3)507 3 2 30 315
(4)275 2 1 36 178
... ... ... ... ...
  • \(x_j\):第 j 个特征

  • n:特征的数量

  • \(\vec{x}^{(i)}\): 第 i 个数据的所有特征,例如: \(\vec{x}^{(2)}=[426,3,2,40]\)

  • \(x_j^{(i)}\):特征 j 的第 i 个数据,例如:\(x_3^{(2)}=2\)

对于目标函数:\(f_{w,b}(x)=wx+b\)

应用以上案例,我们有表达式: \[ f_{w,b}(x)=w_1x_1+w_2x_2+w_3x_3+w_4x_4+b \] 给参数初始化: \[ \begin{gather} f_{w,b}(x)=0.1x_1+4x_2+10x_3-2x_4+80 \\ \quad\quad\quad\quad\quad\quad\quad\quad\qquad\qquad\uparrow 面积\;\uparrow卧室数\uparrow层数\uparrow房龄\uparrow偏置(基本房价) \end{gather} \] 而对于n个特征来说,目标函数: \[ f_{w,b}(x)=w_1x_1+w_2x_2+w_3x_3+...+w_nx_n+b \] 我们可以使用向量来简化上述函数: \[ \begin{gather} f_{\vec{w},b}(\vec{x})=\vec{w}\cdot\vec{x}+b \\ \vec{w}=[w_1,w_2,w_3,...,w_n] \\ b为偏置 \\ \vec{x}=[x_1,x_2,x_3,...,x_n] \end{gather} \] 上述有多个特征/变量,称为:多元线性回归

向量化(Vectorization)

将数据向量化有助于减少计算量,同时也能使用GPU加速,因为GPU很擅长向量/矩阵计算

给一个例子: \[ \begin{gather} \vec{w}=[1.0,2.5,-3.3] \\ b=4 \\ \vec{x}=[10,20,30] \end{gather} \] 如果在python中该如何计算呢?

1
f = w[0] * x[0] + w[1] * x[1] + w[2] * x[2] + b

如果特征数量n=10000甚至更多呢,该怎么计算?

1
2
3
4
f = 0
for i in range(n):
f += w[i] * x[i]
f += b

那向量化该怎么操作?

1
2
3
import numpy as np

f = np.dot(w, x) + b

向量化的操作,比之前的两种方法快得多得多

那么,为什么会那么快呢?

原因是向量化将所有的乘法操作一步完成,就像这样:

单特征梯度下降参数更新公式: \[ \begin{gather} w=w-lr\frac{1}{m}\sum_{i=1}^m(f_{w,b}(x^{(i)})-y^{(i)})x^{(i)} \\ b=b-lr\frac{1}{m}\sum_{i=1}^m(f_{w,b}(x^{(i)})-y^{(i)}) \\ 有时学习率为:lr、\alpha、\eta \end{gather} \] 多特征的参数更新公式: \[ \begin{gather} w_1=w_1-lr\frac{1}{m}\sum_{i=1}^m(f_{\vec{w},b}(\vec{x}^{(i)})-y^{(i)})x^{(i)} \\ . \\ . \\ . \\ w_n=w_n-lr\frac{1}{m}\sum_{i=1}^m(f_{\vec{w},b}(\vec{x}^{(i)})-y^{(i)})x^{(i)} \\ b=b-lr\frac{1}{m}\sum_{i=1}^m(f_{\vec{w},b}(\vec{x}^{(i)})-y^{(i)}) \end{gather} \]

特征缩放(Scale the feature)

有时候,特征与特征之间的数值差距实在很大,这会导致某一特征主导了模型学习过程,并且梯度下降的速度也将变得缓慢且不稳定,我们需要将他们变为相似的尺度

给出一个例子: \[ \hat{price}=w_1x_1+w_2x_2+b\qquad\qquad x_1:房屋面积\quad x_2:楼层数量 \] 房屋面积很大:50~1000 而楼层数量一般较少:1~5

有一套房产:\(x_1=1000\quad x_2=3\quad price=300W元\)

如果:\(w_1=50\quad w_2=0.1\quad b=50\) \[ \begin{gather} \hat{price}=50\times1000+0.1\times3+50 \\ \hat{price}=50150.3W元 \end{gather} \] 与300W差距太大了,如果一开始初始化为这样,那么目标函数的值会非常大

如果:\(w_1=0.1\quad w_2=50\quad b=50\) \[ \begin{gather} \hat{price}=0.1\times1000+50\times3+50 \\ \hat{price}=300W元 \end{gather} \] 如果这是最终梯度下降结束后的参数值,那么 \(w_1\)\(w_2\) 相差500倍!

特征的大小在梯度下降中的表现:

没有进行特征缩放时,原始特征:

进行了特征缩放后:

说了特征缩放的好处,那么该怎么缩放呢?

这里给出一个例子:\(\quad300\leq x_1\leq 2000\qquad 0\leq x_2\leq5\quad\) 下面几种方法都将使用这个例子

这里有几种方法:

  • 方法一:除以各自的最大值

\[ \begin{gather} x_{1,scaled}=\frac{x_1}{x_{1max}}=\frac{x_1}{2000}\qquad\Rightarrow\qquad 0.15\leq x_{1,scaled}\leq1 \\ x_{2,scaled}=\frac{x_2}{x_{2max}}=\frac{x_2}{5}\qquad\Rightarrow\qquad 0\leq x_{2,scaled}\leq1 \end{gather} \]

  • 方法二:均值归一化(标准化)

\[ \begin{gather} x_{1,scaled}=\frac{x_1-\mu_1}{max-min}=\frac{x_1}{2000-300}\qquad\Rightarrow\qquad -0.18\leq x_{1,scaled}\leq0.82 \\ x_{2,scaled}=\frac{x_2-\mu_2}{max-min}=\frac{x_2}{5-0}\qquad\Rightarrow\qquad -0.46\leq x_{2,scaled}\leq0.54 \\ \mu:\;均值 \end{gather} \]

  • 方法三:Z分数标准化(Z-score normalization)

\[ \begin{gather} x_{1,scaled}=\frac{x_1-\mu_1}{\sigma}\qquad\Rightarrow\qquad -0.67\leq x_{1,scaled}\leq3.1 \\ x_{2,scaled}=\frac{x_2-\mu_2}{\sigma}\qquad\Rightarrow\qquad -1.6\leq x_{2,scaled}\leq1.9 \\ \mu:\;均值 \\ \sigma:\;标准差 \end{gather} \]

我们什么时候需要使用特征缩放呢?

首先得了解,特征缩放需要的目标范围: \[ \begin{gather} -1\leq x\leq1 \\ -3\leq x\leq3 \\ -0.3\leq x\leq0.3 \end{gather} \] 以上的范围都是可以的

当然,下面这些范围也是可以接受的,不使用特征缩放也是没有任何危害: \[ \begin{gather} 0\leq x\leq3 \\ -2\leq x\leq0.5 \end{gather} \] 而下面这些范围就需要使用特征缩放了: \[ \begin{gather} -100\leq x\leq100\qquad太大了 \\ -0.001\leq x\leq0.001\qquad太小了 \\ -98.6\leq x\leq105\qquad太大了 \end{gather} \] 合适的特征缩放将会加快梯度下降的速度

判断收敛(Judge convergence)

自动收敛:我们可以选择一个 \(\epsilon\) 值,执行训练时,当某一次训练使得目标函数小于 \(\epsilon\) 就判断收敛,停止训练,此时就找到了 \(\vec{w},b\) 接近于全局最小值

事实上,选择一个合适的 \(\epsilon\) 值是困难的,所以说我们一般都只是看上图,当目标函数每次下降很小时,就接近收敛了

当然,如果你的图像没有一直下降,甚至出现了上升,那么可能是你的学习率设置得太高了,或者你的代码出现了bug

那么如何选择一个合适的学习率呢?

其实,我们可以在一开始选择一个很小的学习率去测试模型

如果目标函数-训练次数图,出现了一些情况:

  • 下降:代码正确,可以进一步设置学习率
  • 出现上升:代码可能有bug

一般可以尝试以下学习率:

每下一次学习率的设置,都是基于本次训练的图像都是正常的下降,才可以接着设置学习率

特征工程(Feature engineering)

通过直觉或者知识和经验,从现有的特征中发现能够影响结果的新特征,或者通过组合现有特征,来获取更能反映输出结果的新特征,甚至可以去掉一些对结果没有影响的特征,来获得一个更好的模型

举一个例子:

  • \(x_1\):宽度
  • \(x_2\):纵深

\[ f_{\vec{w},b}(\vec{x})=w_1x_1+w_2x_2+b \]

但是你会发现,仅仅靠宽度和纵深并不能很好的刻画其与价格的映射,因为如果该房屋恰好是“刀片房”,也就是纵深很小,但是宽度很宽,或者纵深很大,但是宽度很小,那么估计没人会买这个房子,并且它的价格也会很低(刚毕业的大学生可能会考虑...doge)

所以说,我们可以合并这两个特征,也就是将纵深和宽度相乘,组合成新的特征——面积,这样将会很好的适配 \[ \begin{gather} 面积=宽度\times 纵深 \\ x_3=x_1x_2 \\ f_{\vec{w},b}(\vec{x})=w_1x_1+w_2x_2+w_3x_3+b \end{gather} \]

多项式回归(Polynomial regression)

一些无法使用直线拟合的数据,可能需要曲线拟合,这就用到了多项式回归

以下函数是一个多项式 \[ f_{\vec{w},b}(\vec{x})=w_1x_1+w_2x_2^2+w_3x_3^3+b \] 但是它有一个问题,高次的变量可能出现数值膨胀,例如: \[ \begin{gather} if:\quad1\leq x\leq1000 \\ \quad1\leq x_1\leq1000 \\ \quad1\leq x_2\leq1000000 \\ \quad1\leq x_3\leq1000000000 \end{gather} \] 所以说,在多项式回归里,特征缩放显得格外重要

总结

本文章讲了监督学习中的线性回归,同时也讲了一些其他概念:最重要的梯度下降,向量化的意义,特征缩放解决单一特征左右学习过程,收敛判断,特征工程等。

在接下来,我们将学习第二种监督学习——分类

从0了解机器学习:2——线性回归

http://www.heimaolala.top/2024/12/30/ML2/

作者

heimaolala

发布于

2024-12-30

更新于

2025-03-17

许可协议

评论