TowardsDataScience-博客中文翻译-2020-三十五-
TowardsDataScience 博客中文翻译 2020(三十五)
数据分析到 Web 应用程序:简化 it 变得简单
我们展示了使用 Streamlit Python 包部署数据分析和进行交互式机器学习是多么容易。

图片来源: Unsplash
数据(分析/毫升)到应用程序—零痛苦
我们都想展示我们的数据分析技能。我们都想把这个很酷的机器学习模型包装在一个闪亮的包装中,并作为一个应用程序呈现给全世界。
如何将自己从 Jupyter 笔记本的二维世界中解放出来,向外界提供你的数据科学模型/管道?
细流 让它发生。无痛。
它用最少的代码从数据(分析或机器学习)过渡到一个闪亮的应用程序,几乎不需要学习和部署 web 服务框架(如 Flask 或 Django )。
数据科学家可以在实时网络服务器上测试和展示他们的模型或统计分析,同时摆弄数据和算法。
要了解更多关于这个伟大的 Python 包的历史和起源,请观看他们的 CEO 和创始人的系列视频。我发布的只是第一个视频链接,你应该看这个系列的所有四个视频。
我们都想把这个很酷的机器学习模型包装在一个闪亮的包装中,并作为一个应用程序呈现给全世界。
在本文中,我想介绍该框架的一些重要基础知识,让您立即开始创建数据驱动的应用程序之旅!
核心工作流程
安装
当然,您安装了 Streamlit。它正在快速更新。因此,建议使用— U。
pip install -U streamlit
创建第一个应用
他们有一个 Hello World 类型的应用程序供你尝试。但是当你可以编码的时候,为什么还要为此烦恼呢?为什么不用自己的数据/数学技能创建自己的第一个应用呢?
我们将创建一个简单的 web 应用程序来检查给定的数字是否是质数。
打开你最喜欢的 IDE/文本编辑器,输入…

我们可以将脚本保存为is_prime.py。然后,进入终端(命令提示符)运行这个应用程序,
streamlit run is_prime.py
你会看到一个网络服务器自动开始为你的应用服务!在终端中,您会看到类似这样的内容,

端口号可能会有所不同,这取决于运行的其他本地服务器以及它们如何使用特定端口。
数据科学家可以在实时网络服务器上测试和展示他们的模型或统计分析,同时摆弄数据和算法。
查看您的第一个应用并与之互动
你可以打开浏览器,进入localhost:8502。你会看到一些很酷的东西,像这样,

一个简单的小数学应用程序,包括标题和 HTML 格式的文本等等——不错!
我们是如何生成这个应用程序的?
那么,它们是从哪里来的呢?当然是从您的 Python 脚本中。让我们一段一段地重温这段代码,

因此st.title()函数创建了标题(基本上是一个 H1 HTML 标签)。
之后,我们在那些"""..."""标签中写了一段简单的降价。你可以在这些三重引号内放置任何降价,它们会呈现出美丽的效果。当然,它们遵循的降价语法与您在 Jupyter 笔记本降价单元格或 Github repo 的Readme.md文件中使用的相同。
下一个功能st.header()也是另一个降价。我们放了一个*...*语法来风格化它(斜体)。
下一部分是创建接受用户输入(数字)的文本框。

函数st.number_input()本质上创建了一个 HTML 表单/输入框,期望输入数字类型。默认情况下,它接受浮点数,因此,在下一行中,我们将其转换为int类型(因为我们正在检查输入的素性,它们应该是整数)。
下一个函数st.write()是一个非常强大的通用方法,用于呈现各种各样的对象——从简单的文本到 Pandas DataFrame 和 Matplotlib 可视化。这里,我们只是通过传递一个参数来编写一个简单的文本值,类似于我们传递给 Python print()函数的内容。
到目前为止,这么多代码将呈现如下(没有任何实际的数学计算),

因此,用户只需输入一个数字,然后按回车键。您的代码将处理该输入。
接下来,在您的代码中,有一个简单的 Python 函数,它检查输入数字是否是质数。我们不会谈论这个功能,但让我们看看之后会发生什么。

因此,我们调用该函数并将返回值存储在两个变量中— decision和divisor。然后,我们用一个if-else子句编写两个st.write()函数——第一个简单地指出这个数是质数,第二个告诉这个数是非质数,同时显示最小的除数。同样,请注意我们如何简单地将一个类似 Python 的字符串传递给第二个st.write()函数。
用各种输入测试你的网络应用,看看结果。例如,如果我写 35,它会显示,

如果我写 251,它会显示,

我希望您对我们必须编写的代码流有所了解,以便用 Streamlit 构建简单的数学分析应用程序。
但是我们是数据科学家,我们不仅仅致力于解决数学问题。让我们开始吧!
构建机器学习应用的组件
成分
在我们能够构建一个有意义的机器学习应用程序之前,我们需要知道如何使用 Streamlit 将数据对象/组件放到我们的应用程序中。我们展示了在基于 Streamlit 的应用程序上呈现一些大部分数据组件是多么容易。
Python 脚本位于此处 。你可以下载并运行它。我不会通过重复代码来使文章变得单调,而只会在应用程序上显示结果。
创建格式良好的描述的基本降价
简单的 markdown 语法产生了这种带有多级标题、超链接和项目符号列表的描述。

还有,这个,

显示图像
默认的 markdown 图像标签不适合控制图像大小。所以,我们应该使用st.image()方法来显示图像。
这里有一个来自 Streamlit 网站的截图。图片存放在我的 Github repo 上,我们只是传递 URL。

乳胶渲染
默认的降价已经处理了 LaTeX。我们可以单独使用st.latex()来渲染乳胶含量。

密码
我们可以使用st.code()通过可选的语法高亮来很好地呈现代码块。


原生 Python 对象
列表和字典之类的 Python 对象以一种漂亮的、视觉上吸引人的方式呈现。我们使用通用的st.write()方法进行渲染。




Numpy 数组
Numpy 数组(一维和二维)也可以通过st.write()方法很好地渲染,尽管对于长数组,垂直渲染会变得难以处理。



熊猫数据框
我们可以通过使用st.write()或st.dataframe()方法来渲染熊猫数据帧。

每次页面刷新,代码都会生成新的随机数据,下面的表格也会重新生成。

在数据帧上应用过滤器
我们通过只选择那些A1 > 0 和A3 > 3 的行来过滤数据帧。注意,由于数据帧生成的随机性,不能保证我们每次重新运行代码时都会得到非空的数据帧。

将数据帧写入文件
我们可以很容易地向用户询问文件名,并将过滤后的数据写入该文件。当然,我们必须编写一些代码(例如,用户输入有效性、文件名检查逻辑等。)幕后,但由此产生的 app 界面干净清爽。

从 web 上读取数据文件
从远程托管的文件中读取数据、稍微格式化文件并在 DataFrame 中呈现就像下面的简短代码一样简单,

一个简单的条形图使用熊猫内置的'情节'模块
我们可以处理刚刚从 web 导入的数据集,并调用内置的绘图方法。

这产生了预期的 Matplotlib 驱动的绘图(类似于 Jupyter 笔记本)。

带有 Altair 库的折线图
除了 Matplotlib 之外,Streamlit 还支持许多高级和高度交互式的绘图库。其中之一是 Altair,它构建在 Vega 之上(而 Vega 又构建在无处不在且功能强大的 D3.js 之上)。
我们从数据框中取出一些列,并创建一个折线图。您可以缩放和平移图表,甚至可以看到图表后面的 HTML 代码。请看下面的视频。
除了 Matplotlib 之外,Streamlit 还支持许多高级和高度交互式的绘图库。
小工具魔术
我们可以很容易地用 Streamlit 创建交互性。这是它的主要吸引力之一!
假设我们有一个如下定义的函数,

我们可以只用一行代码创建一个滑块,

我们可以左右移动滑块,函数被动态评估,值可以实时显示。就像网络应用程序的预期行为一样。
函数的 Matplotlib 图
下面的代码使用普通的Matplotlib和一个单个 **Streamlit** 调用 **st.pyplot()** 来绘制上面的函数。
这个图表与上面的牛郎星图表不同,它不是一个动态图表。然而,注意Matplotlib代码包含了相当多的复杂性(甚至标题中的 LaTeX 格式的字符串)。所有这些都由st.pyplot()函数完美地处理。


一个交互式线性回归问题
最后,我们展示了如何使用来自 Streamlit 的简单小部件生成一个噪声水平可调的线性回归数据集。
交互式数据生成
在前两节中,我们介绍了 slider 小部件和 pyplot。在本节中,我们以动态的方式将它们结合起来。

下面,滑块可以调整,以调整噪音的水平。每次你移动滑块,你基本上会产生一个新的线性回归问题(具有相同的特征,但观察数据略有不同)。
下图显示了动态更新的数据与特性图,以说明这一点。
移动“噪音标准。dev”滑块从左端到右端,观察对观察数据的影响。当你向右移动滑块时,你是否看到观察到的数据变得更嘈杂?
以交互方式拟合模型!
接下来,我们用我们的数据拟合著名的scikit-learn包中的LinearRegression()模型,并显示模型系数和 R 度量。
请注意,随着新问题的产生,它们会有轻微的变化。注意,我们选择 a1 = 2.5,b1 = 5,估计值应该接近这些数字。
噪声平均值主要影响偏置项,而噪声标准差。dev 主要影响线性系数。您还会注意到,随着噪声 std 的增加, R 得分通常会降低。dev 增加,即线性模型很难解释观察到的数据中的方差(如果噪声的扩散很大)。
所有这些线性回归的东西并不新鲜。但是请注意使用一个实时 web 应用来适应众多模型(对应于动态生成的数据集)的建模练习看起来是多么容易,只需操作几个滑块!
摘要
暂时就这样了。然而,我相信你已经知道这个库有无限的可能性。
您可以在后端创建真正复杂的数据分析和机器学习管道(使用 Jupyter Notebook 或复杂的 Python 模块网络,无论您喜欢什么),并以最小的编码开销在一个简单、实时的 web 应用程序中呈现所有输出结果和可视化效果。
接下来,我计划构建基于 Streamlit 的应用程序,在后端进行更复杂的数据处理和可视化,并在我的媒体页面上与您分享。
敬请关注。
…使用实时网络应用进行建模练习看起来是多么简单,只需操作几个滑块就能适应众多模型(对应于动态生成的数据集)!
A lso,你可以查看作者的 GitHub 知识库获取机器学习和数据科学方面的代码、思想和资源。如果你和我一样,对人工智能/机器学习/数据科学充满热情,请随时在 LinkedIn 上添加我或在 Twitter 上关注我。
[## Tirthajyoti Sarkar - Sr .首席工程师-半导体、人工智能、机器学习- ON…
通过写作使数据科学/ML 概念易于理解:https://medium.com/@tirthajyoti 开源和…
www.linkedin.com](https://www.linkedin.com/in/tirthajyoti-sarkar-2127aa7/)
数据和决策模型——如何在数据科学项目中使用影响图?
逐步构建影响图的方法

价值链——概述
“价值链”是一个广泛使用的术语,它定义了五个关键领域,即需求分析、设计、实现、测试和演进。几个这样的流程模型与数据科学相关,但是没有正确的答案来说明哪一个是最好的。CSIRO、Pivotal(一家大数据公司)等多个组织以及 Miller 和 Mork 等作者提出了不同的价值链模型,以满足数据科学项目的需求。他们提出的模型没有明显的不同,但都是定制的,以满足不同的业务需求。下图说明了 Miller 和 Mork (2013)提出的数据模型。

数据科学项目的价值链改编自 IT Professional,Miller 和 Mork (2013 年)的《从数据到决策:大数据的价值链》
价值链—关键活动
简而言之,价值链通常被描述为一系列为项目创造价值的活动。这些活动包括从多个来源收集数据、清理和争论、与现有系统集成、分析关键绩效指标,以及最终展示结果以推动与组织目标一致的业务价值。数据科学家在所有领域都扮演着关键角色,但是在较大的组织中,这些角色通常是预定义的,并且不会重叠。例如,像 Novartis Health Care Pvt. Ltd .或 Common Wealth Bank,Australia 这样的大型制药和银行公司在一个数据科学项目中有多个预定义的角色,在该项目中,数据科学家需要分析数据并仅向不同的业务利益相关方提供关键陈述。
影响图
在制定和分析问题陈述时,数据科学家需要了解影响业务决策的关键杠杆。一般来说,涉众不熟悉数据模型或统计,因此存在模型结果可能与他们的业务直觉不一致的情况。这就是影响图出现的地方。影响图是不同的已知和未知变量如何影响商业决策的可视化展示,商业决策反过来又控制着结果。影响图可以让你对以下内容有一个 360 度的了解。
- 一个人可以从建立模型中获得的价值
 - 对项目至关重要的附加信息
 - 获取这些附加信息的成本
 

使用清晰图表开发的风险评估模型的影响图。这张影响图是在解决来自 Kaggle 的风险评估问题之前准备的垫脚石。
保诚金融公司是美国最大的保险公司之一。最近,他们观察到由于不正确的保险报价导致的大量客户流失。人寿保险和年金部门的利益相关者希望确定影响风险评估的驱动因素,以及它们如何满足不同的业务目标。影响图被开发来识别问题陈述的关键区域和杠杆,它们如何重叠以实现共同的业务目标。
影响图的组成部分
已知变量
已知变量代表数据科学家在项目开始时已知的度量。这包括对问题至关重要的数据源和属性、现有的性能指标、业务直觉等等。在上面的示例中,节点“历史客户数据”、“申请人客户数据”和“现有业务”是已知变量。

机会变量
机会变量表示在项目开始时未知的任何度量。它可能包括对模型至关重要的变量、对市场的商业理解、从外部来源获取的数据等。重要的是要明白,机会变量的值总会在未来被发现。在上面的例子中,“预测风险评估”、“市场份额”和“客户群”是机会变量。当仔细观察时,人们会发现市场份额只有在竞争对手的数据可用时才能估计出来。竞争对手的数据可以从外部来源获得,因此这个变量的值在项目开始时是未知的。

决策变量
决策变量由决策者来表示。它说明了不同的已知和未知变量如何影响商业选择,以及什么样的选择受到影响。在上图中,“保险报价”、“保险产品开发”和“营销渠道”是受数据科学项目期间研究的已知和未知变量影响的关键决策。

客观变量
目标变量被定义为数据科学项目想要推动的可能结果。目标变量应该与业务目标一致,并且属于受多个决策变量影响的更大范围。

如何制定影响图?
- 确定项目所需的所有可能的变量集
 - 与利益相关者或数据工程和管理团队讨论不同变量的可用性
 - 从讨论中找出已知变量和偶然变量
 - 理解机会变量对项目或模型开发的影响。如果影响很大,就采购流程和所涉及的成本进行讨论
 - 分析受项目影响的所有业务决策
 - 使用在线工具将这些变量放到适当的位置,得出最终的影响图
 
摘要
影响图的数学理论旨在帮助理解各种可能性和成本如何协同工作。影响图通常被归类为解决问题的艺术。它教会我们认识问题中的关键变量、目标、已知和未知因素,以及不同的决策是如何被影响以达到共同目标的。
参考
H.G. Miller 和 P. Mork,“从数据到决策:大数据的价值链”,载于《IT 专业人员》,第 15 卷,第 1 期,第 57-59 页,2013 年 1 月至 2 月,doi: 10.1109/MITP.2013.11。
关于作者:高级分析专家和管理顾问,帮助公司通过对组织数据的商业、技术和数学的组合找到各种问题的解决方案。一个数据科学爱好者,在这里分享、学习、贡献;你可以和我在 上联系 和 上推特;
数据反模式—导入宏

作者照片
大多数反模式都是从堆栈溢出或者更好的 Github 开始的。假设我需要将数据导入到我的分析中,并且我想要获得数据的最快方法。代码片段和电子表格的世界让我可以毫不费力地导入数据和生产数据产品。
什么是数据反模式?它们是看起来合理的解决方案,但是可能不可伸缩、不安全、引入了质量问题,或者对良好的数据治理有所冒犯。
没有人打算实现反模式。说选举快到了;确实是!我需要一些数据来分析。
与其麻烦数据工程师加载我需要的数据,为什么不在 Github 上找到一个电子表格宏,自己把它导入到我的模型中呢?
我使用著名的数据源 FiveThirtyEight,并将我需要的投票数据嵌入到我的电子表格中。
=ImportCSV("[https://projects.fivethirtyeight.com/polls-page/senate_polls.csv](https://projects.fivethirtyeight.com/polls-page/senate_polls.csv)")
反模式已实现。我有数据。它很小,所以加载很快,我可以开始我的分析。以下是一些问题:我阻止了别人检查或监控我的数据。我也排除了自己跟踪这些数据的演变。
怎么修?首先,中转位置应该是共享的、可靠的和安全的。在 AWS 中,暂存 S3 的数据。在 Azure 中,它将是 blob 存储。在谷歌上,它将是一个云存储桶。
电子表格不能代替数据库。确定数据库是否足够好的关键语句是,“它支持 COPY 语句吗?”Postgres 将扩展到万亿字节级别,而像雪花这样的数据库允许您将数据处理与数据存储分开。
遵循以下最佳实践:
- 创造一个舞台
 - 将数据复制到 Stage 表中,表名为第行的唯一性,并且不要删除或覆盖该数据
 
copy into OWLMTN.STAGE.SENATE_POLLS (FILENAME, 
                                     FILE_ROW_VARCHAR,
                                     question_id, ...        
                                     candidate_party, 
                                     pct
    )
    from (
        select METADATA$FILENAME        filedate,
               METADATA$FILE_ROW_NUMBER filename,
               t.$1, ...
               t.$37,
               t.$38
        from @owlmtn.stage.FIVE_THIRTY_EIGHT_POLLS t
    )
    pattern = 'stage/fivethirtyeight/polls/SENATE_POLLS_.*\.csv'
    on_error = continue
    force = false
    file_format = (field_optionally_enclosed_by = '"'
        type = 'csv'
        field_delimiter = ','
        skip_header = 1
        encoding = 'utf-8');
结论
反模式通常只有在大范围内才变得可见。来自 Stack Overflow 或 Github 的解决方案会给数据基础设施带来严重的操作问题。在解决数据问题时,利用您的组织基础设施。如果没有,就从一个支持 COPY 的可靠的 SQL 数据库开始。
在 FiveThirtyEight 选举数据的情况下,反模式会将选举数据带入我的电子表格,但是这些数据很快就没用了。通过将数据存储在关系存储中并保留所有数据,我可以在 11 月 3 日之后使用历史数据来验证模型。
用于端到端语音翻译的数据增强
如何利用音频和文本增强技术解决数据匮乏问题

亚历山大·辛恩在 Unsplash 上的照片
E 端到端(或直接)语音翻译是近年来备受研究界关注的一种语音翻译方法。它包括使用单个深度学习模型,该模型学习以端到端的方式生成输入音频的翻译文本。它的流行是由于实现这一困难任务的科学兴趣,也是由于实际应用中的预期效果。
我们如何为 IWSLT 2018 评估活动构建我们的端到端语音到文本翻译系统。
使用单一模型很有吸引力,原因有很多:
- 用单个模型解码比用(至少)自动语音识别(ASR)和机器翻译(MT)系统的流水线解码更快。
 - 缺少转录步骤可以防止早期不良决策的传播(错误传播),可能会导致较高的质量。
 - 单个系统比级联系统更易于管理和使用,并且在部署时可以节省内存和 GPU 资源。
 
这有一个大问题。端到端的语音翻译需要来自 ASR 和 MT 的不同数据,虽然这两项任务已经研究了几十年,并且有大量数据可供他们使用(至少对于某些语言来说),但这种新方法很少公开可用。在 ST 中,我们只有几十万个资源最好的语言的段对,而神经机器翻译系统(一个更简单的任务,因为输入是文本的)通常在几千万或几亿个句子对上训练。
那么,这么小的数据,怎么训练一个系统呢?到目前为止,答案是数据扩充:通过现有数据的转换创建合成数据。
数据增强是深度学习中常用的技术,因为这种方法以数据饥渴而闻名,模型可以通过添加数据来显著提高质量。经典的方法是改变输入样本,同时保持其类别标签不变。计算机视觉的一个例子是旋转图像:当从不同的角度观看时,输入图像会不同,但是内容是相同的。狗还是狗,猫还是猫,虽然是轮换的。这里可以找到一个实际的例子:
[## 数据扩充:用几行 Python 代码增强您的影像数据集
为了表现良好,图像分类器需要大量的图像进行训练。深度学习算法可能无法分类…
medium.com](https://medium.com/@thimblot/data-augmentation-boost-your-image-dataset-with-few-lines-of-python-155c2dc1baec)
在这篇文章中,我想重点介绍文本和音频增强技术,这些技术已被提议用于语音翻译,但也可用于涉及这些类型数据的其他任务。显然,旋转和移动像素是两种不适用于文本和音频的技术,因此我们需要更复杂的技术,有时涉及其他机器学习系统的使用。
音频增强
第一种方法类似于图像:改变输入但保留标签。ASR 社区广泛使用的一种方法是速度扰动,它包括使用像 SoX 这样的工具来扰动音频速度,同时保持翻译固定。例如,它被用于在 IWSLT 2019 [1]上的获奖作品,这是一个关于语音翻译的国际研讨会,每年都组织一次比赛。一种常见的做法是将速度(或持续时间,相当于我们的目的)乘以一个范围在[0.9–1.1]内的随机因子,这通常会产生一个仍然类似人类的音频,但听起来与原始音频不同。这种转换通常在数据集构建时离线应用。
另一种音频转换发生在在线。只有某些类型的转换可以在线应用,因为当前的语音翻译系统接收的输入是频谱图,而不是波形。为了在训练期间占用更少的磁盘空间并节省计算时间,数据集通常存储为光谱图,这需要计算功率并且比波形更紧凑。

同一话语的波形(上图)和声谱图(下图)。波形是时间序列,而声谱图就像一个矩阵:x 轴代表时间,y 轴代表频率。
SpecAugment [2]是去年提出的一种流行的谱图增强技术,并取得了巨大的成功。它包括三个步骤:
i)时间弯曲是一种复杂且计算昂贵的算法,它沿着时间轴移动声谱图的一部分; ii)频率掩蔽应用水平掩蔽,其覆盖整个时间维度的一些频率; iii)时间屏蔽应用垂直屏蔽,覆盖一些相邻时间步长的所有频率。时间和频率掩蔽是 SpecAugment 的两个最有效的组成部分,基本上迫使模型预测目标序列,同时对音频的一些频率或部分充耳不闻。这两种类型的遮罩在每次迭代中都有不同的宽度和位置,因此模型可以学习使用它们。

应用于原始输入的 SpecAugment(最上面的图像)。来自 SpecAugment 论文[2]
Nguyen 和他的同事最近提出了一个类似的想法,以在线方式干扰音频速度。他们的方法称为时间拉伸将输入频谱图划分为固定宽度的窗口,并使用从(0.8–1.25)中选取的不同随机因子收缩或拉伸每个窗口。利用这种技术,每个谱图将具有以不同且对比的方式随时间扰动的窗口,并且根据作者,它可以代替离线速度扰动。
迁移学习
在任务之间传递知识的最直接的方法,通常是当两者中的一个有更多的数据可用时,就是所谓的预训练。首先,在大资源任务上训练一个模型,然后对第二个任务使用相同的深度学习架构,并用从第一个任务中学习到的权重初始化权重。这正是将 MT 和 ASR 系统的知识转移到直接 st 系统的第一批方法之一[4,5,6]。使用将用于 direct ST 的相同架构(至少编码器端)训练 ASR 系统。使用将用于 direct ST 的相同解码器架构训练 MT 系统。最后,使用 ASR 中学习的编码器权重和 MT 中学习的解码器权重初始化 direct ST 系统。这种方法导致更快的收敛和更好的翻译质量,但是,解码器预训练似乎不如编码器预训练有效。为了克服这个问题,Bahar 等人[7]表明,如果在预训练的编码器之上再加一个“适配器”编码器层,解码器预训练会更有效。
两级解码
Kano 等人[8]提出了两阶段解码,作为更好地使用预训练组件的方法。它是一个由三个部件组成的网络,一个编码器和两个级联的解码器。第一个解码器生成源语言的句子,类似于 ASR 系统,而第二个解码器生成目标语言的文本。第二解码器利用第一解码器的状态计算其注意力,就在它们被用于选择输出符号之前。在这个意义上,两级解码类似于级联系统,但是它没有离散化源序列以防止错误。为了提高效率,从预训练的 ASR 和 MT 模型初始化两阶段解码模型。Sperber 等人[9]提出了一个“注意力传递”模型,该模型改进了两阶段解码模型,以便进行更有效的预训练。它们识别两级解码中的问题,因为它将第一解码器输出作为注意力输入传递到第二解码器。解码器状态已经包含选择要生成的下一个字的信息,然后一种形式的错误传播再次出现在模型中。为了克服它,他们提出使用由第一解码器和编码器之间的注意力产生的上下文向量作为第二解码器注意力的输入。这样,他们假设第二解码器直接连接到相关的音频部分,并且第一解码器做出的一些早期决策不会引入错误。通过在同一训练中涉及 ASR、ST 和 MT 的多任务学习的巧妙方案,该模型似乎更具数据效率。

级联、直接 ST、注意传递模型和两阶段解码模型的图示比较。鸣谢:Sperber 等人
知识蒸馏
如果你的数据被组织成三元组音频-抄本-翻译,那么机器翻译模型的知识可以通过知识提炼转移到直接的机器翻译模型。对于每个三元组,音频作为直接 ST 模型的输入,抄本作为 MT 模型的输入,然后直接 ST 模型根据 MT 模型生成的分布而不是基础事实进行训练。这种训练在某些方面是有用的:1)MT 模型生成的软分布比 one-hot ground truth 更容易学习;以及 2)MT 分布还包含 MT 模型知道但可能不存在于 ST 训练数据中的符号之间的一些关系。这样,直接 ST 模型可以学习比训练数据中存在的更大的词汇[11]。
监管不力
贾等人[12]提出使用现有系统为其他任务创建合成并行音频翻译数据:1)当只有音频抄本数据可用时,使用机器翻译系统将抄本翻译成目标语言;2)当只有并行的源-目标文本可用时,使用文本到语音(TTS)系统来生成源音频。使用这种方法,直接 ST 的训练数据可以增加几个数量级,并且用于这些任务的系统的质量确保数据是高质量的。他们还表明,使用 MT 比 TTS 更有效,可能是因为合成数据与真实条件下的人类语音不太相似。Pino 等人[13]也证实了类似的结果,他们还表明,这种数据扩充优于所有其他提出的方法,在某些情况下,也使得预训练无用。
多语言 ST
数据扩充的最后一项技术是多语言化。由于多语言机器翻译提高了低资源语言的翻译质量,Inaguma 等人[14]和 us [15]在两项平行工作中提出利用不同语言的数据。目标有两个:1)更多的数据来训练音频编码器,以及 2)类似语言之间的正向传输,这些语言可能具有类似的语法或相同的单词,如英语和法语。这两项研究的结果都是积极的,但是当使用其他数据增强技术时,是否也能保持多语言培训的收益还有待观察。
结论
对于直接 ST,已经提出了许多技术来利用比该任务可用的少数数据更多的数据。我个人建议建立一个最先进的系统,始终使用用强 ASR 模型预训练的编码器,通过用强 MT 系统生成合成翻译来扩充训练集,并在训练期间使用 SpecAugment。在我们的实验中,这种组合总是有效的,或者至少不会造成伤害。其他技术也是有用的,但当与其他方法结合使用时,它们的有效性会降低,如果它们增加了训练时间,这可能是一个问题。
如果你现在正在接近这个领域,而且如果你在基于音频和/或文本的相关领域中工作,我希望这种对直接 ST 的现有数据扩充方法的综述是有用的。特别是,通过使用针对其他任务的更多数据训练的其他组件生成数据,或者使用扭曲原始数据的在线增强技术,可以产生巨大的改进。
如果您对 direct ST 感兴趣,但不知道从哪里开始使用它,请查看我的教程:
使用 Pytorch,您只需几个步骤就可以翻译英语演讲
towardsdatascience.com](/getting-started-with-end-to-end-speech-translation-3634c35a6561) [## 阅读和撰写 ML 研究论文的技巧
从几十次同行评审中获得的经验教训
towardsdatascience.com](/tips-for-reading-and-writing-an-ml-research-paper-a505863055cf)
参考
[1] Potapczyk,Tomasz 等人(2019)。三星用于 IWSLT 2019 端到端语音翻译任务的系统。IWSLT 2019 会议录。
[2] Park,Daniel S .等人,“SpecAugment:一种用于自动语音识别的简单数据扩充方法”继续进行。散客 2019(2019):2613–2617。
[3] Nguyen,Thai-Son 等,“用动态数据增强改进序列间语音识别训练” arXiv 预印本 arXiv:1910.13296 (2019)。
[4] Weiss,Ron J .等,“序列到序列模型可以直接翻译外国语音。” Proc。散客 2017(2017):2625–2629。
[5] Bérard,Alexandre 等,《有声读物的端到端自动语音翻译》 2018 IEEE 声学、语音和信号处理国际会议(ICASSP) 。IEEE,2018。
[6] Bansal,Sameer 等人,“高资源语音识别的预训练改善低资源语音到文本的翻译。”NAACL-HLT 会议录。2019.
[7]巴哈、帕尼尔、托拜厄斯·比施克和赫尔曼·内伊。“端到端语音到文本翻译的比较研究”ASRU 会议录。(2019 年 a)。
[8] Kano,Takatomo,Sakriani Sakti 和中村聪。"面向端到端英日语音翻译的结构化课程学习."(2017).
[9] Sperber,Matthias 等人,“鲁棒和数据高效的端到端语音翻译的注意力传递模型”计算语言学协会汇刊7(2019):313–325。
[10]刘,,等.《端到端语音翻译与》过程。散客 2019(2019):1128–1132。
[11]辛顿、杰弗里、奥里奥尔·维尼亚尔斯和杰夫·迪恩。"从神经网络中提取知识." arXiv 预印本 arXiv:1503.02531 (2015)。
[12]贾,叶,等.“利用弱监督数据改进端到端语音到文本的翻译”ICA ssp 2019–2019 IEEE 声学、语音和信号处理国际会议(ICASSP) 。IEEE,2019。
[13] Pino,Juan 等人,“利用间接训练数据进行端到端自动语音翻译:交易技巧”第十六届国际口语翻译研讨会论文集。2019.
[14] Inaguma,Hirofumi,等,“多语言端到端语音翻译”《ASRU 论文集》 (2019)。
[15]迪甘吉、马蒂亚·安东尼诺、马泰奥·内格里和马尔科·图尔奇。“一对多多语言端到端语音翻译。”ASRU 论文集(2019)。
医学图像中的数据增强
实践教程
如何通过重塑和重采样数据来提高视觉模型的性能

机器学习的普及以奇妙的方式改变了我们的世界。机器学习的一些著名应用允许我们做以前不可想象的事情,比如确定一幅图像是不是热狗。

截图来自 HBO 在《硅谷》节目中“SeeFood Technologies”开发的 Not Hotdog 应用。
随着 TensorFlow 和 PyTorch 等开源神经网络框架的发布,开发图像识别和分类应用程序的便利性在过去几年得到了简化。这些神经网络框架的使用是基于标记的训练数据的可用性,这在云基础设施中变得更加容易访问。神经网络需要大量的数据来适当地加权各层之间的函数。然而,在医学成像等领域,大量标记的训练数据并不总是可用的。对于那些对医学成像数据感兴趣的人,可以在 Giorgos Sfikas 的 GitHub 找到大量资源。在 Neptune.ai 上可以找到关于数据增强技术和工具的一个很好的资源。
如何有效地训练一个神经网络,用有限的训练数据对医学图像进行分类。一个答案是增加你已经有的标签数据,并将转换后的图像输入到你的模型中。扩充有两个目的。首先,理论上来自增强的附加标记训练数据将提高您的图像分类模型准确性【警告!!!会导致过度拟合】。第二,转换将允许模型在方向变化上进行训练。当在测试或真实世界数据中遇到微妙的变化时,可能提供模型灵活性。
它真的有用吗?
以下是经过数据增强和未经数据增强训练的模型的准确性。我将在本文后面更详细地介绍这些结果。

使用不同形式增强的 x 射线多类分类的性能高于随机的类别数涉及大于 0.5 的曲线下面积(AUC)分数。图片作者。
一个小训练集的不错的改进。我只使用了 40GB 总数据中的 2GB 来训练模型。数据增强让我想起了半监督学习,因为你正在创建新的标记数据来训练模型。数据扩充也类似于过采样技术。对于那些有兴趣了解更多关于半监督方法的人,请查看下面这篇由 Andre Ye 撰写的文章。
为什么半监督学习是 ML 的未来
towardsdatascience.com](/supervised-learning-but-a-lot-better-semi-supervised-learning-a42dff534781)
数据扩充最常用于图像。数据扩充有两个主题。第一个是图像转换,第二个是合成图像创建。出于本文的目的,我将主要关注使用 python 在医学成像中的图像转换应用。本演示中使用的部分代码改编自 deeplearning.ai 的《医疗诊断人工智能》课程。代码库可以在 GitHub 上找到,用于建模的数据可以从 NIH 临床中心胸部 x 光数据库中获得。
我们如何执行数据扩充?
python 中的图像操作可以使用多个库来执行。 PIL 和增强器是两个可以直接在图像上操作的库的例子。Augmentor 还包括一个流水线功能,可以一次处理多个图像。出于本文的目的,我利用了 keras _ 预处理的一部分 ImageDataGenerator 。图像增强的类型包括旋转、裁剪、缩放、颜色范围变化、灰度和翻转。增强器,还包括一个随机噪声分段创建对象检测模型。执行任何类型的数据扩充时,请务必记住模型的输出以及扩充是否会影响最终的分类。例如,在 X 射线数据中,心脏通常在图像的右侧,然而下图显示了水平翻转增强无意中产生了一种医学状况,称为 situs inversus。

如果位置很重要,数据扩充可能会产生分类标签问题。黄色圆圈突出心脏。这是水平翻转的同一个图像。图片作者。
本文中使用的数据扩充
出于本文的目的,我使用了三个级别的数据扩充。首先,我运行了一个没有任何增强图像的模型。接下来,我使用了基本的颜色正常化增强。最后,我使用复杂的增强技术创建了一个模型,比如缩放、旋转和裁剪图像,如下例所示。

复杂增强训练中使用的数据增强示例。图片作者。
实现增强方法(代码)
数据和库
完整代码可以在文章 GitHub 上找到。本教程的数据可以从 NIH 临床中心胸部 x 光数据库中找到。在这个例子中,我只利用了 images_001.tar.gz 中的数据,它被解压缩成大约 5K 的图像(~2GB)。还有,我下载了图片标签为Data _ Entry _ 2017 _ v 2020 . CSV。用于执行数据扩充的库需要 keras 和keras-预处理。我用 conda 安装了这些包。
### Augmentation
from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img### Visuals
import matplotlib.pyplot as plt
import pandas as pd### Modeling
from tensorflow.keras.applications.densenet import DenseNet121
from tensorflow.keras.layers import Dense, GlobalAveragePooling2D
from tensorflow.keras.models import Model
from keras.models import load_model
from keras import backend as K
创建模型时,我遇到了以下错误:
AttributeError: module 'tensorflow.python.framework.ops' has no attribute '_TensorLike'
解决方案:在 keras 导入调用之前添加 tensorflow,如下所示
from tensorflow.keras.applications.densenet import DenseNet121
from tensorflow.keras.layers import Dense, GlobalAveragePooling2D
from tensorflow.keras.models import Model
准备图像和元数据
为了给 x 射线图像分配标签,我需要将元数据中的 condition 列二进制化。这项研究中有 15 个独特的条件:
['Cardiomegaly', 'Emphysema', 'Effusion', 'Hernia', 'Infiltration', 'Mass', 'Nodule', 'Atelectasis','Pneumothorax','Pleural_Thickening', 'Pneumonia', 'Fibrosis', 'Edema', 'Consolidation', 'No Finding']
在 x 光检查中,病人可能有不止一种情况。我使用 scikit-learn 将数据转换成适当的格式,其中包含 14 种条件的二进制值,不包括“无发现”类别。
from sklearn.preprocessing import MultiLabelBinarizer
### Binarise labels
mlb = MultiLabelBinarizer()
expandedLabelData = mlb.fit_transform(df["labels"])
labelClasses = mlb.classes_### Create a DataFrame from our output
expandedLabels = pd.DataFrame(expandedLabelData, columns=labelClasses)
expandedLabels['Images'] = df['Image Index']
expandedLabels['ID'] = df['Patient ID']
我将路径添加到相应的 x 射线图像,作为多列二进制数据帧中的新列。
接下来,为了测试建模性能,我将数据分为训练组(80%)和测试组(20%)。下图显示了训练数据集中类的频率。

训练数据中条件的频率。图片作者。
建造生成器来增强图像
ImageDataGenerator 能够将图像处理成一个生成器对象,以避免将所有图像转换加载到内存中。ImageDataGenerator 也能够直接从熊猫数据帧创建生成器。我用下面的代码构建了生成器:
def get_train_generator(df, image_dir, x_col, y_cols, shuffle=True, batch_size=8, seed=1, target_w = 320, target_h = 320): ### Perform data augmentation here
    image_generator = ImageDataGenerator(rotation_range = 5, shear_range = 0.02,zoom_range = 0.02, samplewise_center=True, samplewise_std_normalization= True)
    ### Create the image generator
    generator = image_generator.flow_from_dataframe(
            dataframe=df,
            directory=image_dir,
            x_col=x_col,
            y_col=y_cols,
            class_mode="raw",
            batch_size=batch_size,
            shuffle=shuffle,
            seed=seed,
            target_size=(target_w,target_h))
    return generator
要更改增强量,通过调整 ImageDataGenerator 中调用的变量来更改分配给 image_generator 的值。要调用该生成器,请使用以下代码行:
IMAGE_DIR = "images/"
train_generator = get_train_generator(training, IMAGE_DIR, "Images", labels)
我还为测试数据构建了一个生成器。
构建深度学习模型
我使用了一个来自 imagenet 的 DenseNet121 架构来预训练模型。
### Pre-trained model
base_model = DenseNet121(weights='imagenet', include_top=False)x = base_model.output### Add spatial average pooling and logistic layer
x = GlobalAveragePooling2D()(x)
predictions = Dense(len(labels), activation="sigmoid")(x)model = Model(inputs=base_model.input, outputs=predictions)
model.compile(optimizer='adam', loss='categorical_crossentropy')### Build model and predict
model.fit(train_generator, validation_data=valid_generator,steps_per_epoch=100, validation_steps=25, epochs = 10)predicted_vals = model.predict(valid_generator, steps = len(valid_generator))
可视化输出
使用 AUC 曲线可视化模型预测。每次迭代的 AUC 值保存在下表中:

按增强状态划分的 AUC 值。图片作者。
我为每种情况和增强状态创建了 AUC 曲线。
import numpy as np
from sklearn.metrics import roc_auc_score, roc_curvedef get_roc_curve(labels, predicted_vals, generator):
    auc_roc_vals = []
    for i in range(len(labels)):
        try:
            gt = generator.labels[:, i]
            pred = predicted_vals[:, i]
            auc_roc = roc_auc_score(gt, pred)
            auc_roc_vals.append(auc_roc)
            fpr_rf, tpr_rf, _ = roc_curve(gt, pred)
            plt.figure(1, figsize=(10, 10))
            plt.plot([0, 1], [0, 1], 'k--')
            plt.plot(fpr_rf, tpr_rf,
                     label=labels[i] + " (" + str(round(auc_roc, 3)) + ")")
            plt.xlabel('False positive rate')
            plt.ylabel('True positive rate')
            plt.title('ROC curve')
            plt.legend(loc='best')
        except:
            print(
                f"Error in generating ROC curve for {labels[i]}. "
                f"Dataset lacks enough examples."
            )
    plt.show()
    return auc_roc_valsauc_rocs = get_roc_curve(labels, predicted_vals, valid_generator)
没有增加

无增强模型的性能。图片作者。
基本增强

具有基本增强的模型的性能。图片作者。
复合扩增

具有复杂扩充的模型的性能。图片作者。
下表总结了使用增强功能的模型的性能:

使用不同形式增强的 x 射线多类分类的性能高于随机的类别数涉及大于 0.5 的曲线下面积(AUC)分数。图片作者。
讨论和结论
在本文中,我介绍了数据扩充的概念,并在一个小型多类识别任务中演示了它的相对性能改进。数据增强是一种有用的工具,可以扩展深度学习模型的可用标记数据量。我描述了一些类型的数据扩充,并介绍了在不考虑分类方向的情况下进行扩充的潜在缺陷。在这个数据集中,复杂的增强在胸部 x 光片中表现不佳。疝通常出现在腹部底部附近的组织中。通过复杂的增强,由于颜色调整或旋转,我可能会改变模型区分疝和周围组织的能力。

显示食管裂孔疝相对位置的图像。图片来自维基百科。
建模只利用了全部可用数据的一小部分。超过 4000 幅训练图像(在复杂扩增中为 24000 幅)时,数据扩增的优势可能更加明显。这篇文章的代码可以在 GitHub 上找到。同样,对于那些对医学成像数据集感兴趣的人来说,可以在 Giorgos Sfikas 的 GitHub 找到大量资源。我的名字是科迪·格利克曼,可以在 LinkedIn 上找到我。一定要看看我下面的其他文章:
一步一步的教程,让你自己的美丽的图像
towardsdatascience.com](/creating-photo-mosaics-using-python-49100e87efc) [## 刮胡子,还是不刮胡子,这是个问题
使用深度学习对有胡须和无胡须的照片进行年龄分类
towardsdatascience.com](/to-beard-or-not-to-beard-that-is-the-question-b46864d7e003) [## 机器学习中的什么或为什么
使用 Python 解释模型的综合指南
towardsdatascience.com](/what-or-why-in-machine-learning-e2a73da528c8) 
旋转增强。图片作者。
YOLOv4 中的数据扩充
YOLOv4 的“秘密”不是架构:而是数据准备。注意:我们也在博客上发布了 YOLOv4 中的数据增强。
号物体探测空间继续快速移动。不到两个月前,谷歌大脑团队发布了用于物体检测的 EfficientDet,挑战 YOLOv3 作为(近)实时物体检测的首要模型,并推动了物体检测的可能性。我们写了一系列的帖子来比较 YOLOv3 和 EfficientDet 、训练 YOLOv3 定制数据、和训练 EfficientDet 定制数据,我们发现了令人印象深刻的结果。
- *点击此处查看我们关于如何在您的自定义数据集上训练 YOLOv4 的教程。
 
现在 YOLOv4 已经发布,显示 COCO 平均精度(AP)和每秒帧数(FPS)分别提高了 10%和 12%。在这篇文章中,我们将看到作者如何通过深入研究 YOLOv4 中使用的 数据增强技术 的细节来实现这一突破。
The founder of Mosaic Augmentation, Glen Jocher has released a new YOLO training framework titled YOLOv5\. You may also want to see our post on [YOLOv5 vs YOLOv4](https://blog.roboflow.ai/yolov5-improvements-and-evaluation/) This post will explain some of the pros of the new [YOLOv5 framework](https://blog.roboflow.ai/yolov5-improvements-and-evaluation/).[YOLOv5 Breakdown](https://blog.roboflow.ai/yolov5-improvements-and-evaluation/)

(引文)
数据增强对于计算机视觉的重要性并不新鲜!请看我们一月份的帖子,解释了 图像预处理和增强对于计算机视觉 有多重要。
YOLOv4 中的一包赠品是什么?
YOLOv4 的作者在他们题为“一袋赠品”的论文中包括了一系列的贡献可以采取一系列步骤来提高模型的性能,而不会增加推理时的延迟。因为它们不能影响模型的推理时间,所以大多数都在训练管道的数据管理和数据扩充方面进行了改进。这些技术改进并扩大了训练集,从而将模型暴露给原本看不到的场景。 计算机视觉中的数据增强 是从您的数据集获得最大价值的关键,最新的研究继续验证这一假设。
计算机视觉中的数据增强
图像增强从现有的训练数据中创建新的训练样本。不可能为我们的模型在推理中可能看到的每一个真实世界的场景真正捕捉图像。因此,调整现有的训练数据以推广到其他情况允许模型从更广泛的情况中学习。
YOLOv4 的作者引用了许多技术,这些技术最终启发了他们的免费包。我们在下面提供一个概述。
变形
光度失真— 这包括改变图像的亮度、对比度、饱和度和噪声。(例如,写于计算机视觉中的模糊数据增强。)

在我们的平台上调节亮度
几何扭曲— 这包括随机缩放、裁剪、翻转和旋转。这些类型的增强可能特别棘手,因为边界框也会受到影响并且必须更新。(例如,我们已经写过如何在计算机视觉中使用随机裁剪数据增强。)

在我们的平台上翻转图像
这两种方法都是像素调整,这意味着原始图像可以通过一系列变换轻松恢复。
图像遮挡
随机擦除— 这是一种数据扩充技术,用随机值或训练集的平均像素值替换图像区域。通常,它是通过改变图像擦除的比例和擦除区域的纵横比来实现的。在功能上,这成为一种正则化技术,它防止我们的模型记忆训练数据和过度拟合。

(引文
剪切— 正方形区域在训练期间被屏蔽。剪切区域仅对 CNN 的第一层隐藏。这非常类似于随机擦除,但是在覆盖的遮挡中有一个常量值。目的是相似的:我们减少过度拟合。

(引文)
捉迷藏— 将图像分成 SxS 补丁网格。以某种概率隐藏每个补丁(p_hide)。这允许模型学习对象看起来像什么,而不仅仅学习对象的单个部分看起来像什么。

(引文)
网格遮罩— 图像区域以类似网格的方式隐藏。类似于捉迷藏,这迫使我们的模型学习构成单个对象的组成部分。

(引文)
混合— 图像对及其标签的凸叠加。(此处纸)

(引文)
YOLOv4 中部署的数据增强策略
现在,我们将访问 YOLOv4 在培训期间部署的数据增强策略。研究过程的特点是一系列的实验,所以我们可以想象作者实验了许多没有进入最终论文的策略。这进一步证明了在定制视觉任务中,在自己的 训练/测试集 上探索各种数据增强策略非常重要。
CutMix — 通过从一幅图像中剪切部分并将其粘贴到增强图像上来组合图像。图像的剪切迫使模型学习基于大量特征进行预测。参见上面的“捉迷藏”,在没有剪切的情况下,该模型专门依靠狗的头部来进行预测。如果我们想准确地识别一只头藏起来的狗(可能藏在灌木丛后面),这是有问题的。在 CutMix 中,剪切部分被替换为另一个图像的一部分以及第二个图像的基本事实标签。在图像生成过程中设置每个图像的比率(例如,0.4/0.6)。在下面的图片中,你可以看到 CutMix 的作者如何证明这种技术比简单的混合和剪切更好。

(引文
拼接数据增强— 拼接数据增强将 4 幅训练图像按一定比例合成一幅。Mosaic 是 YOLOv4 中引入的第一个新的数据增强技术。这允许模型学习如何在比正常情况下更小的尺度上识别对象。它还鼓励模型在帧的不同部分定位不同类型的图像。

(引文)
马赛克数据增强 YouTube 视频!
类别标签平滑— 类别标签平滑不是一种图像处理技术,而是对类别标签的直观改变。通常,边界框的正确分类被表示为类的一个热点向量[0,0,0,1,0,0,…],并且基于该表示来计算损失函数。然而,当一个模型对接近 1.0 的预测变得过于确定时,它通常是错误的、过度拟合的,并且在某种程度上忽略了其他预测的复杂性。根据这种直觉,对类标签表示进行编码以在某种程度上评估这种不确定性是更合理的。自然,作者选择 0.9,所以[0,0,0,0.9,0…]来表示正确的类。
自我对抗训练(SAT)——该技术通过转换输入图像,使用模型的状态来通知漏洞。首先,图像通过正常的训练步骤。然后,损失信号被用于以对模型最有害的方式来改变图像,而不是通过权重来支持。后来在训练中,模型被迫面对这个特别困难的例子,并围绕它学习。在我们这里讨论的技术中,这种技术可能是最不直观的,也是最接近建模的。
🎉现在我们对 YOLOv4 中使用的所有数据增强技术有了一个全面的了解!

(引文
在您自己的计算机视觉项目中使用数据增强
我们很高兴地看到,模型性能的进步与模型架构一样关注数据扩充。在看到 YOLOv4 和 YOLOv3 在数据扩充方面的差异时,我们怀疑这些“免费赠品”技术对任何架构都是有用的。
祝你好运建设!
想把理论付诸实践?试试我们的教程 如何训练 YOLOv4 。
想看看增强技术是如何不断发展的吗?在 YOLOv5 上查看这篇文章。
关于美国治安和种族的有数据支持的文章

数据说明了什么是不公正
距离我上一篇文章已经很久了。我的文章通常不是关于一个有趣的数据集或问题,而是一个统计学习技术或概念的展示。我计划很快回到这个话题,但我想我应该解决一个最近备受关注的话题,但这个话题已经存在了几个世纪;美国的种族与治安。
我想对美国的警察暴力和种族问题做一些探索性的数据分析,并以此为例说明统计学如何应用于重要的社会问题。然后,我认为这是一个坏主意,因为有很多出色的工作是由比我更了解数据生成过程的人完成的,因为他们已经沉浸在数据中多年了。相反,我整理了一些我读过的有趣文章的链接,这些文章集中在警察暴力和种族的数据上。在 2014 年的抗议之后,学术界对这一主题有了更多的关注,但我选择了更容易理解的数据新闻文章。下面是三个链接。
关于警察枪击的数据说明了什么
《自然》上的这篇文章提供了一个关于美国种族和警察杀人的主要数据库的概览。它也关注学术文献中的争论。
在大城市,警察杀死的人越来越少,但是在美国的郊区和农村,警察杀死的人越来越多
Samuel Sinyangwe 是零战役的数据科学家。这篇文章是关于从 2013 年到现在警察杀人和枪击的趋势,主要在城市,郊区和农村层面进行了细分。
为什么统计数据没有捕捉到警察系统偏见的全部程度
这是另一篇讨论分析警察暴力数据困难的特殊原因的文章;在暴力发生前谁遇到了警察的选择偏差。
最后,我想链接到三个关于警察枪击和暴力的主要数据库:致命遭遇、《华盛顿邮报》的致命力量和描绘警察暴力。如果你选择在这个话题上做你自己的数据分析,请记住在数据收集中可能存在的偏见。
警察暴力并不是统计学和计量经济学揭示美国不同种族群体之间差异的唯一领域(见种族财富差距)。《走向数据科学》的大多数读者都非常关注机器学习和预测,我也是其中之一。但我们不能忘记探索性数据分析和统计对于假设检验和推断的价值,当涉及到识别不公正和评估纠正它们的政策时。
关于本文收益的说明
每当这篇文章的收入达到可执行的数额时,我将把它们捐给零号运动。零运动倡导证据和数据驱动的政策,减少警察暴力的发生率,提高美国的警务质量。
电子病历的数据木工(一)
第一部分:数据的形状
电子病历(EMR)中的数据可能很复杂,难以浏览。这一系列文章是为那些希望理解数据分析师做什么并交流他们对数据操作和分析的意图的临床医生而写的。
我们希望数据是什么样的
大多数临床医生都熟悉平面数据。这是一种数据在二维表中的格式,通常每行一个患者,每个属性一列(如患者年龄、实验室值、出院日期)。数据分析师也可能将此描述为整洁的数据。然而,电子病历数据很少像这样结构化!

平面数据:临床医生通常想要什么(图片由作者提供)
患者生成的大多数数据都是通过多个非周期性事件产生的。我们需要考虑如何在数据库中表示它们。

患者时间表示例(图片由作者提供)
真实的数据是什么样的
数据库通常以【长】格式表示数据。在长表格中,变量的每个观察值都有一行。一个变量可以在不同时间进行多次观察(如系列肌钙蛋白)。因此,每个变量可能不止一行,每个患者也可能不止一行。表格之所以“长”,是因为通常行数比列数多。

一张长桌(图片由作者提供)
长表格通常被转换成‘宽’格式。数据集中的每个患者都有一行。该表有多列,代表不同时间点的变量测量值。它“宽”是因为列比行多。这个过程被称为旋转,因为数据被翻转到它的一侧。我们可以理解宽格式几乎就像一条时间线。

宽桌子——由上面的长桌子改造而成(图片由作者提供)
您可能会注意到,宽表中有许多单元格包含空值。空值是空白。这是不定期临床测量的反映,对于每个患者,临床测量不会在完全相同的时间发生。您可能想知道为什么 EMR 数据库不像这样存储数据——这是因为这种结构要求每个时间点都有一个新列,但是该列中的许多值都是空值。就存储而言,这将是非常低效的!
这个表还不够整洁,因为每个变量下有多列。这由两级列标签表示。为了使数据集整洁,我们需要将每个变量折叠成一列。
划界和聚合
要折叠每个变量下的列,我们必须划定相关的时间段,然后汇总该时间段内的观察值。

在 ICU 入院开始和结束之间(定界),平均毛细血管血糖(总量)(图片由作者提供)
界定可确保我们排除与研究无关的时间段。例如,如果我们对一个病人的 ICU 入院感兴趣,我们应该划定入院的开始和结束日期。
聚合是接受几个值,输出一个值的任何规则。医学中常见的聚合规则包括寻找平均值、中值、最大值或最小值以及第一个或最后一个值。
在上面的示例中,我们可能指定了时间 1 到时间 2 的界限,并使用平均值进行了聚合。请注意,Var 3 具有空值,因为从时间 1 到时间 2 没有相关的观察值。这给了我们一个整洁的表格——每个病人一行,每个变量一列!

整洁的桌子(图片由作者提供)
注意:为什么划定一个范围很重要?
当我们想到一个离散事件时,很容易直接指定一个集合(例如,在入住 ICU 之前测量的“最后”肌酐值)。这可能适用于大多数情况,但我们应该小心——如果患者在一年前有“最后”数值(例如,患者从 A&E 直接入住 ICU,入住时尚未报告实验室),该怎么办?强烈建议定界以获得有效和一致的结果!
在这篇文章中,我们了解了电子医疗记录数据是如何构建的,以及我们如何让它变得整洁——从长到宽,通过定界和聚合。请继续关注电子病历数据木工的更多内容!
Python 中的数据类

数据类适用于 Python 3.7 或更高版本。您可以将数据类用作数据容器,但不仅限于此。数据类还为您编写模板代码,并简化创建类的过程,因为它附带了一些免费实现的方法。让我们开始吧!
你的第一个数据类
让我们创建一个数据类,它表示 3d 坐标系中的一个点。
@dataclass decorator 用于创建一个数据类。x、y和z是我们数据类中的字段。请注意,您需要使用类型注释来指定字段的数据类型,并且记住类型注释不是静态类型声明,这意味着某人仍然可以为x、y或z字段传递除int之外的任何数据类型。
默认情况下,数据类带有实现的__init__、__repr__和__eq__方法,因此您不必自己实现这些方法。
然而__init__、__repr__和__eq__没有在我的Coordinate类中实现,由于数据类,我仍然可以使用这些方法。这对节省时间很有好处。
字段的默认值
您可以为字段分配默认值。让我们把重点放在例子上。正如您在pi字段中看到的,您可以为数据类中的字段分配一个默认值。
自定义字段和数据类
您可以通过使用 dataclass decorator 或 field 函数的参数来自定义字段和数据类。当我在例子中定制任何东西的时候,我会解释,我也会在文章的最后给出字段和数据类的所有参数。
数据类是可变的还是不可变的?
默认情况下,数据类是可变的,这意味着您可以为字段赋值。但是,您仍然可以通过将frozen参数设置为True来使其不可变
易变的例子
不可变的例子
当我们将frozen设置为True时,我们不能再给字段赋值了。您可以在下面的示例中看到异常输出。
比较数据类
假设您想要创建一个表示一个Vector的数据类,并且您想要比较它们。你会怎么做?为此,你需要像__lt__或__gt__这样的方法来比较它们。
默认情况下,数据类的order参数为False。当你设置为True时;__lt__、__le__、__gt__和__ge__方法将自动为您的数据类生成。所以你可以比较对象,就好像它们是字段的元组一样。
让我们来看看下面的例子。我们可以比较v2和v1,因为我们将order设置为True。但是这里有一个比较逻辑的问题。当你说v2 > v1时,它会像(8, 15) > (7, 20)一样比较这两个向量。所以v2 > v1的输出会是True。
回想一下,元组比较是逐个位置进行的。它首先将
8与7进行比较,其结果为True,然后比较结果为True。如果它们相等,那么它将比较15>20,然后结果将是False。
回想了一下元组是怎么比较的,很明显这个比较没有任何意义。我想用向量的大小来比较它们。这里的问题是,当创建每个实例时,你不想自己计算一个Vector的大小。
在这种情况下,我们将受益于field函数和__post_init__方法。field功能将帮助我们自定义magnitude字段。__post_init__方法将帮助我们确定初始化后向量的大小。
我们通过使用来自数据类的field函数来定制magnitude字段。通过将init设置为*False*,我们基本上是说我们不想要__init__方法中的magnitude参数。因为我们希望在初始化后使用__post_init__方法来确定它的值
将其转换为字典或元组
你可以在一个元组或字典中得到你的数据类的属性。您所需要的就是从数据类中导入asdict和astuple函数。
遗产
可以像 Python 中的普通类一样对数据类进行子类化。
使用继承时有一个常见的错误。当默认设置lang字段为Python时,必须为lang字段之后的字段提供默认值。
要了解原因,让我们看看我们的__init__方法是什么样子的。回想一下,有默认值的参数应该在没有默认值的参数之后。
让我们通过为salary字段提供默认值来修复它。
从老丨虎丨机中获益
默认情况下,属性存储在字典中。我们可以从插槽中获得更快的属性访问,并使用更少的内存。请注意,我不会详细讨论插槽,因为这是另一个要讨论的主题。
我们可以使用插槽来使用更少的内存和更快地访问属性。
数据类参数
我们已经更改了 dataclass decorator 中的一些参数来定制我们的数据类。让我给你一个参数列表。
init:__init__方法将在您的数据类中生成,如果True。(默认为True)repr:__repr__方法将在您的数据类中生成,如果True。(默认为True)eq:__eq__方法将在您的数据类中生成,如果True。(默认为True)order:__lt__、__le__、__gt__和__ge__方法将在您的数据类中生成,如果True。(默认为False)unsafe_hash:__hash__方法将在您的数据类中生成,如果True。(默认为False)frozen:如果True,则不能分配给字段。(默认为False。)
请注意,如果order为True,则eq必须为True,否则ValueError将引发异常。
字段参数
init:如果True,该字段包含在生成的__init__方法中。(默认为True)repr:如果True,该字段包含在生成的__repr__方法中。(默认为True)compare:如果True,该字段包含在生成的比较和相等方法中。(默认为True)hash:如果True,该字段包含在生成的__hash__方法中。(默认为None)default:如果提供,这将是该字段的默认值。default_factory:如果提供,这必须是一个零参数的可调用函数,当该字段需要默认值时,将调用该函数。metadata:这可以是一个映射,也可以是一个空字典。
结论
这是对数据类的温和介绍。我希望你喜欢它。感谢您的阅读,别忘了在 Medium 上关注我!
数据清理和分析以及额外的故事
人是企业中最关键的部分。人给人创造价值,卖给人。因此,人们及其生活的变化影响着每一项业务。人口特征和人们的生活方式在不久的过去发生了巨大的变化。塑造和定义一个国家人口的关键指标,如生育率、死亡率、预期寿命、肥胖、劳动力职业分布一直在变化。这些变化对于关键业务决策始终至关重要,因为人是所有业务的核心。
Worldbank.org 拥有关于人口的社会和社会经济指标的全面数据集。根据性别统计,不同国家的劳动力、生育率和死亡率、预期寿命、肥胖和人口年龄分布数据均可获得。
[## 性别统计|数据库
选择已被修改。随时单击“应用更改”以使用所做的更改刷新报告…
databank.worldbank.org](https://databank.worldbank.org/source/gender-statistics)
通过使用 worldbank.org 现有的数据,我将试图展示最近发生了什么变化,并解释这些变化。我将更多地关注数据分析部分,所以这更像是一个有奖金故事的数据分析项目。有许多有用和信息丰富的统计数据,但这些数据并不是一种清晰、易于分析的格式。我需要使用 pandas 来为探索性数据分析准备数据,并使用 matplotlib 和 seaborn 来进行可视化。
所有的代码都可以在 Github 上的这里找到。
为分析准备好数据
# Importing necessary libraries
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline# read the data into a pandas dataframe
data = pd.read_csv('data.csv')data.shape
(2237, 19)
初始数据集有 2237 行和 19 列。这些列是国家名称和代码、年份、系列名称和代码。系列名称和代码列描述了数据是什么。我下载了 4 个不同大洲 4 个国家 15 年(2004-2018)的数据。

指标有 500 多个。我的分析计划是使用 25 个指标来比较不同大洲的 4 个不同国家。为了过滤初始数据集,我创建了一个列表,其中包括我要分析的指标的系列代码。然后我用 isin() 方法创建了一个遮罩来过滤初始数据帧。
mask **=** data['Series Code'].isin(code_list)
data1 **=** data[mask]data1.shape
(100, 19)
我们现在有 4 个不同国家 15 年(2004-2018)的 25 个属性。列名可以简化。例如,“2004 [YR2004]”可以写成 2004,国家名称列可以删除,因为国家代码清楚地显示了国家。
data1.columns = ['series_name', 'series_code', 'country_name', 'country_code', '2004', '2005', '2006', '2007', '2008', '2009', '2010', '2011','2012', '2013', '2014', '2015', '2016', '2017', '2018']data1 = data1.drop('country_name', axis=1)
缺失数据
处理缺失值是数据清理的关键步骤。我们首先需要找到缺失的值,然后根据数据的特征和属性决定如何处理它们。对于所有数据集,没有一种最佳的方法来做到这一点。这在很大程度上取决于数据集。
data1.isna().any().sum()
0
我们的数据集中似乎没有缺失数据,但我知道有些单元格没有任何信息。有些行带有“..”这些值实际上是缺失值,但熊猫无法检测出它们是缺失值。因此,目视检查数据集也非常重要。我将使用 dataframes replace() 方法用 NaN 替换这些值。
data1.replace('..', np.nan, inplace=True)data1.isna().sum()
series_name      0
series_code      0
country_code     0
2004            10
2005             9
2006            10
2007            10
2008            10
2009            10
2010             5
2011            10
2012            10
2013             6
2014             5
2015             7
2016             7
2017            16
2018            40
dtype: int64
isna()。any() 返回一个布尔值,如果该列中有任何缺失值,则该值为真。另一方面,是一种()。sum() 将返回一列中缺失值的总数。
下一步是决定如何处理这些丢失的值。2018 列包含 100 个空值中的 40 个,因此我将删除整个列。
data1 = data1.drop('2018', axis=1)
pandas drop()函数的一个重要参数是轴,用于指定列(1)或行(0)。
正如所料,缺少的值大多在同一行中,因为某些属性没有任何特定国家的值,这导致该行中的大多数值都是 NaN。因此,我将根据该行中 NaN 值的阈值删除行。删除 2018 列后,我们有 14 年(2004-2017)的数据,我将使用 70%的阈值。
data1 = data1.dropna(thresh=14*0.7, axis='rows')
之后,还剩下一些缺失的值。可以接受用同一国家前一年的数值来填充这些数值,这不会对结果产生很大影响。为此,我将对行使用带有 ffill 方法的 fillna() 。
data1 = data1.fillna(method='ffill', axis=0)#Make sure no missing values left
data1.isna().sum().sum()
0
值的数据类型是不适于数值分析的对象。因此,我需要更改数字列的数据类型。
years = ['2004', '2005', '2006','2007', '2008', '2009', '2010', '2011', '2012', '2013', '2014', '2015','2016', '2017']for year in years:
    data1 = data1.astype({year:'float'})
我们的数据集现在包括 90 行和 17 列。我的分析最初旨在基于 15 年期间的 25 个不同属性来比较 4 个不同的国家。由于数据不可用,我删除了一些列和行。删除这些行和列后,有些属性没有所有 4 个国家的数据。为了进行全面彻底的分析,我将只使用包含所有 4 个国家数据的属性。
data1.shape
(90, 17)attributes = data1.series_name.value_counts() == 4# Filter attributes with 4 values 
attributes = attributes[attributes.values == True]# Make a list from series index
attributes_list = list(attributes.index)# Use this list as filter
mask1 = data1['series_name'].isin(attributes_list)
data1 = data1[mask1]data1.shape
(72, 17)
我们现在有 4 个不同国家 14 年的 18 个属性。这些属性是:
attributes_list
['Prevalence of obesity, female (% of female population ages 18+)',
 'Life expectancy at birth, female (years)',
 'Employment in services, female (% of female employment) (modeled ILO estimate)',
 'Fertility rate, total (births per woman)',
 'Population ages 15-64 (% of total)',
 'Employment in industry, male (% of male employment) (modeled ILO estimate)',
 'Employment in agriculture, female (% of female employment) (modeled ILO estimate)',
 'Contributing family workers, female (% of female employment) (modeled ILO estimate)',
 'Employment in industry, female (% of female employment) (modeled ILO estimate)',
 'Prevalence of obesity, male (% of male population ages 18+)',
 'Population ages 65 and above (% of total)',
 'Labor force, female (% of total labor force)',
 'Contributing family workers, male (% of male employment) (modeled ILO estimate)',
 'Employment in services, male (% of male employment) (modeled ILO estimate)',
 'Life expectancy at birth, male (years)',
 'Population ages 0-14 (% of total)',
 'Employment in agriculture, male (% of male employment) (modeled ILO estimate)',
 'Death rate, crude (per 1,000 people)']
探索性数据分析
我计划基于三个主要主题来分析这些数据:
- 雇用
 - 肥胖
 - 年龄分布、预期寿命、生育率和死亡率
 
就业
就业属性显示了农业、服务业和工业这三个不同领域中劳动力职业的百分比。我将使用 series_name 列中的描述来过滤这些属性。
Pandas 有许多有用的矢量化字符串操作。我将使用 contains() 方法如下:
employment = data1[data1.series_name.str.contains('Employment')]employment.shape
(24, 17)
4 个国家有 6 个属性:男性和女性在农业、服务业和工业的就业情况。
我将尝试使系列代码更具信息性,并删除 series_name 列,以便更容易分析和可视化。比如 SL。AGR.EMPL.FE.ZS 指农业就业(女性)。我将从这段代码中导出 AGR 和 FE,并使用矢量化字符串操作 split()生成单独的列。然后使用 pandas concat() 函数将结果数据帧与原始数据帧合并:
split1 = employment.series_code.str.split(".", expand=True)
employment = pd.concat([employment, split1], axis=1)

原始列(不显示年份)

从 split()返回的列
# To simplify, drop series_code, 0, 2 and 4
# Rename 1 and 3 to be more informativeemployment = employment.drop(['series_code', 0, 2, 4], axis=1)
employment.rename(columns={1:'field', 3:'gender'}, inplace=True)# New columns
employment.columnsIndex(['series_name', 'country_code', '2004', '2005', '2006', '2007', '2008','2009', '2010', '2011', '2012', '2013', '2014', '2015', '2016', '2017','field', 'gender'],dtype='object')# Can drop series_name as well because field and gender columns
# are enough to describe the data
employment_new = employment.drop('series_name', axis=1)
以列的形式列出年份不便于分析和可视化。因此,我将创建一个 year 列,并将所有年份作为行项目列出。熊猫已经在中内置了()【融化】功能来完成这个任务。
employment_new = employment_new.melt(id_vars=['country_code', 'field', 'gender'],
                   var_name='year',
                   value_name='employment')

就业数据框架的最终版本
让我们看看劳动力职业是如何随着时间的推移而变化的。使用 seaborn lineplot 的色调和风格参数,我们可以在同一个图表上看到男性和女性的每个职业。我还认为,如果图形上有许多线条,最好将图例放在图形之外。下面代码片段的最后一行找到了图例。
sns.set_context("notebook", font_scale=1.5, rc={"lines.linewidth": 2.5})
plt.figure(figsize=(10,6))
ax = sns.lineplot(x='year', y='employment', hue='field', style='gender', ci=None, data=employment_new)
ax.set_title('Labor Force Occupations in General')
ax.set_xlabel('')
ax.set_ylabel('% share')
ax.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)

总的来说,无论男女,超过一半的劳动力从事与服务相关的工作。这并不奇怪,因为与服务相关的工作在零售、运输、医疗保健、分销和许多其他行业无处不在。虽然与服务相关的工作有增加的趋势,但在工业或农业部门工作的人数却在减少。农业是过去的主要职业,但随着生产力的提高和技术带来的便利,农业工作减少了。近期仍有下降趋势。同样,近年来,越来越多的机器参与到工业中,使得大部分工作自动化并由机器完成,这反过来减少了男性和女性的工作岗位。
在劳动力分布方面,国与国之间可能存在差异。下面截取的代码展示了如何为荷兰创建一个线图。同样,只需更改 mask 中的国家代码,我们就可以为其他国家创建相同的可视化效果。
#Labor force occupations in Netherlands
sns.set_context("notebook", font_scale=1.5, rc={"lines.linewidth": 2.5})
maskNLD = employment_new.country_code == 'NLD'
plt.figure(figsize=(10,6))
ax = sns.lineplot(x='year', y='employment', hue='field', style='gender', data=employment_new[maskNLD])
ax.set_title('Employment in Netherlands')
ax.set_xlabel('')
ax.set_ylabel('% share')
ax.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)




有一个有趣的趋势引起了我们的注意。在发达国家,美国和荷兰,劳动职业份额不随时间变化。2004 年和 2017 年的数值差不多。然而,在发展中国家,我们看到了很多变化。
除土耳其外,所有国家的女性都比男性更多地从事与服务相关的工作。我认为这是因为土耳其女性比过去更多地加入了劳动力大军。2015 年后,服务领域女性份额超过男性份额。
Seaborn 允许我们通过提供许多参数和选项来定制可视化。例如,我们可以在同一个图形上使用色调、风格和大小参数来可视化不同的类别。我用色调和风格来区分职业和性别。另一方面,有时在同一个图表上显示不同的类别并不是一个好的选择,因为它看起来很复杂,很难阅读。在这种情况下,我们可以通过使用子图在一个可视化图形上绘制多个图形:
# Create masks to filter employment dataframe
mask00 = (employment_new.field == 'AGR') & (employment_new.gender == 'MA')
mask01 = (employment_new.field == 'AGR') & (employment_new.gender == 'FE')fig, axs = plt.subplots(ncols=2, figsize=(18,6))
sns.set_context("notebook", font_scale=1.3, rc={"lines.linewidth": 2.})
sns.lineplot(x='year', y='employment', hue='country_code', data=employment_new[mask00], legend=False, ax=axs[0])
axs[0].set_title('Male Employment in Agriculture')
axs[0].set_ylabel('% Share')
axs[0].set_xlabel('')
sns.lineplot(x='year', y='employment', hue='country_code', data=employment_new[mask01], ax=axs[1])
axs[1].set_title('Female Employment in Agriculture')
axs[1].set_ylabel('')
axs[1].set_xlabel('')
axs[1].legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)

农业工作
上面的图表也显示了土耳其和中国农业就业的下降趋势,而美国和荷兰的农业就业份额保持稳定。
肥胖
我使用 str.contains() 函数从初始数据帧中过滤肥胖数据:
obesity = data1[data1.series_name.str.contains('obesity')]
应用同样的步骤,我创建了肥胖数据框架:


每个国家的肥胖程度不同,但它们有一个共同点:肥胖正在增加。这对我们的健康绝对不是一个好兆头。土耳其的一个有趣的区别是,女性的肥胖率远远高于男性,而在其他国家,女性和男性的肥胖率非常接近。
年龄分布、预期寿命、生育率和死亡率
初始数据集具有许多与人口统计学相关的属性。我将尝试了解我们的数据集中包括的 4 个不同国家的总人口年龄组、死亡率、生育率和出生时预期寿命。
通过对初始数据框架应用与就业和肥胖相同的步骤,我获得了 4 个不同的数据框架:年龄分布、预期寿命、生育率和死亡率。
为了简单起见,并且能够更容易地比较一些属性,我将把这些数据帧合并成一个。Pandas 内置的 merge() 函数使得合并数据帧变得非常简单。数据帧的共同点或您想要组合数据帧的条件由' on 参数指定:
population_new = pd.merge(population, life_exp, on=['country_code','year'])
应用 merge() 函数后,最终数据帧如下:

世界人口正在老龄化。据世界卫生组织(世卫组织)称,世界人口老龄化是生育率持续下降和预期寿命延长的结果。这种人口结构的变化导致 60 岁以上人口的数量和比例不断增加。因此,历史上第一次老年人比年轻人多的时代正在迅速到来。
让我们用现有的数据来证实这些:

如上图所示,14 岁及以下的人口在减少,而 65 岁及以上的人口在增加。这一趋势适用于我们数据中包含的所有国家。
mask1 = population_new.ages == '0014'
mask2 = population_new.ages == '65UP'fig, axs = plt.subplots(ncols=2, figsize=(20,6))sns.lineplot(x='year', y='share', hue='country_code', data=population_new[mask1], legend=False, ax=axs[0])
axs[0].set_title('14 and under')
axs[0].set_ylabel('% Share')
axs[0].set_xlabel('')sns.lineplot(x='year', y='share', hue='country_code', data=population_new[mask2], ax=axs[1])
axs[1].set_title('65 and UP')
axs[1].set_ylabel('')
axs[1].set_xlabel('')
axs[1].legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)

正如世卫组织所言,人口老龄化的主要原因是预期寿命增加和生育率下降:

可以肯定地说,一般来说,女人比男人长寿。以下数据证实了这一点:

在这四个国家中,土耳其男人享受生活的时间最少。往好的方面看,土耳其男性的预期寿命也在增加。
人口老龄化意味着比以前有更多的老年人。这可能是与服务相关的工作数量增加的原因之一。
最后,我还想检查不同国家的死亡率。根据 worldbank.org 的定义,粗死亡率是指年中估计的每 1,000 人口中一年内发生的死亡人数。死亡率属性在男性和女性之间没有区别。

死亡率本身并不能告诉我们太多。为了获得关于人口的一些见解,我们需要一起分析死亡率、出生率和移民数据。
结论
我们讨论的特征不会在短时间内改变,但企业应该及时采取行动,因为我们的生活方式和生活方式对每个企业都至关重要。
与大多数企业一样,我们可以在做出关键决策之前,利用数据来审视全局并获得更多洞察力。
Python 和 R 中的数据清理和探索性分析
结合使用 Python 和 r,深入研究一些杂乱的真实世界的数据。

这本笔记本是关于使用 Python 和 R 的组合来执行数据预处理和对杂乱数据集的一些探索性统计分析。面向未来数据科学家的博客和文章经常反复强调使用混乱的真实世界数据的必要性,以及学习数据清理和预处理对这一职业的重要性。然而,我们大多发现带有标准数据集的博客和教程跳过了预处理步骤。同样,现实世界的数据分析可能需要 EDA 和统计分析的结合。为此,可能需要数据科学家同时使用 Python 和 R,并根据手头的微任务在它们之间切换。
在本教程中,我分享了一些数据处理和探索性分析的步骤,这是我在博士期间的一次实验的一部分。我为此引入了一个玩具数据集,但是数据的结构和杂乱程度与我遇到的相似。假设一家零售公司在不同的地理位置有五家商店。每个商店都有两个结账柜台。该公司正在测试一种新产品,他们只把它放在计费柜台上。收银员应该在结账时向顾客推销商品。收银员还会问每位顾客三个关于产品的问题,然后问他们是否想购买该产品。这些问题是关于产品的三个属性,顾客必须回答“是”——如果他们喜欢这个属性,或者回答“否”——如果他们不喜欢这个属性。因此,对于产品的每个副本,我们的数据集中有 4 列——3 列用于属性,1 列用于记录客户最终是否购买该商品。所有的值都是绝对的——“是”或“否”。
但是,数据的存储方式——它存储在一个 csv 文件中,但有 40 列——5 个商店中的每个商店和每个商店中的两个计费柜台都有单独的记录。因此,我们得到了多级列,如下图所示。

混乱的数据
数据存储的方式还有一个问题。如果您查看商店 1 的数据,并比较两个收银台,您会发现记录是互斥的。也就是说,对于访问钱柜 1 的客户,钱柜 2 的相应记录为空。以这种方式存储它可能有一些有效或懒惰的原因。但是现在,作为一名数据科学家,我们已经有了这个数据集。
所以我们开始。我们首先读取 csv 文件,并将其存储为熊猫数据帧。注意,我们使用 header=[2]将第三行用作标题,跳过前两行。
import pandas as pd
d1 = pd.read_csv('https://raw.githubusercontent.com/sagaruprety/data_science/master/multi_attribute_buying_behaviour.csv', header=[2])
d1.head()

合并商店内的收银台
我们看到熊猫把这些柱子标上了“.”扩展。因此{Store_1,Till_1}的“购买”变量仍然是“购买”,但{Store_1,Till_2}的“购买”变量是“购买. 1”。类似地,{Store_2,Till_1}的“Buy”变量是“Buy.2”。还要注意的是,对于任何商店,如果是从其他收银台购买的,商品记录将被注册为 NaN。
这里总共有 40 列——4 个变量 x 5 个商店 x 每个商店 2 个收银台。
我们数据处理的最终目标是合并所有收银台和所有商店的商品记录。这将产生一个只有四列的数据帧——对应于三个属性和购买决定。
第一步是将商店的两个收银台的数据合并成一个。我们迭代数据帧的列,用空字符串(“”)替换 nan,然后连接对应于商店任意两个收银台的列。新的数据帧存储在不同的变量 d2 中。
columns = ['Attribute_1', 'Attribute_2', 'Attribute_3', 'Buy']
num_stores = 5
d2 = pd.DataFrame()
for col in columns:
  for i in range(num_stores):
    if i == 0:
      d2[col+'.'+str(i)] = d1[col].fillna('') + d1[col+'.1'].fillna('')
    else:
      d2[col+'.'+str(i)] = d1[col+'.'+str(2*i)].fillna('') + d1[col+'.'+str(2*i+1)].fillna('')
d2.info()<class 'pandas.core.frame.DataFrame'>
RangeIndex: 202 entries, 0 to 201
Data columns (total 20 columns):
 #   Column         Non-Null Count  Dtype 
---  ------         --------------  ----- 
 0   Attribute_1.0  202 non-null    object
 1   Attribute_1.1  202 non-null    object
 2   Attribute_1.2  202 non-null    object
 3   Attribute_1.3  202 non-null    object
 4   Attribute_1.4  202 non-null    object
 5   Attribute_2.0  202 non-null    object
 6   Attribute_2.1  202 non-null    object
 7   Attribute_2.2  202 non-null    object
 8   Attribute_2.3  202 non-null    object
 9   Attribute_2.4  202 non-null    object
 10  Attribute_3.0  202 non-null    object
 11  Attribute_3.1  202 non-null    object
 12  Attribute_3.2  202 non-null    object
 13  Attribute_3.3  202 non-null    object
 14  Attribute_3.4  202 non-null    object
 15  Buy.0          202 non-null    object
 16  Buy.1          202 non-null    object
 17  Buy.2          202 non-null    object
 18  Buy.3          202 non-null    object
 19  Buy.4          202 non-null    object
dtypes: object(20)
memory usage: 31.7+ KB
合并所有商店的数据
正如我们在上面看到的,我们已经将钱柜级别的信息合并到商店级别。下一步,我们将所有商店的记录合并为一个。我们创建对应于这五个商店的数据帧子集,然后将它们一个接一个地追加。
num_stores = 5
store_dfs = [pd.DataFrame() for _ in range(num_stores)]
col_ind = 0
for col in columns:
  for store in range(num_stores):
    store_dfs[store][col] = d2.iloc[:, col_ind]
    col_ind+=1
store_dfs[4].head()

上面是商店 5 对应的数据框。同样,我们有对应于每个商店的数据框架。请注意,下面每一行都有 202 行。
store_dfs[4].info()<class 'pandas.core.frame.DataFrame'>
RangeIndex: 202 entries, 0 to 201
Data columns (total 4 columns):
 #   Column       Non-Null Count  Dtype 
---  ------       --------------  ----- 
 0   Attribute_1  202 non-null    object
 1   Attribute_2  202 non-null    object
 2   Attribute_3  202 non-null    object
 3   Buy          202 non-null    object
dtypes: object(4)
memory usage: 6.4+ KB
现在,我们将对应于每个商店的数据帧一个接一个地追加,并重置索引,否则索引将从 0 到 201 循环重复 5 个数据帧。
df = store_dfs[0]
for i in range(1,num_stores):
  df = df.append(store_dfs[i])
df.reset_index(drop=True, inplace=True)
df.info()<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1010 entries, 0 to 1009
Data columns (total 4 columns):
 #   Column       Non-Null Count  Dtype 
---  ------       --------------  ----- 
 0   Attribute_1  1010 non-null   object
 1   Attribute_2  1010 non-null   object
 2   Attribute_3  1010 non-null   object
 3   Buy          1010 non-null   object
dtypes: object(4)
memory usage: 31.7+ KB
使用 R 进行神奇命令的统计分析
注意,最终的数据帧具有 202×5 = 1010 行和 4 列。它代表整个公司的数据,而不是商店和钱柜的数据。现在让我们对数据进行一些基本的统计分析。r 是统计分析中最流行的语言之一,我们将在这里使用它。Jupyter(代表 JUlia PYThon R)笔记本允许我们在 PYThon 笔记本中嵌入代码片段。
为此,我们首先需要下载下面的 R 包:
%load_ext rpy2.ipython
%R 是一个神奇的命令,它帮助我们从 Python 切换到 R。以%R 开头的任何一行代码都将使我们能够用 R 编写。
下面的代码行指示机器获取名为 df 的 python 变量,并将其转换为同名的 R 变量。所以我们把熊猫的数据帧转换成 R 数据帧。
%R -i df
接下来,我们检查 R 数据帧的结构。这表明不同属性的值在内部存储为字符串。
%R str(df)'data.frame':	1010 obs. of  4 variables:
 $ Attribute_1: chr  "No" "Yes" "Yes" "No" ...
 $ Attribute_2: chr  "Yes" "Yes" "No" "Yes" ...
 $ Attribute_3: chr  "Yes" "No" "No" "Yes" ...
 $ Buy        : chr  "No" "Yes" "No" "No" ...
转换为 R 数据框架中的分类变量
下面几行代码将不同属性的值存储为分类变量(在 R 中称为因子)。但是我们看到有三种类型的分类变量。有一个空字符串,这是由于数据集中缺少一些值。
请注意,您还可以使用神奇的命令%%R,该命令使整个单元格用于 R。
%%R
df$Attribute_1 <- as.factor(df$Attribute_1)
df$Attribute_2 <- as.factor(df$Attribute_2)
df$Attribute_3 <- as.factor(df$Attribute_3)
df$Buy <- as.factor(df$Buy)
str(df)'data.frame':	1007 obs. of  4 variables:
 $ Attribute_1: Factor w/ 2 levels "No","Yes": 1 2 2 1 2 1 1 2 2 2 ...
 $ Attribute_2: Factor w/ 2 levels "No","Yes": 2 2 1 2 2 2 2 2 2 2 ...
 $ Attribute_3: Factor w/ 2 levels "No","Yes": 2 1 1 2 2 2 2 1 2 2 ...
 $ Buy        : Factor w/ 2 levels "No","Yes": 1 2 1 1 1 1 1 2 2 2 ...
使用 Pandas 从数据帧中删除空字符串
这是我们一开始就应该检查的。我们很容易在熊猫身上做到这一点。注意,空值不是 NaN,而是空字符。所以我们需要首先将它们转换成 NaN,然后使用 pandas dropna 函数删除具有 NaN 值的行。
import numpy as np
df.replace(to_replace='', value=np.NaN, inplace=True)
df.dropna(inplace=True)
现在再次运行上面这段 R 代码,我们得到一个 R 数据帧,其中有两级分类变量。
%R -i df
%R df$Attribute_1 <- as.factor(df$Attribute_1)
%R df$Attribute_2 <- as.factor(df$Attribute_2)
%R df$Attribute_3 <- as.factor(df$Attribute_3)
%R df$Buy <- as.factor(df$Buy)
%R str(df)'data.frame':	1007 obs. of  4 variables:
 $ Attribute_1: Factor w/ 2 levels "No","Yes": 1 2 2 1 2 1 1 2 2 2 ...
 $ Attribute_2: Factor w/ 2 levels "No","Yes": 2 2 1 2 2 2 2 2 2 2 ...
 $ Attribute_3: Factor w/ 2 levels "No","Yes": 2 1 1 2 2 2 2 1 2 2 ...
 $ Buy        : Factor w/ 2 levels "No","Yes": 1 2 1 1 1 1 1 2 2 2 ...
分析数据
现在我们可以对数据进行一些分析。目的是找出这三个属性中哪一个对购买决策影响最大。我们首先使用 xtabs 来计算跨类别频率。这让我们可以一瞥每个属性对购买决策的影响。
%%R
print(xtabs(~Buy+Attribute_1, data=df))
print(xtabs(~Buy+Attribute_2, data=df))
print(xtabs(~Buy+Attribute_3, data=df))Attribute_1
Buy    No Yes
  No  372 122
  Yes  48 465
     Attribute_2
Buy    No Yes
  No  267 227
  Yes 180 333
     Attribute_3
Buy    No Yes
  No  272 222
  Yes 155 358
逻辑回归分析
请注意,在上述矩阵中,Attribute_1 似乎对购买决策产生了重大影响。几乎 80%喜欢新产品属性 1 的顾客会购买它,几乎 90%不喜欢属性 1 的顾客最终不会购买它。其他两个属性的分数倾向于 50-50,情况就不一样了。
由于我们在这里处理分类变量,我们需要使用广义线性模型(GLM)的二项式家族来分析不同属性的影响。所以我们在数据中拟合了一个逻辑回归模型。
在下面的总结中,我们发现属性 1 在购买决策中的重要影响,因为相应的 p 值非常低。
负截距意味着如果所有属性的值都为“否”,那么客户极不可能购买该产品,这是有道理的。请注意,在逻辑回归中,输出变量“购买”被转换为对数优势比例。因此,负值实际上意味着不利于客户购买产品。
如果您不熟悉逻辑回归背后的概念和内涵,请参考这个解释逻辑回归的优秀视频系列。
%%R
logistic <-glm(Buy~Attribute_1+Attribute_2+Attribute_3, data=df, family = "binomial")
print(summary(logistic))Call:
glm(formula = Buy ~ Attribute_1 + Attribute_2 + Attribute_3, 
    family = "binomial", data = df)
Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-2.0684  -0.5250   0.5005   0.6474   2.4538  
Coefficients:
               Estimate Std. Error z value Pr(>|z|)    
(Intercept)     -2.9599     0.2241 -13.206  < 2e-16 ***
Attribute_1Yes   3.3681     0.1912  17.620  < 2e-16 ***
Attribute_2Yes   0.5579     0.1757   3.174   0.0015 ** 
Attribute_3Yes   1.0479     0.1782   5.881 4.07e-09 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for binomial family taken to be 1)
    Null deviance: 1395.6  on 1006  degrees of freedom
Residual deviance:  850.7  on 1003  degrees of freedom
AIC: 858.7
Number of Fisher Scoring iterations: 5
预测购买决策的逻辑回归模型
我们想知道我们是否应该考虑所有这三个变量,以便对数据建模,或者某个变量,比如 Attribute_2,是否对购买决策没有贡献。我们可以使用如下所示的 Anova 技术对此进行测试。
attribute_1 的偏差比其他的高得多。属性 2 和属性 3 对购买决策的影响不大。因此,如果您想让模型更简单,可以单独使用 attribute_1 来预测购买决策。虽然当使用所有三个属性时,剩余偏差是最低的,所以使用所有三个属性的模型是最适合的。
%R anova(logistic, test='Chisq')

我们可以使用这个拟合模型对新客户进行预测。比如我们下面看到,如果一个客户不喜欢第一个属性,但喜欢其他两个,那么购买该产品的概率是 0.2。
%%R
new_customer <- data.frame(Attribute_1=as.factor('No'), Attribute_2=as.factor('Yes'), Attribute_3=as.factor('Yes'))
new_customer_buys <-predict(logistic, new_customer, type='response')
paste(new_customer_buys)[1] "0.205188948698921"
结论和未来设想
所以这只是一些真实世界数据科学工作的介绍。我们从一个非常杂乱的数据集开始准备数据,以便进行一些统计分析和预测。同样,我们使用 Python 和 R 的组合来实现这个目的。这个模型非常简单,只有三个 atrtibutes。即便如此,仅凭其中一个就足以预测决定。
对于那些对决策的行为方面感兴趣的人来说,如果收银员以不同的顺序向顾客提出这三个问题,预测是否会改变,这将是一个有趣的想法。机器学习模型不考虑特征的顺序。我们知道,人类的回答受到提问顺序的影响(顺序效应)。因此,当机器学习模型的特征对应于人类决策/答案/判断时,ML 模型在预测决策时也需要考虑特征的排序。
感谢您阅读这篇文章。我仍在学习数据科学和分析的行业,希望能得到这篇文章各方面的反馈。
数据清理和预处理—为银行存款的订阅建模
探索数据以获得洞察力
对数据的探索一直让我着迷。可以隐藏在原始数据中的见解和信息令人振奋地发现和交流。在这篇文章中,我选择探索来自 UCI 机器学习知识库的银行营销数据,以揭示暗示客户是否会订阅定期存款的见解。所以,是的!你猜对了!这是一个分类问题。数据已经被清理了,至少在某种程度上,没有丢失值,所以不需要太多的数据清理,因此我的重点将放在探索性数据分析(EDA)上。
我在下面概述了我计划遵循的步骤:
1.电子设计自动化(Electronic Design Automation)
a.单变量分析
b.双变量分析
c.洞察力探索
2.预处理
a.数据转换
b.特征工程
3.系统模型化
a.模型开发
b.模型评估
c.模型比较
步骤 1:探索性数据分析(EDA)
数据来源于 UCI 机器学习库。该数据代表一家葡萄牙银行机构营销活动(电话)的结果,包括 41188 个观察(行)和 21 个特征(列),其中包括客户的年龄、工作、教育等数据。、经济和社会属性,如就业变化率、雇员人数等。因变量(目标)用“y”表示,它表示营销活动的结果,无论被调查者订购押金是“是”还是“否”。功能的详细描述可以在这里找到
让我们从探索开始——首先加载所有将要使用的库
# Ignore warningsimport warningswarnings.filterwarnings('ignore')# Handle table-like data and matricesimport numpy as npimport pandas as pd# Modelling Algorithmsfrom sklearn.tree import DecisionTreeClassifierfrom sklearn.svm import SVCfrom sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifierfrom sklearn.neural_network import MLPClassifierfrom xgboost import XGBClassifierfrom sklearn.metrics import accuracy_score, confusion_matrix, classification_report# Modelling Helpersfrom sklearn.preprocessing import StandardScalerfrom sklearn.model_selection import train_test_split# Visualisationimport matplotlib as mplimport matplotlib.pyplot as pltimport matplotlib.pylab as pylabimport seaborn as sns# read in the datadf = pd.read_csv('data/bank-additional-full.csv', sep=';')df.head()
让我们来看看使用 pandas 库中的 describe 方法对数据的描述。
data.select_dtypes(include=[“int64”, “float64”]).describe().T

数据描述
从数据中,我们可以观察到平均年龄为 40 岁,最大年龄为 98 岁,最小年龄为 17 岁。余额是以欧元表示的年平均余额。试着理解剩下的数据描述。在试图理解数据的同时,您可以尝试回答以下问题:
单变量分析
为了使这一步和下一步更容易和可重复,我创建了一个类来可视化数据。这个类有不同的功能来使探索和洞察力的交流变得容易。下面是我是如何做到的:

目标分布
似乎有更多的客户没有申请定期存款。这当然是一个不平衡的阶级问题。
1.这个类不平衡的问题如何影响你的模型性能?
2.哪些数据技术方法可能有用?
注意:关于如何处理这些问题的更多细节将在转换步骤中提供。

婚姻状况分布
生成了更多的可视化效果,以了解数据集中每个要素的分布情况。
双变量分析
比较一个特征相对于另一个特征的分布对于分类任务,目标是主要特征,而另一个特征可以被选择来观察它们的关系

按目标分列的婚姻状况分布 y

按目标分列的教育分布 y


洞察力探索
根据上述单变量和双变量分析的结果,可以推断:
1.在一列中有一些类似的值,如婚姻状况和 basic.4y、basic.6y 和 basic.9y 的离婚和单身类别,它们可以替换为 basic,因为它们都指同一事物。
2.婚姻状况的分布在已婚和单身(单身+离异)之间相对均衡
3.近似的 90%的目标对定期订阅说不,留给我们的任务是为一个好的模型平衡数据
4.大多数受访者没有个人贷款。
5.大多数回答者都有大学学位
6.电话在周末没有接通,一周中每天记录的电话数量相对相等
7.近似的 65%的受访者是通过手机联系的
8.大多数电话发生在 5 月。前几次竞选活动在夏季的不均衡可能会影响未来竞选活动的结果。
步骤 2:预处理(数据转换)
为了准备建模数据,我们将执行以下操作:
1.复制原始数据,以便所有转换都在重复数据上完成
2.指定目标列并从数据中删除
3.将一些相似的特征映射到一个中以进行适当的编码
4.使用 One Hot 编码技术将对象数据类型列转换为整数
5.使用健壮的 scaler 算法缩放数据:之所以选择这个算法,是因为它不太容易受到离群值的影响。
6.修正不平衡部分的数据更多信息此处
7.使用主成分分析进行降维
8.将目标列添加回数据中
9.返回转换后的数据框
为了使这些步骤更容易,我使用了一个类,其中所有的步骤都相应地实现了。下面是一个截图,展示了如何做到这一点

数据转换代码
每一步都有一个功能,使其更具可重复性。将列的相似类别映射在一起,以进一步提高预测模型的性能;使用 imblearn smote 模块对少数类(在我们的案例中是对定期存款订阅说“是”的回答者的数量)进行过采样,从而处理一个热编码数据不平衡;然后进行降维,以降低由一位热编码技术引起的数据复杂性。
特征工程
这是向数据集中现有要素添加更多要素的过程。这可以通过特征转换和/或特征聚合来完成。下面显示了一个示例

特征工程
在一线时代,一个数字特征被转换成包括年轻人、中年人和老年人的类别。年龄也通过一些分类列(如婚姻)进行汇总,并使用平均值进行转换,以获得每个平均年龄的教育额外特征。
第三步:建模
模型开发
在这个阶段,建立了机器学习模型。预测分类变量“y”的最简单和最易解释的模型是逻辑回归。因此,它被用作有待改进的基准模型。在拟合模型时,使用了分层的 5 折交叉验证,因为它对每个折进行采样,使得每个折都是整个数据的良好代表。StratifiedKFold 将数据打乱并分割一次,因此测试集不会重叠,这是执行交叉验证的好方法。
实施逻辑回归模型
################ LOGISTIC REGRSSION #########################def run_logistic_regression(self, X_train, X_val, Y_train, Y_val):model_name = '26-08-2020-20-32-31-00-log-reg.pkl'# initialze the kfoldkfold, scores = KFold(n_splits=5, shuffle=True, random_state=221), list()# split data index to train and testfor train, test in kfold.split(X_train):# specify train and test setsx_train, x_test = X_train[train], X_train[test]y_train, y_test = Y_train[train], Y_train[test]# initialize the modelmodel = LogisticRegression(random_state=27,  solver='lbfgs')# trainmodel.fit(x_train, y_train)# predict for evaluationpreds = model.predict(x_test)# compute f1-scorescore = f1_score(y_test, preds)scores.append(score)test_pred = model.predict(X_val)print('f1-score: ',score)print("Average: ", sum(scores)/len(scores))
建立的其他模型包括 XGBoost、多层感知器、支持向量机、随机森林。

实现 xgboost 模型
选择这些模型是因为它们在检测数据中的隐藏模式和非线性相关性/关系方面的复杂方法。
模型评估
用于该数据的评估指标是 recall_score、f1_score 和受试者操作特征(ROC)曲线。他们被选中是因为:
1.数据高度不平衡,偏向公司的负面,即亏损,因此 f1_score 将有助于检测敏感性和特异性之间的调和平均值。
2.在这里,较高的召回分数比较高的精确度更好,因为召回分数 aka(敏感度)是在所有相关实例中检索到的实例的分数。在我们的情况下,识别将订阅定期存款的客户比识别可能订阅或可能不订阅的客户更重要。
3.ROC 曲线有助于解释每个模型如何很好地解释数据中的方差。越接近 1 越好,并且应该高于 0.5,这比随机猜测要好。

模型评估
评估模型的代码
def eval_model(self, target_test_data, prediction):from sklearn.metrics import accuracy_score,confusion_matrix,recall_score, f1_score, precision_scorefrom sklearn.metrics import classification_reportconfusion_matrix = confusion_matrix(target_test_data, prediction)print('Accuracy Score: ', accuracy_score(target_test_data, prediction))print('F1-Score: ', f1_score(target_test_data, prediction))print('Recall: ', recall_score(target_test_data, prediction))print('Precision: ', precision_score(target_test_data, prediction))print(confusion_matrix)print(classification_report(target_test_data, prediction))def plot_auc_curve(self, model, model_name, test_data, target_test_data):from sklearn.metrics import roc_auc_scorefrom sklearn.metrics import roc_curvelogit_roc_auc = roc_auc_score(target_test_data, model.predict(test_data))fpr, tpr, thresholds = roc_curve(target_test_data, model.predict_proba(test_data)[:,1])plt.figure()plt.plot(fpr, tpr, label=f'{model_name} (area under curve = %0.2f)' % logit_roc_auc)plt.plot([0, 1], [0, 1],'r--')plt.xlim([0.0, 1.0])plt.ylim([0.0, 1.05])plt.xlabel('False Positive Rate')plt.ylabel('True Positive Rate')plt.title(f'Receiver operating characteristic ({model_name})')plt.legend(loc="lower right")plt.savefig(f'{model_name}_ROC')plt.show()
评估模型
准确度分数:0.84676465465
f1-得分:0.41941391337
召回:0 . 48667 . 38686868661
精度:0.36466868665

分类报告

受试者工作特征曲线

xgboost roc 曲线

分类报告
该模型对于类别 0(没有订阅押金的回答者)的预测和召回率较高,但是对于类别 1(订阅的回答者)的预测和召回率较低。0 班的 F1 分数很高,而 1 班的 F1 分数低于 0.5。总的来说,该模型似乎不能很好地预测定期存款的受访者。曲线下的面积为 0.72,大大高于随机猜测的概率面积(0.5)。给定上述分类报告的结果,可以假设对 ROC 曲线下面积的最大贡献来自正确识别的 0 级。
模型比较

建造的模型

在所有模型中,逻辑回归具有最高的回忆得分值。

就 f1-得分而言,梯度推进模型具有最高的性能。
结论
支持向量机为 F1 分数和回忆分数给出了稳定和可靠的模型性能。较高的 F1 分数表明,该模型可以很好地预测现有客户的存款订阅活动是否成功。这是在 10 academy training 中每周挑战的一部分。
有详细分析代码的笔记本可以在这里找到
社交媒体数据 NLP 的数据清理,只需两个简单的步骤。
在本文中,我们将利用 Twitter 数据来演示如何使用 Regex 和 NLTK 执行数据清理。

如果你处理过机器学习或数据科学问题,你应该知道数据清理是构建算法的关键步骤。算法的质量将取决于数据清理的效果。在处理 NLP 时,数据清理变得更加复杂。在这里,我们必须使用单词和语法字符。这就是为什么为了使这个任务更简单,我们将在 Twitter 数据上演示简单的步骤。所以,事不宜迟,让我们开始吧。
注意: 1】这里我们假设一个人知道如何用 Python 编程,并且理解机器学习的概念。2]根据您的应用,下面列出的步骤可能会有细微的变化。
我们将使用 Regex 和 NLTK。Regex 或正则表达式是一个文本字符串,用于描述从大量文本中提取信息时的搜索查询。文档可在此处找到:
[## 7.2.re —正则表达式操作— Python 2.7.17 文档
这个模块提供了类似于 Perl 中的正则表达式匹配操作。无论是图案还是字符串…
docs.python.org](https://docs.python.org/2/library/re.html)
NLTK 或自然语言工具包为计算语言学提供了库和程序。以下是相同的文档:
NLTK 是构建 Python 程序来处理人类语言数据的领先平台。它提供了易于使用的…
www.nltk.org](https://www.nltk.org/)
首先,我们将导入上面提到的库。
这里我们已经导入了 Regex (re)和 NLTK。从 NLTK 库中,我们下载了 停用词 模块。停用词是被认为是不相关的词,可以在分析文本时删除。注意,这里我们使用 NLTK 中给出的默认停用词。您可以根据手头问题的要求制作停用词文件并导入。最后,我们做了一套所有的停用词。
第一步:清理正文。
在这一步中,我们将从文本数据中去除“噪音”。在社交媒体文本数据的背景下,我们将以下内容视为噪音:
1] Html 标签和属性(即/ ]+>/)。
2] Html 字符代码(即&…;).
3]网址和空白。
我们使用正则表达式来做同样的事情。如果你不熟悉正则表达式,我推荐你参考本教程。
正则表达式(RegEx)是定义搜索模式的字符序列。比如上面的代码…
www.programiz.com](https://www.programiz.com/python-programming/regex)
现在我们将在一个列表中收集 tweets 数据。为了这个教程,我在这里只导入了两条 tweets。
现在,我们将创建一个函数,该函数将原始推文列表作为输入,去除“噪声”并生成干净推文列表作为输出。
正如你所看到的,我们计划删除所有的 HTML 字符,标点符号,网址以及空白。此外,我们将字符串中的所有大写字母转换为小写字母。这里我们使用 Regex 的 re.sub()方法。这个方法扫描字符串,并用空格替换我们想要删除的子字符串。
在 re.sub()中,我们在第一个参数中指定正则表达式模式,在第二个参数中指定新字符串,在第三个参数中指定要处理的字符串。
上面的函数为给定的 tweets 生成以下输出。

正如你所看到的,输入的 tweetss 有 URL 和标签,而输出的 tweet 更简洁,并且是小写形式。
第二步:删除停用词。
现在我们有了一个更简单、更整洁的 tweets,我们通过删除不必要的单词来进一步清理它们。停用词给我们的文本分析增加了冗余,因此通过移除这样的词,我们可以使我们的分析更加准确。
类似于步骤 I,我们将定义一个新的函数来删除停用词。
这个函数将一列 tweet 作为输入,将 tweet 拆分成单独的单词,删除停用词,并生成一列干净的 tweet 作为输出。
我们将第一步的输出作为第二步的输入。上述函数产生以下输出。

你可以看到原始推文和最终推文之间的差异。最终的推文非常紧凑,只有相关的词。
如果你觉得这篇文章有用,请给它鼓掌,它会有很大的帮助!!
关注我的 中型 获取更多此类教程&文章。
如果你愿意,在 LinkedIn 上连接。
如果您有任何疑问或发现代码/概念中的任何错误,请随时在评论中写下。这是我试图与世界分享我在数据科学领域所知道的一切!
图片来源:https://www.geotab.com/blog/data-cleaning/
Python 中的数据清理:终极指南
清洁什么和如何清洁的技巧。

来源: Pixabay
对于本指南的更新版本,请访问【Python 中的 数据清理技术:终极指南。
在拟合机器学习或统计模型之前,我们总是必须清理数据。没有模型会用杂乱的数据创造出有意义的结果。
数据清理 是从记录集、表或数据库中检测和纠正(或删除)损坏或不准确记录的过程,指的是识别数据中不完整、不正确、不准确或不相关的部分,然后替换、修改或删除脏的或粗糙的数据。
好长的定义啊!这当然不好玩,而且非常耗时。

为了使更简单,我们用 Python 创建了这个新的完整的分步指南。你将在中学习如何 找到并清理的技巧:
- 缺失数据
 - 不规则数据(异常值)
 - 不必要的数据—重复数据、重复数据等等
 - 不一致的数据—大写、地址等
 
进一步学习:我们推出了一门课程Python for Data Analysis:step-by-step with projects,其中包括一整节更新的数据清理等内容!请在这里查看。
在本指南中,我们使用来自 Kaggle 的俄罗斯住房数据集。这个项目的目标是预测俄罗斯的房价波动。我们不会清理整个数据集,但会展示其中的示例。
在我们进入清理过程之前,让我们简单地看一下数据。
从这些结果中,我们了解到数据集有 30,471 行和 292 列。我们还识别特征是数字变量还是分类变量。这些都是有用的信息。
现在,我们可以浏览“脏”数据类型的清单,并逐一修复它们。
让我们开始吧。
来源: GIPHY
缺失数据
处理缺失数据 /value 是数据清理中最棘手但最常见的部分之一。虽然许多模型可以忍受数据的其他问题,但大多数模型不接受缺失数据。
如何发现?
我们将介绍三种技术来了解关于数据集中缺失数据的更多信息。
- 技巧 1:缺失数据热图
 
当要素数量较少时,我们可以通过热图可视化缺失的数据。
下图展示了前 30 个特性的缺失数据模式。水平轴显示功能名称;纵轴显示观察值/行数;黄色代表丢失的数据,而蓝色代表其他数据。
例如,我们看到 life_sq 特性在许多行中都有缺失值。而楼层特征仅在第 7000 行附近有少量缺失值。

缺失数据热图
- 技术#2:缺失数据百分比列表
 
当数据集中有许多要素时,我们可以为每个要素列出缺失数据百分比。
这将生成一个列表,显示每个要素缺失值的百分比。
具体来说,我们看到 life_sq 特性缺失了 21%,而 floor 只缺失了 1%。这个列表是一个有用的总结,可以补充热图可视化。

缺失数据%列表-前 30 个要素
- 技术#3:缺失数据直方图
 
当我们有许多特征时,缺失数据直方图也是一种技术。
要了解更多关于观察值中缺失值模式的信息,我们可以通过直方图来可视化它。
该直方图有助于识别 30,471 个观察值中缺失值的情况。
例如,有超过 6000 个没有缺失值的观察值和接近 4000 个有一个缺失值的观察值。

缺失数据直方图
该怎么办?
没有一致同意的解决丢失数据的方法。我们必须研究特定的特征和数据集,以决定处理它们的最佳方式。
下面介绍了处理缺失数据的四种最常见的方法。但是,如果情况比平常更复杂,我们需要创造性地使用更复杂的方法,比如缺失数据建模。
- 解决方案#1:放弃观察
 
在统计学中,这种方法被称为列表删除技术。在这个解决方案中,只要它包含一个缺失值,我们就丢弃整个观察值。
只有当我们确定缺失的数据不具有信息性时,我们才执行此操作。否则,我们应该考虑其他解决方案。
可能有其他标准用于删除观察值。
例如,从缺失数据直方图中,我们注意到只有极少量的观察值总共缺失超过 35 个特征。我们可以创建一个新的数据集 df_less_missing_rows 删除超过 35 个缺失特征的观测值。
- 解决方案 2:放弃这个功能
 
类似于解决方案#1,我们只有在确信这个特性不能提供有用信息时才这样做。
例如,从缺失数据百分比列表中,我们注意到 hospital_beds_raion 具有高达 47%的缺失值百分比。我们可能会放弃整个功能。
- 解决方案#3:估算缺失值
 
当特征是数值变量时,我们可以进行缺失数据插补。我们用未缺失的同一要素的数据的平均值或中值替换缺失值。
当特征是一个分类变量时,我们可以通过众数(最频繁值)来估算缺失数据。
以 life_sq 为例,我们可以用它的中值替换这个特性的缺失值。
此外,我们可以一次对所有数字特征应用相同的插补策略。

幸运的是,我们的数据集没有分类特征的缺失值。然而,我们可以一次对所有分类特征应用模式插补策略。
- 解决方案 4:更换缺失的
 
对于分类特征,,我们可以添加一个新的类别,其值为“MISSING”。对于数字特征,我们可以用一个特定的值代替,比如-999。
这样,我们仍然将丢失的值作为有价值的信息保存。
不规则数据(异常值)
异常值是与其他观测值明显不同的数据。它们可能是真正的异常值或错误。
如何发现?
根据特征是数值的还是分类的,我们可以使用不同的技术来研究它的分布以检测异常值。
当特征是数字时,我们可以使用直方图和箱线图来检测异常值。
下面是特征 life_sq 的直方图。
由于可能存在异常值,数据看起来非常不准确。

柱状图
为了更仔细地研究这个特征,让我们画一个方框图。
在该图中,我们可以看到有一个值超过 7000 的异常值。

箱形图
- 技巧 2:描述性统计
 
此外,对于数字要素,异常值可能过于明显,以至于箱线图无法显示它们。相反,我们可以看看他们的描述性统计数据。
例如,再次针对特性 life_sq ,我们可以看到最大值是 7478,而 75%四分位数只有 43。7478 值是一个异常值。

- 技巧三:条形图
 
当特征是绝对的时。我们可以用柱状图来了解它的类别和分布。
比如特色生态分布合理。但是,如果有一个类别只有一个名为“其他”的值,那么这将是一个离群值。

条形图
- 其他技术:许多其他技术也可以发现异常值,比如散点图、z 得分和聚类。本文没有涵盖所有这些内容。
 
做什么?
虽然离群值不难检测,但我们必须确定正确的解决方案来处理它们。它高度依赖于数据集和项目的目标。
处理异常值的方法有点类似于缺失数据。我们要么放弃,要么调整,要么保留它们。我们可以参考缺失数据部分来寻找可能的解决方案。
不必要的数据
在为缺失数据和异常值做了所有的努力之后,让我们来看看不必要的数据,这更简单。
所有输入模型的数据都应该服务于项目的目的。不必要的数据是那些没有增加价值的数据。由于不同的原因,我们涵盖了三种主要类型的不必要数据。
不必要的类型#1:无信息/重复
有时一个特征是无用的,因为它有太多的行是相同的值。
如何发现?
我们可以创建一个具有高百分比相同值的特性列表。
例如,我们在下面指定显示 95%以上的行是相同值的特性。
我们可以逐一研究这些变量,看看它们是否能提供信息。这里就不展示细节了。

该怎么办?
我们需要了解重复特征背后的原因。当它们真的毫无意义时,我们可以把它们扔掉。
不必要的类型 2:不相关
同样,数据需要为项目提供有价值的信息。如果特性与我们在项目中试图解决的问题不相关,它们就是不相关的。
如何发现?
我们需要浏览这些特征,找出不相关的特征。
例如,记录多伦多气温的功能并不能为预测俄罗斯房价提供任何有用的信息。
该怎么办?
当特性没有服务于项目的目标时,我们可以删除它们。
不必要的类型#3:重复
重复数据是指存在相同观测值的副本。
重复数据主要有两种类型。
- 重复类型#1:基于所有特征
 
如何发现?
当观测值中所有要素的值都相同时,会出现这种重复。很容易找到。
我们首先删除数据集中的唯一标识符 id 。然后,我们通过删除重复项来创建一个名为 df_dedupped 的数据集。我们比较两个数据集(df 和 df_dedupped)的形状,找出重复行的数量。
第 10 行是完整的重复观测。

该怎么办?
我们应该删除这些重复的,我们已经这样做了。
- 重复类型#2:基于关键特征
 
如何发现?
有时,根据一组唯一标识符删除重复数据会更好。
例如,两笔交易同时发生、面积相同、价格相同、建造年份相同的几率接近于零。
我们可以设置一组关键特性作为事务的唯一标识符。我们包括时间戳、满 _ 平方、寿命 _ 平方、楼层、建造 _ 年份、房间数量、价格 _ 文档。我们检查是否有基于它们的副本。
基于这组关键特征有 16 个副本。

该怎么办?
我们可以根据关键特征删除这些重复项。
我们在名为 df_dedupped2 的新数据集中删除了 16 个重复项。

不一致的数据
让数据集遵循特定的标准来适应模型也很重要。我们需要以不同的方式探索数据,找出不一致的数据。很多时候,这取决于观察和经验。没有固定的代码来运行和修复它们。
下面我们介绍四种不一致的数据类型。
不一致类型#1:大写
分类值中大小写用法不一致是一个常见的错误。这可能会导致问题,因为 Python 中的分析是区分大小写的。
如何发现?
让我们看看子区域特征。
它存储了不同地区的名称,看起来非常标准化。

但是有时在同一特性中会出现不一致的大写用法。“Poselenie Sosenskoe”和“pOseleNie sosenskeo”可以指同一地区。
该怎么办?
为了避免这一点,我们可以把所有的字母小写(或大写)。

不一致的类型#2:格式
我们需要执行的另一个标准化是数据格式。一个例子是将特征从字符串转换为日期时间格式。
如何发现?
特征时间戳是字符串格式,而它表示日期。

怎么办?
我们可以使用下面的代码转换它并提取日期或时间值。在此之后,按年份或月份分析交易量组就更容易了。

相关文章: 如何像老板一样在 Python 中操纵日期和时间
不一致的类型#3:分类值
不一致的分类值是我们讨论的最后一种不一致类型。分类特征的值数量有限。有时由于错别字等原因可能会有其他值。
如何发现?
我们需要观察特征来找出这种不一致性。让我们用一个例子来说明这一点。
我们在下面创建一个新的数据集,因为我们在房地产数据集中没有这样的问题。例如,城市的值被错误地输入为“多伦多”和“特隆托”。但两者都指的是正确的值“多伦多”。
识别它们的简单方法是模糊逻辑(或编辑距离)。它测量我们需要多少个字母(距离)来改变一个值的拼写以匹配另一个值。
我们知道类别应该只有四个值:“多伦多”、“温哥华”、“蒙特利尔”和“卡尔加里”。我们计算所有值与单词“多伦多”(和“温哥华”)之间的距离。我们可以看到,可能是错别字的那些与正确的单词之间的距离较小。因为它们只相差几个字母。

做什么?
我们可以设置标准来将这些错别字转换成正确的值。例如,下面的代码将距离“toronto”两个字母以内的所有值都设置为“toronto”。

不一致类型#4:地址
地址功能可能会让我们很多人感到头疼。因为向数据库输入数据的人通常不遵循标准格式。
如何发现?
我们可以通过查看找到杂乱的地址数据。即使有时我们不能发现任何问题,我们仍然可以运行代码来标准化它们。
出于隐私原因,我们的数据集中没有地址列。因此,我们创建一个新的数据集 df_add_ex ,其特征地址。
我们可以看到,地址功能相当混乱。

该怎么办?
我们运行下面的代码来小写字母,删除空白,删除句号和标准化的措辞。
现在看起来好多了。

我们做到了了!我们走过了多么漫长的旅程啊。
进一步学习:如果你喜欢这篇文章,你可能会喜欢我们的新课程Python for Data Analysis:step-by-step with projects,它包括一个更新的数据清理的完整部分,等等!
请看这里的。
清除所有阻碍你适应模型的“脏”数据。
是清洗的老板!
来源: GIPHY
感谢您的阅读。
我希望这个数据清理指南对你有所帮助。请留下任何评论,让我们知道你的想法。
在你离开之前,别忘了 报名参加刚刚进入数据快讯 !或者在推特、脸书上与我们联系。
所以您不会错过我们任何新的数据科学文章!
这是利用在线资源进入数据科学的完整路线图/课程。你是否想学习…
www.justintodata.com](https://www.justintodata.com/how-to-learn-data-science-online-all-you-need-to-know/) [## 预测时间序列的三个步骤:LSTM 与 TensorFlow Keras -只是进入数据
这是利用在线资源进入数据科学的完整路线图/课程。你是否想学习…
www.justintodata.com](https://www.justintodata.com/forecast-time-series-lstm-with-tensorflow-keras/) [## 如何像老板一样操纵 Python 中的日期和时间——只处理数据
这是利用在线资源进入数据科学的完整路线图/课程。你是否想学习…
www.justintodata.com](https://www.justintodata.com/manipulate-date-and-time-in-python/)
数据清理终于实现了自动化
苹果 | 谷歌 | SPOTIFY | 其他
Ihab 易勒雅斯在 TDS 播客

编者按:迈向数据科学播客的“攀登数据科学阶梯”系列由 Jeremie Harris 主持。Jeremie 帮助运营一家名为sharpes minds的数据科学导师初创公司。可以听下面的播客:
说数据清理占数据科学家工作的 80%是老生常谈,但这在方向上是正确的。
这太糟糕了,因为像数据探索、可视化和建模这样有趣的事情是大多数人进入数据科学的原因。因此,行业内正在大力推动尽可能自动化数据清理,这是一件好事。
这项工作的领导者之一是滑铁卢大学教授伊哈布·易勒雅斯,他是两家公司 Tamr 和 Inductiv 的创始人,两家公司都专注于数据科学生命周期的早期阶段:数据清理和数据集成。Ihab 非常了解数据清理和数据工程,并有一些关于该领域未来方向的非常棒的见解可以分享——包括一旦自动化了数据清理,数据科学家还有什么工作要做。
以下是我从对话中最大的收获:
- 数据清理涉及很多事情,其中之一就是处理丢失的值。历史上,缺少的值通常由主题专家手动填充,他们可以对数据进行有根据的猜测,但自动化技术在大规模应用时可以工作得很好(通常做得更好)。
 - 这些自动化策略的范围从相当简单的方法(例如,用数据集中其他点的中值或平均值替换某个值)到更复杂的技术(例如,使用预测模型猜测缺失值)。
 - 数据科学生命周期的不同部分之间的区别通常是任意的,但明确定义数据清理、数据探索和建模之间的界限对于确保问题能够以包容和模块化的方式得到解决是至关重要的。这个想法是构成 DataOps 的数据科学最佳实践的一部分,data ops 是我们之前在播客中讨论过的一个主题。
 - 很明显,像建模一样,数据清理也不能避免自动化。因此,数据科学家很可能会发现自己在未来越来越多地学习他们的主题专业知识、沟通和工程技能,而不是将时间花在处理缺失值、超参数优化或模型选择上。
 
你可以在 Twitter 上关注 Ihab,这里是 T1,你也可以在 Twitter 上关注我,这里是 T2,这里是 T3。
R 中的数据清理、合并和争论
这里有一些整理数据和在 r 中进行常见数据操作的有用技巧。
在任何上下文中处理数据的一个大问题是数据清理和数据集合并的问题,因为通常情况下,您会发现自己必须整理多个文件中的数据,并且需要依赖 R 来执行通常在 Excel 中使用 VLOOKUP 等命令执行的功能。
下面是一些关于 R 如何用于数据操作的有用例子。虽然 Python 的 pandas 库传统上被认为是这一领域的赢家,但 R 经常使用的数据操作技术实际上非常强大。
让我们来看看其中的一些。
数据清理和合并功能
对于示例 1–7,我们有两个数据集:
- sales: 该文件包含变量 Date、ID(即产品 ID)和 sales。我们将它加载到 R 中,命名为 mydata。
 - 客户:该文件包含变量 ID、年龄和国家。我们将它加载到 R 中,命名为 mydata2。
 
这些数据集可以在下面的 GitHub 仓库获得。
下面是 R 中用来清理数据集的流行技术的例子,以及如何有效地格式化变量以方便分析。以下函数特别适用于面板数据集,其中混合了横截面和时间序列数据。
1。在数据帧中存储变量
从一个简单的例子开始,让我们选择客户数据集。假设我们只希望在数据中包含变量 ID 和 Age。为此,我们将数据框定义如下:
dataframe<-data.frame(ID,Age)
2。使用合并功能模拟 VLOOKUP
通常,有必要将不同数据集中的两个变量组合起来,类似于在 Excel 中使用 VLOOKUP 根据特定标准连接两个变量。如果你不熟悉 VLOOKUP 函数,你可能会发现 Spreadsheeto 的这个指南特别有用。
在 R 中,这可以使用 merge 函数来完成。
例如,假设我们希望将 sales 数据集中的 Date 变量与 customers 数据集中的 Age 和 Country 变量链接起来,用 ID 变量作为公共链接。
因此,我们做如下工作:
mergeinfo<-merge(mydata[, c("ID", "Sales")],mydata2[, c("ID", "Age", "Country")])
这样做后,我们看到在 R 中形成了一个新的数据集,它连接了我们选择的变量:

3。使用 as.date 格式化日期并计算持续时间
假设我们现在希望计算当前日期和销售文件中列出的销售日期之间的天数。为了实现这一点,我们可以使用 as.date,如下所示:
currentdate=as.Date('2016-12-15')
dateinfile=as.Date(Date)
Duration=currentdate-dateinfile
回到上面的例子,假设我们现在希望将这个持续时间变量与其余的数据结合起来。
因此,我们现在可以将我们的新 Duration 变量与上面的 merge 函数结合起来,并且可以这样做:
durationasdouble=as.double.difftime(Duration, units='days')
updateddataframe=data.frame(ID,Sales,Date,durationasdouble)
updateddataframe

4。使用 as。POSIXct 和 format 来计算秒之间的差异
虽然在上面的例子中情况并非如此,但在我们拥有包含时间的日期的情况下,经常会出现这样的情况,例如“2016–10–13 19:30:55”。
有时,我们可能希望找出两个日期的秒数之间的差异。对此,作为。POSIXct 是比 as.Date 更合适的选项。
date_converted<-format(Date, format="%Y-%m-%d %H:%M:%S")
new_date_variable<-as.POSIXct(date_converted)
seconds<-diff(new_date_variable,1)
当我们定义秒变量时,它会给出两个日期之间的秒差。然后,这是一个简单的算术问题,以获得分钟和秒的差异。
minutes<-seconds/60
hours<-minutes/60
5。grepl:从变量中删除一个字符串的实例
让我们看看国家变量。假设我们希望从变量中删除所有“Greenland”的实例。这是使用 grepl 命令完成的:
countryremoved<-mydata2[!grepl("Greenland", mydata2$Country),]
6。使用头尾功能删除观察值
如果我们希望从变量中删除某些观察值,例如销售额,可以使用 head 和 tail 函数。head 函数允许我们删除前 30 行,而 tail 函数允许我们删除后 30 行。
当使用以这种方式编辑的变量进行计算时,例如回归,as.matrix 函数也用于将变量转换为矩阵格式:
Salesminus30days←head(Sales,-30)
X1=as.matrix(Salesminus30days)
X1
Salesplus30days<-tail(Sales,-30)
X2=as.matrix(Salesplus30days)
X2
7。使用“聚集”功能复制 SUMIF
names <- c("John", "Elizabeth", "Michael", "John", "Elizabeth", "Michael")
webvisitsframe <- cbind("24","32","40","71","65","63")
webvisits=as.numeric(webvisitsframe)
minutesspentframe <- cbind("20", "41", "5", "6", "48", "97")
minutesspent=as.numeric(minutesspentframe)
假设我们已经创建了如下表格,并希望获得在任何特定时间段内网站访问量和在网站上花费时间的总和:

在这种情况下,我们可以通过使用 r 中的聚合函数来复制 Excel 中的 SUMIF 函数(其中与特定标识符相关联的值被求和),这可以按如下方式完成(其中 raw_table 是上面指定的表):
sumif_table<-aggregate(. ~ names, data=raw_table, sum)
sumif_table
因此,与标识符(在本例中是名称)相关联的值总结如下:

根据堆栈溢出中的示例,plyr 和 data.table 库也可用于实现相同的结果,如下所示:
library(plyr)
ddply(nametable, .(names), summarise, Sum_webvisits = sum(webvisits), Sum_minutesspent = sum(minutesspent))
library(data.table)
DT <- as.data.table(nametable)
DT[ , lapply(.SD, sum), by = "names"]
8。使用 diff()函数计算滞后
当进行时间序列分析时,经常需要计算特定变量的滞后时间。为了在 R 中做到这一点,我们使用 diff()函数。
在本例中,我们创建一个矩阵,以价格数据作为列名,以年份作为行名:
pricedata <- matrix(c(102, 90, 84, 130, 45), ncol=1)
colnames(pricedata) <- c('Price')
rownames(pricedata) <- c('2012', '2013', '2014', '2015', '2016')
pricedata.table <- as.table(pricedata)
pricedata.table
Year	Price
2012	102
2013	90
2014	84
2015	130
2016	45
2\. Lag = 1diff(pricedata.table,1)
Year	Price
2013	-12
2014	-6
2015	46
2016	-85
3\. Lag = 2diff(pricedata.table,2)
Year	Price
2014	-18
2015	40
2016	-39
4\. Differences = 2diff(pricedata.table,differences=2)
Year	Price
2014	6
2015	52
2016	131
9。按列表分隔(对面板数据集有用)
假设我们有一个需要分离的数据集,例如通过 ID。手动操作会导致一个相当混乱的过程。相反,我们可以使用 unique 和 split 函数来形成一个列表。这里有一个如何做到这一点的例子。
使用包含日期、姓名和 id 的数据框:
> Date<-c("20/02/2017","21/02/2017","22/02/2017","20/02/2017","21/02/2017","22/02/2017")
> ID<-c("20","20","20","40","40","40")
> Name<-c("Brian","Brian","Brian","Adam","Adam","Adam")
> df<-data.frame(Date,ID,Name)
> df
        Date ID  Name
1 20/02/2017 20 Brian
2 21/02/2017 20 Brian
3 22/02/2017 20 Brian
4 20/02/2017 40  Adam
5 21/02/2017 40  Adam
6 22/02/2017 40  Adam
但是,我们希望通过按 ID 过滤将观察结果分成两个单独的列表。我们将这样做,如下所示:
> listofids=as.character(unique(df$ID))
> mylist <- split(df, df$ID)
> mylist
$`20`
        Date ID  Name
1 20/02/2017 20 Brian
2 21/02/2017 20 Brian
3 22/02/2017 20 Brian$`40`
        Date ID Name
4 20/02/2017 40 Adam
5 21/02/2017 40 Adam
6 22/02/2017 40 Adam
这是完整的列表。如果我们希望一次调用一个(通过 ID 作为我们的唯一标识符,我们可以这样做:
> mylist[1]
$`20`
        Date ID  Name
1 20/02/2017 20 Brian
2 21/02/2017 20 Brian
3 22/02/2017 20 Brian
> mylist[2]
$`40`
        Date ID Name
4 20/02/2017 40 Adam
5 21/02/2017 40 Adam
6 22/02/2017 40 Adam
结论
上面的例子说明了我们在 R 中进行数据操作过程的各种方法,以及复制普通 Excel 函数(如 VLOOKUP)的技术。非常感谢您的宝贵时间,上面例子的相关 GitHub 库再次在这里可用。
你也可以在 michael-grogan.com 的找到更多我的数据科学内容。
免责声明:本文是在“原样”的基础上编写的,没有担保。本文旨在提供数据科学概念的概述,不应以任何方式解释为专业建议。
Python 数据清理系列:第 1 部分
数据预处理
回到基础——处理缺失值

“计算机上的代码”由马库斯·斯皮斯克在 Unsplash 上发表
垃圾进,垃圾出——嘿
几个月前,我和我的一个朋友聊天,他最近申请了班加罗尔一家 IT 公司的高级数据科学职位。作为面试过程的一部分,为了解决一个业务问题,他得到了一个数据集。他开始解释他的方法,很快就被面试官打断了。当我问他原因时,他说,“他们关心的只是我选择的用于数据的算法。”
数据科学领域已经存在了相当一段时间。尽管如此,仍然有很多人低估了干净数据的价值。机器学习算法的好坏取决于输入的数据。
因此,在将你的数据输入你的算法之前,对其进行清理和辩论是至关重要的。
本系列将有助于向该领域的新手灌输有关数据预处理的最佳实践,并为社区中的老成员提供全面的复习。
缺少值的情况
研究人员在进行研究时通常会采取非常谨慎的措施。许多此类研究的主要结果是收集数据。不幸的是,许多研究最终都丢失了信息。必须处理缺失值,因为它们会对我们的机器学习算法的预测能力产生负面影响。然而,某些算法会绕过丢失的值。
数据中缺少值的原因很多。调查数据集的参与者可能选择不共享信息,数据录入人员可能会犯错误,收集数据的自动机器可能会出错等。
我们必须接受人为错误是不可避免的——并围绕这一事实进行设计——唐纳德·伯威克
维基百科定义了三种缺失数据:
- 完全随机失踪(MCAR)
 - 随机失踪(3 月)
 - 非随机缺失(MNAR)
 
我不会详细说明其中的复杂性,但是你可以在这里阅读。
通常,我们会发现数据中缺失值的多种表现形式。有时它们由单个特殊字符表示,如.(句号)、*(星号)。其他时候可以用N/A、NaN或者-999来代表。
让我们看一个这样的数据集。
资料组
我们将使用的数据集是来自 UCI 机器学习知识库的糖尿病数据集。可以从这里下载。让我们快速地看一看。

糖尿病数据集的前 10 个值。
# Check number of rows and columns after removing outcome variable.diabetes.shapeOutput:
(768, 8)
该数据具有 768 个观察值/行和 8 个变量/列。这里面似乎也没有缺失的价值。让我们通过在每一列中随机插入缺失值来解决这个问题。我们将以 0.1 或 10%的因子在每一列中引入缺失值。



注意数据中的某些观察值是如何被称为NaN的。这是 Python 中缺失值的默认表示法。接下来,让我们讨论一些处理这些值的技术。
处理缺失值
移除观察值
也称为 列表式删除 ,这种技术简单地涉及删除整个观察值,如果它有一个或多个丢失的值。如果在非常大的数据集中有少量缺失值,可以选择这种方法。

我们观察到,在列表式删除之后,超过一半的数据集被擦除。看起来我们已经失去了很多有价值的信息让我们的准模特去学习。
此外,它还会影响 统计检验 的功效,因为它们需要大样本量。显然,在这种情况下,这种方法似乎不太合适。
用 0 插补
在这种方法中,数据中所有缺失的值(用NaN表示)都被替换为数字0。


Python 中的 pandas 库有一个名为 *pandas.DataFrame.fillna* 的方法可以帮助我们完成这个任务。
起初,这种方法似乎是一个有吸引力的选择,因为我们能够保留我们所有的观察结果。此外,这是一种快速的估算方法。然而,仔细观察各个列,我们可以看到,将 0 加到一堆行上会在数据集中引入大量的偏差。实际上,那些丢失的条目可能具有远离数字 0 的值。
中心值插补
中心值插补是一种将缺失值替换为各自的中心趋势度量值的方法,又称均值、中位数、众数。对于数值变量,最好使用平均值或中值,而对于分类变量,则使用众数。
这背后的原因是,对于分类变量而言,均值和中值没有意义,因为分类变量具有定性属性而非定量属性。因此,为了说明集中趋势,我们使用 Mode,因为它是最频繁出现的值。
Python 的scikit-learn库有一个名为SimpleImputer的模块,它执行中心值插补。
strategy参数用于设置我们需要的插补类型。
这种形式的插补有其优点,特别是对于低方差数据。如果我们有非常不稳定的特征,用这种方法估算可能不是一个好主意。然而,与以前的技术相比,它通常是一种快速且更好的估算方法。

作为输入者的学习算法
到目前为止,我们只研究了处理缺失值的简单方法。当我们的数据变得复杂时,我们需要更好的估算方法。
在这一部分,我们将看看几个我们喜爱的学习算法,以及它们如何帮助我们估算缺失值。
回归插补
回归插补是相当不言自明的。这种形式的插补使用多元线性回归原理来插补数值。如果你需要线性回归的复习,那么看看我的线性回归系列。
大众体育故事的统计案例研究
towardsdatascience.com](/linear-regression-moneyball-part-1-b93b3b9f5b53)
为了概括线性回归,我们挑选一个因变量或输出 y ,并使用多个自变量 X 来拟合一个能够预测y 的函数。*使用 X 中的变量作为输入量或回归量来预测。***
在回归插补中,带有缺失值的一列被选作我们的 y ,其余的列被用作输入变量X来拟合y .该函数用于预测 y. scikit-learn列中的缺失值。****
虽然回归插补似乎可行,但它也有局限性。由于我们使用拟合值作为插补的输出,我们的插补值将非常精确。
这是因为与正常的线性回归模型不同,回归插补缺少一个 误差 项。完全消除了这些估算值的不确定性。
k-最近邻插补
也被称为 Knn 插补,这种插补形式使用K-最近邻算法来插补数值。
这个算法很好解释。它查看 k 个条目,并比较它们与有缺失值的条目之间的“距离”。这里的 k 值由用户定义。k 的合适值的经验法则是取观察次数(N)的平方根。

乔恩·泰森在 Unsplash 上的照片
k-NN 算法使用距离度量来选择与我们感兴趣的行最近的邻居。
用于数字属性的最常见的距离度量通常是曼哈顿距离( L1 范数)或者欧几里德距离( L2 范数)。在分类变量中,最流行的距离度量是余弦相似度、雅克卡距离和汉明距离。计算距离后,缺失值由“相邻”行的多数投票(分类)或平均值/加权平均值(数值)确定。
在上面的例子中,k=3
k-NN 插补是一种非常有效的插补方法。对于小型、中型数据集,它通常能获得非常好的结果。在大数据集上,算法的运行时间大大增加。此外,对于特别具有大量特征(列)的数据集,会出现维数灾难问题。
结论
在这篇博文中,我们来看看一些插补方法,以处理缺失数据。作为数据科学领域的从业者,我们必须理解每种方法的优势和局限性。这将帮助我们在构建数据预处理管道时做出明智的决策。
请注意,以上插补技术列表并非详尽无遗。还有许多其他的高级方法来处理缺失值,这超出了本文的范围。一种这样的插补类型是小鼠插补。
如果你喜欢这个帖子,请在媒体上关注我,并在 LinkedIn 上给我发一个邀请。查看我关于数据科学的其他帖子。下次见。✋
参考文献:
[1]https://sci kit-learn . org/stable/modules/classes . html # module-sk learn . impute
【2】https://en . Wikipedia . org/wiki/attubation _(统计)
使用 Python Pandas 清理数据
使用内置 Pandas 函数在分析前清理数据的综合指南

介绍
随着时间的推移,公司会产生和收集大量数据,根据公司的不同,这些数据可能以多种不同的形式出现,如用户生成的内容、求职者数据、博客帖子、传感器数据和工资单交易。由于可以生成数据的源系统数量巨大,以及参与数据生成的人数众多,我们永远无法保证我们接收到的数据是干净的记录。这些记录可能由于缺少属性而不完整,它们可能在用户输入的文本字段中有不正确的拼写,或者它们可能有不正确的值,例如将来的出生日期。
作为一名数据科学家,在探索阶段尽早发现这些数据质量问题,并在进行任何分析之前进行清理,这一点非常重要。由于允许未经清理的数据通过我们的分析工具,我们可能会因基于不正确的数据得出质量低劣的调查结果而承担错误地代表公司或用户数据的风险。今天我们将使用 Python 和 Pandas 来探索一些可用于清理数据集的内置函数。
入门指南
对于今天的文章,我们使用的是为 Python 构建的集成开发环境 PyCharm 。对于初学者来说,这是一个非常好的工具,因为它简化了虚拟环境的创建和特定 Python 包(如 Pandas)的安装。使用虚拟环境允许您管理项目依赖性,而不会影响操作系统的默认 Python 安装。
首先打开 Pycharm 并从导航栏中选择File > New Project。在这里,您可以使用Location命名您的项目,或者创建一个新的虚拟环境,或者引用一个现有的虚拟环境。

PyCharm 的“新项目”对话框显示了命名项目的位置和虚拟环境创建路径。
为了让你开始,我们在下面创建了一个基本的 Python 脚本和一个 CSV 文件,这两个文件在整篇文章中都将被引用。这两个文件都可以下载并保存到您的项目根目录下。最终的剧本可以在这里找到。
Python 代码片段读取 CSV 文件,将特定列转换为默认数据类型,并重命名列。
上面的脚本演示了在将文件读入内存后的一些数据帧操作。在第 5–7 行,我们覆盖了许多 Pandas 的默认配置,这些配置在处理较大的文件时会在打印时截断控制台输出。为了将数据读入内存,我们在第 10 行使用 Pandas 内置函数read_csv(),它将一个文件名作为参数。在第 13–15 行,我们设置了三列的数据类型,这有很多好处。首先,通过减少内存占用,设置数据类型可以提高处理数据帧行的性能。其次,丰富了我们在运行 Pandas .describe()内置函数时得到的描述性统计输出。在第 18 行,我们执行了一个列重命名,这是一个将通用列名转换成更有意义的名称的常用方法。
清理数据帧
为了了解数据集的哪些方面需要清理,我们首先需要了解我们正在处理哪些数据。最好的方法是使用熊猫内置函数.info()和.describe()。

调用熊猫内置函数后的控制台输出。信息()。
上面的.info()的结果清楚地显示了非空元素的数量,因此可以使用第一行的 RangeIndex 推导出空元素的数量。总结这一点的一个快速方法是调用df.isnull().sum(),它对每一列中的空元素的数量进行求和。

调用熊猫内置后的控制台输出。isnull()。sum()函数。
如果我们需要知道空元素占整个数据集的百分比,那么我们可以做以下事情。
用于计算缺失元素占整个数据集的百分比的 Python 代码片段。
删除列
调用.info()和.isnull().sum()后跳出的一个元素是跨越 1000 条记录有 1000 个空值的tax_file_no。移除这些类型的行最简单的方法是使用 Pandas .dropna()。.dropna()功能采用.dropna(axis=0, how='any', thresh=None, subset=None, inplace=False)的形式。axis参数决定该函数是应用于行axis='index'还是列axis='columns'。how参数可以是how='any'或how='all',这意味着如果任何或所有元素都为空值,则可以删除该列或行。thresh参数允许您设置列或行中所需的非空元素的最小数量,否则将被删除。subset参数是可选的,可以接收列名列表,如果列表为空,那么.dropna()函数将应用于所有列或行。inplace可以是True也可以是False,如果是True则返回None。对于我们的例子,我们将使用df.dropna(axis='columns', how='all', inplace=True)。执行.dropna()并将数据帧信息打印到控制台后,您会注意到tax_file_no列不再包含在内。

来自的控制台输出。执行后的 info()。显示 tax_file_no 列的 dropna()已被删除。
删除行
在检查完完全为空的列之后,有必要检查是否有任何行没有包含足够的可用元素。我们可以通过使用.dropna(thresh=2)删除任何少于两个元素的行来实现这一点。
Python 代码片段显示了如何检查将被移除的少于两个元素的行。
在第 2 行,我们删除所有少于两个元素的行。然后,第 3 行返回原始数据帧中其索引不存在于under_threshold_removed中的任何行,即被删除的行。它通过否定~熊猫内置的.index.isin()功能来实现这一点。在我们的示例中,返回一条只包含雇员编号的记录。
填充缺失值
在某些情况下,我们可能希望保留包含缺失值的行,而不是在缺失时给它们一个默认值。对于这个例子,我们将把性别列中的空值映射到未知的 U 。熊猫提供了一个内置功能,可以实现这个.fillna(value=None, method=None, axis=None, inplace=False, limit=None, downcast=None)。
熊猫.fillna()在清理数据或操作数据帧时是一个非常强大的功能。value参数可以接受一个字典,该字典允许您指定将在特定列上用来填充空值的值。这样做的好处是当您不希望对数据帧中的所有空元素应用相同的空填充值时。method参数允许您根据序列中的其他值填充空值。您可以将方法设置为ffill,它将使用序列中存在的最后一个有效值来填充空值。bfill方法选项执行类似的功能,但填充值取自系列中出现的下一个有效值。axis和inplace参数获得与上述.dropna()功能相同的结果。如果您已经设置了method参数,您可以使用limit参数告诉.fillna()向前/向后检查连续空值的最大数量,以达到有效值。如果method参数为None,则limit参数可用于设置系列中空值的最大数量,该数量将由传递的值填充。
由于gender列具有分类数据类型,在我们将缺失值映射到 U 之前,我们首先需要在序列中创建一个新的类别。
Python 代码片段显示了如何在映射系列中缺失的值之前添加新类别。
要添加一个新的类别,我们需要将gender列隔离为一个系列,并调用.add_categories()。这将允许你使用接受列表的new_categories=[]来传递新的类别。一旦创建了新类别,您就可以使用.fillna()并引用新类别。要查看所做的更改,您可以调用df['gender'].value_counts(),这将隔离gender列,并为系列中的每个类别提供一个值计数。

显示 206 个缺失值的控制台输出现在映射到性别列中的新类别 U。
提高可读性
在这种情况下,我们理解类别 M、F 和 U 背后的含义,但是,接收数据的利益相关者可能不理解。为了提高分析的可读性,我们可以将类别重命名为更有意义的名称。
Python 代码片段显示了如何重命名性别列中的类别。
上面的代码片段使用了内置函数.rename_categories(),该函数接受一个将当前类别映射到新类别的字典。下面显示了重命名的结果。

显示性别列中新重命名的类别的值计数的控制台输出。
摘要
作为一名数据科学家,在你的职业生涯中,你会遇到不完整和质量差的数据集。为了生成高质量的分析,我们需要确保我们正在清理数据,以便准确地表示数据集。Pandas 提供了各种各样的内置功能,可用于在分析之前清理和操作数据集。它允许您删除不完整的行和列,填充缺失的值,并通过类别重命名提高数据集的可读性。
感谢您花时间阅读我们的故事,我们希望您觉得它很有价值。
用熊猫清理数据——避免这个错误!

https://unsplash.com/photos/FOsina4f7qM
Pandas 是 Python 中一个非常有用的数据操作包。在很大程度上,函数是直观的,快速的,易于使用的。但是有一次,我花了几个小时调试管道,发现在 Pandas 列中混合类型会导致管道中出现各种问题。多读一点去发现我的意思,避免以后这样做。
什么是混合型栏目
混合类型正是您所想的:它们是具有多种类型(string、integer、float 等)的列。在 pandas 中,创建混合型列非常容易:
import pandas
df = pd.DataFrame({"price": [9.99, "$9.99"]})
print(list(map(type, df["price"])))
这输出【浮点,str】。这些混合类型列将始终使用“object”数据类型作为其 d type:

这是因为 Pandas 在幕后使用了 Numpy 数组,Numpy 的 dtypes 之一就是 Python 对象本身。因此,当多个类型被引入到一个列中时,Pandas 将使用这个“全部捕获”选项,而不是抛出一个错误(当您有字符串时,请参阅下面的参考资料,了解为什么它是一个对象数据类型,至少在 Pandas 1.0 之前是这样)。如果创建一个全是整数的熊猫序列,然后添加一个字符串,就可以看到这一点。
import pandas as pd
int_series = pd.Series([1, 2, 3])
print(int_series.dtype)  # dtype('int64')
int_series.loc[3] = "4"
print(int_series.dtype)  # dtype('O')
这是由设计决定的,类似于将数据输入 Excel 电子表格的设计模式。
这会导致问题
假设您有几个文件要合并。
sales_data = pd.read_csv("data/sales_data.csv", parse_dates=["date"])census_data = pd.read_csv("data/population_by_zip_2010.csv")
population = census_data.groupby("zipcode")["population"].sum().reset_index()





我们需要合并邮政编码,但是为了这样做,我们需要首先清理 sales_data 邮政编码。让我们从 9 位数的邮政编码中提取出前 5 位数。有一些缺失值,假设经过调查,我们知道 2018 年之前所有缺失的邮政编码是 90001,之后所有缺失的邮政编码是 90002。
sales_data["zip_code"] = sales_data["zip_code"].str[:5]sales_data.loc[sales_data["zip_code"].isna() & (sales_data["date"] < pd.to_datetime("2018-01-01")), "zip_code"] = 90001sales_data.loc[sales_data["zip_code"].isna() & (sales_data["date"] >= pd.to_datetime("2018-01-01")), "zip_code"] = 90002
现在,我们准备合并
sales_and_population = pd.merge(sales_data, population, left_on="zip_code", right_on="zipcode")

看起来不错,对吧?

嗯,这似乎太低了。现在你可能想知道这是不是因为右边的数据框人口中缺少数据。但不是,这是因为左边的 dataframe sales_data 的 zip_code 列中有混合类型。

当我们用 90001 和 90002 替换缺失的邮政编码时,引入了我们的 int。这些是唯一成功连接到人口数据框架的行,该数据框架的 dtype 为 int 。为了避免这个问题,我们需要在合并之前将我们的类型转换为 int 类型。
sales_data = sales_data.astype({"zip_code": int})sales_and_population = pd.merge(sales_data, population, left_on="zip_code", right_on="zipcode")

关键提示:用熊猫清理数据的时候要小心——类型不是强制的,以后可能会让人头疼,所以要经常检查你的类型,必要的时候进行强制转换!
参考
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/sm14159/pandas-mixedtype/blob/master/notebook/pandas-mixedtypes.ipynb)
数据清理—从哪里开始?

数据清理/争论指南和清单
事实证明,数据科学家和数据分析师将把大部分时间花在数据预处理和 EDA 上,而不是训练一个机器学习模型。作为最重要的工作之一,数据清洗的确非常重要。
我们都知道我们需要清理数据。我想大多数人都知道。但是从哪里开始呢?在本文中,我将提供一个通用的指南/清单。因此,一旦我们开始一个新的数据集,我们就可以像这样开始数据清理。
方法论(C-R-A-I)

如果我们问自己“为什么我们需要清理数据?”我认为,很明显,这是因为我们希望我们的数据遵循一些标准,以输入某种算法或以一致的规模可视化。因此,让我们首先总结一下我们希望我们的数据有哪些“标准”。
在这里,我总结了清洗数据集应该具备的 4 个主要标准。我会称之为“CRAI”。
- 一致性
 
每一列数据在同一比例尺上应该是一致的。
- 合理性
 
每列中的所有值都应符合常识。
- 原子数
 
数据条目不应重复,数据列不应分割。
- 完整性
 
数据条目应该具有所有可用的特性,除非空值有意义。
好的。请记住这 4 个标准。我会用更多的例子来解释它们,希望它们能成为你能记住的东西。
一致性

由absolute vision在 Pixabay 上拍摄的照片
不管是连续的还是分类的,绘制柱状图都是很有帮助的。我们需要注意最小值/最大值、平均值和分布的形状。然后,用常识去发现是否有潜在的不一致。
例如,如果我们对一些人进行抽样,其中一列数据是他们的体重。假设直方图如下。

很明显 80 到 100 之间几乎没有。运用我们的常识就足以找出问题所在。也就是说,一些重量以千克为单位,而另一些重量以磅为单位。
当我们有多个数据源时,这种问题很常见。其中一些可能对相同的数据字段使用不同的单位。
清洗之后,我们可能最终会得到一个这样的分布,看起来不错。

合理性

这也要靠我们的常识,但通常更容易被发现。一些常见的例子:
- 人的年龄、体重、身高不应该是负数。
 - 一些分类数据(如性别)会有特定的枚举值。否则,它是无效的。
 - 大多数类型的文本值(如人名和产品名)不应该有前导空格和尾随空格。
 - 有时候我们可能还需要注意特殊字符。大多数情况下,它们应该被剥离出来。
 
原子数

照片由 Pixabay 上的 WikimediaImages 拍摄
这个很好理解。我们的数据集中不应该有任何重复的行。当我们有多个数据源时,不同的数据源可能会存储重叠的数据,这种情况很常见。
将唯一性检查留在一致性和合理性检查之后是很重要的,因为如果我们不解决一致性和合理性问题,将很难找出重复的行。例如,一个人的名字可能在不同的数据源中以不同的方式呈现,比如González和Gonzalez。一旦我们意识到一些非英语名字的存在,我们需要注意这类问题。
因此,尽管删除重复的行通常并不难,但是这样做的另一个问题可能会影响清理后的数据的最终质量。
违反原子性的另一种类型是一列可能是可分的,这意味着一列中隐藏了多个特性。为了最大化数据集的价值,我们应该把它们分开。
例如,我们可能有一个表示客户名称的列。有时可能需要将它分为名和姓。
完整

由 Pixabay 上的absolute vision拍摄的照片
根据数据源和数据结构的设计方式,我们可能会在原始数据集中丢失一些数据。这种数据丢失有时并不意味着我们丢失了一些数据条目,而是我们可能丢失了某些列的一些值。
发生这种情况时,确定“null”或“NaN”值在数据集中是否有意义非常重要。如果没有,我们可能需要删除该行。
但是,消除缺少值的行并不总是最好的主意。有时,我们可能会使用平均值或其他技术来填补空白。这取决于实际情况。
CRAI 方法的使用

照片由 blickpixel 在 Pixabay 上拍摄
好吧,我希望上述例子分别解释了什么是“CRAI”。现在,让我们举一个真实的例子来练习!
假设我们的数据集中有一个地址列,我们应该做什么来确保它是干净的?
C — 一致性
- 地址可能包含街道后缀,如“street”和“St”、“Avenue”和“Ave”、“Crescent”和“Cres”。检查我们是否在那些对中有两个术语。
 - 同样,如果我们在地址中有州名,我们可能需要确保它们是一致的,比如“VIC”和“Victoria”。
 - 检查地址的单元号表示。“Abc 街 24 号第 9 单元”应与“Abc 街 9/24 号”相同。
 
R —合理性
- 例如,在一个国家,邮政编码必须遵循特定的格式。例如,在澳大利亚必须是 4 位数。
 - 如果地址字符串中有国家,我们可能需要注意这一点。例如,数据集是关于在几个国家开展业务的一家国际公司的所有客户。如果出现不相关的国家,我们可能需要进一步调查。
 
a——原子性
- 最明显的原子性问题是我们应该将地址分成几个字段,比如街道地址、郊区、州和邮政编码。
 - 如果我们的数据集是关于家庭的,比如一份健康保险。更值得注意的是不同数据条目的重复地址。
 
一、诚信
- 这是关于数据集中的整个数据条目(按行)。当然,我们需要删除重复的行。
 - 检查是否有任何数据条目的地址丢失。根据业务规则和数据分析目标,我们可能需要删除没有找到地址的行。此外,地址通常不应该能够被导出,所以我们不应该需要填补空白,因为我们不能。
 - 如果在原子性检查中,我们发现一些行具有相同的地址,并且根据业务规则这可以被确定为重复的,我们可能需要合并或消除它们。
 
摘要

这是我第一次使用新数据集时通常遵循的“CRAI”方法。
事实证明,这种方法是通用的,这意味着它应该适用于几乎所有的场景。然而,也正是因为它的普遍性,我们应该更加关注将影响如何应用 CRAI 清理数据集的领域知识。
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@qiuyujx/membership)
如果你觉得我的文章有帮助,请考虑加入灵媒会员来支持我和成千上万的其他作家!(点击上面的链接)
数据加工:为什么我们都应该玩数据
从一个新的角度看待数据和数据表示

一个很好的数据加工的例子来自我们的一个参与者,周天琦。
我最近主持了一个关于数据加工的研讨会。这个想法(通过制作数据来弄脏我们的手)是在我和哈佛医学院的定量研究员娜塔莉·弗拉迪斯的一次谈话中自发产生的。
事情是这样的:娜塔莉热爱手工艺,生活在数据中。我爱数据可视化,偶尔大杂烩的东西,相信大人玩不够。在一月份,我们希望促成一个有创意的、动手操作的数据约会——让数据变得平易近人 并建立一个专家可以探索其数据的新方面的空间。
玩耍的价值是有科学依据的。但是在数据的背景下玩?那是比较新的。该领域的大多数文献都专注于培养儿童的数据素养,虽然设计经常整合游戏的各个方面来激发新的工作,但它未能有效地渗透到其跨学科邻居数据可视化中。
游戏来自好奇、探究和探索。通过保持好奇心并允许自己去探索,我们在没有期望或竞争压力的情况下学习新技术,并且发现世界未知的一面。当我们被某样东西吓倒时,或者当我们已经习惯了它,把它与世俗联系起来时,这一点尤其重要。
但是我们认为数据是严峻的——完美的——这使得它很难处理。
将普通大众所认为的数据的复杂性(如果你愿意,可以说是一种内在的信念)与可视化的 修辞力量 结合起来——这是我们发现很难对其进行事实检查、调试和评论的主要原因——我们发现了一个难题:数据及其表示是不可接近的。
我指的是数据,作为一个无形的大概念,很可怕。人们回避它。那些经常与数据打交道的人(如分析师、研究人员和科学家)通常只理解一个概念,一个角度,即数据是什么,因此他们在表示和处理所述数据的方式上受到限制。因为数据感觉很难处理。
这就是数据加工的由来。数据应该有趣,应该平易近人,应该被玩弄。娜塔莉和我能想到的最好的方法就是手工制作。
但是首先为什么要制作?什么是手工艺?和数据物理化有什么区别?
“工艺是纪律和想象力、奉献和灵感的结合。当这些东西互相缠绕,并对这种炼金术给予认真的关注,那么一个人的手艺就可以实现了”——罗莎妮·卡什
从历史上看,手工艺是一种熟练的劳动,为未来的观众维护传统艺术。为了应对 19 世纪有害的工厂环境,手工艺的定义演变成了反工业化,提升了消费者和生产者的福祉。然后(在 20 世纪)工作室工艺增加了新的含义:对一致性的反叛。
我们对工艺的现代理解建立在传统艺术的基础上——从绗缝到其他。手工艺通过创造任何东西,不管是材料还是技术,从定制的椅子到手工啤酒到手工制作的绒球,充当一种个人代理的形式。最重要的是,现代手工艺是任何人都能做的事情。
让我们回到最初的问题:什么是数据加工?它代表数据,这里有:
- 一个对工艺的强调,因此期望和规范的限制被忽略,所有的感官被给予空间和参与。
 - 一个强调发挥,让数据变得平易近人。通过使用各种媒介——传统的和非传统的——在一个不完美的空间里,我们可以使探索正常化。
 
不是什么?
可及性的论证。虽然使用多种媒体可以促进与更广泛受众的联系,但在可访问数据表示领域还有许多工作要做。

另一个手工艺的例子,这个是斯蒂芬妮 h。
但是数据加工和数据物理化有什么不同呢?对我和娜塔莉来说,这就是游戏。正如数据物理化维基所说,“数据的物理表示已经存在了数千年。”印加 Quipus,马绍尔群岛棒图,亚卡马时间球是说明这一点的少数例子。从历史的角度来看,这些都是数据加工的产物。

马绍尔群岛棒图示例。来源:库珀·休伊特
数据物理化在研究社区中被重新定义,以描述计算机支持的物理数据表示。在不涉及计算机的情况下,表现仍然是精心策划的,看起来“完美”。正如我们已经讨论过的,感知到的完美让我们很难演奏。
虽然数据物理化和数据加工之间肯定有重叠,但物理化并不强调玩耍。这就是我们如此兴奋的原因!
我们将数据加工描述为与数据物理化相邻或者是数据物理化的一个子集,其中的重点不是一个完美的、随时可以拍照的对象,而是做的过程——用你的手玩,用所有五种感官体验。

因为,正如阿尔伯特·爱因斯坦曾经说过的,“玩耍是研究的最高形式。”当数据是一切研究的基础时,我们怎么能不想玩它呢?考虑到这一点,我鼓励你们所有人都来玩数据——也许还需要一点技巧;)
这是我将要写的关于数据加工的两篇文章之一。这第一篇文章为为什么我们想要精心制作数据奠定了基础。下一个的探索我们如何做到这一点,并分享一些要点,这样你也可以玩数据。敬请期待!
数据民主为组织释放价值。以下是开始的方法

来源:Pixaby
87% 的组织在分析和商业智能(BI)成熟度方面较低,根据 Forrester 的说法,这意味着大多数数据和分析计划都是孤立于各个业务部门的独立项目。
这种情况多久发生一次?你是一名营销人员,正在创建一个关于现有客户的案例研究,但是你必须通过重重困难才能获得正确的数据。或者,您可能是一名分析师,因为团队之外的任何人都无法访问您的报告,所以您的见解是孤立的。在我们的职业生涯中,我们都经历过类似的事情。
组织知道更好地利用数据会带来明显的好处,但很少有组织将数据有效地集成到他们的业务中。事实上, 88% 的高管感到投资大数据的紧迫性;然而10 个 中有 7 个说他们既没有创建一个数据驱动的组织,也没有在公司内部打造一种数据文化。
数据文化的一部分包括访问、共享和利用数据的方式。大多数公司都是数据君主和数据贵族和,在这些公司中,数据访问受到严格控制,只保留给组织中特定的一部分人。但人们越来越渴望另一种数据文化——一种让尽可能多的人能够接触到数据,从而为公司创造最大价值机会的文化。
引入数据民主
**数据民主是让组织内的非技术和非 IT 人员可以使用数据的概念。这种方法的核心是释放任何员工通过访问数据创造本地价值的潜力。
会是什么样子?一个例子是可通过搜索发现的项目的有组织的目录。考虑到治理和隐私法规遵从性,公司中的任何人都可以访问他们需要的任何内容。在受控的形式下,这甚至可以扩展到外部共享数据。
虽然数据民主的实施可能具有挑战性,但好处是相当可观的。此外,这里有一些使您的数据民主化成为现实的必要因素。
为什么公司要这么做?
开放数据访问不仅仅是前瞻性思维的表演秀——它有切实的商业利益。
根据麦肯锡全球调查,表现最佳的公司使其数据可在整个组织内访问,并为员工提供自助服务分析工具来运行可定制的查询。与表现不佳的同行相比,这些公司认为分析对收入有更大影响的可能性是40 倍。
性能是受数据民主或缺乏数据民主影响的另一个因素。让我们看看销售,可以说是产生最明显、最有形价值的业务职能。根据销售绩效管理 SaaS 公司 Xactly 的首席执行官的说法,销售副总裁的平均任期仅为 19 个月。然而,当谈到配额实现时,任期较长的销售代表往往表现更好,通常需要 3 年才能达到最佳业绩。
这部分是因为那些存在时间更长的人会更好地理解产品,并能获得不容易获得的数据点。如果这些见解被捕获到一个单一的存储库中,供整个团队使用,会怎么样?将数据大众化可以作为销售支持解决方案,帮助减少新员工的增加时间,让更多员工更快达到最佳绩效。
一个可搜索的数据产品目录不仅可以作为发现新产品和服务的催化剂,还可以改进现有的产品和服务。如果实施得好,即使非技术人员也可以在不引入工程的情况下发现新的见解,从而带来节省时间和通过支持新用例产生价值的双重好处。
数据民主的关键要素
数据民主当然有相当大的潜力,但是组织可能还没有准备好实现它。为了获得使数据可访问的好处,有一些关键的先决条件:
- 内部和外部整合
 - 定义的输入模式
 - 数据集的可识别目录
 - 可导性
 
1。内部和外部整合
首先,需要一种简单的方法来连接到内部 BI 和第三方 SaaS 工具等系统。员工应该能够去一个地方进行调查,了解现有的数据,然后才能使用这些数据做任何事情。
2。定义的输入模式
不同的应用程序在映射和术语方面总是存在差异。定义这种映射可以更好地理解输入数据的格式,这样最终用户就不必解释命名约定的差异。
3。数据集的可识别目录
现在映射已经存在,以用户友好的可读格式呈现给用户。这意味着要有一个有组织的、可搜索的数据集目录,其中包括元数据,这样就可以清楚地看到哪些系统有哪些数据集。
例如,谷歌的销售代表应该能够查找他们正在销售的公司的类型,以及客户通常会购买哪些关键词,以减少摩擦并增加销售金额。
4。可导性
当衍生数据产品可以相对容易地创建时,特别是由非技术人员创建时,前一点的价值会成倍增加。轻松创建类似的数据产品允许自助服务,并带来为公司创造价值的最大机会。
当扩展到外部共享数据时,这一点被放大,并产生进一步的共同价值。例如,Google Adwords 的客户能够洞察自己的数据,因此可以更好地选择他们希望出现的其他关键词和网站类型。
数据民主在实践中的好处
既然您已经有了关键的要素,那么数据民主应该是什么样的,它如何在实践中提供商业利益呢?
数据访问民主化后,有三个运营成果可以增强组织的工作方式:
- 启用发现
 - 授权自助服务
 - 增强自主性
 
发现
一如既往,要想在工作中取得成功,你需要了解你的业务。
拥有一个组织有序且可搜索的数据项目目录对于实现发现至关重要。获得对组织数据的访问权限使您能够以以前不知道的方式发现趋势,从而做出更多由数据驱动的决策并提高运营绩效。
例如,像沃尔玛这样的大公司可以利用与他们合作或建立关系的所有供应商的索引。有了这些数据,采购部门的员工就可以很容易地识别不良玩家并控制成本。这种广泛的、可发现的商业智能使公司能够以较低的价格运作,同时保持利润。
自助服务
数据民主发展的下一步是能够以自助服务的方式衍生和扩展现有的数据产品。这意味着任何员工都可以提出新问题。
我们的采购朋友可以根据成本或地理位置来研究定价。或者,他们可以为某个地区的流行产品设置新的查询,并在那里寻找新的供应商。
这同样适用于服务业。例如,随着商店在疫情重新开业,目前紧急商店清洁需求激增。在决定雇佣谁时,采购部门不仅可以寻找更低的价格,还可以考虑哪些服务提供商工作更快或对紧急请求的响应更快。
因此,可推导性对于为员工个人提供更清晰的数据图景以及从不同角度应对运营挑战至关重要。数据民主化带来了更多创新方法的可能性。
自治
一旦团队通过对数据的开放访问更好地理解了他们的业务,他们就可以将这些数据带入他们想要使用的工具和技术中。这使得团队可以决定哪些工具最适合自己,而不需要大规模的公司 IT 官僚机构。
例如,这可能意味着一个团队使用一种不同的采购工具,这种工具在当地更受欢迎,从而为他们所在的地区带来更高的效率。他们可以避免被在特定环境中无效的强制工具所困扰。
当涉及到确保商店干净、安全和照明良好时,像沃尔玛这样的全国性巨头可以让不同的区域采购团队选择与商业建筑管理经纪人合作或雇用内部技术人员。通过访问成本和性能数据,他们可以自己决定哪个方向最适合自己。
要点:通过解锁您的数据来释放价值
数据民主有可能为公司带来可观的价值。使业务用户能够定义自己的信息需求、发现自己问题的答案并创建自己的数据工具,只会增强营销、销售和采购等业务流程。
非技术和非 IT 员工利用他们特定的业务知识和洞察力来定义 BI 和分析需求。
有了正确的成分和适当的工具,数据民主让所有员工都成为“公民数据科学家”,这将有助于构建满足组织不断发展的需求的解决方案。
– –
你是如何使你的数据民主化的?你对好处、挑战和要求有什么想法?我很乐意收到你的来信。
想了解更多关于释放公司潜力的信息,还是只想聊聊数据?请通过 dave@estuary.dev 与我联系。
Tableau 桌面中的数据加密
实践教程
如何在没有 ETL 的情况下通过度量在工具提示中显示详细数据

Tableau 桌面的作者的形象。
如果您没有一个合适的数据模型,并且该数据模型的维度允许数据切片,那么前面的图像可能会很有挑战性。我将解释一个快速的方法来解决这个问题,而不改变原始数据。
数据
很多时候我们遇到了麻烦,因为我们的度量是以列而不是行的形式出现的,并且我们无法在一个单独的列中找到值 A、B、C 和 D:

Tableau 桌面的作者的形象。
假设您有一个少量数据(几百万条记录或更少)。在这种情况下,您可以使用 Tableau 桌面中的数据加密方法来构建之前的图表,而无需修改您的数据源。
如果你的数据量更大,我推荐使用合适的 ETL 或数据流软件,如 Tableau Prep Builder、Alteryx、Informatica、AWS Glue 等。它也适用于 SQL、Python Pandas 或 Spark。您仍然可以使用数据加密方法。
什么是致密化?
致密化是变得或使更致密的行为。
什么是数据上下文?
这意味着从你当前的数据中产生更多的行。在某些情况下,添加列和进行特性工程也可以算作数据加密,但是为了简化,我将只关注行。
为了澄清,根据您的背景,您可以使用不同的名称来引用行、例如,记录或观察结果,以及列、在此上下文中的特征或度量。
我们为什么需要它?
一般来说,要使用预先计算的数据来填充间隙,以将其用作维度,例如,如果您需要将 LATAM 和 CAM 显示为国家列表中的另一个条形,我们可以截取日期之间缺少的天数来进行计算。
我如何在 Tableau 桌面中使用它来在我的工具提示中显示更多数据?
首先,创建一个只包含测量或特征列表的新文件。

densitization . CSV包含一个度量或特征列表——作者对文本图像的升华。
其次,通过将文件名拖到画布中来创建与当前数据的关系:

Tableau 桌面的作者的形象。
通过点击橙色线并创建关系计算来修改关系,两边的数字为 1 。这些将在获取数据时被 Tableau 用作 SQL 交叉连接。

Tableau 桌面的作者的形象。
创建一个名为 Measure Selected 的新计算字段,如下所示。请记住,所有度量都必须共享相同的数据类型和相同的格式。
CASE [Measures]
    WHEN "A" THEN [A]
    WHEN "B" THEN [B]
    WHEN "C" THEN [C]
    WHEN "D" THEN [D]
END
此计算字段将映射度量值:

测量选定的计算字段—作者 Tableau 桌面的图像。
并创建一个名为的新计算字段,突出显示,如下所示:
IF  {FIXED  [Measures]:max([Measure selected])} = [Measure selected] THEN
    0
ELSE
    1
END
我将在工具提示中按日期突出显示条形的最大值,将度量的总量与当前值进行比较。

Tableau 桌面的作者的形象。
然后,您会注意到,当您移动度量维度时,density . CSV 文件中的新列在每个度量名称中生成密集数据。

度量名称与度量-作者的 Tableau 桌面图像。
使用测量选定的字段,您将只看到通过测量尺寸的相关值:

测量选定的计算字段—作者 Tableau 桌面的图像。
因为我们使用的是关系,当您将每个度量单独分组时,您不需要担心重复的值。在旧的 Tableau 版本中,您必须创建一个额外的集合,在其中选择我们的度量列表中的一个元素来过滤数据。

现在你可以用它作为一个尺寸来将值传递给工具提示表。

棒材——增密的板材。Tableau 桌面的作者的形象。

条—增密的工作表工具提示。Tableau 桌面的作者的形象。

工具提示—增密的工作表。Tableau 桌面的作者的形象。
来产生我们想要的视觉效果:

Tableau 桌面的作者的形象。
但是为什么不能使用度量名称呢?

Tableau 桌面的作者的形象。
主要原因是度量名称是一个计算的字段,它创建了所有度量的离散列表,但不存在于数据集中,因此,至少在 Tableau Desktop 2020.3.1 版本之前,不能作为值传递给工具提示所引用的表

条-非增密按 Tableau 桌面中的度量名称。Tableau 桌面的作者的形象。

前面条的提示—非增密张引用的提示—非增密张—作者的 Tableau 桌面图片。

工具提示 Tableau 桌面中按日期和度量名称排列的非增密工作表。Tableau 桌面的作者的形象。
结论
我们学习了数据增密以及如何在 Tableau Desktop 中使用它,当您的模型没有表示每个度量名称的维度时,通过工具提示过滤值。
此外,我们看到,无论您使用的软件有多先进,无论您拥有的专业知识或领域有多丰富,您总会发现一个限制,为了解决这个问题,您需要跳出框框思考,发挥创造力。
谢谢
最后,我要感谢丹尼尔·多伦索罗向和询问这件事。还有罗萨里奥·高纳,她促使我继续写这些话题。
有用的资源
Rosario Gauna & Klaus Schulte 数据加密——当你去过……
rosariogaunag.wordpress.com](https://rosariogaunag.wordpress.com/2019/09/06/manifesto-of-internal-data-densification/) [## 去神秘化的数据加密——数据学校
你有没有想过在 Tableau 中创建了一个表计算,结果没有任何意义?你…
www.thedataschool.co.uk](https://www.thedataschool.co.uk/damiana-spadafora/data-densification-demystified/) [## 数据增密简介
数据加密是 Tableau 中常用的技术。很多人都写过,包括场景…
www.flerlagetwins.com](https://www.flerlagetwins.com/2019/05/intro-to-data-densification.html) [## 使用域完成和域填充的数据致密化
4/22/2020 使用域完成和域填充的数据加密表中较复杂的主题之一…
www.dataplusscience.com](https://www.dataplusscience.com/DataDensification.html)
数据通才的日记:从无到有创造数据
日期:2017 年 9 月

来源: Unsplash
“谁给你的这个信息?”
-员工乔
我的同事乔(Joe)带着一丝恐惧和困惑走到我面前,问道:“谁给你的这些信息?”。Joe 收集的信息很难获得,严重依赖于适当的上下文,并且需要每天更新。他对团队的价值是为这家财富 100 强公司提供当前的公共政策和立法风险。在这种情况下,他担心新系统中的信息可能不准确。
Joe 通过我们最近上线的新联系人关系管理工具获得了这些信息。该系统是该团队信息收集、更新和访问方式的巨大转变。直到 2017 年,这个团队一直以特设的方式运作,利用微软 Office 产品套件,并将信息存储在本地硬盘或纸上。早就需要一个中央储存库;然而,不能低估所需的文化变革。
Joe 的声音中带着严肃的抑扬顿挫,我想提供一个有用的回答,特别是因为我是团队中的最新成员之一。我决心在一个由公共政策专家组成的团队中展示我作为数据分析师的价值,这些专家质疑这个新的量化小组的有效性。没有太多的思考,我的直觉踢了进来,我很快给了乔一个回应。
“你做到了。你给了我这些信息。”
-数据通才
我看得出他脸上仍然充满困惑。对 Joe 来说幸运的是,从第一天起我就一直在做这个实现。因为整个团队没有一致的数据标准,也没有任何现有的数据库,我们必须从头开始创建数据字段来捕获这些信息。我们采访了他,以及其他主题专家,通过一个广泛的问题列表,以便用最新的公共政策风险填充 CRM。因为这个过程花了几个月的时间,所以大部分信息现在很有可能已经过时。一旦乔最终明白了采访是数据的来源,我可以看到他的举止立即发生了变化。他的肩膀下降了几英寸,他终于开始放松。
事后,我开始思考他在这次经历中的观点。对于像乔这样的人来说,将信息从纸质文件和采访记录中转移到电脑中就像变魔术一样。理解这一数字化过程的技术本质不是他的责任。我们的团队有责任以更有效的方式传达高层流程。
- 当数字化一个系统时,你的利益相关者必须理解从数据源到最终用户的数据流。
 - 数据通才
 
数据驱动聊天:“这是真正重要的事情。”
Ganna Pogrebna 与 Briana Brownell 的对话——她的数据科学之旅、有影响力的项目和目前在医疗保健领域的工作

学者、教育家、顾问和博主 Ganna Pogrebna 开始了 数据驱动聊天 来探索行为数据科学的许多有趣方面,包括人类行为、数据科学和人工智能。Ganna Pogrebna 是行为分析和数据科学教授,是艾伦图灵研究所(位于英国伦敦的国家人工智能和数据科学中心)行为数据科学团队的负责人。数据驱动聊天是图灵行为数据科学特别兴趣小组的官方播客。
从数据科学家转型为科技企业家的 Briana Brownell 是 Pure Strategy Inc .的创始人兼首席执行官。Pure Strategy 的自动化神经智能引擎(ANIE)使用自然语言处理、机器学习和神经网络领域的领先技术,为组织提供自信地做出决策所需的洞察力。
对话最初出现在数据驱动聊天上。点击 此处 收听。
这是由三部分组成的系列文章的第一部分。
大家好,这是数据驱动聊天,今天我们请到了 Briana Brownell!Briana 是 Pure Strategy Incorporated 的创始人兼首席执行官。你好布里亚纳!很高兴见到你,也很高兴见到你。
布里亚纳:很高兴见到你,也很高兴见到你!
甘娜:谢谢你这么做。我知道你很忙,现在很难找到时间,但是非常感谢你来参加这个播客,和我们分享你的想法。
布里亚纳:不客气。
甘娜:开始我们的讨论吧,我的理解是你从事决策科学和数据科学的工作,我很高兴能和你交谈,因为这也是我的工作。我做学术方面的工作,很少在商业方面遇到像你这样的人,所以我真的很兴奋。你是如何对这个领域感兴趣的?你能告诉我们一些你个人的经历吗?
布里亚纳:当我上大学的时候,我其实想成为一名理论物理学家。整个高中时期我都对物理很感兴趣。我喜欢斯蒂芬·霍金,我对夸克非常着迷。我真的很喜欢粒子物理学。但是当我进入大学时,我发现真正吸引我的是数学课程,它让我对数学的一些可能性感到兴奋。那时数学非常不受欢迎——当我毕业时,我是唯一一个在我那一年获得数学学位的人。没有人能理解我为什么要主修如此不切实际又如此怪异的东西。
我本科毕业后的第一份工作是金融。2006 年,我在纽约证券交易所找到了一份自营交易员的工作,我非常喜欢这份工作。那时候在金融行业工作是一段非常迷人的经历。当然,你可能知道接下来发生了什么。接下来发生了全球金融危机!因此,大约在 2007 年,一切都开始分崩离析,于是我在那时离开了金融行业。
“这么多年来,人们一直不理解我为什么想研究数学模型和数据,但最终他们开始理解了。我很高兴现在人们对数据科学如此感兴趣。”
但真正打动我的是,我可以看到人类行为是多么重要的一部分,是我一直在创造的一些数学模型的关键部分。我开始对人类行为方面产生兴趣,并开始从事数据分析师的工作。我们当时不称自己为数据科学家,因为那个时候这个术语还没有被创造出来。我与不同的公司合作,应对他们在数据方面的一些挑战——做预测、理解消费者行为以及理解人们为什么做出决策的一些深层方面。
几年后,公司开始对更有效地使用他们的数据非常感兴趣,所以我发现自己在一个再好不过的地方了。数据科学越来越受欢迎,我感到有点被证明了,在这么多年人们不理解我为什么要研究数学模型和数据之后,他们终于开始理解它了。我很高兴现在人们对数据科学如此感兴趣。
是的,现在它是当今最热门的领域。对于那些不了解你工作的人,如果你必须选择你职业生涯中最重要的一件事,你会选择什么?会是什么呢?
布里亚纳:我最自豪的事情之一是我在澳大利亚和澳大利亚政府一起做的工作,以了解初级生产者的决策和技术采用。
2007 年,澳大利亚发生了非常严重的干旱,这绝对是毁灭性的。我们研究了人们为什么采用技术来减轻气候变化带来的风险。这项研究大概持续了八年。我从 2007 年开始,2015 年我们还在出版。
这绝对令人着迷,因为它真的把我用数据做的工作和人们的生活联系起来了。它不再只是电子表格中的一串数字或我运行的算法,而是真正重要的东西。它真的很有影响力,我喜欢和它一起工作。我们有一个很棒的研究团队,我很幸运能和他们一起工作。这真的教会了我很多关于如何利用数据来改善世界的知识。
甘娜:是的,我能看到很多和我相似的地方。我也是一名实验室科学家,后来我终于在一个工程部门找到了一份工作,只是因为我想看看我的模型在现实世界中实际工作,所以我认为这非常重要。
布里亚娜:太令人满意了,不是吗?
甘娜:是,是。那么你能告诉我们更多关于你目前在做什么吗?是什么让你夜不能寐?什么让你兴奋?
布里亚纳:我提到过我在澳大利亚做的工作。其中一个重要的组成部分是创建类型学来理解不同的人如何以相似的方式做决定。我们发现不同群体的人有相同的世界观,有相同的态度和信仰,通过理解这些态度和信仰,我们可以预测行为。我们可以干预和鼓励我们想要鼓励的行为。
例如,减轻气候变化导致的风险是我们想要鼓励的事情,因为我们希望人们的生计得到保护。现在,我们正在使用这种方法来理解医疗保健行业中医生和患者的决策。
“我们发现不同群体的人有相同的世界观、态度和信仰,通过理解这些态度和信仰,我们可以预测行为。我们可以干预和鼓励我们想要鼓励的行为。
例如,减轻气候变化导致的风险是我们想要鼓励的事情,因为我们希望人们的生计得到保护。现在,我们正在使用这种方法来理解医疗保健行业中医生和患者的决策。"
我发现这真的很有趣,因为你尊重人们的差异和不同的世界观,而不是像一些做同样事情的铁板一块的团体那样对待病人或医生。
我们已经在医疗保健的多个领域进行了这项研究,以了解诸如为什么患者决定不寻求他们正在经历的症状的护理?有时他们感到尴尬,有时他们对自己经历的一些症状感到无可奈何。我们希望鼓励人们尽可能过上最健康的生活,因此理解他们为什么不选择寻求护理是极其重要的。
再往下看,我们也看到一些个体,当他们有一个针对某种疾病的治疗计划时,他们可能不会继续按计划进行治疗。他们没有在正确的时间服用药物,或者他们没有安排随访预约或与他们需要看的其他医疗保健专业人员的预约。
通过了解患者群体的行为以及围绕决策的核心态度和情绪,我们可以规划干预措施。我们发现,世界各地的医疗保健面临着多么大的挑战,新冠肺炎和所有不同的因素都影响着人们做出如何保持最佳健康状态的决策。我认为能够理解这些行为和动机非常非常重要。
这是三部分系列的第一部分。点击 此处 听完整段对话。
第 2 部分:数据驱动的聊天:“大多数组织都没有意识到数据的潜力”
Ganna Pogrebna 与 Briana Brownell 的对话——数据科学中被低估的技能、获得高管的认同以及我们如何塑造未来
第 3 部分:数据驱动的聊天:“我们没有很好地为真正重要的行业建立弹性。”
Ganna Pogrebna 与 Briana Brownell 的对话——新冠肺炎向我们展示了数据科学,新冠肺炎之后的生活将会如何不同,弹性系统,并推荐阅读和观看人工智能。
数据驱动的聊天:“大多数组织都没有意识到数据的潜力”
Ganna Pogrebna 与 Briana Brownell 的对话——数据科学中被低估的技能、获得高管的认同以及我们如何塑造未来

学者、教育家、顾问和博主 Ganna Pogrebna 开始了 数据驱动聊天 来探索行为数据科学的许多有趣方面,包括人类行为、数据科学和人工智能。Ganna Pogrebna 是行为分析和数据科学教授,是艾伦图灵研究所(位于英国伦敦的国家人工智能和数据科学中心)行为数据科学团队的负责人。数据驱动聊天是图灵行为数据科学特别兴趣小组的官方播客。
从数据科学家转型为科技企业家的 Briana Brownell 是 Pure Strategy Inc .的创始人兼首席执行官。Pure Strategy 的自动化神经智能引擎(ANIE)使用自然语言处理、机器学习和神经网络领域的领先技术,为组织提供自信地做出决策所需的洞察力。
对话最初出现在数据驱动聊天上。点击 此处 收听。
这是由三部分组成的系列文章的第二部分。可以在这里阅读Part 1和Part 3。
Ganna:我们稍后会回到新冠肺炎的话题,但首先,我想问你——许多收听本播客的人都是有抱负的数据科学家,并试图在数据科学中找到一席之地。你能给那些想进入决策科学和数据科学之间的这种联系的人一些提示吗?他们从哪里开始?他们需要做什么?
Briana:我认为,在数据科学中,被低估的技能是沟通和商业头脑。拥有运行模型的技术技能,并能够进行 Python 编程和理解数据库等技术工作确实很重要,但事实是,当你在行业中工作时,这一切都是关于分析如何影响企业关心的指标。因此,如果你不能将你正在做的事情与企业的目标或真正重要的结果联系起来,那么就很难获得资源,如果你正在做的事情在企业中不是高度优先的,那么就很难有效。
“我认为,数据科学中未被充分重视的技能是沟通和商业敏锐度。”
这是我看到数据科学家真正挣扎的地方。在一个组织中,当你用与任何结果都没有联系的数据建模时,这些团队经常被推到一边,或者在组织中被最小化。这很可悲,因为数据科学可以如此有影响力。
技能非常重要,但能够向企业传达技能的价值更为重要。
甘娜:当然,你提到问题陈述也很重要,对吗?你如何支持回答商业上的重要问题?这是作为一名有抱负的数据科学家,每个人都需要能够做到的另一件事。我们如何在业务环境中处理数据?为什么你认为理解数据对现在的企业特别重要?你觉得数据的潜力还没有发挥出来吗?
布里亚纳:很好的问题。我确实认为大多数组织都没有意识到数据的潜力,这有几个原因。第一个是组织内孤立的数据。我曾与一些组织合作过,他们有多个团队在收集基本相同的信息,但由于组织内部的政治原因,他们不愿意在各部门之间来回共享这些数据。我认为这非常危险,因为这是一个组织运转不良的标志。如果没有办法在组织中的不同小组之间共享数据,这总是一个挑战。
第二,个人往往不知道数据有什么用,尤其是当你到了高管层。所有这些技术都是如此的新,以至于很难确切地知道在组织内做一个更大规模的分析项目会有什么样的回报。有时项目本质上是失败的,有时你可以获得额外的洞察力,但你不一定知道,直到你尝试。当高管希望看到他们的数据程序的特定投资回报率时,这有时是一个真正的障碍。
甘娜:在过去的几年里,数据是如何改变商业格局的,或者说它改变了吗?你注意到变化了吗?
Briana:我认为数据在组织中的使用方式的最大变化是,比如说 10 年前,很少有数据项目能够一直上升到高管层或董事会级别。高管们永远不会真正看到数据分析项目的任何结果。他们可能属于营销团队,可能属于 IT 团队,也可能属于销售团队。他们被关在那些小仓库里,永远也不会升到组织的管理层。
但是在人们开始看到它的价值之后,我们开始看到组织的最高层的认同。不仅高管们要求更好的数据、更好的分析、更好的建模,董事会也在要求。你看到一个董事会命令说“我们每个季度都需要某种数据驱动的指标。我们需要看到这个指标。”
“所有这些信息都传到了组织的最高层,我认为这是一件非常新鲜的事情。”
所有这些信息都传到了组织的最高层,我认为这是一件非常新鲜的事情。以前,许多财务指标总是报告给董事会和高管,但现在营销指标、运营研究指标,所有这些领域都出现在董事会会议上,我认为这是一个非常积极的迹象。
甘娜:但同时,我也想挑战你所说的。同时,我觉得董事会对数据科学缺乏了解,认为它不是一根可以解决问题的魔杖。
如果你没有高质量的数据,你就无能为力。也许这些见解并不那么有价值。感觉往往缺乏对方法论的理解。人们会看到无关紧要的结果,或者看到太少的数据点而无法做出决定。
有像你这样的人来解释这可能不是一个好主意,这很重要,你需要看看这里,利用数据获得适当的决策情报和决策洞察力。所以你有没有觉得一方面有数据很棒,但是对于数据能做什么的炒作太多了?
布里亚纳:你完全正确。我认为这很有趣,因为很多时候,我看到董事会或执行团队中有一两个人真正理解数据。如果你让那个人成为分析项目的冠军,你所做的真的很有帮助。
“组织对培训人们成为公民数据科学家很感兴趣。您可以在组织中担任任何角色,并通过更好地理解数据及其与您的角色的关系来增强您的技能。”
绝对有人们误解数据的情况。例如,数据不干净,或者其中有某种偏见,这总是一个挑战,因为你可以根据数据做出不一定像你认为的那么强的决策。
我看到的变化是,组织对将人们培养成公民数据科学家很感兴趣。您可以在组织中担任任何角色,并通过更好地理解数据及其与您的角色的关系来增强您的技能。我看到越来越多的大型组织提供培训,让顾问领导工作小组,研究如何在组织内使用数据和如何理解数据。所以我希望你提到的挑战——绝对真实的挑战——开始变得越来越好。我希望在 10 年内,我们能够摆脱这种困境。
甘娜:是啊,我也希望如此。就像你提到的,当你有一个人可以为董事会翻译复杂的数据见解时,这很酷。我们最近和一个大公司客户合作,我们有一个物理学博士,这个人太棒了!我的意思是,他可以把任何复杂的分析变成条形图,地图和图表等等。他把这些都变成了非常非常简单的条形图。太棒了!我在想,哇!你可以用一种简单的方式做到这一切。
我想问你几个关于 stem 女性的问题。因为你自己是首席执行官,而且你处在一个非常高科技、男性主导的环境中,在你看来,我们是否缺少女性首席执行官?如果是的话,为什么我们会有这个问题?你认为这背后的原因是什么?
布里亚纳:我真的希望有更多的女性首席执行官领导深度技术和高科技公司,因为首先,我认为这是一个迷人的领域。我认为这非常重要,它让人们成为未来的塑造者,而不仅仅是被随之而来的技术所影响。
至于为什么我认为做这些事情的女性越来越少——最重要的事情之一是知名度,让女性和年轻女孩看到这是她们可行的职业道路。我知道有很多女性碰巧成为了律师或兽医或其他类似的职业,她们没有进入科技行业的唯一原因不是她们不擅长这个行业或其他什么,而是因为她们不知道自己可以。他们只是不认识任何工程师或计算机科学家或在该领域工作的人,他们没有意识到这是他们的一个选择。
通过看到正在做有趣事情的人并接触到这些事情是非常重要的,并且能够看到在这些角色中与他们相似的人。
“我认识的很多女性都碰巧成为了律师或兽医或其他类似的职业,她们没有进入科技行业的唯一原因是她们没有意识到这是她们的一个选择。”
我永远不会忘记格温·肖特维尔,她是一个如此了不起的人和工程师,还有 SpaceX 公司的首席运营官。她说她成为一名工程师的原因之一是一名女工程师来她的学校演讲,她穿着一套非常棒的衣服。起初,这听起来真的很傻,就像,“哦哇!为什么她的穿着如此重要?”但它揭示的是,这个女孩想在那个角色,那个职业中看到自己。不是西装,而是“这能让我在这个角色中看到自己吗?我能把自己看成一名工程师吗?如果我是工程师会是什么样子?还是数据科学家或技术专家?”我认为这非常重要。
甘娜:我喜欢你谈论榜样的方式。你谈论这些榜样是因为你不一定需要一个特定的人;你可以有一个穿着很酷的西装的人,这有点激励人心。“实际上我想要这样,”对吗?我想去太空,我想和这群人一起工作,就像这个女人一样,对吗?这个例子很酷。
我想把这种多样性和包容性缩小一点,谈论更多的现代女性,因为即使我们只看女性,如果我们看财富 500 强——我们最近刚刚和我的一个学生和我的一些同事一起做了这项研究——我们实际上发现如果我们看财富 500 强中女性的代表性并不好,对吗?但是如果我们看看,比如说,少数民族的情况就非常糟糕。例如,如果我们寻找有色人种女性,只有三位女性领导财富 500 强公司,而且没有一位是黑人。所以看起来这个系统在某个地方被破坏了。我们能做些什么来提高科技行业的包容性?
布里亚纳:我认为这是关于创造一个让人们有归属感的环境。我曾提到,人们需要能够在这些角色中看到自己,所以能够看到像你这样的人担任高级角色,并意识到这是你可能的职业道路,我认为这真的很重要。当你看不到任何像你一样的人时,很容易觉得你不属于这里,对吗?
每个人,每个人都有归属感,都需要成为一个团体的一部分,这个团体周围有一种团体感。因此,能够创建这些群体是非常重要的。我看到越来越多的在线支持团体,人们可以聚集在一起分享他们的经历,分享他们的故事,分享建议。我认为这是一个非常积极的迹象,能够创建这样的团体,在那里你感觉你可以做你自己,你属于那里,人们不会因为你有兴趣而评判你或认为你很奇怪。这是一个更大、更具挑战性的图景中非常重要的一部分。
Ganna:我的许多学生都是管理专业的学生,他们总是担心他们需要的技能。你提到你来自技术背景,你是 CEO,但是就你在当前条件下需要领导的技术技能而言,你认为知道如何编码很重要吗?理解算法如何工作很重要吗?作为当今的领导者,你需要什么水平的技术能力?不仅仅是作为一个女性领导,总的来说,今天有哪些领导技能是重要的?
布里亚纳:如果你在领导一家科技公司,如果在公司的高层,你有一个技术高超的人,那么找到优秀的人才会容易得多。原因是,许多技术人员在他们刚开始职业生涯时,几乎所有人都有过为非技术领导工作的经历,这些领导并不真正了解我们在做什么,将信息技术边缘化,抱有不切实际的期望,基本上很难为他们工作。因此,当你是一名技术人员时,你希望为了解其中一些问题的人工作,希望有人支持你为公司的重要部分做出贡献,而不是忽视发展和使公司成功所需的技术能力。
“如果你在领导一家科技公司,如果在公司的高层,你有一个技术高超的人,那么找到优秀人才就容易得多。”
例如,对于 CEO 来说,成为一名程序员或知道如何编码并不重要,但你要么需要对软件架构如何工作有足够好的理解,这样你就可以尊重你的技术团队的意见和知识水平,要么你需要与拥有这些知识的人合作,他可以以尊重他们的技能集的方式为技术团队辩护。
我发现女性领导者经常面临的一个挑战是,她们将成为非技术型首席执行官或非技术型创始人,她们总是在寻找技术型联合创始人,对吗?只要领导技术方面的联合创始人从最初的创始人那里获得足够的尊重,能够创造出对业务有益的东西,这种关系就绝对能够发挥作用。而不是仅仅说‘哦,我有这个想法!你能帮我编码吗?因为那根本没用。仅仅为了编码而让某人参与是行不通的。需要尊重技术技能和公司的技术需求。
是的,说到这个和糟糕的老板,我想起来我曾经为一个人工作过,他让我回归变量本身来得到完美的相关性!我当时想,‘你确定吗?!'我的意思是,缺乏理解是一个大问题。
我完全明白你的意思,如果你也有名气,吸引人才会容易得多。
回到你关于榜样的观点,如果人们知道你在科技行业有声望,你肯定能吸引人,这很好。
布里亚纳:是的,当然。
这是三部分系列的第二部分。点击 此处 听完整段对话。
第 1 部分:数据驱动的聊天:“这是真正重要的事情。”
Ganna Pogrebna 与 Briana Brownell 的对话——她的数据科学之旅、有影响力的项目和目前在医疗保健领域的工作。
第 3 部分:数据驱动的聊天:“我们没有很好地为真正重要的行业建立弹性。”
Ganna Pogrebna 与 Briana Brownell 的对话——新冠肺炎向我们展示了数据科学,新冠肺炎之后的生活将会如何不同,弹性系统,并推荐阅读和观看人工智能。
数据驱动聊天:“我们在真正重要的行业中没有很好地建立弹性。”
Ganna Pogrebna 与 Briana Brownell 的对话——新冠肺炎向我们展示了数据科学,新冠肺炎之后的生活将会如何不同,弹性系统,并推荐阅读和观看人工智能。

学者、教育家、顾问和博主 Ganna Pogrebna 开始了 数据驱动聊天 来探索行为数据科学的许多有趣方面,包括人类行为、数据科学和人工智能。Ganna Pogrebna 是行为分析和数据科学教授,是艾伦图灵研究所(位于英国伦敦的国家人工智能和数据科学中心)行为数据科学团队的负责人。数据驱动聊天是图灵行为数据科学特别兴趣小组的官方播客。
从数据科学家转型为科技企业家的 Briana Brownell 是 Pure Strategy Inc .的创始人兼首席执行官。Pure Strategy 的自动化神经智能引擎(ANIE)使用自然语言处理、机器学习和神经网络领域的领先技术,为组织提供自信地做出决策所需的洞察力。
对话最初出现在数据驱动聊天上。点击这里收听。
这是由三部分组成的系列文章的第三部分。你可以在这里阅读 第一部分 和 第二部分 。
Ganna:我们无法回避冠状病毒的话题,你也提到了你在医疗行业为医疗人员所做的令人惊叹的工作,所以我想再问你一点关于数据科学在解决当前危机中的作用。
有很多猜测,比如有些人说,“哦,数据科学家应该只在有领域专家与他们一起工作时才参与进来!”其他人说,“你知道我们都应该在 COVID 上做工作,看看会发生什么!”那么你在光谱的哪一边?对此你怎么看?
布里亚纳:我认为这真的很有趣,因为在对抗冠状病毒方面,数据科学和人工智能的许多真正成功的应用都是人类增强系统或以人为中心的系统,它们得到了良好的数据科学和良好的人工智能的帮助。
这方面的一个例子就是一些分类应用。因此,例如,能够分析胸部 x 光,并预测该人是否有并发症或严重后果的风险。
不是让医生或放射科医生等其他医疗保健专业人员查看所有图像并以较慢的方式进行,而是有一个系统可以自动显示最有可能出现并发症的病例,以便人类可以首先分析这些图像。您增强了在医院工作的内科医生、放射科医生和医疗保健专业人员的工作,使他们的工作变得更加轻松,让他们能够提供尽可能好的护理,让他们能够提供尽可能好的结果。我认为非常有趣和重要。
“您授权医疗保健专业人员尽他们所能提供最好的护理。”
就冠状病毒而言,新兴模式也非常有趣。早在 1 月或 12 月,当人工智能系统最初看到出现“嘿,这可能是什么”的信号时,所有浮出水面的早期预警系统都去找了一组人类专家,他们随后深入研究,看看真正的风险是什么。有趣的是,研究这个问题的人都是传染病方面的专家和专业人士,他们认识到这是一个巨大影响的真正潜力。
我喜欢数据科学和人工智能系统被用作人类增强系统的想法。不是‘AI 要去拯救世界了!’哦,我们有这个技术系统,我们将取代你。相反,它是“我们如何利用人工智能和数据科学让人类变得更好,让我们更有效,让我们有更好的健康结果。”我认为新冠肺炎已经真正证明了人工智能和分析不会取代人。它将增强它们。
甘娜:你认为当今决策科学和数据科学的交叉领域面临哪些挑战?我们在 covid 上看到了什么新的挑战或其他问题吗?这些问题在当前情况下突然凸显出来了吗?
Briana:我们发现的最大问题是我们所有系统的脆弱性。如果你看看由于新冠肺炎而发生的所有巨大的行业系统故障,它们都是因为系统的脆弱性。有些医院没有增援能力或设备,因为医院尽可能高效地运转,所以为什么要有额外的设备呢?额外的不会让你赚钱。它让你赔钱,对吗?
“如果你看看由于新冠肺炎而发生的所有巨大的行业系统故障,它们都是因为系统的脆弱性。”
供应链系统——当所有的餐馆都关门了,人们开始以完全不同的方式购物时,酵母之类的东西就会严重短缺。就像,我不认为我还能在杂货店买到酵母,因为消费者的行为正在改变。买家正在改变。突然间,餐馆不再购买任何食物。人们的饮食习惯完全改变了。
我认为这确实暴露了我们的一些优化对于微小的改变是多么的脆弱。我记得读到过有一个农民在为餐馆和大规模生产生产洋葱。他不能直接卖给消费者,因为他们被放在这些巨大的袋子里,他们没有一个合适的系统能够把它放在一个家庭可以使用的袋子里。
这确实暴露了我们在优化供应链方面做得多么出色,让一切尽可能高效和完美,但一个小小的动作,突然之间这些系统就完全崩溃了。
新冠肺炎真正教给我们的是,我们如何建立我们的系统,我们没有很好地在许多真正重要的事情上建立弹性,我们需要的真正重要的行业。当然,就像食品供应链一样,医疗保健是另一回事。教育系统,突然之间,老师和家长都在努力教他们的孩子,而每个人都试图在家工作,所有这些 IT 系统都需要设置为允许员工在家工作。
我们创建的所有这些系统对于任何类型的变化都非常脆弱,因此我希望在未来,弹性将被视为内置于这些系统中的一件好事。
甘娜:那么这个未来怎么样?除了在供应链中建立弹性之外,您认为数据科学还有其他重要的热门话题吗?以及决策科学和数据科学与未来的交集?
布里亚纳:我认为消费者行为的变化,我们生活方式的变化,这是一个永久性的变化。我们不应该回头看“我们什么时候才能恢复正常”,因为这将是一个新的常态。这将是下一个常态。这将与我们在 covid 之前生活的世界大不相同。
像在家工作这样的事情将会变得非常普遍。已经有一些大公司表示,他们将实行永久性在家办公政策。这将对农村地区或主要中心以外的地方产生巨大影响,因为突然之间,如果你可以在任何有良好宽带连接的地方工作,那么即使那里没有实体办公室,你也可以通过就业刺激经济。
“我鼓励每个人,如果你有关于你的组织的数据,covid 之前,你真的要检查你的假设仍然有效。你根据这些数据做出的任何决定都需要认真考虑它是否仍然适用。”
旅行,尤其是航空旅行,将会有根本的不同。我认为我们将不再拥有大型机场。大型机场基本上将成为过去。我们将会有多个小型机场,因为,想象一下,如果一个小型机场被完全消毒,你会感到多么安全,而在一个大型机场里,你不会面临数十万乘客的危险。因此,新冠肺炎的结果会一直持续下去,在接下来的几年里,我们会经历一段艰难的时期,在这段时间里,我们会适应下一个常态。
数据和分析将是其中重要的一部分,因为我们将能够看到真正的变化,以及哪些变化将成为永久性的。我鼓励每个人,如果你有关于你的组织的数据,covid 之前,你真的要检查你的假设仍然有效。你根据这些数据做出的任何决定都需要认真考虑它是否仍然适用。
甘娜:我很喜欢你关于数据如何在整个供应链系统中传播的观点。我认为,许多人没有意识到,对当前需求的分析实际上会对供应决策产生多大影响,以及这种波动有多大。正常情况下很好,但如果发生这样的事情,那么你的业务可能会完全崩溃,因为你没有准备好理解需求的冲击。就像我说的,你不是很有弹性。
采访快结束了,我还有最后一个问题。很传统的问题:如果让你推荐一本书和一部电影,你会选什么?你有什么建议?
布里亚纳:在我看来,关于人工智能的最好的书是帕梅拉·麦科达克的《会思考的机器》。这本书是几十年前写的,我想是 40 年前左右,那时人工智能开始引起越来越多的兴趣。这绝对是关于这个主题的最引人入胜的书籍之一,因为她将一些人文学科和一些其他领域如艺术、文学与人工智能的主题结合起来,并以比任何其他技术人工智能书籍更全面的方式看待它。所以这是一个百分之百的你应该检查。她还有一本刚出版的传记,我非常喜欢。我很快地浏览了一遍——从头到尾读完了——尽管它真的很长,因为她有着令人惊叹的一生。所以我要说,这绝对是我的清单上的第一位。
我能选择一个电视节目来代替电影吗?
甘娜:是的,这是一个受欢迎的选择。很多人做节目。
布里亚娜:所以我会选太空堡垒卡拉狄加。我喜欢 BSG,这个新的重启,我喜欢它的原因是因为它提出了许多伦理问题,关于我们将如何在未来处理有知觉的人工智能:风险是什么。我们需要建立什么样的系统。这绝对是一场精彩的演出。
甘娜:非常感谢布里亚纳抽出时间。我知道你很忙,但还是谢谢你。祝你一切顺利,继续你正在做的令人惊叹的工作。毫无疑问,我们会密切关注你们的动向,纯策略包括你们的动向!
布里亚纳:不客气,谢谢你。
这是由三部分组成的系列文章的第三部分。点击 此处 听完整段对话。
第 1 部分:数据驱动的聊天:“这是真正重要的事情。”
Ganna Pogrebna 与 Briana Brownell 的对话——她的数据科学之旅、有影响力的项目和目前在医疗保健领域的工作
第 2 部分:数据驱动的聊天:“大多数组织都没有意识到数据的潜力”
Ganna Pogrebna 与 Briana Brownell 的对话——数据科学中被低估的技能、获得高管的认同以及我们如何塑造未来
数据驱动的 T-SQL 业务规则
创建具有动态和可互换业务规则的数据验证器,或者为什么(T-) SQL 比我们愿意承认的更强大

硬编码。我敢肯定,在这一点上,你已经听说了使用它将如何把你带到编码器的地狱。专家似乎建议尽可能避免它。那么,为什么我们的大多数查询都是硬编码的呢?如果我们能够以一种集中的、可互换的方式指定查询的谓词,会怎么样?让我们看看(T-)SQL 到底有多动态。
然而,请注意,这可能不是一个好主意,但无论如何让我们玩得开心点。
什么?
为了说明数据驱动约束引入的可能性,我们将创建一个数据验证器,它强制执行一组约束(不要与 SQL 自身的约束混淆)、业务规则或简单的阈值,这些都是在表上定义的。此外,同样的模型可以扩展到定义您的 where 谓词,或者您的查询的任何部分。如果任何人发现这个帖子相关——怀疑——我会用这个扩展名创建另一个帖子。
我们的最终目标是获得一个存储过程,它允许用户根据一组给定的动态规则来验证给定的条目。例如,验证值 50 是否符合规则集 ID 2,并检索相关的输出代码:
exec ValidateThreshold 2, ‘50’, @returned_code OUTPUT;
为什么?
首先,你到底为什么要这么做?谁会将业务规则硬编码到数据库的查询中呢?事实证明我们大多数人。从数据模型的接近到职责的分离,有很多理由说明为什么需要这样做。
考虑一个拍卖网站的例子。如今,你有一条规则,规定你只接受不低于 0.05 的出价。如果明天你想把所说的价值改成产品估价的 0.01%到 10%之间的任何值呢?是否要更改包含新约束的每个过程、视图、触发器或查询?好吧,希望在这篇文章之后,你不用再这样做了。
实际上,我们引入了一个简单的模型,在实践中,拥有一个规则集表是有意义的,它创建了要应用的规则组。
需要做一个介绍性的说明,我绝不是 SQL 专家——我相信你已经注意到了——相反,我只是一个极其懒惰的人,喜欢想方设法避免手工劳动。希望它也能帮助你的懒惰性格。请务必阅读结尾部分,它可能是整篇文章中最重要的部分。
怎么会?
第一步是实际构建您的规则或阈值。
Create table Threshold
(
 ThresholdID int identity not null,
 ThresholdSetID int not null,
 VarName varchar(20) not null,
 Operator varchar(2) not null,
 TargetValue varchar(50) not null,
 [Description] varchar(100) not null,
 ThresholdOrder int not null,
 Deprecated bit not null default 0,primary key (ThresholdID)
);
并用一组虚拟内容填充它:
insert into Threshold values (1, '@input', '>=', '25', 'dbo.InsertAuctionBid(...)', 1, 0);insert into Threshold values (1, '@input', '<', '(select max(value) from dbo.AuctionDates)', 'dbo.InsertAuctionBid(...)', 2, 0);
注意 rows@如何输入参数,该参数表示要验证的值。第一个规则将确保我们的参数大于或等于 25 的,而第二个规则确保传递的参数小于 AuctionDates 表中的最大日期的。
进入验证程序!
create procedure dbo.ValidateThreshold
(
 @thresholdID int,
 @input nvarchar(50),
 @return_code int OUTPUT
)
as
 if @thresholdID is null 
 begin
  set @return_code = 2;
  return;
 endif @input is null  
 begin
  set @return_code = 2;
  return;
 enddeclare @statement nvarchar(max), @where_clause nvarchar(max);set @where_clause = stuff((
  select '  and '+ VarName +' '+ Operator  +' ' + TargetValue +char(10)
  from 
   Threshold
  where
   ThresholdID in (@thresholdID)
  order by 
   thresholdOrder
  for xml path (''), type).value('.','nvarchar(max)')
  ,1,6,'');set @statement = 'if exists(select 1 '+char(10)+'where '+ @where_clause + char(10) + ') select 0; else select 1;';set @statement = replace(@statement, '@input', @input)exec sp_executesql
  @query = @statement
  ,@params = N'@return_code INT OUTPUT'
  ,@return_code = @return_code OUTPUT;
对于我们这些 SQL 新手来说,有很多东西需要理解,所以让我们把它分成几个部分。
我们的过程应该有三个参数:2 个输入和 1 个输出。要应用的规则;要验证的参数,格式为文本。最后是操作的输出代码,0 表示成功,任何不同都表示特定的错误代码。
create procedure dbo.ValidateThreshold
(
  @thresholdGroup int,
  @input nvarchar(50),
  @return_code int OUTPUT
)
接下来,验证我们的输入并返回一个适当的错误代码
as
 if @thresholdID is null 
 begin
  set @return_code = 2;
  return;
 endif @input is null  
 begin
  set @return_code = 2;
  return;
 end
到目前为止一切顺利。果汁来了
declare @statement nvarchar(max), @where_clause nvarchar(max);-- Generate the underlying where clause by concatenatinc the Variable to test, the boolean operator and the test predicate
 -- using XML PATH to repeat the whole process, gluing subsequent predicates with an ' and'.
 -- Lastly, use stuff to collapse it all together, removing the first 6 characters (corresponding to ' and') starting on the first position.
 -- Note: If more than a @thresholdID is provided, the predicates will be passed according to Threshold.ThresholdOrder set @where_clause = stuff((
  select '  and '+ VarName +' '+ Operator  +' ' + TargetValue +char(10)
  from 
   Threshold
  where
   ThresholdID in (@thresholdID)
  order by 
   thresholdOrder
  for xml path (''), type).value('.','nvarchar(max)')
  ,1,6,'');set @statement = 'if exists(select 1 '+char(10)+'where '+@where_clause + char(10) + ') select 0; else select 1;';-- Feed the input variable
 set @statement = replace(@statement, '@input', @input)exec sp_executesql
  @query = @statement
  ,@params = N'@input nvarchar(50), @return_code INT OUTPUT'
  ,@input = @value
  ,@return_code = @return_code OUTPUT;
那么这是如何工作的呢?
FOR XML PATH 顾名思义,允许您将查询结果转换成 XML 文件。但是,通过将一个空字符串传递给 RAW 参数,我们为返回的数据创建了一个串联的字符串。考虑以下用户表:
╔═══════════╗
║   Name    ║
╠═══════════╣
║ John      ║
║ Mary      ║
║ William   ║
║ Anthony   ║
╚═══════════╩
应用于前一个表:
select ','+ name 
        from Users
        FOR XML PATH('')Output: ‘,John, Mary, William, Anthony’
注意尾部的逗号,它虽然允许我们创建逗号分隔的字符串,但会完全破坏 SQL 语句。在我们的例子中,我们输入了一个和关键字,而不是逗号,这样我们就可以将多个子句粘在一起。
我们首先调用 value() 函数将 XML 对象转换成字符串。然后,我们使用 STUFF() 函数检索逗号,或者在我们的例子中,检索 6 个字符,以从生成的字符串中删除‘and’部分。
下一步是将生成的 where 子句传递给一个布尔语句,使用 Exists 来测试返回的存在。如果返回为 1,则@输入有效,但是如果返回为空,则@输入验证失败。
通过用传递的 @input 替换@input 字段并通过 动态 SQL 执行查询,该过程结束。
但是请注意,动态 SQL 有很多缺点,从性能到安全性。我绝不是建议您的 DBA 应该实现这个模型,它仅仅是(T-)SQL 灵活性的一个展示,人们并不期望它存在。
我希望这个资源对你有所帮助,或者至少是有趣的。
数据驱动、数据知情和数据启发—旧思想、新词汇
不要被流行语迷惑。知道它们代表什么吗
我们需要这些流行语吗?它们增加了什么价值吗?有没有不好的一面?
在这篇文章中,首先,我们将进入这些流行语代表什么。
第二,文章认为,这三个流行语都是在用新衣服营销旧概念,理由很充分。它只是要求我们不要成为数据原教旨主义者,不要放弃常识。事实上,当我们应用清晰的思维时,数据通知的业务决策和数据驱动的业务决策结果是相同的;当我们不运用清晰的思维时,两种情况的结果都是一样的,我们就做出了错误的决定。
最后,我们将探索流行语是如何伤害和帮助的。
当我们谈论数据驱动、数据通知和数据启发时,我们谈论的是什么
如果你想验证,就要数据驱动。如果你想创新,就要了解数据。如果你想为一个想法寻找灵感,那就从数据中寻找灵感。这就是你将看到的解释。
下面是一张表格,显示了业内流行词汇的更多细节。

随着我们从数据驱动的方法转向数据启发的方法,我们开始更加关注数据解释和故事构建技巧。我们不再拘泥于数字。在第一种情况下,我们试图理解所有指标背后的原因,在第二种情况下,我们试图用所有这些数字创造故事。
挑战在于,如果你愿意插入叙述来连接这些点,你总是会找到数据来支持你的观点。我们有这样一种说法是有原因的,数据就像是被警察关押的囚犯。折磨它,它会告诉你你想听的事情。
总而言之,这些流行词只是要求我们不要从表面上看数据,不要只依赖容易获得和测量的数据,不要抛弃常识。
现在,要理解为什么这三个流行语都在用新衣服推销旧概念,以及它们如何以及为什么会同时带来伤害和帮助,我们需要了解它们的历史。
流行语的诞生
请看看这些流行语的谷歌搜索趋势。在 2010 年,我们得到了一个时髦词数据通知,在此之前,技术世界主要是数据驱动的。数据启发从 2018 年开始出现。

数据驱动已经流行了很长时间;数据驱动之前的时代我们称之为石器时代。
石器时代:
一开始,我们没有数据术语,我们有远见者:商业远见者、产品远见者和营销忍者。他们拥有坚如磐石的直觉,对用户的需求和行为有着无可挑剔的理解,他们在组织中做着大部分的决策。商业决策与其说是一门科学,不如说是一门艺术。这并不一致。
幸运的团队有真正的远见者(10 倍),不幸的团队有假的远见者(次 X)。真实的公司在业务活动的各个环节上做得很好,做出了可靠的决策;假的挣扎过,但没人知道。
硅时代:
数据的数字化导致了数据的泛滥,这为提高两个群体的绩效提供了机会——10 倍群体和 X 倍群体。我们需要一个口号来激发人们的热情。行业发明了这个词——数据驱动,将人们聚集到一个新的方法上。毫无疑问,这种方法很有帮助。
数据驱动的决策帮助了整个行业。然而,它对人的帮助是亚 X 人的 10 倍。

在前数据驱动和数据驱动的世界中,对“真天才”和“假天才”的决策准确性
为什么?
这是因为新的数据为那些已经擅长联系事实的人提供了更多的杠杆。10 倍拥有卓越数据解释技能的人在决策方面做得非常出色,但 X 人的收益一般。这是因为他们从字面上理解了“数据驱动”的标签,并将数据误认为是违背常识和深度思考的保险单。
数据站在他们一边,过分热衷于数据的家伙大喊“数据”,而不考虑上下文。它不仅会导致错误和次优的决策,而且会减缓决策过程,进而减缓业务创新。
此外,教条的数据驱动的家伙游说短期利益的战略。他们不愿意相信任何他们第一次看不到和测量不到的东西。他们的热情让公司陷入了本地最大值的困境。
随着滥用数据驱动的流行词的增加,需要一种新的心理模型。一个新的流行词。
一个新的流行词诞生了——数据信息?
一个新术语诞生了。现在,你对过分热衷于数据驱动的同事做出了回应。“伙计们,你们的数据驱动方法很好,但我们需要了解数据。”请注意,这两个流行语都有数据这个词。数据驱动的原教旨主义者更难反对任何始于数据的东西。
数据启发的诞生
不幸的是,所有流行语的诞生并不鼓舞人心。有些流行语是出于需要,有些是为了听起来更聪明。数据启发,在我看来,就属于这一类。
它要求你在数据非常少的时候使用框架。你依靠你的直觉、创造力和过去的经验来发现数据中的趋势。
旧思想,新语言——揭穿流行语
不幸的是,数据解释很难,因为它需要理解用户的需求和大量的思考。为了阻止社区对深度思考的忽视,新的流行语被创造出来作为提醒的线索:不要停止思考。
理解这一点至关重要,否则,我们会被新流行语的光泽所迷惑,最终犯下同样的错误。
让我们来看看知识层次——一个古老的概念,以便更好地理解它。它向我们展示了数据转化为决策的过程?在我们获得智慧之前还有几个步骤。智慧给我们决策。

知识层次。数据到决策(智慧)
上面的模型从来没有暗示收集数据就足够了,它消除了决策的负担。数据驱动从来不意味着数据收集或逐字阅读。请记住,您的业务环境也是数据,即使它没有被公式化为您现在看到的数据。请记住,来自行业的见解或您去年收集的见解也是数据。这些额外的数据可以帮助你将当前的数据转化为智慧。
一方面,新的流行语告诉我们不外乎做数据解读,另一方面,它使我们陷入绿色木材谬论。我们开始把空谈者和实干家混为一谈,我们愚弄自己,认为知道流行词意味着我们擅长数据解释。通常,它会将注意力从核心转移开。
在添加新的流行词之前,重要的是找到平衡并理解权衡。基于数据的听起来不错,但基于数据的似乎有些自我放纵。
外卖食品
- 不要掩饰流行语,试着理解那些流行语想要表达的意思。
 - 数据驱动、数据通知、数据启发都是披着新衣的旧概念。它所做的只是要求你不要停止思考,不要成为数据原教旨主义者,不要做没有数据的解读。
 - 对流行语的了解并不意味着高超的数据解释技能。吹嘘你了解数据并不意味着你做出了正确的决定。不要愚弄自己,也不要在面试一个候选人的时候被愚弄。不要相信绿色木材谬论。
 
参考和延伸阅读
- Adam Mosseri 在 2010 年做了一个演讲“ 数据通知,而不是数据驱动 ”。这可能是“数据通知”框架在公共空间的首次使用。
 - 陈楚翔论 【数据知情 vs 数据驱动】
 - 数据化营销
 
数据高效的 GANs!
看看麻省理工学院最近令人兴奋的论文“数据高效 GAN 训练的差异化增强”
理解本文的前提:你训练过 GAN 或者你了解训练 GAN 时出现的常见困难比如训练数据上的甄别器过拟合。否则,一定要阅读这篇文章,或者自己花几个小时在谷歌上搜索甘斯。然后回到这里,享受这篇文章!
你读过甘斯的书。也许你已经训练了一只。也许你已经尝试过来训练一个,看着鉴频器损耗一降再降,然后“嘣”的一声,你在训练数据上过度拟合了。你打印出 100 张图片,其中 50 张是同样畸形的金毛猎犬图片。你去见你的教授,也许眼里含着泪水,你宣称:
‘模式崩溃,怎么办?’
“增加更多的数据,”你的教授说。或许打个盹。
不要害怕!麻省理工学院最近的论文“数据高效 GAN 训练的差异化增强”声称是你的救星,或者至少是它的一部分(赵,刘,林,朱&韩,2020)。该论文声称需要更少的数据,同时仍然使用一种称为“可区分”增强的特殊数据增强来实现最先进的结果。在这篇博文中,我会把茶洒在这张纸上(如果你还不知道,我对此非常兴奋)。我来告诉你这篇论文是怎么宣称提高 GAN 训练的,我来说说实际上有没有效果。所以,拿起一杯茶和一个笔记本,向 GAN 神祈祷这有助于击败“模式崩溃”的老怪物
甘斯的问题:快速回顾一下
在机器学习中,你将学到的第一个也是最重要的概念之一是“过度适应”。在鉴别器 GANs 的上下文中,D 在训练中继续改进,但是在验证期间表现很差,因为它已经开始“记忆”图像数据。这并不一定会导致模式崩溃,在这种情况下,您会得到许多相同的输出图像,尽管这种情况经常发生。如果您观察到模式崩溃,这是一种证据,表明鉴别器对数据过度拟合。通常,我们只是添加更多的数据来防止这个问题——当然,这通常是有帮助的……但是这么多的数据不一定容易收集。这篇论文提供了一个有力的例子:如果我们试图生成一个稀有物种的图像会怎么样?我们无法获得更多的数据。然而,我们不必把自己局限于稀有物种这种极端的边缘情况。即使当我们谈论像衣服这样的常规物品时,收集数据也是昂贵的。注释数据是昂贵的。需要年(赵等,2020)。我们希望模型现在工作。
解决方案:增强?
因此,现在我们将得到我们的论文谈到的解决方案。该论文观察到,当在监督学习的情况下出现过拟合时(比如一个简单的图像分类问题),并且我们没有更多的数据要添加,我们将对数据进行称为增加 的处理。[作为补充说明,请随意阅读其他解决过度拟合问题的方法,如正则化]。
图像增强是指将图片翻转过来或稍微改变颜色等。等等。我们只是稍微改变一下照片,这样我们可以得到更多的样本。但是对于 GANs,这种增强不能直接起作用。作者提供了两种我们可以在 GAN 训练期间增加数据的方法,以及为什么这两种方法都无法获得良好的输出图像。然后他们提供了第三种选择,这种选择起作用(微分增强),这就是他们论文的全部内容。所以这里有两个行不通的选择:
选项 1:仅增加 Reals】
大家还记得,当我们训练 GAN 时,我们输入的图像是实际物体的实际图片。我们用它和我们的生成器制造的赝品一起输入到鉴别器中。所以在第一种增强方法中,我们只是增强这些真实的图像。简单吧?
不对。
赵等人(2020)报告说,增强随机水平翻转确实适度地改善了结果。但是更强 增强比如翻译&只对真实图像进行剪切会导致生成的图像出现失真和怪异着色等问题。虽然普通增强可能适用于常规分类问题,但对于我们不分类的 gan,我们正试图生成数据的真实分布。但是,如果我们去扭曲真实的输入数据,那么我们生成的输出也将被类似地扭曲。鼓励发生器匹配增大的&失真分布,而不是真实分布。那么,扩充数据的第二个选择呢?
选项 2:增加所有鉴别器输入
在这个选项中,我们不仅增加了实数,还增加了由我们的生成器输出并进入我们的鉴别器的虚数。有趣的是,虽然鉴别器学会了以超过 90%的准确度在增强的真实和增强的虚假之间进行完美分类,但鉴别器未能识别未增强的虚假,导致准确度低于 10%。这是因为发生器 G 从非增强伪图像接收其梯度。因此,我们需要某种方式将梯度传播到我们的生成器 G. 否则,用赵等人(2020)的恐怖诱导的话来说:
生成器完全欺骗了鉴别器

图一。甘斯失败的增强方法。来源:赵等(2020)
选项 3:输入差异化增量
所以这就是作者提出了一种做工作的增强类型,即可微分增强。为了解决选项 1 和选项 2 的问题,作者提供了一个解决方案。增强了鉴别器网络中使用的真实和虚假图像,而且 2。成功地“将增强样本的梯度传播到 g。”这避免了我们之前在选项 2 下讨论的无法识别未增强的假货的问题。这是本文的关键:为了允许梯度传播到生成元 G,他们简单地非常确定增广是,如名字所说,可微的。作者提供了这种可区分增加的三个主要例子:
平移(在图像大小的[1/8,1/8]范围内,用零填充),
剪切(用图像一半大小的随机正方形进行遮罩),以及
颜色(包括随机亮度在[0.5,0.5]范围内,对比度在[0.5,1.5]范围内,饱和度在[0,2]范围内)。
结果
这有用吗?是的。是的,它似乎起作用了。作者列出了一些非常酷的结果,我将在这里列出其中一些。我强烈建议你看看主要论文中的其他结果——它们确实让我大吃一惊。
成果#1 : CIFAR-10 和 CIFAR-100 数据集。作者使用了两个著名的 GAN,即 BigGAN 和 StyleGAN2,并尝试了几种数据集大小(100%数据、10%数据、20%数据)。为了使他们的比较与基线公平,他们甚至确保在基线方法中使用正则化&水平翻转。对于 CIFAR-10 和 CIFAR-100 而言,它们都比基线有所改进,是 CIFAR-10 和 CIFAR-100 的最新技术。
成就#2: ImageNet 。可区分增强推进了 100%数据集和缩减大小数据集的最新水平。
我喜欢本文中提出的解决方案的原因是它非常符合逻辑。作者 1。尝试了不同的增强方法。确定了确切的困难和 3。通过使用特定类型的增强,即在真实和虚假上执行的可区分增强,迅速修复了问题,从而允许梯度传播到生成器。然而,这个逻辑推导出的解决方案做了这么多。现在,任何训练 GAN 的人都可以将“使用可微分增强”添加到他们的规则工具箱中,如“向鉴别器输入添加噪声”和“惩罚[调整]鉴别器权重”(未注明)。
这篇论文真的让我很兴奋,促使我在凌晨 1 点写了一篇关于它的帖子。我希望我对它的讨论能帮助你理解这个解决方案是如何工作的,并让你兴奋起来!
最后,论文中的一张图清晰地展示了他们的方法:

图二。“更新 D(左)和 G(右)的 DiffAugment 概述”。DiffAugment 将扩充 T 应用于真实样本 x 和生成的输出 G(z)。当我们更新 G 时,梯度需要通过 T 反向传播,这要求 T 对于输入是可微分的。”图片来源&图片说明:赵等(2020) 。
参考文献
赵树声,刘,张,林俊杰,朱俊英,韩树声(2020)。数据有效的 GAN 训练的可区分增强。arXiv 预印本 arXiv:2006.10738 。从 https://arxiv.org/pdf/2006.10738v1.pdf取回
生成性对抗网络(未注明)。常见问题。谷歌开发者。从 https://developers.google.com/machine-learning/gan/problems取回
数据工程和数据科学协作流程
沮丧、紧张和痛苦都是缺乏共同合作基础的结果。找到重视每个数据角色的最佳协作流程是最基本的。
作为一名数据工程师,我有机会经历了一个数据工程师/数据科学家的合作过程,并很快看到了它的失败。因此,我对我们如何改善这种合作变得非常感兴趣,并开始记录自己在其他可以改善团队合作的过程中的表现。因此,本文介绍了数据工程师和数据科学家之间的多个组织,每个组织都有其优点和缺点。
数据工程师将数据科学项目产业化
当数据科学家和数据工程师不使用相同的编码语言并且数据工程师是负责生产代码的人时,一切都必须重新编码。

数据科学家/数据工程师组织:数据工程师将数据科学项目工业化
当然,在对数据科学项目进行重新编码之后,数据工程师将会有一些额外的任务,比如调度、构建部署部分以及确保自己创建了监控功能。
好处:
- 这位数据科学家仍然呆在他的舒适区,因为他可以用任何他想用的语言工作
 - 数据科学家在探索部分是自主的
 - 数据工程师仍然呆在他的舒适区,因为他可以使用他认为适合项目的语言和项目架构
 
陨落:
- 它没有“评估”团队的每个成员(在这种情况下也就是数据工程师)。尽管用另一种语言,以一种更优化、更工业化的方式创建同一个项目会有很多挑战,但它创造了一个“思考者”/“实干家”的组合,没有一个工程师愿意只是另一个“实干家”
 - 数据科学家不能自主添加新功能。每一个新特性都需要一个数据工程师来负责产品代码部分,一个数据科学家来评估非工业化项目中的变化。
 - 该项目必须由两个不同的人用两种不同的语言维护(以便能够进行更新)
 
构建数据科学框架
当有了数据工程师和数据科学家使用的通用编码语言,前者就可以免去一切重新编码的麻烦。重新编码部分将被可选的优化所取代。

通过数据科学框架进行数据科学/数据工程师协作
当然,为了限制数据科学家需要学习的技术数量,数据工程师可以创建一个数据科学框架,隐藏/抽象架构复杂性和部署复杂性。
然而,创建这个框架并不意味着数据科学家将独自完成每个项目,仍然有一些任务,如监控功能、优化和构建所需的 API,应该由数据工程师来完成。
然而,这种组织给了数据科学家更多的自主权,因为有些变化不需要数据工程师。
这种组织在 Dailymotion 使用,更多细节我推荐这篇由 Germain Tanguy 写的文章。
好处
- 数据工程师并不是对所有事情都重新编码:没有思考者/行动者的关系
 - 该框架将加速数据科学项目的开发和部署
 - 数据科学家更加自主
 
弊端
- 就数据准备而言,数据工程师只负责优化
 - 建立和维护这样一个框架需要时间
 
封装和结对编程
当没有数据工程师和数据科学家使用的通用编码语言时,你可以试着像 Coursera 数据工程师刘璐珈建议的那样使用 SQL 作为对等编程的通用语言。

通过包和结对编程进行数据科学/数据工程师协作
如果在一些数据科学领域,SQL 不能作为通用语言使用,那么您可以使用包在不同的数据科学阶段和数据工程师之间进行通信。
这本 Xebia 书描述了我们可以创建三个包的事实:
- 特征工程包
 - 用于已训练模型的包
 - 预测部分的包
 
根据您的架构,包可以采用不同的形式:docker 图像、Kafka 队列中的消息等。
在这个协作过程中,数据工程师将主要负责部署模型、监控功能,并在对等编程部分帮助进行测试和优化。
好处:
- 数据工程师并不是对所有事情都重新编码:没有思考者/行动者的关系
 - 数据准备部分的对等编程将有助于两个角色之间的协作
 - 对于建模部分,我们通过使用包作为数据工程师和数据科学家之间的通信来划分职责
 
缺点:
- 使用 SQL 作为通用语言可能会限制语言的可能性。例如,在 Python 中,如果不使用 SQL,可以更容易地进行一些数据操作
 
数据男/数据女
我的一个朋友告诉我,他认为自己是一个“数据人”。事实上,从某个角度来看,我们都在学习不同的技能,因此你可以找到既有数据工程技能又有数据科学家技能的人。

数据男/数据女
弊端:
- 这个人可能会独自处理一些项目(如果这个人离开,可能会丢失一些信息)
 
好处:
- 项目速度
 - 因为这个人拥有所有需要的技能,所以没有共同的基础去寻找
 
笑点
没有完美的协作过程,每个协作方案都有一些缺点和一些好处;取决于您和您的团队,根据您的环境以及您的数据工程师和数据科学家拥有或想要培养的能力,选择最适合您公司的组织!
数据工程师、数据科学和数据分析师—有何区别?
了解数据领域的职业

马库斯·斯皮斯克在 Unsplash 上的照片
数据是新的石油!
这句话你可能听过很多遍了。这句话可以说是对的,例如在古代,石油是世界上最有价值的资源。从政府到当地公司,这是所有事情的关键功能。没有它,进步就会停止,经济就会萎缩。
快进到 21 世纪,一些世界上最有价值的公司,如谷歌、脸书或亚马逊,将他们的整个业务建立在有效处理个人数据的基础上。个人数据据说是当今网络社会市场上最热门的商品。例如,与唐纳德·特朗普的选举团队合作的剑桥分析公司(Cambridge Analytica)的争议是收集 5000 万脸书个人资料的数据成为可能有助于扭转选举的广告活动。我们可以说,如果你有数据,你就可以统治世界。
今天,许多公司都意识到数据的有用性,从获取数据到处理数据以产生公司需要的信息。因此,出现了专门与数据相关的职业。这就是专门与数据相关的职业,我将讨论其中的一些。这些是与数据相关的职业:
数据架构师

丹尼尔·麦卡洛在 Unsplash 上的照片
数据架构师在实际数据存在之前就开始工作。如果数据就像一座建筑,那么在我们建造这座建筑之前,我们必须首先设计这座建筑的样子。从使用的材料、结构到设计。我们当然不希望建筑不符合我们的意愿,因为我们的粗心而导致建筑倒塌或损坏。同样的,对于数据,我们当然不希望我们的数据分崩离析,以至于将来会出现混乱。
数据工程师

数据工程师构建并优化允许数据科学家和数据分析师工作的系统。每家公司都依赖于与其合作的每个人的准确且可访问的数据。数据工程师确保数据被正确接收、转换、存储,并可供其他用户访问。
假设在石油和天然气中。数据工程师的职责是制造管道,将原油排放到像汽油一样随时可以使用的地方。数据工程师负责构建数据管道,通常需要使用复杂的工具和技术来处理大规模数据。数据工程师更倾向于一套软件开发技能。数据工程师的思维方式通常更侧重于开发和优化。
数据科学家

在 Unsplash 上拍摄的 ThisisEngineering RAEng
数据科学家是应用他们在统计和建立机器学习模型方面的专业知识来进行预测并成为关键商业问题的专家。可以说,数据科学家有责任将数据处理成洞察力。
数据科学家必须能够清理、分析和可视化数据,并能够训练和优化机器学习模型。在每个公司中,数据科学家的方向可能会有所不同,例如,汽车公司中的数据科学家角色对数据的要求与餐饮公司不同。我们以一家金融科技公司为例,与金钱相关的数据,比如你能存多少钱,花多少钱,还可以使用机器学习来预测未来。
数据分析师

照片由克里斯蒂娜@ wocintechchat.com在 Unsplash 上拍摄
数据分析师通过数据为他们的公司提供价值,使用数据回答问题并交流结果以帮助业务决策。通常由数据分析师完成的普通工作与数据科学家一致,例如数据清理、执行分析和创建数据可视化。但是数据分析师更侧重于分析和数据通信。
就像数据科学家一样,数据分析的分组取决于公司的需求,取决于公司在什么领域。数据分析师的头衔可以是商业分析师、商业智能分析师、运营分析师、数据库分析师等。
无论头衔如何,数据分析师都是多面手,可以适应许多角色和团队,帮助他人做出更好的数据驱动型决策。数据分析师有潜力将传统业务转变为数据驱动型业务。
数据科学家带来了理解数据的全新方法和视角。虽然分析师可能能够描述趋势并将这些结果转化为商业术语,但科学家会提出新的问题,并可以根据新数据建立模型进行预测。
数据分析师必须通过分析新数据、组合不同报告和翻译结果,成为不同团队之间的有效桥梁。反过来,这使组织能够对其增长保持准确的脉搏检查。
如果你喜欢这篇文章,你可以看看我下面的其他故事。
做机器学习项目的分步指南
towardsdatascience.com](/how-to-start-a-machine-learning-project-5654832cb1ed) [## 人工智能、机器学习和深度学习——有什么区别?
人工智能、机器学习和深度学习的简单解释以及它们之间的区别
towardsdatascience.com](/artificial-intelligence-machine-learning-and-deep-learning-what-the-difference-8b6367dad790) [## 使用 Python 创建你想要的任何形状的单词云
创建漂亮单词云的分步指南
towardsdatascience.com](/create-word-cloud-into-any-shape-you-want-using-python-d0b88834bc32)
数据工程师,模式和架构未来
深入了解流流程的微服务模式

我创造的形象【http://www.igfasouza.com/
TL;博士
在工业 4.0 中,使用了多种技术来进行实时数据分析,另一方面,维护、组织和构建数据是一项复杂的工作。在过去的 30 年里,我们看到了几个将数据库集中在一个地方的想法,因为统一和真正的数据源已经在公司中实现,如数据仓库、NoSQL、数据湖、Lambda & Kappa 架构。
另一方面,软件工程一直在将想法应用于分离的应用程序,以促进和提高应用程序性能,如微服务。
想法是使用日期上的微服务模式,并将模型分成几个更小的模型。分解它的一个好方法是使用 DDD 原则的模型。这就是我试图解释和定义 DataMesh & Data Fabric 的方式。
这里值得一提的是,我简化了数据网格和数据结构的概念和思想,就像我简化了流和 Kafka 的概念和思想一样。
想法
我被邀请在一个数据工程师会议上做一个演讲,我带着这个想法来展示我对数据网格的看法。

https://www . meetup . com/engen haria-de-dados/events/271280539/
工业 4.0

图片灵感来自https://aethon.com/mobile-robots-and-industry4-0/
在过去的几年中,出现了一些想法和架构,如数据仓库、NoSQL、数据湖、Lambda & Kappa 架构、大数据等,它们提出了应该将数据整合并分组到一个地方的想法。将一个地方作为数据的统一和真实来源的想法。

我创造的形象
此处的图像显示了将所有数据分组到一个唯一的位置作为最终目标的概念。
近年来,软件工程领域已经表明,应用程序应该被隔离,以促进和提高应用程序的性能,并便于维护。向该司提出的一个想法是使用 DDD 和微服务。

我创造的形象
如果我们比较数据区和开发区,我们会发现两者的说法正好相反,一个想要统一,另一个想要分裂。
这正是 DataMesh 提出的想法,它提出了我们应该使用 DDD 和微服务的想法来分离数据,以生成更小、更简单的应用程序,这样维护和性能会更好。

Jeffrey T. Pollock 网上研讨会未来数据集成 datamesh 和金门卡夫卡

图片来自https://Martin fowler . com/articles/data-monolith-to-mesh . html
查看微服务模式,我们会发现有一些数据驱动的模式。如果我们更详细地分析它们,我们会发现它们都使用或链接到流处理。

映像的想法来自微服务架构:调整原则、实践和文化。但这个形象并不在书本身。由我创作灵感来自https://medium . com/@ madhukaudantha/microservice-architecture-and-design-patterns-for-microservice-e0e 5013 FD 58 a
这里的想法是,所有与数据相关的设计模式我们都可以应用流,并且像 Apache Spark、Apache Flink 和 Apache Kafka 这样的工具是目前使用最多的。围绕它还有一个生态系统,还有其他一些技术。

我创造的形象
我创建了一个表,其中列出了流媒体市场的主要选项,但这里的想法是,这不是一个银弹,只是我的愿景。这是主观的。

我创造的形象
我用来构思自己想法的书籍(我只想记住有几篇文章、论文和视频围绕着这些想法)
- 域驱动器设计师— Eric Evans
 - 微服务架构:调整原则、实践和文化——irak Li Nadareishvili、Ronnie Mitra、Matt McLarty 和 Mike Amundsen
 - Kubernetes 模式:设计云原生应用的可重用元素
 - 设计数据密集型应用— Martin Kleppmann
 - 第四次工业革命——克拉斯·施瓦布
 - 不可避免的——凯文·凯利
 

我创造的形象
我用来构思的文章:
- 作为数据库流式传输
 
https://Yokota . blog/2019/09/23/building-a-relational-database-using-Kafka/
https://Yokota . blog/2020/01/13/building-a-graph-database-using-Kafka/
- 事件驱动和数据网格
 
http://jacekmajchrzak . com/event-driven-data-mesh-introduction/
- 无服务器时代
 
https://blogs . Oracle . com/cloud-infra structure/server less-big-data-pipelines-architecture
- Martin Kleppmann |卡夫卡峰会 SF 2018 主题演讲(卡夫卡是数据库吗?)
 
【https://www.youtube.com/watch?v=v2RJQELoM6Y
- 库伯内特土著
 
https://medium . com/@ graeme colman/the-new-kubernetes-native-d 19 DD 4 AE 75 a 0
https://developers . red hat . com/blog/2020/05/11/top-10-must-know-kubernetes-design-patterns/
- GoldenGate 的微服务模式
 
https://www . slide share . net/jtpollock/microservice-patterns-with-golden gate
- 网上研讨会未来数据集成-datamesh-and-goldengatekafka
 
https://www . slide share . net/JT pollock/webinar-future-dataintegrationdatameshandgoldengatekafka
- 对分布式数据湖思想的思考
 
https://www.youtube.com/watch?v=mnvxeU3oDyQ
- 什么是服务网格?
 
https://www.youtube.com/watch?v=QiXK0B9FhO0
Twitter 影响者:
@ KaiWaehner
@ bib ryam
@ gschmutz
结论
- 分而治之是最好的开始方式,它简单,便宜,会节省你的时间和金钱
 - 一些公司在尝试实施大数据、数据湖和数据仓库时失败了,因为他们试图构建一些大而复杂的东西
 - 流媒体无处不在
 - 我们正处于多云和混合云时代
 - 无服务器架构越来越流行
 - 我们不应该关心名字,而应该关心目标
 - 我用一种方式简化了它,我传递了这样一个想法:是的,我们已经处于无服务器时代;
是的,我们已经处于土生土长的库伯内特人时代;
没错,串流就是数据库;
是的,流无处不在;
对,分而治之;
对,微服务模式;
是的,Kubernetes 图案是加分项; 
我的幻灯片:
追加:
- 大数据
 
http://www.igfasouza.com/blog/what-is-big-data/
- 阿帕奇火花
 
http://www.igfasouza.com/blog/what-is-apache-spark/
- 阿帕奇卡夫卡
 
http://www.igfasouza.com/blog/what-is-kafka/
- 流处理
 
http://www.igfasouza.com/blog/what-is-stream-processing/
- 数据仓库
 
https://www . Oracle . com/ie/database/what-is-a-data-warehouse/
- 数据湖
 
http://www.igfasouza.com/blog/what-is-data-lake/
- 数据仓库
 
https://databricks . com/blog/2020/01/30/what-is-a-data-lake house . html
- 工业 4.0
 
- 数据结构
 
https://www . Forrester . com/report/Now+Tech+Enterprise+Data+Fabric+Q2+2020/-/E-RES 157315 #
- 数据网格
 
https://Martin fowler . com/articles/data-monolith-to-mesh . html
- 微服务
 
企业家的数据工程

肖恩·波洛克在 Unsplash 上的照片
这是一家更加数据驱动的公司。
到在这个快速发展的世界中竞争,创业公司和公司应该更加敏捷,以客户为中心,并以数据为驱动力,以赢得市场。
他们中的大多数已经实现了敏捷技术,比如 scrum,来开发一个比以前更快发布的产品。
尽管如此,仍有一些公司没有实施这些以客户为中心和数据驱动的东西。
为了实现这一点,管理人员必须实施他们的数据基础设施,然后才能基于数据做出更准确的决策和更个性化的服务。
要解决这个问题,您应该优先考虑数据工程。
数据工程为什么重要?
这就是为什么它很重要的原因,
你有大量的数据。
在这个互联的世界里,你的交易可能不仅仅发生在你的城市或国家。全世界都知道你的产品和你的公司。正因为如此,你会有很多交易。因此,产生的数据变得更大。因此,你需要一个数据工程师来做这件事。
你有多种数据来源。
数据不仅越来越大,而且有多种类型,例如表这样的结构化格式和文本这样的非结构化格式。为了整合这些数据,你需要一个数据工程师。
您的数据还不能用于分析。
现在,您的数据库是一种结构化格式,为事务处理过程进行了优化。如果您看到数据库的模式,它们不在一个表上。有多个表,每个表都有自己的 id,也有其他表的 id。因此,如果您想为分析过程做好准备,那么您应该让数据工程师来解决它。
这些就是你应该优先考虑数据工程的原因。现在,什么是数据工程,他们做什么?
什么是数据工程?

数据工程是一个从收集数据到处理数据的过程,因此数据已经为分析过程做好了准备。
数据工程师是做什么的?
数据工程师将把你的数据整合到一个地方,然后使用任何现有的软件进行处理。之后,数据为分析过程做好了准备,或者,你可以在此基础上创建一个推荐系统。
他们使用什么工具?
他们使用的工具是,
- 数据库,工具有 PostgreSQL、MySQL、MongoDB 等。
 - 用于加工,工具有 Apache Spark,Hive 等。
 - 对于调度,工具有 Apache Airflow、Oozie、Cron 等。
 
注意事项

有一些需要考虑的因素,它们是,
云计算与否?
您可以为您的数据架构构建高性能的计算机。但是如果,
- 你没有维护电脑的成本,
 - 你没有支付电费的费用,或者
 - 你需要备份你的数据。
 
如果这些是你的考虑,你必须使用云计算。
云计算对于任何公司来说都是必须的,尤其是那些不想构建高性能计算机而需要数据架构的公司。云计算有数据工程可以使用的工具。有很多公司都有云计算服务,比如亚马逊网络服务、谷歌云、微软 Azure 等等。
什么时候考虑雇佣数据工程师?
你必须确定你将如何使用这些数据,它可能是用于决策或建立一个推荐系统。
如果你没有任何成为数据驱动公司的迫切需要,那么你就不必考虑雇佣数据工程师。但是如果你有,那么你应该找数据工程师。
在您拥有一个良好的数据架构并且已经可扩展之后,您就可以继续研究如何使用数据,包括数据分析、使用机器学习的预测建模或从数据中挖掘模式。
结论
在你做出决策或个性化服务之前,数据工程是必须的。在构建数据架构之前,您必须考虑要使用哪些数据以及如何使用这些数据。如果你已经有了很好的理由,那么你应该找数据工程师来构建解决方案。这样,你就可以在这个快速发展的世界中竞争。
2020 年的数据工程

数据处理工具和技术的发展速度之快令人难以置信。随之而来的是,数据工程学科的本质也在发生变化。我今天使用的工具与我十年前甚至五年前使用的工具有很大不同,然而,许多经验教训在今天仍然适用。
早在数据工程成为一件事和数据科学家成为 21 世纪最性感的工作之前,我就已经开始在数据领域工作了。六年前,我“正式”成为一名大数据工程师,我直接了解具有“传统”数据开发背景的开发人员在这一过程中所面临的挑战。当然,这种转变对软件工程师来说也不容易,只是不同而已。
尽管技术在不断变化——这是在技术行业工作的任何人的现实——我必须学习的一些技能仍然相关,但经常被刚刚开始向数据工程过渡的数据开发人员忽略。这些通常是软件开发人员认为理所当然的技能。
在这篇文章中,我将谈论数据工程的演变以及“传统”数据开发人员今天可能需要学习的技能(提示:它不是 Hadoop)。
数据工程师的诞生。
大数据热潮之前的数据团队是由商业智能和 ETL 开发人员组成的。典型的 BI / ETL 开发人员活动包括将数据集从位置 A 移动到位置 B (ETL ),并使用该数据构建 web 托管的仪表板(BI)。这些活动都有专门的技术,知识集中在 IT 部门。然而,除此之外,BI 和 ETL 开发与软件工程几乎没有什么关系,软件工程是在本世纪初非常成熟的学科。
随着数据量的增长和对数据分析兴趣的增加,在过去的十年中,新技术不断涌现。他们中的一些人死了,其他人被广泛采用,这反过来改变了对技能和团队结构的需求。随着现代 BI 工具允许分析师和业务人员在 IT 团队支持最少的情况下创建仪表板,数据工程成为一门新的学科,使用一套新的工具将软件工程原则应用于 ETL 开发。
挑战。

亚历山大·杜默摄于佩克斯
创建数据管道听起来很容易,但是在大数据规模下,这意味着将十几种不同的技术(或者更多!).数据工程师必须深入了解各种技术,为工作选择正确的工具,并用 Scala、Java 或 Python 编写代码来创建弹性和可伸缩的解决方案。数据工程师必须了解他们的数据,才能创造出受益于分布式处理能力的工作。数据工程师必须了解基础架构,才能确定失败作业的原因。
从概念上讲,这些数据管道中有许多是典型的 ETL 作业——从许多数据源收集数据集,将它们放在一个集中的数据存储中,准备进行分析,并为商业智能或机器学习进行转换。然而,“传统的”ETL 开发人员不具备在大数据世界中执行这些任务的必要技能。
今天还是这样吗?
我看过很多描述数据工程师应该具备哪些技能的文章。他们大多建议学习像 Hadoop、Spark、Kafka、Hive、HBase、Cassandra、MongoDB、Oozie、Flink、Zookeeper 这样的技术,这样的例子不胜枚举。
虽然我同意了解这些技术不会有什么坏处,但我发现在今天的许多情况下,在 2020 年,“了解它们”就足够了——它们旨在解决哪些特定的用例,它们应该或不应该在哪里使用,以及有哪些替代方案。近年来,快速发展的云技术带来了大量的云原生应用和服务。正如几年前现代 BI 工具使数据分析更容易为更广泛的业务所用一样,现代云原生数据堆栈简化了数据接收和转换任务。
我不认为像 Apache Spark 这样的技术在未来几年内会变得不流行,因为它们非常适合复杂的数据转换。
尽管如此,像雪花和谷歌 BigQuery 这样的云数据仓库的高采用率表明它们提供了某些优势。其中之一是 Spark 需要高度专业化的技能,而基于云数据平台的 ETL 解决方案严重依赖 SQL 技能,即使对于大数据也是如此——这样的角色更容易胜任。
数据开发人员需要具备哪些技能?

BI / ETL 开发人员通常对数据库基础、数据建模和 SQL 有很强的理解。这些技能今天仍然很有价值,并且大多数可以转移到现代数据堆栈中,这比 Hadoop 生态系统更精简、更容易学习。
以下是我经常观察到的“传统”数据开发人员在知识方面存在差距的三个领域,因为在很长一段时间里,他们没有软件工程师拥有的工具和方法。理解和修复这些差距不会花费很多时间,但可能会使向一组新工具的过渡更加顺利。
- 版本控制(Git)和对 CI/CD 管道的理解
 
SQL 代码是一种代码,因此,应该应用软件工程原则。
- 了解谁、何时以及为什么更改了代码是很重要的
 - 代码应该与可以自动运行的测试一起提供
 - 代码应该很容易部署到不同的环境中
 
我是 DBT 的忠实粉丝——这是一个开源工具,它将软件工程的最佳实践带到了 SQL 世界,并简化了所有这些步骤。它比那要多得多,所以我强烈建议去看看。
2。对现代云数据分析体系有很好的理解
我们倾向于坚持使用我们熟悉的工具,因为它们通常会让我们更有效率。然而,我们面临的许多挑战并不是独一无二的,而且通常可以在今天更有效地解决。
一开始尝试在云生态系统中导航可能会令人生畏。一个解决办法是学习其他公司的经验。
许多成功的创业公司都非常开放他们的数据堆栈和他们在旅程中学到的经验教训。如今,采用云数据仓库版本和其他几个组件进行数据摄取(如 Fivetran 或 Segment)和数据可视化是很常见的。看到一些架构通常足以获得 10,000 英尺的视野,并知道在需要时进一步研究什么—例如,处理事件或流数据可能是一个全新的概念。
3。除了 SQL 之外还要知道一门编程语言
尽管我很喜欢 Scala,但 Python 似乎是今天开始的一个安全的赌注。它相当容易掌握,受到数据科学家的喜爱,并且几乎得到云生态系统所有组件的支持。SQL 非常适合许多数据转换,但有时在将复杂的数据结构吸收到表中或使用它自动化数据管道中的特定步骤之前,用 Python 解析复杂的数据结构更容易。
这不是一个详尽的列表,不同的公司可能需要不同的技能,这就是我的最后一点…
数据工程师的角色正在发生变化。

在过去的几年里,数据处理工具和技术有了很大的发展。他们中的许多人已经发展到可以随着数据量的增长轻松扩展,同时也能很好地处理“小数据”的程度。这可以显著简化数据分析堆栈和使用它所需的技能。
是否意味着数据工程师的角色正在发生变化?我也这么认为这并不意味着它变得更容易—业务需求随着技术的进步而增长。然而,看起来这个角色可能会变得更加专业化或者分成几个不同的学科。
新工具使数据工程师能够专注于核心数据基础设施、性能优化、定制数据接收管道和整体管道编排。同时,那些管道中的数据转换代码可以由熟悉 SQL 的任何人拥有。比如分析工程开始成为一个东西。这个角色位于数据工程和数据分析的交叉点,专注于数据转换和数据质量。云数据仓库工程是另外一个。
不管职称的区别是否会被广泛采用,我相信“传统的”数据开发人员拥有许多基本技能,可以在当今许多与数据工程相关的活动中取得成功——强大的 SQL 和数据建模是其中的一部分。通过了解现代云分析数据堆栈以及不同组件如何组合在一起,学习编程语言并习惯版本控制,这种过渡可以相当无缝。
GCP 专业化的数据工程
数据专业人员综合指南
从 Coursera 专业化到认证考试
如果你是一名考虑提升技能的数据专业人士,学习选项并不缺乏,但如果你正在寻找将数据和分析迁移到云的方法,你只能在有限的公共云提供商之间进行选择。
本指南关注谷歌云,更具体地说是谷歌云上的数据工程专业化(正式名称为谷歌云上的数据工程专业证书),并为您提供最新信息和实用建议。
它是基于我自己完成专业化的经验,以及从在该领域工作的其他数据工程师那里收集的信息。
如果你对谷歌云专业数据工程师认证考试感兴趣,那么无论如何专业将会是你的起点。还将讨论认证考试。
该指南包括以下内容:
- 相关学习选项概述
 - 材料涵盖的内容
 - 为什么要考虑数据工程专业化
 - 回顾:有什么好/缺什么/有什么亮点
 - 专业化的实用技巧
 - 完成专业化后的后续步骤
 - 认证考试
 
阅读完这些信息后,你应该能更好地决定这门课程是否适合你。
关于专业化
首先,让我们确定你在正确的地方。
谷歌云专业化的数据工程是属于谷歌云数据轨道的几个按需专业化之一。
它有一个“孪生兄弟”,一个叫做数据工程、大数据和谷歌云上的机器学习的专业。两个专业都在 2020 年 2 月接受了一次大修。本指南适用于两者的改款。我将解释两者之间的细微差别(以及如何一石二鸟,如果你想这么做的话)。
1.谷歌云的学习选项
这一部分将帮助你把专业化放在上下文中,并了解它如何与各种学习选项相关联。由于有多种选择,找到最佳学习路径并不总是显而易见的。
谷歌云的选项包括:
- 实验室
 - 探索
 - 课程
 - 特化作用
 - 专业认证。
 
几个主题,如 BigQuery、Data Studio 和 AI 笔记本,涵盖在多个实验室、课程和专业中,尽管深度各不相同。
为了简单起见,把一门课程想象成你将用来有意义地“学习一些东西”的标准单元。然后将所有其他上游或下游选项与该课程概念相关联。
- 课程由谷歌制作,但通过外部提供商提供,如 Coursera 和 Pluralsight。
 - 一门课程,连同视频和阅读材料,将让你有机会进入几个实验室,这将作为家庭作业的一部分。这些实验室由 Qwiklabs 托管,qwik labs 是一家被谷歌收购的培训公司。
 - 如果你想要更多的练习,你通常可以在 Qwiklabs 网站上找到与感兴趣的特定主题相关的附加实验。有 400 多个实验室覆盖了几乎所有的谷歌云产品。
 - 许多实验室结合了不止一个谷歌云产品。这些相关的实验室组成小组,所谓的任务,任务可以有不同的难度。
 - 一个专业通常是四到五门课程的集合,这些课程基于一个更广泛的主题,例如数据工程。
 - 一旦你成功完成了专业化,你就可以开始考虑相应的谷歌认证考试(阅读下文了解更多)。
 
2.覆盖什么材料
处于高水平
专业化教会你如何设计和管理云上的数据管道:从访问来自各种来源的数据和转换并存储它们,到执行分析以获得商业见解或机器学习以进行预测。然后,它会教你如何打包所有这些步骤,并使数据管道自动化。工作流必须适应任何类型的数据量、速度和多样性。
数据是成批到达还是流式传输进入?是结构化还是非结构化?是很小还是特别大?这些都是数据工程师必须知道如何处理好的工作方面,它们都在本课程中得到了全面的阐述。
最终目标是通过为企业提供基于数据的决策来增加价值。

由 roman pentin 在 Unsplash 上拍摄的照片
产品
例如,当可视的最终产品是交互式实时仪表板或自适应 ML 驱动的 web 应用程序时,数据工程师通常是使这一切成为可能的隐形英雄。
然而,要实现这一切,你必须熟悉越来越多的谷歌云工具,这些工具在构成专业的 6 门课程中逐渐被涵盖。
以下是涵盖的一些关键产品:
云存储,BigQuery 包括 BigQuery ML 和 Data Studio,Dataflow,Dataproc,Pub/Sub,Composer,Datafusion,Kubeflow,ML APIs,AutoML,AI 笔记本。
如果你想了解更多关于这些产品的信息,有一本方便的指南描述了每一个产品,还有很多其他的谷歌云产品,篇幅不超过 4 个字。
学习使用所有这些产品就像是将不同的谷歌云产品拼在一起,你需要决定哪些部分最适合在性能、实用性和成本效益之间取得合理的平衡。
3.为什么选择专业化?
如果你在专业上朝着数据工程的方向发展(有很好的理由这么做),这个问题的答案很明显。
如果您想知道为什么要在云上进行,那么无运营/无服务器的自动化承诺可能会非常有吸引力。
此外,如果你是数据分析师、数据科学家或领导这种类型团队的人,如果你想了解云+人工智能+数据结合在一起时创造的可能性,这种专业化将与你非常相关。如果这符合你的特点,我推荐你去看看专业学院的以下 3 门课程:
4.回顾
4.1 关于专业化的基本信息

twinsfisch 在 Unsplash 上拍摄的照片
难度:与其他 Coursera 编程课程相比,难度属于中等水平,因为你实际上并不需要调试代码。
时间承诺:和上面的原因一样,如果你想的话,你可以相当快的完成六门课程。但不建议把所有课程都挤在一两周内。最好给自己一些时间来吸收这些概念,并边走边练习。
成绩:通过测验和实验需要 80%或更多的分数,但是你可以尝试多次。最终结果不包含数字或字母等级(只是及格)。
必备知识:
- SQL 了解数据库管理/提取-转换-加载/大数据的概念和术语
 - 基本命令行
 - 脚本语言基础知识(部分实验室使用 Python)
 
熟悉一般云(虚拟机、存储等。)和机器学习概念也很有用,尽管入门课程将帮助您快速掌握这些概念。
基础知识足够。在上述任何领域都不需要深厚的专业知识。
4.2 有什么好的?
- 高质量的生产和易于跟进的材料,在课程和不同部分之间自然流动。
 - 2020 更新内容,包括一些仍在 alpha 中的酷功能。
 - 良好的平衡概念和实践方面的。
 - 所有课程中都有大量的动手实验和演示。
 - 关于各种工具和技术如何随时间演变的背景和观点。
 - 所有内容要么是 SQL 要么是 Python(不需要 java 编程,这使得课程更具包容性)。
 - ****提示和技巧如何降低账单,尤其是针对 BigQuery
 
4.3 缺少什么?
- 编写代码的机会越来越多,随着进展,实验室通常会变得更加自主。
 - 更多活跃论坛对话
 - 更多详细测验有助于更好地理解概念。
 - 更多的 TensorFlow ,至少是一个概述或者介绍。尽管 TensorFlow 是谷歌的一个标志性项目,但它实际上已经消失了。
 - 更多内容超出了构建机器学习模型所需的几行 SQL 代码。它还应该涵盖机器学习过程的基础知识、可能的陷阱以及评估结果的方法,以便数据工程师能够更自信地应用它。****
 - 更多关于服务成本的讨论以及与其他可用选项的比较。例如,“如果在课程之外进行,运行实验室的平均成本是多少?”
 
4.4 亮点
根据我的专业经验,以下是我个人关于谷歌云数据分析和工程的亮点:
1。BigQuery 的普遍存在
BigQuery 提供了比数据仓库更多的功能。它存在于每一门课程中,并与数据工程管道中的几乎每个阶段相联系。随着数据湖和数据仓库之间的界限变得模糊,传统的 ETL 开始看起来更像 ELT,它的地位可能仍然是中心。
2。多层次机器学习的可及性
通过像 BigQuery 和 BigQuery ML (一个集成到 BigQuery 中的框架)这样的产品,以及结合 AutoML 和预先训练的 ML API,在机器学习的可访问性和可扩展性方面出现了一个新的现实。现在,开发人员、数据分析师和数据科学家可以从不同角度来研究机器学习。
3。机器学习流水线的自动化
在第 1 点和第 2 点之后,通过人工智能平台上 Kubleflow 管道的管理体验,达到了下一个抽象层次。 Kubeflow pipelines 在完整的机器学习工作流程(数据预处理、特征工程、模型训练和部署)中协调 BigQuery 和 BigQuery ML 以及多个其他步骤,使可扩展和可重用的机器学习解决方案的生产成为可能。
****注意:在本课程中,您只能感受到其中的一点点味道,但是无需管理 Kubernetes 集群就能实现这一点的前景无疑是充满希望的。

上面讨论的 Kubeflow、BQML、AutoML 和 ML APIs 代表了 Sara Robinson 金字塔中的不同抽象层次,它展示了 GCP 上可用的各种 ML 选项,以适应不同的用例及技能组合。
5.实用技巧
1。获得离线访问。
如果你想在离线状态下不受干扰地学习课程,同时建立一个包含所有相关内容的图书馆,你可以使用 Coursera-dl ,这是一个开源工具,可以自动下载所有可用的视频和幻灯片。
2。获取代码。
如果你没有时间完成整个专门化,但是你仍然希望看到例子和使用的代码,你可以在这个 GitHub repo 中找到实验室使用的所有代码——布局很像食谱库。
3。获取资源
每个实验给你 1.5-2 个小时的时间,这通常是绰绰有余的,剩下的时间可以用来试验谷歌云,而不需要从你的信用卡上收费。
将 GitHub repos 中的幻灯片、视频、演示、实验和代码结合起来,以一种对您有意义的方式进行组织。这样,你可以建立一个食谱库,帮助你解决一些常见的使用案例——非常有用,尤其是在课程结束后的第一步。
****4。1 个中的 2 个认证
你更喜欢你的最终证书上写着“GCP 的数据工程、大数据和机器学习”而不是“数据工程”吗?这两个专业实际上是相同的。唯一的区别是,数据工程专业包含一门额外的课程,旨在为专业考试做准备。一旦你完成了数据工程专业,你可以注册另一个,你将立即收到其他认证(没有额外的费用,也没有额外的课程或实验室)。
5。第一个月免费。
如果你没有赞助商,谷歌通常会通过 CloudOnAir 网上研讨会或其他促销活动提供第一个月的免费或大幅折扣——小心他们。或者,您也可以在购买课程前对其进行编辑(在您注册时寻找此选项,因为它可能不太明显)。无论如何,如果你考虑到在离线环境中提供的相同内容的价格可以超过 2000 美元,那么这笔钱是非常值得的。
6.后续步骤—认证考试
专业考试成功秘诀
本部分提示由认证工程师 Suraj Pabari 提供。
通过专业的 6 门课程当然不能保证你会精通这个主题。
完成专业学习并积累大量实践经验后,下一步可能是准备专业数据工程师考试。这是一个向你的客户和雇主展示你的经验的正式资格。
完成专科后如何准备考试?
以下是三个很好的建议:
1.理解为什么:在做练习考试题时,与其跳到‘感觉对’的答案,不如试着理解为什么答案可能是对的。例如,应该使用 BigTable 而不是 BigQuery 吗?在什么情况下可以使用 BigQuery?为什么不用谷歌云存储?浏览给出的所有选项,并尝试理解每个选项的适用范围。如果你犯了一个错误,试着理解你为什么错了,这样你就不会犯同样的错误两次。
2.用例研究:专门化包括一些有用的用例研究:回顾这些并尝试开发一个在给定约束条件下能够工作的基础设施。这将测试你的理解能力,也非常适用于你可能面临的潜在现实生活挑战。思考每个阶段的权衡,并提出选择。您还可以考虑与您合作的公司的需求,并尝试提出最合适的基础架构。
3.练习应用你的知识:确保你真正理解概念,给自己设定挑战,测试你是否能使用谷歌云产品完成挑战。Kaggle 有一些很棒的例子(也有笔记本答案)。思考公共数据源的有用示例:例如,您能否使用 BQML 来预测 COVID 案例数量和股票价格之间的关系,或者使用 Google Analytics 数据建立购买倾向模型。
关于额外的提示,我推荐查看 Panagiotis Tzamtzis 的博客文章和 Vinoaj Vijeyakumaar 的幻灯片。
另请注意,截至 2020 年 5 月,官方谷歌云认证专业数据工程师学习指南已有印刷版本。
7.后续步骤—更多建议
或者,您可以跟进数据跟踪的另一个专门化,例如从数据到洞察或使用 TensorFlow 的机器学习。一些主题,如 BigQuery 或 AI 平台,在这些其他专业中有更深入的讨论。
另一个选择是追求深度而不是广度,专注于你发现与你自己的工作最相关的数据工程的各个方面,同时也要意识到全貌。****
您可以关注与您在数据工程领域感兴趣的特定领域共享内容的社区和个人。
例如,如果你对 BigQuery 和 BigQuery ML 感兴趣,你会发现谷歌人 Lak Lakshmanan 、 BigQuery 权威指南的作者和专业讲师,以及谷歌开发者倡导者 Felipe Hoffa (以及他的 BigQuery twitter 列表)和 Polong Lin 分享的精彩内容。
更多建议:
- 查看 GCP slack 社区(有一个频道专门讨论#数据工程)。
 - 注册专业证书持有人的私人 Coursera 社区(通过所有课程后,您将收到 Coursera 的信息)。
 - 寻找当地的谷歌开发者社区,探索这些团体专门提供的培训选项。
 - 由于每周都会有产品更新,所以关注谷歌云博客或其他相关资源来保持更新是一个好主意(随着时间的推移,培训的某些方面会变得过时)。
 

练习你刚刚学到的东西。凯利·西克玛在 Unsplas 拍摄的照片
最后
对于任何想学习如何在谷歌云上设计和开发数据管道的人来说,数据工程专业是一个很好的选择。
无论你是想成为一名数据工程师,还是只想更好地了解这一令人兴奋的领域,我的建议是从某门课程的内容开始,感受一下它在实践中的样子。查看剩余课程的详细教学大纲,决定是否有一门或多门或者全部专业课程适合你。****
****非常感谢经验丰富的 GCP 开发者Suraj Pabari 和 Panagiotis Tzamtzis 对指南的贡献和反馈。
****特别感谢Mark Edmondson,他的开源软件和文章向我介绍了数字营销领域的 Google Cloud。
关于专业化或通往认证考试的道路,你有更多的建议吗?请在下面的评论区留下它们。
亚历克斯·帕帕乔治
我是营销分析和数据科学领域的独立顾问,帮助转化驱动型数字企业做出明智的营销决策。我在我的 博客 和 上,通过 Twitter 和LinkedIn分享我关于数字、营销和数据分析的故事。**
** [## Alex Papageorgiou 营销分析顾问,前谷歌员工| www.alex-papageo.com | LinkedIn
www.linkedin.com](https://www.linkedin.com/in/alexandrospapageorgiou/)
我在 Medium 上发表的故事,你可能也会喜欢:
[## 用最新的维基百科探索人工智能、数据科学和机器学习的意义…
数据科学、机器学习和人工智能等术语已经在互联网上找到了它们应得的位置
towardsdatascience.com](/exploring-the-meaning-of-ai-data-science-and-machine-learning-with-the-latest-wikipedia-5fea5f0a2d46) [## 内核、点击和提升的树:第一届 Google Analytics Kaggle 竞赛集锦
我参加了上周结束的广受欢迎的谷歌分析竞赛。
medium.com](https://medium.com/innovation-machine/google-analytics-kaggle-competition-highlights-eaa046737ac4) [## 在 R 和 Python 之间选择:数字分析师指南
“R 还是 Python?一个数字分析师应该选择什么?
medium.com](https://medium.com/innovation-machine/choosing-between-r-and-python-a-digital-analysts-guide-b7103f80aa4e)**
数据工程:是什么?
基于数据和历史背景的定义

数据工程正在迅速崛起。在过去的两年里,数据工程在英国招聘的职位中所占的比例增加了一倍多。在 1.5%的水平上,有近 2200 个未平仓头寸。相比之下,“软件工程师”约占 4.6%。以及“项目经理”3.1%。
数据工程甚至比网页开发更受欢迎(1.2%)。
更新【2020 年 11 月 09 日】:在 11 月 09 日之前的六个月期间,这一比例目前为 1.86%,高于本文最初发表日期 2020 年 5 月 11 日之前的 1.5%,也高于 2019 年同期的 1.13%。然而,由于疫情期间就业市场整体放缓,1.86%现在仅代表约 900 个开放职位。

英国数据工程师职位空缺趋势来源: IT 职位观察 (CC BY-NC-SA 4.0)
很明显,数据工程是一项有价值的技能,但它是什么呢?和其他类似的技能组合有什么不同?
概述
大多数职位描述都提到了 Python (66%)和 SQL (56%)。许多人提到像 AWS 这样的平台(42%)和像 T21 这样的过程(42%)。但是数据工程的本质是创建移动数据的管道。
你的每一个人、每一项业务都会不断产生数据。每个事件记录公司的功能(和功能障碍)——显示赚到的钱和损失的钱;社交媒体、第三方合作伙伴、收到的货物、发货的订单。但是,如果这些数据从未被看到,就不会有任何见解。
数据工程要求知道如何从数据中获取价值,以及将数据从 A 点移动到 B 点而不掺杂的实际工程技能。
对于数据工程师来说,知道如何访问所有这些数据(无论其来源或格式如何)是一项关键技能。访问数据可能需要抓取 web、pdf 或半打不同风格的 SQL 和非 SQL 数据库。另一项技能是知道如何高效地移动和存储数据(在时间和成本方面)。处理大量数据是一项专业技能。然而,最重要的是保存数据的价值。
并非所有的数据都是信息
数据只有能被理解才有价值。如果我告诉你今天的天气是 0 级,气温是 0.756743 度,T4 会打我一巴掌。电脑通常会给出更隐晦的回应。解密它们需要两样东西:背景和专业知识。
此外,将数据从一个系统转移到另一个系统会删除大量上下文。专家解释数据时通常需要这种环境。许多不同的系统,许多不同的专家,许多解释。好的数据工程是关于收集解释和数据,并呈现所有用户都能理解的统一视图。
数据工程是商业智能的发展
另一个用来描述上述概念的术语是 BI 或“商业智能”。
商业智能是大型国际公司的领域。很久以前,只有他们有钱存储大量数据,也有足够的经济实力这么做。巨大的 SQL 服务器在由巨大的存储区域网络(SAN)支持的大型企业主机上飞速运转。数据将从纽约、洛杉矶、伦敦、香港和新加坡的系统中被转储进来,因为每个人都去睡觉了,以便在第二天早上之前进行处理。分析师会使用 PowerBI 和 Crystal Reports 等成熟供应商提供的昂贵工具来分析数据。
但是,如果“商业智能”这个术语如此成熟,为什么会出现重复的术语呢?简短的回答是互联网。
随着互联网的兴起,出现了许多使用和收集数据的新应用。对于其中的一些应用程序,数据量对于任何一台数据库服务器来说都太大了。它们被称为 webscale 应用。与此同时,存储数据的价格呈指数级下降(已经下降了一段时间)。然后在 2002 年,塞斯·吉尔伯特和南希·林奇发表了一份现在被称为上限定理的正式证明。

资料来源:Khazaei、Hamzeh & Fokaefs、Marios & Zareian、Saeed & Beigi、Nasim & Ramprasad、Brian & Shtern、Mark & Gaikwad、Purwa & Litoiu、Marin。(2015).我如何选择合适的 NoSQL 解决方案?全面的理论和实验调查。大数据和信息分析杂志(BDIA)。2.10.3934/bdia
它指出,当您跨多个服务器对数据进行分区时,在数据立即可用和跨这些分区获得一致之间存在不可避免的权衡。为了利用这些新的 webscale 机会,需要新的工具。由此开始了 大数据 的时代。
大数据工程师的崛起
最初的成功是像谷歌的大桌子这样的科技巨头的内部解决方案;但很快,开源解决方案如 Memcached(2003)、CouchDB(2005)和 Hadoop(2006)充斥了这个领域。第二波浪潮在 2008-2009 年出现,出现了 No-SQL 数据库,如 HBase、Cassandra、Redis、Riak 和 MongoDB。销售硬件和服务来支持这些开源软件,对于像 Datastax 和 Hortonworks 这样的公司来说,过去和现在都是有利可图的。
那么,你如何称呼为大数据问题设计解决方案的人呢?当然,你称他们为“大数据工程师”。
数据工程和大数据的相对衰落

英国大数据工程师的职位空缺趋势来源: IT 职位观察 (CC BY-NC-SA 4.0)
随着这么多人用“大数据”赚了这么多钱,它变得不仅仅是值得讨论的了。宣传列车开足马力,所有人都上车了。许多销售“大数据”的公司没有 webscale 数据。其他更便宜的解决方案会更好地服务于一些客户——回避这个问题,“大数据到底有多大”?

来源:谷歌趋势,大数据,美国 2004–2020
冷静的头脑现在将这些工具视为工具箱的一部分,并明智地使用它们。将“大”从“大数据工程师”中去掉,重新关注寻找正确的解决方案。这也更符合“数据科学家”这个术语——我从未听到有人自称为“大数据科学家”。
数据工程师 Vs 数据科学家
有些人喜欢狗。还有人爱猫。许多人两样都喜欢。
所有的数据工程师都会做一些分析。所有的数据科学家都会做一些编程。有的人两者兼而有之;他们进行复杂的分析和编写生产质量的软件。再看一下就业统计数据,差异就很明显了。

技能在招聘广告中出现的频率,数据来源: IT 职位观察 (CC BY-NC-SA 4.0)
数据科学家被期望精通机器学习和统计学,但不是敏捷软件工程师。他们应该知道 SQL,但不是数据库专家(因此没有 ETL 或数据仓库)。
数据工程仍在发展
随着技术的发展和我们面临的挑战的变化,这些术语将继续变化。这个行业的乐趣在于它是动态的。总有新的东西要学。
让我们保持联系。你可以在data unboundTwitterLinkedIn找到我。感谢阅读。**
数据工程师不仅仅是技术专家
为什么数据工程师不仅仅是某项特定技术的专家
数据工程师通常被描述为所有数据角色中的“专注于技术/技术专家”角色。然而,如果这是真的,那么一个数据工程师应该专注于什么技术呢?这个角色是如何在技术的发展中存活下来的?
嗯,我认为这并不简单,这个角色不仅仅是“专注于技术”,这个角色的一些核心方面随着时间的推移保持不变,即使技术不再存在。
不同的技术
数据工程可能涉及不同的技术取决于你工作的公司/团队,范围可能相当大: Spark , Apache Beam , Step functions , Airflow , Google Dataprep , Kafka , Hive , Python , Java ,
出于演示的目的,我将从 Linkedin Jobs 获取两个标题为亚马逊数据工程师的职位,我将用黄色强调需要的技术。
- 亚马逊英国公司的数据工程师
 

- Spotify 的一名数据工程师
 

如果我继续举更多的例子,我可能会填充数据& AI 景观

正如你所猜测的,没有人,没有数据工程师可以在他的简历中包含所有这些技术。即使某人的简历上有其中的三分之一,你会认为他是所有这些方面的专家吗?而如果他不是所有这些技术的专家,又怎么可能专注于技术呢?
不同技术之间有一些共享的核心软件工程方面,可以帮助从一种技术转换到另一种技术。
例如,airflow 和 spark 可以用同一种语言 python 编写,尽管它们的目的不同:spark 用于数据处理,airflow 用于工作流管理。
另一个基于语言的例子是在 Hive、 Presto 、 Athena 、Postgres、 InfluxDB 、 Impala 、 BigQuery 和 SparkSQL …
技术不仅共享语言,还共享核心概念,例如:
- 数据建模技术:分区、索引…
 - 数据争论方法:过滤、清理、正则表达式...
 - 优化技术,如执行计划
 - 设计模式: python 和 java 设计模式,数据处理模式
 - 批量数据处理的范例
 
语言/框架/技术之间的共同联系有助于工程师转向更新、更有效的技术。这就像使用 android 手机一样,如果你学会了如何使用 android 手机,你就会很容易知道如何使用 iPhone。
技术、术语和产品生命周期

来源:丹尼尔·弗雷斯·派克斯
技术,就像任何其他商业产品一样,会出现,直到更好的出现,然后,如果没有创新出现,它们就会慢慢消失。
在数据处理领域,如果我们查找 2010 年至 2014 年用于数据处理的技术,我们会看到大多数平台/ERP,如 SAP 或 Oracle。
如今,数据处理更多地是通过 spark、hive、kafka 和其他运行在 AWS 或 Google 等平台上的“大数据”技术来完成的。这些技术允许我们像以前一样处理数据,但让我们更加灵活,以更低的成本处理更多的数据,实时处理数据,点击一下就可以进行机器学习, A/B 测试等等。
用于处理和分析数据的人的数据角色或术语也遵循相同的“生命周期”:如果我们之前谈论 ETL 开发人员或数据集成专家,我们现在谈论的是数据工程师。
这个“以技术为中心”的角色发生了什么变化?工具改变了,它们进化了,它们遵循了技术生命周期,但是这个角色的核心方面仍然存在。作为数据工程师的 ETL 开发人员必须处理数据,对数据处理管道进行质量检查,提取数据并使其可用于其他平台。就编码语言而言,是的,数据工程师必须知道至少一种编程语言,但他还必须对 SQL 有深入的了解。
笑点是
随着人类能够处理的数据处理工具越来越多,技术的不断发展,数据工程师仍然被认为是“以技术为中心”的。当然,数据工程师必须使用技术来完成事情,但他使用技术并不只是为了好玩,他使用技术来收集、存储和处理某个 用例 的数据,以一种 工业化的方式 。
用例、数据量及其速度、数据收集频率和数据交付方法将帮助您定义所使用的技术。例如,实时可视化不能基于 Hive 表,其他数据库和数据处理框架适合这种用例。
工业化的方式意味着数据工程师通常不负责特别分析,但是他参与为特别分析负责人创建/建立一个平台。
最后但同样重要的是,处理数据是为一个特定用例完成的。因此,如果您想避免树摇摆案例,数据工程师必须了解业务需求。

来源:树摇摆迷因的简短修改版
熊猫数据探索 101
Pandas 是访问和使用数据的最强大的图书馆之一。有大量的功能涵盖数据操作,快速绘图以及读取和写入数据。
如果你是数据科学的新手,一个考试前时间不多的学生,或者你只是想看看其他人如何使用熊猫来探索和分析 数据,请跟随我。对于这个快速介绍,我们将使用通过 Kaggle.com获得的主要城市的每日气温数据集。
作为每个数据探索任务的起点,导入数据集是必要的。Python 通过“open()”函数使这变得非常容易,然而不管怎样,因为我们要使用 pandas 库,传统的开放不是办法。Pandas 提供了各种各样的 read_ 函数,允许同时打开文件并将其转换成数据帧。
输入数据
只用两行代码,您就可以导入数据并创建一个 dataframe 对象,这个对象非常适合使用。除了常见的 Python 数据结构(比如字典),操作可以在所有数据点上执行,也可以在经过过滤甚至分组的数据点上执行。想象一下,你必须只用普通的数据结构来完成这项任务,这将是一场噩梦。

不要错过任何关于熊猫的数据细节
Pandas 为您提供了令人难以置信的方便和易于应用的预览、修改和导出数据的可能性。在接下来的几行中,我们将通过几个非常有用的例子来操作数据帧。您可能会观察到, pandas 相当一致(过滤、访问行等。)和其他著名的 Python 库,还有像 r。
描述数据
几乎每次分析新数据集时,您都可能会考虑两件事:
- 您的数据点位于什么范围内——这对于获得数据的“感觉”以及检查一致性、可靠性和异常值至关重要
 - 您是否在数据框架中看到无效或缺失的值
 
仅使用这些 to 行将允许您检查您的数据集并估计您是否需要做更多的数据清理。明确描述()对月、日或年没有意义,但掌握 AvgTemperature 是必不可少的。正如我们在这里看到的,这个度量很可能不是摄氏度(平均温度是 56 度),而是华氏度。
 Month        Day          Year          AvgTemperature
count 2.906327e+06 2.906327e+06 2.906327e+06  2.906327e+06
mean  6.469163e+00 1.571682e+01 2.006624e+03  5.600492e+01
std   3.456489e+00 8.800534e+00 2.338226e+01  3.212359e+01
min   1.000000e+00 0.000000e+00 2.000000e+02 -9.900000e+01
25%   3.000000e+00 8.000000e+00 2.001000e+03  4.580000e+01
50%   6.000000e+00 1.600000e+01 2.007000e+03  6.250000e+01
75%   9.000000e+00 2.300000e+01 2.013000e+03  7.550000e+01
max   1.200000e+01 3.100000e+01 2.020000e+03  1.100000e+02
有时,有些用例要求数据提取可以很容易地复制和插入,我推荐使用 to_markdown() 函数,它为此提供了很好的结果——确实是我的最爱之一。
|         | Country   |   AvgTemperature |
|--------:|:----------|-----------------:|
| 2906322 | US        |             28   |
| 2906323 | US        |             27.6 |
| 2906324 | US        |             29   |
| 2906325 | US        |             28.8 |
| 2906326 | US        |             28.7 |
我们需要进一步检查是否有“非数字”值。如我们所见,只有 State 有缺失字段,这对我们来说完全没问题。请记住,对于机器学习等更复杂的任务,删除以及内插或外推丢失的数据可能是数据科学家的一项关键工作。
Region            False
Country           False
State              True
City              False
Month             False
Day               False
Year              False
AvgTemperature    False
dtype: bool
为了获得一列的唯一值, unique() 函数非常有用——我们也可以在分组对象上使用它。
data.Region.unique()array(['Africa', 'Asia', 'Australia/South Pacific', 'Europe',
       'Middle East', 'North America',
       'South/Central America & Carribean'], dtype=object)
当数据被图解或总结时,你可能会对数据有更好的感觉。如果您的数据是数字,您可能会发现散点图或箱线图非常方便。

箱线图中的平均温度。包括异常值。
旁白:有许多不同的库允许以非常漂亮和快速的方式绘制数据。从个人的角度来看,没有可视化的数据探索通常是困难的,而且要花费更多的时间,因为数据的不规则性可能会在过程的后期被发现。
这是另一个直观的例子,它能让你立即感受到异常值,一个结合了数字和分类变量的非常密集的散点图:

修改数据
正如我们在最初创建的描述表中看到的,温度以华氏温度为单位,对于非美国居民来说,处理数据可能会有点困难,尤其是当涉及到“这里似乎有什么不对劲”这一部分时。
Pandas 允许我们以一种非常简单直接的方式在列上执行操作。
更通用的方法是对列应用函数。结果和上面一样,但是,我们可以通过这种方式更有创造性地应用函数。
Apply( ) 允许用户创建复杂的函数,并将它们应用到一列甚至几列上。还要注意,除了定义一个函数(如我们的 to_celsius 函数), lambda 表达式也可以很容易地使用——这可能是只使用一次时最有用的。
如果您更频繁地面对复杂的修改任务,您可能希望构建能够通过正则表达式解析单元格值的函数。在这种情况下,你可能想把正则表达式和 pandas 的应用函数结合起来。如果您觉得需要复习一下数据科学的正则表达式,可以看看下面的链接:
可以使用正则表达式的用例非常多。不管你是不是数据科学家收藏…
towardsdatascience.com](/mastering-regular-expressions-for-your-day-to-day-tasks-b01385aeea56)
分组数据— groupby()
当数据被分组在一起时,Pandas 创建一个 groupby 对象。有很多函数可以应用到一个分组的对象上,比如 unique()、mean()、min()或 max()——仅举几个例子。请注意,您不能直接“显示”groupby 对象,因为这将导致如下输出:
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x000001F2B6879CD0>
为了获得平均值,下面这条线将有所帮助:
data.groupby([‘Region’,’Country’,’State’,’City’,’Year’]).mean()

显示平均值的重新编制索引的分组对象
同样,平均值对于月或日没有任何意义,因此省略这些列是有用的。还请注意,上表需要重置索引,以便正确显示每行条目。

更干净的输出
过滤数据
通常,您可能只对给定数据的一小部分感兴趣。为此,可以通过简单的过滤操作将数据帧最小化为较小的数据帧:
vienna = data[data['City']=='Vienna'].copy() # great city
数据帧的创建副本将只包含“城市”为“维也纳”的值。如果我们需要额外的过滤要求,pandas 允许通过“与”或“管道”来连接标准。
一般来说,我们可以使用主数据框架来绘制相关信息,但是我更喜欢在较小的数据集上使用简单的绘制操作。plot 函数中的过滤数据使其难以阅读和理解。当我们看下面几行代码时,使用数据帧的专用副本的优势变得非常明显:
只需 3 行代码,我们就能生成一个包含线性趋势的折线图:

1995 年至 2020 年维也纳平均气温的简单线形图
如果我们计算一下我们在这里使用的代码行数和我们用这些代码进行的数据操作次数,毫无疑问 Pandas 是一个非常强大的数据操作工具,不需要大量的文档阅读和实践。
有用的文档
如果您想更好地理解我们在本文中所涉及的内容,我建议您从下面的文档开始,仔细阅读与您相关的细节。请记住,就像每一项学习任务一样,做比(仅仅)阅读要好。
[## 熊猫。数据框架- pandas 1.0.5 文档
数据结构还包含带标签的轴(行和列)。算术运算在行和列上都对齐…
pandas.pydata.org](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) [## Pyplot 教程- Matplotlib 3.2.2 文档
pyplot 接口介绍。是一个命令风格函数的集合,它使 matplotlib 像…
matplotlib.org](https://matplotlib.org/tutorials/introductory/pyplot.html) [## NumPy 滤波器阵列
从现有数组中取出一些元素,然后用它们创建一个新数组,这叫做过滤。在 NumPy,你…
www.w3schools.com](https://www.w3schools.com/python/numpy_array_filter.asp)
一如既往,下次再见,注意安全!
图片由古斯塔夫·古尔斯特兰德提供,谢谢!
使用 Python 进行数据探索和分析
让您的数据说话的简单方法
数据探索是数据分析和模型构建的一个关键方面。如果不花大量时间去理解数据及其模式,就无法构建高效的预测模型。在由数据清理和预处理组成的数据科学项目中,数据探索占据了大部分时间。
在本文中,我将通过简单的解释和 Python 代码片段来解释数据探索中涉及的各个步骤。数据探索中涉及的关键步骤有:
加载数据
识别变量
变量分析
处理缺失值
处理离群值
特征工程
加载数据并识别变量:
数据来源可能因数据库和网站而异。数据源被称为原始数据。原始数据不能直接用于建模,因为它不一致,不适合预测。必须对异常和缺失值进行处理。变量可以是不同的类型,如字符、数字、分类和连续。

可变类型
确定预测值和目标变量也是建立模型的关键步骤。 Target 是因变量,predictor 是独立变量,基于该变量进行预测。分类变量或离散变量是那些无法用数学方法处理的变量。它由 0 和 1 等固定值组成。另一方面,连续变量可以用数学函数来解释,比如求所有值的平均值或总和。您可以使用一系列 Python 代码来理解数据集中的变量类型。
**#Import required libraries**
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns**#Load the data**
titan=pd.read_csv("../input/titan.csv")**#get an overview of the data**
titan.head()
titan.tail()
titan.sample(10)
**#identify variable type**
titan.dtypes
titan.info()
titan.describe()
变量分析:
变量分析有三种方式,单变量分析,双变量分析,多变量分析。

变量分析
单变量分析用于突出缺失值和异常值。这里对每个变量的范围和分布进行单独分析。分类变量和连续变量的单变量分析不同。对于分类变量,您可以使用频率表来了解每个类别的分布情况。对于连续变量,你必须了解变量的中心趋势和扩散。可以用均值、中值、众数等来衡量。它可以使用箱线图或直方图来可视化。
**#Understand various summary statistics of the data**
include =['object', 'float', 'int'] 
titan.describe(include=include)
titan.describe()**#Get count of values in a categorical variable**
titan.survived.value_counts()titan.age.hist(figsize=(10,5))

柱状图
双变量分析用于找出两个变量之间的关系。可以对分类变量和连续变量的组合进行分析。散点图适合分析两个连续变量。表示变量之间的线性或非线性关系。条形图有助于理解两个分类变量之间的关系。某些统计测试也用于有效理解双变量关系。Scipy 库有大量的模块可以在 Python 中执行这些测试。

双变量分析
Matplotlib 和 Seaborn 库可用于绘制不同的关系图,帮助可视化不同类型变量之间的二元关系。

散点图
**iris = sns.load_dataset("iris")**
sns.relplot(x = 'sepal_length', y = 'petal_length', hue='species',data = iris)relplot = sns.catplot(x="pclass", hue="who", col="survived",  
      data=titan, kind="count",  
    height=4, aspect=.7);  
relplot
处理缺失值:
数据集中缺少的值会降低模型拟合度。由于无法对数据进行全面分析,这可能会导致模型出现偏差。行为以及与其他变量的关系无法正确推导。它会导致错误的预测或分类。缺失值可能是由于数据提取或数据收集中的问题造成的,这些问题可分为 MCAR、马尔和 NMAR。

缺少值
缺失值可以通过删除、均值/众数/中位数插补、KNN 插补或使用预测模型来处理。

处理缺失值
您可以使用 Python 中名为 Missingno 的库直观地分析缺失的数据。
import missingno as msno
msno.bar(titan)
msno.heatmap(titan)np.mean(titan['age'])from scipy import stats
stats.mode(titan['embarked'])titancopy['age'].fillna(29,inplace=True)
titancopy['embarked'].fillna("S", inplace=True)
处理异常值:
异常值可能自然出现在数据中,也可能是由于数据输入错误造成的。它们可以彻底改变数据分析和统计建模的结果。异常值很容易通过可视化方法检测,如箱线图、直方图和散点图。异常值的处理类似于缺失值,通过删除观察值、转换观察值、宁滨或分组观察值、将其视为单独的组或输入值。

箱形图
import plotly.express as px
fig = px.box(titan,x='survived',y='age', color='pclass')
fig.show()px.box(titan, y='age')px.box(titan,x='survived',y='fare', color='pclass')*#Adding trendline to the data*
x=iris.sepal_length
y=iris.petal_width
plt.scatter(x, y)
z = np.polyfit(x, y, 1)
p = np.poly1d(z)
plt.plot(x,p(x),"y--")
plt.show()
特征工程:
特征工程是从现有数据中提取更多信息的过程。特征选择也可以是它的一部分。特征工程的两种常用技术是变量转换和变量创建。在变量转换中,使用特定函数转换现有变量。例如,一个数可以用它的对数值来代替。另一种技术是从现有变量创建一个新变量。例如,将 dd/mm/yy 格式的日期字段拆分为日期、月份和年份列。

变量变换
titancopy = titan.copy()**#variable transformation**
titancopy['alive'].replace({'no':0,'yes':1}, inplace=True)**#Convert boolean to integer**
titancopy["alone"]=titancopy["alone"].astype(int)
另外两种数据转换技术是对分类变量进行编码和对连续变量进行缩放以使数据标准化。这取决于用于评估的模型,因为有些模型接受分类变量。
不相关的特征会降低模型的准确性。可以自动或手动选择功能。相关矩阵用于可视化特征之间的相互关系或与目标变量的关系。

相关矩阵
titancopy.corr()plt.figure(figsize=(10,10))
corr = titan.corr()
ax = sns.heatmap(
    corr, 
    vmin=-1, vmax=1, center=0,
    cmap=sns.diverging_palette(20, 220, n=200),
    square=True, annot=True
)
ax.set_xticklabels(
    ax.get_xticklabels(),
    rotation=45,
    horizontalalignment='right'
)
ax.set_yticklabels(
    ax.get_yticklabels(),
    rotation=45,
);
scikit-learn 库提供了一些好的类,比如 SelectBest,用于从给定的数据集中选择特定数量的特征。同一库中的基于树的分类器可用于获得特征重要性分数。
这涵盖了数据探索中涉及的一些关键步骤。根据数据的大小和模型的要求,每个步骤都可以重复。数据科学家在数据预处理上花费的时间最多,因为数据质量直接影响模型的成功。
这里显示的所有代码片段都在探索性数据分析和可视化 Kaggle 笔记本中执行。
利物浦足球俱乐部 2019–2020 EPL 赛季的数据探索
确定“运气”并使用“预期”指标

肖恩·唐纳利在 Unsplash 上的照片
受到 Soner Yildirim 的文章(链接)的启发,他谈到了 EPL 2019-2020 赛季的一些探索性数据分析,我想看看我是否能收集到任何专门针对利物浦的见解。毕竟这是他们赢得冠军的赛季!
我用了他从 kaggle 那里得到的同样的数据集。
2019-2020 赛季所有英超联赛的球队和球员统计数据
www.kaggle.com](https://www.kaggle.com/idoyo92/epl-stats-20192020)
当我浏览数据集时,我脑海中有一个问题——利物浦真的赢得了胜利吗?有量化的证据来支持或反驳利物浦这个赛季只是运气好的说法吗?
准备环境
最初的比特相对简单。我使用 Jupyter 笔记本作为我的主要分析环境,并导入了常用的工具(numpy,pandas)。然后,像 Sonor 一样,我从 kaggle 下载了 csv 文件,并将其读入 dataframe。
import numpy as np
import pandas as pd
df_epl = pd.read_csv(“epl2020.csv”)
df_epl = df_epl.reset_index(drop=True)
df_epl.drop([‘Unnamed: 0’], axis=1)
结果是这样的:

576 行和 44 列的数据。从一个团队的角度来看,每一行都代表一场特定比赛的数据。这意味着每场比赛实际上都是两行数据,而不是一行。使用该数据集时需要记住的一些事情。
关键指标
在浏览数据集时,我决定关注 6 个特定的列——进球、失球、预期进球、预期失球、得分和预期得分。
围绕“预期”指标的一些解释可能是必要的。
- 预期进球得分—Opta(EPL 官方统计追踪器)根据几个变量(助攻类型、射门角度、距离球门的距离等)来衡量一场比赛中一个球队特定射门的质量。).这给出了“每次射门的预期目标”指标。在一场比赛中,将一个球队的每杆预期进球加起来,我们就得到了每场比赛的预期进球,这是我们数据集中的统计数据。(链接)**
 - 预期失球 —基本上是预期失球的反序。注意,对于一场比赛来说,每支球队的预期进球得分就是对方球队的预期失球。
 - 期望分数 —一个队在一场比赛中应该获得的期望分数。我找到了这个指标的一个合适的解释,但是它基本上是预期目标指标的一个衍生物。
 
预期点数(预期点数、xPts 等。)是预期目标(xG)模型的扩展…给定每支球队在比赛中创造的预期目标值,人们可以取这些值并模拟它数千次,以计算比赛将导致赢/平/输的概率。从这些概率(比赛赔率)中,我们可以将它们转换成一个团队在给定他们和他们的对手累积的 xG 的情况下可以赢得多少分(0 到 3 之间的任何值)
点数减去预期点数
因此,为了尝试回答这个问题——“利物浦幸运吗”,我需要找出一个可能“代表”运气的指标,看看利物浦与同行相比如何。
我的第一个想法是用“点数减去预期点数”。这似乎很合理。如果“分数”是一个团队实际上获得了多少分,而“预期分数”是一个团队认为获得了多少分,那么两者之差将代表一个团队是幸运(正数)还是不幸(负数)。任何一个方向上的大量数据都代表着与“应该”发生的情况的重大偏离。
有了这个想法,我可以开始分析了:
步骤 1:创建一个标签为“点数-预期点数”的列。这反映了团队在每场比赛中低于或超过预期的程度。
第二步:得出每个团队的平均值和总和(即一个团队整个赛季的平均和总“分数减去预期分数”)
**//Step 1
df_epl['pts-xpts'] = df_epl['pts']-df_epl['xpts']//Step 2 - Mean
df_epl[['teamId','pts-xpts']].groupby('teamId').mean().sort_values(by='pts-xpts', ascending=False)//Step 2 - Sum
df_epl[['teamId','pts-xpts']].groupby('teamId').sum().sort_values(by='pts-xpts', ascending=False)**

每个团队的平均值(“pts-xpts”)和总和(“pts-xpts”)的递减比较
如你所见,结果相当惊人。利物浦和下一个最幸运的竞争对手纽卡斯尔之间有着巨大的差距。在整个赛季中,利物浦每场比赛的得分都大大超出了预期。
实际净胜球(每场比赛)减去预期净胜球(每场比赛)
在看了积分-期望积分比较之后,我觉得有必要做更多的工作。毕竟,预期分数看起来仍然是一个相当不透明的指标,因为它是预期目标统计的衍生物。
因此,我决定评估“运气”的下一个基准是“实际净胜球减去预期净胜球”。
背后的想法很简单:
- 一个队在一场比赛中的实际净胜球仅仅是他们进的球和丢的球之差。如果你进的球比失球多,你自然会表现得更好。
 - 考虑到创造的得分机会的数量和质量,一支球队的预期净胜球将是一支球队应该取得的进球和他们应该取得的失球之间的差异。
 - 实际净胜球和预期净胜球之间的差异可能再次指向“运气”因素。像以前一样,一个大的正数将代表一个队在特定比赛中的幸运(正数)或不幸(负数)。
 
清楚了这一点,我们可以开始分析了。
第一步:创建一个标签为“实际目标差异减去预期目标差异”的列。这反映了球队在每场比赛中低于或高于净胜球期望值的程度。
请记住,数据集不会直接给出目标差异和预期目标差异。这些必须从(1)进球数,(2)失球数,(3)预期进球数(xG),(4)预期失球数(xGA)中得出,其方式如下: (进球数-失球数)——(xG-xGA)
步骤 2:得出每个团队的平均值和总和
**//Step 1
df_epl['Expected Goal Difference per Match'] = df_epl['xG']-df_epl['xGA']df_epl['Actual Goal Difference per Match'] = df_epl['scored']-df_epl['missed']df_epl['Actual Goal Diff - Expected Goal Diff'] = df_epl['Actual Goal Difference per Match']- df_epl['Expected Goal Difference per Match']//Step 2
df_epl[['teamId','Actual Goal Diff - Expected Goal Diff']].groupby('teamId').mean().sort_values(by='Actual Goal Diff - Expected Goal Diff', ascending=False)df_epl[['teamId','Actual Goal Diff - Expected Goal Diff']].groupby('teamId').sum().sort_values(by='Actual Goal Diff - Expected Goal Diff', ascending=False)**

每个团队的平均值(“实际目标差异-预期目标差异”)和总和(“实际目标差异-预期目标差异”)的降序比较
这种方法讲述了一个类似于“积分减去预期积分”方法的故事,利物浦在这些积分榜上仍然接近榜首。在整个赛季中,利物浦大大超出了预期的净胜球。
这里的一个特点是莱斯特。我不记得他们有一个特别出色的赛季,那么为什么他们在这个指标上遥遥领先呢?
**leicester_results = df_epl[df_epl['teamId']=='Leicester']leicester_results[['teamId', 'Actual Goal Diff - Expected Goal Diff']]**

莱斯特的每场比赛数据(不完整)
很明显,有一场比赛确实扭曲了数据。这是他们 9 比 0 战胜南安普顿的比赛——英格兰顶级足球历史上最大的客场胜利。这场比赛的“实际进球差异——预期进球差异”高达 5.07。
限制
这些数字无法说明问题。我们为他们说话,我们赋予他们意义。—内特·西尔弗
那么经过这么多的分析之后,我们是否有了利物浦是否“幸运”的答案呢?乍一看,似乎是这样。尽管是莱斯特,利物浦在相关的“运气”指标上领先于竞争对手。
然而,如果我们再深入一点,就可以清楚地看到,这些“运气”指标并不一定反映随机机会。生成的两个基准“分数减去预期分数”和“目标差异减去预期目标差异”都严重依赖于预期进球得分(xG)和预期失球(xGA)统计数据。虽然运气肯定会影响 xG 和 xGA 的偏差,但其他因素也会起作用。
例如,如果一支球队创造了相对较少的高质量机会(低 xG),但成功地打进了大量进球(高实际进球),这可以解释为运气,但也可以解释为一支球队只是拥有转换速度很快的伟大前锋。
反之亦然——如果一支球队给了对手很多高质量的机会(高 xGA ),但实际上并没有失球太多(失球率低),这可能是运气使然,但也可能是一支防守令人难以置信的球队或世界级门将阻止了实际失球。
结论
所以如果数据没有告诉我们利物浦是幸运的,我们能从中得出什么合理的结论呢?
对我来说,分析表明,利物浦在 2019-2020 赛季期间,没有创造出大量“高质量”的机会,也没有独特地扼杀对手。
这似乎与视力测试相一致——当我实际观看利物浦本赛季的比赛时,我记得有很多艰难的胜利。利物浦通过创造大量高质量的机会将对手轰下球场的情况并不常见。
然而,仅仅从数据上来看,很难断定是什么样的运气、精彩的射门或精彩的停球组合让利物浦获得了冠军。
我希望你喜欢这个!请随意发表评论。我也喜欢任何关于我将来可以使用的有趣数据集的建议!
Airbnb 新加坡数据探索:01
用 Python 对 Airbnb 新加坡数据进行探索性数据分析

介绍
嗨!我叫阿格拉,我是一名建筑师,对建筑、城市设计、房地产和技术知识的整合感兴趣。本文是我在使用 python 编程语言学习数据科学的几个星期中,对我的个人数据科学项目的一个总结。
如今,我们生活在一个数据大量产生和流通的时代。这些数据可以收集起来,让我们推断出有意义的结果,并做出明智的决定。然而,随着数据数量的增加,我们需要将数据可视化,以帮助我们进行数据分析。通过使用可视化工具,我们能够向我们的观众传递信息,并告知他们我们的发现。
本文的目的是探索一家技术公司的公开数据集,通过可视化工具清晰地绘制结果,并为公众和其他相关方提供新的见解。为了使每篇文章的主题更加集中,本文将分成一系列的几篇文章。
对于第一篇文章,我们将使用基本的探索性数据分析技术来探索和可视化来自新加坡 Airbnb 的数据集。我们将根据每个 Airbnb 房源的位置找出它们的分布,包括价格范围、房间类型、房源名称和其他相关因素。
什么是探索性数据分析?
我指的是数据科学家 Terence S 对探索性数据分析的解释。简而言之,探索性数据分析(EDA),也称为数据探索,是数据分析过程中的一个步骤,其中使用了多种技术来更好地了解所使用的数据集。
一些技术是:
- 提取重要变量,留下无用变量
 - 识别异常值、缺失值和人为错误
 - 理解数据,最大限度地提高我们对数据集的洞察力,并最大限度地减少流程后期可能出现的潜在错误
 
通过进行 EDA,我们可以将几乎可用或不可用的数据集变成可用的数据集。
探索性数据分析的主要组成部分:
- 获取和加载数据
 - 清洗数据集
 - 探索和可视化数据
 
为什么选择 Airbnb?
自 2008 年以来,客人和主人一直使用 Airbnb 来拓展旅行的可能性,并提供一种更独特、更个性化的体验世界的方式。今天,Airbnb 成为一种被全世界使用和认可的服务。通过 Airbnb 提供的数百万房源的数据分析对该公司来说是一个至关重要的因素。这些数以百万计的列表产生了大量的数据——可以分析的数据。
为什么选择新加坡?
Airbnb 在新加坡有着长期且相当复杂的关系。从五年前开始,新加坡政府就将 Airbnb 提供的短租贴上了非法服务的标签。虽然被贴上了这样的标签,但是到目前为止,只有两个案例发现房东因违反租赁法而被罚款。
此外,在疫情危机冲击全球旅游业之前。Airbnb 在新加坡发展迅速,并在东南亚范围内产生了高度综合的数据。
1.获取和加载数据
对于这个项目,我们使用 jupyter 笔记本 IDE 和 python 编程语言来编写我们的脚本。IDE 或集成开发环境是用于软件开发的软件应用程序。
为了获取数据,我们使用 Airbnb 数据,这些数据是在知识共享许可下在互联网上公开共享的。在我们能够将数据加载到我们的 IDE 之前,首先我们需要导入可视化和分析所需的各种外部库/模块。
a .加载 python 库
- 用于数据分析的熊猫和 Numpy 库
 - 用于数据可视化的 Matplotlib 和 Seaborn 库
 
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
import seaborn as sns
b .加载数据集
为了加载数据集,我们使用 pandas 库和函数从http://insideairbnb.com/读取新加坡 Airbnb 2019–2020 数据集的 CSV 文件,将其转换为 DataFrame 并检查排名前 5 的索引数据。
airbnb = pd.read_csv('listings_sum.csv')
**airbnb.head()**

c .了解数据
在我们加载数据集之后,我们需要通过使用各种技术来理解数据集。首先,我们需要寻找关于我们的数据集有多大的信息。通过使用 shape 属性,我们从包含列表索引的若干行和包含与该索引相关的每个特征的内容的若干列中了解我们的数据大小。
airbnb.shape

(行数、列数)
然后我们检查每一列的所有数据类型,如果它已经符合我们的要求。例如,我们需要经度和纬度上的数字数据类型(整数和浮点),为了列出名称,我们需要确保数据使用的是字符串/对象数据类型。
airbnb.dtypes

数据类型信息
我们发现我们的数据集有 7395 个列表。这些特性包括列表名称、主机 id、位置信息、位置坐标、房间类型、每晚价格等等。
接下来,我们查找由所有新加坡地区列表组成的“neighbourhood _ group”的所有唯一值
airbnb['neighbourhood_group'].unique()


区域地图
从上面的列表中,我们看到新加坡有 5 个区域。
城市重建局(URA)将该地区进一步划分为 55 个区域,称为城市规划区。我们将使用“邻居”列来查看哪个规划区域有 Airbnb 列表。
airbnb['neighbourhood'].unique()

邻近

规划区地图
现在,我们知道有 43 个规划区有 Airbnb 房源。
我们还查找列表中每个房间类型的“房间类型”列
airbnb['room_type'].unique()

房间类型
从上面的列表中,我们看到 Airbnb 有 4 种房型。根据 Airbnb 网站上的信息,每种房间类型的定义如下:
- 包间
 
客人可以单独进入酒店的卧室/睡眠区。其他区域如客厅、厨房和浴室也可能对主人开放,甚至对其他客人开放。
- 整个家/公寓
 
客人们可以独享整个地方。它通常包括卧室、浴室和厨房。
- 共享房间
 
游客睡在卧室或可以与他人共享的公共区域。
- 酒店房间
 
典型的酒店房间及其设施。自 2018 年以来,Airbnb 允许一些精品酒店和高评级独立酒店在其网站上列出他们的房间。
2.清洗数据集
下一步是清理数据,我们加载的数据经常会有各种各样的错误,比如打字错误、缺少值、数据不完整等等。通过清理,数据质量将有更好的质量用于进一步的分析。
a .检查缺少值的列
让我们首先检查我们的数据集中是否有任何丢失的值
**airbnb.isnull().sum()**

b .删除冗余变量
在我们的例子中,观察到的缺失值不需要过多的处理。查看我们的数据集,我们可以声明列“name”和“host_name”,“last_review”对于进一步的数据探索分析是不相关和不道德的。因此,我们可以去掉那些列。
airbnb.drop(['id','host_name','last_review'],axis=1,inplace=True)
**airbnb.head()**

c .替换所有缺失值
接下来,我们需要用 0(零)替换“review_per_month”列中所有缺失的值,以确保缺失的值不会干扰我们的分析
airbnb['reviews_per_month'].fillna(0,inplace=True)
3.探索和可视化数据
清理完数据后,下一步是通过可视化和分析要素值来探索数据,解释过程和结果。
对于我们的例子,我们将查找由每个最大值组成的各种列表类别,使用地图可视化列表分布,为每个区域创建房间类型比例,从列表名称中查找销售值,并找到最受欢迎的列表的平均价格。
a .热门列表计数
首先,我们跳过“名称”的第一列,从“主机 id”列开始。然后,我们根据列表计数对前 10 个主机进行切片
top_host_id = airbnb['host_id'].value_counts().head(10)
接下来,我们设置图形大小,并使用条形图为数据可视化绘图进行设置
sns.set(rc={'figure.figsize':(10,8)})viz_bar = top_host_id.plot(kind='bar')
viz_bar.set_title('Hosts with the most listings in Singapore')
viz_bar.set_xlabel('Host IDs')
viz_bar.set_ylabel('Count of listings')
viz_bar.set_xticklabels(viz_bar.get_xticklabels(), rotation=45)

从上面的图表中,我们可以看到前 10 名主机的总数几乎是整个数据集(7395 个列表)的 20%( 1416 个列表)。甚至其中一个主机有 350 多个房源!
b .顶部区域面积
接下来,我们使用“neighbourhood _ group”列来可视化每个区域中列表计数的比例
labels = airbnb.neighbourhood_group.value_counts().index
colors = ['#008fd5','#fc4f30','#e5ae38','#6d904f','#8b8b8b']
explode = (0.1,0,0,0,0)shape = airbnb.neighbourhood_group.value_counts().valuesplt.figure(figsize=(12,12))
plt.pie(shape, explode = explode, labels=shape, colors= colors, autopct = '%1.1f%%', startangle=90)
plt.legend(labels)
plt.title('Neighbourhood Group')
**plt.show()**

从上面的图表中,我们可以看到中心区域拥有最多的房源,有近 6000 个房源,占全部房源的 80%以上。
c .顶级规划领域
接下来,我们查找列表数量最多的前 10 个规划区域
airbnb.neighbourhood.value_counts().head(10)

我们可以看到, Kallang 的列表数最高。我们还发现前 10 个规划区中有 9 个位于中部地区,Bedok 位于东部地区是个例外。
d .列表图
为了创建列表位置的地图,我们将使用“经度”和“纬度”列。但是首先,我们需要检查列中的值
coord = airbnb.loc[:,['longitude','latitude']]
**coord.describe()**

从上面的数据中,我们可以看到最小和最大指标的经度和纬度的外值。
接下来,我们可视化每个列表的散点图,并根据每个不同区域的颜色对其进行分组
plt.figure(figsize=(18,12))
plt.style.use('fivethirtyeight')BBox = (103.5935, 104.0625, 1.1775, 1.5050)sg_map = plt.imread('map_bnw.png')
plt.imshow(sg_map,zorder=0,extent=BBox)
ax = plt.gca()groups = airbnb.groupby('neighbourhood_group')
for name,group in groups :
    plt.scatter(group['longitude'],group['latitude'],label=name,alpha=0.5, edgecolors='k')plt.xlabel('Longitude')
plt.ylabel('Latitude')
plt.legend()

列表映射
现在我们可以看到列表是如何被绘制到地图中的。为了更好地理解列表密度,我们可以使用 follow 热图
**import folium
from folium.plugins import HeatMap**map_folium = folium.Map([1.35255,103.82580],zoom_start=11.4)HeatMap(airbnb[['latitude','longitude']].dropna(),radius=8,gradient={0.2:'blue',0.4:'purple',0.6:'orange',1.0:'red'}).add_to(map_folium)
display(map_folium)

列表密度图
从上面的地图中,我们可以清楚地看到最密集的列表所在的位置,在中央区域的南部区域用红色显示。离中心区域越远,上市密度越低。
e .价格图
在我们可视化价格图之前,我们需要通过移除一些异常数据来更新数据集,因为一些数据价格的值远离 IQR(四分位数范围)。
airbnb_1 = airbnb[airbnb.price < 300]
接下来,我们使用价格热图中的经度和纬度点来可视化每个列表的散点图和价格范围的差异。
plt.figure(figsize=(18,12))sg_map = plt.imread('map_bnw.png')
plt.imshow(sg_map,zorder=0,extent=BBox)
ax = plt.gca()airbnb_1.plot(kind='scatter',x='longitude',y='latitude',label='Listing Location', c='price', ax=ax, cmap=plt.get_cmap('jet'), colorbar=True, alpha=0.4, zorder=5)**plt.legend()
plt.show()**

列表价格图
从上面的地图中,我们观察到价格朝着中心区域的中心部分相对上升,因为该区域是新加坡的 CCR 区域。

从房地产的角度来看,URA 将新加坡分为三个主要区域,他们称之为“细分市场”。核心中心区(CCR),用黄色表示,是中心区的主要区域,在这里可以找到大多数高端和豪华的物业。中部地区(RCR)其余部分的红色被视为位于外部中部地区(OCR)的大众市场公寓和 CCR 中的高价值物业之间的中间层市场。最后一个是 OCR,由灰色表示,覆盖了新加坡四分之三的面积,基本上是低端大众市场公寓所在的区域。
通过查看上面的两张地图,我们可以认为 Airbnb 的挂牌价格与房地产细分市场有关。但要得出这样的结论,我们需要更多的数据来做进一步的分析。
f .价格分布
根据我们对价格热图的观察,我们需要使用一个方框图来显示价格分布,以便更好地了解按“neighborhood _ group”/region 区域分组的标价范围。
plt.style.use('fivethirtyeight')
plt.figure(figsize=(14,12))
sns.boxplot(y='price',x='neighbourhood_group',data = airbnb_1)
plt.title('Neighbourhood Group Price Distribution < S$ 300')
**plt.show()**

从上面的数据中,我们看到中部地区每晚的价格最贵,中位数为130新元。
g .顶级列表词
接下来,我们将通过找出清单名称中最常用的词来更深入地探索属性细节。最常用的词可以代表他们的财产对潜在客人的销售价值。首先,我们将创建一个收集单词的函数。
**#Crete empty list where we are going to put the name strings**
names=[]**#Getting name string from 'name' column and appending it to the empty list**
for name in airbnb.name:
    names.append(name)**#Setting a function to split name strings into seperate words**
def split_name(name):
    s = str(name).split()
    return s**#Create empty list where we are going to count the words**
names_count = []**#Getting name string to appending it to the names_count list**
for n in names:
    for word in split_name(n):
        word = word.lower()
        names_count.append(word)
我们需要导入计数器库来计数并生成包含主机使用的前 25 个字的原始数据
**from collections import Counter**top_25 = Counter(names_count).most_common()
top_25 = top_25[:25]
然后,我们将数据转换成数据帧,并将我们的发现可视化
word_count_data = pd.DataFrame(top_25)
word_count_data.rename(columns={0:'Words',1:'Counts'},inplace=True)viz_count = sns.barplot(x='Words',y='Counts', data = word_count_data)
viz_count.set_title('Top 25 used words for listing names')
viz_count.set_ylabel('Count of words')
viz_count.set_xlabel('Words')
viz_count.set_xticklabels(viz_count.get_xticklabels(),rotation = 90)

列出姓名时最常用的 25 个单词
从上面的图表中,我们看到了列表名称中使用的前 25 个单词。我们可以用文字云可视化的方法来帮助我们更好地理解图表。
**from wordcloud import WordCloud, ImageColorGenerator**text = ' '.join(str(n).lower() for n in airbnb.name)**#Generate wordcloud image**
wordcloud = WordCloud(max_words=200, background_color = 'white').generate(text)
plt.figure(figsize=(25,20))**#Display the image**
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis('off')
plt.show()

正如我们所看到的,大多数列表销售价值与公共设施(如 mrt 和活动中心)的邻近度或连接度有关,通过“MRT”、“near”、“to”、“city”、“walk to”关键字显示。有趣的是,看到房间条件如何落后于这些值,在图表的较低等级上显示为“宽敞”、“舒适”、“惬意”。
h .房型详情
接下来,我们将使用 Plotly API 图形可视化库来可视化每个地区的所有房型比例
**import plotly.offline as pyo
import plotly.graph_objs as go****#Setting up the color pallete**
color_dict = {'Private room': '#cc5a49', 'Entire home/apt' : '#4586ac', 'Shared room' : '#21908d', 'Hotel room' : '#C0C0C0' }**#Group the room type using 'neighbourhood_group' as an index**
airbnb_types=airbnb.groupby(['neighbourhood_group', 'room_type']).size()**#Create function to plot room type proportion on all region area**for region in airbnb.neighbourhood_group.unique():
    plt.figure(figsize=(24,12))
    airbnb_reg=airbnb_types[region]
    labels = airbnb_reg.index
    sizes = airbnb_reg.values
    colors = [color_dict[x] for x in labels]
    plot_num = 321
    plt.subplot(plot_num)
    reg_ch = go.Figure(data = [go.Pie(labels = labels, values = sizes, hole = 0.6)])
    reg_ch.update_traces(title = reg, marker=dict(colors=colors))
    reg_ch.show()
    plot_num += 1

房间类型
我们可以看到,中心区域是唯一由整个住宅/公寓类型主导的区域,其余区域由私人房间类型主导。总体而言,酒店类型是每个地区上最少的房源,因为 Airbnb 在 2018 年才开始接受酒店房源。
一.最受关注的 10 个名单
我们将根据评论数量找出前 10 名的房源,以了解新加坡最受欢迎的 Airbnb 房源。
airbnb.nlargest(10, 'number_of_reviews')

瞧啊。这是 10 个最受欢迎的列表。同样,我们发现大多数最受关注的列表位于中部地区,10 个列表中有 7 个位于中部地区。
j .每晚平均价格
最后,我们将计算 10 个最受欢迎的房源每晚的平均价格
price_avg = top_review.price.mean()
print('Average price per night: S$ {}'.format(price_avg))

从这个输出中,我们可以观察到Airbnb Singapore 上最受欢迎的前 10 个房源的平均价格为 99.9 新元,大多数房源的价格都低于 90 新元,其中 6/10 是“私人房间”类型,热门评论房源总共有 3111 条评论。
结论
简单地通过对数据集执行 EDA,我们已经识别出关于 Airbnb 房源如何在新加坡分布的各种新见解,我们知道房源位于哪里,发现中心区域支配着房源数量并具有最高的价格范围,房源价格可能如何与周围的房地产价格相关,并发现房源与其周围的连接性成为共同的销售价值之一。
在下一篇文章中,我们将使用更详细的版本来探索数据集。我们将重点关注中心区域,以了解更深层次的背景,了解该区域每个房源之间的关系,以及它们与外部变量的关系,例如与公共设施的连接,以及房地产价格对房源租赁价格的影响。
感谢您的阅读!请随时给予任何反馈!
参考:
- https://towards data science . com/an-extensive-guide-to-explorative-data-analysis-DDD 99 a 03199 e
 - https://www . channelnewsasia . com/news/business/Airbnb-records-30-第一季度预订增长率-11817260
 - https://www . property guru . com . SG/property-guides/CCR-ocr-rcr-region-Singapore-ura-map-21045
 - https://www . Airbnb . com/help/article/5/the room-type-of-a-listing-是什么意思
 
数据探索,简化。
厌倦了在互联网上查找数百个方法和函数来探索您的数据集吗?Xplore 将探索性数据分析过程的速度提高了 10 倍,所有这一切都只需要一行代码。

xplore logo 设计由Divine alor vor
什么是数据探索?
根据维基百科的定义,数据探索是一种类似于初始数据分析的方法,数据分析师通过视觉探索来了解数据集中的内容和数据的特征,而不是通过传统的数据管理系统。
正是在数据分析过程的这个阶段,数据科学家或分析师、人工智能或人工智能工程师试图真正理解他们正在处理的数据。在这一点上,他们试图熟悉他们正在处理的数据,以便能够知道它在解决手头的问题时有多有效,以及他们还需要做多少处理。在这个阶段,数据分析师或科学家、人工智能或 ML 工程师使用如此多的工具和库来有效地探索他们的数据集。这使得数据探索的过程很难完全完成,特别是如果你不知道许多必要的工具,库和方法来很好地探索你的数据集。有一个好消息,想象一下,只需一行代码就能高效快速地浏览数据集!
探险
考虑到与有效探索您的数据相关的这么多问题,我的队友、Benjamin acqua ah、 Adam Labaran 和我自己编写了一些自动化脚本,可以极大地自动化和简化数据探索过程。我们使用 Pandas 开源库编写了这个脚本,利用了该库附带的许多方法和函数。在修复了几个错误、优化了代码并运行了一系列测试之后,我们最终构建并打包了 xplore 🎉。
xplore 是为数据科学家或分析师、AI 或 ML 工程师构建的 python 包,用于在单行代码中探索数据集的特征,以便在数据争论和特征提取之前进行快速分析。 xplore 还利用了 pandas-profiling 的全部功能,如果用户需要,可以生成非常高级和详细的数据探索报告。
xplore 完全开源,感兴趣的贡献者或代码爱好者可以在Github上找到完整的源代码和测试文件。该项目也已经发布在 PyPi 上,因此任何感兴趣的人都可以轻松地将它安装并导入到他们的本地项目中。****

xplore logo 由Divine alor vor设计
如何使用 xplore 浏览您的数据
在本节中,我将通过一个演练教程来指导您如何在您的本地项目中安装、导入和使用 xplore 包。
安装 xplore 包
使用 xplore 包成功浏览数据的最低要求是在计算机上安装 Python。一个额外的好处是可以在您的计算机上安装 Anaconda 并添加到 PATH 中。完成这些工作后,您可以轻松地导航到您的命令提示符(Windows)、终端(Linux/macOS)或 anaconda 提示符并运行命令:
****pip install xplore****
通过运行这个命令,最新版本的 xplore 及其依赖项将会完全存储在您的本地计算机上,这样您就可以方便地在以后的 python 文件中导入和使用它。
将 xplore 模块导入到代码中
在任何想要使用 xplore 包探索数据的 python 文件中,您都必须将 xplore 模块直接导入到代码文件中,这样您就可以轻松地访问和使用该模块附带的内置方法。这可以通过在代码中进行必要的导入时添加以下行来实现:
****from xplore.data import xplore****
为探索准备数据
在这篇文章发表的时候, xplore 包已经过优化,只能处理带标签的数据。使用 xplore 包准备您的数据,就像将您读入代码的数据赋给任何变量名一样简单。
****import pandas as pddata = pd.read_csv('name_of_data_file.csv')****
使用 xplore 方法
实际探索数据的过程被简化为一行代码。其他要做的事情将由我们编写的自动化脚本自动完成。您可以使用以下命令浏览您的数据:
****xplore(data)****
通过运行该程序,您将看到从数据探索中得出的分析输出。几乎所有您需要的重要分析都将被打印出来,但是对于那些希望从他们的数据分析中看到非常详细和高级的报告的人,当提示询问您是否希望看到关于您的数据探索的详细报告时,请键入“y”。否则,如果您对打印出来的输出感到满意,当您看到该提示时,您可以轻松地键入“n”。
运行 xplore 方法的示例输出
在运行了使用 xplore 方法浏览数据的代码之后,您的输出应该是这样的:
****------------------------------------
The first 5 entries of your dataset are:
   rank country_full country_abrv  total_points  ...  three_year_ago_avg  three_year_ago_weighted  confederation   rank_date
0     1      Germany          GER           0.0  ...                 0.0                      0.0           UEFA  1993-08-08
1     2        Italy          ITA           0.0  ...                 0.0                      0.0           UEFA  1993-08-08
2     3  Switzerland          SUI           0.0  ...                 0.0                      0.0           UEFA  1993-08-08
3     4       Sweden          SWE           0.0  ...                 0.0                      0.0           UEFA  1993-08-08
4     5    Argentina          ARG           0.0  ...                 0.0                      0.0       CONMEBOL  1993-08-08
[5 rows x 16 columns]
------------------------------------
The last 5 entries of your dataset are:
       rank country_full country_abrv  total_points  ...  three_year_ago_avg  three_year_ago_weighted  confederation   rank_date
57788   206     Anguilla          AIA           0.0  ...                 0.0                      0.0       CONCACAF  2018-06-07
57789   206      Bahamas          BAH           0.0  ...                 0.0                      0.0       CONCACAF  2018-06-07
57790   206      Eritrea          ERI           0.0  ...                 0.0                      0.0            CAF  2018-06-07
57791   206      Somalia          SOM           0.0  ...                 0.0                      0.0            CAF  2018-06-07
57792   206        Tonga          TGA           0.0  ...                 0.0                      0.0            OFC  2018-06-07
[5 rows x 16 columns]
------------------------------------
Stats on your dataset:
<bound method NDFrame.describe of        rank country_full country_abrv  total_points  ...  three_year_ago_avg  three_year_ago_weighted  confederation   rank_date
0         1      Germany          GER           0.0  ...                 0.0                      0.0           UEFA  1993-08-08
1         2        Italy          ITA           0.0  ...                 0.0                      0.0           UEFA  1993-08-08
2         3  Switzerland          SUI           0.0  ...                 0.0                      0.0           UEFA  1993-08-08
3         4       Sweden          SWE           0.0  ...                 0.0                      0.0           UEFA  1993-08-08
4         5    Argentina          ARG           0.0  ...                 0.0                      0.0       CONMEBOL  1993-08-08
...     ...          ...          ...           ...  ...                 ...                      ...            ...         ...
57788   206     Anguilla          AIA           0.0  ...                 0.0                      0.0       CONCACAF  2018-06-07
57789   206      Bahamas          BAH           0.0  ...                 0.0                      0.0       CONCACAF  2018-06-07
57790   206      Eritrea          ERI           0.0  ...                 0.0                      0.0            CAF  2018-06-07
57791   206      Somalia          SOM           0.0  ...                 0.0                      0.0            CAF  2018-06-07
57792   206        Tonga          TGA           0.0  ...                 0.0                      0.0            OFC  2018-06-07
[57793 rows x 16 columns]>
------------------------------------
The Value types of each column are:
rank                         int64
country_full                object
country_abrv                object
total_points               float64
previous_points              int64
rank_change                  int64
cur_year_avg               float64
cur_year_avg_weighted      float64
last_year_avg              float64
last_year_avg_weighted     float64
two_year_ago_avg           float64
two_year_ago_weighted      float64
three_year_ago_avg         float64
three_year_ago_weighted    float64
confederation               object
rank_date                   object
dtype: object
------------------------------------
Info on your Dataset:
<bound method DataFrame.info of        rank country_full country_abrv  total_points  ...  three_year_ago_avg  three_year_ago_weighted  confederation   rank_date
0         1      Germany          GER           0.0  ...                 0.0                      0.0           UEFA  1993-08-08
1         2        Italy          ITA           0.0  ...                 0.0                      0.0           UEFA  1993-08-08
2         3  Switzerland          SUI           0.0  ...                 0.0                      0.0           UEFA  1993-08-08
3         4       Sweden          SWE           0.0  ...                 0.0                      0.0           UEFA  1993-08-08
4         5    Argentina          ARG           0.0  ...                 0.0                      0.0       CONMEBOL  1993-08-08
...     ...          ...          ...           ...  ...                 ...                      ...            ...         ...
57788   206     Anguilla          AIA           0.0  ...                 0.0                      0.0       CONCACAF  2018-06-07
57789   206      Bahamas          BAH           0.0  ...                 0.0                      0.0       CONCACAF  2018-06-07
57790   206      Eritrea          ERI           0.0  ...                 0.0                      0.0            CAF  2018-06-07
57791   206      Somalia          SOM           0.0  ...                 0.0                      0.0            CAF  2018-06-07
57792   206        Tonga          TGA           0.0  ...                 0.0                      0.0            OFC  2018-06-07
[57793 rows x 16 columns]>
------------------------------------
The shape of your dataset in the order of rows and columns is:
(57793, 16)
------------------------------------
The features of your dataset are:
Index(['rank', 'country_full', 'country_abrv', 'total_points',
       'previous_points', 'rank_change', 'cur_year_avg',
       'cur_year_avg_weighted', 'last_year_avg', 'last_year_avg_weighted',
       'two_year_ago_avg', 'two_year_ago_weighted', 'three_year_ago_avg',
       'three_year_ago_weighted', 'confederation', 'rank_date'],
      dtype='object')
------------------------------------
The total number of null values from individual columns of your dataset are:
rank                       0
country_full               0
country_abrv               0
total_points               0
previous_points            0
rank_change                0
cur_year_avg               0
cur_year_avg_weighted      0
last_year_avg              0
last_year_avg_weighted     0
two_year_ago_avg           0
two_year_ago_weighted      0
three_year_ago_avg         0
three_year_ago_weighted    0
confederation              0
rank_date                  0
dtype: int64
------------------------------------
The number of rows in your dataset are:
57793
------------------------------------
The values in your dataset are:
[[1 'Germany' 'GER' ... 0.0 'UEFA' '1993-08-08']
 [2 'Italy' 'ITA' ... 0.0 'UEFA' '1993-08-08']
 [3 'Switzerland' 'SUI' ... 0.0 'UEFA' '1993-08-08']
 ...
 [206 'Eritrea' 'ERI' ... 0.0 'CAF' '2018-06-07']
 [206 'Somalia' 'SOM' ... 0.0 'CAF' '2018-06-07']
 [206 'Tonga' 'TGA' ... 0.0 'OFC' '2018-06-07']]
------------------------------------
Do you want to generate a detailed report on the exploration of your dataset?
[y/n]: y
Generating report...
Summarize dataset: 100%|████████████████████████████████████████████████████████████████████████████| 30/30 [03:34<00:00,  7.14s/it, Completed] 
Generate report structure: 100%|█████████████████████████████████████████████████████████████████████████████████| 1/1 [00:31<00:00, 31.42s/it] 
Render HTML: 100%|███████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:12<00:00, 12.07s/it] 
Export report to file: 100%|█████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00,  8.00it/s] 
Your Report has been generated and saved as 'output.html'****
Python 是你能读懂的最强大的语言。
—保罗·杜布瓦
作为一个狂热的学习者,我非常热衷于为下一代学习者提供更简单的东西,自动化是实现这一点的最简单的方法之一。为自己省去在数据探索上浪费大量时间的压力。当你下一次浏览你的数据时,一定要 浏览 你的数据😉
如果你喜欢我的队友和我在这个项目中所做的,请花几分钟时间给明星⭐️on 留下 GitHub repo ,并通过点击这个链接在 twitter 上告诉你的朋友关于 xplore 。
感谢您抽出几分钟时间阅读本文。我希望它是有教育意义和有帮助的😊如果你想在推特和 T2 的 LinkedIn 上私下聊天,我随时奉陪。编程快乐!
我衷心感谢 安娜·阿伊库 校对并纠正了我写这篇文章时犯的许多错误。
数据探索与洞察

(来源: PxHere )
Pytolemaic 系列
为什么您应该停止数据探索,转而使用自动洞察生成。
动机
一个 ll 数据项目从数据开始,工作从数据探索开始。通过执行数据探索,探索者旨在熟悉和理解数据,发现有趣的事实和趋势,如数据中的损坏、相关性、类别不平衡。
然而,数据浏览器的最终目标不是有趣的事实或趋势,而是可操作的见解。这些数据洞察随时可用——可能用于清理数据、提高模型性能或支持业务 KPI。
这不是一个容易的过程。即使是很小的数据集(包含几千个样本和仅仅十几个特征的表)也很难理解,筛选见解就更难了。在这篇文章中,我将讨论为什么数据探索是发现有用数据洞察的错误方法,并建议用自动洞察生成方法来取代它。我将分享这种洞察力生成方法的一些结果以及我的结论。
数据探索,以及为什么你不应该这样做
人们通常通过查看一些样本来开始数据探索过程,这很好,但最多限于几百个样本。接下来,他/她会查看一些统计数据(例如最小值、最大值、频率、计数)并绘制一些直方图,以寻找有趣的见解。根据一个人的创造力和好奇心,为数据集中的每个要素生成一打统计数据和图表是相当容易的,这些数据可以累积到数百甚至数千个图表。
比如我们来看看 UCI 的成人数据集(链接)。这是一个小数据集——大约 50K 个实例和 15 个特征——这个 Kaggler 已经为其训练了一个简单的逻辑回归模型,但在此之前绘制了 20 多个统计表和图表。
只见树木不见森林

成人数据集中所有特征的直方图(来源:作者)
我们贫乏的人类头脑无法处理太多的信息。太多的统计数据/图表会导致浏览时看不到它们。
在 Data Exploration 干草堆中寻找针

成人数据集中所有特征的最大值(来源:作者)
抛开创建统计表/图表所需的工作不谈,阅读和理解其中的内容需要付出大量的努力。例如,计算每个特征的最大值是微不足道的,但是要注意到一个特定的特征,(例如,成人数据集中的‘资本收益或‘每周小时数’)有一个可疑的最大值——这几乎是不可能的。
信息只有在你能付诸行动时才是有用的
数据探索旨在通过各种功能和技术获取数据信息。然而,我们需要所有这些信息吗?答案是不,我们没有。任何不会引发行动的信息都是无用的,我们不需要无用的信息,不管它多么有趣。
例如,让我们看看成人数据集中职业特征的直方图。我们可以看到每个职业有多少人。

成人数据集中特征占用的直方图(来源:作者)
如果那是你的数据集——你会在意数据集有 994 个渔民样本和 3650 个销售人员样本吗?可能分别是 1515 年和 2317 年,对吗?那么,如果一个箱子高度的 50%的差异没有影响,也不会引发第二个想法,为什么要首先查看直方图呢?
洞察力,以及如何获得洞察力
答案很简单——我们在搜索有趣的信息时进行数据探索,我们可以根据这些信息采取行动,换句话说,就是洞察力。看着上面的例子,我们可以发现一些有趣的事实:
- “职业为‘武装部’的只有 9 人”。
 - 职业不明的有 1500 人。
 - “管理者比渔民多 4 倍”。
 
然而,只有前两句话应被视为见解,因为它们会引发行动。
- “职业为‘武装部’的只有 9 人”。→触发“从数据集中删除这些样本”动作或“将‘职业’类与另一类合并”。
 - 职业不明的有 1500 人。→触发“验证数据正确性”动作,随后触发“处理缺失值”动作。
 
如果你先画一张图表,然后问自己能从中学到什么,那么你就做错了。相反,首先决定你想学什么,然后绘制图表。
绘制一个有趣的图表,然后试图发现洞察力是大多数人做的事情。很有挑战性,也很好玩,但不是很有效。更好的方法是根据问题的答案来定义“问题”( Q )或“假设”( H )以及相应的“动作”( A )。例如:
- H: 超出 5-sigma 范围的异常值数量应≤1。
答:降样。 
在这种方法中,洞察力( I )很容易被发现,因为它们是触发行动的事实——对未实现的问题( Q )或假设( H )的回答。基于成人数据集的一些示例:
- H: 超出 5-sigma 范围的异常值数量应≤1。
I : 709 个异常值超出了特性“资本收益”的 5-sigma 范围。
I : 244 个异常值在特征“资本损失”的 5-sigma 范围之外。
答:滴样品。 - H: 数字特征的最大值不是 10**k-1 的格式。
I :存在‘资本收益’为 99999 的样本。
I :存在“每周小时数”为 99 的样本。
答:验证这些值的正确性。 - 问:唯正特征有没有负值?
I : 无(没有这样的值)。
A :如果有,更换为 N/A 
让我们看看如何将它写入代码:
3 种洞察的代码示例
洞察力不仅限于数据
在前面的示例中,我们重点关注了来自数据集的见解。然而,如果我们定义一些 ML 假设,我们可能会发现额外的见解。例如:
- H :测试集和训练集具有相似的数据分布
 - H :数据集中没有重要性为 0 的特征
 - H :如果主要指标显示良好的结果,那么其他指标也有合理的值。
 
在大多数情况下,回答这些问题或检验假设是很容易的,不需要使用图形方式,甚至不需要人参与。因此,这一过程通常可以自动化,并且由于许多假设不依赖于数据集,因此不难扩展。人们甚至可以继承这个概念,为数据集定义一套单元测试。
自动洞察生成
我已经开始尝试实现这样的自动洞察生成器,作为 Pytolemaic 包的一部分(在这里阅读更多)。我定义并实现了一组通用的假设,后来我在几个数据集上进行了尝试。在讨论我的结论之前,让我们看看那些试验的结果。
见解示例
- Titanic 数据集— 900 个样本 X 11 个特征
 
泰坦尼克号数据集的自动生成洞察
洞察力告诉我们:存在 5-sigma 异常值——需要检查。此外,一些功能(姓名/机票/客舱)使用不正确。
- 加州房价数据集— 20k 样本 X 8 特征
 
加州房价数据集的自动生成洞察
洞察力告诉我们:存在 5-sigma 异常值——需要检查。
- 成人数据集— 32K 样本 X 14 个特征
 
成人数据集的自动生成洞察
洞察力告诉我们:存在 5-sigma 异常值——需要检查。此外,每周小时数( 99.0)和资本收益 (99999.0)也有可疑值。
- Sberbank 房产市场 — 3 万个样本 X 291 个特征(一场卡格尔竞赛)
 
Sberbank 房产市场数据集的自动生成洞察
洞察告诉我们:大约有 250 个洞察,其中大部分是 5-sigma 离群值——需要检查。另外,在子区域的小类应该合并到一个‘其他’类。
下面给出了使用 Pytolemaic 包生成 Titanic insights 的代码,如果您想亲自尝试的话。
我的结论
这些见解的实现非常有趣,并不像我预期的那么难。它向我展示了实现通用的自动生成的见解并获得对数据的有用见解是可能的。产生这种见解的要求是经验、创造力和编码技能——任何高级数据科学家都具备的技能组合。然而,在创建 insight 模块时,我不得不面对几个挑战,使得这个过程充满挑战。
- 有用性 由于定义问题/假设所涉及的过程,使见解变得有用并不是一个很大的挑战。因为行动是定义的一部分,所以获得的任何洞察都是可操作的,因此是有用的。然而,动作应该是 insight 模块输出的一部分,因为读者可能不知道要执行什么动作。
 - 简短、清晰、干净且易于理解 通过查看这些自动生成的见解,很明显选择正确的格式至关重要。对于一些见解,我很难选择一个好的格式,这是显而易见的。难以阅读或难以理解的见解会被忽视和忽略,错过它们包含的信息。
例如,在上述示例中,insight 分析是在分类特征已经通过序号编码的数据集上执行的,这使得“class '1.0 '只有 3 个表示”这样的句子非常模糊,因为人们很难弄清楚 class '1.0 '到底是什么? - 完整信息 洞察应该包含数据科学家采取行动所需的所有相关信息。例如,离群值的“# ”洞察不提供遇到的最大值和最小值。因此,要由读者来查找(即编写一些代码)这些带有离群值洞察力的特性的数字——有很多这样的特性。然而,请注意,如果一个人想要保持简短清晰的洞察力,提供额外的信息并不像看起来那么简单。
 - 洞察力的质量和有用性很大程度上取决于投入到分析中的努力。例如, '# of outliers' 假设正态分布,这可能不是许多特征的情况(例如,“年龄”,“每周小时数”)。可以定义高级假设来揭示隐藏的见解,例如特征之间的高度相关性、数据中的异常、时间漂移等等。
 - 全面性 由于数据集/模型中可能出现的问题数量接近于无穷大,因此要创建一套全面的见解几乎是不可能的。全面性只能通过从经验教训中不断改进来实现。
 - 太多的洞见 克服了上面所有的挑战之后,还有一个主要的挑战——如何避免产生太多的洞见。当有太多的洞见时,用户将很难浏览所有的洞见。Sberbank 的例子展示了这样的行为。我相信我们需要实现一些算法来帮助我们筛选列表中更重要的见解。
 
总结一下
由于人类能力有限,数据探索无法扩展。因此,我们需要使用不同的方法——自动洞察生成。在这种方法中,我们定义了一组问题-行动或假设-行动对。然后将问题/假设应用于数据集,提供可操作的答案。
通过几个例子,我们看到了这种方法的潜力和挑战。我相信,在不久的将来,世界将超越人工数据探索,代之以强大的算法,能够以可扩展的方式提供可操作的见解。
COVID 跟踪项目的数据探索
如何使用新冠肺炎最全面的美国数据库之一轻松进行探索性数据分析(EDA)。

编者按: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
什么是 COVID-tracking-project?
根据他们的网站,COVID 跟踪项目收集并发布了美国各州和地区最完整的测试数据。

图片来源:截图来自 Covid-tracking-project 网站
了解区域疫情的发展动态和精确位置需要完整的测试图——每个州/地区实际上有多少人接受了测试,测试是何时进行的,结果是什么。
艾德亚多·桑奇兹博士是美国心脏协会负责预防的首席医疗官,也是前州卫生局局长
www.heart.org](https://www.heart.org/en/news/2020/04/02/covid-19-science-why-testing-is-so-important)
事实上,该项目已被全国各大媒体公司和机构引用和使用。

图片来源:截图来自 Covid-tracking-project 网站
如何验证数据的质量和准确性?
该网站进一步补充道“…o 我们的数据团队使用网站抓取器和追踪器来提醒我们发生的变化,但对我们数据集的 实际更新是由细心的人 手动完成的,他们会仔细检查每一项变化,并广泛地注释不明确的变化区域。
流行新闻媒体中的一些可视化内容(例如纽约时报、政治、华尔街日报等。)都是从这些数据中创建出来的。

图片来源:截图来自 Covid-tracking-project 网站
在本文中,我们将了解简单的 Python 脚本如何帮助您阅读该数据集并创建有意义的可视化效果,从而追踪和了解新冠肺炎在美国的传播情况
了解区域疫情的发展动态和精确位置需要一个完整的测试图…
代码和演示
代码可以在这个 Jupyter 笔记本 在我的 新冠肺炎分析 Github 回购 中找到。
提取数据并加载到数据帧中
第一部分是从网站上提取数据,并将其加载到熊猫数据框架中,以便于分析。
幸运的是,他们以 CSV 格式为此目的提供了一个简单的 API 端点。

这意味着,为了分析最新的数据,你只需要实时运行脚本,从网站上获取最新的数据。不依赖于旧的下载数据文件!
一些家务
我们可能希望将日期字段转换成特定的格式,删除不必要的列,并确保state字段有字符串值。

有什么样的数据?
这是数据集列的快照,

请注意,并非所有数据都以相同的数量/频率出现。记录阳性/阴性病例,定期维护测试结果,而住院数据(呼吸机、ICU 等。)都有些稀疏。
我们预计在数据帧中会有很多 NaN 或 voids,所以我们可以简单地用一个特殊的数字来替换它们,比如-1,以便稍后签入我们的验证代码。

给定变量/状态的条形图
条形图是最常见的这种类型的视觉分析。我们编写了一个自定义函数来绘制任何给定状态下数据集中的任何变量随时间的变化。
我们不会在这里乱码,但这里有例子。请注意,并非所有系列都具有相同数量的数据点,或者并非所有系列都从相同的时间点开始。但是代码只是简单地处理它,并为用户选择的特定状态绘制可用数据。




散点图检查相关性
相关性的一个基本检查是通过创建双变量散点图来完成的。因此,我们编写一个自定义函数来为任何一对变量创建散点图。
总检测数和阳性病例数之间是否存在正相关关系?

死亡人数是否随住院率单调增加?

跟踪测试的进度
正如我们在开始时提到的,COVID-tracking 项目主要用于测试相关数据。因此,毫不奇怪,我们想要创建一个可视化来跟踪测试工作中各种状态的进展。
我们甚至可以使用折线图在同一个图上比较多个状态。该函数还为我们计算平均测试/日指标,并将其放入图例中。

计算各种比率的函数
我们编写了一组函数来计算各种有用的比率,
- :死亡总人数与阳性总人数之比
 - 住院率 :住院总人数与总阳性病例数之比
 - 阳性病例比率 :总阳性病例数与总检测数的比率
 
一旦对这些函数进行了编码,就可以在标准的可视化脚本中使用它们来绘制条形图,比较各种状态的比率。这将回答一些问题,比如哪个州的死亡率最高?哪个州的住院率最低?
为什么这些比率对计算和跟踪很重要?
这是因为,稍后,公共卫生官员和社会科学家可以查看这些数字,并假设当地因素——医疗保健系统准备情况、测试/跟踪能力、政治权宜之计、人均 GDP 等。影响了每个州的死亡率和住院率。
这里有一些比较图表的例子。请注意,并非所有图表都有相同数量的条形,也并非所有状态都报告相同的指标。



就人口或新冠肺炎病例而言,纽约州或加利福尼亚州比密歇根州大得多并不重要。该比率清楚地表明,在新冠肺炎阳性病例中,心肌梗死的死亡率最高,而在所有检测中,纽约的阳性病例比例最高。
这些断言中的每一个,通过简单的条形图被可视化,都是一个可以跟随和分析的故事,以理解这种疾病的本质和动态。
…公共卫生官员和社会科学家可以查看这些数字,并假设当地因素——医疗保健系统准备情况、检测/跟踪能力、政治权宜之计、人均 GDP 等。影响了每个州的死亡率和住院率。
用于比较所有状态的气泡图
相同的比率可以绘制在气泡图中,以便一起比较所有的状态。
**
哪些州有 14 天病例数下降?
我们需要编写几个自定义函数来从数据集中提取这些数据或趋势,并将其可视化。
基本上,我们可以看看最近 14 天新新冠肺炎病例的连续差异。如果所有的数字都是负数,那么新的病例会单调下降。即使事实并非如此,那么负数越多越好,因为这表明总体趋势在下降。
代码在笔记本中,但当我们比较四种状态(CA、GA、LA 和 MI)时,结果显示在这里。事实上,没有一个州显示出一组完整的负数。

摘要和其他文章
我们展示了如何从美国最受尊敬的新冠肺炎数据库中提取数据,并使用简单的 Python 代码创建有意义的可视化。
同样,代码可以在我的新冠肺炎分析 Github repo 中的这个 Jupyter 笔记本中找到。这个回购里还有其他有用的笔记本,大家可以叉一下,探索一下。
这不是一个预测模型,将来也不会是。这个脚本的目标是只做可视化分析。如果没有扎实的流行病学知识或没有合作,就不应该仅仅从时间序列数据中建立任何预测模型。**
自第二次世界大战以来最大的全球性危机和自 1918-1919 年西班牙流感以来最大的全球性疫情今天降临了。每个人都在关注死亡人数的每日增长和这种新型病毒的快速指数传播。
数据科学家,像其他各行各业的许多人一样,也可能感到焦虑。知道数据科学和统计建模的熟悉工具与分析关键测试和疾病相关数据非常相关,这可能有点令人放心。
我的几篇文章与新冠肺炎有关。
创建一个简单的 Python 类来分析和可视化来自纽约时报的新冠肺炎数据集。
towardsdatascience.com](/analyze-ny-times-covid-19-dataset-86c802164210) [## 新冠肺炎检验的假阳性/假阴性和贝叶斯规则
为什么假阳性和假阴性都不利于新冠肺炎测试。为什么贝叶斯规则对这些很重要…
towardsdatascience.com](/false-positives-negatives-and-bayes-rule-for-covid-19-testing-750eaba84acd) [## “拉平曲线”和“解除锁定”的简单建模
一个基本流行病学模型的简单 Python 脚本,用于演示社交距离的影响。
towardsdatascience.com](/simple-modeling-of-flattening-the-curve-and-lifting-lockdown-1a774a248e68)
注意安全,各位!
作者注 : 我是一名半导体技术专家,对将数据科学和机器学习应用于与我领域相关的各种问题感兴趣。我没有医学、分子生物学、流行病学或任何与新冠肺炎相关的专业知识。 请不要给我发那种查询的邮件 。
答同样,你可以查看作者的 GitHub 知识库获取机器学习和数据科学方面的代码、思想和资源。如果你像我一样,对人工智能/机器学习/数据科学充满热情,请随时在 LinkedIn 上添加我,或者在 Twitter 上关注我。
[## Tirthajyoti Sarkar - Sr .首席工程师-半导体、人工智能、机器学习- ON…
通过写作使数据科学/ML 概念易于理解:https://medium.com/@tirthajyoti 开源和有趣…
www.linkedin.com](https://www.linkedin.com/in/tirthajyoti-sarkar-2127aa7/)*
从具有半结构化布局的 PDF 表格中提取数据
实践教程
了解如何使用 pdfminer、numpy 和 pandas 处理特定于上下文的数据结构

图片来自 https://wiki.atlan.com/unstructured-data/
什么是半结构化数据?
在当今的工作环境中,PDF 文档被广泛用于内部以及与贸易伙伴交换商业信息。很自然,你已经看到了相当多的 pdf 格式的发票、采购订单、发货单、价目表等。尽管 PDF 文档作为纸质文档的数字替代物,但对其存储的数据的自动化操作提出了挑战。它就像写在纸上的数据一样容易获取,因为有些 pdf 是为了向我们人类传递信息而设计的,而不是计算机。此类 pdf 可能包含没有预定义数据模型或没有以预定义方式组织的非结构化信息。它们通常以文本为主,可能包含数字、日期和数字的组合。
使用大多数可用的工具,您通常必须处理整个 PDF 文档,无法将数据提取限制在最有价值的数据所在的特定部分。然而,一些 PDF 表格提取工具就是这样做的。遗憾的是,即使你足够幸运,在你的 PDF 中有一个表格结构,也不意味着你能够无缝地从中提取数据。
例如,让我们看看下面的基于文本的 PDF,其中有一些虚假的内容。它有非常明显和明显的(虽然没有边界)行和列:

作者图片
只要稍加观察,您就可能会忽略一个重要的模式:一些行和列相交处的文本被堆叠和移动,因此很难将其识别为同一数据行的附加特征。
尽管如此,任何不适合列或行的数据都被广泛认为是非结构化的,我们可以将这种特殊的现实世界现象称为半结构化数据。
对于任何现成的提取算法来说,从给定的表中解析数据并不容易。虽然这些工具可能有相当有效的结果,但在这种特殊情况下,我们需要额外的开发工作来满足您的要求。继续学习本教程,您将会找到解决这一挑战的有效方法。
本教程的范围
在本教程中,您将学习如何:
- 使用现成的解决方案从 PDF 中提取表格
 - 使用真实的文档布局从 PDF 获取原始文本
 - 使用 numpy 和 pandas 执行文本操作
 
更一般地说,您将了解如何在一系列数据提取任务中处理特定于上下文的数据结构。
用于表格提取的现成解决方案
为了证实上述陈述的真实性,我们将尝试使用现成的 Python 模块解析半结构化数据,专门用于从 pdf 中提取表格。最受欢迎的开箱即用算法有 camelot-py 和 tabula-py 。他们都证明了自己在许多复杂的环境中是有效的。让我们看看他们如何应对我们的挑战:
看来我们最初的选择变成了悲惨的失败!虽然 tabula-py 在检测我们的表格的网格布局方面似乎稍好一些,但它仍然提供了许多额外的工作来分割第二列中的文本,并不是说它已经完全开始了原始表格的最后一行。
关于 camelot-py 的输出,很明显,所有关于在列中插入文本的相关信息都已经完全消失了。
从现在开始,我们将继续构建我们的自定义解析算法。
使用真实的布局处理 PDF 中的原始文本
首先,我们需要一个自定义算法的基础。这应该是一个字符串输入,完全代表原始文档的布局。同样,您有相当多的选项(想想 python 模块)可供选择。在我们的教程中,我们将决定使用 pdfminer 和pdf text进行实验。以下是他们的工作成果:
看起来两个模块都产生了相当令人满意的结果,除了 pdftotext 去掉了第 5 和第 6 列之间的一些空白。
但最重要的是,在这两种情况下,我们都能够保留垂直对齐的文本块之间的可见间隔(你好,monospace 字体!)
用 numpy 和 pandas 操作文本数据
另一个好消息是,这些空格在某种程度上使您将垂直对齐的文本视为一个完整的元素,即我们的表格布局中的一列!这是一个作用中的邻近定律。如果你之前没有听说过视觉设计的格式塔理论,请参考链接。你尤其应该明白的是,邻近定律与任何物理定律都相去甚远。它只是在你的脑海中,所以每次你都必须明确地告诉计算机元素的排列应该有多接近才能有接近度。在我们的例子中,有一条宽度至少为一个空格的垂直直线就足够了,可以均匀地将列彼此分开。我们所需要的就是显示我们的自定义算法,那些空白行分隔符在哪里。
将字符串输入转换成字符矩阵
为了达到这个目的,我们将把来自 pdfminer 的字符串输出转换成一个 char 矩阵,即每个字符串元素在各自的单元格中包含空格的结构。利用下面代码块中的一些辅助函数,我们依次执行转换并搜索上述除法器:
将原始文本拆分成列
看起来我们已经准备好将输入行分割成新定义的列:
处理行中的堆叠数据
太神奇了!我们的下一步将是把那些堆叠在“悬挂”(偶数)行中的文本块向右移动,并向上移动到(⤴)与它们真正属于的相应奇数行相同的水平上。此外,我们将把第一行作为表格的标题分开,单独处理它:
将列与原始标题匹配
您是否注意到我们的表格是如何自然而一致地为额外的列(如 3–3 和 5–5)设置了双重标题?
为了进一步将所有列引用到表的原始标题,我们将执行下面的重命名技巧:我们将根据它们的父元素(最左边的元素)为所有重复条目分配新的唯一字幕(后缀)。比如一个序列[0,1,2,3,3,4 …]会变成[0,1,2,3,3_1,4 …]。
我们将对表的原始标题执行的有点类似的转换(与上一步中的数据分离)。假设您已经注意到了一个特殊的模式:所有带有堆叠文本的列的标题中都有“/”,这表示我们从数据拆分中获得的列的名称。为了将列与其标题相匹配,我们需要某种查找表,以便标题引用并执行最后的处理:
当您确切知道表格的位置时,应该将上述方法视为从基于文本的 pdf 中提取数据的专用解决方案。尽管您可以尝试采用另一种解决方案来大规模解析 pdf 中的半结构化数据。
参见 GitHub 上的完整代码。
从 GitHub 提取数据,并自动运行或调度 Python 脚本
博客的第一部分—

T 他的博客是LIVE Tableau 公共可视化自动化 ETL的一部分,分为两个部分,即:
- 从原始数据中提取数据。GitHub 用户内容的 csv 文件
 - 使用 Windows 上的任务调度程序自动化 Python 脚本
 
1.从原始数据中提取数据。GitHub 用户内容的 csv 文件
数据来源于 https://github.com/CSSEGISandData/COVID-19 JHU CSSE GitHub 库:

import numpy as np
import pandas as pd
导入了相关的库。

df_names = ['confirmed_global', 'deaths_global', 'recovered_global'] 
df_list = [pd.DataFrame() for df in df_names]
df_dict = dict(zip(df_names, df_list))
因为我们需要提取 3。csv 文件,我创建了一个包含数据帧名称的列表' df_names' 。注意,声明的名称是根据下面解释的url_part选择的。
然后,声明一个列表' df_list '来保存创建的 3 个空数据帧。注意,for df in df_names只需确认创建的空数据帧的数量=列表' df_names '中的元素数量。
然后,使用关键字:值对创建字典' df_dict ',作为' df_names: df_list '。也就是说,每个名称都链接到具有各自位置的空数据帧。

url_part = '[https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_'](https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_')
根据需要创建 URL 部件。*以上申报的名称将成为申报的url_part的后缀。
for key, value in df_dict.items():
    value = pd.read_csv(url_part+key+'.csv', parse_dates=[0])
    value.rename(columns={'Province/State': 'Province_State', 'Country/Region': 'Country_Region'}, inplace=True)
    dim_col = value.columns[0:4]
    date_col = value.columns[4:]
    value = value.melt(id_vars = dim_col, value_vars = date_col, var_name = 'Date', value_name = key)
    value['Date'] = pd.to_datetime(value['Date'])
    df_dict[key] = value
为了加载数据,我在上面声明的字典' df_dict '中的条目中用' for 循环'。使用 pandas read_csv函数一个接一个地输入空的数据帧,该函数从使用url_part +键(它们是各自声明的名称)+'生成的 URL 中读取数据。csv。然后,重命名列名,使其对 Python 友好。
现在有趣的部分来了——pandas
[**melt**](https://pandas.pydata.org/docs/reference/api/pandas.melt.html)函数,它发挥了魔力,使我能够为我的 Tableau 仪表板转换数据。基本上,melt函数将数据帧从宽格式转换为长格式。请参考下面的调试打印输出:

因此,melt函数将 77 个日期列从宽格式转换为长格式,这些列的标题被输入到使用value_vars = date_col, var_name = 'Date'参数创建的新列' Date ,数字数据被输入到使用melt函数的value_name = key参数创建的新列' confirmed_global 。
然后,将“ Date ”列数据类型更改为 datetime,并为之前声明的字典的键分配相应的加载和转换数据帧。

join_on_col = ['Province_State','Country_Region','Lat','Long','Date']df_COVID = df_dict['confirmed_global'].merge(df_dict['deaths_global'], on=join_on_col, how='outer').merge(df_dict['recovered_global'], on=join_on_col, how='outer')df_COVID.rename(columns = {'confirmed_global':'Confirmed', 'deaths_global':'Deaths', 'recovered_global':'Recovered'}, inplace = True)
现在,pandas [merge](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.merge.html)函数被用来合并 3 个不同的文件,它们共同具有'省 _ 州'、国家 _ 地区'、纬度'、经度'、日期。然后,合并的数据帧' df_COVID '的列名被重命名。

# to fill the NaN in 'Province_State' columns with Countries name in 'Country_Region'
df_COVID['Province_State'] = np.where(df_COVID['Province_State'] == 'nan', df_COVID['Country_Region'], df_COVID['Province_State'])# to fill the NaN in last three columns
df_COVID.iloc[0:,-3:] = df_COVID.iloc[0:,-3:].fillna(0)
这最后一行代码有助于根据需要从数据帧‘df _ COVID’中删除 NaN 。稍后,可以使用 pandas 的to_csv 功能将该数据帧提取为. csv 文件。
但是我计划将它导出到Google Sheets——查看博客的第二部分—LIVE Tableau 公共可视化的自动化 ETL
2.使用 Windows 上的任务调度程序自动化 Python 脚本
现在我已经创建了一个. py python 脚本文件来 ETL(提取、转换和加载)数据,我意识到用于获取数据的 GitHub 存储库每天都在更新。
在寻找每天运行 python 脚本的需求时,我看到了一个博客——用任务调度器自动化你的 Python 脚本,作者是 Vincent Tatan。不过,如果你是 Linux 用户,请参考 Ratik Sharma 写的在 macOS 上用 Crontab 调度作业。
这一部分是从以前的博客中简单整理出来的:
- 创建 Windows 可执行文件。运行 Python 的 bat 文件
 - 在 Windows 任务计划程序中配置任务
 

跑步。任务计划程序中创建的任务的 bat 文件
2.1 创建 Windows 可执行文件。运行 Python 的 bat 文件
一个 BAT 文件是一个 DOS 批处理文件用来执行 Windows 命令提示符(cmd.exe)下的命令。它包含一系列通常可能在 DOS 命令提示符下输入的行命令。 BAT 文件最常用于在 Windows 中启动程序和运行维护实用程序。资料来源:https://fileinfo.com/extension/bat
创建新的。bat 文件(例如:etl-covid-data.bat)并对其进行编辑,以如下格式编写您的命令:
***<python.exe location> <python script location>***
C:\Users\eklav\AppData\Local\Programs\Python\Python37\python.exe "C:\Users\eklav\Documents\My Tableau Repository\Datasources\COVID-DataSource\COVID-19\COVID-DataExtraction.py"
请确保您的Python37\Lib\site-packages已经安装了所有相关的库或模块。否则,在 cmd.exe 上执行pip install <module>来下载所需的依赖项。
调试:保存并运行此。双击 bat 文件。您可以在声明的命令前键入**cmd /k**。bat 档。这将在执行后保持 Windows 命令提示符(cmd.exe)窗口打开。蝙蝠文件
2.2 在 Windows 任务计划程序中配置任务
- 从'开始菜单中搜索并打开' 任务调度器
 - 单击“任务调度器”
右侧“操作”选项卡下的“ 创建基本任务… ”,声明“名称:”(例如:COVID-ETL-PyScriptRun)和“描述:’(例如:此任务将执行 COVID 实时更新所需的 python 脚本) - 任务触发 :
选择'您希望任务何时开始?'(例如:每日) - 为之前的选择声明频率参数
 - 动作 :
选择'你希望任务执行什么动作?'(例如:启动程序) - 通过浏览到声明“程序/脚本:”。先前创建的 bat 文件位置。此外,您可以将“ Start in(可选):”声明到应用程序文件夹的位置,以访问相关的依赖项
 - 完成 :
显示上述所有申报的'汇总。当我点击完成时,你可以勾选复选框打开该任务的属性对话框,以发现对你的预定任务的有趣和有用的改变。当我的代码中断时,一个有帮助的编辑是——在任务属性的' General '选项卡上,我选中了'Run with high privileges** 
下面是。上述 7 个步骤的 gif 动画:

上述 7 个步骤的 GIF 动画
参考
- 关于。BAT 文件扩展名
 - Vincent Tatan @ Medium 写的博客
 - Python 数据帧构造器文档
 
感谢您的阅读!我希望这篇博客揭示了如何在 windows 上自动化 python 脚本的有趣方面。如果你觉得这有帮助或者没有帮助,请在评论中告诉我。如果这篇文章是有帮助的,分享它。
来自 JHU CSSE GitHub Repo 的 ETL 创建 Tableau 可视化。ETL: Extract 中执行的步骤。GitHub 中的 csv 文件…
github.com](https://github.com/eklavyasaxena/COVID-19) [## Eklavya Saxena -印度|职业简介| LinkedIn
精通数据的分析师和有抱负的数据科学家,拥有 2 年以上的销售或客户行业经验…
www.linkedin.com](https://www.linkedin.com/in/eklavyasaxena/)
有益的数据有益于灵魂
数据科学家如何回馈

迈克尔·阿莱奥在 Unsplash 上的照片
想象一下所有的数据…
在约翰·列侬的歌曲《想象》中,他唱到了一个没有饥饿、没有痛苦、没有贪婪的世界,在那里他想象着所有的人过着和平的生活,一个共享整个世界的人类兄弟。
想象一下这个世界上所有等待分析、可视化的数据,想象一下将要做出的预测和将要开发的算法。想象一下,通过数据驱动的决策,可以讲述哪些有见地的故事来提高对社会问题以及对人类影响的认识。
数据正以前所未有的速度被创建和增长。根据 IDC 白皮书预测,整个数字世界有望在 2025 年达到 175 兆字节。

IDC:世界的数字化——从边缘到核心
绝大多数慈善组织、非营利组织和基金会只能 想象 拥有数据和分析来影响决策和推动他们的事业。
慈善事业竞争极其激烈,捐赠者要求透明度
捐助者、赞助商和公民越来越要求公开他们的时间和资金贡献的影响。
人们期望慈善组织展示出切实的社会影响和可衡量的成果。慈善监督机构继续深入调查,并根据透明度和影响力对慈善机构进行评级。
通过降低项目、筹资和管理费用的百分比来证明财务效率已经不够了。社会影响报告使慈善机构能够传达他们对社会事业或他们所支持的人的影响。如果做得好,社会影响报告可以增进志愿者、支持者、受益者和捐助者的信任。
引人注目的故事需要用数据、分析和可视化来讲述
慈善机构面临的挑战并不仅仅是获取经过筛选的、易于获取的数据。由于他们面临着维持低运营成本的巨大压力,他们没有能力雇佣数据管理和数据科学领域的熟练员工。数据在电子表格中捕获和/或分散在各种系统中。将数据拼接在一起,使其有意义,并获得有意义的见解是耗时的,并需要正确的技能。
有许多非营利和慈善组织,如联合国难民署、T2 世界粮食计划署,已经利用数据可视化的力量讲述故事,在几秒钟内吸引观众的注意力。

“数据换好”机芯
虽然每个人都为数据的创造做出了贡献,但并不是每个人都从中受益。企业部门继续受益于以创新方式利用其数据来增加利润。
我们都需要关注三重底线——为人、地球和利润做正确的事情。
当使命驱动的组织拥有合适的人才、工具和知识时,他们可以产生切实的人类影响。
Gartner 将数据定义为“人们和组织超越组织界限,利用数据改善社会的运动”
数据科学在行动中的力量继续得到证明。
危机短信热线由儿童求助电话提供给处于危机中的年轻人免费短信服务。数据是他们的生命线,多年来,危机文本热线已经收集了世界上最大的健康数据集之一。这些数据用于推动他们的服务产品和整体危机空间的改进。

危机文本行
利用他们丰富的数据集,他们开发了一种算法,根据短信的初始内容评估短信者的自杀风险。高风险短信发送者被标记为“橙色代码”,并被移到队列的顶部,以减少他们的等待时间。更短的等待时间可以拯救更多的生命。
个人可以通过以下几种方式自愿贡献自己的时间、技能和才能,对数据产生影响。无论是在数据管理、分析、数据可视化、高级分析、机器学习还是人工智能领域,都有大量参与的机会。
通过以下组织之一做出贡献:
DataKind 由 Jake Porway 于 2011 年创立,被认为是 Data for Good 机芯的开创者。他们与社会变革组织合作,在数据科学方面进行协作,以最大限度地发挥社会影响。DataKind 通过 DataCorps、DataDives 和社区活动与全球志愿者合作。
Chloe Tseng 于 2017 年创建了一个在线数据可视化社区。Viz 与世界各地的使命驱动型组织合作,利用数据可视化的力量来影响社会变革。世界各地的志愿者使用他们选择的工具,如 Tableau 、 Power BI 、 Qlik 和 D3 来强调有助于推动组织发展的趋势和机遇。
Kaggle 是全球最大的数据科学社区,拥有强大的工具和资源。Kaggle 为在线学习和数据科学竞赛提供公共数据集。2017 年,Kaggle 推出了“数据科学为善”,并为社会事业举办在线竞赛。
数据和分析供应商通过捐赠免费软件和他们自己的专业知识来促进社会事业,从而为良好的计划提供数据支持。一些提供志愿者和非营利组织之间的在线匹配服务。
Tableau 服务团 隶属于 Tableau 基金会,Tableau 的全球慈善组织。这是一个由 Tableau 专家组成的志愿者网络,他们有兴趣帮助非营利组织完成少于 10 小时的项目。非营利组织可以在 Tableau 服务团注册,并有机会根据项目的性质和所需的技能选择志愿者。
Alteryx for Good Co-lab是一个由 Alteryx 客户、员工和合作伙伴组成的网络,他们通过合作来改变数据。专门从事 Alteryx 的志愿者可以在网上注册,并与非营利组织或教育工作者配对。在整个分析生命周期中,志愿者帮助为报告准备数据,提供关于工具的见解,培训员工或完成项目。

剪贴画库
志愿服务的惊人好处
除了支持社会事业或社区的明显好处之外,志愿服务还提供许多其他好处。优秀志愿者的数据能够提高他们的技能,学习新的工具,并与志同道合的专业人士建立联系。一些人选择利用他们的志愿工作来提升他们的职业形象和寻找新的工作机会。
分析与某项事业或慈善机构相关的数据的过程为志愿者提供了一个全新的视角,非常令人大开眼界。使用数据可以深入主题,这是讲述有意义的故事或提出可行建议所必需的。
根据 BMC 健康研究的一份报告,志愿活动改善了心理和身体健康,增加了自尊和快乐,提高了生活满意度。
如果你是数据爱好者、数据科学家或对任何数据都有热情,那么世界就在你的脚下。支持你的事业,贡献你的才能,加入运动。
你可能会说我是一个梦想家,但我不是唯一的一个。我希望有一天你会加入我们,世界将会像一个人一样生活——约翰·列侬
数据框 EDA 软件包比较:Pandas Profiling、Sweetviz 和 PandasGUI
哪些熊猫数据框 EDA 包适合你?

作者创建的 GIF
作为一名数据科学家,我们的工作总是涉及探索数据,或者通常称为探索性数据分析(EDA)。探索数据的目的是为了更好地了解我们的数据,掌握我们在处理什么。
以前,使用 pandas 数据框探索数据是一件很麻烦的事情,因为我们需要从头开始编写每一个分析。这不仅要花很多时间,还需要我们集中注意力。
以下面的 mpg 数据集为例。
import pandas as pd
import seaborn as sns
mpg = sns.load_dataset('mpg')
mpg.head()

作者创建的图像
虽然数据看起来很简单,但是探索这个数据集仍然需要很多时间。
幸运的是,在当今时代,许多伟大的人已经开发了很棒的软件包来简化 EDA 过程。这些包的例子有熊猫简介、 Sweetviz 和 PandasGUI 。
了解了许多 EDA 软件包,我很想知道它们之间是如何比较的,以及哪些软件包更适合每种情况。
让我们看看每个包是如何工作的,它们的主要特点是什么。
熊猫简介
我以前写了一篇关于熊猫概况的完整文章,但是为了比较起见,让我们从头到尾回顾一下。
将您的基本报告提升到下一个级别
towardsdatascience.com](/fantastic-pandas-data-frame-report-with-pandas-profiling-a05cde64a0e2)
对我来说,熊猫简介是三个软件包中最简单的一个。它提供了一个很好的数据集快速报告。让我们试着看看大熊猫侧写在野外是如何工作的。首先,我们需要安装软件包。
#Installing via pip
pip install -U pandas-profiling[notebook]#Enable the widget extension in Jupyter
jupyter nbextension enable --py widgetsnbextension#or if you prefer via Conda
conda env create -n pandas-profiling
conda activate pandas-profiling
conda install -c conda-forge pandas-profiling#if you prefer installing directly from the source
pip install [https://github.com/pandas-profiling/pandas-profiling/archive/master.zip](https://github.com/pandas-profiling/pandas-profiling/archive/master.zip)#in any case, if the code raise an error, it probably need permission from user. To do that, add --user in the end of the line.
在安装了必要的包之后,我们可以使用 Pandas Profiling 来生成我们的报告。
from pandas_profiling import ProfileReportprofile = ProfileReport(mpg, title='MPG Pandas Profiling Report', explorative = True)profile

熊猫简介报告(GIF 由作者创建)
正如我们在上面看到的,使用 Pandas Profiling 产生了一个快速的报告,有很好的可视化效果,便于我们理解。报告结果直接显示在我们的笔记本中,而不是在单独的文件中打开。让我们来剖析一下大熊猫特征分析给了我们什么。

作者创建的图像
Pandas Profiling 给出了六个部分— 概述、变量、交互、相关性、缺失值、和样本。
Pandas Profiling 的完整部分是变量部分,因为它们为每个变量生成了详细的报告。

作者创造的形象
从上图可以看出,仅仅是那一个变量就有这么多的信息。你可以得到描述性信息和分位数信息。
让我们看看我们能从熊猫档案中得到的其他信息。首先是交互。

作者创建的 GIF
交互作用是我们可以得到两个数值变量之间散点图的部分。
接下来是关联。在这个部分,我们可以得到两个变量之间的关系信息。目前,我们只能得到四个相关分析。

作者创建的 GIF
下一部分是缺失值。你应该已经猜到我们能从这里得到什么信息了。是的,它是每个变量的缺失值计数信息。

作者创建的 GIF
最后是样品部分。这只显示了我们数据集中的样本行。

作者创建的 GIF
这是我们从熊猫报告中能得到的粗略信息。它很简单,但为我们提供了快速重要的信息。
现在,我喜欢熊猫简介的一点是:
- 生成快速报告
 - 每个变量的详细信息
 
虽然有些部分,我感觉不太倾向。有:
- 相当高的内存使用率
 - 变量之间没有太多详细信息,只有相关性和散点图。
 - 样本部分是不必要的。
 
对我来说,熊猫概况对于快速获得我们需要的详细信息非常有用。对于想要掌握我们在处理什么样的数据的人来说已经足够了,但是我们还需要做更详细的信息。
Sweetviz
Sweetviz 是另一个 Sweetviz 是另一个开源 Python 包,可以用一行代码生成漂亮的 EDA 报告。与 Pandas Profiling 不同的是,它的输出是一个完全独立的 HTML 应用程序。
让我们试着安装这个包并生成我们的报告。
#Installing the sweetviz package via pippip install sweetviz
安装完成后,我们可以使用 Sweetviz 生成报告。让我们使用下面的代码来尝试一下。
import sweetviz as sv#You could specify which variable in your dataset is the target for your model creation. We can specify it using the target_feat parameter.my_report = sv.analyze(mpg, target_feat ='mpg')
my_report.show_html()

作者创建的图像
从上图中可以看出,Sweetviz 报告生成的内容与之前的 Pandas Profiling 相似,但使用了不同的用户界面。让我们看看下面 GIF 中的整体 Sweetviz 报告。

作者创建的 GIF
我们知道,当你点击上面 GIF 中的变量时,每个变量都有完整的信息。不过,这些信息也可以通过熊猫档案获得。
如果您还记得以前,我们在代码中设置了目标特性(“mpg”)。这是使用 Sweetviz 的优势之一。我们可以获得关于目标特征的更详细的信息。例如,让我们关注位移变量,并查看右侧的详细报告。

作者创建的图像
我们可以从上面的图像中看到目标特征(“mpg”)和位移变量之间的关系。条形图显示位移分布,而折线图是位移变量后目标特征的平均值。如果我们想知道这两个变量之间的关系,这是一个很好的报告。
在报告的最右侧,我们得到了所有现有变量的数值关联和分类关联的相关信息。有关向我们展示的关联分析信息的更多说明,请参考 Sweetviz 主页。
现在,Sweetviz 的优势不在于针对单个数据集的 EDA 报告,而在于数据集比较。Sweetviz 的主页解释说,Sweetviz 系统是围绕快速可视化目标值和比较数据集而构建的。
有两种方法可以比较数据集;要么我们分割它,比如训练和测试数据集,要么我们用一些过滤器子集化群体。要试用,让我们试试子集化数据。
我想知道当我的数据集是美国汽车的数据与非美国汽车的数据相比有多大的不同。我们可以用下面一行生成报告。
#Subsetting are happen by using the compare_intra. We input the condition in the parameter and the name as well.my_report = sv.compare_intra(mpg, mpg["origin"] == "usa", ["USA", "NOT-USA"], target_feat ='mpg')my_report.show_html()

作者创建的 GIF
从上面的 GIF 可以看出,我们现在比较美国子集数据和非美国子集数据。对我来说,这种报告比较是如此强大,因为我们可以获得人口之间的信息,而不用编码这么多。
让我们更仔细地检查变量。

作者创建的 GIF
从上面的 GIF 中,我们可以了解到,变量被用两种不同颜色(蓝色和橙色)表示的两个子集总体划分。让我们再来看看位移变量。

作者创建的图像
我们可以看到,非美国(橙色)排水量远小于美国排水量。这是我们可以通过比较两个数据集立即得到的信息。
协会怎么样?我们可以通过使用数据集名称上的关联按钮来仔细查看关联。

作者创建的图像

作者创建的 GIF
从上面的 GIF 中,我们可以很容易地得到两个变量之间的关系信息。请参考主页以获得对关联分析的完整理解。
所以,我喜欢 Sweetviz 的是:
- 视觉效果不错
 - 易于理解的统计信息
 - 分析与目标值相关的数据集的能力
 - 两个数据集之间的比较能力
 
对我来说,就数据集和变量比较而言,Sweetviz 是一个比分析熊猫更高级的包。有几件事我对没什么感觉,那就是:
- 变量之间没有可视化,如散点图
 - 该报表将在另一个选项卡中打开
 
虽然我感觉这些东西一点都不差,但是实力,我猜,盖过了弱点。
在我看来,Sweetviz 非常适合用于旨在创建预测模型的比较分析或数据集,因为 Sweetviz 的优势就在这些问题上。
PandasGUI
PandasGUI 不同于我上面解释的前几个包。 PandasGUI 没有生成报告,而是生成了一个 GUI(图形用户界面)数据框,我们可以用它来更详细地分析我们的 Pandas 数据框。
让我们试试这个包裹。首先,我们需要安装 PandasGUI 包。
#Installing via pippip install pandasgui#or if you prefer directly from the sourcepip install git+https://github.com/adamerose/pandasgui.git
安装完成后,让我们看看 PandasGUI 能做什么。要生成数据框 GUI,我们需要运行以下代码。
from pandasgui import show#Deploy the GUI of the mpg dataset
gui = show(mpg)
就像那样,GUI 应该单独显示出来。

作者创建的图像
在这个 GUI 中,您可以做一些事情。主要是过滤,统计 信息,创建变量之间的图,以及重塑你的数据。
作为提醒,您实际上可以根据需要拖动标签。看看下面的 GIF 就知道了。

作者创建的 GIF
现在,让我们仔细看看每个特性,从过滤数据开始。

作者创建的 GIF
使用 PandasGUI 过滤数据需要我们查询条件,就像我们在 Pandas 数据框中写入它一样。看一下上面的例子;我编写“72 年模型”查询。结果是带有勾选框的查询。在这种情况下,如果我们不想再用预期的条件过滤数据,我们需要取消选中该框。
如果您在编写查询时出错了,该怎么办?这很容易;您需要双击您的查询并重写它。就这么简单。
现在,让我们来看看统计选项卡。

作者创建的 GIF
如果我们将从这个 GUI 获得的统计信息与前一个包进行比较,我们在这里获得的信息要比其他两个包少得多。尽管如此,这个选项卡向我们显示了数据集的基本信息。
提醒一下,我们之前所做的任何筛选都会在您在另一个选项卡中进行的下一个活动中出现,所以不要勾选任何您认为不必要的筛选。
从统计开始,我们现在进入图表生成器标签或者绘图 GUI。对我来说,PandasGUI 的优势就在这个标签上。让我告诉你这是为什么。

作者创建的 GIF
从上面的 GIF 中我们可以看到,创建 plot 只是拖拽我们想要的一切。由于绘图资源依赖于 plotly 包,我们可以通过将光标悬停在图形上来浏览图形。
最后,可用的标签是整形标签。在这个选项卡中,我们可以通过创建一个新的数据透视表来重塑或者融化数据集。
pivot 和 melt 函数会产生一个新的表格,如下图所示。

作者创建的图像
作为附加信息,您可以将过滤或整形后的数据导入到新的 CSV 中。您需要从编辑下拉列表中单击导入选择。
如果要将新的 CSV 文件导出到 PandasGUI,也可以单击下图所示的导出选项。

作者创建的图像
现在,我喜欢 PandasGUI 的什么地方:
- 拖放的能力
 - 轻松过滤查询选择
 - 快速剧情创作
 
虽然,我现在有一些低谷,那就是:
- 我们能得到的统计信息很少
 - 没有生成自动报告。
 
在我看来,PandasGUI 是一个很棒的包,尤其是对于喜欢用自己的方式分析数据的人来说。毕竟,这个软件包适合进行深入分析。
我认为 PandasGUI 的目的更多的是我们自己的探索,而不是自动生成报告。然而,它仍然可以与前两个包相媲美,因为这些包在 EDA 过程中对我们有所帮助。
结论
Pandas Profiling、Sweetviz 和 PandasGUI 是为简化 EDA 处理而开发的令人惊叹的软件包。在不同的工作流程中,每个包都有自己的优势和适用性。如果我需要总结我的比较,那就是:
- Pandas Profiling 适合对单个变量进行快速分析生成,
 - Sweetviz 适用于数据集和目标特征之间的分析,
 - PandasGUI 适用于具有手动拖放功能的深入分析。
 
那是我对这三个 EDA 包的比较;我不会推荐什么适合你的工作,因为只有你自己知道。
如果你想了解更多关于我对其他 EDA 包的评论,你可以看看下面的文章。
通过基于一行建议的数据探索,轻松探索您的数据
towardsdatascience.com](/quick-recommendation-based-data-exploration-with-lux-f4d0ccb68133)
如果您喜欢我的内容,并希望获得更多关于数据或数据科学家日常生活的深入知识,请考虑在此订阅我的简讯。
如果您没有订阅为中等会员,请考虑通过我的介绍订阅。
Python 中的数据分组
检查“困难”的任务,并尝试给出替代的解决方案
按列对记录进行分组是数据分析的常见需求。这样的场景包括统计公司各个部门的员工,分别计算各个部门男女员工的平均工资,计算不同年龄段员工的平均工资。熊猫有分组功能,可以方便地处理大部分分组任务。但是该职能部门发现有些任务很难管理。在这里,让我们检查这些“困难”的任务,并尝试给出替代的解决方案。
分组是熊猫最重要的功能之一。它用于根据拆分-应用-组合策略对记录进行分组和汇总。下图显示了工作流程:

作者图片
I .按单个字段分组和聚合
您按特定字段对记录进行分组,然后对每个组执行聚合。
这是上述策略最简单的用法。例如,根据员工信息计算每个部门的员工数:
问题分析:以 department 为关键字,按其对记录进行分组,统计每组中的记录。
以下是部分员工信息:

Python 脚本:
import pandas as  pd#Import data
employee =  pd.read_csv("Employees.csv")#Grouping and perform count over each group
dept_emp_num =  employee.groupby('DEPT')['DEPT'].count()print(dept_emp_num)
解释:groupby('DEPT ')按部门对记录进行分组,count()计算每组中的雇员数。
II 按多个字段分组和聚合
您按多个字段对记录进行分组,然后对每个组执行聚合。
我们以类似的方式处理它。根据前一个实例中相同的员工信息计算每个部门中男性和女性员工的平均工资。
问题分析:分组键有两个,部门和性别。我们将组合键作为一个整体来进行分组和聚合。
Python 脚本:
import pandas as pdemployee = pd.read_csv("Employees.csv")#Group by two keys and then summarize each group
dept_gender_salary =  employee.groupby(['DEPT','GENDER'],as_index=False).SALARY.mean()print(dept_gender_salary)
解释:表达式 groupby(['DEPT ',' GENDER'])将两个分组字段作为列表形式的参数。表达式 as_index 使用 True 或 False 指定是否将分组字段用作索引(这里 False 表示不将它们用作索引)。mean()函数计算平均工资。
III 按计算列分组和聚合
分组键不是显式数据,需要根据已有数据进行计算。这样的键称为计算列。例如,要计算不同年份员工的平均工资:
问题分析:员工信息中没有年份一栏。我们需要根据员工的生日来计算,按计算列对记录进行分组,并计算平均工资。
Python 脚本:
import pandas as pdimport numpy as npemployee = pd.read_csv("Employees.csv")#Convert the BIRTHDAY column into date format
employee['BIRTHDAY']=pd.to_datetime(employee['BIRTHDAY'])#Calculate an array of calculated column values, group records by them, and calculate the average salary
years_salary =  employee.groupby(np.floor((employee['BIRTHDAY'].dt.year-1900)/10)).SALARY.mean()print(years_salary)
说明:由于原始数据中不存在年值,Python 使用 NP . floor((employee[' BIRTHDAY ']. dt . year-1900)/10)来计算年列,按新列对记录进行分组,并计算平均工资。
四多重集合
您可以对多列中的每一列执行一种类型的聚合操作,或者对一列或多列执行几种类型的聚合操作。
1.多列中的每一列都有一个聚合
对多列中的每一列执行一种类型的聚合。计算每个部门的雇员数和平均工资,例如:
问题分析:count 聚合在 EID 列上,average 聚合在 salary 列上。每个列都有自己的一个聚合。
Python 脚本:
import pandas as pdemployee = pd.read_csv("Employees.csv")#Group records by DEPT, perform count on EID and average on SALARY
dept_agg =  employee.groupby('DEPT',as_index=False).agg({'EID':'count','SALARY':'mean'})#Rename the columns
print(dept_agg.rename(columns={'EID':'NUM','SALARY':'AVG_SALARY'}))
解释:Pandas agg()函数可以用来处理这类计算任务。相关的列和涉及的聚合操作以字典的形式传递给函数,其中列是键,聚合是值,以完成聚合。
2.一根色谱柱上的多种聚合
您在单个列上执行多种类型的聚合。对于之前的任务,我们也可以把工资加起来,然后算出平均值。这样,我们在 salary 列上执行两个聚合,count 和 average。
Python 脚本:
import pandas as  pdemployee =  pd.read_csv("Employees.csv")#Perform count and then average on SALARY column
dept_agg = employee.groupby('DEPT').SALARY.agg(['count','mean']).reset_index()#Rename columns
print(dept_agg.rename(columns={'count':'NUM','mean':'AVG_SALARY'}))
说明:我们可以把聚合操作组合成一个列表,并把它作为参数传递给 agg()函数。
3.多个色谱柱上的多个聚合
您汇总了多个列,在此期间,单个列上有多个聚合。聚合操作可以由用户定义。
以获取每个部门的员工人数、平均工资和最大年龄为例:
问题分析:统计员工人数,计算平均工资,都是对工资列(一列多个合计)的操作。查找最大年龄需要对生日列进行自定义操作。
Python 脚本:
import pandas as pdimport datetime#The user-defined function for getting the largest age
def max_age(s):
    #Year
    today = datetime. datetime.today().year
    #Get ages
    age = today-s.dt.year return age.max()employee = pd.read_csv("Employees.csv")employee['BIRTHDAY']=pd.to_datetime(employee\['BIRTHDAY'\])#Group records by DEPT, perform count and average on SALARY, and use the user-defined max_age function to get the largest age
dept_agg = employee.groupby('DEPT').agg({'SALARY':['count','mean'],'BIRTHDAY':max_age})#Rename columns
dept_agg.columns = ['NUM','AVG_SALARY','MAX_AGE']print(dept_agg.reset_index()) 
说明:要汇总的列和聚合操作以字典的形式通过参数传递给函数。对于需要多个聚合操作的列,我们需要将这些操作组合成一个列表,用作字典值。
复制分组和汇总结果
您可以将每个聚合结果扩展到相应组的长度。这相当于将聚合结果复制到其组中的所有行。向员工信息中添加包含每个部门平均工资的新列,例如:
问题分析:按部门对记录进行分组,计算每个部门的平均工资,在保持原有顺序的情况下,将每个平均值填充到相应的组中。
Python 脚本:
import pandas as pdemployee = pd.read_csv("Employees.csv")#Group records by DEPT and calculate average on SLARYemployee['AVG_SALARY'] = employee.groupby('DEPT').SALARY.transform('mean')print(employee)
说明:按部门对记录进行分组,并计算每组的平均工资。transform()函数计算每个组的聚合,返回结果并按照原始索引的顺序将其填充到所有行中。这确保了记录保持原始顺序。
VI 处理分组子集
您可以在每个组中执行一个或多个非聚合操作。例如,为了对每个组进行排序,我们关心的是记录的顺序,而不是集合。要按聘用日期以升序对每个部门的记录进行排序,例如:
问题分析:按部门对记录进行分组,并在每个组中循环,按雇用日期对记录进行排序。
Python 脚本:
import pandas as pdemployee = pd.read_csv("Employees.csv")#Modify hire date format
employee['HIREDATE']=pd.to_datetime(employee['HIREDATE'])#Group records by DEPT, sort each group by HIREDATE, and reset the index
employee_new = employee.groupby('DEPT',as_index=False).apply(lambda x:x.sort_values('HIREDATE')).reset_index(drop=True)print(employee_new)
说明:要对每个组中的记录进行排序,我们可以使用 apply()函数和 lambda 的组合。lambda 表达式通过组进行循环,使用 sort_values()函数对每个组中的记录进行排序,并返回排序结果。
还有更复杂的计算目标。例如,要找出每个部门中年龄最大的员工和年龄最小的员工之间的工资差异:
问题分析:将记录按部门分组,定位最年长的员工记录和最年轻的员工记录,计算他们的工资差异。
Python 脚本:
import pandas as pd#salary_diff(g)function calculates the salary difference over each group
def salary_diff(g):
    #The index of the eldest employee record
    max_age = g['BIRTHDAY'].idxmin() #The index of the youngest employee record
    min_age = g['BIRTHDAY'].idxmax() #Calculate the salary difference
    diff = g.loc[max_age]['SALARY']-g.loc[min_age]['SALARY'] return diffemployee = pd.read_csv("Employees.csv")employee['BIRTHDAY']=pd.to_datetime(employee['BIRTHDAY'])#Group by DEPT and use a user-defined function to get the salary difference
salary_diff = employee.groupby('DEPT').apply(salary_diff)print(salary_diff) 
解释:该脚本使用 apply()和一个用户定义的函数来获取目标。apply()将分组结果作为参数传递给用户定义的函数。自定义函数 salary_diff()中的参数 g 本质上是熊猫 data frame 格式的一个数据帧,这里是分组结果。该脚本通过参数获取最老员工记录的索引和最年轻员工记录的索引,然后计算 salary 字段的差异。
概要:
掌握 Pandas groupby 方法对处理数据分析任务特别有帮助。
让我们进一步看看 Pandas groupby 的使用,尽管现实世界中的问题来自堆栈溢出。
VII 基于职位的分组
您按位置对记录进行分组,也就是说,使用位置作为键,而不是按某个字段。这种情况包括将每三行放入同一组,并将奇数位置的行放入一组,偶数位置的行放入另一组。下面是一个例子:
来源:https://stack overflow . com/questions/59110612/pandas-group by-mode-every-n-rows
以下是部分源数据:
time     a      b
0       0.5    -2.0
1       0.5    -2.0
2       0.1    -1.0
3       0.1    -1.0
4       0.1    -1.0
5       0.5    -1.0
6       0.5    -1.0
7       0.5    -3.0
8       0.5    -1.0
我们希望每隔三行对数据进行分组和组合,并保持每组中每列的模式。预期结果如下:
time     a      b
2       0.5    -2.0
5       0.1    -1.0
8       0.5    -1.0
问题分析:这个分组任务与列值无关,但涉及位置。我们通过位置执行整数乘法来获得一个计算列,并将其用作分组条件。
Python 脚本:
import pandas as pdimport numpy as npdata = pd.read_csv("group3.txt",sep='\\t')#Group records by the calculated column, calculate modes through the cooperation of agg function and lambda, and get the last mode of each column to be used as the final value in each groupres = data.groupby(np.arange(len(data))//3).agg(lambda x: x.mode().iloc[-1])print(res)
说明:表达式 NP . arange(len(data))//3 生成一个计算列,其值为[0 0 1 1 1 2 2]。该脚本使用它作为每三行对数据进行分组的键。表达式 agg(lambda x: x.mode())从每个组中的每一列获取模式。在第一组中,时间列中的模式是[0,1,2],a 和 b 列中的模式分别是[0.5]和[-2.0]。然后,该脚本使用 iloc[-1]来获取它们的最后模式,以用作最终的列值。
VIII 按变化值分组
您可以根据特定字段中的值是否更改来对有序数据进行分组。也就是说,每次出现新值时,都会创建一个新组。这里有一个例子:
来源:https://stack overflow . com/questions/41620920/group by-conditional-sum-of-adjacent-rows-pandas
以下是部分原始数据:
duration  location  user
0 10       house    A
1 5        house    A
2 5        gym      A
3 4        gym      B
4 10       shop     B
5 4        gym      B
6 6        gym      B 
数据按用户分组后,对位置值连续相同的持续时间值求和,并在位置值改变时对持续时间执行下一次求和。以下是预期结果:
duration  location  user
15        house     A
5         gym       A
4         gym       B
10        shop      B
10        gym       B
问题分析:订单是为位置列导入的。具有连续相同位置值的记录被放入同一个组,一旦值改变,一个记录被放入另一个组。当用户为 B 时,第 4 行(其索引为 3)中的位置值为[健身房、商店、健身房、健身房]。这里我们不应该把三个健身房放在一个组里,而应该把第一个健身房放在一个单独的组里,因为第一个健身房之后的位置值是商店,这是一个不同的值。商店应该另设一个小组。然后,其他两个健身房应该在同一组,因为他们一直是相同的。所以用户 B 的分组结果应该是[[健身房],[商店],[健身房,健身房]]。这就是为什么我们不能用 df.groupby(['user ',' location']).duration.sum()来得到结果。相反,我们需要一个计算列作为分组条件。
他们的 Python 脚本:
import pandas as pd#Generate data for computation
df = pd.DataFrame({'user' : ['A', 'A', 'A', 'B', 'B', 'B','B'], 'location' : ['house','house','gym','gym','shop','gym','gym'], 'duration':[10,5,5,4,10,4,6]})#Create a calculated column
derive = (df.location != df.location.shift()).cumsum()#Group records by user, location and the calculated column, and then sum duration values
res = df.groupby(['user', 'location', derive], as_index=False, sort=False)['duration'].sum()print(res)
解释:计算列 derive 通过在每次位置值发生变化之前累计位置值来获取其值。累积值为[1 1 2 2 3 4 4]。然后按用户、位置和计算出的数组对原始数据进行分组,并对持续时间进行求和。
IX 按条件分组
当对有序数据进行分组时,只要某个字段的值满足指定的条件,就会创建一个新组。下面是一个例子:
来源:https://stack overflow . com/questions/62461647/choose-random-rows-in-pandas-data fram
以下是部分原始数据:
ID            code
333_c_132     x
333_c_132     n06
333_c_132     n36
333_c_132     n60
333_c_132     n72
333_c_132     n84
333_c_132     n96
333_c_132     n108
333_c_132     n120
999_c_133     x
999_c_133     n06
999_c_133     n12
999_c_133     n24
998_c_134     x
998_c_134     n06
998_c_134     n12
998_c_134     n18
998_c_134     n36
997_c_135     x
997_c_135     n06
997_c_135     n12
997_c_135     n24
997_c_135     n36
996_c_136     x
996_c_136     n06
996_c_136     n12
996_c_136     n18
996_c_136     n24
996_c_136     n36
995_c_137     x 
我们希望在代码列中的每两个 x 值之间得到一个随机行。
预期结果如下:
333_c_132     n06
999_c_133     n12
998_c_134     n18
997_c_135     n36
996_c_136     n18
问题分析:从两个 x 值中随机获取一行,我们可以根据代码值是否为 x 对行进行分组(即每当代码值变为 x 时创建一个新组),从当前组中随机获取一行。所以我们仍然需要一个计算列作为分组键。
Python 脚本:
import pandas as pddf = pd.read_csv("data.txt")#Generate a calculated column
derive = df.code.eq('x').cumsum()#Group records by the calculated column and get a random record from each groupthrough the cooperation of apply function and lambda
res=df[df.code.ne('x')].groupby(derive).apply(lambda  x : x.sample(1))#Reset the index
res=res.reset_index(level=0, drop=True)print(res)
解释:code.eq(x)当 code 为 x 时返回 True,当 code 不是 x 时返回 False,cumsum()累加真值和假值的个数,生成计算列[1 1 1 1 1 1 1 1 1 2 2…]。然后,该脚本查找 code 为 x 的记录,根据这些 x 值对记录进行分组,并从每个组中获得一个随机记录。
概要:
在上述所有例子中,原始数据集根据指定的条件被分成若干子集,并具有以下两个特征:
1)没有子集是空的;
2)原始数据集中的每个成员属于且只属于一个子集。
我们称这种类型的分组为全分。也有偏科的。
以下是一些例子。
x 对齐分组
路线编组有一个基础集。它将待分组集合的成员的属性(字段或表达式)与基本集合的成员进行比较,并将与基本集合的成员匹配的成员放入同一子集中。子集的数量与基本集中的成员数量相同。路线分组有三个特征:
1)可能存在空的子集(例如,基本集合的一个或多个成员不存在于要分组的集合中);
2)可能存在未被放入任何组的待分组集合的成员(例如,它们并不重要到包括在基本集合中);
3)待分组集合中的每个成员最多属于一个子集。
1.空子集
一家公司想知道每个部门员工的准确人数。如果一个部门没有男性员工或女性员工,它会将他们的人数记录为 0。
问题分析:如果我们直接按部门和性别分组数据,也就是 groupby(['DEPT ',' GENDER']),那么一个部门中没有女性员工或者男性员工的员工都会被放到一个组中,缺失性别的信息就会缺失。很容易想到一个替代方案。该解决方案按部门对记录进行分组,生成一个[男性,女性]基集以左连接每个组,按性别对每个连接结果进行分组,然后计算男性和女性员工的数量。这将确保每个小组都包括女性雇员和男性雇员。
Python 脚本:
import pandas as pd#Alignment grouping function
def align_group(g,l,by):
    #Generate the base dataframe set and use merge function to perform the alignment grouping
    d = pd.DataFrame(l,columns=[by]) m = pd.merge(d,g,on=by,how='left')return m.groupby(by,sort=False)employee = pd.read_csv("Employees.csv")#Define a sequence
l = ['M','F']#Group records by DEPT, perform alignment grouping on each group, and perform count on EID in each subgroupres = employee.groupby('DEPT').apply(lambda x:align_group(x,l,'GENDER').apply(lambda s:s.EID.count()))print(res)
解释:
用户自定义函数 align _ groupuses 使用 merge()函数生成基集,并对基集和要分组的集执行左连接,然后按合并列对每个连接结果集进行分组。记录按部门分组后,apply()函数和 lambda 表达式的配合通过自定义函数对每组进行对齐分组,然后对 EID 列进行计数。(注意:您不应该对性别执行计数,因为在合并操作期间,所有性别成员都会保留。当有一个空的子集时,对性别计数的结果将是 1,而其余的列在左连接时将被记录为 null。这将导致 EID 计数的结果为零)。
2.未放入任何组的待分组集合的成员
任务是按指定的部门['管理','人力资源','营销','销售']对记录进行分组,计算它们的员工数,并按指定的部门顺序返回结果。
问题分析:我们可以使用 left join 过滤掉未包含在指定部门集合中的记录。
Python 脚本:
import pandas as pd#Alignment grouping function
def align_group(g,l,by): d =   pd.DataFrame(l,columns=[by]) m =   pd.merge(d,g,on=by,how='left') return   m.groupby(by,sort=False)employee = pd.read_csv("Employees.csv")#The specified subset of departments
sub_dept = ['Administration', 'HR', 'Marketing', 'Sales']#Use the alignment function to group records and perform count on EID
res =  align_group(employee,sub_dept,'DEPT').apply(lambda x:x.EID.count())print(res)
说明:Pandas 并不直接支持对齐分组功能,所以实现起来比较迂回。此外,使用合并函数会导致性能下降。
XI 计数分组
枚举分组指定一组条件,通过将待分组集合的每个成员作为参数传递给它们来计算条件,并将使条件为真的记录放入同一子集中。结果集中的子集和指定的条件有一对一的关系。枚举分组的一个特点是,要分组的集合中的成员可以放入多个子集中。
这里有一个例子
任务是根据雇佣期限对员工进行分组,雇佣期限为[雇佣期限<5 years, 5 years<= employment duration<10 years, employment duration> =10 年,雇佣期限> =15 年],并统计每组中的女性和男性员工(列出每个枚举条件的所有符合条件的员工记录,即使他们也满足其他条件)。
问题分析:列举条件任职年限> =10 年和任职年限> =15 年有重叠期间。在公司工作了至少 15 年的员工也符合另一个条件。计算列不支持将一条记录放入多个组中。我们需要遍历所有条件,为每个条件搜索符合条件的记录,然后执行计数。
import pandas as pdimport datetime#The function for converting strings into expressions
def eval_g(dd:dict,ss:str): return   eval(ss,dd) emp_file = 'E:\\txt\\employee.txt'emp_info = pd.read_csv(emp_file,sep='\\t')employed_list = ['Within five years','Five to ten   years','More than ten years','Over fifteen years']#Grouping conditions
employed_str_list = ["(s<5)","(s>=5) & (s<10)","(s>=10)","(s>=15)"]today = datetime.datetime.today().yeararr = pd.to_datetime(emp_info['HIREDATE'])#Calculate employment durations
employed = today-arr.dt.yearemp_info['EMPLOYED']=employeddd = {'s':emp_info['EMPLOYED']}group_cond = []#Loop through grouping conditionsfor n in range(len(employed_str_list)): #Group records by conditions
    emp_g = emp_info.groupby(eval_g(dd,employed_str_list[n])) #Grouping indexes
    emp_g_index = [index for index in emp_g.size().index] #If there are not eligible records Then the number of female or male employees are 0 if True not in emp_g_index: female_emp=0 male_emp=0
    #If there are records meeting the current condition Then create a group for them And count the female and male employees else: group =   emp_g.get_group(True) sum_emp = len(group) female_emp = len(group[group['GENDER']=='F']) male_emp = sum_emp-female_emp group_cond.append([employed_list[n],male_emp,female_emp])#Summarize the count results for all conditionsgroup_df = pd.DataFrame(group_cond,columns=['EMPLOYED','MALE','FEMALE'])print(group_df)
说明:已雇佣是根据雇佣日期列新计算的雇佣期限列。用户定义的函数 eval_g()将枚举条件转换为表达式。列举条件<5, for instance, is equivalent to the eval_g(dd,ss) expression emp_info[‘EMPLOYED’]<5. The new calculated column value will then be used to group the records. The script loops through the conditions to divide records into two groups according to the calculated column. get_group(True) gets eligible groups. Finally the script uses concat() function to concatenate all eligible groups.
汇总
Python 可以优雅地处理大多数分组任务。在处理基于顺序的分组任务时,它需要生成一个满足分组条件的计算列,例如按更改的值/条件分组。有点复杂。当面对排列分组和枚举分组任务时,它变得很尴尬,因为它需要采取非常迂回的方式,例如使用合并操作和多重分组。那很费时间和精力。熊猫在处理分组任务方面仍有弱点
esProc SPL 巧妙地处理分组任务。esProc 是专门的数据计算引擎。它所基于的语言 SPL 提供了丰富的分组函数,以更加一致的代码风格方便地处理分组计算。
两个 esProc 分组函数 group()和 group()用于实现按组聚合和子集处理。他们能够以简洁的方式处理上述六个简单的分组问题:

Python 在处理它们时也很方便,但通过涉及许多其他函数,包括 agg、transform、apply、lambda 表达式和用户定义的函数,它具有不同的编码风格。SPL 以组的形式采取一致的编码风格(x;y)和组(x)。(y)。
Python 脚本在处理以下三个涉及计算列的问题时有点复杂。基于有序集的 SPL 通过提供处理基于有序的分组任务的选项,能够保持优雅的编码风格

根据是需要分组后聚合还是希望进一步处理每个子集中的数据,可以选择使用组或组函数来处理分组和聚合任务。
Python 在通过使用合并函数和多重分组操作来管理最后两个类型组任务(对齐分组和枚举分组)时确实有些笨拙。SPL 有专门的对齐分组函数 align()和枚举分组函数 enum(),以保持其优雅的编码风格。

Python 的致命弱点是对大数据分组的处理(数据放不进内存)。该语言需要外部存储读/写和哈希分组。对于一个非专业程序员来说,用 Python 来完成几乎是不可能的。阅读Python 如何处理大文件了解更多信息。
那篇文章指出了 Python 在计算大数据(包括大数据分组)方面的问题,并介绍了 esProc SPL 的游标机制。该机制提供了 group 函数和 groupx()函数,以优雅的方式处理大数据计算。
数据总是脏的
它讲故事的能力取决于你清洗它的能力。

统计学 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 网站下载,并在几分钟内部署到笔记本电脑中。
数据建模:概述
本文概述了软件应用程序中的数据建模。它描述了常用的术语,并使用一个零售销售案例研究来解释一步一步的过程。

如果你观察世界上的任何软件应用程序,你会发现在最基本的层面上,它将处理数据的组织、操作和表示,以满足业务需求。
一个数据模型是表达和交流业务需求的概念表示。它直观地表示了数据的性质、管理数据的业务规则以及数据在数据库中的组织方式。
数据建模的过程可以比作建造房子的过程。假设某公司 ABC 需要建一个招待所(数据库)。它调用一个建筑架构师(数据建模师)并解释它的建筑需求(业务需求)。建筑设计师(数据建模师)开发计划(数据模型)并将其交给 ABC 公司。最后,ABC 公司召集土木工程师(数据库管理员和数据库开发人员)来建造客房(数据库)
数据建模中的关键术语:
实体和属性: 实体是业务环境中的“事物”,我们希望存储关于它们的数据,如产品、客户、订单等。属性提供了一种组织和构造数据的方法。例如,我们需要存储我们销售的产品的某些信息,如售价或可用数量。这些数据是产品实体的属性。实体通常表示数据库的表格,而属性是这些表格的列。
关系: 实体之间的关系描述一个实体如何链接到另一个实体。在数据模型中,实体可以是以下任何一种关系:一对一、多对一或多对多。这就是所谓的给定实体相对于另一个实体的基数。
交集实体(参照表): 当实体间存在多对多关系时,可以用交集实体解析为多对一和一对多关系。一个简单的例子是:有两个实体,电视节目和人。每个电视节目可以由一个或多个人观看,而一个人可以观看一个或多个电视节目:

这可以通过引入新的相交实体“查看记录”来解决,如下所示:

ER 图: 表示实体及实体间关系的图称为 ER 图。ER 图可以采用概念数据模型、逻辑数据模型或物理数据模型的形式。
概念数据模型: 概念数据模型包括所有主要实体和关系,不包含太多关于属性的详细信息,通常用于初始规划阶段。一个例子:

逻辑数据模型: 它是概念数据模型的扩展。它包括代表业务信息和定义业务规则的所有实体、属性、键组和关系。一个例子:

物理数据模型: 它包括数据库物理实现所需的所有表、列、关系、数据库属性。数据库性能、索引策略、物理存储和反规范化是物理模型的重要参数。一个例子:

数据建模开发周期:

关系与维度建模:
根据业务需求,您的数据模型可以是关系型的,也可以是维度型的。关系模型是一种旨在消除数据冗余的设计技术。数据被分成许多离散的实体,每个实体都成为关系数据库中的一个表。这些表格通常被标准化为第三范式。在 OLTP 应用程序中,遵循这种方法。
在仓库需求的情况下,数据被反规范化以提高性能。在维度模型中,数据被分为维度和事实,其设计目标是用户可理解性、查询性能和对变化的弹性。
案例研究:
ABC 公司在八个州拥有 200 家杂货店。每个商店都有不同的部门,如日用品、化妆品、冷冻食品、乳制品等。每家商店的货架上大约有 20000 种产品。单个产品被称为库存单位(SKU)。约 6000 个 SKU 来自外部制造商,产品包装上印有条形码。这些条形码被称为通用产品代码(UPCs)。销售点(POS)系统在两个地方收集数据:测量顾客外卖的前门和供应商送货的后门。
在杂货店,管理关心的是订购、储存和销售产品的物流,同时最大化利润。一些促销方案,如临时降价、报纸广告、展示等,也在不断增加。
设计一个数据模型来分析这个连锁杂货店的运作。
解决方案:
第一步:收集业务需求:
管理层希望更好地了解 POS 系统捕获的客户购买情况。该模型应该允许分析什么产品在什么日子在什么促销条件下在什么商店销售。此外,这是一个仓储环境,因此需要一个维度模型。
步骤 2:实体的识别:
在维度模型的情况下,我们需要识别我们的事实和维度实体。在开发模型之前,需要明确所需数据的粒度。在这种特殊情况下,我们需要颗粒是 POS 交易上的单个行项目。根据要求,我们需要在特定的一天,在特定的促销方案下,查看特定商店中特定产品的数据。这给了我们所需尺寸的概念:
日期维度
产品尺寸
店面尺寸
促销维度
要计算的数量(如销售数量、利润等)将在销售事实表中获取。
第三步:概念数据模型:
将根据收集的关于实体的信息建立一个初步的数据模型。在我们的例子中,它将如下所示:

步骤 4:属性的最终确定和逻辑数据模型的设计
现在,需要最终确定已识别的事实表和维度表的属性。在我们的例子中,以下属性已经完成:
日期维度:


产品:

店铺:

晋级:

销售事实:
交易编号
销售数量:(例如蔬菜汤面罐头的数量)
销售金额:销售数量*单价
成本金额:供应商收取的产品成本金额
毛利金额:销售金额-成本金额
逻辑数据模型将看起来像:

步骤 5:在数据库中创建物理表:
在数据建模工具的帮助下,或者通过编写定制脚本,现在可以在数据库中创建物理表。
数据建模是软件应用程序设计中最重要的任务之一。它为如何组织、存储、检索和呈现数据奠定了基础。
新生婴儿的数据建模和预测
请阅读我在产假期间与我的新生儿一起探索数据建模的经历

机器学习面临的挑战之一是处理数据。人们常说,数据建模是 90%的数据收集/清理和 10%的模型构建。因此,收集能够提供丰富见解的正确数据是一个巨大的难题。
在我生孩子的前几周,我和一个朋友聊了聊我在休产假期间可以做的一些科技项目。毕竟,我要生孩子了,我可以收集她周围的大量数据!!我们认为的一些想法是:
在一段时间内拍摄婴儿指纹的快照,并分析它们是否以及如何变化
收集不同婴儿哭声的音频剪辑,并使用机器学习模型对不同哭声的含义进行分类。
嗯,这两个想法对我来说都失败了。我简直不能正确地提取我孩子的指纹。每次她哭的时候,录音剪辑就更难了。
另一个想法是用一个预测模型来找到她大便和小便的模式。我开始收集出生后几周内的尿布数据。然而,我意识到大便和小便的模式每周都在变化,这取决于婴儿摄入的母乳和配方奶的量。随着年龄的增长,情况也在发生变化。当我问医生不准确的原因时,她大声说道:“很明显,她的便便周期会改变。会有一些天她完全不便便,没什么好惊讶的”。我意识到很难对这么小的婴儿的便便频率进行预测分析。我的想法泡汤了!
我意识到仅仅是我孩子的数据不足以做出任何预测。在网上搜索时,我发现了一个新生儿体重的数据集。数据集包含婴儿的特征,如出生日期、性别、出生时间等,以及关于怀孕的数据点,如产前、生母的医疗状况,如妊娠糖尿病、贫血等,以及父母的病史,包括数据点,如种族、出生子女数、饮酒和吸烟习惯。总的来说,数据集[1]有 131422 个数据点,我觉得对于一个预测模型来说足够了。目标是根据怀孕周预测婴儿的出生体重。这是一个重要的目标,因为分娩时的大尺寸婴儿可能会增加新生儿及其母亲受伤的风险[2]。因此,医生对出生体重的预测越准确,分娩就越容易。
虽然超声波是医生预测婴儿体重的常用方法,但他们往往会有 10-15%的差异。我决定使用机器学习来预测出生体重。
第一步:准备工作空间
我从 kaggle 链接导入了所需的库并加载了数据集“baby-weights-dataset2.csv”。

第二步:数据探索
这一步有助于我们理解目标可变出生体重——其平均值、标准偏差、最小值和最大值、中值等。我们还绘制了出生体重变量的直方图,以了解其性质。我们还计算目标变量的偏斜度和峰度

接下来,我们从训练数据集中识别分类值,并打印定性和定量列。此时,我们处理缺失的值,并将它们设置为“缺失”。我们还采用定性变量 HISPMOM 和 HISPDAD 并对其进行编码。
最后,我们使用 Spearman 的等级相关性来寻找变量之间的相关性,并在 Correlated_Feature 列表中选取最相关的特征,并将其用于进一步的建模。一些最相关的特征是妊娠完成周数、母亲体重增加量、母亲年龄、父母种族和产前检查次数。

第三步:测试和训练集
接下来,我们使用下面的代码将 80%的数据分割成训练集,而将 20%的数据分割成测试集。test_size 变量是我们实际指定测试集比例的地方。
这里,“训练”集是用于创建机器学习模型的数据文件,而“测试”集是我们使用模型来预测目标变量的数据文件。ATrain 和 ATest 分割相关特征,而 BTrain 和 BTest 分割出生体重变量。

然后,我们将归一化技术应用于我们的训练和测试特征数据集。
第四步:模型创建
把数据拆分成训练集和测试集之后,最后,就是训练我们算法的时候了。为此,我们需要设置种子并使用θ来计算预测值并改进模型。这一步也可以使用 scikit 学习线性回归库
模型公式:

第五步:预测出生体重
最后,让我们使用我们在步骤 4 中拟合的回归模型,使用该模型来预测每个测试数据集的出生体重目标变量。我使用误差函数检验了模型的表现:

我用平均 RMSE 和标准差来评估线性模型。RMSE 是更受欢迎的指标,通常与标准差一起用作解释模型的主要指标。
平均 RMSE 在 1.07 左右,我觉得对这个数据集来说已经不错了。此外,标准偏差约为 2.64,可通过进一步调整特性来改善。虽然仍然有一些足够好的误差,这些出生体重预测可能有助于医生在分娩过程中更准确地估计婴儿的大小。
当我休完产假回到办公室时,我期待着分享这一模式的见解。
这个模型的代码和数据文件被添加到这个 Github 库中。如果你觉得这有用,请与你的朋友和同事分享。欢迎在评论区分享你的想法和反馈。
参考资料:
- https://www.kaggle.com/c/csci-ml-s19-pa1/overview
 - https://www . webmd . com/g00/baby/news/2002 09 26/you-can-predict-your-新生儿-体重?i10c . ua = 1&i10c . encreferrer = ahr 0 CHM 6 ly 93d 3c uz 29 vz 2 xllmnvbs 8% 3d&i10c . dv = 1
 
音乐流应用程序的数据建模
Udacity 数据工程师纳米学位
创建一个 Postgres 数据库,其中的表用于优化歌曲播放分析的查询

潘卡杰·帕特尔在 Unsplash 上的照片
介绍
我已经加入了 Udacity 数据工程师 Nanodegree。该计划由许多现实世界的项目组成。在这个项目中,我在一家名为“Sparkify”的虚构数据流公司担任数据工程师。这是一家初创公司,希望分析他们在新的音乐流媒体应用程序上收集的歌曲和用户活动数据。分析团队对了解用户在听什么歌特别感兴趣。目前,他们没有一种简单的方法来查询他们的数据,这些数据位于应用程序上用户活动的 JSON 日志目录中,以及应用程序中歌曲的 JSON 元数据目录中。
他们想要一个数据工程师来创建一个 Postgres 数据库,其表旨在优化歌曲播放分析的查询,并让我参与这个项目。我的角色是为这个分析创建一个数据库模式和 ETL 管道。我已经通过运行 Sparkify 的分析团队给我的查询测试了我的数据库和 ETL 管道,并将我的结果与他们的预期结果进行了比较。
项目描述
在这个项目中,我应用了我在 Postgres 数据建模方面学到的知识,并使用 Python 构建了一个 ETL 管道。我为特定分析焦点的星型模式定义了事实表和维度表,并使用 Python 和 SQL 编写了一个 ETL 管道,将数据从两个本地目录中的文件传输到 Postgres 的这些表中。
歌曲数据集
第一个数据集是来自百万首歌曲数据集的真实数据子集。每个文件都是 JSON 格式的,包含关于一首歌和这首歌的艺术家的元数据。这些文件按每首歌曲曲目 ID 的前三个字母进行分区。例如,以下是该数据集中两个文件的文件路径。
song_data/A/B/C/TRABCEI128F424C983.json
song_data/A/A/B/TRAABJL12903CDCF1A.json
下面是一个歌曲文件 TRAABJL12903CDCF1A.json 的示例。
{"num_songs": 1, "artist_id": "ARJIE2Y1187B994AB7", "artist_latitude": null, "artist_longitude": null, "artist_location": "", "artist_name": "Line Renaud", "song_id": "SOUPIRU12A6D4FA1E1", "title": "Der Kleine Dompfaff", "duration": 152.92036, "year": 0}
日志数据集
第二个数据集由这个事件模拟器基于上面数据集中的歌曲生成的 JSON 格式的日志文件组成。这些根据指定的配置模拟音乐流媒体应用程序的活动日志。
您将使用的数据集中的日志文件按年份和月份进行分区。例如,以下是该数据集中两个文件的文件路径。
log_data/2018/11/2018-11-12-events.json
log_data/2018/11/2018-11-13-events.json
下面是日志文件 2018–11–12-events . JSON 中数据的示例。

如果您想查看 log_data 文件中的 JSON 数据,您需要创建一个 pandas 数据帧来读取数据。记得先导入 JSON 和 pandas 库。
df = pd.read_json(filepath, lines=True)
例如,df = pd.read_json('data/log_data/2018/11/2018-11-01-events.json', lines=True)将读取数据文件 2018-11-01-events.json。
如果你需要复习 JSON 文件格式,这里有一个有用的视频。
歌曲分析的图式
使用歌曲和日志数据集,我创建了一个针对歌曲播放分析查询优化的星型模式。这包括以下表格。
事实表
歌曲播放 —日志数据中与歌曲播放相关的记录,即带有页面NextSong 的记录歌曲播放标识、开始时间、用户标识、级别、歌曲标识、艺术家标识、会话标识、位置、用户代理
维度表
用户 —应用中的用户
用户标识、名字、姓氏、性别、级别
歌曲 —音乐数据库中的歌曲
歌曲 id、标题、艺术家 id、年份、时长
艺术家 —音乐数据库中的艺术家
艺术家 _id、姓名、地点、纬度、经度
时间—歌曲播放中记录的时间戳分解成具体的单位
sstart _ time、hour、day、week、month、year、weekday

火花数据库的 ER 图
在处理关系数据库系统时,像列中的Primary key和NOT NULL这样的条件很重要。同样,作为一名数据工程师,必须根据业务需求指定主键列,并且不能为空。例如,用户标识和开始时间应该被认为不为空。
项目模板
除了数据文件之外,项目工作环境还包括六个文件:
[test.ipynb](https://github.com/joshuayeung/Data-Modeling-for-a-Music-Streaming-App/blob/master/test.ipynb)显示每个表格的前几行以检查数据库。[create_tables.py](https://github.com/joshuayeung/Data-Modeling-for-a-Music-Streaming-App/blob/master/create_tables.py)放下并创建表格。每次运行 ETL 脚本之前,我都会运行这个文件来重置我的表。[etl.ipynb](https://github.com/joshuayeung/Data-Modeling-for-a-Music-Streaming-App/blob/master/etl.ipynb)读取并处理来自song_data和log_data的单个文件,并将数据加载到表格中。这个笔记本包含了对每个表的 ETL 过程的详细解释。[etl.py](https://github.com/joshuayeung/Data-Modeling-for-a-Music-Streaming-App/blob/master/etl.py)从song_data和log_data读取并处理文件,加载到表格中。[sql_queries.py](https://github.com/joshuayeung/Data-Modeling-for-a-Music-Streaming-App/blob/master/sql_queries.py)包含所有的 SQL 查询,并被导入到上面的最后三个文件中。
创建表格
为了创建我需要的所有表,我完成了以下四个步骤:
- 在
[sql_queries.py](https://github.com/joshuayeung/Data-Modeling-for-a-Music-Streaming-App/blob/master/sql_queries.py)中编写CREATE语句,根据上面定义的模式创建每个表。 - 在
[sql_queries.py](https://github.com/joshuayeung/Data-Modeling-for-a-Music-Streaming-App/blob/master/sql_queries.py)中编写DROP语句来删除每个表(如果存在的话)。 - 运行
[create_tables.py](https://github.com/joshuayeung/Data-Modeling-for-a-Music-Streaming-App/blob/master/create_tables.py)创建数据库和表格。 - 运行
[test.ipynb](https://github.com/joshuayeung/Data-Modeling-for-a-Music-Streaming-App/blob/master/test.ipynb)确认用正确的列创建表格。运行本笔记本后,确保点击“重启内核”关闭与数据库的连接。 
创建歌曲播放表的 CREATE 语句
在 create_tables.py 中,有一个函数create_tables来执行create_table_queries列表中列出的所有查询。
您可以看到这些表是用 test.ipynb 中定义的列创建的。

确认创建了具有正确列的表。
构建 ETL 管道
是时候为每个表开发 ETL 过程了。在 etl.py 中,有一个函数叫做process_data。您可以传递处理数据所需的文件路径和处理函数。它获取所有与扩展名匹配的文件。json)从目录。然后它使用传入的函数遍历文件和进程。
流程song_data
首先,让我们处理song_data并创建songs和artists维度表。我构建了process_song_file函数来执行以下任务:
- 首先,在
data/song_data中获取所有 song JSON 文件的列表 - 阅读歌曲文件
 - 提取歌曲表的数据并将数据插入歌曲表
 - 提取艺术家表的数据并将数据插入艺术家表
 
提取歌曲表的数据
要提取歌曲表的数据,需要完成以下任务:
- 选择歌曲 ID、标题、艺术家 ID、年份和持续时间的列
 - 使用
df.values从数据框中选择数值 - 索引以选择数据帧中的第一条(唯一的)记录
 - 将数组转换为列表,并将其设置为
song_data 
将记录插入歌曲表
在sql_queries.py中编写song_table_insert查询,并将这首歌曲的记录插入到songs表中。
sql _ queries.py 中的 song_table_insert 查询
将歌曲记录插入歌曲表的代码
提取艺术家表的数据并将记录插入艺术家表
艺术家表的数据提取类似于歌曲表的数据提取,但是这次我选择了艺术家 ID、姓名、位置、纬度和经度列。
流程log_data
其次,我对第二个数据集log_data执行了 ETL,创建了time和users维度表,以及songplays事实表。
提取时间表的数据并将记录插入时间表
我已经通过NextSong动作过滤了记录
df = df[df['page']=='NextSong']
并将ts时间戳列转换为日期时间。
t = pd.to_datetime(df['ts'], unit='ms')
注意:当前时间戳以毫秒为单位
我使用 pandas 的dt属性轻松访问类似日期时间的属性,例如来自ts列的小时、日、星期、月、年和工作日,并将time_data设置为按顺序包含这些值的列表。我还为这些列指定了标签,并设置为column_labels。我创建了一个数据帧,time_df,,包含这个文件的时间数据,方法是将column_labels和time_data组合成一个字典,并将其转换成一个数据帧。最后,我将日志文件中时间戳的记录插入到time表中。
提取用户表的数据并将记录插入用户表
用户表的数据提取很容易,只需选择用户 ID、名字、姓氏、性别和级别的列并设置为user_df,然后将该日志文件中的用户记录插入到users表中。
一些笔记
需要为每个表修改 INSERT 语句,以便在适当的时候处理现有记录。作为一名数据工程师,我需要仔细考虑当新数据被插入表中时,表将如何处理现有记录。
例如,对用户表使用on conflict update,因为级别可以从免费变为付费。
提取数据和歌曲播放表
这个有点复杂,因为songs表、artists表和原始日志文件中的信息都是songplays表所需要的。因为日志文件没有为歌曲或艺术家指定 ID,所以我需要通过查询songs和artists表来获得歌曲 ID 和艺术家 ID,以便根据歌曲标题、艺术家姓名和歌曲的持续时间找到匹配项。
使用歌曲标题、艺术家姓名和歌曲持续时间来查询歌曲 ID 和艺术家 ID 的 SELECT 语句。
由于这是一个更大的数据集的子集,解决方案数据集将只有一行,其值包含事实表中songid和artistid的 ID。这是sql_queries.py中的查询将返回的唯一两个非空值。对于这两个变量,其余的行将没有值。
结论
就是这样。我创建了一个 Postgres 数据库,其中的表是为优化歌曲播放分析的查询而设计的。分析团队现在可以轻松地查询他们的数据,并分析了解用户正在听什么歌曲。
更多细节可以访问我的 GitHub 库。
使用 Pandas 和 Scikit 实现数据标准化-学习
清洁数据集的完整指南—第 1 部分

杰里米·帕金斯在 Unsplash 上的照片
一个机器学习算法的成功高度依赖于输入模型的数据质量。真实世界的数据通常是脏的,包含异常值、缺失值、错误的数据类型、不相关的要素或非标准化的数据。这些中的任何一个的存在都将阻止机器学习模型正确地学习。出于这个原因,将原始数据转换成有用的格式是机器学习过程中的一个重要阶段。在预处理数据时,您会多次遇到的一种技术是归一化。
数据规范化是机器学习中的常见做法,它包括将数字列转换为通用比例。在机器学习中,一些特征值会多次与其他特征值不同。具有较高值的特征将主导学习过程。然而,这并不意味着这些变量对预测模型的结果更重要。数据标准化将多尺度数据转换为相同尺度。归一化后,所有变量对模型有相似的影响,提高了学习算法的稳定性和性能。
统计学中有多种归一化技术。在本文中,我们将讨论最重要的几个问题:
- 最大绝对缩放比例
 - 最小-最大特征缩放
 - z 值法
 - 稳健缩放
 
此外,我们将用熊猫和 Scikit-Learn 解释如何实现它们。
那么,让我们开始吧💙
以下数据框包含用于预测二手车价格的多元回归模型的输入(独立变量):(1)里程表读数(km)和(2)燃油经济性(km/l)。在本文中,我们使用一个小数据集进行学习。然而,在现实世界中,所使用的数据集将会大得多。


你可以观察到,里程表读数从 120000 到 400000,而燃油经济性从 10 到 17。多元线性回归模型将比燃油经济性属性更重视里程表读数变量,因为它的值更高。然而,这并不意味着里程表读数属性作为一个预测因素更重要。为了解决这个问题,我们必须用归一化两个变量的值。❤️
最大绝对比例
最大绝对缩放通过将每个观察值除以其最大绝对值,在-1 和 1 之间重新缩放每个特征。

我们可以使用在熊猫中应用最大绝对缩放。max() 和。abs() 方法,如下所示。

或者,我们可以使用 Scikit-learn 库来计算最大绝对缩放比例。首先,我们用 maxabscaler 类创建一个 abs_scaler。然后,我们使用拟合方法学习缩放数据所需的参数(每个特征的最大绝对值)。最后,我们使用这些参数来转换数据。

正如你所观察到的,我们使用 Pandas 和 Scikit-learn 获得了相同的结果。下图显示了执行最大绝对缩放后的转换数据。

最小-最大要素缩放
最小-最大方法(通常称为归一化)通过减去特征的最小值然后除以范围,将特征重新缩放到 [0,1] 的固定范围。

我们可以使用在熊猫中应用最小-最大缩放。min() 和。max() 方法。

或者,我们可以使用 Scikit-learn 库中可用的 MinMaxScaler 类。首先,我们创建一个缩放器对象。然后,我们拟合缩放器参数,这意味着我们计算每个特征的最小和最大值。最后,我们使用这些参数对数据进行转换。

此外,我们可以获得由 fit 函数计算的最小值和最大值,以便用 data_min_ 和 data_max_ 属性对数据进行归一化。
下图显示了应用最小-最大要素缩放后的数据。正如您所观察到的,这种标准化技术将所有特征值重新调整到[0,1]的范围内。

正如你所观察到的,我们使用熊猫和 Scikit-learn 获得了相同的结果。但是,如果您想要执行许多数据转换步骤,建议使用最小最大缩放器作为管道构造器的输入,而不是使用熊猫执行规范化。
此外,切记最大绝对缩放和最小-最大缩放对异常值非常敏感,因为单个异常值会影响最小和最大值,并对结果产生重大影响。
z 得分法
z-score 方法(通常称为标准化)将数据转换为一个均值为 0 、标准差为 1 的分布。通过减去相应特征的平均值然后除以标准偏差来计算每个标准化值。

与最小-最大缩放不同, z 分数不会将特征重新缩放至固定范围。如果输入呈正态分布,则 z 值通常在 -3.00 到 3.00 (超过数据的 99%)之间。但是,标准化值也可以更高或更低,如下图所示。

重要的是要记住 z 分数不一定是正态分布的。它们只是缩放数据,并遵循与原始输入相同的分布。该变换后的分布具有平均值为 0 的和标准差为 1 的,并且只有在输入要素遵循正态分布的情况下才会成为标准正态分布(见上图)。
我们可以使用来计算熊猫中的 z 分数。均值()和 std() 方法。

或者,我们可以使用 Scikit-learn 库中可用的 StandardScaler 类来执行 z-score。首先,我们创建一个标准缩放器对象。然后,我们使用计算转换的参数(在这种情况下,表示和标准偏差)。方法契合()。接下来,我们称之为。transform() 方法将标准化应用于数据帧。。transform() 方法使用从生成的参数。fit() 方法来执行 z-score。

为了简化代码,我们使用了。fit_transform()方法将两种方法(fit 和 transform)结合在一起。
正如你所观察到的,这些结果与使用熊猫获得的结果不同。 StandardScaler 函数计算总体标准差,其中平方和除以 N (总体中值的数量)。

反之,。std()方法计算样本标准差,其中公式的分母是 N-1 而不是 N 。

为了使用 Pandas 获得相同的结果,我们将参数 ddof 设置为等于 0(默认值为 ddof=1),它表示计算中使用的除数( N-ddof )。

我们可以获得由 fit 函数计算的参数,用于标准化具有 mean_ 和 scale_ 属性的数据。如你所见,当在中设置参数 ddof 等于 0 时,我们在 Scikit-learn 和 Pandas 中获得相同的结果。std() 方法。
下图显示了应用 z 得分方法后的数据,该方法是使用总体标准差(除以 N)计算的。

稳健的缩放
在稳健缩放中,我们通过减去中值然后除以四分位间距来缩放数据集的每个特征。四分位数范围(IQR) 定义为第三个和第一个四分位数之间的差值,代表数据的中间 50%。数学上,鲁棒定标器可以表示为:

其中 Q1(x) 是属性 x 的第一个四分位数, Q2(x) 是中位数, Q3(x) 是第三个四分位数。
这种方法在处理包含许多异常值的数据集时非常方便,因为它使用的统计数据对异常值 ( 中值和四分位距)非常稳健,而以前的定标器使用的统计数据受异常值的影响很大,如最大值、最小值、平均值和
让我们看看异常值如何影响使用最小-最大缩放和鲁棒缩放缩放数据后的结果。
以下数据集包含 10 个数据点,其中一个是异常值(变量 1 = 30)。****

最小-最大缩放将变量 1 移向 0,因为与变量 2 相比存在异常值,变量 2 的点在 0 到 1 的范围内均匀分布。****
********
缩放前,第一个数据点的值为(1,1),变量 1 和变量 2 的值相等。转换后,变量 2 的值远大于变量 1 (0.034,0.142)。这是因为变量 1 有一个异常值。
相反,如果我们应用鲁棒缩放,两个变量在变换后具有相同的值(-1.00,-1.00),因为两个特征具有相同的中值和四分位间距,是被移动的值异常值。
********
现在,是时候对汽车数据集应用健壮的缩放了💜
正如我们之前所做的,我们可以使用 Pandas 来执行健壮的缩放。

中值被定义为分布的中点,意味着分布值的 50%小于中值。在熊猫中,我们可以用来计算。中位数()或。分位数(0.5) 方法。第一个四分位数是数据集下半部分的中值(25%的值位于第一个四分位数以下),可以用计算。分位数(0.25) 法。第三个四分位数代表数据集上半部分的中值(75%的值位于第三个四分位数之下),可以用计算。【分位数(0.75)】法。****
作为对 Pandas 的替代,我们也可以使用 Scikit-learn 库来执行健壮缩放。

如上所示,我们获得了与之前相同的结果🙌
下图显示了使用鲁棒缩放转换数据后的结果。

摘要
数据规范化包括将数字列转换为通用比例。在 Python 中,我们可以用非常简单的方式实现数据规范化。Pandas 库包含多种用于计算最常见的描述性统计函数的内置方法,这使得数据标准化技术非常容易实现。作为另一种选择,我们可以使用 Scikit-Learn 库将数据转换成通用的标度。在这个库中,已经实现了最常用的缩放方法。
除了数据标准化,我们还必须应用多种数据预处理技术来保证学习算法的性能。我们将在以后的文章中讨论其中的一些。🙌
感谢阅读:)
阿曼达💜
数据可观察性:如何防止数据管道损坏
数据停机时间、可观察性和可靠见解之间的关系

虽然用于分析、聚合和建模数据的技术和方法在很大程度上跟上了现代数据组织的需求,但我们处理破损数据管道的能力却落后了。那么,我们如何在这个太常见的问题变得令人头疼之前识别、补救甚至预防它呢? 答案就在数据行业的下一个前沿: 数据可观测性 。
在你成长的过程中,你有没有读过一本 选择自己的冒险 小说?你,主角,负责做出决定你史诗般旅程结果的选择,无论是杀死喷火龙还是踏上南极洲深处的旅程。如果您从事数据行业,这些“冒险”可能会有所不同:
数据分析师的追求
现在是凌晨 3 点。你已经花了 4 个小时对一个数据消防演习进行故障排除,你已经筋疲力尽了。您需要找出为什么您团队的 Tableau 仪表板没有从雪花中提取最新的数据,以便财务部门的 Jane 可以生成该报告…昨天。
数据工程逃脱
您正在迁移到一个新的数据仓库,并且没有办法知道重要数据存储在哪里。红移?天蓝色?Google Drive 里的电子表格?这就像一个电话游戏,试图弄清楚去哪里看,数据应该是什么样的,以及谁拥有它。
数据科学家的恶作剧
在你知道你公司的“好数据”在哪里之前,你需要入职 9 个月。你发现单个数据集有如此多的“FINAL _ FINAL _ v3 _ I _ PROMISE _ ITS _ FINAL”版本,以至于你再也不知道什么是 up,什么是 down,更不知道哪些数据表在生产中,哪些应该弃用。
听起来熟悉吗?
在深入探讨如何修复这个问题之前,我们先来说说数据管道破裂的常见原因: 数据宕机 。
数据停机时间的增加
在互联网的早期,如果你的网站宕机,没什么大不了的——你可以在几个小时内让它恢复运行,对客户几乎没有影响(因为,坦率地说,没有那么多,我们对软件的期望也低得多)。
快进到 Instagram、T2、抖音和 T4 的时代——现在,如果你的应用崩溃,这意味着对你的业务的直接影响。为了满足我们对五个九的正常运行时间的需求,我们构建了工具、框架,甚至是完全致力于解决这个问题的职业。
2020 年,数据是新的软件。
仅仅拥有一个伟大的产品已经不够了。每个认真保持竞争优势的公司都在利用数据做出更明智的决策,优化他们的解决方案,甚至改善用户体验。在许多方面,监控数据何时“中断”和管道何时被破坏的需求甚至比实现“五个九”更重要。正如一家拥有 5000 名员工的电子商务公司的一名数据主管最近告诉我的那样: “我公司的网站上有糟糕的数据比根本没有网站更糟糕。”
为了向应用程序宕机的概念致敬,我们将这个问题称为数据宕机 ,它指的是数据丢失、不准确或其他错误的时间段。数据停机会影响数据工程师、数据科学家和数据分析师,以及您公司中的其他人,导致时间浪费(数据团队工作时间的 30%之北)!),沉没成本,士气低落,也许最糟糕的是,对自己的见解缺乏信任。

数据停机往往被忽视,直到为时已晚,对您的数据管道造成严重破坏。图片由 蒂尔萨范迪克 上Unsplash。
以下是一些常见的数据宕机来源,也许它们会引起共鸣:
- 越来越多的数据正在从多个来源收集。随着公司越来越依赖数据来推动决策制定,越来越多的数据被吸收,通常达到千兆字节或兆兆字节!通常,这些数据资产没有得到适当的监控和维护,从而导致日后出现问题。
 - 贵公司的快速发展,包括合并、收购和重组。随着时间的推移,不再与业务相关的数据不会被正确归档或删除。数据分析师和数据科学家不知道什么数据是好的,什么数据可以像渡渡鸟一样。
 - 基础设施升级 迁移 。随着团队从本地迁移到云仓库,甚至在云仓库提供商之间迁移,复制数据表以避免在迁移过程中丢失任何数据是很常见的。当您忘记用新的、迁移的数据资产交叉引用旧的数据资产时,就会出现问题。
 
随着对数据收集、存储和应用程序的审查越来越严格,it 数据停机时间得到了应有的重视。
解决方案:数据可观察性
数据可观察性 ,一个来自 DevOps 和软件工程中最佳实践的概念,指的是一个组织完全了解其系统中数据健康状况的能力。通过将软件应用程序可观察性和可靠性的相同原则应用于数据,可以识别、解决甚至预防这些问题,让数据团队对其数据充满信心,从而提供有价值的见解。
数据可观察性可分为五大支柱:

图片由巴尔·摩西提供。
- 我的表最后一次更新是什么时候?我的数据应该多久更新一次?
 - 分布:我的数据在可接受的范围内吗?
 - 卷:我的资料完整吗?2000 排突然变成 50 排了?
 - 模式:谁有权访问我们的营销表并对其进行了更改?
 - 血统:我的数据哪里破了?哪些表或报表受到了影响?
 
数据可观察性提供了对数据管道的端到端可见性,让您知道哪些数据在生产中,哪些数据资产可以废弃,从而识别和防止停机。

一种数据可观察性方法,结合了自定义规则生成,以监控数据的特定维度何时被破坏。图片由巴尔·摩西提供。
实现数据可观察性的强大而全面的方法包括:
- 元数据聚合&编目。如果你不知道你有什么数据,你当然不会知道它是否有用。数据目录通常被整合到最佳的数据可观察性平台中,为您的数据生态系统提供了一个集中的、透明的视角,在一个视图中展示丰富的谱系、模式、历史更改、新鲜度、数量、用户、查询等。
 - 自动监控&数据停机报警。出色的数据可观察性方法将确保您是第一个知道并解决数据问题的人,让您能够在数据停机发生时立即解决其影响,而不是几个月后。最重要的是,这种解决方案需要最少的配置,而且几乎不需要设置阈值。
 - 沿袭 追踪上下游的依存关系。强大的端到端沿袭使数据团队能够跟踪从 A(接收)到 Z(分析)的数据流,并在流程中纳入转换、建模和其他步骤。
 - 既自定义&ML-生成规则。我们建议选择一种两全其美的方法:使用机器学习来监控您的静态数据并确定应该设置什么规则,以及根据您的数据规格设置独特规则的能力。与编码到建模工作流或 SQL 包装器中的特殊查询不同,这种监控不会停留在“表 R 中的字段 T 的值今天低于 S”上
 - 数据分析师、数据工程师和数据科学家之间的协作。数据团队应该能够轻松快速地协作解决问题,制定新规则,并更好地了解数据的健康状况。
 

强大的端到端流程使数据团队能够跟踪其数据流,从接收、转换和测试,一直到生产、合并转换、建模和流程中的其他步骤。图片由巴尔·摩西提供。
有了这些指导原则,数据团队可以更有效地管理数据,甚至从一开始就防止数据停机。
那么,您的数据冒险将带您走向何方?
有兴趣了解有关贵组织数据可观测性的更多信息吗?把手伸向 巴尔摩西 和剩下的 蒙特卡洛团队 。
数据可观测性:数据工程的下一个前沿
介绍构建数据管道的更好方法

图片由 Unsplash 上的 Bekir Donmez 提供。
为了跟上数据创新的时钟速度,数据工程师不仅需要投资于最新的建模和分析工具,还需要投资于能够提高数据准确性和防止管道破裂的技术。解决办法? 数据可观测性 ,数据工程的下一个前沿和新兴支柱 数据可靠性范畴 。
随着公司越来越受数据驱动,这些丰富见解背后的技术变得越来越微妙和复杂。虽然我们收集、存储、聚合和可视化这些数据的能力已经在很大程度上跟上了现代数据团队的需求(想想:面向领域的数据网格、云仓库、数据可视化工具和数据建模解决方案),但是数据质量和完整性背后的机制已经落后了。
无论您的分析仪表板有多先进,或者您在云上的投资有多大,如果它吸收、转换和推送到下游的数据不可靠,那么您最好的计划都是徒劳的。换句话说,“垃圾入”就是“垃圾出”。
在我们讨论数据可靠性之前,让我们先讨论一下不可靠的“垃圾”数据是如何产生的。
好数据如何变坏
在过去 12 个月与数百个数据工程团队交谈后,我注意到好数据变坏有三个主要原因:1)单个数据生态系统中的数据源越来越多,2)数据管道越来越复杂,3)更大、更专业的数据团队。
越来越多的数据源
如今,公司使用数十到数百个内部和外部数据源来生成分析和 ML 模型。这些来源中的任何一个都可能在没有通知的情况下以意想不到的方式发生变化,从而危及公司用于决策的数据。
例如,工程团队可能会对公司的网站进行更改,从而修改对营销分析至关重要的数据集的输出。因此,关键营销指标可能是错误的,导致公司在广告活动、销售目标和其他重要的创收项目上做出糟糕的决策。
日益复杂的数据管道
数据管道越来越复杂,具有多个处理阶段和各种数据资产之间的重要依赖关系。由于缺乏对这些依赖关系的了解,对一个数据集的任何更改都可能会产生意想不到的后果,影响相关数据资产的正确性。
像改变一个系统中的单位这样简单的事情可能会严重影响另一个系统的正确性,就像火星气候轨道飞行器的情况一样。作为美国宇航局的一个太空探测器,火星气候轨道器由于数据输入错误而坠毁,该错误产生了非国际单位与国际单位的输出,使其过于接近火星。像航天器一样,分析管道在过程的任何阶段都极易受到最无害的变化的影响。
更大、更专业的数据团队
随着公司越来越依赖数据来推动智能决策,他们正在雇用越来越多的数据分析师、科学家和工程师来构建和维护数据管道、分析和 ML 模型,为他们的服务和产品以及业务运营提供支持。
沟通不畅或协调不充分是不可避免的,并且会导致这些复杂的系统随着变化而崩溃。例如,一个团队添加到数据表中的新字段可能会导致另一个团队的管道失败,从而导致数据丢失或部分丢失。在下游,这种不良数据可能导致数百万美元的收入损失、客户信任度下降,甚至是合规风险。
坏数据的好消息是什么?数据工程正在经历它自己的复兴,我们应该非常感谢我们在 DevOps 的同行,感谢他们为我们指引下一个前沿领域的一些关键概念和原则。
下一个前沿:数据可观察性
界定“垃圾数据”影响的一个简单方法是从软件应用程序可靠性的角度来看。在过去十年左右的时间里,软件工程师利用 New Relic 和 DataDog 等目标解决方案来确保应用程序的高正常运行时间(换句话说,工作的、高性能的软件),同时将停机时间(中断和落后的软件)降至最低。
在 data 中,我们把这种现象叫做数据宕机。数据宕机指的是数据不完整、错误、丢失或不准确的时间段,随着数据系统变得越来越复杂,它只会成倍增加,从而支持无止境的源和消费者生态系统。
通过将软件应用程序可观察性和可靠性的相同原则应用于数据,可以识别、解决甚至预防这些问题,让数据团队对其数据充满信心,从而提供有价值的见解。

图片由巴尔·摩西提供。
下面,我们将介绍数据可观测性的五大支柱。每个支柱都包含一系列问题,这些问题总体上提供了数据运行状况的整体视图。也许你会觉得它们很眼熟?
- 新鲜度:数据是最近的吗?最后一次生成是什么时候?包含/省略了哪些上游数据?
 - 分布:数据是否在可接受的范围内?格式是否正确?完成了吗?
 - 卷:数据都到了吗?
 - 模式:什么是模式,它是如何改变的?谁做了这些改变,原因是什么?
 - 沿袭:对于给定的数据资产,受其影响的上游来源和下游资产是什么?谁是生成这些数据的人,谁依赖这些数据来做决策?
 
一个强大而全面的数据可观察性方法需要通过一个集中的界面对这五大支柱进行一致而可靠的监控,该界面是关于数据健康状况的真实信息的集中来源。

端到端数据可靠性平台允许团队探索和了解他们的数据谱系,自动映射上游和下游依赖关系,以及这些资产的健康状况。图片由巴尔·摩西提供。
一个有效、主动的数据可观察性解决方案将快速、无缝地连接到您现有的堆栈,提供端到端的沿袭,允许您跟踪下游的依赖关系。此外,它将自动监控您的静态数据,而无需从您的数据存储中提取数据。这种方法可确保您满足最高级别的安全性和合规性要求,并扩展到要求最苛刻的数据量。
这种解决方案还需要最少的配置,并且实际上不需要设置阈值。它使用 ML 模型来自动学习您的环境和数据。它使用异常检测技术让你知道什么时候有东西坏了。此外,它不仅考虑了单个指标,还考虑了数据的整体视图以及任何特定问题的潜在影响,从而最大限度地减少了误报。
这种方法提供了丰富的上下文,能够快速进行分类和故障排除,并与受数据可靠性问题影响的利益相关方进行有效沟通。与特别查询或简单的 SQL 包装器不同,这种监控不会停留在“今天表 Y 中的字段 X 的值低于 Z”上

数据目录将关于数据资产的所有元数据都放在单一窗口中,因此您可以在单一视图中看到沿袭、模式、历史更改、新鲜度、容量、用户、查询等。图片由巴尔·摩西提供。
也许最重要的是,这种解决方案通过公开这五大支柱中有关数据资产的丰富信息,从一开始就防止了数据宕机事件的发生,以便能够负责任地、主动地进行更改和修改。
数据可观察性的下一步是什么?
就我个人而言,我对这个数据工程的新领域感到无比兴奋。随着数据领导者越来越多地投资于利用数据可观察性的数据可靠性解决方案,我预计该领域将继续与数据工程中的其他一些主要趋势相交,包括:数据网格、机器学习、云数据架构,以及数据产品的平台化。
有兴趣了解更多关于数据可观察性的信息吗?伸出手去 巴尔摩西 和剩下的 蒙特卡洛团队 。
有兴趣加入数据可靠性运动吗?把手伸向 蒙特卡洛团队 !

民主化人工智能是不相关的,数据是孤立的,如何建立一个人工智能公司
意见
数据超越一切

当我第一次听到“数据是新的石油”这句话时,我认为这是聪明的营销。
但是做了几年机器学习,我收回。
这是轻描淡写。
正确的数据可以启动公司,创造就业机会,解决实际问题。
要是有那么简单就好了。
你不能仅仅建立一个人工智能公司
最聪明的人工智能科学家无法在没有数据的情况下训练一个模型。
这对创业公司来说是一个先有鸡还是先有蛋的问题。
你需要数据来建立一个“AI 公司”。但是你需要一个正常运作的公司来收集特定领域的数据。
这解释了为什么:
- 公司假装做 AI
 - 很少有产品以人工智能为核心
 - (拥有数据的)大公司拥有巨大的优势
 
解决方案包括与大公司建立数据合作关系,以及利用公共数据集。
但是我提出一个替代方案。
建立业务(软件或其他),收集数据,然后使用 ML 来扩大业务。
从第一天起就把数据收集作为优先事项。与缺乏人才相比,缺乏数据是人工智能的更大障碍。
你不需要大数据,你需要小众数据
自动驾驶汽车和人工智能驱动的药物发现需要大量数据。
但是如果把一个问题的范围最小化,往往就不需要多少数据了。
特定烹饪中的食谱生成、优化温室番茄的水位以及酿造完美的浓缩咖啡可能不需要一百万个数据点。
如果你能结合狭义模型、领域知识和硬编码逻辑,自动化一项令人厌倦/耗时的工作,你就已经构建了一些有价值的东西。
艾将军多虑了。解决特定领域的特定问题。
人工智能的民主化被夸大了
根据定义,民主化意味着增加那些没有知识和资源的人的机会。
实际上,它是提供人工智能驱动的 API 的公司的营销。
轻松添加人工智能支持的聊天、图像识别或情感分析的能力对于适度增强现有产品非常重要。
但不是用于构建产品的核心。
- 它没有提供针对使用相同 API 的其他公司的护城河
 - 你放弃了来之不易的数据,而大公司会用这些数据来训练它的模型
 - 该 API 可能有一天会被弃用
 
你需要拥有你的模型来建立一个可持续发展的企业。
储存你自己的数据
我希望每个人都有足够的开放数据。没有。
对于一个 AI 创业公司来说,数据是你的护城河。
大公司有大量孤立的数据。
- 谷歌有浏览历史
 - 脸书有你的图像、朋友和兴趣
 - 亚马逊有购买历史
 
这些综合数据可能会催生一百家新公司。但不会。
你需要自己的私人数据仓库。你可以在成功后开源你所构建的东西。
用领域知识增强您的数据
如果数据是护城河。数据+领域知识是一片海洋。
大多数真正的机会是解决你不知道的问题,除非你在某个领域工作过。
给定 20 年的精确天气数据,我可以提出一些潜在的创业想法。但是一个农民,一个总承包商,或者一个物流公司,可以想出我无法想象的用例。世界上真正的问题更适合领域专家,而不是一群工程师。
标记需要领域专业知识的数据几乎不可能外包。我试过了。外包狗和猫的图像标签很容易。但是对法律案件进行分类需要专家。
您可能需要标记您自己的数据。糟透了。但如果只有你能做到,这是一件好事。
不要过度依赖公共数据集
如果你发现一个公共数据集的好机会,抓住它。但有趣的是,这种情况少之又少。
这种方法不太可靠,因为任何人都可以使用它,而且除非更新数据集,否则您可能无法生成额外的数据点。
作为世界上数据的一部分,公共数据集只占很小一部分。
重复我之前的例子,找到狗和猫的图像很容易。很难找到没有足够种子的汉堡面包的图像。
根据我的经验,这种影响在 NLP 中比在图像中更加明显。
收集你自己的数据。
这是一个机会
AI 有一个数据问题。我们知道未来会有更多的人工智能。所以解决这个问题是一个机会。
政府可以用数据刺激创新
政府拥有大量数据。并不是所有的都是敏感的。
开放数据和数据伙伴关系可以吸引公司解决具体问题,如果提供正确的数据,还可以产生经济价值。
我想到了这个鱼类黑客马拉松。
向矿工出售铲子
在历史上的淘金热期间,卖铲子比采矿更有利可图。用数据支撑 AI 公司是一个产品。我们需要更多:
- 数据市场
 - 租赁领域专业知识的能力
 - 数据监管
 
解决数据问题是用人工智能解决问题的一个组成部分。
结论
免责声明:我把 AI 和 ML 混为一谈。
人工智能有潜力解决很多问题。人工智能需要数据来做到这一点。
成为机器学习专家是不够的。获取和创造性地使用数据是一个首要的商业问题。
这并不容易,这是一件好事。当您拥有它时,它会提供一种超越竞争对手和其他人的技术专长的优势。
数据人员,来看看云吧

尼古拉斯·斯旺森在 Unsplash 上的照片
数据工程
向数据工程师、分析师和科学家简要介绍云平台,以及如何了解云中的数据
要说 云是未来 就要回溯 20 年。云已经来了。较新的公司确保他们不会建立自己的数据中心,而是使用 AWS、Azure 和 Google Cloud 等云提供商。也有一些小众玩家,如 Databricks、DigitalOcean 等。大多数老公司最终都会以某种方式转移到云平台。一些将使用混合(云+本地)模式运营。我想说的是,数据人员的工作将取决于他们对云的适应程度。
现在,有成百上千的课程会教你这些云技术。我自己已经参加了很多这样的课程,并且使用云平台已经大约七年了,我可以证明在开始他们的云之旅之前应该做些什么。
1.了解供应商
首先,了解主要的云提供商,他们提供的主要服务以及他们的优势领域和市场。根据我的理解,有三个明确的竞争者——AWS、Azure 和 Google,就像开始提到的那样。所有这些云提供商都有认证计划。虽然获得认证并不能保证你成为该平台的专家,但这意味着你必须了解该平台的基础知识,这对于入门来说已经足够了。
正如我所说,这三个认证和相关文档足以让您开始使用云。这并不意味着你必须走这条路来了解云。认证被高估了。直到最近我才全部做完。纳西姆·尼古拉斯·塔勒布有一句名言—
F 还是真人,如果某个东西在理论上行得通,但在实践中行不通,那就是行不通。对于学术来说,如果一个东西在实践中行得通,但在理论上行不通,那它就是不存在的。
实践总是胜过理论。所以,选择自己的路。但这可能是一个好的开始。
2.深入研究服务
所有主要的云提供商都提供一个帐户,在这个帐户中,你可以免费使用每月有限时间内的一些有限服务。你不需要支付任何费用。不过,你可能需要一张信用卡来开设账户。最好的起点是获得一个帐户。如果你不想这样做,你也可以使用几个云学习网站,这些网站提供对这些云提供商的实验室访问。其中一个例子是 Qwiklabs (来自谷歌)。
如果您已经开始了一个基本的认证学习路径,您可能知道所有与云中数据相关的服务。第一步是尝试最简单、最基本的服务,如关系数据库,然后逐步过渡到数据仓库、管道、编排器和 MPP 系统。几周前,我试图列出数据工程师应该知道的所有主要技术和概念。所有这些,不超过 10 个字。它包含了几乎所有值得初学者了解的云数据服务。
数据工程师必须知道的 10 个单词以内的概念
towardsdatascience.com](/complete-data-engineers-vocabulary-87967e374fad)
如果你完全是这方面的新手,我强烈推荐你在开始体验云计算之前,阅读这本由Robert Changairbneng—的第一部分、第二部分、第三部分撰写的关于数据工程的介绍。如果你已经学完了初级课程,所有这些云提供商都设计了针对特定数据的认证课程来提升你的技能。Azure 有 Azure 认证数据工程师项目,Google Cloud 有 Google Cloud 数据工程师项目,AWS 有 AWS 认证数据分析专业。
3.通过在线课程了解云
像 Udemy、Pluralsight、DataCamp、Coursera、Educative、edX、YouTube、ACloudGuru 等热门网站上有大量关于云计算的课程。学习的内容不缺。没有一个云平台还不能破解训练公式,所以市场上有过多的自由职业者或第三方训练者。但是,也有像谷歌授权培训师、 AWS 大使、 AWS 英雄这样的项目,面向真正活跃在社区中,推广各自服务的人。
在这一点上,我要说的是,个人自由职业培训师制作的学习内容质量要比官方培训视频好得多。说到这里,我不会完全拒绝官方视频。下面是 Google Cloud 在 Pluralsight 上发布的一篇关于 Google Cloud 上数据工程的精彩介绍。
这条道路为参与者提供了在谷歌上设计和建立数据处理系统的实践介绍…
www.pluralsight.com](https://www.pluralsight.com/paths/data-engineering-on-google-cloud-platform)
我最近破解了上面列出的所有这三个考试,我采取了不同的方法来破解它们。对于 AWS,我使用了 ACloudGuru 的优质内容和 Andrew Brown 在 freeCodeCamp 上的免费课程。对于谷歌云来说,它是 Udemy 上的一些随机课程,但主要是文档。对于 Azure 来说,它几乎都是文档。Azure 在文档方面做得非常出色。
4.学哪个云?
从一个开始,但要了解所有的人。技术世界正朝着多云的方向发展。大多数公司将使用不止一个云提供商来处理他们的工作负载。这非常有意义,因为不同的云提供商专注于不同类别的工作负载。例如,谷歌是处理大数据的专家。没有其他公司见过这么多数据。AWS 是第一个进入云市场的,比微软和谷歌想都要早很多年。所以,他们的优势在于拥有真正成熟的产品。Azure 有微软的优势。大多数商用电脑仍然运行 Windows。
HashiCorp 的联合创始人 Armon Dadgar 和 Mitchell Hashimoto 谈论多云。
所以,我会说,你应该从其中的任何一个开始,但要继续了解所有这些,以及越来越多的新兴云平台,如阿里云、甲骨文云等。如果你想学习像 Spark 这样非常具体的东西,那就去使用 Databricks 云产品学习吧。我最近破解了 Databricks Spark 开发者考试,发现他们的云平台真的很棒。
结论
当你在学习所有这些关于云的东西时,不要错过在云上的花费是非常重要的。可以说,对于大多数公司来说,这比拥有专用数据中心更划算,因为它可以大幅降低资本支出。几乎所有的云提供商的服务中都包含一个成本计算器,您可以使用它来研究成本。
要成为一名完全独立的工程师,你必须知道、理解并熟练使用云技术。关于这些不同的云平台,需要注意的另一件事是,大多数技术术语和技术实现在所有这些平台中都几乎是相同的。从概念上来说,如果你仔细想想,并没有什么显著的区别。学习一朵云意味着你已经学会了所有的云。所以,都认识。

由埃伯哈德·格罗斯加斯泰格在 Unsplash 上拍摄的照片
GCP 的数据管道:云功能基础

来源:谷歌云
大多数数据科学家更喜欢拥有他们模型的端到端数据管道,但是拥有管道需要大量的工程工作。
在本文中,我将讨论云功能,这是一个无服务器、简单且经济的选项。
第一步:日程安排
GCP 提供了一个简单的调度工具,叫做“云调度器”。从左上角的导航菜单中找到云调度程序。
给你的工作一个名字和描述。接下来,您需要提供计划的频率。如果您曾经使用过包括 Cron 作业在内的任何调度程序,您在这里都会很好。
选择时区和发布/订阅作为目标。

云调度程序用户界面
一旦你点击主题和有效载荷的发布/订阅选项。主题名称稍后将用作 Python 函数的名称,因此请记住使用 Python 中可接受的函数名称主题。现在给 payload 一些任意的字符串。
如果您喜欢使用命令行,可以运行以下命令:
gcloud alpha scheduler jobs create pubsub scheduler-name --schedule="0 8 * * *" --topic="my_pipeline_topic" --message-body=" "
现在,您应该能够在 Cloud Scheduler 中看到您的计划作业。
第二步:发布/订阅
我推荐你阅读谷歌关于 Pub/Sub 的文档。但是简单一句话,Pub/Sub 允许你在不同的应用之间发送消息。您可以将发布/订阅用于批处理和流数据管道。
现在使用该主题创建一个发布/订阅主题
gcloud pubsub topics create my_pipeline_name
您可以选择使用 UI 创建发布/订阅主题:

从用户界面创建发布/订阅主题
第三步:云功能
你可以选择从用户界面创建你的云功能,但我不建议这样做。首先,如果你的代码中有一个 bug,你将会丢失你的工作。第二,您很容易忘记您的更改和版本。
作为第一步,让我们在本地创建我们的函数,并将它们手动部署到 GCP。
你需要什么?
你需要一个“main.py”函数。这是所有函数和类的包装器。在 main.py 中应该有一个函数使用我们的云函数名。
your imports here
def my_pipeline_name(event,contex):
    your_code_here
将其余的功能放在同一个文件夹中,这样更容易!
下面是根据谷歌对事件和背景的定义:
event (dict):  The dictionary with data specific to this type of
         event. The `data` field contains the PubsubMessage message. 
context (google.cloud.functions.Context): The Cloud Functions event
         `timestamp` field contains the publish time.
所以别管他们了!
创建一个. gcloudignore 文件。这个文件类似于一个. gitignore,但是用于云部署。您可以包含不想部署的文件(比如您保存在文件夹中用于本地测试的密钥)
用所需的包创建一个 requirements.txt 文件。
在运行过程中,您可能需要保存一些文件,但是您的云函数的根是只读的!您需要使用/temp/目录来存放临时文件和可修改文件。
是时候部署了!
gcloud functions deploy my_pipeline_name  --runtime python37
--trigger-topic my_pipeline_topic --timeout 540
这里有一个很大的限制!根据文档,云功能的最大超时为 9 分钟。
查看兹登科的文章和 GitHub 了解更多详情。
步骤 4:在 UI 上测试
转到 GCP UI 上的云功能,然后单击功能名称,它会将您重定向到一个名为“功能详细信息”的新页面,其中有最新的部署版本

云功能详细信息
在 general 选项卡中,您可以找到调用、执行时间、内存使用和活动实例。所有这些都是计费的重要因素(我知道云功能很便宜,但跟踪成本是一种很好的做法)。可以参考你 Romin 的关于云函数定价的文章。
你可以点击顶部中间的“编辑”,更改内存、功能或…
单击 Source,您将找到已部署的文件,您可以单击 edit 在线修改它们(不推荐)。
转到测试选项卡,点击TEST THE FUNCTION,代码将运行,如果有任何问题,将返回一个错误。但这是对云功能的测试,Pub/Sub 和 Scheduler 呢?
您可以从导航菜单进入“云调度程序”,您会在您的作业名称前找到一个Run Now按钮。你可以用它来测试和检查Result栏下的信息。
第五步:密钥
我不喜欢在代码中部署我的秘密密钥,这里我将回顾一下我处理秘密的两个最佳选择。
第一个是将环境变量添加到云函数中。您可以使用 UI 或命令行。这个选项不是我最喜欢的,因为首先秘密就在 UI 中,其次我必须再次为其他功能部署它。
第二个选择是使用 GCP 的秘密经理。我将从 Dustin 关于管理云函数秘密的帖子中借用一些材料。
现在可以用云壳了。图标在搜索栏的右上方。
启用“机密管理器 API”:
gcloud services enable secretmanager.googleapis.com 
创造一个秘密:
echo -n "your secret text here" | \
    gcloud beta secrets create my-secret \
      --data-file=- \
      --replication-policy automatic
如果你的秘密文件中有双引号,那就用单引号括起来。
编写一个函数来检索您的秘密:
import os
from google.cloud import secretmanager
import json
def get_secret*(*secret_name*)*:
    client = secretmanager.SecretManagerServiceClient*()* project_id = 'my_gcp_project'
    resource_name = f"projects/*{*project_id*}*/secrets/*{*secret_name*}*/versions/latest"
    response = client.access_secret_version*(*resource_name*)* secret_string = response.payload.data.decode*(*'UTF-8'*)* secret_string = json.loads*(*secret_string*)* return secret_string
您可以在剩下的代码中调用这个函数来检索您的密钥。确保将“google-cloud-secret-manager”添加到您的需求文件中。
你准备好了!去 UI 测试!
第六步:连接回购
即使您可以从本地部署,Google 也提供了一个选项,用于从 GitHub 或 BitBucket 之类的源代码控件进行部署。让我们一步一步来。
- 在 Google Cloud 控制台中,打开云源代码库。
 - 开放云源代码库
 - 点击添加存储库。
 - 将打开添加存储库页面。
 - 选择连接外部库并点击继续。
 - 将打开连接外部存储库页面。
 - 在项目下拉列表中,选择镜像存储库所属的 Google Cloud 项目。
 - 在 Git 提供者下拉列表中,选择 Bitbucket 。
 - 选中复选框以授权云源存储库存储您的凭据。
 - 点击连接到铲斗。
 - 使用您的机器用户凭据登录 Bitbucket。
 - 点击授权 GoogleCloudPlatform 。
 - 此选项授予 Google Cloud 对您的存储库的读取权限。
 - 授权完成后,您将返回到连接外部存储库页面。将打开存储库列表。
 - 从存储库列表中,选择要镜像的存储库。
 - 点击连接选中的库。
 
在左上方的“云资源存储库”下方,您可以找到您的存储库的名称以及活动分支。点击下拉菜单,更改查看其余分支。
从云回购部署
您可以使用以下命令从云源存储库部署到云功能:
gcloud functions deploy my_pipeline_name \
  --source [https://source.developers.google.com/projects/[gcp_project_name]/repos/[cloud_source_repository_root]/moveable-aliases/[branch]/paths/[folder](https://source.developers.google.com/projects/[gcp_project_name]/repos/[cloud_source_repository_root]/moveable-aliases/[branch]/paths/google_ads/[folder)_under_that_branch]/ \
  --runtime python37 \
  --trigger-topic my_pipeline_topic --timeout 540
现在检查你的功能,版本应该增加。前往TESTING选项卡,享受通过测试的乐趣吧!
现在您已经将您的存储库镜像到“云源存储库”了,如果您检查您的云函数的源代码,您会看到它现在指向您的 repo!
这一步似乎是多余的,因为您可以从本地部署,但是让我们进入下一步。
第七步:CI/CD
到目前为止,我们已经学习了如何从本地和从云 repo 进行部署,下面让我们学习如何设置 CI/CD!
您需要在您的目录中添加一个“cloudbuild.yaml ”,并放入以下内容:
steps:
- name: gcr.io/cloud-builders/gcloud
  args:
    - functions
    - deploy
    - my_pipeline_name
    - --source=https://source.developers.google.com/projects/[[gcp_project_name](https://source.developers.google.com/projects/[gcp_project_name]/repos/[cloud_source_repository_root]/moveable-aliases/[branch]/paths/google_ads/[folder)]/repos/[[cloud_source_repository_root]](https://source.developers.google.com/projects/[gcp_project_name]/repos/[cloud_source_repository_root]/moveable-aliases/[branch]/paths/google_ads/[folder)/moveable-aliases/[[branch]](https://source.developers.google.com/projects/[gcp_project_name]/repos/[cloud_source_repository_root]/moveable-aliases/[branch]/paths/google_ads/[folder)/paths/google_ads/[[folder](https://source.developers.google.com/projects/[gcp_project_name]/repos/[cloud_source_repository_root]/moveable-aliases/[branch]/paths/google_ads/[folder)_under_that_branch]/
    - --trigger-topic=my_pipeline_topic
    - --runtime=python37
    - --timeout=540
现在从 GCP 的导航菜单转到云构建,转到触发器,并点击“创建新的”。现在应该是直截了当了!给你的触发器一个名称和描述。我想在每次推送到分支时触发构建,所以将选择该选项。在 source 部分,我将找到步骤 6 中的镜像 repo,并输入分支的名称。
由于构建配置保存在 cloudbuild 中,我将选择第一个选项,并将路径复制并粘贴到 YAML 文件。
一切就绪,单击“创建”并享受您的 CI/CD 管道!
数据预处理:分步指南
我们知道,对数据进行充分的分析和特征工程会产生良好的可视化效果,但是人们在开始时经常会遇到问题。

来源:BYroute 79根据 CC BY-NC-SA 2.0 获得许可
在这篇文章中,让我们来看看数据预处理的不同步骤。
1.用什么编码平台?
虽然 Jupyter Notebook 是一个很好的起点,但 Google Colab 始终是协作工作的最佳选择。在这篇文章中,我将使用 Google Colab 展示数据预处理步骤。
2。如何为进一步的分析准备原始数据?
在针对任何问题优化数据时,遵循正确的步骤以达到正确的目的是很重要的。
## Import required libraries
import numpy as np
import pandas as pd## Upload dataset
from google.colab import files
uploaded = files.upload()
2.1 选择要上传的文件
## Read a .csv file to pandas dataframe
df = pd.read_csv(uploaded['data.csv'])## Read a .json file to pandas dataframe
df = pd.read_json(uploaded['data.json'])## Read an excel file to pandas dataframe
df = pd.read_excel(uploaded['data.xlsx'])
答。csv 文件可以基于;或任何其他分隔符(包括空格)进行分隔。
2.1.1 示例:以空格或制表符作为分隔符的 CSV 文件
*##* Read a .csv file to a dataframe with delimiter as space or tab:
df =  pd.read_csv('data.csv',  sep='\s+', engine='python')Output :
   Name  Age  City
0  Jack   34  Sydney
1  Jill   31  Melbourne
2.1.2 示例:具有多个分隔符的 CSV 文件
*##* Read a .csv file to a dataframe with multiple delimiters :
df =  pd.read_csv('data.csv',  sep='[:,|_]', engine='python')Input :
Name,Age|City
Jack,34_Sydney
Jill:31,Melbourne
Adam,16:New YorkOutput :
   Name  Age   City
0  Jack   34   Sydney
1  Jill   31   Melbourne
2  Adam   16   New York
3。描述数据有哪些不同的方式?
3.1 数据的维度
df.shape 
# df is the dataframe object name whose dimension we want to obtain
3.2 从数据集中删除重复项
df.drop_duplicates(inplace=True)
inplace=True确保 dataframe 对象被修改,但不创建其副本。如果你需要返回数据帧的副本,使用inplace=False代替。
3.3 每个数字列的描述
df.describe()
describe()通过最小值和最大值以及平均值、中值、标准偏差&等几个值,帮助获得数据集的基本信息。
3.4 获取数据集的第一行或最后几行
df.head(5) # returns first '5' rows of the dataframe
df.tail(5) # returns last '5' rows of the dataframe
3.4 列名
如果数据集包含大量的要素(列),它有助于获取整个要素列表。使用df.columns以描述性格式返回数据帧中所有列的名称。
df.columnsOutput:
Index(['MSSubClass', 'LotFrontage', 'LotArea', 'OverallQual', 'OverallCond', 'YearBuilt', 'YearRemodAdd', 'MasVnrArea', 'BsmtFinSF2', 'SalePrice'], dtype='object')
3.5 检查列的数据类型和每列中的条目数:
df.info()
3.6 删除数字列中的特殊字符
现在,在几个实例中,包含数字数据的列可以具有“对象”数据类型。由于缺少数据点,一些特殊字符如**?**或space可能出现在连续变量中。在这种情况下,我们将检查唯一条目,以删除它们并更改数据类型:
for col in ['names of each column containing object datatype with numeric data points']:
  uni_val_col = df[col].unique()
  print ('The unique values in ' , col , 'are ', uni_val_col)## Convert string datatype to float wherever required and change special characters to NaN
for col in ['names of each column containing object datatype with numeric data points']:
  df[col] = pd.to_numeric(df[col], errors='coerce')
这将某些列的特殊字符转换为NaN(非数字)值,并转换为numeric类型。
3.7 创建独立的连续和分类数据框架
## Create a dataframe with continuous columns 
df_cont = df.select_dtypes(include = ['int64','float64'])## Create a dataframe with categorical columns 
df_cat = df.select_dtypes(include =['object'])
3.8 从分类列中删除特殊字符
我们应该在分类列中检查类似的特殊字符(如 3.6 节所述),并用适当的值替换它们。
df.replace(to_replace=["?", ";"], value=np.nan)
4。缺失值处理
没有输入缺失值的最佳方法。它总是取决于问题的类型。在这里,我们只关注执行分析时要遵循的程序。
4.1 查找缺失值百分比
在这里,我们可以看到如何获得我们在 3.7 节中创建的连续数据帧中缺失值的百分比
# Percentage of missing values in each dataframe along with visualizationtotal = df_cont.isnull().sum().sort_values(ascending=False)
percent = df_cont.isnull().sum()/df_cont.isnull().count()).sort_values(ascending=False)
missing_data = pd.concat([total, percent], axis=1, keys=['Total', 'Percent'])
f, ax = plt.subplots(figsize=(15, 6))
plt.xticks(rotation='90')
sns.barplot(x=missing_data.index, y=missing_data['Percent'])
plt.xlabel('df_cont', fontsize=15)
plt.ylabel('Percent of missing values', fontsize=15)
plt.title('Percent missing data by feature', fontsize=15)
missing_data
输出:


我们可以将同样的方法应用于分类数据框架**df_cat**
4.2 缺失值的插补
数字数据框架
任何列的缺失值都可以通过均值、中值或众数进行估算。如果列中的数据点没有太大的偏差,对于连续数据点,中值比平均值更适合用于替换空值。
df_cont.'columnname'.fillna(features.Unemployment.median(), inplace=True)
与其他方法相比,我更喜欢用 KNN 插补来处理缺失值,因为它能提供更好的结果。
from sklearn.impute import KNNImputer
imputer = KNNImputer(n_neighbors=10) 
df_data = imputer.fit_transform(df_cont)## Creating a new dataframe of the imputed data
df_num = pd.DataFrame(df_data, columns = df_cont.columns )
4.2.2 分类数据框架
在分类数据点的情况下,我们可以用模式来代替它
## Replacing NaN with mode for a column
df_cat.replace({'NaN':'four'} , inplace =True)
5。数据分发
5.1 数字数据帧的图形表示
## Plot distplot for continuous data columns 
for col in df_num.columns:
  plt.figure()
  sns.distplot(df_num[col])
5.2 分类数据框架的图示
## Plotting bar plots for categorical data columns
for col in df_cat.columns:
    plt.figure()
    sns.countplot(x=col, data=df_cat)
    plt.xticks(rotation=90)
6。异常值的处理
6.1 异常值百分比和其他描述性统计措施
异常值是可能影响也可能不影响模型的任何特征的极值。要获得每个数值或分类属性中异常值的百分比,我们可以使用-
# Use the appropriate dataframe in place of "dataframe_name" in the code below, i.e. in this case **df_num** and **df_cat**df_outliers = pd.DataFrame(index=dataframe_name.columns, columns=['outliers', 'outliers%']) for col in dataframe_name.columns:if any(x in str(dataframe_name[col].dtype) for x in ['int', 'float']):df_outliers.loc[col, 'count'] = len(dataframe_name)
df_outliers.loc[col, 'q1'] = dataframe_name[col].quantile(0.25)
df_outliers.loc[col, 'q3'] = dataframe_name[col].quantile(0.75)
df_outliers.loc[col, 'iqr'] = df_outliers.loc[col, 'q3'] - df_outliers.loc[col, 'q1']
df_outliers.loc[col, 'lower'] = df_outliers.loc[col, 'q1'] - (3 * df_outliers.loc[col, 'iqr'])
df_outliers.loc[col, 'upper'] = df_outliers.loc[col, 'q3'] + (3 * df_outliers.loc[col, 'iqr'])
df_outliers.loc[col, 'min'] = df[col].min()
df_outliers.loc[col, 'max'] = df[col].max()
df_outliers.loc[col, 'outliers'] = ((dataframe_name[col] < df_outliers.loc[col, 'lower']) | (df[col] > df_outliers.loc[col,'upper'])).sum()
df_outliers.loc[col, 'outliers%'] = np.round(df_outliers.loc[col,
'outliers'] / len(dataframe_name) *100)df_outliers
我们也可以对每个特征使用箱线图来获得相同的图形表示。
6.2 异常值的处理
有不同的方法来处理异常值,z-score 是最简单的一种。
from scipy import statsz_scores = stats.zscore(dataframe_name)
abs_z_scores = np.abs(z_scores)
entries = (abs_z_scores < 3).all(axis=1)
dataframe_name = dataframe_name[entries]
这就完成了我们最初的数据预处理!我们现在可以从可视化和特征工程开始,使我们的数据集模型就绪。
使用火花数据帧进行数据准备
使用 PySpark 继续调查金融服务消费者投诉数据库

当你向消费者金融保护局投诉时,你希望得到的平静——照片由 Unsplash 上的 Stephen Walker 拍摄
正如我们在上周的博客中看到的,三大信用报告机构是美国联邦金融服务消费者投诉数据库中被投诉最多的公司之一。想想你的信用评分被用来做的每一件事都很有趣:获得贷款、租公寓、购买手机套餐。算了吧。与其说有趣,不如说可怕。因此,今天我们将深入挖掘投诉数据库,回答我一直在思考的几个问题:
- 收到的投诉数量与星期几有什么关系?
 - 这些年来投诉数量有什么变化?
 - 投诉数量每月有何变化?
 - 哪个州的居民抱怨最多?
 - 不同州的人提交投诉的比率不同吗?
 - 哪些产品被投诉最多?
 
一旦你有了 Spark 数据框架中的数据(如果没有,查看上周的文章),你就准备好做一些探索和清理了。 PySpark 数据框架、 PySpark 列和 PySpark 函数文档肯定会成为你的朋友,因为你在自己的环境中工作(分别是 Ross、Monica 和 Chandler……对不起 Joey,我仍然不确定你在数据科学世界中的位置)。对于我在美国联邦金融服务消费者投诉数据库上的项目,我将计数、填充和删除 nan,将 date 列转换为 datetime 并提取日期特征,并对照可接受值列表检查值。
使用 Jupyter 笔记本时,更易于使用的输出格式
在开始之前,我建议您像这样设置 Spark 配置:
spark.conf.set('spark.sql.repl.eagerEval.enabled', True)
这个设置使得输出更像熊猫,而不像命令行 SQL。此后,您不再需要指定 show()来查看输出。或者,您也可以使用.toPandas()或.toPandas().T(用于移调)来查看熊猫风格的输出。请记住,仅在足够小以适合内存的数据帧上执行此操作。太大的pandas数据帧很容易使你的内核崩溃。
计算 nan 和 Nulls
请注意,在 PySpark 中,NaN 与 Null 不同。这两者也不同于空字符串"",因此您可能希望在任何数据集特定填充值之上检查其中的每一个。
像这样检查 nan:
from pyspark.sql.functions import isnan, when, count, coldf.select([count(when(isnan(c), c)).alias(c) for c in df.columns])

您可以在这里看到,这种格式肯定比标准输出更容易阅读,标准输出不适合长列标题,但它仍然需要向右滚动才能看到剩余的列。
这个数据集没有 NaNs,所以我转到 Null。
您可以使用以下代码计算空值:
from pyspark.sql.functions import when, count, coldf.select([count(when(col(c).isNull(), c)).alias(c) for c in 
           df.columns]).toPandas().T

检查重复
为了检查重复项,我比较了 df.count()和 df.distinct()。计数()。在这种情况下,我没有。
处理空值
接下来,我决定删除 company_response_to_consumer 中值为 null 的那一行。这里我们看到它和熊猫很像。
df_clean = df.dropna(subset='company_response_to_consumer')
对于 consumer _ contracted 列,我决定用 No 替换 null 值,同时为这一更改添加一个 flag 列:
# add flag column
df_clean = df_clean.withColumn('null_c_disputed', 
                            df_clean['consumer_disputed?'].isNull())# fill na in consumer_disputed? with 'No'
df_clean = df_clean.fillna('No', subset=’consumer_disputed?’)
同样,这与 pandas 非常相似,除了用于添加列的新语法“withColumn”)。在下一节中,您将看到添加新列的另一种方法。
将字符串转换为日期(时间)并生成日期相关特征
from pyspark.sql.functions import (to_date, datediff, date_format, 
                                   month)# add datetime columns
df_clean = df_clean.select('*', to_date(df_clean['date_received'], 
                          'MM/dd/yyyy').alias('date_received_dt'))
df_clean = df_clean.select('*', 
                    to_date(df_clean['date_sent_to_company'], 
                    'MM/dd/yyyy').alias('date_sent_to_company_dt'))# drop string date columns
df_clean = df_clean.drop(‘date_received’) \ 
                   .drop(‘date_sent_to_company’)
现在,我准备添加我的新功能:
# add time difference between receipt and sent to company
df_clean = df_clean.withColumn('transit_time',
                       datediff(df_clean['date_sent_to_company_dt'],
                       df_clean['date_received_dt']))# add submitted day of week (1=Monday, 7=Sunday)
df_clean = df_clean.withColumn('dow_submitted', 
                              date_format('date_received_dt', 'u') \
                              .alias('dow_submitted'))# add submitted month, year
df_clean = df_clean.withColumn('y_submitted', 
                              date_format('date_received_dt', 'y') \ 
                              .alias('y_submitted')) \
                   .withColumn('m_submitted', 
                               month('date_received_dt') \ 
                               .alias('m_submitted'))
这让我能够研究我们数据集的时间方面

有趣的是,尽管有网上表格,但人们大多在投诉。我想知道这是如何按提交类型划分的。

这里似乎确实有周期性模式的可能性,但仅从这张图表上很难说。未来调查的另一个领域。

与可接受值列表相比,来自<75k 2012 to 275k in 2019.
的投诉明显呈上升趋势
我使用州缩写列表清理了我的 state 列,用一个值“unknown”替换了所有非标准响应。
# add clean state column, drop original column, rename new column
df_clean = df_clean.withColumn(‘state_c’, when(col(‘state’)
                                         .isin(states), 
                                         col(‘state’)) \         
                                         .otherwise(‘unknown’)) \
                   .drop(‘state’) \
                   .withColumnRenamed(‘state_c’, ‘state’)
我最终得到了 26k 个“未知”状态的行——这是限制输入的主要原因,但至少现在已经包含了,而不是一大堆随机的错误输入的状态值。
有了这个,我按州分组,并把我现在的 50 行 2 列的数据框架转换成熊猫。然后,我将这个数据框架与我基于州的数据连接起来(谢谢 SimpleMaps CC4.0),并使用 geopandas(以及来自census.gov的 shapefiles)绘制图表。
state_counts = df_clean.groupby(“state”).count().toPandas()
在 GeoPandas 中,我发现阿拉斯加最西部的岛屿与我的可视化效果不太好,于是选择今天只绘制美国的连续部分——改天再详细介绍如何分离和操作形状优美的多多边形。

这仍然不是一个非常有吸引力的投影选择(强迫一个地球仪在一个平面屏幕上),但我们正在了解大多数投诉来自哪里的要点——人口最多的州。我想公平竞争,并考虑人口数量:

choropleth 会自动缩放颜色,因此我们必须有一个投诉提交量不成比例的小州。稍加挖掘就会发现,DC 的华盛顿州以每 100 名居民 1.1 起的投诉率领先。
按投诉计数的产品
最后,我执行了另一个groupby().count()来查看哪些产品是最值得关注的。

我们发现信用报告在前四个最有问题的产品中出现了两次。这与我们在我之前的博客中发现的相吻合,三大信用报告机构 Equifax、Experian 和 Transunion 是投诉最多的三家金融公司。
一如既往,你可以在 GitHub repo 上查看详情。编码快乐!
数据准备——alter yx,Knime 还是 Python?
你选择的工具是什么?

米卡·鲍梅斯特在 Unsplash 上的照片
我们都听说过,在建立机器学习模型时,数据清理是 70%的任务。收集正确的数据、清理数据和合并数据集是数据建模工作的一半以上。数据准备不仅在数据建模中很重要,对于所有类型的分析工作和您构建的任何仪表板(如使用 Power BI 或 Tableau)也同样重要。
“数据准备”有许多方法,包括专门用于数据建模的商业软件。让我们看看本文中的 3 种方法——Alteryx、Python 和 Knime——并对它们进行比较。
正如我之前关于 Alteryx 的文章一样,我将使用 SEMMA 方法。在这篇文章中,我将只谈论样本,探索和修改阶段。

作者图片
我发现 SEMMA 方法非常有用,因为它为数据准备和建模提供了一种直观的方法。但是,您可以使用任何适合您的需求和偏好的数据准备方法。
采样 :流程从数据采样开始,即选择合适的数据集进行建模。数据集应该足够大,以包含足够的信息来有效地建模,但也应该足够小,以有效地使用。
探索 :在这个阶段,我们通过探索变量之间预期的和未预期的关系来理解数据,并借助数据可视化来发现任何异常。
修改 :修改阶段包含选择、创建和转换变量的方法,为数据建模做准备。
这些方法和逻辑可以复制到任何数据集。在下面的例子中,我已经使用波士顿房产数据集进行了演示。关键在于探索阶段,在此阶段,您估算缺失值并执行异常值分析。
你可以在这里找到所有申请的副本!
巨蟒:
样品:
在 Python 中进行数据加载和准备时,我使用了以下逻辑。
读入数据(使用 read_csv)->将数据添加到 pandas dataframe (pd.read_csv)->选择相关属性 ptype-->识别缺少值的列(使用 count()函数)->删除所有与分析无关的列,如名称等。(使用 dropna())
示例的 Python 代码
探索:
在上一个阶段,我们确定了 6 列缺失值,在这个阶段,我们将估算这些缺失值。一些估算策略包括:
均值:对于区间变量,一种策略是用均值或中值进行估算。在这种情况下,我们将使用 mean()函数估算 land_sf。
模式:对于分类变量,我们将使用模式来估算。
计算:对于一些变量,你可能需要做一些计算。例如,在我们的例子中,R _ BTH _ 样式 2、R _ BTH _ 样式 3、R _ 基奇 _ 样式 2 和 R _ 基奇 _ 样式 3 不能直接估算。如果房子的浴室少于两个,R _ BTH _ 样式 2 将具有空值。在这种情况下,我们将使用“NA”替换它
探索阶段:用平均值估算 LAND_SF,用模式估算 STRUCTURE_CLASS
探索阶段:用 YR _ BUILT 估算 YR_REMOD
估算浴室和厨房风格
修改:
现在,在这个阶段,我们有相对干净的数据。下一步是添加分析所需的任何额外变量(如年龄、YR_SINCE_REMOD),确保预测变量呈正态分布(对数变换 AV_TOTAL ),并且必须使用一个热编码对所有分类变量进行编码
修改阶段的 Python 代码
KNIME:
Konstanz Information Miner 是一个免费的开源数据分析、报告和整合平台。KNIME 通过其模块化的数据流水线概念,集成了用于机器学习和数据挖掘的各种组件。
这是快速准备数据的最佳工具之一,不需要任何编程背景。您可以快速合并不同的数据集,过滤行/列,连接列等。
链接到 Knime 例子这里!
样品:
在“示例”中,我们将使用行过滤器选择相关的 PTYE,使用列过滤器过滤掉列,然后使用统计数据块和行过滤器的组合来查找缺失值。我们将多次使用该列来检查缺失值。

样品台


列过滤器和行过滤器


缺少值和统计块的列
探索:
这里的步骤与 Python 中的相同。在这一阶段,我们将估算所有缺失的变量。我们将使用:数学公式、缺失值(估算模式和中值)和规则引擎块。这些模块如下所示。如您所见,您可以从块中的各种可用选项中进行选择,或者键入一个数学公式,类似于我们使用 excel 的方式

探索区块



I:数学块 ii)缺少值 iii)规则编辑器
修改:
这是数据准备的最后阶段。在这一阶段,我们将使用数学公式计算一些新变量,如年龄和 YR_SINCE_REMOD,并对预测变量进行对数变换,最后对数据进行分区(如下所示)。

修改阶段

隔墙砌块
Alteryx:
Alteryx 是一款出色的数据准备工具。它不是一个开源工具,但是 Alteryx 提供了一个试用许可。你可以看看我之前在 Alteryx 上发表的文章中关于 Alteryx 建模的介绍。
样本:
在' Sample '阶段,我们将数据加载到 Alteryx 中,按 property type = 101 (单户住宅)进行过滤,并删除分析不需要的列(如姓名、地址和与单户住宅无关的行)。

样品台
Alteryx 允许你创建“容器”,在这里你可以将一个函数的所有模块组合在一起,如上图所示。我创建了一个名为“查找缺少值的列”的容器来完成这个任务。我已经多次重复使用这个容器来检查是否所有缺失的值都被输入了

缺少值的列(容器的输出)
探索:
这一阶段包括通过探索变量之间预期和未预期的关系来理解数据,并在数据可视化的帮助下发现任何异常。
在此阶段,我们将估算所有缺失的数据,为建模做准备。在最后一步中,我们确定了 7 个缺少值的列。在这一步,我们将估算这些列。





1)用平均值估算 LAND_SF。2)YR _ REMOD = YR _ build,STRUCTURE_CLASS 用 Mode 估算。3)估算浴室风格和厨房风格
修改:
在这一步中,我们将使用公式块转换变量/创建新属性。我们将计算年龄、YR_SINCE_REMOD 并对预测变量进行对数变换,如下所示。


添加分析所需的新变量。
结论:
Python 拥有丰富的库和支持(书籍和在线支持社区),对于任何有编程背景的人来说都是一个很好的工具。
对于没有编程背景并且正在寻找免费工具的人来说,Knime 是一个很好的选择。当我还在学习如何使用 Python 编程时,Knime 是我大学时代的首选工具。伟大和快速的工具,合并数据集,过滤出行和列,并添加新的列。
Alteryx:许多公司都在与 Alteryx 合作他们的分析和数据科学项目。Alteryx 允许您轻松地将数据源与许多现成的自动化构建模块结合起来,这使得例行的数据准备变得非常容易。
数据准备的工具选择完全是个人喜好。我建议选择一个您最熟悉的工具来加速数据准备过程,以便您有更多的时间进行数据建模。
参考文献:
- 数据分析的艺术和科学”,作者 Edward R. Jones 博士,德克萨斯 A&M 分析项目
 - 使用 SAS Enterprise Miner、Barry de Ville 和 Padraic Neville 进行分析的决策树
 - 德克萨斯 A&M 分析计划
 - 所有截图来自 Python,Knime 和 Alteryx 作者
 
组织病理学癌症检测的数据准备指南
关于如何为 Kaggle 组织病理学癌症检测的模型训练准备数据的指南。

Kaggle 是数据科学和机器学习挑战的绝佳主持人。其中之一是组织病理学癌症检测挑战赛。在这个挑战中,我们提供了一个图像数据集,我们应该在这个数据集上创建一个算法(它说的是算法,而不是明确的机器学习模型,所以如果你是一个天才,有一个替代的方法来检测图像中的转移性癌症;去吧!)来检测转移癌。
这篇文章是关于如何准备 Kaggle 数据集的指南,该指南涵盖了以下四个方面:
- 如何从 Kaggle 将数据集下载到您的笔记本中
 - 如何扩充数据集的图像。
 - 如何平衡目标分布,并为训练/测试/验证拆分数据。
 - 如何在 Keras 中为模型训练构建数据?
 
在笔记本中下载数据集
使用下面的命令下载 kaggle 包。我在谷歌的 Colab 上运行它们,但是你应该可以用你的命令行/Jupyter 笔记本来运行它们。
为了使用 Kaggle 的 API 用你的账号下载数据,你需要做以下两件事。
- 转到您的帐户设置,滚动到 API 部分,单击过期 API 令牌删除以前的令牌(如果您有任何令牌),然后单击创建新的 API 令牌。这将下载一个 'kaggle.json' 文件。
 - 将此文件上传到您的项目目录。
 
然后运行下面的代码,该代码使用 json 文件授予访问权限,并下载数据集。
解压缩 zip 文件。这需要几分钟的时间,因为它包含大约 6–7 GB 的数据。
此时,你应该有两个文件夹,和两个 csv 文件。
- 包含训练集图像的“train”文件夹
 - 包含测试集图像的“测试”文件夹
 - 一个“train _ labels”CSV 文件,包含每个图像的 id 及其相应的标签(0 表示无癌症,1 表示有癌症)。
 - 一个“sample _ submission”CSV 文件,它是一个示例,说明如果您想参加 Kaggle 竞赛,您应该如何提交您的结果。
 
数据扩充
什么是数据增强,我们为什么要这样做?从本质上来说,数据扩充是一种通过对数据进行细微更改来增加图像数据集大小的方法。我们的目标是将我们的模型推广到更多通过图像增强引入的例子。更重要的是,图像增强还允许我们的模型概括不同类型图像的不同版本。
看下图。假设左边被画得可怕的猫来自训练数据集,但是右边的猫在测试数据集中。从字面上看,它们是相同的图像,只是右边的图像被翻转了。人类能够很容易地注意到这一点,但是模型可能无法成功完成这项任务,并且无法在测试数据集中识别它。理想情况下,您希望您的模型不关心图像的变化,并正确地对图像进行分类,这就是为什么您引入图像的增强版本,以便模型可以更好地概括。

增强图片的示例
这是一个函数的代码,它通过对图像应用各种变换来放大图像,例如改变图像的对比度、增加图像的亮度、应用随机旋转/移动。这里的代码引用自。
然后,我们使用此功能来扩充“train”文件夹中提取的图像。下面的代码生成 X 数量的新图像(基于一个名为 'images_to_generate' 的变量,您可以更改该变量),方法是从我们的 train 集中随机选择图像,应用上面的增强功能,然后将图像保存在 train 文件夹中,并使用“增强的”+其以前的 ID 作为新名称。最后,我们还将标签和名称附加到 train_labels csv 文件,并保存一个新的 csv 文件,该文件也包含增强图像的 ID 和标签。
平衡目标分布
在机器学习中,我们希望确保我们的模型能够很好地处理我们扔给它的所有类型的数据!如果我们盲目地使用所有可用的训练数据,可能出现的一个问题是不平衡的类别/目标分布的情况。这意味着你的数据集包含一个或多个类比其他类更多的观察值。如果我们在这个完整的数据集上训练我们的模型,我们的模型将在预测具有更多数据点的类方面变得非常好,而在分类其他类方面表现不佳。让我们看看在我们的癌症检测模型的情况下会发生什么!
如果我们观察我们的训练数据集,我们会意识到它是不平衡的。运行下面的代码显示,我们有大约 130000 张没有癌症的图像,以及大约 90000 张有癌症的图像。如前所述,使用不平衡数据集进行训练可能会导致我们的模型在识别一个类时变得非常出色,而在其他类上却失败得很惨。在这种情况下,少数类是检测到癌细胞的一类,我们真的不想在对癌症图像进行分类时失败;因为这样做会导致人们带着未确诊的癌症继续生活,而他们应该接受治疗!
输出:
为了解决这个问题,我们可以从无癌症(0)类中删除图像,如下所示。为了更快的训练,我丢弃了多余的图像,但是我们可以简单地保持 95000:93099 的比例。下面的代码删除图像并保持类的分布相等。
还有一步,我们需要将我们的数据分成训练、测试和验证集。训练集用于训练我们的模型,验证集用于调整模型的超参数,测试集用于检查模型的性能。下面的代码片段按照 60:20:20 的比例对训练:测试:验证进行了划分。
在上面的例子中,我们有一个丰富的数据集,我们可以从中删除数据点来平衡类分布;然而,如果我们没有丢弃数据的奢侈呢?如果我们需要尽可能多的数据呢?
有几种方法可以做到这一点:
- 您可以对 minority 类进行过采样。在我们的例子中,这将简单地从我们的训练集中随机抽取带有检测到的癌细胞的图像样本,并将这些样本附加到我们的训练集中。您可能对此有点怀疑,但这种技术至少确保了您的模型不会严重依赖多数类进行训练,并且还学会了对少数类进行分类。
 - 对于非基于图像的数据集,您可以创建假数据。这可以通过使用像核密度估计这样的技术来完成,在这种技术中,您可以了解数据集中要素的分布,并从这些分布中抽取样本来生成新数据。
 
这只是两种方法,你可以在这里找到更多的。
Keras 生成器的目录结构
机器学习模型使用存储在计算机/服务器内存中的数据。有时,数据集小到足以容纳在内存中;但在大多数实际情况下,并非如此。为了克服这一点,我们可以使用生成器(它们也执行图像增强,但我手动执行了上面的操作)来拍摄我们的图像,并将它们成批地传递给机器学习模型,而不是一次全部传递。为此,我们需要将图像存储在特定的目录结构中。本例中的目录应采用以下格式。
假设您在项目基本目录中,它应该是:
—培训数据文件夹
— — — class_0 文件夹
— — — class_1 文件夹
—测试数据文件夹
— — — class_0 文件夹
— — — class_1 文件夹
—验证数据文件夹
— — — class_0 文件夹
— — — class_1 文件夹
“培训数据”文件夹有两个子文件夹,其中包含每个类别的图像。测试和验证数据文件夹的结构相似。下面的代码创建了这些目录。
一旦我们创建了目录,我们就可以将相应的映像转移到这些目录中。下面的代码可以做到这一点。在 colab 上这样做大约需要 30 分钟,因为我们必须传输 160000 张图像。
结尾注释
太好了!此时,您应该已经设置好数据集,可以输入到您的模型中。完整的 A-Z 库可以在这里找到!
希望您发现这篇文章和笔记有助于理解挑战的预处理数据,以及一般的预处理。
参考
- https://www.kaggle.com/c/histopathologic-cancer-detection
 - https://www . ka ggle . com/qit vision/a-complete-ml-pipeline-fast-ai
 - https://towards data science . com/keras-data-generators-and-how-to-use-them-b 69129 ed 779 c
 - https://github . com/DarthQadir/Cancer-Data-Preprocessing-Medium-Article/blob/master/Cancer _ Detection _ Preprocessing . ipynb
 - https://scikit-learn.org/stable/modules/density.html
 - https://towards data science . com/methods-for-handling-unbalanced-data-5b 761 be 45 a 18
 
数据预处理和解释结果:机器学习的核心:第 1 部分- EDA

卢克·切瑟在 Unsplash 上的照片
为什么以及如何分析数据和结果?
机器学习是当今世界越来越感兴趣的主题。越来越多的人,一些有经验的,一些新的,正在探索这个领域,因为它有趣的机会,应用和证明的能力。我是新来的一员。我进入这个领域是因为它能够完成非常有趣的应用。作为一名新手,我开始关注不同的机器学习模型及其工作方式。很久以后,我意识到,机器学习不仅仅是关于模型。模型是大脑,但是大脑从哪里学习呢?简单的答案是,根据数据。我们给模型的数据表现得越好,它学习得就越好。因此,数据处理和分析是机器学习的一个非常重要的部分。
现在,我们只讨论了输入,那么输出呢?我们还需要解释输出。已经观察到,如果数据集具有不平衡的数据,则在垃圾邮件检测之类的分类问题的情况下,模型可能无法正确地学习每个类别。在这种情况下,如果强表示集合在测试集合中数量很大,并且模型预测主要表示类别的每个样本,则由于集合的不平衡,准确性可能很好。但是这个模型和无技能分类器一样好。所以,我们不能部署这样的模型。我们需要在部署前分析结果。
这些事实是这篇博客背后的动机。
如何分析数据?
我们都听说过探索性数据分析(EDA)和主成分分析(PCA)这两个术语。这些方法被广泛用于可视化、分析、处理和解释数据变化和关系。在这篇文章中,我们将通过这些概念。为此,我们将使用 Kaggle 乳腺癌数据集。

数据集结构
这个数据集有 32 列。它有 30 个特性列、1 个索引列和 1 个“诊断”列,这是我们的目标列。
Y=pd.DataFrame(df['diagnosis'].values,columns=['diagnosis'])
X=df.drop(['diagnosis','id'],axis=1)
因此,我们得到了包含 30 列的特性集和包含 1 列的目标集。目标列有两个目标类,“M”和“B”。那么,我们开始吧。
探索性数据分析和数据预处理
相关图
我们的特征集的每一列被我们的模型用作值的向量。现在,我们如何将两个特征值或向量联系起来。为此,我们使用两个特征向量的点积,这给出了特征向量之间的协方差。协方差的值可以从正无穷大变化到负无穷大。这种协方差让我们了解两个考虑的特征之间的关联程度。符号表示变化的方向。换句话说,说明一个特征是随着另一个特征增加还是减少。它由下式给出:
Cov(x,y)= Sum((x-均值(x))(y-均值(y))) / n
其中 x 和 y 是两个特征。
现在,我们不直接使用协方差,我们使用相关性,即两个向量之间的余弦角。相关值从-1 到+1 不等。它只是给出了变化的方向。它是在协方差除以两个特征的标准差的乘积时获得的。相关性由下式给出:
相关性=corr(x,y)= Cov(x,y) / std(x)。标准(y)
关联是无量纲的,与尺度无关。了解特征之间的相关性很重要,因为我们不希望使用两个相关性非常高的不同特征,因为它们通常表示同一条信息。我们也不想使用与目标值相关性很小的特征,因为它们对预测没有太大影响,但会增加模型的复杂性。
这是相关图的样子:
import seaborn as sb
import matplotlib.pyplot as plt
C_mat = df.corr()
fig = plt.figure(figsize = (15,15))sb.heatmap(C_mat, vmax = .8, square = True)
plt.show()

这里我们可以看到代表两个特征之间相关性的标度和阴影。
对偏斜度的依赖
有几种分布描述了要素值在平面上的分布情况。在本节中,我们关注两种类型的分布:正态分布和偏态分布。在正态分布中,数据总体上是均匀分布的。在偏态分布中,数据可能在几个区域累积,而不是均匀分布在所有区域。偏斜分布通常是要素的一个问题,会影响模型的性能。我们可以使用直方图来研究这个问题。
df.hist(figsize = (35,35))
plt.show()

这些图很容易反映特征的分布。我们可以看到许多特征具有正态分布,而其他特征也具有偏态分布。所以,让我们做点什么吧。
如果我们仔细分析,我们可以发现“分形维数 se”和“面积 se”具有偏态分布。
import seaborn as sns
sns.distplot(df['fractal_dimension_se']);
sns.distplot(df['area_se']);


很明显,使用对数函数可以将偏态分布转换为正态分布。
import numpy as np
df['new_fractal_dimension_se']=np.log(df['fractal_dimension_se'].values)
df['new_area_se']=np.log(df['area_se'].values)


我们可以用数据集中新创建的正态分布要素替换实际的倾斜分布要素。
价值观的宁滨
通常在数据集中,我们会发现年龄、年份、人数等特征。这些特征本质上通常是数字的。但是它们与目标值的相关性很低,这可能是由于值的多样性。通过在几个范围内对这些特征进行宁滨,可以将这些特征转换成分类特征。例如,如果年龄在 0 到 100 的范围内,我们可以生成 5 个箱:
0-20 岁:小孩
20-40 岁:年轻
40-60 岁:中年
60-80 岁:老年人
80-100 岁:非常老
这种类型的数据预处理被称为宁滨,对于稀疏或长范围的数据非常流行。
数据分布
数字特征
有时查看连续数字特征相对于彼此的分布是非常重要的。这通常有助于我们估计某个特征对预测的有用程度。有几个情节可以做到这一点。我们会发现一些。
- 成对绘图
 
import seaborn as sns
sns.set()
cols = ['radius_mean', 'texture_mean', 'perimeter_mean',
       'area_mean', 'smoothness_mean', 'compactness_mean', 'concavity_mean',
       'concave points_mean', 'symmetry_mean', 'fractal_dimension_mean',
       'radius_se', 'texture_se', 'perimeter_se', 'smoothness_se']
sns.pairplot(df[cols], size = 2.5)
plt.show();

由于篇幅限制,我们在这里只展示了几个特性。
配对图:仅用于数值。对角线元素显示特征的分布,另一个图形使用散点图显示两个特征的分布。
我们也可以使用散点图单独完成这项工作。
data = pd.concat([df['radius_mean'], df['new_conacvity_se']], axis=1)
data.plot.scatter(x='new_conacvity_se', y='radius_mean',);

该图显示了 2D 平面上半径平均值和新相关系数之间的分布。
2.基于目标特征的配对绘图。
import seaborn as sns
sns.pairplot(df_1, hue="diagnosis")

这些图显示了基于两个特征的点的分布,以及如何根据目标列区分它们,对角线显示了基于一个特征的两类目标列(M 和 B)的重叠程度。
3.聚类分析
这种类型的分析是基于聚类算法来完成的,主要是 K 均值聚类。这里,采用特征,并且应用 K 均值聚类来检查点分布的边界,如果基于这两个特征来预测目标,则该边界可以是分类边界。让我们看几个例子:
from sklearn.cluster import KMeans
import sklearn.metrics as sm
X_v=X.values
model = KMeans(n_clusters=2)
model.fit(X_v) 
因此,这里我们的特征集被提供给 k=2 的 k 均值聚类算法。这将创建两个集群,它们将成为两个目标类。现在让我们按功能检查除法。
import numpy as np
import matplotlib.pyplot as plt
colormap = np.array(['red','blue'])
plt.scatter(X['radius_mean'], X['compactness_mean'],c=colormap[model.labels_], s=40)
plt.title('K Mean Classification')
plt.show()

import numpy as np
import matplotlib.pyplot as plt
colormap = np.array(['red','blue'])
plt.scatter(X['radius_mean'], X['concave points_mean'],c=colormap[model.labels_], s=40)
plt.title('K Mean Classification')
plt.show()

如果我们检查这些聚类,我们将能够在这两个聚类之间画出一条分类线。
分类特征
分类数据是指具有类、箱或分部的数据。它们不是连续的数字。关于分类特征,最重要的是要知道它们的分布。换句话说,假设“M”和“F”是性别特征中的两个类别,那么“M”实例的数量远大于“F”实例的数量是很常见的。在这种情况下,有一个问题,因为模型不学习代表不足的类。我们可以使用以下类型的分类特征图来了解这一点。
import matplotlib.pyplot as plt
feature = "diagnosis"
ax = df[feature].value_counts().plot(kind='bar',
                                    figsize=(10,10), 
                                    color='blue')
ax.set_xlabel(feature, fontsize=20)
ax.set_ylabel("Count",fontsize=20)

这里的两个条形表示我们的目标列中“B”和“M”类的计数。
研究连续数值数据的分类特征的变化是非常重要的。我们通常使用箱线图和柱状图来分析这种关系。
1。箱线图
data = pd.concat([df['texture_mean'], df['diagnosis']], axis=1)
f, ax = plt.subplots(figsize=(10, 10))
fig = sns.boxplot(x='diagnosis', y="texture_mean", data=data)

这显示了连续 teture_mean 特性根据我们的目标列中的两个类别的分布。这些图形通常反映了特定类别的分类数据中数据的连续值的分布。实心框位于第一和第三个四分位数之间。柱是分布中多次出现的最高点和最低点,孤立点是异常值。它们必须被移除,因为它们降低了模型的准确性。两个方框显示了连续数据相对于两个类别的变化。
2。条形图
import seaborn as sns
sns.set(style="whitegrid")ax = sns.barplot(x="diagnosis", y="area_mean", data=df)

这些图类似于箱线图。它们还反映了不同类别的分类特征中连续数据行为的差异。它侧重于均值和标准差。条形的高度是类别中连续特征分布的平均值,条形代表标准差。
结论
我们在这里已经看到了几种数据分析和预处理的方法。在接下来的部分,我们将看看 PCA、特征选择和结果分析。我希望这有所帮助。
Github 链接在这里是。
数据预处理和解释结果:机器学习的核心:第 2 部分-主成分分析,特征选择和结果分析

卢克·切瑟在 Unsplash 上的照片
如何选择特征进行预测?
在第 1 部分,我们已经看了我们的数据集和探索性数据分析的概念。在这一部分,我们将看看主成分分析或 PCA 和特征选择程序。我们开始吧。
到目前为止,我们已经单独可视化了几个特征以及它们之间的相关性。但是对我们来说,将整个数据可视化是非常重要的。为此,我们需要将这 30 维数据投影到 2D 特征地图中。因此,需要降维。这就是 PCA 的用武之地。
在我们进入主成分分析之前,让我们探讨一下方差。
差异
方差是对集合分散或展开程度的度量,这是“平均值”(均值或中值)所不具备的。例如,如果我告诉你一个数据集的方差为零,你就知道它的每个成员都是相同的。如果方差很高,特别是与平均值的比率,这就告诉你数据在其成员之间有很大的不相似性。
如果方差非常低,我们基本上可以从该特性或特性集获得所有相似类型的数据。机器学习通常针对不同类别中数据点的不同行为。因此,如果它非常低,点预计会聚集在相同的点周围,这导致它们很难区分。因此方差通常被认为是最大似然数据集的信息。
方差由下式给出:
方差= Sum [i=1 到 n]((x { I }-均值(x)))
在 PCA 中,我们试图创建 n 个复合特征,它们能够最好地表示包含在我们的数据集的 30 个特征中的信息。这 n 个特征称为主成分。n 的值取决于用户。这 n 个特征都不是原始特征。这些特征被开发为不同特征的组合。
在我们开始理解和应用 PCA 之前,我们必须注意一件事。PCA 总是在缩放的数据上进行。那么,让我们来看看缩放。
缩放比例
我们使用的数据有几个特点。现在,这些特征根据特征具有不同的范围,例如一些特征具有 0 到 1 之间的十进制值,而其他特征具有 100-1000 之间的值。
如果我们使用像逻辑回归这样的分类器,就会产生很多问题。
y = w1x 1+w2x 2+……………………+wnxn+b
逻辑回归画一条线,用这个公式表示。现在,如果 x1 从 0 到 1,x2 从 100 到 1000,显然 x2 会有很大的压力和重量。为了避免这种情况,进行了缩放,使得所有的值都在固定的范围内。它只是将值更改为一个比例,但保持分布不变。
有两种主要的缩放类型
- 标准比例:由下式给出
 
标度=(x-均值(x))/标准差(x))
它给出-1 到+1 之间的值。
2 。最小-最大缩放:由下式给出
Scale=(x- min(x))/(max(x)-min(x))
它给出 0 到 1 之间的值。
主成分分析
让我们回到 PCA。我们将在这里使用标准的定标器。让我们先来看看应用程序,然后我们再来看解释。
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scale=scaler.fit(X)
X_scaled=scaler.transform(X)
X_scaled_df=pd.DataFrame(X_scaled,columns=X.columns)
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
PC = pca.fit_transform(X_scaled_df)
p_Df = pd.DataFrame(data = PC
             , columns = ['principal component 1', 'principal component 2'])
p_Df.head()

降维后,这两个分量形成为我们的 n 分量是 2。现在,我们将把这作为我们的特征集,并相应地加入我们的目标集,我们将尝试可视化。由于它有两个数据特征,现在可以很容易地在 2D 平面上表示出来。
Y_l=Y.iloc[:]['diagnosis'].tolist()
joined=p_Df
joined['Diagnosis']=Y_l
joined.head()

import matplotlib.pyplot as plt
fig = plt.figure(figsize = (10,10))
ax = fig.add_subplot(1,1,1) 
ax.set_xlabel('PC 1', fontsize = 12)
ax.set_ylabel('PC 2', fontsize = 12)
ax.set_title('PCA', fontsize = 15)
diags=['M','B']
colors=['r','b']
for diag, color in zip(diags,colors):
    i = joined['Diagnosis'] == diag
    ax.scatter(joined.loc[i, 'principal component 1']
               , joined.loc[i, 'principal component 2']
               , c = color
               , s = 50)
ax.legend(diags)
ax.grid()

这是得到的主成分分析分布。如果我们以最好的方式表示 2D 的 30D 特征集,这就是我们的完整数据集表示。但是,这总是不可行的。让我们看看为什么。
PCA 是基于无监督算法的。问题是,这些成分是如何获得的?答案来了。
我们有一个 30 维的数据集。这意味着我们可以在一个 30 维的平面上绘制我们的点,每个维度代表一个特征。比方说,然后我们根据我们的目标分类给这些点着色。“M”是红色的。“B”是蓝色的。现在,在这一时刻,我们试图绘制一个 2D 平面,它最适合于根据目标类来划分点。我们使用 2D,因为 n_components 是 2。现在我们开始在 2D 平面上对这些 30D 点进行投影。因此,我们将 30 长度的元组减少到 2 长度的元组。现在,如果我们思考,我们会非常清楚,由于维数减少,我们也会丢失一些信息。因此,方差减小。x 轴和 y 轴值是主分量。因此,我们的目标是如何减少方差损失。为了做到这一点,我们通常从许多选择中挑选出可投影的 2D 平面。
详细地说,首先,选择一个最能区分这些点的 2D 平面。投影这些点并计算方差损失,然后选择与前一个平面正交的另一个平面并再次计算其方差。如此继续下去,直到获得许多选择,然后使用损失最小的平面。
毕竟,主成分分析并不总是很有信心代表所有的信息。这可以用方差比来测试。
pca.explained_variance_ratio_array([0.44272026, 0.18971182])
这没有给出非常清楚的表示,因为这两个分量仅表示这里所表示的总信息的 44+18=62%。这不是一个准确的表示,因为它仅表示总信息量的 62%。也就是说,它不能用两个主成分来表示。这是一个估计值,但据说如果比率之和小于 85%,则表示不太正确,因为缺少很多信息。
尽管如此,还是可以从这个操作中提取很多信息。比如,如果我们看这个图表,我们可以看到,如果我们画一条直线,那么它可以很容易地分类。因此,对于这个问题,逻辑回归将比 KNN 型分类器发挥更好的作用。
这几乎是关于 PCA 的所有内容,让我们进入下一个主题特性选择。
特征选择
我们有时会面临有很多特点的问题。它们甚至是像 99 100 个特征这样的大数字。现在,这些特征中的一些在模型预测中不是很有用。但是它们增加了特征集的维数,从而使其难以分析,增加了训练的时间,也降低了准确性。所以这些特征必须被去除。因此,在本节中,我们将讨论完成这项任务的几种方法。
随机森林特征重要性
在这种方法中,我们将数据拟合到一个随机森林模型,并获得特征重要性。从而获得最佳特征。正如我们所知,随机森林是基于决策树算法的,因此它们可以非常容易地模拟非线性,并提供非常清晰的特征重要性的图像。让我们看看应用程序。
from sklearn.ensemble import RandomForestClassifier
rfc = RandomForestClassifier()
X_n=X.values
Y_n=Y.values
rfc.fit(X_n,Y_n)
importance = rfc.feature_importances_
从而拟合决策树模型,获得特征重要度。
import matplotlib.pyplot as plt; plt.rcdefaults()
import numpy as np
import matplotlib.pyplot as pltobjects = X.columns
y_pos = np.arange(len(objects))
performance = importancefig, ax = plt.subplots(figsize=(20, 20))
plt.barh(y_pos, performance, align='center', alpha=0.5)
fontsize=14,
plt.yticks(y_pos, objects,fontsize=20)
plt.xticks(fontsize=20)
plt.xlabel('Contributions')
plt.title('Feature Contributions',fontsize=20)plt.show()

这是从随机森林算法中获得的特征重要性。
逻辑回归特征重要性
这是另一种在将数据拟合到逻辑回归模型后使用特征重要性的方法。如果数据本质上是线性的,这种方法非常有效。众所周知,逻辑回归的分类线由一个线性方程给出,如:
Y=w1x1+w2x2+w3x3…………+wnxn
这里的权重是相应的特征重要性。
from sklearn.linear_model import LogisticRegression
model = LogisticRegression(solver='liblinear', random_state=0)
model.fit(X_n, Y_n)
Weights=np.hstack((model.intercept_[:,None], model.coef_))
k=X.columns
k.append('bias')
因此,模型是合适的,并且在权重列表中获得了重要度。

这是由逻辑回归生成的特征重要性分布。
Lasso 回归要素重要性
这是一种非常常用的方法,用于获取特征重要性。这是通过将数据拟合到 lasso 回归模型并获得特征重要性来实现的。Lasso 回归适用于 L1 正则化的策略。
L1 正则化用于稀疏数据,其中有许多特征,但并非所有特征都是预测所必需的。在这种情况下,L1 正则化将不是非常重要的特征的特征重要性归零。Lasso 使用相同的策略。
需要注意的一点是 Lasso 不能用于分类“M”和“B”类,它们必须转换成整数。
让我们检查一下应用程序
from sklearn.linear_model import Lasso
import numpy as np
lasso = Lasso(alpha=0.0001)
i=0
y_d=[]
while i<len(Y_n):
    if Y_n[i][0]=='M':
        y_d.append([1])
    else:
        y_d.append([0])
    i+=1
y_d=np.array(y_d)
lasso.fit(X_n, y_d)l=(lasso.coef_)
因此,我们将数据拟合到 lasso 模型,并加载特征重要性。
import matplotlib.pyplot as plt; plt.rcdefaults()
import numpy as np
import matplotlib.pyplot as pltobjects = X.columns
y_pos = np.arange(len(objects))
performance = lfig, ax = plt.subplots(figsize=(20, 20))
plt.barh(y_pos, performance, align='center', alpha=0.5)
fontsize=14,
plt.yticks(y_pos, objects,fontsize=20)
plt.xticks(fontsize=20)
plt.xlabel('Contributions')
plt.title('Feature Contributions',fontsize=20)plt.show()

这是 lasso 获得的特征重要性列表,我们可以看到一些特征的权重被降低到零,所以在模型的训练中,它们不会起任何作用,因为它们的权重为 0。
递归特征消除
递归特征消除是迄今为止设计的选择最佳特征的最佳方式。它基于一种递归算法。它首先考虑所有特征,建立模型预测,然后找到最不重要的特征。现在,它删除这些特征,重建模型,并再次检查删除特征的效果。这个过程包括一个 k 倍交叉验证步骤,以消除集合中任何种类的不平衡问题。我们设置流程使用的估计器或模型。
实施:
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import StratifiedKFold
from sklearn.feature_selection import RFECV
rfc = RandomForestClassifier(random_state=101)
rfecv = RFECV(estimator=rfc, step=1, cv=StratifiedKFold(10), scoring='accuracy')
rfecv.fit(X_n,Y_n)
因此,我们使用随机森林分类器作为估计器。我们在每一步都使用 10 倍交叉验证。
features=rfecv.n_features_
features
-> 24
这用于获得消除后最终获得的特征的数量。我们可以看到,在剔除之后,获得了 30 个特征中的 24 个。
n_p=np.where(rfecv.support_ == False)[0]
这获得了在该过程中已经消除的特征。让我们想象一下结果。
feat=X.columns
to_drop=[]
for i in n_p:
    to_drop.append(feat[i])
x_imp=X.drop(to_drop,axis=1)
import matplotlib.pyplot as plt; plt.rcdefaults()
import numpy as np
import matplotlib.pyplot as pltobjects = x_imp.columns
y_pos = np.arange(len(objects))
performance = nfig, ax = plt.subplots(figsize=(20, 20))
plt.barh(y_pos, performance, align='center', alpha=0.5)
fontsize=14,
plt.yticks(y_pos, objects,fontsize=20)
plt.xticks(fontsize=20)
plt.xlabel('Contributions')
plt.title('Feature Contributions',fontsize=20)plt.show()

这些是 RFE 之后最后留下的特征和它们的重要性。
我们已经介绍了几乎所有用于获得重要特性的重要过程。
那么,让我们进入下一部分,结果分析。
结果分析
机器学习的另一个非常重要的部分是结果分析或解释。现在,通常情况下,我们理解结果意味着高准确性,但在机器学习的情况下并非如此。在机器学习中,准确性取决于许多其他因素。问题是为什么?让我们来看一个例子。假设有一个包含 100 封电子邮件的数据集,其中有 10 封是垃圾邮件。因此,我们形成 80%的训练集和 20%的测试集。现在,假设训练集有 9 封垃圾邮件,测试集有 1 封垃圾邮件。我们训练了我们的模型,但是由于垃圾邮件的实例较少,它没有正确地学习它。因此,该模型将所有内容分类为非垃圾邮件。现在,如果我们使用我们的测试数据集来评估我们的模型,那么它将给出 90%的准确性,因为 9 个实际上不是垃圾邮件。但是我们的模式实际上失败了。所以,我们不能只把准确性作为一个评价指标。
已经开发了几种方法来测量结果,最常用的是 ROC-AUC 曲线和精确回忆。
ROC- AUC 曲线
ROC 或接收器操作特性曲线用于可视化二元分类器的性能。它显示了真阳性率和假阳性率之间的权衡。
真阳性率=真阳性/(真阳性+假阴性)
假阳性率=假阳性/(真阴性+假阳性)
现在,它是如何工作的?分类模型实际上产生一个预测百分比,该百分比表示给定样本属于给定类别的可能性有多大。预测百分比可以是 0 到 100 之间的任何值。现在,它有一个阈值。在阈值以下,样本被分类为 0 类,在阈值以上,它被认为是 1 类。所以,假阳性,真阳性都取决于这个阈值。如果我们降低阈值,分类为 1 类的样本数量增加,因此假阳性增加,否则假阴性增加。ROC 曲线实际上滚动这个阈值,并相应地指出所有的真阳性和假阳性率。
AUC 代表“ROC 曲线下的面积”也就是说,AUC 测量整个 ROC 曲线下的整个二维面积。AUC 提供了对所有可能的分类阈值的综合绩效衡量。因此,AUC 越大,模型正确标记类别的机会就越大。所以,更多的是准确性。
我发现有一个很棒的帖子,它解释了我在这里使用的图片。
一个优秀的模型具有接近 1 的 AUC,这意味着它具有良好的可分性度量。差模型的 AUC 接近 0,这意味着它具有最差的可分性度量。事实上,这意味着它是往复的结果。它预测 0 是 1,1 是 0。当 AUC 为 0.5 时,意味着模型没有任何类别分离能力。
根据型号的容量,可能有 4 种情况。
案例 1:


这是模型正确预测每个点的理想情况。在实际数据中,正类和负类是不相交的集合,也就是说,一个点可以是真正的,也可以是真负的,但不能同时是真正的和真负的。在这里,我们可以看到模型正确地覆盖和分类了所有的点。因此,曲线下的面积是完整的 2D 盒面积,即 1,精度是 100%
案例二:


这些图表显示了模型的实际行为。在这里,我们可以看到有一个重叠部分,其中模型预测了一些错误的样本,即样本正类作为负类,反之亦然。重叠部分越小,模型的精确度越高。这里我们可以看到 AUC 是 0.7,而不是 1。
案例 3:没有技能分类器


这是一个模型基本没学到东西的案例。所以,它一直在平等的基础上预测两个类。所以,一半时间它分类正确,一半时间它是错误的。
案例 4:


在这种情况下,该模型将所有正类分类为负类,将负类分类为正类。所以,它做了一个完全错误的分类。因此,AUC 值为 0,准确率为 0%
这就是 ROC-AUC 曲线。让我们转向精确回忆。
精确召回
这些度量在用于评估二元分类模型的应用机器学习中也是有用的。
精度由下式给出:
精度=真阳性/(真阳性+假阳性)
召回由以下人员发出:
召回= TP / (TP + FN)
这两个指标在不平衡数据集的情况下非常有用。
如果数据集有太多的正类实例而几乎没有负类实例,那么模型将倾向于预测正类,因此假阳性更多,因此精度低。如果数据集有太多的负类实例而几乎没有正类实例,那么模型将倾向于预测负类,因此会有更多的假阴性,因此召回率低。
因此,在这两种情况下,这些指标可以给我们一个非常清晰的概念。让我们看看精确回忆曲线。

这就是精确回忆曲线的样子。精确回忆不考虑真正的否定。所以只关注正面类。现在,这些图表有一个无技能分类器基线作为参考。在 0.5 处是一条直线。曲线是在其基础上测量的,就像如果模型分类最好,则它是一个凸形的并且远离基线,否则它更接近。
我们已经研究了不同类型的性能矩阵。所以让我们在乳腺癌数据集上实现它。
我在这里使用了逻辑回归。
数据集的逻辑回归结果。
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(x, y, test_size=0.33, random_state=42)
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scale=scaler.fit(X_train)
X_train_scaled=scale.transform(X_train)
from sklearn.linear_model import LogisticRegression
model = LogisticRegression(solver='liblinear', random_state=0)
model.fit(X_train_scaled, y_train)
因此,这里的数据适合我们的模型,模型准备好进行预测。
x_test_scaled=scale.transform(X_test)
y_pred=model.predict(x_test_scaled)
from sklearn.metrics import accuracy_score
accuracy_score(y_test, y_pred)
我们的模型给出了 97%的准确率。这是一个非常高的精度,这意味着我们的主成分分析足够好。
ROC-AUC 曲线
让我们获得 ROC- AUC 曲线:
from sklearn.metrics import roc_curve
from sklearn.metrics import roc_auc_score
import numpy as np
i=0
y_pred_i=[]
y_test_i=[]
while i<len(y_pred):
    if y_pred[i]=='M':
        y_pred_i.append([1])
    else:
        y_pred_i.append([0])
    i+=1
y_pred_n=np.array(y_pred_i)
i=0
while i<len(y_pred):
    if y_test[i]=='M':
        y_test_i.append([1])
    else:
        y_test_i.append([0])
    i+=1
y_test_n=np.array(y_test_i)roc_auc_score(y_test_n, y_pred_n)
ROC 曲线下的 ROC AUC 分数或面积为 0.98
让我们检查图表。
from sklearn import metrics
import matplotlib.pyplot as plt
fpr, tpr, _ = metrics.roc_curve(y_test_n,  y_pred_n)
auc = metrics.roc_auc_score(y_test_n, y_pred_n)
plt.plot(fpr,tpr,label="breast_cancer, auc="+str(auc))
plt.legend(loc=4)
plt.show()

这是我们得到的 ROC 曲线。
现在,我们来看看精确回忆曲线。
from sklearn.metrics import precision_recall_curve
lr_precision, lr_recall, _ = precision_recall_curve(y_test_n, y_pred_n)
plt.plot(lr_recall, lr_precision, marker='.', label='Logistic')
plt.xlabel('Recall')
plt.ylabel('Precision')
plt.legend()
plt.show()

这是获得的精度-召回曲线。正如我们所看到的,它离基线很远。因此,我们的数据集非常好,精度令人满意。
结论
在本文中,我们已经看到了 PCA、特征选择方法和性能度量。这里是 Github 链接。希望这些文章有所帮助。
CNN 的数据预处理和网络构建
学习建立一个典型的端到端管道来训练 CNN

艾莉娜·格鲁布尼亚克在 Unsplash 上的照片
在本文中,我们将经历训练卷积神经网络的端到端管道,即组织数据到目录、预处理、数据扩充、模型建立等。
我们将在图像处理中常用的数据预处理技术上花费大量时间。这是因为在大多数深度学习项目中,预处理大约需要你 50–80%的时间,知道一些有用的技巧会对你的项目有很大帮助。我们将使用 Kaggle 的 flowers 数据集 来演示关键概念。为了直接进入代码,Kaggle 上发布了一个附带的笔记本(请使用 CPU 运行代码的初始部分,使用 GPU 进行模型训练)。
使用 Kaggle 笔记本探索和运行机器学习代码|使用来自多个数据源的数据
www.kaggle.com](https://www.kaggle.com/tanyadayanand/end-to-end-pipeline-for-training-cnns-resnet)
导入数据集
让我们从导入必要的库和加载数据集开始。这是每个数据分析过程中必不可少的一步。
***# Importing necessary libraries*** import keras
import tensorflow
from skimage import io
import os
import glob
import numpy as np
import random
import matplotlib.pyplot as plt
%matplotlib inline***# Importing and Loading the data into data frame
#class 1 - Rose, class 0- Daisy*** DATASET_PATH = '../input/flowers-recognition/flowers/'
flowers_cls = ['daisy', 'rose']
***# glob through the directory (returns a list of all file paths)*** flower_path = os.path.join(DATASET_PATH, flowers_cls[1], '*')
flower_path = glob.glob(flower_path)***# access some element (a file) from the list***
image = io.imread(flower_path[251])
数据预处理
图像—通道和尺寸
图像有不同的形状和大小。他们也来自不同的来源。例如,一些图像是我们所说的“自然图像”,这意味着它们是在真实世界中以颜色拍摄的。例如:
- 花的图片是自然的图像。
 - x 光图像是而不是自然图像。
 
考虑到所有这些变化,我们需要对任何图像数据进行一些预处理。RGB 是最流行的编码格式,我们遇到的大多数“自然图像”都是 RGB 格式的。此外,数据预处理的第一步是使图像尺寸相同。让我们继续讨论如何改变图像的形状和形式。
***# plotting the original image and the RGB channels***
f, (ax1, ax2, ax3, ax4) = plt.subplots(1, 4, sharey=True)
f.set_figwidth(15)
ax1.imshow(image)
***# RGB channels*
*# CHANNELID : 0 for Red, 1 for Green, 2 for Blue.*** 
ax2.imshow(image[:, : , 0]) *#Red*
ax3.imshow(image[:, : , 1]) *#Green*
ax4.imshow(image[:, : , 2]) *#Blue*
f.suptitle('Different Channels of Image')

形态变换
术语形态变换是指涉及图像的形状和形式的任何修改。这些非常常用于图像分析任务。虽然它们适用于所有类型的图像,但对于非自然的图像(来自真实世界的图片以外的来源)来说,它们尤其强大。典型的变换是侵蚀、扩张、张开和闭合。现在让我们看看实现这些形态变换的一些代码。
1。阈值处理
一种更简单的操作,我们把亮度高于某个阈值的所有像素转换成 1;具有小于阈值的值的像素被转换为零。这产生了一个二进制图像。
***# bin_image will be a (240, 320) True/False array*
*#The range of pixel varies between 0 to 255*
*#The pixel having black is more close to 0 and pixel which is white is more close to 255*
*# 125 is Arbitrary heuristic measure halfway between 1 and 255 (the range of image pixel)*** 
bin_image = image[:, :, 0] > 125
plot_image([image, bin_image], cmap='gray')

2。侵蚀、扩张、打开&关闭
侵蚀缩小亮区,放大暗区。另一方面,膨胀正好相反——它缩小黑暗区域,扩大明亮区域。
开口是侵蚀后的扩张。开口可以去除小亮点(即“盐”),连接小暗裂纹。这往往会“打开”(亮)特征之间的(暗)间隙。
关闭是扩张后侵蚀。闭合可以去除小暗斑(即“辣椒”),连接小亮裂。这有助于“封闭”(亮)特征之间的(暗)间隙。
所有这些都可以使用skimage.morphology模块来完成。基本的想法是让一个特定大小的圆盘(下面的 3)在图像周围移动,并使用它应用这些变换。
from skimage.morphology import binary_closing, binary_dilation, binary_erosion, binary_opening
from skimage.morphology import selem
***# use a disk of radius 3***
selem = selem.disk(3)
***# oprning and closing***
open_img = binary_opening(bin_image, selem)
close_img = binary_closing(bin_image, selem)
 ***# erosion and dilation***
eroded_img = binary_erosion(bin_image, selem)
dilated_img = binary_dilation(bin_image, selem)
plot_image([bin_image, open_img, close_img, eroded_img, dilated_img], cmap='gray')

正常化
归一化是预处理部分中最关键的步骤。这是指重新调整像素值,使它们位于一个限定的范围内。这样做的原因之一是有助于传播梯度的问题。我们将讨论多种归一化图像的方法。
***#way1-this is common technique followed in case of RGB images*** 
norm1_image = image/255
***#way2-in case of medical Images/non natural images***
norm2_image = image - np.min(image)/np.max(image) - np.min(image)
***#way3-in case of medical Images/non natural images*** 
norm3_image = image - np.percentile(image,5)/ np.percentile(image,95) - np.percentile(image,5)
plot_image([image, norm1_image, norm2_image, norm3_image], cmap='gray')

增强
这就把我们带到了数据预处理的下一个方面——数据扩充。很多时候,我们拥有的数据量不足以很好地完成分类任务。在这种情况下,我们执行数据扩充。例如,如果我们正在处理将宝石分为不同类型的数据集,我们可能没有足够数量的图像(因为高质量的图像很难获得)。在这种情况下,我们可以执行扩充来增加数据集的大小。增强通常用于基于图像的深度学习任务,以增加训练数据的数量和方差。增强只能在训练集上进行,而不能在验证集上进行。
如你所知,汇集增加了不变性。如果一张狗的照片在图像的左上角,通过池化,您将能够识别出狗是否在左上角的左/右/上/下。但是训练数据由像 翻转、旋转、裁剪、平移、照明、缩放、添加噪声、 等数据增强组成。模型学习所有这些变化。这大大提高了模型的准确性。因此,即使狗出现在图像的任何角落,模型也能够以很高的准确度识别它。
可能有多种类型的增强。基本类型使用以下变换类型之一来变换原始图像:
- 线性变换
 - 仿射变换
 
from skimage import transform as tf
 ***# flip left-right, up-down***
image_flipr = np.fliplr(image)
image_flipud = np.flipud(image)
plot_image([image, image_flipr, image_flipud])

***# specify x and y coordinates to be used for shifting (mid points)***
shift_x, shift_y = image.shape[0]/2, image.shape[1]/2
***# translation by certain units***
matrix_to_topleft = tf.SimilarityTransform(translation=[-shift_x, -shift_y])
matrix_to_center = tf.SimilarityTransform(translation=[shift_x, shift_y])
***# rotation***
rot_transforms =  tf.AffineTransform(rotation=np.deg2rad(45))
rot_matrix = matrix_to_topleft + rot_transforms + matrix_to_center
rot_image = tf.warp(image, rot_matrix)
***# scaling*** 
scale_transforms = tf.AffineTransform(scale=(2, 2))
scale_matrix = matrix_to_topleft + scale_transforms + matrix_to_center
scale_image_zoom_out = tf.warp(image, scale_matrix)
scale_transforms = tf.AffineTransform(scale=(0.5, 0.5))
scale_matrix = matrix_to_topleft + scale_transforms + matrix_to_center
scale_image_zoom_in = tf.warp(image, scale_matrix)
***# translation***
transaltion_transforms = tf.AffineTransform(translation=(50, 50))
translated_image = tf.warp(image, transaltion_transforms)
plot_image([image, rot_image, scale_image_zoom_out, scale_image_zoom_in, translated_image])

***# shear transforms***
shear_transforms = tf.AffineTransform(shear=np.deg2rad(45))
shear_matrix = matrix_to_topleft + shear_transforms + matrix_to_center
shear_image = tf.warp(image, shear_matrix)
bright_jitter = image*0.999 + np.zeros_like(image)*0.001
plot_image([image, shear_image, bright_jitter])

网络建设
现在让我们构建和训练模型。
选择架构
在本节中,我们将使用' ResNet '架构。由于 ResNets 在行业中已经变得相当普遍,所以有必要花一些时间来理解其架构的重要元素。先说这里提出的 原架构 。还有,在 2016 年,ResNet 团队已经在原架构 这里 提出了一些改进。利用这些修改,他们已经训练了超过 1000 层的网络(例如 ResNet-1001 )。

这里使用的“ResNet builder”模块基本上是一个 Python 模块,包含了 ResNet 的所有构建模块。我们将使用该模块导入 ResNet 的变体(ResNet-18、ResNet-34 等。).resnet.py 模块取自 此处 。它最大的好处是“跳过连接”机制允许非常深的网络。
运行数据生成器
数据生成器支持预处理—它将图像归一化(除以 255)并裁剪图像的中心部分 (100 x 100) 。
没有特别的理由将 100 作为尺寸,但是已经选择了它,以便我们可以处理所有大于 100*100 尺寸的图像。如果图像的任何尺寸(高度或宽度)小于 100 像素,则该图像将被自动删除。你可以根据需要把它改成 150 或者 200。
现在让我们设置数据发生器。下面的代码设置了一个定制的数据生成器,与 keras API 自带的略有不同。使用定制生成器的原因是为了能够根据手头的问题修改它(可定制性)。
import numpy as np
import keras
class **DataGenerator**(keras.utils.Sequence):
   ** 'Generates data for Keras'**
    def __init__(self, mode='train', ablation=None, flowers_cls=['daisy', 'rose'], 
                 batch_size=32, dim=(100, 100), n_channels=3, shuffle=True):
       ** *"""*
 *Initialise the data generator*
 *"""***
        self.dim = dim
        self.batch_size = batch_size
        self.labels = {}
        self.list_IDs = []
        ***# glob through directory of each class*** 
        for i, cls **in** enumerate(flowers_cls):
            paths = glob.glob(os.path.join(DATASET_PATH, cls, '*'))
            brk_point = int(len(paths)*0.8)
            if mode == 'train':
                paths = paths[:brk_point]
            else:
                paths = paths[brk_point:]
            if ablation **is** **not** None:
                paths = paths[:ablation]
            self.list_IDs += paths
            self.labels.update({p:i for p **in** paths})
        self.n_channels = n_channels
        self.n_classes = len(flowers_cls)
        self.shuffle = shuffle
        self.on_epoch_end()
    def __len__(self):
        **'Denotes the number of batches per epoch'**
        return int(np.floor(len(self.list_IDs) / self.batch_size))
    def __getitem__(self, index):
        **'Generate one batch of data'**
        ***# Generate indexes of the batch***
        indexes = self.indexes[index*self.batch_size:(index+1)*self.batch_size]
        ***# Find list of IDs***
        list_IDs_temp = [self.list_IDs[k] for k **in** indexes]
        ***# Generate data***
        X, y = self.__data_generation(list_IDs_temp)
        return X, y
    def on_epoch_end(self):
        **'Updates indexes after each epoch'**
        self.indexes = np.arange(len(self.list_IDs))
        if self.shuffle == True:
            np.random.shuffle(self.indexes)
    def __data_generation(self, list_IDs_temp):
        **'Generates data containing batch_size samples' *# X : (n_samples, *dim, n_channels)***
       ** *# Initialization***
        X = np.empty((self.batch_size, *self.dim, self.n_channels))
        y = np.empty((self.batch_size), dtype=int)
        delete_rows = []
       ** *# Generate data***
        for i, ID **in** enumerate(list_IDs_temp):
            ***# Store sample***
            img = io.imread(ID)
            img = img/255
            if img.shape[0] > 100 **and** img.shape[1] > 100:
                h, w, _ = img.shape
                img = img[int(h/2)-50:int(h/2)+50, int(w/2)-50:int(w/2)+50, : ]
            else:
                delete_rows.append(i)
                continue
            X[i,] = img
            ***# Store class***
            y[i] = self.labels[ID]
        X = np.delete(X, delete_rows, axis=0)
        y = np.delete(y, delete_rows, axis=0)
        return X, keras.utils.to_categorical(y, num_classes=self.n_classes)
首先,我们将训练数据存储在 nn 目录中(如果有 nn 类的话)。对于给定的批量大小,我们希望生成批量数据点,并将它们提供给模型。
第一个for循环“遍历”每个类(目录)。对于每个类,它将每个图像的路径存储在列表paths中。在训练模式中,它将paths子集化,以包含前 80%的图像;在验证模式下,它对最后 20%进行子集划分。在消融实验的特殊情况下,它只是对每一类的第一个ablation图像进行子集划分。
我们将所有图像(所有类别)的路径存储在一个组合列表self.list_IDs中。字典self.labels包含标签(作为path: class_number (0/1)的键:值对)。
在循环之后,我们调用方法on_epoch_end(),该方法创建一个长度为self.list_IDs的数组self.indexes,并对它们进行混洗(在每个时期的末尾混洗所有的数据点)。
_getitem_方法使用(混洗)数组self.indexes从路径列表self.list_IDs中选择batch_size个条目(路径)。
最后,方法__data_generation返回一批图像作为对 X,y,其中 X 的形状为(batch_size, height, width, channels),y 的形状为(batch size, )。注意__data_generation也做一些预处理——它标准化图像(除以 255)并裁剪图像中心 100 x 100 的部分。因此,每个图像具有形状(100, 100, num_channels)。如果图像的任何尺寸(高度或宽度)小于 100 像素,该图像将被删除。
消融实验
这些指的是获取一小块数据并在其上运行您的模型——这有助于判断模型是否正在运行。这被称为消融实验。
构建网络的第一步是让网络在数据集上运行。让我们试着仅在几幅图像和一个时期上拟合网络。注意,因为指定了ablation=100,所以使用每类 100 个图像,所以总批次数为np.floor(200/32) = 6。
注意,DataGenerator类“继承”自keras.utils.Sequence类,因此它拥有基础keras.utils.Sequence类的所有功能(比如model.fit_generator方法)。
***# using resnet 18***
model = resnet.ResnetBuilder.build_resnet_18((img_channels, img_rows, img_cols), nb_classes)
model.compile(loss='categorical_crossentropy', optimizer='SGD',
              metrics=['accuracy'])
***# create data generator objects in train and val mode*
*# specify ablation=number of data points to train on***
training_generator = DataGenerator('train', ablation=100)
validation_generator = DataGenerator('val', ablation=100)
***# fit: this will fit the net on 'ablation' samples, only 1 epoch***
model.fit_generator(generator=training_generator,
                    validation_data=validation_generator,
                    epochs=1,)

过拟合训练数据
下一步是尝试在训练数据上过度拟合模型。为什么我们要故意夸大我们的数据呢?简单地说,这将告诉我们网络是否能够学习训练集中的模式。这将告诉您模型的行为是否符合预期。
我们将使用 ablation=100(即在每类的 100 个图像上训练),因此它仍然是一个非常小的数据集,并且我们将使用 20 个时期。在每个时期,将使用 200/32=6 批。
***# resnet 18***
model = resnet.ResnetBuilder.build_resnet_18((img_channels, img_rows, img_cols), nb_classes)
model.compile(loss='categorical_crossentropy',optimizer='SGD',
              metrics=['accuracy'])
***# generators***
training_generator = DataGenerator('train', ablation=100)
validation_generator = DataGenerator('val', ablation=100)
***# fit***
model.fit_generator(generator=training_generator,
                    validation_data=validation_generator,
                    epochs=20)

训练精度随着每个历元不断增加
结果表明,训练精度随着每个历元不断提高。验证准确性也会增加,然后趋于平稳,这是“良好拟合”的标志,即我们知道该模型至少能够从一个小数据集学习,因此我们可以希望它也能够从整个数据集学习。
总而言之,对任何模型的一个好的测试是检查它是否能够过度适应训练数据(即训练损失随着时期持续减少)。这种技术在深度学习中特别有用,因为大多数深度学习模型都是在大型数据集上训练的,如果它们无法过度适应小版本,那么它们就不太可能从大版本中学习。
超参数调谐
我们在数据集的一小块上训练模型,并确认模型可以从数据集学习(通过过度拟合来指示)。在修复了模型和数据扩充之后,我们现在需要找到优化器的学习率(这里是 SGD)。首先,让我们列出想要优化的超参数:
- 学习速度和变化+优化器
 - 增强技术
 
基本思想是随着超参数的各种值的增加,跟踪验证损失。
Keras 回调
在你继续之前,让我们讨论一下回调。回调基本上是您希望在培训的特定情况下执行的操作。例如,我们希望在每个时期结束时执行存储丢失的操作(这里的实例是一个时期的结束)。
形式上,回调只是一个函数(如果您想要执行单个操作),或者一个函数列表(如果您想要执行多个操作),它们将在特定事件(一个时期的结束、每个批次的开始、准确性达到稳定状态时等)时执行。).Keras 通过类keras.callbacks.Callback提供了一些非常有用的回调功能。
Keras 有很多内置的回调函数(这里列出的)。在 keras 中创建自定义回调的一般方法是:
from keras import optimizers
from keras.callbacks import *
***# range of learning rates to tune***
hyper_parameters_for_lr = [0.1, 0.01, 0.001]
***# callback to append loss***
class **LossHistory**(keras.callbacks.Callback):
    def on_train_begin(self, logs={}):
        self.losses = []
    def on_epoch_end(self, epoch, logs={}):
        self.losses.append(logs.get('loss'))
***# instantiate a LossHistory() object to store histories***
history = LossHistory()
plot_data = {}
***# for each hyperparam: train the model and plot loss history***
for lr **in** hyper_parameters_for_lr:
    print ('**\n\n**'+'=='*20 + '   Checking for LR=**{}**  '.format(lr) + '=='*20 )
    sgd = optimizers.SGD(lr=lr, clipnorm=1.)
 ***# model and generators***
    model = resnet.ResnetBuilder.build_resnet_18((img_channels, img_rows, img_cols), nb_classes)
    model.compile(loss='categorical_crossentropy',optimizer= sgd,
                  metrics=['accuracy'])
    training_generator = DataGenerator('train', ablation=100)
    validation_generator = DataGenerator('val', ablation=100)
    model.fit_generator(generator=training_generator,
                        validation_data=validation_generator,
                        epochs=3, callbacks=[history])
 ***# plot loss history***
    plot_data[lr] = history.losses

在上面的代码中,我们创建了一个自定义回调,在每个时期结束时将丢失的数据追加到一个列表中。注意,logs是keras.callbacks.Callback的一个属性(一个字典),我们用它来获得键‘loss’的值。这个字典的其他一些关键字是acc、val_loss等。
为了告诉模型我们想要使用回调,我们创建了一个名为history的LossHistory对象,并使用callbacks=[history]将其传递给model.fit_generator。在这种情况下,我们只有一个回调history,尽管您可以通过这个列表传递多个回调对象(多个回调的示例在下一节中——参见DecayLR()的代码块)。
这里,我们调整了学习率超参数,并观察到与 0.01 和 0.001 相比,0.1 是最佳的学习率。然而,在整个训练过程中使用如此高的学习率并不是一个好主意,因为损失可能在稍后开始在最小值附近振荡。因此,在训练开始时,我们为模型使用高学习率来快速学习,但是随着我们进一步训练并向最小值前进,我们逐渐降低学习率。
***# plot loss history for each value of hyperparameter***
f, axes = plt.subplots(1, 3, sharey=True)
f.set_figwidth(15)
plt.setp(axes, xticks=np.arange(0, len(plot_data[0.01]), 1)+1)
for i, lr **in** enumerate(plot_data.keys()):
    axes[i].plot(np.arange(len(plot_data[lr]))+1, plot_data[lr])

上面的结果表明 0.1 的学习率是最好的,尽管在整个训练中使用如此高的学习率通常不是一个好主意。因此,我们应该使用学习率衰减——从高学习率开始,并随着每个时期衰减。
我们使用另一个自定义回调 ( DecayLR)来衰减每个时期结束时的学习率。衰减率被指定为 0.5 ^历元。另外,注意这次我们告诉模型使用两个回调(作为列表callbacks=[history, decay]传递给model.fit_generator)。
尽管我们在这里使用了自己的自定义衰减实现,但是您也可以使用内置在 keras 优化器中的实现(使用decay参数)。
***# learning rate decay***
class **DecayLR**(keras.callbacks.Callback):
    def __init__(self, base_lr=0.001, decay_epoch=1):
        super(DecayLR, self).__init__()
        self.base_lr = base_lr
        self.decay_epoch = decay_epoch 
        self.lr_history = []
    ***# set lr on_train_begin***
    def on_train_begin(self, logs={}):
        K.set_value(self.model.optimizer.lr, self.base_lr)
 ***# change learning rate at the end of epoch***
    def on_epoch_end(self, epoch, logs={}):
        new_lr = self.base_lr * (0.5 ** (epoch // self.decay_epoch))
        self.lr_history.append(K.get_value(self.model.optimizer.lr))
        K.set_value(self.model.optimizer.lr, new_lr)
***# to store loss history***
history = LossHistory()
plot_data = {}
***# start with lr=0.1***
decay = DecayLR(base_lr=0.1)
***# model***
sgd = optimizers.SGD()
model = resnet.ResnetBuilder.build_resnet_18((img_channels, img_rows, img_cols), nb_classes)
model.compile(loss='categorical_crossentropy',optimizer= sgd,
              metrics=['accuracy'])
training_generator = DataGenerator('train', ablation=100)
validation_generator = DataGenerator('val', ablation=100)
model.fit_generator(generator=training_generator,
                    validation_data=validation_generator,
                    epochs=3, callbacks=[history, decay])
plot_data[lr] = decay.lr_history

plt.plot(np.arange(len(decay.lr_history)), decay.lr_history)

增强技术
现在让我们编写一些代码来实现数据扩充。扩充通常是通过数据生成器完成的,即扩充的数据是动态地批量生成的。你可以使用内置的 keras ImageDataGenerator或者编写你自己的数据生成器(如果你想的话,可以定制一些特性等)。下面的代码显示了如何实现这些。
import numpy as np
import keras
***# data generator with augmentation***
class **AugmentedDataGenerator**(keras.utils.Sequence):
    **'Generates data for Keras'**
    def __init__(self, mode='train', ablation=None, flowers_cls=['daisy', 'rose'], 
                 batch_size=32, dim=(100, 100), n_channels=3, shuffle=True):
        **'Initialization'**
        self.dim = dim
        self.batch_size = batch_size
        self.labels = {}
        self.list_IDs = []
        self.mode = mode
        for i, cls **in** enumerate(flowers_cls):
            paths = glob.glob(os.path.join(DATASET_PATH, cls, '*'))
            brk_point = int(len(paths)*0.8)
            if self.mode == 'train':
                paths = paths[:brk_point]
            else:
                paths = paths[brk_point:]
            if ablation **is** **not** None:
                paths = paths[:ablation]
            self.list_IDs += paths
            self.labels.update({p:i for p **in** paths})
        self.n_channels = n_channels
        self.n_classes = len(flowers_cls)
        self.shuffle = shuffle
        self.on_epoch_end()
    def __len__(self):
        **'Denotes the number of batches per epoch'**
        return int(np.floor(len(self.list_IDs) / self.batch_size))
    def __getitem__(self, index):
       ** 'Generate one batch of data'**
        ***# Generate indexes of the batch***
        indexes = self.indexes[index*self.batch_size:(index+1)*self.batch_size]
        ***# Find list of IDs***
        list_IDs_temp = [self.list_IDs[k] for k **in** indexes]
       ** *# Generate data***
        X, y = self.__data_generation(list_IDs_temp)
        return X, y
    def on_epoch_end(self):
   **     'Updates indexes after each epoch'**
        self.indexes = np.arange(len(self.list_IDs))
        if self.shuffle == True:
            np.random.shuffle(self.indexes)
    def __data_generation(self, list_IDs_temp):
 **'Generates data containing batch_size samples' *# X : (n_samples, *dim, n_channels)***
        ***# Initialization***
        X = np.empty((self.batch_size, *self.dim, self.n_channels))
        y = np.empty((self.batch_size), dtype=int)
        delete_rows = []
       ** *# Generate data***
        for i, ID **in** enumerate(list_IDs_temp):
            ***# Store sample***
            img = io.imread(ID)
            img = img/255
            if img.shape[0] > 100 **and** img.shape[1] > 100:
                h, w, _ = img.shape
                img = img[int(h/2)-50:int(h/2)+50, int(w/2)-50:int(w/2)+50, : ]
            else:
                delete_rows.append(i)
                continue
            X[i,] = img
          **  *# Store class***
            y[i] = self.labels[ID]
        X = np.delete(X, delete_rows, axis=0)
        y = np.delete(y, delete_rows, axis=0)
 ***# data augmentation***
        if self.mode == 'train':
            aug_x = np.stack([datagen.random_transform(img) for img **in** X])
            X = np.concatenate([X, aug_x])
            y = np.concatenate([y, y])
        return X, keras.utils.to_categorical(y, num_classes=self.n_classes)
要优化的指标
根据具体情况,我们选择合适的指标。对于二元分类问题,AUC 通常是最好的度量。
AUC 通常是比准确性更好的指标。因此,让我们监控 AUC,并根据验证数据选择基于 AUC 的最佳模型,而不是针对准确性进行优化。我们将使用回调on_train_begin和on_epoch_end来初始化(在每个时期的开始)和存储 AUC(在时期的结束)。
from sklearn.metrics import roc_auc_score
class **roc_callback**(Callback):
    def on_train_begin(self, logs={}):
        logs['val_auc'] = 0
    def on_epoch_end(self, epoch, logs={}):
        y_p = []
        y_v = []
        for i **in** range(len(validation_generator)):
            x_val, y_val = validation_generator[i]
            y_pred = self.model.predict(x_val)
            y_p.append(y_pred)
            y_v.append(y_val)
        y_p = np.concatenate(y_p)
        y_v = np.concatenate(y_v)
        roc_auc = roc_auc_score(y_v, y_p)
        print ('**\n**Val AUC for epoch**{}**: **{}**'.format(epoch, roc_auc))
        logs['val_auc'] = roc_auc
最终运行
现在让我们来训练最终的模型。请注意,我们将继续在models/best_models.hdf5保存最佳模型的权重,因此您需要创建一个目录models。请注意,模型权重通常保存在 hdf5 文件中。
保存最佳模型是使用ModelCheckpoint附带的回调功能完成的。我们基本上指定了保存模型权重的filepath,monitor='val_auc'指定了您正在基于验证准确性选择最佳模型,save_best_only=True仅保存最佳权重,mode='max'指定了验证准确性将被最大化。
***# model***
model = resnet.ResnetBuilder.build_resnet_18((img_channels, img_rows, img_cols), nb_classes)
model.compile(loss='categorical_crossentropy',optimizer= sgd,
              metrics=['accuracy'])
training_generator = AugmentedDataGenerator('train', ablation=32)
validation_generator = AugmentedDataGenerator('val', ablation=32)
***# checkpoint*** 
filepath = 'models/best_model.hdf5'
checkpoint = ModelCheckpoint(filepath, monitor='val_auc', verbose=1, save_best_only=True, mode='max')
auc_logger = roc_callback()
***# fit*** 
model.fit_generator(generator=training_generator,
                    validation_data=validation_generator,
                    epochs=3, callbacks=[auc_logger, history, decay, checkpoint])

plt.imshow(image)

***#*standardizing *image
#moved the origin to the centre of the image***
h, w, _ = image.shape
img = image[int(h/2)-50:int(h/2)+50, int(w/2)-50:int(w/2)+50, : ]
model.predict(img[np.newaxis,: ])

嘿,我们有一个非常高的概率为 1 类,即玫瑰。如果你还记得的话,0 班是黛西,1 班是罗斯(在博客上面)。因此,模型已经学习得很好了。我们已经建立了一个在 3 个时期结束时具有良好 AUC 的模型。如果您使用更多的纪元来训练,您应该能够达到更好的 AUC 值。
如果你有任何问题、建议或批评,可以通过 LinkedIn 或评论区联系我。
C++中的数据预处理和可视化
关于如何使用 C++实现机器学习的基本功能的工作代码示例
“我们相信上帝。所有其他人都必须带数据。”— W. Edwards Deming,统计学家、教授、作家、讲师和顾问。

卢克·切瑟在 Unsplash 上的照片
D 数据预处理是将原始数据转换成计算机可理解格式的过程,它是任何机器学习操作的第一步。数据收集通常控制松散,可能会导致超出范围的值。数据准备和过滤步骤可能需要相当长的处理时间。
数据预处理包括:
- 从文件中读取数据。
 - 数据清理。
 - 实例选择。
 - 数据标准化。
 - 数据转换。
 - 特征提取和选择。
 
要了解更多详情,您可以查看以下视频
数据预处理的产物就是最终的训练集。在本文中,我将介绍使用 C++时的一些数据预处理步骤,以及使用 Matplotlib-Cpp 库的数据可视化。
这篇文章是解决机器学习算法在 C++中实现的系列文章的一部分,在整个系列中,我们将使用 Iris 数据集这里。
- 什么时候应该学习使用 C++的机器学习?
 - 每个 C++开发人员必读的 8 本书。
 - c++中的数据预处理和可视化。
 - 使用 C++进行机器学习数据操作。
 - 使用 C++ 从零开始的朴素贝叶斯。
 - 线性回归在 C++中的实现。
 
请注意,已经有一些库可以轻松完成这项工作,但是本系列的目的是学习如何从头开始开发这些算法。如果您有兴趣了解更多关于 c++ ML 库的信息,您可以阅读这篇文章:
我喜欢使用 C++,甚至在我发现了用于机器学习的 Python 编程语言之后。C++…
www.analyticsvidhya.com](https://www.analyticsvidhya.com/blog/2020/05/introduction-machine-learning-libraries-c/)
在本文中,我将使用 i ris 数据集作为我们可以对其执行每个操作的数据示例,同时请注意,我将在本教程中使用 C++11。
从文件中读取数据:
从这里下载 iris.data 文件后。让我们用简单的读文件指令从文件中读取数据,并在单独的向量中解析每种类型的数据。
从文件中读取数据
在这段代码中,我们使用 ifstream 从一个文件创建了一个简单的输入流。
我们还使用多个向量来读取数据集中的每种信息,然后将所有数据添加到一个二维向量中。
在 iris 数据集中,除了 iris 类数据是字符串类型之外,所有数据都来自相同的数据类型,因此我必须将其转换为 enum 类型,并将其作为 float 进行处理,以匹配 Iris_Dataset 向量中的其余数据。
但是,您总是可以使用其他方式加载不同类型的数据,例如,您可以创建一个结构并在其上加载数据,或者为 iris 数据集创建一个类并在该类上加载数据。
现在,我决定用这种简单的方法来处理相同数据类型的数据。
数据可视化:
图像胜于文字,直观地表示数据对于理解数据、收集数据信息和识别异常值非常重要。
虽然这在使用 C++开发机器学习算法时似乎不太重要,因为大多数情况下,您将使用 python 等其他语言的数据来测试和实现算法,然后可以将算法转换为 C++,但我相信这对于在实现过程中可视化数据(例如用于调试目的)非常重要。
在本文中,我将使用 Matplotlib-CPP ,它是 Matplotlib 的 python APIs 的简单包装器。请查看文档以了解更多关于该库的信息。
使用 Matplotlib-CPP 很简单,您只需要包含头文件“matplotlibcpp.h”并将其与 python 库链接。下面是来自 GitHub 库的一个最小的例子:

来自 matplotlib-cpp 的最小示例
现在,我将只使用标准绘图 API 表示四个 iris 属性的数据:

用绘图法绘制虹膜数据集
使用 bar API 表示数据的另一种方式是:

利用条形法绘制虹膜数据集
数据清理:
从数据集中检测并纠正(或删除)损坏或不准确数据的过程,例如,在数据收集阶段可能会引入一些缺失、不一致的值或异常值。
在前面的函数中,您可能注意到我使用了 replace std::replace 函数来替换一些值。这一步可用于在将数据读入向量之前删除或替换任何值。例如,我怀疑“,”或“-”可能会混淆从文件中加载的值,所以我决定使用统一的读取方式,用其他值替换它们。
另一种方法是使用[迭代器](http://Iterators in C++ STL)和λ表达式移除或替换添加到向量中的数据。
这是一个去除萼片长度大于 5.8 的值的例子。

移除大于 5.8 的值
这可以通过添加一行代码来完成
数据标准化:
数据标准化是机器学习模型中提高模型精度的重要步骤。要了解更多关于数据标准化的重要性,您可以阅读以下文章:
要素缩放简介我最近在处理一个数据集,该数据集包含多个要素,跨越不同的…
www.analyticsvidhya.com](https://www.analyticsvidhya.com/blog/2020/04/feature-scaling-machine-learning-normalization-standardization/) [## 为什么数据规范化对于机器学习模型是必要的
标准化是一种经常作为机器学习的数据准备的一部分而应用的技术。正常化的目标…
medium.com](https://medium.com/@urvashilluniya/why-data-normalization-is-necessary-for-machine-learning-models-681b65a05029)
标准化数据集包括重新调整值的分布,使观察值的平均值为 0,标准偏差为 1。这将需要减去平均值并除以标准偏差。
首先,我们实现了一个计算平均值的 API:
使用模板计算平均值
这个 API 将获取任何标准类型的向量并计算平均值。可以使用类似的方法来计算标准偏差。
使用模板函数计算标准偏差
计算萼片长度的平均值和标准偏差:
CPP 中的均值和标准差计算

计算萼片长度平均值和标准偏差
我们可以在应用标准化之前将数据可视化:

原始萼片长度直方图
然后我们可以应用这一行代码来计算标准化后的值:
使用 lambda 表达式减去平均值并除以每个向量值的标准偏差

标准化后计算的平均值和标准偏差

标准化萼片长度直方图
在本文中,我们给出了一些数据预处理步骤的实现示例,我们介绍了从文件中读取数据、使用 Matplotlibcpp 进行数据可视化、数据清理,以及在数据标准化过程中对数据执行一些操作,如均值和标准差。
推荐书籍:
- c++编程语言,作者比雅尼·斯特劳斯特鲁普
 - 安德烈·布尔科夫所著的百页机器学习书籍
 - 完全初学者的机器学习,作者奥利弗·西奥博尔德
 
或者你可以跟随这些教程
或者访问这篇文章谈 每个机器学习开发者必读的 9 本书&每个 C++编程开发者必读的 8 本书。
这篇文章是解决机器学习算法在 C++中实现的系列文章的一部分,在整个系列中,我们将使用 Iris 数据集这里。
- 什么时候应该学习使用 C++的机器学习?
 - 每个 C++开发人员必读的 8 本书。
 - c++中的数据预处理和可视化。
 - 使用 C++进行机器学习数据操作。
 - 使用 C++ 从零开始的朴素贝叶斯。
 - 线性回归在 C++中的实现。
 
也请查看我的最新文章:
[## ML 模型的版本控制:为什么需要它,它是什么,如何实现它— neptune.ai
版本控制在任何软件开发环境中都很重要,在机器学习中更是如此。在 ML 中…
medium.com](https://medium.com/coderbyte/version-control-for-ml-models-why-you-need-it-what-it-is-how-to-implement-it-neptune-ai-497ff85b2b1a) [## 加入我的介绍链接媒体-艾哈迈德哈希什
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@ahmhashesh/membership)
感谢你到此为止,查看其他已发表的故事:
长时记忆模型和近期工作综述
medium.com](https://medium.com/ml2b/introduction-to-compressive-transform-53acb767361e) [## 变压器综合指南
关注是你所需要的,甚至更多
pub.towardsai.net](https://pub.towardsai.net/comprehensive-guide-to-transformers-6c73a9e6e2df)
了解数据预处理

弗兰基·查马基在 Unsplash 上拍摄的照片
数据预处理是一项重要的任务。它是一种数据挖掘技术,将原始数据转换成更容易理解、有用和有效的格式。
数据有更好的想法。这种思路在进行数据预处理后会更加清晰易懂。
为什么需要数据预处理?
真实世界的数据通常是:
不完整:某些属性或值或两者缺失,或者只有汇总数据。
噪音:数据包含错误或异常值
不一致:数据包含代码或名称等差异。
数据预处理中的任务
- 数据清洗:又称擦洗。这项任务包括填充缺失值、平滑或去除噪声数据和异常值,以及解决不一致问题。
 - 数据集成:该任务涉及集成来自多个来源的数据,如数据库(关系型和非关系型)、数据立方体、文件等。数据源可以是同类的,也可以是异类的。从源获得的数据在格式上可以是结构化的、非结构化的或半结构化的。
 - 数据转换:这包括根据数据集的需要对数据进行标准化和汇总。
 - 数据缩减:在此步骤中,数据被缩减。可以减少记录的数量或属性或维度的数量。进行缩减时要记住,缩减后的数据应该产生与原始数据相同的结果。
 - 数据离散化:被认为是数据约简的一部分。数值属性被标称属性取代。
 
数据清理
数据清理过程检测并消除数据中存在的错误和不一致,并提高数据质量。由于数据输入过程中的拼写错误、缺少值或任何其他无效数据,会出现数据质量问题。基本上,“脏”数据被转换成干净的数据。“脏”数据不会产生准确而好的结果。垃圾数据给出了垃圾。因此处理这些数据变得非常重要。专业人士在这一步花了很多时间。
“脏”或“不干净”数据的原因
- 虚拟值
 - 数据缺失
 - 违反商业规则
 - 数据集成问题
 - 矛盾的数据
 - 地址线使用不当
 - 重用的主键
 - 非唯一标识符
 
如何清理数据?
- 处理缺失值
 - 处理噪音和异常值
 - 删除不需要的数据
 
处理缺失值
无法在数据集中查看缺失值。他们必须被处理。此外,许多模型不接受缺失值。有几种处理缺失数据的技术,选择正确的技术至关重要。处理缺失数据的技术选择取决于问题域和数据挖掘过程的目标。处理缺失数据的不同方法有:
- 忽略数据行:对于缺少最大数量数据的记录,建议使用这种方法,这样记录就没有意义了。当只有较少的属性值丢失时,通常避免使用这种方法。如果忽略(即删除)所有缺失值的行,将会导致性能下降。
 - 手动填充缺少的值:这是一个非常耗时的方法,因此对于几乎所有场景都不可行。
 - 使用一个全局常量来填充缺失值:像“NA”或 0 这样的全局常量可以用来填充所有缺失的数据。这种方法用于难以预测缺失值的情况。
 - 使用属性均值或中值:属性的均值或中值用于填充缺失值。
 - 使用向前填充或向后填充方法:在这种情况下,要么使用前一个值,要么使用下一个值来填充缺少的值。也可以使用先前和后续值的平均值。
 - 使用数据挖掘算法预测最可能的值
 
处理噪音和异常值
数据中的噪声可能由于数据收集中的错误、数据输入期间的错误或由于数据传输错误等而被引入。未知的编码(例如:婚姻状况— Q)、超出范围的值(例如:年龄— 10)、不一致的数据(例如:出生日期—1999 年 10 月 4 日,年龄— 50)、不一致的格式(例如:司法部—2000 年 1 月 13 日,出生日期—2016 年 10 月 10 日)等。是不同类型的噪声和异常值。
可以使用宁滨处理噪音。在这种技术中,排序后的数据被放入箱或桶中。可以通过等宽(距离)或等深(频率)划分来创建箱。在这些箱上,可以应用平滑。平滑可以通过条均值、条中值或条边界来实现。
使用宁滨平滑异常值,然后对其进行平滑。它们可以通过视觉分析或箱线图检测出来。聚类可用于识别离群数据组。可以平滑或去除检测到的异常值。
删除不需要的数据
不需要的数据是重复的或不相关的数据。如果效率不高,从不同来源抓取数据然后集成可能会导致一些重复数据。应该删除这些冗余数据,因为它们没有任何用处,只会增加数据量和训练模型的时间。此外,由于冗余记录,该模型可能无法提供准确的结果,因为重复数据会干扰分析过程,从而使重复值更加重要。
数据集成
在这个步骤中,准备一个相干数据源。这是通过从多个来源(如数据库、遗留系统、平面文件、数据立方体等)收集和集成数据来实现的。
数据就像垃圾。在你收集它之前,你最好知道你要用它做什么。——马克·吐温
数据集成中的问题
- 模式集成:来自不同来源的元数据(即模式)可能不兼容。这就导致了实体识别问题 。例:考虑两个数据源 R 和 S,R 中的客户 id 表示为 cust_id,S 中表示为 c_id。它们表示相同的东西,代表相同的东西,但是有不同的名称,这导致了集成问题。检测和解决这些问题对于获得一致的数据源非常重要。
 - 数据值冲突:对于不同数据源中的相同真实世界实体,相同数据的值、度量或表示可能不同。这导致相同数据的不同表示、不同的比例等。示例:数据源 R 中的重量以千克表示,而源 S 中的重量以克表示。要解决这个问题,应该使数据表示一致,并相应地执行转换。
 - 冗余数据:在整合不同来源的数据时,可能会出现重复的属性或元组。这也可能导致不一致。通过仔细整合来自多个来源的数据,可以减少这些冗余或不一致。这将有助于提高挖掘速度和质量。此外,可以执行相关分析来检测冗余数据。
 
数据整理
如果数据非常大,则执行数据缩减。有时,还会从大量属性中找出最合适的属性子集。这就是所谓的降维。数据简化还包括减少属性值的数量和/或元组的数量。各种数据简化技术包括:
- 数据立方体聚集:在这种技术中,通过应用像切片、切块或卷起这样的 OLAP 操作来减少数据。它使用解决问题所需的最小级别。
 - 降维:对数据属性或维度进行降维。并非所有属性都是数据挖掘所必需的。通过使用如正向选择、反向消除、决策树归纳或正向选择和反向消除的组合的技术来选择最合适的属性子集。
 - 数据压缩:在这种技术中。大量数据被压缩,即用于存储数据的位数减少。这可以通过使用有损或无损压缩来实现。在有损压缩中,为了进一步压缩,数据质量会受到影响。在无损压缩中,更高的压缩级别不会影响数据质量。
 - 数量减少:这种技术通过选择更小的数据表示形式来减少数据量。可以使用直方图、聚类或数据采样来减少数量。减少数量是必要的,因为处理整个数据集既昂贵又耗时。
 
Python 中机器学习的数据预处理

介绍
数据预处理是机器学习中至关重要的一步,对模型的准确性至关重要。数据包含噪音、缺失值、不完整,有时其格式不可用,无法直接用于机器学习模型。但是如果我们使用有问题和肮脏的数据呢?最后的结果会是什么,这个决定是否可信?预处理数据是关键—预处理的目标是获得更有意义的可信数据。这些技术允许我们将原始数据转换成干净和可用的数据集,并通过重新缩放、标准化、二进制化等使数据更有意义。
数据预处理概念
在下面的例子中,我们将使用一个包含汽车的文件,它可以从https://www.kaggle.com/antfarol/car-sale-advertisements下载。我们将使用 Python 进行数据预处理,并使用几个重要的库:
- pandas——一个提供快速、灵活和富有表现力的数据结构的包,旨在使处理“关系”或“带标签”的数据既简单又直观;
 - sci kit-learn——一个提供许多非监督和监督学习算法的库,建立在 NumPy、pandas 和 Matplotlib 之上;
 - stats model——允许用户探索数据、估计统计模型和执行统计测试的软件包;
 - matplotlib——绘图库;
 - seaborn——一个用 Python 制作统计图形的库。它构建在 matplotlib 之上,并与 pandas 数据结构紧密集成。
 
有许多方法和概念可以使用,但在本例中,我们将只看到其中的一部分:
- 处理缺失值
 - 处理异常值
 - 多重共线性
 - 处理分类值
 - 标准化
 
加载数据
第一步是加载数据。我们可以阅读。csv 文件,使用方法 head,我们可以看到数据集中的前 5 行。

发现数据
现在,让我们来发现数据。我们可以使用 describe 方法-如果使用此方法,我们将仅获得数字特征的描述性统计数据。我们可以通过使用 include='all '来包含所有这些内容。

我们可以看到每个列的唯一值和最常见的类别。例如,我们可以看到列 registration 包含 9015 个值 yes,并且它有两个唯一的值。此外,我们还可以看到平均值、标准差、最大值和最小值等等。
处理缺失值
检查缺失值的一种简单方法是使用 isnull 方法。我们将获得一个包含真(1)和假(0)值的数据框,因此我们将对这些值求和,并可以看到哪一列中有缺失值。

我们可以用两种方法处理缺失值:
1.消除缺失值:
a.删除行:我们可以删除缺失值不可接受的行。这可以通过使用 dropna 方法来完成。这样,我们将排除包含缺失值的行。

b.删除列:如果该列有 95%或更多的缺失值,则可以且需要将其删除,因为缺失值的估计值不可信,因为它是从 5%(或更少)的数据中计算出来的,因此是不相关的。
2.估计缺失值:如果只有可接受百分比的值缺失,我们可以估计这些值。这可以通过用相应特征的平均值、中间值或最频繁值填充值来完成。
此外,有多种方法可用于输入缺失值。我们可以使用简单估算、迭代估算或分类估算。分类输入器用于输入分类特征。

在这之后,如果我们调用方法 describe 我们可以看到,在 price 列中,我们拥有与 car 和 body 相同的计数。我们缺少的值将替换为此列中所有值的平均值。

处理异常值
如果我们正在处理回归,这是一个非常重要的话题。我们将绘制列价格的分布图。为了获得最佳结果,我们正在寻找正态分布。但是,价格是指数级的。如果我们使用回归,这将是一个问题。我们可以在上表中看到,价格的最小值是 259,最大值是 547,800,平均值是 16,182。另外,我们可以看到,25%的值在 5500 以下,75%的值在 16800 以下。因此,在这种情况下,我们有离群值。异常值是指与数据中的其他观察值相距异常距离的观察值,它们会显著影响回归。因此,回归将尝试使直线更接近这些值。

通常的规则是去除所有远离平均值 3 倍标准差的东西。这是什么意思?对于正态分布的值,有一个已知的规则:68–95–99.7。该规则可以解释为:
- 68%的数据分布在区间[均值—标准差,均值+标准差],
 - 95%的数据分布在区间[均值— 2 *标准差,均值+ 2 *标准差],
 - 99.7%的数据分布在区间[均值— 3 *标准差,均值+ 3 *标准差]。
 
基于此,我们可以说,超出区间[mean-3 * STD,mean + 3*std]的值是异常值,这些值可以删除。

最大值离平均值仍然很远,但已经可以接受地接近了。我们现在可以绘制分布图,我们可以看到数据仍然以相同的方式分布,但离群值较少。我们也可以对里程列这样做。

多重共线性
在多元回归方程中,只要一个自变量与一个或多个其他自变量高度相关,就存在多重共线性。多重共线性是一个问题,因为它破坏了独立变量的统计意义。
不幸的是,使用 scikit-learn 我们不能直接确定是否存在多重共线性。我们可以通过使用 statsmodels 来做到这一点。检查多重共线性的最佳方法之一是通过 VIF(方差膨胀因子)。VIF 提出了一种方法,与变量与其他预测因子完全不相关的情况相比,该方法可以估计估计值的标准误差的平方根变大的程度。VIF 的数值告诉我们(以十进制形式)每个系数的方差(即标准误差平方)膨胀的百分比。例如,1.9 的 VIF 告诉我们,如果没有多重共线性(如果与其他预测值没有相关性),特定系数的方差比我们预期的值大 90%。
在我们的例子中,我们可以说:如果里程数越少,价格就越高。还有,车越老,价格就越小。因此,我们可以检查这三列的多重共线性。

当 VIF 值等于 1 时,根本不存在多重共线性。介于 1 和 5 之间的值被认为是完全可以的。但是,对于什么样的值是可接受的,并没有精确的定义。我们可以在不同的资源中发现,低于 5、6 甚至 10 的值都是可以接受的。因此,在我们的示例中,我们可以看到所有的值都低于 5,它们是正常的。我们很难找到所有特性的值都低于 5 的数据。我们可以说我们的数据集没有多重共线性。如果存在多重共线性,我们应该使用 drop 方法删除该列。作为输入,我们将设置想要删除的列,并且 axis = 1 —这意味着我们将删除一列。例如,假设我们想从数据集中删除列 year。

处理分类值
虚拟编码是将分类输入变量转换为连续变量的常用方法。顾名思义,Dummy 是一个重复变量,它代表一个分类变量的一个级别。水平的存在由 1 表示,不存在由 0 表示。对于出现的每个级别,将创建一个虚拟变量。在 Python 中,我们可以使用 get_dummies 方法,该方法返回一个包含一个热编码列的新数据帧。

标准化
处理完分类值后,我们可以对值进行标准化。它们不在一个尺度上;因此,我们的模型将赋予具有较大值的列更大的权重,这不是理想的情况,因为其他列对于构建模型很重要。为了避免这个问题,我们可以执行标准化。
注意:在一些例子中,标准化可能不会给出更好的结果,甚至可能更糟。
我们将使用 scikit-learn 中的 class StandardScaler。StandardScaler 背后的想法是,它将转换数据,使其分布具有平均值 0 和标准差 1。

结论
本文的目的是展示如何使用一些数据预处理技术,并深入了解这些技术的应用场合。还有其他形式的数据清理也是有用的,但是现在,我们在制定任何模型之前覆盖那些重要的。更好更干净的数据胜过最好的算法。如果我们使用一个非常简单的算法对数据进行清理,我们会得到非常令人印象深刻和准确的结果。
如果你对这个话题感兴趣,请随时联系我。
领英简介:【https://www.linkedin.com/in/ceftimoska/
博客原文可从以下链接获得:https://interworks . com . MK/data-pre-processing-for-machine-learning-in-python/
另外,你可以在下面的链接中找到另一篇类似的博文:https://interworks.com.mk/focusareas/data-management/
使用 Python Pandas 进行数据预处理
第 1 部分—缺失数据

本教程解释了如何使用 pandas 库预处理数据。预处理是对数据进行预分析的过程,目的是将数据转换成标准和规范化的格式。
预处理包括以下几个方面:
- 缺少值
 - 数据标准化
 - 数据标准化
 - 宁滨数据
 
在本教程中,我们只处理缺失值。
你可以从我的 Github 数据科学库下载本教程的源代码作为 Jupyter 笔记本。
输入数据
在本教程中,我们将使用与肝炎相关的数据集,可以从此链接下载。
首先,使用 pandas 库导入数据,并将它们转换成 dataframe。通过head(10)方法,我们只打印数据集的前 10 行
**import** pandas **as** pd
df **=** pd.read_csv('hepatitis.csv')
df.head(10)

识别缺失值
我们注意到数据集存在一些问题。例如,“电子邮件”列并不适用于所有行。在某些情况下,它会显示NaN值,这意味着该值缺失。
为了检查我们的数据集是否包含缺失值,我们可以使用函数isna(),该函数返回数据集的单元格是否为NaN。然后我们可以计算每一列有多少个缺失值。
df.isna().sum()
它给出了以下输出:
age                 0
sex                 0
steroid             1
antivirals          0
fatigue             1
malaise             1
anorexia            1
liver_big          10
liver_firm         11
spleen_palpable     5
spiders             5
ascites             5
varices             5
bilirubin           6
alk_phosphate      29
sgot                4
albumin            16
protime            67
histology           0
class               0
dtype: int64
现在我们可以计算每列缺失值的百分比,只需将之前的结果除以数据集的长度(len(df))并乘以 100。
df.isna().sum()**/**len(df)*****100
它给出了以下输出:
age                 0.000000
sex                 0.000000
steroid             0.645161
antivirals          0.000000
fatigue             0.645161
malaise             0.645161
anorexia            0.645161
liver_big           6.451613
liver_firm          7.096774
spleen_palpable     3.225806
spiders             3.225806
ascites             3.225806
varices             3.225806
bilirubin           3.870968
alk_phosphate      18.709677
sgot                2.580645
albumin            10.322581
protime            43.225806
histology           0.000000
class               0.000000
dtype: float64
处理缺失值时,可以采用不同的替代方法:
- 检查数据源,例如通过联系数据源来更正缺少的值
 - 删除缺少的值
 - 用一个值替换缺少的值
 - 保留缺少的值不变。
 
删除缺少的值
删除缺少的值可以是以下方法之一:
- 删除缺少值的行
 - 删除包含缺失值的整列,我们可以通过指定要考虑的
axis来使用dropna()。如果我们设置了axis = 0,我们将删除整个行;如果我们设置了axis = 1,我们将删除整个列。如果我们应用函数df.dropna(axis=0),数据集的 80 行仍然存在。如果我们应用函数df.dropna(axis=1),只有年龄、性别、抗病毒药物、组织学和类别这几列保留下来。但是,移除的值不会应用于原始数据帧,而只会应用于结果。我们可以使用参数inplace=True来存储原始数据帧df(df.dropna(axis=1,inplace=True))中的更改。 
df.dropna(axis**=**1)

或者,我们可以只指定必须对其应用删除操作的列。在下面的示例中,只考虑与列liver_big相关的缺失行。这可以通过subset参数来实现,该参数允许指定应用删除操作的列子集。
df.dropna(subset**=**['liver_big'],axis**=**0,inplace**=True**)
现在我们可以检查列indirizzo是否还有缺失的值。
df.isna().sum()/len(df)*100
另一种方法是删除有一定百分比的非空值的列。这可以通过thresh参数来实现。在下面的例子中,我们只保留至少有 80%的非空值的列。
df.dropna(thresh**=**0.8*****len(df),axis**=**1,inplace**=True**)
替换丢失的值
处理缺失值的一个好策略是用另一个值替换它们。通常采用以下策略:
- 对于数值,用列的平均值替换缺少的值
 - 对于类别值,用该列中最常见的值替换缺失的值
 - 使用其他功能
 
为了替换丢失的值,可以使用三个函数:fillna()、replace()和interpolate()。fillna()函数用作为参数传递的值替换所有 NaN 值。例如,对于数值,数值列中的所有 NaN 值都可以替换为平均值。为了列出列的类型,我们可以使用属性dtypes如下:
df.dtypes
它给出了以下输出:
age                  int64
sex                 object
steroid             object
antivirals            bool
fatigue             object
malaise             object
anorexia            object
liver_big           object
liver_firm          object
spleen_palpable     object
spiders             object
ascites             object
varices             object
bilirubin          float64
alk_phosphate      float64
sgot               float64
albumin            float64
histology             bool
class               object
dtype: object
数字列
首先,我们选择数字列。
**import** numpy **as** np
numeric **=** df.select_dtypes(include**=**np.number)
numeric_columns **=** numeric.columns
然后,我们用平均值填充数值列的 NaN 值,平均值由df.mean()函数给出。
df[numeric_columns] **=** df[numeric_columns].fillna(df.mean())
现在,我们可以检查数字列中的 NaN 值是否已被删除。
df.isna().sum()**/**len(df)*****100
它给出了以下输出:
age                0.000000
sex                0.000000
steroid            0.689655
antivirals         0.000000
fatigue            0.000000
malaise            0.000000
anorexia           0.000000
liver_big          0.000000
liver_firm         0.689655
spleen_palpable    0.689655
spiders            0.689655
ascites            0.689655
varices            0.689655
bilirubin          0.000000
alk_phosphate      0.000000
sgot               0.000000
albumin            0.000000
histology          0.000000
class              0.000000
dtype: float64
类别列
我们注意到在dtypes中,类别列被描述为对象。因此我们可以选择object列。我们只想考虑布尔列。然而,object类型也包括列class,它是一个字符串。我们选择所有的对象列,然后从它们中移除列class。然后我们可以将结果的类型转换为bool。
boolean_columns **=** df.select_dtypes(include**=**np.object).columns.tolist()
boolean_columns.remove('class')
df[boolean_columns] **=** df[boolean_columns].astype('bool')
现在,我们可以用最频繁的值替换所有缺少的值。我们可以使用mode()函数来计算最频繁的值。我们使用fillna()函数来替换丢失的值,但是我们也可以使用replace(old_value,new_value)函数。
df[boolean_columns].fillna(df.mode())
现在我们的数据集不包含任何缺失值。
df.isna().sum()**/**len(df)*****100
它给出了以下输出:
age                0.0
sex                0.0
steroid            0.0
antivirals         0.0
fatigue            0.0
malaise            0.0
anorexia           0.0
liver_big          0.0
liver_firm         0.0
spleen_palpable    0.0
spiders            0.0
ascites            0.0
varices            0.0
bilirubin          0.0
alk_phosphate      0.0
sgot               0.0
albumin            0.0
histology          0.0
class              0.0
dtype: float64
插入文字
替换缺失值的另一种解决方案包括使用其他函数,例如线性插值。例如,在这种情况下,我们可以用上一列和下一列之间的插值来替换一个缺失的值。这可以通过使用interpolate()功能来实现。
因为我们已经管理了所有丢失的值,所以我们重新加载数据集。
df **=** pd.read_csv('hepatitis.csv')
df.isna().sum()**/**len(df)*****100
我们只选择数字列。
numeric **=** df.select_dtypes(include**=**np.number)
numeric_columns **=** numeric.columns
df.head(10)

现在我们可以将interpolate()函数应用于数字列,方法是将限制方向也设置为forward。这意味着从第一行开始应用线性插值,直到最后一行。
df[numeric_columns] **=** df[numeric_columns].interpolate(method **=**'linear', limit_direction **=**'forward')
例如,在第 6 行中,在插值之前为 NaN 的列bilirubin现在假定值为 0.95,这是 0.90(第 4 行)和 1.00(第 6 行)之间的插值。
df.head(10)

摘要
在本教程中,我们已经看到了数据预处理的一个方面,即处理缺失数据。缺失数据会改变数据分析过程,因此必须对其进行管理。
可以使用三种策略来处理缺失数据:
- 丢弃丢失的数据:当数据集有少量丢失的数据时,可以这样做
 - 用其他值替换缺失的数据,例如平均值或最频繁出现的值
 - 让丢失的数据保持原样。
 
如果您想了解数据预处理的其他方面,如数据标准化和数据规范化,请继续关注…
如果你想了解我的研究和其他活动的最新情况,你可以在 Twitter 、 Youtube 和 Github 上关注我。
使用 Scikit-Learn 进行数据预处理:标准化和缩放
如何预处理不同取值范围的数值特征

由 Charles Deluvio 在 Unsplash 上拍摄的照片
Scikit-learn 是一个广泛使用的 Python 机器学习库。由于算法的多样性及其易于理解的语法,它在数据科学从业者中获得了极大的欢迎。除了现成的算法,scikit-learn 还提供了有用的数据预处理功能和方法。
数据预处理是机器学习或深度学习中极其重要的一步。我们不能只是将原始数据转储到一个模型中,然后期望它表现良好。即使我们构建了一个复杂的、结构良好的模型,它的性能也会和我们提供给它的数据一样好。因此,我们需要处理原始数据来提高模型的性能。
在本帖中,我们将介绍处理数值范围差异很大的数字特征(列)的方法。我们将应用标准化和缩放。让我们从这些转变背后的动机开始,然后用例子探讨它们之间的区别。
动机
我们适合机器学习模型的数据集通常有许多特征。不同要素的值很可能处于不同的范围内。例如,考虑一个试图预测房价的模型。房子的面积在 200 平方米左右,而房龄通常不到 20 年。大多数情况下,卧室的数量可以是 1、2 或 3 间。所有这些特征在决定房子的价格时都很重要。然而,如果我们在没有任何缩放的情况下使用它们,机器学习模型可能会对具有较高值的特征给予更多的重视。当要素的比例相对相似时,模型往往表现更好,收敛更快。
标准化和标准定标器
这个问题的一个解决方案是标准化。将列视为变量。如果一个列是标准化的,则从每个值中减去该列的平均值,然后用该列的标准偏差除这些值。结果列的标准偏差为 1,平均值非常接近于零。因此,我们最终得到的变量(列)几乎呈正态分布。标准化可以通过StandardScaler.实现
预处理过程中使用的函数和转换器在sklearn.preprocessing包中。让我们将这个包与 numpy 和熊猫一起导入。
import numpy as np
import pandas as pdfrom sklearn import preprocessing
我们可以创建一个表示特征的样本矩阵。然后使用 StandardScaler 对象对其进行变换。
a = np.random.randint(10, size=(10,1))
b = np.random.randint(50, 100, size=(10,1))
c = np.random.randint(500, 700, size=(10,1))X = np.concatenate((a,b,c), axis=1)
X

x 表示具有 3 列 10 行的数据帧中的值。列表示特征。每列的平均值和标准偏差:

这些列在平均值和标准偏差方面有很大不同。
我们现在可以创建一个 StandardScaler 对象并使 X 适合它。
sc = preprocessing.StandardScaler().fit(X)
可以通过对 StandardScaler 对象应用 transform 方法来转换 x。
X_standardized = sc.transform(X)
X_standardized

让我们来计算变换后要素的平均值和标准差。

每个特征的平均值非常接近于 0,并且所有特征都具有单位(1)方差。请注意,标准差是方差的平方根。标准差为 1 表示方差为 1。
我想在这里强调非常重要的一点。考虑到我们正在进行监督学习任务,因此我们将数据集分成训练和测试子集。在这种情况下,我们只对标准的 scaler 对象进行fit训练集,而不是整个数据集。当然,我们需要转换测试集,但这是通过转换方法完成的。
- StandardScaler.fit(X_train)
 - standard scaler . transform(X _ train)
 - standard scaler . transform(X _ test)
 
将整个数据集拟合到标准缩放器对象会导致模型了解测试集。然而,模型不应该学习任何关于测试集的东西。它破坏了列车测试分离的目的。一般来说,这个问题被称为数据泄露。
如何检测和避免数据泄露
towardsdatascience.com](/data-leakage-in-machine-learning-6161c167e8ba)
当我们转换测试集时,由于转换中使用的定标器是基于训练集的,因此这些特征将不具有精确的零均值和单位标准差。测试集中的变化量与训练集中的变化量相同。让我们创建一个样本测试集并转换它。
X_test = np.array([[8, 90, 650], [5, 70, 590], [7, 80, 580]])
X_test

X_test_transformed = sc.transform(X_test)
X_test_transformed

测试集各列的平均值和标准偏差:

最小最大缩放器和鲁棒缩放器
将数值范围提高到相似水平的另一种方法是在特定范围内缩放它们。例如,我们可以将每一列压缩到 0 和 1 之间,使得缩放前的最小值和最大值在缩放后变成 0 和 1。这种缩放可以通过 scikit learn 的**MinMaxScaler** 来实现。默认范围是[0,1],但是我们可以使用 feature_range 参数来更改它。
from sklearn.preprocessing import MinMaxScalermm_scaler = MinMaxScaler()
X_scaled = mm_scaler.fit_transform(X)
X_scaled

mm_scaler2 = MinMaxScaler(feature_range=(0,10))
X_scaled2 = mm_scaler2.fit_transform(X)
X_scaled2

StandardScaler和MinMaxScaler对异常值不稳健。假设我们有一个值在 100 到 500 之间的特性,其异常值为 15000。如果我们用MinMaxScaler(feature_range=(0,1))缩放这个特性,15000 被缩放为 1,所有其他值变得非常接近下限,即 0。因此,我们最终得到了一个不成比例的比例,这对模型的性能产生了负面影响。一种解决方案是移除异常值,然后应用缩放。然而,删除异常值并不总是一个好的做法。在这种情况下,我们可以使用 scikit-learn 的**RobustScaler** 。
**RobustScaler**顾名思义,对离群值具有鲁棒性。它会移除中位数,并根据分位数范围(默认为 IQR:四分位数范围)缩放数据。IQR 是第一个四分位数(第 25 个四分位数)和第三个四分位数(第 75 个四分位数)之间的范围。RobustScaler 不以预定间隔限制缩放范围。因此,我们不需要像对 MinMaxScaler 那样指定一个范围。
我们可以通过在之前的数据集中添加一行异常值来查看MinMaxScaler和RobustScaler之间的差异。
X_new = np.append(X, np.array([[50,420,1400]]), axis=0)X_new

我们先用 range [0,1]来套用MinMaxScaler 。
X_new_mm = mm_scaler.fit_transform(X_new)X_new_mm

超出范围上限的异常值。因此,所有其他值都非常接近下限。
RobustScaler怎么样?
from sklearn.preprocessing import RobustScalerr_scaler = RobustScaler()
X_new_rs = r_scaler.fit_transform(X_new)X_new_rs

什么时候用哪个?
我们已经讨论了标准定标器、最小最大定标器和鲁棒定标器。许多机器学习模型受益于具有相似规模的特征。然而,没有一个严格的规则来定义哪种转换对于特定的算法是最优的。
MinMaxScaler 和 StandardScaler 对异常值都很敏感。因此,在我们无法移除异常值的情况下,RobustScaler 是比其他两个更好的选择。
在没有异常值的情况下,MinMaxScaler 在大多数情况下表现良好。然而,深度学习算法(例如,神经网络)和回归算法支持具有正态分布的特征。对于这种情况,StandardScaler 是更好的选择。
这些是最常用的转换技术,可以满足我们的一般需求。Scikit-learn 还提供了更多具体的转换,在预处理包的文档中有解释。
感谢您的阅读。如果您有任何反馈,请告诉我。
环境科学中的数据隐私和机器学习
苹果 | 谷歌 | SPOTIFY | 其他
马修·斯图尔特在 TDS 播客

编者按:迈向数据科学播客的“攀登数据科学阶梯”系列由 Jeremie Harris 主持。Jeremie 帮助运营一家名为sharpes minds的数据科学导师初创公司。可以听下面的播客:
2015 年的一个周四下午,我在手机上收到了一条自发通知,告诉我在当前的交通状况下,开车去我最喜欢的餐馆需要多长时间。这令人担忧,不仅因为这意味着我的手机在没有明确询问的情况下就已经知道了我最喜欢的餐馆,还因为这表明我的手机对我的饮食习惯了如指掌,知道我特别喜欢在周四出去吃饭。
随着我们的手机、笔记本电脑和亚马逊 Echos 收集越来越多的关于我们的数据,甚至更多,数据隐私正成为研究、政府和行业应用越来越大的担忧。这就是为什么我想与哈佛大学的博士生和数据科学撰稿人 Matthew Stewart 谈谈,以了解数据隐私背后的一些关键原则。Matthew 是一位多产的博客作者,他在哈佛的研究工作专注于机器学习在环境科学中的应用,这也是我们在这一集讨论的话题。
以下是我最大的收获:
- 进入机器学习的博士课程变得越来越难,但如果你对研究生院级别的机器学习或数据科学死心塌地,你可以选择一个你有专业知识的主题(如环境科学、地质学或物理学),并找到一种用数据科学工具解决它的方法。
 - 随着机器学习工具变得越来越用户友好,Matthew 的经历真正表明了主题专业知识变得多么重要。他更像是使用数据科学工具的环境科学家,而不是解决环境科学问题的数据科学家。这也是我们在行业中越来越多地看到的趋势,也是建立个人项目以解决你深刻理解的主题的一个很好的理由。
 - 像 k-anonymity(我们在播客中定义和讨论的)这样的简单数据隐私方法有严重的缺点,包括它们不允许我们客观地量化它们提供的隐私程度。出于这个原因,替代策略,特别是包括不同的隐私变得越来越重要。
 - 随着公司和政府开始更加关注数据隐私问题,我们消费的公开数据被私有化将变得更加普遍。因此,理解不同私有化技术在实践中的工作原理是负责任地使用这些数据的关键。
 
你可以在推特上关注马修,这里是 T1,你可以在推特上关注我,这里是 T2,这里是 T3。
疫情中的数据隐私
数据隐私
分析新冠肺炎接触追踪的不同方法

世界各地的国家开始逐渐重新开放,政府正在考虑所有的选择,希望控制未来的疫情。
他们的圣杯:联系追踪应用
专家已经对这些应用的安全性和有效性提出了担忧。但在此之前,我们先来讨论一下模拟。
对于我们很多人来说,这可能是第一次听说联系寻人,但这并不是什么新鲜事。公共卫生官员使用接触追踪已经有几个世纪了。最值得注意的是,遏制性病/性传播感染。
首先,他们隔离感染者以防止进一步传播,然后他们追踪与他们接触过的每一个人。他们做所有这些而不透露个人的身份。最后一部分对这一行动至关重要,追踪接触者不需要透露身份,隐私是至关重要的。
那么,政府和私人公司做了什么来把这个过程带到数字世界呢?好吧,让我们讨论一下正在使用的两种方法。

照片由i̇smail·埃内斯·艾汉在 Unsplash 上拍摄
集中方法
在集中式方法中,用户的手机将他们的 GPS 位置以及他们在那里的时间发送到中央服务器。英国国民医疗服务系统和法国都决定走这条路。
集中式方法的最大缺陷是:安全性和隐私,以及电池。
政府知道他们的公民在任何给定时刻的确切位置曾经是老大哥的噩梦,让乔治·奥威尔夜不能寐。一个疫情之后,全球数百万人自愿提供这些信息。作为一个美国人,不信任政府是文化的一部分,但在一些年轻人的反乌托邦小说中,提供近乎实时的位置是毫无疑问的。
英国和法国辩称该应用程序是安全的,数据不会被用于除了追踪联系人之外的任何目的。在一个理想的世界里,通过 GDPR 向欧盟公民提供的保护(甚至不确定这如何与英国退出欧盟合作)将给予他们必要的法律保障。但是,如果政府撒谎并非法使用数据,谁来让他们负责?同一个政府?
除了老大哥,专家们还提出了对恶意行为者获取数据的担忧。英国的联系追踪应用程序目前正在怀特岛进行测试。与此同时,他们还共享了 cybsecurity 专家的信息,以获得反馈。正如任何人可能已经猜到的那样,网络安全专家发现了一些安全漏洞。雪上加霜的是,他们的一个建议是转向分散的方法,这是他们上个月已经拒绝的。
要让任何联系追踪应用程序工作,无论是集中还是分散,手机都必须持续广播信息。加上手机一整天都要这样做,这会对电池造成损害。然而,集中式方法有一个额外的缺点,特别是对于 iOS 设备。苹果不允许应用程序在后台广播蓝牙信息。苹果已经向各公司明确表示,它不会放松这些限制。为了解决这个问题,iOS 上的一些应用需要保持开放才能工作。
新加坡试图在使用集中方法和解决公众关切之间达成平衡。新加坡开源了他们的应用,并声明除非他们转正,否则数据不会共享给中央服务器。
如果这是真的,新加坡可以成为其他仍然坚持使用中央集权方式的国家的榜样。剩下的最后一个问题是选择加入/选择退出的困境。
作为世界上最大的民主国家,印度已经要求公民下载该应用程序,如果他们想继续工作或避免可能的惩罚。即使是新加坡,尽管选择加入,也表示它可能不会永远是可选的。美国阿拉巴马大学系统“鼓励”教职员工和学生使用他们的应用程序,但不确定他们是否会要求在校园内使用。由于世界各地的数据保护法仍然相当有限,个人可能会发现自己被迫下载这些应用程序。如果不是他们的政府,他们的雇主或杂货店或任何其他他们希望合作的企业。
由于这些举动,印度的一名程序员绕过了应用。现在,他们可以带着一个不断显示“安全”的徽章自由行走,而无需广播任何数据。这是最好的情况。专家们都担心个人发出假阳性。这样做,到头来弊大于利。

分散处理方法
苹果和谷歌的合作引领了这种去中心化的方法。两家公司最近都发布了各自手机的更新,增加了这一选择加入 API。
API 的工作方式非常简单,用户的手机会创建经常变化的识别码。如果手机在相当长的时间内检测到附近有另一部手机,这两部手机将交换当前的识别码。如果用户被诊断患有新冠肺炎病毒,该应用程序将通过服务器广播他们之前 2 周的代码。每个人的手机都会定期检查这个服务器,如果发现与被感染代码匹配的,就会收到通知。
通过这种方法,电池仍然是一个问题,因为蓝牙需要一直打开,但在 iOS 设备上,它不会像集中式方法那样必须打开。
到目前为止, Switzerland 是第一批在他们的应用中测试这种 API 的公司之一,澳大利亚政府已经表示他们也将在他们现有的应用中实现这种 API,德国在之前致力于集中式方法之后也采用了这种 API。
所以,分散的方法是完美的,对不对?
嗯,不幸的是,没有。抛开隐私和安全问题,功效仍然是一个问题。
如果新冠肺炎的诊断是由用户输入的,那么肯定会有一些恶意软件发出假阳性,对公众对该应用的信任产生负面影响。
你没带手机的时候呢?或者你的手机没电了?或者穷人和老年人可能根本没有可以安装该应用程序的手机?
我赞扬苹果和谷歌致力于将安全和隐私置于设计中心的 API。我也要赞扬开发联系人追踪应用程序的软件工程师。然而,这是新技术;我们还不确定它到底有多有效。即使它完美地工作,你被通知你可能已经暴露于该病毒,可能是在你已经暴露了其他人之后。
接触追踪应用程序不能替代有效的治疗或疫苗,也不能替代广泛的检测和限制传播的个人防护设备。像其他人一样,我希望这些天的任何事情都会减缓疫情,但重要的是,我们不要从这些应用程序中获得虚假的安全感,最终使病毒传播得更远。
感谢您阅读我的帖子。我很想听听你们的想法,无论是在这里的评论中还是在 Twitter (@SoyCarlosEO) 上。
大数据时代的数据隐私
了解你的隐私是多么的少,以及差别隐私是如何帮助你的。
“争辩说你不在乎隐私权是因为你没什么好隐瞒的,这和说你不在乎言论自由是因为你无话可说没什么区别。”― 爱德华·斯诺登
2017 年 11 月,跑步应用 Strava 发布了一个数据可视化地图,显示了曾经上传到他们系统的每个活动。这相当于超过 3 万亿个 GPS 点,来自从智能手机到 Fitbits 和智能手表等健身追踪器的各种设备。该应用的一个方面是,你可以看到主要城市的热门路线,或者找到偏远地区锻炼模式不同寻常的个人。

2017 年 11 月发布的 Strava 全球热图。来源
与他人分享你的锻炼活动的想法可能看起来相当无害,但这张地图揭示了军事基地和现役人员的位置。其中一个地点是阿富汗赫尔曼德省的一个秘密军事基地。

阿富汗赫尔曼德省的一个军事基地,慢跑者走过的路线由 Strava 标出。照片:Strava 热图
这不是唯一暴露的基地,事实上,在叙利亚和吉布提等地的活动,用户几乎都是美国军事人员。因此,Strava 数据可视化在某种程度上是驻扎在世界各地的美国军事人员的高度详细的地图。
在这个数据不断增长的时代,保持任何形式的隐私都变得越来越困难。为了给我们的生活带来便利,我们现在不断向公司提供信息,帮助他们改善业务运营。
虽然这有许多积极的好处,例如 IPhone 知道我的位置,能够告诉我附近的餐馆或到达某个位置的最快路线,但它也可能被用于不利的方面,可能导致对个人隐私的严重侵犯。随着我们走向一个越来越数据驱动的社会,这个问题只会越来越严重。

图片由福布斯提供。
在这篇文章中,我将谈论公开发布的数据集的隐私泄露方面的一些最大失误,可以对这些数据集进行的不同类型的攻击以重新识别个人,以及介绍当前我们在数据驱动的社会中维护隐私的最佳防御措施:差分隐私。
什么是数据隐私?
1977 年, Tore Dalenius 阐述了统计数据库的迫切需要:
没有任何关于个人的东西是可以从数据库中学习到的,如果不访问数据库就无法学习到。——托雷纽斯
这一想法希望将众所周知的语义安全概念扩展到数据库,语义安全概念是指当一条消息使用加密算法被编码成密文时,密文不包含潜在消息的任何信息,通常被称为明文。
然而,由于种种原因,哈佛大学计算机科学教授辛西娅·德沃克在一篇论文中已经证明,达勒纽斯提出的这个想法在数学上是不可能的。
这背后的一个原因是,虽然在密码学中,我们经常谈论两个用户在安全通道上通信,同时被保护免受不良行为者的影响,但在数据库的情况下,必须将用户本身视为不良行为者。
所以,我们没有太多的选择。我们可以做的一件事是确定我们的数据集在识别一个人时特别重要的方面,并以这样一种方式处理这些方面,即数据集有效地变得“匿名化”。
数据集的匿名化/去标识化本质上意味着不可能(至少表面上)识别数据集中的任何给定个人。我们使用术语重新识别来指代从匿名数据集中识别的个人。
可识别性的金字塔
个人数据存在于可识别的范围内。想象一个金字塔,在金字塔的顶端,我们有可以直接识别个人的数据:姓名、电话号码或社会保险号。
这些形式的数据统称为' 直接标识符。
金字塔上的直接标识符下面是可以间接但明确地与个人联系在一起的数据。只需要少量数据就可以唯一地识别一个人,例如性别、出生日期和邮政编码,这些数据加起来可以唯一地识别 87%的美国人口。
这些数据统称为' 间接标识符 或' 准标识符。’
在准标识符下面是可以与多人模糊关联的数据——身体测量、餐馆偏好或个人最喜欢的电影。
我们的金字塔的第四个阶段是不能与任何特定的人联系起来的数据——汇总的人口普查数据,或广泛的调查结果。
最后,在金字塔的底部,有些数据与个人完全没有直接关系:天气预报和地理数据。

数据的可识别性水平。来源
这样,更难与个人联系起来的信息在可识别性的金字塔上被放在较低的位置。然而,随着数据越来越多地去除个人信息,其对研究和分析的有用性直接下降。因此,隐私和效用在这个范围的两端——楼梯顶端的数据最有用,楼梯底端的数据最隐私。随着数据变得越来越难处理,它对分析的有用性降低了。

效用和隐私之间的权衡。来源
作为一名数据科学家,这似乎是一个不能令人满意的答案。我们总是希望我们的数据尽可能准确,以便我们可以做出最准确的推断。然而,从另一个角度来看,我们对个人了解得越少,对他们的隐私就越有利。
那么我们如何平衡这种权衡呢?我们注定会失去准确性或隐私吗?我们在玩零和游戏吗?我们会发现答案实际上是肯定的。然而,现在有一些方法可以从数学上确定数据集的隐私级别,这样我们就可以获得最大量的信息,同时为数据中的个人提供合适的隐私级别。稍后将详细介绍。
用于匿名化数据的清理技术
有四种常用技术可用于取消数据集的标识:
[1]删除或修订
这种技术最常用于您不想发布的直接标识符,如电话号码、社会保险号或家庭住址。这通常可以自动完成,因为它直接对应于数据库中的主键。简单地说,删除意味着如果我们有一个 Excel 电子表格,我们将删除对应于直接标识符的列。
在下表中,可以删除第一列“姓名”,而不会影响数据对未来研究的有用性。

这种技术不是万无一失的。直接标识符往往没有明确标注,重要信息可能会被误认为个人信息而被意外删除。
【2】假名化
第二种方法只需要将“Name”类别更改为唯一的匿名值,例如列的哈希值或用户 ID。这些可以随机产生或通过算法确定。然而,这样做应该谨慎。如果你有一个学生名单,你用匿名 ID 发布他们的成绩,最好不要按字母顺序排列,因为这样很容易重新识别他们!
类似地,如果使用确定性算法来执行假名化,并且所使用的算法的性质被暴露,那么它会危及个人的匿名性。
例如,2014 年,纽约市出租车和豪华轿车委员会发布了一份当年纽约市所有出租车出行的数据集。在发布数据之前,出租车和豪华轿车委员会试图清除识别信息,特别是他们使用了出租车牌照号码和驾照号码的假名。然而,博客作者能够发现用于改变奖章号码的算法,然后逆转假名。
这种方法也有与第一种方法相同的缺点-直接标识符可能难以识别和替换,并且间接标识符会无意中留在数据集中。
如果在一个数据集内、多个数据集内或长时间内持续使用相同的唯一假名,假名也将失效。
【3】统计噪声
前两种方法几乎只适用于直接标识符,后两种方法几乎只适用于间接标识符。
我们可以设想第三种添加统计噪声的方法,将图像中某人的脸像素化。我们基本上允许数据仍然存在,但是它被随机噪声所掩盖。根据完成的方式,这可能是一种非常有效的技术。
将统计噪声引入数据集的一些方式包括:
- 概括:具体数值可报为一个范围。例如,患者的年龄可以报告为 70-80 岁,而不是给出完整的出生日期。
 - 扰动:可以为数据集中的所有患者随机调整特定值。例如,系统地增加或减少患者接受护理的相同天数,或者从正态分布中添加噪声。
 - 交换:数据可以在数据集中的单个记录之间交换。
 
正如您可能已经怀疑的那样,越多的直接或间接标识符被统计噪声删除和/或模糊,我们数据的准确性就越低。
【4】聚合
第四种方法类似于“统计噪声”部分讨论的一般化思想。不是发布原始数据,而是聚合数据集,只发布汇总统计数据或子集。
例如,数据集可能只提供接受治疗的患者总数,而不是每个患者的个人记录。然而,如果只释放一个小的子样本,重新识别的概率就会增加——比如一个子集只包含一个个体。
在聚合数据集中,个人的直接或间接标识符不会公布。但是,汇总数据必须基于足够广泛的数据范围,以便不会导致对特定个人的识别。例如,在上面的例子中,只有一名女性患者到医院就诊。如果数据中包括 30 名在医院呆过的女性,那么她将更容易被重新识别。
隐私泄露
我可以提出这么多隐私泄露的问题,这实际上非常令人担忧,所以我只挑选了其中的几个故事来说明某些重要的观点。
需要注意的是,我在这里谈论的不是数据泄露:一些坏人侵入公司或政府数据库,窃取客户的机密信息,尽管这也非常普遍,并且随着物联网(IoT)的出现,越来越令人担忧。
我们明确谈论的是公开可用的数据——即你可以(至少在当时)去下载它——或随后用于识别个人身份的商业数据。这也延伸到用于揭示个人信息的商业智能。
Netflix 奖

价值 100 万美元的 Netflix 大奖是由网飞发起的一项竞赛,旨在改进该公司的电影推荐系统。在比赛中,该公司发布了一个大型匿名数据库,参赛者可以将其用作推荐引擎的输入数据。
来自奥斯丁大学的研究生 Arvind Narayanan 和 Vitaly Shmatikov 教授能够重新识别网飞发表的数据集中的两个人。
“公布数据和删除姓名对隐私没有任何好处……如果你知道他们的名字和一些记录,那么你就可以在另一个(私人)数据库中找到那个人。” — 维塔利·什马提科夫
网飞没有在他们的数据集中包括名字,而是为每个用户使用一个匿名标识符。人们发现,当电影分级的收集与分级的公共数据库相结合时,就足以识别这些人。
纳拉亚南和什马蒂科夫通过使用互联网电影数据库(IMDb)中“几十个”人发布的公开评论来确定网飞数据中两个用户的电影评级,证明了这种危险。他们在网飞发布数据后不久发表了一篇论文。
曝光评论者认为是私人的电影分级可能会暴露该人的重要细节。例如,研究人员发现,其中一个人对一些自由主义和同性恋主题的电影有强烈的——表面上是私人的——观点,并且对一些宗教电影也有评级。
更一般地说,这项研究表明,一个人认为是良性的信息可以用来在其他私人数据库中识别他们。在隐私和情报界,这个结果已经被理解了几十年,但是这个案例让大众媒体看到了这个主题。
美国在线
2006 年 8 月,AOL Research 发布了一个文件,其中包含了超过 658,000 个用户在 3 个月内提出的 2000 万个搜索关键词。该数据集旨在用于研究目的,但在获得重大恶名后 3 天后被删除。然而,此时为时已晚,因为数据已经被镜像并分布在互联网上。这一泄密事件最终导致首席技术官 Abdur Chowdhury 博士辞职。
哪里出了问题?这些数据被认为是匿名的,但被发现泄露了搜索者私人生活的敏感细节,包括社会安全号码、信用卡号码、地址,在一个案例中,显然是搜索者的意图杀害他们的妻子。

从 AOL 数据集中提取的一些杂项查询。来源
虽然 AOL 没有明确指出用户的身份,但个人身份信息出现在许多查询中。你试过谷歌自己吗?这就是导致隐私泄露的根本原因。有些人甚至天真到在搜索数据库中输入他们的社会安全号码和地址。
由于 AOL 将查询归因于特定的用户数字标识的账户,因此可以通过这样的信息来识别个人并将其与他们的账户和搜索历史进行匹配。《纽约时报》 通过交叉引用电话簿清单,能够从公布的匿名搜索记录中找到一个人。
目标少女怀孕泄密
《纽约时报》作家查尔斯·杜希格在 2002 年发表的一篇文章中披露,塔吉特百货的一名统计学家安德鲁·波尔被要求开发一个产品预测模型,根据顾客在店内购买的商品来判断她是否怀孕。

WCPO 9 台关于塔吉特怀孕预测模型的新闻报道。来源
该系统将分析购买习惯,并利用这一点来辨别客户怀孕的可能性,然后将邮寄与怀孕相关的商品的优惠券和广告。这对许多人来说似乎是无害的,甚至是积极的事情。然而,一个开始收到优惠券的购物者是一个十几岁的女孩,她愤怒的父亲打电话到商店投诉广告。目标知道,但父亲不知道,十几岁的女孩怀孕了。
支持目标“怀孕”分类的数据与青少年的身份无关。相反,Target 的结论是基于这名青少年从一组 25 种与怀孕购物者相关的产品中购买的,如无味乳液和维生素补充剂。
虽然这些数据可能不会暴露购物者的身份,但塔吉特的大数据预测系统从她的购物模式中得出一个“令人毛骨悚然”且可能不受欢迎的推论。
这本质上是机器学习中分类任务的一个例子,你会惊讶地发现,使用看似无关的信息来预测年龄、性别、种族、政治派别等个人特征是多么容易。事实上,这基本上是剑桥分析公司在 2016 年美国总统选举期间使用脸书提供的数据所做的。
拉坦亚·斯威尼
1996 年,麻省理工学院的一名博士生拉坦娅·斯威尼(Latanya Sweeney)将 GIC 集团保险公司(Group Insurance Company)公开发布和匿名发布的医疗数据与公共选民记录(她花 20 美元购买)相结合,并能够从数据集中重新确定马萨诸塞州州长威廉·韦尔德的身份。

拉坦娅·斯威尼用来重新指认威廉·韦尔德州长的信息。
然后,她使用新获得的信息,向他的家庭地址发送了一封信,解释了她所做的事情,并指出数据匿名的方式显然是不够的。
她的再识别实验结果对以隐私为中心的政策制定产生了重大影响,包括健康隐私立法 HIPAA。
详细描述这些事件的完整文章可以在这里找到。
这段时间以来,她发表了关于数据隐私话题的最重要的领域之一,名为《简单的人口统计学常常唯一地识别人(数据隐私工作论文 3)匹兹堡 2000》。
这篇论文的结论是,美国 87%的个人可以通过知道三条信息而被唯一地识别:性别、出生日期和邮政编码。

Latanya Sweeney 论文中的图表显示了通过不同的准标识符可识别的人口百分比。
拉坦亚现在是一名教授,在哈佛大学管理着数据隐私实验室。本文稍后将概述一些匿名化数据集的技术,例如'k-匿名化 '。
金州黑仔
这个故事可能是最有趣的,也是影响最深远的。臭名昭著的金州黑仔是一名杀人犯和连环强奸犯,在 1978 年至 1986 年期间活跃在加利福尼亚州的萨克拉门托县,最终在 2018 年 4 月被捕,享年 72 岁,当时他的一名亲属将 23AndMe 个人基因组测试的遗传信息上传到公共在线数据库。
调查人员将罪犯的 DNA 上传到数据库,希望能找到部分匹配。令他们惊讶的是,他们做到了。调查人员开始研究家谱,以匹配从一个犯罪现场收集的 DNA。从那里,他们调查了那些树上的个体,以缩小嫌疑人的范围。
最终,他们在合适的年龄组中找到了一个人,他生活在金州黑仔活跃的地区。他们从詹姆斯·迪安杰罗扔掉的物品上收集了他的 DNA,然后在实验室进行分析,发现与凶手直接匹配。
虽然抓住一个连环杀手显然是一件积极的事情,但这种对遗传信息的使用引发了关于如何使用遗传信息的重大伦理问题:
其中最明显的是你的基因信息直接识别你——你不能使用数学技术来“匿名化”它,如果你这样做了,它将不再以任何方式代表你。
【2】第二个也是更令人难以忘怀的想法是,你的一个远房亲戚有能力侵犯你的隐私。如果你的表亲被发现有患卵巢癌的遗传倾向,并且这些信息在一个在线数据库中,保险公司可以直接将这些信息与你联系起来,以提高你的保费。这破坏了大多数数据收集过程中存在的知情同意的整个概念。
2008 年,美国出台了基因信息保密法案(GINA) ,禁止某些类型的基因歧视。该法案意味着健康保险提供者不能基于基因进行歧视。
例如,如果发现一个人有突变的 BRCA2 基因——这种基因通常与患乳腺癌的风险增加有关——他们将被禁止使用这些信息以任何方式歧视这个人。
然而,该法案对人寿保险政策、残疾保险政策或长期医疗保险政策中的歧视只字未提。如果你上传了一个个人基因组测试到一个在线的公共数据库,你最好相信你的人寿保险公司知道这件事。
重新识别攻击
在上一节中,我们看到即使匿名化的数据集也可能受到重新识别攻击。这可能会对数据集中的个人以及与分析或生成数据集相关的人员造成伤害。
在讨论的泄露事件中,有几起发生在出于研究目的或作为公司商业活动的一部分而发布的公共数据集中。
这对公司和学术界都提出了重大问题。仅有的两个真正的选择是:
(1) 不使用或严格限制公共数据,这在全球社会中是行不通的,会严重阻碍科学进步,或
(2) 制定可行的隐私保护方法,允许使用公共数据,而不会给作为公共数据一部分的个人参与者带来重大隐私风险。
然而,如果我们要开发隐私方法,我们需要知道个人能够对数据库进行什么类型的攻击。
联动攻击

链接攻击试图通过将数据与背景信息相结合来重新识别匿名数据集中的个人。“链接”使用两个集合中存在的准标识符,如邮政编码、性别、工资等,来建立识别连接。
许多组织没有意识到涉及准标识符的链接风险,尽管他们可能会屏蔽直接标识符,但他们通常不会想到屏蔽或推广准标识符。这正是拉坦亚·斯威尼找到威廉·韦尔德州长地址的方法,也是网飞在 Netflix 有奖竞赛中陷入麻烦的原因!
差异攻击
在这种攻击中,攻击者可以通过组合关于数据集的多个聚合统计信息来隔离单个值。这实质上攻击了数据清理方法一节中讨论的聚合方法。
一个简单的例子是查询一个关于患有癌症的用户的数据库。我们向数据库询问患有癌症的用户,然后向数据库询问患有癌症但名字不是 John 的用户。我们可以潜在地使用这些组合的查询结果来对 John 执行差异攻击。
这里是另一个例子,考虑一个虚构的忠诚卡数据产品,其中该数据产品包含所有客户在给定的一天花费的总金额和使用忠诚卡的客户子组花费的总金额。如果正好有一个顾客在购物时没有使用忠诚卡,那么对当天的两个统计数据进行一些简单的算术运算,就可以显示出这个顾客的精确消费总额,并且只发布总值。
这种攻击的一个更一般的版本被称为复合攻击。这种攻击涉及组合许多查询的结果来执行差异攻击。
例如,假设一个数据库使用统计噪声来干扰其结果。如果我们对数据库进行 10,000 次相同的查询,根据它产生统计噪声的方式,我们可能能够平均统计噪声数据,并获得接近真实值的结果。解决这个问题的一种方法可能是限制允许的查询数量,或者向相同的查询添加相同的噪声,但是这样做会给系统增加额外的问题。
同质攻击

对去标识数据库的同质性攻击示例。
同质性攻击利用了敏感数据属性的所有值都相同的情况。上表提供了一个例子,其中数据库的性别和邮政编码已被收回和概括,但我们仍然能够确定邮政编码为 537**的每个人的工资的一个相当好的想法。尽管事实上我们不能明确地识别个人,但我们仍然能够找出其中一个条目与他们有关。
背景知识攻击
背景知识攻击尤其难以防御。它们本质上依赖于个人的背景知识,这可能有助于在数据集中去识别某人。
例如,假设一个人知道他们的邻居去了一家特定的医院,还知道他们的某些属性,如邮政编码、年龄和性别,他们想知道他们可能患有什么疾病。他们发现数据库中有两个条目与这些信息相对应,其中一个条目患有癌症,另一个条目患有心脏病。他们已经在数据库中缩小了搜索结果的范围,但是他们能完全识别出这个人吗?
现在想象一下,邻居是日本人,这个人知道日本人比一般人患心脏病的可能性小得多。他们可以据此合理确定地断定该人患有癌症。
背景知识攻击通常使用贝叶斯统计来建模,贝叶斯统计涉及基于数据集中的属性的先验和后验信念,因为这本质上是个人在执行这种攻击时正在做的事情。一种称为贝叶斯最优隐私的条件有助于抵御这种攻击。
k-匿名性、L-多样性和 T-紧密性
在这一节中,我将介绍三种技术,它们可以用来降低某些攻击发生的概率。这些方法中最简单的是k-匿名,其次是l-多样性,再其次是t-紧密度。有人提出了其他方法来形成一种字母汤,但这是三种最常用的方法。对于每一种情况,必须对数据集执行的分析变得越来越复杂,并且不可否认地对数据集的统计有效性有影响。
k-匿名
正如拉坦娅·斯威尼在其开创性的论文中所说:
如果包含在发布中的每个人的信息不能与至少 k-1 个其信息也出现在发布中的个人相区分,则发布提供 k-匿名保护。
这实质上意味着,只要我的数据集包含至少 k 个给定准标识符集合的条目,那么它就是 k-匿名的。如果我们像前面一样使用邮政编码、性别和年龄的超级键,如果数据集中邮政编码、性别和年龄的每个可能组合中至少有 3 个条目,那么数据集将是 3-匿名的。

原始数据集(左)和 4-匿名数据集(右)。来源
这有助于防止链接攻击,因为攻击者不能高度确定地链接到另一个数据库。然而,仍然有可能有人执行同质攻击,如在所有 k 个个体具有相同值的示例中。例如,如果三个年龄组、性别和邮政编码相同的人碰巧都患有同一种癌症,k-匿名不能保护他们的隐私。同样,它也不能防御背景知识攻击。

k-匿名数据集上的同质性和背景知识攻击的例子。来源
k-匿名的可接受水平是多少?没有明确的定义,但一些论文认为 k=5 或 k=10 的水平是优选的。学术领域的大多数个人似乎都同意 k=2 是不够的,k=3 是保护隐私所需的最低限度(尽管不一定能保证隐私)。
您可能已经意识到,选择的 k 值越高,数据的效用就越低,因为我们必须执行泛化(减少列中唯一值的数量)、模糊化(模糊某些数据特征或组合它们)和抑制(在应用其他去标识方法后删除不能满足 k=3 的行元组)。可以添加合成行,从每列的边缘分布或所有列的联合分布中获取样本,而不是隐藏。
显然,所有这些机制都会严重扭曲或偏向数据集的统计数据,这些技术的权衡仍然是学术研究的主题。Olivia Angiuli 和 Jim Waldo 在出版物“ 中讨论了 HarvardX 数据在大规模数据集 的去识别中概括和抑制之间的统计权衡。
当准标识符的数量变大时,使数据集 k 匿名可能导致大部分数据丢失(80%的数据可以仅通过抑制来移除)或被添加(例如为数据集中当前的每一行添加 3 行以使其 4 匿名),这在大多数大型公共数据集中都会发生。
在我自己尝试制作 k-anonymous 数据集之前,我可以告诉你,实现匿名并仍然拥有并非无用的数据绝非易事。
l-多样性
一些人已经注意到可以在 k-匿名数据集上执行的攻击的可能性,因此隐私研究人员更进一步,提出了 l-多样性。作者将 l-多样性定义为:
…要求敏感属性的值在每个组中得到很好的代表。
他们在数学细节上对此进行了扩展,本质上是指任何被认为是“敏感”的属性,如个人的医疗状况,或学生是否通过了某门课,在每个子集 k 内至少有 L 个不同的值。
更简单地说,这意味着如果我们从一个大学班级中取出四个人的数据块,发现这些数据块具有相同的准标识符(例如相同的邮政编码、性别和年龄),那么在该组中必须至少有 L 个不同的值——我们不能让该组中的所有人都只有及格分数。
这有助于确保个体不会在同质攻击中被唯一地识别。然而,如果敏感属性的所有值都是不利的,例如在“等级”列中所有值都有不同但较低的等级,或者在“医疗状况”列中所有值都有不同类型的癌症,这仍然可能侵犯某人的隐私。
这并不能使事情变得完美,但它比 k-匿名更进了一步。然而,在对数据集执行这一操作后,它再次提出了关于数据集的统计有效性的其他问题,因为它将涉及抑制或添加行,这将改变数据的分布,并且也作为自采样偏差的一种形式。
例如,在 EdX 数据中,发现完成课程的学生比不经意的课堂观察者提供了更多关于他们自己的信息,因此这些学生中的大多数可以被唯一地识别。因此,当在数据集上使用 k-匿名和 l-多样性时,它删除了大多数已经完成课程的人!很明显,这不是一个理想的情况,并且仍然存在关于如何处理这种情况以最小化以这种方式向数据集引入偏差的公开问题。
t-贴近度
作为 k-匿名和 l-多样性的另一种扩展,隐私研究人员还提出了 t-紧密度。他们将 t-封闭性描述为:
我们提出了一种新的隐私概念,称为 t-封闭性,它要求敏感属性在任何等价类中的分布都接近属性在整个表中的分布(即两个分布之间的距离应该不超过阈值 t)。我们选择使用推土机距离测量来满足我们的 t 接近度要求。
在上面的段落中,等价类意味着 k 个匿名子集中的 k 个个体。其思想实质上是确保不仅等价类中的值是 L-多样的,而且这 L 个不同值的分布应该尽可能接近总体数据分布。这将有助于消除引入 EdX 数据集中的一些偏见,这些偏见与删除成功完成课程的人有关。
以下是针对这些算法和其他旨在保护数据隐私的算法的参考科学论文:
存在哪些规定?
存在许多隐私法规,它们可能有很大的不同,要写下并解释它们可能有点困难,所以我选择了 HIPAA 和美国 FERPA 法规作为比较的例子。
该法规涵盖了美国的所有医疗数据,最初(1996 年发布时)规定在发布数据之前,必须从数据集中删除所有个人身份信息(PII)。根据我们前面的讨论,这对应于直接标识符,即直接识别您是谁的信息,如姓名、地址和电话号码。因此,HIPAA 只需从公开发布的数据中抑制(删除/移除)这些特性就可以满足。
此后,法规得到了更新,现在要求根据 HIPAA 隐私规则取消数据集的身份,该规则规定:
- 删除上面列出的 18 个特定标识符(安全港方法)
 - 经验丰富的统计专家验证和记录重新识别的统计风险的专业知识非常少(统计方法)
 
受保护健康信息范围内的 18 个属性是:
- 名称
 - 小于一个州的所有地理标识符,邮政编码的前三位数字除外,如果根据美国人口普查局当前公开可用的数据:由所有邮政编码和相同的前三位数字组合而成的地理单元包含超过 20,000 人。
 - 与个人直接相关的日期(年份除外)
 - 电话号码
 - 传真号码
 - 电子邮件地址
 - 社会安全号码
 - 医疗记录号码
 - 健康保险受益人数
 - 账号
 - 证书/许可证号码
 - 车辆标识符和序列号,包括车牌号码;
 - 设备标识符和序列号;
 - Web 统一资源定位符(网址)
 - 互联网协议(IP)地址号码
 - 生物标识符,包括指纹、视网膜和声纹
 - 全脸摄影图像和任何类似的图像
 - 任何其他独特的识别号、特征或代码,除了研究者指定的编码数据的独特代码
 
请注意,HIPAA 数据并不一定是 k 匿名的。
该法规涵盖了美国的所有教育数据,包括 K-12 和大学信息。该条例规定,不仅必须清除所有 PII,而且还必须确保任何人都不可能被高度肯定地认出。这意味着我们必须满足比 HIPAA 更严格的要求。如果我们查看大学医疗信息,必须遵循更严格的法规,因此在这种情况下,FERPA 将占主导地位,而不是 HIPAA。
使用 k-匿名可以满足 FERPA 的要求。
差异隐私
本文的主旨是让您了解不同的隐私,以及它计划如何在一个数据驱动的世界中彻底改变隐私的概念。谷歌、苹果、优步,甚至美国人口普查局都采用了不同形式的差别隐私。
我们已经看到,k-匿名、l-多样性和 t-紧密度方法绝不是完美的,它们也不能保证它们是面向未来的。我们希望能够对数据集进行统计分析,例如关于人口的推断、机器学习训练、有用的描述性统计,同时仍然保护个人级别的数据免受所有攻击策略和关于个人的辅助信息的影响。使用以前的方法,有人可以在 10 年内利用新技术或算法重新识别整个数据集——没有正式的隐私保证。
这就是差别隐私为我们提供的:隐私的数学保证,它是可测量的,是未来可预见的。差别隐私的目标是给每个人大致相同的隐私,因为他们的数据被删除。也就是说,在数据库上运行的统计函数不应该过度依赖于任何一个人的数据。
密码学不适用于数据集,因为潜在的对手是数据集用户本身。因此,隐私研究人员在假设数据分析师是对手的情况下开发了一个数学框架,旨在将敏感信息泄露给分析师的可能性降至最低,即使分析师对数据集提出了多个顺序查询。
当隐私研究人员不再试图确保隐私是数据输出的属性,而是开始认为它是数据分析本身的属性时,这一启示就出现了。这导致了差别隐私的形成,它提供了一种“设计隐私”的形式,而不是作为一种事后的想法在末尾标记隐私。

负责协调数据分析师(对手)与原始数据源(我们的数据库系统)之间的接口的管理员。
因此,我们的要求是,对手不应该知道任何个人的数据是否被任意更改。简单来说,如果我删除数据集中的第二个条目,对手将无法分辨两个数据集之间的区别。
我们使用称为ϵ.的变量来测量(1)具有个体 x 的数据集和(2)不具有个体 x 的数据集之间的差异
这是如何工作的?

让我们想象一下,我们的数据分析师问馆长,数据集中艾滋病毒阳性且血型为 b 型的人占多大比例。差分私有系统会回答这个问题,并向数据中添加已知水平的随机噪声。算法是透明的,所以数据分析师被允许确切地知道这个随机噪声是从什么分布中采样的,这对于算法隐私没有任何影响。
需要添加的噪声量是 1/n,以确保如果从数据集中删除一个人,数据分析师将无法分辨,其中 n 是数据集中的人数。这应该是有意义的,因为噪声水平为 2/n 意味着分析师无法判断个人数据是否被更改、添加或删除,或者它是添加到数据集的噪声的函数。
随着数据集中个体数量的增加,为保护单个个体的隐私而必须添加的噪声量会逐渐变小。

添加的噪声通常是拉普拉斯分布的形式,隐私的级别可以用我们称之为ϵ.的“隐私参数”来控制我们可以认为这个值是两个数据集之间的差异,这两个数据集只有一个不同:一个单独的 X 出现在其中一个数据集中,而不在另一个数据集中。

隐私参数的直观定义。
当ϵ的值非常小时,我们有更大的隐私-我们有效地向数据集添加了更大量的噪声,以掩盖特定个人的存在。当ϵ的值很大时,我们的隐私就更弱了。通常,ϵ的值小于 1,通常更接近于零,大约在 0.01-0.1 之间。
这里创造的是一种算法,它确保无论对手了解到我什么,它都可以从其他人的数据中了解到。因此,诸如吸烟和肺癌之间是否存在联系的推断仍然会在数据中清晰地出现,但关于特定个人是否吸烟或患有癌症的信息将被掩盖。
对于允许多个查询的数据集,这是如何工作的?
这是一个很重要的问题:如果我向数据集提出足够多的问题,它最终会向我坦白所有人的信息吗?这就是隐私预算概念的由来。
“机制”(我们与数据库和数据分析师交互的数据管理员)受到限制,不会泄露特定于个人的信息。每次你问一个问题,它就会回答你的问题,这就消耗了你的一些隐私预算。你可以继续询问关于同一组数据的问题,直到你达到最大隐私预算,此时该机制将拒绝回答你的问题。
请注意,这不会阻止您再次询问有关数据的问题,这意味着该机制将强制您访问的数据必须添加新的噪声量,以防止隐私泄露。
隐私预算的概念起作用的原因是隐私参数的概念构成得很好——来自后续查询的隐私值可以简单地加在一起。
因此,对于 k 个查询,我们有 kε的差分隐私。只要 kε <有隐私预算,该机制仍然会响应查询。
希望,到这一点,你开始意识到这样一个数学上保证的隐私算法的含义,并且现在理解为什么它优于 k-匿名、l-多样性和 t-封闭性的概念。这已经由公司以不同的形式实施,我们将快速查看配方之间的差异。
全局差分隐私
这是我在上面的例子中提到的最直观的差分隐私形式,其中数据库由公司或政府管理员在一个集中(单一)的位置管理。
例如,美国人口普查局正计划在 2020 年美国人口普查中使用全球差异隐私。这意味着该局将得到所有的数据,并把它放入一个数据库中。在此之后,研究人员和感兴趣的团体将能够查询人口普查数据库并检索关于人口普查数据的信息,只要他们不超出他们的隐私预算。
一些人担心全球差异隐私,因为数据以原始形式存在于其来源。如果一家私人公司这么做了(优步是目前我所知道的唯一一家使用全球差分隐私的公司),那么如果这些数据被传唤,该公司将不得不交出个人的敏感信息。幸运的是,对于美国人口普查局来说,他们在加入该局时发誓绝不通过人口普查数据侵犯个人隐私,所以他们对此非常重视。此外,该局不允许被任何政府机构传唤,即使是像联邦调查局或中央情报局这样的机构,所以你的数据在相当安全的手中。
本地差分隐私
这种形式的差别隐私被谷歌用于他们的 RAPPOR 系统用于谷歌 Chrome,以及使用 IOS 10 及以上版本的苹果 IPhones。这个想法是,信息从个人的设备发出,但噪音是在源头添加的,然后以掺假的形式发送到苹果或谷歌的数据库。因此,谷歌和苹果无法访问原始和敏感的数据,即使他们被传唤,这些数据是由他人获得的,也不会侵犯你的隐私。

局部和全局差分隐私的区别。来源
最终意见
恭喜你到文章结尾了!这是对数据隐私的一次相当深入的探讨,我敦促你跟上隐私世界正在发生的事情——了解你的数据在哪里以及如何被公司和政府使用和保护,可能会成为未来数据驱动社会的一个重要话题。
"独处是现代世界中最珍贵的东西。"
― 安东尼·伯吉斯
时事通讯
关于新博客文章和额外内容的更新,请注册我的时事通讯。
丰富您的学术之旅,加入一个由科学家,研究人员和行业专业人士组成的社区,以获得…
mailchi.mp](https://mailchi.mp/6304809e49e7/matthew-stewart)
数据隐私、安全和新冠肺炎

安全性和数据隐私之间的权衡
数据被广泛用于对抗新冠肺炎。大部分数据是个人数据:
- 各州正在聚集力量加强对我们行动和健康状况的监控。以台湾为例,它全面强制跟踪手机,以监控被隔离的个人。西班牙现在推出了一个公共卫生监测应用程序,要求个人报告他们的每日体温,以帮助更准确地绘制传播图,并为早期病例提供支持
 - 私营企业正在通过应用程序收集数据,包括体温、既往病史、姓名、电话号码等,以支持对抗这种疾病的快速研究进展
 - 个人自愿向私营和公共部门提供个人数据,以帮助绘制地图、追踪、跟踪和摧毁新冠肺炎。通过每天报告我们的体温,我们允许卫生服务部门快速识别冠状病毒阳性病例,并尽早解决它们。这种大规模数据报告还允许更准确地绘制扩散图和根病例定位图。但我们也在与雇主分享比平时更多的个人数据,以确保我们继续工作的能力,并与其他为新冠肺炎研究做出贡献的私营公司分享
 
作为个人,我们正在我们的安全和数据隐私之间进行权衡。
可以理解。今天不分享你的个人数据可能会导致人类死亡,包括你和你所爱的人,当我们的生存依赖于分享个人信息时,降低我们对隐私的担忧似乎是合理的。
但这是一个特殊的情况和一个明确的目的,不是一概的许可,也不是承认我们愿意放弃我们的隐私权。
新冠肺炎期间的数据隐私
人们有理由担心,在这场危机之后,数据隐私可能无法恢复。
历史上的许多例子表明,虽然国家在攫取权力方面速度很快,但一旦被攫取,它通常很不愿意放手。
为了避免这种情况,这种全社会范围的个人数据共享行为需要在同意的障碍下理解。
必须遵循《一般数据保护条例》( GDPR)中规定的同意原则。我们自愿提供数据的唯一目的是为了对抗新冠肺炎。
GDPR 案文第五条第一款概述的原则必须遵守。这些要求个人数据应:
“(a)以合法、公平和透明的方式对个人进行处理(“合法、公平和透明”);”
(b)为特定、明确和合法的目的收集,并且不以不符合这些目的的方式进一步处理;出于公共利益、科学或历史研究目的或统计目的的存档目的的进一步处理不应被视为与初始目的不相容(“目的限制”);”
(c)充分、相关且仅限于处理目的所必需的内容(“数据最小化”);”
(d)准确,并在必要时保持更新;必须采取一切合理措施,确保不准确的个人数据(考虑到处理这些数据的目的)立即被删除或更正(“准确性”)。”
(e)以允许识别数据主体的形式保存,保存时间不超过处理个人数据所需的时间;个人数据可以存储更长时间,前提是个人数据的处理仅用于出于公共利益、科学或历史研究目的或统计目的的存档目的,但需执行 GDPR 要求的适当技术和组织措施,以保护个人的权利和自由(“存储限制”);”
(f)使用适当的技术或组织措施(“完整性和保密性”),以确保个人数据适当安全的方式进行处理,包括防止未经授权或非法的处理以及防止意外丢失、破坏或损坏。”
在这种特殊情况下,我们提供数据的唯一目的是为了抗击这种病毒(“目的限制”);我们期望我们的数据不会被非法使用,并要求了解这些数据的用途(“合法、公平和透明”);实施的监测措施应仅整理和分析相关的和需要用于此目的的数据,例如无人驾驶飞机、电话 GPS 跟踪等……(“数据最小化”);我们希望我们的数据在任何时候都不会受到未经授权的访问(“完整性和保密性”)
新冠肺炎会议后的数据隐私工作
在克服这一危机之后,数据隐私方面的工作必须允许个人了解谁拥有他们的数据,在哪里,出于什么目的,并行使他们的数据主体权利。
所需的一些工作包括:
a) 由于冠状病毒危机期间的数据共享,盘点哪些数据保存在哪里。类似于 GDPR 生效时企业所做的工作。目前整理个人数据的公共和私营机构需要清点冠状病毒爆发期间从数据主体持有的数据(结构化和非结构化数据),以审核其是否符合存储限制、准确性和完整性以及保密性的原则。
获取个人的同意。公共和私人代理都需要确保对持有的任何个人数据以及在不确定的情况下应该再次收集的个人数据进行同意。目前,政府和私人公司都被默许访问和使用个人数据来对抗新冠肺炎病毒。在这种情况下,议会授予的特殊权力和个人自愿提供数据就足够了。然而,在此之后,将需要获得用户的明确同意,以继续持有和/或使用经过整理的数据,特别是在目的发生变化时。
c) 允许个人行使其数据权利。为了抗击冠状病毒,个人应该有机会对危机期间收集的任何数据行使删除、遗忘、纠正等权利。
随着人工智能技术的普及和数据在未来几年成为重要的价值来源,保护数据隐私和个人决定使用自己数据的权利应该成为每个人的首要任务。
不管情况如何,我们应该总是要求机制来收回我们的数据并重新访问我们的同意。新冠肺炎就是这样一个例子,在那里,我们放松数据隐私要求的意愿是准时的,并且是为了特定的目的。
使用 Python 的数据处理示例
只是为分析和机器学习准备数据集所涉及的一些步骤。

来源:图片由作者创建
《福布斯》的调查发现,数据科学家工作中最不愉快的部分占据了他们 80%的时间。20%用于收集数据,另外 60%用于清理和组织数据集。就我个人而言,我不同意 80%是我们工作中最不愉快的部分。我经常将数据清理任务视为一个开放式问题。通常,每个数据集可以根据手头的问题以数百种不同的方式进行处理,但我们很少能够将同一组分析和转换从一个数据集应用到另一个数据集。我发现构建不同的处理管道并研究它们的差异如何影响模型性能是我工作中令人愉快的一部分。
也就是说,我想花点时间向您介绍准备数据集进行分析的代码和思考过程,在这种情况下,这将是一个回归(即。多元回归)。
资料组
关注我的人都知道,我对人力资源数据集特别感兴趣,因为我大部分职业生涯都在这个行业工作。
如果你有一个罕见的人力资源数据集,请与我们分享:)
我们将使用 310 名在职和离职员工的数据集,以及婚姻状况、性别、部门、工资率、州、职位等信息。由于我们正在为回归分析准备数据,我们的目标功能是 EngagementSurvey。
我们数据集的代码本可以在这里找到。
分析
import numpy as np
import pandas as pd
import datetime
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.pipeline import make_pipeline
from feature_engine import missing_data_imputers as mdi
from feature_engine import categorical_encoders as ce
from sklearn.model_selection import train_test_split%matplotlib inlinewith open('HRDataset.csv') as f:
    df = pd.read_csv(f)
f.close()df.head()df.info()


加载数据后,我们可以看到许多独特的要素类型。我们有分类特征,例如“雇员姓名”和“职位”。我们有二进制特征,比如“MarriedID”。我们有持续的功能,如“支付率”和“员工满意度”。我们有离散的功能,如“DaysLateLast30”,最后我们有日期功能,如“LastPerformanceReview_Date”。
高或低特征可变性
我通常采取的第一步是检查每个要素值的唯一计数,以确定是否有任何要素会由于非常高或非常低的可变性而被快速删除。换句话说,我们是否有任何具有与数据集长度一样多的唯一值的要素,或者只有一个唯一值的要素?
for col in df.columns:
    print(col, df[col].nunique(), len(df))

df.drop(['Employee_Name'], axis=1, inplace=True)
df.drop(['EmpID'], axis=1, inplace=True)
df.drop(['DOB'], axis=1, inplace=True)
df.drop(['DaysLateLast30'], axis=1, inplace=True)
我们可以安全地删除“雇员姓名”、“雇员 ID”、“出生日期”,因为大多数(如果不是全部的话)值对于每个特性都是唯一的。此外,我们可以删除“DaysLateLast30 ”,因为该特性只包含一个唯一值。
重复特征
接下来,通过检查包含每个特性的定义的码本,我们可以看到我们有许多重复的特性。例如,“MarriedStatusID”是一个数字特征,它生成与“MaritalDesc”特征中的已婚雕像相匹配的代码。我们可以放弃这些功能。
df.drop(['MaritalStatusID', 'EmpStatusID', 'DeptID'], axis=1, inplace=True)
df.drop(['GenderID'], axis=1, inplace=True)
df.drop(['PerformanceScore'], axis=1, inplace=True)
df.drop(['MarriedID'], axis=1, inplace=True)
你可能会问自己“那么‘Position id’,‘Position’,‘manager id’和‘manager name’呢?".从上面的输出可以看出,这些特征对的唯一值计数不匹配。“位置 ID”有 32 个唯一值,而“位置”有 30 个。
df[['PositionID', 'Position']].sort_values('PositionID')[50:70]
df[['ManagerName', 'ManagerID']].sort_values(by='ManagerID').tail(50)df.drop('PositionID', axis=1, inplace=True)
df.drop('ManagerID', axis=1, inplace=True)


我们将删除“PositionID ”,因为它不维护所有可用的位置;我们将删除“ManagerID ”,因为“ManagerName”不包含任何缺失值。
奇数值和数据收集错误
接下来,让我们检查每个特性的单个唯一值。这将有助于我们看到任何赔率值和需要修复的错误。
for col in df.columns:
    print(col, df[col].unique(), len(df))

从码本中,我们知道诸如“FromDiversityJobFairID”和“Termd”的特征是“是”和“否”的二进制编码。为了简化我们的分析和帮助格式化,我们需要将二进制转换成字符串。我们还看到需要删除“数据分析师”和“生产”部门的尾随空格。最后,我们看到一个需要纠正的“西班牙裔拉丁人”的编码错误。
diversity_map = {1: 'yes', 0: 'no'}
termd_map = {1: 'yes', 0: 'no'}
hispanic_latino_map = {'No': 'no', 'Yes': 'yes', 'no': 'no', 'yes': 'yes'}df['FromDiversityJobFairID'].replace(diversity_map, inplace=True)
df['Termd'].replace(termd_map, inplace=True)
df['HispanicLatino'].replace(hispanic_latino_map, inplace=True)df['Position'] = df['Position'].str.strip()
df['Department'] = df['Department'].str.strip()
你可能会问自己“为什么有些邮政编码是 5 位数,而有些只有 4 位数?”。在美国,所有的邮政编码都是 5 位数。经过一点谷歌搜索,许多马萨诸塞州的邮政编码实际上是从零开始的,默认情况下,python 去掉了零,产生了 4 位数的邮政编码。因为我们将把邮政编码视为分类特征,所以长度并不重要。
处理日期时间功能
信不信由你,但是日期时间特性通常包含大量的信息等待被释放。当一个人熟悉数据来源的行业时,这一点尤其明显。
df['DateofHire'] = pd.to_datetime(df['DateofHire'])
df['DateofTermination'] = pd.to_datetime(df['DateofTermination'])
df['LastPerformanceReview_Date'] = pd.to_datetime(df['LastPerformanceReview_Date'])df['DateofHire_month'] = df['DateofHire'].dt.month
df['DateofHire_day'] = df['DateofHire'].dt.day 
df['DateofHire_year'] = df['DateofHire'].dt.year
df['DateofHire_quarter'] = df['DateofHire'].dt.quarter
df['DateofHire_day_week'] = df['DateofHire'].dt.day_name()
df['DateofHire_weekday'] = np.where(df['DateofHire_day_week'].isin(['Sunday','Saturday']),'yes','no')df['DateofTerm_month'] = df['DateofTermination'].dt.month
df['DateofTerm_day'] = df['DateofTermination'].dt.day
df['DateofTerm_year'] = df['DateofTermination'].dt.year
df['DateofTerm_quarter'] = df['DateofTermination'].dt.quarter
df['DateofTerm_day_week'] = df['DateofTermination'].dt.day_name()
df['DateofTerm_weekday'] = np.where(df['DateofTerm_day_week'].isin(['Sunday','Saturday']),'yes','no')df['LastPerform_month'] = df['LastPerformanceReview_Date'].dt.month
df['LastPerform_day'] = df['LastPerformanceReview_Date'].dt.day 
df['LastPerform_year'] = df['LastPerformanceReview_Date'].dt.year 
df['LastPerform_quarter'] = df['LastPerformanceReview_Date'].dt.quarter
df['LastPerform_day_week'] = df['LastPerformanceReview_Date'].dt.day_name()
df['LastPerform_weekday'] = np.where(df['LastPerform_day_week'].isin(['Sunday','Saturday']),'yes','no')df['tenure_termed'] = df['DateofTermination'] - df['DateofHire']
df['tenure'] = datetime.datetime.today() - df['DateofHire']
df['days_since_review'] = datetime.datetime.today() - df['LastPerformanceReview_Date']df.drop(['DateofHire', 'DateofTermination', 'LastPerformanceReview_Date'], axis=1, inplace=True)df.head()

首先,我们需要将我们的特性转换成日期时间格式。接下来,使用“datetime”库,我们可以从原始的 datetime 特性中提取新的特性,包括月、日、年、季度、工作日字符串,甚至当天是否是周末。最后,我们可以将各个日期相减,计算出任期(终止日期—聘用日期)和任期(今天的日期—聘用日期)。一旦我们提取了必要的信息,我们可以放弃原来的功能。
df['days_since_review'] = df['days_since_review'].astype(str)
df['days_since_review'] = [i[0:3] for i in df['days_since_review']]df['days_since_review'] = df['days_since_review'].astype(str)
df['days_since_review'] = [i[0:3] for i in df['days_since_review']]df['tenure_termed'] = df['tenure_termed'].astype(str)
df['tenure_termed'] = [i[0:2] for i in df['tenure_termed']]for var in df.columns:
    df[var].replace(to_replace=['NaT','Na'], value=np.nan, inplace=True)df.head()

也许我有点强迫症,但我喜欢整洁的数据集,因此,让我们从这些新功能中删除不相关的信息,如“天”和时间戳。最后,我们将 NaT 和 Na 转换为真正的 numpy NaN。
检查基数
for var in df.columns:
    print(var, '\n', df[var].value_counts()/len(df))df.drop(['CitizenDesc', 'DateofHire_weekday', 'DateofTerm_weekday', 
         'LastPerform_quarter', 'LastPerform_weekday', 'LastPerform_year'], axis=1, inplace=True)

低方差
基数是指每个特性的唯一值/类别的数量。数字特征,尤其是连续特征,将具有非常高的基数,但是我们主要需要关注分类特征。首先,我们需要识别包含吸收所有方差的值/类别的特征。换句话说,90%以上的观察值属于一个或两个值。例如,“CitizenDesc”有三个唯一的值,但我们看到“美国公民”包含所有观察值的 95%。不幸的是,展示这种模式的其他功能是我们新设计的功能,如“DateofHire_weekday”、“DateofTerm_weekday”、“LastPerform_quarter”、“LastPerform_weekday”和“LastPerform_year”。我们可以放心地放弃这些特性,因为它们没有提供足够的可变性,没有意义。
稀有值/类别

使用与上面相同的代码,我们再次将注意力转向分类特征,但这一次我们要寻找我们认为“罕见”的值。你如何定义“稀有”真的取决于你,但我发现这个决定必须根据不同的特性来做。如果某些值出现的时间少于 1%,那么它们可能很少见。在其他特性中,阈值可能是 2%甚至 5%。我们的最终目标是将这些价值组合成一个新的价值/类别,称为“稀有”。此过程减少了特征的整体基数,如果您选择一次性编码您的类别特征,此方法将大大减少新创建的“虚拟”特征的数量。
- 声明:低于 1% 的任何东西都将被视为‘稀有’
 - 位置:任何低于 2% 的情况都将被视为“罕见”
 - Zip :任何低于 2% 的都将被视为“罕见”
 - RaceDesc :任何低于 2% 的都将被视为“罕见”
 - 招聘来源:低于 2% 的任何东西都将被视为“稀有”
 - 三天的日期:任何低于 2% 的日期都将被视为“罕见”
 - DateofTerm_month :小于 2% 的任何数据都将被视为“罕见”
 - DateofTerm_day :小于 2% 的任何数据都将被视为“罕见”
 - LastPerform_day :任何低于 2% 的情况都将被视为“罕见”
 - LastPerform_day_week :小于 2% 的任何内容都将被视为“罕见”
 - 一年中的日期:任何小于 2% 的日期都将被视为“罕见”
 - DateofTerm_year :小于 2% 的任何数据都将被视为“罕见”
 - 经理姓名:任何低于 5% 的都将被视为‘罕见’
 
缺少值
决定如何处理缺失值是数据科学家将做出的最重要和最有争议的决定之一。
for var in df.columns:
    if df[var].isnull().sum()/len(df) > 0:
        print(var, df[var].isnull().mean().round(3))df.drop('tenure_termed', axis=1, inplace=True)

TermReason 是一个分类特征,只有一些缺失的数据点。我们可以使用模式估算该数据,因为这不会改变特征的分布。此外,我们可以有把握地假设,缺少 TermReason 仅仅意味着该雇员仍然有效。剩下的带有缺失数据的特征就是我们所说的“非随机缺失”(MNAR)。换句话说,这些特征的缺失是有潜在原因的。首先,缺失值的百分比似乎在重复,这给了我们一个线索,即这些缺失值有一个可辨别的模式。其次,我们从数据中了解到,大约 67%的员工是在职的,不会有离职日期。最后,在最近的绩效考核周期后雇用的员工通常不会有与其上次绩效考核日期相关联的日期。如果您希望了解更多关于缺失值的信息,请参考此资源。
有些人会认为 67%的缺失值实际上使特性变得无用,我同意我们的“任期”特性的这种观点。输入这个数字特征可能会在我们的数据中引入太多的误差方差/偏差。然而,诸如“DateofTerm_month”和“LastPerform_month”之类的特征在本质上是分类的,它们的缺失数据具有明确的模式。我想通过用字符串“missing”输入所有缺失值来捕捉缺失值的重要性。通过这种方式,我们为每个特性引入了另一个值/类别,它恰当地捕捉到了缺失值背后的模式。
另一方面,“天数 _ 自 _ 回顾”是一个数字特征,它是 MNAR。换句话说,为了捕捉这些缺失值的重要性,我们将估算一个任意的数字(即-9999)并创建一个新特征,该新特征将指示该特征的观测值是否缺失。
- 术语原因:用模式估算
 - DateofTerm_month:使用' missing '进行估算以创建新类别
 - DateofTerm_day:用' missing '估算以创建新类别
 - DateofTerm_year:用' missing '估算以创建新类别
 - DateofTerm_quarter:用' missing '估算以创建新类别
 - DateofTerm_day_week:用' missing '估算以创建新类别
 - LastPerform_month:用' missing '估算以创建新类别
 - LastPerform_day:用' missing '估算以创建新类别
 - LastPerform_day_week:用' missing '估算以创建新类别
 - 任期 _ 期限:由于大量数据缺失而下降
 - 审查以来的天数:任意插补和缺失指标特征
 
处理异常值
离群值是另一个需要思考的有争议的话题。有许多处理异常值的方法。如果您有一个非常大的数据集和相对较少的离群值,您可以简单地删除它们。我通常对这种方法持谨慎态度,因为它会改变所述特征的分布,这可能会导致新值成为异常值。也就是说,这是一个经常使用的选项。其他方法包括添加指示要素,使用 np.log()重新缩放整个要素,以及通过应用离散化将异常值包含在一个条柱中来将连续要素转换为离散要素。
首先,我们需要确定是否有异常值。用于识别异常值的最著名的方法是 z-score 方法,该方法将特征值标准化为均值为零,标准差为一,任何低于 3 个标准差(正或负)的值都被视为异常值。就个人而言,我认为这种方法是有缺陷的,因为 z 值依赖于特征的平均值和标准差。均值和标准差都受到现有异常值的严重影响。均值和标准差计算中包含的任何异常值都将扩大 z 值的范围,并可能忽略现有的异常值。这个问题可以通过使用中间值而不是平均值来解决。
让我们利用一个更稳健的方法,它依赖于四分位距和中位数。您可以调整此方法,并使用(3 * IQR)仅识别极端异常值。
def outlier_treatment(feature):
    sorted(feature)
    q1,q3 = np.percentile(feature , [25,75])
    IQR = q3 - q1
    lower_range = q1 - (1.5 * IQR)
    upper_range = q3 + (1.5 * IQR)
    return lower_range,upper_rangeoutlier_treatment(df['PayRate'])
lower_range, upper_range = outlier_treatment(df['PayRate'])df[(df['PayRate'] < lower_range) | (df['PayRate'] > upper_range)]

训练/测试分割
X = df.drop('EngagementSurvey', axis=1)
y = df['EngagementSurvey']X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
数据处理流水线
**# impute categorical features with more than 5% missing values w/ a new category 'missing'**
process_pipe = make_pipeline(
    mdi.CategoricalVariableImputer(variables=['DateofTerm_month', 'DateofTerm_day','DateofTerm_quarter', 'DateofTerm_day_week',
'LastPerform_month', 'LastPerform_day','LastPerform_day_week', 'DateofTerm_year'], imputation_method='missing'),
**# Imputing categorical features with less than 5% missing values w/the mode**
    mdi.CategoricalVariableImputer(variables=['TermReason'], imputation_method='frequent'),
**# Imputing missing values for numerical feature 'days_since_review' with an arbitrary digit**
    mdi.ArbitraryNumberImputer(arbitrary_number = -99999, variables='days_since_review'),
**# We are adding a feature to indicate (binary indicator) which records were missing**
    mdi.AddMissingIndicator(variables=['days_since_review']),
**# Encoding rare categories (less than 1% & the feature must have at least 5 categories)**
    ce.RareLabelCategoricalEncoder(tol=0.01, n_categories=5,
                                   variables=['State']),
**# Encoding rare categories (less than 2% & the feature must have at least 5 categories)**
    ce.RareLabelCategoricalEncoder(tol=0.02, n_categories=5,
    variables=['Position', 'Zip', 'DateofTerm_day', 'LastPerform_day_week', 'DateofTerm_year', 'RaceDesc', 'TermReason', 'RecruitmentSource','DateofHire_day', 'DateofTerm_month', 
'LastPerform_day', 'DateofHire_year']),
**# Encoding rare categories (less than 5% & the feature must have at least 5 categories)**
    ce.RareLabelCategoricalEncoder(tol=0.05, n_categories=5,
                                   variables=['ManagerName']),
**# Target or Mean encoding for categorical features**
    ce.OrdinalCategoricalEncoder(encoding_method='ordered',
    variables=['FromDiversityJobFairID', 'Termd','Position', 'State','Zip','Sex', 'MaritalDesc','HispanicLatino', 'RaceDesc', 'TermReason','EmploymentStatus', 'Department', 'ManagerName', 
'RecruitmentSource', 'DateofHire_month','DateofHire_day', 'DateofHire_day','DateofHire_quarter', 'DateofHire_day_week', 
'DateofTerm_month', 'DateofTerm_day','DateofTerm_year', 'DateofTerm_quarter','DateofTerm_day_week', 'LastPerform_month', 
'LastPerform_day', 'LastPerform_day_week'] 
))
我们还没有讨论的一个话题是分类特征编码。我通常尝试并避免使用一键编码,因为它有极大扩展特征空间的趋势。如果我们使用一次性编码,“稀有”值/类别的编码当然有助于解决这个问题。也就是说,我选择使用目标或均值编码,因为它不会扩展特性集。这种方法用从 0 到 k-1 的数字替换类别。我们首先为每个类别的每个分类特征计算目标变量的平均值,然后根据平均值大小用上述数字替换平均值。例如,我们有一个二元目标,第一个分类特征是性别,它有三个类别(男性、女性和未公开)。让我们假设男性的平均值是 0.8,女性是 0.5,未披露的是 0.2。编码值将是男性=2,女性=1,未公开=0。
资料处理
process_pipe.fit(X_train, y_train)X_train_clean = process_pipe.transform(X_train)
X_test_clean = process_pipe.transform(X_test)X_train_clean.head()

摘要
如果您认为我可能错过了某个重要步骤,请随时提供反馈。感谢阅读!
Rust 中的数据处理与数据融合(箭头)

Rust 中的数据处理与数据融合(作者提供图片)
Rust 是最受喜爱的语言,据 stack overflow 称,它连续四年高居榜首!有了 Apache Spark 这样的框架,数据处理变得越来越简单和快速。然而,数据处理领域竞争激烈。data fusion(Arrow now 的一部分)是将数据处理引入 Rust 的最初尝试之一。如果您有兴趣学习 Rust with DataFusion 中数据处理的某些方面,我将展示 Rust with DataFusion 中的一些代码示例,并比较 DataFusion 和 Pandas 之间的查询性能。
更新:我最初在data fusion0 . 15 . 0 版本中写了这篇文章。在 DataFusion 和 Arrow 的 1.0.0 版本中,我添加了代码和基准,因此我们可以看到改进。
数据融合
安迪·格罗夫创造了数据融合,他有一些关于构建现代分布式计算的伟大文章,例如如何构建现代分布式计算平台。正如 Andy 提到的,DataFusion 项目还不适合生产环境,
“这个项目是学习构建查询引擎的一个很好的方式,但这还很早,还不能用于任何现实世界的工作。”
该项目于 2019 年 2 月捐赠给 Apache Arrow 项目,更多人开始为 Arrow 版本的 DataFusion 做贡献。
DataFusion 是一个内存查询引擎,它使用 Apache Arrow 作为内存模型。它支持对 CSV 和 Parquet 文件执行 SQL 查询,也支持直接查询内存中的数据。
项目描述可能不会带来太多的兴奋,但由于整个项目都是在 Rust 中完成的,它为您提供了关于在 Rust 中编写分析 SQL 的想法。此外,您可以轻松地将 DataFusion 作为库添加到 Rust 项目的 Cargo 文件中。
初始设置
为了用 DataFusion 测试运行一些代码,首先,我们需要创建一个新的 Rust 包
cargo new datafusion_test --bin
然后在 Cargo.toml 文件中引入 DataFusion 作为依赖项
[dependencies]
arrow = "1.0.0"
datafusion = "1.0.0"
测试数据集
网上有很多可用的数据集, Kaggle 是我经常去探索新数据集的地方之一。我们将使用的电影数据集,该数据集的完整版本约为 676.68 MB。电影数据集具有以下模式
userId: intmovieId: intrating: doubletimestamp: long
为了处理 CSV 文件格式,DataFusion 过去需要我们在这里提供模式,因为 1.0.0 版本引入了模式推断,这不再需要。
let schema = *Arc*::new(*Schema*::new(vec![ *Field*::new(“userId”, *DataType*::UInt32, false), *Field*::new(“movieId”, *DataType*::UInt32, false), *Field*::new(“rating”, *DataType*::Float64, false), *Field*::new(“timestamp”, *DataType*::Int16, false)]));
初始选择(版本 1.0.0)
随着 1.0.0 版本中引入更多特性,DataFusion API 带来了许多激动人心增强。您会看到诸如模式推断、更容易打印结果等改进。代码非常简洁,易于阅读。
DataFusion 1.0.0 的代码示例
DataFusion 与 Pandas 的性能比较
这不是一个公平的比较,因为数据融合是全新的,缺乏大量的优化。但看到 DataFusion 的当前状态并将其与 pandas 等成熟的数据处理包进行比较仍然很有趣。
免责声明:我在我的个人 Mac 13 ( 2 GHz 四核英特尔酷睿 i5 )上运行它来执行基准测试,结果可能会有偏差。因为最初的基准测试是在调试模式下发布的,所以注意到发布模式下的性能有很大的不同。
查询 1:选择前 10 行
**Query**: “SELECT userId,movieId,rating FROM ratings LIMIT 10”**DataFusion**: 0.7s**Pandas**: 6.15s
数据融合在随机存取 10 行上运行得非常快。另一方面,熊猫要慢 6s 左右。
查询 2:获得每个用户的平均评分
**Query**: “SELECT userId, AVG(rating) FROM ratings GROUP BY userId”**DataFusion**: 18.57s**Pandas**: 6.24s
由于熊猫在引擎盖下使用 NumPy,所以看到熊猫方面的良好表现就不足为奇了。在数据融合方面,虽然它比 Pandas 慢,但性能对于执行这些类型的聚合也是合理的。
问题 3:最高评分是多少
**Query**: “SELECT MAX(rating) FROM ratings”**DataFusion**: 15.28s**Pandas**: 5.97s
由于前面的分析查询看起来很慢,因此该查询在数据融合端也会很慢。
最后的想法
正如我们首先讨论的,DataFusion 是 Rust 进入竞争激烈的数据计算市场的一次令人兴奋的尝试。由于 DataFusion 项目仍处于早期阶段,需要更多的贡献,所以在某些类型的查询上看到一些缓慢的性能并不奇怪。此外,如项目自述文件中所述,缺少一些关键特性,因此您必须小心您编写的 SQL 命令,并仔细检查它当前是否受支持。
总的来说,DataFusion 是 Rust 对数据世界的一个有吸引力的开始,尤其是它现在是 Apache Arrow 的一部分,DataFusion 可以轻松利用 Arrow 生态系统的功能。我希望在 DataFusion 的未来版本中看到显著的性能改进和更多受支持的 SQL 特性。
希望这个故事对你有帮助。本文是我的工程&数据科学系列的部分,目前包括以下内容:

数据工程和数据科学故事
View list47 stories


你也可以 订阅我的新文章 或者成为 推荐媒介会员 可以无限制访问媒介上的所有故事。
如果有问题/评论,请不要犹豫,写下这个故事的评论或者通过 Linkedin 或 Twitter 直接联系我。
数据专业定义
数据分析师 vs 数据科学家 vs 数据工程师

最近,我阅读了很多关于定义数据科学家并将其与其他以数据为中心的角色区分开来的尝试。术语“数据科学家”、“数据分析师”和“数据工程师”显然是相互关联的。但是最近我看到了一些关于它们的怪异定义。
定义的重要性
让我澄清一下,这不仅仅是一个没有实际意义的愚蠢的语义诡辩(尽管它肯定是部分的,也许是大部分的)。这个问题经常出现在人们给出职业建议的时候。最近的一篇博文将数据分析师定义为使用 SQL 和 Excel 查询数据以生成报告的人,而数据科学家则是交付软件的人。这是一个建议,数据分析师职位不是数据科学家职位的良好准备,因为数据科学家基本上是软件工程师,数据分析师职位不会给你这种经验。然而,这个前提是基于对这两种角色极其狭隘的定义,这种定义可能只适用于某些公司。
另一个关于这些角色的愚蠢定义的例子来自我看过的 reddit 帖子,有人声称任何经常使用 pandas/sk-learn 的人一定是数据工程师。这种奇怪的说法似乎源于一种想法,即合法的数据科学家处于机器学习研究的前沿,因此必须从头开始编写全新的机器学习算法。
事情是这样的:如果任何人声称对这些角色有一个非常清晰、直截了当的定义,并对其进行了尖锐的描述,他们很可能是根据这些角色在一个公司(或行业)中是如何定义的经验进行推断的。这是因为这些工作本质上有很多重叠。
模糊定义

我会给出这些角色的高层次、模糊(希望没有争议)的定义如下:
数据工程师:专注于构建数据管道的数据专业人士,管理如何将数据从 A 点到 b 点。
数据分析师:专注于生成描述数据趋势/见解的报告的数据专家。
数据科学家:专注于从数据中产生洞察力和预测的数据专家。
请注意,我使用了“聚焦于”这个含糊的短语来避免做出任何强硬的声明。因为在本质上,这些角色中的每一个都与其他角色有很大的重叠,数据专业人员通常需要提取数据或移动数据。数据工程师制作仪表板或报告,或者数据分析师建立数据管道并不罕见。数据科学家有时可能会生成报告,而一些数据分析师会交付代码以投入生产。
任何你能想到的硬线(数据科学家用机器学习,数据分析师用 excel 等。等。)会有很多反例。有很多使用机器学习的数据分析师和使用 excel 的数据科学家。数据工程师可能会不时制作仪表板或进行分析。数据科学家可能需要制作数据管道或 Tableau 仪表板。
尽管缺乏强硬路线,但这些角色是有区别的。这是一个模糊但重要的问题。通常,数据科学家比数据分析师更专业,经验/技能也更多。数据工程师可能对数据库和数据管道有更多的了解,但对统计学了解较少。但是这个领域还没有到你仅仅通过标题就能轻易确定这个角色的范围的地步。
结论
底线是,如果你想成为一名数据科学家,并想知道该走哪条路,获得数据分析师(或数据工程师)的经验可能不是一个坏方法。然而,这取决于你得到的特定职位的具体情况。如果你是一名数据分析师,与业务人员坐在一起,只使用 excel 生成简单的报告,你将无法获得晋升到数据科学职位所需的经验。但如果你与其他数据科学家密切合作,或者被期望学习统计/机器学习来履行你的职责,这可能是很好的体验。我认为我上面提到的博客文章确实在这方面给出了很好的建议——关注一下你将和谁坐在一起,因为这很可能会告诉你你将会学到什么技能。
帮助您起步的数据项目
如果您足够仔细地观察,就会发现有大量的项目需要复制,还有大量未使用的数据源需要分析。

在 Unsplash 上由 Carlos Muza 拍摄的照片
在一个城市中,有数不清的数据项目要做。项目选择可能非常困难,最初的挑战几乎总是找到合适的数据来使用。尽管来自全国各地的其他首席数据官总是愿意提供帮助并分享他们自己的工作示例(来自数据智能城市解决方案、宾夕法尼亚大学穆萨项目和社会公益数据科学的优秀示例),但通常使用的特定数据集与您所在城市收集的数据并不完全相同,或者数据集无法公开共享以供参考。
在这篇文章中,我将详细介绍几个不同的地方,以找到几乎可以在该县任何其他城市复制的数据(或者以您所在的州为例)。这些数据源是健壮的,并且通常非常干净和易于使用。
人口普查
新推出的data.census.gov是一个优秀且易于使用的数据下载资源。人口普查局还构建了 API,使得以编程方式下载数据变得容易。数据在全国范围内以完全相同的方式格式化,并且在许多情况下可以精确到您所在城市的几个街区。
几年前,我们撰写了一份名为《线下的 T14》的报告,分析了锡拉丘兹与贫困相关的人口普查数据和指标。收集和清理数据很简单,我们能够将锡拉丘兹与纽约北部的其他城市进行比较。任何人都可以为他们的城市找到相同的精确数据表,并将他们的数据与锡拉丘兹的数据进行比较,以扩展报告。人口普查的数据非常重要,经常用于城市分析。一个地方的有趣分析可以很容易地复制到另一个地方,只需简单地转换一下县、市或人口普查区的号码。
财产评估资料
我们与约翰·霍普金斯大学的卓越政府中心合作,这是我们与有效城市合作的一部分,以分析财产评估数据,并试图更好地了解相对于可能的财产销售价值,财产评估哪里出了问题。我们从伊利诺伊州的库克县评估办公室获得了这个项目的灵感。了不起的是,库克县的评估数据与锡拉丘兹的评估数据非常相似。
更好的是,在纽约州,几乎每个自治市都使用一个名为房地产系统(或 RPS)的数据库,该数据库为全州的房地产维护一个一致的数据模式。这意味着使用我们的代码,纽约的另一个市政当局可以很容易地复制我们在锡拉丘兹的工作,在他们各自的地区尝试相同的项目。
物联网
也许你真的想进入“智能城市”领域,开始使用来自传感器的数据。这可能是昂贵的,难以实施,有时价值是值得怀疑的。相反,为了测试分析实时传来的传感器数据,像美国地质调查局这样的联邦级机构在许多不同的地方放置传感器,尤其是水道。因此,您可以创建一个查看湖泊或河流水位的项目,然后只需在 API 调用中更改特定的水体即可轻松复制该项目。
同样,国家气象局在全国各地放置天气传感器,通过他们提供的 API 很容易获取数据。像 ESRI 这样的公司使得使用这些数据变得更加容易,而且你很有可能在工作中拥有 ArcGIS 许可。
开放数据门户
美国联邦政府的开放数据门户data.gov,是一个可用数据的宝库。美国许多州也有开放的数据门户(纽约州的是 data.ny.gov 的)。这些开放的数据门户包含关于你的城市的数据。你可能会发现所有拥有酒类许可证的企业或者你所在城市的质量桥梁在哪里。同样,即使您所在的城市可能没有收集这些数据,但这些数据是有用的,可以通过非常简单的特定位置过滤,与州或国家的其他城市或地区进行比较。
结论
即使在应对让市政当局收集的数据更有用的挑战之前,也有大量资源可以从州政府或联邦政府那里找到数据。很多时候,这些数据得到了更好的维护,并且可以很容易地与该国的其他地区进行比较,或者有人可能已经使用您想要复制的相同数据集完成了一个项目。您还可以将这些数据集用作更大分析中的附加数据点,将您所在城市的数据与其他级别政府的数据相结合。
您在哪里使用这些来源的数据复制分析?
纯度如何定义您的数据科学项目
入门
使用一部电影→ 百老汇回归模型来证明对良好数据的需求

一个丢失的数据点(或字母!)能让都与众不同(图片由 Franki Chamaki 、 Unsplash )
你不需要线性回归器来识别数据科学的核心租户之一— 坏数据 导致 坏研究 。这在我与 Metis data science boot camp 的第二个项目中得到了生动的展示,这是一个线性回归模型,旨在根据电影的商业成功预测改编自百老汇戏剧或音乐剧的总收入。在本文中,我们将讨论数据纯度,以及为什么在这项研究中缺乏数据纯度导致了一个还不太适合这个阶段的模型。
(对于任何对螺母和螺栓感兴趣的人,请查看项目回购!)
什么是数据纯度?
数据纯度是我在学习 SQL 时第一次遇到的术语,特指某一列中的值超出了该列的范围。如果你有一列数字代表一周中的某一天,任何大于 7 的数字都会被认为是不纯的。一周有七天,所以任何超过七天的数字一定是由计算或人为错误造成的。这不一定代表异常值(就像“1”在一个充满周末的表格中代表星期一——6 和 7),但更多的是指逻辑上和统计上不可能的数字(-9,或 900)。
当您处理从 web 上搜集的数据时,数据纯度变得尤为重要。网页抓取是一项细致但奇怪的令人满意的任务,最好的描述是编写成千上万个小机器人进入网页并提取数据。这对于一些巨大的数据收集任务也是必要的——例如,从 10,000+ IMDB 页面中抓取信息。这是我项目的第一步,除了其他特点,我还对每部电影的和 国内外总收入 特别感兴趣。这些变量被认为是特征,可能被你的高中科学老师称为自变量。
特征可变纯度
对于大多数正片长度的电影来说,这些信息在 IMDB 上很容易获得,而且相当可靠。2017 年翻拍的 美女&野兽 是设计这部网络电影的完美参考,预计 1.6 亿美元的预算与 5.04 亿美元的国内总收入和 12.6 亿美元的国际总收入相比非常合理。然而,一些电影在信息方面并不那么可靠。就拿 1933 年的电影来说,这个灵感来源于轰动一时的百老汇同名音乐剧。这部电影在预算和全球票房之间取得了有趣的平衡:

《第 42 街》是 1933 年最卖座的电影之一,它的表现并不理想。(图片:IMDB)**
你试着向投资者解释一下利润。
当然,42 街在其商业寿命中赚了 1600 多美元。事实上,它已经赚了 1000 多倍,达到了220 万美元。这些错误并不总是被额外的研究纠正;事实上,经常交叉引用的来源有一些明显错误的信息,而 IMDB 有正确的数据。然而,通常情况下,这些信息在任何地方都不存在。有时会有国内毛额信息(但没有预算),有时会有预算信息(但没有毛额)。事实证明,当“砒霜和旧花边”的预算总额不容易获得时,并没有太大的轰动。****
这当然是最重要的问题。在最终的数据集中,几乎一半的只在这两个特征中含有杂质。国内总收入虽然不是舞台改编成功的可靠预测指标,但却是相关性最高的变量,但国内总收入仅适用于约三分之二的报废电影。这项研究受益于百老汇票房的铁证金融数据(感谢这个 Kaggle 数据集,来自百老汇联赛挑剔的周票房记录),但所有的特征变量都来自电影表现。****
确保数据纯度的最简单方法是确保准确的数据存在于您的特征中,并在您的模型中仅使用该准确的数据。几乎每个数据集都存在缺失值,但在相对较小的样本中,你必须确保所有数据的都是准确的。当我意识到我的数据有问题时,我花了几个小时在网上搜索,手动输入那些没有通过网络搜索的值。这很有帮助,但是我仍然有数百个空值。那些空值可以用来做什么?**
目标可变纯度
在从 IMDB 中抓取和清理了 10,000 部电影的数据后,是时候与上面提到的百老汇总数据集(1986 年以来的所有节目)合并了。光是名字就找到了 27064 个匹配!正如你所想象的,这些年来有相当多的对《美女》和《野兽》的改编,包括 2010 年《T2》的黎巴嫩版《T3》,这让一位评论家写下了《让野兽呆在笼子里》。经过几个阶段的缩减,数据集变成了 521 部独特的电影,其中大约一半仍然没有可靠甚至完整的财务信息。我发现了鼠标,这是一个非常方便的算法,通过使用其周围的值来处理缺失值,比使用平均值要复杂和彻底得多。
幸运的是,潮流开始流行起来。涉及电影类型的网络抓取要成功得多,从其 IMDB 页面指定指定的类型。不出所料,本质上是“音乐剧”的电影导致了一些高票房的舞台改编——音乐剧通常反映了每周最高票房的百老汇作品,仅《汉密尔顿》一部就经常占到周票房的近 10%。有趣的是,“冒险”电影似乎取得了相对成功的舞台改编——《李尔王》和《冬天的狮子》被恰当地称为具有成功舞台改编的冒险电影。然而,不知何故《灰姑娘》溜进了这一类,它可能更适合类似的“幻想”或“家庭”类别。

不同类型电影的视觉表现,以及它是如何影响舞台电影的周票房的
这些因素,加上总的和预算的信息(无论是真实的还是由 MICE 算法推断出的),使得一个可服务的模型得以完成。利用线性回归,我创建了一个算法,根据电影的成功来预测百老汇演出的总收入。

****残差图,可视化预测值和实际值之间的(巨大)差异
结果可以在左边找到,可能足以让任何有自尊的数据科学家感到不安。这个图表显示了预测值和实际值之间的差异。那些为数不多且影响深远的异常值代表了票房大大低于预期的节目。这些是像猫和歌剧魅影这样的节目——长期播放的作品,在几十年的播放中有机会比像发胶或合法金发女郎这样的音乐剧赚更多的钱——商业上成功的作品,更“正常”地播放 1-3 年。人们可以推断,运行时间的长短是商业成功的一个方面,而“烘焙”这一元素将有助于算法。在更长的时间里赚更多的钱意味着更成功,对吗?事实证明,它确实阻碍了模型试图大量制造目标变量,而不是让平均每周总收入代表节目的成功。
这就引出了我们的第二点——您的目标(预测或相关)变量中的数据纯度可以通过一个简单且无权重的目标来实现。当确定你到底想要预测什么时,最好不要在计算关系之前就加入额外的因素。甚至考虑到消费者价格指数(代表每年的通货膨胀和市场情绪)实际上损害了这个模型。简单的目标创造更有效的模式。对于像运行长度或通货膨胀率这样的因素,试着将它们视为特征而不是目标变量,或者更好的是,实现一个 广义线性模型 ,在这篇有用的文章中 Yuho Kida 对其进行了完美的分解。这一简单但重要的步骤将帮助您的残差图看起来更像下图,表明预测错误的分布信息更丰富。****

一个更好的(尽管不完美)残差图,恢复了对该模型未来的信心
问题的纯粹性——我在解决什么?
这项研究的初衷是预测一部长篇电影的舞台改编的成功。给定有限的样本量,一个感觉不可能考虑的因素是第一个出现的。该数据集有大约 400 部电影在成为百老汇戏剧或音乐剧之前是电影,只剩下 120 部舞台改编电影。简单来说,这是两个独立的问题。电影业历来胜过商业戏剧业(顺便说一下,商业戏剧业仍然是旅游业和经济的发电站,仅在纽约市百老汇区,2018-2019 年就产生了据报道的120 亿美元——这要感谢 Yaakov Bressler 的最新统计数据!).一部电影的广泛知名度往往会导致成功的舞台改编;电影改编只有在百老汇大受欢迎的情况下才有可能被改编。电影到音乐到电影再到商品,如自由和发胶,还有一些因素在这里发挥作用,超出了这个项目的范围。
对数据纯度同样重要的是保持问题的纯度——我们的第三个也是最后一个建议是始终 记住你的“可解决的”问题。当我努力确保项目的样本量足够大时,继续解决同样的问题变得越来越困难,如果不是不可能的话。这是一个可解的问题,关系确实存在。如果我们花时间去注意数据的不纯,那么数据的纯度通常是一个可以克服的问题。数据科学家必须在服务于他们项目的前端找到支持数据,而不是最终会破坏模型的变化无常和未经证实的数据。

《西区故事》最近的复兴是在百老汇上映前几天,当时新冠肺炎关闭了纽约市
这种模式的未来
随着更多的手动输入,网络搜集之外的广泛研究,筛选副本的更精细过程,以及复杂的广义线性模型,我看到了制作人确定舞台改编的财务可行性的真正有用的工具的可能性。我期待着今年晚些时候重新审视这一模式,并打算整合我从准备这篇博客以及在 Metis 工作中学到的所有知识。
发布这些结果和提示而不注意到这些数据可能在一段时间内没有用处,感觉很笨拙。由于新冠肺炎的感染率和不确定性,百老汇重新开放数据的时间越来越晚,很难知道这种数据何时会再次变得重要。然而,随着我们在 2021 年及以后实现大规模复苏,百老汇每天都将面临这类问题。这一过程得到了加强,而没有受到来自商业剧院的可用数据的威胁。凭借纯粹的数据、开放的思维和对百老汇剧院变革力量的承诺,任何逻辑回归都无法捕捉到,复苏不仅是可能的;迫在眉睫。
如何创建数据质量仪表板
提高数据质量的基石
仪表板的主要目的是提供一个全面的性能快照,这意味着您应该包含大量的细节,而不需要使用太多的向下钻取。它使用过去的数据来确定趋势和模式,这些趋势和模式可以帮助设计未来的流程改进。
数据质量仪表板是一种信息管理工具,它可以直观地跟踪、分析和显示关键绩效指标,突出显示关键数据点,以监控业务、部门或特定流程的运行状况。它们可以定制,以满足企业的特定需求,它显示了您对数据的信任程度。
提高数据质量是一个长期的过程,这种计划的最佳结果是防弹过程,它将在未来为您服务,而不仅仅是及时清理数据。如果你想有效率,你应该让你的过程在形状监视器中变化并控制它,而不是定期执行数据清理练习。纠正数据非常耗时,因此在设计和实施新流程时,请尝试提前考虑。在质量保证上投入时间可以为你节省很多后期工作。
如果您仍然不知道为什么需要可靠的数据质量,请查看本文:
[在这里,你可以选择 10 个让数据质量井然有序的理由。](http://Completeness doesn’t bring to much value to the table. It can be misleading as you can have all the attributes completed but its about the content of the field you are validating and it still can be garbage.   Compliance/Validity - This should be the focus when starting a data quality program. Does your data is satisfying business usage requirements? We can split this to : 	• Format checks 		○ This depends on company standards and markets but examples are: 			§ Formats of postal codes (you need to define this per countries) 			§ Minimum and Maximum Number of characters - so there are no 1 character addresses or company names 			§ In the case of a global company you can check if local characters are used in global names   	• External Reference data compliance 		○ Checking external standard can be very beneficial as this will be very usable in reporting but also many of those classifications can be regulatory ones that are mandatory to run business (Customs Tariffs numbers) 		○ Are countries codes are compliant with ISO codes standard. 			§ Are Customers classified with SIC codes that exist 			§ Various Product classifications are mandatory in many markets: Wee classification, ETIM, UNSPC, Customs Tariffs. You can get the list valid codes and perform validation of your products   	• Internal Master Data compliance: 		○ For better Strategic reporting companies are implementing internal segmentation or classification of customers products and orders. 			§ You need to create a master data reference table and then validate your records classifications against it. 			§ Various internal business rules can be implemented here but this should be suited to your needs and started with the design phase to address actual issues of organizations: 				□ Each product need to have assigned active profit center  				□ Each Client needs to have an active owner.   Consistency - is your data the same in different sources? This should be relatively easy if you have Master data in place and each local records are connected to your master data source of truth with a global identifier. Just compare key attributes in different sources. In an ideal world data should be syndicated from source of truth to consuming systems: 	• Addresses in CRM against SAP against your Master Data     Timeliness - is your data up to date 	• schedule and monitor the data review process. Each records with  	•      defined last edit date should be reviewed by the owner 	• Is your data provided on time? - Creating new customers is a workflow and you can have different requirements on different steps of the sales process, always consider the business process when monitoring such aspects.  		○ For example, newly locally created customers records should be cleared and assigned with Global Customer Id withing 2 working days   Correctness/Accuracy - This is the most difficult one as there is no easy way to check that from the IS point of view. How can you check if product weight is 10 kg and not 15 kg? Ideally its established through primary research. In practice: 	• Manual auditing of sample 	• use 3rd party reference data from sources which are deemed trustworthy 	• Data Profiling and finding coherence patterns 	• Manual validation by owner – akin of crowdsourcing It is not possible to set up a validation rule. Instead, you should focus on creating logic that will help discover any suspicious pattern in your data that varies from what you saw in past     What to measure : Start with talking to data users and define your top elements and attributes and then the purpose of it. Look into user problems try a design thinking approach to discover opportunities. Define more crucial ones and start measuring them. You can group your KPI` into domains and accountable parties, then calculate quality indexes. Customer Data Quality can be built as a weighted average of attributes quality (Address, Vat, Owner) but also can include processes whenever these records are updated on time or are consistent in different sources. Juggle with weights  based on Business Impact     Make them SMART   Specific - specifically designed to fulfill certain criteria Measurable - KPI Status is constantly monitored and available on the dashboard Accountable - Clearly defined responsible party Relevant - They have an impact on business Time-based - there is time scope within they should be reach       My KPI checklist: 	• The object or its attribute is defined in the metadata tool rulebook or instruction 	• There is a clear business objective - so people now why are they doing it this is important and it is building data quality awareness across the organization 	• Clearly accountable function/person/organization 	• Communication plan 	• Reviewed with reference team and stakeholders         To recap, to improve and manage your data quality you need to know where you are now and where you want to be in a defined period so: 	• Describe your data with clear definition and rules 	• Implement a continuous monitoring process and keep systems and processes up to date. 	• Engage with everyone responsible for the data tell them why and build data quality awareness Increase the accountability for the data by assigning responsible)

斯蒂芬·道森在 Unsplash 上拍摄的照片
这些是主要的数据质量维度:
完整性— 不会给桌子带来太多价值。这可能会产生误导,因为您可以完成所有属性,但它是关于您正在验证的字段的内容,它仍然可能是垃圾。
合规性/有效性— 这应该是启动数据质量计划的重点。您的数据是否满足业务使用需求?首先定义规则,然后根据规则分析数据。我们可以把它分成:
- 格式检查,取决于公司标准、地点和市场,例如:
 
- 邮政编码的格式(您需要根据国家定义)
 - 最小和最大字符数—因此没有 1 个字符的地址或公司名称
 - 如果是全球性公司,您可以检查全球名称中是否使用了本地字符
 
2.外部参考数据合规性
- 检查外部标准可能非常有益,因为这将在报告中非常有用,而且这些分类中的许多可能是经营业务所必需的监管分类(关税号码)
 - 根据 ISO 代码标准验证国家代码。
 - 根据全球列表,使用有效 SIC 代码分类的客户
 - 各种产品分类在许多市场是强制性的:杂草分类,ETIM,UNSPC,关税代码。您可以获得有效代码的列表,并对您的产品进行验证,以便它们能够满足业务需求。
 
3.主数据合规性—为了更好地进行战略报告,公司正在对客户产品和订单进行内部细分或分类。您需要创建一个主数据参考表,然后根据它验证您的记录分类。这里可以实现各种内部业务规则,但这应该适合您的需求,并从设计阶段开始,以解决组织的实际问题,如:
- 每种产品都需要有一个指定的活动利润中心
 - 每个客户端都需要有一个活动的所有者。
 
一致性— 不同来源的数据是否相同?如果您有主数据,并且每个本地记录都通过一个全局标识符连接到您的主数据源,那么这应该相对容易。只需比较不同来源中的关键属性。在理想世界中,数据应该从真实来源整合到消费系统:
- 根据 SAP 和您的主数据在 CRM 中查找客户地址
 
及时性— 您的数据是最新的吗
- 安排和监控数据审查过程。每个记录有
 - 确定的最后编辑日期应由所有者审核
 - 您的数据是否按时提供?—创造新客户是一个工作流程,您可能对销售流程的不同步骤有不同的要求,在监控这些方面时,请始终考虑业务流程。
 - 例如,本地新创建的客户记录应在 2 个工作日内被清除并分配全球客户 Id
 
正确性/准确性 —这是最困难的一个,因为从 is 的角度来看,没有简单的方法来检查这一点。你怎么能检查产品重量是 10 公斤而不是 15 公斤?理想情况下,它是通过初步研究建立起来的。实际上:
- 样本的人工审核
 - 使用来自可信来源的第三方参考数据
 - 数据剖析和寻找一致性模式
 - 所有者手动验证——类似于众包
 
无法设置验证规则。相反,您应该专注于创建逻辑,这将有助于发现您的数据中与过去不同的任何可疑模式。
你应该测量什么:
从与数据用户交谈开始,定义你的主要元素和属性,然后定义它的目的。
调查用户问题,尝试用设计思维的方法来发现机会。
定义更重要的,并开始衡量它们。
您可以将 KPI 分组到业务领域和责任方,然后计算质量指数。
客户数据质量可以构建为属性质量(地址、增值税、所有者)的加权平均值,但也可以包括这些记录按时更新或在不同来源中保持一致时的流程。基于业务反馈校准度量迭代的权重。
让他们变聪明
特定—专为满足特定标准而设计
可衡量—状态受到持续监控,并可在仪表板上查看
负责——明确定义的责任方
相关—它们对业务有影响
基于时间—在他们应该到达的时间范围内
我的 KPI 清单:
- 对象/属性在元数据工具规则手册或说明中定义
 - 有一个明确的业务“为什么”,所以人们现在为什么要这样做这很重要,它在整个组织中建立了数据质量意识
 - 明确负责的职能/人员/组织
 - 沟通计划
 - 与参考团队和利益相关者一起审查
 
概括地说,为了提高和管理您的数据质量,您需要知道您现在所处的位置,以及在规定的时间段内您想要达到的位置,因此:
- 用清晰的定义和规则描述你的数据
 - 实施持续的监控流程,并保持系统和流程最新。
 - 与负责数据的每个人接触,告诉他们原因,并建立数据质量意识
 - 通过分配负责人来增加数据的责任
 
在 Twitter 上关注我,或者订阅我的博客以获得数据质量主题的更新。
原载于 2020 年 11 月 2 日 https://www.solution-tailor.com。
数据质量、数据运营和信任爆炸半径
缺乏信任将极大地影响您实现数据驱动的努力,除非您主动限制数据质量事件的爆炸半径。
动摇某人对数据的信任只需要一个小问题,但要让他们意识到这只是一个问题,而不是更大的问题,需要付出大量的努力。影响的差异是问题的“爆炸半径”,即使是最成熟的数据组织也可以更好地将其最小化。

图片来源:美国空军( via 维基媒体)
根据 Gartner 的数据,尽管近 98%的组织正在对其成为数据驱动的能力进行重大投资,但数据质量仍然会导致组织平均每年损失 1500 万美元的不良决策,根据 Experian 的数据,会影响 90%的公司。虽然我在之前的文章中报道了一些数据质量的恐怖故事,但是数据质量问题拖垮整个公司的情况并不常见。此外,现在有许多现代工具( Soda 、 ToroData 、 Trifacta )和实践(主要是 DataOps )使得数据质量最佳实践的应用比以前容易得多。
然而,我不认为我会冒险说数据质量永远不会成为一个解决的问题。我还认为,到目前为止,数据质量问题的最大影响不是基于糟糕数据的决策的直接影响,而是整个组织对数据和为数据提供服务的数据平台的信任丧失。特别是在那些过去已经受到 糟糕的数据质量影响的组织中,经常反复地,并不需要重大事件就能让“又来了”的消息在整个组织中回响。
事实上,IBM 的一项研究表明,整整三分之一的企业高管不信任他们的数据,他们认为平均 32%的数据是不正确的。要估计回归直觉决策的成本几乎是不可能的,但它可能非常重要。这次来自 Forrester 的另一项研究发现,由于缺乏信任,三分之一的数据分析师花费超过 40%的时间逐个领域地审查数据的质量问题。这些时间成本很可能没有计入上述 1500 万美元的硬性成本。
信任爆炸半径是多少?
爆炸半径(名词)——爆炸发生时受影响源的距离。

来源:维基媒体原子弹的爆炸半径
子弹和炸弹的区别在于影响范围。虽然一颗子弹实际上只能消灭一个目标,但一枚炸弹的爆炸可以夷平一座拥有数百万人口的城市。炸弹的冲击力与其爆炸半径成正比。近年来,术语“爆炸半径”在 IT 架构领域越来越流行,团队致力于尽量减少因单个系统故障而离线的额外系统的数量。
回到数据质量的话题,我很难相信一个普通组织中有三分之一的数据是坏的。更合理的数字可能是 10%*左右,尽管这可能会因数据领域的不同而有很大差异。10%的实际坏数据和 32%的假设坏数据之间的 22%的差距就是我定义的信任爆炸半径。
信任爆炸半径—单个数据质量问题破坏的额外信任量
因此,TBR 是对组织中不良数据量和整个组织中不信任数据量之间差距的度量。一旦一个人经历了动摇其信任的事件,恐惧、不确定性和怀疑会通过交流迅速传播给其他人,这是一个简单的事实。
正如我们在过去几个月里所了解到的,仅仅依靠遏制的策略注定要失败,并且很可能会产生很大的爆炸半径。不幸的是,几乎所有关于数据质量的文章都集中在预防、检测和快速纠正数据质量问题上。相反,如果我们接受数据质量问题总是会出现,尽管我们尽了最大努力来防止它们,并从预防的态度转变为预防的态度和爆炸半径最小化,我们将在推动数据驱动的文化方面更加成功。
信任爆炸半径 = 数据质量问题的数量在没有上下文的情况下关于问题的对话的数量之前对数据质量的负面体验的数量
如何最小化信任爆炸半径
几年前,我负责为一个处理大规模 IOT 数据的非常复杂的系统开发一个故障模式和影响分析(简称 FMEA)。我发现系统方法在提高系统的可靠性方面是有效的。作为背景,FMEA 最初是在 20 世纪 50 年代由美国军方开发的,用于核武器计划,然后被负责复杂系统的其他组织大量采用(NASA、飞机&汽车制造、半导体、医疗保健等)。它首先详细说明系统的组件(或流程步骤)和子组件,然后列出每个子组件可能出现故障的方式,最后检查故障的下游影响,并推荐一种控制机制来防止或最小化每个故障的影响。
举一个汽车行业的简单例子,内燃机的一个潜在故障点是正时皮带,如果它断裂会导致灾难性的发动机故障。正时皮带本身只是一条简单的橡胶带,带有像齿轮一样的齿。更换一个只需要大约 50 美元。如果一颗牙齿磨损了,它可能会脱落。这会导致发动机发出轻微的滴答声,这可能很烦人,但肯定不是灾难性的。然而,它也具有在缺齿点增加皮带磨损的副作用。如果磨损持续太长时间,更多的齿将失效,导致发动机中的气门和活塞之间更严重的正时失调,熄火。过一会儿,皮带会突然断裂,导致发动机随机启动阀门和活塞,字面意思是从内部自我毁灭。为了避免这个问题,所有的车辆都应该在 60 公里左右进行定期维护,以防止问题的发生。此外,当发动机中的传感器检测到正时皮带磨损的潜在迹象时,检查发动机灯亮起。关键是及早发现并解决问题,以避免发动机内皮带故障的更大爆炸半径。
虽然这些技术是为影响具有某种确定性的机器设计的,但它们为分析复杂系统提供了有用的指导,该复杂系统是一个正在经历向数据驱动转变的组织。
从数据和分析组织的主要职能开始:使企业能够从其数据资产中获得最大价值,通常是通过帮助数据驱动的决策制定,我们开始列举失败。
- 数据产品中包含一条无效数据,导致做出无效决策。例如,对于一小部分客户来说,客户满意度计算不正确,看起来好像不满意的客户非常满意。这导致你的公司向他们发送额外的交叉销售广告,而不是跟进,进一步疏远这些客户。
 - 数据产品的消费者检测到报告的数据点之一无效(即,与之前相同的场景,但是营销中的某人在发出广告之前注意到了该问题)。
 - 多个数据产品以不同的方式表示相同的概念,消费者不知道哪一个是正确的。例如,运营报告将活动客户定义为上周使用过系统的客户,而计费报告将其定义为支付订购费用的客户。
 - 数据产品的消费者不知道导致源和目的地之间转换的需求,并认为它是不正确的。例如,一份营销报告正确地过滤掉了所有选择退出沟通的客户,但是一位选择退出的客户的客户成功代表认为该报告一定是错误的,因为他们的客户不见了。
 
有许多潜在的失败,我们无法在一篇文章中涵盖。关键是,在每一种情况下,初始故障点的影响都不是很大。然而,如果不加以控制,它们会引发一连串的问题,造成巨大的影响。让我们看一看每一个,看看如果不加检查会发生什么
利用 C4 有效地塑造信任爆炸

来源:维基共享资源
为了不离题并使这些更容易记住,我将称它们为 C4,它有一个有趣的特性,可以用来制作聚能射孔弹。C4 技术 : 捕捉、编目、纠正和治愈,类似地塑造数据质量问题的爆炸,使其更有生产力,同时最小化爆炸半径。
捕获 —这是指由具有采取以下步骤的知识和权限的人捕获问题。理想情况下,在任何数据消费者意识到这些问题之前,可以通过在您的数据平台中进行监控来检测这些问题。然而,不可能捕捉到所有问题,正如上面的例子所示,一些未被发现的问题会导致爆炸半径的急剧扩大。因此,让您的数据消费者有发言权是至关重要的,并且他们相信为什么他们使用他们的发言权来提出问题,问题将会得到解决。这使他们能够以富有成效的方式发泄他们的沮丧,而不是与同样无力改善情况的同龄人一起开一个回音室。首先,确保组织中的每个数据消费者都可以访问一个地方来提出数据问题。同样重要的是,他们还必须知道如何使用这个工具。最后,他们必须看到他们的问题得到了解决,这将导致剩下的步骤。
目录 —一旦发现问题,让那些将要受到影响的人知道是非常重要的。在一个害怕承认失败的文化中,这通常是违反直觉的。如果目标是让数据消费者的默认思维模式保持信任而不是不信任,那么最好是告诉人们什么时候有什么需要担心的。回到正时皮带的例子,如果不清楚正时皮带何时出现故障,也没有检查发动机灯告诉你何时该担心,你会默认总是担心你的发动机可能在任何时候出现故障,并对你的汽车的可靠性失去信任,并告诉很多人这件事来发泄你的沮丧。
让人们在日常工作流程中能够看到数据问题的文档是非常重要的。如果您提供一个一致的位置来查找给定数据产品的数据质量说明,这是最容易的。例如,让您的数据消费者通过您的数据目录启动他们的 BI 报告,这为您提供了在他们打开报告之前在报告页面上显示任何数据质量警告的机会。然而,许多人可能会将他们最重要的报告加入书签,然后直接启动它们。这意味着您需要将警报直接推送到报告上(最好是在一致的位置),以引起他们的注意,并将他们引回到目录中的详细信息。显然,这种技术只有在数据管道非常可靠的情况下才有效。如果检查引擎灯每个月都亮,你也不会认为你的车很可靠。
编目什么应该被信任和记录什么现在不应该被信任同样重要。这实际上是检查发动机灯的弱点之一。可能是油箱盖没盖紧,或者你的引擎在接下来的 10 分钟内就要自我毁灭了。因为你不知道,你的反应必须从最坏的情况出发。相反,如果你可以打开一个应用程序,看看哪些引擎检查通过了,哪些导致了警告,那么你就能够做出明智的决定,下一步该做什么。在 DataOps 领域,这涉及到列出在部署到生产中之前为验证给定管道而运行的数据测试,以及那些为确保数据符合关键预期而持续运行的测试。在您的数据测试中使用 BDD 风格命名,并在数据质量注释和警告旁边显示测试状态,让您的数据消费者能够基于对数据当前状态的深刻理解来决定做什么。
正确— 对数据的当前状态(好的和坏的)进行编目和提升,有助于将数据消费者的默认心态从不信任转变为信任。需要的最后一份文件是关于正在采取行动让事情变得更好的文件。通过这种方式,使用工作单系统来跟踪数据问题比简单地将问题直接记录在目录中更有效。一旦你让数据消费者相信你是透明的,他们就不太可能通过询问组织中的所有人来确定他们上周发现的问题是否已经得到纠正,从而形成一个爆炸半径。

我的循环图显示了解决数据问题的行动和更新
这将我们带到最小化信任爆炸半径的下一个阶段,即快速纠正问题。这里的关键是超越简单地纠正问题,增加对问题已被纠正的信任。考虑下面的信任爆炸半径场景:一位营销分析师发现客户地址有问题,并询问 5 个人该向谁报告,然后向负责客户地址管道的数据工程师发送一封电子邮件。该工程师意识到他的最新更改导致了格式问题,修复了该问题,并通过电子邮件通知营销分析师该问题已经解决。现在,尽管分析师认为地址是正确的,但她与之交谈的另外 4 个人不知道该修复(甚至不知道问题的细节),并且很可能不太信任地址数据。
如果您的数据平台提供了前两个 Cs 所涵盖的功能,并且您的数据团队实践了测试驱动的开发,那么这四个人将能够看到在工程师修复问题时添加的新测试正在通过,并且没有针对地址数据的未结票据,从而恢复他们的信任,而不需要与数据工程师直接对话。
解决— 最后一步是通过首先解决导致数据问题的系统问题来阻止问题再次出现。这绝对是最复杂的事业,但也有最高的回报。
对票证执行趋势和根本原因分析,以发现系统性问题
将问题单与“系统修复”单联系起来,后者通常是新数据平台功能的开发,但也包括数据运营运营模式中的流程改进,可在开发生命周期的早期发现问题
我的其他文章中有这类改进的例子:
- 基于模式测试在主数据中应用的标准数据质量规则(参见Data ops 文章)。
 - 改善控制数据捕获的分析团队和应用程序开发团队之间的协作(有关更多详细信息,请参见关于为数据所有者赋权的文章)
 - 创建数据催化剂角色,以增加数据产品开发团队在源数据方面的详细知识(参见使用数据催化剂进行数据转换一文)
 
提供对这些类型的改进的可见性并不像纠正数据问题或捕获数据测试那样简单,但也不是不可能的。您可以从以一种可以与数据目录和票据相互链接的方式记录您的数据流程开始。使用可以直接嵌入到目录中的灵活的流程图表工具,可以将流程更改与它们要解决的系统数据问题一起记录下来。然后,你可以在新的工作方式上运行微型学习会话,记录它,通过人工智能转录运行它,并将记录和转录嵌入目录中。
您可以使用相同的技术来获取和嵌入关于正确使用目录查找上述信息的培训,并将其放入您的目录主页。为了推动文化变革,您可以显示直接在数据目录中提出的数据问题的总体趋势,该数据目录充当“所有数据的大门”。由于此 KPI 呈下降趋势,请突出显示您的组织对推动改进的数据方法进行的系统性修复。在此基础上,您可以启动一个数据管理计划,更直接地激励人们改进数据文档和质量。
结论
到目前为止,几乎地球上的每个人都上了一堂流行病学的课。很少有人认识到,对其组织投资的数据资产的不信任会以非常相似的方式传播。利用这些知识,我们可以将数据策略透镜应用于医疗社区中使用的相同技术,以确定如何应对。
一如既往,我愿意与任何对提高组织从数据中提取价值的能力充满热情的人讨论这些想法。
我找不到一项研究对组织中实际上糟糕的数据百分比进行了严格的报告。最接近的是 2007 年 Gartner 的一项研究指出 27%的财富 1000 强公司的数据是“有缺陷的”,但他们对有缺陷的定义包括重复数据。让我们假设这种趋势一直持续,重复数据占 27%中的 17%,剩下 10%是真正的坏数据。这意味着,平均而言,信任差距是坏数据量的近两倍。
IBM Watson 知识目录中的数据质量维度
入门
理解 IBM Cloud Pak 用于数据和 IBM Infosphere Information Server 的标准数据质量维度。

图片由 saulhm 从 pix abay(【https://pixabay.com/users/saulhm-31267/】T2)拍摄
在之前的文章中,我详细解释了 IBM Cloud Pak for Data 和IBM info sphere Information Analyzer如何为每个分析的数据集计算统一的数据质量分数:
简而言之,数据集的数据质量分数是通过应用寻找不同类型的数据质量问题的算法来计算的。每当数据不满足给定的期望时,就识别出数据质量问题。可以针对数据集的单个单元格、完整的行、列或整个数据集报告此类问题。数据质量问题的类型在用户界面中显示为“数据质量维度

沃森知识目录中的数据质量维度结果
IBM 随其产品发布了一个标准数据质量维度列表。在 Watson Knowledge catalog 或 Information Server 中分析数据集时,会自动应用这些现成的维度。这可以在深入研究所选数据资产的数据质量的数据质量项目中完成,也可以作为数据发现和摄取过程的一部分完成——请看我以前的文章“用 IBM Watson 知识目录解锁您的数据”以了解这种发现过程是如何工作的。
在这篇新文章中,我将详细解释这些标准数据质量维度中的每一个,它们测量什么以及它们执行起来有多昂贵。
数据质量维度的成本
并非所有的数据质量维度都同样昂贵。某些类型的数据质量问题在逐行的基础上很容易识别,其他一些可能需要更多的工作和多次通过数据,因此可能对分析时间产生不可忽略的影响。
就性能而言,数据质量维度的成本主要取决于识别所搜索的数据质量问题所需的数据传递次数。一些数据质量维度不需要读取数据,因为它们可以重用在数据质量分析发生之前由数据分析预先计算的统计信息。大多数数据质量维度需要对数据进行一次遍历。有些人需要读取整个数据集来计算一些统计数据,然后再次对所有记录进行第二次检查,以便识别问题。
数据质量维度的范围
正如我在上一篇文章中所解释的,数据质量问题可以针对单个值、完整的行、完整的列或整个数据集进行报告。这就是我在本文中称之为数据质量维度的范围。
维度的范围越细,计算的数据质量分数就越准确,因为可以避免重复计算问题。
为了说明这一点,假设在同一列中有 10%的数据类违规和 10%的格式违规。如果这两个数据质量维度的范围在列级别,也就是说,如果问题是针对整个列报告的,则无法确定 10%数据类违规中有多少与格式违规的值相同。这意味着该列的数据质量分数将被计算为 90% * 90% = 89%。
实际上,这两个维度可以在价值层面上确定问题。最有可能的情况是,当一个值没有预期的数据类时,它也没有预期的格式,因此许多违反数据类的值可能与违反格式的值相同。
在这种情况下,由于错误值就是错误值,无论它有多少问题,数据质量分数都会被计算为 90%,这表明 10%的值有问题。
这个例子表明范围值的数据质量维度是最准确的。然而,对于一些问题来说,确定有问题的精确值是不可行的或者太昂贵了。因此,一些数据质量维度仅在列级别报告它们的问题。
现在,让我们来看看每个单独的数据质量维度。
没有任何数据传递的维度
重复值-范围:列
此维度在应该只包含唯一值的列中查找重复值,例如在主键列中。由于作为数据质量分析的一部分,搜索重复项的开销太大,因为这需要对所有列进行排序,所以该维度重用了在数据分析(列分析)期间预先计算的统计信息。这样做的好处是,维度不需要再次查看数据,但它只能报告列作为一个整体出现问题的频率,而不能确定哪一行受到了问题的影响。正因为如此,不排除影响相同数值的多个问题被重复计算。
为了找出包含重复项的确切行,您可以使用数据规则。
需要对数据进行一次传递的维度
数据类违规-范围:值
此数据质量维度报告与其列的推断或选择的数据类不匹配的任何值。
但是您需要知道,并不是所有的数据类都可以用于在值级别识别域违规。与数据质量问题一样,数据类有一个范围来指示它们是适用于值级,还是仅适用于列级。
在值级别工作的数据类(例如基于正则表达式或值列表的所有数据类)可以为每个测试值返回完全匹配或不匹配的决策,因此可用于在数据质量分析期间验证值。
在列级工作的数据类——例如 person name 之类的数据类——只计算列作为一个整体属于给定类的置信度,但不能测试任何单个值。
由于这个原因,如果分配给列的数据类的范围是列,则数据质量分析将忽略该数据类,并且不会在该特定列上搜索数据类违规。
您可以通过查看其定义 Watson 知识目录来检查数据类的范围:

查看 Watson 知识目录中数据类的范围
数据类型冲突-范围:值
此维度计算与其推断或选择的数据类型不兼容的列的值:
在数据分析期间,列分析确定每个列的推断数据类型。推断的数据类型独立于源中定义的数据类型,表示最具体的数据类型,它可以包含列的所有值。
为了说明这个概念,让我们想象在 SQL 数据库的表中定义的列,数据类型为 VARCHAR(255)。该数据类型是在数据源上定义的数据类型,但实际上,列的值可能包含编码为字符串的日期。在这种情况下,根据值的格式,推断的数据类型可以是日期或时间戳。
再比如,如果同一列包含字符串,但最长的字符串只有 40 个字符长。那么推断的类型将是 VARCHAR(40)。
如果列包含不同类型的混合,例如日期、字符串和数字,那么推断的数据类型将是可以表示所有这些值的最具体的类型,在本例中是 VARCHAR(n),n 是最长值的长度。
用户可以覆盖推断的数据类型,以指示应该使用哪种数据类型。例如,如果选定的数据类型设置为 DATE,则任何不是本机日期值或者不是可被解析为日期的字符串或数字的值都将被视为违规。
格式冲突-范围:值
此维度计算某一列的值,该列的格式已被用户标记为对此列无效。
这意味着该维度将只查找已识别格式被用户声明为无效的列的问题。为此,您需要在数据质量项目中打开列的分析结果,并转到“格式”选项卡以查看所有已识别格式的列表。然后,您可以进入编辑模式,将不需要的格式标记为无效。

编辑列的有效格式列表
通过这样做,您可以在列上添加一个约束,指示哪些格式是有效的,哪些是无效的。这将使当前数据质量分数无效,当重新计算时,该分数将反映基于新约束的结果。
不一致的大写-范围:值
该维度首先检查列的大多数值是否遵循字符串中关于大小写用法的任何约定。列的大写规则可以是下列规则之一:
- 大写:数值只写大写。比如:
这是一个值 - 小写:数值仅以小写书写。例如:
" 这是一个值" - 名称大小写:数值中每个单词的第一个字母都是大写,其余的都是小写。例如:
这是一个值 - 句子大小写:每个值的第一个字母大写,其余小写。比如:
这是一个值 - 任意大小写:大小写混淆,无法识别规则。比如:
这是一个值 
如果列中的大多数值使用这些大写规则之一,则不遵循相同大写规则的值被视为数据质量问题。
如果数据在使用的资本化规则中没有显示任何强模式,那么分析将假设资本化不受约束,并且不会搜索任何该类型的发行。
缺少值的表示不一致—范围:值
如果在同一列中同时发现 null 值和空值或仅包含空格的值,则此维度会报告问题。
缺少值-范围:值
此维度在不应该包含缺失值的列中搜索为 null 或空的值。
您可以在列分析结果的“列属性”选项卡中设置标志,指示对于给定的列,缺失值是否可接受。

指定列中是否允许缺少值
请注意,与 UI 所建议的相反,这不仅仅是关于空值,而是一般的缺失值,也包括包含空字符串或仅包含空格的值。
如果没有指定约束,那么分析将通过查看列中缺少的值的数量来尝试推断列的可空性标志。如果缺失值(空值和空值)的数量低于可空性阈值,则该列被视为不可空,任何缺失值或空值都将被视为数据质量问题。如果该列包含的缺失值多于阈值所允许的值,则分析将假定缺失值在该列中是预期的,并且默认情况下不会报告问题。
默认的可空性阈值是 1%,这意味着只有包含少于 1%的缺失值的列才被认为是不可空的。您可以在项目的数据质量设置中设置此阈值。

值超出范围-范围:值
仅当指定了列的最小和/或最大允许值的范围约束时,才使用此维度。
您可以通过打开列的分析结果并在“Column Properties”选项卡中进入编辑模式来定义这样的约束,如下一个屏幕截图所示。您可以设置最小值和/或最大值。任何超出指定范围的值都将被报告为有数据质量问题。

指定列的最小和/或最大允许值
违反规则-范围:值
数据规则和质量规则是定义自定义维度的最简单方法。
数据质量分析将考虑所有数据规则或质量规则,这些数据规则或质量规则被绑定到所分析的数据集的列,并且不需要与其他数据集的任何连接操作。如果规则与这些标准匹配,则在数据质量分析期间,将在分析的行上评估其逻辑。
每当数据集的一行没有通过规则时,将为绑定到给定行的规则的每一列报告数据质量问题。每个规则在其自己的数据质量维度下报告。
请注意,没有必要单独运行数据规则来评估它们的逻辑,作为数据质量分析的一部分。包含规则的逻辑作为对数据集的约束将是自动的。
需要两遍数据的尺寸
可疑值-范围:值
这个数据质量维度不太容易解释,但同时它也是一个相当强大的维度。
基本上,这个维度搜索看起来不像与同一列的其他值属于同一个域的值。在某种意义上,这类似于搜索异常值,但是异常值的概念不仅扩展到值本身,还扩展到它的格式和属性。
为了更好地解释这是如何工作的,假设您看到一个打印的电话号码列表。如果不看单个的值,您很有可能一眼就认出这些值是电话号码,因为它们看起来就像电话号码。
人脑不会评估每一个单独的值,但会提取一些关于格式的模式,即它们主要由数字组成的事实,值的长度等,并将这些模式与我们从过去了解到的电话号码通常的样子进行匹配。
与此同时,如果在一长串电话号码中间,有一个值不是电话号码,而可能是电子邮件地址,人类大脑会立即发现其中一个值显然是错误的,而不必读取任何单个值。
在这个简单的例子中,怀疑值维度试图模拟大脑在做什么。为此,它首先为一个列计算一个域指纹,该域指纹包含似乎表征值域的已识别模式。一旦指纹被计算出来,它会对数据进行第二次处理,试图识别出哪个个体值似乎与这些识别出的模式有很大偏差。
该决策中考虑的值的属性是多种多样的,并且根据数据的性质而不同。它可以考虑值的格式、值中更频繁出现的标记、关于长度、标记数量、值中发现的字符类型、值的二元模型分布等的各种统计数据。
在下面的示例中,第一列中突出显示的值将被检测为可疑值,因为它的二元模型分布和令牌数与其他值不一致。在第二列中,该值将被标记为可疑,因为它是包含字符串的列中的一个数字。在第三列中,突出显示的值将被标记为可疑,因为它是数值异常值。

可疑值示例
此维度可用于检测不明显的数据质量问题,如果指向这些问题,人们将能够看到,但这些问题可能隐藏在许多行的中间,因此可能难以识别。
这个维度的缺点是成本更高,因为它需要一遍学习什么应该被认为是预期的,以及一遍检测可疑值。
您还应该理解的是,当一个值被认为可疑或不可疑时,这个维度不提供确定性规则。它基于概率和大多数值的比较。这当然可能会产生误报或遗漏错误的值,就像人脑可能会出错一样。
相关列中的可疑值—范围:值
这个维度是对前一个维度的补充。虽然“可疑值”维度仅查看同一列的值在其列中是否是同质的,但此维度查看单行中的值组合放在一起是否合理。
为此,它首先在第一遍中搜索列之间是否有任何相关性。如果一列的值可以由另一列的值确定,则这两列是相关的。例如,如果一列包含组合一个或多个其他列的运算结果,则可能是这种情况。如果一列对另一列具有包含依赖关系,也可能是这种情况。
作为一个具体的例子,假设您有一个数据集,其中一列包含城市名,另一列包含州名。对于任何给定的城市,通常只有一个州。这意味着这些列之间存在相关性。该分析可以从数据集的记录中学习关联规则,并识别城市和州似乎不匹配的数据质量问题,因为它们的组合会违反关联规则。
简而言之:如果大多数以旧金山为城市的行也以加利福尼亚为州,那么一行{旧金山;Arizona}将被报告为可疑,因为这是一个值的组合,它破坏了在查看所有行时在两列之间检测到的关联规则。
与前面的维度一样,这种方法基于统计而不是布尔规则,可能会产生误报。计算这个维度也比其他维度更需要内存——尤其是在具有大量列的数据集上——因为在分析期间需要计算每对列之间的相关表并将其保存在内存中。
另一方面,启用这个维度可以检测出重要的问题,这些问题在一次查看一列时是看不到的。这是一个数据质量维度,在对所选数据集进行深入的数据质量分析时,您可能希望启用该维度,对于大型数据发现作业,最好禁用该维度,因为在这种情况下,保持作业速度很重要。
摘要
我们已经看到,并非所有的数据质量维度都同样昂贵。有些相当简单,不会使分析慢很多。有些需要多次通过数据,可能会使分析时间加倍,但可能有助于识别不明显的问题。不同的场景可能需要启用不同类型的维度。
我们还看到了每个标准数据质量维度的一些细节。
最后,我们看到可以通过使用数据规则来添加定制的数据质量维度。
Information Analyzer 还允许您通过在 Java 中实现数据质量维度来编程和部署自己的数据质量维度。在当前版本(撰写本文时为 3.5 版本)中,Cloud Pak 尚不支持此功能。但也许这是一个扩展点,将来会被移植到 Cloud Pak 以获取数据…
您认为应该在标准维度列表中添加什么新的数据质量维度?给这篇文章添加一些评论,让我知道。
日常分析的数据质量
入门
什么是数据质量,为什么它很重要,以及如何正确处理!

我们不信任的数据!
不久前,我的一个朋友提交了一份令人信服的分析,说服了一家中型公司的经理根据新成立的数据科学团队的建议做出了一系列决策。然而,不久之后,百万美元的损失揭示了这些见解是错误的。进一步的调查表明,虽然分析是合理的,但使用的数据是错误的。
对于我的朋友来说,意识到数据而不是分析方法是个问题是一种解脱。然而,该报告导致对他能力的负面看法,并损害了他的声誉;他花了一段时间才恢复过来。
我朋友的故事可以发生在任何使用数据的人身上。对最先进的工具和技术、我们想要产生的影响感到兴奋,或者有时被截止日期赶得很急,我们可能会忽略在任何分析之前的基本步骤:评估数据质量。否则,无论多么先进的方法学坏数据肯定会浪费时间和资源以及错误和误导的结果。数据分析和预测模型是垃圾进,垃圾出的真实体现!用托马斯·莱德曼的话说,
如果你的数据不好,你的机器学习工具就没用了。
坏数据的产生有许多原因:ETL 过程中的错误、手动输入、数据集成、专业知识的丧失、不断变化的业务逻辑和遗留数据都可能导致数据质量问题。
无论 ETL 过程多么严格,它仍然不能捕捉所有的数据问题。一个原因是,只有使用数据时,才能发现许多类似不准确的问题。因此,很少有数据科学家(如果有的话)能够幸运地从一个干净现成的数据集开始分析。数据集通常充满了需要修复的错误和不一致。因此,虽然评估数据质量不像训练机器学习模型那样有趣,但它是任何分析中最关键的部分。
因此,任何数据用户都需要对数据可能发生的各种问题有一个基本的了解,并具备检测、解决和交流这些问题的工具和技术。这就是为什么评估数据是完整的、独特的、及时的、一致的、有效的和准确的应该是任何分析的先决条件。
在这里,我将介绍数据质量背后的基本概念,讨论坏数据的成本,回顾数据质量评估的六个方面,并介绍可用于处理出现的质量问题的工具和技术。
什么是数据质量?
数据质量是对数据的有用性和可靠性的评估。为了更清楚起见,请考虑以下场景:
- 当数据集不包括最新记录时。
 - 当从两个不同来源读取的收入数字不匹配时!
 - 当一个数据集有许多同一个国家的名称,如“美国”、“美国”、“美利坚合众国”……加上所有的错别字。
 - 当数据集缺少值时。
 
在上面的第一个例子中,数据不是及时的(最新的)。在第二种情况下,数据不一致,在第三和第四种情况下,数据分别无效和不完整。我们将很快在数据质量的背景下回到这些概念。
坏数据的代价
使用坏数据的后果远不止是一些不完整的行或不一致的记录。简单来说,
当数据有任何缺陷时,完成一项工作的成本是数据完美时的 10 倍。
Ringlead 根据数据记录的数量可视化坏数据的成本。根据这一估计,不良记录的成本约为 100 美元:10 万条不良记录每年要花费 200 万美元,这还不包括添加到数据中的新记录。对于像 Google 这样拥有大量数据的组织来说,这些数字要高得多。

图表中的来源 1 和 3 分别来自 Sirius Decisions——不良数据对需求创造的影响和小企业协会 2013 年人口普查。
IBM 的另一项研究估计,在美国,每年坏数据的成本约为 3.1 万亿美元!托马斯·莱德曼解释了原因:
另一个令人瞠目结舌的数字来自 Gartner:数据质量差是 40%的业务计划失败的原因,它还会影响多达 20%的劳动生产率。
谁对数据质量负责?
通过定义角色、流程和技术来支持数据质量,提供数据生态系统的整体视图是整个组织的责任。然而,数字显示,这些组织在这方面做得并不出色!据 Experian称,29%的组织数据不准确,同时 95%的企业难以实施数据治理计划。同一份报告指出,75%的受访者认为数据质量检查是业务用户的责任,而不是 IT 基础设施的责任。因此,如果您认为您可以信任现有的检查,并且评估数据质量不是您的责任,请三思!
问题的另一方面是,在创建或存储数据时,并不是所有的问题都能被检测到。数据生命周期中的两个重要时刻是数据被创建和消费的时刻。虽然数据在创建时就应该是固定的,但是在使用之前不会对其进行评估。这就是为什么分析师作为数据的消费者,在检测和解决缺陷方面发挥着重要作用。
因此,我认为数据质量评估是每个人的工作;鼓励数据用户利用其技术专长和领域知识来发现不一致之处,并确保分析基于通过质量控制措施的可靠来源。
质量数据的六个维度
到目前为止,我们回顾了数据质量评估的重要性,并量化了坏数据的成本。我们强调了分析师或一般来说数据用户在确保数据在被消费之前符合标准方面的关键作用。在本节中,我们将介绍数据应该满足的要求。
为了评估数据集的质量,需要从 6 个方面进行评估:
- 质量数据是完整的
数据的完整性意味着分析所需的主要特征/属性没有缺失值。缺失值会扭曲分析并导致误导趋势。 - 质量数据是唯一的 重复会产生不利影响。它们占用存储空间,延长代码的运行时间,并扭曲分析。检查的唯一性保证了数据中每个观察只有一条记录。
 - 高质量的数据是及时的 地址、电话号码、电子邮件和信用卡都在不断变化,因此,上个月有效的数据记录现在可能不再有用。及时性确保数据是最新的,最新的记录反映了最新的变化。
 - 质量数据是一致的
一致是指一个数据集内或不同数据集之间没有矛盾。一个 5 英尺高的新生儿或销售和使用表之间的收入不匹配都是数据不一致的例子。 - 质量数据是有效的
有效的意味着数据具有正确的类型、格式和范围。如果数据符合一组预定义的标准和定义,则数据具有正确的类型和格式:当标准格式定义为 YYYY/mm/dd 时,08–12–2019 无效。同时,有效性保证数据在可接受的范围内。离群值是统计学和数据科学中的一个重要概念,是不符合这一要求的数据点。 - 质量数据准确
准确反映数据的正确性,如正确的出生日期和准确的售出数量等。你应该注意到准确性不同于有效性:后者侧重于类型、格式和范围,而前者旨在形式和内容。如中所述,数据质量;准确性维度,准确性是关于正确性,而有效性是关于可能的准确值:对于一个 50k 工资的员工,45K 工资是不准确的,但是有效的(在可接受的范围内)。 
在继续之前,我们应该注意,用真实数据满足 100%的数据质量要求几乎是不可能的。一种解决方法是为我们上面定义的每个维度定义一个阈值,低于该阈值的数据被评估为质量差。例如,只有当 10%的数据丢失时,90%的完整性才允许使用数据。在某种程度上,门槛取决于业务环境。阈值越高,用例的数据质量就越高。
利用分析技术评估和提高数据质量
在这一节中,我们将介绍一些工具和技术,分析师可以使用这些工具和技术来检查和提高他们的数据质量。本节中的示例在 SQL 中。
完整性 不完整的数据以缺失值的形式出现。衡量指标是分析所必需(非可选)的要素的缺失记录比率。例如,如果分析中 100 条记录中有 30 条缺少营销活动所需的行业特征,则数据的完整性为 70%。
首先,检查缺失值的数量:
*SELECT 
 1 — COUNT(col_A) / COUNT(*)
FROM
 table_name;*
或者,为了计算空单元的数量
*SELECT 
 COUNT(col_A)
FROM
 table_name
WHERE 
 col_A = ‘’;*
如果比率超出您可接受的阈值,您可能需要使用以下选项之一:
1.如果可能的话,使用其他数据来源:
当我在研究一个无监督的对外营销细分模型时,我需要知道该企业是否从事电子商务,特别是他们使用什么支付提供商。问题是这些记录中有 90%在数据库中丢失了。我们最终测试了来自多个提供商的数据集,并将其中一个与我们的数据合并。修复不完整记录的整个过程耗时约一个月。
2.插补
插补是机器学习中一种众所周知的方法,它从现有值中推断缺失值,例如用数据的均值、中值或众数替换缺失值。
*SELECT
 COALESCE(col_A, AVG(col_A))
FROM
 table_name;*
您也可以使用 IFNULL()。在 Python 中你可以使用 dropna()、fillna()、interpolate()等。有关更高级插补方法的概述,请查看数据插补和示例。
3.手动修复
手动处理丢失的数据是有风险的、不可伸缩的,不推荐使用,只有当有少量丢失的值并且您非常了解业务逻辑时,才可以使用它。
4.删除缺失值
只有当数据集很大且缺失值很少,从而不会影响分析时,才可以删除空值。
*SELECT
 *
FROM 
 table_A
WHERE
col_A IS NOT NULL;*
注意丢失信息和趋势,因为丢失了一些重要的记录(比如离群值)。
唯一性 统计包能够很好地处理重复值。要检查 SQL 中的重复值:
*SELECT
 col_A, 
 col_B, 
 col_C, 
 COUNT(*) AS cnt
FROM
 table_A
GROUP BY 
 col_A, col_B, col_C
HAVING cnt > 1;*
要删除重复项:
*SELECT
 col_A, 
 col_B, 
 col_C
FROM
 table_A
GROUP BY 
 col_A, col_B, col_C;*
其他消除重复的方法是使用 DISTINCT()、ROW_NUMBER()甚至自连接。在 Python 中,duplicated()告诉您重复值,drop_duplicates()负责删除它们。
及时性 数据分析师需要检查数据的时间线,以确保它是最新的!使用一个没有被更新的表或者一个已经被改变但没有反映在数据中的记录会导致不希望的结果。虽然没有特定的技术工具,但是检查数据的最后更新时间,或者表中的最小和最大日期应该会有所帮助。
*SELECT
 MIN(date), MAX(date)
FROM
 table_A;*
如果您的数据是分区的,您可以用 partition_date 替换上面的日期。
一致性
数据的不一致性可能发生在一个数据集内,也可能发生在数据集之间。编程语言使得相互检查数据集和检测不一致变得容易。最终,你将不得不使用你的商业判断,咨询领域专家或者将你的数据与可靠的来源进行比较。
作为个人经验,我研究了支付行业中被拒绝的交易,我必须解决来自两个不同组织的数据集之间的不一致。在缺乏唯一的真实来源的情况下,我最终研究了维护这些数据集的组织,并选择了拥有知名客户和更好声誉的组织。
有效期 1。异常值
均值和标准差等几个重要的统计数据对极值、异常值非常敏感。因此,数据分析师需要特别注意识别和处理它们:它们是合法的极值,还是由于测量工具的缺陷而被记录下来的。
从使用业务知识和可视化技术(如散点图或箱线图),或者使用分析技术(如基于密度的聚类和隔离森林),有无数种技术可以处理异常值。查看这篇文章进行评论。
箱线图是识别异常值的简单方法。箱线图通过绘制五个重要的数字来显示分布:分布的最小值、最大值、第 25 个百分位数、中间值和第 75 个百分位数。要查找数据中的异常值,请查看小于第 25 个百分点或大于第 75 个百分点 1.5 IQR(四分位间距)的区域,其中 IQR 是第 75 个百分点和第 25 个百分点之间的距离。

(图片鸣谢:了解方框图)
一般来说,不建议删除异常值,因为并非所有异常值都是相同的!为了区分合法数据点和非法数据点,有时前者被标记为异常。然而,大多数时间异常值和异常值可以互换使用。
2.类型和格式
对于数据中的每个属性/要素,检查格式和数据类型(日期、整数、字符串)以确保其符合标准。检查 SQL 中的数据类型
*SELECT COLUMN_NAME, DATA_TYPE 
FROM INFORMATION_SCHEMA.COLUMNS
WHERE 
 TABLE_NAME = table_A*
在 Python 中,您可以简单地使用
*df.dtypes*
其中 df 是你的熊猫数据帧。
浏览输出是快速检查数据值和格式的一种方式。在 SQL 中,您可以使用类似
*SELECT 
 col_A, 
 COUNT(*)
FROM 
 table_A
GROUP BY 
 col_A
ORDER BY 
 col_A ASC
LIMIT 100*
其中合并ORDER BY和LIMIT允许您检查可能错误的值中的错误。在 Python 中,value_counts()可以给你一些关于你的输入的想法。
准确性 使用领域知识以及将您的数据与另一个值得信赖的来源进行比对,可以获得数据的准确性。进行探索性分析,使用可视化和统计方法来识别没有意义的趋势和数字,并与领域专家进行讨论。
最后的话
在学术界,在将我们的文章提交给期刊进行同行评审之前,我们通常会等待一两周,然后再次评审稿件。这种滞后通常会导致工作质量的大幅提高:我们修正了以前没有注意到的错误,改进了可视化效果,使一些段落更加清晰,并重新审视了数据和计算。最终,从长远来看,它帮助我们建立了创建高质量工作的声誉,同时减少了审查过程所花费的时间,这反过来又导致论文更快地发表。
我们是自己作品的最佳评判者,比任何人都更能识别我们所创造的作品的缺点和优点。对数据质量的评估可能是交付高质量和有影响力的工作的最重要的一步,这有助于改善整体业务。我希望这篇短文有助于提高对我们的工具和技术的认识,以便在您的分析工作中使用,并使您的工作更有质量!
数据质量:垃圾输入垃圾输出
纠正错别字和诸如此类的问题是一个 45 亿美元的市场

来源:提莫·埃利奥特,经许可
几年前,我的第一份工作是为银行建立金融模型。那是在手工制作模型特征并由指导委员会批准的时候。深度学习前的日子。由于功能是手工制作的,广泛的数据质量检查是标准。我定期审计数据是如何从一个系统流向另一个系统的。我的前老板会说,垃圾进,垃圾出。
数据质量是个大问题。总是会有重复的、离群的、丢失的数据、损坏的文本或打字错误。但是,即使在数据工程和“人工智能”方面取得了多年的进步,数据质量仍然是一个大问题。事实上,这是一个日益严重的问题。但这也是为什么这是一个令人兴奋的问题。
和往常一样,我喜欢在我的文章开头写些无关紧要的内容:
- 这不是关于数据质量作为一个概念是什么以及如何解决的问题。已经有很棒的文章了:这里的,这里的,这里的
 - 这侧重于结构化的表格数据。图像/视频、音频、文本等数据类型的数据质量问题的性质各不相同
 
为什么数据质量是一个日益严重的问题
更多的决策是基于数据。Tableau 等 BI 工具、AppAnnie 等市场智能工具以及 Optimizely 等 A/B 测试工具的增长都指向了数据驱动决策的趋势。如果底层数据不可信,这些工具就没有用。如果数据质量问题不断出现,我们很快就会对这些工具失去信任。做出了错误的决定,失去了商业机会。Gartner 定期调查不良数据的成本,多年来,即使每年在数据质量工具上花费 20 万美元,每个企业的成本仍保持在 1000 万美元。
更多的公司建立在数据之上。一波又一波的机器学习公司都是建立在数据上的——看下图:)。如果你与机器学习工程师和数据科学家交谈过,你总是会听到好数据有多重要。

来源: CB Insights
为什么数据质量仍然是个问题
大量数据但静态的一次性检查仍是现状。云改变了思维模式,从只存储有用的数据转变为存储所有潜在有用的数据。Kafka 等流媒体技术和 Snowflake 等云数据仓库降低了存储更多数据的摩擦——以更高的速度、更广泛的种类和更大的容量。为了确保质量,指定范围和模式的数据规则由顾问或数据质量分析师手工编写。这是一个昂贵耗时的过程,通常只做一次。一劳永逸。这有两个问题。第一,大多数规则是在生产中学习的——当问题出现时。未知的未知情况。二是数据是动态的,要求规则是动态的。
“可信”的数据来源仍然存在问题。三个行业比其他任何行业都更重视数据质量:公共部门、医疗保健和金融服务。但这些行业继续受到不良数据的困扰。一家医疗保健公司的数据治理负责人告诉我,他们每月收到的政府数据错误百出。他们需要专门的员工来打扫。想象一下,我们正基于肮脏的数据被治理。在金融服务方面,来自一级数据提供商的股票数据经常会出现一些问题。众所周知,彭博的数据质量优于其他供应商,但我记得我不得不经常检查数据,并告诉客户支持人员这些数据没有意义。
数据专业人员的专业化。过去,数据专业人员更多地负责接收、转换、清理和分析/查询数据。现在我们有不同的专业人员处理每一步。数据工程师处理接收和转换。有时会跳过转换,直接将数据推入数据仓库。数据科学家建立模型,并忙于调整深度学习旋钮以提高准确性。和业务分析师查询并撰写报告。他们对数据应该是什么样子有更多的了解,但与编写和实现数据质量检查的数据工程师是分开的。
Tldr:一个日益严重的问题,却没有很好的解决方案
巨大的机会待价而沽
当前的数据质量软件市场差不多有 20 亿美元。但真正的机会要大得多,为 45 亿美元,因为有大量的劳动力可以自动化。美国有 2.1 万个数据质量职位,每个职位的年薪为 8 万美元。这并不包括那些在职称为“顾问”的专业服务公司工作的人。假设直接人工部分乘以 1.5 倍,总人工部分为 25 亿美元。随着数据质量在 ML 应用和业务决策中变得越来越重要,市场将继续健康增长。
虽然 Informatica、SAP、Experian、Syncsort 和 Talend 目前主导着市场,但新一波创业公司正在崛起。当前的产品及其销售方式可以更好——从插入数据管道任何部分的交钥匙解决方案,到不需要 6 个月的实施期和 6 位数的前期承诺,到自动化数据质量规则编写和监控。
数据质量对数据集的影响
我们着眼于影响数据集维度的数据质量的不同方面,以及数据质量在产生数据的组织中的重要性。

在 Unsplash 上由 Carlos Muza 拍摄的照片
背景
去年,我在机器学习领域的介绍一直专注于学习如何解决给定数据集上的回归或分类问题。
当我们开始处理真实的用例时,我们发现我们收到的数据集是一个组织的结果,该组织开发了一项工作,能够对其进行阐述。
该数据集的质量与制造该数据集的组织以及该组织如何处理数据质量直接相关。
我们模型的可持续性也可能与组织中的数据质量有关。
除了数据工程、模型本身的准确性及其生产中的性能之外,如果它所服务的组织没有将数据质量作为优先事项,很可能该模型将无法长期持续。
那么,什么是数据质量呢?
首先,数据代表真实世界的对象,为了在本文中讨论数据质量,我们将研究数据集格式。每一列都是数据集的一个“数据集”,每个单元格都是数据集为一行获取的特定值。
通常,当我们考虑数据质量时,我们会考虑数据的价值及其准确性。然而,数据质量包含多个方面,这些方面被称为维度,我们将在后面更详细地讨论,但它们是数据的常见维度:准确性、唯一性、完整性、有效性和一致性。
数据质量最常见的定义是确定数据是否能够满足收集数据的功能。
重要性和益处
保持数据质量是一项困难但必要的任务。为了获得一致和可靠的数据,企业必须不断管理数据质量,以便建立信任并做出更快、更明智的决策。
数据质量差会对组织的效力和效率产生直接影响,特别是在任务的整个生命周期,数据不同方面的错误会导致财务损失或严重错误。
相比之下,致力于提高所收集和生成的数据质量的组织会在不同层面受益:
- 避免不完整或重复的信息。
 - 节省通信和服务质量
 - 节省了非质量数据的成本,从而导致数据质量的成本自付
 - 显著提高未来模型或组织决策的结果和输入的质量
 
数据质量的重要性毋庸置疑;错误和好处的影响的严重程度因用例而异,因此如果不将它们直接应用到示例中,很难从概念上涵盖这些概念
数据集中的错误类型
为了开发此案例研究文章的内容以帮助我们确认这些概念,我们将使用众所周知的 Kaggle 数据集进行学习:【Kaggle Learn 用户的房价竞争


信息不完整导致的错误
它们可以引用数据中缺失的单元格(例如,Alley 字段仅包含 1460 条记录中的 91 条,或者更糟,包含“PoolQC”字段)。这些是著名的“null”或“NaN”字段。

但它们也可能是由于遗漏了一些可能与研究相关的数据而产生的错误。
具体来说,对于预测销售价格的练习,如果在设计的数据集中省略了“Neighborhood”或“LotArea”列,预测的质量将会受到很大影响。

使用 missingno 的空值可视化

关于缺失值位置的相关矩阵
语法错误
语法错误与数据的格式及其值的表示方式有关。例如,在 YearBuilt 字段中,我们找不到低于 1700 年或高于当前年份(2020 年)的值。
另一方面,街道数据可以支持以下值:
Grvl—Gravel
Pave—Paved
如果我们发现不同于这些值且不同于 null 的值,我们将面临语法错误。

如果日期字段的格式应该是 MM-DD-YYYY,而有些单元格是 YYYY-MM-DD 或 DD/MM/YYYY,那么我们也面临着语法错误。
由于这是一个用于教育的数据集,因此很难在数据中找到语法错误。不过,我们可以寻找异常值,例如,GrLivArea 列,它是出现在最后一个五分位数中的数据,可能是错误输入的数据。

语义错误
语义传达数据的含义。
如果我们在生产年份中输入销售年份,我们将从语法(一个有效的年份)的角度得到正确的数据,但从语义的角度来看却不是这样。

没有建造时间超过 10 年的房子
但是,如果我们查看装修年份,数据应该表明在建造后和出售前是否有改造。但是我们发现了一行重建的年份是在出售之后:

yearremodaddd:改造日期(如果没有改造或增加,则与施工日期相同)
在这种情况下,我们面临一个语法和语义上的错误:
- 如果没有改造,它是句法上的,因为根据定义,如果没有改造,年份必须等于建造年份
 - 如果改造是 2008 年,这是一个语义错误,因为它不代表在建设和销售期间的改造。
 
一个明显的语义错误是,数据“销售价格”包含土地面积(数据输入错误),或者销售价格对应于部分商业交易,例如,部分土地销售。
数据质量维度
在本文的开始,我们提到了质量的一些维度:准确性、唯一性、完整性、有效性、一致性。
一个维度是一组目的相同的质量因素;准确性作为一个维度由语义准确性(值与现实的接近程度)、句法和精确度(数据的适当规模)等组成。
一个度量是我们用来度量维度的一个因素的机制,例如,LotArea 数据的维度准确性中的语义正确性,我们将用实际值和输入到数据集的值之间的平方英尺差来度量它。
测量是实施度量以获得尺寸系数值的过程。在地块面积数据的相同示例中,尺寸准确度、精度因子、“平方英尺的差异”度量可以由专业人员测量,由评估人员使用诸如 GoogleMaps 等计算机工具进行估计。

琳达·佩雷斯·约翰森在 Unsplash 上拍摄的照片
随着时间的推移,度量过程会发生变化,或者根据问题类型的特征,应用于一个维度的相同度量可以用不同的方法进行度量,甚至可以作为验证或改进度量的方法。
维度因素可以与其值(例如准确性)以及其意图和方案(例如句法和语义正确性)相关。
数据质量的主要方面
定义对应于和应用于我们数据集的每个数据的维度的名称和方法可以根据上下文以及分析和定义它们的理论和概念框架而变化。
准确(性)
数据值 v 和数据值 v '之间的接近度,被认为是 v 试图表示的真实世界现象的正确表示。
语义正确性:属性的值 v 与其真实值v’的接近度。
如果我们有代表土地面积和单元面积的 LotArea 数据,但如果交易价格被错误地登记在这里,我们将有一个非常微弱的修正(除非价格和面积数据碰巧相似!).
另一方面,如果土地的平方英尺被输入到数据中,语义校正是强有力的。
语法正确性:表示一个属性的值 v 与该属性定义域的元素之间的接近程度。如果 YrSold 数据表示今天之后或数据集记录开始之前的年销售额,则不能包括在内。
准确性:捕捉数据的详细程度,使其对特定用途有用,或者使其能够与其他不同的数据区分开来。
如果地块面积数据是以公顷为单位,没有小数,那么在城市数据集中进行估计就不方便了。
如果你想测量生产过程的时间并且你没有存储“小时、分钟、秒”;如果只保存开始和结束日期,您将无法访问小时、分钟和秒的计算。
一致性
它捕获对定义在一组业务实体或其属性上的语义规则的违反。在关系模型中,完整性约束是这种语义规则的一个例子。
实体间完整性:它捕获不同业务实体的属性之间的规则满足度。也称为参照完整性,是指一个实体的属性与其他实体的一致性。
例如,在配方的项目列表中,产品代码与“产品”实体相关,如果配方中有不存在产品代码的项目,或者该项目已从产品实体中删除,则违反了该规则。
实体内完整性:捕获同一实体的属性之间的规则满足度。也称为关系完整性,指的是实体内部的完整性。
例如,一个带有区域的地址属于州。
或者在配方示例中,项目来自另一个配方或者一个程序不适用于一件事(例如,搅拌面粉)。
域完整性:捕获关于属性可能取值的规则的满足度
域完整性违规的例子是,如果输入表单上允许的身份文档类型可以是护照或 DNI,并且正在注册公民凭证。
完全
捕获关于属性可能取值的规则的满足度
覆盖率:获取给定数据集合中的实体数量与该集合中应存在的实体总数的比率。
覆盖测量可以在封闭域或开放域上进行。
覆盖率是领域中被覆盖的项目占总项目的比例。
密度:获取具有非零值的属性实例的数量与该属性实例总数的比率
密度比率将取决于关于某个数据的空值的假设标准。
独特性
它捕捉了真实世界数据的独特表现程度。
不重复:捕捉相同数据的重复程度。它是指一个元组在表示同一实体的数据集中重复的可能性。
在住房数据集的情况下,每个元组代表一个事务,因此唯一性的定义不是通过让两个元组引用同一个属性来给出的,而是对同一个属性的同一个事务。
例如,在俱乐部名单中,重复的情况是两行代表同一个人。
不矛盾:捕捉用矛盾数据表示的真实世界实体的相同实例的复制(或重复)程度。
例如,它是指一个俱乐部的会员资格,该会员资格有两个具有相似标识符的元组(例如,DNI 1971 449–3 和 1971 449–8),这两个元组指的是具有相似姓名但不同地址或矛盾数据(不同性别)的人。
及时
捕捉现实世界的变化反映在更新数据中的速度
新鲜度是一种依赖于时间变量的非结构性准确性,这意味着在一个时间正确的数据在另一个时间可能不正确。
现状:捕捉真实世界的变化和相应的数据更新之间的时间延迟。
如果年龄以其数值表示,而不涉及出生日期,则系统地呈现出现实问题。
这同样适用于对活生物体的任何测量。
数据的性质可能存在一些外部变化;例如,电话公司决定从 3 月 1 日起给该地区的所有电话添加前缀。如果没有更新应用于数据,它会在当天自动过期。
及时性:捕捉数据更新和可供使用之间的延迟。
例如,如果我们进行一项关于去年销售演变的研究,而会议推迟了六个月,我们将不可避免地面临一个数据有效性的机会问题。
在组织里做什么?

照片由马克西米利安·魏斯贝克尔在 Unsplash 拍摄
数据治理
公司业务流程交付的大量数据是一种信息来源,可以通过用定量、可靠和及时的元素支持决策制定来帮助产生价值。这种使用数据生成相关信息的需求需要建立一套定义、规则和流程来规范如何处理数据,这一套被称为数据治理。⁴
数据治理影响组织的不同方面,如结构、规则、决策、职责和数据管理的整个操作。
因此,组织数据治理计划旨在改进上述部分或全部方面。
通常,我们使用以下框架之一:
- DMBOK——数据管理知识手册。它提供了定义、实现和操作数据管理和使用的具体细节。⁵
 - TOGAF——开放组架构框架。定义创建作为企业整体架构一部分的数据架构的过程。它可能是实现数据管理的先驱。⁶
 - 信息和相关技术的控制目标。它将数据治理作为信息技术领域整体治理的一部分。它有一个模型来确定组织中使用的数据管理流程的成熟度。⁷
 - DGI 数据治理框架。这是一个生成数据治理的简单参考框架。它提供了一个逻辑结构来分类、组织和交流复杂的决策活动以及与企业数据相关的操作的执行。⁸
 
六西格玛方法
应用的方法称为 DMAIC(定义、测量、分析、改进、控制),使用统计工具以及观察过程变量及其关系的设备,这有助于管理它们的特性。
简而言之,它是一种基于数据的方法,将质量提升到近乎完美的水平,与其他方法不同,因为它还能在问题发生之前就加以纠正。更具体地说,这是一项检查公司重复流程的训练有素的工作。⁹
欧洲委员会
摘要
我们试图开发一些与数据质量相关的定义,以在人工智能、机器学习或数据科学家爱好者中引入这一概念。
在专注于这些学科的不同课程和教程中,我们很少考虑数据集的来源以及交付数据集的组织为生成数据集所做的工作。
当我们处理现实生活中的用例以及必须用新信息进行反馈和再培训的模型时,我们会发现组织的数据质量水平可能会使我们的工作长期失败。
在将工作投入生产之前,我们必须关注所有这些因素,并帮助组织进行改进。
参考
[1]https://www . edq . com/glossary/data-quality-importance/
[2]T2]https://www . kag gle . com/c/home-data-for-ml-course/overview
[3]T4]https://www . gub . uy/agency-government-electronic-society-information-knowledge/sites/agency-government-electronic-society-information-knowledge/files/documents/publications/framework % 20 对于% 20% 20% 20 处理% C3 % B3 n % 20% 20% 20 质量% 20% 20 数据%20v1.0.pdf
[4]https://ms office . WordPress . com/2017/01/11/数据治理/
[5]https://www . dama . org/content/body-knowledge
[6]http://www . open group . org/subject areas/enterprise/toaf
[7]http://www . isaca . org/cobit/pages/default . aspx
[8]http://www . data governance . com/the-dgi 框架/
[9]http://trilenew . bloggespot . com/2015/03/6-sigma . html
资料来源
日积月累:https://www . gub . uy/agency-government-electronic-society-information-knowledge/sites/agency-government-electronic-society-information-knowledge/files/documents/publications/framework % 20 for % 20% 20 处理% C3 % B3 % n % 20% 20% 20 质量% 20% 20 数据%20v1.0.pdf
益百利:https://www.edq.com/glossary/data-quality-importance/
http://sigma-data.com/que-es-la-calidad-de-datos/适马
CPE —数据质量和机器学习课程
数据质量——你衡量它的方式是错误的
还有一个更好的方法

奥利维尔·勒莫阿尔
我们的一位客户最近提出了这个问题:
“我想为我们自己(数据团队)建立一个关于数据可用性的 OKR。我想建立一个单一的关键绩效指标,将总结可用性,新鲜度,质量。
做这件事的最好方法是什么?"

我无法告诉你这个请求给我带来了多少快乐。作为一个痴迷于数据可用性的人——是的,你没看错:这些天来,我不再梦见绵羊,而是梦见空值和数据新鲜度——这是一个梦想成真。
这有什么关系?
如果你从事数据行业,你要么正在从事一个数据质量项目,要么刚刚完成一个项目。这是坏数据的法则——坏数据总是越来越多。
测量数据质量的传统方法通常是时间和资源密集型的,跨越几个变量,从准确性(一个显而易见的问题)和完整性,到有效性和及时性(在数据中,没有时髦的迟到这回事)。但是好消息是有更好的方法来处理数据质量。
数据停机时间 —数据不完整、错误、丢失或不准确的时间段——对于任何努力实现数据驱动的公司来说都是一个重要的衡量指标。这听起来可能是陈词滥调,但这是真的——我们努力收集、跟踪和使用数据,但我们经常不知道数据是否准确。事实上,公司经常以拥有优秀的数据管道,但是糟糕的数据而告终。那么,如果在一天结束时,我们不能实际使用数据,那么建立一个奇特的数据架构的所有这些努力又有什么价值呢?
通过测量数据停机时间,这个简单的公式将帮助您确定数据的可靠性,让您有信心使用它或失去它。
所以你想要它的 KPI?
总的来说,数据停机时间是一个函数:
- 数据事件数量(N) —鉴于您依赖于团队“外部”的数据源,这一因素并不总是在您的控制之下,但它无疑是数据正常运行时间的驱动因素。
 - 检测时间(TTD) —在发生事故时,您能多快得到警报?在极端情况下,如果没有合适的检测方法,这个数量可以在几个月内测量出来。错误数据造成的无声错误会导致代价高昂的决策,对您的公司和客户都有影响。
 - 解决时间(TTR) —在一个已知事件发生后,您能多快解决它?
 
通过这种方法,数据事故指的是数据产品(例如,旁观者报告)是“不正确的”的情况,这可能是许多根本原因的结果,包括:
- 全部/部分数据不够新
 - 全部/部分数据丢失/重复
 - 某些字段缺失/不正确
 
下面是一些 不是 数据事件的例子:
- 不会“破坏”任何下游数据的计划中的模式更改
 - 由于有意更改数据系统而停止更新的表(弃用)
 
综上所述,我建议针对数据停机时间的正确 KPI 是:
数据停机时间=数据事故数量 x
(检测时间+解析时间)
(如果您想进一步了解这个 KPI,您还可以按严重程度对事件进行分类,并按严重程度对正常运行时间进行加权,但是为了简单起见,我们将把它留到以后的文章中。)
通过自动化、高级检测和无缝解决的正确结合,您可以通过减少 TTD 和 TTR 来最大限度地减少数据停机时间。甚至有减少 N 的方法,我们将在未来的帖子中讨论(剧透:这是关于获得正确的可见性以首先防止数据事件)。
测量数据停机时间是了解其质量的第一步,并由此确保其可靠性。随着花哨的算法和业务指标满天飞,我们如何衡量这一点很容易变得过于复杂。有时候,最简单的方法就是最好的方法。
如果你想了解更多, 伸出手去巴尔摩西 。
有兴趣加入数据可靠性运动吗?把手伸向 蒙特卡洛团队 !

数据真实性:模型出错的地方
他们经常说,从原型到生产的这一步是许多数据科学梦想的丧钟。
其原因通常归结为三个主要因素:
- 该模型不能足够快地推断,不能足够大规模地扩展,或者硬件成本太昂贵
 - 现实生活中的表现与开发评估不同
 - 数据不可用
 
那么,我这么说是什么意思?

我们将逐一介绍:
模型速度
有时候,我们可以得到一个模型,虽然它在测试中表现很好,但不能扩大到生产。如果你的模型在 48 小时前预测飓风是 100%准确的,那么如果要花 49 小时才能做出预测,那么它就没有任何用处。
这可能会受到硬件成本等因素的影响。额外复杂性的成本(或简单的 IT 成本)需要被模型给你的收益所抵消。
你还可以发现,花时间采用算法并部署它意味着它已经过时了。一个著名的例子是网飞的 100 万美元算法奖。尽管新算法给出了期望的精度,但当它被部署时,它不再是正确的解决方案。
现实生活中的表现
这可能发生在开发中的模型已经“错过了一个技巧”。通常,这可以追溯到用于开发和培训的数据不代表真实世界。
我见过这样的案例,一家公司开发了一种业务“模拟”来生成机器学习数据,另一家公司强迫所有员工填写一份调查,为“购买可能性”模型收集数据。正如您所料,这两种情况都以数据与现实生活毫无关联而告终,必须启动适当的数据要求和收集程序,以便设计和训练新的适当算法。
数据可用性
这是一个奇怪的问题,也是一个经常被忽略但通过一些准备工作很容易避免的问题,所以我将重点讨论它。
我发现许多人在没有打好基础的情况下就匆忙设计和训练模型。至于前几个问题,你需要做一些准备工作,确定你想要实现什么,成功是什么样的,以及如何利用它(又名。需求收集)可以大大降低您的风险。
这里发生的情况是,当部署模型时,所使用的数据在生产环境中实际上是不可用的。当自定义数据收集已经开始,但没有维护持续的收集方法时,您会经常看到这种情况。
例如,零食自动售货机支持机器学习。它可以告诉你每天需要多少库存,这样你就可以规划整个网络的物流和补给时间表。然而,该模型的一个关键组成部分是它知道它错过了多少客户。现在,虽然在收集过程中,他们会派人监控现有的机器,看看有多少人想使用它,但在现实生活中,机器无法知道是否有人想使用它,当他们看到它是空的时,就会走过去。在真实列表部署中,随着时间的推移,自动售货机会要求越来越少的库存。但这是为什么呢?
发生的情况是,因为错过的客户不能被记录,模型总是被告知错过的需求总是零。这意味着该模型永远不会增加其股票来补偿,但会随着时间的推移慢慢减少其股票。这在逻辑上是有意义的,因为他们可以卖出他们的股票,这将是一个完美的预测,因为它没有“错过销售”。
我们都知道正在发生的事情是它错过了它们,只是它没有意识到,但因为它是一个关键变量,所以它在运行中导致了故障。
如果事先想一想,这本来是可以避免的。通过映射您的模型需要什么数据,并回溯到它是如何收集的,您可以确定没有收集它的机制。这样,数据科学家就有时间:
- 请求安装合适的传感器
 - 从他们的培训中删除该功能
 
在训练模型时,他们可以通过模拟设备传感器来运行数据,以在部署过程中将其转换为预期的信号。这将会导致以后更少的尴尬和更好的模型。

汤姆·普姆福德在 Unsplash 上的照片
如果你仔细想想,这个案例实际上涵盖了我之前给出的所有要点。有趣的是…
总结
在这篇文章中,我很快列出了一些我在恢复失败的机器学习项目时看到的主要陷阱。
几乎所有这些失败都是由于开始“数据科学之旅”的渴望,但没有足够的关注来制定任务的要求。
俗话说得好:
数据相关项目苦苦挣扎?

通用条形图的详细图像。图片来源:“Via Design Pickle”——更多关于属性。
如果你有一个数据相关的项目停滞不前或举步维艰,考虑一下角色混淆是否是问题的一部分。
介绍
H 您是否有过一个困难的数据相关项目陷入停滞的经历?数据相关项目成功的一个常见障碍是角色混淆。角色混乱是指团队中的任何一个或多个人不确定项目需要他们自己做什么。
VentureBeat.comT4 报道称“87%的数据科学项目从未投入生产。”本文中的建议可以帮助您的项目避免这种命运。
当计划(或保存一个挣扎中的)数据相关项目时,考虑是否有一个或多个特定的人拥有以下角色(注意一些人可以“拥有”多个角色)。一般来说,每个角色至少需要一个人。本文将确定并解释每个角色。
1)申请人
这就是提问的人。这个人并不总是专业技术人员。可以是内部的(人力资源总监、设施总监、前台接待员)或外部的(印刷或广播媒体是常见的)。
2)主题专家
这个人是主题专家。SME 在确保问题是重要的质量问题方面发挥着重要作用。换句话说,中小企业有责任停止这个过程,直到每个人都完全相信手头的问题是正确的问题。申请人通常也是中小型企业,但并不总是如此。如果申请人对该主题不熟悉,该项目将受益于 SME 的加入。
3)观众
或者是你的观众的代理人。有时整个观众就是一个人。观众需要问题的答案,以便做好自己的工作,或者做得更好。如果你有很多观众,带上一名观众代表。
4)数据管家
数据管理员对于数据就像图书管理员对于书籍一样。管家有或者知道在哪里可以找到数据。数据管理员通常能够提供关于数据的重要信息(例如,特定数据列的含义、计算方式、收集数据的原因等)。).
5)数据分析师或技术人员
此人将对数据选择提出建议,此人还将对方法选择提出建议。通常这个人也会执行分析并产生原始输出。
数据驱动的团队动态
原始输出将由整个团队进行解释,以确定请求者的答案是什么。拥有一个团队的价值和好处是,当需要解释结果的时候,团队可以一起做出贡献。让团队中的任何一个成员来解释都是错误的。
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
adamrossnelson.medium.com](https://adamrossnelson.medium.com/membership)
结论
本文认为角色混淆是一个障碍,在处理与数据相关的项目时,它会阻碍团队的生产力。角色混乱是指团队中的任何一个或多个人不确定他们在项目中扮演什么角色。

成功的面向团队的数据相关工作通常需要的五种角色。来源:作者插图。
规划(或保存)数据相关项目时,考虑如何通过确保至少有一个特定的人负责 1)请求数据,2)主题专业知识,3)了解受众,4)提供或查找数据,以及 5)方法选择、数据分析和分析执行,来防止(或解决)角色混淆。
重要的是,整个团队在解释和传播结果方面都有自己的角色和贡献。
感谢阅读
如果你喜欢我要说的话,可以在:adamrossnelson.medium.com找到更多。
感谢阅读。把你的想法和主意发给我。你可以写信只是为了说声嗨。如果你真的需要告诉我是怎么错的,我期待着尽快和你聊天。推特:@ adamrossnelson| LinkedIn:亚当·罗斯·纳尔逊 |脸书:亚当·罗斯·纳尔逊。
数据报告与分析
通往快速数据驱动型组织的道路

“我需要更多的报告”——照片由乔治·托马塞蒂在 Unsplash 上拍摄
在竞争激烈的世界中,人们越来越需要数据来做出决策。在成熟的公司中,这可以通过财务报告、会计报告、市场报告和许多其他报告的可用性来证明。
然而,在数据分析环境中,“报告”和“分析”之间有一个显著的差异。
了解这种差异将使组织能够:
- 更多准确的信息
 - 越来越快和周转时间
 - 更多有影响力的商业决策
 
那么,有什么区别呢?
“报告”是指为决策提供信息的数据。典型的报告请求通常意味着对信息的可重复访问,可以是每月、每周、每天,甚至是实时的。
上述定义依赖于两个主要的有缺陷的假设:
- 数据可用:数据通常需要来自不同的源系统,这些系统通常分散在公司内部或外部
 - 数据是干净的:通常数据需要被翻译以供人们使用,并且需要被整形以支持分析
 
“分析”是指原始数据分析。典型的分析请求通常意味着一次性的数据调查。
哪个先来?报告或分析
当报告请求流过时,通常需要执行分析。当分析请求流过时,可能不需要报告。
以下是构建报告的一些步骤:
- 了解业务需求
 - 连接并收集数据
 - 翻译技术数据
 - 从不同维度理解数据背景
 - 找到一种方法来显示 100 个类别及其 5 个子类别的数据(500+组合!)
 - 重新处理数据
 - 商业利益相关者感到困惑
 - 范围发生变化
 - 重复这些步骤
 - 更多返工
 - excel 上的初始可视化
 - 解决利益相关者的理解问题
 - 开始构建报告仪表板
 - 配置功能和参数
 - 更多返工
 - 测试用户体验
 - 符合公司风格指南
 - 测试报告自动化和部署
 - 联络技术或生产团队
 - 设置定期刷新和失败的流程
 - 文件报告流程
 
以上只是触及了最初的表面…
如果企业想要更少的数据点或更好的事实理解,分析将是更有效和高效的替代方案。
以下是数据分析探索中涉及的一些步骤:
- 创建数据假设
 - 收集和处理数据
 - 向企业展示成果
 - 重新迭代
 
企业只需很少的步骤就能获得结果。
通往快速数据驱动型组织的道路
理解“报告”和“分析”之间的区别很重要。在当前的竞争格局中,洞察速度至关重要。
基于以上的解释和步骤,从“分析”入手往往是最好的起点。如果这些见解需要定期广泛传播,那么可以编写一份报告。这也将减轻与常规自动化流程相关的技术操作负荷。
“如果你每年做的实验数量增加一倍,你的创造力也会增加一倍。”—杰夫·贝索斯
正如杰夫(亚马逊公司创始人)提到的,我们需要更多的“实验”和数据探索。我们不需要更多的报告。
如果您是业务分析师,请将请求从“报告”细化到数据分析。
如果你是数据分析师,建议与企业就杂乱的数据建立分析合作关系。
我们可以一起以快速和可持续的方式释放数据的真正商业价值。
如果你喜欢这篇文章,并想看更多的内容,请考虑加入媒体会员,使用下面的链接来支持我和其他作者:
[## 通过我的推荐链接加入 Medium-Albert Suryadi
阅读艾伯特·苏亚迪(以及媒体上成千上万的其他作家)的每一个故事。您的会员费直接支持…
albertsuryadi.medium.com](https://albertsuryadi.medium.com/membership)
关于作者:Albert sur yadi是蓝筹组织中实现高级分析和数据科学能力的公认领导者。他被公认为分析团队(实践社区)的领导者,该团队授权并激励他人超越现状。
几乎每种数据科学项目的数据存储库
针对每种类型问题的数据存储库的综合列表

来自 Unsplash
鉴于我的工作性质,我每周都要处理新项目,解决不同的问题。我的工作要求我解析大量不同种类的数据集,以便为数据科学爱好者设计和开发指导。
这个博客包含了一些有用的数据集和数据仓库,按照不同的问题和行业进行分类。
网络上的数据仓库:

谷歌数据集门户
- 谷歌数据集搜索——研究人员定位在线数据的搜索引擎。
 - datasetlist —提供网络上最大的机器学习数据集列表。
 - UCI —最古老的存储库之一,数据按照问题类型、属性类型、数据类型、研究领域等进行分类。
 - fastai-datasets —用于图像分类、 NLP 和图像定位的数据集
 - NLP-datasets —自然语言处理中使用的带有文本数据的自由/公共领域数据集的字母列表
 - Bifrost —用于按任务、应用、类、标签和格式分类的可视化数据集。
 
图像数据集

打开数据集图像
- ImageNet—ImageNet是一个按照 WordNet 层次结构(目前只有名词)组织起来的图像数据库,其中层次结构的每个节点都由成百上千的图像描述。
 - CT 医学图像 —设计用于测试不同的方法,以检查与使用对比剂和患者年龄相关的 CT 图像数据的趋势。这些数据由癌症影像档案中的一小部分图像组成。
 - Flickr-Faces—Flickr-Faces-HQ(FFHQ)是一个高质量的人脸图像数据集,最初是作为生成对抗网络(GAN)的基准而创建的。
 - object net——一种新的视觉数据集,借鉴了其他科学领域的控制思想。
 - 名人面孔 —大规模名人面孔属性
 - 动物面孔-HQ 数据集(AFHQ)-动物面孔数据集,由 15,000 张分辨率为 512×512 的高质量图像组成。
 
NLP 数据集

https://medium . com/@ ODSC/20-open-datasets-for-natural-language-processing-538 fbfaf8e 38
- nlp-datasets —自然语言处理(nlp)中使用的带有文本数据的自由/公共领域数据集的字母列表。
 - 1 万亿 n-grams —语言学数据联盟。该数据预期对统计语言建模有用,例如用于机器翻译或语音识别,以及用于其他用途。
 - litbank — LitBank 是一个包含 100 部英语小说作品的带注释的数据集,用于支持自然语言处理和计算人文学科的任务。
 - BookCorpus —这些是自己复制 BookCorpus 的脚本。
 - rasa-nlu-training-data —用于开发和测试 Rasa NLU 模型的众包培训数据。
 - Google book Ngram —这是一个在线搜索引擎,它使用 1500 年至 2019 年间在谷歌的英语、中文、法语、德语、希伯来语、意大利语、俄语或西班牙语文本语料库中印刷的来源中发现的 n 元语法的年度计数,绘制任何一组搜索字符串的频率。
 
情感分析

来自 Unsplash
- 评论— 亚马逊评论, Yelp 评论,电影评论,美食评论,推特航空,
 - 斯坦福情感树库 —这个数据集包含了来自烂番茄 HTML 文件的超过 10,000 条斯坦福数据。
 - 词典编纂器情感词典 — 词典编纂器对几乎任何语言的任何类型的文本进行简单的演绎内容分析。
 - 意见词库 —英文正反意见词或情感词列表。
 - 会话数据集—用于会话响应选择的大数据集集合。
 - 更多—NRC-情感-词库-词级, ISEAR(17K) , HappyDB ,情感到表情映射
 
声音的
Audioset —一个大规模数据集,由 632 个音频事件类的扩展本体和从 YouTube 视频中提取的 2,084,320 个人类标记的 10 秒声音剪辑组成。
金融与经济

来自 Unsplash
- Kaggle 金融数据集 —金融数据集是关于金钱和投资的。如果您需要测试一些新的加密货币投资策略或抵御那些讨厌的信用卡欺诈爱好者,那么您来对地方了。
 - CFPB 信用卡历史 —每月新开信用卡的数量和累计信用额度。
 - 顶级银行 —该数据集包含全球最大银行的列表。
 - 学生贷款债务 —学生贷款债务汇总数据的集合,包括按年龄、金额和债务类型划分的债务余额。
 - 国际货币基金组织,英国《金融时报》数据集,世界银行数据
 
卫生保健

来自 Unsplash
- ka ggle health care repository—医疗保健领域的人工智能正引起越来越多的关注。一个主要问题是如何将研究转化为应用。应该很容易吧?
 - 世卫组织:全球卫生数据集。
 - 疾病预防控制中心:把这个用于美国特有的公共卫生。
 - data.gov:以美国为中心的医疗保健数据,可通过多种不同因素进行搜索。
 
科学研究

来自 Unsplash
- re 3 data:re 3 data 拥有超过 2000 个研究数据存储库,已经成为全球研究数据基础设施最全面的参考来源。
 - 埃尔韦拉生物医学数据仓库:生物医学领域的高维数据集。它专注于期刊发表的数据(自然、科学和其他)。
 - 默克分子健康活动挑战:旨在通过模拟分子组合如何相互作用来促进药物发现的机器学习追求的数据集。
 - SEER —由美国政府提供的按人口统计组排列的数据集。您可以根据年龄、种族和性别进行搜索。
 - CT 癌症医学图像 —设计用于测试不同的方法,以检查与使用对比剂和患者年龄相关的 CT 图像数据的趋势。这些数据是癌症影像档案中图像的一小部分。
 
航空航天和国防

来自 Unsplash
- NASA 的数据门户 —一个持续增长的公开可用的 NASA 数据集、API、可视化等目录。包括空间科学、航空航天、地球科学、应用科学和管理数据。
 - 航空数据项目 —来自麻省理工学院全球航空业项目的商业航空数据集
 - 天文数据服务 —美国海军天文台(USNO)提供的各种天文数据。数据包括与太阳、月亮、行星和其他天体等相关的数据。
 - 天文年历的天文现象部分 —各种天文现象,包括太阳、月亮、地心和日心。日出、日落和黄昏的表格以及日食和月食的数据都是可用的
 - NASA 的小行星数据集 —提供对小行星、尘埃、行星卫星、陨石等 PDS 数据的访问。
 
电子商务
提供数据集的 Python 库

https://blog . tensor flow . org/2019/02/introducing-tensor flow-datasets . html
- TensorFlow 数据集 —一组现成的数据集。TensorFlow Datasets 是一个现成的数据集集合,可与 TensorFlow 或其他 Python ML 框架(如 Jax)一起使用。所有数据集都以
[tf.data.Datasets](https://www.tensorflow.org/api_docs/python/tf/data/Dataset)的形式公开,实现了易用、高性能的输入管道。要开始,请参见指南和我们的数据集列表。 - S️klearn —机器学习包。这个包还具有获取更大数据集的帮助器,这些数据集通常被机器学习社区用来对来自“真实世界”的数据进行算法基准测试。
 - ️️nltkt21】:自然语言工具包。自然语言处理中的实际工作通常使用大量的语言数据或语料库。
 - ️ statsmodel :统计模型包。提供数据集(即数据和元数据)用于示例、教程、模型测试等。
 - pydataset —主要用于教育目的的数据集。它试图帮助那些第一次接触 Python 数据科学的人,他们必须处理常见的(且耗时的)数据准备任务。
 - seaborn :数据可视化包,你也可以从在线存储库中加载一个示例数据集(需要互联网)。
 
如果有任何其他重要和真实的数据集或类别,你想让我添加到这个列表中,请随时回复这个故事!
SQL、R 和 Python 中的数据整形
关于长到宽和宽到长转换的有用指南
设想这样一个场景:您刚刚完成了一个 SQL 查询,为涉众生成了汇总统计数据,让我们以下面的表格为例,

长数据格式
这是一个纵向数据,跟踪每月和州的枪支许可证检查次数。原始数据是公开的,更多背景资料链接于此。所以你的项目是对枪支许可变化的时间序列分析,包括纵向跨时间和横向跨州。不难认识到,该分析需要转换数据,以便将月 或 状态 变量放置在列上,如下所示:

宽数据格式
这种数据整形过程被称为旋转(即,长/堆叠到宽/扩散),其逆过程是取消旋转(即,宽/扩散到长/堆叠)。将数据从一种格式转换为另一种格式是分析项目中最常见的数据操作步骤之一。因此,在这篇博客中,我们将探索如何有效地将数据从 long 转换为 wide(反之亦然),我们将使用 SQL、R 和 Python 来完成这一过程。
***更新 2022: 加入我们的 YouTube 社区🎦 【数据说话带吉】 😄
旋转:长到宽
SQL:
先说PIVOT()函数,Oracle 11g 和 MS server 2017 都有。为了方便访问,我还在这里的SQL fiddle playground中对它进行了编码,
在该查询中,允许列被指定为要分摊的值,而月列被指定为新透视表的标签。其他列(即玩具数据中的状态列)被隐式地视为GROUP BY变量。回报正是我们所期望的,

在这里,您一定注意到了我们查询中的聚合函数SUM()。该功能无法消除,因为旋转是一种侵略性操作,因为它将(可能的)多行合并成输出中的一行。
然而,在我们的例子中,由于每个月每个州只有一行,SUM()什么也不做,因此可以被其他 agg 替换。功能(如AVG())。相反,如果我们有多行(对于每个月的每个州)要聚合,这些函数将通过避免额外的子查询而派上用场。
现在,转到其他 SQL 数据库,例如 MySQL 或 PostgreSQL,其中PIVOT操作符不可用,下面显示了查询( SQL fiddle playground ),
与PIVOT操作符一样,聚合函数也是指定的,但是随着月份的增加,这个查询很容易变得冗长。假设我们有 100 个月的记录,而不是 4 个月,我们将不得不手动键入 100 列标签!这肯定不是最佳解决方案。
R—shape()&pivot _ wider():
R 中的数据帧本质上是矩阵,因此矩阵转置的公知思想是适用的。有很多 R 函数可以处理这个任务,我最喜欢的两个是包【stats】和【tidyr】中的reshape(direction = 'wide') 和pivot_wider() 。
请注意,pivot_wider()是spread()的更新功能,不再处于积极开发中(更多详细信息,请参见此处的)。
现在,下面的代码展示了如何使用pivot_wider()用 R 中的几行代码实现旋转。如果你也对reshape() 版本感兴趣,我在我的 Github 中有它的链接,
这里:[1]我们将 names_from 参数设置为跨列分布的变量(即 month 变量);[2]另一个有用的可选参数是 names_prefix ,它指定每个列名的前缀词(例如,month _ 2020–01–31)。
Python — pivot_table() :
同样,Python 中也有一个函数恰如其分地命名为pivot_table()
这里:[1]我们用 0 替换缺失值,将 permit 列转换为整数(与默认 float64 相反);[2]输出表的列被设置为类型字符串,以避免标签在 reset_index 之后被转换为日期时间(如 2020–01–31 00:00:00);[3]此函数有一个可选参数,可用于聚合多行(如‘sum’, ‘count’)。****
非旋转:从宽到长
现在让我们假设我们想要将宽数据转换回原始的长数据结构。在 SQL 中,除了我们用unpivot()替换了函数pivot()之外,查询几乎与旋转相同,并且 SQL 小提琴在这里链接,****
R—shape()&pivot _ longer():
对于这个演示,我们将再次关注来自 {tidyr} 的pivot_longer(),它的对等reshape(direction = 'long')版本可在我的 Github repo 中获得。与pivot_wider()的情况类似,pivot_longer() 是对原有gather()功能的更新,不再开发。
下面是我们如何将数据从宽数据转换回长数据,
在这段代码中, cols 参数接受要堆叠成更长格式的列,即我们数据中的月份变量。这一行colnames(wide_dat)[-1]将排除第一个变量状态。这是输出,它符合我们的原始数据格式,

一个问题是,如果聚合了多行,那么取消投票不会产生原始的表值。
Python — melt():
熊猫 也有,函数melt()执行宽到长的转换,
与 R 输出一样,这段代码的返回与我们的原始数据完全匹配。
想要更多数据科学和编程技巧?使用 我的链接 注册 Medium,获得我所有内容的全部访问权限。
最后的想法
正如我们刚刚了解到的,SQL 作为一种查询语言,在用于数据整形时会变得繁琐冗长。与 SQL 表不同,R 和 Python 中的数据框本质上是矩阵,其中行和列是可互换的;因此更适合像数据转换这样的任务。
关于 R 与 Python 的对比,我的经验是,通常一个任务可以使用 R 中不同的包以多种方式完成,而 Python 的开发方式是尽可能只提供一种功能。虽然一些数据科学家欣赏 R 中的这种灵活性,但其他人可能会发现它含糊不清、令人困惑。
此外,Python 被认为是比 R 稍低级的语言,它有更严格的数据类型要求。例如,一只熊猫。系列与 numpy.array、不同,因此它们不共享属性或方法。然而,在 R 中,不存在这样的区别,其中等价的概念只是一个向量或矩阵。这一特性使得统计/科学分析比 Python 中的分析更加方便。
毕竟,R 和 Python 的设计目的有些不同。我希望对这些区别的认识能使你更有效地选择最佳语言来解决你的具体问题。😀
想要更多数据科学和编程技巧?使用 我的链接 注册 Medium,获得我所有内容的全部访问权限。
还订阅我新创建的 YouTube 频道 【数据谈吉】
更多有用的数据科学博客:
****** [## 每个数据科学家都应该知道的 6 个 SQL 技巧
提高分析效率的 SQL 技巧
towardsdatascience.com](/6-sql-tricks-every-data-scientist-should-know-f84be499aea5) [## 熊猫失败时将 Word 和 PDF 文件导入 Python 的 4 种简单方法
导入非结构化文本/图像数据的实用指南
levelup.gitconnected.com](https://levelup.gitconnected.com/4-simple-ways-to-import-word-and-pdf-files-into-python-when-pandas-fails-43cf81599461)******
数据重启 2020
3 月 5 日,我有机会参加了由 Taste 组织的为期一天的关于数据和营销的会议 Data Restart 2020(布拉格),以下是一些亮点。

图片来源 www.datarestart.cz
该阵容包括来自代理商(Etnetera Activate、Optimics、DataSentics、Data Mind 和活动主办方——Taste)和内部团队(Twisto、Alza、Bonami)的 11 场演讲。这些平台以谷歌为代表,占据了整整两个发言时段。其中一位演讲者 Behavio 以一种方式脱颖而出,他说他们的核心业务是营销和社会学研究,而不是纯粹的数据分析。
主题和案例研究侧重于市场营销,但在数据分析方面非常容易理解。
营销数据凌乱
- 25–35%的 web 流量数据在点击和 GA 报告之间丢失(大约。5%归因于防火墙,25%归因于广告拦截器,10%归因于浏览器在隐私保护方面的努力,未知%归因于 GA/GTM 实施中的错误)。解决方案:定期自我审计,了解你的数据丢失发生在哪里,是提高数据质量的第一步。
 

Etnetera 激活数据质量(图像源)
- 一些营销渠道只是不想共享数据。以播客平台为例:苹果、Spotify、Podtrac——无 API(手动导出、CSV)、Blubrry——付费且昂贵的 API(约。每月 1000 美元)。解决方案:寻找自动导出的方法,例如使用网页抓取。
 - 其他营销平台使用不同的度量标准和维度定义,因此很难找到一种方法来比较“橙子和橙子”以及“苹果和苹果”。解决方案:将来自不同渠道的数据集中到一个地方,您可以根据自己的规则对其进行转换并进行比较,正如 Optimics for esk rozhlas 的案例研究所示。在谷歌云平台上,他们汇集了来自电台不同接触点(14 个电台、网站、播客、移动应用、社交媒体等)的数据。
 

Optimics 公司的 eský rozhlas 数据基础设施
- 但谷歌分析可能会有漏洞,永远不会给你全貌,所以要从整体上处理数据,把不同的数据源整合在一起。例如,fintech Twisto 的数据分析模型如下所示。他们还使用基于客户获得年份的队列分析。
 

Twisto 以客户为中心的数据模型
- 当心平均值,因为它们可能会误导人。再一次,Twisto 用一个例子证明了这一点:平均来说注册的转化率是 38%(这似乎是个好消息!).但现实可能是,一个在视频或帖子中展示如何使用该服务的影响者可能会推动 87%的转化率,而效果广告只有 7%的转化率。所以,始终要看渠道分布。
 

小心平均值(Twisto)
- 传统的 CRM 数据是静态的、交易性的,描述的是长期行为,但如果你想捕捉决策的瞬间,并了解哪些因素在起作用,那么就去看看数字“足迹”。这是雅各布·斯特奇在埃斯卡·spořitelna 案例研究中描述的方法。数字足迹是动态的、混乱的,很难捕捉和分析,但如果你破解了它,这是一种获得 360 度客户视角的方法(在 cs 的情况下,通过使用在线行为数据进行销售电话,贷款申请会大幅增加)。解决方案:使用上下文定位(查看 Word2Vec 模型来分析文本),为该解决方案创建的数据主题揭示了其他投标人忽略的不太明显的关键词。他们方法的另一个特点是使用原始用户级数据和连接数据源。
 

根据数据确定埃斯卡 spořitelna 的背景目标
数据伦理
- 2018 年,最大的转变是 GDPR,其次是浏览器在数据隐私问题上采取立场(甚至谷歌也计划在 2022 年之前废除第三方 cookies)。
 - 在网上 Cookies 状态你可以看到浏览器正在做什么来防止跟踪,以及他们如何对待用户数据。
 - 随着数据隐私意识的提高,2020 年将会有更多的消费者期待公司提供数据隐私。
 - 硬币的另一面是自愿数据交易的出现(例如, Instars 允许用户通过分享他们的数据来赚取加密货币)——但第三方 cookies 的问题是,参与的客户类型可能并不代表你的客户群整体。
 - 来自 Etnetera Activate 的 jiří·塔潘警告说,不要使用第三方 cookies,而应该寻求明确的同意和用户身份——激励用户登录。
 - 要为后 cookie 时代做好准备,请观察已经发生的从基于会话到基于事件的分析的转变。
 - 在我看来,很少有公司会和他们的客户谈论隐私(同意弹出窗口和打勾框不算)。如果有人开始提出这一趋势并采取行动,这可能是一个差异化因素(比较一两年前公司如何抓住环保趋势)。
 
机器学习和人工智能正在取代我们的工作(还没有)
如果你还没有对你自己的数据进行机器学习,或者还没有把它提供给你的客户,现在是你开始研究这个话题的时候了。因为你的竞争对手可能正在这么做。
- 在针对鞋子购买倾向的自动机器学习实验中,Data Mind 的 Jan Matouš ek 将经典逻辑回归和 H2O.ai 的商业和开源解决方案的成本效益放在一起。每个模型的精度非常相似(开源领先时为 0.73-0.75),但差异在于花费的时间(10 小时与 1-2 小时)和所需的专业知识。
 

数据思维的自动化机器学习实验
- 在自动化机器学习中,你可以“外包”算法选择或参数搜索等常规任务,但仍然需要专家和领域知识来定义业务目标,评估实际实施并确保稳定性。
 - 引发了一场关于黑盒 vs .白盒 ML 解决方案的讨论:一方面,作为一名数据分析师,你想控制你放入模型的变量,它们的权重等等。因为这可能会导致大笔资金的决策。但另一方面,为了快速验证概念,使用现成的解决方案可以节省您的时间和金钱。
 - 电子零售商 Alza 的案例研究展示了他们在 MS Azure 上运行的内部 ML 解决方案,以根据 PPC 支出预测销售额。他们用它来决定消费限额,模拟不同的场景和计划销售。
 - 在他们的算法开发过程中,Alza 首先使用了来自销售和广告支出的直接数据,但预测模型并不超级准确,也没有捕捉到季节趋势。所以,他们增加了时间变量(季度、月、周)节假日、特殊事件(比如黑色星期五)和宏观市场趋势来提高预测。
 - 金融科技 Twisto 使用大约 500 个不同的变量来评估借款人的信用风险。其中一些乍听起来无关紧要,但实际上是有道理的:例如,使用全部大写字母填写申请表的用户比具有标准拼写习惯的用户更不可靠,或者如果用户的电子邮件地址包含他们的真实姓名,这样的人比昵称晦涩的用户更有可能按时重新付款。
 - 几年前,当 Twisto 刚刚起步,没有自己的用户数据可供分析时,他们依靠专业知识和常识来评估风险,这导致了 20%的不还款。
 
从头开始
进入数字化转型并希望成为数据驱动的公司和客户可能会被大量的解决方案、工具和提供商所淹没。
- jiří·斯坦潘分享的创始人指南提醒根据企业的生命周期阶段选择数据解决方案,但也警告说,到时候不要在底层获得堆栈。
 

- 来自 Taste 的 Jan kad leek 建议所有者和顾问首先通过询问基本问题来验证他们业务的数字成熟度,并确保他们当前的报告能够回答并持续跟踪这些信息:(1)我有多少客户——客户数据,(2)他们带来多少美元——交易数据,(3)收购成本——广告数据
 - 除此之外,你还可以衡量商品销售成本、客户终身价值和广告支出回报。
 - 基本上,在决定任何解决方案之前,你应该非常清楚你的目标。
 
数据为大家
除非你能让足够多的人积极使用它并做出基于数据的决策,否则最复杂的数据解决方案也不会有回报。
- 这就是为什么博纳米选择了一个时尚的谷歌数据工作室单页仪表板,带有像付费/非付费、媒体、频道分组和活动这样的过滤器。它像一个多级漏斗一样工作,在每个阶段,你可以看到在促销上投入了多少,在销售(ROAS)上回报了多少,以及与前一阶段相比的动态。
 - 该解决方案可能会忽略许多指标,但通过有意保持简单、精心开发文档以及在活动命名上保持一致,他们成功地让 30%的高管到专家员工使用仪表板作为共享的“事实来源”。
 - 类似的信息来自 Alza(顺便说一下,Katka Lahodová是整个活动中唯一的女性发言人!).我上面描述的 ML 工具有一个简单的界面,只有几个关键的输入(广告花费$,活动类型)和一个带有预测的输出图。再次强调,这是一个有意识的选择,旨在提高可用性和采用率。
 - “数据是为每个人准备的”的另一个方面是你如何接近规划阶段——与所有利益相关者交谈并了解他们的需求是非常重要的。例如,对于 eský rozhlas 项目,Optimics 花了几天时间采访编辑、网络编辑、主编、董事会成员、播客和 hbbtv 团队、广播门户、新媒体团队等。
 
需要阅读的工具/想法/资源:
- Exponea 客户数据平台
 - 谷歌大查询和整个数据分析堆栈
 - 针对谷歌应用的 Firebase analytics
 - 机器学习的 H2O.io 解决方案(商业和开源)
 - 归因模型(沙普利,马尔科夫)
 - 群组细分
 - Matomo analytics (开源,上一版。Piwik)与谷歌分析
 - 品味杂志 DigiChef
 
除了程序之外,我真正喜欢的互动测试也在 kahoot.it 上运行。使用这个工具,你可以创建一个多项选择测验,并通过他们的智能手机实时获得观众的答案,并在速度和精度方面进行竞争(在我去年的一次演讲中,我使用了一个类似的工具 Mentimeter )。主持人实际上是在用演示文稿中的事实来测试我们,问了一些问题,比如“什么是 CDP?”或者“百分之多少的决策是在快速思考模式下做出的?”,所以它既吸引人又有用。
明年的愿望清单:听取更多平台和产品(不仅仅是谷歌)以及开源软件的意见。LinkedIn 社交活动。更多的女性演讲者。更多案例研究和趋势(如来自 Etnetera Activate)。
幻灯片可以在这里获得(只有捷克语),你也可以在 Twitter #datarestart 上查看讨论。
你觉得这些笔记有用吗?请在评论中告诉我!
机器学习的数据缩放——基本指南
什么是标准化,为什么它如此重要?
您可能会遇到带有大量内置数字噪声的数据集,如方差或不同规模的数据,因此在考虑机器学习之前,良好的预处理是必不可少的。这类问题的一个好的预处理解决方案通常被称为标准化。

菲德尔·费尔南多在 Unsplash 上的照片
标准化是一种预处理方法,用于转换连续数据,使其看起来呈正态分布。在scikit-learn中,这通常是一个必要的步骤,因为许多模型假设你正在训练的数据是正态分布的,如果不是,你的风险偏向你的模型。
您可以用不同的方式标准化您的数据,在本文中,我们将讨论流行的数据缩放方法— 数据缩放。或标准缩放更精确。
同样重要的是要注意到标准化是一种应用于连续数值数据的预处理方法,在一些不同的场景中会用到它:
- 当处理任何使用线性距离度量或在线性空间上操作的模型时-KNN、线性回归、K-均值
 - 当数据集中的一个或多个要素具有较高的方差时-如果中某个要素的方差比其他要素的方差大一个数量级或更多,这可能会使假设数据呈正态分布的模型产生偏差
 
现在让我们继续进行数据缩放。
数据缩放
当处理包含不同比例的连续要素的数据集时,缩放是一种最有用的标准化方法,并且您使用的是在某种线性空间中操作的模型(如线性回归或 K-最近邻)
要素缩放会变换数据集中的要素,使它们的平均值为零,方差为一。这将使线性比较要素变得更加容易。此外,这也是scikit-learn中许多型号的要求。
让我们来看看一个名为 wine: 的数据集
import pandas as pd 
import numpy as np 
from sklearn import datasets wine = datasets.load_wine() 
wine = pd.DataFrame(
    data=np.c_[wine['data'], wine['target']], 
    columns=wine['feature_names'] + ['target'] 
)
我们想使用葡萄酒数据集中的ash、alcalinity_of_ash和magnesium列来训练一个线性模型,但是有可能这些列都是以不同的方式测量的,这会使线性模型产生偏差。使用describe()函数返回关于数据集的描述性统计数据:
wine[['magnesium', 'ash', 'alcalinity_of_ash']].describe()

我们可以看到,ash的最大值是 3.23,alcalinity_of_ash的最大值是 30,magnesium的最大值是 162。这些值之间存在巨大差异,由于规模更大,机器学习模型在这里可以很容易地将magnesium解释为最重要的属性。
让我们将它们标准化,以便在线性模型中使用。以下是步骤:
- 导入
StandardScaler并创建它的一个实例 - 创建执行缩放的子集
 - 对子集应用缩放器
 
代码如下:
from sklearn.preprocessing import StandardScaler # create the scaler 
ss = StandardScaler() # take a subset of the dataframe you want to scale 
wine_subset = wine[['magnesium', 'ash', 'alcalinity_of_ash']] # apply the scaler to the dataframe subset 
wine_subset_scaled = ss.fit_transform(wine_subset)
厉害!让我们看看前几行缩放后的数据是什么样子的:

这些值现在更加接近了。为了了解缩放实际上如何影响模型的预测能力,让我们快速制作一个 KNN 模型。
首先,对于未缩放的数据:
from sklearn.neighbors import KNeighborsClassifier 
from sklearn.model_selection import train_test_split X = wine.drop('target', axis=1) 
y = wine['target'] X_train, X_test, y_train, y_test = train_test_split(X, y) knn = KNeighborsClassifier() 
knn.fit(X_train, y_train) 
print(knn.score(X_test, y_test)) 
**>>> 0.666666666666**
不太准确。让我们缩放整个数据集并重复这个过程:
ss = StandardScaler() X_scaled = ss.fit_transform(X) X_train, X_test, y_train, y_test = train_test_split(X_scaled, y) knn = KNeighborsClassifier() 
knn.fit(X_train, y_train) 
print(knn.score(X_test, y_test)) 
**>>> 0.97777777777777777**
如您所见,我们模型的准确性显著提高。我将把对这个 KNN 分类器的进一步调整留给您,谁知道呢,也许您可以正确地得到所有的分类。
让我们在下一部分总结一下。
在你走之前
这就是数据标准化的全部内容,也是它为什么重要的原因。我们将在其他时间比较StandardScaler与其他定标器。本文的要点是,无论何时你需要正态分布(相对)的特性,你都应该使用StandardScaler。
更准确地说,每当你使用一个假设数据是正态分布的模型——比如 KNN 或线性回归,就使用StandardScaler。
感谢阅读。
加入我的私人邮件列表,获取更多有用的见解。
喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
[## 通过我的推荐链接加入 Medium-Dario rade ci
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@radecicdario/membership)
原载于 2020 年 8 月 31 日 https://betterdatascience.com**的 。
数据科学:处理新数据集(用于推理)的 5 个步骤

所有权利保留给合法所有者
“如何开始对数据集进行分析和推断”简介,
我们将解释一个经典机器学习问题的一般路线图。我们可以粗略地将步骤数下限为 5,这是必须完成的。
第一步:统计研究
采取这一步骤的一个简单原因是,当您第一次遇到一个新的数据集时,通常会非常陌生,不知道要素的分布/单位/类型。假设您的环境是 Python,并且您使用 pandas 来解析您的数据集,“describe”函数将完成这项工作。

用法示例
第二步:表面数据预处理
这一步包括许多更小的任务。
- 填充 NaN(根据您的数据集使用均值/中值/高斯方法)如果有,在某些情况下,0 值也非常麻烦,因此您可以聚合成更小的组,以便非零值和零值相加,或者用ε值替换 0。
 

这里的 fill_nan 是自定义的,一般使用的是 df.fillna()
- 一个好的习惯是将数据集归一化,使其均值为 0,方差为 1。这有助于模型(如逻辑回归)更好地工作(稳健界限),而不是在优化过程中花费更长的时间来收敛(通过 SGD)
 

再次标准化是一个自定义函数,简单地使用公式(x-mu)/sigma
- 完成这些任务后,您可以在数据集上尝试一些简单的模型,并根据结果决定要应用哪些数据处理。
 
第三步:更多数据处理
从这一点开始,您对目标特征的预测就有了准确性。现在的重点是提高精确度,以下是一些方法:
- 降噪:有些情况下,相同的特征向量给你不同的目标特征,在这些情况下,你可以做平均或做均匀分布,取值之间。还有其他更复杂的方法来处理图像(例如图像增强,噪声 2 噪声)
 - 剔除异常值:剔除一些异常值也是有益的。这些异常值可能出现在数据集中,但不会出现在您的测试用例中。有的著述考虑区间[0.01,0.99]。
 - 特征扩充:最常用的方法是多项式扩充,exp/log/cos 扩充。这些包括在数据集上应用所提到的函数,然后连接到当前的,以获得更多的数据和更复杂的模型进行训练(增加权重维度)。更复杂和具体的情况可能是图像仿射变换/ GAN 图像/噪声添加,或者在经典数据中,交互项(将特征向量相乘)。
 
第四步:模型拟合/训练,超参数
这部分是关于尝试不同的方法并获得正确的超参数。
- 根据你的工作情况(即无监督/有监督/分类等),你将不得不应用不同的方法(无监督的 k-means,有监督的逻辑回归,以及其他类似的方法)。显然,你总是可以为你的神经网络构建一个架构来完成分类/聚类任务,从而与你的研究目标相匹配。
 - 当您知道模型背后的理论时,超参数可以被强力搜索以进行优化,或者也可以被白盒搜索。例如,k-均值/k-最近邻选择 k 的一些一般规则是肘规则。
 
第五步:交叉验证
最后,为了不过度拟合或至少知道存在过度拟合,要进行交叉验证,这里有一些方法:
- 训练/验证分割:最常见的方法是在验证集上进行推断,并与实际情况进行比较
 - k 倍分裂:我们分成 k 个部分,留下 k-1 个用于训练,1 个用于验证。我们对 k-1,1 的所有组合进行推断和基础事实比较。
 
上面提到的解释并不详尽,肯定是可以改进的,但这些是遇到新数据集时要做的最起码的工作。
感谢阅读!请继续关注更多技巧/教程文章。如果感兴趣,我的 GitHub 上有完整的笔记本!此外,点击这个链接(指向联盟计划)真的会帮我解决问题!您只需完成一些快速任务(只需等待和激活通知),所有这些将真正帮助我了解更多未来的硬件相关内容!
数据科学联盟
成为反种族主义数据科学家的一些方法

在 Unsplash 上由 Toa Heftiba 拍摄的照片
本周我打算写一写我是如何坚持并完成最近的一个项目的。然而,考虑到已经发生的一切,现在这感觉毫无意义。当然,不管发生了什么,我说的是艾哈迈德·阿贝里、布里安娜·泰勒和乔治·弗洛伊德的谋杀案,以及随后全国各地发生的抗议活动。作为一个人,除了亲自参加抗议活动,你还可以做很多事情来抗议这些谋杀。你可以向保释基金捐款(链接这里),与你社区的其他成员联系,你可以开始就黑人面临的独特斗争进行自我教育(这里有一个让你开始的书单),还有很多其他事情。不过,你可能已经在互联网上的其他地方看到过很多这样的想法,或者至少我看到过。
反种族主义的数据科学家在这段时间里能做些什么呢?这绝不是一个详尽的列表,但这是一个开始。
思考你的研究的含义
不久前,我看到一条推文,大意是,“干细胞告诉你如何克隆恐龙。文科告诉你为什么那是个坏主意。”有很多人工智能,特别是面部识别,已经被武器化来对付抗议者,无论是现在还是最近的历史。如果你处于开发新工具和算法的最前沿,这不足以确保它获得最好的准确性或 AUC 分数。你需要考虑你正在建造的东西的含义。仅仅决定如何使用你的模型是不够的,还要决定如何使用它,并采取相应的行动。如何做到这一点的一个很好的例子是在 OpenAI 发布的 GPT-2 中看到的,他们从偏移中表示,由于潜在的恶意使用,他们不会发布训练好的模型。然而,如果你不在创造新技术的前沿,但你仍然在数据科学领域工作:
与他人分享你的技术知识
正如我所说,监控技术和警务算法只是用来对付抗议者的许多工具中的一部分。作为技术社区的成员,我们对技术能做什么和如何做有更好的了解。如果你已经在面部识别领域做了很多研究,你就有资格告诉别人它是如何工作的,以及需要采取哪些步骤来绕过它。如果你知道手机拍摄的照片中保存的元数据,你可以向其他人解释如何在社交媒体上发布照片,而不危及任何抗议者的安全。我们生活在一个日益由数据驱动的世界。这意味着数据科学家对世界运行的齿轮有了越来越深入的了解。我们了解像深度假货、面部识别和算法这样的事情是如何工作的,这种了解可能非常有价值。但是,只有当我们有效地与公众交流我们的知识时,这种价值才会产生。说到知识,数据科学的盟友们还有另外一件事:
努力教育自己
https://tenor . com/view/lilo-and-stitch-Disney-pleakley-jumba-education-gif-3562360
我们一直在学习新的东西,一旦你弄清楚了最新的 SOTA 模型,新的就会出现。如果你已经在不断学习,为什么不花点时间了解种族主义是如何影响这个领域的呢?我们目前有种族主义技术,如面部识别,在检测白人面孔方面比有色人种更好。如果这个问题没有直接影响到你,或者你没有有意识地反种族主义,这就是你可能完全忽略的那种错误。因此,努力变得更加反种族主义不仅仅是让你成为更好的人和社区成员,而是让你成为更好的数据科学家。了解科技和数据科学中存在的种族歧视的最佳方式之一是倾听直接受其影响的人的声音。这里有几本书可以作为起点:
[## 技术之后的竞赛:新吉姆法典的废奴主义工具| IndieBound.org
从日常应用到复杂算法,鲁哈·本杰明(Ruha Benjamin)透过科技行业的炒作来理解新兴的…
www.indiebound.org](https://www.indiebound.org/book/9781509526406) [## 迷人的技术:种族、核心技术科学和日常生活中的自由想象
《种族、道德技术科学和日常生活中的解放想象》鲁哈·本杰明(编辑)杜克大学…
www.indiebound.org](https://www.indiebound.org/book/9781478003816) [## 压迫的算法:搜索引擎如何强化种族主义| IndieBound.org
揭示了对有色人种女性的负面偏见是如何嵌入搜索引擎结果和算法运行中的…
www.indiebound.org](https://www.indiebound.org/book/9781479837243) [## 暗物质:对黑暗的监视| IndieBound.org
在《黑暗物质》中,西蒙尼·布朗将黑暗的条件定位为一个关键的场所,通过它监视…
www.indiebound.org](https://www.indiebound.org/book/9780822359388) [## 我们的数据体:数字防御行动手册
我们的数据机构(ODB)已经进行了研究,并制作了一本以数据为重点的普及教育活动手册…
store.alliedmedia.org](https://store.alliedmedia.org/products/our-data-bodies-digital-defense-playbook?variant=18553259622496)
如果你想在 Twitter 上听到并关注黑人的声音,还有# BlackTechTwitter ,坦白地说,我可能错过了很多东西。
最终,努力倾听(而不是谈论)黑人的声音,并从他们所说的话中学习。话虽如此,也要大声说出你的支持,放大那些同样的黑人的声音。作为一名女性,我曾经历过我说了些什么而被当作没什么而不予理睬的时候,但是当我的一个男性朋友说了同样的话时,它就被当真了。如果我们不能确保不同的声音不被听到,多样性就没有什么价值。因此,如果我们想建立更好的技术和技术背后的更好的社区,我们所有人都有责任积极致力于反种族主义。
BlackLivesMatter
数据科学和人工智能是一团乱麻……而你的初创公司可能会让情况变得更糟
数据科学一直被称为“21 世纪最性感的工作 ”但有时我怀疑我们是否在这里。这个世界为我们准备好了吗?在之前,我已经研究过这个问题,但是数据科学的工具问题需要更多的讨论。数据科学家可用的工具限制了他们的效率,所以看到工具制造商更加关注他们的需求将是一件好事。反而感觉工具是为流行语而不是人做的。

这篇文章的灵感来自我的朋友Clemens Mewald——我有幸与之共事过的最优秀的产品经理之一——他写了一篇名为你的企业深度学习工具初创公司将会失败…我读这篇文章时的心情和我的玩具即将被夺走时一样。**
感觉好像这些工具是为流行语而不是人制造的。
一方面,他是对的:如果你像其他人一样制作 ML/AI 开发工具,你的创业公司可能会破产。另一方面,我不希望创业者尖叫着逃跑。
我这么说纯粹是自私的,作为一名数据科学家代表她的人民恳求。我认识到,我很荣幸能在一个相对较少受到我即将提出的问题困扰的环境中工作,所以我想让你知道,这些话是由我过去的经历激发的(即使是在谷歌这里!)和你每天与我分享的故事。让我把我的声音借给你。
全体船员集合!
即使是好的工具也不是完美的,这并不奇怪——要做的工作比任何数据科学工具/平台提供商(让我们简称这些实体为“工具制造商”)可能单独管理的工作都多。算法研究狂热的盲目步伐意味着,理论创新远远超过工具制造商的能力,无法将这些数学蓝图交到渴望使用它们的数据科学家手中。这是一个多么大的问题!
理论创新的速度远远超过工具制造商将这些数学蓝图放到用户手中的能力。
这就是为什么即使我为一个工具制造商工作(谷歌云非常认真地为数据科学家构建和集成伟大的工具),让我成为第一个为任何考虑进入这个领域的工具制造商欢呼的人。这项工作需要全体人员全力以赴!
作为 UX 问题的数据科学有效性
我们数据科学家花了这么多精力来帮助你了解你的用户……你忘记了我们也是用户。这让我想起了克莱门斯对工具制造创业公司的(可靠)建议。

小伙伴们,又在狼吞虎咽了?图片:来源。
如果你追逐“深度学习”的热潮,并将你的整个策略建立在市场对众多数据科学工具中的一种的迷恋之上,那么克莱门斯是对的。播放恐怖电影风格的预感音乐。
追用户。致力于制造不会让数据科学家们眼馋的工具。
而是追用户。那就是数据科学家。为了追赶我们,你必须了解我们是谁,我们如何工作。你必须明白我们已经拥有的和我们缺少的。拜托,不要只是制造另一个实现卷积神经网络的工具。制作一个工具,实现卷积神经网络的方式,数据科学家可以使用,而不想抓自己的眼睛。这是一个微妙的区别。
数据科学家在历史上一直无权决定他们使用的工具,但我敢打赌,随着雇主努力吸引最优秀的人才,数据科学家在他们使用的工具上有发言权的转变正在加速。

让我们更容易完成工作
虽然我们中的一些人声称喜欢做艰苦的事情,但是我们中的大多数人讨厌做那些需要最少技巧和最大努力的家务。就大多数数据科学家而言,如果我们编写的所有代码都是一样的,无论是大的还是小的,笔记本电脑还是云,原型还是产品,那就太好了……在内心深处,我们知道不是这样的唯一原因是我们生活在黑暗时代,在那里我们的工具很烂。
我们热爱的工作部分是涉及数据、创造力、狡猾和可能性的部分。这是我们了解宇宙并与你分享的部分。不是涉及安装设置和旋钮旋拧的部分。这并不是要求数据集采取不同的形状,以便函数能够在其上运行。这绝对不是让智能隔离中构建的软件包相互交流的部分。
您可以帮助我们更加热爱我们的工作,我们会因此而热爱您!
收拾这个烂摊子!
事实是,我们每天花很多时间与讨厌的工具作斗争。我们知道我们确切地想要做什么,只是需要两个星期去做。听起来像伟大的 UX,对吗?
今天的数据科学工具生态系统是如此的支离破碎和混乱,甚至可能会让 Marie Kondo 感到晕眩。
今天的数据科学工具生态系统是如此的支离破碎和混乱,甚至可能会让玛丽·近藤感到晕眩。如果你想制造更多的工具,专注于制造能激发快乐的工具。便于将它们折叠在一起。(对吧,玛丽?)
今天的工具没有一个能解决所有问题。
顺便说一句,这也是克莱门斯告诉你要做的。不要为了工具而开发工具,开发工具是为了满足用户的需求,让用户开心。专注于集成——让这些工具与生态系统的其余部分很好地配合非常重要,因为没有人愿意停止他们正在做的事情来给你的工具特殊待遇,除非它是万灵药。正如克莱门斯解释的那样,没有一种现代工具能解决所有问题,所以不要去想它。(如果有人告诉你深度学习是圣杯,那就更有理由去阅读克莱门斯所说的话了。
重在融合!没有人想停止他们正在做的事情来给你的工具特殊待遇。
要激发快乐,让产品完美地融入满足用户需求的其他工具的生态系统,你必须了解它们,你必须对 UX 有所了解。这意味着你的产品经理、开发人员和用户体验人员必须花时间去理解数据科学家。在谷歌倡导数据科学家一直是我工作的一大部分——包括帮助推动从第一天起就重视数据科学 UX 的项目(例如,谷歌的假设工具)——如果这是我们拥有美好事物的代价,我会让自己在外面成为一个讨厌的人。

为在可用性上全力以赴的 TF 2.0 欢呼吧!当 TF 切换到 Keras 风格,并对让您编写所有样板文件说再见时,可能会有初期的痛苦,但我很兴奋。有人甚至会说我是渴望。
好消息是事情正在好转。去年我最喜欢的一条新闻是 TensorFlow 2.0 以用户为中心,以及该社区致力于改善 TensorFlow 1.x 的用户痛苦。这太棒了,这些著名的计划正在引领潮流,但如果初创公司采取同样的立场,那不是很好吗?
我的观点是什么?
数据科学界感到不被理解,我们看到这反映在雇主要求我们使用的工具中。修理这些工具并使它们变得友好不仅仅是我们几个人的工作,尽管我向那些推动我们克服困难前进的了不起的英雄们致敬。唉,很少有 UX 的专业人士认为数据科学的有效性是(至少部分是)UX 问题。更糟糕的是,新的工具生态系统并没有对鼓励变革浪潮起到多大作用,通常是为时髦词汇而不是用户构建的。让我们尽我们所能来解决这个问题!
感谢阅读!人工智能课程怎么样?
如果你在这里玩得开心,并且你正在寻找一个为初学者和专家设计的有趣的应用人工智能课程,这里有一个我为你制作的娱乐课程:
在这里欣赏整个课程播放列表:bit.ly/machinefriend
喜欢作者?与凯西·科兹尔科夫联系
让我们做朋友吧!你可以在 Twitter 、 YouTube 、 Substack 和 LinkedIn 上找到我。有兴趣让我在你的活动上发言吗?使用表格联系。
数据科学和行为经济学

乔希·里默尔在 Unsplash 上的照片
通过数据了解我们的偏见
什么是数据科学?
根据维基百科的说法,数据科学“是一个跨学科领域,它使用科学的方法、流程、算法和系统从结构化和非结构化数据中提取知识和见解。
和统计学有什么区别?说实话,没那么多。统计学是数学的一个分支,主要研究随机性、不确定性和信息。它是用于从数据中提取知识的科学的一部分,现在几乎在任何科学领域都有应用。
这种知识提取可以通过算法来完成,这有时需要大量的计算能力。由于缺乏足够强大的计算机,这些算法中的一些在许多年前不可能存在或被测试。然而,随着计算机科学和技术的巨大进步,我们现在能够开发更复杂的方法来从数据中提取信息。不仅如此,我们现在可以获得比以前多得多的数据。就好像我们给统计学打了类固醇,然后它就变成了数据科学。如果你想了解更多,可以从这里开始。
什么是行为经济学?
另一方面,行为经济学是心理学在经济学领域的应用(因此,它也被称为经济心理学)。许多年前,主流经济理论基于一些假设,其中之一是人类理性行事(臭名昭著的经济人)。
乍一看,这种假设似乎没有多大意义,因为我们都知道我们自己并不总是理性行事。然而,我们必须考虑到,如果我们从大的方面来看,这个假设似乎更合理:我可能不会完全理性地行动,你也可能不会。然而,总的来说,人类可能会。就像我们的非理性互相抵消了。这是一个更合理的假设,它使得创建模型、尝试和预测市场走向变得容易得多。
然而,即使是这个更合理的假设,也被行为经济学领域质疑,并在某些情况下被证明是错误的。此外,它最大的贡献不是表明经济学家忽视我们的非理性而过度简化了现实,而是表明非理性有时是可以预测的。我们的行为方式可能与理性假设不一致,但这本身是一致的,这意味着我们总是倾向于以同样的非理性方式行事。这种行为被称为认知偏差。
他们是怎么走到一起的?
现在我们有数据和计算能力来提出更好的现实模型,我们知道人类的非理性可以被测量和预测,我们如何利用这一点呢?好吧,我将提出一些著名的认知偏见,以及如何使用数据科学来衡量它们或将它们融入到您的产品/服务中。
确认偏差
最著名的认知偏差之一是确认偏差。它代表了我们倾向于寻找那些证实我们已经知道的东西,而忽略那些与我们自己的观点不一致的观点。如果我反对枪支管制,我看到一篇文章说枪支会增加暴力,我会倾向于忽略它。然而,如果我看到另一篇文章显示了相反的证据,我更有可能去读它。例如,脸书通过选择向我们展示与我们的世界观一致的帖子、文章和观点,从这种偏见中获利。
但是你怎么能深入到只看数据就能知道某人对世界的看法呢?嗯,你不需要。你可以使用算法来考虑我倾向于喜欢的内容类型,将我与其他喜欢过相同内容的用户进行比较,并向我推荐他们喜欢过而我以前没有见过的内容。网飞的推荐系统也是同样的原理。为你做到这一点的算法类型被称为“协同过滤”,也可以用来推荐产品或服务。
风险规避

根据环境的不同,人们或多或少倾向于冒险,这往往会导致他们做出不合理的决定。假设我邀请你赌一枚硬币:正面我给你 50 美元,反面你给我 100 美元。似乎不公平,对吧?我们实际上可以计算出这类游戏的预期收益,方法是将每个可能的结果乘以其发生的概率,然后将结果相加:50% *(-100 美元)+50% *($ 50)=-25 美元。这意味着玩这个游戏你平均会损失 25 美元。然而,如果你仍然因为过于乐观,仍然希望赢得 50 美元而决定玩这个游戏,那么你就是有风险倾向的行为。然而,如果反过来,你就会表现出规避风险的态度。
在这种情况下,期望值通用等式可以写成如下形式:

其中 p 是概率,v 是每个可能结果的相关值。风险中性的个人会根据这个等式做出决定。然而,通常情况下,人们往往是非理性的,因此行为更像下面的模型:

这里我们加入了α,它代表了个体对风险的态度:当α>1 时,个体容易产生风险;当α<1, the individual is averse to risk (and when α=1, the equation becomes just like the one above).
Studies have already shown some characteristics that can influence your attitude towards risk, such as sex, age and wealth. Since this bias can be seen not only in coin-tossing games but also when people buy insurance, warranties and lottery games, you could use regression algorithms to calculate and predict your customers’ behaviour towards risk. By doing so, you could make sure you price your services accordingly, depending on the person’s profile.
Moral hazard

Photo by Conor SamuelonUnsplash
这种偏见在保险行业很常见,举个例子可以更好地解释:一旦你给你的车上了保险,你就开始不那么担心承担风险:例如,你不会像以前那样避免在危险的街区停车。为了在给你的保险定价时考虑到这一点,公司不仅开始考虑年龄和性别的整体统计数据(例如:年轻男性更有可能遭遇车祸,所以他们的保险单通常会更贵),而且他们必须考虑到这些概率在你给汽车投保后如何变化。这意味着通过一个虚拟变量来控制他们的分析,这个虚拟变量告诉人们是否有保险。
结论
综上所述,我们知道数据科学可以为决策过程中存在低效率的领域带来价值。行为经济学可以向我们展示那些低效率在哪里,并且已经可以为我们提供一些模型,我们可以将我们已知的数据科学方法应用于这些模型。另一方面,数据科学可能会帮助我们识别我们还没有意识到的新偏见。这是一个双赢的游戏。
数据科学和竞争性编程
他们在解决问题,但方法不同。

C 竞争是学习新事物的好方法,尤其是对那些有兴趣竞争并赢得某些东西的学生来说。到目前为止,竞争性编程已经成为计算机科学界的热门竞赛。
对我来说,竞争性编程具有挑战性,因为你必须解决问题,并且使用现有的算法或实现自己的算法来解决问题。
当我大一的时候,我仍然花时间在这上面竞争,而且,我被介绍到数据科学。由于数据量和存在的机器学习算法,近年来它一直很受欢迎。
我对这一领域的发展速度以及使用数据科学方法的应用感到惊讶。正因为如此,我对数据科学产生了兴趣。
然后,突然之间,我陷入了两难的境地,要选择是继续追求竞争性编程,还是继续提升我的数据技能。根据我的经验,那些东西是在解决问题。
但是你有没有想过两者都追求还是选择其中一个?
您之所以阅读这篇文章,是因为当我刚进入数据科学领域时,您可能和我有着同样的困境。所以,我想给你一些关于竞技编程对你的职业是否有用的观点。
我写这篇文章,特别是为那些计算机科学的新生或者可能目前刚开始学习数据科学的人。如果你刚接触竞争性编程,我希望这对你有用。
我写这篇文章是基于我在探索计算机科学的许多领域时的经验。
这篇文章将分成几个部分。首先,我将介绍什么是竞争性编程。然后,我将向你展示与 Kaggle 比赛的不同之处。最后,我会给你一些来自软件工程和数据科学的观点,并强调它是否值得追求。
没有别的了,让我们开始吧。
竞争性编程
竞争性编程是一种人们必须在一定时间内解决问题的竞赛。通常,它会给你输入和输出的例子,然后你用任何编程语言来实现这个问题。
这是 Codeforces 的问题示例,

由我从 Codeforces 中捕获
首先我们可以看到,问题陈述用一个故事来说明问题。然后,它向您展示了示例案例。最后,给出了一些注意事项。
有了这个问题陈述,你必须分解我们必须做的步骤,然后,我们设计并实现算法来解决它。它只是显示了几种情况,但实际上,还有更多。因此,你必须确保你的算法可以解决任何情况。
总的来说,竞争性编程将在解决问题和编程技能上挑战你的团队。还有,因为你要用算法解决问题,所以你要一步一步地写解决方案。
与数据科学竞赛的区别
与数据科学社区之一的 Kaggle 相比,竞争确实不同。
在 Kaggle 上,你会得到问题陈述和数据集。你必须使用机器学习算法来解决问题,以最小的误差预测结果。除了解决问题之外,您还必须分析数据以获得洞察力、模式、异常值等等。
这里显示了 Kaggle 的房价预测,

被我从 Kaggle 中捕捉到。
在这个例子中,你想解决回归问题,你必须用给定的数据来预测房子的价格。因此,您必须调整模型,使其能够以更小的误差预测值。此外,你必须分析数据集,以获得更多的见解。
在竞争性编程中,你也分析算法,但这与数据科学不同。您将分析您的算法性能。
如果你发现你的算法不符合某些要求像你的算法超过了时间限制,那么你就要改进算法。因此,你可以解决问题。
在数据科学中,你也将分析你的模型,然后你改进模型以具有更高的性能。
但不同之处在于,你也在研究数据的模式。有了这个模式,我们希望在继续创建模型之前获得一些见解,可能还有一些假设。
总体而言,数据科学竞赛主要在于分析您的数据和建模以实现更高的准确性。你不需要像从零开始的竞争性编程那样显式地编写算法,但是你只需要为这样的算法使用现成的包。
尽管如此,你必须分析数据集并找到它的模式,还要找到可能成为你的问题的假设的见解。这部分是数据科学本身最具挑战性的部分。
最后的想法

因此,根据这些信息,你应该同时追求两者还是只专注其中一个?
我不知道。你有权选择哪一个。如果你还很困惑,我来给你一些我的看法。
竞争性编程和数据科学是不同的。竞技编程通过自己实现一些算法来解决问题。另一方面,数据科学也在解决问题,但它不涉及算法实现。因此,这是一个不同的领域。
如果你想解决一个新的数据科学问题,但没有任何给定的 ML 算法的实现,那么追求竞争性编程仍然是值得的。
此外,如果你想成为一名软件工程师,这是值得追求的,因为它有很多算法实现。
但是,如果您只对数据集的分析和建模感兴趣,并且主要关注于分析,那么您不应该在竞争性编程上花费太多时间。
您可以提高您的数据科学技能,因为有许多技能您必须学习,例如编程、深度学习、数据可视化、统计等等。
这是我的建议,这就是本文的结尾。
感谢您阅读我的文章,您也可以在下面查看我以前的文章:
从勘探到预测 1970 年至 2015 年的二氧化碳排放数据。
towardsdatascience.com](/time-series-forecasting-with-arima-model-in-r-77f4e2ae7abb) [## Python 中的客户细分
基于 K-均值聚类算法的图像分割。
towardsdatascience.com](/customer-segmentation-in-python-9c15acf6f945) [## 更高的准确性并不意味着更好的机器学习模型性能
我们可以定量地衡量机器学习模型的性能,但不仅仅是准确性,还有很多…
towardsdatascience.com](/greater-accuracy-does-not-mean-greater-machine-learning-model-performance-771222345e61)
数据科学和机器学习不一样
虽然数据科学随着机器学习和人工智能的进步而变得流行,但科学是一个更广泛的话题。

图片来自维基共享,根据知识共享 署名-共享 2.0 通用许可改编。
在过去的几年里,机器学习、人工智能以及最终的数据科学成为了行业的热门词汇。
当然,这种现象是有原因的。新的算法和新的硬件使得复杂的预测系统对许多公司来说是负担得起的。不难在行业中找到一个用例,说明他们如何使用一个千层卷积神经网络来克服一个巨大的问题。真的,这是一件好事。
谁从来不想要水晶球?
然而,几十年来,机器学习和人工智能一直是学术界的研究主题。它们不是新的。现在,他们只是更容易接近。几乎任何人都可以运行 python 笔记本,导入 scikit-learn,加载 pandas 数据框,并…安装它。
🎶装就装,装就装,装就装,
没有人想被打败🎵

没错。没有人想在市场上被打败。互联网上充斥着如何训练你的̶d̶r̶a̶g̶o̶n̶模型的教程。你只需要小心过度适应的怪物。对吗?
号码
不要误解我。网络上有大量有价值的内容,学习这些内容很重要。然而,根据我的经验,如果你想成为一名成功的数据科学家,你需要超越机器学习食谱。以下是我认为所有数据科学家都需要掌握(或培养)的三项高级技能:
- 科学方法
 - 如何为企业创造价值
 - 如何恰当地传达调查结果?
 
一方面,具有扎实学术背景的数据科学家通常擅长科学方法。然而,他们常常过于兴奋地钻研有趣的研究,可能会忘记企业真正需要的是什么。另一方面,行业中成长起来的数据科学家往往会忽视科学方法的严谨性。
第三个技能真的是除了的东西。我坚信这取决于个人的经历,甚至可能与他或她的个性有关。
好消息是:即使你缺少这些技能中的一项,你也可以学习它们并发展自己。
今天,我要讲第一个:
科学方法

普里西拉·杜·普里兹在 Unsplash 上的照片
我们把科学这个词放在‘数据科学’里是有原因的。如果你不知道如何进行科学实验,你应该学习(即使你不是数据科学家,因为科学是为每个人服务的)。一个数据科学家必须理解科学是什么,并且知道如何正确地批评它。这包括知道如何审视自己的科学工作。
以数据为基础的科学
这就是数据科学的一般含义。我们使用历史观察来证明或拒绝假设。在这个意义上,人们可以说数据科学是基于证据的研究。一个多世纪以来,人们一直在其他领域(如医学)这样做。因此,当您执行数据科学任务时,请在科学方法中考虑它:
- 你的问题是什么?
 - 你的假设是什么?
 - 你将如何检验你的假设?
 - 结果如何支持你的主张?
 
此外,如果在这个过程中出现了新的见解或证据,你随时可以重新开始这个过程。它叫做:
科学实验生命周期!
但是机器学习管道看起来不像科学方法。
我完全不同意。让我们举一个普通的例子:
问题:什么原因导致堵车?
假设:下雨导致交通堵塞。
方法:训练一个 ML 模型,根据历史降雨数据进行交通预测。用看不见的观测值预测流量并测量误差。此外,基于历史平均值作为基线模型来估计流量,并测量误差。
分析:比较误差分布。ML 模型的误差是否明显低于基线误差?
当我强调'显著更低'时,是因为你不能只说'它比我证明的假设低 5% '。你最好使用假设检验,这是一种统计工具,不幸的是,许多数据科学家不知道如何使用。
我的方法可能不是测试下雨是否造成交通堵塞的最佳方法。实际上,这只是一个可能的方法,而且,还是一个普通的例子。我的观点更多的是关于你应该如何看待数据科学任务。我们不应该因为需要预测流量而按下“适合按钮”,而是应该思考我们试图回答什么,我们将如何回答,以及我们的结果是否真的比更简单甚至随机的结果更好。
现在,我希望你同意我的观点,数据科学和机器学习是不一样的。除了我提到的高级技能之外,一名数据科学家还应该掌握许多其他技术科目。但这是另一篇博文的主题。
如果你喜欢这本书,你可以在 Medium 或者 Twitter 上找到我。此外,如果您想通过电子邮件获得关于数据科学的提示和想法,请订阅我的简讯。这是一封每月一封的电子邮件,可能会附带:书籍建议、flash 小说、关于音乐的讨论等等。
用 Scala 和 Spark 实现数据科学和机器学习(第 1/03 集)
Scala Spark 机器学习
基于 Spark 分布式计算的大规模机器学习

学习 Scala:从护目镜图片下载的 Scala logo
cala 是用来编写最流行的分布式大数据处理框架 apache Spark 的核心语言。从小型企业到大型企业,大数据处理正变得不可避免。每秒产生的数据量都在增加。
从数据中提取有价值的见解需要最先进的处理工具和框架。研究人员正在努力开发特定于应用的工具、编程语言和框架。Scala 是利用大数据处理的发明之一。
Scala 编程语言旨在实现可扩展的解决方案来处理大数据,从而产生可操作的见解。
在这个系列中,我将在 Google colab 中开发一系列教程来学习 Scala,并申请数据科学和机器学习应用。Python 被认为是数据科学和机器学习最常用的编程语言。然而,当处理大数据时,数据科学家应该知道 Scala 等替代方案。
谁应该遵循这些教程?
如果您是一名使用 Pythonic 方法的数据科学家,并且想要添加另一个大数据处理工具,本系列适合您。
我把这个系列分成了三个部分。在这个故事中,我将讲述 Scala 编程语言的基础知识。我们将在下一篇文章中介绍 spark 和 Scala,并以 Spark 和 Scala 的机器学习结束本系列。对于每个故事,将有与谷歌 colab 相关的信息和实践代码。
在第一个故事中,你将学习如何在 Google colab 中安装或设置 Scala,最重要的数据类型,Scala 表达式,Scala 函数和 Scala 对象。
Scala 数据类型
使用 python 时,不需要指定变量的类型,但是 Scala 要求你指定变量的数据类型。因此,理解和实践 Scala 中实现的数据类型更有意义。下面是 Scala 中实现的最基本的数据类型。你可以用 google Colab 做练习。
- Scala 数据类型: Int,Char,Float,Double,Long,Short,Boolean
 - Scala 集合:数组,向量
 - Scala 映射:键值对
 
Scala 表达式
和其他编程语言一样,Scala 表达式也遵循类似的数字、布尔和逻辑表达式。一些常见和基本的表达包括在谷歌 colab 笔记本中。
// Syntax
val <identifier>[: <type>] = <expression>
var <identifier>[: <type>] = <expression>// Comment out one line
println("Hello Scala")// sample expression
var x = 2 * Math.sqrt(10) / 5
Scala 函数
Scala 是一种面向对象的编程语言,你可以按照同样的风格编写函数。下面是在 Scala 中定义函数的语法。你可以通过本博客附带的 google colab 笔记本练习真实的例子。
def <identifier>(<identifier>: <type>[, ... ]): <type> = <expression>
下面给出了一个将两个整数相乘并输出整数的函数示例。
def multiplier(x: Int, y: Int): Int = { x * y }
Scala 类和对象
在面向对象编程中,类被认为是非常有用的,对于 Scala 也是如此。对于使用 Scala 的程序员来说,类可以处理大数据和复杂的代码结构,使事情变得更简单。像其他语言一样,你可以用 Scala 写类。下面是一些例子。下面是一个最小的类示例
class User
val user1 = new User
Scala 类之旅是用 Scala 编写类的快速指南。谷歌 colab 笔记本中给出了更多的例子。
导入包
像其他语言一样,您可以在 Scala 中导入原生包和第三方包。java 和 python 的语法基本相同。
import Array.
Scala 中的并行处理
Scala 的主要目标是处理大型数据集。为了实现这一点,Scala 提供了一个非常简洁的并行处理解决方案,只需要最少的代码修改。如果您来自 Python,多处理很难设置,并且经常会导致意想不到的结果和失败。Scala 对多处理有更好的支持。在其他操作中,filter和map是并行处理时最常用的。下面是一些例子。
谷歌 Colab 笔记本
我准备了一个功能性的 Google colab 笔记本。请随意使用笔记本进行练习。
现实项目结论
在这一集里,我们学习了 Scala 的基础知识,并通过练习涵盖了以下关键概念。
- 在 Google colab 中运行 Scala
 - 基本 Scala 数据类型
 - Scala 函数和类
 - Scala 中的并行处理
 
在下一集,我们将使用 Google colab 了解 Scala 的 spark。
参考资料/阅读/链接
Scala Docs-https://docs.scala-lang.org/tour/tour-of-scala.html
https://www . Lynda . com/Scala-tutorials/Scala-Essential-Training-Data-Science/559182-2 . html
用 Scala 和 Spark 实现数据科学和机器学习(第 2/03 集)
SCALA SPARK 机器学习
Scala API 的 Spark

Spark 的发明者选择 Scala 来编写底层模块。在使用 Scala 和 Spark 的数据科学和机器学习(第 01/03 集)中,我们在使用 Google Colab 环境时讲述了 Scala 编程语言的基础知识。在本文中,我们将了解 Spark 生态系统及其面向 Scala 用户的高级 API。和以前一样,我们仍然使用 Spark 3.0.0 和 Google Colab 来练习一些代码片段。
什么是阿帕奇火花?
Apache Spark 是一个统一的计算引擎和一组用于在计算机集群上进行并行数据处理的库。截至本文撰写之时,Spark 是针对这一任务开发的最活跃的开源引擎;使其成为任何对大数据感兴趣的开发人员或数据科学家的实际工具。Spark 支持多种广泛使用的编程语言(Python、Java、Scala 和 R),包括从 SQL 到流和机器学习等各种任务的库,可以在从笔记本电脑到数千个服务器集群的任何地方运行。这使它成为一个易于启动和扩展到大数据处理或超大规模的系统。

我强烈推荐阅读 Apache Spark 和 Delta Lake Under the Hood 快速参考手册。这是一个 45 页的文档,包含 Scala 和 pyspark APIs 中的示例,阅读时间不会超过 30 分钟。
为什么要用 Spark 进行机器学习?
作为一名数据科学家,我们可以提出这样一个问题“Spark 对于机器学习任务的重要性是什么?”随着电子设备、社交媒体平台和高级 IT 系统使用的增加,数据正以前所未有的水平产生。此外,由于廉价的数据存储,客户很乐意收集大数据来提取价值。机器学习模型已经得到证明,并为企业更好地理解和制定未来扩张战略而工作。就获取大数据而言,Spark 是机器学习的事实上的选择,可以通过收集大量数据来建立模型。
DataFrame API 是机器学习最重要的高层 API。Spark 的 MLlib 放弃了对 RDD 的支持,转而支持 DataFrame API。
Spark 中的 Scala API
Scala 被选为编写 Spark 引擎的核心语言。但是,Apache Spark 提供了 Java、Scala、Python 和 r 的高级 API,在本文中,我们将使用 spark 3.0.0。
下面是在 Google colab 中获取 Scala 和 Spark 模块的命令
// Run below commandsimport $ivy.`org.apache.spark::spark-sql:3.0.0`
import org.apache.spark.sql._import $ivy.`sh.almond::ammonite-spark:0.3.0`
Spark 有两个重要的抽象,Spark 上下文和 Spark 会话。使用下面的代码,我们创建一个 spark 会话和上下文。
import org.apache.spark.SparkContextimport org.apache.spark.SparkConf
通常,当运行 spark 时会有很多警告,使用下面的命令,你可以关闭它们。
// TIP: Turn off the millions lines of logsimport org.apache.log4j.{Level, Logger}Logger.getLogger(“org”).setLevel(Level.OFF)// define spark session
val spark = {SparkSession.builder().master("local[*]").getOrCreate()}// Define Spark Context
def sc = spark.sparkContext
用 Scala 点燃 RDD
弹性分布式数据集(RDD)是与 Scala 密切相关的 Spark 数据结构的最常见抽象。它非常类似于 Scala 的原生并行特性。让我们用 Scala 写一些关于 RRD 的片段。
// Spark RDDimport scala.util.Random// Define variable in Scala
val bigRng = scala.util.Random.shuffle(1 to 100000)// convert Scala variable to spark RDD
val bigPRng = sc.parallelize(bigRng)
你可以在bigPRng上应用很多操作,它会在 Spark 上运行。
// calculate the mean of the population
bigPRng.mean// Find the min of the population
bigPRng.min// Find the stanndard deviation of the population
bigPRng.popStdev
在 RDD 的每个元素上应用函数非常类似于 Scala 并行map函数。
// Map function on RDD, similar to Paralell in Scalaval bigPRng2 = bigPRng.map(_ * 2)// Scala function function to apply on RDDdef div3(x:Int) : Boolean = {val y:Int=(x%3); return(y==0)}
val bigBool = bigPRng2.map(div3(_))
Scala 中的 Spark DataFrame API
在前面的章节中,我们已经包括了关于 RDD 以及如何使用 RDD 进行并行计算的例子。spark 中另一个流行的 API 是 Dataframe。从数据科学家的背景来看,DataFrame API 可能更有意义。然而,有一个主要的区别是如何火花数据帧和熊猫数据帧在引擎盖下操作。
Spark 数据帧可以存在于多个物理机器上,因此它们的计算是以分布式方式执行的,这与 pandas 数据帧相反。
Spark MLlib 将在 DataFrame API 中实现。
让我们学习一些 Spark DataFrame API 的基本技巧,它们对机器学习任务非常有用。
通读 Google colab 的第 0 部分,了解以下片段的数据准备。
// Read the .txt file
val df_emps = spark.read.option("header", "true").csv(data_dir + "employee.txt")// print the schema
df_emps.printSchema()// show top 10 records similar to df.head(10) in pandas
df_emps.show(10, false)
阅读第二张表格
// Read the .txt file
val df_cr = spark.read.option("header", "true").csv(data_dir + "country_region.txt")// print the schema
df_cr.printSchema()// show top 10 records similar to df.head(10) in pandas
df_cr.show(10, false)
阅读第三张表格
// Read the .txt file
val df_dd = spark.read.option("header", "true").csv(data_dir + "dept_div.txt")// print the schema
df_dd.printSchema()// show top 10 records similar to df.head(10) in pandas
df_dd.show(10, false)
合并是 Spark 相比熊猫最常见最高效的操作之一。
// Merge all three tables
val df_joined = df_emps.join(df_cr, "region_id").join(df_dd, "department")
谷歌 Colab 笔记本
我准备了一个功能性的 Google colab 笔记本。请随意使用笔记本进行练习。
有关更多示例,请参考 Spark 官方文档
现实项目结论
在这一集中,我们学习了 Scala 的 Spark 基础知识,并通过练习涵盖了以下关键概念。
- 在 Google Colab 中运行 Scala
 - 火花的基础
 - Spark 的 RDD 与 Scala
 - Sparks 的 Scala 数据框架 API
 
下一集,我们将学习使用 Google Colab 运行时的 Spark 和 Scala 的机器学习模型。
参考资料/阅读/链接
Scala Docs-【https://docs.scala-lang.org/tour/tour-of-scala.html
https://www . Lynda . com/Scala-tutorials/Scala-Essential-Training-Data-Science/559182-2 . html
Spark 2.0 中的 SparkSession 提供了对 Hive 特性的内置支持,包括使用…
spark.apache.org](http://spark.apache.org/docs/latest/sql-getting-started.html)
https://databricks.com/p/ebook/apache-spark-under-the-hood
数据科学和“数学人”的神话
数据科学继承了数学中的错误观念,即只有特别有天赋的人才能做到,但与数学一样,任何人都可以学习它。

图片来自 Andrea Piacquadio
“数据科学是可行的,”EPIC 2018 年檀香山会议的一名与会者会像口头禅一样惊呼。该会议是为商业人种学家和 UX 的研究人员举办的,他们有兴趣了解数据科学和机器学习并将其集成到他们的研究中。她特别试图解决她注意到的一个趋势——我也看到了:定性研究人员和其他所谓的“非数学人士”经常认为数据科学对他们来说太技术性了。这似乎最终植根于关于数学和数学相关领域的文化神话,如计算机科学、工程和现在的数据科学,与她的说法类似,我在这篇文章中的目标是讨论这些态度,并表明数据科学,像数学一样,是相关的和可行的,如果你这样对待它。
“数学人”
在美国,许多人都有一个隐含的“数学人”的形象:一个据说天生在数学方面有天赋的人。许多不认为自己符合这种形象的人只是谴责数学根本不适合他们。然而,认为有些人天生就能做数学而不能做数学的想法是错误的,它阻止了人们努力变得擅长这门学科,即使他们可能喜欢和/或擅长这门学科。
生活中的大多数技能,包括数学技能,就像肌肉:你并不是天生就拥有或缺乏这种技能,而是你的技能随着你练习和完善这种活动而发展。任何人都可以发展一项技能,如果他们足够练习的话。

图片来自安托万·道特里
人类学、社会学、心理学和教育领域的学者已经记录了数学是如何被含蓄地和明确地描绘成一些人能做而一些人不能做的事情,尤其是在小学的数学课上。从童年早期开始,我们就含蓄地、有时明确地了解到,有些人天生擅长数学,但对其他人来说,数学根本不是他们的强项。一些人内化了他们在数学方面的天赋,因此花时间练习足够的时间来发展和完善他们的数学技能;而另一些人认为他们不会数学,因此他们的数学能力停滞不前。但这根本不是真的。
任何人都可以学习和做数学,如果他或她练习数学,培养数学思维。如果你不培养你的数学肌肉,那么它会变得不发达,然后,是的,数学变得更难做。因此,作为一个残酷的讽刺,一个人内心深处认为他或她不会数学可能会变成一个自我实现的预言:他或她放弃发展数学技能,这导致其进一步发展不足。

图片来自迈克·劳伦斯
类似地,我们制造了另一个错误的神话,即精通数学(或数学相关领域,如计算机科学、工程和数据科学)的人通常不具备很强的社交和人际沟通技能。这种刻板印象的根源在于我们如何看待数学和逻辑思维,而不是数学家、计算机科学家或工程师的实际特征。对数学家、计算机科学家和工程师的社交技能进行研究的社会科学家发现,他们在社交和人际交流技能方面与世界上其他人没有明显区别。
定量和定性专业
有些人天生擅长数学,而这些人并不具备强大的社交和人际沟通技能,这种观点导致了定量和定性社会研究在学术和专业背景下的分化。这些态度助长了一种错误的想法,即定量研究和定性研究是不同类型的人的不同技能组合:所谓的定量研究只能由“数学人”完成,而定性研究只能由“人”完成。它们突然变成了独立的专业,尽管社会研究本质上涉及两者。这种分裂不必要地扼杀了对人和社会的真实和全面的理解。
在专业和商业研究背景下,定性和定量研究人员应该相互合作,并最终通过这个过程,慢慢学习彼此的技能。如果做得好,这将激励研究人员培养数学/定量和人际/定性研究技能。

图片来自瑞安·雅各布森
它将奖励发展这两种技能并在研究中加以利用的专业研究人员,而不是鼓励研究人员专攻其中一种。它还可以鼓励大学要求对两者进行深入培训,以培养学生成为未来的工人,而不是要求学生在促进一个方向而不是另一个方向的学科中进行选择。
然而,合作只是第一步,它的成功取决于它是否最终导致这些本应独立的技能组合的整合。通常,当定性和定量研究团队一起工作时,他们大多是独立工作的——定性研究人员负责项目的定性方面,定量研究人员负责项目的定量方面——从而加强了他们之间的假定区别。相反,这种合作应该包括定性研究人员通过实践这种方法发展定量研究技能,定量研究人员同样发展定性技能。
结论
任何人都可以发展数学和数据科学技能,如果他们练习的话。人种学和其他定性研究所需的人际交往技巧也是如此。将它们描述为独立的专业——即使它们聚集在一起在一个研究项目中完成各自的专业部分——函数扼杀了它们作为个人的单一工具集的集成,并强化了我们一直教导自己的错误神话,即数据科学是数学、编程或工程人员的,而人种学是“人”的这种分离扼杀了整体的和真实的社会研究,而社会研究不可避免地涉及定性和定量的方法。
您可以在这里找到原始出版物:。其余的文章请随意查看:【http://ethno-data.com/。
也感谢《数据科学》杂志发表这篇文章。关于他们工作的更多细节,见 本 。
数据科学在绩效营销中的应用
行业笔记
那么,你是数据科学家?但我以为你在市场部工作!
每一个。单身。时间。当我告诉别人我是一家旅游巨头市场部的数据科学家时,得到的反应是这样的。最近,我在网上看到很多文章,提到“利用人工智能和人工智能推动基于绩效的最佳投资和销售”。但还不足以揭开数据科学在这一领域的确切应用。AI 和 ML 是非常宽泛的术语,用来解释数据科学如何帮助企业优化营销支出,并在行业中获得竞争优势。
那么,我们来谈谈吧。用一个真实的生活用例——从数据科学的角度理解绩效营销中的业务问题,然后看看“AI 和 ML”的工具如何帮助解决它。希望这将有助于揭开数据科学家在数字绩效营销领域的神秘面纱。

词汇表的快速复习
- 点击—点击至平台:网站/应用程序/网络应用程序
 - 转化——新用户在平台上做出令人满意的行为,如点击、购买、滚动——任何能为企业带来价值的行为
 - 点击进入——当用户点击某物进入你的网站/应用程序时
 - 点击-用户最后一次点击,将他们带到另一个网站/应用程序
 - 搜索引擎:任何你用来搜索网络的东西。但在这里,我们谈论的主要是谷歌,必应,雅虎,Yandex 等。
 
商业问题
搜索引擎营销(SEM)是不同企业用来为其产品带来更多流量的绩效营销渠道之一。SEM 广告是你在谷歌、必应、雅虎等搜索引擎上点击回车后,在有机搜索结果之前看到的广告。
大多数 SEM 广告在拍卖系统上工作,你必须对与你的业务相关的每个搜索项出价,如果你在拍卖中赢得了一个位置(通常每个搜索有 2-3 个 SEM 广告,或者更多,取决于你所在的地区和你使用的搜索引擎),那么你将支付与你的出价相等或更低的费用,这取决于搜索引擎遵循哪个拍卖系统。
现在,对于一个大企业来说,你可能会处理数百万个你想要竞价的搜索词,但你也想通过竞价来优化这些搜索词(关键词)的利润和流量(访问你的网站/应用程序/网络应用程序)。一种方法是手动设置和更新每个关键词的竞价。另一种方法是查看“人工智能和人工智能”解决方案,根据每个关键词给你的业务带来的价值来帮助你优化投资,加入一些战略性商业决策,以关注流量和投资利润。那么,让我们开始吧!
“人工智能和人工智能”解决方案
让我们从数据科学的角度来看这个业务问题(我能感觉到数据科学家们兴奋得容光焕发)😆
只要在问题中加入人工智能,这个世界就又是阳光和彩虹了!🌈

马库斯·温克勒在 Unsplash 上的照片
你有每个关键词的所有成本和点击数据,你有一个清晰的绩效营销商业策略,你所要做的就是使用一个现成的闪亮算法来预测每个关键词给企业带来的价值,并相应地设定你的出价。数百万个关键词。
很简单,对吧?差不多了。😉
让我强调一下,由于多种原因,这是一个相当具有挑战性的问题:
- 你必须挖掘的数据的庞大规模,推动你走向“大数据”,并需要为你建立整个基础设施,甚至开始模拟关键词值
 - 数据本身的稀疏性给你的模型增加了更多的噪音而不是信号,你必须在如何分割、切割和聚集数据以获得一些合理的数据集方面有真正的创造力
 - 这里的稀疏性有两个方面:由于搜索词的长尾性质(一些搜索词比其他一些不知名的搜索词更受欢迎)和转化率本身——并不是这些 SEM 广告的每次点击都会转化为购买
 - 由于数据的稀疏和易变性质,评估指标很难选择:我们是预测对最近没有点击的关键词出价 0 还是值?如果是这样,在这个膨胀的数据集中,什么样的误差度量是有意义的?
 - 有了可行的数据集、合理的评估指标和某些建模决策,您就可以继续尝试适合用例的各种建模技术,并在缩小到几个之前进行离线比较,以便在测试和控制设置中进行现场测试😄
 
一旦你满意地(笑)得到了一个模型来预测你的业务的每个关键词的价值,你仍然必须考虑:
- 拍卖中竞争者出价变化的模型效应?还记得二价拍卖系统吗?
 - 模拟季节性?在不同的地区。不同的夏季或冬季旅行关键词。在日冕时期和平常时期。你明白了。
 - 如何知道自己是否达到了最佳投资水平?
 - 你如何知道你没有错过为平台带来更多用户的机会?
 
诸如此类。
但是通过利用“人工智能和人工智能”的力量😏—这些问题可以通过制定基于数据的决策和更接近业务目标来逐一解决。
解决方案对业务的影响
不仅仅是阳光和彩虹,这对业务也有明显的影响——通过利用大数据基础设施、数据科学能力、统计测试和分析监控,我们帮助持续优化每年数亿欧元的营销投资,并为用户和业务带来更多价值。
没有什么比令人震惊的数据挑战更能让令人讨厌的数据科学家从床上爬起来,这一挑战对商业和全世界数百万用户产生了如此巨大的影响!
结论
这篇文章中的用例只是数据科学或“人工智能和人工智能”解决方案如何应用于优化营销工作的一个例子。它还有很多令人兴奋的应用:客户终身价值(CLV)建模,特别是针对 SaaS 企业,不同营销渠道的归因模型,销售/流量预测等,这些都伴随着一系列令人兴奋的挑战!😉
所以下次当你听到数据科学和市场营销在一起时,你至少知道一些相关的点!😎
我写关于科技产品、数据科学、市场营销、产品管理和领导力的文章。
- 如果你想跟随我的学习之旅,你可以在媒体或 linkedin 上关注我。
 - 如果你想知道我在 medium 上的文章,请使用 medium 的订阅功能!
 - 如果你愿意支持我的写作,你可以请我喝杯咖啡。 ☕️
 
作为代码的数据科学

Scrum 板,照片由i̇rfan·西姆萨尔在 Unsplash 上拍摄
像构建 IT 项目一样构建人工智能项目
很多文章都是关于人工智能或数据科学的主题,以及 IT 产业化的问题。也有很多工具来处理这个问题,从几乎没有代码的方法(datataiku、 Rapid Miner 、 Knime 、sales force Einstein Analytics、 SAP Analytics 等等。)或多或少的成功,以及一些接近代码的工具(凯德罗、 DVC 、达格斯特、 MLflow 等。).
如果所有这些工具都有它们的优势,我真的不太喜欢它们,因为我认为一个人工智能项目首先是一个 IT 项目,意味着代码。
作为代码的数据科学
免责声明:在这篇文章中,我不包括云中可用的人工智能托管服务,如 GCP 人工智能平台的工具,如果你对所选的提供商有足够的技能,这些工具可以很容易地投入生产(但有一定的限制)。
如果一个企业把一个 AI 项目当成一个 IT 项目,就会跨越一个心理障碍,应该去神秘化这类项目。事实上,组织可能会将人工智能项目视为一个 IT 项目:当构建一个 web 应用程序时,就建立了一个团队,例如后端开发人员、前端开发人员、产品负责人等。,其中需要提到的技术配置文件来处理这种应用程序的技术部分。对于一个人工智能项目,例如,用数据工程师取代后端开发人员,用数据科学家取代前端开发人员,保留你的产品所有者,你就在这里:除了团队的技能和商业目标,项目的过程遵循相同的模式。例如,如果你使用 Scrum 作为你的敏捷框架进行日常开发和交付,你应该能够在你的 AI 项目中使用它。当然,在人工智能项目中有一些特殊性,可能比【经典】 IT 项目更不常见。但是即使是【经典】 IT 项目也有其特殊性:一个基于 PHP 和 JS 技术的在线零售网络应用并不像用 C++编写的物联网嵌入式应用那样涉及相同的团队概况。人工智能项目也是如此。
简单的数据科学架构
在这篇文章中,我将展示一个小型架构和一些代码,给出一个最终的人工智能解决方案投入生产,比方说对于“中间数据”(不是大数据,意思是少于几 TB)和对于批处理。

图一。简单的数据科学架构
具有内部架构(图 1。),我们拥有人工智能解决方案所需的一切:
- 气流分布式架构:专用服务器(使用 Celery executor 的主服务和工作服务)+队列任务服务服务器(Redis)
 - PostgreSQL 数据库存储气流元数据、超集元数据和一些数据项目
 - 用于处理数据集文件(csv、拼花等)的 MinIO 本地对象存储。)和模型持久性
 - 提供一些数据可视化的超集服务器
 
要运行下面的工作流代码示例,所有这些服务都在同一服务器上的沙盒环境就足够了,这里提供的代码不需要 MinIO 和 Celery,它们分别由本地文件系统和本地执行器代替(如果应用了一些数据治理,例如备份系统或 IT DRP,这对于小型 AI 项目和中级 SLA 来说完全没问题)。
数据科学用例

Florian Olivo 在 Unsplash 上拍摄的照片
用来说明我的文章的用例是基于法国 EGC 2017 年学术挑战:它由一个预测任务组成,根据法国格勒诺布尔市(左图)的绿地相关数据来确定一棵树是否有缺陷。
数据包含种植年份、树种、地理位置、树木直径或发育阶段等特征。
这里不讨论数据科学部分,因为获得好的性能很简单(仅供参考,挑战使用的分数是准确性和 F 分数)。将使用两个数据集:一个用于训练,一个用于评估性能。
代码部分
为了方便人工智能项目中的代码开发,我将我的东西打包成一个 Python 库, DSBox ,你可以免费使用。
V. Levorato 制作的包装。该软件包提供:Apache Airflow 的特定操作员,以便管理数据…
github.com](https://github.com/vlevorato/dsbox)
我在这里只集中讨论一揽子计划中的运营部分。这一部分分为两个主要部分:
- 气流数据运算符
 - 数据单元
 
基本上,气流操作员是没有国籍的。一旦任务完成,日志分开,没有状态被保留,你不能直接在任务之间传递信息,即使在某些情况下可以使用一些本地机制( XCom 变量或入口/出口)。数据操作符简单地覆盖气流基本操作符,包含一个或两个数据单元管理输入和/或输出数据流(图 2。).

图二。数据运算符结构
在谈论 IT 生产之前,作为一名数据科学家,当我第一次处理一个问题时,我主要是在 Jupyter 笔记本上操作熊猫数据帧。如果我尽全力编写一个分解的、结构化的和解耦的代码,如果我想让它投入生产,我显然不想重写我的所有工作。这就是数据操作符的用途:编写一个函数,将数据帧作为输入参数,并返回一个数据帧。它可以处理其他类型的数据帧(Dask、Vaex),但是为了简单起见,我更喜欢在本文中关注 Pandas 数据帧。
如前所述,数据操作符使用的函数接受一个输入数据帧,进行一些处理(这里是一个非常简单的fillna操作),并将结果作为数据帧返回。为了完成整个工作,我需要首先定义组成输入和输出数据流的数据单元。假设我需要读取一个带有字符“;”的 CSV 文件作为分隔符,并希望将结果写入一个拼花文件:
我现在可以编写一个标准的气流 DAG 程序,它有一个由我的数据操作符定义的任务。
完整的人工智能解决方案
让我们回到我们的树病预测用例。最终导出到 Postgres 数据库的完整工作流代码可以在这里找到。我们的 DAG 如预期的那样被气流调度程序很好地解释(图 3。).

图三。Airflow UI 中的树病用例工作流
我不会输入最终 DAG 的每个 ML 任务的细节(图 4。),因为你可以在我的 GitHub repo 上探索完整的代码,因为它遵循经典的数据科学模式(加入、清理、特征工程、训练、预测、测量性能、展示结果)。最重要的是,主要思想是通过数据单元显式声明所有数据集读写操作。是的,我以前做过很多爪哇☕️。所有操作符都不读取和写入数据,其中一些只是读取,例如适合模型的“Model _ learning”任务,并且不写入任何数据,只写入将由“Model _ prediction”任务使用的模型本身的序列化。为了避免将数据路径耦合到工作流程序,应该使用元数据管理文件或工具来避免硬编码路径。
注:SubDagOperator此处仅用于教学目的,不建议在生产中使用。

图 4。树木病害用例 DAG
数据展示
为了最终确定用例,需要向业务公开数据,而所提出的体系结构恰恰提出了 Apache 超集来实现这一点。我创建了一个非常简单的仪表板(图 5。)的地图,其中测试数据集的每棵树都带有预测的疾病标签(0 或 1 ),地图框布局自动生成一些聚类,这取决于放大的方式。(差的)旭日图给出了预测病树的比例。

图五。通过 Apache 超集实现数据可视化
如果从 IT 的角度来看,让一个人工智能解决方案促进“走向生产”并不那么困难。
最后的想法
正如你所看到的,如果从 IT 的角度来处理这个项目,那么拥有一个人工智能解决方案来促进【走向生产】并不困难,即使在这篇文章中,几个元素被故意搁置(测试、CI/CD、元数据管理等)。).最后,它更多地是关于了解您的组织是否已经能够平稳地交付 it 应用程序。在所有衡量交付效率的指标中,时间(或频率)是其中之一:使用“数据科学即代码”模式,我能够每周交付一个新版本的产品,而且我在现实生活中也是这样做的。因此,首先,考虑频繁交付(如果需要的话),每月交付一次是一个好的开始。如果你已经这样做了,或者更快,那么恭喜你:你已经知道如何将一个人工智能项目投入生产。
更高级的 AI 架构概念将在以后的文章中讨论,因为这个解决方案不容易扩展,并且有一些限制。
数据科学是绿色的带子
数据科学对抗繁文缛节,新冠肺炎的故事。

你已经回家两个星期了,你开始意识到你的公司将会关闭一段时间。事实上,他们刚刚给你发了休假通知。
你花了太多的时间帮助孩子适应网上学校,你几乎没有时间意识到你的存款几乎花光了,你的信用卡余额稳步上升。
几周后,情况看起来更糟了。你勇敢地去了一趟商店,开始寻找食物捐赠的选择。
随着压力的增加,当你听到国会刚刚通过一项帮助法案时,你会松一口气。
你花了几天时间试图弄清楚在线申请系统。他们也需要文件,但你不能上传。他们允许你传真,但是谁有传真机?
一封电子邮件通知你,你必须和某人通话,但是电话线路已经忙了好几天了。
最后,您会收到一个电子邮件链接。当你点击它,一个网页告诉你,你的索赔已被拒绝。没有理由。
尽管如此,没有人会接你的电话。
你觉得崩溃了。你不知道你将如何支付你的账单或购买食物。
这是政府服务的一贯方式吗?
对许多人来说,这是过去几个月他们现实的一个版本。不幸的是,在很多情况下,这种体验是故意的。幸运的是,我们不必再这样下去了。
别担心,我是政府的,我是来帮忙的!
当前的形势已经提出了许多需要政府计划,尤其是安全网计划的例子。
当我们在新冠肺炎疫情经历接近破纪录的失业率时,立法者颁布了旨在为公民和企业提供救济的计划。在许多情况下,应用程序和需求是复杂的、不清楚的,并且难以导航。
有时这是因为陈旧的基础设施,缺乏人力资源,以及不知情的申请人。在其他情况下,这是因为民选官员特别设置了所谓的行政负担,使得公民参与这些项目的成本更高,难度更大。(当我写这篇文章时,《纽约时报》刚刚发表了一篇关于失业保险的优秀文章。)
失业保险、食品补贴、医疗保险援助和小企业贷款的预期接受者面临着令人困惑的要求、过时的申请流程以及缓慢的处理和裁定工作流程。
你可能会翻着白眼说,“好吧,那只是政府”。但重要的是要关注这样一个事实,其中许多问题本来是可以避免的,而且其中一些问题实际上已经存在,使这些程序难以访问。正如他们所说,繁文缛节“是一种功能,而不是一个缺陷。”
什么是管理负担?
越来越多的文献围绕着项目管理中的行政自由裁量权。
对于政治领导层如何控制大量公共部门,人们有了新的探索,这些探索早已超越了就立法文本进行辩论的阶段,也超越了将程序写入法规和政策手册的阶段。(如果你想要一本关于行政负担的精彩介绍,我推荐莫伊尼汉和赫德医生的书)
简而言之,行政负担是指为获得政府项目或福利而需要付出更多努力的过程、程序或制度。
例如,法律可能要求只有收入达到一定数量的人才有资格享受这种福利。行政负担可能是你必须提供纳税申报单来证明你符合要求。
如果官员想增加行政负担,他们可以要求纳税申报表、工资单、银行账户信息、前雇主的签名和公证信函,以及你的签名证明,证明你说的是实话。
一个常见的理由是,如果没有严格的证据和申请验证标准,太多的人会滥用该系统,浪费纳税人的钱。
在这里列出任何一个政客与“福利女王”或滥用体制的个人的轶事。
另一个理由是,应用程序需求必须确保只有那些最需要好处的人才能真正完成这个过程。这种观点认为,不是“真正需要”的人在遇到困难时会放弃。这节省了纳税人的钱,但也有助于安抚那些不希望自己的税款落入他人之手的人。
我们需要认识到,项目的实施方式通常是基于价值观和政治的。不幸的是,很多时候这是在没有公民参与或透明度的情况下完成的。我们现在看到一个又一个例子,说明这是如何在公民最需要的时候辜负了他们。
数据科学与政治的平衡
无论我们多么渴望“数据驱动的决策”、“基于证据的决策”和“管理科学”,我们都必须考虑到这样一个现实,即在我们的国家——以及许多其他国家——关于采取哪些政策和计划的最终决定是由政治选举产生的领导层做出的基于价值的决定。
再说一次,这与我们的民主并没有内在的冲突,许多人会争辩说,有必要允许民选领导人继续领导行政部门,以确保人民的意志在整个行政阶段得到贯彻。
然而,如果公民不能充分理解这些影响,他们参与这一进程并向当选官员提供见解和反馈的能力就会受到限制。这与普通公民脱离大多数政府内部工作没有什么不同,但由于没有正式的机制或行政负担的强制透明度,这种情况有所增加。
数据科学可以提供更好的方法
数据科学吸引我的一个特点是,许多手动任务既可以自动化,也可以改进。我所说的改进是指变得更有效率、更有效、更准确,并且能够产生更大的影响。
这些都是公共部门关注的完美领域。与私营部门不同的是,在管理项目的方式上,人们一直在寻求效率。
然而,与私营部门不同,也有一些限制和考虑。这些要求包括隐私法、行政法要求、监督和透明度要求。正如我们已经讨论过的,另一个重要的制约因素是公共部门也是一个政治部门。
正如希尔德布兰特所描述的,数据科学在政府部门有两种用途:代码驱动的监管和数据驱动的监管。在法规驱动的监管中,机构使用数据科学技术,根据法规自动做出决定和裁决,这些法规是通过对福利要求的法律理解而形成的。例如,一个机构与法律和政策部门合作,设计一个计算机程序,使申请、裁决和福利发放过程自动化。
该程序代码由法律法规以及程序的管理负担决定。就像法律法规被公开辩论一样,这些决定可以也应该以透明的方式呈现给所有利益相关方,并且最好允许反馈。
在数据驱动的法规上,代码来源于先前的裁决或对法律法规的解释(这里想想无监督的机器学习程序)。这不仅有可能掩盖决策的先验偏差,也有可能掩盖次级监管行政负担的输入和影响。认识到这两种不同的用途是很重要的,因为它们需要不同的考虑和不同的受众。
数据科学可以成为我们需要的“绿带”
代码驱动的监管是决策的自动化,这些决策是基于规则的,并且可以被编程。这些算法和程序的构建需要更多的设计和前期规划,因为它们必须符合法律和法规,但一旦构建完成,这些系统将接管人类裁判的任务,并更有效地做出更有效的决策。
我喜欢把这看作是政府的“自动化枯燥的东西”,这有可能给我们的政府项目以及政策辩论带来显著的附加值。最终,这将大大提高我们帮助同胞的能力。
有例子表明,政府的目标是尽可能多地消除负担。这就是所谓的绿带。使用数据科学技术的代码驱动的监管可以为程序创建许多绿色的带子。
我们在人口普查中看到了这一点,人口普查正在积极尝试将大部分过程自动化,并使人们尽可能容易地做出回应。这是因为当更大比例的个人参与人口普查时,政府(总体上)受益。
在新冠肺炎,我们也看到了一些很好的例子。例如,财政部试图通过使用以前和当前报税中的行政数据来实现现金援助流程的自动化。他们免除了大部分符合条件的公民填写任何类型的申请,允许政府使用现有的流程和信息实际管理福利。
显然,它并不完美。例如,它仅限于已报税的个人,未收到退款的个人必须填写补充信息,并且是对网站和信息交流的迭代响应和更新。但总的来说,这是大数据满足政府管理计划的可能性的相关示例。
消除行政负担的愿望和目标可以通过在政府中扩大使用数据科学以及政府内部的数据共享来实现。
在我们当前的例子中,如果国税局从社会保障计划中获得他们需要的所有信息,以及州的出生和死亡记录,那么事情会自动化得多,这样他们就不会试图向已故的人支付金钱,并且他们知道家庭是否有新的受抚养人。
其他例子包括失业索赔越来越依赖雇主报告的信息。如果我们可以依靠通过公司工资单和税务记录提供的管理数据,人们可能不需要主动申请。
绿色胶带示例
你收到了雇主的休假通知。当你担心你的下一步时,你收到了一封来自你所在州的失业机构的电子邮件,你的雇主也通知了你。
通知告诉您,您已经自动加入失业保险,等待确认信息的准确性。您点击提供的链接,并在几分钟内确认和更新信息。
过了一会儿,您会收到类似的食品援助和医疗保险援助福利通知,这些通知基于他们从失业中获得的信息以及您的税务信息和家属信息。
幕后的过程是喜欢政府机构的信息,自动裁定资格,并主动请求验证和自动支付。
自动化意味着快速准确地发放福利。由于与政府数据来源的联系,它变得更容易自动化反欺诈的系统。自动化流程解放了客户服务代表,让他们可以为少数有问题的人服务。
政治家(因此也是公民)仍然控制着什么项目存在,有多少福利,资格标准是什么。但是这些决定是公开的。
我们需要记住,数据科学是一种工具。这个工具也可以用于政治目的。它要么带来更多的繁文缛节和行政负担,要么成为一个强大的绿带创造者。
认识到这一点对于公共部门的数据科学家来说非常重要,对于公民来说也很重要,因为我们与民选官员接触并倡导政策和计划。
意识到并大声说出我们希望如何实施这些计划,与一开始就支持或反对该计划一样重要。
在你走之前
在当前的新冠肺炎危机中,有很多方法可以帮上忙,我希望你能这样做。如果你有兴趣志愿帮助公共部门更好地管理项目,我推荐像美国代码这样的组织。
初创公司的数据科学 vs FAANG 公司

图片来自 Unsplash
介绍
在一个日益科技化的世界,数据科学家和分析师的角色已经出现,他们的职责从优化 Yelp 评级到过滤亚马逊推荐和设计脸书功能。但是数据科学家到底是做什么的呢?这个角色的参数很少被严格定义,但是面向数据的工作已经成为所有技术公司成功的必要条件。
完整的职位描述很大程度上取决于公司的类型。当你从一家初创公司跳槽到一家中型公司或 FAANG(脸书、亚马逊、苹果、网飞、谷歌)时,你可能会发现自己面临一系列不熟悉的新任务。
但是什么类型的公司最适合你呢?答案在于认识到这些类型的公司之间的主要差异——工作类型、期望的经验、优先考虑的技能——所有这些都有助于更全面地了解这个角色到底需要什么。
创业公司

创业公司办公场所从 Unsplash
创业公司是指那些在快节奏的商业世界中迅速开发创新产品或服务的公司。美国小企业管理局(u . s . Small Business Administration)将初创企业正式描述为“通常以技术为导向且具有高增长潜力的企业”;指员工、收入或市场的高增长潜力。这类公司的独特之处主要体现在两个方面:工作的多样性和低员工数量。
工作的多样性
初创公司的数据科学职位涉及方方面面。它需要一个在数据工程、机器学习、分析、数据可视化以及传统上可能不被称为“数据科学”的工作方面拥有知识的百事通。
你可能会被要求参加营销会议,或者与工程师密切合作来部署模型和建立工程管道。在创业公司工作的最大好处是获得和发展多种技能,这在大公司很少见。作为一名初创公司的数据科学家,你要做好承担必须“解决”的问题的准备。这导致了大量的自学、自定进度、所有权和独立性。
低人数
因为初创公司的员工较少,随着公司的发展,获得晋升会容易得多。然而,人数少是一把双刃剑。员工较少的小公司通常资金较少,这意味着与大公司相比,平均工资较低。因此,一个常见的职业路径是从一家大公司开始,获得经验并获得更高的薪水,然后过渡到一家初创公司,获得更多样化的经验和职业发展。
尽管在初创公司的职业阶梯可能更容易攀爬,但你不会有那么多工作与生活的平衡。创业的速度越来越快,导致环境不断变化,充满活力。虽然成为一名董事可能在几年内实现,但建立一个成功的企业所需的技能需要更多的时间和毅力来磨练。
FAANG 公司

来自教育性的 FAANG 公司标志
FAANG 是首字母缩略词,代表表现最好的五家科技公司:脸书、亚马逊、苹果、网飞和谷歌。这些科技巨头在四个主要领域与初创公司不同:效率、流程、责任和职业轨迹。
注意:在本节中,我们仅指 FAANG 公司的数据科学家,但是所描述的角色也代表其他拥有大量员工的大型科技公司的数据科学职位。
效率
全球科技超级大国拥有数万名员工,他们都执行各自独特的任务。工作产出被精确地衡量,团队成员被分等级。从这个意义上说,工作生活充满了秩序——任务定义明确,员工向一个老板报告,员工的成功是可以衡量的。与创业职位的流动性相比,这个职位更容易管理和理解。
过程
在一家经验丰富、管理良好的公司,从学术界或以前的工作岗位到这个职位的过渡将是无缝的。训练营是一种常见的资源,为未来的员工提供跨多个部门的必要技能。
责任
平均工作体验将围绕分析和创建仪表板。无论是分析有凝聚力的公司业绩,还是某项功能的成功,数据分析工作都非常简单。
职业轨迹
如前所述,在 FAANG 公司,职业发展通常更难。但是,做个体承包人(IC)可能更容易赚钱;这个角色通常需要深入研究优化和生产产品。职业阶梯与初创公司大不相同,爬到董事位置可能需要几十年的努力。
例如,亚马逊的典型职业阶梯可能是从商业分析师到商业智能工程师到数据科学家再到研究科学家,每个后续角色都有更高的薪酬。每个角色也有四个“阶段”:一级、二级、三级(高级)、四级(主要)。正如在这些公司的层级结构中所看到的,有一条清晰的晋升之路——但与初创公司的类似晋升相比,还有更多的阶段要“完成”。
中型公司

来自 Unsplash 的办公室
虽然确切的定义因行业和国家而异,但根据经济合作与发展组织的说法,一家中型企业通常拥有 50 至 250 名员工。这种类型的公司可以被视为介于初创公司和 FAANG 公司之间的中间地带。
随着初创公司的快速增长阶段趋于平稳,公司开始感受到市场和竞争对手的压力,中型公司会经历所谓的成长的烦恼在员工方面,在创业自由和 FAANG 结构之间实现了一种平衡。从这个意义上来说,虽然数据科学家的角色旨在适应不同的需求,但同时也有一组明确的职责需要履行。****
最后,当负面因素在一个平等的基础上平衡时,利益也会被分割。中型公司的数据科学家的平均工资将高于初创公司,但低于 FAANG 公司。晋升机会也介于初创公司和 FAANG 之间。虽然不能保证成为公司的主要贡献者;有了耐心和毅力,就有可能壮大一个团队,给公司带来巨大的价值。
摘要
你可能会问,“什么规模的公司最适合我?”
一个人理想的公司规模很大程度上取决于这个人的个人目标和优先事项——是薪酬、晋升还是多样化的体验?或者可能是所有的混合?尽管如此,鉴于数据科学革命在全球范围内持续发展,仍然有一个问题:“我如何找到数据科学工作?”
答案是:查看面试查询!
感谢阅读
- 如果你有兴趣成为一名数据科学家,请查看 面试查询 !
 - 查看我的 Youtube 频道 获取更多面试指南,以及解决问题的技巧&。
 - 在面试查询博客上找到更多数据科学面试准备资源,如 最佳数据科学面试书籍 和 Python 数据科学面试问题 。
 
原载于 2020 年 7 月 31 日https://www.interviewquery.com。
德勤的数据科学
苹果 | 谷歌 | SPOTIFY | 其他
伊恩·斯科特在 TDS 播客

背景照片由内森·奎洛兹拍摄
编者按:迈向数据科学播客的“攀登数据科学阶梯”系列由 Jeremie Harris 主持。Jeremie 帮助运营一家名为sharpes minds的数据科学导师初创公司。可以听下面的播客:
不同公司的数据科学看起来可能大相径庭,通常很难就数据科学家到底是什么这个问题达成一致意见。
这就是为什么与在不同组织(从初创公司到企业)应用其技能的数据科学家交流如此重要。了解数据科学家需要执行的各种角色和职责是提炼数据科学本质的唯一方法。
这就是为什么我想和伊恩·斯科特聊天,他是德勤人工智能部门德勤综合咨询的首席科学官。Ian 早在 20 世纪 80 年代末就在研究数据科学,当时他在哈佛大学攻读博士学位时,将统计建模应用于实验高能物理的数据。从那以后,他在许多公司担任战略职务,最近包括德勤,在那里他领导了重要的机器学习和数据科学项目。
我们的谈话集中在明确数据科学到底是什么,以及数据科学家团队如何高效地合作。以下是我最喜欢的一些外卖食品:
- 虽然大多数数据科学家倾向于使用类似的工具(Python、SQL、pandas、sklearn、jupyter notebooks、可视化工具等),但从高级职责的角度来定义数据科学比工具更有帮助。Ian 将数据科学家视为从数据中提供见解的人,以及可以将这些见解传达给非技术受众的人,而不是“可以建立神经网络的人”或“可以训练堆叠 XGBoost 模型的人”。越来越多的情况下,如果你想被录用,软技能是决定性的优势。
 - 具有高度技术背景的新数据科学家通常认为数据科学问题是技术问题。不幸的是,这远远不是真的:算法不能单独解决数据科学问题——如果它们解决了,那么数据科学就已经是一个完全自动化的职业了。需要商业和产品知识来弄清楚如何设计和选择你的功能,所以如果你是一个在分析或机器学习领域开始职业生涯的技术人员,你能做的最大杠杆作用可能是投入大量时间来了解你的公司如何赚钱,以及它如何为客户提供价值。
 - 咨询工作涉及到从一个客户到另一个客户的速度比一个内部数据科学家通常要快。这意味着加速是至关重要的,因为你需要足够快地开发不同问题的背景以达到有效。许多咨询公司已经发展出缓解这个问题的策略,通过确保具有深厚领域知识的合作伙伴通常能够帮助需要这种专业知识的用例。
 
你可以在 LinkedIn 上找到伊恩,在 Twitter 上找到德勤,或者在 Twitter 上找到我这里。
美国宇航局的数据科学
苹果 | 谷歌 | SPOTIFY | 其他
大卫·梅萨在 TDS 播客

编者按:迈向数据科学播客的“攀登数据科学阶梯”系列由 Jeremie Harris 主持。Jeremie 帮助运营一家名为sharpes minds的数据科学导师初创公司。可以听下面的播客:
机器学习不是火箭科学,除非你在 NASA 做。如果你碰巧在美国国家航空航天局做数据科学,你和我今天播客的嘉宾大卫·梅萨有共同之处。
大卫在 NASA 的职业生涯中,一直专注于优化 NASA 众多数据库中的信息流,并确保这些数据得到机器学习和分析的利用。他目前的重点是人员分析,包括跟踪美国宇航局员工的技能和能力,以发现那些有能力以新的或意想不到的方式满足该组织已经或可能发展的需求的人。
David 在数据库和建模方面都有丰富的经验。以下是我们谈话中我最喜欢的一些带回家的东西:
- 如果你想发展一套与众不同的技能,图形数据库是一个很好的关注点。它们出现在生产领域只有大约十年的时间,最近它们得到了更多的关注,因为它们在建模社交媒体和其他网络数据类型方面表现出色。
 - 除非你从事的是以产品为中心的工作(例如为用户建立推荐系统),否则数据科学家的产出通常不是模型或图表,而是教育。具体来说,你将培训那些希望做出数据驱动决策的领导者和管理者——这意味着你必须特别小心,以确保你的图表和模型不会被曲解。在某种程度上,你是一名翻译——这意味着你需要会说两种语言:分析和机器学习的技术语言,以及商业价值的语言。
 - 像 NASA 这样已经存在很长时间的组织,在数据科学方面面临着独特的挑战:他们往往有许多与现代工具和基础设施不兼容的遗留系统和旧数据库。在这种情况下,数据科学家必须考虑的一个关键问题是他们的数据库策略的稳健性:你最不想做的事情就是将你的数据存储在一个十年内都不相关的花哨数据库中。
 - 美国宇航局有数千名员工和数万名承包商。在这种规模下,他们面临的最大挑战之一是确保他们的员工能够解决与其技能和能力相匹配的问题。这就是机器学习和人员分析变得如此重要的地方。
 
路透社的数据科学,以及冠状病毒之后的远程工作
苹果 | 谷歌 | SPOTIFY | 其他
Nick Pogrebnyakov 在 TDS 播客

背景图片由肖恩·波洛克拍摄
编者按:迈向数据科学播客的“攀登数据科学阶梯”系列由 Jeremie Harris 主持。Jeremie 帮助运营一家名为sharpes minds的数据科学导师初创公司。可以听下面的播客
尼克·波格雷布尼亚科夫(Nick Pogrebnyakov)是汤森路透(Thomson Reuters)的高级数据科学家,哥本哈根商学院(Copenhagen Business School)的副教授,也是有经验的机器学习开发人员可以找到公司合同工作的市场 Leverness 的创始人。他是一个大忙人,但他同意在今天的 TDS 播客中与我坐下来,谈论他在路透社的日常工作,以及机器学习和数据科学的工作前景。
以下是我从聊天中获得的一些最大收获:
- 用于评估模型的指标必须具有商业意义,因此在设计它们时,您需要咨询主题专家(或者自己成为一名专家)。顺便说一句,这就是为什么我总是建议人们建立涉及他们很好理解的数据的个人项目(例如,如果你喜欢骑自行车,找一个关于自行车道的数据集)。展示你知道如何将商业问题转化为技术问题是绝对必要的。
 - 根据 Nick 的说法,行业研究角色和传统数据科学角色之间的最大区别是失败风险容忍度和获得结果的可接受时间范围,这两者对研究角色来说都更高。研究角色仍然是快节奏的,但有一种理解是,当你试图挑战极限并实现最先进的结果时,更多的实验和更花哨的策略是可以接受的。
 - 对于大型组织来说,拥有大量尚未开发但极具潜力的数据可供分析是相当常见的。他们面临的最大挑战是,由于他们的规模,进行数据分析的团队通常与管理和增长这些有价值的数据集的团队隔离开来,因此在这种情况下值得发展的一项技能是跨团队沟通的能力,这使您能够注意到关键数据资源何时未被利用。
 - 新型冠状病毒已经改变了企业的招聘方式,现在比以往任何时候都更倾向于远程工作。尚不清楚这一举措是否会是永久性的,但早期迹象表明,长期来看,这一势头可能会朝着这个方向转变。
 - 远程工作肯定有缺点,通常最好是在团队至少见过几次面之后。这就是为什么(当然是在疫情之前)我倾向于建议入门级数据科学家和分析师亲自参加工作,即使至少在他们工作的头几个月有远程工作选项。科技越来越多地使远程连接成为可能,但仍然没有任何东西可以替代面对面的连接。
 
你可以在 LinkedIn 这里找到尼克,或者在 Twitter 这里找到我。
在亚马逊 EMR 集群上使用 PySpark 实现大规模数据科学
理解大数据

你有没有遇到过这样的情况,你的计算机无法处理你试图处理的数据?我知道我有。嗯,所以你可能正在处理一个大数据,它很可能太大太复杂,无法由 CPU 上的一台机器来处理。那么,我们所说的大数据是指什么?多少数据才算大数据?嗯,我们可以无休止地争论这个问题——所以我们不要在这里争论了。相反,我们只能说,你有足够大的数据,而你的计算机正在努力处理它。希望你的机器不会冒出任何火焰或烟雾。玩笑归玩笑,这是一个非常常见的问题,解决它的最常见方法是在分布式计算平台上处理如此大的数据集。Apache Spark 是一个开源的并行计算框架,旨在支持在计算机集群上处理这样的大型数据集。
有一些不同的分布式计算平台提供商可供选择,一些流行的选择包括 Cloudera、Hortonworks、Databricks、Amazon AWS 和 Microsoft Azure。在本文中,我将向您展示如何在 AWS cloud 上为您的需求建立一个分布式计算平台,特别是 Amazon EMR。我们将使用 PySpark,它是 Apache Spark 的 Python API。
在 Amazon EMR 上设置 PySpark 之前,请确保您具备以下条件:
- 在 AWS 上创建帐户
 - 创建 EC2 密钥对
 - 创建 EC2 安全组
 
步骤 1:在 AWS 服务中找到 Amazon EMR
现在您有了一个帐户,浏览 AWS 服务并找到 EMR。下面是一个例子。

步骤 2:创建集群
一旦进入 EMR,找到显示“创建集群”的按钮并点击它。

步骤 3:转到高级选项
点击“创建集群”后,您将看到一个类似的页面,然后点击“转到高级选项”

步骤 4:软件和步骤
对于 EMR 版本,我选择 emr-5.31.0,因为这是在本文发布时的最新版本(不是测试版)。然后,我选择 Hadoop 和 Spark,因为这是我需要预安装在集群上来完成标记工作的另外两个软件。一旦选择了这些选项,就没有必要再去搞乱其他选项了,所以请继续操作,然后单击下一步。

第五步:硬件选择
在本节中,您将为集群的主节点和工作节点选择硬件类型。首先,在页面的上部,为实例组配置选择“统一实例组”。

然后向下滚动,找到如下所示的页面部分,并选择硬件类型。理想情况下,您的工作节点需要合理数量的 CPU 和内存。我选择 m5.xlarge 作为主节点和核心/工作节点,因为它们足以满足我对数据集大小的预处理需求。根据数据集和您想要实现的目标,您可以选择所需的正确的 CPU 和内存量。请注意,我请求了两个核心/工作节点实例。您可以根据手头任务的需要使用这个数量的实例。您还会看到任务节点显示在核心/工作节点下,您在本练习中不需要它们,因此可以忽略。

完成上述选择后,将其余选项保留为默认值,然后按下一步。
步骤 6:常规集群设置
在此部分中,选择集群的名称。你想取什么名字都可以。这取决于你是否选择日志记录,我通常会关闭它,因为它会存储 S3 的每一个 EMR 日志,这些日志往往会占用 S3 的空间。但是最佳实践建议让它开着。

将此页面上的其余选项保留为默认设置,然后单击 Next。
步骤 7:配置安全性
这一节很重要!在此部分中,您将配置两件事情:
- EC2 密钥对
 - 安全组
 
选择 EC2 密钥对和您之前创建的安全组,最后单击“Create cluster”

现在,在创建新的 EMR 集群时,您将看到如下页面

创建后,您的群集的状态将从“正在启动”变为“正在等待”,这意味着您的群集现在可以使用了。
步骤 8:在 EMR 上创建一个笔记本实例
现在您需要一个 Jupyter 笔记本来使用 PySpark 与您新创建的集群的主节点一起工作。为此,请单击左侧横幅上的“笔记本”,然后单击“创建笔记本”。

在下一页中,为您的笔记本命名,然后单击集群下的“选择”,然后在那里找到并选择您新创建的集群。最后,在 S3 上选择一个与笔记本相关联的位置来读写数据。请记住将“AWS 服务角色”保留为默认值。然后点击“创建笔记本”,瞧。

现在,您有了一个 Jupyter 笔记本,它连接到新创建的 EMR 集群的主节点,该集群预装了 Hadoop 和 Spark。您已经准备好在 Amazon EMR 集群上使用 PySpark 处理您的大数据。
警告:当你完成后,记得停止你的笔记本并终止你的集群!!!否则,您将在您的下一个 AWS 法案中产生巨大的成本!!!
享受使用 Amazon EMR 集群上强大的 Apache Spark 处理大数据的乐趣吧!
如果你觉得这篇文章有用,我很乐意在下面以鼓掌或评论的形式得到你的反馈。让我们在 LinkedIn 上联系
谢谢大家!
Shopify 的数据科学
苹果 | 谷歌 | SPOTIFY | 其他 | 剪辑
卡梅伦·戴维森-皮隆在 TDS 播客

编者按:迈向数据科学播客的“攀登数据科学阶梯”系列由 Jeremie Harris 主持。Jeremie 帮助运营一家名为sharpes minds的数据科学导师初创公司。可以听下面的播客:
如果你想知道数据科学的发展方向,了解它的发展方向会有所帮助。很少有人有这样的历史眼光,更少有人将它与对尖端工具的理解结合起来,这暗示了该领域未来可能采取的方向。
幸运的是,其中一位是 Shopify 的前数据科学总监卡梅伦·戴维森-皮隆。自 2012 年以来,卡梅伦一直沉迷于数据科学和估计理论,当时该领域仍处于独立发展阶段。他不仅在技术问题上,而且在招聘和团队建设方面都有很好的高水平观点,他非常友好地加入了我们今天的“走向数据科学”播客。
以下是我们谈话中我最大的收获:
- 微积分没有许多数据科学家认为的那么重要。计算机现在可以为我们计算导数和梯度,所以这个挑战已经被抽象掉了。当有疑问时,把你的时间投入到理解统计学和概率论上,而不是微积分。
 - 对于数据科学家来说,通过宁滨或粗粒化数据来丢弃数据中的大量信息是相当常见的做法。这方面的一个经典例子是净推介值(NPS ),它的计算方法是让用户从 1 到 10 给你的产品打分,把所有 8 到 10 的分数都算为正,把所有< 5 的分数都算为负,然后把这些分数平均出来。虽然有时有理由这样做,但这可能会浪费有价值的信息(例如,在 NPS 的情况下,用户提供的 7 分和 8 分之间的差异真的有那么大吗?).
 - 对于分析团队来说,在公司内部建立信任非常重要。他们的工作是帮助其他员工访问他们需要的数据或见解,这要求那些其他员工能够舒服地诚实和明确地描述他们的问题和需求。建立信任是第一步。
 - 随着工具的发展,数据科学家可以花更少的时间在团队工作上,人们越来越希望这些数据科学家能够沿着“商业价值”轴做出贡献。这是产品和商业直觉在数据科学中越来越受关注的一个重要原因。
 - 面试伴随着大量的噪音,对候选人和面试官都是如此。例如,卡梅伦从自己的经历中指出,在午餐前面试的候选人可能会因面试官的低血糖而遭受折磨,并得到更严厉的评价。同样,候选人可能不得不在现场漫长的一天结束时面试一位首席技术官,此时正是疲劳最严重的时候。因为这个过程很嘈杂,所以重要的是不要因为一次糟糕的面试而自责:这完全有可能是你受到了一次纯粹随机的打击!
 
夹子
2020 年必读的数据科学书籍
看看吧,你为什么要读它们?

Rafael Cosquiere 摄于 Pexels
“我们正在进入一个数据可能比软件更重要的新世界。”——
——蒂姆·奥雷利
数据科学产业的应用正在快速增长,并提供了一个非常有前途的未来。为了能够进入这一领域,一个人必须具备各种概念、技术,并对工作可用的各种工具有足够的经验。
有数以百计的资源,包括网上课程、网站、视频和书籍,可以帮助你掌握这门学科,因为乍一看这可能会让人望而生畏。在整篇文章中,我们将提到一些学习数据科学和相关技术的最佳书籍,它们将使学习变得轻而易举。
数据科学是让数据变得有用的学科
数据科学书籍
在本节中,我们将重点介绍各种数据科学书籍,涵盖所有技能水平,以巩固您的领域知识。这些书将被证明对帮助你学习这项新技能至关重要,它们会让你深入了解各种算法、概念、方法,以及支持的编程语言和及其相关包以充分利用它们。
免责声明: 本帖无附属链接。这篇文章仅供参考。
1.Python 机器学习简介:数据科学家指南
作者:安德烈亚斯·c·穆勒和萨拉·圭多
出版商 —奥赖利
难度等级:初学者
在这里获取图书——亚马逊

《用 Python 进行机器学习入门》一书的封面
机器学习是一种新的编程范式,一种向计算机传达你的愿望的新方式。它令人兴奋,因为它允许你自动化不可言喻的事物。
这本书以适合初学者的风格涵盖了各种各样的机器学习主题,向他们展示了如何轻松地开始构建自己的 机器学习解决方案 。它还详细介绍了学习和应用机器学习来解决常见问题的最佳实践,而无需学习高级数学课程。
这本介绍性的书涵盖了基础概念,以及算法和一些用于模型评估的高级方法和 scikit-learn,这是一个经过验证和测试的 Python 工具,它补充了这本书,提供了更多关于机器学习实现的实践经验。
2. R 代表数据科学
作者:哈德利·威克姆,加勒特·格罗勒蒙德
出版商 —奥赖利
难度等级:初学者
在这里获取图书——亚马逊
在线看书——https://r4ds.had.co.nz/

“数据科学的 R”一书的封面
R 是理解大量孤立数据的重要工具,本书旨在指导读者如何在数据科学中充分利用 R。本书涵盖的主题遵循数据科学的核心步骤,包括使用 R 编程语言对数据进行导入、整理、转换、可视化和建模。
这本书要求 R 的先验知识水平,它的包如 tidyverse 伴随着一定程度的足够的数字素养。虽然它没有涵盖数据科学领域的全部,但作者提供了大量额外的资源,可以广泛涵盖所包含的主题。
最近更新由克莱尔 d。人工智能创新的加速增长已经导致几个…
blog.digitalogy.co](https://blog.digitalogy.co/r-for-data-science/)
3.裸统计
作者:查尔斯·惠兰
出版商 — W. W .诺顿&公司;再版
难度等级:初学者
在这里获取图书——亚马逊

《赤裸裸的统计》一书的封面
这本书以数据科学为主题,通过将它们与真实世界的场景联系起来,解释了这个主题的核心概念。这本书旨在以喜剧风格传递来自统计世界的令人难以置信的内容,同时激励读者更深入地探究这个主题。
作者涉及的一些概念包括推理、回归分析、中心极限定理、反向因果关系、正发表偏倚。虽然它需要一定程度的统计经验,但它成功地以一种非常独特的方式传递了预期的知识。
“有统计数据很容易撒谎,没有统计数据就很难说真话。”
― 查尔斯·惠兰
也看看这个—
看看吧,你为什么要读它们?
towardsdatascience.com](/machine-learning-books-you-must-read-in-2020-d6e0620b34d7)
4.数据科学家实用统计
作者:安德鲁·布鲁斯、彼得·布鲁斯和彼得·格德克
出版商 —奥赖利
难度等级:中级
在这里获取图书——亚马逊

《数据科学家实用统计学》的封面
这本书最好是针对以前有编程语言和统计学经验的数据科学专业人士,以一种方便的方式介绍了这个主题的基本概念,以方便学习。它还强调了来自数据科学和统计世界的各种概念及其目的的有用性。
面向数据科学家的实用统计学通过将核心概念与过去和最近几年与数据科学行业相关的实例联系起来,解释了该主题的核心概念。尽管它涵盖了大部分的概念,如果不是全部的话,这本书还是推荐额外的阅读。
新十年的关键数据科学趋势
towardsdatascience.com](/data-science-trends-for-2020-9b2ee27af499)
5.用于数据分析的 Python
作者:韦斯·麦金尼
出版商 —奥赖利
难度等级:中级
在这里获得图书——亚马逊

《用于数据分析的 Python》一书的封面
正如这本书的标题所暗示的,它主要关注 Python 数据分析的实际实现,主要分析以各种形式存储的结构化数据。它详细介绍了 Python 的作用、用于数据分析相关任务的大量库,以及它为数据科学带来的好处。
本书涵盖的基本 Python 库包括 NumPy、pandas、matplotlib、IPython 和 SciPy 。作者从 IPython 开始,并包括了其余的库。
它还涵盖了 Python 编程的基础知识,作为对几乎没有 Python 编程经验的读者的快速复习。
“无为而为;不费力地工作。把小的看成大的,把少的看成多的。在困难还容易的时候去面对它;通过一系列小行动完成大任务。—老子"
― 韦斯·麦金尼
6.深度学习
作者:伊恩·古德菲勒、约舒阿·本吉奥和亚伦·库维尔
出版商 —麻省理工学院出版社
难度等级:初学者
在这里获取图书——亚马逊

《深度学习》一书的封面
主要面向学习机器学习、深度学习和人工智能的大学生以及那些希望快速学习机器学习的程序员。这本书涵盖了机器学习的所有介绍性章节,包括数学章节和深度网络,涵盖了深度学习和深度生成模型。作者提到了许多见解,以理解什么是机器学习,以及如何实现它来解决现代问题。
“由该领域的三位专家撰写,深度学习是关于该主题的唯一一本综合书籍”
——特斯拉和 SpaceX 的联合创始人兼首席执行官埃隆·马斯克
使用谷歌人工智能中心将想法变为现实
towardsdatascience.com](/top-google-ai-tools-for-everyone-60346ab7e08)
7.使用 Scikit-Learn 和 TensorFlow 进行机器实践学习
作者:作者:奥雷连·盖伦
发行方 —奥莱利传媒
难度等级:初学者
在这里获取图书——亚马逊

《使用 Scikit-Learn 和 TensorFlow 进行机器学习》一书的封面
如果你对机器学习一无所知,这本书将是你的正确选择,因为它承担了为你提供正确的工具、概念、知识和理解机器学习的心态的任务。作者介绍了该主题中包含的各种技术,并借助许多生产就绪工具和环境进行了解释,如 Python 的 TensorFlow、Scikit-Learn 和 Keras 。
这本书的目的是通过广泛的例子提供更多的实践经验,同时减少对理论内容的关注,并鼓励读者更深入地研究实际实施。
“在机器学习中,这被称为过度拟合:这意味着模型在训练数据上表现良好,但不能很好地概括。”
――奥雷连·盖伦
看看这本书的第二版—
8.统计学习导论
作者:加雷斯·詹姆斯,丹妮拉·威滕,特雷弗·哈斯蒂,罗伯特·蒂布拉尼
出版商 —施普林格
难度等级:初学者
在这里获取图书——亚马逊

《统计学习导论》的封面
这本书作为统计学习的指南,本质上转化为一套建模和理解数据的工具。这本书涵盖了这门学科中的各种技术,更强调几个概念的实际应用,而不是它的数学实现。
它通过包含 R 编程语言,以一种更加简单和实用的方式成功地交付了几个复杂的主题,从而促进了学习过程。要充分利用这本书,确实需要理解统计术语和概念。
9. Python 数据科学手册
作者:杰克·范德普拉斯
发行方 —奥莱利传媒
难度等级:中级
在这里获取图书——亚马逊
https://github.com/jakevdp/PythonDataScienceHandbookGit Hub—

《Python 数据科学手册》的封面
这本方便的书背后的目标是呈现数据科学中的各种概念,而不是作为一个全新的领域,而仅仅是作为一项新的技能。根据作者的说法,数据科学可以被最好地解释为某个领域的黑客技能、实质性专业知识与该领域的数学和统计知识之间的交集。
本书假设读者具有创建和管理 Python 程序流的基本 Python 经验,因此,主要侧重于讲授 Python 的实现及其在数据科学中值得注意的库栈。
10.从零开始的数据科学
作者:乔尔·格鲁什
出版商 —奥莱利传媒
难度等级:初学者
在这里获取图书——亚马逊

《从头开始的数据科学》一书的封面
如果你很想知道各种算法、库、框架和其他工具包在数据科学中是如何工作的,那么这是一本适合你的书。这本书不是先教你数据科学的核心方面,而是走相反的路线,从使数据科学成为可能的工具的基础开始,逐渐触及数据科学的各种概念。这本书的先决条件包括事先了解数学和编程技能。
"只需运行:pip 安装 ipython,然后在互联网上搜索解决方案,无论是什么原因引起的神秘错误信息。"
― 乔尔·格鲁什
数据科学工具,使任务可以实现
towardsdatascience.com](/best-data-science-tools-for-data-scientists-75be64144a88)
11.想想统计数据
作者:艾伦·b·唐尼
发行方 —奥莱利传媒
难度等级:初学者
在这里获取图书——亚马逊

“思考统计”这本书的封面
Think Stats 为探索性数据分析提供了实用工具的介绍,并遵循作者的数据处理风格。这本书遵循计算方法,而不是传统的数学方法,主要原因是鼓励读者使用 Python 代码以获得更好的可读性和清晰度。
这本书背后的想法是提出一种基于项目的方法,读者可以选择一个统计问题,一个数据集,并将他们学到的每一种技术应用于该数据集。
作者还提到了许多免费的外部参考资料,例如维基百科。
12.使用 Python 进行深度学习
作者:弗朗索瓦·乔莱
出版商 —曼宁出版公司
难度:专家
在这里获取图书——亚马逊

《用 Python 进行深度学习》一书的封面
Python 深度学习讲述了通过使用 Python 和它的库 Keras 让机器学习和深度学习对广大受众可用。这本书涵盖了人工智能、机器学习和深度学习的基本背景,然后聚焦于 Keras 对深度学习的实现。
然后作者继续讨论深度学习的实际应用及其相关概念,并给出了大量代码示例。对于大多数有技术能力的读者来说,比如数据科学家、深度学习专家和研究生,这将是一个合适的选择,因为它需要精通 Python。
“不是所有的问题都能解决;仅仅因为你收集了输入 X 和目标 Y 的例子,并不意味着 X 包含了足够的信息来预测 Y。例如,如果你试图根据最近的价格历史来预测股票市场上的股票走势,你不太可能成功,因为价格历史不包含太多的预测信息。”
―弗朗索瓦·乔莱,
更多可供阅读的数据科学书籍—
- 模式识别和机器学习
 - 实用数据科学与 R
 - Python 机器学习示例
 - 想想 Python
 - 统计学习的要素
 - 想想贝叶斯——贝叶斯统计变得简单了
 - 设计数据密集型应用程序
 
结论
数据科学是一个庞大的行业,包含大量强大而高效的工具,用于执行各种数据任务。一个有抱负的数据科学家应该知道如何使用这些工具来处理数据,以实现性能驱动的结果。通过吸引您对一些最好的数据科学书籍的关注,我们希望鼓励任何正在寻找数据科学和机器学习切入点的人。毫无疑问,这些书是最好的书籍之一,它们不仅能增强你的数学知识,还能增强你对贯穿全文的几种编程语言和库的了解。
注: 为了消除各种各样的问题,我想提醒你一个事实,这篇文章仅代表我想分享的个人观点,你有权不同意它。
更多有趣的阅读—
我希望这篇文章对你有用!以下是一些有趣的读物,希望你也喜欢
[## 2020 年你必须使用的最好的 Python IDEs 和代码编辑器
具有显著特性的顶级 Python IDEs 和代码编辑器
towardsdatascience.com](/best-python-ides-and-code-editors-you-must-use-in-2020-2303a53db24) [## Python vs. Node。JS:哪个最适合你的项目?
使用一组预定义的因素对 Python 和 Node.js 进行详细比较
towardsdatascience.com](/python-vs-node-js-which-one-is-best-for-your-project-e98f2c63f020) [## 10 家使用 Python 的世界级公司
Python 正被 IT 界的一些巨头积极使用
towardsdatascience.com](/10-world-class-companies-using-python-26cde24919a8) [## 2020 年最佳数据科学博客
最值得信赖和享有盛誉的来源,让您了解数据科学领域的最新动态。
towardsdatascience.com](/best-data-science-blogs-to-follow-in-2020-d03044169eb4) [## 用于自然语言处理的 Python 库
用于自然语言处理的流行 python 库概述
towardsdatascience.com](/python-libraries-for-natural-language-processing-be0e5a35dd64)
关于作者
克莱尔 D 。在digital ogy—是一个内容制作者和营销人员。这是一个技术采购和定制匹配市场,根据全球各地的特定需求,将人们与预先筛选的&顶尖开发人员和设计师联系起来。连接DigitalogyonLinkedinTwitterinsta gram。**
数据科学训练营—他们能做什么,不能做什么
经常有人问我,数据科学训练营(或者非全日制硕士项目,我把它归为同一类)是否值得。在我权衡的时候,先把我的证书拿出来:我已经为几个硕士项目和一个在线训练营教过课,并且在我向数据科学转型时也参加过一次训练营。
在过去的日子里,我已经写了一些关于训练营的想法。问题是,这是一个很难给出一个统一答案的问题。每个人的技能不同,目标也不同。然而,我认为有一件事是相当不变的:训练营往往对那些没有高度技术背景的人承诺过多。如果你还没有达到目标,训练营不会让你成为数据科学家。

不同的起点
让我给处于数据科学学习不同阶段的人提供一些关于训练营的想法:
从头开始:我就直说了吧。如果你几乎没有编程、数据或统计方面的经验,6 个月的兼职课程不会让你成为数据科学家。你可能会学到一些很酷的技能,如果你投入工作,你可能会得到一个入门级的数据分析师职位。数据科学职位通常被认为是相当高级的,或者至少是高技能的。一个短期的项目根本不足以让你在基本技能上达到预期的能力水平。
学术背景:我认为那些来自量化学术背景的人是训练营的最佳候选人(坦白说,这是我的背景)。大多数定量学者都有过得去的编码技能,了解统计学,并有处理和讲述数据故事的经验。训练营让我们体验了工具的广度,一些使用数据科学中一些流行工具的实践,以及一些编码实践。一般来说,我认为有这种背景的人最有可能在训练营后获得数据科学职位。作为额外的奖励,像 Data Incubator 和 Insight 这样的项目对来自学术背景的有前途的候选人是免费的。也就是说,许多人在不需要训练营的情况下就完成了转变,所以尽管我认为它们可能是有用的,但首先在没有训练营的情况下,了解一下你在就业市场上的前景可能是值得的。
软件工程背景:老实说,我没看到多少软件工程师参加训练营。我认为这是有道理的——在大多数情况下,如果你已经在技术领域工作,你会知道这个空间和转变没有来自学术界的那么大。你可能拥有从所有伟大的免费在线资源中学习的技能。对拥有严肃编码技能的数据科学家有着巨大的需求,通常走这条路线的人最终会获得“机器学习工程师”的头衔。也就是说,对于一个希望获得一些数据科学背景并希望更多结构化课程的软件工程师来说,我认为训练营可能是一个很好的方式,因为他们会提供他们可能缺乏的统计和机器学习背景,但这肯定不是必要的。
数据分析师:训练营当然可以“提升”你的数据技能。根据你现在的技能,这可能是一个很好的方式,可以让你努力进入更高级的数据分析师职位,或者尝试跃升为数据科学家。但这在很大程度上取决于你目前的角色需要什么——如果你根本没有使用过 Python,而且大多数情况下只是使用 Tableau,训练营会向你介绍一些东西,但不太可能足以让你跃升为数据科学家。如果没有机会使用机器学习,它也可能对你目前的角色没有用处。如果你在目前的职位中发现了可以使用数据科学技能的地方,而唯一阻碍你的是缺乏自己的技能,那么兼职训练营可能会非常有用。
新兵训练营和其他兼职项目非常有助于向你介绍各种各样的数据科学工具。它们本身不足以让你成为专家,它们也不具有变革性。如果你只是对数据科学好奇,有大量的在线学习资源。如果你想做一些更有针对性的事情,并且没有严重的财务限制,训练营是一个合理的选择。只是不要期望训练营能在几个月内让你从 0 到 6 位数的数据科学家。
数据科学—使用 Microsoft Power BI 为 SQL 关系数据构建网络图
讨论如何为存储在 SQL Server 中的销售数据构建网络图,以可视化销售模式。

作者图片
网络理论是一种最先进的理论,用于表示实体之间的复杂关系。一些有趣的应用是疫情扩散分析(如 COVID19)、社会网络分析(如脸书网络)、世界贸易分析等..网络图建立在网络理论的基础上,可以为讲故事提供动态的、有时令人兴奋的图表。
本文将讨论如何为存储在 SQL Server 中的 SQL 关系数据构建网络图。想要从事一些数据科学项目的人(例如软件工程师、数据工程师、数据库管理员)可能会对它感兴趣。
以上是自行车相关产品销售数据的最终网络图。注意,为了简单起见,我没有使用所有的数据,为了演示的目的,我没有使用更清晰的视图。
从这个图表中,很容易回答公司高管的常见问题:
- 卖什么产品?
图中所有的绿色节点,包括旅行车、公路车、山地车、自行车架。 - 产品销售到哪里?
图中的所有灰色节点,包括加利福尼亚州、新英格兰州、新墨西哥州、科罗拉多州、内华达州和犹他州。 - 卖多少产品或者产品卖多少钱?
大部分到加州和新英格兰,部分到新墨西哥州和科罗拉多州,少量到犹他州和内华达州。 - 产品和客户的地理位置之间有什么关联吗?
是的!例如,销售到新英格兰的公路自行车比自行车架多得多,公路自行车的链接更粗就说明了这一点。 - 对于一个全新的产品,它应该在哪里营销和销售?
例如,一辆旅行自行车可以行销到加利福尼亚、新英格兰、新墨西哥和科罗拉多! 
现在,我们如何在微软 Power BI 中构建这样的东西呢?
先决条件
- Microsoft 帐户。可以免费注册。
 - 超级商务智能台式机。你可以从这个微软链接免费下载。
 - SQL Server。你可以从这个微软链接免费下载。
 - Microsoft 示例数据库“AdventureWorksLT2016”
 
示例 Adventure Works 数据库中有什么?
- 销售系统的虚假 CMS 数据
 - 产品和产品类别
 - 客户及其地址
 - 销售订单
 
步骤 1 —打开 Power BI Desktop 并创建一个新工作簿。在可视化面板中,点击三个点并选择“获取更多视觉效果”。

作者图片
步骤 2 —搜索“网络”,安装网络导航图,这是微软提供的自定义可视化工具。安装后,网络导航器应显示在可视化列表中。

作者图片

作者图片
步骤 3 —现在让我们通过将工作簿连接到 SQL Server 上的 AdventureWorks 数据库来获取示例数据。注意,当要求我们选择表格时,我们只需要数据库中的几个表格。如果将来需要,您可以添加更多表格。

作者图片

作者图片

作者图片

作者图片
单击左侧边栏上的模型图图标,确认数据模型。请注意,Power BI 将识别外键和表之间的关系。

作者图片
第 4 步—(可选)为用户界面添加一个新列。在左侧栏中,导航到数据图标,然后选择客户表,并单击新列。

作者图片
在编辑栏中,输入以下文本,为所有记录设置列名和常数值。
PowerBiNodeColor = "#01B1AA "

作者图片
步骤 5——点击网络导航图标,创建网络图。在我们填写所需属性之前,它将为空。

作者图片
第 6 步—添加我们想要探索的数据字段。在本次演示中,我们将使用:
- 列产品类别。作为源节点的名称
 - 列地址。StateProvince 作为目标节点
 - SalesOrderDetail 列 OrderQty 作为边权重,它确定边/链接的厚度。
 - SalesOrderDetail 列 OrderQty 作为目标节点权重,它决定了状态节点的大小。
 - 列 PowerBiNodeColor 作为源节点颜色,这是我们在上一步中创建的绿色。
 
第六步——在“画笔”部分给网络图一些爱和格式。

作者图片
以下是我为此演示更新的设置列表:
- 在“布局”面板中将“最大节点大小”设置为 30,以便节点/气泡不会变得太大
 - 打开布局面板中的标签。
 - 将标题值设置为“Adventure Works”。
 
恭喜恭喜!现在,您有了一个全新的网络图来展示如何以一种非常吸引人的格式可视化 SQL 关系数据!
本文中使用的 Power BI 工作簿发布在这个 GitHub 链接上。请随意使用它作为您下一个数据科学项目的开始!
感谢您的阅读!
数据科学术语:数据插补
数据科学有很多词汇需要学习。这是一个不到 5 分钟的数据插补快速总结。
它是什么,我们为什么需要它?
数据插补是指处理数据集中缺失的数据。我们需要它,因为有些算法不接受空值,还因为如果我们填充数据,我们可以建立更准确的预测模型。我们将在本文中探讨如何很好地填充这些数据。

苏阿德·卡玛丁在 Unsplash 上拍摄的照片
需要注意什么
首先,我们需要看一下我们的数据——缺失数据有趋势吗?
缺失数据主要有 3 类:
完全随机缺失(MCAR) —这是唯一可以验证的缺失数据类型。当数据是 MCAR 时,这意味着缺失的数据点绝对没有模式。这可以通过将数据随机分为已完成的行和缺少数据的行来检查。如果两个子数据集的特征不同,则意味着您的数据是 MCAR。
随机缺失(MAR)——当数据被标记时,意味着数据缺失是由于可以观察到的系统性原因,但与缺失数据本身无关。例如,在包含两列(年龄和性别)的数据集中,通过计算每一列的缺失值,您可能会注意到男性年龄中缺失的数据比女性多。
非随机缺失(MNAR) —当数据是 MNAR 时,这是因为在另一个因素和缺失数据之间存在关系。例如,如果你有一个调查,问他们的第一个宠物的名字,它可能会被那些从未养过宠物的人留为空白。有一个系统性的原因是数据缺失。
那么我们能对丢失的数据做些什么呢?
我将概述几种处理缺失数据的常用方法。还有很多,但这只是对你能做的一些事情的一个洞察。
删除丢失的数据 —根据丢失的数据量,我们可以忽略丢失数据的行。如果当您有 10,000 行时,这只是数据的一小部分,也许是百分之几,这可能是最简单的选择,不会对您的结果产生太大影响。
替换为数据的平均值 —这个有很多变化,取决于你在数据中找到什么。首先,我们有三种类型的平均值:均值、中值和众数。对于非数字数据,您当然不能使用均值或中值,因此您唯一的选择是用模式填充缺失的数据。然而,对于数字数据,所有三个平均值都是可能的。使用这些方法时需要注意的是,您是在人为地减少数据的方差,这可能会影响根据数据训练的模型在新数据上的表现。您选择的平均值取决于您的数据集,例如,如果缺少数据的列在其分布中有很大的偏差,您可以选择中位数。
这种方法可以用于整个数据集,也可以将其分解。例如,如果您试图用平均值填充年龄列,您可以取所有相关数据的平均值并填充空值,或者您可以查看另一列,假设您有一个性别列,并且您意识到男性的平均年龄为 25 岁,而女性的平均年龄为 35 岁,因此选择用两种性别各自计算的平均值来填充缺失的年龄值。但是请注意,您对数据集进行的分解越多,计算的开销就越大,花费的时间也可能越长。
回归 —您可以使用回归技术,根据数据中的其他变量来预测空值。回归有许多不同的类型,这取决于数据的类型以及它们之间的关系。理论上,你可以使用任何合适的回归算法来估算你的数据。这是另一种计算开销很大的方法,具体取决于数据量和回归算法的复杂程度。
还要考虑别的事情 …
M 多重插补 —为了补偿输入数据的潜在偏差,可以在计算值中引入一些自然变化。基于数据的分布计算变化;该算法可以估计所创建的值应该有多少变化。这是一种计算开销很大的方法,但值得考虑,尤其是如果您的数据来自一个可能会有自然变化的来源。
要点: 确保只对训练数据进行计算,这样就不会有数据泄露。如果你用你的测试/验证数据进行计算,你可能会发现你的算法非常准确,但当你得到全新的数据时,你会得到非常低的准确性。
带回家的信息
填充缺失数据的方法有很多种,根据数据集和缺失的数据量,您选择的方法会有所不同。你的插补算法越复杂,花费的时间就越长。在你估算的复杂性和它给你的回报之间进行权衡是很重要的。
数据科学术语:特征工程
数据科学有很多词汇需要学习,这里有一个不到 5 分钟的特性工程的快速总结。
特征工程是这样一个术语,从表面上看,它的意思和它所说的完全一样:你想从你已有的数据中重构或创造一些东西。
好吧,好吧…但是在现实生活中,当你坐在数据集前,不知道该做什么时,这实际上意味着什么呢?

图片由来自 Pixabay 的 sergei akulich 拍摄
特征工程是由什么组成的?
该术语包含各种方法,每种方法都有与其相关联的各种子方法。我将只介绍一些主要的方法,让你对特征工程包含的东西有一个概念,并对广泛使用的方法有一些指示。
编码——我认为这是特征工程最简单和最常用的方面之一。事实上,早在我意识到特征工程作为一个整体存在之前,我就在做这件事了!编码用于将分类数据转换成数字数据。这是必要的,因为计算算法处理的是数字,而不是文字。一些更简单的方法是标签编码器和一个热编码器。
要素生成-要素生成或要素构建是指从数据中已经获得的要素手动创建新要素。这可能只是简单地将两列连接在一起,或者需要更多的代码来计算在某个时间段内有多少条目出现在有问题的条目之前。再说一次,你可能会做这样的事情,只是因为它让你的生活变得更轻松。特征生成有几个好处:
- 它可以给你一列数据,说明两个是做什么的。与编码结合使用,您可以更详细地查看数据的细节,例如,如果您有一个汽车制造商列和一个汽车颜色列,您可以将它们组合起来,得到一个制造商颜色列。这可能会减少你最终模型的特征数量(耶效率!)而不会丢失数据。
 - 通过查看您的数据,您可以立即获得信息,并使用这些信息来简化数据,这样您就可以更清楚地使用例如自事件发生以来的时间计算或先前条目的数量。
 - 您可以简化您的数据,例如,如果您的数据中有超过 100 个不同的国家,其中许多只出现一次或两次,您可能希望创建一个新的要素来给出相关的洲。这样,您就有了更少类别的更多实例,这对您的分析可能更有意义。
 
特征提取 —这是直接从原始数据自动创建特征的地方。通常用于图像、音频或文本数据(尽管当有大量数字数据时,它也可以用于数字数据!)您使用特征提取来降低用于分析的数据的复杂性,从而降低数据的维度,这允许您的模型更快地运行。常用的方法是主成分分析或无监督聚类算法。上面列表中的第 2 点和第 3 点也与此相关。
特性选择——这是特性工程的一个非常重要的部分:一旦你有了一大堆新特性,你需要找出哪些对你真正有用。现在,您可以通过一些尝试和错误来做到这一点,但使用内置函数来做到这一点可能更有效。一个简单的例子是单变量特征选择,例如 SelectKBest ,它选择与因变量关系最密切的给定数量的特征(您可以决定有多少)。您可以使用许多选项来确保对数据使用正确的算法。
带回家的信息
有很多方法可以将数据转换成计算机满意的格式,简化数据,甚至创建新的变量进行分析。没有“正确的方法”,许多方法可以是一种艺术形式,取决于经验。不同的解决方案对不同的数据集更有效。
有用的资源
我在整篇文章中都链接了 Python 文档,因此您可以更详细地查看感兴趣的部分,也许是为了在您的代码中实现这些方法。
ka ggle——特色工程短训班。这门课程不适合编程或机器学习的初学者。它简要地涵盖了特征工程的 3 个方面。就我个人而言,我不认为这是最好的细节和深入学习的课程,但如果你想涉足这个领域,这是一个很好的起点。
优化深度学习神经网络
Hazy 的数据科学
深度学习神经网络有一系列令人眼花缭乱的元参数。了解如何将 GANs 应用于神经网络优化。

来源: WOCinTech ,知识共享
道格拉斯·亚当斯在《银河系漫游指南》中曾断言:“空间很大。你不会相信它有多么巨大,令人难以置信的大。我的意思是,你可能认为去药店的路很长,但那对太空来说只是微不足道。”
神经网络也很大。T2 微软图灵自然语言生成或 T-NLG 网络有大约 190 亿个参数。以大多数人的标准来看,这已经很大了。
然而,我们关心的不仅仅是参数的数量,还有元参数。研究生成对抗网络(GAN)的数据科学家通常必须运行数百万次实验,以优化他们的神经网络。在这篇文章中,我们解释了在 Hazy,我们如何将自动元参数优化注入到我们的 GANs 中,然后让您在较少挫折的情况下训练更好的模型。
调整元参数:成为机器学习工程师的尝试
深度学习神经网络有一系列令人眼花缭乱的元参数。
元参数是提供给网络的参数,用于指导网络的训练过程,控制网络如何修改参数。
元参数包括学习速率、动量、隐藏层的数量、每层神经元的数量以及要使用的优化器的类型。
机器学习工程师工作的一个标准部分是调整网络,也就是选择产生最佳性能的元参数。这可能是一个耗时的过程,因为网络越大,收敛的时间就越长,并且通常需要调整和调整的元参数就越多。
调整网络很像一个科学家,他有一台复杂的设备,有许多旋钮要旋转,要进行大量的实验,看哪一个能给你最好的结果。
幸运的是,有一些软件包可以让这项任务变得更容易。
应用于 GANs 的 Optuna 优化
在合成数据生成公司 Hazy ,我们是 Optuna Python 包的忠实粉丝。
Optuna 是一个自动元参数优化软件框架,专门为机器学习而设计。该代码是高度模块化和强制性的。它支持并行,分布式优化,动态修剪试验。它与机器学习框架无关,并且高度可定制。
我们举个例子。假设我们有一个 GAN,我们希望优化它的生成器和鉴别器的学习速率。我们该怎么做呢?
成为神经网络的考验
Optuna 有两个基本概念:研究和试验。
该研究是优化的总体任务,基于返回优化结果的函数。这个函数通常被称为目标函数。试验是目标函数的一次执行。
让我们来看一个例子,这个例子取自 Optuna 网站,并应用于 Hazy 的 GAN 模型,让您了解什么是可能的。
首先,我们定义一个目标函数来研究。
目标函数封装了整个训练过程,并返回元参数的这个特定实例的值。
def objective(trial):
    iris = sklearn.datasets.load_iris()
    n_estimators = trial.suggest_int('n_estimators', 2, 20)
    max_depth = int(trial.suggest_loguniform('max_depth', 1, 32))
    clf = sklearn.ensemble.RandomForestClassifier(
        n_estimators=n_estimators, max_depth=max_depth)
    return sklearn.model_selection.cross_val_score(
        clf, iris.data, iris.target, n_jobs=-1, cv=3).mean()
该函数加载了虹膜数据集 —一个众所周知的用于评估机器学习分类器的数据集。然后,它从试验对象获得建议的估计数和最大深度。然后它实例化一个随机森林分类器并返回分数。
让我们更详细地讨论一下。
数据集由三种不同种类的虹膜组成,机器学习任务是在给定四个测量值的情况下,将给定的数据点正确地分配给正确的虹膜种类:
- 萼片长度
 - 萼片宽度
 - 花瓣长度
 - 花瓣宽度
 
Iris 数据集被认为是一个相当困难的分类问题,因为就这些测量而言,物种之间有相当多的重叠。很难在物种之间划出一个清晰的界限。
我们希望优化的元参数是n _ estimates和 max_depth 。
试验对象为 n_estimators 建议一个 2≤𝑛≤20 范围内的整数:
n_estimators = trial.suggest_int('n_estimators', 2, 20)
Optuna 有许多不同的机制来提供元参数的值,以便在每次试验中进行测试;使用对数均匀分布分配最大深度的值:
max_depth = int(**trial**.suggest_loguniform('max_depth', 1, 32))
suggest _ log uniform函数接受一个范围,在本例中为 1≤ 𝑥 ≤32,并返回该范围内的浮点值。这被转换为整数。
然后创建随机森林分类器,具有建议的最大深度和 n 估计器。对它进行评估,并返回一个分数:
clf = sklearn.ensemble.RandomForestClassifier(
        n_estimators=n_estimators, max_depth=max_depth)
return sklearn.model_selection.cross_val_score(
        clf, iris.data, iris.target, n_jobs=-1, cv=3).mean()
创建了目标函数后,我们需要创建一个 Optuna 研究,并创建一些试验。然后,我们输出元参数的最佳值:
import optuna
import sklearn
import sklearn.datasets
import sklearn.ensemble
study = optuna.create_study(direction='maximize')
study.optimize(objective, n_trials=100)
trial = study.best_trial
print('Accuracy: {}'.format(trial.value))
print("Best hyperparameters: {}".format(trial.params))
这将输出每次试验的分数,以及所使用的元参数。最终,在研究完成后,它输出最佳元参数:
[I 2020-04-23 17:54:52,817] Finished trial#98 with value: 0.9738562091503268 with parameters: {'n_estimators': 17, 'max_depth': 3.303148836378194}. Best is trial#43 with value: 0.9738562091503268.
[I 2020-04-23 17:54:52,899] Finished trial#99 with value: 0.960375816993464 with parameters: {'n_estimators': 17, 'max_depth': 3.136433926827928}. Best is trial#43 with value: 0.9738562091503268.
Accuracy: 0.9738562091503268
Best hyperparameters: {'n_estimators': 12, 'max_depth': 4.419437654165229}
优化 GANs
我们如何利用这一点来优化由生成性对抗网络所代表的高度复杂的系统呢?
让我们为那些想要优化的元参数定义几个函数。
GAN 由两个神经网络组成,即发生器和鉴别器。生成器的任务是试图通过创建假数据来欺骗鉴别器;给定真实和虚假数据的输入,鉴别器必须能够区分两者。
假设我们想要优化两个网络的学习速率:
def opt_learning_rate(lr_key, trial):
    """
    lr_key: label to use for this learning rate
    trial: optuna trial object
    (one of those hyperparameters which may vary by orders of magnitude!)
    Returns: a string containing which learning rate is being optimised, & a suggested learning rate
    """
    return trial.suggest_loguniform(
        lr_key,  1e-5, 1000
    )
我们使用了建议 _ 日志统一功能,并赋予其广泛的范围。
下面我们使用成人数据集来设置优化两种学习率的代码。
让我们从建立一个 Python 字典开始,该字典将包含用于构建网络的默认元参数。
default_network_dict = {
    "epochs": 250,
    "batch_size": 64,
    "discriminator_learning_rate": 1e-5,
    "generator_learning_rate": 5e-4,
    "latent_dim": 100,
    "input_output_dim": 20,
    "num_bins": 100,
    "layers": 3,
    "hidden_dims": [64, 128, 256],
    "num_critics": 4,
    "dropout": 0.1,
    "neuron_type": "LeakyReLU",
    "optimiser": "RMSProp",
    "output_folder": False,
}
注意,我们已经为 GAN 的学习速率提供了默认值;这允许用户选择他们想要优化的元参数。所有这些都有可能得到优化;然而,字典也可以按原样使用,以创建神经网络。
用户也可以从命令行指定元参数,所以让我们通过从 argparse 创建一个命令行解析器名称空间来适应这种情况。
import argparse
params = argparse.Namespace(
    experiment_name = 'my-experiment',
    location = 'metaparameter-optimisation',
    dataset_name = 'adult',
    #output_folder = 'output',
    num_bins = 100,
    epochs = 500,
    batch_size = 64,
    discriminator_rate = 1e-05,
    generator_rate = 0.0005,
    sigma = 0.1,
    latent_dim = 200,
    num_critics = 4,
    cuda = 0,
    optimise = ['generator_learning_rate', 'discriminator_learning_rate'],
    hidden_dims = [64, 128, 256],
    structure = False,
)
我们需要一种将来自名称空间的命令行元参数与默认网络字典相结合的方法:
def override_params(default_params, optimisable, structure=False):
    if structure:
        default_params['layers'] = 'METAPARAM'
        default_params['hidden_dims'] = 'METAPARAM'
    tmp = dict.fromkeys(optimisable, 'METAPARAM')
    return { **default_params, **tmp }
最后,我们定义我们的目标函数。
目标函数必须覆盖许多基础,因为它必须包含创建、训练和测试 GAN 的所有代码。该函数创建一个 GAN。然后它设置日志,这样我们就可以看到运行试验的结果。然后用给定的元参数调用一个函数来运行试验。
def objective(trial, params, network_dict):
    # need to change all the requested metaparams
    logging.basicConfig(level=logging.INFO)
    logger = logging.getLogger('__metaparams__')
    processor, df, processed_df, categories_n = initialise_processor(params['num_bins'],                                                                  params['dataset_name'],
logger)
   network_dict['input_output_dim'] = categories_n
    fixed_params = fix_metaparams(trial, network_dict)
    generator = build_generator_network(fixed_params)
    discriminator = build_discriminator_network(fixed_params)
    # build the network's optimisers
    gen_optimiser = build_network_optimiser(network_dict['optimiser'],
                                            network_dict['generator_learning_rate'],
                                            generator)
    disc_optimiser = build_network_optimiser(network_dict['optimiser'],
                                            network_dict['discriminator_learning_rate'],
                                            discriminator)
    return run_experiment(
        generator=generator,
        discriminator=discriminator,
        generator_solver=gen_optimiser,
        discriminator_solver=disc_optimiser,
        processor=processor,
        df=df,
        processed_df=processed_df,
        latent_dim=fixed_params["latent_dim"],
        output_folder=fixed_params["output_folder"],
        num_bins=fixed_params["num_bins"],
        epochs=fixed_params["epochs"],
        batch_size=fixed_params["batch_size"],
        sigma=params["sigma"],
        num_critics=fixed_params["num_critics"],
        cuda=params["cuda"],
    )
目标函数和它调用的 run_experiment 函数看起来都有点复杂,但本质上它们只是分配和解析参数。这两段代码中有相当多的内容。然而,他们实际上只是设置了生成器和鉴别器网络、数据集和赋值器。
import logging
from hazy_auto_tuning import initialise_processor, run_experiment
from hazy_network_metaparameters import check_requested_metaparameters, optimisable, fix_metaparams
# from metaparameter_tuning import build_discriminator_network, build_generator_network, build_network_optimiser
from metaparameter_tuning import build_discriminator_network, build_generator_network, build_network_optimiser
在从 Hazy 代码库中再导入几次之后,你可以建立一个 Optuna 研究对象,并要求它为我们优化我们的元参数。
study = optuna.create_study(direction="maximize")
study.optimize(lambda trial: objective(trial, params_dict,       network_dict), n_trials=20)
请注意,对于一项有用的研究来说,这(可能)是太少的试验。对于元参数,如鉴别器和生成器的学习率,我们需要更多的试验。类似地,对于 GANs 性能的精确评估,历元的数量可能不够大。这些仅作为例子给出。
作为机器学习工程师,能够自动化元参数优化令人兴奋,因此我们可以花更多时间探索优化它们对所提供的合成数据集的影响。我们已经将 Optuna 代码应用到模型中,这将节省我们所有人的时间。
2020 年的数据科学职业
宣布 Apteo 关于 2020 年数据科学职业状况的报告

在过去的几年中,我们已经看到数据科学作为一项职业在所有行业和地理位置上的戏剧性崛起。在大约 12 年的时间里,企业已经意识到他们需要精通高级分析的员工,这些员工可以帮助利用和货币化他们可以访问的所有数据。随着这种增长的出现,媒体机构已经开始大肆报道数据科学和人工智能将如何改变世界,从而进一步增加了对该领域的兴趣。然而,尽管对这种新的职业道路已经做了很多,但只有少数来源试图量化这种增长和数据科学家的短缺。
这就是为什么今天我们很高兴发布我们关于 2020 年数据科学职业趋势的报告。这份报告以公共工作空间的形式提供,托管在我们自己的数据科学平台上,提供了当今数据科学职业世界状况的高级概述。该报告试图定量衡量高级分析劳动力市场的当前规模、该市场的增长和薪酬,以及当今和过去数据科学家的短缺情况。
虽然该报告包含了对我们的数据来源和方法的简要说明,但我们希望更详细地说明我们是如何完成这项任务的,因为它需要艺术和科学的结合,我们认为每个人都应该了解我们方法中的任何缺点,这样他们就可以在自己使用这些数据时考虑这些缺点。
就业市场数据
事实证明,发现和汇总当前和过去就业市场状况的数据是这一过程中最具挑战性和最耗时的部分。如前所述,尽管数据科学在媒体和商业中很受欢迎,但几乎没有主要来源公布当今或过去行业中高级分析人员数量的数据。为了收集测量劳动力市场规模所需的数据,我们研究了各种历史报告和分析,以了解过去对劳动力市场的估计。这使我们能够将当今的资源联系起来,为今天的劳动力市场状况提供额外的背景。
这些历史数据虽然不多,但让我们能够确定前几年劳动力市场的规模范围。确定这个范围后,我们试图量化今天的市场规模。虽然我们确实找到了来自劳动统计局的数据科学家总人数的估计,但考虑到我们从以前的文章中收集的背景,这个数字似乎相当低。最终,我们选择使用当今最好的职业数据来源之一 LinkedIn 来收集原始数据。
不幸的是,LinkedIn 并没有提供具有特定职称的员工总数的精确统计,也没有提供其平台上具有给定职称的可用职位的精确统计。然而,它确实允许用户查看在任何给定用户的扩展网络中大约有多少成员符合特定的搜索标准,它还允许单个成员查看特定地理区域内符合给定搜索条件的相关工作的数量。
鉴于这些限制,我们使用我的 LinkedIn 账户运行各种搜索词,以估计我的扩展网络中数据科学家、机器学习工程师和人工智能研究人员的数量。虽然我会第一个谴责这种方法的许多不足之处,但它确实为高级分析行业量化劳动力市场数据提供了一个起点。使用这一策略,我们在 LinkedIn 上进行了各种搜索,提供了各地区高级分析员工总数的近似值,我们将这些搜索的结果与我们从历史指标研究中发现的统计数据相结合。这使我们能够将指数增长曲线拟合到我们收集的时间序列数据中,然后我们使用这些数据对数据集中任何缺失年份的数据进行插值。这条曲线也加强了我们的信念,即 BLS 的估计可能过低。
一旦我们收集了员工数量,我们就使用相同的策略收集不同地理位置的开放数据科学职位列表。有了这两组数据,我们就能够对当今和过去数据科学家的短缺状况进行基本分析。
薪资数据
收集就业市场数据后,我们汇总了历史和当前的薪资数据,并按地理位置进行了细分。我们使用了各种来自求职公告板、咨询报告、调查和文章的公开统计数据来汇总关于平均工资和中位工资的多种统计数据。利用这些数据,我们构建了一个关于高级分析人员平均工资的分析,包括全国和几个大城市中心。
教育数据
最后,我们汇总了专门研究数据科学工具和技能的教育项目的数据。在这种情况下,发现历史数据太难了,所以我们把分析局限于今天的教育项目。在我们的分析中,我们只包括我们认为具有数据科学优先方法的项目,重点关注与数据科学职业相关的核心统计、算法、计算和分析技能。
分析
一旦我们聚集了所有的数据,我们就将其组织成一个公共的 Google Sheet ,然后使用我们的 Google Sheets 数据连接器将该工作表连接到工作区。我们知道我们的分析不够精确,但是,我们相信它仍然对那些试图了解当今数据科学职业状况的人有价值。
留在圈子里
如果你有兴趣了解我们在 Apteo 的最新进展,你可以订阅我们的时事通讯,或者在我们的平台上为你自己创建一个免费账户,在那里你可以可视化、分析和预测你自己的数据。最后,如果你有兴趣帮助我们建立一个数据科学平台,让任何人都可以分析他们的数据,特别是如果你是一名全栈工程师或成长型营销人员,请联系!
最后,别忘了在这里查看报告!
数据科学证书、训练营或硕士学位:哪个最适合你的职业生涯?
充分利用你的时间成为一名数据科学家

韦斯·希克斯在 Unsplash 上的照片
简介
无论您已经学习了多年还是正在考虑转型,如果您希望在数据科学领域取得成功,您都需要拥有合适的工具集。该领域要求申请者跟上最新信息和数据科学实践的步伐,既严格又充满竞争。
在本指南中,我将介绍三种不同的认证方法,它们可以帮助你在数据科学领域获得职业生涯:数据科学证书、数据科学训练营和数据科学硕士学位。具体来说,我将讨论每种方法的优缺点,以便让您更好地了解哪种方法适合您。
让我们跳进来吧!
1。 数据科学证书
数据科学证书是教授基础数据科学技能的专业证书。这些证书由许多大学和机构提供,理论上可以帮助各种数据相关的 IT 领域的工作招聘(但稍后会有更多介绍)。
优点
获得数据科学证书有很多好处:
投资组合构建器
没有合适的作品集,你就别想在数据科学领域找到工作。数据科学证书可以帮助您实现这一目标。虽然证书将只提供基础知识,但它仍将帮助你为以后的高质量投资组合打下基础。
相对便宜
与数千美元的数据科学训练营和硕士学位相比,数据科学证书的价格甚至不到 500 美元。这对于那些希望以低成本建立自己的技能和投资组合的人来说非常好。
不耗时
有些证书可以在几周内完成(按照你自己的时间表)。由于严格程度较低,个人可以快速完成这些证书,而无需放弃之前的承诺(包括工作、学习和抚养孩子)。
缺点
在做出决定之前,一定要考虑数据科学证书的缺点:
基层信息
数据科学证书虽然对那些刚刚进入该领域的人有用,但对那些寻求更高级 IT 工作的人来说不是正确的选择,因为这些证书中提供的信息通常只是基础的。
不直接帮助就业
正因为如此,数据科学证书并不能直接帮助就业,我的意思是没有雇主会仅凭一张证书就雇佣你。相反,你需要丰富的工作经验和/或更专业的经验(包括辅助领域的硕士或博士培训)。
2。 数据科学训练营
数据科学训练营为在数据科学的 IT 世界中前进提供了一种更严格且潜在有益的方式。这些训练营旨在提供更深入和先进的知识,提供更多有用的信息,通常在简历上看起来更好——尽管它们可能不会让完全的初学者受益,并且在项目质量上可能差异很大。
优点
参加数据科学训练营有几个好处:
学术挑战
顾名思义,数据科学训练营以其学术严谨和强度而闻名。通常,这些项目会持续三个月左右的时间,并试图在有限的时间内提供尽可能多的知识。虽然知识的广度达不到数据科学硕士学位,但这些训练营比大多数证书课程更深入。
简历准备
也许数据科学训练营的一个更大的好处是他们专注于工作准备。请记住,这些项目得益于将尽可能多的毕业生送进劳动力市场。出于这个原因,你可以期待导师与你密切合作,制作一份对雇主有吸引力的简历。这包括给你机会从事有利于你职业发展的项目。
联网
数据科学训练营还可以让你接触到你所在领域的主要参与者,因此是让你出名的好方法。根据你的训练营的声誉(记住,并非所有人生来平等),你将有机会见到数据科学领域的雇主并与之互动,并能够准备一份吸引他们眼球的简历。
缺点
然而,数据科学训练营并非没有缺点:
耗时
在数据科学训练营学习期间,不要指望继续正常的生活。这些耗时的项目实际上要求你全神贯注,使得你很难在注册时工作(在某些情况下,甚至是兼职)或专注于其他学习。
贵
另一个不利因素是这些训练营的成本,从 5000 美元到 20000 美元不等。这是一大笔钱,尤其是如果你甚至不确定自己是否想进入这个领域。雪上加霜的是,这些训练营通常最适合那些已经在辅助数学和科学领域拥有博士水平知识的人,因此即使没有这些知识,他们也能找到工作。
3。 数据科学硕士
个人也可以考虑报读数据科学硕士课程。毫无疑问,这些项目是三个选项中最专业的,也是最昂贵的,需要最长的时间来获得。尽管如此,在要求苛刻的数据科学领域,没有什么比研究生学位更令人垂涎的了。
优点
数据科学硕士学位有很多好处,包括:
增加就业机会
你知道这个领域的雇主首先会注意到你的简历吗?没错——不管你有没有该学科的高级学位。这是不争的事实:拥有一个数据科学的研究生学位将会大大增加你的就业机会。
网络机遇
硕士学位课程也提供了极好的社交机会,因为你可以与该领域的专业人士互动,同时建立一个有助于现实世界的投资组合。虽然你可能不会得到和训练营一样的工作准备,但在进入这个领域之前,你仍然可以期望有相当数量的改变游戏规则的人际网络。
实习
当然,研究生学位项目为你提供了难以置信的实习机会,这将极大地有利于你的职业发展。实习是获得该领域实际经验和建立雇主关心的投资组合的主要途径之一。因此,如果有时间和资源,个人应该强烈考虑参加研究生课程。
缺点
尽管如此,在做出这个决定之前,你还是应该考虑一些不利因素:
贵
你不需要我告诉你完成一个硕士项目需要很高的费用。根据你所在的地区和学校的不同,你可能会谈到数万元的费用。这一点,加上该领域的高需求,意味着你将花费大量的金钱,而没有任何立即被雇用的保证。
可能需要数年时间
此外,数据科学硕士学位可能需要长达三年半的时间才能获得,这意味着你不会很快进入劳动力市场。然而,这并不意味着如果你缺乏经验,你应该咬紧牙关,选择更便宜的方案。
底线
找到合适的数据科学项目需要时间和考虑。一般来说,数据科学硕士学位提供了获得真正成功的最佳机会,尽管根据你之前的资历,它们可能不是必需的。如果你已经获得了分析、数学、科学或计算机科学等相关领域的高级学位,你可能会从数据科学训练营中受益最多。如果你只是在试水并考虑职业转型,数据科学证书是你的最佳选择。

                    
                

                
            
        
浙公网安备 33010602011771号