接第二部分 Advanced Learning Algorithms
文章目录
Machine learning development process
这一部分将学习开发机器学习系统的过程。
(机器学习开发的迭代)Iterative loop of ML development
开发机器学习系统的过程:
首先决定系统的总体架构是什么,这意味着选择机器学习模型以及决定使用什么数据。然后根据这些决定来训练模型。第一次训练一个模型时,几乎永远不会像想要的那样工作,因此需要实施一些诊断,比如查看算法的偏差和方差以及错误分析(error analysis),然后根据诊断结果做出提高算法性能的决定,比如扩大神经网络、更改正则化参数 λ 、添加更多的训练数据、使用更多的特征或使用更少的特征。然后使用改进后的体系结构再进行这个循环,并且通常需要通过多次迭代,直到获得想要的算法性能。
下面看一个“构建垃圾邮件分类器(spam classification)”学习算法的例子:
错误分析(error analysis)
运行诊断以选择下一步如何提高算法性能,诊断方法中偏差和方差是最重要的方法,其次就是错误分析方法。
假设 m c v = 500 m_{cv}=500 mcv=500(有500个交叉验证样例),学习算法错误分类
了500个交叉验证样例中的100个,错误分析(error analysis)过程是指手动查看这100个样例,并试图深入了解算法出错的地方。
错误分析(error analysis)常用的方法是从交叉验证集中找到一组错误分类
的样例,并尝试将它们分组为共同的主题或共同的属性或共同的特征。
比如注意到很多被错误分类
的垃圾邮件是药品销售,对错误分类
样例进行分组,有21个药物垃圾邮件。有3个是“故意拼写错误”。有7个异常邮件路径。18个“窃取密码”的钓鱼邮件。有5个嵌入图片的垃圾邮件(嵌入图片的垃圾邮件使得学习算法更难进行分类)。【这些分组类别可以重叠,比如一封邮件可以属于多个分组,既属于药物垃圾邮件,又属于“故意拼写错误”,钓鱼邮件】
最终这些分组中数量最多的似乎是个大问题,因此应该优先解决大问题,这能使学习算法的性能显著提升。
这里仅有100个错误分类
样例,如果有更多比如有1000个错误分类
样例,这时如果没有时间查看所有错误分类
样例,可以随机抽取大约100个错误分类
样例。
在这个例子中错误分类
样例中“药物垃圾邮件”是最多的,因此优先解决这个问题能给学习算法性能带来显著提升。此时如果要添加更多数据,这时应该添加更多的药物垃圾邮件数据,以便学习算法更好地识别药物垃圾邮件,而不是添加全部类型的垃圾邮件数据。或者添加一些与药物相关的特征,以便学习算法更好地识别药物垃圾邮件。
解决了“药物垃圾邮件”再来解决错误分类
样例中第二多的钓鱼邮件。此时如果要添加更多数据,这时应该添加更多的钓鱼垃圾邮件数据,以便学习算法更好地识别钓鱼垃圾邮件,而不是添加全部类型的垃圾邮件数据。或者添加一些与钓鱼链接URL相关的特征,以便学习算法更好地识别钓鱼垃圾邮件。
训练“垃圾邮件分类器”模型时,第一次训练完模型并没有像想象中那样工作,可能会有多种想法提高学习算法的性能:
通过上面的例子可知,偏差和方差诊断以及错误分析对于决定下一步对模型进行哪些更改带来的提升更大非常有帮助。
错误分析(error analysis)的局限性是容易解决人类擅长的问题,因为需要手动的查看错误分类
样例的内容并进行分组。而对于人类不擅长的问题,错误分析会更难,比如试图预测某人会点击网站上哪些广告,人类很难预测某人会点击哪些广告,因此对于这个例子来说,错误分析会比较难。
添加数据(Adding data)
在「添加数据」这一部分将学习一些技巧,用于添加数据或收集更多数据,有时也能为学习算法创建更多数据。
在训练机器学习算法时,总是希望有更多的训练数据,因此想获取所有内容的更多数据。但是尝试获取所有类型的更多数据可能既缓慢又昂贵,相反,添加数据的另一种方法是只添加最有可能提升学习算法性能的数据,上一部分的「错误分析」可以帮助分析哪些类型的数据是最有可能提升算法性能的(优先解决大问题)。【当然如果有方法能添加更多的所有类型的数据,那更好】
针对数据集为图像、音频的,有一种技术可以显著增加这种训练集大小,这种技术称为数据增强(data augmentation):用现有的训练样例创建新的训练样例。
如果你创建的学习算法要识别 A-Z 的字母图像。从已有训练集中选择一张图片A,通过旋转
、放大
、缩小
、改变对比度
、左右翻转
等方法扭曲图像,这些扭曲后的图像仍然是字母A,而不是其他字母,从而获得新的训练样例。
数据增强(data augmentation)是通过扭曲现有图像生成新的训练样例,因此这种方法也可以提高算法的准确性,使算法能应对不同情况。
还可以在字母A上放一个网格,通过引入网格的随机扭曲,可以得到更丰富的字母A示例库。并将其添加到训练集中提供给学习算法,使学习算法更稳健。
这种数据增强方法也适用于“语音识别”。
训练集中有一段原始音频,可以将原始音频分别与不同的噪音背景进行合成从而生成新的训练示例,同样这种方法不仅可以提供更多的训练样例,也能使学习算法更稳健,在不同情况下都能准确识别。
数据增强并不是盲目的对已有训练样例进行扭曲,对已有训练样例所做的扭曲应该是测试集中存在的类型(或者说数据增强得到的东西应该与测试集中的东西非常相似),这样才能增加学习算法的稳健性。比如对字母A进行扭曲可以通过旋转
、放大
、缩小
、改变对比度
、左右翻转
等方法,因为这些扭曲后的图像在测试集中存在(或者说在生活中是经常见到的),而如果对字母A进行上下翻转
进行扭曲,这显然有些不合理,因为倒着的字母A在测试集中不存在(或者说在生活中极少见到倒着写的字母A),因此这种扭曲是没有意义的。
数据合成(data synthesis),可以从头开始构建全新的训练样例(不是修改已有训练样例,而是创建全新样例)。
以照片OCR(OCR,optical character recognition。识别图片中的文本)为例:
照片OCR任务的一个步骤是看这些小图像,并识别中间的字母。为此任务创建人工数据的一种方法是在计算机的文本编辑器中使用不同的字体编写随机文本,使用不同颜色、不同对比度的字体截屏,就可以得到右边那样的合成数据。(左边是拍摄的真实照片中提取的数据;右边是人工合成的数据)。【编写代码给特定应用程序进行数据合成可能需要大量工作,但这样可以为应用程序生成大量数据,并提高学习算法的性能】
数据合成(data synthesis)方法最有可能应用于计算机视觉,而较少应用于其他程序。
机器学习系统或AI系统=code(algorithm/model)+data。在过去,大多数研究人员会固定数据集,专注研究算法或模型。而今天,我们可以使用线性回归、逻辑回归、神经网络、决策树等强大算法或模型,这些算法已经非常好并且适用于许多应用程序;因此,专注于设计算法使用的数据会更有成效。
迁移学习:使用其他任务中的数据(Transfer learning:using data from a different task)
有一些应用程序没有那么多数据,并且很难获得更多数据。迁移学习(transfer learning)可以从几乎不相关的任务中获取数据用于该应用程序,从而提升算法性能。
神经网络有时可以使用不同任务的数据让算法做得更好,但这并不适用于所有事情,但当它适用时,它会非常强大。
对于没有那么多数据的应用程序,迁移学习(transfer learning)是一种很棒的技术,可以让你使用来自不同任务的数据来帮助你的应用程序。
迁移学习(transfer learning)工作原理:
假设要进行“手写数字识别0-9”,但没有那么多手写数字的训练数据。
假设你找到了一个非常大的数据集,其中包含一百万张图片,拥有猫、狗、汽车、人等一千个类别。然后可以在这个一百万张图片的大型数据集上训练神经网络,将图像 X 作为输入,并学习识别这1000个类别。(假设在该大型数据集上训练的神经网络有5层)
要应用迁移学习,那就需要复制训练好的神经网络,所有的隐藏层(包括隐藏层参数)都一样,但对于输出层需要进行修改。原神经网络输出层有1000个神经元(输出1000个类别),在“手写数字识别0-9”中要将输出层该为10个神经元(输出10个类别)。输出层的参数不能复制过来,因为输出层已经修改了(原输出层有1000个神经元,现输出层仅有10个神经元),需要从头开始训练输出层参数。
在迁移学习中要复制所有隐藏层及其参数,以这些参数为起点(初始值)运行优化算法如梯度下降或Adam优化算法。
训练复制后的神经网络有两种方式:
- 只训练输出层参数。
- 训练神经网络中的所有参数(隐藏层和输出层),但隐藏层参数的初始化值是复制过来的参数。
如果有一个非常小的训练集,那么方式1会好些;如果有一个稍微大点的训练集,那么方式2会好些。
以上举例的方法就是迁移学习,因为是通过学习识别猫、狗、人等其他类别,希望它已经为处理图像输入的早期层学习了一些合理的参数集。然后通过将这些参数转移到新的神经网络,新的神经网络从一个更好的地方开始训练参数,这样就可以学习的更好更快。
迁移学习的步骤:
- 首先在大型数据集上训练
- 然后在较小的数据集上进一步调整参数
第1步称为监督预训练(supervised pre-training):在非常大的数据集(如一百万张完全不相关任务的图像)上训练神经网络。
第2步称为微调(fine tuning):获取预训练中的参数作为初始值,然后进一步运行梯度下降或Adam优化算法以微调权重以适应目标数据集。
迁移学习的好处是你并不需要进行监督预训练,对于很多神经网络,已经有研究人员在大型数据集上训练了神经网络(预训练模型)并将其发布在Internet上供任何人下载和使用。只需要下载这些预训练的神经网络,然后将输出层替换为自己的输出层并只训练输出层参数
或训练神经网络中的所有参数(隐藏层和输出层)
即可。只需要在预训练神经网络上进行微调就可以快速得到一个在你的任务上表现良好的神经网络。
为什么迁移学习有用?(怎么可能通过识别猫、狗、汽车和人等类别获得的参数来帮助你“识别手写数字”这样不同的东西?)
简单解释一下:如果训练神经网络来检测图像中的不同对象,那么神经网络的第一层可能会学习检测图像中的边缘(edges)
(认为是图像中用于检测边缘的低级特征)。然后神经网络的下一层学习将边缘组合在一起以检测角点(corners)
,神经网络的下一层可能已经学会检测一些更复杂的东西比如通用形状
。这样通过学习检测大量不同的图像,神经网络学习了检测非常通用的特征:边缘
、角落
、基本形状
,这对于其他计算机视觉任务很有用,比如“手写数字识别”。
注意:
使用迁移学习时的预训练模型的输入类型必须与你的任务输入类型是一样的。(如果你的任务是计算机视觉任务,输入的是图像,那么你需要的是在图像数据上进行预训练的神经网络。如果你的任务是“语音识别系统”,输入的是音频,那么你需要的是在音频数据上进行预训练的神经网络。其他类型的任务亦是如此)
迁移学习的两个步骤:
- 下载预训练神经网络,其参数已在与你的任务具有相同输入类型的大型数据集上进行了预训练。
- 根据你自己的数据进一步训练/微调。
如果你听过GPT-3、BERT或在ImageNet上预训练的神经网络,这些都是在非常大型的文本数据集或图像数据集上进行预训练,然后可以在其他应用程序中对其进行微调。(这些都是预训练的成功应用)
迁移学习实际上就是使用预训练模型,这经常使用。
机器学习项目的完整周期(full cycle of a machine learning project)
构建机器学习系统时,训练模型只是难题的一部分。
以“语音识别”为例说明一个机器学习项目的全周期:
机器学习的第一步是确定项目范围
(决定项目是什么以及想做什么)。第二步收集数据
。第三步训练模型
,并根据错误分析(error analysis)迭代改进模型;在开始训练模型并进行错误分析或偏差、方差诊断后可能会返回以收集更多数据,或者只是收集更多特定类型的数据以提高学习算法的性能。绕着这个循环几次,直到模型足够好,然后在生产环境中部署。第四步部署
,之后还需要接着监控系统的性能并维护系统以防止性能变差。部署后发现并没有像想象中那样工作,可以回去改进训练模型,也可以回去收集更多的数据。(如果你有权使用生产环境中产生的数据,那么就可以将其投入到训练集中改进模型,从而不断提高系统性能)
下面讨论在生产环境中部署的细节:
在训练了一个机器学习模型后,部署该模型的一种常见方法是在服务器中采用你的机器学习模型,将该服务器称为推理服务器(inference server),调用你的机器学习模型进行预测。然后,你的团队实现了一个移动应用程序(Mobile app),比如社交应用程序,那么当用户与应用程序交谈时,应用程序可以进行API调用(API call),将输入特征送到推理服务器,推理服务器根据输入特征进行推理,将预测值送回应用程序。这是应用程序调用API和推理服务器工作的常用方法。
为了实现应用程序调用API将输入特征送入推理服务器,推理服务器再将预测值返回应用程序需要软件工程(software engineering)编写代码:
根据应用程序为少数用户服务器还是为百万用户服务(规模)来编写代码以保证可靠和有效。在用户同意的情况下记录输入特征x与预测值 y ^ \hat y y^。这些记录对监控系统有帮助。(比如在2024年诺贝尔化学奖刚公布时,我询问GPT 2024诺贝尔化学奖得主,它给我的反馈是2024年诺贝尔化学奖还未公布。当我把2024年诺贝尔化学奖得主名单及其论文发给GPT后它给出了正确答案。这就是模型的数据库还未更新,监控系统能够弄清楚数据何时发生变化以及算法何时变得不那么准确,然后重新训练模型,执行模型更新以用新模型替换旧模型)
在机器学习中有一个不断发展得领域:MLOps(machine learning operations,机器学习操作),指如何系统地构建、部署和维护机器学习系统,用以确保机器学习模型可靠、可拓展、对模型进行更新。
公平、偏见与伦理(fairness,bias and ethics)
现在机器学习正在影响数以亿计的人,如果你正在构建一个影响人们的机器学习系统,你需要确保你的系统相当公平、没有偏见、并遵守道德。
先来看一些出现“偏见”的机器学习系统:
- hiring tool that discriminates against women(歧视女性的招聘工具)。
- facial recognition system matching dark skinned individuals to criminal mugshots(面部识别系统更容易将深色皮肤的人与罪犯的面部照片相匹配)。
- biased bank loan approvals(有偏见的银行贷款审批)。
- toxic effect of reinforcing negative stereotypes(强化负面刻板印象的毒性效应)。
除了偏见和不公平对待问题外,还存在机器学习算法的负面用例:
- deepfale(深度造假。比如未经允许伪造视频)。
- spreading toxic/incendiary speech through optimizing for engagement(针对特定用户传播有毒/煽动性言论)。
- generating fake content for commercial or political purposes(为商业或政治目的制造虚假内容)。
- using ML to build harmful products, commit fraud etc(利用机器学习制造有害产品,进行欺诈等)。
一些建议用于创建更少偏见、更公平、更符合道德规范的机器学习系统:
- get a diverse team to brainstorm things that might go wrong, with emphasis on possible harm to vulnerable groups(组建一个多元化的团队来集思广益可能会出错的事情,并强调可能造成的伤害)。
- carry out literature search on standards/guidelines for your industry(对你所在行业的标准/指南进行文献检索)。
- audit systems against possible harm prior to deployment(在部署系统之前,审计系统以防止可能的危害)。
- develop mitigation plan(if applicable), and after deployment, monitor for possible harm(制定缓解计划(如果适用),并在部署后监测可能的危害)。【一个简单的缓解计划是回滚到认为相当公平的早期系统。在部署后继续监控危害,以便可以触发缓解计划并迅速采取行动。比如在退出自动驾驶之前制定了缓解计划,以防万一汽车发生事故,可以立即执行缓解计划,而不是让汽车发生事故,才在事后争先恐后地弄清楚该怎么做】
Skewed datasets
这一部分会学习精确度(precision)和召回率(recall)这两个衡量学习算法的指标。
倾斜数据集的误差指标(Error metrics for skewed datasets)
如果你正在开发一个机器学习算法,其中正例(positive example)与负例(negative example)的比例非常倾斜,与50%:50%相去甚远,那么通常的误差指标( J t r a i n J_{train} Jtrain, J c v J_{cv} Jcv, J t e s t J_{test} Jtest)效果不好。
举例说明:
假设正在训练二分类模型来检测一种罕见病患者。如果存在疾病则 y = 1, 否则 y = 0。
假设你的学习算法在测试集上达到了1%的误差,那么你的诊断正确率为99%,这似乎是一个很好的结果。但是如果这是一种罕见病,y = 1非常罕见,如果在人群中只有0.5%的人患有这种疾病,那么如果将你的学习算法更改为print(y=0)
,即令它始终预测 y = 0,这实际上有0.5%的误差(99.5%的准确度),这样来看这个愚蠢的算法优于你的学习算法。但显然print(y=0)
不是有用的,它永远不会预测任何人患有这种疾病。
因此对于这样的倾斜数据集(正例(positive example)与负例(negative example)的比例非常倾斜),仅使用误差( J t r a i n J_{train} Jtrain, J c v J_{cv} Jcv, J t e s t J_{test} Jtest)来判断算法的性能是不行的,我们会引入另外的指标精确率(precision)和召回率(recall)。
y = 1是罕见的类别,例如想要检测的罕见疾病。
评估“预测罕见类别”算法性能,可以构建混淆矩阵(confusion matrix):一个2×2矩阵。
矩阵的顶部写下实际的类(actual class):1、0。矩阵的左边写下预测的类(predicted class):1、0,即你的学习算法在给定的例子上预测了什么。
为了评估学习算法在交叉验证集或测试集上的表现,会计算出每个的数量。比如假设有100个交叉验证示例,其中有15个示例学习算法predicted class=1,且actual class=1;有5个示例学习算法predicted class=1,而actual class=0;有10个示例学习算法predicted class=0,而actual class=1;有70个示例学习算法predicted class=0,且actual class=0。
- 将actual class=1且predicted class=1称为True positive(TP),因为预测是positive并且实际上也是positive。
- 将actual class=0且predicted class=0称为True negative(TN),因为预测是negative并且实际上也是negative。
- 将actual class=0且predicted class=1称为False positive(FP),因为预测是positive而实际上是negative。
- 将actual class=1且predicted class=0称为False negative(FN),因为预测是negative而实际上是positive
精确度(precision)定义为:在预测患病的人中实际患病人数所占的比例(在所有预测为positive的示例中,实际上是positive的示例所占的比例)。
精确度(precision)的计算公式:
T r