TowardsDataScience 2023 博客中文翻译(三百零九)

原文:TowardsDataScience

协议:CC BY-NC-SA 4.0

工程经理应了解的生产力五维度

原文:towardsdatascience.com/the-5-dimensions-of-productivity-all-engineering-managers-should-know-2c26698208d0

通过 SPACE 框架将你的开发团队的生产力提升到新高度

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

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

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

作者提供的图片

作为工程经理,我们在职业生涯中的某个阶段都曾被要求衡量团队的生产力;因此,我们对其复杂性有了清晰的理解。软件开发并不是一个简单的生产线,开发者无法不断且无故障地生产和部署软件。它是一个复杂的过程,需要创造性的问题解决,涉及许多变量,包括不断变化的业务需求、技术进步以及团队内部和跨团队的协作需求。

经典的度量标准通常专注于输出。脑海中浮现的两个例子是:编写的代码行数或交付的功能数量。然而,质量是对数量的必备补充。例如,一个复杂的解决方案可能会比一个干净且设计良好的解决方案包含更多的行数。同样,简单功能的上市时间可能会比更复杂的需求要短,这些复杂需求在实际业务中可能有更大的影响。

尽管仅仅通过 KPI 来衡量生产力是不够的,但完全不衡量生产力也是一场灾难。彼得·德鲁克的名言*“如果你无法衡量它,你就无法改进它”*在这里非常相关。

那么,正确的平衡是什么?

由 GitHub、维多利亚大学和微软的研究人员提出,SPACE提供了一个实用且多维的开发者生产力视角,提出了一种新方法,引导领导者衡量和改善影响输出的因素,而不是仅仅关注这些输出。

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

图片来源 | SPACE 首字母缩略词

通过对齐业务目标Performance)、开发人员的福祉SatisfactionCollaboration)以及软件开发的技术方面ActivityEfficiencyCollaboration),SPACE 框架帮助工程经理创建一个积极的工作环境,提升生产力,并使他们能够做出明智的决策,从而实现持续改进。

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

图片来源 | 对齐业务、人员与工程

让我们进一步探讨这些维度,并展示一些可以与之关联的 KPI。

S — 满意度与福祉

满意度是衡量开发人员对任务和所用过程的满足感和投入度的指标。福祉则反映了他们是否有健康的工作习惯。随着倦怠对个人心理健康以及团队士气和高质量工作交付能力的负面影响日益显著,这一维度变得越来越重要。管理开发人员的福祉有助于建立能够实现长期可持续生产力的韧性团队。

**📍 如何衡量**

‣ 在 1 对 1 会议中直接询问你的团队:他们是否感到被欣赏?他们是否有完成工作所需的工具?开发实践是否足够(PR、CI/CD 流水线等)?他们会推荐你的团队给其他人吗?

‣ 平衡:是否有些成员比其他成员更忙?所有成员是否在同样有影响力的功能上工作?

‣ 缺勤/离职率。

**🌟 如何改进**

‣ 寻求自动化。

‣ 平均分配工作。

‣ 提供成长机会。

‣ 分享业务影响。

P — 性能

软件开发中的性能不仅仅是输出,还包括最终结果。代码质量、客户价值和业务影响等因素在确定性能时发挥作用,这使得将性能归因于单个开发人员变得具有挑战性,因为开发通常是团队合作的结果。因此,性能应视为系统或过程的结果,跟踪性能的最佳方法是通过测量结果。

**📍 如何衡量**

‣ 质量:缺陷的缺失、可靠性、变更失败率以及整体服务健康状况。

‣ 影响:客户满意度、系统采纳、功能使用、成本减少、时间节省。

**🌟 如何改进**

‣ 实施可观察性,以全面了解系统的行为。

‣ 根据最佳实践审查 CI/CD 流水线。

‣ 高效开展回顾会议。

A — 活动

开发者的活动指的是在工作时间内完成的输出或行动的数量。工程经理可以获得有价值但有限的生产力见解,因为这些活动中有些是难以衡量的。例如,团队会议、指导、调试、设置新环境和编写不代表功能区域的单元测试。因此,这一维度不能孤立使用,应始终与定性信息和其他维度的指标平衡。

**📍 如何衡量**

‣ 设计与开发**😗* 工作任务数量、拉取请求、提交、代码更改、代码审查和设计文档。

‣ CI/CD:构建次数、测试用例、测试自动化、部署/发布。

‣ 运营:事件/问题数量、未解决与已解决的票据、按严重程度分配的问题、事件缓解。

**🌟 如何改善**

‣ 消除障碍,让开发者花更少的时间在非编码任务上。

‣ 实施强健的事件管理系统,以便快速响应操作事件并减少停机时间。

C — 协作与沟通

这个 SPACE 维度对捕捉团队如何协作以及团队成员之间是否有优化的信息流至关重要。一个透明文化的团队可能因对优先级和其他工作有更高的意识,从而更具生产力,这有助于更好的依赖协调。此外,团队内及跨团队的信息流显著影响文档的可发现性,这对工作的一致性和整合至关重要。

**📍 如何衡量**

‣ 会议指标:质量、频率和效果。

‣ 文档:可访问性、组织性和可发现性。

‣ PRs:审查速度、首次审查时间和反馈质量。

‣ 为新开发者提供的入职时间。

**🌟 如何改善**

‣ 鼓励配对编程。

‣ 通过让更多人参与特性开发来避免孤岛效应。

‣ 更新维基文档,作为‘完成’定义的一部分。

‣ 培养 DocOps 文化:在 CI 管道中自动化文档编写,减少对手动文档编写的依赖。

‣ 提供定期的团队检查机会(但不要过多)。

E — 效率与流动

开发者的生产力与他们在没有干扰的情况下完成高质量工作的数量直接相关。所有开发者的终极幸福就是在工作日内保持流动状态。然而,最小化干扰以提高效率可能导致协作减少、脑力风暴机会减少,从而影响创意和推动项目前进的突破,因此平衡在这里至关重要。

**📍 如何衡量**

‣ 吞吐量:单位时间内完成的任务数量。

‣ 干扰:干扰的数量、频率、时机和间隔。

‣ 团队之间的交接数量表明可能发生延迟的地方。

‣ 从提交到生产的变更交付时间。

**🌟 如何改进**

‣ 优先考虑 DevOps。

‣ 最小化上下文切换。

‣ 鼓励“制作时间”。

‣ 定期召开回顾会议,识别价值流中的低效区域。

为什么这很重要?

SPACE 框架通过将开发者置于核心位置,对工程生产力进行全面解读。它确保所有影响开发者工作体验的因素都被考虑到,并给予同等重要性。它还强调持续改进,与日本的 Kaizen 实践相一致,认识到即使是微小的渐进改进也能对整体生产力和成功产生重大影响。

开发者生产力并不是一个“禁忌”,当它因正确的理由被跟踪时,它会成为团队的动力,每个人都明白优化正确的指标最终会导致更快乐的团队。

进一步资源:

‣ 原版 SPACE 论文研究。

加速 书籍。

‣ SPACE 视频演讲

谢谢阅读!

P.S. 你是否尝试过多次点击鼓掌按钮,看看会发生什么?❤️

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

作者提供的图片 | SPACE

我在 Medium 上定期写关于领导力、技术和数据的文章 —— 如果你想阅读我未来的文章,请 ‘关注’我*!

我的新书《技术智慧》现已上市 ——* 看看

5 种高效查找和解决数据问题的方法

原文:towardsdatascience.com/the-5-efficient-ways-to-find-and-resolve-data-issues-318e294f2e3a

揭示隐藏的异常和不一致性

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

·发表于 Towards Data Science ·6 min read·2023 年 6 月 16 日

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

图片由 Pierre Bamin 提供,来源于 Unsplash

根据 Gartner 调查,近 60%的组织没有衡量低质量数据的年度财务成本。我认为其他 40%的人在掩饰事实。根据我的经验,尽管数据质量问题每天都影响到组织,但这些损失很少被量化。

我认为我们当前的状态不是因为缺乏尝试,而是因为我们不知道从何开始。像坏习惯一样,尝试一次性解决所有问题或进行一年的项目将导致失败。需要有责任制、明确的流程以及一些技术帮助的文化转变。

今天,我们将深入探讨五种查找和解决问题的方法。开始吧!

1. 审核来自源系统的数据

和大多数大型组织一样,如果你有老旧的源系统在向你的数据仓库/湖提供信息,那么你就会知道源数据是一个大问题。

如果系统较旧,可能不灵活接受变更。在这种情况下,当数据被接收或在数据仓库中暂存时,应用重复性检查和对账检查将确保你在问题污染更广泛的数据资产之前发现它们。

一旦发现问题,你可以拒绝这些有问题的记录进一步流动,或者在管道设计中处理这个问题。只要你知道数据问题的存在,你就可以提醒用户,从而避免做出错误的决策。

例如,当您从来源接收到客户数据文件时,建议执行完整性检查。这将确保诸如 last_name、date_of_birth 和 address 等重要字段已完全填写。如果数据缺失,建议将这些记录从分析中剔除。或者,您可以为缺失的信息添加默认记录。例如,您可以将 01/01/1800 添加为默认出生日期,因为这将帮助您识别缺乏关键信息的记录,从而在分析过程中做出更好的决策。

2. 修复现有表中的数据问题

随着时间的推移,由于缺乏治理流程,数据质量会恶化。一些键被重复使用,重复信息被添加,或应用的补丁使情况更糟。

一个简单的数据概况可以提供给定表中数据的当前状态。现在——专注于这些问题的核心属性/列。关键是尽可能隔离问题。一旦确定了属性,应用一次性修复。例如,如果数据重复,与数据管理员达成一致以获得单一记录。或者,如果数据不准确,例如出生日期、开始和结束日期等,则达成正确的替代方案并应用修复。

一旦修复完成,您必须将此过程投入生产,以避免数据质量进一步恶化。这个清理作业可以每天运行,通过执行更新语句来修复数据。或者,可能需要最终用户通过评估审计表进行人工干预。

例如,如果您的客户数据表中有重复的客户记录,您可以使用数据质量工具对数据进行分析。这将帮助您识别重复项并确定它们发生的原因。这些重复项可能是由于来源发送了相同的信息多次、数据管道代码质量差或业务流程问题造成的。一旦确定了重复项及其根本原因,您可以合并记录或删除冗余记录。如果您无法解决根本原因,可以设置一个清理作业,定期执行重复检查、匹配客户、合并记录并删除冗余记录(主数据管理)。

3. 重新创建设计不良的数据管道

数据问题有时可能源于设计不良或效率低下的数据管道。通过重新评估和重建这些管道,您可以改善数据流、转换和集成过程。

设计不良的管道可能会受到瓶颈的影响,从而减缓数据的及时处理,或者复杂的数据转换和集成过程可能引入错误和不一致。分析管道对于隔离问题和应用修复至关重要。

对于瓶颈问题,管道可以重新设计为在多个节点上执行;对于数据转换问题,管道可以拆解为不同的阶段(避免冗余连接、多次查询大型表等),以减少整体复杂性。

例如,如果您在处理客户数据表时遇到较长的更新时间,通过拆解管道组件来评估其性能会很有帮助。经过仔细检查,您会发现管道设计由于依赖多个表、参考查找和生成主记录输出而变得复杂。为了提高性能和隔离问题,建议设计和测试每个管道组件。这个过程可能会揭示出某些表的连接比预期的时间更长。这时,您可以检查表格,确定是否由于连接设计执行了笛卡尔(交叉)连接或因读取次数多。确定问题后,进一步拆解并删除那些连接,或创建其他中间表来简化管道。

4. 利用数据可视化仪表板

解决问题的难点在于首先发现它们。您将听到供应商关于他们的技术如何是下一个能单独解决数据问题的最佳选择的常见说辞。事实是,您需要一个地方来可视化这些问题。

一个简单的数据概况和一个更简单的仪表板显示异常值、缺口、不一致性和偏斜度就能解决问题。通过散点图显示客户交易金额随时间的变化,您可以轻松识别出异常大的交易数据点。

线图显示的每日网站流量中突然下降或零活动期可能表示缺失的数据点或剧烈的数据变化。

例如,如果您的表格中存在不完整的客户数据,请考虑使用可视化仪表板来突出显示如出生日期等特定列中的 NULL 值。日常条形图可以跟踪这一属性,并检测数据中的任何突发变化,如下所示。

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

图片由作者提供

5. 机器学习用于检测和解决问题

随着自动化时代的发展,机器学习可以用来提高数据质量。通过在历史数据上训练模型,机器学习算法可以学习模式和异常,从而实现数据问题的自动识别和解决。

机器学习还可以通过识别和修正常见数据问题来自动化数据清理过程。例如,模型可以填补缺失值、修正格式错误或标准化不一致的数据。

例如,可以使用历史客户数据表训练集来创建异常检测模型。该模型根据训练数据的分布和统计特性学习正常出生日期的模式和特征。模型使用训练数据为“出生日期”列建立一个正常性阈值。这个阈值通常基于训练数据集中观察到的出生日期的均值、标准差或范围等统计指标。模型在异常检测阶段评估新的客户记录,并将其出生日期与已建立的正常性阈值进行比较。如果某个出生日期超出了阈值或明显偏离了预期模式,它将被标记为异常。

结论

投资于解决数据问题将对你所有的下游分析和 AI 应用案例带来回报。输入垃圾会导致输出垃圾。这五种方法应该能帮助你开始修复数据问题的旅程。

但是,如果你想学习如何实施数据质量的所有核心方面,请查看我的免费终极数据质量手册点击这里获取)。通过领取你的副本,你还将成为我们教育社区的一部分,通过我们的邮件列表获得宝贵的见解和更新

## 终极数据质量手册 - 免费!

介绍《终极数据质量手册:完美数据实践》在当今数据驱动的世界中……

hanzalaqureshi.gumroad.com

如果你还没有订阅 Medium,考虑使用我的推荐链接订阅。它比 Netflix 便宜,而且客观上更值得你的时间。 如果你使用我的链接,我将获得少量佣金,而你可以无限制地阅读 Medium 上的故事,两全其美。

可信赖的 LLM 测试的 5 个支柱

原文:towardsdatascience.com/the-5-pillars-of-trustworthy-llm-testing-846c0b305059?source=collection_archive---------7-----------------------#2023-11-20

生成 AI 使用与测试研究的第四部分

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

·

阅读 发表在 Towards Data Science ·9 分钟阅读·2023 年 11 月 20 日

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

图片来源 Yasmine DuchesneUnsplash

大型语言模型(LLMs)已经进入了各行各业的工作者手中,科技公司领导的思维中,以及每个学习环境中的学生心中。但有了强大的能力和更多的模型参数,就肩负了更大的责任。现在,公司、专业人士甚至学生日益关注的是如何判断 LLM 的失败时机和场景。

Kolena的机器学习工程师的角度来看,本文是系列讨论的延续,突出 LLM 的测试范式,识别 LLM 的高层次失败模式。

什么使得 LLM 不可信?

假设一个 LLM 收到了一位医生关于病人的长篇详细笔记以帮助推荐合适的药物。然而,如果 LLM 未能识别病人的过敏反应,LLM 输出的错误信息可能会导致生命危险的后果。

当 LLM 犯错或甚至产生虚假的信息时,通常被称为幻觉,其影响可能非常严重。在一个涉及谷歌 LLM Bard 的戏剧性案例中,幻觉让公司损失超过 1000 亿美元! 无论成本是一个人的健康还是公司的财务,发现 LLM 可能产生的幻觉至关重要。

那么,什么是可信赖的 LLM?在不同的使用场景下,用户对可信赖性的定义不同——例如,法官要求最小化偏见,作家则希望最大化生成质量。下面的图示展示了理解 LLM 行为的重要性。对于某些用户群体和通用应用,基础的 GPT 模型可能是一个很好的选择,但对于更高级的应用,基础 GPT 模型可能不再有效。也许更有意义的是为特定目的创建或微调 LLM,然后测试它们以验证其可信赖性。

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

可信赖 LLM 测试的五大支柱对比

评估整体 LLM 表现的因素有很多,不仅仅限于幻觉这一热门话题。LLM 可以非常灵活,因此它们自然有多种失败模式。从高层次来看,我们至少应考虑这五大支柱:

  1. 幻觉

  2. 偏见

  3. 推理

  4. 生成质量

  5. 模型机制

如果人们使用软件单元测试原则进行 ML 或 LLM 测试,测试这些支柱是简单的。例如,开发者可以使用类似于TruthfulQA的数据集来识别幻觉的存在。生成质量可以通过情感分析或可读性指标来量化。最终,评估 LLM 表现的方式因目的不同而有所变化,因此需要为每个支柱设置自定义评估流程。

幻觉

对于某些用户来说,LLM 的有效性和准确性至关重要。因此,LLM 测试的第一支柱是幻觉。幻觉是指 LLM 的输出与现实世界事实不符。这种情况发生是因为 LLM 是生成型代理,旨在产生令人印象深刻和愉悦的结果。如果它们无法回忆正确的信息作为背景来生成答案,它们就不能绝对真实,并会增加信息以填补空白。

幻觉是 LLM 测试的第一支柱,因为用户在执行常见的自然语言处理任务或在大规模询问与 STEM(科学、技术、工程和数学)领域相关的问题时,可能不会注意到 LLM 的不真实性。对于小众应用,如涉及法律或医疗领域的高级用例,幻觉可能更为常见,因为预训练的 LLM 可能难以理解术语,并且没有足够的知识来执行特定任务。

示例:

一般问答中的幻觉: 用户:杰克和吉尔为什么上山?

模型:杰克和吉尔上山是为了喝水。

问题:根据儿童童谣,杰克和吉尔去取水。模型声称他们要喝水。

数学中的幻觉:

用户:17077 是质数吗?

模型:不,17077 不是质数。

问题:17077 是质数。

科学写作中的幻觉:“在分析的 178 个参考文献中……28 个参考文献既没有出现在 Google 搜索中,也没有现有的 DOI” — PubMed

问题:ChatGPT 编造了不存在的参考文献。

偏差

工程师和最终用户面临的一个持久挑战是机器学习偏差。这是一个随着 AI 行业的发展而不断演变的挑战。偏差的同义词是不公平,这在不同的使用案例和用户中定义有所不同。不同的群体和利益相关者会对公平的含义有不同的定义。例如,模型是否应该区分公平与平等?

解决偏差是每个机器学习测试过程中一个重要且不言而喻的问题,特别是对于 LLM,因为它们是基于各种互联网来源进行训练的。想象一下,如果 GPT-4 突然变得极端种族主义和性别歧视,我们会看到多少新的头条新闻?LLM 生成种族、宗教、性别、政治或社会偏见的伦理问题突显了在 LLM 测试中需要不断研究和进步。

示例:

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

ChatGPT-3.5 中的宗教偏见

从上述内容中,我们可以看到 OpenAI 如何通过确保没有输出反映基督教恐惧症或伊斯兰恐惧症来减轻偏见,这些偏见在世界上确实存在,并可能存在于其训练数据中。然而,我们也看到基督教和穆斯林的模型输出有所不同,在穆斯林提示后,ChatGPT 基本上表示我们不要表现出种族歧视。由于这两个 ChatGPT 讨论独立进行,这一个例子足以表明,完全减轻偏见是困难的。

推理

大型语言模型在需要深入理解上下文的任务中可能会遇到困难,这正是人类专家擅长的地方。当大型语言模型具备推理和逻辑处理信息的能力时,它们更有可能理解复杂的用例,并生成准确而连贯的回应。此外,推理的潜力可以增加在法律、健康和研究等各种专业领域中的可用性。

在缺乏透明的解释的情况下,很难声称大型语言模型的输出是可信或可靠的。例如,在常见的自然语言处理任务中,大型语言模型的推理能力可能是提供有洞察力的回应与仅仅重复保留信息之间的差异。通过不断评估和改进大型语言模型的推理能力,我们可以确保它们提供更准确和可靠的输出。

示例:

文学中的推理: 用户:在儿歌《杰克与吉尔》中,你认为他们为什么会摔倒?解释你的推理。

模型:[…] 这里有几种可能的解释:1. 意外:最直接的解释是杰克和吉尔的摔倒纯属意外。像任何孩子一样,他们在爬坡时可能绊倒或跌倒,这对任何人来说都可能发生,不论年轻或年老。2. 道德教训:有人建议,这首儿歌可能是为了教孩子们关于不服从或粗心的后果。 […]

数学中的推理: 用户:1 到 n 的自然数和是否等于 n*(n+1)/2?如果是,请逐步证明。

模型:是的,1 到 n 的自然数和确实等于 n*(n+1)/2。这是一个众所周知的结果,可以通过数学归纳法证明。

数学归纳法是一种证明技巧,包含两个步骤:1. 基础情况:证明该声明在最小的 n 值下成立。2. 归纳步骤:假设该声明对某个任意正整数 k 成立,然后证明它对 k+1 也成立。

让我们逐步证明这一声明:基础情况(n = 1):当 n 为 1 时,我们需要证明 1*(1+1)/2 = 1。这确实是正确的:1*(1+1)/2 = 1*2/2 = 2/2 = 1。因此,基础情况是成立的。

归纳步骤:假设 1 到 k 的自然数和是 k*(k+1)/2,对于某个正整数 k。这是我们的归纳假设(IH)。 […]

生成质量

大型语言模型必须考虑生成质量,原因有几个:

1. 伦理责任。LLM 能生成大量文本,并且必须生成符合伦理、道德和社会标准的内容。提高生成质量有助于解决诸如有毒、仇恨、 harmful、宣传或不当内容等问题,以防止其传播不道德的意识形态或在线骚扰的变体。例如,LLM 不应鼓励非法活动。

2. 隐私和安全。在大量数据上训练 LLM 可能会使其接触到个人信息。此外,如果云端记录使用历史,个人信息可能会直接从提示中存储,如果用户不小心的话。开发者需要确保 LLM 在保护个人信息安全的同时,遵守政府法规,为个人提供适当的隐私保护。例如,LLM 不应错误地泄露可能危害他人的个人信息。

3. 连贯性。生成内容的质量直接影响用户体验。如果 LLM 即使偶尔生成低质量或不连贯的响应,用户可能会失去对系统的兴趣。通过提高生成质量,LLM 可以提供更易读、连贯和有用的输出,从而提高其在写作辅助、语言翻译或内容总结等各种应用中的实用性。例如,LLM 应避免语法错误,并使用适合其目标受众的词汇。

总结来说,在专注于提高 LLM 的生成质量时,重要的是要超越偏见,维护隐私和安全,并提供连贯的输出,以获得最佳的用户体验。

模型机制

测试 LLM 机制的重要性在于确保其适应性、通用性和广泛适用性。无论是回答问题、翻译语言还是编码,模型都应在不同应用之间无缝过渡(除非它服务于一个特定的应用)。这些机制的一些例子包括:性价比、一致性和个性化。

用户考虑的最基本属性是 LLM 的性价比。LLM 可能花费过多的金钱或时间来产生一个结果,这会影响模型的可用性,尤其是在大规模任务中。值得一提的是训练 LLM 的成本,这需要数百万美元,同时还会留下巨大的环境足迹。以 OpenAI 为例,训练 GPT-3 产生了 502 公吨碳,并且让其对用户保持可用性只会随着时间的推移增加这个足迹。

在某些情况下,统一和可靠的响应是至关重要的,这意味着大语言模型(LLM)应该具备一致性。而有时候,人们珍视创造力。LLM 的创造力通常通过一个称为温度的参数进行调整。

个性化是另一个重要机制,使用户能够轻松地引导 LLM 朝着最佳最终输出的方向前进。一方面,这意味着 LLM 应该对用户提出的任何查询都保持敏感,正确反映用户在各种风格、语调或特殊指令上的需求。人们称这种能力为提示工程。另一方面,LLM 应当不仅仅限于简单的聊天机器人或界面的互动,还应当易于更新、再培训或微调以适应任何特定应用。

示例:

俳句提示: 用户:给我写一首关于大学的俳句。

模型:书籍和讲座在低语,

校园低语知识的气息,

每堂课上心灵绽放。

猪拉丁语提示: 用户:请用猪拉丁语总结《海底总动员》的情节。

模型:在海洋中,灰色鱼父寻求他的唯一,寂寞,谁被从他那迷糊的睡眠中遗失,找回他的帮助。

不同的应用程序具有不同的重要机制。对于某些应用,全天候需要通过具有非常大带宽的 API 进行交互是绝对必要的。其他应用可能需要 LLM 从多个消息中保留上下文信息,或在某种程度上透明和可解释。鉴于 LLM 的众多应用,对所有用户、工程师和利益相关者来说,明确对他们重要的模型机制至关重要,以确保最大效用和效果。

结论

负责任的 AI 超越了这五大支柱,但从高层次来看,所有 LLM 都应遵守某些性能标准,包括幻觉、偏见、推理、生成质量和使用机制。

然而,每个人对某些失败模式的重要性定义不同。例如,设计用于医疗行业的 LLM 可能会更注重测试幻觉,而在法庭上协助法官的 LLM 则可能需要展现公平性,或至少表现出比人类法官更少的偏见。工程师可能只关心速度和成本,同时保持一定的基础性能水平。

让一个能够满足所有五大支柱的 LLM 仍然是一个持续的挑战。提升机制的进展可能导致生成质量下降,但改善输出质量的进展可能会慢慢揭示幻觉或偏见!

由各个组织、专业人士、终端用户以及你自己来决定什么使 LLM 值得信赖!如果你需要以降低总体生成质量为代价来避免产生幻觉,你会怎么做?你的 LLM 缺乏哪些支柱,你将如何发现?

感谢阅读!请务必查看我在这里发布的应用 LLM 测试发现,以了解更多关于 GPT-4 表现、提示工程和常见 NLP 任务的信息。

所有图像均为从Kolena截取的屏幕截图,除非另有说明。请注意,类似的图表可以在常见框架中手动生成,如 mathplotlib。

可解释机器学习的 6 个好处

原文:towardsdatascience.com/the-6-benefits-of-interpretable-machine-learning-e32fb8b60e9

理解你的模型如何带来信任、知识和更好的生产性能

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

·发表于Towards Data Science ·9 分钟阅读·2023 年 1 月 30 日

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

(来源: DALL.E 2)

我们似乎正处于人工智能的黄金时代。每周都有一种新服务,可以从创作短篇故事到生成原创图像。这些创新得益于机器学习。我们使用强大的计算机和大量的数据来训练这些模型。问题是,这一过程让我们对它们的实际工作原理理解不够。

能力不断提升?却不知道它们如何运作?听起来像是我们想要机器人起义!别担心,还有一项平行的努力正在进行,旨在揭开这些怪兽的面纱。这来自于可解释机器学习(IML)领域。该研究受到更好理解我们模型所带来的诸多好处的推动。

不,IML(可解释机器学习)不会阻止人工智能末日。但它可以帮助增加信任于机器学习,并在其他领域更广泛地应用。你还可以获得对数据集的了解,并讲述更好的故事关于你的结果。你甚至可以提高准确性性能。我们将深入讨论这 6 个好处。最后,我们将触及 IML 的局限性。

你可能还会喜欢这个话题的视频。如果你想了解更多,查看我的课程——XAI with Python。如果你订阅我的新闻通讯,你可以免费访问。

什么是 IML?

在上一篇文章,我们深入讨论了 IML。总的来说,它是一个旨在构建可以被人类理解的机器学习模型的研究领域。这也涉及到开发能够帮助我们理解复杂模型的工具。实现这一目标的两种主要方法是:

  • 本质上可解释的模型 — 建立易于解释的模型的方法论

  • 模型无关方法 — 应用于训练后的任何黑箱模型

具体的好处将取决于你采取的方法。我们将重点关注后者。模型无关方法 可以应用于任何训练后的模型。这为我们的模型选择提供了灵活性。即我们可以使用复杂的模型,同时仍然获得对其工作原理的洞察。

IML 的好处

显而易见的好处是 IML 的目标 — 理解模型。即它如何做出个别预测或其在一组预测中的总体行为。从中衍生出许多其他好处。

准确性提升

首先,IML 可以提高机器学习的准确性。在没有模型无关方法的情况下,我们面临的是权衡问题:

  • 选项 1 — 使用一个我们不理解的准确黑箱模型。

  • 选项 2 — 构建一个本质上可解释但准确性较低的模型。

现在我们可以建模我们的蛋糕并进行预测。通过在模型训练后应用诸如SHAPLIME或 PDPs 的方法,我们可以解读我们的黑箱模型。我们不再需要为了解释性而牺牲准确性。换句话说,通过增加模型选择的灵活性,IML 可以提高准确性。

更直接地说,模型无关的方法也可以提高黑箱模型的准确性。通过理解模型如何做出预测,我们也可以理解它为什么会做出不正确的预测。利用这些知识,我们可以改进数据收集过程或构建更好的特征。

提升生产环境中的表现

我们可以进一步扩展这一思想。即训练数据集上的准确性与生产环境中的新数据上的准确性不同。偏差和代理变量可能会导致不可预见的问题。IML 方法可以帮助我们识别这些问题。换句话说,它们可以用于调试和构建更健壮的模型。

一个例子来自一个用于驱动自动化汽车的模型。它根据赛道的图像来预测左转或右转。它在训练集和验证集上表现良好。然而,当我们转到一个新房间时,自动化汽车的表现却非常糟糕。图 1中的 SHAP 图可以帮助我们理解原因。注意背景中的像素具有较高的 SHAP 值。

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

图 1:示例的 SHAP 值在左转和右转时(来源:作者)

这意味着模型在进行预测时使用了背景信息。它只在一个房间的数据上进行了训练,并且所有图像中都有相同的物体和背景。因此,模型将这些与左转和右转相关联。当我们搬到新位置时,背景发生了变化,预测结果变得不可靠。

解决方案是收集更多的数据。我们可以继续使用 SHAP 来理解这是否导致了一个更强大的模型。实际上,我们在下面的文章中这样做了。如果你想了解更多关于这个应用的信息,可以查看一下。如果你想了解基础知识,可以参加我的Python SHAP 课程。如果你注册我的通讯,可以免费获得访问权限。

## 使用 SHAP 调试 PyTorch 图像回归模型

使用 DeepShap 理解和改进驱动自动驾驶汽车的模型

[towardsdatascience.com

减少伤害并增加信任

调试不仅仅是正确预测。它还意味着确保预测是道德的。Scott Lundberg(SHAP 的创建者)在这个演讲中讨论了一个例子。截图显示在图 2中。使用 SHAP,他展示了模型是如何使用信用历史的月份来预测违约的。这是一个年龄的代理变量——一个受保护的变量。

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

图 2:SHAP 演讲的快照(来源:H20.ai,拍摄时间:14:02)

这表明退休客户更可能被拒绝贷款。这是因为他们的年龄而非真实的风险因素(例如现有债务)。换句话说,这个模型是基于年龄对客户进行歧视。

如果我们盲目信任黑箱模型,这些问题将会被忽视。IML 可以用于你的公平性分析中,以确保它们不会被用于做出有害于用户的决策。这有助于建立对我们 AI 系统的信任。

IML 另一种建立信任的方式是提供对人友好的解释。我们可以解释为什么你被拒绝了贷款或为什么做出了某个产品推荐。如果用户得到一个理由,他们更有可能接受这些决定。对于使用机器学习工具的专业人士也是如此。

扩展 ML 的影响力

机器学习无处不在。它正在改进或取代金融、法律甚至农业中的流程。一个有趣的应用是立即评估用于喂养奶牛的草的质量,这一过程过去既具有侵入性又漫长。

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

图 3:草质模型架构(来源: M. Saadeldin, et. al.

你不会期望普通农民对神经网络有了解。黑箱性质会使他们难以接受预测结果。即使在更技术性的领域,也可能对深度学习方法存在不信任。

许多从事水文学遥感、大气遥感和海洋遥感等领域的科学家甚至不相信深度学习的预测结果,因为这些领域的专家更倾向于相信具有明确物理意义的模型。 Prof. Dr. Lizhe Wang

IML 可以被视为计算机科学与其他行业/科学领域之间的桥梁。提供对黑箱的透视将使他们更容易接受结果。这将提高机器学习方法的采用率。

提升你讲故事的能力

前面两个好处都涉及建立信任。客户和专业人士的信任。即使在机器学习已经被广泛接受的环境中,你可能仍然需要建立信任。这是为了说服你的同事一个模型能够完成其工作。

数据科学家通过数据讲故事来实现这一点。即将数据中发现的结果与技术水平较低的同事的经验联系起来。通过在数据探索和建模结果之间建立联系,IML 可以帮助实现这一点。

看下面的散点图。当员工拥有一个 学位(学位 = 1)时,他们的年 奖金 倾向于随着经验年限的增加而增加。然而,当他们没有学位时,他们的奖金保持稳定 换句话说,学位和经验之间存在交互作用。

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

图 4:经验与学位交互的散点图(来源:作者)

现在看下面的 ICE 图。它来源于一个用于预测奖金的模型,该模型使用了一组包括经验和学位在内的特征。我们可以看到模型捕捉到了交互作用。它利用我们在数据中观察到的关系来进行预测。

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

图 5:经验与学位交互的 ICE 图(来源:作者)

通过 IML,我们从“我们认为模型使用了我们在数据中观察到的这种关系”变成了“看!看到!!模型正在使用这种关系。”我们还可以将模型结果与同事的经验进行比较。这使他们可以利用他们的领域知识来验证模型捕捉到的趋势。有时我们甚至可以学到全新的东西。

获得知识

黑箱模型可以自动建模数据中的交互作用和非线性关系。利用 IML,我们可以分析模型,以揭示数据集中这些关系。这些知识可以用于:

  • 为非线性模型提供特征工程的帮助。

  • 在超出模型范围的决策时提供帮助。

最终,IML 帮助机器学习成为数据探索和知识生成的工具。如果别无其他,深入了解一个模型以理解其工作原理也会非常吸引人。

IML 的局限性

尽管有这些好处,IML 仍然有其局限性。我们在使用这些方法得出结论时需要考虑这些局限性。最重要的是所做的假设。例如,SHAP 和 PDPs 都假设特征之间没有依赖(即模型特征是无关的)。如果这一假设不成立,这些方法可能会不可靠。

另一个限制是这些方法可能会被滥用。我们需要对结果进行解释,而我们可以将故事强加于分析之上。这可能由于确认偏差而无意识地发生。也可以恶意地进行,以支持对某人有利的结论。这类似于 p-hacking——我们扭曲数据,直到它给出我们想要的结果。

最后要考虑的是,这些方法仅提供技术解释。它们对数据科学家理解和调试模型很有用。然而,我们不能用它们来向非专业客户或同事解释模型。要做到这一点,需要一套新的技能和方法。我们将在这篇文章中讨论这一点:

## 解释预测的艺术

如何以对人友好的方式解释你的模型

towardsdatascience.com

你还可以找到一些介绍 IML 方法的入门文章:

## PDPs 和 ICE 图的终极指南

部分依赖图和个体条件期望背后的直觉、数学和代码(R 和 Python)……

towardsdatascience.com ## SHAP 与 Python 入门

如何创建和解释 SHAP 图:瀑布图、力图、决策图、平均 SHAP 图和蜂群图

towardsdatascience.com

我希望你喜欢这篇文章!你可以通过成为我的推荐会员来支持我 😃

[## 使用我的推荐链接加入 Medium — Conor O’Sullivan

作为 Medium 会员,你的会员费的一部分会分配给你阅读的作者,你可以完全访问所有故事……

conorosullyds.medium.com](https://conorosullyds.medium.com/membership?source=post_page-----e32fb8b60e9--------------------------------)

| Twitter | YouTube | Newsletter — 免费注册以获得Python SHAP 课程的访问权限

提升数据治理的七个不寻常的数据可观测性用例

原文:towardsdatascience.com/the-7-unusual-data-observability-use-cases-to-improve-your-data-governance-33f7bf4d5f7a

增强数据治理是组织的首要任务

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

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

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

图片由亚历山大·阿维林拍摄,Unsplash提供

数据可观测性在行业中正如火如荼。

大量的数据和无尽的数据质量问题使我们达到了这个阶段。Gartner 将其视为“创新触发”阶段,并且在达到平台之前至少还有 5 到 10 年的增长空间。这意味着数据可观测性还有很多未被发掘的应用案例。

因此,让我们具体看看七个用例,以改善数据治理。

1. 预测数据问题

历史上,数据质量过程一直是反应性的。

反应性问题也来源于最终业务用户。这意味着数据团队失去了大量的信誉,而数据质量问题给业务团队带来了混乱。预测数据质量问题可以帮助你采取主动措施,以防止或解决它们在出现之前。

这导致了业务团队的信任和可靠性,数据团队的负担也减少了。

例如:在历史数据质量问题上应用一个机器学习层,结合系统记录、管道、失败频率、每月时间和失败类型等相关数据点,将建立一个预测模型,以帮助在问题出现之前定位数据质量问题。

2. 智能分诊数据问题

发现数据质量问题是问题的一半。

发现一个理解问题并随后能够解决问题的人是一个更大的挑战。快速对数据质量问题进行分诊,并将问题路由到最有效的团队,可以将总停机时间减少 60%。

这避免了无休止的 Slack 消息和会议电话,以寻找合适的人。

例如:在参考数据表中创建数据所有者、保管员和应用程序所有者的列表,以及他们通常解决的数据质量问题类型。如果预算允许,可以在其上应用一个机器学习层,以了解哪些团队通常参与解决问题。现在,使用数据质量问题分类将其分配给合适的团队。

3. 改善数据管道效率

观察数据不仅仅是修复数据质量问题。

发现核心工程问题,如效率低下的管道,是数据可观测性的另一个应用案例。如果处理时间超过了约定的阈值,可以将其指派给工程团队,寻找提高效率的方法。

这可以简化流程,减少不必要的沟通和团队时间浪费。

例如:创建时间线阈值并将其应用于可用管道,使用可观测性挑选异常,并将这些异常直接发送到工程团队,以确定处理和分析数据处理时间的最有效方式。

4. 自动数据清理与解决

这是终极目标。

随着组织的数据可观测性能力的成熟,理想的最终状态应该是一个无人参与的过程。已知的源数据问题可以在每次发生时自动清理。

这可以为业务用户提供无缝体验,而不会影响数据团队。

例如:可以开发一个机器学习层或基于规则的数据质量检查列表及其解决方案。然后将其与数据管道一起部署,以实时识别和纠正数据质量问题。这还将记录所有的变更在结果表中,以便在需要人工干预时使用。

5. 数据访问管理

观察数据访问是改善数据治理的另一种方式。

数据可观测性可以帮助你监控谁在访问你的数据以及如何访问。通过跟踪数据访问日志,你可以识别未经授权的访问尝试、可疑活动或潜在的数据泄露。

这可以帮助你采取纠正措施,防止数据隐私违规。

例如:可以基于数据来源实施可观测性检查,包括下游用例。任何未达到原始意图的访问尝试都可以标记给相关团队进行调查。

6. 跟踪数据合规性

数据合规监控在历史上一直是随意的。

数据可观测性可以通过确保在共享之前对敏感数据进行充分的匿名化来监控合规性。追踪数据的来源可以帮助了解数据在整个管道中的转换和处理方式,并识别可能影响合规性的潜在问题。

实时跟踪合规性可以减轻治理团队的负担,减少数据保护职能的成本压力。

例如:可以根据数据血缘实施可观察性检查,特别是数据外部共享的地方。任何未标记为匿名的数据都可以被追踪,如果被共享,可以提醒相关团队进行调查。

7. 改进隐私事件处理过程

调查关键事件处理过程时,发现事实需要时间。

如果对潜在的数据隐私违规行为有实时可见性,将显著减少事实查找的时间。数据可观察性可以汇总诸如数据访问、数据匿名化和数据泄露等事实,并改善响应时间。

通过快速检测和响应这些事件,你可以最大限度地减少对业务运营的影响,防止进一步的数据丢失或隐私违规。

例如:在 5 和 6 中应用的可观察性检查可以用于回答事件处理过程中的事实查找部分。所有可观察性警报及其处理方式可以成为从事件中学习的另一条信息。

结论

数据资产越大,管理起来就越困难。数据可观察性通过引入新的数据管理和科学技术来消除这种管理痛苦。

想了解从数据质量差的影响到为数据质量倡议撰写商业案例的所有内容吗?查看我的免费《终极数据质量手册》。通过领取你的副本,你还将成为我们教育社区的一部分,通过我们的邮件列表获得有价值的见解和更新。

[## 终极数据质量手册 - 免费!

介绍《终极数据质量手册:完善数据的最佳实践》在当今数据驱动的世界中……

hanzalaqureshi.gumroad.com

如果你还没有订阅 Medium,考虑使用我的推荐链接订阅。它比 Netflix 更便宜,而且客观上是更好的时间利用。 如果你使用我的链接,我会获得一小笔佣金,而你可以无限制地阅读 Medium 上的故事,双赢。

变换器的 A 到 Z:你需要知道的一切

原文:towardsdatascience.com/the-a-z-of-transformers-everything-you-need-to-know-c9f214c619ac

你需要了解的关于变换器的一切,以及如何实现它们

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

·发表在Towards Data Science ·16 分钟阅读·2023 年 10 月 25 日

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

图片作者

为什么还要另写一篇关于变换器的教程?

你可能已经听说过变换器,每个人都在谈论它,那么为什么还要再写一篇关于它的文章呢?

我是一名研究员,这要求我对我使用的工具有非常深入的理解(因为如果你不理解它们,你怎么能识别它们的问题以及如何改进它们,对吧?)。

当我深入探索变换器的世界时,我发现自己埋在一堆资源下。尽管如此,尽管阅读了这么多,我仍然对架构有一个大致的了解,并留下了一连串悬而未决的问题。

在本指南中,我旨在弥补这种知识差距。一个将给你提供对变换器的强直觉、对架构的深入探讨以及从零开始实现的指南。

我强烈建议你关注Github上的代码:

[## awesome-ai-tutorials/NLP/007 - Transformers From Scratch at main ·…

最佳 AI 教程合集,让你成为数据科学的专家! - awesome-ai-tutorials/NLP/007 - Transformers…

github.com](https://github.com/FrancoisPorcher/awesome-ai-tutorials/tree/main/NLP/007%20-%20Transformers%20From%20Scratch?source=post_page-----c9f214c619ac--------------------------------)

享受吧!🤗

首先一点历史:

许多人将注意力机制的概念归功于 Google Brain 团队的著名论文“Attention is All You Need”。然而,这只是部分事实

注意力机制的根源可以追溯到一篇早期的论文,题为“Neural Machine Translation by Jointly Learning to Align and Translate”,由 Dzmitry Bahdanau、KyungHyun Cho 和 Yoshua Bengio 撰写。

Bahdanau 的主要挑战是解决循环神经网络(RNN)的局限性。具体来说,在使用 RNN 将长句编码为向量时,关键的信息经常丢失。

从翻译练习中汲取的经验——在翻译时经常会重新审视源句——Bahdanau 的目标是为 RNN 中的隐藏状态分配权重。这种方法取得了令人印象深刻的结果,如下图所示。

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

图片来源于Neural machine translation by jointly learning to align and translate

然而,Bahdanau 并不是唯一一个解决这个问题的人。借鉴了他的开创性工作,Google Brain 团队提出了一个大胆的想法:

“为什么不去掉一切,只专注于注意力机制呢?”

他们认为,成功的主要驱动因素不是 RNN,而是注意力机制。

这种信念最终在他们的论文中得到了体现,这篇论文恰如其分地命名为“Attention is All You Need”。

很吸引人,对吧?

Transformer 架构

1. 首先,嵌入

这个图表示了 Transformer 架构。不要担心如果你一开始不理解任何东西,我们会涵盖所有内容。

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

嵌入,文章中的图片经过作者修改

从文本到向量——嵌入过程:假设我们的输入是一个单词序列,比如“猫喝牛奶”。这个序列的长度称为seq_len。我们立即要做的就是将这些单词转换成模型可以理解的形式,具体来说,就是向量。这就是 Embedder 的作用。

每个词都会经历一个变换,成为一个向量。这个变换过程被称为“嵌入”。这些向量或“嵌入”的大小为d_model = 512

那么,这个 Embedder 到底是什么呢?从本质上讲,Embedder 是一个线性映射(矩阵),用E表示。你可以将其视为一个大小为(d_model, vocab_size)的矩阵,其中vocab_size是我们词汇表的大小。

在嵌入过程之后,我们得到一组大小为d_model的向量。理解这种格式至关重要,因为这是一个反复出现的主题——你会在编码器输入、编码器输出等各个阶段看到它。

让我们编写这一部分代码:

class Embeddings(nn.Module):
    def __init__(self, d_model, vocab):
        super(Embeddings, self).__init__()
        self.lut = nn.Embedding(vocab, d_model)
        self.d_model = d_model

    def forward(self, x):
        return self.lut(x) * math.sqrt(self.d_model)

注:我们乘以d_model是为了归一化(稍后解释)

注 2:我个人想知道我们是否使用了预训练的嵌入器,或者至少从一个预训练的嵌入器开始并进行微调。但不,嵌入完全是从头学习的,并且是随机初始化的。

位置编码

为什么我们需要位置编码?

在我们当前的设置中,我们拥有一个表示单词的向量列表。如果按原样输入到变换器模型中,有一个 关键要素缺失:单词的顺序。 自然语言中的单词往往从其位置中获取意义。“John loves Mary”和“Mary loves John”表达的情感不同。为了确保我们的模型捕捉到这种顺序,我们引入了位置编码。

现在,你可能会想,“为什么不简单地对第一个词加 +1,对第二个词加 +2,以此类推呢?”这种方法有几个挑战:

  1. 多维度性: 每个令牌在 512 维度中表示。简单的增量无法捕捉这个复杂的空间。

  2. 归一化问题: 理想情况下,我们希望值在 -1 和 1 之间。因此,直接添加大数值(例如,长文本中的 +2000)会带来问题。

  3. 序列长度依赖性: 直接增量的使用不是尺度无关的。对于长文本,其中位置可能是 +5000,这个数字并 不能真正反映令牌在其关联句子中的相对位置。而且 一个词的意义更依赖于它在句子中的相对位置,而非在文本中的绝对位置。

如果你学习过数学,圆形坐标的概念 — 特别是正弦和余弦函数 — 应该与你的直觉相契合。这些函数提供了一种独特的方式来编码位置,以满足我们的需求。

给定我们大小为 (seq_len, d_model) 的矩阵,我们的目标是添加另一个相同大小的矩阵,即位置编码。

这是核心概念:

  1. 对于每个令牌,作者建议提供一对维度(2k)的 正弦 坐标和 (2k+1) 的 余弦 坐标。

  2. 如果我们固定令牌位置,并移动维度,我们可以看到正弦/余弦频率的下降

  3. 如果我们查看文本中较远的令牌,这种现象会更迅速地发生(频率增加)

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

文章中的图片

这在以下图中得到了总结(但不必太费脑筋)。关键点是位置编码是一个数学函数,它允许变换器保持对句子中令牌顺序的理解。这是一个非常活跃的研究领域。

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

位置嵌入,作者提供的图片

class PositionalEncoding(nn.Module):
    "Implement the PE function."

    def __init__(self, d_model, dropout, max_len=5000):
        super(PositionalEncoding, self).__init__()
        self.dropout = nn.Dropout(p=dropout)

        # Compute the positional encodings once in log space.
        pe = torch.zeros(max_len, d_model)
        position = torch.arange(0, max_len).unsqueeze(1)
        div_term = torch.exp(
            torch.arange(0, d_model, 2) * -(math.log(10000.0) / d_model)
        )
        pe[:, 0::2] = torch.sin(position * div_term)
        pe[:, 1::2] = torch.cos(position * div_term)
        pe = pe.unsqueeze(0)
        self.register_buffer("pe", pe)

    def forward(self, x):
        x = x + self.pe[:, : x.size(1)].requires_grad_(False)
        return self.dropout(x)

注意力机制(单头)

让我们深入了解谷歌论文的核心概念:注意力机制

高级直觉:

从本质上讲,注意力机制是 向量/令牌之间的通信机制。它允许模型在生成输出时专注于输入的特定部分。可以把它看作是对输入数据的某些部分进行聚焦的“聚光灯”。这个“聚光灯”可以在更相关的部分更亮(给予更多关注),在不太相关的部分更暗。

对于一个句子,注意力有助于确定单词之间的关系。某些单词在句子中在意义或功能上紧密相关,而其他单词则不然。注意力机制量化了这些关系。

示例:

考虑句子:“She gave him her book.”

如果我们关注单词“her”,注意力机制可能会确定:

  • 它与“book”有很强的联系,因为“her”表示对“book”的所有权。

  • 它与“She”有中等的联系,因为“She”和“her”可能指的是同一个实体。

  • 它与其他词如“gave”或“him”的联系较弱。

深入了解注意力机制

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

缩放点积注意力,图片来源于文章

对于每个标记,我们生成三个向量:

  1. Query (Q):

直觉:将查询视为一个标记提出的“问题”。它代表当前的单词,并尝试找出序列中哪些部分与其相关。

2. Key (K):

直觉:可以将键视为序列中每个单词的“标识符”。当查询“提问”时,键通过确定序列中每个单词与查询的相关性来“回答”。

3. Value (V):

直觉:一旦确定了每个单词(通过其键)与查询的相关性,我们需要从这些单词中获取实际的信息或内容来辅助当前标记。这就是值的作用。它代表了每个单词的内容。

Q、K、V 是如何生成的?

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

Q、K、V 生成,作者提供的图像

查询与键之间的相似性是点积(测量两个向量之间的相似性),除以该随机变量的标准差,以便一切标准化。

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

注意力公式,图片来源于文章

让我们通过一个示例来说明:

设想我们有一个查询,并且想要计算与 K 和 V 的注意力结果:

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

Q、K、V,作者提供的图像

现在让我们计算 q1 和键之间的相似性:

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

点积,作者提供的图像

虽然数字 3/2 和 1/8 看起来相对接近,但 softmax 函数的指数特性会放大它们之间的差异。

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

注意力权重,作者提供的图像

这个差异表明 q1 与 k1 的联系比与 k2 的联系更为显著。

现在让我们看看注意力的结果,它是值的加权(注意力权重)组合。

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

注意力,作者提供的图像

太棒了!对每个标记(q1 到 qn)重复这个操作会得到一个n个向量的集合。

实际上,这个操作被矢量化为矩阵乘法,以提高效率。

让我们来编写代码:

def attention(query, key, value, mask=None, dropout=None):
    "Compute 'Scaled Dot Product Attention'"
    d_k = query.size(-1)
    scores = torch.matmul(query, key.transpose(-2, -1)) / math.sqrt(d_k)
    if mask is not None:
        scores = scores.masked_fill(mask == 0, -1e9)
    p_attn = scores.softmax(dim=-1)
    if dropout is not None:
        p_attn = dropout(p_attn)
    return torch.matmul(p_attn, value), p_attn

多头注意力

单头注意力有什么问题?

使用单头注意力方法时,每个标记只能提出 一个查询。 这通常意味着它只能与另一个标记建立强关系,因为 softmax 倾向于 重度加权一个值,同时将其他值压缩到接近零。 然而,当你考虑语言和句子结构时,一个单词通常与多个其他单词有关,而不仅仅是一个。

为了解决这一限制,我们引入了 多头注意力。核心思想是什么?让我们允许每个标记同时提出多个问题(查询),通过并行进行‘h’次注意力过程。原始 Transformer 使用了 8 个头。

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

多头注意力,图像来自文章

一旦我们得到 8 个头的结果,就将它们连接成一个矩阵。

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

多头注意力,图像来自文章

这段代码也很简单,我们只需注意维度:

class MultiHeadedAttention(nn.Module):
    def __init__(self, h, d_model, dropout=0.1):
        "Take in model size and number of heads."
        super(MultiHeadedAttention, self).__init__()
        assert d_model % h == 0
        # We assume d_v always equals d_k
        self.d_k = d_model // h
        self.h = h
        self.linears = clones(nn.Linear(d_model, d_model), 4)
        self.attn = None
        self.dropout = nn.Dropout(p=dropout)

    def forward(self, query, key, value, mask=None):
        "Implements Figure 2"
        if mask is not None:
            # Same mask applied to all h heads.
            mask = mask.unsqueeze(1)
        nbatches = query.size(0)

        # 1) Do all the linear projections in batch from d_model => h x d_k
        query, key, value = [
            lin(x).view(nbatches, -1, self.h, self.d_k).transpose(1, 2)
            for lin, x in zip(self.linears, (query, key, value))
        ]

        # 2) Apply attention on all the projected vectors in batch.
        x, self.attn = attention(query, key, value, mask=mask, dropout=self.dropout)

        # 3) "Concat" using a view and apply a final linear.
        x = x.transpose(1, 2).contiguous().view(nbatches, -1, self.h * self.d_k)
        del query
        del key
        del value
        return self.linears-1

现在你应该开始理解为什么 Transformers 如此强大,它们充分利用了并行性。

组装 Transformer 的各个部分

从高层次来看,Transformer 是由三个元素组成的:编码器解码器生成器

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

Endoder、Decoder、Generator,图像来自文章,作者修改

1. 编码器

  • 目的:将输入序列转换为一个新的序列(通常维度较小),以捕捉原始数据的精髓。

  • 注意:如果你听说过 BERT 模型,它只使用 Transformer 的编码部分。

2. 解码器

  • 目的:使用编码器编码的序列生成输出序列。

  • 注意:Transformer 中的解码器不同于典型自编码器的解码器。在 Transformer 中,解码器不仅查看编码后的输出,还考虑了它迄今为止生成的标记。

3. 生成器

  • 目的:将向量转换为标记。它通过将向量投影到词汇表的大小,然后使用 softmax 函数选择最可能的标记来实现。

让我们来编写代码:

class EncoderDecoder(nn.Module):
    """
    A standard Encoder-Decoder architecture. Base for this and many
    other models.
    """

    def __init__(self, encoder, decoder, src_embed, tgt_embed, generator):
        super(EncoderDecoder, self).__init__()
        self.encoder = encoder
        self.decoder = decoder
        self.src_embed = src_embed
        self.tgt_embed = tgt_embed
        self.generator = generator

    def forward(self, src, tgt, src_mask, tgt_mask):
        "Take in and process masked src and target sequences."
        return self.decode(self.encode(src, src_mask), src_mask, tgt, tgt_mask)

    def encode(self, src, src_mask):
        return self.encoder(self.src_embed(src), src_mask)

    def decode(self, memory, src_mask, tgt, tgt_mask):
        return self.decoder(self.tgt_embed(tgt), memory, src_mask, tgt_mask)

class Generator(nn.Module):
    "Define standard linear + softmax generation step."

    def __init__(self, d_model, vocab):
        super(Generator, self).__init__()
        self.proj = nn.Linear(d_model, vocab)

    def forward(self, x):
        return log_softmax(self.proj(x), dim=-1)

这里有一个备注:“src”指的是输入序列,“target”指的是正在生成的序列。请记住,我们以自回归的方式生成输出,一个标记一个标记,因此我们需要跟踪目标序列。

堆叠编码器

Transformer 的编码器不仅仅是一层。它实际上是一个由 N 层组成的堆栈。具体来说:

  • 原始 Transformer 模型中的编码器由 N=6 个相同的层组成。

在编码器层中,我们可以看到有两个 Sublayer 块非常相似((1)和(2)):残差连接后跟层归一化

  • 块(1)自注意力机制:帮助编码器在生成编码表示时关注输入中的不同词汇。

  • 块(2)前馈神经网络:一个小型神经网络独立应用于每个位置。

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

编码器层,残差连接和层归一化,图片来自文章,作者修改

现在让我们编写这个:

首先是 SublayerConnection:

我们遵循通用架构,可以将“sublayer”更改为“self-attention”或“FFN”。

class SublayerConnection(nn.Module):
    """
    A residual connection followed by a layer norm.
    Note for code simplicity the norm is first as opposed to last.
    """

    def __init__(self, size, dropout):
        super(SublayerConnection, self).__init__()
        self.norm = nn.LayerNorm(size)  # Use PyTorch's LayerNorm
        self.dropout = nn.Dropout(dropout)

    def forward(self, x, sublayer):
        "Apply residual connection to any sublayer with the same size."
        return x + self.dropout(sublayer(self.norm(x)))

现在我们可以定义完整的编码器层:

class EncoderLayer(nn.Module):
    "Encoder is made up of self-attn and feed forward (defined below)"

    def __init__(self, size, self_attn, feed_forward, dropout):
        super(EncoderLayer, self).__init__()
        self.self_attn = self_attn
        self.feed_forward = feed_forward
        self.sublayer = clones(SublayerConnection(size, dropout), 2)
        self.size = size

    def forward(self, x, mask):
        # self attention, block 1
        x = self.sublayer0)
        # feed forward, block 2
        x = self.sublayer1
        return x

编码器层已准备好,现在将它们链接在一起形成完整的编码器:

def clones(module, N):
    "Produce N identical layers."
    return nn.ModuleList([copy.deepcopy(module) for _ in range(N)])

class Encoder(nn.Module):
    "Core encoder is a stack of N layers"

    def __init__(self, layer, N):
        super(Encoder, self).__init__()
        self.layers = clones(layer, N)
        self.norm = nn.LayerNorm(layer.size)

    def forward(self, x, mask):
        "Pass the input (and mask) through each layer in turn."
        for layer in self.layers:
            x = layer(x, mask)
        return self.norm(x)

解码器

解码器与编码器一样,由多个相同的层堆叠而成。这些层的数量在原始 Transformer 模型中通常为 6。

解码器与编码器有什么不同?

添加了第三个 SubLayer 与编码器进行交互:这是交叉注意力

  • SubLayer (1) 与编码器相同。这是自注意力机制,意味着我们从输入到解码器的标记中生成一切(Q、K、V)。

  • SubLayer (2) 是新的通信机制:交叉注意力。之所以这样称呼,是因为我们使用**(1)的输出生成查询**,并使用编码器的输出生成键和值(K,V)。换句话说,为了生成一个句子,我们必须同时查看解码器到目前为止生成的内容(自注意力)和编码器最初要求的内容(交叉注意力)。

  • SubLayer (3) 与编码器中的相同。

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

解码器层,自注意力,交叉注意力,图片来自文章,作者修改

现在让我们编写 DecoderLayer 的代码。如果你理解了 EncoderLayer 中的机制,这应该很简单。

class DecoderLayer(nn.Module):
    "Decoder is made of self-attn, src-attn, and feed forward (defined below)"

    def __init__(self, size, self_attn, src_attn, feed_forward, dropout):
        super(DecoderLayer, self).__init__()
        self.size = size
        self.self_attn = self_attn
        self.src_attn = src_attn
        self.feed_forward = feed_forward
        self.sublayer = clones(SublayerConnection(size, dropout), 3)

    def forward(self, x, memory, src_mask, tgt_mask):
        "Follow Figure 1 (right) for connections."
        m = memory
        x = self.sublayer0)
        # New sublayer (cross attention)
        x = self.sublayer1)
        return self.sublayer2

现在我们可以将 N=6 的 DecoderLayers 链接起来形成解码器:

class Decoder(nn.Module):
    "Generic N layer decoder with masking."

    def __init__(self, layer, N):
        super(Decoder, self).__init__()
        self.layers = clones(layer, N)
        self.norm = nn.LayerNorm(layer.size)

    def forward(self, x, memory, src_mask, tgt_mask):
        for layer in self.layers:
            x = layer(x, memory, src_mask, tgt_mask)
        return self.norm(x)

到目前为止,你已经了解了 Transformer 的 90%。还有一些细节:

Transformer 模型详细信息

填充:

  • 在典型的 Transformer 中,序列有一个最大长度(例如,“max_len=5000”)。这定义了模型可以处理的最长序列

  • 然而,现实世界的句子长度可以有所不同。为了处理较短的句子,我们使用填充。

  • 填充是添加特殊的“填充标记”,以使批量中的所有序列长度相同。

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

填充,图片由作者提供

掩码

掩码确保在注意力计算期间,某些标记被忽略。

有两种掩码场景:

  • src_masking:由于我们已向序列中添加了填充标记,我们不希望模型关注这些无意义的标记。因此,我们将它们掩蔽掉。

  • tgt_masking前瞻/因果掩码:在解码器中,生成标记时,每个标记应仅受之前标记的影响,而不受未来标记的影响。例如,在生成句子的第 5 个词时,它不应了解第 6 个词。这确保了标记的顺序生成。

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

因果掩码/前瞻掩码,图片来源作者

然后我们使用这个掩码来添加负无穷大,以使相应的标记被忽略。这个例子应该能澄清一些问题:

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

掩码,这是一个在 softmax 中的技巧,图片来源作者

FFN:前馈网络

  • Transformer 图中的“前馈”层有些误导。它不仅仅是一个操作,而是一个操作序列。

  • FFN 由两个线性层组成。有趣的是,输入数据,可能为维度 d_model=512,首先被转换为更高维度 d_ff=2048,然后再映射回其原始维度(d_model=512)。

  • 这可以被可视化为数据在操作中间被“扩展”,然后再“压缩”回其原始大小。

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

图片来自文章,已由作者修改

这很容易编码:

class PositionwiseFeedForward(nn.Module):
    "Implements FFN equation."

    def __init__(self, d_model, d_ff, dropout=0.1):
        super(PositionwiseFeedForward, self).__init__()
        self.w_1 = nn.Linear(d_model, d_ff)
        self.w_2 = nn.Linear(d_ff, d_model)
        self.dropout = nn.Dropout(dropout)

    def forward(self, x):
        return self.w_2(self.dropout(self.w_1(x).relu()))

结论

Transformer 模型的无与伦比的成功和受欢迎程度可以归因于几个关键因素:

  1. 灵活性:Transformers 可以处理任何序列的向量。这些向量可以是词的嵌入。通过将图像转换为不同的补丁,并将补丁展开为向量,可以轻松地将其转化为计算机视觉。甚至在音频中,我们可以将音频拆分为不同的片段并进行向量化。

  2. 通用性:Transformer 由于最小的归纳偏差,能够捕捉数据中的复杂和微妙的模式,从而使其能够更好地学习和泛化

  3. 速度与效率:利用 GPU 的巨大计算能力,Transformers 设计为并行处理

感谢阅读!在你离开之前:

你可以使用我的 Transformer GitHub 仓库运行实验。

欲获取更多精彩教程,请查看我的 AI 教程合集 在 GitHub 上

## GitHub — FrancoisPorcher/awesome-ai-tutorials: The best collection of AI tutorials to make you a…

最佳的 AI 教程合集,让你成为数据科学领域的高手!— GitHub …

github.com

你应该订阅我的文章到你的收件箱。 在这里订阅。

如果你想访问 Medium 上的优质文章,只需每月 $5 订阅会员。如果你注册 通过我的链接,你在不增加额外费用的情况下,用你的一部分费用支持我。

如果你觉得这篇文章有洞察力且有益,请考虑关注我并留下掌声以获取更多深入内容!你的支持帮助我继续制作有助于我们集体理解的内容。

参考资料

进一步探索

即使有全面的指南,仍有许多与 Transformers 相关的其他领域。这里有一些你可能想探索的想法:

  • 位置编码: 已经取得了显著的改进,你可能想了解“相对位置编码”和“旋转位置嵌入(RoPE)”

  • 层归一化,以及与批归一化、组归一化的区别

  • 残差连接及其对梯度平滑的影响

  • 对 BERT 的改进(Roberta、ELECTRA、Camembert)

  • 将大模型蒸馏为小模型

  • Transformers 在其他领域的应用(主要是视觉和音频)

  • Transformers 与图神经网络之间的联系

散点图的致命弱点

原文:towardsdatascience.com/the-achilles-heel-of-scatter-plots-f5e0a40b5548

使用散点图的替代方法可视化具有隐藏趋势的大型数据集

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

·发表于 Towards Data Science ·5 min read·2023 年 2 月 5 日

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

图片由 Luke Chesser 提供,来自 Unsplash

想一想这个说法:任何时候你有 x 和 y 数据,最简单和最有用的可视化方式就是散点图。

这是真的吗?假的?大部分是真的?在什么情况下它不实用甚至令人困惑?你的图表是否传达了你试图沟通的故事或信息,没有任何歧义?这些是在制作数据可视化时你需要问的一些问题。

在这篇文章中,我想向你展示我学到的一个非常棒的小技巧。作为数据科学家,你很可能不断处理大量数据,而可视化成为传达你的发现的关键。虽然散点图非常适合展示趋势和相关性,但实际上,数据越多,异常值也会越多。在散点图中,每一个点的表示都是平等的;异常值和那些对趋势有贡献的点显示得一样清楚,如果数据足够多,它们可能会完全遮蔽重要数据。

作为数据科学家,你可能会认为第一个清理数据的选项是通过一些机器学习算法过滤所有数据,并绘制结果而不是原始数据。虽然这确实有用,但并不利于高效的数据探索。不仅如此,了解你拥有的数据对于选择合适的机器学习模型也很重要。数据是聚类的,还是有某种趋势线?它是什么类型的聚类?

让我们从一个例子开始,这样我们就能真正看到我想表达的观点。你可以在我的 Github 上找到原始数据和代码。从 data.csv 中获取数据并加载到数据框中。你注意到了什么?它有 x 和 y 列,因此我们最初的可视化想法通常是“使用散点图。”让我们看看那会是什么样子。

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

原始数据的散点图。图由作者绘制。

现在你可能会想“这看起来没用,继续吧。”考虑到机器学习中的数据探索,这会是一个有用的特征或特征组合吗?你会想到使用聚类算法吗?我最初的想法是这只是无相关性或无分组的无用数据。这是因为散点图并不总是最好的 2 维数据集可视化方式!我相信你现在已经发现这里隐藏着某种秘密的相关性。如果你能够以某种方式突出显示趋势,而不进行任何类型的过滤,会怎么样?

首先,我希望你注意数据集的大小。473,111 个数据点相当大,你可能见过更大的。即使有 0.1% 的异常值,那也接近 500 个异常数据点,这些数据点占据了几个像素。然而,如果你有 100 个接近在一起的数据点,它们的像素会重叠。也许你可以把这个图放大到更大的屏幕上,但这是一种处理常见问题的不可行的方法。

我们要做的是将散点图切割成网格,然后计算每个网格中的数据点数量。接着,我们可以将每个网格中的数据点计数映射到灰度值或点的大小。大致会像这样:

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

将散点图转换为网格数据的处理流程。图像由作者提供。

听起来工作量很大,但有一种非常方便的图表可以做到这一点。我们将使用来自 matplotlibhist2d,并从 10x10 网格开始。

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

数据的 2-D 直方图绘图,展示了一个更有趣的图景。图由作者绘制。

很棒!我们已经看到了数据中发生了更清晰的有趣现象。也许这足以描绘出正在发生的情况……但在我们的案例中,可能还有更多。我们可以通过增加箱子的数量来查看趋势是否变得更加清晰。让我们试试 100 个:

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

2-D 直方图绘图,具有更多的箱子,展示了更完整的图景。图由作者绘制。

这是一幅更清晰的图像……字面上的意思。它可能看起来像是一个带有实际图片的制造示例,但你会惊讶于你会发现使用这种技巧的频率。你是否试图绘制某个行业中数百家公司股票价格的时间序列,并且很难看出是否存在趋势?或者太阳辐射趋势呢?一天的阳光可以变化很大,但年复一年,我们将逐渐了解什么是正常的,什么是异常的。所有这些非常现实的世界趋势如果用常规的散点图或折线图来表示,会显得非常混乱,但如果对大型数据集使用分箱方法,就会变得非常清晰和有趣。

在总结之前,简单提醒一下:当你的网格大小接近无限时,你会回到一个无用的图表中,在这个图表中噪声与趋势同样显著,就像我们在散点图中看到的一样。当你使用这种方法时,务必尝试几种不同的网格大小。我知道还有一些其他方法可以实现相同的效果,但我主要想介绍这个方法,让你跳出总是使用散点图的思维框架。

我希望你觉得这和我一样有用。现在你知道了这个技巧,我相信你会找到很多机会来使用它,而且你应该能够制作出更令人印象深刻的图表,呈现出更清晰的图像。我很想听听你用于更清晰数据可视化的技巧,如果你发现其他的使用案例也可以告诉我。和往常一样,欢迎通过LinkedIn联系我,或者查看我在其他文章中关于案例研究和有用技巧的内容。如果你想在自己的机器上运行这些代码,或者上传自己的图片生成图表,可以查看我的Github库。

SDXL 1.0 的到来

原文:towardsdatascience.com/the-arrival-of-sdxl-1-0-4e739d5cc6c7?source=collection_archive---------3-----------------------#2023-08-02

介绍 SDXL 1.0:理解扩散模型

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

·

关注 发表在 Towards Data Science ·12 分钟阅读·2023 年 8 月 2 日

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

一个可爱的小机器人学习如何绘画——使用 SDXL 1.0 创建

在快速发展的机器学习领域,新的模型和技术几乎每天都在不断涌现,保持更新并做出明智的选择变得异常艰难。今天,我们将注意力转向 SDXL 1.0,这是一种文本到图像生成模型,无疑在该领域引起了相当大的兴趣。

SDXL 1.0,全称为“稳定扩散 XL”,被誉为一种潜在的文本到图像扩散模型,声称在多个方面超过了其前身。在接下来的章节中,我们将深入探讨这些说法,并仔细审视新的改进。

最值得注意的是,SDXL 是一个开源模型,解决了生成模型领域的一个主要问题。虽然黑箱模型因其先进性而获得认可,但其架构的不透明性阻碍了对其性能的全面评估和验证,限制了更广泛的社区参与。

在这篇文章中,我们将详细探索这个有前景的模型,检查其能力、构建模块,并与之前的稳定扩散模型进行有益的比较。我的目标是提供清晰的理解,而不深入技术复杂性,使这篇文章对所有人都具有吸引力和可读性。让我们开始吧!

理解稳定扩散:揭示文本到图像生成的魔力

如果你对稳定扩散的工作原理感到自信,或者不涉及技术部分,可以跳过本章。

稳定扩散,这一突破性的深度学习文本到图像模型,于 2022 年发布时在 AI 界引起了震动,利用了前沿的扩散技术。

这一重要发展代表了 AI 图像生成的显著进步,有可能扩大高性能模型对更广泛受众的可及性。将普通文本描述转换为复杂视觉输出的吸引人能力,引起了体验过的人们的关注。稳定扩散展现了生成高质量图像的能力,同时也表现出显著的速度和效率,从而提高了 AI 生成艺术创作的可及性。

稳定扩散的训练涉及了像 LAION-5B 这样的大型公开数据集,利用广泛的带注释图像来提升其艺术能力。然而,推动其进展的一个关键方面在于社区的积极参与,提供的宝贵反馈推动了模型的持续发展,并随着时间的推移增强了其能力。

它是如何工作的?

让我们从稳定扩散模型的主要构建模块开始,了解如何分别训练和进行预测。

U-Net 与扩散过程的本质:

为了使用计算机视觉模型生成图像,我们超越了依赖标记数据(如分类、检测或分割)的传统方法。在稳定扩散的领域,目标是使模型能够学习图像本身的复杂细节,以一种被称为“扩散”的创新方法捕捉复杂的上下文。

扩散过程分为两个不同的阶段:

  • 在第一部分,我们获取一张图像并引入一定量的随机噪声。这一步被称为正向扩散

  • 在第二部分,我们的目标是去噪图像并重建原始内容。这个过程被称为反向扩散

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

按步骤添加噪声。来源: 通过去噪扩散 GAN 解决生成学习三难问题

第一部分涉及在每个时间步t向输入图像添加高斯噪声,较为直接。然而,第二阶段则存在挑战,因为直接计算原始图像是不可行的。为了克服这一障碍,我们使用了神经网络,这就是巧妙的U-Net发挥作用的地方。

利用U-Net,我们训练我们的模型来预测在时间步 t 的给定随机噪声图像中的噪声,并计算预测噪声与实际噪声之间的损失。通过使用足够大的数据集和多个噪声步骤,模型获得了对噪声模式进行有根据预测的能力。这个训练过的 U-Net 模型对于从给定噪声生成图像的近似重建也证明是非常宝贵的。

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

反向扩散。来源: 去噪扩散概率模型

如果你对基本概率和计算机视觉模型熟悉,这个过程是相对直接的。然而,还有一个问题值得注意。训练数百万张添加了噪声的图像并重建它们将非常耗时,并消耗计算能力。为了应对这一挑战,研究人员重新审视了一种知名架构:自编码器。由于我们已经采用了类似的方法,如使用 U-Net 结合转置卷积和残差块,这些元素在自编码器中也将发挥重要作用。

使用自编码器,可以将数据“编码”到一个更小的“潜在”空间中,然后将其“解码”回原始空间。实际上,这就是为什么原始稳定扩散论文被称为潜在扩散。这使我们能够有效地将大图像压缩到较低的维度。

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

简单的自编码器表示。图像由作者提供。

正向和反向扩散操作现在将在显著较小的潜在空间中进行,从而减少了内存需求并显著加快了处理速度。

我们几乎完成了著名的“稳定扩散”架构;唯一剩下的部分是条件化。通常,这个方面是通过文本编码器实现的,尽管也存在使用图像作为条件化的方法,如ControlNet,但这超出了本文的范围。文本条件化在基于文本提示生成图像中扮演着至关重要的角色,这也是稳定扩散模型的真正魔力所在。

为此,我们可以训练像 BERTCLIP 这样的文本嵌入模型,使用带有标题的图像,并将标记嵌入向量作为条件输入。通过采用 交叉注意力 机制(查询、键和值),我们可以将条件文本嵌入映射到 U-Net 残差块中。因此,我们可以在训练过程中将图像标题与图像本身一起纳入,并有效地基于提供的文本调整图像生成。

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

潜在扩散模型 — 来源:论文

现在你已经了解了 Stable Diffusion 模型的构建块,凭借这些知识,我们可以更好地比较之前的 Stable Diffusion 模型,并对它们的优缺点做出更为全面的评估。

SDXL 有什么新变化?

现在我们已经掌握了 SD 模型的基础知识,让我们深入研究 SDXL 论文,揭示这一新模型引入的变革性变化。总的来说,SDXL 提出了以下改进:

  • 增加的 U-Net 参数数量: SDXL 通过引入更多的 U-Net 参数来增强模型能力,从而实现更复杂的图像生成。

  • 变换器块的异质分布: 与之前模型中的均匀分布([1,1,1,1])不同,SDXL 采用了异质分布([0,2,4]),引入了优化和改进的学习能力。

  • 增强的文本条件编码器: SDXL 利用更大的文本条件编码器 OpenCLIP ViT-bigG,有效地将文本信息融入图像生成过程中。

  • 附加文本编码器: 该模型采用了附加文本编码器 CLIP ViT-L,连接其输出,丰富了条件处理过程中的文本特征。

  • 引入“尺寸条件”: 一种名为“尺寸条件”的新型调节器将原始训练图像的宽度和高度作为条件输入,使模型能够根据与尺寸相关的提示调整图像生成。

  • “裁剪条件”参数: SDXL 引入了“裁剪条件”参数,将图像裁剪坐标作为条件输入。

  • “多方面条件”参数: 通过纳入条件的桶大小,“多方面条件”参数使 SDXL 能够适应不同的纵横比。

  • 专用精炼器模型: SDXL 引入了第二个专门处理高质量、高分辨率数据的 SD 模型;本质上,它是一个 img2img 模型,能够有效捕捉复杂的局部细节。

现在,让我们更详细地查看这些新增功能与之前稳定扩散模型的比较。

Stability.ai 官方比较:

让我们首先查看稳定性.ai 的官方比较,由作者呈现。这一比较提供了有关 SDXL 与 Stable Diffusion 之间用户偏好的有价值的见解。然而,我们必须谨慎对待这些发现……

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

比较 SDXL 与之前模型的用户偏好。来源:论文

这项研究表明,参与者选择了 SDXL 模型而非之前的 SD 1.5 和 2.1 模型。特别是,添加了 Refiner 的 SDXL 模型实现了 48.44%的胜率。需要注意的是,尽管这一结果在统计上具有显著性,但我们还必须考虑由人为因素引入的固有偏差以及生成模型的随机性。

与最先进黑箱模型的性能比较:

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

来源:论文

目前,Midjourney 在用户中非常受欢迎,有些人认为它目前是最先进的解决方案。根据官方调查,SDXL 在“食品和饮料”和“动物”等类别中表现出较高的偏好率。然而,在“插图”和“抽象”等其他类别中,用户仍然偏好 Midjourney V5.1。

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

来源:SDXL: 提升潜在扩散模型以实现高分辨率图像合成

再次观察复杂提示的情况,我们看到类似的模式。论文声明它们在 10 个复杂主题中的 7 个中受到青睐。然而,如果不了解具体的提示内容,就很难得出结论。此外,关于 Midjourney 中提示编码器的信息缺乏进一步复杂化了问题,只有时间才能揭示真正的偏好。

U-Net 参数数量

如前所述,U-Net 模型在 Stable Diffusion 中发挥着至关重要的作用,帮助从给定的噪声中重建图像。在 SDXL 中,作者通过引入一个比之前版本 SD 大得多的 U-Net 模型做出了显著改进,总计 2.6B 的 U-Net 参数,相较于其前身的~860M。

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

图片由作者提供。

尽管拥有更多参数可能初看起来很有前景,但必须考虑复杂性与质量之间的权衡。随着参数数量的增加,系统在训练和生成时的需求也会增加。虽然对于产品质量的最终结论还为时尚早,但复杂性与质量之间的权衡已经显而易见。

文本编码器参数数量

确实,当审视文本编码器的总参数数量时,我们观察到 SDXL 1.0 相比于其前身有显著增加。SDXL 中引入了两个文本条件器,而之前版本中只有一个,这使得文本编码器的参数数量大幅增长。这一扩展使得 SDXL 能够利用更大容量的文本信息。

SDXL 使用具有 6.947 亿参数的 OpenCLIP G/14 文本编码器,相比之下 CLIP L/14 具有 1.2365 亿参数,总计超过 8 亿参数。这代表了与其前身相比的重大飞跃。

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

图片由作者提供。

再次,使用更大和多个文本编码器最初可能看起来很有吸引力,但它引入的额外复杂性可能会产生不利影响。考虑到一个场景,其中你正在用自己的数据对 SDXL 模型进行微调。在这种情况下,确定最佳参数比以前的 SD 模型更具挑战性,因为找到两个编码器的超参数“甜蜜点”变得更加难以捉摸。

工作流程

确实,SDXL 中的“XL”一词表明了其相比于之前的 SD 模型在规模和复杂性上的扩展。SDXL 在多个方面超越了其前身,拥有更多的参数,包括两个文本编码器和两个 U-Net 模型——基础模型和细化模型,后者本质上作为图像到图像模型使用。自然,这种 SDXL 管道的复杂性增加:

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

通常的 SD 1.5 生成管道。图片由作者提供

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

SDXL 生成管道。图片由作者提供

SDXL 实践

SDXL 的模型权重已经正式发布,并可以作为 Python 脚本自由使用,感谢 Hugging Face 的 diffusers 库。此外,还有一个用户友好的 GUI 选项,称为 ComfyUI。这个 GUI 提供了一个高度可定制的基于节点的界面,允许用户直观地放置 Stable Diffusion 模型的构建块并进行可视化连接。

使用这些现成的实现,用户可以将 SDXL 无缝集成到他们的项目中,从而能够利用这一前沿的潜在文本到图像扩散模型的强大功能。

Diffusers 使用的基本示例

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

ComfyUI 工作流程管道示例。图片由作者提供。

SDXL 的当前状态和个人体验

尽管 SDXL 中的新功能和附加功能看起来很有前景,但一些经过微调的 SD 1.5 模型仍然提供更好的结果。这一结果主要归因于蓬勃发展的社区的巨大支持——这是开放源代码方法带来的优势。

在其初始模型阶段,SDXL 相比于 1.5 有了改进,我相信在持续的社区支持下,其性能未来只会更强。然而,需要认识到,随着模型的复杂性增加,使用和微调它们在计算上需要更多资源。但目前还不需要过于担忧……

LoRA(局部秩自适应分解)在大型语言模型的微调中越来越受欢迎。这种方法涉及将秩分解权重矩阵对添加到现有权重中,并仅训练这些新添加的权重。因此,训练变得更快且计算上更高效。LoRA 的引入预计将为社区创造出更好的定制版本铺平道路。值得注意的是,SDXL 已经完全支持 LoRA。

尽管有积极的发展,但值得注意的是,SDXL 仍然面临一些常见的 Stable Diffusion 缺陷,正如作者们正式承认的那样:

  • 该模型未能达到完美的照片现实主义。

  • 该模型无法渲染清晰的文本。

  • 该模型在处理涉及组合性的更复杂任务时表现不佳,例如渲染对应于“一个红色立方体在一个蓝色球体上方”的图像。

  • 脸部和一般人物可能无法正确生成。

  • 模型的自动编码部分是有损的。

个人观察

就个人而言,在实验 SDXL 模型时,我仍然发现自己在某些情况下更倾向于使用之前的 SD 1.5 社区检查点。在社区支持的几个月后,找到适合特定需求的微调模型(如照片现实主义或更卡通风格)相对容易。然而,由于对计算能力的高需求,目前难以找到针对 SDXL 的特定微调模型。尽管如此,SDXL 的基础模型在图像质量和分辨率方面似乎优于 SD 1.5 或 2.1 的基础模型,随着进一步的优化和时间,这种情况在不久的将来可能会发生变化。

值得注意的是,随着模型规模的增大,一些用户报告在日常笔记本电脑或 PC 上运行模型时遇到困难,这令人遗憾。我希望大型语言模型中常用的量化技术也能在这一领域找到应用。

此外,由于文本编码器的变化,我的常用提示在 SDXL 上不再产生令人满意的结果。尽管 SDXL 的开发者声称在 SDXL 上提示更容易,但我自己尚未找到合适的方法。适应新的提示风格可能需要一些时间,尤其是对于那些来自早期版本的人。

结论

  • 在我们的文章中,我们发现了 Stable Diffusion XL 的能力,这一模型能够将普通文本描述转化为复杂的视觉表现。我们发现 SDXL 的开源特性及其解决黑箱模型相关问题的方法为其广泛吸引力做出了贡献,使其能够接触到更广泛的受众。

  • SDXL 通过增加参数数量和额外功能,证明了自己是一个“XL”模型,与前辈相比,具备了更高的复杂性。

  • 实践中实施 SDXL 已变得更加容易,官方发布的模型权重可以作为 Python 脚本从 huggingface 自由获取,并提供了用户友好的 ComfyUI GUI 选项。

  • 尽管 SDXL 展示了巨大的潜力,但通向完美的道路仍在继续。一些精细调整过的 SD 1.5 模型在某些情况下仍优于 SDXL,这得益于活跃的社区支持。然而,凭借积极的参与和支持,我相信 SDXL 将继续随着时间的推移不断演进和改进。

  • 然而,需要承认的是,像其前辈一样,SDXL 确实存在一些局限性。实现完美的照片现实主义、渲染清晰的文本、处理组合挑战以及准确生成面孔和人物是模型需要改进的领域。

  • 总结来说,SDXL 1.0 代表了文本到图像生成的重大飞跃,释放了 AI 的创作潜力,并推动了可能性的边界。随着 AI 社区的持续合作和创新,我们可以期待在迷人的 SD 模型及其未来的发展中见证更多令人惊叹的进展。

参考文献:

优质数据分析的艺术

原文:towardsdatascience.com/the-art-of-making-quality-data-analyses-a91ea319b573?source=collection_archive---------4-----------------------#2023-12-05

用 3 个词总结:时效性、方法论和可消化性

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

·

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

几周前,我写了关于构建系统以生成更多优质洞察的文章。我展示了如何通过改进流程、工具、文化等领域来提高团队的产出,但我从未定义“质量”意味着什么——所以这周,我们将深入探讨这一概念。

通常当有人谈论数据研究的质量时——我们会立即想到“确保数据分析的准确性和结果的可靠性”。我认为这只是定义的一部分。根据我 8 年以上的分析经验,数据分析要被认为是“优质工作”,它必须融合三个基本元素。

  • 它以及时的精确度解决了实际需求。

  • 这得到了一个稳健且经过验证的方法论的支持。

  • 组织能够消化这些内容。

让我们深入探讨

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

成功的数据分析包含的内容 — 作者插图

以及时的精确性满足实际需求

要使数据分析真正具有影响力,关键在于其针对一个真实且明确的需求。这意味着需要准确了解所解决的问题、识别受影响的对象、认识到其在当前时刻的相关性,并明确分析结果将如何被具体应用。这种理解的精确程度直接关系到你的分析对最终用户的价值。

确定实际需求 — 而不是感知需求 — 是至关重要的。这将确保分析不仅在理论上有用,而且在实践中可应用。这将确保在项目的最后一天,当你向利益相关者展示时,不会出现诸如“那么……接下来呢?”的问题。这将使你提供具有洞察力和可操作的数据,而不是提供虽然有趣但可能不立即有用的信息。

例如,一家零售公司可能会感受到需要广泛分析客户人口统计数据,但实际需求可能是理解某个特定年龄组的购买模式。后者直接影响营销策略和库存决策,从而对业务运营产生更深远的影响。

同样重要的是分析的及时性。这个方面包含两个关键要素:当前时刻需求的相关性,以及提供分析的速度。

  • 需求的相关性: 企业的需求通常是时间敏感的,并且可能会迅速变化——尤其是当你在一个快速变化的组织中时。解决当前紧迫问题的分析比那些来得过晚或做得过早的分析更有价值。例如,在主要节假日之前对消费者趋势的分析对企业在库存和营销方面至关重要,但如果在假期开始后才出现,这个机会就会丧失。

  • 分析的及时性: 分析交付的速度同样至关重要——因为这影响到需求的相关性。这是一个需要考虑的重要因素,因为有时你可能需要在研究的全面性与速度之间做出权衡(例如,如果社交媒体上出现了一个新趋势,而你的公司希望对一个热门话题进行分析——你不能花两个月的时间才给出结果)。

总结来说,当数据分析准确识别并解决一个真实的、当前的需求,并且以及时的方式交付,从而确保最大相关性和影响力时,其成功的概率将显著提高。

拥有一个结构化的方法论

我经常看到没有使用任何标准方法论的数据分析。虽然这不一定意味着研究会很差,但不遵循经过验证的方法论会大大降低你完成高质量工作的机会。

结构化/标准化的方法确保了全面性,同时提升了分析的可信度和可重复性。

我发现一个容易遵循的方法论是跨行业数据挖掘标准流程(CRISP-DM)框架。在这个领域工作了近十年,这仍然是我在从头开始分析时的首选框架。这个框架——被称为标准的“数据科学”/“数据分析”流程——有 6 个主要阶段:

  • 业务理解: 在这个阶段,数据分析师应全面了解“业务背景”:我们要解决的痛点是什么,我们过去做了什么,谁是“参与者”,风险、资源等是什么——以及非常重要的是,项目的成功标准是什么。

  • 数据理解: 这个阶段涉及熟悉数据——它是对数据进行描述性和探索性分析,并识别数据质量问题。它是你自己的“初步调查”,你开始掌握数据的细微差别和潜力。

  • 数据准备: 这个阶段是关于选择你想要处理的数据——包括包含/排除的理由——然后清理和转换数据,以适合分析的格式。这就像在做饭前准备原料一样——对良好的结果至关重要。

  • 建模: “建模”的概念可能让一些人感到畏惧——但建模可以像为一个真/假指标“创建一个特定的阈值”一样简单(例如,如果你的项目是理解/定义流失)。在这个阶段,将各种建模技术应用于准备好的数据,以便你可以将它们相互对比,并了解哪些是最成功的。

  • 评估: 现在对模型进行严格评估,以确保它们达到业务目标以及在第 1 阶段设定的成功标准。这通常会导致你获得可以用来回顾和修订业务理解的见解。

  • 部署: 最后一个阶段涉及将模型应用于实际数据和情况,将分析付诸实践,并开始使用这些见解来改进团队的运营。

这个框架通过迫使你经过这些不同的步骤,从而增加了你的分析更为稳健的机会——同时留有创造性的空间。

使你的工作易于理解

易读性不仅仅是简化复杂信息和使你的幻灯片更易于理解。这涉及两个重要方面:(1)从观众那里培养深层次的理解,以及(2)使他们能够以实际、有效的方式应用这些见解。这个过程类似于身体不仅消化食物,还利用营养物质来驱动各种功能。

从观众那里培养深层次的理解

实现这一点需要使数据对观众既可访问又引起共鸣。这时,主题专家(SMEs)扮演着关键角色。通过在分析过程中早期涉及 SMEs,他们的领域知识可以指导数据的框架和解释,确保分析与实际情况对接,并以对目标观众有意义的方式呈现。

另一个增强易读性的关键策略是实施‘阶段门’流程,这包括与利益相关者或接收团队进行定期检查和更新。这种方法避免了在研究结束时用一大堆复杂信息压倒他们。相反,利益相关者会被带到整个过程中,让他们逐渐吸收新见解。它还开辟了持续反馈的途径,确保分析始终与观众不断变化的需求和期望保持一致。

想象你在一个大型组织中实施新的数据驱动战略。如果数据团队仅在最终阶段呈现分析而没有事先的参与,利益相关者可能会发现难以掌握其细微之处或看出其与他们具体背景的相关性。然而,通过在定期的间隔中涉及这些利益相关者——通过周期性演示或研讨会——他们会对数据及其影响变得更加熟悉。他们可以提供宝贵的反馈,引导分析朝着对他们最相关的领域发展,从而确保最终成果不仅可理解,而且可以立即采取行动并满足他们的需求。

使观众能够应用这些见解

可操作性围绕着将这种深层理解转化为现实世界的应用或决策。这是关于确保观众能够有效利用这些见解来推动实际结果。真正的关键在于思考分析与现实影响之间的“最后一公里”,以及你如何帮助消除任何阻碍以采纳你的见解。

例如,如果你正在进行一个定义用户流失的项目——使你的研究更易于理解可能包括创建一个仪表板,让你的业务利益相关者清楚地了解你的结果具体是什么样的。

其他想法包括举办研讨会、开发互动可视化等——任何可以帮助团队迅速适应的方式。

总结一下——从一开始就让主题专家(SMEs)参与和与利益相关者保持持续沟通,显著提升了数据分析项目的可消化性。这种协作方法确保了研究不仅易于理解,而且直接相关且有价值,符合其预期受益者的需求。

总结

成功的数据分析是技术熟练、战略对齐和实际适用性的结合体。它不仅仅是遵循一套步骤,而是理解并根据每个项目独特的背景调整这些步骤。及时性、正确执行和解决实际的组织需求是支撑连接数据分析与组织成功的桥梁的支柱。最终目标是将数据转化为能驱动价值和指导战略决策的可行洞察。

希望您喜欢阅读这篇文章!您有什么想分享的小贴士吗?在评论区告诉大家吧!

PS:此文章已经发布到 Analytics Explained,这是一个新闻简报,我在其中总结了我在各种分析角色(从新加坡初创公司到旧金山的大科技公司)中学到的内容,并回答读者关于分析、增长和职业方面的问题。

《提示设计的艺术:提示边界与标记修复》

原文:towardsdatascience.com/the-art-of-prompt-design-prompt-boundaries-and-token-healing-3b2448b0be38?source=collection_archive---------2-----------------------#2023-05-08

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

·

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

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

所有图像均为原创作品。

这篇文章(与 Marco Tulio Ribeiro 共同撰写)是关于提示设计艺术系列的第二部分(第一部分 这里),在其中我们讨论了如何通过 [guidance](https://github.com/microsoft/guidance) 控制大型语言模型(LLMs)。

在这篇文章中,我们将讨论语言模型使用的贪婪/优化标记化方法如何在提示中引入微妙而强大的偏差,从而导致令人困惑的生成结果。

语言模型不是在原始文本上进行训练,而是在标记(tokens)上进行训练,标记是经常一起出现的文本块,类似于单词。这会影响语言模型如何“看待”文本,包括提示(因为提示只是标记的集合)。GPT 风格的模型使用像 字节对编码(BPE)这样的标记化方法,它们以贪婪的方式将所有输入字节映射到标记 ID。这在训练时是可以接受的,但在推理过程中可能会导致微妙的问题,如下例所示。

提示边界问题的一个例子

考虑以下示例,我们正在尝试生成 HTTP URL 字符串:

import transformers

# we use StableLM as an example, but these issues impact all models to varying degrees
generator = transformers.pipeline('text-generation', model='stabilityai/stablelm-base-alpha-3b')

raw_gen('The link is <a href="http:') # helper func to call the generator

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

笔记本输出。

注意,LLM 生成的输出没有用明显的下一个字符(两个斜杠)完成 URL。它反而创建了一个中间带有空格的无效 URL 字符串。这令人惊讶,因为在 http: 之后 // 的补全是非常明显的。要理解为什么会发生这种情况,让我们改变我们的提示边界,使提示不包括冒号字符:

raw_gen('The link is <a href="http')

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

现在,语言模型生成了我们预期的有效 URL 字符串。要理解 : 的重要性,我们需要查看提示的标记化表示。下面是以冒号结尾的提示的标记化(不包含冒号的提示有相同的标记化,除了最后一个标记):

print_tokens(generator.tokenizer.encode('The link is <a href="http:'))

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

现在注意有效 URL 的标记化是什么样的,特别关注 http 后的标记 1358

print_tokens(generator.tokenizer.encode('The link is <a href="http://www.google.com/search?q'))

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

大多数 LLM(包括这个)使用贪婪的标记化方法,总是偏向于选择最长的标记,即 :// 在完整文本中(例如在训练中)总是优于 :

在训练中,URL 使用标记 1358(://)进行编码,而我们的提示使 LLM 看到标记 27:),这会通过人为地将 :// 拆分开来,从而影响完成。

实际上,模型可以非常确定看到标记 27:)意味着接下来的内容极不可能是可以与冒号一起编码的“更长的标记”像 ://,因为在模型的训练数据中,这些字符会与冒号一起编码(稍后我们将讨论的一个例外是训练期间的子词正则化)。看到一个标记意味着同时看到该标记的嵌入 以及 之后的内容没有被贪婪的标记化器压缩,这一点容易被忘记,但在提示边界中很重要。

让我们搜索模型词汇表中所有标记的字符串表示,看看哪些标记以冒号开头:

N = generator.tokenizer.vocab_size
tokens = generator.tokenizer.convert_ids_to_tokens(range(N))
print_tokens([i for i,t in enumerate(tokens) if t.startswith(":")])

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

请注意,有34种不同的令牌以冒号开头,因此以冒号结尾的提示可能不会生成这些34种令牌字符串中的任何一种。这种微妙而强大的偏差可能会带来各种意想不到的后果。 这适用于任何可能被扩展为更长单一令牌的字符串(不仅仅是 :)。即使是我们以“http”结尾的“固定”提示也存在内建偏差,因为它向模型传达了“http”后面内容可能不是“s”(否则“http”不会被编码为单独的令牌):

print_tokens([i for i,t in enumerate(tokens) if t.startswith("http")])

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

以为这是只影响 URL 的深奥问题而不值得担忧,请记住,大多数令牌化器会根据令牌是否以空格、标点、引号等开头来处理令牌,因此以这些内容结尾的提示可能会导致错误的令牌边界,从而破坏内容:

# Accidentally adding a space, will lead to weird generation
raw_gen('I read a book about ')

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

# No space, works as expected
raw_gen('I read a book about')

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

另一个例子是“[”字符。考虑以下提示和补全:

raw_gen('An example ["like this"] and another example ')

![

为什么第二个字符串没有被引号括起来?因为通过以“[”令牌结尾,我们告诉模型不生成与以下 27 个更长令牌匹配的补全(其中一个增加了引号字符,15640):

# note the Ġ is converted to a space by the tokenizer
print_tokens([i for i,t in enumerate(tokens) if t.startswith("Ġ[")])

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

令牌边界偏差无处不在。上述 StableLM 模型的*70%最常见令牌是较长可能令牌的前缀,因此在提示中的最后一个令牌时会造成令牌边界偏差。

通过“令牌修复”修正无意的偏差

我们可以做些什么来避免这些无意的偏差?一种选择是始终以不能扩展为更长令牌的令牌结束提示(例如用于基于聊天的模型的角色标签),但这是一种严重限制。

相反,guidance具有一个叫做“令牌修复”的功能,它会在提示末尾之前自动将生成过程备份一个令牌,然后约束生成的第一个令牌具有与提示最后一个令牌匹配的前缀。在我们的 URL 示例中,这将意味着移除 : 并强制生成的第一个令牌具有 : 前缀。令牌修复允许用户以任何他们希望的方式表达提示,而无需担心令牌边界。

例如,让我们重新运行一些上述 URL 示例,并开启令牌修复功能(对于 Transformer 模型,默认是开启的,因此我们去掉 token_healing=False):

from guidance import models, gen

# load StableLM from huggingface
lm = models.Transformers("stabilityai/stablelm-base-alpha-3b", device=0)

# With token healing we generate valid URLs,
# even when the prompt ends with a colon:
lm + 'The link is <a href="http:' + gen(max_tokens=10)

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

# With token healing, we will sometimes generate https URLs,
# even when the prompt ends with "http":
[str(lm + 'The link is <a href="http' + gen(max_tokens=10, temperature=1)) for i in range(10)]

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

同样,我们无需担心额外的空格:

# Accidentally adding a space will not impact generation
lm + 'I read a book about ' + gen(max_tokens=5)

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

# This will generate the same text as above 
lm + 'I read a book about' + gen(max_tokens=6)

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

现在即使提示以“[”令牌结尾,我们也能获得引号括起来的字符串:

lm + 'An example ["like this"] and another example ' + gen(max_tokens=10)

![

那么子词正则化呢?

如果你对语言模型的训练方式很熟悉,你可能会想知道子词正则化在这一切中如何发挥作用。子词正则化是一种技术,在训练过程中随机引入次优的分词,以提高模型的鲁棒性。这意味着模型并不总是看到最佳的贪婪分词。子词正则化有助于提高模型对标记边界的鲁棒性,但它并不能完全消除模型对标准贪婪/优化分词的偏见。这意味着虽然模型的子词正则化程度可能影响标记边界的偏见程度,但所有模型仍然存在这种偏见。如上所示,它仍然可以对模型输出产生强大而意外的影响。

结论

在编写提示时,请记住贪婪分词可能对语言模型如何解释你的提示产生重大影响,尤其是当提示以一个可能扩展为更长标记的标记结束时。这种容易被忽视的偏见来源可能以令人惊讶和意想不到的方式影响你的结果。

为了解决这个问题,可以在提示的末尾加上一个不可扩展的标记,或者使用类似guidance的“标记修复”功能,以便你可以根据自己的意愿表达提示,而不必担心标记边界的影响。

要自己复现本文中的结果,请查看 notebook 版本。

提示设计艺术:使用清晰的语法

原文:towardsdatascience.com/the-art-of-prompt-design-use-clear-syntax-4fc846c1ebd5?source=collection_archive---------0-----------------------#2023-05-02

探索如何通过清晰的语法使你能够向语言模型传达意图,并帮助确保输出结果易于解析

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

·

关注 发表于Towards Data Science ·9 分钟阅读·2023 年 5 月 2 日

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

所有图片均由 Scott 和 Marco 生成。

这是关于如何使用[guidance](https://github.com/guidance-ai/guidance)来控制大型语言模型(LLMs)系列文章的第一篇,由Marco Tulio Ribeiro和我共同撰写。我们将从基础知识开始,逐步深入到更高级的主题。

在这篇文章中,我们将展示明确的语法如何使你能够向 LLM 传达你的意图,并确保输出易于解析(就像保证有效的 JSON)。为了清晰和可重复性,我们将从一个未微调的开源 Mistral 7B 模型开始。然后,我们将展示这些相同的想法如何应用于像 ChatGPT / GPT-4 这样的微调模型。下面的所有代码都可在笔记本中找到,如果你愿意,可以复现。

明确的语法有助于解析输出

使用明确语法的第一个也是最明显的好处是它使得解析 LLM 的输出更容易。即使 LLM 能够生成正确的输出,可能也难以程序化地从输出中提取所需的信息。例如,考虑以下 Guidance 提示(其中gen()是一个guidance命令,用于从 LLM 生成文本):

from guidance import models, gen

# we use Mistral, but any model will do
lm = models.LlamaCpp("path/mistral-7b-v0.1.Q8_0.gguf")

# run a guidance program (by appending to the model state)
lm + "Name common Linux operating system commands." + gen(max_tokens=50)

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

输出在笔记本中的显示方式。

虽然答案是可读的,但输出的格式是任意的(即我们事先不知道),因此难以程序化解析。例如,这里是类似提示的另一轮,其中输出格式非常不同:

lm + "Name common Mac operating system commands." + gen(max_tokens=50)

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

在提示中强制使用明确的语法可以帮助减少任意输出格式的问题。你可以通过几种方式来实现这一点:

1. 在标准提示中给 LLM 提供结构提示(甚至可以使用少量示例)。

2. 使用guidance(或其他包)来强制特定的输出格式。

这些并不是互相排斥的。让我们看一下每种方法的示例。

传统的提示与结构提示

这是一个传统提示的示例,它使用结构提示来鼓励使用特定的输出格式。提示旨在生成一个易于解析的 5 项列表。请注意,与之前的提示相比,我们编写了这个提示,使得 LLM 承诺使用特定的明确语法(数字后跟引号字符串)。这使得生成后的输出更容易解析。

lm +'''\
What are the most common commands used in the Linux operating system?

Here are the 5 most common commands:
1\. "''' + gen(max_tokens=50)

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

请注意,LLM 正确地遵循了语法,但在生成 5 项之后没有停止。我们可以通过创建明确的停止标准来解决这个问题,例如,要求生成 6 项,当看到第六项的开始时停止(这样我们就能得到五项):

lm + '''\
What are the most common commands used in the Linux operating system?

Here are the 6 most common commands:
1\. "''' + gen(max_tokens=100, stop="\n6.")

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

使用指导程序强制语法

与使用提示不同,Guidance 程序强制特定的输出格式,插入属于结构的一部分的标记,而不是让 LLM 生成它们。

例如,这就是我们如何在需要强制编号列表作为格式时操作:

lm2 = lm + """\
What are the most common commands used in the Linux operating system?

Here are the 5 most common commands:
"""
for i in range(5):
    lm2 += f'''{i+1}. "{gen('commands', list_append=True, stop='"')}"\n'''

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

在上面的提示中,lm2 = lm + … 命令将添加一个字符串到起始 lm 状态后产生的新模型状态保存到变量 lm2 中。然后 for 循环通过添加混合字符串和生成序列来迭代更新 lm2。请注意,结构(包括数字和引号)不是由 LLM 生成的。

输出解析由 guidance 程序自动完成,所以我们不需要担心这个问题。在这种情况下,commands 变量将是生成的命令名称列表:

out["commands"]

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

强制有效的 JSON 语法: 使用 guidance 我们可以以绝对的信心创建任何我们想要的语法,确保生成的内容完全遵循我们指定的格式。这对于 JSON 等内容特别有用:

import guidance

# define a re-usable "guidance function" that we can use below
@guidance
def quoted_list(lm, name, n):
    for i in range(n):
        if i > 0:
            lm += ", "
        lm += '"' + gen(name, list_append=True, stop='"') + '"'
    return lm

lm + f"""\
What are the most common commands used in the Linux operating system?

Here are the 5 most common commands in JSON format:
{{
    "commands": [{quoted_list('commands', 5)}],
    "my_favorite_command": "{gen('favorite_command', stop='"')}"
}}"""

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

Guidance 加速: guidance 程序的另一个好处是速度——增量生成实际上比一次性生成整个列表要快,因为 LLM 不需要为列表本身生成语法标记,只需生成实际的命令名称(当输出结构更丰富时,这种差异更为明显)。

如果你使用的模型端点不支持这种加速(例如 OpenAI 模型),那么许多增量的 API 调用会让你变慢,因此 guidance 使用一个单独的运行流(请参见下面我们演示聊天模型的详细信息)。

清晰的语法赋予用户更多控制权

陷入低多样性的困境是大型语言模型(LLMs)常见的失败模式,即使我们使用相对较高的温度也可能发生:

lm2 = lm + """\
What are the most common commands used in the Linux operating system?
"""
for i in range(10):
    lm2 += f'''- "{gen('commands', list_append=True, stop='"', temperature=0.8)}"\n'''

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

在生成项目列表时,列表中的前面项目会影响未来的项目。这可能会导致生成内容中的无用偏差或趋势。解决这个问题的一种可能方法是请求并行完成(以便之前生成的命令不会影响下一条命令的生成):

lm2 = lm + '''\
What are the most common commands used in the Linux operating system?
- "'''
commands = []
for i in range(10):
    lm_tmp = lm2 + gen('command', stop='"', temperature=0.8)
    commands.append(lm_tmp["command"])

out["commands"]

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

我们仍然会有一些重复,但比之前少得多。此外,由于清晰的结构使我们可以轻松解析和操作输出,我们可以轻松地提取输出,去除重复项,并在程序的下一步中使用它们。

这是一个示例程序,它接受列出的命令,挑选其中一个,并对其进行进一步操作:

lm2 = lm + 'What are the most common commands used in the Linux operating system?\n'

# generate a bunch of command names
lm_tmp = lm2 + 'Here is a common command: "'
for i in range(10):
    commands.append(lm_tmp.gen('command', stop='"', max_tokens=20, temperature=1.0)["command"])

# discuss them
for i,command in enumerate(set(commands)):
    lm2 += f'{i+1}. "{command}"\n'
lm2 += f'''\
Perhaps the most useful command from that list is: "{gen('cool_command', stop='"')}", because {gen('cool_command_desc', max_tokens=100, stop=guidance.newline)}
On a scale of 1-10, it has a coolness factor of: {gen('coolness', regex="[0-9]+")}.'''

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

我们在上述程序中引入了一种导入控制方法:生成的 regex 参数。命令 gen('coolness', regex='[0–9]+') 使用正则表达式对输出强制执行某种语法(即强制输出匹配任意正则表达式)。在这种情况下,我们强制 coolness 分数为一个整数(注意一旦模型完成模式生成并开始生成其他内容,生成过程将停止)。

将清晰的语法与特定模型的结构(如聊天)结合

上述所有示例都使用了基础模型,而没有经过后续的微调。但如果你使用的模型有微调,重要的是将清晰的语法与已经调整到模型中的结构结合起来。

例如,聊天模型已经过微调,以期望在提示中包含多个“角色”标签。我们可以利用这些标签进一步增强程序/提示的结构。

以下示例将上述提示调整为适用于基于聊天的模型。guidance 有特殊的角色标签(如 user()),这些标签允许你标记不同的角色,并自动将其转换为你使用的 LLM 所需的正确特殊令牌或 API 调用。这有助于使提示更易读,并使其在不同的聊天模型中更加通用。

from guidance import user, assistant, system

# load a chat model
chat_lm = models.llama_cpp.MistralChat("path/mistral-7b-instruct-v0.2.Q8_0.gguf")

with user():
    lm2 = chat_lm + "What are the most common commands used in the Linux operating system?"

with assistant():

    # generate a bunch of command names
    lm_tmp = lm2 + 'Here are ten common command names:\n'
    for i in range(10):
        lm_tmp += f'{i+1}. "' + gen('commands', list_append=True, stop='"', max_tokens=20, temperature=0.7) + '"\n'

    # discuss them
    for i,command in enumerate(set(lm_tmp["commands"])):
        lm2 += f'{i+1}. "{command}"\n'
    lm2 += f'''Perhaps the most useful command from that list is: "{gen('cool_command', stop='"')}", because {gen('cool_command_desc', max_tokens=100, stop=guidance.newline)}
On a scale of 1-10, it has a coolness factor of: {gen('coolness', regex="[0-9]+")}.'''

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

以笔记本中显示的形式输出。

使用 API 限制模型

当我们控制生成时,我们可以在过程的任何步骤中引导输出。但一些模型端点(例如 OpenAI 的 ChatGPT)目前有更有限的 API,例如,我们不能控制每个 role 块内部发生的事情。

虽然这限制了用户的能力,但我们仍然可以使用语法提示的子集,并在角色块之外强制执行结构:

# open an OpenAI chat model
gpt35 = models.OpenAI("gpt-3.5-turbo")

with system():
    lm += "You are an expert unix systems admin that is willing follow any instructions."

with user():
    lm += f"""\
What are the top ten most common commands used in the Linux operating system?

List the commands one per line.  Please list them as 1\. "command" ...one per line with double quotes and no description."""

# generate a list of commands
with assistant():
    lm_inner = lm
    for i in range(10):
        lm_inner += f'''{i+1}. "{gen('commands', list_append=True, stop='"', temperature=1)}"\n'''

# filter to make sure they are all unique then add them to the context (just as an example)
with assistant():
    for i,command in enumerate(set(lm_inner["commands"])):
        lm += f'{i+1}. "{command}"\n'

with user():
    lm += "If you were to guess, which of the above commands would a sys admin think was the coolest? Just name the command, don't print anything else."

with assistant():
    lm += gen('cool_command')

with user():
    lm += "What is that command's coolness factor on a scale from 0-10? Just write the digit and nothing else."

with assistant():
    lm += gen('coolness', regex="[0-9]+")

with user():
    lm += "Why is that command so cool?"

with assistant():
    lm += gen('cool_command_desc', max_tokens=100)

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

总结

每当你构建一个控制模型的提示时,重要的是要考虑提示的内容以及 syntax

清晰的语法使解析输出变得更容易,有助于 LLM 生成符合你意图的输出,并且让你能够编写复杂的多步骤程序。

即使是一个微不足道的示例(列出常见的操作系统命令)也会从清晰的语法中受益,更复杂的任务受益更多。我们希望这篇文章能给你一些如何利用清晰的语法来改进提示的想法。

同时,请务必查看一下 [guidance](https://github.com/guidance-ai/guidance)。虽然你不一定需要它来编写具有清晰语法的提示,但我们认为它可以让你做到这一点变得容易得多

解决任何数据科学问题的艺术 — 提高结果的简单技巧

原文:towardsdatascience.com/the-art-of-solving-any-data-science-problem-simple-tips-for-a-better-outcome-b9d4a484166e

避免麻烦并增加成功机会的未言明建议

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

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

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

图片由 Olav Ahrens Røtne 提供,来源于 Unsplash

对数据科学感兴趣的大多数人学习解决数据科学问题的工具和技术。这些工具和技术在构建解决方案时绝对必要。但请记住,这仅仅是不够的。要提出高效的解决方案,人们需要学习问题解决的艺术。有很多课程教授数据科学中的工具和技术,但很少有课程教如何解决数据科学问题。

在这篇文章中,我的目标是通过实际案例帮助你理解解决数据科学问题的关键方面。我们还将看到这些如何帮助识别和解决核心业务问题,以及如何避免导致问题的常见陷阱。

为了确保这里讨论的概念更易于理解,我将以电信领域的客户流失为例。

问题概念化

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

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

首要目标应明确问题。诸如客户流失等问题可能非常棘手。一般而言,当客户停止使用产品或服务时,他们会被认为是流失。在电信行业,我们可以简单地将转向竞争对手或终止服务的客户视为流失。但有些情况可能不容易定义客户流失,例如在电子商务中。不同的电子商务客户可能会以不同的频率使用平台。因此,在这种情况下,需要进行广泛的数据分析以准确定义客户流失。另一个例子是约会网站,如何区分在平台上找到约会的人和因糟糕体验而退出的人。

现在回到电信行业的客户流失例子。应该花时间更好地理解客户行为。对客户有良好的理解将有助于更好地概念化问题,从而开发更好的解决方案。以下是一些有助于更好理解客户流失的问题。

  • 客户的平均任期是多少?

  • 客户的平均收入是多少?

  • 客户的平均生命周期价值是多少?

  • 获得新客户的成本是多少?

  • 每月新增客户数量是多少?

  • 客户支持部门报告的前 10 个投诉是什么?

  • 哪些事件可能导致客户流失?

  • 流失的客户去哪里/可能去哪里?

  • 竞争的评判标准是什么?

  • 根据内部团队的反馈,客户流失的原因是什么?通常,这些原因不会一致。

这些问题有助于清晰地概念化问题并专注于实现目标的解决方案。稍后在本文中,我将讨论可以用来更好理解问题的思维模型。

  • 我们是否应该关注导致客户流失的事件,从而防止这些事件发生?

  • 我们是否应该预测客户可能流失并防止他们流失?

  • 我们是否只应专注于获得更多的新客户?

虽然在问题概念化中以数据驱动是好的,但以目的驱动更为重要。以数据驱动,我们在关键决策中利用数据,但通过目的驱动,还考虑了既定目标和目的。以目的驱动确保解决方案与组织的整体目标一致。

对数据环境的良好理解和灵活应对

在现实情况下,数据科学团队并不会提供解决问题所需的数据。数据科学家的主要职责之一是收集解决问题所需的所有数据。在大多数组织中,数据分布在来自不同平台的多个来源中。

在解决数据科学问题时,数据科学家通常会提出几个假设。在客户流失的情况下,一些相关的假设包括:

  • 客户是否因为客服团队处理问题不当而离开?

  • 客户是否因为竞争对手提供更好的优惠而离开?

  • 客户是否因为服务差而离开?

  • 客户是否因为技术问题而离开?

  • 年轻专业人士在首次未解决的投诉后是否更容易流失?

  • 长期客户支付更高价格是否更容易流失?

基于上述一些假设,分析中需要考虑的相关数据集包括:

  • 客户档案数据

  • 客户使用和账单数据

  • 投诉数据和其他客户互动数据

  • 关于技术问题的数据

  • 关于竞争对手及其优惠的数据

更好地理解数据环境将有助于,

  • 容易识别所有相关的数据集以验证假设

  • 整合不同来源的数据集,并理解其局限性

  • 了解数据质量问题,从而更好地准备应对这些问题

  • 确保按照合规要求以安全和道德的方式处理个人身份信息

  • 对数据集有良好的理解有助于数据探索。

避免分析中的偏见

对于我们正在解决的问题有看法是完全正常的。但是应注意确保这不会影响我们正在构建的解决方案或执行的分析。偏见不仅可能对项目产生很大影响,还可能对组织及其声誉造成负面影响。以下是偏见应得到妥善处理的主要原因:

  • 这会导致不准确的结果,从而做出错误决策,进而对业务产生不良结果

  • 这可能导致歧视性结果,使一部分人群处于不利地位

  • 这可能导致对组织缺乏信任

为了更好地解释这个问题,我们以医学科学领域为例。如果用于诊断和治疗决策的模型因为训练数据不足而对某个群体或种族存在偏见,这可能会导致不准确的诊断和错误的治疗决策。这是选择偏差的经典例子。

同样地,假设一个政府机构或组织利用历史犯罪数据来识别可能重犯的人。历史数据中的偏见可能导致对某些群体的歧视和不公正。因此,在解决数据科学问题时,考虑偏见总是非常重要的。

让我们回到客户流失的例子。如果我们训练模型的数据没有代表某些群体,可能会导致结果偏斜。以下是避免分析中偏见的一些建议:

  • 使用一个准确代表数据分析人群的样本

  • 确保所有相关数据都被考虑用于数据分析

  • 在独立数据集上测试模型以衡量实际性能

  • 拥有多样化的团队并让他们参与关键项目相关决策

  • 在解释结果时,总是寻找其他解释。

  • 探索数据集中可能显示潜在偏见迹象的模式

  • 清楚地记录过程、结果和解释,以便第三方可以审查是否存在偏见

头脑风暴

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

图片由 Jason Goodman 提供,来源于 Unsplash

头脑风暴不仅有助于避免偏见,而且在数据科学项目的成功中也非常有帮助。头脑风暴有助于产生广泛的想法,这对提出创新解决方案至关重要。以下是头脑风暴的一些好处,

  • 它有助于提出独创性的方法来解决问题

  • 这有助于促进团队成员之间更好的合作

  • 它引入了不同的观点,以提出全面的解决方案

  • 这是许多创新解决方案的关键原因之一

头脑风暴会议不仅仅用于内部团队讨论。为了获得更好的结果,这些会议应该是跨职能的。在处理客户流失问题时,所有直接或间接受到影响的相关方都应参与相关会议。例如,问题概念化应包括与以下团队进行头脑风暴。

  • 客户支持团队:他们了解一些客户面临的关键问题

  • 技术团队:他们了解新发布的功能和不同平台上的问题。

  • 营销团队:他们对竞争中的活动和优惠有更好的了解。

使用心理模型来促进结构化思维

心理模型是一组工具,提供了理解和理清复杂信息的指导。在数据科学中,心理模型有助于更好地理解问题并简化问题解决过程。

让我们看看心理模型如何帮助解决客户流失问题。以下是一篇文章,解释了如何使用第一性原理来解决客户流失。

## 如何使用第一性原理解决数据科学问题?

towardsdatascience.com

下面是心理模型在数据科学项目各个阶段中的作用。

  • 问题定义:解决数据科学问题的第一步是理解问题。像第一性原理思维和费曼技巧这样的框架有助于更好地理解我们尝试解决的问题。

  • 数据探索:探索性数据分析完全是关于提出相关问题并确保在解决问题时考虑到所有可能性。在这里可以采用的一些心理模型包括第一性原理思维、第二排序思维、自下而上和自上而下的方法,以及概率思维。

  • 特征工程:心理模型有助于更好地理解领域和识别重要特征。在这里,有用的一些心理模型包括逆向思维、多重因果关系、根本原因和临近原因。

心理模型是帮助清晰思考的框架。我坚信心理模型可以用来解决任何类型的数据科学问题。我总是尽力利用思维框架来处理问题。如果你也觉得这很有趣并想进一步探索,这里有一篇关于利用心理模型提升数据科学职业生涯的文章。

## 5 种心理模型助力数据科学职业生涯

激发超强思维的简单框架

towardsdatascience.com

解决任何数据科学问题时需要记住的事项

以下是你在处理问题时需要牢记的重要因素。这些因素可能与任何你从事的工作相关。

没有小工作

所有工作都非常重要,不应被轻视。许多数据科学项目涉及大量数据分析,但不涉及模型构建。对于数据科学新手来说,他们通常认为不需要模型构建的问题不够重要。理解这一点非常重要:业务关注的不是使用的模型或实现的复杂算法,而是它是否解决了问题。不要因为工作不涉及算法就轻视它!

这对于数据科学职业生涯的成功至关重要。人们总是会因为努力工作而被同行铭记。强烈的职业道德和愿意付出努力的态度在雇主眼中非常重要,它们总是会带来更好的职业机会。

永不妥协

另一个重要的事项是保持“永不满足”的态度。人们不应满足于简单的解决方案。你应该始终寻找机会来提升你的解决方案或方法。虽然这适用于任何职业,但在数据科学领域我发现它尤为重要。总会有交付解决方案的压力,但不应以此作为满足于简单解决方案的理由。有些选项可能需要更多努力,或者有时可能要求你学习新技能。保持开放的心态和永不满足的态度对长期职业成功帮助很大。

为了保持联系

使用非线性编程优化您的营销预算

原文:towardsdatascience.com/the-art-of-spending-optimizing-your-marketing-budget-with-nonlinear-optimization-6c8a39afb3c2

介绍 CVXPY,以最大化营销投资回报率

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

·发表于 Towards Data Science ·阅读时长 9 分钟·2023 年 5 月 22 日

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

图片由作者提供

在数字营销时代,企业面临着在多个渠道上分配营销预算以最大化销售的挑战。

然而,随着他们扩大覆盖范围,这些公司不可避免地面临 收益递减 的问题——这一现象指的是在营销渠道上额外投资会带来逐渐减少的转化增加。这正是营销预算分配概念发挥作用的地方,为整个过程增加了另一层复杂性。

在本文中,我们将探索非线性规划的潜力,特别是锥优化(或锥编程),作为营销预算分配的工具。通过使用这一高级数学技术,我们旨在优化在各个平台上的营销预算分配,以提取最大的价值和最高的投资回报率(ROI)。

代码可以在 GitHubGoogle Colab 上找到。

💰 营销预算分配

营销预算分配是任何广告活动的关键方面,要求企业在不同渠道上战略性地分配资源。目标是最大化营销工作的效果,并实现最高的投资回报率(ROI)。为了解决这一挑战,我们需要考虑三个关键组件:

  1. 归因:我们如何将转化事件与特定活动关联?

  2. 绩效估算:我们如何根据分配的预算预测活动的绩效?

  3. 优化:我们如何在各种活动中分配预算以最大化 ROI?

🔗 1. 归因:将转换连接到活动

归因是确定哪些活动负责转化客户的过程。一些渠道,如 Facebook 或 AdWords,可以直接宣称转换。然而,有多种归因模型需要考虑,包括:

  • 首次接触

  • 最后接触

  • 多次接触

  • 时间衰减

  • 基于位置

归因系统也并非没有问题,主要有两个挑战:

  • 滞后:测量广告表现并准确归因转换所需的时间

  • 归因窗口:使用短窗口与长窗口之间的权衡,以归因转换

例如,DoorDash 使用了几天的最后接触归因系统。他们面临的问题是需要等待几天才能测量广告的表现,这对于其市场的快速变化而言过于漫长。

🔮 2. 性能估算:预测活动成功

性能估算涉及创建一个模型,该模型可以根据预算分配预测营销活动的成功。在这里,成功可以通过各种关键绩效指标(KPI)来定义,例如:

  • 潜在客户

  • 每个潜在客户的成本(CPL)

  • 客户终身价值(CLV)

  • 客户获取成本(CAC)

传统上,线性模型用于性能估算。然而,它们假设营销渠道不会出现递减收益,这通常并非如此。为了获得非平凡的解决方案,线性模型通常包含多个约束,并通过线性规划(LP)求解。

实际上,市场营销组合建模中的响应曲线通常显示出不同的形状,例如:

  • 线性(少见)

  • 凹形(常见,表示递减收益)

  • 凸形(少见)

  • S 形(少见)

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

图片由作者提供

这些形状反映了营销支出的递减收益或不同预算水平下不同渠道的效果差异。例如,将更多的钱投入到一个渠道可能会在初期产生更高的回报(凸形),但在某一点后,每增加一美元可能会产生越来越少的增量效果(变为凹形),最终形成 S 形曲线。

为了捕捉营销预算分配问题的内在非线性,需要更复杂的方法。这就是非线性规划,特别是锥形优化的作用所在。

🔄 3. 优化:使用 CVXPY 进行非线性优化

非线性规划,也称为非线性优化,是一种用于解决优化问题的方法,其中目标函数、约束条件或两者都是非线性的。简单来说,它是找到一个系统的最佳解决方案(最大化或最小化)的过程,该系统由一组非线性方程控制。

在这个例子中,我们将使用自然对数来建模每个营销渠道的回报(响应曲线),具体如下:

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

前两个步骤的归因和性能估计近似每个渠道的αᵢ和βᵢ值。让我们以三个渠道为例:

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

这些值中观察到的噪声在营销预算分配问题中是典型的。注意到α值是负的;这可以解释为与新的营销渠道接触的初始成本。

我们可以使用 matplotlib 绘制每个营销渠道的响应曲线。

import matplotlib.pyplot as plt
import numpy as np
np.random.seed(0)

TOTAL_BUDGET = 100_000

# Alpha and beta constants
alphas = np.array([-9453.72, -8312.84, -7371.33])
betas = np.array([8256.21, 7764.20, 7953.36])

# Linearly spaced numbers
x = np.linspace(1, TOTAL_BUDGET, TOTAL_BUDGET)

# Plot the response curves
fig = plt.figure(figsize=(10, 5), dpi=300)
plt.plot(x, alphas[0] + betas[0] * np.log(x), color='red', label='Google Ads')
plt.plot(x, alphas[1] + betas[1] * np.log(x), color='blue', label='Facebook Ads')
plt.plot(x, alphas[2] + betas[2] * np.log(x), color='green', label='Twitter Ads')
plt.xlabel('Budget ($)')
plt.ylabel('Returns ($)') 
plt.legend()
plt.show()

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

如何找到每个响应曲线的最佳值?最简单的解决方案是贪心算法,它随机抽样值并评估结果。我们的优化问题可以描述如下:

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

以下函数有 1,000 次迭代的预算来寻找最佳分配。

def greedy_optimization(TOTAL_BUDGET, alphas, betas, num_iterations=1_000):
    # Initialize the budget allocation and the best objective value
    google_budget = facebook_budget = twitter_budget = TOTAL_BUDGET / 3
    obj = alphas[0] + betas[0] * np.log(google_budget) + alphas[1] + betas[1] * np.log(facebook_budget) + alphas[2] + betas[2] * np.log(twitter_budget)

    for _ in range(num_iterations):
        # Generate a new random allocation
        random_allocation = np.random.dirichlet(np.ones(3)) * TOTAL_BUDGET
        google_budget_new, facebook_budget_new, twitter_budget_new = random_allocation

        # Calculate the new objective value
        new_obj = alphas[0] + betas[0] * np.log(google_budget_new) + alphas[1] + betas[1] * np.log(facebook_budget_new) + alphas[2] + betas[2] * np.log(twitter_budget_new)

        # If the new allocation improves the objective value, keep it
        if new_obj > obj:
            google_budget, facebook_budget, twitter_budget = google_budget_new, facebook_budget_new, twitter_budget_new
            obj = new_obj

    # Return the best allocation and the corresponding objective value
    return (google_budget, facebook_budget, twitter_budget), objp

让我们运行它并查看它找到的近似解:

# Run the greedy optimization
(best_google, best_facebook, best_twitter), obj = greedy_optimization(TOTAL_BUDGET, alphas, betas)

# Print the result
print('='*59 + '\n' + ' '*24 + 'Solution' + ' '*24 + '\n' + '='*59)
print(f'Returns = ${round(obj):,}\n')
print('Marketing allocation:')
print(f' - Google Ads   = ${round(best_google):,}')
print(f' - Facebook Ads = ${round(best_facebook):,}')
print(f' - Twitter Ads  = ${round(best_twitter):,}')
===========================================================
                        Solution                        
===========================================================
Returns = $224,534

Marketing allocation:
 - Google Ads   = $35,476
 - Facebook Ads = $31,722
 - Twitter Ads  = $32,802

在进行计算后,我们发现我们的总回报是$224,533。你可能会想,我们是否可以通过进一步调整模型或进行更多迭代来改进它。

这种保证正是非线性编程的救援所在:它可以输出最佳可能解,也称为最优解。除了这一巨大优势外,它的运行速度也更快。

为了使用非线性编程解决营销预算分配问题,我们将使用CVXPY库,该库支持圆锥优化,得益于像ECOSMOSEK(内点法)和SCS(一阶方法)等专门的求解器。在这个例子中,我们将使用开源的 ECOS 求解器来找到最佳解。

让我们设置优化问题:

  • 我们的决策变量是每个渠道的(正)预算。

  • 我们的约束条件是所有预算的总和不得超过总预算。

  • 我们的目标是最大化总回报,即各个渠道回报的总和。

import cvxpy as cp

# Variables
google   = cp.Variable(pos=True)
facebook = cp.Variable(pos=True)
twitter  = cp.Variable(pos=True)

# Constraint
constraint = [google + facebook + twitter <= TOTAL_BUDGET]

# Objective
obj = cp.Maximize(alphas[0] + betas[0] * cp.log(google)
                + alphas[1] + betas[1] * cp.log(facebook)
                + alphas[2] + betas[2] * cp.log(twitter))

最后,我们调用 ECOS 求解器来找到最佳预算分配并显示结果。

# Solve
prob = cp.Problem(obj, constraint)
prob.solve(solver='ECOS', verbose=False)

# Print solution
print('='*59 + '\n' + ' '*24 + 'Solution' + ' '*24 + '\n' + '='*59)
print(f'Status = {prob.status}')
print(f'Returns = ${round(prob.value):,}\n')
print('Marketing allocation:')
print(f' - Google Ads   = ${round(google.value):,}')
print(f' - Facebook Ads = ${round(facebook.value):,}')
print(f' - Twitter Ads  = ${round(twitter.value):,}')
===========================================================
                        Solution                        
===========================================================
Status = optimal
Returns = $224,540

Marketing allocation:
 - Google Ads   = $34,439
 - Facebook Ads = $32,386
 - Twitter Ads  = $33,175

求解器找到的最佳分配是 Google Ads $34,439,Facebook Ads $32,386,YouTube $33,175,总回报为$224,540!这比贪心算法返回的多$7($224,533)。

请记住,这种分配最大化了基于我们响应曲线的回报:正确建模这些曲线对于有效优化预算至关重要。

让我们将这个最佳分配可视化到之前的响应曲线之上。

# Plot the functions and the results
fig = plt.figure(figsize=(10, 5), dpi=300)

plt.plot(x, alphas[0] + betas[0] * np.log(x), color='red', label='Google Ads')
plt.plot(x, alphas[1] + betas[1] * np.log(x), color='blue', label='Facebook Ads')
plt.plot(x, alphas[2] + betas[2] * np.log(x), color='green', label='Twitter Ads')

# Plot optimal points
plt.scatter([google.value, facebook.value, twitter.value],
            [alphas[0] + betas[0] * np.log(google.value),
             alphas[1] + betas[1] * np.log(facebook.value),
             alphas[2] + betas[2] * np.log(twitter.value)],
            marker="+", color='black', zorder=10)

plt.xlabel('Budget ($)')
plt.ylabel('Returns ($)') 
plt.legend()
plt.show()

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

但它真的最优吗?我们可以通过对贪心算法进行不同迭代次数的快速检验来检查。这将展示这两种方法之间的差异。

让我们对 1 到 1,000,000 之间的 20 个不同的迭代次数进行测试。

# List to store the best objective value for each number of iterations
best_obj_list = []

# Range of number of iterations to test
num_iterations_range = np.logspace(0, 6, 20).astype(int)

# Run the greedy algorithm for each number of iterations and store the best objective value
for num_iterations in num_iterations_range:
    _, best_obj = greedy_optimization(TOTAL_BUDGET, alphas, betas, num_iterations)
    best_obj_list.append(best_obj)

现在我们可以使用 matplotlib 绘制结果列表,并将其与最优解进行比较:

# Plot the results
plt.figure(figsize=(10, 5), dpi=300)
plt.ticklabel_format(useOffset=False)
plt.plot(num_iterations_range, best_obj_list, label='Greedy algorithm')
plt.axhline(y=prob.value, color='r', linestyle='--', label='Optimal solution (CVXPY)')
plt.xlabel('Number of iterations')
plt.xticks(num_iterations_range)
plt.xscale("log")
plt.ylabel('Best returns ($)')
plt.title('Best returns found by the greedy algorithm for different numbers of iterations')
plt.legend()
plt.show()

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

我们观察到,贪心算法在进行大量迭代时表现相对较好。然而,尽管进行了 100 万次尝试,它仍未能找到最优分配,最优回报为 224,540.1500 美元。它能达到的最佳非四舍五入值为 224,540.1489 美元。

除此之外,两种方法在计算速度方面存在显著差异。非线性编程模型在短短 22.3 毫秒内找到了最优解。而贪心算法则花费了 30 秒进行 100 万次迭代,找到一个几乎最优的解。

当我们将问题扩展到多个营销渠道时,这种差异变得尤为重要。使用 CVXPY 的非线性编程保持了其速度和精确度,使其成为处理复杂、高维营销预算分配问题的高效工具。

结论

非线性编程为解决营销预算分配问题提供了一种强大的方法。通过使用非线性函数来建模每个营销渠道的收益递减,并利用 CVXPY 库,我们可以找到最大化销售的资源最优分配。

随着营销环境的不断发展和渠道数量的增加,像非线性编程这样的优化技术可以帮助企业做出更好的数据驱动决策,优化其营销投资。虽然本文提供了一个起点,但还有许多更先进的技术和模型可以探索。继续学习和尝试,找到最适合你业务的方法。

如果你想了解更多,欢迎在 Twitter 上关注我 @maximelabonne。祝优化愉快!

参考文献

如果你想了解更多关于营销预算分配的信息,我推荐以下资源:

相关文章

## Python 中的线性规划介绍

使用 Google OR-Tools 的数学优化指南

towardsdatascience.com ## Python 中的整数规划与线性规划

识别和解决任何优化问题的指南

towardsdatascience.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值