【新智元导读】在Yann LeCun“深度学习已死”的惊人发言下,可微分编程的概念引发了广泛关注。机器学习著名博主colah(Christopher Olah)在展望30年后的深度学习,提到了可微分编程。他从深度学习三大观点之一的表示(representation)角度出发,认为深度学习研究的是优化和函数编程之间的联系,而可微分编程则是函数编程和优化的自然交集,十分优雅而简洁,值得进一步研究。
目前,深度学习是一个非常成功的工具。但这个工具是我们偶然发现的,作为一个领域,还没有统一的看法或共同的理解。事实上,这个领域还存在几种相互竞争的表述!
我认为在30年后回过头看,我们将看到很不一样的深度学习。
30年后的深度学习:神经科学观点、概率统计观点和表征观点,谁会胜出?
如果我们认为30年后,我们可能会以一种非常不同的方式看待深度学习,那么这就提出了一个有趣的问题:
到那时,我们将如何看待深度学习?
当然,没有人能真正知道我们将来如何理解这个领域。但有趣的是,我们现在可以做一些推测。
目前,有三种表述正在相互竞争,打算成为我们理解深度学习的关键。有借鉴生物学原理的神经科学的表述。有以数据转换和自然流形假设为中心的表示(representation)的表述。最后,还有一种概率性的表述,把神经网络解释为隐藏变量(latent variables)。这些表述并不是相互排斥的,但是它们对深度学习的思考方式却有着很大的不同。
而这篇文章将把表示的表述延伸到一个新的答案:深度学习研究的是优化和函数编程之间的联系。
从这个角度看,深度学习中对表示的表述,对应于函数编程中的类型理论(type theory)。这个理论认为,深度学习处在我们已知的两个领域的交汇处,这两个领域都已经有了很多的研究,它们是如此美丽,如此自然,我心中的数学家几乎可以相信,这就是对现实的根本描述。
这是一个推断性的想法。我并不是说这就是真的,而是想提出,这是可信的,完全可以想象深度学习正朝着这个方向发展。需要指出:我主要是在进行美学上的论证,而不是事实论证。我想表明,这是一个自然而优雅的想法,它涵盖了我们目前所说的深度学习。
优化与函数复合
深度学习的独特之处是它研究的是深度神经网络——多层神经网络。在多层的进程中,模型逐渐弯曲数据,将其弯曲成易于解决给定任务的形式。
这些层的细节每隔一段时间就会改变一次。保持不变的是有一个序列的层。
每一层都是一个函数,作用于前一层的输出。整体而言,这个网络是一个复合函数链(a chain of composed functions)。这个复合函数链经过优化以执行任务。
我所知道的所有深度学习模型都涉及优化复合函数。我认为这是当前的研究的核心。
表示即整数
在每一层,神经网络都将数据转换成另一种形式,以使任务更容易达成。我们称这些转换后的数据为“表示”(representation)。
表示(representations)与整数(types)是相对应的。
计算机科学中的整数(type)是一种基础数据类型,指以n 比特嵌入某种数据的方式。类似地,深度学习中表示(representation)是指将数据流形嵌入n维的一种方式。
正如两个函数只有在它们的type一致的情况下才能复合在一起一样,两个layer也只有在它们的representation一致时才能组合。在错误的representation中的数据对于神经网络来说是无意义的。在训练过程中,相邻的层会协商它们将要传递的representation,网络的性能取决于网络所期望的representation中的数据。
f层后面跟着一个f。f的输出表示是f的输入。
在神经网络架构非常简单的情况下,只有线性序列的层。一层输出的表示需要与下一层输入的表示相匹配。
但是许多神经网络具有更复杂的结构。举一个非常简单的例子,让我们来想象一个具有多种类似输入的神经网络,它执行多个相关的任务。它也许需要RGB图像和灰度图像作为输入。也许是以人的照片作为输入,然后试图预测照片中人的年龄和性别。由于输入类型和任务类型相似,因此最好在一个模型中完成所有这些任务,这样训练数据就可以发挥作用。其结果是多个输入层映射到一个representation中,并且多个输出由相同的representation映射。
也许这个例子过于人为设计,但是将不同类型的数据映射成相同的表示可能会达成一些了不起的成果。例如,通过将来自两种语言的单词映射成一种表示,我们可以找到翻译的对应单词,而这些词是开始时不知道的。通过将图像和单词映射到相同的表示中,我们可以将图像分类为计算机从未见过的类!
表示和整数可以分别作为深度学习和函数式编程的基本构建块。深度学习的主要描述,即流形(manifold)和表示(representation),其中心是神经网络讲数据弯曲成新的表示。几何学,逻辑学,拓扑学和函数式编程之间已知的联系表明,表示和整数之间的联系可能具有根本性意义。
深度学习和函数编程:RNN、CNN等模型与函数的惊人对应
现代神经网络背后的一个重要见解是,一个神经元的许多副本都可以在神经网络中使用。
在编程中,函数的抽象是关键。我们可以写一次代码,然后根据需要使用它,省去了重复编码的过程。这不仅大大减少了我们需要编写和维护的代码量,加快了开发过程,还降低了引入错误的风险,并使我们所犯的错误更容易被发现。
在神经网络中,在不同地方使用同一个神经元的多个副本,实际上就相当于在程序中多次调用函数。由于需要学习的内容较少,模型学习速度更快,也能学习到更好的模型。这种技术也叫做“权重绑定”(weight tying),对我们最近从深度学习中看到的优秀表现至关重要。
当然,不能随便把神经元的副本放得到处都是。为了让模型有用,你需要有使用的原则,利用数据中的某些结构。在实践中,有一些被广泛使用的模型,比如循环层和卷积层。
这些神经网络模式只是高阶函数,也就是把函数作为参数的函数。类似的情况已经在函数编程中得到了广泛的研究。实际上,很多这些网络模型都与常见的函数相对应,比如fold函数。唯一不同的是,它们不接收正常的函数作为对象,而是接收神经网络模块。
编码循环神经网络(RNN)就是fold函数。RNN常被用来接受长度可变的列表,比如将句子作为输入。
fold函数 = 编码RNN
生成循环神经网络就是unfold函数。生成RNN常用来让神经网络产生一个输出列表,比如一个句子中的单词。
unfold函数 = 生成RNN
生成RNN也是在做累积映射(Accumulating Map)。当我们要按顺序进行预测时,常会用到它们。例如,在语音识别中,我们可能希望基于过去的上下文,预测音频片段中每个时间步长的现象。
累积映射 = RNN
双向RNN是一个比较晦涩的变体,我这里就提一下。在函数编程术语中,它们是像拉链那样,错位结合在一起的一左一右两个累加映射,用来对过去和未来的情况进行序列预测。
错位结合左右累加映射=双向RNN
卷积神经网络(CNN)是映射的变体。普通的映射将函数应用于每个元素。卷积神经网络也考虑邻近元素,将函数应用于每个元素周围的小窗口。
窗口映射=卷积层
在二维卷积神经网络中,这种情况特别显著。
二维卷积网络
递归神经网络(“TreeNets”)是fold函数的泛化。它们从下到上处理数据结构,主要用于自然语言处理,让神经网络在解析树上进行运算。
Catamorphism = TreeNet
上面的例子说明了神经网络中常见的模型非常自然地对应简单的函数程序。
一种全新的编程,可微分编程:函数编程和优化的自然交集
这些模式(pattern)都是可以组合在一起,构建更大网络的模块。就像基本的构建模块一样,这些组合都是函数程序,其中包含大量的神经网络。函数程序提供高层次的结构,而其中的构建块就是灵活的部分,能够学习在函数程序提供的框架内执行实际的任务。
Sutskever等人()通过将编码器RNN和生成器RNN组合到一起,执行将英语翻译为法语的任务。在函数编程术语中,它们基本上就是fold英语句子,然后unfold生成法语翻译。
Vinyals等人()用卷积网络和生成器RNN生成图说。本质上,这个系统用卷积网络处理输入的图像,然后unfold结果向量,生成一个描述图像的句子。
这些模型都视为一种新的、可微分的函数编程。
你写一个非常粗糙的函数程序,由灵活、可学习的模块组成,你同时定义程序正确的行为,并给它大量的数据。然后你应用梯度下降或者其他一些优化算法。最终的结果是,你得到了一个厉害的系统,我们不知道如何直接构建这个系统,但是它能生成图说、分类图片。
这就是函数编程和优化的自然交集,我认为它十分优美。
结语
我觉得这个想法真的很美。同时,这也是一篇很奇怪的文章,发布出来我自己感觉有些别扭。除了自己的热情之外,我提出了一个没有任何支撑的推测性理念。老实说,根据我所知的一些客观观点,我上面提的这个想法是错误的,大多数未经验证的想法都是错误的。但这也可能是对的,而且我认为值得一提。
此外,我也不是探索这个方向合适的人,这需要从同类类型理论(homotopy type theory)的角度来分析神经网络,我没有相关的背景。但是,这个想法需要更多、更广泛的讨论。因此,我需要将这篇文章发布出来。
最后,我希望这篇文章能够激起更多关于深度学习的讨论和思考。
再说,如果我不能推测,写博客又有什么意义呢?希望我能在自己的激动和不确定之间找到适当的平衡。
原文地址:http://colah.github.io/posts/-09-NN-Types-FP/