前言
AI对软件开发的影响是深远且革命性的。随着神经网络和机器学习技术的发展,我们正在见证从传统的软件1.0向软件2.0的转变。这种转变的核心在于,软件2.0通过学习大量数据集和优化算法,能够自动生成和改进代码,而不再依赖于人类程序员手动编写的详细指令。
在软件1.0时代,软件开发依赖于程序员的创造力和逻辑思维,他们需要精确地编写代码来实现特定的功能。这种方法在处理复杂问题时可能会遇到瓶颈,因为人类的思维和编程能力有限。
然而,软件2.0的出现打破了这一局限。它利用神经网络的强大学习能力,通过训练数据来"学习"如何执行任务。这种方法的优势在于,它能够处理更复杂的模式识别、决策制定和自动化任务,这些都是传统编程难以实现的。例如,图像识别、自然语言处理、语音合成等领域已经实现了显著的进步,这些进步在很大程度上得益于AI技术的应用。
软件2.0还带来了开发效率的提升。在某些情况下,AI可以快速生成代码,减少了开发时间,降低了成本。此外,AI在软件测试和维护方面也显示出巨大潜力,它可以帮助发现和修复错误,提高软件的稳定性和性能。
下方内容是 Andrej Karpathy 于5年前写的文章译文,希望能为现在的我们带来某些启发。
"
我有时会看到人们将神经网络称为"机器学习工具箱中的另一个工具"。它们有优点也有缺点,在这里或那里工作,有时你可以用它们赢得Kaggle比赛。不幸的是,这种解释完全忽略了大局。神经网络不仅仅是另一个分类器,它们代表了我们开发软件方式的根本性转变的开始。它们是软件2.0。
我们熟悉的软件1.0的"经典堆栈"是用Python、C++等语言编写的,它由程序员编写的明确指令组成。通过编写每一行代码,程序员在程序空间中确定了一个具有某种理想行为的特定点。
相比之下,软件2.0是用更抽象、人类不友好的语言编写的,比如神经网络的权重。没有人直接编写这些代码,因为权重非常多(典型的网络可能有数百万),直接在权重上编码是相当困难的(我试过)。
相反,我们的方法是在理想程序的行为上指定一些目标(例如,"满足输入输出对数据集",或"赢得围棋比赛"),编写一个粗略的代码框架(即神经网络架构),这个框架确定了要搜索的程序空间的一个子集,并利用我们手头的计算资源在这个空间中搜索有效的程序。在神经网络的情况下,我们将搜索限制在程序空间的一个连续子集上,这个搜索过程可以通过反向传播和随机梯度下降(有些令人惊讶地)高效进行。
为了明确这个类比,在软件1.0中,人类工程师编写的源代码(例如一些.cpp文件)被编译成执行有用工作的二进制文件。在软件2.0中,源代码通常包括1)定义理想行为的数据集和2)给出代码粗略框架的神经网络架构,但许多细节(权重)需要填充。训练神经网络的过程将数据集编译成二进制文件------最终的神经网络。在当今大多数实际应用中,神经网络架构和训练系统正日益标准化为一种商品,因此大多数活跃的"软件开发"形式是策划、增长、调整和清洗标记数据集。这从根本上改变了我们迭代软件的编程范式,团队分为两部分:2.0程序员(数据标注者)编辑和增长数据集,而少数1.0程序员维护和迭代周围的训练代码基础设施、分析、可视化和标注接口。
事实证明,现实世界中的许多问题具有这样的特性:收集数据(或更一般地说,确定理想行为)比明确编写程序要容易得多。正因为如此以及我将在下面讨论的软件2.0程序的许多其他好处,我们正在见证一个跨行业的大规模转变,许多1.0代码正在被移植到2.0代码。软件(1.0)正在吞噬世界,现在AI(软件2.0)正在吞噬软件。
**正在进行的转变
**
让我们简要审视一下这一正在进行的转变的一些具体例子。在这些领域中,在过去几年里,当我们放弃试图通过编写明确代码来解决复杂问题,而是将代码转移到2.0堆栈时,我们看到了改进。
视觉识别曾经由工程化特征和一些机器学习(例如,SVM)组成。自那时以来,我们通过获取大型数据集(例如ImageNet)和在卷积神经网络架构空间中搜索,发现了更强大的视觉特征。最近,我们甚至不再信任自己手动编码架构,而是开始在这些架构上进行搜索。
语音识别曾经涉及大量的预处理、高斯混合模型和隐马尔可夫模型,但现在几乎完全由神经网络组成。一个与之密切相关、经常被引用的幽默引用(归因于1985年的Fred Jelinek)是:"每当我解雇一个语言学家,我们的语音识别系统的性能就会提高"。
语音合成历来采用各种拼接机制,但今天最先进的模型是大型ConvNets(例如WaveNet),它们产生原始音频信号输出。
机器翻译通常采用基于短语的统计技术,但神经网络正迅速成为主导。我最喜欢的架构是在多语言设置中训练的,其中单个模型可以从任何源语言翻译到任何目标语言,并在弱监督(或完全无监督)设置中进行。
游戏。长期以来,明确编写的围棋程序已经开发出来,但AlphaGo Zero(一个ConvNet,观察棋盘的原始状态并进行移动)现在已经成为游戏中最强的玩家。我预计我们将在其他领域看到非常相似的结果,例如DOTA 2或StarCraft。
数据库。人工智能之外的更传统的系统也在早期显示出转变的迹象。例如,"学习索引结构的案例"用神经网络替换了数据管理系统的核心组件,速度比缓存优化的B-Trees快70%,同时节省了一个数量级的内存。
你会发现我上面链接的许多工作都是在谷歌完成的。这是因为谷歌目前正处于将自己大部分代码重写为软件2.0的前沿。"One model to rule them all"提供了一个早期的草图,展示了各个领域的统计强度如何被融合成一个对世界一致的理解。
软件2.0的好处
为什么我们应该倾向于将复杂程序移植到软件2.0?显然,一个简单的答案是它们在实践中工作得更好。然而,还有很多其他方便的理由来选择这个堆栈。让我们来看一下软件2.0(想想ConvNet)与软件1.0(想想生产级别的C++代码库)相比的一些好处。软件2.0是:
计算上同质的。典型的神经网络,首先,由两个操作组成:矩阵乘法和在零处的阈值化(ReLU)。与古典软件的指令集相比,这要简单得多。因为你只需要为软件1.0提供少量核心计算原语(例如矩阵乘法)的实现,所以更容易做出各种正确性/性能保证。
易于集成到硅片中。作为一个推论,由于神经网络的指令集相对较小,将这些网络实现得更接近硅片(例如,使用定制的ASICs、神经形态芯片等)要容易得多。当低功耗智能在我们周围普及时,世界将会改变。例如,小型、廉价的芯片可以集成预训练的ConvNet、语音识别器和WaveNet语音合成网络,全部集成在一个小型的原型大脑中,你可以将其附加到任何东西上。
运行时间恒定。典型的神经网络前向传递的每次迭代所需的FLOPS完全相同。与你的C++代码可能通过某些庞大的C++代码库采取的不同执行路径相比,没有可变性。当然,你可以有动态计算图,但执行流程通常仍然受到显著限制。这样我们几乎可以保证永远不会发现自己处于意外的无限循环中。
内存使用恒定。与上述相关,没有动态分配的内存,所以几乎没有可能发生磁盘交换或你必须在代码中追踪的内存泄漏。
它高度可移植。与古典二进制或脚本相比,矩阵乘法序列在任意计算配置上运行要容易得多。
它非常敏捷。如果你有一个C++代码,有人想让你将其速度提高两倍(如果需要的话,以牺牲性能为代价),调整系统以适应新规格将非常困难。然而,在软件2.0中,我们可以拿走我们的网络,移除一半的通道,重新训练,然后------它以两倍的速度运行,效果稍差。这是魔法。相反,如果你有更多的数据/计算,你可以通过添加更多的通道和重新训练立即让你的程序工作得更好。
模块可以融合成一个最优整体。我们的软件通常被分解成通过公共函数、API或端点通信的模块。然而,如果两个最初分别训练的软件2.0模块相互作用,我们可以轻松地通过整个网络进行反向传播。想象一下,如果你的网页浏览器能够自动重新设计底层系统指令,以实现加载网页的更高效率,那将是多么惊人。或者,如果你导入的计算机视觉库(例如OpenCV)可以在你的特定数据上自动调整。在2.0中,这是默认行为。
它比你更好。最后,也是最重要的,神经网络在大部分有价值的垂直领域中,至少在涉及图像/视频和声音/语音的领域,比你或我能想出的任何代码都要好。
软件2.0的限制
2.0堆栈也有一些自己的缺点。在优化结束时,我们得到了工作得很好的大型网络,但很难说它们是如何工作的。在许多应用领域,我们将面临一个选择:使用我们理解的90%准确的模型,还是我们不理解的99%准确的模型。
2.0堆栈可能会以不合直觉和尴尬的方式失败,或者更糟,它们可能会"默默失败",例如,通过在训练数据中默默采纳偏见,这在大多数情况下,当它们的规模轻易达到数百万时,很难正确分析和检查。
最后,我们仍在发现这个堆栈的一些特殊性质。例如,对抗性示例和攻击的存在突显了这个堆栈的不合直觉性质。
在2.0堆栈中编程
软件1.0是我们编写的代码。软件2.0是基于评估标准(例如,"正确分类这些训练数据")的优化编写的代码。在任何程序不明显但可以反复评估其性能(例如------你正确分类了一些图像吗?你在围棋游戏中赢了吗?)的设置中,都可能受到这种转变的影响,因为优化可以找到比人类编写的更好的代码。
我们看待趋势的视角很重要。如果你将软件2.0视为一种新的和新兴的编程范式,而不仅仅是将神经网络视为机器学习技术类别中的一个很好的分类器,那么这些推断就变得更加明显,而且很明显还有更多的工作要做。
特别是,我们已经建立了大量的工具来帮助人类编写1.0代码,例如具有语法高亮、调试器、分析器、go to def、git集成等功能的强大IDE。在2.0堆栈中,编程是通过积累、调整和清洗数据集来完成的。
"
索引链接
[1] 英文原文:karpathy.medium.com/software-2-...
[2] 无监督学习:arxiv.org/abs/1710.11...
[3] 搜索:arxiv.org/abs/1703.01...
[4] 网络结构:arxiv.org/abs/1730.01...
[5] 多语言:arxiv.org/abs/1611.04...