梯度下降法及其Python实现

梯度下降法(gradient descent),又名最速下降法(steepest descent)是求解无约束最优化问题最常用的方法,它是一种迭代方法,每一步主要的操作是求解目标函数的梯度向量,将当前位置的负梯度方向作为搜索方向(因为在该方向上目标函数下降最快,这也是最速下降法名称的由来)。

梯度下降法特点:越接近目标值,步长越小,下降速度越慢。

直观上来看如下图所示:

这里每一个圈代表一个函数梯度,最中心表示函数极值点,每次迭代根据当前位置求得的梯度(用于确定搜索方向以及与步长共同决定前进速度)和步长找到一个新的位置,这样不断迭代最终到达目标函数局部最优点(如果目标函数是凸函数,则到达全局最优点)。

下面我们将通过公式来具体说明梯度下降法

下面这个h(θ)是我们的拟合函数

也可以用向量的形式进行表示:

下面函数是我们需要进行最优化的风险函数,其中的每一项都表示在已有的训练集上我们的拟合函数与y之间的残差,计算其平方损失函数作为我们构建的风险函数(参见最小二乘法及其Python实现)

这里我们乘上1/2是为了方便后面求偏导数时结果更加简洁,之所以能乘上1/2是因为乘上这个系数后对求解风险函数最优值没有影响。

我们的目标就是要最小化风险函数,使得我们的拟合函数能够最大程度的对目标函数y进行拟合,即:

后面的具体梯度求解都是围绕这个目标来进行。

批量梯度下降BGD

按照传统的思想,我们需要对上述风险函数中的每个求其偏导数,得到每个对应的梯度

这里表示第i个样本点的第j分量,即h(θ)中的

接下来由于我们要最小化风险函数,故按照每个参数的负梯度方向来更新每一个

这里的α表示每一步的步长

从上面公式可以注意到,它得到的是一个全局最优解,但是每迭代一步,都要用到训练集所有的数据,如果m很大,那么可想而知这种方法的迭代速度!!所以,这就引入了另外一种方法,随机梯度下降。

随机梯度下降SGD

因为批量梯度下降在训练集很大的情况下迭代速度非常之慢,所以在这种情况下再使用批量梯度下降来求解风险函数的最优化问题是不具有可行性的,在此情况下,提出了——随机梯度下降

我们将上述的风险函数改写成以下形式:

其中,

称为样本点的损失函数

接下来我们对每个样本的损失函数,对每个求其偏导数,得到每个对应的梯度

然后根据每个参数的负梯度方向来更新每一个

与批量梯度下降相比,随机梯度下降每次迭代只用到了一个样本,在样本量很大的情况下,常见的情况是只用到了其中一部分样本数据即可将θ迭代到最优解。因此随机梯度下降比批量梯度下降在计算量上会大大减少。

SGD有一个缺点是,其噪音较BGD要多,使得SGD并不是每次迭代都向着整体最优化方向。而且SGD因为每次都是使用一个样本进行迭代,因此最终求得的最优解往往不是全局最优解,而只是局部最优解。但是大的整体的方向是向全局最优解的,最终的结果往往是在全局最优解附近。

下面是两种方法的图形展示:

从上述图形可以看出,SGD因为每次都是用一个样本点进行梯度搜索,因此其最优化路径看上去比较盲目(这也是随机梯度下降名字的由来)。

对比其优劣点如下:

批量梯度下降:

优点:全局最优解;易于并行实现;总体迭代次数不多

缺点:当样本数目很多时,训练过程会很慢,每次迭代需要耗费大量的时间。

随机梯度下降:

优点:训练速度快,每次迭代计算量不大

缺点:准确度下降,并不是全局最优;不易于并行实现;总体迭代次数比较多。

============ 分割分割 =============

上面我们讲解了什么是梯度下降法,以及如何求解梯度下降,下面我们将通过Python来实现梯度下降法。

# _*_ coding: utf-8 _*_
# 作者: yhao
# 博客: http://blog.csdn.net/yhao2014
# 邮箱: [email protected]

# 训练集
# 每个样本点有3个分量 (x0,x1,x2)
x = [(1, 0., 3), (1, 1., 3), (1, 2., 3), (1, 3., 2), (1, 4., 4)]
# y[i] 样本点对应的输出
y = [95.364, 97.217205, 75.195834, 60.105519, 49.342380]

# 迭代阀值,当两次迭代损失函数之差小于该阀值时停止迭代
epsilon = 0.0001

# 学习率
alpha = 0.01
diff = [0, 0]
max_itor = 1000
error1 = 0
error0 = 0
cnt = 0
m = len(x)

# 初始化参数
theta0 = 0
theta1 = 0
theta2 = 0

while True:
    cnt += 1

    # 参数迭代计算
    for i in range(m):
        # 拟合函数为 y = theta0 * x[0] + theta1 * x[1] +theta2 * x[2]
        # 计算残差
        diff[0] = (theta0 + theta1 * x[i][1] + theta2 * x[i][2]) - y[i]

        # 梯度 = diff[0] * x[i][j]
        theta0 -= alpha * diff[0] * x[i][0]
        theta1 -= alpha * diff[0] * x[i][1]
        theta2 -= alpha * diff[0] * x[i][2]

    # 计算损失函数
    error1 = 0
    for lp in range(len(x)):
        error1 += (y[i]-(theta0 + theta1 * x[i][1] + theta2 * x[i][2]))**2/2

    if abs(error1-error0) < epsilon:
        break
    else:
        error0 = error1

    print ' theta0 : %f, theta1 : %f, theta2 : %f, error1 : %f' % (theta0, theta1, theta2, error1)
print 'Done: theta0 : %f, theta1 : %f, theta2 : %f' % (theta0, theta1, theta2)
print '迭代次数: %d' % cnt

结果(截取部分):

 theta0 : 2.782632, theta1 : 3.207850, theta2 : 7.998823, error1 : 7.508687
 theta0 : 4.254302, theta1 : 3.809652, theta2 : 11.972218, error1 : 813.550287
 theta0 : 5.154766, theta1 : 3.351648, theta2 : 14.188535, error1 : 1686.507256
 theta0 : 5.800348, theta1 : 2.489862, theta2 : 15.617995, error1 : 2086.492788
 theta0 : 6.326710, theta1 : 1.500854, theta2 : 16.676947, error1 : 2204.562407
 theta0 : 6.792409, theta1 : 0.499552, theta2 : 17.545335, error1 : 2194.779569
 theta0 : 74.892395, theta1 : -13.494257, theta2 : 8.587471, error1 : 87.700881
 theta0 : 74.942294, theta1 : -13.493667, theta2 : 8.571632, error1 : 87.372640
 theta0 : 74.992087, theta1 : -13.493079, theta2 : 8.555828, error1 : 87.045719
 theta0 : 75.041771, theta1 : -13.492491, theta2 : 8.540057, error1 : 86.720115
 theta0 : 75.091349, theta1 : -13.491905, theta2 : 8.524321, error1 : 86.395820
 theta0 : 75.140820, theta1 : -13.491320, theta2 : 8.508618, error1 : 86.072830
 theta0 : 75.190184, theta1 : -13.490736, theta2 : 8.492950, error1 : 85.751139
 theta0 : 75.239442, theta1 : -13.490154, theta2 : 8.477315, error1 : 85.430741
 theta0 : 97.986390, theta1 : -13.221172, theta2 : 1.257259, error1 : 1.553781
 theta0 : 97.986505, theta1 : -13.221170, theta2 : 1.257223, error1 : 1.553680
 theta0 : 97.986620, theta1 : -13.221169, theta2 : 1.257186, error1 : 1.553579
 theta0 : 97.986735, theta1 : -13.221167, theta2 : 1.257150, error1 : 1.553479
 theta0 : 97.986849, theta1 : -13.221166, theta2 : 1.257113, error1 : 1.553379
 theta0 : 97.986963, theta1 : -13.221165, theta2 : 1.257077, error1 : 1.553278
Done: theta0 : 97.987078, theta1 : -13.221163, theta2 : 1.257041
迭代次数: 3443

可以看到最后收敛到稳定的参数值。

注意:这里在选取alpha和epsilon时需要谨慎选择,可能不适的值会导致最后无法收敛。

参考文档:

随机梯度下降(Stochastic gradient descent)和 批量梯度下降(Batch gradient descent
)的公式对比、实现对比

随机梯度下降法
python实现梯度下降算法
时间: 2024-11-03 21:52:34

梯度下降法及其Python实现的相关文章

(转)梯度下降法及其Python实现

梯度下降法(gradient descent),又名最速下降法(steepest descent)是求解无约束最优化问题最常用的方法,它是一种迭代方法,每一步主要的操作是求解目标函数的梯度向量,将当前位置的负梯度方向作为搜索方向(因为在该方向上目标函数下降最快,这也是最速下降法名称的由来).梯度下降法特点:越接近目标值,步长越小,下降速度越慢.直观上来看如下图所示: 这里每一个圈代表一个函数梯度,最中心表示函数极值点,每次迭代根据当前位置求得的梯度(用于确定搜索方向以及与步长共同决定前进速度)和

Python实现简单的梯度下降法

Python 实现简单的梯度下降法 机器学习算法常常可以归结为求解一个最优化问题,而梯度下降法就是求解最优化问题的一个方法. 梯度下降法(gradient descent)或最速下降法(steepest decent),是求解无约束最优化问题的一种最常用的方法. 梯度下降法实现简单,是一种迭代算法,每一步会求解目标函数的梯度向量. 本文分为理论和 Python 代码实践,希望实现简单的梯度下降法,相关代码已放在 GitHub 中. 理论 问题定义 那么什么是目标函数,在机器学习中这常常是一个损失

【机器学习】机器学习入门05 - 梯度下降法

1. 梯度下降法介绍 1.1 梯度 在多元函数微分学中,我们都接触过梯度(Gradient)的概念. 回顾一下,什么是梯度? 梯度的本意是一个向量(矢量),表示某一函数在该点处的方向导数沿着该方向取得最大值,即函数在该点处沿着该方向(此梯度的方向)变化最快,变化率最大(为该梯度的模). 这是百度百科给出的解释. 事实上,梯度的定义,就是多元函数的偏导数组成的向量.以二元函数 f(x,y) 为例.fx, fy 分别表示 f  对x,y的偏导数.则 f 在(x, y)处的梯度grad f = ( f

梯度下降法VS随机梯度下降法 (Python的实现)

1 # -*- coding: cp936 -*- 2 import numpy as np 3 import matplotlib.pyplot as plt 4 5 6 # 构造训练数据 7 x = np.arange(0., 10., 0.2) 8 m = len(x) # 训练数据点数目 9 x0 = np.full(m, 1.0) 10 input_data = np.vstack([x0, x]).T # 将偏置b作为权向量的第一个分量 11 target_data = 2 * x

梯度下降法

梯度下降法在凸优化中应用很广泛.经常使用于求凸函数极值. 梯度是个向量.其形式为 一般是表示函数上升最快的方向.因此.我们仅仅须要每一步往梯度方向走一小步.终于就能够到达极值点,其表现形式为: 初始点为x0. 然后往梯度的反方向移动一小步r到x1. 再次往梯度反方向移动r到x2,... ....终于会越来越接近极值点min的. 迭代时的公式为X(n+1) = X(n) - r * grad(f) 以下举样例说明梯度下降法求极值点的有效性: #!/usr/bin/python # -*- codi

重新发现梯度下降法--backtracking line search

一直以为梯度下降很简单的,结果最近发现我写的一个梯度下降特别慢,后来终于找到原因:step size的选择很关键,有一种叫backtracking line search的梯度下降法就非常高效,该算法描述见下图: 下面用一个简单的例子来展示,给一个无约束优化问题: minimize y = (x-3)*(x-3) 下面是python代码,比较两种方法 # -*- coding: cp936 -*- #optimization test, y = (x-3)^2 from matplotlib.p

解梯度下降法的三种形式BGD、SGD以及MBGD

原帖地址:https://zhuanlan.zhihu.com/p/25765735           在应用机器学习算法时,我们通常采用梯度下降法来对采用的算法进行训练.其实,常用的梯度下降法还具体包含有三种不同的形式,它们也各自有着不同的优缺点. 下面我们以线性回归算法来对三种梯度下降法进行比较. 一般线性回归函数的假设函数为: $$h_\theta=\sum_{j=0}^n\theta_jx_j$$   对应的损失函数为: $$J_{train}(\theta)=\frac1{2m}\s

20-深谋远虑与想到做到——两种梯度下降法

生活中往往有两种人:一种喜欢谋定而后动,比较有全局观:另一种见机行事,根据外界环境不断调整自己的行为.命运给他们的馈赠也是不同的,前者可能大器晚成,后者容易惊喜不断,然而可能左右摇摆.不能说两种处事态度有什么优劣:思虑过多可能错失良机,贸然行动也可能事倍功半,总之"成功"这件事一半靠命运.顾城的诗中说:命运不是风,来回吹,命运是大地,走到哪你都在命运中.而我们能做的是发挥主观能动性,从而改变条件概率(指事件A在另外一个事件B已经发生条件下的发生概率.表示为:P(A|B),读作"

对数几率回归法(梯度下降法,随机梯度下降与牛顿法)与线性判别法(LDA)

本文主要使用了对数几率回归法与线性判别法(LDA)对数据集(西瓜3.0)进行分类.其中在对数几率回归法中,求解最优权重W时,分别使用梯度下降法,随机梯度下降与牛顿法. 代码如下: 1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 # @Date : 2017-05-09 15:03:50 4 # @Author : whb ([email protected]) 5 # @Link : ${link} 6 # @Version : $Id$