符号编程的一个巨大优势是能够自动求导。这原本是命令式编程的弱项,原因在上面的例子中也有所体现。由于命令式编程需要应对各类分支和循环结构,这让自动求导变得比较复杂。MinPy 采纳了一位西域奇人 Autograd 的招法来解决这一问题。方法也非常简单:首先,用户将需要求导的代码定义在一个函数中,这样通过分析函数参数和返回值我们就能知道自动求导的输入和输出;其次,MinPy 一边执行一边记录下执行的路径,在自动求导时只需要反向这一路径即可。通过这一方法,MinPy 可以支持对于各类分支和循环结构的自动求导:
招式二:完整 NumPy 支持 MinPy 的目标是希望只修改 import 语句,就能将 NumPy 程序变成 MinPy 程序,从而能够使用 GPU 进行加速。无奈 NumPy 老先生的招式博大精深,接口繁多,MinPy 作为后辈不能在短时间内支持所有的接口。因此,MinPy 采用了一套折中的策略。当用户使用 np.func 的时候,MinPy 会检测所调用的 func 是否已经有 GPU 支持。如果有,则直接调用,否则会使用 NumPy 原有的实现。同时,MinPy 会负责一切 CPU 和 GPU 之间的内存拷贝,完全做到用户透明。
招式三:与符号式编程的衔接 尽管命令式编程能灵活地应对各种复杂的算法逻辑,出于性能的考虑,我们仍然希望对某些运算(特别是卷积运算)能够使用已有的符号执行的方式去描述。在 MinPy 中,我们也同样支持 MXNet 的符号编程。其思想是让用户将符号「包装」成一个函数进行调用。
在上面这个例子中,开奖,我们将一个 Convolution 的符号包装成了一个函数。之后该函数可以像普通函数一样被反复调用。其中有一点需要注意的是,由于符号编程需要在执行前确定所有输入矩阵的大小,因此在上面例子中的 x 的大小不能任意改变。 MinPy 的气宗修为 如之前所说,光有招式没有内功修为是没有办法成为令狐冲的,最多也就是个成不忧。命令式编程的挑战就在于如何优化算法使得性能能和符号式编程程序相较。以下我们比较了 MinPy 和使用 MXNet 符号编程的性能区别。
在上面的例子中,我们测试了训练50层MLP网络的性能。我们分别比较了MXNet符号编程,与MinPy命令式编程的运行时间。结果可以看到当网络计算量比较大时,MinPy的命令式编程和符号编程的性能几乎相同。当计算量比较小时,命令式编程有明显性能差距。但如果在MinPy中使用符号编程则性能又和MXNet几乎相同。类似的,我们测试了训练RNN网络的性能。我们比较了MXNet的符号编程以及MinPy的命令式编程的性能区别。我们可以看到,在计算量比较大的情况下,命令式编程和符号式编程的性能比较接近。在小网络中,MinPy有一个固定的性能开销。我们认为这一性能开销主要来源于用于求导的动态路径记录,以及过细的计算粒度等问题。这些都是命令式编程所带来的性能挑战,也是MinPy今后的努力方向。 面向武林新人的武功宝典 对于想要加入五岳剑派的新人们,MinPy 也是一个非常适合的上手工具。原因之一是因为 MinPy 和 NumPy 完全兼容,几乎没有额外修改的语法。另一个原因是我们团队还提供了完整的 MinPy 版本的 CS231n 课程代码。CS231n 是斯坦福大学著名教授 Fei-Fei Li 和她的爱徒 Andrej Karpathy、Justin Johnson 讲授的一门深度学习入门课程。该课程完整覆盖各类深度学习基本知识,包括卷积神经网络和递归神经网络。该课程的作业并不仅仅是对这些知识点的简单堆砌,更是包含了很多最新的实际应用。由于 MinPy 和 NumPy 天生的界面相似性,我们团队改进了 CS231n,使得学生能够更好地体验如何在实际中训练和使用深度神经网络,也让学生能够体会到 MinPy 在实际研究环境下的便利性。基于 MinPy 的 CS231n 课件已经在上海科技大学和交通大学深度学习教程中被试用。 总结 (责任编辑:本港台直播) |