本文主要講解梯度下降算法,以及Python的實(shí)現(xiàn)一個(gè)簡單的例子
梯度下降法又稱為最速下降法富岳,是 1847 年有數(shù)學(xué)家柯西提出的拯腮,是解析法中最古老的一種窖式,其他解析方法或是它的變形动壤,活受到啟發(fā)得到,因此它是最優(yōu)化方法的基礎(chǔ)阁簸。
對(duì)于一個(gè)無約束問題的目標(biāo)函數(shù)
可微函數(shù)
是一階連續(xù)可微哼丈。由泰勒展開式得到:
泰勒展開式
選取
迭代方程
其中
r(gamma)
是迭代步長削祈,這就是梯度下降法脑漫。當(dāng)然由于梯度方向是變化最快的放向,取定x的變化方向?yàn)樘荻鹊姆捶较蛴判遥梢员WC迭代速度最快,當(dāng)然這個(gè)算法的缺點(diǎn)就是
- 只使用一階導(dǎo)數(shù)羹饰,迭代的速度較慢,控制好步長及初值队秩,否則可能出現(xiàn)迭代不收斂的情況
- 迭代到靠近極值的時(shí)候,迭代的速度減慢
- 如果函數(shù)不是凸函數(shù)筒主,則很可能只是局部最優(yōu)解鸟蟹,而不是全局最優(yōu)解乌妙。當(dāng)然極值和最值概念建钥,讀者肯定清楚
接下來給一個(gè)例子幫助理解:
考慮函數(shù) f(x) = x^2 -3x + 5此函數(shù)在x=1.5 時(shí)取得最小值為2.75
迭代初值為x(0)=3,迭代步長為r=0.01
f(x) 的梯度即為函數(shù)的導(dǎo)數(shù)df/dx = 2x - 3
x(n + 1) = x(n) - r df/dx =x(n) - h*(2 x(n) - 3)
x(n + 1) = 0.98 x(n) + 0.03
到此為止泽艘,可以通過求解以上數(shù)列的通項(xiàng)公式奈搜,然后求極限得到最終收斂1.5馋吗。在此我使用迭代1000次得到的結(jié)果為x=1.5000000008414838
說明通過求解橫坐標(biāo)的收斂值,最終可以得到函數(shù)的最小值宏粤。
梯度下降法實(shí)現(xiàn)的思路:
- 通過迭代橫坐標(biāo)最終收斂的值,確定函數(shù)取得極值的橫坐標(biāo)来农。
- 迭代前后函數(shù)值的差小于某一個(gè)指定常數(shù)eps崇堰,如|f(x) - f(x0)| < eps,則跳出循環(huán)海诲,否則繼續(xù)迭代方程
下面給出兩種實(shí)現(xiàn)方法的Python代碼
def grad_dec(eps=1e-8, delta=0.001):
"""
:param eps: 函數(shù)值誤差
:param delta: 迭代步長
"""
x0 = 3.0
f = lambda a: a * a - 3.0 * a + 5.0
while True:
x = x0 - delta * (2.0 * x0 - 3.0)
if abs(x - x0) < eps: # 指定橫坐標(biāo)收斂跳出循環(huán)
break
x0 = x
print(x, f(x))
if __name__ == '__main__':
grad_dec()
輸出結(jié)果為:
1.500004984618336 2.7500000000248463
def grad_dec(eps=1e-8, delta=0.001):
"""
:param eps: 函數(shù)值誤差
:param delta: 迭代步長
"""
x = 3.0
f = lambda a: a * a - 3.0 * a + 5.0
while True:
f_start = f(x)
x = x - delta * (2.0 * x - 3.0)
f_end = f(x)
if f_start - f_end < eps:
break
print(x, f(x))
if __name__ == '__main__':
grad_dec()
輸出結(jié)果為:
1.5015783203943125 2.750002491095267
仔細(xì)看程序,及輸出的精度特幔,你會(huì)發(fā)現(xiàn)什么蚯斯?
我是邊學(xué)邊寫筆記饵较,如果寫的不好的地方,請(qǐng)大神指出循诉。(限于markdown輸出LaTeX數(shù)學(xué)公式不是很方便嵌牺,所以給出公式不是很多)