2.1 学习算法
机器学习算法可以简单理解为是一种能够从数据中学习的算法。那么什么是学习呢?我们使用Mitchell(1997)提出的定义:“对于某类任务T(Task)和性能度量P(Performance Measure),如果一个计算机程序在某项任务T中,其性能P能够随着经验E(Experience)而自我完善,那么我们就称这个计算机程序在从经验中学习。”
如果你对于以上的定义有些不太理解,没关系,那本来也只是让你去大体了解一下而已,其实学习就是一个逐渐优化的过程,我们需要不断地体会与领悟。讲一个少年小飞的故事,小飞和小鱼是男女朋友,关系还算融洽,经常会一起吃饭。每次约好一起去吃饭,小飞都会兴冲冲地跑去等小鱼,但每次都要等很久,小飞也不敢抱怨,但也不想傻傻地站在楼下,两手插在口袋里等待,于是他就开始了“学习”。小飞的任务是“缩小等待的时间”,于是在约好吃饭后就心慌慌地等待了5分钟后再出门,结果还是在楼下等了15分钟。下一次小飞就犹豫地等待10分钟后再出门,还是多等了5分钟。再一次,小飞就等了15分钟后再出门,结果居然还是等了10分钟。后来,小飞果断地等了25分钟后再出门,结果就被小鱼胖揍了一顿……从以上的小飞悲惨故事中,你是否对于任务、性能度量和经验有了点感悟。如果还没有,没关系,旅程还长,你总会知道的。还有一点需要说明就是小飞的学习是无用的,因为学习的前提是要有潜在规律,老实地在楼下等待虽然是万全之策,但是小鱼出门时间是没有规律的。
2.1.1 学习任务
我们相对正式地去定义“任务”一词,但要记住,学习并不是任务本身。学习指的是获得执行任务的能力。比如,我们想要机器人行走,那么行走就是任务,我们可以让机器人学习行走,也可以直接编程让机器人行走。
机器学习任务通常被描述为一个“范例”或“数据”,然后研究机器学习系统怎么样去处理这个“范例”或“数据”。一条数据是一个特征集合,这些特征度量了需要机器学习系统处理的事情。我们通常将一条数据表示为一个n维实数向量x∈Rn,而xi是该向量的一个特征。如果读者不太理解向量,可以把向量简单地理解成一维数组即可,而该数组中的每一元素就是一个特征。例如,我们想要完成图像识别任务,那一张图片就是一条数据,图片中的每一个像素就是一个特征。机器学习可以解决许多任务,接下来我们列举一些最常见的机器学习任务。
- 分类(Classification):分类任务是最常见的机器学习任务之一,其目的是让程序判断一组数据应该属于哪些类别,例如对象识别任务和语音识别任务等。可以说与“识别”一词相关的任务,很大程度上都属于分类任务。要解决这类问题,学习算法通常要执行一个函数f,该函数将数据映射到一个k类别的空间,形式化表示为f : Rn→{1,…,k},也可以使用y=f(x)表示该映射关系,其中输入数据表示为向量x,输出y为一个整数值,表示分类代号。但有时我们并不输出一个离散的y值,而会输出实值概率分布。比如,要判断一封邮件是否是垃圾邮件,这是一个典型的二分类任务,输出“1”表示该邮件为垃圾邮件,输出“0”表示该邮件为正常邮件,但也可以输出“0.8”,表示为该邮件为垃圾邮件的概率为0.8。
- 回归(Regression):回归任务就是要求程序根据输入数据来预测一个数值,比如:股市预测任务和天气预测任务等。为了解决这类问题,学习算法需要将n维特征映射到一个实数空间,表示为f:Rn→R,除了输出格式的不同,这类任务和分类任务没有本质区别。
- 机器翻译(Machine translation):该任务是深度学习领域中最激动人心的任务之一,目前深度学习在图像识别领域取得了重大突破,但很多学者认为视觉虽然非常复杂,但这是大多数动物都具有的基础性能力。可是语言不一样,语言是人这一类比较高级的生物才具有的能力,因此有人断言,深度学习很难在自然语言处理领域取得较大突破。深度学习在自然语言处理领域的突破,造成了深度学习研究者与自然语言处理研究者的激烈讨论,有时甚至恶化到互相排斥的冲突,但在嘈杂之下,也不断地激发人们去深思“智能”的内涵。在机器翻译任务中,输入的数据是由序列信号组成的语言构成,计算机程序需要将该组序列转换成另一种语言序列信号,比如我们将英语转换为中文。这种转换可以是文本转换,也可以是音频的转换。
- 结构化输出(Structured output):结构化输出是指我们的输出结果为一个向量,这是一类宽泛的任务,前面提到的机器翻译就属于其中。图2-1为Google做的一项融合图像识别与机器翻译的图像说明应用,该应用在网络的前几层使用卷积神经网络提取图像特征,然后再将这些特征输入进循环神经网络,将图像特征转换为文字信号输出。其输入为一张图片,而输出为图片的文字描述。
- 异常检测(Anomaly detection):生活中有很多事情并不常见,但我们却很担心这种小概率事件的发生,异常检测就是用程序检测这些离群数据。比如:金融领域中信用卡欺骗越来越常见,由此造成的损失一向难以估计。这些欺诈行为非常严重地扰乱了正常的市场经济秩序,同时也损害了公司以及诚信消费者的切身利益。这类任务的困难在于异常数据相对正常数据而言太少,甚至有时还需要解决未曾发生过的状况。
- 降噪(Denoising):在机器学习中,我们总是假定已知数据和未知数据是相似的,我们在已知数据中找寻各种规律、各种模式,然后将已知数据中学习到的模式应用到未知数据中。但在某种程度上,其实是在“自欺欺人”,因为已知数据和未知数据之间是有噪声的,这些噪声造成了实验结果和实际结果的误差。机器学习的一个重要研究方向就是让机器拥有强大的抗噪声能力去对抗这些误差。为了获得这种健壮性,我们在数据中加入一些噪声学习,从“污浊”的数据中还原“干净”的数据,从而期望学习模型能够学习到更强的抗噪能力。
以上介绍的仅仅是机器学习任务中的沧海一粟,我们只列举了一些常见的机器学习任务。其实说到底,机器学习就是试图替代或辅助人的智能行为,或许人的智能所触及之处,都将是机器学习努力的方向。
图2-1 图片说明应用示例
2.1.2 性能度量
为了评估机器学习算法在某项任务中的好坏,我们就必须设计方法去量化其性能。比如在分类任务中,我们经常衡量模型的精度(accuracy)。精度其实就是正确分类数据与全部分类数据的比值。与之相对应,我们去测量错误分类数据在全部数据中的比例,就将其称之为错误率(error rate)。我们也经常将错误率称为0-1损失期望。在0-1损失中,我们将分类错误的数据记为1,而分类正确的数据就记为0,累加错误分类数据之后,再除以全部的分类数据,就得到了0-1损失期望值。
机器学习算法是要在实际环境中运行的,也就是说,机器学习所面临的数据是未知的。就像我们人一样,学得再多,也只是纸上谈兵,实践才能出真知。但未来总是复杂多变的,庄子曾说过“吾生也有涯,而知也无涯,以有涯随无涯,殆已。”那我们又怎样固执地从已知中,头破血流地去追寻未知呢?因此我们需要“假造”一些未知数据,我们称之为测试数据集(test set of data),我们将训练好的机器学习算法拿到这些测试数据集上进行性能测量,然后我们就“自欺欺人”地宣称我们设计的算法如何的好。测试数据其实也是已知数据的一部分,只是这部分数据我们会密封起来,只在最终的性能测量时才使用。如果拿课程学习作为类比,那平时自己做的练习题或家庭作业就是我们的训练数据(training set of data),而老师组织的月考、期中考,我们也称为验证数据(在本章2.5节中详细描述),最后参加的期末考试我们就称之为测试数据。这三部分数据全是已有的数据,其中训练数据只用来训练,学生(学习算法)的目标就是在这部分数据上不断提高性能,而老师(算法调整人员)会使用验证数据监控学生的学习情况,然后去调整学生的学习方式。当老师认为该学生已经无法再提高时,就使用测试数据模拟未知数据对学生进行最后的性能测试。
- 查全率与查准率
错误率和精度是最常用的度量方式,但在特定的任务中,我们还需要一些额外的度量方式。比如进行信息检索时,我们经常需要关心“检索的信息中有多少是用户感兴趣的”以及“用户感兴趣的信息有多少被检索出来了”这两类问题,而此时,我们引入查准率(precision)与查全率(recall)。
为了更好地介绍查准率与查全率,以二分类问题为例,我们需要将分类器预测结果分为以下4种情况。
(1)真正例(True Positive,TP),分类器预测1,真实类标为“1”的分类数据。
(2)假正例(False Positive,FP),分类器预测1,真实类标为“0”的分类数据。
(3)真反例(True Negative,TN),分类器预测0,真实类标为“0”的分类数据。
(4)假反例(False Negative,FN),分类器预测0,真实类标为“1”的分类数据。
而TP+FP+TN+FN=数据总量,如表2-1所示为混淆矩阵(Confusion Matrix)。
表2-1 混淆矩阵
如式(2.1)所示,查准率P就是分类器预测结果为“1”中预测正确的比率。
查全率R就是全部真实类标为“1”的数据中分类器预测正确的比率,如式(2.2)所示。
查准率与查全率是一对“鱼”与“熊掌”,一般来说,查准率高时,查全率往往偏低;而查全率高时,查准率往往偏低。例如,如果想要将垃圾邮件都选取出来,可以将所有邮件都标记为垃圾邮件,那查全率就可以接近于1了,但这样查准率就会比较低;如果希望分类垃圾邮件的查准率足够高,那么让分类器尽可能挑选最有把握的垃圾邮件,但这样往往会有大量的垃圾邮件成为漏网之鱼,此时查全率就会比较低。
需要注意的是,性能度量也依赖于所需完成任务的应用场景。任务场景不同,度量手段也不相同,如果性能度量选取不当,对于该任务可能是毁灭级的。比如我们让机器完成指纹识别任务,但应用在超市中和应用在安全机构部门的指纹识别系统,其性能度量方式完全不同。在某个超市会员系统中,需要识别用户的指纹以确定用户是否为会员,然后对部分商品进行打折或抽奖服务,此时我们并不关心指纹识别的精确度,假设一个会员用户总是被识别错误,那么该用户就会非常恼火,超市很有可能就会失去一个老顾客。相反,将一个非会员顾客识别错误,其损失就没那么高,或许还有可能获得一个新会员,因此该任务会更关心查全率,也就是期望所有会员都要被识别出来。但如果将指纹识别应用在某安全部门,用于识别员工的身份,此时我们就更关心识别员工的正确性,因此机器只会在最有“把握”的情况下才允许员工通过,此时我们更关心查准率,我们或许情愿对员工识别错误100次,也不愿意放过一个非员工,或许此时机器可能“非常不好用”,但安全性得到了保障。
2.1.3 学习经验
根据数据(经验)的类型,我们可以将机器学习算法粗略地分为监督学习(Supervised Learning)和非监督学习(Unsupervised Learning)。
监督学习算法:试图将已知数据与该数据所对应的标记或类标(label)进行关联。比如幼儿园老师教小朋友识别树,老师拿一堆图片给小朋友看,并告诉小朋友这些图片里都是树。小朋友就拿着这些图片观察(学习),之后老师就再拿些新的图片给小朋友识别,小朋友根据自己已经学习到的知识去识别新的图片,老师会告诉小朋友哪些图片识别对了,哪些图片识别错了。然后根据老师的纠正,小朋友就再次调整自己,不断地学习提高自己识别树的能力。
在我们所拥有的资料中,既有数据x(比如一张张的图片),也有数据所对应的标记y(比如老师的指导),我们从(x,y)中学习的过程就叫监督学习。例如,进行数字图像识别任务时,我们将数字图片作为数据输入到机器学习算法中,然后算法会预测出一个数字分类y',之后我们依据图片所对应的真实标记y,比较y与y'的差异再来调整学习算法。
非监督学习算法:生活中的数据绝大多数是没有标记的,并且也缺少金钱与人力去标记数据。非监督学习就是在没有指导(标记)的前提下,学习数据集内部的有用结构。最常见的非监督学习算法是聚类(Clustering),该类算法通常按照中心点或者分层的方式对输入数据进行归并,试图找到数据的内在结构,以便按照最大的共同点将数据进行归类。
从概率的角度来看,非监督学习试图通过随机变量x去学习概率分布P(x)或某些分布性质;监督学习试图使用随机变量x以及关联y,学习条件概率P(y|x),试图通过x去预测y。但监督学习与非监督学习并不是一种形式化的定义,其界限有时也很模糊。
在一些情况下,我们既有标记数据,也有大量的未标记数据,我们将这两类数据都利用起来就称为半监督学习(Semi-supervised Learning)。
有时数据需要从环境中获取,而数据对应的标记也要从环境中获取,我们并不提供标记数据,我们只提供某种评价机制(奖励或惩罚),这样的学习方式称之为强化学习(Reinforcement Learning)。就像我们教小狗上厕所,但小狗可听不懂你的话,就需要不停地奖励或惩罚其行为,小狗才可能学会上厕所。
为了统一描述,以后我们会将数据集称之为数据矩阵,也可以简单地想象为二维数组,矩阵的列为数据的不同特征,矩阵的行为不同数据。例如,我们有88张大小为32×32的灰度图片,那么数据矩阵就为X∈R88×1024,X4,20就表示为第4张图片的第20维像素。