图&文 线性回归与梯度下降

前言

在机器学习领域,梯度下降法作为基础优化算法,在该领域具有较多的应用,而如何理解梯度下降法是引起初学者困惑的来源之一。本文通过图片阐述,公式推导等,从个人角度描述什么是梯度下降法。并通过梯度下降方法解释线性回归算法的参数收敛情况。

 


 

 

向量与方向:

在生活中,我们时常提到方向一词,如去东南方向,西北方向等。

而描述方向我们通常用东南西北将我们要去的位置进行标记,而我们走去的地方就是方向。

方向在几何学中我们称之为向量,有方向的量。

而对于二维坐标系中来说我们所谓的方向就是向量指向的位置,如图的东北方向。

当图像扩充到三维坐标系中,就有了三维空间的向量,其代表空间的方向。

 

 

 

方向导数与梯度:

导数反应的是函数的变化率,而偏导数反应的是函数沿坐标轴方向的变化率

 

 

方向导数:

e_{_l }=(cos\alpha ,cos\beta ) 是与射线同方向的单位向量,这里的  cos\alpha ,cos\beta 叫做方向余弦(即射线与x轴y轴夹角的余弦值)。

\frac{\partial f}{\partial l} |_{(x_{0},y_{0})}=f_{x}(x_{0},y_{0})cos\alpha +f_{y}(x_{0},y_{0})cos\beta

该式子就是在 (x_{0},y_{0}) 点沿 l 方向的方向导数,描述的就是沿着 l 方向的变化情况。

 

梯度:

在函数上标注一点,沿着该点偏导方向组成的向量就是梯度,也就是函数在该点的移动方向。

grad f(x_{0},y_{0})=\bigtriangledown f(x_{0},y_{0})=f_{x}(x_{0},y_{0})i +f_{y}(x_{0},y_{0})j

 

方向导数与梯度的关系:

图中我们假设函数是 y=0.5x^{2} ,射线AB为梯度方向AC是我们移动方向,可以看到AC方向与AB方向存在一个夹角α。

方向导数与梯度的关系公式,随着角度的变化而变化:

\frac{\partial f}{\partial l} |_{(x_{0},y_{0})}=\left | gradf(x_{0},y_{0}) \right |cos\alpha

而随着夹角的变化我们可以获得方向导数与梯度之间的关系如下:

(1)当α=0,选取方向与梯度方向相同,此时函数增加(上升)最快。

\frac{\partial f}{\partial l} |_{(x_{0},y_{0})}=\left | gradf(x_{0},y_{0}) \right |

(2)α=π,选取方向与梯度方向相反,此时函数减少(下降)最快。

\frac{\partial f}{\partial l} |_{(x_{0},y_{0})}=-\left | gradf(x_{0},y_{0}) \right |

(3)α=π/2,选取方向与梯度方向正交,此时函数变化率为0。

\frac{\partial f}{\partial l} |_{(x_{0},y_{0})}=0

(4)当α=任意值时,选取方向与梯度方向呈α角度,此时函数变化率如下。

\frac{\partial f}{\partial l} |_{(x_{0},y_{0})}=\left | gradf(x_{0},y_{0}) \right |cos\alpha

由于cos\alpha取值在[0,1]之间,因此方向导数是小于等于梯度的

可能有人不理解为什么沿梯度方向是最快的其他方向为什么就慢,我们可以参考物体受力问题。

只有沿着正受力方向才是最快的。

 

 

梯度下降公式推导:

 

通过线性回归获取最小二乘:

 

我们可以把 系数与值得乘积求和形式 写成  \theta ^{T}x的形式

h_{\theta}(x)=\theta _{0}+\theta _{1}x _{1}+x _{2}\theta _{2}

h(x)=\sum_{i=0}^{n}\theta _{i}x _{i}=\theta ^{T}x

 

我们可以把上图写成如下函数, 一条模拟的回归曲线 \theta ^{T}x 与随机震荡 \varepsilon ^{(i)} 的求和 

y^{(i)}=\theta ^{T}x^{(i)}+\varepsilon ^{(i)}

 

由于实际样本值很多,因此由中心极限定理我们可以知道  \varepsilon ^{(i)} 服从期望为0方差为 \sigma ^{2} 的正态分布

因此我们假设其正态分布公式为:

p(\varepsilon ^{(i)})=\frac{1}{\sqrt{2\pi }\sigma}exp\left ( -\frac{(\varepsilon ^{(i)})^{2}}{2\sigma^{2}} \right )

p(y^{(i)}|x^{(i)};\theta )=\frac{1}{\sqrt{2\pi }\sigma}exp\left ( -\frac{(y^{(i)}-\theta ^{T}x^{(i)})^{2}}{2\sigma^{2}} \right )

 

由于\varepsilon ^{(i)} 转化为 (y^{(i)}-\theta ^{T}x^{(i)}) , 因此 \varepsilon ^{(i)} 是由 \theta 变化决定的 

因此我们可以求取其最大似然估计,找出合适的 \theta 使得震荡数据落在高斯分布的中间,也就是让震荡越小。

这里为什么用极大似然估计,因为我们原始的目标是为了让\varepsilon ^{(i)}变小,从而相当让(y^{(i)}-\theta ^{T}x^{(i)})最小,让(y^{(i)}-\theta ^{T}x^{(i)})最小就相当于让整体式子最大,因此求最大概率就相当于让\varepsilon ^{(i)}最小。

L(\theta )=\prod_{i=1}^{m}p(y^{(i)}|x^{(i)};\theta )

         =\prod_{i=1}^{m}\frac{1}{\sqrt{2\pi }\sigma}exp\left ( -\frac{(y^{(i)}-\theta ^{T}x^{(i)})^{2}}{2\sigma^{2}} \right )

 

两边取对数:

l (\theta )=logL(\theta )

       =log\prod_{i=1}^{m}\frac{1}{\sqrt{2\pi }\sigma}exp\left ( -\frac{(y^{(i)}-\theta ^{T}x^{(i)})^{2}}{2\sigma^{2}} \right )

       =\sum_{i=0}^{m}log\frac{1}{\sqrt{2\pi }\sigma}exp\left ( -\frac{(y^{(i)}-\theta ^{T}x^{(i)})^{2}}{2\sigma^{2}} \right )

       =mlog\frac{1}{\sqrt{2\pi }\sigma}-\frac{1}{\sigma^{2}}\cdot\frac{1}{2} \sum_{i=1}^{m}(y^{(i)}-\theta ^{T}x^{(i)})^{2}

 

对分布函数求取最大似然估计,可以看到 影响该函数最值的其实是下面的目标函数,也就是最小二乘目标函数。

J(\theta )=\frac{1}{2} \sum_{i=1}^{m}(h_{\theta} (x^{(i)})-y^{(i)})^{2}

 

梯度下降更新系数值:

到此我们推出了最小二乘目标函数,而该函数有什么作用?

由于上文我们推断,要想求取一个合适的 \theta 使得在回归线附近的震荡最小,那么就相当于求取最小二乘目标函数的极小值

只要我们找到了该目标函数的极小值,那么极小值对应的 \theta 就是我们要求的回归函数的系数

所以现在我们知道我们的目的是什么了。

那么怎样求取最小值,为什么能求取最小值呢?

J(\theta )=\frac{1}{2} \sum_{i=1}^{m}(h_{\theta} (x^{(i)})-y^{(i)})^{2}

 

由于该函数的项数为2次,因此很容易得到该函数是凸函数

求取凸函数的下确界对应的值就是我们要选取的最小值

因此求取最小值,我们对目标函数求偏导:

\frac{\partial}{\partial \theta_{j} }J(\theta ) =\frac{\partial}{\partial\theta_{j} }\frac{1}{2} \sum_{i=1}^{m} (h_{\theta} (x^{(i)})-y^{(i)})^{2}

              =\frac{1}{2}\left ( \frac{\partial}{\partial \theta_{1} }(h_{\theta} (x^{(1)})-y^{(1)})^{2}+\frac{\partial}{\partial \theta_{2} }(h_{\theta} (x^{(2)})-y^{(2)})^{2}+...+\frac{\partial}{\partial \theta_{n} }(h_{\theta} (x^{(n)})-y^{(n)})^{2} \right )

 

每一个h_{\theta}(x) 都是由\theta_{i}组成的,因此对 总体求和的求导相当于对单项求导再求和

h_{\theta}(x)=\theta _{0}+\theta _{1}x _{1}+x _{2}\theta _{2}

 

进行求偏导,获取其梯度方向:

\frac{\partial}{\partial \theta_{j} }J(\theta ) =\frac{\partial}{\partial\theta_{j} }\frac{1}{2} \sum_{i=1}^{m} (h_{\theta} (x^{(i)})-y^{(i)})^{2}

               =\sum_{i=1}^{m}\frac{1}{2}\cdot 2 (h_{\theta} (x^{(i)})-y^{(i)})\cdot \frac{\partial}{\partial\theta _{j}} (h_{\theta} (x^{(i)})-y^{(i)})

               =\sum_{i=1}^{m}(h_{\theta} (x^{(i)})-y^{(i)})\cdot \frac{\partial}{\partial\theta _{j}} (\sum_{i=0}^{n}\theta _{i}x _{i}-y^{(i)})

               =\sum_{i=1}^{m}(h_{\theta} (x^{(i)})-y^{(i)})x_{j}

 

因此该结果就是目标函数沿着\theta方向的变化率

这里可以这样理解

y^{(i)}=\theta ^{T}x^{(i)}+\varepsilon ^{(i)}

 

由于x已知,为了让\varepsilon ^{(i)}震荡方差最小,从而优化\theta值,使结果\varepsilon ^{(i)}目标震荡最小

而对目标函数求偏导就是让\theta沿梯度上升方向变化

\frac{\partial}{\partial \theta_{j} }J(\theta ) =\sum_{i=1}^{m}(h_{\theta} (x^{(i)})-y^{(i)})x_{j}

 

因此我们可以根据梯度下降得到更新\theta值公式

\theta _{j}:=\theta _{j}-\alpha\frac{\partial}{\partial \theta_{j} }J(\theta )

 

\theta值沿着梯度下降方向更新,随着迭代次数增长,最终会收敛到最优的\theta值使得回归函数点在直线附近震荡最小。

y^{(i)}=\theta ^{T}x^{(i)}+\varepsilon ^{(i)}

 

 

图解理解梯度下降:

前文中提到,偏导数反应的是函数沿坐标轴方向的变化率。

下面图中描述梯度方向下降是怎样的过程:

(1)初始值x_{0}

(2)迭代x_{n+1}=x_{n}+\alpha (-grad(x_{n}})),至收敛。-grad(x_{n}})表示在x_{n}}处的负梯度方向即-f(x_{n})^{'}\alpha表示学习率

可以很容易计算,函数f(x)=0.1x^{2} 在A点的导数为正 ,因而函数在A点的梯度方向为正,梯度方向为f(x_{0})^{'},故由梯度下降法可知,下一个迭代值x_{n+1}=x_{n}+\alpha (-f(x_{0})^{'}),也就是说x0向左移动一小步到了x1,同理在x1点的导数同样大于零,下一次迭代x1向左移动一小步到达x2,一直进行下去,只要每次移动的步数不是很大,我们就可以得到收敛1的解x。

同样针对函数反方向,由于f(x_{0})^{'}是小于零的,因此梯度方向为负,负梯度方向为正,因此移动的位置是依次向右的

以下是二维梯度下降图

 

由物理现象理解偏导和步长:

我们会发现x移动的长度越来越短,这是由于在步长\alpha相同的条件下,梯度越来越小f(x_{0})^{'}。这就相当于越靠近最小值点,梯度的值越小,同样乘以步长\alpha,x的变化量就越小。如图可以看见grad1>grad3。

就相当于物体从斜面上的各点放置一个小球,在不同高度其力分量不同,因此单位时间(步长\alpha)其瞬时加速度不同(f(x_{0})^{'}),因此物体瞬时移动位移是不同的。

 

以上是关于梯度下降法原理的理解,后期如有新的理解,会在基础上增加内容。

 

 

本文是作者个人理解,希望讲述内容为大家提供帮助,如有理解或推导错误,忘批评指正。

 

参考资料:

高等数学同济版

Prof. Andrew Ng, Machine Learning, Stanford University

七月算法:http://www.julyedu.com/

该作者对梯度下降理解:https://blog.csdn.net/zhulf0804/article/details/52250220

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用Python的pygame库来实现利用方向键控制移动小球的效果。下面是一个简单的示例代码: ```python import pygame pygame.init() # 设置窗口大小和标题 screen = pygame.display.set_mode((400, 400)) pygame.display.set_caption("Move Ball") # 定义小球的初始位置和速度 ball_pos = [200, 200] ball_speed = [0, 0] # 循环监听事件 while True: for event in pygame.event.get(): # 监听关闭窗口事件 if event.type == pygame.QUIT: pygame.quit() exit() # 监听按键事件 elif event.type == pygame.KEYDOWN: if event.key == pygame.K_UP: ball_speed[1] = -5 elif event.key == pygame.K_DOWN: ball_speed[1] = 5 elif event.key == pygame.K_LEFT: ball_speed[0] = -5 elif event.key == pygame.K_RIGHT: ball_speed[0] = 5 elif event.type == pygame.KEYUP: if event.key == pygame.K_UP or event.key == pygame.K_DOWN: ball_speed[1] = 0 elif event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT: ball_speed[0] = 0 # 更新小球位置 ball_pos[0] += ball_speed[0] ball_pos[1] += ball_speed[1] # 绘制小球和背景 screen.fill((255, 255, 255)) pygame.draw.circle(screen, (255, 0, 0), ball_pos, 20) pygame.display.flip() ``` 在这个示例中,我们首先初始化pygame库,并设置了窗口的大小和标题。然后定义了小球的初始位置和速度。 在主循环中,我们循环监听事件,如果是关闭窗口事件,就退出程序;如果是按键事件,就根据按下的方向键来修改小球的速度;如果是松开方向键事件,就将相应方向的速度设为0。最后,我们根据小球的速度更新小球的位置,并在屏幕上绘制出小球和背景。使用`pygame.display.flip()`函数来更新屏幕上的显示。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值