TowardsDataScience 2023 博客中文翻译(二百二十七)

原文:TowardsDataScience

协议:CC BY-NC-SA 4.0

MDM作为您数据治理之旅的起点

原文:towardsdatascience.com/mdm-as-the-launching-pad-for-your-data-governance-journey-ebb8ee13f64d?source=collection_archive---------4-----------------------#2023-05-25

企业级数据管理成熟度路线图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Willem Koenders

·

关注 发布于 Towards Data Science · 11 分钟阅读 · 2023 年 5 月 25 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来源:Joshua Sortino 通过 Unsplash

许多组织面临的一个问题是——如何开始数据治理这一复杂的旅程?

尽管数据管理的许多不同方面都可以作为起点,本文提出了将主数据管理(MDM)作为组织建立初步数据治理成熟度的基础。MDM 实施可以帮助你将一组核心数据治理学科整合在一起,将其应用于有限但具有影响力的范围,学习经验并设定标准,然后再在组织的其他部分进行扩展。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

理论上,任何数据管理能力领域都可以成为数据治理之旅的起点。来源:DAMA International,根据 CC-BY-ND 许可。

这一观点将首先通过检查典型 MDM 实施的各个方面来实现,然后将 MDM 实施组件映射到标准数据管理框架中。案例研究将描述一家领先的保险公司如何使用 MDM 启动其整体数据治理之旅。

什么是 MDM,MDM 实施项目包括哪些内容?

主数据管理(“MDM”)是一种能力,确保在组织的系统、应用程序和流程中关键业务实体的数据准确且一致。MDM 对于提供主数据属性(如客户、产品、供应商或原材料数据)的单一、可靠的数据来源至关重要。(有关更详细的定义,请参见 这里。)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

主数据管理的概念概述。

MDM 实施项目通常包括以下几个阶段:

  1. 策略、政策和标准:描述了 MDM 解决方案和过程的预期成果,并明确了如何管理关键主数据的规则和期望。

  2. 发现和分析:评估和理解组织内数据的当前状态,并识别需要管理的主数据实体。

  3. 数据治理框架:定义了数据治理框架,包括数据管理员、数据所有者和数据治理论坛的角色和责任,以及将这些角色分配给“真实”的人员和团队,并动员治理论坛。

  4. 数据建模和映射:创建数据模型,定义主数据实体之间的关系以及描述它们的属性,并将主数据映射到使用它的系统和应用程序。

  5. 数据集成:数据集成是通过创建连接器从源系统中提取数据,将其转换为符合数据模型的格式,并将其加载到 MDM 平台中来构建的。同样,也会从 MDM 解决方案中建立数据流,以供消费过程和用例使用。

  6. 数据质量管理:定义和执行数据质量规则、计算指标、建立报告,并确定解决数据质量问题的过程。这还可能包括实体解析和生存分析。

  7. 培训和变更管理:为利益相关者提供培训,以确保他们了解 MDM 平台以及他们在数据治理框架中的角色和责任。建立变更管理过程,以管理对平台或框架的任何变更。

  8. 监控和维护:在此阶段,建立持续改进的过程,包括数据质量监控和报告、数据治理审计,以及识别改进机会。可以遵循问题管理过程来记录和解决观察到的问题。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

MDM 解决方案组件的示意图。

映射到标准数据管理框架能力

当然,实施 MDM 解决方案并使围绕它的过程实现操作化将提升参考和主数据的维度成熟度。然而,在上述描述的典型 MDM 实施程序的 8 个步骤中,也与更广泛的数据管理框架有关联。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

实施 MDM 解决方案当然直接提升参考和主数据管理维度的成熟度。然而,如果从战略上使用,它还会提高其他数据管理能力的成熟度。

让我们明确描述这些连接,以准确识别如何在这些能力领域建立成熟度。

数据战略

  • 如果 MDM 解决方案没有配套的更广泛战略来解释为什么掌握某些关键数据至关重要,它将无法驱动价值。如果已有数据战略,可以用来加强现有战略;如果没有,它实际上可以作为组织的首个明确的数据战略。

  • 对于特定平台的实现,应该在程序开始前确定用例和消费过程,以确保将相关要求纳入其中。这可以将 MDM 解决方案转变为真正的数据产品,并使数据办公室能够开始管理数据产品组合和跟踪数据驱动的用例(以及价值创造!)。

数据治理

  • 在 MDM 解决方案及其掌握的数据周围,建立基础治理,包括通过定义一套政策和标准来概述 MDM 的一般期望,以及具体的角色和责任。这些可以增强现有的数据政策和标准,或者如果还不存在,形成第一版。

  • 数据或领域所有者被指定为对主数据负责的责任方。可以确定数据管理员,他们被赋予了照看数据的责任(由数据所有者委托)。这包括确保数据适用性的责任,并可以使得创建更广泛的数据治理 RACI 矩阵成为可能,该矩阵可以在后续扩展到非 MDM 领域。因此,可以引入和定义主数据的数据治理角色,培养数据所有权和问责文化,然后将其在组织中推广,以确保数据治理实践的一致性。

  • 定义了用于跟踪平台健康状况和使用情况的指标,并跟踪风险。这些指标可以形成第一组数据治理指标,之后可以进行扩展。如果目前还没有,可以召集一个论坛来监控这些指标并解决问题。该论坛可以扩展或为未来涵盖其他数据治理主题的新论坛提供灵感,从而推动治理实践中的关键数据成熟度。

架构

  • 对于 MDM 平台本身,创建了解决方案和数据架构。这可以通过一套明确识别的架构标准来指导。可以建立最佳实践,即任何解决方案架构应受到适用数据标准的指导。实际的标准本身也可用于其他未来的转型倡议。

  • 只有当平台成为组织交易中的可信来源时,MDM 才会创造价值。这不应是可选的——如果存在主数据,那么其消费对任何使用该数据的人来说应该是强制性的。这有助于建立更广泛的参考数据架构,其中的指导方针、原则、最佳实践和实施模式可以推动组织内部架构设计的稳健性和一致性,以及供应商和技术的合理化。

  • 对于 MDM 解决方案,记录了数据从哪些来源获取,以及主数据如何提供给下游消费。记录的数据流和谱系可以作为捕捉更广泛组织数据景观的起点。

数据质量

  • MDM 的一个关键组成部分是测量和管理主数据的质量。如果没有受控(且量化的)质量,就无法建立信任,缺乏信任将导致采用困难。围绕业务规则识别、创建可执行的数据质量规则和编制数据质量指标的过程在任何未来的数据质量工作中都非常可重复使用。

  • 如果使用了特定工具来测量数据质量,那么它可以在后续进行额外的扩展。同样,总结主数据数据质量的仪表板也可以很容易地扩展以包括非 MDM 数据的数据质量指标。

  • 理想情况下,“设计中质量”这一概念应嵌入到 MDM 解决方案的架构中。即,数据捕捉、集成和转换的处理方式要尽可能保证数据质量。例如,对于国家字段,只允许出现相应 ISO 标准中的选项。这建立了一个模式、最佳实践和肌肉记忆,这对任何未来的现代化和转型努力同样适用。

  • 创建了一个问题管理流程,以确保解决主数据中的问题。识别、跟踪和解决数据问题的相应过程可以扩展到其他数据领域。

建模与设计及元数据

  • 如上所述,任何 MDM 解决方案都需要一个数据模型,以定义主数据实体之间的关系及其描述属性,并将主数据映射到使用它的系统和应用程序。为主数据(例如客户、产品)创建的概念模型和逻辑模型(以及底层元模型)可以扩展到其他领域(例如财务、人力资源、供应链、交易)。

  • 作为 MDM 的一部分,可以采用一种技术来设计和捕捉数据模型和元数据。这项技术以及使用它的过程,可以用于后续解决方案和领域的数据模型。

  • 捕捉的数据模型和元数据越多,未来范围的增量工作就越少。例如,如果需要描述数据元素并捕捉元数据以用于客户入职过程,如果关键客户数据和相关业务需求已经在概念和逻辑层面上定义过,那么所需的时间会少得多。

数据存储与操作

  • 在 MDM(主数据管理)程序中,考虑主数据的存储和操作需求至关重要。这一需求推动了数据存储最佳实践的实施以及数据操作标准的制定。作为这一部分,组织需要设计和实施一种最佳的数据存储策略,考虑因素包括数据量、速度、种类以及对可扩展性和弹性的需求。

  • 为 MDM 开发的操作流程,包括数据备份、归档和恢复流程,可以作为其他数据管理领域类似流程的基础,从而为数据存储和操作的成熟度建设铺平道路。

集成与互操作性

  • MDM 本质上需要将来自不同来源的数据整合在一起,从而促进了集成和互操作性的坚实基础。为主数据在不同系统中的合并、去重和同步设置的程序可以作为未来数据集成计划的蓝图。

  • 在 MDM 实施过程中建立数据标准、创建通用数据模型,并执行一致的数据格式,可以为系统之间的互操作性奠定基础。作为 MDM 过程的一部分建立的集成模式和实践可以在整个组织中重复使用,有助于建立成熟的集成和互操作性实践。

  • 具体来说,有机会定义一套互操作性标准——例如,定义使用通用数据模型的数据并采用一组选定的 API 和 ETL 技术——这些标准可以在整个组织中更广泛地采用。

数据仓库与商业智能(BI)

  • 实施良好的 MDM 程序可以确保输入数据仓库的数据是干净、一致和可靠的。它提供了进行有效报告和分析所需的唯一真实来源,从而为稳固的 BI 战略奠定基础。

  • 在 MDM 过程中建立的数据质量规则、指标和流程可以用来维护数据仓库的完整性。此外,主数据的强大元数据管理可以推动高效的数据血缘追踪、影响分析以及对 BI 目的的数据理解。

数据安全

  • 在实施 MDM 程序时,组织会建立并执行具体的数据访问、修改和删除安全政策。这些政策在组织内统一应用,使得对谁可以访问或操作主数据进行严格控制。

  • 这为建立更全面的数据安全框架提供了机会。在设置解决方案的过程中,组织可以定义安全角色和职责,并制定加密、匿名化和伪匿名化敏感数据的协议,从而为更广泛的数据安全成熟度奠定初步基础。

案例研究:一家保险公司在 MDM 方面的历程

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 Vlad Deep 提供,通过 Unsplash 获取。

作为 MDM 如何推动更广泛成熟度的实际说明,我们来看一个涉及领先保险公司的案例研究。我有机会与这家公司合作,这家公司在其主要市场中市场份额排名前三。该公司启动了一个项目,旨在为其客户数据实施 MDM 解决方案。

在这个倡议中,我的角色是确保技术解决方案不仅被实施,而且在企业内真正实现。这包括建立正确的流程、记录这些流程、创建强大的数据模型、开发数据质量解决方案和仪表盘,以及一个元数据模型和基本的元数据管理流程。我们还识别并建立了关键角色,如数据拥有者、数据管理员和数据质量分析师。

在实际应用方面,这里的主数据主要针对公司的市场部门,使用案例包括客户细分和营销活动管理。在实施 MDM 之前,公司由于难以协调来自各种来源的客户数据,甚至无法实现基本的 360 度客户视图。

实施一年后,成功的业务影响已经显而易见。通过整合和可靠的客户数据视图,营销团队能够判断一个与某个业务线有互动的客户是否也拥有其他业务线的产品。这促成了更深层次的数据驱动客户细分,取代了之前基于规则的分析。新获取的数据使得预测建模成为可能,从而确定“下一步最佳行动”,并使营销活动能够在更具个性化的层面上启动。

一个意外但重要的好处是联系数据(如电子邮件地址、电话号码和实际地址)的管理得到改善。通过将来自各种输入渠道(如呼叫中心、实体分支机构或客户电子邮件)的更新整合到 MDM 解决方案中,所有使用这些信息的人员都能获取到最新的详细信息。因此,通过书面营销材料或电话联系到目标受众的成功率提高了超过 20%。根据团队的估计,他们在营销活动上的投资回报率提高了多达 50%。

结论

MDM 可以作为组织数据治理之旅的强大起点。它提供了一种全面的方法来建立一个可靠的关键业务实体信息源,构建一个强大的数据治理框架,并推动各项数据管理能力的成熟。通过将特定领域的 MDM 作为一个可管理的范围,组织可以引入关键数据治理概念,在受控环境中测试这些概念,并逐步扩展到整个组织。

参考文献和进一步阅读建议

除非另有说明,所有图片均由作者提供。

平均绝对对数误差(MALE):一种更好的“相对”性能指标

原文:towardsdatascience.com/mean-absolute-log-error-male-a-better-relative-performance-metric-a8fd17bc5f75?source=collection_archive---------3-----------------------#2023-01-18

介绍“相对”性能指标的 MAE 和 MSE

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Christopher McDonald

·

关注 发表在 Towards Data Science ·11 分钟阅读·2023 年 1 月 18 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来源:William WarbyUnsplash

在预测领域,以及更广泛的机器学习和统计学领域中,性能指标扮演着至关重要的角色。

它们在模型拟合、超参数调优和模型选择过程中被使用,以找到最佳的模型;同时也用于理解和解释模型如何在绝对术语上预测未来。

在这篇文章中,我的目的是说服你,对于许多预测¹问题,你应该使用均值绝对对数误差(MALE)或紧密相关的均方根对数误差(RMSLE)来衡量模型性能。

就像 MAE 和 RMSE 使用预测值与真实值之间的“原始”距离一样,MALE 和 RMSLE 使用“相对”(对数)距离;你可以将 MALE 和 RMSLE 视为“相对”指标的 MAE 和 RMSE。

事实上,我有信心可以说服你,这些指标不仅是最佳选择,而且在许多情况下是显而易见的选择。

在解释原因之前,让我们快速回顾一下性能指标解决了什么问题,以及现有指标的不足之处。

问题

错误度量和性能指标

首先,让我们区分两个密切相关的概念:错误度量和性能指标。

错误度量(或称错误)告诉你预测值f与观测值y的“距离”有多远。例如,“原始”错误 RE = f — y 和百分比误差 PE = (f — y) / y。

相比之下,性能指标(或称指标)使用错误度量来告诉你某个模型(或一组预测)的整体表现如何。一个例子是 MSE,它计算数据集中所有点的“原始”误差的平方均值:

它们有什么用处?

错误度量和性能指标在模型拟合过程中作为模型损失函数的一部分使用;在模型调整过程中,用于选择合适的超参数;以及在模型选择过程中,用于选择最佳的模型类型。它们在决定最终模型时扮演重要角色,因此确保它们能捕捉到你关心的内容非常重要。

当试图理解和解释模型的表现时,它们也会被使用:例如在“我们可以以平均 15%的误差预测下一季度的销售额”这样的陈述中。因此,它们也需要具备可解释性。

到目前为止,都是显而易见的(希望如此)。这些概念稍后会派上用场。

严格为正的数据和相对误差

正如我将在另一篇文章中讨论的(敬请期待!),不同的预测指标在不同的情况下是合适的。

例如,如果你关注的是百分比误差(并且你的数据严格为正),那么“相对”指标如 MAPE 或 sMAPE 通常被推荐;如果你关注的是以实际单位(例如苹果数量)衡量的误差,或者你的数据可以为零或负数,那么“原始”指标如 MAE 或 MSE 更为合适。

如果你想比较或聚合时间序列中的性能指标,那么你可能需要使用标准化指标[1]。

在这篇文章中,我将专注于某种特定问题的指标。具体来说,问题是:

  1. 数据是严格为正的:它们不取零或负值。

  2. 预测者(即你!)关心的是相对误差而非原始误差²。

虽然许多预测问题属于这种类型,但并非所有问题都如此——选择适合你问题的指标非常重要。

当前解决方案

预测者使用什么误差?

Gneiting [2] 发现,到 2000 年代中期,平均绝对百分比误差(MAPE)是商业和组织中最广泛使用的预测准确性度量。

查看流行的统计预测包,例如 R 中的 “fable” 包,或 Python 中的 “gluonts” 包,表明 MAPE(及其相关的 sMAPE)仍然是实际预测应用中使用的主要“相对”性能指标。

MAPE 之所以受欢迎,是因为它能够处理尺度随时间变化的数据;它在时间序列之间具有相对的可比性;对异常值的处理相对较好;并且具有简单的解释。

然而,MAPE 和 sMAPE 存在问题——让我们看看它们是什么。

MAPE 的问题

MAPE 的问题是什么?

正如其名称所示,MAPE 使用 百分比误差 作为其误差度量:

这种误差度量以惩罚高估比低估更著名。

作为一个极端的例子,如果你高估观察值 10 倍,你会得到一个绝对百分比误差(APE = |PE|)为 9;而如果你低估它 10 倍,你得到的 APE 仅为 0.9——仅为误差的 1/10!

在更现实的情况下,这是一个较小的问题(但仍然是一个问题),即你的预测更接近实际情况。

另一种看待 PE 问题的方法是,低估的误差被压缩到 -1 到 0 的范围内(即 -100% 到 0%),而高估的误差可以取任何从 0 到无穷大的值。

sMAPE 的问题

解决这个低估问题的提议是对称 MAPE(sMAPE),它使用“对称百分比误差”作为误差度量:

sPE 压缩 高估的误差,使其与低估的误差处于相同的尺度;这意味着低估和高估会受到同样严格的惩罚。

但虽然 sMAPE 成功解决了“低估”问题,但它也带来了另外两个问题³:

  1. 这个指标现在更难以解释。

  2. 由于 sPE 错误是有界的,它不会告诉你数据中的极端异常值。(这可以是一个特性或缺陷,取决于你的观点。)

(次)最优模型

最后,让我们稍微考虑一下 MAPE 和 sMAPE 优化的是什么

作为提醒,当你使用 MAE 或 MSE 优化模型时,你的模型最终会预测分布的中位数或均值。(前提是你有足够的数据和足够好的模型。)

相反,当你为 MAPE 或 sMAPE 进行优化时,你的模型最终预测的……并没有什么特别的东西。

也就是说,模型最终预测的量将取决于目标 y 的分布,但它通常不会是分布的均值或中位数。

这种行为并不特别好。我们能做得更好吗?

对数误差

更好的误差度量…

我们已经看到,MAPE 和 sMAPE 的问题来自于它们的误差度量——百分比误差(PE)和对称百分比误差(sPE)。

我们能找到一种更好的方法来测量预测 f 和观测值 y 之间的相对误差吗?(也许类似于 MAE 和 MSE 使用的“原始”误差 fy?)

我的解决方案⁵是对数误差(LE):

简而言之,它是预测值和观测值对数之间的差异⁶——或者等效地,预测值和观测值之间比例的对数⁷。它与百分比误差紧密相关:LE = log(1 + PE)。

这种误差度量具有许多优良属性:

  • 如果且仅如果预测完全正确(f = y),它才为零。

  • 低估和高估受到同等严厉的惩罚:例如,低估 y 2 倍的绝对对数误差(ALE = |LE|)与高估 y 2 倍的误差是一样的。

  • 错误相加⁸:在数学中,LE(x, y) + LE(y, z) = LE(x, z)。这使得 LE 不同于 PE 和 sPE,使其看起来像是 MSE 和 MAE 使用的“原始”误差度量。

一种思考 LE 的方式是,它通过使用对数变换将误差低估拉伸,并将误差高估压缩到完整的实数线上(-∞,∞)。

另一种思考它的方式是作为对数尺度上的原始误差——即只是预测值和观测值之间在数据对数上的原始距离。

正如我稍后将解释的,它与 MAE 和 MSE 使用的“原始”误差度量非常相似。

…导致更好的指标

现在我们有了一个更好的相对误差度量,让我们回到我们真正感兴趣的内容:性能指标。

对于 MAPE 或 sMAPE,为了从我们的误差度量中获得一个指标,我们取其绝对值在所有数据点上的均值:

结果是均方绝对对数误差度量,简称“MALE”。

另外,我们可以使用 LE 的平方来得到均方根对数误差(RMSLE):

与 MALE 相比,这一度量对离群值更为敏感。

这些指标相比其他“相对”指标具有一些优势,我将在下面讨论。

它们估计的是什么

当你优化 MALE 时,你会得到预测你分布中位数的模型。

(或者更正式一点:在 MALE 损失下,贝叶斯估计器是中位数。)

当你使用“平方误差”版本(RMSLE)时,你会得到预测数据几何均值的模型。

这与 MAPE 和 sMAPE 相对,它们通常存在偏差。

可解释性

为了将 MALE 度量转换成你的老板能理解的东西,你可以通过取指数来将其转换回相对尺度,即:

这给出了 (几何) 平均相对误差。例如,EMALE 为 1.2 意味着你期望平均上在任一方向上错误因子为 1.2。(向你的老板解释为 20% 平均百分比误差。)

这是对 sMAPE 的改进,sMAPE 没有直接解释,而 MAPE 尽管技术上简单,但可能有点误导⁹。

你可以对 RMSLE 使用相同的技巧:

像 RMSE 一样,这不能直接解释,但它给出了你误差在相对术语中的大小感。

实证证据

尽管关于哪个指标在“实际环境”中表现更好的实证证据较弱,但现有的证据略微表明 MALE 和 RMSLE 至少与 sMAPE 在实际中表现相当。

例如,Tofallis [3] 显示 RMSLE 指标

  1. 在几个示例数据集上,比 MAPE 拟合效果更好。(这并不意外。)

  2. 在使用模拟数据的模型选择任务中表现优于 MAPE 和 sMAPE。

Koutsandreas 等人 [4] 没有发现不同指标(包括 MALE 但不包括 RMSLE)在模型选择中的性能差异。但他们发现的小差异支持了 MALE 指标倾向于选择准确模型的说法。

简单性

MALE 和 RMSLE 易于理解、记忆和编码——甚至比 MAPE 或 sMAPE 更简单。例如,在 Python 中:

male = mean(abs(log(f / y)))
rmsle = sqrt(mean(log(f / y)**2))

MALE 与其他指标的比较

MAE 和 MSE

如果你一直在关注,你可能已经注意到 MAE / MSE 和 MALE / RMSLE 之间的一些相似之处。

实际上,这两组指标之间有密切的联系:具体来说,优化 MALE(或 RMSLE)等同于在数据的对数上优化 MAE(或 MSE)。

也许这很明显,但让我们明确看一下 MAE:

实际上,你可以将 MAE 和 MALE 视为同一家族的指标:唯一的区别是 MAE 使用预测值和观察值之间的原始距离,而 MALE 使用相对(对数)距离。

这意味着什么?

一个含义是,对于在训练过程中使用 MSE(或 MAE)作为损失函数的模型,你可以通过在训练之前对数据取对数来优化 RMSLE(或 MALE)¹⁰。

(只要记得之后转换回原始尺度!)

MAPE 和 sMAPE

绝对百分比误差(APE)、对称绝对百分比误差(sAPE)和绝对对数误差(ALE)在预测值接近真实值时是相似的,如下图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

绝对百分比误差(APE)、对称绝对百分比误差(sAPE)和绝对对数误差(ALE)的比较,观察值为 y = 1。图片来源于作者。

所以实际上,只要你的误差足够小(例如,少于 10%),使用 MALE、sMAPE 还是 MAPE 可能没有太大区别。

ALE 在对异常值的敏感性上介于 APE 和 sAPE 之间。例如,与错估 +10 倍相比,错估 +100 倍会使你的原始 sAPE 增加 1.2 倍,原始 ALE 增加 2 倍,原始 APE 增加 9 倍。

缩放指标

由于 MALE 和 RMSLE 是相对单位(而不是实际单位),它们可以用于比较模型在时间序列中的表现,或在不同时间序列之间汇总性能指标。(就像其他相对指标一样。)

当噪声的水平(相对而言)在不同时间序列之间相似时,这种方法效果很好。但如果,例如,你的一些序列非常嘈杂/难以预测,而其他序列则不那么困难怎么办?

在这种情况下,你可以通过基准方法的误差(例如,天真的或季节性天真的方法)来规范化你的误差,以将它们放在相同的尺度上 [1]。

例如,给定时间t = 1, 2, …, T 的训练数据,时间 T + h 的预测的 scaled 对数误差(SLE)为

均值绝对缩放对数误差为

总结

在这篇文章中,我论证了对于某些预测问题,你应该使用对数误差(LE)来衡量预测误差,而不是“原始”或百分比误差。这意味着使用基于 LE 的指标来衡量模型性能:具体来说是均值绝对对数误差(MALE)和均方根对数误差(RMSLE)。

这些指标仅应在数据严格为正且你对相对(百分比)度量的准确性感兴趣时使用。在这种情况下,它们有以下好处:

  1. 它们具有明确且简单的解释。

  2. 优化这些指标会产生中位数(MALE)或几何平均数(RMSLE)的估计值。

  3. 它们可以在不同时间序列之间轻松比较和汇总。

  4. 它们避免了均值绝对百分比误差(MAPE)和对称均值绝对百分比误差(sMAPE)的著名问题。

MALE 和 RMSLE 可以被视为“相对”性能指标的 MAE 和 RMSE。我认为,如果你有兴趣以相对方式衡量误差,它们应该是默认选择。

我说服你了吗?为什么/为什么没有?在评论中告诉我。

参考文献

[1] R. Hyndman 和 A. Koehler, 预测准确性测量的另一种看法 (2006), 国际预测学期刊 22(4)。

[2] T. Gneiting, 制作和评估点预测 (2011), 美国统计协会期刊 106(494)。

[3] C. Tofallis, 一种更好的相对预测准确性测量方法用于模型选择和模型估计 (2015), 运营研究学会期刊 66(8)。

[4] D. Koutsandreas, S. Evangelos, P. Fotios 和 A. Vassilios, 关于预测准确性度量的选择(2022),《运筹学会期刊》73(5)。

脚注

  1. 我主要关注预测领域——因为这里似乎是“相对”误差度量目前最常用的地方——但相同的论点适用于其他机器学习领域。

  2. 相对误差仅在讨论严格正的数据时才有意义。

  3. 值得注意的是,通常这些问题并不太严重,sMAPE 已经在实际应用中成功使用。

  4. 更准确地说,这对于这个损失函数来说是最佳预测器(“贝叶斯估计量”)。

  5. 这个误差度量已被 Tofallis [3] 和 其他人 讨论;我认为这个想法足够明显,很多人一定已经想到并使用了它。

  6. 对数中可以使用任何底数;在这里我假设使用的是底数 e,即自然对数。

  7. 因此,这也被称为“对数准确性比”。我更喜欢称之为“对数误差”,因为这样更简洁,并且明确它是一个误差度量。

  8. 这个属性并不严格用于误差测量,但它是一个很好的特性。

  9. 特别是,+20% 的百分比误差意味着你的误差因子是 1.2,而 -20% 的百分比误差意味着你的误差因子是 1.25(1 / 0.8)。这种不对称性容易造成混淆。

  10. 你可能会想,如果使用这些新度量与在数据对数上使用 MAE / RMSE 相当,那么定义和命名这些新度量的意义何在。在我看来,明确地定义和命名这些度量可以帮助你更清楚地理解在处理对数尺度数据时优化的内容,并且更易于沟通。(说“我优化了 / 评估了 MALE”比“我优化了 / 评估了数据对数上的 MAE”更简洁且不容易混淆。)

平均精确度@K(MAP@K)清晰解释

原文:towardsdatascience.com/mean-average-precision-at-k-map-k-clearly-explained-538d8e032d2

对于推荐或排名问题,最受欢迎的评估指标逐步解释

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Konstantin Rink

·发布于Towards Data Science ·阅读时长 7 分钟·2023 年 1 月 18 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由Joshua Burdick提供,来源于Unsplash

平均精确度@K(MAP@K)是推荐系统和其他排名相关分类任务中最常用的评估指标之一。由于该指标是不同误差指标或层的组合,因此初次查看时可能不易理解。

本文将逐步解释 MAP@K 及其组成部分。文章末尾还将提供代码片段,说明如何计算该指标。但在深入了解每个部分之前,我们首先谈谈为什么

为什么使用 MAP@K?

MAP@K 是一种误差度量指标,当你的推荐项的序列排名在任务中扮演重要角色或是目标时,可以使用该指标。通过使用它,你可以获得以下问题的答案:

  • 我生成或预测的推荐是否相关

  • 最相关的推荐是否在前几位

使以下步骤更易于理解

既然你知道了“为什么”,让我们来谈谈怎么做。接下来的章节将以“洋葱”风格逐步解释,从内部(从精确度 P 开始)到外部(MAP@K),MAP@K 的结构。

为了使步骤及其组成更易理解,我们以以下示例进行操作:我们希望评估我们的推荐系统,该系统在访问产品详细信息页面时向潜在客户推荐六个项目(见图 1)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 1. 推荐示例(作者提供的图片)。

精确度(P)

你可能已经在书籍或文章中听说过精度,当你学习分类模型的误差指标时。精度可以看作是质量的衡量标准。高精度意味着我们的模型返回的结果或推荐更相关,而不是无关的

精度可以定义为所有推荐项目(相关 + 无关项目)相关项目的比例

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2. 精度公式(图片由作者提供)。

以下示例(图 3)显示了 6 个推荐项目。在这 6 个推荐中,有 2 个是相关的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3. 精度示例(图片由作者提供)。

将这些值代入我们的公式(图 1),我们得到一个0.33的精度( **2** 个相关项目 / (**2** 个相关 **+** **4** 个无关项目) )。

Precision@K(P@K)

精度指标(图 2)本身不考虑相关项目出现的排名或顺序。是时候将排名纳入我们的精度公式中。Precision**@K可以定义为前K**个推荐项中相关项目的比例(图 4)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4. Precision@K 公式(图片由作者提供)。

下图(图 5)展示了我们上述示例(图 3)中的排名场景。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5. Precision@K 示例(图片由作者提供)。

Precision@K 列显示了每个排名(1 到 6)的 Precision@K 值。K 代表我们考虑的排名数量(1、2、…、6)。

Precision@1

假设我们只考虑第一个排名K=1),那么我们将有0 个相关项目除以1(总项目),这导致 Precision@1 为0

Precision@3

假设我们考虑前三名排名(K=3),那么在前 3 个推荐中我们将有 1 个相关项目和 2 个无关项目。如果我们将这些数字代入我们的公式(图 3),我们将得到0.33**1** 个相关项目 / (**1** 个相关 + **2** 个无关项目) )。

Precision@5

最后但同样重要的是,让我们考虑前五名排名(K=5)。我们将有前 5 个推荐中 2 个相关和 3 个无关的项目。如果我们重新计算,我们将得到一个0.4的值。

(**2** 个相关项目 / (**2** 个相关 + **3** 个无关项目)).

平均精度@K(AP@K)

正如我们所见,精度和 Precision@K 都非常简单。下一步有一点复杂性。

平均精度@K 或 AP@K 是 Precision@K 的总和,其中第 kₜₕ 排名的项目是相关的rel(k)),除以前 K 个推荐项中的相关项目总数(r)(图 6)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6. AP@K 公式(图片由作者提供)。

迷惑了?让我们看看以下关于 AP@6 的示例(图 7)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7. AP@K 示例 1(图片由作者提供)。

相关项目的总数(r)在这个示例中为2(在排名 2 和 4)。因此,我们可以将 2 放在分数 1/r 中。

看第一个排名 1。Precision@1 为 0,且该项不相关(灰色)。因此,我们将 Precision@1 的值乘以 0,得到 0 * 0

然而,在第 2 个排名中,我们有一个 Precision@2 值为 0.5 和一个在第 2 个排名的相关项。这导致 0.5 * 1

在第 3 个排名中,我们再次有一个无关项,Precision@3 为 0.33。结果为 0.33 * 0

我们会逐个排名进行处理。如果排名 k 包含相关项,我们将其 Precision@k 乘以 1。如果无关,我们将其乘以 0,这意味着它不会对我们的总和产生影响。

对于这个示例,最终结果将是AP@60.5

在我们进入最后一步之前,你还记得我们在开始时提到 MAP@K 可以回答的问题吗:

最相关的推荐是否在前几个排名中?

该度量的一个重要特性是它惩罚低排名中的相关项。为了让你更好地理解,让我们看看以下示例(图 8)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8. 不同排名下相关项目的示例。最佳情况(左),最差情况(右)。排名越高越好(图片由作者提供)。

与最初的示例(图 7)相比,相关项目的数量没有变化。但变化的是它们被放置的排名。AP@K(因此 MAP@K)会惩罚那些将相关项目放在较低排名的推荐或模型。

平均精度均值@K(MAP@K)

之前的步骤和示例都是基于评估单个查询或一个访客在浏览产品 X 的产品详情页时收到的单个推荐列表。但我们有不止一个访客……

平均精度均值@K 或 MAP@K 考虑到了这一点。它平均了对M 用户显示的推荐的 AP@K

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9. MAP@K 公式(图片由作者提供)。

请注意:为了简化起见,我在这个示例中选择了“用户”。但是,根据你的情况,M 也可以是例如搜索查询。

为了更好地理解 MAP@K 是如何计算的,下面的示例(图 10)可以提供帮助。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 10. MAP@K 示例(图片由作者提供)。

基于 3 个不同的用户(或查询),MAP@6 为0.59

编码

现在我们已经熟悉了理论,让我们开始编码。在接下来的示例中,我们将处理两个包含 product_ids 的列表 actualspredicted

目标是检查我们的实际值是否出现在预测列表中,以及如果出现,它们出现在什么排名/位置。这就是为什么在 actuals 列表中项目的顺序无关紧要,而在 predicted 列表中却很重要。

AP@K

以下列表反映了我们之前使用的示例(图 11)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 11. 从开始回顾的示例(图片由作者提供)。

actuals = ['p_a', 'p_b']
predicted = ['p_d', 'p_a', 'p_c', 'p_b', 'p_e', 'p_f']

如果我们将实际值与预测值进行比较,那么我们可以看到 p_b 出现在第 2 位,p_d 出现在第 4 位。

def apk(y_true, y_pred, k_max=0):

  # Check if all elements in lists are unique
  if len(set(y_true)) != len(y_true):
    raise ValueError("Values in y_true are not unique")

  if len(set(y_pred)) != len(y_pred):
    raise ValueError("Values in y_pred are not unique")

  if k_max != 0:
    y_pred = y_pred[:k_max]

  correct_predictions = 0
  running_sum = 0

  for i, yp_item in enumerate(y_pred):

    k = i+1 # our rank starts at 1

    if yp_item in y_true:
      correct_predictions += 1
      running_sum += correct_predictions/k

  return running_sum/len(y_true)

如果我们将我们的两个列表放入我们的函数中

apk(actuals, predicted)

然后我们得到像我们手动示例中那样的0.5(图 7)。

MAP@K

由于 MAP@K 对多个查询进行平均,我们将我们的列表调整为以下结构:

actual = ['p_a', 'p_b']

predic = [
    ['p_a', 'p_b', 'p_c', 'p_d', 'p_e', 'p_f'],
    ['p_c', 'p_d', 'p_e', 'p_f', 'p_a', 'p_b'],
    ['p_d', 'p_a', 'p_c', 'p_b', 'p_e', 'p_f'],
]

我们的 actuals 保持不变,但我们的 predicted 列表现在包含了多个列表(每个查询一个)。predicted 列表对应于图 10 中的列表。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 12. 从图 10 中回顾的示例(图片由作者提供)。

下面的代码显示了 MAP@K 的计算:

import numpy as np
from itertools import product

def mapk(actuals, predicted, k=0):
  return np.mean([apk(a,p,k) for a,p in product([actual], predicted)])

如果我们将我们的列表放入这个函数中

mapk(actuals, predicted)

然后我们得到0.59

结论

在评估推荐系统或排名模型时,MAP@K 是一个很好的选择。它不仅提供了推荐是否相关的洞察,还考虑了正确预测的排名。

由于其排名考虑因素,它比其他标准误差指标如 F1 分数更难以理解。但我希望这篇文章能为你提供关于这个误差指标如何计算和实施的全面解释。

如果你想测量你的推荐是否相关以及它们有多相关,可以查看归一化折扣累积增益(NDCG)。

来源

信息检索导论 — 评估web.stanford.edu/class/cs276/handouts/EvaluationNew-handout-1-per.pdf

有意义的实验:5 个有影响力的数据项目,帮助打造更好的产品

原文:towardsdatascience.com/meaningful-experimentation-5-impactful-data-projects-to-help-build-better-products-1fb84afdfb2?source=collection_archive---------19-----------------------#2023-01-06

实际数据领导者系列的第二部分,介绍如何与各部门及其所有奇特特性进行最佳合作

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 shane murray

·

关注 发表在 Towards Data Science ·14 分钟阅读·2023 年 1 月 6 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 Shane Murray 提供。

理解并与每个业务领域独特的激励机制和工作流程对齐,这才是让数据团队不仅高效而且卓越的关键。

本系列的第一部分讨论了大家最喜欢的电子表格强用户——财务团队。本文将探讨数据团队如何更好地识别共同原因并避免与产品团队的摩擦点。

虽然这些互动根据交付产品的性质会有所不同,但这篇文章适用于主要提供数字化、面向消费者产品的广泛组织。通常在这些组织中,跨职能的产品团队(产品经理、设计师、工程师等)共同拥有从头到尾的消费者体验,并各自拥有该体验的某些方面,如功能或产品。

让我们先看看一些有影响力的项目示例,其中数据和产品团队可以找到共享的成功点,然后再深入探讨推动有意义协作的技巧。

赢得你产品团队的项目

产品团队可能负责从电子邮件到应用程序的任何东西。他们可以专注于一个新功能,也可以广泛评估全新的货币化策略。然而,有一些共性可以作为产品分析最佳实践的参考。

这里是我看到的推动结果的五个最佳实践:

1. 数据驱动的产品策略

产品团队在产品生命周期的所有阶段都需要以数据为依据,从创意生成和产品定义,到验证原型和构建商业成功的产品。

多年来我遇到的一个不幸的情况是,有些产品团队希望数据来决定他们的策略,可能会问他们的数据合作伙伴,“我们接下来应该构建什么功能?”

这可以理解——开发新功能是一个资源密集型的过程,风险很高。这给产品经理带来了做出正确决策的压力,这通常会产生一定程度的确定性需求,或者至少是可以辩护的理由。但分析师只有过去实验和决策的数据,而没有可能允许他们推断未来决策的反事实数据。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 JUVART 提供,来源于 Shutterstock

当有明确的产品假设需要测试或探索,以及一组可以根据明确定义的结果或成功标准进行评估的选项时,分析团队会做出最佳的工作。

例如,“‘发现’标签会比‘最近播放’标签在日常互动中表现更好”是一个可以通过历史数据(以及一些关于标签使用的假设)或提议的实验来探索的假设。另一方面,如果问题是,“我们应该构建一个发现标签还是其他什么?”你可能需要回到用户研究。

那么这使我们处于何种境地呢?

数据团队应该主导(~年度)建模工作,探索与增长(即客户获取和留存)相关的最重要的产品杠杆。早期的工作通常会附带“这是相关性,而非因果性”的警告,因为对产品机制的因果理解将随着时间和多次迭代而建立。

这些模型可以作为投资产品的有价值的指引,但绝不应过于规定性。那个迫使你抛弃当前模型的大胆想法,可能比你从当前产品杠杆对业务的影响中推导出的想法更具影响力。

我发现这些工作会产生对更精细模型的需求,这些模型深入研究小型产品(如新闻通讯、应用)或客户旅程不同阶段中的产品杠杆的重要性。

此外,数据团队可以利用对业务的更深入、整体理解来定义“北极星指标”或“重要指标”套件,这些指标可以作为产品团队在构建产品战略和路线图时的指南针。

2. 基础知识:跟踪、报告和发布后评估

产品分析中最基础的实践是指标的定义、跟踪和报告,这使得产品或功能在发布后能够可靠地进行评估。但数据往往在产品发布中并不被重视。

事实上,数据往往是发布前最后考虑的事物,但发布后首先被询问的内容。

数据领导者和产品领导者有责任使优质数据成为产品发布的核心。我合作过的最佳产品领导者的态度是,“如果我们无法测量它,那么我们就不能发布它。”

在发布前,讨论通常从数据团队询问哪些指标重要以及哪些用户细分有意义开始。产品团队的回答几乎总是“所有和每一个”。

最佳的产品分析团队既像人类学家,又像工程师。他们首先研究希望在接触新功能的用户群体中观察的行为,定义成功的明确标准,然后将这些标准转化为可实施的结果指标和用户细分。前期做好这些工作会在后期节省大量时间,当高层询问发布是否成功时。

3. 实验

实验是产品经理的生命线。随着大多数数字产品开发团队以敏捷方式进行交付,进行实验的能力现在通常被认为是“基本要求”。

但做得的产品实验远非“基本要求”。这不仅仅是将电子邮件营销活动拆分为对照组和测试组,调整文案,然后测量响应率那么简单。

  • 风险通常更高 — 例如,用户体验的变化可能需要多天的设计、构建和部署。

  • 存在多个集成点——例如,你可能需要通过 SDK 或 CDN 部署你的实验分配库,此外还要提供通过浏览器中的 JavaScript 进行集成。

  • 结果不容易立即知晓——例如,一个推荐系统可能需要根据它对用户参与度和留存率的影响来衡量,而不是其点击率,这可能需要几周或几个月的时间。

  • 权衡可能更复杂——例如,主页实验可能需要测量多个业务结果,每个结果对业务的价值不同,并且需要管理不同的利益相关者。

  • 方法可能根据产品类型有所不同——例如,根据优化问题的形状,你可能会使用离散(A/B 和多变量)或自适应(“土匪”)实验模式。

因此,数据领导者积极标准化平台或工具以支持产品实验是有益的。特别是当实验的执行可能会分散到多个跨职能产品团队时,这一点尤为重要。

不要认为可以购买或构建支持所有用例的平台。但应明确平台将支持的用例,并在实施和数据收集上提供足够的灵活性,以便可靠地完成不常见或更复杂的实验。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 Hans Reniers 提供,来自 Unsplash

实验速度通常被产品团队视为构建和扩展成功产品的关键,这通常通过谷歌(严重缺陷的)“41 种蓝色”实验来体现。

但虽然速度和迭代学习至关重要,你无法通过迭代方式达到新的商业模式。 大型组织中的实验往往受限于当前用户体验的可能性和/或单个产品团队所能控制的范围,而实际任务可能是重新构想体验的可能性。

这就是为什么数据团队还应该推动实验设计和分析的最佳实践,比如:

  • 以行为假设为主导,而不是产品功能的变体

  • 将假设转化为独立的实验属性(也许将蓝色的阴影留给设计团队)

  • 考虑合适的实验设计——是连续的 A/B 测试系列,还是需要多变量方法,以便理解实验属性之间的交互?

不要陷入局部最优。过去 15 年中,我见过的最具影响力的实验都要求团队超越自身范围,定义那些从根本上改变用户体验和商业模式的假设。

4. 队列分析

仅次于进行受控实验,队列分析是产品团队最有用的分析工具。这种方法涉及将用户划分为具有共同特征的组,以评估用户健康状况并制定产品假设。

没有一种正确的方法来进行队列分析——可能性是无限的——但有很多方法会使其变得错误。我将解释一些我见过的这种技术误用的方法,以及如何正确地进行。

首先,让我们考虑一个产品团队,希望了解他们的用户基础的健康状况,以及产品体验是否随着时间变得更“粘性”。

在这里,“健康”可以由用户保留、较为具体的活跃度,或者用户转化为付费客户来定义。

避免对队列定义过于宽泛,例如逐周比较所有用户,这可能会因为不同队列中的回访用户比例不同而混淆分析。

为了使这种分析有用,至关重要的是,你必须比较“苹果与苹果”,例如关注每周到来的新用户。你还可以进一步细分这些队列(例如,按地域或设备),以诊断用户健康状况的增加和减少。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这张图表绘制了每周新用户的用户保留随时间的变化,显示了每个队列的健康状况。 图片由 Shane Murray 提供。

其次,让我们考虑一个产品团队,希望了解哪些特征在推动健康用户方面最有价值。

避免返回那些分析说“做 x 的人更可能留下”的结论。这些陈述因几个原因几乎毫无用处。

首先,执行任何操作的用户更可能留存——你可能只是挑选数据;其次,你没有提供关于特征使用情况的背景信息——它可能是最不受欢迎的特征;最后,缺乏时间意识使得这种说法更可能只是相关性的。

相反,你应该:

  • 对队列操作进行时间限制(例如前 30 天),以将潜在原因与后续效果(例如第 30 天至第 180 天)分开。

  • 比较多个操作,以避免挑选感兴趣的特征。

  • 提供关于特征使用情况及其对用户保留影响的背景信息。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

特征散点图。图片由 Shane Murray 提供。

上述功能散点图显示了一个标记为 A 到 H 的产品功能集的功能使用与保留提升的关系。例如,功能 A 被轻度采纳,但与最大的保留提升相关联;功能 D 被大量采纳,但与较小的保留提升相关联。

尽管这项分析没有规定投资的具体方向,但它可以为未来的产品开发提供信息:

  • 你可能会因功能 E 缺乏采用和对保留的影响而逐步淘汰它

  • 你可能会选择推动高影响力功能 A、B 或 F 的更多采用

  • 你可能会选择重建一个表现不佳的功能,以提升其潜在采纳或影响力

产品分析工具,如 Amplitude 和 Mixpanel,通过前期的实施使得分组变得简单。但你也可以选择在 BI 工具或自定义应用中自行构建,从基本的行为分组开始,然后添加维度以支持更多的探索。

5. 自助访问数据

在上述所有产品数据需求中,你会面临一个共同的问题 —— 我们如何使其自助服务?

尽管数据团队变得越来越灵活,产品团队仍然期望能够随时得到看似简单的问题的答案(例如,“与推送通知交互的用户的保留差异如何?”),即使之前没有人考虑过这个具体问题。

此外,分析工作仍然承载着 自己动手做 的期望,而设计或工程则没有。虽然很容易把产品利益相关者看作是不理解我们领域的人,但实际上往往是因为分析师被困在回答一些基础问题上,这些问题 本可以 通过更高质量的数据访问得到解决,而不是花时间进行更复杂、全面或深刻的分析来展示他们的专业知识。

数据团队需要解决的问题是如何为产品利益相关者提供正确的自助访问,以实现以下目标:

  • 更广泛地访问可靠数据,以便更快地做出良好的决策

  • 从以服务为导向的响应转向数据洞察路线图的分析师工作转变

在工具配置和访问上花费的时间通常是值得的,但自助使用的回报必须大于构建和维护它所花费的努力。你可能会发现,为基本指标访问构建自助服务非常有意义,但如果你进一步推动更精细或复杂的分析,只有在你能够将解决方案普遍化并在许多产品团队中驱动显著采用时,才值得付出额外的努力。

你可以通过多种路径来实现这些能力——从现成的到自制的,以及介于两者之间。数据团队将希望在其数据仓库中保持单一的数据来源,以最小化治理成本并维持数据的可信度。但今天的技术栈需要一系列工具来实现自助服务的承诺——BI、产品分析和实验往往是值得投资的独立工具,因为它们有针对性的用户界面。

成功与产品团队合作的技巧

随着产品团队越来越注重数据,数据团队越来越注重产品,数据与产品学科之间的关系可能变得复杂或充满挑战。

但这并非必须——这是一个关键的合作关系,如果你能为产品团队设定正确的期望,了解数据能带来什么好处,它可以高效运作。以下是方法。

调动他们的能量——产品经理因推动影响力而获得奖励,而最常见的路径是通过专注于产品工程团队并使用实验来实现渐进式的产品改进。

分析师或数据科学家应成为产品的专家伙伴,确保实验设计的质量、完美的执行和对实验数据的严格解释。在这些以实验为驱动的产品团队中,分析师通常会获得一个战略合作伙伴的席位,贡献假设,对产品路线图进行评估,并校准团队在何时使用数据与何时依赖直觉或定性方法的指南针。

实验不会全部都是突破性的,但动能是成功产品团队的必要属性。

用好奇的数据团队提升战略——虽然分析师在支持每个产品团队目标方面成为专家伙伴至关重要,但强大且协作的数据团队的独特优势在于其观察多个产品团队之间的重叠、差距和权衡的能力。

一个协作的分析师团队会看到不同产品团队之间指标和报告的重叠,并可以构建出没人意识到他们需要的分析数据产品。

或者,他们可能会观察到用于理解用户行为的指标存在差距,然后研究并实施一套新的指标,以更好地体现驱动产品战略的行为。例如,一位对多个产品团队有全面了解的数据科学家可能会将多种结果纳入其目标设定或推荐算法中,例如平衡短期增长与长期参与。

培养一种鼓励好奇心和批判性思维的文化,使分析师和数据科学家能够挑战现状,并在产品合作伙伴的直接方向之外产生影响。

总会有权衡——没有免费的午餐。当你为一种行为优化时,按定义,你是在抑制其他行为。实验越雄心勃勃,需要参与的利益相关者就越多,试验的时间也就越长。

产品首页上的实验通常是这些复杂性出现的地方,你可能会在非常小的一部分用户上运行长期实验(例如<1%)。

了解利益相关者及其目标,事先定义成功标准(例如你将如何评估与浏览、导航和购买相关的不同结果),并期望提供一系列解决方案,以便产品团队进行权衡。

嵌入数据团队成员以提高速度,但保持强大的核心——产品团队对数据需求旺盛,乐于实验,并感受到速度的必要性。因此,大多数数据团队会发现利用分散的方法,并嵌入数据分析师以增加与产品团队的接近度、避免瓶颈并提高速度是有帮助的。

然而,我建议只在以下情况下这样做:

  • 数据平台在工具和流程方面已经相当成熟,能够支持高效的分析工作(同样适用于数据科学/机器学习工作)。

  • 数据团队拥有足够的资源来嵌入主管/经理以及个别贡献者,以便你可以在分布式模型下进行管理,同时继续构建更强大的核心(或“卓越中心”)。

  • 产品组织有明确而独特的目标,否则你分析师的工作将充其量只是重叠,最糟糕的情况是毫无意义。

另一个需要考虑的挑战是,一旦你开始在每个产品团队中嵌入分析师,你就会转移管理这些团队所需的关键数据产品。你可能会无意中创建一个孤岛,错过生产有利于多个产品团队的分析或数据产品的机会。

通过共享平台和服务可以捕获协同效应。关于费用分摊模型的问题可能会出现,最好避免这种复杂性,除非实际情况迫使你不得不面对(各团队之间成本差异较大)。

启用自助点击流数据,但不要期望这是万能的——数据团队需要做出的关键决策之一是如何处理其点击流数据,它在理解用户行为方面作为不同数据源之间的连接纽带发挥了关键作用。

这个决策很少是容易的——虽然数据团队的客户通常说他们希望访问原始数据,但他们通常指的是希望访问经过高度筛选、可信的数据,并以一种他们可以轻松操作的方式提供。

自助解决方案(例如 Amplitude、Mixpanel)提供了许多现成的可视化和可下载报告,这些是你的产品客户急需的,但这将要求你遵循他们的数据模型,并且需要数据团队在仪表化、治理、培训和对所选工具的支持上投入大量精力。

另一方面,在你的数据仓库之上构建以产品为中心的报告,通过 BI 工具或更多自定义的数据应用,可能为数据团队提供他们所需的一致性和灵活性,但通常需要为每个新的指标、报告或屏幕进行开发。

无论你选择哪条路径,最终目标都应是为了更好或更快的产品决策。因此,你应考虑更广泛访问的好处,以及数据团队从采用这一解决方案中工作负载的变化。一个好的、轻量级的自服务实施将使你的分析师能够从事更有意义的工作。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 Shane Murray 提供。

另一个需要记住的关于点击流数据的决定性特征是其短暂的价值。产品和市场的根本变化使得从五年前的点击流数据中提取见解几乎是徒劳的。有些人建议 时间衰减可以表示为 1/x。这里的要点是,在迁移或其他数据重组项目中,你通常可以将其留在冷存储中(如果你还保留的话)。

“真正的艺术家会发布作品”

著名的史蒂夫·乔布斯名言恰如其分地总结了有效的数据产品团队关系。在最佳状态下,两个团队共同协作,发布新的有效功能和产品,并由最佳的数据驱动决策…以及一些艺术直觉指导。

关注我以获取更多关于数据领导力、数据科学应用及相关主题的故事。订阅以将我的故事送到你的收件箱。

测量新 Pandas 2.0 相对于 Polars 和 Datatable 的速度——仍然不够好

原文:towardsdatascience.com/measuring-the-speed-of-new-pandas-2-0-against-polars-and-datatable-still-not-good-enough-e44dc78f6585

尽管新的 PyArrow 后端为 Pandas 带来了令人兴奋的功能,但在速度方面仍然令人失望。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Bex T.

·发表于 Towards Data Science ·7 分钟阅读·2023 年 3 月 29 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图像来自 Midjourney

自从第一次尝试用 read_csv 读取一个大小为一千兆字节的数据集,并意识到需要等待 - 喘息 - 五秒钟以来,人们一直在抱怨 Pandas 的速度。是的,我也是那些抱怨者之一。

五秒钟听起来可能不多,但当加载数据集本身需要这么长时间时,通常意味着后续操作也会需要这么久。而且,由于速度是快速、简便的数据探索中最重要的因素之一,这可能让你感到非常沮丧。

因此,PyData 的人员最近宣布了计划发布带有全新 PyArrow 后端的 Pandas 2.0。对于完全不了解的人,PyArrow 本身是一个设计用于高性能、内存高效处理数组的小巧库。

人们真心希望新的后端能带来比原生 Pandas 更显著的加速。本文将通过将 PyArrow 后端与两种最快的数据框库 Datatable 和 Polars 进行比较来测试这一希望的光芒。

难道这些人还没有做过这个吗?

既然 H20 目前已经运行了受欢迎的 Database-like Ops Benchmark 来测量几乎 15 个库在三种不同数据集大小上的三个数据操作的计算速度,那做这个基准测试还有什么意义?我的基准测试不可能做到那么全面。

好吧,首先,这个基准测试没有包括带有 PyArrow 后端的 Pandas,并且最后一次更新是在 2021 年,那已经很久了。

其次,基准测试在一台拥有 40 个 CPU 核心、128 GB 内存和 20 GB GPU 的超级机器上运行(cuDF,有人用过吗?)。普通用户通常无法使用这样的机器,因此比较在像我这样日常设备上的库之间的差异非常重要。它配备了一个拥有十几个核心的中等性能 CPU 和 32 GB 的内存。

最后,我提倡过程中的完全透明,所以我将详细解释基准测试代码,并将其作为 GitHub Gist 提供,供您在自己的机器上运行。

安装和设置

我们首先安装 Pandas 2.0 的 RC(候选版本),以及最新版本的 PyArrow、Datatable 和 Polars。

pip install -U "pandas==2.0.0rc0" pyarrow datatable polars
import datatable as dt
import pandas as pd
import polars as pl
dt.__version__
'1.0.0'
pd.__version__
'2.0.0rc0'
pl.__version__
'0.16.14'

我使用 NumPy 和 Faker 库创建了一个合成数据集,以模拟人口普查数据集中的典型特征,并将其保存为 CSV 和 Parquet 格式。以下是文件路径:

from pathlib import Path

data = Path("data")
data_csv = data / "census_data.csv"
data_parquet = data / "census_data.parquet"

查看这个 GitHub gist以查看生成数据的代码。

有 5000 万行七个特征,使文件大小达到约 2.5 GB。

基准测试结果

在展示代码之前,我们先看看好东西——基准测试结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图片

一开始,我们可以看到 PyArrow Pandas 在所有类别中都排在最后(或在groupby中倒数第二)。

请不要将阅读和写入 Parquet 类别中的不存在的条形图误认为是 0 运行时间。这些操作在 Datatable 中不受支持。

在其他类别中,Datatable 和 Polars 并列第一,Polars 稍微占有优势。

写入 CSV 文件一直是 Pandas 的慢速过程,我猜新后端不足以改变这一点。

你应该切换吗?

所以,百万美元的问题是——你应该切换到更快的 Polars 还是 Datatable?

答案是我非常讨厌的“这要看情况”。你是否愿意为了更快的速度牺牲 Pandas 近二十年的成熟度,以及说实话,愚蠢的容易和熟悉的语法?

在这种情况下,请记住,你花时间学习新库的语法可能会平衡其性能提升。

但是,如果你只是处理大量数据集,那么学习这些快速库中的任何一个可能从长远来看都值得付出努力。

如果你决定继续使用 Pandas,请仔细阅读Pandas 用户指南的性能提升页面。它概述了一些技巧和窍门,以在不依赖第三方库的情况下为 Pandas 引擎增加额外的动力。

此外,如果你被困在一个大的 CSV 文件中,仍然想使用 Pandas,你应该记住以下代码片段:

import datatable as dt
import pandas as pd

df = dt.fread("data.csv").to_pandas()

它以 Datatable 的速度读取文件,将其转换为 Pandas DataFrame 几乎是瞬间完成的。

基准测试代码

好了,最后来看代码吧。

导入库后,首先要做的是定义一个 DataFrame 来存储基准测试结果。这将使绘图过程变得更简单。

import time

import datatable as dt
import pandas as pd
import polars as pl

# Define a DataFrame to store the results
results_df = pd.DataFrame(
    columns=["Function", "Library", "Runtime (s)"]
)

它有三列,一列用于任务名称,另一列用于库名称,还有一列用于存储运行时间。

然后,我们定义一个timer装饰器,执行以下任务:

  1. 测量装饰函数的运行时间。

  2. 提取函数的名称和其library参数的值。

  3. 将运行时间、函数名称和库名称存储到传递的结果 DataFrame 中。

def timer(results: pd.DataFrame):
    """
    A decorator to measure the runtime of the passed function. 
    It stores the runtime, the function name, and the passed 
    function's "library" parameter into the `results` DataFrame 
    as a single row.
    """

这个想法是定义一个通用函数,如read_csv,用于读取三种库中的任意一个的 CSV 文件,可以通过像library这样的参数进行控制:

# Task 1: Reading CSVs
@timer(results_df)
def read_csv(path, library):
    if library == "pandas":
        return pd.read_csv(path, engine="pyarrow")
    elif library == "polars":
        return pl.read_csv(path)
    elif library == "datatable":
        return dt.fread(str(path))

注意我们是如何用timer(results_df)装饰函数的。

我们以类似的方式定义其他任务的函数(参见the Gist中的函数体):

# Task 2: Writing to CSVs
@timer(results_df)
def write_to_csv(df, path, library):
    ...

# Task 3: Reading to Parquet
@timer(results_df)
def read_parquet(path, library):
    ...

# Task 4: Writing to Parquet
@timer(results_df)
def write_to_parquet(df, path, library):
    ...

# Task 5: Sort
@timer(results_df)
def sort(df, column, library):
    ...

# Task 6: Groupby
@timer(results_df)
def groupby(df, library):
    ...

然后,我们为每个库运行这些函数:

from pathlib import Path

# Define the file paths
data = Path("data")
data_csv = data / "census_data.csv"
data_parquet = data / "census_data.parquet"

# libraries = ["pandas", "polars", "datatable"]
l = "datatable"

# Task 3/4
df = read_parquet(data_parquet, library=l)
write_to_parquet(df, data_parquet, library=l)

# Task 1/2
df = read_csv(data_csv, library=l)
write_to_csv(df, data_csv, library=l)

# Task 5/6
sort(df, "age", library=l)
groupby(df, library=l)

为了避免内存错误,我避免了循环,并在 Jupyter Notebook 中运行了三次基准测试,改变了l变量。

然后,我们使用可爱的 Seaborn 创建基准图形,展示以下简单的柱状图:

g = sns.catplot(
    data=results_df,
    kind="bar",
    x="Function",
    y="Runtime (s)",
    hue="Library",
)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供

事情正在发生变化

多年来,Pandas 依赖于 NumPy 的肩膀,因为 NumPy 在流行度上迅猛增长。NumPy 慷慨地借用了其快速计算和数组操作的功能。

但这种方法受限于 NumPy 对文本和缺失值的糟糕支持。Pandas 不能使用本地 Python 数据类型如列表和字典,因为那样会在大规模上成为笑柄。

因此,Pandas 在过去几年中已悄然远离 NumPy。例如,它在 2020 年就引入了 PyArrow 数据类型用于字符串。它还使用了用其他语言编写的扩展,如 C++和 Rust,用于日期(含时区)或分类数据等复杂数据类型。

现在,Pandas 2.0 拥有一个全面的后端,支持所有数据类型,基于 Apache Arrow 的 PyArrow 实现。除了明显的速度提升外,它还提供了更好的缺失值支持、互操作性和更广泛的数据类型支持。

因此,即使后端仍然比其他 DataFrame 库慢,我仍然热切期待其正式发布。感谢阅读!

这里有一些页面可以了解更多关于 Pandas 2.0 和 PyArrow 后端的信息:

喜欢这篇文章以及它那奇特的写作风格?想象一下,获取更多类似的文章,全部由一位才华横溢、迷人幽默的作者(对了,那就是我 :)。

只需 4.99 美元的会员费用,你将不仅能访问我的故事,还能获取来自 Medium 上最聪明、最杰出思想者的宝贵知识。如果你使用我的推荐链接,你将获得我超级感激的心意和一个虚拟的击掌,以支持我的工作。

[## 通过我的推荐链接加入 Medium — Bex T.

独享所有⚡高级⚡内容,并在 Medium 上无限畅游。通过购买我一杯…

ibexorigin.medium.com](https://ibexorigin.medium.com/membership?source=post_page-----e44dc78f6585--------------------------------) 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

媒体组合建模:数据科学家避免陷阱的技术指南

原文:towardsdatascience.com/media-mix-modeling-technical-guideline-to-overcome-pitfalls-for-a-smarter-decision-making-e677165f9140?source=collection_archive---------6-----------------------#2023-03-31

如何理解输出以及最大化其实际应用

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Hajime Takeda

·

关注 发布在 Towards Data Science ·6 分钟阅读·Mar 31, 2023

TLDR: 媒体组合建模(MMM)是一种用于市场测量的统计方法,但它并不是像其他技术那样“一刀切”的解决方案。我将介绍数据科学家提高建模技巧和实现改进结果的重要检查点,广告报告与 MMM 之间的区别,以及多点触摸归因(MTA)与 MMM 之间的区别。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由Austin Distel提供,来源于Unsplash

介绍

MMM 是一种统计方法,用于理解和衡量投资回报率(ROI)并优化媒体预算。

在饮料、消费品、汽车和时尚行业拥有巨额广告预算的公司中的数据科学家们一直在致力于改善 MMM。此外,广告技术公司,如谷歌和 Meta,最近也积极关注 MMM,因为 GDPR 和苹果 IDFA 弃用等隐私法规影响了数字世界的追踪准确性。

欲了解更多信息,请参考我之前发布的这篇文章。

## 媒体混合建模:如何使用 Python 和 LightweightMMM 衡量广告效果

媒体混合建模,它的实施及实用技巧

[towardsdatascience.com

在发布上述文章后,我收到了许多积极的反馈和一些来自 Towards Data Science 读者的问题。一些常见的问题包括:

(1) 成功的 MMM 项目的检查点是什么?

(2) 广告报告和 MMM 有何不同?

(3) 多触点归因(MTA)和 MMM 之间有什么区别?

在这篇文章中,我将解决这些问题,并提供见解,以帮助你更好地理解这些概念。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由krakenimages提供,来源于Unsplash

(1) 成功的 MMM 项目的检查点是什么?

为了确保 MMM 的可靠性和准确性,数据科学家在相信结果之前应考虑以下检查点:一些想法受到谷歌研究论文的启发:Chan, D., & Perry, M. (2017). 媒体混合建模中的挑战与机遇。

  1. ✔️ 足够的数据点:
  • 确保有足够的数据点来建模广告渠道及其关系。

  • 通常,MMM 需要至少两年的周级数据。然而,如果你没有这么多数据,每日数据也是可以接受的,但在这种情况下,你需要更加仔细地审查异常值。

2. ✔️ 选择适当的输入变量:

  • 输入数据的变异性至关重要。例如,如果媒体频道 X 的支出在整个时间段内保持不变,模型可能难以确定其对销售的影响。在这种情况下,排除该频道作为输入变量可能会更有利。

  • 保留影响销售的因素。例如,如果杂志 X 的支出显著小于其他广告且仅为暂时性支出,可能更适合将其排除。

  • 输入变量可以在模型前期和模型选择阶段进行选择。

3. ✔️ 处理相关的输入变量:

  • 检查输入变量之间的潜在多重共线性,这可能导致高方差系数估计和将销售归因于特定广告渠道的困难。

  • 如果你不断为 Meta 和 Tiktok 广告分配相同的预算,模型的可靠性可能会受到影响,使得评估这些媒体渠道的影响变得困难。

  • 使用方法来解决相关变量,例如正则化技术或变量选择方法。

4. ✔️ 控制选择偏差:

  • 注意潜在的选择偏差问题,例如季节性。

  • 例如,11 月份的销售增加可能不是由于广告,而是消费者需求或黑色星期五促销。

  • 根据我的经验,内部促销数据或定价数据可以作为不可观测需求变量的有价值的控制因素。

5. ✔️ 验证外推假设:

  • 外推假设涉及对模型在可用数据范围之外的行为进行预测或得出结论。

  • 在尝试回答诸如“如果将我的广告支出 X 增加十倍会发生什么”或“如果我突然停止对广告 X 的支出会发生什么”等商业问题时,请小心。

  • 测试模型在不同场景下的表现,并在解释需要显著外推的结果时要小心。

6. ✔️ 测试模型性能:

  • 通过将 MMM 的预测与实际销售和营销数据进行比较来验证 MMM。

  • R-squared 和 MAPE,即均值绝对百分比误差,是 MMM 的知名度量指标。一般来说,如果 R2 大于 0.8,则被认为是好的。此外,对于 MAPE,目标是 20% 或以下。

7. ✔️ 进行随机实验

  • 使用 MMM 估计媒体预算变化的影响时,建议进行随机实验以验证发现。

  • 例如,通过将区域划分为测试组和对照组并调整广告支出,你可以测量提升效果并获得更准确的结果。

通过解决这些检查点,数据科学家可以提高对 MMM 结果有效性和可靠性的信心,并根据模型提供的见解做出更明智的决策。

(2) 广告报告和 MMM 有什么不同? 🤔

直截了当地说,MMM 提供了关于营销表现的更广泛视角,帮助企业从长期角度分配资源并优化整体营销组合。相比之下,像 Google/Meta Ads 这样的广告报告提供了对特定广告或活动的更细致见解,允许进行调整以改善短期表现。

媒体组合建模(MMM)的特点:

  1. MMM 专注于帮助企业优化整体营销组合和资源分配。

  2. 它考虑了不同媒体渠道之间的相互作用,包括在线和离线。

  3. 即使转换点是离线的,也可以使用。

广告报告的特点:

  1. 广告报告提供了有关特定广告或活动表现的更详细见解,如点击率(CTR)和每次点击费用(CPC)。

  2. 这些报告主要关注短期表现,帮助广告主快速掌握单个活动的进展。

  3. 实际客户有多个媒体接触点。多个媒体的交织效果无法在每个媒体的广告报告中考虑。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图像:Google Ads 上的广告报告

(3)Multi-Touch Attribution(MTA)和 MMM 之间的区别是什么? 🤔

Multi-Touch Attribution(MTA)是另一种营销测量方法,旨在使用其访问日志将信用分配给客户旅程中的不同营销接触点。

每种方法都有其优缺点。与 MMM 检查每个营销渠道的汇总成本不同,MTA 提供了对各个接触点贡献的更细致和可靠的视角。

另一个区别是跟踪非数字客户行为。MTA 专注于数字接触点和数字转换,而 MMM 考虑了离线媒体支出的成本和离线转换的结果。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图像:MTA 不跟踪离线活动

MMM 更适用于

  • 一个品牌投资于电视和杂志等离线媒体,并希望评估其影响时,MTA 更为适用。

  • 一个品牌通过离线和在线渠道销售商品/ 一个品牌主要通过离线渠道销售商品。

  • 财务视角更为重要。

  • 一个品牌拥有过去 2-3 年的历史广告和销售数据。

另一方面,当

  • 一个品牌在 Google Ads 和 Meta Ads 等数字媒体上花费很多。

  • 一个品牌主要在线销售商品。

  • 优先考虑理解客户旅程。

  • 需要实时评估。

最后

感谢阅读!如果你有任何问题/建议,请随时通过Linkedin与我联系!此外,如果你在 Towards Data Science 上关注我,我会很高兴。

参考

认识 Gemini:谷歌最大、最强大的 AI 模型

原文:towardsdatascience.com/meet-gemini-googles-largest-and-most-powerful-ai-model-2ffd2f07490f

这个下一代 AI 模型在几乎所有学术基准测试中超过了 ChatGPT。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Natassha Selvaraj

·发布于 Towards Data Science ·6 分钟阅读·2023 年 12 月 9 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 Mitchell Luo 拍摄,来源于 Unsplash

当 OpenAI 去年 11 月发布 ChatGPT 时,每个人心中都有一个迫切的问题——科技巨头们在做什么?

像谷歌这样的公司会何时回应这一发展?

我们现在有了答案。

2023 年 12 月 6 日,谷歌宣布了他们最新的 AI 模型:Gemini。

根据公司首席执行官 Sundar Pichai 的说法,这项技术是人工智能的巨大飞跃,将影响几乎所有谷歌的产品。

Gemini 提供 3 种尺寸

当前版本的模型称为 Gemini 1.0。它可以处理文本、图像、视频和音频,并且有 3 种不同的尺寸。

Gemini Nano 是一个小型、高效的版本,可以在原生环境和 Android 设备上运行。

Gemini Pro,中级版本,在能力和效率之间取得了平衡。这个模型的表现比谷歌之前的旗舰模型 PaLM-2 好得多。目前它为 Bard 聊天机器人提供支持。

最终,Gemini Ultra 是系列中最强大的模型。它在复杂推理方面表现出色,并且在各种基准测试中超越了 OpenAI 的 GPT-4 模型。

Gemini Ultra 尚未公开发布。谷歌宣布该模型将在明年初推出,尽管没有提供具体的时间框架。

Gemini 与 OpenAI 的 GPT 模型有何不同?

OpenAI 的 ChatGPT 目前由 2 个 AI 模型提供支持——免费版的 GPT-3.5 和付费版的 GPT-4。

几个月前,OpenAI 宣布 GPT-4 具有多模态能力(即能够 处理文本、音频和图像)。

然而,尽管它可以处理各种数据类型,模型的主要设计和功能仍然集中在 基于文本的输入和输出 上。

这意味着 GPT-4 是一个基于文本的框架,视觉和音频处理模型在其基础上作为第二阶段构建。

例如,将 GPT-4 与图像生成模型 DALLE-3 结合,可以将文本转换为如下所示的图像:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

虽然 GPT-4 在处理其他模态的训练与其基于文本的训练是分开的,但 Gemini 从一开始就接受了文本、图像、视频和音频的多样化数据集训练。

简而言之,多模态能力是从基础上构建到 Gemini 中的,以确保它能原生理解所有数据类型。

这种架构差异意味着 Gemini 更容易进行泛化,因为它理解来自文本、图像、音频和视频的信息。

像 GPT-4 和 DALLE-3 这样的模型,则针对 特定任务 进行了微调(GPT-4 针对文本,DALLE-3 针对图像)。

在 Google Deepmind 关于 Gemini 的研究论文中,提出了以下问题:

一个未解的问题是,这种联合训练是否能产生一个在每个领域都有强大能力的模型——即使与针对单一领域的模型和方法相比。

这个问题涉及 AI 领域中的一个基本挑战:专业化模型与通用模型之间的权衡。

针对单一领域设计的模型通常在该特定任务上的表现更好,相比之下,通过联合训练开发的模型可能表现较差。

现在让我们将 Gemini 的表现与专门针对特定领域的最先进模型进行比较。

Gemini 在几乎所有基准测试中都超过了 ChatGPT

在 Google Deepmind 最新的 报告 中,模型的性能与其他算法如 Claude 2、PaLM-2、GPT-3.5 和 GPT-4 进行了比较。

下面是 Gemini 在各个领域与最佳模型的对比:

文本

Gemini 在文本基准测试中的表现与现有模型的对比:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来自 Deepmind 的技术报告

在涵盖推理能力、阅读理解、STEM 和编码的多个基于文本的基准测试中,注意到 Gemini Ultra 在 9 个评估中的 8 个中优于 OpenAI 的 GPT-4 模型。

根据 Google Deepmind 的报告,当使用一种名为“链式思维”的提示技术时,模型表现最佳。

在思维链提示中,你将一个问题分解,并引导 AI 通过逐步推理的过程,类似于人类解决问题的方式。

这通常比单纯地将整个问题抛给 AI 模型更有效。

你可以阅读这个指南,了解更多关于思维链提示的信息。

同时,请注意Gemini Pro(中档版本),目前为 Bard 提供支持,在几乎所有基准测试中都超越了 GPT-3.5。

自 Gemini Pro 发布以来,我一直在进行实验,个人认为它的响应与 GPT-3.5 相当。

我计划对它们的推理和编码能力进行更详细的比较,并会尽快发布后续文章。

图像理解

即使在特定任务上没有先前的训练,Gemini Ultra 的视觉能力仍然超过了那些为这些基准测试进行了微调的其他模型:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源于Deepmind 的技术报告

第一个基准测试,MMMU,包含了 6 个学科的大学级问题——商业、科学、人文学科、艺术、技术和医学。

这个基准不仅要求强大的推理能力和大学级的专业知识,而且问题也独特地基于图像

准确回答这些问题并不容易,因为模型必须做两件事——解释视觉元素和进行复杂的文本分析。

Gemini Ultra 在这个基准测试中超过了所有其他 AI 模型,突显了其强大的多模态能力和泛化能力。

视频理解

Gemini Ultra 在视频相关任务中也达到了最先进的性能——它能够添加字幕根据视频回答问题

例如,给定这个足球比赛视频,该模型被要求提供有关如何提高球员技术的建议。

这是 Gemini 在分析视频后的回应:

This soccer player needs to work on their ball-striking mechanics. Their foot is not making
good contact with the ball, which is causing the ball to fly up and away from the goal. They
also need to work on their body positioning. They should be leaning into the shot with their
non-kicking leg in front of their kicking leg, and they should be following through with their
kicking leg.

同样,Gemini Ultra 在图像生成和音频理解任务中表现出了卓越的性能。你可以在这里阅读完整报告。

尽管该模型在学术基准测试中的表现看起来很有前景,但请记住,在研究环境中 4-5%的改进可能未必会对现实世界产生实际影响。

在我看来,将 AI 模型整合到其他应用程序中并为特定用例(如自动化数据分析或增强搜索能力)进行产品化,将比性能的边际改进产生更大的影响。

我期待看到 Google 如何将这个新模型整合到其产品套件中,特别是 Google Analytics,以生成更先进的见解和预测。

我从关于 Gemini 的论文中得到的最大收获是,一个以多模态为核心构建的模型可以超越专为特定任务设计的算法。

这种方法可能是实现人工通用智能(AGI)的重要一步,其目标是建立一个可以应用于广泛任务的 AI 模型。

下面是如何开始使用 Gemini 的方法。

正如本文前面提到的,你可以通过访问Bard 聊天机器人今天开始使用 Gemini Pro。

谷歌还宣布,Gemini Nano(最轻版本)将很快被集成到 Pixel 智能手机中,从 Pixel 8 Pro 开始。

这将允许你使用 Recorder 应用创建对话的自动总结,并在 WhatsApp 上生成高质量的回复建议。

最后,Gemini 将于 12 月 13 日通过 Google Generative AI Studio 向开发者开放。你还可以注册谷歌的实时讲座,了解如何在 Google Cloud 上使用 Gemini 构建应用程序

缓存 DataFrame 函数

原文:towardsdatascience.com/memoizing-dataframe-functions-7a27dff532f7?source=collection_archive---------5-----------------------#2023-03-03

使用可哈希 DataFrame 和消息摘要来优化重复计算

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 克里斯托弗·阿里萨

·

关注 发表在 Towards Data Science ·7 分钟阅读·2023 年 3 月 3 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的照片

提高软件系统运行性能的一个著名技术是函数缓存。缓存是一种应用于单个函数的缓存方法。如果函数多次使用相同的参数调用,可以通过将结果存储在映射(或磁盘)中来避免重复计算。后续调用时,如果找到参数,则返回存储的结果。

这种机会伴随着权衡。记忆化以空间换时间:先前计算的结果必须存储在内存或磁盘上。此外,被记忆化的函数必须是纯粹的:输出必须完全由输入决定。最后,并非所有类型的函数参数都是合适的。在内存记忆化中,结果存储在映射中,参数必须是可哈希和不可变的。在基于磁盘的记忆化中,结果存储在文件中,参数必须能还原为唯一的文件名;从密码学哈希函数派生的消息摘要是实现此目的的最佳选择。

记忆化的另一个挑战是缓存失效:为了避免缓存过度增长,必须丢弃缓存。Python 标准库通过 functools.lru_cache() 装饰器提供了一种内存解决方案。该装饰器通过“最近最少使用”(LRU)缓存失效策略实现记忆化:在达到最大计数后,会丢弃最近最少使用的缓存。

对于使用 Pandas DataFrame 作为函数参数的 Python 程序员,还有更多挑战。由于 Pandas DataFrameSeries 是可变容器,因此它们不可哈希。如果参数是 Pandas DataFrame,则 functools.lru_cache() 将失败。

>>> import functools
>>> @functools.lru_cache
... def cube(v):
...     return v ** 3
...
>>> import pandas as pd
>>> df = pd.DataFrame(np.arange(1_000_000).reshape(1000, 1000))
>>> cube(df)
Traceback (most recent call last):
TypeError: unhashable type: 'DataFrame'

StaticFrame 是一个替代 DataFrame 的库,为内存和基于磁盘的记忆化提供了高效的解决方案。

哈希函数和哈希碰撞

在展示使用 StaticFrame 的 DataFrame 记忆化之前,区分不同类型的哈希函数是重要的。

哈希函数将可变大小的值转换为较小的(通常是)固定大小的值。哈希碰撞是指不同的输入哈希到相同的结果。对于某些应用,哈希碰撞是可以接受的。密码学哈希函数旨在消除碰撞。

在 Python 中,内置的 hash() 函数将可哈希对象转换为整数。任意类型可以通过实现魔法方法 __hash__() 提供支持。重要的是,hash() 的结果并不具备抗碰撞能力:

>>> hash('')
0
>>> hash(0)
0
>>> hash(False)
0

Python 字典使用 hash() 将字典键转换为低级 C 数组中的存储位置。预期会有碰撞,如果发生碰撞,会使用 __eq__() 进行相等性比较解决。因此,要使任意类型可哈希,它需要实现 __hash__()__eq__()

密码学哈希函数不同于 hash():它们旨在避免碰撞。Python 在 hashlib 库中实现了一系列密码学哈希函数。这些函数处理字节数据,并通过 hexdigest() 方法返回一个消息摘要字符串。

>>> import hashlib
>>> hashlib.sha256(b'').hexdigest()
'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
>>> hashlib.sha256(b'0').hexdigest()
'5feceb66ffc86f38d952786c6d696c79c2dbc239dd4e91b46729d73a27fb57e9'
>>> hashlib.sha256(b'False').hexdigest()
'60a33e6cf5151f2d52eddae9685cfa270426aa89d8dbc7dfb854606f1d1a40fe'

内存记忆化

要对以 DataFrames 作为参数的函数进行记忆化,需要一个不可变且可哈希的 DataFrame。StaticFrame 提供了 FrameHE 来实现这一点,其中 “HE” 代表“哈希、相等”,这是 Python 哈希功能所需的两个实现。虽然 StaticFrame 的 Frame 是不可变的,但它不是可哈希的。

FrameHE.__hash__() 方法返回索引和列标签的 hash()。虽然这会与任何具有相同标签但值不同的 FrameHE 冲突,但仅使用标签会将更昂贵的完整值比较推迟到 __eq__()

FrameHE.__eq__() 方法的实现简单地委托给 Frame.equals(),这是一个始终返回单一布尔值的方法。这与 Frame.__eq__() 不同,后者返回的是布尔 Frame 中的逐元素比较结果。

>>> f = sf.FrameHE(np.arange(1_000_000).reshape(1000, 1000))
>>> hash(f)
8397108298071051538
>>> f == f * 2
False

使用 FrameHE 作为参数时,可以使用装饰了 functools.lru_cache()cube() 函数。如果没有 FrameHE,可以使用 to_frame_he() 方法从其他 StaticFrame 容器中高效地创建 FrameHE。由于底层的 NumPy 数组数据是不可变且可以在容器之间共享的,这是一种轻量级、无复制的操作。如果来自 Pandas DataFrame,可以使用 FrameHE.from_pandas()

在下面的示例中,cube() 函数与上述创建的 FrameHE 一起调用。IPython 的 %time 工具显示,在首次调用后,使用相同参数的后续调用速度提高了三个数量级(从毫秒到微秒)。

>>> %time cube(f)
CPU times: user 8.24 ms, sys: 99 µs, total: 8.34 ms
>>> %time cube(f)
CPU times: user 5 µs, sys: 4 µs, total: 9 µs

尽管对内存中的记忆化非常有用,FrameHE 实例也可以作为集合的成员,提供了一种收集唯一容器的新方法。

从 DataFrame 创建消息摘要

虽然内存中的记忆化提供了最佳性能,但缓存会消耗系统内存,并且在进程结束后不会持久化。如果函数结果较大或缓存需要持久化,基于磁盘的记忆化是一个替代方案。

在这种情况下,参数的可变性和可哈希性无关紧要。相反,可以从文件中检索缓存结果,该文件名源自参数。对参数应用加密哈希函数是理想的选择。

由于哈希函数通常以字节数据作为输入,因此 Frame 及其所有组件必须转换为字节表示。常见的方法是将 Frame 序列化为 JSON(或其他字符串表示),然后再转换为字节。由于底层的 NumPy 数组数据已经以字节存储,将这些数据转换为字符串是低效的。此外,由于 JSON 不支持全部 NumPy 类型,JSON 输入可能也不够独特,从而导致哈希碰撞。

StaticFrame 提供了 via_hashlib() 来满足这一需求,提供了一种有效的方法来将字节输入传递给 Python hashlib 模块中的加密哈希函数。以下是使用 SHA-256 的示例。

>>> f.via_hashlib(include_name=False).sha256().hexdigest()
'b931bd5662bb75949404f3735acf652cf177c5236e9d20342851417325dd026c'

首先,调用 via_hashlib() 并选择要包括在输入字节中的容器组件。由于默认的 name 属性 None 无法进行字节编码,因此被排除。其次,调用哈希函数构造器 sha256(),返回一个加载了适当输入字节的实例。第三,调用 hexdigest() 方法以字符串形式返回消息摘要。还可以使用其他密码学哈希函数构造器,如 sha3_256shake_256blake2b

为了创建输入字节,StaticFrame 连接了所有基础字节数据(包括值和标签),可选地包括容器元数据(如 name__class__.__name__ 属性)。使用 via_hashlib().to_bytes() 方法可以获得相同的字节表示。如果需要,这可以与其他字节数据结合以创建基于多个组件的哈希摘要。

>>> len(f.via_hashlib(include_name=False).to_bytes())
8016017

StaticFrame 对创建消息摘要的内置支持显示出比 Pandas 的两种常见方法更高效。第一种方法使用 Pandas 工具函数 pd.hash_pandas_object() 来派生每列的整数哈希值。这个例程使用了一种定制的摘要算法,没有声称具有密码学碰撞抵抗性。为了比较,这里将这些每列的整数哈希值作为 hashlib 消息摘要函数的输入。第二种方法提供了整个 DataFrame 的 JSON 表示,作为 hashlib 消息摘要函数的输入。虽然这可能比 pd.hash_pandas_object() 更具碰撞抵抗性,但通常较慢。下图显示了这两种方法与 via_hashlib() 的性能特征比较。在各种 DataFrame 形状和类型组合中,via_hashlib() 表现优于所有方法,只有一个例外。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者图表

基于磁盘的记忆化

给定将 DataFrame 转换为哈希摘要的方法后,可以实现基于磁盘的缓存例程。下面的装饰器适用于接收和返回单个Frame的函数。在这个例程中,文件名是从参数的消息摘要派生的,前缀是函数的名称。如果文件名不存在,则调用装饰的函数并写入结果。如果文件名存在,则加载并返回。这里使用了 StaticFrame NPZ 文件格式。正如最近 PyCon 讲座中演示的,将 Frame 存储为 NPZ 通常比 Parquet 和相关格式要快得多,并提供完整的往返序列化。

>>> def disk_cache(func):
...     def wrapped(arg):
...         fn = '.'.join(func.__name__, arg.via_hashlib(include_name=False).sha256().hexdigest(), 'npz')
...         fp = Path('/tmp') / fn
...         if not fp.exists():
...             func(arg).to_npz(fp)
...         return sf.Frame.from_npz(fp)
...     return wrapped

为了演示这个装饰器,它可以应用于一个迭代十行窗口、对列求和,然后将结果连接成一个单一 Frame 的函数。

>>> @disk_cache
... def windowed_sum(v):
...     return sf.Frame.from_concat(v.iter_window_items(size=10).apply_iter(lambda l, f: f.sum().rename(l)))

在第一次使用后,性能降低到原始运行时间的不到 20%。虽然加载基于磁盘的缓存比检索内存缓存要慢,但避免重复计算的好处可以在不消耗内存的情况下获得,并且可以利用持久缓存。

>>> %time windowed_sum(f)
CPU times: user 596 ms, sys: 15.6 ms, total: 612 ms
>>> %time windowed_sum(f)
CPU times: user 77.3 ms, sys: 24.4 ms, total: 102 ms

via_hashlib()接口可以在其他情况下作为 DataFrame 所有特征的数字签名或校验和。

结论

如果纯函数在相同的参数下被调用多次,记忆化可以极大地提高性能。虽然处理输入和输出 DataFrame 的函数需要特别处理,但 StaticFrame 提供了便捷的工具来实现内存和基于磁盘的记忆化。虽然必须小心确保缓存被正确失效并避免冲突,但当消除重复工作时,可以实现显著的性能提升。

Apache Spark 中的内存管理:磁盘溢出

原文:towardsdatascience.com/memory-management-in-apache-spark-disk-spill-59385256b68c

它是什么以及如何处理

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Tom Corbin

·发表于 Towards Data Science ·阅读时间 12 分钟·2023 年 9 月 15 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由 benjamin lehman 提供,来源于 Unsplash

在大数据领域,Apache Spark 因其极快的数据处理能力而备受喜爱。作为世界上排名第一的大数据处理引擎,学习使用这个工具是任何大数据专业人士技能组合中的基石。而这一路径中的一个重要步骤是了解 Spark 的内存管理系统及“磁盘溢出”的挑战。

磁盘溢出是指当 Spark 无法将数据全部存储在内存中时,需要将其存储到磁盘上。Spark 的主要优势之一是其内存处理能力,这比使用磁盘驱动器要快得多。因此,构建会溢出到磁盘的应用程序在一定程度上违背了 Spark 的目的。

磁盘溢出有许多不良后果,因此学习如何处理它是 Spark 开发者的重要技能。这就是本文旨在帮助的内容。我们将深入了解磁盘溢出是什么,为什么会发生,它的后果是什么,以及如何解决它。通过使用 Spark 的内置 UI,我们将学习如何识别磁盘溢出的迹象并理解其指标。最后,我们将探讨一些减轻磁盘溢出的可操作策略,例如有效的数据分区、适当的缓存和动态集群调整。

Spark 中的内存管理

在深入探讨磁盘溢出之前,了解 Spark 中的内存管理如何工作是非常有用的,因为这在磁盘溢出的发生和管理中起着至关重要的作用。

Spark 被设计为一个内存数据处理引擎,这意味着它主要使用 RAM 来存储和处理数据,而不是依赖磁盘存储。这种内存计算能力是使 Spark 快速高效的关键特性之一。

Spark 为其操作分配了有限的内存,这些内存被分为不同的部分,这些部分组成了所谓的统一内存:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图片

存储内存

这是 Spark 存储将来要重用的数据的地方,比如缓存的数据和广播变量。通过将这些数据保持在随时可用的状态,Spark 可以通过快速检索数据来提高数据处理任务的性能。

你可以在第一次读取后将 DataFrame 缓存到存储内存中,而不是每次单独分析时从磁盘读取销售数据。这样,对于后续的分析,Spark 可以快速访问缓存的数据,从而提高整个过程的效率。

执行内存

这部分内存是 Spark 用于计算的。因此,当你执行连接或聚合时,Spark 使用执行内存。例如,要计算 DataFrame 中一列的平均值,Spark 会:

  1. 将 DataFrame 的相关部分加载到执行内存中(可能从存储内存中的缓存 DataFrame 中提取)。

  2. 执行聚合,将中间的和和计数存储在执行内存中。

  3. 计算最终的平均值,仍然使用执行内存进行计算。

  4. 输出最终结果,释放用于操作的执行内存。

用户内存

这是用于你创建的自定义数据结构或变量的地方,但这些不由 Spark 直接管理。这就像是你在 Spark 应用程序中的工作区。执行内存用于 Spark 主动处理的数据,而用户内存通常包含元数据、自定义哈希表或其他你可能需要的结构。

假设你有一个包含年龄列的 DataFrame,并且你想在应用程序中稍后的自定义逻辑中跟踪最大年龄。你会读取 DataFrame,计算最大年龄,然后将该年龄存储为一个变量,该变量会存储在用户内存中。这个变量是你稍后会使用的信息,但它并没有被 Spark 的内置操作主动处理,因此它属于用户内存。

与主要存储缓存 DataFrame/RDD 的存储内存不同,用户内存不由 Spark 管理。这意味着你需要确保你使用的用户内存不会超过分配的内存,以避免内存不足(OOM)错误。

保留内存

保留内存用于系统级操作和 Spark 的内部对象。与执行内存、存储内存或用户内存不同,这些内存用于 Spark 应用程序中的特定任务或数据,保留内存用于 Spark 自身的内部操作。

这种内存是“保留”的,因为它不能用于你的数据或任务。这就像你计算机上的操作系统保留了一些磁盘空间用于系统文件和操作——你不能将这些空间用于自己的文件。

存储与执行内存之间的动态分配

在 Spark 中,存储内存和执行内存之间的关系就像两个人分享一个派。这个派代表了总的可用内存,而每种内存——存储和执行——都想要这块派的一部分。

如果执行内存有更多任务需要处理并且需要更多资源,它可以占用更大的内存份额,留下较小的份额给存储内存。相反,如果存储内存需要缓存更多数据,它可以占用更大的份额,留下更少的份额给执行内存。就像这样:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图片

如果另一个不需要,执行内存和存储内存都可能占用整个派(总的可用内存)。然而,执行内存在需要更多时对存储内存的份额有“优先权”。但有个限制——它不能占用过多,以至于存储内存留下的份额小于最低限度。

更技术性的说,执行内存和存储内存共享一个统一的内存区域,其中任何一个可以占用整个区域,如果另一个未使用;然而,执行内存可以从存储内存中驱逐数据,直到某个阈值,超过该阈值则不允许驱逐,而存储内存不能驱逐执行内存。

数据从存储内存中的驱逐通常是由最近最少使用(LRU)策略来管理的。这意味着,当执行内存需要更多空间并决定从存储内存中驱逐数据时,它通常会移除那些最近被访问最少的数据。其想法是,你很久没有使用的数据相比最近访问的数据,可能不太容易立即需要。

Spark 中的磁盘溢出

Spark 喜欢在内存中进行大部分工作,因为这是处理数据的最快方式。但当你的数据比内存大时会发生什么?当你的总内存是 100GB,但你的 DataFrame 是 110GB 时会发生什么?当数据过大而无法放入内存时,它将被写入磁盘。这被称为磁盘溢出。

磁盘溢出可以来自存储内存(当缓存的 DataFrame 太大时)或执行内存(当操作需要大量的中间数据存储时)。回想一下,当执行内存需要额外的空间用于诸如连接或洗牌等任务时,它可以从存储内存中借用——但仅限于一定的限制。如果执行内存达到这个限制仍然需要更多空间,Spark 将会将多余的数据溢出到磁盘:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图片

当存储内存需要更多空间但达到从执行内存借用的限制时,也会发生同样的情况:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图片

分区大小对磁盘溢出的影响

当你将一个表加载到 Spark 中时,它会被拆分成可管理的块,称为分区,这些分区会被分配到工作节点上。Spark 会自动将数据拆分成 200 个分区,但你也可以指定 Spark 将数据拆分成多少个分区。了解需要使用多少个分区是理解 Spark 的一件重要事情,它也与磁盘溢出有关。

我们在前一节中讨论的统一内存是以每个节点为基础存在的。每个工作节点都有自己的统一内存,包括存储内存、执行内存、用户内存和保留内存。每个工作节点会将尽可能多的分区装入其统一内存中。但是,如果这些分区太大,部分分区会溢出到磁盘上。

想象一下你正在处理一个 160GB 大小的 DataFrame,并且你告诉 Spark 将其分成 8 个分区。因此,每个分区将为 20GB。现在,如果你的集群中有 10 个工作节点,每个节点总共有 16GB 内存,那么没有一个分区能完全适应单个节点的内存。我们最多能在内存中放入 16GB 的分区,其余 4GB 将被溢出到磁盘。

然而,如果我们将分区数增加到 10,那么每个分区将为 16GB —— 恰好能适应内存!了解分区对于理解磁盘溢出至关重要,也有助于更全面地理解 Spark。为 Spark 任务选择合适的分区数对于快速执行至关重要。

磁盘溢出的成本

磁盘溢出非常低效。Spark 不仅需要花时间将数据写入磁盘,还需要花费更多时间在需要数据时将其读回。这些读写操作是昂贵的,可能会对你的 Spark 应用产生重大影响。

性能影响 磁盘 I/O(读写)比内存访问显著慢,这可能导致作业完成时间变长。

资源利用 磁盘溢出可能导致资源的低效使用。本可以用于计算的 CPU 周期被浪费在读写操作上。

操作复杂性 频繁发生磁盘溢出的 Spark 应用程序可能更复杂。你不仅需要监控 CPU 和内存使用情况,还要监控磁盘使用情况,为你的操作考虑增加了另一层复杂性。

成本影响 在基于云的环境中,你通常会按使用的计算资源计费,包括存储、CPU、内存,有时还包括网络利用。如果磁盘溢出导致 Spark 任务运行变慢,你将需要更长时间运行云实例才能完成相同的工作,这会增加你的成本。

磁盘溢出的原因

造成内存不足进而导致磁盘溢出的常见场景有:

  1. 大数据集: 当处理的数据超过可用内存时,Spark 会将多余的数据溢出到磁盘。

  2. 复杂操作: 需要大量中间数据的任务,如连接、聚合和洗牌,如果执行内存不足,可能会导致磁盘溢出。

  3. 不适当的分区: 当你有太少的分区,而分区大小大于可用内存时,Spark 会将不适合的分区部分溢出到磁盘。

  4. 多个缓存的 DataFrames/RDDs: 如果你缓存了多个大型 DataFrames 或 RDDs,而存储内存已满,则最近最少使用的数据会被溢出到磁盘。

  5. 并发任务: 运行多个每个需要大量内存的任务可能会导致磁盘溢出,因为它们争夺有限的内存资源。

  6. 数据倾斜: 数据倾斜可能导致某些分区的数据远多于其他分区。负责这些“重”分区的工作节点可能会耗尽内存,迫使它们将多余的数据写入磁盘。

  7. 配置不足: 有时候,默认或用户定义的 Spark 配置没有为某些操作分配足够的内存,导致磁盘溢出。

识别磁盘溢出

识别磁盘溢出的最简单方法是通过 Spark UI。进入“Stages”选项卡,然后点击一个阶段。在下面的图片中,我按“Duration”排序阶段,并选择了持续时间最长的阶段。长时间运行不一定意味着磁盘溢出,但长时间运行的阶段通常是开始调查的好地方,因为这些阶段可能表示长时间的洗牌操作或数据倾斜。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片作者

在这里我们可以看到关于这个阶段的各种指标,包括磁盘溢出的量(如果有的话):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片作者

“溢出(内存)”显示了数据在溢出到磁盘之前的内存大小。而“溢出(磁盘)”则显示了溢出到磁盘后的数据大小,在溢出之后

“溢出(磁盘)”比“溢出(内存)”小的原因是数据写入磁盘时,会进行序列化和压缩。序列化是将数据对象转换为字节流,以便于存储或传输,而压缩则涉及减少数据大小,以节省存储空间或加快传输速度。

缓解磁盘溢出

一旦识别了磁盘溢出,下一步是缓解它。你如何处理磁盘溢出将取决于你的具体情况和造成溢出的原因。以下是针对常见磁盘溢出原因的一些一般建议。

了解根本原因 在采取任何措施来减轻磁盘溢出之前,你需要了解它发生的原因。使用 Spark UI 识别导致溢出的操作,查看“Stages”选项卡中的“Spill (Disk)”和“Spill (Memory)”等指标。一旦确定了根本原因,采取适当的解决方案。

有效地划分数据 有效的数据划分是最小化 Spark 中磁盘溢出的关键策略,特别是由于 shuffle 操作。Shuffle 是一种昂贵的操作,它会在分区间重新分配数据,并且通常需要大量的中间存储。如果无法在内存中存储这些中间数据,它将溢出到磁盘。更好的数据划分可以减少对 shuffle 的需求(即使没有磁盘溢出,shuffle 也是一种计算上昂贵的操作)。

通过优化数据的划分方式并减少在任务如连接或聚合过程中数据移动的需求,你可以降低磁盘溢出的风险。

你不能总是避免 shuffle,但你可以有效地划分数据。推荐的分区大小应小于 1GB——如果更大,可能会遇到长时间的 shuffle 和磁盘溢出。

有关优化 Spark 中分区 shuffle 的策略,请参见此指南:

## PySpark: 分区 shuffle 指南

通过采用有效的 shuffle 分区策略来提升你的 Spark 性能

medium.com

适当缓存数据 在 Spark 中缓存数据可以通过将最常访问的数据保留在内存中来显著加快迭代算法。然而,这是一把双刃剑。缓存过多的数据会迅速填满你的存储内存,减少执行内存的空间,并增加磁盘溢出的可能性。

知道何时缓存数据以及何时不缓存数据是至关重要的。选择性地缓存,并考虑缓存与重新计算数据的权衡。

想了解更多关于缓存的信息,请阅读这篇文章:

## 解锁更快的 Spark 操作:PySpark 中的缓存

在 Apache Spark 中弥合重计算与快速结果之间的差距

medium.com

解决数据倾斜 数据倾斜发生在数据不成比例地集中在少数几个分区中,导致集群内存使用不均衡。这可能导致磁盘溢出,因为那些过载的分区可能无法完全放入内存中。

像加盐这样的策略可以帮助更均匀地重新分配数据到各个分区,从而降低溢出的风险。

要了解如何解决数据倾斜并防止它导致磁盘溢出,请参见:

## 驯服 PySpark 中的数据倾斜:简单指南

处理 PySpark 中数据倾斜的策略和技术

medium.com

调整集群规模 向集群中添加更多内存可以帮助减少磁盘溢出,因为执行内存和存储内存有更多的操作空间。这是一个简单但昂贵的解决方案——它可以立即缓解内存压力,但会增加计算成本,具体是否值得取决于磁盘溢出的严重程度。

替代简单地增加集群内存的方法是启用动态扩展,这允许 Spark 根据需要添加或移除节点。这意味着当 Spark 需要更多内存时,它可以添加一个额外的工作节点,然后在不再需要时将其移除。

然而,最好是确定溢出的原因并使用适当的解决方案来解决它。如果这不可行,才考虑扩大你的集群——有时你确实需要更多内存。

结论

Spark 中的磁盘溢出是一个复杂的问题,可能会显著影响 Spark 应用程序的性能、成本和操作复杂性。了解它是什么、为何发生以及如何缓解是 Spark 开发者的重要技能。

在 Spark UI 中监视你的应用程序,并注意溢出情况。当你发现它时,诊断原因,然后你可以应用适当的解决方案,无论是对数据倾斜进行加盐处理还是对大规模洗牌操作进行重新分区。

可能很诱人直接增加集群内存或启用动态扩展,因为这些可以是快速的解决方案。然而,它们通常伴随着增加的成本。因此,识别磁盘溢出的根本原因并解决那个具体问题是很重要的。有关如何处理本文中讨论的特定磁盘溢出原因的更多信息,请阅读文中推荐的帖子。

通过采取积极的磁盘溢出管理方法,你可以确保你的 Spark 应用程序以尽可能高效的方式运行,从长远来看节省金钱和时间。

Meta AI 推出了突破性的图像分割模型,该模型基于 10 亿个掩码进行训练。

原文:towardsdatascience.com/meta-ai-introduces-revolutionary-image-segmentation-model-trained-on-1-billion-masks-8f13c86a13a2

Segment Anything - 最佳深度学习图像分割模型。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 古拉米·克雷特查什维利

·发表在 Towards Data Science ·7 分钟阅读·2023 年 4 月 6 日

介绍

在 OpenAI 的 ChatGPT 在自然语言处理领域取得革命性进展之后,人工智能的进步继续进行,Meta AI 也在计算机视觉领域取得了令人惊叹的进展。Meta AI 研究团队推出了名为 Segment Anything Model(SAM)的模型,并在 1100 万张图像上使用 10 亿个掩码的数据集。图像分割是识别哪些图像像素属于一个对象。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

由 ai.facebook.com 提供的图像分割演示

该项目主要包括三个支柱:任务模型数据

1. Segment Anything 任务

Meta AI 团队的主要目标是创建一个可以根据用户输入提示工作的图像分割模型,就像 ChatGPT 一样。因此,他们提出了将用户输入与图像集成以生成分割掩码的解决方案。分割提示可以是任何指示图像中要分割内容的信息。例如,前景或背景点的集合、框、自由形式的文本等。因此,模型的输出是给定任何用户定义提示的有效分割掩码。

2. Segment Anything 模型

可推广的 Segment Anything Model(SAM)有三个组件,如下图所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Segment Anything 模型工作流程由 ai.facebook.com 提供

高级模型架构由图像编码器提示编码器掩码解码器组成。对于图像编码器,他们使用了具有 Vision Transformer (ViT) [2] 架构的 MAE [1] 预训练模型。ViT 模型在图像分类和分割任务中是最先进的模型。至于提示,他们将其分为两种类型——一种是稀疏的提示,如点、框和文本,另一种是密集的提示,如掩码。提示编码器步骤为每种类型的提示创建嵌入。至于掩码解码器,它仅将图像嵌入、提示嵌入和输出令牌映射到掩码上。

3.2 Segment Anything 数据集

3.1 Segment Anything 数据引擎

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

垃圾进垃圾出(作者图像)

原则——垃圾进垃圾出——同样适用于 AI 领域。如果输入数据质量较差,则模型生成的结果也不会好。这就是为什么 Meta 团队试图选择高质量图像来训练他们的模型。该团队创建了一个数据引擎来筛选原始图像数据集。创建数据引擎分为三个阶段。

  1. 人工阶段:专业的人工标注员参与手动标注图像上的掩码。

  2. 半自动阶段:他们在标注的图像上训练了模型,并对其余图像进行了推断。然后,要求人工标注员标注模型未检测到的附加未标记对象,或纠正置信度低的分段。

  3. 完全自动阶段:这一阶段包括自动掩码生成和自动过滤阶段,试图保留非歧义掩码,并根据置信度、稳定性和大小保留掩码。

3.2 Segment Anything 数据集

Segment Anything 数据引擎创建了一个包含 10 亿个掩码的数据集(SA-1B),这些掩码基于 1100 万张多样化、高分辨率(平均 3300x4900 像素)和授权的图像。值得一提的是,99.1% 的掩码是自动生成的,但由于它们经过精心选择,质量非常高。

结论——为什么该模型具有革命性

Meta AI 团队与其他大型公司团队一起在 AI 发展方面取得了重大进展。Segment Anything 模型(SAM)具有为许多领域中的应用提供支持的能力,这些领域需要在任何图像中查找和分割任何对象。例如:

  • SAM 可能是一个大型多模态模型的组成部分,该模型集成了图像、文本、音频等。

  • SAM 可以基于用户的视线在 AR/VR 领域选择对象,然后将其“提取”到 3D 中。

  • SAM 可以提升创意应用,例如提取图像区域以进行视频编辑。

  • 还有更多。

图像分割演示

在这一部分,我将尝试使用官方 GitHub 代码来玩转算法,并使用Google Colab对图像进行两种类型的分割。首先,我将进行用户定义提示的分割,其次,我将进行完全自动的分割。

第一部分:使用用户定义提示进行图像分割

  1. 设置(导入库和安装)
from IPython.display import display, HTML
import numpy as np
import torch
import matplotlib.pyplot as plt
import cv2

display(HTML(
"""
<a target="_blank" href="https://colab.research.google.com/github/facebookresearch/segment-anything/blob/main/notebooks/predictor_example.ipynb">
  <img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/>
</a>
"""
))

using_colab = True

if using_colab:
    import torch
    import torchvision
    print("PyTorch version:", torch.__version__)
    print("Torchvision version:", torchvision.__version__)
    print("CUDA is available:", torch.cuda.is_available())
    import sys
    !{sys.executable} -m pip install opencv-python matplotlib
    !{sys.executable} -m pip install 'git+https://github.com/facebookresearch/segment-anything.git'

    !mkdir images
    !wget -P images https://raw.githubusercontent.com/facebookresearch/segment-anything/main/notebooks/images/truck.jpg
    !wget -P images https://raw.githubusercontent.com/facebookresearch/segment-anything/main/notebooks/images/groceries.jpg

    !wget https://dl.fbaipublicfiles.com/segment_anything/sam_vit_h_4b8939.pth

2. 辅助函数用于在图像上绘制掩码、点和框。

def show_mask(mask, ax, random_color=False):
    if random_color:
        color = np.concatenate([np.random.random(3), np.array([0.6])], axis=0)
    else:
        color = np.array([30/255, 144/255, 255/255, 0.6])
    h, w = mask.shape[-2:]
    mask_image = mask.reshape(h, w, 1) * color.reshape(1, 1, -1)
    ax.imshow(mask_image)

def show_points(coords, labels, ax, marker_size=375):
    pos_points = coords[labels==1]
    neg_points = coords[labels==0]
    ax.scatter(pos_points[:, 0], pos_points[:, 1], color='green', marker='*', s=marker_size, edgecolor='white', linewidth=1.25)
    ax.scatter(neg_points[:, 0], neg_points[:, 1], color='red', marker='*', s=marker_size, edgecolor='white', linewidth=1.25) 

3. 输入图像(初始图像进行分割)。让我们尝试选择第一袋食品的掩码。

image = cv2.imread('/content/images/groceries.jpg')
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) 
plt.figure(figsize=(5,5))
plt.imshow(image)
plt.axis('on')
plt.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

输入图像(图像来自 Facebook 研究)

4. 加载名为sam_vit_h_4b8939.pth的预训练模型,该模型为默认模型。还有其他更轻量的模型版本,如sam_vit_l_0b3195.pthsam_vit_b_01ec64.pth

sam_checkpoint = "/content/sam_vit_h_4b8939.pth"
device = "cuda"
model_type = "default"

import sys
sys.path.append("..")
from segment_anything import sam_model_registry, SamPredictor

sam = sam_model_registrymodel_type
sam.to(device=device)

predictor = SamPredictor(sam)

predictor.set_image(image)

5. 可视化图像上的点(用户提示),这将有助于识别我们的目标对象 — 第一个食品袋。

input_point = np.array([[465, 300]])
input_label = np.array([1])
plt.figure(figsize=(10,10))
plt.imshow(image)
show_points(input_point, input_label, plt.gca())
plt.axis('on')
plt.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

带用户提示的输入图像(图像来自 Facebook 研究)

6. 进行预测以生成目标对象的掩码。

masks, scores, logits = predictor.predict(
    point_coords=input_point,
    point_labels=input_label,
    multimask_output=True,
)
print(masks.shape)  # (number_of_masks) x H x W

7. 显示前 3 个生成的掩码。当multimask_output=True时,算法返回三个掩码。稍后我们可以选择分数最高的一个。

for i, (mask, score) in enumerate(zip(masks, scores)):
    plt.figure(figsize=(10, 10))
    plt.imshow(image)
    show_mask(mask, plt.gca())
    show_points(input_point, input_label, plt.gca())
    plt.title(f"Mask {i+1}, Score: {score:.3f}", fontsize=18)
    plt.axis('off')
    plt.show() 

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

预测结果(图像由作者提供)

突出的对象是模型预测的掩码。结果显示,模型生成了三个输出掩码,预测分数分别为:掩码 1 — 0.990,掩码 2 — 0.875 和掩码 3 — 0.827。我们选择了分数最高的掩码 1。瞧!!!模型预测的掩码就是我们最初想要分割的目标对象。结果令人惊讶,模型表现得相当好!

第二部分:完全自动的图像分割 — 续

  1. 分段的绘图函数
def show_anns(anns):
    if len(anns) == 0:
        return
    sorted_anns = sorted(anns, key=(lambda x: x['area']), reverse=True)
    ax = plt.gca()
    ax.set_autoscale_on(False)
    polygons = []
    color = []
    for ann in sorted_anns:
        m = ann['segmentation']
        img = np.ones((m.shape[0], m.shape[1], 3))
        color_mask = np.random.random((1, 3)).tolist()[0]
        for i in range(3):
            img[:,:,i] = color_mask[i]
        ax.imshow(np.dstack((img, m*0.35)))

2. 自动生成掩码

from segment_anything import sam_model_registry, SamAutomaticMaskGenerator, SamPredictor

sam = sam_model_registrymodel_type
sam.to(device=device)

mask_generator = SamAutomaticMaskGenerator(sam)

masks = mask_generator.generate(image)
print(len(masks))

3. 显示结果

plt.figure(figsize=(5,5))
plt.imshow(image)
show_anns(masks)
plt.axis('off')
plt.show() 

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

SAM 的自动分割结果(图像由作者提供)

算法使用默认参数识别了 137 个不同的对象(掩码)。每个掩码包含关于分段区域、边界框坐标、预测分数和稳定性分数的信息,这些信息可以用来过滤掉不需要的分段。

希望你喜欢这篇文章,并且现在可以开始自己创建美丽的应用程序了。如果你有任何问题或想分享对这篇文章的看法,请随时评论,我会很高兴回答。

如果你想直接支持我的工作并且获得 Medium 文章的无限访问权限,请通过我的 推荐链接 成为 Medium 会员。在此,万分感谢,祝你有美好的一天!

[## 通过我的推荐链接加入 Medium - Gurami Keretchashvili

阅读 Gurami Keretchashvili(以及 Medium 上成千上万其他作者)的每一个故事。你的会员费直接…

medium.com](https://medium.com/@gkeretchashvili/membership?source=post_page-----8f13c86a13a2--------------------------------)

参考文献

[1] Kaiming He, Xinlei Chen, Saining Xie, Yanghao Li, Piotr Dollar, 和 Ross Girshick. 掩蔽自编码器是可扩展的视觉学习者. CVPR, 2022.

[2] Alexey Dosovitskiy, Lucas Beyer, Alexander Kolesnikov, Dirk Weissenborn, Xiaohua Zhai, Thomas Unterthiner, Mostafa Dehghani, Matthias Minderer, Georg Heigold, Sylvain Gelly, Jakob Uszkoreit, 和 Neil Houlsby. 一张图胜过 16x16 个词:大规模图像识别的变换器. ICLR, 2021.

[3] Alexander Kirillov, Eric Mintun, Nikhila Ravi, Hanzi Mao, Chloe Rolland, Laura Gustafson, Tete Xiao, Spencer Whitehead, Alexander C. Berg, Wan-Yen Lo, Piotr Dollar, Ross Girshick. Segment Anything, 2023

我之前关于机器学习部署的文章

## 如何部署机器学习模型?端到端狗品种识别项目!

在网络上部署你的机器学习模型的最简单方法。

towardsdatascience.com ## 如何部署机器学习模型

在网络上部署机器学习模型的最简单方法

towardsdatascience.com

Meta AI 的另一个革命性大规模模型——DINOv2 用于图像特征提取。

原文:towardsdatascience.com/meta-ais-another-revolutionary-large-scale-model-dinov2-for-image-feature-extraction-1114b287eadd

DINOv2 是一种出色的自监督 ViT 基于深度学习模型,用于图像特征提取。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Gurami Keretchashvili

·发表于 Towards Data Science ·阅读时间 8 分钟·2023 年 6 月 26 日

介绍

Meta AI 介绍了图像特征提取模型的新版本 DINOv2,该模型自动从图像中提取视觉特征。这是 AI 领域,特别是在计算机视觉领域的数据和模型扩展方面的又一步革命性进展。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

DINOv2 的演示由 ai.facebook.com 提供

动机——我们为什么要关注?

DINOv2 是一个自监督模型,无需微调且性能良好。此外,它还可以作为许多计算机视觉任务的主干网络,例如:

  • 分类,细粒度分类——例如猫与狗,或例如狗品种识别

  • 图像检索——例如,从互联网上大量图像中找到与您的包相似的图像。

  • 语义图像分割——为图像中的每一个像素关联标签或类别。

  • 视频理解——自动识别和解释视频的各种方面,如对象、动作、事件、场景,甚至更高级的概念。

  • 单目深度估计——预测图像中一个物体是位于前景还是背景。

  • 图像聚类——将图像分组到簇中,使得同一簇中的图像彼此相似

  • 基于内容的推荐系统——根据图像的表示向用户推荐项目。

DINOv2 补充了另一项近期计算机视觉研究,包括 Segment Anything。Segment Anything 是一个可提示的分割系统,专注于对多样化的分割任务进行零-shot 泛化。

你可以查看我之前的帖子中的 Segment Anything Model (SAM)。

## Meta AI 推出基于 10 亿个掩膜训练的革命性图像分割模型

Segment Anything Model (SAM) - 最佳深度学习图像分割模型

towardsdatascience.com

方法论

论文的主要贡献可以是以下几点:

  • 创建一个大型整理的训练数据集

  • 改进训练算法和实现

  • 设计一个功能性的蒸馏管道。

创建一个大型整理的训练数据集

大型深度学习模型需要大量的数据进行训练。这就是为什么作者创建了一个自动化流程,如下图所示,以获取整理的训练数据集。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

整理图像创建的工作流程 [1]

他们从大约 25 个第三方数据集中选择了一组种子图像,并且他们的目标是增强这些种子图像。其工作原理如下。他们从互联网上抓取了大量未经整理的图像(约 12 亿张独特图像)。之后,他们使用在 ImageNet-22k 上预训练的自监督 ViT-H/16 网络创建了图像嵌入。其次,他们使用余弦相似度作为图像间的距离度量,以过滤重复图像,从而减少冗余并增加多样性。在从大规模未整理数据集中移除重复图像后,他们进行了图像检索阶段,其中提取了与整理图像相似的图像。最终,这种方法使他们能够从 12 亿张未整理的图像数据库中创建出 1.42 亿张整理图像。

改进的训练算法

DINOv2 使用了学生-教师机制,这是一种训练技术,其中一个较小的神经网络(称为学生)学习模仿一个较大或更复杂的神经网络(称为教师)的行为。学生和教师基于视觉变换器架构(ViT)[2]。至于损失函数,他们使用交叉熵损失来计算学生-教师特征的相似性。为了学习图像的局部和全局特征,他们使用了不同层次的学习。对于全局学习,他们使用的是图像层次学习——对同一图像进行随机裁剪数据增强。至于局部特征学习,他们使用了补丁层次学习——随机对输入补丁应用遮罩,仅对学生应用,不对教师应用。此外,他们还进行了不同的归一化技术,如 Sinkhorn-knop 批归一化等。更多细节可以在论文中找到。

蒸馏管道。

使用大型模型进行预测(推理)时需要强大的硬件。为了克服这一限制,他们还将大型模型压缩为较小的模型。知识蒸馏 [5] 旨在通过最小化一组给定输入的两个输出之间的距离来用较小的模型重现大型模型的输出。训练算法基于自蒸馏,使得将大型模型压缩为较小模型变得简单。

结果

他们在八个不同的计算机视觉任务上评估了模型性能,并与其他方法进行了比较。

在下面的图表中,DINOv2 模型的结果为深蓝色,其他自监督方法为浅橙色,弱监督方法则用深粉色突出显示。虚线水平线表示表现最佳的弱监督模型。

结果表明,DINOv2 模型在自监督学习领域大幅超越了之前的最先进技术,达到了与弱监督特征相当的性能。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

DINOv2 与其他 SOTA 模型 [1]

结论

总之,DINOv2 是 Meta AI 团队推出的另一个革命性模型。它无需微调,可以作为许多不同计算机视觉模型的基础。DINOv2 使用自监督机制,能够从任何图像集合中学习。

DINOv2 演示 — 细粒度图像分类

在这一部分,我将尝试展示 DINOv2 在实际场景中的工作原理。我将创建一个细粒度图像分类任务。

分类工作流程:

  • 从 PyTorch 数据集中下载 Food101 数据集。

  • 使用小型 DINOv2 从训练和测试数据集中提取特征

  • 使用从训练数据集中提取的特征训练机器学习分类模型(SVM、XGBoost 和 KNN)。

  • 对测试数据集提取的特征进行预测。

  • 评估每个机器学习模型的准确率和 F1 分数。

数据Food 101 是一个具有挑战性的 101 个食品类别的数据集,共有 101,000 张图像。每个类别提供 250 张手动审核的测试图像以及 750 张训练图像。

模型:小型 DINOv2 模型(ViT-S/14 蒸馏版)

机器学习模型:SVM、XGBoost、KNN。

步骤 1 — 设置(你可以使用 Google Colab 来运行代码并开启 GPU)

import torch
import numpy as np
import torchvision
from torchvision import transforms
from torch.utils.data import Subset, DataLoader
import matplotlib.pyplot as plt
import time
import os
import random
from tqdm import tqdm

from xgboost import XGBClassifier
from sklearn.svm import SVC
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score, f1_score
import pandas as pd

def set_seed(no):
    torch.manual_seed(no)
    random.seed(no)
    np.random.seed(no)
    os.environ['PYTHONHASHSEED'] = str()
    torch.backends.cudnn.benchmark = False
    torch.backends.cudnn.deterministic = True

set_seed(100)

步骤 2 — 创建转换,下载并创建 Food101 Pytorch 数据集,创建训练和测试数据加载器对象。

batch_size = 8

transformation = transforms.Compose([
        transforms.Resize(256),
        transforms.CenterCrop(224),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ])

trainset = torchvision.datasets.Food101(root='./data', split='train',
                                        download=True, transform=transformation)

testset = torchvision.datasets.Food101(root='./data', split='test',
                                       download=True, transform=transformation)

# train_indices = random.sample(range(len(trainset)), 20000)
# test_indices = random.sample(range(len(testset)), 5000)

# trainset = Subset(trainset, train_indices)
# testset  = Subset(testset, test_indices)

trainloader = torch.utils.data.DataLoader(trainset, batch_size=batch_size,
                                          shuffle=True)

testloader = torch.utils.data.DataLoader(testset, batch_size=batch_size,
                                         shuffle=False)

classes = trainset.classes

print(len(trainset), len(testset))
print(len(trainloader), len(testloader))

[输出] 75750 25250

[输出] 9469 3157

步骤 3(可选) — 可视化训练数据加载器批次

# Get a batch of images
dataiter = iter(trainloader)
images, labels = next(dataiter)

# Plot the images
fig, axes = plt.subplots(1, len(images),figsize=(12,12))
for i, ax in enumerate(axes):
    # Convert the tensor image to numpy format
    image = images[i].numpy()
    image = image.transpose((1, 2, 0))  # Transpose to (height, width, channels)

    # Normalize the image
    mean = [0.485, 0.456, 0.406]
    std = [0.229, 0.224, 0.225]
    normalized_image = (image * std) + mean
    # Display the image
    ax.imshow(normalized_image)
    ax.axis('off')
    ax.set_title(f'Label: {labels[i]}')

# Show the plot
plt.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

批量图像

步骤 4 — 加载小型 DINOv2 模型并从训练和测试数据加载器中提取特征。

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
dinov2_vits14 = torch.hub.load('facebookresearch/dinov2', 'dinov2_vits14').to(device)

#training
train_embeddings = []
train_labels = []

dinov2_vits14.eval()
with torch.no_grad():
  for data, labels in tqdm(trainloader):
    image_embeddings_batch = dinov2_vits14(data.to(device))

    train_embeddings.append(image_embeddings_batch.detach().cpu().numpy())
    train_labels.append(labels.detach().cpu().numpy())

#testing
test_embeddings = []
test_labels = []

dinov2_vits14.eval()
with torch.no_grad():
  for data, labels in tqdm(testloader):
    image_embeddings_batch = dinov2_vits14(data.to(device))

    test_embeddings.append(image_embeddings_batch.detach().cpu().numpy())
    test_labels.append(labels.detach().cpu().numpy())

#concatinate result
train_embeddings_f = np.vstack(train_embeddings)
train_labels_f = np.concatenate(train_labels).flatten()

test_embeddings_f = np.vstack(test_embeddings)
test_labels_f = np.concatenate(test_labels).flatten()

train_embeddings_f.shape, train_labels_f.shape, test_embeddings_f.shape, test_labels_f.shape

[输出] ((75750, 384), (75750,), (25250, 384), (25250,))

步骤 5 — 为 SVM、XGBoost 和 KNN 分类器构建一个函数。

def evaluate_classifiers(X_train, y_train, X_test, y_test):
    # Support Vector Machine (SVM)
    svm_classifier = SVC()
    svm_classifier.fit(X_train, y_train)
    svm_predictions = svm_classifier.predict(X_test)

    # XGBoost Classifier
    xgb_classifier = XGBClassifier(tree_method='gpu_hist')
    xgb_classifier.fit(X_train, y_train)
    xgb_predictions = xgb_classifier.predict(X_test)

    # K-Nearest Neighbors (KNN) Classifier
    knn_classifier = KNeighborsClassifier()
    knn_classifier.fit(X_train, y_train)
    knn_predictions = knn_classifier.predict(X_test)

    # Calculating Top-1
    top1_svm = accuracy_score(y_test, svm_predictions)
    top1_xgb = accuracy_score(y_test, xgb_predictions)
    top1_knn = accuracy_score(y_test, knn_predictions)

    # Calculating F1 Score
    f1_svm = f1_score(y_test, svm_predictions, average='weighted')
    f1_xgb = f1_score(y_test, xgb_predictions, average='weighted')
    f1_knn = f1_score(y_test, knn_predictions, average='weighted')

    return pd.DataFrame({
        'SVM': {'Top-1 Accuracy': top1_svm, 'F1 Score': f1_svm},
        'XGBoost': {'Top-1 Accuracy': top1_xgb,'F1 Score': f1_xgb},
        'KNN': {'Top-1 Accuracy': top1_knn, 'F1 Score': f1_knn}
    })

X_train = train_embeddings_f  # Training data features
y_train = train_labels_f  # Training data labels
X_test = test_embeddings_f   # Test data features
y_test = test_labels_f   # Test data labels

results = evaluate_classifiers(X_train, y_train, X_test, y_test)
print(results)

结果

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

小型 DINOv2 + SVM/XGBoost/KNN 的结果(图片由作者提供)

哇,结果真棒!正如展示的那样,基于小型 DINOv2 提取特征训练的 SVM 模型优于其他机器学习模型,达到了近 90%的准确率。

结论

尽管我们使用了小型 DINOv2 模型提取特征,但在提取特征上训练的机器学习模型(尤其是 SVM)在细粒度分类任务上表现出色。该模型能够在 101 个不同类别中以接近 90%的准确率进行分类。

如果使用大型、超大或巨型 DINOv2 模型,准确率会提高。你只需在第 4 步将dinov2_vits14替换为dinov2_vitb14dinov2_vitl14dinov2_vitg14。你可以尝试一下,欢迎在评论区分享准确率结果 😃

希望你喜欢这篇文章。如果你有任何问题或想分享对这篇文章的看法,请随时评论,我将很高兴回答。

如果你想直接支持我的工作,并且获得 Medium 文章的无限访问权限,请使用我的推荐链接成为 Medium 会员。非常感谢,祝你有美好的一天!

[## 使用我的推荐链接加入 Medium - Gurami Keretchashvili

作为 Medium 会员,你的一部分会员费用会分配给你阅读的作者,你可以完全访问每一篇故事……

medium.com](https://medium.com/@gkeretchashvili/membership?source=post_page-----1114b287eadd--------------------------------)

参考文献

[1] Oquab, M., Darcet, T., Moutakanni, T., Vo, H., Szafraniec, M., Khalidov, V., … & Bojanowski, P. (2023). Dinov2: 在没有监督的情况下学习稳健的视觉特征。arXiv 预印本 arXiv:2304.07193

[2] Dosovitskiy, A., Beyer, L., Kolesnikov, A., Weissenborn, D., Zhai, X., Unterthiner, T., … & Houlsby, N. (2020). 一张图片值 16x16 个词:用于大规模图像识别的 Transformers。arXiv 预印本 arXiv:2010.11929

[3] DINOv2 团队,DINOv2: 具有自监督学习的最先进计算机视觉模型

[4] DINOv2 Github

[5] Hinton, G., Vinyals, O., & Dean, J. (2015). 提炼神经网络中的知识。arXiv 预印本 arXiv:1503.02531

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值