数据工程:创建自己的数据集
如何使用 Python 和提取转换加载管道创建自己的数据集
伊恩·巴塔格利亚在 Unsplash 上拍摄的照片
介绍
你是一名机器学习工程师还是一名数据科学家,你想在数据集上应用机器学习(ML),而数据集目前并不存在?或者你是一名数据工程师,你的工作是创建一个数据集,以便机器学习工程师和数据科学家可以将这个数据集转化为你公司的商业价值?在这两种情况下,您应该熟悉提取-转换-加载(ETL)管道。
ETL 是一个允许您从各种来源提取数据,根据您的要求转换数据,并最终将其加载到您选择的数据库或数据格式中的过程。
在本文中,我将向您展示一个 ETL 管道的例子。我想创建一个小型数据集,其中包含所有国家的幸福数据、关于人口数量和国内生产总值的数据,以及每个国家的平均年龄。
作为编程语言,我使用 Python。我从维基百科搜集幸福值,从 Rapid API 搜集每个国家的人口数据,从另一个网站搜集平均年龄。然后,我将这些数据集组合在一起,并对数据集中存储的数据类型和数值应用一些转换。最后,我将数据集加载到一个 CSV 文件中,这样它就可以被机器学习工程师加载。
你可以在我的 Github 库这里找到完整的 Jupyter 笔记本。我使用 Python 中的 BeautifulSoup 包和 request 包从不同的网站和 API 中抓取数据。
提取
现在让我们从管道的第一部分开始,从不同的来源提取数据。作为第一步,我从维基百科收集快乐数据。代码 1 显示了从 Wikipedia 链接中提取完整的 html 数据,然后使用 BeautifulSoup 从提取的 html 数据中获取幸福表的代码。
代码 1: Python 代码,用于从维基百科抓取快乐数据,并将其存储在熊猫数据框中。
在第 8 行,请求包用于从提供的 Wikipedia 链接中获取 html 数据。在第 14 行,创建了 BeautifulSoup 对象,并将原始 html 数据作为输入传递。在第 17 行中,“find_all”函数用于获取所有带有 html 类“wikitable”的表。Gif 1 展示了如何检查一个网站的元素,以获得您感兴趣的表的类别。
Gif 1:这个例子展示了如何检查一个 html 对象来获取 html 类。可以通过右键单击对象,然后选择“检查元素”选项来检查 Html 对象。
Code1 的剩余部分将 html 表转换成 Pandas 数据框。
图 1 显示了这个数据框的头部,它包含了 153 个国家的幸福数据。
图 1:世界幸福数据框头部。
下一步,使用 Rapid API 中的 this API 获取每个国家的人口数据。Rapid API 还提供了一些关于如何从该 API 获取数据的示例 Python 代码。代码 2 显示了从这个 API 获取数据并将其附加到幸福数据帧的代码。
代码 2:通过从 Rapid API 提取数据来获取幸福数据集中每个国家的人口数据的代码。tqdm 包用于在执行 for 循环时获取进度条。
不幸的是,五个国家的人口数字不见了。这些现在可以从互联网上的其他来源加载,但这不是在这个小项目的上下文中完成的。
下一步,通过抓取世界数据网站来加载每个国家的平均年龄,可以在这里找到。再次检查感兴趣的表,以便获得正确的 html 类。代码 3 显示了获取数据并将其存储在数据帧中的完整代码。
代码 3:用于从 worlddata 网站提取每个国家的平均年龄数据并将其存储在 Pandas 数据框中的代码。
这个数据集只包含 116 个不同国家的数据,而幸福数据集包含 153 个国家的数据。同样,人们也可以从不同的来源提取缺失国家的数据,但在这个小项目中没有这样做。
现在,作为提取过程的最后一步,幸福数据框和包含每个国家平均年龄的数据框被合并成一个大数据框(代码 4,图 2)。
代码 4:连接数据框以创建一个大的数据框。
图 2:提取管道步骤结束时的数据帧头。
改变
现在让我们从 ETL 管道的第二部分开始,转换步骤。在转换步骤中,您通常会调整数据格式以满足您的需求,或者将列组合到新功能中。数据集准备得越好,机器学习工程师之后要做的工作就越少。在这个项目中,我决定添加一个包含每个国家 GDP 的列。这可以通过将“人均国内生产总值”和“人口”两栏相乘来计算。作为第二个转换步骤,我通过删除百分号并将字符串转换为浮点数,将列“20 岁以下人口”转换为浮点数。代码 5 显示了这些转换的代码,而图 3 显示了最终转换后的数据帧的头部。
代码 5:转换管道步骤的代码。计算 GDP 并将其添加到数据框中,20 岁以下人口列被转换为 float 类型。
图 3:应用转换后数据帧的最终状态。
负荷
加载步骤是 ETL 管道的最后一步。在加载步骤中,最终数据集被加载为预期的存储格式。这可以是数据库、CSV 文件或许多其他存储类型之一。我决定将这个数据集存储在一个 CSV 文件中。这可以很容易地加载到机器学习中。代码 6 显示了最后一个管道步骤的代码。
代码 6:将最终数据集加载到 CSV 文件中。
结论
在本文中,我通过使用几个不同的数据源创建了一个小型数据集,并将数据组合成一个数据集。我演示了 ETL 管道的样子,并为每个管道步骤添加了代码。数据集现在可用于进一步分析。
谢谢你把我的文章看完!我希望你喜欢这篇文章和我参与的项目。如果你想在未来阅读更多类似的文章,请关注我,保持更新。
数据工程失败—为什么几乎不可能在截止日期前完成?
思想和理论
“我喜欢截止日期。我喜欢它们经过时发出的嗖嗖声。”
工程是一门艺术(鸣谢:我)。
失败。我想写关于失败的东西。为什么数据工程师很难评估项目的持续时间,也很难满足截止日期?
在我过去 7 年的工作经历中,我有机会与多个数据工程团队合作。我注意到一个项目接一个项目的一个常见模式是,工程师很难定义和满足里程碑。
为了创建路线图和里程碑,我们一个团队接一个团队尝试了所有流行的方法。从 Scrum 跳到 Lean,尝试使用扑克计划或同行评估来确定任务的大小。这并没有阻止我们失败。但是,这很正常。
在这篇文章中,我将分享我们作为数据工程师失败的 3 个主要原因,并提出解决方案,以开启与社区的讨论。
数据工程师不擅长区分优先级
我们不擅长优先排序,这意味着大量的中断和不切实际的时间表。你说打扰?是的,数据工程深受上下文切换之苦。我们每天经常在不同的任务间穿梭。
这里是夸张的(是真的吗?)数据工程师的日常计划:
- 早上——修复夜间破裂的管道
- noon —回答#data-public 上关于仓库列的公共松弛问题
- 下午——帮助一位分析师解决一个你在早上喝咖啡休息时聊到的棘手问题
- 下班后——你开始你的日常工作
因为数据工程师在历史上被视为一个支持团队,他们需要(或者他们想要)尽可能快地回答问题,这显然与项目期限相冲突。很难拒绝。我知道。但是为了保持你的心理健康,你需要学习。
另一方面,我们也有太多反复出现的管道问题。编写无错误的管道是一项艰巨的任务。但是为什么呢?因为我们经常处于数据提供者和消费者之间(参见数据网格),面对太多的移动部分。我们将数据从数据库转移到存储或第三方平台。数据库模式、存储、第三方 API 或业务需求可能会发生变化。然后产生新的问题。
但是,我们不要只责怪其他团队,我们有时也会因为没有足够的时间或因为我们只是拙劣地建造蹩脚的管道。很难区分计划好的项目、计划外的项目和日常的 bugs &问题。
解决方案
为了解决这个优先化的问题,我给你提供了 4 条探索的途径。你会看到前三个是组织性的,最后一个更多的是关于消除技术债务以避免每天支付。
1 —开始成为产品团队的旅程。让人们明白你和他们一起开发工具,而不仅仅是提供服务。然后,开一个产品管理岗位,才能开始像考虑产品一样考虑数据。这颗子弹是目前数据网格及其周围一切的行业大趋势。警告:不要雇佣项目经理来管理积压的任务。
2 —如果你管理一个数据团队,创造一个信任的氛围,让工程师在必要时说不。当来自高层的压力很大时,说不并不是一件容易的事。
3-创建图腾持有者角色。团队中应该有人每周负责回答所有可能的外部干扰。创建每周轮换和角色很容易,但不要忘记检查角色是否真的有效。这会减少干扰吗?如果没有,找到原因并改进。
3 —将软件工程最佳实践应用到您的管道或应用程序开发中。像幂等性、可再现性、读/写模式等概念。是必须做的。当你开发一个管道时,它很可能有一天会失败。所以,为了未来,让调试和重启变得容易些。并且记住:造复杂是简单,造简单是复杂。
每天都有新的十字路口
数据工程项目在另一个时间表上
与其他数据任务相比,数据工程任务很少是小任务。您可能已经遇到过这种情况,分析师要求用一个表来回答一个业务问题,而当您添加该表时,分析师已经找到了获取数据的解决方案。
前一种情况说明了人们所处的不同时间表数据,也描述了同步它们的复杂性。
- 数据分析师每天都有时间表,因为他们主要回答问题(业务或直觉)。
- 数据科学家每周都有时间表,由于特征工程,他们将问题转化为模型。
- 数据工程师按月安排工作,他们构建平台以支持过去、当前和未来的使用案例和增长。
我们按月工作的主要原因是,到今天为止,工具仍然很难操作(你还记得 Hadoop 吗?),对于同一项任务,我们有太多的工具和可行的解决方案,而不考虑这样一个事实,即每次我们在做一些事情时,都会发现一些计划外的东西。
如果我们增加工具的复杂性,数据平台得到的低质量输入。它带来了很多边缘案例:*正常案例正在成为边缘案例,不良输入成为常态。*说实话,许多数据平台尚未涵盖数据质量路径,数据工程师每天仍面临边缘情况。
工具复杂性和输入质量之间的这种混合会给我们工作的每个任务带来延迟。我们终于明白为什么我们需要这么长时间才能前进。
一名数据工程师因为洪水而推迟了他的项目
解决方案
1 —循序渐进。第一次评估项目?不要试图确定一年项目的规模。将它分割成 3 周或 3 个月的小项目,并创建小的可理解的任务。第一次你会错,但是经过几次尝试后,你肯定会变得更好。不练习,成不了大师。
2 —我们都在同一条船上。在数据团队中,我们的北极星应该是为同事提供数据。让我们成为队友,理解彼此的限制。工程师在这里为公司创造最好的平台,分析师和科学家在这里创造数据的可见性、用途和界面。
3-关注技术创新,拥抱它们。许多新产品(Airbyte、Meltano、Singer 等)都加入了云数据存储(BigQuery、Snowflake、Databricks)。他们旨在简化数据工程的复杂性。使用它们。更重要的是:让它们适应您的堆栈。
数据工程学科仍然年轻
这一学科如此年轻的事实突出了前面两点。每一个选择或小错误都可能很容易导致技术债务。
这个行业错了好几年,随着数据科学的大肆宣传,许多公司雇佣了数据科学家,让他们做数据工程工作。这导致了两个主要问题:我们有沮丧的数据科学家和糟糕的工程平台。
不要误解我的意思,我认为数据科学家可以建立很好的平台,但是当你在做一项你不应该做的工作时,结果可能是欺骗性的。
数据工程团队通常被整合到“传统的”产品团队中,但是因为这个学科是新的,所以其他团队无法弄清楚数据工程师的能力。这是一个问题。有时,数据工程师可以带来更适合的解决方案,以避免不必要的工作。
我们也缺乏数据产品经理或者对数据平台有了解的产品经理。经常发生的情况是,产品经理在他们的范围界定中完全忘记了数据生态系统,后来给数据团队增加了计划外的工作。
此外,由于他年轻的数据工程技能相当广泛,除了大公司有足够的资源专门团队,小公司需要雇用 5 条腿的绵羊数据工程师。数据工程师被要求从 DevOps 技术跳到生产级代码编写,然后再跳到 SQL 调试。
一名数据工程师正在阅读“数据工程杂志”(鸣谢)
没有多少工程师有构建数据平台的丰富经验。对于一个新项目的团队来说,如果团队中没有人做过,那么很难评估这个项目会持续多久。如果我们再加上每两年变化一次的工具和趋势,我们如何才能更好地进行评估呢?
解决方案
1 —寻求帮助。你可能没有机会在你的团队中有一个前辈,但我认为如果你要求的话,会有人愿意帮助或挑战你。例如,询问其他规模相同或市场相同的公司,要有创意。我过去做过,我遇到了很棒的人。
通过在公共会议和/或聚会上展示来挑战你的选择和愿景。从这里你会得到问题和反馈,这将有助于你评价你的平台。
2——阅读别人写的东西,获得灵感。但不要忘记,你可能不是网飞、优步或 Airbnb。您可能不需要创建新的开源数据库技术来计算您的度量。
3 —雇佣拥有不同技能的团队。如果适合您的使用情形,最好雇用 2 名多面手和 2 名专业人员(例如开发操作系统和流),而不是 4 名多面手。但是要小心,过早地专门化你的团队也会产生问题。你不希望只有一个人负责流媒体。否则假期对他来说会很难熬。
结论
如果你是数据工程师,请善待自己。成为一名伟大的数据工程师需要时间。如果这是你第一次独自创建一个平台,挣扎是正常的。
如果你和数据工程师一起工作,请善待他们。在他们的日常职业生活中,工程师喜欢看到人们使用他们制造的工具。
但是不要忘记给你的项目设定(具有挑战性的)截止日期。只有这样,你才会进步,并开始与同事建立信任。还要记住,每个解决方案都有自己的文章,我们有许多可操作的杠杆来改善这种情况。
这篇文章也可以更普遍地应用于软件工程。数据工程真的如此讲究,有特定的需求吗?难道我们不应该把数据工程师当成另一个工程团队吗?
特别感谢 Augustin、Charlotte、Emmanuel 和 Pierre 的评论。
副标题由道格拉斯·亚当斯引用。
这篇文章最初发表在 blef.fr 上,我在那里发表了一份关于数据的每周策划简讯。工程、筹款、分析、组织一切都是。
数据工程——使用 Apache Airflow 的 Google Bigquery 到漂亮的电子邮件模板
从你的数据仓库到电子邮件
Solen Feyissa 在 Unsplash 上拍摄的照片
大家好。
作为数据从业者,我们经常需要将数据交付给需要它的人。
随着时间的推移,在数百个特别请求和 SQL 查询之后,您很快就会意识到这些请求中有许多是相似的,并且可以自动化。
与此同时,以 excel 文件形式附加数据的传统方式已经过时了。现在是 2021 年,是时候想出创新的方法来显示你的数据了。
你有没有想过从你的数据仓库中提取一些数据,并通过电子邮件发送出去,同时让整个过程自动化?
我正好有适合你的东西。
今天,我们将使用 Apache Airflow 来自动化整个过程,同时保持数据的美观。
先决条件
我们将使用熊猫来转换数据。
我在这里 写了关于熊猫 的基础知识,涵盖了你需要了解的关于处理数据的主要概念。
然后我们将使用阿帕奇气流使整个过程自动化。Airflow 是数据工程师用来有效管理和监控其自动化任务的工作流管理系统。我碰巧在这里 写了一篇关于在 Apache Airflow 上构建第一个管道的综合指南。
对于这个例子,我们将使用 Google Bigquery 作为我们的数据仓库,因为这是我目前正在使用的。但是,要理解数据可以从任何数据仓库中提取出来,并以类似的方式进行操作。
让我们写一些代码。
克里斯托弗·高尔在 Unsplash 上拍摄的照片
安装和导入
#installing libraries
pip install google-cloud
pip install pretty-html-table
pip install pandas-gbq
pip install pandas#importing libraries
import google.cloud.bigquery as bq
import pandas as pd
import pandas_gbq
from pretty_html_table import build_table
from airflow.utils.email import send_email
熊猫-gbq
Pandas-gbq 是一个包,提供了从 Pandas 到 Google BigQuery API 的接口。它允许我们从 Bigquery 中提取数据,并通过一行代码将其导入到我们的 Pandas DataFrame 中。如果你没有使用 Google BQ,如果你的数据仓库有 pandas 连接器,可以做一个快速搜索。
漂亮的 html 表格
Pretty-HTML-table 允许我们在一个漂亮的 HTML 表格中显示我们的熊猫数据帧。这个表格整洁美观,非常适合显示任何类型的汇总数据。
获取数据
使用 Google Bigquery 作为我们的数据仓库。
query = """SELECT * from sample_table"""
project_id = <your google cloud project id>
df = pandas_gbq.read_gbq(query, project_id=project_id)#process your data here
下面是我们的示例数据,用于演示目的。
作者图片
请注意,在继续之前,您可以在这里进行任何类型的数据处理。
美化桌子
在这里,我们将数据转换成一个漂亮的 HTML 表格。
output_table = build_table(df, 'blue_light')
如果你打印‘output _ table’,它会显示一堆 HTML 代码——
作者图片
它在邮件中实际上看起来是什么样的——
作者图片
这个库把你的熊猫数据帧和转换成一个 HTML 编码的表格,这在电子邮件中看起来更顺眼。因此,当您遇到一堵无法阅读的代码墙时,不要感到惊讶。
wolfentertainment.comgif
我在这里使用“蓝光”主题。可用主题的完整列表可以在库的 PYPI 文档 中找到。
准备电子邮件内容
既然我们已经准备好了数据。
是时候创建并发送我们真正的电子邮件了。
#creating email content
html = '<!DOCTYPE html><html><p style="font-family:verdana">'
html += """Here's the data for the day: """
html += '<hr>'
html += output_table
html += '</p></html>'#defining receivers and subject
email_subject = 'Sample Data from Bigquery'
email_to = <receivers>
email_content = html
send_email(email_to, email_subject, email_content)
现在可以发送电子邮件了。就这么简单。
设计气流操作器
现在我们已经完成了代码,下一步是将它们组合成一个气流操作符,这样我们就可以自动完成这项工作。我们可以确定哪些变量要作为实例变量传入。
出于演示的目的,我选择了 query、receivers 和 Pretty-HTML-Table 主题作为实例变量,只是为了好玩。
创建操作符时要注意的主要变量是 execution_date 。这个变量表示 airflow UI 中的执行日期,不会被运行日期弄错。
作者图片
我们可以用执行日期替换查询中的日期,这样我们的作业在每次运行中只提取当天的数据。让我们在 DAG 里做吧。
设计气流 Dag
最后一步是写入气流 Dag 。这就是我们定义的—
- 什么时候运行作业?
- 我们多久运行一次作业?
- 我们什么时候正式开始工作?
通过使用上面的示例,我们已经将管道设置为从 2021 年 3 月 7 日开始,每天在
上午10 点**运行。**我们还将查询设置为只提取当天的数据。
和…差不多就是这样!
现在坐下来,监控你工作中的错误。
结论
安东尼·福明在 Unsplash 上的照片
恭喜
如果你已经走了这么远,给自己一点鼓励。
在这篇文章中,我们谈到了—
- 从 Google Bigquery 中提取数据
- 将它转换成一个漂亮的 HTML 表格
- 创建电子邮件的内容
- 将一切组合成一个气流算子
- 设计 DAG 以自动化作业
现在走吧。建立你的管道并与我分享。
我在等。
数据是一种珍贵的东西,它将比系统本身持续更久——万维网的发明者蒂姆·伯纳斯·李。
订阅我的时事通讯,保持联系。
也可以通过 我的链接 注册一个中等会员来支持我。你将能够从我和其他不可思议的作家那里读到无限量的故事!
我正在撰写更多关于数据行业的故事、文章和指南。你绝对可以期待更多这样的帖子。与此同时,你可以随时查看我的其他 文章 来暂时填补你对数据的渴望。
感谢 的阅读!如果你想和我联系,请随时通过 nickmydata@gmail.com 联系我或者我的 LinkedIn 个人资料 。也可以在我的Github中查看之前写的代码。
数据工程师不应该写气流图——第 1 部分
意见
是时候寻找一种更好的方法来使用 Apache 气流了
里卡多·戈麦斯·安吉尔在 Unsplash 上的照片
我认为数据工程师不应该写气流图。相反,数据工程师应该构建自动化那些 Dag 创建方式的框架。
没有什么比一遍又一遍地做同样的事情更无聊的了。这正是你写 DAG 时要做的。你一遍又一遍地做着同样的事情。过了一段时间,工作变得重复,你的技能开始得不到充分利用。
Stitch Fix 的数据平台副总裁杰夫·马格努松几年前写了一篇文章,他在文章中指出 工程师不应该编写 ETL *。*他的观点是数据工程师的工作不是编写 ETL,而是概括和抽象这些 ETL 的制作方式。
我相信这正是我们在气流方面做错的地方。我们只是在编写 Dag,而不是构建概括和抽象 Dag 创建方式的框架。当你做了一段时间后,它会变得重复并且不好玩。
此外,重复代码不是编写可维护代码的聪明方法。干 ( 不要重复自己)原则存在是有原因的,也就是,写可维护的代码。
这篇文章旨在与你分享我写了两年气流 Dag 后学到的一些经验。我希望这能对社区有所帮助,并从中受益。我相信是时候找到一种更好的方法来使用 Apache Airflow 并改进我们进行数据工程的方式了。
TL;构建框架,不要写 Dag。你可以通过使用动态 Dag、OOP 和软件设计模式来做到这一点。
数据工程师的职责
数据工程师的主要职责不是写 ETL。同样,对于 Apache Airflow,数据工程师的职责不是编写 Dag。为什么?很简单。
“工程师擅长抽象、概括,并在需要的地方找到有效的解决方案。”杰夫·马格努松
我相信数据工程可以被看作是软件工程的一个专门化。软件工程的主要目的是编写可靠的、可伸缩的、可维护的代码。我认为这也是我们作为数据工程师应该努力的事情。
实现这一点的方法之一是对事物进行概括和抽象。那是我们的工作。通过概括和抽象来构建事物,这样我们就可以授权数据分析师和数据科学家来完成他们的工作。
“那么,在这个新的、水平的世界里,工程师的角色是什么?总而言之,工程师必须部署平台、服务、抽象和框架,让数据科学家能够自主地构思、开发和部署他们的想法(比如用于构建、调度和执行 ETL 的工具、框架或服务)。”杰夫·马格努松
数据工程师不应该写 Dag
你需要学习的第一件事是**,确定什么时候写 DAG,什么时候不写。**
我不希望你去工作,开始疯狂地概括和抽象事物。过度工程化和过度一般化也是一个问题。你应该努力保持平衡。
这里有我写博客时学到的 4 课。我希望这给你带来一些关于如何停止写 Dag 并开始构建更多框架的指导!
1.DAG 写入有时会重复
我写的第一个 DAG 是一个 MySQL 数据库的 ELT 过程。任务很简单。考虑到一些限制条件,我必须提取数据。把它载入 S3 自动气象站。最后,使用基于 SQL 的转换来转换数据。就这样。所以,我只是用几个 PythonOperators 写了一个 DAG 文件。
集成之后,我被要求再集成两个数据库。一个是另一个 MySQL 数据库,另一个是 MongoDB 数据库。
很简单。像第一个任务一样的另一个任务。因此,我从第一个 DAG 文件中复制了一些代码,并将这些代码复制到几个 DAG 文件中。我对另外几个积分做了同样的事情。没什么大不了的。只是多了 5 到 6 个数据源。
几个月后,我们决定改变使用气流操作器的方式。我们从 PythonOperators 迁移到了 KubernetesPodOperators。你猜怎么着?我发现我在所有 DAG 文件中都有几乎相同的代码。因此,我不得不在所有 DAG 文件中进行相同的更改。
这时我意识到我做错了。所以,我们开始使用动态 DAGs 。然后,我们使用面向对象编程(OOP)改进了这种方法。特别是,我们构建了一个定制的 DAG 工厂。工厂允许我们从一段独特的代码中创建多个 Dag。这让事情变得简单多了!
这是我在学到的第一课。你 可以使用动态 Dag 和面向对象的方法来构建你的 Dag。但是,要小心,动态 Dag 在大量使用时会产生问题。点击阅读更多。
查看这些文章了解更多信息。
https://www.astronomer.io/guides/dynamically-generating-dags
2.构建允许人们与您的 Dag 进行交互的界面
在我们开始动态生成 DAGs 之后,感觉棒极了。编写用于集成新数据源的新 DAG 可能需要 5 分钟。除非你知道把代码放在哪里。
这是我的第二堂课。你不是给自己造东西,而是给别人用。
我会让数据分析师写他们自己的 Dag,但是他们不能,因为太难了。那时,我们萌生了编写一个框架来加载基于 YAML 文件的数据源的想法。没什么特别的,但是很实用。
这里的底线是构建允许人们与你的 Dag 交互的界面。在我们的例子中是一个简单的 YAML 文件。但是,天空是极限。如果您需要的话,您甚至可以构建一个 web UI 来实现这一点。
3.气流操作员工厂是必要的
我喜欢从 Airflow 1.10 迁移到 2.0。但是,你知道吗?我讨厌在使用 KubernetesPodOperator 的地方修改所有的代码行。
在气流 2.0 中,KubernetesPodOperator 发生了很大的变化。以下是影响我们的一些事情:
- 端口已从列表[Port]迁移到列表[V1ContainerPort]
- env_vars 已从字典迁移到列表【v1 env var】
- 资源已经从 Dict 迁移到 V1ResourceRequirements
- 资源已经从 Dict 迁移到 V1ResourceRequirements
- …点击此处查看变更的完整列表
那是我的第三课。你不仅需要一个 DAG 工厂,还需要一个 Operator 工厂。
迁移之后,我们构建了自己的操作符工厂。如果 KubernetesPodOperator 再次发生变化,我们现在已经做好了准备。下一次改变将在一个文件中引入**,而不是在 10 个不同的文件中。**
4.动态 Dag 和 OOP 是不够的
现在你知道我们喜欢动态 DAGs 和 OOP,让我告诉你另一件事。一切都很好,直到我们开始发展和采用新的用例。我们意识到动态 Dag 和 OOP 不足以解决我们的问题。
我们意识到**我们构建了紧密耦合的模块。我们做得太差了,以至于我们的 DAG 工厂只有在包含两种特定类型的任务时才会生成 DAG。这两种类型是提取和转换。我们有一个用例,我们想要生成一个只包含提取任务的 DAG。我们不能这么做,因为我们的 DAG 工厂不允许。我们期望包括提取和转换任务。**
这是我的第四课。你必须小心你如何概括和抽象事物。你不能只是在生活中到处扔随机的概括和抽象。
我们解决代码紧密性的方法是使用 软件设计模式 **。**DAG 工厂和 Operator 工厂遵循工厂方法模式。这是最广为人知的设计模式之一,但是你应该知道还有更多的!我们还发现遵循策略模式和模板模式非常有用。
结论
我知道我在这篇文章中所做的一些陈述可能会很强烈并引起争议。请让我知道你对它的想法!
小心我在文章中建议的原则。不要把事情过度概括,过度工程化!
“复制远比错误的抽象便宜”桑迪·梅斯
感谢阅读!
最后,感谢胡安·费利佩·戈麦斯让这一切成为可能。
**更新:**本文的第二部分现已推出
如果你想随时更新我的作品, 请加入我的 简讯 ! 偶尔,我会和我的读者分享一些东西。如果你加入我会很感激的:)
数据工程师不应该写气流图——第二部分
阿帕奇气流的框架建议
理查德·霍瓦特在 Unsplash 上的照片
这是关于为什么数据工程师不应该写气流 Dag的第二篇文章。在这篇新文章中,我们将介绍一个针对 Apache 气流的框架 提案**。**
本文旨在阐明构建框架如何帮助您解决一些与 DAG 编写相关的问题。
在这篇新文章中,我将对第一部分做一个简短的回顾。所以,没必要看。尽管如此,如果你想对我在这一篇中要阐述的东西有更详细的解释,你应该考虑读一读。
[## 数据工程师不应该写气流图——第 1 部分
towardsdatascience.com](/data-engineers-shouldnt-write-airflow-dags-b885d57737ce)
为什么数据工程师不应该写 Dag
正如我在第一篇文章中提到的,数据工程师的工作不是编写 ETL。数据工程师的工作是编写可靠的、可伸缩的、可维护的代码。
数据工程师不应该为了写 Dag 而写 Dag。如果数据工程师专注于概括和抽象事物,而不是编写简单的 Dag,他们的技能可以得到更好的利用。
DAG 写入有两个主要问题:
- 这是一个重复的过程。违反了干 ( 不重复自己)的原则。如果处理不当,最终会产生大量重复且不可维护的代码。
- 对于那些没有专业知识的人来说,这可能很难做到。当这种情况发生时,数据工程师就成了为其他人写 Dag 的人。这不一定是坏事,但我们可以做得更好。
我相信你可以遵循几个原则来缓解这两个主要问题:
- 尽可能使用动态 Dag来生成你的 Dag。坚持干原则是个好办法。
- 通过使用面向对象编程(OOP)和设计模式来改进您生成动态 Dag 的方式。如果处理得当,它可以提高代码的可维护性。
- 构建允许人们与他们的 Dag 交互的界面。作为一名数据工程师,你的工作不是为别人写 Dag。你的工作是授权给人们,让他们可以写自己的 Dag 并与他们互动。
这些原则帮助我们解决了上述问题。我们用它们建立了一个处于早期阶段的框架。但是,它被证明是有用的。
在下一节中,我们将介绍我们的框架提案,称为 Castor — ,在西班牙语中代表 beaver 。我们希望这个框架能够为我们如何更好地使用 Apache Airflow 提供一些启示。
该框架允许使用一种更为 的声明性 方法来定义数据管道。而不是由 DAG 编写强制执行的命令式方法。我们相信声明式数据管道是数据管道的未来。
castor:Apache 气流的框架提案
想象一下,编写 DAG 就像编写一个简单的配置文件一样简单。该配置文件将为您做一切。你只需要指定你想做的事情,剩下的事情会由其他的事情来处理。
这就是我们在编写框架时试图实现的目标, Castor 。我们希望简化 DAG 的编写,这样就像编写配置文件一样简单。但是,我们也想解决这两篇文章中已经提到的问题。
为此,我们结合了动态 Dag、OOP 和软件设计模式,并构建了 Castor 。我们通过构建和使用该框架获得的一些好处是:
- 它帮助我们标准化了使用 Dag 的方式。因此,团队中的每个人都在同一页上。因为每个人都知道框架,所以移交很容易完成。当你不得不把一个进程交给别人的时候,你传递配置文件,就是这样。配置文件比 DAG 代码更容易阅读和理解。
- 几乎所有的 Dag 都是由相同的代码行生成的。因此,如果我们想引入一个变化,我们在一个文件中做,这适用于项目的其余部分。我们不必在 10 或 20 个文件中做同样的更改。
- 我们使用设计模式来获得某种程度的代码解耦,这让我们感到安全。引入新功能现在更容易了。就像贬低他们一样。
- 因为编写 DAG 就像编写配置文件一样简单,所以几乎任何人都可以做到。通过这种方式,我们使数据分析师和数据科学家能够编写他们自己的 Dag,而不必沾染 Airflow 编程风格。
我们的框架包括 5 个组件:配置文件、DAG 工厂、任务创建器、任务策略和操作符工厂。
配置文件
配置文件是生成 Dag 的方式。你基本上指定你想在你的 DAG 中是什么,就是这样。
以一个有 5 个任务的简单 DAG 为例。这两个任务中的两个是虚拟操作员用开始任务和结束任务使 DAG 看起来漂亮。其他 3 个任务就是 PythonOperators 做你想做的任何事情——数据提取、数据转换等等。这是它在 Airflow UI 上的样子。
来自 Airflow UI 的 DAG 示例—作者制作的插图。
如果您想采用传统的方法,您可以为 DAG 编写代码,仅此而已。但是,如果您使用更具声明性的方法,这就是使用 YAML 配置文件的样子:
接口获取配置文件,并将其传递给框架的其他组件。此类组件根据您的请求获取文件并构建 DAG。
达格工厂
DAG 工厂只是工厂方法模式的一个实现。
DAG 工厂的责任不仅仅是创建 DAG。但是,要确保 Dag 的任务是根据配置文件中声明的依赖关系正确创建的。为此,它使用了 任务创建器 。
代码看起来是这样的
任务创建者和任务策略
这是魔法开始的地方。任务创建者和任务策略是策略模式的实现。
如果你对策略模式一无所知,这里有它的 UML 图。
战略模式 UML 图—作者基于[ 1 ]所做的图解
基本上,你有一个接口(策略)来声明子类应该实现什么。然后,一个上下文类通过接口与这些子类进行交互。
这是一个有趣的模式,因为您用组合代替了继承。此外,它遵循开闭原理。因此,你可以添加新的策略,而不必改变*的背景。*如果你想了解更多关于这个图案的信息,请查看这个以获取更多信息。
在 Castor 的上下文中,我们使用策略模式来创建任务。创建气流任务的方法之一是使用气流操作符。所以,按照这种模式,你基本上有尽可能多的策略和你想使用的操作符。
首先,我们只实现了两个策略:python operator strategy和 dummy operator strategy。这就是 UML 图的样子。**
策略模式的 Castor 实现——作者举例说明
这里的要点是你应该** **编码你想使用的策略,然后忘记它们。你不必在生活中手动创建另一个气流任务。
操作员工厂
最后,我们有操作符工厂。这是工厂方法模式的另一个实现。我个人喜欢 Operator Factory,因为在从 Airflow 1.10 迁移到 2.0 的过程中,我没有一个这样的工厂。
很简单。如果你在你的项目中到处使用气流操作符,如果操作符改变了,你注定要对项目做很多改变。
让我告诉你它看起来怎么样,因为我们已经做到了。我们的项目中有很多使用 KubertenesPodOperators 的文件。假设有 10 到 20 个文件。
在我们迁移到 2.0 之后,我们意识到 KubernetesPodOperator 发生了变化。以下是一些改变了的东西:
- 端口已经从列表[Port]迁移到列表[V1ContainerPort]
- env_vars 已从字典迁移到列表[V1EnvVar]
- 资源已经从 Dict 迁移到 V1ResourceRequirements
- 资源已经从 Dict 迁移到 V1ResourceRequirements
- …点击此处查看变更的完整列表
迁移之后,一切都失败了。几个小时后,我们意识到这个问题与引入到 KubernetesPodOperator 中的变化有关。所以,我们修好了。但是,我们必须对使用 KubernetesPodOperator 的 20 个文件进行同样的修改。
这时我们意识到我们应该实现一个操作符工厂。我们将所有与气流操作员的互动都集中在那里。因此,如果想要与气流操作符交互,我们可以通过操作符工厂来实现。此外,如果我们必须引入变化,我们只在工厂里做,仅此而已。
实现非常简单。这是代码。
最后的想法
在本文中,我们介绍了一个框架提案被称为Castor。** 之所以这是一个提议,是因为这个框架还没有做好生产准备。它没有测试,是一种实验性的代码。**
如果你想看的话,这里有 Github 回购。
**https://github.com/castor-team/airflow-castor
本文的目的不是宣传我们的框架。我们的目标是揭示如何更好地使用 Apache Airflow。在这种情况下,我们提倡使用更多的声明性数据管道,因为我们相信它们是数据管道的未来。
再一次,我想知道更多关于你的想法。
感谢阅读!
特别感谢胡安·费利佩·戈麦斯让这一切成为可能。**
如果你想随时更新我的作品, 请加入我的 通迅 !偶尔,我会和我的读者分享一些东西。如果你加入我会很感激的:)
数据探索+谷歌地球引擎作为我的本科论文
工程物理毕业前的最后一个项目总结
美国宇航局在 Unsplash 拍摄的照片
放弃
谷歌地球引擎没有赞助这个。我所想要的是给出我为我的本科论文项目所做的总体想法,并展示一些数据可视化。
介绍
我喜欢好奇,在不同的现象中寻找模式,并使用视觉来分享(并获得)知识或强调相关信息。(对我来说)数据科学领域涵盖了这些事情,不仅对重点问题产生了影响,而且有助于找到新的问题来解决。
我的本科论文题目是“Herramientas estadísticas y computacionales en imágenes satelitales de Earth Engine para la explora ción de incindios forestes**”**,从西班牙语翻译成英语是“用于野火探测的地球引擎卫星图像中的统计和计算工具”。
为什么是野火?
野火是复杂的自然现象,超越了“世界变得越来越热”,它们包括了解环境的行为;文化、社会、环境、气候和其他类型的变量。我关注的是墨西哥的尤卡坦州。
Joanne Francis 在 Unsplash 上拍摄的照片
什么是谷歌地球引擎?
谷歌地球引擎(GEE) 或地球引擎(EE) 是一个基于云的平台,拥有庞大的数据目录。它使大规模卫星图像处理能够对与森林砍伐、地表温度变化、干旱等相关的地球表面进行不同的高影响分析。GEE 还旨在帮助研究人员轻松地与其他研究人员、非营利组织和公众分享他们的工作[1]。
Google Earth Engine viahttps://earthengine.google.com官方网页截图
为了提取数据并使用 GEE 的所有功能,用户必须使用一个或两个客户端库来访问 API: JavaScript 或 Python 。在我的特例中,我使用了 GEE Python API 原因如下:
- 我对这种编程语言的掌握比其他任何语言都好。
- 使用 GEE Python API 的一个优势是,借助于该领域中使用的库,如 NumPy、Pandas、Matplotlib、Scikit-Learn、GeoPandas 等,可以轻松集成到数据科学/分析工作流中;以及 Jupyter 笔记本中的开发和文档过程。
- 一些库方便了一些 GEE 对象的操作。我用过的有: eemont 和 geemap 。两者都允许我执行各种操作,从操纵 GEE 对象到将 GEE 对象转换成熊猫。数据帧或 GeoPandas。地理数据框架对象。他们很容易得到一些变量的时间序列。
工作流程
像当今许多与数据相关的项目一样,这些阶段是:
项目的工作流程。作者制作的图表。
(主要)工具
我在整个项目中使用 Python,这里是我使用的库(在一个图像中)。
主要工具( Python 和 R )。图由作者制作。
数据
我使用了来自三个不同来源的数据集:
- 2017 年森林火灾记录:国家林业委员会提供
- 热点记录(2001–2020):由公司提供(资源管理系统的火灾信息)。
- 卫星图片收集:GEE 提供(见上图)
来自谷歌地球引擎的图片集。图由作者制作。
探索性数据分析
一幅图像胜过千言万语,所以我在下面的数据可视化中总结了第 6 章(名为探索性数据分析)。
热点聚集
在 2001 年到 2020 年间,置信水平高于 84%的高热点集中在该州的中部和东部。(公司提供的数据)
置信水平意味着观测实际上是火的置信水平。作者制作的图。
受影响的市(县)
虽然 Tekax 在 2017 年有最高的记录,但它没有最显著的受影响表面积;该市是 Tizimín 市*(国家林业发展委员会提供的数据)*
作者制作的棒棒糖剧情。
作者制作的棒棒糖剧情。
有问题的孕期
在国家森林委员会和公司数据集的帮助下,找到了野火发生率最高的月份。
作者做的条形图。
作者做的时间序列。
环境变量的时间序列
仅仅知道变量的数据分布是不够的。了解变量行为的历史以找到模式或相关时期是很重要的。
该图显示,三月、四月和五月是最热的月份;此外,2017 年是最干旱的一年(低土壤湿度和 PDSI)
作者制作的热图。
交互式地图
多亏了叶子和地图,我可以在一个互动地图中可视化数据。下图显示了 2001 年至 2019 年期间受野火影响的表面以及时间范围内的地表温度。
2001 年至 2019 年的地表温度和受野火影响的地表。由作者创建,用叶子和谷歌地球引擎数据制作的地图。
结论
Google Earth Engine 平台是一个信息丰富的工具,其开发环境(Google Earth Engine 代码编辑器)对没有高水平编程技能的用户以及通过其 Python API 在数据科学和分析领域有经验的用户来说是友好的。这一平台提供的机会不仅限于森林火灾,因为它可以涵盖不同的环境问题,如干旱、水供应、温室气体监测,甚至是社会问题,如人类住区及其如何影响生态系统。
更多信息
方法论的所有过程和对数据的探索都记录在 Jupyter 的笔记本上。这些笔记本位于 GitHub 存储库中。不幸的是,这个库是西班牙语的,但是如果你有任何问题,你可以联系我。
https://github.com/isaacarroyov/thesis_undergrad
我在做这篇论文的时候,有机会参加了火生态学协会举办的**第九届国际火生态学与管理大会,并展示了一张海报。**因此,我创建了一个 GitHub 知识库,用英语提供类似的信息。
https://github.com/isaacarroyov/2021_AFE_FireCongress09
关于我
我叫艾萨克·阿罗约,最近刚从工程物理专业毕业。我对数据科学、机器学习(尤其是无监督学习算法)及其在高影响力项目中的应用感兴趣。
你可以通过电子邮件((isaacarroyov@outlook.com)或社交媒体联系我,比如 LinkedIn (Isaac Arroyo)、insta gram(@ unisaakarroyov)或 Twitter(也可以是@ unisaakarroyov)。点击这里联系我。
参考
[1] Gorelick,n .,Hancher,m .,Dixon,m .,Ilyushchenko,s .,Thau,d .,和 Moore,R. (2017 年)。谷歌地球引擎:面向所有人的全球地理空间分析。环境遥感,202,18–27。
数据探索、理解和可视化
生成可视化效果以快速理解您的数据
卢克·切瑟在 Unsplash 上的照片
D 数据探索、理解和可视化是数据科学问题的一个重要方面。在这里,我提供了几种方法来简化这个过程。
数据探索和可视化是数据科学问题的一个重要方面。最好的可视化总是与手头的问题相关,并利用领域知识。然而,作为一名数据科学家,你会发现自己经常重复许多相同的可视化。
在这篇文章中,我生成了一系列可视化效果,您可以复制并粘贴这些效果来解决您的数据科学问题,从而简化您的工作并理解您的数据。
部分
这些部分是根据用于探索的可视化类型来划分的:
- 相关热图
- 按特征分类分布
- 二维密度图。
所有的可视化都是交互式的,这是 Plotly 的标准。
本文的数据是 scikit-learn 乳腺癌数据集。但是,如果您创建一个数据框架,其中的目标变量被列为可视化的“目标”,则您可以将这些变量应用到您的数据中。
热图
第一种方法是简单的热图,描述特征和目标变量之间的相关性。
这些关联热图包含一条实线对角线,代表每个功能与其自身的关联。这些图旨在快速识别非对角线值中显示的高度相关的特征。
按类别的特征分布
第二种方法是按类分解特征分布。有了这些分布,您可以结合行业知识来识别异常和类别分离。
Plotly 还可以选择显示一维密度图,并将其添加到密度图中。这得益于显示每个单独的实例,而不是密度图中的汇总版本。
2D 密度图
最后展示的是一个二维密度图。这些图更复杂,因为它们需要选择和显示成对特征的组合。
在提供更多信息的同时,展示每一对都扩大了产生的图形的数量。这些类似于之前的密度图,但是它们更详细地揭示了类之间的分离。
根据二维图的性质,您的问题可能需要更复杂的模型来支持有效的分类。
特征相关热图
关联热图是快速识别与其他要素高度相关的要素的好方法。这些图揭示了那些与目标变量最相关的特征,这些特征可以作为特征选择过程来选择。
数据帧的关联热图(由作者编码)
然而,更重要的是识别相关特征的极端情况。
根据要素的布局,很难快速识别高度相关的要素。但是这些相关性在特征具有来自色标的相同极端颜色的区域中是可见的。
要找什么
高度相关的特征,无论是正相关还是负相关,都会影响您的模型。这些高度依赖的特性会通过在特性集中添加冗余来影响模型有效建模数据的能力。
简单地说,它们分散了你的模型学习它需要知道的东西的注意力,因为它必须不止一次地处理相同的信息。
此外,当特征与目标变量不相关时,这些特征有可能是噪声。这些噪声变量也可能对模型的整体性能有害。
本质上,你的模型使用噪声变量没有任何好处。至少,你的模型需要学会忽略这些嘈杂的变量。当存在大量低相关性特征时,请认真考虑特征选择。
因此,在第一次视觉化之后,你已经可以指导你的下一步了。识别并消除冗余和噪声变量。
数据框架的关联热图(由作者绘制)
按类别划分的特征分布
第二种方法是按类分解特征分布。在这里,您可以开始整合行业知识并识别每个特征的异常。
例如,如果年龄是一个特征,那么负年龄就不是一个准确的值。这些情况可以从特征分布中快速识别出来。同样,行业知识可以提供每个特性的更多细节。但是,这些将更多地视情况而定。
按类的特性分布(按作者的代码)
这些图还指示应该实现什么类型的缩放。根据您计划使用的模型,这是使模型有效的关键步骤。
顺便提一下,一些模型对不同的特征尺度更有弹性。例如,基于树的模型或多或少与规模无关。但是,在许多其他情况下,缩放数据可以将指数分布转换为均匀或正态分布,并更好地符合模型预期。
重新缩放问题
许多缩放方法需要知道特征分布中的临界值,并可能导致数据泄漏。例如,最小-最大缩放器应该只适合训练数据,而不是整个数据集。当最小值或最大值在测试集中时,您已经减少了一些数据泄漏到预测过程中。
直方图具有误导性
每个分布下方显示的一维频率图有助于理解数据。乍一看,这些信息似乎是多余的,但是这些信息直接解决了以直方图或分布形式表示数据时的问题。
例如,当数据被转换成直方图时,仓的数量被指定。仓太多很难破译任何模式,仓太少会丢失数据分布。
此外,将数据表示为分布假设数据是连续的。当数据不连续时,这可能表示数据中存在错误或关于要素的重要细节。一维频率图填补了直方图失效的空白。
按类别的特征分布(按作者绘制)
二维密度图
二维密度图结合了先前密度图的各个方面和第一次可视化中的相关热图。
但是这些可视化的代价是,当组合来自多个特征的信息时,有许多配置。
此外,当比较成对的特征时,可能性的复杂性急剧上升,因为特征的每种排列都是可能的。
二维密度图(作者代码)
Plotly 通过“figure_factory”模块为二维密度可视化提供内置功能。
该功能易于实施,分为两个系列,有标记颜色和尺寸选项。同时使用颜色和大小似乎有些问题,但是定义的函数实现了这两个选项。
可视化还利用相关性来限制特征对的大小。默认情况下,我只显示与目标变量最相关的 k 个特性。然后为可视化生成所有特征对的集合。
显示两个以上维度的信息
二维可视化无法显示我们的模型可能捕捉到的更高维度的关系。但是,当局限于二维空间时,人们可以创造性地用形状和颜色来显示数据的其他方面。
在这种情况下,我利用标记的形状来表示类别,用等高线来表示频率。以更高维度表示数据可以获得更多信息,但代价是很难快速理解这些模式。
二维是一个合理的限制,这样即使有大量的信息,可视化仍然容易理解。
二维密度图(作者绘制)
包裹
这篇文章展示了几种不同的可视化方法,用于理解数据中存在的要素。
开发模型时,一切都从数据开始。因此,有效的数据理解对于设计有效的模型至关重要。这些可视化为您的数据提供了大量的洞察力,并且易于重现。
这篇文章旨在展示一个预测建模项目的几个可视化功能以及目标模式。
您可以随意复制和粘贴这些函数,以供将来使用。
如果你有兴趣阅读关于新颖的数据科学工具和理解机器学习算法的文章,可以考虑在 medium 上关注我。
如果你对我的写作感兴趣,想直接支持我,请通过以下链接订阅。这个链接确保我会收到你的会员费的一部分。
https://zjwarnes.medium.com/membership
数据析取
如何做
运动数据域(Mixamo FBX)
主页(按作者)
机器学习和深度学习模型的应用每天都在涌现,对于初学者来说,一个最重要的问题是:“从哪里开始?”作为数据科学领域的新人,mind 在诸如 NLP、计算机视觉或任何其他事物之间周旋。然而,任何 ML/DL 算法的应用都遵循相同的流程:数据提取、清理、模型训练、评估、模型选择、部署。这篇文章和其他文章没什么不同,但它是针对动画或医疗保健信息学领域的数据而策划的。
运动数据本质上是复杂的,因为它是一个分层链接的结构,就像一个图形,其中每个数据点或节点是一个关节,而到其他关节的链接或边是骨骼。骨骼和数据点的方向和位置描述了可能随着帧数的增加和捕获或模拟的对象改变其位置而变化的姿态。
为了不再浪费时间,我将从脚本本身开始。它分为几个步骤,但如果你愿意,你可以直接跳到下面 GitHub 链接中给出的脚本代码。
https://github.com/RahhulDd/FbxToNpyConverter/blob/main/fbx2npy.py
数据采集
在进入下一步之前,我建议您下载一个示例 Mixamo。fbx)文件从下面提供的链接。将此文件放入“常规”文件夹。
我还在文件夹中提供了一个样本文件来测试给定的脚本。
数据处理
首先,我们导入以下库。记住,“bpy”是一个只能由 Blender 工作台访问的 Blender 库。因此,只在 Blender 中编写脚本。
#Library Imports
import bpy
import os
import time
import sys
import json
from mathutils import Vector
import numpy as np
接下来,我们为 I/O 目录路径设置以下设置变量。
#Settings#This is the main file which loads with clear 'Scene' setting HOME_FILE_PATH = os.path.abspath('homefile.blend')
MIN_NR_FRAMES = 64
RESOLUTION = (512, 512) #Crucial joints sufficient for visualisation #FIX ME - Add more #joints if desirable for MixamRig
BASE_JOINT_NAMES = ['Head', 'Neck','RightArm', 'RightForeArm', 'RightHand', 'LeftArm', 'LeftForeArm', 'LeftHand', 'Hips', 'RightUpLeg', 'RightLeg', 'RightFoot', 'LeftUpLeg', 'LeftLeg', 'LeftFoot', ]
#Source directory where .fbx exist
SRC_DATA_DIR ='regular' #Ouput directory where .fbx to JSON dict will be stored
OUT_DATA_DIR ='fbx2json' #Final directory where NPY files will ve stored
FINAL_DIR_PATH ='json2npy'
在上面的代码片段中,我们已经设置了分辨率以及将用于数据提取的关节数量。您也可以限制帧数,使每个动画文件的帧数一致。最终处理后的数据将存储在“\json2npy”文件中。
一旦选择了基础关节名称,我们将创建一个字典来访问装备的每个元素,默认情况下命名为“MixamoRig”。
#Number of joints to be used from MixamoRig
joint_names = ['mixamorig:' + x for x in BASE_JOINT_NAMES]
首先。fbx 文件转化为 JSON 对象字典,每个字典包含每帧关节位置信息。这是通过使用下面给出的函数来完成的。
def fbx2jointDict():
#Remove 'Cube' object if exists in the scene
if bpy.data.objects.get('Cube') is not None:
cube = bpy.data.objects['Cube']
bpy.data.objects.remove(cube)
#Intensify Light Point in the scene
if bpy.data.objects.get('Light') is not None:
bpy.data.objects['Light'].data.energy = 2
bpy.data.objects['Light'].data.type = 'POINT'
#Set resolution and it's rendering percentage
bpy.data.scenes['Scene'].render.resolution_x = RESOLUTION[0]
bpy.data.scenes['Scene'].render.resolution_y = RESOLUTION[1]
bpy.data.scenes['Scene'].render.resolution_percentage = 100
#Base file for blender
bpy.ops.wm.save_as_mainfile(filepath=HOME_FILE_PATH)
#Get animation(.fbx) file paths
anims_path = os.listdir(SRC_DATA_DIR)
#Make OUT_DATA_DIR
if not os.path.exists(OUT_DATA_DIR):
os.makedirs(OUT_DATA_DIR)
for anim_name in anims_path:
anim_file_path = os.path.join(SRC_DATA_DIR,anim_name)
save_dir = os.path.join(OUT_DATA_DIR,anim_name.split('.')[0],'JointDict')
#Make save_dir
if not os.path.exists(save_dir):
os.makedirs(save_dir)
#Load HOME_FILE and .fbx file
bpy.ops.wm.read_homefile(filepath=HOME_FILE_PATH)
bpy.ops.import_scene.fbx(filepath=anim_file_path)
#End Frame Index for .fbx file
frame_end = bpy.data.actions[0].frame_range[1]
for i in range(int(frame_end)+1):
bpy.context.scene.frame_set(i)
bone_struct = bpy.data.objects['Armature'].pose.bones
armature = bpy.data.objects['Armature']out_dict = {'pose_keypoints_3d': []}
for name in joint_names:
global_location = armature.matrix_world @ bone_struct[name].matrix @ Vector((0, 0, 0))
l = [global_location[0], global_location[1], global_location[2]]
out_dict['pose_keypoints_3d'].extend(l)
save_path = os.path.join(save_dir,'%04d_keypoints.json'%i)
with open(save_path,'w') as f:
json.dump(out_dict, f)--EXPLANATION--
In the function above, first we remove pre-rendered objects like “Cube”, which is set as default when Blender is opened. Then we set the “Light” object settings to increase radiance of energy as well as type as “Point”. These objects can be access using “bpy.data.objects[name of object]” to manipulate the data related to it. Also, we have set the resolution settings by using “object.data.scenes[name of scene]” to manipulate scene rendering setting.Once it is done, we save the file as “main_file()” blend file. All the files in the directory ending with “.fbx” is listed and loaded in loop where each loop extracts the global location of Armature and it’s bones. Armature object can be used to get matrix of location in the video file and it’s pose structure for each frame and save it as a dictionary of bones and it’s location in JSON object file.
最后,使用 jointDict2npy()方法收集每个动画的每个 JSON 对象文件,将所有动画连接起来,以帧和位置的矩阵形式表示,就像图像一样。
def jointDict2npy():
json_dir = OUT_DATA_DIR
npy_dir = FINAL_DIR_PATH
if not os.path.exists(npy_dir):
os.makedirs(npy_dir)
anim_names = os.listdir(json_dir)
for anim_name in anim_names:
files_path = os.path.join(json_dir,anim_name,'jointDict')
frame_files = os.listdir(files_path)
motion = []
for frame_file in frame_files:
file_path = os.path.join(files_path,frame_file)
with open(file_path) as f:
info = json.load(f)
joint = np.array(info['pose_keypoints_3d']).reshape((-1, 3))
motion.append(joint[:15,:])
motion = np.stack(motion,axis=2)
save_path = os.path.join(npy_dir,anim_name)
if not os.path.exists(save_path):
os.makedirs(save_path)
print(save_path)
np.save(save_path+'\\'+'{i}.npy'.format(i=anim_name),motion)--EXPLANATION--
Above function saves each of the animation in the form of .npy file which consist of 3D-Data array like Tensor formatted as (NumberOfJoints, NumberOfAxes, NumberOfFrames). “.npy” is an efficient structure which saves the data encoded in binary representation. Another alternative is to save it as a compressed file using “savez_compressed()” to “.npz” files.
使用以管理员身份运行的命令提示符执行脚本。键入以下命令来执行脚本:
CMD COMMAND : blender --background -P fbx2npy.py'if __name__ == '__main__':
#Convert .fbx files to JSON dict
fbx2jointDict()
#Convert JSON dict to NPY
jointDict2npy()
处理的最终结果将看起来像下面给定的图像。这是从视频运动文件中选择的大约 5 帧。您可以使用“visualise_frame.py”文件来显示以下示例数据的结果。
已处理的视频帧(按作者)
结论
在这篇文章中,我们学习了如何处理动画数据。fbx 格式来获取关于每帧每个关节位置的数据。在野外有许多应用需要运动数据来学习任务,如姿态估计、运动重定目标等。在下一篇文章中,我将分享如何将这种类型的数据标准化,以便深度学习模型可以使用它。在那之前,再见,朋友们!!!
使用通用数据集保持数据工厂整洁
如何在 Azure 数据工厂中为 Blob 存储和 SQL DB 创建通用的、可重用的数据集
你有没有遇到过 Azure 数据工厂设置有一英里长的数据集列表,因为每个数据集都是为一个管道而创建的?我确实有。在本文中,我将向您展示如何创建通用的、可重用的数据集来保持工厂整洁。
本文组织如下:
- 如何为 Blob 存储创建通用数据集
- 如何为 SQL 数据库创建通用数据集
- 用法示例
请参见我的注释中的常见问题: 1) 您可能需要为某个字段设置 None 值,当其他字段没有值时,该字段是不可见的, 2) 找到字段的动态内容编辑器可能很棘手,以及 3) 如何在管道属性中包含特殊字符,如\t 或\n(制表符或换行符)。
1.如何为 Blob 存储创建通用数据集
为了创建一个通用的、可重用的 Blob 存储数据集,我们将像往常一样创建一个数据集,并给它一个描述性的名称。这里我将我的数据集命名为 miiastorage_delimitedtext,其中 miiastorage 是我的存储帐户,delimitedtext 是指我为数据集选择的格式类型。
创建后初始数据集属性的屏幕截图。
接下来,我们将为我们希望在使用该数据集时能够动态设置的每个设置创建一个参数。在这里,我决定参数化一切,但你可能总是有相同的编码等。除了容器和路径之外,我已经给了所有设置默认值,因为无论如何在使用它们的时候它们都不能为空。
显示数据集参数的屏幕截图。除了容器和路径之外,其他都有一个默认值,因为几乎每次引用该数据集时,这些值都会发生变化。行分隔符参数默认值似乎没有设置,但它是在 json 代码中设置的,我将在本文后面介绍。
然后,我们设置带有动态内容的数据集属性来引用这些参数。
显示属性设置的屏幕截图,其中每个属性都用数据集参数的动态内容引用来定义。
注 1 :当压缩类型为无时,压缩级别必须设置为无。使用基本属性时,压缩级别默认为无,压缩级别不可见(= 无)。
注 2 :寻找动态内容链接有时很棘手。这里有两个流程可以帮你找到方向。
当编辑框可见时,如何为数据工厂中的下拉菜单设置动态内容的示例流程。步骤 1 是下拉菜单的初始视图。当编辑复选框被选中时,下拉列表变为文本框(步骤 2),当文本框被激活时,动态内容链接出现(步骤 3)。第 4 步展示了动态内容设置后的样子。
当编辑框不可见时,如何为数据工厂中的下拉菜单设置动态内容的示例流程。步骤 1 是下拉菜单的初始视图。单击下拉菜单两次以打开和关闭它(步骤 2)。菜单关闭时会出现动态内容链接(步骤 3)。第 4 步展示了动态内容设置后的样子。
注 3 :数据工厂编辑器对特殊字符如\t (tab)和\n(换行符)进行转义。这意味着,当您在编辑器中的文本字段中键入\n 时,它实际上会\n 并中断您的管道。要添加这些字符,你可以尝试遵循 Azure 的提示,从文本编辑器中复制粘贴,或者你可以通过 json 代码编辑器添加你的特殊字符。
显示列和行分隔符字段如何具有特殊字符(如制表符或换行符)将被编辑器转义的额外信息的屏幕截图。Azure 建议您从文本编辑器中复制并粘贴所需的字符。
数据工厂截图,json 代码编辑器可以从右上角进入。
数据工厂 json 代码编辑器截图。在第 28 行,我已经将换行符的默认值定义为\n。
2.如何为 SQL 数据库创建通用数据集
然后是 SQL 数据库数据集。让我们像往常一样从创建数据集开始。同样,我们希望尽可能通用地命名它,不需要一开始就为它定义任何表。
在没有定义表的情况下创建 Azure SQL 数据库数据集属性后的屏幕截图。
接下来,我们检查“Edit”框,它将“Table”输入字段扩展为两个字段,一个用于模式,一个用于表。这允许我们添加动态内容,通过它我们可以引用数据集参数。
Azure SQL 数据库数据集属性的屏幕截图。选中“编辑”复选框,将“表名”字段展开为单独的“模式”和“表名”字段,以允许添加动态内容。
然后,我们为这个数据集定义参数。我们需要的唯一参数是“模式名”和“表名”。我没有定义任何缺省值,因为这些参数经常在用例之间变化。
架构和表名的 Azure SQL 数据库数据集参数的屏幕截图。通常,不需要缺省值,因为这些参数在用例之间经常变化。
最后,我们在动态内容中添加对这些参数的引用,这样就完成了。
Azure SQL 数据库数据集属性的屏幕截图,其中架构和表名称是动态设置的。
3.用法示例
让我们创建一个简单的管道来演示用法。管道包含复制活动,该活动将 CSV 文件的内容从 blob 存储复制到 SQL 数据库。
对于源代码,我们只需要定义容器和路径参数,因为我的默认参数对这个文件很好。
带有源数据集示例设置的屏幕截图。
对于接收器,我们只需要填充模式和表名字段。
包含接收器数据集示例设置的屏幕截图。
现在我们可以调试我们的管道了。该表将被创建到我的数据库中,其结构与我的存储帐户中的 CSV 文件相同,因为我选择了“自动创建表”。
调试运行成功后数据工厂视图的屏幕截图。
该屏幕截图显示了我的数据库中的简单 SELECT *查询,以展示现在已经创建了表并传输了数据。
感谢您的阅读!如果你学到了新的东西或者喜欢这篇文章,在 Medium 上关注我。我发表关于数据工程和数据科学的文章。你可以从 be 网页了解更多关于我的信息。
用我没有提到的连接器来实现这一点,你会有困难吗?请在评论中告诉我,我会尽力帮助你😊
干旱预报系统的数据
变更数据
应用数据科学和分析应对全球变暖引发的环境挑战。具有真实世界降雨数据的端到端项目
“数据为善是一场运动,在这场运动中,人们和组织超越边界,使用数据科学和人工智能来应对当今紧迫的挑战,以改善社会。”
作者照片。
目录
- 介绍性故事
- 输入数据准备
- 探索性数据分析
- 特征工程
- 型号选择
- 政策建议
- 参考
介绍性故事
花点时间想象以下场景。有一天,你被任命为索马里人道主义和灾害管理部的高级顾问,该政府机构负责处理全国范围的紧急情况。你被纯粹的快乐所感动,并且想要更新你的 LinkedIn 个人资料、Twitter 时间表和你的其他平台。即使你不知道你是怎么被选中的。
你注意到录取通知书附带了几十份令人印象深刻的文件。转眼间,当你阅读非政府组织的报告、评估和以前 PDF 简报中的咨询文件时,你意识到你正坐在职业地雷上。因为挑战不可能变得更难了。
尽管被宣布为失败的国家,索马里几十年来一直试图重新站立起来。内战高峰期出现的恐怖组织“青年党”正在发动持续的叛乱。迄今为止,它们几乎每周都在继续肆虐。此外,索马里面临着重要的体制和国家建设任务。健康的经济、政治气候和利益相关者之间的普遍信任水平都依赖于它们的充分解决。这些只是近年来这个饱受战争蹂躏的国家面临的众多挑战中的几个。根据您询问的对象和他们认为的优先事项,挑战列表可能会有所不同。
回到我们假设的例子,记住给你工作的部门希望你解决其中一个问题:即索马里的干旱问题。
我在这篇文章中的目标是帮助你找到这些解决方案,以便索马里的干旱情况在未来可以得到更好的处理。利用数据科学,我们将设计一个干旱预警系统。它意味着分析相关数据,形成建模方法,并根据收集的数据提出管理方案。
输入数据准备
那么,我们从哪里开始?像往常一样,谷歌来拯救我们。幸运的是,寻找索马里的降雨量数据并不难,尽管这并不令人愉快。在经历了一些挫折之后,我发现 http://www.tamsat.org.uk/的 TAMSAT 似乎是唯一一致的、容易获取的、免费的索马里降雨数据来源。它实际上为整个非洲提供了基于卫星的降雨量估计——可配置到每日粒度和 4 公里半径分辨率。在指定地理位置、所需的粒度和分析时间段后,您将收到一个下载链接,其中包含一个 CSV 或 NETCDF 文件。让我们在使用熊猫图书馆中读到它。
表 1:索马里 1983 年至 2021 年的 TAMSAT 每日粒度数据。作者照片。
观察粒度为每日,度量单位为毫米(缩写为 mm)。一毫米的降雨量相当于每平方米一升水。
我们端到端项目的下一步涉及编写一个数据处理函数。我们的目标是将每日数据向上采样(提升一个粒度级别)到每周一次,并生成一些可能有用的时间序列特征。“我们为什么要这么做?”你可能会想。在数据建模阶段,从我们的原始输入数据中提取这些特征迟早会派上用场。
表 2:基本时间特征。作者照片。
探索性数据分析
必须记住的是,任何严肃的数据项目都是从探索性分析开始的。说实话,这是一个人跳到任何造型形式之前的踏脚石。在这方面,我们可以从备受尊敬的统计学先驱约翰·图基那里汲取深刻的智慧,他曾经创造了一个恰当的短语。作为他 1977 年的开创性著作《探索性数据分析》的一部分,他写道:“探索性数据分析永远不可能是故事的全部,但其他任何东西都不能作为基石。”这就是为什么我们首先只研究索马里的降雨量数据。
图 1:1983-2021 年月降雨量的时间序列可视化。作者照片。
当雨季没有到来时,我们就说发生了干旱。毫无疑问,这是一种以极度匮乏为特征的局面。从上面的时间序列图中可以看出,索马里一直是,而不是不由自主地,最受欢迎的目的地之一。事实上,从 1983 年开始一直到 2021 年的图表中可以明显看出,索马里遭受了频繁的干旱。
此外,为了给可视化技术提供更多的背景信息,值得一提的是蓝线——在零点和 200 毫米最大值之间摆动——代表索马里的月降雨量。而红色虚线表示为分析目的而生成的聚合度量。这是整个研究期间的平均月降雨量,纯粹是识别蓝线间隙的直观助手。参见下面的代码:
查看这段代码,您会发现两个值得注意的地方:1)我使用了 Pandas transform 将聚合数据与分类数据结合起来,2)我创建了一个名为“干旱”的新变量。让我解释一下我的理由。
任何分析索马里干旱问题的人都会面临的第一个问题是:“在索马里的气候和地理背景下,什么是真正的干旱?”根据科彭气候分类,索马里分为两类。第一种是沙漠气候,第二种是温暖的半干旱气候。总共有四个季节,其中两个通常是雨季。
如果不是气候变化带来了更频繁的极端天气状况和干旱,索马里将定期享受 4 月至 6 月的 Gu(春季)雨季和 10 月至 12 月的 Deyr(秋季)雨季。
图 2:按月份、季度和年份划分的平均/累计降雨量的水平条形图。作者照片。
如上图所示,我们可以清楚地看到这些图案。平均而言,4 月/5 月和 10 月/11 月的降雨量比一年中的其他时间要多得多。但这并不是人们可以推断的全部。特别令人吃惊的是第三个也是最后一个条形图中的 1997 年,这是整个 38 年期间的最高峰。它的特点是降雨量超过 600 毫米。
在丰年,索马里通常会有 400-600 毫米的降雨量。然而,这似乎已经成为一种相当罕见的现象:38 年中只有 7 年拥有这样的数量!另一个引人注目的现象是 2017 年的下降,这是索马里历史上最糟糕的一年,最终导致人道主义危机和饥荒。幸运的是,它获得了足够的国际关注和救济资金,防止了急性营养不良升级为大范围的饥饿和死亡。
考虑到长时间的雨水不足会造成如此多的困难,人们不禁要问各国能对此做些什么。这就是为什么我创造了布尔变量“干旱”,以建立一个预测干旱发生的模型。我使用的逻辑非常简单,从最后一段代码中可以明显看出。
我首先生成了一个名为“Rain_Season”的中间列,当日期列显示为四月、五月、六月或十月、十一月、十二月时,根据正常情况下应该发生的两个雨季,该列的值为 1。然后,每次降雨量低于平均水平且“Rain_Season”为 1 时,“干旱”列将为 1,这是干旱发生的布尔代码。虽然这听起来很有道理,但我想承认,如果我的决定是由气象专家提供的话,那会好得多,因为他们确切知道阈值应该是多少毫米的降雨量。理想情况下位于地区级别。
但无论如何,现在让我们转向探索性分析的另一个重要角度。回答我提出的关于国家可以做什么的问题,我们最好使用统计学的概念。其中一个概念是自相关:过去的模式如何解释现在的现实。为此,我们从统计 Python 库 Statsmodels 导入了两个方便的函数。
图 3:自相关图。作者照片。
直观地观察索马里每周降雨量的自相关函数是有用的,因为它使我们能够理解过去和现在是如何交织在一起的。在这种情况下,它的形状以一条反指数曲线为特征,这意味着降雨量的未来值与其过去值适度相关,而相关性的强度随着我们考虑的滞后次数而降低。
然而,检查偏自相关函数,我们只看到降雨量与第一和第二滞后有很强的相关性。对于那些不熟悉时间序列计量经济学概念的人来说,这只是意味着过去的趋势在很大程度上解释了目前观察到的现实。这也意味着未来的降雨量取决于现在的降雨量。
特征工程
现在进入端到端项目的下一阶段,我们将把精力转向特性工程的主题。尽管有时被淡化为一项高强度低产出的活动,但对这一极其关键的步骤的普遍定义是:“从原始输入数据中准备、转换和提取有用的信息。”事实上,我们应该清楚地记得,这个领域的一位圣人曾经用语言描述了下面的话,强烈地强调了特征工程的重要性。
你使用的特性比其他任何东西都更能影响结果。据我所知,没有任何算法可以单独补充正确的特征工程所提供的信息增益。
—卢卡·马萨隆
所以,让我们按照这个聪明的金玉良言行动吧。基于我们从自相关分析中获得的过去解释未来的知识,现在让我们提取一些额外的时间序列特征。我决定提取的降雨滞后值代表前几周的降雨量,存储在每个时间点 t 的单独列中。这肯定会提高我们在后期建模阶段的干旱预测准确性。
我们的决赛表如下所示:
表 3:高级时间序列特性。作者照片。
明眼人无疑会注意到,我们的数据表看起来与我们开始时的原始数据有些不同。不过请放心,我没有诉诸一些非法的黑魔法,现在会给我想要的结果(许多数据怀疑论者会对你提出指控)。
我刚刚将原始的时间序列数据转换成一种适合监督机器学习的形式。换句话说,假设一个时间序列只不过是一系列具有时间维度的数据点,那么算法预测所需要确保的就是我们有一个时间变量来捕捉这个序列的节奏。
在我们的例子中,它是每周节奏,因此在日期时间索引的背景下,查看变量“Time_t”就足以让我们知道我们仍然在查看相同的每周时间序列数据。然而,在这个阶段,我们在数字和布尔变量的组合中捕获了更多的细节。“这对干旱紧急预测有什么帮助?”你可能在想。看看下面的特性重要性图会让事情变得更清楚。
图 4:皮尔逊特征重要度图。作者照片。
为了指出从情节中可以推断出什么,我们可以宣布几件毫不奇怪的事情。首先,春季或秋季的季节性,正如人们明显预料的那样,与干旱的发生或不发生高度相关。因此,当布尔雨季变量等于 1 时,我们很有可能观测不到降雨。这是因为索马里最近的天气历史倾向于突出干旱。其次,当在一个正常的雨季中观察到的平均降雨量(之前的红色虚线)低于实际记录的量(即,“Avg _ rain _ Diff”为正)时,我们很可能会遇到相反的情况:降雨!这就是为什么那个变量有接近 50%的负相关系数。相当直观。
由此得出的结论是,这些特征与我们想要预测的目标在令人满意的程度上相关。这里还有一件重要的事情。看看我们的滞后自相关特征。根据他们的说法,干旱迫在眉睫的最有指示性的迹象是雨季开始后 4 周过去了,还没有降雨记录。虽然有趣的是,我们注意到,4 周的滞后是与干旱最密切相关的,但我们必须记住,这种相关性并不意味着因果关系。
除此之外,不仅要检查特征和目标之间的相关性,还要检查特征本身之间的相关性,这是一个很好的实践。因为在有些情况下,变量之间强烈的负相关或正相关会妨碍模型的预测能力。在下面的图表中,让我们尝试确定我们是否受到这种现象的影响,这种现象在统计学领域被称为多重共线性。任何高于 80%的皮尔逊相关都是有问题的。
图 5:皮尔逊相关热图。作者照片。
与之前的垂直条形图不同,这张图有点难以阅读。但幸运的是,我们有颜色编码,这使我们能够很容易地发现强烈相关的特征。与第一列相邻,左上角的象限看起来很可疑。在那里,我们可以识别出表现出强相互相关性的变量对。它们是“Weeknum”、“Quarter”和“Month”。
从我们的输入数据中删除其中两个不会损害我们预测干旱的能力,因为它们的信息增益相当微不足道,因为它们包含相同的季节性信息。这就好像你在同一层级的会议中有两个人,他们拥有相同数量的信息。其中一个在会议中并不真正需要,因为另一个足以报告他们所拥有的信息。
型号选择
在最终开始我们预测干旱和选择数据科学模型的最初目标之前,我们必须将数据分成训练集和测试集。请记住,我们还必须删除我们在上一步中确定的冗余功能。从截图中可以看出,我选择了 2015-21 年的动荡期作为测试集,以确定该模型是否能准确预测关键时间段。在测试集中,干旱的发生稍微少一些,纯粹是因为时间范围比训练时间周期短得多。
作者照片。
图 6:训练与测试分布图。作者照片。
逻辑回归
鉴于我们的探索性分析揭示了特征-目标关系中的强线性,采用逻辑回归方法来预测索马里的干旱是明智的。下面的代码片段和结果说明了一个简单的逻辑模型足以让我们获得好的结果。
作者照片。
从各方面考虑,结果看起来很有希望。我们在测试集上取得了 92%的预测准确率。这意味着历史降雨量数据足以让任何国家设计一个基于数据科学的干旱管理系统。此外,想象一下我们有更详细、更可靠的地理信息数据,如经度、纬度、降雨区等。我知道我提到过 TAMSAT 有非洲的数据,但是我发现索马里的数据在地理信息方面并不可靠。有些坐标实际上位于邻国肯尼亚和埃塞俄比亚。
图 7:混淆矩阵图。作者照片。
但是,等等,准确性应该是唯一要报告的性能指标吗?不,实际上,你应该始终怀疑那些只交流准确性的数据科学家,尤其是当目标变量不平衡时(一个类别远远超过另一个类别)。对于这个特殊的用例,逻辑回归模型实际上犯了一些严重的错误:假阴性。看右上象限,你可以看到有 8 个实例,大约测试集中 3%的数据点,模型预测没有干旱,即使那些周是干旱的。一般来说,假阴性在许多应用中是相当危险的,例如新冠肺炎预测。相当于宣布一个病人没有病毒,而实际上他们是病毒携带者。不管是哪种情况,我认为我们已经尽了最大的努力来处理现有的数据。
政策建议
技术世界的当前趋势一次又一次地证明了一件事。他们证明了数据具有改变的力量。因此,无论是发达国家还是发展中国家的政府,都必须善用数据。不过,提醒一句。为了不使这篇文章比现在更长,我将简明扼要地总结这些政策建议。
- a)索马里需要建立一个拥有最新设备的气象研究所,以观察干旱周期等天气现象。这将丰富全球组织基于卫星的数据,并使数据驱动的干旱预测任务变得容易得多。最终,这样的努力将最终形成一个干旱管理系统,当某些地区处于人道主义灾难的边缘时,该系统将发出黄色或红色警报。
- b)索马里需要利用其强大的口头传统和人民的集体记忆来记录干旱的历史、地点、生命和牲畜损失方面的影响及其持续时间。通过根据频率、严重程度和持续时间将干旱分为不同级别来提升数据质量是非常重要的。
- c)索马里必须尽一切可能解决极端天气状况的原因。非法木炭生产、过度放牧、商业卡特尔不负责任的用水,所有这些发展都需要受到抑制。事实上,除非目前的森林砍伐速度被遏制,否则情况不会很快好转——即使有数据科学的能力。
- d)索马里应该与国际水技术专家合作,这些专家目前在开发雨水收集和保护系统方面处于世界领先地位。落下的少量雨水往往会在山洪暴发和无人看管的乡村景观中消失。在与饥荒的斗争中,可以做更多的事情来利用这一点。
非常感谢阅读。
参考
- 如何在 Python 中将一个时间序列转化为一个监督学习问题?https://machine learning mastery . com/convert-time-series-supervised-learning-problem-python/
- 数据为善:一场新的社会运动https://www . apexofinnovation . com/data-for-Good-A-New-Social-Movement/
- 罗伯特李哈登 2007 年索马里地质。
- 以色列水务专家帮助世界的 10 种方式https://www . Israel 21 c . org/10-ways-Israel-water-expertise-is-help-the-world/
- 机器学习的特征工程基础技术https://towards data science . com/Feature-Engineering-for-Machine-Learning-3a5e 293 a 5114
- 快速实时审查 2018 年索马里干旱反应,马克·杜布瓦、保罗·哈维和格林·泰勒。
- 使用卫星图像时间序列对陆地生态系统的近实时干扰探测:2011 年索马里的干旱探测。
- 基于 SPEI 的《2020 年索马里干旱的时空评估》, Sylus Kipnegeno,Justine Muhoro Nyaga,Abdi Zeila Dubow。
- 约翰·图基探索性数据分析,1977 年。
福祉数据:认知的范例?
变更数据
个人必须能够理解他们的选择的含义,以便为他们的数字生活做出好的决定
数字化转型因其对进步和发展的益处而受到全球称赞。任何数字化转型组织的核心都是数据,每个人都可以安全地访问这些数据,以开发更好的产品、客户体验或收集更深入的业务见解。
将数据置于日常决策的中心需要改变个人技能和态度、组织结构、政策以及各方之间的关系。这些考虑突出了人类行为的问题,因为不同的社会和社会中的人们对数据驱动的信息技术手段会有不同的看法,但理想情况下,每个人都应该能够自由地做出符合他们自己对福祉的定义的知情选择。
福祉数据
如今,人们的数据不再是公共资产;它越来越多地被私人资助、收集和分析。政府机构、企业和个人之间也有一个广泛的共识,即数字技术、数据和人工智能应该有助于改善人类福利。然而,考虑到围绕个人数据披露和个人福祉之间权衡的辩论,所有利益相关者都必须事先承认数字技术、数据和人工智能可能会产生负面后果。
对一些人来说,大量收集和分享个人数据会降低个人福祉,因为这侵犯了隐私权。除此之外,如何处理和使用一个人的数据可能是更大的问题,因为围绕有针对性的广告、政治竞选甚至虚假信息的不安情绪越来越多。
作为被命名为“数字人道主义”(Meier,2015) [1]或“大数据促进发展”(Hilbert,2016) [2]的倡议的一部分,magal hes 和 Couldry (2021) [3]指出,积极的福祉成果可以来自“数据化”,即将生活的更多方面转换为数字数据,用于算法挖掘和半自动决策。
本文探讨了正在进行的数据管理工作是否以及如何假设个人意识到个人数据的披露和处理所带来的影响。
数据共享中同意的含义
有些情况下,共享信息的选择是由社会、社会的代表为了个人的“利益”而做出的。在使用速度限制、建筑物中危险材料的限制、获取武器方面——这些规定是由社会话语推动的,或者在某些情况下,是为了公民的利益而单方面颁布的法令。制定这些规则是基于这样一种假设,即每个人对这些限制的好处都有一定程度的认识。
GDPR 在这方面取得了长足进步,要求数据使用必须得到明确同意。然而,在没有验证用户对潜在影响的理解的情况下,我们质疑这样的法规是否为公司而不是消费者提供了法律保护。
先驱行为经济学家 Cass Sunstein 支持这一观点,他在最近的一本书中思考信息披露是否有助于改善人类福祉[4]。人们希望从组织获得服务或利益,他们同意分享他们的数据以换取这种效用——每当我们点击接受一组条款和条件时,我们都熟悉这种范式。
然而,桑斯坦认为许多同意协议是无效的;“全成本无收益”。相反,他们征收认知税——阅读和处理信息所涉及的成本——例如,让用户在参与某项交易之前阅读几页条款和条件。
当我们考虑世界各地的许多交易时,这种认知成本是显著的。通常,一个人不能完全理解他们所同意的事情,更不用说做出一个明智的决定,决定这是否对他们有利,或者如何为自己辩护。
人们普遍承认,在个人数据披露中获得同意的过程存在缺陷。例如,网站经常使用设计轻推,以便更容易接受而不是拒绝披露条款,并故意使隐私政策难以理解[5]。这阻碍了知情同意,并使这一过程更像是对合规性的粗略点头,而不是有意义的用户保护。尽管从技术上讲,用户可以获得所有相关数据来做出决策,但这也给他们带来了大量复杂冗长的信息。
对于这种要求消费者具有高认知负荷的同意程序,已经有了一些法规响应。例如,GDPR 规定,平台不能让用户默认同意被跟踪,如果这些 cookies 被消费者拒绝,也不能拒绝访问。但是,这并不能确保用户知道他们的个人数据将如何被收集和使用,也不能减少同意过程中涉及的认知税。人们仍然可以点击同意而不阅读和理解数据披露的全部条款。
健康同意
两种可能的解决方案可能会有所帮助。
首先,同意程序可能需要回答多项选择问题,以确保用户在继续之前理解这些条款。这些问题可以涵盖
i)他们的数据可以用于什么,以及
ii)他们的权利包括什么,例如擦除和访问的权利。
在此过程中,只有用户正确回答问题,同意才有效**。**这证明他们知道他们的个人数据将被如何处理。
这里提出的第二个选择是使用同意管理器。这些机制允许消费者决定向组织提供什么样的数据,以及用于什么目的。用户可以表明他们愿意披露什么,而不是让数据收集者单方面设定使用条款。同意管理的功能可以由收集数据的组织提供,也可以由在个人和数据收集者之间进行协商的第三方平台提供。
当然,个人仍然可以违背自己的最大利益,没有任何解决方案可以始终保证用户得到积极的结果。但是,尽管对福祉的定义仍将存在分歧,但每个人都应该得到有效的理解,作为为自己的数字福祉做出决定的第一步。
**参考文献:**
[1] P .迈耶(2015)。数字人道主义者。佛罗里达州博卡拉顿:CRC。
[2] M .希尔伯特(2016)。大数据促进发展:前景与挑战回顾。发展政策评论,34(1),135-174 页。doi:10.1111/12142
[3]j . c . magal hes 和 N. Couldry (2021 年)。大技术、数据殖民主义和社会公益的重新配置。国际传播杂志,15,20。
[4]桑斯坦(2020 年)。信息太多:了解自己不想知道的东西。麻省理工出版社。
[5] C. Utz,m .德格林,S. Fahl & F. Schaub ( 2019,11 月 11 日–15 日)。(联合国)知情同意:实地研究 GDPR 同意通知。在英国伦敦举行的 ACM SIGSAC 计算机和通信安全会议上。doi:[10.1145/3319535.3354212](http://dx.doi.org/10.1145/3319535.3354212)
# TensorFlow 中用于训练的数据格式:拼花地板、Petastorm、羽毛等
> 原文:<https://towardsdatascience.com/data-formats-for-training-in-tensorflow-parquet-petastorm-feather-and-more-e55179eeeb72?source=collection_archive---------11----------------------->
## [理解大数据](https://towardsdatascience.com/tagged/making-sense-of-big-data)
## 通过统一不同类型的机器学习工作负载的文件格式来简化数据管理

由[马克西姆·舒托夫](https://unsplash.com/@maksimshutov?utm_source=medium&utm_medium=referral)在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄
机器学习是关于数据的。为了成功训练一个复杂的模型,你需要一个*高质量的*训练数据集;一个足够大、标注准确并正确表示现实世界中数据样本分布的数据集。然而,适当的数据管理同样重要。通过*数据管理*,我们指的是数据存储的方式和位置、数据访问的方式以及数据在开发生命周期中经历的转换。这篇文章的重点是用于存储训练数据的*文件格式*以及它对模型训练的影响。在定义机器学习项目时,选择文件格式是您需要做出的许多重要决定之一。
这个职位由四个部分组成。在第一部分中,我们将确定一些我们希望文件格式具有的属性。在第二部分中,我们将回顾潜在的文件格式,并根据我们发现的所需属性对它们进行评估。接下来,我们将调查将这些格式流式传输到 TensorFlow 培训课程的不同选项。在最后一节中,我们将描述我们运行的一些实验,以测试其中的一些选项。
在我们开始之前,让我们先做好准备。在本帖中,我们将假设我们的训练数据集的大小需要将其存储在分布式存储系统中,例如数百 TB。在下面的例子中,我们将使用亚马逊 S3 进行数据存储,但是原则同样适用于任何其他分布式存储系统。在开发周期中,数据可能会被几个消费者访问,用于各种目的,包括数据创建、数据分析、模型训练等等。我们的重点将是 TensorFlow 中的培训,尽管我们要说的大部分内容也适用于其他培训框架。
这篇文章的基本假设是我们的数据需要一种文件格式,即我们需要一个或多个文件用于:1。将单个数据样本的所有元素/列/特征组合在一起,以及 2。将多个数据样本分组在一起。当然,人们可以设想这样的场景,其中人们可以选择将所有样本的所有元素保存在单独的文件中,并以它们的原始格式保存。然而,在许多情况下,特别是如果文件很小(例如几千字节),这种策略可能会严重降低数据访问的运行时性能。
这篇文章的目的是强调选择文件格式时一些重要的考虑因素,并讨论一些目前可用的不同选项。我们将提到许多格式以及许多软件开发框架和工具。这些提及应该*而不是*被解释为认可。适合您的选择可能基于广泛的考虑,其中一些可能超出了本讨论的范围。这篇文章将包括一些简单的代码片段。这些仅用于演示目的,不应视为最佳实施。
机器学习工具的前景是极其动态的。我们将提到的一些格式和工具将继续发展,我们将做出的一些评论可能在您阅读本文时已经过时。注意跟踪新版本和新工具的发布,并确保根据最新的可用信息做出设计决策。
请不要犹豫,与我联系,提出任何意见或纠正。
# 文件格式的期望属性
为了便于讨论,让我们来看看 TensorFlow 中用于培训的一种常见文件格式,即 *TFRecord* 格式。
## TFRecord 格式
[*TFRecord*](https://www.tensorflow.org/tutorials/load_data/tfrecord) 是一种基于[协议缓冲区](https://developers.google.com/protocol-buffers/)的格式,专门设计用于 TensorFlow。一个 *TFRecord* 文件由序列化的二进制样本序列组成。每个样本代表一个 [tf.train.Example](https://www.tensorflow.org/api_docs/python/tf/train/Example?version=nightly) ,它又代表一个字符串到值映射的字典。 *TFRecord* 格式的顺序特性有助于提高数据流吞吐量。特别是,不需要下载并打开一个完整的文件来开始遍历其内容。此外, [TensorFlow tf.data](https://www.tensorflow.org/guide/data#consuming_tfrecord_data) 模块包括高度优化的 [TFRecordDataset](https://www.tensorflow.org/api_docs/python/tf/data/TFRecordDataset) 类,用于基于 *TFRecord* 文件中存储的数据构建输入管道。然而, *TFRecord* 格式并非没有缺点。这里我们列举几个:
**单一目的**:TF record*格式不太可能满足开发管道上任何其他数据消费者的需求。开发团队通常以不同的格式维护他们的数据,并专门为培训目的以 *TFRecord* 格式创建数据的派生。存储数据的多个副本并不理想,尤其是当数据集很大时。除了数据存储的额外成本,这意味着每次核心数据集发生变化时,都需要生成一个新的 *TFRecord* 副本。我们可能希望根据培训课程的发现更新核心数据记录,在这种情况下,我们还需要维护生成的 *TFRecord* 记录与核心数据格式中相应条目之间的映射。*
**提取部分记录数据**:当我们的训练模型只需要 *TFRecord* 元素的子集时, *TFRecord* 格式出现了另一个问题。例如,假设我们有一个多头模型,它对输入图像执行不同类型的像素级分割。数据集中的每个记录包含对应于模型的多个头部的多个地面实况图像。现在我们决定训练一个只有一个头部的模型。简单的解决方案是输入完整的 *TFRecord* ,忽略不必要的字段。然而,提取和解析无关数据的需求会严重影响我们输入管道的吞吐量,从而影响我们训练的速度。为了降低管道中的瓶颈风险,我们需要创建一个额外的数据副本,其中只包含与当前特定培训相关的内容。这进一步加剧了我们上面讨论的数据重复问题。
**记录过滤**:有时我们对遍历具有特定条目值的记录感兴趣。简单的方法是遍历所有数据,简单地删除任何不匹配我们的过滤器的记录(例如,使用 [tf.filter](https://www.tensorflow.org/api_docs/python/tf/data/Dataset?version=nightly#filter) )。和以前一样,这会给数据输入管道带来相当大的开销,并导致训练循环严重不足。在之前的帖子中(这里是[这里是](https://medium.com/@julsimon/making-amazon-sagemaker-and-tensorflow-work-for-you-893365184233)和[这里是](https://medium.com/@julsimon/deep-dive-on-tensorflow-training-with-amazon-sagemaker-and-amazon-s3-12038828075c),我们展示了根据输入图像是否包含粉色汽车来过滤输入图像的需求。我们提出的解决方案是将不同的数据类存储在不同的文件中。每当需要过滤时,我们可以只遍历与过滤器相关的文件。然而,这个解决方案要求我们能够预测我们将需要应用的过滤器,这并不总是可能的。如果我们需要应用一个我们没有预料到的过滤器,我们可以用一个额外的分区重新创建数据,或者使用丢弃不匹配样本的简单方法。这两个选项都不是最优的。
**数据转换**:典型的输入数据管道可能包括对输入数据的多种操作,包括数据扭曲、扩充、批处理等等。TensorFlow 提供了一组内置的数据处理操作,可以通过 [tf.data.Dataset.map](https://www.tensorflow.org/api_docs/python/tf/data/Dataset#map) 函数添加到输入数据管道计算图中。但是,您可能会发现,使用 TensorFlow 无法高效地实现所需的数据处理。一种选择是使用 [tf.py_function](https://www.tensorflow.org/api_docs/python/tf/py_function) 应用原生 python 代码块,但是由于 [Python 全局解释器锁](https://wiki.python.org/moin/GlobalInterpreterLock) (GIL),这可能会限制您的数据吞吐量性能。许多用例要求在进入张量流计算图之前,使用一种能够在原生 python 中应用操作的格式。
## 格式要求
基于上面的讨论,让我们在我们的文件格式中编译一些我们正在寻找的属性的列表。考虑到存储我们数据的多个副本会增加成本和复杂性,我们将从现在开始限制自己只存储一个数据副本,也就是说,我们必须选择一种能够满足所有数据消费者需求的格式。该列表并不打算包含所有内容。应考虑基于特定用例的附加要求。
* **分布式存储**:文件格式和支持库必须支持在分布式存储设置中存储大型数据集的选项,如亚马逊 S3、HDFS 等。
* **软件生态系统**:我们需要一个强大的图书馆生态系统,为分析和操作数据提供一系列工具。
* **列支持**:文件格式和支持库必须支持有效提取每个数据样本的特征子集。
* **行过滤**:文件格式和支持库应支持对样本特征值的高效过滤。
* **TensorFlow 集成**:格式必须有助于数据从存储器高效地流入 TensorFlow 培训课程。
我们在讨论中忽略的一个培训需求是**数据洗牌**。通常的做法是在每次遍历(历元)之前混洗训练数据。如果我们能够随机访问数据集中的任何样本,数据重组就很容易了。然而,这种对单个样本的随机访问是以牺牲性能为代价的,尤其是在分布式存储环境中。取而代之的是,人们必须求助于用于混洗的其他机制,包括以下各项的组合:在数据创建期间混洗样本、在构成完整数据集的文件列表上混洗、在多个数据集之间进行[交错](https://www.tensorflow.org/api_docs/python/tf/data/Dataset#interleave),以及在训练期间使用适当大的混洗缓冲区(例如,参见 [tf.data.Dataset.shuffle](https://www.tensorflow.org/api_docs/python/tf/data/Dataset#shuffle) )。我们选择不将混排作为文件格式的要求,因为在我们看来,在我们提出的培训场景中,这一挑战将存在于任何文件格式选择中。
在下一节中,我们将评估几种用于培训的文件格式的兼容性。在下一节中,我们将讨论将它们流式传输到 TensorFlow 的选项。
# 文件格式调查:镶木地板、花瓣和羽毛
对深度学习的数据格式的全面调查超出了本文的范围。我们将把讨论限制在几个强有力的候选人身上。更广泛的调查比比皆是。这里有一个例子:
</guide-to-file-formats-for-machine-learning-columnar-training-inferencing-and-the-feature-store-2e0c3d18d4f9>
您还可以查看我最近的一篇帖子,它涵盖了相对较新的*[*web dataset*](https://github.com/tmbdev/webdataset)*格式,这是一个有趣的解决方案,专门面向希望尽可能以最原始的形式维护数据的开发人员。**
**我们将根据我们在上面选择的指标来衡量每种格式,如下图所示,其中总结了我们对 *TFRecord* 格式的评估。我们用绿色表示完全支持,黄色表示部分支持,红色表示不支持。**
****
**TFRecord 评估**
## **阿帕奇拼花地板**
**更引人注目的文件格式选项之一是 [*Apache Parquet*](http://parquet.apache.org/) 。 *Apache Parquet* 有一个广泛的软件生态系统,它有多个框架和工具支持各种各样的数据处理操作。它在数据分析师中尤其受欢迎。将我们的培训建立在相同的形式上的可能性是很有吸引力的。**
***Parquet* 格式的成功主要归功于它是一种[列存储](http://en.wikipedia.org/wiki/Column-oriented_DBMS)格式。与 CSV 或 *TFRecord* 等其他格式相反,在列数据格式*中,数据的列*被存储在一起。数据集中的每个文件都被划分为行块,每个行块包含多个样本。在行块内,样本数据根据列存储,即所有样本的第一字段的值首先出现,然后是所有样本的第二字段的值,依此类推。格式的列性质有助于高效的数据分析,因为可以在列的子集上进行查询,而不需要加载整个数据记录。此外,将列组合在一起可以更有效地压缩数据,从而降低存储成本。查看[这篇文章](/understanding-apache-parquet-7197ba6462a9)了解更多关于列数据存储的优势。**
**下图总结了我们对拼花地板的评估:**
****
**拼花地板评估**
**作为一种列格式, *Parquet* 能够有效地提取数据列的子集。此外,我们还可以利用格式的分栏特性,通过以下方式促进行过滤:1 .首先提取我们正在过滤的列,然后 2。仅对匹配过滤器的行提取其余的列。然而,由于有效的数据提取可能依赖于提取完整行块的列数据,因此不清楚这种方法是否能很好地执行。因此我们用黄色标记了这个能力。更高效的过滤方法可能需要在数据集创建期间根据类别将样本分离到不同的 *Parquet* 文件中,如上所述。在 [pyspark](https://spark.apache.org/docs/latest/api/python/) 中,这可以使用 [partitionBy](https://spark.apache.org/docs/2.4.0/api/python/pyspark.html?highlight=partitionby#pyspark.RDD.partitionBy) 功能来完成。**
****Parquet 数据集创建**:在下面的代码块中,我们演示了使用 [pyspark](https://spark.apache.org/docs/latest/api/python/) 库从流行的 [Cifar10](https://www.cs.toronto.edu/~kriz/cifar.html) 数据集创建一个 *Parquet* 数据集。其他库也支持拼花地板的创建,包括熊猫和 pyarrow。**
```
**from tensorflow.keras import datasets
from pyspark.sql import SparkSession, Row
from pyspark.sql.types import StructType, \
StructField, IntegerType, BinaryTypedef cifar_to_parquet():
schema = StructType(
[StructField("image", BinaryType(), True),
StructField("label", IntegerType(), True)])
(data, labels), _ = datasets.cifar10.load_data()
labels = labels.flatten().tolist()
num_procs = 4 *# set the number of parallel processes* spark = SparkSession.builder\
.master('local[{num_procs}]'.format(num_procs=num_procs))\
.getOrCreate()
sc = spark.sparkContext num_samples = len(labels)
output_url = 'file:///tmp/parquet' def row_generator(i):
return {
'image': bytearray(data[i].tobytes()),
'label': labels[i],
} *# optionally configure the size of row blocks
# blockSize = 1024 * 1024 * 16 # 16 MB
# sc._jsc.hadoopConfiguration()\
# .setInt("parquet.block.size", blockSize)* rows_rdd = sc.parallelize(range(num_samples))\
.map(row_generator)\
.map(lambda x: Row(**x)) spark.createDataFrame(rows_rdd, schema)\
.write.mode('overwrite')\
.parquet(output_url)**
```
**虽然组成数据集的文件数量、每个文件的大小以及每个行块的大小会对数据加载的性能产生有意义的影响,但控制这些参数有时会有点棘手。在 pyspark 中,可以使用 *sc 设置行块大小。_jsc.hadoopConfiguration* 如上面代码块中的注释所示(默认值为 128 MB),文件的大小和数量取决于并行进程的数量和 [coalesce](https://spark.apache.org/docs/2.4.0/api/python/pyspark.sql.html?highlight=partition#pyspark.sql.DataFrame.coalesce) 函数。**
**通过适当的配置,该脚本可以修改为直接写入亚马逊 S3(例如,参见此处的和此处的)。**
## **佩塔斯托姆**
**petastorm 库的创建有一个特定的目标,即统一开发管道上所有数据消费者使用的数据集(见[这里](https://www.infoq.com/presentations/petastorm-ml-pipelines/))。尽管 petastorm 抽象了底层存储格式,但使用的默认格式是 *Apache Parquet* 。更准确地说,petastorm 通过在 [Unischema](https://petastorm.readthedocs.io/en/latest/api.html#module-petastorm.unischema) 结构中提供额外的模式信息、支持多维数据和支持数据压缩编解码器来扩展 *Apache Parquet* 。此后,我们将假设使用扩展的 *Parquet* 作为底层格式,并滥用术语 *petastorm* 来指代库本身以及库创建的文件格式。为了区分这两者,我们在提到 *Petastorm* 格式时将使用大写。使用 *Parquet* 作为底层格式意味着 *Petastorm* 享有我们上面讨论的与使用列格式相关的所有好处。然而,使用 petastorm 引入的 *Parquet* 扩展有一个警告:数据集需要由 petastorm 库创建,开发管道上的所有数据消费者都需要 petastorm 库来正确读取和解析数据。这个要求有些限制,因为 *Parquet* 格式最吸引人的属性之一是其用于访问和操作数据的广泛的软件生态系统。正是因为这个原因,我们在下面的评估图中用黄色标记了*软件生态系统*:**
****
**Petastorm 评估**
**Petastorm 包括许多其他引人注目的特性,包括对行组索引和 n 元语法的支持。你可以在这里和这里了解更多关于 petastorm [的信息。](https://eng.uber.com/petastorm/)**
****Petastorm 数据集创建**:PETA storm 中的数据集创建与 pyspark 中的 *Parquet* 创建非常相似。主要区别在于使用了 [Unischema](https://petastorm.readthedocs.io/en/latest/api.html#module-petastorm.unischema) 和包装数据集创建的 *materialize_dataset* 上下文。**
```
**from petastorm.codecs import CompressedImageCodec, \
NdarrayCodec, ScalarCodec
from petastorm.etl.dataset_metadata import materialize_dataset
from petastorm.unischema import Unischema,\
UnischemaField, dict_to_spark_row
from pyspark.sql import SparkSession
from pyspark.sql.types import IntegerTypedef cifar_to_peta():
MySchema = Unischema('MySchema', [
UnischemaField('image', np.uint8,
(32,32,3), NdarrayCodec(), False),
UnischemaField('label', np.uint8,
(), ScalarCodec(IntegerType()), False),
])
(data, labels), _ = datasets.cifar10.load_data()
labels = labels.flatten().tolist()
num_procs = 4 *# set the number of parallel processes* spark = SparkSession.builder.\
master('local[{num_procs}]'.format(num_procs=num_procs))\
.getOrCreate()
sc = spark.sparkContext num_samples = 100*#len(labels)* output_url = 'file:///tmp/petastorm'
rowgroup_size_mb = 128 def row_generator(i):
return {
'image': data[i],
'label': np.uint8(labels[i]),
} *# Wrap dataset materialization portion.
# Will take care of setting up spark environment variables as
# well as save petastorm specific metadata* with materialize_dataset(spark, output_url,
MySchema, rowgroup_size_mb):
rows_rdd = sc.parallelize(range(num_samples)) \
.map(row_generator) \
.map(lambda x: dict_to_spark_row(MySchema, x)) spark.createDataFrame(rows_rdd,
MySchema.as_spark_schema()) \
.write \
.mode('overwrite') \
.parquet(output_url)**
```
**行块大小由 *rowgroup_size_mb* 参数在 petastorm 中确定。在这个例子中,我们没有利用 petastorm 中包含的编解码器支持。当使用大数据元素时,使用编解码器支持可以显著压缩数据并节省存储成本。**
## **羽毛**
**[羽毛文件格式](https://arrow.apache.org/docs/python/feather.html)是我们考虑的另一种纵列格式,因为它包含在 [TensorFlow I/O](https://www.tensorflow.org/io) 中(更多信息见下文)。虽然 *Feather* 和 *Parquet* 之间有许多相似之处,但是它们不同的底层实现也有许多细微的差异。两者之间的一个很好的比较,包括场景中*羽毛*可能是更好的选择,可以在[这里](https://ursalabs.org/blog/2020-feather-v2/#:~:text=Parquet%20is%20fast%20to%20read,is%20even%20faster%20to%20read.&text=In%20the%20case%20of%20Feather,converting%20to%20R%20or%20pandas.)找到。区分*羽化*格式的版本 1 和版本 2 很重要。版本 2 支持更多的数据类型以及不同类型的数据压缩。每当你遇到*羽*的评论,切记它可能是基于格式的版本 1。**
**羽毛和 T21 的主要区别在于软件生态系统的范围。尽管它得到了诸如 [pyarrow](https://arrow.apache.org/docs/python/feather.html) 和 [pandas](https://pythontic.com/pandas/serialization/feather) 等库的支持,但在撰写本文时, *Feather* 格式远没有 *Parquet* 那么流行,而且支持框架的数量也非常有限。我们在下图中总结了我们的*羽*文件格式评估:**
****
**羽毛评价**
**作为列格式,对于我们如何选择对*列支持*和*行过滤*属性进行评级,存在与上述相同的考虑因素。**
****羽毛数据集创建**:在下面的代码块中,我们演示了使用 [pyarrow](https://arrow.apache.org/docs/python/feather.html) 创建一个*羽毛*文件。*羽毛*创作支持也被内置到[熊猫](https://pythontic.com/pandas/serialization/feather)库中。在之前的数据集创建中,流程并行化是数据创建代码不可或缺的一部分,与此相反,我们在这里演示了单个文件的创建。完整的解决方案需要生成多个进程,负责创建构成完整数据集的文件的不相交子集。**
```
**from tensorflow.keras import datasets
import pyarrow as pa
from pyarrow.feather import write_featherdef cifar_to_feather():
(data, labels), _ = datasets.cifar10.load_data()
data = [data[i].flatten() for i in range(data.shape[0])]
labels = labels.flatten()
table = pa.Table.from_arrays([data,labels], ['data','labels'])
write_feather(table, '/tmp/df.feather', chunksize=10000)write_feather(table, '/tmp/df.feather', chunksize=10000)**
```
**在上面的例子中,行块的大小由参数 *chunksize* 决定。注意,与前面的格式创建相反,我们通过每个块的记录数而不是每个块的内存量来确定大小。**
# **使用替代文件格式的 TensorFlow 培训**
**现在,我们将注意力转向上面列出的最后一个要求,文件格式与 TensorFlow 培训的兼容性。无论您选择的文件格式有多么吸引人,如果您不能将其应用到培训课程中,或者输入流的速度不能满足您的需求,那么您就又回到了起点。在本节中,我们将探索一些工具,用于在 TensorFlow 中使用上述文件格式进行培训。在接下来的部分中,我们将在一些实验中测量输入流的速度。我们的讨论是基于 [TensorFlow](https://www.tensorflow.org/) 的 2.4.1 版本、 [TensorFlow I/O](https://www.tensorflow.org/io) 的 0.17.1 版本和 [petastorm](https://petastorm.readthedocs.io/en/latest/index.html#) 的 0.11.0 版本。**
## **张量流数据集 API**
**在一个典型的 TensorFlow 应用程序中,我们定义了一个 [tf.data.Dataset](https://www.tensorflow.org/api_docs/python/tf/data/Dataset) ,它表示一系列数据样本,并将其送入训练循环。建立一个 [tf.data.Dataset](https://www.tensorflow.org/api_docs/python/tf/data/Dataset) 包括定义数据源和对数据应用转换。源可以是存储在内存或文件中的数据。查看[此处](https://www.tensorflow.org/guide/data)了解更多关于如何在 TensorFlow 中创建数据集的信息。既然我们已经选择了 *TFRecord* 格式作为我们的参考点,那么让我们从回顾如何将 *TFRecord* 文件输入到 TensorFlow 培训会话开始。**
****TFRecordDataset:** 一个 [TFRecordDataset](https://www.tensorflow.org/api_docs/python/tf/data/TFRecordDataset) 将一列 *TFRecord* 文件作为输入,并产生一系列序列化的 *TFRecord* 数据样本。之后通常会有一个 [tf.data.Dataset.map](https://www.tensorflow.org/api_docs/python/tf/data/Dataset?version=nightly#map) 调用,在这个调用中会对每个样本进行解析。下面的代码块演示了从以 *TFRecord* 格式存储的 [Cifar10](https://www.cs.toronto.edu/~kriz/cifar.html) 数据创建 [TFRecordDataset](https://www.tensorflow.org/api_docs/python/tf/data/TFRecordDataset) :**
```
**import tensorflow as tf
def get_dataset():
autotune = tf.data.experimental.AUTOTUNE
def parse(example_proto):
feature_description = {
'image': tf.io.FixedLenFeature([], tf.string),
'label': tf.io.FixedLenFeature([], tf.int64)}
features = tf.io.parse_single_example(example_proto,
feature_description)
image = tf.io.decode_raw(features['image'], tf.uint8)
image = tf.reshape(image, [32, 32, 3])
return image, label
records = tf.data.Dataset.list_files(<path_to_files>+'/*')
ds = tf.data.TFRecordDataset(records,
num_parallel_reads=autotune)
ds = ds.map(parse, num_parallel_calls=autotune)
return ds**
```
**我们对 [TFRecordDataset](https://www.tensorflow.org/api_docs/python/tf/data/TFRecordDataset) 的体验总体上是积极的;拉取和解析文件的底层机制似乎相当可靠,我们很少发现自己在管道的这一部分遇到瓶颈。我们还发现该 API 非常健壮,在各种各样的培训环境中都表现良好。**
**TensorFlow 有几个其他的 tf.data.Dataset 类用于直接从文件加载数据,包括 [FixedLengthRecordDataset](https://www.tensorflow.org/api_docs/python/tf/data/FixedLengthRecordDataset) 和 [TextLineDataset](https://www.tensorflow.org/api_docs/python/tf/data/TextLineDataset) 。从与任何现有类都不匹配的文件格式构建 TensorFlow 数据集需要更多的创造力。这里我们将按照复杂程度的升序来提到三个选项。**
****从内存源**创建数据集:第一个选项是下载并解析 Python 中的文件(在 TensorFlow 之外)并将数据样本从内存源加载到 TensorFlow 中。一种方法是使用[TF . data . dataset . from _ generator](https://www.tensorflow.org/api_docs/python/tf/data/Dataset#from_generator),如下面的伪代码块所示。**
```
**import tensorflow as tf
def get_custom_ds(file_names):
def my_generator():
for f in file_names:
# download f
samples = ... # parse samples from f
for sample in samples:
yield sample return tf.data.Dataset.from_generator(
my_generator,
output_types=[tf.uint8,tf.uint8],
output_shapes=[[32,32,3],[]])**
```
****解析 TensorFlow** 中的文件:第二种选择是依赖 TensorFlow 的 [tf.io](https://www.tensorflow.org/api_docs/python/tf/io) 模块来下载和解析文件。与之前的解决方案相比,这里的文件管理是 TensorFlow 执行图的一部分。下面是一种使用[TF . data . dataset . list _ files](https://www.tensorflow.org/api_docs/python/tf/data/Dataset#list_files)和[TF . data . dataset . interleave](https://www.tensorflow.org/api_docs/python/tf/data/Dataset#interleave)API 的方法:**
```
**import tensorflow as tf
def get_custom_ds():
autotune = tf.data.experimental.AUTOTUNE
filenames = tf.data.Dataset.list_files(<path_to_files>+'/*',
shuffle=True)
def make_ds(path):
bytestring = tf.io.read_file(path)
samples = ... # parse bytestring using tf functions
return tf.data.Dataset.from_tensor_slices(samples) ds = filenames.interleave(make_ds,
num_parallel_calls=autotune,
deterministic=False)
return ds**
```
****创建自定义数据集类**:我们提到的最后一个选项是创建一个新的 tf.data.Dataset 类,专门用于处理您的数据格式。这种选择需要最高超的技术。根据数据输入流的速度来衡量,它还提供了最高的潜在回报。实现这一点的一种方法是修改 TensorFlow C++代码,[从源代码](https://www.tensorflow.org/install/source)重新构建 TensorFlow。例如,可以克隆 TFRecordDataset 实现,只覆盖与解析格式特别相关的代码部分。通过这种方式,人们希望能够享受与 TFRecordDataset 相同的性能优势。这种方法的缺点是需要维护一个专门的 TensorFlow 版本。特别是,每次升级到 TensorFlow 的新版本时,您都需要重新构建您的自定义解决方案。请注意,自定义数据集类创建也可以在 TensorFlow I/O 中实现,而不是在 TensorFlow 中实现,如[这篇](/how-to-build-a-custom-dataset-for-tensorflow-1fe3967544d8)帖子中所述。**
**虽然上述任何解决方案都可以进行适当的调整以最大限度地提高性能,但这并不总是那么容易。更糟糕的是,您可能会发现理想的配置(例如,底层系统流程的数量)可能会因培训环境的不同而有很大差异。从这个意义上来说,使用一个专用的数据集类(比如 TFRecordDataset)比我们已经描述过的定制解决方案有更大的优势。接下来我们将看到的两个解决方案将使用专门为我们选择的文件格式设计的数据集类。**
## **张量流输入/输出**
**[TensorFlow I/O](http://TensorFlow I/O) (tfio)是 TensorFlow 的一个扩展包,增加了对 TensorFlow 中不包含的许多文件系统和文件格式的支持。特别是,tfio 定义了用于创建基于 *Feather* 格式的数据集的[tfio . arrow . arrow Feather dataset](https://www.tensorflow.org/io/api_docs/python/tfio/arrow/ArrowFeatherDataset)类和用于创建基于 *Parquet* 格式的数据集的[tfio . v 0 . io dataset . from _ Parquet](https://www.tensorflow.org/io/api_docs/python/tfio/v0/IODataset#from_parquet)函数。**
****tensor flow I/O Feather Dataset**:[tfio . Arrow . Arrow Feather Dataset](https://www.tensorflow.org/io/api_docs/python/tfio/arrow/ArrowFeatherDataset)类只是设计用于支持 [Apache Arrow](https://arrow.apache.org/) 格式的[API 集合](https://www.tensorflow.org/io/api_docs/python/tfio/arrow)中的一个。要全面了解 tfio [Apache Arrow](https://arrow.apache.org/) 产品,请务必查看[这个](https://blog.tensorflow.org/2019/08/tensorflow-with-apache-arrow-datasets.html)博客。在下面的代码块中,我们演示了基于我们在上面创建的以 *Feather* 格式存储的 Cifar10 数据的[tfio . arrow . arrow Feather dataset](https://www.tensorflow.org/io/api_docs/python/tfio/arrow/ArrowFeatherDataset)的使用。**
```
**import tensorflow as tf
import tensorflow_io.arrow as arrow_iodef get_dataset():
filenames = <list of feather files>
ds = arrow_io.ArrowFeatherDataset(filenames,
columns=(0, 1),
output_types=(tf.uint8, tf.uint8),
output_shapes=([32*32*3,], []),
batch_mode='auto')
ds = ds.unbatch()
return ds**
```
**通过将 *batch_mode* 参数设置为*‘auto’*,我们选择让数据集返回 *Parquet* 行块。因此,我们应用的第一个调用是[解锁](https://www.tensorflow.org/api_docs/python/tf/data/Dataset#unbatch)记录,以便返回单个样本。这种策略应该比单独读取样本产生更好的性能。**
**我们发现,如果将[tfio . arrow . arrow feather dataset](https://www.tensorflow.org/io/api_docs/python/tfio/arrow/ArrowFeatherDataset)与[TF . data . dataset . interleave](https://www.tensorflow.org/api_docs/python/tf/data/Dataset#interleave)结合使用,吞吐量性能会有所提高:**
```
**import tensorflow as tf
import tensorflow_io as tfiodef get_dataset():
autotune = tf.data.experimental.AUTOTUNE
filenames = tf.data.Dataset.list_files(<path_to_files>+'/*',
shuffle=True)
def make_ds(file):
ds = arrow_io.ArrowFeatherDataset(
[file], [0,1],
output_types=(tf.uint8, tf.uint8),
output_shapes=([32*32*3,], []),
batch_mode='auto')
return ds
ds = filenames.interleave(make_ds,
num_parallel_calls=autotune,
deterministic=False)
ds = ds.unbatch()
return ds**
```
****TensorFlow I/O 拼花数据集**:与 *Feather* 数据集类相反, [from_parquet](https://www.tensorflow.org/io/api_docs/python/tfio/v0/IODataset#from_parquet) 函数接收单个*拼花*文件。但是,我们可以通过在以 *Parquet* 格式存储的 Cifar10 数据集上使用[TF . data . dataset . interleave](https://www.tensorflow.org/api_docs/python/tf/data/Dataset#interleave)来克服这一限制,如下所示:**
```
**import tensorflow as tf
import tensorflow_io as tfiodef get_dataset():
autotune = tf.data.experimental.AUTOTUNE
filenames = tf.data.Dataset.list_files(<path_to_files>+'/*',
shuffle=True)
def parquet_ds(file):
ds = tfio.IODataset.from_parquet(file,
{'image': tf.string,
'label': tf.int32})
return ds
ds = filenames.interleave(parquet_ds,
num_parallel_calls=autotune,
deterministic=False)
def parse(example):
image = tf.io.decode_raw(example['image'], tf.uint8)
image = tf.reshape(image, [32, 32, 3])
label = example['label']
return image, label
ds = ds.map(parse,num_parallel_calls=autotune)
return ds**
```
## **佩塔斯托姆**
**petastorm 库 [TensorFlow API](https://petastorm.readthedocs.io/en/latest/readme_include.html#tensorflow-api) 定义了 *make_petastorm_dataset* 函数,用于从 petastorm 阅读器(petastorm.reader.Reader)创建 TensorFlow tf.data.Dataset。这个数据集的源可以是 *Petastorm* 格式,也可以是 raw *Parquet* 格式。为了从 *Petastorm* 格式的数据集中读取,我们使用 make_reader API 创建读取器。为了从一个 *Parquet* 格式的数据集中读取数据,我们使用 make_batch_reader API 创建读取器。这里的表[中描述了两个阅读器之间的一些微妙差异](https://petastorm.readthedocs.io/en/latest/readme_include.html#non-petastorm-parquet-stores)。请注意,从 *Petastorm* 格式创建的 TensorFlow tf.data.Dataset 返回单个数据样本的序列,而从 raw *Parquet* 格式创建的 TensorFlow tf.data.Dataset 返回批量数据样本,其大小由 *Parquet* 行组大小决定。**
**在下面的代码块中,我们演示了如何使用*make _ PETA storm _ dataset*API 从以 *Petastorm* 格式存储的 Cifar10 数据创建 TensorFlow tf.data.Dataset。**
```
**from petastorm import make_reader
from petastorm.tf_utils import make_petastorm_datasetdef get_dataset():
with make_reader('<path to data>') as reader:
ds = make_petastorm_dataset(reader)
return ds**
```
**在下面的代码块中,我们演示了如何使用*make _ PETA storm _ dataset*API 从以 *Parquet* 格式存储的 Cifar10 数据创建 TensorFlow tf.data.Dataset。**
```
**from petastorm import make_batch_reader
from petastorm.tf_utils import make_petastorm_datasetdef get_dataset():
autotune = tf.data.experimental.AUTOTUNE
with make_batch_reader('<path to data>') as reader:
ds = make_petastorm_dataset(reader)
ds = ds.unbatch()
def parse(example):
image, label = example
image = tf.io.decode_raw(image, tf.uint8)
image = tf.reshape(image, [32, 32, 3])
return image, label
ds = ds.map(parse,num_parallel_calls=autotune)
return ds**
```
**注意我们如何使用 [unbatch](https://www.tensorflow.org/api_docs/python/tf/data/Dataset#unbatch) 例程来返回单个样本。**
# **结果**
**在这一部分,我们分享几个实验的结果。所有实验都在一个 c5.2xlarge [Amazon EC2 实例类型](https://aws.amazon.com/ec2/instance-types/)(有 8 个 vCPUs)上运行,TensorFlow 版本为 2.4.1,TensorFlow I/O 版本为 0.17.1,petastorm 版本为 0.11.0。实验分为两部分。首先,我们尝试了以我们讨论过的文件格式存储的 Cifar10 数据输入 TensorFlow 会话的不同方法。我们创建了数据的多个副本,以便人为地夸大数据集。对于这些实验,我们选择将训练批量设置为 1024。**
**为了评估样本记录的大小如何影响相对性能,我们运行了第二组测试,其中我们向每个 Cifar10 数据样本添加了一个大小为 2 MB 的随机字节数组。对于这些实验,我们选择将训练批量设置为 16。**
**对于所有实验,数据集被分成大小为 100-200 MB 的基础文件。**
**因为我们只对测量训练数据吞吐量感兴趣,所以我们选择放弃构建训练模型,而是直接在 TensorFlow 数据集上迭代,如下面的代码块所示。**
```
**import time
ds = get_dataset().batch(batch_size)
round = 0
start_time = time.time()
for x in ds:
round = round + 1
if round % 100 == 0:
print("round {}: epoch time: {}".
format(round, time.time() - start_time))
start_time = time.time()
if round == 2000:
break**
```
**注意,在 petastorm 的情况下,数据集遍历必须移动到 petastorm 阅读器上下文中。**
**我们分享这些结果的目的是让你知道你的出发点是什么,以及可能需要的优化工作量。我们强烈建议不要从这些结果中得出任何关于您自己的使用案例的结论,原因如下:**
1. **解决方案的性能可能会因模型、数据集和培训环境的不同而有很大差异。**
2. **对于给定的用例,每个解决方案的性能将根据如何配置格式和 TensorFlow 数据集的具体情况而有所不同,包括:每个文件的大小、行组的大小、压缩方案的使用、工作进程的数量、每个样本批次的大小等等。**
3. **实验通过直接迭代 TensorFlow 数据集来测量解决方案的最大吞吐量。在实践中,吞吐量需要足够高,以保持培训会话繁忙。换句话说,只要我们没有遇到 IO 瓶颈,我们可能会非常满意低于最大值的吞吐量。**
4. **当你读到这篇文章的时候,我用过的库的版本可能已经过时了。较新版本的库可能包含影响其性能的更改。**
5. **最后但并非最不重要的是,我的实验中出现错误的可能性。当你找到他们时,请给我写信。**
****
**测试结果(每步秒数越少越好)**
**结果证明了 *TFRecord* 格式和 *TFRecordDataset* 的实力。特别是,我们可以看到它们在不同环境下的稳定性。与此同时,其他一些实验产生的训练量相比之下并不逊色。虽然我们发现结果令人鼓舞,但在我们测试的两个案例中,必须注意替代解决方案的不稳定性。在一个场景中表现良好的解决方案(与 *TFRecord* 格式相比)在另一个场景中似乎会失效。看起来,与使用 *TFRecord* 格式*相比,*将其他格式用于不同的培训设置可能需要一些额外的工作。鉴于我们在本帖中讨论的替代格式的优势,这种努力可能是值得的。**
**另一个感兴趣的指标是与每个选项相关的 CPU 利用率。在最近的一篇博客文章中,我们讨论了由于一个或多个 CPU 达到最大利用率而导致培训管道中出现瓶颈的可能性。在担心这种可能性的情况下,明智的做法是评估与数据存储相关的不同决策如何影响加载和解析数据的 CPU 利用率。其中包括文件格式的选择、数据压缩(和解压缩)、TensorFlow 数据集创建方法等等。在下面的图表中,我们列出了 Cifar10 实验中三个性能最高的解决方案的平均 CPU 利用率。CPU 利用率是从[亚马逊 CloudWatch](https://aws.amazon.com/cloudwatch/) 的[亚马逊 EC2 实例指标](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/viewing_metrics_with_cloudwatch.html#ec2-cloudwatch-metrics)中获取的。由于我们使用的实例有 8 个 vCPUs,因此最大利用率为 800%。**
****
**CPU 利用率(800%之外—越低越好)**
# **摘要**
**尽管 TensorFlow 明显偏向于 *TFRecord* 格式,但它的一些属性仍不尽如人意。虽然 *TFRecord* 格式对于训练来说很棒,但是它不太可能适合开发管道中数据的任何其他消费者。在本帖中,我们讨论了几种更好地解决整体项目需求的格式,并评估了它们与 TensorFlow 培训的兼容性。虽然可能需要一些努力来支持不同的训练场景,但是我们的结论是有合法的替代方法来代替 *TFRecord* 格式。**
# 数据融合:谷歌云数据仓库的无代码管道
> 原文:<https://towardsdatascience.com/data-fusion-a-code-free-pipeline-for-your-google-cloud-data-warehouse-5b31dd4be91e?source=collection_archive---------15----------------------->
## 无需专业技能,只需几天而不是几个月就能建立企业级端到端数据平台
尽管过去五到十年发布了大量基于云的大数据平台和应用程序,但创建数据仓库通常仍是一项艰巨的任务,需要独特的技术技能来设计、设置和日常操作。在将数据融合添加到其 SaaS 解决方案组合后,谷歌云旨在提供一种解决方案来克服这些挑战,并让每个用户都有能力创建和管理企业级数据平台。
这是及时的,因为对于许多公司来说,新冠肺炎不仅严重破坏了现有的数据源和商业智能操作和仪表板,还造成了快速使用数据的额外压力。与此同时,经济的不确定性削减了预算和资源。如今,几乎每个人都比以往任何时候更需要更简单的解决方案,由于其直观的拖放式用户界面,数据融合可以为许多组织提供极大的帮助。

照片由[西格蒙德](https://unsplash.com/@sigmund?utm_source=medium&utm_medium=referral)在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 拍摄
# 用例
关于数据融合的公开或社区内容仍然很少,即使它已经在谷歌云平台上普遍[提供了一年多](https://cloud.google.com/blog/products/data-analytics/introducing-the-code-free-bridge-to-data-analytics-on-google-cloud)。即使数据融合仍然处于初级阶段,我也想分享我的印象,并解释它是如何信守承诺的。也就是说,
> 数据融合如何允许在几天而不是几个月内建立一个端到端的数据仓库,
同时满足以下要求:

维克多·加西亚在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄的照片
1.每天接收由单租户服务器集群产生的数百千兆字节的压缩数据;
2.定期为每个实体制作 PDF 报告;
3.为一些团队成员提供商业智能工具,他们可以修改现有的仪表板,创建新的仪表板,并通过简单的用户界面查询和可视化最新数据;
4.为未来的机器学习敞开大门。
它还满足了这种性质项目的严格限制,包括
5.零资本支出和低运营支出的基于消费的成本模式;
6.尽可能多的 SaaS 和自助服务;和
7.最少量的编码或高度技术性的操作;
# 示例架构
> 数据融合本质上是协调所有的管道步骤,从第三方数据的**摄取**,到转换数据到分析数据库的**加载**。 [Data Studio](https://datastudio.google.com/overview) 然后根据转换后的数据创建商业智能报告。

利用数据融合、云存储、大查询和 Data Studio 的数据平台的架构图。作者图解。
请注意,数据融合与谷歌的大部分产品组合无缝集成,因此这里提到的几个解决方案可以被其他谷歌云产品取代。例如,这个用例使用[云存储](https://cloud.google.com/storage)作为数据湖,使用[大查询](https://cloud.google.com/bigquery)作为数据仓库,但是存在许多替代方案。在本例中,管道经过以下步骤:
## 1.摄入谷歌云存储
Blob 存储是构建存储原始和非结构化数据的数据湖的明显候选,这是摄取步骤将首先存储数据的地方。数据融合为大多数数据源提供了连接器,包括存储帐户、其他公共云、FTP、Oracle 等数据库等。还有许多方法可以将原始文件发送到谷歌云存储,从高度自动化的解决方案和传输实用程序到依赖虚拟机的更多手动解决方案。
## **2。数据融合工作流程**
数据融合提供了一个易于使用的拖放用户界面来创建数据管道,称为集成。集成允许用户创建具有三种类型元素的管道:
1. 数据源——比如谷歌云存储
2. 转换,位于输入和输出之间
3. 汇,即输出——比如 Big Query,这是谷歌著名的 SaaS 数据仓库解决方案,专门用于分析工作负载

数据融合的基本工作流程:数据输入(源)-转换-数据输出(汇)。作者截图。
每个管道必须至少包含一个源和一个接收器(数据融合不允许“空”箭头)。
**示例**
在从 Google Gloud 存储中读取所有匹配的文件名后,我们的第一个 ETL 管道分为两个路径:
第一个用处理 CSV 文件的内容
* 用 Javascript 编写的第一个逐行转换,
* 一个解析 CSV 文件的“牧马人”,
* 大型查询的接收负载
第二个示例使用
* Group By 和 Count 计算文件中的记录数,
* 添加时间戳的 Javascript 转换,
* 一个大型查询接收负载,
* 最后是文件移动,在成功加载后将文件归档到不同的 Google 云存储目录中。

数据融合示例工作流从云存储接收数据,并将转换后的数据插入到大查询中。作者截图。
数据融合始终依赖于强类型模式,因此每次转换都会接收到可预测的输入并产生可预测的输出。例如,Google Cloud Storage reader 会将每个逐行读取的属性传递给下一个转换:一个字符串“body”表示行的内容,一个字符串“path”表示文件路径。当需要逐记录而不是逐行读取输入文件时,也可以使用 XML 阅读器。
**转换**
数据融合提供的最强大的工具是数据转换,其中包括[牧马人](https://en.wikipedia.org/wiki/Data_wrangling)。
> wrangler 允许用户使用直观的图形用户界面解析平面文件。从逐行加载的样本原始数据文件开始,用户可以解析、重命名和改变变量类型、添加或删除列、提取和分解数据等。所有的操作都在一个被称为“配方”的转换列表上被同时跟踪。

Data Fusion wrangler 用于在平面文件上定义由 14 个转换步骤组成的配方。作者截图。
一旦定义了争论的步骤,配方中的指令列表就应用于管道中的转换。执行时,转换会将其输入模式中的输入行转换为输出模式。数据融合并不总是直接更新 wrangler 转换中的输出模式,但是配方和模式都可以导出为 JSON 文件,并通过数据融合导入。该食谱还与谷歌数据准备共享相同的语言,谷歌数据准备是一个稍微更强大的工具,但需要单独的许可证。
数据融合提供了许多其他对于更复杂的管道不可或缺的转换:规范化/反规范化、XML 解析等。虽然不总是像气流等效物那样通用,但是数据融合转换提供了全面的功能覆盖。JavaScript 是一种必然有用的转换。由于数据融合仍然是一个相对较新的解决方案,在某一点上,它将缺乏一个功能。这就是 JavaScript 转换变得方便的地方。需要添加时间戳,但没有管理时间戳或文件名的转换?没问题,一个三行脚本就能搞定。
## **3。大查询**
转换的输出可以发送到各种数据存储和数据库,其中大查询将成为数据仓库的基础。数据融合 BigQuery 接收器将转换产生的数据转换为附加在 BigQuery 表中的行。请注意,在创建表时,BigQuery 不需要显式定义的模式,在这种情况下,当第一行插入表中时,将记录模式。虽然很方便,但是管理数据融合和大型查询之间的模式更改可能很困难,尤其是在数据仓库创建的早期阶段。

存储转换数据的大型查询数据仓库。作者截图。
数据融合可以反过来从大查询中读取数据,以便转换数据和创建更复杂的管道。相对简单的数据转换的另一种替代方法是使用大查询计划查询:这些查询将在计划的时间运行,从给定的表中选择数据,并将输出写入新的表中。
## **4。数据工作室**
Data studio 是谷歌的 SaaS 数据可视化工具。它是免费的,并与 Big Query 紧密集成,因此
* 使用 SQL 语言,可以使用从大型查询表中检索到的数据即时创建和更新可视化效果
* 反之亦然,来自大查询 GUI 的查询输出可以立即导出并在 Data Studio 中可视化
Data Studio 希望输入相对结构化的数据,并且与 PowerBI 等竞争工具相比,它提供的过滤或聚合功能较少,因此拥有正确的 SQL 脚本和一些预处理表非常重要。一旦理解了这一点,Data Studio 提供了一个极其高效的框架,几乎可以立即检索、编辑、发布和导出报告为 PDF。此外,可以在 SQL 查询中直接考虑报告中的参数,从而可以轻松地为各种配置或每个实体生成报告。

Data Studio 查询大查询数据仓库,为用户构建商业智能报表。作者截图。
# **结论**
> 无代码数据管道:数据融合信守承诺
通过提供图形用户界面,允许非技术用户在几天内创建数据管道,Data Fusion 优雅地处理了一个业务问题,否则需要更复杂的技术堆栈*。本文中提到的所有 Google 云解决方案几乎总是彼此无缝集成,使得任何用户都可以轻松使用所有不同的组件,而无需任何技术配置或代码行。
> 数据融合是一个相对较新的解决方案,还有待改进
不过,一个例外是数据融合的最初几天,不幸的是,这带来了一系列神秘的错误和可用性故障。它甚至在第一次执行后就开始了:数据融合的默认资源需求超过了 Google Cloud 试用帐户配额,这只有在深入研究日志文件后才能理解。也许更重要的是,大多数用户输入不会在 GUI 中得到验证,而只会在管道预览期间得到验证。基本错误(如打字错误)通常会导致模糊错误,仅在精细日志中报告。谷歌必须迅速改善这一点,以确保新用户不会感到沮丧,尤其是 Azure 和 AWS 上的竞争解决方案往往能更好地处理这一问题。最后,维护独立的环境和版本也很困难。如果没有数据融合的专用功能,这些任务中的大多数必须使用导出和导入来手动处理。治理和访问控制也是如此:用户可以按照自己的意愿自由地改变事情,但这可能会以稳定性和复杂性为代价。
> 数据融合对许多公司来说看起来很有前途
Data Fusion Enterprise edition 的标价约为 3000 美元/月,此外还有每个管道执行所收取的 [Dataproc](https://cloud.google.com/dataproc) (Hadoop)成本。目前还不清楚有多少客户在使用数据融合,但数据融合解决了许多公司面临的一个真正的业务问题,因此应该有一个光明的未来。
*[ [气流](https://en.wikipedia.org/wiki/Apache_Airflow)(云作曲) [Hadoop](https://en.wikipedia.org/wiki/Apache_Hadoop) (Dataproc)等]
# 数据治理存在严重的品牌问题
> 原文:<https://towardsdatascience.com/data-governance-has-a-serious-branding-problem-7925b909712b?source=collection_archive---------8----------------------->
## 数据治理从哪里开始以及一切是如何出错的故事

*照片由* [*迪米特里·阿尼金*](https://unsplash.com/@anikinearthwalker?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) *上* [*下*](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
> *“在我在数据行业完成的所有任务中,数据治理一直是我最不喜欢的。”*
>
> *–劳拉·b·麦德森,* [*扰乱数据治理*](http://books.google.com/books?id=YhXCDwAAQBAJ)
当你听到“数据治理”这个词时,你首先想到的是什么?规则还是政策?流程还是管理?控制?
数据治理被视为一个限制性的、官僚的、控制性的过程——一组从高处落下的限制来减缓您的工作。事实是,这通常是组织内部的实际运作方式。
作为从事数据治理工作的人,这让我有点难过。治理不应该是数据人类必须害怕的事情。从本质上讲,数据治理与控制无关。这是为了帮助数据团队更好地合作。
因此,让我们来分析一下为什么数据治理会出现身份危机,它在几十年前的实际设想是什么,以及我们如何才能挽救各地数据管理者的声誉。
# 数据治理从何而来?
数据治理建立在非常酷的原则之上。但是如果你搜索数据治理的历史,你可能不会走得很远。事实上,没有任何东西可以追溯到可笑的早期(想想[数据来源于 20,000 年前的骨头](https://www.weforum.org/agenda/2015/02/a-brief-history-of-big-data-everyone-should-read/)或者[人口普查的‘起源于古埃及](https://www.wsj.com/articles/a-short-history-of-census-taking-11561760685))。
部分原因是,数据治理并不性感。很少有人能忍住哈欠,深究它的现在,更不用说它的过去了。让事情变得更加困难的是,数据治理来自于数据管理,这个词听起来更加密集和专业。

自 1990 年以来,书面提及“数据治理”(蓝色)和“数据管理”(红色)。(图片由 [*图集*](https://atlan.com/) *,用*[*Google Ngrams*](https://books.google.com/ngrams/graph?content=data+governance%2Cdata+stewardship&year_start=1990&year_end=2019&corpus=26&smoothing=3)*创建)。)*
虽然“数据治理”在 2000 年代中期开始兴起,但驯服和保护数据(也称为“数据管理”)的想法自十年前数据爆炸以来就一直存在。
数据管理将技术性的数据世界与非技术性的商业世界联系起来。正如劳拉·麦德森[所写的那样](http://books.google.com/books?id=YhXCDwAAQBAJ),“数据管家的目的是帮助巩固粘糊糊的东西……他们说 IT 的语言,并将其翻译回业务。这个角色需要幼儿园老师的耐心和成功应对人质危机的能力。”
**从本质上讲,数据管理以及后来的治理都与协作和民主化有关。**数据管家充当了人员和流程之间的桥梁。他们熟练地引导公司克服使用数据带来的复杂性,并为令人生畏的大数据新世界带来清晰和秩序。
# 当今的数据治理:控制,而不是协作
尽管数据治理源于这种协作思想,但很少以这种方式实现。今天,它更多地被视为一种强加控制的方式。
**数据治理计划通常围绕保护和风险展开,我们必须治理数据以降低风险。**
难怪公司害怕数据风险。随着数据的增长,围绕数据的规则和期望也在飙升。随着隐私泄露的新闻不断,人们越来越关注如何保护自己的个人数据。2018 年,由于多次大规模数据泄露摧毁了 Equifax、脸书、万豪和雅虎等品牌的信誉和股票价值,出现了一场“[关于数据治理的全球清算](https://www.wsj.com/articles/the-morning-download-facebook-at-center-of-global-reckoning-on-data-governance-1521463522)”。因此,新的数据法规遵从性要求(例如 GDPR 和 CCPA)每天都在涌现。
如今,公司希望降低向错误的人展示机密数据的风险,降低不良数据被用于制定重大决策的风险,以及降低违反重要法规的风险。为了防止这些失误,数据被复杂的安全流程和限制所包围,所有这些都由远程数据治理团队决定。
# 更多的数据治理,更高的敏捷性?
多年来,数据治理已经失去了它的身份。我们害怕它,但我们应该庆祝它——因为从根本上说,它是关于创建更好的数据团队,而不是控制他们。
事实上,越多的人开始信任数据治理,他们实际上能够实现的就越多。听起来不确定?先说个例子。
在 Atlan,我们最初是一个数据团队。当时,我们不知道什么是数据治理。我们只知道我们想要承担大规模的[“数据为善”项目](https://atlan.com/about),比如为联合国创建一个 SDG 监测平台,或者开设 10,000 个新的清洁燃料配送中心。
问题是,每天都很混乱。我们有协作过载,人们花更多的时间试图访问或理解数据,而不是实际使用它。我们的空闲时间被诸如“为什么 721 个地理区域的数据丢失了?”或者“为什么这些仪表板显示不同的数字?”

*来自我们数据团队的松弛消息示例。(图片由* [*阿特兰*](https://atlan.com/) *)。)*
因此,我们努力解决这些问题,建立内部数据工具和更好的协作流程。很快,我们意识到我们完成项目的速度是正常规模三分之一的团队的两倍。我们甚至[建立了印度的国家数据平台](https://youtu.be/cctT8QDDC7w),这是由一个 8 人团队在仅仅 12 个月内完成的。如果没有管理我们的团队和数据的正确的工具和文化实践,我们永远不可能做到这一点。
我认为,组织越是开始相信并投资于(而不是害怕)真正的数据治理,他们就越能实现。这意味着实现敏捷和协作的治理工具和过程,而不是某个地方的自上而下的治理团队宣布,“这就是你需要如何考虑定义”。
# 现代数据堆栈中的数据治理复兴
在 Tristan Handy 关于现代数据堆栈的博客中,他谈到了数据治理落后于现代数据堆栈的其他部分。他写道,“治理是一个时代已经到来的产品领域……**没有良好的治理,更多的数据==更多的混乱==更少的信任。**
我认为他的话反映了现代数据堆栈中数据团队和从业者的广泛情绪。随着数据团队变得越来越主流,现代数据堆栈使得接收和转换数据变得更加容易,数据治理实践的缺乏是阻碍数据团队变得敏捷和产生影响的最大障碍之一。
> *这让我们迎来了数据治理的救赎时刻。从业者第一次自下而上地感受到了治理的需要,而不是由于监管而自上而下地强制实施。*
这种自下而上的采用是我们最终获得正确数据治理的机会。然而,现代数据堆栈的现代数据治理将与其前身大相径庭——这意味着我们必须改变实现数据治理的方式。
# 当今数据治理需要的范式转变

*形象由* [*图册*](https://atlan.com/) *组成。*
## **从数据治理到“数据和分析”治理**
“数据”不再是唯一需要治理的资产。
我们正在转向一个生态系统,在这个系统中,数据资产不仅仅是表格,它们还是仪表板、代码、模型等等。所有这些资产都需要整体形式的治理。
## **从集中的方法到分散的、社区主导的方法**
基于集中式数据管家的自上而下的治理模式将不再有效。
工作场所正在发生变化。自上而下的文化正在被侵蚀,员工渴望他们所做的一切都有目的,所以只是告诉人们做一些事情不再管用。未来的数据治理需要从根本上以实践者为主导。
我几乎认为这是一个数据社区,而不是数据治理,其中从业者感到有责任创建可重用资产,以便他们可以帮助其他社区成员。
## **从事后想法到日常工作流程的一部分**
在过去的十年中,数据治理总是在事后才被应用。数据从业者将按原样交付项目,然后回头添加由自顶向下的命令规定的数据治理需求。
在新的世界里,数据治理将不再是事后的想法。相反,它将成为数据从业者“运输工作流程”中不可或缺的一部分。
# 让我们重塑数据治理
现代数据堆栈是重塑新类别的大师。仅在去年一年,我们就创造了[无头 BI](https://basecase.vc/blog/headless-bi) 、[反向 ETL](https://medium.com/memory-leak/reverse-etl-a-primer-4e6694dcc7fb) 、[数据可观察性](/what-is-data-observability-40b337971e3e),以及更多领域。最让我着迷的运动是“[分析工程](https://www.getdbt.com/what-is-analytics-engineering/)”,它改变了数据清洗和转换的思路,赋予了一整群人更高的目的。
我对我们的社区有一个要求… **让我们最终重塑数据治理的品牌,并在我们的堆栈中给予它应有的位置和尊重**。让我们让它听起来像它的本意—一套令人惊叹的数据团队将遵循的实践。
我不太清楚现代数据治理的新品牌和名称应该是什么,但它需要与治理的基本重新定位保持一致,作为自下而上、社区主导的实践者运动。
也许它应该被称为数据支持、社区主导的数据治理或数据产品思维模式?也许数据管家的角色应该包含在数据产品经理的角色中?也许数据治理经理应该更名为数据社区经理或数据支持经理,并加入更广泛的数据平台团队?
有这么多的可能性,所以我希望听到更多人的意见。你怎么想呢?
**觉得这个内容有帮助?在我的时事通讯《元数据周刊》上,我每周都写关于活动元数据、数据操作、数据文化和我们的学习建设的文章** [**Atlan**](https://atlan.com/) **。** [**在此订阅。**](https://metadataweekly.substack.com/)
# 什么是数据治理?
> 原文:<https://towardsdatascience.com/data-governance-impact-on-24cb8e29f281?source=collection_archive---------23----------------------->
## 数据越多,问题越多=价值越低

数据治理具有直接的业务影响— Image by [Castor](http://www.castordoc.com)
> *“数据治理是衡量公司对其数据的控制力的标准”*
数据治理是一个数据管理概念。这是一种衡量公司对其数据控制能力的方法。这种控制可以通过高质量的数据、数据管道的可见性、可操作的权限管理和明确的责任来实现。数据治理包括创建一致且适当的公司数据处理所需的人员、流程和工具。我所说的一致和适当的数据处理是指确保可用性、可用性、一致性、可理解性、数据完整性和数据安全性。
最全面的治理模型——比方说,对于一家全球银行——将有一个强大的数据治理委员会(通常有首席执行官参与)来驱动它;高度自动化,元数据记录在企业字典或数据目录中;数据沿袭可追溯到许多数据元素的来源;以及随着企业需求的变化而不断调整优先级的更广泛的领域范围。
良好的数据治理和隐私模型是人员、流程和软件的混合体。
# 数据治理对业务有直接影响。
数据治理不仅仅是公司为了遵守法规而不得不部署的生锈流程。当然,一部分是法律义务,感谢上帝,但廉洁的治理可以带来很高的商业成果。
以下是数据治理的主要目标:

数据治理业务影响—按作者分类的图片
# 数据治理什么时候成了一件事?
时间表和该领域的关键里程碑。
在过去的二十年里,围绕数据的挑战是构建一个基础架构来高效、大规模地存储和使用数据。随着云数据仓库和 dbt 等转换工具的出现,这些年来生产数据变得更加便宜和容易。由于有了像 Looker、Tableau 或 Metabase 这样的 BI 工具,对数据的访问已经大众化。现在,构建漂亮的仪表板是运营和营销团队的新常态。**这引发了一个新问题:分散的、不可信的&不相关的数据和仪表盘。**
即使是最受数据驱动的公司也仍然难以从数据中获得价值,因为高达 73%的企业数据未被使用。
## →1990–2010:第一部数据隐私法规的出现
20 世纪 70 年代,世界上第一部数据保护法规在德国黑森州通过审查。自那以后,数据监管不断加强。20 世纪 90 年代,欧盟关于数据保护的指令标志着第一个关于数据隐私的法规。
然而,随着 GDPR、HIPAA 和其他有关个人数据隐私的地区性法规的出现,合规性在 2010 年代后半期真正成为了一项全球性挑战。这些第一批法规推动了大型企业的数据治理。这就迫切需要开发工具来处理这些新的需求。
## →2010–2020:符合法规的首选工具。首席级意识到数据治理成为推动业务价值的战略优势
一方面,随着数据资源/流程越来越复杂,另一方面,随着第一批 GDPR 侵权罚款的出现,公司开始构建法规遵从性流程。组织治理和隐私的第一批软件诞生于 Alation 和 Collibra 等公司。
挑战很简单:在公司的各种数据基础设施中实施可追溯性。那时,数据治理是企业级公司的特权,只有企业能够负担得起这些工具。本地数据存储使得部署该软件非常昂贵。事实上,像 Alation 和 Collibra 这样的公司不得不在现场部署技术专家,将数据连接到他们的软件。数据治理工具的第一个版本旨在收集和引用组织各部门的数据资源。
这一时期有几种力量在起作用。收集数据变得更容易,存储数据变得更便宜,分析数据变得更简单。这导致了数据资源数量的寒武纪大爆发。因此,大公司很难了解使用数据完成的工作。数据是分散的、不可信的和不相关的。这种混乱给数据治理带来了新的战略层面。数据治理不仅仅是一项法规遵从性义务,它还成为了创造商业价值的关键手段。
## → 2020 年+:迈向自动化和可操作的数据治理
随着云数据堆栈的标准化,范式发生了变化。更容易连接到数据基础设施并收集元数据。2012 年,在众多孤岛式内部数据中心上部署数据治理工具需要 6 个月的时间,而在 2021 年,在现代数据堆栈(例如:雪花、Looker 和 DBT)上部署数据治理工具只需 10 分钟。
这带来了新的挑战:自动化和协作。excel 上的数据治理**意味着手动维护数千个表格和仪表板上的 100 多个字段。这是不可能的。使用非自动化工具**的数据治理**意味着在数千个表上维护 10 个以上的字段:这非常耗时。使用**全自动工具**进行数据治理意味着只在数千个表上维护 1 或 2 个字段(字面意思是表和列/字段描述)。对于手工工作的最后一部分,您需要利用社区。基于数据消耗(流行资源的高文档 SLA)对工作进行优先级排序,并通过友好的 UX 使使用民主化。**
此外,您希望将数据治理工具集成到数据堆栈的其余部分。定义一次东西,到处都可以找到:无论是表定义、标记、KPI、仪表板、访问权限还是数据质量结果。
# 每个人面临的数据治理挑战不尽相同
基于行业需求和公司规模的多样化治理用例

基于行业需求和公司规模的多样化治理用例—图片由作者提供
There 是数据治理计划的两个主要驱动因素:
数据监管将数据治理流程的最低标准推得更高。它要求企业添加控制、报告和文档。这是确保有时不清楚的过程透明的需要。
随着公司中数据资源、工具和人员的指数级增长,拥有强大的治理变得越来越重要。
复杂程度随着业务运营范围(涵盖的业务线数量和地理位置)、数据创建速度或基于数据的自动化程度(决策、流程)而增加。
# 如何建立良好的数据治理和隐私模型?
需要几块砖来加强数据管理

实施数据管理需要几块砖—图片由 Xavier de Boisredon 提供
Before 甚至谈到数据治理,一个公司需要基础:一个好的基础设施。根据业务需求和公司的数据成熟度,数据架构的性质可能会发生很大变化。关于存储,您是选择内部存储还是云存储?数据仓库还是数据湖?关于模特:火花还是 DBT?在数据仓库中还是在 BI 工具中?实时还是批量?关于可视化:你只允许任何人建立仪表板或数据团队吗?等等。
任何数据治理策略的第一层都是确保相关人员可以找到相关数据集来进行分析或构建他们的人工智能模型。如果你不执行这一步,公司最终会在与工程团队的会议上提出很多问题。该公司最终拥有大量重复的表格、分析和仪表板。设计执行后续步骤所需的资源需要花费宝贵的时间。
一旦你能有效地找到数据。你需要快速理解它,以便评估它是否有用。例如,您正在查看一个名为“*active _ users _ revenue _ 2021*”的数据集。有一栏“*付款*”。这一栏是€还是美元?是今天早上刷新的,还是上周刷新的,还是去年刷新的?它包含所有活跃用户的数据还是只包含欧洲的数据?如果我删除一列,这会破坏营销或财务团队的重要仪表板吗?等等。
现在,您拥有了存储在可扩展基础架构中的数据,每个人都可以找到并理解这些数据,您需要相信这些数据是高质量的。这就是为什么这么多的数据可观察性和可靠性工具在过去的五年中诞生了。数据可观察性是使用自动化监控、警报和分类来消除数据停机的一般概念。数据质量的两种主要方法是:声明性的(手动定义阈值和行为)或 ML 驱动的(检测分布中的突然变化)。
有些数据可能比其他数据更隐私或更具战略性。假设你是一家银行,你不想让公司里的任何人访问交易日志。您需要定义访问权限,并且随着处理数据的人员数量和类型的增长,高效地管理这些权限会很快变得困难。有时,您想为某个特定的任务或其他任何事情授予某人访问权限。如果你的一名员工曾在财务部工作,但后来转到了市场部,会发生什么?你需要彻底有效地管理这些权利。
这个是不言自明的。您需要列出所有资产,报告个人信息和使用情况,以遵守法规。目前,监管机构只针对企业,规模较小的公司开始被罚款只是时间问题。
# 数据治理在现代数据堆栈中处于什么位置?
数据治理将信任从原始数据源带到领域专家仪表板

现代数据堆栈治理—图片由 Xavier de Boisredon 提供
典型的数据流如下:
* 您从企业的各种来源收集数据。它可以是产品日志、营销和网站数据、支付和销售日志等。您可以使用 Fivetran、Stitch 或 Airbyte 等工具提取这些信息。
* 然后将这些数据存储在数据仓库中(雪花、红移、Bigquery、Firebolt 等等)。数据仓库既是存储数据的地方,也是转换数据以对其进行提炼的地方。
* 过去 3 年的新趋势转化层是 DBT。它支持在数据仓库中用 SQL 执行数据转换,同时实现软件工程的良好实践。
* 最后,这种转换帮助您构建您的“数据集市”,这是提炼数据的黄金标准。可视化砖有助于领域专家可视化这种黄金级数据,以便在整个组织中分享见解。
这些步骤发生在不同的工具上,具有高度的抽象性。很难鸟瞰引擎盖下发生的事情。这就是数据治理带来的好处。你可以看到数据是如何流动的,管道在哪里断裂,风险在哪里,作为数据管理者你的精力应该放在哪里等等。
# 更多分析和基准
点击此处,了解更多关于现代数据堆栈[的性能指标评测和分析。我们写了利用数据资产时涉及的所有过程:从现代数据堆栈到数据团队的组成,再到数据治理。我们的博客涵盖了从数据中创造有形价值的技术和非技术方面。如果你是一名数据领导者,并希望更深入地讨论这些话题,请加入我们为此创建的](https://notion.castordoc.com/)[社区](https://notion.castordoc.com/unsupervised-leaders)!
*最初发表于*[*https://www.castordoc.com*](https://www.castordoc.com/blog/what-is-data-governance-and-privacy)*和*[https://www . moderndatastack . XYZ](https://www.moderndatastack.xyz/category/Data-Privacy-and-Governance)*。*
# 数据有许多需要可视化的周期性成分?把它当成音频!
> 原文:<https://towardsdatascience.com/data-has-many-periodic-components-you-need-to-visualize-treat-it-like-audio-dd9569e2a774?source=collection_archive---------17----------------------->
## [提示和技巧](https://towardsdatascience.com/tagged/tips-and-tricks)
## 使用傅立叶变换可视化周期性分量。
您正在处理时间序列数据,并且处于初始发现阶段。你试图找出数据随时间变化的所有不同方式。可能存在趋势,即数据随时间不断增加或减少。可能有完全随机的变化。并且可能存在以某些固定周期随时间上下变化的循环分量。
如果只有一个周期分量,这可能很容易在数据中看到,你甚至可以直观地估计它的周期。但是如果有多个周期分量,每个都有自己的周期呢?如果数据具有超过 3 个(有时超过 2 个)周期分量,简单的绘图通常没有用。
有没有什么方法可以确保你已经识别出所有的周期性成分,每一个都有不同的周期,以及它们自己的趋势和随时间的变化,并将它们可视化?那个东西其实是存在的,它叫声谱图,是信号处理中一个很好理解的话题。由于您正在处理时间序列数据,因此信号处理中使用的许多技术都应该适用,因为信号(音频、天体物理学等)本质上是时间序列数据,其中每个观察值都有一个时间戳和值。
让我们来看看如何制作声谱图。
# 傅立叶变换
其数学基础被称为傅立叶变换。简而言之,如果您的信号有周期成分,FT 是用于从信号中提取其频率(或周期)的数学过程。
<https://en.wikipedia.org/wiki/Fourier_transform>
对信号中的时间间隔(一个窗口或一段时间)应用一次 FT,可以得到该窗口内的周期分量。如果您将窗口移动到信号中的不同位置,并再次应用 FT,您将获得该窗口中的周期分量。重复这个过程很多次,每次只移动窗口一点点,就会描绘出周期成分如何随时间演化的画面(如果有的话)。
# 来自音频的教训
在音频处理中,这种技术使用非常频繁。捕捉音频的一个小时间窗口并对其应用 FT 将揭示当时信号的“频谱”或音频的一组频率成分。
这是我不久前开始的一个项目,目标是构建任何音频文件的声谱图(周期成分随时间的演变):
<https://github.com/FlorinAndrei/soundspec>
如果你从电影[《黑暗骑士](https://www.imdb.com/title/tt0468569/)中选取歌曲 [Why So Serious](https://www.youtube.com/watch?v=1zyhQjJ5UgY) (小丑主题),并对其应用 soundspec,这就是你得到的声谱图:

(图片由作者提供)
在水平轴上,有时间。纵轴是频率。请注意,周期和频率是成反比的,所以周期= 1 /频率。颜色表示振幅,黄色表示高振幅,蓝色表示低振幅或零振幅。
你可以看到在 200 到 400 秒之间有非常强的周期成分,频率约为 30 … 40 Hz,因此周期为 0.033 … 0.025 秒(你可以在歌曲中听到这是一条强有力的低音线)。还有许多其他周期性成分散布在声谱图中——音乐通常非常复杂。
# 返回数据
让我们来看看这个数据集:
[https://github . com/FlorinAndrei/misc/blob/master/FFT _ data . p?raw=true](https://github.com/FlorinAndrei/misc/blob/master/fft_data.p?raw=true)
初始化所有库:
```
import pandas as pd
from matplotlib import pyplot as plt
from scipy import signal
import numpy as np
import os
import pickleplt.rcParams["figure.figsize"] = (16, 9)
```
绘制数据集:
```
if os.path.isfile('fft_data.p'):
dt = pickle.load(open('fft_data.p', 'rb'))
plt.plot(dt);
```

(图片由作者提供)
第一部分有些明显,有一个周期成分,还有一些噪声。但是剩下的就变得相当复杂了。里面有多个周期成分吗?如果有,她们的经期是什么时候?他们有多少人?就对信号的贡献而言,它们在时间上是恒定的,还是变化的?
SciPy 库有一个名为`signal.spectrogram()`的函数,可以生成这个数据集/信号的谱图。让我们应用它:
```
f, t, Sxx = signal.spectrogram(dt, 1)
plt.pcolormesh(t, f, np.log10(Sxx), shading='auto');
```

(图片由作者提供)
如您所见,傅里叶变换对整个数据集应用了 4 次,生成了 4 组光谱。从黄色的位置可以很清楚地看出,所有的活动都发生在底部,低频的地方(短周期的地方)。
我们只保留声谱图底部的 1/5 放大,其余的可以忽略:
```
f, t, Sxx = signal.spectrogram(dt, 1)
frac = len(f) // 5
fshort = f[0:frac]
Sshort = Sxx[0:frac]
per = np.rint(1 / fshort).astype(int)
plt.pcolormesh(t, fshort, np.log10(Sshort), shading='auto');
```

(图片由作者提供)
那更好。您可能已经开始怀疑可能有 3 个周期成分,一个(具有最高频率)在间隔的中心是重要的,另一个(具有中间频率)在间隔的后半部分,第三个(具有低频率)似乎在任何地方都是相同的。
我们需要在时间和频率上提高图像的分辨率。为此,我们将通过`signal.spectrogram()`的`nperseg`参数为时间窗口定义一个固定的大小。我们还将通过`noverlap`参数最大化连续窗口之间的重叠:如果`noverlap = nperseg-1`将第一个窗口应用于信号的最左边部分,那么它将向右移动 1 个像素,再次应用,再次移动 1 个像素,以此类推。
```
nseg = 200
f, t, Sxx = signal.spectrogram(dt, 1, nperseg=nseg, noverlap=nseg-1)
frac = len(f) // 5
fshort = f[0:frac]
Sshort = Sxx[0:frac]
per = np.rint(1 / fshort).astype(int)
plt.pcolormesh(t, fshort, np.log10(Sshort), shading='auto');
```

(图片由作者提供)
好多了。很明显,有 3 个周期成分。频率最低的一个在整个数据集中是恒定的,可能就是我们在原图中看到的那个——图像左三分之一的上下波动。其他两个组成部分随时间变化——这解释了为什么最后三分之二的情节不同。
让我们使用更大的窗口(400 点)再次放大:
```
nseg = 400
f, t, Sxx = signal.spectrogram(dt, 1, nperseg=nseg, noverlap=nseg-1)
frac = len(f) // 5
fshort = f[0:frac]
Sshort = Sxx[0:frac]
per = np.rint(1 / fshort).astype(int)
plt.pcolormesh(t, fshort, np.log10(Sshort), shading='auto');
```

(图片由作者提供)
这可能是最好的了。请记住,这里有一些权衡:为了提高分辨率,您需要一个大窗口,同时也要正确检测长周期信号。但是增加窗口会丢失图像左右两端的数据点——大窗口无法“足够接近”边缘以进行分析。看看横轴是如何随着窗口变大而变短的。
在纵轴上,我们把频率转换成周期。让我们给图像添加一个网格。最后,让我们平滑图像,使它看起来更好(通过`plt.pcolormesh()`的`shading`参数)。
```
nseg = 400
f, t, Sxx = signal.spectrogram(dt, 1, nperseg=nseg, noverlap=nseg-1)
frac = len(f) // 5
fshort = f[0:frac]
Sshort = Sxx[0:frac]
per = np.rint(1 / fshort).astype(int)plt.yticks(ticks=fshort[::2], labels=per[::2])
plt.ylabel('period')
plt.xlabel('obs')
plt.pcolormesh(t, fshort, np.log10(Sshort), shading='gouraud')
plt.grid(True)
plt.show()
```

(图片由作者提供)
现在很清楚了:有一个分量的周期是 100 个点,在整个数据集中是恒定的。还有一个 50 分周期的成分,只在后半段有关系。还有第三个成分,周期为 25 个点,在数据集的中间很强,但在极端情况下很弱。
数据集实际上是合成的。这是用于生成它的代码,在这里您可以看到分量、它们的频率以及它们的可变幅度:
```
N = 1000
dt = np.zeros(N)
np.random.seed(0)for t in range(N):
dt[t] += 50 * np.random.randn()
a1 = 429 * np.exp(-((t - N / 2) / (N / 10)) ** 2)
p1 = 25
s1 = p1 / 5
dt[t] += a1 * np.sin(2 * np.pi * t / p1 + s1)
a2 = 212 * (np.tanh(5 * (2 * t / N - 1)) + 1)
p2 = 50
s2 = p2 / 7
dt[t] += a2 * np.sin(2 * np.pi * t / p2 + s2 + np.random.randn() / 2)
a3 = 375
p3 = 100
s3 = p3 / 4
dt[t] += a3 * np.sin(2 * np.pi * t / p3 + s3 + np.random.randn() / 10)pickle.dump(dt, open('fft_data.p', 'wb'))
```
具有最短周期的分量具有按照高斯曲线随时间变化的幅度。中间分量的幅度随时间以双曲正切的形式变化。
# 最后的想法
如果数据没有间隙,并且时间维度是均匀的,傅立叶变换就可以很好地工作。否则,您将不得不估算缺失的数据点,填补空白,确保时间维度表现良好。
包含本文中使用的所有代码的笔记本在这里:
[https://github.com/FlorinAndrei/misc/blob/master/fft.ipynb](https://github.com/FlorinAndrei/misc/blob/master/fft.ipynb)
感谢阅读!