第四章 可视化证明神经网络可以计算任何函数

优质
小牛编辑
137浏览
2023-12-01

神经网络的一个最引人注目的特点就是它实际上可以计算任何的函数。也就是说,假设某个人给你某种复杂而奇特的函数,$$f(x)$$:

不管这个函数是什么样的,总会有一个神经网络能够对任何可能的输入 $$x$$,网络可以得到对应的值 $$f(x)$$(或者某个足够准确的近似),如图:

即使函数有很多输入或者多个输出,这个结果都是成立的,$$f=f(x_1,...,x_m)$$ 。例如,这里有一个输入为 $$m=3$$ 和输出为 $$n=2$$ 的网络:

结果表明神经网络拥有一种普遍性(universality)。不过拿过来什么函数,我们都确信存在一个神经网络可以计算它。

而且,这个普遍性定理甚至在我们限制了神经网络只在输入层和输出层存在一个中间层的情况下成立。所以即使是很简单的网络架构都极其强大。

这个定理在使用神经网络的人群中非常著名。但是它为何正确却不被广泛地理解。现有的大多数的解释都具有很强的技术性。例如,最原始的论文使用了 Hahn-Banach 定理、Riesz 表示定理和一些傅里叶分析证明了这个结果。如果你是数学家,这个证明应该不大难理解,但对于大多数人还是很困难的。这不得不算是一种遗憾,因为这个普遍性背后的原理其实是简单而美妙的。

在本章,我会给一个有关普遍性的简单且基本上可视化的解释。我们会一步步深入背后的思想。你会理解为何神经网络可以计算任何的函数。你会理解到一些关于结论的一些极限。并且你还会理解这些结论如何和深度神经网络关联的。

要跟随本章的内容,你不需要读过本书前面的章节。相反,本章其实可以当成字包含的文章阅读。如果已经对神经网络有了一定的熟悉,你应该能够弄清楚这些解释。然而,我偶尔也会给出一些联系到前面的章节的链接,帮助你填补一些知识结构的空白。

普遍性定理在计算机科学领域中常常会有,太多了以至于我们都忘了这些定理的特别之处。但值得提醒自己的是:计算任意函数的能力真是是太赞了。几乎你可以想象的任何过程都可以看做是函数的计算。考虑给一段音乐用短的音乐片段进行命名这个问题。这其实也能够看做是计算一个函数。或者考虑将中文文本翻译成英文。同样,这又可以看成是计算一个函数。{实际上可以看成是计算很多的函数,因为对于一个文本来说有很多种翻译。}又或者根据一个 mp4 视频文件生成视频的画面的描述和对表演质量的讨论。同样,这些也都可以看成是一种类型的函数计算。普遍性是指,在原理上,神经网络可以做所有这些事情,或者更多。

当然,仅仅因为我们知道存在一个可以将中文翻译成英文的神经网络,这并不意味着我们有了一种构造或者识别出这样的网络的很好的技术。这个极限同样可以应用在布尔电路上的传统的普遍性定理上。但是,如同我们在本书前面看到的那样,神经网络拥有强大的算法来学习函数。学习算法和普遍性的结合是一种有趣的混合。直到现在,本书一直是着重谈学习算法。到了本章,我们来看看普遍性,看看它究竟意味着什么。

两个提醒

第一点,这句话不是说一个网络可以被用来准确地计算任何函数。而是说,我们可以获得尽可能好的一个近似。通过增加隐藏元的数量,我们可以提升近似的精度。例如,早先我使用了三个隐藏元的网络来计算 $$f(x)$$。使用三个隐藏元仅仅能得到一个低质量的大多数函数近似。通过增加隐藏元的数量(比如说,设置为五个),我们能够明显地得到更好的近似:

并且我们可以继续增加隐藏元的数目。

为了让这个表述更加准确,假设我们给定一个需要按照目标精度 $$\epsilon > 0$$ 的函数 $$f(x)$$。通过使用足够多的隐藏神经元使得神经网络的输出 $$g(x)$$ 对所有的 $$x$$,满足 $$|g(x)-f(x)|<\epsilon$$ 从而实现近似计算。换言之,近似对每个可能的输入都是限制在目标准确度范围内的。

第二点,就是可以按照上面的方式近似的函数类其实是连续函数。如果函数不是连续的,也就是会有突然、极陡的跳跃,那么一般来说无法使用一个神经网络进行近似。这并不意外,因为神经网络计算的就是输入的连续函数。然而,即使那些我们真的想要计算的函数是不连续的,一般来说连续的近似其实也足够的好了。如果这样的话,我们就可以用神经网络来近似了。实践中,这通常不是一个严重的限制。

总结一下,更加准确的关于普遍性定理的表述是包含一个隐藏层的神经网络可以被用来按照任意给定的精度来近似任何连续函数。本章,我们会使用了两个隐藏层的网络来证明这个结果的弱化的版本。在问题中我将简要介绍如何通过一些修改把解释转化成只使用一个隐藏层的网络的证明。

一个输入和一个输出的普遍性

结果表明,这其实是普遍性问题的核心。一旦我们理解了这个特例,那么实际上就会很容易扩展到那些有多个输入输出的函数上。

为了构建关于如何构造一个计算 $$f$$ 的网络的洞察,让我们从一个只包含一个隐藏层的网络开始,隐藏元两个,还有一个只有一个输出神经元的输出层:

为了感受一下网络的组成部分工作的机制,我们聚焦在最顶上的那个隐藏神经元。在下图例子中,点击权重,$$w$$,将鼠标从左往右拉动可以进行权重的增加。你可以立即看到最上面的隐藏元计算的函数变化的情况:

Paste_Image.png

Paste_Image.png

Paste_Image.png

Paste_Image.png

Paste_Image.png

Paste_Image.png

就在本书前面,我们也讲过隐藏元所计算的函数其实是 $$\sigma(wx+b)$$