本文正在参加「金石方案 . 瓜分6万现金大奖」
前言
前导博文:
- 【AI】浅谈梯度下降算法(理论篇)
- 【AI】浅谈梯度下降算法(实战篇)
通过前导博文的学习,想必大家关于梯度下降也有所掌握了,其中在 【AI】浅谈梯度下降算法(实战篇) 博文中有大略的说到过梯度下降的三大家族,本博文将结合代码完成来细细讲解;
学习率
学习率,想必大家在前导博文中也见过该词,为什么要说到学习率呢,且听我渐渐剖析;
首要要知道,梯度下降的中心思想便是迭代地调整参数从而使本钱函数最小化。
具体来说,首要运用一个随机的 \theta 值(这被称为随机初始化),然后逐渐改进,每次踏出一步,每一步都测验下降一点本钱函数(如在线性回归中选用 MSE),直到算法收敛出一个最小值,如下图所示:
可是,这其中有一个十分重要的超参数,学习率 Learning Rate,它影响了每一步的步长;
假如学习率太低,算法需求通过大量迭代才干收敛,这将消耗很长时刻:
反之,假如学习率太高,这会导致算法发散,值越来越大,终究无法找到好的处理方案:
而且,并不是一切的本钱函数看起来都像一个漂亮的碗。有的或许看着像洞、像山脉、像高原或者是各种不规则的地势,导致很难收敛到最小值。
假如随机初始化,算法从左边起步,那么会收敛到一个部分最小值,而不是大局最小值。假如从右侧起步,那么需求通过很长时刻才干越过整片高原,假如停下来太早,将永久达不到大局最小值。
因此,关于学习率的设置显得尤为重要,下面来看看不同的学习率所带来的影响:
def plot_gradient_descent(theta, eta, theta_path=None):
m = len(X_b)
plt.plot(X, y, "b.")
for i in range(max_iters):
if i < 10:
y_predict = X_new_b.dot(theta)
style = "g-" if i > 0 else "r--"
plt.plot(X_new, y_predict, style)
gradients = 2/m * X_b.T.dot(X_b.dot(theta) - y)
theta = theta - eta * gradients
if theta_path is not None:
theta_path.append(theta)
plt.xlabel("$X$", fontsize=18)
plt.title(r"$\eta = {}$".format(eta), fontsize=16)
绘制了梯度下降的前十步,虚线表明起点,\eta 表明为学习率:
得出结论:
- 左图:在前十步无法找到处理方案,可是只要长时刻的迭代就必定能够找到处理方案;
- 中图:作用看起来不错,比较契合预期,几回迭代就收敛出了终究解;
- 右图:算法发散,直接跳过了数据区域,而且每一步都离实际处理方案越来越远;
要找到合适的学习率,能够运用网络搜索。可是或许需求限制迭代次数,这样网络搜索就能够淘汰掉那些收敛耗时太长的模型。
可是怎样限制迭代次数呢?假如设置太低,算法或许在离最优解还很远时就中止了;可是假如设置得太高,模型抵达最优解后,继续迭代参数不再改变,又会浪费时刻。
一个简略的方法是在开端设置一个十分大的迭代次数,可是当梯度向量的值变得很微小时中止算法,也便是当他的范数变得低于 \varepsilon(称为容差)时,由于这是梯度下降已经(几乎)抵达了最小值。
收敛率:当本钱函数为凸函数,而且斜率没有陡峭的改变时(如 MSE 本钱函数),通过批量梯度下降能够看出一个固定的学习率有一个收敛率,为 O(1迭代次数)O(\frac{1}{迭代次数})。换句话说,假如将容差 \varepsilon 缩小为原本的 110\frac{1}{10}(以得到更准确的解),算法将不得不运转 10 倍的迭代次数。
批量梯度下降 BGD
梯度下降法最常用的形式,具体做法也便是在更新参数时运用一切的样原本进行更新;
- 长处:大局最优解,易于并行完成;
- 缺点:核算代价大,数据量大时,练习进程慢;
要完成梯度下降,需求核算每个模型关于参数 j\theta_j 的本钱函数的梯度。换言之,需求核算的是,假如改变 j\theta_j,本钱函数会改变多少,即偏导数。以线性回归的本钱函数 MSEMSE 为例,其偏导数为:
假如不想独自核算这些梯度,能够运用下面的公式对其进行一次性核算。梯度向量 ∇MSE()\nabla_\theta MSE(\theta),包含一切本钱函数(每个模型参数一个)的偏导数。
代码完成:
1、随机初始化:
X = 2 * np.random.rand(100, 1)
y = 21 + 5 * X + np.random.randn(100, 1)
X_b = np.c_[np.ones((100, 1)), X]
2、设置各参数:
m = 100
eta = 0.1
n_epochs = 1000
theta = np.random.randn(2,1)
3、BGD
算法完成:
for epoch in range(n_epochs):
gradients = 2/m * X_b.T.dot(X_b.dot(theta) - y)
theta = theta - eta * gradients
print('theta:\n{}\n'.format(theta))
4、绘制图画:
X_new = np.array([[0], [2]])
X_new_b = np.c_[np.ones((2, 1)), X_new]
y_predict = X_new_b.dot(theta)
plt.title(f"$\eta = {0.1}$")
plt.plot(X_new, y_predict, "r-")
plt.plot(X, y, "b.")
plt.show()
批量梯度下降法由于运用了悉数样本进行练习,所以当损失函数是凸函数时,理论上能够找到大局最优解,但当练习样本很大时,其练习速度会十分慢,不适用于在线学习的一些项目。为了处理这个问题,随机梯度下降算法被提出。
随机梯度下降 SGD
和批量梯度下降法原理类似,区别在于求梯度时,没有用一切的 mm 个样本的数据,而是只是选取一个样本 jj 来求梯度;
- 长处:练习速度快;
- 缺点:准确度下降,并不是大局最优,不易于并行完成;
由于算法的随机性质,它比批量梯度下降要不规则得多。本钱函数将不再是缓缓下降直到抵达最小值,而是不断上上下下,可是从全体来看,还是在渐渐下降。随着时刻的推移,终究会十分挨近最小值,可是即使它抵达了最小值,仍然还会继续反弹,永久不会中止。所以算法停下来的参数值肯定是足够好的,但不是最优的。
当本钱函数十分不规则时,随机梯度下降其实能够帮助算法跳出部分最小值,所以 比较批量梯度下降,它对找到大局最小值更有优势 。
由于,随机性的优点在于能够逃离部分最优,但缺点是永久定位不出最小值。 要处理这个窘境,有一个办法是逐渐下降学习率。开端的步长比较大(这有助于快速发展和逃离部分最小值),然后越来越小,让算法尽量挨近大局最小值,这个进程叫做模拟退火:由于它类似于冶金时消融的金属渐渐冷却的退火进程。
确认每个迭代学习率的函数叫作学习方案。假如学习率降得太快,或许会堕入部分最小值,甚至是停留在走向最小值的半途中。假如学习率太慢,你或许需求太长时刻太能跳到差不多最小值附近,假如提早结束练习,或许只得到一个次优的处理方案。
代码完成:
1、初始化进程同上;
2、SGD
算法完成:
为了避免练习速度过慢,随机梯度下降法在练习进程中每次仅针对一个样本进行练习,但进行屡次更新。在每一轮新的更新之前,需求对数据样本进行从头洗牌(shuffle)。
for epoch in range(n_epochs):
# 每个次序开端分批次迭代之前打乱数据索引次序
arr = np.arange(len(X_b))
np.random.shuffle(arr)
X_b = X_b[arr]
y = y[arr]
for i in range(m):
xi = X_b[i:i+1]
yi = y[i:i+1]
gradients = xi.T.dot(xi.dot(theta)-yi)
theta = theta - eta * gradients
print('theta:\n{}\n'.format(theta))
3、绘制图画:
# 在上述代码段内部参加
for i in range(m):
xi = X_b[i:i+1]
yi = y[i:i+1]
gradients = xi.T.dot(xi.dot(theta)-yi)
theta = theta - eta * gradients
if epoch == 0 and i % 5 == 0:
y_predict = X_new_b.dot(theta)
style = "m--" if i > 0 else "r--"
plt.plot(X_new, y_predict, style)
if epoch == 1 and i % 5 == 0:
y_predict = X_new_b.dot(theta)
style = "g--" if i > 0 else "r--"
plt.plot(X_new, y_predict, style)
X_new = np.array([[0], [2]])
X_new_b = np.c_[np.ones((2, 1)), X_new]
y_predict = X_new_b.dot(theta)
plt.title(f"$\eta = {0.1}$")
plt.plot(X_new, y_predict, "k-")
plt.plot(X, y, "b.")
plt.show()
随机梯度下降法在更新进程中由于是针对单个样本,所以其迭代的方向有时候并不是全体最优的方向,同时其方差较大,导致损失函数值的变动并不是规律的递减,更多的状况或许是动摇形状的下降。
为了处理批量梯度下降的速度太慢以及随机梯度下降方差变动过大的状况,一种折中的算法–小批量梯度下降算法被提出,其从悉数样本中选取部分样本进行迭代练习。而且在每一轮新的迭代开端之前,对悉数样本进行 Shuffle 处理。
小批量梯度下降 MBGD
小批量梯度下降法是批量梯度下降法和随机梯度下降法的折中,也便是关于 mm 个样本,我们选用 xx 个样原本迭代,1<x<m1<x<m。一般能够取 x=10x=10,当然依据样本的数据量,能够调整这个 xx 的值;
相关于随机梯度下降算法,小批量梯度下降算法下降了收敛动摇性, 即下降了参数更新的方差,使得更新愈加安稳。相关于全量梯度下降,其提高了每次学习的速度。而且其不必忧虑内存瓶颈从而能够使用矩阵运算进行高效核算。一般来说每次更新随 机挑选[50,256]个样本进行学习,可是也要依据具体问题而挑选,实践中能够进行屡次实验, 挑选一个更新速度与更次次数都较适合的样本数。
代码完成:
1、初始化进程同上;
2、动态调整学习率:
t0, t1 = 5, 500
def learning_rate_schedule(t):
return t0 / (t + t1)
3、MBGD
算法完成:
theta = np.random.randn(2,1)
for epoch in range(n_epochs):
arr = np.arange(len(X_b))
np.random.shuffle(arr)
X_b = X_b[arr]
y = y[arr]
for i in range(n_batches):
x_batch = X_b[i * batch: i * batch + batch]
y_batch = y[i * batch: i * batch + batch]
gradients = x_batch.T.dot(x_batch.dot(theta)-y_batch)
eta = learning_rate_schedule(epoch * m + i)
theta = theta - eta * gradients
print('theta:\n{}\n'.format(theta))
4、绘制图画:
# 在上述代码段内部参加
for i in range(n_batches):
x_batch = X_b[i * batch: i * batch + batch]
y_batch = y[i * batch: i * batch + batch]
gradients = x_batch.T.dot(x_batch.dot(theta)-y_batch)
eta = learning_rate_schedule(epoch * m + i)
theta = theta - eta * gradients
if epoch == 0 and i < 5:
y_predict = X_new_b.dot(theta)
style = "m--" if i > 0 else "r--"
plt.plot(X_new, y_predict, style)
if epoch == 1 and i < 5:
y_predict = X_new_b.dot(theta)
style = "g--" if i > 0 else "r--"
plt.plot(X_new, y_predict, style)
X_new = np.array([[0], [2]])
X_new_b = np.c_[np.ones((2, 1)), X_new]
y_predict = X_new_b.dot(theta)
plt.title(f"$\eta = {0.1}$")
plt.plot(X_new, y_predict, "k-")
plt.plot(X, y, "b.")
plt.show()
后记
以上三种梯度下降算法仅局限于对练习样本进行改变,且每次迭代更新权重时运用的梯度仅作用于当时状况。由于每一期的样本有好有坏,导致迭代进程是弯曲动摇的,影响了收敛速度。
下图显示了练习期间参数空间中三种梯度下降算法所选用的路径。它们终究都挨近最小值,可是批量梯度下降的路径实际上是在最小值处中止,而随机梯度下降和小批量梯度下降都继续走动。可是,不要忘记批量梯度下降每步需求花费许多时刻,假如你运用杰出的学习率调度,随机梯度下降和小批量梯度下降也会达到最小值。
让我们比较到目前为止讨论的线性回归算法,mm 是练习实例的数量,nn 是特征的数量。
算法 | mm 很大 | 核外支撑 | nn 很大 | 超参数 | 要求缩放 |
---|---|---|---|---|---|
规范方程 | 快 | 否 | 慢 | 0 | 否 |
SVD | 快 | 否 | 慢 | 0 | 否 |
BGD | 慢 | 否 | 快 | 2 | 是 |
SGD | 快 | 是 | 快 | ≥\geq2 | 是 |
MBGD | 快 | 是 | 快 | ≥\geq2 | 是 |
参阅:
- 不同梯度下降算法的比较及Python完成
- 使用python完成3种梯度下降算法
上篇精讲:【AI】浅谈梯度下降算法(实战篇)
我是,等待你的重视;
创造不易,请多多支撑;
系列专栏:AI