前言
这个系列的文章旨在记录我对AI算法的梳理、理解、思考与灵感。
AI的任务,实际上是一个在连续可导的曲线上,寻找最小值点的过程。实际上,对于AI模型来说,只有两个东西——损失函数和参数。AI的目标实际上就是寻找到$f(x)$函数的最小值点,其中,$f(x)$代表,当参数取值为$x$的时候,整体的损失函数值。
小处落墨:泰勒公式与牛顿法
对于一个连续可导的函数$f(x)$来说,在某一点上,可以用多项式来模拟这个函数的表现,为什么?
首先,$f(x)$是可导的,那么根据导数的定义,必然有下面的公式成立:
既然已经限制在了$a$附近,我们就把极限符号拿掉,添加一个无穷小的余项(根据极限的定义),稍稍变化一下,得到了:
$$
f(x)=(x-a)f’(a)+f(a)+\alpha(x)(x-a)
$$
也就是说,在$a$附近,$f(x)$的值,和一阶导数有关。
那么我们再考虑这样一个公式,如果$f(x)$在$x=a$的时候,二阶可导呢?那么就有这样一个公式:
$$
f’(x)=(x-a)f(a)+f’(a)+\beta(x)(x-a)
$$
为了消除$\alpha(x)(x-a)$,我们首先设之为$R(x)$,而我们根据上面的式子,有:
$$
R(x)=f(x)-(x-a)f’(a)-f(a)
$$
也就有:
$$
R’(x)=f’(x)-f’(a)=(x-a)f’^\prime(a)+\beta(x)(x-a)
$$
那么,根据积分的定义:
$$
R(x)=\frac{1}{2}f’^\prime(a)(x-a)^2+\frac{1}{2}\beta(x)(x-a)^2=\frac{1}{2}f’^\prime(a)(x-a)^2+o((x-a)^2)
$$
那么
将这个式子带入到上面的式子里:
$$
f(x)=\frac{1}{2}(x-a)^2f’^\prime(a)+(x-a)f’(a)+f(a)+o((x-a)^2)
$$
那么,不断地求导下去,假设函数$n+1$阶可导,便有这样一个公式:
$$
f(x)=\sum_{i=0}^n\frac{(x-a)^i}{i!}f^{(i)}(a)+o((x-a)^n)
$$
这便是泰勒公式——用多项式来模拟函数局部情况的方法,更具体地说,是用各阶导数来模拟函数局部情况的方法。只要知道了一点的各阶导数,就可以反推出这个点的函数值。
还记得我们在前言说过的话吗?“AI的任务,实际上是一个在连续可导的曲线上,寻找最小值点的过程”。那么我们有了一个依靠多项式表示函数的方法,我们先不讨论最值点,先来看看它的极值点在哪里吧?由于求高阶导数比较复杂,我们只考虑最高三阶可导的情况。所谓极值点,便是一阶导数值为0的点:
$$
f’(x)=f’(a)+(x-a)f’^\prime(a)=0
$$
那么:
$$
x=a-\frac{f’(a)}{f’^\prime(a)}
$$
这是什么意思呢?AI的目标是寻找到一个极值点,但是AI只知道当前点附近的变化,所以可以通过这个公式进行优化:
$$
x_{t+1}=x_t-\frac{f’(t)}{f’^\prime(t)}
$$
其中,$t$代表当前时间步,$t+1$代表下一时间步,$x_t$代表时间步$t$时刻的参数取值——这便是牛顿法,通过二阶导数和一阶导数寻找极值的方法。
这个方法能用吗?其实并不能直接用到AI上——因为通常二阶导数很难求,而且,并不能保证这样得到的极值点是极小值点,更不能保证是最值点。
一点改进:梯度下降
在牛顿法的基础上,我们引出了两个问题。为了解决这个问题,我们可以将牛顿法分母的二阶导数删去,改为一个阈值$\epsilon$,就变成了:
$$
x_{t+1}=x_t-\frac{f’(t)}{\epsilon}
$$
令$\eta=\frac{1}{\epsilon}$,就得到了:
$$
x_{t+1} = x_t - \eta f’(t)
$$
这便是梯度下降了,其中$\eta$我们叫做学习率,管理下降的步长。它克服了牛顿法的第一个问题——不必求二阶导数了,对于第二个问题来说,由于函数的梯度始终指向增长最快的方向,所以,只要$\eta$设置合理,就必然找到极值点。
那么……一定是最值吗?并不一定——有可能找到的是极小值点而非最小值点,也就是鞍点。除此之外,固定学习率回带来这样的影响:参数很可能在极值点两端跳来跳去,没法达到这个点。
那么,有什么克服的方法吗?有的。
首先便是Momentum方法,梯度下降好比开车下山,如果动力不够,很容易就掉入鞍点,但是,只要速度够快,就能够跨越鞍点所在的坑。Momentum方法就是这样的思想,首先引入了一个动量公式:
$$
m_{t+1}=\rho m_t+f’(x_t)
$$
随后:
$$
x_{t+1} = x_t-\eta m_{t+1}
$$
这个方法考虑了之前变化带来的影响——好比开车带来的惯性影响。对于比较浅的鞍点来说,这个方法能够很好地克服其影响。
在这个基础上,又有很多种变体,比如Nesterov方法,和Momentum方法不同之处在于$m_{t+1}$的计算方法:
$$
m_{t+1}=\rho m_t+f’(x_t+\rho m_t)
$$
和Momentum方法比,Nesterov方法计算梯度的位置不同,笔者认为,这一安排的目的是——提前观察落点的变化情况,从而加速收敛。假设当前的位置在鞍点之右,一旦Momentum过大,到了鞍点之左,Nesterov方法便会按照那个点的变化,中和$\rho m_t$带来的影响;如果Momentum过小,到了鞍点之右,便会增强$\rho m_t$的影响。
随后,便是一些涉及到学习率的方法,通常为了加速训练,比如AdaGrad,它引入了一个因子,管理学习率的变化:
$$
r_{t+1} = r_t + (f’(x_t))^2
$$
更新方法是:
$$
x_{t+1} = x_t - \frac{\eta}{\sqrt{r_t+\alpha}}f’(x_t)
$$
这一方法的思想是——随着训练不断进行,参数越来越接近极值点,那么就要缩小学习率,缓解震荡。这一方法的缺陷很明显——有可能收到鞍点的影响,此外,当参数和极值相差甚远时,有可能很慢才收敛。
解决方法之一为RMSProp方法,和AdaGrad的不同之处在于,其参数累计过程是一个加权平均过程:
$$
r_{t+1} = \rho r_t+(1-\rho)(f’(x))^2
$$
通过加权,一定程度上控制了AdaGrad的不足之处。既考虑了学习率的变化,也考虑了动量带来的影响。
聪明的你已经想到了——何不将动量和学习率控制结合起来呢?这就是现在十分常用的方法——Adam。其公式请自行搜索——hexo不显示我的图片,MathJAX也不渲染公式,疑似本篇文章引发了一些连锁bug。
大处着笔:EM方法
如果说泰勒公式和牛顿法,是“小处落墨”的艺术——从函数上的某一个点开始,不断优化模型的参数;那么EM法便是“大处着笔”的法则——考察整体数据,得到最优参数。
不错,“AI的任务,实际上是一个在连续可导的曲线上,寻找最小值点的过程”。但是,这个过程也可以看作,给定数据,模拟数据分布的过程。其中,前一种观点,是一个损失函数-参数取值的函数,希望获得一个另损失函数值最小的参数取值;后一种观点,是一个契合程度-参数取值的函数,希望获得一个与原分布最为契合的参数取值。
给定一系列数据样本点$x_i$,我们的目标是:
那么一切已经呼之欲出了,我们把$c$解开:
$$
\theta^*=\arg \max_\theta E(y)\log\int \frac{P(x_i,y_i|\theta)}{D(y_i)}{\rm d}y_i
$$
再变换:
$$
\theta^*=\arg \max_\theta E(y)\log\int (\log P(x_i,y_i|\theta) - \log D(y_i)){\rm d}y_i
$$
这便是EM算法:
- 在确定参数$\theta$的情况下,获取$D(y_i)$。
- 获取$D(y_i)$后,调节$\theta$,使式子最大。