TaatikNet: 序列到序列学习用于希伯来文音译
一个简单的示例,展示了字符级别的 seq2seq 学习应用于复杂任务:在希伯来文文本和拉丁文音译之间的转换
·
关注 发表在 Towards Data Science ·10 分钟阅读·2023 年 6 月 28 日
–
我们如何利用深度学习在不被“困惑”的情况下进行字符串转换?(图片 by Andrew Malone, CC BY 2.0)
本文描述了 TaatikNet 以及如何轻松实现 seq2seq 模型。有关代码和文档,请参见 TaatikNet GitHub 仓库。要查看交互式演示,请参见 TaatikNet 在 HF Spaces 上。
介绍
许多自然语言处理中的有趣任务涉及在不同风格、语言或格式的文本之间转换:
-
机器翻译(例如,从英语到德语)
-
文本摘要 和释义(例如,将长文本缩短为短文本)
-
拼写纠正
-
抽象问题回答(输入:上下文和问题,输出:答案文本)
这些任务统称为序列到序列(Seq2seq)学习。在所有这些任务中,输入和期望的输出都是字符串,这些字符串可能具有不同的长度,并且通常彼此之间没有一一对应关系。
假设你有一个配对示例的数据集(例如,句子及其翻译的列表,拼写错误和修正文本的多个示例等)。如今,只要数据足够多,使得模型能够学习到对新输入的泛化,训练神经网络变得相当容易。让我们看看如何使用 PyTorch 和 Hugging Face transformers 库以最小的努力训练 seq2seq 模型。
我们将重点关注一个特别有趣的用例:学习在希伯来文本和拉丁音译之间转换。我们将在下文中概述这一任务,但这里提出的想法和代码对超出这一特定案例的应用也是有用的——本教程对任何希望从示例数据集中执行 seq2seq 学习的人都应该有帮助。
我们的任务:希伯来音译
为了展示具有趣味性和相当新颖的应用案例,我们将其应用于音译。一般来说,音译是指在不同书写系统之间转换。虽然英语使用拉丁字母书写(“ABC…”),但世界上的语言使用许多不同的书写系统,如下所示:
世界上的一些书写系统。(图片 by Nickshanks, CC-BY-SA-3)
如果我们想使用拉丁字母来书写一个原本用不同书写系统书写的语言中的单词怎么办?这一挑战通过许多书写犹太节日汉 ukkah 名称的方式得到体现。目前的介绍在维基百科文章中读取如下:
Hanukkah (/ˈhɑːnəkə/; 希伯来语: חֲנֻכָּה, 现代希伯来语: Ḥanukka, 提比留语: Ḥănukkā) 是一个犹太节日,纪念耶路撒冷的恢复以及第二圣殿的重新奉献,发生在公元前 2 世纪的马加比起义之初,对抗塞琉古帝国。
希伯来词汇חֲנֻכָּה的拉丁字母音译可以是Hanukkah、Chanukah、Chanukkah、Ḥanukka或许多其他变体。在希伯来语以及许多其他书写系统中,存在各种约定和模糊性,使得音译复杂,而不是简单的一对一字符映射。
在希伯来语的情况下,可以使用复杂的规则将带有 nikkud(元音符号)的文本音译成拉丁字符,尽管也存在各种边缘情况,使得这看似复杂。此外,尝试将没有元音符号的文本音译或执行反向映射(例如Chanukah → חֲנֻכָּה)要困难得多,因为可能的有效输出非常多。
幸运的是,借助于对现有数据应用深度学习,我们可以用极少的代码在解决这个问题上取得很大进展。让我们看看如何训练一个 seq2seq 模型——TaatikNet——使其能够自主学习如何在希伯来文文本和拉丁音译之间转换。我们注意到这是一个字符级任务,因为它涉及到对希伯来文本和音译中不同字符之间关系的推理。我们将进一步讨论这一点的重要性。
顺便提一下,你可能听说过我们的 UNIKUD 模型,它用于给无标记的希伯来文文本添加元音符号。这些任务之间有一些相似之处,但主要的区别在于 UNIKUD 执行的是字符级分类,即对每个字符,我们学习是否在其旁边插入一个或多个元音符号。相比之下,在我们的情况下,由于音译的复杂性,输入和输出文本的长度或顺序可能不完全对应,因此我们在这里使用 seq2seq 学习(而不仅仅是按字符分类)。
数据收集
与大多数机器学习任务一样,我们很幸运能够收集到大量模型输入和期望输出的例子,以便我们可以使用监督学习对其进行训练。
对于许多与单词和短语相关的任务,一个很好的资源是Wiktionary及其多语言对照——可以将其想象为维基百科与词典的结合。特别是,希伯来语 Wiktionary (ויקימילון)包含了结构化的语法信息条目,如下所示:
来自希伯来语 Wiktionary 文章עגבניה(西红柿)的语法信息。
特别是,这包括拉丁音译(agvaniya,其中粗体表示重音)。连同包含 nikkud(元音字符)的章节标题,这为我们提供了训练模型所需的(自由许可)数据。
为了创建数据集,我们使用 Wikimedia REST API 抓取这些条目(示例见此)。请注意,Wiktionary 条目的原始文本具有宽松的衍生作品许可(CC 和 GNU 许可,详情见此),并要求共享相同许可(TaatikNet 许可见此);通常情况下,如果你执行数据抓取,请确保使用具有宽松许可的数据,适当抓取,并使用正确的衍生作品许可。
我们对这些数据执行各种预处理步骤,包括:
-
去除 Wiki 标记和元数据
-
用尖音符号代替粗体表示重音(例如 agvaniya → agvaniyá)。
-
Unicode NFC 规范化 用于统一相同出现的字形,例如 בּ(U+05D1 希伯来字母 Bet + U+05BC 希伯来点 Dagesh 或 Mapiq)和 בּ(U+FB31 希伯来字母 Bet 带 Dagesh)。你可以通过将它们粘贴到Show Unicode Character 工具中自行比较。我们还统一了类似的标点符号,如希伯来语 geresh(׳)和撇号(‘)。
-
将多词表达拆分为单个词。
数据抓取和预处理后,我们得到近 15k 对单词-音译对(csv 文件见此)。以下是几个示例:
我们数据集中的几个项目示例。请注意,带有 nikkud(元音点)的希伯来语在第二列,但由于从右到左的文本渲染问题,它首先出现。
音译绝非一致或无误;例如,重音标记不一致且经常错误标记,且使用了各种拼写规则(例如 ח 可能对应于 h, kh, 或 ch)。我们不会尝试清理这些,而是将其直接输入模型,让模型自行理解。
训练
现在我们有了数据集,让我们进入项目的“核心”——在我们的数据上训练 seq2seq 模型。我们将最终模型命名为 TaatikNet,取自希伯来语单词 תעתיק taatik,意为“音译”。我们将在这里高层次地描述 TaatikNet 的训练,但强烈建议你阅读注释过的训练笔记本。训练代码本身非常简短且具有指导性。
要在自然语言处理(NLP)任务上实现最先进的结果,一种常见的方法是使用预训练的变换器神经网络,并通过继续在任务特定数据集上进行微调来应用迁移学习。对于 seq2seq 任务,最自然的基模型选择是一个编码器-解码器(enc-dec)模型。像 T5 和 BART 这样的常见 enc-dec 模型非常适合常见的 seq2seq 任务,如文本摘要,但由于它们对文本进行标记化(将其拆分为子词标记,大致是词或词块),因此不太适合我们的任务,因为我们需要在单个字符级别上进行推理。为此,我们使用无标记化的 ByT5 enc-dec 模型(论文,HF 模型页面),该模型在单个字节级别上进行计算(大致为字符,但请参阅Joel Spolsky 对 Unicode 和字符集的优秀文章以更好地理解 Unicode 字形如何映射到字节)。
我们首先创建一个 PyTorch Dataset 对象来封装我们的训练数据。我们可以简单地将数据集 CSV 文件中的数据包装起来而不做任何修改,但我们添加了一些随机增强,使模型的训练过程更加有趣:
def __getitem__(self, idx):
row = self.df.iloc[idx]
out = {}
if np.random.random() < 0.5:
out['input'] = row.word if np.random.random() < 0.2 else row.nikkud
out['target'] = row.transliteration
else:
out['input'] = randomly_remove_accent(row.transliteration, 0.5)
out['target'] = row.nikkud
return out
这种增强方法教会 TaatikNet 接受希伯来文字或拉丁文字作为输入,并计算相应的匹配输出。我们还会随机丢弃元音符号或重音,以训练模型对其缺失具有鲁棒性。一般来说,随机增强是一种很好的技巧,当你希望网络学会处理各种类型的输入,而不必事先计算数据集中所有可能的输入和输出时。
我们使用一行代码通过 Hugging Face pipeline API 加载基础模型:
pipe = pipeline("text2text-generation", model='google/byt5-small', device_map='auto')
在处理数据整合和设置超参数(如训练轮次、批量大小、学习率)后,我们在数据集上训练模型,并在每轮训练后打印出选定的结果。训练循环是标准的 PyTorch,除了 evaluate(…)
函数外,该函数在其他地方定义,并打印出模型在各种输入上的当前预测:
for i in trange(epochs):
pipe.model.train()
for B in tqdm(dl):
optimizer.zero_grad()
loss = pipe.model(**B).loss
losses.append(loss.item())
loss.backward()
optimizer.step()
evaluate(i + 1)
比较早期轮次和训练结束时的一些结果:
Epoch 0 before training: kokoro => okoroo-oroa-oroa-oroa-oroa-oroa-oroa-oroa-oroa-oroa-oroa-oroa-oroa-oroa-oroa-oroa-oroa-oroa-oroa-o
Epoch 0 before training: יִשְׂרָאֵל => אלאלאלאלאלאלאלאלאלאלאלאלאלאלאלאלאלאלאלאלאלאלאלאלא
Epoch 0 before training: ajiliti => ajabiliti siti siti siti siti siti siti siti siti siti siti siti siti siti siti siti siti siti sit
Epoch 1: kokoro => מְשִׁית
Epoch 1: יִשְׂרָאֵל => mará
Epoch 1: ajiliti => מְשִׁית
Epoch 2: kokoro => כּוֹקוֹרְבּוֹרוֹר
Epoch 2: יִשְׂרָאֵל => yishishál
Epoch 2: ajiliti => אַדִּיטִי
Epoch 5: kokoro => קוֹקוֹרוֹ
Epoch 5: יִשְׂרָאֵל => yisraél
Epoch 5: ajiliti => אֲגִילִיטִי
Epoch 10 after training: kokoro => קוֹקוֹרוֹ
Epoch 10 after training: יִשְׂרָאֵל => yisraél
Epoch 10 after training: ajiliti => אָגִ'ילִיטִי
在训练之前,模型输出的是无意义的字符,这在预期之中。在训练过程中,我们看到模型首先学会如何构造有效的希伯来语和音译,但花费更长时间来学习它们之间的联系。它也需要更长时间来学习诸如ג׳(gimel + geresh)对应于 j 的稀有项目。
一个警告:我们没有尝试优化训练过程;超参数的选择相当随意,也没有为严格评估预留验证集或测试集。此目的仅为提供一个 seq2seq 训练的简单示例和音译学习的概念验证;然而,超参数调优和严格评估将是未来工作的一个有前途的方向,结合下文限制部分提到的要点。
结果
下面显示了一些示例,演示了希伯来文本(有或没有元音)与拉丁音译之间的双向转换。你可以在HF Spaces 上的互动演示中尝试自己使用 TaatikNet。注意,它使用束搜索(5 束)进行解码,推理是对每个单词单独进行的。
TaatikNet 的输入和输出示例见互动演示。使用束搜索解码(5 束)生成多个输出。
更长文本的示例输出。推理是对每个单词单独进行的。注意挑战性案例如שבעיניו(最后的 yud 不发音)、חוכמה(kamatz gadol)、כאלה(倒数第二个音节重音)的成功音译。
限制与进一步方向
为了简化,我们将 TaatikNet 实现为一个最小的 seq2seq 模型,没有进行广泛的调优。然而,如果你对改进希伯来文文本与音译之间的转换结果感兴趣,有许多有前景的未来工作方向:
-
TaatikNet 仅尝试根据字母或声音对应关系猜测适当的拼写(无论是希伯来文还是拉丁音译)。然而,根据上下文,你可能希望将音译转换为有效的希伯来文本(例如 zot dugma → זאת דוגמא,而不是拼写错误的 זות דוגמע)。实现这一点的可能方法包括检索增强生成(访问词典)或在希伯来语句子及其拉丁音译的配对上进行训练,以学习上下文提示。
-
形式不寻常的输入可能会导致 TaatikNet 的解码陷入循环,例如 drapapap → דְּרַפָּפָּאפָּאפָּאפָּאפָּאפָּאפָּאפָּאפָּאפָּאפָּאפָּאפָּאפָּאפָּאפָּאפָּאפָּאפָּאפָּאפָּאפָּאפָּאפָּ. 这可能通过训练中的数据增强、更丰富的训练数据或在训练或解码中使用循环一致性来解决。
-
TaatikNet 可能无法处理其训练数据中一些相当稀有的惯例。例如,它常常无法正确处理ז׳(zayin+geresh),这表示稀有的外来音zh。这可能表明过拟合,或者在训练时使用样本权重以强调困难示例可能会有所帮助。
-
seq2seq 训练的便利性是以解释性和鲁棒性为代价的——我们可能希望确切了解 TaatikNet 如何做出决策,并确保这些决策的一致性。一个有趣的可能扩展是将其知识提炼成一组基于规则的条件(例如,如果在上下文 Y 中看到字符 X,则写 Z)。最近的代码预训练 LLM 可能对这个有所帮助。
-
我们没有处理“完整拼写”和“缺陷拼写”(כתיב מלא / חסר),即希伯来词在有无元音符号的情况下拼写略有不同。理想情况下,模型应在无元音的“完整”拼写和有元音的“缺陷”拼写上进行训练。请参阅 UNIKUD 了解处理这些拼写的一种方法。
如果你尝试这些或其他想法并发现它们带来了改进,我非常乐意听到你的反馈,并在此处给你致谢——可以通过本文下方的联系信息与我联系。
结论
我们已经看到,用监督学习训练一个 seq2seq 模型是相当简单的——教它从大量配对示例中进行归纳。在我们的案例中,我们使用了一个字符级模型(TaatikNet,从基础 ByT5 模型微调而来),但几乎可以使用相同的过程和代码来处理更标准的 seq2seq 任务,如机器翻译。
我希望你从本教程中学到的东西与我整理它时学到的一样多!如有任何问题、意见或建议,请随时与我联系;我的联系信息可以在下面链接的我的网站上找到。
莫里斯·阿尔珀,硕士 是特拉维夫大学的博士生,研究多模态学习(NLP、计算机视觉及其他模态)。有关更多信息和联系信息,请访问他的网页:morrisalp.github.io/
使用 Tableau 仪表盘处理大数据:挑战与经验
原文:
towardsdatascience.com/tableau-dashboards-and-big-data-learnings-e0a29cb7377c
像专业人士一样使用 Tableau 分析大数据
·发表于 Towards Data Science ·阅读时长 7 分钟·2023 年 1 月 5 日
–
图片由 Myriam Jessier 在 Unsplash 提供
我的谦逊仪表盘创建旅程始于 Excel。此后,我使用了多个工具,如 Qlik、Sisense、PowerBI 和 Tableau。尽管如此,Tableau 仍然是我最喜欢的工具,因为它从未变得枯燥。它易于使用和学习,但也可以迅速变得复杂。完成任务后获得的满足感是无价的。我有机会与许多 Tableau 专家合作,逐渐掌握了制作强大视觉效果的许多技巧和窍门。尽管我已经熟练使用这个工具,我认为我仅仅是触及了表面。
最近我面临的最大挑战之一是使用大数据构建仪表盘。我需要设计一个仪表盘来跟踪推送通知对移动应用用户的效果。推送通知发送的原因有很多,包括状态更新、新优惠、提醒、活动等。根据用户数量和发送的通知,这些数据可能会变得极其庞大。当我开始处理这个项目时,源表中有三个月的数据,总共有超过 5000 万条记录!
仪表盘创建过程的最佳实践。图像由作者使用 Powerpoint 创建。
在创建新仪表板之前,应从利益相关者/最终用户那里收集所有需求。理解仪表板的目的——它是为了什么,需要跟踪哪些指标,使用什么粒度级别,需要哪些过滤器等,这一点至关重要。如果可能的话,所有这些内容都应进行文档记录。这是为了避免收到多次变更请求和浪费时间开发最终不会被使用的内容。在项目进行期间,我与利益相关者进行了几次会议,以确保满足所有需求。我还涉及了工程团队,以确保所需数据在我们的数据仓库中随时可用。
下一步是创建工程框架——在 Tableau 的情况下,这将是一个适当的数据提取,仪表板可以连接到其中。什么是提取?它们只是原始数据的保存子集,可以定期刷新。提取的最大优势是性能提升。你减少了对主要数据源的总查询次数(仅在刷新时需要)。此外,你可以汇总或仅保留所需字段,并应用过滤器以减少提取的总大小。如果提取设计得当,可以作为多个工作簿的数据源,从而节省每次创建新数据集的时间。你可以在这里阅读 Tableau 提取的完整文档。
创建提取的方法有多种:
-
使用 Tableau Desktop 创建数据模型,然后将其发布到服务器作为提取——这种方法简单且适用于小型数据集。
-
使用 Tableau Desktop 创建数据模型,将其发布到服务器作为“实时”连接,然后在服务器上将其更改为提取——这种方法最适合中等大小的数据集,有助于节省在本地创建提取的时间。
这是我遇到的第一个障碍。我无法创建提取,因为数据量太大。我建立了与数据集的实时连接,看看是否可以在不创建提取的情况下继续工作。这一过程简直是一场噩梦。仪表板非常缓慢,每当我尝试更改视图中的内容时,加载时间要么需要 20 秒或更长时间,要么应用程序完全停止工作。我开始寻找其他选项,直到遇到了一篇有用的文章,展示了如何创建空提取并欺骗服务器刷新数据这里。
发布到 Tableau 后的成功消息。截图由作者拍摄。
我对成功创建提取感到非常兴奋。我根据规格构建了仪表板,并在经过彻底的 QA(质量保证)检查后,仪表板向所有人开放。然而,我的成功并未持续太久。几个月后,提取在服务器上未能刷新,连接自动从提取切换到实时。数据量已超过 2 亿条记录,任何尝试提取的方法,即便使用空提取技巧,也失败了。仪表板再次变得缓慢,我开始收到来自各个用户的提高性能的请求。
课程 1 — 临时修复不会持久
我知道唯一提高性能的方法是减少数据的大小并将其制作成提取。虽然在我们的数据仓库中创建数据集时,已经遵循了一些最佳实践。为了避免昂贵的联接,所有需要分析的属性(无论是用户还是推送通知)都被整合到一个大型表中(OBT)。普遍认为星型模式总是优于 OBT,因为“规范化”表需要更少的存储空间且更易于理解。然而,对于大数据分析报告,事实表和多个维度表之间的联接在检索数据时会对性能产生很大影响。有关星型模式和 OBT 之间权衡的详细解释,请参见这个博客 这里。
我能进行的任何操作仅限于我为仪表板创建的数据集。现在仪表板已经完成,我注意到有些指标仅针对用户,而其他指标仅针对推送通知。这开启了新的可能性:
-
我可以创建两个不同的数据集 — 一个用于用户,另一个用于推送通知
-
我还可以利用 CTE(公用表表达式)和窗口查询来添加额外的指标,以避免在 Tableau 中创建一些计算字段。
通过上述更改,新聚合数据集的合并大小仅为原始数据的 3%!剩下的就是用新的数据源替换仪表板中的旧数据源。
课程 2 — 在 Tableau 上始终使用提取
我遇到的第二个障碍是,虽然 Tableau 允许你替换数据源,但不能用多个数据源替换它。没有办法选择性地将数据源分配给特定的工作表。这意味着我必须用新的数据集之一从头开始重建至少一半的整个仪表板。我对重新开始感到犹豫,因为我已经实现了很多自定义计算、参数和格式化技巧。这是我最后的选择。我在网上寻找解决方案但没有找到。我认识的一位 Tableau 专家 — Kasia Gąsiewska-Holc— 建议了一个聪明的解决方法,即从另一个工作簿复制工作表。
以下是其工作原理:
-
复制你的原始工作簿(称之为 workbook1),并删除任何你不想替换数据源的工作表。
-
将 workbook1 中的数据源替换为新的数据源。
-
将 workbook1 的工作表复制并粘贴到原始工作簿中。(要复制工作表,请在底部功能区选择工作表名称,然后选择‘复制’。然后,通过右键单击功能区并选择粘贴,返回到原始工作簿。)
-
现在就是魔法时刻了:你将有两套工作表,一套来自 workbook1 具有正确的数据源,一套来自原始数据源但具有不正确的数据源。
-
剩下的就是交换工作表了。要交换工作表,进入仪表板并点击‘交换工作表’以确保你选择了正确的工作表。
交换后,删除原始工作簿中不再需要的工作表。
-
将原始工作簿的旧数据源替换为新的数据源。这将改变剩余工作表的数据源。
-
恭喜!你已成功将单一数据源工作簿替换为两个数据源工作簿。
整个过程花费了一个小时,而手动构建一半的仪表板可能要花费我整整一天的时间。
第三课 — 与 Tableau 专家交朋友
新版仪表板上线已有一段时间,目前没有报告任何错误或性能问题。所以我猜这里的工作已经完成了。有时候,你会期待一个非常复杂的解决方案,但实际上效果最好的解决方案往往是最简单的。希望你在这里找到了有用的东西。如果你也是 Tableau 用户,我很想知道你最近使用过的最佳技巧!
继续学习,不要犹豫寻求帮助。图片由 John Schnobrich 提供,来源于 Unsplash。
在你离开之前…
请在 Medium 上关注我,以免错过我未来撰写的任何新文章;你可以在我的 个人主页上找到更多我的文章。你也可以通过 LinkedIn 或 Twitter与我联系!
Tableau 数据融合教程——初学者的逐步指南
我们探索使用 Tableau 对数据融合进行全面概述,适用于数据科学家和数据分析师
·发布于 数据科学前沿 ·7 分钟阅读·2023 年 1 月 30 日
–
图片由 Lukas Blazek 提供,来源于 Unsplash
数据融合——动机
现在,公司使用来自不同来源的数据来解决业务问题。能够有效地收集和结合这些数据已成为所有数据科学家和数据工程师的基本技能,以帮助组织做出明智的决策。
在本教程中,我们将首先建立对一种强大的数据组合方法——数据融合的理解,然后探索其好处。接着,我们将探讨其一些缺点,最后解答一些关于使用 Tableau 进行数据融合的常见问题。
Tableau 中的数据融合与连接。
在现实生活中,你将处理来自多个来源的信息,例如 Excel 表格、SQL、CSV 等。作为数据科学家,你需要将这些信息互联,以生成全球业务洞察。
Tableau 可以通过两种不同的方法来解决这个问题:连接、融合和关系。
在本节中,我们将重点理解前两种方法之间的区别。
Tableau 中的连接是什么?
如果你之前使用过 SQL,可能对主要的连接概念有所了解:左连接、右连接、内连接、交叉连接和全外连接。使用 Tableau 时也是如此。
这些连接旨在基于这些表之间的一些逻辑列关系,结合来自相同来源的不同表。例如,尝试将 Excel 文件和 SQL 表结合起来会失败,因为它们不来自相同的来源。
此外,在连接表时,两个表中使用的列必须相同,改变这些数据类型会导致连接中断。
最后,无法从 Tableau 的连接中删除重复列。
Tableau 中的数据混合是什么?
与连接和关系不同,数据混合将来自多个来源(如数据库、商业智能系统、云系统、平面文件、网络服务等)的数据汇总为单一数据,以便更好地进行可视化。
为什么使用 Tableau 进行数据混合?
首先,什么是 Tableau?
Tableau 是一个无代码的商业智能工具,提供了一个直观的拖放界面用于分析和可视化。这一非技术性特点使其在行业中脱颖而出。
此外,它快速且提供了将来自多个来源的数据互连的能力,如电子表格、SQL 数据库、网络服务等,无论是来自云还是本地。
使用 Tableau 进行数据混合提供了相同的灵活性,并使得从多个来源合并数据变得更容易,无需编程技能。
数据混合在 Tableau 中的逐步指南。
为了更好地理解数据混合的概念,本节将通过逐步过程指导你如何在 Tableau 中进行数据混合。
- 了解用例
本案例分析了来自 Zoom.AI 的两个部门在 2020 年和 2021 年的收入,Zoom.AI 是一家在不同非洲首都(大城市)运营的 AI 公司,如下图所示。
部门 1 和部门 2 的收入数据(作者图片)
2. 了解数据列
我们注意到这两个数据的格式相同,并传达相同的信息。然而,前两列的名称不同(部门 1 为 Period、Capitals,部门 2 为 Year、Cities)。
尝试将连接应用于当前的数据格式将会失败,因为参与连接的列需要相同。我们将看到数据混合如何巧妙地结合这些数据,而无需事先进行列的标准化。
3. 创建数据连接
了解我们的数据存储在不同的文件中,我们需要在 Tableau 中创建一个空间,将它们重新分组,这可以通过在 Tableau 中创建数据连接来完成,如下所示:
将数据导入 Tableau(作者动画)
我们部门的数据出现在左上角的数据选项卡中,意味着它们已成功上传。
4. 开始数据混合
首先,我们从可视化第一个部门的 Capitals 收入的变化开始。这可以通过以下两个步骤完成:
-
将 Revenue 列拖放到 Tableau 的列部分。
-
将 Capitals 列拖放到 Tableau 的行部分。
2020 年收入的可视化(作者动画)
目标是使用数据融合来比较部门的收入。为此,我们需要对第二部门的数据执行相同的拖放操作,而该数据使用的是城市列,如下所示。
部门 2 的结果已用橙色标记以便于说明。
为部门 2 添加收入(作者动画)
可视化破裂了💥💥💥,为什么?!
原因在于我们没有向 Tableau 指明首都列的信息水平与城市列相同,这导致在可视化中出现了城市列的星号标记。
这时数据融合就派上用场了,通过指定城市和首都列表示相同的内容来解决这个问题。下面是示例图。
数据的正确融合(作者动画)
在解决问题后,我们可以看到左侧城市列上有一个橙色链条⛓ 标记。这意味着城市列被用作连接字段。
更多的数据融合
现在你理解了如何正确地融合数据,让我们在年份/期间级别上进行相同的分析。为此,我们只需在期间和年份列之间创建一个链接,否则,我们将面临与之前相同的问题。
数据的正确融合(作者动画)
恭喜你达到了这个层级!现在你知道如何进行数据融合,你可以通过这个课程学习如何使用 Tableau 创建高级可视化。
数据融合在 Tableau 中有哪些好处?
从之前的教程中可以观察到,与 Joins 相比,使用数据融合提供了许多好处。下面列出了一些:
- 数据列无需预处理
我们不需要对列进行任何昂贵的预处理就能将不同的数据结合起来,因为只需简单指定感兴趣的列,数据融合算法就能理解如何高效地结合数据。
2. 解决粒度问题的更好方法
数据融合在结合不同粒度级别的数据时提供了更好的灵活性。假设我们的部门收入数据是按月组织的,而不是按年组织的。
使用简单的联接会导致不准确的结果,因为每年的行将被复制到每个月的行中,如下所示。数据融合可以通过将月份信息汇总到年度水平来解决这个问题。
不同粒度级别的数据融合(作者图片)
团队生产力
让我们考虑之前的粒度情况。如果没有数据混合,我们将不得不执行一些数据预处理,如汇总和重复数据删除。处理庞大的数据集时,这种预处理可能会迅速变得耗时。
快速分析以更好地决策
精确的决策制定依赖于对数据的更好概述。只需几次点击和拖放,就能捕捉到两个部门的本质。使用联接可能会导致不准确的结果,从而导致不准确的决策制定。
Tableau 数据混合的限制。
尽管数据混合有其优点,但也有一些缺点,如下所示:
-
数据混合在后台使用左连接,它不执行其他类型的连接。
-
在尝试混合不同粒度的数据时,顺序很重要。次要数据始终必须具有最小的粒度,因为它是需要聚合的。
-
非加性汇总,如 COUNT、MEAN、MEDIAN 和 SUM,会受到数据混合的影响。
结论
本教程涵盖了使用数据混合的动机、与连接相比对数据科学家的某些好处,以及实践操作,以更好地理解其工作原理。
希望你觉得这次基准分析对做出明智选择有帮助!
如果你喜欢阅读我的故事并希望支持我的写作,可以考虑 成为 Medium 会员。每月$5 的承诺,您将解锁对 Medium 上故事的无限访问权限。
随时欢迎在 Medium、Twitter 和 YouTube 上关注我,或者在 LinkedIn 上打招呼。讨论 AI、ML、数据科学、NLP 和 MLOps 相关话题总是一件愉快的事!
什么是禁忌搜索?
原文:
towardsdatascience.com/tabu-search-simply-explained-ee2852339d78
禁忌搜索优化算法的直观解释及其在旅行商问题中的应用
·发表于Towards Data Science ·5 分钟阅读·2023 年 3 月 13 日
–
图片由Clint Adair提供,来源于Unsplash
背景
在我的上一篇文章中,我们讨论了元启发式优化算法模拟退火。 这是一种随机搜索算法,用于尝试在组合优化问题中找到全局最优解,如著名的旅行商问题 (TSP)和背包问题。
另一种类似的算法称为禁忌搜索, 它可以被视为模拟退火算法的推广。在这篇文章中,我想讨论和解释禁忌搜索,回顾旅行商问题(TSP),然后在 Python 中实现禁忌搜索来解决 TSP。
禁忌搜索
概述
Tabu Search 是一种元启发式优化算法,由 Fred Glover 在 1980 年代末期构思。类似于模拟退火,Tabu Search 使用 局部搜索,但可以接受更差的解以避免陷入 局部最小值。它的另一个主要关键成分是它使用 记忆结构 防止算法访问之前观察过的解,从而更广泛地探索搜索空间。换句话说,它有一个‘TABU’列表!
Tabu Search 算法可以用来解决各种各样的问题:
因此,学习和理解它是值得的,因为它可以应用于多种情况。
记忆结构、任期和 Tabu List
如上所述,Tabu Search 记录之前访问过的解,这被称为 Tabu List,并在特定时间内将它们保存在记忆中,任期,以防止解的回收并更好地 探索 搜索空间。
一般来说,Tabu Search 使用两种类型的 记忆结构:
-
短期: 这通常是一定数量的之前访问过的解,我们不应回到这些解上。
-
长期: 这是为了在搜索遇到困境时提供帮助,并帮助扩展搜索范围。
实际上,没有要求一定要有一个或两个,甚至两个都不需要。主要的思想是我们跟踪算法正在做什么,并帮助其探索更广泛的可能解。
算法概述与愿望准则
Tabu Search 的一般流程如下:
-
生成一个初始有效解。
-
使用从当前解出发的局部搜索获取可能的邻域解集。
-
从这些邻域解中,获取一个不在 Tabu List 上的最佳候选解。
-
将这个最佳候选解与迄今为止找到的最佳解进行比较,并根据需要进行分配。
-
使用最佳候选解更新 tabu 列表。
-
使用最佳候选解重复步骤 2-5 以生成新的邻域,直到满足某些停止条件。
另一个规则是,如果我们发现一个在 Tabu List 上的解但其目标函数比当前最佳解更好,我们仍然接受这个解。这被称为 愿望准则。
就这样!如果你对这个过程还有疑问,请继续阅读,我们将用 Python 实现这个理论以使其更为具体。
旅行推销员问题
在使用 Tabu Search 解决旅行推销员问题(TSP)之前,值得快速讨论一下什么是 TSP。
TSP 可能是最著名且最易于理解的组合优化问题。问题很简单:“给定一组城市,什么是访问每个城市一次并返回原始城市的最短路线?”
这个问题难以解决的原因是它是NP 难的,随着我们需要访问的城市数量增加,可能路线的数量会组合爆炸。例如,对 20 个城市进行穷举所有解需要约 2000 年!
可能路线的数量按**(n-1)!/2** 计算
由于 TSP 在特定数量城市下的难解性,我们需要 resort to heuristics such as Tabu Search and Simulated Annealing to provide sufficient solutions in a reasonable amount of time.
用 Python 实现 TSP 的禁忌搜索
算法设计
首先列出一些伪代码,说明我们如何实现 TSP 的禁忌搜索:
-
生成一个初始路线并用这个初始路线更新禁忌列表
-
从这个初始路线中,通过交换当前路线中的相邻城市来生成邻域
-
从这个邻域中获取最短的最佳邻域路线,该路线不在禁忌列表上
-
将最佳邻域路线与找到的最佳总体路线进行比较,并根据需要更新
-
使用当前最佳邻域路线重复步骤 1–3,以产生新的邻域
这是一个相当基础的禁忌搜索算法,因为它仅包含短期记忆结构。
Python 代码
以下是实现上述算法的通用类。该类只需要一个initial_solution
,即城市的某个顺序列表,以及一个将城市映射到其坐标的字典cities
。
作者的 Github Gist。
现在让我们对一些合成生成的数据集运行这个类:
由作者在 Python 中生成的图。
由作者在 Python 中生成的图。
最佳解决方案看起来是一个相当合理的结果,而且没有花费我们数千年的时间来计算!
总结与进一步思考
在这篇文章中,我们解释了元启发式禁忌搜索算法。这个优化算法使用局部搜索技术,但仍可以通过接受更差的解决方案来逃避局部最小值。它还利用了禁忌列表,阻止它过渡到之前访问过的解决方案,并更大程度地探索搜索空间。应用于旅行推销员问题时,这个算法取得了很好的结果。
完整代码可以在我的 GitHub 上找到:
## Medium-Articles/Optimisation/tabu-search at main · egorhowell/Medium-Articles
目前无法执行该操作。您已在另一个标签页或窗口中登录。您在另一个标签页或…
另一个事项!
我有一个免费的新闻通讯,Dishing the Data,每周分享成为更好的数据科学家的技巧。没有“废话”或“点击诱饵”,只有来自实践数据科学家的纯粹可操作见解。
## Dishing The Data | Egor Howell | Substack
如何成为更好的数据科学家。点击阅读《Dishing The Data》,由 Egor Howell 编写,是 Substack 出版物,包含…
连接与我!
参考文献与进一步阅读
- 优化算法。 Mykel J. Kochenderfer 和 Tim A. Wheeler。2019。
Tabyl:现代 R 用户的频率表格
旧的已过时,新的正在兴起!
·
关注 发表在 向数据科学迈进 ·6 分钟阅读·2023 年 5 月 20 日
–
使用 Canva 图像生成器创建的图像
任何处理分类数据的人最终都会遇到计算某个类别的绝对数和比例的需要。本文介绍了通过一系列实际示例使用 tabyl
函数创建频率表格。
tabyl
为表格带来了什么(没有刻意捣乱的意思 😄)?
tabyl
函数是 R 语言中 janitor
包的一个特性。它是创建列联表的非常方便的工具,也被称为频率表或交叉制表表格。以下是使用 tabyl
的一些好处:
1. 简单的语法:tabyl
具有易于使用的语法。它可以接受一个、两个或三个变量,并自动返回一个包含计数和比例的数据框。
2. 灵活性:tabyl
可以生成单向(单变量)、双向(双变量)和三向(三变量)列联表。这种灵活性使其适用于各种应用场景。
3. 自动计算比例:tabyl
自动计算单向列联表的比例(百分比)。对于双向和三向表,可以结合使用同一包中的 adorn_percentages
函数来实现相同的结果。
4. 与 dplyr
的兼容性:tabyl
的输出是数据框(或 tibble),这使其完全兼容 dplyr
函数和 tidyverse 生态系统。这意味着你可以轻松地将 %>%
管道操作符应用于进一步的数据处理或可视化功能。
5. 整洁且信息丰富的输出:tabyl
提供整洁且信息丰富的输出,包括将变量名作为行名和列名,这使得结果更易于解释。
基于以上所有原因,当你想在 R 中创建频率表时,tabyl
是一个很好的选择。它简化了许多步骤,并且与 tidyverse 数据分析方法很好地集成。
数据集
本文将使用关于不同类型蘑菇的气味的可食性数据来演示 tabyl
函数的优点。在这里,我将使用一个名为 mushrooms 的整理数据集,但你可以访问 Kaggle 上的原始数据。以下是用于清理数据的代码。
library(tidyverse)
library(janitor)
mushrooms <- read_csv("mushrooms.csv") %>%
select(class, odor) %>%
mutate(
class = case_when(
class == "p" ~ "poisonous",
class == "e" ~ "edible"
),
odor = case_when(
odor == "a" ~ "almond",
odor == "l" ~ "anise",
odor == "c" ~ "creosote",
odor == "y" ~ "fishy",
odor == "f" ~ "foul",
odor == "m" ~ "musty",
odor == "n" ~ "none",
odor == "p" ~ "pungent",
odor == "s" ~ "spicy"
)
)
如果你对上述语法不熟悉,请查看我早期文章中的 tidyverse 实用指南。
[towardsdatascience.com
旧的
为了更好地理解 tabyl
提供了哪些优势,让我们首先使用基础 R 中的 table
函数创建一个频率表。
table(mushrooms$class)
edible poisonous
4208 3916
table(mushrooms$odor, mushrooms$class)
edible poisonous
almond 400 0
anise 400 0
creosote 0 192
fishy 0 576
foul 0 2160
musty 0 36
none 3408 120
pungent 0 256
spicy 0 576
毫不奇怪,气味竟然是预测蘑菇可食性的一个重要指标,任何“有怪味”的蘑菇可能都是有毒的。谢谢进化!此外,似乎还有很多更多的有毒蘑菇,因此在自己采摘蘑菇时始终要小心谨慎。
如果我们希望直接使用变量名而不指定$
运算符,我们需要使用with
命令使数据集对table
函数可用。
mush_table <- with(mushrooms, table(odor, class))
不幸的是,如果我们想升级到比例而不是绝对数,我们不能使用相同的函数,而是要使用另一个函数——prop.table
。
prop.table(mush_table)
class
odor edible poisonous
almond 0.049236829 0.000000000
anise 0.049236829 0.000000000
creosote 0.000000000 0.023633678
fishy 0.000000000 0.070901034
foul 0.000000000 0.265878877
musty 0.000000000 0.004431315
none 0.419497784 0.014771049
pungent 0.000000000 0.031511571
spicy 0.000000000 0.070901034
默认情况下,这会给我们一个按列的比例表。如果我们想要按行的比例,我们可以指定margin
参数(1 表示按行,2 表示按列)。
prop.table(mush_table, margin = 1)
class
odor edible poisonous
almond 1.00000000 0.00000000
anise 1.00000000 0.00000000
creosote 0.00000000 1.00000000
fishy 0.00000000 1.00000000
foul 0.00000000 1.00000000
musty 0.00000000 1.00000000
none 0.96598639 0.03401361
pungent 0.00000000 1.00000000
spicy 0.00000000 1.00000000
所有这些特殊函数可能会感觉繁琐且难以记住,因此拥有一个包含所有上述功能的单一函数将是很好的。
此外,如果我们使用class(mush_table)
命令检查创建的对象类型,我们会发现它属于table
类。
这创建了一个兼容性问题,因为如今 R 用户大多使用 tidyverse 生态系统,该系统以将函数应用于data.frame
类型对象并通过管道(%>%
)运算符串联结果为中心。
新的
让我们用tabyl
函数做同样的事情。
tabyl(mushrooms, class)
class n percent
edible 4208 0.5179714
poisonous 3916 0.4820286
mush_tabyl <- tabyl(mushrooms, odor, class)
mush_tabyl
odor edible poisonous
almond 400 0
anise 400 0
creosote 0 192
fishy 0 576
foul 0 2160
musty 0 36
none 3408 120
pungent 0 256
spicy 0 576
与相应的table
输出相比,使用tabyl
函数生成的表格更整洁,变量名(类别)被明确指出。此外,对于一维表格,除了数字,百分比也会自动生成。
我们还可以注意到,我们不需要使用 which 函数就可以直接指定变量名。此外,运行class(mush_tabyl)
告诉我们生成的对象是data.frame
类,这确保了与 tidyverse 的兼容性!
装饰过的 janitor
使用 Canva 图像生成器创建的图像
为了额外的tabyl
功能,janitor
包还包含了一系列adorn
函数。要获取百分比,我们只需将生成的频率表传递给adorn_percentages
函数。
mush_tabyl %>% adorn_percentages()
odor edible poisonous
almond 1.0000000 0.00000000
anise 1.0000000 0.00000000
creosote 0.0000000 1.00000000
fishy 0.0000000 1.00000000
foul 0.0000000 1.00000000
musty 0.0000000 1.00000000
none 0.9659864 0.03401361
pungent 0.0000000 1.00000000
spicy 0.0000000 1.00000000
如果我们想要按列的百分比,我们可以将denominator
参数指定为“col”。
mush_tabyl %>% adorn_percentages(denominator = "col")
odor edible poisonous
almond 0.09505703 0.000000000
anise 0.09505703 0.000000000
creosote 0.00000000 0.049029622
fishy 0.00000000 0.147088866
foul 0.00000000 0.551583248
musty 0.00000000 0.009193054
none 0.80988593 0.030643514
pungent 0.00000000 0.065372829
spicy 0.00000000 0.147088866
tabyl
— adorn
组合甚至使我们能够轻松地将数量和百分比结合在同一表格单元格中…
mush_tabyl %>% adorn_percentages %>% adorn_ns
odor edible poisonous
almond 1.0000000 (400) 0.00000000 (0)
anise 1.0000000 (400) 0.00000000 (0)
creosote 0.0000000 (0) 1.00000000 (192)
fishy 0.0000000 (0) 1.00000000 (576)
foul 0.0000000 (0) 1.00000000 (2160)
musty 0.0000000 (0) 1.00000000 (36)
none 0.9659864 (3408) 0.03401361 (120)
pungent 0.0000000 (0) 1.00000000 (256)
spicy 0.0000000 (0) 1.00000000 (576)
… 或将总计添加到行和列。
mush_tabyl %>% adorn_totals(c("row", "col"))
odor edible poisonous Total
almond 400 0 400
anise 400 0 400
creosote 0 192 192
fishy 0 576 576
foul 0 2160 2160
musty 0 36 36
none 3408 120 3528
pungent 0 256 256
spicy 0 576 576
Total 4208 3916 8124
结论
R 中janitor
包的tabyl()
函数提供了一个用户友好且灵活的解决方案,用于创建一维、二维或三维列联表。它在自动计算比例和生成整洁的数据框方面表现出色,能够与 tidyverse 生态系统,特别是dplyr
,无缝集成。它的输出结构良好且易于解释,并且可以通过 adorn 函数进一步增强,从而简化生成信息频率表的整体过程。这使得tabyl()
在 R 的数据分析中成为一个非常有用的工具。
处理集中数据管理中的敏感性问题
战斗中的经验教训
·
关注 发表在 Towards Data Science ·8 分钟阅读·2023 年 7 月 24 日
–
图片由 Jehyun Sung 提供,通过 Unsplash 获取。
大多数规模和年龄相当的组织如今已经启动了提升数据处理和管理方式的举措。任何结构性提升数据管理能力的尝试都将需要一定程度的集中化,即便只是为了发现组织内的现状实践。一个普遍的趋势是任命首席数据官,一项调查发现 超过 80%的财富 1000 强组织现在都报告说已经设立了首席数据官。
任何变革都可能引发反应,尤其是那些定义新责任、改变权威并需要资金的组织变革可能会敏感,因此处理起来可能棘手。我花了十多年时间陪伴新兴的首席数据官走过他们的旅程。我有许多经验教训可以分享。接下来的文章中,我们将回顾启动中央数据团队时的典型挑战以及应对这些风险的实际措施。
启动中央数据团队及相关敏感问题
创建一个初步的中央团队并集中责任可以通过多种方式完成。这可能包括启动首席数据办公室、成立数据(治理)委员会、改进中央驱动的政策和标准,以及提供中央资源以执行特定的数据治理流程。
随着中央数据团队获得权威,其他团队必须让出这部分权力——这可能带来敏感问题。以下是一些最常见的挑战:
-
资源争夺战。中央团队需要人员和预算来运作。有时,这可能意味着从其他团队的预算或人员中挪用资源,这可能引发这些团队领导的反应。
-
控制权丧失。曾经对某些任务有自由支配权的团队可能不喜欢中央团队接管这些任务,或对如何执行这些任务提供标准。
-
缺乏地方相关性。如果中央团队与地方(或业务特定)的需求、操作和细节过于脱节,他们可能做出不能产生预期业务影响的决策,并且地方专长可能会丧失。
-
成为瓶颈。如果中央团队的人员配置和管理不当,可能会成为组织中的瓶颈或摩擦点,从而成为挫败感和怨恨的源头。
-
成为倾卸点。中央团队可能成为一个倾卸点,接手其他人不愿意承担的任务和责任,而这些任务和责任只产生有限的价值。
-
对变革的普遍抵触。团队和个人可能会对变革产生抵触,尤其是当影响未知或理解不充分时,且如果他们觉得自己无法达到新的期望。
让我们回顾一些与这些挑战相关的真实案例,我曾亲身目睹。在第一个案例中,该组织是一家全球前 100 的保险公司,拥有超过 5 万名员工,策略非常激进。新任首席数据官有“完成任务”的历史,这也是他被任命的部分原因。他的计划是定义一系列被归类为“数据治理活动”的活动。然后,手握描述的他,识别出整个组织中已经执行这些活动的人,最初是以评估当前状态的名义进行的。在最终被识别出的人中,有时数据治理占据了他们整个工作的内容,有时只是其中的一小部分。例如,有人可能在市场营销流程中从事数据质量工作。
一旦完成了对这些人员的分析,提出了将这些人员的大部分转移到中央团队的建议。当然,这导致了业务和职能团队的即时反抗,这些人员原本就位于这些团队中。他们曾通过参与成熟度评估展现了善意,却看到他们的团队成员,往往是各自操作中至关重要的部分,被重新分配。新的首席数据官很快发现自己陷入了敌对的局面,并且在第一年剩下的时间里几乎没有取得任何成果。
另一个案例来自一家全球银行,其中全球首席数据与分析官(“CDAO”)启动了一个转型项目,以创建一个经过整理的数据湖。CDAO 担心创建一个数据沼泽,因此她坚持严格的认证过程。该项目的承诺很强 — 团队可以提交请求,将数据上传到数据湖中,由 CDAO 领导的中央团队负责数据的摄取、标记和质量控制,以及访问权限的提供,使得业务和职能团队可以专注于数据分析和建立分析模型。然而,需求很快超过了容量,数据进入数据湖的平均处理时间超过了 1 个月,业务团队也因此变得沮丧,因为中央数据团队成了瓶颈。尽管有良好的意图,但需要进行一次重大重置(在情况如上所述恶化时,我的团队帮助分析了可以自动化数据治理过程的工具)。
上述例子来源于我的个人经验,但对于那些感兴趣的人,《数据驱动企业与 DataOps》由 Ashish Thusoo 和 Joydeep Sen Sarma 编写,提供了一些出色的阅读材料和附加案例研究。
减轻策略
图片由作者提供。
组织可以采取各种措施来管理与集中数据管理相关的敏感问题。以下是我个人的一些偏爱方法:
-
关注自动化。通过采用自动化优先的思维方式,可以减少手动工作和成本,从而缩减对大团队的需求。设计中的数据治理,将治理原则嵌入数据系统设计中,可以促进一致性和效率。
-
沟通和透明度。关于集中化的原因和预期结果的清晰及时沟通可以培养信任,并鼓励利益相关者的支持。
-
指导和培训。任何新的或更新的流程或政策都应配备适用的教育材料和社交化流程,以明确其实施方式。
-
提供反馈和影响的途径。数据委员会或治理论坛可以确保利益相关者不仅仅是数据治理指南的接受者,而是旅程中积极且受重视的合作伙伴。
-
主动应对棘手的利益相关者。识别可能有特定关注点或异议的利益相关者,并主动应对,尽可能包括一对一的会议,并明确管理各自的需求和要求。
-
从小处开始,取得初步胜利。从一个理解明确、涉及相对“友好”人员且有明确业务案例的范围开始。这可以产生初步的动力,为以后处理更复杂的问题奠定基础。
-
赋权于本地团队和管理者。智能数据治理不是将所有工作集中化,而是使现有角色和人员能够以一致的方式更好地履行职责。跨功能和跨区域的团队可能是一个选择。
-
仅在需要时集中化。确保标准化或集中化数据治理的努力基于积极的业务案例。在不确定时避免集中化。
让我们回顾一下我个人观察的一些额外案例。首先,为了避免资源上的激烈争夺,一家大型区域零售商采用了有针对性的、基于用例的方法,分析了基于约 25 个数据角色的资源需求和缺口。这些角色包括数据所有者、数据管理员、数据建模师、数据科学家、数据工程师、系统所有者、流程所有者、领域数据管理员、数据架构师等。下一步是与业务和职能团队讨论这些角色,识别他们已经拥有的角色和面临的挑战,例如在拥有正确的专业知识和技术方面。当识别出共同的痛点和机会领域,中央团队能够有效地提升业务和职能团队时,这会得到立即欢迎。完成业务案例以获得初步的、尽管规模较小的团队的资金是快速而简单的。
与我曾合作过的另一位首席数据官一起,我们在她推出新的数据治理操作模型的同时,开展了数据素养和文化推广活动。新的操作模型引入了许多员工不熟悉的新术语和责任,我们认为这可能会引起混淆和焦虑。除了其他举措外,我们还组织了一场“问我任何问题”的会议,组织中的任何人——总计超过 25,000 名员工——都可以匿名提交问题,问题会被实时回答。除了许多实际问题外,还提出了很多敏感问题,比如“这些新责任对我的薪酬有何影响?”,“这是三年来的第 3 个新操作模型——我们真的需要另一个吗?”,以及“我的团队领导认为这是胡说八道——我该怎么办?”随后匿名收集的反馈和轶事评论表明,这种透明的方法缓解了个人的担忧,并鼓励了那些受到重新定义的责任影响的员工的认可。
最后的一个例子,也许是我最喜欢的案例研究,是经过改造的首席数据办公室采纳了自动化优先的思维模式。为新实施的云原生数据平台创建了一个参考架构,其中包括几个基础设施:数据产品方法、严格的互操作标准和数据管理中心。这意味着任何转移到平台上的内容从定义上都是自动管理的。即,只有符合数据产品标准的内容才被允许存储在平台上,从而确保了(产品和数据)所有权的定义。互操作标准、平台内部的共同存储模式以及数据管理中心(包括数据目录)的结合实现了几乎完全自动化的元数据管理。尽管这需要大量的前期投资来打好基础,但避免了中央数据平台团队需要大量分析师和工程师来操作平台及其数据产品的情况。
展望未来
集中管理数据并非一项简单的任务;它充满了复杂性和敏感性。然而,通过有效的沟通、利益相关者参与、重点培训和经过深思熟虑的方法,仅在有明确业务案例的情况下进行集中,这些挑战可以得到有效管理。如果你有任何见解或经验要分享,请在评论中告诉我们。
参考文献
-
首席数据官的三个被低估的成功因素,Medium。
-
首席数据官创造并展示价值的 8 种策略,HBR。
-
三次首席数据官的五个教训,Data World。
-
创建以数据驱动的企业与 DataOps,Ashish Thusoo 和 Joydeep Sen Sarma。
应对变化世界中的问题
·
关注 发表在 Towards Data Science · 以 新闻通讯 发送 · 3 分钟阅读 · 2023 年 3 月 30 日
–
如果你觉得过去几年特别忙碌和紧张,你并不孤单。我们怀疑人类历史上任何时期都可以被描述为平静,但全球危机、技术进步和媒体传播的交汇使得我们当前的时刻具有非常独特的—有时甚至是压倒性的—特质。一切!无处不在!一齐发生!
我们希望为许多数据从业者提供一个建设性的出口,让他们思考解决方案和务实的方法来应对我们全球社区面临的(众多)问题,因此 我们最近汇编了一系列 30 篇优秀文章,这些文章涉及人口分析、可持续农业和城市规划等主题。我们还包括了一些公共数据集,以便您可以直接参与并开始探索。
本周,我们重点介绍了您可以在 “我们的全球村庄变迁” 中找到的一些贡献,这是一项我们本月早些时候分享的特别特辑。我们希望您能探索我们其他的一些推荐,并希望您阅读后能受到启发,进一步了解更多内容,并可能参与有意义的项目。祝您阅读愉快!
-
在人的尺度上讲故事。当我们谈论全球性问题如人口增长或气候变化时,很容易忽视那些将要参与(并受这些讨论影响)的实际人群。Emily A. Halford 对艺术家 Norwood Viviano 作品的概述很好地将数据、可视化叙事与复杂信息的传达连接起来。
-
计算机视觉与野生动物的结合。设计得当,新兴技术具有巨大的潜力,可以帮助人类在其环境中更可持续地生活。Abhay Kashyap 提供了一个引人注目的案例研究:一个利用 AI 系统支持致力于保护加州野猫的非营利组织的项目。
Kyle Winkle 拍摄的照片,来源于 Unsplash。
-
评估关键行业对环境的影响。由于研究人员可以获取大量公开数据,挑战通常在于找到合适的数据集并为项目定义合理的范围。Aine Fairbrother-Browne 提供了一个很好的例子,展示了如何同时完成这两项工作,通过对英国航空公司数据的研究,突显了航空行业对环境的影响以及改进的最大潜力领域。
-
如何推动交通规划向前发展。如果你对地理空间数据、城市规划或图论感兴趣,不要错过苏坦·穆夫提的实践入门,其中向我们介绍了运输规划者网络分析这一迷人的主题。(苏坦使用的 Python 工具你可能已经熟悉,所以学习曲线可能比你想象的要平缓!)
在我们让你去探索这些重要主题之前,我们想为希望本周探索其他主题的你提供一些额外的阅读推荐:
-
针对在生产中监控 NLP 模型的实践方法,不要错过埃琳娜·萨穆伊洛娃的最新教程。
-
什么是模拟退火,为什么你需要关心它?跟随亨妮·德·哈德的介绍,了解这一强大的优化技术。
-
管理数据团队面临独特的挑战;瑞贝卡·维克里提出了在你的组织中实施最佳实践的六种方法。
-
在他的首篇 TDS 文章中,迪奥戈·莱塔奥探讨了一个对机器学习从业者至关重要的问题:在使用梯度提升树时,何时使用提前停止。
-
来自图形机器学习前沿的迈克尔·加尔金及其合著者任洪宇、迈克尔·科赫兹和朱兆诚展示他们最新的神经图数据库研究。
感谢你本周的时间和支持!如果你喜欢我们发布的内容(并想访问所有内容),考虑成为 Medium 会员。
直到下次可变性,
TDS 编辑们
Taipy:构建用户友好的生产就绪数据科学应用程序的工具
一种简单、快速且高效的方式来构建全栈数据应用程序
·发布在 Towards Data Science ·14 分钟阅读·2023 年 7 月 6 日
–
图片由 Campaign Creators 提供,来源于 Unsplash
介绍
作为数据科学家,你可能希望创建数据可视化的仪表板,展示数据,甚至实现商业应用来协助利益相关者做出可操作的决策。
多种工具和技术可以用于执行这些任务,无论是开源还是专有软件。然而,这些可能由于以下原因而不理想:
-
一些开源技术需要陡峭的学习曲线和聘请具备相应专长的人员。因此,组织可能面临新员工的入职时间增加、培训成本更高以及寻找合格候选人的潜在挑战。
-
其他开源解决方案非常适合原型设计,但无法扩展到生产就绪的应用程序。
-
同样,专有工具也带来了自己的挑战,包括更高的许可费用、有限的自定义和企业难以切换到其他解决方案。
如果有一个不仅是开源的,而且易于学习并能够扩展为完整应用程序的工具,那该多好啊?
这就是 Taipy 发挥作用的地方🎉
本文将解释 Taipy 是什么,并展示它可以解决的一些商业案例,然后再深入探讨其关键特性。此外,它还将说明创建完整 Web 应用程序的所有步骤。
Taipy 是什么,为什么你应该关心它?
这是一个开源的、100% Python 库,只需要基本的 Python 编程知识即可使用。它允许数据科学家、机器学习工程师以及任何其他 Python 程序员迅速将他们的数据和机器学习模型转化为功能齐全的 Web 应用程序。
在当今迅速变化的环境中,对强大、灵活且高效工具的需求变得至关重要,以下是一些使 Taipy 成为独特平台的特性:
-
它不仅仅为试点项目设计,还可以扩展到工业化项目。
-
Taipy 的简单性与强大的功能相结合,使得具有最低编程背景的 Python 开发者可以在短时间内构建强大的解决方案。
-
高度的可定制性使用户能够快速修改和调整 Taipy 的功能以满足他们的需求,这提供了许多开源工具无法提供的个性化体验。
-
Taipy 提供的同步和异步调用允许同时执行多个任务,从而提高了整体性能。
-
Taipy 应用程序可以通过 Python 脚本或 Jupyter Notebooks 开发。
-
借助 Taipy 的管道版本控制功能,用户可以有效地管理不同的项目版本。
Taipy studio 扩展可以安装到 Visual Studio Code 中,从而显著加快 Taipy 应用程序的开发速度。
Taipy 的关键特性
尽管 Taipy 对于前端或后端开发非常出色,但当涉及到开发具有前端和后端组件的完整 Web 应用程序时,其真正的潜力才会显现。
让我们仔细看看它们的主要功能:
Taipy 前端功能
-
创建用户界面只需具备基本的 Python 编程知识。
-
Taipy 旨在用户友好,使用户界面的创建简单直观。
-
不需要网页设计知识,消除了所有 CSS 和 HTML 的先决条件。
-
它利用增强的 Markdown 语法来帮助用户创建他们想要的网页。
Taipy 后端功能
-
Taipy 支持创建强大的管道以处理不同的场景。
-
它使得有向无环图(DAGs)的建模变得简单明了。
-
数据缓存功能提升了 Taipy 应用程序的整体性能。
-
管道执行的注册。
-
管道版本控制。
-
用户可以通过 Taipy 的 KPI 追踪工具跟踪和评估他们应用程序的性能。
-
内置的管道和相关数据的可视化。
开始使用 Taipy
现在你对 Taipy 有了更好的了解,让我们深入探讨一个端到端的实现。
核心Taipy 文档和社区贡献包含相关信息,本文绝不会取代它们,但可以作为了解 Taipy 在实际场景中的一种替代起点。
为了更好地说明我们的案例,我们将使用健康相关数据泄露,这些数据由美国卫生与公众服务部民权办公室维护。它提供了关于 500 多名个人的未加密受保护健康信息泄露的报告信息。
本节将分为两个部分:
-
使用 Taipy 构建一个图形界面,以帮助最终用户对不同类型的漏洞有一个整体概述,从而做出可操作的决策。
-
开发一个 Taipy 后端框架,以与分类机器学习模型互动,以预测给定信息的漏洞类型。
快速安装
使用 Taipy 需要 Python 3.8 或更高版本。使用 Anaconda Python 发行版(conda)和 Visual Studio Code IDE 安装 Taipy,如下所示:
创建名为taipy-env的虚拟环境并安装 Python 3.8
conda create –-name taipy-env python=3.8
激活之前创建的环境
conda activate taipy-env
以下命令将在虚拟环境中安装 taipy 库
pip install taipy
运行 Taipy 应用程序
-
创建一个 Python 脚本文件<taipy_app.py>
-
输入以下代码,然后保存文件:
from taipy import Gui
analytics_choice = ["Breach types distribution",
"Breach by State",
"Top 10 Risky States",
"Covered Entity Type",
""]
choice = ""
my_app_page = """
# Security Breach Analytics Dashboard
## Breach Analysis
Please choose from the list below to start your analysis
<|{choice}|selector|lov={analytics_choice}|dropdown|>
Your choice: <|{choice}|text|>
"""
if __name__ == '__main__':
Gui(page=my_app_page).run(host="0.0.0.0", port=9696)
在 conda 控制台中,从 taipy_app.py 中输入以下命令:
python taipy_app.py
上述代码的成功执行会生成此 URL,并自动打开一个浏览器窗口:
访问应用程序的 URL
作者提供的图片
太棒了!
现在,让我们深入了解之前的代码。
-
导入用于创建仪表盘的 Gui 模块。
-
analytics_choice
是可能选择的列表。 -
然后,变量
choice
将保存来自analytics_choice
的值,这些变量的插值使用<|…|>语法完成。 -
my_page 包含以下 markdown 格式的信息:
-
安全漏洞分析仪表盘的 H1 级别用单个“#”符号表示。
-
漏洞分析的 H2 级别用双“#”符号表示,后跟简单的文本“请选择…分析”
-
我们使用原始的
analytics_choice
和 choice 变量创建一个下拉列表。 -
显示用户做出的选择。
最后,通过指定 my_app_page 以及端口和主机来运行应用程序。不指定服务器端口将使用默认端口(5000)。对于这个特定的示例,应用程序在9696端口打开,网址为http://localhost:9696
从头开始创建一个 Taipy 仪表盘
通过实现一个完整的仪表盘,将我们的 Taipy 知识提升到一个新的水平。仪表盘的主要部分将利用 Taipy 的以下视觉元素:
-
从选项列表中进行选择,使用 选择器。
-
使用 按钮 通过点击按钮触发操作。
-
在表格中显示原始数据。
使用 图表 显示图形结果。
所有这些可视化元素都是通过引入以下 Markdown 语法创建的:
<|{variable}|visual_element_name|param1=param1|param2=param2|…|>
最终仪表板将如下所示,最终的源代码将在文章末尾提供。
使用 Taipy GUI 创建的最终仪表板(作者提供的图像)
为了进行逐步演示,将在单独的文件中提供每个组件的示例,并使用以下命令运行每个文件:
python file_name.py
选择器
这些选项允许用户从下拉列表中选择,这与我们在“运行 Taipy 应用程序”部分中实现的功能相对应。
按钮和表格
用户界面中的按钮在被点击或按下时会启动特定的功能。on_action 函数会在按钮被按下时触发。
表格用于组织数据,提供三种显示模式:分页、allow_all_rows、unpaginated 和 auto_loading。 官方文档 提供了关于这些模式的更多信息。
创建一个新文件 button.py
,并包含以下代码:
from taipy import Gui
import pandas as pd
breach_data = pd.read_csv("data/breach_report_data.csv")
def toggle_table_dialog(state):
state.show_table_dialog = not state.show_table_dialog
show_table_dialog = False
my_app_page = """
<center> Security Breach Analytics Dashboard</center>
------------------------------
<br/>
<center> Click the Button below to display data </center>
<br/>
<center><|Display Raw Data|button|on_action=toggle_table_dialog|></center>
<|{show_table_dialog}|dialog|on_action=toggle_table_dialog|width=90vw|labels=Cancel|
<center><|{breach_data}|table|width=fit-content|height=65vh|></center>
|>
"""
我们首先将违约数据加载到 Pandas 数据框中。然后,选择“显示原始数据”将所有数据以表格格式展示,如下所示:
使用 Taipy 创建的按钮结果(作者提供的图像)
图表
通过更好地理解上述组件,我们可以将它们结合起来创建图表,基于全面的 plotly.js 图形库。否则,Taipy 的文档 提供了很好的示例作为起点。与前一部分类似,创建一个 charts.py
文件并包含以下代码:
创建一个条形图,其中 State 位于 x 轴
,Proportion 位于 y 轴
。
# import libraries here
my_app_page = """
<center> Security Breach Analytics Dashboard</center>
------------------------------
<center> Graph 3: Top 10 Most Affected States</center>
<br/>
<|{breach_df}|chart|type=bar|x=State|y=Individuals_Affected|>
"""
# Put the '__main__' section here
最终结果是这个动态图表,显示了按 State 受影响的个人数量,似乎加利福尼亚州受影响最严重。
使用 Taipy 的图表(作者提供的图像)
显示图像
在 Taipy GUI 中显示图像也很简单,可以使用 image
属性实现。以下代码展示了由 generate_word_cloud
生成的词云。图像的宽度为 2400 像素,高度为 1000 像素。当用户的鼠标悬停在图像上时,将显示 hover_text
属性的值:在这种特定情况下为 “违约地点的词云”。
<|{breach_location_image}|image|width="2400px"|height="1000px"|hover_text="Word cloud of Breach Location"|>
违约信息的位置词云(作者提供的图像)
此外,辅助函数generate_word_cloud
的定义如下:
from wordcloud import WordCloud
from PIL import Image
from io import BytesIO
def generate_word_cloud(data, column_name):
# Join all the location information into one long string
text = ' '.join(data[str(column_name)])
wordcloud = WordCloud(
background_color="#1E3043"
)
# Generate the word cloud
my_wordcloud = wordcloud.generate(text)
image = my_wordcloud.to_image()
my_buffer = BytesIO()
image.save(my_buffer, format = 'PNG')
return my_buffer.getvalue()
回调函数
目标是拥有一个基于用户选择动态更新的 GUI。通过使用 Taipy 的回调函数实现,这些函数会自动触发局部命名空间中的任何on_change
函数作为全局回调函数。实现如下:
def update_Type_of_Breach(state, var_name, var_value):
if var_name == "Type_of_Breach":
state.df = breach_df[breach_df.Type_of_Breach == var_value]
布局
多个图表可以提供有价值的商业洞察,但将它们垂直展示一个接一个可能不是最有效的方法。
相反,我们可以创建一个布局,将组件组织成一个规则网格,放置在layout.start
和layout.end
块之间。每个组件都在part.start
和part.end
块内创建。
以下基本语法创建了一个 2 列网格,根元素的字体大小为 1.8:
<|layout.start|columns= 1 2|gap=1.8rem|
<optional_id|part|>
<|{first content}|>
|optional_id>
…
<
<|{second content}|>
>
>
理解布局后,我们可以创建最终的仪表板,其中包含五个主要图表:
-
图表 1 展示了与漏洞信息位置相关的词云。
-
图表 2 显示了按州受影响的人员数量。
-
图表 3 确定了按漏洞类型受影响的总人数。
-
图表 4 展示了每年受影响的总人数。
-
图表 5 显示了每个覆盖实体的受影响人数。
# Preprocessing of the DateTime column
breach_df['Breach_Submission_Date'] = pd.to_datetime(breach_df['Breach_Submission_Date'])
breach_df["Year"] = breach_df["Breach_Submission_Date"].dt.year
markdown = """
<|toggle|theme|>
# <center>Security Breach Analytics Dashboard 🚨</center>
<center>**Chart 1:**General Trend Location of Breached Information </center>
<center><|{breach_location_image}|image|width=2400px|height=1000px|hover_text=Word cloud of Breach Location|></center>
------------------------------
<|layout|columns=2 5 5|gap=1.5rem|
<column_1|
### Type of Breach:
<|{breach_type}|selector|lov={breach_types}|dropdown|width=100%|>
------------------------------
<|Display Raw Data|button|on_action=toggle_table_dialog|>
<|{show_table_dialog}|dialog|on_action=toggle_table_dialog|width=90vw|labels=Cancel|
<center><|{breach_df}|table|width=fit-content|height=65vh|></center>
|>
|column_1>
<column_2|
**Chart 2:** Individuals Affected by State
<|{df}|chart|type=bar|x=State|y=Individuals_Affected|>
**Chart 4:** Individuals Affected by Year
<|{df}|chart|type=bar|x=Year|y=Individuals_Affected|>
|column_2>
<column_3|
**Chart 3:** Individuals Affected by Type of Breach
<|{df}|chart|type=bar|x=Type_of_Breach|y=Individuals_Affected|>
**Chart 5:** Individuals Affected per Covered Entity Type
<|{df}|chart|type=bar|x=Covered_Entity_Type|y=Individuals_Affected|>
|column_3>
|>
"""
if __name__ == "__main__":
gui = Gui(page=markdown)
gui.run(dark_mode=False, host="0.0.0.0", port=9696)
在配置仪表板之前,从Breach_Submission
列创建一个新的Year
列,然后将其用作图表 4 中的 x 轴。
运行所有代码应生成上面展示的第一个仪表板。
Taipy 后端运作情况
在下一节中,你将使用 Taipy 的后端功能轻松高效地创建、管理和执行数据管道,以训练一个随机森林分类器,从而确定给定数据的漏洞类型。
本节分为两个主要部分。首先,你将使用 Taipy Studio 构建完整的工作流图形表示。然后,编写相应的 Python 代码。
Taipy Studio
Taipy Studio 是 Visual Studio Code 的一个扩展,安装方法如下:
Taipy 安装过程(图像由作者提供)
安装完成后重启 VSCode,然后点击左下角的 Taipy 图标将显示 Taipy Studio 界面。这将显示四个主要标签,如配置文件、数据笔记、任务、管道和场景。
Taipy Studio 界面(图像由作者提供)
所有这些标签都可以用来实现我们的端到端管道目标,第一步是创建一个配置文件(taipy_config.toml),该文件将包含所有这些标签,这些标签由选择“Taipy: Show View”图标后右上角的 4 个图标表示。
Taipy Studio 组件(图像由作者提供)
Taipy 标签说明
以下是将要实现的主要函数,并附有对每个先前选项卡的简要说明。
-
filter_columns
函数负责从数据中选择相关列并生成 Pandas 数据框。 -
preprocess_columns
用于执行特征工程。 -
encode_features
负责以正确的格式对相关特征进行编码。 -
split_data
是将数据拆分为训练集和测试集的函数。 -
train_model
用于训练模型。 -
show_performance
是展示模型性能的最后阶段。
场景和管道
这是设置管道时要做的第一件事。一个场景由一个或多个管道组成。它作为执行的注册表。让我们创建一个名为 DATA_BREACH_SCENARIO 的场景,然后创建一个名为 DATA_BREACH_PIPELINE 的管道,如下所示:
从场景到管道(作者提供的图像)
任务
一个任务指的是一个可以执行的 Python 函数,总共会实现六个任务,从 filter_columns
到 show_performance
。
管道的输出连接到每个任务的输入,如下所示:
从管道到任务
下一步是在 Taipy Studio 中配置这些任务,通过将每个 Python 函数连接到相应的任务。但是在此之前,我们需要在 data_breach_tasks.py
文件中创建这些函数的签名,如下所示:
import pandas as pd
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import (
confusion_matrix,
accuracy_score,
precision_score,
recall_score,
f1_score
)
def filter_columns(df, list_columns_to_skip):
filtered_df = df.drop(list_columns_to_skip, axis=1)
return filtered_df
def preprocess_columns(df):
df['Breach_Submission_Date'] = pd.to_datetime(data['Breach_Submission_Date'])
df['Breach_Submission_Month'] = df['Breach_Submission_Date'].dt.month
df['Breach_Submission_Year'] = df['Breach_Submission_Date'].dt.year
df.drop("Breach_Submission_Date", axis=1, inplace=True)
return df
def encode_features(df):
list_columns_to_encode = ['State','Location_of_Breached_Information',
'Business_Associate_Present',
'Covered_Entity_Type']
le = LabelEncoder()
for col in list_columns_to_encode:
df[col] = le.fit_transform(df[col])
X = df.drop('Type_of_Breach', axis=1)
y = le.fit_transform(df['Type_of_Breach'])
return {"X": X, "y": y}
def split_data(features_target_dict):
X_train, X_test, y_train, y_test =
train_test_split(features_target_dict["X"],
features_target_dict["y"],
test_size=0.3,
random_state=42)
return {
"X_train": X_train, "X_test": X_test,
"y_train": y_train, "y_test": y_test
}
def train_model(train_test_dictionary):
classifier = RandomForestClassifier()
classifier.fit(train_test_dictionary["X_train"],
train_test_dictionary["y_train"])
predictions = classifier.predict(train_test_dictionary["X_test"],
train_test_dictionary["y_test"])
return predictions
def show_performance(train_test_dictionary, predictions):
y_test = train_test_dictionary["y_test"]
accuracy = accuracy_score(y_test, predictions)
precision = precision_score(y_test, predictions)
recall = recall_score(y_test, predictions)
f1score = f1_score(y_test, predictions)
return pd.DataFrame({
"Metrics": ['accuracy', 'precision', 'recall', 'f1_score'],
"Values": [accuracy, precision, recall, f1score]
})
接下来,我们按照以下 3 个步骤将每个任务链接到相应的 Python。下面的插图是针对 filter_columns
任务的,但必须对每个任务执行。
将任务链接到脚本的 3 个主要步骤(作者提供的图像)
数据节点
数据节点不包含实际数据,而是包含读取和写入这些数据所需的所有信息。它们可以是对任何数据类型的引用,例如文本、CSV、JSON 等。
例如,filter_columns
函数包含:
-
一个输入节点 (filtering_node),其类型为 .CSV 文件,以及
-
一个输出节点 (filtered_df):也以 .CSV 文件的形式存储。这然后作为 preprocess_columns 函数的输入。
交互节点定义如下,显示了存储类型从 pickle 修改为 .csv:
过滤节点输入类型的定义(作者提供的图像)
更新后的过滤节点的输入类型(作者提供的图像)
下一步是定义原始输入数据集的路径。这是通过数据节点中的“新属性”属性完成的。然后,按 Enter 并提供 .CSV 文件的路径。
过滤节点属性的定义(作者提供的图像)
过滤节点路径的定义(图片来源于作者)
对于所有需要.csv 文件的输入,重复相同的过程,最终图示在指定所有数据节点及其关系后将如下所示。
指定所有数据节点及其关系后的工作流程状态(图片来源于作者)
在配置管道后,整个图示的.toml 脚本格式会生成在taipy_config.toml文件中,其样式如下面的动画所示。
taipy_config.toml 文件的内容
然后,可以在任何 Python 脚本中加载这个.toml 文件来执行管道。我们来创建一个名为run_pipeline.py
的文件。
from taipy import Core, create_scenario
from taipy.core.config import Config
config_file_name = "./taipy_config.toml"
scenario_name = "DATA_BREACH_SCENARIO"
Config.load(config_file_name)
scenario_config = Config.scenarios[scenario_name]
if __name__ == "__main__":
Core().run()
pipeline_scenario = create_scenario(scenario_config)
pipeline_scenario.submit() # This executes the scenario
model_metrics = pipeline_scenario.performance_data.read()
print(model_metrics)
我们首先导入相关模块,然后定义配置文件及触发场景的名称。
然后,使用 submit()函数执行管道。
最后,我们检索模型的性能并打印结果,如下所示:
run_pipeline.py 的结果(图片来源于作者)
这个数据框可以进一步整合到初始仪表盘中,以图形化的方式展示数值。
结论
本文提供了对 Taipy 的全面概述,并展示了如何将前端和后端与任何数据和机器学习模型结合起来,创建完全功能的 Web 应用程序。
此外,随着新版本的发布,Taipy 提供了核心可视化元素,允许前端和后端之间的无缝集成,使用户能够轻松创建强大的业务对象,这些集成功能可以从官方网站获取。
如果你还在犹豫是否使用 Taipy,是时候尝试一下,以节省时间、精力,最重要的是金钱。最后,这些绝妙的教程可以帮助你进一步学习并提升技能。
迈出下一步,扩展你的数据科学技能
·
关注 发布于 Towards Data Science · 发送至 通讯 · 阅读时间 3 分钟 · 2023 年 11 月 9 日
–
从有效的讲故事技巧到战略性的职业规划,你在数据科学职业生涯中所需的技能各异且日益跨学科。与统计或编程不同,这些领域的结构化教育环境,如学位课程或训练营,只能提供有限的帮助。
幸运的是,TDS 作者来自各种专业和个人背景,并在实际组织中学到了许多关于什么有效、什么无效的经验。本周的重点,我们汇聚了一系列强有力的文章,关注这些不那么技术性的但同样重要的数据科学工作方面:它们基于这些专业人士的实际经验提供了宝贵的见解。
-
哦,你是说“管理变革”? 在数据科学迅速变化的领域中航行总是一个挑战,尤其是在应对业务优先级变化的组织中。Marc Delbaere 揭示了在数据团队背景下实施变革管理的困难,并探讨了领导者和个体贡献者如何平衡他们有时冲突的目标。
-
数据讲故事中的 4D:将科学变为艺术 “ 数据科学家的工作如果没有讲故事,纯粹是数字化的算命,” Zijing Zhu, PhD 如是说,他接着分享了一个详细的框架,该框架超越了可视化基础,帮助从业者更高效、更有影响力地传达数据见解。
-
了解你的受众:技术演示准备指南 从不同的角度探讨数据讲故事,John Lenehan 深入分析了数据驱动的演示文稿准备工作,并提供了具体建议,帮助你以引人入胜的方式结构化见解,吸引同事和利益相关者并解决他们的关注点。(完成后,你还应该探讨 John 的后续文章,关于 将数据转化为连贯叙事。)
图片由 Terri Bleeker 提供,来源于 Unsplash
-
在掌握这 6 项必备数据科学技能之前不要申请科技职位在她最新的职业指导中,Khouloud El Alami 聚焦于数据科学家需要在一些关键领域扎实掌握的技能,以便成为主要科技公司职位的竞争者。根据她在 Spotify 的经验,Khouloud 涵盖了技术和非技术技能,并解释了它们如何最终必须与可衡量的影响连接起来。
-
初级数据科学家的 3 个关键职业决策尽管这个领域相对较新,但数据专业人员现在已经有了相当成熟的职业路径——但是如果你不想让你的职业跟随这些路径怎么办?Matt Chapman的新帖子邀请早期职业者审视自己的优先事项,反思对他们真正重要的东西,并根据他们所追求的角色类型来塑造他们的选择。
如果你也希望拓展你的技能和知识,我们为你准备了一些优秀的阅读材料,你不容错过。
-
想要了解推荐系统的新视角,请访问 Irene Chang的 Thompson 采样简介,这是关于这些无处不在的算法工具系列的第一部分。
-
通过关注 Caroline Arnold 的易懂且图文并茂的入门介绍,了解 伪随机数及其在机器学习中的作用。
-
Michael Galkin及其合著者介绍了他们最新的研究,ULTRA,一个 知识图谱推理的基础模型。
-
在最近的一次深入探讨中,Ms Aerin 探索了 RLHF(来自人类反馈的强化学习)及其作用 在训练数据和学习范式中,推动了最近的大型语言模型的进展。
-
我们非常高兴欢迎新的Carolina Bento解释员:一个隐藏马尔可夫模型的实践指南,配有直观的实现。
-
在他的首篇 TDS 文章中,Jon Flynn提供了关于当前 AI 持续学习方法的清晰全面的介绍,以及它们如何旨在应对保持模型最新这一(主要)挑战。
感谢支持我们作者的工作!如果你喜欢在 TDS 上阅读的文章,可以考虑成为 Medium 会员——这将解锁我们的整个档案(以及 Medium 上的其他每一篇文章)。
直到下一期 Variable,
TDS 编辑部
什么是时间序列预测中的谐波回归?
原文:
towardsdatascience.com/take-your-forecasting-to-the-next-level-with-harmonic-regression-5a8515f63295
揭示傅里叶级数与时间序列之间的迷人关系
·发表于Towards Data Science ·阅读时间 6 分钟·2023 年 3 月 29 日
–
图片来自于Pawel Czerwinski在Unsplash
背景与问题
当我们想要对时间序列中的季节性进行建模时,我们通常会使用SARIMA模型。这个模型通过在特定滞后索引处找到自回归量和移动平均来添加季节性组件到ARIMA模型中。例如,具有年度季节性的月度数据将适配自回归量和移动平均于12的倍数。你可以在我之前的文章中阅读更多关于这个过程的信息:
深入探讨 SARIMA 模型及其应用
然而,如果我们有一个年季节性为365.25 天的日数据集怎么办?或者有一个季节性为52.14的周数据集呢?
不幸的是,SARIMA 无法处理这种 非整数 的数据,并且由于需要在 365 个数据点中寻找模式,计算上也 有困难。
那么,我们该怎么办?
使用 傅里叶级数 来拯救局面!
补充视频。
什么是傅里叶级数?
直觉
傅里叶级数是数学中最有趣的发现之一,它指出 这个:
任何周期函数都可以分解为正弦和余弦波的总和
这是一个非常简单的陈述,但其含义非常重要。
例如,下图展示了 sin(2x) 和 cos(3x) 及其对应的总和:
作者在 Python 中生成的图。
注意到 sin(2x) 和 cos(3x) 的函数非常均匀和简单,但它们的总和(红线)却产生了更复杂的模式。这就是傅里叶级数的核心思想。
我们甚至可以使用傅里叶级数通过将不同 奇数 频率和幅度的正弦波 (谐波) 相加来构造一个 方波:
作者在 LaTeX 中的方程。
作者在 Python 中生成的图。
令人惊讶的是,我们从光滑的正弦函数中生成了一条尖锐而直的图。这展示了傅里叶级数构造任何周期函数的真正力量。
用于生成这些图的代码可以在我的 GitHub 上找到:
[## Medium-Articles/fourier_series.py 在 egorhowell/Medium-Articles 主分支]
我在我的中等博客/文章中使用的代码。通过创建账户来贡献于 egorhowell/Medium-Articles 的开发…
github.com](https://github.com/egorhowell/Medium-Articles/blob/main/Time%20Series/Time%20Series%20Tools/fourier_series.py?source=post_page-----5a8515f63295--------------------------------)
理论
如上所述,傅里叶级数指出任何周期函数都可以分解为正弦和余弦波的总和。从数学角度来看,这是写作的:
作者在 LaTeX 中的方程。
其中:
-
A_0: 给定周期函数的平均值
-
A_n: 余弦分量的系数
-
B_n: 正弦分量的系数
-
n: 阶数,即正弦或余弦波的频率,这被称为‘谐波’
-
P: 函数的周期
周期P和阶数n是事先已知的。然而,需要计算系数(A_0, A_n, B_n)来确定哪些正弦和余弦分量的组合产生给定的周期函数。这些通常通过积分推导得出(有关示例请参见这里),但幸运的是,大多数 Python 数据科学包为我们完成了这个过程!
预测链接
你是否在想傅里叶级数如何适用于时间序列预测?好吧,请记住傅里叶级数处理周期函数,而我们经常发现时间序列中包含某些周期性结构(通常是季节性)。因此,我们可以使用傅里叶级数来建模我们时间序列数据中的任何复杂季节性模式!
使用傅里叶级数建模季节性的优点是:
-
任何季节长度
-
建模多个季节模式
-
傅里叶季节性的敏感性可以通过正弦和余弦分量的阶数和振幅进行调节
-
当季节性周期 大于~200 时计算效率高
许多这些优势无法通过 SARIMA 模型实现,因为它仅接受整数季节性、单一季节,并且当季节周期超过~200时,往往会耗尽内存。
使用傅里叶级数建模季节性的缺点是:
- 假设季节性模式和周期保持不变
现在的问题是,我们如何将其添加到我们的模型中?
ARIMAX 与外生特征
直觉
对于 ARIMA 模型,我们可以添加额外的外部特征来帮助预测。这些特征被称为 外生特征,使得 ARIMA 模型变成一个 ARIMAX 模型。例如,我们可以在预测房屋价值时使用当前的利率作为外生特征。
你可以将 ARIMAX 模型看作是常规的线性回归加上自回归量和移动平均组件(内生变量)。关键是让傅里叶级数成为这些外生特征之一,或者像线性回归中常描述的那样成为解释变量。
由于我们处理的是时间序列,外生特征需要像自回归量和移动平均一样具有时间索引。它们也需要在预测时已知。例如,如果我们想预测 5 月的房价,我们需要知道 5 月的利率,如果我们希望将其作为外生特征。
理论
数学上,外生特征以以下方式添加到经典 ARIMA 模型中:
作者用 LaTeX 给出的方程。
-
y: 不同时间步长的时间序列/滞后
-
x: 外生特征
-
β: 外生特征的系数
-
ϕ: 自回归组件(滞后)的系数 自回归组件(滞后)
-
p: 自回归组件的数量
-
ε: 预测 误差项, 移动平均组件
-
θ: 滞后预测误差的系数
-
q: 滞后误差组件的数量
傅里叶级数特征
将傅里叶级数作为外生量添加到 ARIMA 模型中相对简单,因为系数/幅度β是为我们推导的,我们只需要提供相应的正弦和余弦项。在伪代码中,这等同于:
# Sine component
sin(2*pi*frequency*time_index/period)
# Cosine component
cos(2*pi*frequency*time_index/period)
例如,假设我们有每月数据并且有年度季节性,我们想要 5 月的傅里叶分量。在伪代码中,这将是:
# Sine component
sin(2*pi*frequency*5/12)
# Cosine component
cos(2*pi*frequency*5/12)
五月是第 5 个月,一年有 12 个月。
然而,我们仍然需要推导频率(阶数)值。这通常通过传递大量正弦和余弦组件的阶数来找到,并让模型找出最有用的阶数。在下面的 Python 示例中,我们将演示这个过程。
Python 实现
我们将使用谐波回归和 ARIMAX 进行一些实际的预测!我们将使用来自 Kaggle 的美国航空公司乘客数据集。
数据 来自 Kaggle 采用 CC0 许可证。
作者总结。
由作者在 Python 中生成的图。
正如我们所看到的,傅里叶级数已经很好地捕捉到了季节性!
注意:在上面的代码中,我们使用了 Box-Cox 变换以使方差平稳。你可以在这里了解更多关于这个过程的内容。
总结与思考
当你的时间序列的季节性是非整数的、有众多模式或非常长(>50 点)时,最好使用傅里叶级数来建模这一季节性组件。这可以通过将傅里叶级数作为外生特征添加到常规 ARIMA 模型中,将其转化为 ARIMAX 来实现。这些外生特征是辅助预测时间序列的外部协变量。
完整代码可以在我的 GitHub 上找到:
## GitHub - egorhowell/Medium-Articles: 代码我在我的 Medium 博客/文章中使用。
你目前无法执行该操作。你在另一个标签或窗口中登录了。你在另一个标签或窗口中注销了…
还有别的事情!
我有一个免费的时事通讯,Dishing the Data,在其中我每周分享成为更好数据科学家的技巧。没有“无关紧要的内容”或“点击诱饵”,只有来自实践数据科学家的纯粹可操作的见解。
## Dishing The Data | Egor Howell | Substack
如何成为更好的数据科学家。点击阅读《Dishing The Data》,由 Egor Howell 撰写的 Substack 出版物,包含…
连接我!
参考文献和进一步阅读
- 预测:原则与实践:
otexts.com/fpp2/
使用 LangChain 和 Azure OpenAI 与您的 SQL 数据库“对话”
探索使用 LLM 处理数据库查询的自然语言处理的强大功能
·
关注 发表在 Towards Data Science · 10 分钟阅读 · 2023 年 9 月 28 日
–
LangChain 是一个开源框架,用于开发可以使用 LLM(大型语言模型)处理自然语言的应用程序。
LangChain 的 Agent 组件是一个 LLM 的封装器,它决定解决问题的最佳步骤或行动。Agent 通常可以访问一组称为 Tools(或工具包)的功能,并且可以根据用户输入决定使用哪个工具。每个代理都可以执行各种 NLP 任务,例如解析、计算、翻译等。
Agent Executor 是 Agent 及其工具集的可运行接口。Agent 执行器负责调用 Agent、获取操作和操作输入、调用操作引用的工具及其对应输入、获取工具的输出,然后将所有这些信息传回 Agent 以获取下一步操作。通常这是一个迭代过程,直到 Agent 达到最终答案或输出。
在这篇文章中,我将展示如何使用 LangChain Agent 和 Azure OpenAI gpt-35-turbo 模型 通过自然语言查询你的 SQL 数据库(无需编写任何 SQL!)并获取有用的数据洞察。我们将使用 SQL Database Toolkit and Agent,它可以将用户输入转换为适当的 SQL 查询,并在数据库中执行以获取答案。
这是一篇探索性文章。它旨在提供对当前可用工具的概述,并在过程中识别任何挑战。
作者提供的图片(使用 Bing 图像创作者创建)
需求范围
在这次探索中,我们只读取数据库中的数据,避免任何插入、更新或删除操作。这是为了保持数据库中的数据完整性。我们将重点关注如何利用数据库中可用的数据来回答问题。
不过,SQL Agent 不保证它不会根据特定的问题对你的数据库执行任何 DML 操作。确保不发生任何意外 DML 操作的一种方法是创建一个仅具有 *read*
权限的数据库用户,并在以下代码中使用它。
让我们以一个电子零售公司的订单和库存系统数据库为例。库存跟踪多个类别的产品,例如厨房、园艺、文具、浴室等。订单系统记录每个产品的购买历史,包括订单状态、交货日期等。
以下可能是该应用程序的最终用户提出的一些问题:
-
上个月销售的厨房产品数量。
-
有多少订单尚未发货?
-
上个月有多少订单延迟交付?
-
上个月销售的前三大产品是什么?
设置
-
Python>=3.8 和一个 IDE 进行我们的探索。我使用 VS Code。
-
我在这里使用 Azure OpenAI gpt-35-turbo 作为 LLM。这个模型是 GPT-3.5 系列的一部分,可以理解和生成自然语言及代码。要跟随本指南,你需要一个启用了 OpenAI 服务的 Azure 订阅。了解更多 here。
-
我在这里使用一个 Azure SQL 数据库。然而,你也可以使用本地 SQL 数据库。
数据库
我创建了一个名为retailshopdb
的数据库,包含以下表格和关系:
-
类别
-
产品
-
订单
作者提供的图片
除了‘Id’列作为每个表的主键外,这些表还有相互之间的外键关系,例如 CategoryId 是 Product 表中的外键,ProductId 是 Orders 表中的外键。这些关系对于 LangChain 代理根据最终用户的问题构造 SQL 查询至关重要。
Azure OpenAI
如果你在订阅中创建了 Azure OpenAI 资源,请导航到 Azure OpenAI Studio。为 gpt-35-turbo
模型创建一个 deployment
。
作者提供的图片
代码与输出分析
让我们从一些基础代码开始,以便在 VS Code Python 笔记本中访问 LLM。
- 通过安装所需的库并设置所需的环境变量来初始化笔记本。
%pip install langchain openai sqlalchemy
import os
from dotenv import load_dotenv
os.environ["OPENAI_API_TYPE"]="azure"
os.environ["OPENAI_API_VERSION"]="2023-07-01-preview"
os.environ["OPENAI_API_BASE"]="" # Your Azure OpenAI resource endpoint
os.environ["OPENAI_API_KEY"]="" # Your Azure OpenAI resource key
os.environ["OPENAI_CHAT_MODEL"]="gpt-35-turbo-16k" # Use name of deployment
os.environ["SQL_SERVER"]="" # Your az SQL server name
os.environ["SQL_DB"]="retailshop"
os.environ["SQL_USERNAME"]="" # SQL server username
os.environ["SQL_PWD"]="{<password>}" # SQL server password
2. 连接到数据库。
from sqlalchemy import create_engine
driver = '{ODBC Driver 17 for SQL Server}'
odbc_str = 'mssql+pyodbc:///?odbc_connect=' \
'Driver='+driver+ \
';Server=tcp:' + os.getenv("SQL_SERVER")+'.database.windows.net;PORT=1433' + \
';DATABASE=' + os.getenv("SQL_DB") + \
';Uid=' + os.getenv("SQL_USERNAME")+ \
';Pwd=' + os.getenv("SQL_PWD") + \
';Encrypt=yes;TrustServerCertificate=no;Connection Timeout=30;'
db_engine = create_engine(odbc_str)
3. 初始化 LangChain chat_model
实例,它提供了使用聊天 API 调用 LLM 提供者的接口。选择聊天模型的原因是 gpt-35-turbo
模型已针对聊天进行了优化,因此我们在这里使用 AzureChatOpenAI
类来初始化实例。
from langchain.chat_models import AzureChatOpenAI
llm = AzureChatOpenAI(model=os.getenv("OPENAI_CHAT_MODEL"),
deployment_name=os.getenv("OPENAI_CHAT_MODEL"),
temperature=0)
请注意,
temperature
设置为 0。温度是一个控制生成文本的“创造力”或随机性的参数。较低的温度(0 为最低)使输出更“专注”或确定。由于我们处理的是数据库,LLM 生成的响应必须是事实性的。
4. 创建提示模板。
提示 是我们发送给 LLM 以生成输出的输入。提示也可以设计为包含指令、上下文、示例(单次或少次),这些都对生成准确的输出至关重要,同时也可以设置语气和格式化输出数据。
使用提示模板是结构化这些属性的好方法,包括提供给 LLM 的最终用户输入。我们在这里使用 LangChain 的 ChatPromptTemplate
模块,它基于 ChatML(聊天标记语言)。
这是一个基础提示模板,供我们开始使用。随着时间的推移,我们会根据需要更新此模板 —
from langchain.prompts.chat import ChatPromptTemplate
final_prompt = ChatPromptTemplate.from_messages(
[
("system",
"""
You are a helpful AI assistant expert in querying SQL Database to find answers to user's question about Categories, Products and Orders.
"""
),
("user", "{question}\n ai: "),
]
)
现在初始化 create_sql_agent
,它设计用于与 SQL 数据库交互,如下所示。该代理配备了与 SQL 数据库连接并读取表的元数据和内容的工具包。
from langchain.agents import AgentType, create_sql_agent
from langchain.sql_database import SQLDatabase
from langchain.agents.agent_toolkits.sql.toolkit import SQLDatabaseToolkit
db = SQLDatabase(db_engine)
sql_toolkit = SQLDatabaseToolkit(db=db, llm=llm)
sql_toolkit.get_tools()
sqldb_agent = create_sql_agent(
llm=llm,
toolkit=sql_toolkit,
agent_type=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
verbose=True
)
请注意,我们在这里使用 ZERO_SHOT_REACT_DESCRIPTION
作为 agent_type
参数的值,这指示代理 不使用记忆。
一切准备就绪进行测试 —
sqldb_agent.run(final_prompt.format(
question="Quantity of kitchen products sold last month?"
))
注意在以下单元格输出中,LangChain Agent Executor 如何以迭代的方式使用
Action
、Observation
和Thought
流,直到达到Final Answer
。
作者提供的图片
输出: 10
这是一个正确的答案。
让我们来点乐趣吧?将问题中的‘Quantity’替换为‘how many’,这应该会产生相同的答案。
sqldb_agent.run(final_prompt.format(
question="How many kitchen products were sold last month?"
))
但这就是我们得到的结果 —
作者提供的图片
输出: ‘本月销售了 2 件厨房产品。’
这个输出不正确! 代理在创建 SQL 查询时犯了错误。它没有执行 SUM(ProductOrderedQuantity)
来获取输出,而是对 JOIN 结果执行了 COUNT(*)
,这导致了错误的输出。
为什么稍微改变提示输入会产生不同的输出?
OpenAI 模型是非确定性的,这意味着相同的输入可能会产生不同的输出。将温度设置为 0 会使输出大多是确定性的,但由于 GPU 浮点运算,可能仍会存在少量的变异。
使用不同的输入运行另一个测试 —
sqldb_agent.run(final_prompt.format(
question="How many orders have not been shipped yet?"
))
图片由作者提供
输出:‘还有 15 个订单尚未发货。’
这又是错误的结果。 代理也考虑了‘已完成’的订单,而我们的提问仅涉及尚未发货的订单。
让我们看看可以做哪些修改以生成准确的输出。
玩转 Prompt Engineering
LangChain 代理可以使用其工具包从 SQL 数据库中读取表格元数据,并且在一定程度上可以解释列名。但是仍然存在一些推理上的差距,我们可以尝试使用 Prompt Engineering 技术来弥补这些差距。
我们从一个基础提示模板开始,该模板只有一行指令。让我们添加一些额外的信息,以便向 LLM 提供更多关于我们用例的上下文,以形成更好的 SQL 查询。以下是我在系统消息中添加的高层次信息:
-
表格列的信息
-
订单状态值的‘含义’
-
最具体的信息在最后
from langchain.prompts.chat import ChatPromptTemplate
final_prompt = ChatPromptTemplate.from_messages(
[
("system",
"""
You are a helpful AI assistant expert in identifying the relevant topic from user's question about Categories, Products and Orders and then querying SQL Database to find answer.
Use following context to create the SQL query. Context:
Product table contains information about products including product name, description, product price and product category.
Category table contains information about categories including category name and description. Each Product is mapped to a Category.
Orders table contains information about orders placed by customers including
quantity or number of products ordered,
expected delivery date and actual delivery date of the Order in the location and the status of the order.
Order status = 'Processing' means the order is being processed by seller and not yet shipped,
Order status = 'Shipped' means the order is shipped by the seller and is on the way to the customer,
Order status = 'Completed' means the order is delivered to the customer, and
Order status = 'Cancelled' means the order is cancelled by the customer.
If the question is about number of products in an order, then look for column names with 'quantity' in the tables and use 'sum' function to find the total number of products.
"""
),
("user", "{question}\n ai: "),
]
)
现在重新运行第一个输入 —
sqldb_agent.run(final_prompt.format(
question ="How many Kitchen products were sold in current month?"
))
图片由作者提供
输出:10
推理得到了改善!通过向 LLM 提供额外的上下文,我们能够获得准确的输出。
现在测试所有用户输入 —
思考之后 . . .
这一切在测试时看起来都很不错,但如果我们想实际构建一个解决方案并将其发布供最终用户使用呢?这是一个很好的想法,适用于类似于在自己数据库上运行聊天机器人的用例,但像任何典型的软件开发一样,在构建基于 LLM 的系统之前,我们还需要考虑和决定一些关键的设计方面。
可扩展性
在这个例子中,我使用了 3 个表,总共约 30 行。涉及连接所有 3 个表的输出的平均延迟约为 5 秒。截至目前,我在官方文档中没有找到关于我们可以使用的数据库最大大小的信息。然而,我们可以考虑一些参数来确定我们的需求:
-
您的应用程序需要的延迟是多少?如果您正在构建一个聊天机器人,那么您的预期延迟可能不会超过某个数值。
-
您的数据库大小是多少?还要考虑您希望用于查询的各个表的大小。
请注意,你不需要将整个数据库传递给 Agent Toolkit。可以选择特定的表与 Toolkit 一起使用。一个好的选择是为不同的用例识别表的子集,并创建多个指向不同表子集的 Agent。
3. Azure OpenAI 资源的速率和配额限制。如果你使用的是其他 LLM 提供商,也请查看那里可能存在的限制/约束。
可靠性
我们如何确保始终获得准确的响应?如何确保系统不会出现幻觉或产生完全意外的内容?
当前正在研究如何提高 LLM 的可靠性和鲁棒性。通过使用特定用例的提示,我们可以帮助改善我们的用例的推理,这有时也被称为“临时学习”或“上下文学习”。
请记住,我们在这里不是在训练 LLM。从使用预训练 LLM 构建产品的角度,我们只能有针对性地调整我们的代码、模型参数和构建在这些 LLM 上的提示。
以迭代方式进行开发,并在过程中进行评估,可以将我们引向正确的方向,开发一个整体有效的系统。
日志记录和监控
像其他典型的软件开发一样,启用日志记录和持续监控 LLM 基础的应用程序是一种好习惯。监控不仅可以捕获系统相关的指标,如性能、延迟、请求-响应率,还可以捕获我们系统的输入和输出,这可以帮助我们确定系统的一致性。从监控中收集的一些有用信息可以用来改进我们的系统:
-
终端用户频繁提出类似问题,以及这些问题生成的输出
-
LLM 的幻觉率
结论
软件工程领域正在迅速变化,LLM 的巨大生成能力带来了许多解决方案。我们有机会采用这项技术,利用其力量创建产品,同时保持对 LLM 支持系统的可靠性的检查。通常,从小处开始,建立一个概念验证应用程序,看看它是否符合你的需求,总是一个好主意。
参考文献:
community.openai.com/t/run-same-query-many-times-different-results/140588
help.openai.com/en/articles/6654000-best-practices-for-prompt-engineering-with-openai-api
mlops.community/concepts-for-reliability-of-llms-in-production/
如果你想阅读更多关于新兴技术的内容,请关注我。请在评论区留下你的反馈。
2023 年最佳:关于 ChatGPT 和 LLMs
·
关注 发表在 Towards Data Science · 发送为 通讯 · 阅读时间 5 分钟·2023 年 12 月 14 日
–
你可能会说 2023 年对数据科学家和机器学习专业人士来说是多事之年,但这并不能完全捕捉到过去 12 个月我们在这个领域所经历的繁忙活动量。
尽管我们总是力图抵制炒作和夸张,但我们不得不承认,是的,我们确实看到了一些戏剧性的变化,既包括从业者的观点,也包括社会整体对人工智能及其对我们日常生活影响的看法。ChatGPT 在 2022 年最后几周的发布远不是这种过渡的唯一因素,但很难否认它既是催化剂又是象征性的焦点。
当我们考虑如何盘点 2023 年我们作者的最佳和最受欢迎作品时,回顾关于大语言模型的文章——尤其是那个无处不在的聊天机器人——成为了一个非常自然的选择。我们在这里呈现的文章并不全面,但确实提供了一个具有代表性的样本,展示了你们这些读者对哪些文章反响最强烈——无论是你们无法停止阅读和分享的文章,还是那些在 TDS 及其他地方引发了最深刻讨论的文章。
在我们深入探讨过去一年中最引起关注的文章之前,我们想花一点时间感谢我们的整个社区对我们的支持。我们特别感谢我们了不起的作者们、Medium的合作伙伴、慷慨提供专业知识的志愿编辑组,以及我们的两位前同事和杰出编辑,凯特琳·金迪格和凯瑟琳·普雷里。
-
ChatGPT 如何运作:模型背后的机器人在最不令人惊讶的发展中,莫莉·鲁比的易于理解且信息丰富的解释成为了我们 2023 年最受欢迎的文章。如果你还没读过,现在也不算太晚!
-
封闭的 AI 模型造成糟糕的基准在一个后 ChatGPT 世界中,自然语言处理研究将会采取什么方向?安娜·罗杰斯考察了这个迅速变化领域的现状。
-
**ChatGPT 能写出比数据分析师更好的 SQL 吗?**虽然大语言模型是否对整个职业构成威胁仍有待观察,玛丽·陈在 ChatGPT 发布后不久便花时间调查了其编程技能。
-
GPT 是一个不可靠的信息库在对人工智能幻觉的前瞻性观察中,诺布尔·阿克森深入探讨了将大语言模型当作可靠搜索引擎使用的潜在风险。
-
如何将任何文本转换成概念图 由于 LLM,NLP 领域的可能性得到了探索,Rahul Nayak 提供了一种将文本语料库转换为知识图谱的实用方法。
-
并非所有美好:ChatGPT 的阴暗面 从内建偏见到隐私和剽窃问题,Mary Reagan PhD 揭示了 ChatGPT 崛起后出现的一些主要风险。
-
零 ETL、ChatGPT 与数据工程的未来 ChatGPT 和类似工具将如何影响日常的数据工程工作流?Barr Moses 分享了对“后现代数据栈”未来的见解。
-
构建你的第一个 LLM 应用所需了解的一切 2023 年是 LLM 驱动的应用程序构建过程变得实际民主化的一年,这在很大程度上得益于像 Dominik Polzer 的广泛分享的教程。
-
GPT-4 与 ChatGPT:训练、性能、能力与局限性的探讨 在发布 ChatGPT 几个月后,OpenAI 通过最新的 GPT-4 提升了标准,Mary Newhauser 迅速提供了这两款产品的详细对比。
-
TimeGPT:首个时间序列预测的基础模型 随着年份的推进,我们遇到了越来越多针对特定用例的 LLM 解决方案。Marco Peixeiro 对 TimeGPT 进行了解释,它是一个定制化基础模型的示例。
-
掌握客户细分与 LLM LLM 的实际应用案例及其支持的产品每天都在不断增长;Damian Gil 为营销人员和商业战略家概述了一个有前途的方向。
-
开始使用 LangChain:构建 LLM 驱动应用程序的初学者指南 与 ChatGPT 一起,LangChain 成为了构建基于 LLM 的产品的热门工具;Leonie Monigatti 撰写了这本资源指南,适合任何对其进行探索的人。
-
新的 ChatGPT 提示工程技术:程序模拟 将我们的需求和目标转化为 LLM 可以正确解读的语言仍然是一个挑战。Giuseppe Scalamogna 揭示了一种更有效的提示设计创新框架。
-
GPT 模型如何工作 作为对 GPT 模型背后的数学和理论的全面且易于理解的入门介绍,Beatriz Stollnitz的深入分析仍然是初学者和经验丰富的从业者的顶级选择。
-
如何从零开始构建 LLM 如果你偏好更具实践性的学习方法,Shawhin Talebi 的教程将带你从数据整理到模型评估——即使你不打算在家里创建下一个 Llama 或 Falcon 模型,它也值得一探!
-
RAG 与微调——哪个是提升 LLM 应用的最佳工具? 随着我们了解了预训练模型的局限性,新的方法出现以提升其性能。Heiko Hotz 提供了对两种主要选项的有用比较:微调和检索增强生成(RAG)。
-
在 CPU 上本地运行 Llama 2 进行文档问答 能够与我们自己的文本文件、PDF 和音频记录“对话”已经成为 LLM 的一个流行日常应用场景。Kenneth Leung 的逐步指南展示了我们如何在本地机器上创建这样的工作流程。
-
LangChain 中链式 LLMs、代理和工具的温和介绍 对于任何刚刚开始使用 LLMs 的人,Dr. Varshita Sher关于 LangChain 构建模块的有用且全面的教程是必读之作。
-
分子生物学中的大型语言模型 探索 LLMs 在科学研究中的潜力,Serafim Batzoglou的深度挖掘关注了其在分子生物学中的影响,应用范围从基因结构预测到药物发现。
敬请关注! 在 2023 年,我们发布了大量优秀文章,涵盖了远超 LLMs 和 ChatGPT 的广泛话题。下周,我们将把今年的最后一期 Variable 专注于数据科学和编程技能、职业道路以及特别项目的精彩文章。
再次感谢您在 2023 年支持我们作者的工作!如果您喜欢 TDS 上的文章,可以考虑成为 Medium 的朋友会员:这是一个新的会员等级,能为您喜爱的作者提供更大的奖励。
直到下一个 Variable,
TDS 编辑部
TDSP:当敏捷遇上数据科学
原文:
towardsdatascience.com/tdsp-when-agile-meets-data-science-15ccb5bf8f87
实用指南:将敏捷原则应用于数据科学项目
·发表于 Towards Data Science ·7 分钟阅读·2023 年 1 月 23 日
–
由 Daria Nepriakhina 🇺🇦 拍摄于 Unsplash
如果你参加过软件开发/项目管理课程或培训,你可能听说过敏捷。敏捷是一套关注适应性规划、早期交付、持续改进和灵活响应需求变化的软件开发实践。
尽管敏捷在软件开发中非常流行,但这些实践带来的灵活性在数据科学项目中同样,甚至更为有效。事实上,微软在 2016 年发布了一个迭代的数据科学框架,专门将敏捷原则应用于数据科学项目。
在这篇文章中,我将解释微软的团队数据科学流程(TDSP)如何用于将敏捷原则应用于数据科学项目。
引言——敏捷原则
在介绍 TDSP 之前,我们应当讨论敏捷的指导原则,这些原则最初由敏捷宣言的作者提出。
-
个人与互动胜于过程和工具。
-
工作软件胜于全面文档。
-
客户协作胜于合同谈判。
-
响应变化胜于遵循计划。
整个敏捷框架中的实践,如每日立会和迭代增量开发,都是基于这些价值观。这些实践旨在适应变化,并迅速交付可工作的解决方案。
什么是 TDSP?
TDSP 是一种将敏捷原则应用于高效交付数据科学解决方案的方法论。TDSP 的核心概念是数据科学生命周期,类似于敏捷中的软件开发生命周期。数据科学生命周期包括在数据科学项目中反复进行的五个生命周期步骤:
-
业务理解
-
数据获取与理解
-
建模
-
部署
-
利益相关者/客户接受
这些步骤可以通过下面的工作流图进行可视化。
数据科学工作流。图片由作者提供,灵感来源于Microsoft Azure。
在这种方法论中,每个数据科学项目都从定义业务问题和理解业务需求开始。这导致了数据获取和理解步骤,这是进行任何模型开发工作的先决条件。一旦我们有了一个表现良好的模型,就可以将其部署到生产环境中,或以仪表板或报告的形式展示结果。
如果在任何时候我们对结果不满意或面临变化的需求,我们可以返回到之前的步骤,因为这种方法论专注于迭代开发。每个步骤将在后续部分中详细解释。
业务理解
照片由Medienstürmer提供,来源于Unsplash
这一阶段的核心是确定项目的业务需求和识别解决相关机器学习问题所需的数据。此阶段有两个主要任务:
-
定义目标: 我们需要与客户/利益相关者合作,以确定我们试图解决的业务问题。
-
识别数据来源:一旦我们知道了要解决的问题,我们需要识别为解决该问题所需的数据来源。
这些步骤是每个实际数据科学项目的基础。明确的目标和数据来源在数据分析和模型开发之前就应确定。
数据获取与理解
照片由Myriam Jessier提供,来源于Unsplash
在制定业务问题并确定数据来源之后,下一步最自然的步骤是获取和探索数据。TDSP 的这一阶段包括三个主要任务:
-
获取数据: 我们需要将数据引入用于分析的环境中。如果我们在本地工作,这个任务可能只是将文件上传到 Jupyter 的工作目录。
-
探索数据: 这一步通常被称为探索性数据分析(EDA),包括预处理和理解数据中的属性和模式,并确定数据是否适合模型开发。
-
建立数据管道: 这一步涉及构建一个处理新数据的过程。数据管道可以是基于批处理的、实时的或这两者的混合。
尽管所有这些步骤可能由数据科学家执行,但第三步甚至可能是第一步可能需要由数据工程师执行。这个阶段突显了数据科学团队中除数据科学外的其他技能的重要性。数据科学家在进行 EDA 时,数据工程师可能在设置数据管道,这样我们可以更快地完成这个阶段。
建模
建模阶段,可能是大多数数据科学家最兴奋的阶段,依赖于前两个阶段的成功完成。我们的模型质量最终受到数据质量以及对数据理解的限制。一旦我们有了数据管道和经过探索的高质量数据,我们就准备开始建模阶段,该阶段有三个关键步骤:
-
特征工程: 这一步是从原始数据中创建数据特征以用于模型训练的过程。特征工程通过对数据的良好理解来增强,这使我们能够提取甚至创建新的特征以供模型使用。
-
模型训练: 一旦我们有了一组特征和目标变量,我们可以训练模型来预测目标变量。在这一阶段,我们将数据分为训练集、验证集和测试集。
-
模型评估: 在训练每个模型后,我们需要通过回答以下问题来评估这些模型:1)模型在验证/测试集上的指标是什么?2)模型是否解决了业务问题并符合问题的限制?3)这个模型是否适合生产环境?
这一阶段的步骤是迭代的。我们可以训练一个模型,发现结果不令人满意,然后返回到特征工程和模型训练阶段,打造更好的特征并尝试不同的建模方法。在这个阶段训练和评估多个模型并不是不寻常的,事实上,这是预期中的事情。
部署
这个阶段将我们的模型转变为实际可用并产生业务结果的东西。这个阶段的唯一步骤是通过将数据管道和模型集成到生产或类似生产的环境中来使我们的模型具备操作性。有许多方法可以部署模型,但我们选择的路线将取决于业务用例。考虑以下部署选项:
-
通过 API 公开模型,以便其他应用程序可以使用。
-
创建一个微服务或容器化应用程序来运行模型。
-
将模型集成到一个具有仪表板的 Web 应用程序中,仪表板显示预测结果。
-
创建一个批处理过程来运行模型并将预测写入一个可以使用的数据源。
一旦这个阶段完成,相关利益方和/或客户应该能够观察到模型产生的结果。例如,一个投入生产的产品推荐系统应该能够为在线购物的客户生成推荐。
客户接受
照片由 Rock Staar 提供,来源于 Unsplash
在这个最终阶段,我们的目标是确认数据管道、模型和生产部署满足客户的需求,并解决第一阶段中提到的业务问题。这个阶段有两个步骤:
-
系统验证: 确认数据管道、模型和部署满足业务用例,并满足客户需求。
-
项目移交: 将项目转交给负责生产管理的团队。
请注意,这个过程是迭代的,因此如果数据管道、模型或系统验证步骤中的部署有问题,我们可能需要返回到前一个步骤来修复问题。
为什么 TDSP 适用于数据科学
以下是 TDSP 在数据科学项目中效果良好的原因:
-
TDSP 捕捉了大多数数据科学项目中的基本步骤和依赖关系。
-
数据科学是一个迭代的过程,我们经常在项目的不同阶段发现新信息。
-
TDSP 设计用于包含多个角色的数据科学团队,这些角色包括纯机器学习之外的技能,如数据工程和软件工程。
-
TDSP 从业务需求和数据开始,然后进入模型开发。
-
TDSP 允许数据科学团队适应不断变化的需求以及数据分析、建模和部署步骤中的意外结果。
总结
尽管敏捷原则通常应用于软件开发,但我们也可以认为这些原则在数据科学项目中更为重要。微软的团队数据科学过程(TDSP)是一个将敏捷原则应用于数据科学的框架,围绕五步数据科学生命周期进行设计。TDSP 设计良好,能够反映大多数数据科学项目的阶段,并允许数据科学团队使用迭代方法适应变化。
加入我的邮件列表
加入我的 邮件列表 以获取有关我数据科学内容的更新。你还可以在 注册 时免费获得我的 解决机器学习问题的逐步指南!你也可以通过 Twitter 关注我以获取内容更新。
同时,你也可以考虑 加入 Medium 社区,阅读来自其他成千上万位作者的文章。
来源
- 微软 Azure 团队,什么是团队数据科学过程?,(2020),团队数据科学过程文档。