李宏毅 机器学习 2016 秋:3、Gradient Descent

2023-11-14

三、Gradient Descent

今天我们要讲的是 Gradient Descent,Gradient Descent 我们上次已经大概讲过怎么做了,但是有一些小技巧呢,你可能是不知道的,所以我们要再详细说明一下,Gradient Descent 你要怎么把它做得更好,那我们上次是这样说的,在整个 machine learning 的第 3 个步骤,我们要找一个最好的 function,那找一个最好的 function 这件事呢,是要解一个 optimization 的 problem,也就是说,在第二步我们先定了一个 loss function: L L L,这个 loss function 呢,它是一个 functional unction,你把一个 function 代到这个 loss function 里面,或者是你把一个操控 function 形状的参数。

我们现在,在这张投影片里面,把那些参数写成 θ \theta θ L L L 是 loss function, θ \theta θ 是那些参数,你把一组参数代到一个 loss function 里面,它就会告诉你说,这组参数有多不好,那你接下来,要做的事情呢,就是我们要找一组参数 θ \theta θ,让这个 loss function 越小越好,那这件事情怎么做呢?

我们可以用 Gradient Descent,假设现在这个 θ \theta θ 是一个参数的 set,那里面有两个参数: θ 1 \theta_1 θ1 θ 2 \theta_2 θ2,首先,你先随机的选取一个起始的点,随机选取一组起始的参数,这边写成 θ 1 1 \theta^1_1 θ11 θ 2 0 \theta^0_2 θ20,上标 0 来代表说,它是初始的那一组参数,那用下标代表说,这个是这一组参数里面的 第 1 个 component 跟第 2 个 component,接下来,你计算 θ 1 0 \theta^0_1 θ10 θ 2 0 \theta^0_2 θ20,对这个 loss function 的偏微分,计算他们的偏微分,然后把这个 θ 1 0 \theta^0_1 θ10 θ 2 0 \theta^0_2 θ20 减掉 learning rate,乘上这个偏微分的值,得到一组新的参数,这个参数,这边写做 θ 1 1 \theta^1_1 θ11 θ 2 1 \theta^1_2 θ21 θ 1 \theta^1 θ1 代表说它是在第二个时间点,由 θ 0 \theta^0 θ0 update 以后得到的参数,下标代表说,它有两个 component,那同样的步骤,你就反复不断地进行,接下来你有 θ 1 1 \theta^1_1 θ11 θ 2 1 \theta^1_2 θ21 以后呢,你就一样去计算它们的偏微分,再乘上 learning rate,再去减 θ 1 1 \theta^1_1 θ11 θ 2 1 \theta^1_2 θ21 ,得到下一组参数,每个反复进行这个 process,这个就是 Gradient Descent。

那如果你想要更简洁一点的话呢,其实你可以这样写,假设你现在有两个参数: θ 1 \theta_1 θ1 θ 2 \theta_2 θ2,你把这个 θ 1 \theta_1 θ1 θ 2 \theta_2 θ2 对这个 loss function 做偏微分,你把这两个偏微分得到的值串在一起, 变成一个 vector 以后,那这个 vector 呢,就叫做 Gradient,你把 L L L 前面,加一个倒三角形,这个东西呢,就叫做 Gradient,那它其实是一个 vector。所以你可以把 update 参数呢,简单写成 θ 0 \theta^0 θ0 减掉 learning rate,乘上 Gradient,就等于 θ 1 \theta^1 θ1,同理, θ 1 \theta^1 θ1 减掉 learning rate 乘上 Gradient 就得到 θ 2 \theta^2 θ2

如果把它 visualize 的话呢,它看起来像是这个样子,假设我们现在有两个参数, θ 1 \theta_1 θ1 θ 2 \theta_2 θ2,那你随机的选一个初始的位置, θ 0 \theta^0 θ0,然后接下来呢,你计算在 θ 0 \theta^0 θ0 这个点,这个参数对 loss function 的 Gradient,假设参数对 loss function 的 Gradient 是这个红色的箭头,Gradient 就是一个 vector,它是一个红色的箭头,那如果你不知道 Gradient 是什么的话呢,你就想成它是等高线的法线方向,这个箭头它指的方向就是,如果你把 loss 的等高线画出来的话呢,这个箭头指的方向,就是等高线的法线方向,那怎么 update 参数呢?

你就把这个 Gradient 乘上 learning rate,然后再取一个负号,就是这个蓝色的箭头,再把它加上 θ 0 \theta^0 θ0 ,就得到 θ 1 \theta^1 θ1,那这个步骤就反复地持续进行下去,再计算一遍 Gradient,你得到另外一个红色的箭头,红色箭头指向这个地方,那你现在走的方向呢,就变成是红色的箭头的相反,红色箭头乘上一个负号,再乘上 learning rate,就是现在这个蓝色的箭头 ,得到 θ 2 \theta^2 θ2,这个步骤就反复一直进行下去,再算一下在 θ 2 \theta^2 θ2 这个地方的 Gradient,然后再决定要走的方向,再算一次 Gradient,再决定要走的方向,这个就是 Gradient Descent,这些,我们上次其实都讲过了。

3.1 Tuning your learning rates

接下来呢,要讲一些 Gradient Descent 的 tip,首先,第一件事情就是,你要小心地调你的 learning rate,有时候,learning rate 是可以给你造成一些问题的,举例来说,假设这个是我们的 loss function 的 surface, 假设长这样子,如果你今天 learning rate 调刚刚好的话,你从左边这边开始,那你可能就是顺著红色的箭头,很顺利地走到了最低点,可是,如果你今天 learning rate 调的太小的话,那它走的速度呢,会变得非常慢,虽然只要给它够多的时间,它终究会 走到这个 local minimum 的地方,但是如果它走得太慢的话呢,你会没有办法接受这件事情,如果你今天这个 learning rate 调得稍微大一点,比如说,像绿色这个箭头的话,那就变成说,它的步伐太大了,它变得像一个巨人一样,步伐太大了,它永远没有办法走到这个特别低的地方,它都在这个山谷的口上面震荡,它永远走不下去,那甚至如果你今天真的把 learning rate 调太大的话,它可能就,一瞬间就飞出去了,结果你 update 参数以后,loss 反而越 update 越大,那其实只有在你的参数是一维或二维的时候,你才能够把这样子的图 visualize 出来,如果你今天是有很多维参数,这个 error 的 surface,在这个高维的空间里面,你是没有办法 visualize 它的,但是,有另外一个东西,你是可以 visualize 的,什么东西呢?

你可以 visualize 参数的变化对这个 loss 的变化,你可以 visualize 每次参数 update 的时候,loss 的改变的情形,所以,今天如果你 learning rate 设得太小的话,你就会发现说,这个 loss 它下降地非常非常慢,今天如果你 learning rate 调得太大的话,你在左边这个图会看到说 loss 先快速地下降,接下来呢,它就卡住了,所以,如果你 learning rate 调得太大的话,你把参数的 update 对 loss 的变化, 做出来会看到的是绿色这条线,你的 loss 很快地下降,但很快地卡住了, 很快地不再下降,那如果你今天 learning rate 是调得太大,你就会发现,你的 loss 就飞出去了,你需要调整它,让它调到刚刚好,那你才能够得到一个好的结果,所以你在做 Gradient Descent 的时候,你应该要把这个图画出来,没有把这个图画出来,你就会非常非常地卡,有人就说,它就把 Gradient 的程式写好,那写好放下去之后开始跑,他去打一场 LOL,然后,打完回来就发现说:结果烂掉啦,然后,他也不知道烂在哪里这样子,所以如果你在做 Gradient Descent 的时候,你应该把这个图画出来,然后你要先看一下,它前几次 update 参数的时候,它 update 的走法是怎么样,搞不好它,你 learning rate 调太大,它一下子就爆炸了,所以这个时候,你就知道你要赶快调 learning rate,你要确定它呢,是稳定地下降,才能去打 LOL 这样子,好,但是要调 learning rate 很麻烦,有没有办法自动地调 learning rate 呢?

有一些自动的方法可以帮我们调 learning rate,最基本而简单的大原则是,通常 learning rate 是随着参数的 update 会越来越小的,为什么会这样呢?因为当你在刚开始的起始点的时候,它通常离最低点,是比较远的,所以你步伐呢,要踏大一点,就是走得快一点,才能够赶快走到最低点,但是,经过好几次的参数 update 以后呢,你已经比较靠近你的目标了,所以这个时候呢,你就应该减少你的 learning rate,这样它能够收敛在你最低点的地方,举例来说,你 learning rate 的设法可能是这样,好,你可以设成说,这个 learning rate 是一个 t t t dependent 的函数,它是 depend on 你现在参数 update 的次数,在第 t t t 次 update 参数的时候,你就把你的 learning rate 设成一个 constant η / t + 1 \eta / \sqrt{t+1} η/t+1 ,这样当你参数 update 的次数越多的时候呢,这个 learning rate 就会越来越小,但是光这样呢,是不够的,你到这边,我们需要因材施教,所以这每一个不同的参数,最好的状况应该是,每一个不同的参数,都给它不同的 learning rate,这件事情呢,是有很多的小技巧的,其中,我觉得最简单,最容易实作的,叫做 Adagrad。

那 Adagrad 是这样子的,他说,每一个参数的 learning rate 呢,都把它除上之前算出来的微分值的 root mean square,什么意思呢,我们原来的 Gradient Descent 是这样,假设 w w w 是某一个参数,这个时候 w w w 不是一组参数,我们现在只考虑一个参数,因为我们现在在做 Adagrad 这个做法的时候,它是 adaptive 的 learning rate,所以,每一个参数,它都有不同的 learning rate,所以呢,我们现在要把每一个参数都分开来考虑,那 w w w 呢,是某一个参数,那 w w w 的 learning rate 在一般的 Gradient Descent 呢,depend on 时间的值,比如说 η t \eta^t ηt,但是你可以把这件事情做的更好,在 Adagrad 里面呢, 你把这个 η t / σ t \eta^t / \sigma^t ηt/σt,这个 σ t \sigma^t σt 是什么呢? 这个 σ t \sigma^t σt 是过去,这边这个 g g g 呢,是这个偏微分的值,这个 σ t \sigma^t σt 是过去所有微分的值的 root mean square,这个值,对每一个参数而言,都是不一样的,所以现在就会变成说,不同的参数,它的 learning rate 都是不一样的,那我们实际举个例子,来看看这件事情是怎么实作的。

假设你现在初始的值,是 w 0 w^0 w0,接下来呢,你就计算在 w 0 w^0 w0 那点的微分,这边呢,写作 g 0 g^0 g0,然后,它的 learning rate 是多少呢?它的 learning rate 是 η 0 / σ 0 \eta^0 / \sigma^0 η0/σ0 η 0 \eta^0 η0 是一个时间 dependent 的参数 ,那 σ 0 \sigma^0 σ0 是什么呢? σ 0 \sigma^0 σ0 是一个参数 dependent 的参数, σ 0 \sigma^0 σ0 它是过去算过所有微分值的 root mean square,那在这个 case 里面,我们过去只算过 一个微分值,就是 g 0 g^0 g0,所以这个 σ 0 \sigma^0 σ0,就是 g 0 g^0 g0 的平方再开根号,那接下来呢,你再 update 参数,你把这个 w 0 w^0 w0 更新变成 w 1 w^1 w1,在 w 1 w^1 w1 这个地方,你再算一次 Gradient,就是 g 1 g^1 g1,那 g 1 g^1 g1 的 learning rate 应该乘上多少呢?它要乘 η 1 / σ 1 \eta^1 / \sigma^1 η1/σ1,那 σ 1 \sigma^1 σ1,它是过去所有微分值的 root mean square,过去我们已经算过两次微分值,一次是 g 0 g^0 g0,一次是 g 1 g^1 g1,所以 σ 1 \sigma^1 σ1,就变成 g 0 g^0 g0 g 1 g^1 g1 的 root mean square,也就是把 g 0 g^0 g0 平方再加 g 1 g^1 g1 平方, 再取平均值 ,再开根号,那 w 3 w^3 w3 一样,你就是 update 参数就得到 w 2 w^2 w2,你有了 w 2 w^2 w2 以后,你可以算 g 2 g^2 g2,在 w 2 w^2 w2 地方的微分值就是 g 2 g^2 g2,它的 learning rate 就是 η 2 / σ 2 \eta^2 / \sigma^2 η2/σ2,那这个 σ 2 \sigma^2 σ2 呢,就是过去算出来所有微分值的 root mean square,过去算出 g 0 , g 1 , g 2 g^0, g^1, g^2 g0,g1,g2,你就把 g 0 , g 1 , g 2 g^0, g^1, g^2 g0,g1,g2 都平方,再平均,然后再开根号,得到 σ 2 \sigma^2 σ2,然后把它放在这边,搭配参数得到 w 3 w^3 w3,这个步骤呢,就反复地一直继续下去,到第 t t t 次 update 参数的时候,你有一个微分直 g t g^t gt,那这个 g t g^t gt 的 learning rate 就是 η t / σ t \eta^t / \sigma^t ηt/σt,这个 σ t \sigma^t σt,是过去所有微分的值的 root mean square,过去已经算出 g 0 , g 1 , g 2 , ⋯ g t g^0, g^1, g^2, \cdots g^t g0,g1,g2,gt,你就把 g 0 , g 1 , g 2 , ⋯   , g t g^0, g^1, g^2, \cdots, g^t g0,g1,g2,,gt,都取平方,再加起来,再平均,再开根号,得到 σ t \sigma^t σt,就把它放在这边,所以,现在如果我们用 Adagrad 的时候呢,它 update 参数的式子,写成这样子。

那这个 time dependent 的 learning rate 呢?这个 time dependent 的 learning rate, 你可以写成 η / t + 1 \eta / \sqrt{t+1} η/t+1 ,那你可以发现说,当你把这一项除以这一项的时候,因为他们都有: t + 1 \sqrt{t+1} t+1 ,所以 t + 1 \sqrt{t+1} t+1 是可以删掉的,所以整个 Adagrad 的 learning rate,你就可以写成,一个 constant η \eta η,除掉 根号(过去所有 gradient 的平方和),但不用算平均这样,因为平均这件事情,会跟上面 time dependent 的 learning rate 抵销掉,所以你在写 Adagrad 的式子的时候,你可以简化成,不需要把 time dependent 的这件事情 explicitly 的写出来,你就直接把你的 learning rate 写成, η \eta η 除以根号(过去算出来的 gradient 的平方),再开根号就好,这个方法,你可以接受吗?

讲到这边,大家有问题吗?来,请说,”Q:在做 Adagrad 的时候,它在后面下降的速度很慢,就是看的过 1000 笔资料,才降不到 0.1,这是正常的吗?”,这其实是正常的,就是说 Adagrad 它的参数 update,其实整体而言是会是越来越慢的,因为它有加上 time depend,如果你不喜欢这个结果的话,有很多比这个更强的方法,这个 adaptive 的 learning rate 其实是一系列的方法,今天讲 Adagrad 其实是里面最简单的,还有很多其他的,他们都是用 Ada- 开头这样子,比如说 Adadelta, Adam 什么之类的,所以,如果你用别的方法,比如说,Adam 的话,它就比较不会有这个情形这样子,其实,如果你没有什么特别偏好的话,你现在可以用 Adam 啦,它应该是现在我觉得最稳定的,但是它 implement 比较复杂就是了,但其实也没有什么啦,好,讲到这边大家有什么问题吗?

那我其实有一个问题啦,我们在做一般的 Gradient Descent 的时候,我们这个参数的 update 取决于两件事情,一件事情是 learning rate,另外一件事情是 Gradient,我们的意思就是说 Gradient 越大,你参数 update 就越快,斜率算出来越大,参数 update 就越快,我相信你可以接受这件事情,但是在 Adagrad 里面,你不觉得相当矛盾吗?红色这一项告诉我们,微分的值越大,你参数 update 越快,但是蓝色这一项它是相反的,对不对?也就是说,今天当你的 Gradient 越大的时候,你底下算出来的这项就越大,你的参数 update 的步伐就越小,这不就跟我们原来要做的事情是有所冲突的吗?在分子的地方告诉我们说,Gradient 越大,踏的步伐越大 ,参数就 update 的越大,但是分母的地方却说,如果 Gradient 越大,参数 update 的越小这样,好,怎么解释这件事情呢?

有一些 paper 这样解释的,这个 Adagrad 它想要考虑的是: 今天这个 Gradient 有多 surprise,也就是所谓的"反差"这样,反差,大家知道吗?反差萌的意思就是说,如果本来一个很凶恶的角色,突然对你很温柔,你就会觉得它特别温柔这样,所以呢,对 Gradient 来说,也是一样的道理,假设有某一个参数 ,它在第一次 update 参数的时候,它算出来的 Gradient 是 0.001,再来又算 0.001, 0.003, 等等…等等,到某一次呢,它 Gradient 算出来是 0.1,你就会觉得特别大,因为它比之前算出来的 Gradient 都大了 100 倍,特别大,但是,如果是有另外一个参数,它一开始算出来是 10.8, 再来算 20.9, 再来算 31.7,它的 Gradient 平常都很大,但是它在某一次算出来的 Gradient 是 0.1,这时候你就会觉得它特别小这样子,所以为了强调这种反差的效果,在 Adagrad 里面呢,我们就把它除以这项,这项就是把过去这些 Gradient 的平方,把它算出来,我们就想要知道说过去 Gradient 有多大,然后再把它们相除,看这个反差有多大这样,这个是直观的解释。

那更正式的解释呢,我有这样的解释,我们来考虑一个二次函数,这个二次函数呢,我们就写成这样子,他只有一个参数,就是 x x x,如果我们把这个二次函数,对 x x x 做微分的话,把 y y y x x x 做微分,这是 2 a x + b 2ax + b 2ax+b,如果它绝对值算出来的话,长这样子,好,那这个二次函数的最低点在哪里呢?是 − ( b / 2 a ) -(b/2a) (b/2a),如果你今天呢,在这个二次函数上你随机的选一个点开始 ,你要做 Gradient Descent,那你的步伐多大,踏出去是最好的?假设这个起始的点是 x 0 x_0 x0,最低点是 − ( b / 2 a ) -(b/2a) (b/2a),那踏出去一步,最好的步伐其实这两个点之间的距离,因为如果你踏出去的步伐,是这两个点之间的距离的话,你就一步到位了,这两个点之间的距离是什么呢?这两个点之间的距离你整理一下,它是 ∣ 2 a x 0 + b ∣ / 2 a |2a x_0 + b| / 2a 2ax0+b/2a ∣ 2 a x 0 + b ∣ |2a x_0 + b| 2ax0+b 这一项, 2 a x 0 + b 2a x_0 + b 2ax0+b 就是 x 0 x_0 x0 这一点的微分, x 0 x_0 x0 这一点的一次微分,所以 Gradient Descent 你不觉得说听起来很有道理,就是说,如果我今天算出来的微分越大,我就离原点越远,如果踏出去的(我最好的)步伐,是跟微分的大小成正比,如果踏出去的步伐跟微分的大小成正比,它可能是最好的步伐,但是,这件事情只有在,只考虑一个参数的时候才成立,如果我们今天呢,同时有好几个参数,我们要同时考虑好几个参数的时候,这个时候呢,刚才的论述就不见得成立了,也就是说,Gradient 的值越大就跟最低点的距离越远,这件事情,在有好多个参数的时候 ,是不一定成立的。

比如说,你想看看,我们现在考虑 w 1 w_1 w1 w 2 w_2 w2 两个参数,这个图上面的顏色,是它的 loss,那如果我们考虑 w 1 w_1 w1 的变化,我们就在蓝色这条线这边切一刀,我们把蓝色这条线切一刀,我们看到的 error surface 长得是这个样子,如果你比较图上的两个点, a a a 点跟 b b b 点,那确实 a a a 点的微分值比较大,那它就距离最低点比较远,但是,如果我们同时考虑几个参数,我们同时考虑 w 2 w_2 w2 这个参数,我们在绿色的这条线上切一刀,如果我们在绿色这条线上切一刀的话,我们得到的值是这样子,我们得到的 error surface 是这样子,它是比较尖的,这个谷呢,是比较深的,因为你会发现说, w 2 w_2 w2 在这个方向的变化是比较猛烈的,如果我们只比较在 w 2 w_2 w2 这条线上的两个点 , c c c d d d 的话,确实 c c c 的微分比较大,所以,它距离最低点是比较远的,但是,如果我们今天的比较是跨参数的话,如果我们比较 a a a 这的点对 w 1 w_1 w1 的微分, c c c 这个点对 w 2 w_2 w2 的微分,这个结论就不成立了,虽然说, c c c 这个点对 w 2 w_2 w2 的微分值是比较大的,但 c c c 呢,是离最低点比较近的,而 a a a 是比较远的,所以当我们 update 参数选择跟微分值成正比,这样的论述是在,没有考虑跨参数的条件下才成立的,当我们要同时考虑好几个参数的时候呢,我们这样想呢,就不足够了,所以,如果我们今天要同时考虑好几个参数的话,我们应该要怎么想呢?

如果你看看,我们说的最好的 step 的话,我们看最好的这个 step,它其实还有分母这一项 ,它的分母这一项是 2 a 2a 2a,这个 2 a 2a 2a 哪来的呢?这个 2 a 2a 2a 是什么呢?这个 2 a 2a 2a 呢,如果我们今天把这个 y y y 做 2 次微分,我们做一次微分得到这个式子,那如果我们做二次微分的话,就得到 2 a 2a 2a,那它是一个 constant,这个 2 a 2a 2a 呢,就出现在最好的 step 的分母的地方,所以今天最好的 step,它不只是要正比于一次微分,它同时要和二次微分的大小成反比,如果你二次微分比较大,这个时候你参数 update 量应该要小,如果二次微分小的话,你参数 update 量应该要比较大,所以最好的 step 应该要把二次微分考虑进来。

所以,如果我们今天把二次微分考虑进来的话,你会发现说,在 w 1 w_1 w1 这个方向上,你的二次微分是比较小的,因为这个是一个比较平滑的弧,所以这个二次微分是比较小的,在 w 2 w_2 w2 的方向上,这个是一个比较尖的弧、比较深的弧,所以它的二次微分是比较大的,所以你光比较 a a a c c c 的微分值是不够的,你要比较 a a a 的微分值除掉它的二次,跟 c c c 的微分值除掉它的二次,再去比,如果你做这件事,你才能够真正显示,这些点跟最低点的距离这样,虽然 a a a 这个点,它的微分是比较小的,但它的二次也同时是比较小的, c c c 比较大、二次是比较大的,所以,如果你把二次微分的值呢,考虑进去,做这个评检、做调整的话,那你这个时候,才能真正反映, 你现在所在位置跟最低点的距离,好,那这件事情跟 Adagrad 的关系是什么呢?

如果你把 Adagrad 的式子列出来的话,它参数的 update 量是这个样子的, η \eta η 是一个 constant,所以我们就不理它,这个 g t g^t gt ,它就是一次微分,对不对,下面这个,过去所有微分值的平方和开根号,神奇的是,它想要代表的是二次微分,那你可能会问说,怎么不直接算二次微分呢?你可以直接算二次微分,确实可以这么做,也有这样的方法, 而且你确实可以这么做,但是,有时候你会遇到的状况是,有时候你参数量大、data 多的时候,你可能算一次微分就花一天这样子,然后你再算二次微分,你要再多花一天,有时候,这样子的结果是你不能承受的,而且你多花一天 performance 还不见得会比较好,其实这个结果,是你不能承受的,所以,Adagrad 它提供的做法就是,我们在没有增加任何额外运算的前提之下,想办法能不能够做一件事情,去估一下,二次的微分应该是多少,在 Adagrad 里面,你只需要一次微分的值,那这个东西我们本来就要算它了,所以并没有多做任何多余的运算,好,怎么做呢?

如果我们考虑一个二次微分比较小的峡谷,跟一个二次微分比较大的峡谷,然后我们把它的一次微分的值,考虑进来的话,这个是长这样,如果你只是在,蓝色这个区间和绿色这个区间里面,随机 sample 一个点,算它的一次微分的话,你看不出来它的二次微分值是多少,但是如果你 sample 够多点,你在某一个 range 之内,sample 够多点的话,那你就会发现说,在这个比较平滑的峡谷里面,它的一次微分通常就是比较小的,在比较尖的峡谷里面,它的一次微分通常是比较大的,而 Adagrad 这边,这一件事情,summation over 过去所有的微分的平方,这件事情,你就可以想成,在这个地方呢,做 sampling,那你再把它的平方和,再开根号算出来,那这个东西,就反映了二次微分的大小,这个 Adagrad 怎么做,其实我们上次已经有示范过了,那所以我们就不再示范,接下来我们要讲的另外一件事情呢, 是 Stochastic 的 Gradient Descent,那它可以让你的 training 呢,更快一点。

3.2 Stochastic Gradient Descent

**随机梯度下降可以使训练更快一些。**我们之前讲说,我们的 loss function,它的样子呢,如果我们今天做的是这个 Regression 的话,这个是 Regression 的式子,那你把 Regression 得到 estimation 的结果,减掉 y ^ \hat y y^,再去平方,再 summation over 所有的 training data,这是我们的 loss function,所以,这个式子非常合理,我们的 loss 本来就应该考虑所有的 example,它本来就应该 summation over 所有的 example,有这些以后,你就可以去算 Gradient,然后你就可以做 Gradient Descent。

但 Stochastic Gradient Descent,他的想法不一样,Stochastic Gradient Descent 它做的事情是,每次就拿一个 x n x^n xn 出来,这边你可以随机取,也可以按照顺序取,那其实随机取的时候,如果你今天是在做 deep learning 的 case,也就是说你的 error surface 不是 convex,是非常崎岖的,随机取呢,是有帮助的,总之,你就取一个 example 出来,假设取出来的 example 是 x n x^n xn,这个时候呢,你要计算你的 loss,你的 loss 呢,只考虑一个 example,你只考虑你现在的参数,对这个 example 的 y y y 的估测值,再减掉它的正确答案,再做平方,然后就不 summation over 所有的 example,因为你现在只取一个 example 出来,你只算某一个 example 的 loss,那接下来呢,你在 update 参数的时候,你只考虑那一个 example,我们只考虑一个 example 的 loss function,我们就写成, L n L^n Ln,代表它是考虑第 n n n 个 example 的 loss function,那你在算 Gradient 的时候呢?你不是算对 total 所有的 data,它的 Gradient 的和,你只算对某一个 example,它的 loss 的 Gradient,然后呢,你就很急躁的 update 参数了,所以在原来的 Gradient Descent 里面, 你计算所有 data 的 loss,然后才 update 参数,但是在 Stochastic Gradient Descent 里面,你看一个 example,就 update 一个参数这样,你可能想说,这有啥好呢?

听起来好像没有什么好的,那我们实际来操作一下好了,刚才看到图呢,它可能是这个样子的,我们刚才看到的图呢,它可能是这个样子,原来的 Gradient Descent,你看完所有的 example 以后,你就 update 一次参数,那它其实是比较稳定,你会发现说,它走的方向,就是按照 Gradient 建议我们的方向呢,来走,但是如果你是用 Stochastic Gradient Descent 的话,你每看到一个 example ,你就 update 一次参数,如果你有 20 个 example 的时候,那你就 update 20 次参数,那这边他是看完 20 个 example 才 update 一次参数,这边是,每一个 example 都 update 一次参数,所以在它看 20 个 example 的时候,你这边也已经看了 20 个 example, 而且 update 20 次参数了,所以 update 20 次参数的结果呢,看起来就像是这样,从一样的起始点开始,但它已经 update 了 20 次参数,所以,这个如果只看一个 example 的话,它的步伐是小的,而且可能是散乱的,因为你每次只考虑一个 example,所以它参数 update 的方向,跟这个 Gradient Descent,total loss 的 error surface 界定我们走的方向,不见得是一致的,但是因为我们可以看很多个 example,所以天下武功,为快不破。在它走一步的时候,你已经出 20 拳了,所以它走的反而是比较快的。

3.3 Feature Scaling

然后呢,接下来我们要讲的是第三个 tip,就是你可以做 Feature 的 Scaling,所谓的 Feature Scaling 意思呢是这样子,假设我们现在要做 Regression,那我们这个 Regression 的 function 里面,input 的 feature 有两个, x 1 x_1 x1 x 2 x_2 x2,比如说,如果是要 predict 宝可梦进化以后 CP 值的话,那 x 1 x_1 x1 是进化前的 CP值, x 2 x_2 x2 是它的生命值…等等这样,你有两个 input feature, x 1 x_1 x1 x 2 x_2 x2,那如果你看你今天的 x 1 x_1 x1 x 2 x_2 x2,它们分布的 range 是很不一样的话,那就建议你呢,把它们做 scaling,把它们的 range 分布变成是一样,比如,这边的 x 2 x_2 x2 它的分布是远比 x 1 x_1 x1 大,那就建议你把 x 2 x_2 x2 这个值呢,做一下 rescaling,把它的值缩小,让 x 2 x_2 x2 的分布跟 x 1 x_1 x1 的分布是比较像的,你希望不同的 feature,他们的 scale 是一样的,为什么要这么做呢?

我们举个例子,假设这个是我们的 Regression 的 function,那我们写成这样,这边这个意思跟这个是一样的啦, y = b + w 1 x 1 + w 2 x 2 y = b + w_1x_1 + w_2x_2 y=b+w1x1+w2x2,那假设 x 1 x_1 x1 平常的值,都是比较小的,假设说 1, 2 之类的,假设 x 2 x_2 x2 它平常的值都很大,它 input 的值都很大,100, 200 之类的,那这个时候,如果你把 loss 的 surface 画出来,会遇到什么样的状况呢?

你会发现说,如果你更动 w 1 w_1 w1 w 2 w_2 w2 的值,假设你把 w 1 w_1 w1 w 2 w_2 w2 的值都做一样的更动,都加个 Δ w \Delta w Δw ,你会发现说, w 1 w_1 w1 的变化,对 y y y 的变化而言是比较小的, w 2 w_2 w2 的变化,对 y y y 的变化而言是比较大的,对不对,这件事情是很合理的,因为你要把 w 2 w_2 w2 乘上它 input 的这些值,你要把 w 1 w_1 w1 乘上它 input 的这些值,如果 w 2 w_2 w2 它乘的这些 input 的值是比较大的,那只要把 w 2 w_2 w2 小小的变化,那 y y y 就会有很大的变化,那同样的变化, w 1 w_1 w1 它 input 的值是比较小的,它对 y y y 的影响呢,就变成是比较小的,所以如果你把他们的 error surface 画出来的话呢,你看到的可能像是这个样子,这个图是什么意思呢?因为 w 1 w_1 w1 y y y 的影响比较小,所以 w 1 w_1 w1 就对 loss 的影响比较小,所以 w 1 w_1 w1 对 loss 是有比较小的微分的,所以 w 1 w_1 w1 这个方向上,它是比较平滑, w 2 w_2 w2 y y y 的影响比较大,所以它对 loss 的影响比较大,所以改变 w 2 w_2 w2 的时候,它对 loss 的影响比较大,所以,它在这个方向上,是比较 sharp 的,所以这个方向上,有一个比较尖的峡谷,那如果今天, x 1 x_1 x1 x 2 x_2 x2 的值,它们的 scale 是接近的,那如果你把 loss 画出来的话呢,它就会比较接近圆形, w 1 w_1 w1 w 2 w_2 w2 呢,对你的 loss 是有差不多的影响力,这个对做 Gradient Descent 会有什么样的影响呢?是会有影响的,比如说,如果你从这个地方开始,其实我们上次已经有看到了,就是这样,这种长椭圆的 error surface 阿,如果你不出些 Adagrad 什么的,你是很难搞定它的,因为就在这个方向上,和这个方向上,你会需要非常不同的 learning rate,你同一组 learning rate 会搞不定它,你要 adaptive learning 才能够搞定它,所以这样子的状况,没有 scaling 的时候, 它 update 参数是比较难的,但是,如果你有 scale 的话,它就变成一个正圆形,如果是在正圆形的时候 ,update 参数就会变得比较容易,而且,你知道说 Gradient Descent 它并不是向着最低点走,在这个蓝色圈圈,它的最低点是在这边,绿色圈圈最低点是在这边,但是你今天在 update 参数的时候,走的方向是顺着等高线的方向,是顺着 Gradient 箭头的方向,所以,虽然最低点在这边,你从边开始走,你还是会走这个方向,再走进去,你不会只向那个最低点去走,那如果是绿色的呢,绿色的又不一样,因为,它如果真的是一个正圆的话,你不管在这个区域的哪一个点,它都会向着圆心走,所以,如果你有做 feature scaling 的时候,你在做参数的 update 的时候呢,它是会比较有效率的,那你可能会问说,怎么做 scaling,这个方法有千百种啦,你就选一个你喜欢的就是了。

那常见的作法是这样,假设我有 r r r 个 example, x 1 , x 2 , ⋯ x R x^1, x^2, \cdots x^R x1,x2,xR,每一笔 example,里面都有一组 feature, x 1 x^1 x1 它第一个 component 就是 x 1 1 x^1_1 x11 x 2 x^2 x2 它第一个 component 就是 x 1 2 x^2_1 x12 x 1 x^1 x1 它第二个 component 就是 x 2 1 x^1_2 x21 x 2 x^2 x2 它第二个 component 就是 x 2 2 x^2_2 x22,那怎么做 feature scaling?你就对每一个 dimension i i i,都去算它的 mean,这边写成 m i m_i mi,都去算它的 deviation,这边写成 σ i \sigma_i σi,然后呢,对第 r r r 个 example 的第 i i i 个 component,你就把它减掉,所有的 data 的 第 i i i 个 component 的 mean,也就是 m i m_i mi,再除掉所有的 data 的第 i i i 个 component 的 standard deviation,然后呢,你就会得到说,你做完这件事以后,你所有 dimension 的 mean 就会是 0,你的 variance 就会是 1,这是其中一个常见地做 localization 的方法。

3.4 理论支持

最后,在下课前呢,我们来讲一下,为什么 Gradient Descent 它会 work,Gradient Descent 背后的理论基础是什么,那在真正深入数学部分的基础之前呢,我们来问大家一个问题,大家都已经知道 Gradient Descent 是怎么做的,假设,我问你一个这样的是非题,每一次,我们在 update 参数的时候,我们都得到一个新的 θ \theta θ,这个新的 θ \theta θ,总是会让我们的 loss 比较小,这个陈述,是对的吗?好,也就是意思就是说 θ 0 \theta^0 θ0 你把它代到 L L L 里面,它会大于 θ 1 \theta^1 θ1 代到 L L L 里面,它会大于 θ 2 \theta^2 θ2 代到 L L L 里面,每次 update 参数的时候, 这个 loss 的值,它都是越来越小的,这陈述,是正确的吗?

没错,就是 update 参数以后,loss 不见得会下降的,所以如果你今天自己 implement Gradient Descent,做出来,update 参数以后的 loss 没有下降,那不见得是你的程式有 bug,因为,本来就有可能发生这种事情,我们刚已经看过说,如果你 learning rate 调太大的话,会发生这种事情,好,那在解释 Gradient Descent 的 Theory 之前,这边有一个 Warning of Math ,意思就是说,这个部分,就算是你没有听懂,也没有关系,太阳明天依旧会升起。

好,那我们先不要管 Gradient Descent,我们先来想想看, 假如你要解一个 Optimization 的 problem,你要在这一个 figure 上面,找他的最低点,你到底应该要怎么做?那有一个这样子的作法,如果今天给我一个起始的点 ,也就是 θ 0 \theta^0 θ0,我们有方法,在这个起始点的附近,画一个圆圏、画一个范围、画一个红色圈圈,然后,在这个红色圈圈里面,找出它的最低点,比如说,红色圈圈里面的最低点,就是在这个边上,这个意思就是说,如果你给我一整个 error function,我没有办法,马上一秒钟就告诉你说,我没有办法马上告诉你说,它的最低点在哪里,但是如果你给我一个 error function,加上一个初始的点,我可以告诉你说,在这个初始点附近,画一个范围之内,我们可以在那个附近,找出一个最小的值,那你假设找到最小的值以后,我们就更新我们中间的位置,中间的位置挪到 θ 1 \theta^1 θ1,接下来呢,再画一个圆圈,我们可以在这个圆圈范围之内,再找一个最小的点,假设呢,它是落在这个地方,然后,你就再更新中心点的参数,到 θ 2 \theta^2 θ2 这个地方,然后,你就可以再找小小范围内的最小值,然后,再更新你的参数,就一直这样下去,好,那现在的问题就是,怎么很快的在红色圈圈里面,找一个可以让 loss 最小的参数呢?怎么做这件事呢?

这个地方要从 Taylor series 说起,假设你是知道 Taylor series 的,那个微积分有教过,Taylor series 告诉我们什么呢?它告诉我们说,任何一个 function h ( x ) h(x) h(x),如果它在 x = x 0 x = x_0 x=x0 这点呢,是 infinitely differentiable,那你可以把这个 h ( x ) h(x) h(x) 写成以下这个样子,你可以把 h ( x ) h(x) h(x) 写成, ∑ k = 0 ∞ \sum_{k=0}^\infty k=0,这里 k k k 代表微分的次数,( h h h x 0 x_0 x0 微分 k k k 次以后的值) / k ! k! k!,然后 ( x − x 0 ) k (x-x_0)^k (xx0)k,不过,把它展开的话,你可以把 h ( x ) h(x) h(x) 写成图中公式那样,那当 x x x 很接近 x 0 x_0 x0 的时候, ( x − x 0 ) (x - x_0) (xx0) 就会远大于 ( x − x 0 ) 2 (x - x_0)^2 (xx0)2,就会远大于后面的 3 次、4 次,到无穷多次,所以这个时候,你可以把后面的高次项删掉,所以,当 x x x 很接近 x 0 x_0 x0 的时候,这个只有在 x x x 很接近 x 0 x_0 x0 的时候才成立, h ( x ) h(x) h(x) 就可以写成 h ( x 0 ) + h ′ ( x 0 ) ( x − x 0 ) h(x_0) + h'(x_0)(x - x_0) h(x0)+h(x0)(xx0),那这个是只有考虑一个 variable 的 case,那其实,我这边有个例子,假设 h ( x ) = sin ⁡ ( x ) h(x) = \sin(x) h(x)=sin(x),那在 x 0 x_0 x0 约等于 ( π / 4 ) (\pi/4) (π/4) 的地方, sin ⁡ ( x ) \sin(x) sin(x) 你可以写成什么样子呢?

你用计算机算一下,它算出来是这样子,这个 sin ⁡ ( x ) \sin(x) sin(x),可以写成这么多这么多这么多项的相加,那如果我们把这些项,画出来的话,你得到这样子,如果是 1 / 2 1/\sqrt{2} 1/2 ,只有考虑 0 次的话,是这条水平线,考虑 1 / 2 + ( x − π / 4 ) / 2 1/\sqrt{2} + (x-\pi/4)/\sqrt{2} 1/2 +(xπ/4)/2 ,考虑一次的话,是这条斜线,如果你有再把 2 次考虑进去,考虑 0 次, 1 次, 2 次的话,我猜你得到的,可能是这条线,如果你再把 3 次考虑进去的话,你得到这条线,橙色这条线是 sin ⁡ ( x ) \sin(x) sin(x),你发现说,如果你只有考虑一次的时候,它其实跟这个 sin ⁡ ( x ) \sin(x) sin(x),橙色这条线差很多啊,根本不像,但是,它在 ( π / 4 ) (\pi/4) (π/4) 的附近,在这个地方附近,它是像的,因为,如果 x x x 很接近 ( π / 4 ) (\pi/4) (π/4) 的话,那后面这些项,平方项、三次方项这些都很小,所以就可以忽略它们,只考虑一次的部分,那这个 Taylor series 也可以是有好几个参数的。

如果今天有好几个参数的话,那你就可以这样子做,这个 h ( x , y ) h(x, y) h(x,y),假设这个 function 有两个参数,它在 x 0 x_0 x0 y 0 y_0 y0 附近,你可以把它写成呢,这个 h ( x , y ) h(x, y) h(x,y),你可以用 Taylor series 把它展开成这样,就有 0 次的,有考虑 ( x − x 0 ) (x - x_0) (xx0) 的,有考虑 ( y − y 0 ) (y - y_0) (yy0) 的,还有考虑 ( x − x 0 ) 2 (x - x_0)^2 (xx0)2 ( y − y 0 ) 2 (y - y_0)^2 (yy0)2 的,如果今天 x , y x, y x,y 很接近 x 0 , y 0 x_0, y_0 x0,y0 的话,那平方项呢,就可以被消掉,就只剩这个部份而已,所以,今天 x , y x, y x,y 如果很接近 x 0 , y 0 x_0, y_0 x0,y0 的话,那 h ( x , y ) h(x, y) h(x,y) 就可以写成呢,约等于 h ( x 0 , y 0 ) h(x_0, y_0) h(x0,y0) 加上, ( x − x 0 ) (x - x_0) (xx0) 乘上 ( x 0 , y 0 ) (x_0, y_0) (x0,y0) x x x 做偏微分,再加上 ( y − y 0 ) (y - y_0) (yy0) 乘上 ( x 0 , y 0 ) (x_0, y_0) (x0,y0) y y y 做偏微分,这个偏微分的值,你不要看他这么复杂,微分的值,它其实就是一个 constant 而已,就是一个常数项而已。

好,那如果我们今天考虑 Gradient Descent 的话,如果我们今天考虑我们刚才讲的问题,如果,今天给我一个中心点,这是 a a a b b b,那我画了一个很小很小的圆圈,红色的圆圈,假设它是很小的,再这个红色圆圈的范围之内,我其实可以把 loss function 用 Taylor series 做简化,我可以把 loss function, L ( θ ) L(\theta) L(θ) 写成, L ( a , b ) L(a, b) L(a,b) + θ 1 \theta_1 θ1 对 loss function 的偏微分, 在 ( a , b ) (a, b) (a,b) 这个位置的偏微分 ,乘上 ( θ 1 − a ) (\theta_1 - a) (θ1a),加上 θ 2 \theta_2 θ2 对 loss function 在 ( a , b ) (a, b) (a,b) 这个位置的偏微分,再乘上 ( θ 2 − b ) (\theta_2 - b) (θ2b),所以在红色的圈圈内,loss function 可以写成这样子,那我们把 L ( a , b ) L(a,b) L(a,b) L L L ( a , b ) (a, b) (a,b) 代进去, 它就是一个 constant,用一个 s s s 来表示,那 θ 1 \theta_1 θ1 L L L 的偏微分,在 ( a , b ) (a, b) (a,b) 这个位置,这也是一个 constant, 所以我们用 u u u 来表示,这也是一个 constant,所以我们用 v v v 来表示,这样这个式子呢,看起来就非常简单了。如果告诉你说,红色圈圈内的式子都长这个样子,你能不能秒算, 哪一个 θ 1 \theta_1 θ1 θ 2 \theta_2 θ2 可以让它的 loss 最小呢?我相信你可以秒算这个结果,不过,我们还是很快地稍微看一下。

L L L 写成这样, s , u , v s, u, v s,u,v 都是常数,我们就把它放在蓝色的框框那里面,不用管它值是多少,我们现在的问题,就是找,在红色的圈圈内呢,找 θ 1 \theta_1 θ1 θ 2 \theta_2 θ2 让 loss 最小,那所谓的在红色圈圈内的意思就是说,红色圈圈的中心就是 a a a b b b,所以你这个 ( θ 1 − a ) 2 + ( θ 2 − b ) 2 ≤ d 2 (\theta_1 - a)^2 + (\theta_2 - b)^2 \leq d^2 (θ1a)2+(θ2b)2d2,他们要在这个红色圈圈的范围内,这件事情,其实就是秒算对不对,太简单了,你一眼就可以看出来。

如果你今天把 ( θ 1 − a ) (\theta_1 - a) (θ1a) 都用 Δ θ 1 \Delta \theta_1 Δθ1 表示, ( θ 2 − b ) (\theta_2 - b) (θ2b) 都用 Δ θ 2 \Delta \theta_2 Δθ2 来表示, s s s 你可以不用理它,因为它跟 θ \theta θ 没关系啊,所以你要找不同 θ \theta θ 让它值最小,不用管 s s s。好,如果我们看一下 L L L,你会发现说它是 u Δ θ 1 + v Δ θ 2 u \Delta \theta_1 + v \Delta \theta_2 uΔθ1+vΔθ2,也就是说,它就好像是,它的值就是,有一个 vector ,叫做 ( Δ θ 1 , Δ θ 2 ) (\Delta \theta_1, \Delta \theta_2) (Δθ1,Δθ2),有另外一个 vector,叫做 ( u , v ) (u, v) (u,v),你把这个 vector 跟这个 vector 做 inner product,忽略 s s s 的话, 你就得到这个值,接下来的问题就是,如果我们要让 L ( θ ) L(\theta) L(θ) 最小,我们应该选择什么样的 ( Δ θ 1 , Δ θ 2 ) (\Delta \theta_1, \Delta \theta_2) (Δθ1,Δθ2) 呢?

这个,太容易了,就是选正对面的,对不对?如果我们今天把 ( Δ θ 1 , Δ θ 2 ) (\Delta \theta_1, \Delta \theta_2) (Δθ1,Δθ2) 转成跟 ( u , v ) (u, v) (u,v) 这条反方向,然后,再把 ( Δ θ 1 , Δ θ 2 ) (\Delta \theta_1, \Delta \theta_2) (Δθ1,Δθ2) 的长度增长,我们把它转到反方向,再把它伸长,长到极限,也就是长到这个红色圈圈的边缘,那这个 ( Δ θ 1 , Δ θ 2 ) (\Delta \theta_1, \Delta \theta_2) (Δθ1,Δθ2) ( u , v ) (u, v) (u,v),它们做 inner product 的时候,它的值是最大的,所以,这告诉我们说,什么样的 ( Δ θ 1 , Δ θ 2 ) (\Delta \theta_1, \Delta \theta_2) (Δθ1,Δθ2) 可以让 loss 的值最小呢?

就是它是 ( u , v ) (u, v) (u,v) 乘上负号,再乘上一个 scale,再乘上一个 constant η \eta η,也就是说你要把 ( Δ θ 1 , Δ θ 2 ) (\Delta \theta_1, \Delta \theta_2) (Δθ1,Δθ2) 调整它的长度,长到正好顶到这个红色圈圈的边边,这个时候呢,它算出来的 loss 是最小的,这一项应该跟长度是成正比的,所以呢,我们再整理一下式子, Δ θ 1 \Delta \theta_1 Δθ1 就是 ( θ 1 − a ) (\theta_1 - a) (θ1a) Δ θ 2 \Delta \theta_2 Δθ2 就是 ( θ 2 − b ) (\theta_2 - b) (θ2b),所以,如果我们今天要在红色圈圈里面,找一个 θ 1 \theta_1 θ1 θ 2 \theta_2 θ2 让 loss 最小的话,那怎么做呢?那个最小的值,就是中心点 ( a , b ) (a, b) (a,b),减掉某一个 constant 乘上 ( u , v ) (u, v) (u,v)

所以,我们就知道了这件事,那你接下来要做的事,就是把 ( u , v ) (u, v) (u,v) 带进去,把它带进去,就得到这样子的式子,那这个式子,你就发现它其实,exactly 就是 Gradient Descent,对不对?

我们做 Gradient Descent 的时候,就是找一个初始值,算每一个参数在初始值的地方的偏微分,把它排成一个 vector,就是 Gradient,然后再乘上某一个东西,叫做 learning rate,再把它减掉,所以这个式子,exactly 就是 Gradient Descent 的式子,但你要想想看,我们今天可以做这件事情,我们可以用这个方法,找一个最小值,它的前提是什么? 它的前提是,你的上面这个式子,要成立,Maclaurin(麦克劳林) series 给你的这个 approximation 是够精确的,什么样 Taylor series 给我们的 approximation 才够精确呢?当你今天画出来的红色圈圈够小的时候,Taylor series 给我们的 approximation 才会够精确,所以,这个就告诉我们什么?

这个告诉我们说,你这个红色圈圈的半径是小的,那这个 η \eta η ,这个 learning rate,它跟红色圈圈的半径是成正比的,所以这个 learning rate 不能太大,你 learning rate 要很小, 你这个 learning rate 无穷小的时候呢,这个式子才会成立,所以 Gradient Descent,如果你要让你每次 update 参数的时候,你的 loss 都越来越小的话,其实,理论上你的 learning rate 要无穷小, 你才能够保证这件事情,虽然实作上,只要够小就行了,所以,你会发现说,如果你的 learning rate 没有设好,是有可能说,你每次 update 参数的时候,这个式子是不成立的,所以导致你做 Gradient Descent 的时候, 你没有办法让 loss 越来越小,那你会发现说,这个 L L L,它只考虑了,Taylor series 里面的一次式,可不可以考虑二次式呢?Taylor series 不是有二次、三次,还有很多吗?如果你把二次式考虑进来,你把二次式考虑进来,理论上,你的 learning rate 就可以设大一点,对不对,如果我们把二次式考虑进来,可不可以呢?是可以的,那有一些方法,我们今天没有要讲, 是有考虑到二次式的,比如说,牛顿法这样子,那在实作上,尤其是假设你在做 deep learning 的时候,这样的方法,不见得太普及,不见得太 practical,为什么呢?因为你现在要算二次微分,甚至它还会包含一个 Hessian 的 matrix,和 Hessian matrix 的 inverse,总之,你会多很多运算,而这些运算,在做 deep learning 的时候呢,你是无法承受的,你用这个运算,来换你 update 的时候比较有效率,会觉得是不划算的,所以,今天如果在做,比如说,deep learning 的时候,通常,还是 Gradient Descent 是比较普及、主流的作法。

上面如果你没有听懂的话,也没关系,在最后一页,我们要讲的是 Gradient Descent 的限制,Gradient Descent 有什么样的限制呢?有一个大家都知道的是, 它会卡在这个 local minimum 的地方,所以,如果这是你的 error surface,那你从这个地方,当作你的初始值,去更新你的参数,最后走到一个微分值是 0,也就是 local minimum 的地方,你参数的更新,就停止了,但是,一般人就只知道这个问题而已,那其实还有别的问题,事实上,这个微分值是 0 的地方, 并不是只有 local minimum,对不对,seddle point 也是微分值是 0,所以,你今天在参数 update 的时候,你也是有可能卡在一个不是 local minimum, 但是微分值是 0 的地方,这件事情,也是有可能发生的,但是,这什么卡在 local minimum 或微分值是 0 的地方啊,这都只是幻想啦,其实,真正的问题是这样,你今天其实只要,你想想看,你几时是真的算出来,那个微分值 exactly 等于 0 的时候,就把它停下来了,也就是,你最多就做微分值小于 1 0 − 6 10^{-6} 106,小于一个很小的值,你就把它停下来了,对不对?但是,你怎么知道,那个微分值算出来很小的时候,它就很接近 local minimum 呢?不见得很接近 local minimum 啊,有可能,微分值算出来很小, 但它其实是在一个高原的地方,而那高原的地方,微分值算出来很小,你就觉得说,哦,那这个一定就是很接近 local minimum,在 local minimum 附近,所以你就停下来了,因为你们真的很少有机会 exactly 微分值算出来是 0 嘛,对不对,你可能觉得说, 微分算出来很小,就很接近 local minimum,你就把它停下来,那其实搞不好,它是一个高原的地方,它离那个 local minimum 还很远啊,这也是有可能的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

李宏毅 机器学习 2016 秋:3、Gradient Descent 的相关文章

  • html5新特性

    目录 使用语义化标签的目的 1 html5新增的语义化标签 2 html新增的多媒体标签 1 视频 video 2 音频 audio 属性 object fit 3 html5新增的input表单元素属性 1 新增的input标签type属
  • 准备加入第二个项目(第5960小时加入)

    今天 老师过来办事 看了我做的东西后 邀请我加入他的项目 让我受宠若惊 2012年10月 我加入老师的项目后 2天内落荒而逃 因为一句代码都没有写出来 再然后 老师以我没有项目经验为由 拒绝了我后来想加入项目的要求 2年后 老师邀请我去做项
  • 安装Anaconda科学计算包

    Anaconda介绍 最近在看 Python语言及其应用 这本书 作为一本介绍Python语言和应用的书非常不错 在这本书的最后 介绍了一些Python常用的第三方类库 像科学计算库 金融计算库 图形图像库等等 其中也介绍了Anaconda
  • 移动端H5页面生成图片解决方案

    现在有很多微信公众号运营活动 都有生成图片的需求 生成图片后可以发送给好友和发到朋友圈扩散 利于产品的宣传 1 生成图片可以用canvas 但是由于已经有了html2canvas这个开源库 所以为了节省时间就没有自己写了 github地址

随机推荐

  • 为什么文件删除了但磁盘空间没有释放?

    1 案例现象 这天 监控系统发来一条告警消息 内容说某台服务器根目录磁盘占用空间达到阈值 超过百分之八十了 登上服务器 df Th 看一下 发现磁盘空间确实不够用了 root localhost df Th 文件系统 类型 容量 已用 可用
  • java怎么从一个类传值到另一个类,关于JAVA的引用类型传值.

    方法参数传递都按值传递 对于基本类型 传递原始值 对于对象类型 传递其指向的对象的地址值 多个同类型不同的变量可以指向同一个对象 但是其中任何一个变量被重新赋值 也就是指向一个新的对象时 不影响其它变量的指向 方法定义的形参 在调用的发生的
  • Socket编程之聊天程序 - 模拟Fins/ModBus协议通信过程

    设备控制软件编程涉及到的基本通信方式主要有TCP IP与串口 用到的数据通信协议有Fins与ModBus 更高级别的通信如 net中的Remoting与WCF在进行C S架构软件开发时会采用 本篇文章结合Fins ModBus协议的指令帧结
  • 关于前端获取后端传输的参数并在js中应用该参数

    在进行dynamicTree名称获取时 如果是涉及到不同数据库需要使用不同的dynamicTree的xml文件且该名称在前端写死状态 可以采用setAttribute方法将值赋给前端 前端用 接收该值 并在js处使用document get
  • TCP UDP协议的应用以及高级IO的介绍

    TCP UDP协议的应用以及高级IO的介绍 网络通信协议 模型 TCP和UDP两个协议都是一对多的网络通信模型 TCP编程模型 UDP编程模型 实例 TCP模型 聊天室的服务器 有私密消息功能以及列出聊天者的功能 include
  • RCE远程命令执行漏洞挖掘思路

    RCE漏洞可能出现在哪些地方 1 URL上 在url参数上 不仅仅可能存在ssrf漏洞 也有很大概率存在命令执行 很大可能调用系统命令如curl payload例子 index php id 2 phpinfo ttp www xxx co
  • ue4编辑模型时,让模型底部刚好在地面上的方法

    选中模型按住End键
  • Matlab 公式大全

    1 MATLAB公式 例如 在命令窗口中输入sin pi 5 然后单击回车键 则会得到该表达式的值 sin pi 5 ans 0 5878 例如 sin 1 9 pi sin 2 9 pi sin 3 9 pi sin 4 9 pi sin
  • linux软件共用的依赖关系,利用 yum 解决 Linux 软件包的依赖关系

    在Linux系统软件安装包依赖关系是一个很烦恼的问题 yum能够从指定的服务器自动下载RPM包并且安装 可以自动处理依赖性关系 并且一次安装所有依赖的软体包 无须繁琐地一次次下载 安装 可以利用ftp和Createrepo共同搭建本地软件库
  • C语言结构体中定义函数指针详解

    C语言结构体中定义函数指针详解 结构体指针函数应用场景之一 驱动程序编写 结构体的一些基本用法 形式 先定义结构体类型 再定义变量 形式 在定义类型的同时定义变量 形式 直接定义变量 用无名结构体直接定义变量只能一次 结构体指针在嵌入式Li
  • canvas绘制线条、矩形、曲线及填充

    1 绘制线条和填充 1 绘制线段的API是上下文对象的方法 2 beginPath 开始定义一条新的路径 3 moveTo 开始定义一条新的子路径 该方法确定了线段的起点 4 lineTo 将上面定义的线段起点和指定的新的点连接起来 5 到
  • Vue+element ui -- 自定义表单验证:金额

    在实际项目中 表单验证可以说非常普遍 尤其是财务系统项目和商城项目 涉及到金额的输入框更是很多 那么验证用户输入信息的争取与否 就变得至关重要 不单要做到准确还要照顾用户的输入习惯以及舒适度 这边笔记记录了原来我在项目中进行 金额 方面的自
  • xp系统电脑服务器端口,XP的电脑用CMD指令怎么开3389端口

    输入命令 REG ADD HKLM SYSTEM CurrentControlSet Control Terminal Server v fDenyTSConnections t REG DWORD d 00000000 f 如果用CMD命
  • MATLAB与深度学习(一)— Deep Learning Toolbox

    MATLAB与深度学习 一 Deep Learning Toolbox 最近 我在学习基于matlab的深度学习的内容 并整理出如下学习笔记 本文借鉴和引用了网上许多前辈的经验和代码 如有冒犯 请及时与我联系 1 MATLAB与深度学习的简
  • 使用ImageMagick为你的网站减重(转)

    片在网站所占的比重越来越重 更好的优化图片可以提高网站速度 减少宽带流量 1 对用户上传图片进行缩放 对于用户自己上传的图片不能简单的 用css限制大小 因为这样每次加载图片时候还是会加载整幅大图 占用多余的宽带 并且影响页面加载速度 应该
  • 安装程序无法自动安装Virtual Machine Communication Interface Sockets(VSock)驱动程序

    关于 VMware Tools安装时出现的问题的解决办法 安装时出现问题对话框 安装程序无法自动安装Virtual Machine Communication Interface Sockets VSock 驱动程序 必须手动安装此驱动程序
  • 动态场景下基于实例分割的SLAM(毕业设计开题及语义分割部分)

    动态场景下基于实例分割的SLAM 毕业论文设计思路及流水 前言 今年选了个比较难的毕设题目 这里记录一下自己思路和流程 为之后的学弟学妹 划掉 铺个方向 会按日期不定期的更新 一 开题 2019 12 24 考研前选择课题是 利用深度学习对
  • Linux ixgbe网卡(光模块)兼容性问题(没有网卡配置文件)

    Linux ixgbe网卡 光模块 兼容性问题 ixgbe光纤网卡的驱动在默认情况下不支持第三方兼容光模块 会导致网卡驱动加载失败 表现为 执行lspci grep 82599能看到网卡在pci设备中 06 00 0 Ethernet co
  • 剑指 Offer 15. 二进制中1的个数

    public class Solution you need to treat n as an unsigned value public int hammingWeight int n int div 1 int num 0 for in
  • 李宏毅 机器学习 2016 秋:3、Gradient Descent

    文章目录 三 Gradient Descent 3 1 Tuning your learning rates 3 2 Stochastic Gradient Descent 3 3 Feature Scaling 3 4 理论支持 三 Gr