TowardsDataScience 2023 博客中文翻译(一百八十三)

原文:TowardsDataScience

协议:CC BY-NC-SA 4.0

如何理解和使用 Jensen-Shannon 散度

原文:towardsdatascience.com/how-to-understand-and-use-jensen-shannon-divergence-b10e11b03fd6?source=collection_archive---------0-----------------------#2023-03-02

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

作者提供的图片

关于 JS 散度的数学、逻辑和实际应用的入门 — 包括如何在漂移监控中最佳使用它

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

·

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

本文由 Arize AI 的首席执行官兼联合创始人 Jason Lopatecki 共同撰写

在机器学习系统中,漂移监控对于提供高质量的 ML 至关重要。一些在生产 ML 系统中漂移分析的常见用例包括:

  • 检测训练和生产之间的特征变化,以在性能下降之前发现问题

  • 检测两个生产周期之间的预测分布变化,以作为性能变化的代理(特别适用于延迟真实情况)

  • 使用漂移作为重新训练的信号——以及重新训练的频率

  • 捕捉特征转换问题或管道中断

  • 检测错误使用的默认回退值

  • 查找新的数据以进行标记

  • 查找对模型有问题的新数据集群,特别是在非结构化数据中

  • 查找不在训练集中的异常数据集群

虽然没有完美的漂移度量,但在过去十年里这个领域已经学到了很多,有一些经过良好测试的方法和度量在不同的使用场景中非常有用。

一种这样的度量是詹森-香农散度(JS Div)。此外 被称为相对于平均值的总散度信息半径,JS 散度是一个基于信息理论的统计度量**。** JS 散度相比于其他度量的优势主要与某些事件或箱的空概率问题有关,这些问题会影响 Kullback-Leibler 散度(KL 散度)和人口稳定性指数(PSI)。JS 散度在比较两个分布时使用混合概率作为基线。在 PSI 和 KL 散度的离散版本中,当出现 0 概率事件时,方程会出现爆炸。

本博客文章涵盖了 JS 散度的定义、它与 KL 散度的不同、如何在漂移监测中使用 JS 散度,以及混合分布如何解决常见的测量问题。

JS 散度概述

詹森-香农是一种非对称度量,测量相对熵或两个分布所表示信息的差异。与 KL 散度密切相关,它可以被视为测量两个数据分布之间的距离,显示这两个分布之间的差异。

下图展示了与 KL 散度的对称性:

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

图片由作者提供

以及 JS 散度的离散形式:

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

图片由作者提供

其中混合分布是:

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

图片由作者提供

更多背景信息中,关于 JS 散度的技术论文由 Sony Computer Science Laboratories 的 Frank Nielsen 撰写。

在模型监测中,JS 散度的离散形式通常用于通过数据分箱来获取离散分布。JS 的离散形式和连续形式会随着样本和箱数趋于无穷大而收敛。有优化的选择方法来选择箱数以接近连续形式。

JS 散度如何在漂移监测中使用?

在模型监控中,JS 散度类似于 PSI,因为它用于监控生产环境,特别是特征和预测数据方面。JS 散度还用于确保生产中的输入或输出数据没有从基准数据中发生剧烈变化。基准数据可以是数据的训练生产窗口或训练/验证数据集。

漂移监控对于那些收到延迟地面真相以与生产模型决策进行比较的团队尤为有用。团队依赖于预测和特征分布的变化作为性能变化的代理。

JS 散度通常应用于每个特征独立地;它不是作为协方差特征测量的设计,而是显示每个特征如何独立于基准值发生偏离的度量。虽然 JS 散度确实支持多分布混合方法,但它实际上并不适用于比较完全不同的分布——它不是一个多变量漂移测量。

JS 散度的挑战 — 也是它的优势 — 是比较基准是一个混合分布。可以将 JS 散度视为两个步骤进行:

步骤 1:

使用生产和基准分布创建混合分布进行比较;

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

作者提供的图片

步骤 2:

比较生产和基准与混合。

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

作者提供的图片

上图展示了 A 分布、B 分布和混合分布。JS 散度是通过将 JS 分布与 A 和 B 进行比较来计算的。

✏️注意*:* 有时非从业者对捕捉数据变化的数学完美目标过于热衷。在实践中,重要的是要记住真实数据在生产中一直在变化,许多模型可以很好地适应这些修改的数据。使用漂移度量的目标是拥有一个可靠、稳定且非常有用的度量,以便进行故障排除。

JS 散度是对称度量

JS 散度类似于 PSI,因为它是一个对称度量。如果你交换基准分布 p(x) 和样本分布 q(x),你将得到相同的数字。这相比于 KL 散度在故障排除数据模型比较中有几个优势。有时团队希望在故障排除工作流中将比较基准替换为不同的分布,而拥有一个度量使得 A / BB / A 相同,可以使比较结果更容易。

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

作者提供的图片

JS 散度的优势:处理零 bin

JS 散度的主要优势在于混合分布允许计算处理 bin 比较到 0。对于 KL 散度,如果你比较 0 bin,方程式基本上会爆炸。

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

作者提供的图片

如上图所示,有两个桶,其中一个桶在当前时间段内为 0,另一个有一个值。处理 0 桶的 JS 散度方法是将 JS 散度中的两个项假设其中一个为0 (0ln(0) = 0)*,因为函数是光滑的,并且在接近 0 时有一个极限,而另一个有一个值:

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

假设一个项为 0,你在 0 桶中得到:

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

这在 KL 散度或 PSI 中不起作用,因为你会在分母中除以 0:

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

在 q(x) = 0 的情况下,你有:

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

优势:零桶自然处理,无问题

✏️注意:在需要时,也可以进行修改,以允许 KL 散度和 PSI 用于 0 桶的分布。

JS 散度的劣势:混合分布移动

JS 散度的劣势实际上源于它的优势,即比较分布是两个分布的“混合”。

在 PSI 或 KL 散度的情况下,基线比较分布是静态比较分布,在每次比较时间段内固定。这使你能够获得一个稳定的指标,在每次比较和每个时期都具有相同的含义。例如,如果一天的 PSI 值为 0.2,那么一周后仍然是 0.2,这意味着这两天与基线的熵差异是相同的。这在 JS 散度中不一定如此。

在 JS 散度的情况下,每次进行比较时混合分布都会改变,因为生产分布在每个样本周期内都会变化。

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

每个监测日的混合分布计算(图片由作者提供)

上图展示了为两个不同时间框架计算的混合分布的示例。混合分布像是一个缓慢移动的基线,通过平均差异将时间 A 的基线平滑地连接到时间 B。

连续数值和分类特征之间的差异

JS 散度可以用来测量数值分布和分类分布之间的差异。

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

图片由作者提供

数值

对于数值分布,数据基于分割点、桶大小和桶宽度被分成桶。桶化策略可以是均匀桶、五分位数或复杂的混合策略,最终影响 JS 散度(请关注未来关于桶化策略的文章)。

分类

JS 散度的监控跟踪分类数据集中大的分布变化。对于分类特征,通常有一个大小点,卡尔多性变得过大,导致度量值不再有用。理想的大小在 50–100 个独特值左右——随着分布的卡尔多性增加,两个分布的差异及其重要性变得模糊。

高卡尔多性

对于高卡尔多性特征监控,现成的统计距离通常效果不好——建议使用以下其中一种选项:

  1. 嵌入: 在一些高卡尔多性的情况下,使用的值——例如用户 ID内容 ID——已经用于内部创建嵌入。监控嵌入可以有所帮助。

  2. 纯高卡尔多性分类变量: 在其他情况下,当模型对输入进行大规模编码时,仅监控前 50–100 个最重要项的 JS 散度,而将所有其他值视为“其他”,可能会很有用。

当然,有时你可能想监控的是非常具体的内容——例如某一时期内新值或箱的百分比。此类情况更适合使用数据质量监控工具。

JS 散度示例

这是一个包含数值和分类特征的 JS 散度示例。

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

作者提供的图片

假设你在一家信用卡公司工作,负责为欺诈模型制定数值分布。模型是基于上图所示的基线进行训练的。我们可以看到费用分布发生了变化。行业标准在 PSI 阈值方面有许多,但如你所见,JS 散度的值却非常不同。0.2 的 PSI 标准不适用于 JS 散度。在 Arize(完全披露:我在 Arize 工作),我们通常查看多日周期内的移动窗口值,以为每个特征设置阈值。

该示例展示了一个数值变量及其分布上的 JS 散度。在上述示例中,值得注意的是,bin 95–97 从 12% 降到 3% 导致 JS 散度移动了 1.4。对于 bin 105–107 的 3% 到 12% 的九个百分点增加,JS 散度也有类似的变化。PSI 以类似对称的方式工作,这与 KL 散度不同。对于 KL 散度,12%->3% 会导致数值上更大的变化。

JS 散度的直觉

理解一些关于度量和基于分布变化的度量变化的逻辑非常重要。

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

作者提供的图片

上述示例展示了从一个分类 bin 到另一个分类 bin 的迁移。以“医疗”为输入的预测(贷款用途)从 2% 增加到 8%,而以“度假”为输入的预测从 23% 减少到 17%。

在这个例子中,与“医疗”相关的 JS 散度组件是 0.96,远大于“度假”百分比移动的 0.023。这与 KL 散度得到的结果正好相反。

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

图片由作者提供

结论

JS 散度 是一种常见的漂移测量方法。它具有对称性,并自然处理 0 桶比较,但在使用移动混合作为基准时也有一些缺点。根据你的使用场景,它可能是一个很好的漂移度量选择。

也就是说,这并不是唯一的选择。另一种替代方法是使用 人口稳定性指数 结合分布外分桶技术来处理零桶。利用分布外分桶技术可以让团队调节度量对分布外事件的敏感性,并轻松与固定基准分布进行比较(没有混合)。敬请关注更多关于此主题和分桶最佳实践的后续内容!

如何理解因果关系的世界

原文:towardsdatascience.com/how-to-understand-the-world-of-causality-c698cdc9f27c?source=collection_archive---------3-----------------------#2023-02-18

因果关系是一个广泛而复杂的领域。这里有一张地图帮助你理解它。

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

·

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

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

因果关系地图。图片由作者创作。

因果关系的世界大致分为两个主要领域:

  • 因果推断的主要领域: 因果推断关注的是理解你所采取行动的效果。因果推断提供了工具,使你能够隔离并计算系统内变更的效果——即使该变更在实践中从未发生。因果推断可以用来回答以下问题:我因为服用了某种药物而变得更好吗?我需要增加多少广告支出才能实现我的收入目标?课堂规模对教育成就的影响是什么?

  • 因果发现岛:因果发现方法利用数据确定其中的因果关系。关键是,因果发现揭示的关系不仅仅是统计相关性。因果关系对变化是不变的,代表了理解系统的更基本基础。

实验山脉 ⛰️

探索因果关系的最明显起点是实验山脉。这些山脉在景观中高耸入云,理由很充分。这些方法包括用于理解因果效应的金标准方法,具有最大的确定性。

理解这些方法有效性的关键在于掌握随机分配的意义。通过干预世界,实验随机分配那些接受某种处理和那些不接受处理的人——即对照组。处理可以是药物剂量、施加在作物上的肥料量、晨间例程等任何事物。

由于处理是随机化的,如果你从人群中选择一个足够大的样本,那么从统计学上讲,你的处理组和对照组之间唯一的差异就是处理本身。你已经成功排除了所有其他通常会偏倚结果的因素。这些对你的处理和结果有因果关系的外部因素被称为混杂因素。你在这篇文章中阅读的所有因果推断技术的目标都是消除混杂因素。因此,处理组和对照组之间的任何差异都必须是由于处理——从而使你能够计算处理效果。

以你是一个农民并希望了解使用一种新型肥料对作物的效果为例。与其盲目地将肥料施加到整个田地上,你可以将田地划分为若干个方块。对于每一个方块,你掷硬币,根据结果决定是否施加肥料。通过这样做,你已经随机化了是否施肥,从而排除了可能偏倚你选择的因素。此外,由于你在同一片田地内操作,天气等混杂因素也得到控制,不会影响结果。然后你可以简单地比较施肥方块和未施肥方块的作物产量,从而得到处理效果。

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

随机化实验如何计算处理效果的示例。图片由作者创建。

自然实验之城 🌆

在许多情况下,进行现实世界的实验实际上是不可行的。实验可能是非伦理的、费用过高、在后勤上不可能,或是这些因素的组合。那么,如果你面临一个无法进行实验的情况,你该怎么办?

各领域的科学家们几代人都面临这些情况。经济学家无法将受控实验扩展到国家的规模。生物学家无法干预分配可能有害的治疗。因此,这些科学家们发展了一系列技术来识别自然随机化,使他们能够去除偏差并识别处理效果,而无需直接干预自己。这些技术填充了自然实验的城市。

城市中的所有技术行为类似,利用自然随机化来计算处理效果,但要更深入理解它,现在是时候专注于一种:工具变量。这些变量不会导致或与结果相关,也不会与其他混杂因素相关,但它们对处理有直接的因果影响。在图形形式中,工具变量看起来与前一部分农民掷硬币的情况相同。

让我们回到农业例子。 农民选择的作物是玉米,他们希望了解改变价格会对销售量产生多大影响。农民知道有多种因素影响玉米销售:运输成本、当年的总体产量、消费者趋势等。然而,我们的农民知道在降雨较少的年份,产量较低,而产量较低时,农民会提高价格。

现在为了使天气成为一个好的工具变量,我们的农民假设:

  • 天气和玉米销售不会被另一个因素混杂;即导致它们两个的因素。

  • 天气对玉米销售没有影响。

如果这些假设是正确的,并且农民对玉米市场的领域知识也认为天气引入的随机化以及足够大的数据集,会让农民计算价格对玉米销售的影响——所有这些都不需要进行真实世界的实验!

因果图桥梁 🌉

因果推断可以看作是一个两阶段过程:识别和估计。识别是确定你需要控制的变量集合,即保持不变,以隔离感兴趣的因果效应的过程。估计则是应用统计技术到你的数据中以计算效果。因果图是执行识别的事实工具。

因果图可视化你希望探究的数据中的因果关系。在前面的部分,你已经看到了一个因果图,考虑了肥料对农作物产量的影响。

因果图是有向无环图(DAGs),这意味着它们将变量表示为节点,节点之间的有向边显示了一个变量对另一个变量的因果影响。边还表示变量之间的双向相关性,而因果关系仅是单向的,相关性或统计关联是双向的。因此,相关性可以表明因果关系,但不能作为证据。

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

如何理解因果图。图像由作者创作。

理解因果图的一种方式是将其视为对数据生成方式的估计。因果关系描述了单独的一个特征或与其他特征组合,如何导致另一个特征——最终形成你希望研究的特征。

在之前的章节中,你学习了如何通过随机化来消除混杂变量的偏倚效应。因果图允许你在不进行随机化的情况下实现相同的目标。这意味着你不一定需要进行实验或识别自然的随机源来解开数据中的因果关系。

因果发现岛 🏝️

因果发现是将算法和领域知识相结合,以找到适当的因果图的过程。

然而,因果发现的岛屿是一个难以生存的地方。你正试图估计一个表示数据生成过程的因果图,而这个过程你在现实中永远无法完全观察到——没有绝对的真相。因此,对于大多数现实世界的数据,因果图是数据生成过程的最佳估计,不能被验证为对现象的真实表征。

这并不意味着从因果发现中恢复的因果图,以及支撑大多数因果推断的图,毫无用处。恰恰相反——这些图为纯统计方法的机器学习提供了强大的进展,使你更进一步地理解你感兴趣的系统的机制。

你可以应用许多不同的算法来分析收集的数据,以揭示因果关系。最常见的两种因果发现算法类别是:

  • **基于约束的:**通过执行条件独立性测试,在测试中控制数据集中的不同变量,并测量这样做对其他变量的影响,算法可以识别出某些因果模式。在整个数据集中迭代地应用条件独立性测试,然后可以建立出更完整的潜在因果图。

  • 基于评分: 这类算法提出了一系列不同的因果结构,然后根据它们与基础数据的适配程度来分配一个评分。该算法从基本结构开始,然后通过重复评分的回合,建立最适合的结构,从而形成一个包含可用变量的因果结构。

应用算法到你的数据时的难点在于,它们永远无法获取一个完全解决的因果图。输出总会有一些没有明确因果方向的边,这时人类领域知识显得尤为重要。领域专业知识在创建可用的因果图中至关重要,因此对于获得准确的因果发现结果至关重要。

因果发现的最终难题是存在未观察到的混淆变量。这些变量混淆了你的兴趣变量,但在你的数据集中不存在。由于没有观察到这些混淆变量,许多因果推断方法无法有效工作。因果发现方法和人类领域专业知识在这里非常强大,因为它们可以帮助标记未观察到的混淆变量可能影响数据生成过程的地方。

匹配森林 🌲

匹配森林是因果图桥梁的落脚点。因果图使你能够轻松了解在尝试估计因果效应时需要控制哪些变量。匹配森林中的技术为你提供了从图形世界到数据应用的工具。匹配技术在文献中被广泛理解和使用——这就像一片茂密的绿色森林。

匹配是通过构建根据一组匹配变量相似的比较组,来去除处理与结果之间的混淆效应的过程。这些匹配变量通常通过你的因果图来确定。

这里的直觉是你正在构建一个具有与处理组相似属性的对照组。因此,两个组之间的任何结果变异都必须归因于处理,从而得到因果效应的估计。

最简单的匹配工具是子分类。

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

使用胆固醇与运动在年龄的混淆下的子分类示例。与 Judea Pearl 的《为何之书》中使用的示例相同。图像由作者创建。

当你将治疗(运动)与结果(胆固醇)数据进行绘图时,你会注意到一个下降的趋势,如上图的左侧。然而,通过按混杂变量(年龄)对数据进行分组,从而创建子类,你可以观察到治疗与结果之间的真实关系——见右侧。子分类直观易懂,但随着需要控制的变量数量增加,所需的数据量急剧增加。这限制了子分类的适用性,导致了其他方法的出现,这些方法充实了匹配森林。

建模沼泽 🍃

建模沼泽是事情开始变得有些模糊的地方。建模沼泽是一些最熟悉的因果推断工具的家园,相比之下,新兴工具则较少被建立。模型提供了强大的因果效应估计方法,虽然有些依赖于完全指定的因果图,但其他模型在没有该要求的情况下也能有效运行。

建模沼泽中最受欢迎的方法是普通回归。普通最小二乘(OLS)回归是一个极其灵活且有价值的因果效应估计工具。它之所以受欢迎也有充分的理由:

  • 理论上已被很好理解: OLS 和其他类型的回归方法从统计学角度非常清楚。这意味着应用回归到你的挑战中的假设是明确的,允许你对结果做出明智的选择。

  • 可解释性强: 回归模型易于解释,不像现代机器学习技术。这使得它们在高风险情况下,如涉及监管时,表现优异。

  • 因果推断很简单: 控制混杂变量并使用回归估计因果效应是直接的。回归方程中的学习系数是给定变量的因果效应的估计,同时控制其他变量——请参见下面的图示。

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

普通最小二乘回归的参数描述了每个变量如何随结果的变化而变化,同时控制其他变量。图像由作者创建。

这里值得更详细了解的第二种方法是结构因果模型(SCM)。SCM 直接基于因果图的基础,并学习由领域专业知识或算法因果发现确定的因果关系的数学形式。

这意味着你因果图中的边缘和节点现在有了从数据中学到的数学关系。这是非常强大的,因为它使你能够通过干预模型来轻松创建“如果……会怎样”的情境。干预只是意味着改变图中一个节点的值。然后,SCM 描述了这种变化如何传递到其他变量,最终影响处理结果。结果是,通过一个具有代表性的 SCM,你可以开始探索各种不同的情境,并比较不同动作的影响。

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

结构性因果模型学习到的边函数的一个例子。图片由作者创建。

决策智能沙漠 🐪

决策智能沙漠是荒凉而偏远的,但也有绿洲。这一地图区域包含了超越处理效果估计的各种新兴技术。为了说明沙漠中包含的方法类型,我们来考虑一下算法性救济

在机器学习中,一种常见的解释性技术是反事实解释。反事实解释提出了一个问题:为了让结果有所不同,需要改变什么?

例如,设想一个保留预测机器学习模型,它预测一个客户将会流失。一个反事实解释来帮助解释为什么这个人可能会流失可能是:如果他们是 65 岁或以上的高级客户,他们会续订。

算法性救济从反事实解释的概念出发,但重点在于提供你行动的能力,而不仅仅是理解。因此,算法性救济提供了推荐行动以改变不利结果的能力,使你能够干预系统以防止这些结果。

这最终将上述的流失示例从不可操作的解释,转变为可操作的建议。应用救济以防止此人流失:如果他们获得 10%的折扣,他们会续订。由于折扣是可以采取行动的,这使你能够在现实世界中产生变化。

结论 🏁

你已经对一个深奥而迷人的主题进行了 whirlwind 之旅。我希望你喜欢对因果关系的探索,并感到有动力去学习更多。

如果你希望更深入地了解,我强烈推荐以下书籍和资源作为起点:

  1. Brady Neal 的因果推断课程(Youtube):这是一个很好的入门视频系列,可以让你了解本文讨论的许多主题。

  2. 效果,或 因果推断混音带:这些书更侧重于因果推断的传统技术。这些书将为你提供一个强大的基础,帮助你继续前行。两本书的作者都很慷慨地免费提供,但如果你能负担得起,我总是建议你获取纸质版!

  3. 勇敢且真实的因果推断:这是一本非常有趣的书,探讨了因果推断和机器学习如何碰撞。书中包含了很好的实践代码示例,让你可以实际学习!

如何将初级数据科学代码升级为高级数据科学代码

原文:towardsdatascience.com/how-to-upgrade-your-junior-level-data-science-code-to-senior-level-data-science-code-d3eb88a5555d?source=collection_archive---------4-----------------------#2023-06-12

这 4 个技巧将帮助你像高级数据科学家一样编写代码

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

·

关注 发布于数据科学的方向 ·7 分钟阅读·2023 年 6 月 12 日

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

照片由玛丽亚·特涅瓦拍摄,发布在Unsplash

你做到了。经过多年的努力工作,你成功获得了初级数据科学家的职位。你最初的几周迅速过去,公司入职培训结束后,你还没来得及反应,几年已经过去了。你参与了无数项目,无论是独立完成还是团队合作,你的解决方案都对公司产生了积极的影响。

但现在,你已经准备好迎接下一个挑战:成为一名高级数据科学家。但是,你如何弥补这个差距呢?一名高级数据科学家需要知道哪些内容?最重要的是:你如何将初级数据科学代码转化为高级数据科学代码?

幸运的是,最后一个问题是最容易回答的,也是提升技能的最简单途径,以便你在成为高级数据科学家的道路上不断进步。我已经列出了四个主要领域,你的初级代码可以在这些领域转变为任何公司都愿意提升你为高级数据科学家职位的代码。关键是掌握基础知识,摆脱“意大利面条”代码,开始实施测试和质量保证技能,并学会优化你的代码。

掌握数据科学代码的基础知识

你不能在走路之前跑步,因此在你能够编写高级数据科学家级别的代码之前,你需要掌握代码的基础知识。

在数据科学之旅的开始阶段,仅仅编写能正常运行的代码就是一种成就。然而,现在是时候开始掌握这些基础知识,使得你的代码能够顺利运行不再令人惊讶。

这是一个无法加速的建议,只能通过花时间做工作来实现。在你作为初级数据科学家的前几年里,你每天都会有机会专注于掌握数据科学代码的基础知识,从编程基础到算法,再到数据结构和设计模式。

此外,现在是通过学习其他编程语言(可能是你公司使用的语言或是你自己有时间学习的语言)和其他可以提高工作质量的技术(例如,用于组织项目的 Notion,版本控制的 Git,代码编辑器中的语法检查扩展等)来深化你的知识基础的时机。一些语言和工具会让你受益终身,而其他工具则会提供有价值的经验,即使你不再使用它们,也会让你成为更好的数据科学家。

现在也是扩展你的能力并开始探索数据科学中更复杂概念的时机。例如,你可能目前是在解释过去事件原因的数据分析师角色。然而,你的老板现在希望你转向预测分析,这需要你开始学习机器学习和人工智能。推动自己学习这些主题将使你能够进入更高级和监督的角色,在这些角色中,你可以开始将你的知识传递给那些像你一样刚开始的新初级数据科学家。

专注于编写干净、可维护和易读的代码

我常在以前的文章中开玩笑说数据科学家写的代码很糟糕。意大利面条代码确实存在,尤其是在你刚开始的时候。这在你作为初级数据科学家的前两年可能是可以接受的,但随着经验的增加,写出凌乱的代码就变得越来越不可接受。

使你脱颖而出的一个方面是你能够编写干净、可维护和易读的代码。这不仅让你在工作中更容易合作且非常专业,还表明你能够将这些技巧传授给未来在你指导下的初级数据科学家。

因此,要将你的初级代码提升到高级代码水平,你需要专注于使你的代码始终保持干净、可维护和易读。

Python 和 R 都有关于最佳实践和风格的很好的指南,这些指南可以帮助你开始更专业地格式化代码。代码的整洁性、可维护性和可读性是数据科学家的基石,这样的数据科学家是合作起来令人愉快的,这也是为什么这些标准应该铭记于心(或者至少,在你桌面上显眼的位置,随手可得)。最佳实践和风格是你在提交最终提交或将代码发送到软件工程部门进行生产级代码转换之前,应该始终考虑和仔细审查的两个方面。

这也意味着你应该至少遵循DRY 编码原则(至少),以及可维护性 编码原则(在更高级的层次上),以确保你编写出尽可能好的代码。虽然这些原则可能在你主要编写的代码不会被其他人触及或仅在小型内部机器上运行时不太相关,但如果你换工作或开始编写生产级代码,熟练掌握这些原则并不坏。

此外,在你职业生涯的这个阶段,你应该成为行业/公司代码标准的标杆。你推送到仓库的每一个代码提交都应该是你所在行业或公司所期望的光辉范例,应该是可以打印出来用作培训手册的内容。是的,这会花费你额外的时间,但这额外的细致思考将在公司内部晋升时带来回报。他们会关注什么?一个持续编写干净、可维护且易读代码的员工——这应该就是你!

这份快速简便的 7 步检查清单将帮助你编写更好的数据科学 Python 代码 [## 这份快速简便的 7 步检查清单将帮助你编写更好的数据科学 Python 代码

这个检查清单将帮助你编写干净且易于管理的 Python 代码

发展测试和质量保证技能

开发测试和质量保证技能

精通单元测试、集成测试和自动化测试框架是立即提升代码水平的好方法。虽然这些技能你作为初级数据科学家应当了解,但作为高级数据科学家你应该精通这些技能。

测试和质量保证技能是你开始编写优秀代码的地方,这些代码按设计工作,并能与其他代码片段协同工作。在以前,你可能只是将代码发送到软件工程部门,由他们准备一切以进行集成,而现在你将像高级数据科学家一样编写代码,必须确保你的代码正常运行,并能够集成到更大的代码库中。

虽然你的公司可能有特定的单元测试和集成测试要求你运行,但开始构建自己的测试以确保代码的运行和集成方式是一个不错的主意。自己的质量保证方式是对自己的代码负责的好方法,并确保如果代码能通过你自己的测试,它也能顺利通过公司测试。这不仅让你成为一个更好的数据科学家,而且使你在编写代码时变得更加高效。

发展测试和质量保证技能是向公司展示你致力于提升技艺和关心工作质量及推送到生产环境的代码的好方法。这些都是让你成为高级数据科学家职位优秀候选人的属性。

单元测试和数据科学的 Python ## 单元测试与数据科学的 Python

使用 nose2 和参数化测试尽早发现错误

[towardsdatascience.com

将性能优化作为优先事项

没有什么比在将代码提交给软件工程部门后,听到与收到数据科学家的代码相关的抱怨声更能激励你学习如何优化代码了。这是每个数据科学家都应该经历的一个谦逊的体验。

学习代码优化不仅仅是为了与软件部门保持良好的工作关系——更是为了让自己成为一个更加稳健的数据科学家,能够在没有其他部门支持的情况下编写出优秀的代码。能够在第一次就编写出稳定、优化的代码,是成为高级数据科学家的一个重要步骤。

在诸如缓存(将数据副本存储在主要数据存储前面——并非所有应用程序都相关,但在为客户制作仪表板时可能有用)、时间复杂度(算法运行所需的时间)、数据库索引(可以加速数据库表中数据检索操作的结构)和查询优化(找出改善查询性能的最佳方法)等主题上进行学习,是优化数据科学代码的良好起点。

虽然上述提到的所有主题并不适用于所有类型的数据科学工作,但它们都是很好的工具,可以放在备用工具中,无论是为了未来的工作,还是在某次需要时能够迅速上手解决问题——这是高级数据科学家的一个重要特质。

订阅以直接将我的故事发送到您的收件箱:故事订阅

请成为会员,通过我的推荐链接获得无限制访问 Medium 的权限(您不会额外产生费用,我将获得少量佣金):Medium 会员

支持我的写作,通过捐赠来资助更多类似故事的创作:捐赠

如何利用参数解析提升机器学习工作流的效率

原文:towardsdatascience.com/how-to-use-argument-parsing-for-greater-efficiency-in-machine-learning-workflows-2f637eaf5f6a

如何使用 argparse 来提升命令行应用程序的效率,并且如何将其应用于机器学习项目的完整指南

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

·发表在 Towards Data Science ·阅读时间 6 分钟·2023 年 3 月 29 日

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

图片来源于作者。

如果你在数据科学或软件工程领域有过一些探索,你很可能遇到过需要使用命令行接口(CLI)的应用程序。常见的例子包括用于管理 Azure 资源的 Azure CLI 或用于版本控制和源代码管理的 Git

同样的功能和程序互动性也可以通过你自己定制的 Python 应用程序来实现。命令行参数是丰富应用程序功能的绝佳工具,它允许你和你的用户无缝配置和定制程序的行为,从而增加了必要的灵活性。

一个流行且(也许是)最常用的 Python 库来解析命令行参数是 argparse。在本文中,我们将探索一些其核心功能,并通过具体示例详细了解如何高效地将其应用于 Python 应用程序。

argparse 简介

Python 的 argparse 模块提供了一种直观且用户友好的方式来解析命令行参数。简而言之,你只需完成以下三步:(1)创建一个 ArgumentParser 对象,(2)通过 add_argument() 方法添加参数规范,(3)使用 parse_args() 方法运行解析器。现在让我们详细探讨这三个步骤,并看看如何将它们组合成一个功能齐全的命令行解析器。

首先,[ArgumentParser](https://docs.python.org/3/library/argparse.html#argparse.ArgumentParser) 对象作为一个容器,保存了必要的信息,如程序的名称或简要描述。用户可以通过帮助参数 -h--help 检索这些信息,从而更好地理解程序的意图。

import argparse

parser = argparse.ArgumentParser(
    prog = 'Sample Program',
    description='Description of the sample program'
)

其次,我们可以通过 add_argument() 方法添加位置参数或可选参数。位置参数通过直接提供参数名称来指定,而可选参数需要通过 前缀进行识别。一个单破折号用于指定参数的缩写版本,通常是一个字母,而双破折号用于提供更具描述性的参数名称。

# adding positional argument
parser.add_argument('filename')

# adding optional argument
parser.add_argument('-p', '--parameter')

最后,我们可以使用 parse_args() 方法运行解析器,这样我们就可以访问和操作 CLI 中指定的参数。

args = parser.parse_args()

# print the parsed arguments
print("filename: " + args.filename + "\n" + "parameter: " + args.parameter)

现在我们可以在 CLI 中运行这个程序——我们称之为 program.py——并使用一些随机参数来查看它的工作情况:

>>> python program.py 'sample_data.csv' -p 10
filename: sample_data.csv
parameter: 10

我们现在已经构建了一个功能,允许我们直接在命令行上指定输入参数,然后使用这些参数执行任何我们想要的操作。你现在可能已经能够想象这对于任何需要重复运行程序的开发过程有多么有用,从而实现了一种简单而无缝的交互方式。

机器学习中的实用工具

假设你已经在 Python 中构建了一个机器学习或深度学习模型,你希望使用不同的超参数,如学习率、批处理大小或训练轮次,并将结果存储在不同的目录中。

直接在命令行上指定这些超参数大大简化了与该程序的交互方式。它使你能够在不实际修改底层源代码的情况下对不同的模型配置进行实验,从而减少了引入意外错误的可能性。

示例:训练随机森林分类器

想象一下,你想建立一个实验工作流,使你能够无缝且反复地训练随机森林分类器。你希望以一种方式进行配置,以便你只需将训练数据集、一些超参数和模型的目标目录传递给 CLI,它就会运行、训练模型并将其存储在指定位置。

在这个例子中,我们将使用公开的 鸢尾花种类 数据集。我们可以通过 seaborn 加载数据集并将其保存为 iris.csv

import searborn as sns
iris = sns.load_dataset("iris")
iris.to_csv('iris.csv', index=False)

为了更好地了解我们的数据,我们可以使用 成对图 可视化它:

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

作者提供的图片。使用的数据集:鸢尾花种类。许可证:CC0 公开领域

现在开始我们的主要任务:在我们的 Python 程序中构建一个解析器功能。为了训练随机森林分类器,我们希望将训练数据集传递给它——这将是我们的位置参数——两个超参数,以及一个我们希望保存模型的目标路径。后者将是我们的可选参数。

对于可选参数,我们还将通过type关键字指定类型,通过default关键字指定默认值,并通过help关键字提供参数的有用描述。

然后,我们将解析参数并将结果存储在变量args中,稍后我们将使用这些结果来指定我们正在读取的数据集、训练分类器的超参数以及我们希望模型保存的位置。

这段代码的样子如下:

import argparse
import pandas as pd
import pickle
from sklearn.ensemble import RandomForestClassifier

# Define and parse command-line arguments
parser = argparse.ArgumentParser(
    prog = 'Model training',
    description = 'Train a random forest classifier on the iris dataset'
)
parser.add_argument(
    'train_data', help='training data (.csv format)'
)
parser.add_argument(
    '--n_estimators', type=int, default=100,
    help='number of trees in the forest (default: 100)'
)
parser.add_argument(
    '--max_depth', type=int, default=None,
    help='maximum depth of the tree (default: None)'
)
parser.add_argument(
    '--model_path', type=str, default='./model.pkl',
    help='path to save the trained model (default: ./model.pkl)'
)
args = parser.parse_args()

# Read the dataset
iris = pd.read_csv(args.train_data)
X = iris.loc[:, iris.columns != 'species']
y = iris['species']

# Train a random forest classifier with the specified hyperparameters
clf = RandomForestClassifier(
    n_estimators=args.n_estimators,
    max_depth=args.max_depth,
    random_state=42)

clf.fit(X, y)

# Save the trained model to a pickle file
with open(args.model_path, 'wb') as f:
    pickle.dump(clf, f)

现在,让我们将脚本保存为train_rf.py并将其放置在与我们的训练数据集iris.csv相同的目录中。

接下来,我们打开一个终端窗口,从中可以用自定义参数调用这个程序。在下面的示例中,我们将n_estimators指定为 100,将max_depth指定为 10。至于model_path,我们对默认路径感到满意,因此在这种情况下无需指定。

>>> python .\train_rf.py 'iris.csv' --n_estimators 100 --max_depth 10 

这行代码将训练我们的随机森林分类器,过一会儿,你将会看到一个名为model.pkl的文件出现在你的目录中,你可以用它来在测试集上验证你的模型或生成预测。

我希望这篇文章给你提供了一些关于如何在 Python 中使用 argparse 直接从 CLI 解析参数的见解,从而改善你的机器学习应用程序的用户体验和互动性。

编程愉快!

更多资源:

喜欢这篇文章吗?

让我们联系一下吧!你可以在 TwitterLinkedIn 上找到我。

如果你希望支持我的写作,你可以通过 Medium 会员 来实现,这将为你提供访问我所有故事以及 Medium 上成千上万其他作者故事的权限。

[## 通过我的推荐链接加入 Medium - Thomas A Dorfer

阅读 Thomas A Dorfer(以及 Medium 上成千上万的其他作者)的每一篇文章。您的会员费直接支持……

medium.com](https://medium.com/@thomasdorfer/membership?source=post_page-----2f637eaf5f6a--------------------------------)

如何使用 Chat-GPT 和 Python 在 Neo4j 中基于你自己的文章构建知识图谱

原文:towardsdatascience.com/how-to-use-chat-gpt-and-python-to-build-a-knowledge-graph-in-neo4j-based-on-your-own-articles-c622bc4e2eaa

一个包含 120 多篇关于数学和数据科学的文章结构化知识的图形

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

·发布在 Towards Data Science ·8 分钟阅读·2023 年 8 月 26 日

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

作者截图

在这篇文章中,我将展示如何利用图形技术和一些编程来结构化和探索你自己的文章内容。

使用 NLP 技术来结构化非结构化数据的想法并不新鲜,然而,最新的大型语言模型(LLMs)的进展激发了无数机会。Chat-GPT 的普及技术使得业余爱好者对 LLMs 和生成模型产生了很多关注。

实际上,生成式 AI 已经成为许多公司议程中的一部分!

在这篇文章中,我们将通过编程语言 Python 使用 OpenAI 的开发者 API 来处理技术。我们将处理来自 Medium 的数据(哈哈,元数据?),并构建一个知识图谱。听起来可能有些复杂,但实际上开始时非常简单。

开始

首先,攻击计划如下。

  1. 使 API 正常工作并通过 Python 访问它。

  2. 使用示例文本进行提示工程,以确保 GPT-4 模型理解你的需求。

  3. 从 Medium 下载你的文章(如果你愿意,也可以使用其他文本),并对数据进行预处理。

  4. 提取和收集 Chat-GPT 的输出。

  5. 对 Chat-GPT 的输出进行后处理

  6. 编写代码使用 Cypher 查询语言进一步将数据结构化为图形。

  7. 玩弄你的新伙伴并探索你的文章。

话不多说,让我们通过快速设置基础技术来开始吧。

设置

我们需要在本地计算机上安装编程语言 Python 和图形数据库 Neo4j。

首先,你需要确保你在 OpenAI 有一个付费账户,以便可以使用 GPT-4。其次,你应该确保你已注册 API 使用。一旦准备好,你需要生成一个API 密钥。然后你需要 pip install openai

在连接 ChatGPT 之前,让我们去浏览器中尝试找到询问此任务的正确方式。这被称为提示工程,正确处理非常重要。通过使用我的一篇随机文章作为示例,尝试不同的询问方式,我发现正确的方法是提供一个详细且有指导性的预设,然后再给出实际文本。

我最终得到了以下的预设:

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

作者截图

作为示例,我给它了一段关于 Gamma 函数的文章摘录,这篇文章是我很久以前写的:

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

作者截图

它得出的结果是:

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

作者截图

尽管它显然并没有真正理解任务,但它做得还不错,特别是在格式上。然而,有时它会创建重复项,并且注意到它有时会虚构一些实体和关系,尽管我们要求它不要这样做。恼人的不听话的机器!我们稍后会处理这个问题。

为了将来使用,我们将把这个预设存储在一个名为 prompt_input.py 的 Python 文件中。

现在基础设置已经就绪,让我们测试一下它是否真的有效。

如果代码仅供你自己使用,并且只在本地机器上,你可以将 API 密钥硬编码到 Python 文件中,否则,你可以将其设置为环境变量或放在一个你不会推送的配置文件中!

让我们测试一下这个设置是否有效。我们创建一个名为 connect.py 的文件,包含从 Python 连接 ChatGPT 的基本代码。

我们验证这个是否有效!

数据

我需要从我的 Medium 账户中提取文章。在写作时,我已经发布了 123 篇文章,但从 Medium 下载功能返回了 259 个文件!这是因为它也将评论和草稿分类为帖子。我们只想要已发布的文章,但这还不是唯一的问题。这些文件是 HTML 文件!如果你想在浏览器中阅读当然没问题,但如果你想处理纯文本就不太适用了。

好吧,中等水平,你做得不错,但这不能阻止一个装备了编程语言和各种窍门的数据科学家!

我们还注意到下载文件的文件名相当混乱。一个标准名称的例子是“2020–12–11_The-Most-Beautiful-Equation-in-the-World-5ab6e49c363.html

让我们将这些文件存储在一个名为 raw 的文件夹中。

我们编写一个名为 extract_text_from_html.py 的小模块,功能是从这些文件中提取文本:

在我们能够实际从 ChatGPT 获取结果之前,我们需要能够将文本拆分成批次。原因是 GPT-4 有一个令牌限制。幸运的是,这很简单。在名为preprocess.py的文件中,我们编写:

现在我们准备实际从 ChatGPT 获取一些数据。

我们编写一个名为process_articels.py的文件,在其中循环处理文章,从令人恐惧的文件名中检索标题,从 HTML 文件中提取实际的文本,将每批文本通过ChatGPT处理,从文件中收集结果,并将模型的输出保存到一个名为data的文件夹中。我们还将实际的文本保存在一个名为cleaned的文件夹中,以便以后使用。

呼!!那真是一大堆工作。但实际上,代码很简单,因为我们已经在其他文件中完成了一些工作。

上述代码可能需要一段时间来执行,因为 GPT-4 模型相对较慢,与其他表现较差的模型相比。我们确保使用缓存设置,这样如果程序崩溃,我们不会从头开始,而是从中断的地方继续。

现在(经过几个小时的痛苦之后),我们有了一个结构化的 GPT-4 结果数据集。完美。现在我们“只”需要从中构建图谱。

构建知识图谱

我们将预处理和图谱创建过程合并为一个单独的函数。这通常不是很明智(关注点分离),但由于我们在预处理阶段需要查看“关系和实体”层级,我们可以在双手沾满污垢时创建图谱中的节点和关系。

我们创建一个小型 API,包含一个驱动程序,以便我们可以与图形进行交互。

我们需要循环处理结果,确保实体太长,清理结果,并定义 gpt 模型输出中的节点关系,我们希望用相同的查询多次调用图形,我们希望实体与原始文章相关联,然后我们需要确保 Chat-GPT 提出的每个实体和关系实际存在于文本中,以免我们构建一个机器梦的图谱!

上述要求的最后一点是提高我们信任图形的概率,即使它不是万无一失的,考虑到这一点。

没问题!我们写下以下内容:

当然,有很多方法可以为知识图谱创建模式。不是总能容易看出什么应该是节点,什么应该是关系,但由于我们不希望关系之间有关系,所以我们选择了上述方法。

此外,我为这篇文章选择了简约的方法。通常,我们会用更多的属性来丰富节点和关系。

现在我们只需要一个主要入口点。

就这样。现在我们有了一个包含 Medium 上我文章信息的知识图谱。事实上,我们有大约 2000 个节点和 4500 个关系。

探索图谱

那么我们可以用这个做什么?我们应该问它什么?

让我们尝试找出不同的人出现在多少篇文章中。我们有如下结果:

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

作者截图

不出所料,欧拉排在榜首,但我惊讶于拉马努 jan 和牛顿出现在我的 4 篇文章中。当然,我可以找到这些文章的标题,但让我们继续。好吧,这很有趣,但你不需要一个图表就能搞清楚这一点。

我们再试试别的。让我们看看有多少篇文章同时提到瑞曼和欧拉。

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

作者截图

让我们看看我的文章提到了多少欧拉的发现。

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

作者截图

嗯,没有欧拉线?我得写一篇关于这个的文章。

让我们找出有多少篇文章与文章群论共享了一些数学关键词。

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

作者截图

结果显示在这里,与上图中非橙色节点连接的 27 篇其他文章。尽管这只是一个玩具示例,但可以想象它同样可以显示业务相关文档如何通过一些在某些学科(如 GDPR 或审计)中重要的敏感关键词相互关联。

收获

显然,这项工作应该被视为我们所谓的“概念验证”。我们不能真正地利用我的文章,但如果这些文本来自一个公司,包含关于他们的客户和员工的信息,从电子邮件到 Word 文档、PDF 等等,这可以用来绘制客户之间的关系以及哪些员工密切合作。

这将使我们能够 360 度了解数据如何在整个组织中流动,谁是特定信息流的最重要人物,谁是了解特定主题或文档的合适人选,我们部门联系的客户曾被另一个部门联系过,等等。

极其宝贵的信息。当然,我们不能用 ChatGPT 来做这个,因为我们不知道我们发送的数据会发生什么。因此,询问它关于敏感或业务关键的信息不是一个好主意。我们需要做的是下载另一个仅存在于我们笔记本电脑上的 LLM(大型语言模型)。一个本地 LLM。我们甚至可以在自己的数据上进行微调。目前许多公司已经在进行这种操作,用于构建聊天机器人、助手等。

但如果你问我,用它来构建一个关于你非结构化数据的知识图谱是更高层次的工作,我认为我已经展示了这完全是可行的!

如果你的公司想知道我们如何利用你的数据为你的业务编织可能性网络,请联系或我的同事Kenneth Nielsen

感谢你的阅读。

如果你喜欢在 Medium 上阅读像这样的一些文章,你可以 获取会员资格 以获得全部访问权限。要加入社区,只需点击 这里

如何使用 ChatGPT 生成图表

原文:towardsdatascience.com/how-to-use-chatgpt-to-generate-diagrams-a78fb6693057

提示工程,SVG

快速教程:如何编写合适的提示以让 ChatGPT 生成图表

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

·发布于 Towards Data Science ·阅读时长 4 分钟·2023 年 5 月 29 日

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

图片来源:Christina @ wocintechchat.comUnsplash

你可能知道 ChatGPT 在生成文本方面非常出色。你是否想过它也能为你创建令人惊叹的图表?如果你还没听说过,也不用担心,因为我在这里告诉你所有的相关信息。

在这篇文章中,我们将向你展示如何利用 ChatGPT 生成令人惊叹的图表。所以,让我们直接开始吧!

我们将涵盖以下内容:

  • 入门指南

  • 提示的结构

  • 一个更高级的示例

入门指南

让我们假设你想使用 ChatGPT 创建以下图形:

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

作者提供的图像

创建视觉上引人注目且易于理解的图表的关键在于让 ChatGPT 生成 SVG 代码。是的,你没听错——ChatGPT 掌握着你成功的关键,你需要做的就是学习如何挖掘它的无限潜力。

向 ChatGPT 写下以下提示:

编写 SVG 代码生成以下图像:一个白色矩形,边框为绿色。将以下文本居中放置在矩形内:hello world!

ChatGPT 将生成以下代码:

<svg xmlns="http://www.w3.org/2000/svg" width="300" height="200">
  <rect x="50" y="50" width="200" height="100" fill="white" stroke="green" stroke-width="2"/>
  <text x="150" y="100" text-anchor="middle" alignment-baseline="middle" font-size="20" fill="black">Hello World!</text>
</svg>

复制并粘贴到一个新文件中。将文件保存为 SVG 扩展名并打开它!你将看到生成的图像!

提示的结构

让 ChatGPT 绘制复杂图表不仅仅是生成代码。要掌握图表绘制的艺术,你需要将指令分解为小的、具体的步骤。只有这样,你才能释放创造力,设计出既美观又实用的图表。

为了让 ChatGPT 绘制复杂的图表,我们可以将它们拆分成单独的组件,然后给出如何构建每个组件的指令。我们可以按如下方式组织 ChatGPT 提示:

1. 初始声明

在这里,我们指示 ChatGPT 构建生成 SVG 图像的代码:

Write the svg code to generate the following image width 600 height 300:

2. 生成组件列表

现在我们将组件生成列表指定为一个项目符号列表:

- A
- B
- C

对每个组件,指定一些细节作为嵌套列表:

- A
-- A1
-- A2
- B
-- B1
-- B2
-- B3
- C
-- C1

细节包括与每个组件相关的具体元素,如大小、颜色等。

一个更高级的例子

现在,让我们进入一个更高级的例子。假设我们要绘制以下图表:

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

图片由作者提供

将问题分成三个独立的部分:

  • 绘制带有文本的矩形

  • 绘制带有文本的圆形

  • 绘制带有文本的箭头。

让我们指示 ChatGPT 执行这三个步骤。

首先,给 ChatGPT 一些通用建议:

Write the svg code to generate the following image width 600 height 300: 

然后,指示 ChatGPT 绘制矩形。尽可能具体:

- a white rectangle with:
-- width 150, height 50
-- green borders. 
-- center the following text inside the rectangle: Application

现在,关于圆形的建议:

- on the right of the rectangle, draw a white circle with:
-- cx 500
-- radius 50
-- green borders. 
-- center the following text inside the circle: lake

最后,指定如何构建箭头:

- a green arrow from the rectangle to the circle:
-- the arrow must end when the circle begins
-- add the following text centered above the arrow: request

就这些!ChatGPT 将为你生成以下代码:

<svg xmlns="http://www.w3.org/2000/svg" width="600" height="300">
  <rect x="225" y="125" width="150" height="50" fill="white" stroke="green" stroke-width="2" />
  <text x="300" y="150" text-anchor="middle" alignment-baseline="middle">Application</text>
  <circle cx="500" cy="150" r="50" fill="white" stroke="green" stroke-width="2" />
  <text x="500" y="150" text-anchor="middle" alignment-baseline="middle">lake</text>
  <path d="M375,150 L450,150" fill="none" stroke="green" stroke-width="2" marker-end="url(#arrowhead)" />
  <text x="412.5" y="125" text-anchor="middle">request</text>
  <defs>
    <marker id="arrowhead" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto">
      <polygon points="0 0, 10 3.5, 0 7" />
    </marker>
  </defs>
</svg>

将代码粘贴到一个空文件中,并将其保存为 SVG 扩展名。然后,用浏览器打开该文件以查看生成的图表!

总结

恭喜!你刚刚学会了如何在 ChatGPT 中生成图表!主要有两个要素:

  • 让 ChatGPT 为你生成 SVG 代码

  • 将指令拆分成小而具体的步骤。

尝试不同的形状、颜色和布局,以创建视觉上吸引人且易于理解的图表。

记住,成功生成图表的关键是将指令拆分成小而具体的步骤。这将使你能够专注于每个图表元素,并确保一切都正确放置。

利用 ChatGPT 强大的 AI 技术,生成图表从未如此简单!无论你是学生、商业专业人士,还是喜欢视觉沟通的人,ChatGPT 都可以帮助你快速创建令人惊叹的图表。那么为什么不今天就试试看,看看你能想到什么令人惊叹的图表呢?

如何在数据可视化中使用颜色

原文:towardsdatascience.com/how-to-use-color-in-data-visualizations-37b9752b182d

利用颜色提升数据理解

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

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

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

长臂猿。 来源:Adobe Stock,标准许可

上图突出了弗朗索瓦长臂猿,这是一种最不常见的猴类物种之一。 值得注意的是,它们的幼崽拥有鲜艳的橙色皮毛,随着成长逐渐变为黑色。现有理论认为,这种橙色使父母能够在树顶环境中轻松监控幼崽¹。这对于及时识别和应对威胁,如即将到来的捕食者攻击至关重要。如果成年猴子能够用语言表达,它可能会说:

抓住橙色的!

这里应该给自然母亲以赞美。多亏了颜色的有效使用,最小和最脆弱的存在有可能被保留。

为什么颜色在数据可视化中如此重要?

我必须承认,我犹豫了很久才发布这篇文章。原因是这个话题已经被广泛讨论。然而,我仍然看到一个细分领域,特别是在实际运用颜色的细节展示上。

我已经在最近的一篇文章中介绍了颜色概念的功能性用途。现在,我想分享一些在这一领域的额外提示。希望你会发现它们既实用又客观。让我们从一些无效的颜色使用例子开始。

1. 装饰优先于功能

如果我们没有明确解释为什么在特定可视化中使用了颜色,这个问题就会出现。以这张图表为例。你能解释一下为什么这里应用了如此多的颜色吗?

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

来源:作者提供的图片。

有时候,美学是一种可行的解释。但这很棘手。我们进入了一个充满个人品味、喜好和厌恶的模糊领域。对某些人而言视觉上令人愉悦的东西可能对其他人来说是不可接受的。

2. 缺乏一致性和客观性

有时,我们在可视化中不一致地使用饱和度或亮度级别。我们通过从调色板(如 PowerPoint 中)选择颜色来做到这一点,而不确保幻灯片之间的一致性。这有时可能是由于疏忽,但主要是由于匆忙。虽然大多数人会忽略这种“问题”,但一些敏锐的观察者可能不会。

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

来源:作者的屏幕截图。

疏忽通常表现为关键信息突出显示不一致:一张幻灯片上是黄色,另一张幻灯片上是蓝色。同样,不一致的颜色编码也会发生错误——当一种颜色代表一个元素(如某一页的预算),而在另一页上代表结果或预测时。

3. 忽视色彩障碍用户

众多杰出的出版物巧妙地突出了这个问题。通过如Adobe Color这样的工具可以深入了解这个问题,该工具展示了不同颜色组合如何适应各种视觉障碍。即使我没有视力障碍(或我认为我没有),我仍然很难区分某些色调和渐变。

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

Adobe Color 工具展示了不同视力障碍如何影响颜色的解读。 来源:作者的屏幕截图。

4. 忽视上下文

颜色不是孤立看到的:它们的周围环境会影响它们。尽管我们的眼睛通过光波长来检测颜色,但我们通过与邻近颜色的比较来看到颜色。

请看下面的例子。同一个方块在从白色到黑色的渐变中放置在不同的位置时,看起来不同。我们看到每个方块的方式不同,因为它旁边的灰色阴影各异。它在浅灰色背景下看起来比在深色背景下更暗。²

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

来源:基于 2 的作者图片。

5. 使用颜色进行精确可视化

虽然颜色可以表示值,但对于精确比较并不是最佳选择。如下面所示,色调和饱和度在精确度领域的排名较低。这表明它们在值评估中不够准确,更容易出现用户错误。

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

来源:基于SAP,数据讲述手册的作者图片。

为什么正确使用颜色如此重要?

正如上述例子所示,颜色深刻影响我们对信息的感知。这就是为什么它在数据可视化中扮演了关键角色。

你是否遇到过**“前注意处理”这个术语?它指的是我们两步信息吸收过程中的初始阶段。这个阶段是自动的,涉及启发式方法、反射和模式识别——这些元素是我们不会主动思考的。前注意处理主要注意到呈现给我们的信息中最显著的特征,例如形状、大小和颜色!**然而,它并非完美无缺。由于其冲动的性质,它有时会误导我们。

考虑这个(非色彩示例):

A 项和 B 项的费用为$110,其中 A 项比 B 项贵$100。许多人可能本能地说 B 项是$10。但那么,A 项的费用就是$110,两个项目的总费用是$120。B 项的正确价格是$5. 在许多情况下,那些回答$10 的人被前注意处理所误导。

这就是为什么 我们必须有意识地使用它的证据!

简要色彩理论³

在我展示有关有效使用颜色的想法之前,我想展示一些理论设置。

色彩理论有两个基本组成部分(根据我的简化理解):

  • 色彩解剖学,和

  • 色彩层次。

色彩解剖学

色彩解剖学,分析我们如何感知颜色,包含三个核心组件:

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

色调、饱和度与明度。 来源:作者提供的图片。

色调是指感知到的颜色或色调。简单来说——那就是我们所说的颜色,例如红色、绿色、蓝色等。

饱和度表示颜色的强度,高饱和度产生鲜艳的颜色,而低饱和度则产生较暗、较白的色调。

明度虽然类似于饱和度,但涉及的是色调的深浅——黑白的程度——而不是颜色的亮度。

明度和饱和度都创建了一个显著的强度尺度,可用于突出差异。

色彩和谐

色彩和谐体现了特定颜色组合可以产生视觉对比或协调的思想。根据你希望通过数据传达的叙事,你选择的安排可以优化效果。

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

Adobe Color 中的各种色彩和谐。 来源:作者提供的图片,基于 Adobe Color 的屏幕截图。

如何在数据可视化中使用颜色?

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

来源:作者在 Adobe Photoshop 2024 中生成的图像。

为了让用户成功地与可视化中的信息互动,他们必须:

  1. 找到它,

  2. 阅读它,并且

  3. 理解它。

“找到它”

可视化应使用户能够以最小的认知努力找到关键信息。更重要的信息应比不那么关键的数据更显著。旨在区分操作上关键数据的颜色编码必须始终可辨别。

“阅读它”

在所有条件下展示操作性重要信息时,易读性至关重要。为了确保易读性:

  • 确保符号(或文本)与背景之间有足够的对比度。

  • 符号或文本应当具有足够的大小和笔画宽度,以确保可见性和可读性。

“理解它”

一旦信息被找到并阅读,颜色应当以最小的认知努力和错误风险来促进用户的理解。

  • 颜色编码: 颜色代码用于区分关键数据类别,应当易于识别、数量有限,并在所有背景下都能区分。

  • 一致性: 报告或演示文稿中的颜色代码应保持一致:每种颜色代码只能代表单一的数据类别(或者单一颜色可以代表所有数据类别)。

  • 惯例: 遵循文化惯例是有帮助的(例如,红色表示警告,黄色表示注意,绿色表示安全)。⁴

颜色不仅仅是为了让你的数据看起来更漂亮;它是为了引导你的观众通过一个故事,并使复杂的信息易于消化。

如何处理数据展示中的颜色?

为什么,为什么,为什么?

这是选择可视化和其元素时的关键问题。颜色必须专门用于数据讲述,以实现明确的沟通目的。 颜色不应仅仅用于装饰图形。虽然美化图表可能有助于品牌意识或广告目标,但这会分散对数据讲述真正重要内容的关注。而这就是我们信息中的数据。²

从灰度开始!

那么,我如何处理颜色?正如Cole Nussbaumer Knafflic 在 YouTube 采访中建议的,我的可视化初稿通常使用灰度(轴线或标签可能有例外)。然后,我应用不同的颜色,但总是有明确的目的,比如吸引注意力或帮助理解。

与 Cole Nussbaumer Knafflic 的视频采访。 来源:YouTube。

我在展示这种方法的有效性时感到满足,同时“提升”所谓的意大利面图表,如上图所示。这些图表通常作为沟通方法存在缺陷。然而,一个简单的策略——一次专注于一个系列,同时将其他(用灰色标记)作为背景信息(例如,用来说明趋势)——可能非常有效。

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

来源:作者灵感来源于 5。

重新考虑你的视觉效果⁵

好吧,我们从灰度开始,应用了颜色,最后变成了圣诞树。字面上的。

有时,过度使用颜色的倾向源于选择不适当的视觉效果。 请参考以下例子,这些例子受到了 Datawrapper 博客的启发。虽然渐变颜色可以有效地显示模式,例如在 choropleth 地图上,但它们挑战了实际值和差异的辨别。选择使用条形图、位置或区域来显示最重要的值,将颜色保留用于区分类别或集中注意力。这应能使读者更快地解读值。

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

来源:作者的图片,灵感来源于 5。

如果图表需要超过七种颜色,考虑使用不同的图表类型或对类别进行分组。虽然颜色有助于读者区分数据类别,但使用过多的颜色可能会由于频繁查阅颜色键而阻碍快速数据理解。

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

来源:作者的图片,灵感来源于 5。

使用不同的颜色

好的。所以,我们已经选择了正确的视觉效果。然而,在决定颜色时,我们必须确保它们是不同的。色调在创建颜色区分度方面至关重要。虽然亮度和饱和度的调整可以增加变化,但它们可能会暗示虚假的重要性层次——除非这是你的意图(我稍后会展示)。例如,我们应该避免使用两个具有相同色调但不同亮度和饱和度的颜色,除非它们相关联的值本质上是相关的。⁷

对比度规则

颜色需求 上下文,正如前面的段落中展示的那样。 我建议考虑以下两个规则以确保颜色之间的对比。

规则 1: 确保表格或图表中相同颜色的对象看起来相同,通过提供匹配的背景颜色来实现。

规则 2: 为了使表格或图表中的对象清晰可见,使用与对象有足够对比度的背景颜色。

规则 1 在图表中的直接应用是避免使用背景颜色渐变或变化的背景颜色。 避免不必要的图表装饰对清晰和有说服力的数据展示至关重要。²

我应用的对比度基本规则是:

  • 浅色背景配以深色元素(例如,白色背景,黑色字体,深灰色图表填充,蓝色突出显示填充)。

  • 深色背景配以浅色元素(例如,黑色背景,白色字体,浅灰色图表填充,黄色突出显示填充)。

背景颜色

两种颜色有效:白色或黑色。

开玩笑的! 几乎任何颜色都适用,无论是浅色还是深色,只要你遵循一些特定的指导方针,其中一些我将在下面概述。我经常遵循的一条规则是对于较长的演示文稿使用浅色背景,因为它在长时间观看时较少疲劳。我可能会选择深色背景用于较短的演示文稿,主要是出于审美原因或个人喜好。然而,我会避免所有闪亮的颜色变体。

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

这些颜色不适合用作背景。 来源:作者提供的图片。

三色规则

选择背景颜色后,我必须决定其他元素。在这里,我尝试应用“三色规则”。三色计数不包括背景,背景作为“上下文设置器”。说实话,我通常无法完全遵守这个规则。不过没关系。只要我尽量减少颜色数量,效果通常不会远离理想状态。

对于浅色背景(通常是白色),我使用以下颜色:

  • 颜色 1: 通常黑色或深灰色用于文本(标题、正文)。

  • 颜色 2: 通常中灰色用于较少相关的图表元素(填充、标签、网格等)。

  • 颜色 3: 通常使用蓝色突出显示重要文本或可视化元素。有时,我使用绿色表示积极,红色表示消极,以指示变化。

对于深色背景(在我的演示文稿中大多数是纯黑色):

  • 颜色 1: 文字用白色。

  • 颜色 2: 如果颜色容易辨别,这可以与浅色背景的情况相同。

  • 颜色 3: 我可能会选择柔和的黄色,同时适用绿色或红色规则。

可能会有例外,但仅在必要时(例如,为了区分直接放置在可视化上的标签而添加白色或黑色字体)。

仅此而已。这是它的可能效果。

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

遵循三色规则的幻灯片示例。 来源:作者提供的图片。

参考调色板

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

颜色调色板。 来源:作者在 Adobe Photoshop 2024 中生成的图片。

有时,我对颜色选择感到困惑,尤其是当我选择标准 PowerPoint 调色板之外的颜色时。但我有一个技巧可以帮助我缓解这个问题。我在精心设计的公司模板中发现了它。它们有时包含一个颜色调色板,通常放在最后一张幻灯片上。如果没有这样的模板,我会用填充参考颜色的形状来制作我的参考调色板。每当我不确定选择哪个颜色时,我就会去最后一张幻灯片,使用颜色选择器选择颜色。这是一种可靠的方法!

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

参考调色板示例。 来源:作者提供的图片

如果你制作大量演示文稿,建立一套标准的优质颜色可能会很有效。 理想情况下,创建几种颜色调色板,每种调色板设计用于特定用途。至少,开发三种调色板:一种包含鲜艳的颜色,第二种包含对人眼容易辨别的中等色调,第三种则包含浅色、几乎透明的颜色。²

使用直观的颜色

我强烈建议选择与受众文化理解相符的颜色调色板,使用他们自然会将数据与之联系起来的颜色。尽可能做到这一点。请参见下方的可视化,这一可视化再次受到 Datawrapper 博客文章的启发。⁵

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

来源:作者基于 5 的图片

一点说明:虽然绿-红组合通常用于表示好-坏关系,但重要的是要注意,大约 5%的人群难以区分这些颜色。例如,给绿色加上蓝色的色调可以帮助确保更广泛的观众能清楚辨别。⁶

注意颜色心理学

说到颜色直观,值得注意的是最常见的颜色解释。

这些是跨文化中最广泛的颜色解释:

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

颜色的文化解释。来源:作者基于 8 的图片

在商业中,这可能略有不同。以下是根据商业目的可以使用的颜色:

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

颜色的商业解释。来源:作者基于 8 的图片

颜色差异的灰度测试

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

来源:由作者在 Adobe Photoshop 2024 中生成的图像

尽管我缺乏科学证据,不能保证其普遍适用(例如,帮助那些有特定视力障碍的人),但这种方法曾多次帮助过我。我称之为“灰度测试”。你可以在 PowerPoint 中轻松完成此操作。在打印选项卡中选择“灰度”选项,而不是“彩色”选项。然后,“打印预览”窗口中的显示颜色将发生变化。如果你仍然能区分可视化中的系列和类别,你可以祝贺自己:你做得很好。

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

来源:作者的打印屏幕

在下方的图像中,我展示了我的意思。右侧的图表使用灰度展示。即便如此,仍然可以看到类别之间的差异。

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

如果在灰度下有效,那么在其他地方也应该有效! 来源:作者的图片

使用颜色表示数字中的顺序

在利用颜色表示数值的序列范围时,遵循单一色调(或一组相关色调),从浅色到深色、饱和度更高的颜色来表示低值到高值。我们直观地将颜色强度的增加感知为数值的增加,但这种感知不适用于不同颜色。

这些颜色可以分配给图表中的四组柱,以指示四个部门在一年中的表现,从最差(最暗)到最好(最浅)。

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

使用颜色表示序列。 来源:受 2 启发的作者提供的图片。

在热图中使用一组有序颜色可以直观地呈现高销售值,快速识别出哪些产品卖得最好或最差,哪些省份或产品表现最好或最差,即使没有具体数值。²

序列和分歧调色板

序列调色板包括一组按顺序排列的颜色,感知上呈递增。相比之下,如这里所示,分歧或双步骤调色板由两个颜色序列组成,这些序列从中央中点对称地增强,每个方向相反。

分歧调色板有效地展示了逻辑中点以上和以下的数值。例如,一家公司的利润可以通过热图使用分歧调色板表示:一种调色板用于利润,另一种用于亏损,以零作为中点。²

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

序列和分歧调色板。 来源:作者提供的图片。

一些有用的工具

有许多工具可以帮助你有效选择颜色。我之前提到过Adobe Colors。这里是一些你在设计有效颜色调色板时可以考虑使用的其他工具:

我如何使用这些工具?

首先,我决定关键颜色。这可以是你公司标志中的颜色,或者用于企业沟通的颜色,或任何激发你灵感的颜色。第二步是使用应用程序选择一个颜色和谐:适合背景和预期效果。最后,我尽量减少颜色的数量(注意三色规则!)。

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

Viz Palette 工具。 来源:作者截图。

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

数据颜色选择器。 来源:作者提供的图像。

使用 LLM 和生成式 AI

ChatGPT 和 DALL-e 3

最后,我们可以利用 LLMs 自我帮助。以下是一个使用 ChatGPT 和 DALL-e 3 生成的简单示例。

这是我的初步构思: 初始提示和一些生成的创意。

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

提示 1。 来源:作者截屏。

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

由 ChatGPT 和 DALL-e 3 生成的第一个提案。 来源:作者截屏。

这是经过一些微调后的第 4 版(我花了 3-4 个额外提示)。我可以用它来激发后续幻灯片的灵感,选择颜色,使用类似字体等。

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

第 4 版提案的微调版本。 来源:作者截屏。

ChatGPT 和 Canva

你还可以使用 ChatGPT 和 Canva 插件。

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

使用 ChatGPT 和 Canva 插件生成幻灯片创意。 来源:作者截屏。

这是我得到的其中一个创意。

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

ChatGPT 和 Canva 插件建议的模板。 来源:作者截屏。

ChatGPT 独立使用

好的。上述功能适用于 ChatGPT Plus(付费)用户。不过,如果你使用的是 ChatGPT 免费版,仍然可以用它来提供帮助,如下所示。

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

使用 ChatGPT 生成的特定背景色的演示文稿颜色建议。 来源:作者截屏。

结论

颜色不仅仅是为了让你的数据看起来漂亮;它还引导你的观众理解故事,使复杂信息易于消化。 从观察自然到与我们多彩的计算机屏幕互动,颜色影响着我们对体验和信息的感知、理解和记忆。

有效使用数据可视化中的颜色不仅仅是选择吸引人的色调。它包括:

  • 清晰沟通: 确保数据易于查找、阅读和理解。

  • 保持一致性: 采用统一的调色板以在视觉效果中保持颜色含义的一致性。

  • 包容性: 选择对色盲人士可见的调色板,认识到颜色感知的差异。

秘诀在于将美学吸引力与清晰度和精确度结合起来,制作引人入胜且启发性的视觉效果。

通过遵循基本的色彩理论原则,优先考虑可访问性,并使用战略性和一致性的色彩调色板,你可以将数据可视化从简单的图表转变为引人入胜的叙述。让颜色成为讲述数据故事的盟友,引导观众通过可视化,并提供连贯、可访问且令人难忘的用户体验。

你喜欢这篇文章吗?考虑订阅以获取我发布的新故事通知,或关注我

参考资料:

  1. 安迪·杰弗里,婴儿时期的弗朗索瓦长臂猿身披霓虹橙色外套

  2. Skuteczne Raporty,九条有效使用颜色的原则 (颜色有效使用的十条规则)

  3. Revuint,色彩理论在数据可视化中的作用

  4. NASA AMES 研究中心,颜色使用指南层级

  5. 丽莎·夏洛特·穆斯,选择数据可视化颜色时需要考虑的事项

  6. 威罗妮卡·加瓦尔斯卡-蒂沃内克,数据可视化中色彩的功能:一个简单(但完整)的指南

  7. 迈克尔·易,如何为数据可视化选择颜色

  8. 迪米拉·特涅瓦,颜色心理学:不同颜色在营销中的含义

如何在 Neo4j 图数据科学库中使用 Cypher 聚合

原文:towardsdatascience.com/how-to-use-cypher-aggregations-in-neo4j-graph-data-science-library-5d8c40c2670c?source=collection_archive---------11-----------------------#2023-03-27

利用 Cypher 聚合功能,在内存图中展示所有 Cypher 查询语言的灵活性和表现力

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

·

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

Cypher 聚合是 Neo4j 图数据科学库的一个强大功能,允许用户使用灵活而表达力强的方法来投影内存中的图。尽管使用 Cypher 投影可以在很长一段时间内投影内存中的图,但它缺乏一些功能,最显著的是无法投影无向关系。因此,GDS 中添加了一种新的内存图投影方法,称为 Cypher 聚合。这篇博客将探讨 Neo4j 图数据科学库中 Cypher 聚合投影选项的语法和常见用法。

环境设置

如果你想跟随示例,可以打开一个 Neo4j Sandbox 中的图数据科学项目。该项目包含有关机场、其位置和航班路线的小数据集。

我们可以使用以下 Cypher 语句可视化图模式:

CALL db.schema.visualization()

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

图模式。图片由作者提供。

使用 Cypher 聚合投影内存中的图

首先,让我们快速回顾一下 Neo4j 图数据科学库的操作方式。

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

图数据科学库工作流。图片由作者提供。

在我们执行任何图算法之前,首先必须投影内存中的图。内存图不必是数据库中存储图的精确副本。我们可以选择图的子集,或者如你稍后将学到的,也可以投影未存储在数据库中的虚拟关系。投影内存图后,我们可以执行任意多的图算法,然后直接将结果流式传输给用户,或将其写回数据库。

使用 Cypher 聚合投影内存中的图

Cypher 聚合功能是图数据科学工作流的第一步,即在内存中投影图。它提供了 Cypher 查询语言的完全灵活性,可以在投影过程中选择、过滤或转换图。Cypher 聚合函数的语法如下:

gds.alpha.graph.project(
    graphName: String,
    sourceNode: Node or Integer,
    targetNode: Node or Integer,
    nodesConfig: Map,
    relationshipConfig: Map,
    configuration: Map
)

只有前两个参数(graphName 作为 sourceNode)是必需的,但你需要指定 sourceNode 和 relationshipNode 参数以定义单个关系。我们将详细介绍你可能需要的大部分选项,以帮助你使用 Cypher 聚合来投影图。

我们将从一个简单的示例开始。假设我们想要投影所有 Airport 节点及其之间的 HAS_ROUTE 关系。

MATCH (source:Airport)-[:HAS_ROUTE]->(target:Airport)
WITH gds.alpha.graph.project('airports', source, target) AS graph
RETURN graph.nodeCount AS nodeCount, 
       graph.relationshipCount AS relationshipCount

Cypher 语句以 MATCH 子句开始,该子句选择相关的图。要使用 Cypher 聚合定义关系,我们输入 sourcetarget 节点。

当然,Cypher 查询语言提供了选择图的任何子集的灵活性。例如,我们可以只投影大洋洲的机场及其航班路线。

MATCH (source:Airport)-[:HAS_ROUTE]->(target:Airport)
WHERE EXISTS {(source)-[:ON_CONTINENT]->(:Continent {name:"OC"})}
  AND EXISTS {(target)-[:ON_CONTINENT]->(:Continent {name:"OC"})}
WITH gds.alpha.graph.project('airports-oceania', source, target) AS graph
RETURN graph.nodeCount AS nodeCount, 
       graph.relationshipCount AS relationshipCount

在这个例子中,匹配的 Cypher 语句变得稍微复杂了一些,但 Cypher 聚合函数保持不变。airports-oceania 图包含 272 个节点和 973 条关系。如果你对 Cypher 有经验,你可能会注意到上述 Cypher 语句不会捕获任何在大洋洲没有航班路线的机场。

假设我们也想在投影中显示孤立机场。在这种情况下,我们需要稍微修改 Cypher 匹配语句。

MATCH (source:Airport)
WHERE EXISTS {(source)-[:ON_CONTINENT]->(:Continent {name:"OC"})}
OPTIONAL MATCH (source)-[:HAS_ROUTE]->(target:Airport)
WHERE EXISTS {(target)-[:ON_CONTINENT]->(:Continent {name:"OC"})}
WITH gds.alpha.graph.project('airports-isolated', source, target) AS graph
RETURN graph.nodeCount AS nodeCount, graph.relationshipCount AS relationshipCount

关系数量保持不变,而节点数量增加到 304。因此,32 个大洋洲的机场没有任何航班路线通往其他大洋洲机场。

在处理图中的多个节点和关系类型时,我们可能希望在投影过程中保留节点标签和关系类型的信息。在图投影过程中定义节点和关系类型使我们可以在算法执行时对其进行筛选。

CALL {
    MATCH (source:Airport)-[r:HAS_ROUTE]->(target:Airport)
    RETURN source, target, r
    UNION
    MATCH (source:Airport)-[r:IN_CITY]->(target:City)
    RETURN source, target, r
}
WITH gds.alpha.graph.project('airports-labels', source, target,
  {sourceNodeLabels: labels(source),
   targetNodeLabels: labels(target)},
  {relationshipType:type(r)}) AS graph
RETURN graph.nodeCount AS nodeCount, graph.relationshipCount AS relationshipCount

当投影多个不同的图模式时,我更倾向于使用UNION子句。然而,具体使用什么 Cypher 匹配语句完全取决于你。由于我们投影的是两种类型的节点和关系,保留它们的标签和类型信息可能是个好主意。因此,我们使用了sourceNodeLabelstargetNodeLabelsrelationshipType参数。在这个例子中,我们使用了现有的节点标签和关系类型。

然而,有时我们可能希望在投影过程中使用自定义标签或关系类型。

CALL {
    MATCH (source:Airport)-[r:HAS_ROUTE]->(target:Airport)
    RETURN source, target, r
    UNION
    MATCH (source:Airport)-[r:IN_CITY]->(target:City)
    RETURN source, target, r
}
WITH gds.alpha.graph.project('airports-labels-custom', source, target,
{sourceNodeLabels: CASE WHEN source.city = 'Miami' 
                       THEN 'Miami' ELSE 'NotMiami' END,
 targetNodeLabels: ['CustomLabel']},
{relationshipType: CASE WHEN type(r) = 'HAS_ROUTE' 
                        THEN 'FLIGHT' ELSE 'NOT_FLIGHT' END}) AS graph
RETURN graph.nodeCount AS nodeCount, graph.relationshipCount AS relationshipCount

正如你所见,我们可以使用 Cypher 动态定义节点或关系类型,也可以直接硬编码它。如果自定义的节点标签或关系类型比较复杂,也可以在 Cypher 匹配语句中计算。

CALL {
    MATCH (source:Airport)-[r:HAS_ROUTE]->(target:Airport)
    RETURN source, target, r,
         CASE WHEN source.city = target.city 
              THEN 'INTRACITY' ELSE 'INTERCITY' END as rel_type
    UNION
    MATCH (source:Airport)-[r:IN_CITY]->(target:City)
    RETURN source, target, r, type(r) as rel_type
}
WITH gds.alpha.graph.project('airports-labels-precalculated', source, target,
  {sourceNodeLabels: labels(source),
   targetNodeLabels: labels(target)},
  {relationshipType: rel_type}) AS graph
RETURN graph.nodeCount AS nodeCount, graph.relationshipCount AS relationshipCount

有时,我们也希望投影节点或关系属性。

MATCH (source:Airport)-[r:HAS_ROUTE]->(target:Airport)
WITH gds.alpha.graph.project('airports-properties', source, target,
  {sourceNodeLabels: labels(source),
   targetNodeLabels: labels(target),
   sourceNodeProperties: {runways: source.runways},
   targetNodeProperties: {runways: target.runways}},
  {relationshipType: type(r), properties: {distance: r.distance}}) AS graph
RETURN graph.nodeCount AS nodeCount, graph.relationshipCount AS relationshipCount

节点或关系属性被定义为一个映射对象(对于 Python 或 JS 开发者来说是字典或 JSON 对象),其中键表示投影的属性,值表示投影的值。这种语法允许我们投影在投影过程中计算出的属性。

MATCH (source:Airport)-[r:HAS_ROUTE]->(target:Airport)
WITH gds.alpha.graph.project('airports-properties-custom', source, target,
  {sourceNodeLabels: labels(source),
   targetNodeLabels: labels(target),
   sourceNodeProperties: {runways10: source.runways * 10},
   targetNodeProperties: {runways10: target.runways * 10}},
  {relationshipType: type(r),
  properties: {inverseDistance: 1 / r.distance}}) AS graph
RETURN graph.nodeCount AS nodeCount, graph.relationshipCount AS relationshipCount

同样,我们可以利用 Cypher 的所有灵活性来计算任何节点或关系属性。与节点标签类似,我们也可以在MATCH子句中计算自定义属性。

一个重要的注意事项是当前的投影行为是引擎在第一次遇到节点时存储节点属性。然而,在随后的节点遇到中,它会完全忽略节点属性。因此,你必须小心为源节点和目标节点计算相同的节点属性。否则,投影结果可能与预期存在差异。

Neo4j 图数据科学库中的一些图算法期望无向关系。关系不能以无向方式存储在数据库中,必须在图投影期间明确地定义。

假设你想将所有投影关系视为无向关系。

MATCH (source:Airport)-[r:HAS_ROUTE]->(target:Airport)
WITH gds.alpha.graph.project('airports-undirected', source, target,
  {}, // nodeConfiguration
  {}, // relationshipConfiguration
  {undirectedRelationshipTypes: ['*']}
) AS graph
RETURN graph.nodeCount AS nodeCount, graph.relationshipCount AS relationshipCount

我们可以使用 undirectedRelationshipType 来指定哪些关系应被投影为无向关系。在实际操作中,你可以观察到,当我们投影无向图时,关系数量翻了一倍。

有时你可能希望将某一类关系投影为无向关系,而将其他关系视为有向关系。

CALL {
    MATCH (source:Airport)-[r:HAS_ROUTE]->(target:Airport)
    RETURN source, target, r
    UNION ALL
    MATCH (source:Airport)-[r:IN_CITY]->(target:City)
    RETURN source, target, r
}
WITH gds.alpha.graph.project('airports-undirected-specific', source, target,
  {},
  {relationshipType:type(r)},
  {undirectedRelationshipTypes: ['IN_CITY']}) AS graph
RETURN graph.nodeCount AS nodeCount, graph.relationshipCount AS relationshipCount

在这个示例中,HAS_ROUTE 关系被视为有向关系,而 IN_CITY 关系被视为无向关系。当我们想要指定特定的关系类型被视为无向关系时,必须在关系配置中包含 relationshipType 参数。

最后,我们还可以投影虚拟关系。虚拟关系是一种未存储在数据库中的关系。

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

虚拟关系。作者提供的图像。

假设你想根据城市的航班连接来检查城市。数据库中没有城市之间的航班关系。你可以在图投影期间计算这些关系,而不是在数据库中创建它们。

MATCH (sourceCity)<-[:IN_CITY]-(:Airport)-[:HAS_ROUTE]->(:Airport)-[:IN_CITY]->(targetCity)
WITH sourceCity, targetCity, count(*) AS countOfRoutes
WITH gds.alpha.graph.project('airports-virtual', sourceCity, targetCity,
  {},
  {relationshipType:'VIRTUAL_ROUTE'},
  {}) AS graph
RETURN graph.nodeCount AS nodeCount, graph.relationshipCount AS relationshipCount

正如你所观察到的,使用 Cypher 聚合投影投影虚拟关系非常简单。我们计算了各个城市之间的路线数量,并将其添加为投影图中的关系属性。

让我们基于 PageRank 算法计算最重要的城市,以完成这篇博客文章。

CALL gds.pageRank.stream('airports-virtual')
YIELD nodeId, score
RETURN gds.util.asNode(nodeId).name AS city, score
ORDER BY score DESC
LIMIT 5

结果

总结

Cypher 聚合是使用 Cypher 语句在 Neo4j 图数据科学库中投影内存图的新选项。具体来说,它可以用于投影无向关系,这在旧的 Cypher 投影中是不可能的。然而,随着在投影期间选择和转换图的灵活性增加,性能成本也随之增加。因此,如果可能的话,你应该出于性能考虑使用原生投影。另一方面,当你有特定的用例需要投影图的某一特定子集、计算自定义属性或投影虚拟关系时,Cypher 聚合是你的好帮手。

如何使用 dbt 种子

原文:towardsdatascience.com/how-to-use-dbt-seeds-f9239c347711

它们是什么,何时使用

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

·发布于 Towards Data Science ·阅读时间 4 分钟·2023 年 4 月 25 日

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

engin akyurtUnsplash 上的照片

我必须诚实地说,我已经很久没有使用 dbt seeds 了。实际上,我是在几天前试图验证对我们一个数据模型所做的更改时重新发现了它们。

我的经理给我发送了一个包含在我们数据模型中发现的真正重复值的 CSV 文件。我正在处理在我们一个源的临时模型中删除这些重复项。修改后,我需要验证这些重复项是否不再出现在模型中。

我没有手动将 CSV 文件上传到我们的数据仓库,这在 Redshift 中几乎不可能。我使用了 dbt 种子将 CSV 文件导入我们的仓库。然后,我能够快速运行一个验证查询,以确认重复项已被删除。

这太简单了!作为一名分析工程师,我喜欢事情简单。因为老实说,它们很少如此简单。这让我思考我们如何进一步利用 dbt 种子来简化我们的分析工程师工作。

更不用说,dbt 种子还可以被数据科学家和机器学习工程师用来测试他们的模型。你可以用它来摄取测试数据和训练数据,使它们在你的数据仓库中存在为两个不同的参考点。

什么是 dbt 种子?

在 dbt 中,有三种主要类型的对象——源、模型和种子。你可以像对待源和模型一样测试和记录种子。唯一的区别是它们不是从你的 dbt 项目中的 SQL 代码创建的。它们不是数据模型。它们只是你已读取到 dbt 中的 CSV 文件,用于作为模型的参考

dbt 种子命令

要使用 dbt seeds,你需要一个要导入到数据仓库的 CSV 文件。首先,确保你能找到 CSV 文件的位置。然后,将其移动到 dbt 项目中的 seeds 目录。如果你已经在 dbt 项目中,可以运行以下命令将其移动到 seeds 目录:

mv <CSV file path> seeds

每个 dbt 项目自动具有此目录,所以你不需要自己重新创建它。

注意:确保为这个 CSV 文件起一个描述性的名字!最好在你的 dbt 风格指南 中设定关于 seeds 命名的标准。

然后,简单地运行 dbt seed 命令:

dbt seed

这将以你的 CSV 文件名在数据仓库的目标模式中创建一个表。现在,你可以像引用自己创建的 dbt 模型一样引用这个表!

如果你不熟悉,选择 dbt 模型的语法是:

{{ ref('duplicate_users') }}

如果我的 CSV 文件名为 duplicate_users.csv,那么目标模式中的表将命名为 duplicate_users,我会像上面那样在另一个模型中引用这个表。

如何使用 dbt seeds

dbt seeds 可以用于许多不同的原因。每当你需要查询一个静态 CSV 文件时,你可以将其创建为 seed 并使用 dbt 转换这些数据!

验证

我在介绍中提到过一个使用 dbt seeds 进行验证的例子。这是我最近作为分析工程师使用 seeds 的方式。我有别人为我拉取的数据,我用它来检查对数据模型所做的一些更改的输出。

当业务团队找你寻求帮助时,他们提供给你一个 CSV 或 Excel 文件,指出某些数据问题,这时使用这个数据是很好的。你可以直接在 dbt 中使用这些数据来解决问题,而不是自己重新创建问题。

静态参考表

我看到大多数人使用 dbt seeds 来创建静态参考表。因为这些表始终保持不变,并且不需要更改,所以使用 seeds 将它们导入数据仓库是有意义的。

一些很好的例子是 dim_date 表、country_code 表或 zipcode 映射表。这些表在分析中经常使用但从不更改。与其手动创建这些表作为 dbt 数据模型,不如重用公开的文件并将其导入你的仓库。这样,你就不会增加额外的工作量!

测试和训练模型

与其处理大型数据集,不如使用 dbt seeds 导入 CSV 文件作为测试和训练数据集。这将节省运行模型的时间和在数据仓库中存储大量数据的空间,从而节省资金。

将业务知识转移到你的数据仓库

最后,你可以使用 seeds 来移动仅以电子表格形式存在的数据。如果公司还没有数据仓库,大多数数据通常存储在 Excel 电子表格中。

dbt seeds 允许你轻松导出这些电子表格,并将它们创建为数据表,旨在创建单一的真实数据源。只需记住,不要在业务团队仍在使用的电子表格上频繁种子/重新种子。这更适用于捕捉不再更新的静态或历史数据。

结论

当正确使用时,dbt seeds 功能强大。如果你已经是 dbt 用户,它们是将 CSV 文件移动到数据仓库的简单解决方案。它可以快速验证并创建静态数据表。因此,下次你需要使用 CSV 进行分析时,考虑一下种子文件吧!

想了解更多关于 dbt 和分析工程的信息,请查看我的每周免费通讯

正确使用 DAX 中的 FILTER

原文:towardsdatascience.com/how-to-use-filter-in-dax-the-correct-way-eb621b49527a

DAX 中的 FILTER()函数可能难以驾驭。你可能会陷入一些陷阱,导致 DAX 代码的性能不佳。以下是如何使用 FILTER()以及不该如何使用的一些示例。

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

·发表于Towards Data Science ·阅读时长 11 分钟·2023 年 2 月 13 日

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

图片由Andrea De SantisUnsplash提供

介绍

一年多前,我写了一篇关于FILTER()函数的文章:

## 发现 DAX 中 FILTER()的强大功能

FILTER()函数在 DAX 中非常强大,但它有一些复杂之处。让我们深入探讨这些细节,以构建一个良好的…

towardsdatascience.com

我在那里解释了一些关于这个强大函数的细节。

我没有做的是解释和展示 FILTER()的一些性能相关细节。

如果你对这个函数不熟悉或不确定如何使用它,可以跳到那篇文章以获得基本了解。

我的旧文和这篇文章之间有一些冗余,但学习基础知识总是正确的。

除了展示如何使用 FILTER()函数外,我还将展示每种变体对性能和效率的影响。

为此,我将使用DAX Studio和 DAX Studio 中的服务器时间来获取性能统计数据。

如果你不知道 DAX Studio 中的这个功能,或者对那里显示的度量解释不确定,可以阅读这篇文章,我将在其中深入探讨这个功能:

## 如何使用 DAX Studio 从 Power BI 获取性能数据

有时我们有一个慢报表,需要找出原因。我们将看到如何收集性能数据以及……

towardsdatascience.com

基本查询

为了确定我们的起点,我在我的演示数据集中定义了一个基本查询(详见参考部分):

我想获取国家和相应的销售数据,但我希望将销售产品的品牌限制为这三个:

  • Contoso

  • Northwind Traders

  • Fabrikam

基本查询如下:

// Basic Query with the Measure using a direct Filter
 DEFINE
   MEASURE 'All Measures'[RestrictedRetailSales] =
          VAR ListOfBrands = {"Contoso", "Northwind Traders", "Fabrikam" }

          VAR Result = 
              CALCULATE(
                  [Sum Online Sales]
                  ,'Product'[BrandName] IN ListOfBrands
                  )

 RETURN
   Result

EVALUATE
    CALCULATETABLE(
            ADDCOLUMNS(
                SUMMARIZE(Geography, Geography[RegionCountryName])
            ,"Restricted Online Sales", [RestrictedRetailSales])
            )

我将展示如何更改行 ‘Product’[BrandName] IN ListOfBrands 并查看这些更改的后果。

结果如下(片段):

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

图 1 — 基本查询的部分结果(图由作者提供)

我们得到 35 行所有已知国家的值,包括中国、德国和美国。

基本查询的服务器时间如下:

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

图 2 — 基本查询的服务器时间(图由作者提供)

查询执行得相当快,持续时间为 0.3 秒,效率也不错,因为 91.6%的时间花费在存储引擎上。

好的,让我们做一些修改并查看后果。

第一个变体 — 引入 FILTER()

这是查询的第一个变体:

// Query with the Measure using a Filter using the FILTER Function on the table
DEFINE
  MEASURE 'All Measures'[RestrictedRetailSales] =
      VAR ListOfBrands = {"Contoso", "Northwind Traders", "Fabrikam" }

      VAR Result = 
            CALCULATE(
                [Sum Online Sales]
                ,FILTER('Product'
                      ,'Product'[BrandName] IN ListOfBrands)
                      )

RETURN
  Result

EVALUATE
    CALCULATETABLE(
            ADDCOLUMNS(
                SUMMARIZE(Geography, Geography[RegionCountryName])
            ,"Restricted Online Sales", [RestrictedRetailSales])
            )

这次,我在产品表上添加了一个过滤器,以根据这三个品牌进行过滤。

这里是服务器时间:

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

图 3 — 第一个变体的服务器时间(图由作者提供)

总执行时间几乎相同,但存储引擎所花费的时间多了 100 毫秒。

并且,我们有五个存储引擎查询,而不是三个。

这些查询中的两个使用了 CallbackDataID 调用,这意味着存储引擎调用公式引擎执行其无法完成的操作。

在这种情况下,品牌列表创建了两次进行过滤。

DAX Studio 将包含 CallbackDataID 的查询标记为粗体,因为此调用不适合性能和效率。

此外,前两个查询各返回了超过 2’500 行。这称为物化。

我们应该尽量减少 DAX 表达式中的物化大小。

在这种情况下,2’517 是整个产品表的行数,这意味着公式引擎获取了整个表格,并需要随后进行过滤。

想象一下我们有一个包含数十万行的表。这个变体将加载整个表格,所需时间为:

· 很多内存

· 很多时间

好的,使用 FILTER() 这种方式完全不可取。

第二个变体 — 使用 ALL() 的 FILTER

使用以下变体,我们将ALL()函数添加到 FILTER()调用中。

ALL() 函数移除给定表或列上的任何过滤器,并返回一个包含所有值的表。

// Query with the Measure using a Filter using the FILTER Function on the Product[Brand] column with ALL()
  DEFINE
    MEASURE 'All Measures'[RestrictedRetailSales] =
      VAR ListOfBrands = {"Contoso", "Northwind Traders", "Fabrikam" }

      VAR Result = 
            CALCULATE(
              [Sum Online Sales]
              ,FILTER(ALL('Product'[BrandName])
                      ,'Product'[BrandName] IN ListOfBrands)
                      )

RETURN
  Result

EVALUATE
    CALCULATETABLE(
            ADDCOLUMNS(
                SUMMARIZE(Geography, Geography[RegionCountryName])
            ,"Restricted Online Sales", [RestrictedRetailSales])
            )

结果仍然相同,但服务器时间与第一种变体的差异很大:

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

图 4 — 第二种变体使用 ALL() 的服务器时间(图由作者提供)

使用这个变体,我们得到的查询和时间几乎与原始查询相同,而无需使用 FILTER()。

如果我们仔细观察,我们会发现存储引擎查询在两者之间是相同的。

因此,这两个查询在性能和效率上是等效的。

这非常有趣,因为它展示了两个引擎的智能。

差异如下:

  • 基础和第二种变体替换了品牌列上的过滤器。

  • 第一种变体添加了对品牌列的过滤器,而没有改变现有的过滤器上下文。

    这会导致额外的查询。

由你决定使用哪种变体。作为一个懒人,我更喜欢输入更少的代码来获得相同的结果。

第三种变体——添加 VALUES() 代替 ALL()

让我们将 ALL() 函数替换为VALUES()函数。

VALUES() 函数对于一个列返回一个包含源列唯一值(排除重复项)的表。

// Query with the Measure using a Filter using the FILTER Function on the Product[Brand] column with VALUES()
DEFINE
  MEASURE 'All Measures'[RestrictedRetailSales] =
      VAR ListOfBrands = {"Contoso", "Northwind Traders", "Fabrikam" }

      VAR Result = 
            CALCULATE(
                [Sum Online Sales]
                ,FILTER(VALUES('Product'[BrandName])
                      ,'Product'[BrandName] IN ListOfBrands)
                      )

RETURN
  Result

EVALUATE
    CALCULATETABLE(
          ADDCOLUMNS(
              SUMMARIZE(Geography, Geography[RegionCountryName])
          ,"Restricted Online Sales", [RestrictedRetailSales])
          )

结果仍然相同:35 行所有国家和三个值。

这些是服务器时间:

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

图 5 — 第三种变体使用 VALUES() 的服务器时间(图由作者提供)

再次,我们看到相同的三个 SE(存储引擎)查询(与基础和第二个查询看起来相同)和几乎相同的持续时间。

数字在执行之间变化很小,但它们与基础查询非常相似。

这表明使用 VALUES() 就像使用简单的过滤谓词或使用 FILTER() 与 ALL() 相同。

第四种变体——添加一个额外的过滤器

除了过滤品牌外,我还想按产品颜色进行过滤:

// Query with the Measure using a Filter using the FILTER Function on the Product[Brand] column with ALL()
// This time with two columns
DEFINE
    MEASURE 'All Measures'[RestrictedRetailSales] =
      VAR ListOfBrands = {"Contoso", "Northwind Traders", "Fabrikam" }

      VAR Result = 
            CALCULATE(
                [Sum Online Sales]
                ,FILTER(ALL('Product'[BrandName], 'Product'[ColorName])
                        ,'Product'[BrandName] = "Contoso"
                           && 'Product'[ColorName] = "Red"
                        )
                    )

RETURN
  Result

EVALUATE
    CALCULATETABLE(
            ADDCOLUMNS(
                SUMMARIZE(Geography, Geography[RegionCountryName])
                ,"Restricted Online Sales", [RestrictedRetailSales])
                )

当然,查询结果中的数字会变化,因为我们只想获取红色产品的销售数据。

以下是服务器时间:

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

图 6 — 第四种变体过滤两个列的服务器时间(图由作者提供)

结果很吸引人。

查询比之前快得多,并且只使用了两个 SE 查询。

如上图所示,我们得到一个查询,该查询在产品表中使用一个 WHERE 过滤器来过滤两个列。

这意味着 SE 在组合一个表上的过滤器时非常智能,因为它消除了第一个查询,只执行了两个而不是三个查询。

第五种变体——从两个表中过滤列

下一步是尝试从两个不同的表中过滤两个列:

  • 品牌 = “Contoso” 在产品表中

  • 大陆 = “欧洲” 来自客户表

这是满足这一要求的起点。

// Query with the Measure using a Filter using the FILTER Function on the Product[Brand] column with VALUES()
// This time with two columns from two different tables
DEFINE
    MEASURE 'All Measures'[RestrictedRetailSales] =
      VAR ListOfBrands = {"Contoso", "Northwind Traders", "Fabrikam" }

      VAR Result = 
          CALCULATE(
              [Sum Online Sales]
              ,FILTER(ALL('Product'[BrandName])
                  ,'Product'[BrandName] = "Contoso"
                    && 'Customer'[ContinentName] = "Europe" - < Why this cannot function? )
                )

RETURN
  Result

EVALUATE
  CALCULATETABLE(
        ADDCOLUMNS(
              SUMMARIZE(Geography, Geography[RegionCountryName])
        ,"Restricted Online Sales", [RestrictedRetailSales])
        )

这不起作用:

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

图 7 — 使用 FILTER()时过滤来自不同表的列的错误(图由作者提供)

不能工作的原因是第二列来自另一个不属于 FILTER 函数输入的表:

FILTER(ALL('Product'[BrandName]) <--Input table
         ,'Product'[BrandName] = "Contoso"
         & 'Customer'[ContinentName] = "Europe" <-- Not part of input table
        )

让我们尝试另一种方法:

// Query with the Measure using a direct Filter in CALCULATE, but without FILTER
// Again with two columns from two different tables
DEFINE
    MEASURE 'All Measures'[RestrictedRetailSales] =
      VAR ListOfBrands = {"Contoso", "Northwind Traders", "Fabrikam" }

      VAR Result = 
          CALCULATE(
              [Sum Online Sales]
              ,'Product'[BrandName] = "Contoso"
              ,'Customer'[ContinentName] = "Europe" - < This works, But without FILTER()
              )

RETURN
  Result

EVALUATE
  CALCULATETABLE(
      ADDCOLUMNS(
            SUMMARIZE(Geography, Geography[RegionCountryName])
      ,"Restricted Online Sales", [RestrictedRetailSales])
      )

这次我们使用直接过滤器(谓词),不使用 FILTER()函数。

这种方法有效,并且执行速度非常快且高效:

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

图 8 — 第五个变体的服务器时间,使用直接过滤器(图由作者提供)

但我们想看到其他内容。

我们如何在来自不同表的列中使用 FILTER 函数?

第六个变体 — 为 FILTER()构建表

我们必须从不同的源表中构建一个输入表以实现这一点。

为此,我们使用SUMMARIZECOLUMNS()来生成一个结合给定列中值的表:

// Query with the Measure using a Filter using the FILTER Function with two columns from two separate tables
DEFINE
  MEASURE 'All Measures'[RestrictedRetailSales] =
    VAR ListOfBrands = {"Contoso", "Northwind Traders", "Fabrikam" }

    VAR Result = 
        CALCULATE(
            [Sum Online Sales]
            ,FILTER(SUMMARIZECOLUMNS('Product'[BrandName]
                                    ,'Customer'[Continent])
                ,'Product'[BrandName] = "Contoso"
                && 'Customer'[Continent] = "Europe" - < This works, as we build a table with SUMMARIZECOLUMN() as the input for FILTER()
                )
            )

RETURN
  Result

EVALUATE
  CALCULATETABLE(
        ADDCOLUMNS(
            SUMMARIZE(Geography, Geography[RegionCountryName])
        ,"Restricted Online Sales", [RestrictedRetailSales])
        )

SE 可以将这个变体解释为执行仅一个查询以获得结果(第二个查询仅检索国家列表):

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

图 9 — 第六个变体的服务器时间和 SE 查询(图由作者提供)

此外,总执行时间非常短。

但在我们得出结论之前,我还有一个变体给你。

第七个变体 — 使用 CROSSJOIN()进行 FILTER()

最后的变体使用了CROSSJOIN()函数。

这个函数返回一个表,其中包含第一个输入表的每一行与第二个表的每一行的乘积。

详细信息请阅读上面链接的DAX Guide文章或观看视频。

// Query with the Measure using a Filter using the FILTER Function with two columns from two different tables
DEFINE
  MEASURE 'All Measures'[RestrictedRetailSales] =
    VAR ListOfBrands = {"Contoso", "Northwind Traders", "Fabrikam" }

    VAR Result = 
          CALCULATE(
              [Sum Online Sales]
              ,FILTER(CROSSJOIN(ALL('Product'[BrandName])
                                ,ALL('Customer'[ContinentName]))
                    ,'Product'[BrandName] = "Contoso"
                    && 'Customer'[ContinentName] = "Europe" - < This works, as we build a table with SUMMARIZECOLUMN() as the input for FILTER()
                    )
              )

RETURN
  Result

EVALUATE
  CALCULATETABLE(
        ADDCOLUMNS(
              SUMMARIZE(Geography, Geography[RegionCountryName])
          ,"Restricted Online Sales", [RestrictedRetailSales])
          )

结果仍然没有改变。但执行模式却大相径庭:

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

图 10 — 使用 CROSSJOIN()的第七个变体的服务器时间(图由作者提供)

尽管总执行时间没有多长,但现在我们有四个 SE 查询。

但前两个查询执行速度极快。

第一个查询检索所有大洲的列表(6 行),第二个查询检索所有品牌的列表(14 行)。

第三和第四个查询与之前的变体相同。

但这个变体还有更多需要考虑的地方:

  1. Cross-Join 由公式引擎(FE)完成。对于如此少量的值来说,这不是问题。但当你有数百或数千个值时,这将花费大量时间。

  2. 这个变体生成一个包含两个列(品牌和大洲)的表,其中包含所有可能的组合。该表用两个谓词(Brand = “Contoso”和 Continent = “Europe”)进行了过滤。最后,生成的表被作为过滤器应用于 CALCULATE()函数。

  3. 使用 CROSSJOIN()函数必须配合使用 ALL()函数。如果不使用 ALL()函数,你将会遇到错误。作为替代方案,可以使用 VALUES()函数,它会产生相同的结果。

  4. 这种变体需要大量编写而没有任何好处,因为 SE 查询与上述两个变体中的查询相同。但当你需要以这种特定方式构造 FILTER()的输入表时,现在你知道这是可能的。

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

Afif RamdhasumaUnsplash拍摄的照片

结论

正如你所见,使用 DAX 中的 FILTER 函数有很多可能的变体。

但请注意。在我的示例中看起来很快的操作,在你的场景中可能会大相径庭,因为你可能会面临不同的数据情况。

你需要过滤的列中独特的值越多,你就越需要注意如何使用 FILTER()。

在我看来,直接过滤的方法是第一种也是最有效的方法,因为它需要最少的努力和输入。在大多数情况下,它可以正常工作。

所以,不要过度工作或过度思考你的度量值,因为最简单和直接的方法可能是正确的。

如果你想了解更多关于这种方法的信息,可以阅读以下内容:

## 不要从优化代码开始。这可能不是一个好主意

这篇文章的标题似乎违背直觉。为什么你不应该用最优化的方式来开发你的解决方案……

medium.com

参考文献

我使用了 Contoso 示例数据集,就像我之前的文章中提到的那样。你可以从微软这里免费下载 ContosoRetailDW 数据集。

Contoso 数据可以在 MIT 许可证下自由使用,如这里所述。

我扩大了数据集,以使 DAX 引擎更加费劲。

在线销售表包含 7100 万行(而不是 1260 万行),零售销售表包含 1850 万行(而不是 340 万行)。

## 通过我的推荐链接加入 Medium - Salvatore Cagliari

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

medium.com

如何使用 Google 的 PaLM 2 API 与 Python

原文:towardsdatascience.com/how-to-use-google-palm-2-api-with-python-373bc564251c?source=collection_archive---------2-----------------------#2023-08-14

自定义并将 Google 的 LLM 集成到你的应用程序中。

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

·

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

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

图片由 Alexandre Debiève 提供,来源于 Unsplash

生成型人工智能无处不在。我们看到越来越多的公司投资于这项强大技术,因为它的潜力变得越来越明显。正如 Gartner 所说:在不久的将来,[生成型人工智能]将成为竞争优势和差异化的关键。

“在不久的将来,[生成型人工智能]将成为竞争优势和差异化的关键。”

不幸的是,开发生成性 AI 模型不仅是复杂的工程工作,而且通常是一个相当昂贵的项目。幸运的是,我们不必自己开发这些模型 — 我们可以重用已经为我们预先开发的:通过 APIs!所以,不要再等了 — 让我们直接深入了解如何通过集成生成性 AI 到我们的应用程序中来利用它。

对于本文,我们将查看谷歌对 LLM 的回答PaLM 2 API。PaLM 2 是谷歌最新版本的Pathways 语言模型,这是一个大型语言模型,使用的训练数据量约是他们在 2022 年发布的初始模型的五倍。

在本文中,我将介绍一些代码示例并展示如何认证到 Google Cloud,使用以及自定义PaLM 2 APIs,并使用 Python 3.11。

1 | 入门

PaLM 2 APIs 可以通过Google CloudVertex AI 平台访问。因此,在我们进行任何 API 调用之前,我们需要设置我们的 Google Cloud 账户。你可以 在这里注册 并获得 $300 的免费额度 来开始使用这些服务。

一旦你的账户和项目设置完成,我们可以继续 创建一个服务账户,我们将用它来认证到 Vertex AI APIs。我们使用服务账户,是因为我们可以通过仅给予它们特定的 IAM 权限来确保对 Google Cloud 资源的访问控制。对于我们的用例,我们将授予服务账户 Vertex AI User 角色。这可能对你的用例来说过于宽泛,所以我建议你检查 可用的访问角色 并选择适合你需求的角色。

在创建了服务账户并赋予其正确的权限后,我们可以继续 生成一个服务账户密钥。选择 JSON 作为密钥类型,并将文件保存在安全的位置。

很好 — 我们准备动手操作了!👏

2 | 认证到 Google Cloud

在这个示例中,我们将使用 OAuth 2.0 进行认证,并借助我们在前一步生成的服务账户密钥请求访问令牌。

为了便利这个过程,我们可以使用 [google-auth](https://pypi.org/project/google-auth/) Python 库,如下面的代码示例所示:

使用 google-auth Python 库认证到 Google Cloud。

这个代码示例使用服务账户密钥文件“key.json”来请求和生成一个访问令牌,我们可以用它来访问 Google Cloud APIs。在获得访问令牌后,我们可以开始使用它调用 Vertex AI PaLM 2 APIs。

3 | 调用 PaLM 2 API

截至今天,Google Cloud 中提供了两种不同的 PaLM 2 模型:PaLM 2 for Text(即[text-bison](https://cloud.google.com/vertex-ai/docs/generative-ai/text/text-overview))和PaLM 2 for Chat(即[chat-bison](https://cloud.google.com/vertex-ai/docs/generative-ai/chat/chat-prompts))。文档建议对可以用一个回复完成的文本任务使用text-bison,对需要更多对话互动的文本任务使用chat-bison

让我们从text-bison模型开始。对于这些示例,我们将使用 Python 的[requests](https://pypi.org/project/requests/)库来进行 API 调用。如果你愿意,也可以使用Vertex AI SDK

PaLM 2 for Text:情感分析

PaLM 2 for Text 模型可用于各种与文本相关的任务:包括摘要、回答问题、情感分析等。它接受以下参数作为输入:

  • prompt:我们希望模型执行的任务的指令。

  • temperature:控制模型的“创造性”。如果我们希望模型在回复中更具开放性和创造性,则应提高温度。如果我们希望模型更具确定性,则温度应降低。值的范围在 0 到 1 之间。

  • maxOutputTokens:生成输出的 token 数量(1 个 token = 4 个字符)。值的范围在 1 到 1024 之间。

  • topK:改变模型选择生成输出的 token 的概率。在每个 token 选择步骤中,具有最高概率的topK个 token 被采样,然后进一步通过topP筛选。值越高,响应越随机。值的范围在 1 到 40 之间。

  • topP:改变模型选择生成输出的 token 的概率。token 的选择直到其概率总和等于topP。值越高,响应越随机。值的范围在 0 到 1 之间。

有关参数的更多细节,请参见 此文档

在这个第一个例子中,我们将对一些示例产品评论进行情感分析:

sentences = ["I have been using this product for a long time. Somehow the 
             product I received this time seems to be a fake one. It's 
             very thick and the smell is very chemical.",
             "A good book for for dog owners. The book dosen't just 
             focus on dog training itself, but also on nutrition and care. 
             The book contains all the information needed for beginner dog 
             owners.",
             "This lamp was better than I expected when it comes to its 
             quality. Nonetheless, the colours are not exactly as 
             displayed and it does not really fit with the curtains that I 
             purchased recently. Therefore I give this 3 out of 5 stars."]

我们给模型的指令(即提示)需要清楚地说明我们希望模型执行的任务,以及我们期望它生成的输出。在我们的例子中,我们要求它遍历sentences列表中的每个评论,并告诉我们这些评论的情感。我们还指示它将输出提供为 Python 列表。

prompt = f"What is the sentiment of each of these reviews: {sentences}. 
         Output should be in a python list."

最后,我们需要定义输入参数值

  • 我们将temperature设置为0,因为对于这个任务,我们希望避免模型过于创意。通过降低温度,我们使得模型更有可能输出我们请求的确切结构。

  • 我们将256设置为maxOutputTokens,因为它大约相当于 200 个单词,并且是适合我们任务的长度。

  • 我们将topK设置为 40,因为这是模型的默认值。

  • 我们将topK设置为 0.95,因为这是模型的默认值。

我们现在可以像进行任何其他 API 调用一样发出 API 调用,使用[requests](https://pypi.org/project/requests/)库,如下所示:

向 Google Cloud PaLM 2 for Text API 发出 API 调用。

我们可以通过response.json()[“predictions”][0][“content”]来获取响应的输出:

"['negative', 'positive', 'positive']"

很棒!现在,让我们做完全相同的操作并尝试将temperature参数设置为1.0。这将意味着我们的模型输出将变得越来越富有创意。我们得到的输出如下:

"The sentiment of each of these reviews is:
1\. Negative
2\. Positive
3\. Positive"

的确,我们可以看到输出比以前更具创意,并且没有正确遵循我们提到的“输出应该是一个 python 列表”的提示。因此,这是一个很好的教训,即选择合适的参数值非常重要,以从模型中获得期望的输出。

现在你可能会问自己:“这是否意味着我不能确定模型输出是否符合正确的格式?” 有多种机制可以设置以测试模型的输出并检查其是否符合你预期的格式。从理解并正确配置模型的输入参数,到优化你的提示(即提示工程),以及实施额外的静态测试以验证输出的结构。强烈建议应用这些技术,因为生成式 AI 可能会出错,我们希望在它们发生之前就解决这些问题。

PaLM 2 for Text: 文本生成

在我们的下一个示例中,让我们要求 PaLM 2 为新客户生成欢迎文本,他们正在访问一个电子商务网站。我们想欢迎他们,并在首次购买时提供 20%的折扣码。对于这个用例,我们希望我们的模型提出一些更具创意的内容。因此,我们将temperature设置为0.5

discount_code = "2023-promo"

prompt = f"Can you write 2-3 sentences that can be displayed on an 
         e-commerce webpage if someone first visits it? It should contain 
         the code '{discount_code}' which gives the customer 20% discount 
         on their first purchase."

输出如下:

"**Introducing our 20% off first purchase offer!**

Use the code **2023-promo** at checkout to save 20% on your first 
purchase. This offer is valid for a limited time only, so don't miss out!

**Shop now and start saving!**"

很好!它甚至以 markdown 格式给出了输出。让我们再次尝试将temperature调整为1.0。输出如下:

"**20% OFF YOUR FIRST PURCHASE**

Use code 2023-promo at checkout to save 20% on your first purchase from 
our store. This offer is valid for new customers only and expires on 
March 31, 2023.

**Shop now and save big!**"

我们再次可以看到我们的模型相比之前的输出变得更加富有创意。它甚至提出了一个优惠过期日期,而我们并没有明确要求它这样做。

PaLM 2 for Chat: 对话助手

在最后一个示例中,我们将测试专注于生成对话体验的 PaLM 2 for Chat API。我们将使用的模型称为chat-bison。它接受以下参数作为输入:

  • messages:包含与聊天机器人之间的消息和消息历史记录。

  • context:定义聊天机器人行为的“指南”。例如:聊天机器人的名称是什么,它的角色是什么,包含/排除的词汇等。

  • examples:示例输入和输出,展示了聊天机器人在对话中的响应方式。

  • 以及temperaturemaxOutputTokenstopKtopP,它们的作用与前一节中的text-bison模型相同。

有关参数及其具体作用的更多详细信息,请参见 此文档

我们来创建一个聊天机器人,作为在线园艺商店“GardenWorld”的客户支持代表。这个机器人应当能够回答有关植物和花卉类型、园艺工具等问题。我们希望机器人始终对客户友好和热情,并且应该用“Hoowdy gardener! 🌱”来问候客户,并激励客户注册新闻通讯以获得首次购买的 10%折扣码。

我们可以通过设置contextexamples参数来定义这些,如下所示:

context = "You're a customer assistance bot for an online gardening store 
          called GardenWorld and you want to help customers. You give 
          advice around gardening best practices, plant and flower types. 
          Always welcome the customer by telling them to subscribe to 
          the GardenWorld newsletter to get a 10% discount on their first 
          purchase."

examples = [{
           "input": {"content": "Hi!"},
           "output": {"content": "Hoowdy gardener! 🌱"}},
           {
           "input": {"content": "Hello"},
           "output": {"content": "Hoowdy gardener! 🌱"}
           },
           {
           "input": {"content": "Why should I choose GardenWorld?"},
           "output": {"content": "GardenWorld has been the award winning 
                                 supplier for best quality plants and 
                                 gardening equipment. With over 25 years 
                                 of experience, we continuously provide 
                                 the best in class service to our 
                                 customers."}}
           ]

我们将给模型三个示例,说明输出应是什么样的。当然,我们提供的示例越多,机器人可以定制的程度就越高,模型将能够更好地学习我们期望的内容。由于我们的用例非常简单,这三个示例应该能给机器人足够的信息来提供正确的答案结构。我们将temperature设置为1.0maxOutputTokens设置为256topK设置为40topP设置为0.95

现在,我们开始对话,先说“Hi!”。

messages = [{
          "author": "user",
          "content": "Hi!",
           }]

然后我们可以进行 API 调用:

向 Google Cloud PaLM 2 进行聊天 API 调用。

几秒钟后,我们得到以下回复:

"Hoowdy gardener! 🌱 How can I help you today? Don’t forget to subscribe 
to the GardenWorld newsletter to get a 10% discount on your first 
purchase!"

好的!我们的模型准确地完成了我们的要求:它使用了正确的问候语(甚至包括了表情符号🌱),并提到了 10%折扣码。

为了继续与机器人对话,我们需要相应地更新对话历史。我们可以定义两个简单的函数,在每次 API 调用后调用它们:

更新聊天机器人的消息历史的功能。

update_history()将最新的机器人回复添加到messages列表中。然后我们可以使用send_message()向机器人发送一个新问题“我需要一株易于照料的漂亮室内植物。你有什么推荐?”。

现在我们的messages变量如下所示,最新的消息位于列表末尾:

[{"author": "user", 
  "content": "Hi!" },
 {"author": "1"
  "content": "Hoowdy gardener! 🌱 How can I help you today? Don’t forget 
             to subscribe to the GardenWorld newsletter to get a 10% 
             discount on your first purchase!" },
 {"author": "user",
  "content": "I need a nice houseplant that is easy to take care of. What 
             can you recommend?" }]

我们可以在下一次 API 调用中包含messages历史记录,得到的回复是:

"A snake plant is a great choice for a houseplant because it is very low 
maintenance and can thrive in a variety of conditions. They are also very 
tolerant of neglect, so they are perfect for people who are busy or 
forgetful."

它建议我们选择“蛇尾兰”,这是一种被认为易于照料的室内植物。让我们将这条消息也添加到messages历史记录中。

然后,我们提出最后一个问题“你能建议一些替代方案吗?另外,我可以获得折扣吗?”我们得到的回复是:

"Sure! We offer a 10% discount to all first time customers who subscribe 
to our newsletter. A ZZ plant is another great option for a low-
maintenance houseplant. They are also very tolerant of neglect and can 
thrive in a variety of conditions.'

很好!如上所示,机器人建议了我们的折扣码,感谢messages历史记录,它记住了我们之前提出的问题,并建议了一个容易打理的植物“ZZ plant”。

结果展示了我们如何轻松迅速地让一个自定义聊天机器人运行起来:只需提供三个示例和一个高层次的上下文,机器人就能够理解我们的期望,并在对话中正确返回信息。想象一下如果我们提供数百甚至数千个额外的示例——潜力巨大!

4 | 结论

在本文中,我们看到利用 Google Cloud 的PaLM 2 APIs是多么简单,使用了text-bisonchat-bison模型。我们了解到如何使用 Python 的[google-auth](https://pypi.org/project/google-auth/)库进行远程认证,以及如何使用[requests](https://pypi.org/project/requests/)库调用这些 APIs。最后,我们看到如何通过调整和玩转输入参数来定制这些 APIs。

希望这篇文章对你有帮助,并给你一些灵感和关于如何开始使用 PaLM 2 APIs 的想法! 🪴🤖

🔜🔜 在即将到来的第二部分中,我们将专注于使用 PaLM 2 APIs 进行提示工程,并探讨如何更好地优化输入提示和模型参数选择。

反馈或问题?请随时在评论区联系我! 💬

📚 想了解更多?查看 Google Cloud 上的生成 AI 或尝试 Google Cloud Skills Boost 上免费的 生成 AI 学习路径

参考文献

[1] Gartner, Gartner 专家回答您的企业生成 AI 顶级问题,访问日期:2023 年 8 月 13 日。

[2] CB Insights, 生成 AI 的现状:7 张图表,2023 年 8 月 2 日。

[3] Google Cloud, Vertex AI 上生成 AI 支持概览,访问日期:2023 年 8 月 13 日。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值