最速下降法/梯度下降法公式推导与python实现

来源:互联网 发布:英文域名注册 编辑:程序博客网 时间:2024/04/28 20:50

目录

  1. 最速下降法
    1.1 最速下降法的导出
    1.2 最速下降法的几个重要命题
    1.3 迭代停止条件
    1.4 最速下降算法步骤
  2. 各种梯度下降法
    2.1 梯度下降法
    2.2 梯度下降法与最速下降法的区别
    2.3 随机梯度下降法(Stochastic gradient descent)
    2.4 批量梯度下降法(BGD)
    2.5 小批量梯度下降(Mini-Batch Gradient Descent)

1.最速下降法

1.1 最速下降法的导出

最速下降法以负梯度方向为极小化算法的方向,又称梯度法,人们经常把最速下降法和梯度下降法等同,事实上,它们是不同的,这个稍后再说。先看一下最速下降法的定义。

设函数f(x)xk附近连续可微,gk=f(xk)0,在xk处对f进行泰勒展开有:

f(x)=f(xk)+(xxk)Tf(xk)+o(||xxk||)(1.1)
若记xxk=αdk,则满足dTkgk<0的方向dk是下降方向,也就是负梯度方向。当α取定之后,dTkgk的值越小,表示图中的坡越陡,函数下降得越快。

使用Cauchy-Schwartz不等式:

|dTkgk||dk||gk|
解这个不等式,当且仅当dk=gk时,dTkgk最小,从而称gk时最速下降方向。

其中最速下降法的迭代格式为:

xk+1=xkαkgk

1.2 最速下降法的几个重要命题

  1. 步长应该如何选取?在做逻辑回归的时候,我们用梯度下降法来求解最优参数,当时的步长可以是人工随机取符合数据和当前情境下的步长,那在这里,步长该如何选取呢?Cauchy曾经建议使用精确线搜索( 一维线搜索)来确定步长:
    f(xαkf(xk))=min{f(xαf(x)):α>0}
    其中αk就是最优步长
  2. 利用最速下降法搜索函数f:R2R的极小点,迭代过程中产生的迭代序列{x(k)}k=0,对于任意的k>0,都有
    xk+1xkxk+2xk+1
  3. 利用最速下降法搜索函数f:R2R的极小点,迭代过程中产生的迭代序列{x(k)}k=0,若梯度:f(x)0,则必有
    f(xk+1)<f(xk)

1.3 迭代停止条件

在实际中,采用数值计算的方法很难恰好得到梯度为0的结果,因此以梯度为0作为停止规则很不恰当。以下ϵ>0
(1) |f(xk+1)f(xk)|<ϵ

(2) ||xk+1xk||<ϵ

(3) |f(xk+1)f(xk)||f(xk)|<ϵ

(4) ||xk+1xk||||xk||<ϵ

(5) |f(xk+1)f(xk)|max{1,|f(xk)|}<ϵ

(6) ||xk+1xk||max{||xk||}<ϵ

上边的3,4式为1,2式的相对值,而5,6式是为了避免3,4式中的分母过小进行的修改。

1.4 最速下降算法步骤

A. 任取x0Rn,ϵ>0,k:=0
B .计算梯度f(xk),||f(xk)||<ϵ(或满足其他停止条件),则算法停止,计算步长αk,使得:

f(xαkf(xk))=min{f(xαf(x)):α>0}

C. 计算下一个迭代点xk+1=xkαkf(xk),令k:=k+1

2.各种梯度下降法

2.1 梯度下降法

梯度下降法经常用于机器学习,深度学习领域,用来更新模型的参数,使得模型的预测误差越来越小。它的原理就是沿着负梯度方向下山:这里写图片描述
其核心也是:

xk+1=xkaf(x)
不断迭代更新,直到最低点。

看一下它的伪代码:

model = initialization(...)n_epochs = ...train_data = ...for i in n_epochs:    train_data = shuffle(train_data)    X, y = split(train_data)    predictions = predict(X, train_data)    error = calculate_error(y, predictions)    model = update_model(model, error)

2.2 梯度下降法与最速下降法的区别

看完最速下降法,你可能觉得梯度下降法和最速下降法是一样的,但事实是,他们是有细微区别的。

梯度下降法同样认为梯度的反方向为下降最快的方向,所以沿着负梯度方向移动一定距离,目标函数也会减小,如果是凸函数,最终会达到全局最小值。同样,它的步长α也可以通过精准线搜索确定。

感觉它们都是移动单位步长,沿着下降最多的方向移动,但对于梯度下降法,如果是:

nsd=argminv(f(x)Tvv<=1)
,梯度下降法使用的是欧式范数||v||,也就是说,梯度下降法是最速下降法的一个特列,是最速下降法使用欧式范数的一种特例。更加详细的看这里:梯度下降法和最速下降法的细微差别

2.3 随机梯度下降法(Stochastic gradient descent)

随机梯度下降法是梯度下降法个一个变体,简称SGD,它对每个样本都会更新一次参数。正因如此,它会消耗更多的计算量,在大数据集上,训练得也会很慢。如果一连遇到比较多的噪声数据,频繁更新也会导致找不到正确的方向到达最低点。
这里写图片描述
如图所示,它的晃动会比较明显,但有可能只使用一部分样本,就能到底最低点了。

SGD 的另一个好处是, 可以使用在线学习 [online learning]. 也就是说, 在模型训练好之后, 只要有新的数据到来, 模型都可以利用新的数据进行再学习, 更新参数,以适应新的变化.

每个样本都会计算一次损失,更新公式如下:

θj=θj+(yihθ(xi))xij

def sgd(alpha, x, y, numIterations):    m = x.shape[0]    theta = np.ones(2)    #随机序列化,选样本    idx = np.random.permutation(y.shape[0])    x,y = x[idx], y[idx]    for j in range(numIterations):        for i in idx:            single_hypothesis = np.dot(x[i],theta)            single_loss = y[i] - single_hypothesis            gradient = np.dot(x[i].transpose(), single_loss)            theta += alpha*gradient    return theta

2.4 批量梯度下降法(BGD)

BGD会对每个训练样本都计算误差,但是更新参数是等所有的样本误差都计算完之后才更新的。也就是说,等计算完所有的训练样本的损失之后,模型的参数才更新一次。

整个训练集遍历完才更新参数,意味着损失(误差),或者说下降的方向更加稳定,同时需要的计算量也会更小。但也会因为最后才更新参数,训练模型的时候,整个训练集都要存在内存上,在大数据集上,训练的速度也会很慢。
这里写图片描述
如图所示,虽然很慢,但迭代的方向基本都是正确的,不会发生非常大的偏移,迭代起来较稳定。

遍历整个训练集,所以需要累加:

θj=θj+1mi=1m(yihθ(xi))xij

批量梯度下降的python代码

def bgd(alpha, x, y, numIterations):    m = x.shape[0]    theta = np.ones(2)    x_train = x.transpose()    for iteration in range(0, numIterations):        hypothesis = np.dot(x, theta)        loss = y - hypothesis        gradient = np.dot(x_train, loss)/m        theta +=alpha*gradient #所有数据完了之后,更新一次    return theta

2.4 小批量梯度下降(Mini-Batch Gradient Descent)

我们从上面两种梯度下降法可以看出,其各自均有优缺点,那么能不能在两种方法的性能之间取得一个折衷呢?即,算法的训练过程比较快,而且也要保证最终参数训练的准确率,而这正是小批量梯度下降法(Mini-batch Gradient Descent,简称MBGD)的初衷。

它的主要想法就是取一小批量的样本,然后计算梯度的平均值,这样既能减小梯度的方差,更新参数的速度也不会那么慢。

在训练的时候,也不需要把所有的训练样本都读取到内存中。
而每一批取多少,就是一个超参数的选择了,这应该怎么选呢?

给两个建议:
1. 一般选择32左右。如果不行,可以在10到一百中选择,可以自己设一个跨度试一下。
2. 用不同的批次,看一下验证误差和训练时间的学习曲线。

小批量梯度下降python代码实现

def mbgd(alpha, x, y, numIterations,minibatches):    m = x.shape[0]    theta = np.ones(2)    for j in range(numIterations):        idx = np.random.permutation(y.shape[0])        x, y = x[idx], y[idx]        mini = np.array_split(range(y.shape[0]), minibatches)        for i in mini:            mb_hypothesis = np.dot(x[i],theta)            mb_loss = y[i] - mb_hypothesis            gradient = np.dot(x[i].transpose(), mb_loss)/minibatches            theta += alpha*gradient    return theta

参考
A Gentle Introduction to Mini-Batch Gradient Descent and How to Configure Batch Size

ML之梯度下降算法
详解梯度下降法的三种形式BGD、SGD以及MBGD
最优化学习笔记(四)——最速下降法
梯度下降法和最速下降法的细微差别
最优化理论与方法-袁亚湘
最优化选讲-董云达(郑州大学出版社)