0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

梯度下降是门手艺活

新机器视觉 来源:新机器视觉 2023-03-13 10:42 次阅读

导读

梯度下降法作为大家耳熟能详的优化算法,极易理解。但虽然和的一些方法比起来在寻找优化方向上比较轻松,可是这个步长却需要点技巧。本文作者通过简单的函数举例说明梯度下降中容易出现的问题。

本文收录在无痛的机器学习第一季(https://zhuanlan.zhihu.com/p/22464594)。

机器学习所涉及的内容实在是太多了,于是我决定挑个软柿子捏起,从最基础的一个优化算法开始聊起。这个算法就是梯度下降法,英文Gradient Descent。

什么是梯度下降法

作为大众耳熟能详的优化算法,梯度下降法受到的关注不要太多。梯度下降法极易理解,但凡学过一点数学的童鞋都知道,梯度方向表示了函数增长速度最快的方向,那么和它相反的方向就是函数减少速度最快的方向了。对于机器学习模型优化的问题,当我们需要求解最小值的时候,朝着梯度下降的方向走,就能找到最优值了。

那么具体来说梯度下降的算法怎么实现呢?我们先来一个最简单的梯度下降算法,最简单的梯度下降算法由两个函数,三个变量组成:

函数1:待求的函数

函数2:待求函数的导数

变量1:当前找到的变量,这个变量是“我们认为”当前找到的最好的变量,可以是函数达到最优值(这里是最小值)。

变量2:梯度,对于绝大多数的函数来说,这个就是函数的负导数。

变量3:步长,也就是沿着梯度下降方向行进的步长。也是这篇文章的主角。

我们可以用python写出一个最简单的梯度下降算法:


						
def gd(x_start, step, g):   # gd代表了Gradient Descent
    x = x_start
    for i in range(20):
        grad = g(x)
        x -= grad * step
        print '[ Epoch {0} ] grad = {1}, x = {2}'.format(i, grad, x)
        if abs(grad) < 1e-6:
            break;
    return x
关于python的语法在此不再赘述了,看不懂得童鞋自己想办法去补课吧。

优雅的步长

好了,算法搞定了,虽然有点粗糙,但是对于一些问题它是可以用的。我们用一个简单到爆的例子来尝试一下:


						
def f(x):
    return x * x - 2 * x + 1


def g(x):
    return 2 * x - 2


这个函数f(x)就是大家在中学喜闻乐见的,大家一眼就可以看出,最小值是x=1,这是函数值为0。为了防止大家对这个函数没有感觉(真不应该没感觉啊……)我们首先把图画出来看一下:


						
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-5,7,100)
y = f(x)
plt.plot(x,y)
然后我们就看到了:
f4dc5690-c141-11ed-bfe3-dac502259ad0.png

一个很简单的抛物线的函数有木有?x=1是最小点有木有?

来让我用梯度下降法计算一下:


						
gd(5,0.1,g)
于是我们得到了下面的输出:

[ Epoch 0 ] grad = 8, x = 4.2
[ Epoch 1 ] grad = 6.4, x = 3.56
[ Epoch 2 ] grad = 5.12, x = 3.048
[ Epoch 3 ] grad = 4.096, x = 2.6384
[ Epoch 4 ] grad = 3.2768, x = 2.31072
[ Epoch 5 ] grad = 2.62144, x = 2.048576
[ Epoch 6 ] grad = 2.097152, x = 1.8388608
[ Epoch 7 ] grad = 1.6777216, x = 1.67108864
[ Epoch 8 ] grad = 1.34217728, x = 1.536870912
[ Epoch 9 ] grad = 1.073741824, x = 1.4294967296
[ Epoch 10 ] grad = 0.8589934592, x = 1.34359738368
[ Epoch 11 ] grad = 0.68719476736, x = 1.27487790694
[ Epoch 12 ] grad = 0.549755813888, x = 1.21990232556
[ Epoch 13 ] grad = 0.43980465111, x = 1.17592186044
[ Epoch 14 ] grad = 0.351843720888, x = 1.14073748836
[ Epoch 15 ] grad = 0.281474976711, x = 1.11258999068
[ Epoch 16 ] grad = 0.225179981369, x = 1.09007199255
[ Epoch 17 ] grad = 0.180143985095, x = 1.07205759404
[ Epoch 18 ] grad = 0.144115188076, x = 1.05764607523
[ Epoch 19 ] grad = 0.115292150461, x = 1.04611686018

可以看到,经过20轮迭代,我们从初始值x=5不断地逼近x=1,虽然没有完全等于,但是在后面的迭代中它会不断地逼近的。

好像我们已经解决了这个问题,感觉有点轻松啊。高兴之余,突然回过神来,那个步长我设的好像有点随意啊,迭代了20轮还没有完全收敛,是不是我太保守了,设得有点小?俗话说的好,人有多大胆,地有多大产。咱们设个大点的数字,让它一步到位!(豪迈的表情)


						
gd(5,100,g)
这回设得够大了,来看看结果:

[ Epoch 0 ] grad = 8, x = -795
[ Epoch 1 ] grad = -1592, x = 158405
[ Epoch 2 ] grad = 316808, x = -31522395
[ Epoch 3 ] grad = -63044792, x = 6272956805
[ Epoch 4 ] grad = 12545913608, x = -1248318403995
[ Epoch 5 ] grad = -2496636807992, x = 248415362395205
[ Epoch 6 ] grad = 496830724790408, x = -49434657116645595
[ Epoch 7 ] grad = -98869314233291192, x = 9837496766212473605
[ Epoch 8 ] grad = 19674993532424947208, x = -1957661856476282247195
[ Epoch 9 ] grad = -3915323712952564494392, x = 389574709438780167192005
[ Epoch 10 ] grad = 779149418877560334384008, x = -77525367178317253271208795
[ Epoch 11 ] grad = -155050734356634506542417592, x = 15427548068485133400970550405
[ Epoch 12 ] grad = 30855096136970266801941100808, x = -3070082065628541546793139530395
[ Epoch 13 ] grad = -6140164131257083093586279060792, x = 610946331060079767811834766548805
[ Epoch 14 ] grad = 1221892662120159535623669533097608, x = -121578319880955873794555118543211995
[ Epoch 15 ] grad = -243156639761911747589110237086423992, x = 24194085656310218885116468590099187205
[ Epoch 16 ] grad = 48388171312620437770232937180198374408, x = -4814623045605733558138177249429738253595
[ Epoch 17 ] grad = -9629246091211467116276354498859476507192, x = 958109986075540978069497272636517912465605
[ Epoch 18 ] grad = 1916219972151081956138994545273035824931208, x = -190663887229032654635829957254667064580655195
[ Epoch 19 ] grad = -381327774458065309271659914509334129161310392, x = 37942113558577498272530161493678745851550384005

我去,这是什么结果!不但没有收敛,反而数字越来越大!这是要把python的数字撑爆的节奏啊!(实际上python的数字没这么容易撑爆的……)

需要冷静一下……为什么会出现这样的情况?不是说好了是梯度下降么?怎么还会升上去?这个问题就要回到梯度这个概念本身来。

实际上梯度指的是在当前变量处的梯度,对于这一点来说,它的梯度方向是这个方向,我们也可以利用泰勒公式证明在一定的范围内,沿着这个梯度方向走函数值是会下降的。但是,从函数中也可以看出,如果一步迈得太大,会跳出函数值下降的范围,反而会使函数值越变越大,造成悲剧。

如何避免这种悲剧发生呢?简单的方法就是将步长减少,像我们前面那样设得小点。另外,还有一些Line-search的方法可以避免这样的事情发生,这些方法以后有机会在慢慢聊。

现在,我们要镇定一下,看样子我们只能通过修改步长来完成这个问题了。这时候我们可以开一个脑洞:既然小步长会让优化问题收敛,大步长会让优化问题发散,那么有没有一个步长会让优化问题原地打转呢?

我们还是从x=5出发,假设经过一轮迭代,我们求出了另一个x值,再用这个值迭代,x值又回到了5。我们用中学的数学能力建一个方程出来:

x=5, g(x)=8, 新的值x'=5 - 8 * step
g(x')=2 * (5-8*step) - 2,回到过去:x' - g(x') * step = x = 5
合并公式求解得,step=1

也就是说step=1时,求解会原地打转,赶紧试一下:


						
gd(5,1,g)

[ Epoch 0 ] grad = 8, x = -3
[ Epoch 1 ] grad = -8, x = 5
[ Epoch 2 ] grad = 8, x = -3
[ Epoch 3 ] grad = -8, x = 5
[ Epoch 4 ] grad = 8, x = -3
[ Epoch 5 ] grad = -8, x = 5
[ Epoch 6 ] grad = 8, x = -3
[ Epoch 7 ] grad = -8, x = 5
[ Epoch 8 ] grad = 8, x = -3
[ Epoch 9 ] grad = -8, x = 5
[ Epoch 10 ] grad = 8, x = -3
[ Epoch 11 ] grad = -8, x = 5
[ Epoch 12 ] grad = 8, x = -3
[ Epoch 13 ] grad = -8, x = 5
[ Epoch 14 ] grad = 8, x = -3
[ Epoch 15 ] grad = -8, x = 5
[ Epoch 16 ] grad = 8, x = -3
[ Epoch 17 ] grad = -8, x = 5
[ Epoch 18 ] grad = 8, x = -3
[ Epoch 19 ] grad = -8, x = 5

果然不出我们所料,打转了……

好了,现在我们基本明白了,当步长大于1会出现求解发散,而小于1则不会,那么对于别的初始值,这个规则适用么?


						
gd(4,1,g)

[ Epoch 0 ] grad = 6, x = -2
[ Epoch 1 ] grad = -6, x = 4
[ Epoch 2 ] grad = 6, x = -2
[ Epoch 3 ] grad = -6, x = 4
[ Epoch 4 ] grad = 6, x = -2
[ Epoch 5 ] grad = -6, x = 4
[ Epoch 6 ] grad = 6, x = -2
[ Epoch 7 ] grad = -6, x = 4
[ Epoch 8 ] grad = 6, x = -2
[ Epoch 9 ] grad = -6, x = 4
[ Epoch 10 ] grad = 6, x = -2
[ Epoch 11 ] grad = -6, x = 4
[ Epoch 12 ] grad = 6, x = -2
[ Epoch 13 ] grad = -6, x = 4
[ Epoch 14 ] grad = 6, x = -2
[ Epoch 15 ] grad = -6, x = 4
[ Epoch 16 ] grad = 6, x = -2
[ Epoch 17 ] grad = -6, x = 4
[ Epoch 18 ] grad = 6, x = -2
[ Epoch 19 ] grad = -6, x = 4

果然试用,这样一来,我们可以“认为”,对于这个优化问题,采用梯度下降法,对于固定步长的算法,步长不能超过1,不然问题会发散!

好了,下面我们换一个函数:,对于这个问题,它的安全阈值是多少呢?不罗嗦了,是0.25:


						
def f2(x):
    return 4 * x * x - 4 * x + 1
def g2(x):
    return 8 * x - 4
gd(5,0.25,g2)

[ Epoch 0 ] grad = 36, x = -4.0
[ Epoch 1 ] grad = -36.0, x = 5.0
[ Epoch 2 ] grad = 36.0, x = -4.0
[ Epoch 3 ] grad = -36.0, x = 5.0
[ Epoch 4 ] grad = 36.0, x = -4.0
[ Epoch 5 ] grad = -36.0, x = 5.0
[ Epoch 6 ] grad = 36.0, x = -4.0
[ Epoch 7 ] grad = -36.0, x = 5.0
[ Epoch 8 ] grad = 36.0, x = -4.0
[ Epoch 9 ] grad = -36.0, x = 5.0
[ Epoch 10 ] grad = 36.0, x = -4.0
[ Epoch 11 ] grad = -36.0, x = 5.0
[ Epoch 12 ] grad = 36.0, x = -4.0
[ Epoch 13 ] grad = -36.0, x = 5.0
[ Epoch 14 ] grad = 36.0, x = -4.0
[ Epoch 15 ] grad = -36.0, x = 5.0
[ Epoch 16 ] grad = 36.0, x = -4.0
[ Epoch 17 ] grad = -36.0, x = 5.0
[ Epoch 18 ] grad = 36.0, x = -4.0
[ Epoch 19 ] grad = -36.0, x = 5.0

好了,这个故事讲完了。为什么要讲这个故事呢?

这个故事说明了梯度下降法简单中的不简单(划重点啊),虽然和的一些方法比起来在寻找优化方向上比较轻松,可是这个步长真心需要点技巧,即使这样一个一维的优化问题都有这些问题,对于现在大火的深度学习,CNN优化(没错,说得就是你),一个base_lr基础学习率+gamma学习衰减率真的可以轻松跳过像上面这样的坑么?说实话还是需要一定的尝试才能找到感觉。

最后多说一句,对于上面的一元二次函数,有没有发现步长阈值和二阶导数的关系呢?

审核编辑 :李倩


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 函数
    +关注

    关注

    3

    文章

    3882

    浏览量

    61310
  • 梯度
    +关注

    关注

    0

    文章

    30

    浏览量

    10259
  • 机器学习
    +关注

    关注

    66

    文章

    8126

    浏览量

    130570

原文标题:梯度下降是门手艺活

文章出处:【微信号:vision263com,微信公众号:新机器视觉】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    分享一个自己写的机器学习线性回归梯度下降算法

    单变量线性回归算法,利用Batch梯度梯度下降算法迭代计算得到误差最小的代价函数theta0,theta1。调节学习率a可以观察拟合得到的函数和代价函数误差收敛情况。
    发表于 10-02 21:48

    机器学习新手必学的三种优化算法(牛顿法、梯度下降法、最速下降法)

    法、梯度下降法、最速下降法)进行了介绍和比较,并结合算法的数学原理和实际案例给出了优化算法选择的一些建议。阅读本文的基础准备线性代数多变量微积分对凸函数的基本知识我们都知道,机器学习中最重要的内容之一
    发表于 05-07 08:30

    如何更新权重实现梯度下降

    实现梯度下降
    发表于 07-15 10:09

    梯度下降法、牛顿法到拟牛顿法它们的联系与区别是什么

    梯度下降法、牛顿法到拟牛顿法,浅谈它们的联系与区别
    发表于 05-21 11:06

    机器学习:随机梯度下降和批量梯度下降算法介绍

    随机梯度下降(Stochastic gradient descent) 批量梯度下降(Batch gradient descent) 梯度
    发表于 11-28 04:00 8301次阅读
    机器学习:随机<b class='flag-5'>梯度</b><b class='flag-5'>下降</b>和批量<b class='flag-5'>梯度</b><b class='flag-5'>下降</b>算法介绍

    一文看懂常用的梯度下降算法

    编辑:祝鑫泉 一 概述 梯度下降算法( Gradient Descent Optimization )是神经网络模型训练最常用的优化算法。对于深度学习模型,基本都是采用梯度下降算法来进
    发表于 12-04 18:17 1549次阅读

    机器学习中梯度下降法的过程

    梯度下降法是一个用于寻找最小化成本函数的参数值的最优化算法。当我们无法通过分析计算(比如线性代数运算)求得函数的最优解时,我们可以利用梯度下降法来求解该问题。
    发表于 04-26 16:44 3272次阅读

    梯度下降算法及其变种:批量梯度下降,小批量梯度下降和随机梯度下降

    现在我们来讨论梯度下降算法的三个变种,它们之间的主要区别在于每个学习步骤中计算梯度时使用的数据量,是对每个参数更新(学习步骤)时的梯度准确性与时间复杂度的折衷考虑。
    的头像 发表于 05-03 15:55 2w次阅读

    机器学习优化算法中梯度下降,牛顿法和拟牛顿法的优缺点详细介绍

    梯度下降法实现简单,当目标函数是凸函数时,梯度下降法的解是全局解。一般情况下,其解不保证是全局最优解,梯度
    的头像 发表于 08-04 11:40 5.1w次阅读

    简单的梯度下降算法,你真的懂了吗?

    梯度下降算法的公式非常简单,”沿着梯度的反方向(坡度最陡)“是我们日常经验得到的,其本质的原因到底是什么呢?为什么局部下降最快的方向就是梯度
    发表于 09-19 00:17 690次阅读

    各种梯度下降法是如何工作的

    导读一图胜千言,什么?还是动画,那就更棒啦!本文用了大量的资源来解释各种梯度下降法(gradient descents),想给大家直观地介绍一下这些方法是如何工作的。
    的头像 发表于 08-17 11:50 828次阅读

    梯度下降法在机器学习中的应用

    梯度下降法沿着梯度的反方向进行搜索,利用了函数的一阶导数信息。
    的头像 发表于 05-18 09:20 866次阅读
    <b class='flag-5'>梯度</b><b class='flag-5'>下降</b>法在机器学习中的应用

    PyTorch教程12.4之随机梯度下降

    电子发烧友网站提供《PyTorch教程12.4之随机梯度下降.pdf》资料免费下载
    发表于 06-05 14:58 0次下载
    PyTorch教程12.4之随机<b class='flag-5'>梯度</b><b class='flag-5'>下降</b>

    PyTorch教程12.5之小批量随机梯度下降

    电子发烧友网站提供《PyTorch教程12.5之小批量随机梯度下降.pdf》资料免费下载
    发表于 06-05 15:00 0次下载
    PyTorch教程12.5之小批量随机<b class='flag-5'>梯度</b><b class='flag-5'>下降</b>

    PyTorch教程-12.4。随机梯度下降

    12.4。随机梯度下降¶ Colab [火炬]在 Colab 中打开笔记本 Colab [mxnet] Open the notebook in Colab Colab [jax
    的头像 发表于 06-05 15:44 264次阅读
    PyTorch教程-12.4。随机<b class='flag-5'>梯度</b><b class='flag-5'>下降</b>