深入理解神经网络:从数学细节到训练动态可视化

本文通过数学形式化分析神经网络的线性代数本质,探讨ReLU激活函数下的多面体划分特性,并展示不同网络结构在图像拟合任务中的训练动态,包括瓶颈层和过参数化网络的特殊行为。

ADD / XOR / ROL

神经网络理解实验系列(第2篇/N)

在这篇文章中,我将解释当前对神经网络的思考。在之前的文章中,我解释了"神经网络的折纸视角"(在某些圈子里也称为"多面体透镜")的直观理解。本文将深入探讨其数学细节。

神经网络层的标准教科书解释通常如下:

[ \sigma( \overline{W}x + b )]

其中 (\sigma : \mathbb{R} \to \mathbb{R}) 是非线性函数(如sigmoid或ReLU等),(\overline{W}) 是连接到神经元输入边的权重矩阵,(b) 是"偏置"向量。个人认为这种表示法有些繁琐,我更喜欢将偏置向量纳入权重矩阵中,这样可以将神经网络视为"矩阵乘法与非线性函数应用的交替"。

我实在不喜欢考虑除ReLU和leaky ReLU之外的非线性函数——也许随着时间的推移我将不得不接受它们的存在,但目前我考虑的所有神经网络都是ReLU或leaky ReLU。暂时我们还假设网络最终输出实向量,因此(还)不是分类器。

假设我们有一个包含 (k) 层的网络,每层的神经元数量为 (n_1, \dots, n_k)。该网络在维度为 (i) 和 (o) 的实向量空间(或其近似)之间映射:

[ NN : \mathbb{R}^i \to \mathbb{R}^o ]

首先,我将偏置向量纳入矩阵乘法中,因为这大大简化了表示法。输入向量 (\overline{x}) 通过附加1来扩展,偏置向量 (b) 附加到 (\overline{W}):

[ W’ = [\overline{W}b], x = \left[\begin{array}{c}\overline{x}\1\end{array}\right] ]

这样,我们可以将 (\sigma(\overline{W}x + b)) 写作 (\sigma(W’x))。

在我们的情况下,(\sigma) 始终是ReLU或leaky ReLU,因此"1"将再次映射为"1"。为了便于后续组合,我还希望 (\sigma(W’x)) 的输出像输入向量 (x) 一样,最后一个分量为1。为了实现这一点,我需要向 (W’) 附加一行全零并以1结尾。最终我们得到:

[ W = \left[\begin{array}{cc}\overline{W}& b\0, \dots & 1\end{array}\right], x = \left[\begin{array}{c}\overline{x}\1\end{array}\right] ]

上一篇文章解释了为什么神经网络将输入空间划分为多面体,在这些多面体上近似函数将完全线性。考虑数据点 (x_1)。如果在 (x_1) 上评估神经网络,一些ReLU会被激活(因为它们的输入数据之和大于0),而一些则不会。对于给定的 (x_1),将有 (k) 个布尔向量表示神经网络中每个ReLU的激活(或非激活)。这意味着我们有一个函数,对于给定的输入向量、层和层中的神经元编号,在ReLU情况下返回 (0) 或 (1),在leaky ReLU情况下返回 (0.01) 和 (1)。

我们称这个函数为 (a)。我们可以使其成为具有三个参数(层、神经元索引、输入向量)的函数,但我更喜欢将层和神经元索引移到索引中,因此我们有:

[ a_{l, n} : \mathbb{R}^i \to { 0, 1 } \text{ 对于 ReLU } ]

[ a_{l, n} : \mathbb{R}^i \to { 0.01, 1 } \text{ 对于 leaky ReLU } ]

这为我们提供了整个网络的非常线性代数的表达式:

[ NN(x) = W_1 A_1 \dots W_k A_k x = \prod_{i=0}^k (W_i A_i)x ]

其中 (A_k) 的形式为:

[ A_k = \left( \begin{array}{cccc} a_{k, 1}(x) & \dots & 0 & 0\ \dots & \dots & \dots & \dots \ 0 & \dots & a_{k, n_k}(x) & 0\ 0 & 0 & 0 & 1\end{array}\right) ]

现在我们可以非常清楚地看到,一旦激活模式确定,整个函数就变成线性的,只是一系列矩阵乘法,其中每隔一个矩阵是对角线上有激活模式图像的对角矩阵。

这种表示表明,只要激活模式不变,函数就保持相同(且线性)——同一多面体上的点将具有相同的激活模式,因此我们可以使用激活模式作为"多面体标识符"——对于任何输入点 (x),我可以将其通过网络运行,如果第二个点 (x’) 具有相同的模式,我知道它位于同一多面体上。

因此,我可以为单层神经网络制作类似第1部分中创建的那种动画——我们可以将任意二维图像作为要学习的未知分布,然后可视化训练动态:显示输入空间如何被切割成不同的多面体,函数在这些多面体上线性近似,并展示这种划分和近似在不同形状网络的训练过程中如何演变。

我们采用1024x1024大小的输入图像,因此有一兆字节的字节大小值,并从中采样5000个数据点——约占图像总点数的0.4%。我们为MLP指定一个形状,并训练6000步,可视化进度。

为简单起见,我们尝试学习一个白底黑环,边缘清晰——首先使用每层14个神经元、深度为6层的网络。

在左侧,我们看到评估的神经网络及其为分割输入空间而生成的多面体边界。在中心,我们只看到神经网络的输出——神经网络目前"学习"重现的内容。在右侧,我们看到原始图像,几乎难以察觉的红点是5000个训练点,蓝点是1000个验证点。

以下是训练运行动态的动画:

这很整洁,那么不同形状的神经网络呢?如果我们在训练过程中强制神经网络通过2个神经元的瓶颈会发生什么?

最后一个网络有10层每层10个神经元,然后是一层2个神经元,再有3层每层10个神经元。就参数数量而言,它与其他网络大致相当,但表现出明显不同的训练动态。

如果我们 dramatically 过参数化一个网络会发生什么?它会过拟合我们的底层数据,并找到一种方法来分割输入空间以减少训练集上的误差,而不重现圆形吗?

让我们试试——一个20个神经元、40层深的网络怎么样?这应该使用大约20k个浮点参数来学习5000个数据点,所以可能会过拟合?

事实证明这个例子没有过拟合,但提供了特别丰富的动态:大约第1000个epoch,我们可以看到网络似乎已经弄清了圆形的大致形状,大多数多面体边界似乎迁移到这个圆上。网络有点摇摆但似乎有进展。到第2000个epoch,我们认为已经看到了一切,网络将围绕圆形巩固。在第3000到4000个epoch之间,某些东西破裂了,损失飙升,网络似乎正在解体,训练发散。到第4000个epoch,它重新稳定下来,但输入空间划分的配置非常不同。这个视频大约在第5500个epoch结束。

这非常引人入胜。没有过拟合的迹象,但我们可以看到随着网络变深,训练变得不那么稳定:圆形似乎摇摆得更厉害,并且我们有这些奇怪的、看似灾难性的相变,之后网络必须重新稳定。尽管只有相对较少的数据点和足够的能力来过拟合它们,但网络似乎准确地捕捉到了"圆形"形状。

只要有时间,我就会继续深入研究这一点,希望这既有趣又有信息量。我的下一个任务是构建一个工具,对于输入空间中的给定点,提取描述该点所在多面体的线性不等式系统。如果您想讨论任何这些内容,请随时联系!

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计