參考伯禹學習平台《動手學深度學習》課程内容内容撰寫的學習筆記
原文連結:https://www.boyuai.com/elites/course/cZu18YmweLv10OeV/jupyter/6X2EcSYKYpTDlzAKwQhNi
感謝伯禹平台,Datawhale,和鲸,AWS給我們提供的免費學習機會!!
總的學習感受:伯禹的課程做的很好,課程非常系統,每個較進階别的課程都會有需要掌握的前續基礎知識的介紹,是以很适合本人這種基礎較差的同學學習,建議基礎較差的同學可以關注伯禹的其他課程:
數學基礎:https://www.boyuai.com/elites/course/D91JM0bv72Zop1D3
機器學習基礎:https://www.boyuai.com/elites/course/5ICEBwpbHVwwnK3C
主要内容:
批量歸一化(BatchNormalization)和殘差網絡
凸優化
梯度下降
1、 批量歸一化(BatchNormalization)和殘差網絡
批量歸一化(BatchNormalization)
對輸入的标準化(淺層模型)
處理後的任意一個特征在資料集中所有樣本上的均值為0、标準差為1。
标準化處理輸入資料使各個特征的分布相近
批量歸一化(深度模型)
利用小批量上的均值和标準差,不斷調整神經網絡中間輸出,進而使整個神經網絡在各層的中間輸出的數值更穩定。
本質上是标準化資料的處理
1.對全連接配接層做批量歸一化
位置:全連接配接層中的仿射變換和激活函數之間。
全連接配接:
x = W u + b o u t p u t = ϕ ( x ) \boldsymbol{x} = \boldsymbol{W\boldsymbol{u} + \boldsymbol{b}} \\ output =\phi(\boldsymbol{x}) x=Wu+boutput=ϕ(x)
批量歸一化(均值為0标準差為1):
o u t p u t = ϕ ( BN ( x ) ) output=\phi(\text{BN}(\boldsymbol{x})) output=ϕ(BN(x))
y ( i ) = BN ( x ( i ) ) \boldsymbol{y}^{(i)} = \text{BN}(\boldsymbol{x}^{(i)}) y(i)=BN(x(i))
μ B ← 1 m ∑ i = 1 m x ( i ) , \boldsymbol{\mu}_\mathcal{B} \leftarrow \frac{1}{m}\sum_{i = 1}^{m} \boldsymbol{x}^{(i)}, μB←m1i=1∑mx(i),
σ B 2 ← 1 m ∑ i = 1 m ( x ( i ) − μ B ) 2 , \boldsymbol{\sigma}_\mathcal{B}^2 \leftarrow \frac{1}{m} \sum_{i=1}^{m}(\boldsymbol{x}^{(i)} - \boldsymbol{\mu}_\mathcal{B})^2, σB2←m1i=1∑m(x(i)−μB)2,
x ^ ( i ) ← x ( i ) − μ B σ B 2 + ϵ , \hat{\boldsymbol{x}}^{(i)} \leftarrow \frac{\boldsymbol{x}^{(i)} - \boldsymbol{\mu}_\mathcal{B}}{\sqrt{\boldsymbol{\sigma}_\mathcal{B}^2 + \epsilon}}, x^(i)←σB2+ϵ
x(i)−μB,
這⾥ϵ > 0是個很小的常數,保證分母大于0
y ( i ) ← γ ⊙ x ^ ( i ) + β . {\boldsymbol{y}}^{(i)} \leftarrow \boldsymbol{\gamma} \odot \hat{\boldsymbol{x}}^{(i)} + \boldsymbol{\beta}. y(i)←γ⊙x^(i)+β.
引入可學習參數:拉伸參數γ和偏移參數β。若 γ = σ B 2 + ϵ \boldsymbol{\gamma} = \sqrt{\boldsymbol{\sigma}_\mathcal{B}^2 + \epsilon} γ=σB2+ϵ
和 β = μ B \boldsymbol{\beta} = \boldsymbol{\mu}_\mathcal{B} β=μB,批量歸一化無效。
m*d
2.對卷積層做批量歸⼀化
位置:卷積計算之後、應⽤激活函數之前。
如果卷積計算輸出多個通道,我們需要對這些通道的輸出分别做批量歸一化,且每個通道都擁有獨立的拉伸和偏移參數。
計算:對單通道,batchsize=m,卷積計算輸出=pxq
對該通道中m×p×q個元素同時做批量歸一化,使用相同的均值和方差。mcp*q
3.預測時的批量歸⼀化
訓練:以batch為機關,對每個batch計算均值和方差。
預測:用移動平均估算整個訓練資料集的樣本均值和方差。
從零實作
殘差網絡(ResNet)
(何凱明2015imagenet圖像識别賽裡奪魁)
深度學習的問題:深度CNN網絡達到一定深度後再一味地增加層數并不能帶來進一步地分類性能提高,反而會招緻網絡收斂變得更慢,準确率也變得更差。
殘差塊(Residual Block)
恒等映射:
左邊:f(x)=x
右邊:f(x)-x=0 (易于捕捉恒等映射的細微波動)
在殘差塊中,輸⼊x可通過跨層的資料線路更快 地向前傳播。 并沒有對層做改變。
ResNet模型
卷積(64,7x7,3)
批量一體化
最大池化(3x3,2)
殘差塊x4 (通過步幅為2的殘差塊在每個子產品之間減小高和寬)
全局平均池化
全連接配接
稠密連接配接網絡(DenseNet)
用connect連結 A的通道數和B的通道數相加
###主要構模組化塊:
稠密塊(dense block): 定義了輸入和輸出是如何連結的。
過渡層(transition layer):用來控制通道數,使之不過大。
稠密塊
A inchannels 與B outchannels連結 輸出inchannels+outchannels,在給Ainchannels+outchannels,循環
過渡層
1 × 1 1\times1 1×1卷積層:來減小通道數
步幅為2的平均池化層:減半高和寬
減小模型複雜度
2、凸優化
優化與估計
盡管優化方法可以最小化深度學習中的損失函數值,但本質上優化方法達到的目标與深度學習的目标并不相同。
- 優化方法目标:訓練集損失函數值
- 深度學習目标:測試集損失函數值(泛化性)
-
優化在深度學習中的挑戰
- 局部最小值
-
鞍點
(對所有自變量一階偏導數都為0,且Hessian矩陣特征值有正有負的點)
- 梯度消失
局部最小值
f ( x ) = x cos π x f(x) = x\cos \pi x f(x)=xcosπx
鞍點
梯度為0
e.g. Hessian矩陣
A = [ ∂ 2 f ∂ x 1 2 ∂ 2 f ∂ x 1 ∂ x 2 ⋯ ∂ 2 f ∂ x 1 ∂ x n ∂ 2 f ∂ x 2 ∂ x 1 ∂ 2 f ∂ x 2 2 ⋯ ∂ 2 f ∂ x 2 ∂ x n ⋮ ⋮ ⋱ ⋮ ∂ 2 f ∂ x n ∂ x 1 ∂ 2 f ∂ x n ∂ x 2 ⋯ ∂ 2 f ∂ x n 2 ] A=\left[\begin{array}{cccc}{\frac{\partial^{2} f}{\partial x_{1}^{2}}} & {\frac{\partial^{2} f}{\partial x_{1} \partial x_{2}}} & {\cdots} & {\frac{\partial^{2} f}{\partial x_{1} \partial x_{n}}} \\ {\frac{\partial^{2} f}{\partial x_{2} \partial x_{1}}} & {\frac{\partial^{2} f}{\partial x_{2}^{2}}} & {\cdots} & {\frac{\partial^{2} f}{\partial x_{2} \partial x_{n}}} \\ {\vdots} & {\vdots} & {\ddots} & {\vdots} \\ {\frac{\partial^{2} f}{\partial x_{n} \partial x_{1}}} & {\frac{\partial^{2} f}{\partial x_{n} \partial x_{2}}} & {\cdots} & {\frac{\partial^{2} f}{\partial x_{n}^{2}}}\end{array}\right] A=⎣⎢⎢⎢⎢⎢⎡∂x12∂2f∂x2∂x1∂2f⋮∂xn∂x1∂2f∂x1∂x2∂2f∂x22∂2f⋮∂xn∂x2∂2f⋯⋯⋱⋯∂x1∂xn∂2f∂x2∂xn∂2f⋮∂xn2∂2f⎦⎥⎥⎥⎥⎥⎤
梯度消失
凸性 (Convexity)
凸函數的性質對研究損失函數的優化問題是有一定幫助的,局部最小值點的區域展現出凸函數的特征(盡管整個函數并不是凸函數)
集合
對于一個集合内的任意兩點,如果這兩點的連線的所有點都在這個集合内,那麼這個集合就是凸集合。
1、不是凸集合,2/3/4/5是凸集合、兩個凸集合的交集是凸集合6,并一定是凸集合7
Jensen 不等式
函數值的期望大于期望的函數值
∑ i α i f ( x i ) ≥ f ( ∑ i α i x i ) and E x [ f ( x ) ] ≥ f ( E x [ x ] ) \sum_{i} \alpha_{i} f\left(x_{i}\right) \geq f\left(\sum_{i} \alpha_{i} x_{i}\right) \text { and } E_{x}[f(x)] \geq f\left(E_{x}[x]\right) i∑αif(xi)≥f(i∑αixi) and Ex[f(x)]≥f(Ex[x])
性質
- 無局部極小值
- 與凸集的關系
-
二階條件
4.
凸函數與二階導數
f ′ ′ ( x ) ≥ 0 ⟺ f ( x ) f^{''}(x) \ge 0 \Longleftrightarrow f(x) f′′(x)≥0⟺f(x) 是凸函數
必要性 ( ⇐ \Leftarrow ⇐):
對于凸函數:
1 2 f ( x + ϵ ) + 1 2 f ( x − ϵ ) ≥ f ( x + ϵ 2 + x − ϵ 2 ) = f ( x ) \frac{1}{2} f(x+\epsilon)+\frac{1}{2} f(x-\epsilon) \geq f\left(\frac{x+\epsilon}{2}+\frac{x-\epsilon}{2}\right)=f(x) 21f(x+ϵ)+21f(x−ϵ)≥f(2x+ϵ+2x−ϵ)=f(x)
故:
f ′ ′ ( x ) = lim ε → 0 f ( x + ϵ ) − f ( x ) ϵ − f ( x ) − f ( x − ϵ ) ϵ ϵ f^{\prime \prime}(x)=\lim _{\varepsilon \rightarrow 0} \frac{\frac{f(x+\epsilon) - f(x)}{\epsilon}-\frac{f(x) - f(x-\epsilon)}{\epsilon}}{\epsilon} f′′(x)=ε→0limϵϵf(x+ϵ)−f(x)−ϵf(x)−f(x−ϵ)
f ′ ′ ( x ) = lim ε → 0 f ( x + ϵ ) + f ( x − ϵ ) − 2 f ( x ) ϵ 2 ≥ 0 f^{\prime \prime}(x)=\lim _{\varepsilon \rightarrow 0} \frac{f(x+\epsilon)+f(x-\epsilon)-2 f(x)}{\epsilon^{2}} \geq 0 f′′(x)=ε→0limϵ2f(x+ϵ)+f(x−ϵ)−2f(x)≥0
充分性 ( ⇒ \Rightarrow ⇒):
令 a < x < b a < x < b a<x<b 為 f ( x ) f(x) f(x) 上的三個點,由拉格朗日中值定理:
f ( x ) − f ( a ) = ( x − a ) f ′ ( α ) for some α ∈ [ a , x ] and f ( b ) − f ( x ) = ( b − x ) f ′ ( β ) for some β ∈ [ x , b ] \begin{array}{l}{f(x)-f(a)=(x-a) f^{\prime}(\alpha) \text { for some } \alpha \in[a, x] \text { and }} \\ {f(b)-f(x)=(b-x) f^{\prime}(\beta) \text { for some } \beta \in[x, b]}\end{array} f(x)−f(a)=(x−a)f′(α) for some α∈[a,x] and f(b)−f(x)=(b−x)f′(β) for some β∈[x,b]
根據單調性,有 f ′ ( β ) ≥ f ′ ( α ) f^{\prime}(\beta) \geq f^{\prime}(\alpha) f′(β)≥f′(α), 故:
f ( b ) − f ( a ) = f ( b ) − f ( x ) + f ( x ) − f ( a ) = ( b − x ) f ′ ( β ) + ( x − a ) f ′ ( α ) ≥ ( b − a ) f ′ ( α ) \begin{aligned} f(b)-f(a) &=f(b)-f(x)+f(x)-f(a) \\ &=(b-x) f^{\prime}(\beta)+(x-a) f^{\prime}(\alpha) \\ & \geq(b-a) f^{\prime}(\alpha) \end{aligned} f(b)−f(a)=f(b)−f(x)+f(x)−f(a)=(b−x)f′(β)+(x−a)f′(α)≥(b−a)f′(α)
限制條件
minimize x f ( x ) subject to c i ( x ) ≤ 0 for all i ∈ { 1 , … , N } \begin{array}{l}{\underset{\mathbf{x}}{\operatorname{minimize}} f(\mathbf{x})} \\ {\text { subject to } c_{i}(\mathbf{x}) \leq 0 \text { for all } i \in\{1, \ldots, N\}}\end{array} xminimizef(x) subject to ci(x)≤0 for all i∈{1,…,N}
拉格朗日乘子法
Boyd & Vandenberghe, 2004
L ( x , α ) = f ( x ) + ∑ i α i c i ( x ) where α i ≥ 0 L(\mathbf{x}, \alpha)=f(\mathbf{x})+\sum_{i} \alpha_{i} c_{i}(\mathbf{x}) \text { where } \alpha_{i} \geq 0 L(x,α)=f(x)+i∑αici(x) where αi≥0
懲罰項
欲使 c i ( x ) ≤ 0 c_i(x) \leq 0 ci(x)≤0, 将項 α i c i ( x ) \alpha_ic_i(x) αici(x) 加入目标函數,如多層感覺機章節中的 λ 2 ∣ ∣ w ∣ ∣ 2 \frac{\lambda}{2} ||w||^2 2λ∣∣w∣∣2
投影
Proj X ( x ) = argmin x ′ ∈ X ∥ x − x ′ ∥ 2 \operatorname{Proj}_{X}(\mathbf{x})=\underset{\mathbf{x}^{\prime} \in X}{\operatorname{argmin}}\left\|\mathbf{x}-\mathbf{x}^{\prime}\right\|_{2} ProjX(x)=x′∈Xargmin∥x−x′∥2
3、 梯度下降
(Boyd & Vandenberghe, 2004)
一維梯度下降
證明:沿梯度反方向移動自變量可以減小函數值
泰勒展開:
f ( x + ϵ ) = f ( x ) + ϵ f ′ ( x ) + O ( ϵ 2 ) f(x+\epsilon)=f(x)+\epsilon f^{\prime}(x)+\mathcal{O}\left(\epsilon^{2}\right) f(x+ϵ)=f(x)+ϵf′(x)+O(ϵ2)
代入沿梯度方向的移動量 η f ′ ( x ) \eta f^{\prime}(x) ηf′(x):
f ( x − η f ′ ( x ) ) = f ( x ) − η f ′ 2 ( x ) + O ( η 2 f ′ 2 ( x ) ) f\left(x-\eta f^{\prime}(x)\right)=f(x)-\eta f^{\prime 2}(x)+\mathcal{O}\left(\eta^{2} f^{\prime 2}(x)\right) f(x−ηf′(x))=f(x)−ηf′2(x)+O(η2f′2(x))
f ( x − η f ′ ( x ) ) ≲ f ( x ) f\left(x-\eta f^{\prime}(x)\right) \lesssim f(x) f(x−ηf′(x))≲f(x)
x ← x − η f ′ ( x ) x \leftarrow x-\eta f^{\prime}(x) x←x−ηf′(x)
e.g.
f ( x ) = x 2 f(x) = x^2 f(x)=x2
def f(x):
return x**2 # Objective function
def gradf(x):
return 2 * x # Its derivative
def gd(eta):
x = 10 #初值
results = [x]
for i in range(10):
x -= eta * gradf(x)
results.append(x)
print(‘epoch 10, x:’, x)
return results
res = gd(0.2)
def show_trace(res):
n = max(abs(min(res)), abs(max(res)))
f_line = np.arange(-n, n, 0.01)
d2l.set_figsize((3.5, 2.5))
d2l.plt.plot(f_line, [f(x) for x in f_line],’-’)
d2l.plt.plot(res, [f(x) for x in res],’-o’)
d2l.plt.xlabel(‘x’)
d2l.plt.ylabel(‘f(x)’)
show_trace(res)
學習率
show_trace(gd(0.05))
show_trace(gd(1.1))
局部極小值
e.g.
f ( x ) = x cos c x f(x) = x\cos cx f(x)=xcoscx
c = 0.15 * np.pi
def f(x):
return x * np.cos(c * x)
def gradf(x):
return np.cos(c * x) - c * x * np.sin(c * x)
show_trace(gd(2)) #學習率過大導緻
多元梯度下降
def train_2d(trainer, steps=20):
x1, x2 = -5, -2
results = [(x1, x2)]
for i in range(steps):
x1, x2 = trainer(x1, x2)
results.append((x1, x2))
print(‘epoch %d, x1 %f, x2 %f’ % (i + 1, x1, x2))
return results
def show_trace_2d(f, results):
d2l.plt.plot(*zip(*results), ‘-o’, color=’#ff7f0e’)
x1, x2 = np.meshgrid(np.arange(-5.5, 1.0, 0.1), np.arange(-3.0, 1.0, 0.1))
d2l.plt.contour(x1, x2, f(x1, x2), colors=’#1f77b4’)
d2l.plt.xlabel(‘x1’)
d2l.plt.ylabel(‘x2’)
f ( x ) = x 1 2 + 2 x 2 2 f(x) = x_1^2 + 2x_2^2 f(x)=x12+2x22
eta = 0.1
def f_2d(x1, x2): # 目标函數
return x1 ** 2 + 2 * x2 ** 2
def gd_2d(x1, x2):
return (x1 - eta * 2 * x1, x2 - eta * 4 * x2)
show_trace_2d(f_2d, train_2d(gd_2d))
自适應方法
牛頓法
(自動調整學習率),實際應用中,由于速度太慢,可能用的少,但可以給我們提供一種思路。
高中的時候,牛頓法求根,很相似。
在 x + ϵ x + \epsilon x+ϵ 處泰勒展開:
f ( x + ϵ ) = f ( x ) + ϵ ⊤ ∇ f ( x ) + 1 2 ϵ ⊤ ∇ ∇ ⊤ f ( x ) ϵ + O ( ∥ ϵ ∥ 3 ) f(\mathbf{x}+\epsilon)=f(\mathbf{x})+\epsilon^{\top} \nabla f(\mathbf{x})+\frac{1}{2} \epsilon^{\top} \nabla \nabla^{\top} f(\mathbf{x}) \epsilon+\mathcal{O}\left(\|\epsilon\|^{3}\right) f(x+ϵ)=f(x)+ϵ⊤∇f(x)+21ϵ⊤∇∇⊤f(x)ϵ+O(∥ϵ∥3)
最小值點處滿足: ∇ f ( x ) = 0 \nabla f(\mathbf{x})=0 ∇f(x)=0, 即我們希望 ∇ f ( x + ϵ ) = 0 \nabla f(\mathbf{x} + \epsilon)=0 ∇f(x+ϵ)=0, 對上式關于 ϵ \epsilon ϵ 求導,忽略高階無窮小,有:
∇ f ( x ) + H f ϵ = 0 and hence ϵ = − H f − 1 ∇ f ( x ) \nabla f(\mathbf{x})+\boldsymbol{H}_{f} \boldsymbol{\epsilon}=0 \text { and hence } \epsilon=-\boldsymbol{H}_{f}^{-1} \nabla f(\mathbf{x}) ∇f(x)+Hfϵ=0 and hence ϵ=−Hf−1∇f(x)
c = 0.5
def f(x):
return np.cosh(c * x) # Objective
def gradf(x):
return c * np.sinh(c * x) # Derivative
def hessf(x):
return c**2 * np.cosh(c * x) # Hessian
Hide learning rate for now
def newton(eta=1):
x = 10
results = [x]
for i in range(10):
x -= eta * gradf(x) / hessf(x)
results.append(x)
print(‘epoch 10, x:’, x)
return results
show_trace(newton())
c = 0.15 * np.pi
def f(x):
return x * np.cos(c * x)
def gradf(x):
return np.cos(c * x) - c * x * np.sin(c * x)
def hessf(x):
return - 2 * c * np.sin(c * x) - x * c**2 * np.cos(c * x)
show_trace(newton()) #錯誤,預設學習率1
show_trace(newton(0.5))
收斂性分析
隻考慮在函數為凸函數, 且最小值點上 f ′ ′ ( x ∗ ) > 0 f''(x^*) > 0 f′′(x∗)>0 時的收斂速度:
令 x k x_k xk 為第 k k k 次疊代後 x x x 的值, e k : = x k − x ∗ e_{k}:=x_{k}-x^{*} ek:=xk−x∗ 表示 x k x_k xk 到最小值點 x ∗ x^{*} x∗ 的距離,由 f ′ ( x ∗ ) = 0 f'(x^{*}) = 0 f′(x∗)=0:
0 = f ′ ( x k − e k ) = f ′ ( x k ) − e k f ′ ′ ( x k ) + 1 2 e k 2 f ′ ′ ′ ( ξ k ) for some ξ k ∈ [ x k − e k , x k ] 0=f^{\prime}\left(x_{k}-e_{k}\right)=f^{\prime}\left(x_{k}\right)-e_{k} f^{\prime \prime}\left(x_{k}\right)+\frac{1}{2} e_{k}^{2} f^{\prime \prime \prime}\left(\xi_{k}\right) \text{for some } \xi_{k} \in\left[x_{k}-e_{k}, x_{k}\right] 0=f′(xk−ek)=f′(xk)−ekf′′(xk)+21ek2f′′′(ξk)for some ξk∈[xk−ek,xk]
兩邊除以 f ′ ′ ( x k ) f''(x_k) f′′(xk), 有:
e k − f ′ ( x k ) / f ′ ′ ( x k ) = 1 2 e k 2 f ′ ′ ′ ( ξ k ) / f ′ ′ ( x k ) e_{k}-f^{\prime}\left(x_{k}\right) / f^{\prime \prime}\left(x_{k}\right)=\frac{1}{2} e_{k}^{2} f^{\prime \prime \prime}\left(\xi_{k}\right) / f^{\prime \prime}\left(x_{k}\right) ek−f′(xk)/f′′(xk)=21ek2f′′′(ξk)/f′′(xk)
代入更新方程 x k + 1 = x k − f ′ ( x k ) / f ′ ′ ( x k ) x_{k+1} = x_{k} - f^{\prime}\left(x_{k}\right) / f^{\prime \prime}\left(x_{k}\right) xk+1=xk−f′(xk)/f′′(xk), 得到:
x k − x ∗ − f ′ ( x k ) / f ′ ′ ( x k ) = 1 2 e k 2 f ′ ′ ′ ( ξ k ) / f ′ ′ ( x k ) x_k - x^{*} - f^{\prime}\left(x_{k}\right) / f^{\prime \prime}\left(x_{k}\right) =\frac{1}{2} e_{k}^{2} f^{\prime \prime \prime}\left(\xi_{k}\right) / f^{\prime \prime}\left(x_{k}\right) xk−x∗−f′(xk)/f′′(xk)=21ek2f′′′(ξk)/f′′(xk)
x k + 1 − x ∗ = e k + 1 = 1 2 e k 2 f ′ ′ ′ ( ξ k ) / f ′ ′ ( x k ) x_{k+1} - x^{*} = e_{k+1} = \frac{1}{2} e_{k}^{2} f^{\prime \prime \prime}\left(\xi_{k}\right) / f^{\prime \prime}\left(x_{k}\right) xk+1−x∗=ek+1=21ek2f′′′(ξk)/f′′(xk)
當 1 2 f ′ ′ ′ ( ξ k ) / f ′ ′ ( x k ) ≤ c \frac{1}{2} f^{\prime \prime \prime}\left(\xi_{k}\right) / f^{\prime \prime}\left(x_{k}\right) \leq c 21f′′′(ξk)/f′′(xk)≤c 時,有:
e k + 1 ≤ c e k 2 e_{k+1} \leq c e_{k}^{2} ek+1≤cek2
預處理 (Heissan陣輔助梯度下降)
x ← x − η diag ( H f ) − 1 ∇ x \mathbf{x} \leftarrow \mathbf{x}-\eta \operatorname{diag}\left(H_{f}\right)^{-1} \nabla \mathbf{x} x←x−ηdiag(Hf)−1∇x
梯度下降與線性搜尋(共轭梯度法)
随機梯度下降
随機梯度下降參數更新
對于有 n n n 個樣本對訓練資料集,設 f i ( x ) f_i(x) fi(x) 是第 i i i 個樣本的損失函數, 則目标函數為:
f ( x ) = 1 n ∑ i = 1 n f i ( x ) f(\mathbf{x})=\frac{1}{n} \sum_{i=1}^{n} f_{i}(\mathbf{x}) f(x)=n1i=1∑nfi(x)
其梯度為:
∇ f ( x ) = 1 n ∑ i = 1 n ∇ f i ( x ) \nabla f(\mathbf{x})=\frac{1}{n} \sum_{i=1}^{n} \nabla f_{i}(\mathbf{x}) ∇f(x)=n1i=1∑n∇fi(x)
使用該梯度的一次更新的時間複雜度為 O ( n ) \mathcal{O}(n) O(n)
随機梯度下降更新公式 O ( 1 ) \mathcal{O}(1) O(1):
x ← x − η ∇ f i ( x ) \mathbf{x} \leftarrow \mathbf{x}-\eta \nabla f_{i}(\mathbf{x}) x←x−η∇fi(x)
且有:
E i ∇ f i ( x ) = 1 n ∑ i = 1 n ∇ f i ( x ) = ∇ f ( x ) \mathbb{E}_{i} \nabla f_{i}(\mathbf{x})=\frac{1}{n} \sum_{i=1}^{n} \nabla f_{i}(\mathbf{x})=\nabla f(\mathbf{x}) Ei∇fi(x)=n1i=1∑n∇fi(x)=∇f(x)
e.g.
f ( x 1 , x 2 ) = x 1 2 + 2 x 2 2 f(x_1, x_2) = x_1^2 + 2 x_2^2 f(x1,x2)=x12+2x22
def f(x1, x2):
return x1 ** 2 + 2 * x2 ** 2 # Objective
def gradf(x1, x2):
return (2 * x1, 4 * x2) # Gradient
def sgd(x1, x2): # Simulate noisy gradient
global lr # Learning rate scheduler
(g1, g2) = gradf(x1, x2) # Compute gradient
(g1, g2) = (g1 + np.random.normal(0.1), g2 + np.random.normal(0.1))
eta_t = eta * lr() # Learning rate at time t
return (x1 - eta_t * g1, x2 - eta_t * g2) # Update variables
eta = 0.1
lr = (lambda: 1) # Constant learning rate
show_trace_2d(f, train_2d(sgd, steps=50))
#最後在最有點處還是有抖動。
動态學習率
規劃學習率
η ( t ) = η i if t i ≤ t ≤ t i + 1 piecewise constant η ( t ) = η 0 ⋅ e − λ t exponential η ( t ) = η 0 ⋅ ( β t + 1 ) − α polynomial \begin{array}{ll}{\eta(t)=\eta_{i} \text { if } t_{i} \leq t \leq t_{i+1}} & {\text { piecewise constant }} \\ {\eta(t)=\eta_{0} \cdot e^{-\lambda t}} & {\text { exponential }} \\ {\eta(t)=\eta_{0} \cdot(\beta t+1)^{-\alpha}} & {\text { polynomial }}\end{array} η(t)=ηi if ti≤t≤ti+1η(t)=η0⋅e−λtη(t)=η0⋅(βt+1)−α piecewise constant exponential polynomial
def exponential():
global ctr #疊加的次數
ctr += 1
return math.exp(-0.1 * ctr)
ctr = 1
lr = exponential # Set up learning rate
show_trace_2d(f, train_2d(sgd, steps=1000))
def polynomial():
global ctr
ctr += 1
return (1 + 0.1 * ctr)**(-0.5)
ctr = 1
lr = polynomial # Set up learning rate
show_trace_2d(f, train_2d(sgd, steps=50))
在這裡插入圖檔描述
小批量随機梯度下降
梯度下降和随機梯度下降折中的一種方法。
def get_data_ch7(): # 本函數已儲存在d2lzh_pytorch包中友善以後使用
data = np.genfromtxt(’/home/kesci/input/airfoil4755/airfoil_self_noise.dat’, delimiter=’\t’)
data = (data - data.mean(axis=0)) / data.std(axis=0) # 标準化
return torch.tensor(data[:1500, :-1], dtype=torch.float32),
torch.tensor(data[:1500, -1], dtype=torch.float32) # 前1500個樣本(每個樣本5個特征)
features, labels = get_data_ch7()
features.shape
import pandas as pd
df = pd.read_csv(’/home/kesci/input/airfoil4755/airfoil_self_noise.dat’, delimiter=’\t’, header=None)
df.head(10)
如何更新參數
def sgd(params, states, hyperparams): #params,模型參數;states,不用;hyperparams,學習率
for p in params:
p.data -= hyperparams[‘lr’] * p.grad.data
本函數已儲存在d2lzh_pytorch包中友善以後使用
def train_ch7(optimizer_fn, states, hyperparams, features, labels,
batch_size=10, num_epochs=2):
# 初始化模型
net, loss = d2l.linreg, d2l.squared_loss
w = torch.nn.Parameter(torch.tensor(np.random.normal(0, 0.01, size=(features.shape[1], 1)), dtype=torch.float32),
requires_grad=True) #weight
b = torch.nn.Parameter(torch.zeros(1, dtype=torch.float32), requires_grad=True)
def eval_loss():
return loss(net(features, w, b), labels).mean().item()
ls = [eval_loss()]
data_iter = torch.utils.data.DataLoader(
torch.utils.data.TensorDataset(features, labels), batch_size, shuffle=True)
for _ in range(num_epochs):
start = time.time()
for batch_i, (X, y) in enumerate(data_iter):
l = loss(net(X, w, b), y).mean() # 使用平均損失
# 梯度清零
if w.grad is not None:
w.grad.data.zero_()
b.grad.data.zero_()
l.backward()
optimizer_fn([w, b], states, hyperparams) # 疊代模型參數
if (batch_i + 1) * batch_size % 100 == 0:
ls.append(eval_loss()) # 每100個樣本記錄下目前訓練誤差
# 列印結果和作圖
print('loss: %f, %f sec per epoch' % (ls[-1], time.time() - start))
d2l.set_figsize()
d2l.plt.plot(np.linspace(0, num_epochs, len(ls)), ls)
d2l.plt.xlabel('epoch')
d2l.plt.ylabel('loss')
def train_sgd(lr, batch_size, num_epochs=2):
train_ch7(sgd, None, {‘lr’: lr}, features, labels, batch_size, num_epochs)
對比
train_sgd(1, 1500, 6)
train_sgd(0.005, 1)
train_sgd(0.05, 10)