"); //-->
最近,特斯拉 AI 高级总监 Andrej Karpathy 做了一件很有趣的事情,他把 Yann LeCun 等人 1989 年的一篇论文复现了一遍。一是为了好玩,二是为了看看这 33 年间,深度学习领域到底发生了哪些有趣的变化,当年的 LeCun 到底被什么卡了脖子。此外,他还展望了一下 2055 年的人将如何看待今天的深度学习研究。
1989 年,Yann Lecun 等人发表了一篇名为「Backpropagation Applied to Handwritten Zip Code Recognition」的论文。在我看来,这篇论文有一定的历史意义,因为据我所知,它是使用反向传播训练的端到端神经网络在现实世界中最早的应用。
论文链接:http://yann.lecun.com/exdb/publis/pdf/lecun-89e.pdf
尽管数据集和神经网络都比较小(7291 张 16x16 灰度数字图像,1000 个神经元),但这篇论文在 33 年后的今天读起来依然没感觉过时:它展示了一个数据集,描述了神经网络的架构、损失函数、优化,还给出了训练集和测试集的实验分类错误率。它是那么得有辨识度,完全可以被归类为现代深度学习论文,但它却来自 33 年前。所以我开始复现这篇论文,一是为了好玩,二是为了将此练习作为一个案例研究,探讨深度学习进步的本质。
实现
我试着尽可能地接近论文,并在 PyTorch 中复现了每个细节,参见以下 GitHub 库:
复现链接:https://github.com/karpathy/lecun1989-repro
最初的网络是用 Lisp 实现的,使用了 Bottou 和 LeCun 1988 年提出的反向传播模拟器 SN(后来被命名为 Lush)。这篇论文是法语的,所以我读不懂。但从句法来看,你可以使用高级 API 指定神经网络,类似于今天在 PyTorch 中做的事情。
在当代软件设计中,库的设计分为以下 3 个部分:
1)一个快速 (C/CUDA) 通用 Tensor 库,用来实现多维张量的基本数学运算;2)一个 autograd 引擎,用来跟踪前向计算图并为 backward pass 生成运算;3)一个可脚本化的(Python)深度学习、高级 API,包含常见的深度学习运算、层、架构、优化器、损失函数等。
训练
在训练过程中,我们要对 7291 个样本组成的训练集进行 23 次 pass,总共有 167693 个样本 / 标签展示给神经网络。最初的网络在一个 SUN-4/260 工作站(发布于 1987 年)上训练了 3 天。现如今,我用我的 MacBook Air (M1) CPU 就能运行这个实现,而且只用了 90 秒(实现了大约 3000 倍的加速)。我的 conda 被设置为使用本机 amd64 构建,而不是 Rosetta 模拟。如果 PyTorch 能够支持 M1 的所有功能(包括 GPU 和 NPU),那么加速效果可能会更加明显。
我还尝试单纯地在一个 A100 GPU 上运行代码,但训练却更慢,原因很可能是网络太小(4 层 convnet,最多 12 个通道,总共 9760 个参数,64K MACs,1K 激活),并且 SGD 一次只使用一个示例。也就是说,如果一个人真的想用现代硬件(A100)和软件基础设施(CUDA,PyTorch)来解决这个问题,我们需要把 per-example SGD 换成 full-batch 训练,以最大限度地提高 GPU 利用率。这样一来,我们很有可能额外实现约 100 倍的训练加速。
复现 1989 年的实验结果
原始论文给出了以下实验结果:
eval: split train. loss 2.5e-3. error 0.14%. misses: 10eval: split test . loss 1.8e-2. error 5.00%. misses: 102
eval: split train. loss 4.073383e-03. error 0.62%. misses: 45eval: split test . loss 2.838382e-02. error 4.09%. misses: 82
eval: split train. loss 4.073383e-03. error 0.62%. misses: 45eval: split test . loss 2.838382e-02. error 4.09%. misses: 82
eval: split train. loss 9.536698e-06. error 0.00%. misses: 0eval: split test . loss 9.536698e-06. error 4.38%. misses: 87
eval: split train. loss 0.000000e+00. error 0.00%. misses: 0eval: split test . loss 0.000000e+00. error 3.59%. misses: 72
eval: split train. loss 8.780676e-04. error 1.70%. misses: 123eval: split test . loss 8.780676e-04. error 2.19%. misses: 43
eval: split train. loss 2.601336e-03. error 1.47%. misses: 106eval: split test . loss 2.601336e-03. error 1.59%. misses: 32
eval: split train. loss 4.073383e-03. error 0.62%. misses: 45eval: split test . loss 2.838382e-02. error 4.09%. misses: 82
eval: split train. loss 1.305315e-02. error 2.03%. misses: 60eval: split test . loss 1.943992e-02. error 2.74%. misses: 54
eval: split train. loss 3.238392e-04. error 1.07%. misses: 31eval: split test . loss 3.238392e-04. error 1.25%. misses: 24
首先,33 年来的宏观层面没有太大变化。我们仍然在建立由神经元层构成的可微神经网络体系架构,并使用反向传播和随机梯度下降对它们进行端到端优化。一切读起来都非常熟悉,只是 1989 年的网络更小。
以今天的标准来看,1989 年的数据集还是个「婴儿」: 训练集只有 7291 张 16x16 的灰度图像。今天的视觉数据集通常包含来自网络的几亿张高分辨率彩色图像(谷歌有 JFT-300M,OpenAI CLIP 是在 400M 张图上训练的),而且会增长到几十亿张的规模。每张图像包含的像素信息增长了 1000 倍(384 * 384 * 3/(16 * 16)),图像数量增长了 100,000 倍(1e9/1e4) ,粗略计算的话,像素数据输入增长了 100,000,000 倍以上。
那时的神经网络也是一个「婴儿」:它大约有 9760 个参数、64K MACs 和 1K activations。当前(视觉)神经网络的规模达到了几十亿参数,而自然语言模型可以达到数万亿参数。
当年,一个 SOTA 分类器在工作站上训练需要 3 天,现在如果是在无风扇笔记本电脑上训练只需要 90 秒(3000 倍加速),如果切换到 full-batch 优化并使用 GPU,速度还能提升百倍以上。
事实上,我能够通过微调模型、增强、损失函数,以及基于现代创新的优化,将错误率降低 60% ,同时保持数据集和模型测试时间不变。
仅仅通过扩大数据集就可以获得适度的收益。
进一步的重大收益可能必须来自一个更大的模型,这将需要更多的计算和额外的研究与开发,以帮助稳定规模不断扩大的训练。如果我被传送到 1989 年,而且没有一台更大的计算机,我将无法进一步改进系统。
假设这个练习课程时间上保持不变,这对 2022 年的深度学习意味着什么?一个来自 2055 年的时间旅行者会如何看待当前网络的表现?
2055 年的神经网络在宏观层面上基本上与 2022 年的神经网络相同,只是规模更大。
我们今天的数据集和模型看起来像个笑话,2055 年的二者规模都大约有 10,000,000 倍。
一个人可以在一分钟内训练 2022 个 SOTA 模型,而且是在他们的个人电脑上作为一个周末娱乐项目来训练。
今天的模型并不是最优化的,只是改变了模型的一些细节、损失函数、增强或者可以将误差降低一半的优化器。
我们的数据集太小了,通过扩大数据集可以获得适度的收益。
如果不扩大计算机基础设施和投资相应规模的高效训练模式的研发,就不可能取得进一步的收益。
但我想要表达的最重要的趋势是,随着 GPT 这种基础模型的出现,根据某些目标任务(比如数字识别)从零开始训练整个神经网络的设置,会由于「微调」而变得落伍。这些基础模型由那些拥有大量计算资源的少数机构进行训练,大多数应用是通过对网络的一部分进行轻量级微调、prompt engineering,或是通过数据和模型蒸馏到更小的专用推理网络的 optional step 来实现的。
我认为,这一趋势在未来将十分活跃。大胆假设一下,你根本不会再想训练一个神经网络。在 2055 年,你可以用说话的方式去要求一个 10,000,000 倍大小的神经网络大脑去执行一些任务。如果你的要求足够明确,它就会答应你。
当然,你也可以自己训练一个神经网络,但你为什么要这么做呢?
原文链接:https://karpathy.github.io/2022/03/14/lecun1989/
*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。