图解深度学习-梯度下降法优化器可视化(SGD, Momentum,Adam, Adagrad and RMSProp)
圖解深度學(xué)習(xí)-梯度下降法優(yōu)化器可視化(SGD, Momentum,Adam, Adagrad and RMSProp
- 前言
 - 定義了4個(gè)基本函數(shù)
 - 機(jī)器學(xué)習(xí)原理
 - 原始的梯度下降算法
 - 帶動(dòng)量的梯度下降算法
 - 帶慣性的梯度下降算法
 - Adagrad 自適應(yīng)調(diào)整的梯度下降
 - RMSProp
 - Adam
 
前言
主要用了Jupyter Notebook的插件ipywidgets,可以進(jìn)行交互,可以自己調(diào)整參數(shù)來(lái)看結(jié)果,用于理解來(lái)說(shuō)非常好,今后也會(huì)繼續(xù)用這些東西來(lái)做圖解深度學(xué)習(xí),主要代碼來(lái)自鏈接,框架是他的,我主要做了點(diǎn)修改,更加方便理解和調(diào)試,可以動(dòng)手改變學(xué)習(xí)率,訓(xùn)練次數(shù)等一些參數(shù),可視化非常友好,當(dāng)然也可以自己改變咯。提供下修改后的jupyter的文件鏈接
%matplotlib inline import numpy as np import matplotlib.pyplot as plt from matplotlib import ticker, cm import seaborn as sns from ipywidgets import * import math#繪圖元素比例 比較小 sns.set_context('paper', font_scale=2) #設(shè)置顯示中文字體 font = {'family' : 'SimHei', # 'weight' : 'bold','size' : '15'} plt.rc('font', **font) # 步驟一(設(shè)置字體的更多屬性) plt.rc('axes', unicode_minus=False) # 步驟二(解決坐標(biāo)軸負(fù)數(shù)的負(fù)號(hào)顯示問(wèn)題)定義了4個(gè)基本函數(shù)
機(jī)器學(xué)習(xí)原理
機(jī)器學(xué)習(xí)是一種新的編程模式。這種模式先假設(shè)任何輸入 x 與輸出 y 之間存在連續(xù)幾何變換,
 其函數(shù)形式可用 y=f(x,θ)y= f(x, \theta)y=f(x,θ) 表示。其中 θ\thetaθ 是函數(shù)參數(shù),初始化為隨機(jī)數(shù)。
 注意,初始化過(guò)程并不任意,這里有一篇很好的文章講參數(shù)初始化
 deeplearning.ai。
機(jī)器學(xué)習(xí)通過(guò)逐步微調(diào)函數(shù)參數(shù) θ\thetaθ的方式,試圖最小化模型預(yù)言 y^\hat{y}y^? 與真實(shí)標(biāo)簽 yyy的差別。
 此差別最簡(jiǎn)單的數(shù)學(xué)表達(dá)式是 MAE 或者 MSE,即
 L(θ)=∣y^?y∣L(\theta) = |\hat{y} - y|L(θ)=∣y^??y∣
 或
 L(θ)=∣y^?y∣2L(\theta) = |\hat{y} - y|^2L(θ)=∣y^??y∣2
為了最小化誤差 L(θ)L(\theta)L(θ), 我們只需要計(jì)算誤差對(duì)參數(shù) θ\thetaθ 的梯度,通過(guò)鏈?zhǔn)揭?guī)則,
 將誤差反向傳遞到 θ\thetaθ, 并使用梯度下降,更新θ\thetaθ 即可。
如果增加 θ\thetaθ, 損失函數(shù) L(θ)L(\theta)L(θ) 增大,那么損失函數(shù)對(duì)參數(shù)θ\thetaθ的梯度為正數(shù), 即 ?θL(θ)>0\nabla_{\theta} L(\theta) > 0?θ?L(θ)>0,
 只要將 θ\thetaθ 減去一個(gè)正數(shù) η??θL(θ)\eta \cdot \nabla_{\theta} L(\theta)η??θ?L(θ) 即可使損失函數(shù)減小。
 其中 η\etaη 是學(xué)習(xí)率 (Learning Rate, 簡(jiǎn)寫(xiě)為 lr),為一個(gè)很小的正數(shù)。
如果增加 θ\thetaθ, 損失函數(shù) L(θ)L(\theta)L(θ) 變小,那么 ?θL(θ)<0\nabla_{\theta} L(\theta) < 0?θ?L(θ)<0,
 將 θ\thetaθ 減去一個(gè)負(fù)數(shù) η??θL\eta \cdot \nabla_{\theta} Lη??θ?L 同樣可使損失函數(shù)減小。
 你發(fā)現(xiàn)無(wú)論梯度是正是負(fù),只要將參數(shù)減去學(xué)習(xí)率乘以梯度,總可以將損失降低。
這就是梯度下降的原理!
接下來(lái)會(huì)以交互式可視化的方式,展示幾種最常用的梯度下降算法。
原始的梯度下降算法
θ=θ?η??θL(θ)\theta = \theta - \eta \cdot \nabla_{\theta} L(\theta)θ=θ?η??θ?L(θ)
#最原始的梯度下降法 def sgd(x1, x2, s1, s2, lr):dfdx1, dfdx2 = f_grad(x1, x2)return (x1 - lr * dfdx1, x2 - lr * dfdx2, 0, 0, lr)#定義了4個(gè)變量控件,可以隨時(shí)調(diào)節(jié),查看效果 (最小值,最大值,步長(zhǎng)) @interact(lr=(0, 1, 0.001),epoch=(0,100,1),init_x1=(-5,5,0.1),init_x2=(-5,5,0.1),continuous_update=False) def visualize_gradient_descent(lr=0.05,epoch=50,init_x1=-4,init_x2=-2.4):res = train_2d(sgd, lr,epoch,init_x1,init_x2)plot_2d(res,(12,8), title='原始SGD')帶動(dòng)量的梯度下降算法
vt=γvt?1+η??θL(θ)v_t = \gamma v_{t-1} + \eta \cdot \nabla_{\theta} L(\theta)vt?=γvt?1?+η??θ?L(θ)
 θ=θ?vt\theta = \theta - v_tθ=θ?vt?
可見(jiàn)下圖。對(duì)以前的梯度做了指數(shù)加權(quán)平均,不會(huì)像原始的那樣直接折線那么厲害,因?yàn)橛兄八俣扔绊?#xff0c;所以瞬間就折,而是會(huì)再向原來(lái)那個(gè)方向前進(jìn)一段距離,也可以理解為對(duì)原始梯度做了一個(gè)平滑,然后再用來(lái)做梯度下降
@interact(lr=(0, 0.99, 0.001), gamma=(0, 0.99, 0.001),continuous_update=False,epoch=(0,100,1),init_x1=(-5,5,0.1),init_x2=(-5,5,0.1)) def visualize_sgd_momentum(lr=0.1, gamma=0.1,epoch=10,init_x1=-4,init_x2=-2.4):'''lr: learning rategamma: parameter for momentum sgd每次都會(huì)根據(jù)上一次的動(dòng)量來(lái)進(jìn)行更新'''def momentum(x1, x2, v1, v2, lr):dfdx1, dfdx2 = f_grad(x1, x2)v1 = gamma * v1 + lr * dfdx1v2 = gamma * v2 + lr * dfdx2x1 = x1 - v1x2 = x2 - v2return (x1, x2, v1, v2, lr)res = train_2d(momentum, lr,epoch,init_x1,init_x2)plot_2d(res, title='momentum')帶慣性的梯度下降算法
vt=γvt?1+(1?γ)??θL(θ)v_t = \gamma v_{t-1} + (1 - \gamma) \cdot \nabla_{\theta} L(\theta)vt?=γvt?1?+(1?γ)??θ?L(θ)
 θ=θ?ηvt\theta = \theta - \eta v_tθ=θ?ηvt?
Adagrad 自適應(yīng)調(diào)整的梯度下降
gt=?θL(θ)g_t = \nabla_{\theta} L(\theta)gt?=?θ?L(θ)
G=∑tgt2G = \sum_{t} g_t^2G=t∑?gt2?
θ=θ?ηG+??gt\theta = \theta - \frac{\eta}{\sqrt{G + \epsilon}} \cdot g_tθ=θ?G+??η??gt?
可以自動(dòng)調(diào)節(jié)學(xué)習(xí)率,但是下降的太快,學(xué)習(xí)率很小,可能導(dǎo)致后期學(xué)不到東西了
 此方法也經(jīng)常用于參數(shù)未標(biāo)準(zhǔn)化時(shí),提供不通的學(xué)習(xí)率,以便于快速到達(dá)最小點(diǎn)
RMSProp
g=?θL(θ)g = \nabla_{\theta} L(\theta) g=?θ?L(θ)
E[g2]=γE[g2]+(1?γ)g2E\left[g^2\right] = \gamma E\left[g^2\right] + (1-\gamma) g^2 E[g2]=γE[g2]+(1?γ)g2
θ=θ?ηE[g2]+??g\theta = \theta - \frac{\eta}{\sqrt{E\left[g^2\right] + \epsilon}} \cdot gθ=θ?E[g2]+??η??g
對(duì)Adagrad做了相應(yīng)修改,讓學(xué)習(xí)率不會(huì)下降了太快導(dǎo)致后期學(xué)不到東西,相當(dāng)于做了歸一化,調(diào)整不同參數(shù)的步長(zhǎng),加快收斂速度
@interact(lr=(0, 4, 0.001), gamma=(0, 0.99, 0.001),continuous_update=False,epoch=(0,100,1),init_x1=(-5,5,0.1),init_x2=(-5,5,0.1)) def visualize_rmsprop(lr=0.1, gamma=0.9,epoch=50,init_x1=-4,init_x2=-4):'''lr: learning rate, gamma: momentum''' def rmsprop_2d(x1, x2, s1, s2, lr):eps = 1e-6g1, g2 = f_grad(x1, x2)s1 = gamma * s1 + (1 - gamma) * g1 ** 2s2 = gamma * s2 + (1 - gamma) * g2 ** 2x1 -= lr / math.sqrt(s1 + eps) * g1x2 -= lr / math.sqrt(s2 + eps) * g2return x1, x2, s1, s2, lrres = train_2d(rmsprop_2d, lr,epoch,init_x1,init_x2)plot_2d(res, title='RMSProp')Adam
g=?θL(θ)g = \nabla_{\theta} L(\theta) g=?θ?L(θ)
m=β1m+(1?β1)gm = \beta_1 m + (1 - \beta_1) g m=β1?m+(1?β1?)g
n=β2n+(1?β2)g2n = \beta_2 n + (1 - \beta_2) g^2 n=β2?n+(1?β2?)g2
m^=m(1?β1t)\hat{m} = \frac{m}{(1 - \beta_1^t)} m^=(1?β1t?)m?
n^=n(1?β2t)\hat{n} = \frac{n}{(1 - \beta_2^t)} n^=(1?β2t?)n?
θ=θ?ηn^+?m^\theta = \theta - \frac{\eta}{\sqrt{\hat{n}} + \epsilon} \hat{m}θ=θ?n^?+?η?m^
結(jié)合Momentum和RMSProp的2個(gè)特征,即做指數(shù)加權(quán)平均,又做歸一化
@interact(lr=(0, 1, 0.001), beta1=(0, 0.999, 0.001),beta2=(0, 0.999, 0.001),continuous_update=False,epoch=(0,100,1),init_x1=(-5,5,0.1),init_x2=(-5,5,0.1)) def visualize_adam(lr=0.1, beta1=0.9, beta2=0.999,epoch=10,init_x1=-4,init_x2=-2.4):'''lr: learning ratebeta1: parameter for E(g)beta2: parameter for E(g^2)''' def Deltax(m, n, g, t):eps = 1.0E-6m = beta1 * m + (1 - beta1) * gn = beta2 * n + (1 - beta2) * g*gm_hat = m / (1 - beta1**t)n_hat = n / (1 - beta2**t)dx = lr * m_hat / (math.sqrt(n_hat) + eps)return m, n, dxdef adam_2d(x1, x2, m1, n1, m2, n2, lr, t):'''m1, m2: E(g1), E(g2)n1, n2: E(g1^2), E(g2^2) where E() is expectationlr: learning ratet: time step'''eps = 1e-6g1, g2 = f_grad(x1, x2)m1, n1, dx1 = Deltax(m1, n1, g1, t)m2, n2, dx2 = Deltax(m2, n2, g2, t) x1 -= dx1x2 -= dx2return x1, x2, m1, n1, m2, n2, lrdef train_adam(trainer, lr,epoch=10,init_x1=-4,init_x2=-4):"""Train a 2d object function with a customized trainer"""x1, x2 = init_x1,init_x2m1, n1, m2, n2 = 0, 0, 0, 0res = [(x1, x2)]for i in range(epoch):x1, x2, m1, n1, m2, n2, lr = trainer(x1, x2, m1, n1, m2, n2, lr, i+1)res.append((x1, x2))return resres = train_adam(adam_2d, lr,epoch,init_x1,init_x2)plot_2d(res, title='adam')好了,今天就到這里了,希望對(duì)學(xué)習(xí)理解有幫助,大神看見(jiàn)勿噴,僅為自己的學(xué)習(xí)理解,能力有限,請(qǐng)多包涵。
總結(jié)
以上是生活随笔為你收集整理的图解深度学习-梯度下降法优化器可视化(SGD, Momentum,Adam, Adagrad and RMSProp)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
                            
                        - 上一篇: React开发(154):注意div得写
 - 下一篇: Julia 排坑指南