梯度下降算法实际是在计算函数的极值问题,我们通过求函数的极值获取函数的局部最值
在计算梯度下降的过程中,求函数的导数来通过逼近的方法去求局部最值
而一般文章中介绍变量变化的时候是通过将变量自身减去导数值计算的,这点很难让人理解
下面举例说明:
函数f(x) = x^2+x-1
导函数的 f(x)' = 2x + 1
当x = 0 时候
f(x) = -1
f(x)' = 1
然后 令x = x - f(x)' (让x值减去导数的值)
所以 x = 0 -1 = -1
当x = -1 时
f(x) = -1
f(x)' = -1
然后 令x = x - f(x)' (让x值减去导数的值)
所以 x = -1 - (-1) = 0
然后进入死循环(x值一直在0和 -1 变化)
那怎么让他不进去死循环呢 ,就是在x 设值的时候做文章
令x = x - f(x)' 这里在f(x)' 后面再乘一个小的变量,让x值的变化范围小一点
令x = x- f(x)' * 0.1
这样我们再来一次
当x = 0 时候
f(x) = -1
f(x)' = 1
然后 令x = x - f(x)' * 0.1 (让x值减去导数的值)
所以 x = 0 -1 * 0.1 = -0.1
f(x) = -0.89
f(x)' = 0.8
然后 令x = x - f(x)' * 0.1 (让x值减去导数的值)
所以x = -0.81
f(x) = -1.1539
f(x)' = -0.62
然后 令x = x - f(x)' * 0.1 (让x值减去导数的值)
10次之后 x 将变成 -0.4463129088
而通过二次函数的极值计算公式 -b/2a 得到x = -1/2 = -0.5
比较接近了,如果进行50次之后x 将变成 -0.49999286376153645
几乎接近了。
这里还有一个问题,为什么要令x = x - f(x)' * 0.1
这样的意图是:
首先我们要知道,最值一定出现在导数等于(接近)0的地方,为什么 ?因为最值一定是再最上面,或者最下面,斜率等于0
所以我们要调整x ,使得导数等于0
然后:当导数大于0时,说明,最值在x值左边,那x应该减小 ,所以将 x 减去一个正数 比如0.2
当导数小于0时,说明,最值再在x值右边,那x应该增大,所以将x 加上一个正数,比如0.3
一个加,一个减 ,要分情况,很麻烦,此时我们发现导数正好有正有负,减一个负数,等于加一个正式 (1-(-1)就等于 1 + 1)
所以我们都直接减导数 就满足条件,不用再去判断是加还是减
为什么要乘一个小数呢,就是防止之前我们出现x都在0,1之前变化
over 就这样
这个问题想了很久,终于相通了
下面是Java的实现方式