1.1 编程与机器学习
下面是一个介绍机器学习(简称为ML)和常规编程之间区别的例子。想象一下打造一个玩电子游戏的程序。传统编程方式下的程序可能是这个样子:
其中大部分代码由if...else语句组成,还包括如shoot()等必要的指令。
现代的编程语言能够使我们构造出更好的程序结构,例如可以使用多态性、模式匹配或事件驱动调用等手段来消除这些丑陋的内嵌if语句。然而,编程的核心概念并没有发生变化,你告诉计算机要寻找什么,然后告诉它如何去做。你必须列出每个条件并定义每个行为。
这种方法十分有用,但还是有一些缺陷。首先,你必须穷尽一切可能。你可能可以想象得到电子游戏中数十或数百种的特殊情形。如果敌人正在接近,但你和敌人之间有一个能量道具,这个能量道具能帮你抵御敌人的炮火,那该怎么办?人类玩家会迅速注意到这一点,并进行充分利用。你的程序的应对……则要看情况。如果你在编程中写到了这种情况,那么你的程序就能处理这种情况。但是我们知道要涵盖所有特殊情况到底有多难,即使在结构域内也是如此。列出复杂域(如电子游戏、开卡车或图像识别)的每一种可能发生的特殊情形真的是太难了!
即使你能够列出所有的情况,那也必须首先知道应该如何去解决所有这些情况下的问题。这就是编程的第二个缺陷,也是某些领域的巨大障碍。例如,以计算机视觉任务为例,我们最初提出的问题是:在胸部扫描图片中识别肺炎。
我们其实并不知道人类放射科医生是如何识别肺炎的。没错,我们有一些笼统的概念,如“放射科医生查看不透明的区域”。然而,我们并不知道放射科医生的大脑究竟是如何识别并评估不透明区域的。在某些情况下,专家自己可能都不知道究竟是如何得出诊断结论的,而只是根据非常模糊的理由:“从经验可以判断肺炎不是这个样子的。”由于我们不知道这些决定是怎么做出的,因此不能命令计算机做出这些决定。这是所有典型的人类任务都存在的问题,比如品尝啤酒或理解语句。
机器学习彻底颠覆了传统的编程方式:机器学习不是向计算机提供指令,而是向计算机提供数据,并要求它自己想出需要做些什么。
让计算机“想出”某种东西的想法听起来像是一厢情愿,但实际上可以有几种不同的方法来实现。让我来告诉你,这些方法还是需要运行代码的。然而,这种代码并不是像传统编程那样一步一步地解决问题。机器学习中的代码告诉计算机应该如何处理数据,这样计算机就可以自己解决问题了。
举个例子,这是计算机想出如何玩电子游戏的一种方法。想象这样一种能够通过试错的方法学习如何玩电子游戏的算法。它以发出随机指令(如“开枪”“减速”“旋转”等)作为开始。如果这些指令最终能够成功运行,比如得到高分,那么算法就会记住这段经历。如果指令导致失败,比如阵亡,那么算法也会记录下来。同时,它还会记录游戏的状态,如敌人的位置、障碍物、能量道具、剩余生命值,等等。
从那时起,每当算法碰到相似的游戏状态,就更有可能采取成功率较高的行为,而不是采取失败率较高的行为。在不断的试错循环之后,这个程序就会成为一名合格的虚拟玩家。在2013年,一种使用这种方法的系统在老式雅达利游戏里取得了超越人类的成绩[1]。
这种形式的机器学习就是强化学习。强化学习很像训练狗:我们会因为狗做了“好”的事情而奖励它,这样狗就会做更多好的事情(我也用了这种方法来训练猫,但迄今为止还没有成功过)。
强化学习只是让计算机解决问题的一种方法。在本书中,我们将关注另外一种机器学习方法,可以说是目前最流行的一种。下面我们来讨论此种方法。
[1] deepmind.com/research/publications/playing-atari-deep-reinforcement-learning。