最近發現 Jupyter Notebook 裡面的 ipywidgets 提供了一個非常方便的功能。這個插件可以通過一條命令,將自己定義的一個 Python 函數轉換為有用戶界面的可滑鼠點擊交互的動畫。這種方式對教學演示有非常大的幫助。

下面舉一個簡單的例子,用最少的代碼交互演示深度學習裡面的梯度下降演算法。梯度下降演算法是優化演算法,目標是尋找損失函數的極小值位置。對於損失函數 L(x), 從一個點 x_0 出發,增大 x_0 一點點使其變為 x_0 + Delta x , 如果我們觀察到 L(x_0 + Delta x) > L(x_0) , 即損失變大了,那很明顯下一步要減小 x。如果我們觀察到 L(x_0 + Delta x) < L(x_0) , 即損失變小了,那我們下一步要增大 x,繼續朝著損失最小化的方向前進。

如何將此過程用數學表達式表示呢?這就是梯度下降演算法。我們觀察到如果損失隨 x 的增大而增大,那麼梯度 frac{partial f} {partial x} approx frac{f(x+Delta x) - f(x) }{Delta x} > 0 是正數,我們只要將x減去一個正數,即可使 x 變小,從而使損失變小。同理,如果損失隨 x 的增大而減小,則梯度為負數,我們減去一個負數,則 x 變大,同樣達到使損失變小的目的。所以梯度的符號很重要,在 RMSProp 這種特殊的隨機梯度下降演算法中,就利用了梯度的符號信息 {
m sign}(partial f / partial x) ,而將梯度的絕對值做了加權歸一化處理。所以最簡單的 SGD 完整的數學表達如下,

x_{
m new} = x_{
m old} - {
m sign}(partial f / partial x) 	imes lr

而在一般的隨機梯度下降中,同時保留了梯度絕對值的信息,即,

x_{
m new} = x_{
m old} -partial f / partial x 	imes lr

下面這個交互動畫,通過非常簡短的Python代碼,動態的展示了隨機梯度下降這一過程。用戶可以為紅色小球選擇不同的起始點 xstart,以及不同的學習率 lr, 來觀察梯度下降演算法如何幫助紅色小球找到極小值點。改變學習率,可以直觀的觀察到收斂到極小值的情況。非常小的學習率導致收斂速度過慢。小的學習率能幫助小球穩定找到極小值。中等學習率會導致小球左右震蕩,很難實現在極小值附近穩定下來。而大的學習率直接導致損失函數極速變大,發散。所以在訓練神經網路的時候,如果驗證誤差逐步增大,那可能是過擬合。但如果訓練誤差不減反增,那幾乎一定是學習率太大惹的禍。這也是為什麼深度學習訓練的時候,大家都喜歡使用隨訓練時間衰減,階梯式下降或cosine函數方式下降的學習率。

小學習率動畫

中學習率動畫

大學習率動畫:

全部共 23 行 Python 代碼如下,

%matplotlib inline
import matplotlib.pyplot as plt
from ipywidgets import *
import numpy as np

@interact(xstart=[-4, -2, 0.5, 2], lr=[0.01, 0.1, 0.49, 0.99, 9.9],
step=widgets.Play(min=0, interval=100, layout=Layout(width=100px)))
def sgd(xstart=-5, lr=0.01, step=1):
x = np.linspace(-4, 4, 100)
y = x ** 2
xsteps = []
xstep = xstart
for i in range(101):
xsteps.append(xstep)
xgrad = 2 * xstep
xstep = xstep - lr * xgrad

xi = xsteps[step]
yi = xi ** 2
plt.plot(xi, yi, ro, ms=20)
plt.plot(x, y, k-)
plt.title(step: %s%step)

plt.xlabel(x)
plt.ylabel(y)
plt.show()

在這段代碼中,為了實現用戶輸入,動畫演示,只在正常的 Python 函數之外加入一句裝飾器,即那個以@開頭的函數 decorator。裝飾器的參數類型及取值決定用戶交互界面的輸入方式及可能選項。如果參數取值是列表,則會提供下拉框選項。step 則提供了timer,實現動畫功能。如果不需要動畫,只需要隨用戶輸入而變化的靜態圖片,則可刪除 widgets.Play() 這個參數。

@interact(xstart=[-4, -2, 0.5, 2], lr=[0.01, 0.1, 0.49, 0.99, 9.9],
step=widgets.Play(min=0, interval=100, layout=Layout(width_=100px)))

總結:這篇博客使用 Jupyter Notebook裡面的 ipywidgets, 使用23 行代碼,交互演示深度學習裡面的梯度下降演算法。後面可能會進一步演示動量機制 momentum,以及Adaptive步長的優化演算法,比如Adam。

interact 可以做到在正常 Python 函數之外加一個語句的方法,將此函數變為可交互的演示動畫。此方法一方面能大大減少老師的工作,另一方面又能以最直觀的方式向學生傳遞知識。希望此文能給需要的人帶來幫助。

推薦閱讀:

相关文章