機(jī)器學(xué)習(xí)當(dāng)中的數(shù)學(xué)---微分學(xué)部分
關(guān)于無窮小的物理學(xué)遐想
我認(rèn)為無窮小還是很不好理解的淆攻,于是我想到了物理學(xué)上的另外一個類比,也就是牛頓的經(jīng)典力學(xué)和愛因斯坦的相對論。
無窮小的自然語言解釋是鹦倚,當(dāng)自變量x趨向于0的時候,函數(shù)冀惭。但是不同函數(shù)趨于0的速度是不同的震叙,最典型的就是指數(shù)型的函數(shù)比如
就要比
趨于0的速度要快很多,因此
是
的高階無窮小云头,記作
捐友,相應(yīng)的其他函數(shù)的類比也是一樣的。
無窮小與無窮小的比較
如果一個無窮小是另外一個無窮小的高階無窮小溃槐,那么兩者之比就是0匣砖。
其實(shí)兩個無窮小可以認(rèn)為是兩個維度或者說兩個世界的東西,實(shí)際上算術(shù)上的差距并沒有可比性昏滴,就好像我們在牛頓經(jīng)典力學(xué)時空觀下猴鲫,我們的運(yùn)動其實(shí)是相對于光速的極限下是靜止不動的一樣,這里也就是相當(dāng)于那個與
的比較一樣谣殊,
要比
小得太多太多太多了拂共,以至于
在
這個無窮小看來看來也是0帮匾。正如光速比我們快得太多太多太多了黍匾,實(shí)際上那個
與
姑荷,光與我們已經(jīng)不是同一個維度下的東西了稽坤,我們無法理解光在那種速度下會發(fā)生什么事。而同階無窮小伞矩,就像光與其他電磁波一樣温赔,雖然它們快得難以被我們理解巡蘸,但他們是同樣地快络拌,或者說他們的速度的差別是可以被測量俭驮,被常數(shù)化的,所以其實(shí)是相同的級別春贸。
當(dāng)x較小的時候
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
%matplotlib inline
import seaborn as sns
plt.style.use('ggplot')
x=np.linspace(0,20,9)
y=2*x**2+2*x+1
new_x=[i for i in x if x.tolist().index(i)%2==0]
new_y=2*np.array(new_x)**2+2*np.array(new_x)+1
在做任何事情前混萝,一定要明白為什么這么做。這也是為什么學(xué)習(xí)機(jī)器學(xué)習(xí)要從學(xué)習(xí)高等數(shù)學(xué)開始萍恕,這點(diǎn)很重要逸嘀。
因?yàn)闄C(jī)器學(xué)習(xí)本質(zhì)上是一個逼近的問題,我們現(xiàn)在可以回到歐幾里得時代允粤,發(fā)現(xiàn)圓的測量可能沒有工具借助厘熟,幾乎是不可能的屯蹦,但是聰明的哲學(xué)家或者說研究者,他們通過對圓進(jìn)行外接和內(nèi)接绳姨,通過求圓內(nèi)部和外部的多邊形的面積,如果不斷增加邊的數(shù)量阔挠,那么外接和內(nèi)接多邊形就可以不斷逼近圓飘庄,最終三者的面積的極限就是相等的,進(jìn)而求出圓的面積
fig=plt.figure(figsize=(8,8))
ax=fig.add_subplot(1,1,1)
circle1=plt.Circle((0.5, 0.5), 0.2, color='k', fill=False)
ax.add_artist(circle1)
<matplotlib.patches.Circle at 0x1a1738b3c8>
import matplotlib.pyplot as plt
from matplotlib.patches import CirclePolygon
circle = CirclePolygon((0, 0), radius = 0.75, fc = 'y')
plt.gca().add_patch(circle)
verts = circle.get_path().vertices
trans = circle.get_patch_transform()
points = trans.transform(verts)
# print(points)
plt.plot(points[:,0],points[:,1])
plt.axis('scaled')
plt.show()
機(jī)器學(xué)習(xí)當(dāng)中的逼近
低階的線性逼近
plt.plot(x.tolist(),y.tolist())
plt.plot(new_x, new_y, 'b-o')
plt.xlim(0,20)
plt.ylim(0,1000)
plt.show()
fig=plt.figure(figsize=(16,8))
x_s=np.linspace(1,10000,1000)
y_s=np.sin(2*np.pi*x_s)
x_s_new=np.array([i for i in x_s if x_s.tolist().index(i)%20 == 0])
y_s_new=np.sin(2*np.pi*x_s_new)
plt.plot(x_s, y_s)
plt.plot(x_s_new, y_s_new,'b--o')
[<matplotlib.lines.Line2D at 0x1a17821908>]
從上面看到购撼,都是用一些局部的線性函數(shù)去逼近一些復(fù)雜的函數(shù)跪削,這樣子我們就可以用簡單的函數(shù)去近似出復(fù)雜的函數(shù),可以想到迂求,如果點(diǎn)足夠多的話可以無限逼近碾盐。線性方程在該點(diǎn)的值與該復(fù)雜函數(shù)在該點(diǎn)的值是一致的。
這里的是
的高階無窮小揩局,
也就是
毫玖,相當(dāng)于橫坐標(biāo)差,當(dāng)
的時候凌盯,因?yàn)?img class="math-inline" src="https://math.jianshu.com/math?formula=%5Cmathcal%7BO%7D(%5CDelta)" alt="\mathcal{O}(\Delta)" mathimg="1">是
的高階無窮小付枫,因此趨于0的速度要快于前面的線性方程部分,因此
驰怎。
也就是復(fù)雜函數(shù)和線性方程逼近于的這個極限是相同的阐滩,
在非趨近的情況下是個誤差項(xiàng)
高階的線性逼近
上面的是低階的線性逼近,這里的“低階”意思是指只有次數(shù)為1的導(dǎo)數(shù)县忌,我們可以想到后面的導(dǎo)數(shù)部分又可以展開掂榔,所以
進(jìn)行進(jìn)一步的展開,這里進(jìn)行二階的泰勒展開后誤差為的高階無窮小症杏,如果是n階展開的話就是n階無窮小
多元函數(shù)的逼近
from mpl_toolkits import mplot3d
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
def f(x, y):
return x ** 2 + y ** 2
x = np.linspace(-6, 6, 30)
y = np.linspace(-6, 6, 30)
X, Y = np.meshgrid(x, y)
# print(X)
Z = f(X, Y)
Z.shape
(30, 30)
fig = plt.figure()
ax = plt.axes(projection='3d')
ax.plot_surface(X, Y, Z, rstride=1, cstride=1,
cmap='viridis', edgecolor='none')
plt.show()
多元函數(shù)
偏導(dǎo)數(shù)
其實(shí)偏導(dǎo)數(shù)就是装获,對于一個多元函數(shù),比如說二元函數(shù)f(x,y)其沿著坐標(biāo)軸方向上的導(dǎo)數(shù)即為偏導(dǎo)數(shù)鸳慈,沿著x方向上的為x的偏導(dǎo)數(shù)饱溢,在y方向?yàn)閥的偏導(dǎo)數(shù)。表示為:
以上是沿著x軸和y軸方向上的偏導(dǎo)數(shù)走芋,如果是沿著任意一個方向的話绩郎,在該方向上該多元函數(shù)的導(dǎo)數(shù)為
和可以認(rèn)為是
在x軸和y軸方向的一個投影,從x和y的方向上進(jìn)行逼近翁逞。
線性逼近
同樣的肋杖,類似于一元復(fù)雜函數(shù)可以通過一個線性函數(shù)來不斷逼近,多元函數(shù)也可以用一個線性方程來不斷逼近
偏導(dǎo)數(shù)與梯度的關(guān)系
我們上面說過挖函,偏導(dǎo)數(shù)是多元函數(shù)對于x軸和y軸方向上的導(dǎo)數(shù)状植,但是很多時候我們并不是只限定在x軸和y軸方向上求導(dǎo)數(shù),比如v方向,
津畸,那么在v方向上的導(dǎo)數(shù)不叫偏導(dǎo)數(shù)振定,叫梯度,梯度也是在該點(diǎn)處下降最快的方向肉拓。
我們將某點(diǎn)(x, y)x軸的偏導(dǎo)數(shù)和y軸的偏導(dǎo)數(shù)組成一個向量后频,表示為(備注:T表示為列向量的意思)
那么在該點(diǎn)(x, y)朝著某個方向最快下降方向也就是梯度方向,表示為
關(guān)于導(dǎo)數(shù)為什么是下降最快的方向
import seaborn as sns
# def f(x):
# return np.sin(2*np.pi * x)
# x_d=np.linspace(0, 1000, 500)
# y_d=f(x_d)
# x_p=x_d[250]
# y_p=np.sin(2*np.pi * x_p)
# f_der=2*np.pi*np.cos(2*np.pi*x_p)#get the derivatives
# print(f_der)
# tangent_line=y_p+f_der*(x_d-x_p)
# plt.plot(x_d,y_d,'-b',x_p, y_p, 'om', x_d, tangent_line,'--r')
# # plt.plot(x_d,y_d)
# plt.xticks(color='w')
# plt.yticks(color='w')
# plt.ylim(-1,1)
# plt.show()
def f(x): # sample function
return x*np.sin(np.power(x,2))
# evaluation of the function
x = np.linspace(-2,4,150)
y = f(x)
a = 1.4
h = 0.1
fprime = (f(a+h)-f(a))/h # derivative
tan = f(a)+fprime*(x-a) # tangent
larger_tan = f(a)+ -5*(x-a) # larger tangent
print(fprime)
# plot of the function and the tangent
plt.plot(x,y,'b',a,f(a),'om',x,tan,'--r',x,larger_tan, '-g')
plt.xticks(color='white')
plt.yticks(color='white')
plt.show()
-1.2818633377155364
關(guān)于這個問題暖途,我的理解是這樣的卑惜,在圖上那個紅點(diǎn)處,紅色虛線是切線驻售,綠色是絕對值大于切線斜率絕對值的線露久,我們想象成一個點(diǎn)在曲線上快速運(yùn)動,它不能越軌欺栗,否則該點(diǎn)就不算是曲線上的點(diǎn)了毫痕,這樣的話,每個點(diǎn)在曲線上面的最大下降方向只能是切線方向纸巷,如果比切線下降更快镇草,如綠色線,接下來這個點(diǎn)繼續(xù)往綠色方向運(yùn)動瘤旨,哪怕一點(diǎn)點(diǎn)梯啤,都是飛出圖上藍(lán)色的軌道外了,也就不算是曲線上的點(diǎn)了存哲。所以在某一點(diǎn)處因宇,切線方向一定是下降最快的方向
梯度下降法和牛頓法
簡而言之,梯度下降法就是多元函數(shù)的線性逼近祟偷,而牛頓法相當(dāng)于是多元函數(shù)泰勒展開后的n階逼近察滑。(不太明白的可以參考一元函數(shù)的線性逼近和n階逼近)
先修知識 泰勒展開
泰勒展開是關(guān)于某個復(fù)雜函數(shù)在a點(diǎn)處的展開表達(dá)式,對于一個無限可微分函數(shù)
修肠,其在真實(shí)點(diǎn)
處的泰勒展開式為
梯度下降法
梯度下降法相當(dāng)于是對函數(shù)在
這點(diǎn)的線性逼近
梯度下降法并不能告訴我們極小值點(diǎn)在哪贺辰,但是可以告訴我們在這一點(diǎn)下降最快的方向在哪里。然后我們可以以一定的下降速率去更新已有的
值嵌施。這個下降速率就是學(xué)習(xí)率饲化,類似于一個人在完全黑暗之中在山谷里面摸索最低點(diǎn)谷底,那么學(xué)習(xí)率就像是這個人的步伐吗伤,可以一腳邁一大步吃靠,但是很容易邁過頭;同樣足淆,也可以一腳邁一小步巢块,但收斂速度會很慢礁阁。
對于一個數(shù)據(jù)集X來說,其梯度就是所有單個樣本的梯度之和
其中是指樣本i族奢,i從1到n代表X所有的每個樣本姥闭,而
則代表樣本i的梯度
梯度下降根據(jù)對總體樣本的選取不同計(jì)算出選取樣本的梯度,以此樣本計(jì)算出來的梯度作為參數(shù)更新的方向歹鱼,直到梯度為0的時候即為到達(dá)最優(yōu)點(diǎn)泣栈。三種不同的計(jì)算梯度方式:
- 全量梯度下降法
這種方法就是計(jì)算所有樣本的梯度之和,以此作為參數(shù)更新的方向
- 隨機(jī)梯度下降法
這種方法是每次只計(jì)算一個樣本的梯度弥姻,以此作為參數(shù)更新的方向,一般配合學(xué)習(xí)率逐漸降低的方法掺涛,有和全量梯度相似的收斂速度庭敦,好處是可以跳出局部最優(yōu)點(diǎn),有可能找到全局最優(yōu)點(diǎn)
- 小批量隨機(jī)梯度下降法
這種方法也是隨機(jī)抽取樣本薪缆,不同的是秧廉,每次計(jì)算梯度是以每個小樣本的梯度之和作為更新方向,比起隨機(jī)梯度下降法來說好處是更加容易收斂拣帽,受單個樣本波動性更小疼电。
def plot_saddle(x, y):
return x**2 - y**2
from mpl_toolkits import mplot3d
from mpl_toolkits.mplot3d import Axes3D
Z2=plot_saddle(X, Y)
fig = plt.figure()
ax = plt.axes(projection='3d')
ax.plot_surface(X, Y, Z2, rstride=1, cstride=1,
cmap='viridis', edgecolor='none')
plt.show()
plt.contour(X, Y, Z2, 20, cmap='RdGy');
fig = plt.figure()
ax = plt.axes(projection='3d')
ax.plot_surface(X, Y, Z, rstride=1, cstride=1,
cmap='viridis', edgecolor='none')
plt.show()
plt.contour(X, Y, Z, 20, cmap='RdGy');
如何閱讀等高線圖:
- 等高線越密集的地方,說明其斜度越大减拭。
- 等高線包圍的一圈又一圈可能是valley,可能是mountain蔽豺,需要通過等高線的密集變化來看出。
- 從上面可以看出來拧粪,對于低谷來說修陡,其兩側(cè)的等高線由外向內(nèi)梯度越來越小,對于山谷則剛好相反可霎,其梯度越來越大魄鸦,參考再上面一副圖的左右兩邊,鞍形的左右兩邊就各是一座山峰癣朗,中間等高線變緩的就是鞍部拾因。
牛頓法
首先要明白牛頓法是做什么的,它是要找到時候的x值
牛頓法與初始點(diǎn)的選取很有關(guān)系旷余,如果初始點(diǎn)所對應(yīng)的切線斜率為0的話绢记,那么接下來的x值就無法更新。牛頓法的好處是荣暮,比起一階的梯度下降庭惜,其收斂速度會更快。
參考鏈接:https://blog.paperspace.com/intro-to-optimization-momentum-rmsprop-adam/
這個二階導(dǎo)數(shù)是多個變量的求導(dǎo)組合穗酥,其形式如下:
對于兩個變量的情況:
這里的第一行代表先對進(jìn)行求導(dǎo)护赊,再依次對
惠遏,
進(jìn)行二階求導(dǎo),同理第二行也是一樣的對
進(jìn)行相同的操作骏啰。
對于多個變量則有:
牛頓法一個很好地彌補(bǔ)了一階的梯度下降的缺點(diǎn)节吮,一階的梯度下降只能知道當(dāng)前函數(shù)值是下降還是上升以及斜率的絕對值,但并不知道當(dāng)前下降的快慢判耕,也就是不知道目前是否已經(jīng)越來越陡還是越來越緩透绩,而二階導(dǎo)數(shù)可以彌補(bǔ)這個問題
打個比方,就好像如果我們只有一階的信息壁熄,那么我們能知道身處現(xiàn)在的位置帚豪,往哪個方向上是下降的,而且下降得最快草丧,但我們并不知道接下來越來越緩還是越來越陡
牛頓法對多元函數(shù)的二階求導(dǎo)
def newton_func(x):
return x**2 + 2 * x -3
fig=plt.figure()
x_r=np.linspace(-5,1, 600)
y_r= newton_func(x_r)
x_rp=-3
y_rp=0
x_rp2=1
y_rp2=0
plt.plot(x_r, y_r, 'r--', x_rp, y_rp, 'om',x_rp2, y_rp2,'om')
plt.text(x_rp+0.2, y_rp+0.5, 'a')
plt.text(x_rp2+0.1, y_rp2+0.5, 'b')
plt.hlines(y=0,xmin=-5,xmax=1)
plt.xticks(color='w')
plt.yticks(color='w')
(array([-6., -4., -2., 0., 2., 4., 6., 8., 10., 12., 14.]),
<a list of 11 Text yticklabel objects>)
比如在這里有個函數(shù)狸臣,那么牛頓法的目的就是要求出
等于0的時候的x值,也就是a點(diǎn)和b點(diǎn)的對應(yīng)的x(在圖中就是-3和-1)
x_rp3=-4.8
y_rp3=newton_func(x_rp3)
h = 0.1
fprime = (newton_func(x_rp3+h)-newton_func(x_rp3))/h # derivative
xrange=np.linspace(-5, -3, 600)
tan = newton_func(x_rp3)+fprime*(xrange-x_rp3) # tangent
# larger_tan = f(x_rp3)+ -5*(x-x_rp3) # larger tangent
plt.plot(x_r, y_r, 'r--', x_rp, y_rp, 'om',x_rp2, y_rp2,'om',x_rp3, y_rp3,'om', xrange, tan, 'g--')
plt.text(x_rp+0.2, y_rp+0.5, 'a')
plt.text(x_rp2+0.1, y_rp2+0.5, 'b')
plt.text(x_rp3+0.1, y_rp3+0.5, 'c')
plt.hlines(y=0,xmin=-5,xmax=1)
plt.vlines(x=x_rp3,ymin=-4, ymax=12,linestyles='dashed',color='blue')
plt.xticks(color='w')
plt.yticks(color='w')
(array([-6., -4., -2., 0., 2., 4., 6., 8., 10., 12., 14.]),
<a list of 11 Text yticklabel objects>)
牛頓法就是通過不斷更新某個點(diǎn)的切線與x軸相交的點(diǎn)昌执,從而不斷逼近f(x)=0時候的x值
比如我們選c點(diǎn)(x1, y1)作為起始點(diǎn)烛亦,做切線,跟x軸會有交點(diǎn)懂拾,這個時候這個交點(diǎn)對應(yīng)的x在曲線上面的點(diǎn)為x2煤禽,這個時候x2比x1接近了a點(diǎn),繼續(xù)做(x2, y2)的切線岖赋,重復(fù)以上的步驟檬果,直到找到xn對應(yīng)的f(x_n)無限接近于0,x_n無限接近于a點(diǎn)的橫坐標(biāo)贾节,這就是牛頓法汁汗。而在求損失函數(shù)的時候我們想要找到一階導(dǎo)數(shù)為0的,用的函數(shù)是一階導(dǎo)數(shù)栗涂,而對應(yīng)的切線斜率則是二階導(dǎo)數(shù)
關(guān)于梯度下降法和牛頓法的直觀區(qū)別
關(guān)于梯度下降法知牌,我認(rèn)為一個直觀的解釋就是,像是下山的時候總是在每走一步就看一下周圍斤程,朝著下降最快的方向進(jìn)行更新角寸,直到梯度為0,那么就不再更新忿墅,因?yàn)?img class="math-inline" src="https://math.jianshu.com/math?formula=%5Ctheta_n%3D%5Ctheta_%7Bn-1%7D-%5Ceta%C2%B7%5Cnabla%20J(%5Ctheta_%7Bn-1%7D)%3D%5Ctheta_%7Bn-1%7D-0%3D%5Ctheta_%7Bn-1%7D" alt="\theta_n=\theta_{n-1}-\eta·\nabla J(\theta_{n-1})=\theta_{n-1}-0=\theta_{n-1}" mathimg="1">扁藕。
對于牛頓法,它的目標(biāo)則不一樣疚脐,它是通過二階梯度來不斷以當(dāng)前點(diǎn)x以及梯度
來計(jì)算出當(dāng)前點(diǎn)的切線與x軸的交點(diǎn)亿柑,這個交點(diǎn)越來越逼近于極小值點(diǎn),直到梯度
無限接近于0棍弄,更新的方式是
望薄。在這個過程中疟游,二階梯度
其實(shí)可以描繪出一階梯度的變化,也就是山的斜率是越來越陡還是越來越緩痕支,從而相應(yīng)地去調(diào)節(jié)學(xué)習(xí)率(每次的更新的步伐大邪渑啊),而一階梯度相對于二階梯度卧须,它只能告訴我們現(xiàn)在是下山還是上山另绩,這個坡的斜率是多少(有多陡),而并不能告訴我們是越來越緩花嘶,還是越來越陡笋籽,自然也就無法自適應(yīng)學(xué)習(xí)率了。
為什么機(jī)器學(xué)習(xí)中不多使用牛頓法
主要是因?yàn)榕nD法要求二階導(dǎo)數(shù)椭员,而對于多個變量來說干签,求二階導(dǎo)數(shù)是一個交叉組合的形式,比如對于兩個變量,
其函數(shù)
的二階梯度是一個
的矩陣拆撼,而n個則是
,對于有多個特征的情況下喘沿,這種計(jì)算是指數(shù)型地增長
動量法
參考鏈接:https://towardsdatascience.com/stochastic-gradient-descent-with-momentum-a84097641a5d
動量法的出現(xiàn)其實(shí)是因?yàn)閿?shù)據(jù)點(diǎn)有很多噪音闸度,我們希望能夠讓權(quán)重在通過這些數(shù)據(jù)點(diǎn)計(jì)算出損失函數(shù)梯度下降的時候能夠把握好大方向,而減少噪聲對梯度更新方向的干擾蚜印。
動量法的梯度更新方式如下:
t代表在數(shù)據(jù)點(diǎn)t的時候莺禁,代表對前面的t-1個數(shù)據(jù)點(diǎn)進(jìn)行動量法更新后的序列,
是原始的數(shù)據(jù)點(diǎn)窄赋,相當(dāng)于每次更新的時候都會保留之前的余勢哟冬,這樣可以減少單個數(shù)據(jù)點(diǎn)的噪聲的影響。
def cos(x):
return np.cos(x)
np.random.randn()
y_noi
array([-2.49084187, -2.44073906, -2.35054648, -2.22411117, -2.06682606,
-1.88539995, -1.68757134, -1.48177834, -1.27679879, -1.08137583,
-0.90384497, -0.75177856, -0.63166279, -0.54862105, -0.50619538,
-0.50619538, -0.54862105, -0.63166279, -0.75177856, -0.90384497,
-1.08137583, -1.27679879, -1.48177834, -1.68757134, -1.88539995,
-2.06682606, -2.22411117, -2.35054648, -2.44073906, -2.49084187])
x_noi=np.linspace(-3, 3, 500)
y_noi=cos(x_noi) + np.random.randn(len(x_noi))*0.2
plt.plot(x_noi, y_noi, 'om', x_noi,cos(x_noi),'-r')
plt.legend(['a','b'])
<matplotlib.legend.Legend at 0x1a15698390>
計(jì)算前面原始序列的加和
y_t = 0
s_t=[]
for i in range(len(y_noi)):
y_t = y_t + y_noi[i]
s_t.append(y_t)
計(jì)算平均后的序列
v_t = 0
v_new = []
for i in range(len(y_noi)):
v_t = 0.9 * v_t + (1 - 0.9) * y_noi[i]
v_new.append(v_t)
def plot_beta(beta):
v_t = 0
v_new = []
for i in range(len(y_noi)):
v_t = beta * v_t + (1 - beta) * y_noi[i]
v_new.append(v_t)
return v_new
plt.figure(figsize=(10, 5))
x_noi=np.linspace(-3, 3, 500)
y_noi=cos(x_noi) + np.random.randn(len(x_noi))*0.2
plt.plot(x_noi, y_noi, 'om', x_noi,cos(x_noi),'-r')
plt.plot(x_noi,plot_beta(0.5), color='green', marker='o', linewidth=2)
plt.plot(x_noi,plot_beta(0.9), color='blue', marker='o', linewidth=2)
plt.plot(x_noi,plot_beta(0.98), color='yellow', marker='o', linewidth=2)
plt.legend(['point', 'original function', 'beta=0.5', 'beta=0.9', 'beta=0.98'], loc='upper right')
plt.show()
如圖是對不同beta進(jìn)行求和的結(jié)果忆绰,動量法在每次更新梯度的的時候都有兩部分組成浩峡,一個是前面的余量,也就是,beta從直覺上來說可以認(rèn)為是在計(jì)算梯度更新的時候?qū)η懊鏀?shù)據(jù)點(diǎn)的余勢的權(quán)重错敢,而
則是對當(dāng)前數(shù)據(jù)點(diǎn)的權(quán)重翰灾,因此減少了單個數(shù)據(jù)點(diǎn)對梯度更新方向的波動的影響,變得更加穩(wěn)健稚茅,從上面可以看出來纸淮,隨著
值越來越大,曲線越來越光滑亚享,但是會有偏移咽块。
在損失函數(shù)的更新公式當(dāng)中表現(xiàn)為:
總體上看,既保留了前面數(shù)據(jù)點(diǎn)的余勢(也就是它們的梯度欺税,包括方向和大谐藁Α)揭璃,另外一方面也有當(dāng)前點(diǎn)的梯度。由這兩部分組成峭竣。物理上看像是推動一個很重的鐵球下山塘辅,因?yàn)殍F球保持了下山的方向,所以鐵球向左右兩側(cè)的振蕩會越來越少皆撩,兩側(cè)就是非函數(shù)方向扣墩,也就是噪聲。
Nesterov accelerated gradient(動量法的改進(jìn)算法)
動量法的問題在于隨著后面的不斷疊加扛吞,余勢會越來越大呻惕,那么我們希望當(dāng)損失函數(shù)的梯度接近于0的時候,能夠減小學(xué)習(xí)率滥比。要做到這一點(diǎn)亚脆,我們可以通過使用下一步的損失函數(shù)梯度。公式如下:
這樣可以提早預(yù)知下一步的梯度盲泛,從而盡早進(jìn)行剎車濒持,也就是減小步伐,減小學(xué)習(xí)率寺滚。
Adagrad算法
Adagrad是一種自動調(diào)整學(xué)習(xí)率的辦法柑营,這種調(diào)整包括對于每一步的學(xué)習(xí)率,以及不同參數(shù)的學(xué)習(xí)率都不同:
- 隨著模型的訓(xùn)練村视,學(xué)習(xí)率會逐漸衰減官套。
- 對于更新參數(shù)比較頻繁的變量,學(xué)習(xí)率會比較大蚁孔。
- 對于更新參數(shù)比較緩慢的變量奶赔,學(xué)習(xí)率比較小。
實(shí)現(xiàn)原理
這里實(shí)現(xiàn)原理主要是從歷史上的更新梯度疊加組合成一個歷史梯度的矩陣杠氢,并取對角線上面的組合值作為下一次更新的懲罰參數(shù)站刑。
梯度:
梯度歷史矩陣:
為對角矩陣,上面的元素
參數(shù)更新:
在這里i是代表第幾個特征,t是代表第t次更新修然,對角矩陣上面的元素是前面到現(xiàn)在的梯度的疊加笛钝,如果疊加越多,相應(yīng)學(xué)習(xí)率就會越小愕宋,更新也會放慢
AdaDelta(Adagrad的改進(jìn)算法)
AdaDelta解決了Adagrad學(xué)習(xí)率衰減過快的問題玻靡,因?yàn)榉帜敢恢倍际乔懊娴睦奂樱珹daDelta則是將分母從前面的歷史梯度的全部累加改成了歷史的移動平均值中贝。
同時之前說的Adagrad和其他梯度算法沒有解決一個問題是參數(shù)的單位和梯度的單位并不是一致的囤捻,因此AdaDelta進(jìn)一步把學(xué)習(xí)率改成了前面的參數(shù)更新的移動平均值。更新后結(jié)果如下:
Adam(基于AdaDelta進(jìn)行改進(jìn)的算法)
AdaDelta是對二階矩(也就是下面的梯度的平方求移動平均值)邻寿,而Adam則是更進(jìn)一步蝎土,對
也進(jìn)行一階的求移動平均值视哑。更新公式如下:
結(jié)論
究竟如何選擇算法呢?
? 動量法與Nesterov的改進(jìn)方法著重解決目標(biāo)函數(shù)圖像崎嶇的問題
? Adagrad與Adadelta主要解決學(xué)習(xí)率更新的問題
? Adam集中了前述兩種做法的主要優(yōu)點(diǎn)