Python-主动机器学习-全-
Python 主动机器学习(全)
原文:
annas-archive.org/md5/4d0971dfe04e35421f1568b6eb1214fa译者:飞龙
前言
欢迎阅读 使用 Python 进行主动学习,这是一本全面指南,旨在向您介绍主动机器学习的力量。本书坚信,尽管数据丰富,但其质量和相关性是构建既高效又稳健且富有洞察力的模型的关键。
主动机器学习是一种机器学习方法,其中算法可以查询一个预言者来标记新的数据点以获得期望的输出。它位于优化和人与计算机交互的十字路口,使机器能够用更少的数据更有效地学习。这在数据标记成本高、耗时或需要专业知识的情况下尤其有价值。
在整本书中,我们利用 Python,这是数据科学和机器学习领域的领先编程语言,以其简洁和强大的库而闻名。Python 是探索主动机器学习概念的绝佳媒介,为初学者和经验丰富的从业者提供实施复杂模型所需的工具。
本书面向对象
本书旨在面向数据科学家、机器学习工程师、研究人员以及任何对优化机器学习工作流程感兴趣的人。无论你是主动学习的初学者还是希望提升现有模型,本书都能通过战略查询和学习技术帮助你充分利用数据。
本书涵盖内容
第一章, 介绍主动机器学习,探讨了主动机器学习的基本原理,这是一种高度有效的方法,与被动方法有显著不同。本章还提供了关于其独特策略和优势的见解。
第二章, 设计查询策略框架,全面探讨了主动机器学习中最为有效和广泛使用的查询策略框架,包括不确定性采样、委员会查询、期望模型变化、期望误差减少和密度加权方法。
第三章, 管理闭环中的人类,讨论了设计交互式主动机器学习系统的最佳实践和技术,重点在于优化闭环中的人类标记。涵盖了标记界面设计、有效工作流程的构建、解决模型与标记差异的策略、合适标记者的选择以及他们的有效管理等方面。
第四章, 将主动学习应用于计算机视觉,涵盖了利用主动机器学习的力量来增强计算机视觉模型在图像分类、目标检测和语义分割等任务中的性能的各种技术,同时也讨论了它们应用中的挑战。
第五章,利用主动学习处理大数据,探讨了用于管理大数据(如视频)的主动机器学习技术,并承认了由于视频分析模型的大尺寸和基于每秒帧率的频繁数据重复导致的开发挑战,并演示了一种主动机器学习方法,用于选择用于标记的最具信息量的帧。
第六章,评估和增强效率,详细介绍了主动机器学习系统的评估,包括指标、自动化、高效标注、测试、监控和停止标准,旨在进行准确的评估和深入了解系统效率,指导该领域的明智改进。
第七章,利用主动机器学习工具和包,讨论了用于主动学习的常用 Python 库、框架和工具,突出了它们在实施各种主动学习技术中的价值,并为初学者和经验丰富的程序员提供了一个概述。
要充分利用本书
您应具备熟练的 Python 编程技能,熟悉 Google Colab,并具备机器学习和深度学习原理的基础知识。您还需要熟悉像 PyTorch 这样的机器学习框架。
本书面向那些对机器学习和深度学习有基本理解,并希望获取有关主动学习知识以优化其机器学习数据集标注过程的人。这种优化将使他们能够训练出最有效的模型。
| 本书涵盖的软件 |
|---|
Python 包:scikit-learn、matplotlib、numpy、datasets、transformers、huggingface_hub、torch、pandas、torchvision、roboflow、tqdm、glob、pyyaml、opencv-python、ultralytics、lightly、docker、encord、clearml、pymongo和modAL-python |
| Jupyter 或 Google Colab 笔记本(Python 版本 3.10.12 及以上) |
您需要为各种工具创建账户:Encord、Roboflow和Lightly。您还需要访问AWS EC2 实例以进行第六章**,评估和提高效率*。
如果您使用的是本书的数字版,我们建议您亲自输入代码或从本书的 GitHub 仓库(下一节中有一个链接)获取代码。这样做将帮助您避免与代码复制粘贴相关的任何潜在错误。
下载示例代码文件
您可以从 GitHub(github.com/PacktPublishing/Active-Machine-Learning-with-Python)下载本书的示例代码文件。如果代码有更新,它将在 GitHub 仓库中更新。
我们还有其他来自我们丰富图书和视频目录的代码包,可在github.com/PacktPublishing/找到。查看它们吧!
使用的约定
在这本书中使用了多种文本约定。
文本中的代码: 表示文本中的代码单词、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 昵称。以下是一个示例:“我们定义x_true和y_true。”
代码块设置如下:
y_true = np.array(small_dataset['label'])
x_true = np.array(small_dataset['text'])
粗体: 表示新术语、重要单词或您在屏幕上看到的单词。例如,菜单或对话框中的单词以粗体显示。以下是一个示例:“异常检测是主动学习证明高度有效的另一个领域。”
小贴士或重要提示
看起来像这样。
联系我们
我们始终欢迎读者的反馈。
一般反馈: 如果您对这本书的任何方面有疑问,请通过 mailto:customercare@packtpub.com 给我们发邮件,并在邮件主题中提及书名。
勘误: 尽管我们已经尽最大努力确保内容的准确性,但错误仍然可能发生。如果您在这本书中发现了错误,如果您能向我们报告,我们将不胜感激。请访问 www.packtpub.com/support/errata 并填写表格。
盗版: 如果您在互联网上以任何形式发现我们作品的非法副本,如果您能向我们提供位置地址或网站名称,我们将不胜感激。请通过 mailto:copyright@packt.com 与我们联系,并提供材料的链接。
如果您有兴趣成为作者:如果您在某个领域有专业知识,并且您有兴趣撰写或为书籍做出贡献,请访问 authors.packtpub.com。
分享您的想法
一旦您阅读了《使用 Python 的主动机器学习》,我们很乐意听到您的想法!请点击此处直接转到该书的 Amazon 评论页面并分享您的反馈。
您的评论对我们和科技社区都至关重要,并将帮助我们确保我们提供高质量的内容。
下载这本书的免费 PDF 副本
感谢您购买这本书!
您喜欢在路上阅读,但无法携带您的印刷书籍到处走?
您的电子书购买是否与您选择的设备不兼容?
请放心,现在,随着每本 Packt 书籍,您都可以免费获得该书的 DRM 免费 PDF 版本。
在任何地方、任何设备上阅读。直接从您最喜欢的技术书籍中搜索、复制和粘贴代码到您的应用程序中。
优惠远不止于此,您还可以获得独家折扣、时事通讯和每日收件箱中的精彩免费内容。
按照以下简单步骤获取好处:
- 扫描二维码或访问以下链接

packt.link/free-ebook/9781835464946
-
提交您的购买证明
-
就这样!我们将直接将您的免费 PDF 和其他优惠发送到您的邮箱
第一部分:主动机器学习基础
在快速发展的机器学习(ML)领域,主动机器学习的概念作为一种变革性的方法出现,通过从未标记数据集中选择性地查询最有信息量的数据点来优化学习过程。本书的这一部分致力于阐述基础原理,例如不确定性采样、委员会查询、预期模型变化、预期误差减少和密度加权方法,以及理解和有效实施主动机器学习所必需的考虑因素。通过结构化的探索,我们旨在通过探讨标签界面设计、有效的工作流程、处理模型-标签不一致的策略、寻找合适的标签员以及高效管理他们,为读者提供闭环中管理人类的最佳实践。
本部分包括以下章节:
-
第一章,介绍主动机器学习
-
第二章,设计查询策略框架
-
第三章,管理闭环中的人类
第一章:介绍主动机器学习
机器学习模型需要大量标记的数据集,这可能既昂贵又耗时。主动机器学习(主动 ML)通过智能地选择人类应该标记的数据点来最小化所需的标记工作。在本书中,你将获得理解主动学习所需的知识,包括其机制和应用。有了这些基础知识,后续章节将为你提供具体技能,以便你能够自己实现主动学习技术。
在本书结束时,你将拥有使用最先进策略来最小化标记成本和最大化模型性能的实践经验。你将能够将主动学习应用于提高模型在不同应用领域的效率和适应性,例如视觉和语言。
首先,本章介绍了主动机器学习,并解释了它是如何使用更少的标记示例来提高模型准确性的。到本章结束时,你将涵盖以下内容:
-
理解主动机器学习系统
-
探索查询策略场景
-
比较主动学习和被动学习
理解主动机器学习系统
主动机器学习(主动 ML)是一种强大的方法,旨在创建具有非凡准确性的预测模型,同时最大限度地减少所需的标记训练示例数量。这是通过采用一种巧妙策略来实现的,该策略涉及选择最有信息量的数据点由知识渊博的预言者进行标记,例如人类标注者。通过这样做,主动学习使模型能够从相对较少的数据中提取所需的知识。
现在,让我们探讨一些定义和构成主动机器学习基础的基本概念。
定义
主动学习可以被定义为一种动态和迭代的机器学习方法,其中算法智能地与一个预言者互动来标记新的数据点。预言者是一个为主动学习查询的数据点提供标签的来源。预言者充当教师角色,通过为其最有信息量的查询提供标签来指导模型。通常,预言者是能够手动为新数据点分配标签的人类标注者或专家。然而,预言者也可以是模拟引擎、众包服务或其他能够标记的系统。
主动机器学习的关键目标是选择并优先考虑对模型最有信息量的数据点。目标是实现更高的准确率,同时最大限度地减少对大量训练标签的需求,与传统的监督学习方法相比,后者依赖于大量预标记的示例数据集来训练模型以预测结果。另一方面,无监督学习方法与未标记的数据一起工作,寻求模式或结构,而不需要关于结果的明确指导。主动学习通过专注于半监督学习策略来连接这些方法。这个过程允许模型通过利用最相关和最重要的数据点,随着时间的推移主动学习和适应,持续提高其预测能力。通过积极与数据互动并仔细选择哪些样本进行标记,主动机器学习优化了整个学习过程。它允许算法专注于最相关和最有信息量的实例,从而减少了对大量标签工作的需求。因此,主动机器学习不仅节省了时间和资源,而且使机器学习模型能够实现更高的准确率和更好的泛化。通过有效地优先考虑数据标签,主动机器学习为更高级和智能的机器学习系统打开了大门。
潜在的应用范围
主动学习是一种高度灵活的技术,可以显著提高各种应用中的效率和模型性能。它通过将人工标签工作引导到它们可以产生最大影响的地方来实现这一点。
这种方法在计算机视觉应用中已被证明特别有效,例如图像分类、目标检测和图像分割。通过选择性地获取传统采样方法经常错过的模糊图像的标签,主动学习可以降低成本并提高准确率。它是通过识别最具有信息量的边缘案例进行查询来实现的,允许在更少的标记样本下获得准确的结果。例如,如果我们考虑一个需要识别各种对象(如人、树木和其他汽车)的自动驾驶汽车目标检测模型,我们可以利用主动学习来优先考虑它可能难以学习的类别。
在自然语言处理任务中,例如文档分类和翻译,主动学习者在填补语言覆盖范围缺口方面发挥着至关重要的作用。通过查询涵盖罕见词汇和结构的句子,主动学习提高了适应性和整体性能。标签过程仅关注最有用的示例,最大限度地减少了对大量标签工作的需求。
异常检测是另一个活动学习证明高度有效的领域。通过针对罕见异常值和异常,这些对于识别欺诈等问题至关重要,活动学习提高了这些重要但罕见的示例的检测。通过将人工审查集中在异常案例上,活动学习提高了异常检测系统的整体准确性。
推荐系统高度依赖用户反馈,而活动学习提供了一个智能获取这种反馈的框架。通过查询用户对某些内容的偏好,活动学习收集了可以用于微调推荐的专注信号。例如,流媒体服务可以使用活动学习技术来提高其视频建议的准确性和相关性。
在医学诊断领域,活动学习技术在最小化医生在常见诊断上花费的时间方面发挥着至关重要的作用。通过识别需要专家输入的挑战性案例,活动学习确保了努力集中在可以显著提高诊断模型性能的模糊示例上。
活动学习提供了在各个应用中高效聚焦人力在有用区域的算法和机制。通过选择性获取标签,它克服了与监督机器学习相关的固有成本和挑战,使其成为人工智能领域的一项宝贵工具。在科学、工程和技术领域,智能引导数据收集和标注的能力可以以最小的人力加速进步。
现在,让我们继续讨论活动学习系统的关键组成部分以及它们如何应用于我们刚刚提到的所有应用。
活动学习系统的关键组成部分
活动机器学习系统由四个关键元素组成:
-
未标记数据集:这个未标记数据点的集合是活动学习器可以查询的。它可能包含数十、数百甚至数百万个示例。
-
查询策略:这是活动学习的核心机制。它指导系统选择哪些数据点查询标签。可以使用不同的标准,我们将在稍后探讨。
-
机器学习模型:正在训练的底层预测模型,例如神经网络、随机森林或 SVM。
-
预言者:提供标签的来源。这通常是能够手动标注查询数据点的人工标注员。
提到的关键组件是如何相互作用的?图 1.1描绘了活动机器学习循环中各个组件之间的相互作用:

图 1.1 – 活动机器学习循环
模型参与以下迭代循环:
-
查询策略确定了最需要标记的数据点。
-
这些标签由预言者(人工标注员)提供。
-
新标记的数据用于训练机器学习模型。
-
然后使用更新后的模型来指导下一轮的查询和标记。
这个循环允许主动学习模型智能地探索数据集,获取新的训练标签,以最大化信息增益。
在下一节中,我们将通过首先检查可以选择的各种场景来深入探讨查询策略步骤。
探索查询策略场景
主动学习可以根据未标记数据的性质和查询的执行方式以不同的方式实现。在实施主动学习时,需要考虑三个主要场景:
-
成员查询合成
-
基于流的选样
-
基于池的采样
这些场景提供了不同的方法来优化和改进主动学习过程。理解这些场景可以帮助你做出明智的决定,并选择最适合你特定需求的方案。在本节中,我们将探讨这些场景中的每一个。
成员查询合成
在成员查询合成中,主动学习器有能力创建自己的未标记数据点以改进其训练。这是通过从头生成新的数据点,然后请求预言者提供标签来完成的,如图图 1**.2所示。通过将这些新标记的数据点纳入其训练集,模型变得更加稳健和准确:

图 1.2 – 成员查询合成工作流程
让我们以图像分类器为例。借助合成的力量,主动学习器可以通过在不同组合中结合各种形状、纹理和颜色来创建新的图像。这允许模型探索广泛的可能性和学习识别在原始标记数据中可能不存在模式和特征。
类似地,文本分类器也可以从成员查询合成中受益。通过生成包含特定单词或结构的新的句子和段落,模型可以扩展其对不同语言模式的理解,并提高其准确分类文本的能力。
成员查询合成的优点有几个:
-
模型对其查询的数据点有完全的控制权,允许它专注于正常采样可能忽略的边缘情况和异常示例。这有助于减少过拟合,并通过增加数据的多样性来提高模型的一般化能力。
-
通过合成数据,模型可以主动探索其弱点,而不是依赖于训练数据中的内容。
-
这对于数据合成简单的问题很有用,例如简单的表格数据和序列。
然而,使用这种场景也存在一些缺点:
-
这需要能够准确合成新的有用数据点的能力。对于图像、音频和视频等复杂现实世界数据,这可能极其困难。
-
数据综合对于高维、细微的数据效果不佳。生成的点往往不够自然。
-
与基于池的采样相比,在今天的实际应用中,数据综合的实用性较低。生成模型的发展可以提高综合效果。
-
从头开始反复生成完整数据点在计算上非常昂贵,尤其是对于多媒体数据。
-
过度生成合成示例可能导致过拟合,其中模型过于专注于分类合成实例而不是实际数据。因此,当模型面对不熟悉和未见过的数据时,其准确性可能会受到影响。
总体而言,成员查询综合在理论研究中占主导地位,而在今天的实践中应用很少。然而,生成模型的发展可能会增加其在未来实际应用中的可行性。
基于流的选择性采样
在基于流的选择性采样中,接收未标记数据点的过程是持续和动态的,而不是静态和预定的批量。图 1.3展示了激活学习者如何被呈现为一系列连续的数据点:

图 1.3 – 基于流的选择性采样工作流程
激活学习者在每个单独的点是否请求标签的问题上需要做出即时决策。这个实时决策过程为学习算法增加了灵活性和适应性。这使得它可以根据传入数据流的演变特征即时调整其采样策略。通过主动选择查询标签的数据点,激活学习者可以优化学习过程,并最大限度地利用有限的标签资源。
基于流的选择性采样在包括用户活动、实时传感器数据以及新闻推送、社交媒体等多个来源的数据中找到其应用。
用户活动以点击、搜索和帖子等形式产生的大量数据。通过选择性地标记网站和应用程序上用户行为的部分以训练模型(例如,预测流失和参与度),基于流的选择性采样避免了存储所有用户行为的庞大日志。
另一方面,来自设备或机械的实时传感器数据需要持续监控。为了最小化这种疏忽,仅在自主系统的最关键传感器事件上执行标签查询。
在新闻推送、社交媒体流和内容推荐系统中,基于流的选择性采样有助于获取用户反馈,以推荐一小部分内容项。这种专注的用户输入改善了建议,而不会让用户感到不知所措。
在这些情况下,数据以实时方式不断到达。活跃学习模型评估每个新的数据点,并选择性地查询预言机对最有用的示例进行标记。不那么有用的点被丢弃而不是存储。
基于流的精选采样的主要优势如下:
-
它非常适合实时应用,因为需要处理不断变化的实时数据流
-
它在存储效率上很高效,因为不需要保存完整的数据流,只需保存查询的点
-
它是可扩展的,因为它涉及高效管理大量传入数据,而无需存储所有数据
然而,它也有一些缺点,如下列所示:
-
模型必须在数据流到达时即时评估和做出查询决策。没有进行深入分析的机会。
-
被丢弃的点不能在以后重新访问或重新查询。
-
没有从头开始重新训练,适应数据分布随时间的变化变得更加困难。
-
如果模型只对特定数据类型进行标记,可能会引入偏差。这可能导致模型针对这些特定数据类型进行了优化,但面对新数据时可能表现不佳。
-
该方法的有效性可能因流平台及其限制而异,这可能会限制其有用性。
总体而言,基于流的精选采样在存储需求和实时响应至关重要时是一种有效的方法。当流分布相对稳定时,它效果良好。如果流随时间变化,基于池的采样可能更有效,因为早期点可以被重新分析。
基于池的采样
在 基于池的采样 的背景下,活跃学习者可以访问一个大型未标记数据点集合,这些数据点随时间保持静态。在这种情况下,数据点通常来自现有的未标记数据集或标记数据集,其中标签暂时被隐藏。它们也可以通过抓取公共来源收集。
活跃学习从静态数据池中选择数据点并将其发送到预言机进行标记。与基于流的采样场景不同,没有数据点被丢弃。
图 1**.4 展示了一个基于池的采样工作流程:

图 1.4 – 基于池的采样工作流程
静态池作为数据集,学习者可以从中反复抽取样本,目的是获取最有信息量的标记示例。通过利用这个池,学习者可以探索并提取有助于学习过程的有价值见解。通过多次迭代采样,学习者可以加深理解并提高做出明智决策的能力。
样本池旨在为用户提供最大的灵活性,使他们能够在任何给定时间查询池中的任何点。这一功能允许无缝访问数据点,确保查询过程中的便利性和多功能性。池的大小基于计算约束确定,常见的大小从 10,000 到 1,000,000 个数据点不等。池的大小选择取决于各种因素,例如可用的计算资源和所使用模型的特定要求。
需要强调的是,在整个迭代过程中,样本池保持固定。模型持续查询并从样本池中选择最有价值的点,优化其性能并细化其结果。这种池与模型之间的动态互动对于在数据分析中实现最佳效率和准确性至关重要。
通过在迭代查询有价值点的同时保持固定的池大小,模型确保可以根据分析需求的变化进行适应和演变。这种迭代方法允许模型持续完善其理解并提高其预测,从而得出更有洞察力和更准确的结果。
例如,潜在的池数据集可能包括以下内容:
-
一个带有许多未标记行的数据库表
-
一组图像、音频剪辑或文档
-
一个带有标签暂时移除的现有机器学习数据集
基于池的采样具有以下优点:
-
样本具有最大的灵活性。任何点都可以被多次查询
-
样本策略可以在多次迭代中进行调整和改进
-
能够在模型变化时重新查询点并随着时间的推移进行微调
同样存在一些挑战:
-
需要有足够的存储空间来容纳完整的未标记样本池数据集
-
在大型、高维数据池中搜索最佳查询是计算密集型的
-
样本池不会像实时数据流那样随时间适应。
-
模型的准确性取决于用于识别最有信息量样本的选择方法,这可能会降低模型的准确性
总体而言,基于池的采样为许多现实世界的应用提供了最实用的主动学习方法。在足够的存储和计算能力下,它提供了迭代查询的完全灵活性。在实时性能至关重要的场合,流式采样可以补充。
探索了三种不同的主动机器学习场景后,我们现在可以评估它们与传统被动学习方法的不同之处。
比较主动学习和被动学习
在传统的被动机器学习中,模型是在固定和预先存在的标注数据集上训练的,这些数据集被精心组装以包括数据点和它们各自的地面真实标签。然后,模型一次性遍历数据集,没有任何迭代或交互,学习特征和标签之间的模式和关系。这就是被动学习的方法。重要的是要注意,模型只在其提供的有限数据上训练,不能主动寻求新信息或根据新输入修改其训练。此外,被动学习方法所需的标注数据集是有成本的。
传统机器学习中标注昂贵的原因有几个:
-
人工标注需要专家:准确标注数据通常需要领域专家如医生或生态学家的专业知识。然而,他们的时间是有限的且宝贵的,这使得他们的参与变得昂贵。
-
耗时过程:手动标注图像、音频剪辑或文本等数据是一项缓慢且繁琐的任务,扩展性不佳。准确标注单个数据点可能需要几分钟到几小时。虽然几个标注平台集成了功能和工具以使标注过程更加顺畅和快速,但它仍然很慢。
-
标注错误:由于过度劳累、匆忙或非专家标注员,一些标签可能质量较低。这些错误和噪声标签可能会对模型的性能产生负面影响。为了防止这种情况,通常需要额外的监督和一或多个审查步骤。
-
累积标注成本:当每小时标注成本乘以所需示例数量时,数据标注的整体费用可能会迅速变得难以承受,尤其是如果需要多个审查步骤。现代深度学习模型通常需要大量的标注示例,这可能非常昂贵。
-
扩展模型能力:随着新案例的出现,不断获取新的标注数据是一个持续的需求。持续标注不断变化的数据是一个挑战。
所有这些原因使得被动标注成为一个昂贵的瓶颈。最小化这些成本对于开发可扩展且准确的 AI 系统至关重要。
另一方面,主动学习采取了一种交互和迭代的途径。主动学习模型不是接收一个预定义的标注数据集,而是动态地选择它想要标注的数据点。它分析一个未标注数据池,并智能地选择最有用的点向专家查询标签。然后,新标注的数据被纳入其训练集中。
这引入了数据采样、人工标注和模型训练之间的反馈循环。模型通过获取专门针对改进其弱点的新训练数据来引导自己的学习。通过选择性采样,人力仅集中在最有信息量的示例上:

图 1.5 – 被动学习和主动学习 – 对比
主动学习的一个关键优势是它减少了所需的总标记数据量。被动学习者在达到期望性能时通常需要大量的标记示例,这可能会耗费大量成本和时间来收集和准备。主动学习通过仅获取提供最大信息价值的示例来最小化前期标记工作。
此外,主动学习系统可以在多次查询迭代中适应和调整。模型可以根据前几轮的结果改变其采样策略,重新查询某些示例,或增加对其最薄弱领域的关注。相比之下,被动学习涉及一个静态数据集,没有调整的空间。
总体而言,主动学习提供了降低标记成本和灵活、自适应训练的关键好处。通过自行引导数据收集,主动机器学习实现了更高的预测性能,同时显著减少了对大量标记数据集的依赖。
摘要
在本章的介绍中,我们涵盖了主动机器学习的基础以及它与被动学习方法的对比。
你已经学习了什么是主动学习以及其通过更少的标记训练示例来最大化预测性能的目标。我们讨论了主动学习系统的核心组件:未标记数据池、查询策略、机器学习模型和预言标签器。
你现在理解了成员查询综合、基于流的采样和基于池的采样场景之间的区别。我们比较了主动学习和被动学习,突出了主动学习中交互式、迭代方法的好处。
重要的是,你现在知道主动学习可以产生具有相等或更高准确性的模型,同时需要远少于标记训练数据。这对于降低建模成本至关重要,因为标记通常是成本最高的部分。
在本介绍中你获得的能力将使你能够确定何时主动学习适用于一个问题。你现在可以正确选择在实现主动学习系统时所需的正确组件。
现在我们已经介绍了主动学习的基础、查询场景和应用,下一步是深入了解特定的查询策略。在下一章中,我们将探讨设计有效查询的框架,以识别最有价值的标记数据点。
第二章:设计查询策略框架
查询策略作为驱动主动机器学习的引擎,并决定哪些数据点被选中进行标记。在本章中,我们旨在提供对主动机器学习中应用最广泛、最有效的查询策略框架的全面和详细解释。这些框架在主动机器学习领域发挥着至关重要的作用,有助于选择具有信息性和代表性的数据点进行标记。我们将深入探讨的策略包括不确定性采样、委员会查询、预期模型变化(EMC)、预期误差减少(EER)和密度加权方法。通过彻底理解这些框架及其背后的原理,你可以在设计和实现主动机器学习算法时做出明智的决策。
在本章中,你将获得设计并部署查询策略的技能,这些策略可以从标记工作中提取最大价值。你将获得在构建主动机器学习系统时将匹配策略与数据集和用例相匹配的直觉。
我们将涵盖以下主题:
-
探索不确定性采样方法
-
理解委员会查询方法
-
使用 EMC 采样进行标记
-
使用 EER 进行采样
-
理解密度加权采样方法
技术要求
对于本章中演示的代码示例,我们使用了 Python 3.9.6 以及以下包:
-
numpy(版本 1.23.5) -
scikit-learn(版本 1.2.2) -
matplotlib(版本 3.7.1)
探索不确定性采样方法
不确定性采样指的是查询模型对其预测最不确定的数据点。这些是模型认为最模糊且无法自信地自行标记的样本。将这些高不确定性点标记出来,允许模型阐明其知识不足之处。
在不确定性采样中,主动机器学习系统查询当前模型预测表现出高不确定性的实例。目标是选择位于类别之间的决策边界附近的数据点。标记这些模糊示例有助于模型在知识最薄弱的领域建立信心。
不确定性采样方法选择靠近决策边界的数据点,因为这些点表现出最高的预测不确定性。决策边界定义为模型在区分给定输入的不同类别时表现出最大不确定性的点。边界上的点代表模型最模糊、最不确定的情况。
图 2**.1展示了不确定性采样与随机采样的区别:

图 2.1 – 不确定性采样与随机采样的比较
对于位于类区域(标记为 A 或 B)内远离决策边界(图 2**.1)的数据点,模型将非常自信地将它们分配到该类(例如,>95%)。这些点被认为是确定的,在采用不确定性采样时不会被选中。然而,当使用随机采样时,可能选择其中的一些点。对于非常接近或直接位于决策边界上的数据点,模型将难以区分这些类别。预测的类概率将更加均匀分布,顶级预测非常接近。因此,这些点被认为是不确定的,在采用不确定性采样时将被选中。这些重要的数据点在使用随机采样时可能会被忽略。因此,到边界的距离与不确定性相关联——最接近边界的点将具有最低的最大置信度,顶级类别之间的最小边缘,以及类概率的最高熵。
因此,通过根据低置信度、低边缘和高熵度等指标选择点,不确定性采样查询了最接近决策边界的实例。我们将在本章接下来的部分详细讨论这些指标。对这些实例进行标注提供了帮助,有助于明确类区域并细化边界。模型不太可能从它已经可以高置信度正确预测的例子中获得很多信息。然而,直接查询模型非常不确定的数据点直接提供了关于其差距的有用信息。不确定性采样通过针对具有高预测模糊性的点来利用这一点。
例如,图像分类器的最小置信度预测很可能对应于具有挑战性的分布外示例,传统采样会错过这些示例。通过查询这些异常情况以获取标签,模型可以快速提高对边缘案例的分类能力。现在,让我们讨论一些用于不确定性采样的常用方法。
首先,我们将讨论最小置信度采样,其中数据点根据它们的最小置信度得分进行排序。这个得分是通过从每个项目的最自信预测标签中减去 1 来获得的,这代表 100%的置信度。为了便于理解,将不确定性得分转换为 0-1 的范围是有益的,其中 1 表示最高水平的不确定性。分配给每个数据点的分数的大小在于它与模型预测的不确定性之间的关联。因此,具有最高最小置信度得分的数据样本应该优先进行标注。
最具信息量的样本 x 可以按以下方式计算:

这里,我们有以下内容:

例如,假设我们有一个将样本分类为三个不同类别的模型。现在,我们正在尝试使用最小置信度采样方法对两个样本进行排序。样本 1 和样本 2 的预测概率分别为 [0.05, 0.85, 0.10] 和 [0.35, 0.15, 0.50]。让我们通过以下 Python 代码找出使用最小置信度采样方法时哪个样本最有信息量:
import numpy as np
# Model's probabilities of samples 1 and 2 for the 3 classes
probs_sample_1 = np.array([0.05, 0.85, 0.10])
probs_sample_2 = np.array([0.35, 0.15, 0.50])
def least_confident_score(predicted_probs):
return 1 - predicted_probs[np.argmax(predicted_probs)]
LC_samples_scores = np.array(
[least_confident_score(probs_sample_1),
least_confident_score(probs_sample_2)])
print(f'Least confident score for sample 1 is:
{LC_samples_scores[0]}')
print(f'Least confident score for sample 2 is:
{LC_samples_scores[1]}')
most_informative_sample = np.argmax(LC_samples_scores)
print(f'The most informative sample is sample
{most_informative_sample+1}')
上述代码片段的输出如下:
Least confident score for sample 1 is: 0.15000000000000002
Least confident score for sample 2 is: 0.5
因此,最有信息量的样本是样本 2。
在这个例子中,我们可以看到当使用最小置信度采样方法时,选择了样本 2,因为模型对该样本的预测最不自信。
接下来,我们将讨论边缘采样。这种方法旨在识别和选择在两个预测类别之间概率差异最小的数据点。通过关注类别之间最小边缘的数据点,我们可以有效地优先标注导致模型产生更高混淆程度的数据样本。因此,当模型遇到边缘分数较低的数据点时,其不确定性水平更高,这使得它们成为理想的标注候选。使用边缘采样方法计算最有信息量数据点分数的公式如下:

让我们再次使用我们之前的示例中的样本:
import numpy as np
# Model's probabilities of sample 1 and 2 for the 3 classes
probs_sample_1 = np.array([0.05, 0.85, 0.10])
probs_sample_2 = np.array([0.35, 0.15, 0.50])
def margin_score(predicted_probs):
predicted_probs_max_1 = np.sort(predicted_probs)[-1]
predicted_probs_max_2 = np.sort(predicted_probs)[-2]
margin_score = predicted_probs_max_1 - predicted_probs_max_2
return margin_score
# For sample 1
margin_score_sample_1 = margin_score(probs_sample_1)
print(f'The margin score of sample 1 is: {margin_score_sample_1}')
# For sample 2
margin_score_sample_2 = margin_score(probs_sample_2)
print(f'The margin score of sample 2 is: {margin_score_sample_2}')
margin_scores = np.array([margin_score_sample_1,
margin_score_sample_2])
most_informative_sample = np.argmin(margin_scores)
print(f'The most informative sample is sample
{most_informative_sample+1}')
上述脚本的输出如下:
The margin score of sample 1 is: 0.75
The margin score of sample 2 is: 0.15000000000000002
The most informative sample is sample 2
使用边缘采样方法,样本 2 也被选中,因为它在两个预测类别之间的概率差异最小。
在置信度比率方法中,选择具有最小概率比的数据点,即最高预测类别的概率与第二可能类别的概率之间的比率。这针对的是模型的前两个预测在可能性上最接近的例子。较低的比率表示模型对第二类相对于最高类别的置信度较低。通过查询最高两个类别概率之间的最小比率点,这种技术专注于模型在两个类别之间几乎无法区分的情况。将这些边界点标记出来将推动模型对真实类别有更大的信心。较低的比率意味着更高的歧义,因此置信度采样比率找到模型最不确定哪个类别是正确的点。
我们可以使用置信度采样方法通过以下方程计算最有信息量的数据点的得分:

再次,我们将使用之前用于此方法的样本:
import numpy as np
# Model's probabilities of sample 1 and 2 for the 3 classes
probs_sample_1 = np.array([0.05, 0.85, 0.10])
probs_sample_2 = np.array([0.35, 0.15, 0.50])
def ratio_score(predicted_probs):
predicted_probs_max_1 = np.sort(predicted_probs)[-1]
predicted_probs_max_2 = np.sort(predicted_probs)[-2]
margin_score = predicted_probs_max_1 / predicted_probs_max_2
return margin_score
# For sample 1
ratio_score_sample_1 = ratio_score(probs_sample_1)
print(f'The ratio score of sample 1 is: {ratio_score_sample_1}')
# For sample 2
ratio_score_sample_2 = ratio_score(probs_sample_2)
print(f'The ratio score of sample 2 is: {ratio_score_sample_2}')
margin_scores = np.array([ratio_score_sample_1, ratio_score_sample_2])
most_informative_sample = np.argmin(margin_scores)
print(f'The most informative sample is sample
{most_informative_sample+1}')
该脚本的输出如下:
The ratio score of sample 1 is: 8.5
The ratio score of sample 2 is: 1.4285714285714286
The most informative sample is sample 2
因此,当使用置信度采样方法时,选择样本 2,因为它具有最高预测类别概率与第二可能类别概率之间的最小比率。
另一种方法是熵采样。这种方法选择在类别概率分布上具有最高熵的数据点。熵表示预测类别概率的整体不确定性。熵值越高,模型的不确定性越大,类别上的概率分布越均匀。熵值越低,表示信心,概率集中在单个类别上。
通过查询具有最大熵的点,这种技术针对模型预测的类别概率分布最均匀的实例。这些高度不确定的点提供了最多的信息增益,因为模型不能强烈偏向一个类别——其预测是最不确定的。获取这些高熵点进行标记使模型能够对其最不确定的领域获得更多信心。总的来说,熵采样找到具有最高总模糊度的点。使用熵采样方法计算最有信息数据点得分的公式如下:

让我们再次使用这个方法来使用我们的样本示例:
import numpy as np
# Model's probabilities of sample 1 and 2 for the 3 classes
probs_sample_1 = np.array([0.05, 0.85, 0.10])
probs_sample_2 = np.array([0.35, 0.15, 0.50])
def entropy_score(predicted_probs):
return -np.multiply(predicted_probs, \
np.nan_to_num(np.log2(predicted_probs))).sum()
# For sample 1
entropy_score_sample_1 = entropy_score(probs_sample_1)
print(f'The margin score of sample 1 is: {entropy_score_sample_1}')
# For sample 2
entropy_score_sample_2 = entropy_score(probs_sample_2)
print(f'The margin score of sample 2 is: {entropy_score_sample_2}')
entropy_scores = np.array([entropy_score_sample_1, \
entropy_score_sample_2])
most_informative_sample = np.argmax(entropy_scores)
print(f'The most informative sample is sample
{most_informative_sample+1}')
此脚本输出以下结果:
The margin score of sample 1 is: 0.747584679824574
The margin score of sample 2 is: 1.4406454496153462
The most informative sample is sample 2.
使用熵采样,样本 2 被选中,因为它在类别概率分布上具有最高的熵。
这些常见的不确定性采样技术提供了简单但有效的策略来识别高度模糊的点进行查询。
现在,让我们探索不确定性采样为主动机器学习提供的关键好处:
-
不确定性采样是一种概念上直观且计算效率高的查询策略。如置信度、间隔、比率和熵等指标具有明确的不确定性解释,并且可以快速计算。
-
它通过查询最不确定的案例以获取其真实情感,积极增强模型在不确定区域中的信心,扩大知识边界。例如,情感分类器可以通过查询最不确定的案例来获得包含罕见短语的模糊评论的更多确定性。
-
不确定性采样在分类任务和各种模型类型(如支持向量机(SVMs)、逻辑回归、随机森林和神经网络(NNs))中具有广泛的应用。不确定性在分类任务中具有广泛的应用。
-
不确定性采样通过寻找模型无法解释的模糊异常值来用于异常检测。不确定性突出了不寻常的案例。
-
它可以通过寻找模型之间预测不一致的点来识别标签错误。高不确定性可能表明数据有噪声。
总体而言,不确定性采样是一种高度有效和通用的主动机器学习方法。它可用于各种领域,直观且高效。它有助于扩展模型的能力并发现未知点。无论是用于分类、回归还是其他机器学习任务,不确定性采样都能持续提高模型性能。通过选择不确定数据点进行标注,模型从信息丰富的例子中学习并改进预测。它在自然语言处理、计算机视觉和数据挖掘中已被证明是有用的。不确定性采样积极获取新知识并增强机器学习模型。虽然不确定性采样关注模型个体不确定的点,但查询委员会方法旨在通过识别模型集成分歧的点来增加多样性。我们将在下一节中讨论查询委员会方法。
理解查询委员会方法
查询委员会旨在通过查询模型集成分歧最大的点来增加多样性。不同的模型会在数据最不确定或模糊的地方产生分歧。
在查询委员会方法中,一组模型使用标记数据集进行训练。通过这样做,集成模型可以协同工作并提供更稳健和准确的预测。
这种方法的一个有趣方面是,它确定了导致集成成员之间最大分歧的数据点。然后,这个数据点被选中进行查询以获取标签。
这种方法之所以有效,是因为不同的模型往往在难以处理和边界示例上存在最大分歧,如图*2**.2 所示。这些是存在歧义或不确定性的实例,通过关注这些最大分歧的点,集成模型可以达成共识并做出更自信的预测:

图 2.2 – 使用五个未标记数据点的查询委员会采样
图 2.2揭示了模型 1 和 4 之间的分歧,而不是模型 2 和 3,关于数据点 2。类似的模式也可以在数据点 4 上观察到。因此,数据点 2 和 4 已被选中发送到预言机进行标记。
查询委员会是一种广泛使用且有效的活跃机器学习策略,它解决了不确定性采样的局限性。虽然不确定性采样可能会偏向当前的学习者,并可能忽略其估计者关注范围之外的至关重要示例,但查询委员会克服了这些挑战。这种方法涉及同时维护多个假设,并选择导致这些假设之间产生不一致的查询。通过这样做,它确保了对数据的更全面和多样化的探索,从而增强了学习过程。例如,一个图像分类器的委员会可能会在传统采样无法捕捉到的模糊图像上产生很大的分歧。通过查询具有最大分歧的图像标签,例如对不寻常物体的不同预测,委员会可以集体改进。
查询委员会采样的常见技术包括最大不一致、投票熵和平均 KL 散度,我们将在下面讨论这些内容。
最大不一致
这种简单的方法关注委员会成员之间预测标签的直接不一致。在标签上大多数集成成员存在分歧的数据点被查询。例如,如果一个三模型委员会的标签投票为(1,2,3),这表明最大不一致,因为每个模型预测了不同的类别。查询具有最多标签冲突的点有助于我们只关注分裂委员会的案例。最大不一致的目标实例在集成中造成了最大的分歧。对这些高分歧点进行标记的目的是解决模型之间的核心差异。
让我们通过一个活跃机器学习中的查询委员会最大不一致方法的数值示例来探讨。在这个例子中,我们将考虑一个包含 10 个未标记数据点的集合,如图图 2.3所示,我们希望对这些数据进行标记以训练一个分类器。我们创建了两个委员会成员(模型),分别称为 M1 和 M2。我们使用 M1 和 M2 评估每个未标记数据点,以获得以下预测标签:

图 2.3 – 用数值示例说明查询委员会最大不一致方法
然后,我们选择两个委员会成员之间分歧最大的数据点。在这里,数据点 1、4、5、8 和 9 被 M1 和 M2 预测为不同的标签。我们选择这些点中的一个,比如点 4,来查询来自先知者的真实标签。然后,我们将新标记的点添加到重新训练委员会成员。
我们可以用一个简单的 Python 脚本来实现:
import numpy as np
# Predicted labels from 2 committee members
y1 = np.array([0, 1, 0, 1, 0, 1, 0, 1, 0, 1])
y2 = np.array([1, 1, 0, 0, 1, 1, 0, 0, 1, 1])
# Calculate disagreement
disagreement = np.abs(y1 - y2)
# Find index of point with max disagreement
query_index = np.argmax(disagreement)
print(f"Data point {query_index+1} selected with maximum disagreement")
这将返回以下输出:
Data point 1 selected with maximum disagreement
然后重复此过程,查询委员会预测标签分歧最大的点,直到达到足够的性能。最有信息量的点通过委员会成员的最大分歧显现出来。
投票熵
这种技术计算了集成委员会中每个模型的标签投票的熵。熵代表整体不确定性,熵值越高意味着模型预测的分布越广。熵值较低表明模型在标签上大体上达成一致。查询投票分布中熵值最大的数据点有助于定位委员会显示最高集体不确定性和分歧的实例。对具有最大熵的点进行标记将推动集成向更大的一致性发展。总的来说,投票熵识别出最分裂委员会的案例,将标记重点放在它们的分歧上。如果我们回到使用数值示例来更好地理解基于委员会的投票熵方法的工作原理,我们可以再次使用一个包含 10 个未标记数据点的池,如图图 2**.4所示,以及一个由两个模型 M1 和 M2 组成的委员会。我们对数据点上的每个类别得到以下预测概率:

图 2.4 – 用一个数值示例来说明基于委员会的投票熵方法
我们按照以下方式计算每个点的投票熵:

这里,
是平均每个委员会成员的。
在计算投票熵时,委员会成员的概率会被平均,因为我们想测量整个委员会对一个数据点的总不确定性或分歧。通过平均,我们实际上得到了整个委员会对每个类别的概率的“投票”,而不仅仅是考虑个别成员的预测。这使我们能够选择委员会在数据点上最不确定或与其预测分歧最大的数据点:

图 2.5 – 用每类的平均值和计算出的熵来展示查询委员会投票熵方法的一个数值示例
具有最大熵的点将在模型之间产生最多的分歧。在 *图 2**.5 中,点 1、4、5、8 和 9 具有最高的熵,因此我们查询它们的标签。下一步将是重新训练模型并重复此过程。
我们也可以用一些 Python 代码来写这个:
import numpy as np
p1 = np.array([[0.6, 0.4], [0.2, 0.8], [0.8, 0.2], [0.4, 0.6], [0.7, 0.3],
[0.2, 0.8], [0.9, 0.1], [0.5, 0.5], [0.3, 0.7], [0.1, 0.9]])
p2 = np.array([[0.3, 0.7], [0.1, 0.9], [0.9, 0.1], [0.7, 0.3], [0.4, 0.6],
[0.1, 0.9], [0.8, 0.2], [0.4, 0.6], [0.6, 0.4], [0.2, 0.8]])
# Average probabilities per class
p_class0 = (p1[:, 0] + p2[:, 0]) / 2
p_class1 = (p1[:, 1] + p2[:, 1]) / 2
p_avg = np.concatenate((p_class0.reshape(-1, 1), \
p_class1.reshape(-1, 1)), axis=1)
# Calculate entropy
H = -np.sum(p_avg * np.log2(p_avg), axis=1)
query_index = np.argmax(H)
print(f"Data point {query_index+1} selected with maximum entropy of {H[query_index]}")
此脚本的输出如下:
Data point 1 selected with maximum entropy of 0.9927744539878083
接下来,我们将把重点转移到使用 KL 散度方法进行预测的计算上。
平均 KL 散度
此方法测量每个委员会成员预测的标签分布与所有成员的平均预测分布之间的Kullback-Leibler 散度(KL 散度)。
KL 散度定义为以下:

在这里,P 和 Q 是两个概率分布。
具有最高平均 KL 散度的数据点将被查询。更高的 KL 散度表明模型预测与委员会共识之间的差异更大。查询最大差异的点旨在针对个体模型与整体集成强烈不一致的实例。标记这些高差异点将使个体模型更接近委员会的平均值。平均 KL 散度识别出具有异常模型预测的案例,以便将标记重点放在协调上。让我们看一下我们的查询委员会平均 KL 散度方法的数值示例。同样,我们使用图 2**.6中显示的 10 个未标记数据点的池,以及一个由两个模型 M1 和 M2 组成的委员会。我们从 M1 和 M2 对每个数据点进行预测,并计算 M1 和 M2 预测之间的 KL 散度:

图 2.6 – 一个数值示例,说明查询委员会平均 KL 散度方法
我们计算 M1 和 M2 之间以及 M2 和 M1 之间的 KL 散度平均值。我们计算两个方向的 KL 散度(KL(M1||M2)和 KL(M2||M1))——因为 KL 散度是非对称的,它将根据方向给出不同的值。
从 M1 到 M2 的 KL 散度 KL(M1||M2)衡量 M2 的分布如何近似 M1 的分布。另一方面,KL(M2||M1)衡量 M1 的分布如何近似 M2 的分布。
在查询委员会中,我们想要衡量两位委员会成员分布之间的总差异。仅仅使用 KL(M1||M2)或仅仅使用 KL(M2||M1)将无法捕捉到完整的差异。通过取 KL(M1||M2)和 KL(M2||M1)的平均值,我们得到两个分布之间总差异的对称度量。这为两个委员会成员在数据点上的整体差异提供了更好的指示。
在两个方向上取平均 KL 散度确保我们选择两个模型预测之间最大互变异的点。这揭示了标记以解决委员会不确定性的最有信息量的点。具有最大平均 KL 散度的点是分歧最大的点。因此,这里点 1、4、5 和 9 具有最高的平均 KL 散度。然后我们会查询这些标签,重新训练模型,并重复此过程。
我们也可以用一些 Python 代码来实现这一点:
import numpy as np
p1 = np.array([[0.6, 0.4], [0.2, 0.8], [0.8, 0.2], [0.4, 0.6], [0.7, 0.3],
[0.2, 0.8], [0.9, 0.1], [0.5, 0.5], [0.3, 0.7], [0.1, 0.9]])
p2 = np.array([[0.3, 0.7], [0.1, 0.9], [0.9, 0.1], [0.7, 0.3], [0.4, 0.6],
[0.1, 0.9], [0.8, 0.2], [0.4, 0.6], [0.6, 0.4], [0.2, 0.8]])
KL1 = np.sum(p1 * np.log(p1 / p2), axis=1)
KL2 = np.sum(p2 * np.log(p2 / p1), axis=1)
avg_KL = (KL1 + KL2) / 2
print("KL(M1||M2):", KL1)
print("KL(M2||M1):", KL2)
print("Average KL:", avg_KL)
query_index = np.argmax(avg_KL)
print("\nData point", query_index+1, "selected with max average KL of", avg_KL[query_index])
这是我们的输出结果:
KL(M1||M2): [0.19204199 0.04440301 0.04440301 0.19204199 0.1837869 0.04440301
0.03669001 0.020411 0.1837869 0.03669001]
KL(M2||M1): [0.1837869 0.03669001 0.03669001 0.1837869 0.19204199 0.03669001
0.04440301 0.02013551 0.19204199 0.04440301]
Average KL: [0.18791445 0.04054651 0.04054651 0.18791445 0.18791445 0.04054651
0.04054651 0.02027326 0.18791445 0.04054651]
Data point 1 selected with max average KL of 0.18791444527430518
在探索用于执行查询委员会采样的不同方法时,我们发现这可能会非常计算密集。确实,如图图 2**.7所示,查询委员会技术是一种迭代方法,每次向训练集中添加新的标记数据时,都需要重新训练委员会中的模型:

图 2.7 – 查询委员会采样技术中的迭代过程
总之,这项技术旨在通过量化集成模型之间的一致性水平来识别信息查询点,并提供了几个关键优势:
-
通过寻找各种模型解释不同的点来促进多样性。这些技术可以有效地优先处理可能提供有价值信息的查询点,从而提高基于查询的学习过程的整体质量。
-
它通过积极寻找不太可预测或常见的查询点来鼓励探索,从而对数据集有更全面的理解。
-
它提供了构建包含 SVMs、NNs 等多种不同模型的委员会的能力。这种多功能性允许在做出重要决策时采用多样化的策略和方法。通过利用这些不同的模型,你可以获得更深入的见解并提高委员会的整体性能。查询委员会方法与传统技术(如 bagging 和 boosting)不同。其主要目标是选择最有信息的未标记数据点进行标记并包含在训练集中。另一方面,传统的集成方法(如 bagging 和 boosting)侧重于结合多个模型以增强整体预测性能。确实,查询委员会方法通过计算委员会成员之间的不一致性来找到最佳的查询点,正如我们之前所看到的。传统的集成通过投票或平均来组合预测以产生统一的预测。
-
在未标记数据池中,底层分布的表示有限的情况下,它非常有用。通过结合不同委员会成员的意见和预测,查询委员会方法可以有效地解决未标记数据池中覆盖不良分布所提出的挑战。
通过利用委员会的不同意见,查询委员会增强了学习系统的整体性能。
现在,我们将更深入地探讨 EMC 策略的实施及其潜在优势。
使用 EMC 采样进行标记
EMC 旨在查询那些在被标记和训练后将对当前模型产生最大变化的点。这侧重于对具有最高预期影响的点进行标记。
EMC 技术涉及选择一个特定的数据点进行标记和学习,以对当前模型的参数和预测造成最大的改变。核心思想是查询如果知道其标签,将对模型参数的最大变化产生影响的点。通过仔细识别这个特定的数据点,EMC 方法旨在最大化对模型的影响并提高其整体性能。这个过程涉及评估各种因素和分析每个数据点的潜在影响,最终选择预期将对模型产生最大变化的那个,如图图 2.8*所示。目标是提高模型的准确性并使其在做出预测时更加有效。
当我们提到查询导致模型目标更新更大的点时,我们讨论的是在输入空间的不确定区域中识别高度信息性的示例。这些示例在影响和提升模型性能方面起着至关重要的作用。通过关注这些特定实例,我们可以更深入地了解输入空间的复杂性和微妙之处,从而实现更全面的理解和改进的整体结果:

图 2.8 – EMC 采样
初始模型使用训练数据集进行训练。然后,根据将未标记样本包括在训练集中后模型输出的变化来评估这些样本。在图 2.8*中,图表显示了三个示例样本导致的模型输出变化(MOC)。在考虑所有数据的情况下,导致最大输出变化的样本被选中进行标记。
换句话说,在 EMC 采样中,过程从对未标记的示例进行排序开始。这种排序是通过估计如果每个示例都被标记,模型预测中预期会发生的变化来确定的。这种估计考虑了各种因素和考虑事项,最终为标记优先级提供了依据。
这种估计通常基于计算预期梯度长度(EGL)。EGL 方法估计如果模型在新的标记点上训练,损失函数梯度的预期长度。在训练判别概率模型时,基于梯度的优化通常被使用。为了评估模型的变化,我们可以检查训练梯度的尺寸。这个梯度指的是在训练过程中用来更新参数值的向量。简单来说,学习者应该选择实例,
,当标记并包含在标记数据集中时,
),将导致新的训练梯度具有最大的幅度:

在这里,||.|| 是每个结果梯度向量的欧几里得范数,θ 是模型参数,x 是一个未标记的点,y 是对 x 的预测标签,
是通过将训练元组
添加到标记数据集
中所获得的新梯度。具有更长预期梯度的数据点被优先用于查询。更长的梯度表示在训练过程中模型参数的预期变化更大。通过选择具有高预期梯度长度的点,模型专注于一旦标记将对模型产生重大影响的样本。这针对的是那些将对模型预测更新产生巨大影响的不确定区域中的点。简而言之,EGL 识别出那些可能显著重塑决策边界的数据点。
通过采用这种技术,算法可以精确地识别出预计将对模型预测产生重大改变的具体数据点。选定的示例随后被发送进行标记,因为它们被认为在有效训练模型方面具有最大的价值。一旦指定,这些信息样本就会无缝地集成到现有的训练数据中,从而促进对模型整体性能和准确性的必要更新和改进。
EMC 方法有几个关键优势:
-
它能够在输入空间内积极寻找有影响力和代表性不足的区域。这意味着它可以有效地识别在传统建模方法中可能被忽视或未得到足够关注的区域。假设我们正在训练一个预测房价的模型。输入特征包括平方英尺、卧室数量、位置等等。使用传统的建模方法,我们可能会收集一个随机样本的房屋来训练模型。然而,如果某些社区或房屋风格不太常见,这可能会导致某些社区或房屋风格代表性不足。EMC 方法会分析当前模型,并确定新训练数据可能导致模型预测最大变化的地方。例如,它可能会发现添加更多旧房屋的样本可以更好地校准模型对年龄影响价格的理解,或者从代表性不足的新郊区开发中收集数据可以提高该地区房屋的性能。通过积极寻找这些有影响力的区域,EMC 可以使模型在更少的整体训练示例下更加稳健。与被动或随机数据收集相比,它降低了输入空间中某些区域欠拟合的风险。它可以帮助揭示可能不是立即显而易见的隐藏模式或关系,从而进一步增强对数据集的整体理解。
-
它与概率模型和基于核的模型兼容。通过利用这些模型的概率性质,EMC 方法可以提供有洞察力和准确的预测。此外,它与基于核的模型的兼容性允许对复杂数据模式和相关关系有更深入的理解。这些特性的结合使 EMC 方法成为分析和解释广泛领域数据的有力工具。
-
它允许在每一步无需完全重新训练的情况下进行估计。这意味着过程可以更加高效且节省时间,因为它消除了反复从头开始训练模型的需求。相反,该方法通过关注模型参数的预期变化来估计模型的变化。通过利用这种方法,你可以在仍然获得准确和可靠估计的同时,节省宝贵的时间和资源。
总结来说,EMC 查询旨在识别对模型影响最大的点。它选择那些预期影响最大的点。这种方法在文献中广泛讨论,但由于其高计算成本,在实践中并未得到实施。
接下来,我们将探讨 EER 采样。这种技术通过选择预期对错误减少贡献最大的点来减少模型的误差。通过战略性地采样这些点,我们可以提高整体模型的准确性。
使用 EER 进行采样
EER 关注于衡量泛化误差的潜在下降,而不是像先前方法中看到的那样,关注模型期望的变化。目标是通过对当前标记集和剩余未标记样本进行训练来估计模型预期的未来误差。EER 可以定义为以下:

在这里,
是成对标记数据的集合,
,和
是估计的输出分布。L 是一个选择的损失函数,用于衡量真实分布
和学习者的预测
之间的误差。
这涉及到选择预计未来误差(称为风险)最低的实例进行查询。这使主动机器学习专注于减少长期泛化误差,而不仅仅是立即的训练性能。
换句话说,EER 选择那些在查询和学习后预计将显著减少模型在相同分布的新数据点上错误的数据点。通过关注如图*图 2**.9 所示的最小化未来预期误差的点,EER 旨在识别有价值的训练示例,这将增强模型有效泛化的能力。这项技术针对高价值的训练示例,通过最小化错误预测来提高模型的表现。
这种方法通过避免包含冗余的相似示例,而是专注于更好地覆盖特征空间的多样化边缘情况,有助于防止短期过拟合。例如,在图像分类器的情况下,该技术可能会优先考虑包含能够捕捉广泛特征的多样化边缘情况,而不是包含冗余的相似示例:

图 2.9 – EER 采样
可以使用各种损失函数来计算预期模型的预测误差,例如对数损失,其定义为
,或者 0/1 损失,其定义为
.
由于误差减少的估计,EER 会带来显著的时间成本。为了计算预期的泛化误差,分类器必须针对每个数据点重新优化,考虑其可能的标签。此外,还需要重新推断其他数据点的标签。然而,这项技术提供了一些关键优势:
-
它允许直接优化减少泛化误差的真实目标,而不是仅仅关注提高训练性能。通过优先考虑减少泛化误差,EER 允许在现实世界场景中进行更准确和可靠的预测。这不仅提高了模型的总体性能,还确保了它能够有效地推广到未见过的数据。
-
它考虑了对未见数据点的影响,而不仅仅是训练集。通过这样做,EER 有助于减轻过拟合,这是机器学习和统计建模中常见的挑战。过拟合发生在模型在训练数据上表现极好,但无法很好地推广到新的、未见过的数据时。EER 通过综合评估潜在错误及其减少来直接应对这个问题。这确保了模型的表现不仅限于训练集,而是扩展到现实世界场景,使其成为数据驱动决策的有价值工具。
EER 是一个预测性和鲁棒的查询框架,专注于最大限度地减少模型的一般化误差。与 EMC 方法类似,EER 方法在文献中是一个广泛讨论的话题。然而,它并没有在实用应用中得到广泛采用,主要是因为它对计算资源的需求非常显著。
我们将要探索的下一个采样方法是密度加权采样,旨在通过从所有密度区域中选择代表性点来提高多样性。
理解密度加权采样方法
密度加权方法是旨在仔细选择能够准确代表其各自局部邻域密度的点的途径。通过这样做,这些方法优先考虑对多样化聚类中心的标记,确保数据的全面和包容性表示。
密度加权技术在查询点时非常有用和有效。这些技术利用了信息性度量与密度权重的一个巧妙组合。一个 信息性度量 提供了一个分数,表示如果我们查询数据点的标签,它对改进模型有多有用。信息性越高,表示该点对标记和添加到训练集越有价值。在本章中,我们探讨了几个信息性度量,如不确定性和不一致性。在密度加权方法中,信息性分数与密度权重相结合,以确保我们在输入空间的不同区域选择具有代表性且多样化的查询。这是通过根据数据点的密度和信息性为其分配权重来实现的。信息性高且密度低的数据点将获得更高的权重,因此更有可能被选中进行标记。密集聚类中的点将获得较低的权重。密度和信息性通过乘法、指数或加法公式相结合。这平衡了信息性和密度,以实现多样性。
密度权重表示每个点周围局部邻域的密度,允许从不同密度中更全面和准确地采样点,如图 *图 2**.10 所示。这种方法避免了仅仅关注密集聚类的陷阱,这可能导致冗余点。通过考虑密度权重,这些技术保证所选点能够有效地捕捉数据集的整体分布。因此,获得的结果更有意义,并提供了对数据的更深入洞察:

图 2.10 – 密度加权采样
在 *图 2**.10 中,我们可以观察到样本密度在主动机器学习过程中的重要性。由于实例 1 位于决策边界附近,这使得它成为被选为最不确定实例的理想候选者。然而,如果我们更仔细地分析情况,很明显,选择实例 2 在提高模型整体质量方面会更有利。这是因为实例 2 不仅能够准确代表自身,而且还能代表数据分布中的其他实例。因此,将其纳入主动机器学习过程可以导致更全面和可靠的模型改进。
在前面的例子中,通过各种密度加权采样方法(如 kNN 密度、核密度估计(KDE)、K-均值聚类和最大均值差异(MMD))实现选择实例 2 的查询可以完成。
让我们从导入和生成虚拟数据开始:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.neighbors import NearestNeighbors
from sklearn.neighbors import KernelDensity
from sklearn.cluster import KMeans
from sklearn.metrics.pairwise import pairwise_distances
# Generate sample 2D data
np.random.seed(1)
X = np.concatenate((np.random.randn(100, 2) + [2, 2],
np.random.randn(50, 2)))
现在,让我们了解并应用不同的基于密度的技术来处理我们的 X 样本数据:
-
kNN 密度通过每个数据点的k 个最近邻来计算其周围的局部密度。密度是通过取到 k 个最近点平均距离的倒数来估计的。密度较高的点具有更高的密度,而孤立点具有较低的密度。估计的密度随后用作权重。当与信息性标准(如不确定性)结合时,稀疏邻域中的点会获得更高的密度权重,从而提高它们的优先级。kNN 密度加权提供了一种有效的方法来增加样本多样性,并在查询时避免对簇进行过度采样:
# kNN density knn = NearestNeighbors(n_neighbors=5).fit(X) distances, _ = knn.kneighbors(X) knn_density = 1 / distances.sum(axis=1) -
核密度估计(KDE)使用以点为中心的核函数来估计每个点周围的局部密度。通常使用高斯核。通过将附近点的核密度求和来获得整体估计密度。与 kNN 密度类似,稀疏区域的点与拥挤区域相比将具有较低的核密度。这些密度值可以与信息性标准结合使用作为权重。孤立簇中的点将被赋予更高的权重,从而提高它们的查询优先级。KDE 提供了一种平滑、概率性的局部密度估计,与 kNN 的离散簇相对。它比 kNN 计算成本更高,但在高维中可以高效实现。KDE 加权将采样集中在代表性低密度点上:
# Kernel density estimation kde = KernelDensity(kernel='gaussian', bandwidth=0.2).fit(X) kde_dens = np.exp(kde.score_samples(X)) -
K-means 密度使用 k-means 将未标记的数据点聚类成 k 个簇。每个簇的大小表示其密度——较小的簇对应于稀疏区域。这种簇密度可以与信息性标准结合使用作为权重。较小、更紧密的簇中的点会获得更高的权重,从而使其更有可能被查询。这平衡了不同密度下的采样。K-means 提供了一种简单的方法来估计密度并从所有密度中识别代表性点。它速度快,并且在大数据集上具有良好的扩展性。一个限制是预先确定簇的数量,k。K-means 密度加权将主动机器学习集中在所有密度的多样化案例上:
# K-means clustering km = KMeans(n_clusters=5).fit(X) km_density = 1 / pairwise_distances(X, km.cluster_centers_).sum(axis=1) -
最大均值差异(MMD)测量分布之间的距离以识别低密度区域的点。计算一个点的邻域分布与整体数据分布之间的 MMD。较高的 MMD 表明局部区域与整体分布非常不同,因此它很可能是一个低密度区域。然后,将这些 MMD 密度分数与信息性度量结合使用作为权重。具有高 MMD 的稀疏、孤立区域中的点在查询时将获得更高的优先级。这导致在变化密度上实现平衡采样,从而避免簇过度采样。MMD 提供了一种原则性的方法来估计密度,它捕捉了有用的非线性变化。MMD 密度加权将主动机器学习集中在代表性低密度区域上:
# Maximum Mean Discrepancy mmd = pairwise_distances(X).mean() mmd_density = 1 / pairwise_distances(X).sum(axis=1)
现在,让我们可视化这些密度加权采样方法:
# Plot the density estimations
fig, axs = plt.subplots(2, 2, figsize=(12, 8))
axs[0, 0].scatter(X[:, 0], X[:, 1], c=knn_density)
axs[0, 0].set_title('kNN Density')
axs[0, 1].scatter(X[:, 0], X[:, 1], c=kde_dens)
axs[0, 1].set_title('Kernel Density')
axs[1, 0].scatter(X[:, 0], X[:, 1], c=km_density)
axs[1, 0].set_title('K-Means Density')
axs[1, 1].scatter(X[:, 0], X[:, 1], c=mmd_density)
axs[1, 1].set_title('Maximum mean discrepancy (MMD) Density')
fig.suptitle('Density-Weighted Sampling methods')
plt.show()
结果图展示在 图 2**.11 中:

图 2.11 – 不同密度加权采样方法的比较
包括之前提到的在内的密度加权采样方法提供了多种优势:
-
它们可以帮助通过选择更有可能提供信息的样本来提高机器学习模型的表现。这是因为位于数据高密度区域的样本更有可能代表基础分布,因此更有可能对模型提供信息。
-
它们有助于减少训练模型所需的标注样本数量。这是因为密度加权采样可以帮助将标注工作集中在最有信息的样本上,这可能导致模型更快收敛。
-
它们可以与任何类型的数据一起使用。密度加权采样不对数据分布做出任何假设,因此可以与任何类型的数据一起使用,包括结构化和非结构化数据。
总结来说,密度加权,这是一种用于增加样本多样性和覆盖率的技巧,提供了一种有效且高效的方法。通过根据每个样本的密度为其分配权重,这种方法确保了结果样本集更准确地代表基础人群。采用这种方法,您可以获得对数据的更全面理解,从而进行更好的决策和分析。总的来说,密度加权是研究和统计分析中的一个宝贵工具,可以帮助您突出那些可能被忽视的隐藏模式和趋势。
现在我们已经讨论了几种查询策略,让我们比较它们以了解它们之间的表现:

图 2.12 – 查询策略比较图
图 2**.12 总结并比较了本章中讨论的各种查询策略。
摘要
在本章中,我们介绍了设计有效的主动机器学习查询策略的关键技术,如不确定性采样、委员会查询、EMC、EER 和密度加权。展望未来,在下一章中,我们的重点将转向探索管理闭环中人类角色的策略。优化与专家标签器的交互对于确保主动机器学习过程的最大效率至关重要。通过理解人类交互的复杂性并利用这些知识来简化标注过程,我们可以显著提高主动机器学习算法的效率和效果。在下一章中,我们将讨论如何管理主动机器学习中人类标注员的角色。
第三章:管理人机交互
活跃式机器学习通过智能选择由人类神谕进行标记的最具信息量的样本,承诺实现更高效的机器学习。然而,这些人机交互系统的成功取决于有效的界面设计和工作流程管理。在本章中,我们将介绍优化活跃式机器学习中人类角色的最佳实践。首先,我们将探讨交互式系统设计,讨论如何创建能够实现高效和准确标注的标记界面。接下来,我们将提供对管理标注管道的领先人机交互框架的广泛概述。然后,我们将转向通过裁决和质量控制处理模型与标签之间的不一致。之后,我们将讨论招募合格标注员和管理他们的策略。最后,我们将检查评估和确保高质量标注以及适当平衡数据集的技术。到本章结束时,你将具备构建充分利用人类与 AI 共生关系的优化人机交互系统的技能。
在本章中,我们将讨论以下主题:
-
设计交互式学习系统和工作流程
-
处理模型与标签不一致
-
有效管理人机交互系统
-
确保标注质量和数据集平衡
技术要求
在本章中,我们将使用huggingface包,因此你需要按照以下步骤进行安装:
pip install datasets transformers huggingface_hub && apt-get install git-lfs
此外,你还需要以下导入:
from transformers import pipeline
import torch
from datasets import load_dataset
import numpy as np
import pandas as pd
from sklearn.metrics import accuracy_score
设计交互式学习系统和工作流程
人机交互系统的有效性在很大程度上取决于标注界面和工作流程的设计是否得当。即使有先进的活跃式机器学习算法选择最有用的数据点,糟糕的界面设计也可能破坏标注过程。如果没有直观的控制、信息丰富的查询和适应人类的效率高工作流程,标注质量和速度将受到影响。
在本节中,我们将介绍优化与活跃式机器学习系统交互的人类体验的最佳实践。遵循这些指南将使你能够创建直观的标注管道,最大限度地减少歧义,尽可能简化标注过程。我们还将讨论集成活跃式机器学习查询、收集标注员反馈以及结合专家和众包标注员的策略。通过关注以人为中心的设计,你可以开发出最大化人类输入模型效用性的交互式系统。
首先,我们将提供之前提到的术语的定义,因为它们将是本节的主要内容。
标注界面是通过它,人类标注员为数据样本提供标签的用户界面,例如Roboflow、Encord和LabelBox等。它包括每个样本的视觉展示,以及输入或选择所需标签的控制和机制。例如,一个目标检测标注界面可能显示一张图像并提供绘制对象边界框和为每个框选择类别标签的工具。标注员可以使用界面控制来标注图像中出现的汽车、行人、动物和其他对象。这可以在图 3.1中看到,其中狗周围已经用狗类别绘制了边界框:

图 3.1 – 标注员在狗周围绘制边界框的标注界面示例
现在,让我们来谈谈工作流程。
工作流程是标注员完成标注任务所遵循的端到端步骤序列。它包括标注工作的完整生命周期,从接收待标注的样本,与界面交互应用标签,提交完成的标注,以及可能处理异常或错误,如图图 3.2所示。优化工作流程涉及简化这些步骤,以便标注员可以高效地完成标注。对于图像分类任务,工作流程可能如下进行:
-
标注员登录到标注系统并接收一批需要标注的图像。
-
标注员首先看到第一张图像,并使用界面应用标签。
-
标注员提交标注后的图像并继续到下一张图像。
-
在标注完一批图像后,标注员提交工作,这会触发一个质量检查阶段。
-
审查员检查标注图像的准确性和一致性。
-
如果发现任何错误,带有错误标注的图像将被退回给标注员,此时他们需要重新标注这些图像。
-
一旦所有图像通过质量检查,工作将被标记为完成:

图 3.2 – 标注工作流程的说明
简而言之,标注界面专注于与单个样本交互并应用标签的具体时刻。工作流程则更全面地看待整个过程以及如何顺畅地引导标注员完成标注工作。一个有效的人机交互系统需要在围绕人类用户设计这两个方面时都仔细考虑。
现在我们已经了解了标注界面和工作流程是什么,我们明白它们可以极大地影响一个活跃的机器学习系统中标注的效率、准确性和整体质量。在设计交互式系统时,有几个关键考虑因素:
- 直观且高效的界面:标记界面应该是直观且易于使用的。在选择您想要用于项目的标记界面时,请记住,标记者将使用的 UI 必须简单且高效。例如,在计算机视觉标注项目中,围绕感兴趣的对象绘制边界框或多边形是否容易?是否有加快标记过程的功能,例如使用预训练模型,如 Meta 的Segment Anything Model(SAM)(
segment-anything.com/),该模型可以分割图像中的任何对象并在图像上预先标记对象?Roboflow 提供的智能多边形功能是一个很好的例子,它允许用户使用多边形或边界框自动标记对象,如图图 3.3所示。我们将在本章后面讨论 Roboflow。

图 3.3 - Roboflow 的智能多边形功能,使用 SAM 自动在图像上标记对象,如blog.roboflow.com/automated-polygon-labeling-computer-vision/所示
-
入门资源:标记者使用标记平台所需的培训应尽可能少。为了最小化所需的培训量,一个有效的方法是提供一份由熟悉使用标记界面的知识人士最初编写的入门文档。然后,标记者可以在学习如何克服障碍的过程中自行编辑和更新该文档。这样,标记者的培训变得更加高效,因为他们可以利用每个标记者获得的知识,并将所学内容传授给新加入团队的新成员。
-
本体 – 命名约定:在设计标注项目的工作流程时,一个重要的考虑因素是仔细选择用于标注的类的名称。对于同一类使用多个拼写或词汇是常见问题。例如,在一个旨在对各种宠物进行分类的项目中,如果标注者决定使用狗的品种(例如,澳大利亚牧羊犬)而不是类狗,这可能会在以后造成问题。修复这些问题并不总是容易,可能耗时且昂贵。因此,选择一个允许使用标注本体的标注平台至关重要。标注本体是一个结构化词汇表,它提供了对如何标注数据的共同理解,定义了类,并概述了不同类之间的关系,特别是在存在嵌套结构的情况下。本体还应支持纠正拼写错误或错误的命名。在这种情况下,类的名称应该是可修改的,并更新使用该类标注的所有对象。此外,本体应在不同的标注项目中可共享,以确保一致性。本体应支持不同风格的标注,如边界框、多边形、分类等。例如,标注平台 Encord 具有灵活的标注本体功能,如图图 3.4所示。我们将在本章后面讨论 Encord:

图 3.4 – Encord 的标注本体
-
信息查询:提供给标注者的样本应提供足够的信息和上下文,以确保标注任务的清晰性。这可能涉及提供完整的文档或图像,而不仅仅是摘录。查询应设计得尽可能减少任何潜在的歧义。例如,当使用主动机器学习从未标记的视频中选择用于标注的最具信息量的帧时,仔细组织工作流程以确保标注者了解他们正在标注的具体视频至关重要。在这种情况下,解决方案是确保选定的帧按视频分开并排序后再发送到标注平台。然后,应将这些帧以包含因缺少未选帧而产生的跳跃的视频形式呈现给标注者。然而,需要注意的是,这些缺失的帧并没有完全消除整体上下文。Encord 的标注平台为这类情况提供了一个解决方案,其名为图像序列的功能。他们的图像序列格式将图像组以视频的形式呈现给标注者。
-
自动化工作流程:标注任务应尽可能自动化。创建任务的过程应涉及最小程度的人类干预。实现这种自动化的一个有效方法是通过实施一个脚本,该脚本可以在未标记的数据池上运行模型推理,然后使用这些预测在主动机器学习采样中,尤其是在利用不确定性采样时,最后将选定的数据样本发送到标注平台,并根据他们的可用性分配给标注者和审稿人。
-
标注者反馈:允许标注者对困难或模糊的样本提供反馈或提问,可以使注释质量随着时间的推移而提高。因此,标注平台应包括评论和聊天系统,这将允许标注者互相帮助或寻求领域专家和审稿人的指导。
通过关注这些方面,您可以创建适应人类优势和局限性的标注系统。精心设计的界面和工作流程导致更准确、一致和高效的注释,这对于机器学习项目的成功至关重要。现在,让我们探索您可以考虑的当前标注平台。
探索人类在循环的标注工具
人类在循环的标注框架对于实现人类与机器学习系统之间有效协作至关重要。在本节中,我们将探讨一些领先的用于主动机器学习的人类在循环标注工具。
我们将探讨这些框架如何允许人类通过优化人类-人工智能协作的界面和工作流程来提供注释、验证预测、调整模型置信度阈值以及指导模型训练。人类在循环框架提供的关键能力包括注释辅助的主动机器学习、人类验证预测、置信度校准和模型可解释性。
我们将要检查的标注工具包括 Snorkel AI、Prodigy、Encord、Roboflow 等。我们将通过示例说明如何利用这些工具在有效的人类指导下构建应用主动学习系统。我们将讨论不同方法的优缺点。在本节结束时,您将深入了解如何根据您的用例需求和限制确定适合您的机器学习项目的正确人类在循环框架。
常见的标注平台
许多标注平台提供了一系列数据标注功能,包括人工智能辅助标注、主动机器学习、协作工具和质量控制工具。然而,它们在定价、模型训练、部署能力、数据管理和整理工具以及模型可解释性功能方面存在差异。例如,当我们检查如图 3.5 所示的六种最常用的标注平台时,我们可以观察到这些区别:

图 3.5 – 六个最常见的标注平台比较表
总体而言,之前提到的所有标注平台都提供了各种优点和缺点。选择一个适合特定 ML 项目需求和要求的平台非常重要。
如果你正在寻找一个具有广泛功能平台的用户,包括 AI 辅助标注、主动学习、协作工具和质量控制,那么 Snorkel AI (snorkel.ai/)、Encord (encord.com/)、LabelBox (labelbox.com/)和 Dataloop (dataloop.ai/)可能是适合你的选择。另一方面,如果你需要一个专门为自然语言处理(NLP)任务设计的平台,那么 Prodigy (prodi.gy/)可能是一个不错的选择。
接下来,我们将检查如何处理模型与人工意见不一致的情况。
处理模型与标签之间的不一致
模型预测与人工标签之间的不一致是不可避免的。在本节中,我们将研究如何识别和解决冲突。
编程识别不匹配
为了识别模型预测与人工标注标签之间的差异,我们可以编写一些简单的 Python 代码来突出显示这些不匹配以便审查。
让我们考虑一个 NLP 情感分类器的例子。这种分类器旨在分析和理解文本中表达的情感或情绪。通过检查给定文本中使用的单词、短语和上下文,NLP 情感分类器可以确定情感是正面、负面还是中性。首先,我们将使用 Huggingface 的sentiment-analysis模型:
sentiment_pipeline = pipeline("sentiment-analysis")
data = ["I love you", "I hate you"]
sentiment_pipeline(data)
这返回以下输出:
[{'label': 'POSITIVE', 'score': 0.9998656511306763},
{'label': 'NEGATIVE', 'score': 0.9991129040718079}]
模型正确地分类了这两句话。现在,我们想要研究是什么标志了标注数据集与模型预测之间的不匹配,以便进行进一步审查。因此,我们将从huggingface下载一个名为imdb的标注数据集。这个数据集是一个大型的电影评论数据集,用于二元情感分类。我们可以使用以下代码行来加载数据集:
imdb = load_dataset("imdb")
为了测试目的,我们只使用几个样本:
small_dataset = imdb["train"].shuffle(seed=120).
select([i for i in list(range(5))])
print(small_dataset)
这返回以下输出:
Dataset({
features: ['text', 'label'],
num_rows: 5
})
我们可以通过查看数据集的最后一条记录来更好地了解这个数据集:
small_dataset[-1]
这给出了以下输出:
{'text': "Shot into car from through the windscreen, someone is playing someone else their latest song, someone else didn't react, according to the voice-over. I just wonder how that came to be made. There were too many scenes in this movie that I wondered about how come a camera was there. If the scenes shot where the Warhols descended on a BJM post-party are true then that was inexcusable exploitation to the max, if not, then it was a total fabrication, either way it made me uncomfortable, if that was the purpose? All the way thru this movie I kept wondering how the footage came about. Taken at face value, a nice portrait of the (tortured) genius we all believe ourselves to be.",
'label': 1}
在这里,我们有一个名为text的字段,它提供了电影的评论,还有一个名为label的字段,它将情感分类为正面或负面。在这种情况下,它是正面的。
让我们收集模型对这五个样本的预测:
classes = ['NEGATIVE', 'POSITIVE']
results = []
for review in small_dataset['text']:
results.append(classes.index(sentiment_pipeline(review)[0]['label']))
print(results)
这返回以下输出:
[1, 0, 0, 1, 0]
现在,为了找出我们是否有与数据集原始标注的不匹配,我们必须定义x_true和y_true,如下所示:
y_true = np.array(small_dataset['label'])
x_true = np.array(small_dataset['text'])
在这里,x_true是一个包含评论的数组,而y_true是一个包含标签的数组。我们可以将这些与模型的预测进行比较:
# Compare to true labels
mismatches = np.where(results != y_true)[0]
# Return mismatched samples
X_mismatched = x_true[mismatches]
y_mismatched = y_true[mismatches]
print(f"There are {len(X_mismatched)} mismatches: {X_mismatched}")
这将返回以下输出:
There are 2 mismatches: ['"Meatball Machine" has got to be one of the most complex ridiculous, awful and over-exaggerated sci-fi horror films that I have ever came across. It is about good against evil and a coming-of-age tale, with the aim of to entertain with bloody, sleazy and humorous context. Because of that the violence isn\'t particularly gruesome and it doesn\'t make you squirm, but the gratuitous bloodletting and nudity does run freely. The performances by Issei Takahashi and Toru Tezuka is the worst i have seen, if that was not enough it is also directed by an unheard of director called Yudai Yamaguchi. This movie just have it all, it is bad to the bone!, A must see for every b-movie freak!!!... Simply: an enjoying and rare gem.'
"Shot into car from through the windscreen, someone is playing someone else their latest song, someone else didn't react, according to the voice-over. I just wonder how that came to be made. There were too many scenes in this movie that I wondered about how come a camera was there. If the scenes shot where the Warhols descended on a BJM post-party are true then that was inexcusable exploitation to the max, if not, then it was a total fabrication, either way it made me uncomfortable, if that was the purpose? All the way thru this movie I kept wondering how the footage came about. Taken at face value, a nice portrait of the (tortured) genius we all believe ourselves to be."]
在这里,模型和人类不一致的数据点已被返回。在这种情况下,这些数据点将被选中进行额外审查。
手动审查冲突
在采样不匹配案例后,我们可以进行手动审查。以下是一些示例场景:
-
模型预测的是狗,但人类标注的是猫。在审查过程中,照片质量很差,实际上是一只狗。这是一个人为错误。
-
模型预测的是负面情绪,但根据审阅者的判断,文本是自信地正面的。这表明模型存在弱点,需要修复。
对模型预测进行手动审查可以提供关于模型和人类标注者所犯错误的有价值见解。一个关键优势是它能够识别训练数据中的系统性偏差,以及模型以人类不会的方式失败的情况。然而,手动审查耗时且受限于人类的主观性和监督。通常,只有一小部分案例被审查,这可能无法揭示模型的所有弱点。虽然手动审查在模型开发期间作为有用的调试工具很有用,但进行大规模审查通常不切实际。在这种情况下,可能需要采用如主动学习周期等替代技术来进一步提高模型的鲁棒性。
利用不匹配采样的另一种方式是将不匹配的样本包含在主动机器学习池中重新标注。这有助于更好地理解复杂案例,并使模型能够更有效地处理此类案例。这种持续添加和重新标注数据的迭代过程有助于微调模型,而无需手动审查。
通过系统地识别、理解和解决模型与标注之间的不一致,系统会随着时间的推移而改进。关键是在这个过程中保持人类的监督。在下一节中,我们将讨论如何管理闭环人类系统。
有效管理闭环人类系统
获取高质量的标注需要找到、审查、支持和保留有效的标注者。构建一个符合机器学习项目要求的适当标注团队至关重要。
第一个选择是建立内部标注团队。这涉及到雇佣全职员工进行数据标注,这有助于密切管理和培训。当内部进行时,培养领域专业知识更容易。然而,这种方法也有缺点,例如成本较高和人员流动。这种方法仅适用于大型、持续的数据标注需求。
另一种选择是使用 ScaleAI 等平台进行众包标注任务,这些平台允许将标注任务分配给大量按需工作的人员。这种选择提供了灵活性和较低的成本,但可能缺乏领域专业知识。与匿名众包工作者合作时,质量控制变得具有挑战性。
您可以使用第三方标注服务,例如 Innovatiana,该服务专门为 ML 项目提供训练有素的标注员。此选项利用现有的标注团队和工作流程。然而,这可能比众包成本更高,且管理起来更具挑战性。
最后,混合选项也是可行的。例如,您可以使用结合第三方标注员和内部审查员的混合策略。最佳方法取决于预算、时间表、数据敏感性、领域专业知识以及项目范围。来源的组合提供了灵活性。关键是实施强大的培训、验证和监控,以从任何标注资源中获得所需的质量。
接下来要问的问题是如何高效地管理标注 团队。
为了最大限度地提高效率,管理标注团队需要制定明确的指南,使标注员了解期望和整体目标。如本章前面所述,工作流程应结构化以优化标注员的时间,尽可能自动化,并最小化重复性任务。提供良好的工具也是关键。
当可行时,给予标注员访问仪表板和指标的权利,以便他们可以看到不断增长的数据库。这使他们保持对过程的参与。例如,在图 3.6 中,我们可以看到在 Encord 平台上,标注员可以看到他们已经标注了多少以及还剩下多少:

图 3.6 – Encord 的标注项目实例标签任务状态
开放沟通渠道使标注员能够轻松讨论模糊性、提问并提供反馈。让自己成为一个可利用的资源。审查标注速度、准确性和成本,以识别通过改进工具、培训或工作流程来提高生产力的机会。
有效的管理还要求定期举行会议来讨论进度、问题和反馈。指派资深标注员帮助培训和支援新成员。将大型项目分解为阶段,并设定里程碑以保持专注。突出表现优异者并庆祝胜利以激励团队。通过指导和培训解决表现不佳的问题。
通过强大的培训、优化的工作流程、沟通和绩效管理,标注团队能够高效工作。
另一个需要注意并解决的问题是,标注者可能会根据他们的个人经验、文化背景或对当前任务的误解引入偏差。这可能导致某些观点或特征在数据集中过度或不足代表,从而影响基于这些数据集训练的机器学习模型的公平性和准确性。有偏差的标注可能导致 AI 模型持续或甚至放大这些偏差。这在面部识别、情感分析和预测警务等敏感应用中尤其令人担忧,因为有偏差的数据可能导致不公平或歧视性的结果。随着机器学习的发展,越来越重视开发通用基础模型,这些模型可以显著减少对大量人工标注的依赖。
注意
通用基础模型是一种多才多艺的 AI 系统,它已经在大量数据上进行了训练,可以适应或微调以执行不同领域内广泛的任务,而无需从头开始进行特定任务的训练。
这样的创新例子是当 SAM 作为标注平台上的一个功能使用时,它有助于加速标注,体现了理解和分割图像或视频中的各种对象的能力,而无需为每个新的对象类型进行明确、详细的人工标注。这不仅通过减少手动标注来简化开发过程,还旨在通过依赖可以适应各种场景的通用学习能力来减轻偏差,而不继承一小部分人类标注者的特定偏差。然而,这些基础模型的设计和训练仍然需要仔细考虑它们所训练的数据以及这些数据集中固有的潜在偏差,突出了在 AI 领域公平性和伦理考量持续的重要性。
即使有一个高效的标注团队,我们能否确保标注质量在时间上的一致性?在下一节中,我们将探讨这个问题,并讨论确保标注持续质量的方法。
确保标注质量和数据集平衡
维护高标注质量和目标类别平衡需要勤勉的管理。在本节中,我们将探讨一些可以帮助确保标注质量的技巧。
评估标注者技能
非常推荐标注者在独立工作之前接受彻底的培训课程并完成资格测试。这确保了他们在各自任务上拥有坚实的知识和理解基础。这些性能指标可以在标注平台上通过审查者接受或拒绝标注时进行可视化。如果一个标注者有许多被拒绝的标注,有必要确保他们理解任务并评估可以提供的帮助。
建议定期通过提供用于评估的控制样本来评估标签者的技能。这种持续的评估有助于保持他们工作质量的一致性。
例如,设计带有已知标签的数据集,并要求标签者对这些评估集进行标注,可以是一种检查任务是否理解良好的好方法。然后,我们可以使用简单的 Python 脚本来评估标注的准确性。
首先,我们必须定义一些标签者已做的虚拟标注和一些真实标注:
dummy_annotator_labels = ['positive', 'negative', 'positive',
'positive', 'positive']
dummy_known_labels = ['negative', 'negative', 'positive', 'positive',
'negative']
然后,我们必须使用 sklearn 函数计算准确率和 kappa 分数:
accuracy = accuracy_score(dummy_annotator_labels, dummy_known_labels)
print(f"Annotator accuracy: {accuracy*100:.2f}%")
kappa = cohen_kappa_score(dummy_annotator_labels, dummy_known_labels)
print(f"Cohen's Kappa: {kappa:.3f}")
这将返回以下输出:
Annotator accuracy: 60.00%
Cohen's Kappa: 0.286
这种技术是实现标注者技能基本评估的简单易行方法。目标是准确性超过 90% 和 kappa 分数超过 0.80,然后我们可以调查不良的协议。
使用多个标注者
如果您的预算允许,您可以将每个数据点分配给多个标注者以识别冲突。然后,可以通过共识或由专家审阅员来解决这些冲突。
例如,在情感分析标注中,我们有三个标签者的虚拟标注:
dummy_annotator_labels_1 = ['positive', 'negative', 'positive',
'positive', 'positive']
dummy_annotator_labels_2 = ['positive', 'negative', 'positive',
'negative', 'positive']
dummy_annotator_labels_3 = ['negative', 'negative', 'positive',
'positive', 'negative']
我们可以使用来自三个标签器的标签创建一个 pandas DataFrame:
df = pd.DataFrame({
"Annotator1": dummy_annotator_labels_1,
"Annotator2": dummy_annotator_labels_2,
"Annotator3": dummy_annotator_labels_3
})
然后,我们可以将多数投票作为真实标签:
df["MajorityVote"] = df.mode(axis=1)[0]
print(df["MajorityVote"])
这将返回以下输出:
0 positive
1 negative
2 positive
3 positive
4 positive
这种方法可能成本较高,因为标签器在相同的数据上工作,但它最终可能导致更准确的标注。其可行性取决于机器学习项目的优先级,以及标注团队的预算和组织。例如,如果标注团队由对领域新手的初级标签器组成,这种方法可能是一个合适的选择。
平衡采样
为了防止数据集不平衡,我们可以在数据收集期间以更高的比率主动采样少数类。
在收集数据集时,重要的是要监控标签在各个类别之间的分布,并相应地调整采样率。如果没有干预,由于自然的高频率,数据集往往偏向于多数类。
让我们看看一些在更高比率上主动采样少数类的方法:
-
采用如不确定性采样等主动机器学习方法可能会使选择偏向于罕见案例。实际上,不确定性采样会主动选择当前模型最不确定的数据点进行标注。这些通常是边缘案例和罕见示例,而不是模型已经看到很多示例的常见案例。由于,根据定义,少数类出现的频率较低,模型对这些类自然更不确定。因此,不确定性采样倾向于从代表性不足的类别中选取更多示例进行标注,以改善模型的理解。
-
在数据收集期间定期检查标签分布很重要。如果少数类代表性不足,建议有选择性地采样更多具有这些标签的数据点。这可以通过使用能够识别未代表类别的预训练模型从未标记数据池中采样数据来实现。为了确保更高的代表性,采样策略应设置为以更高的比例选择特定类别。例如,让我们重新使用 Hugging Face 的imdb数据集:
dataset = load_dataset('imdb')为了测试目的,我们假设数据集是无标签的,并且附加到其上的标签来自模型的预测。因此,我们的目标是采样代表性不足的类别。假设类别
0是代表性不足的,我们希望对其进行过采样。首先,我们必须将训练数据集作为我们的虚拟无标签数据池,并将其转换为 pandasDataFrame:dummy_unlabeled_dataset_with_predictions_from_a_model \ dataset['train'] df = pd.DataFrame( dummy_unlabeled_dataset_with_predictions_from_a_model) -
接下来,我们必须获取每个标签的数据点数量:
n_label_0 = df[df['label'] == 0].shape[0] n_label_1 = df[df['label'] == 1].shape[0] -
现在,我们必须计算每个标签要采样的样本数量,假设我们想要采样 1,000 个样本,并且我们希望其中 80%的样本属于类别
0,20%属于类别1:nb_samples = 1000 n_sample_0 = int(0.8 * nb_samples) n_sample_1 = int(0.2 * nb_samples) sample_0 = df[df['label'] == 0].sample(n_sample_0, replace=False) sample_1 = df[df['label'] == 1].sample(n_sample_1, replace=False) # Concatenate the two samples into a single dataframe sample_df = pd.concat([sample_0, sample_1], ignore_index=True) # Print the sample dataframe print(f"We have {len(sample_df['label'][sample_df['label']==0])} class 0 samples and {len(sample_df['label'][sample_df['label']==1])} class 1 samples") We have 800 class 0 samples and 200 class 1 samples因此,我们按照正确的比例进行了采样,理论上可以将这些样本添加到我们的标记队列中。通过从未标记数据中为类别
0设置更高的采样率,我们在获取新的标记数据时,有选择性地对少数类进行了过采样。
关键是密切跟踪标签分布的演变,并将采样引导到代表性不足的类别。这防止了高度不平衡的数据集,这些数据集未能为少数类提供足够的示例。结果是更高质量、更平衡的训练数据。
摘要
本章探讨了将人工输入有效融入主动机器学习系统的策略。我们讨论了如何设计工作流程,以实现人类与 AI 模型之间的有效协作。回顾了包括其注释、验证和主动学习能力在内的领先开源框架。
处理模型与标签之间的不一致性是人与 AI 系统中的关键挑战。例如,手动审查冲突和主动学习周期等技术有助于识别和解决不匹配。仔细管理人工标注工作团队也是至关重要的,因为它涵盖了招聘、培训、质量控制和技术工具。
主要重点是确保使用如资格考试、注释者间度量(如准确率或 Kappa 分数)、共识评估和针对性采样等方法获得高质量的平衡数据集。通过在协作、冲突解决、标注者管理和数据标注质量周围实施稳健的过程,可以最大化循环中人工输入的有用性。
在下一章中,我们将把我们的重点转向应用专门针对计算机视觉任务的主动机器学习(ML)方法,例如图像分类、语义分割和目标检测。
第二部分:实践中的主动机器学习
在第一部分建立的基础知识之上,本书的第二部分第二部分从理论转向应用,展示了主动机器学习在各个项目中的强大影响。本节精心设计,旨在展示主动机器学习原则如何应用于解决现实世界的问题,强调使用计算机视觉示例的实际实施。通过详细的案例研究和深入实例,读者将深入了解面对实际数据的复杂性时,主动机器学习策略的多样性和效率。
本部分包括以下章节:
-
第四章,将主动学习应用于计算机视觉
-
第五章**,利用主动学习处理大数据
第四章:将主动学习应用于计算机视觉
在本章中,我们将深入探讨使用主动学习技术进行计算机视觉任务。计算机视觉涉及分析图像和视频等视觉数据以提取有用信息。它严重依赖于卷积神经网络等机器学习模型。然而,这些模型需要大量的标记训练集,这可能既昂贵又耗时。主动机器学习通过交互式查询用户仅对最有信息量的示例进行标记来提供解决方案。本章演示了如何为各种计算机视觉任务实现不确定性采样。到本章结束时,您将拥有使用优化标记努力高效训练计算机视觉模型的工具。所提出的主动机器学习方法为在更少的数据需求下构建鲁棒的视觉系统开辟了新的可能性。
到本章结束时,您将能够做到以下事项:
-
在图像分类项目中实现主动机器学习
-
将主动机器学习应用于目标检测项目
-
使用主动机器学习进行实例分割项目
技术要求
在本章中,您需要安装 Ultralytics、PyYAML 和 Roboflow 包。
Ultralytics 是一个流行的开源 Python 库,用于构建高性能计算机视觉和深度学习模型。它提供了包括 YOLO 在内的最先进的对象检测和图像分割模型的实现,这些模型可以在自定义数据集上训练。
PyYAML 是一个 Python 库,用于读取和写入 YAML 文件。YAML 是一种人类可读的数据序列化格式。PyYAML 允许将 YAML 数据从文件或字符串加载到 Python 数据类型,如字典和列表。它还可以将 Python 对象转储回 YAML 字符串。
如前几章所述,Roboflow 是一个帮助准备和管理计算机视觉模型数据集的平台。它提供了注释图像、创建训练/测试分割以及以 PyTorch 等深度学习框架可用的格式导出标记数据集的工具。Roboflow 还与 Ultralytics 等库集成,以简化训练流程。主要目标是简化开发 CV 模型的数据集管理方面。
要安装这些包,我们可以运行以下代码:
pip install ultralytics && pip install pyyaml && pip install roboflow
您还需要以下导入:
import torch
from torch.utils.data import DataLoader, Subset
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
import torchvision
import torch.optim as optim
import matplotlib.pyplot as plt
import numpy as np
from tqdm import tqdm
from roboflow import Roboflow
import glob
import os
import yaml
import cv2
此外,您还需要一个 Roboflow 账户以获取 Roboflow API 密钥。您可以在以下链接创建账户:app.roboflow.com/.
在图像分类项目中实现主动机器学习
在本节中,我们将指导您实现图像分类项目的主动机器学习技术。图像分类在计算机视觉领域有各种应用,从为电子商务网站识别产品到检测地理空间瓦片上的森林砍伐模式。然而,创建准确的图像分类器需要大量的标记图像数据集,这可能会非常昂贵且耗时,如第一章中所述,介绍主动机器学习。主动机器学习通过交互式请求仅对最有信息量的示例进行标记,为这一标记瓶颈提供了解决方案。
我们将构建一个图像分类模型,该模型能够准确地对从 CIFAR-10 数据集中获得的各类图像进行分类。这个数据集在计算机视觉领域广为人知,包含了一个多样化的 60,000 张图像集合,每张图像属于 10 个不同的类别之一。我们将从 CIFAR-10 数据集中的 2,000 张小批量的标记图像开始,然后采用主动机器学习策略来选择最佳图像展示给标记者进行标记。具体来说,我们将使用不确定性采样来查询模型最不确定的示例。我们在这里使用不确定性采样,因为它比我们之前讨论的其他方法更简单且计算成本更低。例如,委员会查询需要训练多个模型,这计算成本较高。
随着获取的标签越来越多,模型精度随着训练样本数量的减少而提高。这展示了主动学习如何以显著较低的数据需求创建高性能的计算机视觉模型。
为 CIFAR 数据集构建 CNN
实现将包括初始化一个卷积神经网络(CNN)分类器,使用小批量的标记数据集训练我们的模型,使用主动机器学习选择下一标记步骤的未标记图像,获取新的标签,重新训练模型,并跟踪模型性能。
快速提醒
CNN 分类器以图像为输入,使用卷积提取特征图,在完全连接层中整合特征,并根据训练期间学习到的内容输出预测的类别概率。卷积允许它自动学习相关的视觉模式,这使得 CNN 对于图像分类任务非常有效。您可以在 PyTorch 官方教程中找到构建神经网络模型的说明,请参阅pytorch.org/tutorials/beginner/blitz/neural_networks_tutorial.html#sphx-glr-beginner-blitz-neural-networks-tutorial-py。
让我们创建一个简单的图像分类模型:
class Net(nn.Module):
def __init__(self):
super().__init__()
# First convolutional layer with 6 output channels, 5x5 kernel
self.conv1 = nn.Conv2d(3, 6, 5)
# Max pooling layer with 2x2 window and default stride
self.pool = nn.MaxPool2d(2, 2)
# Second convolutional layer with 16 output channels, 5x5 kernel
self.conv2 = nn.Conv2d(6, 16, 5)
# First fully connected layer
# Flattened input size determined by conv2 output shape
self.fc1 = nn.Linear(16 * 5 * 5, 120)
# Second fully connected layer with 84 nodes
self.fc2 = nn.Linear(120, 84)
# Final fully connected output layer
# 10 nodes for 10 image classes
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
# Pass input through first conv and activation
x = self.pool(F.relu(self.conv1(x)))
# Second conv and activation, then pool
x = self.pool(F.relu(self.conv2(x)))
# Flatten input for first fully connected layer
x = torch.flatten(x, 1)
# Pass through all fully connected layers and activations
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
注意,我们使用这个模型是因为它是一个运行快速且高效的较小 CNN。这对于运行简单的概念验证很有帮助。然而,接下来,我们可以使用预训练模型之一(例如torchvision,如下所示:
from torchvision import models
model = models.resnet18(pretrained=True)
model = models.mobilenet_v2(pretrained=True)
您可以在库的模型页面上找到所有torchvision预训练模型:pytorch.org/vision/stable/models.html。
现在,我们使用适当的转换函数加载 CIFAR-10 数据集。转换函数定义了一系列在从 PyTorch 数据集中获取样本时自动应用的数据处理和增强操作。在下面的代码中,我们将图像转换为张量并对它们进行归一化:
transform = transforms.Compose(
[transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
full_dataset = torchvision.datasets.CIFAR10(
root='cifar10', train=True, download=True, transform=transform)
print(len(full_dataset))
这个打印结果显示,完整训练数据集的长度是 50,000 张图像。我们使用 CIFAR-10 训练数据集是因为我们将train=True的布尔值设置为 True。稍后,我们将使用 CIFAR-10 的测试集,并将train=False设置为 False。
现在,我们将创建一个包含 2,000 个标记图像的小型数据集。这里的目的是模拟存在一个小型标记图像集,而其余图像未标记。我们的目标是使用主动机器学习识别和选择下一个标记的最具信息量的图像:
init_indices = list(range(2000)) # indices for initial our "labeled" set
labeled_set = Subset(full_dataset, init_indices)
因此,我们已经创建了一个小型标记数据集,现在需要初始化我们的训练 PyTorch 数据加载器。PyTorch 数据加载器用于加载和迭代用于训练神经网络的数据集。它接受包含实际图像和标签的数据集,并负责将这些样本分批并馈送到模型。数据加载器允许您指定批大小,这决定了多少个样本被一起分批 – 这通常设置为 64 或 128 等。此外,如果您使用它作为训练集,数据加载器默认会打乱数据。这种样本顺序的随机化有助于模型在训练期间更好地泛化:
# Data loaders
labeled_loader = DataLoader(labeled_set, batch_size=64, shuffle=True)
下一步是初始化我们的模型。我们知道 CIFAR-10 有 10 个类别:
classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog',
'horse', 'ship', 'truck')
model = Net(n_classes=len(classes))
一个好的做法是可视化我们正在处理的数据:
def imshow(img):
img = img / 2 + 0.5 # unnormalize
npimg = img.numpy()
plt.imshow(np.transpose(npimg, (1, 2, 0)))
plt.show()
# get some random training images
dataiter = iter(labeled_loader)
images, labels = next(dataiter)
# show images
imshow(torchvision.utils.make_grid(images))
图 4.1展示了 CIFAR-10 数据集图像的一个样本。

图 4.1 – 一些 CIFAR-10 数据集图像的随机可视化
最好也看一下这些标签,所以让我们打印前五个标签:
print(' '.join(f'{classes[labels[j]]:5s}' for j in range(5)))
前面的代码返回以下标签列表作为输出:
frog truck truck deer car
我们可以通过将这些标签与图 4.1中的前五张图像进行交叉引用来验证这是否正确。
什么是反归一化?
反归一化一张图像意味着反转之前应用于图像像素值的任何归一化,以便恢复原始像素值分布(从 0-1 范围到原始 0-255 范围)。
现在我们有了数据加载器,我们可以开始训练循环;我们首先定义我们的损失函数和优化器。损失函数衡量模型预测与一批图像的真实标签匹配的程度。它计算预测标签和真实标签之间的误差。常见的分类损失函数包括交叉熵损失和负对数似然损失。如果模型预测了错误的标签,这些损失函数将输出一个高数值,如果预测准确,则输出一个低数值。训练的目标是通过更新模型参数来最小化损失。有关 PyTorch 中可用的损失函数的更多信息,可以在此处找到:pytorch.org/docs/stable/nn.html#loss-functions。
优化器负责参数更新。它使用损失值执行反向传播并更新模型的权重和偏差以减少损失。随机梯度下降(SGD)是一种流行的优化算法,其中参数的更新与损失函数的梯度成比例。学习率控制更新的大小。其他如Adam和RMSProp等优化器也常用于深度学习模型(有关 PyTorch 中可用的优化函数的更多信息,您可以访问此链接:pytorch.org/docs/stable/optim.html):
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
我们将训练我们的模型 100 个 epoch。Epoch 表示在模型训练过程中通过完整训练数据集的次数。我们定义一个train函数如下以运行我们的训练:
def train(model, data_loader, epochs = 100):
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
for epoch in range(epochs): # loop over the dataset multiple times
running_loss = 0.0
for i, data in enumerate(data_loader, 0):
# get the inputs; data is a list of [inputs, labels]
inputs, labels = data
# zero the parameter gradients
optimizer.zero_grad()
# forward + backward + optimize
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
# print statistics
running_loss += loss.item()
if i % 10 == 9: # print every 10 mini-batches
print(f'[{epoch + 1}, {i + 1:5d}] loss: {
running_loss / 2000:.3f}')
running_loss = 0.0
print('Finished Training')
return model
然后,我们开始训练:
model = train(model, labeled_loader)
我们现在在我们的小型数据集上有一个初始训练好的模型,我们想用它来选择下一个要标记的图像。但首先,让我们在 CIFAR-10 测试集上评估这个模型。我们定义一个评估函数:
def evaluate(model, test_dataset, batch_size=1):
# Testing
model.eval()
test_loader = torch.utils.data.DataLoader(test_dataset,
batch_size)
correct = 0
total = 0
with torch.no_grad():
for images, labels in tqdm(test_loader):
outputs = model(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print('\nAccuracy of the model on the test images: {}
%'.format(100 * correct / total))
我们可以定义测试集后使用此函数与我们的训练好的模型:
test_set = torchvision.datasets.CIFAR10(
root='data', train=False, transform=transform, download=True)
print(len(test_set))
测试集的长度是 10,000。
让我们使用我们的评估函数与这个测试集:
evaluate(model, test_set)
这给我们以下结果:
Accuracy of the model on the test images: 40.08 %
因此,我们现在已经测试了我们第一个训练好的模型,该模型是在我们的初始小型标记集的 2,000 个图像上训练的。模型在测试集上的准确率为 40.08%。我们的目标是通过标记更多图像来提高这个准确率。这就是我们的主动机器学习选择策略发挥作用的地方。
应用不确定性采样以改进分类性能
我们将从我们的数据集中选择最具信息量的图像进行标记,即模型最不自信的帧,这是在第第二章,设计查询策略框架中讨论的方法。
我们首先定义一个函数来获取模型的不确定性分数:
def least_confident_score(predicted_probs):
return 1 - predicted_probs[np.argmax(predicted_probs)]
然后,我们为未标记集定义我们的数据加载器。由于我们将遍历所有图像以获取不确定性分数,我们将使用批大小为 1:
unlabeled_loader = DataLoader(full_dataset, batch_size=1)
我们收集了我们一组未标记图像的置信度分数:
least_confident_scores = []
for image, label in unlabeled_loader:
probs = F.softmax(model(image), dim=1)
score = least_confident_score(probs.detach().numpy()[0])
least_confident_scores.append(score)
print(least_confident_scores)
这返回了以下结果:
[0.637821763753891, 0.4338147044181824, 0.18698161840438843, 0.6028554439544678, 0.35655343532562256, 0.3845849633216858, 0.4887065887451172, ...]
这些值代表模型预测的最低置信度分数。分数越高,模型越不自信。因此,接下来,我们想知道分数最高的图像索引。我们决定要选择 200 张图像(查询):
num_queries = 200
然后,我们按不确定性排序:
sorted_uncertainties, indices = torch.sort(
torch.tensor(least_confident_scores))
我们获取最不确定样本的原始索引并打印结果:
most_uncertain_indices = indices[-num_queries:]
print(f"sorted_uncertainties: {sorted_uncertainties} \
nmost_uncertain_indices selected: {most_uncertain_indices}")
这返回了以下结果:
sorted_uncertainties: tensor([0.0000, 0.0000, 0.0000, ..., 0.7419, 0.7460, 0.7928], dtype=torch.float64)
most_uncertain_indices selected: tensor([45820, 36802, 15912, 8635, 32207, 11987, 39232, 6099, 18543, 29082, 42403, 21331, 5633, 29284, 29566, 23878, 47522, 17097, 15229, 11468, 18130, 45120, 25245, 19864, 45457, 20434, 34309, 10034, 45285, 25496, 40169, 31792, 22868, 35525, 31238, 24694, 48734, 18419, 45289, 16126, 31668, 45971, 26393, ... 44338, 19687, 18283, 23128, 20556, 26325])
现在我们有了使用我们的主动 ML 最不自信策略选择的图像索引。这些是会被发送到我们的预言机进行标记,然后用于再次训练模型的图像。
让我们看看这五张选定的图像:
fig, axs = plt.subplots(1, 5)
for i in range(5):
image, label = full_dataset[most_uncertain_indices[i]]
image = image.squeeze().permute(1, 2, 0) / 2 + 0.5
axs[i].imshow(image)
axs[i].axis('off')
plt.show()

图 4.2 – 下一个要标记的五张选择的图像
我们现在有了需要标记的图像。由于这是一个演示,我们已经有标签了,所以让我们用这些新标记的图像重新训练我们的模型。首先,我们需要将这些图像添加到我们的标记集中:
init_indices.extend(most_uncertain_indices)
labeled_set_2 = Subset(full_dataset, init_indices)
labeled_loader_2 = DataLoader(labeled_set, batch_size=64)
print(len(labeled_set_2))
这返回了 2,200,这是正确的,因为我们首先从我们的数据集中选择了 2,000 张图像,然后使用我们的主动 ML 采样查询了 200 张。
让我们从 100 个 epoch 开始重新从头开始训练:
model_2 = Net(n_classes=len(classes))
model_2 = train(model_2, labeled_loader_2)
然后,在测试集上运行评估:
evaluate(model_2, test_set)
这返回了以下结果:
Accuracy of the model on the test images: 41.54 %
通过将使用我们的主动 ML 策略选择的图像添加到训练数据集中,我们将测试集上的准确率从 40.08%提高到了 41.54%。我们还可以按照以下方式微调最初训练的模型:
model = train(model, labeled_loader_2)
evaluate(model, test_set)
这给出了以下结果:
Accuracy of the model on the test images: 40.84 %
这里有一个有趣的结果:微调模型的表现不如从头开始使用更大数据集训练的模型。总体而言,当添加由主动 ML 选择的图像时,模型的表现有所提高。
这种方法可以应用于现实世界的问题。然而,需要注意的是,这只是一个如何使用最不自信采样方法进行分类的基本演示。在实际项目中,你需要有预言机对所选图像进行标记。此外,你可能会需要查询超过 200 张图像,并使用一个更大的预训练模型,如前所述。
虽然前面的例子展示了主动 ML 在图像分类中的应用,但相同的原理也可以应用于其他计算机视觉任务,例如目标检测,我们将在下面看到。
将主动 ML 应用于目标检测项目
在本节中,我们将指导您实现针对目标检测项目的主动机器学习技术。目标检测项目指的是开发一个计算机视觉模型,用于在图像或视频中检测和定位对象。数据集是一组包含您想要检测的对象示例的图像(视频帧),以及其他内容。数据集需要以对象周围的边界框形式包含标签。用于此目的的流行数据集包括COCO (cocodataset.org/)、PASCAL VOC (host.robots.ox.ac.uk/pascal/VOC/)和OpenImages (storage.googleapis.com/openimages/web/index.html)。模型架构使用专为对象检测设计的神经网络,如 Faster R-CNN、YOLO 等。这种架构可以自动在视觉数据中识别和定位现实世界中的对象。最终结果是能够检测并在对象周围绘制边界框的模型,例如汽车、人、家具等。
目标检测项目面临与分类项目相同的问题:创建数据集既困难又耗时。实际上,对于目标检测任务来说,这更具挑战性,因为它涉及到手动在对象周围绘制边界框。再次强调,主动机器学习通过将最有信息量的图像发送到仲裁者进行标记,为这个标记瓶颈提供了解决方案。我们将构建一个能够定位脑肿瘤的目标检测模型。我们将使用的数据集来自 Roboflow Universe (universe.roboflow.com/),被称为脑肿瘤计算机视觉项目。为了下载这个数据集,我们使用 Roboflow API:
rf = Roboflow(api_key="your_key")
project = rf.workspace("roboflow-100").project("brain-tumor-m2pbp")
dataset = project.version(2).download("yolov8")
这将在本地下载数据集。数据集以图 4.3中所示的结构作为一个文件夹下载。

图 4.3 – Roboflow Universe 数据集的文件夹结构,brain-tumor-m2pbp
准备和训练我们的模型
接下来,我们需要修复data.yaml文件,以便在 Google Colab 中正常工作,并为我们的主动机器学习演示组织数据。data.yaml文件在ultralytics训练中用于指定不同的集合(train、valid和test)的位置。我们假设原始训练集是我们的未标记图像集,验证集是我们的测试数据,测试集是我们的标记数据,因为它包含的示例最少。因此,首先,我们定义一个函数来相应地重命名文件夹:
def rename_folders(current_folder_name, new_folder_name):
# Check if the folder exists
if os.path.exists(current_folder_name):
# Rename the folder
os.rename(current_folder_name, new_folder_name)
else:
print(f'The folder {current_folder_name} does not exist.')
# Now let's run it on our three folders train, valid, and test:
rename_folders(current_folder_name='/content/brain-tumor-2/train',
new_folder_name='/content/brain-tumor-2/unlabeled')
rename_folders(current_folder_name='/content/brain-tumor-2/valid',
new_folder_name='/content/brain-tumor-2/testing')
rename_folders(current_folder_name='/content/brain-tumor-2/test',
new_folder_name='/content/brain-tumor-2/labeled')

图 4.4 – 重命名子文件夹后数据集的结构
图 4**.4显示了我们在对演示中的文件夹进行重命名后,现在在我们脑肿瘤数据集中拥有的结构。然后我们修改data.yaml文件:
path_data_yaml = '/content/brain-tumor-2/data.yaml'
with open(path_data_yaml, 'r') as file:
data = yaml.safe_load(file)
data['train'] = 'labeled/images'
data['val'] = ''
data['test'] = 'testing/images'
with open(path_data_yaml, 'w') as file:
yaml.dump(data, file)
在这里,我们在data.yaml文件中重命名了子文件夹路径,这是我们用于训练的文件。我们目前不想在训练中使用val文件夹。
现在我们来看看我们的子文件夹,以确定其中一个文件夹中的图片数量:
unlabeled_files = glob.glob('/content/brain-tumor-2/unlabeled/images/*.jpg')
labeled_files = glob.glob('/content/brain-tumor-2/labeled/images/*.jpg')
testing_files = glob.glob('/content/brain-tumor-2/testing/images/*.jpg')
print(f"For our demo, we have {len(unlabeled_files)} unlabeled files,
{len(labeled_files)} labeled files, and {len(testing_files)}
testing files")
上述代码返回以下内容:
For our demo, we have 6930 unlabeled files, 990 labeled files, and 1980 testing files
我们现在可以开始在我们的labeled数据集上进行初始训练。为此训练,我们将使用一个广泛使用的 Python 计算机视觉包,称为ultralytics (github.com/ultralytics/ultralytics),并使用yolov8模型。yolov8模型能够执行检测和跟踪、实例分割、图像分类和姿态估计等任务。为了演示目的,我们将只训练我们的模型 10 个 epoch。我们使用detect任务类型,因为我们想训练模型进行目标检测:
from ultralytics import YOLO
model = YOLO('yolov8s.pt')
print('Start training ')
results = model.train(data=path_data_yaml,
batch=32,
task='detect',
mode='train',
epochs=10
)
分析评估指标
一旦训练完成,我们就在测试集上对其进行评估。以下是评估模型的方法:
metrics = model.val(data=path_data_yaml, split='test')
print(metrics.results_dict)
上述代码返回以下输出:
{'metrics/precision(B)': 0.6022637781613859,
'metrics/recall(B)': 0.4763619681952341,
'metrics/mAP50(B)': 0.4953616848732552,
'metrics/mAP50-95(B)': 0.2252478418006819,
'fitness': 0.25225922610793927}
让我们分析这些指标:
-
precision(B)衡量预测的边界框中有多少是正确的。0.60 的值意味着 60%的预测框与真实框匹配。 -
recall(B)衡量有多少真实框被正确检测到。0.48 的值意味着模型检测到了 48%的真实框。 -
mAP50(B)是在交并比(IoU)阈值为 50%时的平均精度,它衡量了模型在不同置信度阈值下的精度。如果预测与真实框的 IoU 至少为 50%,则认为预测是正确的。0.50 的值意味着模型在这个 IoU 阈值下有 50%的 mAP。 -
mAP50-95(B)是在 50%到 95%的 IoU 阈值之间的平均精度,这是一个更严格的指标,它期望与真实框有更高的重叠才能被认为是正确的。0.23 的较低值表明在更高的 IoU 阈值下性能下降。 -
fitness结合了精度和召回率。一个在精度上得分高但在召回率上得分低的模型会有较差的适应性。同样,高召回率但低精度也会导致适应性差。高适应性分数需要在精度和召回率指标上都有良好的表现。这鼓励模型在训练过程中提高检测的准确性和完整性。这里 0.25 的具体适应性值表明在精度、召回率或两者方面都有很大的改进空间。
指标显示精度相当好,但召回率较低,这意味着模型难以检测到所有真实框。高精度但低 mAP 表明许多检测偏离了真实框。总体而言,指标显示在检测的对齐和完整性方面仍有改进空间。
下一步是使用我们的主动机器学习(ML)方法选择最具有信息量的图像进行标注。
实施主动机器学习策略
我们将使用ultralytics包,这个包非常有用,可以帮助我们选择具有信息量的图像。这可以帮助我们提高我们刚才讨论的指标。此包为每个边界框预测提供置信度分数,我们将在这里使用它。
我们使用置信度阈值0.15将模型应用于未标注集中的每个图像。这意味着任何置信度分数低于 0.15 的预测将被丢弃。你可以根据你的具体需求和用例选择这个值。重要的是要记住,选择一个低的置信度分数阈值允许选择模型缺乏信心的图像:
results = model(os.path.join('/content/brain-tumor-2/',
'unlabeled/images'), verbose=False, conf=0.15)
让我们看看一些这些图像和预测到的边界框:
plt.figure(figsize=(12, 8))
for i in range(1, 33):
plt.subplot(4,8,i)
image = results[i].orig_img
for b in results[i].boxes.xywhn:
x, y, w, h = b.tolist()
# Convert YOLO format coordinates to OpenCV format coordinates
dh, dw, _ = image.shape
l = int((x - w / 2) * dw)
r = int((x + w / 2) * dw)
t = int((y - h / 2) * dh)
b = int((y + h / 2) * dh)
cv2.rectangle(image, (l, t), (r, b), (0, 255, 0), 1)
plt.imshow(image)
plt.show()

图 4.5 – 未标注集图像上的模型预测样本
我们可以在图 4.5**.5中看到模型正在检测未标注的脑部图像中的肿瘤。
让我们收集所有预测边界框的置信度分数:
confidences = []
for result in results:
confidences.append(result.boxes.conf)
我们只为每张图像保留最低的置信度值。如果没有预测到的边界框,我们添加一个置信度分数为10(一个高值,将这些图像放在潜在图像列表的末尾)。置信度分数是介于 0 到 1 之间的值,其中 1 表示高:
confidence_scores = []
for confidence in confidences:
if len(confidence) > 0:
confidence_scores.append(np.min(np.array(confidence.cpu())))
else:
confidence_scores.append(10)
print(confidence_scores)
我们有 6,930 个置信度分数,这是正确的,因为我们有 6,930 个未标注的文件。
接下来,我们选择 500 张置信度分数最低的图像:
num_queries = 500
# Sort by uncertainty
sorted_uncertainties, indices = torch.sort(torch.tensor(confidence_scores))
# Get original indices of most uncertain samples
most_uncertain_indices = indices[-num_queries:]
print(f"sorted_uncertainties: {sorted_uncertainties[0:num_queries]} \
nmost_uncertain_indices selected: {most_uncertain_indices}")
这返回以下结果:
sorted_uncertainties: tensor([0.1500, 0.1500, 0.1501, 0.1501, 0.1501, 0.1501, ..., 0.1598, 0.1598, 0.1598, 0.1599, 0.1599, 0.1599, 0.1599, 0.1599, 0.1600])
most_uncertain_indices selected: tensor([4714, 4713, 4712, 4304, 4305, 4306, ...., 5554, 5553, 5552, 5551, 5550, 5549, 5548, 5547, 3135, 5544, 5543])
现在我们得到了以下选定的图像:
images_selected = np.array(
glob.glob(os.path.join('/content/brain-tumor-2/',
'unlabeled/images', '*.jpg'))
)[np.array(most_uncertain_indices)]
我们将这些选定的图像(及其相应的标签文件)移动到我们的标注集中 – 这模拟了我们将有神谕标注这些图像的步骤:
import shutil
for image_path in images_selected:
shutil.move(image_path, image_path.replace('unlabeled',
'labeled'))
label_file = image_path.replace('images', 'labels').replace('.jpg', '.txt')
shutil.move(label_file, label_file.replace('unlabeled',
'labeled'))
让我们检查我们是否正确地移动了图像和标签文件:
images_labeled = glob.glob('/content/brain-tumor-2/labeled/images/*.jpg')
labels_labeled = glob.glob('/content/brain-tumor-2/labeled/labels/*.txt')
print(len(images_labeled))
print(len(labels_labeled))
这两个print命令都返回 1,490,这是我们预期的,因为我们有 990 个标注图像,然后添加了 500 个新的图像/标签对。
我们可以使用这个更新后的数据集再次训练我们的模型:
model = YOLO('yolov8s.pt')
print('Start training ')
results = model.train(data=path_data_yaml,
batch=32,
task='detect',
mode='train',
epochs=10
)
然后,我们在测试集上评估这个模型:
metrics = model.val(data=path_data_yaml, split='test')
metrics.results_dict
现在我们得到了以下指标:
{'metrics/precision(B)': 0.6469528069030884,
'metrics/recall(B)': 0.5106541285546612,
'metrics/mAP50(B)': 0.543579045283473,
'metrics/mAP50-95(B)': 0.26662268193511757,
'fitness': 0.29431831826995314}
将这些指标与我们之前得到的指标进行比较,我们可以看到,精确度从 0.60 提高到 0.65,召回率从 0.48 提高到 0.51,mAP50 从 0.50 提高到 0.54,mAP50-95 从 0.22 提高到 0.27,适应性从 0.25 提高到 0.29。因此,将 500 张最具信息量的图像添加到我们的标注集中,提高了我们各项指标。
我们可以使用类似的方法进行实例分割,我们将在下一节中介绍。
使用主动机器学习进行分割项目
在本节中,我们将重复我们在对象检测任务中做的事情,但我们将使用yolov8的segment任务的实例分割数据集,而不是使用对象检测数据集。
person、car等。实例分割将那些类别的单个实例分开 – 1 号人 versus 2 号人,或 1 号车 versus 2 号车。
定位、分类和实例分离的组合使得可以精确分析图像直到像素级别。这使得实例分割在需要精细级别理解场景的应用中非常有用,例如自动驾驶、医学成像和机器人技术。一些流行的实例分割算法和模型包括Mask R-CNN (arxiv.org/abs/1703.06870)、Panoptic FPN (arxiv.org/abs/1901.02446)和YOLACT (arxiv.org/abs/1904.02689)。
让我们从 Roboflow 宇宙下载strawberry数据集
rf = Roboflow(api_key="your_key")
project = rf.workspace("5060tanapoowapat-yumsarn").project("strawberry-2vs5u")
dataset = project.version(2).download("yolov8")
然后,我们按照前面章节中针对对象检测数据集所遵循的相同步骤进行操作。我们为我们的演示用例重命名子文件夹并更新 YAML 文件。最终我们得到了图 4**.6中所示的架构。

图 4.6 – 重命名子文件夹后的草莓数据集结构,用于我们的演示
对于这个数据集,在重命名文件夹并更新 YAML 文件后,代码返回以下内容:
For our demo, we have 3006 unlabeled files, 184 labeled files, and 659 testing files
由于我们现在正在训练实例分割,我们更新训练代码如下:
model = YOLO('yolov8n-seg.pt')
print('Start training ')
results = model.train(data=path_data_yaml,
batch=16,
task='segment',
mode='train',
epochs=10
)
一旦训练完成,我们使用与上一个项目相同的代码评估模型,并得到以下指标:
{'metrics/precision(B)': 0.673169825129636,
'metrics/recall(B)': 0.7297833796885302,
'metrics/mAP50(B)': 0.7664149988792639,
'metrics/mAP50-95(B)': 0.533442993245899,
'metrics/precision(M)': 0.7415224838967787,
'metrics/recall(M)': 0.7482014388489209,
'metrics/mAP50(M)': 0.8165979711704425,
'metrics/mAP50-95(M)': 0.5967313838152124,
'fitness': 1.175458236359971}
带有(B)的指标代表目标检测的指标,而带有(M)的指标指的是实例分割,其中M代表蒙版。两种类型的指标相同;唯一的区别是M指标是在蒙版的像素上计算的,而不是在边界框的像素上。
按照相同的逻辑,我们然后选择要标记的图像以提高我们的指标。
当我们在未标记集中的每张图像上运行模型时,代码略有不同:
results = model(os.path.join(f'/content/{dataset_name}/',
'unlabeled/images'), verbose=False, conf=0.25, task='segment')
我们必须指定我们正在进行分割任务,并选择一个更高的置信度阈值,以避免在 Colab 中发生内存问题。
让我们看看模型对一些未标记图像的预测:
plt.figure(figsize=(12, 8))
# Generate a list of 32 random integers between 0 and 100
random_integers = [random.randint(0, 100) for _ in range(32)]
for i, index in enumerate(random_integers):
plt.subplot(4,8,i+1)
image = results[index].orig_img
for b in results[index].boxes.xywhn:
x, y, w, h = b.tolist()
# Convert YOLO format coordinates to OpenCV format coordinates
dh, dw, _ = image.shape
l = int((x - w / 2) * dw)
r = int((x + w / 2) * dw)
t = int((y - h / 2) * dh)
b = int((y + h / 2) * dh)
cv2.rectangle(image, (l, t), (r, b), (0, 255, 0), 2)
if results[index].masks:
overlayed_image = image.copy()
for m in results[index].masks:
# Make sure both images are of data type uint8
mask = np.array(m.data.cpu()[0])
mask = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)
image = image.astype(np.uint8)
mask = mask*255
mask = mask.astype(np.uint8)
# Overlay the mask on the RGB image
overlayed_image = cv2.addWeighted(overlayed_image, 1,
mask, 0.8, 0)
plt.imshow(cv2.cvtColor(overlayed_image, cv2.COLOR_BGR2RGB))
plt.show()
这返回了图 4**.7中所示的照片。

图 4.7 – 从未标记集图像上的模型预测样本
在图 4.7 中,我们可以看到模型正确地检测到了大部分的草莓。图像中的绿色边界框表示目标检测,而白色叠加的蒙版表示分割。
然后,我们遵循前面章节中讨论的对象检测步骤,选择了 500 张图像进行标记,并得到以下结果:
sorted_uncertainties: tensor([0.2500, 0.2501, 0.2501, 0.2501, 0.2501, 0.2502, 0.2503, 0.2503, 0.2503, 0.2503, 0.2503,..., 0.2703, 0.2703, 0.2703, 0.2703, 0.2703, 0.2704, 0.2704, 0.2704, 0.2704, 0.2704])
most_uncertain_indices selected: tensor([2744, 806, 1822, 1025, 1486, 345, 743, 1374, 2329, 1381, 301, 2322, 2272, 1196, ..., 2127, 2004, 2119, 2118, 1401, 1402, 2666, 2105, 100, 47, 2093, 46, 2092, 2085, 970, 1422])
我们将这些图像移动到我们的标记集中,因此从标记集中的 184 张图像增加到 684 张。我们在更新后的标记集上运行训练,然后进行评估,并得到以下指标:
{'metrics/precision(B)': 0.7522007556106134,
'metrics/recall(B)': 0.7570614064930203,
'metrics/mAP50(B)': 0.800552933790843,
'metrics/mAP50-95(B)': 0.6079730626509038,
'metrics/precision(M)': 0.8061734224988162,
'metrics/recall(M)': 0.8069544364508393,
'metrics/mAP50(M)': 0.8511208111235853,
'metrics/mAP50-95(M)': 0.6554160034789296,
'fitness': 1.3022175340082929}
让我们比较一下在添加了 500 张最有信息量的图像之前的指标:
{'metrics/precision(B)': 0.673169825129636,
'metrics/recall(B)': 0.7297833796885302,
'metrics/mAP50(B)': 0.7664149988792639,
'metrics/mAP50-95(B)': 0.533442993245899,
'metrics/precision(M)': 0.7415224838967787,
'metrics/recall(M)': 0.7482014388489209,
'metrics/mAP50(M)': 0.8165979711704425,
'metrics/mAP50-95(M)': 0.5967313838152124,
'fitness': 1.175458236359971}
我们可以观察到所有指标都有所提高。
摘要
总结来说,本章展示了如何将主动机器学习应用于优化计算机视觉模型的训练。正如我们所见,图像分类、目标检测和实例分割等计算机视觉任务需要大量的标记数据集来训练卷积神经网络(CNNs)。手动收集和标记如此大量的数据既昂贵又耗时。
主动机器学习通过智能选择最具有信息量的示例由人类专家进行标记,从而为这一挑战提供了解决方案。例如,不确定性采样策略会查询模型以找到它最不确定的数据点。通过仅标记这些有用的数据点,我们可以用显著减少的数据标记工作来训练我们的模型。
在本章中,我们介绍了为各种计算机视觉应用实现主动机器学习方法的步骤。通过交互式查询模型和细化训练数据,我们可以以标记成本的一小部分快速提高模型性能。这些技术使得即使在有限数据的情况下开发计算机视觉系统也成为可能。
本章节中提出的主动机器学习实现提供了在无需大量数据集的情况下构建高性能和鲁棒的计算机视觉模型的新可能性。通过这些策略,您可以优化和针对数据收集和训练工作以实现高效的结果。展望未来,主动机器学习将成为开发现实世界计算机视觉系统的一个基本工具。
在下一章中,我们将探讨如何利用主动机器学习来处理使用大量数据的大数据项目,例如视频。
第五章:利用主动学习处理大数据
在本章中,我们将探讨如何使用机器学习(ML)来处理大数据,例如视频。开发视频分析的 ML 模型带来了一系列独特的挑战。视频本身很大,在高效处理方面提出了重大障碍。使用 ML 进行视频分析已成为许多行业和应用的越来越重要的技术。从依赖计算机视觉模型分析实时视频流中的道路条件的自动驾驶汽车,到能够自动检测可疑活动的安全系统,ML 正在改变视频数据所能实现的可能性。这些模型可以自动化耗时的人工分析并提供可扩展的视频理解。实现高效和可扩展的视频分析管道需要克服关键障碍,如大量数据标注。
我们将引导您了解一种前沿的 ML 方法,这将帮助您选择最具信息量的帧进行标注,从而提高分析的整体准确性和效率。
在本章中,我们将涵盖以下主题:
-
实现视频分析的 ML 模型
-
使用 Lightly 选择最具信息量的帧
技术要求
在本章中,您需要安装以下软件包:
pip install ultralytics lightly docker encord
您还需要以下导入:
import os
from IPython.display import display, Markdown
from ultralytics import YOLO
from pathlib import Path
import json
import contextlib
from typing import Iterator
import docker
from docker.models.containers import Container
from lightly.api import ApiWorkflowClient
from lightly.openapi_generated.swagger_client import DatasetType
from lightly.openapi_generated.swagger_client import DatasourcePurpose
from encord.orm.cloud_integration import CloudIntegration
from encord.orm.dataset import AddPrivateDataResponse
from encord.user_client import EncordUserClient
from encord.orm.dataset import CreateDatasetResponse, StorageLocation
接下来,您需要创建一个 Lightly 账户并设置您的 API 令牌,如下所示:
lightly_token = "your_lightly_token"
然后,您必须设置 Lightly 客户端以连接到 API:
client = ApiWorkflowClient(token=lightly_token)
这个演示是在 AWS SageMaker 笔记本(ml.g4dn.2xlarge 实例)上运行的。这个实例有一个 GPU 和足够的内存来运行这个演示,因为我们需要访问 Docker,这在 Google Colab 中是不可能的。
如果您想将选定的帧发送到标注平台,还需要一个 Encord 账户([app.encord.com/](https://app.encord.com/))。
实现视频分析的 ML 模型
活跃式机器学习(Active ML)在管理大数据项目方面发挥着变革性的作用,通过战略性地优化数据标注过程,从而以更少的手动努力提高模型性能。例如,在大型图像识别任务中,如从数百万社交媒体照片中识别特定对象,活跃学习可以通过定位最有可能提升模型能力的图像,显著减少工作量。同样,在自然语言处理(NLP)应用中,处理来自新闻文章、论坛和客户反馈等来源的大量文本数据,活跃式机器学习有助于选择性地标注对理解复杂语言细微差别或情感最有价值的文档。这种方法不仅简化了标注大规模数据集所需的工作量,而且确保了基于此类数据训练的模型更加准确、高效,并且能够处理大数据源中固有的现实世界变化。将这种方法扩展到视频分析中,由于视频内容中增加了复杂性和数据量,活跃式机器学习变得更加关键。活跃式机器学习可以用来识别对模型学习有显著贡献的关键帧或片段,在确保全面理解和分析视频数据的同时,大幅减少标注负担。这种在视频项目中采用的有针对性的方法不仅节省了资源,而且加速了复杂视频分析模型的发展,这些模型能够以更高的精度和效率执行活动识别、事件检测和情感分析等任务。
在本节中,我们将探讨如何利用活跃式机器学习开发用于视频的机器学习模型。机器学习视频分析系统需要实施策略来高效地整理视频帧。视频通常是大型文件,标注视频中的所有帧是不可能的。此外,根据每秒帧数(FPS)的速率,视频往往包含大量重复数据,如果对这样的数据进行标注,将浪费时间和金钱。常见的做法是以 1 FPS 的速率进行标注,而不是像 30 FPS 那样,以减少需要标注的帧数。然而,这并不是一个最佳解决方案,因为它会导致相似帧被标注,代表类别的平衡性失衡,以及所选数据缺乏多样性。此外,如果实施这样的流程,将被标注的许多帧可能一开始就无需标注,因为模型可能已经在某些帧上表现得很出色。因此,标注模型有信心且正确的帧是浪费时间和金钱。
换句话说,手动标注视频数据集中的所有帧对于机器学习来说是不切实际的,由于以下因素,活跃学习变得至关重要:
-
数据量:视频数据由大量帧组成,这使得全面的手动标注变得极其耗时且昂贵。例如,对 30 FPS 视频仅 10 分钟的每一帧进行标注就需要标注 18,000 张图片。
-
冗余:连续的视频帧高度冗余,因为它们包含几乎相同的内容。手动标注这种重复数据是不高效的。
-
成本:雇佣人工标注员仔细标注视频帧的费用会非常高昂,使得大多数项目在经济上不可行。仅 10 小时的视频标注费用就可能高达数千美元。
这就是主动机器学习非常有价值的地方。它通过识别最有可能提高模型性能的最具信息量的帧来优化标注工作,正如我们在前面的章节中看到的。人工标注员可以专注于这些高价值帧。通过将标注过程引导至最大化性能提升,需要手动标注的帧数大大减少,使得视频机器学习变得可行且经济高效。
总结来说,全面手动视频数据标注既不实际,在经济上也不可行。主动学习为标注提供了关键优化,使得模型能够以可行、经济和适应性强的方式分析视频。
现在,让我们通过一个使用常见主动机器学习工具Lightly(https://www.lightly.ai/)的实例来探讨现实世界的情况。
使用 Lightly 选择最具信息量的帧
在本节中,我们将使用一个名为Lightly的主动机器学习工具。Lightly 是一个数据整理工具,它配备了一个网络平台,使用户能够选择最优的样本子集以最大化模型精度。Lightly 的算法可以在不到 24 小时内处理大量数据,例如 1000 万张图片或 1 万段视频。
网络应用程序允许用户使用诸如锐度、亮度、对比度、文件大小等过滤器来探索他们的数据集。然后,他们可以使用这些过滤器来探索这些特征之间的相关性。
用户还可以在应用内搜索相似图像或对象,并查看嵌入(主成分分析(PCA),T 分布随机近邻嵌入(TSNE),和均匀流形近似与投影(UMAP))。嵌入是指由深度神经网络学习到的图像的向量表示。它们以允许分析图像之间相似性和关系的方式捕捉图像的视觉特征和语义。当图像通过卷积神经网络时,分类前的最后一层通常是图像特征的密集表示。这个密集层为每个图像输出一个具有数百或数千维度的向量。这个向量被称为嵌入。在嵌入空间中映射时,具有相似特征的图像的嵌入将更接近或相邻。具有非常不同特征的图像在嵌入空间中将更远。
有几种技术可以将这些高维嵌入可视化到二维或三维空间,以便于人类分析:
-
PCA:PCA 将嵌入的维度降低到二维或三维,以便于绘制。它将它们投影到捕捉最大变差的维度上。在 PCA 投影后,具有相似显著视觉特征的图像将更靠近。
-
TSNE:TSNE 是一种技术,在保持相似图像靠近和不相似图像分开的同时,将高维嵌入表示在较低维度。二维或三维映射试图模拟更高维空间中的局部结构。
-
UMAP:UMAP 是一种更近期的技术,在很多情况下比 TSNE 更好地保留投影中的全局数据结构。它将具有相似嵌入的图像映射到投影附近,将不相似的图像映射得更远。
嵌入以向量的形式捕捉图像特征和语义。PCA、TSNE 和 UMAP 等技术然后将这些高维向量投影到二维或三维,以便于可视化和分析图像之间的相似性关系。Lightly 应用利用这些投影来实现图像相似性搜索。
使用 Lightly 选择用于对象检测的最佳帧进行标记
为了选择最佳帧,我们需要进行一系列步骤。
数据集和预训练模型
在这个例子中,我们将使用一只狗追球的视频。出于演示目的,我们只会使用一个视频,如图 5.1所示。这个视频可以在本书的 GitHub 仓库中找到(github.com/PacktPublishing/Active-Machine-Learning-with-Python/blob/main/Chapter_5/videos/project_demo/dog_running_ball.mp4):

图 5.1 – 用于测试我们的 Lightly 演示的视频
在本节中,我们的主要目标是使用 Lightly 提供的不同采样策略选择这个视频中最具信息量的帧。
我们的视频 dog_running_ball.mp4 存储在名为 videos 的文件夹下的一个名为 project_demo 的子文件夹中。
一旦我们在 videos/project_demo 文件夹中有视频,下一步就是加载一个预训练的对象检测模型:
Model = YOLO("yolov8x.pt")
这个来自 ultralytics 的预训练模型支持 80 个类别,我们可以使用以下命令进行可视化:
model.namesg
这将返回以下输出:
{0: 'person',
1: 'bicycle',
2: 'car',
3: 'motorcycle',
...
32: 'sports ball',
33: 'kite',
34: 'baseball bat',
...
76: 'scissors',
77: 'teddy bear',
78: 'hair drier',
79: 'toothbrush'}
在我们这个例子中,我们知道我们正在处理一个狗追球的视频,因此我们将关注 狗 和 运动 球 类别。
然后,我们必须为 Lightly 运行准备一些变量,例如预测输出文件夹的路径、任务的名称以及我们在这轮运行中想要关注的、以改进模型的重要类别(狗 和 运动球):
important_classes = {"dog": 16, " sports ball": 32}
classes = list(important_classes.values())
我们这里的类别是 16 和 32。
创建所需的 Lightly 文件
我们将把我们的推理预测保存到一个名为 predictions 的子文件夹中;我们的任务名称是 yolov8_demo_dog_detection:
predictions_rooth_path = Path("predictions")
task_name = "yolov8_demo_dog_detection"
predictions_path = Path(predictions_rooth_path / task_name)
然后,我们需要创建 Lightly 将使用的所有配置文件:
-
tasks.json文件,它指定了我们当前任务的名称。任务名称是预测文件夹中相应子文件夹的名称。 -
schema.json文件,它允许 Lightly 了解预测的格式。 -
包含我们
videos文件夹中视频名称的元数据schema.json文件。
创建这些配置文件的代码可以在本书 GitHub 仓库的第五章部分找到(github.com/PacktPublishing/Active-Machine-Learning-with-Python/tree/main/Chapter_5)。
我们现在可以使用我们之前加载的预训练模型运行对象检测推理。
推理
我们将以低置信度阈值 0.3 在我们的测试视频上运行对象检测推理,因为我们想要较低的置信度分数。代码已经设置好以处理子文件夹中的多个视频。然而,出于测试目的,我们只有一个视频。我们将跳过不属于重要类别的预测:
videos = Path("videos/project_demo/").glob("*.mp4")
for video in videos:
print(video)
results = model.predict(video, conf=0.3)
predictions = [result.boxes.data for result in results]
number_of_frames = len(predictions)
padding = len(str(number_of_frames))
fname = video
for idx, prediction in enumerate(predictions):
populate_predictions_json_files(prediction, fname, padding)
populate_predictions_json_files 函数定义在这本书的 GitHub 仓库中的代码里(github.com/PacktPublishing/Active-Machine-Learning-with-Python/tree/main/Chapter_5)。
一旦我们运行了这段代码,我们将在 predictions 子文件夹中以 Lightly 支持的格式收到推理运行的输出,如图 图 5**.2 所示:

图 5.2 – Lightly JSON 预测(快照)
如果我们查看这些文件之一,JSON 文件包含的信息是推理的结果。这包括边界框的坐标,以及相应的类别 ID 和置信度分数,如图 图 5.3 所示:

图 5.3 – Lightly 预测 JSON 文件格式,用于第一帧
现在,我们已经准备好安排活动 Lightly 机器学习运行。
安排活动机器学习运行
我们可以使用以下代码注册 Lightly 工作进程,该代码返回我们的 Lightly 工作进程的 ID:
注意
如果已存在具有此名称的工作进程,则将返回现有工作进程的 ID。
worker_id = client.register_compute_worker(name="Demo")
Lightly 使用 Docker 通过 lightly/worker:latest 镜像运行活动机器学习。可以使用命令行拉取:
docker pull lightly/worker:latest
Docker 是一个开源平台,用于在软件容器内开发、运输和运行应用程序。它允许将代码及其所有依赖项和库打包成一个标准化的单元,用于软件开发。使用 Docker 容器消除了由环境差异引起的不兼容性问题。简而言之,它使得在运行脚本时易于复制,因为 Docker 镜像中的环境已经配置了正确的已安装包。
接下来,我们需要安排我们的活动机器学习运行。这个过程涉及几个步骤:
-
创建一个名为
demo_dataset的 Lightly 数据集:client.create_dataset(dataset_name="demo_dataset", dataset_type=DatasetType.VIDEOS) dataset_id = client.dataset_id -
使用
project_demo项目作为数据输入或输出位置来设置数据源。在我们的案例中,我们使用本地存储选项 (docs.lightly.ai/docs/local-storage) 进行演示,但理想情况下,您应该使用云服务选项 (docs.lightly.ai/docs/cloud-storage),该选项使用 AWS、Azure 或 GCP:client.set_local_config( relative_path="project_demo", purpose=DatasourcePurpose.INPUT ) client.set_local_config( relative_path="project_demo", purpose=DatasourcePurpose.LIGHTLY ) -
安排我们想要使用的活动机器学习运行计划:一个用于寻找不同对象的策略,一个用于平衡类别比例的策略,以及一个用于使用预测分数来表示对象的频率和最不自信的结果的策略。在这个例子中,我们采样了五个样本,并试图在
狗和运动``球类别之间达到 50/50 的平衡:scheduled_run_id = client.schedule_compute_worker_run( worker_config={}, selection_config={ "n_samples": 5, "strategies": [ { # strategy to find diverse objects "input": { "type": "EMBEDDINGS", "task": task_name, }, "strategy": { "type": "DIVERSITY", }, }, { # strategy to balance the class ratios "input": { "type": "PREDICTIONS", "name": "CLASS_DISTRIBUTION", "task": task_name, }, "strategy": { "type": "BALANCE", "target": { dog: 0.50, 'sports ball': 0.50, } }, }, { # strategy to use prediction score (Active Learning) "input": { "type": "SCORES", "task": task_name, "score": "object_frequency" }, "strategy": { "type": "WEIGHTS" }, }, { # strategy to use prediction score (Active Learning) "input": { "type": "SCORES", "task": task_name, "score": "objectness_least_confidence" }, "strategy": { "type": "WEIGHTS" }, }, ], }, lightly_config={}, runs_on=['Demo'], ) -
现在,组织本地文件,使其与 Lightly 期望的格式相匹配:
!mkdir lightly && mkdir lightly/project_demo && mkdir lightly/project_demo/.lightly !mv metadata lightly/project_demo/.lightly && mv predictions lightly/project_demo/.lightly -
当我们查看文件夹时,我们会看到以下结构:

图 5.4 – 为 Lightly 本地存储组织的文件夹
现在,我们已经准备好开始运行。
启动工作进程和活动机器学习运行
我们需要创建一个函数,该函数将用于在 Docker 容器中挂载的已组织文件夹中启动工作进程:
@contextlib.contextmanager
def start_worker(lightly_token, lightly_worker_id, image_name="lightly/worker:latest", WORKER_LABEL="Demo") -> Iterator[Container]:
docker_client = docker.from_env()
volumes = ["/home/user/videos:/input_mount",
"/home/user/lightly:/lightly_mount"]
container = docker_client.containers.run(
image_name,
f"token={lightly_token} worker.worker_id={lightly_worker_id}",
detach=True,
labels={"lightly_worker_label": WORKER_LABEL},
volumes=volumes,
)
try:
yield container
finally:
try:
container.kill()
except docker.errors.APIError:
# if a container was killed from outside, we don't care
pass
让我们开始运行:
with start_worker(lightly_token, lightly_worker_id=worker_id):
print('Worker running ...')
last_run_info = None
no_update_count = 0
while True:
run_info = client.get_compute_worker_run_info(
scheduled_run_id=scheduled_run_id
)
print(run_info)
if run_info.in_end_state():
assert run_info.ended_successfully(),
"Run did not end successfully"
break
if run_info != last_run_info:
no_update_count = 0
else:
no_update_count += 1
if no_update_count >= 10000:
raise RuntimeError(
f"Test timout: no run_info update\n"
f"last_run_info: {str(last_run_info)},
run_info: {str(run_info)}"
)
last_run_info = run_info
我们可以在 Lightly 平台上检查我们运行的进度,如图 图 5.5 所示,以及通过查看前一段代码的输出:

图 5.5 – Lightly 活动机器学习运行的视图
完成后,我们可以访问运行详细的报告和所有必要的日志,例如内存日志和默认日志。我们还可以在 Lightly 网络应用程序中查看我们的数据集(app.lightly.ai/dataset)。
让我们探索我们的结果。在 图 5.6 中,我们可以看到我们有几个新的子文件夹,包括 frames 和 crops。这些文件夹包含所选的帧和裁剪(裁剪边界框):

图 5.6 – Lightly 活动机器学习运行后的结果文件夹
让我们可视化所选的帧:
most_informative_frames = glob('lightly/project_demo/.lightly/frames/*.png')
for img_path in most_informative_frames:
plt.imshow(Image.open(img_path))
plt.show()
这返回了 图 5.7 中显示的图像:

图 5.7 – Lightly 活动机器学习运行选择的五个最有信息量的帧
我们还可以探索报告,它为我们提供了关于我们新样本子集的大量信息。
报告保存在 lightly/project_demo/.lightly/runs/run_id 下。我们可以查看运行 ID,然后像 图 5.8 中所示的那样在本地复制 report.pdf 文件:

图 5.8 – 复制报告文档
报告中信息量很大,所以我们只关注某些部分。
首先,让我们快速看一下我们开始时的内容和最终的结果。如图 图 5.9 所示,我们最初有 290 帧和一个视频,只创建了一个包含五个帧的子集,这与我们请求的五个样本相对应。请注意,可以通过 n_samples 选择样本比例,也可以通过 proportionSamples 选择数据百分比。因此,要选择 30% 的数据,我们可以设置以下内容:
"proportionSamples": 0.30
我们可以这样做,而不是运行以下操作:
"n_samples": 5
这是输出:

图 5.9 – Lightly 报告 – 数据集信息
现在,让我们检查嵌入图,如图 图 5.10 所示。在检查 UMAP 和 PCA 嵌入图后,我们会看到没有明显的聚类,这表明帧之间缺乏一致性。这种不一致性可以归因于视频的动态拍摄条件,包括不同的角度、与狗的距离以及由于在移动和跟随狗的过程中遇到有阴影和无阴影区域而造成的照明变化。这些因素导致在帧中捕获了多样化的视觉输入:

图 5.10 – 轻量级报告 – 嵌入图
通过 图 5.11,我们更好地理解了活动机器学习算法选择的帧。我们可以看到它很好地从嵌入空间的不同位置选择了帧:

图 5.11 – 轻量级报告 – 嵌入图选定帧
在 图 5.12 中,我们可以观察到类别分布已经得到了有效平衡:狗 类占 54.5%,而 运动球 类占 45.5% 的选择,与我们的 50/50 类别平衡比率非常接近。这种平衡得益于我们配置的类别平衡比率。尽管如此,达到这种平衡往往具有挑战性,尤其是在数据集中一个类别显著多于其他类别时:

图 5.12 – 轻量级报告 – 类别分布
现在,我们可以探索一些模型预测结果,如图 图 5.13 所示。在这里,我们有不同检测数量的预测示例。总体而言,模型表现出强大的性能,始终在帧内识别出狗。然而,它似乎在检测球方面遇到了更多困难。值得注意的是,球在其中一个样本帧中被识别出来,这是一个令人鼓舞的迹象。这种检测准确性的差异很可能是由于测试中使用的球的本性;它偏离了原始模型训练时使用的传统运动球,如网球或足球。这个上下文有助于解释观察到的模型性能变化,可以通过标记球并重新训练模型来修复:

图 5.13 – 轻量级报告 – 模型预测示例
最后,图 5.14 展示了视频中的选定帧。每个选定的帧对应一条垂直线,我们可以确认有五条线对应我们选定的五个帧:

图 5.14 – 轻量级报告 – 视频采样密度
现在我们有了希望标记的最具信息量的帧,我们可以将它们发送到项目中使用的注释平台,例如 Encord Annotate (docs.encord.com/docs/annotate-overview) 或 Roboflow (roboflow.com/),如 第三章 中所述,管理闭环中的人类。在这个例子中,我们将使用 Encord Annotate,因为它提供了一个将选定帧可视化为视频的功能。
在运行此代码之前,您需要根据他们提供的文档创建 Encord SSH 私钥 (docs.encord.com/reference/authentication-sdk)。
然后,您可以使用以下代码进行验证:
encord_private_key = "-----BEGIN OPENSSH PRIVATE KEY-----{your_key}-----END OPENSSH PRIVATE KEY-----"
user_client = EncordUserClient.create_with_ssh_private_key(
encord_private_key)
下一步是创建一个名为我们项目名称的 Encord 数据集(docs.encord.com/docs/annotate-datasets) – 即 project_demo。这个 Encord 数据集是我们想要标注的数据:
print('\nCreating Encord Dataset...')
encord_dataset_created = user_client.create_dataset(
'project_demo', StorageLocation.CORD_STORAGE
)
这将返回一个字典,包含创建的数据集的 title、type、dataset_hash、user_hash 和 backing_folder_uuid 值。在这里,我们使用 Encord 的云存储,但你也可以使用自定义云存储。例如,如果你使用 AWS S3,那么你可以使用 StorageLocation.AWS 代替。
现在,我们可以查询数据集哈希,因为在上传图像时将需要它:
dataset_hash = encord_dataset_created.dataset_hash
接下来,我们可以用我们选择的帧填充数据集:
dataset = user_client.get_dataset(dataset_hash)
image_files = sorted(
[
p.as_posix()
for p in Path("lightly/project_demo/.lightly/frames").iterdir()
if p.suffix in {".jpg", ".png"}
]
)
dataset.create_image_group(image_files, create_video=True)
这将返回一个包含上传数据的 data_hash、backing_item_uuid 和 title 值的字典。
注意,我们使用了 create_video=True,这样我们就可以从图像组创建一个压缩视频;这些被称为图像序列(docs.encord.com/docs/annotate-supported-data#image-sequences)。当可视化帧时,这有助于保持视频的时间上下文,并且通常对标注者非常有帮助。它还允许标注者使用诸如自动标注(docs.encord.com/docs/automated-labeling)等特性,包括插值。这通过自动估计两个手动标注帧之间的标签位置,大大加快了标注过程。
在这一点上,我们可以在 Encord 网络应用程序的 Index/Datasets 部分查看我们的数据集(app.encord.com/datasets),如图 图 5.15 所示。我们可以观察到图像被保存为 img_sequence,这意味着它们将以视频的形式显示:

图 5.15 – 使用我们选择的五个帧保存为图像序列的 Encord 数据集
在 Encord 中,我们定义了用于此标注项目的本体(docs.encord.com/reference/ontologies-sdk),如图 图 5.16 所示。我们在 第三章 的 设计交互式学习系统和工作流程 部分介绍了本体的概念:

图 5.16 – 在 Encord 中创建的包含我们的两个类别,狗和球的本体
从 图 5.16 中可视化的页面,我们可以复制本体 ID 并使用它来创建 Encord Annotate 项目(docs.encord.com/docs/annotate-overview):
project_hash = user_client.create_project(
project_title='project_demo',
dataset_hashes=[dataset_hash],
ontology_hash='a0e16402-a5b4-417e-a4b1-7871ed386362')
我们将看到以下内容:

图 5.17 – Encord Annotate 项目中的 project_demo 样本
我们的数据现在已准备好进行标注。我们可以在 Web 应用的 Annote/标注项目 部分查看我们的 Encord Annotate 项目(app.encord.com/projects)。然后,在 project_demo 标注项目中,我们可以将所选帧作为视频查看,如图 5.18 所示:

图 5.18 – Encord 中所选帧图像序列的标注视图
在 图 5.18 所示的视图中,我们可以看到所有帧都作为视频呈现,用户可以使用滑块来浏览帧。还有我们在本体论中的 类别 部分定义的两个类别(狗和球),标注者可以选择来标注帧,如图 5.19 所示:

图 5.19 – 在所选帧上标注的示例
从这个页面,标注者可以使用之前提到的自动标注功能轻松标注对象;完成标注后,他们可以提交结果以供审查。
您也可以使用以下代码访问所选帧:
client_lightly_dataset = ApiWorkflowClient(
token=lightly_token, dataset_id=dataset_id)
filenames_and_read_urls \
client_lightly_dataset.export_filenames_and_read_urls_by_tag_name(
tag_name="initial-tag" # name of the tag in the dataset
)
print(f'There are {len(filenames_and_read_urls)} frames')
这将返回以下输出:
There are 5 frames
这是正确的!现在,让我们打印结果,以便我们更好地理解:
print(filenames_and_read_urls)
这将返回以下输出:
[{'fileName': 'dog_running_ball-024-mp4.png', 'readUrl': 'https://api.lightly.ai/v1/datasets/...', 'datasourceUrl': 'project_demo/.lightly/frames/dog_running_ball-024-mp4.png'}, .... {'fileName': 'dog_running_ball-180-mp4.png', 'readUrl': 'https://api.lightly.ai/v1/datasets/...', 'datasourceUrl': 'project_demo/.lightly/frames/dog_running_ball-180-mp4.png'}]
这些 URL 可以用来将所选帧发送到用于项目的标注平台。请注意,由于我们在演示中使用本地存储,数据不容易被标注平台和云服务访问,因此应使用云服务。本地数据也可以通过在 Lightly 中提供 localhost 来可视化(docs.lightly.ai/docs/local-storage#optional-view-local-data-in-lightly-platform)。
在本节中,我们使用 Lightly 通过几种策略选择了一只狗追球的测试视频中最具信息量的帧。这些策略包括寻找多样化的对象、平衡类别比率、使用预测分数来计算对象频率,以及考虑最不自信的结果。Lightly 还有很多其他功能来改进这些结果,并且有很好的组织文档(docs.lightly.ai/)。
接下来,我们将讨论如何使用 Lightly 进行自监督学习(SSL)。
带有主动机器学习的 SSL
Lightly 提供了其他有用的功能,例如SSL,它允许用户在嵌入图像之前,在他们的数据上微调 SSL 模型。SSL 算法利用未标记图像或视频中的结构和上下文来生成替代监督信号,使模型能够自行发现强大的视觉表示。例如,模型可能被训练在微调下游任务之前,以识别空间模式、着色、旋转或时间顺序作为先验目标。本质上,SSL 允许模型利用大量的未标记视频和图像来发现数据本身中的有用特征和模式,避免对人工标记的依赖,这在规模上可能是不切实际的。模型通过精心设计的先验任务自动监督其特征学习,同时利用视频中的时间连续性等特性。因此,当开发特定领域的模型时,例如医学视频,这个 Lightly 功能可以非常有益。额外的训练步骤提高了嵌入的质量,因为模型可以在不要求更多标记的情况下适应特定领域。
启用 SSL 很简单,只需在我们的worker_config和lightly_config子字典中添加几行代码,这两个子字典都是scheduled_run_id字典的一部分:
scheduled_run_id = client.schedule_compute_worker_run(
worker_config={
"enable_training": True
},
selection_config={
"n_samples": 5,
"strategies": [....], # same as before
},
lightly_config={
'loader': {
'num_workers': -1,
},
'trainer': {
'max_epochs': 10,
"gpus": 0, # cpu
},
},
runs_on=['Demo'],
)
在这里,我们配置了主动的机器学习运行,在生成嵌入之前,在 CPU 上执行 10 个时期的 SSL 训练。
现在,让我们看看我们的输出。被选中的帧大多与之前我们选择的帧不同——即dog_running_ball-024-mp4.png、dog_running_ball-101-mp4.png、dog_running_ball-033-mp4.png、dog_running_ball-224-mp4.png和dog_running_ball-049-mp4.png——与dog_running_ball-024-mp4.png、dog_running_ball-183-mp4.png、dog_running_ball-151-mp4.png、dog_running_ball-194-mp4.png和dog_running_ball-180-mp4.png相比。
因此,只有帧024再次被选中。图 5.20显示了五个最有信息量的帧:

图 5.20 – 通过 Lightly 主动机器学习 SSL 运行选择五个最有信息量的帧
在 SSL 和非 SSL 运行中都被选中的帧在边缘被突出显示。
图 5.20显示,添加 SSL 步骤明显改变了帧的选择标准。主要的是,SSL 之后选择的帧往往显示狗在更远的距离,与未使用 SSL 选择的帧形成鲜明对比,后者主要是特写镜头,展示了狗拿着球。这种转变突出了 SSL 对模型关注点和帧选择偏好的影响:

图 5.21 – 简要报告 – 比较非 SSL 运行(顶部图像)和 SSL 运行(底部图像)之间的视频采样密度
在检查图 5.21**.21中显示的新嵌入图后,很明显,嵌入模型在聚类帧方面表现更好。尽管有这种改进,但聚类仍然没有明确界定,这表明在 SSL 训练中增加 epoch 的数量可以进一步细化这一方面:

图 5.22 – SSL 活跃机器学习运行的新嵌入图
将 Lightly SSL 功能纳入机器学习管道是一个简单添加,可以为特定领域的数据提供显著的好处。通过利用这项高级技术,我们观察到在测试中经过 SSL 处理的模型生成的嵌入得到了显著改善。这种增强不仅提高了整体性能,还确保了管道针对正在处理的数据的独特特征进行了优化。
摘要
在本章中,我们学习了如何使用 Lightly 通过不同的采样策略高效地选择视频中最具信息量的帧,以改进目标检测模型。我们还看到了如何将这些选定的帧发送到标记平台 Encord,从而完成一个端到端的使用案例。最后,我们探讨了如何通过将 SSL 步骤纳入活跃的机器学习管道来进一步优化采样。
在接下来的工作中,我们的重点将转向探索如何有效地评估、监控和测试活跃的机器学习管道。这一步骤对于确保管道在整个部署过程中保持稳健和可靠至关重要。通过实施全面的评估策略,我们可以评估管道相对于预定义的指标和基准的性能。此外,持续的监控将使我们能够识别任何潜在的问题或与预期行为不符的情况,从而使我们能够采取主动措施以保持最佳性能。
此外,对活跃的机器学习管道进行严格的测试对于验证其功能并验证其准确性至关重要。通过系统化的测试程序,我们可以确保管道在各种场景和输入条件下表现一致。这将涉及设计并执行各种测试用例,涵盖广泛潜在的使用案例和边缘场景。
通过彻底评估、监控和测试活跃的机器学习管道,我们可以对其可靠性和性能建立信心。这个稳健的框架将使我们能够做出明智的决定,并从处理的数据中获得有价值的见解,最终导致特定领域领域的成果改进和决策能力增强。
第三部分:将主动机器学习应用于现实世界项目
第三部分 通过为读者提供理解高级主动机器学习(ML)方法的知识,并有效地将这些方法应用于现实场景,从而结束了对主动机器学习的探索。通过这些章节中讨论的先进工具,实践者将准备好应对复杂挑战,推动创新,并在他们的机器学习项目中取得显著改进。无论是通过改进评估实践还是利用强大的软件,本节旨在激发并指导读者掌握主动机器学习的艺术和科学。
本部分包括以下章节:
-
第六章,评估和提升效率
-
第七章,利用主动机器学习的工具和包
第六章:评估和提升效率
在本章中,我们将探讨严格评估主动机器学习系统性能的重要方面。我们将涵盖自动化、测试、监控和确定停止标准等各个主题。在本章中,我们将使用付费云服务,如 AWS,来演示如何在现实世界中实现自动、高效的主动学习管道。
通过彻底理解这些概念和技术,我们可以确保一个全面的主动机器学习过程,从而产生准确和可靠的结果。通过这次探索,我们将深入了解主动机器学习系统的有效性和效率,使我们能够做出明智的决定和改进。
到本章结束时,我们将涵盖以下内容:
-
创建高效的主动机器学习管道
-
监控主动机器学习管道
-
确定何时停止主动机器学习运行
-
通过主动机器学习增强生产模型监控
技术要求
对于本章,您需要以下内容:
-
MongoDB 账户:(
www.mongodb.com/) -
ClearML 账户:(
app.clear.ml/) -
GPU:您可以从您将使用的工具的网页上检查具体的硬件要求
-
一个考虑成本因素的 EC2 实例
在本章中,您需要安装以下包:
pip install clearml
pip install pymongo
您需要以下导入:
import os
from clearml import Task, TaskTypes
import pymongo
import datetime
创建高效的主动机器学习管道
正如我们在上一章中看到的,高效的主动机器学习管道由端到端管道组成。这意味着主动机器学习算法需要能够访问未标记的数据,选择最有信息量的帧,然后将它们无缝发送到标记平台。所有这些步骤都需要依次自动进行,以减少人工干预。
此外,测试此管道以确保每个步骤正常工作至关重要。一个云托管主动机器学习管道的例子如下:
-
未标记的数据存储在 AWS S3 桶中。
-
一个主动机器学习算法在可以访问 S3 桶的 EC2 实例上运行。
-
主动机器学习运行的成果保存在专门用于此目的的 S3 桶中,并与用于项目的标记平台相关联。
-
主动机器学习运行的最后一步是将选定的帧链接到标记平台并创建注释项目,以便标记人员开始工作。
在选择和配置 EC2 实例以运行主动机器学习代码时,考虑效率是至关重要的。很可能需要 GPU 来执行推理和计算主动机器学习嵌入。例如,如果你使用 Lightly,你可以参考他们在此页面的硬件推荐(docs.lightly.ai/docs/hardware-recommendations)。此外,考虑所选 EC2 实例的成本并确定其是否符合你的预算也很重要。你可以在这里找到 AWS EC2 按需定价(aws.amazon.com/ec2/pricing/on-demand/)。当你没有运行任何主动机器学习进程时,停止实例是一种良好的做法,可以节省金钱。
其他良好实践包括拥有一个 requirements.txt 文件,列出运行所需的软件包的所有版本。例如,对于在 第五章,利用主动学习处理大数据 中使用的软件包,requirements.txt 文件可能看起来是这样的。
awscli==1.31.6
ultralytics==8.0.145
lightly==1.4.23
docker==6.1.3
encord==0.1.85
你可以用所需的任何版本替换任何版本;理想情况下,使用软件包的最新版本会更好。
此外,通过参数使管道可配置可以更容易地进行扩展。例如,通过 YAML 配置文件指定选项,如采样策略、模型选择和数据源。这允许在不更改代码的情况下更改管道行为,简化工作流程的集成。作为提醒,我们已经在 第二章,设计查询策略框架 中探讨了不同的采样策略,并在 第四章,将主动学习应用于计算机视觉 中探讨了计算机视觉任务的模型选择。
使用我们的 Lightly 示例配置 YAML 文件的简单示例,可以参考 第五章,利用主动学习处理大数据,可能看起来是这样的:
model_path_in_s3: 's3://my-models-library/my-best-object-detection-model.pt'
inference_confidence_threshold: 0.3
proportionSamples: 0.20 # 20% of the samples
isSSLenabled: true
maxSSLepochs: 20
important_classes: {"person": 0, " sports ball": 32}
balance: true
balance_strategy:{ 'person': 0.50, 'sports ball': 0.50}
videos_folder_in_s3: "test"
s3_bucket_output: 'labeling-queue'
然后,可以使用此函数访问这些参数:
def get_config_yaml(path_to_config_yaml="config.yaml"):
# Open the YAML file
with open(path_to_config_yaml, "r") as file:
# Load the YAML content
config = yaml.safe_load(file)
file.close()
return config
然后是以下内容:
config = get_config_yaml(path_to_config_yaml="config.yaml")
model_path_in_s3 = config["model_path_in_s3"]
inference_confidence_threshold = config["inference_confidence_threshold"]
proportionSamples = config["proportionSamples"]
isSSLenabled = config["isSSLenabled"]
if isSSLenabled:
maxSSLepochs = config['maxSSLepochs']
important_classes = config["important_classes"]
s3_bucket_output = config["s3_bucket_output"]
balance_strategy = config['balance_strategy']
if balance_strategy:
balance = config['balance']
这些变量可以在 第五章,利用主动学习处理大数据 中使用,并将使其可扩展到所有工作流程和应用。
因此,对于你的项目,你只需要更改 YAML 文件,然后就可以使用这些脚本为所有项目服务,而无需修改脚本本身。
接下来,我们将探讨监控我们的主动机器学习运行并确保我们能够全面了解整个过程的解决方案。
监控主动机器学习管道
logging,这是一个多功能且内置的库。
引入如ClearML(clear.ml/)这样的 MLOps 平台可以显著简化管道运行的监控。ClearML 提供实时统计、图形数据可视化、广泛的日志记录、模型工件以及以并排格式比较管道运行的能力。虽然 ClearML 传统上用于提高机器学习训练和部署管道的可观察性,但它对于活跃机器学习管道也非常有效,增强了其管理和监督。
active_learning_runs and initialize a task within it, labeled testing-AL, which corresponds to a specific run. Once implemented, this configuration enables the automatic tracking of the run, as illustrated in *Figure 6**.1*, under the console tab of the ClearML project configured via this code snippet:

图 6.1 – 初始化 ClearML 运行后自动保存的控制台日志
这种集成不仅简化了监控和管理机器学习运行的过程,而且还确保所有相关数据和指标都能系统地捕获并可在 ClearML 平台上进行分析:
Task.set_credentials(api_host='https://api.community.clear.ml',
web_host='https://app.community.clear.ml',
key='your_clearml_access_key',
secret='your_clearml_secret_key')
task = Task.init(project_name='active_learning_runs',
task_name='testing-AL',
task_type=TaskTypes.inference)
我们选择 ClearML 任务类型TaskTypes.inference,因为它专门设计用于促进机器学习中推理过程的全面日志记录和细致监控。此任务类型擅长细致跟踪输入数据、模型输出的预测以及一系列相关指标或性能指标,使其特别适合活跃的机器学习运行。确实,正如我们在前面的章节中看到的,活跃的机器学习运行包括进行推理以识别最有利于添加到标注队列的帧。因此,TaskTypes.inference是这里理想的选项。此任务类型对于系统地收集和彻底分析推理阶段特有的关键性能指标(如延迟)至关重要。此外,利用TaskTypes.inference使团队能够积累有关模型与实时数据交互时行为的宝贵见解——这是活跃机器学习系统成功的基本方面。对运行实时性能的详细了解对于优化活跃机器学习策略和增强整体模型效能至关重要。
监控活跃机器学习管道的另一项宝贵工具是MongoDB(www.mongodb.com/),这是一个以用户友好著称的广泛使用的数据库。其灵活性使其成为机器学习管道的理想选择,因为机器学习管道通常会随着时间的推移而演变。在活跃机器学习管道的背景下,MongoDB 可以用于自动生成标注队列,例如。MongoDB 的这种应用不仅简化了数据处理过程,还有助于提高机器学习管道的整体效率和适应性。
mongodb:
username = 'your_mongodb_username'
password = 'your_mongodb_pwd'
cluster = 'your_mongodb_cluster'
uri = 'mongodb+srv://' + username + ':' + password + '@' + cluster
client = pymongo.MongoClient(uri)
接下来,我们为这个项目创建一个特定的 MongoDB 集合,我们将命名为ml_demo_project。在这个集合中,我们将创建一个名为ml_labeling_queue_demo的表格。这种在 MongoDB 中的组织结构将有助于高效管理和检索与我们的项目相关的数据:
db = client['ml_demo_project']
collection = db['ml_labeling_queue_demo']
最后一步是将我们活跃机器学习运行得出的数据填充到我们的标注队列表中。这是一个通用示例,应针对个别项目的具体要求进行调整。通过整合这一步骤,我们确保了机器学习运行的信息被准确且高效地转移到标注队列中,为针对每个项目的独特需求进行的后续处理和分析奠定了基础:
document = {'Name dataset': 'demo',
'Labeler': 'TBD',
'Reviewer': 'TBD',
'Labeling status': 'In queue',
'Reviewing status': 'None',
'date': datetime.datetime.now()}
collection.insert_one(document)
这个 MongoDB 集合简化了监控标注队列进度的过程,便于与标注者就即将到来的项目进行有效沟通。这种设置消除了手动输入每个新标注项目需求,显著提高了工作流程效率。通过自动化跟踪和更新队列,它确保了管理标注任务更加顺畅和协调的方法。
通过日志、MLOps 平台、数据库和其他工具进行积极监控对于保持可见性和快速捕捉生产活跃机器学习管道中的任何问题至关重要。这有助于降低风险并提高系统可靠性。
为了确保这种监控在决策过程中得到有效利用,建立明确的临界行动标准至关重要,例如确定何时停止活跃的机器学习运行,我们将在下一部分进行讨论。
确定何时停止活跃机器学习运行
主动机器学习运行是动态和迭代的进程,需要仔细监控,正如我们之前所看到的。但它们还需要战略性的决策来决定停止的最佳时机。停止活跃机器学习运行的决定至关重要,因为它会影响学习模型的表现和效率。本节重点介绍有效确定何时停止活跃机器学习运行的关键考虑因素和策略。
在主动机器学习中,为项目建立明确的性能目标是至关重要的。例如,考虑一个旨在开发面部识别系统的项目。在这里,准确率和精确率可能是选择的表现指标。一个多样化的测试集,反映了现实世界的条件和不同的面部特征,对于评估模型至关重要。
假设我们在建立的测试集上预定义的准确率阈值为 95%,而对于精确度,则为 90%。活跃的机器学习过程应继续进行,直到模型在测试集上持续达到或超过这些指标。如果模型在测试集上显示出 95%或更高的准确率和 90%或更高的精确率,这表明模型已经学会了在不同面孔和场景中很好地泛化。这种在多样化的测试集上的一致表现表明,模型已经通过主动学习过程有效地进行了调整,可以应用于现实世界。
在决定何时停止活跃的机器学习过程时,额外的考虑因素起着至关重要的作用。在先前的面部识别示例中,在决定停止活跃的机器学习过程时,有几个简单但重要的额外因素需要考虑。以下是一些在决定停止活跃的机器学习过程之前可以采取的步骤:
-
警惕过拟合:当模型在训练数据上的表现远好于测试集时,就会发生这种情况。如果我们看到这种情况,那就是停止并调整模型以避免过拟合的时候了。
-
考虑我们的资源:时间、计算能力和金钱等资源是有限的。即使我们的模型还没有达到我们想要的 95%的准确率或 90%的精确度,如果我们资源不足,我们可能不得不停止。
-
注意收益递减:这意味着如果继续训练并不能真正提高我们的模型,那么它可能已经学到了它能学到的所有东西。在这种情况下继续训练它不会有所帮助。
-
通过反馈循环持续重新评估模型:随着世界和数据的改变,我们的模型的目标可能也需要改变。定期检查我们的模型是否仍然满足我们当前的需求有助于保持其相关性和有效性。
停止活跃的机器学习运行的决策应基于达到预定义的性能指标、在多样化的测试集上保持稳定性、监控资源限制以及警惕过拟合和收益递减。通过仔细考虑这些因素,我们可以确保活跃的机器学习模型既有效又高效,与项目的总体目标保持一致。
现在让我们讨论如何在生产环境中使用主动学习。
通过活跃的机器学习增强生产模型监控
已经对活跃的机器学习有了全面的理解,本节将重点转向其在生产环境中监控机器学习模型的实际应用。用户数据和市场条件的动态性为保持部署模型的准确性和相关性带来了独特的挑战。在此背景下,活跃的机器学习成为了一个关键工具,它提供了一种主动的方法来实时识别和适应变化。本节将探讨通过哪些方法和策略可以利用活跃的机器学习来持续改进和调整模型,根据不断变化的数据来确保这些模型保持稳健、高效,并与当前趋势和用户行为保持一致。
监控生产模型的挑战
在监控生产模型时存在几个挑战。首先,我们有数据漂移和模型退化的问题。
数据漂移指的是机器学习模型输入数据随时间的变化。这种变化可能由于各种原因而发生,例如用户行为的演变、季节性效应、经济变化或模型运行环境的更广泛环境的变化。数据漂移的关键特征是当前输入数据的统计特性与原始训练数据不同,如图 6.2所示。数据漂移可能会显著影响模型的性能,因为模型最初训练时所做的假设不再成立。它可能导致准确性和可靠性的下降,使模型在做出预测或分类时变得不那么有效:

图 6.2 – 数据漂移的示意图
模型退化,也称为模型降级或性能衰减,指的是机器学习模型随时间推移性能的下降。这一现象与数据漂移密切相关,如图 6.3所示。模型退化的一个主要原因是模型在真实环境中遇到的数据性质发生变化:

图 6.3 – 模型随时间退化的示意图
然而,模型退化也可能由于其他因素,例如以下因素:
-
关系变化:随着时间的推移,变量之间的关系可能会发生变化,使得模型学习到的模式过时
-
反馈循环:如果一个模型的预测被用作影响未来数据的决策过程的一部分,它可能会创建逐渐降低模型性能的反馈循环
-
外部因素:政策变化、自然灾害或全球事件等不可预见的外部因素也可能导致模型退化
数据漂移和模型退化都强调了在生产中对机器学习模型进行持续监控和更新的必要性。确定这些变化何时以及如何发生对于保持模型的有效性和准确性至关重要。
活跃的机器学习用于监控生产中的模型
由于主动机器学习具有动态和响应性,它特别适合对抗数据漂移和模型退化。确实,正如我们在章节中讨论的那样,主动机器学习在目标数据获取方面表现出色,能够识别和获取最具信息量的数据点。这种方法在解决数据漂移和模型退化问题时特别有利,因为算法主动查询新的数据,这些数据能够准确反映当前的环境或用户行为。这种方法不仅比被动收集大量数据集更有效率,而且确保数据的相关性,避免冗余。主动机器学习系统天生具有适应性,能够快速调整其理解和预测,以应对新的数据,这对于在数据分布变化中保持有效性至关重要。这种适应性通过系统的持续学习和改进能力得到增强。随着主动机器学习系统接收新的数据点和反馈,它们不断更新和优化其模型,从而减轻模型退化的影响,并确保模型随着数据和环境的改变而发展。
主动机器学习通过选择最具信息量的样本来解决数据标注成本高和时间密集的问题,这个过程在适应数据漂移时特别有益。在标注过程中对资源的有效利用确保了模型获得最大效益。此外,主动机器学习算法旨在早期检测数据模式的变化或性能下降,作为数据漂移和模型退化的早期预警系统。这种早期检测能力允许及时采取干预措施,如模型调整或重新训练,以防止性能显著下降。
在第二章《设计查询策略框架》中,我们也讨论了主动机器学习如何提供可定制的查询策略,包括不确定性采样和委员会查询,这些策略可以根据应用程序的具体需求进行定制。这种灵活性使得在应对各种场景中数据漂移和模型退化等独特挑战时,能够更加有效地做出响应,凸显了主动机器学习在动态数据环境中的全面适应性。
一旦机器学习模型部署后,早期检测漂移和退化对于维持模型的性能至关重要。主动机器学习在这里扮演着不可或缺的角色,有效地作为早期预警系统。这种能力对于在问题升级之前进行预先识别和缓解潜在问题至关重要,从而保护模型的完整性和准确性。
我们现在将探讨通过哪些机制和策略可以使用主动机器学习(ML)来实现这一目标,并强调其在动态环境中主动管理和维护机器学习模型的重要性。
在前几章中,我们已经看到了一些使用主动机器学习方法进行早期检测的机制:
-
不确定性采样:主动机器学习算法通常采用不确定性采样,其中模型识别出对其预测信心最低的数据点。此类点数量的突然增加可能表明底层数据分布的变化,表明可能存在数据漂移。
-
异常检测:主动机器学习系统可以配备异常检测功能,以识别传入数据中的异常模式。这些异常可能表明数据景观的变化,如果不加以解决,可能导致模型退化。
-
委员会查询:这种方法涉及维护多个模型或模型的多个版本(委员会),并使用它们的分歧来识别具有挑战性的数据点。委员会成员预测之间的差异越来越大可能表明新兴的数据漂移或模型退化,因为它表明模型对当前数据的信心越来越低。
-
反馈循环:在用户反馈或现实世界结果可用的情况下,主动机器学习可以使用此反馈来评估模型性能。用户反馈模式的变化可以提供早期迹象,表明数据趋势的变化或模型有效性的下降。
主动机器学习在早期问题检测方面的能力至关重要,它允许及时进行干预。这种主动策略比传统的被动方法更为有效,后者只有在性能明显下降后才会处理问题。通过早期发现问题,主动机器学习确保为模型重新训练或调整分配的资源得到高效和审慎的使用。在计算资源或标记数据稀缺的环境中,这一点尤为重要。此外,在面向最终用户的应用中,模型性能的一致性对于维持用户信任至关重要。通过早期检测和及时纠正数据漂移或模型退化,主动机器学习对提供可靠和一致的用户体验做出了重大贡献,凸显了其在维持机器学习模型在各种实际应用中的可信度和有效性的价值。
早期检测数据漂移和模型退化
在主动机器学习中,有效实施数据漂移和模型退化的早期检测需要考虑几个关键因素:
-
选择合适的监控指标是关键。这些指标应与模型的目标以及数据和应用的独特特征紧密一致。
-
设置合理的警报阈值也非常关键,在敏感性和实用性之间取得平衡,以避免频繁的误报或错过关键变化。
-
将活跃的机器学习系统与现有数据管道集成对于实时监控和对检测到的问题快速响应至关重要,从而提高系统效率和响应能力。对于实际实施,这意味着将活跃的机器学习算法直接链接到用户数据的存储,使系统能够在数据上传后立即自动参与和分析新数据。这种集成确保了持续、最新的监控,这对于及时检测和处理潜在的数据漂移或模型退化至关重要。
让我们考虑一个来自零售用例的例子,具体是在库存管理中使用的计算机视觉系统的背景下。想象一家零售店使用配备计算机视觉的活跃机器学习系统进行库存管理。该系统旨在通过摄像头监控商店的货架,跟踪库存水平,检测商品库存不足的情况,并确定何时需要补货。计算机视觉模型最初是在一个图像数据集上训练的,该数据集展示了货架库存的各种状态,从满载到几乎空。它学会了识别不同的产品、它们的位置和数量。随着时间的推移,商店引入了新产品并更改了一些商品的布局。在常规监控期间,活跃的机器学习系统开始检测图像中的异常;模型遇到了不熟悉的图像,导致其预测的不确定性。这种不确定性通常反映在较低的置信度分数上,表明潜在的异常。系统还采用统计方法来识别异常值——与产品排列的既定模式显著偏离的数据点。此外,它还分析随时间的变化,将当前图像与历史数据进行比较,以发现产品类型或排列中的偏差。当系统标记出异常时,它会提醒商店经理进行进一步检查。如果变化是有意的,例如新产品的引入,则此信息用于更新和重新训练模型,确保其适应新的商店布局和库存。如果变化是无意的,例如产品放置不当,则可以纠正以保持库存的准确性。这一自适应过程确保机器学习模型在实时库存管理中保持有效性,适应零售环境的渐进和突然变化。
在本例中,活跃的机器学习系统的异常检测能力对于维持库存管理系统的有效性至关重要。它确保计算机视觉模型在商店产品范围和布局发生变化时仍能保持准确性和可靠性,从而防止模型退化并确保运营效率。
总结来说,通过关注最有信息量的数据点并整合用户反馈,主动机器学习提供了一种动态的方法来维护模型在用户数据和市场条件变化中的相关性和准确性。这种方法带来的适应性和效率对于机器学习在各种领域的长期成功至关重要。
摘要
在本章中,我们深入探讨了严格评估主动机器学习系统性能的关键方面。我们首先理解了自动化流程以增强效率和准确性的重要性。然后,章节引导我们了解各种测试方法,强调它们在确保稳健和可靠的主动机器学习管道中的作用。
我们讨论的大部分内容集中在主动机器学习管道的持续监控的重要性上。这种监控不仅涉及观察性能,还涉及理解和解释结果,以便做出数据驱动的决策。
我们讨论的最重要的主题之一是确定主动机器学习运行的适当停止标准。我们探讨了如何设置预定义的性能指标,如准确性和精确度,对于指导这些决策至关重要。我们还强调了拥有多样性和代表性的测试集的重要性,以确保模型在实际场景中的适用性。
此外,我们还讨论了需要注意过度拟合、资源限制、回报递减以及实施反馈循环的重要性。这些考虑因素在确定何时停止机器学习运行以及确保模型在不断变化的环境中的整体成功和相关性方面发挥着关键作用。
最后,我们确定主动机器学习在监控生产环境中的模型方面非常擅长。其应用范围包括早期检测数据漂移和模型退化,尤其是在无缝集成到用户数据管道时。这种集成使得主动机器学习系统能够监控数据,确保任何偏差或异常都能被及时连续地检测到。此外,系统可以配置为在出现这些不规则性时触发警报,以便立即关注并采取行动。这种能力不仅增强了模型的可靠性和准确性,还确保了其在不断变化的数据景观面前具有适应性和弹性,使主动机器学习成为生产模型监控的有力工具。
在下一章,利用工具和包进行主动机器学习中,我们将关注在主动机器学习中常用到的各种 Python 库、框架和工具。我们将对这些资源进行概述,强调它们在实现各种主动机器学习技术中的价值。这将为您提供提升您的主动机器学习项目所需的知识和技能,并帮助您确定最适合它们的工具。这一章承诺将成为当前主动机器学习工具的全面指南。
第七章:利用主动机器学习的工具和包
在本章中,我们将讨论一系列在主动机器学习中常用的 Python 库、框架和工具。这些资源对于实现各种主动机器学习技术至关重要。本章的内容旨在为不同水平的专家提供信息丰富且实用的内容,从初学者到经验丰富的程序员。目标是提供对我们将要涵盖的工具的坚实基础理解,以便有效地将主动机器学习技术融入您的项目中。
在本章中,重点将放在理解主动机器学习的 Python 包上。我们将使用流行的 Python 库scikit-learn和modAL。您将了解它们的特性以及它们如何应用于主动机器学习场景。我们还将探索一系列主动机器学习工具。除了本书前几节中涵盖的工具外,本章还将介绍一些额外的主动机器学习工具。每个工具都将提供其特性和潜在应用的概述,帮助您了解它们如何适应不同的主动机器学习环境。
在本章中,我们将讨论以下主题:
-
掌握用于增强主动机器学习的 Python 包
-
熟悉主动机器学习工具
技术要求
对于本章的练习,您需要安装以下包:
pip install scikit-learn
pip install modAL-python
您将需要以下导入:
from sklearn.cluster import KMeans
from sklearn.linear_model import LogisticRegression
from sklearn.utils import shuffle
import numpy as np
import random
from modAL.models import ActiveLearner, Committee
from sklearn.ensemble import RandomForestClassifier
from modAL.uncertainty import uncertainty_sampling
import os
from PIL import Image
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from modAL.disagreement import vote_entropy_sampling
掌握用于增强主动机器学习的 Python 包
本节提供了两个广受欢迎的 Python 包的全面概述,这些包以其在促进主动机器学习方面的能力而闻名:scikit-learn,一个功能丰富且用户友好的库,在机器学习社区中是基础性的,因为它拥有广泛的传统机器学习工具。另一方面,专门为主动机器学习设计的modAL,建立在scikit-learn的强大框架之上,引入了更动态、数据高效的机器学习技术。这两个包共同代表了一个强大的工具包,供那些希望利用主动机器学习方法优势的人使用。
scikit-learn
虽然不是专门为主动机器学习设计的,但scikit-learn(scikit-learn.org/stable/index.html)是 Python 机器学习生态系统中的基础包。它提供了一系列算法和工具,这些工具通常与主动机器学习包一起使用——一个用于分类、回归、聚类和降维的算法集合。它还提供了模型评估和数据预处理的工具。
scikit-learn通常用作模型开发的基础,并且经常与主动机器学习包集成以进行模型训练和评估。
例如,scikit-learn可以通过根据购买行为、人口统计和参与度指标对客户进行聚类,在营销中执行客户细分。scikit-learn中流行的 K-means 聚类算法有助于识别用于针对性营销活动的不同客户群体。通过迭代改进聚类模型,可以结合活跃机器学习。例如,营销分析师可以对聚类算法不确定的模糊案例进行标记,随着时间的推移提高模型的准确性。
让我们用一个模拟示例来说明这一点。
首先,我们使用KMeans进行初始聚类。我们首先定义一些模拟客户数据(年龄,年收入):
X = np.array([[34, 20000], [42, 30000], [23, 25000], [32, 45000],
[38, 30000]])
然后我们使用KMeans进行聚类:
kmeans = KMeans(n_clusters=2, random_state=0).fit(X)
然后,我们预测每个客户的聚类:
clusters = kmeans.predict(X)
我们已经根据年龄和年收入将客户分为两个聚类。
接下来,我们设置活跃机器学习部分。假设我们有一个更大的、未标记的客户特征数据集X_unlabeled。在我们的客户细分场景中使用KMeans时,未标记数据将包括具有与我们用于聚类的相同特征(在我们的案例中是年龄和年收入)的客户记录,但没有分配的聚类标签。这些数据是我们将在活跃机器学习框架中应用和改进聚类和分类模型的数据:
X_unlabeled = np.array([[28, 22000], [45, 55000], [37, 35000],
[50, 48000], [29, 27000], [41, 32000]])
我们需要一个模型(一个分类器)来对这个未标记的数据进行预测。为了说明,让我们使用一个简单的分类器LogisticRegression。我们初始化这个分类器,并使用聚类作为标签,在我们的初始数据集(X)上对其进行训练:
classifier = LogisticRegression()
classifier.fit(X, clusters)
然后我们实现活跃机器学习循环。在每次迭代中,分类器对未标记数据进行标签预测。首先,我们需要创建一个obtain_labels占位符函数,用于获取所选数据点的真实标签。在实际场景中,此函数将涉及获取实际标签的过程,例如进行调查或专家分析。由于我们正在创建一个模拟示例,我们设计这个函数以基于某些假设逻辑随机分配标签:
def obtain_labels(data):
return np.random.choice([0, 1], size=len(data))
对于我们的活跃机器学习循环,我们需要选择我们想要进行的迭代次数以及每次迭代中要标记的样本数量:
num_iterations = 10
num_to_label = 2
我们现在可以创建我们的活跃机器学习循环,它将执行以下操作:
-
选择分类器最不自信的实例。
-
获取这些实例的真实标签(在实际操作中,这可能涉及手动标记或额外数据收集)。
-
使用这些新标签更新分类器。
-
定期使用新标记的数据更新
KMeans模型,以细化客户细分。
以下是一个代码片段,帮助我们实现这一点:
for iteration in range(num_iterations):
if len(X_unlabeled) == 0:
break # No more data to label
# Predict on unlabeled data
predictions = classifier.predict_proba(X_unlabeled)
uncertainty = np.max(predictions, axis=1)
# Select num_to_label instances with least confidence
uncertain_indices = np.argsort(uncertainty)[:num_to_label]
# Obtain labels for these instances
new_labels = obtain_labels(X_unlabeled[uncertain_indices])
# Update our dataset
X = np.vstack([X, X_unlabeled[uncertain_indices]])
clusters = np.hstack([clusters, new_labels])
# Re-train classifier and KMeans
classifier.fit(X, clusters)
kmeans.fit(X)
print(f"Iteration {iteration+1}, Labeled Data: {
X_unlabeled[uncertain_indices]} with Labels: {new_labels}")
# Remove labeled instances from unlabeled data
X_unlabeled = np.delete(X_unlabeled, uncertain_indices, axis=0)
# Shuffle unlabeled data to avoid any order bias
X_unlabeled = shuffle(X_unlabeled)
上述代码返回以下结果:
Iteration 1, Labeled Data: [[45 55000] [29 27000]] with Labels: [0 1]
Iteration 2, Labeled Data: [[37 35000] [28 22000]] with Labels: [1 1]
Iteration 3, Labeled Data: [[41 32000] [50 48000]] with Labels: [0 0]
我们的活动机器学习循环迭代指定次数,每次选择分类器做出的最不自信的预测,为这些实例获取标签,然后使用新数据更新分类器和KMeans模型。记住,obtain_labels函数是一种简化。在实际应用中,获取标签将涉及一个预言者手动标记样本,正如我们在第三章中描述的,在循环中管理人类。
modAL
scikit-learn。它允许轻松地将活动学习策略集成到现有的机器学习工作流程中。它提供了各种活动机器学习策略,如不确定性采样和委员会查询。它还支持自定义查询策略,并易于与scikit-learn模型集成。
例如,它非常适合图像分类和回归等任务,在这些任务中,活动机器学习可以有效地选择用于注释的信息性样本。
让我们看看一个例子,其中我们使用流行的torchvision数据集对图像进行分类。鉴于图像的大量,活动机器学习可以帮助优先考虑哪些图像应该手动标记。我们将使用modAL框架的不确定性采样查询策略。它将能够识别最有信息量的图像(分类器最不确定的图像)并对其进行标记查询。
我们实现了一个load_images函数来从数据集目录中读取图像,然后我们将它们转换为灰度图并展平图像以进行训练。实际上,我们需要将图像数据转换为与RandomForest兼容的格式,因此每个图像(一个二维数组)被展平成一个一维数组。这意味着将图像转换成一个像素值的长时间向量。对于我们的 32x32 像素的灰度图像,展平形式将是一个包含 1,024 个元素的向量(32x32):
def load_data():
# Define the transformation
transform = transforms.Compose([
transforms.ToTensor(), # Convert images to PyTorch tensors
])
# Load the CIFAR10 dataset
dataset = CIFAR10(root='data', train=True, download=True,
transform=transform)
# Load all data into memory (for small datasets)
dataloader = DataLoader(dataset, batch_size=len(dataset),
shuffle=False)
data_iter = iter(dataloader)
images, labels = next(data_iter)
# Convert images and labels to numpy arrays
X_all = images.numpy()
y_all = np.array(labels)
# Convert images from 3D to 1D (batch_size, 3, 32, 32) -> (batch_size, 3072) for RandomForest
X_all = X_all.reshape(X_all.shape[0], -1)
# Map numerical labels to string labels
class_names = dataset.classes
y_all = np.array([class_names[label] for label in y_all])
return X_all, y_all
接下来,为了我们的示例,我们将数据集分为初始标记数据(图像存储在X_initial中,标签存储在y_initial中)和未标记数据(X_unlabeled):
X_initial, X_unlabeled, y_initial, _ = train_test_split(X_all, y_all,
test_size=0.75, random_state=42)
我们以 12,500 个标记图像和 37,500 个未标记图像开始我们的示例。
然后我们初始化modAL活动学习器:
learner = ActiveLearner(
estimator=RandomForestClassifier(),
query_strategy=uncertainty_sampling,
X_training=X_initial_flat, y_training=y_initial
)
ActiveLearner object is created. This learner uses RandomForestClassifier as its estimator. RandomForest is a popular ensemble learning method for classification, which operates by constructing multiple decision trees during training and outputting the class that is the mode of the classes of the individual trees. The query strategy is set to X_initial_flat initial training data and y_training labels are provided to the learner.
最后,我们使用以下五次迭代循环模拟标签的查询:
for i in range(5):
query_idx, _ = learner.query(X_unlabeled)
actual_label = y_all[query_idx[0]]
print(f"Selected unlabeled query is sample number {query_idx[0]}. Actual label: {actual_label}")
learner.teach(X_unlabeled[query_idx].reshape(1, -1), actual_label.reshape(1,))
X_unlabeled = np.delete(X_unlabeled, query_idx, axis=0)
y_all = np.delete(y_all, query_idx)
前面的循环返回以下内容:
Selected unlabeled query is sample number 3100\. Actual label: cat
Selected unlabeled query is sample number 7393\. Actual label: deer
Selected unlabeled query is sample number 4728\. Actual label: horse
Selected unlabeled query is sample number 447\. Actual label: deer
Selected unlabeled query is sample number 17968\. Actual label: bird
循环代表五次活动机器学习迭代。在每次迭代中,模型查询数据集以标记新实例。学习者查询X_unlabeled训练数据,并返回它最不确定的样本的query_idx索引和query_instance实例。然后,使用查询的实例对学习者进行教学。在现实世界场景中,这一步将涉及从预言者(如人类注释员)那里获取查询实例的标签。然而,在这个模拟示例中,标签直接从y_all数据集中获取。
这个例子说明了使用 modAL 进行主动机器学习的过程,其中模型主动查询特定的实例进行学习,而不是从静态数据集中被动学习。
modAL 是一个优秀的 Python 包,它允许我们轻松实现复杂的主动机器学习方法。例如,让我们使用 modAL 包创建一个主动机器学习的用例,特别关注 基于委员会 的算法。在这个例子中,我们将使用一个分类器委员会从未标记数据集中查询最有信息量的样本。作为提醒,我们在 第二章**,设计查询策略框架 中定义了 委员会查询方法。
在这个例子中,让我们使用 Iris 数据集(Fisher, R. A.. (1988). Iris. UCI Machine Learning Repository doi.org/10.24432/C56C76),这是分类任务中常用的选择。Iris 数据集是机器学习和统计学中的一个经典数据集,常用于演示分类算法。该数据集包含 150 个鸢尾花样本。每个样本有四个特征:花瓣长度、花瓣宽度、花萼长度和花萼宽度。这些特征是鸢尾花植物相应部分的厘米测量值。数据集中有三种(类别)鸢尾花植物:Iris setosa、Iris virginica 和 Iris versicolor。每个类别有 50 个样本,使得数据集在三个类别之间均衡。使用 Iris 数据集的典型任务是多类分类问题。目标是根据花萼和花瓣的测量值预测鸢尾花植物的物种。
我们将使用一个 K-Nearest Neighbors 分类器委员会。该委员会将使用 委员会查询(QBC)策略 来选择意见分歧最大的数据点。
我们首先加载 Iris 数据集(来自 scikit-learn 提供的数据集),并创建一个初始的小型标记数据集和一个较大的未标记数据集:
X, y = load_iris(return_X_y=True)
X_labeled, X_unlabeled, y_labeled, y_unlabeled = train_test_split(
X, y, test_size=0.9, random_state=42)
我们初始化了二十个 ActiveLearner 实例,每个实例都使用一个 RandomForestClassifier,并将它们组合成一个 Committee:
n_learners = 20
learners = [ActiveLearner(
estimator=RandomForestClassifier(), X_training=X_labeled, \
y_training=y_labeled
) for _ in range(n_learners)]
committee = Committee(learner_list=learners,
query_strategy=vote_entropy_sampling)
主动机器学习循环使用 vote_entropy_sampling 策略来选择委员会成员意见分歧最大的样本。
下面是我们的主动机器学习循环在五次迭代中的样子:
n_queries = 5
for idx in range(n_queries):
query_idx, query_instance = committee.query(X_unlabeled)
print(f"\nSelected unlabeled query is sample number {query_idx}. We simulate labeling this sample which is labeled as: {y_unlabeled[query_idx]}")
committee.teach(X_unlabeled[query_idx], y_unlabeled[query_idx])
# Remove the queried instance from the pool
X_unlabeled = np.delete(X_unlabeled, query_idx, axis=0)
y_unlabeled = np.delete(y_unlabeled, query_idx)
print(f"Number of unlabeled samples is {len(X_unlabeled)}")
# Calculate and print committee score
committee_score = committee.score(X, y)
print(f"Iteration {idx+1}, Committee Score: {committee_score}")
Committee 对象的 query 方法用于从未标记的 X_unlabeled 数据集中选择最有信息量的样本。该委员会由多个学习者组成,使用其内部的查询策略 vote_entropy_sampling 来确定在 X_unlabeled 中它认为对学习最有价值的实例。
每次迭代中选择的样本用于教导(重新训练)所有委员会的学习者。每次查询后,评估委员会的性能:
Selected unlabeled query is sample number [8]. We simulate labeling this sample which is labeled as: [0]
Number of unlabeled samples is 129
Iteration 1, Committee Score: 0.96
Selected unlabeled query is sample number [125]. We simulate labeling this sample which is labeled as: [2]
Number of unlabeled samples is 128
Iteration 2, Committee Score: 0.9466666666666667
Selected unlabeled query is sample number [42]. We simulate labeling this sample which is labeled as: [2]
Number of unlabeled samples is 127
Iteration 3, Committee Score: 0.9466666666666667
Selected unlabeled query is sample number [47]. We simulate labeling this sample which is labeled as: [1]
Number of unlabeled samples is 126
Iteration 4, Committee Score: 0.9733333333333334
Selected unlabeled query is sample number [95]. We simulate labeling this sample which is labeled as: [1]
Number of unlabeled samples is 125
Iteration 5, Committee Score: 0.9733333333333334
这个例子演示了如何使用modAL中的学习者委员会通过查询最有信息量的样本来主动提高模型性能。委员会的多样化意见有助于选择对学习更有信息量的样本,从而更有效地提高整体模型。例如,我们在输出中观察到,委员会的分数从 0.96 提高到 0.973。
在主动机器学习中,特别是在使用如前例所示的基于委员会的方法时,通常期望模型的性能(或在这种情况下,模型的委员会)会随着迭代而提高。这种改进是预期的,因为委员会正在被训练以越来越有信息量的样本,这些样本是根据委员会的不确定性或分歧选择的。
然而,有几个要点值得注意:
-
增量改进:性能的提高可能不是线性的或在整个迭代过程中都是一致的。在某些迭代中,模型可能显著改进,而在其他迭代中,改进可能很小甚至停滞。我们可以从我们的例子中看到这一点,其中委员会的分数从 0.96 降至 0.94,然后又回升到 0.973。
-
取决于数据和模型:改进的速度和一致性取决于数据的性质和学习算法的有效性。对于某些数据集或配置,改进可能快速且一致,而对于其他数据集,改进可能较慢或不可预测。
-
递减回报:随着最有信息量的样本被添加到训练集中,剩余的无标签样本可能变得不那么有信息量,导致在后续迭代中性能改进的递减回报。
-
modAL函数默认使用准确率(accuracy)作为衡量委员会综合预测与真实标签一致性的指标。随着委员会接触到更多数据的有代表性样本,其预测应该变得更加准确。 -
评估方法:评估委员会表现的方法也可能影响感知到的改进。如果评估是在静态测试集上进行的,改进可能更为明显。然而,如果评估是在训练集上进行的(包括新添加的样本),由于数据复杂性的增加或方差的变化,改进可能不那么明显。
总结来说,虽然在一个迭代周期内委员会性能分数的增加在主动机器学习中是一个常见的期望,但实际的改进模式可能因各种因素而异。定期监控和调整可能有必要,以确保主动机器学习过程产生预期的结果,正如我们在第六章,评估和 提高效率中看到的。
选择合适的 Python 包进行主动机器学习取决于手头任务的特定要求,包括数据类型、所使用的机器学习模型和期望的主动学习策略。有效地整合这些包可以提高数据标注的效率、加快模型收敛速度,并整体提高机器学习模型的表现。
接下来,我们将探讨可以轻松用于对未标记数据进行主动机器学习的工具,如 Encord Active、Lightly、Cleanlab、Voxel51 和 UBIAI。
熟悉主动机器学习工具
在整本书中,我们介绍了讨论了几个关键的主动机器学习工具和标注平台,包括 Lightly、Encord、LabelBox、Snorkel AI、Prodigy、modAL和 Roboflow。为了进一步加深你的理解并帮助你选择最适合你特定项目需求的最合适的工具,让我们带着更深入的见解重新审视这些工具,并介绍一些额外的工具:
-
scikit-learn。它因其广泛的查询策略而脱颖而出,这些策略可以根据不同的主动机器学习场景进行定制。无论你是在处理分类、回归还是聚类任务,modAL都提供了一个强大且直观的界面,用于实现主动学习工作流程。 -
Label Studio (
docs.humansignal.com/guide/active_learning.html?__hstc=90244869.a32555b92661e36e5f4b3b8a0f2cc99a.1706210819596.1706210819596.1706210819596.1&__hssc=90244869.2.1706210819596&__hsfp=3755259113&_gl=1*1i1r2ib*_ga*MTE1NzM0NDQ4Ny4xNzA2MjEwODE5*_ga_NQELN45JRH*MTcwNjIxMDgxOS4xLjEuMTcwNjIxMDgzNC4wLjAuMA): 一个开源的多类型数据标注工具,Label Studio 在适应不同形式的数据方面表现出色,包括文本、图像和音频。它允许将机器学习模型集成到标注过程中,从而通过主动机器学习提高标注效率。其灵活性扩展到可定制的标注界面,使其适用于数据标注的广泛应用。 -
Prodigy (
prodi.gy/):Prodigy 提供了一种独特的主动机器学习和人机交互方法的结合。它是一个高效的标注工具,尤其适用于精炼 NLP 模型的训练数据。它的实时反馈循环允许快速迭代和模型改进,使其成为需要快速适应和精确数据标注的项目的一个理想选择。 -
Lightly(
www.lightly.ai/): 专注于图像数据集,Lightly 使用主动机器学习来识别训练中最具代表性和多样化的图像集。这确保了模型在平衡和多样化的数据集上训练,从而提高了泛化能力和性能。Lightly 对于数据丰富但标注资源有限的项目特别有用。 -
Encord Active (
encord.com/active): Encord Active 专注于图像和视频数据的主动机器学习,集成在一个全面的标注平台中。它通过识别和优先处理最有信息量的样本来简化标注流程,从而提高效率并减少人工标注的工作量。这个平台对于大规模计算机视觉项目特别有益。 -
Cleanlab (
cleanlab.ai/): Cleanlab 以其在数据集中检测、量化并纠正标签错误的能力而脱颖而出。这种能力对于主动机器学习至关重要,因为标注数据的质量直接影响模型性能。它提供了一种确保数据完整性的系统方法,这对于训练稳健和可靠的模型至关重要。 -
Voxel51 (
voxel51.com/blog/supercharge-your-annotation-workflow-with-active-learning): 专注于视频和图像数据,Voxel51 提供了一个优先处理标注最有信息量数据的主动机器学习平台。这增强了标注工作流程,使其更加高效和有效。该平台特别擅长处理复杂的大型视频数据集,提供强大的视频分析和机器学习工具。 -
UBIAI (
ubiai.tools/active-learning-2): UBIAI 是一个专注于文本标注并支持主动机器学习的工具。它通过简化标注工作流程来简化训练和部署 NLP 模型的过程。其主动机器学习能力确保最有信息量的文本样本被优先标注,从而在更少的标注示例中提高模型准确性。 -
Snorkel AI (
snorkel.ai): 以其创建、建模和管理训练数据的创新方法而闻名,Snorkel AI 使用一种称为弱监督的技术。这种方法结合了各种标注来源,以减少对大量标注数据集的依赖,补充主动机器学习策略以创建高效的训练数据管道。 -
Deepchecks (
deepchecks.com/importance-of-active-learning-in-machine-learning): Deepchecks 提供了一套在主动机器学习环境中至关重要的验证检查。这些检查确保了数据集和模型的质量和多样性,从而促进了更准确、更稳健的机器学习系统的开发。它是维护数据完整性和模型可靠性在整个机器学习生命周期中的必备工具。 -
LabelBox (
labelbox.com/guides/the-guide-to-getting-started-with-active-learning): 作为一款全面的数据标注平台,LabelBox 在管理整个数据标注流程方面表现出色。它提供了一套创建、管理和迭代标注数据的工具,适用于各种数据类型,如图像、视频和文本。其对主动学习方法的支撑进一步提高了标注过程的效率,使其成为大规模机器学习项目的理想选择。 -
Roboflow (
docs.roboflow.com/api-reference/active-learning): 专为计算机视觉项目设计,Roboflow 简化了图像数据准备的过程。它对于涉及图像识别和目标检测的任务尤其有价值。Roboflow 专注于简化图像数据准备、标注和管理,使其成为计算机视觉领域团队和个人不可或缺的资源。
此扩展列表中的每个工具都为机器学习项目带来了独特的功能,解决了特定挑战。从图像和视频标注到文本处理和数据完整性检查,这些工具提供了通过主动机器学习策略提高项目效率和效果所必需的功能。
摘要
本章全面探讨了各种对主动机器学习至关重要的 Python 库、框架和工具。通过深入了解流行的库如scikit-learn和modAL的复杂性,我们探讨了它们的性能以及如何在主动机器学习场景中有效地应用。此外,本章还通过介绍一系列其他主动机器学习工具,每个工具都有其独特的特性和潜在应用,扩展了您的工具箱。
不论你是刚开始在主动机器学习领域迈出第一步的新手,还是寻求提升技能的经验丰富的程序员,本章旨在为你提供主动机器学习工具和技术的坚实基础。在这里获得的知识不仅仅是理论性的;它是一份实用指南,帮助你掌握增强主动机器学习的 Python 包,并熟悉广泛的主动机器学习工具。这种理解将使你能够为特定的机器学习项目选择并应用最合适的工具,从而提高模型的高效性和有效性。
恭喜!你已经到达了本书的结尾。但请记住,你只是在主动机器学习的世界中开始了你的旅程。随着你在机器学习旅程中不断前进,请记住,主动机器学习的领域正在不断演变。了解新的发展、工具和技术将是保持你在工作中保持前沿方法的关键。本章涵盖的工具和概念为在令人兴奋且动态的主动机器学习领域中进一步探索和创新提供了坚实的基础。


浙公网安备 33010602011771号