DLAI-机器学习工程师的生产实践笔记-全-

DLAI 机器学习工程师的生产实践笔记(全)

001:专项课程概述 🎯

在本节课中,我们将要学习《机器学习工程师的生产实践(MLOps)》专项课程的整体介绍。我们将了解课程的目标、涵盖的核心主题、讲师团队以及学习本课程所需的基础知识。


欢迎与课程目标

欢迎来到《机器学习工程师的生产实践与MLOps》专项课程。

假设你已经在Jupyter笔记本中训练了一个准确的机器学习模型,并为此感到高兴。你可能会想,接下来该做什么?

在开发出一个好模型之后,实际上将模型投入生产,构建一个能够持续做出有用预测的工作系统,仍然需要完成大量工作。

本专项课程将教授你构建和部署生产级机器学习系统所需的技能。你将学习完整的机器学习项目生命周期,从项目范围界定、数据处理、建模到部署,从而真正从头到尾执行一个机器学习项目。

一个常见的误解是,在本地机器的Jupyter笔记本中开发模型与将该模型部署到生产环境之间的唯一区别,仅仅在于“部署”这一步,可能只是一些软件工程工作。但事实并非如此。这不仅仅是软件工程,生产环境也带来了独特的机器学习挑战。在Jupyter笔记本中开发模型的过程,与构建和维护生产系统的学科是不同的。

构建和维护生产系统的流程与工具,有时被称为MLOps(机器学习运维),你也将学习这方面的内容。


讲师介绍

我很高兴能与来自Google TensorFlow团队的两位杰出讲师——Robert Crowe和Laurence Moroney——共同为大家带来这个新的专项课程。

Robert Crowe是Google的TensorFlow开发工程师、数据科学家和TensorFlow倡导者。Robert热衷于帮助开发者快速学习他们需要掌握的知识,希望这正是你们所需要的。

Laurence Moroney在Google领导AI倡导工作,同时也是DeepLearning.AI另外三门TensorFlow专项课程的讲师,并且是《AI and Machine Learning for Coders》一书的作者。非常高兴你们两位能加入这个专项课程的教学工作。

正如Andrew所说,除了在生产系统中构建第一个可工作的模型,你还需要处理一系列问题,包括数据漂移——你训练所用的数据分布最终可能会变得与进行推理时所用的数据分布非常不同。我们将讨论的一个关键主题是变化。世界在变化,你的模型需要意识到这种变化。

在本专项课程中,我们还将向你介绍机器学习之外的几个相关主题。你可以将生产机器学习视为机器学习本身与现代软件开发所需知识和技能的结合。

如果你在工业界的机器学习团队工作,你确实需要同时具备机器学习和软件方面的专业知识才能成功。这是因为你的团队不仅仅是产出一个单一的结果,你们将开发一个持续运行的产品或服务,并可能成为公司工作中至关重要的一部分。

根据我自己的经验,构建机器学习系统最具挑战性的方面,往往是那些你最意想不到的事情,比如部署。能够构建一个模型固然很好,但将其交到用户手中并观察他们如何使用它,可能会让人大开眼界。你可能认为自己为完美场景构建了完美模型,但你的用户可能有不同的看法,向他们学习总是非常有益的。

例如,用户可能可以接受为了频繁更新的模型而将数据轮询发送到服务器,也可能坚持他们的数据绝不能离开设备。因此,你需要了解保持他们设备上模型新鲜度的最佳方法。


课程结构与内容

本专项课程包含四门课程,为你提供启动和运行生产机器学习系统所需的知识和实践经验。

以下是四门课程的简要介绍:

  • 课程一(由我讲授):你将看到生产机器学习项目从范围界定、获取数据、建模到部署的整个生命周期的概述。
  • 课程二(关于数据及其随时间演变):在这门课程中,你将使用TensorFlow Extended(TFX)及其系列库,通过收集、清理和验证数据集来构建数据管道。为了理解数据的演变,你将使用数据溯源作为概念框架,通过ML元数据来跟踪变化。
  • 课程三(专注于生产中的机器学习建模管道):在这门课程中,你将学习如何管理建模资源,以最佳方式服务推理请求并最小化成本。你还将使用分析工具来解决模型公平性、可解释性问题并缓解瓶颈。
  • 课程四(关于部署):这意味着你需要准备好服务用户的请求。这既令人兴奋又充满挑战。在课程四中,你将交付部署管道,用于可能需要多种不同基础设施的模型服务。你还将应用最佳实践来维护一个持续运行的生产系统,使其保持最新状态,并且重要的是,始终将用户需求放在首位。

学习前提

作为本专项课程的学习者,我们假设你熟悉Python编程和机器学习,并对Python中的一种深度学习框架(如TensorFlow、Keras或PyTorch)有一定了解。

如果你已经完成了DeepLearning.AI提供的深度学习专项课程,那么你将非常适合开始学习本专项课程。当然,如果你已经完成了DeepLearning.AI的TensorFlow开发者专业课程,你将为本专项课程的学习做好充分准备。


总结

本节课中,我们一起学习了《机器学习工程师的生产实践(MLOps)》专项课程的概述。我们了解了课程旨在解决从模型开发到生产部署的完整流程挑战,认识了讲师团队,预览了四门核心课程的内容(生命周期概述、数据处理、建模管道和部署),并明确了学习本课程所需的Python编程、机器学习及深度学习框架基础。现在,让我们开始正式的学习之旅。

002:欢迎与机器学习工程概述 🚀

在本课程中,我们将学习机器学习工程的核心概念,了解将模型从实验室部署到生产环境所面临的挑战,并概述一个完整的机器学习项目生命周期。


许多学习者曾问我:“Andrew,我已经学会了训练机器学习模型,接下来该做什么?” 机器学习模型固然重要,但除非你知道如何将其投入生产,否则很难发挥其最大价值。对于寻求机器学习职位的人来说,许多面试官也会问:“你是否曾将机器学习算法部署到生产环境中?”

在这个由四门课程组成的专项课程中,第一门课程由我讲授,第二、三、四门课程则由来自谷歌的专家Robert Crowe讲授。我们希望与大家分享实用的动手技能和技术,不仅教你如何构建模型,更教你如何将其部署到生产环境中。在本课程和整个专项课程结束时,我希望你能对机器学习项目的完整生命周期——从模型训练到生产部署,以及如何管理整个项目——有一个清晰的认识。

让我们开始吧。


一个生产部署的实例

让我们从一个例子开始。假设你正在使用计算机视觉来检查生产线上的手机,以发现是否存在缺陷。左侧显示的完好手机没有任何划痕。但如果存在划痕或裂纹,计算机视觉算法有望发现这类缺陷,并可能为其绘制边界框,作为质量控制的一部分。

如果你获得了一个有划痕手机的数据集,你可以训练一个计算机视觉算法(例如神经网络)来检测这类缺陷。但为了将其部署到生产环境中,你现在需要做什么?

以下是一个可能的部署系统示例。你可能会使用一个边缘设备。所谓边缘设备,是指位于制造这些智能手机的工厂内部的设备。该设备上会运行一个检测软件,其职责是拍摄手机照片,判断是否存在划痕,然后决定该手机是否合格。这在工厂中实际上很常见,被称为自动视觉缺陷检测。

检测软件会控制一个摄像头,在手机下线时拍摄照片。然后,它需要发起一个API调用,将图片传递给一个预测服务器。预测服务器的职责是接收这些API调用和图像,判断手机是否有缺陷,并返回预测结果。随后,检测软件可以做出相应的控制决策:是让手机继续在产线上流转,还是因其有缺陷且不合格而将其分拣到一旁。

因此,在你训练了一个学习算法(例如,训练一个以手机图片X为输入,输出缺陷预测Y的神经网络)之后,你仍然需要将这个机器学习模型放入预测服务器,设置API接口,并编写所有其他软件,才能真正将这个学习算法部署到生产环境中。这个预测服务器有时位于云端。

有时,预测服务器实际上也位于边缘。事实上,在制造业中,我们大量使用边缘部署,因为你不能让工厂在每次互联网连接中断时都停工。但将预测服务器部署在云端的云部署,也用于许多应用。


部署后可能遇到的问题

假设你已经编写了所有软件。那么,可能会出什么问题呢?

事实证明,仅仅因为你训练了一个在测试集上表现良好的学习算法(这值得庆祝),并不意味着你的工作已经完成。要获得一个有价值的、运行中的生产部署,可能仍然存在大量工作和挑战。

例如,假设你的训练集中的图像看起来是这样的:

左侧是完好的手机,中间的手机有一道大划痕。你训练的学习算法可以识别出左侧这类手机是合格的(即无缺陷),并可能在发现的划痕或其他缺陷周围绘制边界框。

然而,当你将其部署到工厂时,你可能会发现实际生产部署返回的图像是这样的:由于工厂的照明条件与收集训练集时相比发生了变化,图像变得暗得多。这个问题有时被称为概念漂移或数据漂移(你将在本周后续课程中了解更多相关术语)。

这只是我们作为机器学习工程师,为了确保系统不仅在测试集上表现良好,而且能在实际生产部署环境中创造价值,所必须解决的众多实际问题之一。

我参与过不少项目,在这些项目中,我的机器学习团队和我成功地完成了概念验证。所谓概念验证,是指我们在Jupyter笔记本中训练了一个模型,并且它运行得很好,我们会为此庆祝。当你的学习算法在Jupyter笔记本或开发环境中运行良好时,确实值得庆祝。

但事实证明,有时我看到许多项目在取得这一巨大成功后,距离实际部署可能还需要六个月的工作。这只是机器学习团队为了真正部署这些系统而必须注意和处理的众多实际问题之一。

有些机器学习工程师会说,解决这些问题不是机器学习问题。例如,数据集发生了变化,一些机器学习工程师会想:“这算机器学习问题吗?” 我的观点是,我们的工作是让这些东西运转起来。因此,如果数据集发生了变化,我认为我在项目中工作时,有责任介入并尽我所能去处理数据分布的实际状况,而不是我期望的状况。本专项课程将教你许多这类重要的实用知识,帮助你构建不仅在实验室、不仅在Jupyter笔记本中,而且能在生产部署环境中工作的机器学习系统。


生产部署的第二个挑战:远不止机器学习代码

在生产环境中部署机器学习模型的第二个挑战是,它需要的远不止机器学习代码。过去十年,人们对机器学习模型(即你的神经网络或其他学习从输入到输出映射函数的算法)给予了大量关注,并且机器学习模型取得了惊人的进展。

但事实证明,如果你观察一个生产环境中的机器学习系统,假设这个橙色小矩形代表机器学习代码(即机器学习模型代码),那么这就是整个机器学习项目所需的全部代码吗?

对于许多机器学习项目,我认为机器学习代码可能只占全部代码的5%到10%,甚至更少。我想,这也是为什么当你有一个概念验证模型在Jupyter笔记本中运行良好后,从最初的概念验证到生产部署之间仍然存在大量工作的原因之一。有时人们称之为“概念验证到生产的鸿沟”。这个鸿沟很大程度上有时仅仅是因为还需要编写所有这些模型之外的代码。

那么,所有这些其他东西是什么呢?这张图改编自D. Scully等人的一篇论文。除了机器学习代码,还有许多组件,特别是用于管理数据的组件,例如数据收集、数据验证、特征提取。在模型上线服务后,还需要监控系统或监控返回的数据,以帮助你进行分析。通常,为了建立一个可运行的生产部署,还需要构建许多其他组件。在本课程中,你将学习到一个有价值的生产部署所需的所有这些其他软件组件是什么。


组织项目工作流的有用框架

与其审视所有这些复杂的部分,我发现组织机器学习项目工作流最有用的框架之一是,系统地规划出机器学习项目的生命周期。

让我们进入下一个视频,深入探讨什么是机器学习项目的完整生命周期。我希望这个框架对你未来计划部署的所有机器学习项目都非常有用。让我们进入下一个视频。


总结

在本节课中,我们一起学习了机器学习工程的重要性,它关注如何将训练好的模型部署到生产环境以创造实际价值。我们通过一个手机缺陷检测的实例,了解了生产部署的基本架构(如边缘设备、预测服务器和API调用)。我们探讨了部署后可能遇到的挑战,例如数据分布变化(概念漂移/数据漂移),并认识到从概念验证到生产部署往往需要大量额外工作。最后,我们了解到一个生产级的机器学习系统,其机器学习代码通常只占很小一部分,还需要数据管理、监控等诸多其他组件。下一节,我们将深入探讨机器学习项目的完整生命周期框架。

003:机器学习项目生命周期 🚀

在本节课中,我们将学习机器学习项目的完整生命周期。理解这个框架有助于你规划项目步骤,确保系统顺利运行并减少意外情况。


项目范围界定 📋

上一节我们介绍了课程概述,本节中我们来看看项目生命周期的第一步:范围界定。

范围界定是指定义项目目标。你需要决定将机器学习应用于何处,并明确输入 X 和输出 Y

公式项目目标 = f(X, Y)


数据收集与整理 📊

在确定了项目范围后,下一步是收集或获取算法所需的数据。

以下是数据阶段的关键任务:

  • 定义数据:明确需要哪些数据。
  • 建立基线:设定一个性能基准。
  • 数据标注与组织:对数据进行标记和整理。

本周后续课程将介绍一些关于数据的最佳实践。


模型训练与迭代 🔄

拥有了数据之后,接下来进入模型训练阶段。

在模型阶段,你需要选择和训练模型,并进行错误分析。机器学习通常是一个高度迭代的过程。

代码示例(伪代码):

model = select_model()
model.train(training_data)
performance = error_analysis(model, validation_data)

在错误分析过程中,你可能会返回更新模型,甚至可能回到前一阶段决定收集更多数据。


部署前检查与部署 🚀

在将系统部署到生产环境之前,我通常会进行最终检查或审计,以确保系统性能足够好且足够可靠。

有时人们认为部署系统就意味着项目结束。但我现在告诉大多数人,首次部署系统时,你可能只走完了全程的一半。因为往往只有在系统处理真实流量后,你才能学到让系统表现良好的另一半重要经验。

部署步骤包括:

  • 生产环境部署:将所需软件投入生产。
  • 系统监控:跟踪持续流入的数据。
  • 系统维护:例如,当数据分布发生变化时,可能需要更新模型。

监控与持续维护 🔧

初始部署后,维护工作通常意味着返回进行更多的错误分析,可能重新训练模型。这也可能意味着将系统在实时数据上运行后得到的新数据,反馈到你的数据集中,从而更新数据、重新训练模型,如此循环,直到可以将更新后的模型再次部署。


总结与展望 📝

本节课中,我们一起学习了机器学习项目的完整生命周期框架,包括范围界定、数据收集、模型训练、部署前检查、部署以及持续的监控与维护。

我发现这个框架适用于非常广泛的机器学习项目,从计算机视觉、音频数据到结构化数据等众多应用。你可以随时截取这张框架图,与朋友或自己一起用它来规划你的机器学习项目。

为了加深对这个生命周期的理解,在下一个视频中,我们将通过一个语音识别应用的具体例子,逐步了解机器学习项目生命周期各个步骤的实际操作。让我们进入下一个视频。

004:语音识别案例学习 🎤

在本节课中,我们将通过一个语音识别的实际案例,完整地学习机器学习项目的生命周期。我们将从项目定义开始,逐步探讨数据准备、模型训练、系统部署以及后续的监控维护。通过这个案例,你将了解构建一个生产级语音识别系统所需的全部步骤。


项目定义与范围确定 📋

上一节我们介绍了课程的整体目标,本节中我们来看看如何为一个机器学习项目确定范围。

深度学习的一大成功应用是语音识别。与大约十年前相比,深度学习显著提升了语音识别的准确率。这使得我们能够在智能音箱、智能手机的语音助手等场景中使用语音识别技术。你可能偶尔会听到关于构建更好语音模型的研究工作,但要实际构建一个有价值的、可投入生产的语音识别系统,还需要哪些步骤呢?让我们使用机器学习项目生命周期来梳理一个语音识别案例。

我曾在一个商业环境中参与过语音识别系统的开发,第一步就是确定项目范围。我们必须首先定义一个项目,并决定着手进行语音识别工作,例如将其作为语音搜索的一部分。在定义项目时,我鼓励你尝试估算或至少猜测关键指标。这些指标几乎完全取决于具体问题,每个应用都有其独特的目标和指标。对于语音识别,我关心的一些指标包括:

  • 准确率:语音系统的准确度如何。
  • 延迟:系统转录语音需要多长时间。
  • 吞吐量:我们每秒能处理多少个查询。

如果可能,你还可以尝试估算所需的资源,例如需要多少时间、多少计算资源、多少预算,以及项目的时间线。关于项目范围确定,我们将在本课程的第三周详细讨论,届时会回到这个话题并深入描述。


数据阶段:定义、基准与组织 📊

在确定了项目范围之后,下一步就进入了数据阶段。在这个阶段,你需要定义数据、建立基准,并对数据进行标注和组织。

实际语音识别系统的一个挑战在于数据标注的一致性。以下是一个典型的语音搜索录音片段:“today's weather”。问题是,给定这个音频片段,你会如何转录它?以下是几种合理的转录方式:

  • today's weather
  • today's weather.
  • [noise]

前两种转录方式都是完全合理的。第三种方式考虑到音频中可能存在噪音(例如碰撞声),选择不转录噪音部分。实际上,这三种转录方式都可以接受。我可能更倾向于第一种或第二种,而不是第三种。但是,如果数据集中三分之一的标注使用第一种方式,三分之一使用第二种,三分之一使用第三种,这就会损害学习算法的性能。因为数据不一致会让学习算法感到困惑,它无法猜测对于某个特定的音频片段,标注者恰好使用了哪种约定。

发现并修正此类不一致性,例如要求所有人都标准化使用第一种约定,能对你的学习算法性能产生显著影响。我们将在本课程后续部分深入探讨如何发现不一致性并进行调整的最佳实践。

对于像“today's weather”这样的音频片段,其他数据定义问题还包括:

  • 在说话者停止说话后,你希望在每个片段前后保留多少静音?是100毫秒、300毫秒还是500毫秒?
  • 如何进行音量归一化?有些说话者声音大,有些声音小。更棘手的情况是,同一个音频片段中同时存在音量极大和极小的部分。

所有这些问题都属于数据定义问题。机器学习的许多进步,即大量的机器学习研究,是由研究人员致力于提升在基准数据集上的性能所驱动的。在这种模式下,研究人员可能会下载数据并在固定的数据集上工作。这种思维方式推动了机器学习的巨大进步。但是,如果你正在开发一个生产系统,你就不必保持数据集固定不变。我经常为了提升数据质量、让生产系统运行得更好而编辑训练集,甚至编辑测试集。本课程及后续专项课程中,你将学习如何有效地、系统化地(而非临时地)确保数据质量。


建模阶段:选择、训练与错误分析 🤖

收集数据之后,下一步是建模。在这个阶段,你需要选择和训练模型,并进行错误分析。

训练机器学习模型的三个关键输入是:

  1. 代码:即你选择的算法或神经网络模型架构。
  2. 超参数
  3. 数据

运行你的代码,结合超参数和数据,就能得到机器学习模型,例如一个从音频片段学习生成文本转录的模型。

我发现,在很多研究或学术工作中,人们倾向于固定数据,然后主要调整代码超参数以获得良好性能。相比之下,对于许多产品团队,如果你的主要目标是构建并部署一个可工作的、有价值的机器学习系统,我发现固定代码,转而专注于优化数据(以及超参数)可能更为有效。机器学习系统包括代码、数据和超参数。超参数可能比代码或数据更容易优化。我发现,与其采取以模型为中心的观点,试图针对固定数据集优化代码,对于许多问题,你可以使用从GitHub下载的开源实现,转而专注于优化数据。

因此,在建模阶段,你需要选择和训练某个模型架构(例如某个神经网络架构)。错误分析可以告诉你模型在哪些方面仍然存在不足。如果错误分析能告诉你如何系统地改进数据(当然,改进代码也可以),这通常是你获得高精度模型的一种非常高效的途径。关键在于,你不需要总是感觉需要收集更多数据(虽然更多数据总是有帮助的,但可能成本高昂)。如果错误分析能帮助你更有针对性地确定具体需要收集哪些数据,这将帮助你更高效地构建一个准确的模型。


部署与监控维护 🚀

当你训练好模型,并且错误分析表明其性能足够好时,就可以进入部署阶段了。

对于语音识别,部署一个语音系统的方式可能如下:你有一部智能手机,这是一个边缘设备,上面运行着本地软件。该软件接入麦克风,录制某人说的话(例如用于语音搜索)。在典型的语音识别实现中,你会使用一个VAD模块(语音活动检测)。VAD通常是一个简单的算法(也可能是学习算法),其任务是让智能手机筛选出只包含人声的音频片段,以便只将该音频片段发送到你的预测服务器。在这个例子中,预测服务器可能位于云端。预测服务器随后返回转录文本(以便用户看到系统认为你说了什么),如果进行的是语音搜索,还会返回搜索结果。转录文本和搜索结果会显示在手机前端运行的代码中。

实现这种类型的系统,就是在生产中部署语音模型所需的工作。

然而,即使在系统运行之后,你仍然需要监控和维护系统。

我曾遇到过这样的情况:我的团队构建了一个语音识别系统,它主要是在成人语音数据上训练的。我们将其推送到生产环境后,发现随着时间的推移,越来越多的年轻人(例如青少年,有时甚至更年幼)开始使用我们的系统。而非常年轻的人的声音听起来是不同的。因此,我的语音系统性能开始下降,我们在识别年轻声音方面的表现不佳。我们必须回过头来,想办法收集更多数据或采取其他措施来修复这个问题。

因此,部署阶段的一个关键挑战是概念漂移数据漂移。这是指数据分布发生变化的情况,例如有越来越多的年轻声音被输入到语音识别系统中。知道如何建立适当的监控机制来发现此类问题,以及如何及时修复它们,是确保你的生产部署能够创造预期价值的关键技能。


总结 📝

本节课中,我们一起学习了机器学习项目的完整生命周期,并以语音识别作为贯穿始终的案例。我们从项目范围确定开始,经历了数据准备、模型训练,一直到系统部署和后续的监控维护。通过这个案例,你看到了构建一个实际可用的生产级机器学习系统所需考虑的全方位步骤。

005:课程大纲 📚

在本节课中,我们将简要介绍吴恩达《机器学习工程师的生产实践(MLOps)》课程的整体结构与学习路径。我们将从最终目标——部署开始,逆向学习建模、数据管理及项目规划等核心环节,并了解MLOps工具与原则如何系统化地支持整个机器学习项目生命周期。

课程学习路径 🔄

上一节我们介绍了机器学习项目生命周期,本节中我们来看看本课程的具体安排。

尽管项目生命周期通常从左至右进行,但为了更高效地学习,本课程将从最终目标——部署开始,逆向回溯至建模、数据管理及项目规划。

以下是本课程的核心模块安排:

  • 第一周(本周后续内容):学习部署的核心概念。
  • 第二周:学习建模。除了常规的模型训练知识,还将介绍如何系统化地采用以数据为中心的方法来更高效地提升模型性能。
  • 第三周:学习数据管理。包括如何定义数据、建立性能基线,以及如何系统化地标注和组织数据,而非在Jupyter Notebook中盲目尝试。
  • 可选部分:在第三周,我们还将提供一个关于项目规划的可选章节,分享定义高效机器学习项目的实用技巧。

贯穿课程的MLOps 🛠️

在整个课程中,您还将学习MLOps(机器学习运维)。这是一个新兴的学科,包含一系列支持机器学习项目生命周期推进的工具与原则,尤其关注部署、建模和数据这三个核心步骤。

例如,在Landing AI,我们曾手动执行许多步骤,虽然可行但效率较低。在构建了名为LandingLens的计算机视觉MLOps平台后,所有这些步骤都变得快捷许多。

MLOps的核心思想是:为项目规划、数据管理、建模和部署提供系统化的方法论,并利用软件工具来支持最佳实践。

总结与展望 🎯

本节课中我们一起学习了本课程“从目标出发,逆向学习”的整体框架。您已经了解到,部署系统是当今机器学习领域最重要且最具价值的技能之一。

接下来,让我们进入下一个视频,深入探讨部署机器学习系统所需的核心知识与重要理念。

006:机器学习部署关键挑战 🚀

在本节课中,我们将探讨将机器学习模型部署到生产环境时面临的主要挑战。我们将这些挑战分为两大类:机器学习/统计问题,以及软件工程问题。理解这些挑战是确保系统成功部署的关键。


1. 机器学习与统计挑战 📊

上一节我们介绍了部署模型时可能遇到的挑战类别。本节中,我们来看看第一类挑战:机器学习或统计问题。其中最常见的挑战之一是概念漂移和数据漂移。

1.1 概念漂移与数据漂移

概念漂移和数据漂移指的是在系统部署后,数据发生变化的情况。例如,在制造业中,你可能在特定光照条件下训练了一个检测智能手机划痕的算法,但工厂的光照条件后来发生了变化。这就是数据分布变化的一个例子。

让我们通过语音识别的第二个例子来详细说明。在构建语音识别系统时,我通常会使用一些购买或授权的数据,这些数据包括输入X(音频)和输出Y(转录文本)。此外,还可能包括用户与应用程序交互的历史数据及其转录文本。当然,这些用户数据应在获得明确许可并确保隐私安全的前提下收集。

在类似的数据集上训练好语音识别系统后,你会在测试集上评估它。但由于语音数据会随时间变化,我有时会收集一个包含最近几个月数据的深度集或保留验证集以及测试集,以确保系统在相对较新的数据上也能正常工作。

系统部署后,问题在于数据是否会再次变化。运行几周或几个月后,数据可能已经改变。例如,语言本身可能发生变化,或者人们开始使用配备不同麦克风的新型智能手机,导致音频听起来不同。这些变化可能导致语音识别系统的性能下降。因此,识别数据如何变化以及是否需要因此更新学习算法至关重要。

数据变化有时是渐进的。例如,英语语言确实在变化,但新词汇的引入速度相对较慢。有时,数据变化则非常突然,系统会受到冲击。例如,当COVID-19大流行来袭时,许多信用卡欺诈系统开始失效,因为个人的购买模式突然改变。许多原本很少在线购物的人突然开始大量在线购物,人们使用信用卡的方式发生了剧变。这实际上导致了许多反欺诈系统出现问题。数据的这种突然转变意味着许多机器学习团队在COVID-19初期需要匆忙收集新数据并重新训练系统,以适应全新的数据分布。

有时,描述这些数据变化的术语使用并不完全一致。但术语“数据漂移”有时用于描述输入分布的变化。例如,如果一位新的政治家或名人突然变得众所周知,被提及的次数比以前多得多。而术语“概念漂移”指的是期望的从X到Y的映射关系发生变化。例如,在COVID-19之前,对于特定用户,许多令人惊讶的在线购买可能标记该账户存在欺诈风险。但在COVID-19开始后,同样的购买行为可能不再引起警报,表明信用卡可能被盗。

概念漂移的另一个例子是,假设X是房屋大小,Y是房屋价格(因为你试图估算房价)。由于通货膨胀或市场变化,房屋可能随时间变得更贵,那么相同大小的房屋最终会有更高的价格,这就是概念漂移。也许房屋大小没有变化,但给定房屋的价格发生了变化。而数据漂移则可能是人们开始建造更大或更小的房屋,即房屋大小的输入分布实际上随时间发生了变化。

因此,当你部署机器学习系统时,最重要的任务之一通常是确保能够检测和管理任何变化,包括概念漂移(即给定X时Y的定义发生变化)和数据漂移(即X的分布发生变化,即使从X到Y的映射关系没有改变)。


2. 软件工程挑战 💻

除了管理数据变化,成功部署系统需要应对的第二组问题是软件工程问题。

当你实现一个预测服务,其职责是接收查询X并输出预测Y时,关于如何实现这段软件,你有很多设计选择。以下是一个问题清单,可能有助于你为管理软件工程问题做出适当的决策。

2.1 关键设计决策清单

以下是你在设计预测服务时需要考虑的一系列关键问题:

  • 实时预测 vs. 批量预测:你的应用需要实时预测,还是批量预测即可?例如,构建语音识别系统时,用户说话后需要在半秒内得到响应,显然需要实时预测。相反,我曾为医院构建系统,处理电子健康记录,运行夜间批处理流程以查看是否能发现与患者相关的信息。在这种系统中,每晚仅对一批患者记录运行一次即可。因此,是需要编写能在几百毫秒内响应的实时软件,还是可以编写仅在夜间进行大量计算的软件,这将影响你的软件实现方式。
  • 运行环境:云端、边缘还是浏览器:你的预测服务是在云端运行,在边缘运行,还是在网络浏览器中运行?如今,许多语音识别系统在云端运行,因为云端的计算资源可以实现更准确的语音识别。但也有一些语音系统在边缘运行,例如汽车内的许多语音系统。还有一些移动语音识别系统即使在没有互联网连接(Wi-Fi关闭)时也能工作,这些就是在边缘运行的语音系统例子。当我在工厂部署视觉检测系统时,几乎总是在边缘运行,因为有时工厂与互联网其他部分之间的连接不可避免地会中断,而你不能承受每次互联网连接中断(虽然很少发生,但有时确实会发生)就关闭工厂。随着现代网络浏览器的发展,在浏览器内部署学习算法的工具也越来越好。
  • 计算资源限制:构建预测服务时,考虑你拥有多少计算资源也很有用。有很多次,我在非常强大的GPU上训练了一个神经网络,结果发现我无法为部署负担同样强大的GPU组,最终不得不采取其他措施来压缩或降低模型复杂度。因此,如果你知道预测服务有多少CPU或GPU资源,可能还有多少内存资源,那将有助于你选择正确的软件架构。
  • 延迟与吞吐量:根据你的应用,特别是如果是实时应用,延迟和吞吐量(例如以每秒查询数QPS衡量)将是其他需要达成的软件工程指标。在语音识别中,希望在半秒或500毫秒内向用户返回答案并不少见。在这500毫秒的预算中,你可能只能分配大约300毫秒给语音识别本身。这就给你的系统带来了延迟要求。吞吐量指的是在给定计算资源(可能给定一定数量的云服务器)的情况下,你需要处理多少每秒查询数。例如,如果你构建的系统需要处理每秒100个查询,那么确保规划你的系统以满足QPS要求将非常有用。
  • 日志记录:构建系统时,尽可能多地记录数据以供分析和审查,以及为未来重新训练学习算法提供更多数据,可能非常有用。
  • 安全与隐私:我发现对于不同的应用,所需的安全和隐私级别可能非常不同。例如,当我处理电子健康记录、患者记录时,对安全和隐私的要求显然非常高,因为患者记录是高度敏感的信息。根据你的应用,你可能需要设计适当的安全和隐私级别,这取决于数据的敏感性,有时也基于监管要求。

因此,如果你在设计软件时参考这个清单,可能会帮助你在实现预测服务时做出适当的软件工程选择。


3. 总结与展望 🎯

本节课中我们一起学习了部署系统所需的两大类任务:编写软件以使系统能够在生产环境中运行,以及监控系统性能并持续维护系统所需的工作,尤其是在面对概念漂移和数据漂移时。

构建机器学习系统时,你会发现首次部署的实践与更新或维护已部署系统时的实践有很大不同。有些工程师可能认为部署机器学习模型就是到达了终点线。但不幸的是,我认为首次部署可能只意味着你大约完成了一半的工作,而另一半工作恰恰在首次部署之后才开始。因为即使在部署之后,仍然有很多工作要做,例如反馈数据、更新模型以在不断变化的数据面前持续维护模型。

在相关视频中,我们提到了首次部署(例如,如果你的产品从未有过语音识别系统,但你训练了一个并首次部署)与已经运行了一段时间的学习算法并希望维护或更新该实现之间的差异。

总结本视频,你看到了一些机器学习或统计相关的问题,如概念漂移和数据漂移,以及一些软件工程相关的问题,例如是否需要批量或实时预测服务器,以及需要考虑的计算和内存要求。

事实证明,当你部署机器学习模型时,存在许多常见的设计模式,即跨许多不同行业的许多应用中使用的常见部署模式。在下一个视频中,你将看到一些最常见的部署模式,以便为你的应用选择合适的一种。让我们继续下一个视频。

007:机器学习部署模式 🚀

在本节课中,我们将学习机器学习模型部署的几种常见模式。我们将探讨如何根据不同的应用场景选择合适的部署策略,并理解从“影子模式”到“全自动化”的自动化程度光谱。这些模式的核心目标是安全、可控地将模型引入生产环境。


上一节我们介绍了部署的基本概念,本节中我们来看看几种具体的部署模式。

部署用例类型

部署系统时,根据不同的使用场景,存在几种常见的用例类型。

以下是三种主要的部署用例:

  1. 推出新产品或新功能:例如,首次提供语音识别服务。
  2. 自动化或辅助人工任务:例如,在工厂中,原本由人工检查智能手机划痕,现在希望用学习算法来辅助或自动化该任务。
  3. 替换现有机器学习系统:用(希望是)更好的新版本替换旧的机器学习系统实现。

在这些用例中,有两个反复出现的主题:渐进式推广回滚机制。渐进式推广意味着,与其将大量流量导向一个可能未经充分验证的算法,不如先发送少量流量进行监控,然后逐步增加流量比例。回滚机制则意味着,如果算法因某种原因无法工作,可以回退到之前的系统。


上一节我们了解了部署的常见场景,本节中我们来看看具体的部署模式。

部署模式详解

影子模式部署

当一项任务最初由人工完成时,一种常见的部署模式是使用影子模式部署

这意味着,在初始阶段,机器学习算法将“影子”人工检查员,与其并行运行。在此阶段,学习算法的输出不用于工厂的任何决策。我们暂时完全依赖人工判断。

影子模式部署的目的是收集数据,以评估学习算法的性能及其与人工判断的对比。通过抽样输出,可以验证学习算法的预测是否准确,从而决定未来是否允许学习算法做出一些实际决策。

当你已经有一个能做出良好决策的系统(无论是人工检查员还是旧版学习算法)时,使用影子模式部署可以让你在允许算法做出任何实际决策之前,有效地验证其性能。

金丝雀部署

当你准备让学习算法开始做出实际决策时,一种常见的部署模式是使用金丝雀部署

在金丝雀部署中,你最初只向一小部分流量(可能是5%甚至更少)推出新算法,并让其做出实际决策。通过仅在少量流量上运行,即使算法犯错,也只会影响一小部分流量。这为你提供了更多监控系统的机会,并且只有在对其性能有更大信心时,才逐步增加其接收的流量比例。

“金丝雀部署”一词源自英语习语“煤矿中的金丝雀”,指的是矿工曾用金丝雀来探测瓦斯泄漏。金丝雀部署希望让你在问题产生过大后果之前及早发现。

蓝绿部署

有时使用的另一种部署模式是蓝绿部署

在蓝绿部署的术语中,旧版本的软件被称为版本,而新实现的学习算法被称为绿版本。在蓝绿部署中,路由器将图像发送到旧的蓝版本并让其做出决策。当你想切换到新版本时,你会让路由器停止向旧版本发送图像,并突然切换到新版本。

蓝绿部署的实现方式是:你有一个旧的预测服务(蓝版本)在运行,然后启动一个新的预测服务(绿版本),并让路由器突然将流量从旧服务切换到新服务。

蓝绿部署的优势在于,如果出现问题,可以轻松实现回滚。你可以非常快速地让路由器重新配置,将流量发送回旧的蓝版本(假设你一直让蓝版本的预测服务保持运行)。在典型的蓝绿部署实现中,人们会考虑同时切换100%的流量,但你当然也可以使用更渐进的版本,慢慢切换流量。


上一节我们介绍了具体的部署模式,本节中我们来看看如何根据自动化程度来设计部署系统。

自动化程度光谱

思考如何部署系统最有用的框架之一,不是将部署视为“0或1”(要么部署,要么不部署),而是设计一个系统,思考什么是合适的自动化程度

例如,在智能手机视觉检查中:

  • 最左端:无自动化,纯人工系统。
  • 影子模式:系统在影子模式下运行,算法输出预测但不实际用于工厂。
  • AI辅助:给定智能手机图片,人工检查员做决定,但AI系统可以通过用户界面高亮显示可能有划痕的区域,以帮助吸引检查员的注意力。
  • 部分自动化:如果学习算法确信手机没问题或有缺陷,就遵循算法的决定;如果学习算法不确定(即预测置信度不高),则将其发送给人工判断。
  • 最右端:全自动化,学习算法做出每一个决定。

因此,存在一个从左端(仅使用人工决策)到右端(仅使用AI系统决策)的光谱。许多部署应用将从左端开始,逐渐向右移动。你不必一定要达到全自动化,可以根据系统性能和应用需求,选择停止在AI辅助或部分自动化阶段。

在这个光谱上,AI辅助和部分自动化都是人在回路部署的例子。

对于消费者互联网应用(如网络搜索引擎或在线语音识别系统),许多企业必须使用全自动化,因为不可能在每次有人进行网络搜索或产品搜索时,都让后端人员参与工作。然而,在消费者软件互联网之外(例如工厂检查),实际上有许多应用的最佳设计点可能是“人在回路”部署,而非全自动化部署。


本节课中我们一起学习了机器学习模型的几种关键部署模式:影子模式、金丝雀部署和蓝绿部署。我们还探讨了如何根据应用需求,在从“人在回路”到“全自动化”的自动化程度光谱上选择最合适的点。这些策略的核心在于实现安全、可控和渐进的模型上线。

在讨论这些概念时,我们多次提到了监控对于及早发现问题并加以解决的重要性。在下一个视频中,让我们深入探讨如何监控系统的细节。

008:机器学习系统监控 📊

在本节课中,我们将学习如何监控已部署的机器学习系统,以确保其性能符合预期。我们将探讨监控的最佳实践,包括如何选择监控指标、设置警报阈值,以及如何通过迭代优化监控策略。


概述

监控机器学习系统是确保其长期稳定运行的关键环节。通过有效的监控,我们可以及时发现性能下降、数据分布变化或软件问题,从而采取相应措施进行维护或修复。


监控的核心方法

最常见的监控方法是使用仪表盘来跟踪系统随时间的变化情况。根据具体应用,仪表盘可以监控不同的指标。

以下是监控仪表盘可能关注的几种指标类型:

  • 服务器负载:监控计算资源的占用情况。
  • 非空输出比例:例如,在语音识别系统中,监控系统输出“无”(即认为用户没有说话)的比例。如果该比例发生剧烈变化,可能表明系统出现问题。
  • 缺失输入值比例:对于结构化数据任务,监控输入数据中缺失值的比例变化,这通常意味着数据源发生了变化。

如何设计监控指标

上一节我们介绍了常见的监控指标,本节中我们来看看如何系统地设计监控方案。

我的建议是,与你的团队一起坐下来进行头脑风暴,列出所有可能出错的情况以及你希望知晓的问题。针对每一个潜在问题,构思一些能够检测到该问题的统计数据或指标。

例如:

  • 如果你担心用户流量激增导致服务过载,那么服务器负载就是一个可以跟踪的指标。
  • 在设计监控仪表盘的初期,从较多的指标开始监控是可以接受的。随后,可以逐渐淘汰那些在实践中发现不太有用的指标。

监控指标分类示例

以下是各类项目中常用监控指标的一些例子。

软件指标

这些指标帮助你监控预测服务或其他相关软件实现的健康状态。

  • 内存使用率
  • 计算延迟
  • 吞吐量
  • 服务器负载

许多MLOps工具已经内置了对这些软件指标的跟踪功能。

算法性能指标

除了软件指标,我们通常还需要监控学习算法的统计性能或健康状况。这主要分为两类:

1. 输入指标

这类指标用于衡量输入数据分布是否发生了变化。

  • 平均输入长度:例如,语音识别系统中音频片段的平均时长(秒)。
  • 平均输入音量:监控音频的平均响度。
  • 缺失值数量或百分比:处理结构化数据时的常用指标。
  • 平均图像亮度:例如,在制造业视觉检测中,监控图像的平均亮度,以防光照条件变化影响算法。

2. 输出指标

这类指标帮助你理解学习算法的输出是否正常。

  • 空字符串输出频率:语音识别系统返回“无”(认为用户未说话)的频率。
  • 连续快速搜索频率:在语音搜索应用中,用户连续进行两次内容基本相同的快速搜索,可能意味着第一次识别错误。
  • 用户切换至键入的频率:用户先尝试语音系统,然后转而使用键盘输入,这可能表明用户因识别效果不佳而感到沮丧。
  • 点击率:在网页搜索等应用中,使用CTR等宏观指标确保整体系统健康。

由于输入和输出指标具有高度的应用特异性,大多数MLOps工具都需要专门配置才能跟踪这些指标。


部署是一个迭代过程

机器学习建模是一个高度迭代的过程,部署同样如此。

当你完成首次部署并建立了一套监控仪表盘时,这只是迭代过程的开始。运行中的系统使你能够获取真实的用户数据和流量。通过观察学习算法在真实数据和流量上的表现,你可以进行性能分析,进而更新部署并持续监控系统。

根据我的经验,通常需要多次尝试才能收敛到一组正确的监控指标。有时,你部署系统时设定了一套初始指标,运行几周后才发现之前未考虑到的问题,这时就需要增加新的监控指标。或者,某些指标在几周内几乎不变,显得无用,就可以将其移除,以便将注意力集中在其他地方。


设置警报阈值

确定了要监控的指标集后,常见的做法是设置警报阈值。

例如:

  • 如果服务器负载超过 0.91,则触发警报,通知团队检查问题并可能启动更多服务器。
  • 如果非空输出比例超出特定阈值,则触发警报。
  • 如果缺失值比例超出设定的阈值,则触发警报。

你可以随时间调整这些指标和阈值,以确保它们能向你标记出最相关的问题情况。


发现问题后的行动

如果学习算法出现问题,需要采取相应行动:

  • 软件问题(如服务器负载过高):可能需要更改软件实现。
  • 性能问题(与学习算法准确性相关):可能需要更新模型。

因此,许多机器学习模型需要随着时间的推移进行一些维护或重新训练,就像几乎所有软件都需要一定程度的维护一样。

当模型需要更新时,你可以:

  1. 手动训练:由工程师重新训练模型,对新模型进行错误分析,确保其性能良好后再部署。
  2. 自动重训练:建立一个系统进行自动重训练。目前,对于许多应用,手动重训练远比自动重训练常见,因为开发者通常不愿意让学习算法完全自动地决定何时重训练并推送新模型到生产环境。不过,在一些应用(尤其是消费级互联网软件)中,确实存在自动重训练。

我们将在后续课程中更详细地讨论重训练以及在将新模型推送到生产环境前如何验证其性能。


总结

本节课中,我们一起学习了如何监控机器学习系统的性能,以便在需要维护或修复时能够及时收到警报并采取适当措施。我们讨论了如何监控单个机器学习模型的性能,并了解了部署和监控本身也是一个需要迭代优化的过程。

监控的核心价值在于,只有通过监控,你才能发现可能存在的问题,从而促使你进行更深入的错误分析,或获取更多数据来更新模型,以维持或提升系统的性能。

在接下来的视频中,我们将探讨一个更有用的概念:对于更复杂的系统(不是单一模型,而是更复杂的机器学习流水线),如何监控其整体性能。

009:流水线监控 📊

在本节课中,我们将要学习机器学习流水线的概念,以及如何为复杂的多步骤系统构建监控体系。我们将通过语音识别和用户画像两个具体例子,理解流水线中组件间的相互影响,并探讨监控不同阶段数据变化的方法。


什么是机器学习流水线? 🔄

许多人工智能系统并非仅运行一个单一的预测服务模型,而是涉及多个步骤组成的流水线。

上一节我们介绍了单一模型的监控,本节中我们来看看当多个模型或组件串联工作时,情况会如何变化。


语音识别流水线示例 🎤

让我们继续以语音识别为例。一个典型的移动端语音识别系统并非直接将音频输入并输出文本。

其实现是一个更复杂的流水线:

  1. 音频首先被送入一个语音活动检测模块。
  2. 只有当该模块检测到有人说话时,才会将处理后的音频片段传递给语音识别系统以生成文本。

使用VAD模块的原因是,如果语音识别服务在云端运行,我们希望通过手机只上传有人说话的那部分音频,以节省带宽。

这是一个典型的机器学习流水线,包含两个由学习算法构成的步骤。第一个步骤决定是否有人说话,第二个步骤生成文本转录。

核心影响:当两个模块协同工作时,第一个模块的任何变化都可能影响第二个模块的性能。例如,如果新手机麦克风导致VAD模块裁剪音频的方式改变(如开头或结尾静音部分变长或变短),那么语音识别系统的输入就会随之改变,可能导致其性能下降。


用户画像与推荐系统流水线示例 👤

让我们看一个涉及用户画像的例子。

系统可能使用用户的点击流数据来构建用户画像,以捕捉用户的关键特征。例如,我曾构建过试图估计用户是否拥有汽车的用户画像,因为这有助于我们决定是否向该用户推荐汽车保险。

构建用户画像的典型方式是使用一个学习算法来预测“用户是否拥有汽车”等属性。这个包含一长串预测属性的用户画像,随后会被输入到一个推荐系统(另一个学习算法)中,用于生成产品推荐。

核心影响:如果点击流数据发生变化(输入分布漂移),我们预测用户是否拥有汽车的能力可能会随时间减弱。这可能导致用户画像中“未知”标签的比例上升。

# 概念示意:用户画像属性变化可能影响推荐系统输入
user_profile['owns_car'] = 'unknown'  # 此属性从 'yes'/'no' 变为 'unknown'
recommendation_input = user_profile  # 推荐系统的输入因此改变

由于用户画像的输出改变,推荐系统的输入也随之改变,这可能会影响产品推荐的质量。在机器学习流水线中,这种级联效应可能非常复杂,难以追踪。


如何监控流水线? 🛠️

构建这些可能包含机器学习或非机器学习组件的复杂流水线时,我发现构思用于监控的指标非常有用。这些指标应能检测包括概念漂移或数据漂移在内的变化,并覆盖流水线的多个阶段。

以下是需要监控的指标类型:

  • 软件指标:针对流水线中的每个组件或整个流水线。
  • 输入/输出指标:针对流水线中的每个组件。

通过构思与流水线各个组件相关的指标,可以帮助你发现问题。例如:

  • 语音活动检测系统输出的音频片段随时间变长或变短。
  • 用户画像系统突然对“用户是否拥有汽车”这一属性产生更多“未知”结果。

这能提醒你数据发生的变化,这些变化可能需要你采取行动来维护模型。你在上一节视频中学到的原则——构思所有可能出错的地方(包括流水线中单个组件可能出的问题),并设计指标来追踪它们——仍然适用,只是现在你需要关注流水线中的多个组件。


数据变化的速度有多快? ⏱️

数据变化的速度高度依赖于具体问题。

  • 变化缓慢的例子:人脸识别系统。人们的相貌通常变化不快(发型、服饰会随潮流变化,相机分辨率会提升),但总体上变化不大。
  • 变化迅速的例外:如果手机工厂采用了一批新材料,所有手机的外观可能突然改变。

一般而言

  • 用户数据:如果你面向海量消费者,用户行为通常变化相对缓慢。因为很少有力量能让数百万用户同时突然改变行为(当然也有例外,如新冠疫情或新电影上映引发的搜索趋势)。
  • 企业数据:则可能变化得非常快。例如,一家公司决定改变其业务流程,或者工厂采用新的生产工艺,都可能导致整个数据集迅速发生转变。

这两点只是概括,两种情况下都有例外。但这可以为你提供一个思考框架,来评估你的数据可能变化的速度。


总结 📝

本节课中我们一起学习了:

  1. 机器学习流水线由多个步骤组成,组件间存在相互依赖。
  2. 通过语音识别用户画像两个例子,我们看到了流水线中一个组件的变化如何影响下游组件的性能。
  3. 监控此类系统需要构思覆盖软件指标组件输入/输出指标在内的多方面指标,以检测数据漂移和概念漂移。
  4. 数据变化的速度因应用场景而异,用户数据通常变化较慢,而企业数据可能因业务决策而快速转变。

恭喜你完成第一周视频的学习!建议你查看练习题以巩固这些概念,也可以尝试本周的可选编程练习,在你自己电脑上部署一个机器学习模型。我期待在下一周的课程中与你再见,我们将更深入地探讨机器学习项目全周期中的建模部分。

010:建模概述 🧠

在本节课中,我们将学习如何构建一个值得投入生产部署的机器学习模型。我们将探讨模型构建的最佳实践,并理解在实际项目中可能遇到的关键挑战。通过掌握这些知识,你将能够更高效地改进模型,使其满足实际应用的需求。


模型构建的关键挑战 ⚠️

上一节我们介绍了课程的整体目标,本节中我们来看看在构建机器学习模型时,许多团队会面临哪些关键挑战。理解这些挑战有助于你提前识别并更高效地调整项目。

我的一个朋友Adam Cos开玩笑说,他听我给机器学习团队提建议时,感觉我的建议在不同项目间相当一致,以至于他几乎可以用一连串的“如果-那么-否则”语句来替代我。我也发现,当几位资深机器学习工程师审视同一个项目时,他们给出的建议也惊人地一致。本周你将学习的是,构建一个可用于生产的机器学习模型会遇到哪些关键挑战。

例如,如何处理数据量少的数据集?或者,如果在测试集上表现良好,但出于某些原因,这仍然无法满足实际应用的需求,该怎么办?我希望通过本周的学习,你将能够非常高效地知道如何改进你的机器学习模型,以解决最重要的问题,从而使其为部署做好准备。


本周重点:建模与改进策略 🎯

现在,让我们深入本周的内容。我们的重点将放在完整机器学习项目周期的建模部分。你将学习一些关于如何选择和训练模型、如何进行错误分析以及如何利用分析结果来驱动模型改进的建议。

你会多次听到我提到一个主题:以模型为中心的AI开发以数据为中心的AI开发。AI的发展历程中,人们非常强调如何选择正确的模型,例如如何选择正确的神经网络架构。

我发现,对于实际项目,采取更以数据为中心的方法可能更有用。在这种方法中,你不仅关注改进神经网络架构,还确保为算法提供高质量的数据。这最终能让你更高效地使系统表现良好。

然而,我参与以数据为中心的AI开发的方式,并不是简单地尝试收集越来越多的数据(这可能非常耗时),而是使用工具来帮助我以最高效的方式改进数据。在本周的学习中,你将了解一些实现这一目标的方法。


总结 📝

本节课中我们一起学习了构建生产级机器学习模型的概述。我们明确了本周的学习重点是建模环节,并介绍了以模型为中心和以数据为中心的两种开发理念。理解常见的建模挑战,并掌握通过数据质量提升来驱动模型改进的策略,是构建成功生产系统的关键。接下来,我们将进入具体的实践环节。

011:机器学习模型部署的关键挑战 🔑

在本节课中,我们将探讨在部署一个表现良好的机器学习模型时面临的关键挑战。我们将了解机器学习系统由代码和数据共同构成,并深入分析模型开发过程中的主要难点与关键里程碑。


概述:机器学习系统的构成

上一节我们介绍了机器学习模型部署的宏观背景,本节中我们来看看构建机器学习系统时的一个核心框架。

一个我希望你在开发机器学习系统时牢记的框架是:人工智能系统和机器学习系统同时包含代码(即算法或模型)和数据

过去几十年,人们非常强调如何改进代码。事实上,许多人工智能研究都是研究人员下载数据集,并试图找到在该数据上表现良好的算法模型。

但对于许多应用,如果你对数据不满意,你拥有改变数据的灵活性。因此,在许多项目中,算法或模型基本上是一个已解决的问题。从GitHub下载的某个模型可能就足够好,而将大量时间花在改进数据上会更有效率,因为数据通常需要针对你的问题进行更多定制。这个观点将贯穿本周和下周的材料。


模型开发的迭代过程

了解了系统的基本构成后,我们来深入探讨构建机器学习系统的具体过程。

构建机器学习系统时,你可能有一个算法或一个模型。这可以是 model = SomeAlgorithm()。还有一些数据。通过在你的数据上训练算法,你便得到了可以进行预测的机器学习模型。

当然,超参数是这个过程的额外输入。对于许多应用来说,确保你有一个调整良好的学习率和正则化参数以及其他一些参数是很重要的。超参数很重要,但由于超参数的空间通常相对有限,我们将花更多时间关注代码和数据。

因此,模型开发是一个高度迭代的过程。通常从一个模型、超参数和数据开始,训练一个模型。然后对模型进行错误分析,并利用分析结果帮助你决定如何改进模型、超参数或数据。因为机器学习是一个如此依赖经验的过程,能够非常快速地多次进行这个循环是提高性能的关键。

但同样有助于你提高性能的是,在每次循环中,能够就如何修改数据、模型或超参数做出明智的选择。在你进行了足够多次尝试并获得一个良好模型后,通常有用的最后一步是进行更丰富的错误分析,并在将其推送到生产部署之前,让你的系统通过最终审核,以确保其正常工作。


模型开发的三大关键里程碑

在深入探讨挑战之前,我们先明确模型开发过程中需要达成的目标。那么,为什么构建模型时模型开发很困难呢?我认为大多数项目都应努力实现三个关键里程碑。

以下是构建模型时需要达成的三个关键里程碑:

  1. 在训练集上表现良好:你可能首先需要确保至少在训练集上表现良好。例如,你根据房屋大小预测房价。你至少需要能够拟合一条与你的训练集相当吻合的线。
  2. 在开发集/测试集上表现良好:在训练集上表现良好后,你必须问你的算法在开发集或保留交叉验证集以及测试集上是否表现良好。如果你的算法甚至在训练集上表现都不好,那么它在开发集或测试集上表现良好的可能性非常小。因此,我认为第一步是你必须首先完成的一个里程碑,作为实现第二步的途径。
  3. 满足业务指标或项目目标:在开发集或测试集上表现良好后,你还必须确保你的学习算法根据业务指标或项目目标表现良好。过去几十年,许多机器学习开发都是由在开发集或测试集上表现良好的目标驱动的。

不幸的是,对于许多问题,拥有高的测试集精度并不足以实现项目的目标。这导致了许多挫折,以及在非常擅长此事的机器学习团队和更关心业务指标或项目其他目标的业务团队之间的分歧。


为何低平均测试误差可能不够

你可能会想,嘿,Andrew,实现低的平均测试误差怎么可能对一个项目来说还不够呢?我在许多项目中看到过一些常见的模式,在这些情况下,你需要的东西超越了低的平均测试集误差。能够发现这些问题将帮助你更有效地解决它们。

我们将在下一个视频中更深入地探讨这个话题。


总结

本节课中,我们一起学习了机器学习模型部署的关键挑战。我们明确了机器学习系统由代码和数据共同构成,理解了模型开发是一个高度迭代的过程,并掌握了评估模型成功的三个关键里程碑:在训练集上表现良好、在开发/测试集上表现良好,以及最终满足业务指标。我们还认识到,仅仅追求低的平均测试误差可能不足以实现项目的最终目标,这为后续深入探讨具体挑战奠定了基础。

012:为什么低平均错误率还不够好 🎯

在本节课中,我们将要学习一个在机器学习项目部署中至关重要的概念:仅仅在测试集上取得低的平均错误率,有时并不足以让一个系统成功投入生产。我们将探讨几种常见但容易被平均指标掩盖的问题场景。

上一节我们介绍了概念漂移和数据漂移,本节中我们来看看除了平均测试集性能之外,还需要关注哪些方面才能确保项目的成功。

平均测试误差的局限性

一个机器学习系统可能在测试集上拥有较低的平均错误率,但如果它在一些不成比例地重要的样本上表现不佳,该系统仍然无法被接受并部署到生产环境中。

让我用一个网络搜索的例子来说明。

网络搜索查询主要分为两类:

  • 信息型或事务型查询:例如“苹果派食谱”、“激光电影”、“无线数据套餐”。用户希望了解信息或完成交易。对于这类查询,搜索引擎需要返回最相关的结果,但用户可能可以容忍最佳结果被排在第二或第三位。
  • 导航型查询:例如“Stanford”、“Reddit”、“YouTube”。用户有非常明确的意图,希望直接访问特定网站。对于这类查询,如果搜索引擎没有将目标网站(如 stanford.edu)排在第一位,用户会非常不满。一个无法正确处理导航型查询的搜索引擎会迅速失去用户的信任。

在这个上下文中,导航型查询就是一组不成比例地重要的样本。如果你的学习算法提升了网络搜索的平均测试准确率,但却搞砸了少数几个导航型查询,这可能就无法被部署。

挑战在于,平均测试集准确率倾向于平等地对待所有样本,而在网络搜索中,某些查询的重要性远高于其他。

一种可能的解决方案是尝试给这些重要样本更高的权重。这适用于某些应用,但根据我的经验,仅仅改变不同样本的权重并不总能解决全部问题。

关键数据切片的性能

与上述问题密切相关的是关键数据切片的性能问题。

假设你构建了一个用于贷款审批的机器学习算法,以决定谁可能偿还贷款。对于这样的系统,你必须确保它不会根据种族、性别、地点、语言或其他受保护属性,不公平地歧视贷款申请人。许多国家的法律或法规也要求金融系统和贷款审批流程不得基于这些受保护属性进行歧视。

因此,即使一个贷款审批的学习算法取得了很高的平均测试准确率,如果它表现出不可接受的偏见或歧视水平,那么它对于生产部署来说也是不可接受的。

虽然AI社区对个体公平性进行了大量讨论(这是正确且重要的),但“公平性”或关键切片性能的问题也出现在其他场景中。

假设你运营一个在线购物网站,聚合并销售来自许多不同制造商和零售商品牌的产品。你可能希望确保你的系统公平地对待所有主要的用户、零售商和产品类别。

例如,即使一个机器学习系统拥有很高的平均测试准确率(也许它平均能推荐更好的产品),但如果它对某一特定种族的所有用户都给出完全不相关的推荐,这可能是不可接受的。

或者,如果它总是推送大零售商的产品而忽略小品牌,这不仅可能损害业务(导致失去所有小零售商),构建一个只推荐大品牌产品、忽视小企业的推荐系统也会显得不公平。

再比如,一个产品推荐器给出了高度相关的推荐,但出于某种原因从不推荐电子产品,那么销售电子产品的零售商很可能会非常不满。这对于平台上的零售商或你业务的长期健康都是不利的,即使平均测试准确率显示,由于不推荐电子产品,你出于某种原因向用户展示了稍微更相关的结果。

本周晚些时候,你将学习如何对数据的关键切片进行分析,以确保发现并解决这类潜在问题。

稀有类别与倾斜的数据分布

接下来是稀有类别的问题,特别是倾斜的数据分布

在医疗诊断中,许多患者没有某种疾病的情况并不少见。因此,如果你有一个99%是阴性样本(因为99%的人口没有某种疾病)、1%是阳性样本的数据集,那么你可以通过写一个程序来获得非常好的测试准确率:

print(0)  # 总是预测为阴性

你不需要学习算法,只需这一行代码,就能在你的数据集上获得99%的准确率。但显然,print(0) 对于疾病诊断来说并不是一个有用的算法。

顺便说一下,这确实在我身上发生过一次。我的团队训练了一个巨大的神经网络,发现它达到了99%的平均准确率,结果发现它是通过一直预测“0”来实现的。我们基本上训练了一个和 print(0) 做同样事情的巨型神经网络。当然,当我们发现这个问题后,就回去修复了它。希望这不会发生在你身上。

与倾斜数据分布(通常讨论阳性和阴性)密切相关的问题是稀有类别的准确率

我曾与朋友 Praav Rajpurkar 等人合作进行胸部X光诊断,我们使用深度学习来识别不同的病症。对于一些相对常见的病症(如医学上的“胸腔积液”),我们拥有约10,000张图像,因此能够实现较高的性能水平。而对于罕见得多的病症“疝气”,我们只有大约100张图像,因此性能要差得多。

从医学角度来看,如果一个诊断系统忽略了明显的疝气病例(即患者X光片清晰显示患有疝气),而学习算法漏诊了,那将是有问题的。但由于这是一个相对稀有的类别,算法的整体平均测试集准确率并不算太差。事实上,算法本可以完全忽略所有疝气病例,这对它的平均测试集准确率影响有限,因为疝气病例很罕见,算法几乎可以忽略它而不太影响平均测试准确率。

如果平均测试准确率平等地对待测试集中的每一个样本,就会出现这种情况。

超越平均测试准确率

我曾在太多公司听到过几乎完全相同的对话。对话是这样的:

  • 机器学习工程师说:“我在测试集上表现很好。这个能用。我们用它吧。”
  • 产品负责人或业务负责人说:“但这在我的应用中行不通。”
  • 机器学习工程师回答:“但我在测试集上表现很好。”

我的建议是,如果你发现自己身处这样的对话中,不要采取防御姿态

我们作为一个社区,已经构建了许多在测试集上表现出色的工具,这值得庆祝。我认为这很棒,但我们常常需要超越这一点,因为对于许多生产应用来说,仅仅在测试集上表现出色是不够的。

当我构建一个机器学习系统时,我认为我的工作不仅仅是在测试集上表现出色,而是要构建一个能解决实际业务或应用需求的机器学习系统。我希望你也能采取类似的观点。

本周晚些时候,我们将介绍一些技术(通常涉及误差分析,可能是在数据切片上的误差分析),这些技术将帮助你发现这些需要超越平均测试准确率的问题,并为你提供工具来应对这些更广泛的挑战。


本节课中我们一起学习了:在机器学习生产实践中,仅追求低的平均测试错误率是远远不够的。我们必须关注系统在不成比例地重要的样本(如导航型查询)、关键数据切片(如受保护属性群体、重要业务类别)以及稀有类别上的性能。平均指标可能会掩盖这些关键问题。成功的机器学习工程师的职责是构建真正满足业务需求的系统,而不仅仅是优化测试集分数。

013:建立基准 📊

在本节课中,我们将要学习启动机器学习项目时一个至关重要的初始步骤:建立性能基准。我们将探讨为什么基准如此重要,以及如何针对不同类型的数据(非结构化与结构化数据)有效地建立基准。


为何需要建立基准?🎯

开始一个机器学习项目时,最有用的第一步通常是建立一个性能基准。通常,只有在建立了基准性能水平之后,你才能拥有有效改进该基准的工具。

让我们深入探讨快速建立基准的一些最佳实践。


一个语音识别的例子 🎤

假设你已确定数据中存在四种主要的语音类别:

  • 清晰语音:说话时背景噪音很小。
  • 含汽车噪音的语音:如同在车内使用语音识别系统。
  • 含人声背景噪音的语音:如同在户外,背景中有其他人说话。
  • 低带宽连接下的语音:如同在使用信号很差的手机通话。

如果你的模型在这四类语音上的准确率分别是 94%、89%、87%、70%,你可能会想:“它在低带宽音频上表现更差,所以我们应该集中精力改进这个。”

但在仓促下结论之前,为所有这四类语音建立一个性能基准水平会很有用。你可以通过请人工转录员标注数据并测量他们的准确率来实现。

以下是这四类语音的人类水平性能

  • 清晰语音:95% 准确率
  • 含汽车噪音的语音:93% 准确率
  • 含人声背景噪音的语音:89% 准确率
  • 低带宽连接下的语音:70% 准确率

通过对比,我们发现:

  • 在清晰语音上,将性能提升至人类水平有 1% 的改进空间。
  • 在含汽车噪音的语音上,有 4% 的改进空间。
  • 在含人声背景噪音的语音上,有 2% 的改进空间。
  • 在低带宽语音上,改进空间为 0%

因此,在没有人类水平性能作为参考时,我们可能认为改进低带宽音频最有希望。但通过此分析,我们意识到低带宽音频本身质量就很差,甚至连人类都无法听清,在这方面努力可能收效甚微。相反,将注意力集中在改进含汽车噪音的语音识别上可能更有成效。

在这个例子中,使用人类水平性能(有时缩写为 HLP)为你提供了一个比较点或基准,帮助你决定将努力集中在含汽车噪音的数据上,而非低带宽数据上。


非结构化数据 vs. 结构化数据 🗂️

事实证明,建立基准的最佳实践根据你处理的是非结构化数据还是结构化数据而有很大不同。

非结构化数据指的是如图像(猫的图片)、音频(如语音识别例子)或自然语言(如餐厅评论文本)这类数据集。非结构化数据往往是人类非常擅长解读的数据类型。因为人类非常擅长处理非结构化数据任务,所以测量人类水平性能通常是建立基准的好方法。

结构化数据则是指你可能拥有的大型数据库或巨型电子表格。例如,如果你运营一个电商网站,记录用户何时以何价格购买了何物的数据就存储在一个大型数据库中。这类存储在电子表格或更健壮的数据库中的数据就是结构化数据的例子。由于人类并不擅长通过查看此类数据来做出预测,人类水平性能通常对结构化数据应用来说是一个不太有用的基准。

我发现,机器学习开发的最佳实践根据你处理的是非结构化数据问题还是结构化数据问题而有很大不同。牢记这一区别,让我们看看为这两种类型的问题建立基准的一些方法。


如何建立基准?🔧

上一节我们介绍了人类水平性能作为基准,特别是针对非结构化数据问题。以下是建立基准的其他几种方法:

另一种建立基准的方法是进行文献搜索,寻找最先进的技术,或查看开源结果,了解他人在同类问题上报告能达到什么水平。例如,如果你正在构建一个语音识别系统,而其他人报告了在与你数据相似的数据上达到的某种准确率,那么这可能为你提供了一个起点。

使用开源代码时,你也可以考虑构建一个快速而粗糙的实现。这不仅仅是一个占位系统,而是一个能让你初步了解可能达到何种性能的快速实现。

最后,如果你已经有一个机器学习系统在运行,那么旧系统的性能也可以帮助你建立一个基准,作为你努力改进的目标。


基准系统的作用 💡

一个基准系统或基准性能水平有助于指示什么是可能达到的

在某些情况下,例如使用人类水平性能(尤其是针对非结构化数据问题)时,这个基准还可以让你了解什么是不可减少的误差基础误差。换句话说,对于这个问题,任何人可能达到的最佳性能是什么。这就像帮助我们认识到,也许低带宽音频质量太差,不可能获得超过70%的准确率(如我们之前的例子所示)。

通过帮助我们大致了解什么是可能达到的,基准可以让我们在确定工作优先级时更加高效。


一个重要的提醒 ⚠️

有时,我见过一些业务团队在机器学习团队甚至还没有机会建立一个粗略的基准之前,就要求他们保证学习算法能达到80%、90%或99%的准确率。这不幸地将机器学习团队置于一个非常困难的境地。

如果你处于这种境地,我建议你考虑进行沟通,要求在给出关于机器学习系统最终能达到多准确的更坚定预测之前,争取时间建立一个粗略的基准性能水平。你可以告诉他们,这样做是为了更好地为长期成功奠定基础。


总结 📝

本节课中,我们一起学习了建立基准在机器学习项目中的核心重要性。我们了解到:

  1. 基准是衡量进步和确定工作重点的起点。
  2. 人类水平性能是评估非结构化数据任务的一个强大基准。
  3. 对于结构化数据,需要依赖其他基准,如文献中的最佳结果快速原型旧系统性能
  4. 基准帮助我们设定现实的期望,识别改进潜力最大的领域,并避免在不切实际的目标上浪费精力。

现在我们已经讨论了基准的重要性,在接下来的视频中,我将分享一些关于如何快速启动机器学习项目的额外技巧。

014:机器学习项目启动指南 🚀

在本节课中,我们将学习如何高效地启动一个机器学习项目。课程内容涵盖从初始模型选择到快速验证的多个实用技巧,旨在帮助你快速建立项目基线并进入迭代循环。


1. 初始模型选择:文献调研与开源实现

上一节我们介绍了机器学习是一个迭代过程。本节中我们来看看如何迈出第一步:选择一个初始模型。

我启动机器学习项目时,几乎总是从快速的文献调研开始,以了解当前的技术可能性。你可以查阅在线课程、博客和开源项目。

我的建议是:如果你的目标是构建一个实用的生产系统,而非进行学术研究,那么不必执着于寻找最新、最前沿的算法。相反,花半天或几天时间阅读博客文章,选择一个合理的方案,以便快速启动。如果能找到开源实现,将帮助你更高效地建立基线。

对于许多实际应用,一个合理的算法加上优质的数据,其表现往往优于一个顶尖算法加上普通的数据。因此,不要纠结于上周某个会议上刚发表的最前沿算法。选择一个合理的方案,找到一个好的开源实现,并快速启动。因为能够快速完成迭代循环的第一步,可以使你更高效地进行多次迭代,从而更快地达到理想的性能。


2. 部署约束的考量时机

一个常见的问题是:在选择模型时,是否需要考虑部署约束(如计算资源限制)?

我的回答是:是的,你应该考虑部署约束,但前提是基线已经建立,并且你相对确信这个项目可行,且目标就是构建和部署系统。

然而,如果你尚未建立基线,或者还不确定这个项目是否值得长期投入和部署,那么答案可能是否定的,或者不一定。在项目的这个阶段,首要目标是建立基线并确定项目的可行性。此时,忽略部署约束,直接找一个开源实现来尝试,看看能达到什么效果,即使这个实现计算量巨大以至于你明知无法部署,也是可以的。

当然,在这个阶段考虑部署约束也无妨,但更高效的做法可能是先专注于建立基线。


3. 运行前的快速健全性检查

在首次尝试学习算法,尤其是在所有数据上运行之前,我强烈建议你对代码和算法进行一些快速的健全性检查。

以下是几种有效的检查方法:

  • 在小数据集上过拟合:在花费数小时甚至数天时间在大数据集上训练算法之前,我通常会尝试在一个非常小的训练集上过拟合模型。
  • 拟合单个样本:特别是当输出很复杂时,确保算法至少能拟合一个训练样本。例如,我曾开发一个语音识别系统,输入是音频,输出是文本。当我在仅包含一个音频片段的训练集上训练时,系统输出了一连串空格。这表明系统甚至无法准确转录一个样本,那么花大量时间在巨型训练集上训练就没有意义。
  • 图像分割示例:如果你的目标是输入图片并分割出其中的猫,那么在花费数小时训练数百或数千张图像之前,一个值得做的健全性检查是:输入一张图片,看看系统是否能至少过拟合这一个训练样本。
  • 小规模图像分类:对于图像分类问题,即使你的训练集有1万、10万甚至100万张图片,也值得先用一个很小的子集(例如10或100张图片)快速训练你的算法。因为你可以快速完成这个步骤。如果你的算法在100张图片上都表现不佳,那么它在1万张图片上显然也不会好。

这些检查的优势在于,你可以在几分钟甚至几秒钟内,在一个或少数几个样本上训练你的算法,从而更快地发现代码中的错误。


4. 后续步骤:误差分析与性能审计

现在,在你训练了第一个机器学习模型之后,最重要的事情之一就是如何进行误差分析,以帮助你决定如何改进算法的性能。

让我们进入下一个视频,深入探讨误差分析和性能审计。


总结

本节课中,我们一起学习了启动机器学习项目的关键步骤:

  1. 通过快速文献调研和利用开源实现来选择合理的初始模型,以快速建立基线。
  2. 根据项目阶段(建立基线 vs. 准备部署)来决定是否优先考虑部署约束
  3. 在投入大量计算资源前,通过在小数据集上过拟合、拟合单个样本等方法进行快速健全性检查,以高效发现并修复问题。

掌握这些启动技巧,能帮助你更顺畅地进入“构建模型 -> 误差分析 -> 改进”的迭代循环,从而更高效地推进项目。

015:错误分析示例 🧐

在本节课中,我们将学习错误分析的核心流程。错误分析是机器学习开发过程中的关键环节,它能高效地指引我们如何改进算法性能。我们将通过一个语音识别的具体例子,来展示如何进行系统性的错误分析。


首次训练一个学习算法时,几乎可以保证它不会一次就成功运行。因此,我认为机器学习开发过程的核心是错误分析。如果执行得当,错误分析可以告诉你,为了提升学习算法的性能,最有效的时间利用方式是什么。

让我们从一个例子开始。我将通过一个语音识别的错误分析示例来逐步讲解。当我进行错误分析时,这基本上就是我自己在电子表格中会做的事情,目的是弄清楚语音系统的错误所在。

你可能会从开发集中听一百个被错误标记的样本。假设第一个样本的真实标签是“stir fried letters recipe”,但你的学习算法预测为“stir fed letters recipe”。如果你对数据集中主要的数据类型有一些假设,例如你认为有些数据包含汽车噪音,有些包含人声噪音,那么你可以建立一个电子表格。我确实会在电子表格中创建如下几列。

当你听这个样本时,如果背景中有汽车噪音,你可以在电子表格中打勾或做其他标记,以表明这个样本有汽车噪音。

然后你听第二个样本,可能“sweetened coffee”被错误转录为“Swedish coffee”,也许这个样本的背景中有人声噪音。

再一个样本,“sailaway song”被误转录为“Seaway song”,这个样本同样有人声噪音。另一个样本,“less‘s catch up”被转录为“lesss catchch up”,这个样本可能同时有汽车噪音和人声噪音。

请注意,顶部的这些标签不必是互斥的。在错误分析过程中,当你听音频片段时,可能会产生新的标签想法。假设这第四个样本的连接带宽非常低。反思你发现的错误,你可能会想起相当多的音频片段都存在低带宽连接的问题。此时,你可能会决定在电子表格中添加一个新列,标记为“低带宽”,并打上勾,甚至可能回头检查其他样本是否也有低带宽连接。

尽管我在幻灯片中演示了这个例子,但当我亲自进行错误分析时,有时会直接打开像Google Sheets、Excel或Mac上的Numbers这样的电子表格程序,像这样在表格中操作。这个过程帮助你理解哪些标签所代表的数据类型可能是更多错误的来源,从而值得投入更多精力和关注。

到目前为止,错误分析通常是通过手动过程完成的,例如在Jupyter笔记本中或在电子表格中跟踪错误。我有时仍然这样做,如果你也这样做,那没问题。但也有新兴的MLOps工具让开发者更容易进行这个过程。例如,当我的团队Landing AI处理计算机视觉应用时,整个团队现在都使用Landing Lens,这比使用电子表格要容易得多。

你听我说过,训练模型是一个迭代过程,部署模型也是一个迭代过程。那么,错误分析同样是一个迭代过程,这或许并不令人意外。一个典型的过程是:你可能会用一组初始标签(如汽车噪音、人声噪音)来检查和标记一些样本。基于检查这组初始样本的结果,你可能会回来提出一些新标签。有了新标签,你可以回头检查和标记更多的样本。

让我再举几个这类标签可能是什么的例子。以视觉检测为例,比如检测智能手机的缺陷。一些标签可以是特定的类别标签,例如“这个设备有划痕吗?”或“有凹痕吗?”等等。所以,如果其中一些标签与特定的类别标签Y相关联,这是可以的。另一些标签可能是图像属性,例如“这张手机照片模糊吗?”、“背景是暗的还是亮的?”、“图片中有不需要的反光吗?”。标签也可能来自其他形式的元数据,例如“手机型号是什么?”、“是哪个工厂?”、“是哪个生产线捕获的这张特定图像?”。

这种提出标签、标记更多数据、再提出新标签的过程,其目标是尝试找出几个可以有效地改进算法的数据类别。就像我们最早的语音例子中,决定处理背景有汽车噪音的语音。

让我再举一个例子。对于一个在线电商网站的产品推荐,你可能会查看系统向用户推荐了哪些产品,并找出明显错误或不相关的推荐。然后尝试找出是否存在特定的用户群体,例如“我们是否真的不擅长向年轻女性或年长男性推荐产品?”,或者是否存在特定的产品特征或类别,其推荐效果特别差。通过创造性地头脑风暴和应用这些标签,你希望能为值得努力改进算法性能的数据类别想出一些点子。

当你浏览这些不同的标签时,以下是一些值得关注的有用数字:

以下是计算这些关键指标的方法:

  1. 带有该标签的错误所占比例。例如,如果你听了100个音频片段,发现其中12%被标记为“汽车噪音”标签,那么这让你了解到处理汽车噪音问题的重要性。它也告诉你,即使你解决了所有汽车噪音问题,性能可能也只提升12%,这实际上并不算多。
  2. 带有该标签的所有数据中,被错误分类的比例。到目前为止,我们只讨论了标记错误分类的样本。为了提高时间效率,你可能将注意力集中在标记错误分类的样本上。但如果有一个标签可以同时应用于正确标记和错误标记的样本,那么你可以问:带有该标签的所有数据中,有多少比例被错误分类了?例如,如果你发现所有带有汽车噪音的数据中,有18%被错误转录,那么这告诉你,带有此类标签的数据的性能只有某个准确度水平,并让你了解这些带有汽车噪音的样本到底有多难处理。
  3. 所有数据中带有该标签的比例。这告诉你,相对于整个数据集,带有该标签的样本有多重要。例如,你的整个数据集中有多少比例有汽车噪音?
  4. 在该标签数据上,还有多少改进空间。你已经见过的一个分析例子是,测量人类在该标签数据上的表现水平。

因此,通过头脑风暴不同的标签,你可以将数据分割成不同的类别,然后利用上述问题来尝试决定优先处理哪些方面。

在下一个视频中,让我们更深入地探讨一个进行此类分析的例子。

016:确定优先处理的内容 🔍

在本节课中,我们将学习如何利用数据标注和属性分析,来系统性地确定机器学习项目改进的优先方向。我们将通过一个语音识别系统的具体案例,展示如何计算不同类别数据改进的潜在影响,从而做出更高效的决策。

上一节我们介绍了如何为数据打上不同的属性标签。本节中我们来看看如何利用这些标签信息,确定应该优先处理哪些问题。

案例分析:语音识别系统的性能评估

我们沿用之前的例子,假设数据被标记为四种属性:干净语音汽车噪音人声噪音低带宽音频。我们已知算法在各属性上的准确率、人类水平表现(HLP)以及两者之间的差距。

以下是关键数据:

  • 算法在“干净语音”上的准确率为 94%,人类水平为 95%,差距为 1%
  • 算法在“汽车噪音”语音上的准确率为 75%,人类水平为 95%,差距为 20%
  • 算法在“人声噪音”语音上的准确率为 85%,人类水平为 95%,差距为 10%
  • 算法在“低带宽音频”上的准确率已达到 95%,与人类水平持平,差距为 0%

如果仅看与人类水平的差距,“汽车噪音”类别似乎是改进空间最大的。然而,另一个关键因素是各类别数据在总体数据中的占比

假设数据分布如下:

  • 60% 的数据是干净语音。
  • 4% 的数据带有汽车噪音。
  • 30% 的数据带有人声噪音。
  • 6% 的数据是低带宽音频。

计算改进的潜在影响

现在,我们可以计算将每个类别的性能提升至人类水平,对系统整体准确率的提升效果。计算公式为:

整体提升 = (人类水平准确率 - 当前算法准确率) × 该类别数据占比

以下是具体计算:

  • 干净语音(95% - 94%) × 60% = 0.6% 的整体提升。
  • 汽车噪音(95% - 75%) × 4% = 0.8% 的整体提升。
  • 人声噪音(95% - 85%) × 30% = 3.0% 的整体提升。
  • 低带宽音频(95% - 95%) × 6% = 0.0% 的整体提升。

通过这个更全面的分析,我们发现,尽管“汽车噪音”类别的性能差距最大,但由于其数据量很少,彻底改进它对整体的提升(0.8%)有限。相反,“人声噪音”类别由于数据占比高(30%),将其性能提升至人类水平能为整体带来 3.0% 的显著提升。因此,优先处理“人声噪音”或数据量最大的“干净语音”类别,可能比处理“汽车噪音”更具价值。

确定优先级的考量因素

以下是决定工作重点时,可以综合考虑的几个关键因素:

  1. 改进空间:当前性能与期望目标(如人类水平表现)之间的差距有多大。
  2. 出现频率:该类别数据在总体数据中的占比是多少。
  3. 改进难度:你是否有明确、可行的思路来提升该类别的性能。例如,如果你对如何改进“汽车噪音”下的语音识别已有数据增强的具体想法,可能会提高它的优先级。
  4. 业务重要性:提升该类别性能对产品核心功能或用户体验有多重要。例如,在驾驶场景下,提升“汽车噪音”环境的语音识别准确率可能具有更高的战略价值,因为它关系到行车安全和使用便利性。

没有一个数学公式能直接告诉你应该做什么,但综合权衡这些因素,可以帮助你做出更有成效的决策。

采取针对性行动

一旦确定了需要优先改进的一个或少数几个类别,一个有效的方法是针对性地增加或提升该类别的数据质量

例如,如果你决定提升“汽车噪音”下的语音识别性能,你可以:

  • 专门去收集更多带有汽车噪音的语音数据。
  • 使用数据增强技术,基于现有数据生成更多带汽车噪音的样本。

这种方法比泛泛地收集更多数据更加高效。在机器学习项目中,盲目收集所有类型的数据通常耗时且昂贵。通过上述分析,你可以精确地指导数据收集或增强工作,避免在低价值(如已接近人类水平的“低带宽音频”)或低占比的类别上浪费资源。

总结与预告

本节课中我们一起学习了如何通过量化分析不同数据类别对系统整体性能的潜在影响,来优先处理机器学习项目中的改进方向。核心在于结合 性能差距数据分布,做出聚焦且高效的决策。

我发现这种错误分析流程在我参与的许多项目中都非常有用,希望它也能帮助你构建更成熟的生产级机器学习系统。

接下来,我们将面对机器学习中一个最常见的挑战:偏斜数据集。让我们进入下一个视频,学习处理偏斜数据集的一些技术。

017:偏态数据集 📊

在本节课中,我们将要学习如何处理偏态数据集。当数据集中正负样本的比例严重偏离50:50时,我们称之为偏态数据集。我们将探讨为什么传统的准确率指标在此类数据集上会失效,并学习更有效的评估工具:混淆矩阵精确率召回率以及F1分数

什么是偏态数据集?🤔

上一节我们介绍了偏态数据集的基本概念。本节中我们来看看几个具体的例子,以理解为什么准确率指标会具有误导性。

  • 制造业缺陷检测:假设一家公司生产智能手机,其中绝大多数(例如99.7%)是完好的(标签 y=0),只有一小部分(0.3%)是有缺陷的(标签 y=1)。如果一个学习算法总是预测“无缺陷”(y=0),它的准确率将达到99.7%,但这显然不是一个有用的算法。
  • 医疗诊断:如果99%的患者没有某种疾病,那么一个总是预测“无病”的算法也能达到99%的准确率。
  • 唤醒词检测:在构建类似“Alexa”或“Hey Siri”的唤醒词检测系统时,绝大多数时间用户并没有说出唤醒词。因此,数据集会高度偏斜(例如,96.7%的负样本,3.3%的正样本)。

在这些情况下,原始准确率并不是一个有用的评估指标,因为一个总是预测多数类的简单算法就能获得很高的准确率。

混淆矩阵:评估的基础 📈

既然准确率不可靠,我们需要一个更细致的工具来评估模型性能。这就是混淆矩阵

混淆矩阵是一个表格,其中一个轴代表真实标签(y=0 或 y=1),另一个轴代表预测标签(y=0 或 y=1)。矩阵的四个单元格分别统计了以下四种情况的数量:

以下是混淆矩阵的四个核心组成部分:

  • 真阴性:真实为负(y=0),预测也为负(y=0)。
  • 真阳性:真实为正(y=1),预测也为正(y=1)。
  • 假阴性:真实为正(y=1),但预测为负(y=0)。这是“漏报”。
  • 假阳性:真实为负(y=0),但预测为正(y=1)。这是“误报”。

假设我们在开发集上有1000个样本,其混淆矩阵如下:

真实 \ 预测 预测为 0 预测为 1
真实为 0 905 (TN) 9 (FP)
真实为 1 18 (FN) 68 (TP)

在这个例子中,总共有914个负样本和86个正样本,是一个偏态数据集(8.6%为正)。

精确率与召回率:更优的指标 🎯

基于混淆矩阵,我们可以定义两个在偏态数据集中至关重要的指标:精确率召回率

精确率 衡量的是所有被模型预测为正的样本中,有多少是真正的正样本。它关注的是预测结果的准确性

公式精确率 = TP / (TP + FP)

在上面的例子中,精确率 = 68 / (68 + 9) ≈ 88.3%。

召回率 衡量的是所有真实的正样本中,有多少被模型正确地找了出来。它关注的是模型发现正样本的能力

公式召回率 = TP / (TP + FN)

在上面的例子中,召回率 = 68 / (68 + 18) ≈ 79.1%。

现在,让我们看看那个总是预测 y=0 的“简单算法”在这两个指标上的表现。它的混淆矩阵会是:

真实 \ 预测 预测为 0 预测为 1
真实为 0 914 0
真实为 1 86 0

它的精确率是 0/(0+0)(未定义),而召回率是 0/(0+86) = 0%。极低的召回率清晰地表明这个算法没有检测到任何正样本,因此不是一个有用的模型。

F1分数:综合考量 🤝

在实际应用中,我们经常需要比较不同模型。一个模型可能精确率高但召回率低,另一个则相反。如何综合比较呢?一个常用的方法是计算 F1分数

F1分数是精确率和召回率的调和平均数。它对精确率和召回率中较低的值赋予更大的权重,这意味着只有当模型的精确率和召回率都较高时,F1分数才会高。

公式F1分数 = 2 * (精确率 * 召回率) / (精确率 + 召回率)

假设模型A的精确率为88.3%,召回率为79.1%,其F1分数计算如下:
F1 = 2 * (0.883 * 0.791) / (0.883 + 0.791) ≈ 0.834 或 83.4%

如果一个模型(如总是预测0的模型)召回率极低,即使精确率可能很高(或未定义),其F1分数也会非常低,从而帮助我们判断其性能不佳。

在多类别偏态问题中的应用 🔍

精确率和召回率的概念同样适用于多类别分类问题,尤其是当每个类别都可能很罕见时。

例如,在智能手机缺陷检测中,我们可能需要同时检测四种罕见缺陷:划痕、凹痕、坑点、屏幕变色。我们可以为每一种缺陷类型单独计算精确率、召回率和F1分数

以下是评估多类别缺陷检测性能的示例方法:

  • 划痕:精确率 82.1%,召回率 99.2%,F1分数 89.9%
  • 凹痕:精确率 95.2%,召回率 76.5%,F1分数 84.8%
  • 坑点:精确率 87.5%,召回率 88.9%,F1分数 88.2%
  • 变色:精确率 94.7%,召回率 90.0%,F1分数 92.3%

通过观察每个类别的F1分数,我们可以:

  1. 获得一个单一的数字评估指标来整体衡量算法性能。
  2. 与人类水平性能进行基准比较。
  3. 确定下一步工作的优先级(例如,F1分数最低的“凹痕”类别可能是最需要改进的)。

使用F1分数而不是准确率的原因在于,即使算法漏检了很多罕见缺陷,整体准确率可能依然很高,从而掩盖了问题。

总结 📝

本节课中我们一起学习了如何处理和评估偏态数据集:

  1. 偏态数据集中正负样本比例严重失衡,使得准确率指标失效。
  2. 混淆矩阵是评估分类模型性能的基础工具,它区分了真阳性、真阴性、假阳性和假阴性。
  3. 精确率关注预测为正的样本中有多少是对的,召回率关注真实为正的样本中有多少被找出。它们是评估偏态数据集模型的关键指标。
  4. F1分数是精确率和召回率的调和平均数,提供了一个综合考量两者的单一评估指标,特别适用于模型比较和优先级排序。
  5. 这些指标不仅适用于二分类偏态问题,也适用于多类别分类中每个类别都罕见的场景,帮助我们更有效地评估算法并确定改进方向。

掌握这些工具将使你能够更准确地评估模型在现实世界不平衡数据上的性能,并做出更明智的工程决策。

018:性能审计 🔍

在本节课中,我们将学习在机器学习模型部署到生产环境之前,如何进行最后一次性能审计。这个步骤至关重要,它能帮助我们发现潜在问题,避免部署后出现重大故障。

概述:为何需要性能审计

即使你的学习算法在准确率、F1分数或其他合适的指标上表现良好,在将其推送到生产环境之前,进行一次最终的性能审计也常常是值得的。这有时能帮助你避免部署后出现的重大问题。

让我们来看一下。你之前见过这个图表,在你多次循环这个流程以开发出一个好的学习算法之后,最后一次审计这个性能是很有价值的。


性能审计框架

上一节我们介绍了性能审计的重要性,本节中我们来看看一个具体的审计框架。这个框架可以帮助你从准确性、公平性、偏见以及其他可能的问题方面,双重检查你的系统。

以下是执行性能审计的步骤:

第一步:头脑风暴潜在问题

首先,你需要集思广益,思考系统可能出错的不同方式。

例如:

  • 算法在不同数据子集(如特定种族或不同性别的个体)上的表现是否足够好?
  • 算法是否会犯某些特定错误,例如在倾斜数据集上可能担心的假阳性或假阴性?
  • 它在某些罕见但重要的类别上表现如何?这些是我们本周早些时候在“关键挑战”视频中讨论过的问题类型。

任何你关心的问题,都可以纳入这个头脑风暴出的系统可能出错的方式列表中。

第二步:为关注的问题建立评估指标

对于所有你担心系统可能出错的方式,你需要建立相应的评估指标。

为了根据这些问题评估算法的性能,一个非常常见的设计模式是,你经常需要评估数据“切片”上的性能。

因此,与其在整个数据集上评估性能,不如提取出特定种族的所有个体、特定性别的所有个体,或者智能手机上有划痕缺陷的所有样本。也就是说,取一个数据子集(也称为数据切片),分析这些切片上的性能,以检查可能存在的问题。

在建立了适当的指标之后,MLOps工具也可以帮助触发对每个模型的自动评估,以审计其性能。例如,TensorFlow有一个名为TensorFlow模型分析(TFMA)的包,它可以在不同的数据切片上计算新机器学习模型的详细指标。你将在下一门课程中了解更多关于这个工具的信息。

作为这个过程的一部分,我还建议你获得业务方或产品负责人的认可,确认这些是最值得关注的问题集合,以及评估这些潜在问题的合理指标集合。

第三步:分析并解决问题

如果你确实发现了问题,那么很高兴你在将系统推送到生产环境之前发现了它。然后,你可以返回去更新系统以解决这个问题,然后再部署一个可能在下游引发问题的系统。

实例演练:语音识别系统

让我们通过一个例子来演练这个框架。我将再次使用语音识别系统。

如果你构建了一个语音识别系统,你可能会头脑风暴系统可能出错的方式。例如,我之前研究过的一些系统,会关注在不同性别和不同种族上的准确性。一个在特定性别上表现不佳的语音系统可能是有问题的。种族问题也是如此。

我之前做过的一种分析是,根据说话者感知到的口音来分析我们的准确性,因为我们想了解语音系统的性能是否在很大程度上取决于说话者的口音。

或者,你可能会担心在不同设备上的准确性,因为不同的设备可能有不同的麦克风。因此,如果在某个品牌的手机上表现差很多,如果存在问题,你可以主动修复它。

最后,这可能不是你会想到的例子,但“粗俗和错误转录”的普遍性。这里有一个实际发生在一些深度学习AI课程中的例子。我们的一位讲师劳伦斯·莫罗尼正在谈论GANs(生成对抗网络),但由于转录系统错误地转录了“GANs”(因为这个词在英语中不常见),字幕中出现了很多对“gun”(枪)和“gang”(帮派)的引用,这些都是对讲师实际所说的“GAN”的错误转录。这使得那门深度学习AI课程看起来有很多枪支暴力内容,我们实际上不得不去修复它,因为我们不希望字幕里有那么多枪支帮派暴力。

更普遍的情况是,将某人的语音错误转录成一个粗俗的词语,比一个更中性的错误转录,其负面影响要大得多。因此,我也构建过语音系统,我们会特别注意避免错误转录导致语音系统认为某人说了一个粗俗的词,而实际上他们可能并没有说那个词。

基于这个头脑风暴出的语音系统可能出错的方式列表,你可以建立指标,在适当的数据切片上评估针对这些问题的性能。例如,你可以测量语音系统对于数据中代表的不同性别和不同口音的平均准确率,同时检查在不同设备上的准确性,并检查输出中是否有冒犯性或粗俗的词语。

行业标准与团队协作

我发现系统可能出错的方式很大程度上取决于具体问题。不同的行业、不同的成本会有非常不同的标准。事实上,今天在AI领域,对于什么被认为是不可接受的偏见水平,或者什么存在、什么不存在,标准仍在不断演变。在许多特定行业中,标准也仍在继续发展。

因此,我建议你搜索你所在的行业,了解什么是可接受的,并跟上公平性标准以及我们日益增长的关于如何使系统更公平、偏见更少的认识。

最后一个建议:我发现,对于高风险应用,与其让一个人独自头脑风暴可能出错的地方,不如让一个团队,有时甚至是外部顾问,帮助你集思广益,列出需要注意的事项。这可以降低你或你的团队后来被某个未曾想到的问题困扰的风险。

我知道在许多行业中,关于我们认为什么是公平和足够无偏见的标准仍在演变,但这是一个我认为我们应该走在前面、主动尝试识别、衡量并解决问题的主题,而不是部署一个系统后,在很久以后才被一些意想不到的后果所震惊。

总结

本节课中,我们一起学习了性能审计的完整流程。我们了解了在模型部署前进行最终审计的重要性,掌握了通过头脑风暴、建立切片指标、利用工具自动评估以及团队协作来系统化检查模型准确性、公平性和潜在问题的方法。我们还通过语音识别的具体例子,看到了如何将框架应用于实践。希望经过这样的审计,当你将学习算法推送到生产环境时,能拥有更高的信心。

019:面向数据的AI开发 📊

在本节课中,我们将学习如何通过面向数据的AI开发方法来提升学习算法的性能。我们将重点探讨模型中心化与数据中心化两种开发视角的区别,并理解为何在众多实际应用中,提升数据质量是改善模型性能的关键。

假设通过误差分析,你决定专注于提升学习算法在带有特定类别标签数据上的性能,例如提升在含有汽车背景噪音的语音数据上的表现。接下来,我们来看看如何采用面向数据的方法来达成这一目标。

你之前可能听我讨论过模型中心化与数据中心化的AI开发。这里,我将更详细地阐述模型中心化AI开发的含义。

模型中心化视角 🔬

在模型中心化的AI开发视角下,开发者会基于已有的数据,投入大量精力去开发一个在该数据上表现尽可能好的模型。由于大量AI学术研究是由研究人员下载基准数据集并试图在该基准上取得好成绩所驱动的,因此大多数AI学术研究都是模型中心化的。在这种视角下,基准数据是一个固定量。

因此,在模型中心化开发中,你会将数据固定,然后迭代地改进代码或模型

开发更好的模型仍然扮演着重要的角色。然而,对于许多应用而言,存在另一种我认为更有用的AI开发视角。

数据中心化视角 🗃️

这种视角是从模型中心化向数据中心化进行一定程度的转变。在此视角下,我们认为数据的质量至关重要。你可以使用误差分析或数据增强等工具来系统地提升数据质量。对于许多应用,我发现如果你的数据足够好,会有多个模型都能表现良好。

因此,在这种视角下,你可以转而将代码固定,并迭代地改进数据

模型中心化开发和数据中心化开发各有其作用。如果你在机器学习的大部分经验中习惯于模型中心化思维,我强烈建议你也考虑采用数据中心化视角。

当你试图提升学习算法的性能时,试着问自己:如何才能让你的数据变得更好?

提升数据质量最重要的方法之一是数据增强。因此,让我们进入下一个视频,开始探讨数据增强。


本节课中,我们一起学习了模型中心化与数据中心化AI开发的核心区别。我们了解到,模型中心化方法侧重于在固定数据集上优化模型,而数据中心化方法则强调通过提升数据质量(例如利用误差分析、数据增强)来驱动性能改进。对于实际应用,后者往往能带来更显著和稳健的效果提升。

020:📈 数据增强的图示理解

在本节课中,我们将学习一个用于理解数据增强及其如何提升学习算法性能的概念性图示。这个“橡皮筋”或“橡皮膜”的比喻,将帮助我们直观地规划如何通过数据增强或数据收集来系统地提升模型表现。


🧠 核心概念图示

有一张概念图,对于思考数据增强及其如何帮助提升学习算法的性能非常有用。

以语音识别为例,语音输入中可能存在多种不同类型的噪声,例如汽车噪声、飞机噪声、火车噪声、机器噪声,或者咖啡馆噪声、图书馆噪声(通常不那么吵)、美食广场噪声等。

也许这些机械类噪声彼此更相似,而这些以人声交谈为主的噪声彼此也更相似。接下来分享的这张图,便是我在规划通过数据增强或实际数据收集来获取更多数据时,心中所想的画面。

在这张图中,纵轴代表性能,例如准确率。横轴则是一个概念性的、思想实验性质的轴,代表可能的输入空间

例如,带有汽车噪声、飞机噪声、火车噪声的语音彼此相似,机器噪声则稍远一些(我设想的是洗衣机或很吵的空调的声音)。然后,你可能有带咖啡馆噪声、图书馆噪声或美食广场噪声的语音,这些彼此之间可能比与机械噪声更相似。

你的系统在这些不同类型的输入上会有不同水平的性能。假设在飞机噪声、汽车噪声、火车噪声、机器噪声数据上性能如此,而在图书馆噪声、咖啡馆噪声、美食广场噪声数据上表现更差。

因此,我可以将其想象成一条曲线,或者一个一维的橡皮筋,又或者一张橡皮膜,它展示了你的语音系统性能如何随输入类型变化。

人类在这些不同类型数据上会有另一个性能水平。也许人类在飞机噪声、汽车噪声上稍好一些,而在图书馆噪声、咖啡馆噪声和美食广场噪声上,则比你的算法好得多。因此,人类水平性能是另一条曲线。

让我用蓝色标出当前模型的性能。那么,这个差距就代表了改进的机会


🔄 数据增强的作用

现在,如果你使用数据增强,或者不是数据增强,而是实际去很多咖啡馆收集更多带有咖啡馆背景噪声的数据,会发生什么?

你所做的,就是抓住蓝色橡皮膜上的这个点,并想象把它向上拉。这就是当你收集或通过某种方式获得更多带有咖啡馆噪声的数据,并将其加入训练集时所做的事:你正在提升算法在带有咖啡馆噪声的输入上的性能。

这往往会将橡皮膜在相邻区域也向上拉。因此,如果对咖啡馆噪声的性能上升,很可能邻近点的性能也会上升。而远处点的性能可能上升不多,也可能上升不少。

事实证明,对于非结构化数据问题,拉起橡皮膜的一部分不太可能导致另一部分大幅下降。相反,拉起一个点会导致邻近点被显著拉起,而远处的点可能被拉起一点,如果运气好,也许不止一点。


🎯 规划性能提升路径

当我规划如何改进学习算法的性能,以及希望将其提升到何处时,我会在那些地方获取更多数据,从而明确地拉起橡皮膜的那些部分,使它们更接近人类水平性能。

当你拉起橡皮膜的一部分时,最大差距的位置可能会转移到其他地方。误差分析将告诉你这个新的最大差距位于何处,这可能值得你投入精力去收集更多数据,从而尝试一次拉起一个部分。

事实证明,这是一种相当高效的方法,可以决定接下来应该拉起蓝色橡皮膜的哪个部分,以尝试让性能更接近(例如)人类水平性能。


📝 总结与展望

我希望这个关于橡皮筋或橡皮膜,以及反复拉起其上某一点的类比,能帮助你预测收集与特定类别或标签相关的更多数据所带来的效果。

那么,如何获取更多这类数据呢?在下一个视频中,我们将看看如何执行数据增强以及这样做的一些最佳实践。

021:📈 第20课 数据增强

在本节课中,我们将要学习数据增强技术。这是一种为机器学习模型高效获取更多训练数据的有效方法,尤其适用于图像、音频、文本等非结构化数据问题。我们将探讨如何设计数据增强方案,并了解一些最佳实践。


🎯 数据增强的核心目标与框架

数据增强可以非常高效地获取更多数据,特别是对于图像、音频或文本等非结构化数据问题。

但在执行数据增强时,你需要做出许多选择,例如参数设置以及如何设计数据增强方案。让我们深入探讨,了解一些最佳实践。

上一节我们介绍了数据增强的基本概念,本节中我们来看看如何系统地应用它。

数据增强的目标是创建能让你的学习算法从中学习的样本。作为一个实践框架,我鼓励你思考如何创建那些算法目前表现不佳但看起来真实的样本。因为如果算法在这些样本上已经表现良好,那么它能学到的东西就有限了。

但你希望这些样本仍然是人类或某些基线模型能够处理好的。否则,生成算法表现不佳的样本的一个简单方法就是创建噪音大到任何人都听不清内容的音频,但这没有帮助。你希望样本足够有挑战性,但又不至于难到任何人类或算法都无法处理。这就是为什么在使用数据增强生成新样本时,我试图生成满足这两个标准的样本。


🔊 音频数据增强实例:语音识别

以语音识别为例。给定一段音频片段,例如“AI is the new electricity.”😊。

如果你加入咖啡馆的背景噪音,它听起来会是这样。将这两个音频波形直接相加,你就可以创建一个听起来像这样的合成样本:“AI is the new electricity.”。

这听起来就像有人在嘈杂的咖啡馆里说“AI is the new electricity.”。这是一种数据增强形式,可以让你高效地创建大量听起来像是在咖啡馆收集的数据。

或者,如果你将同一段“AI is the new electricity.”音频与背景音乐相加,那么它听起来就像有人在开着收音机的背景下说话:“AI is the new electricity.”。

现在,在执行数据增强时,你需要做出一些决定。你应该使用什么类型的背景噪音?背景噪音相对于语音应该有多大?

让我们系统地看看如何做出这些决定。


✅ 数据增强有效性检查清单

有些人进行数据增强的方法是:生成一个增强数据集,然后训练学习算法,看看算法在开发集上是否表现更好,接着调整数据增强参数,再次训练学习算法,如此循环。这种方法效率很低,因为每次更改数据增强参数,你都需要重新训练神经网络或学习算法,这可能耗时很长。

相反,我发现使用以下原则可以让你在不实际花费数小时甚至数天时间训练学习算法来验证性能提升的情况下,就能初步判断你使用数据增强生成的新数据是否有用。

具体来说,当你生成新数据时,可以遵循以下检查清单:

以下是生成新数据时可以参考的检查步骤:

  1. 它听起来/看起来真实吗? 你希望你的音频听起来像你期望算法处理的那种真实音频。
  2. X到Y的映射清晰吗? 换句话说,人类还能识别出说了什么吗?这是为了验证标准2。
  3. 算法目前在这新数据上表现不佳吗? 这有助于你验证标准1。

如果你能生成满足所有这些标准的数据,那么当你将这些数据放入训练集并重新训练算法时,成功提升算法性能的几率就会更高。


🖼️ 图像数据增强实例:划痕检测

让我们再看一个这次使用图像的例子。假设你只有一小部分带有划痕的智能手机图像。

以下是你可以使用数据增强的方法:你可以水平翻转图像,这会产生一个相当真实的图像(手机按钮现在在另一侧),但这可能是一个有用的样本来添加到你的训练集中。

或者,你可以实施对比度变化,比如实际上调亮图像,使划痕更明显一些。或者你可以尝试使图像变暗。

但在下面这个例子中,图像现在太暗了,即使我作为一个人也无法真正分辨那里是否有划痕。因此,虽然顶部的这两个例子符合我们之前的检查清单(人类仍然可以很好地检测到划痕),但这个例子太暗了,会失败那个检查。所以我会尝试选择一个能生成更多像顶部那样的例子,而不是像底部那样的例子的数据增强方案。

事实上,遵循我们希望图像看起来真实、人类能处理好、并且希望算法处理不好的原则,你也可以使用更复杂的技术,例如拍摄一张没有划痕的手机照片,然后使用Photoshop人工绘制一条划痕。

这种直接使用Photoshop的技术,也可以是生成更多样本的有效方法,因为这里的划痕例子(取决于视频压缩和你观看视频的图像对比度,你可能看到也可能看不到),但有了这条划痕,这看起来像一条相当真实的划痕,我作为一个人可以识别出这条划痕,所以如果学习算法现在没有正确检测到它,这将是一个很好的例子来添加。

我也使用过更先进的技术,如生成对抗网络来自动合成类似这样的划痕,尽管我发现像这样的技术有时可能有些“杀鸡用牛刀”,这意味着有更简单的技术实现起来快得多,效果也很好,无需构建GAN来合成划痕的复杂性。


🔄 数据迭代循环

你可能听说过“模型迭代”这个术语,它指的是迭代地训练模型,使用我们的分析,然后决定如何改进模型。

采取以数据为中心的AI开发方法,有时使用“数据迭代循环”更有用。在这个循环中,你反复获取数据和模型,训练你的学习算法,进行错误分析,并在此过程中专注于如何添加数据或提高数据质量。对于许多实际应用,采取这种数据迭代循环方法,配合稳健的超参数搜索(这也很重要),能更快地提升学习算法的性能,具体取决于你的问题。


📝 总结与下节预告

本节课中我们一起学习了数据增强技术。

当你处理非结构化数据问题时,数据增强——如果你能创建看起来真实、人类能很好处理但算法处理起来有困难的新数据——这可能是提高学习算法性能的有效方法。

因此,如果你通过错误分析发现你的学习算法在带有咖啡馆噪音的语音上表现不佳,那么通过数据增强生成更多带有咖啡馆噪音的数据,可能是提高学习算法性能的有效方法。

现在,当你向系统添加数据时,一个我经常被问到的问题是:添加数据会损害学习算法的性能吗?

通常对于非结构化数据性能,答案是否定的,但有一些注意事项。让我们在下一个视频中更深入地探讨这个问题。

022:21_增加数据会伤害模型吗?🤔

在本节课中,我们将探讨一个在机器学习实践中常见的问题:通过数据增强或收集更多特定类型的数据来改变训练集分布,是否会损害模型的性能?我们将深入分析其背后的原理,并了解在何种情况下这种做法是安全的,以及在极少数情况下可能存在的风险。


概述:数据分布变化的影响

在许多机器学习问题中,训练集、开发集和测试集的初始分布通常是相似的。

但是,如果你使用了数据增强,你就是在向训练集的特定部分添加数据,例如添加大量带有咖啡馆背景噪音的数据。

这样一来,你的训练集可能就与开发集和测试集来自非常不同的分布。

这通常会损害你的学习算法性能吗?答案通常是“不会”,但在处理非结构化数据问题时有一些注意事项。让我们更深入地看看这究竟意味着什么。


非结构化数据问题的核心原则

如果你正在处理一个非结构化数据问题,并且你的模型足够大(例如一个容量很大、偏差较低的神经网络),同时从输入X到输出Y的映射关系是清晰的(我的意思是,仅给定输入X,人类就能做出准确的预测),那么事实证明:

添加准确标记的数据很少会损害模型的准确性。

这是一个重要的观察结果,因为通过数据增强或收集更多特定类型的数据来增加数据,确实会改变你的输入数据分布,即X的概率。


模型容量是关键

假设在你的问题开始时,20%的数据带有咖啡馆噪音。但通过数据增强,你添加了大量咖啡馆噪音数据,现在50%的数据都带有背景咖啡馆噪音。

事实证明,只要你的模型足够大,它就不会妨碍它在咖啡馆噪音数据以及非咖啡馆噪音数据上都表现出色。

相反,如果你的模型很小,那么以这种方式改变输入数据分布可能会导致它花费过多资源来建模咖啡馆噪音场景,这可能会损害其在非咖啡馆噪音数据上的性能。但如果你的模型足够大,这就不是一个问题。


映射关系模糊的罕见情况

可能出现的第二个问题是,如果从X到Y的映射关系不清晰,意味着给定X,Y的真实标签非常模糊。

这在语音识别中并不常见,但让我用一个计算机视觉的例子来说明。这种情况非常罕见,因此在大多数实际问题中我并不担心,但让我们看看为什么理解这一点很重要。

多年前我参与开发的一个系统,使用谷歌街景图像来读取门牌号,以便在谷歌地图中更准确地定位建筑物和地址。

以下是该系统需要处理的任务示例:

  • 输入图片1: 识别这个数字。显然,这是一个“1”。
  • 输入图片2: 识别这个字符。这是一个字母“I”。你在街景图像中不会看到很多“I”,但有些建筑物上可能会有,例如一个写着“导航到门牌号 42 I”的指示牌。但门牌号中很少包含字母“I”。

现在,如果你发现你的算法在识别“1”时准确率很高,但在识别“I”时准确率很低,你可能会做的一件事就是在训练集中添加更多“I”的示例。

问题在于(这是一个罕见的问题),有些图像是真正模糊的:这到底是一个“1”,还是一个“I”?如果你在训练集中添加大量新的“I”,特别是像这样模糊的例子,那么可能会使数据偏向于有更多的“I”,从而损害性能。

因为我们知道门牌号上“1”的数量远多于“I”,如果学习算法看到这样一张图片,更安全的猜测是这是一个“1”,而不是一个“I”。但如果数据增强使数据偏向于有更多的“I”而不是“1”,那么它可能会导致算法在这样一个模糊的例子中做出糟糕的猜测。

因此,这是一个罕见的例子,说明增加更多数据可能会损害性能。这个“1”与“I”的例子与前面提到的第二个要点(映射清晰)相矛盾,因为对于某些图像,仅给定右边这样的图像,即使人类也无法真正分辨它是什么。


重要说明与过渡

需要明确的是,我们刚刚一起讨论的这个例子是一个非常罕见的、近乎极端的情况。对于数据增强或添加更多数据会损害学习算法性能的情况来说,这是相当不寻常的,只要你的模型足够大(也许你的神经网络足够大,能够从多样化的数据源中学习)。

但我希望,理解这种假设上可能造成损害的罕见情况,能让你更放心地使用数据增强或收集更多数据来提高算法的性能,即使这会导致你的训练集分布与开发集和测试集分布变得不同。


总结

本节课中,我们一起学习了关于增加数据是否会影响模型性能的核心观点。关键在于:

  1. 对于非结构化数据问题,如果模型容量足够大且输入到输出的映射关系清晰,通过数据增强改变训练集分布通常不会损害模型性能,反而能提升泛化能力。
  2. 只有在模型容量不足,或遇到输入输出映射极其模糊的极端罕见情况下,增加特定类型的数据才可能带来风险。

理解这些原则,可以帮助我们更自信地运用数据增强策略来改进模型。


到目前为止,我们的讨论都集中在非结构化数据问题上。那么结构化数据问题呢?事实证明,对于结构化数据,有一套不同的有用技术。让我们在下一个视频中探讨一下。

023:22_增加特征 🧩

在本节课中,我们将要学习如何通过增加特征来改进机器学习模型,特别是在处理结构化数据问题时。我们将探讨为何在难以获取新数据样本时,添加新特征是一种更有效的性能提升策略。


概述

对于许多结构化数据问题,创建全新的训练样本通常很困难。然而,我们可以采取另一种策略:利用现有的训练样本,并思考是否可以为其添加更多有用的特征。本节将通过一个餐厅推荐的实例,详细阐述这一过程。


餐厅推荐实例分析

上一节我们讨论了数据增强的局限性,本节中我们来看看一个具体的应用场景。假设你正在开发一个餐厅推荐应用,其目标是为可能感兴趣的用户推荐餐厅。

一种常见的方法是,为每个用户和每家餐厅定义一组特征,然后将这些特征输入到一个学习算法(例如神经网络)中。该算法的任务是预测“向该用户推荐此餐厅是否合适”。

问题识别

在这个真实的案例中,错误分析显示系统存在一个明显问题:它频繁地向素食者推荐只有肉类选项的餐厅。这些用户根据历史点餐记录可以明确判定为素食者,但系统仍可能因为某家新餐厅热门而推荐它,即使该餐厅没有好的素食选择。这导致了糟糕的用户体验。

解决方案:增加特征

我们无法凭空合成新的用户或餐厅样本,因为应用的用户池和餐厅数量相对固定。因此,与其尝试使用数据增强来创建全新的训练样本,不如思考为现有样本增加特征

以下是针对此问题可以考虑增加的特征:

  • 用户侧特征:增加一个特征,用于指示该用户是否为素食者。这不一定非得是二值特征(0或1),也可以是软特征,例如“历史点餐中素食所占的百分比”或其他衡量其素食倾向的指标。
    • 公式/代码示例user_feature['vegetarian_ratio'] = vegetarian_orders / total_orders
  • 餐厅侧特征:增加一个特征,用于指示该餐厅是否提供(或提供优质的)素食选项。这可以基于菜单信息得出。

通过错误分析识别出这类问题后,增加相应的特征就成为修复问题、提升算法性能的有效途径。


特征来源与生成方式

这些新增的特征可以通过多种方式获取或生成:

  • 手动编码:根据具体应用,可以由人工根据规则进行标注(例如,人工阅读菜单并判断是否为素食餐厅)。
  • 算法生成:也可以由另一个学习算法自动生成。例如,训练一个算法来阅读菜单并自动将菜品分类为“素食”或“非素食”。

更多应用场景

在其他外卖应用的例子中,我们发现有些用户只点茶和咖啡,而有些用户只点披萨。如果产品团队希望改善这些用户的体验,机器学习团队可以问:我们能否增加一些特征来识别这些特定偏好的用户? 通过丰富用户特征,可以帮助学习算法为他们做出更精准的餐厅推荐。


协同过滤 vs. 基于内容的过滤

过去几年,产品推荐领域有一个趋势:从协同过滤方法转向基于内容的过滤方法。

  • 协同过滤:这种方法主要关注用户之间的相似性。它试图找出与目标用户相似的其他用户,然后推荐这些相似用户喜欢的东西。其公式可简化为:推荐项 = 相似用户喜欢的项
  • 基于内容的过滤:这种方法更关注用户本身和物品(如餐厅)的属性。它会分析用户的特征和餐厅的描述(如菜单、类型等信息),直接判断该餐厅是否与用户匹配。

基于内容过滤的优势在于,即使面对一个全新的、几乎无人评价过的餐厅或产品(即“冷启动问题”),通过分析其内容描述而非依赖他人的评价,也能更快地做出合理的推荐。要实现这一点,确保为你想要推荐的事物捕获良好的特征至关重要。


结构化数据问题的迭代流程

对于结构化数据问题,一个典型的数据迭代流程可能如下所示:

  1. 从一个初始模型开始。
  2. 训练该模型。
  3. 进行错误分析。

在结构化数据问题上进行错误分析可能更具挑战性,因为通常缺乏一个明确的基准(例如人类水平性能)进行比较。让人工来推荐餐厅本身就很困难。

尽管如此,错误分析、用户反馈以及与竞争对手的基准测试,都能帮助你发现改进的思路。通过这些方法,如果你能识别出某个希望改进的特定数据类别或标签,就可以回过头去选择并增加一些特征


特征工程在现代深度学习中的角色

我知道在深度学习兴起之前,人们对其寄予的厚望之一就是不再需要手动设计特征。我认为,对于非结构化数据问题(如图像、音频、文本),这一点在很大程度上已经实现。我不再为图像手动设计特征,而是让学习算法自动学习。

然而,即使现代深度学习已经普及,如果你的数据集规模不够庞大,那么基于错误分析来设计特征,对于当今许多应用而言仍然非常有用。数据集越大,纯端到端的深度学习算法才越可能独立工作良好。

但对于绝大多数公司(有时甚至包括最大的科技公司),在某些应用场景下,设计特征——尤其是针对结构化数据问题——仍然是驱动性能提升的重要手段。也许对于非结构化数据我们不再需要过多手动设计特征,因为学习算法在这方面已经非常出色。但对于结构化数据,深入研究和优化特征仍然是合理且有效的做法。


总结

本节课中我们一起学习了:

  1. 核心策略:在处理结构化数据且难以获取新样本时,为现有数据增加特征是提升模型性能的有效方法。
  2. 实施步骤:通过错误分析识别模型的具体缺陷(如向素食者推荐肉食餐厅),进而设计并添加能解决该问题的特征(如用户素食倾向、餐厅素食选项)。
  3. 方法对比:了解了协同过滤基于内容的过滤在推荐系统中的区别,后者更依赖良好的物品特征来应对“冷启动问题”。
  4. 现代意义:认识到即使在深度学习时代,对于数据量有限的结构化数据问题,基于错误分析的特征工程仍然是提升性能的关键驱动力。

通过本节课,希望你掌握了如何通过增加特征这一具体、可操作的步骤,来迭代和改进你的机器学习模型。

024:实验跟踪 📊

在本节课中,我们将学习如何通过有效的实验跟踪来系统性地改进机器学习算法。随着实验数量的增加,记录每一次尝试的细节变得至关重要。本节将介绍实验跟踪的最佳实践、需要记录的关键信息以及可用的工具。


实验跟踪的重要性

当你致力于迭代改进算法时,确保拥有稳健的实验跟踪系统能帮助你更高效地工作。随着实验数量增加到几十、几百甚至更多,很容易忘记已经运行过哪些实验。一个跟踪系统能帮助你在数据、模型或超参数的选择上做出更明智的决策,从而系统地提升算法性能。

需要跟踪的关键信息

当你跟踪已运行的实验(即已训练的模型)时,我建议你记录以下几类信息。以下是需要记录的核心内容:

  1. 算法与代码版本:记录你使用的算法和代码版本。保留这些记录能让你更容易地回溯和复现可能在两周前运行、细节已记不清的实验。
  2. 使用的数据:记录训练模型时使用的具体数据集。
  3. 超参数:记录模型训练时使用的所有超参数设置。
  4. 实验结果:将结果保存在某个地方。这至少应包括高层次指标,如准确率、F1分数或其他相关指标。如果可能,保存一份训练好的模型副本会很有用。

实验跟踪工具

那么,如何跟踪这些信息呢?你可以考虑使用以下一些跟踪工具。很多个人,有时甚至是小型团队,最初会从文本文件开始。当我独自进行实验时,可能会用一个文本文件,为每个实验写几行文字来记录我所做的事情。这种方法扩展性不好,但对于小型实验可能可行。

许多团队随后会从文本文件迁移到电子表格,尤其是在团队协作时。电子表格的不同列可以用来跟踪你想为不同实验记录的不同信息。电子表格的扩展性实际上要好得多,特别是团队成员都可以查看的共享电子表格。

但超过一定规模后,一些团队也会考虑迁移到更正式的实验跟踪系统。实验跟踪系统领域仍在快速发展,因此可用的工具越来越多。一些例子包括:

  • Weights & Biases
  • Comet.ml
  • MLflow
  • SageMaker Studio
  • Landing AI(我担任CEO的公司)也有自己的实验跟踪工具,专注于计算机视觉和制造应用。

选择工具时的考量因素

当我尝试使用一个跟踪工具时,无论是文本文件、电子表格还是更大型的系统,我会关注以下几点:

  1. 可复现性:它是否提供了复现结果所需的全部信息?在可复现性方面,需要注意的一点是:如果你的学习算法从互联网上获取数据,由于网络数据可能发生变化,这会降低可复现性,除非你在系统实现时非常小心。
  2. 结果分析:能帮助你快速理解特定训练运行的实验结果的工具,最好能提供有用的汇总指标,甚至可能进行一些深入分析。这能帮助你更快地查看最近的实验,甚至回顾旧实验并记起当时的情况。
  3. 其他功能:一些其他可以考虑的功能包括资源监控(使用了多少CPU或GPU内存资源)、帮助可视化训练模型的工具,甚至能帮助进行更深入错误分析的工具。我发现所有这些功能有时都是实验跟踪框架中有用的特性。

核心建议与总结

不过,与其过分纠结于具体使用哪个实验跟踪框架,我希望你从本视频中带走的首要建议是:务必建立某种系统,哪怕只是一个文本文件或一个电子表格。通过跟踪你的实验,并尽可能方便地包含更多信息,因为日后当你试图回顾、记起你是如何生成某个模型时,拥有这些信息将对帮助你复现自己的结果非常有用。

在本节课中,我们一起学习了实验跟踪在机器学习工作流中的重要性,明确了需要记录的四大类关键信息(代码、数据、超参数、结果),并概览了从简单文本文件到专业平台的各种跟踪工具及其选择考量。最重要的是,建立并坚持使用一个跟踪系统,是高效、可复现地改进模型的基础。

025:从大数据到好数据 📊

在本节课中,我们将学习如何从追求“大数据”转向关注“好数据”,并理解“好数据”在机器学习项目生命周期中的核心作用。我们将探讨“好数据”应具备的关键特性,以及如何通过系统化的方法确保数据质量,从而构建高性能、可靠的机器学习系统。


在上一节中,我们讨论了以数据为中心的AI开发方法。本节中,我们来看看一个重要的思维转变:从“大数据”到“好数据”。

许多现代AI技术成长于拥有海量用户的大型消费互联网公司。这类公司拥有数十亿用户,因此积累了海量数据。如果你拥有这样的“大数据”,它无疑能极大地提升你的模型性能。

然而,对于许多其他行业而言,并不存在数十亿的数据点。我认为,对于这些应用场景,关注“好数据”可能比追求“大数据”更为重要。我发现,如果你能在机器学习项目生命周期的所有阶段,确保数据始终保持高质量,这是保证机器学习部署高性能和可靠性的关键。

那么,什么是“好数据”呢?我认为“好数据”涵盖了以下几个重要的“C”:

以下是“好数据”应具备的几个关键特性:

  1. 良好的覆盖范围:你的数据应能良好地覆盖不同的输入 X。例如,如果你发现缺少带有咖啡馆噪音的语音数据,数据增强技术可以帮助你获取更多、更多样化的输入 X,从而改善覆盖范围。我们在本周的材料中花了相当多的时间讨论这一点。
  2. 一致的定义:“好数据”也意味着标签 Y 的定义是一致且明确的。我们尚未深入讨论这一点,但下周我们会进行更详细的探讨。
  3. 及时的反馈:“好数据”需要来自生产数据的及时反馈。我们实际上在上周讨论部署部分时已经谈到了这一点,即通过监控系统来跟踪概念漂移和数据漂移。
  4. 合理的规模:最后,你确实需要一个合理规模的数据集。

为了总结,在机器学习项目生命周期中:

  • 上周我们讨论了在部署阶段,如何确保获得及时的反馈。
  • 本周我们讨论了建模,并在讨论中包含了如何确保对重要场景有良好的覆盖。
  • 下周,当我们深入探讨数据定义时,我们将花更多时间讨论如何确保你的数据定义是一致的。

我希望,通过上周、本周和下周传达的理念,你将掌握所需的工具,能够在机器学习项目生命周期的所有阶段,为你的学习算法提供“好数据”。


本节课中我们一起学习了“好数据”的概念及其四大关键特性:良好的覆盖范围、一致的定义、及时的反馈和合理的规模。理解并实践这些原则,是构建稳健、高效机器学习系统的基石。

恭喜你完成本周关于建模的视频学习!我期待在下周与你更深入地探讨机器学习项目全周期中的数据部分。下周我们还将有一个关于确定机器学习项目范围的简短可选章节。期待下周与你再见!

026:数据定义为何困难 🎯

概述

在本节课中,我们将要学习为什么在机器学习项目中,明确定义数据(即输入X和输出Y)是一项具有挑战性的任务。我们将通过具体的例子,探讨数据标注不一致如何影响模型性能,并理解清晰定义数据的重要性。


数据定义为何困难?🤔

欢迎回来,你现在已经进入了本课程的第三周,也是最后一周。完成本周内容后,你将结束这个专业课程的第一门课。

本周我们将深入探讨数据。你如何获取数据,为成功的模型训练做好准备?

但首先,为什么定义要使用什么数据本身就很困难?让我们来看一个例子。

我将使用检测鬣蜥的例子。我的一位朋友凯伦非常喜欢鬣蜥,所以我周围有很多鬣蜥的图片。假设你进入森林,收集了数百张这样的图片,并将这些图片发送给标注员,并附上指令:“请使用边界框来指示鬣蜥的位置。”

一位标注员可能会像这样标注,并说“一只鬣蜥,两只鬣蜥”。这位标注员做得很好。

第二位同样勤奋、同样努力的标注员可能会说:“看,左边的鬣蜥有一条尾巴一直延伸到图片的右侧。”因此,第二位标注员可能会说“一只鬣蜥,两只鬣蜥”。这位标注员也做得很好。

第三位标注员可能会说:“好吧,我将浏览所有数百张图片并标注它们,我将使用边界框来指示鬣蜥的位置,并像这样画一个边界框。”

三位勤奋努力的标注员可能会想出这三种非常不同的标注鬣蜥的方式。也许其中任何一种方式实际上都可以接受。我个人更倾向于前两种,而不是第三种。但是,如果这些标注约定中的任何一种都能让你的学习算法学会一个相当不错的鬣蜥检测器,那也没问题。

真正有问题的是,如果你的标注员中,三分之一使用第一种约定,三分之一使用第二种,三分之一使用第三种约定。因为那样你的标签就会不一致,这会让学习算法感到困惑。

鬣蜥的例子很有趣,你在许多实际的计算机视觉问题中也会看到这种影响。

让我们使用手机缺陷检测的例子。如果你要求标注员使用边界框来指示重大缺陷。

也许一位标注员会看着图片说:“哦,很明显,划痕是最重大的缺陷。让我在上面画一个边界框。”

第二位标注员可能会看着这部手机说:“实际上有两个重大缺陷。有一个大划痕,然后那里还有一个小痕迹。那叫做凹坑,就像有人用尖锐的螺丝刀戳了手机一样。”我认为第二位标注员可能做得更好。

然后,第三位标注员可能会看着这个说:“好吧,这里有一个边界框,显示了这些缺陷的位置。”

在这三个标签中,可能中间的那个效果最好。但这是一个非常典型的例子,说明了即使标注指令只有轻微的模糊性,你也会从标注过程中得到不一致的标签。

如果你能始终如一地使用一种约定(也许是中间那种)来标注数据,你的学习算法会表现得更好。

本周我们将要做的是,深入探讨机器学习项目全周期中数据阶段的最佳实践。

具体来说,我们将讨论如何:

  • 定义什么是数据,什么应该是X,什么应该是Y。
  • 建立一个基线。

做好这些工作将为你很好地标注和组织数据奠定基础,从而在你进入建模阶段时为你提供一个良好的数据集。

正如你上周所看到的,许多机器学习研究者和工程师最初都是从网上下载数据来试验模型的,也就是使用别人准备好的数据。这本身没有任何问题。

但对于许多实际应用来说,你准备数据的方式将对机器学习项目的成功产生巨大影响。


总结

本节课中,我们一起学习了数据定义在机器学习项目中的核心挑战。我们通过鬣蜥检测和手机缺陷检测的例子,看到了标注不一致如何导致模型困惑。关键在于,团队需要就X(输入)Y(输出/标签) 的定义达成清晰、一致的共识,并建立可靠的基线。清晰的数据定义是构建高质量数据集、进而训练出高性能模型的基石。

在下一个视频中,我们将查看更多数据可能模糊不清的例子,这将为我们本周后续学习一些提高数据质量的技术做好准备。让我们继续观看下一个视频。

027:更多标签歧义示例 🧩

在本节课中,我们将学习机器学习项目中常见的标签歧义问题。通过分析图像、语音和结构化数据的具体案例,我们将理解为什么数据标注会不一致,以及这种不一致性如何影响模型性能。最后,我们将探讨如何通过定义清晰的输入和输出来系统性地解决这些问题。


在上一节视频中,我们看到了图像的正确边界框标注可能存在歧义。

本节中,我们来看看更多标签歧义的示例。

我们在课程第一周简要提及过语音识别,这里有一个相关例子。

给定这段音频片段。听起来像是有人站在繁忙的路边询问最近的加油站,然后一辆车驶过。那么他们在车驶过后是否还说了些什么?这并不确定。

因此,一种转录方式可能是“nearest gas station”。在某些地区,人们会用两个M来拼写“station”,这将是另一种拼写方式。我们也可以用省略号(…)代替逗号,这又是一种歧义。

或者,考虑到音频在最后一个词后有噪音。“Ands guest station”。他们是否说了“off the nearest gas station”?实际上并不确定。

那么,你会像这样转录吗?因此,转录这段音频存在多种方式。

使用一个M还是两个M,用逗号还是省略号,是否在末尾标注“unintelligible”(无法识别)。

能够标准化一种约定将有助于你的语音识别算法。


我们也来看一个结构化数据的例子。在许多大公司中,一个常见的应用是用户ID合并。这是指当你拥有多个你认为对应同一个人的数据记录,并希望将这些用户数据记录合并时的情况。

例如,假设你运营一个提供在线职位列表的网站。这可能是你从一位注册用户那里获得的一条数据记录,包含电子邮件、名、姓和地址。现在,假设你的公司收购了第二家公司,该公司运营一个移动应用程序,允许人们登录并互相聊天、获取关于简历的建议。

如果你运营在线职位列表业务,这看起来具有协同效应。也许你合并或收购了第二家运营移动应用程序的公司。该应用程序让人们可以就简历进行聊天。从这个移动应用程序中,你拥有一个不同的用户数据库。

那么,给定这条数据记录和另一条数据记录,你认为这两个是同一个人吗?

解决用户ID合并问题的一种方法是使用监督学习算法。该算法接收两个用户数据记录作为输入,并尝试输出1或0,基于它是否认为这两个记录实际上是同一个真实的人。

如果你有办法获取真实数据记录,例如,如果少数用户愿意明确地关联两个账户,那么这可以成为训练算法的一组良好的标注示例。

但如果你没有这样一组真实数据,许多公司所做的就是请求人工标注,有时是产品管理团队,手动查看一些经过筛选的记录对(这些记录对可能具有相似的名字或邮政编码),然后仅凭人工判断来确定这两条记录是否看起来是同一个人。

因为这两条记录是否真的是同一个人确实存在歧义,他们可能是,也可能不是。不同的人会不一致地标注这些记录。

如果有办法让他们更一致地标注数据(你将在后面看到一些如何做到这一点的例子),即使真实情况是模糊的,这也能帮助你提升学习算法的性能。用户ID合并在许多公司中是一个非常常见的功能。

请允许我提醒你,请务必以尊重用户数据及其隐私的方式进行此操作,并且仅在你使用数据的方式符合用户已授予的权限范围内进行。用户隐私确实非常重要。


结构化数据的其他几个例子。

如果你尝试使用学习算法来查看像这样的用户账户,并预测它是否是机器人或垃圾账户。有时这可能是模糊的。

或者,如果你查看一次在线购买,判断这是否是一次欺诈交易。是否有人窃取了账户并使用被盗账户与你的网站互动或进行购买?有时这也存在歧义。

或者,如果你查看某人与你网站的互动,并想知道他们此刻是否正在寻找新工作。基于某人在招聘网站或简历聊天应用上的行为,你有时可以猜测他们是否在找工作,但很难确定。因此,这也存在一些歧义。

面对这些可能非常重要且有价值的预测任务时,真实情况可能是模糊的。

因此,如果你请人们对这些任务的真实标签做出最佳猜测,那么提供能带来更一致、噪声更少、随机性更低的标签的标注说明,将提升你的学习算法的性能。


因此,在为你的学习算法定义数据时,以下是一些重要问题。

首先,什么是输入X?例如,如果你试图检测智能手机上的缺陷,对于你拍摄的图片,光线是否足够好?相机对比度是否足够好?相机分辨率是否足够好?

所以,如果你发现有一批像这样暗到连人都很难看清情况的图片,正确的做法可能不是直接拿这个输入X去标注。正确的做法可能是去工厂,礼貌地请求改善照明条件。因为只有图像质量更好,标注员才能更容易地看到像这样的划痕并进行标注。

因此,有时如果你的传感器、成像解决方案或录音解决方案不够好,你能做的最好的事情就是认识到:如果连人都无法通过查看输入来判断发生了什么,那么提升传感器质量或提升输入X的质量,可能是确保你的学习算法获得合理性能的重要第一步。

对于结构化数据问题,定义要包含哪些特征会对学习算法的性能产生巨大影响。例如,对于用户ID合并,如果你有办法获取用户的位置(即使是粗略的GPS位置),并且在获得用户许可的情况下使用,这可能是判断两个用户账户是否真正属于同一个人的非常有用的线索。当然,请务必仅在获得用户许可以这种方式使用其数据的情况下进行此类操作。


除了定义输入X,你还必须弄清楚目标标签Y应该是什么。正如你从前面的例子中看到的,一个关键问题是:我们如何确保标注员给出一致的标签?

在上一个视频和本视频中,你看到了标签存在歧义的各种问题,或者在有些情况下,输入X的信息量不足(如图像太暗)。让我们将这些数据问题纳入一个更系统的框架中,以便我们能以更系统化的方式设计解决方案。让我们进入下一个视频来一探究竟。


本节课中,我们一起学习了机器学习项目中标签歧义的多种表现形式,包括图像边界框、语音转录和结构化数据(如用户ID合并、欺诈检测)中的案例。我们认识到,清晰定义输入数据的质量(如光照、传感器)和输出标签的标注规范,对于减少歧义、获得一致标注至关重要,这是构建高性能模型的基础。下一节,我们将系统性地探讨解决这些数据问题的方法。

028:27_主要的数据问题类型 🧠

在本节课中,我们将学习一个用于思考不同类型机器学习项目的实用框架。我们将看到,为一种类型项目组织数据的最佳实践,可能与另一种完全不同类型项目的最佳实践大相径庭。

概述:一个实用的项目分类框架

为了清晰地理解不同机器学习项目的特点,我们可以使用一个二维网格进行分类。这个框架有助于我们预测哪些数据实践和机器学习思想可以从一个项目推广到另一个项目。

数据类型的两个维度

上一节我们介绍了分类框架的概念,本节中我们来看看构成这个框架的两个核心维度。

维度一:结构化与非结构化数据

第一个维度是数据的形式:你的机器学习问题是使用非结构化数据还是结构化数据

  • 非结构化数据:如图像、音频和文本。人类擅长处理这类数据。
  • 结构化数据:如数据库记录。人类处理这类数据的效率相对较低。

我发现,处理这两类数据的最佳实践非常不同。

维度二:数据集的规模

第二个维度是数据集的规模:你拥有的是相对较小的数据集还是非常大的数据集

这里没有精确的大小定义,但我将使用一个稍显任意的阈值:10,000个样本

  • 小数据集:通常指样本数少于10,000的数据集。这个规模小到足以让个人或小团队高效地检查每一个样本。
  • 大数据集:通常指样本数超过10,000的数据集。这个规模使得手动检查每个样本变得非常耗时。

选择10,000作为阈值的原因是,超过这个规模后,亲自检查每一个样本会变得相当困难。

四种项目类型示例

以下是四种不同类型机器学习项目的例子:

  • 非结构化数据 & 小数据集:使用仅100个有划痕手机图像样本来训练一个制造视觉检测系统。
  • 结构化数据 & 小数据集:基于房屋面积等特征,使用仅50个训练样本来预测房价。
  • 非结构化数据 & 大数据集:使用5000万个训练样本来进行语音识别。
  • 结构化数据 & 大数据集:拥有100万用户的数据库,尝试进行在线购物产品推荐。

不同象限的最佳实践差异

了解了四种基本类型后,我们来看看处理它们时,最佳实践有何关键区别。

非结构化 vs. 结构化数据

对于许多非结构化数据问题,人类可以帮助你标注数据。此外,数据增强技术(如合成新图像、新音频或新文本)可以提供帮助。

  • 制造视觉检测:可以使用数据增强生成更多智能手机图片。
  • 语音识别:数据增强可以帮助合成带有不同背景噪音的音频片段。

相比之下,对于结构化数据问题,通常更难获取更多数据,也更难使用数据增强。例如,如果某个地区最近只售出了50套房屋,很难合成不存在的“新房屋”。同样,拥有100万用户的数据库,也很难合成不存在的“新用户”。此外,让人工标注结构化数据通常也更困难(尽管并非不可能)。

小数据集 vs. 大数据集

当你的数据规模不同时,工作的侧重点也会发生显著变化。

对于小数据集:
干净的标签至关重要。如果只有100个训练样本,哪怕只有一个样本被错误标注,也意味着数据集的1%出现了错误。由于数据集小到足以让你或一个小团队高效地检查,花时间确保每个样本都按照一致的标注标准被清晰、一致地标注,通常是值得的。

对于大数据集:
干净的标签仍然非常有帮助,但让一个小型机器学习团队手动检查每个样本可能很困难甚至不可能。因此,工作重点应放在数据流程上,即你如何收集、安装、存储数据,以及你为大型众包标注团队编写的标注指令。一旦你执行了某个数据流程(例如让大型标注团队标注了大量音频片段),再回头更改决定并重新标注所有内容也会困难得多。

各象限策略总结

以下是针对不同象限的策略总结:

对于非结构化数据问题:
你可能拥有大量未标注的样本 X。有时,你可以通过获取这些未标注数据 X 并让人工标注更多数据来获得更多数据。数据增强也可能有帮助。

对于结构化数据问题:
通常更难获得更多数据,因为你能收集数据的来源(如用户、房屋)是有限的。人工标注平均而言也更困难,因为即使对于人类标注者,确定某些结构化数据的正确标签也可能存在更多模糊性。

对于小数据集:
干净的标签至关重要。数据集可能小到足以让你手动检查整个数据集并修复任何不一致的标签。此外,标注团队可能不大,如果发现标签不一致,可以很容易地让相关人员协商并统一标注标准。

对于大数据集:
重点必须放在数据流程上。如果你有100名甚至更多的标注员,很难让所有人聚在一起讨论并敲定流程。因此,你可能需要依靠一个较小的团队来建立一致的标签定义,然后与所有标注员分享该定义,并要求他们执行相同的流程。

一个重要的思考与建议

我发现这种将问题分类为非结构化/结构化、小数据/大数据的方法,不仅有助于预测数据实践的可推广性,也有助于预测其他机器学习思想的可推广性。

因此,一个建议是:如果你正在处理这四个象限中某一类的问题,那么平均而言,来自在同一象限工作过的人的建议,可能比来自在不同象限工作过的人的建议更有用。

在招聘机器学习工程师时我也发现,在与我试图解决的问题相同象限工作过的人,通常能更快地适应在该象限内处理其他问题,因为在一个象限内,其工作直觉和决策比切换到图表中完全不同的象限更为相似。

我有时听到人们给出诸如“如果你在构建计算机视觉系统,至少要获取10个标注样本”的建议。我认为给出这种建议的人是善意的,但我发现这种建议并非对所有问题都有用。机器学习非常多样化,很难找到这种“一刀切”的建议。我见过用100个样本构建的计算机视觉问题,也见过用1亿个样本构建的分类系统。

因此,如果你正在为机器学习项目寻求建议,请尝试找到在你正试图解决的问题的同一象限工作过的人。😊

总结与下节预告

本节课中,我们一起学习了根据数据是结构化/非结构化、数据集规模是大/小来对机器学习项目进行分类的框架,并探讨了不同类别项目在最佳实践上的核心差异。

我们讨论了一种机器学习问题的分类方法。在下一个视频中,我想与大家深入探讨其中一个方面:为什么对于小数据问题,拥有干净的数据尤为重要。让我们在下一个视频中看看为什么这是真的。

029:小数据集与标签一致性 📊

在本节课中,我们将要学习在小数据集场景下,保持标签的干净一致为何至关重要。我们将通过具体例子,理解标签一致性如何帮助学习算法建立更可靠的模型,并探讨即使在拥有大数据集时,如何处理其中的“小数据”挑战。


概述:小数据集的挑战

在小数据集问题中,拥有干净且一致的标签尤为重要。当数据量有限时,标签中的噪声或不一致性会极大地影响模型学习正确函数映射的能力。

上一节我们介绍了数据质量的重要性,本节中我们来看看在小数据集场景下,标签一致性如何成为决定模型成败的关键。


从直升机控制说起 🚁

让我们从一个例子开始。我曾使用机器学习来控制直升机飞行。其中一个任务是:输入施加在直升机旋翼电机上的电压,预测旋翼的转速(RPM)。这类问题也常见于其他电机控制场景。

假设我们只有五个数据点,这是一个非常小的数据集。由于输出标签 y(转速)存在噪声,我们很难确定应该使用何种函数来映射电压到转速。

可能的函数关系:

  • 可能是一条直线。
  • 可能先上升后变平。
  • 可能是一条曲线。

当数据集很小且标签有噪声时,我们很难有信心地拟合出一个函数。


大数据集的优势

如果我们拥有海量数据,情况则完全不同。即使数据噪声水平与左边的小数据集相同,但数据量巨大,学习算法可以通过对噪声数据取平均来拟合出一个函数。此时,我们可以相当自信地认为函数曲线应该是某种形状。

许多AI技术成长于拥有海量用户(如数亿或数十亿)的大型互联网公司,因此处理大数据集的方法得到了充分发展。然而,如何应对小数据集的实践方法,对于那些没有一亿个样本,而只有一千甚至更少样本的问题,强调得还不够。


小数据集的关键:干净一致的标签

对我来说,更有趣的情况是:如果我们仍然只有五个数据点(与左侧例子相同),但标签是干净且一致的。在这种情况下,即使只有五个例子,我们也能相当自信地拟合出一个函数,并建立一个相当好的模型来根据输入电压预测速度。

我曾用仅仅30张图像训练计算机视觉系统,并且效果很好。关键通常在于确保标签是干净和一致的。


手机缺陷检测示例 📱

让我们看另一个手机缺陷检测的例子。任务是输入如下图片,判断手机上是否存在缺陷。

如果标注说明最初不清晰,那么标注员对图像的标注就会不一致。例如,一个巨大的划痕,所有人都同意是缺陷;一个微小的瑕疵,检查员会忽略它。但在一个模糊区域(例如划痕长度在0.2到0.4毫米之间),不同的检查员可能会以略微不一致的方式标注。

一种解决方案是尝试获取更多手机或划痕的图片,观察检查员如何判断,最终训练一个神经网络来从图像中平均判断什么是划痕。这种方法可能有效,但需要大量工作来收集图像。

我发现,更有效的方法是让检查员坐下来,就“多大尺寸的划痕需要被标注为缺陷”达成一致。例如,如果标注员能同意,从“小瑕疵”转变为“缺陷”的临界点是长度为0.3毫米,那么他们对图像的标注就会变得一致得多。这使得学习算法更容易以这些图像作为输入,并一致地判断某物是否是划痕或缺陷。

需要明确的是,在这个例子中,学习算法的输入是左侧那样的图像,而不是右侧那样的划痕长度。关键在于,如果你能让检查员就“什么是划痕”达成一致,并将任务定义为“为长度超过0.3毫米的缺陷绘制边界框”,那么这将使你的图像标注更加一致,即使你的数据集不大,也能让你的学习算法达到更高的准确度。


大数据集中的“小数据”挑战

你已经看到了几个标签一致性如何帮助学习算法的例子。我想用一个更深入的思考来结束这个视频:大数据问题也可能面临小数据挑战

具体来说,有些问题虽然拥有大数据集,但其中存在一个罕见事件的长尾分布,那么这些罕见事件的输入数据同样会面临小数据挑战。

以下是几个例子:

  • 网络搜索引擎:大型网络搜索引擎公司拥有海量的搜索查询数据集,但许多搜索查询实际上非常罕见。因此,针对这些罕见查询的点击流数据量实际上很小。
  • 自动驾驶汽车:自动驾驶汽车公司往往拥有从数十万或数百万小时驾驶中收集的庞大数据集。但存在一些对确保自动驾驶汽车安全至关重要的罕见情况,例如“小孩跑上高速公路”或“卡车横停在高速公路上”。即使自动驾驶汽车有非常大的数据集,它拥有的这些罕见事件的例子数量实际上也非常少。因此,确保这些罕见事件如何被检测和标注的标签一致性,对于提升自动驾驶汽车或产品推荐系统的性能仍然非常有帮助。
  • 产品推荐系统:如果你有一个包含数十万或数百万甚至更多商品的在线目录,那么你将会有很多商品,其销售量非常小。因此,你拥有的关于用户与这些长尾商品互动的数据量实际上也很小。如果有一种方法(虽然不容易)能确保这些数据是干净和一致的,那么这将有助于你的学习算法决定是否推荐这些每个商品数据量都很少的长尾商品。

总结与预告

所以,当你拥有小数据时,标签一致性至关重要。即使你拥有大数据,标签一致性也可能非常重要。只是平均而言,在较小的数据集上实现标签一致性比在非常大的数据集上更容易。

在下一节视频中,我们将探讨一些具体的想法和最佳实践,以提高你数据集的标签一致性。让我们继续学习下一课。

030:提高标签一致性 📝

在本节课中,我们将学习如何提高数据标签的一致性。标签质量是机器学习项目成功的关键,不一致的标签会严重影响模型性能。我们将探讨一个系统性的流程和几种实用技巧,帮助你获得更高质量的训练数据。

概述

标签不一致是数据标注过程中的常见问题。本节将介绍一个通用流程,通过让标注者讨论、标准化定义、合并类别或创建新类别等方法,来系统地提高标签的一致性。

提高标签一致性的通用流程

如果你担心标签不一致,可以遵循以下流程。

以下是具体步骤:

  1. 找出不一致的示例:选取一些样本,让多位标注者为同一个样本打标签。
  2. 检查自我一致性:在某些情况下,可以让同一位标注者标注一个样本,等待一段时间(例如让他们休息一下),然后回来重新标注同一个样本,检查他们自身是否保持一致。
  3. 讨论分歧:当发现存在分歧时,让负责标注的人员(可能是机器学习工程师、领域专家或专职标注员)一起讨论,就标签更一致的定义达成共识。
  4. 记录共识:将达成的一致意见和定义记录下来。
  5. 更新标注指南:这个新的定义可以成为更新后的标注指南,用于标注新数据或重新标注旧数据。
  6. 评估输入信息:在讨论中,如果标注者反馈输入信息 X 不足(例如图片太暗无法判断),则应考虑改进输入 X(例如改善拍摄光照条件)。
  7. 迭代优化:这是一个迭代过程。在改进操作或标注指南后,让团队标注更多数据。如果仍然存在分歧,则重复上述流程。

上一节我们介绍了提高标签一致性的通用流程,本节中我们来看看一些具体的应用实例和技巧。

提高一致性的具体技巧

以下是几种在实践中常用的技巧。

  • 标准化标签定义:这是最常见的结果之一。例如,对于之前视频中的音频片段,标注者可以标准化一个统一的标注惯例(如统一标注为“nearest”),从而使数据更一致。
  • 合并难以区分的类别:如果标注指南要求区分“深划痕”和“浅划痕”,但两者的界限模糊,导致标注极不一致,而业务上又不需要严格区分,那么合并这两个类别为一个单一的“划痕”类,可以消除不一致性。公式可以表示为:
    合并后类别 = 类别A ∪ 类别B
  • 创建“不确定”类别:对于边界模糊的样本,强制标注可能导致不一致。此时,可以创建一个新的“边界”或“不确定”类别。例如,在判断手机划痕是否为缺陷时,可以设立三个标签:“明确无缺陷”、“明确有缺陷”和“边界情况”。这承认了某些样本的模糊性,反而能提高其他样本标注的一致性。
  • 处理模糊输入:以语音识别为例,如果一段音频确实难以听清(如“nearest”),强迫标注者猜测会导致不一致。更好的做法是创建一个“无法识别”的标签,让所有标注者都将此类样本标为“无法识别”,从而提高整体一致性。

处理不同规模数据集的建议

根据数据集规模的不同,提高标签一致性的策略也应有所调整。

  • 小数据集:通常标注者数量较少。发现不一致时,可以直接请标注者坐下来,针对具体的图像或音频片段进行讨论,以达成一致。
  • 大数据集:更常见的做法是,先由一个小组达成一致的定义和标注指南,然后将这些指南分发给更大的标注团队去执行。

关于“投票”机制的说明

一种常用但可能被过度使用的技术是让多位标注者标注每个样本,然后通过投票(有时称为“共识标注”)来决定最终标签,以提高准确性。

虽然这种投票机制有效,但在当今机器学习领域可能被过度使用了。我见过很多团队的做法是,在标注指南本身不一致的情况下,试图通过大量标注者和投票来使其变得一致。

在诉诸投票(我有时也会用,但更多是作为最后手段)之前,我通常会首先尝试获得更一致的标签定义,努力从源头上减少单个标注者选择的噪声,而不是先获取大量带噪声的数据,再试图用投票来减少噪声。

总结

本节课中我们一起学习了如何系统性地提高数据标签的一致性。我们介绍了一个包含发现分歧、讨论共识、迭代优化的通用流程,并探讨了标准化定义、合并类别、创建不确定类别等具体技巧。同时,我们也了解了针对不同规模数据集的策略,并对“投票”机制的使用给出了建议。提高标签一致性是获取高质量训练数据、构建可靠机器学习模型的重要基础步骤。


关于提高标签质量,一个经常被提及的问题是:一项任务的“人类水平表现”是什么?我发现“人类水平表现”是一个重要但有时被误解的概念。让我们在下一个视频中更深入地探讨这个问题。

031:人类水平表现 👨‍💻

在本节课中,我们将要学习机器学习中一个重要的概念:人类水平表现。我们将探讨它的定义、主要用途、常见的误用场景以及如何更有效地利用它来指导机器学习项目的开发。


概述

人类水平表现是衡量机器学习模型性能的一个重要基准。它主要用于估计任务的贝叶斯错误率,帮助我们设定合理的性能目标,并指导错误分析和优化工作的优先级。然而,它也可能被误用,例如作为证明算法“优越性”的简单标准。本节课将详细解析这些内容。


什么是人类水平表现?

一些机器学习任务试图预测本质上就模糊不清的输出。人类水平表现可以作为一个有用的性能基准和参考。

衡量人类水平表现最重要的用途之一是估计贝叶斯错误率不可约错误,尤其是在非结构化数据任务上,以帮助进行错误分析和确定优化优先级。


如何测量人类水平表现?🔍

为了确定什么是可能达到的性能,我们可以进行一个视觉检查任务。例如,业务负责人可能要求构建一个准确率达到99%或99.9%的系统。

一种确定可能性的方法是:取一个数据集,查看其真实标签。假设有6个样本,其真实标签如下。然后,请一位人类检查员在不知道真实标签的情况下,对相同的数据进行标注。

如果检查员标注的结果如下,那么可以说,这位检查员在6个样本中的4个上与真实标签一致,在2个上不一致。因此,人类水平表现就是 66.7%

这样,你就可以向业务负责人说明:即使是人类检查员也只有66.7%的准确率,因此期望达到99%的准确率是不现实的。所以,人类水平表现有助于建立一个关于可能达到的性能的基线。


关于“真实标签”的思考 🤔

这里有一个常被忽视的问题:所谓的“真实标签”究竟是什么?我们测量的,究竟是相对于某个“真实标签”我们能做得多好,还是仅仅测量两个不同的人恰好彼此同意的程度?

当“真实标签”本身也是由人确定时,情况就有所不同。在本次和下一个视频中,我将分享一种关于人类水平表现的非常不同的思考方式。


人类水平表现的其他用途

除了估计贝叶斯错误率和确定可能性以帮助进行错误分析和优先级排序外,人类水平表现还有其他一些用途。

  • 学术界的基准:在学术界,人类水平表现常被用作一个受人尊敬的基准。如果你能证明在一个语音识别数据集上,人类只有92%的准确率,而你的算法超越了人类水平,这就有助于证明你的学习算法正在做一件困难的事情,并有助于论文发表。这并不是说这是人类水平表现的最佳用途,但在学术界,展示你能首次超越人类水平表现,一直是一个行之有效的公式,用于确立一项工作的学术意义。

  • 设定现实目标:我们在上一节简要讨论了,如果业务或产品负责人要求99%的准确率,而你认为这不现实,那么测量人类水平表现可以帮助你建立一个更合理的目标。

  • 一个需要谨慎使用的用途:你可能听说过的另一个用途是,许多机器学习团队希望用“超越人类水平表现”来证明机器学习系统优于执行该工作的人类。尽管这种逻辑很诱人,但作为一个实际问题,这种方法很少奏效。而且,正如上周所讨论的,企业需要的系统不仅仅是平均测试集准确率高。因此,如果你发现自己处于这种情况,我敦促你谨慎使用这种逻辑,或者更优选的是,根本不要使用这种论点。我通常发现,与企业合作探讨是否应该采用机器学习系统时,其他论点比这更有效。


以“超越人类水平表现”证明优越性的问题

以“超越人类水平表现”作为机器学习优越性证明的问题是多方面的,除了大多数应用需要的不只是高的平均测试准确率之外。

这个指标的一个问题是,当标注指令不一致时,它有时会给学习算法一个不公平的优势。

让我解释一下这是什么意思。如果你有不一致的标注指令,例如,当一段音频说“哦,最近的加油站……”时,假设70%的标注员使用“...”的标注惯例,30%的标注员使用“,”的标注惯例。这两种转录方式没有优劣之分,都完全可以接受,但只是碰巧70%的标注员选择了第一种,30%选择了第二种。

如果“真实标签”是由一位标注员(可能只是头衔稍高的标注员)确定的,那么两个随机标注员达成一致的概率将是:
0.7² + 0.3² = 0.58

按照通常测量人类水平表现的方法,你会得出结论:人类水平表现是0.58。但你真正测量的是两个随机标注员达成一致的概率。

这就是机器学习算法具有不公平优势的地方。我认为这两种标注惯例都完全可以接受。但如果学习算法更擅长统计在这种上下文中使用省略号与逗号的频率,那么它可能总是选择第一种标注惯例,因为它知道从统计上讲,如果使用省略号,它有70%的机会是正确的。因此,学习算法将有70%的时间与人类标注一致。

仅仅通过选择第一种标注惯例,学习算法就获得了12%的性能提升(70% - 58%)。但这12%的性能提升,对于这两种同样好、略带任意性的选择来说,实际上并不重要。学习算法只是始终如一地选择第一种,所以它在这种类型的查询上获得了看似12%的优势,但实际上并没有以任何用户关心的方式超越任何人类。

这种做法的副作用是:如果你的语音识别任务有多种类型的音频,对于某些类型存在这种“...”与“,”的模糊性,学习算法在这方面表现好12%。如果你的学习算法在其他类型的输入音频上犯了更严重的错误,那么它实际表现更差的地方,可能会被这类查询平均掉,从而掩盖或隐藏你的学习算法实际上产生的转录结果比人类更差的事实。

这意味着,一个机器学习系统可能看起来比人类水平表现更好,但实际上产生的转录结果比人更差,因为它只是在这种不重要的问题上做得更好,同时可能在其他类型的输入音频上实际做得更差。


总结与更好的方法

鉴于人类水平表现的这些问题,我们应该怎么做?测量人类水平表现对于建立基线、用以驱动错误分析和优先级排序是有用的,但用它来对机器和人类进行基准测试有时会遇到像这样的问题。

我发现,当我的目标是构建一个有用的应用程序(而不是发表论文)时,与其试图超越人类水平表现,不如尝试提高人类水平表现往往更有用。因为我们可以通过提高标签一致性来提高人类水平表现,而这最终也会带来更好的学习算法性能。

在下一个视频中,让我们更深入地探讨这一点。


本节课中,我们一起学习了人类水平表现的概念、测量方法、主要用途以及常见的陷阱。关键在于理解它作为一个参考基准分析工具的价值,而不是一个简单的“超越”目标。合理使用它可以帮助我们设定现实期望、指导模型优化,并最终构建出更实用的机器学习系统。

032:31_提高人类水平表现 🎯

在本节课中,我们将探讨“人类水平表现”在机器学习项目中的意义、作用以及潜在的误用。我们将重点分析当“真实标签”的来源不同时,HLP 所扮演角色的差异,并学习如何通过提升标签一致性来优化机器学习系统的实际性能。


概述

人类水平表现常被用作衡量机器学习算法性能的基准。然而,其价值高度依赖于“真实标签”的定义方式。当真实标签由外部客观标准定义时,HLP 是衡量算法潜力的有效工具。但当真实标签仅来源于另一人的标注时,HLP 的低下可能揭示了标签标准本身的不一致问题。

真实标签的来源与 HLP 的意义

上一节我们提到了人类水平表现的概念,本节中我们来看看其意义如何随真实标签的来源而变化。

当真实标签由外部客观事实定义时,HLP 能有效衡量可避免偏差。例如,在基于 X 光片预测诊断结果的任务中,如果诊断的“真实标签”依据的是活检等医学检测结果,那么 HLP 衡量的是医生或算法预测该客观结果的能力。这种对比非常有价值。

但当真实标签仅来源于人类的标注时,情况则不同。例如,一位医生标注的 X 光片成为“真实标签”,那么 HLP 衡量的就是另一位医生或算法预测这位医生标注的能力。这虽然也有用,但与预测客观医学结果有着本质区别。

标签不一致对 HLP 的影响

在真实标签源于人工标注的场景下,HLP 显著低于 100% 可能仅仅意味着标签标准模糊或不一致,而非任务本身难以达到完美。

以下是来自视觉检测的一个具体例子:

假设一位质检员对缺陷的标注准确率为 66.7%。与其单纯追求算法超越这位质检员的表现,更有价值的做法是探究为何作为“真实标签”的另一位质检员的标注会与之不同。

例如,检查他们对六处划痕长度的标注记录:

样本 质检员A标注 质检员B标注(作为真实标签) 实际划痕长度 (mm)
1 有缺陷 (1) 有缺陷 (1) 1.0
2 无缺陷 (0) 有缺陷 (1) 0.2
3 有缺陷 (1) 有缺陷 (1) 0.5
4 无缺陷 (0) 无缺陷 (0) 0.0
5 有缺陷 (1) 无缺陷 (0) 0.1
6 无缺陷 (0) 无缺陷 (0) 0.0

如果两位质检员能共同商定一个明确标准,例如“长度超过 0.3mm 的划痕才算缺陷”,那么上述不一致的标签就可以被修正:

  • 样本2:长度0.2mm < 0.3mm,应修正为“无缺陷 (0)”。
  • 样本5:长度0.1mm < 0.3mm,应修正为“无缺陷 (0)”。

通过这个统一标准的过程,人类水平表现在此六样本集上就从 66.7% 提升到了 100%。虽然这使得算法在表面上更难“击败”HLP,但更关键的是,我们获得了更清晰、更一致的数据,这将最终帮助学习算法实现更好的实际性能。

结构化数据中的 HLP

上述讨论主要围绕非结构化数据展开,但其中一些问题同样适用于结构化数据。

结构化数据问题较少涉及人工标注,因此 HLP 的使用频率较低。但仍存在例外情况,例如:

  • 记录匹配:判断两条记录是否属于同一个人,可能需要人工标注。
  • 网络安全:根据网络流量判断计算机是否被黑客入侵,需要 IT 专家提供标签。
  • 欺诈检测:难以判断交易是否欺诈时,需人工介入标注。
  • 账户分类:区分真实用户账户与机器人生成的账户。
  • 交通模式识别:根据 GPS 轨迹判断出行方式是步行、骑车、驾车还是乘公交。

对于此类问题,初期请人工标注数据是合理的。同样,当预测目标来自人工标注时,关于 HLP 意义的疑问依然存在:较低的 HLP 可能源于标签不一致,而努力提升标签一致性,既能提高 HLP,也能为算法提供更干净的数据以提升其性能。

核心要点总结

本节课中我们一起学习了人类水平表现在机器学习项目中的正确理解与应用方式。

以下是本节课的核心要点:

  1. HLP 是一个重要参考:对于人类表现能提供有用基准的问题,应当测量并利用 HLP 来评估可能性、指导错误分析和确定优化优先级。
  2. 警惕低 HLP 的根源:在测量 HLP 时,如果发现其远低于 100%,需要自问:这是否源于标签指令或标准的不一致?
  3. 提升一致性是关键:如果确实存在不一致,那么致力于改进标签一致性,虽然会提高 HLP(使算法更难超越),但更重要的是能为学习算法提供更干净、更一致的数据,从而最终提升算法的实际性能。

简而言之,HLP 的终极价值不应仅是提供一个被超越的靶子,更应是帮助我们发现数据标注过程本身的问题,从而构建出更健壮、更有效的机器学习系统。

033:获取数据 📊

在本节课中,我们将要学习如何为机器学习项目获取数据。我们将探讨获取数据的最佳实践,包括如何平衡数据收集时间、如何盘点数据来源、如何选择数据标注方式,以及如何决定数据集的增长规模。

你已经了解了如何定义数据、如何定义输出 y 和输入 X。那么,如何为你的任务实际获取数据呢?让我们来看看一些最佳实践。

数据收集的时间投入 ⏱️

一个关键问题是,你应该在获取数据上花费多长时间?机器学习是一个高度迭代的过程,你需要选择模型、超参数,拥有数据集,然后进行训练或分析,并多次循环这个过程才能得到一个好模型。

假设训练你的第一个模型需要几天时间,进行第一次误差分析也需要几天。在这种情况下,我建议你不要花30天去收集数据,因为这会让你延迟整整一个月才能进入这个迭代循环。相反,我建议你尽快进入这个迭代循环。

如果训练模型和误差分析可能只需要几天,我建议你问自己:如果只给自己两天时间收集数据,是否能帮助你更快地进入这个循环?也许两天太短,但我见过太多团队在训练初始模型之前花了太长时间收集初始数据集。实际上,我很少遇到一个团队,我会对他们说:“嘿,你们真的应该花更多时间收集数据。”

在你训练了初始模型并进行误差分析之后,有足够的时间可以回去收集更多数据。对于我领导的许多项目,当我告诉团队“我们最多花七天收集数据,我们能做什么?”时,我发现以这种方式提出问题通常会带来更有创意的方法,这些方法仍然100%尊重隐私使用并遵守任何监管考虑,但能以更灵活的方式快速获取大量数据,让你更快地进入迭代循环,使项目进展更快。

这个准则的一个例外是,如果你以前处理过这个问题,并且从经验中知道至少需要一定的训练集规模,那么前期投入更多精力收集那么多数据可能是可以的。因为我从事过语音识别工作,我对需要多少数据来完成某些事情有很好的感觉,我知道如果数据少于一定小时数,尝试训练某些模型是不值得的。

但很多时候,如果你在处理一个全新的问题,并且不确定需要多少数据,通常很难从文献中判断。如果你不确定到底需要多少数据,那么最好快速收集少量数据来训练模型,然后使用误差分析来判断是否值得去收集更多数据。

盘点数据来源 📋

在获取所需数据方面,我经常执行的另一个步骤是盘点可能的数据来源。让我们继续以语音识别为例。

如果你要集思广益列出数据来源,这可能是你想出的清单:

  • 可能已经拥有100小时的转录语音数据。因为你已经拥有它,所以成本为零。
  • 你可能能够使用众包平台并付钱让人们朗读文本。你提供一段文本,让他们大声朗读,这样就创建了文本数据,因为你已经有了转录稿,他们正在朗读你拥有的一段文本。
  • 你可能决定获取尚未标记的音频,并付费进行转录。事实证明,按小时计算,这比付钱让人们朗读文本更昂贵,但这会产生听起来更自然的音频,因为人们不是在朗读。对于100小时的数据,获得高质量的转录可能需要花费6000美元。
  • 你可能会发现一些商业组织可以通过类似这样的练习向你出售数据。

通过这样的练习,你可以集思广益,思考你可能使用的不同类型的数据及其相关成本。我发现这个表格中缺少一个非常重要的列,那就是时间成本。执行项目以获取这些不同类型的数据需要多长时间?

对于自有数据,你可以立即获得。对于众包朗读,你可能需要实现一堆软件,找到合适的众包平台,进行软件集成,因此你可能会估计有两周的工程工作量。付费标记数据更简单,但仍然需要组织和管理工作。而购买数据可能涉及采购订单流程,可能会快得多。

我发现有些团队不会经历这样的盘点过程,而只是随机选择一个想法。也许决定使用众包朗读来收集数据。但如果你能坐下来,写下所有不同的数据来源,并仔细考虑权衡,包括成本和时间,那么这通常可以帮助你做出更好的决策,决定使用哪些数据来源。

因此,如果你时间特别紧迫,基于此分析,你可能会决定使用自有数据,也许购买一些数据,并使用这些数据,而不是中间两个选项,以便更快地启动。

数据标注方式的选择 🏷️

除了可以获取的数据量、财务成本和时间成本之外,其他重要因素还包括数据质量。例如,你可能会决定付费标记实际上比让人们听起来像在朗读能提供更自然的音频。同样重要的是隐私和监管约束。

如果你决定获取数据标记,以下是一些你可能需要考虑的选项。获取数据标记的三种最常见方式是:

  • 内部标记:让你自己的团队标记数据。
  • 外包:你可能找到一些专门标记数据的公司,让他们为你做。
  • 众包:你可能使用众包平台,让一大群人共同标记数据。

外包与众包的区别在于,根据你拥有的数据类型,可能有专门的公司可以非常高效地帮助你获得标记。

这些选项之间的一些权衡包括:

  • 让机器学习工程师标记数据通常很昂贵,但我发现,为了让项目快速启动,让机器学习工程师做几天通常是可以的。事实上,这有助于建立机器学习工程师对数据的直觉。当我从事一个新项目时,如果这有助于我建立对项目的直觉,我通常不介意自己花几个小时或一两天标记数据。但超过某个点后,你可能不希望作为机器学习工程师把所有时间都花在标记数据上,你可能希望转向更具扩展性的标记流程。
  • 根据你的应用,可能也有不同的群体或亚群体更有资格提供标记。例如,如果你从事语音识别工作,那么几乎任何相当流利的说话者都可以听音频并转录。因此,由于说某种语言的人数众多,语音识别拥有非常大的潜在劳动力池。对于更专业的应用,如工厂检查或医学图像诊断,街上的普通人可能无法查看医学X光图像并从中诊断,或者查看智能手机并确定什么是缺陷、什么不是缺陷。因此,像这样更专业的任务通常需要SME(主题专家)才能提供准确的标记。
  • 最后,有些应用很难让任何人给出好的标记。以产品推荐为例。可能有些产品推荐系统给你的推荐比你最好的朋友甚至你的另一半给你的更好。对于这种情况,你可能只能依赖用户的购买数据作为标记,而不是让人类来标记。

当你从事一个应用时,弄清楚你正在处理的应用属于哪一类,并确定合适类型的人或人群来帮助你标记,将是确保你的标记高质量的重要一步。

数据集规模的扩大策略 📈

最后一个建议。假设你有一千个样本,并且你决定需要一个更大的数据集。你应该把你的数据集扩大多少?我给很多团队的一个建议是,一次不要将数据增加超过10倍。

所以,如果你有一千个样本,并且你已经在一千个样本上训练了你的模型,也许值得投入尝试将你的数据集增加到3000个样本,或者最多10000个样本。但我首先会进行10倍或少于10倍的增加,训练另一个模型,进行误差分析,然后才确定是否值得大幅增加数据量。因为一旦你的数据量增加了10倍,很多事情都会改变,真的很难预测会发生什么。

将数据量增加10%或50%或仅仅2倍也是可以的,所以这只是你可能投入增加数据量的上限。希望这个准则能帮助团队避免过度投资于大量数据,结果却发现收集大量数据并不是他们能做的最有用的事情。

我希望本视频中的技巧能帮助你在收集数据时更有效率。

总结 ✨

本节课中我们一起学习了获取数据的核心策略。我们讨论了应尽快进入“训练-分析”的迭代循环,避免在初期过度收集数据。我们介绍了盘点数据来源的方法,需要综合考虑成本、时间和数据质量。我们分析了内部标记、外包和众包三种数据标注方式的适用场景与权衡。最后,我们学习了数据集扩大的策略,建议一次增长不超过10倍,并通过误差分析指导后续的数据收集工作。掌握这些方法,将帮助你更高效、更明智地为机器学习项目获取所需的数据。

现在,当你收集数据时,你可能会遇到的一个需求是构建数据管道,因为你的数据不是一次性全部到来的,而是需要经过多个预处理步骤。让我们进入下一个视频,看看构建数据管道的一些最佳实践。

034:数据管道 🛠️

在本节课中,我们将要学习数据管道的基本概念、其重要性,以及在机器学习项目不同阶段如何管理数据管道的可复现性。


数据管道概述

数据管道,有时也称为数据级联,指的是数据在到达最终输出之前需要经过多个处理步骤。管理这类数据管道有一些最佳实践。

数据管道示例

上一节我们介绍了数据管道的概念,本节中我们来看看一个具体的例子。

假设给定一些用户信息,你需要预测该用户当前是否正在寻找工作。如果用户正在找工作,你可能希望向他们展示招聘广告或其他特别有用的信息。

给定原始数据(例如顶部的数据),在数据被输入到学习算法进行预测之前,通常需要进行某种预处理或数据清洗。数据清洗可能包括垃圾信息清理(例如移除垃圾账户)以及用户ID合并(我们在之前的视频中讨论过)。

为了这个例子,假设垃圾信息清理和用户ID合并仅通过脚本完成。脚本是明确的指令序列,告诉你的代码何时应将账户视为垃圾账户,以及何时应合并两个用户ID。当然,这些系统也可以使用机器学习算法构建,这会使它们的管理稍微复杂一些。

数据清洗脚本与可复现性问题

当你使用脚本进行数据清洗时,会遇到的一个问题是在生产部署中的可复现性。

假设在系统开发期间,输入数据通过预处理脚本进行处理,预处理后的数据被输入到机器学习算法中。经过一段时间的工作,你的学习算法在测试集上表现良好。

在开发阶段,你可能已经发现预处理脚本可能相当混乱。可能是你临时拼凑了一些东西来处理数据,将文件通过邮件发送给团队中的另一个成员,让他们用Python或其他脚本语言执行一些指令来处理数据,然后再让他们将处理后的数据通过邮件发回给你。

当你将这个系统投入生产时,新的数据需要经过一组类似的脚本进行处理,因为这些数据将被输入到同一个机器学习算法中。而你的机器学习算法在这些数据上的运行结果将体现在你的产品中。

因此,关键问题是:如果你的预处理是通过分散在一堆不同人员的电脑和笔记本电脑上的一系列脚本完成的,你如何复制这些脚本,以确保输入到机器学习算法的数据分布对于开发数据和对于生产数据是相同的?

项目不同阶段的投资策略

我发现,为确保预处理脚本高度可复现而应投入的工作量,可能在一定程度上取决于项目所处的阶段。

我知道,现在可能流行说你所做的一切都应该是100%可复现的,我可能会因为没有严格遵循这一原则而受到一些批评。但我发现很多项目确实会经历一个概念验证阶段,然后是一个生产阶段。

在概念验证阶段,主要目标是决定该应用是否可行,是否值得构建和部署。我给大多数团队的建议是,在概念验证阶段,专注于让原型工作起来。如果一些数据预处理是手动的,这是可以接受的。如果项目成功,你以后需要复制所有这些预处理,所以我的建议是:做详细的笔记,写大量的注释,以提高以后能够复制所有这些预处理的可能性。但在这个阶段,也不应该为了确保可复现性而陷入大量的流程中,因为重点确实是决定该应用是否可行,是否值得进入下一阶段。

一旦你决定这个项目值得投入生产,那么你就知道能够复制任何预处理脚本将变得非常重要。因此,在这个阶段,我会使用更复杂的工具来确保整个数据管道是可复现的。这时,一些可能稍显重量级但非常有价值的工具,如TensorFlow Transform、Apache Beam、Airflow等,就变得非常重要。事实上,你将在本专项课程后面学到更多关于TensorFlow Transform的知识。

总结

本节课中我们一起学习了数据管道及其可复现性。你了解了数据管道的基本概念,并通过一个预测用户求职意向的例子看到了数据清洗和预处理步骤。我们讨论了使用脚本进行预处理时可能遇到的可复现性挑战,特别是在从开发过渡到生产环境时。最后,我们探讨了在项目不同阶段(概念验证阶段和生产阶段)应如何调整对数据管道可复现性的投资策略,并介绍了一些用于确保可复现性的工具。


事实证明,许多应用的数据管道比我们在本视频中看到的要复杂得多。对于这些场景,你还必须考虑需要哪些元数据,或许还需要跟踪和处理数据的来源和谱系。让我们继续下一个视频来探讨这些主题。

035:元数据、数据溯源与血统 📊

在本节课中,我们将学习元数据、数据溯源与数据血统的概念。这些概念对于构建和维护复杂、可维护的机器学习系统至关重要。我们将通过一个具体的例子来理解它们,并探讨如何利用元数据来辅助错误分析和系统改进。


数据管道的复杂性

上一节我们讨论了数据处理的基本流程。本节中,我们来看看一个更复杂的商业数据管道示例。

假设我们正在构建一个系统,用于预测用户在当前时刻是否正在寻找工作。这个系统可能涉及多个步骤和数据源。

以下是构建该预测模型可能涉及的数据处理步骤:

  1. 反垃圾邮件处理:从原始用户数据开始,首先需要过滤垃圾邮件账户。

    • 你从外部供应商处获得一份垃圾邮件数据,其中包含已知的垃圾邮件账户列表和特征,例如一份已知被垃圾邮件发送者使用的IP地址黑名单
    • 你实现一个机器学习算法(一段代码),并在垃圾邮件数据集上训练它,从而得到一个反垃圾邮件模型
    • 将你的用户数据输入这个反垃圾邮件模型,得到去垃圾邮件后的用户数据
  2. 用户ID合并:接下来,你可能需要合并属于同一个人的多个账户。

    • 你有一些ID合并数据,这是标注数据,告诉你哪些账户对实际上对应同一个人。
    • 你训练另一个机器学习模型,得到一个学习到的ID合并模型,用于判断何时将两个账户合并为一个用户ID。
    • 将这个ID合并模型应用于去垃圾邮件后的用户数据,得到清理后的用户数据
  3. 最终预测:最后,基于清理后的用户数据(希望其中包含用户是否正在找工作的标签),训练另一个机器学习模型,得到一个预测用户是否找工作的模型。这个模型随后可用于对其他用户或整个用户数据库进行预测。

这种复杂程度的数据管道在大型商业系统中并不少见,甚至存在比这复杂得多的数据级联。


数据溯源与血统的挑战

构建了这样一个复杂系统后,一个挑战随之而来:如果运行数月后,你发现上游数据出了问题怎么办?

例如,你发现所使用的IP地址黑名单中存在错误。具体来说,有些IP地址被错误地列入了黑名单。这可能是因为供应商误将公司或大学校园内出于安全原因共享的IP地址判定为垃圾邮件源。

问题在于:如果你更新了你的垃圾邮件数据,这将会改变你的反垃圾邮件模型,进而影响后续的ID合并模型和最终预测模型。你该如何追溯并修复这个问题?特别是当每个子系统由不同的工程师开发,相关文件分散在团队成员的笔记本电脑上时。

为了确保系统的可维护性,尤其是在上游数据需要更改时,跟踪数据溯源血统会非常有帮助。

  • 数据溯源指的是数据的来源。例如,你从谁那里购买了垃圾邮件IP地址列表。
  • 数据血统指的是到达管道末端所需的一系列步骤序列。

至少,详尽的文档可以帮助你重建数据溯源和血统。但要构建健壮、可维护的生产级系统(而非概念验证阶段),有更成熟的工具可以帮助你跟踪发生的一切,从而让你能够更改系统的某一部分,并相对容易地复现数据管道的其余部分。

坦率地说,在当前的机器学习领域,用于跟踪数据溯源和血统的工具仍不成熟。我发现详尽的文档可以提供帮助,一些正式的工具如 TensorFlow Transform 也有所助益。但作为一个技术社区,我们尚未完全解决这类问题。


元数据的强大作用

为了让管理数据管道、进行错误分析和推动机器学习开发变得更轻松,我想分享一个秘诀:广泛使用元数据

元数据是关于数据的数据。例如,在制造业视觉检测中,数据是手机图片和对应的缺陷标签。

但如果你拥有以下元数据,情况就不同了:

  • 这张手机图片是何时拍摄的?
  • 图片来自哪个工厂?哪条生产线?
  • 相机设置是什么(如曝光时间、光圈)?
  • 你正在检测的手机编号是多少?
  • 提供此标签的检测员ID是什么?

这些是关于你的数据集 XY 的数据示例。这类元数据可能非常有用。

因为如果你在机器学习开发过程中发现,由于某种奇怪的原因,工厂2的第17号生产线产生的图像错误率异常高,那么这些元数据就能让你回溯,去探究工厂2第17号线到底有什么问题。

但如果你一开始就没有存储工厂和生产线编号这些元数据,那么在错误分析阶段就很难发现这一点。我多次遇到这样的情况:有时甚至只是碰巧存储了正确的元数据,却在一个月后发现,这些元数据帮助产生了推动项目前进的关键洞察。

我的建议是:如果你有存储元数据的框架或MLOps工具集,那肯定会让事情变得更简单。但即使没有,就像你很少会后悔为代码添加注释一样,我认为你也很少会后悔存储那些日后可能变得有用的元数据。同样,如果你没有及时存储元数据,之后再想回头收集和组织这些数据会困难得多。

再举一个语音识别的例子:

  • 如果你有来自不同品牌智能手机录制的音频。
  • 或者你有不同的标注员为你的语音数据做标注。
  • 或者你使用了语音活动检测模型,那么请记录你所使用的VAD模型的版本号。

所有这些都意味着,如果由于某种原因,某个版本的VAD系统导致了更大的错误,这些元数据将显著增加你发现这一问题并利用它来提升算法性能的几率。

总而言之,元数据对于错误分析、发现意外效应或识别某些性能异常差的数据子类别非常有用,从而为如何改进系统提供线索。当然,毫不意外,这类元数据对于跟踪数据来源(数据溯源)也非常有用。


本节总结

本节课中我们一起学习了数据溯源、数据血统和元数据的概念。

本视频的核心要点是:对于你可能需要维护的大型复杂机器学习系统,跟踪数据溯源血统可以让你的工作轻松得多。作为构建这些系统的一部分,请考虑跟踪元数据,这不仅能帮助你追踪数据溯源,还能辅助错误分析。

在结束本节之前,还有一个重要的技巧希望与大家分享,那就是平衡训练/开发/测试集划分的重要性。让我们进入下一个视频。

036:平衡的训练集、开发集和测试集 🎯

在本节课中,我们将要学习一个在数据量较小时能显著提升机器学习开发流程效率的技巧:如何创建平衡的训练集、开发集和测试集。


许多机器学习实践者习惯于将数据随机分割为训练集、开发集和测试集。然而,当你的数据集规模较小时,确保这些集合具有平衡的类别分布,可以极大地改善你的机器学习开发流程。让我们通过一个例子来深入理解这一点。

为何需要平衡分割? ⚖️

上一节我们介绍了数据分割的基本概念,本节中我们来看看当数据量不足时,随机分割可能带来的问题。

以制造业视觉检测为例。假设你的训练集共有100张图像,这是一个相当小的数据集。其中包含30个正例(有缺陷的手机)和70个负例(无缺陷的手机)。

如果你采用60/20/20的比例进行随机分割,即:

  • 60%的数据进入训练集
  • 20%的数据进入开发集(验证集)
  • 20%的数据进入测试集

那么,仅凭随机性,你最终可能会得到以下分布:

  • 训练集:21个正例
  • 开发集:2个正例
  • 测试集:7个正例

以下是各集合的正例比例计算:

  • 训练集:21 / 60 ≈ 35%
  • 开发集:2 / 20 = 10%
  • 测试集:7 / 20 = 35%

虽然训练集(35%)和测试集(35%)的正例比例与整体数据(30%)相差不大,但开发集的正例比例仅为10%。这意味着你的开发集不具有代表性,因为它只包含了2个正例,而非与整体分布匹配的6个正例。当数据集很小时,这种因随机性导致的不具代表性的分割发生的几率会更高。

什么是平衡分割? ✅

我们真正希望的是每个集合都能准确地反映整体数据的分布。对于这个例子,理想的分割应该是:

  • 训练集(60个样本):60 * 30% = 18 个正例
  • 开发集(20个样本):20 * 30% = 6 个正例
  • 测试集(20个样本):20 * 30% = 6 个正例

这样,每个集合都保持了30%的正例比例。这种分割方式被称为平衡分割。它使得你的开发集和测试集能更可靠地衡量学习算法的性能。

何时使用平衡分割? 📊

理解平衡分割的优势后,我们来看看它的适用场景。

  • 小数据集场景:当你处理的数据集规模较小时,显式地确保进行平衡分割至关重要。这是能对你的模型性能产生重大影响的小技巧之一。
  • 大数据集场景:如果你的数据集非常庞大,则无需担心此问题。随机分割极有可能产生具有代表性的子集,各子集中的正例比例会非常接近整体数据分布。


总结与课程回顾 🏁

本节课中我们一起学习了平衡分割的概念、方法及其重要性。核心要点是:在处理小数据集时,采用平衡的训练集、开发集和测试集分割,可以使你的评估指标更加可靠。

恭喜你完成本课程数据部分的所有视频学习!在过去的课程中,你还学习了建模与部署。接下来还有一个关于项目范围界定的可选章节,如果你有兴趣了解如何选择机器学习项目,欢迎继续观看。

无论如何,祝贺你完成了本课程所有必修内容!希望你收获颇丰,并能在未来的所有机器学习项目中应用这些思想。

037:什么是确定范围

在本节课中,我们将学习如何为机器学习项目“确定范围”,即如何选择最有价值的工作项目并进行规划。这是当今人工智能领域一项至关重要且稀缺的技能。

项目范围确定的重要性

上一节我们介绍了课程背景,本节中我们来看看为什么需要仔细确定项目范围。

我记得在我年轻时,我倾向于直接投入第一个让我兴奋的项目。有时我很幸运,项目进展顺利。但当我积累了更多经验后,我发现,如果你或你的团队将要花费大量时间(数周、数月甚至更久)在一个项目上,那么花时间思考几个选项,并尝试在投入巨大努力之前选择最有前景的项目,是非常值得的。

因此,让我们深入探讨“确定范围”。

项目构思与头脑风暴

让我们以一个希望扩大规模的电子商务零售商为例。如果你坐下来头脑风暴一家电商公司可以做什么,你可能会想出很多点子。

以下是可能想到的一些项目想法:

  • 更好的产品推荐系统。
  • 更好的搜索功能,以便用户能找到他们想要的东西。
  • 发现商品目录数据缺少字段或不完整,这影响了搜索和推荐结果,因此你可能启动一个项目来改进目录数据的质量。
  • 帮助他们进行库存管理,例如决定购买多少衬衫以及将衬衫运往何处。
  • 进行价格优化。

通过一次快速的头脑风暴,你可能会想出几十个帮助这家电商零售商的点子。

范围确定过程的核心问题

在范围确定过程中,我们希望回答以下问题:

  • 我们应该从事哪个(或哪些)项目?
  • 成功的衡量标准是什么?
  • 执行这个项目需要哪些资源(例如数据、时间、人员)?

我在很多企业中观察到,在所有你可以从事的想法中,有些想法的价值会远高于其他想法,可能高出两倍、五倍甚至一百倍。能够选择最有价值的项目将显著增加你工作的影响力。

总结与过渡

机器学习是一个通用工具,我们可以用它做很多事情。那么,我们如何选择有价值的工作项目呢?

在下一节视频中,我们将更深入地探讨范围确定的具体过程。

038:确定项目范围的过程 🎯

在本节课中,我们将学习一个用于确定机器学习项目范围的系统性过程。这个过程有助于在项目初期,清晰地识别业务问题并探索可能的AI解决方案,从而确保团队将精力投入到最具价值和可行性的项目上。


识别问题与解决方案

上一节我们介绍了项目范围确定的重要性,本节中我们来看看如何具体地识别业务问题与潜在的解决方案。

当首次与公司讨论AI项目时,我通常会与业务或产品负责人(通常不是AI专家)一起进行头脑风暴。这个阶段的目标是识别业务问题,而不是AI问题。

例如,在与一家电子商务零售公司交流时,我可能会问:“你们最希望改进的前三件事是什么?”他们可能会提出以下业务问题:

  • 希望提高网站转化率(即访问者完成购买的比例)。
  • 希望减少库存积压。
  • 希望提高每件售出商品的利润率。

在这个阶段,我明确不关注AI问题。我的职责是与合作伙伴一起,判断是否存在AI解决方案。有时答案是否定的,这也没关系。

只有在明确了业务问题之后,我们才开始头脑风暴,探索是否存在可能的AI解决方案。并非所有问题都能用AI解决,但我们需要为一些业务问题构思机器学习算法的应用思路。

我发现,将问题识别解决方案识别分开进行非常有帮助。作为工程师,我们擅长提出解决方案,但首先清晰地阐述问题是什么,往往能帮助我们想出更好的方案。这种问题与解决方案的分离,在设计思维的相关著作中也能见到。


探索解决方案示例

以下是针对之前提到的三个业务问题,可能产生的AI解决方案思路。

针对“提高转化率”的问题,可以构思多种解决方案:

  • 改进网站搜索结果质量,让用户搜索时找到更相关的商品。
  • 基于用户购买历史提供更好的商品推荐
  • 重新设计商品在页面上的展示方式。
  • 找到有趣的方式,突出显示最相关的商品评论,帮助用户了解商品并促成购买。

针对“减少库存”的问题,可以构思的解决方案包括:

  • 启动需求预测项目,以更准确地估计销量,从而避免采购过多或过少,实现更精准的库存管理。
  • 策划营销活动,专门推动那些采购过多的商品的销售,引导更多购买以消化仓库库存。

针对“提高利润率”的问题,可以构思的解决方案有:

  • 使用机器学习来优化销售品类(在零售业中有时称为商品规划),决定什么值得销售,什么不值得。
  • 推荐商品捆绑销售,例如当用户购买相机时,向他们推荐相机保护套,这类捆绑销售也能提高利润率。

问题识别是思考“你想要实现什么目标”的步骤,而解决方案识别则是思考“如何实现这些目标”的过程。


发散思维与收敛思维

在探索了多种可能性后,我们需要进行评估和筛选。这个过程涉及从发散思维到收敛思维的转变。

我至今仍看到太多团队会直接跳入他们第一个感到兴奋的项目。根据我的经验,如果你对某个应用或行业有深厚的领域知识,你的直觉认为可行的第一个想法或许可以。但即便如此,我仍然认为首先进行发散思维是值得的,即头脑风暴出大量可能性;随后再进行收敛思维,将范围缩小到一个或少数几个最有前景的项目上集中精力。

我希望大家能避免的一种情况是:在一个项目上投入大量工作,创造了一定量的经济或社会价值,但如果有另一个项目,在相同的工作量下能创造10倍的价值。我认为这种项目范围确定过程将帮助你实现这一点。


评估与规划

在头脑风暴出各种不同的解决方案后,下一步就是评估这些方案的可行性价值。我有时会用“尽职调查”这个词来指代这个阶段。这个词源自法律领域,但基本上意味着双重验证——验证一个AI解决方案在技术上是否真的可行、是否有价值,或者验证你希望成立的事情是否真的成立。

在验证了技术可行性和价值(或投资回报率ROI)之后,如果项目看起来仍然有希望,我们接着会细化项目的里程碑,并最终为项目预算资源


本节课中我们一起学习了确定机器学习项目范围的系统过程:从识别核心业务问题出发,通过头脑风暴探索多种AI解决方案,并强调将问题与方案分离思考的重要性。接着,我们看到了从发散思维到收敛思维的过渡,以及通过评估可行性与价值来筛选最具潜力的项目。这个过程旨在帮助团队避免盲目投入,而是将资源集中在能创造最大价值的项目上。

039:38_可行性和价值调查 📊

在本节课中,我们将学习如何对一个机器学习项目进行技术可行性和价值评估。我们将深入探讨如何通过尽职调查步骤,判断一个项目是否真正可行,以及其潜在价值有多大。

上一节我们介绍了项目评估的整体步骤,本节中我们来看看如何具体评估项目的技术可行性。

评估技术可行性

在启动一个机器学习项目之前,如何知道这个想法是否能够实现?

一种快速评估可行性的方法是使用外部基准。

例如,可以参考研究文献或其他形式的出版物。

或者,如果其他公司甚至竞争对手已经成功构建了某种类型的在线搜索系统、推荐系统或库存管理系统。

如果存在这样的外部基准,可能有助于你判断这个项目在技术上是否可行。

因为其他人已经成功完成了类似的事情。

为了补充这类外部基准,或者在缺乏此类基准的情况下,以下是评估可行性的其他方法。

我将构建一个2x2矩阵,根据你的问题是涉及非结构化数据(如语音、图像)还是结构化数据(如交易记录),以及是全新项目还是改进现有项目,来审视不同情况。

在另一个轴上,我将区分“全新”与“现有”。“全新”指你首次尝试构建一个系统来完成某项任务。

例如,如果你从未做过需求预测,现在正考虑构建一个。

而“现有”指你已经拥有一个执行此任务的现有系统(可能是机器学习系统,也可能不是),并且正在规划一个改进现有系统的项目。

因此,“全新”意味着你正在交付一个全新的能力,“现有”意味着你正在规划一个项目来改进现有能力。

在左上象限(非结构化数据,全新项目),要判断一个项目在技术上是否可行,我发现人类水平性能(HLP)对于给出初步判断非常有用。

在评估HLP时,我会给人类提供与学习算法相同的数据,然后询问:人类在给定相同数据的情况下,能否执行某项任务?

例如,人类在给定一张有划痕的智能手机图片时,能否可靠地检测出划痕?

如果人类能做到,那么这大大增加了机器学习算法也能做到的可能性。

对于现有项目,我也会将HLP作为参考。

如果你有一个视觉缺陷检测系统,并希望将其性能提升到某个水平,而人类能够达到你希望达到的水平,那么这可能让你更有信心认为它在技术上是可行的。

反之,如果你希望将性能提升到远超过人类水平,则表明该项目可能更困难或不可能实现。

除了HLP,我还经常使用项目的历史进展作为未来进展的预测指标。

我们将在接下来的几张幻灯片中详细讨论HLP和项目历史。

但项目过去的进展速度,可以合理地预测其未来的进展速度。我们将在本视频后面看到更多相关内容。

移动到右侧列(结构化数据,全新项目),我会问的问题是:我们是否有可用的预测性特征?

你是否有理由认为你所拥有的数据,即输入X,能够强有力地或足够地预测目标输出y?

在右下象限(结构化数据,现有项目),如果你试图改进一个现有系统,那么一件事会非常有帮助:你是否能识别出新的预测性特征?

也就是说,是否存在你尚未使用、但可以识别出来并能真正帮助预测y的特征?

同时,通过审视项目的历史进展。

在这张幻灯片中,你听到了三个概念:人类水平性能、预测性特征是否可用以及项目历史。让我们更深入地看看这三个概念。

深入探讨可行性评估概念

让我们从在非结构化数据(如图像)上使用HLP开始。

我使用HLP来基准化非结构化数据任务可能实现的目标,因为人类在非结构化数据任务上非常出色。

因此,评估项目可行性的关键标准是:人类在仅获得与学习算法完全相同的数据时,能否执行该任务?

让我们看一个例子。假设你正在构建一辆自动驾驶汽车,并且希望算法能分类交通灯当前是红色、黄色还是绿色。

我会从你的自动驾驶汽车上获取图片,然后让一个人看像这样的图像,看看仅凭图像,一个人能否分辨出哪个灯是亮的。在这个例子中,很明显是绿灯。

但如果你发现你也有像这样的图片,那么,在这个例子中,我无法分辨哪个灯是亮的。

这就是为什么对于这个HLP基准测试来说,确保人类只获得与你的学习算法相同的数据非常重要。

事实证明,也许一个坐在车里亲眼看到交通灯的人可以告诉你右边这个例子中哪个灯是亮的。

但那是因为人眼比大多数数码相机具有更好的对比度。

然而,有用的测试不是人眼能否识别哪个灯是亮的,有用的测试是如果这个人坐在办公室里,只能看到相机拍摄的图像,他们是否仍然能完成这个任务。

这能让你更好地判断可行性。

具体来说,它帮助你更好地猜测一个学习算法(它只能访问这张图像)是否也能准确检测出交通灯中哪个灯是亮的。

确保人类看到的与学习算法将看到的数据完全相同,这一点非常重要。

我见过很多项目,团队长时间致力于一个计算机视觉系统,他们认为可以做到,因为人类亲自检查手机或某物时可以检测到缺陷。

但花了很长时间才意识到,即使是人类只看图像也无法弄清楚发生了什么。

这样,你就可以更早地发现,以当前的相机设置,这根本不可行。更有效的做法是早期投资于更好的相机或更好的照明设置等,而不是继续在一个我认为在当时可用的成像设置下无法解决的问题上研究机器学习算法。

接下来,对于结构化数据问题,评估技术可行性的关键标准之一是:我们是否有看起来可以预测我们试图预测的Y的输入特征X?

让我们看几个例子。

在我们的电商例子中,如果你有显示用户过去购买记录的特征,并且你想预测未来的购买行为,这对我来说似乎是合理的,因为大多数人的过去购买记录可以预测未来的购买。

因此,如果你有过去的购买数据,你确实拥有似乎可以预测未来购买的特征,这个项目可能值得尝试。

或者,如果你在一家实体店工作,给定天气数据,如果你想预测购物中心的人流量(即有多少人会去商场),我们知道下雨时出门的人会少得多,所以天气可以预测购物中心的人流量。因此,我会说你有值得尝试的预测性特征。

让我们看更多的例子。

给定一个人的DNA,尝试预测这个人是否会患心脏病。这个我不确定。

从你的DNA到你是否会患心脏病,在生物学中是一个非常嘈杂的映射,这被称为基因型和表型。

但从基因型到表型,或者说从你的遗传信息到你的健康状况,是一个非常嘈杂的映射。

所以我对这个项目持复杂态度,因为事实证明,你的基因序列对是否会患心脏病只有轻微或中度的预测性。我会在那里放一个问号。

或者,给定社交媒体上的讨论,你能预测一种服装风格的需求吗?这是另一个例子。

我认为你可能能够预测当前服装风格的需求,但给定社交媒体上的讨论,你能预测六个月后流行的时尚趋势吗?这实际上似乎非常困难。

我见过人工智能项目失败的一种情况是,有这样一个想法:让我们使用社交媒体来了解人们在时尚方面谈论什么,然后制造服装并在六个月后销售。

有时数据就是没有那么强的预测性,最终你得到的只是一个比随机猜测好不了多少的学习算法。

这就是为什么审视你是否拥有你认为具有预测性的特征,是评估项目技术可行性的一个重要尽职调查步骤。

最后一个可能更清晰的例子:给定某只股票或特定股价的历史记录,尝试预测该股票的未来价格。

我所看到的所有证据表明,除非你获得其他一些巧妙的特征集,否则这是不可行的。

仅凭单一股票的历史价格来预测其未来价格是极其困难的。

根据我所看到的证据,我会说,如果这些是你仅有的特征,那么这些特征并不能预测该股票的未来价格。

因此,即使抛开预测股价进行交易能创造多少社会价值的问题,我有时认为这个项目在技术上也是不可行的。

最后,在这个图表中,我提到过几次的最后一个标准是项目的历史。让我们来看看这个。

当我从事一个机器学习应用项目许多个月后,我发现之前的改进速度可能是预测未来改进速度的一个令人惊讶的好指标。

以下是一个你可以使用的简单模型。

以语音识别为例。

假设这是人类水平性能,我将使用人类水平性能作为我们对基础误差或我们希望达到的不可减少的误差水平的估计。

假设在项目开始时,比如某年的第一季度(Q1),系统的错误率是10%。

随着时间的推移,在随后的季度中,错误率下降,像这样:Q2,Q3,Q4,等等。

事实证明,估计这条曲线的一个不算太差的模型是:如果你想估计团队未来能做得如何,我使用过的一个简单模型是,估计进展速度为:每段固定时间(比如每个季度),团队将相对于人类水平性能,将错误率降低某个百分比。

在这种情况下,当前性能水平与人类水平性能之间的差距似乎每个季度缩小了大约30%。

这就是为什么你得到这条向HLP呈指数衰减的曲线。

通过估计这个进展速度,你可以预测未来,希望在未来的季度中,你继续相对于HLP将错误率降低30%。

这将让你了解这个项目未来可能的合理进展速度,并让你对一个已有此类历史、可以尝试推断未来的现有项目,什么是可行的有一个概念。

在本视频中,你看到了如何使用人类水平性能、预测性特征是否可用以及项目历史来评估技术可行性。

下一节,让我们更深入地探讨如何评估项目的价值,我们将在下一个视频中进行。

040:如何评估机器学习项目的价值 💰

在本节课中,我们将学习如何评估一个机器学习项目的价值。这并非易事,但我们将分享一些最佳实践,帮助你从技术指标和商业目标两个维度进行综合考量。


从技术指标到商业价值

上一节我们介绍了项目评估的重要性,本节中我们来看看如何将机器学习团队的技术指标与业务团队关心的商业价值联系起来。

以语音识别为例。假设你正在为智能手机应用开发一个更精准的语音搜索系统,允许用户通过语音进行网络搜索。

在大多数企业中,通常存在两类指标:

  • 机器学习工程师习惯优化的技术指标。
  • 产品或业务负责人希望最大化的商业指标。

这两者之间往往存在差距。


指标间的差距与妥协

构建机器学习系统时,学习算法优化的目标可能是词级准确率。例如,用户说了一定数量的词,我们正确识别了多少个。学习算法可能通过梯度下降来优化对数似然或其他标准。许多机器学习团队会致力于获得良好的词级准确率。

但在商业应用场景中,另一个关键指标是查询级准确率,即用户整个查询语句被完全正确识别的频率。对某些业务而言,词级准确率固然重要,但查询级准确率可能更为关键。

至此,我们已经离学习算法直接优化的目标(词级准确率)远了一步。

即使用户查询被正确识别,这对用户体验很重要,但用户更关心的是搜索结果的质量。业务方希望确保搜索结果质量,因为这能提供更好的用户体验,从而提高用户参与度,使用户更频繁地使用搜索引擎。这很重要,但这只是最终驱动业务收入的其中一步。

我经常看到机器学习团队和业务团队之间存在这样的差距:工程团队通常希望专注于技术指标(如词级准确率),而业务领导者则希望得到关于商业结果(如收入)的承诺。

为了让项目顺利进行,我通常尝试让技术团队和业务团队就双方都能接受的指标达成一致。这往往需要一些妥协:机器学习团队可能需要更多地向右(商业指标)靠拢,而业务团队则需要更多地向左(技术指标)靠拢。我们越向右靠拢,机器学习团队就越难给出确切的保证。

我希望更多问题可以通过梯度下降或优化测试集准确率来解决,但现实并非如此。许多实际问题需要我们做的不仅仅是优化测试集准确率。因此,技术团队和业务团队都稍微走出各自的舒适区,对于达成妥协、选取一套双方都能接受的指标至关重要。这套指标需要技术团队觉得通过努力可以实现,而业务团队也相信它能创造足够的商业价值。


建立粗略的关联估算

另一个有用的实践是,进行粗略的“信封背面”计算,将技术指标与右侧的商业指标关联起来。

例如,如果词级准确率提高1%,你可以大致估算这会使查询级准确率提高多少(也许是0.7%或0.8%),进而会如何改善搜索结果质量、用户参与度,甚至最终影响收入。

即使是非常粗略的估算(有时也称为费米估算,你可以在维基百科上了解更多),也能帮助弥合机器学习工程指标和商业指标之间的鸿沟。


项目价值的伦理考量

在评估项目价值时,我鼓励你也思考任何伦理方面的考量。例如:

  • 这个项目是否创造了净正面的社会价值?如果没有,我希望你不要做。
  • 这个项目是否相对公平且没有偏见
  • 任何基于伦理或价值观的担忧是否已被公开提出和讨论?

我发现价值观和伦理问题高度依赖于具体领域,在贷款、医疗保健和在线产品推荐等不同场景下差异很大。

因此,我鼓励你查找为你的行业和应用场景制定的任何伦理框架。如果你有任何担忧,请在团队内部提出来进行辩论。

最终,如果你认为你正在做的项目不能帮助他人或推动人类进步,我希望你能继续寻找其他更有意义的项目。

在我的工作中,我曾面临艰难的选择,当时我真的不确定是否应该参与某个特定项目,因为我不知道它是否会让人们的生活变得更好。我发现,让团队公开辩论和讨论,通常能帮助我们找到更好的答案,并对最终做出的决定感到更安心。我曾基于伦理考量终止了多个项目,尽管它们在经济上完全可行,但我认为它们不能真正帮助人们。我只是告诉团队我不想做,也不会做。


总结与展望

本节课中,我们一起学习了如何评估机器学习项目的价值。我们探讨了技术指标与商业目标之间的差距,以及通过妥协和粗略估算来弥合这一差距的方法。更重要的是,我们强调了在项目评估中纳入伦理考量的必要性,确保我们所从事的工作能够创造净正面的社会价值,帮助他人,并推动人类进步。

我希望这能为你提供一个评估项目价值的框架。在伦理和价值方面,我认为我们所有人都应该只从事那些能创造净正面社会价值、帮助他人、推动人类进步的项目。我个人曾仅基于这个理由终止过多个项目,尽管它们的经济价值完全合理,但我审视后认为它们并不能真正帮助人们。我因此终止了项目,并告诉我的团队让我们找点别的事情做,因为我不想做那些事。我希望你也能将精力集中在那些帮助他人、推动人类进步的项目上。

041:里程碑与资源分配 🎯

在本节课中,我们将学习项目范围界定流程的最后两个关键步骤:确定里程碑资源分配。这两个步骤旨在将项目构想转化为具体、可执行的计划。

上一节我们讨论了技术可行性与价值评估,本节中我们来看看如何将评估结果转化为清晰的项目路线图。

确定里程碑与资源

确定里程碑与资源分配,涉及为你的项目撰写关键的技术规格说明。

这些规格说明通常包括:

  • 机器学习指标:例如,对于分类任务,你可能需要关注准确率精确率与召回率。在某些应用中,还可能包括公平性相关的指标。
  • 软件系统指标:考虑到可用的计算资源,你需要定义软件层面的要求,例如延迟吞吐量每秒查询数
  • 业务指标:如果可能,还应预估项目希望推动的业务指标,例如增量收入的估算。

以下是撰写规格说明时需要考虑的核心方面:

  • 所需资源:明确项目需要哪些资源。
  • 数据来源:需要多少数据,以及从哪些团队获取。
  • 人员配置:需要哪些人员,以及需要跨职能团队提供何种帮助。
  • 软件与集成:需要哪些软件集成。
  • 外部支持:是否需要数据标注支持或其他团队的支持。
  • 时间线:希望在何时达成特定的里程碑或交付成果。

应对不确定性:基准测试与概念验证

如果你在定义上述关键规格时遇到困难,可以考虑以下两种方法:

  1. 进行基准测试:与其他类似项目进行比较,了解行业或团队内的可行标准。
  2. 构建概念验证:首先构建一个POC,以更准确地评估可实现的准确率、延迟、吞吐量等指标。

只有在完成概念验证后,你才能更自信地为项目的大规模执行规划里程碑和所需资源。

总结

本节课中,我们一起学习了项目范围界定流程的收尾工作。我们探讨了如何通过定义机器学习指标软件指标业务指标来确立项目里程碑,并详细规划了所需的数据人员时间线等资源。当面临不确定性时,进行基准测试或构建概念验证是有效的应对策略。

恭喜你完成了整个项目范围界定部分的学习。希望这些思路能帮助你选择有价值、有意义的项目进行工作。感谢你从部署、建模、训练一直追溯到范围界定的全程陪伴,希望这个完整的机器学习项目周期框架,能对你未来构建和部署的所有项目有所助益。

042:专项课程概述 🎯

在本节课中,我们将要学习《机器学习工程师的生产实践(MLOps)》专项课程的整体介绍。我们将了解从开发一个模型到将其部署到生产环境所需的全套技能和挑战,并认识本课程的教学团队。


假设你已经在Jupyter笔记本中训练了一个准确的机器学习模型,并为此感到高兴。你现在可能在想,接下来该做什么?

在开发出一个好模型这一里程碑之后,实际上将你的模型投入生产,构建一个能够持续做出有用预测的工作系统,仍然需要做很多工作。

本专项课程将教你构建和部署生产级机器学习系统所需的技能。你将学习完整的机器学习项目生命周期,从项目规划、数据处理、建模到部署,从而真正从头到尾执行一个机器学习项目。

一个常见的误解是,在本地机器的Jupyter笔记本中开发模型与将该模型部署到生产环境之间的唯一区别,仅仅在于部署环节本身,可能只是一些软件工程工作。但事实并非如此,这不仅仅是软件工程问题,生产环境也面临机器学习特有的挑战,这些挑战在Jupyter笔记本开发模型的过程中并不突出。构建和维护生产系统的这门学科,即执行所有这些工作的流程和工具,有时被称为MLOps(机器学习运维),你也将学习这方面的知识。

我很高兴能与来自Google TensorFlow团队的两位杰出讲师——Robert Crowe和Laurence Moroney——共同为大家带来这个新的专项课程。

Robert Crowe是Google的TensorFlow开发工程师、数据科学家和TensorFlow布道师。他热衷于帮助开发者快速学习他们需要掌握的知识,希望这正是你所需要的。Laurence Moroney在Google领导AI布道工作,同时也是DeepLearning.AI与TensorFlow合作的其他三门专项课程的讲师,并著有《AI and Machine Learning for Coders》一书。非常高兴你们两位能加入本专项课程的教学团队。

正如Andrew所说,除了在生产系统中构建第一个可工作的模型,你还需要处理一系列问题,包括数据漂移——你训练所用的数据分布最终可能会变得与模型进行推理时所面对的数据分布非常不同。我们将讨论的一个关键主题是“变化”。世界在变化,你的模型需要意识到这种变化。

在本专项课程中,我们还将向你介绍机器学习之外的几个相关主题。你可以将生产机器学习视为机器学习本身与现代软件开发所需知识和技能的结合。如果你在工业界的机器学习团队工作,你确实需要同时具备机器学习和软件方面的专业知识才能成功。这是因为你的团队不仅仅是产出一个单一的结果,你将开发一个持续运行的产品或服务,它可能是公司工作中至关重要的一部分。

根据我自己的经验,构建机器学习系统最具挑战性的方面,往往是那些你最意想不到的事情,比如部署。能够构建一个模型固然很好,但将其交到用户手中并观察他们如何使用它,可能会让你大开眼界。你可能认为自己拥有针对完美场景的完美模型,但你的用户可能有不同的看法,向他们学习总是非常有益的。例如,他们可能可以接受频繁更新的模型需要往返服务器,或者他们可能坚持要求他们的数据永不离开设备,因此你需要知道保持他们设备上模型新鲜度的最佳方法。

本专项课程包含四门课程,为你提供启动和运行生产机器学习系统所需的知识和实践经验。

以下是四门课程的简要介绍:

  • 第一门课程:由我(Andrew)讲授,你将看到生产机器学习项目从规划、获取数据、建模到部署的整个生命周期的概述。
  • 第二门课程:专注于数据及其随时间的变化。在这门课程中,你将使用TensorFlow Extended(TFX)及其系列库,通过收集、清理和验证数据集来构建数据管道。为了理解数据演变,你将使用数据溯源作为概念框架,通过ML元数据来追踪变化。
  • 第三门课程:聚焦于生产环境中的机器学习建模流水线。在这门课程中,你将学习如何管理建模资源,以最佳方式服务推理请求并最小化成本。你还将使用分析工具来解决模型公平性和可解释性问题,并缓解瓶颈。
  • 第四门课程:全部关于部署。这意味着你需要准备好服务用户的请求。这既令人兴奋又充满挑战。因此,在第四门课程中,你将构建部署流水线,用于可能需要多种不同基础设施的模型服务。你还将应用最佳实践来维护一个持续运行的生产系统,使其保持最新状态,并且重要的是,始终将用户的需求放在首位。

作为本专项课程的学习者,我们假设你熟悉Python编程和机器学习,并对Python中的一种深度学习框架(如TensorFlow、Keras或PyTorch)有一定了解。如果你已经完成了DeepLearning.AI提供的深度学习专项课程,那么你将非常适合开始学习本专项课程。当然,如果你完成了DeepLearning.AI的TensorFlow开发者专业课程,你将为本专项课程的学习做好更充分的准备。


本节课中,我们一起学习了《机器学习工程师的生产实践(MLOps)》专项课程的目标和结构。我们了解到,将模型投入生产远不止于部署,它涉及数据管理、模型维护、系统部署和持续监控等一系列挑战(MLOps)。本课程由四位专家共同设计,包含四门循序渐进的课程,旨在帮助具备一定机器学习基础的开发者掌握构建和维护生产级机器学习系统所需的完整技能栈。

043:生产环境机器学习概述 🚀

在本节课中,我们将要学习生产环境机器学习的基本概念,并探讨它与学术研究环境中的机器学习有何不同。我们将了解构建和维护生产级机器学习系统所需的关键组件和挑战。


上一节我们介绍了课程主题,本节中我们来看看什么是生产环境机器学习。

生产环境机器学习可以看作是机器学习开发与现代软件开发实践的结合。它不仅关注模型本身,还涉及整个系统的设计、部署、监控和维护。


学术研究环境与生产环境的对比

在学术或研究环境中,建模过程通常较为直接。你通常会获得一个标准数据集,该数据集已经过清洗和标注,然后你用它来训练模型并评估结果。最终目标是获得一个预测性能良好的模型。

然而,生产环境机器学习的要求远不止一个模型。

我们发现,模型代码通常只占将机器学习应用投入生产所需总代码量的约 5%。下图展示了生产ML系统的其他关键组成部分:

从根本上说,我们讨论的不仅是机器学习和建模,更是生产级机器学习应用,以及创建、部署、维护和改进它们所需的一切,以便为你的用户、企业或组织提供服务。


以下是学术研究ML与生产ML的一些核心区别:

  • 数据:学术研究通常使用静态数据集;生产ML使用动态且不断变化的真实世界数据。
  • 设计优先级:学术研究追求在整个训练集上的最高准确率;生产ML则需平衡快速推理、良好的可解释性准确率成本
  • 模型训练:学术研究基于单一最优结果进行调优;生产ML需要持续监控、评估和再训练
  • 可解释性与公平性:这对所有ML建模都很重要,但对生产ML绝对至关重要
  • 主要挑战:学术研究的主要挑战是找到高精度模型;生产ML的挑战是“模型加上整个系统的一切”。


生产ML的双重属性

因此,可以公平地说,生产环境机器学习既是机器学习本身,也需要现代软件开发的知识和技能集。要取得成功,需要在这两个领域都具备专业知识,因为你不仅仅是在产出单一结果,而是在开发一个产品或服务,它通常是你业务中关键任务的一部分。


上一节我们了解了生产ML的复合属性,本节中我们分别看看这两个方面。

机器学习开发本身关注与数据和预测质量相关的具体问题。例如,在监督学习中,你需要确保:

  • 标签准确。
  • 训练数据覆盖的特征空间与模型将接收的请求一致。
  • 在保留或增强数据中预测信息的同时,降低特征向量的维度以优化系统性能。
  • 在整个过程中,需要考虑并衡量数据和模型的公平性,特别是对于罕见但重要的情况(例如在医疗保健领域)。


但除此之外,你还需要将软件投入生产。这需要一个系统设计,包含任何生产软件部署所需的所有要素。当然,这个部署必须专注于ML和你的应用。

以下是需要考虑的软件工程原则:

  • 系统是否可扩展(能否向上和向下扩展)?
  • 能否清晰地扩展以添加新功能?
  • 是否有清晰、定义明确的配置
  • 是否一致且能可靠地复现结果
  • 是否加固以抵御攻击?
  • 设计是否模块化,遵循现代软件开发原则?
  • 能否进行单元测试端到端测试
  • 能否持续监控系统的健康状况和性能,并在出现问题时收到警报?
  • 是否采用了行业最佳实践

机器学习生产流程

在现实世界应用中使用模型,需要的远不止理解机器学习算法。

以下是构建生产ML系统的主要步骤:

  1. 项目范围确定:定义项目需求、目标以及实现它们所需的资源。
  2. 数据处理:定义将要使用的特征,并组织和标注数据。有时可能需要测量人类水平表现以设定比较基线。
  3. 模型设计与训练:在此阶段,误差分析将帮助你优化模型以适应项目需求。
  4. 模型部署:部署模型以服务预测请求。部署目标可以是移动设备、云端、物联网设备甚至网页浏览器。
  5. 持续监控与维护:随着时间的推移,真实世界数据不断变化,可能导致模型性能下降。因此需要持续监控模型性能。如果检测到性能下降,则需要返回进行模型再训练和调优,或修订数据。

在部署期间,新数据可能会对项目设计产生积极或消极的影响,可能需要进行重新范围确定

最终,所有这些步骤共同构成了你的生产ML系统。这个系统需要自动运行,以便你能够持续监控模型性能、获取新数据、根据需要重新训练,然后重新部署以维持或提升性能。


核心挑战与总结

本节课中我们一起学习了生产环境机器学习与学术研究环境的关键区别。

进行生产ML所面临的挑战与学术研究ML非常不同。在某种意义上,挑战是相同的,但包含了更多内容。你将构建一个专注于ML用例的集成系统。你需要考虑在生产中持续运行它,对于在线用例,这意味着它必须保持 24/7 可用。你必须考虑并建立系统来处理不断变化的世界和数据。当然,与任何生产系统一样,你需要在最低成本下尝试完成所有这些,同时产生最佳性能

这看起来可能令人生畏,但好消息是,对于完成所有这些工作,已有成熟的工具和方法论,你将在本课程中学到很多。


总结:生产环境机器学习是一个结合了机器学习技术与软件工程实践的综合性领域。它要求从业者不仅关注模型精度,还要统筹考虑数据动态性、系统可扩展性、部署可靠性、持续监控和成本效益,以构建和维护能够持续创造价值的实时应用系统。

044:机器学习流水线 🚀

在本节课中,我们将学习机器学习流水线的核心概念。我们将介绍什么是机器学习流水线,它在MLOps架构中的角色,以及如何使用流水线编排器来自动化机器学习工作流程。最后,我们将以TensorFlow Extended(TFX)为例,了解一个广泛应用的机器学习流水线框架的具体构成。


机器学习流水线是任何生产级机器学习系统的核心。它指的是一种软件架构,旨在自动化、监控和维护从数据到训练模型的整个机器学习工作流程。

上一节我们回顾了迭代式的机器学习工作流程,本节中我们来看看如何通过流水线架构来具体实现它。

机器学习流水线构成了MLOps架构的关键组成部分。下图展示了由行业组织CDF基金会提出的一个流水线架构示例。


不同的流水线架构可能存在一些差异,但总体上它们都与此类似。你会注意到,它们基本上反映了机器学习开发过程,从数据摄取开始,到训练出模型结束。这是有意设计的,因为它们需要封装并规范化这个过程。


机器学习流水线几乎总是有向无环图,尽管在一些高级用例中,它们有时可能包含循环。

DAG(有向无环图)是所有你想要运行的任务的集合,这些任务按照反映它们之间关系和依赖性的方式排序。请注意,在这个图中,边是有方向的,并且没有循环。这使得这个图成为一个DAG。


流水线编排器负责根据DAG定义的依赖关系,调度机器学习流水线中的各个组件。编排器有助于实现流水线自动化。

以下是编排器的例子:

  • Argo
  • Airflow
  • Celery
  • Luigi
  • Kubeflow

现在,让我们来看一个具体的机器学习流水线框架示例:TensorFlow Extended(TFX)。

TFX是一个开源的全栈机器学习平台,也是我们在谷歌内部使用的平台。一个TFX流水线是一系列可扩展的组件序列,能够处理海量数据。

从左侧开始,我们摄取数据,然后进行数据验证和特征工程,接着训练模型并验证它。如果它优于我们生产环境中已有的模型,我们就会将其推送到生产环境,最后用于提供预测服务。这个组件序列专为可扩展、高性能的机器学习任务而设计。

在本课程中,你将使用TFX来实现真实的机器学习流水线,就像为生产系统所做的那样。


TFX的生产组件建立在开源库之上,例如:

  • TensorFlow Data Validation(本周晚些时候会学习)
  • TensorFlow Transform(本课程后续会深入使用)
  • TensorFlow Model Analysis

下图中橙色的组件利用了这些库,并构成了你的DAG。当你对这些组件进行排序并设置它们之间的依赖关系时,你就创建了你的DAG,也就是你的机器学习流水线。


接下来,我们详细看看一个基础的TFX流水线结构,可以称之为TFX的“Hello World”。

我们从左侧的数据开始,使用名为 ExampleGen 的TFX组件来摄取数据。你在此处看到的所有橙色框都是TFX组件。实际上,这些是当你执行 pip install 安装TFX时自带的组件。

以下是各个组件的功能:

  • StatisticsGen:为数据生成统计信息,例如数值特征的范围、分类特征的有效类别等。
  • ExampleValidator:用于查找数据中的问题。
  • SchemaGen:为整个特征向量生成数据模式。
  • Transform:进行特征工程。
  • TunerTrainer:用于训练模型并调整其超参数。
  • Evaluator:对模型性能进行深入分析。
  • InfraValidator:确保我们可以在现有基础设施上实际使用模型运行预测(例如,内存是否足够)。
  • Pusher:如果模型通过所有验证,并且性能优于生产环境中的现有模型,则将其推送到生产环境。

“推送到生产环境”意味着什么?它可能意味着:

  • 推送到像 TensorFlow Hub 这样的存储库,用于后续的迁移学习或生成嵌入。
  • 推送到 TensorFlow.js,用于Web浏览器或Node.js应用。
  • 推送到 TensorFlow Lite,用于移动应用或物联网设备。
  • 推送到 TensorFlow Serving,用于服务器或服务集群。

本节课中我们一起学习了机器学习流水线的核心要点。首先,生产级机器学习流水线不仅仅是机器学习代码,它结合了机器学习开发、软件开发,并以一种可维护和可扩展的方式,规范化了运行这一系列任务的流程。

其次,TFX是一个开源的全栈机器学习平台,我们将在本课程中使用它。

045:4_数据的重要性 📊

在本节课中,我们将要学习机器学习项目中数据的重要性,以及如何在实际生产环境中收集和管理数据。数据是机器学习系统的基石,其质量直接决定了模型的成败。


上一节我们介绍了机器学习项目的整体流程,本节中我们来看看数据这一核心要素。

数据收集的现实挑战

首先,让我分享一个我曾参与的应用案例。我们被要求创建一个模型,用于预测在不同日期、不同时间、不同队伍长度下,通过机场安检点所需的时间。为此,我们需要数据。

我们如何获取这些数据呢?我们必须测量人们通过安检点所需的时间。具体方法是:我们派人前往机场,并获得安全部门的许可。一人在安检队伍起点记录某人进入的时间,另一人在安检出口记录该人离开的时间。两人距离很远,甚至无法看到彼此。通过这种方式,我们逐步构建了一个带有标签的数据集,记录了人们通过安检所需的时间。

可以想象,这个过程极其繁琐且昂贵。我们必须开发应用程序来支持数据收集,并支付人员费用,他们还需要通过安全审查。这个例子说明,在生产环境中收集数据通常需要创造性的方法,并且可能成本高昂。除非你非常幸运,已经有人为你准备好了数据。

数据与数据质量的重要性

你的模型质量将完全取决于你的数据质量。如果数据中存在大量噪声,尤其是标签噪声,你必须设法清理这些信号。

我们将几乎完全使用数据管道,因为我们需要自动化这些流程。在管道中,数据收集、摄取和准备将作为一系列自动化任务进行。我们还需要监控数据收集过程,因为对于大多数应用而言,数据收集不是一次性的,而是贯穿应用整个生命周期的持续活动。

正如我们所见,数据是机器学习中最困难也是最重要的一环。优步(Uber)曾指出:“损坏的数据是生产机器学习系统中最常见的问题根源。”GoJk 等公司也有类似看法。几乎任何生产机器学习团队都会告诉你数据收集的故事,以及确保数据正确的重要性。

在编程语言设计中,“一等公民”指的是支持该语言中所有通用操作的实体。在机器学习中,数据就是一等公民

  • 软件 1.0 的核心是代码,即给计算机的指令。
  • 软件 2.0 则需要我们指定程序行为的目标。代码虽然重要,但已不是我们唯一关心的事情。

优化是这里的驱动力,我们需要在多个方向上进行优化:性能、可维护性和可扩展性。对于机器学习而言,数据和数据质量对成功至关重要。在某种程度上,数据在机器学习应用中的角色,类似于代码在传统软件应用中的角色。

模型并非魔法。你可能拥有海量数据,但如果这些数据没有预测性内容,你将无法用它构建出有效的预测模型。因此,你需要从模型中移除那些没有预测性的信息和特征,因为它们不仅会引发问题,还会浪费宝贵的计算资源。

在监督学习甚至无监督学习中,你必须确保训练数据所覆盖的特征空间,与模型投入生产后收到的预测请求所覆盖的特征空间是一致的。你的模型需要在该空间的所有区域都有良好的信息来进行预测。正如常言道:垃圾进,垃圾出。如果你的数据质量低下,你的模型和应用质量也会低下。

机器学习的一个好消息是,我们可以相对容易地衡量解决方案的好坏。而在许多传统软件应用中,这可能不那么直接。因此,数据收集是构建机器学习系统关键且重要的第一步

构建稳健机器学习系统的考量

为了避免系统停机等问题,你需要确保训练的模型是可扩展的,能够服务于预测请求。特别是对于时间序列数据,你需要考虑季节性和趋势等因素。你需要思考不同类型的错误,我们将在后续课程中详细讨论。

在开发过程中,你需要在脑海中构建一个完整的图景:这是一个从数据摄取到模型服务的全过程。所有环节都必须实现自动化、可测试、可维护和可扩展。

你需要理解你的用户,并确保将用户需求转化为数据问题。你不能仅仅使用手头现成的模型,如果它不符合用户需求的话。

你需要确保你的数据覆盖的特征空间区域与未来预测请求的一致。你需要最大化数据中的预测信号。你不仅需要在项目开始时关注数据质量,更要在应用的整个生命周期中持续关注。这包括确保数据来源可靠,并考虑偏见和公平性等问题,我们将在本课程后续部分进行讨论。


本节课中我们一起学习了数据在机器学习项目中的核心地位。我们探讨了在生产环境中收集数据可能面临的现实挑战,理解了数据质量如何直接决定模型性能,并认识到数据应被视为机器学习系统中的“一等公民”。最后,我们概述了构建一个稳健、可维护的机器学习系统时,围绕数据需要进行的全盘考量。记住,优质的模型始于优质的数据。

046:5_建议运行的应用示例 🏃‍♂️📱

在本节课中,我们将学习如何为一个“跑步建议”应用收集和准备数据。我们将通过一个具体示例,探讨从理解用户需求到定义数据特征和标签的完整过程。


理解用户与应用目标

上一节我们讨论了数据收集的重要性,本节中我们来看看一个具体的应用示例。

我们正在构建一个为跑步者推荐跑步路线的应用。用户是不同健康水平的跑步者。系统的目标是通过分析用户行为和偏好模式来推荐跑步路线,从而提高用户跑步的规律性、完成率与满意度。

将用户需求转化为数据需求

理解用户是第一步,但最终我们需要将其转化为具体的数据和特征需求,否则可能收集到无用的数据。

我们需要明确:数据是什么?特征是什么?标签是什么?

以下是一个示例数据集,包含三种不同类型的跑步活动及其特征:

跑步活动示例 跑步者用时 海拔变化 趣味性评分(标签)
波士顿马拉松 3小时30分 200英尺 7
西雅图十月节5K 28分钟 50英尺 9
休斯顿半程马拉松 1小时45分 100英尺 6

在这个例子中,特征包括跑步活动本身跑步者用时海拔变化。标签是跑步者对这次跑步趣味性的评分

了解你的数据源

你需要确定数据来源,不仅用于首次训练,还要考虑持续推断时的数据收集。你需要思考:

  • 训练数据需要多久更新一次?
  • 数据是否具有预测价值?需要剔除无预测价值的特征。
  • 数据是否一致?例如,预期为浮点数的字段是否总是浮点数?
  • 是否存在异常值或错误?例如,传感器故障可能导致错误数据。
  • 缺失值如何编码?例如,海拔数据为0英尺,是代表海平面还是数据缺失?
  • 如果特征来自其他ML模型(如集成模型),其中的错误会在下游模型中被放大。

你需要在流程早期发现错误和问题,并监控数据源的系统问题和中断。例如,如果应用离线一段时间,记录的跑步者时间出错,你是否有办法处理?

评估数据有效性并优化特征

你需要对数据价值有直觉,但直觉可能具有误导性。因此,必须通过分析来确定哪些数据真正提供了最多信息。

特征工程和特征选择对于塑造数据至关重要:

  • 特征工程:在确定预测信号所在后,帮助你最大化这些信号。
  • 特征选择:帮助你衡量预测信息的位置,并专注于那些能提供最大价值、对模型帮助最大的特征。

定义特征与标签

再次强调,你需要理解用户和应用。在本例中,我们可以从应用获取跑步数据,用户填写资料时获取人口统计数据,并通过GPS获取本地地理信息。

以下是如何将高层理解转化为具体特征和标签:

特征来源示例:

  • 跑步者人口统计:转化为一个或多个特征。
  • 跑步行为数据:一天中的跑步时间、完成跑步所需时长、跑步配速、距离、海拔变化等。
  • 传感器数据:如果应用连接了心率监测器等传感器,这些是极好的信息源,可能包含预测信息(但需验证)。

标签定义:

  • 跑步者接受度:用户是否采纳了我们的建议并执行了推荐跑步。这表示应用成功推荐了他们想进行的跑步。
  • 用户生成的反馈:需要以结构化方式获取,以便用于模型训练。例如,用户对推荐跑步的趣味性进行评分。反馈通常不能是自由文本(除非使用NLP技术处理),而应是可直接使用的形式。

关键要点总结

本节课中我们一起学习了为机器学习应用准备数据的关键步骤:

  1. 理解你的用户或应用:如果没有直接用户,则理解应用要解决的问题。
  2. 将需求转化为数据问题和特征:定义能提供预测信息的、明确的特征。
  3. 评估可用数据:你能获取什么数据?有哪些细节和问题?(例如传感器可靠性)
  4. 定位预测信息:数据中的预测信息可能不在你预期的地方。
  5. 正确定义标签:确保我们训练的模型是在预测正确的东西,标签需与目标一致。
  6. 关联到评估指标:确定用于衡量模型性能的指标。

通过以上步骤,你可以为构建一个有效的“跑步建议”系统打下坚实的数据基础。

047:负责任的数据、安全、隐私与公平 🔒⚖️

在本节课中,我们将学习如何负责任地收集和管理数据,重点关注数据安全、用户隐私以及确保机器学习系统的公平性。我们将探讨数据来源、偏见产生的原因以及如何设计标注系统来减轻偏见。


负责任地收集数据

上一节我们介绍了数据收集的重要性,本节中我们来看看如何确保数据收集过程是负责任的。收集数据的一个关键方面是确保以负责任的方式进行,并关注安全、隐私和公平性等问题。

我们将探讨如何负责任地获取数据源,确保数据安全,并正确管理用户隐私。我们还需要知道如何检查和确保公平性,并设计能够减轻偏见的标注系统。

以下是一个例子:

这些图片展示了一个标准的开源图像分类器,它在一个开放图像数据集上训练,但未能正确地将与婚礼相关的标签应用于来自世界不同地区的婚礼传统图片。

  • 最左边的图片,分类器的预测标签是“仪式、婚礼、新娘、男人、群体、女人、礼服”,这基本正确。
  • 下一张图片的标签是“新娘、仪式、婚礼、礼服、女人”,在西方文化中,这看起来也是正确的。
  • 再下一张图片的标签“仪式、新娘、婚礼、男人、女人、礼服”同样正确。
  • 但最右边的图片,描绘的是一个非洲婚礼仪式,却被错误地仅标记为“人”或“人们”。虽然图片中确实有人,但它也是一个仪式,并且包含新娘、新郎、礼服等元素。

这是一个经典案例,常被引用来说明数据集中存在的偏见问题。


数据来源与安全隐私

在机器学习系统中,数据可能来自不同来源。你需要考虑这些来源,而不仅仅是你拥有的数据本身,还要考虑你是从哪里获取的。

数据来源可能包括:

  • 构建合成数据
  • 进行网络爬取
  • 收集实时数据(尤其是在运行推理时)
  • 构建自己的数据集(最常见)
  • 使用开源数据集(取决于可用性和需求)

数据安全和隐私至关重要。数据安全指的是保护个人数据(通常称为PII,个人可识别信息)的策略、方法和手段。数据隐私则涉及对这些数据的正确使用、收集、保留、删除和存储。

数据收集不仅关乎你的模型,还需要考虑你的用户。你需要将数据视为托付给你保管的东西,并负责任地进行管理。用户应该能够控制哪些数据被收集,并且建立机制以防止系统无意中或因攻击而泄露用户数据至关重要。

你处理数据隐私和安全的方式取决于数据的性质、操作条件、法规和政策(如GDPR)等因素。


用户隐私保护

用户隐私同样关键,你需要保护个人可识别信息或数据。

以下是几种保护方式:

  • 数据聚合:如果能将数据聚合,使其无法识别其中的个体,这将大有帮助。
  • 匿名化:对数据进行匿名处理。
  • 用户控制:让用户控制他们分享哪些数据。
  • 遵守法规:考虑在你使用模型的地区可能影响用户隐私的任何法律或法规。
  • 数据删除:在许多情况下,你需要为用户提供删除部分数据的方式,这虽然会形成不完整的画像,但却是负责任处理数据的一部分。

机器学习系统的失败与公平性

机器学习系统可能以多种方式对用户造成损害,我们需要在公平、准确、透明和可解释性之间取得平衡。

机器学习系统可能失败的方式包括:

  • 代表性伤害:系统放大或反映对特定群体的负面刻板印象。
  • 机会剥夺:系统的预测产生负面的现实生活后果,可能导致持久影响。
  • 不成比例的产品失效:模型的有效性严重偏斜,导致对特定用户群体的输出(可以视为错误)更频繁地发生。
  • 劣势关联伤害:系统在不同人口特征和用户行为之间推断出不利的关联。

公平性非常重要,你应该从一开始就致力于实现它。


实现公平性

那么,公平意味着什么?公平意味着识别某些人群,或识别某些人群是否以有问题的方式获得与其他人群不同的体验。

例如,假设特定的性别、职业或年龄字段是你数据的一部分,并且你用它来训练一个预测某人是否会是可靠新员工的模型(涉及招聘)。你需要仔细检查,确保你的模型不会以有问题的方式持续为某些群体预测不同的体验,这需要通过确保群体公平性来实现。

这意味着要实现人口统计上的平等,使不同群体间的事物均衡化。你还需要确保准确性也尽可能相等或接近。

由人类收集和标注的数据在许多情况下会反映他们的偏见和个人经验,因此你必须考虑到这一点。多样化你的用户基础是迈向公平的好方法,但这并非保证。机器学习系统可能放大偏见,你需要意识到这一点并谨慎对待。你真正想做的是部署公平的模型。

当你的数据中某些群体的代表性不成比例或根本没有代表性时,也可能产生偏见。

观察这里的图示,我们试图展示的是,图中显示的部分人在你的数据中,但还有大量其他人不在其中。因此,那些不在你数据中的群体可能会被刻板印象化,或以不那么积极的方式呈现,或者他们可能更频繁地获得糟糕的体验。


减少监督学习中的偏见

为了减少监督学习中的偏见,你需要准确的标签来训练模型并进行预测。

标签通常来自两个广泛的来源(当然也有其他来源):

  • 自动化系统
  • 人类标注员

我们接下来会讨论两者。

人类能够以不同的方式标注数据,数据越复杂,你可能越需要专家来查看这些数据,我们稍后会讨论这一点。标注数据的人类被称为“标注员”。


标注员的类型

那么,标注员是谁?他们可能是:

  • 通才:这些是普通人,通过各种众包工具添加标签。适用于人们能相对容易识别正确标签的情况。例如,让人识别猫和狗的区别,大多数人看图片就能做到。
  • 主题专家或领域专家:在某些情况下,你真的需要一位主题专家。这时你通常使用专门的工具。一个例子是查看X光片进行诊断,这不是任何人都能做的,你需要确保与专家合作,这种标注往往成本很高。
  • 用户:我们之前为跑步应用程序看到的这种反馈,如果你能在应用程序中找到利用它的方法,通常非常有价值。如果你能让它发挥作用,它将为你提供持续的数据标签流。

关键要点

以下是关于负责任数据管理的几个关键要点:

  • 公平性与代表性:始终考虑数据集中标注员的公平性和数据的公平代表性,以避免潜在的偏见。考虑那些标注员是谁以及他们的动机是什么,因为如果你设计的激励机制不正确,你的数据中可能会充斥大量垃圾。
  • 成本考量:成本无疑总是一个重要的考虑因素。如果能找到一种以高质量但较低成本完成的方法,那很好。但你需要足够的数据,并找到实现这一目标的方法,这是生产应用面临的挑战之一。
  • 数据新鲜度:你将处理数据,根据应用程序周围世界的变化以及你拥有的数据,你需要定期刷新数据,并检测何时需要这样做。

这些都是你需要思考的问题,以便真正管理好数据收集,并以负责任的方式进行。


本节课中,我们一起学习了如何负责任地收集和管理数据,重点关注了数据安全、用户隐私和机器学习公平性的核心概念。我们探讨了数据来源、偏见产生的原因、不同类型的标注员以及确保数据质量和公平性的关键实践。记住,构建负责任的机器学习系统始于对数据的深思熟虑和谨慎管理。

048:模型性能退化案例研究 📉

在本节课中,我们将通过一个具体的案例研究,探讨机器学习模型在生产环境中性能退化的常见原因、影响以及应对策略。我们将学习如何识别和处理由数据变化、世界变化以及系统问题导致的模型性能下降。


概述

模型部署到生产环境后,其性能并非一成不变。现实世界是动态变化的,这些变化会直接影响模型的表现。本节课将通过一个在线零售商的案例,分析模型性能退化的具体场景、根本原因以及监控和缓解方法。

上一节我们介绍了模型部署后的监控概念,本节中我们来看看一个具体的性能退化案例。


案例背景:在线零售商的点击率预测模型

想象你是一家在线零售商,销售鞋子。你有一个用于预测商品点击率(CTR)的模型,该模型的预测结果帮助你决定订购多少库存。

突然,模型的评估指标(如AUC和预测准确率)出现了下降。值得注意的是,这种下降并非全局性的,而是集中体现在库存的某个特定部分——男士正装鞋

这就引出了几个关键问题:

  • 为什么模型在训练时表现良好,现在却对男士正装鞋的预测不准了?
  • 发生了什么变化?
  • 更重要的是,你如何能及早发现这个问题?模型仍在运行、仍在给出预测、你仍在根据预测订购库存。你如何知道你的订单决策和模型预测已经不如从前?

性能退化的后果与早期检测的重要性

如果不为生产环境建立良好的实践,你可能只有在订购了过多或过少的鞋子时才会发现问题。这在商业环境中是不可取的,会造成直接的经济损失。

因此,你需要思考:

  1. 如何早期检测此类问题。
  2. 问题的可能原因是什么,以便你能有针对性地监控系统。
  3. 建立应对机制和系统,以便在问题发生时进行处理(因为问题很可能会在某个时刻发生)。

性能退化问题的两大类别

性能退化问题通常可分为两大类,它们需要不同的监控和应对策略。

1. 缓慢发生的问题(渐变问题)

这类问题随着时间推移逐渐发生,通常与世界的变化相关。它们又可以细分为以下相互关联的几类:

以下是渐变问题的几种常见形式:

  • 趋势与季节性:尤其在时间序列数据中,趋势和季节性变化非常普遍。这可以看作是数据的变化,也是世界运行规律的变化。
  • 特征分布变化:输入模型的数据特征其统计分布会逐渐改变。
  • 特征重要性变化:不同特征对预测结果的相对重要性会发生改变。如果模型没有重新训练,其准确性就会开始衰减。

2. 突然发生的问题(剧变问题)

这类问题通常与系统本身直接相关,发生得很快。

以下是剧变问题的几种常见形式:

  • 数据收集问题:例如传感器或摄像头损坏;日志数据格式突然改变或轮转方式变化;传感器位置被移动而未被告知。
  • 系统问题:软件更新引入了未被察觉的重大变更;网络连接中断(尽管我们希望它永不中断);整个系统宕机。
  • 凭证问题:访问凭证过期或变更,导致数据流中断。

现实世界的变化对模型的影响

世界在不断变化,在生产环境中,这必须成为你系统设计和流程的一部分。理解这些变化有助于预判模型性能的衰退。

以下是世界变化影响模型的具体例子:

  • 风格与偏好变化:在零售业中,商品风格会变。例如,去年男士正装鞋流行黑色,今年可能流行棕色。
  • 流程与范围变化:业务流程或范围的变化会影响模型对结果的解读。
  • 竞争与业务变化:新产品的引入、旧产品的淘汰、新竞争对手的出现、业务地域的扩张或收缩。
  • 市场价格变化:供应商价格或公开市场价格波动。

所有这些都要求模型去适应世界。这种影响通常是领域特定的,但几乎在所有领域,世界的变化都会影响模型性能。


应对性能退化的关键考量

在设计和监控系统时,需要考虑以下几个核心点:

  1. 预测错误的成本不均等:并非所有的预测错误对业务的影响都一样大。有些错误影响甚微,有些则可能造成巨大损失。监控系统时,应重点关注那些可能产生较大影响的错误。
  2. 可用数据与理想数据的差距:你收集到的数据很少是你理想中希望拥有的完美数据。通常需要基于现有的、可能有噪声或不完整的数据进行工作。
    • 代码示例data = load_real_world_data() # 数据通常是嘈杂、不完整的
  3. 模型目标是真实目标的代理:在很多情况下,模型优化的目标(如点击率)只是你真正业务目标(如优化库存利润)的一个代理指标。
    • 公式描述:我们真正关心的是 最大化利润,但模型优化的是 点击率预测准确率,即 模型目标 ≈ f(真实目标)
  4. 部分客户体验不佳:总会有一定比例的客户获得不理想的体验(如收到不准确的推荐)。目标是尽可能降低这个比例,并尽可能理解哪些客户会受到影响,从而设计缓解方案。

总结

本节课中我们一起学习了机器学习模型在生产环境中性能退化的典型案例。核心要点在于:唯一不变的是变化本身

我们分析了性能退化如何通过渐变问题(如数据漂移、趋势变化)和剧变问题(如系统故障、数据源异常)两种形式出现。通过在线零售商的案例,我们认识到早期检测和持续监控的重要性,并理解了模型需要不断适应变化的现实世界。建立应对这些问题的系统和流程,是维持生产环境机器学习模型长期健康的关键。

049:生产环境中的数据与概念变更 📊

在本节课中,我们将学习如何检测生产环境中已部署机器学习模型的问题,重点关注数据变更概念变更。理解这些变更的类型及其应对策略,对于维护模型在生产环境中的性能至关重要。


模型问题检测概述

检测已部署模型的问题,可以从数据和现实世界范围等多个角度进行。其根本在于需要对模型进行持续监控,并验证模型的结果与数据,以便及时发现问题。我们尤其希望快速发现系统性问题,例如之前讨论过的传感器故障等。

然而,一个根本性问题是不断变化的真实情况。这意味着在应用程序的整个生命周期中,你需要持续标注新数据。具体采用何种方法可行,很大程度上取决于你所处的领域和试图解决的问题类型。


不同类型的问题与应对策略

以下是几种不同难度级别的问题及其应对方法。

简单问题:缓慢变化的真实情况

上一节我们介绍了问题检测的基本概念,本节中我们来看看第一种情况。这类问题的真实情况变化非常缓慢,例如识别猫狗图像。在这种情况下,模型重新训练通常由模型改进驱动,例如提升了识别猫狗的准确率。

此外,软件或系统的升级(如使用不同的库)也可能触发重新训练。对于此类问题,数据标注相对简单。

以下是可行的数据标注方法:

  • 使用现有数据集:可以利用来自公共领域或组织长期使用的精选数据集。
  • 众包标注:如果问题简单,这也是一种可行方式。
  • 用户反馈:如果能够获得用户反馈,应充分利用。

较难问题:快速变化的真实情况

接下来,我们探讨真实情况变化更快的场景。例如时尚风格(如鞋款),现实世界可能在数周内就会发生变化。在这种情况下,模型重新训练通常由模型性能下降驱动,因此你需要有能力测量这种下降。

当然,模型改进、获得更好数据以及软件系统变更也可能触发重新训练。随着问题难度增加,模型性能下降成为一个更关键的驱动因素。

对于此类问题的数据标注,以下是可行的方法:

  • 直接反馈:如果能够从系统或用户那里获得直接反馈,这是最佳选择。
  • 众包人工标注:由于你可能有数周的时间来响应,通过人工评审员进行标注是另一种可行的方法。

极难问题:急速变化的真实情况

然而,当问题变得极其困难时,应对策略也完全不同。在这种情况下,真实情况变化极快,可能以天、小时甚至分钟为单位。金融市场预测就属于此类范畴,它们变化非常迅速。

此时,模型性能下降无疑是触发模型重新训练的主要驱动因素。模型改进和软件变更等工作通常在线下进行,而应对性能下降则需要定义清晰的流程。

此类问题的数据标注极具挑战性。如果领域允许,直接反馈是理想方式;否则,可能需要借助我们后续会讨论的弱监督等方法。这些领域(如市场预测)往往价值很高,进行预测的激励很大,因此挑战也相应更大。


核心要点总结

本节课中,我们一起学习了生产环境中数据与概念变更的应对。核心要点如下:

  1. 模型性能会随时间衰减。衰减速度可能很慢(如猫狗识别),也可能极快(如金融市场)。
  2. 模型重新训练有助于提升或维持性能。当模型性能下降时,重新训练是关键的应对手段。
  3. 数据标注是关键环节。假设你使用的是常见的监督学习,那么数据标注是重新训练过程中的核心部分。你需要根据具体的问题、领域以及可用的系统,仔细思考如何实施数据标注策略。

公式/代码表示核心概念

  • 模型性能衰减可概念化为:模型性能 = f(时间, 数据分布, 概念漂移),其中 f 通常随时间呈下降趋势。
  • 触发重新训练的条件常基于性能指标阈值,例如:if current_accuracy < threshold: trigger_retraining()

050:流程反馈与人工标注 📝

在本节课中,我们将学习为机器学习数据生成标签的两种最常见方法:流程反馈(或称直接标注)与人工标注。我们将探讨它们的工作原理、各自的优缺点,以及在实际生产环境中的应用场景。


概述

在监督学习中,模型需要带有标签的数据进行训练。然而,原始数据通常是无标签的。因此,如何高效、准确地为数据生成标签,是机器学习工程中的一个关键环节。本节将重点介绍两种最基础的标签生成方法。


流程反馈(直接标注) 🔄

上一节我们介绍了标签的重要性,本节中我们首先来看看流程反馈(或称直接标注)这种方法。这是一种通过监控系统运行结果,自动为模型预测数据打上标签的方法。

其核心思想是:收集模型在生产环境中进行推理请求时所用的特征数据,然后通过监控后续的系统反馈(如用户行为),为这些特征数据生成对应的标签。

公式化描述
标签 = 系统反馈(模型预测(特征))

例如,在推荐系统中,模型根据用户特征预测其可能点击的项目。随后,系统可以监控用户是否真的点击了该推荐。点击行为可以作为一个“正”标签,未点击则作为“负”标签。

以下是流程反馈的主要特点:

  • 优点

    • 标签信号强:标签直接来源于真实世界的反馈(如点击、购买),非常可靠。
    • 可持续生成:只要系统在运行,就能持续产生新的带标签训练数据,便于模型迭代更新。
    • 自动化程度高:一旦流程建立,无需持续的人工干预。
  • 缺点

    • 适用领域有限:并非所有问题都能轻易获得这种直接的、自动化的反馈(例如,医疗诊断)。
    • 系统设计复杂:需要定制化开发数据管道,以关联推理请求和后续反馈(两者在时间上可能相隔数小时甚至数天)。
    • 非通用方案:解决方案高度依赖于具体的业务系统和问题。

在实施流程反馈时,日志分析是关键技术环节,因为反馈数据常来源于系统日志。

以下是几种常用的日志分析工具:

  • 开源工具
    • Logstash:用于收集、解析和存储日志,可与 Elasticsearch 集成。
    • Fluentd:云原生计算基金会旗下的项目,擅长从多种平台收集和统一日志数据。
  • 云服务商工具
    • Google Cloud Logging:适用于 GCP 及混合云环境。
    • Amazon OpenSearch Service:AWS 提供的 Elasticsearch 服务,可用于日志分析。
    • Azure Monitor:微软 Azure 平台的监控与日志分析服务。

人工标注 👥

如果无法通过系统自动获得标签,人工标注便是另一种基础且广泛使用的方法。这种方法的核心是聘请标注员(人类)来检查原始数据并手动分配标签。

其流程可以概括为:从未标注的原始数据开始,交由人工标注员根据明确的标注指南进行审查和打标,最终形成可用于训练的标注数据集

以下是实施人工标注的关键步骤:

  1. 准备数据与指南:提供未标注的原始数据和清晰、具体的标注说明书。
  2. 招募标注员:可以自行招募,或使用提供现成标注员池的专业服务(如亚马逊 Mechanical Turk)。
  3. 分配与标注:将数据分发给标注员。通常,同一份数据会分给多人标注,以检验一致性。
  4. 收集与解决冲突:回收标注结果,并处理不同标注员之间的分歧,以得到最终一致的标签。

以下是人工标注的主要特点:

  • 优点

    • 适用范围广:几乎任何类型的数据都可以通过人工进行标注。
    • 能够处理复杂判断:对于需要专业领域知识(如医学影像分析)或复杂逻辑判断的任务,人类标注员不可或缺。
  • 缺点

    • 成本高昂:尤其是需要领域专家(如放射科医生)参与时,人力成本非常可观。
    • 速度缓慢:人工处理每个数据样本需要时间,难以应对数据快速变化的场景。
    • 质量不一致:不同标注员对同一数据的判断可能存在分歧,需要额外的质量控制流程。
    • 难以规模化:由于成本和时间的限制,通常难以通过纯人工方式获得超大规模的数据集。

总结

本节课中我们一起学习了为机器学习生成训练标签的两种核心方法。

  • 流程反馈(直接标注) 通过系统自动监控反馈来生成标签,适用于能获得明确行为反馈的场景(如推荐系统),优点是自动化、可持续,但系统设计复杂且适用面较窄。
  • 人工标注 依靠人力为数据打标,几乎万能但成本高、速度慢,常用于缺乏自动反馈或需要专业知识的领域。

选择哪种方法,取决于具体问题的性质、数据的类型、对标签更新频率的要求以及项目预算。在实际生产中,有时也需要结合使用多种方法。后续课程中,我们还将探讨半监督标注、主动学习等更高级的标签生成技术。

051:第10课 检测数据问题 📊

在本节课中,我们将学习如何验证数据并检测数据问题,特别是理解在机器学习生产实践中需要处理的各种数据漂移和偏斜问题。数据质量是模型性能的基石,糟糕的数据必然导致糟糕的模型输出。


数据漂移与偏斜的定义

上一节我们明确了数据质量的重要性,本节中我们来看看数据问题的具体类型。首先,我们需要区分两个核心概念:漂移和偏斜。

  • 漂移 指的是数据随时间发生的变化。例如,每天收集的数据,在一周或一个月后,其统计特性可能已经发生了变化。
  • 偏斜 指的是两个静态版本、来自不同来源但概念上相同的数据集之间的差异。例如,你的训练集和用于预测请求的服务数据之间的差异。

在一个典型的机器学习流水线中,无论是批处理还是在线处理,你都会遇到概念相同但来源不同的数据。这些数据拥有相同的特征向量,但会随时间发生变化。这意味着模型性能可能因系统故障而快速下降,也可能因数据或世界的变化而随时间衰减。我们将重点关注因训练数据与服务数据之间的问题而导致的性能衰减。


模型衰减与概念漂移

模型衰减通常由漂移引起,即特征的统计属性发生了变化。这可能是由于季节性、趋势、意外事件或世界本身的变化。

示例:一个应用在训练时,将每分钟发送20条或以上消息的用户分类为垃圾信息发送者。但在一次系统更新后,无论是垃圾信息发送者还是普通用户,都开始发送更多消息。此时,世界已经改变,导致模型将所有用户误分类为垃圾信息发送者。

概念漂移 是指标签的统计属性随时间发生了变化。在训练时,模型学习特征与标签之间的映射关系。在一个静态世界中这没问题,但在现实世界中,标签的分布和含义会改变,因此模型也需要随之改变,否则训练时找到的映射将不再有效。


偏斜的类型与检测

导致数据随时间变化的因素很多,包括上游数据变化、季节性和不断演变的业务流程。

以下是两种主要的偏斜类型:

  • 模式偏斜:当训练数据和服务数据的模式不一致时发生。例如,你期望收到浮点数却收到了整数,或期望收到分类值却收到了字符串。
  • 分布偏斜:训练数据集和服务数据集之间的分布出现差异。数据偏移可以通过协变量偏移、概念偏移等形式表现出来。

偏斜检测涉及在模型部署后,对流入服务的数据进行持续评估。为了检测这类变化,你需要对数据进行持续的监控和评估。


数据偏移的严格定义

让我们更严谨地定义一下我们讨论的漂移和偏斜类型。

  • 数据集偏移:当特征 X 和标签 Y 的联合概率分布在训练时和服务时不同时发生。即数据随时间发生了偏移。
    • 公式P_train(X, Y) != P_serve(X, Y)
  • 协变量偏移:指训练数据和服务数据中输入变量分布的变化。换句话说,特征是 X 的边缘分布在训练和服务时不同,但条件分布保持不变。
    • 公式P_train(X) != P_serve(X),但 P_train(Y|X) = P_serve(Y|X)
  • 概念偏移:指输入变量和输出变量之间关系的变化,而不是数据分布或输入本身的差异。换句话说,给定特征 X 时,标签 Y 的条件分布在训练和服务时不同,但特征 X 的边缘分布保持不变。
    • 公式P_train(Y|X) != P_serve(Y|X),但 P_train(X) = P_serve(X)

检测数据偏斜的工作流程

检测数据偏斜有一个直接的工作流程。

以下是具体步骤:

  1. 建立基线:分析训练数据,计算基线统计量并定义参考模式。
  2. 分析服务数据:对服务数据执行相同操作,生成描述性统计量。
  3. 比较差异:将服务数据的基线统计量和实例与训练数据进行比较,寻找偏斜和漂移。
  4. 告警与处理:显著的差异被视为异常,并触发警报。警报会发送给监控系统(可以是人或另一个系统),由其分析变化并决定采取适当的纠正措施。

本节课中我们一起学习了机器学习生产中的数据问题。我们明确了漂移(数据随时间变化)和偏斜(不同数据源间的静态差异)的定义,探讨了模型衰减概念漂移的成因,并区分了数据集偏移协变量偏移概念偏移。最后,我们介绍了一个用于检测数据偏斜的标准化工作流程,包括建立基线、持续比较和触发警报修复。理解并监控这些数据问题是构建健壮、可持续的机器学习系统的关键。

052:TensorFlow 数据验证 📊

在本节课中,我们将学习 TensorFlow Data Validation(TFDV)库。这是一个来自谷歌的工具,属于 TFX 生态系统的一部分。我们将了解如何使用 Python 进行数据验证,并理解其在生产规模机器学习系统中的重要性。


什么是 TensorFlow Data Validation?

上一节我们介绍了数据问题及其检测工作流的重要性。本节中,我们来看看 TensorFlow Data Validation(TFDV)这个具体的工具。

TFDV 帮助开发者在规模上理解、验证和监控他们的机器学习数据。谷歌每天使用 TFDV 分析和验证数百或数千个生产应用中的 PB 级数据。它帮助 TFX 用户维护其机器学习管道的健康。

TFDV 的核心功能包括:

  • 生成数据统计信息并提供浏览器可视化。
  • 推断数据模式,但需要开发者确保该模式合理。
  • 基于统计信息和模式,检测数据中的问题或异常。
  • 通过比较训练数据集和服务数据集,检查训练-服务偏差。

一个常见的用例是:持续检查新到达的数据,将其与从训练数据生成的参考模式中的预期进行验证。典型的设置是维护一个长期有效的模式,然后计算新数据的统计信息,并用这些统计信息根据原始模式来验证数据。


使用 TFDV 检测数据偏差

还记得我们讨论过的偏差检测吗?使用 TFDV,你可以轻松检测三种不同类型的偏差。

以下是 TFDV 可以检测的偏差类型:

  1. 模式偏差:当服务数据和训练数据不遵循相同的模式时发生。例如,类型变更(期望是浮点数,实际是整数),或特征本身的变更。
  2. 特征偏差:训练和服务之间特征值的变化。这可能是因为系统在训练和服务时使用了不同的数据源,或者数据本身发生了变化(如季节性、趋势)。有时,仅仅是因为训练模型和服务模型时使用了不同的代码路径进行相同的转换,导致了不同的结果。
  3. 分布偏差:数据中单个特征分布的变化。例如,训练时某个特征的范围是 0 到 100,而服务时看到的数据在 5 到 600 之间。均值、中位数或标准差的变化都属于分布变化。偏差的严重程度决定了它是否构成问题,关键在于它是否足以影响模型性能。

TFDV 对分类特征执行偏差或漂移检测。偏差用 L∞ 距离(也称为切比雪夫距离)表示。你可以设置阈值,当漂移超过可接受范围时收到警告。


TFDV 的功能与可视化

TFDV 提供了大规模数据的描述性统计(可处理 PB 级数据)和一些可视化工具,帮助你监控和理解数据。

其核心目标是:

  • 理解数据的底层统计信息并进行比较。
  • 比较训练、评估和服务数据集在统计上的差异(例如,它们是否具有相同的均值)。
  • 计算、检测并修复数据异常。

本周内容回顾与总结

本节课中我们一起学习了 TFDV 的基础知识。现在,让我们回顾一下本周的核心内容。

本周,你看到了学术/研究环境与生产 ML 系统中的机器学习建模差异。我们讨论了负责任的数据收集以及如何构建公平的生产 ML 系统。我们学习了过程反馈、直接标记和人工标记。我们还研究了一些可能遇到的数据问题,以及如何识别和检测这些问题。

现在,我们将在本周的练习笔记本中实践使用 TFDV 进行数据验证。你将通过生成数据集统计信息、创建、比较和更新数据模式来测试你的编程技能。

祝你好运!🚀

053:特征工程、转换与选择简介 🧠

在本节课中,我们将学习特征工程、转换与选择的基础知识。这些内容可能看起来像是复习,尤其是如果你之前学习过相关课程或在学术研究环境中工作过。但在这里,我们将重点关注生产环境中的问题,其中一个关键点是如何以可重复且一致的方式大规模执行这些操作。


概述

特征工程是应用机器学习中至关重要的一环。正如吴恩达所说:“构思特征很困难,耗时且需要专业知识。” 应用机器学习通常需要对特征和数据集进行细致的工程化处理。

接下来,我们将探讨如何从数据中提取最大价值,了解特征工程这门“艺术”,审视特征工程过程本身,并看看它在典型机器学习流水线中是如何实现的。


如何从数据中提取信息 📊

机器学习模型通常需要一些数据预处理来改进训练效果。你可能已经训练过足够多的模型,对此非常熟悉。但可能不太熟悉的是生产环境中涉及的一些问题,而这正是我们的重点。

数据的表示方式会极大地影响模型从中学习的能力。例如,当数值数据被归一化后,模型往往会更快、更可靠地收敛。

选择和转换输入数据的技术是提高模型预测质量的关键。此外,只要可能,就推荐进行降维,这样可以在增强数据表示和预测能力的同时,保留最相关的信息,并减少所需的计算资源。请记住,在生产环境中,计算资源是模型运行成本的主要组成部分。


特征工程的概念审视 🎨

特征工程这门“艺术”旨在提高模型的学习能力,同时尽可能减少其所需的计算资源。它通过对原始数据中的特征进行转换、投影、消除和/或组合,来形成数据集的新版本。

在典型的机器学习流水线中,你会整合原始特征(通常经过转换或投影到新空间)和/或特征的组合。必须正确调整目标函数,以确保模型朝着正确的方向前进,并且与你的特征工程保持一致。

你还可以通过从可用数据集中添加新特征来更新模型。与机器学习中的许多事情一样,这往往是一个迭代过程,随着迭代逐步改进结果(或者你希望如此)。你必须监控这个过程,如果没有改进,可能需要回退并尝试另一种方法。


训练与部署中的特征工程 🔄

特征工程通常以两种相当不同的方式应用。

在训练期间,你通常可以访问整个数据集,因此可以在特征工程转换中使用各个特征的全局属性。例如,你可以计算一个特征的标准差,然后用它来执行归一化。

然而,在部署训练好的模型时,你必须进行相同的特征工程,以便为模型提供与训练时相同类型的数据。例如,如果你在训练时为分类特征创建了独热编码向量,那么在部署模型时也需要创建等效的独热编码向量。

在训练和部署期间,你通常单独处理每个请求。因此,至关重要的是,如果你在训练时使用了特征的全局属性(如标准差),那么在部署时进行的特征工程中也必须包含这些属性。未能正确处理这一点是生产系统中一个非常常见的问题来源,而且这些错误往往难以发现。


总结

本节课我们一起学习了特征工程、转换与选择的核心概念。

回顾一些关键点:

  • 正如吴恩达的引述所示,特征工程可能非常困难且耗时,但它对成功至关重要。
  • 你需要从数据中榨取最大价值,而特征工程正是实现这一目标的手段。通过它,你的模型能够更好地学习。
  • 你还需要确保将数据中的预测信息集中在尽可能少的特征中,以最佳且最经济的方式利用计算资源。
  • 最后,你必须确保在模型部署时应用与训练时相同的特征工程流程。

054:13_预处理操作 🛠️

在本节课中,我们将要学习机器学习中关键的预处理操作。这些操作是特征工程的核心,负责将原始数据转化为模型能够有效学习的格式。我们将探讨数据清洗、数值缩放、降维以及特征构建等主要技术,并了解如何根据数据类型(如文本、图像)应用特定的预处理方法。

从原始数据到特征向量

上一节我们介绍了特征工程的重要性,本节中我们来看看具体的映射过程。特征工程的核心在于分析原始数据,并从中创建出特征向量。

例如,整数数据可以映射为浮点数,数值数据可以进行归一化,而分类值则可以创建为独热编码向量。特征工程正是从原始数据中创建这些特征的过程。

以下是一个将分类特征转换为模型友好格式的示例:

  • 我们有一个名为“街道名称”的分类特征。
  • 我们通过独热编码对其进行特征工程处理。
  • 最终,我们得到了特征向量中的一个特征。

创建词汇表是处理文本分类特征的另一种常见方式。TensorFlow等框架提供了相应的函数来实现。

主要预处理操作概述

以下是数据预处理中一些最主要的操作类型。请注意,这并非一份详尽的列表,但涵盖了关键部分。

数据清洗
数据清洗广义上指消除或纠正错误数据。

数值变换
通常需要对数据进行变换,例如对数值进行缩放或归一化。因为模型(尤其是神经网络)对数值特征的幅度或范围很敏感。数据预处理有助于机器学习构建更好的预测模型。

降维
降维通过创建更低维度、更鲁棒的数据表示来减少特征数量。

特征构建
特征构建可以通过多种技术来创建新特征,我们稍后会讨论其中一些。

处理分类特征:词汇表

对于分类特征,创建词汇表是一种标准做法。TensorFlow提供了两个不同的函数来创建分类词汇表列,其他框架也有类似功能。

categorical_column_with_vocabulary_list
此函数根据一个显式定义的词汇表列表,将每个字符串映射为一个整数。

  • feature_name 是一个字符串,对应分类特征。
  • vocabulary_list 是一个有序列表,用于定义词汇表。

categorical_column_with_vocabulary_file
此函数功能类似,但词汇表来源于文件。当词汇表过长时,它允许你将词汇放在一个单独的文件中。

  • 在这种情况下,vocabulary_list 被定义为一个文件路径,该文件包含了词汇列表。

依据数据知识指导特征变换

我们对数据的理解(无论是领域专业知识还是处理不同类型数据的经验)能够指导我们如何转换特征,从而设计出更好的特征。

针对不同的数据类型,有截然不同的操作和预处理技术,可以帮助我们增加其预测信息。

文本数据
对于文本,我们有词干提取、词形还原、以及像TF-IDF、N-gram和词嵌入这样的归一化技术。这些技术真正聚焦于词语的语义价值,这是我们作为数据科学家或机器学习工程师所应掌握的处理文本数据的知识。

图像数据
图像处理类似。我们知道一些方法可以提升图像的预测质量,例如:

  • 裁剪
  • 调整大小
  • 模糊处理
  • 使用Canny滤波器、Sobel滤波器等滤波器
  • 应用其他光度畸变

所有这些方法都能真正帮助我们处理图像数据,以改善其预测质量。

关键要点总结

本节课中我们一起学习了数据预处理与特征工程的核心概念。

数据预处理是一种将原始数据转换为对训练模型有用的数据的技术。

特征工程则包括映射原始输入数据,并利用针对不同数据类型的各种技术从中创建特征向量。它还可以包括将数据从一个空间映射到另一个空间,这根据模型特性(例如线性模型与神经网络)的不同,会对模型的学习效果产生重大影响。

记住一个故事:我曾因匆忙而跳过数据归一化步骤,结果模型无法收敛。在花费时间调整超参数和模型结构后,才想起是归一化的问题。希望这个教训能帮助你避免类似的失误。

055:特征工程技术 🛠️

在本节课中,我们将学习特征工程的核心技术。特征工程是数据预处理的关键步骤,它通过转换和优化原始数据,使其更适合机器学习模型。我们将探讨特征缩放、分桶、降维等基本技术,并理解它们如何影响模型性能。


特征缩放基础

上一节我们介绍了特征工程的重要性,本节中我们来看看特征缩放的具体方法。特征缩放旨在将数值特征转换到标准范围内,以帮助模型更高效地学习。

以下是几种常见的特征缩放技术:

  • 归一化 (Normalization / Min-Max Scaling)
    归一化将数据线性缩放到 [0, 1] 区间。其公式为:
    x_normalized = (x - min(x)) / (max(x) - min(x))
    这种方法适用于数据分布不遵循高斯(正态)分布的情况。需要注意的是,计算最小值和最大值需要对整个数据集进行一次完整遍历。

  • 标准化 (Standardization / Z-score Normalization)
    标准化基于数据的均值和标准差进行缩放,使数据均值为0,标准差为1。其公式为:
    x_standardized = (x - mean(x)) / std(x)
    标准化后的数据范围不固定,可包含负值。当数据近似服从正态分布时,标准化是一个很好的起点。

在实际应用中,建议尝试归一化标准化两种方法,并比较模型效果,因为不同数据集和模型对缩放方式的响应可能不同。


分桶与离散化

了解了数值特征的连续缩放后,我们来看一种将连续值转换为类别特征的技术:分桶。

有时,直接将一个数值(如房屋建造年份)输入模型效果不佳。通过将其分组到不同的“桶”中,可以更好地捕捉其内在意义。例如,1960年和1961年的差异,远不如1960年和1970年的差异重要。

以下是分桶的一个示例:
原始特征:建造年份 = 1960
分桶后(例如按年代):[1960-1969]
进一步进行独热编码 (One-Hot Encoding),可能表示为:[0, 1, 0, 0, ...]

这种技术有助于模型学习更有意义的模式,同时也是探索和理解数据分布的有效可视化手段。


降维与其他技术

除了缩放和分桶,特征工程还包含其他高级技术,用于处理高维数据或创造新的特征。

  • 降维技术
    当特征维度很高时,降维可以帮助我们理解和可视化数据,同时可能提升模型效率。

    • 主成分分析 (PCA):将数据投影到方差最大的几个主成分上。
    • t-分布随机邻域嵌入 (t-SNE):常用于高维数据的可视化,能较好地保留局部结构。
    • 统一流形逼近与投影 (UMAP):另一种降维和可视化技术,在保留全局结构方面可能有优势。
  • 特征交叉与可视化
    特征交叉是指将两个或多个特征组合,以捕捉它们之间的交互作用。对于由嵌入(如词向量)构成的高维数据,使用像 TensorFlow Embedding Projector 这样的工具进行可视化至关重要。它可以帮助我们直观地看到数据点在空间中的聚类情况,从而形成对数据的“直觉”,这是特征工程中“艺术性”的一部分。


本节总结 🎯

本节课中我们一起学习了特征工程的核心技术。
我们首先介绍了特征缩放,包括归一化和标准化的原理与应用场景。
接着,我们探讨了分桶技术,它如何将连续值转化为更具表达力的类别特征。
最后,我们概述了降维方法(如PCA、t-SNE)和可视化工具的重要性,它们能帮助我们在高维空间中理解数据。

特征工程是连接原始数据与机器学习模型的桥梁,精心设计的特征能显著提升模型的性能与收敛速度。掌握这些技术,是成为一名优秀机器学习工程师的关键一步。

056:交叉特征与特征编码 🧩

在本节课中,我们将学习特征工程中的两个重要概念:交叉特征特征编码。我们将了解如何通过组合现有特征来创建新的合成特征,以及如何对特征进行编码以更好地适应模型。


交叉特征介绍

上一节我们讨论了特征工程的基础,本节中我们来看看交叉特征。交叉特征是本节将要讨论的核心内容。

交叉特征的本质是将多个特征组合在一起,形成一个新的特征。它能在特征空间中编码非线性关系,或者用更少的特征表达相同的信息。

我们可以创建多种类型的交叉特征,这很大程度上取决于我们的数据。因此,这需要一些想象力来寻找组合现有特征的方法。

以下是创建交叉特征的几种常见方式:

  • 数值特征相乘:例如,将两个数值特征相乘,生成一个表达两者关系的新特征。如果我们有多个数值特征,甚至可以将它们全部相乘,最终得到一个特征,而不是原来的五个。
  • 组合分类与数值特征:以符合语义逻辑的方式组合特征。例如,如果我们有“星期几”和“小时”这两个特征,可以将它们组合成“一周中的第几个小时”,从而在一个特征中表达相同的信息。

特征编码示例

现在让我们快速了解一下特征编码。特征编码是将特征转换为更适合机器学习模型处理格式的过程。

假设我们有一个数据集,用于区分健康树木和患病树木。我们使用散点图来理解数据,并问自己:能否画一条线来分隔这两个数据簇?

如果能用一条线创建决策边界,那么我们知道可以使用线性模型,这非常高效。

但是,假设数据分布如下图所示,问题就变得非线性了。此时的问题是:我们能否将数据投影到一个线性空间,以便使用线性模型?还是必须使用非线性模型来处理这些数据?因为如果尝试在原始数据上绘制线性分类边界,效果不会很好。

可视化工具能帮助我们理解这一点。审视数据能有效指导我们作为开发者,在选择模型类型和应用何种特征工程时做出决策。


核心要点总结

本节课中我们一起学习了交叉特征与特征编码。

关键点总结如下:

  • 交叉特征 是一种创建合成特征的方法,常用于在特征空间中编码非线性关系。
  • 我们可以转换特征,特别是分类特征(实际上数值特征也可以),将其转换为连续变量,或进行其他形式的转换。

通过巧妙地组合和编码特征,我们可以帮助模型更好地理解数据中的复杂模式,即使使用相对简单的线性模型也能解决非线性问题。

057:🚀 大规模数据预处理

在本节课中,我们将要学习如何在生产环境中进行大规模的数据预处理和特征工程。我们将探讨从笔记本环境到生产环境的转变所带来的挑战,并介绍确保处理过程可重复、一致且高效的关键策略。


我们可能都进行过特征工程。但在笔记本中处理几百兆字节的数据是一回事,而在生产环境中以可重复、自动化的流程处理可能高达数TB的数据,则是另一回事。现在,让我们来看看如何进行大规模的特征工程。

在笔记本中进行一次性的转换和特征工程是一回事,但在生产环境中以可重复、一致的方式进行大规模处理则是另一回事。因此,我们现在来探讨大规模数据预处理。

首先,让我分享一个故事。我曾在一个生产环境中担任数据科学家,我们将生产负载部署在Apache Storm上。这个平台性能不错。我们作为数据科学家在笔记本中创建模型,然后将其部署到Apache Storm中。然而,过程并不简单:我们在Python中开发笔记本,但部署到Storm时,必须将所有特征工程代码转换为Java。可以想象,这并不理想,并且经常出现一些难以排查的奇怪问题。这不是进行生产级机器学习的理想方式。

更好的技术是使用一个统一的流水线(pipeline)框架,它允许你以一致且可重复的结果进行训练和部署。我们将在本课程中学习这一点。现在,让我们看看大规模特征工程面临的一些问题。

以下是我们要讨论的内容:

  • 特征工程中的不一致性:非常重要。
  • 预处理的粒度:在生产环境中也是一个有趣的问题。
  • 预处理训练数据是一回事,而为实例级转换进行优化则有所不同,但你需要应对许多挑战。

为了进行大规模数据预处理,我们从现实世界的数据模型开始,这些数据可能高达TB级别。在进行这类工作时,你希望从一个数据子集开始,尽可能多地解决问题,并思考如何扩展到处理整个数据集所需的TB级别。

大规模数据处理框架与你将在笔记本电脑或笔记本中使用的工具不同。因此,你需要从流程一开始就思考如何应用这些框架。越早开始使用这些框架,你就能越早地用较小的数据集和更快的周转时间解决问题。

训练与部署间转换的一致性至关重要。如果在部署模型时进行的转换与训练时不同,你将会遇到问题,而且这些问题通常很难发现。

以下是特征工程中不一致性的具体表现:

  • 训练与部署的代码路径:训练模型时使用一套代码(例如Python),而部署时可能使用另一套代码(例如Java),这是潜在的问题来源。
  • 不同的部署场景:你可能在不同的环境中部署模型,例如在服务集群中使用,同时也在物联网设备上使用。不同的部署目标有不同的CPU或计算资源限制(例如移动设备资源紧张,服务器则宽松些),需要考虑这些因素。
  • 引入训练-部署偏差的风险:由于训练和部署间的代码路径不同,如果两者间的转换不完全一致(最佳做法是使用完全相同的代码),就会导致模型性能下降。模型可能完全出错、给出奇怪结果,或在某些情况下出现轻微偏差,这些更难检测。

接下来,我们需要考虑预处理的粒度。你需要在两个层面进行转换:实例级全数据遍历级。根据你进行的转换类型,可能需要选择其中一种或另一种。通常你总是可以进行实例级转换,但全数据遍历则需要整个数据集。

以下是不同转换类型对粒度的要求示例:

  • 裁剪(Clipping):即使进行裁剪,也需要设定边界。如果不是任意设定,而是基于数据集本身来确定如何裁剪,那么就需要进行全数据遍历以确定最小值和最大值。
  • 乘法(Multiplication):在实例级别进行即可。
  • 缩放(Scaling):通常需要标准差,可能还需要最小值和最大值,因此可能需要全数据遍历。
  • 分桶(Bucketizing):除非提前知道分桶边界,否则需要全数据遍历来确定合理的分桶区间。
  • 特征扩展(Expanding features):通常可以在实例级别完成。

在训练时,我拥有整个数据集,因此可以进行全数据遍历(尽管可能成本高昂)。在部署时,我收到的是单个样本,因此只能进行实例级转换。任何需要整个数据集特征的转换,我都必须将计算出的信息(如标准差)保存下来,以便在部署时使用。

那么,何时进行转换呢?你可以预处理整个训练数据集。这样做的好处是每个训练会话只运行一次,并且是在整个数据集上计算。但缺点是,你必须在部署时重现所有这些转换,或者保存从数据中学到的信息(如标准差)以供后续部署使用。此外,每次更改都需要对整个数据集进行一次完整的遍历,迭代速度较慢。

另一种方法是在模型内部进行转换。这样做的好处是迭代更容易,因为转换作为模型的一部分被嵌入,并且能保证转换的一致性。但缺点是,执行这些转换可能成本高昂,尤其是在计算资源有限的情况下。在模型内部进行转换意味着部署时也会进行同样的转换,而训练时可能使用GPU或TPU,部署时则可能没有。这可能导致模型延迟增加,影响响应时间。此外,如果未保存所需的常量(如用于归一化的均值),也可能出现问题。

你还可以选择按批次(per batch)进行转换,而不是针对整个数据集。例如,你可以根据批次内的平均值来归一化特征。这只需要遍历每个批次,而不是整个数据集。在处理TB级数据时,这在处理效率上是一个显著优势。你也可以按批次进行归一化,例如计算一个批次的平均值并用其进行归一化,然后对下一个批次重复此过程。批次之间会存在差异,有时这是有益的(例如在时间序列数据中,这能适应随时间的变化),但你需要考虑这一点。例如,按批次平均值进行归一化,预计算平均值并在归一化中使用,可以用于多个批次。这是在处理大型数据集时需要考虑的不同方法。

你还需要考虑优化实例级转换,因为这会影响训练效率和部署效率。你需要考虑加速器(如GPU)的使用情况,避免在CPU进行转换时让昂贵的加速器闲置。解决方案之一是预取(prefetching)。通过预取,你可以用CPU预取数据并馈送给加速器(GPU或TPU),尝试并行化处理过程。这最终都关系到成本、训练所需的时间以及效率。


总结

本节课我们一起学习了大规模数据预处理的挑战与策略。关键点包括:

  • 不一致的数据会影响结果的准确性
  • 可扩展的数据处理框架允许我们以分布式和高效的方式处理大型数据集。
  • 我们还需要思考这些处理如何应用于模型部署阶段。

我们必须平衡模型的预测性能与其实现要求。如果要对训练数据进行全数据遍历转换,就需要考虑这在模型部署时如何工作,并保存必要的常量。同时,我们需要优化实例级转换以提高训练效率,预取等技术对此很有帮助。

058:TensorFlow Transform 详解 🛠️

在本节课中,我们将深入学习 TensorFlow Transform(TFT)这一工具。我们将探讨它的工作原理、核心优势以及如何在实际的机器学习流水线中应用它进行大规模数据预处理。

概述:为什么需要 TensorFlow Transform?

为了进行大规模的数据预处理,我们需要高效的工具。TensorFlow Transform 是当前可用的最佳工具之一。

上一节我们介绍了大规模数据预处理的必要性,本节中我们来看看 TensorFlow Transform 的具体工作机制。

TensorFlow Transform 的工作流程

首先,我们来看看它的工作流程。TensorFlow Transform 接收训练数据,对其进行处理,最终将处理结果部署到服务系统中。在这个过程中,一个流水线被使用,而元数据在组织和管理数据转换过程中产生的工件(Artifacts)方面扮演着关键角色。这很重要,原因之一是我们希望理解这些工件的来源,并能够追踪生成它们的操作链。

以下是其核心流程:

  • 输入:训练数据作为系统输入,形成一个工件。
  • 转换:Transform 组件接收原始数据,通过特征工程将其转换为实际可用的形式。
  • 训练:转换后的数据被交给训练器(Trainer)进行模型训练。Transform 和 Trainer 都是 ML 流水线(特别是 TFX ML 流水线)中的组件。
  • 输出:训练器产生一个训练好的模型(也是一个工件),该模型被交付给服务系统,用于运行推理。

从另一个视角看,流程始于训练和评估数据。数据集通过 ExampleGen 组件进行拆分。拆分后的数据被送入 StatisticsGen 组件(这些都是 TFX 流水线中的组件)。StatisticsGen 为数据计算统计信息,例如数值特征的均值、标准差、最小值、最大值等。这些统计信息被送入 SchemaGen 组件,后者推断每个特征的类型,从而创建一个模式(Schema)。下游组件(如 ExampleValidator)会使用这个模式和统计信息来检查数据中的问题。

接着,Transform 组件登场。它会接收生成的模式(Schema)和原始拆分的数据集,并执行我们的特征工程。因此,Transform 是特征工程发生的地方。处理后的数据交给 Trainer,由 Evaluator 评估结果,最后由 Pusher 推送到部署目标(如 TensorFlow Serving、TensorFlow Lite 或 TensorFlow.js)。

Transform 组件的内部机制

如果我们深入观察 Transform 组件内部,它会接收来自 ExampleGen 和 SchemaGen 的输入,即原始拆分的数据和生成的模式。这个模式很可能已经过开发者的审查和改进,这个过程称为“模式治理”(curating the schema)。

Transform 还需要接收大量用户代码,因为我们需要通过代码来表达想要进行的特征工程类型。例如,如果要标准化一个特征,我们需要提供用户代码来指示 Transform 执行此操作。

Transform 的输出是一个 TensorFlow 计算图(称为转换图)以及转换后的数据本身。转换图以 TensorFlow 图的形式表达了我们对数据所做的所有转换。转换后的数据就是执行这些转换的结果。这两者都会被提供给 Trainer 用于训练。

核心概念:分析器与转换图

我们使用 TF Transform API 来表达想要进行的特征工程。Transform 组件将此代码提交给 Apache Beam 分布式处理集群进行处理。这使我们有能力处理可能高达 TB 级别的数据。

在这个过程中,分析器(Analyzers)发挥着关键作用。分析器会对整个数据集进行一次完整的遍历,以收集进行特征工程时所需的常量。例如,如果我们要进行最小-最大缩放,就需要遍历整个数据集以了解每个相关特征的最小值和最大值。分析器会收集这些常量,并表达将要执行的操作。它们的行为类似于 TensorFlow 操作,但只在训练期间运行一次,然后被保存为图的一部分。

例如,使用 tft.min(Transform SDK 中的一个方法)会计算张量在整个训练数据集上的最小值。

其应用方式如下:

  1. 我们有一个代表特征工程的图。
  2. 我们运行分析器遍历数据集以收集所需的常量。
  3. 这使得我们能够在后续将常量应用到转换图中,从而能够转换单个样本,而无需再次遍历整个数据集。

这个图在训练期间被应用,并且在服务期间应用完全相同的图。这消除了训练和服务之间因代码路径不同而导致差异的可能性,确保了转换的一致性。

TensorFlow Transform 的主要优势

使用 TensorFlow Transform 带来了多重好处:

  • 统一的转换图:Transform 生成的图包含了所有必要的常量和转换。
  • 训练时专注预处理:它专注于在训练时进行数据预处理并生成转换图。
  • 训练与服务一致性:该图在训练和服务期间以相同的方式内联运行,并被预置到训练模型中。因此,在服务时不需要额外的预处理代码。
  • 平台无关性:无论部署到哪个平台(TensorFlow Serving、TensorFlow Lite 移动设备或 TensorFlow.js 浏览器环境),都能一致地应用这些转换。

分析器框架的功能

分析器框架支持多种特征转换操作:

  • 缩放:例如使用 Z-score 标准化,或在 0 和 1 之间进行缩放。
  • 分桶:例如按分位数进行分桶,或设置一组桶并将数值分配到这些桶中,从而为数值范围创建分类值。
  • 词汇表处理:例如在文本处理中,运行 TF-IDF、词袋模型或 N-grams 时,通常需要处理词汇表。
  • 降维:例如可以执行 PCA 转换来降低数据的维度。

代码示例:编写预处理函数

现在让我们看一些代码。我们将创建一个预处理函数,这是定义用户代码的入口点,用于表达我们要进行的特征工程。

例如,我们可能遍历数据寻找浮点型特征,并对它们进行 Z-score 标准化。以下是一个示例代码风格:

def preprocessing_fn(inputs):
    # 假设 FLOAT_FEATURE_KEYS 是一个浮点特征键的列表
    outputs = {}
    for key in FLOAT_FEATURE_KEYS:
        outputs[key] = tft.scale_to_z_score(inputs[key])
    return outputs

对于词汇表特征,处理方式非常相似:

def preprocessing_fn(inputs):
    outputs = {}
    # 假设 VOCAB_FEATURE_KEYS 是需要词汇表处理的特征键列表
    for key in VOCAB_FEATURE_KEYS:
        outputs[key] = tft.compute_and_apply_vocabulary(inputs[key])
    return outputs

对于分桶特征,逻辑类似,BUCKET_FEATURE_KEYS 常量只是我们想要分桶的特征键列表。

必要的导入

使用 Transform 时,通常需要以下基本导入:

import tensorflow as tf
import apache_beam as beam
from apache_beam.io import tfrecordio  # 用于不同格式的I/O
import tensorflow_transform as tft
import tensorflow_transform.beam as tft_beam

请注意,Transform 使用 Apache Beam 在集群上分布式处理。你也可以在单机(如笔记本电脑)上使用 Beam 的 Direct Runner,这在开发阶段处理小量数据时非常有用。在正式部署中,除非数据量很小,否则可能需要更强的计算能力。

总结

本节课中,我们一起深入学习了 TensorFlow Transform。我们了解了它如何在大规模机器学习流水线中作为核心预处理工具,通过分析器收集数据集常量并生成统一的转换图,确保了从训练到服务整个流程中特征工程的一致性、高效性和平台无关性。我们还通过代码示例,了解了如何编写预处理函数来定义具体的特征转换逻辑。掌握 TensorFlow Transform 是构建可靠、可扩展的机器学习生产系统的重要一步。

059:使用 TF Transform 的 Hello World 🌟

在本节课中,我们将学习如何使用 TensorFlow Transform 进行特征工程。我们将通过一个简单的示例,展示如何将原始数据转换为可用于机器学习模型的特征。我们将涵盖数据收集、元数据定义、预处理函数编写以及使用 Apache Beam 执行转换的完整流程。


数据收集与元数据定义

首先,我们需要收集一些原始数据。在本示例中,我们使用一些为演示创建的静态数据。数据包含三个特征:XYS

接下来,我们使用 TensorFlow Transform 的元数据模块来定义这些特征的类型和信息。我们通过创建一个特征规范(Feature Spec)来实现这一点。特征规范描述了每个特征的类型和结构。

以下是定义元数据的代码示例:

import tensorflow_transform as tft

# 定义特征规范
feature_spec = {
    'X': tf.io.FixedLenFeature([], tf.float32),
    'Y': tf.io.FixedLenFeature([], tf.float32),
    'S': tf.io.FixedLenFeature([], tf.string)
}

在这个示例中,XY 是固定长度的浮点特征,而 S 是固定长度的字符串特征。


编写预处理函数

预处理函数是用户代码的入口点,用于定义特征工程的具体操作。在这个函数中,我们将对原始数据进行转换,生成新的特征。

以下是预处理函数的代码示例:

def preprocessing_fn(inputs):
    # 提取输入特征
    x = inputs['X']
    y = inputs['Y']
    s = inputs['S']
    
    # 对 X 进行中心化处理
    x_centered = x - tft.mean(x)
    
    # 对 Y 进行归一化处理,缩放到 [0, 1] 范围
    y_normalized = tft.scale_to_0_1(y)
    
    # 为字符串特征 S 创建词汇表并转换为整数
    s_integerized = tft.compute_and_apply_vocabulary(s)
    
    # 创建特征交叉:X_centered * Y_normalized
    feature_cross = x_centered * y_normalized
    
    # 返回转换后的特征
    return {
        'x_centered': x_centered,
        'y_normalized': y_normalized,
        's_integerized': s_integerized,
        'feature_cross': feature_cross
    }

在这个预处理函数中,我们执行了以下操作:

  • X 进行中心化处理,减去其均值。
  • Y 进行归一化处理,将其缩放到 [0, 1] 范围。
  • 为字符串特征 S 创建词汇表,并将其转换为整数。
  • 创建了一个特征交叉,将中心化后的 X 与归一化后的 Y 相乘。

执行转换流程

现在,我们将使用 Apache Beam 来执行转换流程。虽然在实际的 TFX 管道中,我们通常会使用 Transform 组件,但这里我们直接使用 TensorFlow Transform 库来演示。

以下是执行转换的代码示例:

import apache_beam as beam
import tensorflow_transform.beam as tft_beam

def main():
    # 建立 Apache Beam 上下文
    with beam.Pipeline() as pipeline:
        # 定义 Beam 管道
        raw_data = pipeline | 'ReadRawData' >> beam.Create([...])  # 原始数据
        raw_data_metadata = ...  # 原始数据元数据
        
        # 执行转换
        transform_fn = (
            (raw_data, raw_data_metadata)
            | tft_beam.AnalyzeAndTransformDataset(preprocessing_fn)
        )
        
        # 获取转换后的数据和元数据
        transformed_data, transform_metadata = transform_fn
        
        # 打印结果
        print("原始数据:", raw_data)
        print("转换后的数据:", transformed_data)

if __name__ == "__main__":
    main()

在这个示例中,我们使用 Apache Beam 管道来执行转换。AnalyzeAndTransformDataset 函数会调用我们的预处理函数,并返回转换后的数据和元数据。


转换结果对比

在执行转换之前,原始数据如下所示:

原始数据:
X: [1, 2, 3]
Y: [10, 20, 30]
S: ["a", "b", "c"]

执行转换后,我们得到以下特征:

转换后的数据:
x_centered: [-1, 0, 1]
y_normalized: [0.0, 0.5, 1.0]
s_integerized: [0, 1, 2]
feature_cross: [-0.0, 0.0, 1.0]

通过转换,原始数据被成功转换为可用于机器学习模型的特征。


核心要点总结

在本节课中,我们一起学习了如何使用 TensorFlow Transform 进行特征工程。以下是本课程的核心要点:

  1. 数据预处理与特征工程:TensorFlow Transform 允许对输入数据进行预处理,并创建新的特征。
  2. 大规模数据处理:通过 Apache Beam,可以在大规模数据处理框架(如 Spark、Flink 或 Google Cloud Dataflow)上运行预处理管道。
  3. TFX 集成:在 TFX 管道中,Transform 组件使用 TensorFlow Transform 库来实现特征工程。

通过本课程的学习,你应该能够理解如何使用 TensorFlow Transform 进行简单的特征工程,并将其应用于实际的数据处理流程中。

060:19_特征空间 🧭

在本节课中,我们将要学习特征空间这一核心概念。特征空间是理解数据分布和模型行为的基础。我们将探讨特征空间的定义、重要性,以及如何确保训练数据与生产数据在特征空间上的一致性。


特征空间简介 🗺️

特征空间是由数据特征定义的N维空间。如果你的数据有两个特征,特征空间就是二维的;如果有三个特征,就是三维的,以此类推。特征空间仅包含特征本身,不包括目标标签。

假设你的特征向量是 x,其维度为 D,那么它就定义了一个D维空间。例如,一个三维特征向量定义了一个三维空间。

我们可以用散点图来可视化二维特征空间,这对于人类理解来说相对容易。


特征空间在模型中的作用 ⚙️

让我们通过一个房屋预测的例子来理解。特征可能包括房间数量、房屋面积和地理位置,模型 F 在这个特征空间中运作,并产生一个预测结果 y(例如价格)。

在分类问题中,我们同样在特征空间中工作。理想情况下,不同类别的样本在特征空间中是线性可分的。但在现实中,样本分布可能更复杂,可能需要非线性模型或特征投影来划分决策边界。

模型的任务就是学习这个决策边界。一旦确定了边界,模型就能对新的输入样本进行分类。


特征空间覆盖的重要性 ✅

一个关键点是,用于训练和评估模型的数据,其特征空间必须能够代表模型上线后将遇到的数据。

这意味着:

  • 对于数值特征,训练数据和未来数据应具有相同的数值范围。
  • 对于分类特征,应包含相同的类别。
  • 对于图像数据,需要具有相似的视觉特征。
  • 对于自然语言处理,词汇的语法和语义特征需要一致。

对于时间序列问题,我们需要考虑季节性、趋势和漂移。生产数据中可能出现新的值或标签,这会导致概念漂移,正如我们之前讨论过的。

因此,我们需要设计流程来处理这种变化,而持续监控是确保模型在变化世界中保持成功的关键。请记住,模型只学习了世界的一个“快照”,当世界改变时,我们需要更新模型以适应新世界。


特征选择方法简介 🔍

上一节我们介绍了特征空间本身,本节中我们来看看如何从特征空间中选择最重要的特征,即特征选择。

特征选择主要有三种方法:

以下是三种主要的特征选择方法:

  1. 过滤法:在训练模型之前,根据特征的统计属性(如与目标的相关性)进行筛选。
  2. 包装法:使用模型的性能作为评价标准,来搜索最佳特征子集。例如递归特征消除。
  3. 嵌入法:特征选择过程嵌入在模型训练中。例如,Lasso回归(L1正则化)的系数可以自动进行特征选择。

总结 📝

本节课中我们一起学习了:

  1. 特征空间是由数据特征定义的多维空间,是模型学习决策边界的基础。
  2. 确保训练数据与生产数据在特征空间上覆盖一致至关重要,否则模型性能会下降。
  3. 对于动态数据(如时间序列),需要持续监控以应对概念漂移
  4. 介绍了特征选择的三种基本方法:过滤法、包装法和嵌入法,它们能帮助我们从原始特征空间中挑选出最相关的特征。

理解并管理好特征空间,是构建鲁棒、可投入生产的机器学习系统的重要一步。

061:特征选择 🎯

在本节课中,我们将学习特征选择的概念、重要性以及几种常见的实现方法。特征选择是机器学习流程中的关键步骤,它帮助我们识别并保留对预测目标最有价值的特征,同时剔除无关或冗余的特征,从而提升模型效率与性能。


什么是特征选择?

上一节我们介绍了特征工程的基础,本节中我们来看看特征选择。特征选择是指从所有可用特征中,挑选出对预测目标变量最有贡献的一个子集的过程。

我们通常拥有许多特征,但实际建模时可能并不需要全部。特征选择旨在识别最能代表特征与预测目标之间关系的特征,并移除那些对结果影响甚微的特征。这能有效减少特征空间的大小。

公式:若原始特征集为 F = {f1, f2, ..., fn},特征选择的目标是找到一个子集 F' ⊆ F,使得模型性能 P(F') 最优或接近使用 F 时的性能,同时满足 |F'| < |F|

每增加一个特征,特征空间的维度会指数级增长。减少特征数量可以降低数据处理所需的资源开销,同时也能简化模型复杂度。


为什么需要特征选择?

特征选择主要有以下几个目的:

  1. 降低存储与I/O需求:更少的特征意味着更小的数据体积,节省存储空间和读写时间。
  2. 最小化训练与推理成本:尤其是在模型部署后,面对海量的推理请求时,每个请求的处理成本都与特征数量相关。减少特征能直接降低计算开销。
  3. 缓解维度灾难:在高维空间中,数据变得稀疏,模型需要更多数据才能有效学习,且更容易过拟合。
  4. 提升模型可解释性:使用更少、更相关的特征有助于我们理解模型决策的依据。

特征选择的方法

特征选择方法主要分为无监督和有监督两大类。

无监督特征选择

无监督特征选择不利用目标变量(标签)的信息。它主要关注特征本身之间的关系,目标是移除冗余的特征。

以下是其核心思路:

  • 它分析特征间的相关性。
  • 当两个或多个特征高度相关时,它们所提供的信息大量重叠,通常只需保留其中一个。

有监督特征选择

有监督特征选择则会利用标签信息。它评估每个特征与目标变量之间的关系,并选择那些对正确预测目标贡献最大的特征。

我们将重点介绍几种有监督的特征选择方法,主要包括过滤法、包装法和嵌入法。


实践案例:乳腺癌诊断数据集

为了具体说明这些方法,我们将使用一个乳腺癌诊断数据集作为示例。我们的目标是预测肿瘤是良性(benign)还是恶性(malignant)。

代码:加载数据集的示例代码结构如下(以Python的pandas库为例):

import pandas as pd
from sklearn.datasets import load_breast_cancer

data = load_breast_cancer()
df = pd.DataFrame(data.data, columns=data.feature_names)
df['target'] = data.target

我们的特征列表中包含30个特征。此外,为了演示,数据集中特意添加了一个名为“Unnamed: 32”的无关特征(通常由数据读取错误产生,值全为NaN)。在实际项目中,无关特征可能以缺失值过多或与业务逻辑明显不符等形式出现。


性能评估基线

在应用任何特征选择方法之前,我们需要建立一个性能基线。我们将使用包含全部30个特征的数据集,训练一个随机森林分类器,并计算多项评估指标。

以下是使用的评估指标:

  • 准确率:正确预测的样本比例。
  • AUC分数:衡量模型区分能力的指标。
  • 精确率:在被预测为正类的样本中,实际为正类的比例。
  • 召回率:在实际为正类的样本中,被正确预测为正类的比例。
  • F1分数:精确率和召回率的调和平均数。

使用所有特征得到的各项指标值,将作为我们比较后续特征选择结果的基准。


总结

本节课中我们一起学习了特征选择的核心知识。我们了解了特征选择的定义及其在减少资源消耗、提升模型效率方面的重要性。我们区分了无监督与有监督特征选择的基本原理,并引入了过滤法、包装法和嵌入法这三大类有监督方法。最后,我们以乳腺癌诊断数据集为例,建立了模型性能的评估基线。在接下来的课程中,我们将深入探讨具体的特征选择算法及其应用。

062:特征选择之过滤法 🔍

在本节课中,我们将要学习特征选择的一种重要方法——过滤法。我们将了解其核心思想、常用技术,并通过代码示例展示如何在实际项目中应用过滤法来选择对模型最有价值的特征。


概述

特征选择是机器学习流程中的关键步骤,旨在从原始特征集中筛选出最相关、信息量最大的子集,以提升模型性能、降低计算成本并增强模型可解释性。过滤法是一种监督式特征选择方法,它主要依据特征与目标变量之间的统计相关性来评估特征的重要性。

上一节我们介绍了特征选择的基本概念和重要性,本节中我们来看看过滤法的具体实现。

什么是过滤法?

过滤法是一种特征选择方法,它独立于任何机器学习模型,通过分析数据本身的统计特性来评估特征。它属于监督式特征选择,因为其评估过程依赖于目标变量。除了过滤法,监督式特征选择还包括包装法和嵌入法。

过滤法主要利用相关性分析来寻找那些包含用于预测目标变量信息的特征。单变量特征选择也因其高效性而被频繁使用。

过滤法的核心思想

相关性高的特征通常是冗余的。正如我们之前讨论的,当两个特征彼此高度相关时,通常表明它们是冗余的。因此,你希望选择其中一个,而移除另一个。

以下是过滤法的基本流程:

  1. 我们从所有特征开始。
  2. 我们选择最佳的特征子集。
  3. 我们将这个子集提供给模型进行训练。
  4. 模型使用这个特征子集将给出其性能表现。

常用过滤方法

以下是几种流行的过滤方法:

  • 皮尔逊相关系数:这是最常用的相关性计算方法之一。它用于计算特征之间以及特征与标签之间的线性相关性。这正是它被称为监督方法的原因。
  • 肯德尔等级相关系数:这是一种等级相关系数,用于检测单调关系。它通常在样本量较小且追求效率时使用。
  • 斯皮尔曼等级相关系数:另一种等级相关系数,同样用于检测单调关系。
  • 互信息:互信息方法具有一些优良特性,可以捕捉线性和非线性关系。
  • F检验:这是另一种相当常见的方法,用于检验特征与目标变量之间的线性关系是否显著。
  • 卡方检验:这也是一个相当常见的方法,主要用于分类问题中检验特征与目标变量之间的独立性。

可视化工具:相关性矩阵

可视化过滤过程的一种方式是使用相关性矩阵。我们可以寻找两个或多个特征之间存在相关性的特征。相关性矩阵有助于展示特征之间以及特征与目标变量之间的关系。

需要强调的是,特征之间高度相关是不利的,你通常只需要保留其中一个。当然,你确实希望特征与目标变量相关。

相关性系数的取值范围在 -11 之间。1 表示高度正相关,-1 表示高度负相关。

代码实现:皮尔逊相关

让我们看看如何使用皮尔逊相关系数在代码中实现过滤法。这里使用 pandas 库。

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

# 假设 df 是一个包含特征和标签的 DataFrame
# 计算皮尔逊相关系数矩阵
correlation_matrix = df.corr(method='pearson')

# 绘制热力图
plt.figure(figsize=(12, 10))
sns.heatmap(correlation_matrix, annot=True, fmt=".2f", cmap='coolwarm', center=0)
plt.title('Feature Correlation Matrix')
plt.show()

上述代码会生成一个相关性矩阵的热力图。通过观察热力图,我们可以识别出高度相关的特征对。

接下来,我们可以基于特征与目标变量的相关性绝对值来选择特征。

# 假设目标变量列名为 'target'
target_corr = correlation_matrix['target'].abs().sort_values(ascending=False)

# 选择与目标变量相关性最高的前N个特征
selected_features = target_corr[1:22].index.tolist()  # 排除目标变量自身,选择前21个

通过这种方法,我们可能从原始的30个特征中剔除了7个高度相关或与目标无关的特征,最终得到21个特征。

使用这个特征子集训练模型后,我们可能会发现:

  • 准确率有所提升。
  • AUC(曲线下面积)有所提升。
  • 精确率有所提升。
  • 召回率保持不变(至少到小数点后五位)。
  • F1分数略有提升。

移除冗余特征不仅提升了几乎所有评估指标,还减少了处理21个特征(而非30个)所需的计算资源。这可能是我们目前得到的最佳结果。

单变量特征选择

现在,让我们看看单变量特征选择。我们将使用 scikit-learn 库来实现。

scikit-learn 提供了多种单变量特征选择工具:

  • SelectKBest:选择得分最高的K个特征。
  • SelectPercentile:选择得分最高的指定百分比的特征。
  • GenericUnivariateSelect:一个通用的单变量选择器,可以通过策略参数配置。
  • 可用的统计检验包括:
    • 对于回归问题:互信息和F检验。
    • 对于分类问题:卡方检验、分类专用的F检验版本以及分类专用的互信息版本。

以下是使用卡方检验进行单变量特征选择的代码示例:

from sklearn.feature_selection import SelectKBest, chi2
from sklearn.preprocessing import StandardScaler, MinMaxScaler
from sklearn.model_selection import train_test_split

# 分割数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 数据标准化(某些特征选择方法需要)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

# 也可以使用 MinMaxScaler
# scaler = MinMaxScaler()

# 初始化选择器,使用卡方检验选择最好的20个特征
selector = SelectKBest(score_func=chi2, k=20)

![](https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-ml-engi-prod-prac/img/60cbcfab27d17dea9a1cbf310312f8ac_6.png)

# 在训练集上拟合并转换
X_train_selected = selector.fit_transform(X_train_scaled, y_train)
X_test_selected = selector.transform(X_test_scaled)

# 获取被选中的特征索引或名称
selected_feature_indices = selector.get_support(indices=True)
selected_feature_names = X.columns[selected_feature_indices]

print("Selected features:", selected_feature_names)

这段代码定义了一个用于单变量选择的函数。它接收已分割的训练集和测试集,使用 StandardScalerMinMaxScaler 进行缩放,然后使用 SelectKBest 结合卡方检验来寻找最佳的20个特征。通过 fit_transform 得到选中的特征,并在原始数据集中剔除其他特征。

那么它的性能如何呢?
使用卡方检验的单变量测试要求选择20个特征,因此我们得到了20个特征。

  • 准确率略有下降。
  • AUC略有下降。
  • 精确率略有下降。
  • 有趣的是,召回率仍然完全相同。
  • 遗憾的是,F1分数也略低一些。

因此,基于相关性分析的方法(得到21个特征)仍然是我们目前的最佳结果。


总结

本节课中我们一起学习了特征选择中的过滤法。我们了解到过滤法是一种基于统计指标(如相关性)来评估特征重要性的监督式方法。我们探讨了皮尔逊相关、卡方检验等具体技术,并通过代码示例演示了如何计算相关性矩阵、可视化特征关系以及使用 scikit-learn 进行单变量特征选择。实践表明,通过移除冗余特征,我们可以在提升模型性能的同时降低计算复杂度。虽然不同的过滤方法可能产生不同数量的特征和模型表现,但核心目标始终是找到最有效、最简洁的特征子集。

063:包装法特征选择 📦

在本节课中,我们将学习特征选择中的“包装法”。包装法是一种监督式特征选择方法,它通过迭代搜索,并使用一个机器学习模型来评估特征子集的有效性,从而找到最优的特征组合。

上一节我们介绍了基于统计的过滤法,本节中我们来看看如何使用模型本身来指导特征选择。

包装法的工作原理

包装法的工作方式有所不同。它仍然是一种监督方法,但会与一个具体的模型结合使用。其核心思想是:通过迭代搜索特征空间,并使用选定模型的性能作为衡量特征子集优劣的指标。

基本流程如下:

  1. 从所有特征开始。
  2. 生成一个特征子集。
  3. 将该子集输入模型进行训练和评估。
  4. 根据模型性能(作为反馈),生成下一个待评估的特征子集。
  5. 重复此过程,直至找到性能最优的特征子集。

这样就形成了一个使用模型性能作为度量的反馈循环,最终选出最佳特征子集。

常见的包装法

以下是几种常用的包装法实现策略。

前向选择

前向选择是一种迭代的贪心算法。

  • 起点:从一个空特征集或单个特征开始。
  • 过程:每次迭代中,尝试添加一个尚未使用的特征,并评估模型性能。选择能带来最大性能提升的那个特征加入集合。
  • 终止:重复此过程,直到添加任何新特征都无法显著提升模型性能。

后向消除

理解了前向选择,后向消除就很容易想象了。

  • 起点:从包含所有特征的全集开始。
  • 过程:每次迭代中,尝试移除一个现有特征,并评估模型性能。移除对性能影响最小的那个特征(或移除后性能下降最少的特征)。
  • 终止:重复此过程,直到移除任何特征都会导致模型性能显著下降。

递归特征消除

递归特征消除是另一种强大的包装法。

  • 步骤1:选择一个能评估特征重要性的模型(例如,随机森林、线性模型)。
  • 步骤2:设定最终想要保留的特征数量。
  • 步骤3:用全部特征训练模型,并根据模型输出对特征进行重要性排序。
  • 步骤4:丢弃重要性最低的特征。
  • 步骤5:用剩余的特征重复步骤3和4,直到特征数量达到预设目标。

一个重要的前提是:所使用的模型必须能够提供特征重要性度量,并非所有模型都具备此功能。

递归特征消除代码示例

让我们通过代码来看看递归特征消除的具体实现。以下示例使用 scikit-learn 库中的 RFECV(带交叉验证的递归特征消除)。

# 导入必要的库
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestClassifier
from sklearn.feature_selection import RFECV
from sklearn.metrics import accuracy_score

# 1. 准备数据(这里使用模拟数据)
X, y = make_classification(n_samples=1000, n_features=50, n_informative=20, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 2. 特征缩放(通常是个好习惯)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

# 3. 选择基础模型(此处使用能提供特征重要性的随机森林)
model = RandomForestClassifier(n_estimators=100, random_state=42, criterion='entropy')

![](https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-ml-engi-prod-prac/img/f35c45c39677c9820ca8511a359bbd6d_2.png)

# 4. 创建递归特征消除器,使用交叉验证自动选择最佳特征数量
rfecv = RFECV(estimator=model, step=1, cv=5, scoring='accuracy')
rfecv.fit(X_train_scaled, y_train)

# 5. 输出结果
print(f"最优特征数量: {rfecv.n_features_}")
print(f"被选中的特征掩码: {rfecv.support_}")
print(f"特征排名(1为最佳): {rfecv.ranking_}")

# 6. 使用选出的特征转换数据集
X_train_selected = rfecv.transform(X_train_scaled)
X_test_selected = rfecv.transform(X_test_scaled)

# 7. 用选出的特征重新训练并评估最终模型
final_model = RandomForestClassifier(n_estimators=100, random_state=42)
final_model.fit(X_train_selected, y_train)
y_pred = final_model.predict(X_test_selected)
accuracy = accuracy_score(y_test, y_pred)
print(f"使用 {rfecv.n_features_} 个特征后的模型准确率: {accuracy:.4f}")

在这段代码中:

  1. 我们生成了包含50个特征的数据集,其中只有20个是真正有信息的。
  2. 使用 RandomForestClassifier 作为评估特征重要性的基础模型。
  3. RFECV 对象会通过交叉验证自动决定最优的特征数量。
  4. 最终,我们使用筛选出的特征子集训练了一个新模型,并评估其性能。

方法对比与总结

与之前介绍的单变量过滤法相比,递归特征消除的表现如何?

在课程示例中,递归特征消除成功地将特征数量缩减到了目标值(20个)。其模型准确率、AUC(曲线下面积)和召回率等指标,均与基于相关性的过滤法表现相当,甚至在某些指标(如F1分数)上略有优势。同时,它使用的特征数量(20个)比相关性方法(21个)更少。

因此,在这个具体案例中,递归特征消除取得了最佳的综合结果

本节课中我们一起学习了特征选择的包装法。我们了解了其核心思想是利用模型性能作为反馈来迭代搜索最优特征子集,并介绍了前向选择、后向消除和递归特征消除三种具体策略。最后,我们通过代码示例演示了递归特征消除的实现过程,并看到它能够有效地平衡特征数量与模型性能。

064:第23课 嵌入法 🧩

在本节课中,我们将要学习特征选择的第三种主要方法:嵌入法。嵌入法是一种监督式的特征选择技术,它将特征选择过程与模型训练本身紧密结合。

上一节我们介绍了包装法,本节中我们来看看嵌入法。

什么是嵌入法? 🤔

嵌入法是一种监督式的特征选择方法。它与我们之前学习的过滤法和包装法不同,其核心在于特征选择过程是模型训练流程的一个内在组成部分

以下是嵌入法的两个主要示例:

  • L1或L2正则化:本质上是一种通过惩罚项进行特征选择的嵌入方法。
  • 特征重要性:另一种嵌入方法,直接评估模型中每个特征的贡献度。

这两种方法都与你所使用的模型高度相关。L1正则化和特征重要性更像是你所使用模型的一种固有特性。它们为数据中的每个特征分配分数或权重,并通过将某些特征的权重设置为零或接近零来“丢弃”这些特征,从而实现特征选择。

在Scikit-learn中实现嵌入法 💻

在Scikit-learn中,我们可以利用基于树的模型内置的feature_importance_属性。

我们继续使用贯穿本课程的随机森林分类器作为示例模型,这是一种包含特征重要性属性的模型类型。

我们可以使用SelectFromModel来根据模型分配的特征重要性分数,从已训练的模型中选择特征。这再次体现了嵌入法与模型本身的紧密联系。

代码实现步骤

以下是基于树模型计算特征重要性的函数实现步骤:

  1. 准备数据:数据已被分割为训练集和测试集,并且标签已被分离。
  2. 定义模型:使用随机森林分类器。
  3. 训练模型:在训练数据上拟合模型。
  4. 提取特征重要性:从训练好的模型中提取feature_importances_属性,这将得到一个Pandas Series序列。
  5. 选择特征:从该序列中选择重要性得分最高的前10个特征并进行展示。

可视化与特征选择

执行上述步骤后,我们可以得到特征重要性的可视化图表。图表展示了模型计算出的最重要的10个特征。

接下来,我们利用这些信息进行特征选择:

  1. 使用SelectFromModel根据重要性阈值选择特征,得到一个新的模型转换器。
  2. 调用get_support()方法获取被选中特征的索引。
  3. 根据这些索引,从原始特征向量中删除未被选中的特征,从而得到我们最终保留的特征名称列表。

性能评估

将上述步骤整合后,我们首先通过feature_importance_from_tree_based_model函数计算并绘制特征重要性,然后基于此选择要保留的特征,最后评估模型性能。

在本案例中,我们最终选择了14个特征。观察其性能指标:

  • 准确率略有下降。
  • ROC-AUC略有上升,几乎回到了使用全部特征时的水平。
  • 精确率略有下降。
  • 召回率基本保持不变。
  • F1分数回到了使用全部特征时的水平。

方法对比与选择考量 ⚖️

递归特征消除法(RFE)目前仍然是我们得到的最佳结果。然而,通过特征重要性嵌入法,我们成功将特征数量减少到了14个。

这里出现了一个需要权衡的问题:我们更看重性能指标,还是更看重降低计算资源消耗?

  • 如果节省计算资源至关重要,我们可能会选择使用特征重要性法筛选出的14个特征。
  • 如果我们更关注维持或提升模型性能指标,那么递归特征消除法(RFE)仍然是更好的选择。

本周内容总结 📚

本周我们涵盖了大量内容:

  1. 我们首先介绍了数据预处理的基础知识。
  2. 我们深入探讨了特征工程及其在机器学习,尤其是生产环境中的重要性。
  3. 我们学习了大规模数据预处理,这在处理海量数据或大型模型时至关重要,并特别介绍了TensorFlow Transform工具。
  4. 我们研究了特征空间,理解了它的工作原理以及在特征选择时为何需要考虑它。
  5. 我们详细学习了三种不同的特征选择方法:过滤法包装法嵌入法

本节课中我们一起学习了嵌入法特征选择,理解了其如何将选择过程嵌入模型训练,并通过代码实践了基于特征重要性的选择流程。至此,关于数据处理和特征工程,我们已经学习了相当丰富的内容。

065:数据之旅与存储 📊

在本节课中,我们将学习数据在机器学习生产流程中的流转过程(数据之旅),以及如何有效地存储和管理数据。我们将重点探讨元数据、数据模式(Schema)以及数据版本控制等核心概念,这些对于理解数据演变、确保实验可复现性至关重要。


数据之旅:理解数据的生命周期 🔄

上一节我们介绍了课程的整体安排,本节中我们来看看数据在生产流水线中的完整旅程。理解数据来源(Data Provenance)需要理解数据在整个生产流水线生命周期中的流转过程,更具体地说,是关注数据和模型在整个流程中的演变。

ML元数据(ML Metadata)是一个用于应对这些挑战的多功能库,它有助于调试和保证可复现性。具体而言,它允许我们回顾和追踪在训练过程中发生的数据和模型变化。

理解数据来源始于数据之旅。这段旅程从我们拥有的各种来源的原始特征和标签开始。数据描述了一个函数,该函数将训练集中的输入映射到我们试图预测的标签。在训练期间,模型学习从输入到标签的函数映射,以尽可能达到高准确度。

数据作为训练过程的一部分会发生转换和变化。当数据在流程中流动时,它会经历转换,例如改变数据格式、应用特征工程以及训练模型进行预测。

理解这些数据转换与解释模型结果之间存在双重联系。因此,密切追踪和记录这些变化非常重要。

以下是数据转换的几个关键环节:

  • 数据格式转换:例如,从CSV文件转换为TFRecord格式。
  • 特征工程:应用如标准化、归一化或创建新特征等操作。
  • 模型训练:数据被用于调整模型参数以进行预测。

数据工件与溯源 📦

流水线组件执行时会创建数据工件(Data Artifacts)。那么,究竟什么是工件?每当一个组件产生结果时,它就会生成一个工件。这基本上包括了流水线产生的一切,包括不同转换阶段的数据(通常是特征工程的结果)、模型本身,以及模式(Schema)、指标等等。基本上,产生的每一个结果都是一个工件。

术语“数据来源”(Data Provenance)和“数据谱系”(Data Lineage)基本上是同义词,可以互换使用。数据来源或谱系,是我们在流水线中移动时所创建的工件序列。这些工件与我们创建的代码和组件相关联。

追踪这些序列对于调试、理解训练过程以及比较可能相隔数月发生的不同训练运行至关重要。数据来源非常重要,它帮助我们理解流水线并进行调试。

调试和理解需要检查训练过程中每个点的那些工件,这可以帮助我们理解这些工件是如何创建的,以及结果的实际含义。溯源还允许你从流程中的任何一点回溯整个训练运行。

此外,溯源使得比较不同训练运行并理解它们产生不同结果的原因成为可能。根据GDPR(通用数据保护条例),组织需要对个人数据的来源、变更和位置负责。个人数据高度敏感,因此追踪其在流水线中的来源和变化是合规的关键。

数据谱系是企业和组织快速确定数据如何被使用以及在流经流水线时执行了哪些转换的好方法。因此,数据溯源是解释模型结果的关键。模型理解与此相关,但只是其中一部分。模型本身是训练集中数据的一种表达。因此,在某种意义上,我们可以将模型视为数据的一种转换。溯源还有助于我们理解模型在训练和优化过程中是如何演变的。


数据版本控制 🔄

让我们在此添加一个重要成分:追踪不同的数据版本。管理数据流水线是一个巨大的挑战,因为数据会随着项目在多次不同训练运行中的自然生命周期而演变。一个正确执行的机器学习项目,应该能够产生可以相当一致地复现的结果。自然会有一些差异,但结果应该接近。

代码版本控制可能是你熟悉的概念。GitHub是最流行的基于云的代码仓库之一,当然还有其他选择。环境版本控制也很重要,因此像Docker和Terraform这样的工具帮助我们创建可重复的环境和配置。

然而,数据版本控制同样重要,并且在追踪来源和谱系方面扮演着重要角色。数据版本控制本质上是数据文件的版本控制,以便你可以追踪随时间发生的变化并在需要时恢复早期版本。

但是,相关工具有些不同,原因之一是我们处理的文件大小。这些文件通常(或可能)比代码文件大得多。因此,用于数据版本控制的工具才刚刚开始出现,其中包括DVC和Git LFS(LFS代表大文件存储)。


总结 📝

本节课中,我们一起学习了数据在机器学习生产流程中的完整旅程。我们探讨了如何通过追踪数据工件和理解数据谱系来确保流程的可解释性与可复现性。同时,我们认识到数据版本控制与代码、环境版本控制同等重要,是管理数据演变、支持调试和合规要求的关键工具。掌握这些概念,是构建可靠、可维护的机器学习系统的基础。

066:机器学习元数据简介 📊

在本节课中,我们将要学习机器学习元数据(ML Metadata,简称MLMD)的基本概念、架构及其在生产环境中的重要性。元数据是记录机器学习工作流中各个组件、执行过程和生成结果的关键信息,它对于调试、审计和理解模型训练过程至关重要。


现在我们来讨论元数据。在讨论这个话题时,需要考虑法律和监管方面的因素。

随着机器学习越来越多地用于做出重要的商业决策、医疗决策和金融决策,法律责任成为一个因素。能够解释模型,并能够追溯用于训练模型的数据的血统或来源,对于限制风险暴露变得越来越重要。

好的,让我们开始吧。现在让我们开始探索机器学习元数据如何帮助你在生产生命周期中跟踪工件和流水线变更。


什么是机器学习元数据?🔍

上一节我们提到了元数据的重要性,本节中我们来看看它的具体定义和作用。

生产机器学习流水线的每次运行都会生成元数据,这些元数据包含关于各个流水线组件及其执行(或训练运行)的信息,以及生成的工件(例如,训练好的模型)。在流水线行为异常或出现错误的情况下,可以利用这些元数据来分析流水线组件的血统,并帮助你调试问题。

可以将这些元数据视为软件开发中的日志记录。机器学习元数据帮助你理解和分析机器学习流水线中所有相互关联的部分,而不是孤立地分析它们。


元数据在流水线中的作用 🏗️

上一节我们介绍了元数据的定义,本节中我们来看看它在实际流水线中是如何工作的。

考虑你目前看到的机器学习工程中的两个阶段。首先,你进行了数据验证。然后,你将结果传递给数据转换或特征工程。这是任何模型训练过程的第一部分。

但是,如果你有一个集中式的存储库,每次运行一个组件时,都将该阶段的结果、更新或任何其他输出存储到该存储库中,会怎样呢?这样,每当任何更改导致不同结果时,你无需担心到目前为止取得的进展丢失,你可以检查之前的结果,试图理解发生了什么,并进行纠正或利用改进。

让我们更仔细地看一下。除了运行代码的执行器之外,每个组件还包括两个额外的部分:驱动程序和发布器。

  • 执行器:组件工作完成的地方,这也是不同组件之间的区别所在。
  • 驱动程序:为执行器提供所需的任何输入,这些输入从元数据存储中获取。
  • 发布器:将运行执行器的结果推送回元数据存储。

大多数时候,你不需要自定义驱动程序或发布器。创建自定义组件几乎总是通过创建自定义执行器来完成。


机器学习元数据(MLMD)库 📚

上一节我们了解了组件结构,本节中我们专门看看机器学习元数据库。

机器学习元数据是一个用于跟踪和检索与机器学习开发者和数据科学家工作流相关的元数据的库。机器学习元数据可以作为机器学习流水线的一个组成部分使用,也可以独立使用。然而,当与机器学习流水线集成时,你可能甚至不需要显式地与机器学习元数据对象交互。

存储在机器学习元数据中的对象被称为工件。机器学习元数据在关系数据库中存储每个工件的属性,并将大型对象(如数据集)存储在磁盘、文件系统或块存储中。

当你使用机器学习元数据时,需要了解数据如何在不同的连续组件之间流动。这个数据流中的每一步都通过一个你需要熟悉的实体来描述。


机器学习元数据的数据实体 🧱

上一节我们提到了“实体”,本节中我们来详细看看机器学习元数据中的核心数据实体。

在机器学习元数据的最高层级,有一些可以被视为单元的数据实体。

以下是这些核心实体:

  • 工件:输入到机器学习元数据存储中的基本数据单元,作为每个组件的输入被消耗或作为输出生成。
  • 执行:机器学习流水线工作流期间任何组件运行的记录,及其相关的运行时参数。
  • 上下文:用于将同一类型组件的工件和执行聚类在一起的分组。一个上下文可能包含正在运行的项目、正在进行的实验、流水线详情等的元数据。
  • 类型:定义存储在元数据中的各种单元(如工件类型、执行类型)的模板,包括该类型的属性。
  • 关系:存储与其他单元交互时生成或消耗的各种单元之间的关系。例如,事件是记录工件与执行之间关系的记录。

所以,机器学习元数据存储了关于流水线组件结果和执行运行的广泛信息。它存储工件,存储流水线中每个组件的执行,还存储每个生成的工件的血统信息。所有这些信息都表示在元数据对象中,并且这些元数据存储在后端存储解决方案中。


机器学习元数据架构 🏛️

上一节我们介绍了核心实体,本节中我们来看看它们是如何组织在一起的。

让我们看一下机器学习元数据的架构。顶部是任何机器学习流水线中存在的各种组件。所有这些组件都单独连接到一个集中的机器学习元数据存储,以便每个组件可以在流水线的任何阶段独立访问元数据。

一个机器学习流水线可以选择性地拥有一个图形用户界面控制台,可以直接从元数据存储访问数据,以跟踪每个组件的进度。

在元数据存储的核心是工件,它由其对应的工件类型描述。工件成为任何依赖它们的流水线组件的输入,而组件对工件的相应使用记录在执行中。

工件输入到组件由输入事件描述,组件输出新工件由输出事件描述。工件和执行之间的这种交互通过归因和关联的关系由上下文表示。

最后,元数据存储生成的所有数据都存储在各种类型的后端存储中,如SQLite和MySQL,大型对象则存储在文件系统或块存储中。


总结 📝

本节课中我们一起学习了机器学习元数据的架构和术语,以及包含其中的工件和实体。这应该让你对如何利用机器学习元数据来跟踪元数据和流经流水线的结果有了初步了解,从而更好地理解你当前以及之前流水线训练运行的过程。

067:机器学习元数据实战 🧠 - 课程 P67

在本节课中,我们将学习如何使用机器学习元数据(ML Metadata)库,并通过一个具体的编码示例来理解其核心功能,包括数据溯源、组件执行图的构建以及实验结果的追踪与比较。


配置存储后端

首先,我们需要设置 ML Metadata 的存储后端。MetadataStore 是一个数据库,用于注册与项目相关的所有元数据。ML Metadata 提供了连接多种数据库的 API,包括用于快速原型设计的伪数据库、SQLite 和 MySQL。此外,我们还需要一个块存储或文件系统来存储数据集等大型对象。

以下是三种主要存储后端的配置方法:

伪数据库(内存存储)

from ml_metadata import metadata_store
from ml_metadata.proto import metadata_store_pb2

![](https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-ml-engi-prod-prac/img/725504f5697ac8ee7300639e8c71b1eb_6.png)

connection_config = metadata_store_pb2.ConnectionConfig()
connection_config.fake_database.SetInParent()  # 使用内存数据库
store = metadata_store.MetadataStore(connection_config)

SQLite 数据库

connection_config = metadata_store_pb2.ConnectionConfig()
connection_config.sqlite.filename_uri = ‘./my_metadata.db’
connection_config.sqlite.connection_mode = 3  # READWRITE_OPENCREATE 模式
store = metadata_store.MetadataStore(connection_config)

MySQL 数据库

connection_config = metadata_store_pb2.ConnectionConfig()
connection_config.mysql.host = ‘localhost’
connection_config.mysql.port = 3306
connection_config.mysql.database = ‘metadata_db’
connection_config.mysql.user = ‘root’
connection_config.mysql.password = ‘password’
store = metadata_store.MetadataStore(connection_config)

无论使用哪种存储,store 对象都是与 ML Metadata 交互的核心。


结合 TFDV 的工作流示例

上一节我们介绍了如何配置存储后端,本节中我们来看看如何将 ML Metadata 应用于解决实际问题。我们将通过一个结合 TensorFlow Data Validation(TFDV)的工作流示例进行说明。

本实验选用一个包含多个特征的表格数据集。在完整的机器学习流水线中,ML Metadata 能够自动理解组件间的数据流并执行其必要职责。但为了帮助初学者更好地理解其原理,本实验将在流水线之外显式地编程使用 ML Metadata。实验还将展示 ML Metadata 与 TFDV 的集成。

通过本实验,您将直观了解 ML Metadata 如何跟踪进度,以及如何利用它来追踪训练过程和流水线。


核心优势与应用

除了数据溯源,使用 ML Metadata 还能带来其他几项好处。

构建执行有向无环图(DAG)
ML Metadata 能够构建流水线中组件执行的有向无环图。这对于调试非常有用,您可以验证某次执行中具体使用了哪些输入。

汇总与比较实验结果
您可以汇总一系列实验后生成的所有特定类型的工件。例如,您可以列出所有训练过的模型,然后对它们进行比较,以评估不同的训练运行效果。


课程总结

在本节课中,我们一起学习了以下内容:

  1. 首先,我们了解了用于应对 ML 流水线生命周期中数据演变问题的数据溯源概念。
  2. 接着,我们探讨了用于追踪这些数据变化的元数据
  3. 然后,我们审视了 ML Metadata 库的架构
  4. 最后,在未评分的实验中,您运行了一个示例,注册了工件、执行过程和上下文,进行了实际操作。

通过以上学习,您应该对 ML Metadata 的核心功能及其在机器学习工程化中的实践价值有了初步的认识。

068:27_模式开发 🧩

在本节课中,我们将学习数据演进过程中的模式开发。你将了解如何为企业级模式环境进行开发,以及如何迭代式地创建和维护企业数据模式。模式在生产环境机器学习中应用广泛,因此我们先快速回顾一下模式是什么,以及它们为何如此重要。

什么是模式?📋

模式是一种关系型对象,用于总结给定数据集或项目中的特征。它包含以下信息:

  • 特征名称
  • 特征变量类型,例如整数、浮点数、字符串或分类变量。
  • 特征是否为必需项
  • 特征的有效性,这适用于具有多个值的特征(如列表或数组特征),并规定了最小和最大值的数量。
  • 关于取值范围和类别的信息
  • 特征默认值

模式之所以重要,是因为你的数据和特征集会随着时间不断演进。从经验可知,数据总是在变化,而这种变化常常导致数据分布的改变。

数据演进与模式调整 🔄

上一节我们介绍了模式的基本构成,本节中我们来看看数据如何变化以及如何应对。数据变化常常导致生成新的模式。然而,存在一些特殊用例。

例如,即使在评估数据集之前,你可能已经对特征的预期取值范围有所了解,而你收到的初始数据集仅覆盖了该范围的一小部分。在这种情况下,调整或精心设计你的模式以反映特征的预期取值范围是合理的。

类似的情况也可能出现在分类特征的预期值上。此外,你的模式可以帮助你发现数据集中的问题或异常,例如缺失必需值或值类型错误。

在设计机器学习流水线的模式时,必须考虑所有这些因素。

生产环境的要求 ⚙️

随着数据不断演进,在生产和部署中必须满足一些要求。以下是几个重要的考虑因素:

可靠性:你所选择的机器学习运维平台应能抵御不一致数据带来的干扰。无法保证每次都能收到干净一致的数据。事实上,几乎可以肯定不会。你的系统需要被设计成能高效处理这种情况。此外,你的软件可能会产生意外的运行时错误,你的流水线也需要优雅地处理这些问题。配置错误的问题应被检测并优雅地处理。最重要的是,流水线中不同组件之间的执行编排应平稳高效地进行。

可扩展性:在数据演进过程中,你的机器学习流水线平台需要考虑的另一个因素是可扩展性。在训练期间,你的流水线可能需要妥善处理大量训练数据,包括在运行昂贵加速器(如GPU和TPU)时保持其忙碌状态。在服务模型时,尤其是在线场景(如在服务器上运行),你几乎总会遇到不同级别的请求流量。你的基础设施需要能够向上和向下扩展,以满足这些延迟要求,同时最小化成本。

处理数据演进的重要性 🚨

如果你的系统没有设计成能处理数据演进,它将很快遇到问题。这些问题包括:

  • 数据集中引入异常。你的系统能检测到这些异常吗?
  • 你的系统和开发流程应被设计成将数据错误视为一等公民,就像处理代码中的错误一样。
  • 在某些情况下,这些异常会提醒你需要更新模式以适应数据中的有效变化。

你的模式的演进可以成为理解和跟踪数据演进的有用工具。此外,模式可以作为自动化流程的关键输入,这些流程处理你的数据,例如自动特征工程。

总结 📝

本节课中,我们一起学习了模式开发的核心概念。我们回顾了模式的定义及其包含的关键信息,探讨了数据演进如何影响模式,并强调了在生产环境中设计可靠、可扩展的机器学习流水线以应对数据变化的重要性。记住,模式不仅是数据的静态描述,更是理解和适应数据动态变化的强大工具。

069:模式环境 🧩

在本节课中,我们将要学习模式环境的概念及其在机器学习生产管道中的重要性。随着业务和数据的发展,数据模式也会随之演变。我们将探讨如何管理多个模式版本,以及如何利用模式环境来检测和处理数据异常,确保模型的可靠性和可扩展性。


现在我们来讨论模式环境。你的业务和数据在整个生产管道的生命周期中都会不断演变。

通常情况下,随着数据的演变,你的模式也会演变。

当你开发代码来处理模式变化时,你可能同时有多个版本的模式处于活动状态。

你可能有一个用于开发的模式,一个当前正在测试的模式,以及另一个当前正在生产环境中使用的模式。对你的模式进行版本控制,就像对你的代码进行版本控制一样,有助于管理这种情况。

在某些情况下,你可能需要不同的模式来支持不同数据环境下的多种训练和部署场景。

例如,你可能希望在服务器和移动应用程序上使用相同的模型。

但想象一下,某个特定特征在这两种环境中是不同的,可能在一个环境中是整数,而在另一个环境中是浮点数。你需要为每种情况使用不同的模式,以反映数据的差异。

与此同时,你的数据正在演变,可能在你所有不同的数据环境中同时进行。

但同时,你还需要检查数据是否存在问题或异常,而模式是检查异常的关键部分。


让我们看一个例子,了解模式如何帮助你检测服务请求数据中的错误,以及为什么多个模式版本很重要。

我们将从推断服务模式开始,并使用 TensorFlow Data Validation(TFTV)来完成这个任务。

然后,我们将为服务数据集生成统计信息。

接着,我们将使用 TFTV 来查找此数据是否存在任何问题,并在笔记本中可视化结果。


哦,看这里。TFDV 报告称服务数据中存在异常。

但由于这是一个包含预测请求的数据集,这实际上并不令人惊讶。

标签(即覆盖类型)缺失了,但模式告诉 TFTV 覆盖类型特征是必需的,因此它将其标记为异常。我们如何解决这个问题?

在需要维护同一模式的多种类型的情况下,你通常需要保留模式环境。这在训练数据和服务数据之间的差异中最为常见。

你可以根据要处理的情况选择自定义模式。例如,在这种情况下,设置是维护两个模式:一个用于训练数据(其中标签是必需的),另一个用于服务(我们知道不会有标签)。


多个模式环境的代码相当直接。在我们现有的环境中,我们已经有了一个训练模式。

然后,我们创建两个名为 trainingserving 的环境。

我们通过移除覆盖类型特征来修改服务环境,因为我们知道在服务中,我们的特征集中不会有该特征。

最后,代码设置服务环境并使用它来验证服务数据。现在,由于我们为数据使用了正确的模式,没有发现异常。


那么,让我们回顾一下。首先,我们讨论了如何迭代更新和微调你的模式以适应不断演变的数据。

然后,我们关注了数据演变周期中的可靠性和可扩展性。

接着,你实现了模式环境来处理服务数据中的异常。


本节课中,我们一起学习了模式环境的核心概念。我们了解到,随着数据和业务需求的变化,维护多个模式版本是必要的。通过创建不同的模式环境(如训练环境和服务环境),我们可以有效地处理数据差异并检测异常,从而确保机器学习管道在生产中的稳定运行。

070:特征存储 🗄️

在本节课中,我们将要学习数据存储的核心概念之一——特征存储。我们将探讨它的定义、价值、工作原理以及在实际应用中的关键考量。

接下来三个主题,我们将讨论数据存储。这三个部分没有需要提交的作业,但我强烈建议你认真学习。这里包含了一些非常重要的信息,尤其是关于特征存储的部分,正变得越来越重要。不过,根据你所在的环境和已有资源,你可能需要利用数据仓库或数据湖,因此理解这些概念也变得至关重要。现在,让我们开始学习。

现在,我们转向应该在哪里存储数据的问题。我们将从讨论特征存储开始。


什么是特征存储?🤔

特征存储是一个用于存储经过文档化、精心整理且访问受控的特征的中央仓库。使用特征存储能使团队共享、发现和使用这些高质量的特征。特征存储让特征的发现和消费变得容易。

特征可以同时用于在线或离线场景,服务于模型训练和预测。

人们常常发现,许多建模问题会使用相同或相似的特征。因此,相同的数据经常在多个建模场景中被使用。在许多情况下,特征存储可以被视为特征工程和模型开发之间的接口。

特征存储是有价值的、集中的特征仓库,它能减少冗余工作。它们之所以有价值,还因为它们使团队能够共享数据,并发现已有的可用数据。一个组织内可能有不同的团队在解决不同的业务问题,但他们可能在使用完全相同或非常相似的数据。基于这些原因,对于大型项目和组织的机器学习应用,特征存储正成为企业数据存储的主流选择。


特征存储的功能与优势 ⚙️

以下是特征存储提供的一些关键功能:

  • 数据处理与转换:特征存储通常允许对数据进行转换,从而避免在不同的独立流水线中重复进行相同的处理。
  • 访问控制:对特征存储中数据的访问可以基于角色权限进行控制。
  • 特征聚合与衍生:存储中的数据可以被聚合以形成新的特征。
  • 数据治理:数据可以被匿名化,甚至根据法规要求(例如为符合GDPR的“被遗忘权”)进行清除。

离线与在线特征处理 🔄

上一节我们介绍了特征存储的基本功能,本节中我们来看看它在不同场景下的具体应用。

特征处理通常分为离线和在线两种模式。

对于离线处理,这可以定期进行,例如通过一个定时任务。想象一下,你需要运行一个任务来摄取数据,然后可能对其进行一些特征工程,并从中生成额外的特征(例如特征交叉)。这些新特征也会被发布到特征存储中。在处理和调整数据时,你还可以将其与监控工具集成,再次进行离线监控。这些处理后的特征被存储起来供离线使用。

对于在线特征使用,当预测需要实时返回时,延迟要求通常非常严格。你需要确保能快速访问数据。例如,如果你需要将用户账户信息与单个预测请求进行关联,这种关联操作必须快速完成。这很好,但通常很难在线以高性能的方式计算某些特征。因此,预先计算并存储这些特征通常是个好主意。如果你预先计算并存储了这些特征,那么之后就可以以较低的延迟使用它们。

你也可以在批处理环境中进行类似操作。同样,你不希望延迟太长,但要求可能不像在线请求那样严格。


关键考量:避免数据穿越 🚫

从预先计算和加载(尤其是历史特征)的角度看,过程往往相当简单。对于批处理环境中的历史特征,通常也很直接。

然而,在训练模型时,你需要确保只包含在服务请求发生时可用的数据。包含在服务请求发生之后的某个时间才可用的数据被称为“数据穿越”,许多特征存储都包含防护措施来避免这种情况。此外,这违反了物理定律,我们不应该这样做。

你可能会每隔几小时或每天定时进行预计算。当然,为了避免训练-服务偏差,你将使用相同的数据进行训练和服务。


特征存储的设计目标 🎯

大多数特征存储的目标是提供一种统一的管理特征数据的方法,这种方法可以从单个人扩展到大型企业。它需要具备高性能。你希望在训练模型和服务模型时都尝试使用相同的数据。

你需要一致性,并能按时间点正确访问特征数据。例如,你希望避免在服务模型时,使用未来才可用的数据来进行预测。换句话说,如果你试图预测明天早上会发生的事情,你要确保没有包含来自明天的数据。它应该只包含今天之前的数据。

大多数特征存储提供工具来支持特征发现,并允许你记录特征信息,提供对特征的洞察。


总结 📝

本节课中,我们一起学习了特征存储。我们了解到,特征存储是一个集中化管理、文档化和访问控制特征的中央仓库,它能促进团队协作、减少冗余工作,并确保训练与服务数据的一致性。我们探讨了其离线与在线处理模式,并重点强调了避免“数据穿越”以确保预测有效性的重要性。特征存储是现代机器学习工程中实现高效、可扩展数据管理的关键组件。

071:数据仓库 📊

在本节课中,我们将要学习数据仓库的概念。数据仓库是一种在企业中广泛使用的数据存储解决方案,尤其适用于大数据、商业智能以及生产环境中的机器学习运维(MLOps)。我们将探讨其定义、关键特性、优势以及与常见数据库的区别。


现在,我们来讨论数据仓库。需要说明的是,数据仓库最初是为大数据和商业智能应用而开发的,但它对于生产环境中的机器学习运维同样是一个非常有价值的工具。

一个数据仓库是一种技术,它聚合来自一个或多个来源的数据,以便进行处理和分析。数据仓库通常用于运行时间较长的批处理作业,其存储针对读取操作进行了优化。进入仓库的数据可能不是实时的。当你在数据仓库中存储数据时,你的数据需要遵循一致的模式


上一节我们介绍了数据仓库的基本定义,本节中我们来看看它的一些关键特性。

以下是数据仓库的几个关键特性:

  • 主题导向:存储在其中的信息围绕一个主题展开。例如,数据仓库中的数据可能专注于组织的客户或供应商等。
  • 集成性:数据仓库中的数据可能从多种类型的来源收集,例如关系数据库或文件等。
  • 时变性:收集在数据仓库中的数据通常会打上时间戳,以维护其生成时的上下文。
  • 非易失性:这意味着添加新数据时,不会擦除旧版本的数据。因此,你可以按时间函数访问存储在数据仓库中的数据,并理解数据是如何演变的。

了解了数据仓库的特性后,我们来看看它的主要优势。

以下是数据仓库的一些优势:

  • 增强的分析能力:通过为数据打上时间戳,数据仓库有助于维护上下文,从而增强分析能力。
  • 提高数据质量和一致性:当数据存储在数据仓库中时,它遵循一致的模式,这有助于提高数据质量和一致性。
  • 高投资回报率:研究表明,对于许多用例,数据仓库的投资回报率往往相当高。
  • 高效的读取和查询:数据仓库的读取和查询效率通常很高,能让你快速访问数据。

你可能熟悉数据库,那么一个很自然的问题是:数据仓库和数据库有什么区别?

以下是两者的一些比较:

  • 用途:数据仓库用于分析数据,而数据库通常用于事务处理。
  • 数据可用性:在数据仓库中,存储数据与数据在系统中反映出来之间可能存在延迟。但在数据库中,数据通常在存储后立即可用。
  • 历史数据:数据仓库将数据作为时间的函数存储,因此历史数据也可用。数据库则不一定。
  • 数据规模:与数据库相比,数据仓库通常能够存储更大量的数据。
  • 查询性质:数据仓库中的查询本质复杂,且往往运行时间较长。而数据库中的查询简单,倾向于实时运行。
  • 规范化:数据仓库不一定需要规范化,但数据库应使用规范化。


在本节课中,我们一起学习了数据仓库。我们了解了数据仓库是一种用于聚合和分析数据的存储技术,其关键特性包括主题导向、集成性、时变性和非易失性。我们还探讨了数据仓库在增强分析能力、保证数据一致性等方面的优势,并重点比较了数据仓库与传统数据库在用途、数据可用性、查询方式等方面的主要区别。理解这些概念对于构建高效的数据处理和分析管道至关重要。

072:吴恩达《机器学习工程师的生产实践(MLOps)》第31讲 🏞️

概述

在本节课中,我们将要学习企业级数据存储解决方案中的另一个重要概念——数据湖。我们将探讨数据湖的定义、特点,并将其与之前介绍过的数据仓库进行比较,以帮助你理解它们各自的应用场景和差异。


什么是数据湖?

上一节我们介绍了数据仓库,它是一种面向主题、经过优化用于读取的数据存储库。本节中我们来看看数据湖。

数据湖是一个以数据原始、自然格式存储的系统或存储库。其存储形式通常是二进制大对象或文件。

数据湖与数据仓库类似,也汇聚了来自企业各种数据源的信息。然而,数据湖可以包含多种类型的数据:

以下是数据湖可能包含的数据类型:

  • 结构化数据:例如关系型数据库中的数据。
  • 半结构化数据:例如CSV文件。
  • 非结构化数据:例如图像集合或文档集合等。

由于数据湖以原始格式存储数据,它通常不进行任何处理,也不遵循固定的模式。


数据湖 vs. 数据仓库

了解了数据湖的基本概念后,我们将其与数据仓库进行对比,以明确两者的核心区别。

以下是数据湖与数据仓库的主要区别:

  • 数据格式与模式
    • 数据仓库中,数据以遵循特定模式的一致格式存储。
    • 数据湖中,数据通常以其原始格式存储。
  • 存储目的
    • 数据湖存储数据的目的通常在存储时并未预先确定
    • 数据仓库则通常为特定目的而存储数据。
  • 主要用户
    • 数据仓库常被业务专业人员使用。
    • 数据湖则通常仅由数据科学家等数据专业人员使用。
  • 灵活性与变更成本
    • 由于数据仓库中的数据格式一致,对其进行变更可能复杂且成本高昂
    • 数据湖则更加灵活,更容易对数据进行更改。

企业数据存储方案回顾

在本周的学习中,我们探讨了多种企业数据存储方案。现在,让我们做一个简要的回顾。

首先,你学习了特征存储,它是为机器学习专门设计、高度精选的特征数据存储库。

接着,你了解了面向主题、为读取优化的数据存储库,即数据仓库

最后,我们探索了存储原始、未处理数据的存储库——数据湖


总结

本节课中我们一起学习了数据湖的概念及其与数据仓库的关键区别。我们了解到,数据湖以其存储原始、格式多样的数据以及高度的灵活性,为数据科学家的探索性工作提供了强大的支持。至此,我们完成了本周关于数据存储与管理的重要讨论。期待下次再见!😊

073:半监督学习 🧠

在本节课中,我们将要学习几种高级的数据标注技术,包括半监督标注、主动学习和弱监督。这些技术能帮助我们利用大量未标注数据,降低标注成本,同时提升模型性能。我们首先从半监督学习开始。

概述

机器学习无处不在,而监督学习需要标注数据。手动标注数据通常昂贵且困难,而未标注数据则相对廉价且易于获取。未标注数据中包含大量有助于改进模型的信息。高级标注技术旨在降低标注成本,同时利用大量未标注数据中的信息。

半监督标注

上一节我们概述了高级标注技术的重要性,本节中我们来看看半监督标注的具体工作原理。

半监督标注从一个相对较小、由人工标注的数据集开始。然后,将这个标注数据集与大量未标注数据结合。通过观察不同人工标注类别在特征空间中的聚类或结构方式,来推断未标注数据的标签。最后,使用这两个数据集的组合来训练模型。

这种方法基于一个假设:不同的标签类别会在特征空间内聚集在一起,或具有某种可识别的结构。

使用半监督标注主要有两个优势:

  1. 结合标注和未标注数据可以提高机器学习模型的准确性。
  2. 获取未标注数据通常成本很低,因为它不需要人工分配标签。未标注数据通常可以大量、轻易地获得。

标签传播算法

标签传播是一种为先前未标注的样本分配标签的算法。这使其成为一种半监督算法,其中数据点的子集拥有标签。该算法将标签传播到没有标签的数据点。

以下是其工作原理:
它基于已标注数据点和未标注数据点之间的相似性或社区结构来完成传播。这种相似性或结构被用来为未标注数据分配标签。

例如,在基于图的方法中(如上图所示),你可以看到一些已标注数据(图中的红、蓝、绿色三角形)和大量未标注数据(灰色圆圈)。通过这种方法,根据未标注样本的邻居为其分配标签。然后,标签会传播到集群的其余部分,如图所示的不同颜色。

需要说明的是,实现标签传播有多种不同方法。基于图的标签传播只是其中一种技术。标签传播本身被视为转导学习,这意味着我们直接从样本本身进行映射,而不学习一个映射函数。

总结

本节课中,我们一起学习了半监督学习的基本概念。我们了解到,通过从少量人工标注数据出发,并利用未标注数据在特征空间中的结构来推断其标签,可以有效地扩充训练集。这种方法能够以较低成本利用大量易得的未标注数据,从而潜在地提升模型性能。标签传播是实施半监督学习的一种具体算法示例。

074:主动学习 🎯

在本节课中,我们将要学习一种名为“主动学习”的智能数据采样方法。主动学习旨在通过选择最具预测价值的未标记数据点进行标注,从而高效地提升模型性能。这对于数据标注预算有限、数据集不平衡或标准采样方法效果不佳的场景尤其有用。

什么是主动学习?🤔

主动学习是一种智能的数据采样方式。其核心在于,智能采样会选择那些能为模型带来最大预测价值的未标记数据点。

这种方法在多种情境下都非常有帮助。首先,在数据标注预算有限时,标注数据需要成本,尤其是当需要人类专家查看数据并分配标签时(例如在医疗保健领域)。主动学习有助于抵消这种成本和负担。其次,如果你有一个不平衡的数据集,主动学习是在训练阶段选择稀有类别的高效方法。最后,如果标准采样技术无助于提高准确性或其他目标指标,主动学习可以找到实现或帮助实现所需准确性的途径。

主动学习策略的工作原理是,在完全监督的设置下,选择最能帮助模型学习的样本进行标注。训练数据集仅包含你已标注的样本。在半监督设置中,你还可以利用这些样本来执行某种标签传播,这是对主动学习的补充。

主动学习的典型生命周期 🔄

以下是主动学习的典型工作流程。

  • 初始未标记数据池:你从一个未标记的数据池开始。
  • 智能采样选择:主动学习通过智能采样选择少量样本。
  • 数据标注:你通过人工标注员或其他技术为这些数据添加注释。
  • 生成训练集:这个标注过程会生成一个带标签的训练数据集。
  • 训练与预测:最后,你使用这些已标注的数据来训练模型并进行预测。

这个循环会持续进行。但这引出了一个关键问题:我们如何进行智能采样?

如何进行智能采样?🎯

上一节我们介绍了主动学习的流程,本节中我们来看看一种广泛使用的智能采样技术:边界采样。

在边界采样中,你根据数据点与决策边界的距离,为最不确定的点分配标签。在这个示例中,数据属于两个类别。此外,还有一些未标记的数据点。在此设置下,最简单的策略是训练一个二元线性分类器模型(为了简化示例,我们使用线性模型)。我们在已标记数据上训练该模型,这将得到一个决策边界。

现在,在未标记数据中,最不确定的点是离决策边界最近的点。因此,通过主动学习,你将选择那个最不确定的点进行下一步标注,并将其添加到数据集中。然后,使用这个新标记的数据点作为数据集的一部分,重新训练模型以学习新的分类边界。移动边界后,模型能更好地分离这些类别。接下来,你再次找到最不确定的数据点并重复此过程,直到模型不再改进。

这张图显示了不同采样技术下,模型准确率随训练样本数量变化的函数关系。红线显示了随机选择点进行标注的结果。蓝线和绿线显示了使用主动学习的两种边界采样算法的性能。如图所示,与随机采样技术相比,边界采样方法用更少的训练样本实现了更高的准确率。当然,最终,当未标记数据中有更高比例被标注后,即使是随机采样也能赶上边界采样的性能,但这需要标注多得多的数据。

常见的主动学习采样技术 📊

除了边界采样,还有其他几种常见的主动学习采样技术。

  • 基于聚类的采样:你通过特征空间上的聚类方法,选择一组多样化的点。
  • 委员会查询:你训练多个模型,并选择这些模型之间分歧最大的数据点。
  • 基于区域的采样:这是一种相对较新的算法。概括来说,该算法通过将输入空间划分为不同的区域,并在这些区域内运行主动学习算法来工作。

总结 📝

本节课中我们一起学习了主动学习的概念。主动学习通过智能选择最具信息量的未标记数据进行标注,能够有效降低标注成本、处理不平衡数据集,并更快地提升模型性能。我们探讨了其典型生命周期,并重点介绍了边界采样这一核心方法,同时也简要了解了基于聚类、委员会查询和基于区域等其他采样技术。掌握主动学习,能帮助你在资源有限的情况下更高效地构建机器学习模型。

075:弱监督 📝

在本节课中,我们将学习一种高级数据标注技术——弱监督。我们将了解其核心概念、工作原理以及如何通过Snorkel框架来实践它。


概述

监督学习需要带标签的数据,但数据标注过程通常昂贵、困难且缓慢。为了解决这个问题,我们引入了多种高级标注技术。上一节我们介绍了主动学习,本节中我们来看看最后一种技术:弱监督。这是一种利用来自一个或多个信息源的噪声标签来生成训练数据的方法。


什么是弱监督?🤔

弱监督是一种利用来自一个或多个信息源的信息来生成标签的方法。这些信息源通常是领域专家设计的启发式规则。由此产生的标签是带有噪声的,而非我们习惯的确定性标签。

更具体地说,弱监督包含一个或多个基于未标记数据的噪声条件分布。其主要目标是学习一个生成模型,以确定每个噪声源的相关性。

以下是弱监督流程的核心步骤:

  1. 未标记数据开始。
  2. 添加一个或多个弱监督源。这些源是实现噪声和不完美自动标注的启发式程序列表。
  3. 学习每个监督源的可信度。这是通过训练一个生成模型来完成的。

Snorkel框架 🛠️

Snorkel框架于2016年由斯坦福大学提出,是实施弱监督最广泛使用的框架。它不需要手动标注,而是通过编程方式构建和管理训练数据集。Snorkel提供工具来清理、建模和整合通过弱监督流程产生的训练数据。

使用Snorkel的典型流程如下:

  1. 未标记数据开始。
  2. 应用标注函数。这些是由领域专家设计的、用于生成噪声标签的启发式规则。
  3. 使用生成模型对噪声标签进行去噪,并为不同的标注函数分配重要性权重。
  4. 最后,使用去噪后的标签训练一个判别模型(即你的最终模型)。

标注函数示例 💻

以下是使用Snorkel创建简单标注函数来识别垃圾邮件的代码示例。我们使用多个标注函数来共同决定标签。

首先,从Snorkel导入标注函数:

from snorkel.labeling import labeling_function

然后,定义第一个标注函数。如果消息包含单词“my”,则将其标记为垃圾邮件(这只是一个简单的示例):

@labeling_function()
def lf_contains_my(x):
    return SPAM if "my" in x.text.lower() else ABSTAIN

接着,定义第二个标注函数。如果消息长度超过5个单词,则将其标记为垃圾邮件:

@labeling_function()
def lf_long_message(x):
    return SPAM if len(x.text.split()) > 5 else ABSTAIN

我们所展示的是使用多个标注函数来尝试确定应有的标签。


高级标注技术要点回顾 📋

以下是几种高级标注技术的关键点总结:

  • 半监督学习:一种介于无监督学习和监督学习之间的方法。它通过将少量带标签数据与大量未标记数据相结合来提高学习准确性。
  • 主动学习:依赖于智能采样技术,选择最重要的样本进行标注并添加到数据集中。它在最小化标注成本的同时提高了预测准确性。
  • 弱监督:在监督学习环境中利用噪声、有限或不准确的标签源来生成训练数据集。Snorkel是一个用于管理弱监督所有操作、并建立训练数据集的紧凑且用户友好的系统。

总结

本节课中,我们一起学习了弱监督技术。我们了解到,弱监督通过利用领域专家设计的启发式规则作为噪声标签源,能够以编程方式高效地生成训练数据。借助Snorkel这样的框架,我们可以整合多个标注函数,通过生成模型去噪并加权,最终训练出强大的判别模型。这为解决数据标注瓶颈提供了一种强有力的实践方案。

076:数据增强 📈

在本节课中,我们将学习数据增强技术。数据增强是一种通过修改现有数据或生成合成数据来扩展数据集的方法,旨在提升模型的性能和泛化能力。我们将从基本概念入手,通过一个图像数据增强的实例,最后简要介绍一些高级技术。


概述

上一节我们讨论了通过标注未标注数据来获取更多训练样本的方法。本节中,我们来看看另一种策略:数据增强。数据增强通过对现有数据进行合理的微小修改或扰动,生成新的、有效的训练样本,从而扩大数据集规模并提升其多样性。

什么是数据增强?

数据增强通过向数据集中添加经过轻微修改的现有数据副本,或基于现有数据创建新的合成数据来扩展数据集。

利用现有数据,通过对样本进行微小的改变或扰动,可以创建更多数据。对于图像数据,简单的操作如翻转或旋转,可以轻松地将数据集中的图像数量翻倍或增至三倍。

下图展示了这类变换的示例:

数据增强是提升模型性能的一种方式。它通过添加新的、有效的样本来覆盖特征空间中未被真实样本覆盖的区域,从而改善特征空间的覆盖度。

需要注意的是,如果添加了无效的样本,可能会导致模型学到错误的答案,或至少引入不必要的噪声。因此,务必确保仅以有效的方式进行数据增强。

使用 CIFAR-10 数据集进行实践

CIFAR-10 数据集是加拿大高级研究所收集的一组图像,常用于训练机器学习和计算机视觉模型。它是机器学习研究中使用最广泛的数据集之一。CIFAR-10 包含 60,000 张 32x32 的彩色图像,共有 10 个不同的类别,每个类别有 6,000 张图像。

接下来,我们以 CIFAR-10 数据集为例,实际看看数据增强的过程。我们将对图像进行边框填充,这个新生成的样本是完全有效的。然后,我们将填充后的图像裁剪回 32x32 大小,并根据随机变量(如抛硬币的结果)对填充并裁剪后的图像进行翻转或旋转。这样做的目的是防止模型对特定的旋转或尺度产生过拟合。

由于彩色图像是张量,TensorFlow 提供了非常有用的函数来对图像数据集执行增强操作。

代码示例:左右翻转

以下是封装了执行左右翻转步骤的一段代码:

首先,我们定义一个用于增强图像数据集的函数。

import tensorflow as tf

def augment_image(image):
    # 使用填充或裁剪调整图像大小,这里我们选择填充
    image = tf.image.resize_with_crop_or_pad(image, target_height=40, target_width=40)
    # 随机裁剪回原始尺寸
    image = tf.image.random_crop(image, size=[32, 32, 3])
    # 随机进行左右翻转
    image = tf.image.random_flip_left_right(image)
    return image
  • tf.image.resize_with_crop_or_pad 允许你调整图像大小或进行裁剪,在本例中我们将进行填充。
  • tf.image.random_crop 生成一个指定高度和宽度的裁剪区域,作用于所有通道。
  • tf.image.random_flip_left_right 随机对图像进行左右翻转。

该函数返回修改后的图像,以便将其添加到数据集中。

下图展示了应用填充、裁剪和左右翻转后的一些示例:


其他高级数据增强技术

除了简单的图像操作,还有其他高级的数据增强技术。

例如,半监督数据增强技术,如无监督数据增强(UDA),或使用基于策略的数据增强方法,如 AutoAugment。

右侧是一个电影评论的例子。通过使用策略增强,我们生成了一个变体样本。这样,我们就通过增强得到了一个全新的、完全有效的样本,并且我们可以重复这个过程,生成另一个样本。

总结

本节课中,我们一起学习了数据增强技术。总而言之,数据增强是增加数据集中已标注样本数量的绝佳方法。

  • 它增加了数据集的规模和样本多样性,从而带来更好的特征空间覆盖。
  • 数据增强可以减少过拟合,并提高模型的泛化能力。

通过合理应用数据增强,我们能够用有限的数据训练出更强大、更稳健的机器学习模型。

077:时间序列数据处理 📊

概述

在本节课中,我们将学习如何处理时间序列数据。时间序列数据是按时间顺序记录的数据点序列,常见于传感器读数、气象记录等领域。我们将以气象数据为例,探讨其关键特性、预处理方法以及如何为模型训练(如LSTM)准备数据。


数据类型的多样性

上一节我们介绍了课程背景,本节中我们来看看不同类型的数据。

根据你处理的问题和拥有的数据,你可能会遇到多种数据类型,每种类型都需要不同的预处理方法,有时甚至需要不同的建模技术。例如,你可能处理图像、视频、文本、音频或时间序列数据。本课程无法详尽讨论所有数据类型,因此我们提供了一些可选材料供你自行探索。

以下是可选材料列表:

  • 一个用于处理CIFAR-10图像数据集的可选笔记本。
  • 两个用于处理时间序列数据的笔记本:一个基于气象数据,另一个基于大多数手机上都有的加速度计和其他传感器数据。

在列出的所有数据类型中,时间序列可能是大多数开发者最不熟悉的一种。因此,让我们从回顾时间序列的关键方面开始。


什么是时间序列?

时间序列是按时间顺序排列的数据点序列,通常来自记录的事件,其中时间维度指示事件发生的时间。原始数据中的时间序列可能有序也可能无序,但为了建模,你几乎总是希望它们按时间顺序排列。

在典型情况下,我们希望预测未来的值。具体来说,我们希望基于先前的测量值,预测未来某个时间点T的y值。目标是训练一个模型,以可接受的准确度预测未来的输出。

卡尔·克里斯蒂安·克劳斯曾指出,做出预测是困难的,尤其是关于未来的预测。当然,其推论是,预测过去相对容易,因为那已经发生了。时间序列预测正是试图预测未来,它通过分析过去的数据来实现这一点。

这需要有时间索引的数据。例如,为了预测某个地点未来的温度,我们可以使用过去记录的其他气象变量,如大气压力、风向和风速等。


气象预测实例

让我们看一个进行气象预测的具体例子。

在这个例子中,你将处理一个由马克斯·普朗克生物地球化学研究所记录的时间序列数据集。该数据集包含14个不同的特征,包括气温、大气压力和湿度。这些数据从2003年开始,每10分钟记录一次。

你的任务是使用TFX管道预处理这些特征,并将数据转换为时间序列格式。这种格式是训练循环神经网络(如长短期记忆模型或LSTM)所必需的。

让我们更仔细地看看数据的组织和收集方式。

以下是数据的关键信息列表:

  • 共有14个变量,包括与湿度、风向和风速、温度及大气压力相关的测量值。
  • 预测目标是温度。
  • 采样率为每10分钟一次观测,即每小时6次观测,每天144次观测(6 * 24)。

这些是部分特征随时间变化的图表,以及目标变量T(温度)。你可以看到数据中存在一种模式,在特定的时间间隔内重复出现。这里存在明显的季节性,我们在为此数据进行特征工程时需要加以考虑。

我们应该考虑进行季节性分解,但为了简化本例,我们不会这样做。数据表现出明显的周期性或季节性,在这种情况下,很可能与一年中典型的季节变化有关。但请记住,数据的季节性特征通常与实际的年季节无关,它实际上是关于周期性的。


窗口化策略

采用窗口化策略来观察与过去数据的依赖关系似乎是一条自然的路径。幸运的是,TFX已经内置了此功能。在笔记本中,你将看到TF Data的window函数,我们将使用它将数据集分组到窗口中。

那么,让我们以气象数据为例,确切地看看这是如何工作的。

时间序列中的窗口化策略变得非常重要,并且它们对于时间序列和类似类型的序列数据来说是相当独特的。

以下是两个窗口化示例:

  • 示例一:你有一个模型,可用于预测未来一小时的情况。给定6小时的历史记录,将使用窗口大小为6、偏移量为1的滑动窗口。因此,总窗口大小为7(6 + 1)。
  • 示例二:假设你预测未来24小时的情况,给定24小时的历史记录。那么,你的历史记录大小为24,偏移量大小也为24。因此,你可以使用总窗口大小为48(历史记录加上输出偏移量)。

同样重要的是要考虑“现在”是什么时候,并且不要包含未来的数据,这被称为“时间旅行”。在这个例子中,如果“现在”是t=24,那么我们需要小心,不要将t=25到t=47的数据包含在我们的训练数据中。我们可以通过特征工程或通过缩小窗口仅包含历史记录和标签来实现这一点。


采样策略

让我们谈谈采样策略。你已经知道在我们的例子中每小时有6次观测(每10分钟一次)。一天中,将有144次观测。

如果你取过去5天的观测值,并预测未来6小时的情况,这意味着我们的历史记录大小将是 5 * 144 = 720 次观测。输出偏移量将是 12 * 6 = 72。因此,时间上的总窗口大小为792。

由于一小时内观测值的变化可能不大,让我们每小时采样一次观测值。因此,我们将从每10分钟一次变为每小时一次。

以下是采样策略说明:

  • 我们可以取每小时内的第一次观测作为样本。
  • 或者,更好的方法是取每小时内观测值的中位数。

那么,我们的历史记录大小变为 5 * 24 * 1 = 120,我们的输出偏移量变为6,因此我们的总窗口大小变为126。这样,我们通过在每个小时内采样或通过取中位数聚合每小时的数据,将特征向量的大小从792减少到126。

我知道这里的数字可能有点令人困惑,但重要的是思考我们如何处理窗口中的数据。


在可选笔记本中你将做什么?

那么,在可选笔记本中你将做什么呢?

在笔记本中,你将首先使用TFX预处理天气时间序列数据集。你将使用 tf.data.Dataset.window 来创建用于构建样本的窗口。你将把转换和预处理后的数据以TFRecord格式保存。最后,你将创建训练和测试数据集,以便这些特征可以轻松地用于训练LSTM模型(使用TensorFlow或Keras的窗口化策略或其他框架)。由于我们专注于数据本身,笔记本中没有实现训练部分。


总结

本节课中,我们一起学习了时间序列数据的基本概念。我们了解了时间序列是按时间顺序排列的数据点,用于预测未来值。我们以气象数据为例,探讨了其季节性特征,并重点介绍了为模型训练准备数据的关键技术:窗口化策略和采样策略。通过合理设置窗口大小、偏移量并进行采样(如每小时取中位数),我们可以有效地构建用于训练循环神经网络(如LSTM)的特征数据集。

078:传感器与信号 📡

在本节课中,我们将学习传感器生成的数据,这类数据通常被称为“信号”。我们将通过一个具体的例子来理解相关的重要术语,并探讨如何处理和分析这类时间序列数据,特别是针对人类活动识别这一应用场景。


传感器与信号基础

上一节我们介绍了课程的主题。本节中,我们来看看传感器数据的基本概念。

传感器是一种能够检测和测量物理属性的设备。信号则是传感器实时收集到的数据序列。由于数据点按时间戳 t 索引,因此这类数据被称为时间序列数据,我们将使用时间序列分析方法来处理它。


一个具体问题:人类活动识别

理解了基本概念后,我们来看一个具体的应用问题:人类活动识别。其核心问题是:我们能否根据加速度计随时间变化的模式,推断出人的活动?

以下是人类活动识别面临的一些挑战:

  • 传感器数据波动剧烈。
  • 需要从连续数据流中准确识别出代表特定活动的片段。

关键步骤:数据分段

成功进行活动识别的关键在于对传感器数据进行正确的分段。这类似于我们之前讨论天气数据时使用的窗口化策略。

惯性数据随时间波动很大,因此分段是检测正确活动片段的关键。在数据分段过程中,原始的、与时间相关的加速度数据集被分割成多个片段。

所有后续的相关操作,包括特征提取、分类和验证等,都基于这些片段进行。 片段的长度取决于应用场景、上下文和传感器的采样率。对于人类活动识别,片段长度通常在 1 到 10 秒 之间。


数据转换与特征提取

数据被分段后,我们来谈谈典型的转换方法。为了提高模型的准确性和性能,应对分段后的数据进行转换。

以下是几种转换数据的方法:

  • 频谱图:惯性信号的频谱图是将信号表示为频率和时间函数的一种新形式。它是一种强大的方法,用于提取可解释的特征,这些特征代表了不同惯性数据点之间的强度差异。
  • 归一化与编码
  • 多通道处理
  • 应用傅里叶变换

实践练习概览

最后,我们简要了解一下将在可选笔记本中进行的实践内容。

你将尝试从传感器数据中识别人类活动。所使用的无线传感器数据挖掘数据集是在受控实验室条件下收集的。该数据集是使用手机加速度计数据进行活动识别的测试平台。

在该笔记本中,你将在 TfX 流水线中预处理数据。你将使用 tf.data.Dataset.window 将数据分组为窗口,这些窗口可用于 RNN 或类似模型。由于我们在此重点关注数据本身,笔记本中未实现训练和模型开发部分。


本节课中,我们一起学习了传感器信号的基本概念,探讨了人类活动识别这一应用,并深入了解了数据处理的关键步骤:分段与转换。这些是处理时间序列传感器数据的核心基础。

079:超参数调优 🎯

在本节课中,我们将学习超参数调优的基本概念,并了解其与神经架构搜索的关联。我们将探讨超参数调优的重要性,并介绍如何使用工具(如Keras Tuner)来自动化这一过程。

超参数调优与神经架构搜索

上一节我们介绍了课程的整体安排,本节中我们来看看超参数调优。神经架构搜索在近期的机器学习发展中扮演着重要角色。

本质上,它是一种自动化设计神经网络的技术。通过神经架构搜索发现的模型,在许多问题上常常能与手工设计的架构相媲美甚至更优。

神经架构搜索的目标是找到最优的架构。需要记住的是,现代神经网络覆盖了巨大的参数空间,因此使用像AutoML这样的工具来自动化搜索非常有意义。

在深入探讨AutoML之前,让我们通过分析机器学习建模中最繁琐的过程之一——超参数调优,来理解它所要解决的问题。

模型参数与超参数

在机器学习模型中,存在两种类型的参数。

  • 模型参数:这些是模型必须使用训练集学习的参数,它们是我们模型的拟合或训练参数。通常这指的是权重和偏置
  • 超参数:这些是可调整的参数,必须经过调优才能创建出具有最佳性能的模型。但与模型参数不同,超参数不会在训练过程中自动优化。它们需要在模型训练开始之前设定,并影响模型的训练方式。

超参数调优对模型性能有重大影响。不幸的是,即使对于小型模型,超参数的数量也可能相当可观。

以下是浅层神经网络中可能需要做出选择的超参数类别:

  • 架构选项
  • 激活函数
  • 权重初始化策略
  • 优化器超参数
  • 以及其他

自动化调优的必要性

执行手动的超参数调优可能非常费神,因为你需要跟踪已经尝试过的配置并启动不同的实验。这样的手动过程是繁琐的。

尽管如此,如果操作得当,超参数调优能显著提升模型性能。

超参数调优工具

已经创建了多个使用不同方法进行超参数调优的开源库。Keras团队发布了其中最好的一个——Keras Tuner

这是一个可以轻松与TensorFlow 2.0配合进行超参数调优的库。它提供了多种不同的调优方法,包括:

  • 随机搜索
  • Hyperband
  • 贝叶斯优化

在下一节视频中,我们将看一个具体的例子。


本节课中,我们一起学习了超参数调优的基本概念,区分了模型参数与超参数,并理解了自动化调优工具(如Keras Tuner)的重要性。我们还初步了解了神经架构搜索与超参数调优之间的相似性。

080:Keras AutoTuner 演示 🧠

在本节课中,我们将学习如何使用 Keras AutoTuner 来自动化神经网络超参数的调优过程。我们将从一个手动设置超参数的简单模型开始,逐步演示如何利用 AutoTuner 自动寻找更优的架构配置,从而提高模型性能或训练效率。


手动构建基础模型

首先,我们从一个手动设置超参数的模型开始。这个模型用于分类 MNIST 数据集中的时尚物品。为了简化,我们采用最基本的神经网络架构,包含一个输入层、一个隐藏层和一个输出层。

以下是实现该模型的 Keras 代码。这可以说是深度学习的“Hello World”示例,目标是在一个时尚物品数据集上构建一个基础识别模型。

import tensorflow as tf

# 加载数据
mnist = tf.keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()

# 数据归一化
training_images = training_images / 255.0
test_images = test_images / 255.0

# 定义模型
model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28)),
  tf.keras.layers.Dense(512, activation='relu'),
  tf.keras.layers.Dropout(0.2),
  tf.keras.layers.Dense(10, activation='softmax')
])

# 编译模型
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

# 训练模型
model.fit(training_images, training_labels, epochs=5)

# 评估模型
model.evaluate(test_images, test_labels)

运行此代码,我们得到了约 98.66% 的准确率,每个训练周期(epoch)耗时略超过 10 秒。


引入超参数调优的思考

一个自然的问题是:我们能否做得更好?在展示上述代码后,我常被问到:“这些数字(如 512 个神经元,Dropout 为 0.2)是从哪里来的?为什么不是其他数字?” 答案通常是,这些数字来自大量的试错,或者是从一个可运行的示例中直接复制而来,并未深入思考。

我们需要思考:这是否是最优的选择?模型使用更多或更少的隐藏单元会更好吗?更少的单元会学得更快吗?更小的架构能否在不损失准确性的前提下达到相同效果?

你可以通过手动更改这些值、重新运行、再更改、再运行来进行实验,但这需要大量工作。如果能自动化这个过程就好了。这时,Keras Tuner 就能派上用场。


安装与使用 Keras AutoTuner

上一节我们介绍了手动调参的局限性,本节中我们来看看如何安装并使用 Keras Tuner 来自动化超参数搜索。

安装 Keras Tuner 非常简单,只需使用 pip 命令:

pip install keras-tuner

然后,在代码中导入它。在本例中,我们将其导入为 kt

import keras_tuner as kt

现在,让我们回到模型定义部分。我们将不再硬编码隐藏层为 512 个神经元,而是使用以下代码:

def build_model(hp):
    model = tf.keras.models.Sequential([
        tf.keras.layers.Flatten(input_shape=(28, 28)),
        tf.keras.layers.Dense(
            units=hp.Int('units', min_value=16, max_value=512, step=16),
            activation='relu'
        ),
        tf.keras.layers.Dropout(0.2),
        tf.keras.layers.Dense(10, activation='softmax')
    ])
    model.compile(
        optimizer='adam',
        loss='sparse_categorical_crossentropy',
        metrics=['accuracy']
    )
    return model

请注意,第一个密集层(Dense layer)的单元数被设置为 hp.Int('units', min_value=16, max_value=512, step=16)。这定义了一个整数值范围,从 16 开始,到 512 结束,步长为 16。Keras Tuner 将运行模型多次,每次收集指标,并优化出最佳值。


配置搜索策略与执行调优

接下来,你需要定义搜索策略。Keras Tuner 支持多种策略,你可以像下面这样指定要使用的策略:

tuner = kt.Hyperband(
    build_model,
    objective='val_accuracy',
    max_epochs=10,
    factor=3,
    directory='my_dir',
    project_name='intro_to_kt'
)

在这个例子中,我使用了 Hyperband 策略。它也支持随机搜索、贝叶斯优化和 SKLearn 策略。你可以在 Keras Tuner 官网 了解更多关于这些策略的细节。

你选择的参数会根据策略而变化,但需要注意的一个重要参数是 objective。在本例中,我们的目标是验证准确率(val_accuracy),因此我们希望最大化验证准确率。你可以在 Keras 官网上找到其余参数的详细信息。

搜索可能需要一段时间才能完成,并且会使用大量计算资源。但你可以配置一个早停回调(early stopping callback),在满足条件时停止搜索。例如:

stop_early = tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=5)

这里,我监控验证损失(val_loss),并将耐心值(patience)设置为 5。这意味着如果验证损失在连续 5 个周期内没有显著改善,则停止对此迭代的搜索。你可以将此回调设置为搜索的一个参数。

其余参数指定了如何搜索,例如数据和标签、训练的周期数以及验证集划分比例(即,有多少数据将用于验证训练集)。

在搜索过程中,你将看到每次试验(trial)的结果。我们只搜索一个参数:密集隐藏层中的单元数。正如你所见,随着搜索更新,你可以跟踪迄今为止的最佳值。在幻灯片所示的例子中,最佳值是 48。


应用调优结果并重新训练

搜索完成后,我可以返回并再次尝试我的架构,这次使用 Keras Tuner 的结果来手动设置单元数,即使用 48 个神经元(这是我们从 Keras Tuner 得到的最佳值)。

# 使用最佳超参数构建最终模型
best_hps = tuner.get_best_hyperparameters(num_trials=1)[0]
model = build_model(best_hps)

# 重新训练模型
model.fit(training_images, training_labels, epochs=5, validation_split=0.2, callbacks=[stop_early])

# 评估最终模型
test_loss, test_acc = model.evaluate(test_images, test_labels)
print(f"测试准确率: {test_acc}")

重新训练后,你会看到结果。虽然只训练了 5 个周期,且验证准确率可能没有之前手动设置的模型高,但我们的每个训练周期速度比之前快了三倍。因此,我知道至少已经优化了部分架构,并且可以尝试训练更长时间以获得更好的结果。


总结

本节课中,我们一起学习了 Keras AutoTuner 的基本用法。我们从手动设置超参数的基础模型出发,探讨了自动化调优的必要性,并逐步演示了如何安装 Keras Tuner、定义可调超参数、配置搜索策略以及应用调优结果。通过自动化搜索,我们能够更高效地探索神经网络架构的可能性,从而在模型性能与训练效率之间找到更好的平衡点。

081:AutoML简介 🤖

在本节课中,我们将学习自动化机器学习(AutoML)的基本概念。我们将了解AutoML如何端到端地自动化机器学习流程,其核心组件神经架构搜索(NAS),以及它在实际应用中的价值。


上一节我们介绍了超参数调优,本节中我们来看看实际的AutoML。AutoML是一套功能多样的工具,旨在端到端地自动化机器学习过程。

什么是AutoML?

找到合适的模型是机器学习拼图中的重要一块。自动化机器学习(AutoML)旨在让机器学习经验很少的开发者也能利用机器学习模型和技术。

它试图端到端地自动化机器学习过程,以产生简单的解决方案,加快解决方案和模型的创建速度,有时甚至能产生优于手动调优模型的模型。AutoML将机器学习和搜索技术应用于创建机器学习模型和流水线的过程。

它涵盖了从原始数据集到可部署机器学习模型的完整流水线。

传统机器学习 vs. AutoML

在传统机器学习中,我们需要为流程的所有阶段编写代码。

我们从摄取和清理原始数据开始,然后进行特征选择和特征工程。我们为任务选择一个模型架构,训练模型,并进行超参数调优(可能是手动的,或使用像Keras Tuner这样的调优器)。

然后我们验证模型的性能。传统机器学习需要大量手动编程和高度专业化的技能。

AutoML旨在自动化整个机器学习工作流。如果我们能为AutoML系统提供原始数据和模型验证要求,它就会遍历机器学习工作流中的所有阶段,并以系统化的方式执行机器学习开发的迭代过程,直到模型训练完成。

神经架构搜索(NAS)

神经架构搜索(NAS)是AutoML的核心。神经架构搜索包含三个主要部分:搜索空间搜索策略性能评估策略

  • 搜索空间定义了架构的范围。为了减少搜索问题的规模,我们需要将搜索空间限制在最适合我们试图建模的问题的架构上。这有助于缩小搜索空间,但也意味着会引入人为偏见,这可能会阻止神经架构搜索找到超越当前人类知识的架构模块。

  • 搜索策略定义了我们如何探索搜索空间。我们希望快速探索搜索空间,但这可能导致过早收敛到搜索空间中的次优区域。
  • 性能评估策略有助于测量和比较各种架构的性能。

神经架构搜索的目标是找到在我们的数据上表现良好的架构。搜索策略从预定义的架构搜索空间中选择一个架构。选定的架构被传递给性能评估策略,该策略将其估计的性能返回给搜索策略。搜索空间、搜索策略和性能评估策略是神经架构搜索的关键组成部分,我们将依次讨论它们。

AutoML与NAS的关系

AutoML以自动化方式促进模型构建。此外,AutoML不局限于特定的模型家族或子集。

神经架构搜索是AutoML的一个子领域。它特别关注AutoML工作流中的模型选择部分和神经网络的设计。神经架构搜索已被用于设计出与手动设计模型相当或优于手动设计模型的架构。

AutoML的实际应用案例

让我们看一个AutoML在现实世界中的应用。

Meredith Digital是一家专注于多种媒体和娱乐形式的出版公司。Meredith Digital使用AutoML(主要是基于自然语言的模型)来训练模型,以自动化内容分类。AutoML通过将流程从几个月缩短到仅仅几天来加速分类过程。它还通过提供有洞察力、可操作的建议来帮助建立客户忠诚度。😊 此外,它还有助于识别新的用户趋势和客户兴趣,从而调整内容以更好地服务客户。

为了测试其有效性,他们进行了一项测试,将AutoML与他们手动生成的模型进行比较,结果非常显著。Google Cloud AutoML自然语言工具提供的内容分类性能可与人类水平相媲美。


本节课中我们一起学习了AutoML的基本概念。我们了解到AutoML旨在自动化端到端的机器学习流程,其核心是神经架构搜索,它由搜索空间、搜索策略和性能评估策略三个关键部分组成。最后,我们通过一个实际案例看到了AutoML如何显著提升模型开发效率并达到优异性能。

082:理解搜索空间 🔍

在本节课中,我们将继续讨论 AutoML,重点介绍其核心概念之一:搜索空间。我们将了解搜索空间的两种主要类型,并解释它们如何帮助自动构建高效的神经网络架构。


宏观与微观搜索空间

上一节我们介绍了 AutoML 的基本概念,本节中我们来看看其核心组成部分——搜索空间。搜索空间定义了神经网络架构的可能配置范围,AutoML 算法在其中寻找最优模型。

搜索空间主要有两种类型:宏观搜索空间微观搜索空间。有趣的是,它们的名称与实际含义可能有些相反,但这是业界通用的叫法。接下来,我们将详细探讨这两种类型。

首先,我们需要明确一个基本概念:节点。在神经网络中,一个节点通常指代一个层,例如卷积层或池化层。

在架构图示中,不同颜色通常代表不同类型的层。从层 L_I 指向层 L_J 的箭头表示层 L_J 接收层 L_I 的输出作为其输入。


宏观搜索空间 🏗️

宏观搜索空间包含了神经网络的各个独立层及其连接方式。神经架构搜索(NAS)在此空间内寻找最佳模型,其构建过程是逐层进行的。

如下图所示,网络可以通过简单地堆叠各个层来构建,这种结构被称为链式结构空间

或者,也可以在更复杂的空间中构建具有多个分支和跳跃连接的网络。


微观搜索空间 🧩

与宏观搜索空间不同,在微观搜索空间中,神经架构搜索通过组合细胞来构建神经网络。每个细胞本身就是一个较小的网络。

以下是两种不同类型的细胞示例:顶部的普通细胞和底部的缩减细胞

通过堆叠这些细胞,最终形成完整的网络。研究表明,与宏观方法相比,这种微观细胞堆叠方法具有显著的性能优势。

下图展示了一个通过顺序堆叠细胞构建的架构。

需要注意的是,细胞也可以通过更复杂的方式组合,例如在多分支空间中,直接用细胞替换原有的层即可。


总结

本节课中,我们一起学习了 AutoML 中搜索空间的概念。我们明确了节点即神经网络中的层,并深入探讨了两种主要的搜索空间类型:宏观搜索空间(逐层构建网络)和微观搜索空间(通过堆叠预定义的细胞单元构建网络)。理解这两种空间是掌握自动机器学习如何高效探索并发现最优神经网络架构的关键一步。

083:神经架构搜索的搜索策略 🔍

在本节课中,我们将学习神经架构搜索(NAS)如何决定在庞大的搜索空间中尝试哪些架构选项。核心在于其搜索策略。我们将探讨几种不同的搜索方法,了解它们的工作原理、适用场景以及优缺点。

上一节我们介绍了神经架构搜索的搜索空间,本节中我们来看看它如何在这个空间中进行高效探索。

神经架构搜索的目标是在搜索空间中找到能产生最佳性能的模型架构。为了实现这一目标,可以采用多种不同的搜索方法。

以下是几种主要的搜索策略:

  • 网格搜索:这种方法会穷举搜索空间中的所有选项组合。其公式可以表示为:遍历所有 (option_1, option_2, ..., option_n) 的组合。
  • 随机搜索:这种方法在搜索空间内随机选择下一个要尝试的架构选项。
  • 贝叶斯优化:这是一种更复杂的方法。它假设模型架构的性能背后存在一个特定的概率分布(通常是高斯分布)。利用已测试架构的观测结果来约束这个概率分布,从而指导下一个选项的选择。
  • 进化算法:这种方法模拟生物进化过程。以下是其工作原理:
    1. 随机生成一个包含 n 个不同模型架构的初始种群。
    2. 评估每个个体(即每个架构)的性能(依据我们下一节将讨论的性能评估策略)。
    3. 选择性能最好的 X 个架构作为父代,用于产生新一代。
    4. 新一代架构可能是父代的副本,并引入随机改变(突变),也可能是父代架构的组合。
    5. 再次使用性能评估策略评估后代的性能。
    6. 从种群中移除 Y 个架构(可能是性能最差的、最老的,或基于综合参数选择的个体)。
    7. 后代取代被移除的架构,形成新的种群,并重复此过程。
  • 强化学习:在这种方法中,智能体在环境中采取行动以最大化奖励。在NAS的语境下:
    • 环境 是我们的搜索空间。
    • 奖励函数 是我们的性能评估策略。
    • 一个神经网络架构可以用一个可变长度字符串来指定,其中字符串的元素指定了各个网络层。这使得我们可以使用循环神经网络(RNN)来生成这个字符串,就像在自然语言处理模型中生成句子一样。这个生成字符串的RNN被称为控制器
    • 控制器生成的架构(称为子网络)在真实数据上训练后,我们可以在验证集上测量其准确率。
    • 该准确率决定了强化学习的奖励。基于此奖励,我们可以计算策略梯度来更新控制器RNN。
    • 在接下来的迭代中,控制器将学会给那些在训练中能产生更高准确率的架构分配更高的生成概率。这样,控制器就能随着时间推移学会改进其搜索。

例如,在CIFAR-10数据集上,这种从零开始的方法可以设计出新的网络架构,其在测试集准确率上足以媲美最佳的人工设计架构。


本节课中我们一起学习了神经架构搜索的多种搜索策略。从简单的网格搜索和随机搜索,到更复杂的贝叶斯优化、进化算法和强化学习,每种策略都有其独特的探索方式。理解这些策略有助于我们根据搜索空间的规模和复杂性,选择合适的方法来自动化地发现高性能的神经网络架构。下一节,我们将探讨另一个关键部分:如何高效地评估这些候选架构的性能。

084:测量AutoML的功效 📊

在本节课中,我们将学习神经架构搜索(NAS)中用于评估不同架构性能的策略。理解这些策略对于高效、经济地应用AutoML技术至关重要。

神经架构搜索依赖于能够衡量其所尝试的不同架构的准确性或有效性。这需要一个性能评估策略。现在我们来讨论这个问题。

神经架构搜索中的搜索策略需要评估所生成架构的性能,以便能生成性能更优的架构。接下来,我们将讨论神经架构搜索中使用的一些性能评估策略。

性能评估策略概览

以下是几种主要的性能评估策略,旨在平衡计算成本与评估准确性。

1. 直接验证准确率法

最简单的方法是直接测量每个生成架构的验证准确率,正如我们在强化学习方法中看到的那样。

  • 优点:评估结果直接、准确。
  • 缺点:计算量巨大,尤其对于大型搜索空间和复杂网络。使用这种方法寻找最佳架构可能需要数百个GPU日,成本高昂且缓慢,使得神经架构搜索在许多用例中不切实际。

2. 降低保真度估计法

为了降低性能评估成本,研究者提出了多种策略,包括降低保真度估计、学习曲线外推法和权重继承或网络形态法。

降低保真度或低精度估计试图通过重构问题来减少训练时间,使其更容易解决。

  • 具体做法:例如,在数据子集上训练、使用较低分辨率的图像、每层使用更少的滤波器或更少的单元。
  • 效果:这大大降低了计算成本,但会导致性能被低估。
  • 关键假设:只要能够确保架构的相对排名不因其低保真度估计而改变,这种方法就是可行的。但遗憾的是,最近的研究表明情况并非如此。

3. 学习曲线外推法

学习曲线外推法基于一个假设:存在能够可靠预测学习曲线的机制,因此外推是一个敏感且有效的选择。

  • 原理:如上图右侧所示,不同架构有其学习曲线。该方法基于少量迭代和现有知识,外推初始学习曲线,并提前终止表现不佳的架构的训练。
  • 应用实例:渐进式神经架构搜索算法(PNAS)就采用了类似的方法,它训练一个代理模型,并使用该模型根据架构属性来预测性能。

4. 权重继承与网络形态法

另一种加速架构搜索的方法,是基于已训练的其他架构的权重来初始化新架构的权重,其原理类似于迁移学习。实现此目标的一种方式被称为网络形态法。

  • 核心思想:网络形态法在不改变底层功能的情况下修改架构。
  • 优势:网络从父网络继承知识,这使得方法仅需少量GPU日即可设计和评估。它允许逐步增加网络容量并保持高性能,而无需从头开始训练。
  • 重要优点:这种方法允许搜索空间在架构大小上没有固有的上限,提供了更大的灵活性。

总结

本节课我们一起学习了神经架构搜索中几种关键的性能评估策略。我们从计算成本最高的直接验证法开始,探讨了旨在降低成本的低保真度估计法及其局限性,接着介绍了基于预测的学习曲线外推法,最后学习了能高效利用已有知识的权重继承与网络形态法。理解这些策略的权衡,对于在实际项目中有效应用AutoML至关重要。

085:云端 AutoML 服务概览 🚀

在本节课中,我们将学习如何利用云服务来轻松实现 AutoML。我们将回顾三种主流的云端 AutoML 产品:Amazon SageMaker Autopilot、Microsoft Azure Automated Machine Learning 和 Google Cloud AutoML。课程最后,你将通过练习使用 Google Cloud AutoML 来训练一个模型。


Amazon SageMaker Autopilot

上一节我们介绍了云端 AutoML 的概念,本节中我们来看看亚马逊的解决方案。

Amazon SageMaker Autopilot 能基于你的数据,自动训练和调优用于分类或回归任务的最佳机器学习模型,同时让你保持对过程的完全控制和可见性。

以下是其核心工作流程:

  1. 数据与目标设定:从原始数据开始,你选择一个标签或目标变量。
  2. 自动搜索模型:Autopilot 随后会为你搜索候选模型以供审阅和选择。
  3. 透明与可复现:所有步骤都记录在可执行的 Notebook 中,确保过程的完全控制和可复现性。
  4. 模型排行榜:系统会生成一个模型排行榜,帮助你根据需求选择最佳模型。
  5. 部署与迭代:你可以将模型部署到生产环境,或者基于推荐方案进行迭代以进一步提升模型质量。

Autopilot 针对快速迭代进行了优化,能迅速生成高质量模型。在初始几轮迭代后,它会创建一个按性能排名的模型排行榜。你可以查看每个模型选择了数据集中的哪些特征,然后选择将模型部署到生产环境。

模型生成过程是完全透明的。Autopilot 允许你从其创建的任何模型中生成一个 SageMaker Notebook。你可以检查这个 Notebook 以深入了解模型实现的细节。如果需要,你可以在任何时候基于该 Notebook 优化并重新创建模型。

Amazon 建议 Autopilot 可应用于多种不同场景,例如:

  • 价格预测:基于历史数据(如需求、季节性趋势、其他商品价格)预测未来价格,辅助投资决策。这在金融服务(预测股票价格)、房地产(预测房价)以及能源公用事业(预测自然资源价格)领域尤为有用。
  • 客户流失预测:预测客户流失。公司始终在寻找减少流失的方法。流失预测通过学习现有数据中的模式,并识别新数据集中的模式,从而预测哪些客户最有可能流失。
  • 风险评估:识别和分析可能对个人或公司产生负面影响的潜在事件。风险评估模型使用你的现有数据集进行训练,以便为你的业务优化模型预测。

Microsoft Azure Automated Machine Learning

了解了亚马逊的方案后,我们接下来看看微软的云端 AutoML 服务。

Microsoft Azure Automated Machine Learning 旨在帮助专业和非专业的数据科学家快速构建机器学习模型。它自动化了模型开发中耗时且重复的任务,本质上就是执行 AutoML。

其流程始于自动特征选择,然后是模型选择以及对所选模型的超参数调优,从而为手头任务生成最优化的模型。

你可以通过两种方式创建模型:

  • 使用无代码 UI
  • 使用代码优先的 Notebook

你可以快速定制模型,对迭代次数、阈值、验证方式、禁用的算法以及其他实验标准应用控制设置。

该系统还提供工具以完全自动化特征工程过程。你可以轻松地可视化和分析数据,以发现趋势,以及数据中的常见错误和不一致之处。这有助于你更好地理解建议的操作并自动应用它们。

此外,它还提供以下功能以提升效率:

  • 智能停止:节省计算时间,并优先考虑主要评估指标。
  • 子采样:简化实验运行并加速获得结果。
  • 内置实验运行摘要和详细指标可视化:帮助你理解模型并比较模型性能。
  • 模型可解释性:评估模型对原始特征和工程特征的拟合度,并提供特征重要性洞察。你可以发现模式、执行假设分析,并加深对模型的理解,从而支持业务的透明度和信任度。

Google Cloud AutoML

上一节我们讨论了微软的解决方案,本节中我们将重点介绍你将在后续练习中使用的 Google Cloud AutoML。

Google Cloud AutoML 是一套机器学习产品,使机器学习专业知识有限的开发人员能够训练符合其业务需求的高质量模型。它依赖于谷歌先进的迁移学习和神经架构搜索技术。

Cloud AutoML 利用了谷歌超过十年的研究成果,帮助你的机器学习模型实现更快的性能和更准确的预测。你可以使用 Cloud AutoML 简单的图形用户界面,基于你的数据来训练、评估、改进和部署模型。你只需几分钟就能获得自己的定制机器学习模型。

谷歌的人工标注服务还可以安排团队为你的标签进行标注或清理,确保你的模型是基于高质量数据训练的。

因为不同类型的问题和数据需要不同的处理方式,Cloud AutoML 不只是一个单一产品,而是一套针对特定用例和数据类型的系列产品。例如:

  • 对于图像数据,有 AutoML Vision
  • 对于视频数据,有 AutoML Video Intelligence
  • 对于自然语言,有 AutoML Natural Language
  • 对于翻译,有 AutoML Translation
  • 对于通用的结构化数据,有 AutoML Tables

其中一些产品还会进一步细分。例如,对于图像数据,既有视觉分类,也有视觉对象检测。并且这两者都有针对在移动应用或物联网设备等边缘端进行推理优化的“边缘”版本。对于视频,同样有视频智能分类和视频对象检测,专注于这些特定用例。


云端 AutoML 的底层原理与共性

那么,这三种不同的云服务在底层是如何运作的呢?

虽然没有人确切知道(或者为特定供应商工作的人不能说),但可以安全地假设,其核心算法与我们之前课程中讨论过的那些是相似的。

同时请记住,面向生产的机器学习工程是一个快速发展的领域,新技术和发展每隔几个月就会出现。这些新的进步通常会被 AutoML 提供商最大限度地吸收和利用。

另外请注意,这些不同的 AutoML 服务都执行着与你在训练模型时执行(或应该执行)的相同类型的操作,包括特征选择特征工程清理标签。AutoML 的设计者深刻理解这些活动的重要性。


总结

本节课中,我们一起学习了三种主流的云端 AutoML 服务:Amazon SageMaker AutopilotMicrosoft Azure Automated Machine LearningGoogle Cloud AutoML。我们了解了它们如何通过自动化特征工程、模型选择和超参数调优等复杂步骤,降低机器学习应用门槛,并提供了透明、可控的模型开发流程。这些服务都旨在帮助用户快速构建和部署高质量模型,是实践 MLOps 的强大工具。在接下来的练习中,你将有机会亲手体验 Google Cloud AutoML 的强大功能。

086:作业设置 🎯

在本节课中,我们将学习如何使用 Google Cloud AutoML Vision 对图像进行分类。我们将通过一个包含六个步骤的作业来实践这一流程,并在 Quicklabs 提供的真实云环境中完成操作。


作业概述 📋

本次作业的目标是使用 Google Cloud AutoML Vision 服务构建一个图像分类模型。整个过程分为六个清晰的步骤,从环境设置到模型部署与测试。

上一节我们介绍了 AutoML 的基本概念,本节中我们来看看具体的作业步骤。

以下是完成图像分类任务所需的六个步骤:

  1. 设置 AutoML 环境。
  2. 将图像上传至云存储。
  3. 在 Vision 中创建数据集。
  4. 启动 AutoML 训练以选择最佳模型。
  5. 部署训练好的模型。
  6. 使用已部署的模型生成预测以进行测试。

请注意:数据集中包含的是“云朵”的图片,而我们的训练是在“云平台”上进行的,请注意区分这两个“云”的概念。


实践环境:Quicklabs ☁️

为了让大家在真实的云环境中完成练习,我们将使用 Quicklabs 平台。

Quicklabs 为开发者和IT专业人士提供真实的云环境,帮助学习如何应用云平台及相关软件。在本练习中,你将通过 Quicklabs 在 Google Cloud 上实际操作,学习如何使用 Google Cloud AutoML 训练模型。

以下是关于开始使用 Quicklabs 的指引:

  • 请查阅附带的实验手册,了解如何启动 Quicklabs 的详细步骤。

总结与开始实践 🚀

本节课中,我们一起学习了使用 Google Cloud AutoML Vision 进行图像分类的完整工作流程,包括六个核心步骤以及实践平台 Quicklabs 的介绍。

现在,轮到你来尝试使用 AutoML 了。请按照步骤,在 Quicklabs 提供的 Google Cloud 环境中完成这六个步骤的练习。

087:第1周总结 📚

在本节课中,我们将对第一周的核心学习内容进行回顾与总结。我们主要探讨了超参数调优和自动化机器学习(AutoML)这两个关键主题。

上一节我们介绍了超参数调优的基本概念,本节中我们来看看本周内容的整体回顾。

我们以关于超参数调优的深入讨论作为本周的开始。我认为这是一个富有启发性的实践练习。

随后,我们深入探讨了自动化机器学习(AutoML)。这同样是一个在云平台上进行的有趣实践练习。

我享受了这个学习过程,希望你也同样有所收获。我们下次课程再见。


本节课中我们一起学习了超参数调优的方法论以及自动化机器学习工具的基本应用,为后续的机器学习工程化实践奠定了基础。

088:维度对性能的影响 📊

在本节课中,我们将学习模型优化与资源管理中的一个核心话题:数据维度如何影响模型性能与资源需求。我们将探讨高维数据的挑战,并通过一个具体的文本分类示例,展示降低维度如何帮助改善模型泛化能力。

概述:维度的重要性

上一节我们介绍了模型资源管理的整体背景。本节中,我们来看看数据维度这个具体因素。

计算、存储和I/O系统的需求决定了将模型投入生产及在其整个生命周期内维护它的成本。本周,我们将探讨一些有助于管理模型资源需求的重要技术。我们将从讨论维度及其如何影响模型性能和资源需求开始。

在过去,数据生成和数据存储的成本比今天高得多。那时,许多领域专家在设计实验和特征转换前,会仔细考虑测量哪些特征或变量。因此,数据集通常设计精良,可能只包含少量相关特征。

如今,数据科学更倾向于端到端地整合一切。生成和存储数据变得更快、更容易且成本更低。因此,人们倾向于测量所有能测量的东西,并包含更复杂的特征转换。结果,数据集通常是高维的,包含大量特征,尽管每个特征对于分析数据的相关性并不总是明确的。

在深入之前,让我们讨论一个关于神经网络的常见误解。许多开发者正确地认为,当他们训练神经网络模型时,模型本身作为训练过程的一部分,会通过将不提供预测信息的特征的权重减少到0或接近0来学会忽略它们。这虽然正确,但结果并非一个高效的模型。在运行推理生成预测时,模型的大部分可能最终被关闭,但这些未使用的模型部分仍然存在。它们占用空间,并且在模型服务器遍历计算图时消耗计算资源。这些不需要的特征还会给数据引入不必要的噪声,从而降低模型性能。

在模型本身之外,每个额外的特征仍然需要系统和基础设施来收集、存储、管理更新等数据,这增加了整个系统的成本和复杂性。这包括监控数据问题以及在问题发生时修复这些问题的工作。这些成本在你部署的产品或服务的整个生命周期内持续存在,可能长达数年。本课程后面你将学到更多关于优化权重接近零的模型的技术。但总的来说,你不应该只是把所有东西都扔给模型,并依赖训练过程来确定哪些特征真正有用。

高维数据的挑战

在机器学习中,我们经常需要处理高维数据。考虑一个例子,我们为每位购物者记录60个不同的指标。这意味着我们在一个60维的空间中工作。在其他情况下,如果你试图分析50x50的灰度图像,你就在一个2500维的领域中工作。如果图像是RGB的,维度则增加到7500维。在这种情况下,图像的每个像素的每个颜色通道对应一个维度。

某些特征表示,例如独热编码,在处理高维空间中的文本时存在问题,因为它们往往会产生非常稀疏的表示,且扩展性不好。克服这个问题的一种方法是使用嵌入层,它对句子进行标记化,并为每个单词分配一个浮点值。这导致了一个更强大的向量表示,它尊重给定句子中单词的时间和顺序。这种表示可以在训练过程中自动学习。图中标记为“嵌入层”的立方体是这些向量在高维空间中的概念表示。

实践示例:词嵌入与维度削减

让我们看一个使用Keras进行词嵌入的具体例子。

以下是构建和训练模型的关键步骤:

  1. 加载数据与库:首先加载必要的库和模块,并定义一些重要参数。我们将使用的路透社新闻数据集包含11,228条新闻专线,标记为46个主题。文档已经过编码,每个单词由一个整数索引,代表其在数据集中的总体频率。加载数据集时,我们指定将处理1000个单词,以便最不常出现的单词被视为未知。
  2. 数据预处理:进一步预处理数据,使其准备好训练模型。首先,将训练向量Y转换为分类变量(针对训练集和测试集)。接下来,将输入文本分割成20个单词长的序列。
  3. 构建网络:下一步是构建网络。这里选择使用所有维度来嵌入1000个单词的词汇表。最后一层是维度为46的密集层,因为目标变量是一个46维的类别向量。
  4. 编译模型:准备好模型结构后,通过指定损失函数、优化器和输出指标来编译模型。对于这个问题,自然的选择是分类交叉熵损失、RMSprop优化器,准确率作为指标。
  5. 训练模型:现在一切就绪,可以进行模型拟合。我们将指定验证集、批大小和训练周期数。

图中,A是准确率随训练周期的变化,L是模型损失随训练周期的变化。请注意,大约两个周期后,与验证集相比,我们的训练数据产生了显著更高的准确率和更低的损失。这清楚地表明模型严重过拟合。这可能是使用数据所有维度的结果,因此模型捕捉到了训练集中泛化能力不佳的细微差别。

降低维度以改善性能

让我们尝试降低维度,看看这如何影响模型性能。为此,让我们将1000个单词的词汇表嵌入到6个维度中。

这大约是减少了四次方根的因子。除此之外,模型保持不变。

可能仍然存在一些过拟合,但仅通过这一改变,这个模型的性能就显著优于1000维版本。

总结

本节课中,我们一起学习了数据维度对机器学习模型性能与资源消耗的关键影响。我们了解到,并非所有特征都对预测有益,高维数据可能导致模型过拟合、计算资源浪费以及系统复杂性增加。通过一个具体的文本分类案例,我们实践了使用嵌入层降低维度的方法,并观察到降低嵌入维度能有效缓解过拟合,提升模型在验证集上的泛化能力。这为我们后续学习模型量化、剪枝等更深入的优化技术奠定了基础。记住,精心设计特征和合理控制模型复杂度,是构建高效、可维护的生产级机器学习系统的重要一步。

089:11_维度灾难 🧠

在本节课中,我们将要学习一个在构建模型时至关重要的概念——维度灾难。我们将探讨高维数据带来的挑战,理解为什么增加特征数量有时反而会损害模型性能,并了解其背后的数学原理。


什么是维度灾难?

许多常见的机器学习任务,如分割和聚类,都依赖于计算观测值之间的距离。例如,监督分类使用观测值之间的距离来分配类别。K近邻算法就是一个基本例子。支持向量机(SVM)则通过基于投影后观测值之间距离的核函数来处理观测值的投影。另一个例子是推荐系统,它使用用户和物品属性向量之间基于距离的相似性度量。甚至可能使用其他形式的距离。因此,距离在理解维度方面扮演着重要角色。

最常用的距离度量之一是欧几里得距离,它简单地表示多维空间中两点之间的线性距离。两个具有笛卡尔坐标的二维向量之间的欧几里得距离使用这个熟悉的公式计算:distance = sqrt((x2 - x1)^2 + (y2 - y1)^2)


为什么高维空间中的距离会成为问题?

你可能会疑惑,为什么数据维度高会成为一个问题。在极端情况下,当我们拥有比观测值更多的特征时,我们面临模型严重过拟合的风险。但在更普遍的情况下,当特征过多时,观测值变得更难聚类。过多的维度会导致数据集中的每个观测值看起来与其他所有观测值都等距。

因为聚类使用诸如欧几里得距离这样的度量来量化观测值之间的相似性,这是一个大问题。如果所有距离都大致相等,所有观测值看起来都同样相似,就无法形成有意义的聚类。

随着维度的增长,常用度量提供的对比度会下降。换句话说,给定点分布中的范数分布趋于集中。这可能导致高维空间中出现意想不到的行为。这种现象被称为维度灾难

它包括在这些高维空间中观察到的数据反直觉属性。这特别与距离和体积的可用性及解释有关。


维度灾难的两个方面

谈到维度灾难,有两件事需要考虑。一方面,机器学习擅长处理多维度数据。然而,我们人类并不擅长在可能分散在多个维度的数据中发现模式,特别是当这些维度以反直觉的方式相互关联时。另一方面,随着我们添加更多维度,我们也增加了分析数据所需的处理能力。同时,我们也增加了构建有意义模型所需的训练数据量。

如果你好奇的话,“维度灾难”这个术语是由理查德·贝尔曼在半个多世纪前的1961年,在他的著作《自适应控制过程:导览》中首次提出的。


添加更多特征可能引发的问题

因此,添加更多特征很容易引发问题。这可能包括数据中出现冗余或不相关的特征。此外,当特征不为我们的模型提供预测能力时,还会增加噪声。除此之外,更多的特征使得人们更难解释和可视化数据。最后,更多的特征意味着更多的数据,因此你需要更多的存储空间和处理能力来处理它。最终,拥有更多维度通常意味着我们的模型效率更低。

当你遇到模型性能问题时,你常常会忍不住尝试添加越来越多的特征。但随着你添加更多特征,你会达到一个临界点,模型的性能开始下降。

下图很好地展示了这一点:随着维度的增加,分类器的性能在达到最佳特征数量之前会提升。这里需要理解的一个关键点是,你是在不增加训练样本数量的情况下增加维度,这导致分类器性能持续下降。


维度灾难背后的数学原理

为了揭示这种行为背后的原因,让我们更深入地探讨为什么更多维度会损害你的模型。让我们从理解为什么函数的参数数量会影响学习该函数的难度开始。

以线性函数的参数为例。在这种情况下,列表是有限的。这仅仅意味着对特征进行离散化。让我们通过使用1到5的数字来简化这个问题,假设你有一个函数只有一个参数。那么这个参数只能取五个可能的值。

如果你添加第二个也可以取五个值的参数会发生什么?那么现在有 5 * 5 = 25 种可能的参数对。这是一个使用离散参数值的简单例子,但当然,对于连续变量情况会更糟。

如果你现在添加第三个参数呢?表示形式变成了一个立方体。你可能已经看到了这背后的公式:如果我们有 n 个参数可以取的值和 M 个参数,你最终会得到 n^M 种可能的参数值。参数值的数量呈指数级增长。现在,这个问题有多大?确实,这是一个非常大的问题,这就是为什么它被称为“维度灾难”。


高维空间中的数据稀疏性

数据集维度的增加意味着代表每个训练样本的特征向量中有更多条目。让我们聚焦于欧几里得空间和欧几里得距离度量。每个新维度都会向总和中添加一个非负项。因此,对于不同的向量,距离随着维度的增加而增加。换句话说,对于给定数量的训练样本,随着特征数量的增长,特征空间变得越来越稀疏,训练样本之间的距离越来越大。

正因为如此,较低的数据密度需要更多的训练样本来保持数据点之间的平均距离相同。同样重要的是,你添加的样本需要与样本中已有的样本有显著不同。这里的论证是使用欧几里得距离构建的,但对于任何正确定义的距离度量都是成立的。


对监督学习的影响

当观测值之间的距离增大时,监督学习变得更加困难,因为对新样本的预测不太可能基于从相似训练样本中学到的知识。特征空间的大小随着特征数量的增加呈指数级增长,使得有效泛化变得更加困难。方差增加,并且在更多维度中过拟合噪声的几率更高,导致泛化性能差。

在实践中,特征也可能相关或没有表现出太多变化。由于这些原因,有必要进行降维。挑战在于使用尽可能少的特征,同时保留尽可能多的预测信息。


分类中的休斯效应

无论你使用哪种建模方法,增加维度还有另一个问题,特别是对于分类,这被称为休斯效应。这种现象展示了分类性能随着特征数量的增加而提高,直到我们达到拥有足够特征的最佳点。在保持训练集大小不变的情况下添加更多特征,将会降低分类器的性能。我们在前面的图表中看到了这一点。

在分类中,目标是找到一个能区分两个或多个类别的函数。你可以通过在空间中搜索分隔这些类别的超平面来实现这一点。你拥有的维度越多,在训练期间找到超平面就越容易。但同时,在泛化到未见数据时,要匹配这种性能就越困难。你拥有的训练数据越少,你就越不确定自己识别出了对区分类别重要的维度。


总结

在本节课中,我们一起学习了维度灾难的概念。我们了解到,虽然增加特征数量有时能提升模型性能,但超过某个最佳点后,反而会导致数据稀疏、距离度量失效、模型过拟合和性能下降。其核心原因在于特征空间随维度呈指数级膨胀,而训练数据量却无法同步增长。这解释了为什么在实践中,降维特征选择是构建高效、泛化能力强模型的关键步骤。理解维度灾难有助于我们在特征工程和模型构建中做出更明智的决策。

090:维度灾难示例 📊

在本节课中,我们将通过一个具体示例,探讨特征维度增加如何影响机器学习模型的性能与资源需求。我们将理解为何有时“更多”并不等同于“更好”。


维度增加带来的问题

上一节我们介绍了高维空间中距离和体积的直观变化。本节中我们来看看,除了这些几何问题,增加维度还会引发哪些实际挑战。

以下是维度增加可能带来的主要问题:

  • 计算资源需求非线性增长:处理器和内存需求通常随维度增加而非线性增长。
  • 优化难度增加:由于可行解数量呈指数级上升,许多优化方法难以找到全局最优解,容易陷入局部最优。
  • 特征相关性增强:维度增加通常意味着特征间存在相关性的可能性变大。
  • 参数估计困难:在回归模型中,参数估计常常会变得更具挑战性。

接下来,我们通过一个例子来具体看看更多特征如何使模型训练变得更困难。


特征增加对模型的影响

当你创建一个模型时,会为其设计特定数量的特征或维度。你可能会倾向于添加更多特征以获得更好的模型,但更多特征实际上可能损害模型性能。每个特征都包含信息,这些信息可能有助于也可能无助于模型进行准确预测。

随着添加的特征越来越多,你需要沿着这些特征的值域范围提供越来越多的训练样本。所需训练数据量随每个新增特征呈指数级增长。这意味着训练数据的“体积”呈指数增长。我们必须确保训练数据覆盖的特征空间区域,与我们将收到的预测请求所覆盖的区域相同。所有这些都可能降低模型的泛化能力。

与此同时,模型中可训练变量的数量也会增加。为了证明这一点,我们来看一个为克利夫兰心脏病数据集构建二元分类模型的例子,观察添加一个额外特征时发生的变化。


示例:克利夫兰心脏病数据集

我们首先为克利夫兰心脏病数据集创建一个结构化分类模型。该数据集包含 14个特征,用于预测患者是否患有心脏病。这是一个二元分类问题。

第一个模型省略了原始特征中的一个,名为 foul。我们将观察这一点,并看看向数据集中添加一个特征如何影响模型中可训练变量的数量。

现在,让我们将第一个模型中移除的那个额外特征添加回来。为此,我们使用 TensorFlow 中提供的 Keras 预处理层,将其编码为一个分类字符串特征。

接下来,我们看看添加它如何影响原始模型的可训练参数数量。如果你比较两者的可训练参数数量,即使只添加一个特征,也会导致参数数量 增加27%

这至少意味着参数数量有了显著增长,这将使训练速度更慢、成本更高。你还需要增加训练数据集的大小,这会使训练变得更慢、更昂贵。


核心结论与权衡

本节的核心要点是:当数据维度变得过大时,分类器的性能会下降,而对资源的需求会增加

随之而来的问题是:“过大”究竟意味着什么?遗憾的是,对于机器学习问题中应使用多少特征,并没有固定的规则。事实上,这取决于可用训练数据的数量、数据的方差、决策面的复杂性以及所使用的分类器类型。

它还取决于哪些特征真正包含有助于模型训练的预测信息。你的目标是:在尽可能简化模型的同时,拥有足够的数据、最佳的特征、这些特征值有足够的多样性,并且这些特征中包含足够的预测信息,以最大化模型的性能。


总结

本节课中,我们一起学习了维度灾难的一个具体示例。我们看到,向模型添加更多特征会导致可训练参数显著增加,进而需要更多训练数据,并可能损害模型的泛化能力。关键在于在模型复杂度和特征信息量之间找到平衡,使用足够多且高质量的特征,而非盲目追求数量。

091:手动降维 📉

在本节课中,我们将要学习手动降维技术。我们将探讨数据如何影响模型性能,以及如何通过特征工程和特征选择来减少数据维度,同时保留关键的预测信息。


上一节我们讨论了数据对模型性能及资源需求的影响,本节中我们来看看一些手动降维的技术。

在预处理一组特征以创建新特征集时,尽可能多地保留预测信息至关重要。没有预测信息,再多的数据也无法帮助模型学习。

特征必须能代表数据集中的预测信息。这些信息还需要以有助于模型学习的形式存在。

虽然一些固有特征可以直接从原始数据中获得,但通常需要衍生特征、归一化特征、工程化特征或嵌入特征。一个使用重要特征的普通模型,其性能会优于一个使用低质量或不良特征的优秀模型。

😊

许多领域涉及大量特征和维度。通常,特征的初步选择是基于领域知识,这可能导致特征数量超出实际需要。

正如我们在讨论维度灾难时所看到的,这存在固有的缺点。这意味着你需要减少维度,更准确地说,是在保留或提高数据所含预测信息量的同时,减少数据中包含的特征数量。

降维技术寻找数据中的模式,并利用这些模式以更低维度的形式重新表达数据。这使得计算效率大大提高,在大模型和大数据集的世界中,这可能是一个重要因素。

然而,降维最基本的功能是将数据集精简到核心部分,丢弃那些对回归和分类等监督学习任务造成严重问题的噪声特征。

在许多实际应用中,正是降维使得预测成为可能。你的数据收集和管理基础设施也将得到简化。

另一个需要考虑的因素是,当维度很大时,某些算法表现不佳。降维还能通过移除冗余特征来减少多重共线性。

当我们试图可视化数据时,降维也很有帮助。正如我们之前讨论的,在高维度中可视化数据并不容易。因此,将我们的空间降至2D或3D可能有助于我们更清晰地绘制和观察模式。

特征工程有助于满足这些要求。它通过重新格式化、组合和转换原始特征来从原始数据中构建有价值的信息,直到产生一个能带来更好模型的新数据集。

此外,特征选择会检查一组潜在特征,选择其中一部分并丢弃其余部分。应用特征选择是为了防止原始特征中的冗余和/或无关性,或者仅仅是为了将特征数量限制在一定范围内以避免问题。

既然我们已经了解了各种特征选择技术,现在让我们看看特征工程。最佳结果最终取决于你——实践者如何精心设计特征。这是机器学习工程带有些许艺术形式的领域之一。

特征重要性和特征选择可以帮助你了解特征的客观效用,但这些特征必须来自某个地方。你通常需要手动创建它们。这需要花费大量时间研究实际样本数据,思考问题的基本形式、数据的结构,以及如何最好地表达它们以供预测建模算法使用。😊

以下是针对不同类型数据的特征工程方法:

  • 对于表格数据:通常意味着聚合和/或组合特征以创建新特征,以及分解或拆分特征以创建新特征。
  • 对于文本数据:通常意味着设计与问题相关的文档或内容特定指标。
  • 对于图像数据:通常意味着使用过滤器来挑选出相关的结构,如像素、轮廓、形状和纹理。

特征工程往往是一个迭代过程,需要反复进行数据选择和模型评估。

以下是特征工程的一般流程:

该过程通常从头脑风暴特征开始。在这里,你需要深入问题,查看大量数据,研究其他问题上的特征工程,看看能学到什么。

然后,你开始设计新特征。这取决于你的问题,但你可以使用自动特征提取、手动特征工程或两者结合。

接下来,你使用特征重要性评分和特征选择方法挑选正确的特征,以准备数据的一个或多个视图。

最后,你使用选定的特征在未见过的数据上衡量模型的性能。


本节课中我们一起学习了手动降维的核心概念。我们了解到,降维旨在减少特征数量以提高计算效率并提升模型性能。关键方法包括特征工程(通过转换和组合创建新特征)和特征选择(筛选最有价值的特征)。这是一个需要结合领域知识和反复实践的迭代过程,对于构建高效、准确的机器学习模型至关重要。

092:手动降维案例研究 📊

在本节课中,我们将学习数据维度对模型性能及训练、部署资源需求的影响。我们将通过一个出租车费预测的具体案例,探索手动进行特征工程和降维的技术,以提升模型效率与效果。


数据维度的重要性

上一节我们介绍了数据维度对模型的影响。处理数据维度时,通常意味着需要寻找降低维度的方法。这在处理资源受限的场景(如移动端部署)时尤为重要。

现在,我们来看看一些手动降维的技术。


案例研究:出租车费数据集

让我们看一个使用出租车费数据集的具体例子。该数据集包含106,545次出租车行程记录。目标是根据多种特征(如上车时间、地点、行驶距离、乘客数量等)预测每次行程的车费。

通常,第一步是下载CSV格式的数据集,将变量分为字符串和数值类型,并定义有用的常量和参数。


建立基线模型

为了预测车费,我们先建立一个基线模型。我们将尝试使用以下特征:下车纬度、下车经度、乘客数量、上车纬度和上车经度。

网络结构由多个密集隐藏层串联而成,最后一层输出车费预测值。我们将使用Keras的函数式API构建模型。与顺序API不同,你需要指定输入层和隐藏层。

请注意,你正在创建一个没有特征工程的线性回归基线模型。快速回顾一下,基线模型是一个朴素的实现,有助于设定模型性能的期望。

在设置好训练模型并创建数据集后,你就可以开始训练基线模型了。只需调用 model.fit() 即可。


评估基线模型性能

让我们使用训练周期内的均方根误差损失来查看训练和验证性能。理想情况下,你希望验证集的RMSE接近训练集。

现在,让我们尝试改进模型以提高其性能。我们将创建两种新的特征工程类型:时间特征和地理特征。例如,我们将处理一个时间特征。


特征工程:时间与地理特征

上车日期时间是一个字符串,我们需要在模型内部处理它。首先,你将把上车日期时间作为一个特征包含进来,然后需要修改模型以将其作为字符串特征处理。

上车或下车的经度和纬度数据对于预测车费金额至关重要,因为纽约市出租车费主要由行驶距离决定。因此,我们需要教给模型上车点和下车点之间的欧几里得距离。

回想一下,纬度和经度允许我们使用一组坐标来指定地球上的任何位置。数据集包含有关上车和下车坐标的信息,但没有关于上车点和下车点之间距离的信息。

所以,让我们创建一个新特征来计算每对上车点和下车点之间的距离。你可以使用欧几里得距离来实现,它是任意两个坐标点之间的直线距离。但请注意,这只是实际驾驶距离的一个粗略指标。


数据标准化处理

在将数值变量输入神经网络之前,对其进行缩放非常重要。让我们对地理定位特征使用最小-最大缩放,也称为归一化。稍后在模型中,你会看到这些值被移动和重新缩放,最终范围在0到1之间。

我们利用领域知识创建一个名为 scale_longitude 的函数,传入所有经度值并为每个值加上78。请注意,我们的缩放经度值范围是从-70到-78,因此值78是最大经度值。-70和-78之间的差值是8。该函数为每个经度值加上78,然后除以8以返回缩放后的值。

类似地,我们创建一个名为 scale_latitude 的函数,传入所有纬度值并从每个值中减去37。请注意,我们的缩放纬度范围是从37到45。因此,值37是最小纬度值。-37和-45之间的差值也恰好是8。因此,该函数从每个纬度值中减去37,然后除以8以返回缩放后的值。

接下来,我们创建一个 geo_transform 函数。该函数将数值和字符串列特征作为输入传递给模型,然后按照上一张幻灯片所示缩放经度和纬度。接着,我们基于地理定位参数计算欧几里得距离。


分桶与特征交叉

除非地球的特定几何形状与你的数据相关,否则地图的分桶版本可能比原始输入更有用。这需要分别对纬度和经度维度进行分桶,然后将它们交叉,有效地对位置数据进行二维分桶。

在这个例子中,你对这些纬度和经度特征进行分桶,并基于地理定位特征创建特征交叉。

以下是代码为上车和下车的纬度和经度创建分桶列,然后为每个创建交叉列。代码将这些结果组合在一个嵌入列中。


新模型架构

这是你的模型的新架构。与第一次尝试的模型一样,你需要使用Keras的函数式API创建一个模型。当然,这将利用你到目前为止完成的所有特征工程。


新模型性能评估

让我们看看这个新模型的性能。观察训练和验证的结果,很明显,右侧进行了特征工程的模型相比左侧的基线模型有显著改进。


总结

本节课中,我们一起学习了数据维度管理的重要性,并通过出租车费预测案例实践了手动降维技术。我们建立了基线模型,并引入了时间与地理特征工程,包括数据标准化、欧几里得距离计算以及特征分桶与交叉。最终,改进后的模型性能得到了显著提升。这些技术对于在资源受限环境下构建高效模型至关重要。

093:算法降维 📉

在本节课中,我们将学习如何运用算法自动降低数据集的维度。除了手动处理,算法降维能更高效地发现数据中的关键结构。


上一节我们介绍了手动降维的概念,本节中我们来看看几种自动降维的算法方法。

线性降维的工作原理

首先,让我们建立对线性降维工作原理的直观理解。在这种方法中,我们将 N 维数据线性投影到一个更小的 K 维子空间上。通常,K 远小于 N

由于存在无限多个可能的子空间可供投影,因此我们需要选择最合适的一个。为了理解如何选择子空间,我们先退一步,看看如何将数据投影到一条直线上。

数据投影与嵌入

我们可以将特征视为存在于高维空间中的向量。虽然人类无法同时观察这么多维度,但通过将数据投影到低维空间,我们可能更直接地可视化数据分布。这种投影被称为嵌入

计算嵌入需要为每个样本计算一个(或多个)数值来描述它。降至一维的好处是,所有样本都可以在一条线上排序。例如,我们可以将图像包含的信息降至一维,比如其平均像素亮度,然后将每张图像可视化为这条线上的一个点。

以下是计算图像平均像素亮度的伪代码示例:

average_brightness = sum(pixel_values) / total_number_of_pixels

如何选择子空间

回到子空间选择的问题,根据任务目标的不同,有几种选择 K 维子空间的方法:

以下是几种常见方法及其适用场景:

  • 线性判别分析:在分类任务中,通常希望最大化不同类别之间的分离度。线性判别分析 在这方面效果很好。
  • 偏最小二乘法:在回归任务中,目标是最大化投影数据与输出之间的相关性。偏最小二乘法 是常用的方法。
  • 主成分分析:在无监督任务中,我们通常希望尽可能保留原始数据的方差。主成分分析 是应用最广泛的技术。

本节课中我们一起学习了算法降维的核心思想。我们了解到,通过线性投影可以将高维数据映射到低维子空间,并且可以根据任务目标(如分类、回归或无监督学习)选择不同的算法(如LDA、PLS或PCA)来找到最优的子空间。这为后续处理高维数据提供了强大的工具。

094:主成分分析 (PCA) 🧩

在本节课中,我们将要学习一种广泛使用的降维算法——主成分分析(PCA)。我们将了解其工作原理、核心目标、具体步骤以及如何在实践中应用它。


概述

降维有多种算法方法,主成分分析(PCA)是其中最广泛使用的之一。PCA是一种无监督算法,它通过创建原始特征的线性组合来减少数据的维度,同时尽可能保留数据中的信息。

PCA 的工作原理

上一节我们介绍了PCA是一种降维方法,本节中我们来看看它是如何具体工作的。

PCA通过两个步骤执行降维。第一步是去相关,这一步并不改变数据的维度。PCA首先旋转样本,使其与坐标轴对齐。实际上,它做的更多:PCA还会平移样本,使其均值为0。下图展示了PCA应用于鸢尾花数据集三个特征后的效果。

PCA被称为主成分分析,因为它学习数据的主成分。主成分是样本变化最大的方向,在图中用红色箭头表示。PCA正是将这些主成分与坐标轴对齐。

PCA 的核心目标

PCA的目标是找到一个低维平面,将数据投影到这个平面上,以最小化平方投影误差。换句话说,就是最小化每个数据点与其投影点之间距离的平方。

这个目标的结果是最大化投影的方差。

  • 第一主成分:是使投影数据方差最大的投影方向。
  • 第二主成分:是与第一主成分正交,并使剩余投影数据方差最大的投影方向。

一个简单的例子

让我们通过一个二维数据点的简单例子来应用PCA。

第一主成分是使投影数据(红点)方差最大的方向。在图中,你可以看到三条尝试线,很明显,红色线方向上的方差最大。

第二主成分是与第一主成分正交,并使剩余投影数据方差最大的方向,在图中用绿线表示。

完整的主成分集合构成了特征空间的一个新的正交基,其轴遵循原始数据的最大方差方向。当我们将原始数据投影到前K个主成分上时,就实现了数据的降维。

重构与误差

之后,你可以从这个降维后的投影中恢复原始空间。当然,这种重构会有一些误差,但考虑到降维带来的其他好处,这个误差通常是微不足道且可接受的。

观察红点随着线条旋转如何变化,那就是方差。你能看出它何时达到最大值吗?

其次,如果我们从新的红点重构原始的两个特征(蓝点),重构误差将由连接红点的红线长度给出。观察这些红线(误差线)的长度如何随着线条旋转而变化。你能看出总长度在哪里达到最小值吗?

在鸢尾花数据集上的应用

这里我们在鸢尾花数据集上应用具有两个主成分的PCA算法并可视化结果。

现在,假设你再次应用PCA,但使用四个成分而不是两个,让我们可视化这四个成分解释了多少方差。

如果你观察相对方差,可能会丢失一些信息。但如果特征值很小,则信息丢失不多。

主成分的特性与选择

正如我们之前所见,主成分本质上是正交的,这意味着它们是不相关的。同时,它们按照解释方差的多少进行排序。

  • 第一主成分解释了数据集中的最大方差。
  • 第二主成分解释了第二大方差,依此类推。

因此,你可以根据累积解释方差来限制保留的主成分数量,从而实现降维。例如,你可以决定只保留足够达到90%累积解释方差的主成分。

因子载荷是特征向量的非标准化值。我们可以将载荷解释为协方差或相关性。

使用 Scikit-learn 实现 PCA

Scikit-learn 提供了PCA的实现,它包含 fittransform 方法,就像标准缩放器一样,还有一个结合了 fittransformfit_transform 方法。

  • fit 方法学习如何平移和旋转样本,但实际上并不改变它们。
  • transform 方法则应用 fit 学到的变换。特别是,transform 方法可以应用于PCA之前未见过的新样本

以下是使用代码示例:

# 首先对特征使用标准缩放器
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# 创建PCA实例,保留99%的方差
from sklearn.decomposition import PCA
pca = PCA(n_components=0.99)

# 拟合数据并应用学到的变换
X_pca = pca.fit_transform(X_scaled)

总结与优缺点

综上所述,PCA是一种在实践中表现良好的有用技术。它快速且易于实现,这意味着你可以轻松地测试使用和不使用PCA的算法以比较性能。

此外,PCA提供了多种变体和扩展,例如核PCA或稀疏PCA等,以解决特定的障碍。

然而,PCA也有其局限性:

  1. 生成的主成分难以解释,这在可解释性很重要的某些场景中可能是一个致命缺点。
  2. 你仍然必须手动设置或调整累积解释方差的阈值。

尽管如此,PCA在可视化研究高维数据中的观测聚类时特别有用,例如在你仍在探索数据时。或者,当你有理由相信数据本质上是低秩时(即有很多属性,但只有少数几个属性主要通过线性关联决定其余属性),PCA也很有用。


本节课中我们一起学习了主成分分析(PCA)。我们了解了它是一种通过寻找数据最大方差方向来进行降维的无监督算法,掌握了其核心目标、计算步骤、特性以及如何使用Scikit-learn库实现它,并讨论了其优缺点和适用场景。

095:其他降维技术 🧩

在本节课中,我们将学习几种主成分分析之外的降维算法。我们将探讨奇异值分解、独立成分分析和非负矩阵分解等方法,了解它们各自的原理、适用场景以及与PCA的区别。


除了我们已经讨论过的技术,还有几种其他的算法方法可以进行降维。让我们来看看其中的一些。有些技术专注于特定类型的问题。

例如,在无监督方法中,有诸如奇异值分解SVD,以及独立成分分析ICA等技术。

在矩阵分解技术中,你可以使用非负矩阵分解。最后,潜在狄利克雷分配LDA是更流行的潜在降维方法之一。


奇异值分解 🔍

上一节我们介绍了降维的多种途径,本节中我们来看看奇异值分解

矩阵可以被视为空间中的线性变换。我们之前讨论过的PCA依赖于特征分解,而特征分解只能对方阵进行。当然,你并不总是拥有方阵。

例如,在TF-IDF中,高频词在某些情况下可能并不真正有效。一般来说,稀有词贡献更大,如果这些词在同一文档中出现的次数增加,其重要性也会增加。另一方面,在语料库中频繁出现的词的重要性会降低。

挑战在于,生成的矩阵非常稀疏且不是方阵。为了分解这些无法通过特征分解处理的矩阵,我们可以使用奇异值分解SVD等技术。

SVD将我们的原始数据集分解为其组成部分,从而实现降维。它用于从数据集中移除冗余特征。

公式表示
对于一个矩阵 A (m×n),SVD将其分解为:
A = U Σ V^T
其中 U 是 m×m 正交矩阵,Σ 是 m×n 对角矩阵(奇异值),V^T 是 n×n 正交矩阵的转置。


独立成分分析 🧠

接下来,我们转向另一种基于信息论的算法——独立成分分析

它也是最广泛使用的降维技术之一。PCA和ICA的一个显著区别是,PCA寻找不相关的因素,而ICA寻找独立的因素。

如果两个因素不相关,意味着它们之间没有线性关系。如果它们独立,则意味着它们不依赖于其他变量。例如,一个人的年龄与他吃什么或看多少电视是独立的(可能)。尽管你可能注意到不同年龄组在食物选择和看电视方面存在模式。

独立成分分析将多元信号分离为最大程度上独立的加性分量。ICA通常不用于降维,而是用于分离叠加的信号。

由于ICA模型不包含噪声项,因此必须应用白化处理。这可以通过多种方式完成,包括使用PCA的某个变体。

ICA进一步假设存在独立信号 S,以及信号的线性组合 Y。ICA的目标是从 Y 中恢复原始信号 S

ICA假设给定变量是某些未知潜在变量的线性混合。它还假设这些潜在变量是相互独立的,换句话说,它们不依赖于其他变量,因此它们被称为观测数据的独立成分

让我们直观地比较一下PCA和ICA,以更好地理解它们的不同之处。两者都是统计变换,即PCA使用从二阶统计量中提取的信息,而ICA则使用更高阶的统计量。

两者都用于各种领域,如盲源分离、特征提取以及神经科学。ICA是一种在特征空间中寻找方向的算法,这些方向对应于高度非高斯分布的投影。

与PCA不同,这些方向在原始特征空间中不需要正交,但在白化后的特征空间中是正交的,其中所有方向都对应于相同的方差。

另一方面,PCA在原始特征空间中找到正交方向,这些方向对应于能解释最大方差的方向。

让我们看一个模拟:左侧使用高度非高斯过程模拟两个独立源。接下来,应用混合方案来创建观测值。在这个原始观测空间中,由PCA识别的方向用橙色向量表示。然后,在PCA向量对应的方差白化后,在PCA空间中表示信号。运行ICA对应于在这个空间中进行旋转,以识别最非高斯的方向(右下角)。

从图中可以看出,PCA去除了相关性,但没有去除高阶依赖性;相反,ICA去除了相关性以及高阶依赖性。在成分重要性方面,PCA认为其中一些成分比其他成分更重要,而ICA则认为所有成分同等重要。


非负矩阵分解 📊

现在让我们讨论一种称为非负矩阵分解的降维技术。

NMF将样本表示为可解释部分的组合。例如,它将文档表示为主题的组合,将图像表示为常见视觉模式的组合。

与PCA一样,NMF是一种降维技术。然而,与PCA相比,NMF模型是可解释的。这意味着NMF模型更容易理解,也更容易向他人解释。

NMF不能应用于每个数据集。它要求样本特征是非负的,即值必须大于或等于0。已经观察到,在精心约束下,NMF可以产生数据集的基于部分的表示,从而得到可解释的模型。

以下是一个示例,右侧显示了NMF从Olivetti人脸数据集的图像中找到的16个稀疏成分,左侧是PCA特征脸。


总结 📝

本节课中我们一起学习了三种重要的降维技术:

  1. 奇异值分解:通过分解非方阵来去除冗余特征。
  2. 独立成分分析:专注于寻找统计上独立的成分,适用于信号分离。
  3. 非负矩阵分解:产生可解释的、基于部分的表示,但要求数据非负。

每种技术都有其独特的假设和适用场景,是PCA之外处理特定降维问题的有力工具。理解它们的区别有助于在实际项目中做出合适的选择。

097:模型量化技术详解 🚀

在本节课中,我们将要学习模型量化技术。这是一种优化模型以提升其在资源受限环境(如移动设备和物联网设备)中部署效率的关键方法。我们将探讨量化的基本概念、好处、具体流程以及其对模型性能的影响。

上一节我们介绍了模型部署面临的挑战,本节中我们来看看如何通过量化技术来优化模型。

量化概述与动机

量化是指将模型转换为一种使用更低精度参数和计算的等效表示形式。这能提升模型的执行性能和效率,但通常会导致模型精度略有下降。

为了更好理解,可以想象一张图片。图片是由像素网格组成的,每个像素有一定数量的比特。将现实世界的连续色彩光谱减少为离散颜色的过程,就是一种量化或近似。本质上,量化减少了表示信息所需的比特数。

神经网络模型可能占用大量磁盘空间。例如,AlexNet模型需要约200MB的存储空间。其大小主要由神经网络连接的权重参数占据,这些权重通常是数百万个略有不同的浮点数。最直接的量化动机是缩小文件大小。对于移动应用,在手机上存储一个200MB的模型来运行单个应用通常是不切实际的,因此压缩高精度模型是必要的。

另一个量化原因是为了减少推理计算所需的计算资源,通过完全使用低精度输入和输出来运行。这虽然实现起来更困难,但能带来显著回报:模型运行更快、功耗更低,并且为许多无法高效运行浮点计算的嵌入式系统(如物联网设备)打开了应用之门。

量化的好处

以下是量化带来的主要优势:

  • 提升速度:在硬件支持的前提下,低比特深度的算术运算更快。从32位浮点数转换到8位整数,通常能获得约4倍的内存减少和速度提升。
  • 减小模型体积:更轻量的部署模型意味着占用更少的存储空间,更容易通过较小带宽进行分享和更新。
  • 提高能效:低比特深度意味着可以将更多数据塞入相同的缓存和寄存器中,从而构建具有更好缓存能力的应用,降低功耗并运行得更快。
  • 增强硬件兼容性:浮点运算复杂,并非所有微控制器和超低功耗嵌入式设备(如无人机、手表)都支持。而整数运算支持则普遍可用。

量化的原理与影响

神经网络由节点、节点间的连接、每条连接关联的权重参数以及偏置项组成。量化主要针对这些权重参数和激活节点的计算进行。

量化将一小段浮点数值范围挤压到固定数量的信息“桶”中。这个过程本质是有损的,但特定层的权重和激活值往往分布在一个较小的、可以预先估计的范围内。这意味着我们不需要用同一种数据类型来存储整个大范围,而是可以将宝贵的有限比特集中在更小的范围(例如-3到+3)内。如果操作得当,量化只会造成很小的精度损失,通常不会显著改变输出结果。

现在,让我们看看量化会影响模型的哪些部分:

  • 静态参数:如各层的权重。
  • 动态参数:如网络内部的激活值。
  • 结构变换:如添加、修改或删除操作,合并不同操作等。

在某些情况下,变换可能需要额外数据。例如,在量化的一种技术中,会使用一些未标记的数据来确定缩放参数。

优化通常会导致模型精度的变化,这在应用开发过程中必须予以考虑。精度变化取决于被优化的具体模型和数据,很难提前预测。一般来说,为体积和延迟优化的模型会损失一定精度。根据应用场景,这可能影响也可能不影响用户体验。在极少数情况下,某些模型可能因优化过程而获得精度提升。

实践中的权衡与步骤

移动和嵌入式设备的计算资源有限,因此保持应用资源高效至关重要。根据任务需求,你需要在模型精度和模型复杂度之间做出权衡。

如果任务要求高精度,则可能需要一个庞大而复杂的模型。对于精度要求较低的任务,最好使用更小、更简单的模型,因为它们不仅占用更少的内存和磁盘空间,而且通常更快、更节能。

例如,MobileNets就是为移动设备优化的模型系列,专为移动视觉应用设计,在设备延迟和ImageNet分类精度之间实现了先进的权衡。

一旦为你的任务选定了候选模型,一个好的做法是对模型进行分析和基准测试。

本节课中我们一起学习了模型量化的核心概念、优势、工作原理以及在实践中的应用考量。量化是模型部署,特别是在资源受限环境下的关键优化步骤,它通过权衡精度以换取显著的效率提升,从而使得复杂的机器学习模型能够在更广泛的设备上运行。

098:后训练量化 🧠

在本节课中,我们将学习一种名为“后训练量化”的模型优化技术。这项技术可以在几乎不影响模型准确性的前提下,显著减小模型体积并提升其在CPU和硬件加速器上的推理速度。

量化可以在模型训练期间进行,也可以在模型训练完成后进行。本节我们首先关注后训练量化。

什么是后训练量化?🔍

后训练量化是一种转换技术,它能在模型精度损失很小的情况下,减小模型体积,同时改善CPU和硬件加速器的推理延迟。

你可以使用TensorFlow Lite转换器,将一个已训练好的TensorFlow模型转换为TensorFlow Lite格式时,对其进行量化。这种方法易于使用,因为它已直接集成到TF Lite转换器中。

后训练量化的核心作用,是以高效的方式将权重从浮点数转换为整数

通过这种方式,你可以在不显著影响准确性的前提下,获得高达三倍的延迟降低

量化选项与策略 ⚙️

使用默认的优化策略时,转换器会尽力应用后训练量化,尝试同时优化模型的体积和延迟。这是推荐的做法,但你也可以自定义此行为。

以下是几种可供选择的后训练量化选项及其优势的总结:

  • 动态范围量化:如果你希望获得约2-3倍的加速,同时模型体积减小约一半,可以考虑此选项。
  • 全整数量化浮点16量化:如果你希望从模型中榨取更多性能,这两种量化方式可能带来更快的推理速度。其中,浮点16量化在你计划使用GPU时尤其有用。

在动态范围量化中,推理时权重会从8位整数转换为浮点数,激活值则使用浮点内核进行计算。这种转换只进行一次并被缓存,以降低延迟。这种优化提供的延迟,接近于完全定点推理。

如何实施后训练量化?💻

后训练量化仅需两行代码即可实现。

首先,导入TensorFlow并定义一个TF Lite转换器。

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)

然后,设置转换器以优化模型体积。

converter.optimizations = [tf.lite.Optimize.DEFAULT]

最后,应用转换器转换你的模型。其他可用的优化模式包括OPTIMIZE_FOR_LATENCY(降低模型延迟),而DEFAULT模式则默认尝试同时优化速度和存储。

更进一步的量化:全整数量化 🚀

上一节我们介绍了动态范围量化,本节我们来看看更进一步的优化选项。

通过提供代表性数据集,可以应用增强的优化,例如动态范围量化。这可以减少模型体积和/或延迟,但它有一个限制:推理仍需使用浮点数。

这并非总是理想的选择,因为某些硬件加速器(例如Edge TPUs)仅支持整数运算。因此,优化工具包也支持后训练全整数量化

这项技术使用户能够获取已训练的浮点模型,并将其完全量化为仅使用8位有符号整数,从而使得定点硬件加速器能够运行这些模型。当目标是获得更大的CPU改进或使用定点加速器时,这通常是更好的选择。

后训练整数量化通过收集校准数据来工作。它在一小部分输入上运行推理,以确定将模型转换为整数量化模型所需的正确缩放参数。

量化后的考量与总结 📝

后训练量化可能导致精度损失,特别是对于较小的网络,但这种损失通常可以忽略不计。从积极的一面看,它通过使用较低精度处理最繁重的计算,而使用较高精度处理最敏感的计算,从而加速了执行速度,因此通常导致很少或没有最终的精度损失。

TensorFlow Lite模型库中也为特定网络提供了预训练的全量化模型。重要的是,需要检查量化后模型的准确性,以验证任何精度下降是否在可接受的范围内。TensorFlow Lite包含一个评估模型准确性的工具。

或者,如果精度损失过大,可以考虑使用量化感知训练。然而,这样做需要在模型训练期间进行修改以添加伪量化节点,而后训练量化技术则相对简单。


本节课总结:我们一起学习了后训练量化的概念、优势以及实施方法。我们了解到,量化是一种强大的模型优化技术,能够有效平衡模型大小、推理速度和准确性,尤其适用于移动端和边缘设备的部署场景。

099:量化感知训练 🧠

在本节课中,我们将要学习量化感知训练。这是一种在模型训练过程中就模拟量化效果的技术,旨在让模型学习到的参数对后续的定点化操作更具鲁棒性,从而在部署时获得更好的精度与性能平衡。


概述

量化感知训练的核心思想是在训练阶段的前向传播路径中,模拟低精度推理时的计算过程。通过插入“伪量化”节点,模型可以在训练时就“感知”到量化带来的舍入误差,并据此调整权重,以最小化最终部署时的精度损失。

上一节我们介绍了训练后量化,本节中我们来看看如何在训练过程中就融入量化。


量化感知训练的原理

最简单的神经网络量化方法是先以全精度训练模型,然后直接将权重量化为定点数,这被称为训练后量化。

相比之下,量化感知训练在模型训练时就应用量化。

其核心思想是,量化感知训练在训练过程的前向传播中,模拟低精度推理时的计算。

通过插入伪量化节点,在训练的前向传播中模拟量化通常会发生的舍入效应。

目标是微调权重,以适应精度损失。

因此,如果在模型图中预期会发生量化的位置(例如,在卷积层)包含了伪量化节点。

那么在训练的前向传播中,浮点数值将被舍入到指定的量化级别,以模拟量化的效果。

这会在训练过程中将量化误差作为噪声引入,并成为整体损失的一部分,优化算法会尝试最小化这个损失。

这样,模型就能学习到对量化更具鲁棒性的参数。


量化感知训练的过程

接下来,让我们看看在训练期间量化模型的具体过程。

在量化感知训练中,你首先像往常一样构建模型,然后使用 TensorFlow 模型优化工具包的 API 使其具备量化感知能力。

最后,你使用量化模拟操作来训练这个模型,以获得我们最终的纯整数量化模型。

让我们看一下这个展示神经网络基本操作的简化图。

下一步是添加量化模拟操作。

量化模拟操作需要被放置在训练图中,其放置方式要与量化图的计算方式保持一致。

权重量化和激活量化操作在模型的前向传播中引入损失,以模拟推理期间的实际量化损失。

请注意,在卷积层和 ReLU6 之间没有量化操作。

这是因为在 TensorFlow Lite 中,ReLU 操作会被融合。

量化感知训练 API 使得为整个模型或仅部分模型训练量化感知能力变得容易,然后可以将其导出以使用 TensorFlow Lite 进行部署。

因此,为了使整个模型具备量化感知能力,我们应用 tfmot.quantization.keras.quantize_model 到模型。

import tensorflow_model_optimization as tfmot

quant_aware_model = tfmot.quantization.keras.quantize_model(model)

API 的灵活性与高级用法

该 API 也非常灵活,能够处理更复杂的用例。

例如,它允许你在层内精确控制量化、创建自定义量化算法,并处理你可能编写的任何自定义层。

以下是量化感知训练的一些高级应用场景:

你可以选择性地量化模型的某些层,以探索精度、速度和模型大小之间的权衡。例如,尝试量化后面的层而不是前面的层。

请始终记住,避免量化关键层,例如 Transformer 架构中的注意力机制。

例如,如果你的激活函数或其他操作恰好是量化感知框架尚未支持的,你可以使用量化配置来解决这个问题。

例如,在这段代码片段中,调用了一个像 DefaultDenseQuantizeConfig 这样的自定义配置来量化一个自定义层。

quantize_config = tfmot.quantization.keras.QuantizeConfig(
    # ... 自定义配置细节
)

最后,在调用 quantize_apply 之前,记得在你的量化作用域中包含你的自定义配置。

with tfmot.quantization.keras.quantize_scope({'CustomLayer': CustomLayer,
                                              'DefaultDenseQuantizeConfig': DefaultDenseQuantizeConfig}):
    # 应用量化
    model = tfmot.quantization.keras.quantize_apply(model, quantize_config)

效果评估:精度、延迟与模型大小

以下是一些模型在量化后的精度损失结果。这可以让你对自己的模型可能发生的情况有一个大致的预期。

接下来,让我们看看几个模型的推理延迟。请记住,在这种情况下,数值越低越好。

最后,让我们看看模型的大小。同样,数值越低越好。


总结

本节课中,我们一起学习了量化感知训练。我们了解了其核心原理是在训练时通过伪量化节点模拟推理时的量化误差,从而使模型参数对量化更具鲁棒性。我们探讨了使用 TensorFlow 工具包实施量化感知训练的基本流程,并介绍了其 API 在选择性量化、处理自定义层等方面的灵活性。最后,我们通过精度、延迟和模型大小的数据,直观地认识了量化带来的影响。掌握量化感知训练,是优化模型以便在资源受限环境中高效部署的关键一步。

100:模型剪枝 🧹

在本节课中,我们将学习一种提升模型效率的重要方法——模型剪枝。我们将探讨其核心概念、历史背景、工作原理、具体实现及其带来的益处。


概述

另一种提升模型效率的方法是移除那些对产生准确结果贡献不大的模型部分。这被称为剪枝。现在我们来讨论它。

优化机器学习程序可以采取多种形式。幸运的是,神经网络已被证明对旨在实现该目标的各种变换具有鲁棒性。

上一节我们讨论了模型量化的方法,本节中我们来看看如何通过剪枝来精简模型。

剪枝的动机与概念

当你考虑具有更多层和节点的更广泛神经网络时,减少其存储和计算成本变得至关重要,尤其对于一些实时应用。随着机器学习模型被部署到移动电话等嵌入式设备中,模型压缩变得日益重要,压缩神经网络的重要性也随之增长。

剪枝是深度学习中一个受生物学启发的概念。

剪枝旨在通过移除网络连接来减少生成预测所涉及的参数和操作数量。因此,通过剪枝,你可以降低网络中的总体参数数量。

网络通常看起来像左边这样。在这里,一层中的每个神经元都连接到它前面的一层。但这意味着我们必须将许多浮点数相乘。理想情况下,我们只将每个神经元连接到少数其他神经元,从而节省一些乘法运算。如果我们能找到一种方法在不过多损失精度的情况下做到这一点,那就是剪枝背后的动机。

稀疏性的重要性

连接稀疏性长期以来一直是神经科学研究的基本原则,也是关于新皮质的关键观察之一。在大脑的任何地方,神经元的活动总是稀疏的,但常见的神经网络架构有很多参数,而这些参数通常并不稀疏。以 ResNet-50 为例,它拥有近 2500 万个连接。

这意味着在训练期间,我们需要调整 2500 万个权重,这至少可以说是相对昂贵的。因此,需要以某种方式解决这个问题。

神经网络中稀疏性的故事始于剪枝,这是一种通过压缩来减小神经网络大小的方法。

以下是减少参数数量带来的几个好处:

  • 模型更小更快:稀疏网络不仅更小,而且训练和使用速度更快。
  • 适用于资源受限环境:在硬件受限的环境中,例如嵌入式设备或智能手机,速度和大小可以决定模型的成败。
  • 缓解过拟合:更复杂的模型更容易过拟合。因此,在某种意义上,限制搜索空间也可以起到正则化的作用。

然而,即便如此,这也不是一项简单的任务,因为降低模型的容量也可能导致精度损失。因此,与许多其他领域一样,复杂性和性能之间存在着微妙的平衡。

现在,让我们更深入地了解一些挑战和潜在的解决方案。

剪枝的历史与方法演变

让我们从一点历史开始。第一篇倡导神经网络稀疏性的重要论文可以追溯到 1990 年,由 Janon Lacoon、John S. Denker 和 Sarah A. Solla 撰写,标题相当具有挑衅性,名为《最优脑损伤》。当时,对训练好的模型进行后剪枝以压缩模型已经是一种流行的方法。

剪枝主要通过使用权重幅度作为显著性的近似值来确定不太有用的连接。其直觉是,幅度较小的权重对输出的影响较小,因此如果被剪枝,对模型结果的影响也较小。

这是一种迭代剪枝方法:

  1. 第一步是训练一个模型。
  2. 然后估计每个权重的显著性,其定义为对网络中的神经元施加扰动时损失函数的变化。
  3. 变化越小,权重对训练的影响就越小。
  4. 最后,他们消除显著性最低的权重。这相当于将它们设置为零。
  5. 最后,对这个剪枝后的模型进行重新训练。

这种方法在重新训练剪枝后的网络时出现了一个特别的挑战。事实证明,由于其容量减少,重新训练变得更加困难。

这个问题的解决方案后来才出现,伴随着一个被称为彩票假设的见解。

彩票假设

赢得彩票头奖的概率非常低。例如,如果你玩强力球,中头奖的几率大约是 300 万分之一。如果你购买 N 张彩票,你的机会是多少?

所以,如果获胜的概率是 P = 1/3,000,000,那么不获胜的几率就是其补集 1 - P。将其扩展到购买 n 张彩票时,我们得到概率为 (1 - P)^N。由此可知,至少有一张中奖的概率再次简单地是其补集。

这与神经网络有什么关系?在训练之前,模型的权重是随机初始化的。是否可能存在一个随机初始化网络的子网络,它赢得了“初始化彩票”?

一些研究人员着手调查这个问题并寻找答案。最值得注意的是,Frankle 和 Carbin 在 2019 年发现,对于这些新剪枝的网络,训练后对权重进行微调并不是必需的。

事实上,他们表明,最好的方法是将权重重置为其原始值,然后重新训练整个网络。与 Han 及其同事提出的原始密集模型以及后剪枝加微调方法相比,这将导致模型具有更高的准确性。

这一发现使他们提出了一个最初被认为是疯狂的、但现在被普遍接受的想法:过度参数化的密集网络包含多个具有不同性能的稀疏子网络,其中一个子网络就是“中奖彩票”,其性能优于所有其他子网络。

然而,这种方法存在显著的局限性。首先,它对于更大规模的问题和架构表现不佳。在原论文中,作者指出,对于像 ImageNet 这样更复杂的数据集和像 ResNet 这样更深的架构,该方法通常无法识别初始化彩票的赢家。

现代剪枝实践与 TensorFlow 工具

实现良好的稀疏性与准确性权衡是一个难题,也是一个非常活跃的研究领域,最先进的技术不断改进。

TensorFlow 包含一个基于 Keras 的权重剪枝 API,它使用一种简单但广泛适用的算法,旨在训练期间根据权重幅度迭代地移除连接。

从根本上说,需要指定一个最终的目标稀疏度,以及一个执行剪枝的时间表

在此图中,你可以看到在训练期间,将按计划执行剪枝例程,移除幅度值最低、最接近 0 的权重,直到达到当前稀疏度目标。每次计划执行剪枝例程时,都会重新计算当前稀疏度目标,从 0% 开始,直到在剪枝时间表结束时,根据平滑的斜坡上升函数逐渐增加,达到最终的目标稀疏度。

就像时间表一样,斜坡上升函数可以根据需要进行调整。例如,在某些情况下,可能需要在达到一定收敛水平后的某个步骤开始安排训练过程,或者在你的训练程序的总训练步骤数之前结束剪枝,以在最终目标稀疏度水平上进一步微调系统。

稀疏度随着训练的进行而增加。所以你需要知道何时停止。这意味着在训练过程结束时,对应于已剪枝的 Keras 层的张量将根据该层的最终稀疏度目标,在权重已被剪枝的位置包含零。

剪枝带来的益处

你可以从剪枝中获得的一个直接好处是磁盘压缩。这是因为稀疏张量是可压缩的。因此,通过对剪枝后的 TensorFlow 检查点或转换后的 TensorFlow Lite 模型应用简单的文件压缩,我们可以减小模型的大小以便存储和/或传输。在某些情况下,你甚至可以在利用整数精度效率的 CPU 和机器学习加速器上获得速度提升。

此外,在多项实验中,我们发现权重剪枝与量化是兼容的,从而产生复合效益。在接下来的练习中,我们将展示通过应用训练后量化,我们可以将剪枝后的模型从两兆字节进一步压缩到仅约半兆字节。

在不久的将来,TensorFlow Lite 将增加对稀疏表示和计算的一流支持,从而将压缩优势扩展到运行时内存,并解锁性能提升,因为稀疏张量允许你跳过涉及零值的不必要计算。或者,取决于你观看此内容的时间,它可能已经包含在内。

如何使用剪枝 API

要使用剪枝 API,你首先需要创建一个 TensorFlow Keras 模型。然后,我们向模型中的某些层添加稀疏性,并重新训练或训练它。最后,你还可以通过将剪枝后的模型转换为 TF Lite 来获得量化的好处。

在此示例中,让我们将剪枝应用于整个模型。你从 50% 的稀疏度(即权重中 50% 为零)开始,最终达到 80% 的稀疏度。你也可以仅剪枝模型的一部分或特定层,以改进模型精度。稍后,你将看到如何使用 TensorFlow Model Optimization Toolkit API 为 TensorFlow 和 TF Lite 创建稀疏模型。然后,你可以将剪枝与训练后量化结合以获得额外的好处。

此外,这种技术可以成功地应用于跨不同任务的各种类型的模型,从基于卷积的图像处理神经网络到使用循环神经网络的语音处理。此表显示了一些实验结果。


总结

本节课中我们一起学习了模型剪枝技术。我们了解到,剪枝是一种通过移除神经网络中不重要的连接来减少模型大小和计算成本的有效方法。它受大脑神经元活动稀疏性的启发,能够提升模型在资源受限环境下的部署效率。我们从其历史发展、核心的“彩票假设”原理,到现代 TensorFlow 中的具体实现工具都进行了探讨。最后,我们看到了剪枝与量化技术结合所能带来的复合优势,这是优化生产环境机器学习模型的重要一环。

101:分布式训练 🚀

在本节课中,我们将要学习分布式训练的核心概念与技术。随着数据集和模型规模的不断增长,单机训练可能变得非常耗时。分布式训练允许我们利用多台机器或多个加速器(如GPU)来并行处理训练任务,从而显著缩短训练时间并支持训练超大规模模型。

上一节我们介绍了分布式训练的必要性,本节中我们来看看实现分布式训练的两种基本方式。

数据并行与模型并行

分布式训练主要有两种基本范式:数据并行和模型并行。

数据并行

数据并行可能是两者中较易实现的一种。在这种方法中,数据被划分为多个分区。完整的模型被复制到所有工作节点上,每个节点处理不同的数据分区,模型更新在工作节点间同步。这种并行方式与模型架构无关,可应用于任何神经网络。

通常,数据并行的规模与批次大小相对应。

模型并行

在模型并行中,模型本身被分割成不同的部分,在不同的工作节点上并发训练。每个模型部分在同一份数据上进行训练。这里,工作节点只需要同步共享的参数,通常在每个前向或反向传播步骤中进行一次。

当模型过大,无法放入单个加速器的内存时,通常会使用模型并行。与数据并行相比,模型并行的实现相对复杂。

模型并行是一个更复杂的主题。因此,我们现在先通过图示了解数据并行的工作原理,稍后再讨论模型并行。

数据并行的工作原理

在数据并行中,数据被分割成多个分区。分区的数量通常是计算集群中可用工作节点的总数。

为了进行训练,模型被复制到每个工作节点上,每个节点在其自己的数据子集上进行训练。这要求每个工作节点都有足够的内存来加载整个模型,对于大型模型来说,这可能是个问题。

每个工作节点独立计算其训练样本的预测值与标注数据之间的误差。然后,每个工作节点执行反向传播,根据误差更新其模型,并将其所有更改通信给其他工作节点,以便它们更新自己的模型。

这意味着工作节点需要在每个批次结束时同步它们的梯度,以确保它们训练的是同一个一致的模型。

以下是使用数据并行进行分布式训练的两种基本风格:

  • 同步训练:每个工作节点在其当前的小批次数据上进行训练,计算其自身的更新,将其更新通信给其他工作节点,并在进行下一个小批次之前等待接收并应用来自所有其他工作节点的更新。All-Reduce算法就是这种风格的一个例子。
  • 异步训练:所有工作节点独立地在其小批次数据上进行训练,并异步地更新变量。参数服务器算法是这种风格的一个例子。异步训练往往效率更高,但实现起来可能更困难。

异步训练的一个主要缺点是精度降低和收敛速度变慢,这意味着需要更多的步骤才能收敛。收敛速度慢可能不是问题,因为异步训练带来的加速可能足以弥补。然而,精度损失可能是个问题,具体取决于损失了多少精度以及应用的要求。

使模型支持分布式训练

要使用分布式训练,模型必须变得“分布式感知”。幸运的是,像Keras或Estimators这样的高级API支持分布式训练。你甚至可以创建自定义训练循环以提供更精确的控制。

你会发现,为了使这些普通模型能够以分布式方式进行训练或推理,你需要通过一些小的代码更改使它们支持分布式。通过这样做,你就可以获得在大量加速器(如GPU或TPU)上训练模型的强大能力。

具体来说,要在TensorFlow中执行分布式训练,你可以利用TensorFlow的tf.distribute.Strategy类库。这个类支持多种用于高级API的分布式策略,也支持使用自定义训练循环进行训练。tf.distribute.Strategy类不仅支持在Eager模式下执行TensorFlow代码,也支持在图模式下以及使用tf.function

除了训练模型,还可以使用此API在不同平台上以分布式方式执行模型评估和预测。它只需要最少的额外代码来使你的模型适应分布式训练。你可以轻松地在不同策略之间切换,进行实验并找到最适合你需求的策略。

TensorFlow分布式策略

TensorFlow有许多不同的策略来执行分布式训练。以下是最常用的几种:

  • OneDeviceStrategy
  • MirroredStrategy
  • ParameterServerStrategy
  • MultiWorkerMirroredStrategy
  • CentralStorageStrategy
  • TPUStrategy

让我们重点了解前三种选项。关于tf.distribute.Strategy的更多信息,请参阅资源部分的链接。

OneDeviceStrategy 会将在其作用域内创建的任何变量放置在指定的设备上。通过该策略输入的分布式数据将被预取到指定设备。此外,通过strategy.run调用的任何函数也将被放置在指定设备上。该策略的典型用法是在切换到实际分发到多个设备和机器的其他策略之前,使用tf.distribute.Strategy API测试你的代码。因此,这通常是你在开发中使用的东西。

MirroredStrategy 支持在一台机器的多个GPU上进行同步分布式训练。它为每个GPU设备创建一个副本。模型中的每个变量在所有其他副本之间进行镜像。这些变量共同形成一个称为“镜像变量”的单一概念变量。这些变量通过应用相同的更新来保持彼此同步。高效的All-Reduce算法用于在设备之间通信变量更新。All-Reduce通过对所有设备上的张量进行求和来聚合它们,并使每个设备上都可以使用。它是一种融合算法,非常高效,可以显著减少同步开销。

ParameterServerStrategy 是一种常见的异步数据并行方法,用于在多台机器上扩展模型训练。一个参数服务器训练集群由工作节点和参数服务器组成。变量在参数服务器上创建,并在每个步骤中由工作节点读取和更新。默认情况下,工作节点独立读取和更新这些变量,彼此之间不同步。这就是为什么有时参数服务器风格的训练也被称为异步训练。

容错性考量

通常在同步训练中,如果一个或多个工作节点发生故障,整个工作节点集群都会失败。在工作节点死亡或不稳定的情况下,考虑某种形式的容错性非常重要。这允许你从因抢占工作节点而导致的故障中恢复。这可以通过在分布式文件系统中保存训练状态来实现。

由于所有工作节点在训练轮次和步骤方面都保持同步,其他工作节点需要等待失败或被抢占的工作节点重新启动才能继续。

例如,在MultiWorkerMirroredStrategy中,如果一个工作节点被中断,整个集群会暂停,直到被中断的工作节点重新启动。其他工作节点也会重新启动,被中断的工作节点重新加入集群。然后需要有一种方式让每个工作节点恢复其之前的状态,从而使集群重新同步,让训练顺利进行。例如,Keras在BackupAndRestore回调中提供了此功能。


本节课中我们一起学习了分布式训练的核心概念,包括数据并行和模型并行的基本原理,以及如何使用TensorFlow的tf.distribute.Strategy来实现不同的分布式训练策略。我们还探讨了同步与异步训练的差异,以及在分布式环境中需要考虑的容错性问题。掌握这些知识将帮助你有效地利用计算资源,加速大规模机器学习模型的训练过程。

102:高性能数据输入 🚀

在本节课中,我们将要学习如何构建高性能的数据输入管道。这对于高效利用昂贵的计算资源(如GPU/TPU)至关重要,因为我们需要确保这些加速器在训练或推理过程中能够持续获得足够的数据,避免因等待数据而空闲。


为什么需要高性能输入管道?🤔

上一节我们提到了加速器的重要性,本节中我们来看看如何高效地为它们提供数据。

加速器是高性能建模、训练和推理的关键部分。但加速器价格昂贵,因此高效使用它们非常重要。这意味着要让它们保持忙碌状态,这要求你能够足够快地为它们提供足够的数据。这就是为什么在高性能建模中,高性能的数据摄取如此重要。

现在,我们来讨论为什么训练模型通常需要输入管道,以及围绕数据应用转换时可能出现的问题。

通常,转换处理的是预处理任务,这往往会增加训练输入管道的开销。例如,在对庞大的图像分类数据集进行数据增强时,许多转换通常是逐元素应用的。因此,如果应用转换花费的时间太长,可能会导致CPU在等待数据时利用率不足。

问题不仅限于转换。有时,你可能拥有根本无法装入内存的数据。构建一个可扩展的输入数据管道,使其能够足够快地提供数据以保持训练处理器忙碌,通常成为一个挑战。

最终,目标应该是高效利用可用硬件,减少从磁盘加载数据所需的时间,并减少预处理所需的时间。

输入管道是许多训练管道的重要组成部分,但推理管道通常也有类似的要求。在更大的训练管道(如TFX训练管道)背景下,高性能输入管道将是训练器组件的一部分,可能还包括像Transform这样可能需要对数据进行大量处理的其他组件。


设计高效输入管道的框架 🛠️

有多种方法可以设计高效的输入管道。一个可以提供帮助的框架是TensorFlow Data或TF.data。让我们以TF.data为例,看看如何设计高效的输入管道。

你可以将输入管道视为一个ETL(提取、转换、加载)过程,它提供了一个框架来促进应用性能优化。

以下是ETL过程的三个主要步骤:

  1. 提取:从数据存储中提取数据,这些存储可能是本地的或远程的,例如硬盘、SSD、云存储和HDFS。
  2. 转换:数据通常需要进行预处理。这包括打乱、批处理和重复数据。
  3. 加载:将预处理后的数据加载到模型中,模型可能在GPU或TPU上进行训练,然后开始训练。

你安排这些转换的顺序可能会影响管道的性能。在使用任何数据转换(如mapbatchshufflerepeat等)时,你需要注意这一点。

高性能输入管道的一个关键要求是跨各种系统并行处理数据,以尝试最大限度地有效利用可用的计算、IO和网络资源。特别是对于更昂贵的组件(如加速器),你希望尽可能让它们保持忙碌。


需要避免的低效模式与高效模式 🔄

让我们看一个容易陷入的典型模式,一个你真正想要避免的模式。

在这种场景下,包括CPU和加速器在内的关键硬件组件处于空闲状态,等待前一步骤完成。如果你仔细想想,ETL(提取、转换、加载)是思考数据性能的一个很好的心智模型。

现在,为了让你对流水线如何执行有一些直观理解,ETL的每个不同阶段都使用系统中的不同硬件组件:

  • 提取阶段:使用你的磁盘和网络(如果你从远程系统加载)。
  • 转换阶段:通常发生在CPU上,并且可能非常消耗CPU资源。
  • 加载阶段:使用DMA(直接内存访问)子系统以及到加速器(可能是GPU或TPU)的连接。

上图展示了一种比前一种模式高效得多的模式,尽管它仍然不是最优的。在实践中,这种模式在许多情况下可能难以进一步优化。

如图所示,通过并行化操作,你可以使用一种称为软件流水线的技术来重叠ETL的不同部分。通过软件流水线,你可以同时为步骤5提取数据,为步骤4转换数据,为步骤3加载数据,最后为步骤2进行训练。这导致了对计算资源非常高效的利用。因此,你的训练速度更快,资源利用率更高。请注意,现在只有少数情况下你的硬盘和CPU实际上处于空闲状态。

通过流水线化训练过程,你可以通过重叠CPU预处理和加速器的模型执行来克服CPU瓶颈。当加速器忙于在后台训练模型时,CPU开始为下一个训练步骤准备数据。你可以看到,在使用流水线时,模型训练时间有显著改善。虽然你仍然可以预期有一些空闲时间,但通过使用流水线,空闲时间大大减少了。


优化数据管道的实践方法 ⚡

那么在实践中如何优化你的数据管道呢?以下是几种可以用于加速管道的基本方法。

以下是几种关键的优化技术:

  • 预取:在当前步骤完成之前,开始为下一步加载数据。
  • 并行化:并行化数据提取和转换。
  • 缓存:缓存数据集,以便在新周期开始时立即开始训练(当你有足够缓存时)。
  • 优化顺序:最后,你需要注意如何在管道中安排这些优化的顺序,以最大化管道的效率。

1. 预取

通过预取,你可以重叠生产者(输入管道)和消费者(模型)的工作。当模型正在执行步骤S时,输入管道正在为步骤S+1读取数据。这减少了步骤训练模型或从磁盘提取数据所需的总时间(取两者中耗时较长的那个)。

TF.data API提供了tf.data.Dataset.prefetch转换。你可以使用它来解耦数据生产的时间和数据消费的时间。此转换使用后台线程和内部缓冲区,在数据被请求之前提前从输入数据集中预取元素。理想情况下,预取的元素数量应等于或可能大于单个训练步骤消耗的批次数量。

你可以手动调整此值,或将其设置为tf.data.experimental.AUTOTUNE,如下例所示,这将配置TF.data运行时在运行时动态优化该值。

dataset = dataset.prefetch(buffer_size=tf.data.experimental.AUTOTUNE)

2. 并行数据提取

在现实环境中,输入数据可能存储在远程,例如在GCS或S3上。在本地读取数据时运行良好的数据集管道,在远程读取数据时可能会在IO上遇到瓶颈,这是因为本地存储和远程存储之间存在以下差异:

  • 首字节时间:从远程存储读取文件的第一个字节可能比从本地存储读取要长几个数量级。
  • 读取吞吐量:虽然远程存储通常提供较大的总带宽,但读取单个文件可能只能利用这一带宽的一小部分。

为了减少数据提取开销,使用tf.data.Dataset.interleave转换来并行化数据加载步骤,包括交错其他数据集的内容。要重叠的数据集数量由cycle_length参数指定,而并行级别由num_parallel_calls参数设置。

prefetch转换类似,interleave转换也支持tf.data.experimental.AUTOTUNE,这将把使用何种并行级别的决定权委托给TF.data运行时。

dataset = files.interleave(
    tf.data.TFRecordDataset,
    cycle_length=tf.data.experimental.AUTOTUNE,
    num_parallel_calls=tf.data.experimental.AUTOTUNE
)

3. 并行数据转换

在准备数据时,输入元素可能需要进行预处理。例如,TF.data API提供了tf.data.Dataset.map转换,它将用户定义的函数应用于输入数据集的每个元素。逐元素的预处理可以在多个CPU核心上并行化。

prefetchinterleave转换类似,map转换提供了num_parallel_calls参数来指定并行级别。为num_parallel_calls参数选择最佳值取决于你的硬件、训练数据的特征(如大小和形状)、你的映射函数的成本以及CPU上同时进行的其他处理。

一个简单的启发式方法是使用可用CPU核心的数量。然而,与prefetchinterleave转换一样,TF.data中的map转换也支持tf.data.experimental.AUTOTUNE参数,这将把使用何种并行级别的决定权委托给TF.data运行时。

dataset = dataset.map(
    preprocess_function,
    num_parallel_calls=tf.data.experimental.AUTOTUNE
)

让我们看看当你在多个样本上并行应用预处理时会发生什么。在这里,预处理步骤重叠,减少了单次迭代的总时间。这可能是一个巨大的优势。你实现了相同的预处理函数,但将其并行应用于多个样本。

4. 缓存

TF.data数据集具有将数据集缓存到内存或本地存储的能力。在许多情况下,缓存是有利的,并能提高性能。

这将避免在每个周期执行一些操作(如文件打开和数据读取)。当你缓存一个数据集时,缓存之前的转换(如文件打开和数据读取)仅在第一个周期执行,后续周期将重用缓存的数据。

让我们考虑两种缓存场景:

  1. map后缓存:如果传入map转换的用户定义函数计算成本很高,只要结果数据集能够装入内存或本地存储,那么在map转换之后应用cache转换是有意义的。
  2. map前缓存或离线预处理:相反,如果用户定义函数增加了存储数据集所需的空间,超出了缓存容量,要么在cache转换之后应用它,要么考虑在训练作业之前预处理数据以减少资源需求。
# 场景1:昂贵转换后缓存
dataset = dataset.map(expensive_function).cache()
# 场景2:缓存后应用转换或离线处理
dataset = dataset.cache().map(less_expensive_function)

总结 📝

在本节课中,我们一起学习了构建高性能机器学习数据输入管道的核心概念与实践方法。

我们首先理解了为什么需要高性能输入管道来避免昂贵的加速器(GPU/TPU)空闲。接着,我们引入了ETL(提取、转换、加载) 作为设计管道的核心框架。然后,我们对比了低效的顺序执行模式与高效的软件流水线模式,后者通过重叠不同阶段的工作来大幅提升资源利用率和训练速度。

最后,我们深入探讨了四种关键的优化技术:

  1. 预取:使用dataset.prefetch重叠数据生产与消费。
  2. 并行提取:使用dataset.interleave并行读取多个文件,应对远程存储延迟。
  3. 并行转换:使用dataset.mapnum_parallel_calls参数在多个CPU核心上并行预处理数据。
  4. 缓存:使用dataset.cache将预处理结果存入内存或本地磁盘,避免重复计算。

重要的是,TF.data API为prefetchinterleavemap的并行参数提供了tf.data.experimental.AUTOTUNE选项,允许运行时自动寻找最优配置。通过合理组合运用这些技术,你可以构建出能够充分“喂饱”加速器、最大化硬件利用率的高性能数据管道,从而缩短模型训练时间。

103:训练大型模型 - 巨型神经网络与并行化的兴起 🚀

在本节课中,我们将探讨高性能建模,特别是处理日益增大的模型时所面临的问题,并介绍一些用于训练大型模型的先进技术。


近年来,机器学习数据集和模型的规模持续增长,这为包括语音识别、视觉识别和语言处理在内的广泛任务带来了更好的结果。BigGAN、BERT和GPT-3等最新进展表明,更大的模型通常能带来更好的任务性能。

与此同时,GPU和TPU等硬件加速器的性能也在提升,但速度明显更慢。模型增长与硬件改进之间的差距,使得并行化的重要性日益凸显。

这里的并行化,指的是在多个硬件设备上训练单个机器学习模型。


并行化的挑战与机遇

一些模型架构,特别是小型模型,非常适合并行化,可以很容易地在硬件设备之间进行划分。

然而,对于巨型模型,同步成本会导致性能下降,从而阻碍其使用。模型大小与分类精度之间存在很强的相关性。

例如,2014年ImageNet视觉识别挑战赛的冠军是GoogleNet,它使用400万个参数实现了74.8%的Top-1准确率。仅仅三年后,2017年ImageNet的冠军是Squeeze-and-Excitation网络,它使用1.458亿个参数实现了82.7%的Top-1准确率。这意味着参数数量在三年内增加了36倍。

海量的权重和激活参数需要巨大的内存存储空间。因此,一个自然而然的问题是:随着模型需要越来越多的参数,这些参数存储在哪里?

过去几年,内存容量的增长与模型参数的增长相比非常有限。具体来说,TPU内存仅增加了大约三倍,而当前最先进的图像模型已经达到了云TPU V2上可用的内存上限。

因此,迫切需要一种高效、可扩展的基础设施,以实现大规模深度学习并克服当前加速器的内存限制。


克服内存限制的传统方法

在某种程度上,这不是一个新问题。让我们看看一些旧方法如何应对克服内存限制的问题,并思考今天是否还能应用它们。然后,我们再看看一些新方法及其取得的进展。

需要制定策略并实施解决方案来克服这些重要的内存限制。

梯度累积是一种可以克服GPU内存不足问题的策略。梯度累积是一种将完整批次拆分为几个小批次的机制。在反向传播过程中,模型不会随每个小批次更新,而是累积梯度。当一个完整批次完成后,所有先前小批次的累积梯度被用于反向传播来更新模型。

这个过程与使用完整批次训练网络一样有效,因为模型参数更新的次数相同。

交换是第二种方法。由于加速器上没有足够的存储空间,需要将激活值复制回CPU或内存,然后再复制回加速器。这里的问题是速度慢,CPU/内存与加速器之间的通信成为瓶颈。


并行化的基本方法

回到我们对并行化的讨论,其基本思想是将计算拆分到多个工作节点上。你已经看到了两种并行化方式:数据并行和模型并行。

  • 数据并行:在不同工作节点间拆分输入数据。
  • 模型并行:在不同工作节点间拆分模型本身。

在数据并行中,不同的工作节点(或GPU)处理相同的模型,但处理不同的数据。模型在多个工作节点上复制,每个工作节点执行前向和后向传播。当它完成这个过程后,会与其他设备同步更新后的模型权重,并计算整个小批次的更新权重。

在模型并行中,工作节点只需要同步共享参数,通常每个前向或反向传播步骤同步一次。此外,由于每个工作节点使用相同的训练数据处理模型的一个子部分,因此模型大小不是主要问题。

在使用模型并行进行训练时,模型被划分到K个工作节点上,每个工作节点持有模型的一部分。模型并行的一种简单方法是将一个N层神经网络划分到K个工作节点上,只需在每个工作节点上托管N/K层。更复杂的方法会通过分析每层的计算复杂度,确保每个工作节点都同样繁忙。

标准的模型并行能够训练更大的神经网络,但由于工作节点经常相互等待,并且在给定时间只有一个能执行更新,因此性能会受到很大影响。


数据并行的瓶颈

让我们回到数据并行,看一些基准测试。下图显示了三种不同硬件配置下,通信开销占总训练时间的百分比。

像AlexNet和VGG16这样的许多模型,即使在相对较慢的K80加速器上,也有很高的通信开销。有两个因素导致所有模型的通信开销增加:数据并行工作节点数量的增加,以及GPU计算能力的增加。

在数据并行中,输入数据集在多个GPU之间分区。每个GPU维护模型的完整副本,并在自己的数据分区上进行训练,同时定期与其他GPU同步权重,使用集体通信原语或参数服务器。

参数同步的频率影响统计效率和硬件效率。在每个小批次结束时同步,可以减少用于计算梯度的权重陈旧性,确保良好的统计效率。不幸的是,这要求每个GPU等待来自其他GPU的梯度,这会显著降低硬件效率。

由于神经网络的结构,通信延迟在数据并行训练中是不可避免的,其结果往往是通信主导总执行时间。加速器速度的快速提升进一步将训练瓶颈转向通信。


管道并行:一种新的解决方案

此外还有另一个问题。加速器内存有限,主机上的通信带宽也有限。这意味着需要通过将模型划分为多个分区并将不同分区分配给不同加速器,来在加速器上训练更大的模型。

但由于神经网络的顺序性质,简单的策略可能导致在计算过程中只有一个加速器处于活动状态,从而未充分利用加速器的计算能力。另一方面,标准的数据并行方法允许在多个加速器上使用不同的输入数据并发训练相同的模型,但无法增加单个加速器所能支持的最大模型大小。

数据并行和模型并行的问题导致了管道并行的发展。

在下图中,由于模型的顺序性质,简单的模型并行策略导致严重的利用不足,一次只有一个加速器处于活动状态。

为了在多个加速器上实现高效训练,需要找到一种方法,将模型划分到不同的加速器上,并自动将一个小批次的训练样本拆分成更小的微批次。通过跨微批次进行流水线执行,加速器可以并行操作。此外,梯度在微批次之间持续累积,因此分区数量不会影响模型质量。


管道并行的实现:Gpipe 与 PipeDream

Google的Gpipe是一个使用管道并行高效训练大规模模型的开源库。在下图中,Gpipe将输入小批次划分为更小的微批次,使不同的加速器能够同时处理不同的微批次。

Gpipe本质上提出了一种处理模型并行的新方法,它允许在多个硬件设备上训练大型模型,性能提升几乎是一比一的。它还有助于模型包含更多的参数,从而在训练中获得更好的结果。

微软的PipeDream也支持管道并行。Gpipe和PipeDream在许多方面都很相似。

像Gpipe和PipeDream这样的管道并行框架,集成了数据并行和模型并行,以实现高效率并保持模型精度。它们通过将小批次划分为更小的微批次,并允许不同的工作节点并行处理不同的微批次来实现这一点。因此,它们可以训练参数数量显著更多的模型。


Gpipe 的工作原理与效果

Gpipe是一个开源的分布式机器学习库,它使用同步小批次梯度下降进行训练。它将模型划分到不同的加速器上,并自动将一个小批次的训练样本拆分为微批次。通过跨微批次进行流水线执行,加速器可以并行训练。

Gpipe接收神经网络架构、小批次大小以及可用于计算的硬件设备数量作为输入。然后,它自动将网络层划分为阶段,将小批次划分为微批次,并将它们分布在各个设备上,从而将模型划分为K个阶段。

Gpipe根据每层的激活函数和训练数据内容来估计其计算成本。Gpipe试图最大化模型参数的内存分配。

谷歌的研究团队在云TPU V2上进行了实验,每个TPU有8个加速器核心和64GB内存(每个加速器8GB)。如果没有Gpipe,由于内存限制,单个加速器最多只能训练8200万个模型参数。

得益于反向传播中的重新计算和批次拆分,Gpipe将中间激活内存从6.2GB减少到3.4GB,使单个加速器能够训练多达3.18亿个参数。他们还观察到,通过管道并行,最大模型大小与分区数量成正比,正如预期的那样。

使用Gpipe,在云TPU的八个加速器上测试AmoebaNet模型时,能够整合18亿个参数,比不使用Gpipe时多25倍。为了测试效率,他们测量了Gpipe对AmoebaNet-D模型吞吐量的影响。

由于训练至少需要两个加速器来容纳模型大小,他们测量了相对于没有管道并行、只有两个分区的简单情况的加速比。他们观察到,与简单方法相比,训练速度几乎呈线性提升:将模型分布在四倍的加速器上,实现了3.5倍的加速。


总结

本节课中,我们一起学习了训练大型模型所面临的挑战,特别是内存和计算瓶颈。我们回顾了梯度累积和交换等传统方法,深入探讨了数据并行和模型并行的基本原理及其局限性。最后,我们重点介绍了管道并行这一先进技术,它通过将小批次拆分为微批次并进行流水线执行,巧妙地结合了数据并行和模型并行的优点,从而能够高效地训练参数数量极其庞大的模型。Google的Gpipe和微软的PipeDream是这一领域的代表性框架,它们使得在现有硬件上训练巨型神经网络成为可能。

104:知识蒸馏(教师-学生网络)🧠➡️🎓

在本节课中,我们将学习一种名为“知识蒸馏”的技术。它旨在将大型、复杂模型(教师模型)学到的“知识”提炼并转移到一个小型、高效的模型(学生模型)中,从而解决复杂模型在移动设备等生产环境中部署困难的问题。

到目前为止,我们已经讨论了优化模型实现以提升效率的方法。

但是,你也可以尝试通过一种不同的训练方式,来捕捉或提炼模型已学到的知识,并将其封装到一个更紧凑的模型中。

这就是所谓的知识蒸馏。让我们来详细了解一下。

为何需要知识蒸馏?🤔

现在,你已经了解了几种不同的模型优化方法。

但如果你想部署一个相对复杂且体积庞大的模型,仅仅减少参数数量或降低模型复杂度,是否足以帮助你部署这些更强大、更大的模型呢?

让我们尝试回答这些问题。首先,我们来看看大型模型是如何变得复杂的,并探究是否可能用更小的模型达到同等的复杂程度。

模型为了学习复杂的任务,会试图捕捉更多的信息或知识,从而变得更大、更复杂。

然而,如果我们能更高效地表达或呈现这种学习成果,或许就能创造出与这些大型复杂模型等效的更小模型。

举个例子,我们来看一个在部署上存在挑战的复杂图像分类模型。

例如,让我们看看GoogleNet。它是一个如此深且复杂的网络,甚至无法完整地呈现在这张幻灯片上。

其深度赋予了它表达特征间复杂关系的能力,但也正因为它如此庞大,在许多生产环境(包括手机和边缘设备)中难以甚至无法部署。

那么,能否两全其美,将像GoogleNet这样的复杂模型中所包含的知识,捕捉到一个更小、更高效的模型中呢?这就是知识蒸馏的目标。

与我们之前看到的量化和剪枝不同,知识蒸馏并非优化网络实现,而是旨在创建一个更高效的模型,使其能捕捉到与更复杂模型相同的知识。如果需要,还可以对结果模型进一步应用优化。

知识蒸馏如何工作?⚙️

知识蒸馏是一种训练小型模型以模仿大型模型甚至模型集成的方法。

以下是其核心步骤:

首先,训练一个复杂的模型或模型集成,以达到较高的准确度水平。

然后,将该模型作为“教师”,用于指导一个更简单的“学生”模型进行训练。

最终,这个学生模型将成为实际部署到生产环境中的模型。

这个教师网络可以是固定的,也可以与学生的训练过程联合优化,甚至可以同时用于训练多个不同大小的学生模型。

总结 📝

本节课中,我们一起学习了知识蒸馏技术。我们了解到,通过让一个大型、高性能的教师模型指导一个小型学生模型,可以将复杂模型的知识“蒸馏”出来,从而得到一个既高效又保持高性能的、易于部署的模型。这为解决大型模型在生产环境中的部署难题提供了一种有效的思路。

105:知识蒸馏技术 🧠

在本节课中,我们将深入探讨知识蒸馏技术的工作原理。知识蒸馏是一种模型压缩技术,旨在将大型、复杂模型(教师模型)的知识转移到小型、高效模型(学生模型)中。我们将学习其核心概念、训练目标以及实际应用。


教师模型与学生模型 👨‍🏫👨‍🎓

上一节我们介绍了知识蒸馏的基本概念,本节中我们来看看其中的两个核心角色:教师模型与学生模型。

在知识蒸馏中,教师模型和学生模型扮演着不同的角色。

  • 教师模型:通常是一个大型、高性能的预训练模型。它的任务是提供“知识”。
  • 学生模型:通常是一个更小、更高效的模型。它的任务是学习并模仿教师模型的行为。

训练目标与知识转移 🎯

了解了教师与学生的角色后,我们来看看它们是如何通过不同的训练目标进行知识转移的。

在知识蒸馏中,学生模型和教师模型的训练目标函数是不同的。

教师模型首先使用标准的目标函数进行训练,该函数旨在最大化模型的准确率或类似指标。这就是正常的模型训练过程。

随后,学生模型寻求可转移的知识。因此,它使用一个旨在匹配教师模型预测概率分布的目标函数。

需要注意的是,学生模型学习的不仅仅是教师模型的预测结果,更是其预测的概率。教师模型预测的概率构成了“软目标”,与最终的预测结果本身相比,这些软目标提供了更多关于教师模型所学知识的信息。


软目标与温度参数 🌡️

知识蒸馏并非神秘技术,但它确实涉及“暗知识”。现在我们来讨论这一点。

知识蒸馏的工作原理是通过最小化一个损失函数,将知识从教师模型转移到学生模型,该损失函数的目标是教师模型预测的类别概率分布。

具体而言,教师模型的逻辑值作为最终 Softmax 层的输入。通常使用逻辑值是因为它们为每个样本的所有目标类别概率提供了更多信息。

然而,在许多情况下,这个概率分布中正确类别的概率非常高,而其他所有类别的概率都接近于零。因此,实际上,它有时除了数据集中已提供的真实标签外,并未提供太多额外信息。

为了解决这个问题,Hinton、Vinyals 和 Dean 引入了 Softmax 温度 的概念。

通过提高学生和教师目标函数中的温度,可以改善教师模型分布的“柔软度”。在以下公式中,类别 i 的概率 P 由逻辑值 Z 计算得出:

P_i = exp(z_i / T) / Σ_j exp(z_j / T)

其中,T 指的是温度参数。当 T = 1 时,得到标准的 Softmax 函数。但随着 T 增大,Softmax 函数生成的概率分布会变得更“软”,从而提供更多信息,表明教师模型认为哪些类别与预测类别更相似。

作者将此称为教师模型中蕴含的“暗知识”,而正是这种暗知识在蒸馏过程中被转移到了学生模型中。


学生模型的训练技巧 ⚙️

有多种技术用于训练学生模型以匹配教师的软目标。以下是两种主要方法:

  • 方法一:学生模型同时基于教师的逻辑值和真实标签进行训练,使用一个标准的目标函数,这两个目标函数在反向传播中进行加权和组合。
  • 方法二:使用诸如 KL 散度等度量来比较学生模型预测分布与教师模型预测分布。

现在让我们看看第二种技术,因为它应用更广泛。

通常,知识蒸馏通过混合两个损失函数来完成,选择一个介于 0 和 1 之间的 alpha 值。损失函数公式如下:

L = α * L_CE + (1 - α) * L_KL

其中,L_CE 是来自硬标签的交叉熵损失,L_KL 是来自教师逻辑值的 Kullback-Leibler 散度损失。

在数据增强非常剧烈的情况下,由于对数据应用了激进的扰动,可能无法完全信任原始的硬标签。

这里的 Kullback-Leibler 散度是两个概率分布之间差异的度量。我们希望这两个概率分布尽可能接近,因此目标就是使学生模型预测的类别分布尽可能接近教师模型。

在计算相对于教师软目标的损失函数时,使用相同的 T 值来计算学生模型逻辑值的 Softmax。这个损失就是蒸馏损失

作者还发现了另一个有趣的现象:蒸馏后的模型除了能产生教师的软目标外,还能产生正确的标签。这意味着可以计算学生模型预测的类别概率与真实标签(称为硬标签或硬目标)之间的标准损失。这个损失就是学生损失。在计算学生模型的概率时,将 Softmax 温度设置为 1。


知识蒸馏的量化结果与优势 📊

知识蒸馏的首个量化结果令人鼓舞。

Hinton 及其同事为一个自动语音识别任务训练了 10 个独立的模型,其架构和训练过程与当时的基线相同。当时的自动语音识别任务依赖于深度神经网络,将波形特征的一个短时上下文映射到隐马尔可夫模型离散状态的概率分布上。

对于这些模型,他们使用不同的初始参数值随机初始化权重。这样做本质上是为了确保训练后的模型具有足够的多样性。

在集成模型预测时,它们能轻松超越单个模型。他们也考虑了让每个模型看到不同的数据集,但发现这不会显著影响结果。因此,他们决定使用这种更直接的策略,将模型集成与单个模型进行比较。

对于蒸馏过程,他们尝试了不同的 Softmax 温度值,如 1、2.5 和 10。他们在硬目标的交叉熵上使用了 0.5 的相对权重。

结果表明,蒸馏确实可以从训练集中提取比仅使用硬标签训练单个模型更有用的信息。由 10 个模型组成的集成所实现的准确率提升中,超过 80% 被转移到了蒸馏后的模型上。

由于目标函数不匹配,集成模型在最终目标(23K 词测试集上的词错误率)上带来的增益较小。但同样,集成模型实现的词错误率降低也被转移到了蒸馏后的模型中。

由此,他们能够证明模型蒸馏策略确实是有益的,并且可以用来实现将模型集成蒸馏成单个模型的效果,该模型比直接从相同训练数据学习的相同大小的模型表现要好得多。


现实世界应用:DistilBERT 🌐

在现实世界中,人们更感兴趣的是部署一个接近最先进结果但体积小得多、速度快得多的低资源模型。这就是 Hugging Face 创建 DistilBERT 的原因。

DistilBERT 是 BERT 的蒸馏版本,它使用的参数减少了 40%,运行速度提高了 60%,同时在 GLUE 语言理解基准测试中保留了 BERT 97% 的性能。

本质上,它是 BERT 的一个较小版本。为了创建 DistilBERT,移除了通常用于下一句分类任务的标记类型嵌入和池化层。Hugging Face 的研究人员将知识蒸馏应用于 BERT,因此得名 DistilBERT。他们在减少层数的同时,保持了架构的其余部分相同。


总结 📝

本节课中,我们一起学习了知识蒸馏技术。我们了解了教师模型与学生模型的概念,探讨了通过软目标和温度参数进行知识转移的原理,分析了学生模型的训练技巧,并看到了知识蒸馏在提升模型效率方面的量化优势及其在现实世界(如 DistilBERT)中的成功应用。知识蒸馏是一种强大的模型压缩方法,能够在保持高性能的同时,显著减小模型体积并提升推理速度。

106:问答任务的知识蒸馏案例研究 📚

在本节课中,我们将学习知识蒸馏在具体任务——问答(Q&A)中的应用。我们将通过一个来自微软研究团队的具体实现案例,了解如何通过多教师知识蒸馏方法来压缩大型模型,同时保持其高性能。


概述

知识蒸馏是一种将大型、复杂模型(教师模型)的知识转移到小型、高效模型(学生模型)的技术。在问答任务中,直接部署像BERT或GPT这样的大型模型会面临参数量巨大、推理速度慢的挑战。传统的模型压缩方法往往会导致信息损失,使压缩后模型的性能不如原模型。为了解决这个问题,研究人员提出了创新的多阶段蒸馏方法。

上一节我们介绍了知识蒸馏的基本概念,本节中我们来看看它在实际问答系统中的具体实现。


多教师知识蒸馏(TMKD)方法

微软的研究人员提出了一种两阶段的多教师知识蒸馏方法,简称TMKD。该方法旨在解决信息损失问题,使学生模型的性能尽可能接近甚至达到教师模型的水平。

第一阶段:通用问答蒸馏预训练

首先,该方法为学生模型设计了一个通用的问答蒸馏预训练任务。这使学生模型能够在特定任务微调之前,就从大规模的无监督问答对数据中学习到良好的特征表示。

第二阶段:多教师知识蒸馏微调

随后,使用一个多教师知识蒸馏模型对这个预训练好的学生模型进行微调。这与我们之前介绍的一对一(一个教师对一个学生)的基础蒸馏方法不同。


从“一对一”到“多对多”

基础的知识蒸馏方法可被视为“一对一”模型。虽然它能有效减少参数和推理时间,但由于蒸馏过程中的信息损失,学生模型的性能有时无法与教师模型媲美。

这促使研究者创建了名为“多对多”的集成模型方法,它结合了模型集成知识蒸馏

以下是该方法的实现步骤:

  1. 训练多个教师模型:首先,训练多个强大的教师模型(例如,不同超参数的BERT或GPT模型)。
  2. 为每个教师训练学生模型:然后,为每一个教师模型分别训练一个对应的学生模型。
  3. 集成学生模型:最后,将这些从不同教师那里学到的学生模型集成起来,产生最终结果。

这种方法让每个教师专注于特定的学习目标,不同的模型对训练数据有不同的泛化能力和过拟合方式,从而使学生模型能够融合更广泛的知识,达到接近教师模型的性能。


TMKD的优势与实验验证

TMKD方法在多个公开基准和大规模数据集上的实验表明,它能够显著超越基线方法,甚至取得与原始教师模型相当的结果,同时大幅提升了模型推理速度。

为了支持这些结论,我们来逐一分析它的优势。

优势一:蒸馏预训练提升性能

TMKD的一个独特之处在于,它使用多教师蒸馏任务进行学生模型预训练,以提升模型性能。

为了分析预训练的影响,作者评估了两个模型:

  • TKD模型:一个基于三层BERT的模型,先在通用问答数据集上进行知识蒸馏预训练,然后在特定任务语料上使用单一教师进行微调。
  • 传统KD模型:同样的模型结构,但没有蒸馏预训练阶段。

实验表明,TKD通过利用大规模无监督问答对进行蒸馏预训练,获得了显著的性能增益。

优势二:多教师联合学习的统一框架

TMKD的另一个好处是其能从多个教师那里联合学习的统一框架。

作者比较了多教师与单教师蒸馏的影响:

  • MKD模型:基于三层BERT,通过多教师蒸馏(无预训练阶段)训练。
  • KD模型:基于三层BERT,通过单教师蒸馏(无预训练阶段)训练,其目标是学习教师模型的平均分数。

MKD在大多数任务上优于KD,这表明多教师蒸馏方法能帮助学生模型学习更泛化的知识,融合来自不同教师的见解。

优势三:两阶段的互补效应

最后,作者比较了TKD、MKD和完整的TMKD。

结果显示,TMKD在所有数据集上都显著优于TKD和MKD。这验证了蒸馏预训练多教师微调这两个阶段的互补影响。


扩展案例:Noisy Student训练法

在另一个例子中,来自Google Brain和卡内基梅隆大学的研究人员使用一种称为“Noisy Student”的半监督学习方法训练模型。

这种方法的知识蒸馏过程是迭代的,它使用了经典师生范式的变体,但有一个关键不同:学生模型的参数量被有意设计得比教师模型更大

这样做是为了让模型对噪声标签具有鲁棒性,这与传统的知识蒸馏模式相反。

以下是“Noisy Student”的工作流程:

  1. 首先,使用有标签图像训练一个EfficientNet作为教师模型。
  2. 然后,使用教师模型在一个更大的无标签图像集上生成伪标签。
  3. 接着,结合有标签图像和伪标签图像,训练一个更大的EfficientNet作为学生模型。
  4. 通过将学生模型视为新的教师模型来重新标注无标签数据,并训练新的学生模型,将此算法迭代多次。

该方法的一个重要元素是,在训练学生模型时,通过Dropout、随机深度、数据增强(如RandAugment) 等方式为其添加噪声。

这种“制造困难”的做法迫使学生模型必须更努力地从伪标签中学习。给学生模型添加噪声确保了任务对学生来说更难,因此得名“Noisy Student”,这防止了学生模型仅仅机械地复制教师的知识。

需要注意的是,教师模型在生成伪标签时不添加噪声,以确保其准确性不受影响。

循环结束时,用优化后的学生网络替换原来的教师模型。

通过对比“Noisy Student”训练的结果,作者发现这种方法不仅能用于压缩模型(如DistilBERT),还能用于增强一个已经很优秀的模型的鲁棒性。结果显示,使用该方法训练的模型在ImageNet等基准测试中达到了新的顶尖水平。


总结

本节课中我们一起学习了知识蒸馏在问答任务中的具体应用。我们深入探讨了微软提出的两阶段多教师知识蒸馏(TMKD)方法,了解了它如何通过蒸馏预训练多教师联合微调来提升小模型的性能。此外,我们还扩展了解了“Noisy Student”训练法,看到了知识蒸馏如何以迭代和添加噪声的方式,用于提升大模型本身的鲁棒性和性能。

这些案例表明,知识蒸馏是一个灵活而强大的工具,既能用于模型压缩和加速,也能用于提升模型的学习能力和泛化性能。

107:第29课 模型性能分析 📊

在本节课中,我们将深入学习模型性能分析。我们将首先回顾模型分析的基础知识,然后深入探讨一个关键工具——TensorFlow模型分析(TFMA)。我们还将了解模型调试、理解模型鲁棒性,并初步接触模型修复、公平性以及持续评估等概念。这是一个内容丰富的主题,让我们开始吧。

成功训练一个模型并使其收敛的感觉很好。这常常让人觉得任务已经完成。如果你是在为课程项目或论文训练模型,那么确实可以告一段落。但对于生产环境的机器学习,你现在需要进入开发的新阶段,这涉及到从多个方向对模型性能进行更深入的分析。这就是我们本周要学习的内容。

让我们从回顾模型分析的一些基础知识开始,看看分析模型和确定性能的不同方法。本周大部分内容,你将使用TensorFlow模型分析(TFMA)及其相关工具和技术。但首先,我们来回顾一下模型分析的一些要点。

这里需要强调的是,你不仅要在整个数据集上查看模型性能,还要在数据的各个独立切片上进行查看。在训练和/或部署后,你可能会注意到性能下降。因此,很自然地会去探究改进模型性能的可能方法。

此外,你需要预测未来可能看到的数据变化,并对自你最初训练模型以来已经发生的数据变化采取行动。选择需要分析的数据切片通常基于领域知识。这将使你能够确定模型是否有改进空间,并可能解决自最初训练模型以来发生的数据变化。

例如,如果你的模型旨在预测不同类型鞋子的需求,那么查看模型在单个鞋类(可能是不同颜色或款式)上的性能将非常重要。这需要为不同类型的鞋子对数据进行切片。

从高层次来看,分析模型性能主要有两种方法:黑盒评估和模型内省。

黑盒评估与模型内省 🔍

在黑盒评估中,你通常不考虑模型的内部结构。你只关心通过指标和损失来量化模型的性能。这在常规开发过程中通常是足够的。

但如果你对模型内部如何工作感兴趣,也许是为了寻找改进方法,你可以应用各种模型内省方法。当你尝试新的架构以理解数据在模型每一层内部如何流动时,模型内省方法非常有用。这可以帮助你调整和迭代模型架构,以提高性能和效率。

TensorBoard是用于黑盒评估的工具的一个例子。使用TensorBoard,我们可以监控模型每次迭代的损失和准确率。你还可以密切监控训练过程本身。请查看阅读列表以了解更多关于TensorBoard的信息。

在模型内省中,目标完全不同。你不仅对模型的最终结果感兴趣,还对每一层的细节感兴趣。在左侧,我们看到了模型卷积层中各种滤波器的最大激活区域。这是一个CNN模型。当我们运行一系列属于特定类别的图像时,利用这些模式,你可以检查模型在哪一层学习到了数据的特定结构。右侧是类别激活图的一个例子。在这里,你感兴趣的是知道图像的哪些部分主要负责对该类别做出期望的预测。利用这些信息,你可以尝试通过调整或包含更多与这些高亮区域相关的特征来提高模型的性能。

接下来,我们来看看性能指标和优化之间的区别。

性能指标与优化目标 ⚖️

首先是性能指标。根据你试图解决的问题,你需要使用某种度量来量化模型的成功。为此,你使用各种性能指标。对于不同类型的任务(如分类和回归等),性能指标会有所不同。你在设计和训练模型时已经熟悉了这些。

现在让我们关注优化部分。这是你的目标函数、成本函数或损失函数。人们对它的称呼不同。当你训练模型时,你试图最小化这个函数的值,以在损失曲面上找到一个最优值,希望是全局最优值。如果你再次查看TensorBoard,你会注意到有选项可以跟踪性能指标(如准确率)和优化目标(如每次训练和验证周期后的损失)。

让我们快速检查一下优化环境。这也被称为损失曲面。在这里,损失被表示为两个参数的函数。图中描绘的是一个鞍点,其中沿不同维度的曲率符号不同。一个维度向上弯曲,另一个向下弯曲。这是许多优化问题的典型情况。

动画显示了不同优化算法的轨迹。这些优化器中的每一个都根据其更新方法以不同的方式遍历曲面,并且可能需要不同的时间收敛到最优值。

当你评估训练性能时,你通常关注的是顶层指标。这是为了决定你的模型是否表现良好,但它并不能告诉你模型在数据的各个部分上表现如何。例如,不同商店的不同客户对你的模型体验可能大不相同。如果他们的体验不好,就会给你的模型带来负面影响。

108:TensorFlow Model Analysis (TFMA) 简介 🔍

在本节课中,我们将学习 TensorFlow Model Analysis (TFMA) 这一工具。TFMA 是一个用于对模型性能进行深度分析的多功能框架。我们将了解其重要性、核心架构、工作流程以及它与 TensorBoard 的区别。

概述

整体性能指标很容易掩盖模型在特定数据部分存在的问题。例如,模型可能对特定客户、产品、店铺、星期几或对您的领域有意义的其他数据子集表现不佳。

考虑到向模型请求预测的客户,如果模型产生了一个糟糕的预测,那么该客户对模型的体验就是糟糕的,无论其整体指标表现多好。

为了让开发者能够更深入地审视模型性能,Google 创建了 TensorFlow Model Analysis (TFMA)。TFMA 是一个开源的、可扩展的框架,用于对模型性能进行深度分析,包括分析数据切片上的性能。

TFMA 也是机器学习流水线(如 TFX 流水线)的关键部分,用于在部署新训练模型版本之前执行深度分析。TFMA 内置了检查模型是否满足特定质量标准的能力,并能可视化评估指标、检查不同数据切片上的性能。TFMA 可以单独使用,也可以作为 TFX 等其他框架的一部分使用。

TFMA 高层架构

上一节我们介绍了 TFMA 的基本概念,本节中我们来看看它的高层架构。

TFMA 流水线由四个主要组件构成:读取输入、提取器、评估器和写入结果。

以下是各组件的主要功能:

  • 读取输入:此阶段由一个转换器组成,它接收原始输入(如 CSV 或 TFRecords 等),并将其转换为下一个阶段(提取)可以理解的字典格式。
  • 提取:此阶段使用 Apache Beam 进行分布式处理。输入提取器和切片键提取器从原始数据集中形成切片,预测提取器将在每个切片上运行预测。结果再次以 TFMA.extracts 字典格式发送到下一阶段。
  • 评估:此阶段同样使用 Apache Beam 进行分布式处理。有多个评估器,您也可以创建自定义评估器。例如,指标和绘图评估器从数据中提取所需字段,以根据上一阶段收到的预测来评估模型性能。
  • 写入结果:顾名思义,此阶段将结果写入磁盘。

TFMA 与 TensorBoard 的区别

了解了 TFMA 的架构后,我们来看看它与另一个常用工具 TensorBoard 有何不同。

TensorBoard 和 TFMA 在开发过程的不同阶段使用。总体而言,TensorBoard 用于分析训练过程本身,而 TFMA 用于对训练完成的模型进行深度分析。

以下是两者的主要区别:

  • TensorBoard:用于检查单个模型的训练过程,通常在训练期间监控进度。它也可以用于可视化多个模型的训练进度,在训练过程中将每个模型的性能与其全局训练步数进行对比绘图。
  • TFMA:在训练完成后,TFMA 允许开发者比较他们训练模型的不同版本。TensorBoard 可视化的是多个模型在全局训练步数上的流式指标,而 TFMA 可视化的是为单个模型在多个导出的已保存模型版本上计算出的指标。

为何需要切片分析

大多数模型评估结果关注的是整个训练数据集上的聚合或顶层指标,这种聚合常常会掩盖模型性能的问题。

例如,一个模型在整个评估数据集上可能有可接受的 AUC,但在特定切片上表现不佳。通常,一个平均性能良好的模型,可能存在通过查看聚合指标无法发现的故障模式。

切片指标允许您在更细粒度的层面上分析模型性能。此功能使开发者能够识别示例可能被错误标记的切片,或者模型预测过高或过低的切片。

例如,通过按小时对数据进行切片,TFMA 可用于分析一个预测出租车小费慷慨度的模型,对于白天和夜间乘车的乘客是否表现同样良好。

通常,确定哪些切片需要分析,需要关于您的数据和应用的领域知识。

TFMA 的计算优势

上一节我们讨论了切片分析的重要性,本节中我们来看看 TFMA 在计算上的优势。

TensorBoard 在训练期间基于小批量计算指标,这些被称为流式指标,是基于观察到的小批量的近似值。

TFMA 使用 Apache Beam 对整个评估数据集进行一次完整的遍历。这不仅允许准确计算指标,而且由于 Beam 流水线可以使用分布式处理后端运行,因此可以扩展到海量的评估数据集。

需要注意的是,TFMA 计算的是与 TensorFlow 评估工作器相同的 TensorFlow 指标,只是通过对指定数据集的完整遍历来计算得更准确。TFMA 还可以配置为计算模型中未识别或未定义的其他指标。

此外,如果评估数据集被切片以计算特定分段的指标,每个分段可能只包含少量示例。因此,为了准确计算指标,对这些示例进行确定性的完整遍历非常重要。

总结

本节课中,我们一起学习了 TensorFlow Model Analysis (TFMA)。我们了解到 TFMA 是一个强大的开源框架,用于对训练完成的模型进行深度、可扩展的性能分析,尤其擅长通过数据切片来发现隐藏在整体指标下的问题。我们探讨了其四阶段的高层架构,明确了它与 TensorBoard 在用途和计算方式上的区别,并理解了其基于 Apache Beam 进行完整数据集遍历以确保指标计算准确性的优势。掌握 TFMA 有助于确保模型在部署前满足质量标准,并在实际应用中表现稳健。

109:TFMA 实战指南 🛠️

在本节课中,我们将学习如何设置和使用 TensorFlow Model Analysis (TFMA) 来执行模型分析。我们将了解 TFMA 如何帮助您以不同方式评估模型性能,包括评估模型在不同数据切片上的表现,以及随时间跟踪指标。


准备工作与库导入

在开始之前,请注意,本示例在 TFX 管道之外独立使用 TFMA。当您在 TFX 管道中使用 TFMA 时,评估器组件已包含本示例中的许多步骤,因此您无需手动执行。通常,您只需向评估器组件提供 EvalConfig,我们稍后会看到这一点。

首先,我们需要导入所有必要的库。在本例中,我们需要 TensorFlow、TensorFlow Transform 和 TensorFlow Model Analysis。

import tensorflow as tf
import tensorflow_transform as tft
import tensorflow_model_analysis as tfma

第一步:训练模型与生成 SavedModel

使用 TFMA 的第一步是训练您的模型并生成一个 SavedModel 对象。这通常是您为了部署模型而需要做的常规步骤。

原始输入示例在使用 TFMA 进行评估时,需要以与训练期间相同的方式进行预处理。例如,如果某个特征在训练前进行了归一化,那么在评估前也需要进行归一化。

如果您在 TFX 管道中训练模型并包含了 Transform 组件,那么训练期间完成的相同预处理和特征工程将已包含在您的 SavedModel 中。然而,如果您不是在 TFX 中训练的,则需要手动应用相同的预处理,这在本例中通过 get_serving_tf_examples 函数完成,其中使用了 TensorFlow Transform。

接下来,我们生成 SavedModel。在大多数情况下,您希望为 SavedModel 使用默认的服务签名,但您也可以在模型规范配置中明确指定不同的签名。


第二步:创建评估配置 (EvalConfig)

下一步涉及创建一个 EvalConfig 对象,该对象封装了 TFMA 的要求。

具体来说,首先您必须定义数据集的分片以及您希望用于分析模型的指标。然后,将模型、分片、指标和其他配置包装在一个 EvalConfig 对象中。这将决定 TFMA 在运行时执行的操作。这与您在 TFX 管道中提供给评估器组件的 EvalConfig 是相同的。

以下是定义配置的示例:

# 定义分片规范
slice_spec = [
    tfma.slicer.SingleSliceSpec(columns=['feature_column_name']),
    tfma.slicer.SingleSliceSpec(columns=['another_feature'], feature_values={'value': 'specific_value'})
]

# 定义要计算的指标
metrics_specs = [
    tfma.metrics.specs_from_metrics([
        tf.keras.metrics.BinaryAccuracy(name='accuracy'),
        tf.keras.metrics.AUC(name='auc'),
    ])
]

# 创建 EvalConfig
eval_config = tfma.EvalConfig(
    model_specs=[tfma.ModelSpec(label_key='label')],
    slicing_specs=slice_spec,
    metrics_specs=metrics_specs
)

第三步:运行模型分析

设置好 EvalConfig 对象后,您现在可以开始分析模型了。这些示例仅使用一台机器执行分析,因此不需要使用编排器。

代码设置了评估图的路径和存储分析结果的目录。下一步是调用 tfma.run_model_analysis API。这将启动您的模型分析。此 API 也可以直接接受分片规范。

# 设置输出路径
output_path = '/path/to/output/directory'

# 运行模型分析
eval_result = tfma.run_model_analysis(
    eval_shared_model=model_spec, # 您的模型规范
    eval_config=eval_config,
    data_location='/path/to/eval/data', # 评估数据位置
    output_path=output_path
)

第四步:可视化分析结果

最后,让我们渲染结果并可视化模型分析指标。TFMA 提供了可以在 Notebook 中运行的交互式小组件。这是您将包含在 Notebook 单元格中以生成 TFMA 可视化小组件的代码。

# 在 Jupyter Notebook 中渲染结果
tfma.view.render_slicing_metrics(eval_result)

可视化工具看起来是这样的。该工具使您能够深入挖掘模型性能,并理解它在不同数据切片上的变化情况。


总结

在本节课中,我们一起学习了如何设置和使用 TensorFlow Model Analysis (TFMA)。我们从导入必要库开始,然后学习了如何训练模型并生成 SavedModel。接着,我们探讨了如何创建 EvalConfig 对象来定义分析需求,包括数据分片和评估指标。最后,我们运行了模型分析并学习了如何可视化结果,从而深入理解模型在不同数据切片上的表现。

110:模型调试概述 🐛

在本节课中,我们将超越简单的性能指标,探讨如何分析和提升模型性能。我们将重点介绍模型调试的概念、目标及其核心方法。

上一节我们讨论了模型性能的基础评估,本节中我们来看看如何深入分析并提升模型的鲁棒性。

模型鲁棒性检查 🛡️

检查模型鲁棒性是超越简单性能或泛化能力测量的重要一步。

一个模型被认为是鲁棒的,即使一个或多个特征发生相当剧烈的变化,其结果也能保持一致的准确性。当然,鲁棒性有其限度,所有模型都对数据变化敏感。但是,一个模型随着数据变化而以渐进、可预测的方式改变,与一个模型突然产生截然不同的结果,两者之间存在明显差异。

那么,如何衡量模型的鲁棒性呢?首要的一点是,不应在模型训练期间衡量其鲁棒性,也不应使用训练期间使用的相同数据集。在开始训练过程之前,应将数据集拆分为训练集、验证集和测试集。

您可以使用在验证阶段也完全未被模型见过的测试集来测试模型鲁棒性。或者,更好的选择是生成各种新型数据,我们稍后将讨论一些生成此类数据的方法。

衡量指标本身将与训练时使用的类型相同,具体取决于模型类型。例如,回归模型使用RMSE,分类模型使用AUC


提升鲁棒性与模型调试 🧪

接下来,我们看看提升模型鲁棒性的方法。

模型调试是一个新兴学科,专注于发现和修复模型中的问题,并提高模型鲁棒性。模型调试借鉴了模型风险管理、传统模型诊断和软件测试中的各种实践。它试图像测试代码一样测试机器学习模型,这与软件开发中的测试方式非常相似。它探查复杂的机器学习响应函数和决策边界,以检测和纠正机器学习系统中的准确性、公平性、安全性等问题。我们稍后将详细讨论这一点。


模型调试有几个目标。机器学习模型的一大问题是它们可能变得相当不透明,成为“黑箱”。模型调试试图通过突出数据在内部的流动方式来提高模型的透明度。另一个问题是社会歧视。您的模型是否对某些人群效果不佳?模型调试还旨在降低模型遭受攻击的脆弱性。例如,模型投入生产后,可能会收到某些旨在从模型中提取数据以了解模型构建方式的请求。当数据包含私人信息并已用于训练时,这尤其是一个问题。因此,数据在用于训练前是否经过匿名化处理?最后,随着时间的推移,随着输入数据分布的变化,您的模型性能会下降。

以下是三种最广泛使用的调试技术:

  • 基准模型:使用简单或已知的模型作为性能比较的基准。
  • 敏感性分析:系统地改变输入特征,观察模型输出的变化程度。
  • 残差分析:检查模型预测值与实际值之间的差异(残差),以发现系统性误差模式。



本节课中我们一起学习了模型鲁棒性的概念及其重要性,并介绍了模型调试这一新兴领域的目标和三种核心方法(基准模型、敏感性分析、残差分析)。理解这些概念是构建可靠、可信赖的机器学习系统的关键一步。

111:基准模型 🎯

在本节课中,我们将学习基准模型的概念及其在模型调试中的重要作用。基准模型是一种简单而强大的工具,用于评估和验证我们开发的复杂模型的性能。

我们将从讨论使用基准模型开始,这始终是一种良好的模型调试技术。一个不错的起点是将你的模型与基准模型进行比较。

基准模型是一种简单而有效的方法,用于检查模型的性能。基准模型通常是小而简单的模型,在开始正式开发之前,用于为你的问题建立性能基线。

它们通常不是最先进的模型,而是线性模型或其他具有非常稳定性能的简单模型。你可以将你的模型与基准模型进行比较,以查看它是否真的比更简单的基准模型表现更好,这是一种合理性检验。

如果你的模型没有超过基准模型,那可能意味着你的模型存在问题,或者一个简单的模型已经能够准确地对数据进行建模,并且这实际上就是你的应用所需要的全部。

一旦模型通过了基准测试,基准模型就可以作为一个可靠的调试工具。即使你的模型性能优于基准模型,你仍然可以评估哪些测试样本是你的模型预测失败,但基准模型预测正确的。

然后,你需要研究你的模型,找出为什么会发生这种情况。


上一节我们介绍了基准模型的基本概念,本节中我们来看看基准模型的具体应用场景和步骤。

以下是使用基准模型进行模型调试的关键步骤:

  1. 选择基准模型:选择一个简单且性能稳定的模型作为基准,例如线性回归(用于回归问题)或逻辑回归(用于分类问题)。
  2. 在相同数据集上训练:使用完全相同的数据集(训练集、验证集、测试集)来训练你的复杂模型和基准模型。
  3. 比较性能指标:在测试集上计算并比较两个模型的性能指标,例如准确率、精确率、召回率或均方误差(MSE)。
  4. 分析预测差异:如果复杂模型性能更优,进一步分析那些基准模型预测正确而复杂模型预测错误的样本,以发现潜在问题。
  5. 迭代优化:根据分析结果,优化你的复杂模型(例如,调整特征、修改架构或增加数据)。

本节课中我们一起学习了基准模型的核心价值和应用方法。基准模型不仅是衡量模型性能的标尺,更是诊断模型问题的有效工具。通过将复杂模型与简单可靠的基准模型进行比较,我们可以快速验证模型的有效性,并定位性能瓶颈,从而更高效地进行模型开发和调试。记住,一个无法超越简单基准的复杂模型,很可能存在根本性的设计或数据问题。

112:敏感度分析与对抗性攻击 🛡️

在本节课中,我们将学习如何评估机器学习模型的性能,特别是其面对对抗性攻击时的脆弱性。我们将探讨敏感度分析的概念、方法,以及如何识别和防御对抗性攻击。

概述

敏感度分析是评估模型性能的重要方法,包括评估模型对对抗性攻击的脆弱性。让我们深入了解其内容。

敏感度分析通过检查每个特征对模型预测的影响,帮助你理解模型。

在敏感度分析中,你通过改变单个特征的值(同时保持其他特征不变)进行实验,并观察模型结果。

如果改变特征值导致模型结果发生剧烈变化,这意味着该特征对预测有很大影响。

通常,你根据某种分布或过程人为地改变特征值,并忽略数据的标签。

你实际上并不关注预测是否正确,而是关注它改变了多少。不同的敏感度分析方法使用不同的技术来改变特征值。

让我们探讨几种不同的方法。

敏感度分析方法

上一节我们介绍了敏感度分析的基本概念,本节中我们来看看几种具体的分析方法。

以下是几种常见的敏感度分析方法:

  • 随机攻击:你生成大量随机输入数据并测试模型的输出。随机攻击可以揭示各种意想不到的软件和数学错误。如果你不知道从何处开始调试机器学习系统,随机攻击是一个很好的起点。
  • 部分依赖图:部分依赖图显示一个或两个特征的边际效应及其对模型结果的影响。部分依赖图可以显示标签与特定特征之间的关系是线性的、单调的还是更复杂的。例如,当应用于线性回归模型时,部分依赖图总是显示线性关系。
  • 开源工具:PDPbox 和 PICbox 是可用于创建部分依赖图的开源软件包。请查阅阅读列表以获取更多信息。

对抗性攻击

现在我们已经介绍了两种敏感度分析技术,值得一问的是,你的模型对攻击有多脆弱?包括神经网络在内的几个机器学习问题,都可能被欺骗,从而错误分类对抗性样本。这些样本通过对数据进行微小但精心设计的更改而形成,使得模型以高置信度返回错误答案。

这可能带来令人担忧的影响。想象一下,仅基于略微损坏的数据就对重要问题做出错误决定。

根据错误结果对你的应用程序造成的灾难性程度,你可能需要测试模型的漏洞,并根据你的分析,加固你的模型以使其更能抵御攻击。

那么这些攻击是什么样的呢?这里有一个著名的例子,包含两组图像。

仅对左列图像应用微小的扭曲,就产生了右列图像,而一个在 ImageNet 上训练的模型将其分类为鸵鸟。

那么这个问题有多严重呢?这取决于你的应用程序。但让我们讨论几个例子。

  • 自动驾驶汽车:识别交通标志、其他车辆、人等非常重要。不幸的是,我们在现实生活中已经看到了这样的例子。但正如这个例子所示,如果一个标志以某种方式被改变,它就可以欺骗模型,结果可能是灾难性的。
  • 应用程序质量:如果你的企业销售用于检测垃圾邮件的软件,而钓鱼邮件能够通过,这会对你的产品产生负面影响。
  • 关键任务应用:一个更可怕的例子。随着你越来越多地依赖机器学习来完成关键任务应用程序,你需要考虑安全影响。行李箱扫描仪基本上只是一个物体分类器。但如果它容易受到攻击,结果可能是危险的。

攻击类型

未来隐私论坛是一个研究隐私和安全的行业组织,它提出由机器学习促成的安全和隐私危害大致分为两类:信息危害和行为危害。

信息危害涉及信息的意外或未预期的泄露。另一方面,行为危害涉及操纵模型本身的行为,影响模型的预测或结果。

让我们看看信息危害。

以下是几种信息危害攻击:

  • 成员推断攻击:旨在根据模型输出的样本推断某个个体的数据是否被用于训练模型。虽然看起来很复杂,但研究表明,这些攻击所需的复杂程度远低于通常假设的水平。
  • 模型反演攻击:使用模型输出来重建训练数据。在一个著名的例子中,研究人员能够重建个人面部的图像。另一项研究关注使用遗传信息来推荐特定药物剂量的机器学习系统,它能够直接预测个体患者的遗传标记。
  • 模型提取攻击:使用模型输出来重建模型本身。这已被证明可以针对像 BigML 和 Amazon Machine Learning 这样的模型即服务提供商,并且可能损害隐私和安全,以及底层模型本身的知识产权。

那么行为危害呢?

以下是几种行为危害攻击:

  • 模型投毒攻击:当攻击者将恶意数据插入训练数据中以改变模型行为时发生。例如,为特定个人创建人为的低保险费。
  • 规避攻击:当推理请求中的数据故意导致模型对该数据进行错误分类时发生。这些攻击发生在各种场景中,并且数据的变化可能不会被人类察觉。我们之前提到的被篡改的停车标志就是规避攻击的一个例子。

防御与加固

在加固你的模型之前,你需要有某种方法来衡量其受攻击的脆弱性。

CleverHans 是一个开源 Python 库,你可以用它来对你的模型进行基准测试,以衡量它们对对抗性样本的脆弱性。

为了加固你的模型以抵御对抗性攻击,一种方法是在你的训练数据中包含对抗性图像集,以便分类器能够理解噪声的各种分布,并且你的模型学会识别正确的类别。这被称为对抗性训练。由 CleverHans 等工具创建的示例可以添加到你的数据集中,但这样做会限制你使用它们来衡量模型脆弱性的能力,因为你几乎是在用你的训练数据进行测试。

Foolbox 是另一个开源 Python 库,它可以让你轻松地对深度学习网络等机器学习模型运行对抗性攻击。它建立在 EagerPy 之上,并原生支持 PyTorch、TensorFlow 和 JAX 中的模型。

不幸的是,检测漏洞比修复漏洞更容易。这是一个新兴领域,就像安全领域的许多事情一样,攻击者和防御者之间正在进行一场军备竞赛。

一个相当先进的方法是防御性蒸馏。由于它不使用特定的对抗性示例,它可能为新的攻击提供更普遍的加固。顾名思义,这与知识蒸馏训练非常相似,目标是提高模型的鲁棒性并降低敏感性,从而降低受攻击的脆弱性。

在一项研究中,防御性蒸馏将样本创建的有效性从 95% 降低到不到 0.5%。防御性蒸馏与我们之前在模型优化部分讨论的 Hinton 等人提出的原始蒸馏之间的主要区别在于,我们保持相同的网络架构来训练原始网络和蒸馏网络。换句话说,作者提出使用知识蒸馏来提高模型自身的抗攻击能力,而不是在不同架构之间转移知识。

总结

本节课中,我们一起学习了敏感度分析的概念及其在评估模型性能中的作用。我们探讨了随机攻击和部分依赖图等分析方法,并深入了解了对抗性攻击的类型,如信息危害和行为危害。最后,我们讨论了使用 CleverHans 和 Foolbox 等工具进行漏洞检测,以及通过对抗性训练和防御性蒸馏等技术来加固模型。理解并应对这些挑战对于构建健壮、可靠的机器学习系统至关重要。

113:对抗攻击演示 🛡️

在本节课中,我们将学习一种针对机器学习模型的攻击方法——对抗攻击。我们将通过一个具体的演示,了解攻击者如何利用“快速梯度符号法”生成对抗样本,从而欺骗一个原本表现良好的图像分类模型,使其做出错误的预测。

什么是对抗样本?🤔

上一节我们介绍了课程背景,本节中我们来看看对抗攻击的核心概念。

对抗样本是一种专门设计的输入,其目的是混淆神经网络,导致模型对给定的输入进行错误分类。这些输入对人眼来说与正常样本几乎没有区别,但却能导致模型无法正确识别图像内容。

快速梯度符号法攻击 ⚔️

了解了对抗样本的概念后,我们来看看本次演示中使用的具体攻击方法。

存在多种类型的对抗攻击。然而,本演示的重点是快速梯度符号法攻击。这是一种白盒攻击,其目标是确保模型错误分类。白盒攻击是指攻击者拥有对被攻击模型的完全访问权限。

以下是该攻击方法的一个著名示例,取自Goodfellow等人的一篇具有里程碑意义的论文:

  • 左侧的熊猫图片被模型以较高的置信度正确分类。
  • 添加了一些人眼难以察觉的噪声。
  • 结果是,模型现在以极高的置信度认为那只熊猫是一只长臂猿。

实战演示:攻击图像分类模型 🖼️➡️🐕

理论介绍完毕,现在让我们通过一个实际的代码示例,看看这种攻击是如何实施的。我们将看到这种攻击实现起来有多么简单。

我们将在Colab环境中运行此演示。首先进行一些必要的导入并加载一个预训练的MobileNet V2模型及ImageNet类别名称。

import tensorflow as tf
import matplotlib.pyplot as plt

pretrained_model = tf.keras.applications.MobileNetV2(include_top=True, weights='imagenet')

接下来,我们下载并查看原始图像,本例中是一只拉布拉多犬。

# 下载并预处理图像
image_path = tf.keras.utils.get_file('Labrador.jpg', 'https://...')
original_image = preprocess(image_path)
plt.imshow(original_image)

生成对抗图像 🔧

现在,我们将使用快速梯度符号法来创建对抗图像。以下是用于生成扰动的主要代码,其原理非常简单直接:

def create_adversarial_pattern(input_image, input_label):
    with tf.GradientTape() as tape:
        tape.watch(input_image)
        prediction = pretrained_model(input_image)
        loss = loss_object(input_label, prediction)
    gradient = tape.gradient(loss, input_image)
    perturbations = tf.sign(gradient)
    return perturbations

生成扰动后,我们可以将其可视化。观察下图,大多数人不会预期添加这样的扰动会对模型判断产生任何影响,但事实并非如此。

探索攻击参数 Epsilon 📊

为了理解攻击强度的影响,我们将尝试不同的 epsilon 值,这是该方法的一个关键参数。我们将观察不同的 epsilon 值如何导致模型做出不同的预测。

以下是用于展示图像和预测结果的辅助方法。我们测试了几个不同的 epsilon 值及其对应的模型预测:

  • 原始图像:模型以高置信度识别为“拉布拉多犬”。
  • epsilon = 0.01:模型将其误分类为“萨路基犬”(一种细犬)。
  • epsilon 值稍高:模型认为它是“威玛犬”。
  • epsilon 值继续增高:模型仍然以更高的置信度认为是“威玛犬”。

总结 📝

本节课中我们一起学习了对抗攻击的基本概念。我们通过一个具体的演示,展示了如何使用快速梯度符号法这种简单的白盒攻击方法,通过向原始图像添加人眼难以察觉的微小扰动(由 epsilon 参数控制),成功欺骗了一个强大的图像分类模型,使其将拉布拉多犬错误地识别为其他犬种。这个例子清晰地表明,机器学习模型在面对精心设计的对抗样本时可能非常脆弱,这也是MLOps和生产环境中需要考虑模型安全性和鲁棒性的重要原因。

114:残差分析 📊

在本节课中,我们将学习模型调试的最后一项技术——残差分析。这是一种主要用于回归模型的诊断方法,通过分析预测值与真实值之间的差异(即残差)来评估模型性能并发现潜在的改进空间。

上一节我们介绍了其他模型调试技术,本节中我们来看看残差分析的具体应用。

什么是残差分析?

残差分析是一种模型调试技术。在大多数情况下,它适用于回归模型,因为它需要测量预测值与真实值之间的距离。

残差公式残差 = 真实值 - 预测值

然而,这项技术要求拥有用于比较的真实值,这在许多在线或实时场景中可能难以获取。

残差分析的目标

理想情况下,你希望残差遵循随机分布。如果发现残差之间存在相关性,这通常表明你的模型还有改进的余地。

如果你训练过回归模型,可能对均方根误差(RMSE)等指标很熟悉。残差分析也会用到这类误差指标,但它主要关注误差的分布,通常使用残差图来直观检查残差的分布情况。

如果你的模型训练良好,并且已经捕捉到了数据中的预测信息,那么残差应该是随机分布的。然而,如果你看到系统性的或相关的残差,那就说明模型未能捕捉到某些预测信息,你可以据此寻找改进模型的方法。

进行残差分析时的检查要点

以下是进行残差分析时需要注意的几个关键点。

残差不应与未被使用的特征相关
残差不应与另一个可用但未被纳入特征向量的特征相关。如果你能用另一个特征来预测残差,那么这个特征就应该被包含在特征向量中。这需要检查未使用的特征与残差之间是否存在相关性。

相邻残差不应彼此相关
换句话说,它们不应存在自相关性。如果你能用一个残差来预测下一个残差,那就说明模型未能捕捉到某些预测信息。通常(但不总是),你可以在残差图中直观地看到这一点。理解这一点时,数据的顺序可能很重要。

例如,如果一个残差之后更可能出现另一个符号相同的残差,则相邻残差呈正相关。进行杜宾-瓦森检验也有助于检测自相关性。

总结

本节课中,我们一起学习了残差分析这项重要的模型调试技术。我们了解到,残差分析通过检查预测误差的分布来诊断回归模型。核心目标是确保残差随机分布,无系统性模式或自相关性。若发现残差与遗漏特征相关或自身存在自相关,则表明模型有改进空间,可以通过纳入新特征或调整模型结构来提升性能。

115:模型修复 🛠️

在本节课中,我们将探讨如何提升机器学习模型的鲁棒性,并学习一系列模型修复技术。我们将从数据增强、模型可解释性入手,进而讨论如何减少模型偏见,并介绍模型调试与持续监控的重要性。


分析鲁棒性与修复方法

上一节我们讨论了如何分析模型的鲁棒性。本节中,我们来看看如何通过具体技术来提升它。

模型修复是指当发现模型在鲁棒性、公平性或安全性等方面存在不足时,所采取的一系列改进措施。


提升模型鲁棒性的技术

为了提升模型的鲁棒性,你可以采取以下几种方法。

确保训练数据代表性

首先,必须确保你的训练数据能够准确反映模型部署后将接收到的请求。这是构建鲁棒模型的基础。

数据增强

数据增强可以帮助模型更好地泛化,从而通常能降低其对输入变化的敏感性。

以下是几种常见的数据生成方式:

  • 生成式技术:使用生成模型(如GANs)创建新数据。
  • 解释性技术:基于对数据分布的理解来生成样本。
  • 添加噪声:简单地向现有数据中添加随机噪声。

数据增强也是纠正数据不平衡问题的有效手段。

理解模型内部机制

理解模型的内部工作机制同样重要。通常,更复杂的模型如同“黑箱”,我们有时并未深入探究其内部运行逻辑。

然而,存在一些工具和技术可以帮助提升模型的可解释性,这反过来也有助于改善模型的鲁棒性。

此外,某些模型架构本身就更容易解释,包括:

  • 基于树的模型(如决策树、随机森林)。
  • 专门为可解释性设计的神经网络模型

模型编辑

模型编辑是另一种修复技术。对于一些模型,例如决策树,其学习到的参数可以直接被理解。

如果你发现模型在某些方面表现不佳,可以直接调整模型参数来提升其性能和鲁棒性。

模型断言

模型断言是将业务规则或简单的合理性检查应用于模型的输出结果,并在交付结果前对其进行修改或绕过。

例如:

  • 如果预测某人的年龄,结果永远不应为负数
  • 如果预测信用额度,则永远不应超过某个最大金额

这可以通过在输出层添加后处理逻辑来实现,例如:

def apply_assertions(prediction):
    if prediction < 0:
        return 0
    elif prediction > MAX_CREDIT_LIMIT:
        return MAX_CREDIT_LIMIT
    else:
        return prediction

减少或消除模型偏见

接下来,我们看看如何减少或消除模型偏见,这被称为歧视修复

使用多样化的数据集

最佳的解决方案是拥有一个多样化的数据集,它能代表将要使用你模型的所有人群。

组建多元化的开发团队

让具有不同背景、并在伦理、隐私、社会科学等相关领域有专长的人员加入开发团队也大有裨益。

谨慎的特征选择与数据重加权

在训练数据阶段,通过采样重新加权数据行来最小化歧视,也是很有帮助的方法。

训练时考虑公平性指标

在训练时,选择超参数和决策截断阈值时应考虑公平性指标。这需要使用像 Fairness Indicators 这样的工具来度量公平性。

这也可能涉及直接训练公平模型,具体方法包括:

  • 学习公平表示
  • 使用如 AIF360 等工具进行对抗性去偏
  • 使用同时考虑准确性和公平性指标的双目标损失函数,例如:
    总损失 = α * 准确率损失 + β * 公平性损失

预测后处理

在训练后改变模型预测,例如使用 AIF360TensorFlow Model Analysis 中的拒绝选项分类等工具,也有助于减少不希望的偏见。

Google Model Remediation Library 这样的工具库可以帮助提升模型公平性。请查阅课程末尾的参考资料,获取相关库和资源的链接。


模型调试与持续监控

模型调试并非仅在开发阶段进行,它需要对模型进行持续监控

随着数据和世界的变化,以及新攻击方式的出现,模型的准确性、公平性或安全性特征在其整个生命周期内都会发生变化。

你应该将监控构建到你的流程中,以便定期检查模型是否存在准确性、公平性和安全性问题。

在机器学习中,奇怪或异常的输入和预测值总是令人担忧,并可能预示着攻击。

幸运的是,可以利用多种工具和技术实时捕获并纠正异常输入和预测,包括:

  • 对输入流施加数据完整性约束
  • 对输入和预测应用统计过程控制方法
  • 通过自编码器隔离森林进行异常检测。
  • 将你的模型预测与基准模型预测进行比较。

总结

本节课中,我们一起学习了多种模型修复技术。我们从提升模型鲁棒性的方法开始,涵盖了数据增强、提高模型可解释性模型编辑模型断言。接着,我们探讨了如何通过使用多样化数据、谨慎的特征工程、在训练中纳入公平性指标以及后处理技术来减少模型偏见。最后,我们强调了持续监控实时异常检测对于维护模型长期健康与安全的重要性。记住,构建负责任的机器学习系统是一个需要不断迭代和改进的过程。

116:38_公平性 🧠⚖️

在本节课中,我们将学习如何确保机器学习模型的公平性,并介绍如何使用公平性指标库来评估公平性。除了提升模型性能,确保模型在不同场景下公平运行,避免对任何人群产生偏见,是负责任地服务社区和客户的重要环节。


公平性的重要性

上一节我们介绍了模型性能分析,本节中我们来看看公平性。确保模型不会对使用者造成伤害至关重要。公平性指标库是TensorFlow团队开发的开源工具,旨在方便地计算二元和多类分类器中常见的公平性指标。

该库基于TensorFlow模型分析框架构建,具有良好的扩展性。


公平性指标库的主要功能

公平性指标库的核心功能是便于测量二元和多类分类器的常见公平性指标。

以下是其主要功能:

  • 可以比较模型在不同子组间的性能,并与基线或其他模型进行对比。
  • 支持使用置信区间来揭示统计上显著的差异。
  • 支持在多个阈值上进行评估。

需要明确的是,公平性指标库主要用于测量公平性,而非直接进行修正以提升公平性。


如何测量公平性:数据切片

在尝试减轻偏见和检查公平时,查看数据切片能提供丰富的信息。

测量公平性时,识别对公平性敏感的数据切片并测量模型在这些切片上的性能非常重要。如果仅使用整个数据集测量公平性,很容易掩盖针对特定人群的公平性问题。

同样重要的是,为你的数据集和用户考虑并选择合适的度量指标,否则可能测量错误而无法发现问题。这通常基于领域知识。

请记住,测量公平性只是评估更广泛用户体验的一部分。


识别相关数据切片

首先,思考用户可能体验你应用程序的不同情境。

以下是识别切片的关键步骤:

  • 明确你应用程序的不同用户类型。
  • 思考还有哪些人会受到体验的影响。

人类社会极其复杂,理解人及其社会身份、社会结构和文化体系本身都是广阔的研究领域。在可能的情况下,建议咨询相关领域专家,例如社会科学家、社会语言学家、文化人类学家,以及将使用你应用程序的社区成员。

一个好的经验法则是尽可能多地对数据组进行切片。要特别关注涉及敏感特征的数据切片,例如:

  • 种族
  • 民族
  • 性别
  • 国籍
  • 收入
  • 性取向
  • 残疾状况

理想情况下,你应该使用带有标签的数据。如果没有,则可以应用统计学方法,在假设任何预期差异的情况下,查看结果的分布。


使用公平性指标的指导原则

让我们看看使用公平性指标时,为避免常见陷阱的一些重要指导原则。

以下是关键指导原则:

  1. 刚开始使用公平性指标时,应对所有可用数据切片进行各种公平性测试。
  2. 接下来,应跨多个阈值评估公平性指标,以理解阈值如何影响不同群体的性能。
  3. 最后,对于那些预测结果与决策边界没有明显分离的情况,应考虑报告标签被预测的比率。

总结

本节课中,我们一起学习了机器学习模型公平性的重要性,并详细介绍了TensorFlow公平性指标库的功能与使用方法。我们探讨了通过数据切片来识别和测量公平性问题,以及在实际应用中应遵循的指导原则。记住,构建公平的模型是创建负责任、可信赖人工智能系统的关键一步。

117:39_衡量公平性 😊

在本节课中,我们将学习机器学习模型公平性的各种衡量指标。我们将了解这些指标的定义、适用场景,并通过一个具体的数据集案例来实践如何评估模型的公平性。


现在,让我们看看公平性指标工具中提供的各种公平性度量标准。

这包括正负率、真正假正例比率、准确率和曲线下面积。我们将从这些指标的快速概述开始。

基本正负率 📊

上一节我们介绍了公平性指标的概念,本节中我们来看看最基础的衡量标准。

基本正负率显示被分类为正例或负例的数据点的百分比。这些指标独立于真实标签。它们有助于理解人口统计平等性,即结果在不同子群体间应保持平等。

这适用于不同群体获得相同比例结果至关重要的用例。

以下是基本正负率的定义:

  • 正例率:模型预测为正例的数据点占总数据点的百分比。
  • 负例率:模型预测为负例的数据点占总数据点的百分比。

真正率与假负率 ⚖️

了解了基础比率后,我们来看看与正类机会平等相关的指标。

真正率,也称为TPR;假负率,也称为FNR。

真正率衡量的是,在真实标签为正例的数据点中,被正确预测为正例的百分比。类似地,假负率衡量的是,在真实标签为正例的数据点中,被错误预测为负例的百分比。

这个指标关系到正类的机会平等,它应在不同子群体间保持相等。这通常适用于以下用例:确保每个群体中相同比例的合格候选人获得积极评价至关重要,例如贷款申请或学校录取。

以下是相关公式:

  • 真正率 = 真正例 / (真正例 + 假负例)
  • 假负率 = 假负例 / (真正例 + 假负例)

真负率与假正率 ⚖️

接下来,我们探讨与负类机会平等相关的指标。

真负率,也称为TNR;假正率,也称为FPR。

真负率衡量的是,在真实标签为负例的数据点中,被正确预测为负例的百分比。类似地,假正率是真实标签为负例的数据点中,被错误预测为正例的百分比。

这个指标关系到负类的机会平等,它应在不同子群体间保持相等。这适用于以下用例:将某物错误分类为正例比正确分类正例更令人担忧。这在滥用检测案例中最常见,其中正例通常会导致负面行动。这对于面部分析技术(如人脸检测或人脸属性识别)也很重要。

以下是相关公式:

  • 真负率 = 真负例 / (真负例 + 假正例)
  • 假正率 = 假正例 / (真负例 + 假正例)

准确率与AUC 📈

最后,我们来了解准确率和曲线下面积这两组公平性指标。

准确率是被正确标记的数据点的百分比。AUC是在每个类别被赋予相同权重(与样本数量无关)时,被正确标记的数据点的百分比。

这两个指标都与预测平等性相关,应在不同子群体间保持相等。这适用于任务精度至关重要,但不必特定于某个方向的用例,例如人脸识别或人脸聚类。

以下是相关公式:

  • 准确率 = (真正例 + 真负例) / 总样本数

重要考量与注意事项 ⚠️

在介绍了各类指标后,我们需要理解如何正确解读和使用它们。

以下是使用公平性指标时需要考虑的一些要点:

  • 两个群体之间指标的显著差异可能表明你的模型存在公平性问题。你应该根据你的用例来解释结果。
  • 其次,使用公平性指标实现群体间的平等并不能保证你的模型是公平的。系统非常复杂。在一个甚至所有提供的指标上实现平等都不能保证公平性。
  • 公平性评估应在整个开发过程以及发布后持续进行。就像改进产品是一个持续的过程,并根据用户和市场反馈进行调整一样,使产品公平公正也需要持续的关注。随着模型的不同方面发生变化,例如训练数据、来自其他模型的输入或设计本身,公平性指标很可能会发生变化。
  • 最后,应对罕见和恶意示例进行对抗性测试。公平性评估并非旨在取代对抗性测试,而是为了针对罕见的有针对性的示例提供额外的防御,这一点至关重要,因为这些示例可能不会包含在训练或评估数据中。

实践案例:CelebA数据集 😊

现在,让我们看一个使用公平性指标的具体例子。

让我们考虑CelebA数据集,它包含20万张名人图像。除了名人的图像,每个示例还有40个属性注释。其中一些属性是头发类型、面部特征、时尚配饰等。每张图像还有五个面部标志位置,标记眼睛、鼻子和嘴巴的位置。

通常假设,在这个数据集的标注过程中,微笑属性是通过对象脸上愉悦、友善或有趣的表情类型来确定的。

因此,你将练习使用公平性指标来探索此数据集中的微笑属性。

以下是实践步骤:

  1. 首先,你将开始构建一个分类模型,以识别图像中的人是否在微笑。
  2. 模型准备就绪后,你将使用公平性指标评估模型在不同年龄组中的表现。
  3. 最后,你将绘制一些指标图表,以了解我们的模型表现如何。

本节课中,我们一起学习了衡量机器学习模型公平性的核心指标,包括基本正负率、真正/假负率、真负/假正率以及准确率和AUC。我们理解了这些指标分别适用于评估不同维度的公平性,并认识到公平性评估是一个需要结合具体业务场景、贯穿模型生命周期并辅以对抗测试的持续过程。最后,我们通过CelebA数据集的微笑属性分类案例,了解了公平性评估的实践流程。

118:持续评估与监控 📊

在本节课中,我们将学习如何确保已部署的机器学习模型在生产环境中保持健康运行。核心在于理解并实施持续评估与监控,以便在模型性能下降时获得早期预警。


模型性能为何会变化?🔄

上一节我们介绍了模型部署后的基本流程,本节中我们来看看模型上线后可能面临的核心挑战。

训练模型时,我们使用的是当时可用的训练数据。这些数据代表了数据收集和标注时世界的一个快照。但世界会变化,对于许多领域,数据也会随之变化。一段时间后,当模型被用于生成预测时,它可能对当前世界的状态了解不足,从而无法做出准确的预测。

例如,一个预测电影销量的模型如果基于90年代收集的数据训练,它可能会预测客户会购买VHS录像带。这在今天显然不是一个好的预测。当模型性能变差时,你的应用程序和客户将受到影响。

为了避免在问题爆发后才手忙脚乱地收集新训练数据并修复模型,你需要一个关于模型性能变化的早期预警。持续监控和评估你的数据及模型性能有助于提供这种预警。


理解数据漂移与偏移 📈

让我们深入了解数据可能发生变化的几种形式。

最极端的形式是概念漂移,它指的是输入数据和标签之间关系的变化。即使你的其他数据没有变化,概念漂移也可能发生。例如,六个月前购买红色靴子的同一位客户,如果时尚潮流改变,今天可能想要白色运动鞋。模型的输入可能完全相同(取决于你捕获了哪些特征),但正确的预测已经改变。

还有新兴概念,指的是数据分布中以前数据集中不存在的新模式。这可以通过几种方式发生。标签可能变得过时,可能需要添加新标签,就像我们之前的VHS例子。

根据分布变化的类型,数据集偏移可分为两种类型:

以下是两种主要的数据集偏移类型:

  1. 协变量偏移:输入数据的分布发生变化,但给定输入时输出的条件概率保持不变。标签的分布没有改变。
    • 公式描述P(Y|X) 不变,但 P(X) 改变。
  2. 先验概率偏移:基本上是协变量偏移的反面。标签的分布发生变化,但输入数据保持不变。概念漂移可以被视为一种先验概率偏移。
    • 公式描述P(X) 不变,但 P(Y) 和/或 P(Y|X) 改变。

如何监控数据与模型?🔍

现在,让我们思考如何在生产环境中监控数据和模型性能。

首先,设想一个生产环境中的已训练模型。从用于预测的原始数据开始,在做出预测之前,你可能需要对原始数据进行一些预处理,然后模型根据输入数据生成预测。

现在,让我们添加监控和评估环节:

  1. 监控接收到的原始数据:将其与你训练模型时使用的数据进行比较。这让你可以寻找输入数据随时间的变化,即协变量偏移。
  2. 监控模型生成的预测:这使你能够检测先验概率偏移。
  3. 添加标注流程:这有助于检测概念漂移。请注意,在许多情况下,为新输入数据的样本生成标签会有显著的延迟。

添加了监控之后,如何寻找漂移和偏移呢?方法分为有监督无监督两种,取决于你是否拥有输入数据流的标签以及你要寻找的漂移或偏移类型。


有监督监控技术 🎯

有监督技术需要数据的真实标签。以下是三种主要方法:

1. 统计过程控制

这种方法自20世纪20年代以来主要用于制造业的质量控制。它使用统计方法来监控和控制一个过程,对于已部署的模型而言,这个过程就是用于预测请求的输入原始数据流。它假设数据流是平稳的(取决于你的应用可能成立也可能不成立),并且错误遵循二项分布。它分析错误率,并在分布参数超出某个阈值规则时触发漂移警报。

2. 序列分析

在序列分析中,我们使用一种称为线性四率的方法。基本思想是,如果数据是平稳的,列联表应保持恒定。这里的列联表对应于你可能熟悉的分类器真值表:真正例、假正例、假反例、真反例。你用这些来计算四个率:净预测值、精确率、召回率和特异度。如果模型预测正确,这四个值应保持恒定。

3. 错误分布监控

这里选择的方法称为自适应窗口法。在此方法中,你将输入数据划分为窗口,窗口大小根据数据自适应调整。然后计算每个数据窗口的平均错误率。最后,计算每个连续窗口平均错误率均值的绝对差,并将其与基于霍夫丁界的阈值进行比较。霍夫丁界用于检验两个总体均值之间的差异。


无监督监控技术 🕵️♂️

有监督技术的主要问题是你需要标签,而生成标签可能成本高昂且速度慢。无监督技术则不需要标签。请注意,即使你拥有标签,除了有监督技术外,也可以使用无监督技术。

以下是三种主要的无监督监控技术:

1. 聚类或新颖性检测

在此方法中,你将输入数据聚类到已知类别之一。如果你发现新数据的特征远离已知类别的特征,那么你就知道遇到了新兴概念。根据你选择的聚类类型,有多种算法可用(如Olinda, Minas, ES Minor, GC3)。虽然聚类可视化和处理低维数据效果很好,但一旦维度数量显著增长,维度灾难就会出现。此时这些方法开始变得低效,但你可以使用PCA等降维技术来使其易于管理。此方法的缺点是它只检测基于聚类的漂移,而非基于总体的变化。

2. 特征分布监控

在特征分布监控中,我们分别监控数据集的每个特征。你将输入数据分割成统一大小的窗口,然后将各个特征与每个数据窗口进行比较。有多种算法可用于进行比较,其中最流行的两种是:

  • 皮尔逊相关性:用于“概念变化”技术。
  • 海林格距离:用于海林格距离漂移检测方法。海林格距离用于量化两个概率分布之间的相似性。

与新颖性检测类似,如果出现维度灾难,你可以利用PCA等降维技术来减少特征数量。此方法的缺点是无法检测总体漂移,因为它只查看单个特征。

3. 模型依赖监控

此方法监控模型潜在特征空间中决策边界或边界附近的空间。使用的算法之一是边界密度漂移检测。模型置信度低的边界附近的空间比其他地方更重要,此方法寻找落入边界内的输入数据。边界内样本数量的变化(边界密度)即指示漂移。此方法非常擅长降低误报率。


实践工具与服务示例 🛠️

有许多方法可以评估模型性能的不同方面,包括查看输入请求流和模型生成的预测。包括谷歌在内的云托管提供商都提供了可用于持续评估数据和/或模型的服务。

让我们以谷歌云AI持续评估为例,它主要关注概念漂移,作为可用服务类型的一个示例。

谷歌云AI持续评估会定期从你部署到AI平台预测的已训练模型中采样预测输入和输出。AI平台数据标注服务随后为收到的预测请求样本分配人工审核员以提供真实标签,或者你也可以使用其他技术提供自己的真实标签。数据标注服务然后将模型的预测与真实标签进行比较,以提供关于模型随时间性能表现的持续反馈。

流程如下:

  1. 将训练好的模型作为模型版本部署到AI平台预测。
  2. 为该模型版本创建评估任务。
  3. 当模型提供在线预测时,部分预测的输入和输出会保存在BigQuery表中(可自定义采样数据量)。
  4. 评估任务间歇性运行,生成评估指标,你可以在谷歌云控制台中查看。


何时重新训练模型?⏰

你应该多久重新训练一次模型?这个问题没有固定答案,很大程度上取决于数据和所建模的世界。数据的变化速率和你所建模世界的变化速率将决定你需要多频繁地重新训练模型以适应变化。

当然,你可以随时重新训练模型,包括当你改进了模型设计时。过于频繁地重新训练是可以的,但可能导致计算资源成本更高。重新训练不够频繁则可能导致模型性能下降。理想情况下,你应该充分监控数据和模型,以便能够使用评估结果自动触发重新训练。如果无法做到这一点或部署尚未达到该成熟度水平,那么你也可以按计划重新训练。

示例:假设你销售体育用品,并使用模型预测销售额以便订购库存。在冬季,你的模型表现良好,库存订购近乎完美。然而,随着春天临近,你开始看到客户行为的变化。以前购买滑雪板的同一位客户开始购买网球拍。但由于你实施了持续监控,你及早发现了问题,并使用近期客户互动和销售的新数据重新训练了模型,使你的库存恢复近乎完美。


总结 📝

本节课中我们一起学习了机器学习模型部署后保持健康运行的关键:持续评估与监控

我们首先探讨了模型性能随时间变化的原因,特别是数据漂移(如协变量偏移)和概念漂移。接着,我们介绍了监控的框架,包括对原始数据、模型预测以及通过标注流程进行监控。

然后,我们详细讲解了有监督监控技术(如统计过程控制、序列分析、错误分布监控)和无监督监控技术(如聚类检测、特征分布监控、模型依赖监控),并分析了各自的优缺点。我们还以谷歌云AI持续评估为例,了解了可用的云服务工具。

最后,我们讨论了重新训练模型的时机,强调需要根据数据变化速率和业务需求,通过监控结果来指导决策,以实现成本与性能的平衡。

通过实施有效的持续评估与监控,你可以在模型性能显著影响业务之前及时发现问题并采取行动,确保机器学习系统长期稳定地创造价值。

119:可解释的AI 🔍

在本节课中,我们将要学习可解释人工智能(Explainable AI)的概念、重要性及其在机器学习工程生产实践中的应用。我们将探讨为什么理解模型决策过程至关重要,并介绍一些核心的解释技术。


欢迎回来。本周的主题是可解释性。

向你自己,也可能向其他人解释,为什么你的模型做出了特定的决策。

在许多生产环境的机器学习应用中,可解释性正变得越来越重要,原因有很多,包括公平性、监管要求和法律要求,以及为了更好地理解你的模型,以便修复问题或改进它。

因此,让我们开始探讨可解释性。我们将从讨论可解释人工智能开始。

随着模型变得越来越复杂,可解释性变得越来越重要,同时也变得越来越困难。但好消息是,实现可解释性的技术也在不断进步。

具体来说,你可以理解为我们将要研究可解释性。

可解释性与负责任的人工智能 🤝

可解释性和可说明性是更广泛的“负责任的人工智能”领域的一部分。

人工智能的发展及其在越来越多问题上的成功应用,使得执行以前不可能完成的任务的能力迅速增长。这创造了许多新的巨大机遇,但同时也将巨大的权力赋予了模型的结果。

有时,人们会对模型及其如何负责任地处理影响人们并可能造成伤害的诸多因素提出疑问。因此,我们之前讨论过的公平性问题,是负责任人工智能的核心。在更小的意义上,可说明性和可解释性是实现负责任人工智能的关键,因为我们需要理解模型是如何生成其结果的。

隐私也是负责任人工智能的一部分,因为模型通常使用个人可识别信息(PII)进行操作,并且通常使用PII进行训练。当然,安全性也是一个问题,并且与隐私相关,因为我们讨论过的一种攻击就是从模型中提取训练数据,这可能意味着从模型中提取私人信息。

解释模型结果的不同方式 🛠️

模型产生的结果可以通过不同的方式解释。

最先进的技术之一是创建一种本质上可解释的模型架构。一个简单的例子是基于决策树的模型,其本质上是可解释的。但如今,越来越多先进且复杂的模型架构也被设计成具有内在可解释性。这就是可解释人工智能(XAI)领域。

可解释性在许多方面都很重要,包括确保公平性、寻找训练数据中的偏见问题、满足监管、法律和品牌声誉要求,以及单纯地研究模型内部结构以优化其产生最佳结果。

为什么AI可解释性如此重要?❓

从根本上说,这是因为我们需要解释模型做出的结果和决策。这对于高敏感性的模型尤其重要,包括自然语言模型,这些模型在面对某些示例时,可能会产生完全错误的结果。

这也包括对攻击的脆弱性,我们需要持续评估这种脆弱性,而不仅仅是在攻击发生之后。当然,公平性是一个关键问题,因为我们希望确保公平对待模型的每一位用户。

这也会影响我们的声誉和品牌形象,尤其是在客户或其他利益相关者可能质疑或挑战我们模型的决策时,但事实上,在任何我们生成预测的情况下都可能发生。当然,还存在法律和监管方面的担忧,特别是当有人非常不满,以至于在法庭上挑战我们和我们的模型时,或者当我们的模型导致有害行为时。

深度神经网络的脆弱性:对抗性攻击 🎯

深度神经网络可能会被欺骗,从而对输入进行错误分类,产生与真实类别毫无相似之处的结果。这在图像分类的例子中最容易看到,但根本上,它可以发生在任何模型架构上。

本幻灯片上的示例演示了一种黑盒攻击,即攻击是在无法访问模型的情况下构建的。该示例基于一个使用物理对抗样本进行图像分类的手机应用程序。

你看到的是数据集中一张干净的洗衣机图像,即左侧的图像A。该图像被用来生成具有不同程度扰动的对抗性图像。接下来是打印出干净图像和对抗性图像,然后使用Tensorflow相机演示应用程序对它们进行分类。

干净的图像B通过相机感知时被正确识别为洗衣机,而图像C和D中增加的对抗性扰动导致了更严重的错误分类。关键结果是图像D,模型认为洗衣机要么是一个保险箱,要么是一个扬声器,但绝对不是洗衣机。😊,看着这张图片,你同意模型的判断吗?可能不同意吧?

你能看出所施加的对抗性扰动吗?这并不容易看出来。

这或许是此类模型攻击中最著名的例子:通过添加难以察觉的、精心设计的小量噪声,一张熊猫的图片可以被错误分类为长臂猿,并且置信度高达99.3%。这远高于模型最初认为它是熊猫的置信度。😊。


总结 📝

本节课中,我们一起学习了可解释人工智能的核心概念。我们了解到,随着模型复杂度的增加,理解其决策过程对于确保公平性、满足法规要求、维护品牌声誉以及优化模型性能变得至关重要。我们探讨了可解释性作为“负责任的人工智能”一部分的角色,并看到了即使是先进的深度神经网络也可能受到对抗性攻击的影响,这进一步凸显了拥有可解释模型的重要性。掌握这些知识是构建可靠、可信赖的生产级机器学习系统的关键一步。

120:模型解释方法 🧠

在本节课中,我们将要学习模型解释的基本方法。理解模型为何做出特定预测至关重要,这有助于建立信任、确保公平性、实现透明化,并促进模型诊断与调试。


模型解释的定义与重要性

模型的可解释性没有一个严格的数学定义。Beron 和 Cotton 提供了一个很好的定义:如果一个系统(或模型)的运作过程能够被人类通过内省或生成的解释所理解,那么它就是可解释的。换句话说,如果人类有办法弄清楚模型为何产生某个特定结果,那么该模型就是可解释的。

然而,从实践角度看,所需的解释工作量也必须是可行的。衡量模型可解释性的一个标准,就是理解一个给定结果所需付出的努力或分析量。

理想情况下,你应该能够通过查询模型来理解其算法决策的内容原因方式。这能帮助你识别和验证驱动模型输出的关键变量,从而在即使面对未预见情况时,也能建立对预测系统可靠性的信任。这种诊断有助于确保模型的安全性和可问责性。


模型解释方法的分类标准

有多种标准可用于对模型解释方法进行分类。例如,解释方法可以根据其是内在的还是事后的来分组;也可以是模型特定的或模型无关的;还可以根据其解释范围是局部的还是全局的来划分。

接下来,我们逐一讨论这些分类标准。


内在可解释模型 vs. 事后解释方法

一种对模型可解释性方法进行分类的方式,是看模型本身是否是内在可解释的。

内在可解释的模型架构已经存在很长时间,其经典例子是线性模型基于树的模型。然而,最近也出现了更先进的模型架构,例如格模型,它们能够在复杂的建模问题上同时实现可解释性和高精度。例如,格模型的精度可以匹配甚至在某些情况下超过神经网络。

现在,让我们考虑事后方法。

事后方法将模型视为“黑箱”,通常不区分不同的模型架构。它们倾向于以相同方式对待所有模型,并在训练后应用,试图通过检查特定结果来理解模型生成它们的原因。不过,也存在一些方法(特别是针对卷积网络),会检查网络内部的层以试图理解结果是如何生成的。

然而,由于事后方法并不评估导致结果生成的实际操作序列,因此对于特定结果的原因解释是否正确,总是存在一定程度的不确定性。通常,内在可解释模型对于其为何生成特定结果能提供更高的确定性。这类分析的例子包括特征重要性部分依赖图


解释方法的输出类型

各种解释方法也可以根据其产生的结果类型进行大致分类。

以下是几种主要的输出类型:

  • 特征统计摘要:一些方法创建特征的统计摘要。
  • 单值特征解释:一些方法为特征返回单个值。例如,特征重要性为每个特征返回一个数字。一个更复杂的例子是成对特征交互强度,它为每对特征关联一个数字。
  • 可视化摘要:一些方法依赖可视化来总结特征,例如部分依赖图。部分依赖图是显示某个特征与其平均预测输出之间关系的曲线。在这种情况下,绘制曲线比简单地在表格中表示数值更有意义且更直观。

模型特定方法与模型无关方法

一些方法会查看模型的内部结构。内在可解释模型的解释就属于这一类。

例如,对于线性模型这类较简单的模型,你可以查看学习到的权重来进行解释。类似地,基于树的模型中学习到的树结构本身就是一种解释。在格模型中,每一层的参数就是该层的输出,这使得分析和调试模型的每个部分相对容易。

模型特定方法仅限于特定的模型类型。例如,回归权重和线性模型的解释就是模型特定的。根据定义,解释内在可解释模型的技术也是模型特定的。但模型特定方法并不仅限于内在可解释模型,也存在专门针对神经网络解释的工具。

模型无关方法则不特定于任何特定模型。它们可以在任何模型训练完成后应用。本质上,它们属于事后方法。这些方法无法访问模型的内部结构(如权重、参数等),它们通常通过分析特征输入和输出对,并试图推断其关系来工作。


局部解释与全局解释

除了将解释方法分为模型无关或模型特定,还可以根据它们生成的解释是局部的还是全局的来分组。

可解释性方法可以是局部的或全局的,这取决于该方法是解释单个预测还是解释整个模型的行为。有时,解释范围可能介于局部和全局之间。

局部可解释性方法解释单个预测。例如,对数据集中单个示例的预测进行特征归因。特征归因衡量了每个特征对给定结果的预测贡献了多少。

以下是一个使用名为 Shap 的库进行特征归因的示例,它解释了一个在波士顿房价数据集上训练的梯度提升集成树对单个示例的预测。这个例子展示了局部解释的样子。

# 示例:使用 SHAP 库进行局部特征归因
import shap
# ... 加载模型和单个数据实例 ...
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(instance)
shap.force_plot(explainer.expected_value, shap_values, instance)

图表显示了各特征在将模型输出从基准值推向实际模型输出过程中的贡献。红色特征将模型推向更高值,蓝色特征则将模型输出推向更低值。

全局方法解释整个模型的行为。例如,如果某个方法为整个测试集上的预测创建了特征归因的摘要,那么它就可以被认为是全局的。

以下是一个由 Shap 库创建的全局解释示例。它显示了波士顿房价数据集预测中,每个样本的每个特征的 Shap 值(特征归因)。颜色代表特征值,红色表示高,蓝色表示低。你可以看到,例如,随着 LSTAT(低收入人口比例)的增加,往往会导致预测房价下降。由于这个解释展示了数据集中所有实例的所有特征归因的概览,因此它被认为是全局的。


总结

本节课中,我们一起学习了模型解释的核心概念与方法。我们首先明确了模型可解释性的定义及其在建立信任、确保公平与透明方面的重要性。接着,我们系统性地探讨了模型解释方法的多种分类维度:内在可解释模型(如线性模型、决策树、格模型)与事后解释方法;根据输出类型划分的统计摘要单值解释可视化模型特定方法模型无关方法;以及局部解释(针对单个预测)与全局解释(针对整个模型行为)。理解这些分类有助于我们在实际工作中,根据模型类型和业务需求,选择合适的工具和技术来打开模型“黑箱”,使其决策过程更加可信和可控。

121:内生可解释模型 📊

在本节课中,我们将学习什么是内生可解释模型,并探讨几种具体的可解释模型架构,包括线性模型和格点模型。我们将了解这些模型如何通过其透明和直观的工作原理,帮助我们理解模型是如何得出特定预测结果的。


什么是内生可解释模型?🤔

自统计分析和机器学习的早期阶段以来,就存在一些本质上可解释的模型架构。

内生可解释模型的一个定义是:模型的工作原理足够透明和直观,通过检查模型本身,就能相对容易地理解模型是如何产生特定结果的。

许多经典模型具有高度可解释性,例如基于树的模型和线性模型。然而,尽管我们看到神经网络能够产生惊人的结果,但它们往往非常不透明,尤其是那些更大、更复杂的架构,这使得它们在试图解释时如同“黑箱”。这限制了我们解释其结果的能力,并迫使我们使用事后分析工具来试图理解它们如何得出特定结果。

不过,一些专门为可解释性设计的新架构已经被创建出来,它们同时保留了深度神经网络的能力。这仍然是一个活跃的研究领域。


单调性:提升可解释性的关键 🔑

有助于提高可解释性的一个关键特征是特征的单调性。

单调性意味着,随着特征值的变化,该特征对模型结果的贡献要么持续增加,要么持续减少,要么保持不变。这里的关键因素是“一致性”。这与许多问题中许多特征的领域知识相匹配。

因此,当你试图理解一个模型结果时,如果特征是单调的,它就符合你对所建模现实世界的直觉。例如,如果你试图创建一个预测二手车价值的模型,在所有其他特征保持不变的情况下,汽车行驶的里程数越多,其价值应该越低。你不会期望一辆里程数更多的车比里程数更少的车更值钱。这符合你对世界的认知,因此你的模型也应该与之匹配,里程数特征应该是单调的。

在下图中,蓝色和绿色曲线是单调的,而红色曲线不是,因为它没有持续增加、减少或保持不变。


可解释的模型架构 🏗️

上一节我们介绍了单调性的概念,本节中我们来看看几种被认为是可解释的模型架构。

首先,线性模型非常可解释,因为线性关系易于理解和解释,并且线性模型的特征总是单调的。

一些其他模型架构也具有线性方面。例如,当用于回归时,规则拟合模型是线性的;在所有情况下,TFLattice模型在格点之间使用线性插值,我们稍后会学习到。

有些模型可以自动包含特征交互,或对特征交互施加约束。理论上,你可以通过特征工程在所有模型中包含特征交互。符合我们领域知识的交互往往使模型更具可解释性。

以下是几种可解释模型架构的特点:

  • 线性模型:关系简单直观,特征贡献易于量化。
  • 规则拟合模型(用于回归时):本质上是线性的,易于解释。
  • TFLattice模型:在格点间使用线性插值,并允许注入领域知识。


准确性与可解释性的权衡 ⚖️

根据你试图建模的损失面的特征,更复杂的模型架构可以实现高精度。但这往往以牺牲可解释性为代价。

由于前面讨论的许多原因,可解释性可能是模型的严格要求。因此,你需要在可以解释的模型和能够生成所需精度的模型之间找到平衡。

再次强调,一些新创建的架构在提供更高精度的同时,也提供了良好的可解释性。TensorFlow Lattice 就是这类架构的一个例子。


线性回归:可解释性的典范 📈

可解释性的典范可能是我们的老朋友——线性回归。

线性回归非常容易理解特征贡献之间的关系,即使是多元线性回归也是如此。随着特征值的增加或减少,它们对模型结果的贡献也相应增加或减少。

这里展示的例子根据空气温度模拟了蟋蟀每分钟鸣叫的次数。这是一个非常简单的线性关系,因此线性回归可以很好地建模它。顺便说一句,这也意味着当你在夜晚外出时,如果你仔细听蟋蟀的叫声并数它们鸣叫的次数,你就可以测量空气的温度。

你可以查阅多贝尔定律以了解更多信息。

当然,一个特征对模型结果的实际贡献将取决于其权重。这对于线性模型尤其容易看出。

对于数值特征,特征值每增加或减少一个单位,预测值就会根据相应权重的值增加或减少。对于二元特征,预测值会根据特征值是1还是0,增加或减少权重值的大小。


如何衡量特征重要性?📊

我们如何确定给定特征对于进行预测的相关性?特征重要性告诉我们一个特征对于生成模型结果有多重要。特征越重要,我们就越想将其包含在特征向量中。

但不同模型的特征重要性计算方式不同,因为不同模型计算结果的方
式不同。

对于线性回归模型,特征的T统计量的绝对值是衡量该特征重要性的一个好指标。T统计量是特征的已学习或估计的权重,除以其标准误差。因此,特征的权重越大,其重要性就越高;但权重的方差越大(换句话说,我们对权重正确值的确定性越低),该特征的重要性就越低。

以下是计算特征重要性的关键点:

  • T统计量T = 权重 / 标准误差
  • 重要性重要性 ∝ |T|
  • 权重方差越大,我们对权重的确定性越低,特征重要性相对降低。


深入了解格点模型 🧊

你可能不熟悉格点模型,让我们来看看它们是如何工作的。

格点模型在特征空间上覆盖一个网格,并在网格的每个顶点设置它试图学习的函数值。当预测请求到来时,如果它们没有直接落在顶点上,则使用来自最近网格顶点的线性插值来计算结果。

这样做的好处之一是通过在特征空间上施加规则网格来正则化模型,并大大降低对训练数据覆盖范围之外的样本的敏感性。

然而,TensorFlow Lattice 模型超越了简单的格点模型。


TensorFlow Lattice:结合领域知识 🧠

TensorFlow Lattice 进一步允许你添加约束并将领域知识注入模型。这些图表显示了正则化和领域知识的好处。

比较左上角和右下角的图表,注意与其他类型的模型相比,该模型与真实情况有多么接近。

当你知道领域中某些特征是单调的或凸的,或者一个或多个特征存在交互时,你可以在模型学习过程中将这些知识注入模型。对于可解释性而言,这意味着特征值和结果很可能符合你对预期结果的领域知识。

你还可以表达特征之间的关系或交互,以表明一个特征反映了对另一个特征的信任度。例如,更多的评论数量让你对餐厅的平均星级评分更有信心。当你在网上购物时,你自己可能也考虑过这一点。

所有这些基于你的领域知识或你对所建模世界的认知的约束,都有助于模型产生有意义的结果,从而使它们更具可解释性。此外,由于模型在顶点之间使用线性插值,它在可解释性方面也具有线性模型的许多优点。

但是,除了基于领域知识添加约束的所有好处之外,TensorFlow Lattice 模型在复杂问题上的精度水平也与深度神经网络相似。当然,TensorFlow Lattice 模型也比神经网络更容易解释。


格点模型的局限性 ⚠️

然而,格点模型确实有一个弱点。维度是它们的“氪石”。

格点的参数数量随着输入特征的数量呈指数级增长,这对于具有大量特征的数据集会产生扩展性问题。作为一个粗略的经验法则,处理20个或更少的特征可能没问题,但这也取决于你指定的顶点数量。

不过,有另一种方法来应对这个维度“氪石”,那就是使用集成方法。但这超出了本次演示的范围。


总结 📝

在本节课中,我们一起学习了内生可解释模型的概念。我们探讨了单调性作为提升模型可解释性的关键特性,并深入了解了线性回归和格点模型等可解释架构的工作原理。特别是,我们看到了 TensorFlow Lattice 如何通过注入领域知识(如单调性约束)和利用线性插值,在保持高精度的同时提供出色的可解释性。最后,我们也了解了格点模型在处理高维数据时面临的挑战。理解这些模型有助于我们在需要模型透明度和可解释性的场景中做出更合适的选择。

122:模型无关解释方法 🔍

在本节课中,我们将学习模型无关的解释方法。当模型本身不具备内在可解释性时,这些方法可以帮助我们理解模型的预测结果。我们将探讨模型无关方法的核心概念、特点以及几种常见的实现方式。


模型无关方法的必要性

上一节我们介绍了模型内在可解释性的重要性。然而,由于各种原因,我们并非总能使用具备内在可解释性的模型。

你可能需要尝试解释那些本身不易解释的模型的预测结果。

幸运的是,存在多种不依赖于特定模型类型的方法。换句话说,它们是模型无关的。现在让我们来看看其中一些方法。


模型无关方法的核心特点

模型无关方法将解释与模型本身分离开来。这些方法可以在模型训练完成后应用于任何模型。

例如,它们可以应用于线性回归、决策树,甚至是像神经网络这样的黑盒模型。

一个理想的模型无关方法应具备以下特点:

以下是模型无关方法应具备的几个关键特性:

  • 模型灵活性:方法不应局限于特定类型的模型。
  • 解释灵活性:解释不应局限于某种特定形式。方法应能提供公式形式的解释,或者在某些情况下,提供图形化的解释(例如特征重要性图)。
  • 表示灵活性:所使用的特征表示应在被解释模型的上下文中具有意义。

让我们以一个使用词嵌入的文本分类器为例。在这种情况下,解释中使用单个词语的存在与否是有意义的。


常见的模型无关方法

目前有许多正在使用的模型无关方法,数量太多,无法在此一一详述。我将讨论其中几种,让你了解如何使用模型无关方法来解释模型生成的结果。

以下是几种常见的模型无关解释方法:

  • 部分依赖图:通过可视化某个特征在保持其他特征平均值不变的情况下,对模型预测输出的边际效应,来理解特征与预测之间的关系。
  • 个体条件期望图:展示对于单个数据实例,某个特征的变化如何影响模型的预测,有助于理解模型在局部区域的行为。
  • 置换特征重要性:通过随机打乱某个特征的值并观察模型性能下降的程度,来衡量该特征对模型预测的重要性。其核心思想是:如果一个特征很重要,打乱它会显著降低模型性能。
  • 全局代理模型:训练一个简单的、可解释的模型(如线性回归或决策树)来近似复杂黑盒模型的预测。通过解释这个代理模型来间接理解原模型。
  • 局部可解释模型:例如 LIME,通过在单个预测点附近构建一个简单的局部模型来解释该点的预测。其公式可简化为:explanation_model ≈ complex_modelx 点附近。
  • SHAP值:基于博弈论的 SHapley Additive exPlanations,为每个特征分配一个值,表示该特征对特定预测的贡献度。其核心是加性特征归因:prediction = base_value + sum(SHAP_values_for_all_features)

本节课中,我们一起学习了模型无关的解释方法。我们了解到,当模型本身是黑盒时,这些方法能够将解释与模型分离,提供模型灵活性、解释灵活性和表示灵活性。我们简要介绍了几种常见的方法,如部分依赖图、置换特征重要性、LIME和SHAP值,它们都能帮助我们以不同方式理解和解释复杂模型的预测行为。

123:部分依赖图 📊

在本节课中,我们将要学习一种广泛使用的模型可解释性方法——部分依赖图。我们将了解它的工作原理、如何解读,以及它的优缺点。


什么是部分依赖图?

上一节我们介绍了模型可解释性的重要性,本节中我们来看看一种具体的全局解释方法。

部分依赖图是一种帮助你理解特定特征对模型预测结果的影响,以及这些特征与训练数据中目标变量之间关系类型的方法。它通常专注于分析一个或两个特征对模型预测结果的边际影响。

这些关系可能是线性的、单调的,也可能是更复杂的类型。例如,对于一个线性回归模型,部分依赖图将始终显示线性单调关系。PDP是一种全局方法,因为它考虑了所有数据实例,并评估特征与结果之间的全局关系。


部分依赖图如何工作?

部分函数 F_S(x) 通过计算训练数据中的平均值来估计,这种方法也称为蒙特卡洛方法。

以下公式展示了部分函数的估计过程:

F_S(x) ≈ (1/n) * Σ_{i=1}^{n} f(x_S, x_C_i)

其中:

  • n 是训练数据集中的样本数量。
  • S 是我们感兴趣的特征集合。
  • C 是所有其他特征的集合。
  • x_C_i 是第 i 个样本中我们不感兴趣的特征的值。

部分函数告诉我们,对于特征集合 S 的给定值,其对预测结果的平均边际效应是多少。

PDP 有一个重要的假设:集合 C 中的特征与集合 S 中的特征不相关。如果这个假设被违反,计算出的平均值将包含非常不可能甚至不可能的数据点。


一个具体例子:自行车租赁预测

让我们看一个在自行车租赁数据集上训练的随机森林模型例子,该模型用于预测每天租赁的自行车数量,使用的特征包括温度、湿度和风速。

以下是温度、湿度和风速的部分依赖图:

请注意,当温度上升到大约 15 摄氏度(59 华氏度)时,租赁自行车的人可能会更多。这是合理的,因为人们喜欢在天气好的时候骑自行车,而这个温度正是开始变好的时候。但请注意,这个趋势在大约 25 摄氏度(77 华氏度)以上趋于平稳并开始下降。

你还可以看到湿度也是一个因素,当湿度高于约 60% 时,人们开始对骑自行车的兴趣降低。你觉得呢?这些图符合你的骑车偏好吗?


处理分类特征

对于分类特征,我们通过强制所有实例具有相同的类别值来计算其 PDP。

以下是自行车租赁数据集中分类特征“季节”的 PDP 图,它有四个可能的值:春、夏、秋、冬。

为了计算“夏季”的 PDP,我们强制数据集中的所有实例在“季节”特征上的值等于“夏季”。此图显示了不同季节的值。请注意,季节变化对自行车租赁的影响差异不大,除了春季的租赁数量略低。坦率地说,我没想到会是这样,但数据就是这样告诉我们的。


部分依赖图的优缺点

了解了 PDP 的应用后,我们来系统地总结一下它的优势与局限。

部分依赖图的主要优点如下:

  • 结果直观:结果往往很直观,尤其是在特征不相关的情况下。当特征不相关时,PDP 图显示的是改变一个特征时预测结果的平均变化。
  • 因果解释:对 PDP 的解释通常具有因果性,即如果我们改变一个特征并测量结果的变化,我们期望结果是一致的。
  • 易于实现:PDP 相对容易实现,本课末尾的参考资料部分列出了一些可用的软件包。

然而,像大多数方法一样,PDP 也有一些缺点:

  • 可视化限制:实际上,你一次只能处理两个特征,因为人类很难可视化超过三个维度,但这并不是 PDP 本身的错。
  • 独立性假设:更严重的限制是独立性假设。PDP 假设你正在分析的特征与其他特征不相关。正如我们在特征选择的讨论中学到的,无论如何,消除相关特征都是一个好主意。但如果你仍然有相关的特征,PDP 就无法正常工作。

例如,假设你想根据一个人的身高和体重来预测他的步行速度。PDP 会假设身高和体重不相关,这显然是一个错误的假设。结果,我们可能会将身高两米、体重 50 公斤的人纳入计算,这对于时装模特来说都有点不现实(尽管我搜索时惊讶地发现有些人确实很接近)。总之,你明白了:相关的特征会导致问题。


总结

本节课中,我们一起学习了部分依赖图这一重要的模型可解释性工具。我们了解了它的定义、工作原理、如何通过公式和代码理解其计算过程,并通过自行车租赁的实例看到了它的应用。我们还讨论了 PDP 直观、易于解释的优点,以及其受限于特征独立假设和可视化维度的缺点。掌握 PDP 能帮助你在理解复杂模型预测行为时,聚焦于单个或少数特征的影响。

124:排列特征重要性 📊

在本节课中,我们将学习一种名为“排列特征重要性”的技术,用于衡量模型中各个特征的重要性。我们将了解其工作原理、算法步骤、优势与局限性。


概述

排列特征重要性是一种通过打乱(排列)某个特征的值,并观察模型预测误差的变化,来衡量该特征重要性的方法。如果打乱某个特征的值导致模型误差显著增加,说明该特征对模型预测很重要;反之,则说明该特征不重要。

基本概念与算法

上一节我们概述了排列特征重要性的核心思想。本节中,我们来看看其具体的算法步骤。

以下是排列特征重要性的基本算法流程:

  1. 输入:训练好的模型、特征数据集、真实标签(目标值)以及一个误差评估指标。
  2. 计算基准误差:使用原始(未打乱的)特征数据,计算模型的初始预测误差。记此误差为 original_error
  3. 迭代评估每个特征:对数据集中的每一个特征,执行以下操作:
    • 打乱(排列)该特征在所有样本中的值,其他特征保持不变。
    • 使用打乱后的新数据集,让模型进行预测,并计算新的预测误差。记此误差为 permuted_error
  4. 计算特征重要性:对于每个特征,通过比较打乱前后的误差来计算其重要性。通常有两种方式:
    • 比率importance = permuted_error / original_error
    • 差值importance = permuted_error - original_error
  5. 排序与分析:根据计算出的重要性值对所有特征进行排序。重要性值越高(差值越大或比率越大),表明该特征越重要。

优势

了解了算法步骤后,我们来看看排列特征重要性有哪些优点。

排列特征重要性具有直观的解释性:特征重要性等于破坏该特征信息后模型误差的增加量。这为我们理解模型行为提供了一个高度概括的全局视角。

此外,由于在打乱某个特征时,也破坏了它与其他特征之间的交互效应,因此该方法能够反映出特征间的相互作用。这意味着它同时考虑了特征的主效应和交互效应对模型性能的影响。

😊 一个巨大的优势是,该方法不需要重新训练模型。其他一些方法(如删除特征法)需要删除特征后重新训练模型再比较误差,而重新训练模型可能非常耗时。无需重新训练是一个显著优点。

局限性

上一节我们探讨了该方法的优势,本节中我们来看看它存在哪些固有的局限性。

排列特征重要性也存在一些缺点。一个略显奇怪的问题是,不清楚应该使用训练数据还是测试数据来计算排列重要性,两者各有优缺点。

与部分依赖图(PDP)类似,高度相关的特征再次成为一个问题,可能会影响重要性评估的准确性。

同时,该方法需要能够访问原始的带标签训练数据集。如果你从他人那里获得模型,但对方未提供训练数据,则无法使用此方法。


总结

本节课中,我们一起学习了排列特征重要性。我们了解到,它是一种通过打乱特征值并观察模型误差变化来评估特征重要性的方法。其核心优势在于解释性强、能捕捉特征交互且无需重新训练模型。然而,它也面临数据选择(训练集/测试集)、特征相关性以及依赖原始训练数据等挑战。当发现不重要的特征时,应考虑将其从特征向量中移除,以简化模型。

125:47_Shapley值 🎯

在本节课中,我们将要学习一个衡量特征重要性的核心概念——Shapley值。我们将了解它的理论基础、如何应用于机器学习模型的解释,以及它的优缺点。


什么是Shapley值?🤔

Shapley值是合作博弈论中的一个概念。它以Lloyd Shapley的名字命名,他在1951年提出了这一概念,并于2012年因此获得了诺贝尔经济学奖。对于每一个合作博弈,Shapley值在所有参与者之间,对联盟产生的总剩余价值进行一种独特的分配。

上一节我们介绍了Shapley值的起源,本节中我们来看看它在博弈论中是如何运作的。

在博弈论中,可以想象一组参与者进行合作,并因其合作产生了总体收益。由于一些参与者可能比其他人贡献更多,或者拥有不同的议价能力,我们应该如何在参与者之间分配收益?换句话说,每个参与者对整体合作有多重要?他或她可以合理地期望得到多少回报?Shapley值为这个问题提供了一个可能的答案。


如何应用于机器学习?💡

那么,如何将这个思想应用到机器学习中呢?对于机器学习和可解释性而言,参与者就是数据集的特征。我们使用Shapley值来确定每个特征对结果贡献了多少。

正如你可能预期的,模型的预测就是“收益”。了解特征的贡献将帮助你理解在生成模型结果时,哪些是重要的因素。因为它不特定于任何特定类型的模型,所以无论模型架构如何,都可以使用Shapley值。

以上是对Shapley值背后思想的快速概述。现在让我们聚焦于一个具体的例子。


一个具体示例:公寓价格预测 🏢

假设你训练了一个机器学习模型来预测公寓价格。你需要解释为什么模型对某个公寓的预测价格是30万欧元。

你需要处理哪些数据呢?在这个例子中,该公寓面积为50平方米,位于二楼,附近有一个公园,并且禁止养猫。所有公寓的平均预测价格是31万欧元。

Shapley值源于博弈论。因此,让我们阐明如何将它们应用于机器学习的可解释性。

  • 博弈:针对数据集中单个实例的预测任务。具体来说,是这个实例的实际预测值与所有实例的平均预测值之间的差值。
  • 参与者:是该实例的特征值,它们“协作”产生了博弈的“收益”。

在公寓的例子中,特征值 park = nearbycat = bannedarea = 50floor = second 共同作用,得出了30万欧元的预测。

我们的目标是解释实际预测值(30万)与平均预测值(31万)之间的差值,即1万欧元的损失。

以下是特征贡献的一种可能解释:

  • 附近的公园贡献了 +3万欧元。
  • 50平方米的面积贡献了 +1万欧元。
  • 位于二楼贡献了 0欧元。
  • 禁止养猫贡献了 -5万欧元。

这些贡献值加起来正好是 -1万欧元,即最终预测减去平均预测公寓价格。你可以将其视为绝对值1万欧元,或者视为平均值的约3.3%。

这是一种可能的解释。但我们是如何得到这些数字的呢?


Shapley值的理论基础与优势 ⚖️

与解释模型结果的其他方法不同,Shapley值建立在坚实的理论基础之上。其他方法可能凭直觉说得通(这对可解释性很重要),但没有同样严谨的理论基础。这也是Shapley因其工作获得诺贝尔奖的原因之一。

该理论定义了必须满足的四个属性:效率对称性虚拟性可加性

Shapley值的一个关键优势在于,它在一个实例的特征值之间进行公平分配。有人认为,在法律要求可解释性的情况下(例如欧盟的“解释权”),Shapley可能是唯一能提供完整解释的方法。一些人认为,Shapley值可能是唯一符合法律要求的方法,因为它基于坚实的理论并公平地分配了影响。

Shapley值还允许对比解释。你不仅可以比较一个预测值与整个数据集的平均预测值,还可以将其与一个子集甚至单个数据点进行比较。这种对比能力是像LIME这样的局部模型所不具备的。


Shapley值的局限性 ⚠️

像任何方法一样,Shapley也有一些缺点。

以下是其主要局限性:

  1. 计算成本高:这可能是最重要的缺点。在现实世界的大多数情况下,这意味着通常只能计算一个近似解。
  2. 容易被误解:Shapley值不是从模型训练中移除某个特征后预测值的差值。它是一个特征值对实际预测与平均预测之间差值的贡献。
  3. 必须使用所有特征:如果你只想解释少数几个特征,Shapley可能不是合适的方法,因为它总是使用所有特征。人类更喜欢选择性的解释(例如LIME等方法产生的解释),因此对于非专业人士需要处理的解释,那些方法可能是更好的选择。另一个可能的解决方案是使用基于Shapley值的SHAP,它可以仅用少数特征提供解释(我们将在下一节讨论SHAP)。
  4. 不创建模型:与其他一些方法不同,Shapley不创建一个模型。这意味着你不能用它来测试输入的变化(例如,如果我换成100平方米的公寓,预测会如何变化?)。
  5. 特征相关性影响:与许多其他方法一样,当特征之间存在相关性时,它的效果不佳。但你已经知道,在进行特征选择时,应该从特征向量中移除相关的特征,所以这对你来说不是问题,对吧?无论如何,希望如此,但这是需要注意的一点。

总结 📝

本节课中我们一起学习了Shapley值。我们了解到它是一个源于合作博弈论、用于公平分配“收益”的概念。在机器学习中,它被用来衡量每个特征对单个预测结果的贡献,通过比较该预测与平均预测的差值来实现。Shapley值具有坚实的理论基础和公平分配的特性,使其在某些法律合规场景下具有优势。然而,它也存在计算成本高、必须使用所有特征、无法测试输入变化以及对特征相关性敏感等局限性。理解这些优缺点有助于我们在实际工作中选择合适的模型解释方法。

126:48_Shapley可加性解释 📊

在本节课中,我们将学习开源Shap库。这是一个用于处理Shapley值及其他类似指标的强大工具。我们将了解其理论基础、核心功能以及如何通过可视化结果来解释机器学习模型。


开源Shap库简介

上一节我们介绍了Shapley值的概念。本节中,我们来看看一个名为Shap的开源库,它是处理Shapley值及相关度量的强大工具。

Shap是Shapley Additive Explanations的缩写。它是一种基于博弈论的方法,用于解释任何机器学习模型的输出,因此具有模型无关性。它通过使用博弈论中的经典Shapley值及其相关扩展,将最优信用分配与局部解释联系起来。这些扩展是近期多篇论文的研究主题。需要记住,Shapley在1951年创立了其初始理论,而近期的研究者们一直在扩展他的工作。


Shap库的核心功能与解释器

Shap库为特定预测中的每个特征分配一个重要性值,并包含一些非常有用的扩展功能,其中许多都基于近期的理论研究。

以下是Shap库提供的主要解释器:

  • Tree Explainer:一种针对树集成模型的高速精确算法。
  • Deep Explainer:一种针对深度学习模型中Shap值的高速近似算法。
  • Gradient Explainer:该解释器将积分梯度、Shap和平滑梯度的思想结合到一个单一的期望值方程中。
  • Kernel Explainer:该解释器使用特殊加权的局部线性回归来估计任何模型的Shap值。

此外,该库还包含多种用于可视化结果的图表,这有助于你解释模型。


可视化解释:力图

我们可以将Shapley值可视化为一种“力”。每个特征值都是一股推动预测值增加或减少的力。

预测从一个基线开始,对于Shapley值而言,这个基线是所有预测的平均值。在力图中,每个Shapley值都显示为一个箭头,将预测推向增加(正值,图中显示为红色)或减少(负值,图中显示为蓝色)。这些力在预测点处交汇,以达到相互平衡。


可视化解释:摘要图与依赖图

摘要图将特征重要性与特征效应结合起来。摘要图上的每个点都是一个特征在一个实例上的Shapley值。颜色代表特征值的高低(从低/蓝色到高/红色)。在Y轴方向上,重叠的点会进行轻微抖动,这样我们就能感受到每个特征的Shap值分布情况。特征按照其重要性进行排序。因此,在这个例子中,我们可以快速看出两个最重要的特征是“day”和“hour”。

在Shap依赖图中,特征值绘制在X轴上,Shap值绘制在Y轴上。从本例的图中,你可以看到“hour”特征与“loke 15 temperature”特征之间的相关性较低。具体来说,在这个例子中,凌晨时分(午夜刚过),能源价格会下降。在下午10点到12点之间,价格会上涨,然后在3点之后回落。接着,晚上8点之后,价格会再次上涨。


课程总结

本节课中,我们一起学习了开源Shap库。我们了解到Shap是一个基于博弈论Shapley值的模型无关解释工具。它提供了多种高效的解释器(如Tree、Deep、Gradient、Kernel Explainer)来处理不同类型的模型,并提供了力图、摘要图和依赖图等强大的可视化手段,帮助我们直观理解各个特征如何影响模型的单个预测及整体行为。

127:测试概念激活向量 🧠

在本节课中,我们将学习一种名为“测试概念激活向量”的高级方法,它用于解释深度学习模型的内部状态。

深度学习模型的解释因其规模、复杂性以及通常不透明的内部状态而充满挑战。此外,许多系统(如图像分类器)处理的是低级特征,而非高级概念。

为了应对这些挑战,谷歌团队引入了概念激活向量。它能够以人类友好的概念来解释神经网络的内部状态。这些高级概念是通过为待检查模型定义一组示例输入数据来确定的。

例如,对于一个图像模型,要定义“卷曲”这个概念,可以使用一组发型和纹理图像。请注意,这些示例并不局限于训练数据,它们可以由用户提供的新数据来定义。事实证明,示例是与专家和非专家用户进行模型交互的有效手段。

概念激活向量的应用 📊

上一节我们介绍了概念激活向量的基本思想,本节中我们来看看它的具体应用。

你可以使用概念激活向量来根据其与某个概念的关系对示例(在本例中是图像)进行排序。这对于定性地确认概念激活向量是否正确反映了感兴趣的概念非常有用。

由于概念激活向量代表了瓶颈层向量空间中某个概念的方向,我们可以计算一组感兴趣图片与概念激活向量之间的余弦相似度,从而对图片进行排序。请注意,被排序的图片并未用于训练此处展示的概念激活向量。这里展示了两个感兴趣的概念:“CEO”和“模特女性”,以及根据与概念的相似度排序后的图像。

以下是两个具体的排序示例:

  • CEO概念:左侧是根据从ImageNet收集的更抽象“CEO”概念学习到的概念激活向量,对条纹图像进行的排序。前三张图像与“CEO”概念最相似,看起来像是细条纹,这可能与CEO可能佩戴的领带或西装有关。这证实了CEO更可能穿细条纹而非横条纹的想法。
  • 模特女性概念:右侧是根据“模特女性”概念激活向量对领带图像进行的排序。同样,前三张图像与“模特女性”概念最相似,展示了女性佩戴的领带。而底部三张图像都展示了男性佩戴的领带。这也表明,概念激活向量可以作为一种独立的相似度排序工具,用于对图像进行排序,以揭示学习概念激活向量所用示例图像中可能存在的任何偏见。

总结 📝

本节课中,我们一起学习了概念激活向量这一高级解释方法。我们了解到,CAV通过定义人类友好的高级概念(如“卷曲”、“CEO”),并利用示例数据在模型内部向量空间中定位这些概念的方向,从而实现对模型内部状态的解释。我们还看到了如何利用CAV对图像进行排序,以验证概念的有效性,并揭示数据中可能存在的模式或偏见。这种方法为理解和调试复杂的深度学习模型提供了一个有力的工具。

128:LIME 局部可解释模型 📊

在本节课中,我们将学习一个名为 LIME 的流行框架,它用于生成模型预测的局部解释。我们将了解其核心思想、工作原理以及如何通过一个简单的可解释模型来近似理解复杂“黑盒”模型的决策过程。


概述

LIME 是一个广为人知的框架,用于创建模型结果的局部解释。其核心思想非常直观:我们暂时忽略原始训练数据,只关注一个可以输入数据点并获得预测的“黑盒”模型。通过探查这个黑盒,并观察输入数据变化时预测如何改变,LIME 能够构建一个局部可解释的模型,帮助我们理解特定预测背后的原因。


LIME 的核心思想

上一节我们概述了 LIME 的目标,本节中我们来看看其具体的工作流程。整个过程始于一个我们只能进行输入和获得预测的“黑盒”模型。

你的目标是理解模型为何做出某个特定预测。LIME 通过向模型提供原始数据的各种变体,并观察预测结果的变化来实现这一目标。


LIME 的工作流程

以下是 LIME 生成解释的具体步骤:

  1. 生成扰动数据:LIME 在待解释的数据点周围生成一系列经过扰动的样本。
  2. 获取黑盒预测:将这些扰动后的样本输入原始的黑盒模型,获取对应的预测结果。
  3. 训练可解释模型:利用这个由(扰动样本,模型预测)构成的新数据集,LIME 训练一个简单的、可解释的模型(例如线性模型或决策树)。这个新模型的训练样本会根据其与原始待解释数据点的距离进行加权,距离越近,权重越高。
  4. 解释预测:最后,通过解释这个新训练的、在局部有效的简单模型,来理解原始黑盒模型在特定数据点上的预测。

这个新模型只需要在待解释的数据点附近对原始模型的预测有较好的近似精度,这种特性被称为 局部保真度。它不需要在整个数据空间上都表现良好。


总结

本节课中,我们一起学习了 LIME 框架。我们了解到,LIME 通过探查黑盒模型在扰动数据上的表现,构建一个加权的、简单的可解释模型(如线性模型),从而为复杂的模型预测提供局部解释。其核心在于追求局部保真度,而非全局准确性,这使其成为理解单个预测原因的强大工具。

129:AI 模型解释工具与服务 🧠

在本节课中,我们将学习如何利用基于云的工具和服务来解释模型的结果。这些服务能帮助我们理解模型的预测依据,验证模型行为,并识别潜在的偏差。

上一节我们讨论了模型可解释性的基本概念,本节中我们来看看具体的云服务工具。

基于云的解释服务

除了本地工具,基于云的工具和服务对于解释模型结果也极具价值。现在,让我们看看其中一项服务:Google 的 AI 解释服务。

另一种实现可解释性的方案是利用云服务商提供的托管服务,例如 Google AI Platform 的 AI Explanations。AI Explanations 将特征归因功能集成到了 Google AI Platform 的预测服务中。

AI Explanations 工作原理

当你通过 AI Platform 请求预测时,AI Explanations 能帮助你理解模型针对分类和回归任务的输出。它会告诉你数据中的每个特征对预测结果贡献了多少。

你可以利用这些信息来验证模型行为是否符合预期,识别模型中的任何偏差,并获得改进模型及训练数据的思路。

以下是 AI Explanations 的核心工作流程:

  • 特征归因:指示每个特征对给定预测的贡献程度。
  • 集成服务:AI Explanations 与 Google AI Platform Prediction 托管服务协同工作。
  • 输出差异:通常使用 AI Platform Predictions 请求预测时,你只会得到预测结果。然而,当你请求解释时,你将同时获得预测结果和这些预测对应的特征归因信息。

可视化辅助理解

系统还提供了可视化工具来帮助你理解特征归因。

对于表格数据集,特征归因的示例如下所示:

# 特征归因结果示例(伪代码)
特征贡献度 = {
    “年龄”: +0.32,
    “收入”: -0.15,
    “历史信用”: +0.48
}

对于图像数据,可视化示例如下。它们为每张图像提供覆盖层,高亮显示对最终预测贡献最大的像素区域。

特征归因方法

AI Explanations 目前提供三种特征归因方法,包括:

  • Sampled Shapley
  • Integrated Gradients
  • XRAI

归根结底,所有这些方法都基于 Shapley 值。我们已经充分讨论过 Shapley 值,此处不再赘述。让我们看看另外两种方法:Integrated Gradients 和 XRAI。

Integrated Gradients(积分梯度)

Integrated Gradients 是一种生成特征归因的不同方法,它具有与 Shapley 值相同的公理特性。该方法基于梯度,当应用于深度网络时,其效率比原始的 Shapley 三次方法高出数个数量级。

在积分梯度方法中,预测输出相对于输入特征的梯度是沿着一条积分路径计算的。梯度根据你可指定的缩放参数在不同间隔点进行计算。对于图像数据,可以将缩放参数想象成一个滑块,它将图像的所有像素逐渐调暗至黑色。

“梯度被积分”意味着它们首先被平均在一起,然后计算平均梯度与原始输入的逐元素乘积。

XRAI(基于区域积分排序的解释)

XRAI 方法专门针对图像分类任务。它在积分梯度方法的基础上增加了额外步骤,以确定图像的哪些区域对给定预测的贡献最大。

以下是 XRAI 的工作步骤:

  1. 像素级归因:使用积分梯度方法对输入图像进行像素级归因计算。
  2. 图像过分割:将图像过度分割,创建由小区域组成的拼图。
  3. 区域归因聚合:汇总每个分割区域内的像素级归因,以确定该区域的归因密度。
  4. 区域排序:对每个区域进行排序,按从最正向到最负向的顺序排列。这决定了图像的哪些区域最显著,或对给定预测的贡献最强。

工作流程示例

这里有一个蜂鸟图像的示例。从左侧开始:

  1. 原始图像被分割成不同区域,同时使用积分梯度计算像素级归因。
  2. 每个区域内的归因被加总。
  3. 区域被排序以确定最重要的结果。

如右侧图像所示,这张图中最重要的部分是蜂鸟本身。


本周内容总结 🎯

本节课中我们一起学习了模型可解释性与可说明性,并从几个不同的角度进行了探讨。我们看了一些本质上可解释的模型,了解了局部解释与全局解释的概念,并研究了几种不同的事后解释方法,包括对可解释性非常重要的 Shapley 值,以及帮助我们应用它们的 Shap 库。

我们还了解了一些较新的方法,包括 TCAV 和格子模型。希望你觉得这是收获丰富的一课,我们下次再见。

130:1_模型服务简介 🚀

在本节课中,我们将学习模型服务的基本概念,包括其定义、关键组件、不同类型以及在生产环境中部署模型时需要考虑的性能指标与权衡。


大家好,欢迎来到本课程。我们将讨论模型服务的模式与基础设施。我们还将探讨管理与交付,以及监控。

本周,我将介绍模型服务。在动手实践之前,你将探索部署模型的方法。别担心,你不需要拥有自己的服务基础设施,所有练习都可以使用Colab完成。让我们开始吧。

首先,我们将讨论模型性能与资源需求,从批量推理开始讨论。

那么,服务一个模型究竟是什么意思呢?这是一个很好的问题。训练一个好的机器学习模型只是第一步,你需要让最终用户能够使用模型。你可以通过在服务器上提供模型访问权限来实现,这将在本周探讨。服务还包括将模型文件部署到应用程序的功能,这通常在移动端机器学习场景中出现。

在生产环境中服务机器学习模型时,应考虑三个关键组件:模型本身用于执行的解释器以及输入数据。这些组件被推理过程使用,其目的是让数据被模型接收以计算预测。

从高层次看机器学习工作流,可以归结为类似这样的过程:你需要考虑模型训练和预测,同时理解你想用模型进行的推理或预测类型。

模型训练通过离线学习(也称为批量或静态学习)进行,模型在一组已收集的数据上进行训练。部署到生产环境后,机器学习模型保持不变,直到重新训练。因为模型会看到大量真实数据,所以很快就会变得过时。这种现象称为模型衰减,需要仔细监控。

还有在线学习(有时称为动态学习),模型会随着新数据的到达(例如数据流)定期重新训练。这通常是使用时间序列数据(如传感器、股票等)的机器学习系统的情况,其目的是在机器学习模型中适应时间效应。

然后,在使用模型进行预测时,也有两种主要类型。对于批量预测,部署的机器学习模型基于历史输入数据进行一组预测。这对于不依赖时间的数据,或者不需要实时获取预测输出的情况通常就足够了。

或者,对于实时预测(也称为按需预测),这些预测是使用请求时可用的输入数据实时生成的。

当我们讨论优化在线推理时,大多数相关材料首先会概述需要优化的重要指标,即延迟吞吐量成本。延迟是用户操作与应用程序响应用户操作之间的延迟。在机器学习推理的情况下,它是在线推理的整个过程,从发送数据到服务器、使用模型执行推理,然后返回响应。大多数应用程序是面向用户的,因此最小化延迟是维持客户满意度的关键要求。例如,你的用户可能会抱怨,一个推荐酒店的应用程序在根据用户输入刷新搜索结果时速度太慢。

吞吐量是单位时间内成功服务的请求数量。一个例子是,如果你希望你的模型处理大量数据,例如来自安全摄像头的高保真视频,以确保快速发现任何安全事件。

我们应该始终记住并考虑与每次推理相关的成本。你的服务基础设施总是有相关成本,因此你应该考虑诸如CPU、GPU等硬件加速器以及用于存储输入特征以便以最小延迟轻松检索的缓存等成本。

许多面向客户的应用程序的目标是在最大化吞吐量的同时最小化延迟。一个例子是航空推荐网站,它根据你的输入为你推荐可用的最佳航班。更智能的系统可能运行机器学习模型来预测用户的最佳选择。在某些时间点,例如节假日,此应用程序可能面临非常高的用户负载,因此你肩负着提供低延迟(快速给用户结果)和高吞吐量(拥有能够处理高负载的模型服务基础设施)的负担。

我们可以扩展使用的基础设施以满足这些响应时间和吞吐量阈值,但这可能会成比例地增加成本。因此,随着基础设施扩展以处理延迟和吞吐量,在生产中运行机器学习模型的成本可能会急剧增加。这导致你在成本和客户满意度之间进行平衡游戏。

没有完美的答案,总是存在权衡。但幸运的是,你可以使用一些策略来尝试在控制成本的同时,最小化对客户的影响。这些策略可能包括通过共享GPU等资产来降低成本、使用多个模型来提高吞吐量,甚至探索优化你的模型。


上一节我们介绍了模型服务的基本概念和关键权衡。本节中,我们来看看一些能帮助你做出这些决策的策略。

现在你已经了解了在服务器上托管模型以及理解你可能需要做出的决策所需的基本概念,接下来我们将看看一些有助于你做出这些决策的策略,包括甚至可能不使用服务器,并探索将模型直接部署到用户的移动或边缘设备上。

131:模型服务基础设施简介 🏗️

在本节课中,我们将要学习模型部署到生产环境时,如何权衡资源成本与性能约束,并了解构建高效模型服务基础设施的关键考量。


上一节课我们了解到,将模型部署到生产环境时,需要做出一些决策,以在最小化延迟和成本的同时最大化吞吐量。

现在,我们来看看资源成本相关的一些问题以及可能遇到的约束。

模型复杂性与资源成本的权衡 ⚖️

模型变得复杂通常有充分理由。为了提高准确性或建模更复杂的关系,很自然地会倾向于采用更复杂的模型架构,并纳入越来越多的特征。这通常会导致更长的预测延迟,但有望提升预测准确性。

然而,随着模型变得更复杂、特征越来越多,训练和服务基础设施的每个部分对资源的需求都会增加。

资源需求的增加意味着成本上升、硬件要求提高、更大的模型注册表管理,从而导致更高的支持和维护负担。

如同生活中的许多事情一样,关键在于找到正确的平衡点。在成本与复杂性之间找到恰当的平衡,是经验丰富的从业者会随着时间积累的技能。

因此,模型的预测效果与其预测延迟速度之间存在权衡,具体取决于你的用例,你需要决定两个指标。

以下是这两个关键指标:

  • 模型的优化指标:这反映了模型的预测效果,包括准确率精确率召回率等。这些指标的良好值是模型质量的强有力信号。
  • 模型的约束指标:这反映了模型必须满足的操作约束,例如预测延迟

例如,你可以将延迟阈值设定为一个特定值,比如200毫秒,任何不满足此阈值的模型都不会被接受。

约束指标的另一个例子是模型的大小,如果你计划将模型部署到移动设备和嵌入式设备等低功耗硬件上,这一点当然非常重要。

你可以采取的一种方法是,先指定服务基础设施(CPU、GPU等),然后开始增加模型复杂性以提高模型的预测能力,直到在该基础设施上触及一个或多个约束指标。然后,你可以评估结果,要么接受当前模型,要么努力改进准确性、降低复杂性,或者决定提高服务基础设施的规格。

基础设施设计:加速器与数据存储 🚀

在设计服务和训练基础设施时,需要考虑的一个因素是使用GPU和TPU等加速器。它们各有不同的优势,但也都有成本和潜在的限制。

GPU倾向于针对并行吞吐量进行优化,常用于训练基础设施。而GPU除了在训练中有用外,对于大型复杂模型和大批量大小(尤其是在推理期间)也有优势。这些决策会对项目预算产生重大影响。

因此,在应用大量性能较低的加速器与使用少量性能更强的加速器之间也存在权衡。通常在团队或部门中工作时,这些选择需要针对广泛的模型范围做出,而不仅仅是你当前正在处理的新模型,因为资源总是共享的。

特征检索与缓存策略 💾

对你的机器学习模型的预测请求可能不会提供预测所需的所有特征。有些特征可能需要预先计算或聚合,然后从数据存储中实时读取。

以需要预测订单预计送达时间的食品配送应用为例。虽然这基于许多特征,如当前交通状况,但也有一些可以从数据存储中读取,例如传入订单列表、过去一小时每分钟的未完成订单数量等。

你需要强大的缓存来以低延迟检索这些数据,因为送达时间必须实时更新。你不能等待数秒从数据库检索数据。当然,这也有成本影响。

NoSQL数据库是实现缓存和特征查找的良好解决方案,有多种可用选项。

以下是几种常见的数据存储选择及其适用场景:

  • 需要亚毫秒级读取延迟,处理少量快速变化的数据,由数千个客户端检索:一个不错的选择是Google Cloud Memorystore。它是Redis和Memcached的完全托管版本。当然,也有非常好的开源选项。
  • 需要毫秒级读取延迟,处理缓慢变化的数据,且存储可自动扩展:一个不错的选择是Google Cloud Firestore
  • 需要毫秒级读取延迟,处理动态变化的数据,使用可随大量读写线性扩展的存储:一个不错的选择当然是Google Cloud Bigtable
  • Amazon的DynamoDB也是一个不错的选择,它是一个具有内存缓存的可扩展低读取延迟数据库。

添加缓存可以加速特征查找,同时减少预测检索延迟。你必须根据需求从不同的可用产品中仔细选择,然后与预算限制进行平衡。


本节课中,我们一起学习了模型服务基础设施的核心考量。我们探讨了模型复杂性与资源成本(如延迟、硬件)之间的权衡,介绍了优化指标与约束指标的概念。我们还了解了在设计基础设施时,如何根据数据访问模式(延迟、变化频率、规模)选择合适的加速器(如GPU)和数据存储/缓存解决方案(如Memorystore、Firestore、Bigtable)。关键在于根据具体需求和预算,在这些因素之间找到最佳平衡点。

132:3_部署选项 🚀

在本节课中,我们将探讨机器学习模型部署的核心问题:在哪里部署模型。我们将分析两种主要的部署方式,并讨论在不同环境(如数据中心与移动设备)中部署时需要考虑的关键约束与权衡。


模型部署的两个主要选择

回到“我应该在哪里部署模型”这个问题,主要有两种选择。

第一种选择是拥有一个位于数据中心的集中式模型,通过远程调用来访问它。

第二种选择是将模型的实例分发给用户,以便他们在本地使用,例如在移动设备或嵌入式系统中。


数据中心部署的考量

在我们的数据中心中,无论规模大小,成本和效率都至关重要。即使是在拥有庞大资源的大型数据中心也是如此。

例如,像谷歌这样的大公司不断寻找方法来提高资源利用率并降低应用程序和数据中心的成本,它们使用的许多技术和策略与本课程讨论的内容相同。


移动设备部署的约束

接下来,让我们看看在移动设备上运行模型的情况,并了解这些设备可能带来的硬件限制。

在移动电话中,即使设备有GPU,其平均GPU内存大小也远小于数据中心中的GPU,通常小于约4 GB

你通常只有一个GPU,并且它由多个应用程序共享,而不仅仅是你的应用。

在大多数情况下,你可以使用GPU进行加速处理,但这需要付出代价:可用的GPU资源有限,使用它可能导致电池电量快速耗尽。

如果你的机器学习模型操作复杂,导致电池快速耗尽或手机过热,你的应用将不会受到欢迎,并可能获得差评。

此外,还有存储限制,因为用户不喜欢占用手机存储空间的大型应用。

如果模型太大,你很少能将一个非常庞大、复杂的模型部署到像手机这样的设备上。由于内存限制,用户甚至可能选择不安装它。

因此,由于存在内存、处理能力、电池使用等方面的这些约束,有许多类别的模型我们根本无法部署到移动电话或嵌入式系统中。


服务器部署与API暴露

因此,我们可能会选择将模型部署到服务器,然后通过REST API将其暴露出来,以便在我们的应用程序中用于推理。

但这当然也可能不合适。在预测延迟至关重要或网络连接可能不总是可用的环境中,将模型部署到服务器可能不可行。

一个例子是部署到自动驾驶汽车中的物体检测模型。在这些应用中,系统能够基于近乎实时的预测采取行动,而无需等待服务器往返,这一点至关重要。


延迟、准确性与模型权衡

作为一般规则,你应该始终尽可能选择最小化推理延迟。这通过减少应用程序的响应时间来增强用户体验。

但也有例外。在模型准确性至关重要的场景中,延迟可能不那么重要,例如疾病诊断

因此,你需要在模型复杂性、大小、准确性和预测延迟之间进行权衡,并为你正在开发的应用理解各自的成本和约束。这不是一项容易的任务。

所有这些因素都会影响你为任务选择最佳模型,这取决于你的限制和约束。


移动设备专用模型示例

一个例子是MobileNets,这些是专门为移动设备上的计算机视觉设计的模型。

它们可能没有最多的预测类别,也可能不是最先进的识别模型,但为获得最佳移动模型而进行的所有权衡工作已经为你完成,你可以在此基础上进行构建。

因此,如果你要部署到移动设备,还应遵循一些策略来优化你的模型,以适应受限的移动环境。


本节总结

在本节课中,我们一起学习了机器学习模型部署的两种主要路径:集中式服务器部署分布式边缘部署。我们深入探讨了数据中心部署对效率与成本的关注,以及移动设备部署面临的内存、算力、电池和存储等多重硬性约束。同时,我们理解了在延迟、准确性、模型复杂度与大小之间进行权衡的必要性,并了解了像MobileNets这样的专用模型如何帮助我们在受限环境中找到平衡点。选择正确的部署策略,需要紧密结合应用场景的具体需求与约束条件。

133:改善预测延迟与降低资源成本 🚀

在本节课中,我们将学习如何对候选模型进行性能剖析与基准测试,并探讨多种模型部署方案,包括移动端、服务器端以及云服务,旨在优化预测延迟并有效控制资源成本。

模型性能剖析与优化 🔍

上一节我们讨论了模型选择,一旦你为任务选定了候选模型,对其进行性能剖析和基准测试是良好的实践。

TensorFlow Lite 基准测试工具内置了性能剖析器,可以展示每个算子的性能统计信息。这有助于理解性能瓶颈,并识别出哪些算子占用了主要的计算时间。

如果某个特定算子频繁出现在模型中,并且通过剖析发现它消耗了大量时间和资源,你可以着手优化它或考虑使用不同的算子。

我们之前讨论了很多关于模型优化的内容,其目标是创建更小、通常更快且更节能的模型。这对于在移动设备上的部署尤为重要。

TensorFlow Lite 支持多种优化技术,例如量化。量化是一种通过降低模型权重和激活值的数值精度(例如,从32位浮点数到8位整数)来减小模型大小并提升推理速度的技术。

# 示例:TensorFlow Lite 量化转换(概念性代码)
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT] # 启用默认优化(通常包括量化)
tflite_quant_model = converter.convert()

你也可以通过增加解释器线程数来加速算子的执行。然而,增加线程数也会使模型使用更多资源和功耗。

对于某些应用,延迟可能比能效更重要。但多线程执行也会导致性能波动性增加,这取决于同时运行的其他任务,在移动应用中尤其如此。

例如,一些隔离测试可能显示多线程版本比单线程版本快2倍,但如果另一个应用同时运行,其性能实际上可能比单线程版本更差。因此,你需要进行实际测试验证。

服务器端模型部署设计 🖥️

如果你选择另一条路径,将模型部署到服务器,在设计时也需要考虑一些因素。

你的模型用户需要一种发出请求的方式,这通常通过Web应用程序实现。在这种方法中,模型被包装成一个API服务。大多数服务基础设施和编程语言都有Web框架可以帮助你实现这一点。

以下是几种常见的Web框架选项:

  • Flask:一个非常流行的Python Web框架,可以非常轻松地推出API。
  • Django:同样是一个功能强大的Python Web框架。
  • Java:也有许多选择,如Apache Tomcat、Spring等。

如果你熟悉Flask,也许可以在10分钟内创建一个新的Web客户端端点。

使用模型服务器进行部署 ⚙️

模型服务器可以管理模型部署,例如创建服务器并管理它以服务来自客户端的预测请求。它们消除了将模型放入定制Web应用的需要,通常只需几行代码即可部署模型。

模型服务器还使得更新或回滚模型、按需或在需要资源时加载和卸载模型、以及管理模型的多个版本变得容易。

以下是两个流行的开源模型服务器:

1. Clipper

  • 由UC Berkeley RISELab开发。
  • 帮助你部署在Caffe、TensorFlow、Scikit-learn等框架中构建的各种模型,其总体目标是模型无关
  • 包含标准的REST接口,便于与生产应用程序集成。
  • 支持将模型包装在Docker容器中,以便进行集群和资源管理。
  • 帮助你为可靠的延迟设置服务级别目标。

2. TensorFlow Serving

  • 一个开源模型服务器,为生产环境设计的机器学习模型提供灵活的高性能服务系统。
  • 使得在保持相同服务器架构和API的同时,轻松部署新算法和实验。
  • 提供与TensorFlow模型的开箱即用集成,但也可以扩展以服务其他类型的模型和数据。
  • 同时提供REST和gRPC协议,gRPC通常比REST更高效
  • 已证明每个核心每秒可处理高达100,000个请求,是服务机器学习应用的强大工具。
  • 具有版本管理器,可以轻松加载和回滚同一模型的不同版本,并允许客户端为每个请求选择要使用的版本。

使用托管云服务 ☁️

使用托管服务来部署模型也有其优势。让我们以Google Cloud AI Platform Prediction Service为例来看一下。

  • 它允许你设置提供低延迟预测的实时端点,也可以用于对批量数据进行预测。
  • 允许你部署在Google Cloud上或本地训练的模型。
  • 可以根据流量自动扩展,这可以在提供高度可扩展性的同时节省大量成本。
  • 当然,也提供加速器,包括GPU和TPU。

其他云平台,如Microsoft Azure和Amazon AWS,也提供类似的功能。

总结与预告 📚

本节课中,我们一起学习了如何剖析模型性能以识别瓶颈,并探索了从移动端优化到服务器端部署的多种方案。我们介绍了通过量化等技术优化模型,使用Flask等框架或Clipper、TensorFlow Serving等专用服务器进行部署,以及利用Google Cloud AI Platform等托管服务来平衡延迟、成本与可扩展性。

接下来,你将进行实际操作,探索如何部署到AI预测平台。之后,我们将学习如何安装TensorFlow Serving并使用它进行计算机视觉预测。

134:将模型部署到AI预测平台 🚀

在本节课中,我们将学习如何在Google Cloud AI Platform上构建并部署一个XGBoost模型。整个过程包括访问控制台、启用必要服务、在Notebook中训练模型,最终将模型部署为可提供预测的在线服务。


访问AI平台控制台

首先,您需要登录Google Cloud Platform控制台。向下滚动页面,直到找到“AI平台”的入口。

点击进入后,选择“仪表板”,您将被导航至AI Platform的主仪表板界面。

启用必要API与服务

在左侧列表中选择“模型”。您可能会看到需要启用相关API才能创建模型的提示,请点击启用并等待进度完成。

启用完成后,在左侧导航菜单中找到“Compute Engine”条目。

如果Compute Engine尚未启用,请务必点击相应按钮启用它。此过程可能需要一些时间。



创建Notebook实例

服务启用后,返回导航菜单中的“AI平台”条目,找到“Notebooks”。

页面打开后,您会看到一个Notebook列表(初始可能为空)。点击顶部的“新实例”按钮。

选择“Python 3”环境。

接受默认设置并点击“创建”。列表中会出现一个新条目,需要等待片刻使其准备就绪。

当实例状态变为就绪后,您会看到一个“打开JupyterLab”的链接。点击它,Jupyter环境将打开并提供多个选项。

安装依赖与准备环境

在JupyterLab中,选择“终端”选项。

在终端中,使用以下命令安装XGBoost库:

pip3 install xgboost

安装完成后,您可以新建一个Python 3笔记本。接下来的代码实验会提供所有必要代码,因此如果您现在看不到代码也无需担心。

构建与训练XGBoost模型

在笔记本中,您可以逐单元格运行代码。

前几个单元格用于查看和分析数据。随着代码运行,您将看到如何为此数据创建一个XGBoost回归器,该模型将预测婴儿体重并与实际体重进行比较。

核心训练步骤的伪代码如下:

import xgboost as xgb
# 创建回归器
model = xgb.XGBRegressor()
# 训练模型
model.fit(X_train, y_train)

保存模型

模型训练完成后,您可以将其保存为TensorFlow SavedModel格式,以便后续部署。

# 示例:使用TF兼容的方式保存模型
model.save_model('saved_model.pb')

部署模型到GCP

现在可以将模型部署到Google Cloud Platform。请注意,您需要一个GCP项目。项目ID可以通过点击控制台顶部的项目选择器,从您拥有的项目列表中找到。

模型存储桶是一个云存储桶,您可以用变量model_bucket为其命名。创建存储桶后,您可以将保存的模型复制到其中。

您可以在云存储中浏览以找到该存储桶,并在其中看到保存的模型文件。

创建AI平台模型与版本

运行以下命令将在AI Platform上创建模型:

gcloud ai-platform models create [MODEL_NAME]

接着,部署一个模型版本:

gcloud ai-platform versions create [VERSION_NAME] --model=[MODEL_NAME] --origin=gs://[BUCKET_NAME]/saved_model

完成后,刷新您的模型列表,您应该能看到名为“baby_model”的模型。该模型下会有一个名为“v1”的版本。

测试模型预测

现在,我们可以将一些模拟数据写入文件,并使用已部署的端点来获取预测结果。

预测调用的示例代码如下:

from googleapiclient import discovery
# 创建预测服务
service = discovery.build('ml', 'v1')
# 构建请求并获取预测
response = service.projects().predict(name=name, body={'instances': instances}).execute()

总结

本节课中,我们一起学习了将XGBoost模型部署到Google Cloud AI Platform的完整流程。我们从访问控制台和启用服务开始,接着在Notebook环境中安装依赖、训练并保存模型,最后将模型部署为云端的在线预测服务并进行了测试。

现在轮到您了,请尝试完成代码实验,看是否能复现上述所有步骤。

135:安装与使用 TensorFlow Serving 🚀

在本节课中,我们将学习如何在自己的基础设施上部署机器学习模型。我们将重点介绍开源解决方案 TensorFlow Serving,并完成从训练一个简单模型到部署并远程调用它的完整流程。我们将使用基于 Linux 的 Google Colab 环境,这些步骤同样适用于你自己的服务器。


概述:TensorFlow Serving 的安装方式

上一节我们介绍了云端部署,本节中我们来看看如何在自己的基础设施上进行部署。TensorFlow Serving 提供了多种安装方式,具体取决于你的需求和环境。

以下是几种主要的安装方法:

  • Docker 镜像:这是最简单直接的方式。除非你有容器化无法满足的特定需求,否则强烈推荐此方法。这也是让 TensorFlow Serving 支持 GPU 的最简单途径。
  • 预编译二进制文件:你可以使用两种可用的二进制文件之一。
    • TensorFlow Model Server:这是一个完全优化的服务器,使用了平台特定的编译器优化(如 SSE4 和 AVX 指令集)。对大多数用户来说,这是首选选项,但它可能无法在一些较旧的机器上运行。
    • TensorFlow Model Server Universal:此版本使用基本优化编译,不包含平台特定的指令集,因此应该能在几乎所有机器上运行。如果 TensorFlow Model Server 无法工作,你可以使用此版本。
  • 从源码构建:如果你想根据需求完全自定义 TensorFlow Serving,可以参考官方文档从源码进行构建。

在基于 Debian 的 Linux 系统上,你可以使用 apt-get 命令通过 aptitude 进行安装。由于本示例使用的 Colab 环境运行在基于 Debian 的虚拟机上,我们将采用这种方法。


准备安装环境

现在,让我们开始准备使用 aptitude 安装 TensorFlow Serving。首先,需要将 TensorFlow Model Server 软件包添加到 aptitude 的软件包源列表中。

请注意,在 Colab 环境中,你将需要以 root 权限运行命令。安装 TensorFlow Serving 只需一行命令:

apt-get install tensorflow-model-server

训练一个简单的模型

接下来,我们将使用 MNIST 数据集训练一个简单的计算机视觉模型,然后使用 TensorFlow Serving 来部署它进行推理。

MNIST 数据集包含 70,000 张 0 到 9 的手写数字灰度图像。这些图像以低分辨率(28x28 像素)显示单个数字。

尽管这些是图像,但我们将把它们作为 NumPy 数组加载,而不是二进制图像对象,因此我们不处理 JPEG、位图或 PNG 等格式。

对于模型训练,将像素强度重新缩放到 0 到 1 的范围非常重要,这个过程称为归一化

接着,我们将训练集重塑为一个形状为 (60000, 28, 28, 1) 的数组。同样,将测试集重塑为形状 (10000, 28, 28, 1)。这里的 1 代表像素的颜色深度,因为是灰度图像,我们不需要红、绿、蓝三个通道。

在继续之前,检查数据总是很重要的。这里我们将可视化数据集中的一个样本,你可以自由更改 idx 的值来查看其他样本。

现在,让我们构建一个 tf.keras.Sequential 模型,用于对 MNIST 数据集的图像进行分类。我们将使用一个非常简单的卷积神经网络(CNN)。

确保你的模型具有正确的输入形状和正确数量的输出单元。我们将在输出层使用 softmax 作为激活函数。

然后,使用 Adam 优化器、稀疏分类交叉熵作为损失函数、准确率作为评估指标来配置模型以进行训练。接着,通过将训练图像拟合到训练标签来训练模型指定的周期数。

训练完成后,我们可以查看模型在测试集上的损失和准确率,对于一个如此简单的模型来说,结果还不错。

为了让 TensorFlow Serving 能够访问模型,你需要保存它。为此,你将使用 SavedModel 格式。以下代码将模型保存到 MODEL_DIR 变量指定的目录中。

为了让另一个进程(如 TensorFlow Serving)知道模型保存在哪里,你可以使用环境变量。这里,你可以为刚刚写入的模型路径创建一个环境变量。


部署模型并进行推理

安装好 TensorFlow Serving 后,你可以通过一个 bash 脚本启动它。然后使用以下参数来配置模型服务器:

  • REST API 端口:处理请求的端口,本例中为 8501
  • 模型名称:在 URL 中使用的模型名称,这里我们使用 digits_model
  • 模型基础路径:应使用环境变量 MODEL_DIR 作为已保存模型的基础路径。

要使用我们保存的模型发送预测请求,可以使用 JSON 格式。这里我们看到,我们使用测试集的前几个图像创建了一个 JSON 对象。

然后,我们将一个预测请求作为 POST 请求发送到服务器的 REST 端点,并传递这个包含请求数据的 JSON 对象。

默认情况下,服务器将使用模型的最新版本,但如果你需要(例如为了测试或进行 A/B 测试),也可以在此处指定特定版本。请注意 URL 中的 digits_model,这就是我们在上一步中使用的名称。

如果你想绘制结果,可以使用这样的代码。请注意,如果某个值的预测结果与标签相同,我们将其绘制为绿色,否则绘制为红色。

结果如下,效果不错。


总结

本节课中,我们一起学习了如何在自己的基础设施上部署机器学习模型。我们介绍了 TensorFlow Serving 的几种安装方式,并重点演示了在 Debian 环境下通过 apt-get 安装。随后,我们训练了一个简单的 MNIST 分类模型,将其保存为 SavedModel 格式,最后配置并启动了 TensorFlow Serving 服务器,成功通过 REST API 发送请求并获得了预测结果。这为你管理自己的模型服务提供了一个坚实的起点。

136:模型服务架构 🏗️

在本节课中,我们将学习模型服务的基础设施模式与扩展性。我们将从宏观层面探讨运行机器学习模型的基础设施选择,并深入了解几种流行的模型服务器架构。


基础设施部署地点概览

首先,我们从宏观层面审视构建和使用机器学习模型的两个主要基础设施部署地点。

这通常归结为两个主要选择:你可以在自己的场所拥有所有必需的硬件和软件,或者将它们外包给云服务提供商,由他们为你提供所有硬件管理以及软件服务(如管道管理)。

当你在自己的场所运行时,你对硬件基础设施拥有完全的控制权。显然,这非常灵活,你可以敏捷地快速适应需求变化,但这需要付出成本。你必须采购、安装、配置和维护你的硬件基础设施,这可能既复杂又昂贵。大公司倾向于采用这种方法,因为他们可以利用规模经济,例如拥有丰富的内部经验。

另一个选择,通常被小公司采用,是将他们的基础设施需求外包给在构建、管理、扩展和监控硬件、软件及应用程序方面的专家。这方面的优秀例子包括亚马逊、谷歌云平台和微软Azure等提供的服务。


模型服务的工作方式

在选择基础设施之后,你还必须根据你的选择考虑模型服务将如何工作。

当使用本地硬件时,你可以灵活选择你喜欢的模型服务器,并负责安装、配置和维护它。因此,像TensorFlow Serving、Kubeflow Serving和Viserver等选项将可供你使用,我们稍后会探讨其中一些的具体情况。

如果你在云端进行模型服务,那么你可以在他们的基础设施上创建虚拟机,这为你提供了与本地相同的灵活性,因此你可以安装和配置相同类型的预构建服务器,例如TensorFlow Serving和Kubeflow等。或者,你可以使用该云供应商提供的一套工具和服务。例如,如果你选择了谷歌云平台,你可以使用AutoML或任何谷歌云AI服务;如果你选择了亚马逊网络服务,那么SageMaker Autopilot将可供你使用。


模型服务器简介

现在你已经探索了关于如何进行模型服务的高层选项,无论是在本地还是使用云提供商,接下来让我们深入了解模型服务器,并探讨一些可供你选择的流行选项。

这些包括TensorFlow Serving、TorchServe、Kubeflow Serving和NVIDIA Triton推理服务器。但在了解它们之前,让我们快速回顾一下模型服务器实际上做什么。

模型服务器的高层架构可以用这样的图表来概括。你的模型通常保存到文件系统中。你也可以拥有同一模型的多个版本,以便尝试不同的模型,但最终它可供模型服务器读取。模型服务器的职责是实例化模型,并公开你希望向客户端提供的模型方法。

例如,如果模型是一个图像分类器,模型本身将接收特定大小和形状的张量。对于MobileNet,这将是224x224x3。模型服务器接收这些数据,将其格式化为所需的形状,传递给模型文件,并获取推理结果。它还可以管理多个模型版本,如果你希望进行A/B测试或为不同用户提供不同版本的模型。然后,模型服务器将该API暴露给客户端,正如我们之前提到的,例如,它有一个REST或gRPC接口,允许将图像传递给模型。模型服务器将处理该请求,并从模型获取推理结果(在本例中是图像分类),并将其返回给调用者。

以下是一些最流行的模型服务器:

  • TensorFlow Serving
  • TorchServe
  • Kubeflow Serving
  • NVIDIA Triton推理服务器

接下来,我们将简要了解每种服务器的架构。


总结

本节课中,我们一起学习了模型服务架构的基础知识。我们首先比较了本地部署与云部署两种基础设施选择及其优缺点。接着,我们探讨了在不同部署环境下模型服务的工作方式。最后,我们介绍了模型服务器的核心功能,并列举了几种主流的模型服务器选项,为后续深入学习具体技术细节奠定了基础。

137:模型服务器 - TensorFlow Serving 🚀

在本节课中,我们将深入学习模型服务,并重点探讨 TensorFlow Serving 的架构与核心工作原理。我们将了解其如何高效地加载、管理和服务机器学习模型。


概述

上一节我们从宏观层面介绍了模型服务。本节中,我们将更深入地剖析一些具体的架构,首先从 TensorFlow Serving 开始。

TensorFlow Serving 是一个灵活、高性能的机器学习模型服务系统。它提供了与 TensorFlow 模型的开箱即用集成,同时也能扩展以服务其他类型的模型。


TensorFlow Serving 的核心特性

以下是 TensorFlow Serving 的一些重要特性:

  • 批量与实时推理:它支持同时获取大量推理结果(适用于推荐引擎等场景),也支持快速返回单个任务的答案(适用于图像分类等场景)。
  • 多模型服务:允许为同一任务部署多个模型,服务器可在它们之间进行选择。这对于 A/B 测试、受众细分等场景非常有用。
  • 远程调用接口:提供了远程过程调用(RPC)或传统的 REST 端点,供客户端调用服务器。

TensorFlow Serving 的架构解析

TensorFlow Serving 的架构围绕一个核心概念构建:Servable。这是 TF Serving 中的核心抽象。

  • Servable(可服务对象):这是客户端用于执行计算(例如推理或查找)的基础对象。它们可以是任何类型或接口,因此非常灵活。一个典型的 Servable 是一个 TensorFlow SavedModel,但也可能是一个嵌入查找表。
  • Loader(加载器):管理 Servable 的生命周期。Loader API 实现了与特定学习算法、数据或产品用例无关的通用基础设施。具体来说,加载器标准化了加载和卸载 Servable 的 API。
  • Aspired Versions(期望版本):代表一组应该被加载并准备就绪的 Servable 版本。
  • Source(源):一次为单个 Servable 流通信这组期望版本。当源向管理器提供新的期望版本列表时,它会取代该 Servable 流之前的列表。
  • Manager(管理器):处理 Servable 的完整生命周期,包括加载、服务和卸载 Servable。管理器监听源,并根据版本策略跟踪所有版本。它会卸载列表中不再出现的任何先前已加载的版本。
  • Servable Handle(可服务对象句柄):为客户端提供外部接口。

架构中有许多组件,让我们通过一个例子来看看它们是如何协同工作的。


工作流程示例

假设一个源代表一个具有频繁更新权重的 TensorFlow 图,权重存储在磁盘上的文件中。

  1. 源检测到模型权重的新版本。
  2. 它创建一个包含指向磁盘上模型数据指针的加载器。
  3. 源将“期望版本”通知动态管理器。
  4. 动态管理器应用版本策略,并决定加载新版本。
  5. 动态管理器告知加载器有足够的内存。
  6. 加载器使用新权重将 TensorFlow 图实例化为一个 Servable。
  7. 客户端请求最新版本模型的句柄。
  8. 动态管理器返回新版本 Servable 的句柄。
  9. 随后,您可以使用该 Servable 运行推理。这就是您上周构建 Fashion MNIST 模型示例时所看到的过程。

总结

本节课中,我们一起学习了 TensorFlow Serving 的核心架构与工作流程。我们了解了 ServableLoaderManager 等关键组件如何协作,以支持模型的灵活部署、版本管理和高效推理。掌握这些概念是构建可靠生产级模型服务系统的重要基础。

138:模型服务器 - 其他供应商 🚀

在本节课中,我们将学习除TensorFlow Serving之外的其他几种流行的模型服务器解决方案。我们将重点介绍NVIDIA的Triton推理服务器、PyTorch的TorchServe以及Kubeflow Serving,了解它们的特点、架构和适用场景。


Triton推理服务器 🧠

上一节我们介绍了TensorFlow Serving,本节中我们来看看由NVIDIA提供的Triton推理服务器。它是一个开源推理服务软件,旨在简化生产环境中AI模型的大规模部署。

Triton推理服务器允许团队部署来自任何框架的训练好的AI模型,例如:

  • TensorFlow
  • TensorRT
  • PyTorch
  • ONNX Runtime
  • 甚至是自定义框架

模型可以从本地存储或云平台(如Google Cloud Platform或AWS)部署,并可以运行在任何基于GPU或CPU的基础设施上,包括云端、数据中心或边缘设备。

Triton的核心优势在于其高效的资源利用。它使用CUDA流在单个GPU上并发运行来自相同或不同框架的多个模型。在多GPU服务器中,它会自动在每个GPU上创建每个模型的实例。所有这些都提高了GPU利用率,而无需用户编写额外的代码。

该推理服务器支持低延迟的实时推理和批处理推理,以最大化GPU和CPU的利用率。它还内置了对流式输入的支持,方便进行流式推理。

为了获得更高性能,用户可以使用共享内存支持。传递给Triton推理服务器的输入和输出可以存储在系统或CUDA共享内存中,这可以减少HTTP或gRPC的开销,从而提高整体性能。

Triton还支持模型集成。它与Kubernetes集成,用于编排、指标收集和自动扩缩容。同时,它也集成了KFServing和Kubeflow Pipelines,以构建端到端的AI工作流。

在监控方面,Triton推理服务器导出Prometheus指标,用于监控GPU利用率、延迟、内存使用率和推理吞吐量。它支持标准的HTTP/gRPC接口,便于与负载均衡器等应用程序连接,并且可以轻松扩展到任意数量的服务器,以处理任何模型不断增长的推理负载。

通过模型控制API,Triton推理服务器可以服务数十或数百个模型。可以根据模型控制配置中的更改,显式地将模型加载到推理服务器中或从中卸载,以适应GPU或CPU内存。它也可以用于在CPU上服务模型。它支持包含GPU和CPU的异构集群,有助于标准化跨这些平台的推理,因此在峰值负载期间,它可以动态扩展到任何CPU或GPU。


TorchServe ⚡

除了TensorFlow Serving和Triton推理服务器,另一个流行的服务环境是围绕PyTorch设计的TorchServe。

TorchServe是AWS和Facebook共同发起的一个项目,旨在为PyTorch模型构建一个模型服务框架。在TorchServe发布之前,如果你想服务PyTorch模型,必须开发自己的模型服务解决方案,例如通过自定义处理程序、开发模型服务器、构建自己的Docker容器,并找到一种方法使模型可通过网络访问,并将其与集群编排系统集成。

使用TorchServe,你可以以即时执行模式或图形模式部署PyTorch模型。以下是其主要功能:

  • 可以同时服务多个模型。
  • 可以拥有版本化的生产模型,用于A/B测试。
  • 可以动态加载和卸载模型。
  • 可以监控详细的日志和可自定义的指标。
  • 最重要的是,TorchServe是开源的,因此可以扩展以满足你的部署需求。

其服务器架构如下:前端负责处理请求和响应,管理来自客户端的请求、响应以及模型生命周期。后端使用模型工作器,这些工作器是从模型存储中加载的模型的运行实例,负责执行实际的推理。可以看到,在TorchServe上可以同时运行多个工作器,它们可以是同一模型的不同实例,也可以是不同模型的实例。实例化更多模型实例可以同时处理更多请求,从而提高吞吐量。

模型可以从云存储或本地主机加载。TorchServe支持服务PyTorch的即时执行模式模型和TorchScript保存的模型。服务器支持用于管理和推理的API,以及用于常见功能(如服务器日志、快照和报告)的插件。


Kubeflow Serving 📦

除了TF Serving、Triton推理服务器和TorchServe,你可能还想了解一下Kubeflow Serving。这里内容较多,无法详细展开,但我们简要看一下。

Kubeflow也通过Kubeflow Serving提供了服务能力。这允许你使用带有Kubernetes的计算集群,通过抽象实现无服务器推理。它适用于TensorFlow、PyTorch等框架。我们在此不深入细节,但你可以在附加阅读材料提供的URL中了解更多信息。


总结与展望 🎯

本节课中我们一起学习了三种重要的模型服务器:NVIDIA的Triton推理服务器、PyTorch的TorchServe以及Kubeflow Serving。我们了解了它们如何支持多框架模型部署、提高资源利用率、提供监控和扩展能力。

现在你已经了解了机器学习模型服务是如何实现的,让我们退一步,探索如何扩展此类应用程序。接下来,你将理解水平扩展和垂直扩展的基本原理。从那里,你将看到如何使用虚拟化、容器和容器编排技术,通过开源服务来管理你的应用程序服务,并将其扩展到合适的规模。

139:扩展基础设施 🚀

在本节课中,我们将要学习如何扩展机器学习系统的基础设施。我们将探讨扩展的重要性、两种主要的扩展方式(垂直与水平),并深入了解容器化技术及其编排工具,特别是Kubernetes和Kubeflow,它们如何帮助我们高效、弹性地管理机器学习工作负载。


扩展的重要性与方式

上一节我们介绍了模型服务架构。本节中我们来看看如何管理这些架构的规模。

当需要像这样部署模型时,管理规模和众多服务变得至关重要。接下来,你将了解什么是扩展、为什么它很重要,以及有哪些服务可以帮助你在应用程序和机器学习工作负载中实现扩展。

考虑一个模型,这里有一个非常简单的例子,但大多数模型会比这个模型大得多且复杂得多。

然后考虑在大型数据集上训练具有数十亿次操作的深度神经网络的成本。在标准CPU或单个GPU上完成训练可能需要数天时间。

因此,如果你能扩展运行训练的硬件,并将训练分布到不同的硬件设备上,甚至可能通过分片将数据分布到这些硬件上,你就可以使训练效率大大提高。

同样,你也可以考虑训练网络成本,这不仅仅是数据成本。网络越大、越复杂,需要调整和微调的参数就越多。像这样一个简单的神经元有两个浮点参数,因此可以想象拥有数百万个需要学习参数的大型网络。

不仅如此,还要考虑当你将模型部署到服务器时会发生什么。服务器收到的大量推理请求可能会使其不堪重负。因此,扩展运行时推理以及训练的能力至关重要。

扩展主要有两种方式:水平扩展和垂直扩展。让我们从垂直扩展开始。


垂直扩展 📈

垂直扩展非常直接,正如其名,它意味着使用更大、更强大的硬件。这可能是升级你的CPU、增加更多RAM、使用更新的GPU或其他类型的强大硬件。

如果你的车只能载5个人,而你需要运送100个人,你可以换一辆能载10个人的更大的车,这样你的运送速度就能快一倍。


水平扩展 ↔️

水平扩展则意味着向网络中添加更多设备。它会在负载增加时添加更多GPU或CPU。所以,与其买一辆更大的车,你可以找来20辆同样大小的车,一次性运送所有100个人。

沿用这个比喻,你可以在需要的时候借用其他19辆车,连同你自己的车一起使用。这基本上就是云计算的概念,你可以根据需要扩展,在不需要时再缩减回去,并且只为使用的部分付费。


为什么推荐水平扩展?

我通常推荐水平扩展,原因有很多。

首先是弹性。就像我那个100个人和5座车的例子,与其放弃你可靠的车去换一辆更大的车,并且只能逐步解决问题,你可以租用19辆和你自己车一样的车,用完后归还。

这样,你就不必持续维护和确保所有其他车辆的正常运行,在这种场景下道理完全相同。

不仅如此,如果你进行垂直扩展,通常必须让应用程序离线才能升级硬件资源。而在弹性扩展中,你不需要这样做,你只需启动新的实例。

一些框架,如Google的App Engine,也非常智能地使用机器学习来预测使用模式,以便在实际需要之前预热机器,从而降低整体延迟。

当然,也存在限制。但这些限制通常是预算上的,而不是硬件上的。所以,如果你需要更多节点并且负担得起,你就可以去获取它们。


选择云平台时的考量

许多供应商提供允许你水平扩展的云平台。在选择时,请关注他们为系统整体扩展提供的服务。我通常会关注以下三点:

以下是选择云平台时需要考虑的三个关键方面:

  • 手动扩展:例如,我是否可以说我只想要N个虚拟机实例?
  • 自动扩展:如果我希望我的应用程序能根据需求自动启动和关闭,会发生什么?延迟和成本是怎样的?
  • 扩展策略:系统根据我的需求启动和关闭实例的策略有多积极?

容器化:实现高效水平扩展

当然,下一个问题随之而来:我如何管理我的额外虚拟机,以确保它们上面有我想要的内容?

对于机器学习来说,可能有很多依赖项、数据访问权限、权限以及许多其他可配置项。如果我打算进行水平扩展,我希望新机器能够快速启动并运行。

为此,就有了容器化。接下来让我们探讨一下容器化是什么。


从虚拟机到容器

让我们思考一个典型的系统,我可能运行着许多应用程序。

模式通常看起来是这样的:我的应用程序在操作系统内使用一些二进制文件或库运行,而操作系统则由硬件执行。

对此的扩展是虚拟机架构,应用程序仍然可以在操作系统内的二进制文件和库上运行,但该操作系统并不直接在硬件上运行,而是在一个没有硬件的虚拟机上运行。这个虚拟机由管理程序管理,管理程序充当虚拟机的管理者,每个虚拟机都有自己的操作系统、二进制文件和应用程序,如图所示。管理程序通常直接运行在硬件上。

你已经可以看到这如何用于水平扩展:我们的硬件可能支持多个操作系统和应用程序实例,如图所示。

这很酷,但它可能面临一个限制:即每个虚拟机上必须安装很多东西,至少是一个完整的操作系统。因此,这可能不是系统资源最有效的利用方式。

这就是容器可以提供帮助的地方。从架构上看,它们与虚拟机概念非常相似,只是每个分区不需要单独的操作系统,因此它们重量更轻,相同的硬件通常可以管理比虚拟机更多的容器。


容器的优势

考虑使用容器的优势:因为每个应用程序实例不需要一个操作系统,你通常可以在相同的硬件上运行更多实例,从而获得更好的水平可扩展性。

让它们在容器运行时中运行的抽象,也为你提供了在支持容器运行时的硬件上更大的灵活性。你无需担心操作系统,你的应用程序可以直接运行。

这带来了更轻松的部署和更多的部署选择。


Docker:流行的容器运行时

你无疑听说过Docker,它是最流行的容器运行时。它最初是一项基于Linux的技术,但迅速扩展到Windows等其他操作系统,并广泛应用于数据中心、个人机器和公共云基础设施中。

你经常会看到开发人员教程以Docker实例的形式实现,因为这使得处理复杂的依赖关系或操作系统特性变得更加容易。

容器为你提供了一种非常方便的水平扩展方式,但并非没有其自身的挑战。


容器编排:管理容器集群

例如,你可能希望在多台机器上运行多个容器,并尝试让它们保持同步。像任何应用程序一样,即使是容器中的应用程序,也有宕机的风险,或者容器主机本身可能发生故障。因此,你还需要保持一组容器处于热备用状态,以便在某个容器宕机时切换流量。

因此,我们需要牢记容器编排的概念,接下来让我们深入探讨一下。

容器编排背后的想法很简单:它是一组工具,用于管理容器的生命周期,包括它们的扩展。

在你的容器管理器之上,容器编排通常提供多种服务,例如资源管理,以确保容器不会过度分配硬件资源;调度,以便容器满足运行和停机时间要求;当然还有常规的服务管理,以便你可以管理编排环境如何执行其工作。

例如,你可以使用服务管理来确保一定数量的容器处于热备用状态,以防某些容器发生故障。随着时间的推移,当你了解系统如何运行时,可以调整这个数量。

两个比较流行的容器编排工具是Kubernetes和Docker Swarm。接下来让我们看看Kubernetes,因为它支撑了Kubeflow,这项技术让你能够使用容器通过水平扩展来扩展你的ML应用程序和学习。


Kubernetes简介

我在这里不会深入介绍Kubernetes的细节,你可以在Kubernetes.io上了解更多。总之,它是一个用于自动化容器化应用程序的部署、扩展和管理的开源系统。

它将组成应用程序的一组容器分组为逻辑单元,以便于管理和发现。

Kubernetes建立在Google多年来构建可扩展应用程序的经验之上,并结合了社区的经验,旨在为你带来两全其美的效果。

请查看课程末尾附加阅读材料中提供的网站和链接,你会看到一个视频,介绍伦敦《金融时报》如何将数百个微服务迁移到容器环境,使用Kubernetes进行水平扩展。本周晚些时候,你将做一个关于TensorFlow Serving的快速实验,使用Kubernetes进行自动扩展。


Kubeflow:Kubernetes上的ML工作流

当涉及到在Kubernetes上部署ML工作流时,Kubeflow应运而生。它旨在使ML工作流的部署(包括数据摄取、特征提取、训练、模型管理等所有这类任务)能够使用Kubernetes实现可移植和可扩展。

Kubeflow的一个重要特性是,它的设计使得任何可以运行Kubernetes的地方,你都可以使用它。因此,无论你是选择云供应商、在自己的场所运行容器,还是某种两者结合的方式,你的机器学习工作流都能够与之一起运行。

请访问Kubeflow.org了解更多信息,特别是查看他们的入门指南,了解如何安装和使用它。


总结

本节课中我们一起学习了如何扩展机器学习系统的基础设施。我们探讨了水平扩展与垂直扩展的区别及其适用场景,深入了解了容器化技术(以Docker为例)如何实现轻量级、高效的应用部署。接着,我们介绍了容器编排的必要性,并重点学习了Kubernetes这一强大的编排工具,以及专为机器学习工作流设计的Kubeflow项目。它们共同构成了构建弹性、可扩展的现代机器学习生产系统的基石。

我建议你在继续深入学习之前,花一些时间尝试使用这些产品。

140:第11讲 在线推理 🚀

在本节课中,我们将要学习在线推理的基本流程,并探讨如何从多个维度优化模型服务系统,包括延迟、吞吐量和成本。我们还将了解一些可用于优化的技术和策略。


在线推理的典型流程

上一节我们介绍了模型服务的基础设施,本节中我们来看看在线推理的典型交互过程。一个模型与在线调用之间的典型交互流程如下所示。

外部世界与调用者之间的接口通常通过一个 REST API 实现。你通常会拥有一些关于用户的数据,通常称为观测值,你希望基于此获得预测。例如,这可能是关于客户的上下文信息,可用于预测适合他们的购买类型,从而生成推荐列表。或者,它也可能是像智能回复生成器这样的应用,在对话中,文本可用于自动生成用户可以选择回复。

观测值通过 REST API 发布到模型,返回的预测结果被呈现出来。


在线推理的优化指标

在第一周,我们讨论了在一般场景下进行推理时需要优化的指标。现在,让我们在在线推理的上下文中重新审视它们。

如果你想优化这样一个系统,你应该从三个不同的轴来考虑。

  • 延迟:数据传递到服务器、推理执行以及响应处理总共需要多长时间。延迟有多种形式,但从用户的角度来看,是他们的操作与应用响应之间的延迟。这不仅仅是推理时间。即使模型性能优异,但如果数据传输或结果呈现引入了延迟,用户也会感受到延迟。因此,在应用程序设计的各个环节管理延迟至关重要。
  • 吞吐量:系统在单位时间内处理的请求数量。虽然吞吐量对所有系统都很重要,但对于像密集型数据处理应用这样的非面向客户的系统,吞吐量通常更为关键。尽管如此,对所有系统而言,都需要牢记这一点。
  • 成本:大多数预算并非无限。你为尽可能提高延迟和吞吐量效率所做的工作会产生成本。你需要始终考虑这一点。系统中的成本有多种,不仅仅是硬件,还包括工程和测试、时间和精力、软件许可、更新缓慢的机会成本以及应用中断的损失成本等。这些以及许多其他因素都必须考虑在内。

优化策略与技术

现在你已经了解了在机器学习服务系统中需要优化的方面,接下来让我们探讨一些优化策略,以及一些可用于优化延迟和吞吐量的技术。

如果你想优化推理,可以关注三个主要领域。

以下是三个主要的优化方向:

  1. 服务基础设施:用于服务模型和处理用户输入输出的基础设施。这可以通过增加或使用更强大的硬件,以及使用本周早些时候介绍的容器化或虚拟化环境来进行扩展。
  2. 模型架构:理解你的模型架构及其训练和测试时使用的指标。在推理速度和准确性之间通常存在权衡。如果一个准确率为99%的模型比准确率为98%的模型慢10倍,那么额外的成本真的值得吗?
  3. 模型编译:如果你知道将要部署模型的硬件(例如特定类型的GPU),通常存在一个训练后步骤,包括创建模型工件和模型执行运行时,最终适配底层硬件。你可以优化模型图和推理运行时,以减少内存消耗和延迟。

此外,在应用层也可以执行一些优化。

例如,考虑进行购物预测的场景,为客户提供他们接下来可能想购买的产品列表。

应用程序将接收客户的详细信息,包括某种形式的标识符。这些数据被模型用来生成推理,模型将返回一系列可能适合该客户的产品ID。因此,应用程序必须在数据存储中查找这些ID,以获取有关它们的详细信息,然后将其作为预测结果返回给客户端。

这里涉及大量数据库查询,因此一个明显的优化是考虑将常见场景缓存到比典型数据存储更快的介质中。

例如,如果你有一些热门产品,可以将它们存储在更快的数据存储中。当然,存储速度越快,成本就越高,因此这里存在权衡,并且可能无法将所有数据都放在这样的存储中。如果你能找到放入其中的数据量的平衡点,就可以在最小化额外成本的同时最大化延迟效益。

快速数据缓存通常使用 NoSQL 数据库或内存缓存来实现。市场上有一些产品可以处理这个问题,例如亚马逊的 DynamoDB、谷歌云的内存存储(以前称为 Memcache)。在我之前使用的男孩乐队案例研究中,我广泛使用了 Memcache 这个术语。此外,像 Big Table 和 Cloud Datastore 这样的服务也可以快速处理大型数据集。


数据处理的优化

前面我们从高层次探讨了在线推理的工作原理,并讨论了一些可以优化机器学习推理的场景和技术,特别是管理应用程序内部的数据。还有另一个可以考虑优化的领域,那就是传入和传出模型的数据。接下来,我们将看看数据的预处理和后处理。


本节课中我们一起学习了在线推理的基本流程、关键的优化指标(延迟、吞吐量、成本),并探讨了从基础设施、模型架构、模型编译到应用层缓存等多个维度的优化策略。理解这些概念对于构建高效、可靠的机器学习服务系统至关重要。

141:数据预处理 🛠️

在本节课中,我们将要学习机器学习应用中的数据预处理环节。我们将探讨为何需要对输入数据进行转换、常见的预处理任务类型,以及预处理在模型部署流程中的位置。


上一节我们介绍了通过优化硬件、容器、模型架构和应用缓存来提升应用性能。本节中我们来看看另一个关键的优化领域:数据预处理

回顾一个简单的应用高层架构图,传入系统的观测数据可能是一种格式,但这不一定是模型设计时所接受的格式。数据必须以某种方式进行转换。

例如,考虑一个简单的语言模型,观测数据可能是用户输入的一个句子,并以字符串形式存储。模型被设计用于对该文本进行分类,以判断其是否含有不当内容。此类NLP模型在输入向量上进行训练,其中单词被转换为高维向量,句子则是这些向量的序列。

现在,数据的预处理必须在某个环节完成。这只是一个相对简单的例子,说明了需要将数据从一种格式转换为另一种格式。


除了格式转换,在预处理时还需考虑其他方面,例如数据清洗,即修正传入数据中的无效值。

以下是数据预处理中需要考虑的几个关键任务:

  • 数据清洗:例如,你正在构建一个图像分类器,用户发送的图片因尺寸过大而无效。你当然可以拒绝它,或者也可以承担起调整其尺寸以获得有效图片大小的处理任务。
  • 特征调整:对数据进行某种转换,使其适合模型。对于图像,这可能是归一化。例如,不是用32位值表示一个像素,而是将其转换为代表红、绿、蓝的三个8位值(忽略Alpha通道)。然后,不是让这些值在0到255之间,而是可以将它们转换为0到1之间的值,因为神经网络往往能更好地处理此类归一化后的值。
  • 特征构造:模型通常要求数据预处理包含特征构造。例如,对于一个预测房价的模型,输入数据可能包含多个列,如房间数量和每个房间的大小,但模型是在房屋的总建筑面积上训练的。那么,可以使用特征交叉来将你拥有的值相乘,以得到模型使用的特征类型。这里的其他场景可能包括多项式扩展,即根据原始特征的公式计算新特征。也许数据包含摄氏温度,但模型期望的是华氏温度。
  • 表示转换:特征调整和特征构造也可以是表示转换的一种形式,即输入数据需要被转换以便模型理解。一个经典应用是数据的独热编码

此外,还有特征智能缓存,这可以在训练期间完成。例如,在我们的句子示例中,可能存在像“早上好”这样的常见句子。与其每次都经过清洗、调整、构造和表示转换,不如直接将输入数据格式预先转换并缓存起来,然后直接使用它。


但不要忘记后处理。一旦你的模型将预测结果返回给应用,你仍然需要对这些结果进行处理。

例如,在一个智能回复应用中,模型可能会给出几个关于最佳下一句可能是什么的预测。这些预测可能是代表句子中单词的向量序列,但并非句子本身。你的应用在将其返回给用户之前,需要将这些向量转换为字符串。这就是数据的后处理。你在预处理中看到的所有内容都可以应用,但通常是反向的。


现在你已经了解了后处理是什么样子,让我们探索一些现有的产品,它们可以为你完成这项任务提供捷径。

接下来,我将提供一份阅读笔记,向你介绍 Apache BeamTensorFlow Transform,它们能极大地帮助完成预处理任务。


本节课中我们一起学习了数据预处理的核心概念。我们了解到,输入数据通常需要经过清洗、调整、构造和转换,才能匹配模型的期望格式。同时,预测输出也可能需要后处理才能返回给用户。高效地管理这些步骤对于构建健壮、高性能的机器学习应用至关重要。

142:批量推理场景 🚀

在本节课中,我们将学习机器学习模型在生产环境中的一种关键部署方式:批量推理。我们将探讨其定义、优势、劣势、适用场景以及性能优化的核心考量。


概述

上一节我们讨论了模型扩展和推理架构。本节中,我们来看看批量推理场景下的模型性能与资源需求。

在训练、评估和调优一个机器学习模型之后,模型会被部署到生产环境中以生成预测。

机器学习模型可以提供批量预测,这些预测将在未来的某个时间点应用于实际用例。

什么是批量推理?📦

基于批量推理的预测,是指您的机器学习模型在一个批量评分作业中,为大量数据点生成预测。这些预测不需要实时生成,或者实时生成并不可行。

例如,在批量推荐中,您可能只使用客户与商品交互的历史信息来进行预测,而不需要任何实时信息。

批量推荐通常用于针对有高流失倾向的非活跃用户的留存活动,或用于促销活动等场景。

用于预测的批量作业通常按某种循环计划生成,例如每日夜间或每周。

预测结果通常存储在一个数据库中,随后可供开发人员和用户使用。

批量推理的优势与劣势 ⚖️

批量推理有一些重要的优势。您可以使用复杂的机器学习模型来提高预测的准确性,因为推理时间没有限制,并且通常也不需要缓存预测结果。

为预测所需的特征采用缓存策略会增加您机器学习系统的总体成本。

如果不采用缓存策略,数据检索可能会花费一些时间。

批量推理也可以等待数据检索完成后再进行预测,因为预测结果并非实时可用。

然而,批量推理也有一些缺点。

预测无法用于实时目的。

预测的更新延迟可能长达数小时,有时甚至是数天。

因此,预测通常是基于旧数据进行的,这在某些场景下会产生问题。

假设一个像电影流媒体这样的服务在夜间生成推荐,如果有新用户注册,他们可能无法立即看到个性化推荐。

为了解决这个问题,系统被设计为向新用户展示来自相似人群(如同一年龄段或相同地理位置)的其他用户的推荐。

批量推理的用例

以下是批量推理的一些典型用例。

在执行批量预测时,需要优化的最重要指标是吞吐量

在批量预测中,您应始终致力于提高吞吐量,而不是降低延迟。

当数据以批次形式可用时,模型应能一次处理大量数据。

随着吞吐量的增加,生成每个预测的延迟也会增加。

但这在批量预测系统中不是一个大问题,因为预测不需要立即可用。预测通常被存储起来供后续使用,因此可以牺牲一些延迟。

通过使用硬件加速器(如GPU),可以提高处理批量数据的机器学习模型或生产系统的吞吐量。

您还可以增加部署模型的服务器或工作节点的数量。

您可以将模型的多个实例加载到多个工作节点上以提高吞吐量。

用例详解

让我们具体看一些批量预测的用例。

首先,电子商务网站上的新产品推荐可以在一个循环计划中生成,然后缓存这些预测结果以便于检索,而不是在每次用户登录时都生成。这使系统更简单,并且可以节省推理成本,因为您不需要保证像实时推理那样的低延迟。

您还可以使用更复杂的模型进行预测,因为您没有预测延迟的限制。

这有助于实现更高程度的个性化,但使用的是可能不包含用户新信息的延迟数据。

让我们看一个情感分析问题。根据用户的评论(通常是文本格式),您可能希望预测一条评论是正面、中性还是负面的。

基于客户评论来分析用户对您产品或服务情感的系统,可以利用循环计划的批量预测。

例如,有些系统可能每周生成一次产品情感分析。

在这种情况下不需要实时预测,因为客户和利益相关者并非在等待基于预测结果实时完成某个操作。

情感预测可以用于长期改进服务或产品,正如您所见,这并非一个实时的业务流程。

基于CNN、RNN或LSTM的方法可以用于情感分析,我倾向于喜欢LSTM。

这些模型更复杂,但它们通常能提供更高的准确性。

这使得在批量预测中使用它们更具成本效益。

让我们看一个不同的例子:预测产品或服务的需求。

您可以使用批量预测来估计产品需求的模型,例如每日一次,用于库存和订单优化。

这可以建模为一个时间序列问题,因为您是基于历史数据预测未来需求。

由于批量预测的延迟约束最小,可以使用像ARIMA、SARIMA或RNN这样的时间序列模型,而不是线性回归等方法,以获得更准确的预测。


总结

本节课中,我们一起学习了机器学习中的批量推理场景。我们明确了批量推理的定义,分析了其允许使用复杂模型、无需严格实时性等优势,以及预测延迟高、基于旧数据等劣势。我们探讨了其在推荐系统、情感分析和需求预测等领域的典型用例,并强调了在批量推理中优化吞吐量而非延迟的核心原则。理解批量推理是构建高效、经济生产级机器学习系统的重要一环。

143:使用ETL进行批处理 📊

在本节课中,我们将学习如何为机器学习模型准备数据,特别是处理那些频繁更新的时间序列数据或流式数据。我们将重点介绍一个称为ETL(提取、转换、加载)的核心数据处理流程,并了解其工作原理及常用工具。


上一节我们介绍了静态数据的批处理。本节中,我们来看看如何处理时间序列数据或其他需要作为流读取的、频繁更新的数据类型。

根据来源不同,数据可以有多种类型。例如,数据湖中通常存储着来自CSV文件、日志文件等的大量批处理数据。另一方面,流式数据则是实时到达的,传感器数据就是其中一个例子。

在数据用于进行批量预测之前,必须从多个来源(如我们提到的日志文件和CSV文件)中提取数据。这些来源也可能包括API、其他应用程序、流式数据源等。

提取的数据需要进行转换,以便进行机器学习预测,然后将其加载到数据库中。之后,数据可以分批发送进行预测。

整个准备数据的流程被称为ETL管道。ETL代表提取、转换和加载。

ETL管道是一系列从数据源提取数据、转换数据,然后将数据加载到输出目标(如数据仓库)的过程。加载后的数据可用于多种目的,包括运行批量预测、执行其他分析、进行数据挖掘等。

从数据源提取数据和对数据进行转换可以分布式执行。数据被分割成块,然后可以由多个工作节点并行处理。

ETL工作流的结果存储在数据库中,其优势在于数据处理延迟更低、吞吐量更高。

在数据被发送进行推理之前,让我们看看ETL管道中可用于数据批处理的各种框架。

以下是数据可能来源的几种类型:

  • CSV文件
  • XML文件
  • JSON API
  • 数据湖(如Google Cloud Storage)

对数据的ETL操作由Apache Spark或Google Cloud Dataflow等引擎执行,它们利用了Apache Beam编程范式。

转换后的数据被存储到BigQuery等数据仓库中,并且可以在发送进行批量预测之前,被送回Google Cloud Storage等数据湖。

持续更新的数据源(如传感器)可以连接到Apache Kafka、Google Cloud Pub/Sub等产品。使用Apache Beam的Cloud Dataflow也可以对流式数据执行ETL。Spark有一个专门用于处理流式数据的产品。Apache Kafka同样可以作为流式数据的ETL引擎。

这些数据随后可能被收集到BigQuery等数据仓库,或数据市场、数据湖中。它也可以作为另一个管道的流式数据源。


现在,让我们通过探索Google Cloud平台上的一个场景来实践上述内容。在该场景中,您将使用Beam和TensorFlow。

虽然您使用的关于碳、氢、氮和氧的分子数据是静态的而非流式的,但这个例子将让您了解基于Beam的系统中所有组件如何协同工作以实现学习目标。


本节课中,我们一起学习了ETL(提取、转换、加载)管道如何为机器学习准备数据,特别是处理流式或频繁更新的数据。我们了解了数据的不同来源、分布式处理的优势,以及Apache Spark、Apache Beam(通过Google Cloud Dataflow)和Apache Kafka等关键工具在构建高效数据处理流程中的作用。

144:实验跟踪 📊

在本节课中,我们将学习机器学习开发中的一个核心实践——实验跟踪。我们将探讨为什么实验跟踪至关重要,以及如何有效地记录和管理实验的各个方面,包括代码、参数、环境和结果。


概述

机器学习在很大程度上是一门实验科学。开发过程的核心是不断实验和分析结果。为了获得可重现的结果并建立严谨的流程,我们需要系统地跟踪实验。本节将介绍实验跟踪的基本概念、重要性以及实施方法。


实验跟踪的重要性 🔍

上一节我们概述了实验跟踪的意义,本节中我们来看看为什么它在机器学习实践中如此关键。

机器学习实践更像实验科学而非理论科学。因此,在生产环境中跟踪实验结果对于实现目标至关重要。

机器学习中的调试通常与软件工程中的调试有根本不同。它通常涉及模型不收敛或泛化能力差的问题,而非像段错误这样的功能性问题。清晰记录模型和数据的随时间变化,有助于定位问题根源。

即使是微小的更改,例如改变层的宽度或学习率,也可能对模型性能和训练所需资源产生重大影响。因此,跟踪所有更改非常重要。

此外,运行实验(即反复训练模型)可能非常耗时且昂贵,对于大型模型和数据集尤其如此。因此,最大化利用每次实验至关重要。


实验跟踪的内容

现在,我们了解了实验跟踪的重要性,接下来具体看看需要跟踪哪些内容。

首先,需要记录所有为复现结果所必需的信息。许多人有过这样的糟糕经历:获得一个好结果后,进行了一些未妥善记录的更改,随后发现很难恢复到产生好结果的原始设置。

另一个重要目标是能够进行有意义的比较。这有助于指导你决定下一步实验的方向。但若没有良好的跟踪,很难对大量实验进行比较。

因此,重要的是跟踪和管理每次实验的所有投入,包括:

  • 代码
  • 超参数
  • 执行环境(例如使用的库版本)
  • 评估的指标

当然,以有意义的方式组织它们会很有帮助。许多人最初会做自由形式的笔记,这对于少量简单实验尚可,但很快就会变得混乱。最后,由于你很可能在团队中工作,良好的跟踪有助于与团队分享结果。这通常意味着团队需要共享通用工具并保持一致性。


从笔记本开始 📓

对于初学者或项目初期,大多数实验可能都在笔记本中进行。

笔记本是用于机器学习、数据和模型开发的强大且友好的工具,支持良好的迭代开发过程,包括内联可视化。然而,笔记本代码通常不会直接部署到生产环境,且结构往往不佳。原因之一是笔记本不完全是产品代码,它们通常包含仅适用于笔记本环境的特殊注解(magics)、检查值的代码以及生成可视化的代码,这些在生产工作流中很少需要。

在笔记本中进行实验时,需要确保跟踪这些实验。以下是一些辅助工具:

  • N B convert:可用于从笔记本中提取 Python 代码。
  • En be dime:支持 Jupyter 笔记本的差异比较和合并。
  • Juoppy text:在笔记本和匹配的 Python 文件之间进行转换和同步。
  • Neptune notebooks:帮助进行笔记本的版本控制、差异比较和共享。

例如,为确保从笔记本提取的 Python 代码能够运行,可以使用类似以下的命令提取代码并尝试运行。如果失败,则说明你的代码依赖于笔记本中的某些特定元素,例如 notebook magics。

jupyter nbconvert --to python your_notebook.ipynb
python your_notebook.py

迈向模块化代码

随着实验从简单、小型发展到生产级别,将所有内容放在笔记本中的模式很快就会显得不足。

你应该计划编写模块化代码,而非单体代码,并且这个过程开始得越早越好。因为你会反复执行许多核心工作,从而开发出可重用的模块,这些模块将成为高级工具,通常特定于你的环境、基础设施和团队。这些模块将节省大量时间,并且更加健壮和可维护,也使理解和复现实验变得更加容易。

最简单的形式是目录层次结构,特别是当整个团队在单一代码库中工作时。但在更高级和分布式的工作流中,代码仓库和基于提交的版本控制是管理大型项目(包括实验)的强大且广泛可用的工具。在这些情况下,如果你与团队使用共享的单一代码库,可能希望将实验分开,以免你的提交影响团队仓库的其他部分。


管理运行时参数

进行实验时,你经常需要更改运行时参数,包括模型的超参数。将这些参数的值纳入实验跟踪非常重要,而你设置它们的方式将决定如何实现跟踪。

一个简单而稳健的方法是使用配置文件,并通过编辑这些文件来更改值。这些文件可以与你的代码一起进行版本控制以进行跟踪。

另一种选择是在命令行上设置参数。但这需要额外的代码来保存这些参数值并将其与你的实验关联起来。这意味着需要在实验代码中加入逻辑,将这些值保存到某个数据存储中。这是一个额外的负担,但它也使这些值易于用于分析和可视化,而无需从特定版本的配置文件代码中解析它们。

当然,如果你使用配置文件,也可以在实验代码中加入逻辑,将这些值保存到数据存储中,从而兼得两者优点。

以下是一个示例代码,展示了当你在命令行设置运行时参数时,如何保存这些值(此示例使用 Neptune AI API):

import neptune

# 初始化 Neptune 运行
run = neptune.init_run(project='your-project')

# 记录超参数
run['parameters'] = {
    'learning_rate': 0.001,
    'batch_size': 32,
    'num_epochs': 10
}

# ... 你的训练代码 ...

# 记录指标
run['metrics/accuracy'].log(0.95)
run['metrics/loss'].log(0.05)

# 结束运行
run.stop()

总结

本节课中,我们一起学习了机器学习实验跟踪的核心概念。我们认识到,由于机器学习的实验性质,系统化地跟踪代码、超参数、环境和结果对于实现可重现性、有效比较实验结果以及团队协作至关重要。我们从简单的笔记本工具开始,探讨了如何逐步过渡到模块化代码和专业的版本控制工具,并介绍了管理运行时参数的几种方法。良好的实验跟踪实践是构建可靠、可维护的机器学习生产系统的基础。

145:实验跟踪工具 🧪

在本节课中,我们将学习实验跟踪的重要性以及用于实现实验跟踪的各种工具。我们将了解如何系统地记录实验的各个方面,包括代码、数据和参数,以便于比较、复现和协作。

概述

实验跟踪是机器学习工作流中的关键环节。它确保你能系统地记录每次实验的配置、数据和结果,从而能够有效地比较不同实验、复现成功的结果,并与团队协作。

数据版本控制 📊

上一节我们介绍了实验跟踪的概念,本节中我们来看看一个核心组成部分:数据版本控制。

你的代码和运行时参数需要版本控制,你的数据同样需要。数据反映了其收集时世界的一个快照,而世界是不断变化的。添加新数据、清理旧数据或修改数据都会改变实验结果。因此,就像修改代码、模型或超参数一样,你需要跟踪数据的版本。在实验过程中,你可能还会更改特征向量,例如添加、删除或修改特征,这些变更也需要被版本化。

为了能够跟踪、理解、比较和复现你的实验结果,你必须对数据进行版本控制。

以下是可用于数据版本控制的一些工具:

  • Neptune:集成了数据版本控制、实验跟踪和模型注册表功能。
  • Pyderm:允许你在仓库的主分支中持续更新数据,同时在独立分支中基于特定的数据提交进行实验。
  • Delta Lake:运行在现有数据湖之上,提供数据版本控制功能,包括回滚和完整的历史审计追踪。
  • Git LFS:Git 的扩展,用 Git 内部的文本指针替换大型文件(如音频样本、视频、数据集和图形)。
  • Dolt:一个可以像 Git 仓库一样进行分叉、克隆、分支、合并、推送和拉取的 SQL 数据库。
  • LakeFS:一个开源平台,提供类似 Git 的分支和提交模型,可扩展到 PB 级数据。
  • DVC:一个面向机器学习项目的开源版本控制系统,构建于 Git 之上。
  • ML Metadata:一个用于记录和检索与 ML 开发者和数据科学家工作流(包括数据集)相关的元数据的库。MLMD 是 TFX 的组成部分,但也可独立使用。

实验管理与分析 🔍

典型的机器学习工作流涉及运行大量实验。开发者通常发现,在与其他结果的对比中查看单个结果,比孤立地查看更有意义。起初,同时查看大量实验可能会让人困惑,但随着对工具的熟悉,你会更得心应手,更容易聚焦于所需信息。

不同的实验风格会导致不同的工作流,但一个好的习惯是记录所有你可能关心的指标,用几个对你有意义的一致标签来标记实验,并添加注释。养成这些习惯能让后续工作更有条理。

TensorBoard 是分析训练过程的绝佳工具,有助于理解实验。例如,你可以使用 TensorBoard 回调来记录指标,并在每个训练周期(Epoch)结束时记录混淆矩阵。

# 示例:在 Keras 中使用 TensorBoard 回调
tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1)
model.fit(x_train, y_train, epochs=5, callbacks=[tensorboard_callback])

当展示结果时,你能清晰地了解模型的表现。例如,通过检查混淆矩阵,默认仪表板会显示最后一步或最后一个周期的图像摘要。你可以使用滑块查看更早的混淆矩阵。注意矩阵如何随着训练进程发生显著变化:更深的色块沿对角线聚集,而矩阵其余部分趋向于0和白色。这意味着你的分类器随着训练在不断改进。

在模型训练过程中(而不仅仅是训练完成后)可视化结果的能力,也能为你提供对实验的深刻洞察。随着实验的进行,你会在每个结果可用时查看并开始进行比较。

协作与共享 🤝

从一开始就组织好你的实验和结果非常重要,这既能帮助你在日后回顾时理解自己的工作,也能帮助你的团队理解。你需要确保实验易于共享和访问,以便你和团队能够协作,尤其是在处理大型项目时。为每个实验添加标签和注释将对你和团队都有帮助,并有助于避免重复运行实验。

支持共享的工具能提供很大帮助。例如,使用 Neptune AI 提供的实验管理工具,你可以发送一个链接来共享实验比较视图。这使得你和团队可以轻松跟踪和审查进度、讨论问题并激发新想法。

像 Vertex AI TensorBoard 这类基于云的工具也能提供显著优势。首先,与许多基础设施决策一样,使用托管服务在安全、隐私和合规性方面具有重要优势。但最重要的功能之一是拥有一个持久、可共享的仪表板链接,你可以与团队分享,而无需担心其设置和维护。拥有项目中所有实验的可搜索列表也非常有用。

这类工具比电子表格和笔记是巨大的进步和帮助。

从实验到项目目标 🎯

然而,你可以通过创造性的迭代将机器学习项目提升到新的水平。在每个项目中,都有一个制定业务规范的阶段,通常包括时间表、预算和项目目标。目标通常是一组关键绩效指标(KPIs)、业务指标,或者如果你非常幸运的话,是实际的机器学习指标。

你和你的团队应该选择与项目一致的、你认为可能实现的业务目标,并首先定义一个基线方法。实现你的基线并评估它,以获得第一组指标。

你通常可以从这些最初的基线结果中学到很多。它们可能接近你的目标,这表明这可能是一个简单的问题。或者你的结果可能相差甚远,以至于你会开始怀疑数据中预测信号的强度,并开始考虑更复杂的建模方法。

不要忘记,尽管人们倾向于关注建模指标(不幸的是,许多工具也聚焦于此),但既然你从事的是生产级机器学习,你还需要满足业务在延迟、成本、公平性、隐私、GDPR 等方面的目标。

总结

本节课中,我们一起学习了实验跟踪在机器学习项目中的核心作用。我们了解到,为了有效管理实验,需要对代码、数据和超参数进行系统性的版本控制。我们介绍了一系列数据版本控制和实验跟踪工具(如 Neptune, DVC, TensorBoard),并探讨了如何利用它们记录指标、可视化结果(如混淆矩阵)以及促进团队协作。最后,我们强调实验的最终目的是服务于业务目标,因此在关注模型性能指标的同时,也必须考虑延迟、成本、公平性等生产环境约束。良好的实验跟踪实践是连接模型开发与成功部署的桥梁。

146:MLOps简介 🚀

在本节课中,我们将要学习机器学习运维(MLOps)的基本概念。我们将探讨数据科学家与软件工程师角色的差异,理解将机器学习模型投入生产环境所面临的挑战,并介绍MLOps如何借鉴DevOps的理念来构建一套系统化的工程实践,以管理机器学习系统的整个生命周期。


数据科学家与软件工程师的角色差异

上一节我们概述了MLOps的背景,本节中我们来看看构建机器学习系统的两个核心角色:数据科学家和软件工程师。理解他们的不同关注点,有助于我们明白为什么生产级机器学习需要两者协作。

  • 数据科学家:通常专注于固定数据集,在笔记本中进行原型设计,主要目标是优化模型指标(如准确率)。他们是建模和特征工程方面的专家,但模型大小、成本、延迟和公平性等问题往往不是其工作的核心。
  • 软件工程师:更专注于构建产品。成本、性能、稳定性、可扩展性、可维护性和项目进度对他们至关重要。他们非常关注客户满意度、基础设施需求(如可扩展性)、质量保证、测试以及错误检测与缓解,并对安全性、可靠性和公平性有深刻认识。然而,他们通常将产品视为基本静态的,变化主要源于错误修复或新功能。

机器学习成为核心能力

随着机器学习在解决复杂现实问题、推动行业转型和创造价值方面日益成为核心能力,将模型投入生产的需求变得空前强烈。当前,应用机器学习的要素(如大型数据集、按需计算资源、强大的GPU/TPU加速器)已变得触手可及。计算机视觉、自然语言理解和推荐系统等领域的研究进展迅速,市场对应用机器学习提供新功能的需求也在增长。因此,许多企业已开始投资数据科学团队和机器学习能力,以开发能为客户带来商业价值的预测模型。

这一切推动了面向产品的机器学习工程实践的发展,而这正是MLOps发展的基础。


当前机器学习工作流面临的挑战

然而,当前的机器学习工作流面临诸多问题,促使我们越来越关注如何改进它。有趣的是,软件工程在不久之前也面临过类似处境。

以下是当前影响机器学习项目的一些主要问题:

  • 部署缓慢:许多团队在训练好模型后,需要数月时间才能将其部署到生产环境。这种缓慢的上市速度可能意味着错失机会,或部署已经性能衰退的模型。
  • 缺乏追踪与可复现性:传统数据科学项目缺乏追踪,存在手动记录、模型不可复现、数据缺乏溯源等问题。
  • 协作工具与流程缺失:不同团队之间普遍缺乏良好的协作工具和流程。
  • 生产环境监控缺位:模型一旦部署到生产环境,通常缺乏有效的监控。

从DevOps到MLOps

为了解决上述挑战,我们可以借鉴软件工程领域的成熟实践——DevOps。DevOps是一门专注于开发和管理软件系统的工程学科,它提供了减少开发周期、提高部署速度、确保高质量软件可靠发布等潜在益处。

类似于DevOps,MLOps是一种旨在统一机器学习系统开发(Dev)与机器学习系统运维(Ops)的机器学习工程文化与实践

然而,机器学习系统对DevOps的核心原则提出了独特挑战:

  • 持续集成(CI):对机器学习而言,这不仅意味着测试和验证代码与组件,还包括对数据、数据模式和模型进行同样的操作。
  • 持续交付(CD):不仅仅是部署单个软件或服务,而是部署一个自动将模型部署到预测服务的机器学习流水线系统

随着机器学习从研究走向工程,软件工程、DevOps和机器学习需要融合,形成MLOps。这带来了对新型自动化技术的需求,包括:

  • 持续训练(CT):这是机器学习系统独有的新特性,能够自动为测试和服务重新训练模型。

一旦模型进入生产环境,通过持续监控来捕获错误、监控推理数据和性能指标就变得至关重要。


机器学习解决方案的生命周期

现在,让我们考虑一个机器学习解决方案生命周期的主要阶段。

通常,数据科学家或机器学习工程师会从整理数据和开发机器学习模型开始,通过不断实验直到获得符合目标的结果。之后,通常会着手建立持续训练的流水线(除非在实验和模型开发阶段就已经使用了流水线结构,这值得鼓励)。

接着转向模型部署,这涉及更多生产环境和流程中的运维与基础设施方面。然后是持续监控你的模型、系统以及来自传入请求的数据。这些传入请求的数据将成为进一步实验和持续训练的基础。

因此,当你从持续训练过渡到模型部署时,任务演变为传统上由DevOps工程师负责的范畴。这意味着你需要一位理解机器学习部署和监控的DevOps工程师。


MLOps的核心能力与实践

现在,让我们转向数据科学家和运维专业人员之间协作与沟通的新实践,即MLOps。

MLOps提供的能力将帮助你构建、部署和管理对确保业务流程完整性至关重要的机器学习模型。它通过管理机器学习生命周期,提供了一种将模型从开发环境迁移到生产环境的一致且可靠的方法。

以下是MLOps平台通常提供的关键能力:

  • 模型版本管理与迭代:模型通常需要迭代和版本控制,以应对不断出现的新需求。模型会根据进一步的训练或更接近当前现实的真实世界数据而变化。MLOps包括按需创建模型版本和维护模型版本历史。
  • 管理模型衰退:由于真实世界及其数据持续变化,管理模型性能衰退至关重要。通过MLOps,你可以持续监控和管理模型结果,确保准确性、性能及其他目标和关键要求保持在可接受水平。
  • 审计、合规与治理:MLOps平台通常提供审计合规性、访问控制、治理、测试验证以及访问日志变更的能力。记录的信息可包括与访问控制相关的细节,例如谁发布了模型、修改的原因以及模型何时被部署或在生产中使用。
  • 模型安全:你需要保护模型免受攻击和未经授权的访问。MLOps解决方案可以提供一些功能,以防止模型被感染的数据破坏、因拒绝服务攻击而变得不可用或被未经授权的用户不当访问。
  • 模型发现与共享:确保模型安全、可信且准备就绪后,建立一个能让团队轻松发现模型的平台是很好的实践。MLOps可以通过为已生成的模型提供模型目录以及可搜索的模型市场来实现这一点。这些模型发现解决方案将提供信息来追踪特定模型的数据起源、重要性、模型架构和历史以及其他元数据。

总结

本节课中,我们一起学习了MLOps的基本概念。我们了解了数据科学家与软件工程师角色的不同侧重点,认识到将机器学习模型投入生产所面临的独特挑战(如部署缓慢、可复现性差、缺乏监控)。我们探讨了MLOps如何借鉴并扩展DevOps的理念,引入了持续集成、持续交付、持续训练和持续监控等实践,以系统化管理机器学习模型从开发到部署、再到运维的完整生命周期。最后,我们介绍了MLOps平台提供的核心能力,包括模型版本管理、性能衰退监控、安全合规保障以及模型发现共享,这些是构建可靠、高效且可维护的生产级机器学习系统的关键。

147:MLOps 成熟度级别 0 🚦

在本节课中,我们将学习 MLOps 流程如何随着团队经验的增长而演进和成熟。我们将重点介绍 MLOps 成熟度的基础级别——级别 0,并探讨其特点、局限性以及向更高级别演进的需求。

概述

MLOps 流程的成熟度根本上由数据、建模、部署和维护系统的自动化水平决定。随着成熟度的提高,训练和部署新模型的可用速度也会随之提升。MLOps 团队的目标是将机器学习模型自动训练和部署到核心软件系统中,并提供稳健且全面的监控。理想情况下,这意味着以尽可能少的人工干预来自动化完整的机器学习工作流。

上一节我们介绍了 MLOps 的基本目标,本节中我们来看看其成熟度模型中的初始级别。

MLOps 级别 0:手动流程

许多团队拥有能够构建先进模型的数据科学家和机器学习研究员,但他们构建和部署机器学习模型的流程完全是手动的。这被认为是成熟度的基础级别,即级别 0

该流程在很大程度上由脚本或 Notebook 驱动,每个训练步骤都是手动的,包括数据分析、数据准备、模型训练和验证。它需要手动执行每个步骤,并手动从一个步骤过渡到另一个步骤。这个过程通常由实验性代码驱动,这些代码由数据科学家在 Notebook 中交互式地编写和执行,直到产生一个可用的模型。

这造成了机器学习团队与运维团队之间的脱节,并为潜在的训练-服务偏差敞开了大门。

为了更好地理解这里的情况,我们假设数据科学家将一个训练好的模型移交给工程团队,以便在他们的基础设施上部署以进行服务或批量预测。这种形式的手动交接可能包括将训练好的模型放在某个文件系统中、将模型对象签入代码仓库,或将其上传到模型注册表。然后,部署模型的工程师需要使所需的输入特征在生产环境中可用(可能用于低延迟服务),这可能导致训练-服务偏差。

以下是级别 0 流程的主要特征:

  • 模型变更频率低:级别 0 流程假设你的数据科学团队管理着少数不经常变更的模型。变更可能源于模型实现的修改,或使用新数据重新训练模型,或两者兼有。新模型版本可能每年只部署几次。
  • 缺乏持续集成与测试:由于代码变更较少,持续集成甚至单元测试通常被完全忽略。代码测试通常是 Notebook 或脚本执行的一部分。
  • 实验代码管理:实现实验步骤的脚本和 Notebook 通常进行版本控制。它们会产生诸如训练好的模型、评估指标和可视化结果等工件。
  • 缺乏持续部署:因为需要部署的模型版本不多,所以甚至不会考虑持续部署。
  • 仅部署预测服务:级别 0 流程只关心将训练好的模型部署为预测服务(例如,一个带有 REST API 的微服务),而不是部署整个机器学习系统。
  • 缺乏预测跟踪:在此级别,你不会跟踪或记录模型的预测和行动,而这些是检测模型性能下降和其他模型行为漂移所必需的。

MLOps 级别 0 在许多刚开始将机器学习应用于其用例的企业中很常见。当模型很少更改或重新训练时,这种手动、数据科学驱动的流程可能就足够了。

级别 0 的挑战与演进需求

然而在实践中,模型部署到现实世界时经常出现问题。模型无法适应环境动态的变化或描述环境的数据的变化。

为了应对这些挑战并保持模型在生产环境中的准确性,你需要解决以下问题:

首先,需要解决缺乏主动性能监控的问题。主动监控你的模型可以让你检测性能下降和模型衰退。它作为一个信号,提示是时候进行新的实验并使用新数据重新训练模型了。

其次,是模型持续适应最新趋势的问题。为了克服这一点,你需要经常使用最新的数据重新训练你的生产模型,以捕捉不断演变和新兴的模式。例如,如果你的应用程序使用机器学习推荐时尚产品,其推荐应适应最新的趋势和产品。当然,这要求你拥有新数据并以某种方式为其打标签。而在级别 0,这些通常是手动过程。

总结

本节课中,我们一起学习了 MLOps 成熟度模型的级别 0。我们了解到这是一个以手动、脚本驱动为主的流程,适用于模型变更不频繁的场景。其核心特点包括缺乏自动化、监控和持续部署实践。然而,为了应对现实世界中模型性能衰退和数据漂移的挑战,向更自动化、可监控和可重复的 MLOps 更高级别演进是必要的。下一节,我们将探讨如何通过引入自动化来提升 MLOps 的成熟度。

148:MLOps 级别 1 与 2 🚀

在本节课中,我们将学习 MLOps 的级别 1 和级别 2。这两个级别主要关注如何通过实现流水线自动化,来提升机器学习工作流程的效率和可靠性。我们将了解自动化训练流水线的关键组件、数据与模型验证的重要性,以及如何构建一个从开发到生产的统一部署流程。


流水线自动化概述

上一节我们了解了 MLOps 的基础概念。本节中,我们来看看如何通过自动化流水线来实现持续训练和持续交付。

级别 1 的一个核心目标是:通过自动化训练流水线,实现模型的持续训练。这使得你可以持续地将训练好的模型交付给预测服务。

为了自动化使用新数据在生产环境中重新训练模型的过程,你需要在流水线中引入自动化数据验证模型验证步骤,以及流水线触发器元数据管理

机器学习工作流需要具备可重复的训练能力,因此让我们看看流水线自动化的一些特点。

请注意,由于实验步骤是经过编排的,步骤之间的转换是自动化的。这使你能够快速迭代实验,并更容易地将整个流水线迁移到生产环境。


多环境架构

现在,让我们扩展这个架构,使其包含不同的环境:开发、测试、预生产和生产。请注意,这里展示的架构是典型的,但不同团队会根据需求和基础设施选择以不同方式实现它。

在这个架构中,模型会基于实时流水线触发器(稍后讨论)使用新数据自动重新训练。在开发或实验环境中使用的流水线实现,同样会用于预生产和生产环境,这是统一 DevOps 工作的 MLOps 实践的一个关键方面。

为了构建机器学习流水线,组件需要具备可重用性可组合性,并且可能需要在多个流水线之间可共享。因此,虽然探索性数据分析代码仍可存在于 Notebook 中,但组件的源代码必须模块化。

此外,组件最好进行容器化。这样做是为了将执行环境与自定义代码的运行时解耦,并确保代码在开发和生产环境之间具有可重现性。这实质上隔离了流水线中的每个组件,使它们拥有自己的运行时环境版本,并可以使用不同的语言和库。

请注意,如果探索性数据分析是使用生产组件和生产风格的流水线完成的,将极大地简化该代码向生产的过渡。


生产中的持续交付

生产中的机器学习流水线会持续地将基于新数据训练出的新模型交付给预测服务。

请注意,当我说“持续”时,指的是一个自动化过程,新模型可能按计划或基于触发器进行交付。模型部署步骤是自动化的,它将训练好并经过验证的模型交付给预测服务,用于在线或批量预测。

在级别 0 中,你只是简单地将训练好的模型部署到生产环境。但在这里,你部署的是整个训练流水线,它会自动且循环地运行,以将训练好的模型作为预测服务提供。

当你将流水线部署到生产环境时,一个或多个触发器会自动执行该流水线。流水线期望获得新的实时数据,以生成基于新数据训练的新模型版本。

因此,生产流水线中需要自动化数据验证模型验证步骤。


数据验证

首先,让我们谈谈为什么在模型训练之前需要进行数据验证,以决定是否应该重新训练模型或停止流水线的执行。

这个决定只有在数据被认为是有效的情况下才会自动做出。例如,数据模式偏移被认为是输入数据中的异常,这意味着下游流水线步骤(包括数据处理和模型训练)接收到的数据不符合预期的模式。在这种情况下,你应该停止流水线并发出通知,以便团队进行调查。团队可能会发布修复程序或更新流水线以处理这些模式变化。

模式偏移包括:接收到意外的特征、未接收到所有预期特征,或接收到具有意外值的特征。

此外还有数据值偏移,即数据的统计属性发生显著变化,你需要触发模型的重新训练以捕捉这些变化。


模型验证

模型验证是另一个步骤,在你使用新数据成功训练模型后运行。在这里,你在将模型提升到生产环境之前对其进行评估和验证。

这个离线模型验证步骤可能首先涉及:使用训练好的模型在测试数据集上生成评估指标值,以评估模型的预测质量。

下一步是将新训练模型产生的评估指标值与当前模型(例如,当前的生产模型或基线模型,或任何满足业务要求的模型)进行比较。在这里,你要确保新模型在性能上优于当前模型,然后再将其提升到生产环境。

同时,你需要确保模型在数据的各个部分或切片上的性能是一致的。你新训练的客户流失模型可能在整体预测准确率上优于之前的模型,但每个客户区域的准确率值可能存在很大差异。

最后,在最终部署模型之前,你还需要考虑基础设施兼容性以及与预测服务 API 的一致性等因素。换句话说,新模型是否能在当前基础设施上实际运行。

除了离线模型验证,新部署的模型还会在金丝雀部署A/B 测试设置中进行在线模型验证。在过渡到为在线流量提供预测服务期间,你将在后续课程中了解更多相关内容。


特征存储

级别 1 MLOps 的一个可选附加组件是特征存储

特征存储是一个集中式存储库,用于标准化训练和服务的特征定义、存储和访问。理想情况下,特征存储将为特征值提供高吞吐量批量服务和低延迟实时服务的 API,并同时支持训练和服务工作负载。

特征存储通过多种方式帮助你。首先,它让你能够发现和重用可用的特征集,而不是重新创建相同或相似的特征集。通过维护特征和相关元数据,可以避免出现定义不同的相似特征。

此外,你可以从特征存储中获取最新的特征值,并通过将特征存储用作实验、持续训练和在线服务的数据源,来避免训练-服务偏移。这种方法确保了用于训练的特征与在服务期间使用的特征相同。

例如,在实验方面,数据科学家可以从特征存储中获取离线数据来运行实验。对于持续训练,自动化训练流水线可以获取一批最新的数据特征值。对于在线预测,预测服务可以获取特征值,如客户人口统计特征、产品特征和当前会话聚合特征。


元数据存储

另一个关键组件是元数据存储,其中记录了每次流水线执行的信息,以帮助进行数据和工件溯源、可重现性以及比较。它还有助于你调试错误和异常。

每次执行流水线时,元数据存储都会跟踪诸如执行的流水线和组件版本、开始和结束时间与日期、流水线完成每个步骤所需的时间、每个步骤的输入和输出工件等信息。

基本上,这意味着你可以依赖指向流水线每个步骤产生的工件的指针(例如,准备好的数据的位置、验证异常、计算出的统计数据等),以便在中断时无缝恢复执行。跟踪这些中间输出有助于你从最近的步骤恢复流水线,如果流水线因某个步骤失败而停止,则无需重新启动整个流水线。


MLOps 级别 2

事实上,在 MLOps 最佳实践的当前发展阶段,级别 2 在某种程度上仍然是推测性的。下图展示了当前的一种架构,其重点是实现生产环境中流水线的快速可靠更新

这需要健壮的、自动化的 CI/CD,以使你的数据科学家和机器学习工程师能够快速探索关于特征工程、模型架构和超参数的新想法。他们可以实现这些想法,并自动构建、测试和部署新的流水线组件到目标环境。

这种 MLOps 设置包括源代码控制、测试和构建服务、部署服务、模型注册表、特征存储、元数据存储和流水线编排器等组件。由于内容较多,让我们以简化且更易理解的形式,看看机器学习持续集成和持续交付(CI/CD)流水线的不同阶段。


级别 2 生命周期总结

总而言之,让我们用这张图来理解级别 2 生命周期的步骤。

首先,是实验与开发阶段。在这里,你迭代地尝试新算法和新模型,实验步骤是经过编排的。此阶段的输出是机器学习流水线步骤的源代码,然后被推送到源代码仓库。

接下来是用于训练流水线本身CI/CD 阶段。在这里,你构建源代码并运行各种测试。此阶段的输出是流水线实体,如软件包、可执行文件和将在后续阶段部署的工件。

此阶段的输出是一个部署了模型新实现的流水线。然后,你在这里训练模型。流水线会根据计划或响应触发器在生产环境中自动执行。此阶段的输出是一个训练好的模型,并被推送到模型注册表。

一旦模型训练完成,流水线的目标现在是通过持续交付来部署模型。你通过将训练好的模型作为预测服务来提供预测。此阶段的输出是一个已部署的模型预测服务。

最后,一旦你的所有模型都经过训练和部署,监控服务的角色就是基于实时数据收集模型性能的统计数据。此阶段的输出是从服务基础设施运行中收集到日志中的数据,包括预测请求数据,这些数据将用于形成新的数据集并重新训练你的模型。


课程总结

在本节课中,我们一起学习了 MLOps 的级别 1 和级别 2。我们探讨了如何通过流水线自动化实现模型的持续训练和交付,深入了解了数据验证模型验证在生产流水线中的关键作用,并介绍了特征存储元数据存储等重要组件。最后,我们展望了级别 2 的愿景,即通过健壮的 CI/CD 流程实现生产流水线的快速可靠更新。掌握这些概念是构建高效、可靠机器学习系统的基石。

149:20_为编排工作流开发组件 🧩

在本节课中,我们将学习如何使用 TFX 框架来开发机器学习训练流水线,并重点探讨如何通过创建自定义组件来满足特定的工作流需求。


MLOps 基础设施的一个关键部分是训练流水线。

现在,我们来看看如何使用 TFX 开发训练流水线,包括通过自定义组件来调整流水线以满足需求的方法。

TFX 是一个开源框架,可用于创建机器学习流水线。TFX 使你能够在多种执行环境中实现模型训练工作流,包括像 Kubernetes 这样的容器化环境。

TFX 流水线将你的工作流组织成一系列组件,每个组件执行机器学习工作流中的一个步骤。TFX 标准组件提供了现成的功能,帮助你轻松开始构建机器学习工作流。你也可以在工作流中包含自定义组件,包括创建在容器中运行的组件,这些组件可以使用任何能在容器中运行的语言或库,例如使用 R 进行数据分析。

自定义组件允许你通过创建量身定制的组件来扩展机器学习工作流,例如数据增强、上采样或下采样、异常检测,或与外部系统(如用于警报和监控的帮助台等)对接。

一个入门级或“Hello World”级别的 TFX 流水线通常如下图所示。图中橙色和绿色的部分就是组件。在这个例子中,这些是 TFX 开箱即用的标准组件,但它们也可以是你创建的自定义组件。橙色组件构成训练流水线,绿色组件构成用于批量推理的推理流水线。

因此,通过混合使用标准组件和自定义组件,你可以构建一个满足需求、同时又能利用 TFX 标准组件内置最佳实践的机器学习工作流。

现在,让我们看看 TFX 组件是如何组合在一起的。它们本质上由组件规范和一个执行器类组成,并打包在一个组件类中。

  • 规范定义了组件的输入和输出契约。这个契约指定了组件的输入和输出工件以及用于组件执行的参数。
  • 执行器类提供了组件执行工作的实现。它是组件的主要代码。
  • 最后,组件类将组件规范与执行器结合起来,作为 TFX 流水线中的一个组件使用。

请注意,这是 TFX 标准组件和完全自定义风格组件所使用的实现风格。但创建自定义组件还有其他两种风格,我们接下来会讨论。

当流水线运行一个 TFX 组件时,该组件的执行分为三个阶段:

  1. 首先,驱动程序使用组件规范从元数据存储中检索所需的工件,并将其传递给组件。
  2. 接着,执行器执行组件的工作。
  3. 最后,发布器使用组件规范和执行器的结果,将组件的输出存储到元数据存储中。

大多数自定义组件实现不需要你自定义驱动程序或发布器。通常,只有当你想要改变流水线组件与元数据存储之间的交互时,才需要修改驱动程序和发布器。如果你只想更改组件的输入、输出或参数,则只需修改组件规范。

自定义组件有三种类型:基于 Python 函数的自定义组件、基于容器的自定义组件和完全自定义组件。完全自定义组件在前面的幻灯片中已经讨论过,它允许你通过定义组件规范、执行器和组件接口类来构建组件。这种方法允许你重用和扩展现有标准组件以满足需求。

基于 Python 函数的组件最容易构建,比基于容器的组件或完全自定义组件更简单。它们只需要一个带有装饰器和类型提示的 Python 函数作为执行器。另一方面,基于容器的组件提供了将任何语言编写的代码集成到流水线中的灵活性,前提是你能在 Docker 容器中执行该代码。要创建基于容器的组件,你需要创建一个类似于 Dockerfile 的组件定义,并调用一个包装函数来实例化它。

接下来,我们将学习如何利用每种自定义组件类型。


基于 Python 函数的组件风格让你能够轻松创建 TFX 自定义组件,省去了定义组件规范类、执行器类和组件接口类的麻烦。在这种风格中,你编写一个带有装饰器和类型提示的函数。类型提示描述了组件的输入工件、输出工件和参数。

用这种风格为简单的模型验证编写自定义组件非常直接,如下例所示。组件规范在 Python 函数的参数中使用类型注解来定义,描述参数是输入工件、输出工件还是参数。函数体定义了组件的执行器。组件接口通过向函数添加 @component 装饰器来定义。

通过用 @component 装饰器装饰你的函数,并用类型注解定义函数参数,你可以创建一个组件,而无需构建组件规范、执行器和组件接口的复杂性。

接下来,我们看看如何创建基于容器的组件。

基于容器的组件由容器化的命令行程序支持,在某些方面类似于创建 Dockerfile。要创建一个,你需要指定一个包含组件依赖项的 Docker 容器镜像。然后,你调用 create_container_component 函数并传递组件定义,包括组件的输入、输出和参数。配置的其他部分包括容器镜像名称和可选的镜像标签。最后,对于组件的主体,你有 command 参数,它定义了容器的入口点命令行。与 Dockerfile 一样,除非你在命令行中指定,否则它不会在 shell 内执行。命令行可以使用占位符对象,这些对象在编译时会被输入、输出或参数替换。占位符对象可以从 tfx.dsl.component.experimental.placeholders 导入。

在这个例子中,组件代码使用 gsutil 将数据上传到 Google Cloud Storage,因此容器镜像需要安装并配置好 gsutil,这是一个依赖项。

这种方法比构建基于 Python 函数的组件更复杂,因为它需要将你的代码打包为容器镜像。这种方法最适合在流水线中包含非 Python 代码,或者为具有复杂运行时环境或依赖项的 Python 构建组件。


回到完全自定义组件,这种风格允许你通过直接定义组件规范、执行器类和组件类来构建组件。这种方法也允许你重用和扩展现有标准组件或其他预先存在的组件以满足需求。例如,如果一个现有组件(可能是自定义组件)定义的输入和输出与你正在开发的自定义组件相同,你可以简单地覆盖现有组件的执行器类。这意味着你可以重用组件规范,并实现一个从现有组件派生的新执行器。这样,你可以重用现有组件内置的功能,只实现所需的功能。

这种组件风格的主要用途是扩展现有组件。否则,如果你不需要容器化组件,你可能应该使用 Python 函数风格。然而,深入理解这种完全自定义组件的风格将有助于你更好地理解所有 TFX 组件,所以让我们更仔细地看看如何创建一个完全自定义组件。


开发一个完全自定义组件首先需要你定义一个组件规范,其中包含新组件的一组输入和输出工件规范。其次,你必须定义新组件所需的任何非工件的执行参数。

因此,组件规范有三个主要部分:输入、输出和参数。输入和输出被包装在通道中,本质上是输入和输出工件的类型化参数字典。参数是一个额外的执行参数字典,这些参数会传递给执行器,并且不是元数据工件。

接下来,你需要创建一个执行器类。基本上,这是 base_executor.BaseExecutor 的一个子类,并重写其 Do 函数。在 Do 函数中,会传入参数 input_dictoutput_dictexec_properties,它们映射到组件规范中定义的输入、输出和参数。对于 exec_properties,可以直接通过字典查找获取值。

继续实现用于处理 input_dictoutput_dict 中工件的执行器,TFX 的 artifact_utils 类中提供了方便的函数,可用于获取工件的实例或 URI。

现在最复杂的部分完成了,下一步是将这些部分组装成一个组件类,以便该组件可以在流水线中使用。有几个步骤:

  1. 首先,你需要使组件类成为 base_component.BaseComponent 的子类(或者,如果你要扩展现有组件,则是其他组件的子类)。
  2. 接下来,你将类变量 SPEC_CLASSEXECUTOR_SPEC 分别分配给你刚刚创建的组件规范类和执行器类。
  3. 完成自定义组件的最后一步是实现 __init__ 函数来初始化组件。在这里,你使用函数的参数来定义构造函数,以构建组件规范类的一个实例,并使用该值以及一个可选的名称调用父类的 __init__ 函数。

当创建组件实例时,将调用基类 base_component.BaseComponent 中的类型检查逻辑,以确保传入的参数与组件规范类中定义的类型兼容。

最后一步是将新的自定义组件插入到 TFX 流水线中。除了添加新组件的实例外,你还需要将其与上游和下游组件连接起来。通常,你可以通过在新组件中引用上游组件的输出,并在下游组件中引用新组件的输出来实现。另外,需要记住的一点是,在构建流水线时,需要将新组件实例添加到组件的列表中。


在本节课中,我们一起学习了 TFX 流水线的基本结构,探讨了三种创建自定义组件的方法:基于 Python 函数的组件、基于容器的组件和完全自定义组件。我们了解了每种方法的适用场景和实现要点,特别是详细剖析了完全自定义组件的开发步骤。掌握这些知识将使你能够灵活地构建和扩展机器学习工作流,以满足各种生产需求。

150:模型版本管理 📚

在本节课中,我们将要学习机器学习运维(MLOps)中的一个核心主题:模型版本管理。我们将探讨版本控制的重要性、面临的挑战,并介绍一种实用的版本命名方案。此外,我们还将了解模型谱系和模型注册表的概念及其在生产工作流中的作用。


为什么版本控制至关重要?🤔

在正常的软件开发中,尤其是团队协作时,组织依赖版本控制软件来帮助团队管理和控制代码的变更。

想象一下如果没有版本控制会怎样。你将如何让多位开发者保持同步?出现问题如何回滚?如何进行持续集成?

与软件开发类似,在开发模型时,你同样有这些需求,甚至更多。生成模型是一个迭代过程。在开发期间,你通常会生成多个模型,并相互比较以评估每个模型的性能。

每个模型版本可能拥有不同的代码、数据和配置。你需要跟踪所有这些信息才能正确地复现结果。这就是模型版本管理至关重要的地方。

版本控制将提升从个人开发者到团队乃至整个组织等不同层面的协作效率。


如何为模型设定版本?🔢

首先,让我们思考如何为软件设定版本。

在大多数情况下,你使用三个数字的组合来为软件设定版本。这些数字分别是主版本号、次版本号和补丁版本号。

  • 主版本号:通常在做出不兼容的API更改时递增。
  • 次版本号:在以向后兼容的方式添加功能时递增。
  • 补丁版本号:在进行向后兼容的错误修复时递增。

那么,你能对模型采用类似的方法吗?截至目前,行业内还没有一个被广泛接受的、统一的模型版本标准。

不同的公司采用了各自的版本命名惯例。作为其组织内的开发者,你需要了解他们如何为模型设定版本。


一种实用的版本命名方案

以下是我建议的一种可能方案,它易于理解,并且与常规的软件版本命名保持一致。

我们使用三个数字的组合,并将其表示为主版本、次版本和流水线版本。听起来很熟悉,对吗?

  • 主版本:当发生不兼容的数据变更时递增,例如模式变更或目标变量变更,这些变更可能导致模型在用于预测时与其先前版本不兼容。
  • 次版本:当你确信已经改进或增强了模型的输出时递增。
  • 流水线版本:对应于训练流水线的更新,但它不一定改进甚至改变模型本身。

其他版本命名风格包括任意分组、黑盒功能模型和流水线执行版本控制等,但这里不做讨论。相反,我想重点介绍如何检索旧模型、利用模型谱系,以及使用模型注册表来简化生产工作流。


模型谱系与检索

测试一种版本命名风格的一种方法是问:你能利用模型框架的能力来检索先前训练过的模型吗?

你可能直觉上认为,对于ML框架来说,要检索旧模型,框架内部必须通过某种版本控制技术对模型进行版本管理。

不同的ML框架可能使用不同的技术来检索先前训练过的模型。其中一种技术是利用模型谱系。

模型谱系是导致训练模型产生的各工件之间的一组关系。要构建模型工件,你必须能够跟踪构建它们的代码以及数据,包括模型训练和测试时使用的预处理操作。

像TFX这样的ML编排框架会存储这种模型谱系,原因有很多,包括在必要时重新创建模型的不同版本。

请注意,模型谱系通常只包含那些作为模型训练一部分的工件和操作。训练后的工件和操作通常不属于谱系的一部分。


模型注册表:中央存储库

现在让我们看看模型注册表。模型注册表是用于存储已训练模型的中央存储库。

模型注册表提供了一个API,用于在整个模型开发生命周期中管理已训练的模型。模型注册表对于支持模型发现、模型理解和模型重用至关重要,尤其是在拥有数百或数千个模型的大规模环境中。

因此,模型注册表已成为许多开源和商业ML平台不可或缺的一部分。


注册表中的元数据

接下来,我们看看大多数开源和商业模型注册表中存储的元数据。

元数据通常包括可用的不同模型版本。一些模型注册表为序列化的模型工件提供存储,以提高模型在注册表中的可发现性。

存储一些自由文本注释以及模型的其他结构化或可搜索属性非常重要。为了促进模型谱系,注册表有时会包含指向其他ML工件和元数据存储的链接。


模型注册表的优势

模型注册表是非常有用的工具。

  • 促进模型搜索与发现:模型注册表促进了组织内的模型搜索和可发现性,这有助于提高团队对模型的理解。
  • 加强治理:模型注册表可以帮助强制执行上传模型时需要遵循的一套审批指南,从而有助于改善治理。
  • 促进协作:通过与团队共享模型,你提高了同事之间协作的机会。
  • 简化部署:模型注册表还可以帮助简化部署。模型注册表甚至可以提供一个用于持续评估、监控、暂存和升级的平台。

现有的模型注册表示例

以下是一些当前可用的模型注册表列表,你可以看到有不少选择。每个注册表的功能集都有些不同,这里不做比较,只是为了让你了解一些现有的产品。

例如,有:

  • Azure ML Model Registry
  • SAS Model Manager
  • MLflow Model Registry
  • Google AI Platform
  • Althia

总结

在本节课中,我们一起学习了模型版本管理。我们探讨了版本控制对MLOps的重要性,并提出了一种结合主版本、次版本和流水线版本的实用命名方案。我们还介绍了模型谱系的概念,它记录了模型构建的完整链路。最后,我们了解了模型注册表作为中央存储库的关键作用,它能促进模型的发现、理解、协作和治理,是简化生产工作流的重要工具。

151:22_持续交付 🚀

在本节课中,我们将学习在成熟的MLOps流程中,如何通过持续集成(CI)持续交付(CD) 构建一个稳健的模型部署流程。这对于管理多个模型,特别是当模型预测作为在线应用的一部分直接面向用户时,至关重要。


上一节我们介绍了稳健部署的重要性,本节中我们来看看实现它的核心流程:持续集成与持续交付。

持续集成(CI):确保代码质量

在部署模型之前,必须确保代码能够正常工作。这需要通过全面的单元测试来确定。持续集成(CI)自动化了这一过程。

每当有新代码提交或推送到源代码仓库时,CI就会被触发。它主要执行组件的构建打包测试。测试的质量取决于单元测试套件的覆盖率和质量。

如果所有测试都通过,CI会将测试通过的代码和包交付给持续交付管道。

持续交付(CD):部署到目标环境

接下来,持续交付(CD)负责将新代码和训练好的模型部署到目标环境。它确保代码和模型与目标环境兼容。对于机器学习部署,CD还应检查模型的预测服务性能,以确保新模型能够成功提供服务。

完整的持续集成与持续交付流程及基础设施被称为 CICD

CICD流程中的数据分析与模型分析

CICD流程包含两种不同形式的数据分析和模型分析。

在实验阶段,数据分析和模型分析通常是数据科学家执行的手动过程。一旦模型和代码被提升到生产训练管道,数据分析和模型分析就应该自动执行。

以下是代码提升到生产环境的关键步骤:

  1. 源代码被提交到源代码控制系统,并启动CI。
  2. CD将生产代码部署到生产训练管道,并训练模型。
  3. 训练好的模型随后被部署到在线服务环境或批量预测服务。
  4. 在服务期间,性能监控会从实时数据中收集模型的性能指标。


上一节我们概述了CICD的整体流程,本节中我们深入探讨在持续集成阶段执行的两项主要测试。

持续集成中的主要测试类型

在持续集成中,主要执行两种测试:单元测试集成测试

单元测试

单元测试用于测试每个组件,以确保它们产生正确的输出。除了遵循软件开发标准实践的代码单元测试外,为机器学习做CI时,还有两种额外的单元测试类型:

  • 数据的单元测试
  • 模型的单元测试

数据的单元测试

数据的单元测试与对原始特征进行数据验证不同。它主要关注特征工程的结果。

以下是你可以编写的数据单元测试示例:

  • 检查工程化特征是否被正确计算。
  • 检查特征是否被正确缩放或归一化。
  • 检查独热编码值是否正确。
  • 检查嵌入是否被正确生成和使用。
  • 确认列和数据的类型、范围正确,且不为空等。

模型的单元测试

建模代码也应以模块化方式编写,使其可测试。

以下是需要为建模代码编写的单元测试:

  • 测试内部函数是否以正确的形状和类型返回输出。对于数值特征,这包括测试NaN值;对于字符串特征,包括测试空字符串等。
  • 添加测试以确保准确率、错误率、AUC、ROC等指标高于你指定的性能基线。
  • 即使训练模型具有可接受的准确率,也需要针对数据切片进行测试,以确保模型对数据的关键子集也是准确的,从而避免偏见。


上一节我们讨论了标准的单元测试,本节中我们来看看针对机器学习的一些额外考虑。

机器学习单元测试的特殊考量

虽然应执行标准的代码单元测试,但对于机器学习还有一些额外的考量。这包括模拟数据(Mock Data) 的设计,这对ML单元测试尤为重要。

模拟数据应设计为覆盖你的边缘情况角落情况。这要求你思考每个特征和你的领域,并识别这些边缘和角落情况在哪里。

理想情况下,你的模拟数据应大致占据与实际数据相同的特征空间区域,但当然要稀疏得多,因为在大多数情况下,模拟数据集应远小于实际数据集。

如果你创建了良好的模拟数据和测试,就应该有良好的代码覆盖率。但为了确保万无一失,可以利用现有的库来测试和跟踪你的代码覆盖率。


上一节我们确保了代码和模型逻辑的正确性,本节中我们来看看部署前的最后一道防线。

基础设施验证:生产前的预警

基础设施验证是在将模型推送到生产环境之前的一个预警层,旨在避免模型在生产中实际服务请求时无法运行或性能低下的问题。它侧重于模型服务器二进制文件与即将部署的模型之间的兼容性。

将基础设施验证包含在你的训练管道中是一个好主意,这样在训练模型时就可以及早避免问题。你也可以将其作为CICD工作流的一部分来运行,如果你在模型训练期间没有运行它,这一点尤其重要。

基础设施验证示例

让我们看一个在训练管道中运行基础设施验证的例子。

在TFX管道中,基础设施验证器组件会获取模型,启动一个包含该模型的沙箱模型服务器,并查看它是否能成功加载并可选择性地进行查询。

如果模型行为符合预期,则它被称为“受祝福的”,并被认为已准备好部署。

基础设施验证器侧重于模型服务器二进制文件(例如TensorFlow Serving)与要部署的模型之间的兼容性。尽管名为“基础设施验证器”,但正确配置环境是用户的责任。基础设施验证器仅与用户配置环境中的模型服务器交互,以查看其是否按预期工作。正确配置此环境将确保你的基础设施验证通过或失败,能够指示模型在生产服务环境中是否可服务。


在本节课中,我们一起学习了如何通过持续集成(CI)和持续交付(CD)构建稳健的机器学习部署流程。我们探讨了CI中的单元测试(包括对数据和模型的特殊测试)、模拟数据的设计,以及部署前的基础设施验证。掌握这些实践,是确保机器学习模型能够可靠、高效地服务于生产环境的关键。

152:渐进式交付 🚀

在本节课中,我们将学习一种更高级的部署方式——渐进式交付。这是一种在持续集成和持续交付核心理念基础上发展起来的软件开发流程,旨在通过逐步推出新功能来降低风险并评估用户反馈。


什么是渐进式交付?🤔

渐进式交付建立在持续集成和持续交付的核心原则之上,本质上是对CICD的改进。它包含了许多现代软件开发流程,例如金丝雀部署、A/B测试、多臂赌博机算法和可观测性。

其核心思想是逐步推出新功能,以限制潜在的负面影响,并评估用户对新功能的反应。该流程首先将变更交付给少量、低风险的用户,然后逐步扩展到更大、风险更高的受众,从而验证结果。

渐进式交付的优势在于,它提供了诸如功能标志等控制和保障措施,以提高部署速度并降低风险。这通常能带来更快的部署速度,并为推出和所有权管理实施一个渐进的过程。


渐进式交付的常见模式 🛠️

上一节我们介绍了渐进式交付的概念,本节中我们来看看几种具体的实践模式。这些模式通常涉及同时部署多个版本,以便进行性能比较。这种做法源于软件工程,尤其适用于在线服务。每个模型执行相同的任务,以便进行比较。

以下是几种关键模式:

  • 蓝绿部署:这是渐进式交付的一种简单形式。存在两个生产服务环境(蓝环境和绿环境)。请求流经负载均衡器,该均衡器将流量导向当前活跃的环境(称为蓝环境)。同时,新版本被部署到绿环境,绿环境充当预发布环境,在此进行一系列测试以确保性能和功能。通过测试后,流量被导向绿环境部署。如果出现任何问题,流量可以切回蓝环境。这意味着部署期间没有停机时间,回滚容易,可靠性高,并且在上线前包含冒烟测试。
  • 金丝雀部署:金丝雀部署类似于蓝绿部署,但不是一次性将所有传入流量从蓝环境切换到绿环境,而是逐步切换流量。随着流量开始使用新版本,会监控新版本的性能。如有必要,可以停止并回滚部署,而不会造成停机,并且用户对新版本的暴露最小。最终,所有流量都将使用新版本提供服务。
  • 在线实验:渐进式部署与在线实验密切相关。在线实验用于测试模型,以衡量其带来的实际业务结果,或尽可能测量与业务结果密切相关的数据。这是必要的,因为你在训练期间用于优化模型的模型指标,通常与业务目标不完全匹配。例如,考虑推荐系统。你训练模型以最大化点击率(这是你数据的标注方式)。但业务真正想要的是最大化利润。这与点击率密切相关,但并不完全匹配,因为有些点击带来的利润比其他点击更高(例如,不同产品的利润率不同)。

在线实验的具体方法 🔬

上一节提到了在线实验的重要性,本节中我们来看看两种具体的实验方法:A/B测试和多臂赌博机。

以下是A/B测试的基本流程:

  • A/B测试:这是一种简单的在线实验形式。在A/B测试中,你至少有两个不同的模型(或N个模型),通过比较它们之间的业务结果,来选择能带来最佳业务表现的模型。具体做法是将用户分成两组或N组,并将用户路由到随机选择的模型。注意:重要的是,如果用户发出多个请求,他们在整个会话期间应持续使用同一个模型。然后,你收集每个模型的结果,选择表现最好的一个。A/B测试实际上是许多科学领域广泛使用的工具,而不仅仅是机器学习。它是比较同一系统的两个变体的过程,通常通过测试变体A与变体B的响应,并得出结论哪个变体更有效。A/B测试常用于测试药物,其中一个变体是安慰剂。

一种更高级的方法是多臂赌博机。多臂赌博机方法类似于A/B测试,但使用机器学习从测试期间收集的结果中学习。随着它了解到哪些模型表现更好,它会动态地将越来越多的请求路由到胜出的模型。这意味着最终所有请求都将被路由到单个模型或一组性能相似的较小模型组。其主要好处之一是,它通过不等待测试结束来选择胜者,从而最大限度地减少低性能模型的使用。多臂赌博机方法是一种强化学习架构,它平衡了探索和利用。


更高级的上下文赌博机 🧠

多臂赌博机方法已经相当先进,但还有一种更高级的变体:上下文赌博机。

上下文赌博机算法是多臂赌博机方法的扩展,在选择“赌博机”(即模型或策略)时,你还会考虑客户的环境或请求的其他上下文信息。上下文会影响每个赌博机所关联的奖励。因此,随着上下文的变化,模型应该学会调整其赌博机的选择。

例如,考虑向不同气候地区的人们推荐服装选择。炎热气候下的客户与寒冷气候下的客户将具有非常不同的上下文。你不仅希望找到最大奖励,还希望在探索不同赌博机时减少奖励损失。在判断模型性能时,衡量奖励损失的指标称为遗憾。遗憾是最优策略的累积奖励与模型随时间累积的奖励总和之间的差值。遗憾越低,模型越好,而上下文赌博机有助于最小化遗憾。


总结 📝

本节课中我们一起学习了渐进式交付这一高级部署策略。我们从其核心概念出发,了解了它如何通过逐步推出和验证来降低风险。接着,我们探讨了蓝绿部署和金丝雀部署这两种具体模式,它们提供了可控的发布流程。然后,我们深入研究了在线实验的重要性,并介绍了A/B测试和多臂赌博机这两种评估模型业务价值的关键方法。最后,我们了解了更高级的上下文赌博机,它通过结合请求的上下文信息来进一步优化决策,最小化遗憾。

理解这些渐进式交付和实验技术,对于构建稳健、可适应且能持续提供业务价值的机器学习系统至关重要。

153:为何监控很重要 🔍

在本节课中,我们将探讨机器学习模型部署到生产环境后,为何持续监控至关重要。我们将了解监控如何帮助发现模型性能衰退、数据偏移等问题,并区分功能性监控与非功能性监控。理解这些概念是构建可靠、可持续的机器学习系统的基石。


模型部署后的持续循环 🔄

上一节我们介绍了机器学习从开发到部署的流程,本节中我们来看看部署并非终点。监控生产环境中的模型是一个持续的任务,只要模型仍在运行,就需要进行监控。

通过监控收集的数据将指导您构建下一个版本的模型,并使您意识到模型性能的变化。这是一个循环迭代的过程,需要最后一步——监控——来完成整个流程。

您应该注意,此图仅关注与模型性能直接相关的监控。但您还需要监控包含在您整个产品或服务中的系统和基础设施,例如数据库和Web服务器。这类监控仅关注产品或服务的基本运行,而非模型本身,但对用户体验至关重要。基本上,如果系统宕机,您的模型再好也无济于事。


预防胜于治疗 🛡️

本杰明·富兰克林曾写道:“一盎司的预防胜过一磅的治疗。” 在我们的场景中,您可以将同样的理念应用于预防“消防演习”——即系统性能突然变差,需要紧急修复的情况。

以下是如果不监控模型性能可能发生的几种“消防演习”:

  • 初始数据偏移:如果您的训练数据过于陈旧,即使首次部署新模型,也可能立即出现数据偏移。如果不从一开始就进行监控,您可能很容易忽视这个问题,导致新模型从一开始就不准确。
  • 模型陈旧化:正如之前讨论的,模型也会变得陈旧或不准确,因为世界在不断变化,您最初收集的训练数据可能不再反映当前状态。同样,没有监控,您不太可能意识到这个问题。
  • 负反馈循环:这是一个更复杂的问题,当您在从生产环境收集的数据上自动训练模型时会出现。如果这些数据存在任何偏见或损坏,那么基于这些数据训练的模型将表现不佳。即使对于自动化流程,监控也很重要,因为它们也可能出现问题。

两种类型的监控 📊

现在我们来区分两种主要的监控类型。

ML监控(功能性监控) 涉及密切关注模型的预测性能和服务数据的变化。这包括:

  • 模型在训练期间优化的指标
  • 服务数据中每个特征的分布和特性

系统监控(非功能性监控) 指的是监控整个生产系统的性能、系统状态和服务系统的可靠性。这包括:

  • 每秒查询数。
  • 故障率。
  • 延迟。
  • 资源利用率等。

ML监控为何与众不同?🤔

您可能会问,为什么ML监控与软件监控不同?与纯软件系统不同,在ML系统中需要考虑两个额外的组件:数据模型

与传统软件系统不同,ML系统的准确性取决于模型在多大程度上反映了它所要建模的世界,而这又取决于用于训练的数据以及服务请求时接收到的数据。这不仅仅是监控系统故障(如段错误、内存不足或网络问题)那么简单。模型和数据也需要额外的、非常专业的监控。

由于纠缠配置两个方面,ML系统中的代码和配置也变得更加复杂和敏感。

  • 纠缠:这里指的是“改变任何东西都会改变一切”的问题。您需要谨慎处理特征工程和特征选择,并理解模型的敏感性。
  • 配置:模型超参数、版本和特征通常由系统配置控制,此处最微小的错误都可能导致模型行为发生根本性变化,而传统的软件测试无法发现这些问题,因此同样需要额外的、非常专业的监控。

总结 📝

本节课中,我们一起学习了机器学习模型生产监控的重要性。我们了解到,监控是一个持续的循环过程,能预防性能衰退和数据偏移等问题。我们区分了功能性监控(关注模型性能和数据)和非功能性监控(关注系统健康)。最后,我们明白了ML监控的特殊性在于需要同时关注数据模型的动态变化,以及由纠缠配置带来的额外复杂性。建立全面的监控体系是确保机器学习系统在生产环境中长期稳定、可靠运行的关键。

154:机器学习中的可观测性 🕵️

在本节课中,我们将要学习机器学习系统中的“可观测性”概念。我们将探讨其定义、重要性、在复杂ML系统中的具体应用,以及如何通过数据切片、监控和告警来实现有效的系统观测。


接下来,让我们探讨可观测性的概念,以及它如何应用于机器学习运维。

首先,什么是可观测性?可观测性衡量的是,仅通过了解系统的输入和输出来推断其内部状态的能力。对于机器学习系统,这意味着监控和分析模型的预测请求及其生成的预测结果。

可观测性并非一个新概念。它实际上源于控制理论,并在该领域已确立数十年。在控制理论中,可观测性与可控性紧密相连。你只能在你能够观测到的范围内控制系统。

对于一个基于机器学习的产品或服务,这映射到一个理念:要控制整体结果的准确性(通常涉及模型的不同版本),就需要可观测性。这也增加了模型可解释性的重要性。

在机器学习系统中,可观测性成为一个更复杂的问题,因为你需要考虑多个相互作用的系统和服务,例如云部署、容器化基础设施、分布式系统和微服务。这通常意味着存在大量需要监控和聚合的系统。因此,我们常常需要依赖供应商的监控系统来收集(有时是聚合)数据,因为每个实例的可观测性可能有限。例如,监控一个自动扩展的容器化应用程序的CPU利用率,与简单地监控单个服务器的CPU使用情况有很大不同。

可观测性是关于进行测量。就像你在训练期间分析模型性能时一样,仅测量顶层指标是不够的,并且会提供不完整的图景。你需要对数据进行切片,以了解模型在不同数据子集上的表现。

例如,在自动驾驶汽车中,你需要了解其在雨天和晴天条件下的性能,并分别进行测量。更普遍地说,数据切片为分析不同人群或不同类型条件提供了有用的方法。

这意味着领域知识在生产环境中观察和监控系统时非常重要,就像你在训练模型时一样。是你的领域知识将指导你如何对数据进行切片。

TFX框架和TensorFlow模型分析是非常强大的工具,包含了对已部署模型进行多数据切片可观测性分析的功能。

这对于模型的监督式和非监督式监控都适用。在监督式设置中,可以使用真实标签来衡量预测的准确性。相比之下,在非监督式设置中,你将监控每个特征的均值、中位数、范围和标准差等指标。无论在监督式还是非监督式设置中,你都需要对数据进行切片,以了解系统在不同子集下的行为。

回到自动驾驶汽车的例子,按天气条件进行切片非常重要,以避免在雨天做出糟糕的驾驶决策。

在监控的背景下,可观测性的主要目标是预防系统故障或对其采取行动。为此,观测需要在故障发生时提供警报,并理想情况下提供建议措施以使系统恢复正常行为。

更具体地说,告警能力指的是设计指标和阈值,以便在故障发生时能够非常清晰地识别。这可能包括定义规则,将多个测量值关联起来以识别故障。

知道系统出现故障是一个好的开始。但基于故障性质的可操作建议对于纠正这种行为更有帮助。可操作的警报明确定义了系统故障的根本原因。至少,你的系统应该收集足够的信息以支持根本原因分析。

告警能力和可操作性都是目标,而系统的有效性反映了它实现这些目标的程度。


本节课中,我们一起学习了机器学习可观测性的核心概念。我们了解到,可观测性是通过输入和输出来推断系统内部状态的能力,对于确保ML系统的可靠性和性能至关重要。实现有效的可观测性需要结合领域知识进行数据切片分析,并建立具备良好告警能力和可操作建议的监控系统。

155:机器学习中的监控目标 📊

在本节课中,我们将学习在机器学习系统中可以实际观察和监控哪些内容。我们将从系统的基础输入输出开始,逐步深入到更具体的监控指标、统计方法以及软件工程领域的监控实践。


监控系统的基础:输入与输出

上一节我们介绍了监控的重要性,本节中我们来看看监控的具体对象。首先,你可以监控系统的输入输出

在已部署的系统中,输入是预测请求,每个请求都是一个特征向量。你可以监控每个特征的统计度量,包括它们的分布,并寻找可能与故障相关的变化。同样,这不应仅仅是顶层的测量,还应包括与你的业务领域相关的数据切片的测量。

输出是模型的预测结果,你也可以对其进行监控和测量。这包括理解不同模型版本的部署情况,以帮助你了解不同版本的表现。


输入数据的监控与分析

以下是针对输入数据(即预测请求)进行监控的关键方面:

  • 错误监控:对于每个特征,应监控其值是否超出允许的范围或类别集合。这些错误条件通常基于领域知识来定义。
  • 分布变化监控:监控每个特征的分布如何随时间变化,并将其与训练数据的分布进行比较。
  • 切片数据分析:在数据切片上进行错误和变化监控,能帮助你更好地理解和识别潜在的系统故障。

统计测试与比较

统计测试和比较是分析数据的基本工具。典型的描述性统计包括中位数、均值、标准差和范围值。

对于监控模型预测,你也可以使用统计测试。在某些场景下,例如预测点击率时,如果标签可用,你还可以在已知标签和模型预测之间进行比较。

公式示例:如果变量呈正态分布,那么均值应落在均值区间的标准误差范围内。

此外,如果你曾为纠正类别不平衡或公平性问题而调整过训练数据的分布,那么在将其与通过监控预测请求收集的输入数据分布进行比较时,需要考虑这一点。


软件工程领域的监控实践

软件工程领域的监控实践更为成熟。因此,围绕我们机器学习系统的运维关注点可能包括:

  • 系统性能监控:例如延迟、I/O、内存或磁盘利用率等指标。
  • 系统可靠性监控:例如正常运行时间。
  • 可审计性监控:在考虑可审计性的同时进行监控。

在软件工程中,严格来说,谈论监控就是谈论事件。事件几乎可以是任何操作,例如接收一个HTTP请求、进入或离开一个函数(无论是否包含ML代码)、用户登录、从网络读取或写入磁盘等等。

这里列出的所有事件都带有一些上下文。拥有所有事件的完整上下文对于调试和理解系统在技术和业务层面的表现非常有帮助。然而,收集所有上下文信息通常不切实际,因为要处理和存储的数据量可能非常庞大。因此,理解最相关的上下文并尝试收集这些信息至关重要。


总结

本节课中,我们一起学习了机器学习系统中监控的核心目标。我们从监控系统的基础输入和输出开始,探讨了如何监控输入数据的错误和分布变化,并强调了在数据切片上进行监控的重要性。接着,我们介绍了用于分析的统计工具,并指出了在比较数据分布时需要考虑训练数据处理历史。最后,我们了解了软件工程中更广泛的监控实践,包括性能、可靠性监控以及事件上下文收集的挑战。有效的监控是确保机器学习系统在生产环境中稳定、可靠运行的关键。

156:第27课 机器学习监控的日志记录 📝

在本节课中,我们将要学习机器学习系统中日志记录的核心概念、重要性以及实施方法。日志是监控模型和系统的基础,它记录了系统运行过程中发生的离散事件,是进行问题诊断、性能分析和模型迭代的宝贵数据来源。


什么是日志?📖

上一节我们介绍了课程概述,本节中我们来看看日志的具体定义。

日志是机器学习系统随时间发生的离散事件的不可变时间戳记录,通常附带额外的上下文信息。这包括从应用程序打印到日志的调试或性能分析消息,以及根据日志记录详细程度设置自动生成的警告、错误和调试消息。

核心概念日志 = 不可变(事件 + 时间戳 + 上下文)


为什么需要日志记录?🔍

为了避免重复犯错,从历史中学习很重要。对于机器学习系统,这一逻辑同样适用。日志记录在此变得非常有用,尤其是在构建系统可观测性时。

以下是日志记录的主要目的:

  • 问题调查与根因分析:日志信息可用于调查事故并帮助进行根本原因分析。
  • 提供详细上下文:事件日志与上下文一起提供了有价值的洞察力,提供了平均值和百分位数无法呈现的细节。
  • 记录特定事件:指标显示服务或应用程序的趋势,而日志则侧重于记录特定事件。
  • 生成后续训练数据:日志数据当然也是你下一个训练数据集的基础。

如何实施日志记录?🛠️

探索了日志的“为什么”之后,我们来看看“如何做”。你可以从开箱即用的日志和指标开始。

以下是实施日志记录的一般步骤:

  1. 利用基础监控:开箱即用的日志和指标通常能提供一些基本的整体监控能力。
  2. 补充应用日志:例如,在谷歌计算引擎平台中,如果需要额外的应用程序日志,可以安装代理来收集这些日志。
  3. 收集云服务指标:云监控默认从所有云服务收集指标,然后你可以用这些指标来构建仪表板。
  4. 添加自定义指标:当需要额外的应用程序或业务级别指标时,可以使用这些自定义指标进行长期监控。
  5. 集中化管理日志:使用聚合接收器和工作区,可以将来自许多不同来源或服务的日志集中起来,以便创建应用程序的统一视图。

主要的云服务商也提供基于云的分布式服务的托管日志服务,例如 Google Cloud Monitoring、Amazon CloudWatch 和 Azure Monitor,以及一些第三方托管产品。


日志记录的挑战与处理 🚧

然而,日志记录并非完美无缺。在实施过程中,需要注意以下挑战和处理方式:

  • 性能影响:过多的日志记录会对系统性能产生负面影响。
  • 处理成本:由于性能问题,对日志的聚合操作可能成本高昂,因此基于日志的警报应谨慎处理。
  • 数据处理流程:原始日志在被持久化到 Elasticsearch 或 BigQuery 等数据存储之前,几乎总是需要通过 Logstash、Fluentd、Fluent Bit 或 Heka 等工具进行规范化、过滤和处理。
  • 运维成本:设置和维护这些工具会带来显著的运营成本。托管服务的主要优势之一就是消除了这部分成本。

日志数据存储与分析 📊

如何存储日志数据会显著影响其被查询分析的难易程度。此时,你应该考虑解析并存储你的输入和预测数据。

以下是存储与分析的关键点:

  • 使用可查询的数据存储:将输入和预测数据以及你能收集到的任何标签,存储在可查询的数据存储(如数据库或基于搜索引擎的工具如 Elasticsearch)中。
  • 支持分析:这支持对诸如生成特征分布和统计信息等进行分析,这些信息可以随时间跟踪和比较。
  • 时间序列分析:通过为每个项目关联时间戳,你还可以对数据进行排序,这对于识别趋势和季节性很重要。
  • 根因分析:通过识别所涉及的系统,可以帮助进行系统故障的根因分析。
  • 支持报告与告警:在可查询的数据存储中拥有这些数据还支持离线自动报告、仪表板和告警。

数据收集与标注技术 🏷️

至少,收集预测请求应该能提供代表你的应用程序所处世界当前状态的特征向量,因此这些数据非常有价值。让我们简要考虑一下标注问题和标注技术。

以下是几种常见的标注方法:

  • 直接标注:如果你所在的领域足够幸运,你将能够使用直接标注。例如,对于推荐系统,你通常可以在推荐后捕获用户行为,以确定是否推荐了正确的选项。
  • 人工标注:在其他情况下,你将需要使用人工标注,这可能缓慢且昂贵,但有时也是唯一可行的选择。
  • 主动学习:使用像主动学习这样的技术,可以通过仅选择最重要的样本来标注,从而帮助降低成本,这包括为类不平衡和公平性等问题塑造你的数据集。
  • 弱监督:弱监督是一种具有显著优势的强大技术,但也存在一些挑战。

最重要的是,你需要捕获这些有价值的数据,以便让你的模型与不断变化的世界保持同步。


需要警惕的信号 🚩

到目前为止的讨论大多围绕如何使用指标来监控机器学习系统中的输入数据和预测。这通常是监控应用程序时收集数据的基本方式。

以下是一些需要警惕的信号示例:

  • 特征不可用:特征变得不可用,尤其是当你的预测请求中包含需要从数据存储中检索的历史数据时。
  • 输入分布偏移:关键输入值的分布发生显著变化。例如,在训练数据中相对罕见的分类值变得更常见。
  • 特定模式变化:特定于你的模型的模式变化,例如,在自然语言处理场景中,训练数据中未出现过的单词数量突然增加,这也可能是导致问题的潜在变化的另一个迹象。

总结 ✨

本节课中我们一起学习了机器学习监控中日志记录的核心知识。我们明确了日志是不可变的时间戳事件记录,是系统可观测性的基础。我们探讨了实施日志记录的步骤、面临的挑战(如性能影响和处理成本)以及如何通过可查询的数据存储(如数据库或 Elasticsearch)来有效存储和分析日志数据,以支持特征分析、趋势识别和根因分析。最后,我们强调了收集预测数据对于模型迭代的重要性,并简要介绍了直接标注、人工标注、主动学习和弱监督等数据标注技术。记住,持续捕获真实环境中的数据是使模型适应动态世界的关键。

157:机器学习系统的追踪 🕵️

在本节课中,我们将学习分布式机器学习系统中的追踪技术。追踪专注于监控和理解系统性能,尤其是在基于微服务的应用程序中。我们将探讨为何在分布式系统中追踪变得至关重要,以及如何通过追踪来诊断性能瓶颈和问题。


从单体系统到分布式系统

上一节我们介绍了追踪的基本概念。本节中我们来看看,当系统架构从单体式转变为分布式时,追踪面临的挑战。

在单体系统中,从系统的不同部分收集诊断数据相对容易。所有模块甚至可能在一个进程内运行,并共享用于日志记录的公共资源。

当考虑分布式系统时,情况变得更有趣。假设你正在尝试排查一个预测延迟问题。你的系统由许多独立服务组成,预测是通过许多下游服务生成的。你无法确定是哪些服务导致了速度变慢。你无法清楚地了解这是程序错误、集成问题、架构选择不当导致的瓶颈,还是网络性能不佳。

如果你的服务作为分布式系统中的独立进程运行,解决这个问题会变得更加困难。你无法依赖那些有助于诊断单体系统的传统方法。你需要更细粒度地了解每个服务内部发生了什么,以及它们在用户请求的生命周期内如何相互交互。


分布式追踪的必要性

从上一节可知,在分布式系统中定位问题非常困难。本节我们将深入探讨为何需要专门的追踪技术。

从前端网络服务器开始,跟踪一个调用,直到预测结果返回给用户,这个过程变得更加困难。你会注意到,我们真正关注的是在线服务。

为了正确检查和调试分布式系统中请求的延迟问题,你需要理解服务的顺序和并行性,以及每个服务对系统最终延迟的贡献。


Dapper:分布式追踪的解决方案

为了解决上述问题,谷歌开发了分布式追踪系统Dapper,用于检测和分析其生产服务。Dapper论文启发了许多开源项目,如Zipkin和Jaeger。Dapper风格的追踪已成为行业范围内的标准。

在基于服务的架构中,Dapper风格的追踪通过在服务之间传播追踪数据来工作。每个服务用额外的数据注释追踪信息,并将追踪头传递给其他服务,直到最终请求完成。

以下是其核心工作流程的简述:

  1. 请求进入系统,生成一个唯一的追踪ID。
  2. 该ID随请求在服务间传递。
  3. 每个服务记录其操作的开始时间、结束时间和其他元数据(称为一个Span)。
  4. 所有Span数据被收集到追踪后端。

追踪的组成与可视化

每个追踪都是一个调用树,从请求的入口点开始,到服务器的响应结束,包括沿途所有的RPC调用。每个追踪由称为Span的小单元组成。

服务负责将其追踪数据上传到追踪后端。追踪后端然后将相关的延迟数据像拼图一样组合在一起。追踪后端还提供用户界面,用于分析和可视化追踪数据。


总结

本节课中,我们一起学习了机器学习系统中追踪技术的重要性。我们了解到,在分布式微服务架构中,传统的日志调试方法难以定位性能瓶颈。通过引入类似Dapper的分布式追踪系统,我们可以传播追踪上下文、记录每个服务单元的Span、并在后端聚合可视化,从而清晰地洞察请求在系统中的完整路径和每个环节的耗时,最终有效地诊断延迟等复杂问题。

158:29_什么是模型衰减 📉

在本节课中,我们将要学习机器学习模型在生产环境中面临的一个核心问题:模型衰减。我们将探讨模型衰减发生的原因、主要类型以及如何预防它,以确保模型在动态变化的环境中保持高性能。


模型衰减概述

在许多应用领域中,模型衰减是一个关键问题。模型衰减指的是随着时间的推移,机器学习模型在生产环境中的性能逐渐下降的现象。这通常是因为模型所处的环境是动态变化的,而静态的模型无法适应这些变化。

上一节我们介绍了模型衰减的基本概念,本节中我们来看看为什么模型衰减会发生以及如何理解它。

生产环境中的机器学习模型通常在动态环境中运行。动态环境会发生变化,这正是“动态”一词的含义。例如,一个推荐系统试图推荐用户可能喜欢的音乐。音乐品味和流行趋势是不断变化的,新音乐不断涌现,人们的喜好也在改变。如果模型是静态的,并持续推荐已经过时的音乐,那么推荐的质量就会下降。模型逐渐偏离了当前的真实情况,因为它没有针对当前的新趋势进行训练。


模型衰减的两种主要类型

模型衰减主要有两种类型:数据漂移和概念漂移。以下是这两种类型的详细说明。

数据漂移

数据漂移发生在输入特征(即模型接收的数据)的统计属性发生变化时。随着输入数据的变化,预测请求的输入数据会越来越偏离模型训练时使用的数据,从而导致模型准确性下降。这类变化通常发生在人口统计特征上,例如年龄分布,这些特征可能会随时间而变化。

右侧的图表展示了年龄特征的均值和方差如何增加。这就是数据漂移的一个例子。

公式表示: 若训练数据分布为 P_train(X),而生产环境中的数据分布变为 P_prod(X),当 P_train(X) ≠ P_prod(X) 时,即发生数据漂移。

概念漂移

概念漂移发生在特征与标签之间的关系发生变化时。当模型被训练时,它学习的是输入特征与真实标签之间的关系。如果这种关系随时间发生变化,就意味着你试图预测的事物的“含义”本身发生了改变。世界已经变了,但我们的模型并不知道。

例如,请看右侧的图表。你可以看到两个类别(蓝点和红点)的特征分布在时间间隔 T1、T2 和 T3 中发生了变化。如果你的模型仍然基于 T1 时期的关系进行预测,而世界已经进入了 T3 时期,那么它的许多预测将是错误的。

公式表示: 若训练时的条件分布为 P_train(Y|X),而生产环境中的条件分布变为 P_prod(Y|X),当 P_train(Y|X) ≠ P_prod(Y|X) 时,即发生概念漂移。

注:还存在其他相关的漂移形式,例如预测漂移(仅模型预测结果发生漂移)或标签漂移,但本课程不会详细讨论它们。


模型衰减的影响与应对策略

如果不提前为漂移做好计划,它会随着时间的推移慢慢渗透到你的系统中。系统漂移的速度取决于你所处领域的性质。有些领域(如金融市场)可能在几小时甚至几分钟内就发生变化,而其他领域的变化则更为缓慢。

如果未能检测到漂移(无论是数据漂移、概念漂移还是两者兼有),模型的准确性就会受损,而你却可能对此一无所知。这可能导致需要对模型进行紧急重新训练,这是应该尽量避免的情况。

因此,监控和提前规划至关重要。知道你已经提前做好了计划并建立了相应的系统,可能会让你在晚上睡得更安稳。

以下是应对模型衰减的关键步骤:

  1. 持续监控:建立系统以持续监控模型输入数据的分布和模型预测性能。
  2. 设定警报:当检测到统计属性发生显著变化时,触发警报。
  3. 定期评估与再训练:规划模型的定期评估周期,并在性能下降时启动再训练流程。
  4. 自动化管道:构建自动化的模型再训练和部署管道,以快速响应变化。

总结

本节课中我们一起学习了模型衰减的概念。我们了解到,模型衰减是由于生产环境动态变化而导致的模型性能下降,主要分为数据漂移概念漂移两种类型。通过理解这些漂移发生的原因,我们可以采取监控、预警和定期再训练等策略来预防和应对模型衰减,从而确保机器学习系统能够长期稳定、有效地运行。提前规划应对机制是维持模型在生产环境中生命力的关键。

159:第30课 检测模型衰减 📉

在本节课中,我们将学习如何检测机器学习模型在生产环境中可能发生的性能衰减。模型衰减通常由数据漂移或概念漂移引起,及时发现这些问题是维持模型有效性的关键。


概述:检测模型衰减的方法

上一节我们讨论了模型衰减是一个普遍存在的问题。本节中,我们来看看如何具体地检测它。

检测模型衰减,无论是数据漂移还是概念漂移,都始于收集当前数据。


数据收集:检测的基础

以下是检测工作的第一步,即数据收集的具体要求:

  • 你应该收集所有传入模型的预测请求数据,以及模型做出的预测结果。
  • 如果你的应用场景允许,还应该收集模型本应预测出的正确标签或真实值。这对于后续的模型重新训练也极具价值。
  • 但至少,你必须捕获预测请求数据,这些数据可以用来通过无监督的统计方法检测数据漂移。

检测流程与工具

一旦你建立了持续监控和记录数据的机制,检测过程就相当直接了。

你将使用工具,借助成熟的统计方法,来比较当前数据与之前的训练数据。同时,你还会使用仪表板来监控数据随时间变化的趋势和季节性。本质上,你是在处理时间序列数据,因为你的数据是有序的,并且与时间成分相关联。

在这方面,你无需重复造轮子,已有一些优秀的工具和库可以帮助你完成这类分析。

以下是可用于此类分析的工具和库示例:

  • TensorFlow Data Validation (TFDV)
  • River 库(原 scikit-multiflow

此外,包括谷歌在内的云服务提供商也提供了托管服务来协助完成这项工作。


云服务的持续评估功能

以谷歌的 Vertex AI Prediction 为例,它可以帮助你对预测请求进行持续评估。

continuous_evaluation 服务会定期从你部署到 Vertex Prediction 的已训练机器学习模型中,对预测输入和输出进行采样。

随后,Vertex 的数据标注服务会分配人工审核员为你的预测输入提供真实值标签,或者你也可以自行提供真实值标签。

数据标注服务会将模型的预测结果与真实值标签进行比较,从而持续提供关于模型随时间推移的性能表现反馈。

Azure、AWS 和其他云服务提供商也提供类似的服务。


总结

本节课中,我们一起学习了检测模型衰减的核心步骤。关键在于系统地收集生产环境中的预测请求、模型输出以及(如有可能)真实标签数据。利用专门的工具(如 TFDV、River)或云平台的托管服务,通过统计比较和时间序列分析,可以有效地监控数据分布和模型性能的变化,从而及时发现衰减迹象。

160:31_缓解模型衰减的方法 🛠️

在本节课中,我们将学习当检测到模型性能衰减(即模型衰减)后,可以采取哪些具体措施来缓解这一问题。模型衰减通常由数据漂移引起,我们将探讨从数据管理、模型再训练策略到流程自动化的完整应对方案。


检测到衰减后的基本步骤

上一节我们讨论了如何检测模型衰减。本节中我们来看看检测到衰减后,首先应该做什么。

你需要将模型衰减的情况告知相关的运营和业务利益相关者,并附上你对漂移严重程度的初步评估。

随后,你的工作重点是将模型的性能恢复到可接受的水平。


构建新的训练数据集

在着手恢复模型性能之前,你需要决定如何处理新旧训练数据。以下是几种常见的方法。

首先,可以尝试使用无监督方法(如聚类)或统计方法(如计算散度)来确定旧训练数据中哪些部分仍然有效。可选的方法包括Kullback-Leibler (KL) 散度Jensen-Shannon (JS) 散度Kolmogorov-Smirnov (KS) 检验。这一步是可选的,但在新数据不足时,尽可能保留有效的旧数据尤为重要。

另一种方法是,直接丢弃训练数据集中某个日期之前收集的部分,并加入新数据。

或者,如果你有足够新标注的数据,可以直接创建一个全新的数据集。

具体选择哪种方法,通常取决于你的应用场景现实和收集新标注数据的能力。


模型再训练策略

现在你有了新的训练数据集。对于如何训练模型,你基本上有两种选择:微调从头开始

你可以选择继续训练现有模型,使用新数据从最后一个检查点开始进行微调

也可以选择重新初始化模型并完全重新训练

这两种方法都有效。选择哪种很大程度上取决于你拥有的新数据量,以及自上次训练以来数据分布发生了多大程度的漂移。

理想情况下,如果你有足够的新数据,应该尝试两种方法并比较结果。


制定再训练策略

为模型再训练制定明确的策略通常是个好主意。这里没有绝对正确或错误的答案,一切取决于你的具体情况。

你可以选择在必要时才重新训练模型,例如检测到数据漂移时,或者需要增删类别标签或特征时。

你也可以按照固定的时间表重新训练模型,无论是否需要。实践中很多人这样做,因为它简单易懂,并且在许多领域效果相当好。

然而,这可能导致不必要的训练和数据收集成本(如果训练过于频繁),或者允许模型衰减超出理想范围(如果训练不够频繁)。

最后,你可能受到新训练数据可用性的限制。在数据标注缓慢且昂贵的场景中尤其如此。因此,你可能被迫尽可能长时间地保留旧训练数据,并避免完全重新训练模型。


实现自动化再训练流程

如果能自动化检测需要模型再训练的条件,那将是最理想的。

这包括能够检测到模型性能下降并触发再训练,或者检测到显著的数据漂移时自动触发。

为了实现自动化再训练,你应该有一个独立的流程来自动收集和标注数据,并且只在有足够数据可用时才触发再训练。

理想情况下,你还应该设置持续训练、集成和部署流程,使整个过程完全自动化。对于那些变化快速、需要频繁再训练的领域,这些自动化流程不再是奢侈品,而是必需品。


模型架构与设计的重新考量

当模型衰减超出可接受的阈值,或者你试图预测的变量含义发生显著变化时,你可能需要重新设计数据预处理步骤和模型架构。

我喜欢将此视为一个改进的机会。

你可能需要重新思考特征工程特征选择等,以使你的模型适应当前数据,并选择从头开始重新训练模型,而不是应用微调。

你可能还需要研究其他潜在的模型架构,我个人认为这非常有趣。

这里的重点是,没有模型可以永远有效。你需要定期回到起点重新开始,并应用自上次更新模型以来所学到的一切。


总结

本节课中,我们一起学习了缓解模型衰减的一系列方法。我们从检测到衰减后的基本沟通步骤开始,探讨了如何构建新的训练数据集,比较了微调与完全重新训练两种策略,并讨论了制定再训练计划的重要性。我们还了解了实现自动化再训练流程的价值,以及在必要时重新考量模型架构与设计的必要性。记住,应对模型衰减是一个持续的过程,需要结合监控、策略和自动化来有效管理。

161:负责任的AI 🧠

在本节课中,我们将探讨负责任的AI这一新兴议题,并了解作为开发者,你可以采取哪些措施来确保你的模型和应用尽可能负责任。


概述

人工智能的发展为改善世界各地人们的生活创造了新机遇,从商业到医疗保健再到教育等领域。然而,与此同时,它也引发了关于如何最好地将公平性、可解释性、隐私和安全性融入这些系统的新问题。这些问题远未解决,是当前极其活跃的研究和开发领域。

构建负责任的AI系统

上一节我们介绍了负责任AI的重要性,本节中我们来看看构建此类系统时需要考虑的具体方面。

关注用户体验

评估系统预测、推荐和决策的真实影响,关键在于实际用户的体验。例如,你应该在设计功能时就内置适当的披露说明。清晰度和可控性对于良好的用户体验至关重要。

考虑辅助与建议

在答案很可能满足多样化用户和用例的情况下,提供单一答案是合适的。但在其他情况下,系统向用户建议几个选项可能更好。事实上,这样做有时甚至更容易,因为要确保单一答案(Top-1)的高精确度,通常比确保前几个答案(例如Top-3)的精确度要困难得多。

规划与测试

在设计过程的早期,就应尝试规划对潜在负面反馈的建模。随后,在全面部署之前,应对一小部分流量进行具体的实时测试和迭代。

吸纳多元反馈

最后,与多样化的用户群体和不同的用例场景互动,并在项目开发之前和整个过程中吸纳他们的反馈。这将在项目中融入丰富的用户视角,增加从技术中受益的人数,并帮助你及早发现潜在问题。

评估与度量

上一节我们讨论了构建过程中的考量,本节中我们来看看如何评估系统的表现。

以下是评估系统时可以考虑的一些关键度量指标:

  • 用户反馈: 包括来自用户调查的反馈。
  • 系统性能: 跟踪整体系统性能的量化指标。
  • 产品健康度: 短期和长期的产品健康指标,例如点击率和客户终身价值。
  • 错误率分析: 在不同子群体中切分的假阳性率和假阴性率。

当然,你选择的度量指标至关重要。你应该努力确保你的指标适合系统的背景和目标。例如,火灾报警系统应该具有高召回率,即使这意味着偶尔会有误报。

数据的重要性

正如我们一直强调的,一切最终都回到数据上。机器学习模型将反映它们所训练的数据,因此请仔细分析你的原始数据以确保你理解它。

理解你的数据

在无法直接分析原始数据的情况下(例如涉及敏感数据),应在尊重隐私的前提下尽可能理解你的输入数据。例如,可以通过计算聚合的匿名摘要来实现。

检查数据代表性

考虑你的数据采样方式是否能代表你的用户。例如,如果你的应用将被所有年龄段的人使用,但你的训练数据仅来自老年人,那么它可能对其他年龄段的用户效果不佳。想象一下,当你所有的数据都来自老年人时,去做音乐推荐,我的猜测是它对青少年可能效果不佳。

注意代理标签

有时,你会使用模型来预测你感兴趣的实际目标的代理标签,因为对实际目标进行标注很困难或不可能。在这些情况下,请考虑你拥有的数据标签与你试图预测的实际事物之间的关系。是否存在有问题的差距?例如,如果你使用数据标签 X 作为代理来预测目标 y,那么在哪些情况下 xy 之间的差距会成为问题?


总结

本节课中,我们一起学习了负责任的AI的核心概念。我们探讨了在构建AI系统时关注用户体验、进行多元化测试与反馈的重要性。我们了解了评估系统时使用多种度量指标的必要性,并再次强调了深入理解数据、检查其代表性以及注意代理标签潜在问题的基础性作用。虽然构建完全负责任的AI系统是一个持续的挑战,但通过应用这些原则和不断发展的工具,开发者可以显著提升其模型和应用的负责任程度。

162:安全私密AI的法律要求 ⚖️🔒

在本节课中,我们将探讨实践负责任AI所涉及的法律层面。我们将了解现有的法律要求、数据隐私的重要性,以及如何保护机器学习模型免受攻击,确保用户数据的安全与私密。


法律要求概览

实践负责任AI存在法律层面。一些国家和地区已有法律要求,且这一趋势正在增长。承担民事责任的风险是另一个需要关注的问题。

现在我们来探讨一些具体问题。

敏感数据的隐私保护

训练数据、预测请求或两者都可能包含关于个人的非常敏感的信息。对于预测请求,这些人就是你的用户。

敏感数据的隐私应受到保护。这不仅包括遵守法律和监管要求,还需考虑社会规范和个人的普遍期望。

考虑到机器学习模型可能会记住或暴露它们所接触数据的某些方面,你需要采取哪些保障措施来确保个人隐私?

需要哪些步骤来确保用户对其数据拥有足够的透明度和控制权?

这并非仅由你决定需要什么。例如,在欧洲,你需要遵守《通用数据保护条例》(GDPR);在加利福尼亚州,你需要遵守《加州消费者隐私法案》(CCPA)。


主要法规介绍

上一节我们提到了数据隐私的重要性,本节中我们来看看两项重要的法律框架。

《通用数据保护条例》(GDPR) 由欧盟于2016年颁布,并成为欧盟以外许多国家法律的范本,包括智利、日本、巴西、韩国、阿根廷和肯尼亚。它规范了欧盟和欧洲经济区的数据保护与隐私。GDPR赋予个人对其个人数据的控制权,并要求公司保护员工和消费者的数据。

当数据处理基于同意时,数据主体(通常为个人)有权随时撤销其同意。

《加州消费者隐私法案》(CCPA) 以GDPR为范本,具有相似的目标,包括增强加州居民的隐私权和消费者保护。它规定用户有权知道正在收集关于他们的哪些个人数据,包括个人数据是否被出售或以某种方式披露、谁提供了他们的数据以及谁接收了他们的数据。

用户可以访问公司持有的关于他们的个人数据,阻止其数据被出售,并要求企业删除其数据。

机器学习中的安全与隐私危害

安全与隐私对于机器学习中的某些问题或危害是紧密相连的。

信息危害 是指信息从模型中泄露所造成的危害。至少存在三种不同类型的信息危害:

以下是不同类型信息危害的列表:

  • 成员推断:攻击者能够确定某个个体的数据是否包含在训练集中。
  • 模型反演:攻击者实际上能够重建训练集。
  • 模型提取:攻击者能够重建模型本身。

行为危害 是指攻击者能够改变模型本身行为所造成的危害。这包括:

以下是不同类型行为危害的列表:

  • 投毒攻击:攻击者能够将恶意数据插入训练集。
  • 规避攻击:攻击者对预测请求进行微小更改,导致模型做出错误预测。

因此,保护你的模型免受攻击,同时确保用户数据的隐私和安全至关重要。

防御攻击的方法

了解了可能面临的危害后,本节我们来看看如何防御这些攻击。

在训练和服务模型时,你应该考虑隐私增强技术,例如安全多方计算(SMC)全同态加密(FHE)

简而言之,SMC使多个系统能够安全地协作来训练和/或服务模型,同时通过使用共享秘密来确保实际数据的安全。另一方面,FHE使开发人员能够在加密数据上训练模型,而无需先解密。特别是FHE,允许用户发送加密的预测请求并接收加密的结果。在整个过程中,数据除了用户之外从未被解密。然而,你应该意识到,目前FHE的计算成本非常高。

这里的目标是,通过使用密码学,你可以保护训练数据的机密性。

差分隐私简介

粗略地说,如果一个攻击者看到模型的预测结果后,无法判断某个特定用户的信息是否包含在训练数据中,那么这个模型就是差分隐私的。

通过实现差分隐私,你可以在私有数据上负责任地训练模型。它提供了可证明的隐私保证,降低了暴露敏感训练数据的风险。

让我们简要讨论实现差分隐私的三种不同方法:

以下是三种差分隐私实现方法的列表:

  • 差分隐私随机梯度下降(DP-SGD)
  • 教师模型集合的私有聚合(PATE)
  • 保密与隐私协作学习(CAPC)

差分隐私随机梯度下降(DP-SGD)

如果攻击者能够获得一个正常训练的模型的副本,那么他们可以利用权重来提取私有信息。

差分隐私随机梯度下降(DP-SGD) 通过在训练过程中应用差分隐私来消除这种可能性。它通过在小批量随机优化过程中添加噪声来实现这一点。结果是得到一个训练好的模型,由于差分隐私的后处理免疫特性,该模型保留了差分隐私。

后处理免疫是差分隐私的一个基本属性,意味着无论你如何处理模型的预测,都不会影响其隐私保证。

教师模型集合的私有聚合(PATE)

接下来,我们看看教师模型集合的私有聚合(PATE)

PATE首先将敏感数据划分为K个不重叠的分区。然后分别在每个分区数据上训练K个模型作为教师模型,然后将它们的结果聚合到一个聚合教师模型中。这与用于知识蒸馏的师生模型类似。

在聚合教师模型的聚合过程中,你会以一种不影响最终预测结果的方式向输出添加噪声。所有这些模型和敏感数据对最终用户(包括攻击者)都是不可用的。

对于部署,你将创建一个学生模型。为了训练学生模型,你将获取未标记的公共数据,并将其输入聚合教师模型。此过程的输出是标记数据,且保持了隐私性。你将使用这些数据作为学生模型的训练集。训练完成后,你将丢弃本图左侧的所有内容,仅部署学生模型供使用。

保密与隐私协作学习(CAPC)

保密与隐私协作学习(CAPC) 使使用不同数据的多个开发人员能够协作提高模型准确性,而无需共享信息。这同时保护了隐私和机密性。

为了实现这一点,它应用了密码学和差分隐私的技术与原理。这包括使用同态加密(HE) 来加密每个协作模型接收的预测请求,从而不泄露预测请求中的信息。然后,它使用PATE向每个协作模型的预测添加噪声,并使用投票来得出最终预测,同样不泄露信息。

CAPC应用的一个很好的例子是考虑一组希望协作改进彼此模型和预测的医院。由于医疗隐私法,他们不能直接共享信息,但使用CAPC,他们可以在保护患者隐私和机密性的同时获得更好的结果。


总结

本节课中,我们一起学习了实践安全私密AI的法律要求。我们了解了GDPR和CCPA等关键法规,认识了机器学习中信息危害和行为危害的类型,并探讨了通过安全多方计算、全同态加密以及差分隐私技术(如DP-SGD、PATE和CAPC)来防御攻击、保护用户数据隐私和安全的方法。遵守法律要求并实施强有力的隐私保护措施,是构建负责任且可信赖的AI系统的基石。

163:匿名化与伪匿名化 🔒

在本节课中,我们将学习数据隐私保护中的两个核心概念:匿名化与伪匿名化。我们将探讨它们的定义、区别、实现方式以及在《通用数据保护条例》(GDPR)框架下的应用。


《通用数据保护条例》(GDPR)包含了许多旨在保护用户数据隐私的法规,并对其使用的诸多术语进行了定义。其中,我们将重点讨论两个术语:匿名化与伪匿名化。

匿名化:不可逆的隐私保护

上一节我们提到了GDPR的隐私保护目标,本节中我们来看看匿名化的具体含义。

匿名化是指从数据集中移除所有个人可识别信息(PII),使得数据所描述的个人身份保持匿名。GDPR第26条序言将可接受的匿名化定义为不可逆的过程,其实现方式必须达到无法识别具体个人的程度。这意味着,即使是负责匿名化的一方,也无法从数据中推导出任何见解或离散的个人信息。

一旦数据被成功匿名化,GDPR的法规将不再适用于该数据。

核心概念匿名化数据 = 原始数据 - 所有个人可识别信息(PII),且此过程不可逆。

伪匿名化:可逆的标识符处理

了解了不可逆的匿名化后,我们再来看看另一种可逆的处理方式。

伪匿名化则有所不同。这是一个可逆的过程,意味着如果获得了正确的附加信息,仍然可以识别出具体的个人。伪匿名化可以通过数据掩码、加密或令牌化等技术来实现。它的有效性依赖于对附加识别信息访问权限的严格控制。

核心概念伪匿名化数据 = 原始数据 - 直接标识符 + 加密密钥/映射表,此过程可逆。

核心区别:可逆性

为了更清晰地理解,匿名化与伪匿名化之间最大的区别在于:伪匿名化数据可以通过一组附加信息或加密密钥进行还原,而匿名化则是不可逆的。

数据隐私的连续光谱

多年来,业界已经发展出许多方法、机制和工具,能够产生具有不同匿名程度和可识别能力的数据。这构成了一个从“个人可识别”到“完全匿名”的连续光谱。

以下是这个光谱的主要组成部分:

  • 个人可识别数据:包含姓名、地址、电话、邮箱等直接标识符。
  • 伪匿名化与去标识化数据:构成了光谱的中间类别。它们确实是保护数据隐私某些方面的一种方式,但尚未达到真正匿名化数据的级别。需要注意的是,去标识化数据与伪匿名化数据之间的界限并不十分明确,许多讨论会将它们归为一类。
  • 真正的匿名化数据:符合GDPR指南,不包含任何个人可识别信息(PII),并且即使拥有附加信息也无法与PII关联。

需要匿名化的数据范围

那么,数据的哪些部分应该被匿名化呢?基本上,所有属于个人可识别信息(PII)的部分都需要处理。

这包括任何能够揭示个人身份的数据,即所谓的“标识符”。这里的“标识符”指任何在世或已故的自然人或法人,包括其家属、祖先和后代。此外,也包括那些可能通过直接或间接关系被识别的其他相关人员。

例如,需要处理的标识符特征包括:

  • 姓氏、父姓、名字、婚前姓、别名
  • 地址、电话号码
  • 银行账户详情、信用卡信息
  • 税号等


本节课中,我们一起学习了匿名化与伪匿名化这两个关键的数据隐私保护技术。我们明确了匿名化是不可逆的移除PII的过程,而伪匿名化则是可逆的标识符替换或加密过程。理解它们在数据隐私连续光谱中的位置,以及明确哪些数据属于需要处理的PII,对于在GDPR等法规框架下合规地处理用户数据至关重要。

164:35_被遗忘权 👤➡️🗑️

在本节课中,我们将学习《通用数据保护条例》(GDPR)中的“被遗忘权”。我们将了解其定义、适用场景、例外情况以及如何在实践中实施数据删除。理解这些内容对于负责任地处理用户数据和构建合规的机器学习系统至关重要。


概述与术语澄清

首先,我们需要澄清一些关键术语。在GDPR的语境中:

  • 数据主体:指个人。
  • 控制者:指控制包含个人可识别信息(PII)数据集的个人或组织。

明确了这些术语后,我们可以开始探讨核心问题。


被遗忘权的适用场景

那么,个人在什么情况下拥有被遗忘权呢?GDPR列举了一系列个人有权要求删除其个人数据的原因。以下是主要情形列表:

  • 个人数据对于组织最初收集或处理它的目的而言不再必要。
  • 组织依赖个人同意作为处理数据的合法依据,而该个人撤回了同意。
  • 组织以合法利益为由处理个人数据,个人对此提出反对,且组织没有压倒性的合法利益来继续处理。
  • 组织为直接营销目的处理个人数据,个人对此提出反对。
  • 组织非法处理了个人数据。
  • 组织必须删除个人数据以遵守法律裁决或义务。
  • 组织处理了儿童的个人数据以向其提供信息社会服务(例如社交网络)。

通常,如果满足上述任一条件,就必须删除该个人的数据。这些规定大多符合常识。


被遗忘权的例外情况

然而,在某些情况下,组织处理个人数据的权利可能优先于个人的被遗忘权。以下是GDPR中列举的例外情况:

  • 数据被用于行使言论自由和信息自由权。
  • 数据被用于遵守法律裁决或义务。
  • 数据被用于执行符合公共利益的任务或行使组织的官方职权。
  • 被处理的数据对于公共卫生目的和公共利益是必要的。
  • 被处理的数据对于执行预防性或职业性医学是必要的(仅适用于由受职业保密法律义务约束的健康专业人员处理数据时)。
  • 数据代表了服务于公共利益、科学研究、历史研究或统计目的的重要信息,删除数据可能会损害或阻碍实现处理目标。
  • 数据被用于建立法律辩护或行使其他法律主张。

此外,如果组织能证明删除请求是毫无根据或过度的,可以收取合理费用或拒绝该请求。但一般而言,除非你明确符合上述例外条件之一,否则应避免凌驾于个人的被遗忘权之上。如有疑问,应以保护隐私为先。


其他相关数据权利

GDPR还规定了数据主体拥有的其他一系列权利。上一节我们讨论了被遗忘权,本节中我们来看看这些补充性权利,它们共同构成了个人数据保护的核心。

  • 更正权:个人有权要求更正其不准确的个人信息。这在信用记录、健康记录或就业记录等场景中尤为重要。
  • 访问权:数据主体有权访问其个人数据。
  • 限制处理权:数据主体有权限制对其数据的处理。
  • 数据可携权:数据主体有权以结构化、通用和机器可读的格式接收其提供给控制者的个人数据,并有权将这些数据传输给另一个控制者。
  • 反对权:数据主体有权反对基于特定情况对其个人数据进行的处理。

作为一般规则,最好以保护隐私为先,将数据中的所有个人信息都视为敏感信息。应限制对其的访问并确保其安全。最重要的是,应将其视为信息所属者的财产,并尊重他们的意愿。


实施数据删除的要求

当你收到有效的删除个人信息请求时,需要执行一系列操作。以下是需要完成的步骤列表:

  • 识别所有相关信息:识别与请求删除内容相关的所有信息。
  • 删除关联元数据:识别并删除与该个人相关的所有元数据。
  • 处理衍生数据:如果你进行过任何分析或训练过任何模型,则衍生的数据、日志和模型也必须被删除或修正。

此处的目标是尽可能做到仿佛你从未拥有过他们的数据。


数据删除的两种方法

基本上有两种删除数据的方法可以满足GDPR的要求。

1. 数据匿名化
正如之前所见,匿名化将使数据在GDPR条款下不再具有个人可识别性。GDPR将不再适用于匿名化后的数据。

2. 硬删除
即实际删除数据,包括数据库中可能包含它的任何行。

通常,你的第一反应可能总是进行硬删除。但这通常会带来问题,因此匿名化是另一个选择。


匿名化与硬删除的考量

在数据库或任何类似的关系型数据存储中,删除记录可能会造成严重破坏。部分原因是用户数据通常被多个表引用。删除这些记录会破坏连接,这在大型复杂数据库中尤其困难。例如,它可能破坏外键约束。

另一方面,匿名化保留记录,只对包含PII的字段进行匿名化处理,同时仍能满足GDPR的要求。这通常能更好地维持数据完整性和系统稳定性。


实施被遗忘权的挑战

实施被遗忘权面临几个挑战。识别数据隐私是否被侵犯的过程本身就是一项艰巨的任务。

为了执行GDPR,需要进行一些组织变革,包括政策变更和培训员工如何执行被遗忘权。还有一个最后需要考虑的棘手问题。


备份数据的处理

如果你的组织维护数据的多个备份(实际上你应该这样做),确保个人数据已从所有备份中删除是具有挑战性的。你可能需要改变数据存储和备份实施方案,以保持对GDPR的合规性。


总结

本节课中,我们一起学习了GDPR中的“被遗忘权”。我们了解了它的定义、触发条件、例外情况以及其他相关的数据主体权利(如更正权)。我们还探讨了实施数据删除的两种主要方法(匿名化与硬删除)及其各自的考量,并指出了在数据库关系维护和备份处理中可能遇到的挑战。

像GDPR和被遗忘权这样的问题,在商业环境中运营已经至关重要。理解围绕它们的机器学习问题只会变得越来越重要。我们已经为你提供了该领域现状的基本理解,但我强烈建议你持续关注新的发展。同时,我认为尊重客户隐私、极其谨慎地对待你拥有的任何信息或PII始终是重要的,我强烈建议你这样做。

posted @ 2026-03-26 08:16  绝不原创的飞龙  阅读(6)  评论(0)    收藏  举报