AI开启软件2.0时代

2024-09-11 18:53:49 浏览数 (2)

作者:Andrej Karpathy,2018年Spark AI summit

大家好,很高兴来到这里。我想跟大家谈谈我对软件编写方式转变的看法,我称之为“软件2.0”。实际上,要完整地讲述这个故事,我得追溯到很久以前,大约100万年前。那时,我们还像这样互相扔石头。但我们人类是相当聪明的物种,我们发现了如何控制火,发展了农业,然后开始制造机器。我们用这些机器进行计算,并将计算从机械过渡到电子,然后就到了2018年,我们开始编写软件,并构建了相当复杂的软件工具。

我们之所以能取得这些进步,是因为我们在所有这些应用中都应用了一种单一的方法。首先,我们确定一个问题,然后将其分解成子问题。接着,我们为每个子问题创建算法,并将它们组合成一个系统。这些系统可以变得非常精细和复杂。这种通过分解来解决问题的方法非常有效,我们也因此取得了惊人的进步。

然而,不幸的是,在过去几年里,我们遇到了一些问题,这些问题使得应用这种传统方法变得非常困难。我比较熟悉的一个问题是计算机视觉。将描述图像的数百万个数字转换为“猫”或“非猫”这样的概念,实际上非常困难。这种通过分解和设计解决方案的方法效果并不好。

这并不是因为我们没有尝试过。人们已经尝试过分解计算机视觉问题。我们提出了一种分解问题的理论。

如果你想识别一个人,你可能想先识别人的各个部位。我们会经历多个处理阶段,并尝试设计解决方案。不幸的是,这种方法效果并不好,因为外观存在太多变化。

因此,在20世纪90年代左右,我们开始发现机器学习实际上是解决其中一些问题的好方法。我们开始尝试积累一些数据集,但我们仍然在尝试设计解决方案。我们仍然抱着开发工程工具来解决问题的心态,我们仍然在设计特征,因为这就是我们受过的训练,这就是我们取得进步的方式。然后,我们在最顶层使用一点机器学习,比如训练一个支持向量机。

到了2012年,我们发现实际上我们应该退一步,不要设计这些特征。我们实际上只需要设计架构的框架,即卷积神经网络架构的框架。我们要把更多的东西留给优化,特别是我们优化网络的权重,并训练这些特征。所以我们退了一步,减少了设计,结果事情变得更好了。

现在我们仍然在设计架构,但ImageNet上一些最先进的技术实际上更进一步。我们现在正在优化架构本身。所以我们做的设计更少了,我们甚至不相信自己能够设计出好的架构,而这也取得了很好的效果。因此,我们以计算机视觉为例,看到了这样一个趋势:你希望事情做得越好(如果你有一个评估标准,比如测试集上的损失或测试集上的准确率),最好的办法实际上是退一步,减少设计,把更多的东西留给优化。

我认为,一个好的框架是,如果你想自己设计代码,这就是软件1.0。你坐下来写一些Python或C 代码,然后确定程序空间中的一块区域,编写一个算法,这个算法不能太复杂,因为它必须在我们有限的能力范围内。这就是一个解决方案,然后你可以评估它,当你从软件2.0的角度来处理这个问题时,你可以迭代你的算法。你指定了一个要搜索的程序子集,例如卷积神经网络架构,你基本上确定了程序空间中的一块区域,你愿意在其中搜索解决方案,然后优化算法会根据你的数据或问题找到该程序空间中效果很好的部分。

所以实际上是优化算法在写代码,我们只是确定一个应该搜索的区域。我在不久前发了一条推文,推文中说:“梯度下降比你更会写代码,抱歉。”。人们对这句话的意思感到困惑,但我所说的就是这个意思:我们不自己写代码,我们只是设计框架,我们不相信自己能写出好的代码。

这种方法不仅在计算机视觉领域很有效,我们还在其他学科中看到了这一点,比如机器翻译、语音识别等等。它甚至不局限于数据集。

任何时候,只要你有一个可以评估的评估标准,比如玩好围棋或国际象棋并获胜,你就可以应用这种方法。你可以继续编写C 和Python代码,以及复杂的代码库,这就像Stockfish的做法,或者你可以退一步,说:“我不知道如何编写一个围棋程序,所以我只是在程序空间中搜索。”你可以通过计算来发现该领域中更好的算法。这甚至不局限于神经网络,你也可以搜索汇编程序等,只要你有一个可以反复评估的评估标准,那么最好不要自己设计,最好是退一步,通过计算来找到效果很好的程序。

我是特斯拉人工智能总监,我们正在应用这种方法来让自动驾驶汽车真正地运转起来。特斯拉拥有世界上最大的机器人部署规模,大约有25万个机器人。我们的工作是试图让它们实现自动驾驶,并能很好地驾驶。

大约一年前我刚到特斯拉的时候,我们基本上有这样一个软件栈。这个软件栈在代码方面实际上非常简单,有许多传感器随着时间的推移将数据流式传输到软件栈中,而我们只需要预测两个标量:车辆的方向盘转向和加速度,我们试图让它保持在车道内等等。当我到特斯拉的时候,他们有一堆代码,其中大部分是一个巨大的C 代码库,当然,还有一个卷积神经网络在做一些基本的视觉识别。在过去的一年里,我们基本上一直在将其中的一些代码移植到2.0栈中。我们发现,当你真正采用这种方法并让它很好地工作时,就会看到改进。

红色是我们编写的代码,蓝色是我们通过大量计算发现的代码。为了让大家具体了解这种转变以及它的样子,我们假设你想检测一辆车是否停放。这是我们想知道的,因为它与控制算法有关。

如果你仍然抱着设计解决方案的心态,你可能会想:“好吧,神经网络给你提供了一些边界框。如果一辆车在路边,而且它已经有一段时间没有移动了,而且这些车之间可能存在某种模式,那么这辆车就是停着的。”你现在正在设计解决方案,对吧?这不是正确的方法。我认为你不应该相信自己能写出这样的代码。相反,如果神经网络根据大量的标记数据说一辆车停着,那么它就是停着的,这是一种更好的方法。我们发现这是一种更好的方法,因为我们已经尝试过了,而且我们已经非常努力地尝试过了。这只是一个例子,说明了这种转变。

现在,关于使用2.0栈进行编程,它是什么样子的呢?你实际上在做什么?工作在哪里?你可能熟悉的是,当你编写代码时,你实际上是在设计算法。你在测量运行时间,你在设计这些算法,你写出这样的伪代码。当你得到一些很酷的东西时,你会感到非常聪明。

在软件2.0栈中,情况并非如此。

劳动力分成了两部分。其中很大一部分人所做的只是标记数据。所以你有一些非常复杂的UI界面,这些人正在这些图像上放置边界框、线条等等。在这个过程中,他们实际上是在为自动驾驶仪编程,因为这些数据最终将通过优化编译成软件2.0代码。他们在标记数据,而我们只是在帮助他们。这就是我们这些软件1.0程序员所做的,我们帮助软件2.0程序员,他们在做所有的工作,他们在为自动驾驶仪编程。我们试图用周围的基础设施来帮助他们。所以我们创建UI工具,创建相关的分析工具,并在他们必须经历的一些工作流程中插入一层智能。

我将在后面详细介绍这一点。

我的背景是博士生,我花了很多时间研究模型、算法以及如何训练这些网络。但当我到特斯拉的时候,在如何实际应用这种方法以及它在实践中是什么样子方面,我已经有了一些转变。我读博士的时候,大部分时间都在研究架构,但在特斯拉,我大部分时间都在处理数据集。这需要大量的工作,大量的努力,而且你需要把它做得非常好。

这里只是想让大家了解为什么维护这个基础设施如此复杂。

首先,即使是数据标记也是一项艰巨而重要的任务。你可能认为这很简单,因为我们有一些图像,我们想让车辆保持在车道内。所以这里有一条车道线,那里有一条车道线,我们应该保持在这条车道内。

这是给标记员的标注说明。然后你到了现实世界中,发现各种各样的疯狂的事情。这是在欧洲的某个地方,那里有之字形道路,你现在突然不确定了,我应该标注之字形道路吗?我应该直接穿过它吗?真的不清楚。或者你发现了这样的东西,然后标记员就困惑了,每个人都困惑了。现在我不得不修改标注说明了。这简直太疯狂了,那是什么鬼东西?为什么它会在侧面?我应该标注它吗?然后以后有人会担心它,或者我应该直接穿过它进行标注,我试图把这个放到2.0栈中,但真的不清楚你应该把处理这个小问题的代码放在哪里。

你想标记汽车,你可能认为在汽车周围放置边界框很简单。事实并非如此,因为世界上有很多疯狂的东西。不清楚这是一辆车还是四辆车,还是两辆车,因为交通灯是连在一起的。你可能认为交通灯只是红色、橙色、绿色,你在它们周围放置边界框就可以了。但这很快就会变得非常复杂。所以,最终你会积累数百页的标注文档来完成其中一些任务。

这支2.0劳动力实际上必须具备相当高的技能,才能理解你想让他们标注什么。如果他们做得不好,那么你的网络就不会很好地工作。

限速标志完全是一场灾难,我原以为它只是一个数字,也许我可以运行一些OCR或其他什么东西。限速标志非常复杂,比如每小时60英里,如果你是一辆卡车,在下午6点以后,在星期天,我不知道,它很快就会变得像人工智能一样复杂。我该如何在我的神经网络中处理这个问题?我应该输出什么?所以,即使是标记数据,我也被困在那里一段时间。

下一个巨大的挑战是,如果你要应用这个栈,你需要确保你的数据平衡。例如,如果我们试图识别一辆车的转向灯是否亮着,你可以想象,转向灯几乎总是关闭的。所以,如果你很天真,只是随机抽取数据,那么你得到的转向灯打开或关闭的例子就会非常少。所以,你突然之间就不得不担心你的数据不平衡问题,不得不去追逐它,开发工具来找到所有这些非常重要的罕见例子。例如,橙色交通灯就是另一个例子。我们有大量的红色和绿色的标注,但橙色的标注却没有那么多。所以在这些情况下,网络就会遇到困难。

这不仅仅是标签的问题,也是数据的问题。我们的大部分数据看起来都像这样,在高速公路上向前行驶。当然,如果你把一个在这种数据上训练出来的神经网络,放到一个看起来不同的环境中,它就不会很好地工作。比如在这种环境中,或者即使在旧金山,那里的道路也会做一些看起来很奇怪的事情。所以现在你需要相当多的数据来覆盖这些情况,并拥有广泛的数据分布。

还有一点我没有意识到的是,在学术界,标记数据的过程是多么的迭代。我当时只是认为ImageNet已经完成了,但你不能标注完一个数据集就不管了,这不是一件能够完成的事情。

举个例子,我们需要一个自动雨刷功能。通常情况下,你会使用传感器,但马斯克看了其中一些挡风玻璃图像后说:“视觉可以看到,我们可以看到雨滴,所以我们可以直接使用它。”现在就成了我的问题了。所以现在的问题是,我们有一个挡风玻璃,我们用摄像头向外看,我们试图检测那里是否有雨滴。你可能认为这很简单,我们收集一些数据,训练一个模型,然后尝试部署它,但它完全失效了。它在所有罕见的情况下都会失效,这就是问题所在。

你知道,如果挡风玻璃上有冰,有灰尘,自动雨刷在我们第一次训练它的时候,它对隧道非常兴奋,雨刷会在隧道里疯狂地刮,当太阳照射到挡风玻璃上的时候也是如此。所以现在你要做的是,你必须修改你的训练集。所以突然之间,我需要更多隧道的图像,我需要确保网络知道你不应该在隧道里打开雨刷。现在我需要添加这些图像,我需要在数据集中有足够的图像,并且要注意这个问题。但如果你做得很好,它实际上是可以工作的。我们已经把它发布出去了,它在一定程度上是可以工作的,我们仍在改进它。

当挡风玻璃上有很多水的时候,它肯定会刮。事实上,即使你把玉米片放在上面,它也会刮,根据这个叫做“它会刮玉米片吗?”的视频,它会刮番茄酱,但不会刮玉米片。这很酷。

所以,我在特斯拉工作了一年,并尝试真正应用这项技术的体会是,这是一种全新的软件设计方式,我们需要相应的工具。

我们编写软件1.0已经很长时间了,我们已经编写了IDE(集成开发环境),例如,我们有IDE可以帮助我们编写代码。所以,你知道,我们有一些非常棒的程序,可以做语法高亮显示、跳转到定义、调试器、分析器等等,这些基础设施可以帮助你编写代码。但现在,我们不是显式地编写代码,而是在积累和处理数据集。这些数据集实际上就是代码,因为它们会被优化算法编译成代码。所以你的数据集实际上就是代码。那么,数据集的IDE是什么呢?

我们自己也有一些答案,我们仍在努力开发它。我不会展示具体的界面,但只是想让大家从高层次上了解一下,我们发现非常有用的一些东西是围绕数据集的可视化。当然,要确保你有一个非常广泛的分布,你想查看标签分布,你想查看每个图像的一些标签,网络对任何图像的一些预测。

所以,很多基础设施只是为了了解数据集中有什么,因为这实际上就是你的代码。标注当然非常重要,所以我们有一些非常复杂的工具。我们正在设计一个类似于Photoshop的工具,专门用于数据标注。

这些软件2.0工作者,他们的全职工作就是标记数据。你不需要让他们成为高级用户,你只需要让他们高效地工作。这不仅仅是标注本身,通常情况下,你有一支劳动力队伍。所以现在你需要确保,当一个标记员感到困惑的时候,他们不会只是做一些随机的事情,他们需要能够上报一个功能,上报一些他们感到困惑的图像,你需要在以后解决这个问题,或者你需要标记他们之间的分歧。你需要确保他们的表现良好。当然,你可能希望有一层人工智能来帮助他们,就像他们在编程一样。你必须尽你所能帮助他们。

我再举一个例子,说明如何清理数据集。可以帮助你做到这一点的人工智能是,你的网络实际上可以判断一个图像的标签是否可疑。例如,如果你正在标注车道线,最左边的那条车道线的损失会很小,因为网络会认为:“哦,是的,那是对的。”但如果你不小心把车道线标注在了天空中,网络实际上可以把它标记出来,并说:“嗯,那看起来很奇怪,我会对它做出很多错误的预测。”所以我们可以创建这些干净的数据集,我们可以帮助标记员找到数据中的错误。

顺便说一下,这不仅仅是由于错误造成的,而且如果我们更改了标注说明,我们经常这样做,那么当你更改了标注文档后,突然之间你的很多数据实际上就被错误地标注了,你需要回过头来修复它。

我们还非常担心的一件事是,通常情况下,你有很多标记数据,但你有更多未标记数据。在我们的例子中,我们有车队,我们实际上有无限的数据。问题不在于如何用无限的数据进行训练,问题在于如何明智地选择应该标记哪些数据,因为我必须为这些标记付费。哪些例子值得标记?当然,这是你的网络不确定或预测错误的地方,你如何把它们标记出来?你如何把它们展示给标记员,并向他们展示网络实际上在这里做出了错误的预测?

所以,最终你会得到我所说的“数据引擎”,为了解决这些问题,你实际上需要将围绕数据基础设施和数据集处理的许多微服务结合起来。

所以,当你注意到一个问题,比如隧道让我们的自动雨刷过于兴奋,我们需要有一种方法来增加隧道的数量,我们有很多基础设施来标记这些相似的图像。然后我们标记它们,然后我们训练、重新训练和重新部署,我们为所有的任务、所有的摄像头运行这个数据引擎。

这样做的好处是,程序员不需要自己处理所有的边缘情况。你已经用同样的方式解决了所有问题,因为现在你只需要转动数据曲柄,处理所有这些问题,积累这些数据集,并拥有所有问题的基础设施,比为所有失败的情况编写显式代码要容易得多。所以我们用这种方法让所有问题看起来都一样。然后我们训练网络,发布它们,我们只是处理这些数据集。

如果我们能把工作做得很好,我们就能让这个漂亮的机器人很好地驾驶。然后更多的人会购买特斯拉汽车,未来在地球上和地球之外都将是一个美好的地方。

如果你对软件2.0栈非常感兴趣,想把它推向极致,请联系我们。我们需要更多的人来帮助我们构建整个软件栈和基础设施。

好的,谢谢大家。

0 人点赞