最近发现 Jupyter Notebook 里面的 ipywidgets 提供了一个非常方便的功能。这个插件可以通过一条命令,将自己定义的一个 Python 函数转换为有用户界面的可鼠标点击交互的动画。这种方式对教学演示有非常大的帮助。
下面举一个简单的例子,用最少的代码交互演示深度学习里面的梯度下降算法。梯度下降算法是优化算法,目标是寻找损失函数的极小值位置。对于损失函数 L(x), 从一个点
出发,增大
一点点使其变为
, 如果我们观察到
, 即损失变大了,那很明显下一步要减小 x。如果我们观察到
, 即损失变小了,那我们下一步要增大 x,继续朝着损失最小化的方向前进。
如何将此过程用数学表达式表示呢?这就是梯度下降算法。我们观察到如果损失随 x 的增大而增大,那么梯度
是正数,我们只要将x减去一个正数,即可使 x 变小,从而使损失变小。同理,如果损失随 x 的增大而减小,则梯度为负数,我们减去一个负数,则 x 变大,同样达到使损失变小的目的。所以梯度的符号很重要,在 RMSProp 这种特殊的随机梯度下降算法中,就利用了梯度的符号信息
,而将梯度的绝对值做了加权归一化处理。所以最简单的 SGD 完整的数学表达如下,
而在一般的随机梯度下降中,同时保留了梯度绝对值的信息,即,
下面这个交互动画,通过非常简短的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 函数之外加一个语句的方法,将此函数变为可交互的演示动画。此方法一方面能大大减少老师的工作,另一方面又能以最直观的方式向学生传递知识。希望此文能给需要的人带来帮助。