梯度下降
前言,本人关于梯度下降的见解会随着鄙人认识的深浅进行更新,欢迎小白和我一起探寻,也欢迎大佬们指教一二。
梯度下降
梯度?第一次接触这个词有没有让你想到“梯子”呢,梯度其实也是用于下高度而引出的梯度,但不是下楼梯,更为形象的比喻为下山,站在山峰之巅,如何快速地下到山脚?就是我们要研究的梯度下降问题。
1.1 方向导数
要说明梯度下降,不可避免地要引入梯度的有关概念。
然而梯度又涉及到方向导数的概念。
方向导数:在函数定义域的内点,对某一方向求导得到的导数。一般为二元函数和三元函数的方向导数,方向导数可分为沿直线方向和沿曲线方向的方向导数。
我们之前学习的偏导数
几何意义
其实就是方向导数的特殊情况,当我们求对x的偏导数时,就是在空间上把沿x轴正方向的线作为准线的一个柱面与原有曲面的交线的一点上的切线,这条切线也在这个柱面上。而方向导数的不同是把沿特定坐标轴的线和点换成了空间中的点和单位向量,考虑到白话的叙述难以理解,上图:
x与y轴上的红色箭头表示沿此方向的反向导数。
1.2梯度
梯度:梯度的本意是一个向量(矢量),表示某一函数在该点处的方向导数沿着该方向取得最大值,即函数在该点处沿着该方向(此梯度的方向)变化最快,变化率最大(为该梯度的模)。梯度表示下降最快的原因推导
梯度的数值表述为:(二元函数常用)
表示在点(x,y)处的梯度。
那么,梯度的方向到底是什么含义呢?
梯度方向是指函数变化率最大的方向,也就是斜率越来越大的方向,曲线会越来越陡。
1.3 梯度下降
1.31 基本思想
梯度下降是一种通过递归的方式来逼近最小值的一个比较优化的算法,在机器学习,矩阵分解和线性回归中均有体现。
还以下山为例,我们要尽快的下到山脚,就要走最为陡峭的山路,其中还会涉及到的是步长,就是你一步的距离,可以这么来理解,这种下山的思想就是所为的梯度下降。
在这里不得不提醒的是去找寻最小值一定是沿负梯度的方向
1.32 核心公式
下面的核心公式给出了迭代的变化规则:
其中
α
α
α为步长,还有一个比较书面的名字叫做学习率。
1.33 一般步骤
假设一个抽象函数为f(x,y),只有一个极小值点,给定一参数Xo(趋向的初始值),那么怎样才能得到那个点的值呢?(这里的值是理论值,是满足你设定误差范围的值)
1,先设定一个较小的正数
α
α
α,就是步长,再设定一个可以接受的误差的值
ε
ε
ε;
2,求两个位置的偏导数:
3,修改当前参数的值(梯度下降得到体现)
4,判断参数变化量小于
ε
ε
ε,退出递归,否者继续按照步长去迭代。
1.34 有关问题
1,为什么我们要求得是最小值,却用参数的变化量在一个极小误差内是就可以了呢?
那还要追本溯源,公式中的步长是给定的,故没有任何变化,然而后面的偏导数却是会因为趋近于最小值而发生变化,从而导致靠近极小值时收敛速度减慢,这一点还会有一些同学误以为是步长在改变,要多加注意。
2.步长的设定问题
1.在使用梯度下降法来进行逼近时,步长的设定不能太大,不然会导致"一步横跨,找不到家"的局面。就像下图一样:
当步长大于山峰间的距离时,就会出现不管迭代多少次都不会得到结果的情况,一定要注意。
2.步长过小则会导致趋近的速率过于小,则导致趋近的时间过于浪费。就相当于你要下山,你以极小的步去下山,你还没下到山脚,就累得不行了。(就是迭代次数结束了)
1.4 梯度下降的“好基友”们
1.41批量梯度下降法(Batch Gradient Descent)
批量梯度下降法,通俗的讲不如叫全量梯度下降法,也就是说构造损失函数后,所有有关的数据都会参与每次通过梯度下降调参的过程,没漏没弃,都是兄弟。优点就是拟合的非常精准,是全局最优解,然而缺点就是当数据足够多时,趋近的速度会慢得像乌龟。
1.42 小批量梯度下降(Mini-batch Gradient Descent)
小批量也是论“批”的,也就是把批量的全部有规则的拿出数据中若干个小点的“批量”来对loss函数的自变量进行趋近。这种方法得到解的效果会处于批量与随机的中间。既能保证时间也能保证准确度。
1.43随机梯度下降法(Stochastic Gradient Descent)
随机梯度下降法,则更加容易理解了。所谓的随机也就是用数据中随机产生的一个数据进行调参过程中的趋近。会导致速度很快,众人所知,欲速则不达,效果可想而知。
1.5
1.51 例子
假设函数y=f(x1,x2,…,xn) 只有一个极小点。
初始给定参数为 X0=(x10,x20,…,xn0)。从这个点如何搜索才能找到原函数的极小值点?
方法
1.首先设定一个较小的正数η,ε.
2.求当前位置处的各个偏导数:
3.修改当前函数的参数值,公式如下:
- 如果参数变化量小于ε,退出;否则返回2。
1.52 代码
任给一个初始出发点,设为x0=-4,利用梯度下降法求函数y=x2/2-2x的极小值。
# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt #用于画函数图像的函数库
def f(x): #就是f(x)的函数表示
return np.power(x, 2)-2*x
def d_f_1(x): #f(x)的一阶导数
return x-2
def d_f_2(f, x, delta=1e-4): #f(x)的二阶导数,按导数定义表示的,delta就是差值
return (f(x+delta) - f(x-delta)) / (2 * delta)
# plot the function
xs = np.arange(-10, 11)
plt.plot(xs, f(xs)) #xs对应x轴,f(xs)对应y轴
plt.show()
learning_rate = 0.1 #步长,学习率
max_loop = 40 #迭代次数
x_init = -4 #初始值
x = x_init #为了输出最初的值而用的一个容器
lr = 0.1 #阈值,误差接受度
for i in range(max_loop): #迭代作用并进行判断
# d_f_x = d_f_1(x)
d_f_x = d_f_2(f, x)
x = x - learning_rate * d_f_x
print('initial x =', x_init)
print('arg min f(x) of x =', x)
print('f(x) =', f(x))
运行结果: