如何与非数据人士讨论数据和分析
原文:
towardsdatascience.com/how-to-talk-about-data-and-analysis-to-non-data-people-2457dc600219
面向数据专业人员的逐步教程
·发表于 Towards Data Science ·14 分钟阅读·2023 年 9 月 22 日
–
数字盲症是新的文盲
在我最近的 文章 中,我指出今天许多公司面临的一个重大挑战是可用数据的庞大数量和它们在决策中有效使用数据的能力有限。这个问题的核心主要是人为因素。因此,迫切需要建立 数据素养。如果公司真心希望从海量数据中受益,它们必须提升整体的数字能力。
88% 的潜在受众可能在阅读数字、图表或计算时感到困难。
根据全球识字研究,仅有 12% 的成年人在数字方面具备基本能力。这意味着88% 的潜在受众可能在阅读数字、图表或计算时感到困难。¹ 这与全球的识字率形成鲜明对比,后者目前超过 86%。²
值得注意的是,许多社会忽视了这个问题。更有甚者,许多人对自己的数字盲症感到自豪。³ 你是否听过这样的借口:
-
我不是一个擅长数字的人。
-
统计学从未引起过我的兴趣。
-
物理学对我而言似乎像巫术。
或者是“终极”的:
- 我更倾向于人文学科。
这真的算是一个有效的借口吗?
通常,这不是能力不足的问题,而是缺乏合适的工具。考虑一下这种情况:
我们尝试过马路。我们观察到交通从两个方向接近。我们必须判断是否有足够的时间安全过马路。远处的那辆车呢?它的速度有多快?它的速度是在增加吗?在减少吗?司机注意到我们了吗?
来源:作者提供的图片
实际上,过马路是一个复杂的概率挑战。然而,我们每天都会处理这个问题,通常会多次进行,并且通常能做对。⁴
这只是冰山一角。
想想以 60 英里每小时的速度驾驶汽车。涉及多少因素?驾驶时,你还在监控速度计和各种其他仪器。这与解读管理仪表板上的复杂视觉信息并无不同。再说早上选择穿什么衣服。你在做出判断和预测,这些都是即使是复杂的 AI 工具也会面临的挑战:预测天气,判断流行趋势,以及搭配颜色。
人脑每天处理大约 74 GB 的数据。⁵ 值得注意的是,它仍然能做出决策。与此同时,我的 ChatGPT 在处理一个 20 万行的 Excel 电子表格时出现了问题。
来源:图片由 Alexander Wivel 提供,CC BY 3.0,链接。
使用“人文主义者”标签也不是一个有效的借口。考虑拆解复杂的文学作品,比如诗歌。或者处理深奥的哲学难题?或者拼凑复杂的历史战斗计划?这些任务往往比构建统计模型更具挑战性。
我为什么提到这些?我的观点是,不算数的情况通常并不是由于能力的缺乏。而是由于缺乏工具和无效的沟通。
讽刺的是,许多声称不懂统计的人在日常任务中表现出处理复杂概率评估和决策的能力。
为什么我们在沟通中使用数据?
有效的沟通在商业中至关重要;整合数据分析可以提升它。以下是方法:
-
提高意识: 使用数据突出问题,解释其原因,提出解决方案,并预测结果。
-
强调重要性: 数据客观地排序,指导决策,例如先处理哪些项目。
-
证明因果关系: 企业常常混淆相关性和因果关系。只有合适的数据工具才能澄清这一点。
-
讲故事的基础: 使用数据来构建叙事,提供背景,阐明问题,并得出结论。
-
预测能力: 许多公司依赖直觉进行情景规划。这是一种有风险的方法。数据提供了更清晰的前进路径。⁶
谁应该负责讨论数据?
在观看了许多 YouTube 视频和阅读了无数文章后,我能给出的简单答案是“数据科学家”。但这并不正确。请允许我详细说明我的理由。
来源:图片由作者基于 Rebecca Nugent | TEDxCMU 制作:我们都是数据科学家。
你看到上面图片中的独角兽了吗?从理论上讲,它代表了“完美的数据科学家”,具备硬技能和软技能的最佳结合。 然而,找到这样的人才就像寻找真正的独角兽一样困难。当你找到时,确保你的口袋足够深。
过分依赖这些稀有的人才有其风险。许多企业在这些顶级人才转向新机会时面临挫折。组织如何减轻这一风险? 可以在整个团队中培养这些结合的技能,而不是集中在一个人身上。 我将介绍一个关于小团队的简短案例研究,以更好地说明我的观点。
小案例研究:数据科学家和业务分析师之间的合作
方法论
这个小案例使用 ChatGPT Plus 和高级数据分析准备。具体来说,我利用它创建了合成数据和数据可视化。
设置
设想一个由数据科学家(DS)和业务分析师(BA)组成的小团队。他们的任务是探查和阐明零售公司日常销售中的不规律现象,该公司主要依赖店内购买。
合作模型
第 1 步: 数据科学家(DS)与业务分析师(BA)合作,精炼问题范围,确定分析的数据,建立时间框架,并选择最有效的沟通方式。
第 2 步: 然后数据科学家(DS)开始分析,过程如下:
来源:作者根据数据分析过程步骤制作的图片
第 3 步。 数据科学家(DS)采用结合移动平均和标准差的方法。这有助于检测销售数据中的异常。一个数据点超出设定的阈值(距离移动平均 2 个标准差)被标记为异常。
第 4 步。 完成后,数据科学家(DS)将发现传达给业务分析师(BA)。
来源:作者使用 ChatGPT 和高级数据分析生成的图片
第 5 步。 业务分析师(BA)解读异常:
-
我们店内的促销(第 50–60 天,2 月底): 这里的销售上升可能是由于店内促销,导致顾客访问和购买增加。
-
竞争对手的新店开张(第 150–160 天,6 月初): 附近的新店可能吸引了一些我们的顾客,导致我们的销售额下降。
-
临时店铺关闭(第 250–260 天,9 月中旬): 9 月份销售显著下降,表明我们的一家门店可能因翻修或意外事件暂时停止运营。
-
另一个促销活动(第 320–330 天,11 月下旬): 这个时期销售的激增可能源于我们店内的另一个促销或销售活动。
第 6 步。 业务分析师(BA)和数据科学家(DS)一起审查发现。这种合作使数据科学家(DS)获得业务方面的见解,同时业务分析师(BA)提升数据处理能力。
第 7 步。在相关建议的补充下,最终的分析结果会呈现给相关利益相关者。
结论
这个简洁的案例研究强调了数据科学家与业务分析师之间的协同关系。数据科学家专注于通过统计技术进行异常检测,而业务分析师则将这些发现置于背景中,描述潜在原因并提供实际见解。正如所示,两个角色之间的强大沟通对这一协作的成功至关重要。
就像那些“没有数学能力”的人可能会避开数字和图表一样,“有数学能力”的人常常也会犹豫参与人际互动。
沟通也是一门科学
就像那些“没有数学能力”的人可能会避开数字和图表一样,“有数学能力”的人常常也会犹豫参与人际互动。
你知道吗?这是一个极其不公正的刻板印象。
虽然我认识一些能够轻松沟通的数学能力强的人,即使你是一个内向的数学能力强者,你也可以利用你的技能,将沟通视为一种方法论,就像任何统计挑战一样。
沟通可以提炼为三个主要组成部分:
来源:基于沟通的谁、为什么、怎么做和什么的作者图片
这个简单的模型不仅是一种结构化沟通的方法。它还为我的演示提供了一个即时的结构,我可以始终如一地应用它。
现在,让我提供一些关于如何处理这三个组成部分的一手指导。
WHY: 关注他人
背景至关重要,正如我最新的一篇文章所示。背景对叙述的影响高达 80%。故事的背景涵盖三个核心方面:情境、功能和数据驱动。这些基础信息为叙述者和听众提供了准备,解答了关于故事受众、核心主题和传达方式的关键问题。拥抱并融入背景对于故事与其目标听众的连接和理解至关重要。
数据专业人员常见的一个疏忽是过于依赖技术语言。这种情况很容易发生,尤其是当我们忽视上下文时。例如,针对特定观众使用某些术语是否合适?如*“cohort”或“longitudinal”这样不常在学术界外使用的短语,以及“surveillance”这样解释多样的术语,可能会引起困惑。类似地,“probability”或“risk”*这样的概念也可能被误解。如果这些术语不可或缺,尽量以易于理解的方式呈现。即便详细的论点制作得再精细,也应避免陷入细节的泥潭。理解许多人基于直觉捷径而非逻辑模型进行操作是有益的,这些捷径受到诸如锚定效应、误解因果关系、忽视随机性等偏见的影响。⁶
如何:编写好的故事
精心编写的故事在企业沟通中的影响显而易见,特别是当有数据支持时。但在这次讨论中,我想深入探讨这些故事是如何构建的。考虑一下Brent Dykes所倡导的叙事弧。
来源:作者基于Brent Dykes 的帖子的图片
漫长的开头可能会毁掉使用数据的故事。 这可能是故意的,也可能是无意的。例如,观众可能突然缩短了一个精心组织的故事,导致我们不得不对其进行删减。有时只是因为故事计划得不好。我们如何避免这些问题呢?
Cole Nussbaumer Knafflic,全球畅销书的著名作者⁷,推荐了一种方法:3 分钟故事。
考虑制作一个简洁的、3 分钟的演讲版本。这种方法有两个好处。首先,它作为备用方案,以防你分配的时间意外减少到仅有的 3-5 分钟。其次,它作为一个完善工具。如果你能有效并快速地将演讲缩减到 3 分钟,从完整版本中剔除多余内容就会变得轻而易举。
排练
我建议的另一种策略是排练。尽可能地练习你的演讲,最好是大声朗读。虽然在镜子前排练是有益的,但请可信的同事提供反馈可能更有价值。
如何:使用类比
类比是将两个事物进行类比,通常用于阐明或澄清。例如,考虑我之前使用的“过马路”例子。使用类比时,我们旨在通过更熟悉的场景来揭示复杂的分析。
来源:作者基于数据讲故事:类比的力量的图片
类比背后的概念是将视角从具体的数据项目转移到一个更广泛、更熟悉的背景中,在那里解释,然后再将理解带回到原始数据背景中。类比作为有用的连接器,将复杂的数据主题与日常情况联系起来,使其更易于理解。要制作有意义的类比,重要的是深入理解数据,脑暴相关的情境,评估其适用性,然后重新聚焦于数据的核心问题。
那么,在哪里可以找到好的类比呢? 现实生活中的例子往往能够准确打击目标。然而,挑战在于当需要时能够随手拿到它们。一个现代解决方案是咨询 ChatGPT 以获得创意建议。以下,我提供了与之前讨论的迷你案例研究相关的类比示例。
来源:作者截图
另一种策略需要更多的投入:持续收集和存储类比想法。 这可以是一个实体笔记本、一个数字平板或任何适合你的方法。关键是保持这些笔记有条理并且触手可及。
然而,关于类比还有一个警示点。 过度延伸类比的风险。你对背景越不熟悉,你偏离的可能性就越大。如果人们认为比较过于简单、粗鲁或幼稚,这可能会成为问题。
不要让你的观众感觉像幼儿园的孩子一样。 来源:作者图像
如何:注意时间安排
为了管理时间问题,我为自己设定了一个指导方针。通常,我为每张幻灯片分配大约 1.5 分钟用于复杂的数据驱动型演示文稿,包括标题、议程、休息幻灯片等。我不区分内容丰富的幻灯片和较为简洁的幻灯片。在较长的演示文稿中,这种做法往往能达到平衡。对于不那么复杂的演讲,其中幻灯片的数据量较少,我可能将时间减少到每张幻灯片 1 分钟。在这种情况下,我总是优先提前排练这些演示文稿。有时,这种减少是基于之前的排练估算出来的。
如果给定了具体的时间,例如 15 分钟,特别是针对高级管理人员的演示文稿,我使用以下公式来确定最大幻灯片数量:
最优幻灯片数量公式。
Nslides
表示演示文稿中的最大幻灯片数量(四舍五入到最接近的整数值)。Tminutes
是分配的时间。对于少于十张幻灯片的简短演示文稿,我省略了议程或问答幻灯片。
对于 15 分钟的时间段,这个公式允许我制作最多 7 张幻灯片。因此,我会将我的演示结构为一个标题幻灯片,接着最多 6 张内容幻灯片。这将分解为一个背景幻灯片,最多四个分析幻灯片,以及一个专门用于主要结论和行动呼吁(CTA)的幻灯片。如有必要,我可能会略微调整这个分配,也许为 CTA 保存一个独立的幻灯片。
为什么要如此简洁?通常这样就足够了。此外,我们还需要考虑到不可预见的情况,例如:
-
连接显示设备的时间延长
-
主要参与者迟到
-
分配时间用于积极讨论
-
任何其他不可预见的中断或延迟。
如何:关注数字
一个关键的方面是我们展示数字的方法。为了说明这一点,我将提供一个示例。首先,让我们查看“错误的”图表。
来源:作者提供的图片
现在是修正后的版本。
来源:作者提供的图片
看出区别了吗?
第二张图展示了**“有效数字”**的指南。从我的经验来看,三个似乎是显示数字的最佳数量。使用两个数字虽然很诱人,但对于像公司收入这样的关键数据,有过度简化的风险,可能会误导。
然后是**“友好数字”**原则。它涉及以最简单、最易记的方式呈现数字。例如,与其详细说明 USD 2,954,321.51,我们可能会四舍五入到大约 USD 3 百万。但使用这种方法时要小心:这可能会无意中扭曲数据,从而误导受众。
如何:利用标题的力量
标题在数据驱动的讲述中扮演着至关重要的角色。一个引人注目的标题吸引了观众,并且通常提供了重要的见解,消除了从表格或图表中进行详细数据分析的需要。它使他们能够决定是否深入了解内容或等待更相关的信息。
在制作标题时,考虑利用新闻业和互联网中的**“力量词”**技巧。这些词汇能够巧妙地管理注意力和设定期望。例如,“迅速的胜利”,“唯一可行的解决方案”或“项目中的红旗”可能具有很大的影响力。然而,使用力量词时需谨慎:如果我们最初将一个解决方案呈现为简单快捷,但随后的内容揭示了复杂的挑战,我们的可信度可能会受到影响。
此外,避免使用纯技术性的标题,例如“报告给 IT 的事件数量”。相反,选择 功能性标题,提供背景信息,例如*“实施后,报告的事件数量增加。”* 这能确保你的受众能够迅速理解内容的相关性和影响。
如何:战略性地使用颜色
颜色是数据驱动沟通中的强大工具。然而,它是一个需要负责任使用的工具。我们应抵制仅仅为了装饰目的使用颜色的诱惑。在所有情况下,颜色应具有功能性意义,突出关键信息。为说明这一点,让我们看看下面的图表。
装饰性使用颜色:
来源:作者提供的图像
战略(功能性)使用颜色:
HOW: 明智选择视觉效果
正如这篇文章中探讨的那样,三种可视化方式是可靠的,可以传达广泛的数据相关信息而不会引起混淆。虽然这个列表并不详尽,但遵循它会显著提高成功的可能性。
来源:作者提供的图像
使用这三种可视化方式:
-
柱状图(或条形图): 适用于比较累积或离散的值。可以用于趋势展示,前提是没有重大变化。
-
折线图: 有效展示方向和趋势的变化,特别适用于连续变量。多个折线可以在同一图表上进行比较。
-
饼图: 适合显示某部分对整体的贡献(例如,某一特定产品产生的收入占总销售额的百分比)。无论如何都要避免使用饼图进行比较!
来源:作者在 Adobe Photoshop 2024 中生成的图像
创建图表时,遵循上述规则(例如,颜色和标题),并考虑适当的缩放(特别是纵轴,通常应从 0 开始,除非有充分理由)。通过去除框架、网格线、坐标轴标签或图例等多余元素来简化图表。
WHAT: 使用 CTA
本文的最后一条建议是使用行动号召(CTA)。
没有 CTA,我们的演示最多只能是一个引人入胜的或许有趣的信息。一个精心制作的 CTA 赋予数据驱动的讲故事以独特的特征。
什么使 CTA 有效?
-
使用主动语态而非被动语态。
-
小心使用祈使句。
-
清楚地识别出负责执行商定行动的个人或团队。
-
在演示后立即跟进决策,并随后在短时间内进行跟进以确保进展。
结论
成功: 作者在 Adobe Photoshop 2024 中生成的图像
在数据沟通中,数字能力和数字盲之间存在显著差距。尽管全球只有 12%的成年人具备数字素养,大多数人却难以理解数据。然而,讽刺的是,许多自称数字盲的人在日常任务中展示了处理复杂概率评估和决策的能力。挑战不在于他们的固有能力,而在于传达数据所使用的工具和方法。
有效的沟通策略通过制作相关的类比、战略性地使用视觉效果和采用深思熟虑的叙事来弥合这一鸿沟。通过掌握观众的背景并减少技术术语,数据专业人士可以提高可及性。
最终,数据讲故事和沟通的核心在于简化复杂性、与观众建立联系,并推动可操作的洞见。无论你是数据科学家还是商业分析师,关键在于使用观众的语言进行对话,确保数据的力量保持清晰。
你喜欢这篇文章吗?考虑订阅以获取我发布的新故事通知或关注我。
资源
-
安·怀利:各国的数字能力水平是多少?
-
世界人口审查:2023 年各国识字率
-
密苏里科技大学:数字盲:误传的结果
-
丽贝卡·纽金特 | TEDxCMU:我们都是数据科学家
-
奇思妙想:人脑每天学习多少信息?
-
国家癌症研究所:让数据发声:一本工作手册
-
科尔·努斯鲍默·克纳夫利克:用数据讲故事:商业专业人士的数据可视化指南
如何使用 Pytest 测试您的 Python 代码
原文:
towardsdatascience.com/how-to-test-your-python-code-with-pytest-c8f055979dd7
编程,Python
简化您的测试过程,并通过 Pytest 提升代码质量
·发布在 Towards Data Science ·5 分钟阅读·2023 年 6 月 1 日
–
作者提供的图像
您是否厌倦了花费几个小时调试代码和修复那些本可以轻易避免的错误?我们知道当您的代码不能正确工作时,尤其是在需要迅速交付结果的压力下,这会让人感到非常沮丧。但是别担心!有一个解决方案:Pytest。
Pytest 是一个强大的测试框架,帮助确保您的代码在不同的场景和条件下按预期工作。将 Pytest 集成到您的代码中可以帮助您在问题变成麻烦之前发现并修复错误,从而节省时间和精力。
在本文中,我们将向您展示如何开始使用 Pytest。从设置环境到编写覆盖所有代码的测试,我们为您提供了完整的指导。那么还等什么?让我们开始测试,确保您的代码每次都能完美运行。
我们将涵盖:
-
Pytest 概述
-
实际示例
让我们从 Pytest 的概述开始描述。
Pytest 概述
Pytest 是一个关注简单性和易用性的 Python 测试框架。要安装 Pytest,请运行以下命令:
$ pip install pytest
Pytest 遵循模块化和可扩展的架构,允许开发人员将测试组织成单独的测试函数或类。
当您使用 Pytest 构建测试时,必须遵循以下步骤:
-
创建一个新的脚本
test_<mytest>.py
用于您的测试。将 Pytest 导入到脚本中。 -
定义您的测试函数:测试函数是一个 Python 函数,用于验证代码行为的特定方面。每个测试函数应该是自包含的,专注于单个测试用例。Pytest 会自动发现并执行这些测试函数。
-
测试命名规范:每个测试函数必须以
test_
开头,以便 Pytest 正确识别它。 -
测试断言:使用测试断言来定义函数的行为。Pytest 提供了广泛的强大断言函数。
-
测试夹具:夹具是提供可重用和预配置的资源或测试数据的函数,供你的测试函数使用。
一些资产函数列表
下面是 Pytest 提供的一些主要断言:
-
assert
:通过检查给定条件是否为真来进行简单断言。 -
assertEqual
:比较两个值的相等性。它检查期望值是否等于实际值。 -
assertTrue
和assertFalse
:验证给定条件是否为真或假。 -
assertRaises
:检查在执行代码时是否抛出特定异常。 -
assertIn
和assertNotIn
:验证值是否在给定集合或序列中存在或不存在。 -
assertAlmostEqual
:将浮点值与指定的精度进行比较。 -
assertDictEqual
:检查两个字典是否具有相同的键值对集合。 -
assertRaisesRegex
:验证是否抛出特定异常,并且异常消息是否匹配正则表达式模式。
现在你已经了解了 Pytest 背后的基本概念,让我们进入实际示例。
实际示例
让我们设想构建一个计算器并测试其实现是否正确。首先,我们定义核心函数,然后编写测试。
核心函数
核心函数实现了计算器的操作。例如,我们可以编写以下简单代码来实现主要操作:
def add(a, b):
return a + b
def subtract(a, b):
return a - b
def multiply(a, b):
return a * b
def divide(a, b):
return a / b
将文件保存为 calculator.py
。
测试函数
在我们保存核心函数的相同目录中,添加一个名为 test_calculator.py
的脚本。首先,导入核心函数和 Pytest 库:
import pytest
from calculator import add
然后,为 calculator.py
文件中的每个函数添加测试。对于每个函数,添加一个单独的测试。例如,要测试 add()
函数,编写以下测试:
def test_addition():
result = add(2, 4)
assert result == 6
result = add(-1, 3)
assert result == 2
result = add(0, 0)
assert result == 0
类似地,你可以为其他函数编写测试。你可以在这个 GitHub 仓库中找到完整的示例。
要运行测试,打开终端,并从包含两个脚本的文件夹中运行以下命令:
pytest
你应该得到以下输出:
% pytest
================================================== test session starts ===================================================
platform darwin -- Python 3.8.10, pytest-7.1.3, pluggy-1.0.0
rootdir: /Users/angelica/CNR/Git/data-science/Tests/Calculator
plugins: typeguard-2.13.3, anyio-3.3.4
collected 4 items
test_calculator.py .... [100%]
=================================================== 4 passed in 0.02s ====================================================
使用测试夹具
让我们修改前面的示例以支持测试夹具。首先,创建一个新目录和一个名为 calculator.py
的新文件。将计算函数封装在一个类中:
class Calculator:
def __init__(self):
self.result = 0
def add(self, a, b):
self.result = a + b
return self.result
def subtract(self, a, b):
self.result = a - b
return self.result
def multiply(self, a, b):
self.result = a * b
return self.result
def divide(self, a, b):
self.result = a / b
return self.result
然后,在相同目录中创建另一个名为 test_calculator.py
的脚本。在脚本开始时导入 Pytest 和 Calculator
类:
import pytest
from calculator import *
使用 @pytest.fixture
装饰器定义一个名为 calculator
的夹具。夹具是提供可重用资源或设置操作的函数。在这种情况下,calculator
夹具创建了 Calculator
类的实例并返回它。
@pytest.fixture
def calculator():
# Create an instance of the calculator
calc = Calculator()
return calc
现在我们可以在测试中使用测试夹具 calculator
:
def test_multiplication(calculator):
result = calculator.multiply(4, 3)
assert result == 12
def test_division(calculator):
result = calculator.divide(10, 2)
assert result == 5
最后,运行测试:
pytest
你应该得到以下输出:
pytest
================================================== test session starts ===================================================
platform darwin -- Python 3.8.10, pytest-7.1.3, pluggy-1.0.0
rootdir: /Users/angelica/CNR/Git/data-science/Tests/CalculatorFixture
plugins: typeguard-2.13.3, anyio-3.3.4
collected 4 items
test_calculator.py .... [100%]
=================================================== 4 passed in 0.01s ====================================================
你可以在这个 GitHub 仓库中找到完整的示例。
总结
恭喜!你刚刚学习了如何使用 Pytest 为你的 Python 代码添加测试!将 Pytest 作为你的测试框架可以确保你的 Python 代码的可靠性和长期稳定性!
使用 Pytest 非常简单:你只需编写直观的测试函数!
你可能还感兴趣的是……
如何在 Docker 中删除镜像,从基础镜像重建镜像,将一些配置文件传递给 Docker……
medium.com ## 如何安装 Spark NLP
关于如何在本地计算机上使 Spark NLP 工作的分步教程
[towardsdatascience.com ## Python Pandas 数据清洗入门
一个使用流行的 Python 库进行数据清洗的实际示例。
[towardsdatascience.com
如何测试你的单元测试
原文:
towardsdatascience.com/how-to-test-your-unit-tests-afe18d6e19d8
单元测试
突变测试简介
·发表于 Towards Data Science ·阅读时长 5 分钟·2023 年 1 月 16 日
–
图片由 Erik Mclean 提供,来自 Unsplash
在我上一篇文章中,我讲述了单元测试如何成为数据科学家工作中的一个重要方面,因为错误的代码会导致分析结果出现问题。提高单元测试的一种方法是将属性驱动测试与示例驱动测试结合使用,即常规的单元测试方式。你可以在这里查看我上一篇文章:
Python 中使用 Hypothesis 进行属性驱动测试的指南
towardsdatascience.com
在发布这篇文章后,我收到了来自**.com 软件的回应,向我推荐了突变测试**,我今天想向你解释一下。长话短说:
突变测试可以帮助你发现弱测试。
弱测试是那些给你错误安全感的测试,因为它们即使明知道不该通过也会通过,其中最典型的就是assert True
。替换这些测试可以使你的整个测试套件更有意义和可信。
现在,让我们深入了解一下这是什么吧!
弱测试
考虑这个非常简单的函数:
def mean(x, y):
return (x+y) / 2
假设你想编写单元测试,尽管这个函数非常简单。一个test_mean.py 文件可能如下所示:
def mean(x, y):
return (x+y) / 2
def test_mean():
assert mean(4, 0) == 2
调用pytest test_mean.py
当然会导致测试通过。一切都是绿色的,我们甚至达到了 100%的覆盖率!是时候继续下一个功能了,对吧?不!
让我们仔细看看测试代码中的断言:函数的第二个参数是零,这意味着函数中的y
基本上被忽略了。输入具有特殊的形状,使测试比预期更容易通过。例如,如果函数是
def definitely_not_the_mean(x, y):
return (x-y) / 2 # test_mean still passes
即使在这种简单的函数变异——将加号改为减号——test_mean
仍然通过。
这不应该发生,如果测试足够好,它应该在我们更改函数定义时失败!
像这样的测试就像一个金属探测器,即使面对木材也会发出声音。这就是为什么我们称test_mean
为薄弱的测试。
这个薄弱的测试在这里可能很容易被发现,但如果你写的代码稍微复杂一些,你可能会意外地创建出薄弱的示例却没有注意到,从而给你一种虚假的安全感。
变异测试
我们可以使用变异测试来发现薄弱的测试。变异测试的理念已经相当古老:它最初由理查德·利普顿在 1971 年作为学生提出。它也非常简单,实际上我在上一章已经简单介绍过了。
对你想要测试的函数源代码进行小的修改,并查看测试是否仍然通过。如果它们通过了,那它们就是薄弱的。如果它们失败(并且原函数没有失败),它们幸存下来并可能是强的。
你已经看到了一个变异,即从 + 变为 -。此外,你还可以改变:
-
- 改为 +
-
/ 改为 * 或反之亦然,
-
≥ 改为 > 或者 <,
-
≤ 改为 < 或者 >
-
= 改为 != 或反之亦然
-
从整数中加减 1
-
向字符串中添加一些随机字符
-
…
你明白了吧。只需简单的调整,仍然生成有效的源代码,将你想要测试的原函数变成稍微不同的东西。
当然,你可以手动完成这些操作,几次更改源代码,每次之后都运行一次pytest
。但因为这没有趣味,有人创建了一个包来自动完成这项工作并记录结果。
Mutmut 方便的变异测试
Anders Hovmöller aka boxed和许多其他贡献者创建了一个名为mutmut的包来为你完成这项工作。
首先,通过pip install mutmut
安装它。然后,你需要将你想要测试的函数提取到一个文件中,我们称之为function.py。我们还假设测试在test_mean.py中。然后你可以调用
mutmut run --paths-to-mutate function.py
它将创建一些包含我们想要测试的mean函数的function.py的变异。
如果你在 mutmut 运行时在一个会不断重新加载文件的编辑器中打开 function.py ,你甚至可以看到文件如何实时变化!但不用担心:mutmut 会在进行修改之前先创建原始文件的副本。
输出将如下所示:
图片由作者提供。
你可以在这里看到几个方面,尤其是在底部:
-
创建了三个突变体。(旁注:+变为-,/变为,在我们的案例中是 2 变为 3*)
-
这三个突变体中的两个被杀死,意味着之前通过的单元测试在文件更改后失败了,这很好 🎉。
-
一个突变体幸存了,这意味着尽管源代码发生了变化,测试仍然通过。这很糟糕 🙁。我们已经看到过这个幸存者:
def mean(x, y):
return (x-y) / 2 # the surviving mutant
你还可以通过 mutmut html
创建一个 HTML 报告并在浏览器中打开:
图片由作者提供。
设计可以更好,但它包含了关于幸存者的主要信息。
注意: 有时两个较弱的单独测试可以形成一个更好的测试套件。例如,如果你添加了断言
*assert mean(-1, 1) == 0*
— 另一个较弱的测试,因为突变体*return (x+y) * 2*
将幸存 — 总的来说,没有突变体会幸存于 mutmut 的程序,从而改进测试套件。
结论
在本文中,我们看到通过测试甚至 100%的测试覆盖率可能会令人误解。通过的测试很好,但如果即使在更改被测试函数后仍然通过,这可能是一个红旗,表明测试可能较弱。
突变测试提供了一种结构化的方式来更改(突变)函数。Python 库 mutmut 甚至允许我们自动更改源代码(事先创建了备份),并检查哪些测试在突变后仍然通过(🙁),哪些测试失败(🎉)。
这使你的测试套件更加健壮,从而让你生成正确的代码,这对于无错误分析是必要的。
我希望你今天学到了新的、有趣的、有用的东西。感谢阅读!
最后一点,如果你
-
想支持我写更多关于机器学习的内容和
-
计划无论如何获得一个 Medium 订阅,
为什么不通过 这个链接支持我呢?这对我帮助很大!😊**
为了透明起见,对你来说价格不会改变,但约一半的订阅费用直接归我。
非常感谢,如果你考虑支持我!
如果你有任何问题,请在 LinkedIn上写信给我!
如何使用 Gensim 从头开始训练 Word2Vec 模型
原文:
towardsdatascience.com/how-to-train-a-word2vec-model-from-scratch-with-gensim-c457d587e031
在本文中,我们将探索 Gensim,这是一种非常流行的 Python 库,用于训练基于文本的机器学习模型,以从头开始训练一个 Word2Vec 模型
·发表于 Towards Data Science ·9 分钟阅读·2023 年 2 月 6 日
–
作者提供的图像。
Word2Vec 是一个机器学习算法,它允许你创建单词的向量表示。
这些表示被称为嵌入,在许多自然语言处理任务中使用,如单词聚类、分类和文本生成。
Word2Vec 算法标志着自然语言处理(NLP)世界的一个时代的开始,它在 2013 年由 Google 首次介绍。
它基于通过神经网络训练的非常大的数据语料库创建的单词表示。
Word2Vec 的输出是向量,每个向量对应训练词典中的一个单词,有效地捕捉了单词之间的关系。
在向量空间中相互接近的向量基于上下文具有相似的含义,而相距较远的向量具有不同的含义。例如,“强大”和“雄伟”这两个词在向量空间中会很接近,而“强大”和“巴黎”这两个词则会相对远离。
这比基于简单计算文本数据语料库中存在的标记的袋装单词模型性能有了显著改进。
在本文中,我们将探索 Gensim,这是一种流行的 Python 库,用于训练基于文本的机器学习模型,以从头开始训练一个 Word2Vec 模型。
我将使用我个人博客中的意大利语文章作为本项目的文本语料库。 随意使用你希望的任何语料库——这个流程是可扩展的。
这种方法适用于任何文本数据集。你将能够自己创建嵌入向量并进行可视化。
让我们开始吧!
项目要求
让我们列出一些行动步骤,这些步骤将作为项目的基础。
-
我们将创建一个新的虚拟环境。
(阅读这里以了解如何操作:如何为机器学习设置开发环境)
-
安装依赖项,其中包括 Gensim
-
准备我们的语料库以交给 Word2Vec
-
训练模型并保存它
-
使用 TSNE 和 Plotly 来可视化嵌入,以便直观理解 Word2Vec 生成的向量空间。
-
附加:使用 Datapane 库创建一个互动 HTML 报告,与我们想要分享的人共享
到文章结尾时,我们将拥有一个很好的基础,以便开展更复杂的推理,例如嵌入的聚类等。
我假设你已经正确配置了你的环境,所以在这篇文章中我不会解释如何操作。我们直接开始下载博客数据吧。
依赖项
在开始之前,我们需要通过在终端中运行pip install XXXXX
来确保安装以下项目级别的依赖。
-
trafilatura
-
pandas
-
gensim
-
nltk
-
tqdm
-
scikit-learn
-
plotly
-
datapane
我们还将初始化一个logger
对象,以便在终端接收 Gensim 消息。
获取语料库数据
如前所述,我们将使用我个人博客中的意大利语文章(diariodiunanalista.it)作为我们的语料库数据。
在 Deepnote 中它的样子是这样的。
我们以 pandas 数据框格式收集的数据。图片来源于作者。
我们将要使用的文本数据位于article列中。让我们看看随机文本的样子。
无论语言如何,这些数据在交给 Word2Vec 模型之前都应进行处理。我们需要去除意大利语停用词,清理标点符号、数字和其他符号。这将是下一步。
数据语料库的准备
首先需要导入一些用于预处理的基本依赖。
# Text manipulation libraries
import re
import string
import nltk
from nltk.corpus import stopwords
# nltk.download('stopwords') <-- we run this command to download the stopwords in the project
# nltk.download('punkt') <-- essential for tokenization
stopwords.words("italian")[:10]
>>> ['ad', 'al', 'allo', 'ai', 'agli', 'all', 'agl', 'alla', 'alle', 'con']
现在让我们创建一个preprocess_text
函数,它接收一些文本作为输入并返回一个干净的版本。
def preprocess_text(text: str, remove_stopwords: bool) -> str:
"""Function that cleans the input text by going to:
- remove links
- remove special characters
- remove numbers
- remove stopwords
- convert to lowercase
- remove excessive white spaces
Arguments:
text (str): text to clean
remove_stopwords (bool): whether to remove stopwords
Returns:
str: cleaned text
"""
# remove links
text = re.sub(r"http\S+", "", text)
# remove numbers and special characters
text = re.sub("[^A-Za-z]+", " ", text)
# remove stopwords
if remove_stopwords:
# 1\. create tokens
tokens = nltk.word_tokenize(text)
# 2\. check if it's a stopword
tokens = [w.lower().strip() for w in tokens if not w.lower() in stopwords.words("italian")]
# return a list of cleaned tokens
return tokens
让我们通过使用带有.apply
的 lambda 函数将这个函数应用到 Pandas 数据框中。
df["cleaned"] = df.article.apply(
lambda x: preprocess_text(x, remove_stopwords=True)
)
我们得到了一个干净的系列。
每篇文章都经过了清理和分词处理。图片来源于作者。
让我们检查一下文本,看看我们预处理的效果。
单个清理后的文本的样子。图片来源于作者。
现在文本看起来已经准备好被 Gensim 处理了。我们继续。
Word2Vec 训练
首先要做的是创建一个变量texts
,它将包含我们的文本。
texts = df.cleaned.tolist()
现在我们准备好训练模型了。Word2Vec 可以接受许多参数,但现在我们不必担心这些。训练模型非常简单,只需要一行代码。
from gensim.models import Word2Vec
model = Word2Vec(sentences=texts)
Word2Vec 训练过程。图片来源于作者。
我们的模型已经准备好,并且嵌入已经创建。为了测试这一点,让我们尝试找出单词overfitting的向量。
“overfitting”一词的词嵌入。图像来源:作者。
默认情况下,Word2Vec 创建 100 维的向量。这个参数可以更改,还有许多其他参数,在我们实例化类时进行设置。无论如何,关联的维度越多,神经网络对单词本身及其与其他单词关系的了解就越多。
显然,这具有更高的计算和内存成本。
请注意:Word2Vec无法为词汇表中未出现的单词生成向量(称为 OOV — 词汇外单词)是其最重要的限制之一。
W2V 的一个主要限制是无法为词汇外单词映射嵌入。图像来源:作者。
因此,为了处理新单词,我们必须训练一个新模型或手动添加向量。
计算两个单词之间的相似度
使用余弦相似度,我们可以计算向量在空间中的距离。
使用下面的命令,我们指示 Gensim 查找与overfitting最相似的前三个单词
model.wv.most_similar(positive=['overfitting'], topn=3))
与“overfitting”最相似的词。图像来源:作者。
让我们看看单词“when”(quando 在意大利语中)在这个结果中是如何呈现的。将类似的副词包含在停用词中以清理结果会比较合适。
要保存模型,只需执行model.save("./path/to/model")
。
使用 TSNE 和 Plotly 可视化嵌入
我们的向量是 100 维的。除非我们做些事情来减少它们的维度,否则可视化它们是个问题。
我们将使用 TSNE,这是一种降低向量维度的技术,并创建两个组件,一个用于 X 轴,另一个用于 Y 轴上的散点图。
在下面的.gif 中,你可以看到感谢 Plotly 功能嵌入在空间中的单词。
我的意大利博客的嵌入在 TSNE 投影中呈现的效果。图像来源:作者。
这是生成此图像的代码。
def reduce_dimensions(model):
num_components = 2 # number of dimensions to keep after compression
# extract vocabulary from model and vectors in order to associate them in the graph
vectors = np.asarray(model.wv.vectors)
labels = np.asarray(model.wv.index_to_key)
# apply TSNE
tsne = TSNE(n_components=num_components, random_state=0)
vectors = tsne.fit_transform(vectors)
x_vals = [v[0] for v in vectors]
y_vals = [v[1] for v in vectors]
return x_vals, y_vals, labels
def plot_embeddings(x_vals, y_vals, labels):
import plotly.graph_objs as go
fig = go.Figure()
trace = go.Scatter(x=x_vals, y=y_vals, mode='markers', text=labels)
fig.add_trace(trace)
fig.update_layout(title="Word2Vec - Visualizzazione embedding con TSNE")
fig.show()
return fig
x_vals, y_vals, labels = reduce_dimensions(model)
plot = plot_embeddings(x_vals, y_vals, labels)
这种可视化有助于识别数据中的语义和句法倾向。
例如,这非常有助于指出异常,如因某种原因倾向于聚集在一起的单词组。
Word2Vec 的参数
通过检查 Gensim 网站,我们可以看到 Word2Vec 接受许多参数。最重要的参数包括vectors_size
、min_count
、window
和sg
。
-
vectors_size : 定义了我们向量空间的维度。
-
min_count: 训练前,会将频率低于 min_count 的单词从词汇表中移除。
-
window: 句子中当前词与期望词之间的最大距离。
-
sg:定义训练算法。0 = CBOW(连续词袋),1 = Skip-Gram。
我们不会详细讨论每一个。我建议感兴趣的读者查看Gensim 文档。
我们尝试使用以下参数重新训练我们的模型。
VECTOR_SIZE = 100
MIN_COUNT = 5
WINDOW = 3
SG = 1
new_model = Word2Vec(
sentences=texts,
vector_size=VECTOR_SIZE,
min_count=MIN_COUNT,
sg=SG
)
x_vals, y_vals, labels = reduce_dimensions(new_model)
plot = plot_embeddings(x_vals, y_vals, labels)
基于 Word2Vec 新参数的新投影。图片由作者提供。
表示发生了很大变化。向量的数量与之前相同(Word2Vec 的默认值为 100),而min_count
、window
和sg
已从默认值进行了更改。
我建议读者更改这些参数,以了解哪种表示更适合自己的情况。
奖金:使用 Datapane 创建一个互动报告
我们已经到了文章的结尾。我们通过创建一个 HTML 格式的互动报告,利用 Datapane 使用户能够在浏览器中直接查看之前用 Plotly 创建的图表来结束这个项目。
使用 Datapane 创建的互动报告。图片由作者提供。
这是 Python 代码
import datapane as dp
app = dp.App(
dp.Text(text='# Visualizzazione degli embedding creati con Word2Vec'),
dp.Divider(),
dp.Text(text='## Grafico a dispersione'),
dp.Group(
dp.Plot(plot),
columns=1,
),
)
app.save(path="test.html")
Datapane 高度可定制。我建议读者查阅文档,以便整合美学和其他功能。
结论
我们已经看到如何使用 Gensim 和 Word2Vec 从头构建嵌入。如果你有结构化的数据集,并且知道 Gensim 的 API,这个过程非常简单。
使用嵌入我们可以做很多事情,例如
-
做文档聚类,在向量空间中展示这些聚类
-
研究单词之间的相似性
-
将嵌入作为机器学习模型中的特征
-
为机器翻译奠定基础
等等。如果你对延伸至这里讨论主题的内容感兴趣,请留言告诉我 👍
通过这个项目,你可以丰富你的 NLP 模板组合,并向利益相关者展示你在机器学习背景下处理文本文件的专业知识。
下一篇文章 👋
如果你想支持我的内容创作活动,请随时通过下面的推荐链接关注我并加入 Medium 会员计划。我将获得你投资的一部分,同时你也能无缝访问 Medium 上大量的数据科学等相关文章。
[## 使用我的推荐链接加入 Medium - Andrea D’Agostino
阅读 Andrea D’Agostino(以及 Medium 上其他数千名作家的)每个故事。你的会员费用直接…
medium.com](https://medium.com/@theDrewDag/membership?source=post_page-----c457d587e031--------------------------------)
如何训练 BERT 进行掩码语言建模任务
原文:
towardsdatascience.com/how-to-train-bert-for-masked-language-modeling-tasks-3ccce07c6fdc
从零开始使用 Python 和 Transformers 库构建 MLM 任务语言模型的实用指南
Medium Towards Data Science
Ransaka Ravihara
·发表于 Towards Data Science ·阅读时长 7 分钟·2023 年 10 月 17 日
–
介绍
近年来,大型语言模型(LLMs)吸引了整个机器学习社区的关注。在 LLMs 出现之前,我们经历了一个重要的研究阶段,研究了各种语言建模技术,包括掩码语言建模、因果语言建模和序列到序列语言建模。
从上述列表来看,诸如 BERT 这样的掩码语言模型在分类和聚类等下游 NLP 任务中变得更加实用。由于 Hugging Face Transformers 等库的帮助,调整这些模型以适应下游任务变得更加可及和可管理。感谢开源社区,我们有大量的语言模型可以选择,涵盖了广泛使用的语言和领域。
本教程的 GitHub 仓库
GitHub [## GitHub - Ransaka/Train-BERT-for-Masked-Language-Modeling-Tasks: GitHub repo for TDS article "How to…
GitHub 仓库用于 TDS 文章 “如何训练 BERT 进行掩码语言建模任务” - GitHub …
微调还是从头开始构建?
在将现有语言模型适应于特定用例时,有时我们可以在不进一步调整(即所谓的微调)的情况下使用现有模型。例如,如果你需要一个英语情感/意图检测模型,你可以进入 HuggingFace.co 并找到适合你用例的模型。
然而,您只能对现实世界中遇到的一些任务抱有这种期望。这就是我们需要一种称为微调的额外技术的地方。首先,您必须选择一个将要微调的基础模型。在这里,您必须小心选择的模型和目标语言的词汇相似性。
然而,如果您找不到适用于所需语言的合适模型,请考虑从头开始构建一个。在本教程中,我们将实现用于掩码语言模型的 BERT 模型。
BERT 架构
尽管描述 BERT 架构超出了本教程的范围,但为了清晰起见,我们还是非常简略地介绍一下。BERT,或双向编码器表示来自变换器,属于仅编码器的变换器家族。它于 2018 年由 Google 的研究人员引入。
论文摘要:
我们介绍了一种新的语言表示模型,称为 BERT,代表双向编码器表示来自变换器。与最近的语言表示模型不同,BERT 旨在通过在所有层中共同考虑左右上下文来从未标记文本中预训练深度双向表示。因此,预训练的 BERT 模型可以通过添加一个额外的输出层来进行微调,从而创建广泛任务的最先进模型,如问答和语言推理,而无需对任务特定的架构进行 substantial 修改。
BERT 从概念上讲很简单,从经验上讲却非常强大。它在十一项自然语言处理任务中获得了新的最先进结果,包括将 GLUE 分数推高至 80.5%(绝对提高 7.7 个百分点),MultiNLI 准确率提升至 86.7%(绝对提高 4.6 个百分点),SQuAD v1.1 问答测试 F1 提升至 93.2(绝对提高 1.5 个点),以及 SQuAD v2.0 测试 F1 提升至 83.1(绝对提高 5.1 个点)。
在上面,我们可以看到一个有趣的关键词——双向。双向特性赋予了 BERT 类似于人类的能力。假设您需要填入一个像下面这样的空白,
“战争有时可能是一种必要的恶行。但无论多么必要,它始终是一种 _____,从来不是一种好事。”
要猜测单词填入空白位置,您需要注意以下几点:空白前的单词、空白后的单词,以及整个句子的上下文。根据这种人类特性,BERT 也以相同的方式工作。在训练过程中,我们隐藏一些单词,并要求 BERT 尝试预测这些单词。训练完成后,BERT 可以根据前后单词来预测被掩码的标记。为此,模型应对输入序列中的单词分配不同的注意力,这可能会显著影响对掩码标记的预测。
图片来源:作者,huggingface.co/spaces/exbert-project/exbert
如您所见,模型将适合隐藏位置的词视为 evil,并且将第一个句子的 evil 视为进行此预测所必需的。这是一个显著的点,表明模型理解输入序列的上下文。这种上下文感知使得 BERT 能够为给定任务生成有意义的句子嵌入。进一步,这些嵌入可以用于下游任务,如聚类和分类。说够了 BERT;让我们从头开始构建一个。
定义 BERT 模型
我们通常有 BERT*(base)* 和 BERT*(large)*。两者每个头部都有 64 维度。large 变体包含 24 个编码器层,而 base 变体只有 12 层。不过,我们并不局限于这些配置。令人惊讶的是,我们可以完全控制使用 Hugging Face Transformers 库定义模型。我们需要做的就是使用 BertConfig 类定义所需的模型配置。
我选择了 6 个头和 384 个总模型维度,以符合原始实现。这样,每个头都有 64 个维度,类似于原始实现。让我们初始化我们的 BERT 模型。
from transformers import BertConfig, BertForMaskedLM
config = BertConfig(
hidden_size = 384,
vocab_size= tokenizer.vocab_size,
num_hidden_layers = 6,
num_attention_heads = 6,
intermediate_size = 1024,
max_position_embeddings = 256
)
model = BertForMaskedLM(config=config)
print(model.num_parameters()) #10457864
训练标记器
在这里,我不会描述标记化的底层工作原理。相反,让我们使用 Hugging Face tokenizers 库从零开始训练一个标记器。请注意,原始 BERT 实现中使用的标记器是 WordPiece 标记器,这是一种基于子词的标记化方法。您可以通过下面的 HuggingFace 资源深入了解这种标记化。
## WordPiece tokenization — Hugging Face NLP Course
我们正在通过开源和开放科学来推进和普及人工智能。
这里使用的数据集是 Sinhala-400M 数据集 (under apache-2.0)。您可以使用任何您拥有的数据集来进行相同的操作。
正如您可能注意到的,有些僧伽罗语单词也用英语键入。让我们为这些语料库训练一个标记器。
首先让我们导入必要的模块。使用 Hugging Face Tokenizers 库训练标记器的好处是,我们可以使用现有的标记器并仅根据我们的训练语料库替换词汇表(并在适用时合并)。这意味着标记化步骤,如预标记化和后标记化,将被保留。为此,我们可以使用 train_new_from_iterator 方法来自 BertTokenizer 类。
from tokenizers.implementations import ByteLevelBPETokenizer
from tokenizers.processors import BertProcessing
from transformers import AutoTokenizer
from datasets import Dataset
import pandas as pd
#load base tokenizer to train on dataset
tokenizer_base = AutoTokenizer.from_pretrained("bert-base-cased")
# convert pandas dataset to HF dataset
dataset = Dataset.from_pandas(df.rename(columns={"comment":'text'}))
# define iterator
training_corpus = (
dataset[i : i + 1000]["text"]
for i in range(0, len(dataset), 1000)
)
#train the new tokenizer for dataset
tokenizer = tokenizer_base.train_new_from_iterator(training_corpus, 5000)
#test trained tokenizer for sample text
text = dataset['text'][123]
print(text)
# let's check tokenization process
input_ids = tokenizer(text).input_ids
subword_view = [tokenizer.convert_ids_to_tokens(id) for id in input_ids]
np.array(subword_view)
你可以看到像“cricketer”这样的词被分解为cricket和*##er*,这表明标记器已经经过充分训练。然而,可以尝试不同的词汇大小;我的词汇量是 5000,相对较小,但适合这个玩具示例。
最终,我们可以将训练好的标记器保存到我们的目录中。
tokenizer.save_pretrained("tokenizer/sinhala-wordpiece-yt-comments")
定义数据整理器并标记化数据集。
让我们定义一个用于 MLM 任务的整理器。在这里,我们将掩盖 15%的标记。无论如何,我们可以设置不同的掩盖概率。
from transformers import DataCollatorForLanguageModeling
data_collator = DataCollatorForLanguageModeling(
tokenizer=tokenizer, mlm=True, mlm_probability=0.15
)
让我们使用之前创建的标记器对数据集进行标记化。我用自定义类替代了原始的LineByLineTextDataset,利用了 Hugging Face accelerate。
import torch
from torch.utils.data import Dataset
from accelerate import Accelerator, DistributedType
class LineByLineTextDataset(Dataset):
def __init__(self, tokenizer, raw_datasets, max_length: int):
self.padding = "max_length"
self.text_column_name = 'text'
self.max_length = max_length
self.accelerator = Accelerator(gradient_accumulation_steps=1)
self.tokenizer = tokenizer
with self.accelerator.main_process_first():
self.tokenized_datasets = raw_datasets.map(
self.tokenize_function,
batched=True,
num_proc=4,
remove_columns=[self.text_column_name],
desc="Running tokenizer on dataset line_by_line",
)
self.tokenized_datasets.set_format('torch',columns=['input_ids'],dtype=torch.long)
def tokenize_function(self,examples):
examples[self.text_column_name] = [
line for line in examples[self.text_column_name] if len(line[0]) > 0 and not line[0].isspace()
]
return self.tokenizer(
examples[self.text_column_name],
padding=self.padding,
truncation=True,
max_length=self.max_length,
return_special_tokens_mask=True,
)
def __len__(self):
return len(self.tokenized_datasets)
def __getitem__(self, i):
return self.tokenized_datasets[i]
让我们对数据集进行标记化。
tokenized_dataset_train = LineByLineTextDataset(
tokenizer= tokenizer,
raw_datasets = dataset,
max_length=256,
)
好的,让我们编写训练循环代码。
from transformers import Trainer, TrainingArguments
training_args = TrainingArguments(
output_dir="./model",
overwrite_output_dir=True,
push_to_hub=True,
hub_model_id="Ransaka/sinhala-bert-yt-comments",
num_train_epochs=2,
per_device_train_batch_size=32,
save_steps=5_000,
logging_steps = 1000,
save_total_limit=2,
use_mps_device = True, # disable this if you're running non-mac env
hub_private_repo = False, # please set true if you want to save model privetly
save_safetensors= True,
learning_rate = 1e-4,
report_to='wandb'
)
trainer = Trainer(
model=model,
args=training_args,
data_collator=data_collator,
train_dataset=tokenized_dataset_train
)
我们可以使用其*train()*方法调用训练器。
trainer.train()
在充分训练后,我们的模型可以用于下游任务,如零样本分类和聚类。你可以通过使用这个 Hugging Face 空间的示例获得更多详细信息。
[## Sinhala Embedding Space - Ransaka 的 Hugging Face 空间
发现由社区制作的惊人 ML 应用
huggingface.co](https://huggingface.co/spaces/Ransaka/sinhala-embedding-space?source=post_page-----3ccce07c6fdc--------------------------------)
结论
在资源有限的情况下,预训练模型可能只识别特定的语言模式,但它们在特定的使用案例中仍然很有用。强烈建议在可能的情况下进行微调。
在本文中,除非另有说明,否则所有图片均为作者提供。
参考文献
-
一个可探究的 BERT —
huggingface.co/spaces/exbert-project/exbert
-
BERT 论文 —
arxiv.org/abs/1810.04805
如何训练 LILT 模型并在发票上进行推断
原文:
towardsdatascience.com/how-to-train-the-lilt-model-on-invoices-and-run-inference-8fd6b3cfae1b
分步教程
·发布于Towards Data Science ·5 分钟阅读·2023 年 1 月 3 日
–
图片来源:Zinkevych_D来自Envato
在文档理解领域,深度学习模型发挥了重要作用。这些模型能够准确地解读文档的内容和结构,使其成为处理发票、简历解析和合同分析等任务的宝贵工具。深度学习模型在文档理解中的另一个重要好处是它们能够随着时间的推移不断学习和适应。随着新类型文档的出现,这些模型可以继续学习并提升性能,使其在文档分类和信息提取等任务中具有高度的可扩展性和效率。
其中一个模型是 LILT 模型(Language-Independent Layout Transformer),这是一个为文档布局分析任务开发的深度学习模型。与其前身 LayoutLM 不同,LILT 最初设计为语言无关,这意味着它可以分析任何语言的文档,同时在许多下游任务应用中相较于其他现有模型表现优越。此外,该模型拥有 MIT 许可证,这意味着它可以用于商业用途,与最新的 LayoutLM v3 和 LayoutXLM 不同。因此,创建一个关于如何微调该模型的教程是值得的,因为它有潜力被广泛用于各种文档理解任务。
在本教程中,我们将讨论这一新型模型架构,并展示如何在发票提取上进行微调。然后,我们将使用该模型对一组新的发票进行推断。
LILT 模型架构:
使用 LILT 模型的一个关键优势是其处理多语言文档理解的能力,表现出色。作者通过将文本和布局嵌入分离到各自的变压器架构中,并使用双向注意力补充机制(BiACM)实现两种数据类型之间的跨模态交互,从而达到了这一点。编码后的文本和布局特征被连接在一起,并添加了额外的头部,允许模型用于自监督预训练或下游微调。这种方法不同于 layoutXLM 模型,该模型涉及收集和预处理大量多语言文档数据集。
LILT 模型架构。 来源
该模型的关键创新在于使用 BiACM 来捕捉文本和布局特征在编码过程中的交互。仅仅连接文本和布局模型输出会导致性能下降,这表明编码流程中的交互对于模型的成功至关重要。有关更深入的细节,请阅读 原始文章。
模型微调:
类似于我之前关于如何 微调 layoutLM 模型 的文章,我们将使用相同的数据集来微调 LILT 模型。数据通过使用 UBIAI 文本注释工具手动标记 220 张发票获得。关于标记过程的更多细节可以在这个 链接 中找到。有关深入的视频教程,请查看以下链接:
LILT 教程
要训练模型,我们首先预处理来自 UBIAI 的数据输出,以准备模型训练。这些步骤与之前训练 layoutLM 模型的笔记本中的步骤相同,这里是笔记本:
编辑描述
我们从 Huggingface 下载 LILT 模型:
from transformers import LiltForTokenClassification
# huggingface hub model id
model_id = "SCUT-DLVCLab/lilt-roberta-en-base"
# load model with correct number of labels and mapping
model = LiltForTokenClassification.from_pretrained(
model_id, num_labels=len(label_list), label2id=label2id, id2label=id2label
)
对于此模型训练,我们使用以下超参数:
NUM_TRAIN_EPOCHS = 120
PER_DEVICE_TRAIN_BATCH_SIZE = 6
PER_DEVICE_EVAL_BATCH_SIZE = 6
LEARNING_RATE = 4e-5
要训练模型,只需运行 trainer.train() 命令:
作者提供的图片:模型训练进行中。
在 GPU 上,训练大约需要 1 小时。训练完成后,我们通过运行 trainer.evaluate() 来评估模型:
{
'eval_precision': 0.6335952848722987,
'eval_recall': 0.7413793103448276,
'eval_f1': 0.6832627118644069,
}
我们的精度、召回率和 F-1 分数分别为 0.63、0.74 和 0.68。LILT 模型的 F-1 分数为 0.68,表明模型在准确分类和预测结果方面表现良好,准确率中等到良好。然而,值得注意的是,仍有改进的空间,继续标注更多数据将有助于进一步提高模型性能。总体来看,LILT 模型的 F-1 分数为 0.68 是一个积极的结果,表明模型在其预期任务中表现良好。
为了评估模型在未见数据上的表现,我们在新发票上运行了推理。
我们确保保存模型,以便稍后使用以下命令进行推理:
torch.save(model,'/content/drive/MyDrive/LILT_Model/lilt.pth')
模型推理:
要在新的发票上测试模型,我们运行下面的推理脚本:
编辑描述
colab.research.google.com](https://colab.research.google.com/drive/1om_xsTuuwOXzrldhkQj76HXSQkLYftRz?usp=sharing&source=post_page-----8fd6b3cfae1b--------------------------------)
以下是结果:
作者提供的图片:LILT 在发票 1 上的输出
LILT 模型正确识别了广泛的实体,包括卖方名称、发票号码和总金额。让我们再尝试几张发票:
作者提供的图片:LILT 在发票 2 上的输出
作者提供的图片:LILT 在发票 3 上的输出
如我们所见,LILT 模型能够处理各种不同格式和不同上下文的内容,尽管有一些错误,但准确性相对较好。总体而言,LILT 模型表现良好,其预测结果与 layoutLM v3 产生的结果相似,突显了其在文档理解任务中的有效性。
结论
总结来说,LILT 模型已经证明在文档理解任务中是有效的。与 layoutLM v3 模型不同,LILT 模型采用 MIT 许可证,这允许研究人员和开发者广泛商业使用,使其成为许多项目的理想选择。下一步,我们可以通过标注和改进训练数据集来提升模型性能。
如果你想高效便捷地创建自己的训练数据集,可以免费体验UBIAI 的 OCR 标注功能。
如何将家庭作业转化为数据科学职位
逐步指南,教你如何从数据集中创建引人注目的故事
·
关注 发表在 Towards Data Science · 8 分钟阅读 · 2023 年 1 月 23 日
–
图片由 Patrick Federi 提供,来源于 Unsplash
家庭作业是许多数据科学面试中的常见步骤,通常在筛选过程的后期阶段进行。第一轮考察你的统计学知识(假设检验等),通常包括实践编码问题(SQL、R 等)。如果你需要巩固这些领域的技能,请查看以下文章。
## 如何将你的 SQL 从零基础提升到数据科学家水平 — 第 1/3 部分
设置 SQL 并执行你的第一个 SELECT 查询
towardsdatascience.com ## 我作为数据科学家在进行一年 AB 测试后的收获 — 第 1/2 部分
按照这些简单步骤设置你的 A/B 测试,像数据科学家一样
towardsdatascience.com
在许多方面,家庭作业模拟了公司对你期望的情况,如果你被聘用并遇到类似的问题。在本文中,我根据我作为候选人和招聘经理的经验,创建了一个逐步指导如何应对这一挑战。该指南将按以下结构进行:
-
家庭作业的基础知识
-
数据的快速 QA
-
探索阶段: 查找数据中的模式
-
解释阶段: 构建你的故事
1. 家庭作业的基础知识
照片由Dennis Scherdt提供,来自Unsplash
1.1 家庭作业的结构是什么?
家庭作业由两个元素组成。一个数据集和一个作业概述。
-
数据集通常是公司数据的虚拟版本。它以.csv 格式提供,附有所有列的描述。很少情况下,你可能会得到多个数据集,并且需要将它们结合起来。
-
作业概述 提供了任务的一些背景信息以及他们期望你对数据集做什么的简短描述。例如,在我为 Deliveroo 的数据科学职位做的家庭作业中,任务是分析他们的 RGR(Rider Gets Rider)推荐程序与其他营销渠道的表现。然后评估其是否成功,如果没有(哈哈!),我们应该考虑更改的一些重要因素。任务的最后一步涉及向高级非技术利益相关者提供信息摘要,并建议下一步行动,例如收集额外的数据。
1.2 通过家庭作业期望获得的洞察是什么?
家庭作业使你同时处于一种独特的优势和劣势的位置。一方面,你已经有了问题定义和数据集,这通常需要项目流程中的大量时间。你还可以自由选择如何进行分析。另一方面,你无法与业务利益相关者进一步沟通,这很可怕。这正是测试评估的内容。能够接受这样的模糊作业,并且在不让其过于复杂的情况下(事实上,这也是你将被评估的内容之一),提供以下内容:
对数据集有清晰的理解,使你能够发现其中隐藏的问题(或机会)。
此外,你能够 pinpoint 可能的问题来源,并为你的目标受众提供清晰的建议和下一步计划。
换句话说,他们希望你展示你能够从数据中提供价值!
2. 数据的快速质量检查
在我们继续之前,我们需要快速检查数据集的健康状况。在计算机科学中,“垃圾进,垃圾出”(GIGO)是一个概念,表示有缺陷或无意义(垃圾)的输入数据会产生无意义的输出。虽然跳过这一步直接进入分析是很诱人的,但你不希望因为这样一个简单的错误而失败。
-
确定作为主键的列(即,对于数据集中的每一行都是唯一的)。此信息通常会提供。
-
检查列中的缺失值并相应地标记它们(NA 适用于 R,NULL 适用于 SQL 等)。隐藏的缺失值,如 999 的可疑峰值,也可以标记为NA。
-
确保所有列格式正确。例如,二进制属性(值为 0 和 1)标记为类别型,而不是整数,或者日期不会被错误标记为字符型。
-
检查是否有不合理的值。当所有其他观察值都在 0 到 1000 之间时,1 亿的值可以在可能的情况下进行修正,否则排除(确保在你的展示中解释任何排除的决定)
3. 探索阶段:发现数据中的模式
照片由 Daniel Lerman 拍摄,来源于 Unsplash
3.1 创建 KPI
对于大多数公司来说,兴趣点集中在数值属性上。这些属性可以是任何东西,取决于公司。例如,在我们以 Deliveroo 为例的情况中,可能是推荐次数;而对于像 Netflix 这样的公司,可能是观看视频的数量。对于大多数公司来说,这些属性将是货币性的(即基于收入的)。
首先,我们需要更好地理解这些数值属性。我们可以利用描述性统计和图表来实现这一目标。
-
描述性统计: 总和、均值、中位数、众数、四分位距(IQR)、标准差
-
可视化: 离散属性使用条形图,连续属性使用直方图或箱形图
我们现在需要确定我们的 KPI(关键绩效指标)。KPI 是对业务相关者有意义的描述性统计的子集。例如,相比 IQR,KPI 还有更好的选择。KPI 最常用的统计量是平均值(每个骑手的平均推荐次数或每个用户的平均观看视频数)。你需要根据数据的分布选择适当的统计量作为你的 KPI。如果存在离群值,你可以选择 95%截断均值;如果分布高度偏斜,你可以选择中位数。
重要的是要让业务相关者了解这些决策。解释由于极端离群值的存在,均值为$10000,因此选择 95%截断均值,其更具代表性的值为$120,这样可以展示 a) 你已经识别出了离群值,b) 你知道如何处理这些离群值!
3.2 添加维度
我们的分析仍然过于高层次。我们需要将分类属性纳入分析中。你可以把它们看作是我们 KPI 的维度。以 Deliveroo 为例,我们可以按城市或月份拆分每个骑手的中位推荐次数。日期是最常用的维度列之一。
一些分类属性可能会有许多稀有类别(类别是分类属性的唯一值,例如“男孩”和“女孩”)。这些稀有类别可以被合并或重新分配。我们还可以以类似的方式对数值属性进行分组,以创建新的分类维度。例如,通过使用分位数,我们可以将收入分成四个区间(或桶)。但尽量避免过度复杂化分配;除非有充分的理由,否则应避免对数值属性进行分箱。
现在我们可以通过按分类属性或日期拆分我们的关键绩效指标来开始进行比较:
-
我们的关键绩效指标(KPI)在一个城市的表现是否优于另一个城市?
-
总收入与前几个月相比是下降还是上升?
-
我们还可以结合维度。如果收入同比下降了 15%,这是因为一个或两个城市的表现更差,还是所有城市的降幅几乎都达到 15%?
3.3 根本原因分析
根本原因分析旨在识别导致问题的潜在因素。让我们通过一个例子来看这如何运作。假设一个任务中总收入相比上个月下降了 25%。你将城市作为维度,观察到差异几乎完全来自纽约和伦敦。其他城市的总收入月月保持不变。首先,我们将把总收入分解为两个组成部分。
总收入 = 总订单数 * 平均订单价值
从(虚构的)数据来看,两个城市的总订单数都增加了 9%,但平均订单价值却下降了 38%!好吧,现在我们有了一些进展。我们还可以检查用户经历的漏斗。例如,如果订单下降了,我们可以先检查一下有多少访客,多少人将产品添加到购物篮中,多少人进入了结账页面,最后有多少人确认了订单。
当然,上述内容依赖于我们可以获取的数据量。但我们只能使用现有的数据,因此如果由于数据限制导致上述步骤无法进行,请不要担心。但请确保在分析建议和下一步计划时将其作为潜在数据源添加进去。
4. 解释阶段:构建你的故事
图片由 RetroSupply 提供,来源于 Unsplash
这是你的作业的最终部分,也可能是最重要的部分。你的分析是评估的关键部分,但同样重要的是你的展示的简洁性和清晰度(利益相关者只有在理解你的观点时才能欣赏它们)。你需要遵循三个关键规则:
-
你的演示文稿应该简洁。不要展示你打开的每一只牡蛎,而只展示珍珠
-
在你的幻灯片中使用视觉效果和摘要,使洞察更易于理解。任何不促进这一方向的元素应当被移除或更改
-
在分析的基础上给出明确的建议和下一步计划
你也可以在下面找到有关如何创建视觉效果和结构化演示文稿的更详细文章。
公共演讲是否是数据科学家的致命弱点?
帮助我提升演讲技巧的三个关键经验
towardsdatascience.com
总结
🚀🚀 通过最后一步,我们已经完成了指南。以下你还可以找到步骤的简要总结:
✅ 仔细阅读描述并理解任务和目标
✅ 在开始分析之前对数据进行质量检查
✅ 创建关键绩效指标,并按维度拆分以精准定位问题
✅ 进行根本原因分析,以识别可能解释问题的因素
✅ 仅传达分析中的关键点。抵制展示所有开过的牡蛎的冲动
我想强调的最后一点是根据家庭作业的质量对公司进行自我评估的重要性。描述是否清晰?数据集是否具有一定挑战性?在问题和数据集上投入了足够的努力,还是看起来像是草率的工作?
如果你有任何问题或需要进一步的帮助,请随时在下方评论,我会及时回答。
保持联系!
如果你喜欢阅读这篇文章并想了解更多,请别忘了订阅,以便直接将我的故事发送到你的邮箱。
在下面的链接中,你还可以找到一个关于在实际商业场景中使用数据科学技术和最佳实践完成客户群体分析的免费 PDF 指南。👇
我是一名拥有 7 年以上分析经验的数据科学家,目前在英国伦敦的一家游戏公司工作。我的……
如何将时间序列转换为深度学习格式
原文:
towardsdatascience.com/how-to-transform-time-series-for-deep-learning-3b6abbbb3726
使用深度神经网络进行预测
·发布于 Towards Data Science ·6 分钟阅读·2023 年 2 月 14 日
–
图片由 Claudio Testa 提供,来源于 Unsplash
使用时间序列的监督学习
监督学习涉及使用输入数据集来训练机器学习模型。这个数据集通常是一个矩阵:一个由行(样本)和列(特征)组成的二维数据结构。
时间序列是按时间排序的值的序列。因此,它需要转换以进行监督学习。
在 上一篇文章中,我们学习了如何将单变量时间序列从序列转换为矩阵。这是通过滑动窗口完成的。每个观察值基于过去的最近值进行建模,这些值也称为滞后。
以下是使用 1 到 10 序列的转换示例:
将序列转换为带滑动窗口的矩阵。图片由作者提供。
这种转换实现了一种称为自回归(auto-regression)的建模类型。在自回归中,使用时间序列的过去最近值(滞后)作为解释变量来建立模型。这些值用于预测未来的观察值(目标变量)。自回归的命名直观上是因为时间序列与自身回归。
在上述示例中,滞后是前 5 列。目标变量是最后一列(下一个时间步的系列值)。
深度学习中的自回归
虽然大多数方法适用于矩阵,但深度神经网络需要不同的结构。
深度神经网络如 LSTM 或 CNN 的输入是一个三维数组。实际数据与放入矩阵中的数据相同,但结构不同。
除了行(样本)和列(滞后),额外的维度指的是序列中的变量数量。在矩阵中,你会将所有属性连接在一起,而不考虑它们的来源。神经网络则更整洁。输入是通过第三维度按序列中的每个变量组织的。
让我们做一个实际示例来澄清这个概念。
实践操作
在本教程中,你将学习如何使用 LSTM(长短期记忆网络)转换时间序列以进行监督学习。LSTM 是一种特别适合建模时间序列的神经网络类型。
我们将时间序列转换过程分为两个步骤:
-
从值序列到矩阵;
-
从矩阵到深度学习的 3 维数组。
首先,我们将进行一个单变量时间序列的示例。多变量时间序列将在后面介绍。
单变量时间序列
首先,我们来读取数据。我们将使用与不同类型葡萄酒销售相关的时间序列。你可以在参考文献[1]中查看源数据。
import pandas as pd
# https://github.com/vcerqueira/blog/tree/main/data
data = pd.read_csv('data/wine_sales.csv', parse_dates=['date'])
data.set_index('date', inplace=True)
series = data['Sparkling']
我们以香槟酒的销售数据为例进行单变量情况的示范。这个时间序列如下所示:
从值序列到矩阵
我们应用滑动窗口将此序列转换为监督学习所需的格式。你可以在之前的文章中了解更多关于此过程的信息。
# src module here: https://github.com/vcerqueira/blog/tree/main/src
from src.tde import time_delay_embedding
# using 3 lags as explanatory variables
N_LAGS = 3
# forecasting the next 2 values
HORIZON = 2
# using a sliding window method called time delay embedding
X, Y = time_delay_embedding(series, n_lags=N_LAGS, horizon=HORIZON, return_Xy=True)
这里是解释变量(X)和相应目标变量(Y)的示例:
转换时间序列为 2 维矩阵结构后的解释变量(左)和目标变量(右)的样本。图片由作者提供。
这个数据集是训练传统机器学习方法的基础。例如,线性回归或 xgboost。
from sklearn.linear_model import RidgeCV
# training a ridge regression model
model = RidgeCV()
model.fit(X, Y)
从矩阵到深度学习的 3 维结构
你需要重塑这个数据集来训练像 LSTM 这样的神经网络。以下函数可用于完成此操作:
import re
import pandas as pd
import numpy as np
def from_matrix_to_3d(df: pd.DataFrame) -> np.ndarray:
"""
Transforming a time series from matrix into 3-d structure for deep learning
:param df: (pd.DataFrame) Time series in the matrix format after embedding
:return: Reshaped time series into 3-d structure
"""
cols = df.columns
# getting unique variables in the time series
# this list has a single element for univariate time series
var_names = np.unique([re.sub(r'\([^)]*\)', '', c) for c in cols]).tolist()
# getting observation for each variable
arr_by_var = [df.loc[:, cols.str.contains(v)].values for v in var_names]
# reshaping the data of each variable into a 3-d format
arr_by_var = [x.reshape(x.shape[0], x.shape[1], 1) for x in arr_by_var]
# concatenating the arrays of each variable into a single array
ts_arr = np.concatenate(arr_by_var, axis=2)
return ts_arr
# transforming the matrices
X_3d = from_matrix_to_3d(X)
Y_3d = from_matrix_to_3d(Y)
最终,你可以使用得到的数据集训练一个 LSTM:
from sklearn.model_selection import train_test_split
from keras.models import Sequential
from keras.layers import (Dense,
LSTM,
TimeDistributed,
RepeatVector)
# number of variables in the time series
# 1 because the series is univariate
N_FEATURES = 1
# creating a simple stacked LSTM
model = Sequential()
model.add(LSTM(8, activation='relu', input_shape=(N_LAGS, N_FEATURES)))
model.add(RepeatVector(HORIZON))
model.add(LSTM(4, activation='relu', return_sequences=True))
model.add(TimeDistributed(Dense(N_FEATURES)))
model.compile(optimizer='adam', loss='mse')
# compiling the model
model.compile(optimizer='adam', loss='mse')
# basic train/validation split
X_train, X_valid, Y_train, Y_valid = train_test_split(X_3d, Y_3d, test_size=.2, shuffle=False)
# training the model
model.fit(X_train, Y_train, epochs=100, validation_data=(X_valid, Y_valid))
# making predictions
preds = model.predict_on_batch(X_valid)
多变量时间序列
现在,我们来看一个多变量时间序列的示例。在这种情况下,目标是预测多个变量的未来值,而不仅仅是一个。因此,你需要一个用于多变量和多步预测的模型。
关于不同类型葡萄酒销售的多变量时间序列。图片由作者提供。
转换过程与之前类似。
要将多变量时间序列转换为矩阵格式,可以对每个变量应用滑动窗口方法。然后,将所有结果矩阵合并为一个。
这是一个示例:
# transforming each variable into a matrix format
mat_by_variable = []
for col in data:
col_df = time_delay_embedding(data[col], n_lags=N_LAGS, horizon=HORIZON)
mat_by_variable.append(col_df)
# concatenating all variables
mat_df = pd.concat(mat_by_variable, axis=1).dropna()
# defining target (Y) and explanatory variables (X)
predictor_variables = mat_df.columns.str.contains('\(t\-|\(t\)')
target_variables = mat_df.columns.str.contains('\(t\+')
X = mat_df.iloc[:, predictor_variables]
Y = mat_df.iloc[:, target_variables]
解释变量对于两个变量如下(其他变量为了简洁省略):
你可以使用相同的函数将数据转换为三维:
X_3d = from_matrix_to_3d(X)
Y_3d = from_matrix_to_3d(Y)
训练部分与之前相似。序列中变量数量的信息在 N_FEATURES 常量中提供。顾名思义,这个常量表示时间序列中的变量数量。
model = Sequential()
model.add(LSTM(8, activation='relu', input_shape=(N_LAGS, N_FEATURES)))
model.add(Dropout(.2))
model.add(RepeatVector(HORIZON))
model.add(LSTM(4, activation='relu', return_sequences=True))
model.add(Dropout(.2))
model.add(TimeDistributed(Dense(N_FEATURES)))
model.compile(optimizer='adam', loss='mse')
X_train, X_valid, Y_train, Y_valid = train_test_split(X_3d, Y_3d, test_size=.2, shuffle=False)
model.fit(X_train, Y_train, epochs=500, validation_data=(X_valid, Y_valid))
preds = model.predict_on_batch(X_valid)
以下图表展示了一个步进预测样本。
LSTM 的一步预测。图像作者提供。
预测效果不是很好。时间序列较小,我们也没有对模型进行优化。深度学习方法以数据为食。如果你选择这种方法,请确保你有足够的数据。
关键要点
深度学习在时间序列应用中越来越相关。
在本文中,我们探讨了如何为深度学习转换时间序列。
传统机器学习算法的输入是一个矩阵。但是,像 LSTM 这样的神经网络使用三维数据集。因此,时间序列需要从序列转换为这种格式。
这种转换基于滑动窗口,该窗口应用于序列中的每个变量。
感谢阅读,下次故事见!
相关文章
-
预测的机器学习:转换和特征提取
-
预测的机器学习:使用多变量时间序列的监督学习
参考文献
[1] Rob Hyndman 和 Yangzhuoran Yang (2018). tsdl: 时间序列数据库. v0.1.0. (GPL-3 许可证)
转行到数据分析的路线图
原文:
towardsdatascience.com/how-to-transition-to-data-analytics-128a3dca54d5
·发表于 Towards Data Science ·11 分钟阅读·2023 年 11 月 6 日
–
如果你在其他领域工作,如何转行到数据分析?
你可能拥有一个与数据分析无关的大学学位,或者在一个完全不同的领域工作过。你可能一直对转行数据分析角色感兴趣,但不知道从哪里开始。如果这听起来像你,继续阅读吧!😉
图片来源:Myriam Jessier 在 Unsplash
进入数据分析的两种方式
本质上,有 2 种进入数据分析的方式:
-
(1) 完全自学:然后巧妙地将分析技能与当前领域知识(无论是来自早期的学习还是工作)结合,以获得竞争优势;
-
(2) 选择数据分析学位或训练营。
在这篇博客文章中,我们将主要关注自学的途径,目标是成为数据分析师,这也是许多其他数据科学角色的良好起点。这也是我 6 年前开始的方式,当时我对医疗分析非常感兴趣,所以我从这一领域起步。
在这篇文章中,我们将讨论你应该学习和准备的内容:
-
所需技能
-
作品集项目
-
如何接触招聘人员
事情变化迅速,许多人担心人工智能可能取代工作,这可能会影响你在追求数据分析工作时的情况。我将在本文最后分享一些关于这一点的见解。
你还可以观看下面的博客文章视频版本 👇
www.youtube.com/@Thuvu5/videos
那么数据分析师实际上做什么?
实际上,有很多不同的职位涉及到处理数据并将其转化为见解。很久以前,从事这类工作的人员在保险行业工作时会被称为统计学家或精算师。
如今,我们有时对职位头衔过于执着,这很快就会变得令人困惑。如果我们查看招聘信息,就会看到业务分析师、研究分析师、分析顾问、初级数据科学家等等。更不用说数据分析 + X 这类职位,这些职位特定于某个领域,比如 HR 数据分析师、销售分析师、市场分析师等。
我发现了解工作的本质和你实际使用的技能更为有用。因此,在本文中,我将所有这些头衔简化为数据分析师。
数据分析师是一个分析数据的职位。
数据分析是一个检查、清理、转换和建模数据的过程,目的是发现有用的信息、得出结论并支持决策。
因此,数据分析师通常会做大量的数据科学工作,除了预测分析、机器学习和软件工程,这些通常是数据科学家更关注的领域。因此,作为数据分析师可以为你进入数据科学家、数据工程师和其他数据科学职位打下坚实的基础。
职业前景
在美国,数据分析师的中位薪资为 95,000 美元。对既具备领域知识又能分析数据的人才需求不断上升。
作为数据分析师,你将有机会在医疗保健、金融、银行、物流、人力资源等多个领域工作。你可以为初创公司、代理机构、企业或像我这样的咨询公司工作。你可以全职或自由职业,甚至远程工作。所以你在职业生涯中有很大的灵活性!
所需技能
说到数据分析师最重要的技能,让我展示这个技能模型来帮助你可视化它。
图片来源:作者。
(1) 基础数学和统计:
在最基本的层面上,你需要一些基础数学和统计学。仅仅是基础的高中或本科数学和统计学就足够了,除非你希望在工作中进行更高级的分析或机器学习。大多数时候,作为数据分析师,你会对数据进行一些描述性统计,比如计算平均值、最小值、最大值、中位数、标准差等。根据项目的不同,你可能还会进行离群值检测、假设检验、线性回归、聚类甚至机器学习。这取决于你的工作及其技术复杂性。我强烈推荐你阅读达雷尔·哈夫的经典书籍*《如何用统计数据撒谎》*。这本书读起来非常有趣,指出了我们在从数据中得出结论时最常犯的错误。我认为每个从事数据工作的人都应该读一读。
(2) 技术技能:
其次,数据分析师需要工具,即特定的技术或软件。作为数据分析师,你几乎每天需要完成 3 件事:
-
提取数据
-
数据分析
-
可视化数据以传达洞察力并讲述故事
有各种工具可以帮助你完成这些任务中的每一个,或所有任务。**最受欢迎的技能是 SQL、Excel、Tableau、Python 和 R。**你也可以选择学习 PowerBI。如果你已经掌握了 Tableau,学习 PowerBI 应该很快,反之亦然。未来,我们可以预期作为数据分析师将处理大数据。因此,学习这些工具的大数据版本可能对你有用,例如用于查询大数据的 SparkSQL,以及用于以 Python 风格处理大数据的 PySpark。
(3) “软”技能:
在下一个层级,我们有软技能。数据分析师能够沟通洞察力是至关重要的,因为你将与业务利益相关者、产品经理及其他关键利益相关者合作。你需要提出问题,理解业务问题,然后与他们一起迭代不同的分析和结果,最终为业务提供一些洞察和建议。大多数时候,沟通和讲故事的形式包括演示文稿、文档、电子邮件、仪表盘等。
图片来源于 path digital 在 Unsplash
(4) 领域知识
最终,在顶层,我们需要领域知识。它让你真正理解业务问题,并且更好地理解数据。例如,如果你在航空公司工作,你需要了解航空公司的运作。如果你在医疗保健领域进行数据分析,了解医疗保健领域也是至关重要的。这些领域知识可以通过你的教育背景或在该领域的工作经验获得。
如何学习这些技能——从哪里开始?
学习数据分析角色所需技能的方式有很多。以下是一些建议:
-
关于数学和统计学,很容易陷入一个无限循环中,总觉得自己学得不够。对我来说,即使经过 6 年我仍然有这种感觉。但拥有基础到中级的理解是可以的。很多东西你可以在工作中学到,所以不要太担心从一开始就不知道足够的内容。
-
关于 Excel,我建议你真正掌握它。你需要像对自己手背一样了解基本功能,如 VLOOKUP、XLOOKUP、Index match、条件格式、数据透视表等。你还可以学习更高级的工具,如宏和 VBA 来自动化重复性任务,如果需要连接不同的数据源,可以选择 PowerQuery。未来,很多小任务可以通过 AI 自动化。因此,我们需要的主要能力是了解事物的运作方式。如果你已经了解 VBA 的工作原理,使用 ChatGPT 为你编写一些 VBA 代码以填充 Excel 模板会更容易!
-
学习编程时使用迁移学习:如果你已经掌握了一种编程语言,例如 SQL 或 R,那么将这些技能迁移到 Python 等新语言上会比较容易。当我第一次学习 Python 时,我经常尝试将 R 中的知识关联起来。例如,如果我想合并两个数据框,我会搜索“如何在 Python 中按行绑定数据框”,因为这是我在 R 中的描述方式。此外,所有的基本概念,如变量、数据类型、函数、词法作用域,几乎都是相同的。因此,随着时间的推移,你会培养出如何做事和解决问题的直觉,无论使用什么语言。其余的只是练习!
-
关于数据可视化,它可能是数据分析师工作中最有趣的部分。数据可视化可以是你在 R、Python 或 Excel 中创建的独立图表,或以仪表板或演示文稿的形式存在。初学者可以参考一些好的书籍,如《用数据讲故事》。对于仪表板的制作,你可以通过一些 Tableau 或 PowerBI 课程快速学习,这些工具是拖拽式的,无需编码。
-
关于讲故事、提问和演讲等软技能,你会随着时间的推移而不断提高。但你也可以通过主动练习来提高沟通和讲故事的能力,比如写关于你项目的博客,将想法和见解展示给朋友和家人,看看他们的反馈。
准备一个数据作品集
在众多候选人中,你绝对需要脱颖而出。我相信一个好的个人作品集将帮助你最好地展示你的技能,并吸引招聘者的注意。做项目也是检验你技能的好方法。这会给你带来自尊和信心,这可能是最重要的方面。
如果你不知道做什么项目,我在我的频道上有一些项目教程,你可以使用并根据你的具体使用案例或领域进行调整。
这里有一些额外的建议:
-
确保你的作品集里有 3–5 个项目。我认为 3–5 个项目是展示你技能的最佳数量。
-
做一个你关心的项目,找到或创建一个你真正感兴趣的数据集,并投入一些LOVE ❤️!你的热情会显露出来!通过对比两个项目,人们可以很容易地看出哪个作者投入了更多的思考和承诺。
-
一切都是困难的,直到你搞明白!有时候需要很大的勇气才能克服心理障碍开始或继续。有几个月前我开始了抱石攀岩。攀岩教会了我很多关于克服恐惧、完全投入到一个困难动作中的课程。知道我可以训练自己去想:“我害怕,但我还是要去做”令人振奋。
接触招聘人员
线下 & 线上网络
在掌握了一些技能和作品集项目之后,是时候让自己走出去。我发现像朋友、亲戚、以前的同学或同事这样的线下网络是找到工作的最简单方法,这也是我之前有效的方式。但在线上也有很多机会。
LinkedIn 也是一个联系已有领域人员和招聘人员的好地方。我实际上从未尝试过在 LinkedIn 上联系招聘人员,也许是因为 7-8 年前这并不常见。但如果你试一试,请在信息中保持真诚和礼貌。如果你与公司有任何联系,哪怕是微小的,比如你参加过公司的活动或与那里的某人交谈过,请在信息中提及!
你也可能想要使用 Grammarly 来检查你的语法,或者让朋友帮你校对。小错误可能会留下不好的印象,特别是当这是你唯一能留下的印象时!
不要低估自己!
从我的经验来看,低估自己是一个常见的错误。如果你真的在这个领域很新,你可能会想“我刚毕业,还在学习”。这可能是真的,但这不是雇主所寻找的。你可以以更自信的方式来表达,强调你所做的事情和你能贡献的东西。同时,确保向招聘人员发送一份最新的简历,其中应包括指向你的作品集项目的链接,如 Github 仓库、作品集网站或其他在线项目提及。
如果你有之前的工作经验或一些“领域知识”,你应该充分利用这些经验。即使你曾在超市做过咖啡师或收银员,这也算作你的领域经验。数据分析离不开背景和业务问题。如果我是你,我会提到这些经历,并尝试将它们与我申请的工作联系起来,讲述一个小故事,并展示这些经历所学的内容如何对公司有益。这并不总是简单直接的,但我认为这是一个非常有效的聪明策略。
ChatGPT 将如何影响数据分析师的工作?
说到 AI,毫无疑问,语言模型和 AI 工具将在某种程度上改变分析工作。最近的一项分析发现,大型语言模型如 GPT 可能对 80%的美国劳动力产生一些影响。一些最易受影响的创意和高薪工作包括作家、网页和数字设计师,以及金融量化分析师和区块链工程师。
但我认为好处将超过坏处。一项最近的研究表明,AI 工具对技能和成就最低的工人帮助最大,缩小了员工之间的表现差距。换句话说,能力较弱的数据分析师将会变得更好,而优秀的分析师则会变得更快!
正如你可能已经知道的,数据预处理占据了许多数据分析师和数据科学家工作的大约 70–80%。这些工作大多非常枯燥乏味。我认为像 ChatGPT 和 GPT-4 这样的工具可以帮助我们自动化很多这些任务,从而简化和优化数据分析过程。AI 工具如 ChatGPT 在数据分析中的一些最佳应用场景包括:
· 它可以创建用于构建数据库、进行简单数据清理、探索性数据分析和创建各种图表的代码。
· 优化你的代码并添加注释和解释以供文档使用。
· 为如何将信息传达给不同的受众——高层管理人员、部门主管、经理等,提供建议。
· 建议数据来源,例如“我在哪里可以找到关于荷兰金融欺诈的数据?”
· 你还可以让它创建合成数据以用于模型训练或算法测试。
· 提供基于互联网上开放资源的法规、法律流程的一般建议。
尽管如此,有些生成型 AI 还做不到,幸运的是,至少目前还不行!即便是今天最先进的语言模型也仍然缺乏关键能力,如批判性思维、战略规划和复杂问题解决能力。如今,企业不仅仅是要以更便宜的方式做相同的事情。公司需要创新和跳出框框思考,如果他们想要保持业务的持续性。因此,作为数据分析师,你有能力帮助他们做到这一点。语言模型也还不能编写笑话,而幽默和可爱在建立信任和关系中出乎意料地重要。因此,我们可以预期人类数据分析师在这些方面能够大放异彩。
对我们来说,关键是持续学习,掌握良好的基础技能,跟上利用 AI 工具和技术以提高工作效率的步伐。同时,我们比以往任何时候都更加关注同理心、沟通和关系建设等软技能。
结论
我希望这篇博客文章能让你更好地理解如何从其他领域过渡成为数据分析师,并为你提供一份路线图。祝你在职业生涯的下一步好运!😊🍀
如何将数据转化为可操作的商业洞察
原文:
towardsdatascience.com/how-to-translate-data-into-actionable-business-insights-1321ce7edc2a
你的数据只是故事的一半
·发布在Towards Data Science ·6 分钟阅读·2023 年 7 月 18 日
–
图片来源:Matt Popovich在Unsplash
在当今迅速扩展的世界中,对能够为企业翻译数据的专业人士需求旺盛——分析数据并为企业制定行动建议。一切都在于迈出那一步,使数据对企业更具可读性。
数据无处不在。企业希望利用这些数据来做出更好的决策,并在市场中保持灵活和竞争力。现在,当我们谈论企业时,许多做决策的高管不一定理解原始数据及其分析方法。这就需要数据专业人员来完成工作并提供可操作的洞察。
即使在较低层级,你的同事可能也不完全理解预测模型的准确性意味着什么。我听过有人说“这*信息很好,但我接下来该怎么做?”*因此,关键是你不仅要分析数据,还要以企业也能理解的方式呈现数据。
在这篇博客中,我想强调数据转化和讲故事如何相辅相成,以及将数据转化为可操作商业洞察的六步流程。
数据与洞察有何不同?
人们往往将数据和洞察互换使用,而实际上它们的含义有很大区别。
数据是原始且未处理的。它可能是数字、文本、图像、音频或视频文件等,这些数据可能独立存在时没有意义,也没有为企业提供有价值的输入。
洞察是通过转化原始数据来分析信息并得出结论的结果。今天的企业利用洞察而非数据来最大化盈利、提高成本效益并创造价值。
将数据转化为业务的六个步骤
1. 了解业务并提升洞察力
解决任何商业问题的第一步是理解业务本身。除非你理解一个业务的挑战、需求、要求和机会,否则你如何能为更好的未来优化现在的状况?
了解你的组织及其业务书籍是一个持续的过程。由于组织的业务方式是如此动态并快速发展,因此数据专业人员必须调整他们的数据模型并理解业务需求,这是至关重要的。
在讲故事方面,理解商业背景就像理解你故事所基于的城市和文化——没有这些,你的故事就会失去灵魂。
2. 首先理解问题
作为数据专业人员,你的第一反应可能是提出创建一个模型作为解决方案,但没有明确、简洁的问题陈述,数据专业人员将很难将这些文字转化为代码行或 Excel 表格。
当你对问题陈述有了充分的理解,并查看任务的数据时,接受或拒绝这些数据变得非常容易。你可以考虑数据生命周期中的下一步。
我通常遵循下面的五步过程来解决问题 —
-
多读几遍问题陈述或那封电子邮件
-
将你的问题分解成更小的步骤
-
确定你能解决的问题部分
-
探索所有可能的支持信息(阅读文档!)
-
决定一种方法(你的数据模型、可视化等)
3. 通过漏斗分析来发现你的 KPI
每个部门可能有比其他部门更关键的 KPI,因为他们负责推动特定的业务影响。每当你被要求解决商业问题时,首先从所有相关的 KPI 和对你的建模和分析重要的指标开始。
有效的漏斗分析需要一致的数据分析。首先假设问题(或创建你的漏斗),并使用 A/B 或多变量测试来开始筛选出可能对你的问题陈述的意图没有价值的 KPI。根据最终的 KPI,这时你可以开始创建数据分析和模型。
漏斗分析的例子——假设你在一家饮料公司工作,你的任务是预测公司目录下一个品牌在整体饮料市场中的市场份额。在这种情况下,创建漏斗分析可以帮助你揭示你最畅销的产品。你问怎么做?方法如下 —
-
绘制理想的端到端业务流程图
-
确定每个漏斗阶段的问题
-
收集尽可能多的相关数据用于分析
-
监控关键绩效指标(KPIs)
-
创建一个行动优先矩阵,以便在四个象限中映射高低优先级的努力和影响。
-
根据上述矩阵中的任务重要性进行排序,将会得到一个待办事项列表,这就是你的漏斗分析的结果。
4. 使用三原则
人类以有趣的方式处理信息。我们擅长模式识别,而三是创建模式所需的最小元素数,因此当信息以三的形式呈现时,易于消化。
故事讲述的核心形式:电影、戏剧和故事通常遵循三幕剧结构,其中第一幕、第二幕和第三幕通过建立情节、对比和高潮来捕捉故事。类似地,三原则可以让你的内容更具吸引力,将你的话总结为三个行动项或关键要点。例如,你可以将你的演示或关键要点总结为——
-
重点 1 —
-
重点 2—
-
重点 3—
这样可以让你的观众更容易记住你的内容,并在需要时采取行动。
5. 使其易于理解
我会让这部分非常易读易懂——
-
在演示文稿(或任何沟通中)使用较少或不使用行话。
-
不要在演示文稿中使用过多的颜色,保持视觉的舒适。
-
使用易于理解且与上下文相符的视觉效果。
-
保持幻灯片中的格式简单且一致。
-
在图表中标注坐标轴,添加颜色图例,并在需要的地方添加注释。
6. 创建一个成功的数据展示
大多数人不了解数据。
大多数人理解故事。
销售故事,而不是数据。
利用我刚刚提到的五个要点,现在是将这些要点整合起来,创建一个有效、简洁且成功的数据展示的最佳时机——
-
***了解你的观众——***映射观众的知识水平,并根据他们是同事、利益相关者还是高管和领导者来准备内容。
-
构建你的内容流程——一个好的故事应该从介绍议程到呈现关键发现,提供支持数据,讨论方法论,再到重新审视关键发现,整个过程应无缝衔接,这也是整个博客的重点:提供建议或下一步行动。
-
像讲故事一样叙述——就像每部好电影都有情节、冲突和高潮一样,你的数据故事应该有一个开始、中间和结尾,以形成一个全面的叙述。
-
确定你的故事类型——根据问题陈述、使用的方法和洞察,你的故事可以是一个演示、仪表板中的可视化,或者只是 Excel 中的数据。
-
保持简洁明了——每张幻灯片最多花费 5 分钟时间,并始终预留 10 分钟用于问答环节。
总之,仅仅通过数据讲解是不够的。数据讲故事是一项极其重要的技能(几乎是一种艺术),这正是我们必须追求的——将数据转化为业务价值。
关于这篇博客,我就说到这里。感谢阅读!希望你觉得这篇文章有趣。请在评论中告诉我你在讲故事方面的经验、你的数据之旅,以及你对 2023 年的期望!
如果你喜欢阅读这样的故事,可以考虑通过这个链接注册成为 Medium 会员。
祝数据探险愉快!
拉希是一位来自芝加哥的数据专家,热衷于分析数据并创作数据故事以传达洞见。她是一名全职医疗数据分析顾问,周末时会喝着咖啡撰写数据博客……
如何将数据视为产品
通过应用产品管理原则,最大化你从数据中获得的杠杆效应
·
关注 发表于 数据科学的前沿 ·10 分钟阅读·2023 年 2 月 8 日
–
许多组织希望他们的技术从一个成本变成一个差异化的竞争因素——数据技术也是如此。你经常会听到这种愿景被表达为“我们想要 将数据视为产品”。
图片由 Brands&People 提供,来源于 Unsplash
不同的定义
几年前,许多高管所说的“将数据视作产品”是指他们希望通过直接出售数据(例如在数据市场上)来实现数据的货币化。然而,今天这些市场大多包含的是由专门从多个来源汇聚数据的公司创建的数据(例如零售客流量、信用卡收据、产品评论)。很少有公司在货币化其第一方数据方面取得成功。
那么,当一个典型的企业希望将数据视作产品时,这意味着什么呢?有几种相互竞争但又互补的定义。Tableau 的定义——任何使用数据来帮助企业改善决策和流程的应用程序或工具都是数据产品——强调了数据的有用性。McKinsey 的定义——一套高质量、随时可用的数据,组织内的人员可以轻松访问并应用于不同的业务挑战——强调了标准化。Montecarlo 的定义——数据以可用的形式存在于公司内部(即使最后的环节涉及自助式转换)——强调了数据的治理。
将产品管理原则应用于数据
我倾向于将其视为结合期望结果和达到结果的过程。
期望的结果是,组织将通过将数据视作产品来最大化数据的杠杆效应,在这里,上述定义中强调的特征(有用性、标准化、治理)很重要。像 Tableau 一样,我对数据产品的定义持扩展性观点——数据集符合要求,但数据管道、仪表板、依赖数据的应用程序和机器学习模型也是如此。
期望的结果只有在有通向结果的路径时才有价值。要将数据视作产品,请在构思和构建数据产品时应用产品管理原则。哪些产品管理原则?(1)制定产品战略,(2)以客户为中心,(3)进行轻量级产品发现,以及(4)专注于找到市场契合点。我建议采纳以下与这些原则相一致的 10 个数据实践:
要将数据视作产品,采纳这些 10 种实践,将产品管理原则应用于构思和构建数据产品。
1. 理解并维护企业中的数据流图
产品经理的一个关键工作是简化。过于频繁地,当有人问“你有什么数据”时,答案是一个包含公司各个业务部门收集的数百个数据集的电子表格。这并不太有用。
将数据视为产品意味着你(数据产品团队)维护一个高层次的数据流模型,以便于发现和沟通。维持这个地图在多个粒度层级上。在最高层次,对于一个电子商务网站,它可能是:
-
网络流量
-
产品目录
-
网页内容
-
订单
-
库存
-
客户调查
在下一个粒度层次上,网页流量可能被拆分为会话数据、页面数据等。记录每个数据集是如何收集的、如何处理的、哪些角色可以访问以及如何访问、是否存在 PII 或其他属性、有哪些质量保证措施等。此外,记录每个数据集的生产使用案例。
正如你所看到的,当你从较高的粒度层次降到较低的层次时,映射开始包括你的数据平台实现的细节。它开始变成一个数据目录。
2. 识别关键指标
数据目录只是记录当前存在的内容。它不记录数据为何重要或数据是否适合用途。它不会告诉你需要改进什么。
数据产品策略的一个重要部分是使企业内的关键指标达成一致——你将测量什么、如何测量以及指标的目标数值是什么(目标会随时间变化)。你跟踪的指标范围应包括:
-
业务 KPI:需要通过数据实现哪些业务成果?
-
SLA:数据的可用性?数据质量?刷新率?
-
参与度:数据在公司内的使用范围和频率如何?
-
满意度:客户(可能是内部客户)对可用数据及其易用性满意度如何?
对于我们假设的电子商务网站,业务成果可能包括提高客户生命周期价值、增加免费层转化率等。对于内部采购者(用于补货)显示的库存的服务水平协议(SLA)可能是:其可用率达到 99.99%,每小时刷新,并保持在下周预测销售额之上。我们可能希望库存预测不仅被内部采购使用,还被物流团队使用并纳入到仪表盘中。我们还可能会有一个衡量预测库存数量被覆盖的频率的指标。
3. 已达成的标准、承诺的路线图和远见的待办事项
数据目录记录了当前存在的内容。指标捕捉了你的目标。两者都没有解释你接下来要去哪里。
根据客户反馈、利益相关者意见和市场条件,随着时间的推移调整产品愿景非常重要。在这一过程中,你的利益相关者会要求你提供功能和时间表,并期望你履行承诺。要处理变化和用户反馈,你需要三个方面:
-
优先级标准 是利益相关者事先达成一致的——这能够在组织内部实现透明度和对产品路线图的认可。
-
产品路线图本身是通过产品发现过程来指导的,以便团队可以避免在没有信息和原型的情况下同意时间表。产品发现很重要,我会深入探讨这一点。
-
我们认为重要但尚未纳入路线图的事项将被记录在产品待办事项列表中。通常,产品待办事项列表包含需要解决的客户问题(而非必须构建的功能)。在许多方面,待办事项列表(而非路线图)形成了你的长期产品愿景。组织待办事项列表以讲述一个清晰的故事。
路线图需要高度承诺——你应该能够对路线图上的时间表和功能做出承诺。一种很好的做法是达成优先级标准的共识,进行产品发现,并维护产品待办事项列表。
对于我们假设的库存预测数据产品,我们需要达成一致,如何衡量预测的准确性——是否我们很少出现缺货?我们是否最小化了采购和存储成本?缺货发生在仓库层面?还是公司层面?这些构成了优先级标准。如果有人要求你为易腐品定制库存模型,这值得做吗?你会首先将其添加到产品待办事项列表中。然后,你会进行产品发现,以确定进行这样的项目的投资回报率——例如,这将包括增加/减少仓库冷藏的成本。只有在了解了价值之后,你才会将其添加到你的产品路线图中。
4. 为你已有的客户构建
数据团队经常被技术口号困扰:他们只提供 API,或坚持要求每个人将数据发布到企业数据仓库中,或期望遵循单一词典。
借鉴产品管理的经验,深入了解你的客户是谁。他们在做什么?移动应用还是月度报告?他们知道什么?SQL 还是 Java?他们使用什么工具?仪表板还是 Tensorflow?他们是否需要数据变化时的警报?他们是否需要实时数据的移动平均值?他们是否关心测试覆盖率?
然后,以目标客户能够使用的方式提供数据。例如,你可能将数据提供在数据仓库中(供数据分析师使用),通过 API 使其可访问(供开发者使用),在功能存储中发布(供数据科学家使用),或提供一个可以在仪表板中使用的语义层(供业务用户使用)。
如果我们假设的库存预测数据产品将被内部采购员(即业务用户)使用,预测结果必须在用于订购补货的应用程序中提供。因此,预测结果可能需要通过 API 供该应用程序的开发者使用。
5. 不要将变更管理的负担转移
变更和冲突是不可避免的。数据供应商将更改格式;数据消费者将有新的需求;数据流速将发生变化;相同的数据可能通过多个渠道提供;你的客户可能因为成本而转向其他供应商。这些问题不仅仅是发生变更的团队或使用数据的团队的问题。
将数据视为产品的一大部分是确保数据用户不必承担变更管理的责任。尽可能确保演变的架构和服务对下游用户保持透明。
当不可逆的变更不可避免地发生时,为变更版本化,并与利益相关者合作,将他们从数据的旧版本迁移到新版本。这可能涉及创建一个迁移团队,其工作是将企业从一个版本迁移到下一个版本。
变更管理的原则同样适用于安全。确保为个人身份信息(PII)和合规性建立保护措施,而不是将负担转嫁给你的数据产品用户。
假设我们假设的库存预测数据产品被定制为包括易腐商品的预测。如果这涉及请求关于正在销售的商品的额外信息,你将不得不承担确保你的商品目录得到增强的责任。这项数据工程工作是项目范围的一部分,并影响是否值得进行这项工作的投资回报。
6. 采访客户以发现他们的数据需求
你如何演进产品待办事项,优先排序需求,并添加到路线图中?一个重要的原则是确保你不断与客户沟通,发现他们需要什么数据来解决他们遇到的问题。他们在当前数据产品中有哪些不足需要绕过?这些问题会成为你的产品待办事项,供你优先处理和解决。
在任何新的数据产品想法进入产品路线图之前,确保该产品的需求已经得到了潜在(内部或外部)客户的验证是非常重要的。基于规范的开发(“造出来,他们就会来”)是极其冒险的。更安全的方法是构建已经得到客户验证的想法的实现。
你怎么做呢?
7. 广泛进行白板讨论和原型设计
与希望使用数据产品的客户一起进行白板设计。这确保了你在数据平台上落地的内容能够满足他们在质量、完整性、延迟等方面的需求。在你构建任何数据管道或转化之前,与他们讨论数据的潜在用途。
这里一个很好的工具是原型。许多数据用例可以通过构建最小可行原型来验证,而不是产品。原型。
我什么意思?如果销售团队认为构建一个客户数据平台将帮助他们交叉销售产品,通过从各个产品的销售管道中挑选一组记录,手动进行匹配,并尝试对结果客户进行交叉销售来验证这一点。
使用这样的原型和与最终产品潜在用户的访谈来界定问题,具体包括:
-
需要构建的内容:识别项目成功所需的所有内容,从数据管道到用户界面。
-
你可以期待的商业关键绩效指标的投资回报
在编写任何代码之前做到这一点。只有当你对需要构建的内容和预期的投资回报有清晰的想法时,才应将项目添加到你的路线图中。在此之前,将问题保留在待办事项中。
在我们假设的库存预测数据产品的情况下,你需要与产品的关键用户验证输入模式和预测的使用,确保冷藏仓库能容纳多少等。在编写任何代码之前,你可能会在电子表格中进行预测,并对各种产品的整个场景进行模拟。
8. 仅构建立即需要的功能
优先考虑快速投入生产而不是构建所有必要功能。这意味着你应使用敏捷、迭代的过程,仅构建立即需要的数据集、数据管道、分析等。
使用产品待办事项来捕捉未来的需求。在你确定了会使用这些功能并能在白板/原型设计会议中提供反馈的客户之后,再构建这些能力。
9. 标准化常见实体和关键绩效指标
提供标准化的、丰富的常见实体和关键绩效指标数据集,这些数据集在整个业务中都是标准的。通常,这些丰富的实体驱动大量高投资回报的用例(例如客户数据平台、内容管理平台)或用于监管/合规目的(例如计算税收的方式)。
通常,你会有仅仅少数这些标准化的数据集和指标,因为这种增强需要跨业务单元的大量协作,并降低了它们的发布速度。
10. 在你的数据平台中提供自助服务功能
你必须在适合你组织的方式下平衡灵活性和标准化。不要过度实施第 9 条。不构建包含任何人可能想要的所有内容的集中数据集。相反,赋能团队实现自给自足。这是微服务原则在数据中的应用。
实现这一平衡的一种方式是提供小型、自包含的数据集,客户可以通过与其他数据集以特定领域的方式进行联合来定制这些数据集。通常,这种方法实现为数据网格,每个业务单元负责其发布到共享分析中心的数据集的质量。
总结
将数据视为产品,运用产品管理原则制定你的数据产品战略,以客户为中心,通过白板和原型设计来发现产品,并在标准化和灵活性之间找到合适的平衡。
如何使用日志模块调试 Python 脚本
原文:
towardsdatascience.com/how-to-troubleshoot-python-scripts-with-the-logging-module-aaf630c35fe3
打印语句只能带你走到一定程度…
·发布于 Towards Data Science ·阅读时间 7 分钟·2023 年 8 月 26 日
–
图片来源:Tima Miroshnichenko: www.pexels.com/photo/a-person-writing-on-a-notebook-5336909/
目录
∘ 介绍
∘ 日志模块
∘ 日志级别
∘ 配置级别
∘ 调试级别配置
∘ 创建日志文件
∘ 格式化日志消息
∘ 关键要点
介绍
考虑以下情况:你编写了一段代码,该代码要么返回错误,要么产生意外的值。
x1 = function1(x)
x2 = function2(x1)
x3 = function3(x2)
为了找出错误的代码行,你会写一个打印语句…
x1 = function1(x)
print(x1)
x2 = function2(x1)
x3 = function3(x2)
然后再添加一个打印语句…
x1 = function1(x)
print(x1)
x2 = function2(x1)
print(x2)
x3 = function3(x2)
然后再跟进另一个打印语句。
x1 = function1(x)
print(x1)
x2 = function2(x1)
print(x2)
x3 = function3(x2)
print(x3)
一旦你识别并修复了问题,这些打印语句就变得无用。所以,你一个个地删除或注释掉它们:
x1 = function1(x)
#print(x1)
x2 = function2(x1)
#print(x2)
x3 = function3(x2)
#print(x3)
如果你的故障排除经验类似于上述场景,你一定对使用打印语句处理错误代码行的挫败感感同身受。
幸运的是,Python 中有一个工具提供了更有效的调试策略:日志模块。
在这里,我们深入探讨日志模块的基本功能,并探索使其成为强大故障排除工具的特点。
日志模块
日志模块是为那些希望有效跟踪程序中某些事件的程序员设计的。
幸运的是,学习使用该工具没有任何前提条件,特别是如果你已经熟悉 Python 的打印语句。
从语法上看,日志模块的命令与打印语句非常相似,允许用户使用简单的一行代码生成消息。
import logging
logging.warning('Hello World')
代码输出(由作者创建)
话虽如此,日志记录包括了常规 print 语句所不提供的功能,我们现在将介绍这些功能。
日志等级
在日志模块中,并非所有消息都是相等的。日志模块中的事件被分解为不同的重要性等级。
日志模块的文档列出了 5 个日志等级,并解释了它们的使用场景。
日志等级(作者创建)
换句话说,当用户使用日志记录消息时,他们还可以设置该消息的重要性。INFO 消息最适合监控事件状态,WARNING 消息最适合发出警告,而 ERROR 消息最适合报告错误。
因此,用户可以根据消息的目的使用等级来分配其消息的重要性。例如,在加载数据集时,可以编写 INFO 和 ERROR 等级的消息。
try:
mock_data = pd.read_csv('random_data_source.csv')
logging.info('random_data_source.csv has been loaded')
except:
logging.error('random_data_source.csv does not exist')
通过对消息分配不同的重要性等级,用户可以定义他们希望看到或不希望看到的消息的重要性阈值。
默认情况下,日志模块只考虑 WARNING 及以上等级的日志。
日志等级(作者创建)
这意味着,未进行额外配置的消息记录不会返回 DEBUG 和 INFO 等级的消息。
代码输出(作者创建)
如输出所示,实际上只有 WARNING、ERROR 和 CRITICAL 等级的消息被生成。
配置等级
与 print 语句不同,日志允许用户配置应该生成的消息的重要性等级。
例如,假设我们需要记录 INFO 及以上等级的消息。
日志等级(作者创建)
我们可以通过使用basicConfig
方法并定义level
参数来指示程序生成 INFO 等级的消息:
现在,所有 INFO 及以上等级的消息都会被显示。
代码输出(作者创建)
由于程序已配置为接受 INFO 及以上等级的日志,因此记录了所有非 DEBUG 等级的日志。
调试等级配置
通过basicConfig
方法,用户可以调整日志等级的阈值,以包含所需等级而忽略不需要的等级。
例如,假设我们正在对一个变量进行转换,并希望在每次转换后找到该变量的值。在这里,我们对变量 x 执行数学运算:
import logging
logging.basicConfig(level=logging.DEBUG)
x = 5
logging.info('Performing mathematical operations on x')
x = x * 2
logging.debug(f'x * 2 = {x}')
x = x + 6
logging.debug(f'x + 6 = {x}')
x = x / 4
logging.debug(f'x divided by 4 = {x}')
阈值日志等级已设置为 DEBUG,这意味着所有日志消息都会被创建。运行代码将返回如下结果:
代码输出(作者创建)
这些消息可能很有用,但一旦调试完成,它们便没有任何价值。那么,我们如何阻止这些消息在未来的迭代中被生成呢?
如果我们使用打印语句,解决方案是删除或注释掉每一个不需要的打印语句。幸运的是,使用日志记录时,可以通过简单地修改basicConfig
方法中的日志级别阈值来移除不需要的调试消息。
现在,我们可以将日志级别更改为 INFO,从而省略所有 DEBUG 级别重要性的日志消息。
logging.basicConfig(level=logging.INFO) # Change from DEBUG to INFO
x = 5
logging.info('Performing mathematical operations on x')
x = x * 2
logging.debug(f'x * 2 = {x}')
x = x + 6
logging.debug(f'x + 6 = {x}')
x = x / 4
logging.debug(f'x divided by 4 = {x}')
代码输出(由作者创建)
这一次,即使日志命令仍在使用,它们也会被省略,因为 DEBUG 级别低于分配的 INFO 级别阈值。
同样,当我们希望开始调试过程时,我们可以使用日志记录来做相反的事情:降低日志消息的阈值重要性,以便程序生成较低重要性的消息。
创建日志文件
使用打印语句时,消息会显示在命令行或控制台上,但不会存储在任何位置。
使用日志模块的basicConfig
方法,用户可以创建一个专门记录所有由模块创建的消息的文件。
例如,以下代码片段使用basicConfig
方法将所有消息保存到一个名为“demo.log”的新创建的文件中。
import logging
logging.basicConfig(filename='demo.log',
level=logging.DEBUG)
logging.debug('Debug message')
logging.info('Info message')
现在,当运行脚本时,控制台不会显示任何消息。相反,消息将直接存储在“demo.log”文件中。
demo.log(由作者创建)
此外,这些记录的消息不会被覆盖;当添加更多日志时,它们会保留在“demo.log”文件中。如果我们再次运行相同的脚本,新日志消息将会被添加到新的一行中。
demo.log(由作者创建)
格式化日志消息
日志中的消息并不总是那么具有信息性和可读性。
为了生成更适合给定用例的消息,用户可以使用basicConfig
方法配置消息的格式。
在下面的代码片段中,我们配置消息的格式为时间戳、日志级别和消息内容。
logging.basicConfig(filename='demo.log',
level=logging.DEBUG,
format='%(asctime)s %(levelname)s %(message)s'
)
logging.debug('Debug message')
logging.info('Info message')
代码输出(由作者创建)
确立日志的格式可以使生成的消息既具有信息性又具有可读性。当然,理想的格式取决于程序员的个人偏好。
关键要点
照片由Prateek Katyal提供,来源于Unsplash
总的来说,尽管打印语句通常被视为检查或调试代码的首选工具,但日志模块是更合适的工具。
日志提供了一个系统,将消息分类为不同的重要级别。此外,它们还具备一些功能,使用户能够轻松配置生成哪些消息、如何格式化这些消息以及它们应该存储在哪里。
日志模块能够让调试过程更快捷、无压力,因此,如果你厌倦了使用普通的、通用的打印语句,考虑采用它。
感谢阅读!