数据结构—简化和分类
照片由克里斯蒂娜·莫里路通过 T2 的像素拍摄
为了通过编程面试,你需要解决算法,而要解决算法,你需要数据结构。现在的问题是,当你打开一本数据结构和算法教科书时,它充满了复杂的数学,对于那些不太喜欢这门学科的人来说,它将变成一场噩梦。然而,一旦你理解了数据结构,它们并不像看起来那么难。本文将简化和总结这些最基本的数据结构,您将理解并能够轻松使用它们。
什么是数据结构?
数据结构是在计算机中组织数据的一种特殊方式,以便可以有效地使用它:
在计算机科学中,数据结构是一种数据组织、管理和存储格式,能够实现高效的访问和修改。更准确地说,数据结构是数据值、数据值之间的关系以及可应用于数据的功能或操作的集合— 维基百科
因此,我们必须将数据存储在某种数据结构中,选择正确的结构至关重要。
值得注意的是,没有什么数据结构是好的或坏的,而是每一种都有自己的优点和缺点。许多方法被用来衡量一个数据结构的好坏。这些也被称为大 O 符号。这是对操作可伸缩性的一种度量。
现在,让我们讨论不同类型的数据结构。
链表
链表的原子单位称为“节点”。这个节点包含一个值和一个指针。该值只是一个数字,比如 12,而指针将该值连接到链中的下一个节点。因此是链表的链接部分。列表中的第一个节点称为头,没有指针的最后一个节点称为尾。
图片来源:维基百科
**优点:**非常适合添加新节点和删除节点。这是通过改变下一个指针指向的位置来实现的。
**缺点:**不太擅长检索节点,尽管知道索引或搜索,因为每个节点只知道它旁边的节点。
排列
数组在所有编程语言中都很常见。它是计算机内存中连续的单元块。
下面的示例表示一个有 12 个元素的整数数组。数组的索引从 0 开始,因此有 12 个元素的数组的索引从 0 到 11。
图片来源: BeginnersBook
**优势:**数组在检索项目方面很棒,但只有在数组很小的时候。
**缺点:**随着数组的不断增长,我们开始在内存中运行其他项目。结果,加法是低效的,因为我们可能不得不将数组移动到内存中的新位置,这样它才合适。
幸运的是,这发生在 JavaScript 和 Python 这样的高级语言中。然而,在低级语言中,你必须预先声明数组的大小。
哈希映射
第三种类型的数据结构,也是非常重要的一种,是哈希表。这类似于 JavaScript 中的对象和 Python 语言中的字典。在这种类型的数据结构中,您给哈希映射一个单词或一个键,它就会为您检索定义或值。在引擎盖下,它的工作方式很像一个数组。这个密钥通过一个叫做“哈希函数”的函数运行,这个函数会为你溢出内存位置。
不同的是,这些内存位置不需要彼此相邻,而是可以在任何地方。因此,不存在大小增加的问题。然而,有一个不同的问题——取决于您使用的散列算法,两个密钥可能散列到同一个内存位置。这就是所谓的“冲突”,有多种方法可以解决它们,但同样,这一切都发生在引擎盖下。
图片来源:维基百科
**优势:**正如我们所知,哈希映射对于添加和检索非常有用。
**缺点:**可能会造成按键碰撞。
堆栈和队列
这两种结构彼此非常相似,都构建在数组之上,并具有一些额外的功能。
堆栈是一个 后进先出 的数据结构。这类似于一堆托盘相互堆叠,你放在上面的最后一个托盘是你需要取下的第一个托盘。当我们在顶部添加一个项目时,这被称为推动,而当我们从顶部取出一个项目时,这被称为弹出。每种语言都用调用栈来跟踪被调用的函数。栈对于一个叫做深度优先搜索 (DFS)的算法非常重要。
图片来源:维基百科
另一方面,队列是一种 先进先出 结构,类似于公共汽车站的队列或队伍,最后加入队列的人最后进入公共汽车。将一个项目添加到末尾称为入队,将它从前面移除称为出队。队列被用于一种叫做广度优先搜索 (BFS)的重要算法中。
图片来源:维基百科
**优点:**两种结构在添加和删除项目上都非常高效。
**缺点:**与其他数据结构相比,它们的用例数量都非常有限。
图形和树
这个主题相当复杂,在计算机语言中有一个专门的章节叫做“图论”。一个图类似于一个链表,其中我们有指向其他节点的节点,除了在这种情况下指针被称为“边”。边也可以被赋予权重或数字。
有一种称为“树”的特殊类型的分层图,其中数据向一个方向扩展。这些可以用来指代很多东西,比如“家谱”,或者用来表示网络。与数组、链表、堆栈和队列这些线性数据结构不同,树是分层的数据结构。
图片来源:维基百科
**优点:**树提供了有效的插入和搜索,树是非常灵活的数据,允许以最小的努力移动子树。
**缺点:**缺点是修改列表和检索需要花费 O(log n) 的时间。
总之,这些数据结构会给你一个很好的基础来开始求解算法。
我希望现在你对数据结构有了更多的了解,并且你可以更好地理解抽象表面下的可行结构来使用你的编程语言。
感谢阅读这篇文章!如果你有任何问题,请在下面留言。此外,看看我的其他文章,你可能会喜欢:
你的算法效率如何?
medium.com](https://medium.com/swlh/understanding-big-o-ff675cf63e11) [## 如何增加你找到工作的机会
本文将详细介绍设计简历的最重要的技巧和诀窍,以便在求职过程中获得优势
medium.com](https://medium.com/@vpodk/how-to-increase-your-chances-of-getting-a-job-254c97c3b448)
data.table: R 的最佳数据对象
data.frame 太 2016 了
data.table 是我更喜欢用 R 而不是 Python 工作的主要原因。尽管 R 是一种众所周知的慢语言,但 data.table 通常比 Python 的 pandas ( benchmark )运行得更快,只要 R 能够处理如此大规模的数据,它甚至可以与 Spark 一较高下。更好的是,data.table 非常简洁,只需要一点点输入就可以支持像窗口函数这样的复杂操作。
我相信 data.table 是最重要的 R 包。任何形式的争论最好使用 data.table。它是我们需要的数据超级英雄。
除了函数不接受 data.table .我个人不喜欢 tidyverse(抱歉!)因为它使用 data.frame 和 tibble,因此运行起来比较慢——需要两倍的打字量。(最近 Wickham 发布了 dtplyr ,它将 dplyr 代码翻译成 data.table 操作。你得到 dplyr 语法和数据表速度,如果那是你的事情。)
本文将指导您如何使用 data.table,以及让您更快更轻松地处理数据的提示和技巧。
构建数据表
除了使用 read.csv()之类的方法,您还可以使用 fread()将数据直接加载到 data.table 中。一旦有了大小适中的数据,就可以看到 fread()比 read.csv()快多少。
您也可以使用 data.table()函数构造一个,就像您对 data.frame()所做的那样。请注意,字符串不再自动转换为因子。
如果您已经有一个 data.frame,data.table()函数将转换它。
如果您的数据被分割成多个文件,您可以将每个文件加载到它自己的 data.table 中,存储到一个列表中,然后使用 rbindlist()。这类似于 do.call("rbind ",……),但效率更高。
library(data.table)dt <- fread('mydata.csv')
dt <- data.table(x = 1:10, y = 1:10)
dt <- data.table(mydataframe)templist <- list()
for(i in 1:length(filenames)){
templist[[i]] <- fread(filenames[i])
}
dt <- rbindlist(templist)
类似 SQL 的语法
SQL 是事实上的数据语言(还记得 NoSQL 被说成“不仅仅是 SQL”吗?)并且应该为大多数数据专业人员所熟悉。如果能写 SQL,就能写数据,表语法:
FROM[WHERE, SELECT, GROUP BY][ORDER BY]
假设您想要运行以下查询:
SELECT
col1,
count(1) as num_obs,
sum(col2) AS group_sum
FROM mydt
WHERE col3 > 0
GROUP BY col1
ORDER BY 2 DESC
在 data.table 中,这变成了
mydt[
col3 > 0,
.(num_obs = .N,
group_sum = sum(col2)),
by = col1
][
order(-num_obs)
]
就是这样!最少的输入,不需要管道传输大量的函数。这确实需要一些时间来适应,但一旦你掌握了窍门,这就很有意义了。
的。()是 list()的简称。在 SELECT 语句中使用它将返回一个 data.table(将在下一节中解释)。
有了 data.table,您在引用字段时不再需要重复键入表名。使用 data.frame 您需要键入
mydt[mydt$col3 > 0]
但是 data.table 知道方括号内的内容可能是指它的列,所以您可以输入
mydt[col3 > 0]
这看起来并不多,但当您键入数百行代码时,这是生活质量的巨大提高。
快速转化和变异
SELECT 语句采用两种形式之一:
- 。()返回一个新的数据表
- :=就地修改数据表
来自的输出。除非创建新的对象,否则()不会存储在任何位置。对于示例任务,data.table X 有两列:grp(分组变量)和 val(数值)。
任务 1:创建所有值的平均值的标量。
X[,mean(val)]
任务 2:创建一个包含组均值的新 data.table X_agg。
X_agg <- X[,.(avg = mean(val)), by = grp]
任务 3:在 X 中创建一个包含组平均值的新列。
X[,avg := mean(val), by = grp]
任务 4:在 X 中创建新列,说明观察值是否大于组平均值。
X[,is_greater := val > mean(val), by = grp]
任务 5:在 X 中为组 avg 和 stdev 创建两个新列。
X[,
':='(avg = mean(val), stdev = sd(val)),
by = grp
]
有时,您有许多列需要按两个字段分组,grp1 和 grp2。您可以:
X_agg <- X[,lapply(.SD, mean), by = .(grp1, grp2)]
的。SD 是除用于分组的列之外的所有列的简写。注意所有这些任务的代码有多短!
快速搜索和加入
与 data.frame 不同,data.table 支持使用 setkey()函数进行索引:
X <- data.table(
grp = sample(1:10),
xval = rnorm(10)
)
Y <- data.table(
grp = sample(rep(1:10, 2)),
yval = rnorm(20)
)
setkey(X, grp)
setkey(Y, grp)
X[Y]
最后一行 X[Y]使用指定的索引合并两个表,比使用 base merge()要快得多。当您希望查找特定值时,索引还使 data.table 能够使用二分搜索法。
窗口功能
在 SQL 中,您可以使用一些有趣的累积和,例如
SELECT
grp,
obs_date,
sum(val) over (
partition by grp
order by obs_date
rows unbounded preceding
) as cumulative
FROM mydt
您可以在 data.table 中快速完成同样的操作:
mydt[
order(obs_date),
.(obs_date,
cumulative = cumsum(val)),
by = grp
][
order(obs_date)
]
data.table 甚至自带了 shift()和 frank()等快速窗口函数——后者用于快速排序。
最后
如果您还没有在 R 工作中使用过 data.table,我强烈建议您尝试并学习它。你会回过头来想,如果没有它,你以前是怎么工作的。它速度更快,内存效率更高,而且比 r 中的其他任何东西都更简洁。
与纯粹使用 SQL 相比,一个主要的优势是您可以保持中间表组织良好,而不是创建视图。在 Rstudio 中,可以使用环境窗口来跟踪所有对象。
数据对话:熊猫数据操作实用教程
了解如何使用 Kickstarter 项目数据集处理和操作数据。
来源: Kickstarter
数据无处不在
直到互联网的诞生,数据才真正对我们的生活产生重大影响,并彻底改变了商业运作的方式。这些天,我们有几乎所有的数据,从我们最喜欢的麦片品牌,你最好的朋友毕业的学校,到你下午 2 点的心率。现在说数据已经融入到我们的基因里,大概不为过。
收集、组织、构建和分析大规模数据的能力可能是最重要的特质…
medium.com](https://medium.com/scidex/data-is-everything-and-everyone-is-data-1886cfce2d92)
无论是在日常生活中还是在商业环境中,为了我们自己的利益利用这些数据都不是一件容易的事情。**为什么?**处理数据不仅需要相关领域的知识,还需要对数学或计算机科学(仅举几个例子)的技术理解,这对任何没有技术背景的人来说都是一个挑战。
希望能帮助初学者消除这个入门障碍,我正在写这个系列,叫做**数据会谈。**它将介绍处理数据的必要工具,更重要的是,讲述数据语言的“词汇和语法”。
该系列将包括三个部分:
- 第 1 部分:熊猫的数据操作
- **第 2 部分:**使用 Matplotlib 实现数据可视化(即将推出)
- **第 3 部分:**使用 Google Data Studio 进行数据报告(即将推出)
为了演示这些技术,我将使用来自 Kaggle 的 Kickstarter 项目数据集 。ka ggle是一个非常有用的网站,拥有大量数据集、竞赛和其他资源,可以帮助您提高数据科学技能。
来源: Kickstarter
这是给谁的?
这个系列适合完全初学者。一些关于 Python 的先验知识会有所帮助,但并不是必须遵循的。即使您熟悉所介绍的工具,您仍然可以找到一些提示和技巧来升级您的武器库。
开始之前
- 基本 Python :我们将在第 1 部分和第 2 部分使用的工具在 Python 中。Python 是一种流行而强大的编程语言,有很多应用,尤其是在数据科学领域。Python 很容易上手,所以如果你不熟悉这种编程语言,可以看看下面的文章。
首先,Python 是什么?根据它的创造者吉多·范·罗苏姆的说法,Python 是一种:
medium.com](https://medium.com/the-renaissance-developer/learning-python-from-zero-to-hero-8ceed48486d5)
- **Google 账号:**使用 GoogleColab—我们的编码环境和 GoogleData Studio。
Google Colab 是一个编码环境,你可以在其中运行 Python 代码,无需任何预先设置。很整洁,不是吗?它也是以互动的形式开发的,允许你轻松地写笔记,使它成为学习者的理想工具。
要创建新笔记本,请进入 Google Colab 然后点击新笔记本。
你会看到如下界面:
- 代码单元:这些是你编写和执行代码的地方。
- 文本单元格:你可以在这些单元格中写笔记/标题。**
熊猫
Pandas 是一个强大的 Python 库,用于处理和分析数据。它能够处理大型数据集(不像 Excel)和处理复杂的数据操作任务。在本文的剩余部分,将向您介绍 Pandas 的基本特性,以及如何在 Kickstarter 项目数据集中应用它们。
这篇文章中没有提到熊猫的许多特征。我建议你在图书馆工作时参考熊猫文档。
导入库
Pandas 没有自带 Python,所以我们首先需要将这个库导入到我们的笔记本中。幸运的是,Colab 的环境中预装了 Pandas,所以我们不必担心安装步骤。
pd
是熊猫的常用别名。****
注意pd
是我们为熊猫设置的别名(即昵称)。从现在开始,无论何时我们想使用这个库,我们都可以简单地调用pd
。****
读取数据
Pandas 支持各种输入数据源,如 csv 文件、Excel 电子表格、SQL 查询等。在本例中,我们将从 csv 文件导入 Kickstarter 项目数据集。
我们首先需要让 Colab 笔记本访问我们的 Google Drive,这是我们存储 csv 文件的地方。
运行上面的代码将生成一个链接,您可以点击它。用你的 Google 帐户登录,然后将授权码复制到运行代码后你会在 Colab 笔记本上看到的输入框中。
为了从 csv 文件中读取数据,我们使用 Pandas 方法 pamdas .read_csv()
。
方法.read_csv()
将文件的路径作为参数。您可能需要根据您放置 csv 文件的位置进行更改。数据将被读取并保存到数据帧**(我将把它保存到一个名为data
的变量中)。数据帧和**系列、是 Pandas 中使用的两种主要数据结构。
- ****数据帧是二维数组。这些就像你的 Excel 表格,有多列和多行,因此是二维的。
- ****系列是数据框架中的“列”。这些对象只是一维的,每个对象只能包含一种数据类型(如字符串、浮点、日期时间等)。)
查看数据
****
data.info()的输出
方法.info()
为我们提供了数据的汇总报告,包括行数、非空值的数量、每个系列的数据类型以及数据帧的内存使用情况。这通常是我们导入数据后做的第一件事。
为了显示数据,我们可以简单地在代码单元中写下data
(或者你给变量起的名字)并执行/运行代码单元。您可以使用快捷键 shift-enter 来完成此操作。
或者,我们可以用方法.sample(n)
显示一些随机样本。n
是我们想要显示的样本数量。例如,下面的代码打印出 Kickstarter 项目数据集中的 10 个随机行。
同样,您可以使用.head(n)
和.tail(n)
分别显示第一行和最后一行的和。
为了只选择一个或一些系列(列),我们可以将系列名称放在数据帧 data
后面的方括号[]
中。
清理数据
我们处理的数据几乎从未为直接分析做好充分准备。有时,可能会有丢失或不准确的值,这会打乱我们的计算。在其他情况下,我们将需要执行进一步的处理和工程,以进行更有意义的分析。
处理缺失数据
Pandas 有几个内置函数来处理丢失的数据。例如,方法.isnull()
过滤掉丢失的值。结合聚合方法.sum()
,这将得出每个序列中缺失值的总数。
data.isnull()的输出。总和()
在我们的例子中,序列name
中有 4 个缺失值。我们可以通过应用过滤器来进一步研究这些值是什么。
数据的输出[数据[‘名称’]。isnull()]
data['name'].isnull()
过滤掉name
系列中缺失的值。当放在数据框data
后面的方括号[]
内时,它被用作步进器。NaN
代表非数字,它是一种特殊的数值数据类型,代表未识别或缺失的值。
既然我们已经确定了丢失的值,下一步就是决定如何处理它们。最简单的方法是删除包含丢失数据的行。然而,这种方法通常应该避免,因为它减少了我们拥有的数据总量,并可能导致我们分析中的偏差。如果缺失数据在数据集中占很大比例,这种偏差可能非常显著。查看下面的文章,了解更多处理丢失数据的方法。
“归罪的想法既诱人又危险”(R.J.A .利特& D.B .鲁宾)
towardsdatascience.com](/how-to-handle-missing-data-8646b18db0d4)
对于我们的例子,name
对于我们的分析来说不是一个非常有用的序列,所以我们可以安全地用某个任意值替换这个序列中缺失的值,或者简单地从数据帧中删除这个序列。先说第一种方法。
data['name']
选择系列name
。方法.fillna()
用指定值替换所选系列中缺失的数据。参数inplace = True
告诉 Pandas 直接修改原始数据帧data
。将参数inplace = False
保留为默认值将返回一个填充了缺失值的新序列,而不是将更改应用到实际的数据帧data
。
下降系列
有时我们可能想排除一些不必要的系列。这样做的一个原因是它可以提高性能,特别是当我们处理大型数据集时。但是,在决定删除哪个系列时应该仔细考虑,因为您可能会删除有用的信息。
我们还包括参数inplace = True
来直接修改data
。
处理错误
在我们的数据中出现错误并不罕见,它可能由于多种原因而发生,从人为错误到系统故障。无论如何,我们都需要适当地处理它们,以便我们的分析更加准确。然而,识别和修复这些错误通常非常具有挑战性,因为它们不仅需要技术技能,还需要对数据集的深刻理解。
数字数据:数字数据中的错误需要各种各样的统计技术,这对于这篇介绍性文章来说可能太难了。
分类数据:检测分类数据错误的最快方法是打印出所有唯一值。
数据输出[‘国家’]。唯一()
稍微好一点的方法是使用熊猫的方法.value_counts()
,它打印出唯一的值和它们的频率。
数据输出[‘国家’]。值计数()
这个系列讲述了 Kickstarter 上的一个项目是从哪里来的。有一个奇怪的值N,0"
,好像是个错误。让我们看看它们是什么。
数据的输出[data[’ country ']= ’ N,0 ']。样本(10)
这些值是数据收集期间的错误(未定义状态和 0 支持者),由于它们只占整个数据集的 1%,我们可以删除它们。
处理日期时间数据
日期时间数据通常需要不同类型的处理。例如,我们可能想要计算两个日期之间的持续时间,或者提取时间部分(月、年、小时、分钟等。).Pandas 通过内置的日期时间函数使这些任务变得简单。
首先,我们需要转换 datetime 序列,以更正其正确的数据类型。
将截止日期和启动日期系列转换为日期时间后的输出 data.info()
为了提取任何日期时间成分,我们使用子模块dt
。
上面的代码在我们的数据框架中创建了一个关于项目启动年份的新系列。有了它,我们可以很容易地发现这个系列中的一个错误。
这段代码返回 1970 年,这没有任何意义,因为 Kickstarter 是在 2008 年成立的!这显然是一个错误,因此我们可以从数据框架中排除任何启动年份小于 2008 年的行。
为了计算项目的持续时间,我们可以取deadline
和launched
系列的差值。
这将在两个 datetime 序列之间执行元素减法,并返回一个 timedelta 序列,我们可以将它转换为月或日这样的时间组件。
我们这里需要numpy
的帮助。Numpy 是另一个非常强大的 Python 库,它增加了对数组和矩阵的支持。Pandas 构建在 Numpy 之上(还记得 DataFrame 是一个二维数组或矩阵吗?)所以这两个库配合得很好。要将时间增量转换为月份,请将'D'
转换为'M'
,或者如果您想转换为小时,请选择'h'
。点击阅读更多。**
完整的笔记本
你可以在这里 找到本文 中的数据和包含代码的 Colab 笔记本。
下一步是什么?
在接下来的几年里,熟练使用数据将成为一项基本技能。Pandas 是帮助你处理数据的一个很好的工具,尤其是当数据变得更大更复杂的时候。
在数据会谈系列的第二部分,我将讨论数据分析项目的下一步,即探索数据和提取见解。有了它,我将介绍 Matplotlib ,一个用于数据可视化的 Python 库。
- ****第 2 部分:使用 Matplotlib 进行数据可视化(待更新)
- ****第 3 部分:使用 Google Data Studio 进行数据报告(待更新)
数据—数据科学之旅的起点
数据为什么重要?有哪些类型的数据?我们如何在数据科学预测中使用数据?
什么是数据科学?
关于数据科学的有趣的事情是,它是一个年轻的领域,从教科书到报纸到白皮书,定义可能会有所不同。一般的定义是,数据科学是多种工具、算法和机器学习原则的混合物,目的是发现数据中隐藏的模式。这与已经存在并使用多年的统计数据有何不同?答案在于解释和预测的区别。
数据科学过程
数据科学由七个主要步骤组成。它们中的每一个对模型的准确性都很重要。我们来看看每一步都包含了什么。
商业理解
如果我们想创建一个数据科学项目,我们需要理解我们试图解决的问题。因此,在这一步中,我们必须得到以下问题的答案:
多少人?
哪个类别?
哪个小组?
这很奇怪吗?
-应考虑哪个选项?
基于对这些问题的回答,我们可以得出哪些变量应该被预测的结论。
数据挖掘
下一步是找到正确的数据。数据挖掘是从不同来源寻找和收集数据的过程。我们需要回答以下问题:
-项目需要哪些数据?
-我在哪里可以找到这些数据?
-如何获取数据?
-存储和访问数据的最有效方式是什么?
如果数据在一个地方,这个过程对我们来说会很容易。通常情况下,情况并非如此。
数据清理
这是最复杂的一步,需要 50%到 80%的时间。数据收集后,我们必须清理它。数据可能包含丢失的值,或者在一列中可能不一致。这就是为什么我们需要清理和组织我们的数据。
数据探索
在数据被清理之后,我们将试图在其中找到一个隐藏的模式。该步骤包括提取子集、分析和可视化子集。在此之后,我们得到了每个数据点背后的完整图像。
特征工程
在机器学习中,特征被解释为被观察到的现象的属性。例如,如果我们正在观察一个学生的成绩——一个可能的属性可能是学生获得的睡眠时间。该步骤分为两个子步骤。第一个是特征选择。在这一步中,我们可以删除一些特征,以减少可能导致模型复杂的维度。此外,我们想要删除的功能通常会带来比有用信息更多的干扰。第二个子步骤是要素构建-这意味着我们可以在现有要素的基础上构建一个新要素。
预测建模
这是我们最终建立模型的步骤。在这里,我们决定我们将使用哪个模型——基于我们在第一步获得的答案。这不是一个容易的决定,也不总是有一个答案。模型及其准确性取决于数据——数据的大小、数据的类型以及数据的质量。模型训练完成后,我们必须评估精度,确定模型是否成功。
数据可视化
在我们从模型中获得信息后,我们需要以不同的方式将它们可视化,以便被项目中的每个人理解。
商业理解
一旦一切都完成了,我们就返回到第一步,检查模型是否满足最初的需求。如果我们在生命周期的第一次迭代中遇到了新的见解(我确信我们会遇到),我们现在可以将这些知识输入到下一次迭代中,以产生更强大的见解,并释放数据的力量,为项目提取非凡的结果。
什么是数据?
我们可以看到,几乎每一步都需要数据。我们可以看到,上一部分的五个步骤中有四个是与数据相关的。因此,我们可以假设数据在数据科学项目中起着至关重要的作用。什么是数据?数据是如何定义的?这看起来似乎是一个不重要的定义,但它是。每当我们使用“数据”这个词时,我们指的是一组有组织或无组织的信息。
基本数据类型
根据上一部分的定义,有两种格式:
o **结构化(有组织的)数据:**按行/列结构分类的数据,其中每一行代表一个观察值,每一列代表该观察值的特征
o **非结构化(无组织)数据:**自由形式的数据,通常是文本或原始音频/信号,必须进一步解析才能变得有组织。
当我们谈论数据时,我们首先需要回答的是数据是定量的还是定性的。当我们谈论定量数据时,我们通常会想到结构化数据集。这两种数据类型可以定义如下:
o **量化数据:**当数据可以用数字来描述,并且在集合上可以进行基本的数学运算,包括加法。
o **定性数据:**当数据无法用数字和基础数学描述时。这些数据通常使用自然类别和语言来描述。
数据
定量数据可以是:
o **离散数据:**描述被计数的数据。它只能呈现特定的值。离散定量数据的例子包括掷骰子,因为它只能取六个值,以及咖啡店的顾客数量,因为你不能有一个真实的人群范围。
o **连续数据:**描述测量的数据。它存在于无限的价值范围内。
数据的四个层次
一般认为,结构化数据的特定特征(特征/列)可以分为四个数据级别。这些级别如下:
o 名义水平
o 序数级别
o 区间水平
o 比率水平
让我们更深入地了解每一个层次,并解释每一个层次。
名义水平
该级别包含由名称或类别描述的数据。比如性别,名字,物种等等。这些数据不能用数字来描述,所以它是定性数据,因此我们不能对这些数据进行数学运算,如加法或除法。我们可以在这个级别上执行的操作是等式和设置隶属函数。此外,我们不能使用中心的度量——中心的度量被解释为向我们显示数据趋向于什么的数字,有时它被称为数据的平衡点。为什么我们不能使用中心的测量?解释很简单——通常,当我们使用这种方法时,我们使用众数、中位数或平均值。但是,在名义水平上,我们不能使用数学运算,所以这些措施没有意义。总之,这一层由分类数据组成,我们必须小心使用这些数据——因为它可能包含对我们非常有用的见解。
序数级别
当我们谈论数学运算时,名义水平不是很灵活。序数级的数据提供了一个等级顺序,但是我们仍然不能使用更复杂的数学运算——比如减法或加法,以便获得真正的意义。例如,从 1 到 10 的等级是序数数据——如果我们想使用加法,我们不会从中获得任何有用的信息。再比如一个调查结果。在这个层次上,我们在数学运算上比在名义上有更多的自由。名义级别的数学运算(相等和集合成员)被继承,允许的附加运算是排序和比较。在顺序级别,中位数通常是定义数据中心的合适方法,但我们也可以使用该模式。然而,平均值是不可能的,因为这一级别的划分是不允许的。
间隔等级
现在,我们正在达到这样一个水平,数据可以用平均值来表示,我们可以使用更复杂的数学公式。间隔级别的数据支持数据点之间的相减。例如,包含温度的数据属于间隔级别。来自较低级别的操作(排序、比较等)被继承,并且允许的附加操作是加法和减法。当我们谈论中心的度量时,我们可以使用中位数、众数或平均值,通常,对中心最准确的描述是算术平均值。让我们看一个例子。我们试图使用包含储存疫苗的冰箱温度的数据来找到中心的度量。最佳温度必须低于 29 度。找到平均值和中值后,我们假设它们都接近 31,因此这对于我们的数据集来说是不可接受的。这就是我们需要另一个衡量标准的地方——方差或标准差。如果我们想知道我们的数据是如何分布的,我们可以使用这个方法。如果要求方差的度量,需要计算均值,从均值中减去每个点,求每个平方差的平均值,求平方根。公式如下:
如果我们在温度的例子中使用这个公式,我们可以计算数据集的标准偏差,根据这个度量,我们可以看到温度可能会下降(平均值减去标准偏差)。
比率水平
最后一个层次叫做比率层次。比率和区间水平之间没有太大的区别——有时我们可能会搞不清哪个才是正确的。在区间水平上,我们没有自然起点或自然零点,但在比率水平上——我们有。来自较低层的数学运算被继承,而附加的是乘法和除法。例如,银行账户中的钱被分类到这一级——一个银行账户可以有一个自然零。作为中心的度量,我们可以使用几何平均值—它是所有值的乘积的平方根。这个级别的数据应该是非负的,这就是为什么这个级别不是优选的。
结论
数据科学可以为任何业务增加价值,重要的是好好利用数据。此外,数据科学可以帮助我们基于可测量的证据做出更好的决策。当我们做决策时,数据应该总是可用的。使用数据科学方法,我们可以研究历史数据,与竞争对手进行比较,分析市场,最重要的是,就产品或服务的最佳表现提出建议。这些分析是数据科学的一部分,提供了对市场的深入了解和理解,以及他们对产品或服务的反馈。据估计,每天产生大约 25 亿千兆字节的数据。随着数据量的增加,获取对目标群体来说重要的内容可能会很困难。公司从客户那里收集的每一条数据——无论是社交媒体赞、网站访问还是电子邮件调查——都包含可以分析的数据,以便更有效地了解客户。这意味着某些群体的服务和产品是可以定制的。例如,发现年龄和收入之间的相关性可以帮助公司为以前可能没有的群体创造新的促销或优惠。
如果你对这个话题感兴趣,请随时联系我。
领英简介:https://www.linkedin.com/in/ceftimoska/
用 T5 产生数据到文本;建立一个简单而先进的 NLG 模型
通过微调 T5 实现数据到文本的 NLG 模型
作者图片
简介
自从自然语言处理领域中的序列到序列模型出现以来,我就一直在探索 NLG 模型的数据到文本生成能力。解决这个问题的早期尝试没有显示出任何有希望的结果。像简单 NLG 这样的非基于 ML 规则的方法似乎没有很好地扩展,因为它们需要格式良好的输入,并且只能执行诸如改变句子时态之类的任务。但是在语言模型的时代,每两周就会有变形金刚的新版本发布,这样的任务不再是遥不可及的梦想。
在这篇博客中,我将讨论我如何用高级深度学习模型处理数据到文本的生成问题。
模因通过图像翻转
openAI GPT-2 似乎是一个不错的选择,因为它具有引人注目的文本生成能力。但是在 NLG 2017 年数据上训练它并没有让我有所收获。模型根本没有收敛。GPT-2 的有条件和无条件文本生成能力相当不错,但是您很难找到可以处理这些任务的业务用例。
此外,根据特定领域的数据对它们进行微调有时会导致产生脱离上下文的句子
通过图像翻转进行迷因
由于 openAI(不那么开放)没有发布 GPT-3 的代码,我在该系列中只剩下第二好的,即 T5 。
型号:谷歌 T5
Google 的 T5 是一个文本到文本转换转换器,它是一个共享的 NLP 框架,所有的 NLP 任务都被重新组织成一个统一的文本到文本格式,输入和输出都是文本串。
图片来源:谷歌博客
它与只能输出一个类标签或输入范围的 BERT 型模型有很大的不同。T5 允许我们在任何 NLP 任务中使用相同的模型以及损失函数和超参数。
数据:WebNLG 2020
我使用 WebNLG Challenge 2020 的 RDF-to-text 生成任务的数据来训练 T5。
给定(a)中所示的四个 RDF 三元组,目标是生成一个像(b)这样的文本
(a)RDF 三元组
来源: WebNLG
(b)英文本
特灵于 1913 年 1 月 1 日在威斯康星州的拉克罗斯成立,总部位于爱尔兰。它有 29,000 名员工。
数据预处理
要对数据进行预处理,可以使用 Python 中的 XML WebNLG 数据读取器这里是,或者使用下面代码中给出的[xml.etree.ElementTree](https://docs.python.org/3/library/xml.etree.elementtree.html#module-xml.etree.ElementTree)
模块。(我最终使用了后者,因为我太无知了,无法阅读整个挑战文档😐)
在代码中,您可以看到我们保留了正常的三元组,并用“&&”连接多个三元组。当一个表的多行被一次输入到模型中时,它可以被认为是一个分隔符。
训练模型
像往常一样,谷歌的 TensorFlow 实现很难解释,我继续使用拥抱脸的 PyTorch 实现,并选择了 T5 基础模型。整个模型训练在 google colab 中进行。
通过图像翻转进行迷因
安装转换器库
!pip install transformers
导入所需的模块
import pandas as pdimport torchfrom transformers import T5Tokenizer, T5ForConditionalGeneration,Adafactor
加载预处理后的数据,并随机重排行,使不同长度的三元组(1 个三元组到 7 个三元组)分布在数据框中,从而快速归纳损失。
修剪掉一些数据点,这样一批就不会留下任何余数,因此可以避免一些代码行(好吧,这可能是一种粗略的做法)。
train_df=pd.read_csv(‘webNLG2020_train.csv’, index_col=[0])
train_df=train_df.iloc[ :35000,:]
train_df=train_df.sample(frac = 1)batch_size=8
num_of_batches=len(train_df)/batch_size
检测 GPU。
if torch.cuda.is_available():
dev = torch.device("cuda:0")
print("Running on the GPU")
else:
dev = torch.device("cpu")
print("Running on the CPU")
加载预训练的模型、记号化器,并将模型移入 GPU。
tokenizer = T5Tokenizer.from_pretrained(‘t5-base’)
model = T5ForConditionalGeneration.from_pretrained(‘t5-base’,
return_dict=True)#moving the model to GPU
model.to(dev)
使用推荐的 T5 设置启动 Adafactor 优化器。
optimizer = Adafactor(model.parameters(),lr=1e-3,
eps=(1e-30, 1e-3),
clip_threshold=1.0,
decay_rate=-0.8,
beta1=None,
weight_decay=0.0,
relative_step=False,
scale_parameter=False,
warmup_init=False)
基于 Html 的进度条。
from IPython.display import HTML, display
def progress(loss,value, max=100):
return HTML(""" Batch loss :{loss} <progress
value='{value}'max='{max}',style='width: 100%'>{value}
</progress> """.format(loss=loss,value=value, max=max))
现在,训练模型。
我花了大约 3-4 个小时在 Colab GPU 上运行四个纪元。
序列化模型
torch.save(model.state_dict(),'pytoch_model.bin')
t5 基础模型的配置文件可以下载并放置在与保存的模型相同的目录中。确保将其重命名为 config.json
!wget https://s3.amazonaws.com/models.huggingface.co/bert/t5-base-config.json
加载训练好的模型进行推理
确保给定的路径既有保存的模型又有配置文件。此外,如果您有一个用于执行推理的 GPU,请记住将模型和输入张量移动到 GPU。
生成的结果
现在让我们看看不同输入生成的文本输出。
作者图片
结论
我们讨论了如何构建一个从结构化数据生成文本的高级 NLG 模型。T5 的文本到文本架构使得将结构化数据(可以是文本和数字数据的组合)输入模型变得容易。我在 huggingface 的 transformer 上使用了原生 PyTorch 代码,在 WebNLG 2020 数据集上对其进行了微调。
与基于 GPT-2 的文本生成不同,这里我们不仅触发语言生成,我们还控制它!!
然而,这是该方法的基本实现,并且使用相对不太复杂的数据集来测试该模型。当用具有两个以上三元组的数据点测试模型时,它似乎忽略了数据输入中存在的一些信息。为了解决这个问题,需要做进一步的研究和大量的实验。
你可以在这个回购里找到代码
有什么问题尽管问!谢谢大家!
数据转换
理解为什么数据科学家工作中“不性感”的部分可能是最重要和最酷的部分之一
阿瑟尼·托古列夫在 Unsplash 上的照片
介绍
当我们谈论数据科学时,我们偏向于从像人工智能(AI)、机器学习(ML)、预测未来等性感的方面入手。就像我们的大脑试图从过去的经验中模拟未来一样,ML 算法从过去中工作和学习,我们的工作是为它们提供尽可能最好的学习体验。
你有没有想过如何现在就闭上眼睛,体验明天你要向广大听众发表的演讲的激情?
在本文的前半部分,我们将看看简单的用例,这些用例将帮助我们理解为什么数据转换是必不可少的,以及它如何帮助我们的分类器更好地执行。在后半部分,我们将直观地理解为什么对指数特征执行对数变换将允许我们使用线性回归对其建模。
分类环境中的数据转换
我们试图根据特征 x 将汽车分为两种类型——红色和绿色,我们在下面绘制了不同汽车 id 的 x 值。
如您所见,我们的分类器必须在红色区域周围绘制一个平行四边形边界,以准确识别不同的汽车。
现在,想想如果我们使用特征绝对(x)或|x| 而不是 x 会发生什么?
如上图,分类器可以画一条直线,对数据进行准确的分类。
多酷啊!我们通过对特征 x 执行简单的数据转换,将非线性分类问题转化为线性问题。这种转换将允许我们使用线性分类器,或者如果我们仍然希望使用复杂的非线性分类器,则减少它们的工作量。类比——想象你在幼儿园的美术课上,你的老师要求你画一条直线或一个平行四边形。你会选什么?为什么?
将问题转换成线性分类的对特征 x 的另一个操作是平方(x)。
锻炼
比方说,我们对不同的汽车有两个特征 f1 和 f2,我们把它们画在下面。你能想出(f1,f2)上的一个变换来把它转换成一个线性分类问题吗?
回答
计算并绘制(f1,f2)到(0,0)的欧几里德距离。
回归环境中的数据转换
假设我们的老板希望我们预测特定 x 的 y 值,作为一名负责任的数据科学家,我们将 y 可视化为我们的特征 x 的不同值,曲线图如下所示。
看了上面的图,我们知道 x 和 y 的关系不是线性的。考虑到散点图的形状,我们可以考虑使用指数模型,这非常有意义。但是,在此之前,让我们考虑绘制 x 和 log(y)。
一旦我们把 y 转换成 log(y),我们就可以用一条直线来模拟 x 和 log(y)。这种操作称为对数变换,用于指数数据,使其成为线性。注意,x 和 y 仍然是非线性相关的。但是,由于变换,我们可以拟合一条线性回归线,从数学上讲,从线性模型回到指数模型并不困难。
此外,线性回归是可解释性的冠军,能够通过量化不同预测因素对因变量的影响来提供可操作的见解,受到许多企业利益相关者的青睐。
结论
没有通用的数据转换方法。了解您的模型喜欢什么,并以那种格式为它提供输入,将极大地提高您的 ML 管道的性能。
一般准则:
- 可视化您的数据,尝试并了解其分布
- 选择您要使用的型号
- 根据您选择的数据和模型,为您的用例定制数据转换
请注意,有时,数据转换可能会:
- 成为唯一的出路。
- 在准确性、处理时间和可解释性方面提高性能。
- 不需要。
看完这篇文章,希望你偏从数据探索入手。在你开始训练一个复杂的模型之前,试着了解是否有任何转换会让你的机器学习模型受益。
我使用 Matplotlib 创建了本文中的所有可视化效果,代码在 this GitHub Gist 中。
最后,我想感谢我的朋友萨姆校对了这篇文章。
数据转换
📈Python for finance 系列
如何将现代机器学习应用于体积扩散分析(VSA)
警告:这里没有神奇的公式或圣杯,尽管一个新的世界可能会为你打开大门。
📈Python For Finance 系列
在预览文章中,我简要介绍了体积扩散分析(VSA)。在我们完成特征工程和特征选择后,我立即注意到两件事,第一件是数据集中有异常值,第二件是分布不接近正态分布。通过使用这里描述的、这里描述的和这里描述的的方法,我去除了大部分的异常值。现在是时候面对更大的问题了,常态。
有许多方法可以传输数据。众所周知的一个例子是一键编码,更好的例子是自然语言处理(NLP)中的单词嵌入。考虑到使用深度学习的一个优势是,它完全自动化了过去机器学习工作流程中最关键的步骤:特征工程。在后面的文章进入深度学习之前,我们先来看看一些简单的转移数据的方法,看看能否让它更接近正态分布。
在这篇文章中,我想尝试几件事。第一种是将所有特征转换成简单的百分比变化。第二个是做百分位数排名。最后,我将向您展示,如果我只选择所有数据的符号,会发生什么。像 Z-score 这样的方法,是深度学习中的标准预处理,我宁愿暂时不做。
1.数据准备
为了一致性,在所有的📈Python for finance 系列,我会尽量重用相同的数据。关于数据准备的更多细节可以在这里,这里这里和这里找到,或者你可以参考我之前的文章。或者,如果你愿意,你可以忽略下面的所有代码,使用你手头上任何干净的数据,这不会影响我们将要一起做的事情。
#import all the libraries
import pandas as pd
import numpy as np
import seaborn as sns
import yfinance as yf #the stock data from Yahoo Finance
import matplotlib.pyplot as plt #set the parameters for plotting
plt.style.use('seaborn')
plt.rcParams['figure.dpi'] = 300#define a function to get data
def get_data(symbols, begin_date=None,end_date=None):
df = yf.download('AAPL', start = '2000-01-01',
auto_adjust=True,#only download adjusted data
end= '2010-12-31')
#my convention: always lowercase
df.columns = ['open','high','low',
'close','volume']
return dfprices = get_data('AAPL', '2000-01-01', '2010-12-31')#create some features
def create_HLCV(i):
#as we don't care open that much, that leaves volume,
#high,low and close
df = pd.DataFrame(index=prices.index)
df[f'high_{i}D'] = prices.high.rolling(i).max()
df[f'low_{i}D'] = prices.low.rolling(i).min()
df[f'close_{i}D'] = prices.close.rolling(i).\
apply(lambda x:x[-1])
# close_2D = close as rolling backwards means today is
# literly the last day of the rolling window.
df[f'volume_{i}D'] = prices.volume.rolling(i).sum()
return df# create features at different rolling windows
def create_features_and_outcomes(i):
df = create_HLCV(i)
high = df[f'high_{i}D']
low = df[f'low_{i}D']
close = df[f'close_{i}D']
volume = df[f'volume_{i}D']
features = pd.DataFrame(index=prices.index)
outcomes = pd.DataFrame(index=prices.index)
#as we already considered the different time span,
#here only day of simple percentage change used.
features[f'volume_{i}D'] = volume.pct_change()
features[f'price_spread_{i}D'] = (high - low).pct_change()
#aligne the close location with the stock price change
features[f'close_loc_{i}D'] = ((close - low) / \
(high - low)).pct_change() #the future outcome is what we are going to predict
outcomes[f'close_change_{i}D'] = close.pct_change(-i)
return features, outcomesdef create_bunch_of_features_and_outcomes():
'''
the timespan that i would like to explore
are 1, 2, 3 days and 1 week, 1 month, 2 month, 3 month
which roughly are [1,2,3,5,20,40,60]
'''
days = [1,2,3,5,20,40,60]
bunch_of_features = pd.DataFrame(index=prices.index)
bunch_of_outcomes = pd.DataFrame(index=prices.index)
for day in days:
f,o = create_features_and_outcomes(day)
bunch_of_features = bunch_of_features.join(f)
bunch_of_outcomes = bunch_of_outcomes .join(o)
return bunch_of_features, bunch_of_outcomesbunch_of_features, bunch_of_outcomes = create_bunch_of_features_and_outcomes()#define the method to identify outliers
def get_outliers(df, i=4):
#i is number of sigma, which define the boundary along mean
outliers = pd.DataFrame()
stats = df.describe()
for col in df.columns:
mu = stats.loc['mean', col]
sigma = stats.loc['std', col]
condition = (df[col] > mu + sigma * i) | \
(df[col] < mu - sigma * i)
outliers[f'{col}_outliers'] = df[col][condition]
return outliers#remove all the outliers
features_outcomes = bunch_of_features.join(bunch_of_outcomes)
outliers = get_outliers(features_outcomes, i=1)features_outcomes_rmv_outliers = features_outcomes.drop(index = outliers.index).dropna()features = features_outcomes_rmv_outliers[bunch_of_features.columns]
outcomes = features_outcomes_rmv_outliers[bunch_of_outcomes.columns]
features.info(), outcomes.info()
要素数据集的信息
结果数据集信息
最后,我们将具有基于不同时间尺度的量差分析(VSA)的基本四个特征,如下所列,即 1 天、2 天、3 天、一周、一个月、2 个月和 3 个月。
- 音量:非常直接
- 范围/价差:最高价和收盘价之间的差异
- 收盘价相对于区间:收盘价是接近价格柱的顶部还是底部?
- 股票价格的变化:非常直接
2.百分比回报
我知道上面有很多代码。我们通过下面的函数将所有特征转换成简单的百分比变化。
def create_features_and_outcomes(i):
df = create_HLCV(i)
high = df[f'high_{i}D']
low = df[f'low_{i}D']
close = df[f'close_{i}D']
volume = df[f'volume_{i}D']
features = pd.DataFrame(index=prices.index)
outcomes = pd.DataFrame(index=prices.index)
#as we already considered the different time span,
#here only 1 day of simple percentage change used.
features[f'volume_{i}D'] = volume.pct_change()
features[f'price_spread_{i}D'] = (high - low).pct_change()
#aligne the close location with the stock price change
features[f'close_loc_{i}D'] = ((close - low) / \
(high - low)).pct_change()#the future outcome is what we are going to predict
outcomes[f'close_change_{i}D'] = close.pct_change(-i)
return features, outcomes
现在,让我们用聚类图来看看它们的相关性。Seaborn 的 clustermap()
层次聚类算法展示了一种将最密切相关的特征分组的好方法。
corr_features = features.corr().sort_index()
sns.clustermap(corr_features, cmap='coolwarm', linewidth=1);
基于此聚类图,为了最大限度地减少所选要素中的要素重叠量,我将移除那些与其他要素紧密配对且与结果目标相关性较小的要素。从上面的聚类图中,很容易发现[40D,60D]和[2D,3D]上的特征是成对出现的。为了了解这些特征与结果之间的关系,我们先来看看结果之间的关系。
corr_outcomes = outcomes.corr()
sns.clustermap(corr_outcomes, cmap='coolwarm', linewidth=2);
从上到下,20 天、40 天和 60 天的价格百分比变化被分组在一起,2 天、3 天和 5 天也是如此。然而,一天的股价百分比变化相对独立于这两组。如果我们选择第二天的价格百分比变化作为结果目标,让我们看看这些特性是如何与之相关的。
corr_features_outcomes = features.corrwith(outcomes. \
close_change_1D).sort_values()
corr_features_outcomes.dropna(inplace=True)
corr_features_outcomes.plot(kind='barh',title = 'Strength of Correlation');
相关系数太小,无法得出可靠的结论。我会期望最近的数据具有更强的相关性,但这里的情况并非如此。
双人情节怎么样?我们只选择那些基于 1 天时间尺度的特征作为演示。与此同时,我将close_change_1D
转换为基于它是负数还是正数的符号,以增加绘图的额外维度。
selected_features_1D_list = ['volume_1D', 'price_spread_1D', 'close_loc_1D', 'close_change_1D']
features_outcomes_rmv_outliers['sign_of_close'] = features_outcomes_rmv_outliers['close_change_1D']. \
apply(np.sign)sns.pairplot(features_outcomes_rmv_outliers,
vars=selected_features_1D_list,
diag_kind='kde',
palette='husl', hue='sign_of_close',
markers = ['*', '<', '+'],
plot_kws={'alpha':0.3});
配对图建立在两个基本图形上,直方图和散点图。对角线上的直方图允许我们看到单个变量的分布,而上下三角形上的散点图显示了两个变量之间的关系(或缺乏关系)。从上面的图中,我们可以看到,随着交易量的增加,价差越来越大。大部分价格变动位于狭窄的价差,换句话说,更大的价差并不总是伴随着更大的价格波动。无论是低交易量还是高交易量都会导致几乎所有规模的价格变动。我们可以把所有这些结论应用到上涨和下跌的日子里。
您也可以使用接近的酒吧位置,以增加更多的维度,简单地应用
features[‘sign_of_close_loc’] = np.where( \
features[‘close_loc_1D’] > 0.5, \
1, -1)
看有多少棒线的收盘价高于 0.5 或低于 0.5。
在 pair 图中,我不喜欢的一点是所有的图都浓缩了close_loc_1D
,看起来像离群值仍然存在,即使我知道我使用了一个标准偏差作为边界,这是一个非常低的阈值,338 个离群值被删除。我意识到因为 close 的位置已经是百分比变化了,在上面再加一个百分比变化没有太大意义。让我们改变它。
def create_features_and_outcomes(i):
df = create_HLCV(i)
high = df[f'high_{i}D']
low = df[f'low_{i}D']
close = df[f'close_{i}D']
volume = df[f'volume_{i}D']
features = pd.DataFrame(index=prices.index)
outcomes = pd.DataFrame(index=prices.index)
#as we already considered the different time span,
#simple percentage change of 1 day used here.
features[f'volume_{i}D'] = volume.pct_change()
features[f'price_spread_{i}D'] = (high - low).pct_change()
#remove pct_change() here
features[f'close_loc_{i}D'] = ((close - low) / (high - low))
#predict the future with -i
outcomes[f'close_change_{i}D'] = close.pct_change(-i)
return features, outcomes
去掉了pct_change()
,让我们看看现在的星团图是什么样子。
corr_features = features.corr().sort_index()
sns.clustermap(corr_features, cmap='coolwarm', linewidth=1);
聚类图现在更有意义了。所有四个基本特征都有非常相似的模式。[40D,60D],[2D,3D]配对在一起。
以及与结果相关的特征。
corr_features_outcomes.plot(kind='barh',title = 'Strength of Correlation');
长期时间尺度特征与股票价格回报的相关性较弱,而近期事件对价格回报的影响更大。
通过去掉close_loc_1D
的pct_change()
,最大的区别在于pairplot()
。
最后,close_loc_1D
变量在正确的范围内绘图。这说明我们应该小心过度设计。它可能会导致一个完全意想不到的方式。
3.百分位数排名
根据维基百科,百分位排名是
分数的百分位数等级是分数在其频率分布中等于或低于它的百分比。例如,一个测试分数大于参加测试的人的分数的 75%被认为是在第75百分位,其中 75 是百分位等级。
以下示例返回与过去 60 天期间相比,每个值的交易量的百分比等级(从 0.00 到 1.00)。
roll_rank = lambda x: pd.Series(x).rank(pct=True)[-1]
# you only pick the first value [0]
# of the 60 windows rank if you rolling forward.
# if you rolling backward, we should pick last one,[-1].features_rank = features.rolling(60, min_periods=60). \
apply(roll_rank).dropna()
outcomes_rank = outcomes.rolling(60, min_periods=60). \
apply(roll_rank).dropna()
✍Tip!
熊猫rolling()
,默认情况下,结果设置为窗口的右边缘。这意味着该窗口是向后看的窗口,从过去滚动到当前时间戳。这就是为什么对于那个窗口帧中的rank()
,我们选择最后一个值[-1]
。
更多关于rolling()
的信息,请查看官方文档。
首先,我们快速浏览一下结果的聚类图。它几乎等同于顺序不同的百分比变化。
corr_outcomes_rank = outcomes_rank.corr().sort_index()
sns.clustermap(corr_outcomes_rank, cmap='coolwarm', linewidth=2);
同样的模式也适用于要素的聚类图。
corr_features_rank = features_rank.corr().sort_index()
sns.clustermap(corr_features_rank, cmap='coolwarm', linewidth=2);
即使使用不同的方法,
# using 'ward' method
corr_features_rank = features_rank.corr().sort_index()
sns.clustermap(corr_features_rank, cmap='coolwarm', linewidth=2, method='ward');
当然,特征和结果的相关性也是一样的。
corr_features_outcomes_rank = features_rank.corrwith( \
outcomes_rank. \
close_change_1D).sort_values()corr_features_outcomes_rank
corr_features_outcomes_rank.plot(kind='barh',title = 'Strength of Correlation');
最后,你可能会猜到结对图也是一样的。
selected_features_1D_list = ['volume_1D', 'price_spread_1D', 'close_loc_1D', 'close_change_1D']
features_outcomes_rank['sign_of_close'] = features_outcomes_rmv_outliers['close_change_1D']. \
apply(np.sign)sns.pairplot(features_outcomes_rank,
vars=selected_features_1D_list,
diag_kind='kde',
palette='husl', hue='sign_of_close',
markers = ['*', '<', '+'],
plot_kws={'alpha':0.3});
因为我们在集合窗口中使用了百分位等级(从 0.00 到 1.00),所以斑点均匀地分布在所有特征上。与未经变换的相同数据相比,所有特征的分布或多或少接近正态分布。
4.签署
最后同样重要的是,我想删除所有的数据颗粒,看看这些功能在这种情况下是如何关联的。
features_sign = features.apply(np.sign)
outcomes_sign = outcomes.apply(np.sign)
然后再次计算相关系数。
corr_features_outcomes_sign = features_sign.corrwith(
outcomes_sign. \
close_change_1D).sort_values(ascending=False)corr_features_outcomes_sign
corr_features_outcomes_sign.plot(kind='barh',title = 'Strength of Correlation');
现在看来有点怪,像volume_1D
和price_spread_1D
和现在的胜负相关性很弱。
幸运的是,聚类图基本保持不变。
corr_features_sign = features_sign.corr().sort_index()
sns.clustermap(corr_features_sign, cmap='coolwarm', linewidth=2);
结果之间的关系也是如此。
corr_outcomes_sign = outcomes_sign.corr().sort_index()
sns.clustermap(corr_outcomes_sign, cmap='coolwarm', linewidth=2);
至于 pair plot,由于所有数据都被转移到-1 或 1,它没有显示任何有意义的东西。
有时对数据进行“标准化”或“规范化”是至关重要的,这样我们才能在不同尺度的特征之间进行公平的比较。我很想用 Z-score 来标准化数据集。
Z 得分的公式需要平均值和标准差,通过计算整个数据集的这两个参数,我们有机会看到未来。当然,我们可以再次利用滚动窗口。但一般来说,人们会在将数据注入模型之前对其进行标准化。
总之,通过利用 3 种不同的数据转换方法,现在我们很有信心可以选择最相关的特性并丢弃那些大量的特性,因为所有 3 种方法几乎共享相同的模式。
5.平稳和正态性检验
最后一个问题转换后的数据能通过平稳性/正态性检验吗?这里,我将使用扩展的 Dickey-Fuller 检验,这是一种叫做单位根检验的统计检验。同时,我还想看看偏斜度和峰度。
import statsmodels.api as sm
import scipy.stats as scs
p_val = lambda s: sm.tsa.stattools.adfuller(s)[1]def build_stats(df):
stats = pd.DataFrame({'skew':scs.skew(df),
'skew_test':scs.skewtest(df)[1],
'kurtosis': scs.kurtosis(df),
'kurtosis_test' : scs.kurtosistest(df)[1],
'normal_test' : scs.normaltest(df)[1]},
index = df.columns)
return stats
检验的零假设是时间序列可以用一个单位根来表示,它不是平稳的(具有一些依赖于时间的结构)。另一个假设(拒绝零假设)是时间序列是平稳的。
- 零假设(H0) :如果没有被拒绝,说明时间序列有单位根,意味着它是非平稳的。它有一些依赖于时间的结构。
- 备选假设(H1) :拒绝零假设;这表明时间序列没有单位根,这意味着它是平稳的。它没有依赖于时间的结构。
以下是来自增强迪基-富勒测试的结果:
对于功能和结果:
features_p_val = features.apply(p_val)
outcomes_p_val = outcomes.apply(p_val)
outcomes_p_val,features_p_val
测试可以通过 p 值来解释。低于阈值的p-值(如 5%或 1%)表明我们拒绝零假设(平稳),否则,高于阈值的p-值表明我们不能拒绝零假设(非平稳)。
- p-值> 0.05 :不能拒绝零假设(H0),数据有单位根,非平稳。
- p-值< = 0.05 :拒绝零假设(H0),数据没有单位根,是平稳的。
从这个测试中,我们可以看到所有的结果都远低于 5%,这表明我们可以拒绝零假设,所有转换的数据都是平稳的。
接下来,我们来测试正态性。
build_stats(features_outcomes_rmv_outliers)
对于正态分布的数据,偏斜度应该大约为零。对于单峰连续分布,大于零的偏斜值意味着分布的右尾有更多的权重,反之亦然。
scs.skewtest()
检验样本总体的偏斜度与相应正态分布的偏斜度相同的原假设。由于所有的数字都低于 5%的阈值,我们不得不拒绝零假设,并说偏斜度不符合正态分布。同样的事情去scs.kurtosistest()
。
scs.normaltest()
检验样本来自正态分布的原假设。它基于 D’Agostino 和 Pearson 的测试,结合了偏斜度和峰度,以产生一个正态性的综合测试。同样,所有数字都低于 5%阈值。我们必须拒绝零假设,并说由百分比变化转换的数据不是正态分布。
我们可以对通过百分比排名和签名转换的数据进行同样的测试。我不想让事情变得更复杂,把人们吓跑。在这篇文章太长之前,我最好在这里结束。
参考
- 麦金农,J.G. 1994。单位根和协整检验的近似渐近分布函数。《商业与经济统计杂志》12,167–76。
- 达戈斯蒂诺,R. B. (1971),“中等和大样本量的正态性综合检验”,《生物计量学》,58,341–348
- 达戈斯蒂诺,r .和皮尔逊,E. S. (1973),“偏离正态性的检验”,《生物计量学》,60,613–622
PySpark 中的数据转换
PySpark 中数据转换的演练
图片来自PexelsMarkus Spiske
现在,数据的增长速度超过了处理速度。这个问题的众多解决方案之一是在大型集群上并行计算。输入 PySpark。
然而,PySpark 要求您以不同的方式考虑数据。
而不是逐行查看数据集。PySpark 鼓励您从专栏的角度来看待它。起初,这对我来说是一个艰难的转变。我会告诉你我学到的主要技巧,这样你就不用浪费时间去寻找答案了。
资料组
我将使用来自 Kaggle 的有害空气污染物数据集。
这个数据集是8,097,069
行。
df = spark.read.csv(‘epa_hap_daily_summary.csv’,inferSchema=True, header =True)
df.show()
作者图片
条件 If 语句
我们要做的第一个转换是条件 if 语句转换。如下所示:如果数据集中的一个单元格包含一个特定的字符串,我们希望更改另一列中的单元格。
基本上我们想从这里开始:
作者图片
对此:
作者图片
如果local site name
包含单词police
,那么我们将is_police
列设置为1
。否则我们将其设置为0
。
这种条件如果在熊猫身上陈述是相当容易做到的。我们会使用[pd.np.where](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.where.html)
或[df.appl](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.apply.html)y
。在最坏的情况下,我们甚至可以遍历这些行。我们在 Pyspark 做不到这些。
在 Pyspark 中,我们可以使用[F.when](https://spark.apache.org/docs/2.1.0/api/python/pyspark.sql.html#pyspark.sql.functions.when)
语句或[UDF](https://spark.apache.org/docs/2.2.0/api/python/pyspark.sql.html#pyspark.sql.functions.udf).
语句,这允许我们获得与上面相同的结果。
from pyspark.sql import functions as Fdf = df.withColumn('is_police',\
F.when(\
F.lower(\
F.col('local_site_name')).contains('police'),\
F.lit(1)).\
otherwise(F.lit(0)))df.select('is_police', 'local_site_name').show()
作者图片
现在假设我们想扩展我们上面所做的。这一次,如果一个单元格包含 3 个字符串中的任何一个,那么我们将在另一列中更改相应的单元格。
如果任何一个字符串:'Police', 'Fort' , 'Lab'
在local_site_name
列中,那么我们将相应的单元格标记为High Rating
。
与我们之前看到的F.when
函数结合的[rlike](https://spark.apache.org/docs/2.2.0/api/python/pyspark.sql.html#pyspark.sql.Column.like)
函数允许我们这样做。
parameter_list = ['Police', 'Fort' , 'Lab']df = df.withColumn('rating',\
F.when(\
F.col('local_site_name').rlike('|'.join(parameter_list)),\
F.lit('High Rating')).\
otherwise(F.lit('Low Rating')))df.select('rating', 'local_site_name').show()
作者图片
F.when
实际上对很多不同的事情都有用。事实上你甚至可以做一个连锁F.when
:
df = df.withColumn('rating', F.when(F.lower(F.col('local_site_name')).contains('police'), F.lit('High Rating'))\
.when(F.lower(F.col('local_site_name')).contains('fort'), F.lit('High Rating'))\
.when(F.lower(F.col('local_site_name')).contains('lab'), F.lit('High Rating'))\
.otherwise(F.lit('Low Rating')))df.select('rating', 'local_site_name').show(
作者图片
这与我们在前面的例子中看到的完全一样。然而,要写的代码更多,要维护的代码也更多。
我更喜欢上面讨论的rlike
方法。
删除空白
空白真的很烦人。它确实会影响字符串匹配,并会导致查询中不必要的错误。
在我看来,尽快删除空白是个好主意。
[F.trim](https://spark.apache.org/docs/2.1.0/api/python/pyspark.sql.html#pyspark.sql.functions.trim)
允许我们这样做。它将删除指定列中每一行的所有空白。
df = df.withColumn('address', F.trim(F.col('address')))
df.show()
作者图片
删除特定列的空行
假设我们只想删除一列中的空行。如果我们在pollutant_standard
列中遇到NaN
值,则删除整行。
这可以相当简单地完成。
filtered_data = df.filter((F.col('pollutant_standard').isNotNull())) # filter out nulls
filtered_data.count()
条件 OR 参数允许删除我们event_type
或site_num
所在的行NaN.
这就是所指的的 |
。
filtered_data = df.filter((F.col('event_type').isNotNull()) | (F.col('site_num').isNotNull())) # filter out nulls
filtered_data.count()
df.na.drop 允许我们删除所有列都是NaN
的行。
filtered_data = df.na.drop(how = 'all') # filter out nulls
filtered_data.show()
结论
PySpark 仍然是一门相当新的语言。可能正因为如此,互联网上没有太多的帮助。像熊猫或 R 这样的东西有丰富的信息。有了 Spark 就完全不是这么回事了。
所以我希望这些代码能帮助到一些人。他们肯定会帮助我,节省我很多时间。我经历的转变可能看起来很小或微不足道,但当它涉及到 Spark 时,没有多少人谈论这些东西。我希望这能在某种程度上帮助你。
如果我犯了一个错误,或者你想联系我,请随时通过 twitter 联系我。
原载于 2020 年 9 月 6 日https://spiyer 99 . github . io。
R 中的数据转换
带 tidyverse 包
D ata T 转换是从事商业数据分析、数据科学甚至人工智能前期工作的关键方面之一。在本练习中,我们将了解如何在 R 中转换数据。 R 是一种开源的统计计算和机器学习编程语言,由 R 统计计算基金会提供支持。使用其广泛使用的集成开发环境- RStudio 既易学又舒适。这里我们要用的 R 包是tidy verse。
tidyverse 是专为数据科学设计的 R 包集合。所有的包共享一个底层的设计哲学、语法和数据结构。
dplyr&tidyr包 tidyverse 中的函数主要完成数据转换的工作。
让我们先安装并加载这个包
**install.packages("tidyverse")
library(tidyverse)**
注意:您只需要安装软件包一次,但是每次启动环境时都需要加载软件包。
这些是我们将在本文中研究的功能—
- 排列():对观察值进行排序
- select() :选择变量或列
- filter() :根据观察值过滤观察值
- gather() :将观察从列转移到行
- spread() :将变量从行移动到列
- group _ by()&summary():将数据进行分组汇总
- mutate() :从现有变量创建新变量
排列()
按变量排列行
埃菲社在 Unsplash 上拍摄的照片
该函数按顺序排列观察值。它将一个列名或一组列名作为参数。对于单个列名,它将该列的数据与该列后面的其他列一起排序;对于多个列名,每个附加的列都会打断前面列的值。
为了展示这一点,我们将加载 mpg 数据集。它有 38 种流行车型从 1999 年到 2008 年的燃油经济性数据。
?mpg **data(mpg)
View(mpg)**
作者图片
首先,我们将根据 displ 列对观察结果进行排序。默认情况下,该列的值将按升序排列,其他列将遵循 displ 列的顺序。
**mpg_arrange1 <- mpg %>% arrange(displ)**
View(mpg_arrange1)
作者图片
然后我们将在参数中添加更多的两个列名—cty&hwy。
**mpg_arrange2 <- mpg %>% arrange(displ, cty, hwy)**
View(mpg_arrange2)
作者图片
我们可以看到第二( cty )和第三( hwy )列分别打破了第一( displ )和第二( cty )列的值之间的联系。
为了按降序排列观察值,将使用 desc() 函数
**mpg_arrange3 <- mpg %>% arrange(desc(displ))**
View(mpg_arrange3)
作者图片
注意:如果有任何丢失的值,那么这些值将总是在末尾排序
选择()
按名称选择变量
亚历山大·席默克在 Unsplash 上拍摄的照片
我们将在这里使用相同的 mpg 数据集
?mpg **data(mpg)
View(mpg)**
作者图片
现在我们将选择三列— displ , cty & hwy 到一个新的数据帧
**mpg_select1 <- mpg %>% select(displ, cty, hwy)**
View(mpg_select1)
图片由 RStudio 作者提供
如果我们想选择从 displ 到 hwy 的所有列,我们可以写如下
**mpg_select2 <- mpg %>% select(displ : hwy)**
View(mpg_select2)
图片由 RStudio 作者提供
过滤器()
按条件过滤观察值
比尔·牛津在 Unsplash 上拍摄的照片
为此,我们将使用钻石数据集,看看如何根据条件选择观察值。
?diamonds
**data(diamonds)
View(diamonds)**
图片由 RStudio 作者提供
我们可以检查列值的汇总
> **summary(diamonds$carat)**
***Min. 1st Qu. Median Mean 3rd Qu. Max.***
0.2000 0.4000 0.7000 0.7979 1.0400 5.0100> **summary(diamonds$price)**
***Min. 1st Qu. Median Mean 3rd Qu. Max.***
326 950 2401 3933 5324 18823> **table(diamonds$cut)
*Fair Good Very Good Premium Ideal***
1610 4906 12082 13791 21551
让我们只过滤掉 理想的 切工的钻石
**diamonds_filter1 <- diamonds %>% filter(cut == 'Ideal')**
View(diamonds_filter1)
作者图片
现在让我们过滤 理想高级 切割钻石
**diamonds_filter2 <- diamonds %>%
filter(cut == c('Ideal', 'Premium'))**
View(diamonds_filter2)
作者图片
这就是我们如何过滤价格大于 2500 的钻石
**diamonds_filter3 <- diamonds %>% filter(price > 2500)**
View(diamonds_filter3)
作者图片
现在我们将在三列中应用滤镜: 理想 切工0.54克拉钻石与价格 1266
**diamonds_filter4 <- diamonds %>%
filter(cut == 'Ideal', carat == 0.54, price == 1266)**
View(diamonds_filter4)
作者图片
我们来看一个更复杂的过滤标准——理想 切, 介于 0.4 和(&)1.0克拉同价格** 小于 580 或者( | 大于 10000 适当的逻辑运算符将被用来表达这些条件。
**diamonds_filter5 <- diamonds %>%
filter(cut == 'Ideal' ,
carat >= 0.4 & carat <= 1.0 ,
price < 580 | price > 10000)**
View(diamonds_filter5)
作者图片
不是(! ) 运算符需要非常小心地使用。在使用时,我们需要牢记德摩根定律。本法写明 !(x & y) 同 !x |!y ,还有 **!(x | y)**同 !x &!yT91。
**diamonds_filter6 <- diamonds %>%
filter(cut != 'Ideal',
!(carat >= 0.4 & carat <= 1.0) ,
!(price < 580 | price > 10000))**
View(diamonds_filter6)
作者图片
聚集()
将列收集到键值对中
菲尔·科夫曼在 Unsplash 上拍摄的照片
有时,我们可以有一个数据集,其中的观察值是在列名中找到的,需要收集到具有新列名的变量下。让我们先构建数据集。
**Country_Name** <- c('Qatar', 'United States', 'Germany',
'Canada', 'United Kingdom')
**Y2009** <- c(59094, 47099, 41732, 40773, 38454)
**Y2010** <- c(67403, 48466, 41785, 47450, 39080)
**Y2011** <- c(82409, 49883, 46810, 52101, 41652)**gdp <- data.frame(Country_Name, Y2009, Y2010, Y2011)
View(gdp)**
作者图片
该数据集可视为五个国家 2009 年、2010 年和 2011 年的 GDP 数据。可以清楚地看到,Y2009,Y2010 & Y2011 这些列名本身就是观测值,应该在一个变量或列名之下- ’ Year '。我们将通过 gather() 函数来实现。
**gdp_gather <- gdp %>% gather("Year", "GDP" , 2:4)**
View(gdp_gather)
作者图片
为了让这个数据集为数值分析做好准备,我们需要从年值中删除字符“ Y ”(或任何字符),并将其从字符转换为整数。
**gdp_gather$Year <- gsub("[a-zA-Z]", "", gdp_gather$Year)
gdp_gather$Year <- as.integer(gdp_gather$Year)**
View(gdp_gather)
glimpse(gdp_gather)
作者图片
作者图片
传播()
将键值对分布在多个列中
有时,我们可以看到变量分布在数据集中的观察值中。在这种情况下,我们需要将它扩展到列名。让我们用键值构建一个数据集。
**Student** <- c('Jack', 'Jack', 'Jack', 'Jack', 'Jack', 'Jack',
'Rose', 'Rose', 'Rose', 'Rose', 'Rose', 'Rose')
**Subject** <- c('English', 'Biology', 'Chemistry', 'Maths', 'Physics',
'Social Science', 'English', 'Biology', 'Chemistry',
'Maths', 'Physics', 'Social Science')
**Marks** <- c(80, 70, 87, 75, 90, 82, 65, 70, 88, 92, 79, 93)**reportCard <- data.frame(Student, Subject, Marks)**
**View(reportCard)**
作者图片
在这个报告卡数据集中,如果我们将主题名称视为变量,那么它需要扩展到列名称。我们将通过 spread() 函数来实现。
**reportCard_spread1 <- reportCard %>% spread(Subject, Marks)**
View(reportCard_spread1)
作者图片
如果我们将学生的名字视为变量-
**reportCard_spread2 <- reportCard %>% spread(Student, Marks)**
View(reportCard_spread2)
作者图片
group _ by()& summary()
按变量分组&将多个值减少到一个值
照片由塞维多夫·热莫夫斯基在 Unsplash 拍摄
这些是非常有用的函数,它们组合在一起将值汇总成组。这里我们将使用 msleep 数据集。它包含了一些哺乳动物的睡眠数据和体重数据。
?msleep
**data(msleep)**
colnames(msleep)
**msleep <- msleep %>% select(name, order, sleep_total, bodywt)
View(msleep)**
作者图片
我们将 sleep_total 汇总到其平均值值- sleep_avg 和 bodywt 到其最大值值- bodywt_max 。该汇总将按订单分组,每个订单观察的数量将在计数栏下。这些都将由 group_by() 和**summary()**用数学函数- n() 、 mean() 和 max() 来完成。
**msleep_groupby_summarize <- msleep %>% group_by(order) %>%
summarise(
count = n(),
sleep_avg = mean(sleep_total),
bodywt_max = max(bodywt)
)**
View(msleep_groupby_summarize)
作者图片
变异()
创建或转换变量
克里斯·劳顿在 Unsplash 上拍摄的照片
在数据分析中,从现有变量推导出新变量是非常常见的。这里我们将使用航班数据集。它有 2013 年从纽约起飞的所有航班的准点数据。为了得到这个数据集,我们需要安装并加载包nyflights 13。
**install.packages("nycflights13")**
**library(nycflights13)**?flights
**data(flights)**
colnames(flights)
**flights <- flights %>% select(year, month, day, dep_delay,
arr_delay, distance, air_time )
View(flight)**
作者图片
现在我们将通过从 dep_delay 中减去 arr_delay 来创建两个新变量- time_gain 以及通过将距离除以 air_time 和乘以 60 来创建速度。
**flights_mutate <- flights %>%
mutate(time_gain = dep_delay - arr_delay ,
speed = distance / air_time * 60)**
View(flights_mutate)
作者图片
所以现在就这样了。我建议您使用不同的数据集以及您自己的数据来练习这种数据转换功能。这可能是你进入数据科学这一惊人领域的第一步。祝你接下来的旅程一切顺利!
你也可以看看我关于数据可视化的文章
R 语言中的“图形语法”一瞥
towardsdatascience.com](/data-visualization-with-ggplot2-db04c4956236)
数据可信度
如果收件人值得信任,泄露一些个人隐私不一定是件坏事
本·怀特在 Unsplash 上的照片
想象一下,你有一条敏感信息,你必须告诉至少一个人。你会把它告诉那个众所周知爱说长道短、经常走漏风声的人,还是那个把你的秘密看得不仅仅是有趣的细节、而且非常负责任地保管这些信息的人?你会告诉那个你几乎不认识,但你听说过的值得信任的人,还是那个你已经认识一段时间并赢得你信任的人?你会告诉那个听到这个敏感信息后会问十个不同的后续问题的人,还是那个重视你给他们的信息而不会追问你更多信息的人?
希望这些问题已经帮助你明确了在敏感信息方面你认为什么样的人是值得信任的。
随着政府处理当前的新冠肺炎疫情,隐私已经让位于更大的利益,这种趋势在当前危机之前我们已经在医疗数据中看到了(见这篇文章讨论了医疗数据的使用,以及这篇后续文章关于我们如何开始看到这种情况在疫情发生)。最近,我看了 Vox 关于韩国相当成功地应对新冠肺炎病毒的视频,其中一段话让我特别感兴趣,下图是疾病控制和预防中心的韩国主任说的。
视频截图链接此处(同上)
事实是,为了公众健康,我们现在可能不得不放弃一些隐私,特别是如果我们想得到像韩国那样有效的回应。然而,放弃一些隐私并不等同于放弃我们在余下的数字生活中所有的隐私权。至少,不一定是这个意思。正如《纽约时报》的这篇文章所描述的,一月份,韩国当局公布了大量感染新冠肺炎病毒的人的信息。由于韩国是一个网络发达的社会,这些人很快就被抓了起来,并被公开羞辱。作为回应,卫生官员本月宣布,“他们将完善数据共享指南,以将患者风险降至最低。”通过这样做,他们证明了自己是敏感个人数据的更周到、更值得信赖的管理者。事实上,韩国疾病控制和预防中心主任郑恩景最近说:
“我们将在保护个人人权和隐私的价值与维护公共利益防止大规模感染的价值之间取得平衡”
还记得在这篇文章的开头,我让你想象你会和什么样的人分享敏感的个人信息吗?从这些问题中,你可能已经确定了一个人,他有着重视敏感信息、尊重你和信息敏感性的良好记录。简而言之,他们已经证明了自己在数据方面是值得信赖的。上述声明以及韩国卫生官员正在采取的措施证明,韩国政府正在积极努力成为公共数据的可信管理者。
当然,这种敏感数据的获取和使用远不止发生在韩国。我们看到技术正被用于跟踪像波兰、T2、以色列、T4、法国和其他许多地方的人。正如美国人从 911 袭击的后果中知道的那样,一旦这些许可被授予,就很难再取消。此外,随着我们进入一个更加数据驱动的时代,无论我们喜欢与否,我们的个人数据可能会变得越来越容易获取。这就是为什么我们开发具体的方法来确保拥有我们数据的人是值得信赖的管理者更加重要。如果像政府这样的机构想要访问我们的数据,我们需要确保它们是可信的,而确保它们保持可信的最佳方式是明确定义“可信”的含义。当然,这是一项艰巨的任务,因为这个定义可能会根据你交谈的对象而有所不同。然而,回想一下我在开始时问的那个假设的值得信任的人,我认为我们确实普遍同意让一个人值得信任的某些特质,例如以这样一种方式行事,一个人不会获取超过他们需要的信息,并确保敏感信息不会无意中传播给其他人。
在我上周的文章中,我讨论了轻视个人隐私的文化是如何导致灾难性后果的,正如最近的 Zoom 安全问题所展示的那样。上周,我指出了轻视隐私的文化的负面影响,而本周,我想指出重视个人隐私的文化的正面影响,这种文化就像是在韩国医疗机构对新冠肺炎事件的反应中培养的那种文化。是的,当他们在一月份发布敏感信息时,他们肯定犯了很大的错误,但他们利用这个机会赢得了公众的信任,并且在处理数据时更加小心。如果损失的是值得信赖、安全的一方,他们会负责任地处理数据,不会要求超出他们需要的东西,并且已经证明他们积极重视人权和隐私,那么一定程度的隐私损失不一定是坏事。
没有任何科学是非政治性的,数据科学也不例外。在我们生活的这个数据密集的现实中尤其如此。有鉴于此,数据科学家不应将他们的目标局限于获得最佳准确度或精确度分数。尤其是当我们处理越来越多的敏感信息时,我们的目标不应该总是“获取更多数据”我们的目标应该是,“充分利用我们所拥有的一切。”也许这有时会有局限性,但是一些最好的创新来自于适应局限性。
数据科学中的数据一致性
处理熊猫最常见的一致性问题
介绍
在我以前关于数据清理的文章中,我谈到了超出范围的值、不正确的数据类型、唯一性约束是如何成为常见问题的,如果不加以处理,会严重影响我们的分析。
在本文中,我们将解决一个同样危险的问题,它同样会扭曲我们的分析,这就是单元一致性。
与一致性相关的问题有多种形式:
- 华氏和摄氏温度数据
- 重量以千克和磅表示
- 多种日期格式
- 用不同货币表示的货币
这些问题的出现有很多原因。例如,跨多个位置收集数据并合并到一个位置。这会导致上述问题。您必须知道如何处理一致性问题,以便进行准确的分析。
设置
people.head()
单位一致性
考虑之前导入的这个温度数据集。它以摄氏度为单位给出了 3 个月的日平均温度信息:
temperatures.sample(10)
如果我们看指数 48,除非发生重大气候事件,我们可以猜测值是以华氏温度给出的:
图片由 作者
在这种情况下,使用散点图直观地发现它们:
散点图清楚地显示了华氏温度值。快速的谷歌搜索向我们展示了将华氏温度转换为摄氏温度的公式:
图片由 作者
现在,我们将使用该等式将 40 以上的任何值转换为摄氏度:
我们可以通过两种方式检查转换是否成功。首先,用assert
声明:
再次使用散点图:
尽管这是一个简单的例子,但你的情况可能完全不同。有时,你可能甚至没有注意到数据海洋中的不一致。在寻找它们之前,你必须完全了解你的数据,并了解这些数据是如何收集的。
日期一致性
另一个非常普遍的问题是日期一致性。不同的国家有不同的标准日期时间格式,当您有来自多个来源的数据时,您将不得不处理多种日期格式。在 Python 中,有 3 种主要的日期时间格式可供使用:
- 25–12–2019–>(% d-% m-% Y)->年,月,日
- 2020 年 10 月 31 日-> (%c) - >字面日期
- 12–25–2019–>(% m-% d-% Y)->月,日,年
当您使用pandas
将数据加载到您的环境中时,它总是将日期作为object
数据类型导入。在设置部分,我们导入了包含人的全名和生日的示例数据:
people.sample(5)
birthday
列用 YY-MM-DD 格式表示日期,但用字符串表示。将日期列转换为datetime
对于执行分析有很多好处。我们将使用pd.to_datetime()
功能将列转换为datetime
:
我们出错了!如果我们仔细看,错误说月份必须在 1,2,…,12。这意味着,在数据的某个地方,有一个不一致的值阻止了函数的运行。pd.to_datetime
对此类情况有一个很好的解决方法:
这一次,我们没有出现任何错误。如果您将infer_datetime_format
设置为True
,pandas
将根据第一个非 NaN 元素自动识别日期格式,并将其余部分转换为该格式。如果有任何值不适合转换,errors
参数决定如何处理它们。如果设置为coerce
,pandas
将放置NaT
为缺失的日期值。
基于我们的假设,上面的代码行应该已经发现了日期不一致,并将NaT
放入不一致的日期:
有几种方法可以处理这种不一致:
- 转换为 NA 并进行相应处理
- 通过查看数据源推断格式,它是如何收集的
- 通过查看其他日期来推断格式
如果你有许多不一致,将它们转换成NaN
并不总是一个选项。您应该通过观察它们的模式和推断它们的格式来尝试提出定制的解决方案。
完成错误处理和转换后,最佳做法是将日期列转换为全局日期时间标准:
图片由 作者
如果你喜欢这篇文章,请分享并留下反馈。作为一名作家,你的支持对我来说意味着一切!
阅读更多与主题相关的文章:
处理常见的数据问题
towardsdatascience.com](/data-type-constraints-data-range-constraints-duplicate-data-with-pandas-44897a350b1e) [## 掌握 DS/ML 中最讨厌的任务
用 Pandas 清理分类数据
towardsdatascience.com](/master-the-most-hated-task-in-ds-ml-3b9779276d7c) [## FuzzyWuzzy:Python 中的模糊字符串匹配,初学者指南
…以及在真实数据集上的动手实践
towardsdatascience.com](/fuzzywuzzy-fuzzy-string-matching-in-python-beginners-guide-9adc0edf4b35) [## 认识熊猫最难的功能,第一部分
掌握 pivot_table()、stack()、unstack()的时机和方式
towardsdatascience.com](/meet-the-hardest-functions-of-pandas-part-i-7d1f74597e92) [## 来自 Kagglers:DS 和 ML 的最佳项目设置
来自顶级 Kagglers 的项目成功最佳实践的集合
towardsdatascience.com](/from-kagglers-best-project-setup-for-ds-and-ml-ffb253485f98) [## 我的情节糟透了。以下是我如何修复它们。
你的,在某种意义上,可能也是。
towardsdatascience.com](/deep-guide-into-styling-plots-delivering-effective-visuals-12e40107b380)
数据验证:应对大数据管理挑战的关键解决方案
由于数据验证仍然是当今数据驱动型公司面临的最大挑战之一,这里有一个适用于全球技术团队的有效改进解决方案。
数据验证预计将是 2020 年电子商务网站可能面临的最大挑战之一。在本文中,我们将回顾一些关键统计数据,强调当前影响大数据公司的主要数据验证问题。这篇文章的最终目的是为技术团队提供一个质量改进的解决方案。
全球范围内,零售电子商务公司的销售额持续快速增长。2019 年,全球销售额达到 35,350 亿美元,据 Statista 统计,这些数字将在 2023 年翻近一番,达到 65,420 亿美元之多。
随着电子商务的持续增长,存储的数据也在增长。仅电子商务的数据量就将呈指数级增长。希捷的《2025 年数据时代报告》预测,到 2025 年,全球数据空间将达到 175 兆字节。
但是,只有一小部分从竞争对手和公开来源收集的数据将用于分析。这是因为电子商店接收非标准数据,无论是来自第三方供应商还是通过他们自己构建的抓取基础设施。他们通常收集的数据是未格式化的,并且是原始格式,例如 HTML,因此很难阅读。
我们在 Oxylabs 的客户也面临这些挑战,因为我们的大多数电子商务客户都处理大数据。本文旨在指出数据管理的主要难点,并为任何处理大数据的技术团队提供解决方案和捷径。
主要数据管理问题
体积增长
数据管理将是 2020 年大数据面临的最大挑战之一。不仅进入组织的信息量将难以存储和组织,而且非结构化数据流的涌入将减慢任何分析流程,中断工作流。
不同的数据格式
数据量增长并不是唯一的问题。不同的数据格式及其变体也在增长。举个例子,有些网站提供的日期是 CSV 格式,如 YYYY-MM-DD,而其他网站的标准是 JSON ,格式为 MM/DD/YYYY。在读取非标准化数据时,这种看似很小的差异可能会导致很大的错误。
数据有效性
当范围的增长速度超过人力资源的增长速度时,必须考虑使用自动化来处理这些任务。近 90%的公司表示他们已经实现了部分数据管理流程的自动化。这包括分析和报告形式的后端以及前端和数据过滤。这就是我们的数据管理解决方案数据验证发挥作用的地方。
什么是数据验证?
数据验证是一种检查和调整数据(通常在导入和处理之前)的准确性和质量的方法或功能。根据您使用的验证选项(我们将在本文后面介绍不同的 Cerberus 验证选项),它可以成为一个自定义验证,确保您的数据是完整的,包含不同的值,并确保它们不会重复,并确保值的范围是一致的。
简而言之,数据验证允许您执行分析,知道您的结果将是准确的。那么,什么方法或库可以用于顺利的数据验证过程呢?
Cerberus:强大的数据验证功能
Cerberus 提供强大而简单的轻量级数据验证功能。它被设计成易于扩展,允许自定义验证。简单来说,它是 Python 的一个验证库。
请注意,我们选择 Cerberus 作为例子,因为验证模式是语言不可知论者(JSON ),可以很好地与其他语言一起工作,使它更灵活地适应各种工作流。
Cerberus 基本工作流程
要使用 Cerberus 验证您的数据,您需要做的就是定义规则。这是通过一个叫做模式的 python 字典对象来完成的。
假设您有 JSON 人员数据集:
```json**[**{**"name": "john snow",**"age": 23,**"fictional": True,**},**...**}```*
你希望确保它的有效性。您可以定义的最基本的模式如下所示:
```python**schema = {**"name": {"type": "string", "required": True},**"age": {"type": "int"},**"fictional": {"type": "bool"},**}```*
这里我们为个人数据字段定义了严格的类型:姓名必须是字符串,年龄必须是整数,虚构的必须是布尔值。此外,我们总是希望名字出现,因为没有名字的人的数据很少有用。一旦我们获得了数据集和模式,我们就可以在 python 中执行我们的验证:
```python**import json**from cerberus import Validator****dataset: dict**schema: dict****validator = Validator()**success = validator.validate(dataset, schema)**if not success:**print(validator.errors)**# error example:**# {'name': ["field 'name' is required"]}```
这里我们创建了一个 Cerberus 验证器对象。现在,您可以简单地为它提供一个数据集和模式,并运行 validate。如果验证失败,验证器将向您显示错误消息。很简单。现在让我们看看 Cerberus 为我们准备了什么样的验证选项!
Cerberus 验证选项
类型验证
第一种也是最重要的一种验证是 __ 类型验证 _ _。
确保数据集字段是正确的类型是一种很好的做法,因为无效的类型可能会破坏整个数据工作流,甚至更糟的是,以静默方式执行无效的操作。例如,字段“年龄”最终是浮点数,而不是整数。这会在你不知不觉中打乱你所有的计算。
值验证
接下来,我们将验证价值覆盖和价值本身。例如,可以设置“必需”规则以确保该字段总是存在。“禁止”、“允许”和“包含”规则的混合可以确保严格的值选项。
为了举例,让我们验证一个食谱数据集:
```python**schema = {**# forbid some ingredients**"ingredients": {"forbidden": "pork"},**# restrict recipe type**"type": {"allowed": ["breakfast", "lunch", "dinner"]},**# all recipes posts should have recipes category**"categories": {"contains": "recipes"},**}```*
考虑到这一点,我们也可以将关系添加到一些关系期望中。例如,如果我们的食谱有素食版本,我们希望确保它包含素食成分:
```python**schema = {**"vegan_alternative": {"dependencies": "vegan_ingredients"}**}```*
最后,最灵活和最常见的值验证规则是正则表达式模式,Cerberus 也支持这种模式。以我们的食谱为例,我们可以进一步确保食谱的标题以大写字母开头:
```python**schema = {**"title": {"regex": "[A-Z].+"}**}```*
Cerberus 提供了广泛的内置值、覆盖范围和类型验证,并且可以通过自定义规则轻松扩展。让我们添加我们自己的 python 函数作为规则:
```python**def is_odd(field, value, error):**if not value & 1:**error(field, "Must be an odd number")**schema = {**"preparation_time": {"check_with": is_odd}**}```*
在这里,我们确保准备时间总是一个奇数(营销告诉我们奇数往往卖得更好)。
密钥验证
只剩下一件需要验证的事情了——密钥本身。这是一个重要的步骤,特别是如果您自己不做数据解释,而将数据提供给其他服务的话。例如,如果图形可视化工具不支持大写字母,您应该确保数据没有大写字母:
```python**schema = {**"keysrule": {**"type": "string",**"regex": "[a-z]+"**}**}```*
在这里,模式验证确保所有键都应该只包含小写字符。
正如我们所看到的,Cerberus 支持广泛的验证规则,通过使用它们的整体组合,我们确保我们的数据遵循严格的可预测格式,以进行无错误的数据处理。此外,地狱犬也可以帮助处理。
Cerberus 附加处理
有时我们知道数据集已经有无效值。正是因为这个原因,Cerberus 提供了在验证之前处理数据的能力。
首先,我们可以规范化密钥格式:
```python**v = Validator({}, allow_unknown={'rename_handler': [str, str.lower]})**v.normalized({'Cat': 'meow'})**# {'cat': 'meow'}```*
这里,我们确保所有的键都是小写字符串。
今后,我们还可以通过清除未知键来精简数据集,因为数据集通常带有元键和不重要的数据:
```python**v = Validator({'cat': {'type': 'string'}}, purge_unknown=True)**v.normalized({'cat': 'meow', 'dog': 'woof'})**# {'cat': 'meow'}**# cat people > dog people```
在这个例子中,我们去掉了不想要的动物类型。
我们也可以反其道而行之,通过为不存在的值设置默认值来扩展数据集:
```python**schema = {"dogs_or_cats": {**"type": "string",**"default": "cats"**}}```*
因此,如果“dogs_or_cats”字段没有值,我们可以直接假设该值是“cat”。
最后,我们可以通过强制将字符串转换为整数,以任何方式改变数据:
```python**schema = {'amount': {'type': 'integer', 'coerce': int}}**validator.validate({'amount': '1.0'})**validator.document**# {'amount': 1}```*
通过结合这两个 Cerberus 的特性,验证和处理,我们可以始终确保以一种非常实用的方式拥有一个可靠的数据流。您将拥有一个数据源模式文件,团队中的任何人都可以轻松地访问、编辑、维护和理解该文件。
包扎
随着不可靠结构化数据量的增加,管理和处理数据以使其可读的需求对大数据公司来说变得越来越重要。分析非结构化数据会变得非常令人头疼,并会降低您的工作流程。通过应用数据验证解决方案,如 Cerberus,您可以创建一个节省资源、资金和时间的重要公司生活帮。
数据验证—数据湖和数据库迁移项目
使用 Spark 进行高速低成本数据验证的指南
在过去的 25 年里,我参与了大量的数据库迁移和数据湖项目。数据迁移/数据湖接收后,客户的一个非常常见的验收标准是执行数据验证。根据经验,我可以很容易地说,任何给定项目的大部分时间都花在了数据验证上。在处理异构数据库时尤其如此。花费在数据验证上的时间经常超过实际执行迁移或接收所花费的时间。如果您需要执行多次迁移和摄取迭代,问题会成倍增长。
在过去的几年里,我的主要目标是开发一种不仅速度快而且成本低的解决方案。以下是我多年来开发的框架的发展阶段。
采样后进行人工验证
在我早期,一种非常常见的数据验证方法是抽样。在此方法中,从源和目标中选择了一组样本行。质量保证工程师对样本集进行了目视扫描/比较。该过程大部分是手动的,因此效率低下且容易出错。此外,它只验证了一小部分行样本。
采样后自动验证
在这个方法中,从源和目标中选择一组样本行,然后是执行数据验证的 SQL/PERL 脚本。该过程是自动化的,非常高效,但有时仍然很慢,这取决于样本大小。该方法还验证了一个小样本行。
整个数据集的自动验证
客户开始要求逐行逐列地进行数据验证。这意味着数据采样不再是一个选项。需要一种能够执行完整数据验证的解决方案。我们制定了如下计划:
- 从源和目标中根据主键选择相同行的串联列
- 创建行的校验和并进行比较。校验和匹配确保行完全相同。
- 如果发现不一致,则将违规行写入失败表
(图片作者)
在我们开始处理大型数据集之前,上述解决方案对我们来说工作得相当好。与此同时,大数据开始变得强大。尽管上述解决方案具有内置的并行处理能力,但我们经常开始缺少时间,错过最后期限。
当我们计算出当前项目的数据验证每一次迭代需要超过 30 天时,问题变得极其严重和可怕。一个失败的开始,因为我们最终会错过所有的最后期限。
我们需要一个更好的解决方案…快速
分布式计算拯救世界
幸运的是,我们已经进入了大数据时代。作为早期采用者,我们已经在几个项目中采用了 Hadoop。Spark 和云计算的应用即将出现。除了数据迁移,我们还遇到了几个数据湖项目。因此,我们希望创建一个框架,既能适用于这两种使用情形,又能兼容内部部署或云基础架构。我们是这样做的:
- **数据接收:**除了从源到目的地迁移/接收数据,我们还选择在 HDFS(本地 Hadoop)或 S3 (AWS cloud)上以 Parquet 格式转储源和目的地数据的额外副本。如果您使用 AWS DMS 并使用—S3-settings“data format”:“parquet”创建一个 S3 端点,这一步非常简单
- **基础架构:**针对内部部署的——Spark 集群(Hadoop ),针对 AWS 云的——EMR 的——HDFS 上的 PySpark,HDFS 上的 PySpark。由于数据验证计划不是真正的关键任务,我们选择使用 4-5 个 Spot 实例来降低成本。对我们来说效果很好。我已经发布了 EMR 实例的详细信息,如下所示:
--instance-groups '[{"InstanceCount":5,"BidPrice":"OnDemandPrice",
"EbsConfiguration":{"EbsBlockDeviceConfigs":[{"VolumeSpecification":{"SizeInGB":32,"VolumeType":"gp2"},"VolumesPerInstance":2}]},
"InstanceGroupType":"CORE","InstanceType":"c4.8xlarge","Name":"Core - 2"},{"InstanceCount":1,
"EbsConfiguration":{"EbsBlockDeviceConfigs":[{"VolumeSpecification":{"SizeInGB":32,"VolumeType":"gp2"},"VolumesPerInstance":2}]},
"InstanceGroupType":"MASTER","InstanceType":"m5.xlarge","Name":"Master - 1"}]'
(作者图片)
- **火花码:**漂亮简单却非常有效。为每个表创建两个 pyspark 数据帧,并执行两次减法,如下所示:
dfsourcesubdfdest = dfsource.subtract(dfdest)
dfdestsubdfsource = dfdest.subtract(dfsource)
- **以前的方法与新方法的比较:**假设比较 5 亿行,以前的方法需要 36 个小时才能完成。如果表有数十亿行(在我们的例子中经常如此),那么您就完了。使用新方法,将数据转储到存储器只需一个多小时,进行火花比较大约需要 20 分钟。相当整洁…😄
我希望这篇文章能帮助你进行快速而低成本的数据验证。尽管我还没有发布完整的代码集和命令,但是如果您需要更多的细节,请随时联系我。
我希望这篇文章是有帮助的。三角洲湖作为大数据 Hadoop、Spark & Kafka 课程的一部分,由 Datafence 云学院提供。课程是周末自己在网上教的。
使用 Azure 机器学习服务进行数据版本控制
读完这些,你就会明白 Azure ML 是如何处理数据的,MLOps 是如何关联的,学会自己怎么做
在这个数据科学时代,最重要的问题之一是实现人工智能的整个生命周期。你可能知道,机器学习的基础是数据。如果你想确保你的项目有完全的可追溯性,你不能忘记不那么性感的部分。
这篇文章旨在探讨为什么数据版本化是必不可少的,以及如何在 Azure 机器学习上做到这一点。
只是对 MLOps 的一瞥
但首先,让我们深入了解一下 MLOps 到底是什么。理解这一点的一个很好的方法是看看微软制作的信息图。在这里,您可以看到良好的实践是:
- 能够创建或重新训练模型。
- 模型和数据版本控制。
- 审计能力。
- 部署和监控性能。
- 观察数据漂移。
微软的图片
这是一个表面的表示,但具有构成机器学习项目的所有关键组件。
那么…为什么是数据版本化?
你可能已经注意到了,我们需要为审计做好准备,如果我们不能证明我们使用了哪些数据,这个难题就不完整。这只是在我们考虑监管问题的情况下,但我们还需要考虑良好的质量流程。
了解所有使用过的零件在哪里是至关重要的。如果失败或表现不佳,我们可能不知道为什么我们没有得到预期的结果。数据应该永远是我们的第一怀疑对象,所以无法检查数据是一个大问题。
由 Borna Bevanda 在 Unsplash 上拍摄的照片
但是可能还有其他原因来修改我们的数据。正如我们也看到的,数据漂移也是一个非常令人头疼的问题。数据漂移是模型精度随时间下降的主要原因之一。因此,如果我们不断检查我们的数据是否在漂移,我们就可以及时做出反应,并在为时已晚之前重新训练我们的模型。
那就开始吧!
在数据版本化方面有不同的选择。标准玩家是 DVC ,但是如果你正在寻找一些考虑到所有 Azure 服务的东西,Azure 机器学习服务是最适合你的。
创建 Azure 机器学习工作区!
先决条件:完成以下步骤后,你应该创建一个 Azure 账户并开始免费试用。如果你已经知道如何创建你的机器学习工作空间,直接跳到下一节。
首先,您应该创建一个资源组,它是您创建的其他资源所在的容器,所以请转到搜索栏并单击“Resource groups”选项。
作者从门户网站 Azure 、图片截屏。
之后,你应该点击“添加”按钮。
来自门户 Azure 的屏幕截图
然后,为您的资源组选择一个名称,并选择“查看+创建”选项。
作者从门户网站 Azure 、获取的屏幕截图。
一旦你准备好资源,下一步就是找到机器学习服务。
来自作者的门户网站 Azure 、图片的截屏。
然后,你应该点击“添加”按钮。
作者从 Portal Azure 、图片中截取的屏幕截图。
之后,您将被重定向到下面的页面,您应该在这个页面上创建您的资源。
作者从 Portal Azure 、图片中截取的屏幕截图。
之后,你应该准备好了!点击这个链接,选择你的资源。
太棒了,你已经创建了你的第一个 Azure 机器学习工作区!
Azure 机器学习数据存储
数据存储是 Azure ML 的第一个组件,它与我们今天要看的数据相关。数据存储是到 Azure 存储服务的安全连接。这很好,因为您可以引用不同资源上的任何其他存储服务。您的数据应该可以在您的工作区内访问。
当您创建 Azure 机器学习资源时,会自动创建一个 Blob 存储和一个文件共享,并将其作为数据存储引用。如您所见,如果您选择侧栏上的 Datastore 选项,您将看到它们被创建(Blob 存储是工作区的默认选项)。
截屏来自 Azure ML ,图片作者。
因此,创建数据存储是为了更好地访问您的数据,而不必担心代码中的硬编码凭证。但是,具体的文件呢?如何跟踪我的图像、CSV、拼花地板或其他文件?
数据集!
数据集是拯救数据版本化的元素。它们是引用数据源位置及其元数据副本的抽象。
数据集的伟大之处在于你可以注册它们,并且会自动以给定的名称创建。当您使用相同名称注册新数据集时,数据集将作为新版本上传,并保留其他版本的注册表。
每次创建新模型时,您都可以存储所使用的数据,并且有权访问工作空间的每个人都应该能够检查您的数据集。
让我们把手弄脏吧!
你知道没有代码的教程是不完整的。因此,让我们创建一个新的计算实例来最终破解一些代码。去计算,点击“新建”按钮。
作者截图自 Azure ML ,图片。
之后,选择您的虚拟机,并点击“下一步”。
作者提供的来自 Azure ML 、图片的截屏。
在最后一部分,您可以创建您的资源。
作者提供的来自 Azure ML 、图片的截屏。
一旦你的实例准备好了,点击“Jupyter”选项。
截屏来自 Azure ML ,图片作者。
要显示我们心爱的具有 AzureML 可能性的“Jupyter”笔记本,请单击选项“新建”,选择“Python 3.6 — AzureML”或您应该看到显示的版本。
屏幕截图来自 Azure ML Jupyter 笔记本,图片作者。
现在我们已经准备好在我们的机器学习工作空间中编码了!
在下一节中,我将使用屏幕截图,但是您可以在我的 GitHub repo 中找到代码。
了解我们的工作空间
首先,我们需要定义我们将要使用的工作空间。如果您在我们创建的计算实例的“Jupyter”笔记本中,您可以只使用方法*。from_config(),*这通常应该是一个 JSON 文件,但是这里所有的配置设置都已经完成了。
截屏来自 Azure ML Jupyter 笔记本,图片作者。
将文件上传到您的数据存储
之后,我们可以上传一些数据到我们的数据存储。在我们的工作空间上使用 get_default_datastore() ,我们获得了对 Blob 存储的引用。我们需要选择一些数据来保存它,所以我们将使用 Azure open datasets 中的糖尿病数据集。
说到数据集,Azure 有两种风格:TabularDataset 和 FileDataset。当我们有结构化数据时,第一种方法是有用的(就像在这种情况下)。我们可以将这些数据集转换成熊猫或 spark 数据帧。FileDataset 是非结构化数据的正确选择。正如您将看到的,我们将把文件上传到 Blob 中。
屏幕截图来自 Azure ML Jupyter notebook,图片由作者提供。
数据集
在我们将数据加载到 Blob 中之后,我们需要为注册过程检索它。当我们注册数据集时,您只是引用存储中的一个位置,因此不会产生额外的成本。如果你的数据在你自己的存储器里,你只需要连接到你的工作空间。
屏幕截图来自Azure MLJupyter notebook,图片作者。
使用最后一个块,您成功注册了您的第一个数据集!。很好,但是如果在处理这些数据一段时间后,您意识到年龄字段被错误地赋值了呢?您应该将数据上传到数据存储,并用相同的名称注册新数据。
屏幕截图来自Azure MLJupyter notebook,图片作者。
因此,我们即将到达数据版本化发挥其魔力的时刻。如果我们收集数据集,我们应该会看到我们在年龄字段中所做的更改。但是如果我们想检查第一个数据集呢?嗯,我们只需指定版本,瞧!现在你有了一个可靠的方法来调用你的数据集!
截屏来自Azure MLJupyter notebook,图片作者。
回头见!
我认为 Azure 根据数据构建的解决方案非常酷。我们刚刚看到了为该服务创建的所有功能的一小部分,如果你想将工作负载迁移到 Azure,不要忘记数据是非常重要的。
我真的希望你喜欢或发现这篇文章有用!如果你喜欢这个内容让我知道!我们可以更详细地回顾 Azure 机器学习服务的其他组件。
关于作者:我对数据科学、云基础设施、商业问题和写作充满热情。我最近获得了 DP-100 Azure 数据科学家助理认证,我喜欢一拿到就分享所有的知识。
如果你喜欢,就在 Medium 和 Linkedin 上关注我。如果你想给我写信,我最近在推特上。我很乐意与你交谈!
如果你想多读一点,看看我最近的一些帖子:
[## 想成为 Azure 数据科学家助理(DP-100)吗?让我们
读完本文后,您将对云认证和 DP-100 有更深刻的理解
towardsdatascience.com](/thinking-about-becoming-an-azure-data-scientist-associate-dp-100-lets-32f8766df21e) [## 具有两个以上特征的聚类?尝试用这个来解释你的发现
使用 Plotly 的 line_polar 将向我们展示一种令人兴奋的聚类解释方法。此外,我们将看到…
towardsdatascience.com](/clustering-with-more-than-two-features-try-this-to-explain-your-findings-b053007d680a)