数据总是脏的
它讲故事的能力取决于你清洗它的能力。
统计学 101 课程可以教给你的最好的一课是,你的故事的质量取决于你的数据的质量。您的问题越复杂,在您对数据做任何有趣的事情之前,您可能要花越多的时间来清理数据。一些项目可能需要你 90%的时间来清理数据,如果你不喜欢这样,或者至少接受这个事实,这会让你正在做的工作变得极其痛苦。了解你的数据,然后清理你的数据,然后分析你的数据!
随着大数据的增长,数据的潜在肮脏程度达到了极限,接受这一事实的人非常适合处理任何类型的数据。在我参与的一个公共卫生项目中,我的职责之一是对一个程序进行更新,该程序用于创建关于特定公共卫生指标的季度报告。该报告的数据来自多个利益相关方。其中一个利益相关者坐拥数据宝库,但他们的部门不太适合处理这类项目,而且数据很脏,非常脏。
马库斯·斯皮斯克在 Unsplash 上拍摄的照片
不足为奇的是,在为这种与数据直接相关的公共卫生指标编写报告时,经常会遇到两难的问题。数据驱动领域(如数据科学)的个人有多方面的工作,但一个简单的解释将他们的角色分为两个主要目标-第一个是组织和分析数据以讲述一个连贯的故事(这是报告方面),并理解与处理数据相关的技术(这是方法和编程方面)。问题是这两者可能会因为项目的目标和正在进行的计划而相互矛盾。
这个项目非常适合面试这样的问题:“说出一个让你感到沮丧的困难项目,并描述你是如何处理这个项目的各个方面的”。对我来说,我的目标是对已经写好的东西进行调整。因此,有人更熟悉这个项目。为了说明这一点,我首先关注可解决的技术方面,并试图根据团队中每个人擅长或特别感兴趣的项目的具体方面,对他们的输入进行分层。目标是没有一个人(包括我自己)会忘记总体目标和他们的具体任务,因为每个人都有重要的角色。这种方法很有效——直到它失效。那些因为参与过某个项目而与该项目有利害关系的个人,从一开始就把他们固有的偏见带到了桌面上。在一些看似立竿见影的胜利鼓舞了士气之后,在遇到下一个(不可避免的)路障后,这一点显露了出来。
当上述场景被打破时,两种思维模式将会盛行
- 让我们庆祝我们的胜利,记录它们,描述它们,并谨慎行事,直到我们解决这个障碍,达到我们的下一个里程碑。采用这种方法,可以量化代码的具体变化以及它们如何影响报告——记录的数据的一个问题是 X,我们用 Y 解决方案解决了它,我们的度量标准以 Z 的方式发生了变化。这是对数据科学项目的方法和编程方面的加倍努力,希望这将导致一个更好或更可接受的方法来提高你讲故事的能力。为此,我提出了“这是一个新颖而复杂的数据源,而且很脏”的想法。我们可以专门就脏数据做一次演讲,并强调这些数据和项目中以前没有讨论过的方面。这并没有发生,虽然我希望我可以在某个时候给一个肮脏的数据讲话!
- 第二种方法是对已经存在的过程的加倍,不管它是否正确,因为它更熟悉。对于这个特定的项目,它变得很难取得进展,因为每次遇到新的路障时都采用相同的不准确的起点。此外,沟通中断导致与工程不同部分相关的工作重叠。在第一个场景中,你把每一个路障看作是通向另一个直接分支的途径,同时牢记更大的目标。最后,当你有了一个“解决方案”或更简单的更好的答案时,你会看到一棵树——主干是你的设计和方法——每个分支都是一条路径,作为创建过程、测试、实施、检查和继续的迭代过程的一部分。通过回溯,每当你遇到路障时,你就在主干处切断树枝。最终结果是一个树桩——没有进展。发育不良和无进展随之而来。
许多定量领域的细节隐藏在数据中,尽管数据总是肮脏的,但水看起来比以往任何时候都更浑浊。不仅数据脏,而且数据量也在以更快的速度增长。虽然正确地清理数据可能被视为一件麻烦事或必要的坏事,但这一过程现在已经势在必行。接受脏数据并实现适当的数据清理过程可能意味着项目将顺利进行,而有缺陷的系统将导致延迟和挫折。最近数据量的增长与更好地处理和讲述数据故事的能力相结合。这些过程的相互作用加速了新领域的发展,并使数据的价值呈指数级增长。接受清理数据的过程是允许早期职业数据专家在其职业生涯中蓬勃发展的一个因素。
数据是纳斯卡和 F1 的驱动力。NoSQL 在杆子上
速度和动力推动着 NoSQL 技术在赛车运动中的应用
2020 年,乔治·拉塞尔在 63 号车里进站。图片 via 威廉姆斯车队 下牌照给丹尼尔福尔克斯莱昂。
谈到赛车和速度,f1 和纳斯卡车队的目标是相同的。获胜。他们的目标是拥有最快的赛车,招募最熟练的车手,并在赛前和赛中做出最佳的战略和竞争决策。进入海量数据呈指数级增长的时代:从汽车内的大量传感器、司机制服、赛道旁扫描仪、视频馈送、天气预报;你说吧。数据库技术及其管理现在不仅是影响赛道决策的因素,也是确保登上领奖台的关键。
Formula 1 和 NASCAR 从数据分析和处理中获得了明显的好处,但它们的实现和方法彼此非常不同。在一级方程式赛车中,车队的遥测数据是专有的,受到高度保护。另一方面,NASCAR 将所有车辆和车队的遥测数据实时提供给车迷、车队和原始设备制造商(原始设备制造商,即 NASCAR 的福特、雪佛兰和丰田)。但是 f1 和纳斯卡都有一个共同的关键因素:对 NoSQL 技术的快速采用。
奥古斯托·卡多佐(Augusto Cardoso)是 SportMedia Technologies (SMT)的首席工程师,该公司是纳斯卡的合作伙伴,负责汇总、处理和向各种观众传输所有比赛数据。卡多佐指出,在多种运动中,它们的采用速度正在加快。“大约 3 年前,我们在赛车运动团队中首次采用了 MongoDB。它取代了 SQL 数据库。我们正在扩大 MongoDB 在曲棍球和棒球等其他运动中的使用。每项运动都有自己的要求,MongoDB 提供了很大的灵活性。”
2020 年,凯文·哈维克驾驶 04 号赛车进站。图片由丹尼尔·福尔克斯·莱昂授权。
英国一级方程式赛车队的首席工程师菲利普·托马森(Phillip Thomason)指出了使用 NoSQL 技术的两大优势:打破以前孤立的存储库之间的墙壁,以及允许多个团队之间的协作。NoSQL 有助于解决筒仓挖好后通常会出现的特殊问题。Thomason 描述了他们开始使用 NoSQL 技术之前的情况,“这些查询是缓慢的、手动的,并且通常实际上是不可能的。NoSQL 允许用户访问所有数据的潜力,并改善了部门间的沟通。”
在这种数据丰富的环境中,通过“合适的工作工具”理念来接纳各种各样的数据,NoSQL 技术公司可以提供这些团队所需的能力和速度。
这并不容易,因为 f1 车队每场比赛至少会产生 3TB 的数据,仅纳斯卡在一个周末就产生了超过 1 亿个数据点。
数据通过赛道从赛车传输到基站,工具需要快速处理数据,以便团队分析和视频动画配对播放。
“在纳斯卡的情况下,数据需要为多个观众实时准备好,”卡多佐说。“在赛车运动中,我们有一些独特的应用,我们有一辆生产卡车,每周前往每个场地。我们为赛道用户提供服务,包括车队、汽车制造商(OEM)和电视广播公司。挑战在于,我们需要在卡车和云中复制数据。客户直接从我们的卡车或云端使用数据。如果出现网络问题,电视广播不能停止。我们的本地基础架构可以独立运行,但大多数性能分析和数据科学用户都连接到云。”高辛烷值的数据性能是业务的重要组成部分,但它不能以可用性为代价。Cardoso 补充道,“自从我们迁移到 MongoDB,有了‘在卡车中’和云的存在,我们还没有一个数据库相关的问题。”
在 F1 中,车队都在积极地试图获得彼此之间的竞争优势,他们对各种技术的使用和组合也不例外。
“F1 车队不得不“内部”开发所需的大部分软件,因为市场上根本没有这些软件,”汤姆森解释道。“由于我们是一个相对较小的团队,技术选择通常由团队中的现有技能决定。通常没有足够的时间(或资源)来招聘额外的技能。我们依靠非常有能力的团队成员,他们都在‘全栈’工作,他们的日常职责包括研究新技术。”在 Williams 内部,将结构化和非结构化数据整合在一起的过程是一个关键的竞争领域,也是一个不能公开披露太多信息的领域。
“NoSQL 已经允许用户访问所有数据的潜力,它还改善了部门间的沟通。”
威廉姆斯车队的菲利普·托马森
随着数据库技术在潜力和机会方面的进步,方法也在进步。赛车运动也不例外,推动 DevOps 流程引领着持续集成—持续开发(CI-CD)的发展。关于 DevOps 流程,Thomason 补充说,对于 F1 中的威廉姆斯车队来说,“我们总是面临着时间和资源的挑战,以及提高所有业务领域效率的动力。像 Docker 这样的工具允许我们将传统的软件开发团队转移到 DevOps 领域,并帮助更好地定义 IT 和软件部门之间的界限。我们一直有一个非常快速的软件更新机制(基于不同种族发布),但 DevOps 无疑给了我们更多的灵活性。”
遥测数据不是比赛中可以收集的唯一数据类型;其他来源也会对团队及其奖金产生巨大影响。一个这样的例子是在进站。自从 f1 禁止中途加油以来,他们的进站一直保持在三秒以内,威廉姆斯在 2016 年实现了最快的进站。NASCAR 也在努力缩短进站时间,车队可以在比赛中跟踪和监控所有赛车的进站时间。这导致团队只根据 SMT 汇总的数据向他们的团队发放特别奖金。
由 SMT 开发的 NASCAR 团队分析应用程序中的 PitStop 报告示例。图片经由 SMT 授权给丹尼尔·福尔克斯·莱昂。
NASCAR 和 SMT 完全通过 MongoDB 和微服务处理他们的数据。Cardoso 甚至表示,自从他们实施以来,没有一次生产失败。“微服务要快得多。我已经有了一个包含脚本和所有设置的漏斗…所以就 CI-CD 而言,继续推出这些东西对我来说要容易得多…我只需添加和编辑即可”。
关于数据的采用,Thomason 补充说:“F1 一直是数据驱动的,随着管理机构限制我们可以做的测试(有限轮胎、计算流体力学、风洞和赛道测试),这导致了围绕技术的效率驱动,以从我们允许的运行中提取最大的利益。因此,遥测数据的扩展是由寻求竞争优势的团队推动的。”
尽管这两项运动高度重视数据,并且都从数据分析中获得了明显的回报,但它们的方法非常不同。对于 F1,汤姆森将其描述为一种非常有价值和令人垂涎的资源:“鉴于 F1 的历史,任何公开发布的数据都会被车队用来分析竞争对手的表现,并且需要大量的资源投资才能保持竞争力。”
另一方面,纳斯卡则截然不同。“这是纳斯卡做的一件事,”卡多佐补充道,“每个人都可以看到每个人的数据。所以这是一件非常重要的事情。这都是纳斯卡的政策!为此,我推荐他们,因为这样更容易理解。”这导致了一种非常不同的数据处理方式,以及围绕这种方式建立竞争力的方式。卡多佐是一个团队的成员,该团队开发了一个由 NASCAR、车队及其原始设备制造商直接使用的应用程序,该程序可以帮助实时计算每辆车的燃油效率和估计值。应用程序瞬时运行,当显示结果的速度时,卡多佐补充道:“我不知道你是否能理解这有多快。这个集合有 28 个阶段,我在 3T T1 工作室完成了整个过程。
不仅后面的车队可以实时看到领先的汽车是否有足够的燃料完成比赛,而且粉丝和竞争对手也可以随着比赛的发展制定策略。
SMT 为 NASCAR 开发的数据应用中的燃料指标示例。图片经由 SMT 授权给丹尼尔·福尔克斯·莱昂。
Formula 1 和 NASCAR 可能会以不同的方式处理遥测数据,但它们都希望尽可能快地传输数据。数据传输率是 F1 和 NASCAR 的普遍瓶颈,因为网络错误或基站在降雨期间淹没赛道会导致连接问题。即便如此,他们已经达到了令人印象深刻的延迟速度。在 NASCAR 中,SMT 能够以比一般广播延迟更快的速度处理从赛道到现场卡车、云以及用户的数据。
卡多佐说:“让你了解一下,当你在赛道上时,我们发送数据的延迟大约是 5 到 6 毫秒。真的很快。数据到达云时的延迟接近 100 毫秒。这个巨大的差距,基本上是从卡车到数据中心,最快也就是 60 毫秒的延迟。”正如 Thomason 指出的那样,Williams 也在推动更快的数据速度,“推动处理尽可能接近比赛,以减少数据处理/流丰富套件中的延迟。这里节省的十分之一秒对比赛性能有真正的好处。”
速度、动力和多功能性是赛车运动的每一个要素的要求,从空气动力学到轮胎质量和遥测数据流。数据库技术和架构模型也不例外,NoSQL 现在是另一个帮助获得下一秒的可靠元素。
如何从数据中获取能量
数据=知识=力量
马库斯·斯皮斯克在 Unsplash 上的照片
想想最强大的人和公司。他们都有什么共同点?
我们都听说过这样一句话知识等于力量,这是真的。无论你想到的是脸书、谷歌、亚马逊还是政府,他们都因为自己的知识而拥有权力。
但是他们是如何获得这些知识的呢?
这句话中经常被忽视的部分是如何首先获得知识。它不是你刚刚拥有的东西,你必须走出去获得它。那么他们是怎么做到的呢?
他们收集和使用数据。
所有的科技巨头都从收集数据开始,然后将数据转化为知识。然后,因为他们知道的事情,他们的力量增长。然而,不仅仅是科技巨头,政府也是这样运作的,在大多数情况下,政府领导人也是这样当选的。
你认为唐纳德·特朗普只是碰巧成为美国总统吗?
他之所以能做到这一点,是因为他(以及他的团队)收集了美国公民的数据,将其转化为关于哪些地区甚至哪些人可以被说服投票给特朗普的知识,这反过来给了他权力。
让我们看看这种数据趋势的好与坏,以及为什么如果你正在寻找一条职业道路,一个安全的赌注是在数据领域。
权力饥渴?变得数据贪婪
当脸书开始时,我确信最初的意图是创建一个远程连接人们的平台。然而,即使在早期,扎克伯格也会知道他收集的数据本来就是有用的。
是的,他为人们提供了一种联系的方式,但这只是脸书的一个小副作用。事实是,他收集的数据比服务本身更有用。脸书收集关于你是谁,你认识谁,你在哪里,去过哪里,甚至你在做什么的数据。
“Hive 是脸书的数据仓库,80 万个表中有 300 的数据” 【来源】
想象一下,从 300Pb 的数据中可以提取出多少知识。脸书就是这样掌权的。它收集了尽可能多的数据,即使它还不知道要用这些数据做什么。
这种对数据的贪婪仍在继续,脸书并不孤单。任何想要繁荣发展的现代公司都需要收集数据。任何不从客户或服务中收集数据的企业在未来几年都将难以生存。
这并不完全是厄运和黑暗
我们经常读到这些大公司甚至我们的政府如何滥用我们的隐私来获取这些数据的故事。的确,您应该关注并采取积极的方法来保护您的数据足迹。
大公司总是并且将继续滥用权力以保持权力。他们最初就是这样变得强大的,那么为什么现在要停止呢?早在计算机出现之前,人们已经知道公司和政府滥用权力很多年了。我不是说这是对的,我只是说这不是一个新问题。
然而,我们有很多方法可以善用数据。为了了解我们周围的世界,现代科学需要收集和处理数据。我们将这些数据用于技术、可再生能源和治疗疾病等等。
设想没有疟疾正在利用数据科学帮助卫生服务了解疟疾在哪里出现,以便在这些地区提供更快的治疗,防止传播。
Factom 区块链让偏远地区的人们拥有可访问和安全的健康记录。它还防止医疗用品在黑市上出售,以便到达预定目的地。
癌症基因组图谱计划帮助生成和处理数据,这些数据被用于改善我们诊断和治疗癌症的方式。
正如你所看到的,不要让关于渴求数据的公司的悲观消息把你引入歧途。数据可以作为一种工具,就像任何事物一样,有好有坏。我们需要更多的人用数据做好事。
数据职业道路
我目前是一名数据工程师,所以我对数据职业生涯的寿命的想法会有一点偏见,但幸运的是,我有一些数据来支持它。
我们是现代的淘金者
towardsdatascience.com](/why-your-company-needs-a-data-engineer-51735a1e5cf0)
美国劳工统计局在一份报告中指出,从 2016 年到 2026 年,数学科学职业将增长 7.4%。这基本上意味着,与 4 年前相比,2026 年数据和分析职位将增加约 1150 万个。
我认为可以肯定地说,随着公司努力实现增长,特别是在现代气候下,他们被迫转向网络,数据职业是一个非常安全的赌注。毕竟,数据是获取知识的第一步。
如果你能帮助一家公司获得和处理数据,你就为它的发展和成功提供了关键。
如果我今天考虑职业或学习道路,并且对数学、科学或技术有热情,我会选择面向数据的道路。数据不会说谎,目前的趋势表明,我们收集和使用数据的规模只会越来越大。
数据标签是中国在联网汽车大战中的秘密武器
这是一场真正的军备竞赛。
“你现在看到的一切——所有这些人工智能的壮举,比如自动驾驶汽车、解读医学图像、击败围棋世界冠军等等——这些都是非常狭隘的智能,它们实际上是为特定目的而训练的。在这些情况下,我们可以收集大量数据。”
这是根据脸书人工智能研究的负责人 Yann LeCun 的说法。
这些话强调了一个事实,即在最近闪亮的人工智能产品繁荣的背后,隐藏着一个更加平庸的人类现实。
世界科技巨头经常依赖大群人来标记将用于训练其机器学习算法的数据。
“标记数据”只是指获取一组未标记的数据(例如,电话记录或街道图像),并在单个元素(如单词或汽车)上添加信息性的描述性标签。
例如,为了帮助训练自然语言处理系统,数据标注者可能会添加标签来显示某个单词在不同上下文中的含义。
虽然这种估计总是通用和简化的,但数据科学类型已经有益地将机器学习项目中的时间分配细分如下:
如果机器学习算法被输入大量精确标记的训练数据,它可以在“现实世界”中用于包括无人驾驶汽车中的计算机视觉在内的任务。
数据标记需要很多时间,这是一项重要的任务,尤其是当数据将用于训练自动驾驶汽车时。可接受的误差幅度非常小,我相信我们都同意这一点。
尽管有所进步,人工智能仍然像它的名字所暗示的那样非常人工。
机器学习算法的学习方式与人类不同。一些科学家正试图教人工智能像孩子一样学习( 这篇科学杂志文章 是一个很好的入门),但这些努力仍处于婴儿阶段。
我们偶尔会收到这一事实的严峻提醒,比如对街道标志的细微修改,这完全扰乱了计算机视觉系统,如下所示:
当我们看着这个被破坏的停车标志时,我们看到的是很清楚的,但神经网络分类器在几乎 100%的测试中认为这是一个“限速 100”的标志。
因此,就目前情况而言,机器学习需要良好的数据,而获得这些数据的最可靠方式是付钱给那些整天坐着给图像做注释的人。
你有越多的人,你就能标记越多的数据。
这是一场军备竞赛,但不是我们所知道的那种。
在中国,人们谈论钱坫后厂经济模式——字面意思是“前店后厂”。通常,这是用来帮助分工,资本和供应链内的资源。
中国过去曾让人民币贬值(特别是在 20 世纪 80 年代和 90 年代),以使其出口商品对外国更便宜,并刺激对生产大众消费品的工厂的投资。这也使得中国公司的进口更加昂贵,刺激他们在当地购买设备。
基本上,在这种情况下,中国是后面的工厂,西方是商店前面。
现在,中国的野心自这一时期以来(也因为这一时期)一直在增长,到了中国公司希望“跃上”价值链并拥有客户关系和产品创造的地步。
为什么要提这个?嗯,钱坫猴场模式仍然占主导地位。现代中国的区别是,机器人在前面,人在后面。
人们正在投入艰苦的劳动,以便中国汽车、数字助理和店内机器人能够蓬勃发展。在理想的情况下,中国会向世界其他地区出口更好的产品。
这有点让人想起 18 世纪的“土耳其机器人”(mechanical Turk),那个让赌客惊叹不已的下棋机器人原来是一个由下面一个隐藏隔间中的一个小人控制的木偶。
信不信由你,我提到这个例子是有原因的。亚马逊做出了一个颇能说明问题的决定,将其众包工作平台命名为“ ”亚马逊机械土耳其人 ”,这是对昔日迷人的投机者的滑稽引用。
在 17 世纪,“计算机”是能够进行算术计算的人。在 20 世纪中期,计算机仍然是公司内部处理数字运算的人(主要是女性)。只是到了后来,计算机才变得程序化和数字化,我们今天还在训练它们。
我们每天都是这个动态的一部分。我们使用这些验证码形式来“证明”我们是人类,这些数据被用来让机器变得更智能。
尽管我们偶尔会瞥见幕后的场景,但人们可能会对今天人工智能训练的手工程度感到惊讶。
去年,苹果、谷歌、亚马逊和脸书在被发现出口用户数据并与第三方分享后都不得不道歉。
这些科技巨头向数据注释公司提供信息,如用户与数字助理的对话,以提高其人工智能系统的准确性。
在文章发表的时候,还没有人找到一种精确的、成本有效的方法来取代人类贴标机的角色。
就这样,回到了中国。
中国的农村地区,比如贵州,现在是庞大的数据标注工厂的所在地。
对于当地人来说,是一个很有诱惑力的职业;每月 3000 元(425 美元)的平均工资是该地区平均工资的三倍。贵州去年的经济产出增长了 10.2%,成为全国增长最快的省份。
当然,科技公司之间的这场“军备竞赛”不仅仅是让更多的人来完成标签制作过程。
然而,这是一个好的开始。
正如贵州一家数据标签公司的老板在接受《纽约时报》采访时说的那样,
“我们是数字世界的建筑工人。我们的工作是一砖一瓦地砌。但是我们在人工智能中扮演着重要的角色,没有我们,他们无法建造摩天大楼。”
像淘宝的视觉搜索( 在最近的时事通讯中讨论过 )这样的知名产品是根据阿里巴巴在这些农村地区的仓库中标记的数据进行训练的。
就其本身而言,腾讯正在研究这个巨大的掩体,以存储、处理和分析来自其一直受欢迎的微信应用程序的用户数据:
当然,中国经常比其他国家拥有更多的劳动力。
它还在一些关键技术领域落后于美国,并陷入了与特朗普政府的持续斗争。
出于多种原因,美国将这种体力劳动外包出去。首先,建立这些设施,培训员工,然后付给他们讨厌的最低工资,成本很高。把工作送到更便宜的地方要容易得多,尤其是如果成品(大量有标签的数据)看起来都一样的话。
中国或许能够将其昔日的弱点转化为优势。像贵州这样的农村地区仍然欠发达;数据标签公司带来了急需的工作和相对健康的薪水。与北京等大城市相比,这些工资就相形见绌了,这也为科技公司提供了进一步的好处。
中国完全跳过了几代人的技术发展,让它在下一个重大事件上领先一步。非接触式信用卡从未真正在那里起飞,它们已经转向智能手机支付。在西方,从非接触式卡转向智能手机支付的动机远没有那么有吸引力。
这同样适用于自动驾驶汽车;在未能严重削弱全球有人驾驶汽车市场后,中国公司已将重点转向制造无人驾驶机器。
如果中国科学家在这个过程中学会开发更复杂的微处理器,中国发展的这一最新阶段只会真正对美国科技巨头构成威胁。
正如《经济学家》 本周 报道的那样,中国仍在一个至关重要的行业追赶,到 2022 年,这个行业的价值将达到 5750 亿美元。
虽然数据标记看起来是一项只有一个有用目的的令人沮丧、单调的任务,但它在这个宏观层次上也发挥着作用。
通过自始至终拥有机器学习供应链的所有权,中国人工智能科学家仍然接近这些复杂、有时不透明的系统的内部运作。
中国劳动力的庞大数量将在开发知识产权这一珍贵商品方面发挥至关重要的作用。
使用亚马逊数据库迁移服务的数据湖变化数据捕获(CDC)——第 1 部分——捕获
使用 Amazon Database Migration Service(DMS ),轻松捕获随时间推移从数据库到数据湖的数据更改
图片由来自 Pixabay 的 Gino Crescoli 拍摄
在我过去 10 年在大数据和分析领域的经历中,我逐渐意识到捕获和处理变化数据集一直是一个具有挑战性的领域。这些年来,我看到了疾控中心是如何发展的。让我带你走过这段旅程:
2011–2013 年—对许多人来说,Hadoop 是主要的数据分析平台。通常,Sqoop 用于将数据从给定的数据库传输到 HDFS。这对于满表负载非常有效。Sqoop incremental 可以捕获插入以及*。*
但是 CDC 不仅仅是关于插页。我的更新和删除在哪里?
2016 年—我们创建了一个策略,使用数据库表上的触发器捕获更新和删除,并将更改写入影子表。一旦捕获到发生更改的数据,我们将使用 Sqoop 将数据传输到 HDFS。这种方法需要修改数据库,所以我们的很多客户都反对。
2015–2016 年——名为 Debezium 的新开源项目的使用越来越多。此后的几年里,我们非常有效地使用了这个 CDC 工具。最初,Debezium 只支持有限数量的数据库,但这足以覆盖我们的大部分用例。
Debezium 能够查询数据库二进制日志并提取更改。它以 JSON 文档的形式将每个变化发布给 Kafka。
按作者分类的图像—在图像之前和之后记录
2016 年—现在—对于 AWS 云部署,我们通常使用亚马逊数据库迁移服务(DMS)。DMS 可以从内部服务器或 RDS 读取变更数据集,并将其发布到许多目的地,包括 S3、红移、Kafka 和 Elasticsearch 等。
让我向您展示如何创建一个示例 CDC 管道。我们将首先在 AWS 上创建一个 RDS 数据库,创建一个示例数据库,最后设置 Amazon DMS 来执行到 S3 的变更数据捕获。
让我们从下载一个样本数据文件开始
$ git clone https://github.com/mkukreja1/blogs.git
创建 RDS 安全组并打开入口
$ aws ec2 delete-security-group --group-name "RDS Security Group"$ RDS_GROUP=` aws ec2 create-security-group --description sg-rds --group-name "RDS Security Group" | grep GroupId | sed 's/"GroupId"://' | sed 's/"//g' | sed 's/,//g'`;echo $RDS_GROUP$ aws ec2 authorize-security-group-ingress --group-id $RDS_GROUP --protocol tcp --port 3306 --cidr **0.0.0.0/0***# For security reasons you may want the replace* ***0.0.0.0/0*** *with your web facing IP. This will limit traffic originating from your IP address only.*
我们将创建一个 MySQL 数据库。该数据库将用作 CDC 的来源。首先创建一个 RDS 参数组。
$ aws rds delete-db-parameter-group --db-parameter-group-name rds-mysql$ PG_ARN=`aws rds create-db-parameter-group --db-parameter-group-name rds-mysql --db-parameter-group-family MySQL5.7 --description "RDS Group" | grep DBParameterGroupArn | sed -e 's/"//g' -e 's/,//g' -e 's/DBParameterGroupArn//g' -e 's/: //g' `;echo $PG_ARN$ aws rds modify-db-parameter-group --db-parameter-group-name rds-mysql --parameters "ParameterName=binlog_format, ParameterValue=ROW,ApplyMethod=immediate" "ParameterName=binlog_checksum,ParameterValue=None,ApplyMethod=immediate"
创建 RDS 实例
$ aws rds delete-db-instance --db-instance-identifier fossil --skip-final-snapshot$ aws rds create-db-instance --db-instance-identifier fossil --db-instance-class db.t2.micro --engine mysql --region us-east-1 --output text --master-username admin --master-user-password admin123 --allocated-storage 20 --vpc-security-group-ids $RDS_GROUP --db-parameter-group-name rds-mysql --option-group-name default:mysql-5-7 --engine-version 5.7.30**-- Wait for 5-10 minutes after this step**
安装一个 MySQL 客户端并测试与 MySQL 的连接。将数据文件导入新创建的数据库。
$ sudo yum -y install mysql$ RDS_ENDPOINT=`aws rds describe-db-instances --db-instance-identifier fossil | grep "Address" | sed 's/.*://' | sed 's/"//g' | sed 's/,//g'`;echo $RDS_ENDPOINT$ mysql -uadmin -padmin123 -h $RDS_ENDPOINT -e "DROP DATABASE IF EXISTS fossil;CREATE DATABASE fossil;grant REPLICATION CLIENT on *.* to admin;grant REPLICATION SLAVE on *.* to admin;"$ mysql -uadmin -padmin123 -h $RDS_ENDPOINT fossil < blogs/dms/energy.sql$ mysql -uadmin -padmin123 -h $RDS_ENDPOINT -e "use fossil;select count(*) from coal_prod"
配置 DMS。首先创建 DMS 复制实例。
$ SG_RDS=`aws ec2 describe-security-groups --group-names "RDS Security Group" | grep GroupId | sed -e 's/"//g' -e 's/,//g' -e 's/GroupId//g' -e 's/: //g' `;echo $SG_RDS$ aws dms create-replication-instance --replication-instance-identifier rds-s3-dms --replication-instance-class dms.t2.micro --no-publicly-accessible --vpc-security-group-ids $SG_RDS$ REP_ARN=`aws dms describe-replication-instances | grep ReplicationInstanceArn | sed -e 's/"//g' -e 's/,//g' -e 's/ReplicationInstanceArn//g' -e 's/: //g' `;echo $REP_ARN**# wait 5 minutes for the above to finish**
创建 DMS 源端点。在这种情况下,上面创建的 RDS 实例将充当源。
$ DMS_END_SOURCE=`aws dms create-endpoint --endpoint-identifier rds-end --endpoint-type source --server-name $RDS_ENDPOINT --engine-name mysql --username admin --password admin123 --port 3306 --database-name fossil | grep EndpointArn | sed -e 's/"//g' -e 's/,//g' -e 's/EndpointArn//g' -e 's/: //g' `;echo $DMS_END_SOURCE
测试 DMS 源端点连接。只有在成功的情况下才能继续。
$ aws dms test-connection --replication-instance-arn $REP_ARN --endpoint-arn $DMS_END_SOURCE
按作者分类的图像— DMS 源端点
创建有权访问 S3 的 DMS 角色。我们将使用该角色来定义 DMS 目的地端点。
$ aws iam detach-role-policy --role-name dms-role --policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess$ aws iam delete-role --role-name dms-role$ DMS_ROLE=`aws iam create-role --role-name dms-role --assume-role-policy-document file://blogs/dms/policy.json | grep Arn | sed -e 's/"//g' -e 's/,//g' -e 's/Arn//g' -e 's/ //g' -e 's/://' `;echo $DMS_ROLE$ aws iam attach-role-policy --role-name dms-role --policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess**# you ay want to tighten up the above policy to limit access to specific buckets only**$ aws iam create-role --role-name dms-vpc-role --assume-role-policy-document file://blogs/dms/policy.json$ aws iam attach-role-policy --role-name dms-vpc-role --policy-arn arn:aws:iam::aws:policy/service-role/AmazonDMSVPCManagementRole
创建 DMS 目标端点
$ S3_JSON="{\"ServiceAccessRoleArn\": \"$DMS_ROLE\",\"BucketFolder\": \"raw/dms\",\"BucketName\": \"aws-analytics-course\",\"DataFormat\": \"csv\", \"IncludeOpForFullLoad\": true }";echo $S3_JSON >s3.json;cat s3.json$ DMS_END_DEST=`aws dms create-endpoint --endpoint-identifier s3-end --engine-name s3 --endpoint-type target --s3-settings file://s3.json | grep EndpointArn | sed -e 's/"//g' -e 's/,//g' -e 's/EndpointArn//g' -e 's/: //g' `;echo $DMS_END_DEST$ aws dms test-connection --replication-instance-arn $REP_ARN --endpoint-arn $DMS_END_DEST
按作者分类的图像— DMS 目标端点
创建并运行 DMS 任务。在第一次运行时,该任务将从源端点的所有表中获取全部数据,并将数据复制到目的端点。之后,复制实例跟踪源端点上的更改,并迅速将它们传递到目标。在这个过程中,复制实例维护每个表的日志。
$ aws dms create-replication-task --replication-task-identifier rdstos3 --source-endpoint-arn $DMS_END_SOURCE --target-endpoint-arn $DMS_END_DEST --replication-instance-arn $REP_ARN **--migration-type full-load-and-cdc ** --table-mappings file://blogs/dms/table-mappings.json$ TASK_ARN=` aws dms describe-replication-tasks | grep ReplicationTaskArn | sed -e 's/"//g' -e 's/,//g' -e 's/ReplicationTaskArn//g' -e 's/ //g' -e 's/://' `;echo $TASK_ARN$ aws dms start-replication-task --replication-task-arn $TASK_ARN --start-replication-task-type reload-target
按作者分类的图像—复制任务的状态
一旦 DMS 作业运行,我们就可以检查 S3 上满负载的数据
$ aws s3 ls aws-analytics-course/raw/dms/$ aws s3 ls aws-analytics-course/raw/dms/
PRE fossil/$ aws s3 ls aws-analytics-course/raw/dms/fossil/
PRE coal_prod/
PRE fossil_capita/
PRE gas_prod/
PRE oil_prod/$ aws s3 ls aws-analytics-course/raw/dms/fossil/coal_prod/
2020-07-13 18:08:09 326026 LOAD00000001.csv
请注意,每条记录都标记了 DML 操作,在本例中,所有行都标记了 Insert (I ),因为这是第一次将数据从源装载到目标。
作者图片
让我们对源数据库执行更多的 DML 操作——插入、更新和删除。从几个插页开始。
$ mysql -uadmin -padmin123 -h $RDS_ENDPOINT fossil -e "INSERT INTO fossil.coal_prod VALUES('India', 'IND', 2015, 4056.33, 0.00);INSERT INTO fossil.coal_prod VALUES('India', 'IND', 2016, 4890.45, 0.00)"
作者图片
注意,S3 的文件将新插入的行标记为“I”。现在让我们发送一个更新。
$ mysql -uadmin -padmin123 -h $RDS_ENDPOINT fossil -e "UPDATE fossil.coal_prod SET Production=2845.66, consumption=145.66 WHERE Entity='India' AND Year=2013"
作者图片
注意,S3 的文件将新插入的行标记为“U”。最后发个删除。
$ mysql -uadmin -padmin123 -h $RDS_ENDPOINT fossil -e "DELETE FROM fossil.coal_prod WHERE Entity='India' AND Year=2010"
作者图片
请注意,S3 的文件将新插入的行标记为“D”。
有什么大惊小怪的?毕竟它只是插入、更新和删除。
既然我们已经有了连续复制,源端和目标端将保持同步。在本文的第 2 部分,我将向您展示如何使用 Apache 胡迪将 CDC 接收到数据湖中。
如果您将本文用于测试/教育,不要忘记在完成后清理您的 AWS 资源。如果在生产中使用,DMS 资源将永久部署。
$ aws dms stop-replication-task --replication-task-arn $TASK_ARN$ aws dms delete-replication-task --replication-task-arn $TASK_ARN$ aws dms delete-endpoint --endpoint-arn $DMS_END_SOURCE$ aws dms delete-endpoint --endpoint-arn $DMS_END_DEST$ aws dms delete-replication-instance --replication-instance-arn $REP_ARN$ aws rds delete-db-instance --db-instance-identifier fossil --skip-final-snapshot
本文中使用的所有代码都可以在下面的链接中找到:
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/mkukreja1/blogs/tree/master/dms)
我希望这篇文章是有帮助的。 CDC 使用亚马逊数据库迁移服务是由 Datafence 云学院提供的 AWS 大数据分析课程的一部分。课程是周末自己在网上教的。
在 Amazon EMR 上使用 Apache 胡迪进行数据湖变更数据捕获(CDC)——第 2 部分——流程
使用 Amazon EMR 上的 Apache 胡迪轻松处理从数据库到数据湖的数据变化
图片由来自 Pixabay 的 Gino Crescoli 拍摄
在下面的前一篇文章中,我们讨论了如何使用亚马逊数据库迁移服务(DMS)无缝地收集 CDC 数据。
下一篇文章将展示如何处理 CDC 数据,以便在数据湖中实现数据库的接近实时的表示。我们将使用 Apache 胡迪和 Amazon EMR 的联合力量来执行此操作。Apache 胡迪是一个开源数据管理框架,用于简化近乎实时的增量数据处理。
我们将通过创建一个新的 EMR 集群来启动该流程
$ aws emr create-cluster --auto-scaling-role EMR_AutoScaling_DefaultRole --applications Name=Spark Name=Hive --ebs-root-volume-size 10 --ec2-attributes '{"KeyName":"roopikadf","InstanceProfile":"EMR_EC2_DefaultRole","SubnetId":"subnet-097e5d6e","EmrManagedSlaveSecurityGroup":"sg-088d03d676ac73013","EmrManagedMasterSecurityGroup":"sg-062368f478fb07c11"}' --service-role EMR_DefaultRole --release-label emr-6.0.0 --name 'Training' --instance-groups '[{"InstanceCount":3,"EbsConfiguration":{"EbsBlockDeviceConfigs":[{"VolumeSpecification":{"SizeInGB":32,"VolumeType":"gp2"},"VolumesPerInstance":2}]},"InstanceGroupType":"CORE","InstanceType":"m5.xlarge","Name":"Core - 2"},{"InstanceCount":1,"EbsConfiguration":{"EbsBlockDeviceConfigs":[{"VolumeSpecification":{"SizeInGB":32,"VolumeType":"gp2"},"VolumesPerInstance":2}]},"InstanceGroupType":"MASTER","InstanceType":"m5.xlarge","Name":"Master - 1"}]' --scale-down-behavior TERMINATE_AT_TASK_COMPLETION --region us-east-1 --bootstrap-actions Path=s3://aws-analytics-course/job/energy/emr.sh,Name=InstallPythonLibs
创建 EMR 集群后,使用 SSH 登录到主节点,并发出以下命令。这些命令将把 Apache 胡迪 JAR 文件复制到 S3。
$ aws s3 cp /usr/lib/hudi/hudi-spark-bundle.jar s3://aws-analytics-course/hudi/jar/ upload: ../../usr/lib/hudi/hudi-spark-bundle.jar to s3://aws-analytics-course/hudi/jar/hudi-spark-bundle.jar$ aws s3 cp /usr/lib/spark/external/lib/spark-avro.jar s3://aws-analytics-course/hudi/jar/
upload: ../../usr/lib/spark/external/lib/spark-avro.jar to s3://aws-analytics-course/hudi/jar/spark-avro.jar$ aws s3 ls s3://aws-analytics-course/hudi/jar/
2020-10-21 17:00:41 23214176 hudi-spark-bundle.jar
2020-10-21 17:00:56 101212 spark-avro.jar
现在创建一个新的 EMR 笔记本并上传到以下位置。上传胡迪/hudi.ipynb
$ git clone https://github.com/mkukreja1/blogs.git
使用在上一步中上传到 S3 的胡迪 JAR 文件创建一个 Spark 会话。
from pyspark.sql import SparkSession
import pyspark
from pyspark.sql.types import StructType, StructField, IntegerType, StringType, array, ArrayType, DateType, DecimalType
from pyspark.sql.functions import *
from pyspark.sql.functions import concat, lit, colspark = pyspark.sql.SparkSession.builder.appName("Product_Price_Tracking") \
**.config("spark.jars", "s3://aws-analytics-course/hudi/jar/hudi-spark-bundle.jar,s3://aws-analytics-course/hudi/jar/spark-avro.jar")** \
.config("spark.serializer", "org.apache.spark.serializer.KryoSerializer") \
.config("spark.sql.hive.convertMetastoreParquet", "false") \
.getOrCreate()
让我们读取疾病控制中心的文件。我们将从读取完整的加载文件开始。
TABLE_NAME = "coal_prod"
S3_RAW_DATA = "s3://aws-analytics-course/raw/dms/fossil/coal_prod/LOAD00000001.csv"
S3_HUDI_DATA = "s3://aws-analytics-course/hudi/data/coal_prod"coal_prod_schema = StructType([StructField("Mode", StringType()),
StructField("Entity", StringType()),
StructField("Code", StringType()),
StructField("Year", IntegerType()),
StructField("Production", DecimalType(10,2)),
StructField("Consumption", DecimalType(10,2))
])
df_coal_prod = spark.read.csv(S3_RAW_DATA, header=False, schema=coal_prod_schema)df_coal_prod.show(5)+----+-----------+----+----+----------+-----------+
|Mode| Entity|Code|Year|Production|Consumption|
+----+-----------+----+----+----------+-----------+
| I|Afghanistan| AFG|1949| 0.04| 0.00|
| I|Afghanistan| AFG|1950| 0.11| 0.00|
| I|Afghanistan| AFG|1951| 0.12| 0.00|
| I|Afghanistan| AFG|1952| 0.14| 0.00|
| I|Afghanistan| AFG|1953| 0.13| 0.00|
+----+-----------+----+----+----------+-----------+
only showing top 5 rows
Apache 胡迪需要一个主键来唯一标识每个记录。通常,顺序生成的主键最适合此目的。然而我们的桌子没有。为了解决这个问题,让我们通过使用实体和年份列的组合来生成一个 PK。下面的键列将被用作主键。
df_coal_prod=df_coal_prod.select("*", concat(col("Entity"),lit(""),col("Year")).alias("key"))
df_coal_prod_f=df_coal_prod.drop(df_coal_prod.Mode)
df_coal_prod_f.show(5)+-----------+----+----+----------+-----------+---------------+
| Entity|Code|Year|Production|Consumption| **key**|
+-----------+----+----+----------+-----------+---------------+
|Afghanistan| AFG|1949| 0.04| 0.00|Afghanistan1949|
|Afghanistan| AFG|1950| 0.11| 0.00|Afghanistan1950|
|Afghanistan| AFG|1951| 0.12| 0.00|Afghanistan1951|
|Afghanistan| AFG|1952| 0.14| 0.00|Afghanistan1952|
|Afghanistan| AFG|1953| 0.13| 0.00|Afghanistan1953|
+-----------+----+----+----------+-----------+---------------+
only showing top 5 rows
我们现在准备以胡迪格式保存数据。由于这是我们第一次保存该表,我们将使用" bulk_insert "操作和模式=覆盖。还要注意,我们使用“键列作为记录键。
df_coal_prod_f.write.format("org.apache.hudi") \
.option("hoodie.table.name", TABLE_NAME) \
.option("hoodie.datasource.write.storage.type", "COPY_ON_WRITE") \
**.option("hoodie.datasource.write.operation", "bulk_insert") \
.option("hoodie.datasource.write.recordkey.field","key")** \
.option("hoodie.datasource.write.precombine.field", "key") \
.mode("**overwrite**") \
.save(S3_HUDI_DATA)
我们现在可以读取新创建的胡迪表。
df_final = spark.read.format("org.apache.hudi")\
.load("s3://aws-analytics-course/hudi/data/coal_prod/default/*.parquet")
df_final.registerTempTable("coal_prod")
spark.sql("select count(*) from coal_prod").show(5)
spark.sql("select * from coal_prod where key='India2013'").show(5)+--------+
|count(1)|
+--------+
| **6282**|
+--------+
+-------------------+--------------------+------------------+----------------------+--------------------+------+----+----+----------+-----------+---------+
|_hoodie_commit_time|_hoodie_commit_seqno|_hoodie_record_key|_hoodie_partition_path| _hoodie_file_name|Entity|Code|Year|Production|Consumption| key|
+-------------------+--------------------+------------------+----------------------+--------------------+------+----+----+----------+-----------+---------+
| 20201021215857|20201021215857_54...| India2013| default|8fae00ae-34e7-45e...| India| IND|2013| **2841.01**| **0.00**|India2013|
+-------------------+--------------------+------------------+----------------------+--------------------+------+----+----+----------+-----------+---------+
请注意,我们有来自满载的 6282 行和 2013 年关键**印度的数据。**该密钥将在下一次操作中更新,因此记录历史非常重要。我们现在将读取增量数据。
增量数据带有 4 行,插入 2 行,更新一行,删除和一行。我们将首先处理插入和更新的行。注意下面的**(“模式输入(’ U ‘,’ I ')”)**的过滤器。
S3_INCR_RAW_DATA = "s3://aws-analytics-course/raw/dms/fossil/coal_prod/20200808-*.csv"
df_coal_prod_incr = spark.read.csv(S3_INCR_RAW_DATA, header=False, schema=coal_prod_schema)
**df_coal_prod_incr_u_i=df_coal_prod_incr.filter("Mode IN ('U', 'I')")**
df_coal_prod_incr_u_i=df_coal_prod_incr_u_i.select("*", concat(col("Entity"),lit(""),col("Year")).alias("key"))
df_coal_prod_incr_u_i.show(5)df_coal_prod_incr_u_i_f=df_coal_prod_incr_u_i.drop(df_coal_prod_incr_u_i.Mode)
df_coal_prod_incr_u_i_f.show()+----+------+----+----+----------+-----------+---------+
|Mode|Entity|Code|Year|Production|Consumption| key|
+----+------+----+----+----------+-----------+---------+
| I| India| IND|2015| 4056.33| 0.00|India2015|
| I| India| IND|2016| 4890.45| 0.00|India2016|
| U| India| IND|2013| 2845.66| 145.66|India2013|
+----+------+----+----+----------+-----------+---------+
+------+----+----+----------+-----------+---------+
|Entity|Code|Year|Production|Consumption| key|
+------+----+----+----------+-----------+---------+
| India| IND|2015| 4056.33| 0.00|India2015|
| India| IND|2016| 4890.45| 0.00|India2016|
| India| IND|2013| 2845.66| 145.66|India2013|
+------+----+----+----------+-----------+---------+
我们现在准备对增量数据执行胡迪上插操作。由于这个表已经存在,这次我们将使用追加选项。
df_coal_prod_incr_u_i_f.write.format("org.apache.hudi") \
.option("hoodie.table.name", TABLE_NAME) \
.option("hoodie.datasource.write.storage.type", "COPY_ON_WRITE") \
**.option("hoodie.datasource.write.operation", "upsert")** \
.option("hoodie.upsert.shuffle.parallelism", 20) \
.option("hoodie.datasource.write.recordkey.field","key") \
.option("hoodie.datasource.write.precombine.field", "key") \
.mode("**append**") \
.save(S3_HUDI_DATA)
检查基础数据。请注意,已经添加了 2 个新行,因此表计数已经从 6282 增加到 6284。另请注意,2013 年印度的关键行现已更新为生产&消耗列。
df_final = spark.read.format("org.apache.hudi")\
.load("s3://aws-analytics-course/hudi/data/coal_prod/default/*.parquet")
df_final.registerTempTable("coal_prod")
spark.sql("select count(*) from coal_prod").show(5)
spark.sql("select * from coal_prod where key='India2013'").show(5)+--------+
|count(1)|
+--------+
| **6284**|
+--------+
+-------------------+--------------------+------------------+----------------------+--------------------+------+----+----+----------+-----------+---------+
|_hoodie_commit_time|_hoodie_commit_seqno|_hoodie_record_key|_hoodie_partition_path| _hoodie_file_name|Entity|Code|Year|**Production**|**Consumption**| key|
+-------------------+--------------------+------------------+----------------------+--------------------+------+----+----+----------+-----------+---------+
| 20201021220359|20201021220359_0_...| India2013| default|8fae00ae-34e7-45e...| India| IND|2013| **2845.66**| **145.66**|India2013|
+-------------------+--------------------+------------------+----------------------+--------------------+------+----+----+----------+-----------+---------+
现在我们要处理删除了行的行。
df_coal_prod_incr_d=df_coal_prod_incr.filter**("Mode IN ('D')")**
df_coal_prod_incr_d=df_coal_prod_incr_d.select("*", concat(col("Entity"),lit(""),col("Year")).alias("key"))
df_coal_prod_incr_d_f=df_coal_prod_incr_d.drop(df_coal_prod_incr_u_i.Mode)
df_coal_prod_incr_d_f.show()+------+----+----+----------+-----------+---------+
|Entity|Code|Year|Production|Consumption| key|
+------+----+----+----------+-----------+---------+
| India| IND|2010| 2710.54| 0.00|India2010|
+------+----+----+----------+-----------+---------+
我们可以通过胡迪 Upsert 操作来实现这一点,但是需要使用额外的选项来删除hoodie . data source . write . payload . class = org . Apache . hudi . emptyhoodierecordpayload
df_coal_prod_incr_d_f.write.format("org.apache.hudi") \
.option("hoodie.table.name", TABLE_NAME) \
.option("hoodie.datasource.write.storage.type", "COPY_ON_WRITE") \
.option("hoodie.datasource.write.operation", "upsert") \
.option("hoodie.upsert.shuffle.parallelism", 20) \
.option("hoodie.datasource.write.recordkey.field","key") \
.option("hoodie.datasource.write.precombine.field", "key") \
** .option("hoodie.datasource.write.payload.class", "org.apache.hudi.EmptyHoodieRecordPayload") \**
.mode("append") \
.save(S3_HUDI_DATA)
我们现在可以检查结果。由于删除了一行,计数从 6284 下降到 6283。此外,对已删除行的查询返回空值。一切都按预期进行。
df_final = spark.read.format("org.apache.hudi")\
.load("s3://aws-analytics-course/hudi/data/coal_prod/default/*.parquet")
df_final.registerTempTable("coal_prod")
spark.sql("select count(*) from coal_prod").show(5)
spark.sql("select * from coal_prod where key='India2010'").show(5)+--------+
|count(1)|
+--------+
| **6283**|
+--------+
+-------------------+--------------------+------------------+----------------------+-----------------+------+----+----+----------+-----------+---+
|_hoodie_commit_time|_hoodie_commit_seqno|_hoodie_record_key|_hoodie_partition_path|_hoodie_file_name|Entity|Code|Year|Production|Consumption|key|
+-------------------+--------------------+------------------+----------------------+-----------------+------+----+----+----------+-----------+---+
+-------------------+--------------------+------------------+----------------------+-----------------+------+----+----+----------+-----------+---+
本文中使用的所有代码都可以在下面的链接中找到:
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/mkukreja1/blogs/tree/master/dms)
我希望这篇文章是有帮助的。 CDC 使用亚马逊数据库迁移服务是由 Datafence Cloud Academy 提供的 AWS 大数据分析课程的一部分。课程是周末自己在网上教的。
数据湖—比较已知大数据格式的性能
众所周知的大数据格式(CSV、JSON、AVRO、PARQUET 和 ORC)的性能比较
米卡·鲍梅斯特在 Unsplash 上的照片
在过去的几年里,我一直在大数据项目中使用各种数据格式。在这段时间里,我强烈倾向于一种形式,而不是另一种——我的失败给了我一些教训。在我的讲座中,我一直强调为正确的目的使用正确的数据格式的重要性——这让世界变得不同。
一直以来,我都在想,我是否向我的客户和学生传授了正确的知识。我可以用数据来支持我的主张吗?因此,我决定做这个性能比较。
在我开始比较之前,让我简要地向您描述一下所考虑的各种数据格式。
行格式
CSV、JSON 和 Avro(二进制)
分栏格式
拼花地板和 ORC(都是二元的)
我相信你一定想知道行和列格式之间的区别。数据在磁盘上的存储方式至关重要。行格式存储为行 1 >行 2 >行 3 列格式存储到磁盘为列 1 >列 2 >列 3
一切都好,但这有什么关系…数据就是数据。不完全是。如果我让你平均一下工资栏呢。对于数据的行格式,需要从磁盘中读取每一行,提取薪金列,然后进行平均。这消耗了大量的 IO,因为需要读取大量的磁盘扇区。
对于列格式,从磁盘中一次性读取连续的薪金列块,然后进行平均。更少的 IO 意味着更高的性能。像平均、求和等数学运算。包括很大一部分数据分析处理——自然,柱状格式在 OLAP 更受欢迎
作者图片
如果行格式那么糟糕,为什么还在使用?如果您正在执行 OLTP,行格式显然是最佳选择。在 web/mobile 应用程序中,您不太关心一系列行的数学处理,但是您确实希望快速访问单个行。这就是自动选择行格式的地方。由于这个原因,所有已知的关系数据库都以这种方式存储数据。
性能比较—平台
存储层: Hadoop 3 .2.1— Hadoop 文件系统(HDFS)
**计算层:**Spark 3-4 个工作线程-32 个内核 58GB
**数据样本量:**HDFS 存储 5 亿行
样本数据:
+-----+---------+----------+
|stock| price| timetamp|
+-----+---------+----------+
| AMZN| 121.1792|1600952178|
| SBUX|132.03702|1600952178|
| MCD| 407.2828|1600952178|
| MCD| 43.12032|1600952178|
| MSFT|115.79154|1600952178|
+-----+---------+----------+
加工操作
- 按照这个顺序[股票,价格,时间]对 5 亿行进行排序,并将结果保存到 HDFS
- 按股票分组数据,找到最高价,并将结果保存到 HDFS
性能比较结果
以下是不同格式的文件大小的结果。请注意 5 亿行文件大小的巨大差异。JSON 的占地面积最大,而 Parquet 的占地面积最小。
作者图片
JSON 占用的内存最大,因为它存储了每行的模式属性。因此,我很少将 JSON 或 CSV 格式存储在数据湖的管理和转换区域中。JSON 和 CSV 格式仍然是最广泛使用的数据交换方法。我特别注意在从源代码中获取之后将它们转换成二进制格式。我的数据湖通常看起来像:
原始区域:JSON 或 CSV
策划和改造区:Avro、ORC 或拼花地板(或其组合)
以下是不同格式的排序操作的结果。不出所料,JSON 表现最慢,Parquet、ORC 最快。我必须承认,看到 AVRO 表现得相当好,我有点惊讶。
作者图片
以下是分组操作的结果,并找出不同格式的最大值。注意,这个操作本质上是纯数学的。它非常类似于数据分析用例。我很高兴地证实,所有二进制格式(AVRO,拼花,ORC)表现相当不错。
Parquet 和 ORC 的性能几乎相同,但 ORC 的文件占用空间略小。看到近年来 ORC 的采用率大幅下降并不奇怪。我几乎不再遇到任何使用 ORC 格式的项目。
作者图片
总之,我现在可以有把握地推断,Parquet 和 ORC 格式确实非常适合数据分析操作。从这篇文章中得到的另一个非常重要的启示是— **立即停止在您的管理和转换区域中使用 CSV、JSON。**这似乎是显而易见的,但你会惊讶地发现,我遇到过多少次不遵循这一规则的部署。
这种比较的所有代码都可以在下面的链接中找到:
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/mkukreja1/blogs/tree/master/data-formats)
我希望这篇文章是有帮助的。由 Datafence Cloud Academy 提供的大数据格式主题将作为大数据 Hadoop、Spark & Kafka 课程的一部分进行详细介绍。课程是周末自己在网上教的。
AWS 上的数据湖设计模式——简单、恰到好处和复杂
为您的企业选择正确的 AWS 数据湖设计指南
图片来自皮克斯拜
互联网上对数据湖有不同的定义。一些站点将它定义为存储结构化和非结构化数据的集中存储库,其他站点则讨论以原始格式存储数据,以便以后可以使用 schema on read 对其进行处理。一切都好…但我想补充一些关于存储和计算层的非常重要的内容。
过去几年,我参与了几个数据湖项目,其中存储层与计算层非常紧密耦合。尽管这种设计非常适合使用本地物理/虚拟机的基础架构。但是,对于云基础架构来说,这可能不是最好的主意,因为资源需要全天候可用。
作者图片
存储便宜,但计算昂贵——分离存储和计算
作为替代方案,我支持将存储和计算分离的想法。这样,唯一不昂贵的存储层需要 24x7 全天候运行,而昂贵的计算层只能在需要时按需创建。
作者图片
我在以前的一篇文章中演示了如何做到这一点(链接如下)。
Data ops——使用 AWS Lambda 和 Amazon EMR 的全自动低成本数据管道
因为我们支持存储和计算分离的想法,所以让我们讨论 AWS 上的一些数据湖设计模式。我尝试根据 3 个关键因素对每个模式进行分类:
- 费用
- 操作简单
- 用户基础
简单的
数据收集过程不断地将各种来源的数据转储到亚马逊 S3。使用 Glue crawler 可以推断出数据的模式和格式,表元数据存储在 AWS Glue Catalog 中。对于数据分析,用户可以使用 Amazon Athena 通过标准 SQL 查询数据。
低成本、操作简单(无服务器架构)。使用标准 SQL 进行查询让分析师、商业智能开发人员和特别报告用户非常高兴。对于数据科学家、机器学习/人工智能工程师来说,情况并非如此。他们通常希望从文件中获取数据,最好是大文件和二进制格式,如 Parquet、ORC 和 Avro。
正好
数据收集过程不断地将各种来源的数据转储到亚马逊 S3。粘合 ETL 作业管理/转换数据,并将数据写入大型 Parquet/ORC/Avro。使用 Glue crawler 推断出管理/转换数据的模式和格式,并将表元数据存储在 AWS Glue Catalog 中。对于数据分析,用户可以选择使用 Amazon Athena 使用标准 SQL 查询数据,或者从 S3 获取文件。
作者图片
价格经济、操作简单(无服务器架构)。分析师、商业智能开发人员可以选择使用 Amazon Athena。数据科学家、机器学习/人工智能工程师可以以最适合他们需求的合适格式获取大文件。每个人都很开心……算是吧。
这种模式的缺点是,它将复杂的转换和连接数据操作推给 Amazon Athena 处理,或者假设这些操作将由数据科学家和机器学习/AI 工程师以编程方式处理。在某些情况下,这两个选项都不理想,因为它们会降低性能,并且会导致数据不标准和不可重用。
老练的人
数据收集过程不断地将各种来源的数据转储到亚马逊 S3。粘合 ETL 作业管理/转换数据,并将数据写入大型 Parquet/ORC/Avro。这些数据被复制到 Amazon Redshift 表中,该表使用键分布将数据存储在跨越多个节点的表中。用户不仅可以利用 Amazon Redshift 进行即席报告,还可以进行复杂的转换和连接数据集。此外,经过转换和连接的数据版本可以转储到大型文件中,供数据科学家和机器学习/人工智能工程师使用。每个人都非常高兴。
作者图片
价格较高,操作相对简单(无服务器架构)。使用分布式和并行处理执行所有计算,因此性能相当好。每个人都能以他们需要的形式得到他们需要的东西。较高的价格可能是合理的,因为它通过以标准化和可重用的方式执行复杂的转换来简化它们。
我希望以上信息能帮助您为自己的企业选择正确的数据湖设计。如果你需要进一步的帮助,我随时乐意与你聊天。
我希望这篇文章是有帮助的。 AWS 数据湖是由 Datafence 云学院提供的 AWS 大数据分析课程的一部分。课程是周末自己在网上教的。
使用 Terraform 的 GCP 数据湖
使用 Terraform 为谷歌云平台上的数据湖建立基础设施代码。
我们将在这个项目中建设的总结(作者图片)
过去,处理物理基础架构是一项巨大的负担,不仅需要专家团队来管理,而且非常耗时。然而,在现代云计算时代,只需点击一个按钮,你就可以立即部署数百台计算机来解决你的问题。实际上,我们试图解决的大多数日常问题并不需要那么多的计算能力。
什么是基础设施即代码(IaC)
基础设施即代码(IaC)是通过机器可读的定义文件,而不是物理硬件配置或交互式配置工具来管理和配置计算机数据中心的过程。
因此,您可以编写代码来完成所有这些工作,而不是将物理服务器放在机架上,设置所有电缆,配置网络,安装所有必需的操作系统。要使用 IaC,您通常会使用源代码控制库,编写代码来配置您的基础设施,在本地运行代码,或者设置一个自动化来在每次提交时执行您的代码。
为什么是 IaC?
你可能会问,既然可以通过所有云提供商的界面来管理基础设施,为什么还要设置和学习新的东西呢?对我们的基础设施进行版本控制有很多好处。
再现性
IaC 使您能够轻松地创建不同的环境,尤其是当您的项目很复杂,并且有许多活动部分时。例如,在设置了包含多个项目、VPC、存储、计算实例和 IAM 的开发环境后,对试运行和生产环境做同样的事情会适得其反。
使用 IaC,您可以通过对您的代码库做一些小的修改来复制您的环境。您甚至可以定制您的环境来满足您的需求。例如,您可以为生产和开发设置不同的机器类型,或者为开发设置更宽松的 IAM。
想象一下,如果一个实习生搞乱了你的生产环境,你可以拆除一切,轻松构建你的环境(假设你的底层数据毫发无损)
安全性
在大型项目中,您可以拥有具有复杂权限和策略的环境。您不仅要担心设计和设置这些环境,而且实施策略和权限也很有挑战性。
有了 IaC,您环境中的每一个更改都被版本化,因此您知道谁做了什么更改(假设您将管理权限限制为仅您的 IaC 服务)。您还可以定期扫描您的环境,查看配置和实际环境之间的差异。如果大多数 IaC 服务检测到任何变更,它们将能够将您的环境恢复到配置。
合作
当您的基础设施由代码管理时,您可以在团队之间共享它们,或者在以后的项目中使用它们。您还可以根据配置自动生成基础设施文档。
在 GCP 上使用 Terraform 开始使用 IaC
很好,那么让我们开始使用 Terraform 在 Google 云平台上建立数据湖的基础设施。您可以在任何其他云提供商上使用任何其他 IaC 工具,我选择这种组合,因为它对我来说很熟悉。
Terraform 是由 HashiCorp 创建的开源基础设施代码软件工具。它使用户能够使用一种称为 HashiCorp 配置语言的声明式配置语言,或可选的 JSON,来定义和配置数据中心基础架构。Terraform 通过“提供者”管理外部资源。维基百科
我们将在这个项目中建设的总结(作者图片)
在这个项目中,我们将使用 terraform 代码为 GCP 的一个数据湖提供资源和权限。上图是数据湖的简化版本,我们将编写代码在 GCP 上提供和设置一切。
让我简要介绍一下 GCP 上一个典型数据湖的架构(为了简单起见,我只考虑批处理管道)。您通常会有生成数据的系统,在本地运行,或者您需要连接的其他云提供商/项目。出于安全目的,您可以通过 VPN 或互连连接到这些系统。然后,您将需要一个编排/暂存服务器来提取数据并将它们加载到您的存储桶中。
然后,数据将被分类并加载到不同的桶中。原始数据通常会被接收到着陆桶中。包含敏感客户信息的数据将被单独处理(屏蔽、去识别、单独的许可政策)并加载到敏感存储桶中。工作桶用于数据工程师和数据科学家的在制品数据,备份桶用于清洗数据的备份。
然后,数据将被加载到数据仓库,在那里,数据将根据接收系统进行分离(不同的公司可能会有不同的做法)。这里的数据根据需要进行清理、规格化/反规格化,并建模以备后用。来自数据仓库的数据将被进一步建模、聚合并加载到数据集市。数据集市通常按业务功能组织,如市场营销、销售和财务。
您可以看到,我们有几个层,不同的团队访问这些层。上面的架构是基于我们的工作和具体的业务问题。欢迎任何建设性的反馈:)
开始之前
您需要为此项目做以下工作:
- 下载并设置 Terraform CLI: 使用本入门指南在您的本地机器上安装 Terraform CLI。
- 创建一个谷歌云账户:如果你还没有,注册一个谷歌云账户。注册时你将获得 300 美元的信用,足够让你不用花一美元就能完成本教程。
- 获取您的账单 ID: 遵循此处的指南在 GCP 上找到您的账单 ID。你以后会需要它的。
- 安装 gcloud CLI :使用这个链接帮助你在本地安装 gcloud CLI。
你可以在这里查看该项目的完整代码。
使用 Terraform 为谷歌云平台上的数据湖建立基础设施代码。你需要做…
github.com](https://github.com/tuanchris/data-lake-iac)
在 GCP 上使用 Terraform 开始使用 IaC
向 GCP 认证
首先,我们需要向 GCP 认证。将以下注释粘贴到终端,并按照说明进行操作。
gcloud auth application-default login
Setup main.tf
用以下内容创建一个main.tf
文件:
provider "google" {}
这将为我们的 terraform 项目设置提供者。
terraform init
创建项目
现在我们可以开始建立我们的基础设施。我们将首先为数据湖和数据仓库创建两个项目。你可以把你所有的设置放在一个巨大的main.tf
文件中,但是我建议根据服务分开。让我们创建一个新的project.tf
文件,我们将在其中定义我们的项目。
第一行将定义我们想要创建的资源:google_project
。下一位data-lake
是被其他服务引用的资源的名称。将project_id
替换为全球唯一的 ID(包括您的姓名或项目),将billing_account
替换为您自己的 ID。
terraform apply
您将看到如下输出:
# google_project.data-lake will be created
+ resource "google_project" "data-lake" {
+ auto_create_network = true
+ billing_account = ""
+ folder_id = (known after apply)
+ id = (known after apply)
+ name = "Data Lake"
+ number = (known after apply)
+ org_id = (known after apply)
+ project_id = "cloud-iac-data-lake"
+ skip_delete = true
}# google_project.data-warehouse will be created
+ resource "google_project" "data-warehouse" {
+ auto_create_network = true
+ billing_account = ""
+ folder_id = (known after apply)
+ id = (known after apply)
+ name = "Data Warehouse"
+ number = (known after apply)
+ org_id = (known after apply)
+ project_id = "cloud-iac-data-warehouse"
+ skip_delete = true
}# google_project.data-marts will be created
+ resource "google_project" "data-marts" {
+ auto_create_network = true
+ billing_account = ""
+ folder_id = (known after apply)
+ id = (known after apply)
+ name = "Data Marts"
+ number = (known after apply)
+ org_id = (known after apply)
+ project_id = "cloud-iac-data-marts"
+ skip_delete = true
}
这是详细说明 terraform 将创建什么的提示。研究这些以确保结果与您想要做的相匹配,并在终端中键入yes
。
您已经成功地创建了三个项目:数据湖、数据仓库和数据集市!转到 GCP 控制台验证您的结果。请注意,每个计费帐户最多只能有三个项目,这可能会阻止您继续操作。
定义变量
在继续之前,我们先来谈谈变量。你可以看到,在我们上面的project.tf
中的 terraform 代码中,我们使用特定的名称作为项目 ID。这并不总是最好的方式。想象一下,如果我们想在其他地方使用代码,我们必须手动更改所有的名称。
相反,我们可以定义一个将在整个项目中使用的variables.tf
文件。我们可以把常用的变量存储在那里。我们可以使用不同类型的变量,但为了简单起见,我将使用局部变量。你可以在这里阅读更多关于地形变量的内容。
locals {
region = "asia-southeast1"
unique_id = "cloud-iac"
billing_id = ""
}
创建 GCS 资源
以类似的方式创建三个项目,我们可以创建我们需要的 4 个 GCS 存储桶:landing
、sensitive
、work
和backup
存储桶。创建一个gcs.tf
文件并粘贴到以下内容中:
运行terraform apply
并输入yes
,您将在我们的数据湖项目中创建了四个存储桶。在上面的代码中,您可以看到我们使用变量来引用项目和存储桶的区域。如果我们需要再次创建数据湖(可能是为不同的客户,或者不同的公司),我们只需要改变variables.tf
中的值。相当强大的东西!
为 GCS 存储桶配置 ACL 权限
现在我们需要为不同的团队提供不同的权限。例如,DE 应该可以访问所有桶,而 DS 不能访问sensitive
桶,只能在landing
和backup
上读取,但可以在work
上写入。我们可以用下面的代码很容易地设置它:
我们将创建 Google groups 来管理不同团队中的人员,使权限控制变得更容易(而不是在这里有十个不同的电子邮件来获得权限,我们只需要每个团队一个电子邮件)。
请记住,如果电子邮件不存在,terraform 命令将失败。
数据仓库
接下来,我们将为我们的数据仓库创建数据集。回到图中,我们有三个系统,因此将创建三个相应的数据集。与 GCS 不同,我们可以在google_bigquery_dataset
定义中定义 Bigquery ACL。
我们将为数据仓库数据集配置相同的 ACL。DE 将是这些数据集的owner
(在生产环境中,建议设置一个服务帐户作为所有者),DS 将是writer
,DA 将是reader
。
数据集市
对于我们的数据集市,我们将拥有与数据仓库相似的配置,但是具有不同的访问权限。
计算引擎
对于编排部分,我们将构建一个 VPC 网络、一个编排实例和一个静态外部 IP 地址。如果你通读下面的代码,这里没有什么复杂的事情。你可以在这里阅读关于如何创建实例的 Terraform 文档。
IAM 权限
最后但同样重要的是,我们需要为我们的项目设置 IAM 权限。对于这一部分,我将只提供一个示例,但是我们可以将每个组映射到任何角色,如下所示。
结论
在这个迷你项目中,我们已经创建了在 Google Cloud 上运行数据湖所需的大部分基础设施。您可能需要更深入地为您的特定需求定制代码。
打扫
不要忘记清理未使用的资源,以避免任何意外收费。使用 terraform,您可以运行一个命令来拆除一切。
terraform destroy
希望你学到了一些东西:)
数据湖、Oracle ADWH 和对象存储
引言。
现在是 2020 年,再也没有时间使用大型昂贵的集群了。
如今,构建在云环境中的现代数据湖,应该尽可能多地使用云原生的、无服务器的服务,以获得公共云范例提供的全部敏捷性、弹性和效率。
在本笔记中,我想简要介绍如何使用 Oracle 云基础设施(OCI) 构建这样一个数据湖,以及如何使用 Oracle 自治数据仓库(ADWH) 为存储在数据湖中的数据提供 SQL 访问。
我将简要描述存储数据的最佳选择,以及提取、转换和加载数据的可用服务。然后,我将介绍启用 SQL 访问所需的步骤。
我还将提供并描述一些实用程序,它们有助于简化任务。
文件作为对象。
在数据湖环境中,您应该能够高效地为您的数据科学家、BI 专家和业务用户想要探索和利用的所有数据集提供弹性存储。您不应该忘记“读取模式”的要求:当您存储数据时,您不希望被迫指定一个模式。
对象存储是存储所有数据集的最佳位置。您可以将它们组织在不同的存储桶中,例如创建一个“原始数据区”和一个“分析就绪”区,前者存储源系统提供的数据集,后者存储所有经过验证、过滤和聚合的数据集,以备分析和数据科学家的笔记本使用。
对象存储可以根据您的需要扩展,无需任何规划,并且足够便宜(大约 25.5 美元/TB/月)来存储数 Pb 的数据。此外,您可以使用许多 OCI 功能,例如,管理文件的生命周期(您可以定义规则来归档超过一定时间的文件),甚至添加元数据,以便更容易地找到您工作所需的数据。
快速浏览加工过程。
在我看来,数据湖中的处理必须使用无服务器云服务来完成,首选引擎应该基于 Apache Spark 。
Apache Spark 是并行、分布式、大规模处理的绝佳环境。这是一个完善且持久的开源项目,由许多公司支持。您可以在几种语言(Scala、Python、Java、SQL)之间进行选择,并且您可以找到支持数据帧、流和分布式机器学习(MLlib)的库。
图 1:阿帕奇火花模块(来源:https://spark.apache.org).)。
而且, Spark 比 Hadoop 和 MapReduce 快得多。
图 2: Spark 表演(来源: https://spark.apache.org)。.)
在 OCI 我们有两项服务提供基于 Spark 无服务器引擎的完整集成处理环境: OCI 数据集成和 OCI 数据流。
有了这些服务,您可以开发快速且可伸缩的 ETL。而且,由于无服务器的特性,您只能在启动作业时指定使用的资源(CPU)。此外,您只需为执行时间付费。
第一种允许使用“无代码”方法开发数据流,使用图形用户界面。使用第二种语言,您可以基于 Apache Spark 库,以自己喜欢的语言编写代码,并拥有充分的能力和灵活性。这两者结合起来提供了你所需要的一切。
这幅图展示了一个集成了所有这些服务的架构:
图 3:数据湖架构(图片作者)。
Oracle Data Flow 和 OCI 数据集成等无服务器服务与对象存储相结合,可以为您提供处理和准备数据集所需的全部计算能力和存储能力。即使它们比您在大数据之旅开始时计划的要大。
好吧,Spark 很酷,但是我们想用 SQL。
但是,当数据准备就绪并且结构良好时,您的 BI 专家、业务用户和数据科学家可能希望能够使用众所周知的 SQL 语言查询这些数据。例如,使用 Oracle 分析云(OAC)构建丰富而强大的数据可视化。
Oracle Autonomous Data Warehouse(ADWH)与对象存储完美集成,为您提供了两种选择:在 ADWH 存储中加载数据,或者使用"外部表"并使用 ADWH SQL 查询引擎查询数据,而数据集则保留在对象存储中的存储桶中。
如果您将数据集放在对象存储上,您可以将对象存储的易用性和高效性与 ADWH 提供的 Oracle SQL 引擎的功能、健壮性和安全性结合起来。或许以后,您可以决定在 ADWH 存储中只加载那些您需要更好性能的数据。
说到这里,我想在本文的剩余部分为您提供一些建议,使访问存储在对象存储器上的文件变得容易。我还会提供一些我为自己的工作和客户开发的实用程序的链接。
首先是安全。
要从 ADWH 访问对象存储,您需要一组凭证:一个身份验证令牌。这个令牌必须存储在 DB 中,以使 SQL 代码能够访问对象存储桶。
首先,要创建令牌,请转到 OCI UI 控制台,在您的配置文件中创建(右上方的图标和用户设置)和 AuthToken:
图 4:安全访问对象存储的授权令牌(作者的图片)。
然后,从 UI 复制身份验证令牌。请记住在创建后立即这样做,否则,您将无法重新阅读它。
第二,将云凭证存储在 DB 中,在 SQLDeveloper 中执行这段代码;该步骤只需执行一次:
BEGIN DBMS_CLOUD.CREATE_CREDENTIAL(
credential_name => 'ADWH2',
username => 'oracleidentitycloudservice/myname',
password => '<AUTH Token>' );
END;
注意:如果您的用户是联邦用户,那么这个名称就是完全限定的名称。它有一个前缀,如:
oracleidentitycloudservice/
创建外部表的 DDL。
下一步是创建“外部表”。它是存储在 DB 数据字典中的一个“定义”,允许 SQL 访问存储在对象存储桶中的文件。
在下文中,我将假设数据文件是一个 CSV 文件,并且它在第一行中包含一个带有字段名称的标题。
在我的测试中,我使用了来自 MovieLens 数据集的文件。因此,其中一个文件(movies.csv)包含这种类型的记录:
movieId,title,genres 1,Toy Story (1995),Adventure|Animation|Children|Comedy|Fantasy 2,Jumanji (1995),Adventure|Children|Fantasy 3,Grumpier Old Men (1995),Comedy|Romance 4,Waiting to Exhale (1995),Comedy|Drama|Romance 5,Father of the Bride Part II (1995),Comedy 6,Heat (1995),Action|Crime|Thriller 7,Sabrina (1995),Comedy|Romance
使用提供的 Python 实用程序(参见上一节中的链接),我已经能够生成下面的 SQL DDL 指令(再次在 SQLDeveloper 中执行):
BEGIN DBMS_CLOUD.CREATE_EXTERNAL_TABLE(
table_name =>'MOVIES',
credential_name =>'ADWH2',
file_uri_list =>'https://objectstorage.eu-frankfurt-1.oraclecloud.com/n/emeaseitalyp/b/datalake_in/o/movies.csv',
format => json_object('type' value 'csv', 'skipheaders' value '1'), column_list => 'MOVIEID NUMBER, TITLE VARCHAR2(4000), GENRES VARCHAR2(4000)'
);
END;
/
一些解释:
- credential_name 是身份验证令牌的名称(ADWH2,见上文):
- column_list 包含一组所有列的名称/类型。数据类型是 Oracle 类型
- 格式这里指定第一行包含列名(表头)
- 文件 uri 列表包含访问对象存储器中文件的 URL。
这是 URL 的格式:
https:///n//b//o/
查询数据。
创建外部表后,我可以使用 SQL 语言的全部功能来提取我需要的所有信息。
例如,再次从 MovieLens 数据集,假设我想知道什么是最高评级的战争片。
使用 SqlDeveloper,大约 20 秒钟,我就能得到结果:
图 SQL 查询的结果(作者的图片)。
链接到 Python 实用程序代码。
编写 DDL 代码来创建外部表有点无聊,而且容易出错。
为了帮助完成这项任务,我准备了一个 Python 实用程序,它可以读取 CSV 文件(只有前 N 行),理解数据类型,并在标准输出中打印 DDL,准备好进行复制和执行。
你可以在我的 GitHub 仓库中找到这个工具的最新版本:https://github.com/luigisaetta/adw_external_tables。
希望您会发现它很有用,祝数据科学愉快。
原载于 2020 年 10 月 27 日https://luigisaetta . it。
机器学习中的数据泄漏
如何检测和避免数据泄露
当训练过程中使用的数据包含有关模型试图预测的信息时,就会发生数据泄漏。这听起来像是“欺骗”,但我们并没有意识到这一点,所以称之为“泄漏”更好。数据泄漏是数据挖掘和机器学习中一个严重而普遍的问题,需要很好地处理以获得一个健壮和通用的预测模型。
数据泄露有不同的原因。有些非常明显,但有些乍一看就很难发现。在这篇文章中,我将解释数据泄漏的原因,它是如何误导的,以及检测和避免数据泄漏的方法。
你可能知道它们,但我只想提一下我在这篇文章中经常用到的两个术语:
- 目标变量:模型试图预测的内容
- 特征:模型用来预测目标变量的数据
数据泄露的例子
明显案例
数据泄露最明显的原因是将目标变量作为一个特征包括进来,这完全破坏了“预测”的目的。这很可能是错误的,但是要确保目标变量与特征是不同的。
数据泄漏的另一个常见原因是在训练数据中包含测试数据。用新的、以前看不见的数据来测试模型是非常重要的。在训练过程中包括测试数据会破坏这个目的。
这两种情况不太可能发生,因为它们很容易被发现。更危险的原因是那些能够偷偷摸摸的原因。
赠品功能
赠品特征是暴露关于目标变量的信息的特征,并且在模型被部署之后将不可用。
- 示例:假设我们正在构建一个模型来预测某种医疗状况。指示患者是否进行了与该医疗状况相关的手术的特征会导致数据泄露,并且不应作为特征包含在训练数据中。手术指征高度预示了医疗状况,可能并不是在所有情况下都适用。如果我们已经知道一个病人做了与医疗条件相关的手术,我们甚至不需要一个预测模型来开始。
- 例如:考虑一个预测用户是否会停留在网站上的模型。包含暴露未来访问信息的功能将导致数据泄漏。我们应该只使用关于当前会话的特性,因为在部署模型之后,关于未来会话的信息通常是不可用的。
预处理过程中的泄漏
有许多预处理步骤来探索或清理数据。
- 查找用于规格化或重新缩放的参数
- 要素的最小/最大值
- 估计缺失值的特征变量的分布
- 移除异常值
这些步骤应该只使用训练集来完成。如果我们使用整个数据集来执行这些操作,可能会发生数据泄漏。对整个数据集应用预处理技术将使模型不仅学习训练集,而且学习测试集。我们都知道测试集应该是新的,以前从未见过的数据。
在处理时间序列数据时,我们应该更加注意数据泄漏。例如,如果我们在计算当前特征或预测时以某种方式使用来自未来的数据,很有可能以泄漏的模型结束。
如何检测和避免数据泄露
作为一个将军,如果模型好得不真实,我们就应该怀疑。该模型可能以某种方式记忆特征-目标关系,而不是学习和概括。
在探索性数据分析过程中,我们可能会发现与目标变量高度相关的特征。当然,有些特性比其他特性更相关,但是惊人的高相关性需要仔细检查和处理。我们应该密切注意那些特征。
模型训练好之后,如果有权重非常高的特征,就要密切关注。它们可能是泄漏的特征。
为了最小化或避免泄漏,如果可能的话,除了训练集和测试集之外,我们应该尽量留出一个验证集。验证集可以用作最后一步,模拟真实场景。
当处理时间序列数据时,时间上的截止值可能非常有用,因为它会阻止我们获得预测时间之后的任何信息。
在训练过程中经常使用交叉验证,尤其是在数据有限的情况下。交叉验证将数据分成 k 个折叠,并在整个数据集上迭代 k 次,每次使用 k-1 个折叠训练和 1 个折叠进行测试。交叉验证的优点是它允许使用整个数据集进行训练和测试。但是,如果您怀疑数据泄漏,最好对数据进行缩放/标准化,并分别计算每个折叠的参数。
结论
数据泄露是预测分析中的一个普遍问题。我们用已知数据训练模型,并期望模型对以前看不到的数据进行预测。一个模型要在这些预测中有良好的表现,它必须有良好的泛化能力。数据泄漏会阻止模型很好地泛化,从而导致对模型性能的错误假设。为了获得稳健的广义预测模型,我们应该密切注意检测和避免数据泄漏。
感谢您的阅读。如果您有任何反馈,请告诉我。
超参数调整的数据泄漏
超参数调优有时会打乱您的模型,并导致对看不见的数据产生不可预测的结果。
作者图片
介绍
D 数据泄漏是指模型在其训练阶段不知何故知道了测试数据中的模式。换句话说,你用来训练最大似然算法的数据恰好包含了你试图预测的信息。
数据泄漏阻碍了模型的推广。数据科学家很难识别数据泄露。数据泄露的一些原因是
- 分割前使用中心值处理异常值和缺失值
- 在划分为培训和测试之前,对数据进行缩放
- 使用训练和测试数据训练您的模型。
超参数调整是寻找提供最佳性能的 ML 算法的最佳超参数集的过程。
关于超参数和调优技术的更多信息,请参考我以前的文章。
每个数据科学家都应该知道的流行超参数调整技术
medium.com](https://medium.com/swlh/4-hyper-parameter-tuning-techniques-924cb188d199)
大多数超参数调整技术使用交叉验证来选择最佳超参数集。交叉验证将数据分成训练测试集,在训练集上用不同的超参数集建立不同的模型,并在测试集上验证性能。最终,它会选择最佳的参数组合来获得最高的性能。
但是,当我们使用网格搜索、随机搜索等交叉验证的调整技术执行缩放、输入等预处理步骤时,会导致数据泄漏。
让我们用代码更详细地理解这一点。
在上面的代码中,我首先对训练数据执行缩放(StandardScaler ) ,然后使用支持向量分类器作为估计器和 cv = 3 即 3 重交叉验证来训练我的 GridSearchCV。使用三重交叉验证,训练数据将分成 3 组,在每组中,它进一步分成 2 组作为训练集,1 组作为测试集。对于具有唯一参数集的每个模型,将在训练集上进行训练,并在测试集上进行评估,稍后将评估分数并丢弃模型。这一过程对所有 3 组继续进行。
作者图片
这里的模型在训练时受到了测试集中的数据的影响(数据泄漏),数据是用 StandardScaler 操作泄漏的。标准标度/ z 分数通过平均值和标准差计算得出。
作者图片
在网格搜索之前,对列车数据进行了缩放(平均值和标准缩放器的标准差根据列车数据进行计算,然后通过交叉验证将列车数据分成列车&测试组。用于训练/拟合算法的训练组已经有了关于测试组的信息(即训练数据的平均值和标准差,它是训练&测试组的组合)。这就是超参数调优发生数据泄漏的原因。
解决办法
这种情况下数据泄露的解决方案是管道。
一个管道被用来帮助自动化机器学习工作流,如缩放、降维、模型拟合和验证等。它基本上在机器学习过程中采取多个步骤,并将其组合成单个对象,这使得开发和使用以及保存和以后重用都变得更容易。
我们先来了解一下 pipeline 是如何用代码解决数据泄露的。
在上面的代码中,我将 StandardScaler 和 SVC 与 pipeline 一起使用,然后将 pipeline 对象传递给 cv = 3 的网格搜索。
作者图片
在这种情况下,数据首先被分成 3 组(cv=3),即 2 个训练组和 1 个测试组。在每个组上,将执行缩放。所以,这里没有数据泄露。
这样,我们可以成功地避免数据泄漏。
结论
使用交叉验证技术进行超参数调整时,应注意数据泄漏。在这种情况下,使用管道将有助于避免数据泄漏。
感谢您的阅读!
非常感谢您的任何反馈和意见!
你可能喜欢我的其他文章,
超参数调优有时会打乱您的模型,并导致对看不见的数据产生不可预测的结果。
towardsdatascience.com](/data-leakage-with-hyper-parameter-tuning-c57ba2006046) [## Python 中的“是”和“==”
加快字符串比较的速度
medium.com](https://medium.com/swlh/is-and-in-python-f084f36cbc0e) [## 4 种超参数调整技术
每个数据科学家都应该知道的流行超参数调整技术
medium.com](https://medium.com/swlh/4-hyper-parameter-tuning-techniques-924cb188d199)
通过新冠肺炎进行数据扫盲
有些人在没有意识到的情况下快速学习数据科学
照片:兰迪·欧
这些天,当尽我所能不碰我的脸的时候,我在看着这个世界上的人上基础数据分析的速成班。由于教授数据素养是我工作的一大部分,我更加关注人们在日常生活中学习数据。是的,我应对充满越来越多不确定性和风险的时事的方法是说“看!这是学习的时刻!”
我希望我知道这是谁造成的,但我记得在这些情况下听到了一些被证明是真实的事情:普通人并不愚蠢,他们只是非常没有动力去学习那些似乎与他们无关的事情。但是在危机时刻,比如癌症诊断[或者即将来临的疫情],人们可以很快成为专家。
我记得当我有一个个人医疗问题,需要一个低风险的常规手术。确诊后不到 24 小时,我就一头扎进了描述预后、治疗方法及其风险评估等的医学论文中。有了正确的动机,在堆积如山的信息中跋涉是很容易的。
现在,新冠肺炎为世界许多地方提供了学习流行病学和病毒学的巨大动力。虽然他们可能没有意识到这一点,但这些人正在学习许多优秀科学的基础知识:理解数据是如何收集的,并接受我们寻求的知识只能通过近似和代理来获得。
我发现非常有趣的是,很多很可能没有接受过数据处理培训的人是如何学习这些东西的。这给了我很大的希望,努力提高人们的数据素养是对时间的有效利用,因为很容易证明,在适当的条件下,许多人可以“获得它”。
这一切都要感谢伟大的科学传播者
现在互联网上有很多恐慌和错误的信息。所以我今天指出的很多东西实际上是医学领域各种专家的工作,他们尽最大努力用好的信息抵消坏的信息。
我愚蠢地没有跟踪所有的推文和人,所以我借用了一个消息灵通的朋友的声誉良好的科学人士的名单来关注这个问题:@ Helen branswell@ Angie _ Rasmussen@ aetoiology@ marynmck@ cmy eaton@ mlipsitch@ statnews。
所说的朋友可能想在我的简讯中保持匿名,但他们知道他们是谁!
给我们分母!
一个例子是计算经常被引用的“死亡率”,粗略估计约为 1-3%,这使得这种疾病类似于 1918 年的西班牙流感。这个数字本质上取决于分母,每个人都承认,由于症状可能非常轻微,新冠肺炎感染的总人数被低估了。
也就是说,从我对这个话题的理解来看,网上人们随便称之为死亡率的说法更接近于病死率,即死亡人数/确诊人数。死亡率(典型的“每 1000 人中有 1 人死于 X 原因”)是一个太滞后的统计数据。我们要到几个月后才能知道新冠肺炎是否在全因死亡率方面有所进展。
有趣的一面注意到 一些参考文献 表明,1918 年的大战促使审查人员早在 1916 年就压制了流感杀死士兵的新闻,而西班牙只是碰巧没有参战,因此没有像其他国家一样压制人们如何死于流感的新闻。流感病毒株的真正起源显然仍在争论中。
正如你所看到的,很多人突然对分母感兴趣,因为现在这个暗示你未来死亡率的可怕数字是高估还是低估非常重要。
许多数据科学工作都是关于使用分母,并在得出结论之前理解比率的分母意味着什么。人们正直接看到这一过程有多混乱,因为他们想知道“真实数字”,但由于测量/定义问题,他们完全无法获得它,这让他们感到沮丧。在他们看来,真实的死亡率存在于柏拉图的空间中,但由于测量的原因,它是不可接近的。
查看发行版
我们很多人都知道,平均值隐藏了很多东西。这一点即使对外行人来说也是显而易见的,尤其是当人们很容易假设人口中的某些部分会对自变量做出不同的反应时。我们在关于弱势人群和不同病死率的讨论中看到了这一点,特别是在老年人和已有健康问题的人群中。
你也可以看到人们开始把他们对统计数据中定义的理解用于解释官方公布的统计数据。
就像上面那条关于 20 岁以下的病例低并不意味着该年龄组的实际感染率低,而是可能存在与被测试者的阈值之间的相互作用。然后你可以得出一个初步的结论,相对于老年人,年轻人受疾病的影响较小。
坚持教授数据素养!
数据科学是沟通,我知道随着组织内人员的流动,不断教授各种形式的数据知识有时是一种负担。人们很容易感觉到,似乎有永无止境的人在不顾一切地进行劣质数据分析,以符合选定的议程。但是振作起来,大多数人可以很快学会这些东西。
本文原载兰迪的 计数玩意儿通迅 。每周在你的收件箱里免费收到这样的帖子。
使用 C++进行机器学习数据操作
关于如何使用 C++实现机器学习基础的工作代码教程
克里斯·利维拉尼在 Unsplash 上的照片
数据操作是改变数据使其更容易阅读或更容易处理的过程。在开始模型构建之前,数据操作通常用于机器学习,作为数据预处理的一部分,也在模型构建期间将数据转换成更适合处理的形式。
在下面的文章中,我们将简要介绍 C++中各种数据操作 API 的实现。
- 按类拆分数据。
- 二维向量转置。
- 二维向量随机化。
- 数据分为训练数据和测试数据。
这篇文章是解决机器学习算法在 C++中实现的系列文章的一部分,在整个系列中,我们将使用 C++特性实现基本的机器学习算法。
- 什么时候应该学习使用 C++的机器学习?
- c++中的数据预处理和可视化。
- 使用 C++进行机器学习数据操作。
- 使用 C++ 从零开始的朴素贝叶斯。
- 线性回归在 C++中的实现。
- 每个 C++开发人员必读的 8 本书。
- 每个机器学习开发者必读的 9 本书。
这里我们将使用可用的虹膜数据集。
按类别划分数据:
正如我们在上一篇文章中讨论的,我们将使用 Iris 数据集作为我们的数据的例子。我们从读取文件中的虹膜数据开始。
从 iris.data 文件加载数据集
如果您不熟悉这行代码,请阅读本文。
关于如何使用 C++实现机器学习的基本功能的工作代码示例
towardsdatascience.com](/data-preprocessing-and-visualization-in-c-6d97ed236f3b)
我们现在需要实现一个函数,我们可以给它一个向量和一个标签,它会过滤出值,并返回一个包含这个标签的元素的向量。
这个函数的实现并不复杂:
- 首先,我们需要遍历二维向量中的每个元素,并将每个标签与需要的标签进行比较。
- 其次,我们将这些向量推入新的输出向量并返回。
按类拆分数据集
前面代码的注释:
- 我们使用了一个 lambda 表达式来完成函数中的所有重要工作,你会注意到,比较和存储是在 lambda 表达式中进行的。
- 当试图存储数据时,我们使用一个向量,并将该向量推回到输出向量中。这改变了数据形状,因为当我从文件中加载数据集时,我使用的格式是将每个特征加载到一个单独的矢量中,然后通过将这些矢量放入一个二维矢量中来创建数据集矢量。
输入向量中的数据格式
转置功能之前的数据格式
- 扩展之前的注释,这需要我们在收集数据后转置向量。
现在,我们可以使用这个 API 来检查数据大小:
按类拆分数据的函数的用法
先前数据拆分代码的输出
二维向量转置:
在上一节中,我们使用了一个二维向量转置,但是这个函数不是一个标准函数。如前所述,在我们的实现过程中,数据格式需要多次更改,因此我为此创建了一个单独的函数。
转置功能实现
如你所见,向量转置是一个简单的操作。您只需从索引为[i][j]的向量中读取数据,并将其存储在索引为[j][i]的向量中。
检查移调前后的数据大小
移调示例的输出
虽然这个操作很简单,但它将大大简化我们的实现,原因是,有时我们需要将数据作为一个整体来处理,而在某些情况下,我们需要将数据作为整个特性的值的样本来处理。
数据随机化:
在分割任何数据之前,通常最好先随机化数据。我们不希望所有的训练数据都来自同一类型。
例如,如果您研究 Iris 数据集,您会发现来自相同类型的数据被分组在一起,这可能会导致您在 Iris-Sentosa 数据上训练您的模型,然后在 Versicolor 数据上测试它。
Iris 数据集包含分组在一起的相同类型的数据
为了解决这个问题,我们需要在拆分之前添加一个随机化步骤。
使用 random_shuffle 的向量随机化
请注意,根据 random_shuffle 文档,这个函数是一个模板,这就是为什么我在使用它之前转置了二维向量,以每次处理一个样本,这将确保样本数据不会混合在一起。
随机化代码的输出
训练数据和测试数据分割:
机器学习中最重要的步骤之一就是数据拆分。
这旨在为任何需要了解各种数据集分割之间的差异的人提供一个简短的入门指南,同时…
towardsdatascience.com](/train-validation-and-test-sets-72cb40cba9e7)
这是一个如何在 C++中实现数据拆分的例子。
训练和测试数据拆分的实现
测试和训练数据拆分的调用
拆分后的数据大小
如果你对这些函数的数据输出感兴趣,可以查看这个链接
把所有这些代码一起修改,我们会发现,矢量转置是这些功能中的重要一步。所以我们必须注意这一步的优化。
毕竟,数据操作就是如何在 C++中处理向量,并把你需要做的事情分成小步骤。
想回忆一下吗?
这篇文章是解决机器学习算法在 C++中的实现的系列文章的一部分,在整个系列中,我们将使用可用的 Iris 数据集这里。
- 什么时候应该学习使用 C++的机器学习?
- 每个 C++开发人员必读的 8 本书。
- c++中的数据预处理和可视化。
- 使用 C++进行机器学习数据操作。
- 使用 C++ 从零开始的朴素贝叶斯。
- 线性回归在 C++中的实现。
希望这篇文章对您有用,请关注本系列新文章发布时的通知。
您可能也会觉得这些文章很有趣:
C 语言中改变你想法的 5 个技巧…
medium.com](https://medium.com/ml2b/so-you-think-you-have-mastered-c-programming-caecc56a587f) [## 压缩变换简介
长时记忆模型和近期工作综述
medium.com](https://medium.com/ml2b/introduction-to-compressive-transform-53acb767361e)
数据地图:数据集也可以被提炼
TL;DR:这篇帖子是关于论文 数据集制图:用训练动力学 绘制和诊断数据集,以及在 TensorFlow 2 中的实现。
链接:
论文: 数据集制图:用训练动态对数据集进行制图和诊断 笔记本:https://github.com/eliorc/Medium/blob/master/datamaps.ipynb
一周前,我在工作场所的一个空闲频道上看到了一篇有趣的论文。不要误会我的意思,我略读了很多论文,但有些确实引起了我的注意,让我继续尝试。
我在这里写的论文是数据集制图:用训练动力学绘制和诊断数据集。我发现这篇论文的有趣之处在于,它挑战了训练数据时“越多越好”的常见方法,并将重点从数据的数量转移到数据的质量。在这篇文章中,我将回顾这篇文章,并以一个 TensorFlow 实现结束。
行动纲要
本文创新性地提出了为训练数据集中的每个样本计算训练动态(称为置信度、可变性和正确性)的方法。使用这些,我们可以诊断我们的数据集,目的是将数据集提取到一个更小的子集,具有很少或没有内分布* 性能损失和更好的外分布* 性能,这意味着更好的泛化能力。
该方法不知道数据的类型,但是特定于通过基于随机梯度的方法(基本上任何分类神经网络)优化的分类器。
这篇文章继续探索作为不确定性度量的训练动态,并使用训练动态来检测错误标记的样本。这两个板块我在这篇文章里就不说了。
*内分布— 训练/测试数据取自同一分布
- 外分布 —训练和测试来自不同的分布
使用训练动态创建数据地图
本文给出了三个度量标准,即置信度、可变性和正确性,它们都是为训练集中的每个样本计算的。这些指标是在以下列方式训练模型时收集的。
在每个时期之后,在没有梯度更新的情况下,对训练集进行全面检查,并且保存每个样本的真实标签的概率。
然后,一旦训练结束,对于每个样本,我们将有一个大小为 E(时代数)的向量。
置信度被定义为跨时期的平均真实标签概率:
可变性被定义为跨时期的真实标签概率的标准偏差:
正确性是最直观的指标,定义为样本在不同时期被正确标记的次数。这个度量可以被认为是样本在不同时期的准确性。
一旦我们为每个样本收集了这些指标,我们就可以绘制一个“数据图”。
绘制数据图,作者将样本分为三组,易学的样本是变异性低、置信度高的样本。难学习的样本是可变性低、置信度低的样本,最后,不明确的是可变性高的样本。
SNLI 训练集的数据图,基于 RoBERTA-large 分类器。摘自原论文
使用提取数据集的实验
一旦数据图准备好了,作者就以下面的方式设置实验。选择模型并为其定型集创建数据映射。然后创建 7 个不同的数据集:
- 100%训练:所有数据集
- 随机 : 33%随机选择的样本
- 高信心:高信心样本的 33%
- 低可变性 : 33%的低可变性样品
- 高正确率:高正确率样本的 33%
- 低正确性:低正确性样本的 33%
- 不明确 : 33%的高可变性样品
一旦不同的分割准备就绪,它们就在不同的训练集上训练相同的模型,同时在相同的集上进行评估。以下是 RoBERTA-large 在 WinoGrande 数据集(训练和验证)上作为分布内(ID)数据集和 WSC 数据集作为分布外(OOD)数据集的结果。它们还与其他相关作品进行了比较:
论文中的结果
性能提升不是很大,但考虑到这表明你可以使用 33%的数据实现相同的 ID 性能,甚至更好的 OOD 性能——这在处理非常大的数据集时可能非常显著(有人说 GPT-3?)并提供了一种将数据集缩小的方法。此外,这些实验揭示了歧义样本的属性,其本身导致更好的泛化和相同的 ID 性能,而训练成本为 33%。
以下是更多的结果:
论文中的结果
不同样品组的作用
作者继续进行另一组实验,测试多少模糊才算足够。由于在上一节中我们看到,在保持 ID 性能的同时,模糊样本是对 OOD 性能贡献最大的样本,因此自然的问题是,对于来自训练集的模糊样本的分数,我们可以达到多低。
作者尝试了从 50%到 1%的不同歧义百分比,并观察了在 ID 和 OOD 集上的性能。他们得出的模棱两可的样本太少,而且模型不收敛。
为了应对这种情况,他们尝试用易于学习的样本交换一些不明确的样本,并观察到这些交换(用大多数不明确的样本和一些易于学习的样本构建训练集)产生了收敛性和性能。他们接着得出结论,尽管模糊样本的作用对于泛化很重要,但包含一些易于学习的样本对于收敛也很重要。
结果:
论文中的图 3:左边和中间是 ID 和 OOD 性能,与随机相比,模糊样本的百分比不断增加。右边是 17%的歧义样本,以及不同比例的简单易学的替换样本。所有结果是 3 个随机种子的平均值。
我的看法
从我的角度来看,我首先要说的是,发现一个我以前从未接触过的新的信息来源——训练动力学——非常有趣。实际上,模糊样本的概念和创建具有更好概括能力的模型基本上是实用 ML 的全部内容,所以尽管不像一篇关于新奇的异国建筑的文章那样“性感”,我认为这项工作和基于它的工作非常重要。数据集越来越大的趋势只会继续,因为我们总是在收集数据。随着时间的推移,构建高质量数据集的能力将变得更加重要。最后,拥有另一个工具来构建更好地概括的模型是非常相关和重要的,并且使它更有趣的是,这个工具是关于数据的,而不仅仅是模型。
在 TensorFlow 2 中创建数据地图
由于我发现这篇文章很有趣,我不得不亲自尝试一下。正如我的一些读者可能已经知道的那样,无论我为 TensorFlow 构建什么样的模块,并且我认为它在不同的数据科学应用程序中都是有用的,我都保存在我的经过测试和记录的 PyPI 包中— [tavolo](https://github.com/eliorc/tavolo)
。
为了试验数据映射,在tavolo
中,我创建了一个回调函数来计算创建数据映射所需的所有指标。你可以在我的 Github 里看到完整的笔记本,用法相当简单。
在我的实验中,我采用了一个 DistillBERT 模型,并将其应用于 QNLI 数据集。
回调和训练力度计算的用法相当简单:
import tensorflow as tf
import tavolo as tvl # Load data
train_data = ... # Instance of tf.data.Dataset
train_data_unshuffled = ... # Another instance of the train_data
# without shufflingmodel = ... # Instance of tf.keras.Model# Creating the callback
datamap = tvl.learning.DataMapCallback(train_data_unshuffled)# Training
model.compile(...)
model.fit(train_data, callbacks=[datamap], ...)# Access training dynamics
confidence = datamap.confidence # This is a numpy array
variability = datamap.variability # This is a numpy array
correctness = datamap.correctness # This is a numpy array# Plot datamap
...
使用 DistillBERT 模型在 QNLI 数据集上运行这段代码,得到了下面的数据图(取自笔记本
就是这样:)我希望你喜欢阅读,并学到了一些新的✌️
数据网格(不是服务网格)
当今业务的发展速度要求数据架构不断发展——从仓库到数据湖再到数据网格。
数据科学
Olena Domanska 的宝贵意见。
长话短说
如何正确管理业务数据?这是保险、银行、制药、工业、建筑等所有行业都必须回答的问题。
组织中数据管理的有效性对组织绩效和更好的战术和战略规划有着直接的影响。
本文描述了业务组织中数据的基本方法的演变以及最新的趋势—数据网格。
数据仓库时代
数据仓库已经有 40 多年的历史了。从今天的角度来看,这个想法很明显。关系数据库针对读取和修改小块数据的数十亿个短事务进行了很好的优化,但不适合长时间运行的分析查询。
需要一个不同的存储和数据引擎,于是数据仓库系统诞生了。
传统上,数据仓库针对事实进行了优化,为预期要执行的一组查询提供了维度。一个典型的经典例子是给定时间段内每个分支机构的月度销售报告。
数据仓库最常见的数据摄取场景是提取-转换-加载(ETL): E 从源数据库提取数据, T 转换数据(清理、初始过滤和聚合),然后 L 将数据加载到仓库存储中。很经典,不是吗?
提取-转换-加载(ETL)方案
作者对威尼斯湾的想象
数据湖的故事
数据仓库是为特定的目的而创建的,它们很好地服务了这个目的。当业务需求发生重大变化时,问题就出现了,即使在早期阶段,转换也开始带来伤害而不是帮助,因为它们是针对不同的、现在已经过时的业务场景进行优化的。
如果领域是众所周知的,并且分析需求是众所周知的和稳定的,那么这是一个有效的方法。但是商业的速度、更多的非关系数据来源以及动态变化的分析需求都被现代机器学习技术加速了。
此外,数据仓库开始成为一个问题,因为它们的模式很强,一旦装满了万亿字节的数据,就很难改变。
另一个问题是,不同的业务用户组,根据他们特定的报告和分析需求,使用不同的供应商和分析系统创建了他们自己的带有 ETL 机制的仓库。原始数据和转换后的数据都存储在不同的系统中,因此在不同的部门级别上产生了数据孤岛。
IT 部门对此感到很不舒服。需要将组织的所有数据放在一个中心位置,由一个中心团队管理,并采用未经修改的原始格式,以便以后进行任何转换,这导致了数据湖的流行。
数据湖方案
好人
您可以 E xtract, L oad,然后 T 转换(ELT)数据,以实现您当前和未来的分析目标。数据湖在一个集中的位置提供来自所有业务领域和组织所有部分的数据。分析师可以用以前似乎不可能或太难的方式加入数据并从中提取信息。数据是原始格式,因此在此过程中不会丢失任何东西,也不会破坏任何信息。
消费者可以决定他们现在和将来如何从湖中存储的数据中受益。IT 部门可以添加新的数据源并填补数据湖。
不同的视图和访问机制由中央团队管理,因此,尽管数据位于一个位置,也能防止未经授权的访问。
此外,数据流技术支持实时报告和持续接收数据湖。数据湖的适当设计使基于云的工具能够从数据中推断出模式,并在其上运行复杂的查询,我们可以将这些工具视为半自动数据仓库,但是是现代的、灵活的版本。
坏事
好了,我们把所有的数据都放在了一个地方,但是这些数据意味着什么呢?将数据存储在一个位置并不会使它更容易理解。例如,数据呈指数级增长。在没有正确理解数据的哪些部分重要,哪些部分不重要的情况下,我们如何处理这种数据洪流?
一切都是“以防万一”存储的——但“万一”是什么呢?
原始格式也没有帮助,因为如果数据消费者想要做任何事情,向更文明的格式的转换必须由数据消费者自己来执行。
它不再是一个干净、结构化和定义良好的数据仓库。数据工程师通常与业务团队隔离,与业务领域和数据知识隔离。此外,所有部门都依赖于一个数据工程师团队。
数据网格——微服务革命的教训
对新方法的需求导致了数据网格模式。
事务性系统发展成了微服务,但在数据领域,集中化占据了主导地位。打破企业应用程序的铁板一块已经成为一个新的口号,但是数据呢?数据湖可以被看作是一个数据块。打破它怎么办?如何将领域驱动架构原则也应用于数据呢?
数据流和数据集归用户所有;它是原始数据,而不是来自源数据库的运营数据。它可以被转换以创建业务领域的联合聚合视图。附属于商业专家的独立团队现在可以更深入地理解数据的含义,以便创造更好的见解和预测。
这是否意味着逆转潮流,把老问题带回来?不——如果处理得当的话。
数据作为一种产品
数据作为一种产品,意味着一个产品团队,一个产品路线图,适当的管理和开发管道。从用户的角度来看,这意味着更好的数据可发现性、自助服务(即文档、示例、模式)和自治。
必须创建一个数据平台,作为一组模式、约定、工具和基础设施(即存储、事件、监控),以使数据用户能够专注于他们的目标,并帮助避免过去不可维护的数据孤岛。数据体验对于数据科学家和业务用户来说起着至关重要的作用。
从 IT 角度来看,团队不需要决定存储机制。分布式数据所有权模型并不意味着在物理上分离数据。
这是数据民主化的真正开始,而不会失去 It 治理。
数据平台结构
已知挑战
在这种方法中,数据是分离的,而不是集中的。创建数据孤岛并(再次)失去组合来自不同领域的数据的能力有多容易?解决方案是数据平台组件和通信机制的适当标准化。
技术挑战也在这里。在微服务领域,Kubernetes 占据了主导地位,并成为事实上的标准,但在数据领域,它更加分散,不够成熟。在数据网格中出现类似的情况需要几年时间,就像我们现在在企业应用程序世界中一样。
最后的话
数据仓库、数据湖和数据网格
数据网格、数据湖和数据仓库将继续共存。
例如,最新的云数据服务系列支持使用现有的数据湖,并在其上构建现代化的半自动数据仓库,从数据中推断模式,并支持复杂的查询功能。
如果您当前的数据湖或数据仓库解决方案正在实现您的目标,那么很难证明投资迁移到数据网格体系结构来满足您的数据需求是合理的。一些首席信息官或首席债务官甚至声称他们已经拥有数据网格架构多年,但没有使用新的名称。
我也听到了支持 IT 部门严格控制数据的声音;他们不愿意在这种范式下建立这样一个平台。
这一次,传统的“如果有效,就不要修复它”的态度是目前最好的策略。
然而,没有什么能阻止 Avenga 公司密切关注这一趋势和支持工具,并在新的领域尝试这种方法,以了解其全部价值。
数据网格痛点
意见
为什么在实施数据网格之前要三思
介绍
最近,在数据平台架构领域,引入了一个名为数据网格的新概念/范式。它假装推动一种新的架构方法来构建分析解决方案,这种方法通常被视为尖端、新奇的方法,并且已经开始被一些组织采用。
尽管事实上,Zhamak Dehghani 带来了许多伟大的思想,背后有着体面的推理(原文是这里是),但我看到了严重的担忧,阻止我推荐它应用于大多数数据分析平台。
数据网格概念摘录
数据网格架构非常广泛,涵盖了数据分析平台的不同方面,但我想集中讨论两个方面,在我看来,这两个方面非常重要,值得深入研究:
- 面向领域的数据分解 —将单一数据平台分散到一组面向领域的数据集中。域需要以一种易于使用的方式托管和服务它们的域数据集。
- 面向领域的数据所有权 —每个领域都应该有自己的跨职能数据团队,包括数据产品负责人和数据工程师。
除此之外,域数据还被拆分为:
- 面向源的域 数据代表业务的事实和现实
- 面向消费者和共享的领域数据以满足一组密切相关的用例。这些数据集经历了更多的变化,它们将源域事件转换为符合特定访问模型的聚合视图。
下图概括展示了 data domains 的分布以及可能的数据提取依赖关系:
数据域以及可能的相互依赖关系(图片由作者提供)
面向消费者领域的数据集似曾相识
当我看上面的图表时,它的右边部分(一组面向消费者的领域数据集)看起来非常类似于 1998 年发布的著名的 Inmon 的 CIF 架构中的数据集市组件:
图片来自 Claudia Imhoff 的《企业信息工厂》一书;瑞安·索萨;W. H. Inmon,威利出版,2001 年
面向领域的数据集被称为为部门需求创建的数据集或数据集市。
在 Daniel Linstedt 定义的 Data Vault 架构中也可以找到非常相似的方法,唯一的区别是数据集市被称为“信息集市”,但服务于相同的目的。
Ralph Kimball 还提到了“独立的数据集市架构”(作为其总线架构的替代方案之一),同样的部分与消费相关:
独立数据集市“架构”的简化说明(《数据仓库工具包》,第三版,作者拉尔夫·金博尔和玛吉·罗斯)
因此,我不同意Zhamak 关于尚未利用领域驱动设计范例的数据平台的说法:
尽管我们在实现操作能力时采用了面向领域的分解和所有权,但奇怪的是,当涉及到数据时,我们忽略了业务领域的概念
如您所见,20 多年前,这个概念开始以稍微不同的形式引入数据分析架构,随之而来的是赞美、批评、赞美,甚至是圣战(Inmon vs Kimball)
域数据集隔离有什么问题
让我们首先认同这样一种说法,即用于分析的最佳数据模型是建立在星型模式之上的(多维数据模型)。它是最高效和最灵活的。它的规模很大,大多数现代 MPP 发动机都为此进行了优化。它被用在所有大型架构(Inmon 的、Linstedt 的和 Kimbal 的)的数据消费层。
所以我们有事实/事件和维度之间的模型分离。描述组织中不同业务流程的事实可以很好地相互隔离,并且可以分布在不同的域中。但是维度呢?通常,我们有一堆不同领域共享的维度,比如产品、客户、组织结构、员工、银行账户、商店等。使用数据网格方法和隔离的面向消费者的数据集,我们有两个选项,都有各自的问题:
- 为每个维度创建 一个单独的域。这将带来许多不必要的复杂性,因为要从其他域访问这些数据,并增加要维护的域的数量
- 在每个域中复制所需的尺寸**。这将导致与维度处理和质量保证相关的逻辑重复。**
Zhamak 在她的文章中部分提到了这些问题,并通过以下方法给出了解决方案:“全球治理以实现多语言领域数据集之间的互操作性”。
坦率地说,我认为全球治理可以帮助防止混乱,并跟踪不同领域中同一实体的所有版本,告知它们之间的差异或相似性,但事实上,它不会防止数据集的重复问题以及与其支持相关的工作。
集成和整合优势
因此,数据仓库的“单片性质及其负面解释可以转化为具有所有正面意义和优势的集成和整合。
在我看来,集成和整合是数据平台的重要优势之一,它实际上允许以各种方式进行数据分析:描述性的、诊断性的、预测性的和规范性的。如果每个数据源都包含自给自足的数据,那么将它加载到其他地方就没有意义了。不同数据集的实际集成、整合和关联为企业带来了最大的价值。
不可分离的数据仓库神话
有一种神话认为数据仓库项目是长期运行且永无止境的。它们不能以敏捷的方式执行,因为很难将它们分割成具有商业价值的增量部分。
但事实上,并不是这样。
如果我们遵循 Ralph Kimball 提出的总线架构,那么描述业务流程的总线矩阵中的每一行都可以在端到端的一次迭代中实现,并交付业务价值。因此,使用这种方法,交付给企业的价值可以按周来衡量,而不是按月或年来衡量。
领域跨职能团队挑战
在一家大型服务提供商公司建立分析解决方案方面,我有 15 年以上的经验,我有以下更好的观察结果:将在较窄知识领域具有较深专业知识的工程师结合起来,比在较宽主题上具有较浅专业知识的工程师更好。
因此,流、ETL 批处理、DW 设计、数据可视化知识领域之间的专业知识分离非常完美。
如果我们有 5-10 个不同的领域,在每个领域保持 4 个以上的工程师和数据所有者的跨职能团队看起来是不真实的,并且对于大多数项目来说是负担不起的。
利用 DW 传统
数据仓库或数据分析解决方案已经在市场上存在了 25 年以上,因此从不同的角度来看,特别是在方法论方面,它们已经非常成熟。正在发生积极变化的是用于数据传输的下划线存储和框架的技术:它们在性能和拥有成本方面变得更快、更可靠、更高效。
值得利用这一传统,并在适当调整后将其应用于现代现实,但没有必要发明另一种自行车。
结论
我的意图不是贬低数据网格体系结构,而是强调现有数据仓库方法的不同方面,这些方面通常不为人所知,没有得到充分的研究和重视。
我希望这将导致一些富有成效的合作讨论:)
数据挖掘日记:TextBlob 和 NLKT 来分析你的个人日记
介绍
2003 年,我开始写日记:把我的想法、计划、恐惧和反省写在一个简单的文本文件里。从此,我将631597 字写进了 787 总日志,跨越 17 年。日志是更好地了解一个人的想法的无价工具:分析决策模式,识别趋势,并在这个混乱的世界中找到目标。
这些年来,我对我的日记进行了多次特别的深入研究。例如,当从受伤中恢复时,我用我的日记来识别导致恶化的触发因素,并随着时间的推移绘制这些触发因素,以更好地了解我的行为如何影响我的恢复过程。如果有一种方法可以通过编程来进行这种类型的分析,会怎么样呢?幸运的是,有——它被称为自然语言处理——并且有大量的库允许我们解析和分析大量的文本。
我们将使用 TextBlob ,一个基于 NLKT 和模式构建的流行 python NLP 库,来计算以下内容:
- 描述性统计:每年字数,每年条目,总字数。
- 使用词云和 N-gram 分析的最常用词(词的组合)
- 词性标注(名词、动词、形容词)。
- 情感极性分析——随着时间的推移,语气(积极/消极)发生了怎样的变化?
阅读下面的每一个过程的细节或简单地进入我的 Jupyter 笔记本。
数据清理和处理
《华尔街日报》位于谷歌文档中;每一年都由一个单独的 Docs 文件表示。文档文件被导出为。然后导入到我们的笔记本中。我们将遍历每个文件中的段落,解析出日期(使用各种可能的格式)并将其与后续日志条目一起存储在 pandas 数据帧中。日记账的格式如下:
2020 年 6 月 11 日
今天写了一篇中帖。我希望它能得到一些掌声。
6/15/2020
我的帖子收到了一些掌声:我太激动了!!!
现在是时候开始下一个数据项目了…
这个过程的一个挑战性方面是处理不一致的日期格式:代码需要考虑日期的每一种可能的格式,以便正确地解析日期和随后的日志条目。这个问题通过使用正则表达式模式匹配的大量试验和错误得到了解决。
产生的数据帧显示了正确解析的日志条目和相应的日期。
我们现在已经将数据合理地组织成一个数据框架。每一行都是包含多个段落的单个条目。让我们通过为以下任务创建函数来进一步清理数据:
- **基本清理。**去除空段落,统计单词/段落,标记句子,转换成小写,去除缩写,标准化日期格式。
- **词汇化。**为了简化分析,我们将每个单词转换为其引理,本质上是其基本形式(got,going = go,claps = clap)。在上下文中,词汇化不同于词干化;通常需要词类(动词、名词、形容词)来完成这个过程。为了做到这一点,我们需要首先将每个句子标记为单独的单词,将单词传递给 TextBlobs POS tagging 函数,然后通过 lemmatizer 函数运行它。我发现这篇博客文章对学习更多关于词汇化的知识很有帮助。
成功了!我太兴奋了。
作为一个有趣的附带项目,我决定快速编写一些代码来自动输出 1 年前、5 年前和 15 年前的日志条目。这个想法是基于佩恩·吉列特每天写日记和自我反省的方法。令人难以置信的是,这些年来,事情发生了怎样的变化(并保持不变)。
我在 60 个单词之后就停止了输出——之后就变得太私人了!很高兴看到我在 15 年前可怕的 127 考试中获得了 a。
高级结果
我把631597 字写进了 787 总日志,跨越 17 年。我平均每年写 44 条和350000 字每条 803 字。下面的代码块显示了我是如何计算这些汇总统计数据的,此外还生成了一个显示日志条目的频率和长度的图表。
大约在 2005/2006 年,期刊产量急剧上升,这一年对我来说恰好是转变的一年——完成大学学业,找到工作,搬到旧金山。显然,在这段时间里,我的日记中有更多的事情需要分析、计划、思考和组织。
字数的其他峰值出现在 2013 年(旅行一年,过渡到一份新工作)和 2016 年(搬到西班牙)。2020 年,采用了一种新的每日日志格式(每天早上写 5 分钟——受佩恩方法的启发),这反映在条目和总字数的大幅增加上。
接下来让我们看看季节性——旅行条目的频率是否会按月下降?也许写日记在一月份更常见——因为人们越来越关注反思和决心。
按月记录日志的频率相对稳定,在夏季(7 月/8 月)出现小高峰。可能在这段时间有更多的假期和旅行,因此有更多新的经历可以写。
独特的单词用法
让我们深入研究一下内容,首先看看一段时间以来独特的单词用法。
随着时间的推移,我们可以看到独特词汇的使用有所增加——这可能表明词汇量的增加以及可以写的经历种类的增加。
右图显示了总字数中的%独特字数,计算方法是将独特字数相加,然后除以总字数。这基本上是一个单词重复的统计——它通常保持不变,在 2003/2004 年和 2009/2010 年有显著的峰值。需要进一步的分析来挖掘这些峰值。
最流行的词
让我们来看看在我的日记中找到的热门词汇。第一步是对最常见的单词有一个大致的了解。为了简化我们的可视化,我们将使用词汇化的版本(‘got’,‘go’,‘going’都应该被认为是动词‘go’)。除了对热门词汇的标准统计,我们还将利用一个名为 WordCloud 的简洁函数来可视化热门词汇。
第一步是过滤掉停用词——对我们的分析没有价值的词,如“The”、“a”、“an”、“in”。接下来,我们遍历词汇化的单词,并创建一个频率分布,输入到 WordCloud 库中。
行动的词汇(去,得到,工作),欲望(想要,需要,感觉),以及我们每天都在思考的精髓名词(时间,日子,乐趣)。
让我们更深入地研究热门词汇,并根据词类(动词、名词、形容词、副词)对它们进行分类。
名词“单词云”给了我一个有趣的视角来看待我生活中什么是重要的:人、时间和乐趣!
内省动词:思考,想要,感觉,知道,需要,知道。
大多是正面的形容词和副词:很好,很棒,很棒,超级,很好。我觉得这反映了我普遍积极向上的天性!
N-Gram 提取
n 元语法被定义为来自给定文本或语音样本的 n 个项目的连续序列例如,在我的日记中常见的两个单词是“我曾经是”,“在这个世界中”,“将要成为”,“那个我”。让我们对该杂志做一些基本的 n 元语法分析,看看是否有任何有趣的模式出现。
我们将遍历每个标记化的句子,并将其传递给 NLKT 的 n-gram 函数,附加到一个 n-gram 列表,该列表将被转换为 DataFrame,以便于数据处理。
一些初步想法:
- 3 克。像“我需要”和“我想”这样的短语揭示了反复出现的想法、欲望和计划。深入挖掘这些二元模型会很有趣——它们后面的常用词是什么?
- **4-克。**还有很多道路需要调查。例如,我提到“很多乐趣”超过 100 次——什么是很多乐趣?与这个 4-gram 相关联的常见名词有哪些?
- **5-克。**有趣的是,“但同时”被写了 40 多次——它的出现表明了对比——也许在同一个句子中有积极和消极的想法?这是一个很好的例子,说明分析一篇文章是多么的混乱:通常,一个单独的句子或短语不容易被归类为 100%肯定或否定。
情感分析
情感分析是一种量化文本情感状态的自然语言处理技术。它利用机器学习原理,一种常见的方法是将文本分类为正面或负面。Textblob 提供了情绪的“极性得分”,其浮动范围为[-1.0,1.0] —负值表示负面情绪,正值表示正面情绪。
Textblob 的情感得分的默认方法使用一个情感极性词典,(基于模式库),它本质上是一个单词及其相应极性和主观性值的词典。Textblob 也有一个使用朴素贝叶斯分析器(一个在电影评论上训练的 NLKT 分类器)的选项。此外,它允许使用你自己的测试数据来训练一个定制的朴素贝叶斯分类器。我们将保存分类器方法供将来的项目使用——现在,让我们深入研究计算极性的默认方法。
让我们从计算每个日志条目和句子的极性开始。
让我们快速输出 5 个完美的 1.0 积极情绪极性的随机句子。
在我看来,它们都很明显是积极的。显然,“棒极了”是我最喜欢的词之一,也是正极性的高度预示。
一些被认定为高度否定的句子的随机例子:
这看起来不太准确:一些人明显是消极的,但其他人不一定传达消极的想法(例如,“疯狂!”可能指的是更积极或更令人震惊的事情。)
情感极性是如何在所有日志条目中分布的?
我们看到期刊条目的情绪极性得分呈正态分布,大多数略微偏正。情绪极性是如何随时间变化的?
平均情绪极性逐年稳步上升!这是一个很好的迹象,随着时间的推移,日志条目的积极性总体呈上升趋势。这能证明生活会随着年龄的增长而变得更好吗?
按年份划分的盒须图显示了每个条目的情绪极性按年份的可变性。我们可以看到,2003 年是一个高度动荡的年份;这是有意义的,因为这是一个过渡时期,也是写日记的开始。季节性呢?在寒冷的月份和温暖的月份,情绪极性会发生变化吗?
当按日历月查看情绪极性时,我们看到一些非常轻微的季节性:年初情绪稍微积极一些,年底情绪略有下降。这在逻辑上是有意义的:一月是一年的开始,是下定决心、新的开始和更高的动力去改变生活的时候!
常用词类的情感极性
某些单词是与更多的肯定句还是否定句联系在一起?也许像“工作”、“税收”和“车管所”这样的词通常更消极,而像“娱乐”、“野营”和“度假”这样的词更积极。我们能用这种技术发现我们的选择、行动和言语中未知的趋势吗?
为了进行这种计算,我们在句子级别计算情感极性,然后简单地用整个句子的极性分数标记该句子中的每个单词。这是一个粗略的近似值,可以大致了解单词如何影响句子的整体情绪。
让我们创建一个快捷的函数,轻松地按词类(名词、专有名词、动词、形容词)绘制不同的单词切分。
前三个最积极的名词是“人”、“生活”和“乐趣”——显而易见的非常积极的东西。
创造和体验动词,如“制造”、“感觉”和“思考”,是一些最积极的常见动词。
Textblob analyzer 为单词“awesome”赋予了额外的权重,这是我个人的最爱。另一方面,“bad”是迄今为止最常用的负面形容词。有道理。
结论
我希望这对于开始学习基本的 NLP 和基于文本的数据的数据处理技术是一个有用的练习。所有代码都可以在我的 Github repo 上找到。以下是我在这个项目中发现的一些有用的链接:
- Python 中的情感分析:TextBlob vs Vader 情感 vs Flair —这是对 Python 中一些比较流行的 NLP 包的一个很好的总结。
- 处理文本数据的终极指南
- 使用 NLTK 的初学者文本分析
- 教程:用 Python 进行文本分析来测试一个假设
未知领域的数据挖掘
从提取仿真陈述到构建高级模型
你有没有遇到过这样的情况,不管出于什么原因,你不得不处理一个来自你知之甚少或一无所知的领域的数据集?我打赌是的。没有多少数据科学家对泰坦尼克号或 Iris flowers 有专业知识,但他们完全可以处理这些数据集。
数据科学家经常抱怨他们 80%的时间被浪费了?)在数据清理方面。虽然这是事实,但花在数据清理上的时间并没有完全浪费。恰恰相反。你花在数据上的时间越多,你对数据了解得越多,你的分析直觉就越好。
这篇文章的目的是——假设你有一个开放的心态,对数据集一无所知,头脑中没有任何问题,只是好奇——你如何发现数据集会泄露什么有趣的故事和信息?
正如我在上一篇文章中所写的,数据科学有两个可能的起点——从问题开始或者从数据开始。在那篇文章中,我谈到了从一个问题开始的项目的生命周期。在理想情况下,是的,数据科学家会首先提出一个问题,然后使用所有可用的工具和技术来尝试找到该问题的答案。然而,现实中并非总是如此。偶尔会碰到一些你一无所知的数据。你不问任何问题,你只想知道他们掌握了什么信息。
数据科学项目周期(@mab.datasc)
在接下来的部分中,我将带您完成这个过程。为此,我从世界银行微数据数据库下载了一个数据集来使用(稍后会有更多的介绍)。我将使用 python jupyter 笔记本环境,使用三个主要库:pandas
、seaborn
和Scikit-Learn
。但是不管你用什么工具——R,excel,tableau,power BI,等等——重要的是你做了什么。
声明:为了公平起见,我选择了一个我以前不了解的领域,并选择了一个我在写这篇文章之前从未见过的数据集。以前我处理过其他类型的世界银行数据集,但是对非洲的援助从来都与我的工作或兴趣无关。
理解数据及其起源
当你得到一个未知的数据集时,你要做的第一件事就是问一些基本的问题来了解数据的来源/血统:这个数据是关于什么的?它从哪里来的?谁生产的,出于什么目的?什么时候收集的,怎么收集的?可能有描述数据集、一些关键变量的定义等的相关文档。您可能会在哪里找到这些信息
元数据和数据文档
我在这里使用的数据集是 1990 年至 1996 年间从非洲依赖援助的国家收集的时间序列数据。根据文件,该数据集创建于 2010 年,目的是了解捐助方为一个目的提供的援助最终是否被用于另一个目的。
这些数据包含了什么?
接下来:启动你最喜欢的数据辩论库,第一次让你的数据达到顶峰。我不知道其他人做了什么,但我导入数据后做的第一件事就是调用head()
函数,看看它在原始状态下是什么样子。然后我会检查(不一定按这个顺序)有什么样的列,数据类型是什么,数据大小是多少,是否有缺失值。老实说,对我来说,这是处理数据最令人兴奋的部分,尤其是处理未知数据,就好像我发现了新的东西!
# import libraries
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns# import data
df = pd.read_csv("../data.csv")# take a peak into the data
df.head()
清理您的数据
数据清理确实会花费你大量的时间,尤其是当你对它几乎一无所知的时候。我也花了不少时间来清理我的数据集。为了不把这篇文章写得太长,如果你感兴趣的话,我已经把数据清理的整个过程记录在一个 jupter 笔记本和上传到 GitHub 的中。
提问
现在您的数据已经清理完毕,您可以将它带到您的环境中来做一些事情了。如果您了解探索性数据分析(EDA),那么您已经知道可以对数据集做什么:
- 描述统计学
- 散点图
- 图表
- 分布图
- 还有更多…
您可能可以从数据集中提取数百条不同的信息。这绝对是一种解决方法。但我认为更有趣的方式是问一些你可能会感兴趣的问题。这样你的时间会得到更有效的利用。因为我的数据集是关于非洲艾滋病的,我感兴趣的第一个问题是:
问:有多少国家和哪些国家接受了援助?
# number of countries
print("Number of countries: ", df["country"].nunique())# name of the countries
print(df["country"].unique())
既然我们知道有多少和哪些国家接受了援助,接下来显而易见的国家是:
问:这些年来哪些国家接受了相对较多的援助?
# creating boxplots to see summary of aid by receiving countries
sns.boxplot(y="country", x="aid_percap", data=df)
这是一个面板数据集,意味着每个国家都有自己的所有变量的时间序列。所以下一个问题是:
问:在研究期间,aid 的总体时间趋势是什么?
# plotting time series
sns.lineplot(x="year", y="aid_percap", data=df)
我可以继续下去……对每个变量问类似的问题,但我会在这里停下来。我将继续讨论一些更有趣的问题,一些双变量分析:
问:政府支出和援助之间有关联吗?
# bivariate scatter plot with linear model
sns.lmplot(x="aid_percap", y="govt_expenditure", data=df, fit_reg=True)
这个数据集不是终点。我会用其他来源的数据或文献来补充这个数据集中的发现,以验证和支持我的问题的答案。
建立预测模型
到目前为止,我在上一节中所做的事情是让您的数据准备好进行分析,并提出一些琐碎的问题来提取一些有趣的事实。它并没有在这里结束,而是很可能是一些更有趣和有用的东西的开始。下面是一个使用数据集构建线性回归模型以根据农业支出预测人均 GDP 的示例[注意:该模型仅用于演示目的,我跳过了许多中间步骤]。
# import necessary libraries
import numpy
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn import metricsdata = df[[ "gdp_percap", "agri_expenditure"]]# remove NA values
data=data.dropna()# select x, y data for modeling
y = data.iloc[:, 1].values
X = data.iloc[:, :-1].values# Split X and y into X_
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=1)# instantiate model
model = LinearRegression()# fit model
model.fit(X_train, y_train)# Model evaluationprint("Model score: ", model.score(X_test, y_test))
print("Intercept: ", model.intercept_)
print("Coefficients: ", model.coef_)print("*******")print('Mean Absolute Error:', metrics.mean_absolute_error(y_test, y_pred))
print('Mean Squared Error:', metrics.mean_squared_error(y_test, y_pred))
print('Root Mean Squared Error:', np.sqrt(metrics.mean_squared_error(y_test, y_pred)))
传达调查结果
讲述和交流你从数据中学到的东西是最不受重视的,但却是做数据科学最重要的部分。作为一名数据科学家,你需要能够总结故事中最有趣的部分,并能够将其传达给可能使用它们的人。这种交流可以采取任何形式,从写博客、制作幻灯片、为公司高管写报告到在科学期刊上发表。
注:jupyter 笔记本及更多代码、注释和相关数据在GitHub repo中。
Db2 仓库中的数据挖掘:基础知识
Db2 仓库数据挖掘
从数据所在的 SQL 中运行数据库内分析功能
数据库内数据挖掘是一种分析和操作方法,它利用数据库平台的功能和资源来支持、嵌入和公开数据挖掘功能。与其他数据库中的计划一样,这个想法是将建模和推理工作尽可能地集中到核心业务数据所在的位置。除了这种协同定位在性能和可伸缩性方面提供的好处之外,使用 SQL 来训练、验证和评分数据挖掘模型使得这些工件与公司事务和分析过程的集成变得容易。您可以在我之前的故事中了解更多关于数据库内数据挖掘的特性和好处。
利用关系数据库引擎实现集成的模式发现和预测建模解决方案
towardsdatascience.com](/five-reasons-for-in-database-data-mining-84e9cf8e084a)
本文的目标是将 IBM Db2 Warehouse 作为开发和部署数据挖掘工作负载的参考数据库平台。它涵盖了数据仓库引擎的主要特性,特别关注可用的分析例程,概述了模型管理框架和扩展点,以便在同一个通用平台中利用 Spark、Python 或 R。它应该作为围绕特定建模功能和场景的未来故事的起点。
Db2 仓库概述
Db2 Warehouse【1】是 IBM 开发的一个分析数据仓库平台。Db2 Warehouse 构建于 IBM 的通用 SQL 引擎之上,可以作为托管服务或 Docker 映像在云(IBM Cloud 和 Amazon Web Services)上使用,以便进行定制部署和轻松扩展(图 1)。主要特性包括:
- 分析优化。Db2 Warehouse 采用了 IBM BLU 加速技术,包括列数据的内存处理、并行向量处理、高密度压缩和智能数据跳过。BLU 加速是自我优化的,消除了对索引、聚集或定期数据库调整的需要,使其成为在线分析处理(OLAP)应用的理想选择。
- 可扩展性和性能。遵循无共享架构,Db2 Warehouse 支持单个和多个数据库分区配置。向外扩展是通过向现有集群添加新的逻辑或物理分区来实现的。在多分区数据库中,一个表可以放在多个分区中,因此它的行沿着集群的成员分布。
- 数据虚拟化。Db2 仓库数据库可以充当一个或多个数据源的联邦数据库。这样,一条 SQL 语句就可以访问分布在不同的异构远程数据源中的数据,就好像这些数据存储在一个数据库中一样。此外,Db2 Warehouse 支持透明地指向驻留在数据库之外的文件的外部表。
- 工作量管理。在 Db2 Warehouse 中,可以根据用户和应用程序需求对工作负载进行分类。通过这种方式,可以将 CPU、内存访问优先级或最大执行时间等资源分配给每组工作负载。为了隔离数据库中运行的密集型分析应用程序,这一点尤其重要。
- 多语种持久性。Db2 Warehouse 不仅是 SQL 引擎,还支持关系结构、空间数据和半结构化文档,如 XML、JSON 和 BSON。
- 数据挖掘特性。预测建模算法以分析例程的形式在数据库中实现,可以使用 SQL 调用这些分析例程。无需将数据移出数据库就可以实现高性能的数据挖掘应用程序。
在数据库中开发和部署数据挖掘应用程序是 Db2 Warehouse 最重要的特性之一。
图 1 —基于 Db2 仓库容器的架构
训练机器学习算法意味着大量的数据库交互,因为必须在每个训练时期重复获取数据。这个过程涉及多个 SQL 语句,如果在外部应用程序中进行训练,这又会产生许多发送和接收网络操作(以及相关的 CPU 成本)。但是,如果将训练实现为在数据库中执行的例程,则所有这些 SQL 语句(包括写入结果表的语句)都被封装到一个发送和接收操作中:网络流量被最小化,可以处理更多的数据,训练性能得到提高。这是数据库内数据挖掘方法的主要优点之一。
分析程序
Db2 Warehouse 提供了超过 125 个内置的分析例程[2],涵盖了数据挖掘解决方案工作流的不同步骤:数据探索和理解、转换、建模、验证和评分。这些例程中的大多数都是存储过程和用户定义函数的形式。在第一种情况下,通过对存储过程的 CALL 语句进行调用,在第二种情况下,作为 SQL SELECT 的一部分。
这些例程是 SQL PL 模块 SYSIBMADM 形式的每个数据库目录的一部分。IDAX,它也包含支持数据类型和变量。它们可以分为六大类。
数据探索
数据探索的目标是通过分析不同的统计数据和识别分布来了解将要建模的数据,同时也是为了检测可能的质量问题,这些问题可以在建模任务之前通过数据转换功能来解决。
表 1 —数据探索功能
统计测试
通过验证性数据分析,您可以测试假设并检查几组数据,验证独立性、相关性和显著性。
表 2 —统计测试函数
数据转换
数据转换类别包含转换要分析的数据结构的例程,以便使它们更适合于进一步的分析处理。它们可以很容易地与探索和建模例程链接起来,以便符合也可以安排的训练管道。
表 3 —数据转换功能
无监督学习
这些机器学习方法在没有预定义类别和最少用户监督的情况下检测数据集中的模式和共现关系。
表 4 —无监督学习功能
监督学习
监督学习方法包括分类和回归函数,这取决于目标变量是分类变量还是数值变量。它们都实现了建模和评分模式。
表 5 —监督学习功能
诊断功能
诊断功能提供了在验证阶段评估分类和回归模型的准确性和质量的方法。
表 6 —诊断功能
图 2 显示了一个典型的分类模型管道,包括数据探索、数据准备、训练和验证步骤。清单 1 根据所使用的分析例程(存储过程)、其功能和所需的参数详细说明了管道的每一步。
图 2 —建立分类模型的步骤和相关表格
管道的输入数据集包含属于三个不同品种的几种葡萄酒中存在的 13 种成分的化学分析结果。目的是根据这些成分鉴定正确的栽培品种。
清单 1 —在 IBM Db2 仓库中使用分析存储过程的分类管道实现
其思想是,这个过程的调用可以被链接和打包在另一个例程或复合语句中,该例程或复合语句可以作为一个整体被调用,添加附加的逻辑、错误处理、审计或执行权限。此外,还可以利用集成的 Db2 调度器来定义和自动化执行类似这样的管道的任务。
模型管理
机器学习算法生成存储在数据库中的数据挖掘模型。为了管理它们,提供了一组管理例程,包括安全性和权限。模型目录位于 SYSTOOLS 模式中,由存储不同模型元数据的四个表组成(图 3):
- IDAX_MODELS 。目录中的中央表,存储常规模型属性,包括模型名称、创建者、所有者、挖掘函数、算法或模型源(如果模型已导入)。
- IDAX_PARAMS 。定义模型时指定的参数。这些包括源表、名称映射支持表、生成模型的例程以及为算法定义的任何超参数。
- IDAX。COLPROPS 。用于创建模型的源表中的列属性。其中一些属性是自动派生的,比如 SQL 类型或基数。其他的被指定为模型定义的一部分,如列角色(输入、目标、权重等。).
- IDAX。组件。根据模型挖掘功能的不同,会创建不同的结果表,其中包含模型的参数和细节。该表记录了模型中涉及的所有数据结构,包括源表、支持表和结果表。
图 3 —模型目录库表格
除了需要特定权限之外,不应直接访问模型目录表。因此,元数据管理的几个例程以不同的类别提供:
- 行政操作。这些函数用于检查模型目录库的状态,包括初始化和重置。
- 列表操作。提供对目录表的只读访问的函数。
- 模型操纵操作。一组例程,用于更新、删除和获取存储在目录中的不同模型的摘要。包括在专有的中导出和导入模型的功能。mdl 格式,以及导出为 PMML 模型。
- 安全操作。在模型级别为不同的用户、组或角色授予、撤销或列出权限。
简而言之,Db2 Warehouse 为元数据管理提供了完整的 SQL API。与其他分析例程一样,您可以通过 SQL 脚本或支持存储过程调用的外部应用程序与这些函数进行交互。此外,这些功能中的大部分都可以在 Db2 Warehouse web 控制台界面中获得。
扩展分析能力
除了从 SQL 中运行数据库内数据挖掘功能之外,还有其他选项来扩展 Db2 Warehouse 数据库环境的分析能力。
用户定义的扩展
数据库功能可以通过不同类型的例程来扩展。在任何情况下,例程实现数据库内逻辑,这意味着应用程序在与数据库相同的进程中执行,具有最少的网络操作和降低的处理器成本。结果是数据密集型流程和 SQL 执行的性能得到了显著提高。如前所述,Db2 Warehouse 已经提供了一整套内置的分析过程。但是,可以通过编写用户定义的扩展来扩展分析能力。有几个选项可用:
- SQL PL 例程。Db2 SQL 过程语言是 SQL 的扩展,它提供变量和条件处理程序声明、控制结构和错误管理的语句,以便在数据库中实现过程逻辑。这些语言元素可用于开发存储过程、标量函数和表函数,这些函数可打包成模块。就数据访问而言,SQL PL 中实现的例程在性能、安全性和可伸缩性方面提供了最佳选择。然而,对于复杂的应用程序逻辑,它们可能不是最佳选择。当在内置的分析程序之上实现例程时,应该考虑这些扩展,因此,为了提供定制的组件和解决方案,应该对它们进行组合和包装。
- 对外套路。流行的编程语言,如 C/C++,Java。NET、Python 或者 Lua,都可以用来实现 Db2 仓库中的复杂逻辑。如果目标是在数据库中实现新的建模算法,这可能是最好的选择。最后,对于存储过程,它们将作为 SQL SELECT 或 CALL 语句的一部分被透明地调用。为了部署这些功能,必须将源代码和附加文件上传到 Db2 实例。然后,在创建和编译库文件之后,通过指定其签名和类,在数据库目录中注册该例程。
除了其他数据库对象之外,用户定义的例程可以在 Db2 Warehouse 中被混淆,因此它们可以被部署到数据库中,而不会暴露应用程序逻辑。这对于想要保护其知识产权的解决方案提供商和开发者来说非常重要。
嵌入式 Apache Spark 引擎
Db2 Warehouse 包括一个与数据库引擎高度集成的 Apache Spark 集群。通过这种方式,可以部署、启动和监控直接从数据库读取数据的 Spark 应用程序,在集群中并行处理这些数据,然后将结果写回数据库。有四种可能的方法来管理集成 Spark 集群中的作业:
- SQL 存储过程。有三个程序可用于启动、监控和取消火花应用。
- REST API 。与存储过程功能类似,分析 API 可用于管理应用程序。
- 命令行工具。提供了一个基于 cURL 的脚本,它实现了 spark-submit 脚本的一个子集,外加一些特定的 Db2 仓库命令。
- 阿帕奇 Livy 服务器。Db2 Warehouse 提供了一个经过集成和配置的 Livy 服务器,它通过 REST 或编程(Java、Scala、Python) API 接受 Spark 作业。
因为 Spark 执行器与数据库节点位于同一位置,所以对数据的访问延迟被最小化(图 4)。数据通过进程间通信使用共享内存进行传输,因此在处理大型数据集时速度会显著提高。
图 4—Db2 仓库集群中的集成 Spark 引擎
Python 包
Db2 Warehouse 为从 Python 应用程序访问数据库提供了几个组件和扩展:
- ibm_db 。这个包提供了两个 API 来连接和管理数据库(支持 Db2 和 Informix 数据服务器)。ibm_db API 是由 ibm 定义的,它提供了一组丰富的方法来发布 SQL 查询、调用存储过程和管理数据库对象[3]。第二个是 ibm_db_dbi API,实现了 Python 数据库 API 规范 2.0 版。虽然它的功能不是很广泛,但是当应用程序需要符合规范时,它是必要的。当需要通过 Pandas 访问数据库时就是这种情况(清单 2)。
清单 2 —将 Db2 仓库数据放入 Pandas 数据框架
- ibmdbPy 。这个开源包提供了一个数据库内分析 Python 接口来访问 Db2 仓库中的数据和算法[4]。它实现了 Pandas 和 Scikit-learn 库的接口,分别用于数据操作和机器学习算法,将 Python 操作推到底层数据库中执行。通过提供等效的数据结构,如 IdaDataSeries、IdaDataFrames 或 IdaGeoDataFrames,ibmdbPy 可以通过提升 Python 的内存和 CPU 限制以及利用 Db2 Warehouse 的并行处理和列存储功能来非常有效地处理大量数据。例如,IDA 数据帧使用延迟加载来仅获取实际需要的数据部分:当函数请求数据时,它不在应用程序中运行,而是被转换为 SQL 查询,该查询在数据库中执行,结果被转换回 Python 对象。除了数据访问操作之外,ibmdbPy 还提供了特性选择、相关性分析、数据库内地理空间函数(利用 Db2 Spatial Extender)的方法,以及作为 SQL 例程提供的几种机器学习算法的包装器。
- 朱庇特笔记本。为了方便 Jupyter 笔记本中 Db2 对象的连接和操作,可以导入一个扩展(Db2 . ipynb)[5]。这个扩展启用了一个神奇的命令(%sql),它允许将输入的文本解释为 sql 脚本,而不是 Python 代码。通过这种方式,不需要导入其他数据库访问库,将数据转移到 Pandas DataFrames 中非常简单(清单 3)。
清单 3—Jupyter 笔记本中 Db2 仓库数据的直接 SQL 操作
r 包
与 Python 类似,Db2 Warehouse 中的 R 编程基于几个包:
- RODBC 。通过 ODBC 接口提供对 Db2 仓库数据库的访问的标准包。
- ibmdbR 。相当于 Python 中的对应物,它通过在 R [6]中实现 IDA 数据帧结构,允许直接在 Db2 仓库中进行数据库内分析。这个库中还提供了许多 SQL 分析例程。
结论
Db2 Warehouse 是一个高可伸缩的平台,其中数据和分析位于同一位置。通过利用关系数据库引擎和 SQL 语言,数据挖掘工作负载可以部署在数据已经驻留的地方,避免提取到专门的外部系统。
Db2 Warehouse 配备了 100 多个分析例程,涵盖了数据探索、转换和机器学习算法,还通过集成的 Spark 集群和专门的 Python 和 R 库提供了扩展功能。这是一个可以构建和部署高性能、以数据为中心的分析应用程序的环境。
一般参考
[1] IBM 公司, Db2 Warehouse 文档,Db2 Warehouse 11.5 产品中心
[2] IBM 公司,分析存储过程,Db2 仓库 11.5 知识中心
[3] GitHub,IBM _ db 驱动程序的 API 描述,IBM db—IBM 数据库服务器的开源驱动程序
[4] GitHub,通过数据库内处理加速 Python 分析,ibmdbanalytics
[5] GitHub, Db2 Jupyter 笔记本扩展,DB2-Samples
[6] CRAN, IBM 数据库内 R 分析,ibmdbR
软件访问
Db2 Warehouse 可以在 IBM Cloud 和 Amazon Web Services 中作为一个灵活的、完全托管的数据仓库即服务产品来访问。该服务有单节点和多节点两种形式。或者,它也可以作为 Docker 映像发布,用于可以从 IBM Cloud Container Registry 中提取的定制部署。
Db2 Warehouse Developer Edition是 Db2 Warehouse 的一个全功能版本,免费,面向开发和测试环境。此版本不适用于生产,并且不支持多节点部署。Docker 映像可以从 IBM 网站下载,并在几分钟内部署到笔记本电脑中。