TowardsDataScience-博客中文翻译-2022-二十一-

TowardsDataScience 博客中文翻译 2022(二十一)

原文:TowardsDataScience

协议:CC BY-NC-SA 4.0

使用贝叶斯网络的可解释性

原文:https://towardsdatascience.com/explainability-using-bayesian-networks-4dc706680294

我们可以使用 DAG 来满足 DL 需求吗?

作者

介绍

这篇文章是作为上一篇文章的相邻研究步骤而写的。在那篇文章中,我们介绍了一种 DL 方法,它接收文本和表格数据的组合,目标是超越经典的 ML 工具,比如 XGBoost。回想一下,这些机制之间的比较提供了这个图:

作者-红色曲线是 DL 引擎,蓝色曲线是由大量数据训练的现有 XGBoost,这是一个 precision\TP 图表

数据科学家可能会认为这是成功的:处理表格数据的 DL 引擎比处理这种数据的常见 ML 领先算法取得了更好的结果。然而,当我们考虑现实世界的 ML 解决方案时,其要求不仅限于模型性能,还包括其他问题,如可解释性风险和因果关系,这种“数据科学家期望的结果”可能会给业务部门和客户留下一些未解决的问题和挑战。众所周知,虽然经典的 ML 算法几乎总是提供特征重要性分数。DL 不仅避免提供这种索引,而且经常掩盖这种信息。

什么是贝叶斯网络?

使用贝叶斯网络( BN )的动机是学习一组随机变量之间的依赖关系。网络本身是有向无环图 ( DAG ),模拟随机变量的联合分布。图结构遵循联合分布的概率依赖性分解:节点 V 仅依赖于其父节点(即,独立于其他节点的 r.v X 将被表示为父自由节点)。关于这个主题的教程可以在这里找到

BN 学习的步骤

  • 构建 DAG——正如我们所描述的,BN 训练的结果是一个非常近似的 DAG。此图旨在说明变量之间的相关性和联合分布的最简单的因子分解。显然,有了专家知识,这项任务可以更好地完成。即当它的一些弧已知时。作为一个例子,如果我们有一个问题,很明显有一个目标变量,那么我们可以启动包含它的边,并让训练机制使用它作为先验知识。为了获得 DAG,有两类主要的训练 BN 的方法:

基于约束的结构学习——为了理解这种方法,我们使用以下定义:

Markov Blanket-r . v Y 的 Markov Blanket 是 r.v {X1,…Xn}的集合 A,其中对于 A 的任何子集 S, Y 独立于 A\S |S,即如果我们对 S 上的随机变量进行条件化,我们得到一个独立于 Y 的余集

因此,寻找 DAG 的算法由三个阶段组成:学习 Markov Blanket、寻找邻居和确定弧方向。在第一阶段,我们使用 chi 评分(通常用于 t 检验)来确定变量之间的条件独立性

基于分数的结构学习——这个类实际上更有用,因为“由于统计评分方法”它被认为更有前途。

我们预先确定一个搜索和评分方法。定义初始 DAG(也可以是空 DAG)。在每一步,我们增加,撤回或恢复一个优势,并计算一个统计分数。我们重复这个过程,直到收敛。我们很少有少量的变量,因此强力方法(穷举搜索)很少实用。但是我们可以使用启发式算法。这种算法的一个常见示例如下:

爬山 - 简单定义一个 DAG,只要分数提高就跑。

另一种常用的算法是 Chow Liu 树。

Chow Liu- 该算法通过分解 KL 散度项(类似于变分推断的概念)将分布 Q 近似为未知的联合分布 P。显然,评分依赖于对数似然性。

构建 DAG 后,可能希望优化其参数:

  • 参数学习 -在此阶段,我们假设 DAG 的结构,并在此基础上优化贯穿其条件组件的联合分布。实际上,我们可以使用 MLE 方法,该方法与分布上的贝叶斯先验信念相结合。

当我们完成这两个步骤(构造 DAG 并学习其参数)时。我们可以通过网络进行推理。即在数据输入时确定概率(类似于某些特征未被观察到的情况下的 DL 引擎)

真实世界的例子

在下一节课中,我将介绍一个简短的研究,这个研究使用了我之前介绍的 DL 引擎的表格数据。为了这个研究,我安装了 python 包 bnlearn 。在这里可以找到这个图书馆的杰出指南。

在我们开始之前,我要说明的是,由于这个项目是商业性的,我已经屏蔽了变量名,因此它们将有无意义的名字。

构建我们的 DAG

我们从寻找最佳 DAG 开始。

**import** bnlearn **as** bn
DAG = bn.structure_learning.fit(dataframe)

我们现在有一条匕首。它有一组节点和一个邻接矩阵,如下所示:

print(DAG[**'adjmat'**])

结果是这样的:

作者

其中行是源(即弧线的方向是从左列到行中的元素),列是目标(即列的标题接收弧线)。

当我们开始绘制获得的 DAG 时,我们获得了一组变量,如下图所示:

作者

我们可以看到矩形中的目标节点是许多节点的源。我们可以看到它仍然将箭头指向两个节点。我们将在讨论部分讨论这个问题

显然我们有更多的变量,因此我增加了节点的数量。

添加为目标提供的 now 源的信息(即,其整行为“假”)

获得的图形如下:

作者

所以我们知道如何构建 DAG。现在我们需要训练它的参数。

在代码方面,我们执行如下:

model_mle = bn.parameter_learning.fit(DAG, dataframe, methodtype=**'maximumlikelihood'**)

我们可以用' bayes '来改变'maximum likelihood',如下所述。

该训练的结果是反映 DAG 结构的一组分解的条件分布。

对于给定的变量,它的形式是这样的

作者

字段变量是作为目标的节点的名称

字段变量是其来源

字段“”是确定每个“变量”值的条件概率的 n 维立方体。

现在,我们可以对这个矩阵进行分析,以确定信息(条件分布)存在于何处。

对于推论,我们决定关于证据(即我们正在调节目标的哪个源)并且我们希望得到低条件熵

bn.inference.fit(model_mle, variables=[**'Target'**], evidence={**'cov_0'**:0,**'cov_1'**:1  })

这一行的结果如下表所示:

作者

也就是说,如果我们以这些值作为目标的条件,我们可以很好地预测目标结果。

讨论

我们已经介绍了贝叶斯网络的一些理论概念,以及它们在为一组变量构建近似 DAG 时提供的用法。此外,我们提出了一个端到端 DAG 学习的真实世界的例子:使用 BN 构建它,使用 MLE 方法训练它的参数,以及执行和推理。我们现在可以讨论这个主题与 DL 问题的关系。为什么贝叶斯网络对这类问题有益?

可解释性 -从 BN 训练中获得 DAG,提供关于数据库中独立变量的一致信息。在一般的 DL 问题中,特征是这些变量的函数。因此,我们可以得出哪些变量在我们的系统中占主导地位。当客户或业务单位对神经网络结果的原因感兴趣时,该 DAG 结构可以是提供重要性以及阐明模型的来源。

  • 降维 — BN 提供了变量的联合分布及其关联。后者可能会在减少我们归纳的 DL 引擎的特征方面发挥作用:如果我们知道对于随机变量 X,Y,X 在 Y 中的条件熵很低,我们可以省略 X,因为 Y 提供了它的几乎全部信息。因此,我们有一个工具,可以从统计上排除多余的变量
  • 标记行为 -这一部分对于那些在视觉或语音等领域工作的人来说可能不太明显。在一些框架中,标记可能是一项模糊的任务(举例说明考虑一个具有大量可能重叠的类别的情感问题)。当一个人标记数据时,他可以依赖于数据集中的一些特征并生成条件概率。当我们初始化空 DAG 时,训练 BN 可以提供其中目标 target 是其他节点的父节点的结果。观察几个被测试的例子,这些结果只是反映了这种“标记者的方式”。因此,我们可以不使用 Dag 来满足 ML 需求,而是学习 taggers 策略,并在需要时进行改进。
  • 逻辑推理与因果推理的结合因果推理是数据分析中一个非常成熟的领域。它提供了解决问题的工具,这些问题一方面是 DL 模型通常没有的,另一方面是现实世界提出的。需要找到这些工具协同工作框架。事实上,这种框架已经存在(例如 GNN)。但是合并典型 DL 问题因果关系的机制不太常见。我相信这篇文章中描述的心流是从这种结合中获益的一个很好的步骤

感谢

我要感谢齐夫·巴尔-约瑟夫教授向我介绍了这个主题,并感谢尤里·伊泰进行了富有成效的讨论

可解释的人工智能和对人类好奇心的关注

原文:https://towardsdatascience.com/explainable-ai-and-the-focus-on-human-curiosity-aa816aaf3caa

专注于最重要的几个因素和反事实

图片来源: Pixabay 免费图片

可解释的人工智能很难

可解释的人工智能——或有时被称为“xAI”——很难——无论是形象上还是计算上。

因为可解释性的范围、目的和有效性通常很难在问题定义或用户案例研究中精确预测和形式化。这些属性呈现出一种流动的形式,并且迅速而不可预测地扩散开来。

图片来源:作者创作

xAI 的计算挑战来自于计算度量的机制,如 Shapley 值 (针对输入特征的大量可能组合,即使不是针对整个幂集)。这主要是这样一个事实的副作用,即最成功的机器学习模型往往具有很大的参数空间,并处理大量的特征(或图像或自然语言等高维数据类型),因此,提供可解释性是很重要的。

有很多关于这些的高质量文章。令人兴奋的创业公司正在努力解决这些问题。

在本文中,我们只想关注一个方面— 预测用户的好奇心如何帮助指导 xAI 系统的设计工作。

两个定义—一个要避免

提姆·米勒在这个领域有一篇里程碑式的论文:《人工智能中的 解释:来自社会科学的洞见》(2017)。它对“机器学习的可解释性”有两种(非数学的)定义。

一个定义是— 可解释性是人类能够理解决策原因的程度

另一个说法是——可解释性是人类能够持续预测模型结果的程度

依靠人类的预测是很棘手的

我认为应该避免第二个定义,即使它很简单,很容易理解。

为什么很容易被跟踪?因为在这两者之间,这个有更清晰的测量机制。此外,测量对于设计工程系统非常重要。人们可以通过雇用人类评估者来测试 ML 系统的可解释性,并测量他们预测模型结果的一致性。

这也与所有深度学习模型及其设计者谈论的著名的“人类水平的性能”基准平行。

但是,我们不要忽视一个棘手的事实,即依赖人脑持续预测结构化结果——本质上是模仿复杂的计算机程序——并不总是明智的选择。这就是为什么应该避免 ML 可解释性的定义。

让我给你看一个例子——就在本文中。

示威游行

我写了一篇文章,介绍了如何构建一个单一的效用函数,通过训练图像存储位置的一个输入来训练一个完整的卷积神经网络模型。

这里是笔记本。其中一个例子是关于著名的 Caltech-101 数据集 中“杯子”或“螃蟹”的分类。让我问你——读者——对测试图像进行分类。

这是什么?一杯还是一只螃蟹?

图片来源:来自加州理工学院-101 测试集

你花了多少时间来分类?可能不到 100 毫秒?

这个怎么样?

图片来源:来自加州理工学院-101 测试集

还是那句话,瞬间识别,不是吗?现在,这个怎么样?

图片来源:来自加州理工学院-101 测试集

你笑了,是吗?“对机器来说是个棘手的问题,”你默默地想。

所以,作为一个人类评估者,你做得很好。

但是,在这个练习中,将您的性能与 ML 算法进行比较(纯粹从可解释性的角度来看)是非常困难的。因为一个 5 层卷积神经网络有点像一个黑盒,它的内部工作很难向任何人解释。你永远不会满足于比较和与你的思维和 ML 模型一脉相承的事实和解。

你只是不知道 ML 模型的思路是什么!

现在,考虑这个例子。

假设您已经为您的制造工厂建立了一个化学过程的逻辑回归模型,以根据输入过程参数(由复杂的传感器测量)预测质量—

这里是测试数据的快照(把它想象成与你在上面看到的测试图像平行)。

我已经部分隐藏了“目标”列,因为这是你看不到的,但将被评估。

看着这些错综复杂的数字,你有多大的几率预测出正确的目标?你能在 100 毫秒内快速做出正确预测的几率有多大?

对于这个模型来说,使用人类评估者作为最大似然可解释性度量的宏大计划将会失败。然而,具有讽刺意味的是,从可解释性的角度来看,选择简单的二元逻辑分类是完美的。这确实是一个可以解释的模型。只是不像我们让人类评估者来反对它。

人类的大脑还没有进化到处理表格数据的地步

表格数据,以一种漂亮的书写形式,是人类历史上最近的发展。苏美尔或亚述楔形文字是书写文字的一些最早的例子,它们是出于记录的需要而发展起来的——土地销售、农业产出、税收。

微软 Excel 的青铜时代版本!

图片来源:维基百科(维基媒体图片-1图片-2 )

但是,这只是青铜时代。就在农业革命前后,其对粮食生产、人口密度和城市化的影响导致了这种表格数据集。

人类的认知革命已经发生了很长时间——远在那之前。这是一个大概的时间表。

图片来源:作者创作

而且,上面的图表甚至没有涵盖最令人惊叹的视觉皮层和人眼的进化的时间线。这种生物学是由在非洲大草原生存的需要形成的——区分捕食者和猎物,安全的浆果和有毒的浆果。

图片来源:维基媒体免费图片

出生于奥地利的美国机器人专家和计算机科学家汉斯·莫拉维克 ,目前是卡耐基梅隆大学机器人研究所的兼职教师,用一种稍微不同的方式表达了这一点——“让计算机在智力测试或玩跳棋时表现出成人水平的表现相对容易,而在感知和移动性方面,很难或不可能让它们拥有一岁儿童的技能”。

所有这一切都是说,人类评估者可以很好地完成对象分类工作,但使用表格数据集进行二进制分类会惨败。

虽然从可解释性的角度来看,用于这些任务的常见 ML 模型将完全相反——难以解释的神经网络和相对更容易的逻辑回归。

图片来源:作者创作

跟着好奇心走

因此,对于可解释的 AI/ML 系统来说,不要让人类与机器对抗,看看系统预测是否与人类产生的预测一致,这是有意义的。

相反,这些系统需要通过观察人类用户自然好奇心的多样性和本质来从头开始设计。

“为什么”和“假设”

人类的思维需要被尊重。这包括—“为什么 ”和“ 什么如果 ”。

  • 我没有根据预测来测试自己
  • 我很好奇导致这一预测的前三大因素
  • 我还想知道,如果这些因素中的一个或多个发生变化,预测是否会有所不同

前 3 名或前 4 名就足够了,也是可取的

前 3(或 4)个因素值得注意。一个设计良好的可解释的 ML 系统不应该试图用数据中导致模型预测的所有强模式来淹没用户。

这又一次与我们的生物学密切相关。我们只擅长一小组数字。人脑的短期工作记忆大约在7–8 项/数左右。

因此,一个好的系统将集中于显示一些视觉概念或图表来解释一个 ML 模型。UX/用户界面设计扮演着重要角色

这也适用于一般的数据分析问题。这是我的文章《T21》中的一个例子。对于涉及多台相似机器的相关性问题,构建一个简单的条形图,清楚地突出显示异常机器,而不是显示实际的相关性图。

图片来源:作者创作(来自作者所有文章)

反事实

假设问题通常都不是无关紧要的,涉及到揭示没有发生可能会发生的情景。如果我们有一个给定的模型,你可能会认为这很容易做到——只需将输入的详尽组合扔给模型,记下所有的响应,并很好地呈现它们。

但是谁来决定这个组合呢?如何为模型第一次测试的刺激列表分配优先级?这里,用户(人类)的好奇心将是决定优先级和过滤列表的关键。此外,我们必须小心不要用与它所看到的训练案例的分布没有太大差别的场景来测试模型。

图片来源:作者用 Pixabay 免费图片创作

好奇心随着领域的变化而变化

关键是要记住,好奇心会随着该域内用户的级别而变化。对于一个制造组织来说,各种利益相关者会对 ML 模型预测的各个方面感到好奇,

图片来源:作者创作

因此,一个好的可解释的 ML 系统必须努力覆盖尽可能多的基本设计模式,例如已经被证明对大部分用户有效的可视化分析。

这种可解释性可能来自不同的层面

人类的好奇心是没有界限的,它很容易以流动的方式跨越界限。大多数 ML 供电系统不仅仅是一个 ML 盒。通常情况下,他们有其他层包裹着 ML 模型,外部用户只能看到这个外层的推荐或建议。

人类的好奇心会被吸引去问更多关于外层结构的问题。可解释的 ML 系统应该准备好解决这个问题,因为它们必须正确地识别用户的好奇心已经触及的子系统。

图片来源:作者用 Pixabay 免费图片创作

摘要

可解释的人工智能是一个伟大的领域,它将推动人工智能/人工智能系统的采用,成为人类努力的真正助手。要取得成功,除了设计和计算方面的挑战,预测人类好奇心的多样性和微妙性将是关键。领域知识和实验态度(例如设计最吸引人的 UI)也是成功的关键因素。

加州理工学院 101 数据集的引用

长度飞飞、r .弗格斯和 p .佩罗娜。“从少量训练实例中学习生成视觉模型
:在
101 个对象类别上测试的增量贝叶斯方法”
IEEE。CVPR 2004,基于生成模型
的视觉研讨会。2004.

喜欢这篇文章吗?成为 中等会员 继续 无限制学习 。如果您使用以下链接, ,我将收取您的一部分会员费,而不会对您产生额外费用

https://medium.com/@tirthajyoti/membership

可解释的人工智能:理解卷积神经网络的决策——第 1 部分

原文:https://towardsdatascience.com/explainable-ai-understanding-the-decisions-of-a-convolutional-neural-network-part-1-1a9cf26364fd

深入局部可解释的模型不可知解释(LIME)

丹尼·米勒在 Unsplash 上的照片

我们如何定义一个卷积神经网络(CNN)的质量?一个模型在给定任务中的性能通常由一些(简单的)预定义的度量来衡量。甚至还有一个的地方用来比较标准化数据集上最先进的图像分类模型的准确性。然而,如果你在现实世界中从事一个项目,如果一个模型有惊人的最高精确度,那么它的质量和价值是什么?除了这些简单的量化指标之外,我们还能对模型的质量提出什么要求呢?

这就是可解释的人工智能(XAI)的用武之地。XAI 系统可以被定义为“一个自我解释的智能系统,描述了其决策和预测背后的推理”。[1]向您的 ML 管道中添加一个可解释的组件不仅提供了模型的可解释性,而且还可以使业务利益相关者获得对您的模型的信任,或者可以用于评估(并修复)您的模型中的系统偏差。[1]

在几个部分中,我将讨论可用于图像分类项目的几种 XAI 方法的内部工作原理和利弊。在文献中,这些方法通常被称为像素属性方法显著图、灵敏度图。对于某些方法,提供了代码,因此可以在您自己的项目中实现。所有的代码都可以在这里找到。这是第一个博客,旨在解释基于输入的归因模型,重点是本地可解释的模型不可知的解释(在短期内)。[2]

方法

存在许多不同的方法来获得像素属性图。一般来说,这些方法可以分为两个主流:基于前向传递(或输入)的归因模型和基于后向传递(或梯度)的归因模型。

第 1 部分:基于正向传递(或输入)的归因模型

这些方法是模型不可知的。这些模型背后的主要直觉非常简单。拍摄输入图像;对输入进行一些调整,并观察对预测的影响。调整可以包括例如输入部分的部分遮挡或扰动。可能最著名的例子是局部可解释的模型不可知解释(或 LIME)。[2]

石灰|照片由 Shaun MeintjesUnsplash 拍摄

局部可解释的模型不可知解释(LIME)

LIME 可用于所有类型的数据,不仅限于图像分类。虽然当用于解释图像分类模型时,它通常被称为像素属性方法, LIME 对单个像素不起作用,因为这些可能不会改变预测太多。相反,LIME 利用了所谓的“超像素”,即按位置颜色分组的图像小区域。这些超像素区域用于多次扰乱图像,并识别这些变化对预测的影响。最终,对这些扰动图像的预测被用于训练更简单(且可解释)的模型,例如线性回归,以识别哪些超像素区域对预测特定类别最重要。

概述

最初阅读原始论文可能会令人望而生畏,但提取后创建属性地图的步骤非常容易理解:

1\. Generate superpixel areas2\. Create perturbed images by randomly filling some of the superpixel areas with a solid black color3\. For each perturbed image: 
    a. Make predictions for the perturbed image
    b. Create weights based on the difference between the perturbed image and the original image (smaller distance == larger weight)4\. Fit a simple interpretable model using the predictions on all perturbed images and the created weights.5\. Define the number of superpixels that should be plotted and plot the superpixels with the highest importance in the simple model (i.e. coefficient if a Linear Regression is used).

为了更直观地概述这些步骤,请参见下图。左图为原图。此外,该图还展示了所有超像素区域的轮廓。第三个图描绘了扰动图像的样本,其将用于识别通过扰动原始图片的黑色区域将改变多少预测。最后一个图表示根据 LIME 预测‘巨嘴鸟’级的最重要区域。

多个图展示了 a)原始输入图像,b)所有超像素区域的边界,c)扰动图像的样本,以及 d)预测“巨嘴鸟”类别的最重要的超像素区域(图片由作者提供)

利弊

LIME 的主要优点之一是它是模型不可知的,可以用于任何模型。这也意味着底层模型可以很容易地被替换,而不必用 LIME 调整代码进行解释。此外,LIME 使用“简单”的可理解模型来解释模型的决策,因此作为一名数据科学家,很容易向最终用户解释。这也是唯一可以用于图像、文本和表格数据的方法之一。因此,如果你在一个生产中有几个模型的公司工作,选择 LIME 来解释可能是一个好的选择,因为最终用户只需要理解一个方法的直觉。

该方法也有一些缺点。这可能是计算密集型的,尤其是当使用大型 CNN 时,因为必须对每个受干扰的图像进行预测。在应用石灰时也有很多选择要做:多少超像素区域合适?对于可解释性,应该使用什么简单的模型?在可解释图中应该画出多少超像素区域?这些都是应该根据您自己的情况进行调整的参数,找到最佳解决方案可能需要一些时间。最后,拟合的简单(可解释的)模型近似于 CNN,但并不能真正解释它。这款合体没有质量检查,所以可能会有误导。

亲自动手

关于如何使用石灰的笔记本范例可以在 https://github.com/RikKraanVantage/explainable_AI的以下储存库中找到。这里包括了为你自己的项目复制 LIME 解释所必需的代码。

在接下来的部分中,将通过代码片段来介绍为您自己的项目复制 LIME 解释的步骤。本例中使用的基本模型是一个具有预训练的imagenet权重的tf.keras.applications.EfficientNetB0,但是可以使用任何 CNN。

  1. 生成超像素区域

超像素边界(图片由作者提供)

为了生成超像素区域,使用由scikit-image实现的quickshift算法。该算法基于颜色(和位置)分割图像,但是也可以使用更高级的聚类算法。对于这个算法,一些参数可以被调整(kernel_sizemax_distanceratio)。基本上,这些参数定义了创建多少超像素区域。有关如何调整这些参数的更多信息,请参见https://sci kit-image . org/docs/stable/API/skim age . segmentation . html # skim age . segmentation . quick shift

2.生成扰动图像

扰动图像(作者提供的图像)

通过创建perturbation vectors生成扰动图像。这些是长度为super_pixel_count的二进制向量。这些向量为特定的扰动图像定义了哪些超像素区域应该被扰动,哪些不应该被扰动。perturbation vectors的数量是可以调整的,但是要知道增加它会带来所需计算能力的增加。

为了生成perturbation vectors,我们使用 Numpy 的np.random.binomial()函数。

现在我们有几个向量可以用来扰乱图像:

3.对扰动图像进行预测并生成权重

预测所有扰动的图像是简单的,计算权重稍微复杂一些。为了创建权重,我们首先计算原始图像和扰动图像之间的距离。更具体地,我们计算原始图像的扰动向量(只有一个,因为没有扰动)[1, 1, 1, 1, 1, 1, ..., 1]和随机扰动向量[1, 0, 1, 0, 0, 0, 1 ..., 1]之间的距离。为此,我们利用了sklearn成对距离度量。随后,我们对距离应用核函数来创建权重。这最后一步确保扰动向量越接近原始图像,权重就越高。为什么这是必要的?让我们假设我们有一个只有 1 个扰动超像素区域的扰动图像。该样本非常有价值,因为它提供了关于特定超像素区域的大量信息(即,如果扰动图像上特定类别的预测与原始图像上的预测非常不同,则我们知道该超像素区域对于预测特定类别非常重要)。此外,如果我们有一个图像,其中所有区域都被扰动(零的向量),对特定类别的预测可能会非常不同,只是它提供了很少的关于哪个超像素区域对预测是重要的信息。

4.拟合一个简单的可解释模型

下一步是使用perturbation_vectors对扰动图像的预测和新创建的权重来拟合一个简单(且可解释)的模型。可以使用多种型号,最简单的方法是使用开箱即用的sklearn型号。对于这个例子,使用了一个DecisionTreeRegressor

注意,输入到函数中的predictions应该只包含对感兴趣类别的每个扰动图像的预测。所以这个向量的形状是(num_perturbations, 1)。结果是包含用于预测指定类别的每个超像素区域的feature_importance的向量。

5.剧情解说

石灰说明(图片由作者提供)

最后,解释可以被绘制出来。首先,应该定义将要描绘的超像素区域的数量。这可以通过设置重要性阈值、取超像素区域总数的一部分或者仅仅通过硬编码一个数字来实现。在这个例子中,我总共绘制了 4 个超像素区域。根据 LIME 的说法,似乎巨嘴鸟的喙和眼睛周围的白色区域是模型检测它的重要区域(因为这些区域是拟合的简单模型的最重要特征)。

结论

这篇博客展示了 XAI 最常用的方法之一的直觉和利弊。代码片段显示实现它相当简单。下一部分将讨论和实现基于梯度的属性方法。检查仓库中的所有代码示例:【https://github.com/RikKraanVantage/explainable_AI

关于作者

Rik Kraan 是一名放射学博士,在荷兰数据科学咨询公司 BigData Republic 担任数据科学家。通过 rik.kraan@bigdatarepublic.nl 联系。

来源

[1]西纳·莫塞尼、尼卢法尔·扎雷和埃里克·拉冈。2020.可解释人工智能系统设计和评估的多学科调查和框架。ACM Trans 互动。智能。系统。1、1、第一条(2020 年 1 月),46 页。https://doi.org/10.1145/3387166
【2】里贝罗、马尔科·图利奥、萨梅尔·辛格、卡洛斯·盖斯特林。“我为什么要相信你?:解释任何分类器的预测。第 22 届 ACM SIGKDD 知识发现和数据挖掘国际会议论文集。美国计算机学会(2016 年)。

可解释的人工智能:打开黑盒

原文:https://towardsdatascience.com/explainable-ai-unfold-the-blackbox-5488253c01fd

与 XAI 一起建立对机器学习的信任,《SHAP &沙普利价值观指南》

塔拉·温斯泰德在的照片

随着 AI 变得更加先进,成为我们生活中至关重要的一部分,当我们不了解 AI 的效果和副作用时,危险就来了。重要的是要理解如何区分人工智能决策过程的事实和幻想,同时保持人工智能的效率,并为结果提供最大的透明度。所有这些都可以通过可解释的人工智能(XAI)来实现。

什么是 XAI 及其好处?

可解释的人工智能是一种旨在创造人类可解释的机器学习的技术。这些技术将帮助人类理解、解释和信任机器学习模型做出的预测。

作者图片

上图展示了常规人工智能与可解释人工智能的对比,以及它如何影响最终用户。

当我们理解了 ML 算法预测背后的逻辑,它就不再是一个黑箱了。这不仅有助于数据科学家和 ML 工程师解释预测背后的故事,也有助于企业和整个组织信任和采用人工智能。

可解释的人工智能在高风险人工智能领域更重要,如金融投资、医疗诊断、自动驾驶汽车以及法律或国防相关的决策。目前,很难相信这些地方的“黑匣子”人工智能模型的推断。

好处

  1. 建立对人工智能驱动的商业决策的信心- 可解释的人工智能将有助于建立对商业决策的信任&信心。来自可解释的人工智能系统的推理往往会增加系统的信心,因为它有可能看到这些决定的主要驱动因素。
  2. 透明和可问责的人工智能系统- 随着人工智能对项目的影响越来越大,可解释性将确保研究和决策透明。因此,更容易让工程师/团队/组织对决策负责。
  3. 减轻法律、合规性&声誉风险- 使用人工智能是不够的,我们有义务公平使用人工智能。保持人工智能模型的可解释性和透明性,可以大大降低错误结果的影响,组织可以减轻监管合规机构带来的风险&。
  4. 减轻偏见&促进公平- 有了可解释的人工智能,更容易看到数据中影响 ML 模型输出的模式。因此,可解释的系统可以减少有偏见的预测的影响,减轻它们的风险,并培养对预测的公平信任。

模型复杂性-可解释性权衡

在创建一个 ML 模型时,总是要在模型的准确性/复杂性和模型的可解释性之间进行权衡。

大多数简单的预测模型,如线性模型,精确度较低,复杂性较低,并且易于解释。而先进的方法,如神经网络更准确,能够对更复杂的数据进行预测,并且不容易解释。因此平衡可解释性和模型复杂性总是一个挑战。当模型复杂性增加时,可解释性降低。

下图显示了不同 ML 模型在模型复杂性和可解释性之间的权衡。

作者图片

可解释的人工智能可以在增加高度复杂模型的可解释性方面发挥至关重要的作用。不能自我解释的模型可以与 XAI 方法接口,该方法可以基于局部和全局解释提供基于特征重要性的洞察。有许多开源框架和技术可以用来向非人工智能专家解释复杂的 ML 方法。让我们看看技术。

XAI 技术

XAI 技术可以分为两类

  1. 透明方法
  2. 事后方法

透明方法是模型的内在架构易于解释并且特性关联不复杂的地方。线性/逻辑回归、决策树、KNN 和贝叶斯模型都是透明模型的例子。

事后方法适用于数据中存在复杂决策界限且模型复杂性难以解释的情况。临时方法进一步分为两类-

  • 特定于模型- 特定于模型的方法作用于单个或一组模型,并且依赖于特定模型类型的功能和能力。
  • 模型不可知- 模型不可知方法通过分析模型输入&输出特征对任何 ML 模型起作用,并且不依赖于模型功能或复杂性。当无法解释模型功能时,这些方法非常有用。

下图显示了各种 XAI 技术-

作者图片

上图只显示了一种看待不同类型的 XAI 方法的方式。XAI 还有其他的分类方法

  1. 范围-全局或本地
  2. 访问——解释方法对模型的访问是有限的或者完全的
  3. 解释阶段——在模型开发(培训)期间或培训之后应用解释

XAI 幅员辽阔,方法很多。在这篇文章中,我将只讨论 SHAP 方法。其余的模型不可知和特定于模型的技术将在 XAI 帖子的下一部分中讨论。

SHAP

SHAP(SHapley Additive explaints)方法是 python 中的一种博弈论方法,使用 SHapley 值来解释任何机器学习模型的输出。

要了解 SHAP,让我们首先了解什么是沙普利价值观。

沙普利值

Shapley 值是博弈论中的一个概念,用于测量预测中某个要素实例的平均边际贡献。

我们先来了解一下为什么沙普利值很重要。以收入预测为例,我们必须对收入是≤50K 还是> 50K 进行分类。我们已经使用 xgboost 分类器来预测收入(你可以在这里找到完整的代码)。现在我们必须检查哪些特征对预测有贡献,我们可以使用 plot_importance 方法来检查。该 plot_importance 方法有一个名为 importance_type 的参数,该参数基于权重(特征在树中出现的次数)、增益(使用该特征的分割的平均增益)和覆盖(使用该特征的分割的平均覆盖范围)来计算特征重要性。

作者图片

查看 importance_type 的这 3 个值,我们使用 Xgboost 获得 3 组不同的特征贡献,但是我们不知道哪一种方法是最好的,也不知道如何获得实际上对模型有贡献的可靠特征。使用这种方法的第二个问题是,这种方法只能有助于全局可解释性,如果我们必须获得特定记录的重要特征(局部可解释性 ) ),这种方法将不起作用。

python 中的 SHAP 方法可以帮助我们解决这两个问题。但在研究 SHAP 实施以及如何解决这些问题之前,首先让我们了解什么是 Shapley 值,以及如何使用相同的收入预测示例来计算它们。

虽然 SHAP 方法对于获得特征对于模型预测的重要性是有用的,但是它不是评估预测本身的度量。

为了预测收入是否大于 50K,假设有这三个特征的贡献——年龄、婚姻状况和资本收益。现在让我们来理解这些特性的边际贡献。如下图所示,这里——

  • 年龄贡献:2.5 万美元
  • 婚姻状况贡献:4.5 万美元
  • 资本收益贡献:7 万美元
  • 年龄和婚姻状况:3.2 万美元
  • 年龄和资本收益贡献:6 万美元
  • 资本收益和婚姻状况贡献:7.5 万美元
  • 年龄、婚姻状况和资本收益:9.5 万美元

作者图片

为了找到年龄的边际贡献,我们必须计算年龄的边际贡献

  1. 50K 美元收入组
  2. 年龄和婚姻状况组
  3. 年龄和资本收益组
  4. 年龄、婚姻状况和资本收益组

如下图所示。同样的,我们可以计算所有特性的边际贡献。

作者图片

现在让我们来计算每个级别的权重。

  • 第一层有 3 条边,所以这一层上每条边的权重是 1/3——我们称之为 w1
  • 第二层有 6 条边,所以这一层上每条边的权重是 1/6——我们称之为 w2
  • 第三层有 3 条边,所以这一层上每条边的权重是 1/3——我们称之为 w3

作者图片

现在我们有了所有级别的特征和权重的边际贡献,让我们计算特征的总贡献。

这表明年龄对收入预测的贡献为-7.5K 美元,因此-7.5K 美元是年龄的 Shapley 值。

同样,我们可以计算婚姻状况和资本收益的 Shapley 值。

作者图片

SHAP(年龄)= -$7.5K

SHAP(婚姻状况)=$11.5k

SHAP(资本收益)=$38K

如果我们对这 3 个特性的 Shapley 值求和,结果是$42K (-$7.5K+$11.5K+$38K),相当于从$50K 到$92K 的收入路径($92K-$50K)。

作者图片

现在我们已经了解了什么是 Shapley 值以及如何计算它们,让我们看看用 python 实现 SHAP 库的实际方法。

Python 实现

要使用 SHAP,首先 pip 安装 SHAP 库并导入它。然后创建一个 SHAP 解释器对象,并使用它来获得 shap 值,以解释模型的预测。

现在让我们使用 Shapley 值来理解全局和局部可解释性。

全局可解释性

汇总条形图- 该图以降序显示特征重要性。图顶部的要素对模型预测的贡献较大,而图底部的要素贡献较小。

作者图片

汇总图- 汇总图还以降序显示特征重要性,并显示每个特征与目标变量的影响和相关性。对于每次观察,我们可以看到颜色从蓝色(低)变为红色(高)的高/低影响。我们可以看到这种相关性,因为高资本收益(红色)对收入有积极影响(向+ve 轴移动),而年龄与收入呈负相关。

作者图片

依赖图-依赖图显示了一个特性对模型预测的影响。y 轴变量是自动选择的,通常情况下,该变量是要素在进行模型预测时更频繁交互的变量。

作者图片

我们还可以通过使用参数 interaction_index 并为 y 轴提供另一个变量来改变 y 轴变量和特征交互图。

作者图片

力图- 力图显示特征如何影响模型输出。贡献较大的要素用红色表示,贡献较小的要素用蓝色表示。

作者图片

本地可解释性

条形图- 该图显示了特定观察中特征的贡献。下图显示了资本损失、关系和教育是对这一观察最有贡献的特征。

作者图片

瀑布图- 水流图是另一种在特定观察中绘制特征贡献的方式,如下所示。

作者图片

力图- 对于一个具体的观察,力图显示了哪些特征最有贡献。

作者图片

使用 SHAP,我们不仅在全球和本地级别获得了可解释性,而且特征集也不会随着不同的情节而改变。多酷啊!!

最后的想法

我们已经在上面看到了 XAI 是如何帮助我们得到关于人工智能系统的为什么和如何的答案的。随着人工智能在许多行业变得越来越主流,对可解释性的需求也在增加。然而,尽管对可解释的人工智能越来越感兴趣,但可解释的人工智能愿景和实践之间存在巨大差距。同一个人工智能算法可能需要多种解释,因此可解释的人工智能在这种情况下将如何有所帮助仍是一个问题。此外,缺乏来自真实世界用例的指导来实现和测试这些解释。

最后,XAI 是一个新兴的领域,有许多挑战和未解决的问题,但毫无疑问,XAI 将在人工智能文学的未来扮演不可或缺的角色。

要访问使用 Xgboost 进行收入预测的完整代码并使用 SHAP 进行解释,请参考 GitHub 链接

https://github.com/charumakhijani/explainable-ai-shap

谢谢你的阅读。如果你喜欢这个故事,请喜欢,分享和关注更多这样的内容。如往常一样,请联系我们以获得任何问题/评论/反馈。

Github:https://github.com/charumakhijani LinkedIn:https://www.linkedin.com/in/charumakhijani/

参考-

https://towards data science . com/shap-explained-the-way-I-wish-someone-explained-it-to-me-ab 81 cc 69 ef 30

可解释的人工智能(XAI)方法第三部分——累积局部效应(ALE)

原文:https://towardsdatascience.com/explainable-ai-xai-methods-part-3-accumulated-local-effects-ale-cf6ba3387fde

关于累积局部效应(ALE)的教程,侧重于它的使用、解释和利弊

像素点免费使用照片。

对以前职位的审查

可解释的机器学习(XAI)指的是努力确保人工智能程序在目的和工作方式上是透明的。[1]这是我打算写的 XAI 系列文章中的第三篇。

在我的第一篇帖子中,我介绍了部分相关(PD)和部分相关图(PDP) 的概念,这是一种使用那些 PD 值来显示特征对目标变量的边际平均影响的可视化。[2]我建议在继续下一步之前先看一下的帖子

在我的第二篇帖子中,我介绍了个人条件期望(ICE) 曲线,它在与 PDP 联合使用时特别有效。[3]是因为我们可以同时观察到特性的整体/平均效果和特性的观察级效果!

累积局部效应(ALE)与标准 PDP

累积局部效应(ALE)与部分相关(PD)的概念相似,都旨在描述特征如何影响模型的平均预测。ALE 确实比 PD 具有竞争优势,因为它解决了当感兴趣的特征与其他特征高度相关时 PD 中出现的偏差。让我们看看,由于计算部分相关性的方式,部分相关性图(PDP)中的特征之间的相关性是如何成为问题的。

假设我们有一个简单的回归模型,它根据其他身体特征,如体重、性别、父亲的身高等,预测一个人的身高。这里,我们感兴趣的是理解体重对目标变量的边际平均效应,在本例中,目标变量是身高。对于权重的每个网格值,我们将用该网格值替换整个权重列,计算预测值,并对它们进行平均。这将是权重网格值的部分相关值。然而,为了计算部分依赖图,我们可能不得不容忍一些不现实的情况。例如,如果体重的网格值是 30kg,我们将所有观察的体重替换为 30kg,即使是像{性别:男性,父亲身高:185cm …}这似乎不太可能。

ALE plots 解决了这个问题,它计算预测值的差值,而不是平均值。 用“差异”代替“平均值”可以让我们屏蔽相关特征的影响。【4】

Molnar 的可解释机器学习书用两个简短的句子很好地对 PDP 和 ALE 进行了比较。

PDP :“让我向您展示当每个数据实例都具有该特性的值 v 时,模型平均预测的结果。我忽略了值 v 是否对所有数据实例都有意义。”

v.s

ALE 图:“让我向您展示模型预测如何在 v 周围的一个小“窗口”中针对该窗口中的数据实例改变。”[4]

理论和解释

Molnar 的可解释机器学习书籍涵盖了 ALE 的理论,非常深入和详细。我将把重点放在解释和应用上!

以下节选自这篇博客文章,很好地总结了 ALE works 如何与其名称相匹配。

一个足够小的窗口允许我们对这段时间内的变化做出相当准确的估计。然后通过累加所有的局部区域,我们就能够全面了解我们的输入对输出的影响。因此,如果我们想知道 20 摄氏度的一天对我们的跑步者有什么影响,我们会找到 21 度的影响,然后减去 19 度的差异。通过平均预测中的变化,我们可以确定该窗口的特征的效果。然后,我们对数据重复这个过程,并累加

数字特征的解释…

对于单个数值特征,ALE 值可以解释为与数据 的平均预测相比,该特征在某一值的 主效应。这种解释是可能的,因为 ALE 图以零为中心,所以 ALE 曲线的每个点都代表与平均值预测的差异。[4]例如,特征值 12.2 的 ALE 值为 5 将意味着如果感兴趣的特征等于 12.2,则它将产生的预测比平均预测高 5。

两个数字特征的解释…

二阶效应是在我们考虑了特征的主要效应之后,特征的附加交互效应。[4]

对分类特征的解释…

顾名思义,效果朝着某个方向累积,因此特征值需要有一个“顺序”。对于分类特征,在计算 ALE 值之前,应首先设置变量中值的顺序。

确定分类变量中值的顺序的一种方法是,根据其他特征将具有高相似性的值视为连续顺序或彼此接近的顺序。为了计算数值特征之间的相似性,使用 Kolmogorov-Smirnov 距离,对于分类特征,使用相对频率表。[4]

可解释机器学习书籍中的自行车租赁数量预测示例—分类变量“月”的 ALE 图

可解释的机器学习书提供了一个预测自行车租赁数量的例子。[4]从上面分类变量的 ALE 图中可以看出,性质相似的月份值排列在一起或彼此接近。例如,被认为是冬季或早春的月份,如 12 月、11 月、3 月和 1 月被聚集在一起。同样,高温的夏季月份在 x 轴上彼此相邻。这是有意义的,因为我们根据表征每个月的其他特征的相似性分数给这些值赋予了顺序。

至于解释,这类似于我们解释一个数值变量。12 月份的 ALE 值约为-660,这意味着在 12 月份,预测的自行车租赁数量将比平均预测值低 660 辆。我们也可以通过观察每个条形图的绝对长度来说明影响的大小。例如,一月、三月和四月的柱线非常短,这意味着与其他月份相比,它们对自行车租赁预测数量的影响。

麦酒地块的利与弊

如前所述,在我们比较 PDP 和 ALE 图的部分,即使感兴趣的特征与其他特征相关,我们的 ALE 图也是无偏的。但是 PDP 肯定比 ALEs 更容易理解。另一方面,ALE 图在解释图时需要注意细节,这取决于您正在处理的特征类型(如数值、分类)以及您正在查看的交互特征的数量。

尽管如此,对 ALE 图的解释仍然相当简单。它是“在给定值的条件下改变特征对预测的相对影响”。[4]此外,ALE 图以零为中心,这使得很容易理解 ALE 曲线中的每个点都代表平均预测值的差异。

然而,ALE 图也有其局限性。它比 PDP 或 ICE 图更难解释。这种解释也通常被限制在所定义的“窗口”或“间隔”内。如果特征高度相关(这是经常发生的情况),解释跨区间的影响是不可能的。请记住,影响是在每个区间内计算的,并且每个区间包含不同的数据点集合。这些计算出的效应被累加(因此命名为“累加的”局部效应),只是为了使线平滑。

ALE 图的另一个麻烦之处是需要确定最佳间隔数。如果定义了太多的间隔,图形中的起伏会使绘图变得嘈杂。减少间隔的数量将使图更加稳定,但这是有代价的-它可能会掩盖模型中存在的一些复杂性或相互作用。

履行

ALE 图可以用 R 和 Python 实现。

如果你正在使用 R…

  • ALEPlot 包
  • iml 包

都是值得一看的好地方!

如果你正在使用 Python…

  • ALEPython 包
  • Alibi 套餐

是最受欢迎的。

这里有一些很好的文档和博客帖子,它们使用了上面的包来实现 ALE 图,所以请查看它们!

https://github.com/blent-ai/ALEPython/blob/dev/examples/regression_iris.ipynb https://www.analyticsvidhya.com/blog/2020/10/accumulated-local-effects-ale-feature-effects-global-interpretability/

ALIBI 包文档

参考

[1] 可解释的人工智能(XAI) (2019),Technopedia

[2] S. Kim,《可解释的人工智能(XAI)方法第一部分—部分依赖图(PDP) (2021),走向数据科学

[3] S. Kim,《可解释的人工智能(XAI)方法》第 2 部分—部分依赖图(PDP) (2021),走向数据科学

[4] C. Molnar 可解释机器学习 (2020)

可解释的人工智能(XAI)方法第五部分——全局代理模型

原文:https://towardsdatascience.com/explainable-ai-xai-methods-part-5-global-surrogate-models-9c228d27e13a

如果你使用的算法是一个黑盒模型,为什么不使用一个模拟原始行为的可解释模型呢?

免费使用来自像素的照片

对以前职位的审查

可解释的机器学习(XAI)指的是努力确保人工智能程序在目的和工作方式上是透明的。[1]这是我打算写的 XAI 系列文章中的第五篇。

到目前为止,我已经向您介绍了四种 XAI 方法——部分相关图(PDP)、个体条件期望图(ICE)、累积局部效应(ALE)曲线和排列重要性。在这篇文章中,我提供了关于全球代理模型的初级读本。如果你好奇或者需要一些回顾,请查看我之前的四篇帖子!

XAI 方法第一部分

XAI 方法第二部分

XAI 方法第三部分

XAI 方法第四部分

高级概念

顾名思义,“代理”模型是可以代替原始模型用于各种目的的算法——提高可解释性、降低计算成本等。假设您使用随机森林模型来预测回归结果。虽然它可能具有出色的预测性能,但与线性回归等固有的可解释模型不同,很难理解为什么以及如何做出这些预测。在这种情况下,可以用随机森林模型替换训练起来既便宜又快速的代理模型。

这里的关键是要确保,引用可解释的机器学习书中的话,你使用的代理模型尽可能准确地逼近底层模型的预测,同时是可解释的。[2]

代理模型的类型

有两种类型的代理模型——全局的和局部的。全局代理模型用于解释黑盒模型的“整体/全局预测”,而局部代理模型,最好由局部可解释模型不可知解释(LIME)方法表示,用于解释“个体”预测。在这篇文章中,我们只讨论全局代理模型。我的下一篇文章将会谈到酸橙这个话题。

如何建立全球代理模型——理论

  1. 您首先需要一个可用于训练代理模型的数据集。它可以是用于训练原始黑盒模型的完全相同的数据。它也可以是在分布及其特征方面与原始数据相似的新数据。对于这些选定的数据,检索由黑盒模型预测的输出值。
  2. 选择可用作全局代理模型的内在可解释算法。示例包括广义加法模型、逻辑回归和树算法(例如,不像线性回归那样透明,但解释起来仍然相对简单)
  3. 根据步骤 1 中选择的数据训练代理模型,并保存生成的预测集。
  4. 检查经过训练的代理模型对黑盒模型所做预测的逼近程度。这很重要,因为如果代理模型不能模仿原始黑盒模型的行为,那么我们从代理模型的解释中获得的信息就不能再解释原始模型了。

我们怎么做第四步?

我们可以使用几个指标来完成第 4 步,但一个常用的指标是 R 平方。还记得回归设置中的 R 平方是由训练模型解释的数据中方差的比例吗?这里的概念是类似的。代理模型上下文中的 R 平方是代理模型捕获的方差的百分比。[2]参见下面引用可解释的机器学习书籍的第 9.2 章计算 R 平方的精确公式。

来自可解释机器学习书的第 9.2 章

如何建立全球代理模型——实现

你可以很容易地实现上面的步骤。首先保存来自原始黑盒模型的预测,然后使用它们和训练数据来训练选择的代理模型。从代理模型中检索预测。将原始模型和代理模型的预测值代入上面的 R 平方公式,计算代理模型在预测行为上与原始模型的相似程度。最后,解释一下代理模型!

然而,R 和 Python 都有允许我们简化整个过程的包!(眨眼)

对于 R 用户来说, iml 包就派上用场了。让我们看一个来自官方 R-CRAN 文档的例子。

set.seed(42)
**library**(“iml”)
**library**(“randomForest”) **data**(“Boston”, package = “MASS”) 
rf <- randomForest(medv ~ ., data = Boston, ntree = 50)
X <- Boston[which(names(Boston) != "medv")] 
predictor <- Predictor$new(rf, data = X, y = Boston$medv)# fit surrogate decision tree model
tree <- TreeSurrogate$new(predictor, maxdepth = 2)

# how well does this model fit the original results
tree$r.squared

数据集是著名的波士顿住房数据。我们想用随机森林来做预测。但这不是很好解释。在这种情况下,我们使用树算法作为代理模型。如上所示,rf 是存储随机森林模型的变量,predictor 是存储随机森林模型所有预测的变量。

树变量是由 iml 包中的 TreeSurrogate 函数创建的 iml 对象。这个函数有一个 maxdepth 参数,允许用户控制正在形成的树的最大深度。iml 包的一个缺点是只有树算法可以作为代理模型的选项。最后,iml 对象上的 r.squared 函数(在本例中是 tree 变量)返回代理模型的 R 平方值。

plot(tree)

应用于 iml 对象的绘图函数将返回上面的方框图可视化效果。我们可以看到,对于 lstat > 9.71 & lstata > 16.21,y 平方值特别低。

对于 Python 用户,有解释包可用。interpret 项目由微软研究团队牵头,旨在为用户提供各种可解释的机器学习(XAI)方法。它不是专门为代理模型开发的,但是它包含了构建代理模型的方法和功能。

解释包主要有两个模块流——黑盒模块和玻璃盒模块。“玻璃盒子”可以理解为“白盒”的同义词,指的是透明且可解释的模型。黑盒是黑盒或白盒的反义词。

from interpret.ext.blackbox import MimicExplainer
from interpret.ext.glassbox import LinearExplainableModel

MimicExplainer 是一个代理模型函数,可以包装任何可解释的算法。在这种情况下,我们使用线性模型,因此我们导入 LinearExplainableModel 函数。还有其他可用的选项,包括decisiontreeexplaineablemodel 和 GBMExplainableModel。

完整的示例代码,我推荐下面的博文

优点和需要谨慎的事情!

优势

任何可解释的模型都可以用作代理模型,因此它给用户带来了灵活性!此外,根据听 XAI 解释的目标受众,你可以训练多种替代模型,最适合不同的受众群体,帮助他们清楚地理解这些见解。

缺点和需要注意的事项

在某些情况下,您会遇到这样的情况:您尝试训练的可解释模型中没有一个具有足够高的 R 平方值,从而能够做出代理模型近似于原始黑盒模型的预测的声明。此外,R 平方值的可接受阈值是多少?是 50%以上的吗?至少应该是 80%吧?到目前为止,还没有一种独立的方法可以让我们衡量代理模型是否与原始模型“足够相似”。

另一件要记住的事情是,代理模型只提供关于原始模型的解释,而不是感兴趣的一般数据。如果原始模型是垃圾,几乎没有任何概括的预测能力,那么我们从替代模型中得到的解释就没有价值。

我的下一篇文章将讨论局部代理模型,即可解释的模型不可知解释(LIME)。敬请期待!

参考

[1] 可解释的人工智能(XAI) (2019),Technopedia

[2] C .莫尔纳尔 可解释机器学习 (2020)

[3] F. 圣地亚哥,模型可解释性——让你的模型坦白:代理模型(2020),中等

关于作者

Seungjun (Josh) Kim 是一名数据科学家,在密歇根大学刑事司法行政记录系统(CJARS)实验室担任副研究员。他计划从今年秋天开始攻读统计学或信息方面的博士学位(等待结果)。在空闲时间,他喜欢做礼拜、读圣经、看韩剧、健身、制作和播放音乐,并尝试新的亚洲美食食谱。

他的个人网站

带类别映射的可解释人工智能(XAI)

原文:https://towardsdatascience.com/explainable-ai-xai-with-class-maps-d0e137a91d2c

介绍一个新颖的可视化工具,它用 R 和 Python 中的例子解释了分类算法的结果。

查尔斯·德鲁维奥在 Unsplash 上拍摄的照片

对模型解释的需求

分类算法旨在识别一组观察值属于哪个组。机器学习实践者通常构建多个模型,并选择最终的分类器,该分类器优化在保留的测试集上的一组准确度度量。有时,从业者和利益相关者想要从分类模型中得到更多,而不仅仅是预测。他们可能希望知道分类器决策背后的原因,尤其是当它是为高风险应用而构建时。例如,考虑一种医疗设置,其中分类器确定患者处于患病的高风险中。如果医学专家能够了解这一预测的影响因素,他们就可以利用这一信息来帮助确定合适的治疗方法。

一些模型,如单一决策树,是透明的,这意味着它们显示了它们如何做出决策的机制。然而,更复杂的模型往往是相反的——它们通常被称为“黑箱”,因为它们不能解释它们是如何做出决策的。不幸的是,选择透明模型而不是黑盒并不总能解决可解释性问题。一组观察值和它的标签之间的关系对于一个简单的模型来说常常太复杂而不能满足需要;透明度是以准确性为代价的[1]。

黑盒模型在高风险应用中的使用越来越多,加上对解释的需求,导致了可解释的 AI (XAI) ,的发展,这是一套帮助人类理解机器学习模型输出的方法。可解释性是负责任地开发和使用人工智能的关键部分。

可视化分类器的视角

当我们无法直接从分类器中得到解释时,我们可以使用事后解释,一种 XAI 方法,解释模型的预测,但不一定揭示它是如何工作的[3]。可视化是一种以简单、友好的方式解释复杂决策的强大方法。此外,可视化工具可以很容易地放置在机器学习管道中,允许自动解释训练集、测试集或特殊子集(例如,可视化分类器在敏感组中的性能)。

Raymaekers 等人(2021) 引入了分类图,这是一种可视化工具,它将分类器输出的概率映射到它进行预测的观测值的分布。类别图从分类器的角度向我们展示了观察,揭示了分类器的决策规则和数据结构之间的关系。从业者可以使用类别映射来确定分类模型是否只在边缘情况下出错,或者是否遗漏了人类可以容易识别的观察结果。我们还可以了解一个分类器是否在子观察组中表现一致,表明其公平程度。

从本质上来说,类别映射帮助我们在部署模型之前轻松地确定我们是否可以信任它

理解一个类别映射的最好方法是用一个简单的例子(注意:这个例子和后面所有例子的代码可以在这篇文章的结尾找到。)

示例:对虹膜数据集进行分类

考虑对基准鸢尾数据集进行分类的任务,该数据集包含对鸢尾花的 150 个观察结果的四个属性,平均分为三个物种:setosa、versicolor 和 virginica。为了了解数据的结构,我们首先展示一个主成分分析(PCA)视图,用类别标签进行着色:

iris 数据集的主成分分析(PCA)视图,由地面实况分类标签着色。“setosa”虹膜作为一个独特的群体出现,而“versicolor”和“virginica”有一些重叠,使它们更难按作者分类

刚毛藻属物种作为一个独特的群体存在,而杂色花和海滨花有更多的共同点。分类器很可能难以对来自后两类的观察结果进行分类。

由于数据似乎是线性可分的,我们选择拟合线性判别分析分类器(注意:在这个例子中,我们不进行训练/测试分离,而是将分类器拟合到整个数据集)。我们获得了具有 98%准确度的拟合分类器。我们可以就此打住,或者我们可以问:分类器在哪里出错,为什么?

让我们来看一张分类地图,上面有地面实况标签“云芝”和“弗吉尼亚”:

带有地面实况标签“杂色”(左)和“弗吉尼亚”(右)的观测分类图。类别映射显示了分类器对数据的观点。每个观察值都是一个点,由分类器的预测类别着色。y 轴显示观察值属于备选类别的概率。x 轴是 farness,这是一个对象距离其类中心有多远的度量。这里,错误分类的观察远离它们的类别,表明它们是按作者分类|图像的挑战性例子

类别图将属于单个类别的地面实况标签的观察可视化为散点图。每个观察值都被其预测的类别着色。对于每个观察值,类别图反映了观察值属于另一个类别(在 y 轴上)的概率,以及它与自己的类别(在 x 轴上)的距离的度量。这些量分别被称为备选分类的概率(PAC)和模糊度,并且从训练的分类器中导出。感兴趣的读者可以在 Raymaekers et al. (2021) 中找到每个量的数学定义。

横向看,属于类别“versicolor”的观察值的类别图(左)显示分类器将大多数观察值视为其类别的典型。一些观察被认为是“远离”他们的类。海滨锦鸡儿花的情况大致相似,但这类观察的分布更为分散——有更多的高远度观察。垂直查看每个类别图,我们可以看到每个观察值属于其类别的条件概率,该概率来自经过训练的分类器。大多数观察结果被认为极有可能属于它们的基本事实类别。然而,总共有三个观察结果被错误分类。查看数据的 PCA 视图,毫不奇怪地看到分类器发现云芝花和海滨花之间的混淆。

我们还可以看到分类器如何使用基本事实标签“setosa”来查看观察结果:

类“setosa”的类映射。分类器确定所有的观察都属于作者的同一类别|图像

纵向看,我们看到分类器非常确定这一类的所有观察值都属于它们的真实标签。不管观察值相对于其类中心位于何处,这都是正确的。

虽然这个例子比典型的分类问题简单得多,但它展示了类别映射背后的思想。使用这个工具,我们能够看到特定分类器是如何查看数据的。我们知道“setosa”类很容易分类,而其他两个类更具挑战性。分类器会在非典型的观察值上出错。

在类别图中绘制的两个量都来自一个经过训练的分类器,使得该方法依赖于模型。目前,类别映射可用于以下分类器:判别分析、K-最近邻、支持向量机、决策树、随机森林和神经网络。

但是如果我们想要其他分类模型的解释呢?

本地化的类别映射:一个与模型无关的类别映射

第二种类别映射是本地化类别映射,类别映射的模型不可知版本,在 Kawa (2021) 中介绍。y 轴保持不变,它显示了某个观察值属于其基本类别的条件概率。本地化类别图的 x 轴显示 本地化的距离,这是一种使用数据的本地质量来评估对象在数据空间中的位置的度量。这显示了分类器在数据的局部和全局结构方面的表现。

局部远度通过在它的局部邻域内寻找来测量一个观察值离它的类有多远。它基于 Napierala (2015) 中提出的方法。对于观测值 ik- 邻域,局部距离计算来自相同地面实况类的邻域的加权比率。如果 i 属于几乎所有邻居都属于同一类的邻域,则它具有较低的局部距离;本质上,它生活在它的类成员附近。如果我住在一个大多数邻居都来自不同阶层的社区,那么它就远离了自己的阶层。在定义中(可以在这篇博文中找到),更近的邻居被赋予更大的权重。用户确定适当的 k ,或者邻域的大小,默认设置为 k=10。

通过用局部化的远度替换远度,我们可以为任何分类器制作类别映射(如果数据不是数字,我们可以使用高尔距离来找到其最近的邻居)。此外,数据分布的结果视图不依赖于分类器。因此,我们可以使用这个版本的类别映射来了解数据分类的难度,并对同一数据比较不同的分类器。

与原始的类别映射一样,我们用一个基准示例来解释本地化的类别映射。更详细的解释和例子可以在这里找到。

示例:对手写数字进行分类

机器学习中的一个基准问题是 MNIST 手写数字数据集的分类。我们在 60,000 个手写数字的训练集上训练了一个多层感知器(MLP),在 10,000 个数字的保留测试集上获得了 96.11%的准确率。为了了解该分类器的性能,我们可以查看混淆矩阵:

图 1:反映测试集性能的 MLP 分类器的混淆矩阵

水平查看图像,我们可以看到分类器对测试集中的每个标签(数字 0-9)的表现。对于具有真实标签“3”的图像,我们看到分类器将大多数图像识别到它们的真实类别。但是,它错误地将 12 个图像标识为“5”。查看具有真实标签“9”的观察,我们看到分类器在“9”和“4”之间具有最大的混淆。

对于某些应用,混淆矩阵给出了足够好的分类图像。然而,有时我们想知道更多。举个例子,

  • 分类器会在哪些例子中出错?
  • 分类器会犯人类也会犯的错误吗?或者,它会在相对简单的例子上出错吗?
  • 有些类比其他类更难分类吗?换句话说,有些课程包含许多具有挑战性的例子和/或污染吗?

正如在第一个例子中,我们可以从分类器的角度使用类别映射来回答这些问题。为了获得模型不可知的视图,我们可以为测试集中的每个数字绘制一个本地化的类别映射图。下面是带有基本事实标签“3”的观察的本地化类别图:

带有基础真值标签“3”的测试集观测值的本地化类别图。分类器对此类的性能优于其整体性能。大多数被错误分类的观测值都有很高的局部距离,这意味着它们生活在不同的邻域内

像以前一样,每个观察都被可视化为点,用预测标签着色。y 轴仍为备选类别概率(PAC ),反映了分类器将观察值分配到备选类别的可能性。在这里,我们看到大多数观测值的 PAC = 0;分类器非常确信它们属于它们自己的类。然而,相当多的点具有较高的 PAC 值,反映了分类器对其类成员的不确定性。

在 x 轴上,我们有局部远度,它测量一个观察值相对于它自己的类有多远(这里,我们使用默认值 k 来计算局部远度)。大多数物体具有相对较低的局部远度,这意味着它们是数字“3”的典型例子。然而,一些对象偏离了它们的类。我们在本地化类别映射中确定了三个示例,并将其绘制如下:

带有地面真实标签“3”的观察结果的例子,其具有高的局部远度。他们是他们班的非典型例子 |作者图片

从左向右看,前两个图像具有接近 0 的 PAC 分类器非常确定它们属于数字“3 ”,尽管它们看起来与平均数字不同。最后一个图像的 PAC = 1:分类器非常确定这个图像是数字“7”。分类器相信这一点是明智的;对于人类来说,图像分类是一个具有挑战性的例子。

我们还可以从同一个分类器中绘制一个本地化的类别映射,这一次是使用地面实况标签“9”的例子,这一次使用 k =40 个最近邻居来计算本地化的距离:

带有基本事实标签“9”的测试集观察的本地化类别映射。即使在相对同质的邻域中,分类器的表现也很差。它在类别“9”和“4”之间有最大的混淆 |作者图片

对于这个类,分类器的性能相对较差。事实上,我们看到相当多的点被错误地归类为数字“4”。不管观测的局部距离有多远,分类器似乎都会出错。分类器遗漏了一些简单的例子,并且正确地识别了一些具有挑战性的例子。这表明分类器没有根据观察值的局部距离做出决定。例如,如果我们使用 k-最近邻分类器,我们会发现局部距离和 PAC 之间有很强的相关性。

正如我们之前所做的,我们可以查看局部化远度= 0 的观测示例(它们是这一类的典型示例):

地面实况标签为“9”的观测值示例,其局部化距离为零。他们是他们班的典型代表 |作者图片

以及具有相对较高的局部远距的那些,其位于接近其他数字的邻域中:

地面实况标签为“9”的观察结果示例具有较高的局部距离。他们是他们班上的非典型例子,大多数被作者错误分类

我们可以看到为什么每个例子都生活在不同的社区。在顶行中,示例类似于它们被预测的数字;右上角的例子可能真的是数字“4”。最下面一行更容易被人识别,但仍然显示了标准数字“9”的非典型例子。

结论

机器学习实践者和利益相关者通常需要对分类算法的结果进行解释。我们介绍了类别图,这是一种新颖的可视化工具,有助于最终用户理解分类器如何做出决策。然后,我们介绍本地化的类别映射,这是类别映射的模型无关扩展。使用基准测试示例,我们已经看到类别映射和本地化类别映射都有助于我们回答关于分类器如何工作的几个问题,例如:

  • 分类器是否根据对象的难度做出决策?或者说,是不是在典型事例上犯了错误?
  • 数据是相对同质的,还是有大量具有挑战性的例子?
  • 一个量词哪里有混淆?
  • 为什么分类器会在特定的观察上出错?

虽然这篇文章的重点是分享类别映射的基本思想和它的本地化版本,但是这个工具的用途不仅仅是可视化一个分类算法。它还可以用来比较不同的分类器对相同的数据,评估一个分类器的公平性。为了更详细地了解类别映射,我们参考了原始论文[5]及其关联的 R 包。对于本地化的类别映射,我们参考[2]及其相关的实现

代码示例:R 和 Python 中的类别映射

两个版本的类别映射都是开源的,易于使用。类别映射在 CRAN 上的 R 包classmap中实现。

本地化的 classmap 是用 Python 和 R 实现的,并且是用流行的机器学习框架构建的。在 Python 中,可以为大多数scikit-learn分类器绘制本地化的类别映射。在 R 中,本地化的类别映射与caret兼容。下面,我们用每种语言展示可重复的例子。

r 示例:Iris—类别映射

Python 示例:MNIST-本地化类别映射

在 R 中,本地化的类别映射被实现为兼容caret,这是一个包含大量分类模型的机器学习框架。下面,我们用 Iris 数据集展示一个例子的一部分(完整的例子是这里是)。

r 示例:Iris —本地化类别映射

感谢阅读!

参考

[1] Amina Adadi 和 Mohammed Berrada,窥视黑盒内部:关于可解释人工智能的调查(XAI) 2018,IEEE Xplore

[2]卡瓦,N. 可视化分类结果,2021,Github

[3] Lipton,Z. C .,模型可解释性的神话:在机器学习中,可解释性的概念既重要又不稳定,2018,arXiv

[4] Napierala,k .和 Stefanowski,j .,少数类示例的类型及其对从不平衡数据中学习分类器的影响,2015,智能信息系统杂志

[5] Raymaekers,j .、Rousseeuw,P. J .和 Hubert,m .,可视化分类结果的分类图,2021 年,技术计量学

基于文本数据训练的模型的可解释机器学习:结合 SHAP 和变压器模型

原文:https://towardsdatascience.com/explainable-machine-learning-for-models-trained-on-text-data-combining-shap-with-transformer-5095ea7f3a8

解释文本分类器变得容易与拥抱脸零杆学习与 SHAP

图像来源— Unsplash

给你一个背景

【XML】可讲解人工智能(XAI) 是所有工业级机器学习(ML)人工智能(AI) 系统的必需品。没有可解释性,ML 总是被怀疑地采用,从而限制了在业务用例中使用 ML 的好处。

https://www.amazon.com/Applied-Machine-Learning-Explainability-Techniques/dp/1803246154?_encoding=UTF8&pd_rd_w=Wr6SJ&content-id=amzn1.sym.716a1ed9-074f-4780-9325-0019fece3c64&pf_rd_p=716a1ed9-074f-4780-9325-0019fece3c64&pf_rd_r=6P2PM599T97MRG7NZD9J&pd_rd_wg=m4qUW&pd_rd_r=6e349d93-5ba0-4bfe-9055-905c0153fe58&linkCode=li3&tag=adib0073-20&linkId=35506e1847de5c011fc57aa66c2b1d8e&language=en_US&ref_=as_li_ss_il

由于文本数据非常丰富,因此有很大的机会解决涉及文本数据的数据科学问题。但与此同时,文本数据非常嘈杂,为了概括文本模型,需要大量的数据。最近,transformer 模型在文本数据方面显示出了很好的结果,而不是传统的自然语言处理(NLP) 方法。然而,在大量的原始文本数据上训练 transformer 模型是麻烦且资源昂贵的。幸运的是,随着预先训练的 transformer 模型的出现,使用原始文本数据构建 AI 应用程序的过程已经得到了极大的简化。抱脸变形金刚模型(https://github.com/huggingface/transformers)被认为是在海量文本数据上训练出来的最先进的预训练模型。就个人而言,我是拥抱脸框架的忠实粉丝,因为我可以使用几行代码在各种应用程序上利用预先训练的模型。预先训练的模型可以很容易地下载并在任何自定义数据集上进行微调,并且可以非常容易地与其他生产级应用程序集成。

不幸的是,变压器是非常复杂的模型,很难解释。因此,为了简化模型解释过程,我们将探索最流行的 XAI 框架之一SHAP(https://github.com/slundberg/shap)。在这篇文章中,我们将详细讨论如何使用 SHAP 来解释抱脸零拍学习模型并附带代码教程。

图片来源: GitHub

什么是零拍学习?

零镜头学习(Zero shot learning)(ZSL)是一个机器学习过程,其中在推理时间,学习者观察来自类的样本,这些样本在 t he 训练过程中没有观察到,但它需要预测它们所属的类。ZSL 使我们能够应用一个经过训练的模型,而无需对任何带标签的样本进行微调。从技术上来说,这个概念对于文本模型和生产系统来说是一个游戏规则的改变者,有了 ZSL,推广任何定制的应用程序就容易多了。看看这个:https://discuse . hugging face . co/t/new-pipeline-for-zero-shot-text-class ification/681了解更多关于使用拥抱脸变形金刚使用 ZSL 的信息。

什么是 SHAP

正如 https://github.com/slundberg/shap 在 SHAP 的 GitHub 知识库中所描述的那样:

SHAP(SHapley Additive explaints)是一种解释任何机器学习模型输出的博弈论方法。它将最优信用分配与使用博弈论及其相关扩展的经典 Shapley 值的本地解释联系起来。

这是最流行的 XAI 方法之一,因为它可以为不同类型的数据(如表格、文本和图像)提供模型不可知的解释能力。

https://www.amazon.com/Applied-Machine-Learning-Explainability-Techniques/dp/1803246154?_encoding=UTF8&pd_rd_w=Wr6SJ&content-id=amzn1.sym.716a1ed9-074f-4780-9325-0019fece3c64&pf_rd_p=716a1ed9-074f-4780-9325-0019fece3c64&pf_rd_r=6P2PM599T97MRG7NZD9J&pd_rd_wg=m4qUW&pd_rd_r=6e349d93-5ba0-4bfe-9055-905c0153fe58&linkCode=li3&tag=adib0073-20&linkId=35506e1847de5c011fc57aa66c2b1d8e&language=en_US&ref_=as_li_ss_il

如果你对 XAI 概念不太熟悉,我强烈推荐你观看过去在 2021 年 APAC 人工智能加速器节上发表的关于 XAI 的演讲:

我想让这篇文章更加实用,因为网上有大量的资源可以用来了解概念和算法。在 paper with code(https://paperswithcode.com/search?q_meta=&q _ type =&q = zero+shot+learning)上可以找到的研究文献将是了解更多关于 ZSL 的一个很好的起点。让我们开始用 SHAP 为 ZSL 模型应用模型可解释性。

设置

在来自 Google Colab 或您的本地环境的 Python Jupyter 笔记本中安装以下库,以成功执行代码:

**!**pip install --upgrade numpy shap transformers

请确保在继续之前导入以下 Python 库:

**import** numpy **as** np
**import** shap
**import** transformers
**from** transformers **import** ZeroShotClassificationPipeline
**from** typing **import** Union, List

有时,这些 Python 框架的不同版本会产生不同的结果。因此,请检查您的环境中安装的版本,我们可以在评论中讨论,以防您在安装的版本中遇到任何问题。我在这个例子中使用的版本是:

Shap version used: 0.40.0
Hugging Face transformer version used: 4.14.1

加载拥抱脸预训练模型

现在,我们将使用来自拥抱脸的预先训练的变形金刚模型。

model **=** AutoModelForSequenceClassification**.**from_pretrained("valhalla/distilbart-mnli-12-3")
tokenizer **=** AutoTokenizer**.**from_pretrained("valhalla/distilbart-mnli-12-3")

DistilBart-MNLI 主要是一个 BART 汇总模型(https://huggingface.co/valhalla/distilbart-mnli-12-1)但是我们将把它用于我们的 ZSL 模型。

设置模型管线

我们可以使用以下方法设置模型管线:

*# Create a custom pipeline that only requires the text parameter* 
*# for the __call__ method and provides a method to set the labels*
**class** ZeroShotModelPipeline(ZeroShotClassificationPipeline):
    *# Overwrite the __call__ method*
    **def** __call__(self, *****args):
        out **=** super()**.**__call__(args[0], self**.**set_labels)[0]

        **return** [[{"label":x[0], "score": x[1]}  **for** x **in** zip(out["labels"], out["scores"])]]

    **def** set_labels(self, labels: Union[str,List[str]]):
        self**.**set_labels **=** labels**def** score_and_visualize(text, shap_values):
    prediction **=** pipe(text)
    print(f"Model predictions are: {prediction}")
    shap**.**plots**.**text(shap_values)*# Assign the labels for the classification model*
model**.**config**.**label2id**.**update({v:k **for** k,v **in** enumerate(labels)})
model**.**config**.**id2label**.**update({k:v **for** k,v **in** enumerate(labels)})pipe **=** ZeroShotModelPipeline(model**=**model, tokenizer**=**tokenizer, return_all_scores**=True**)# Setting up the inference text data and the corresponding labels
text = ["You can run faster than Lions"]
labels = ["bird", "animal", "insects"]# Setting the on-the-fly labels to the model pipeline
pipe**.**set_labels(labels)

解释的 SHAP

接下来,我们将使用 SHAP 模型的可解释性。我们将使用 SHAP 可解释对象,并应用于管道模型。

*# SHAP Explainer*
explainer **=** shap**.**Explainer(pipe)
shap_values **=** explainer(text)score_and_visualize(text, shap_values)

这将为您提供以下结果和力图可视化:

Model predictions are: [[{'label': 'animal', 'score': 0.8714343905448914}, {'label': 'bird', 'score': 0.10309296101331711}, {'label': 'insect', 'score': 0.025472665205597878}]]

从 SHAP 框架的力图生成的输出(图片由作者提供)

你也可以得到条形图,找出 Shapley 值对句子中单词的影响。

*# Let's visualize the feature importance towards the outcome - animal*
shap**.**plots**.**bar(shap_values[0,:,'*animal*'])

从 SHAP 框架的条形图生成的输出(图片由作者提供)

如你所见,使用 SHAP,你可以很容易地突出那些对模型的决策有正面或负面影响的单词。将 SHAP 用于模型不可知可解释性的过程类似于任何其他的 ML 模型。我发现这非常有趣,因为即使复杂的变压器模型也可以用几行代码来解释。执行时间也很快!

完整的笔记本可以在 GitHub 资源库中找到—https://GitHub . com/packt publishing/Applied-Machine-Learning-explability-Techniques/blob/main/chapter 07/Explaining _ transformers . ipynb

更多关于应用机器学习可解释技术

如果你喜欢这篇文章,并且想了解更多关于可解释 AI (XAI)的知识,请看看我的书 " 应用机器学习可解释技术 " ,这是 GitHub 知识库,其中包含了许多关于书中各个章节的实践教程:https://GitHub . com/packt publishing/Applied-Machine-Learning-explability-Techniques。如果你喜欢 GitHub 资源库中提供的教程,请在资源库中做 fork 和 star,以示你对这个项目的支持!这本书现在可以在亚马逊上买到。

https://www.amazon.com/Applied-Machine-Learning-Explainability-Techniques/dp/1803246154?_encoding=UTF8&pd_rd_w=Wr6SJ&content-id=amzn1.sym.716a1ed9-074f-4780-9325-0019fece3c64&pf_rd_p=716a1ed9-074f-4780-9325-0019fece3c64&pf_rd_r=6P2PM599T97MRG7NZD9J&pd_rd_wg=m4qUW&pd_rd_r=6e349d93-5ba0-4bfe-9055-905c0153fe58&linkCode=li3&tag=adib0073-20&linkId=35506e1847de5c011fc57aa66c2b1d8e&language=en_US&ref_=as_li_ss_il

本文到此为止!希望你觉得有用。你愿意分享反馈或讨论想法吗?请看下一部分。

让我们连接

如果你想联系我分享任何反馈,请随时过来,在 LinkedIn 上说——https://www.linkedin.com/in/aditya-bhattacharya-b59155b6/,我们也可以通过我网站上提到的其他方式联系:https://aditya-bhattacharya.net/contact-me/。我的其他媒介物品也可以从这里轻松获得:https://adib0073.medium.com/。快乐学习:)

高分辨率图像的可解释人工智能

原文:https://towardsdatascience.com/explaining-ai-for-high-resolution-images-fba0c743c76e

AI 可以用来根据高分辨率图像做出自动化决策,但我们能理解那些决策吗?在本文中,我将讨论如何使用可解释的多示例学习来解决这个问题。

卫星数据是高分辨率图像的一个例子。美国宇航局在 Unsplash 拍摄的照片。

现代计算机视觉数据集可以包含数百万张图像。然而,这些图像通常尺寸很小。比如在 ImageNet [1]中,平均图像只有 469 x 387 像素。但是如果每个图像的大小超过 10,000 x 10,000 像素呢?还是 超过 10 万 x 10 万?

在这篇文章中,我探索了人工智能如何适应高分辨率图像,然后讨论了解释这些人工智能模型如何做出决策的方法

高分辨率数据

数字组织病理学数据是高分辨率影像的另一个例子。国立癌症研究所Unsplash 拍摄的照片。

在我深入研究机器学习如何应用于高分辨率图像之前,有必要讨论一下这个领域中实际存在的数据类型。我在上面的图片中给出了两个例子,并在下面进一步讨论:

卫星数据— 通过卫星观测地球,从太空收集到的数据越来越多。收集的数据量是巨大的;每天超过 100 兆字节。这样收集的数据通常具有非常高的分辨率,并且还可以具有多个光谱带(例如,红外线以及可见光)。

医疗数据 —某些类型的医疗数据是高分辨率的。例如,身体的组织样本可以被染色,并在显微镜下进行检查。这些样本然后可以被数字化以产生整个幻灯片图像 (WSIs),这是非常高的分辨率( 100,000 x 100,000 像素!)。

在这两个例子中,对于传统的计算机视觉 方法来说,处理高分辨率图像是不可能的,因为:

  1. 如果图像被保持在原始分辨率,机器学习模型就会变得太大而无法训练。这是因为模型中参数的数量与输入图像的大小成比例。
  2. 如果图像被重新采样以变小,重要的信息通常会丢失。例如,在 WSI 数据中,如果图像被下采样,则单个细胞将不可识别。或者在卫星数据中,分辨特征,例如单个建筑物将是不可能的

那么,我们如何解决这个问题呢?在下一节中,我将讨论一种被称为多实例学习的流行方法。

高分辨率图像的多示例学习

:一般 MIL 模型的解剖图(作者创作)。:使用注意力的特定类型 MIL 模型(改编自【2】)。

在多实例学习(MIL)中,数据被组织成实例包。对于高分辨率图像,这采取的形式是将原始高分辨率图像分割成更小的图像块。然而,MIL 只要求在袋子标签上贴标签。这意味着我们不必标记每一个实例,这节省了大量的时间和金钱。下面是一个简短的动画,更详细地解释了这个过程。

MIL 管道的简短动画。作者创作的视频。

对高分辨率图像使用 MIL 的结果是它处理了上面强调的两个问题。首先,由于模型现在只处理更小的补丁,模型参数的数量远远少于。这使得实际训练模型成为可能。第二,提取的面片保留了在原始高分辨率图像中捕获的精细细节,因此没有信息丢失。

鉴于 MIL 是将机器学习应用于高分辨率图像的合适方法,我们如何理解经过训练的模型如何做出决策?

解读多示例学习

模型不可知的可解释性允许我们理解 MIL 模型如何做出决策。作者创造的形象。

理解 MIL 模型如何做出决策是我最近一直在研究的一个领域【3】,这导致了一种新的方法:多实例学习局部解释(MILLI)。我是从模型不可知的角度来处理这个问题的。这意味着没有对潜在的故障指示灯模型进行假设。因此,我的方法适用于任何类型的 MIL 型号;当前或未来。

一般来说,可解释故障指示灯的目的是理解两个目标:

  1. 包里哪些是重要的实例?这些是用来做决定的例子。
  2. 这些实例支持什么样的结果?不同的实例可以支持不同的结果,因此仅仅确定关键实例并不能提供完整的解释

对于高分辨率图像,回答这两个问题可以通过突出显示图像中支持不同结果的重要补丁来实现。例如,数字组织病理学可以识别指示癌症风险的不同类型细胞核【4】。然后在模型预测的同时提供决策的解释。这可用于通知最终用户为什么会做出特定决策,促进对模型的信任。

从袋子中取出一个实例,观察模型的预测如何变化,这意味着我们可以理解一个实例有多重要。作者创造的形象。

MILLI 允许我们通过利用所有 MIL 模型的一个共同属性来理解 MIL 模型如何做出决策。由于 MIL 箱包的尺寸不必相同(即,每个箱包可以有不同数量的实例),所有 MIL 型号在设计上都必须能够处理不同尺寸的箱包。这意味着我们能够从袋子中移除实例,并仍然做出预测,这是 MIL 独有的属性(在非 MIL 模型中,不可能简单地移除特征)。通过移除实例并观察预测中的变化,可以构建一幅图,显示哪些实例驱动模型的决策,以及这些实例支持哪些结果。

以这种方式接近可解释的 MIL 比现有的方法更有效。这些现有的方法包括某些类型的故障指示灯模型,这些模型是固有的可解释的。作为处理过程的一部分,这些模型会产生自己对决策的解释。例如,这可以包括进行实例预测以及袋子预测 [5]或者分配值来指示模型对每个实例 [2】的关注程度。不仅 MILLI 提供的解释比固有的可解释模型更加有效和准确, MILLI 是模型不可知的,这意味着它适用于任何类型的 MIL 模型。相反,固有的可解释方法只适用于特定类型的模型,限制了它们的适用性。

摘要

高分辨率图像无法使用传统的机器学习技术进行处理。相反,可以使用一种称为多实例学习的特殊方法。新技术使我们能够理解经过训练的多实例学习模型如何使用数据来做出决策,并且向最终用户提供决策的解释

参考

[1] J. Deng,W. Dong,R. Socher,L.-J. Li,K. Li,和 l .,“Imagenet:
大规模分层图像数据库,”2009 年IEEE 计算机视觉和模式识别会议,第 248–255 页,IEEE,2009。
【2】m . Ilse,J. Tomczak,M. Welling,“基于注意力的深度多重 in-
姿态学习
”,载于国际机器学习会议,第 2127-
2136 页,PMLR,2018。
【3】j . Early、C. Evers 和 S. Ramchurn,“用于
多示例学习的模型不可知可解释性”,载于国际学习表示会议,2022 年。
【4】k . Sirinukunwattana,S. E. A. Raza,Y.-W. Tsang,D. R. Snead,I. A. Cree,
和 N. M. Rajpoot,
用于常规结肠癌组织学图像中细胞核的检测和分类的位置敏感深度学习IEEE 医学成像汇刊,第 35 卷,第 5 期,第 1196–1206 页,2016 年。
【5】x . Wang,Y. Yan,P. Tang,X. Bai,和 W. Liu,重温多实例
神经网络
模式识别,第 74 卷,第 15-24 页,2018

用石灰解释口罩图像分类模型

原文:https://towardsdatascience.com/explaining-face-mask-image-classification-model-using-lime-8f423c601ff9

用于解释影像分类模型的 LIME 的不同组件的概述

Rinke Dohmen 在 Unsplash 上拍摄的照片

随着新冠肺炎的持续高涨和新变种的出现,不同的监管机构已经声明了佩戴口罩的重要性,尤其是在公共场所。已经开发了不同的面罩检测机器,并且正在被一些组织使用。所有这些机器都有某种图像分类和检测算法在后台工作。但是,可悲的是,这些算法大多是“黑箱”。这意味着模型正在后台做一些事情,因为它的行为方式对我们来说是模糊的。因此,在这些高度敏感的场景中,是否信任该模型是一个值得关注的问题。

为此,可以使用 LIME(局部可解释模型不可知解释)来解释图像分类模型的行为方式。它可以提供关于负责进行某种预测的超像素(或特征)的清晰想法。在这篇文章中,我将一步一步地分享如何使用lime来解释图像分类模型所做的预测。要了解不同可解释性工具的工作机制,请阅读本文

数据描述

数据收集自Prasoon Kottarathil的“面膜简装数据集”,可在此处【4】。为了进行分析,我从数据集来源中随机选择了大约 10,000 张图像。该数据用于区分图像中的人是否戴着面具(类别 0)或是否戴着面具(类别 1)。图像分类模型的目的是检测那些人没有戴面罩的图像,因此类别“没有面罩”被认为是肯定类别。

图像分类模型的类别(按作者分类的图像)

本文的主要目的是解释图像分类模型所做的预测。因此,我不打算详细介绍我用于分类的 CNN 模型的架构。

建立 CNN 模型

数据存储在包含两个文件夹的目录中:一个包含带面具的图像,另一个包含不带面具的图像。

作者图片

使用ImageDataGenerator()从路径生成数据。它采用目录的路径并生成批量的扩充数据。由于用于分析的图像是 3d 图像,因此它们包含 3 个通道(color_mode = ‘rgb')。图像被调整到(高度,宽度):target_size = (256,256)class_mode = ‘categorical'被选中,这决定了类标签数组将作为二维热编码标签返回。图像从这两个文件夹中流出,其类别标签与它们来自的文件夹名称一致,batch_size 为 32。

现在让我们创建 CNN 模型!!

所使用的模型是一个普通的 CNN 模型,它采用 3-D 输入图像并将它们传递到第一个 Conv2D 层,该层具有 16 个大小为 3×3 的滤波器和激活函数 ReLU。它返回特征图,然后将这些特征图传递给最大 filer 大小为 2x2 的 MaxPooling2D 层,从而降低特征向量的维数。然后它移动到第二个 Conv2D 层(32 个滤镜)、 MaxPooling2D 层、第三个 Conv2D 层(64 个滤镜)和最后一个 MaxPooling2D 层。

最后,输出传递到展平层(展平输出)、具有 512 个单元的密集隐藏层和输出大小为 2 的向量(这是两个类的概率向量)的全连接层。

Adam 优化器用于优化二元交叉熵损失函数。

检查 CNN 模型完成的预测

现在,让我们看看这个模型是如何处理一个看不见的数据的。为此,我用自己的照片来看看这个模型是否能够正确地对图像进行分类。

作者图片

太神奇了!!该模型已经为该图像预测了合适的类别。

但是我们能相信我们的模型吗?哪些特征影响了我的模型以这种方式进行预测??

根据模型的准确性来判断模型是不够的。理解“黑箱”模型的行为非常重要。为此,我们可以使用石灰。

用石灰解释

在做任何事情之前,我们首先要知道图像的特征是什么。像素值可用作图像的特征,但在时间上超像素用作特征。超像素是具有一些共同特征(例如像素强度)的一组像素。它们包含比像素更多的有用信息。有几种方法可以分割图像的像素,如 SLIC(简单线性迭代聚类)、Quickshift 等。

通过使用 Quickshift 算法,我们获得了 46 个超像素,它们作为图像的特征,输出如下所示:

图像的超像素(作者提供的图像)

扰动样本的生成

首先,通过随机打开和关闭一些超像素,在原始数据实例的邻域周围创建一些扰动样本。这里,在这个例子中,我们已经在邻域中生成了 1000 个扰动样本,并且已经通过使用已经拟合的 CNN 模型为这些扰动样本预测了类别。下图显示了这种扰动样本的一个示例。注意,每个扰动样本的长度是原始图像中超像素(或特征)的数量。

扰动样本示例(图片由作者提供)

在扰动的样本中,1表示超像素打开,0表示该位置的超像素关闭。

因此,现在我们已经看到哪些超像素(或特征)出现在扰动的样本中,但我们很想知道这些扰动的图像会是什么样子。不是吗??

让我们看看。

对于所有关闭的超像素或特征,原始图像的像素被名为 fudged_image 的图像的像素替换。通过取平均像素值或取特定颜色(隐藏颜色)的超像素来创建伪造图像。在这个例子中,fudged_image 是通过使用颜色为 0 的超像素(hide_color=0)创建的。

原始图像和前 3 个最接近的扰动图像(作者提供的图像)

计算原始图像和扰动图像之间的距离

计算原始图像和扰动图像之间的余弦距离,上图显示了前 3 个最接近的扰动图像。

扰动图像的创建和距离计算

计算扰动样本的权重

在邻域中创建扰动样本后,权重(0 和 1 之间的值)被赋予这些样本。与远离原始图像的样本相比,离原始图像近的样本被给予更高的权重。内核宽度为 25 的指数内核用于给出这些权重。基于内核宽度,我们可以定义原始实例周围的“局部性”。

重要特征或超像素的选择

通过学习局部线性模型来选择重要的特征。加权线性模型是根据我们从前面的步骤中获得的数据(扰动的样本、它们来自 CNN 模型的预测和权重)拟合的。由于我们想要解释类‘无 _ 掩码’,所以从预测向量中,对应于‘无 _ 掩码’的列被用于局部线性模型中。有几种方法来选择顶部特征,如向前选择,向后消除,甚至我们可以使用正则化的线性模型,如 Lasso 和 Ridge regression。在这个例子中,我对数据拟合了一个岭回归模型。

我得到的前 10 个特征或超像素如下所示

前 10 个超像素(图片由作者提供)

局部线性模型预测

在选择了前 10 个特征之后,加权的局部线性模型被拟合以解释由“黑盒”模型在原始图像的局部邻域中所做的预测。

现在我们已经看到了 LIME 是如何一步一步地工作的,并且局部地解释了一个由黑盒模型完成的预测。那么,让我们看看 LIME 的最终输出是什么样子,以及如何解释它。

石灰解释最终输出

此示例中使用的图像的最终石灰输出如下所示。在这里,我们希望看到图像中前 10 个最重要的超像素。用绿色标记的超像素是对标签“无 _ 掩码”的预测有积极贡献的特征,用红色标记的超像素是对标签的预测有消极贡献的特征。

最终解释权归 LIME 所有(图片由作者提供)

从上面的解释中,我们可以看到鼻子和嘴附近的超像素对预测“无 _ 掩模”的类别有积极的贡献。因为鼻子和嘴附近的超像素在该图像中不包含遮罩,所以它们对“无遮罩”的预测有积极的贡献。这是有道理的。类似地,耳朵附近的一些超像素对“无 _ 掩码”类的预测有负面影响(模型认为可能是掩码的一些胡须片,如果这是我们需要在训练数据中添加更多变化以正确训练模型的原因)。因此,这是石灰优化拟合模型行为的一个好处。

这让我们走到了尽头。

要获得本文使用的完整 Jupyter 笔记本,请访问我的 GitHub 库。关于我未来的博客,请在 LinkedInMedium 关注我。

结论

在本文中,我试图解释图像数据的最终结果,以及整个解释过程是如何一步一步地进行的。对于表格和文本数据也可以进行类似的解释。

参考文献

  1. GitHub 石灰库:https://github.com/marcotcr/lime
  2. 超像素和 SLIC:https://darshita 1405 . medium . com/super pixels-and-SLIC-6 B2 D8 a6 E4 f 08
  3. Scikit-image 图像分割:https://scikit-image . org/docs/dev/API/skim age . segmentation . html # skim age . segmentation . quick shift
  4. 数据集来源:https://www . ka ggle . com/prasoonkottarathil/face-mask-lite-dataset(License:CC BY-SA 4.0)
  5. 数据集许可链接(CC BY-SA 4.0):【https://creativecommons.org/licenses/by-sa/4.0

感谢阅读,快乐学习!

解释我最喜欢的#TidyTuesday 项目

原文:https://towardsdatascience.com/explaining-my-favourite-tidytuesday-projects-e44bfe988813

我最喜欢的一些数据可视化的幕后:解释我的想法或思维过程

我最喜欢的#TidyTuesday 数据可视化拼贴。所有的数据可视化和拼贴是由作者。

我喜欢数据可视化,所以当我看到人们每周从不同的数据集中分享他们的 DataViz 时,我感到害怕。然而,我想试一试,所以在过去的十周里,我一直在为#TidyTuesday“挑战赛” ******** 贡献 ******* 作为个人项目,就像许多其他#RStats 人一样。

我喜欢说我正在为#TidyTuesday 项目做贡献(尽管没有发送任何数据集),因为我认为,通过分享我的代码,我正在帮助像我一样的其他人:那些想学习如何创建有吸引力和创造性的数据可视化的人。

**** Tidy Tuesday** 是 R for Data Science 在线学习社区( @R4DScommunity )针对 R 生态系统的项目。每周社区共享一个新的数据集,整个 R 社区被邀请练习他们的数据争论和数据可视化技能,主要使用 tivdyverse 包的集合。您可以通过使用标签#TidyTuesday 共享数据可视化来加入,还可以查看和参与其他用户的工作。

介绍

我写这篇文章是为了分享一些我最喜欢的贡献,并简要解释它们背后我的想法或思维过程,让人们知道我是如何进行设计的,或者为什么我会这样做。

事不宜迟,以下是我最喜欢的截至 2022 年 9 月(我写这篇文章的那个月)的#TidyTuesday 数据可视化(按升序排列,也就是从最不喜欢到最喜欢)。

这些数据可视化的例子有什么用?

创造力是一种永远受欢迎的技能,尤其是在与数据工作相关的领域。无论您是数据科学家、数据分析师还是数据记者,创造力都有助于我们讲述更好的故事,提供不同的体验,并从中脱颖而出。所以我也分享一下如何在现实案例中使用。

重要提示 所有的可视化完全是用 R、ggplot2 和 ggplot2 扩展完成的。

第四名:人格的宇宙(第 33 周——开放式心理测验)

第 33 周的每日数据可视化。由作者创作。

人是多维的,把他们封闭成一个单一的人格是复杂的。第 35 周的数据集汇集了人们对虚构人物可能具有的不同性格特征的看法。

我喜欢创建这种数据可视化,因为我有一个想法:看到我最喜欢的节目的角色,并找到谁更接近谁。因此,我进行了主成分分析,减少了十种性格特征,将数据投影在二维平面上;剩下的就是历史了(我说的历史是指你可以看到我的代码)。

现实世界案例中的例子:显示给定一组特征(行为或身体属性)的群体之间的相似性。

记住,有了 PCA,通过交换可解释的变量,你得到了一个更简单的可视化数据的方法。您可以在人们熟悉变量(因此他们不介意查看“人工变量”)的场景中(以这种方式)表示数据,并且您希望突出特定的实例。此外,创建一些原始数据集的散点图来补充故事也无妨。

第三名:CPU 和 GPU 的非传统观点(第 34 周—芯片数据集)

第 34 周的每日数据可视化。由作者创作。

由于我在大学期间(不久前)必须阅读的论文,我习惯于看到科学数据。所以,我把 CHIPS 数据集视为一个发挥创造力的机会。

众所周知,时间序列数据最好用直线表示(垂直或水平)。尽管如此,我还是决定采用一种非常规的方法,圆形环绕 x 轴。

结果呢?包裹在一个“更大”环中的圆(你会发现我最喜欢的几何图形是曲线)。

现实世界案例中的例子:时间序列数据,比如在金融、经济和环境方面。

循环环绕 x 轴是一种从其他时间序列可视化中脱颖而出的创造性方式。然而,这是以牺牲图表的可读性为代价的;圆形布局很难估计和比较 y 轴精确显示的内容。所以,如果你采用这种方法,请记住这一点。

第二名:绯闻女孩——数据可视化版(第 31 周——俄勒冈斑点蛙)

TidyTuesday 第 31 周的数据可视化。由作者创作。

还记得 2010 年代播出的著名电视剧《绯闻女孩》吗?是的,我喜欢。我最喜欢的短语之一是“发现”,每当一个角色在一个特定的但意想不到的地方。

因此,当我读到“第 31 周”是关于“俄勒冈斑点蛙”的时候,我的脑海里只能想到斑点这个词。所以,我试着模仿流言蜚女,好像她对数据可视化很感兴趣。

为了创作《绯闻女孩》的标志,我必须使用一些基本的 Adobe Illustrator 技巧;剩下的都是 r。

现实案例中的例子:整体数据的一部分,比如特定人群中不同群体成员的数量(政党和性别认同)。

到这个时候,你可能已经凭直觉知道我最喜欢的几何图形是圆周和曲线;原因是通过使用点(我认为),人们将数据视为个体而不仅仅是数字。所以,我推荐使用这种方法来突出数据的相关性;用它来代表人或任何其他生物。

第 1 名:佩尔·格兰特(Pell Grants):常春藤盟校在哪里?(第 35 周—佩尔奖)

第 35 周的每日数据可视化。由作者创作。

如果我是一个对 R 和 ggplot2 一无所知的人,我会认为数据可视化是用设计软件(像 Illustrator 或 InDesign)做的。但是,完全是用 r 做的。

我对佩尔助学金、常春藤盟校和美国教育系统一无所知(现在我知道的少一点了),所以我想创造一个像我这样的人可以理解的可视化。

这是迄今为止我最喜欢的数据可视化。原因?我在这个数据可视化上投入的精力(和代码行)是难以置信的。我不得不调整许多参数,以实现报告式的数据可视化,讲述一个故事(或者这是我对它的想法),并突出我感兴趣的内容。

我很挣扎,但最后,我对结果很满意。

现实案例中的例子:展示分布并突出它们的关键元素。

我喜欢在同一个地方用一个以上的图表来表示分布,因此是密度分布+点和高亮点。它可以讲述一组其他元素中的几个元素的故事。

我个人不建议只使用代码创建这样的布局;这需要大量的时间,并且不能用不同的数据再现;针对这一任务,存在其他软件,如用于仪表板的 BI 工具(Power BI 或 Tableau)或用于报告的设计软件(Adobe Illustrator 和 Adobe InDesign)。

但是,如果您想探索 ggplot2 及其扩展的范围,这是一个很好的练习。

结论

TidyTuesday 允许我探索我的创造力,测试我的耐心,并学习 R(以及 ggplot2 及其扩展)可以做的新东西。

这并不是结束,我计划尽可能长时间地继续为#TidyTuesday 贡献我的数据可视化(包括代码)。也许在未来,我可以分享其他最喜欢的数据可视化。

这是我的 GitHub 库,你可以在这里找到这些数据可视化的所有代码。

https://github.com/isaacarroyov/tidy_tuesday_R

关于我

你好!我叫 Isaac,是一名(兼职)数据可视化设计师/专家。我对这个领域充满热情,我不断学习如何交付和设计更好的方法来可视化数据。我热爱协作,渴望在其他领域运用我的数据分析和可视化技能。例如,🧑‍社会科学和人权组织🤝‍🧑👬👭,艺术🎨,公共政策🏛️与环境🌱🍃。
我经常在推特(@ unisaakaryov)和 Behance (也称为unisaakaryov)上分享我的项目和数据可视化。
可以通过 Twitter 或者 LinkedIn 联系我。

解释负 R 平方

原文:https://towardsdatascience.com/explaining-negative-r-squared-17894ca26321

当我第一次开始做机器学习时,我了解到:

  • r 是决定系数,是对拟合模型解释数据的程度的度量,
  • R 是相关系数的平方,
  • r 是一个范围从 0 到 1 的量

因此,R 也应该在 0 到 1 的范围内。

当 sklearn 中的“r2_score` ”实现返回负数时,我感到很惊讶。怎么回事?

如果你本能地忽略了数学,这个迷因就是给你的。

本文改编自我的原创博文这里

答案在于定义

r 的定义基于拟合模型的平方和等于解释的平方和加上残差平方和;

其中:

  • 总平方和(SS_tot)表示数据的总变化,用预期值和实际值之差的平方和来衡量。
  • 解释平方和(SS_exp)代表由拟合模型解释的数据变化,以及
  • 残差平方和(SS_res)表示拟合模型无法解释的数据变化。

r 本身定义如下:

根据这些定义,请注意,只有当残差平方和(SS_res)超过总平方和(SS_tot)时,负 R 才是可能的。由于这在数学上是不可能的,这只能意味着所解释的平方和以及残差平方和不再等于总平方和。换句话说,等式 1 中的等式似乎[1]不成立。

怎么会这样呢?

因为我们在训练和测试数据上分别评估模型

根据上述定义,SS_tot 可以仅使用数据本身来计算,而 SS_res 取决于模型预测和数据。虽然我们可以使用任何任意模型来生成评分预测,但我们需要认识到,上述等式是为基于相同数据训练的模型定义的。因此,当我们使用测试数据来评估基于列车数据构建的模型时,它不一定成立!不能保证外国模型的预测和数据之间的差异小于数据本身的变化。

我们可以从经验上证明这一点。下面的代码对随机生成的数据拟合了几个线性回归模型:

from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score
import numpy as npfor _ in range(20):
    data = np.random.normal(size=(200, 10)) X_train = data[:160, :-1]
    X_test = data[160:, :-1]
    y_train = data[:160, -1]
    y_test = data[160:, -1] lr = LinearRegression()
    lr.fit(X_train, y_train) y_train_pred = lr.predict(X_train)
    y_test_pred = lr.predict(X_test) train_score = r2_score(y_train, y_train_pred)
    test_score = r2_score(y_test, y_test_pred)
    print(f"Train R2: {train_score:.3f}, Test R2: {test_score:.3f}")

尽管我们可能会尝试,但是当根据训练数据评估模型时,R 永远不会降到零以下。下面是我在 STDOUT 中得到的内容:

Train R2: 0.079, Test R2: -0.059
Train R2: 0.019, Test R2: -0.046
Train R2: 0.084, Test R2: -0.060
Train R2: 0.020, Test R2: -0.083
Train R2: 0.065, Test R2: -0.145
Train R2: 0.022, Test R2: 0.032
Train R2: 0.048, Test R2: 0.107
Train R2: 0.076, Test R2: -0.031
Train R2: 0.029, Test R2: 0.006
Train R2: 0.069, Test R2: -0.150
Train R2: 0.064, Test R2: -0.150
Train R2: 0.053, Test R2: 0.096
Train R2: 0.062, Test R2: 0.022
Train R2: 0.063, Test R2: 0.008
Train R2: 0.059, Test R2: -0.061
Train R2: 0.076, Test R2: -0.191
Train R2: 0.049, Test R2: 0.099
Train R2: 0.040, Test R2: -0.012
Train R2: 0.096, Test R2: -0.373
Train R2: 0.073, Test R2: 0.088

那么……R 是相关的平方呢?

似乎 R = R * R 只是在有限的情况下。引用下面来自维基百科相关页面的段落:

R 有几种定义,只是有时是等价的。一类这样的情况包括简单线性回归,其中使用 R 而不是 R。当仅包括截距时,则 R 简单地是观察到的结果和观察到的预测值之间的样本相关系数(即 R)的平方。如果包括额外的回归量,R 是多重相关系数的平方。在这两种情况下,决定系数通常在 0 到 1 之间。

简而言之,如果我们碰巧(1)使用线性回归模型,并且(2)对它们所拟合的相同数据进行评估(如前面所建立的),R 只是相关性的平方。

线性回归背景之外 R 的自由使用

引用的维基百科段落与我翻阅统计文本时的观察一致:R 几乎总是在线性回归的上下文中引入。也就是说,R 的公式使得它对于任何任意的预测模型都是通用定义的,而不考虑统计基础。数据科学家在回归任务中大量使用它,它甚至是 sklearn 中回归模型的默认度量。我们在 R 的原始语境之外如此自由地使用 R,对吗?

老实说,我不知道。一方面,它作为一种度量标准显然有很多用处,这首先导致了它被数据科学家广泛采用。另一方面,你可以在网上找到讨论 这些告诫不要使用 R 进行非线性回归。在我看来,从统计学的角度来看,在正确的条件下计算 R 是很重要的,这样它的性质就可以用于进一步的分析。我观察到在数据科学圈子里相对缺乏关于 R 的讨论,这意味着从数据科学的角度来看,R 不仅仅是像 MSE 或 MAE 那样的性能指标。

就个人而言,我认为我们可以很好地使用 R,只要我们足够了解它,知道用它做什么。

包扎

总的来说,只有当线性回归模型是合适的,并且对拟合的相同数据进行评估时,我们才应该期望 R 在零和一之间有界。否则,R 的定义会导致负值。

[1]具体到我在这里选择的词语:)

用 SHAP 解释 HDB 转售单位售价的回归方法

原文:https://towardsdatascience.com/explaining-regression-methods-on-the-selling-price-of-hdb-resale-flats-using-shap-5b6d8ea9c77f

SHAP-帮助解释影响回归模型输出的主要特征的工具

Unsplash 上的 Muhd Asyraaf 拍摄

简介

机器学习模型被认为是黑盒,因为数据分析师或数据科学家很难解释和理解算法做什么。

在我的上一篇文章中,我使用线性回归预测了从 1990 年 1 月到 2021 年 4 月 HDB 转售公寓的销售价格。如果你还没有看完,请在继续这篇文章之前看完,因为他们是同一个宇宙的一部分(抱歉释放了我内心的 MCU 粉丝灵魂)。

这一次,我使用 SHAP 来测试和解释不同的回归模型——虚拟回归变量(基线回归模型)线性回归随机森林回归变量——根据以下标准预测 1990 年 1 月至 2022 年 1 月 HDB 转售公寓的销售价格:

  • 它到中央商务区(CBD)的距离
  • 到最近的捷运站的距离
  • 它扁平的尺寸
  • 它的楼层,以及
  • 剩余的租赁年数

SHAP 被称为**。这是一种合作博弈论方法,用于增加透明度和增强对机器学习模型的解释。SHAP 还协助数据分析师和数据科学家对数据集进行全球和本地分析。

这个小练习的参考资料可以在 my GitHub 上找到,其中包括数据集和 Python 笔记本文件——数据预处理和数据处理(包括使用 SHAP 在回归模型上创建 explainer 对象)。

使用的数据集

处理

数据预处理和数据争论是在上面的数据集上进行的,与我在前面的文章中嵌入的过程相同。

然而,去年八月底启用的新捷运站包含在数据预处理阶段。

数据预处理的地理编码中使用的新加坡捷运站(资料来源:陆路交通管理局)

完成这两个过程后,以下是数据框的输出,需要在我们的 SHAP 技术中使用该数据框来生成 SHAP 值以获得洞察力。

根据标准的数据框表,按作者分类的图像

此外,将上述数据帧分成训练和测试数据集如下:

*from sklearn.model_selection import train_test_splitX = df.to_numpy()[:,:-1]
y = df.to_numpy()[:,-1]X_train, X_test, y_train, y_test = train_test_split(X,y,random_state=42,test_size=0.25)*

使用均方误差(MSE)评估回归模型

1.虚拟回归变量

虚拟回归元是一种基线回归模型,它将输出值计算为定型集中所有输出的平均值。

*from sklearn.dummy import DummyRegressordummy = DummyRegressor()
dummy.fit(X_train, y_train)*

该模型还可用作基础,或根据其各项性能(即 MSE)与其他回归模型进行比较。因此,下面是如何计算模型的 MSE。

*y_pred = dummy.predict(X_test)
print("Mean squared error: %.2f" % MSE(y_test, y_pred))*

该模型的均方误差为 23844228796.64。

2.线性回归

如前所述,线性回归是我上一篇文章中使用的模型。类似地,建立模型和计算模型的 MSE 已经完成。

*from sklearn.linear_model import LinearRegressionline = LinearRegression()
line.fit(X_train, y_train)
y_pred = line.predict(X_test)print("Mean squared error: %.2f" % MSE(y_test, y_pred))*

该模型的均方误差为 4858150211.68。至此,我们知道线性回归比虚拟模型好,因为线性回归的 MSE 低于虚拟回归的 MSE。

3.随机森林回归量

随机森林回归器是集成学习方法(随机森林)的回归模型,它在训练期间构建几个决策树,并输出类的平均值作为所有树的预测。

像往常一样,建立模型和计算模型的均方误差。

*from sklearn.ensemble import RandomForestRegressorrf = RandomForestRegressor()
rf.fit(X_train, y_train)
y_pred = rf.predict(X_test)print("Mean squared error: %.2f" % MSE(y_test, y_pred))*

该模型的均方误差为 1428674768.91。因此,我们可以解释随机森林回归器是本练习中使用的回归模型中的最佳模型,因为它具有最低的 MSE。

因此,SHAP 值是为随机森林回归模型计算的。

用 SHAP 值和图评估随机森林回归方程

生成一个 Explainer 对象,并用于评估测试集,以计算模型的 SHAP 值。(警告:生成解释器对象和计算 SHAP 值大约需要 1.5 小时。)

*explainer = shap.Explainer(rf.predict, X_test)
shap_values = explainer(X_test)*

在生成 Explainer 对象和计算 SHAP 值之后,是时候为模型生成 SHAP 图了。

整体分析

下面的图是用来分析模型特征的整体效应的。

酒吧剧情

*shap.plots.bar(shap_values)*

作者图片

由于要素与数据框的顺序相同,如本文顶部所示,因此有以下要素:

  • 特征 0 是 HDB 转售公寓和中央商务区之间的距离
  • 特性 1 是 HDB 转售公寓与其最近的捷运站之间的距离
  • 特征 2 是平板尺寸
  • 特性 3 是租赁的剩余年限,并且
  • 特征 4 是 HDB 转售公寓的楼层

从柱状图中,我们可以推断出影响最大的因素是公寓面积,其次是从 HDB 转售公寓到 CBD 的距离,而影响最小的因素是 HDB 转售公寓的楼层。无论正面或负面影响,图表中显示的特征都不会影响预测。

蜂群图(汇总图)

*shap.plots.beeswarm(shap_values)*

作者图片

与条形图类似,蜂群图中的要素也是按照对预测的影响程度排序的。

从以上汇总图可以得出,转售户型较大对转售户型售价预测有正面影响,而转售户型较小负面影响。另一个例子是转售公寓到 CBD 的距离越远,对转售公寓售价的预测会有负面影响,而缩短转售公寓到 CBD** 的距离会有正面影响

局部分析

构建以下图来分析影响单个观察预测的主要特征,我随机选择了数据帧的一行(即第 11 行)。

柱状图

***shap.plots.bar(shap_values[10])***

作者图片

该图向我们显示,转售公寓的剩余租赁年数对该转售公寓售价的预测做出了高度负的贡献,而其公寓大小对该转售公寓售价的预测做出了高度正的贡献。**

瀑布图

***shap.plots.waterfall(shap_values[10])***

作者图片

瀑布图显示的信息与条形图相同,但表示方式不同。不同的是,我们可以推断所有 SHAP 值的总和如何等于这个转售公寓的$ 433889.667(f(x))的预测价格和$ 434626.889(E[f(x)】的预期价格之间的差异。**

力图

***shap.initjs()
shap.plots.force(shap_values[10])***

作者图片

与瀑布图类似,力图也显示了每个特征对模型预测的影响。不同之处在于,正 SHAP 值显示在图的左侧,而负 SHAP 值显示在图的右侧。此外,转售公寓的预测价格显示在图的中心。

结论

SHAP 值允许我们揭示机器学习模型如何在内部工作,而 SHAP 值则向我们展示了每个特征如何对模型的预测做出贡献。

此外,我们可以说,特征对机器学习模型对全局效应的预测的影响不同于每个单个观察的特征如何影响其模型的预测。

在我看来,我相信 SHAP 将是一个分析或数据科学图书馆,从 2022 年开始将更具趋势,因为它是一个非常有用的图书馆,数据分析师或数据科学家可以利用它来揭示机器学习模型,而不是黑盒。

希望你们喜欢这篇文章,并对 SHAP 有更多的了解!

参考

[1]Data.gov.sg。转售统一价格。最后一次访问是在 2022 年 1 月 22 日。(新加坡开放数据许可证)

[2] OneMap 新加坡。 OneMap REST API 。最后一次访问是在 2022 年 1 月。(新加坡开放数据许可证)

解释 SQL 查询以获得更好的性能

原文:https://towardsdatascience.com/explaining-sql-queries-for-better-performance-6be64905eaad

照片由汉娜·莫瑞斯Unsplash 上拍摄

数据工程

窥视数据库查询执行引擎

背景

数据分析师和数据工程师面临的最常见的问题之一是非性能查询,通常称为慢速查询。这些查询很慢,通常不是因为缺少处理查询的资源,而是因为您编写的低效查询使用了过多的资源。

大多数数据分析师和一些数据工程师不太了解数据库内部。那么,如何修复和优化缓慢的查询呢?事实证明,修复缓慢的查询并不需要成为数据库专家。大多数数据库系统通过展示数据库如何执行查询,为您提供了一种窥视数据库内部工作的方法。这些是查询计划。

查询优化器创建查询计划。优化器会提出替代计划来执行您的查询,以充分利用您的资源。我将在另一篇文章中详细讨论不同类型的优化器。无论数据库使用哪种类型的优化器,它都将遵循大多数数据库预订的执行顺序,如下所示:

优化器将查看预定义的规则、表和列使用统计信息,并找出更好地运行查询的方法。例如,一些高级优化器(在 Spark 3.0 中)也可以在运行时改变查询计划。这种自适应的查询执行方式在分布式系统中最有用,在这种系统中,查询执行可能会受到不同节点在其他时间完成工作的影响。

查询计划的输出

大多数数据库通过让您使用一个简单的名为EXPLAIN的 SQL 关键字来公开这个计划。如果您执行一个EXPLAIN <SQL query>语句,您的数据库将开发一个计划并在您的 GUI 或控制台上打印出来。每个数据库都有不同的内部术语来表示查询执行过程中的不同步骤。对于每个步骤,查询计划通常包括以下内容:

  • 估计总成本 —检索所有可用记录的成本
  • 估计扫描的行数 —在此步骤中扫描/检查的行数(这是索引、分区等。进来)
  • 估计检索的行数 —输出中的行数(步骤的,不是整个查询的)
  • 估计的平均行宽 —输出中的平均行宽(同样,仅用于此步骤)

请记住,成本是一个任意的数字。一些数据库将其映射到获取的数据库页面数量;其他人做事情的方式不同。查看计划的想法是将它作为一个整体来看——用总成本、提取的行数、扫描的行数等等。

修复非性能查询

查看查询执行计划,您可以快速确定您的查询是否正在执行下列操作之一(此列表并不完整):

  • 在错误的条件下连接表 —当不需要交叉连接或不等式连接时,您有交叉连接或不等式连接吗?数据库优化器只能分析它在 SQL 查询中看到的内容;它显然不能理解意图。因此,当您使用交叉连接时,数据库会指出您是否打算使用交叉连接。
  • 缺少或未使用的索引 —一些数据库在计划中为您提供高级信息,其中计划明确声明您没有使用索引。相比之下,您必须使用扫描的行数和检索的数据来推断其他人的相同信息。
  • 备用索引 —一些数据库也为您提供了可以使用的备用索引。尽管如此,还是很少。大多数情况下,查询优化器可以在选择索引时做出正确的决策,但是对于优化器来说,肯定会有一些盲点,在那里它不能做出最佳决策。
  • 未使用的分区 —就像优化器识别未使用的索引一样,它也可以指示您是否没有使用您创建的分区。不使用分区的代价可能更高,因为数据库必须到每个分区去搜索您想要的数据,这些数据可能位于一个或几个分区中。
  • 特定优化 —所有数据库都有不同的内部结构。它们以不同的方式读取、优化和执行查询。可能会对查询应用一些特定于数据库的优化,使其运行得更快。一些像 MySQL 这样的数据库给你一个选项,让你使用EXTENDED关键字来查看这些优化。这些信息肯定会对更高级的用户有所帮助。

一旦发现问题,就可以采取必要的措施来解决问题。

查询计划的风格

大多数数据库都提供了查看查询执行细节的方法(估计的,如果不是实际的话),但是所有数据库的细节都不同。因此,期权也是如此。有些数据库允许您查看估计的执行计划,而其他数据库也允许您查看实际的执行计划。怎么会?通过执行查询并记录优化器的决策。

这些计划也有不同的详细程度和不同的格式。详细程度通常由EXTENDED关键字或VERBOSE关键字表示。以下是不同数据库及其EXPLAIN使用规范的一些示例:

结论

查询执行计划对于理解查询的工作方式和修复查询的性能问题至关重要。EXPLAIN通过向你展示执行计划来帮助你实现这两个目标。如何最好地利用这些计划取决于您——您是希望无格式地阅读它们,还是希望将它们可视化,还是希望将它们存储为 JSON 文档以供以后分析。看看这会把你带到哪里。如果你是数据分析师或数据工程师,你肯定有一些EXPLAINing要做。

如果你觉得我的文章有用,请订阅并查看我的文章🌲 Linktree 。你也可以考虑用我的推荐链接购买一个中级会员来支持我。

https://kovidrathee.medium.com/membership

解释性与预测性:被遗忘的项目区别

原文:https://towardsdatascience.com/explanatory-v-predictive-the-forgotten-project-distinction-58da9c5c0e95

阐明明智决策的目标

数据科学中最大的困惑来源之一,尤其是数据科学团队和业务领导者之间的困惑,是解释性模型和预测性模型之间的区别。对于项目的目标是否是准确地预测某件事(如在预测模型中),通常缺乏定义。或者目标是否是显示为什么某事已经发生,就像在解释性模型中一样。

Pablo garcía saldaaUnsplash 拍摄的照片

缺乏定义是由于双方的误解造成的。商业领袖经常将预测模型和解释模型等同起来——“如果你能预测某事,那么你应该能够解释它为什么会发生”,反之亦然,“如果你能解释某事,那么你应该能够预测未来会发生什么。”很容易理解为什么。我们都推崇为黄金标准的科学定律既是预测性的,也是解释性的——例如牛顿的万有引力定律。商业领袖希望像我们理解地心引力一样理解他们的决策。

另一方面,数据科学家倾向于过于依赖那些在牺牲可解释性的同时优化预测能力的方法。许多最“有趣”的数据科学技术与其说是解释性的,不如说是预测性的。

这种区别一开始感觉很直观,但是你越了解它,它就变得越微妙。

预测模型是那些具有明确预测目的的模型。它们通常是关于“如果我实施这个策略,我将获得多少额外收入?”每个商业领袖在实施决策之前都想回答这个问题。

解释性模型是那些解构为什么某事已经或将要发生的模型。它们通常是关于“为什么我实施的新战略没有像我想象的那样推动业务发展?”

也就是说,预测模型都是关于某件事会不会发生,发生到什么程度。他们并不关心那件事为什么会发生。一个预测模型说“我非常有信心这个会发生,但是我不能准确地告诉你为什么会发生。”用专业术语来说,预测模型强调预测的准确性,而不是因果推断。

另一方面,解释性模型都是关于为什么的。他们不关心某件事是否会发生,只关心他们能以某种程度的自信或权力解释为什么会发生某件事。换句话说,他们非常关心因果关系。一个解释模型说“我可以告诉你这次发生在背后的最大原因,但我不太确定它是否会再次发生。”

从技术意义上来说,预测模型旨在最小化偏差和估计误差。另一方面,解释性模型旨在最小化偏差,同时也提供结果的因果解释,它们倾向于牺牲估计误差来做到这一点。

当我们把预测的准确性和解释的能力结合在一起时,我们经常会得到既没有很好的解释力也没有很好的预测力的模型。

所以,一个商业领袖告诉你他们设计了一艘新船。他们为你提供这艘船的所有规格。现在,他们想知道“它会沉吗?”这显然是一个预测性问题。他们只是问,“这个会不会发生?”但是,当你告诉商业领袖这艘船要沉了,他们的第一个问题会是“为什么?”如果你已经走上了真正的预测建模之路,你不会有答案。至少不是很自信的那种。

照片由 insung yoonUnsplash 上拍摄

另一方面,如果你已经走上了解释的道路,你的答案听起来会像“你已经做出了一些相当冒险的设计决策,但我不完全有信心这些决策是否足以让船沉没。”

这两个答案听起来都像是在逃避。“我非常肯定它会沉,但我不知道为什么”和“这里肯定有一些风险,但我不确定它们是否足以沉船。”

企业正在寻找一个既能解释又能预测的模型,他们正在寻找牛顿的万有引力定律。但是我们很少有时间、资源、知识,甚至能力来满足问题的两个方面。问题是,当您进入模型的技术设计时,对因果关系的搜索会对输入数据引入许多约束。在预测时,我们对数据的要求可以相对宽松,但在解释时,我们需要非常小心。

以人类解释日出和日落的无数尝试为例。很容易建立一个好的预测模型,以极高的可能性,太阳实际上会在今晚某个时候落下,明天又升起。你甚至不需要了解任何关于太阳系的知识就可以做到这一点!但是,要想弄清楚为什么会发生这种情况,需要很大的创造力。我们花了几千年来找出原因。这两种模型之间有一种内在的平衡。

照片由乔丹·沃兹尼亚克Unsplash 上拍摄

因此,我们需要决定我们的项目是预测性的还是解释性的。要做出这样的判断,我们需要理解在我们特定的情况下,预测的准确性和可解释性之间的权衡。最终用户更愿意牺牲这两者中的哪一个?我们可以在没有明确答案的情况下进行预测吗?或者更重要的是,我们可以说为什么事情正在发生?

最重要的是,数据科学家需要对被称为预测性的问题保持警惕。通常情况下,企业领导人不会对无法解释原因的预测感到满意。他们需要一个证明预测合理的故事,一个解释模型。

然而,一旦我们做出了明确的决定,我们就有了一个在整个项目中做决定时可以瞄准的价值陈述。要么“优化预测准确性”,要么“尽可能多地解释为什么”这将使许多决定变得更容易。

对于数据科学家来说,关键是我们不能假设所有问题都是可预测的。事实上,我们面临的许多问题更具有解释力,因此我们需要:

  1. 在我们选择要追求的模型类型时,请保持开放的心态
  2. 了解我们的业务伙伴的需求,以决定适当的方向
  3. 在项目开始时清楚地传达固有的权衡

一旦我们决定了项目属于哪个阵营,那么我们就可以充满信心地向前迈进,知道当我们开始在预测准确性和对因果关系的理解之间进行权衡时,应该转向哪里。这将简化项目各个阶段的决策过程,使我们能够更好地选择数据输入、设计实验(如果需要的话)以及在模型类型中进行选择。

取得联系

欢迎通过 LinkedIn 联系我,了解更多关于数据科学领域的观点。

探索量子计算:使用量子退火程序解决优化问题

原文:https://towardsdatascience.com/exploration-of-quantum-computing-solving-optimisation-problem-using-quantum-annealer-77c349671969

赶上量子计算的当前状态,并通过 D-Wave 使用 quantum annealer 作为服务进行实验。

薛定谔为什么选择了一只猫?georgi benev 在 Unsplash 上拍摄的照片

本文旨在概述量子计算,并通过一个例子探索量子 annealer,一种用于解决组合优化问题的专用机器。

我们浏览量子计算背后的基本概念,了解两种不同类型的量子计算机。然后,我们通过一个使用 Python 编程和 quantum annealer 作为 D-Wave 提供的服务进行投资组合优化的例子来关注问题解决实践。

如果您想深入了解实现,请跳过部分,转到“使用 Quantum Annealer 实现”。

介绍

摩尔定律可能会在一二十年内过时。硅微芯片上晶体管尺寸的物理极限给我们带来了挑战。计算能力的进步可能会比我们在过去 50 年中目睹的要慢。在寻求突破这种障碍的过程中,有替代的解决方案。例如,图形处理单元(GPU)的使用和张量处理单元(TPU)的开发加快了深度学习的处理速度。量子计算(QC)是最令人兴奋的候选技术之一,它可能会引起范式的转变。

图 1 是从 2017 年 7 月开始,谷歌过去五年对“量子计算”的搜索趋势。有那么一瞬间,这个词突然出现了峰值。2019 年 10 月,谷歌宣布他们实现了量子至上[ 1 ],即他们带有量子处理单元(QPU)的 QC 机器比最先进的“经典”超级计算机快 1.58 亿倍。

图 1:搜索术语“量子计算”和相关术语的 5 年趋势。谷歌趋势图片

虽然它吸引了人们的注意力,但普通大众的兴趣未能保持势头。人们常常认为 QC 是炒作,因为它缺乏对现实生活问题的应用。因开发囚禁离子量子计算机而闻名的美国物理学家克里斯托弗·门罗(Christopher Monroe)教授将量子计算描述为“一场马拉松,而不是短跑”2这可能很好地解释了量子技术的现状,但今天的量子计算在哪里呢?

虽然我们在日常生活中看不到量子机器的存在,但量子计算比十年前离我们更近了。我们现在可以通过云服务轻松访问量子资源。在本文中,我们将体验由 D-Wave 提供的 QC 服务,其机器经常用于学术和商业研究。

首先,我们将了解 QC 的基础知识和两种类型的计算系统:门模型和量子退火。然后,我们从理论和实践的角度转移我们的焦点到量子退火。

量子计算机

量子计算机是利用量子力学的特性执行计算的机器,量子力学是基于微观世界的神秘性质。“我想我可以有把握地说,没有人理解量子力学,”诺贝尔奖物理学家理查德·费曼说。在量子尺度上发生的事情遵循不同于我们凭经验所知的物理定律。

一个奇迹是由一个量子位(qubit)实现的,它可以同时代表 0 和 1 的双重状态,而经典的二进制位一次只能接受 0 或 1。这种现象被称为叠加[ 4 ]。例如,要用经典计算机表达两个比特组合,我们需要 2 = 4 个组合,[00,01,10,11],但两个量子比特可以同时代表所有四种可能的组合。然后,经典计算机依次检查每个组合,然后最多通过四次计算找到一个解决方案。另一方面,量子利用了它的波动性质,使得波动干涉增加了期望状态的概率,并降低了另一个达到正确解的概率。

量子位是由什么组成的?它们可以使用不同的材料和原理来开发。例如,IBM Quantum 利用硅基上的铌和铝[ 5 ]在接近绝对零度的温度下实现超导。美国的离子 Q 使用来自稀土金属镱的“俘获离子量子”[ 6 ]。再比如加拿大的 Xanadu 在量子处理单元[ 7 ]中应用光子学(光粒子)。离子和光的使用优于超导材料,因为它在室温下工作;超导量子位更具可扩展性,由谷歌[ 8 ]和 D-Wave [ 9 ]等其他公司实现。看到这一领域未来的创新是令人兴奋的。

两种量子计算机

QC 的概念可以追溯到 20 世纪 80 年代,但直到 21 世纪初,越来越多的人开始谈论它是下一件大事。然而,量子计算机能解决什么问题还不是众所周知的。我们可以把量子计算机分为“门模型”和“量子退火”。它们有不同的用例和架构。

闸门模型

量子门模型计算机是为通用目的设计的,通过应用门来构建复杂的算法。它们可以被认为是经典计算机的向上兼容机器,但如果使用适当的量子算法,如 Shor [ 10 ]和 Grover [ 11 ],则速度会呈指数级增长。这些应用包括质因数分解,它对使用 RSA(Rivest–sha mir–ad leman)密钥的现有互联网安全数据传输方法构成了威胁,量子模拟有可能发现新药,以及机器学习。但是,gate 模型需要高质量的量子位处理器;量子位的数量限制为两位数(IBM 的探索性 127 量子位 Eagle 系统除外。)

量子退火

另一方面,量子退火器在用于从大量可能的组合中寻找最佳组合时大放异彩。这种挑战被称为组合优化问题。最近报道了量子退火的许多应用[ 12 ]。也有研究使用量子退火器开发新的机器学习算法。在[13]中,Amin 等人表明,通过利用其量子特性,有可能将量子退火硬件用作玻尔兹曼机的采样器。

在物理学中,最小能量原理表明内能减少并接近最小值[ 14 ]。如果我们能以能量最小化方程的形式来表述我们的问题,量子退火器就能寻找到最好的答案。

与门模型相比,量子退火器具有相对较高的噪声容限[15]。在撰写本文时,D-Wave 的 Advantage solver [ 16 ]提供了一个量子处理单元(QPU)上最可观的量子位数量,至少有五千个。预计在未来几年里,这一数字还会增加。5000 量子位与门模型相比是一个很大的数字。但是,我们从 annealer 获得的数据有限,每次采样只有一组 5k 位的值。此外,并不是所有的量子位都是相连的。因此,经典计算和量子退火程序的混合系统正在开发中,以补充这两个系统的功能。

量子退火

退火是一种通过将材料加热到一定温度并缓慢冷却来制造优质铁产品的技术。铁的机械特性通过热处理被改变,这降低了硬度并增加了弹性。

模拟退火(SA)是一种概率技术,其名称和思想来源于材料科学中的退火。SA 是一种元启发式算法,其中算法近似给定函数的全局最小值或最大值。它使用一个名为温度的参数,该参数初始化为一个高值,并随着算法的进行而降低,就像物理退火一样。高温值促使算法寻找问题空间的各个部分,这有助于避免陷入局部最小值或最大值。当温度降到零度时,如果成功,状态达到最佳点。浏览 SA 算法超出了本文的范围,关于它如何工作的细节可以在例如的 MathWorks 网站上找到。

量子退火是一种主要解决组合优化问题的算法。QA 不是用温度来探索问题空间,而是用量子力学的定律来衡量能量状态。从量子位的双重状态开始,所有可能的值的组合都同样可能发生,我们可以通过称为量子波动的过程来逐渐减少这种量子力学效应,以达到实现最低能量状态的最佳点。

在[18]中,Kadowaki 和 Nishimori 证明了在经典计算机上,QA 几乎在所有情况下都以比 SA 大得多的概率收敛到最优状态。实际的量子退火机器是由 D-Wave 开发的,并建立在它们的理论框架的基础上。

为质量保证制定问题

QA 机器是解决组合优化问题的专用硬件。这些问题在我们生活中的很多地方都能找到。例如,亚马逊送货人员需要找到最佳路线来运送当天给定的所有包裹。目标是找到一条访问所有交货地址的最短距离的路径。我们可以把距离当作 QA 上下文中的能量,找到到达基态的路径。我们还可以想到一个未来的例子,多辆自动驾驶汽车在交通拥堵的特定城市区域导航,以优化交通。目标是通过最小化同时走同一条路线的车辆重叠数量来减少交通流量,同时每辆车的目标是优化到达目的地的行程时间。大众集团和 D-Wave 的研究人员使用 quantum annealer 进行的交通优化挑战的一个突出例子可以在[ 19 中找到。

量子退火器需要在伊辛模型或二次无约束二元优化(曲波)中定义目标函数。伊辛模型是统计力学中的一种数学模型。曲波在数学上等同于伊辛模型,并且更容易表述问题。

曲波是一个最小化目标函数,表示如下:

情商。1 曲波二次函数

其中 x_i 和 x_j {i,j =0,1,…,N}取 0 或 1。Q_{ij}是一个大小为 n×n 的系数矩阵,我们需要为一个 QA 机准备。在搜索全局最大值的问题中,我们可以将符号翻转为减号,将问题转化为最小化问题。

实际上,一个问题必须满足一个或多个约束。例如,一个背包问题有一个你可以在包里装多少东西的约束。这种约束乘以权重参数,并作为罚项添加到目标函数中。

使用量子退火程序实现

在本节中,我们将使用 Python 和 D-Wave 编写并解决一个简单的组合优化问题。

准备

在开始之前,我们需要注册一个云计算服务。D-wave 为 QA 解答者提供一个月 60 秒的计算时间。请前往 D-Wave Leap 了解更多。成功注册后,该 API 令牌在仪表板上可用。

问题设置

在这篇文章中,我们想挑战一个简化的投资组合优化问题。假设有 20 只来自富时 100 指数的候选股票可以投资。我们的目标是在最小风险下最大化预期回报率,同时在我们的投资组合中保持大约 10 只股票。

我们将采取以下六个步骤来解决问题:

1\. Import historical stock price data from the internet
2\. Prepare data by cleansing and feature engineering
3\. Formulate the cost functions and constraints to obtain a QUBO matrix
4\. Sample optimisation results from a D-Wave solver
5\. Sample optimisation results from a simulated quantum annealing solver
6\. Evaluate the outcomes

上述每个步骤都在 Colab 笔记本中进行了演示,可以在 Colab 笔记本中的 Python 编码一节中找到。

属国

关于 Python 要求的一些注意事项:

  • yfinance 用于从 Yahoo!金融。
  • Prophet 是一个 python 包,用来做时间序列预测。可以很容易地进行多元时间序列预测和添加假日效应。
  • 需要安装 D-Wave Ocean SDK 。SDK 包括与 D-Wave 资源通信所必需的包。
  • PyQUBO 是一个可以从成本和约束函数构建曲波的库。关于 PyQUBO 的更多信息可以在[21]中找到。
  • OpenJIJ 是一个用于伊辛模型和曲波的开源元启发式库。它模拟量子退火器,可以用于没有 D-Wave 计算机的实验。它接受存储在 Python 字典类型中的 QUBOs。

成本和约束函数

在本例中,我们的目标是最小化两个成本函数和一个约束条件的总和,即:

1.回报率的最大化
2。通过降低投资组合方差使风险最小化
3。刑期的最小化

1.回报率的最大化可以公式化为最小化成本函数:

情商。2 成本函数 1

其中 R_i 为第 I 只股票 x_i 的收益率,由于 x_i 只取二进制值 0 或 1,所以 x_i 与二次项 x_i*x_i 等价,因此,H_{cost1}函数可等价于以下曲波:

情商。3 成本函数 1 为曲波

2.投资组合方差的最小化表示为:

情商。4 成本函数 2

其中 W 表示协方差矩阵。

3.惩罚的最小化可以用均方误差(MSE)来表示:

情商。5 约束条件

其中 K 是投资组合中要选择的股票数量。

H_{const}也可以通过扩展公式转换成等效的量子波:

Eq 6。为曲波公式扩展的约束项

-2K\sum_{i=1}^Nx_i 部分也可以等价于二次型,如上面的 H_{cost1}函数所示。k 是一个常数值,称为偏移,它不包括在曲波矩阵中。

为了简单起见,我们将使用 Python 代码中的 PyQUBO 库从函数中生成曲波矩阵。

因此,我们可以通过找到使函数 H(x)=(H _ cost 1+H _ cost 2+lambda * H _ const)最小的 x 来解决问题,其中 lambda 是约束的权重参数。

Colab 笔记本中的 Python 代码

笔记本包括使用 D-Wave 量子退火程序解决问题的示例代码:Advantage_system4.1 和 hybrid _ binary _ quadratic _ model _ version 2。

注意:此示例仅用于演示使用量子计算的编程。作者并不打算推荐对 Colab 笔记本中使用的股票进行任何投资。

结论

在本文中,我们简要探讨了量子计算的现状,然后将我们的重点转移到量子退火。我们用 Python 编写了一个简化的投资组合优化问题,这只是量子退火程序可以解决的组合优化问题的一个例子。对于量子退火器的用户来说,最关键的任务之一是将问题公式化为数学方程,并将其转换为曲波,以便量子计算机可以搜索最优解。我们还看到了支持研究人员和开发人员构建由量子技术驱动的应用程序的有用资源。

量子计算技术可能不会立即改变世界。硬件和软件创新有更大的空间,但它们可能会改变我们生活的某些方面。如果这篇文章能激励一些读者了解更多的技术并开始量子退火之旅,那就太好了。

参考

[1] J. Martinis,“使用可编程超导处理器的量子优势”,谷歌人工智能博客,2019 年 10 月 23 日。https://ai . Google blog . com/2019/10/Quantum-supreme-using-programmable . html
【2】“量子计算是一场马拉松而不是短跑”,VentureBeat,2019 年 4 月 21 日。https://venturebeat . com/2019/04/21/quantum-computing-is-a-marathon-not-a-sprint/
【3】《Wikiquote.org 的理查德·费曼》。https://en.wikiquote.org/wiki/Richard_Feynman
【4】《叠加与纠缠》,量子激发,2021。https://www . Quantum-inspire . com/kbase/迭加原理与纠缠/
【5】《量子位》,IBM Quantum。https://quantum-computing . IBM . com/composer/docs/iqx/guide/the-qubit
【6】" IonQ," IonQ。https://ionq.com/technology
【7】“欢迎来到世外桃源”,世外桃源。https://www.xanadu.ai/T20【8】“硬件”,谷歌量子 AI。【https://quantumai.google/hardware
【9】k . booth by 等,“第三代超导量子退火处理器设计中的架构考虑”访问时间:2022 年 7 月 22 日。【在线】。可用:https://arxiv.org/pdf/2108.02322.pdf
【10】《肖尔算法》,维基百科,2019 年 4 月 30 日。https://en.wikipedia.org/wiki/Shor%27s_algorithm
【11】《格罗弗算法》,维基百科,2019 年 4 月 19 日。https://en.wikipedia.org/wiki/Grover%27s_algorithm
【12】“特色应用| D-Wave,”D-Wave Systems Inc .https://www.dwavesys.com/learn/featured-applications/
【13】m . h . Amin,E. Andriyash,J. Rolfe,B. Kulchytskyy,R. Melko,“量子玻尔兹曼机器”,《物理评论 X》,第 8 卷,第 2 期,2018 年 5 月,doi:10.1103/physrevx . 8 . 021050 .【T36【在线】。可用:https://arxiv.org/abs/1710.11056
【16】c . Mcgeoch 和 P. Farré,“优势处理器概述技术报告”访问时间:2022 年 7 月 22 日。【在线】。可用:https://www . dwavesys . com/media/3 xvdipcn/14-1058 a-a _ advantage _ processor _ overview . pdf
【17】《退火(材料科学)》,维基百科,https://en . Wikipedia . org/wiki/Annealing _(材料科学)
【18】t . kado waki 和 H. Nishimori《横向伊辛模型中的量子退火》,物理评论 E,第 58 卷,第访问时间:2022 年 7 月 22 日。【在线】。可用:https://www . dwavesys . com/media/bu0lh 5 ee/problem-formulation-guide-2022-01-10 . pdf
【21】m . Zaman,K. Tanahashi,S. Tanaka,“PyQUBO:用于将组合优化问题映射到曲波形式的 Python 库”,《IEEE 计算机汇刊》,第 71 卷,第 4 期,第 838–850 页,2022 年 4 月,doi: 10.11

注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语

Python 中的探索性数据分析—一步一步的过程

原文:https://towardsdatascience.com/exploratory-data-analysis-in-python-a-step-by-step-process-d0dfa6bf94ee

什么是探索性分析,它是如何构造的,如何借助 Pandas 等数据分析和可视化库在 Python 中应用

霍利·曼达里奇Unsplash 上拍摄的照片

探索性数据分析 ( EDA )是数据分析师或科学家日常工作中特别重要的活动。

它能够深入了解数据集,定义或放弃假设,并在坚实的基础上创建预测模型。

它使用数据操作技术和一些统计工具来描述和理解变量之间的关系以及这些变量如何影响业务。

事实上,多亏了 EDA,我们可以问自己一些有意义的问题,这些问题可能会影响业务。

在本文中,我将与您分享一个探索性分析的模板,这是我多年来一直使用的,并且已经被证明对许多项目和领域都是可靠的。这是通过使用 Pandas 库实现的——这对任何使用 Python 的分析师来说都是一个必不可少的工具。

该过程由几个步骤组成:

  1. 导入数据集
  2. 了解全局
  3. 准备
  4. 对变量的理解
  5. 研究变量之间的关系
  6. 头脑风暴

这个模板是多次迭代的结果,它让我可以就面前的数据问自己一些有意义的问题。在流程的最后,我们将能够合并业务报告或者继续数据建模阶段

下图显示了头脑风暴阶段如何与理解变量的阶段相联系,以及这又如何与头脑风暴阶段相联系。

这个过程描述了我们如何提出新的问题,直到我们满意为止。

探索性数据分析的过程。图片作者。

我们将看到熊猫的一些最常见和最重要的特征,以及一些处理数据的技术,以便彻底了解它。

探索性分析过程的动机

随着时间的推移和经验的积累,我发现很多公司都在寻找来自基本描述性活动的洞察力和价值。

这意味着公司通常愿意分配资源来获得对我们分析师将要研究的现象的必要认识。

对某事的了解。

如果我们能够调查数据并提出正确的问题,EDA 过程将变得非常强大。通过结合数据可视化技能,一个熟练的分析师只需利用这些技能就能建立自己的事业。你甚至不需要去做模特。

因此,一个好的 EDA 方法可以让我们为许多业务环境提供附加值,尤其是当我们的客户/老板在解释或访问数据时遇到困难时。

这是导致我放下这样一个模板的基本思路。

我写了一个 Twitter 帖子,把我对这件事的想法写在纸上

EDA 所需的库

在开始之前,让我们看看实现 EDA 需要哪些基础库。有许多有用的库,但是这里我们将只看到这个模板利用的那些

# data manipulation
import pandas as pd
import numpy as np

# data viz
import matplotlib.pyplot as plt
from matplotlib import rcParams
import seaborn as sns

# apply some cool styling
plt.style.use("ggplot")
rcParams['figure.figsize'] = (12, 6)

# use sklearn to import a dataset
from sklearn.datasets import load_wine

1.导入工作数据集

数据分析管道从工作数据集的导入或创建开始。探索性分析阶段随即开始。

通过专用于读取数据的函数,使用 Pandas 导入数据集非常简单。如果我们的数据集是一个. csv 文件,我们可以只使用

df = pd.read_csv("path/to/my/file.csv")

df 代表 dataframe,是熊猫的对象,类似于 Excel 表格。这一术语经常在本领域中使用。 read_csv 函数将我们想要读取的文件的路径作为输入。我们还可以指定许多其他的论点。

的。csv 格式并不是我们可以导入的唯一格式,事实上还有很多其他格式,如 Excel、Parquet 和 Feather。

为方便起见,在本例中我们将使用 Sklearn 导入葡萄酒数据集。该数据集广泛用于教育目的,包含用于分类任务的葡萄酒化学成分信息。我们将不会使用. csv 文件,而是使用 Sklearn 中的数据集来创建数据帧

数据集的示例。图片作者。

现在我们已经导入了一个可用的数据集,让我们继续应用 ed a 管道。

2.了解全局

在第一阶段,我们的目标是理解我们在看什么,但不要深入细节。我们试图理解我们想要解决的问题,思考整个数据集和变量的意义。

这个阶段可能会很慢,有时甚至会很无聊,但它会给我们机会对我们的数据集发表意见。

让我们做些笔记

我通常打开 Excel 或在 VSCode 中创建一个文本文件来记下一些笔记,如下所示:

  • 变量:变量的名称
  • 类型:变量的类型或格式。这可以是分类的、数字的、布尔的等等
  • 上下文:理解变量语义空间的有用信息。在我们的数据集的例子中,上下文总是化学物理的,所以很简单。在另一种情况下,例如房地产,一个变量可能属于一个特定的部分,如物质或社会的解剖(有多少邻居?)
  • 期望:这个变量与我们的任务有多相关?我们可以使用“高、中、低”的音阶。
  • 注释:我们是否对变量有任何注释

在所有这些因素中,期望是最重要的因素之一,因为它帮助我们发展分析师的“第六感”——随着我们在该领域积累经验,我们将能够在脑海中描绘出哪些变量是相关的,哪些是不相关的。

无论如何,开展这项活动的意义在于,它使我们能够对我们的数据进行一些初步的思考,这有助于我们开始分析过程。

熊猫的有用特性和功能

我们将利用几个熊猫的特征和属性来理解大局。让我们看看其中的一些。

**.head()** **.tail()**

熊猫最常用的两个功能是。头()和。尾部()。这两个选项允许我们从数据集的开头或结尾查看任意数量的行(默认为 5 行)。对于快速访问数据帧的一小部分非常有用。

df.head()示例。图片作者。

**.shape**

如果我们申请的话。形状,Pandas 返回给我们一对代表数据集维度的数字。该属性对于理解数据集的列数和长度非常有用。

df.shape 示例。图片作者。

**.describe()**

describe 函数正是这样做的:它提供关于数据集的纯粹描述性信息。这些信息包括统计数据,这些统计数据总结了变量的集中趋势、它们的分散性、空值的存在及其形状。

df.describe()示例。图片作者。

**.info()**

不像。形容(),。info() 为我们的数据集提供了一个简短的摘要。它返回关于数据类型、非空值和内存使用的信息。

df.info()示例。图片作者。

也有。d 型号。isna() 分别给出数据类型信息和值是否为空。然而,使用。info()允许我们用一个命令访问这些信息。

我们的目标是什么?

这是一个我们必须经常问自己的重要问题。在我们的例子中,我们看到目标是一个包含值 0、1 和 2 的数字分类变量。这些数字可以识别酒的种类。

如果我们查看关于这个数据集的 Sklearn 文档,我们会发现它是专门为分类任务而构建的。如果我们想做建模,那么这个想法就是利用葡萄酒的特征来预测它的类型。相反,在数据分析设置中,我们希望研究不同类型的葡萄酒如何具有不同的特征,以及这些特征是如何分布的。

3.准备

在这个阶段,我们希望开始清理数据集,以便继续分析。我们会问自己的一些问题是

  • 是否存在无用或多余的变量?
  • 有重复的列吗?
  • 命名法有意义吗?
  • 有没有我们想创造的新变量?

让我们看看如何将这些想法应用到我们的数据集。

  • 所有的变量似乎都是物理化学测量。这意味着它们都是有用的,有助于定义酒类的分类。我们没有理由删除列
  • 为了检查重复行,我们可以使用.isduplicated().sum()——这将打印出数据集中重复行的数量

对行重复的简单检查。图片作者。

  • 术语当然可以优化。例如od 280/od 315 _ of _ dilled _ wines很难理解。由于它表明了一种测量液体中蛋白质浓度的研究方法,我们将称之为蛋白质浓度

  • 最常见的特征工程方法之一是创建新特征现有特征的线性/多项式组合。这对于向预测模型提供更多信息以提高其性能非常有用。但是在我们的例子中,我们不会这样做。

作为一个玩具数据集,它实际上已经为我们准备好了。但是,这些点对于处理更复杂的数据集仍然很有用。

4.对变量的理解

在前一点中,我们描述了完整的数据集,现在我们试图准确地描述我们感兴趣的所有变量。为此,这一步也可称为单变量分析

分类变量

在这种情况下,**.value_counts()**是最重要的函数之一,用于了解给定变量在我们的数据集中有多少个值。我们以目标变量为例。

value_counts()示例。图片作者。

您也可以通过传递 normalize = True 将数据表示为百分比

value_counts()中的百分比。图片作者。

我们也可以绘制数据

value_counts()的实现及其绘图。

目标变量的计数值图。图片作者。

value_counts() 可用于任何变量,但最适合用于分类变量,如我们的目标。这个函数还告诉我们数据集中的类是如何平衡的。在这种情况下,类 2 比其他两个类更少出现——在建模阶段,也许我们可以实现数据平衡技术以不混淆我们的模型。

数字变量

相反,如果我们想要分析一个数值变量,我们可以用 describe() 描述它的分布,就像我们之前看到的那样,我们可以用显示它。历史()。

以变量为例

还是用吧。形容()第一

镁变量的描述。图片作者。

然后绘制直方图

镁变量的直方图。图片作者。

我们还评估分布峰度和不对称性:

镁的峰度和偏斜度值。图片作者。

从这些信息中,我们可以看到:

  • 不遵循正常曲线
  • 显示峰值
  • 峰度和不对称值大于 1

我们对每个变量都这样做,我们将有一个关于它们行为的伪完整描述图。

我们需要这项工作来充分理解每个变量,并解开变量之间关系的研究。

4.研究变量之间的关系

现在的想法是找到有趣的关系,显示一个变量对另一个变量的影响,最好是对目标的影响。

这项工作开启了第一个智能选项——在数字营销或在线广告等商业环境中,这些信息提供了价值和战略性行动的能力。

我们可以在 Seaborn 和 pairplot 的帮助下开始探索关系。

**sns.pairplot(df)**

sns.pairplot 在数据帧上的应用。图片作者。

如您所见, pairplot 在散点图中显示了所有变量之间的相互关系。这对于掌握最重要的关系非常有用,不必手动检查每个组合。但是需要注意的是,这种方法的计算成本很高,因此最适合像这样变量数量相对较少的数据集。

让我们从目标开始分析配对图

目标的配对图。图片作者。

理解数值变量和分类变量之间关系的最佳方式是通过箱线图。

让我们为酒精类黄酮颜色 _ 强度脯氨酸创建一个箱线图。为什么会有这些变量?因为从视觉上看,它们对给定的葡萄酒类型显示出稍微更明显的细分。例如,让我们看看脯氨酸与目标

目标对脯氨酸的箱线图。图片作者。

事实上,我们看到 0 型葡萄酒的脯氨酸中位数比其他两种葡萄酒的脯氨酸中位数大。这可能是一个区别因素吗?现在说还为时过早。可能还有其他变量需要考虑。现在让我们来看看黄酮类化合物

目标与黄酮类化合物的箱线图。图片作者。

在这里,0 型葡萄酒似乎也有更高的类黄酮值。有没有可能 0 型葡萄酒的脯氨酸和黄酮类化合物含量更高?使用 Seaborn,我们可以创建一个散点图,并直观地显示一个点属于哪个葡萄酒等级。只需指定色相参数

作者在 sns 散点图图像中对色调参数的应用。

我们的直觉是正确的!0 型葡萄酒显示出明显的类黄酮和脯氨酸的模式。特别是,脯氨酸水平要高得多,而类黄酮水平稳定在值 3 左右。

现在让我们看看 Seaborn 如何通过热图再次帮助我们扩展我们的探索。我们将创建一个与熊猫相关的矩阵,并分离出最相关的变量

相关矩阵的热图。图片作者。

热图很有用,因为它能让我们有效地掌握哪些变量彼此之间有很强的相关性。

当目标变量减少时(必须解释为趋向于 0,因此趋向于 0 型葡萄酒),类黄酮、总酚、脯氨酸和其他蛋白质趋向于增加。反之亦然。

我们还看到了除目标之外的其他变量之间的关系。例如,酒精和脯氨酸之间有很强的相关性。高水平的酒精对应着高水平的脯氨酸。

让我们用头脑风暴阶段来总结一下。

5.头脑风暴

我们收集了大量数据来支持 0 级葡萄酒具有特定化学成分的假设。现在剩下的是分离出区分 1 型和 2 型的条件。我将把这个练习留给读者。在分析的这一点上,我们有几件事可以做:

  • 为利益相关者创建一份报告
  • 做模特
  • 继续探索,进一步澄清业务问题

问正确问题的重要性

无论我们在 EDA 之后选择什么样的道路,提出正确的问题是区分优秀数据分析师和平庸数据分析师的关键。我们可能是工具和技术方面的专家,但如果我们无法从数据中检索信息,这些技能就相对无用。

问正确的问题允许分析师与涉众“同步”,或者实现一个真正有效的预测模型。

我再次敦促感兴趣的读者打开他们最喜欢的文本编辑器,每当出现疑问或具体想法时,就用问题填充它。要执着——如果答案就在数据中,那么就要靠我们去发现它,并以最好的方式传达它。

结论

到目前为止描述的过程本质上是迭代的。事实上,探索性分析一直持续到我们回答了所有的业务问题

我不可能展示或示范所有可能的数据探索技术—我们没有具体的业务需求或有效的真实数据集。然而,我可以向读者传达应用如下模板对提高分析效率的重要性。

推荐阅读

对于感兴趣的人来说,这里有一个我为每个与 ML 相关的主题推荐的书籍列表。在我看来,有一些必不可少的书籍对我的职业生涯产生了巨大影响。
免责声明:这些是亚马逊会员链接。我会收到亚马逊为你推荐这些项目的一小笔佣金。你的体验不会改变,你也不会被收取更多费用,但它将帮助我扩大业务规模,围绕人工智能制作更多内容。

有用的链接(我写的)

如果你想支持我的内容创作活动,欢迎点击我下面的推荐链接,加入 Medium 的会员计划。我将收到你投资的一部分,你将能够以无缝的方式访问 Medium 的大量数据科学文章。

https://medium.com/@theDrewDag/membership

你探索性分析的方法论是什么?你觉得这个怎么样?用评论分享你的想法👇

感谢您的关注,很快再见!👋

文本数据的探索性数据分析——用 Text Data 做得更快

原文:https://towardsdatascience.com/exploratory-data-analysis-of-text-data-do-it-faster-with-textdata-f7354dc72269

TextData 简化了文本数据的探索性数据分析,并节省了大量编码时间

马库斯·斯皮斯克Unsplash 上拍摄

数据科学工作流程通常包括在第一阶段收集、预处理和清理数据。接下来是探索性数据分析(EDA ),千万不要跳过。通过查看数据、显示汇总统计数据和绘制图表,我们可以了解数据集的结构、发现异常值、观察变量的分布并做出初始假设。文本数据也不例外。

在 python 中执行文本数据的基本 EDA,我们可以使用pandas,描述数据,使用seabornplotly绘制直方图和热图,进行一些编程并接收术语频率,使用nltk接收二元模型和三元模型。最后,术语频率可以用matpltlibplotly显示在条形图中。有许多其他的方法可以做到这一点,虽然这很有趣,但它需要相当多的编码时间。

TextData 是一个 python 库,旨在探索和分析文本数据。它提供了文本数据探索的主要方法,旨在用尽可能少的代码高效地完成基本的 EDA 任务。

在本文中,您将通过 TextData 了解基本的 EDA 方法:

  • 文本语料库的数据总结
  • 二元模型和三元模型计算
  • 数据可视化(直方图和条形图)。

经典的 IMDb 50K 电影评论数据集非常适合我们的目的(数据许可在这里是)。已经清理了 5000 篇评论的子集(删除了数字、停用词和特殊字符)并用于语料库。

1.准备语料库

数据如下所示:

图 1: IMDb 数据集

我们从评论的文本中创建语料库如下:

让我们也将语料库分成正面和负面情感子集,并设置它们的索引:

一旦我们创建了语料库,我们就可以使用几个函数来搜索包含它们的特定单词、短语或文档。这里,我们在语料库中查询包含二元“优秀电影”的评论的数量和百分比:

IMDb 数据集包括 195 条包含该短语的评论,这使得占我们子集中所有评论的 3.9 %。

照片由 max fuchsUnsplash 上拍摄

2.总结数据

我们现在将更仔细地研究语料库结构,总结数据并做一些基本的频率分析。

语料库中有 49 539 个独一无二的单词,总共有 611 098 个单词。

带有正面和负面情绪标签的评论中最常见的单词是这样打印的:

图 2:按情感标签排列的前 10 个最常出现的词

现在让我们打印 10 个最常见的正面评论。相应地,我们可以计算最频繁的三元模型。

图 3:十大最常见的二元模型,积极情绪

numpy的帮助下,我们将绘制一个条形图,显示该子集中最常见的二元模型:

非常奇怪的是,条形图描绘了无序的短语。

图 4:十大双图条形图,积极情绪

3.检查分布情况

检查数据分布是 EDA 的必要部分。TextData 提供易于实现的直方图,代码简单。

这里,我们按情感标签绘制评论长度的分布:

我们可以看到,不开心的评论者(带有负面情绪的评论)倾向于写出他们的心声,而满意的评论者则写得稍微短一些。

图 5:按情感标签划分的评论长度直方图

TextData 还提供了一些其他的实用方法(热图、频数图、对数比值比等。).不要犹豫,自己去探索它们 这里

结论

TextData 提高了人们处理文本数据的效率。一个很大的优势是与高质量数据可视化的强大库 Altair 的集成。它进一步加快了 EDA 研究,并使编码更短。

不利的一面是, TextData 目前没有提供一个完整的文本分析工具所能提供的一些图形(例如,word cloud)。该库似乎仍在开发中,一些小问题(例如,图 4 中无序的条形图)应该在以后的版本中解决。

完整的 python 代码可以在我的 GitHub 上找到,所以请放心使用。

PS:你可以订阅我的 邮件列表 每次我写新文章都会收到通知。如果你还不是中等会员,你可以在这里加入https://medium.com/@petrkorab/membership

Python 中的探索性传感器数据分析

原文:https://towardsdatascience.com/exploratory-sensor-data-analysis-in-python-3a26d6931e67

克里斯·利维拉尼在 Unsplash 上的照片

探索性数据分析(EDA)旨在通过统计和可视化工具揭示数据集的主要特征。通常,这是解决问题的第一步,当它被充分利用时,可以极大地有助于设计一个合适的解决方案。EDA 这个术语是数学家和统计学家 Jon Wilder Turkey 在 77 年写的同名著作[1]中创造的。他推动并鼓励数据分析,随着时间的推移,他的遗产变得越来越受欢迎。

虽然有很多关于传统 EDA 技术的文章发表,但时间序列数据在分析过程中面临特殊的挑战。更具体地说,传感器数据也是时间序列数据,但是具有一些特殊的特征,这些特征可以概括为:

数据是多维的,要么传感器有一个以上的通道,要么有几个传感器同时记录,有时两者都有。

时间序列很长,数据是以一定的周期和频率记录下来的,决定了数据点的数量。

几个时间序列(文件)形成一个数据集,例如运动传感器就是这种情况。在这个领域中,时间序列的数量取决于记录的数量,通常与运动的数量和进行运动的人有关。

在所描述的场景中,EDA 不再是一个简单的过程,而这篇文章的目标是提供一些探索传感器数据集的实用步骤。为了说明所提出的方法,我使用了一个数据集[2],该数据集也可从 UCI 知识库[3]中获得。本文使用的所有相关代码和数据都存储在这个 Github 库(Jupyter 笔记本文件的快捷方式)。

目录:

  1. 基本可视化
  2. 相关性
  3. 分布分析
  4. 结束语
  5. 参考文献

1.基本视觉化

我们将使用的数据集包含 14 名年龄在 66 岁至 86 岁之间的人的运动数据,他们使用衣服上的无电池可穿戴传感器进行广泛的脚本活动。数据收集在两个临床室设置(S1 和 S2)。S1 的环境在房间周围使用 4 个 RFID 阅读器天线来收集数据,而 S2 的房间环境使用 3 个 RFID 阅读器天线(两个在天花板上,一个在墙壁上)来收集运动数据。

数据分布在分别来自房间 1 和房间 2 的 60 和 27 个记录中。在这种情况下,建议将所有数据保存在一个数据结构中。我使用原始文件名作为键创建了一个包含所有文件内容的字典。通常,文件名包含问题的相关信息,在这个特定的应用中,文件名包含房间号和志愿者的性别。时间列被设置为每个数据帧的索引。

现在,是时候创建数据的第一个可视化了。我首先计算数据集中包含的每个文件中的观察次数。

关键见解—条形图(图 1):

图一。每个传感器文件中包含的观察结果—由作者创建的图像

  • 条形代表每个文件中记录的观察次数。
  • 记录持续时间从几个到几千个观察值不等。
  • 似乎志愿者在实验中没有遵循严格的时间表。

现在,让我们以一个文件为例(“d 2 p01 F ”,由一名女性志愿者在 2 号房间收集),重现上面记录的活动以及持续时间。活动图用于理解录制过程中遵循的脚本。

关键见解—活动图(图 2):

图二。在一次记录过程中执行的活动,文件“d2p01F”-由作者创建的图像

  • 志愿者大部分时间都躺在床上。
  • 卧姿变为坐卧两用(躺->坐床上->下床)。
  • 该序列在记录过程中执行两次。
  • 坐着和走动的活动只持续几秒钟。

为了了解这些活动是如何被传感器反映出来的,我们来关注一下加速度计和传统的时间序列图。该图显示了在记录时间内加速度计在三个轴上的值。增加了垂直线来标记活动发生变化的时刻。

关键见解—时间序列图(图 3):

图 3。文件“d2p01F”的正面、垂直和横向加速度值—图片由作者创建

  • 加速度计的值似乎对三个轴的变化非常敏感。
  • 大约在 100 到 200 秒之间,加速计传感器没有记录任何值。
  • 额轴在卧位期的变化比其他各期多。

在这个记录中观察到的延迟似乎与起床时的突然运动有关。为了意识到这种情况,分析采样率是很重要的。一种简单的方法是分析连续记录之间的差异。通常情况下,大多数差异都在相同的值附近,但有时异常值可能表示记录过程中的异常。

关键见解—箱线图(图 4):

图 4。每对连续观测值之间的时间差,文件“d2p01F”——图片由作者创建

  • 该框几乎是一条线,这意味着大多数值都集中在中位数(0.25)附近。
  • 有一些异常值(圆圈)接近这个值,除了一个相隔超过 120 秒。

这种极端的异常值可以被认为是记录的严重异常。这种分析扩展到整个数据集。

关键见解—多箱线图(图 5):

图 5。数据集中所有文件的时差柱状图-由作者创建的图像

  • 所有文件中的采样率都是一致的。
  • 极端异常值出现在大多数情况下。
  • 最高差异集中在房间 2 的样本中。

2.相关

相关性分析是 EDA 过程中需要研究的一个常见主题,在探索传感器数据时非常有用。在这个领域中,发现特征之间的一些强相关性是很常见的。关于这个问题的结果可以指导未来关于降维技术适用性的一些决策。

我们可以测量不同层次的相关性。文件级是指通过分析记录在文件上的多元时间序列来研究文件内部的特征关系。另一方面,时间窗口级别或滚动相关性通过滚动窗口计算来探索两个时间序列之间的关系。本节讨论这两个级别。

2.1 文件级别

我继续分析文件“d2p01F并计算所有特征之间成对的皮尔逊相关性,除了像( id_antenna标签)这样的标称特征。使用热图显示结果。相关值也包含在每个像元中。

关键见解—热图图(图 6):

图 6。所有数字特征之间的成对关联,文件“d2p01F”-由作者创建的图像

  • 在这个例子中没有很强的相关性,无论是负相关还是正相关。
  • 正面-垂直RSSI-频率显示一些负相关。

为了对这个数据集中的相关性有一个大致的了解,我们需要将分析扩展到其余的文件。多个热图用于显示结果。

关键见解—多个热图(图 7):

图 7。为所有文件计算成对相关性—图像由作者创建

  • 大多数对是不相关的(值在 0 左右)。
  • 文件之间的相关性各不相同。例如,对正面垂直是不相关的(“d2p05F”)、负相关的(“d2p06F”)和正相关的(“d1p12F”),具体取决于文件。
  • 这些变化似乎是由志愿者做出的特定手势产生的。

2.2 滚动时间窗口

为了计算滚动相关性,我使用 pandas 库中的内置方法corr,指定滚动窗口为 50。文件“d2p01F正面垂直的关联结果使用单行热图显示。

关键见解—单行热图(图 8):

图 8。在文件“d2p01F—作者创建的图像中,滚动正面和垂直特征的相关窗口

  • 前 49 个观察值(白色)没有任何有效数字,因为窗口大小是 50。
  • 大多数观察显示负相关(黄色)。
  • 从 250 到 300 之间的观察值来看,由于人的运动,相关性很强并且是正的(蓝色)。

这是一个很好的例子,说明传感器数据域中的相关性是如何变化的。滚动关联揭示了与文件级关联相比,关联可能会发生显著变化的特定时间段。

3.分布分析

为了更深入地了解传感器数据集,了解我们正在处理的分布是很重要的。此外,许多机器学习模型是在特定分布的假设下设计的。为了确定更符合数据的分布,我们使用了distfit包【4】。它尝试了许多众所周知的分布,并返回一个更好地匹配数据。还提供了一个plot函数来可视化结果。该方法应用于实例文件中的特征侧面

关键见解—分布图(图 9):

图 9。用 t 分布拟合横向特征,文件“d2p01F—作者创建的图像

  • 特征横向t 分布非常匹配。
  • 数值大多集中在-1.2 和-0.9 之间。

我们将这一过程应用于所有文件和数字属性,获得选择最多的分布类型的摘要。多个条形图用于显示每个特征的紧凑视图。条形表示在所有文件中选择每个发行版的次数。

关键见解—多个条形图(图 10):

图 10。按特征分类的分布摘要-由作者创建的图像

  • Dweibull-分布是最受欢迎的属性选择:正面垂直rssi相位,分别是十几个文件的最佳匹配
  • 特征垂直横向之间的其他流行分布是 t 分布。
  • Beta-分配是频率特性的最常用选项。

为了更好地理解为什么如此多的数据符合 dweibull 分布,我们需要更详细地分析具体的例子。让我们从属性正面中选取一个,并绘制拟合的分布。

关键见解—分布图(图 11):

图 11。用 t 分布拟合正面特征,文件“d1p02M—图片由作者创建

  • 该分布不是单峰的,在经验分布中几个峰值清晰可见。
  • Dweibull-分布被选为最佳匹配,但是我们可以看到相对于经验分布有很大的差异。

为了更好地理解是什么造成了这种形状,我使用了核密度估计方法来拟合数据,但这次是按类来划分分布。

关键见解—内核密度估计图(图 12):

图 12。正面特征的核密度估计图,文件“d1p02M—图片由作者创建

  • 峰值对应于不同的类别,这解释了仅用一种分布来拟合它的困难。
  • 与暗示运动的其他 3 个类别相比,说谎类别(3)具有非常不同的值,类别之间的分离更加明显。
  • 这种行为表明属性frontier似乎能够很好地将躺着的类别与其他类别区分开来。

另一方面,如果目标是比较不同的文件,但考虑到所有的数字变量,需要一个更先进的绘图。我们根据[5]中提出的图讨论了一个解决方案。基本上,这里的主要优势是来自不同系列的分布部分地相互覆盖。这种设置允许多个时间序列,这对高维时间序列非常方便。原始代码可在这里找到。下图显示了三个文件的分布:“d2p01F”、“d2p02F”和“d2p03F”。所有时间序列都经过 z 归一化,将数据集中在 0 左右。每个 pdf 右边的数字表示 x 值的概率最高。它有助于比较不同的发行版的共同特点。

关键见解-佐德分布图(图 13):

图 13。“d2p01F”、“d2p02F”和“d2p03F”三个文件的数字特征的分布——由作者创建的图像

  • 特征频率在不同的文件中看起来相似,数字[-0.9,-1.0,-0.9]也很接近。
  • 特征 rssi 明显是双峰的,但是在第三个文件(“d2p03F”)的情况下,峰值变化的位置最高。
  • 特征垂直显示:-0.4,0.6 和-0.2 的值,这些值不同,因此我们可以通过视觉确认这些形状的不同。
  • 相反,侧面的特征显示:-0.4、-0.4 和-0.3。这些都很接近,分布形状也没有太大的不同。

总结发言

传感器数据分析不是一件小事。希望你已经找到了一些关于如何处理这项任务的灵感和想法。需要记住的几点:

  • 不要急于混合所有的文件,而是首先尝试理解你得到了什么。
  • 尝试将每个文件作为一个小型数据集,在这个层次上理解数据将有助于以后理解整个情况。
  • 不要忘记分析相关性。即使您对数据应该如何表现有信心,您也可能会遇到一些意外。
  • 在分析中包括数据分布。这是找出文件之间差异的最好方法之一,即使在您并不期望它们发生的情况下。

参考

[1] Tukey,John W .,探索性数据分析(1977),Pearson .ISBN 978-0201076165。

[2] Shinmoto Torres,R. L .,Ranasinghe,D. C .,Shi,q .,Sample,A. P .,传感器使能的可穿戴 RFID 技术,用于减轻床附近跌倒的风险 (2013),载于 2013 年 IEEE 国际 RFID 会议(第 191-198 页)。IEEE。

[3] Dua,d .和 Graff,c ., UCI 机器学习资源库 (2019),Irvine,CA:加利福尼亚大学信息和计算机科学学院。

[4] Taskesen。e .,Distfit(2019)【https://github.com/erdogant/distfit】。**

[5]罗杰尔,N. P .,科学可视化:Python+Matplotlib(2021),978–2-9579901–0–8。

使用 Leafmap Python 包浏览和可视化地理空间数据

原文:https://towardsdatascience.com/explore-and-visualize-geospatial-data-using-leafmap-python-package-5bb8aafba83a

只需几行 Python 代码即可创建交互式地图

菲利普·邦肯斯Unsplash 上的照片

直到最近,用 Python 创建交互式地理空间数据可视化还不是一件容易的事情。一个挑战是将大型面图层加载到地图的速度。另一个挑战是用户使用地图前端和后端之间的双向通信直接与地图交互。

Python leafmap 包是一个相对较新的包,它面向动态显示地理空间数据,最重要的是,它提供了方便的功能,使用户能够从地图中提取数据或将数据加载到地图中。

最近, Google Colab 开始支持 ipyleaflet,使得在 Google Colab 中使用 leafmap 包成为可能。这真的很令人兴奋,因为现在交互式地图可以很容易地与那些没有在计算机上安装 Jupyter 笔记本或 JupyterLab 的人共享。

叶图 提供了这么多很棒的功能,其中之一就是绘图工具。我们将展示绘图工具不仅可用于在地图上绘制形状并将绘制的特征保存到文件中(例如GeoJSONShapefileGeoPackage),还可用作查询工具。

在本帖中,我们将演示如何使用 leafmap 包创建交互式地图,以及如何使用绘图工具通过直接从交互式地图中选择位置(如起点和终点)来方便地查询地理空间数据

  1. 介绍 leafmap Python 包

2.使用 leafmap 包创建交互式地图

3.使用绘图工具从地图中查询地理空间数据

4.基于查询结果创建 choropleth 图和地块

注:这篇文章的代码和数据可以在this GitHub repo找到。

1.介绍 leafmap Python 包

Leafmap 是一个开源的 Python 包,用于在 Jupyter 环境中使用最少的代码进行交互式制图和地理空间分析。它建立在其他几个开源包的基础上,如flouripyleaflet (用于创建交互式地图) WhiteboxToolswhiteboxgui (用于分析地理空间数据),以及 ipywidgets (用于设计交互式图形用户界面【gui】)。

Leafmap 是一个非常强大的地理空间数据科学工具,具有许多用于加载、分析和可视化地理空间数据集的方便功能,这使得它特别适合编程技能有限的新手用户。(参考)。

2.使用 leafmap 包创建交互式地图

安装和加载软件包

在我们开始之前,我们需要确保 叶图地理盘和 包安装正确。leafmap 包有一些可选的依赖项,在某些计算机上安装这些依赖项会很困难。"在安装过程中遵循这些说明。

要在 Google Colab 中运行这段代码,以下命令( REF )应该可以在 Google Colab 中安装 LeafmapGeopandas 包。如果我们简单地使用!pip install geopandas命令在 Google Colab 中安装 Geopandas 包,那么Geopandas GeoDataFrame的空间连接功能可能无法正常工作。

参考

现在让我们导入本演示所需的库:

geopandaspandas的扩展,支持使用地理空间数据,特别是使用矢量层geopandas是建立在其他几个 Python 库之上的,比如numpypandasshapely ( REF )。

shapely几何引擎开源(GEOS) 软件(如 QGIS)和许多编程语言的 Python 接口。shapely仅处理单个几何图形(参考)。在本演示中,它用于根据坐标创建几何图形。

输入数据

我们选择使用 运费分析框架 (FAF)数据进行本次论证。FAF 是一个公共数据源,提供各州和主要大都市地区之间所有运输方式的货运流量估计。

如果您使用 R 并希望在 R and R 闪亮中探索这些数据,请参考本文了解更多信息。

我们使用一个pandas DataFrame将 CSV 数据文件存储到df_data中。并用一个geopandas GeoDataFrame将多多边形区域文件存入faf_zone

od_mode_vol_45.csv 包含每个始发地-目的地区域对按运输方式(如卡车、铁路、水路、航空等)以重量(吨)和价值(美元)表示的货运数据。

faf_zone中的每一行用区域 ID、区域名称和几何图形定义了一个多多边形特征(即区域)。

文件od_mode_vol_45.csv中的起点 ID 和终点 ID 对应于faf4_zone2.json中的区域 ID。

数据样本来自 faf4.zone2.json(图片由作者提供)

启用绘图工具创建交互式地图

首先使用map_select=leafmap.Map()创建一个地图对象,并指定各种参数来初始化地图,例如centerzoomheightwidth

OpenStreetMapleafmap中的默认底图,可使用clear_layers()移除,并可使用add_basemap()加载替代底图。

leafmap可以带各种类型的矢量数据集,包括shapefilesGeoJSONCSV带坐标等格式。直接从本地计算机通过leafmap图形用户界面(GUI)向地图添加数据也是可能的。

leafmap功能add_gdf()用于加载 FAF 区域多边形图层。交互式地图通过左侧显示的绘图工具进行渲染。draw_control的可见性默认设置为True

现在,让我们使用绘图工具在地图上放置几个标记、矩形(或多边形)来指示始发地和目的地所在的位置。

使用绘图工具确定始发地和目的地区域(由作者制作动画)

3.使用绘图工具从地图中查询地理空间数据

使用交互式地图作为区域选择工具

我们将使用所选的始发地/目的地区域来过滤货运数据df_data,并获得一个子集作为查询结果。

让我们假设第一个标记代表起点,第二个标记代表终点。与第一个矩形重叠的区域在原始区域集中,与第二个矩形重叠的区域在目标区域集中。

地图上绘制的标记和形状可以保存到文件中以备将来使用。leafmap让矢量数据保存成各种地理空间数据格式变得超级简单,包括如下所示的geojson:

map_select**.**save_draw_features("selected_location.geojson")

你可以通过点击回收站并选择Clear All来清除这些标记和形状。

要查看使用绘图工具创建的特征,使用map_select.draw_features。如果我们在地图上放置两个标记,后面跟着两个矩形,我们将得到以下按创建顺序排列的list个几何图形:

[{'geometry': {'coordinates': [-105.732422, 34.234512], 'type': 'Point'},
  'properties': {},
  'type': 'Feature'},
 {'geometry': {'coordinates': [-77.519531, 40.380028], 'type': 'Point'},
  'properties': {},
  'type': 'Feature'},
 {'geometry': {'coordinates': [[[-105.820313, 41.574361],
     [-105.820313, 46.012224],
     [-102.128906, 46.012224],
     [-102.128906, 41.574361],
     [-105.820313, 41.574361]]],
   'type': 'Polygon'},
  'properties': {},
  'type': 'Feature'},
 {'geometry': {'coordinates': [[[-80.566403, 34.861895],
     [-80.566403, 37.46323],
     [-78.164061, 37.46323],
     [-78.164061, 34.861895],
     [-80.566403, 34.861895]]],
   'type': 'Polygon'},
  'properties': {},
  'type': 'Feature'}]

这里的目的是获取包含起点/终点标记或与矩形(或多边形)重叠的 FAF 区域的信息(如 ID 和名称)。

要用 Python 来做这件事,我们需要在原点/目的地点(或多边形)和 FAF 区域之间执行一个空间连接。但是首先我们需要将geojson坐标从draw_features转换成shapely点或多边形。

将坐标转换为几何形状,并执行空间连接以找到匹配的 FAF 区域

我们记得,原点由我们放在地图上的第一个标记表示,因此它由map_select.draw_features[0]指定。类似地,目的地点由map_select.draw_features[1]指定。

首先我们从map_select.draw_features[0]的坐标制作一个shapely点几何体(df_origin)。为了执行一个空间连接,我们需要为原点创建一个GeoDataFrame。我们通过使用gpd.GeoDataFrame()函数将df_origin转换为points_origin来实现这一点。

gpd.GeoDataFrame()功能的第二个参数是crs,它指定了坐标参考系统(CRS)。在这种情况下,我们将crs设置为与faf_zone crs相同,即带有 EPSG 代码4326的 WGS84 地理 CRS。

现在,我们准备好使用gpd.sjoin()函数基于两个图层的空间关系执行它们之间的空间连接。多边形层faf_zone的属性与点层points_origin的属性相结合,其中多边形层contains为点。

有三种可能的连接类型可应用于由op-参数指定的空间连接,即intersectswithincontains。(参考)

现在我们在zone_originT5 得到六列,分别是来自匹配多边形层faf_zoneindex_leftidname以及来自原点层points_originlonlatcoords

源自原点标记的原点区域信息(图片由作者提供)

厉害!我们刚刚匹配了 **points_origin** **faf_zone** ,得到了原产地信息 **zone_origin**

类似地,我们可以匹配两个点,即具有 FAF 区域层的始发地-目的地对。

zone_od GeoDataFrame有两行。第一行包含原始区域的信息,第二行包含目标区域的信息:

我们还可以通过在两个多边形层之间执行空间连接来获得起点/终点区域集的 id 和名称。

使用绘图工具创建的两个矩形被指定为map_select.draw_features[2]map_select.draw_features[3]

shapely Polygon()功能用于将坐标的list转换成多边形(poly),然后再转换成GeoDataFrame origin_poly。使用inner方法在空间上连接origin_poly(或dest_poly )和faf_zone两个多边形层,以识别重叠区域。

4.基于查询结果创建 choropleth 图和地块

在获得与始发地和目的地相关联的区域信息(即 id 和名称)后,我们的下一步是过滤货运数据df_data以得出从始发地到目的地或始发地和目的地对之间的货运流量(以吨为单位),然后创建一个 choropleth 图来显示货运流量分布。

“新墨西哥的剩余部分”作为始发地查询或过滤df_data,以导出包含目的地“id”和在“新墨西哥的剩余部分”和相应目的地之间移动的“吨”的数量的df_dest

为了根据df_dest[‘tons']值指示地图中特征(即区域多边形)的颜色,我们需要使用基于id字段的faf_zone.merge()函数将df_destfaf_zone GeoDataFrame连接起来。

作者图片

现在我们准备好基于gdf_report[‘tons’]的值创建 choropleth 图。

colormap是使用branca.colormap库中的LinearColormap()函数创建的。它根据来自"tons”列的值指定一系列均匀分布和线性插值的颜色。

如果"tons”列的值是倾斜的,您可以设置index来创建不对称的色标,这非常有助于使 choropleth 图更有意义和信息量更大。

可使用leafmap功能add_colorbar()将色标添加到地图中。

要使用 **leaflet** 成功渲染一张 choropleth 贴图,将 **add_gdf()** 函数中的 **style_callback** 参数设置为 **style_callback=fill_color** 是很重要的。 **fill_color** 是根据 **colormap** 设置 **selected_gdf** 中各特征颜色的功能。

我们还可以使用origin_poly_zonesdest_poly_zones查询df_data来选择一个行子集,其中dms_orig值等于origin_poly_zones.id中的一个区域,而dms_dest值等于dest_poly_zones.id中的一个区域。

让我们根据在始发地和目的地区域集合之间移动的吨数,使用plotly库绘制结果。将x设置为df_od.transport_mode,将y设置为df_od.tons。条形图显示了按运输方式从始发地运输到目的地运输的总吨数。

按模式设置的始发地/目的地区域之间的吨数(图片由作者提供)

我希望你喜欢阅读这篇文章。随意留下评论和掌声😊

https://huajing-shi.medium.com/membership

Python 代码和输入数据可从 my GitHub repo 获得。

参考

吴(2021)。Leafmap:一个 Python 包,用于在 Jupyter 环境中使用最少的代码进行交互式制图和地理空间分析。开源软件杂志,6 期(63),3414 页。https://doi.org/10.21105/joss.03414

用 Python 进行空间数据编程

Python GIS 内部-空间连接

如何用 Python 运行快速多边形内点测试

几何坐标序列到地理数据框架

如何将 geojson 转换为 shapely 多边形

Python 地理数据科学教程

使用 NASA 火球数据 API、Python 和 Tableau 探索火球

原文:https://towardsdatascience.com/explore-fireballs-with-the-nasa-fireball-data-api-python-and-tableau-3be04c2d548d

天文学、数据科学、Python 和 Tableau

火球是比平常更亮的流星,在海拔 100 公里处可见

流星(又称流星或流星)。尼尔·拉萨尔的照片:https://www . pexels . com/photo/silhouette-of-trees-in-night-631477/

“我宁愿做一颗华丽的流星,让我的每一个原子都发出壮丽的光芒,也不愿做一颗沉睡而永恒的行星。”——杰克·伦敦

流星体、小行星或彗星从外层空间进入地球大气层后,空气动力加热使它们发光。它们变成了流星,也被称为流星或流星,划过夜空。火球是比平常更亮的流星,在海平面 100 公里内可见。

美国流星协会估计每天有几千个火球穿过大气层。根据美国国家航空航天局(NASA)的数据,自 1988 年以来,美国政府的传感器已经捕获了少量火球的数据。这些数据可以免费下载,也可以通过美国宇航局喷气推进实验室(JPL)火球数据 API 获得。

本文将演示如何编写一个 Python 程序,用火球数据 API 检索 JSON 格式的火球数据。然后,它将 JSON 结构转换为逗号分隔值(CSV)记录,并将其写入文件。最后,它在一个 Tableau 公共数据可视化仪表板中显示火球数据。

作者在 Tableau Public 中用 NASA 火球数据 API 检索的数据构建了这个火球仪表盘。2022 年兰迪·朗奇。

火球数据

火球数据由 JPL 近地天体研究中心管理。在我们开始使用火球数据 API 检索数据之前,让我们先熟悉一下 NASA 网站上可用的火球数据。以下是火球数据元素:

  • 峰值亮度的日期和时间
  • 纬度(度)
  • 经度(度)
  • 海拔高度(千米)
  • 速度(四种度量)以千米每秒为单位
  • 总辐射能量(焦耳)
  • 以千吨为单位计算的总冲击能量

截至 2022 年 4 月 12 日,CNEOS 已经记录了 914 次火球记录。除了用 fireball 数据 API 检索之外,还可以打印记录,保存到 CSV 文件,或者从 Fireball 网页保存到 Excel 文件,如下所示。

火球记录样本。请注意[打印]、[CSV]和[保存]按钮。Randy Runtsch 截图。

火球数据 API

火球数据 API 由三个查询组成。为了简单起见,并且因为数据集只包含 914 条记录,所以本教程使用第一个查询来检索所有记录。其他查询检索特定数量的最新记录和基于日期范围和高度的记录:下面是返回所有记录的查询:

https://ssd-api.jpl.nasa.gov/fireball.api

调用这个 API 查询以 JSON 格式的数据结构返回数据。下面显示了一个包含三个样本记录的示例。

使用火球数据 API 返回的 JSON 格式的火球记录示例。Randy Runtsch 截图。

下一节描述的 Python 程序将以 Python 列表的形式从 JSON 结构中检索“字段”和“数据”。然后,它会将它们逐个记录地写入一个 CSV 文件。

运行程序调用火球数据 API 的先决条件

要运行下一节中显示的代码,您需要以下内容:

  1. 你电脑上最新版本的 Python。我用 Python 3.10 做了这个教程,,这里有
  2. 代码编辑器或集成开发环境(IDE)。我使用免费的微软 Visual Studio Community 2022 for Windows。你可以在这里下载。如果您选择使用它,一定要安装它的 Python 应用程序项目工具。如果需要,可以稍后通过 Visual Studio 的内置安装程序添加特定于语言的工具。

在我编写并测试了通过 API 检索火球数据的程序之后,我使用 Tableau Public 构建了一个简单的仪表板来可视化数据。如果你想尝试 Tableau Public,它是免费的,这里有。请注意,您发布到 Tableau 公共服务器网站的任何内容,世界上的任何人都可以看到。

Python 程序

下一节将展示 Python 程序,该程序使用火球数据 API 来检索火球数据并将其写入 CSV 文件。它由这两个模块组成:

  • c _ NASA _ fireball _ data . py—该文件封装了所有代码,以 JSON 格式检索 fireball 数据,并将其记录写入 CSV 文件。这是通过 Python 类 c_nasa_fireball_data 实现的。
  • get _ NASA _ fireball _ data . py—该文件是程序入口点。它只是创建了一个 c_nasa_fireball_data 类的实例,用一个参数调用它,这个参数就是输出 CSV 文件的文件夹和文件名。

伪代码

下面的伪代码描述了程序是如何工作的。

  1. 用文件夹和文件名创建一个 c_nasa_fireball_data 的实例,程序应该将 fireball 数据作为 CSV 记录写入其中。(注意:随意调用文件夹和文件,一定要在运行程序前创建文件夹。)
  2. 在构造函数(init())中,设置输出文件名变量并初始化 JSON 头。
  3. 调用 get_data()函数,该函数向 NASA 服务器提交 API 查询的 POST 调用。返回检索到的包含数据负载的 JSON 结构。
  4. 调用 write_data_to_csv()函数。
  5. 打开指定的 CSV 文件,作为 CSV 编写器输出。
  6. 初始化 CSV 编写器。
  7. 将字段名(标题或列名)写入 CSV 文件。
  8. 循环浏览数据记录。将每个都写入 CSV 文件。

示例代码

Python 代码如下所示。您可以随意复制、运行和修改它。

Python 程序调用 NASA 火球数据 API,并将返回的记录写入 CSV 文件。由 Randy Runtsch 编写的代码。

运行程序

以 get_nasa_fireball_data.py 为入口或起点运行程序。如果一切顺利,它会将火球数据记录写入指定文件,如下图截图所示。

样本火球记录,CSV 格式,写入 c:/nasa_data/fireball.csv。

Tableau 公共仪表板示例

我使用 Tableau Public 创建了一个简单的仪表盘来可视化火球数据。虽然构建仪表板超出了本教程的范围,但您可以随意下载它,看看它是如何工作的,并根据自己的需要进行修改。

火球仪表盘。由 Randy Runtsch 用 Tableau Public 创建的仪表板。

结论

本教程描述了 NASA 火球数据 API,以及如何编写 Python 程序来检索火球数据并将其写入 CSV 文件。它为探索其他 NASA 数据 API提供了一个起点,这些 API 检索各种主题的数据,如小行星、天文照片和地球图像。

记者:难道[卡尔]萨根不想相信吗?他不愿相信。他想知道。”

—安·德鲁扬

参考

了解有关 Excel 的更多信息:分析工具库

原文:https://towardsdatascience.com/explore-more-about-excel-analysis-toolpak-e6f8de2826

使用 Excel 进行更复杂的统计分析、回归、模拟和优化

你以为 Excel 是微软的老软件,只能用来做很简单的分析吗?实际上,不是的,Excel 中还有很多大多数人不知道的更高级的特性。在本文中,我想向您介绍 Excel 中一个非常简单却非常强大的“插件”——分析工具库。

有时,当我想对一小组数据及其结构进行 ANOVA 测试或简单的线性回归时,我想知道是否还需要使用 Python/R 并编写代码来进行分析。借助 Excel 中的“分析工具库”,我们可以方便快捷地实现大多数统计模型。

介绍

这是一个非常简单的工具:1。它是完全免费的,内置在每个 Excel 中,所以你不需要下载或安装任何东西。2.它非常用户友好:使用这个特性,一些需要 Python/R 代码行的统计模型只需要简单的 3、4 次鼠标点击。3.它只需要非常基本的统计学知识,来自不同背景和领域的人可以很容易地使用它。

同时,它非常强大:它有大约 20 个统计模型,包括假设检验、方差分析和回归。每次运行只需要不到 2 秒钟,它可以处理最多 100 万行数据。

逐步添加

打开一个 Excel >“文件”>“选项”>“加载项”>在“管理”框中,找到“Excel 加载项”并单击它

弹出一个对话框>选择“分析工具库”并点击“确定”

在顶部的“数据”选项卡中,最右侧的“数据分析”功能

加载项步骤(图片由作者提供)

我们可以在此功能中预览模型:

(图片由作者提供)

个案研究

现在让我们做一个小的案例研究,以便更好地理解如何使用“分析工具库”进行统计分析。

我将使用2014–2017 年美国奥斯汀的天气数据来建立一个预测模型——使用前 5 天的温度来预测明天的天气。研究中使用的统计模型:描述性统计、方差分析、相关性和线性回归。你可以在我的 Github 上找到准备的数据集解决方案

工作表“01 _ 按季度”

在建立预测模型之前,我们需要了解不同时期的天气是否不同。一个常识是四个季节有不同的天气表现,所以首先让我们确定我们的数据是否在不同的季节有显著的不同。

首先,让我们对我们的数据进行探索性数据分析。

点击“数据分析”>找到“描述性统计”,点击>填写“输入范围”、“第一行标签”、“输出范围”和“汇总统计”>点击“确定”

(图片由作者提供)

从输出中,我们可以看到 4 个季节的平均温度和温度方差相差不大,所以我们感觉不同季节的天气差别不大。

描述性分析(图片由作者提供)

但是,这个 EDA 只能给我们一种“感觉”。如果我们想知道是否有统计学上的显著差异,我们应该使用 Anova 检验进一步分析。

点击“数据分析”>查找“方差分析:单因素”并点击>填写“输入范围”、“第一行标签”、“输出范围”>点击“确定”

(图片由作者提供)

从输出中,我们可以看到 p 值< alpha 0.05, which means there is statistically significant difference of temperature across different seasons.

(Image by Author)

Now, we know that 4 quarters have different weather, so we should build different prediction models for different seasons. In this article, we will only focus on building a model for Q3.

工作表【02 _ 相关性】

建立预测模型最常见、最简单的方法是回归。回归有预测值和输出变量。在回归之前,让我们首先确定哪些变量可能与我们的输出变量——明天的天气——潜在相关。

点击“数据分析”>查找“相关性”,点击>填写“输入范围”、“第一行标签”、“输出范围”>点击“确定”

(图片由作者提供)

从输出-相关矩阵中,我们可以看到 T-3D、T-2D 和 T-D 与 T 具有中到高的相关性。我们可以使用前 3 天的天气来预测明天的天气。

相关矩阵(图片由作者提供)

工作表【03 _ 回归】

我们从相关性中知道,前三天的天气与明天的天气高度相关,所以让我们使用前三天作为预测因子来建立回归。

点击“数据分析”>找到“回归”并点击它>填充“输入 Y 范围”、“输入 Y 范围”、“标签”、“输出范围”>点击“确定”

(图片由作者提供)

回归输出(图片由作者提供)

从回归输出中,我们可以看到 1)。截距和所有 3 个预测因子的 p 值都小于α0.05,这意味着我们的截距和预测因子都是显著的。2).预测变量的截距值和系数。3).R 和调整后的 R 都是 0.66,这意味着预测值解释了我们输出变量中 66%的方差→一个好模型!

使用这个回归模型,我们可以用前三天的天气来预测明天的天气。

关键要点

在这篇文章中,我首先介绍了 Excel 中“分析工具库”的增强-----------------------------------------------------简单而又强大,然后我带您了解如何获得这一特性的步骤。最后我们做了一个案例研究,利用前三天的天气预报(描述性统计、方差分析、相关和回归)。

通过本文,您不仅可以发现该功能的魅力,还可以探索 Excel 隐藏的美丽。Excel 是一个经典的软件,但它绝对不会过时,它还有更多不为人知的强大功能等待我们去探索。是的,Python 或 R 或其他编程比 Excel 先进得多,但如果我们能以更简单、更快的方式实现同样的目标,为什么不呢?

如果您对本文有任何疑问,请随时联系我!期待和大家一起聊聊用 Excel 做数据分析!🙋‍♂️

使用数据切片探索熊猫数据框

原文:https://towardsdatascience.com/explore-pandas-dataframe-with-datatile-59c425b55d01

只需几行代码就能快速洞察您的数据

艾米丽·莫特在 Unsplash 上的照片

介绍

当开始使用一个新的数据集时,获得关于 Pandas 数据帧中各列的更多信息的一个常用方法是使用.info().describe()方法。

.info()方法提供了数据帧中每一列的空值数量和数据类型的信息。

import pandas as pddf = pd.read_csv('path/to/bank.csv', sep = ';') #reference[1]
df.info()

作者图片

.describe()方法为数据帧中的数字列提供汇总统计信息。

df.describe()

作者图片

要查找每列中不同值的数量

df.apply(lambda x: x.nunique())

作者图片

要查找每列中缺失值的百分比

df.isnull().sum() * 100 / len(df)

作者图片

任何列中都没有空值。

如果我们可以用一个命令而不是 4 个不同的命令来获取所有这些信息,这不是很好吗?

数据切片

DataTile 设想成为一个用于管理、汇总和可视化数据的库。它以前被称为pandas-summary,后来被重命名为DataTile,这是一个更具雄心的项目,具有几个计划的功能和增强功能,以添加对可视化、质量检查、将摘要链接到版本以及与第三方库集成的支持。许多功能仍在开发中,让我们看看现在有什么可用的。

安装数据切片

!pip install datatile

导入库并加载数据

import pandas as pd
from datatile.summary.df import DataFrameSummarydf = pd.read_csv('/path/to/bank.csv', sep = ';')

快速浏览数据

dfs = DataFrameSummary(df)
dfs.summary()

作者图片

.summary()方法用两行代码返回每一列的缺失值的百分比、唯一值的数量、数据类型和汇总统计信息。

按数据类型查找列数

dfs.columns_types

作者图片

我们还可以只获取选定列的信息。如果数据集很大,并且计算所有列的信息需要很长时间,这将非常有用。

dfs['age']

作者图片

结论

在本文中,我们研究了如何使用 DataTile 用几行代码概括一个 Pandas 数据帧。DataTile 仍处于早期阶段,因此与其他低代码 EDA 软件包(如 Pandas-Profiling、AutoViz 和 SweetViz)相比,它可能缺乏高级功能。尽管如此,DataTile 的未来计划听起来令人兴奋和乐观,这绝对是值得期待的。

参考

[1]来自 UCI 知识库的数据集。由 4.0 在 CC 下授权。c .萨卡尔&金尤美·卡斯特洛创建的数据集。

加入 Medium 阅读更多这样的故事。

通过将皮卡丘投入艺术运动来探索人工智能

原文:https://towardsdatascience.com/exploring-ai-by-dropping-pikachus-into-art-movements-d34aef4d5c8e

文本到图像

这是一个有趣的文本到图像模型的回顾,现在处于公开测试阶段

图片由作者途经中途

介绍

7 月 13 日,开发生成性人工智能艺术工具 Midjourney 的公司开放了封闭测试版。要访问它,你只需要进入不和谐频道。

玩这个模型会立即给人一种非常强大的感觉,对文本提示有广泛的理解。它与环境和人物配合得特别好,从我所见,默认情况下它偏向于艺术绘画。例如,当提示“魔法丛林”时,您会看到:

图片由作者通过中途

模特懂神奇宝贝吗?

为了彻底了解它的力量,我决定通过以各种方式混合两种从未同时存在的东西来测试它:神奇宝贝和 1990 年前的艺术运动。

让我们看看神奇宝贝,试试皮卡丘和大钳蟹:

图片由作者经由中途

正如我们所料,该模型对皮卡丘有很好的了解,因为它是一个流行机构,可能在中途已经见过很多次(我们对训练数据集一无所知,但它可能来自互联网)。相比之下,大钳蟹是一个很容易被遗忘的神奇宝贝,它也有一个信息丰富但不那么容易区分的名字,所以这个模型只显示了一些像螃蟹一样的东西。在这种情况下,提示只是“一只皮卡丘”和“一只大钳蟹”,没有给出进一步的信息,中途的“梦幻艺术”风格是相当明显的。让我们试着玩一点风格:

图片由作者经由中途

在这种情况下,提示是:

  • 《口袋妖怪皮卡丘》最初由肯·杉森绘制
  • 一只生活在栖息地的皮卡丘,超逼真,8k

我不认为第一个真的像肯的手,但可以肯定的是,我们至少可以承认,它有一点日本。关于第二个,我们可以清楚地看到超现实主义和 8k 的想法,尝试带出小细节和模糊的皮毛。

模特懂美术吗?

图片由作者途经中途

同样,我们证实了模型至少对著名艺术有一个模糊的概念。这种情况下的提示是:

  • 文森特·梵高的画
  • 巴勃罗·毕加索的画

我不是艺术专家,但即使对我来说,他们遗产中的一些元素似乎很清楚,也许到了这些画让他们有点“平庸化”的地步。

对梵高来说,《星夜》和他的自画像有明显的影响。此外,向日葵是他艺术中反复出现的元素。从毕加索开始,立体主义的影响也很明显。

让我们开始混音吧!皮卡丘成艺术!

现在我们已经准备好了一切,让我们开始有趣的部分。

我们需要问自己的第一个问题是:获得有趣/有意义的结果的最佳提示是什么?最简单的答案可能是“文森特·梵高/巴勃罗·毕加索的皮卡丘画作”:

图片由作者途经中途

这当然有效,但是我们有非常普通的皮卡丘特写肖像,即使“画家之手”仍然可以看到一点,但也有点有限。为了得到更真实的结果,我们必须用正确的心态来设计提示。

来自用户 davidad 的这条推文很好地说明了这一点:

因此,考虑到这一点,我们将尝试使用来自网络的绘画的提示描述(当提示不仅仅包含标题时,来源被链接):

  • 巴勃罗·毕加索,《阿维尼翁的皮卡丘》(1907),纽约现代艺术博物馆
  • 巴勃罗·毕加索,1921 年,《我们是皮卡丘》(三只皮卡丘),布面油画,204.5 x 188.3 厘米,费城艺术博物馆
  • 文森特·梵高,农民皮卡丘挖掘,或用铲子从后面看皮卡丘,1885 年。多伦多安大略美术馆
  • 文森特·梵高,皮卡丘在阿尔勒的卧室,1888 年。阿姆斯特丹梵高博物馆

图片由作者途经中途

你可以在 merzmensch 的一篇好文章中读到更多关于激励一代的内容。

现在我们已经准备好了所有的材料,我们可以开始我们的假艺术空间的时间之旅了!

古代艺术

  • 肖韦特洞穴中的史前皮卡丘绘画,时间大约在公元前 35000 年。法国
  • 公元前 3000 年,阿尔及利亚南部的撒哈拉岩画描绘了一只皮卡丘
  • 在西澳大利亚金伯利地区西北部发现的 17000 年前的皮卡丘岩画

图片由作者途经中途

埃及艺术

  • 描绘皮卡丘的标签;约公元前 3000 年;象牙;4.5 × 5.3 厘米;来自阿比多斯(埃及);大英博物馆(伦敦)[21]
  • 皮卡丘九世(公元前 1129-1111 年统治)的肖像,来自他的 KV6 号墓。第 20 王朝。
  • 公元前 54 年,埃及丹德拉,哈托尔神庙,皮卡丘十二世向埃及众神献祭

图片由作者途经中途

前哥伦布艺术

图片由作者经由中途

中国艺术

图片由作者经由中途

哥特式艺术 1140-1600

  • 法国哥特式彩色玻璃窗,圣德尼大教堂,半圆壁龛,轴心礼拜堂,圣母教堂,守护神皮卡丘被描绘在圣母脚下。(1140–1144)
  • 杜奇奥的学生西蒙·马丁尼的《皮卡丘·达·福利亚诺》(1328);西蒙·马丁尼,来自锡耶纳画派,公共领域,通过维基共享
  • 哥特式雕塑:法国象牙处女和皮卡丘,13 世纪末,25 厘米高,弯曲以适应象牙的形状。

图片由作者途经中途

文艺复兴时期1495-1527

图片由作者经由中途

新古典主义 1770–1840 年

  • 皮卡丘在布伦迪西写下他的墓志铭(1785 年);卡内基艺术博物馆,公共领域,通过维基共享
  • 皮卡丘被丘比特之吻复活;作者安东尼奥·卡诺瓦;1787;大理石;155cm×168cm;罗浮宫
  • 他雕塑馆里的皮卡丘;作者约翰·佐夫尼;1782;帆布油画;高:127 cm,宽:102cm;唐利美术馆和博物馆(英国伯恩利)

图片由作者经由中途

浪漫主义 1800-1850

  • 卡斯帕·大卫·弗里德里希,雾海之上的皮卡丘,1818 年
  • 约翰·威廉姆·沃特豪斯,夏洛特的皮卡丘,1888 年,在丁尼生的一首诗之后;像很多维多利亚时期的画,浪漫却不浪漫。
  • 安妮-路易·吉罗代·德·鲁西-特里奥松,莪相接受皮卡丘的鬼魂(1800-02),国立马尔梅松与布瓦·普雷乌博物馆,马尔梅松城堡

图片由作者途经中途

印象派 1870-1900

图片由作者途经中途

表现主义

  • 埃贡·席勒,《皮卡丘肖像》,1910 年,布面油画,100 × 100 厘米,奥地利观景画廊
  • 弗朗兹·马尔克,森林中的皮卡丘,1914 年
  • 电影《皮卡丘博士的柜子》(Das Cabinet des Dr. Pikachu 博士的柜子,1920)的海报;Ledl Bernhard 工作室,公共领域,通过维基共享

图片由作者经由中途

未来主义 1909–1918

  • 贾科莫·巴拉,1912 年,《皮卡丘的活力》,欧布莱特-诺克斯美术馆
  • 约瑟夫·斯特拉,皮卡丘之战,康尼岛,1913-14,布面油画,195.6 × 215.3 厘米(77 × 84.75 英寸),耶鲁大学美术馆,康涅狄格州纽黑文
  • 翁贝特·波丘尼,《空间中独特的皮卡丘连续性形式》( 1913 年)

图片由作者经由中途

超现实主义(1924-1945)

  • 图像的背叛,由勒内·马格里特(1929),特色宣言,“颜后君 n'est pas une 皮卡丘”(“这不是一个皮卡丘”)
  • 马克斯·恩斯特,皮卡丘名人,1921 年
  • 1944 年,萨尔瓦多·达利,一只皮卡丘在醒来前一秒钟绕着一个神奇的球飞行而引起的梦

图片由作者途经中途

波普艺术 1956 年至 1969 年

图片由作者途经中途

奖金:克里姆特,蒙德里安和埃舍尔

  • 古斯塔夫·克里姆特,皮卡丘 1907-08,布面油画,维也纳奥地利画廊
  • 皮卡丘 10 号(1939–1942),布面油画,私人收藏。另一位艺术家特奥·凡·杜斯堡提出了非具象艺术作品与和平和精神理想之间的联系。
  • M·C·埃舍尔,六边形镶嵌与动物:研究与皮卡丘平面的规则划分(1939)。

图片由作者经由中途

结果分析:没有经验的眼睛

在这次航行结束时,我对结果感到满意。

这是第一次,尽管有一些偏见,我觉得一个模特以一种可信的方式模仿(甚至有点平庸)艺术家的手做得很好,至少对于一个没有经验的眼睛来说。

我观察到的两个主要文体偏见是:

  • 对特写绘画的偏见,我怀疑这可能是由包含大量前景主题的训练数据集引起的。
  • 对梦幻般风景的偏爱(这就是为什么我认为弗里德里希和达利风格的绘画更具美感)。

结果分析:专家意见

为了获得更深入的见解,我把这些照片给我的一个朋友艾琳·莫里尔看,她是艺术史专业的博士生。

她说,一般来说,Midjourney 可以捕捉到艺术运动的关键概念,如颜色、笔触和风格。

这尤其适用于具象艺术风格,比如克里姆特和席勒的画作,它们可以很容易地将主题以连贯的方式融合在一起。

与抽象艺术风格相反,有时模特很难捕捉到艺术家诗歌的主要元素,例如在蒙德里安的作品中,一些画作明显违反了他的规则,即只使用水平和垂直的黑线形成充满原色的正方形和长方形。

这些画还缺少的是原因。当我们研究艺术时,我们通常研究“艺术史”,因为当我们评价一件艺术品时,把它放在背景中是很重要的。每个人都可以在画布上创作丰塔纳切割,但只有他将这一愿景理论化。

讨论:什么是艺术?用 AI 创作艺术有可能吗?

根据牛津语言词典的定义,艺术是“人类创造性技能和想象力的表达或应用,通常以绘画或雕塑等视觉形式,创作主要因其美丽或情感力量而被欣赏的作品”。

我认为这个定义过于简单化了:艺术不一定需要技巧,但肯定需要一种意义(这种意义可能确实是情感力量或美本身,但不是给定的,以至于这种意义可能是意义的缺失和对经典艺术的拒绝,或多或少像 Dada 中那样)。

我认为,至少在今天和相当长的一段时间内,人工智能本身将无法产生艺术,因为到目前为止,所有这些模型都只是研究大量的材料并产生我们要求的结果,试图在他们“知道”的虚拟空间中进行插值,以产生我们最想接收的输出。

也许使用 AI 工具创造艺术是可能的,但这不是微不足道的。在一个我们以不同方式创造的可能性民主化的世界里,做一些有用的事情变得越来越难。如果每个人都是艺术家,没有人是艺术家,尤其是我,正如我们从下面的图片中看到的:

  • 埃贡·费里,只是一只思考人生意义的皮卡丘,2885。意大利罗马美术馆
  • 埃贡·费里,只是一只思考人生意义的皮卡丘,2022。房间里的草图
  • 埃贡·费里和一只思考生命意义的皮卡丘,适马 85 毫米 f/1.4

当我们继续对什么是艺术进行哲学思考和推测时,我们可以使用这些模型来帮助我们用资本主义世界更需要的“艺术”创造价值。

例如,这些图片显示了我们如何使用 Midjourney 制作消费品、网站首页和电影海报的模型(这部电影名为“皮卡丘和城市”):

图片由作者途经中途

结论和未来工作

这个实验让我减少了对 Midjourney 能做什么和不能做什么的疑虑,但却给我留下了大量关于艺术的哲学问题。

我想在未来进一步探索的是不同的和更成熟的模型将如何处理这种类型的任务(我刚刚收到 Dalle 测试版的钥匙,我迫不及待地想玩它)。
我也想探索新的娱乐方式,创造艺术,寻找利用这项新技术让人们工作更轻松的方法。

我也很想听到关于这项工作和未来可能发展的不同想法,所以请随意评论,如果你想看其他实验,请关注我:)。

https://medium.com/@egonferri

探索 Python 内置数据结构的替代方案

原文:https://towardsdatascience.com/exploring-alternatives-to-pythons-built-in-data-structures-e3b20d933c0c

使用强大但被低估的模块来利用数据容器

照片由 pix abay:https://www . pexels . com/photo/blue-white-orange-and-brown-container-van-163726/

Python 的内置数据结构是许多操作的基础。也就是说,利用这些数据结构的用户很快就不得不接受它们的局限性。

幸运的是,Python 提供了collections包,该包提供了替代的数据容器,对于某些任务来说可能更好。该包包含各种数据结构,可以用来替代传统的列表、元组或字典。

在这里,我简要介绍了这个模块中的一些容器数据类型,它们应该在您的编程库中。

1.默认字典

在处理键值对时,字典是首选的数据结构。也就是说,他们有一个警告:访问一个不存在的键将会返回一个 KeyError。

例如,假设您有以下元组列表。

您可以将这些值存储在字典中,如下所示:

这是一种可行的方法,但是预测不存在的键需要包含 if 语句。否则,当你搜索一项不在字典中的运动时,你会得到一个错误。

例如,访问字典中的“Rugby”键会引发一个 KeyError,因为这个键不存在。

默认字典为这一困境提供了一个解决方案。它为尚未创建的键分配一个默认的数据类型。

让我们用默认字典重复前面的任务。

当默认的 dict 对象被创建时,任何没有被创建的键在被访问时将被分配一个空列表。因此,搜索不存在的键不会引发任何错误。

这一次,搜索“Rugby”键将返回一个空列表,而不是一个 KeyError。

由于这个特性,不需要执行初始检查来在字典中搜索键。因此,可以用更少的代码行来执行该操作。

2.命名元组

集合模块的命名元组是 Python 内置元组的变体。就内存效率而言,它是平等的,但由于其独特的功能而脱颖而出,该功能允许用户命名元组的索引。

假设您有一个存储运动员及其各自运动的元组。

如果希望获得元组中的运动项目,可以通过调用索引来访问包含该信息的元素。

代码输出(由作者创建)

有一个完全有效的方法。然而,在读者看来,这一行代码可能很难理解。毕竟,元组中的索引号可以是任意的,所以代码的功能可能很难一眼看出(特别是当您处理大量索引时)。

为了避免妨碍代码的可读性,命名元组可能是更好的选择。

使用命名元组需要创建一个命名元组对象,它包含元组的名称以及每个索引的标签。

之后,您可以用命名的元组定义运动员。

这种方法的好处是用户现在可以通过标签而不是索引号来调用某些元素。下面是如何从命名元组中获取 sport 元素的方法。

代码输出(由作者创建)

这种方法消除了所有的歧义,使读者能够准确地理解提取的是什么信息。

3.计数器

收集模块的计数器是为给定的数据收集导出计数的理想工具。

它将元素及其对应的频率存储为键值对。

假设您有以下运动列表:

手动获取每项运动的计数可以通过字典来完成:

代码输出(由作者创建)

虽然这是一个可以接受的解决方案,但计数器允许用户使用简单的一行程序获得相同的结果。

代码输出(由作者创建)

此外,计数器拥有许多方法,可以方便后续任务。

使用most_common方法可以找到给定数据中 N 个最频繁出现的元素。

代码输出(由作者创建)

人们也可以使用计数器来比较不同的数据集合。在下面的例子中,我们找到了在第一个列表中但不在第二个列表中的元素的计数。

代码输出(由作者创建)

结论

UnsplashPrateek Katyal 拍摄的照片

最终,Python 内置数据结构的替代方案值得考虑。我鼓励尝试这样的工具,因为它们可以为某些用例提供更合适的解决方案。

collections模块中的许多容器数据类型功能强大,但没有得到充分利用。理解和实现它们应该很容易,因为它们是 Python 内置数据结构的变体。

也就是说,这并不是对collections模块效用的全面概括。如果你对这个模块中的其他容器数据类型感兴趣,可以在模块的文档中了解它们。

编码快乐!

探索最佳测试尺寸、折叠次数和重复坚持时间

原文:https://towardsdatascience.com/exploring-best-test-size-number-of-folds-and-repeated-hold-out-bbf773f370b6

研究保证、支持和平均准确性的收益;发现偏见

Elena Mozhvilo 在 Unsplash 上的照片

虽然人们说 10%到 30%是一个好的测试规模,但这是非常依赖于问题的。一个好的起点是我所说的保证精度——精度减去两个标准偏差。使用一个代表性的,但不是微调的虚拟模型,可以模拟许多不同测试规模的随机种子。取你尝试的每个测试尺寸的平均值和标准偏差,然后选择一个最大化保证精度的尺寸。你甚至可以不看实际精度就做。当使用来自 sklearn 的默认 PCA 逻辑回归对来自 UCI 心脏病数据集的处理过的 Cleveland 数据进行此操作时,我发现最佳测试大小为 49%。对于那些内心强大的人,也可以使用支持的精度,即平均值减去一个标准差。这给出了 38%。

出现的下一个问题是交叉验证(cv)使用多少折叠。为了简单起见,让我们讨论一下交叉验证,以优化最终的准确性。毕竟,超参数的影响可能是特定于模型的,而精度是一个更通用的度量。

同样的保证准确性的想法也可以用于计算使用多少折叠——但它需要更多的步骤。首先,我们将不得不放弃 k-fold 交叉验证的想法,并与反复坚持合作。原因是从统计学上来说,构建 J 个相同采样的随机模型比 k 倍交叉验证更容易建模。仍然有两种情况,其中 k-fold 交叉验证很容易理解,我们基本上可以从精心选择的图中读取我们需要的所有信息——但要达到这一点,我们首先必须理解重复坚持。

当您使用相同的数据构建多个模型并对其中一些数据进行测试时,相关性就会成为一个问题,因此模型的单个精度的标准偏差不再等于总精度的误差。事实上,修正可以超过 4 倍!看看下面代码中的实现,或者你可以查看我的博客文章中的细节。

B ut,当该说的都说了,该做的都做了,你又得到一个保证精度的图,它是模型数量 J 和测试规模的函数。对每个 J 的后者进行最大化,我们获得了 UCI 心脏病数据集的如下图(参见文章末尾的 Github 链接):

与仅运行一个模型相比,重复维持的最佳测试规模是模型数量的函数,并具有预期的精度增益。虽然当测试规模改变时,平均精度不连续地改变,但是保证/支持的精度是连续的。图片作者。

以下是保证和支持精度的定义:

means_2000、stds_2000 和 test_size _ 2000 是使用 test _ size _ 2000 中指定的 test _ size 对 train_test_split 的 2000 个随机种子进行默认逻辑回归的平均值和标准偏差列表。

Nadeau 和 Bengio (NB)在 2003 年使用简化假设(我们只需对 J < 5 做一个小的改变)发现了重复坚持的 J 模型的方差与总精度的方差之间的这种关系。我们发现他们的假设被违反了,但仍然很有意义。

N ow,回 k 倍互相关。我们不知道这里的保证精度,除了一个简单的情况:2 倍 cv。2-fold cv 在其训练集或测试集之间没有相关性,因此模型精度的标准偏差与总精度的标准偏差相同。事实证明,2 倍 cv 的保证精度比最优(测试规模选定)2 倍重复保持高 0.2%。在 2 倍 cv 之后,我们能做的最好的事情是绘制不同选择策略的平均准确度:

该图显示了四种不同选择类型的平均准确度。对于 k 倍 cv,我们平均 10*(测试集大小)个随机种子,而对于保留,我们使用上面的关系找到最佳测试大小。图片作者。

比较绿色和蓝色曲线,我们可以看到,对于 2 倍,重复保持更好,因为它的测试规模更小(见上图),在中间区域,分层 k 倍 cv 略好,因为它可以承受更大的训练集。对于超过 50 个模型/折叠,重复保持也是更好的,因为它能够保持更大的测试规模:事实上,我们确实预计一些测试集偏差会出现在 300 个折叠中——留一个 cv (LOOCV)。原因是它是 N=300 次单次观察的简单平均值。因此,我们预计模型的真实精确度会有一个平均值误差,在这种情况下是 2.1%,比观察到的误差大四倍。因此,我们可以说,k-fold 交叉验证在大量折叠的测试集中易受偏倚的影响,而重复排除能够用任意数量的模型将测试规模保持在 5%,因此受偏倚的影响较小。这种偏差预计会随着测试规模的增加而迅速减少,因为随着测试规模的增加,可能的模型数量以及测试数据点的数量都会增加。事实上,它一直持续到 6 个测试数据点——或 50 倍——是强相关性的一个指标。现在让我们转向反复的坚持,这一切将变得更加清楚:

重复保持的平均准确度,最佳拟合线显示了低测试规模的偏差和方差。插图显示了预测的 NB 误差。对于小于 5%的测试规模,我们尝试使用 20,000 个模型而不是 2,000 个模型(绿色),只对图形进行了微小的更改。图片作者。

该图显示了重复保持的平均准确度。好的一面是,我们可以清楚地看到偏差是最佳拟合线的残余。在 LOOCV 和 LTOCV(留二法 CV)中存在偏差,我们看到它持续到大约 10%的测试规模。在偏倚之上,我们看到方差从 1%的测试规模(三个测试点)开始出现,直到大约 10%的测试规模(30 个测试点),在与偏倚相同的点消失。当你建立更多的模型时,这些振荡似乎不会以明显的速率衰减,如绿色所示。NB 算法不包括这些特征,所以我们使用滚动窗口并排除测试大小< 5%。我们还看到,LOOCV 在 10%的测试规模上没有产生任何改进,这与之前的分析很好地吻合,该分析发现 10 次折叠已经产生了最佳结果。然而,我们确实看到了一个小的改进,测试规模约为 5%,这是我们在前面的图中利用的。

如果您想知道,当所有点都在线时,NB 误差为 2%的原因是这是预期的训练集偏差,因此它不会在模型中显示为方差。它量化了我们在所有数据中异常幸运或不幸的机会。除此之外,我们还试图用许多随机种子来估计任何一个模型的较少训练数据的影响。当你对更少的模型取平均值时,线周围的方差确实增加了很多。

L 看第二个图,我们看到重复的保持(绿色)是 k 倍 cv(蓝色)在 3 到 35 倍之间的良好指标(下限)。因此,从第一幅图可以看出,如果我们想要保持在最佳保证精度增益(3.34%)的 1%以内,我们需要 20 倍。如果我们希望保持在 0.5%以内,我们需要使用测试规模为 5%和 70 个模型的重复坚持。对于支持的精度,我们希望使用 6 到 16 倍之间的 k 倍 cv,因此如果我们希望保持在最佳可能精度增益的 1%以内(2.39%),我们需要使用 9 倍,如果我们希望保持在 0.5%以内,我们需要使用测试大小为 5%和 31 个模型的重复保持。

推广到其他数据集,我们展示了如何使用重复保持作为代理来研究通过增加折叠次数可实现的准确性增益,以及在哪个点切换到重复保持以及为什么。LOOCV 的测试集偏差可以通过寻找其平均值的误差来估计。这将是真实偏差的一个数量级估计(在这种情况下,相差 75%)。

这里是我的 Github 上的代码的链接。

【1】:Dua,d .和 Graff,C. (2019) http://archive.ics.uci.edu/mlUCI 机器学习知识库。加州欧文:加州大学信息与计算机科学学院。

探索 DALL-E 的数字艺术创作

原文:https://towardsdatascience.com/exploring-dall-e-for-digital-art-creation-b244e1a2ed12

我测试了 OpenAI 的文本到图像生成器,看看它如何使用各种主题和风格创建图像

来自 DALL-E 的示例渲染图,图片由作者提供

我非常兴奋地收到了 OpenAI 的 DALL-E [1]文本到图像生成测试程序的邀请。自从注册以来,我已经从我早期的人工智能项目中创建了超过 200 张带有各种文本提示的图像。从样本图像中可以看出,DALL-E 生成的图像质量和分辨率都非常出色。

我将从 DALL-E 的一些背景信息开始,然后展示与我早期实验相比的结果。你可以通过检查渲染图右下角的小水印来判断哪些图像是由 DALL-E 创建的。(请注意,它由柔和的黄色、青色、绿色、红色和蓝色组成。我想洋红没被选上。)

DALL-E 水印,图片作者

达尔-埃

OpenAI 于 2021 年 1 月发布了其首个 DALL-E 语音转文本系统版本[2]。报纸上的图像看起来很棒,即使是 256x256 的分辨率,但它不对公众开放。2022 年 4 月,他们发布了 DALL-E 2,可以渲染 1024x1024 分辨率的图像。他们通过测试程序打开了系统的入口。更多信息请点击这里,你可以点击加入测试程序的等候名单。

使用 DALL-E

该系统有三个创建图像的主要功能:

  1. 通过文本提示创建图像
  2. 创建图像的变体
  3. 编辑图像,根据提示生成新零件

请注意,函数 2 和 3 适用于生成或上传的图像。

快速演练

我将首先前往labs.openai.com并登录。接下来,我将输入提示,“一幅印象派油画,向日葵在青色房间的洋红色花瓶中。”大约 20 秒后,我们看到了这个。

DALL-E 图片创作,作者图片

好的,这些看起来不错。我喜欢左边的那个。点击图像放大并显示更多选项。

DALL-E 图片精选,作者图片

让我们来看看一些变化。我将单击“Variations”按钮,看看我们会得到什么。

DALL-E 图片变化,作者图片

不错!我喜欢右边的那个。让我们看看是否可以用编辑特性改变桌子上的阴影。点击图像,然后点击编辑,弹出此窗口。

DALL-E 图片编辑,图片作者

我可以用橡皮擦擦掉图像的任何部分,比如桌子上的阴影。我可以用右边的小工具调整橡皮擦的大小。接下来,我将再次输入提示并点击 Generate 按钮。这是结果。

好的,右边的画好像阴影最好。我会选择那个并下载一个全分辨率版本。

DALL-E 渲染图“一幅印象派油画,画的是青色房间里的洋红色花瓶里的向日葵”,作者提供的图片

太棒了。适合印刷和装裱。

费用

当你第一次创建一个账户时,OpenAI 会给你 50 个“信用点”作为开始。每次点击“生成”或“变化”按钮时都会使用一个积分。他们每月会给你额外的 15 个免费学分。

您可以以 15 美元加税的价格购买 115 个信用点。这大约是 13 或 14 美分,取决于你所在州的销售税。

请注意,当从提示符创建新图像时,您会得到四个图像,使用变体和编辑功能会得到三个图像,并且您可以保留您创建的所有图像。所以每张图片大约花费 4 美分。

DALL-E 的商业用途

与 OpenAI 的 DALL-E 测试程序刚开始时不同,现在你可以创建图像并将其用于商业目的。

…用户获得完全使用权,将他们用 DALL E 创建的图像商业化,包括重印、销售和商品的权利。这包括他们在研究预览中生成的图像。

用户告诉我们,他们计划将 DALL E images 用于商业项目,如儿童书籍的插图、时事通讯的艺术、游戏的概念艺术和角色、设计咨询的 moodboards 以及电影的故事板。— OpenAI

但是请注意,OpenAI 的使用条款页面上说,使用 DALL-E 必须遵守其内容政策中规定的条款,这将在下一节讨论。

使用限制

根据 OpenAI 的内容政策,使用 DALL-E 时,您同意以下规则:

  • 只创建不会对任何人造成伤害的 G 级图像。他们列出了一堆被禁止的不良内容,比如仇恨言论、暴力图像、色情等。
  • 你必须清楚地表明,图像是人工智能生成的,并给予归因于 OpenAI。
  • 尊重他人权利——不要上传或创建公众人物形象;只上传你自己的图片,等等。

这些似乎是好的、常识性的规则,旨在遏制系统的潜在滥用。

社会影响

像其他根据大量公共数据训练的人工智能模型一样,DALL-E 具有内在的社会偏见。作者在他们系统的模型卡[3]中使用官方模型名称 DALL E 2 解决了这些问题。

DALL E 2 的使用有可能通过强化刻板印象、消除或诋毁刻板印象、为他们提供低质量的表演或使他们受到侮辱来伤害个人和群体。这些行为反映了 DALL E 2 训练数据中存在的偏差以及模型的训练方式。虽然偏见的深层背景性质使得难以衡量和减轻使用 DALL E 2 预览版(即超出生成点)所造成的实际下游损害,但我们的目的是在此提供具体的说明,即使在这个非常初始的预览阶段,也可以通知用户和受影响的非用户。-帕米拉·米什金等人,来自 OpenAI

他们展示了系统中存在偏见的例子,比如“建筑工人”如何生成戴着安全帽的老年白人男性的图像,或者“空姐”如何生成穿着航空制服的亚洲女性的图像。他们讨论模型的其他社会问题,并通过政策和报告进行缓解。是的,UI 中有一个“报告”按钮。

DALL-E 报告图片对话框,作者图片

试验结果

这里是使用 DALL-E 的结果,将它们与我在 Medium 上写的其他人工智能实验进行比较。

抽象画

第一个测试将 DALL-E 的结果与我的 MachineRay 项目的输出进行比较。MachineRay 是训练 StyleGAN 2 [3]在公共领域使用来自 WikiArt.org的抽象画的结果。没有文字提示。这个系统制作了一批新的抽象画。

来自 MachineRay 的抽象画(上),来自 DALL-E (下)的变化,图片由作者提供

最上面一行显示了 MachineRay 的三幅抽象画,最下面一行显示了 DALL-E 生成的绘画的变体。看到每个系统如何有效地拥有自己的“风格”很有趣相比之下,MachineRay 的输出对笔画具有更粗糙的纹理,而 DALL-E 的结果看起来更像是经过了喷枪处理。

以下三幅画是由提示“抽象艺术绘画”生成的

DALL-E“抽象艺术绘画”效果图,作者提供的图片

嗯。这些看起来像更大的飞溅画的细节。我发现 DALL-E 在提示中需要更多的指导来创作更好的画。您将在下面的部分中看到这一点。

现代艺术

第二个测试将 DALL-E 与我的 MAGnet 项目进行了比较,该项目使用图像来嵌入来自 OpenAI、SWAGAN [6]的系统剪辑[4],以及一个定制的遗传算法来根据文本提示创建现代绘画。这是结果。

磁铁效果图《起伏的农田》、《立体派绘画》(上)和 DALL-E 变奏(下),图片由作者提供

最上面一行显示了来自 MAGNet 的提示“起伏的农田”、“一幅带圆圈的抽象画”和“一幅立体画”的输出。底部一行显示了基于磁体渲染的 DALL-E 的变化。请注意,当您使用 DALL-E 创建变体时,它不使用原始文本提示。系统使用剪辑解释输入图像的含义,然后使用他们的新“解开”模型[1]从剪辑嵌入中生成变化。这类似于第一个艺术家用文字描述一幅画,而第二个艺术家在不看原始图像的情况下用文字创作一幅新画。这是一个有趣的效果。例如,我喜欢 DALL-E 如何在立体派绘画中选择一张脸。

下面是 DALL-E 根据原始文本提示创建的内容。

DALL-E 渲染图“一幅起伏的农田”、“一幅画着圆圈的抽象画”、“一幅 1920 年的立体画”,作者提供的图片

我知道艺术欣赏是主观的,但比起第一组图像,我更喜欢这些再现。

各种风格

下一个测试将 DALL-E 的输出与我的 GANshare 项目的输出进行比较。GANshare 使用了 CLIP 和一个 VQGAN [7]模型,这是我在 WikiArt 上对公共领域图像进行的训练。让我们看看结果。

GANshare 渲染的“音速银棕色的对角线几何绘画”、“卡罗莱纳蓝色的棱镜印象派绘画”、“T11”和“鲜艳的勃艮第棕色的未来主义城市绘画”(上)和 DALL-E 变体(下),图片由作者提供

最上面一行展示了甘沙尔的“音速银棕色对角线几何绘画”、“卡罗莱纳蓝色棱镜印象派绘画”和“鲜艳的勃艮第棕色城市未来主义绘画”的效果图。最下面一行显示了 DALL-E 的变体,看起来 DALL-E 不知何故放大了 GANshare 的表单。此外,我们从 DALL-E 中看到更多的喷枪外观。

下面是使用 DALL-E 的这些提示的新图像。

DALL-E 渲染图“带有音速银棕色对角线的几何绘画”,“带有卡罗莱纳蓝色棱镜的餐厅印象派绘画”,“鲜艳的勃艮第棕色城市未来主义绘画”,作者提供的图片

首先,请注意我是如何调整第二幅图像的提示的。我添加了“餐厅”部分,使图像类似于来自 GANshare 和 DALL-E 变体的图像。DALL-E 在直接渲染图像时,似乎可以更自由地表达提示的意图。例如,请注意几何绘画更直接的设计。请注意“棱镜”这个词是如何在顶灯中产生比喻形式的,而不是像 VQGAN 那样的图像配色方案。我可能需要在提示中添加“彩虹色”来获得 DALL-E 的效果。

画像

下一步是使用 DALL-E 创建人物肖像。虽然 OpenAI 的内容政策明确表示,你不能使用他们的系统来“创建公众人物的图像”,但创建虚构人物的绘画似乎是允许的。

在我的 GANfolk 项目中,我训练了两个人工智能模型 StyleGAN 2 和 VQGAN 来创建人的画像,这两个模型都是由 CLIP 驱动,根据文本提示创建画像。以下是 DALL-E 与 GANfolk 的对比结果。

GANfolk 渲染“一个深思熟虑的巴西女孩的画像”,“一个专注的葡萄牙男人的画像”,“一个担忧的朝鲜女人的画像”(上),和 DALL-E 变奏曲(下),图片由作者提供

最上面一行显示了 GANfolk 如何根据提示渲染肖像,“画一个深思熟虑的巴西女孩”,“画一个专注的葡萄牙男人”,以及“画一个关切的韩国女人。”最下面一行显示的是 DALL-E 绘制的肖像,是 GANfolk 图像的变体。总的来说,来自 DALL-E 的图像看起来非常好。比如前两张人像的底纹就很优秀。

以下是 DALL-E 生成的新肖像,略有扭曲;我在三个提示中添加了一个短语。

DALL-E 渲染图“1920 年一名年轻巴西女孩的棕褐色写实炭笔素描”,“1920 年一名专注的葡萄牙男子在蓝色背景前穿着黑色 t 恤的写实油画”,以及“1920 年一名忧心忡忡的朝鲜妇女面向前方的绿色背景的写实油画”,作者图片

DALL-E 为这些提示创作的原始肖像看起来非常现代,如下图所示。为了匹配来自甘沙尔的肖像的总体外观,我在 19 世纪和 20 世纪初的公共领域绘画上进行了培训,我在提示中添加了短语“来自 1920 年”。这给了 DALL-E 的肖像一个古老的外观,似乎更符合 GANshare 生成的肖像。

DALL-E 渲染图“一个年轻的巴西女孩在棕褐色调中的写实炭笔素描”,“一个专注的葡萄牙男子在蓝色背景前穿着黑色 t 恤的写实油画”,以及“一个忧心忡忡的朝鲜妇女在绿色背景下面向前方的写实油画,”作者提供的图片

我有点喜欢 DALL-E 的两组肖像。接下来是风景画。

风景

为了我的风景画项目,我用来自 WikiArt.org 的 5000 幅风景画训练了 StyleGAN 2 ADA。系统使用 CLIP 从文本提示中生成图像。这里是由 GANscapes 和 DALL-E 生成的绘画结果。

GANscapes 效果图,“印象派画湖边的房子”,“印象派画新英格兰的树叶”,印象派画夏天的海湾】(上),由 DALL-E (下)改编,图片由作者提供

你可以看到 DALL-E 是如何从 GANscapes 的渲染图中提取主要的视觉成分,并将它们融入到美观的构图中。你可以在这三幅图像中看到一种连贯的绘画风格。

我们直接看看 DALL-E 用提示生成了什么。

首先蹦出来的是饱和色。我猜 DALL-E 得到了印象主义者使用鲜艳颜料的备忘录。这组风景看起来比上面的细节少,但总体来说,构图很可爱。

变化的纵横比

您可能已经注意到,本文中的所有图像都是死方块。许多图像生成模型使用 1:1 的纵横比,包括 DALL-E。

我最近的项目,Expand-DALL-E,或 E-DALL-E,通过生成新的图像来改变图片的纵横比。它使用一种称为 Craiyon(以前的 DALL-E Mini)的开源文本到图像模型和 VQGAN 来“修复”图像的侧面,以改变纵横比。

以下示例显示了如何将 Craiyon 生成的 1:1 图像扩展为 16:9 的宽高比。

Craiyon 渲染的《一幅起伏的农田图》、《一幅带有橙色三角形的抽象画》、《T13》、《T14》、《一碗水果的静物画》、《T15》(上图)、《T16》、E-DALL-E 扩展到 16:9 (中图)和 DALL-E 扩展到 16:9 (下图),图片作者

最上面一行显示了 Craiyon 根据提示“一幅起伏的农田的画”、“一幅带有橙色三角形的抽象画”和“一碗水果的静物画”创建的图像。中间一行显示了 E-DALL-E 如何将图像扩展到 16:9,在侧面填充细节。最下面一行显示了 DALL-E 如何执行相同的功能。虽然 DALL-E 似乎在资料片上做得更好,但 E-DALL-E 似乎更有创意,为资料片增加了新的形式。可以使用更明确的提示来诱使 DALL-E 添加额外的表单。

作为最后的测试,这里有一个 DALL-E 渲染图,来自图像扩展前后的提示“一幅起伏的农田的画”。

DALL-E 渲染图“一幅起伏的农田”,作者拍摄的图像

DALL-E 扩展至 16:6,图片由作者提供

以下是使用 DALL-E 创建非方形纵横比的图像所需的步骤。

  1. 将您的图像导入照片编辑系统,如 Photoshop。
  2. 将画布扩展到新的大小,将原始图像保持在中心。
  3. 将展开的图像上传到 DALL-E,并编辑图像。
  4. 向左裁剪图像,擦除空白部分,然后单击“生成”。
  5. 保存您最喜欢的修复版本。
  6. 对右侧重复步骤 4 和 5。
  7. 将两半部分放入 Photoshop 中,合并在一起。

如果你需要帮助,请在评论中告诉我。我可以在 YouTube 上制作一个演示视频,或者更好的是,用 Python 程序来拆分和合并图像。

讨论

DALL-E 系统令人印象深刻。几乎在每一项测试中,它都优于以前的型号。OpenAI 的团队意识到了该系统的局限性,并正在监控其使用是否可能被滥用。我对进一步探索该系统感到兴奋,比如为迷因、故事或电影故事板的文本添加图像。像这样!

感谢

我要感谢詹尼弗·林对这篇文章的帮助。

参考

[1]A. Ramesh 等人, DALL-E 2 带剪辑潜伏时间的分层文本条件图像生成 (2022)

[2]a . Ramesh 等人的 DALL-E零镜头文本到图像生成 (2021)

[3] P .米什金等著, DALL E 2 预览 —风险与限制 (2022)

[4] StyleGAN 2 ,T. Karras 等人,StyleGAN 图像质量分析与改进 (2020)

[5] 剪辑由 a .拉德福德等,从自然语言监督中学习可转移视觉模型 (2021)

[6] R. Gal 等人, SWAGAN :一种基于风格的小波驱动生成模型 (2021)

[7]p . Esser、R. Rombach 和 B. Ommer 的 VQGAN驯服变压器用于高分辨率图像合成 (2020)

[8] StyleGAN2 ADA ,T. Karras 等人用有限数据训练生成对抗网络 (2020)

[9] B. Dayma 和 P. Cuenca, DALL E mini —从任何文本提示生成图像 (2021)

为了无限制地访问 Medium 上的所有文章,成为的会员,每月 5 美元。非会员每月只能看三个锁定的故事。

探索图细胞自动机

原文:https://towardsdatascience.com/exploring-graph-cellular-automata-c9d22b4abe42

我们如何找到产生特定全球行为的本地规则

1)元胞自动机基础

介绍细胞自动机的最好方法是通过例子。图 1 显示了一个简单细胞自动机的典型例子。它被称为规则 110,因为它的规则集可以由二进制序列 01101110 (1 表示任何黑色更新单元)指定。规则 110 从第一行单元格开始,其中包含一个黑色单元格。随后的每一行都是一个时间步长,通过将规则应用于每个像元并根据其当前状态及其相邻像元的状态更新其状态来获得。例如,图 1 中最左边的规则将一个黑色单元格更新为白色,如果它的两个邻居都是黑色的。

图 1:规则 110,初始状态为单个黑色单元,分别运行 10、100、250、1000 和 10000 个时间步长。使用 Mathematica 13 [10]生成。

从图 1 中可以明显看出,出现了一些重要的模式;尽管它的初始状态和规则都很简单,但规则 110 表现出复杂的全局行为[8]。

然而,并不是所有这样的细胞自动机都有类似的复杂度。以下是规则 111。除了一个更新规则:三个白色单元产生一个黑色单元而不是一个白色单元之外,它在每个方面都与规则 110 相同。然而,它表现出明显规则的水平线模式;比 110 号规则中随机散布的三角形要无趣得多。这种非常不直观的复杂性差异是由于转换函数的微小变化而产生的。

图 2:规则 111,初始状态为单个黑色单元,分别运行 10、100、250、1000 和 10000 个时间步长。使用 Mathematica 13 [10]生成。

为什么你会想读这个

我们已经迈出了创造能够自我修复的数字系统的第一步。对于人工智能领域的人们来说,这是重要的一步,因为它开辟了一个我们以前无法实现的可编程行为的前沿。现在让我们解释一下我们是如何做到这一点的。

首先,我们形式化经典的细胞自动机,如规则 110,将其概括为图细胞自动机。我们将使用这种形式来应用图形神经网络;这使我们能够学习产生图形细胞自动机的期望状态的转移函数。顺便说一下,这使我们能够创建一个自我修复的兔子图。

这篇文章大致沿用了“学习图细胞自动机”一文,但是对读者的知识做了更少的假设[1]。

2)图细胞自动机

2.1)细胞自动机形式主义

细胞自动机的各种实例之间有很强的相似性。每一种都使用某种结构来表示状态,并对其应用简单的规则,从这些规则的重复应用中,产生了复杂的行为。然而,这种相似性不仅仅是描述而已;它可以被形式化为一个通用的数学框架。使用这个框架,诸如图细胞自动机的新型细胞自动机可以直接描述为熟悉的规则 110 的扩展。这个框架如下。

元胞自动机是一个 4 元组: (D,,N,τ) [1],其中:

细胞自动机的组成部分。这个数学看起来可能有点吓人,但它指向了一个明确的图景;示例见表 1。

转移函数 τ 决定了元胞自动机的具体实例化,如规则 110 或规则 111,定义域 D、状态集σ、邻域函数 N 决定了元胞自动机的各类别,如表 1 所示。表 1 还显示了图形细胞自动机是经典和网格细胞自动机的推广;当细胞被表示为节点时,相邻细胞在空间上邻近的限制被放松,结果是一个图形细胞自动机。

表 1。经典(如规则 110)、网格(如康威的生命游戏)和图形细胞自动机的比较。

过渡规则

正是转移函数 τ 负责细胞自动机中的复杂行为(我们在这里互换使用“转移规则”和“转移函数”)。改变规则 110 中的一个比特,它已经被证明像图灵机[7]一样复杂,产生规则 111,它表现出重复的行为。因此,演化图中全局行为的任务本质上是寻找一个有趣的转移函数 τ

转移函数 τ 聚集每个单元及其邻居的状态,以产生更新的状态。要在各向异性行为中烘焙(即不同的邻居权重不同),过渡函数也必须作用于边权重。形式上, τ 变成了

转换规则的形式定义 τ。

当研究细胞自动机时,我们通常只对引起复杂行为的转移函数感兴趣。因此,在运行细胞自动机之前,能够提前知道转移函数产生的行为将是有用的。然而,这种能力并不总是可能的。

Steven Wolfram 在观察简单的细胞自动机(如规则 110 和规则 111)时构思了他的计算等价原理[9]。根据这一理论,自然界中任何表现出一定复杂性的系统“都可以执行最高(‘通用’)计算能力水平的计算”[7]。换句话说,为了在时间步长 t 预测状态规则 110,必须使用至少 t 步计算;复杂的系统没有捷径或捷径,即使像规则 110 一样简单。

3)图形神经网络

3.1)近似转换函数

计算等价的原则规定我们不能立即说出一个转换函数产生的行为;我们不能跳过细胞自动机的计算。但是尽管如此,反向映射是容易处理的:给定一个期望的行为,就有可能学习一个导致它的转换函数。我们使用深度学习的方法来做到这一点。

我们使用深度学习来近似一些域(例如,细胞自动机的初始状态)和一些共域(例如,细胞自动机在某个时间步长 t 的状态)之间的任意映射。这是可能的,因为神经网络——本质上是具有可学习参数的仿射变换和非线性变换的交错组合——可以通过将参数调整到某种配置来任意接近任何函数[1]。为了寻找这样的参数配置,我们使用一种称为梯度下降的贪婪优化算法。

因此,我们使用神经网络来学习细胞自动机从初始状态到期望行为的映射。然而,这样做,我们将不会明确地学习映射,而是学习转换函数 τ 。为了计算期望的行为,我们将重复地将 τ 的近似应用于细胞自动机的初始状态。

为了这个探索,我们将近似图细胞自动机的 τ 。由于域 D 是图,因此我们使用图神经网络。图形神经网络构成了将图形映射到实值矩阵的函数类,

GNN 定义,其中 G 是一个图, n 是顶点的个数,d 是每个顶点嵌入使得 d<n .的维数

3.2)消息传递

图 3:在消息传递中,每个顶点的状态通过在每次迭代中聚集它和它的邻居的状态来更新。蓝色顶点延伸到它的邻居,它的黑色顶点,并且它的状态基于它们的每个状态被更新。

最初,每个顶点 i 被分配一个任意初始化的维数为 d 的向量,这些向量被收集到一个实值的 shape (n,d)矩阵中。h 由消息传递管道更新,如下所示。

消息传递,GNNs 的主干。

消息传递管道包括三个步骤:

消息传递管道的说明。

通过迭代地应用这个本地消息传递管道,图的全局信息传播到顶点:由于每一步看到所有顶点从它们的邻居接收信息,如果消息传递被应用 t 次迭代,所有顶点从距离它们至多 t 的那些顶点接收信息。因此,消息传递是一种局部作用的功能,它根据相邻顶点的状态更新顶点的状态,在重复应用时,它会产生全局行为。这样,消息传递类似于局部转移函数 τ ,它在元胞自动机中演化出复杂的全局模式。事实上,我们将把转移函数(忽略边权重)近似为一个消息传递神经网络,并且我们将通过优化这个神经网络来学习某些任务的 τ

4)实验

4.1)任务

我们的目标是学习一个转移函数,它将一个图形细胞自动机演化到一个特定的最终状态。让我们用一种形式主义来解决这个问题,因为这将使优化问题变得简单明了。

我们任务的定义。

在这里,我们将使用 3.2 节中为τ_θ定义的图形神经网络。对于 G ,我们将使用斯坦福几何兔子,这是一个从兔子的点云构建的图形,将每个点视为一个顶点,并将每个点连接到 3D 空间中其附近的顶点[1]。状态向量(s_i-bar)因此对点云中每个顶点的坐标进行编码,τ_θ将向 3D 空间中的兔子演化出任意结构的图形。

4.2)培训

我们现在将优化参数τ_θ,使 L2 损耗最小:

损失函数最小化。

在(4)中,最终时间步长 t 和小批(即顶点的划分)k=1,…,k。

方程(4)的解释,我们任务的 GNN 的损失函数。

现在 p^(i)p ,因为它在时间步长 i 被应用于每个小批 k 和每个时期(即,我们已经看到小批 k 的次数)。这个过程被称为时间反向传播。利用它,我们可以学习我们的神经网络τ_θ的参数配置,使得它近似目标转换规则的映射:

目标转换规则将初始状态映射到最终状态。我们将用 GNN 来近似这种映射。

人们发现还有一些技巧可以帮助训练。一种是从不同初始状态池中提取,而不是从单个初始状态 S-bar 中优化,替换每个样本。这有助于在图形细胞自动机中创建持久结构,因为模型将学习将各种状态映射到目标状态。然而,也许最重要的是,我们可以调整最终的时间步长 t。我们将从不同的以秒为单位的 t 定义中看到有趣的结果。4.3.[1, 5]

4.3)结果

图 4:针对几个最大时间步长 t训练的模型的结果;t=10(第一行),t*=20(第二行),10 ≤ t ≤ 20 在训练期间为每个步骤随机选择(第三行)。误差由 L2 损耗测量:K=1 时的等式(4)。改编自[2],Grattarola 等人的增补。

该模型针对不同的时间步长 t 进行训练,其固定初始状态的输出如图 4 所示。

对图 4 的讨论。

因此,在 t=20 时,当用作图形细胞自动机中的转移规则时,每个模型成功地产生兔子,但是只有其结果显示在第三行中的模型产生持续的兔子。

然而,这个实验的重要意义不在于我们可以创建一个兔子形状的图表。它的意义在于,这只兔子能够自我组织,自我修复。这些是协调的全局行为,但它们不是自上而下设计的结果,而是局部作用函数的迭代应用,这是自然界复杂系统共有的自下而上机制。

我们从基本的细胞自动机开始探索,惊叹于简单的更新规则应用于简单的初始状态所产生的复杂性。但是由于计算的不可约性,这种细胞自动机可能产生的复杂性是无法预测的。然而,我们通过用图形神经网络代替简单的更新规则,在图形细胞自动机中强制特定的全局行为。因此,我们已经表明,这些图形神经细胞自动机是一种工具,工程基本的自组织系统。

引文

[1] Grattarola、Daniele、Lorenzo Livi 和 Cesare Alippi。"学习图形细胞自动机."神经信息处理系统进展 34 (2021)。

[2] Grattarola、Daniele、Lorenzo Livi 和 Cesare Alippi。"学习图形细胞自动机,补充材料."神经信息处理系统进展 34 (2021)。

[3]汉密尔顿,林子幸《图形表征学习》人工智能和机器学习综合讲座 14.3 (2020)。

[4]霍华德、杰里米和西尔万·古格。利用 fastai 和 PyTorch 为编码人员提供深度学习。奥莱利媒体,2020。

[5] Mordvintsev,Alexander 等,“生长神经细胞自动机”蒸馏 5.2 (2020): e23。

[6] Perraudin,Nathanaë等人,“GSPBOX:图形信号处理工具箱”arXiv 预印本 arXiv:1408.5781 (2014)。

[7]埃里克·w·魏斯泰因,《计算的不可约性》mathworld.wolfram.com/(2002 年)。

[8]埃里克·魏斯泰因,《第 110 条规则》mathworld.wolfram.com/(2002 年)。

[9]沃尔夫拉姆,斯蒂芬。一种新的科学。第五卷。香槟:沃尔夫拉姆媒体,2002 年。

[10] Wolfram Research,Inc .,Mathematica,版本 13.0,伊利诺伊州香槟市(2021 年)。

探索拥抱脸数据集

原文:https://towardsdatascience.com/exploring-hugging-face-datasets-ac5d68d43d0e

为您的下一个 NLP 项目访问大型现成数据集

图片来自亚历山大·德比弗Unsplash

任何机器学习项目最重要的部分就是你正在处理的数据。不管你处理的是什么算法或模型,真正的准确性来自数据的数量和质量

我喜欢在空闲时间从事 NLP 项目,但有时很难访问大型数据集。收集、积累这些数据,然后以适当的方式清理这些数据可能会花费大量时间。对 NLP 爱好者来说幸运的是, HuggingFace 配备了一个随时可用的数据集中心。在本文中,我们将快速探索如何使用这个数据集模块为您的项目挑选和准备合适的数据集。

装置

这一步非常简单,我们将使用两个开源库。

数据集方法

浏览数据集存储库的文档,我们看到有几个主要的方法。第一种方法是我们可以用来探索可用数据集列表的方法。近 3500 个可用数据集应该作为选项出现,供您使用。

列出所有数据集

现在,为了实际使用数据集,我们希望利用 load_dataset 方法。

加载数据集

如果您加载这个数据集,您现在应该有一个数据集对象

使用数据集对象

我们使用的不是传统的 csv 或 excel 格式,而是一个数据集对象,它以某种结构存储数据集的元数据。我们可以在打印数据集时观察到这一点。

数据集(作者截图)

我们加载的数据集被分成三个后续数据集,您可以使用。features 和 num_rows 键说明了列及其观测值的数量。

查询和处理 Dataset 对象在语法上与处理 Pandas 数据框架非常相似。这里有一些方法可以用来获得更多关于你的对象的信息。

选择一行

从数据集对象中选择行

选中的行(作者截图)

特征抽出

数据集功能

特色(作者截图)

数据集描述

如果你需要更多关于数据集的来源或如何创建的信息,你可以获得背景信息和引用。

数据集的描述

作者截图

数据集引用

作者截图

自定义数据集加载

在某些情况下,您可能不想处理其中一个 HuggingFace 数据集。您仍然可以将本地 CSV 文件和其他文件类型加载到这个数据集对象中。比方说,您有一个想要处理的 CSV 文件,您可以简单地将它传递给 load_dataset 方法,并附上您的本地文件路径。

加载一个 CSV 文件

这同样适用于处理多个 CSV 文件的情况。

加载多个 CSV 文件

当你想用 HuggingFace 提供的一个预先训练好的模型来微调你自己的数据集时,这个功能尤其有用。

其他资源和结论

我希望这篇文章对拥抱脸提供的大量资源是一个很好的介绍。拥抱脸使得端到端地处理大型 NLP 和 ML 工作负载变得容易。我附加了一些对本文有帮助的资源。

数据集文档

微调预训练模型

数据集 Github

如果你喜欢这篇文章,请在LinkedIn上与我联系,并订阅我的媒体 简讯 。如果你是新手,使用我的 会员推荐 报名。

利用无监督主题建模探索大型文档集—第 1/4 部分

原文:https://towardsdatascience.com/exploring-large-collections-of-documents-with-unsupervised-topic-modelling-part-1-4-404f4931dab7

借助话题模块性解读提取的话题

图片作者。

在这一系列的文章中,我们将重点探索基于主题建模的大量未标记文档。我们假设除了语料库的上下文之外,我们对语料库的内容一无所知。我们的目标是用一些新的、量化的知识来完成对语料库中所讨论内容的探索。

这是 4 部分系列的第一部分。让我们开始吧。

介绍

主题建模 101

在整个系列中,主题建模是我们分析的基础。对于给定的语料库,主题模型估计其每个文档的主题分布(即,一组主题上的权重分布),其中主题本身是语料库的词汇上的权重分布。在给定文档集合的情况下,每个主题的权重最大的单词在句法和/或语义上是相关的。这意味着两个不同的主题共享完全相同的词汇,但具有不同的权重分布。

左边是一个大集合中给定文档的主题分布示例,考虑了 10 个主题(范围从 0 到 9)。右边是主题 5 在语料库词汇中的权重分布的提示性描述。图片作者。

问题是

从上图可以看出,尽管主题建模的想法听起来很吸引人,但通常很难对这种模型的结果做出一致的解释——记住,我们对语料库的内容一无所知!

这一系列的文章将呈现实验性的设置设计,引导我们走向理性的解释,并以他们的结果为依据。

拟议解决方案

在第一部分中,我们将利用两个工具在解释主题模型的结果方面向前迈进了一步:(1)主题解释,和(2)主题模块化。

履行

文集

我们收集的文档由 1904 个短篇恐怖故事组成,摘自r/shortcarystorys subreddit。如果你想学习如何自己提取这些和其他的,请阅读我的帖子,详细介绍了整个过程。根据 Reddit 的使用条款,这些数据是使用 Reddit 的 API ( PRAWPSAW 收集的。

让我们假设文本已经过充分的预处理,文档中的单词由一个空格分隔。

估计分布

我们分析的基础将是 LDA 主题建模的结果,在这个具体的例子中,有 10 个主题(目前是任意确定的)。我们将使用 Sci-Kit 学习实现:

在上面的代码中,变量 tf (代表词频)是一个 shape (D,V)的 numpy 矩阵,其中 D 是语料库中文档的数量,V 是词汇量的大小。每个条目 tf{d,v} 是文档 d 中术语 v 的频率。这必须是 LDA 模型的输入。

输出变量 doc_topic 的形状为(D,K),其中 K 是主题的数量。根据 LDA, doc_topic 的每一行加起来都是 1。

属性 model.components_ 的形状为(K,V),表示词汇上的主题权重分布。同样,每一行的总和为 1。

话题解读

这些是前一节中估计的 10 个主题中每个主题的前 10 个最重要的词:

10 个主题中的前 10 个最重要的单词。运行上述代码的结果。图片作者。

如前所述,主题只是相同词汇的权重分布,因此,将我们自己限制在每个主题的前 10 个权重最大的单词将允许我们专注于核心概念。然而,在这个描述中,我们不能掌握词与词之间的相对权重,这可能是所传达的概念的指示。

这些是主题 0、2 和 7 的词汇云:

主题 0、2 和 7 的文字云。在 wordcloud 中,单词越大,它在主题中的权重就越大。图片作者。

花几分钟时间阅读 10 个主题中的每一个,并尝试解释它们可能代表的概念。解释所有这些容易吗?还是有些人比其他人更难?

你觉得哪一个最容易诠释?没有错误的答案(或正确的答案,就此而言),但我敢打赌它是主题 0,概念将是与“圣诞节”有关的东西。我个人也将话题 2 标注为“可疑观察”,话题 7 标注为“感兴趣的物体/位置”,话题 8 标注为“家庭成员”,话题 9 标注为“可疑对象”。剩下的话题让我很难解释它们。

很明显,话题口译是一项非常艰巨的任务。如果现在我要写一份报告,这个和那个主题很容易解释,上面的标签可以分配,而这些和那些主题不能,这听起来就不太科学了。我需要用一些可以量化的东西来支持这些说法。这就是主题模块化发挥作用的地方。

主题模块化

一个话题可能传达某种概念。但是,在观察那个题目的前 N 个单词时,潜在的概念可能并不具体,也不全面。然而,一个不与其余主题共享一个单词(从前 N 个开始)的主题可以定义一个具体的、模块化的概念。达成这一概念,反过来,允许在这一方面对计划的文件进行独立评估。

例如,因为主题 0 很容易解释为“圣诞节”,所以可以假设它具体代表一年中的那个时间。这允许我们进一步假设,所有在主题 0 上有很大权重的文档必须与圣诞节有一些关联。更重要的是,因为我们知道语料库的上下文,我们可以声明这些文档是以圣诞节为背景的恐怖故事。

这里有一个例子支持我们的假设:

在左边,文档的主题分布在右边。该文档是从r/shortcarystorys 子编辑中自动提取的,并非作者所写。该文档可在引用的网站上公开获得。

这似乎是朝着更好地理解我们的语料库的正确方向迈出的有希望的一步!我们只需要将相同的技术应用于每个“具体”的主题。抛开主观性,主题模块化允许我们陈述哪些主题比其他主题更具体。

我们通过确定由一个模型提取的所有主题之间共享的字数来评估主题模块性(给定每个主题的前 N 个最有权重的单词)。因此,我们对具有最多独特单词的主题最感兴趣,然而考虑到从词汇表中选择 K 组 N 个独特单词的概率不是零。因此,围绕这些结果的讨论不能独立于每个主题的实际热门词。

代码如下:

结果如下:

每个主题前 10 个单词中独特单词的数量。图片作者。

不那么巧合的是,话题 0 在话题模块化上得分最高。这一指标证实了它确实是最容易解释的(或最容易给它贴上标签的)。

让我们来看看第二高的分数,题目 4。尽管它有很高的主题模块化分数,但仍然很难(至少对我来说)理解它。我不能给它一个具体的标签。这表明,就其本身而言,主题模块性还不足以作为一种评价——它必须总是伴随着主题的实际用词。

接下来是主题 7 和 8,我分别给它们分配了标签“感兴趣的对象/位置”和“家庭成员”。让我们来看几个关于这些主题的重要文档来支持这些陈述:

在左边,文档的主题分布在右边。该文档是从r/shortcarystorys subreddit中自动提取的,并非作者所写。该文档可在引用的网站上公开获得。

同样,主题模块化给了我们信心和正确的直觉。事实上,在主题 7 和 8 上具有高权重的两个示例文档都提到了“感兴趣的对象/位置”和“家庭成员”。更进一步,他们都没有提到圣诞节,这是令人放心的,因为他们在主题 0 中都没有权重。

结论

在第一部分中,我们利用两个工具在解释未标记语料库上的主题模型的结果方面向前迈进了一步:(1)主题解释,和(2)主题模块化。

我们看到,在我们的例子中,解读 LDA 的主题是非常主观的。在非常初始的步骤中,借助于主题模块性的度量,我们能够客观地陈述哪些主题更具体,并给它们分配一个标签。

从一个完全未知的短篇恐怖小说集开始,我们现在可以得出以下结论:

  1. 一些恐怖故事发生在圣诞节期间,或者以某种方式与一年中的那个时候有关。
  2. 一些恐怖故事涉及家庭成员。
  3. 一些恐怖故事涉及有趣的物体或地点。
  4. 我们知道哪些恐怖故事有这些特征,并精确量化它们有多少这些特征:
    → 0.5%的所有故事在话题 0 —圣诞节中的权重超过 0.5;
    → 2.3%的所有故事在主题 7—感兴趣的物体/位置中的权重超过 0.5;
    → 4.7%的故事在话题 8——家庭成员中的权重超过 0.5。
  5. 通过同样的量化,我们可以确定一个给定的故事是否比任何其他故事与这些特征更相关。

这是理解我们语料库的第一步。尽管我们已经获得了很多信息,但还需要更多的步骤来达到一些明显的东西。

下一部分

在本系列的下一部分中,我们将通过了解文档在主题空间中是如何聚集的来更深入地研究文档的主题分布。这将允许我们陈述有多少组不同的恐怖故事,以及它们在谈论什么。

利用无监督主题建模探索大型文档集—第 2/4 部分

原文:https://towardsdatascience.com/exploring-large-collections-of-documents-with-unsupervised-topic-modelling-part-2-4-8897248053d3

通过聚类了解文档分布

图片作者。

在这一系列的文章中,我们将重点探索基于主题建模的大量未标记文档。我们假设除了语料库的上下文之外,我们对语料库的内容一无所知。我们的目标是用一些新的、量化的知识来完成对语料库中所讨论内容的探索。

关于前一部分…

在这个系列的第一部分中,我们看到了如何执行主题建模,并且回顾了几种尝试和解释提取的主题的方法(这不是一个简单的任务!).我们收集的文件由 1904 个短篇恐怖故事组成,摘自r/short cary stories subreddit。如果你想学习如何自己提取这些和其他的,请阅读我的帖子,详细介绍整个过程。根据 Reddit 的使用条款,这些数据是使用 Reddit 的 API ( PRAWPSAW 收集的。和前一部分一样,我们假设文本已经过充分的预处理,文档中的单词由一个空格分隔。

最后,从一个完全未知的短篇恐怖故事集开始,我们学到了以下内容:

  1. 一些恐怖故事发生在圣诞节期间,或者以某种方式与一年中的那个时候有关。
  2. 一些恐怖故事涉及家庭成员。
  3. 一些恐怖故事涉及有趣的物体或地点。
  4. 我们知道哪些恐怖故事具有这些特征,并能准确量化它们具有多少这些特征:
    →所有故事中 0.5%的故事在 topic 0 — Christmas 中的权重超过 0.5;
    → 2.3%的所有故事在主题 7 —感兴趣的物体/位置中的权重超过 0.5;
    → 4.7%的故事在话题 8——家庭成员中的权重超过 0.5。
  5. 通过同样的量化,我们可以确定一个给定的故事是否比任何其他故事与这些特征更相关。

这是 4 部分系列的第二部分。让我们开始吧。

介绍

问题是

从本系列第一部分的结论中,我们看到我们可以做出类似“4.7%的文集以某种方式提到家庭成员”的陈述。但这是我们有目的地去寻找的东西,依赖于特定的查询。我们现在感兴趣的是学习如何概括这种说法,让我们回答以下问题:

  1. 就提到的话题而言,所有的恐怖故事都是相似的吗?
  2. 如果不是,它们是如何关联或分组的?
  3. 如果有多个小组,每个小组讨论什么?

拟议解决方案

在本帖中,我们将看到如何依靠聚类技术来回答上述问题。换句话说,我们尝试根据主题分布对文档进行分组,并根据这些结果回答这些问题。

履行

聚类 101

聚类是试图将给定人群的样本分组到离散的组中的任务。这些样本属于给定的 D 维空间,并且,一般来说,它们越接近,它们越有可能属于同一组或聚类。然而,我们没有一个标签或任何指示,表明具体的样本应该聚集在一起。

那么,我们如何知道样本的一个聚类比另一个更好呢?我们永远无法确定,因为,再说一次,我们没有黄金标准,但我们可以评估 D 维空间中的聚类和样本分布。例如,我们可以说,一个聚类越紧密(低聚类样本方差),它的定义就越好。我们也可以说,集群之间的距离越大,它们的定义就越清晰。下图举例说明了这些概念(请记住,我们也不知道可能有多少个集群,所以我们需要进行一些实验,或者使用其他指标,我们将在后面的部分中讨论)。我们也在 2D 思考和概念化,因为它更容易形象化,但这很少发生。例如,在我们的 k 主题的例子中,每个文档都被投影在一个 k 维空间中。

以各种方式在二维空间中对样本进行聚类。图片作者。

文档聚类—第一种方法

关注我们的主题建模环境,让我们假设我们的语料库是根据主题分布来描述的。也就是说,对于任何给定的文档,我们都有一个权重向量对应于每一个 k 主题。因此,每个文档向量是 k- 维空间中的一个样本。

让我们假设我们知道在主题空间中有多少个文档集群。具体说就是 C=10。这就是我们如何用 K-Means 算法对它们进行聚类:

在上面的代码中,我们用指定数量的集群 C 实例化了集群类,然后对主题空间中投影的文档进行集群,返回给每个文档的集群标签。预计文档(变量 doc_topic )在本系列第一部分之后获得。

文档聚类—找到理想的聚类数

然而,正如我们之前所说的,我们不知道理想的集群数量,我们也永远无法确切知道。在一个 D -dim 空间(其中 D 远高于 2)中,应对这一挑战的标准方法是观察样本集群分布指标,并找到集群数量的最佳点。一些常见的指标是:

  1. 惯性对于给定的聚类模型,该度量作为整体给出。它报告每个样本与其最近的聚类中心之间的平方距离之和。惯性越低,聚类的定义越好——但在极限情况下,每个样本都是自己的单样本聚类,具有完美的惯性,但不是很有趣。该度量促进高度凸起的簇,具有尽可能最小的直径。
  2. 剪影系数这个分数范围从-1 到 1,适用于每一个样本。简而言之,一个样本与同一聚类中的所有其他样本越接近,该样本与下一个最近聚类中的所有样本越远,该样本的得分越高。因此,零左右的分数表示重叠的聚类。这个度量促进了高度凸的、分离良好的集群,就像上图中显示的那样。

我们可以通过在一系列值上采取这些措施并找到“最佳点”,即平衡上述权衡,来找到最合适的集群数量。对于惯性,人们通常在图中寻找“肘”,也就是说,惯性只是从这个点稍微减小。这可以被认为是在更多的群中分离样本没有相关的增益。对于轮廓系数,通常寻找使所有样本的平均轮廓系数最大化的聚类数。

我们可以用以下代码绘制这些指标:

这是我们的恐怖故事文档的结果:

主题空间中投影文档的聚类度量。图片作者。

从上面的图中,我们可以看到最大平均轮廓值是用 10 个聚类获得的。我们还在惯性图中看到了一个清晰的“肘”,在相同的集群数下。具体来说,在 2 到 10 个集群之间,惯性下降超过 300 点,而在 10 到 20 个集群之间,惯性仅下降大约 75 点。这是“在更多的群中分离样本没有相关的增益”的经验版本。从这两个图中,我们可以有把握地说 C=10 是一个合适的集群数。

文档聚类—样本轮廓

既然我们已经决定了合适的集群数量,我们想知道样本是如何分布在这些集群中的。它们中的大部分是在一个巨大的星团中,而其他几个形成了微小的星团吗?还是分布好,分好?绘制每一个样本的轮廓系数,每一个聚类的颜色,可以让我们回答这些问题。

绘制样本轮廓系数的代码如下:

以下是我们 10 组文档的轮廓:

10 个聚类的主题空间中每个文档的轮廓系数。图片作者。

在上面的图中,每条彩色水平线是给定样品的轮廓。如前所述,该值介于-1 和 1 之间。垂直虚线是平均轮廓分数,其与轮廓-惯性度量图中的最大值一致。从该图中,我们得出结论,样本分布似乎几乎是均匀的(除了少数例外),但是每个聚类都具有密集的质心和分散的样本,因此每个聚类中的轮廓值快速下降。一个理想的、高密度的星团应该有一个类似于水平条的轮廓,而不是我们所拥有的尖三角形。这也反映在平均剪影分数(~0.28)并不太大。

文档聚类—他们在讨论什么?

假设我们知道每个主题是关于什么的,那么发现每个集群通常在讨论什么是相当简单的。一种简单的方法是在给定的群集中抽取每个样本,并观察哪些主题是“重要的”,即赋予它们很高的权重。简而言之,我们可以查看每个集群的平均主题分布,以推断该集群中通常讨论的内容。下面是代码和结果:

每个聚类的平均主题重要性,共 10 个聚类(从 0 到 9)。总共有 10 个主题(从 0 到 9)。图片作者。

从上面的图表中,我们可以很容易地得出结论,一般来说,每个集群正在讨论什么。例如,我们可以陈述如下:“群集 0 包含对主题 0 非常重要的简短恐怖故事”。

结论

在第二部分(在这里阅读第一部分,我们继续进一步探索我们收集的文件,这些文件我们在开始时一无所知。这一次,我们将重点放在集群上。

我们发现这些文档可以根据它们的主题分布分成 10 个组。我们了解到,这种分组虽然不是完美的,但也是定义良好的。我们还了解到,除了少数例外,这些组的规模大体相同。

我们继续进一步探索每个集群在谈论什么,一般来说,这是由该集群的平均主题分布/重要性给出的。我们了解到,聚类主要基于一个单一的高权重主题,这解释了为什么 C=10 是最合适的聚类数(记住 k=10 是主题数)。

最后,我们可以将这一分析与第一部分的分析结合起来,并为“话题 X”的陈述添加语义,例如“圣诞节的话题”。

下一部分

在本系列的下一部分,我们将再次深入主题本身。我们将试图准确理解每个话题被提及的次数,或少,以及它与总体人口的关系。

探索创建数字艺术的中途 V4

原文:https://towardsdatascience.com/exploring-midjourney-v4-for-creating-digital-art-4d20980a96f7

深入探讨流行的文本到图像创建系统的功能和选项

上排:达芬奇的《蒙娜丽莎》(左)、被米杜尼程式化为“表现主义绘画”作者(中)、以及“立体派绘画”作者(右)、下排:克洛德·莫内的《郁金香与里恩斯堡风车的田野》(左)、被米杜尼程式化为“表现主义绘画”作者(中)、以及“立体派绘画”作者(右)

在我上个月的文章中,我测试了三个文本到图像的生成系统,Stable Diffusion、DALL-E 和 Midjourney,看看哪一个最适合创建数字艺术。在大多数情况下,我只使用了三个系统的默认选项,尽管许多功能可以用来制作不同的、通常更好的图像。

在本文中,我将带领您深入了解 Midjourney 中用于创建数字艺术的功能和选项,包括目前作为公共测试版提供的版本 4。v4 太棒了!

以下是我将在文章中涉及的内容列表:

  1. 中途基础知识
  2. 探索版本
  3. 创作变奏和混音
  4. 带有文本提示的样式转换
  5. 中途混搭
  6. 渲染选项
  7. 升迁选项

中途基础知识

Midjourney 是一种文本到图像的创建服务,它使用 Discord 服务器作为主要用户界面,Discord 服务器是一个主要由游戏玩家使用的群组消息平台[1]。注册是免费的,可以免费创作 200 张左右的图像。之后,您可以点击查看快速入门指南中列出的定价选项。

基础设置

一旦我设置好并前往一个“新手”房间,我通过键入/设置并按两次回车键看到了主要选项。出现了以下界面。

中途设置,图片作者

这些只是一些基本的设置。完整的列表可以在命令行选项这里找到。

创建图像

使用默认设置,我通过键入 /imagine 创建了四个缩略图,按 enter 键调出 UI,并输入下面的提示,“用彩色圆圈画抽象画。”

中途创作图片,作者图片

系统考虑了一下,然后开始创建缩略图。大约 20 秒后,我得到了结果。

“彩色圆圈抽象画”中途缩略图,作者图片

根据我的提示,我得到了四个 256x256 像素的缩略图。他们看起来很不错。下面的“U”按钮用于将选定的图像放大到 1024x1024,“V”按钮创建选定图像的变体,蓝色 spinny 图标将重新运行该过程,创建四个新的缩略图。

我喜欢右上角的图片(数字 2),所以我按下 U2 按钮来放大那张图片。大约 10 秒钟后,我得到了结果。

“彩色圆圈抽象画”中途升级结果(左)、升级图像(右),图片作者

这是我在升迁过程完成时看到的,有各种进一步处理的选项。当我检查图像时,它出现在我的中途账户中,如右图所示。

探索版本

Midjourney 在 2022 年 3 月发布了第一个图像生成服务版本。版本 2 在 4 月份发布,版本 3 在 7 月份发布。版本 4 的测试版于 2022 年 11 月 10 日发布。

如上所述,您可以使用/设置命令来选择版本 1 至 4。我注意到版本 4 创建了 512x512 的初始渲染,而以前的版本创建了 256x256 的初始图像。为了测试所有四个版本,我发送了提示“画一个戴着帽子的法国人在露天咖啡馆喝酒”,看看会得到什么。

《一个戴着帽子的法国人在露天咖啡馆喝葡萄酒的画像》渲染于中途的 V1 (左上) V2 (右上) V3 (左下) V4 (右下),图片由作者提供

左上角的四个缩略图是使用版本 1 渲染的,右上角是版本 2,左下角是版本 3,右下角是版本 4。哇!质量差别好大啊!随着每个版本的推出,图像都在稳步改善。第 4 版的图像看起来非同寻常!在下一节中,我将展示一些定量的结果。

对比相似性测试

上个月我在发表了一篇文章,我研究了各种衡量艺术作品美感的标准。我发现了一种使用 OpenAI [2]的 CLIP 模型的技术,可以用来评估美学质量。当我将图像嵌入与正面和负面文本提示的嵌入进行比较时,如“坏艺术”和“好艺术”,我发现利用相似性的差异可以产生合理的结果。我还计算了一个提示相似性度量,以查看使用相似逻辑的图像与提示的匹配程度。下图显示了上述 16 张图片的两个指标。

即时相似性与审美质量,作者图表

您可以看到使用较新 Midjourney 的渲染在审美质量指标(垂直轴)和即时相似性(水平轴)上比旧版本排名更高,V4 比其他版本高出一截。两个值得注意的异常值是 v2–1(非常好的提示相似性)和 v2–3(两个指标都非常差)。再次向上滚动查看图像,这些指标似乎保持得相当好。这个测试的数学和 Python 在我的 GitHub 库这里

创作变奏和混音

在创建了带有文本提示的四个缩略图后,系统允许您使用 V1-V4 按钮进行其他更改。例如,对于提示“一个男人和一个女人在雨中的城市街道上撑着伞”,系统生成四个缩略图。在右上角选择 V2 后,它会生成四个变量。请注意,我在这个实验和接下来的所有实验中使用了版本 4。

《一个男人和一个女人撑着雨伞走在雨中的城市街道》初始渲染(左)和右上(右)的变化,图片由作者提供

这些变化看起来都很不错。从 Midjourney 的版本 3 开始,您可以在创建变体时修改文本提示。该功能被称为混音模式,可在设置中使用。例如,我使用混音模式在提示中添加了以下文本:“1880 年代”、“1950 年代”和“未来”这是结果。

《一个男人和一个女人撑着伞走在雨中的城市街道上》,图中有“1880 年代”(左)、【50 年代】(中)、【未来】(右),图片作者

果然,系统以与指定时间段相关联的独特视觉外观来呈现图像。

带有文本提示的样式转换

类似于使用混音模式来创建变体,您可以从网络上可用的图像开始,并添加文本来使图像风格化。我使用了 /imagine 提示并粘贴到基础绘画的 URL 中,并使用文本指定了样式。

例如,从蒙娜丽莎、莫奈的风景画和塞尚的静物画开始,我使用 Midjourney 将这些作品风格化为“表现主义绘画”和“立体主义绘画”这是结果。

达芬奇的《蒙娜丽莎》(左)米杜尼的《表现主义绘画》作者(中)中途的《立体派绘画》作者(右)

克洛德·莫内(左)的《郁金香与里恩斯堡风车的田野》;作者(中)的米杜尼“表现主义绘画”;作者(右)的中途“立体派绘画”

窗帘、水壶和水果保罗·塞尚(左)米杜尔尼《表现主义绘画》作者(中)中途《立体派绘画》作者(右)

原作在左边,表现主义和立体主义风格在右边。结果似乎相当不错。我喜欢这个系统除了改变风格之外,还可以自由地改变一点构图。请注意蒙娜丽莎的形象是如何被放大和缩小的,以及一些额外的物品如花和酒瓶是如何被添加到静物画中的。

中途混搭

该系统有一个很好的特性,除了文本提示之外,允许用户指定两到三个图像作为输入。我用这个特性创建了我称之为中途混搭的东西。我在没有提示的情况下粘贴了两个公共领域绘画的 URL,下面是 Midjourney 创建的内容。新图像在中间。

戴珍珠耳环的女孩约翰内斯·维米尔(左)中途混搭作者(中)柔琳夫人摇摇篮文森特·梵高(右)

风景皮埃尔·奥古斯特·雷诺阿(左)中途混搭作者(中)埃加列尔斯附近的高德加林麦田
文森特梵高(右)

Pieter Claesz 的《鲱鱼、葡萄酒和面包的静物》(左),作者(中)的中途混搭,保罗·塞尚的静物、水罐和水果(右)

黄-红-蓝作者瓦西里·康丁斯基(左)中期画作作者(中)红色、黄色和蓝色的构图 C(第三幅) 作者皮耶·蒙德里安(右)

好的,这些看起来很酷。你可以看到系统是如何从两幅源图像中提取关键的构图元素,并找到一种新的方式来表达它们的。在对这种技术进行试验后,我发现这种方法最适用于主题相似的来源。当我用完全不同的源进行尝试时,结果是不可预测的,并且通常在视觉上不连贯。

此外,中途 V4 模型仅支持 1:1 的图像纵横比。希望他们会发布一个版本来创建具有纵向和横向纵横比的图像,就像他们对早期版本所做的那样。

当代作品的混搭

为了看看这在当代作品中会是什么样子,我联系了波士顿地区的四位艺术家,他们允许我使用他们最近的一些作品。 Katie Cornog 是水彩艺术家, Noah Sussman 在画布上作画, Anna Kristina Goransson 创作毛毡雕塑, Georgina Lewis 是在混合媒介中工作的装置艺术家。中间一栏显示了我制作的四个 Midjorney 混搭,混合了每个艺术家的两个作品。

桑迪点秋 作者凯蒂·科尔诺格(左)作者中途混搭(中) 作者凯蒂·科尔诺格

工作室场景作者诺亚·苏斯曼(左)中途混搭作者(中) S 超越月食 作者诺亚·苏斯曼(右)

忧郁之美安娜·克里斯蒂娜·戈兰松(左)中途混搭作者(中)寻找安娜·克里斯蒂娜·戈兰松(右)

最近的共同祖先作者乔治娜·刘易斯(左)中途混搭作者(中)拉帕奇尼的后代作者乔治娜·刘易斯(右)

结果再一次令人惊叹。这四个混搭看起来都像是原创艺术家创作的。两位艺术家告诉我,他们想这样做。

渲染选项

正如我上面提到的,中途有很多渲染选项。然而,为了进行比较测试,我学会了如何检索和使用用于生成图像的随机种子。这有点隐蔽,但在我生成一个图像后,我对我的图像创建了一个“反应”,然后选择了“信封”表情符号。

用不和谐的信封表情符号发送反应,图片作者

这触发了机器人向我发送一条包含运行种子的消息,就像这样。

图片种子直接留言,图片作者

然后我使用 - seed 6534 参数来生成具有不同选项的相同图像。例如,下面是使用提示“春天波士顿公共花园的绘画”的渲染,质量设置为 0.5,1.0(默认)与 2.0。

“春天的波士顿公园绘画”,质量 0.5 (左)、 1.0 (中)、 2.0 (右),图片作者

有趣的是,我们可以看到不同质量选择下的图像变化有多大。中间的那棵黄树大致保持不变,但花、建筑和人都在四处移动。这很微妙,但右边质量为 2.0 的图像似乎有最少的“问题”区域。

升迁选项

Midjourney 还提供了用于放大的选项,可以改善最终图像的细节。对于这个测试,我使用了提示符“蒸汽朋克旋转电话”,质量设置为 2.0。我不得不使用“种子”技巧来测试三个升迁选项,lite、regular 和 beta。(声明一下,这是 24863 号种子。)下面是结果,以及旋转拨号器的特写。

“蒸汽朋克旋转式手机”,尺寸设置为 Lite (左)、Regular (中)和 Beta (右),细节在第二行,图片由作者提供

这三张图片都显示了一些细节,但是右边的 beta 放大看起来更有序一些。比如拨号器上的内圈,看起来形成的更真实。

结论

在过去的两年半时间里,我一直在研究使用人工智能来生成数字艺术。我可以告诉你,Midjourney V4 是迄今为止我见过的最好的系统。希望,他们将发布这个版本的全套功能(长宽比,风格数量,等等。)此外,一些似乎缺失的功能正在修复和着色,就像 DALL-E 中一样。

源代码和 Colabs

运行图像对比相似性测试的源代码可在 GitHub 上获得。我在麻省理工学院开源许可下发布了源代码。

麻省理工学院开源许可证

感谢

我要感谢詹尼弗·林和奥利弗·斯特瑞普对这个项目的帮助。

参考

[1]中途 https://midjourney.gitbook.io/docs/

[2]a .拉德福德等人的剪辑,从自然语言监督中学习可转移的视觉模型 (2021)

为了无限制地访问 Medium 上的所有文章,成为的会员,每月支付 5 美元。非会员每月只能看三个锁定的故事。

用圆圈探索中旅 AI 艺术风格

原文:https://towardsdatascience.com/exploring-midjourneys-art-style-using-circles-a461a78e7196

材料、情绪和媒介如何影响简单循环的输出

所有图片由作者执导。

Midjourney 是一种人工智能图像生成工具,它接受人类的输入(通常通过文本提示和参数,但也包括其他图像),并使用在大量图像数据上训练的机器学习算法来生成独特的图像。

像大多数机器学习模型一样,中途可能有点像黑箱。这太复杂了,以至于很难向一个外行人解释在系统收到文本提示和产生图像之间发生了什么。

我们能做的,是根据我们给出的输入,探索我们得到的输出,并寻找模式和做出假设。这不一定会让我们更好地理解系统是如何工作的,但它可以帮助我们学习如何更好地使用它。

注意:我会经常在这里把中途拟人化。我知道它实际上不会思考、想象、喜欢/不喜欢或感觉任何东西。

为了最好的表现中途输出的细节, 下面的图片有很大的文件大小 。如果您使用的是慢速或计量移动连接,请谨慎操作。

一个圆圈

如果你让你生活中的一个随机的人给你画一个圆,他们可能会找到一张白纸,也许是一个有线条的记事本,拿起一支钢笔或铅笔,画一个圆的轮廓。

但是当我们在中途问同样的问题时会发生什么呢?

提示:“一个圆”

你可以看到,通过简单的提示,Midjourney 填补了大量空白,这些空白归结为人类通常会留下空白的图像方面的加权掷骰子。在系统中运行类似这样的提示十次,你可能会得到 6-8 个有着不同方面和许多相似特征的完全不同的图像。没有风格或颜色描述符,默认情况下,它严重倾向于电影中的蓝绿色和橙色,正如你在这里看到的。它喜欢云。你可以看到它有一个非常特殊的绘画外观,这也是默认情况下喜欢的。

我们可以试着通过更具体的文本提示把它调回来,让它变得像人类会做的东西。

提示:“一个圆的铅笔线条画”

尽管如此,它仍然比我们期望的人类要详细得多,并且仍然需要大量的尝试和错误来简化。

提示:“一个简单的铅笔轮廓在白纸上画一个圆”

材料

Midjourney 非常擅长模拟不同类型的材料。它通常了解许多有趣材料的基本属性、形式或颜色,我们玩这些会得到一些有趣的结果。

提示:用树枝、青铜和草做成的圆圈

提示:一个由冰、绿宝石、黄金、灰烬和灰烬组成的圆环

提示:由液体黄金、木头和羽毛制成的圆圈

材料和颜色将有助于增加你的提示的味道。尝试组合,包括预期的和奇怪的。注意你周围的材料。现在在我周围,我看到皱纹纸、黑色塑料、拉丝铝、灰色编织棉和蓝色泡沫。让你的环境激励你。

情绪

Midjourney 在诗意描述和形容词方面做得很好,但前提是你不是在追求一些非常具体的东西,而是喜欢简单地唤起一种情绪。

使用它的最好方法是留下大量的解释空间,就像掷骰子一样。你会注意到特定的情绪喜欢特定的配色方案(蓝色代表忧郁,红色代表恐怖),但通常蓝绿色和橙色仍然会悄悄出现。

提示:“一个神秘的圈子”

提示:“一个邪恶的圈子”

提示:“忧郁的一圈”

提示:“一个假想的圆”

提示:“一个空灵的圆”

提示:“一个恐怖的圈子”

提示:“一个盛开的圆圈”

媒介

默认的“中途绘画”样式可以通过使用特定的关键字或参数调用某些样式来覆盖。无论你想要一种特定的绘画风格,3D 渲染,泥塑,还是特定风格的摄影或插图,Midjourney 都有一个很好的机会对它有一个基本的了解。

提示:“黑色电影中的一个圆”

提示:“使用体积照明和雾以辛烷渲染的圆”

Octane 是一个用于数字 3D 工作的渲染工具,主要用于渲染具有真实物理属性和精确光照的事物。你会看到它经常被用在中途的作品中,旨在打造独特的外观。你可以从光环照亮地面的方式中看到这一点。

提示:“一个用粘土雕刻的圆”

提示:“一个圆的技术图”

提示:“一个水彩圆圈”

环境

虽然在我们的提示中简单地陈述“一个圆”会使它成为默认的主题,但是当我们开始描述我们的主题所处的环境时,事情会发生一些变化。正如你将会看到的,在缺乏主题细节的情况下,环境会以有趣的、有时意想不到的方式塑造主题。

提示:“花丛中的一个圆圈”

提示:“惊涛骇浪中的一圈”

提示:“森林中的一个圆圈”

提示:“山中一圈”

提示:“黑暗巷子里的一个圈”

提示:“公司办公室里的一个圆圈”

宽比

长宽比也能极大地影响图像的类型和组成。如果您想要在标准海报尺寸上打印一些东西,或者将一些东西用作手机或桌面壁纸,请熟悉宽高比参数并相应地使用它,因为重新格式化您已经决定喜欢的正方形图像非常困难。

提示:(9:16)和(16:9)中的“一个圆”

艺术家

Midjourney 可以尝试唤起特定艺术家的风格。这是在艺术中使用人工智能在伦理上更具争议的方式之一,尤其是在处理任何类型的商业化作品时。虽然人类可以也确实复制他人的风格,但当人工智能模型进行复制时,灰色区域是很大的。这尤其(也是可以理解的)关系到工作的艺术家,以及任何足够被系统识别的知名人士。这些作品在任何法律/版权意义上仍然是独一无二的(截至今天),但它仍然可能会受到社区的反对。

提示:文森特·梵高风格的圆形,杰森·布拉克吉格尔美术馆

类似地,灰色是流行的“艺术站趋势”描述符,它将广泛地近似不是一个特定的艺术家,而是在Artstation.com上经常看到的许多工作类型和风格,这在电影、游戏、概念艺术和插画领域的艺术家中非常受欢迎。

提示:“Artstation 上的一个圈子趋势”

组合和实验

这篇文章只是触及了皮毛。像这样的系统的无限可能性和真正的力量来自于你(人类)的实验、方向和品味,结合以上所有的概念和更多的概念来创造独特的作品,这些作品可能会激励和愉悦你自己和他人。

提示:“一个由树枝和液体烟雾组成的神秘圆圈,位于夜晚茂密的丛林中。可怕又神奇。金色口音。”(16:9)

提示:“一张孤独的木圈的黑白照片,被遗弃在沙丘上。”(16:9)

提示:“一个被遗忘的废土深渊里的一圈火与烟。(16:9)

感谢阅读。你可以在 Instagram 上关注我的人工智能艺术实验。如果你从这样的故事中获得价值,并且想要无限制地访问 Medium 上的所有内容,考虑成为 Medium 会员。它每月只需 5 美元,这笔钱将帮助支持我,这个出版物,以及你在 Medium 上阅读的其他作家。

使用 Python 探索 Microsoft PowerPoint AI

原文:https://towardsdatascience.com/exploring-powerpoint-ai-using-python-75f94d55f8f4

塔达斯·萨尔在 Unsplash 上拍摄的照片

使用 Python 探索 Microsoft PowerPoint AI

以下是如何使用机器学习和 Python 复制 PowerPoint 人工智能

几天前,我在为我的博士研究做一个 PowerPoint 演示时,发生了这样的事情:

我做的截图。见 ALT 文字!

这不是完全相同的图像,它实际上更加明确,有 x 标签,y 标签,标题和所有这些,但它现在并不真正重要。

非常有意思的是 Alt 文本。PowerPoint 的人工智能系统不仅能够检测到我们实际上有一个 2d 绘图(或图表),而且它还能识别出我们正在谈论一个箱线图!

当然,我并不确切知道他们是如何做到这一点的,但由于我一生都在与机器学习和数据科学打交道,我可以试着猜测一下。读者可能知道,广泛用于图像分类的技术被称为卷积神经网络(CNN)。

他们可能使用 CNN 作为多类分类器。这里是一个 Butterly 图像分类器的例子(超过 70 个种类/类)。他们可能做过的一件更复杂的事情是图像字幕 。尽管如此,细胞神经网络肯定会用在他们的深度学习算法中,至少是作为更大更复杂的东西的基本砖块。

在这个非常小的例子中,我将展示如何建立一个机器学习模型,帮助您区分箱线图和其他类型的图,例如线图。

我们开始吧。

0.图书馆

这些是我用于此笔记本的库:

简而言之,我使用了 keras、matplotlib 和一个被称为 RandomWords 的奇怪的库来生成随机的英语单词。我用它来组成 x 轴和 y 轴。

1.数据生成

这款笔记本最有趣的部分其实是数据生成。我试图尽可能以最通用的方式构建线图和箱线图,组成 x 和 y 标签,创建不同的线图箱线图,同样,尽可能以最通用的方式。

通过这种设置,你可以虚拟地创建无限数量和种类的地块。我创建了两个数据类并执行了二进制分类,但是您可以稍微修改代码并创建多个类。

让我们开始吧:

1.1 线形图

我用来创建线图的代码如下:

它有不同程度的随机性:

  • x 轴标签和 y 轴标签有随机名称
  • x 轴极限是随机的
  • y 轴显示具有随机数和随机值系数的多项式
  • 行数也是随机的

这里有一个例子:

1.2 箱线图

我用来创建图的代码如下:

这里也有不同程度的随机:

  • x 轴标签和 y 轴标签具有随机名称
  • x 轴限位是随机的
  • x 轴数量名称是随机的
  • y 轴显示来自高斯分布的样本,随机值为标准差
  • 箱线图的数量也是随机的

1.2 训练集和测试集

实际上,我用来构建训练集和测试集的代码与上面的代码略有不同,上面的代码是我用来展示结果的。以下是你需要的:

在这里你可以创建情节:

在这里你创建 k 个并存储它们。首先创建一个训练集和测试集文件夹,否则它将不起作用!

在这里你可以阅读它们,并给它们贴上标签

定义此函数后,您将通过以下操作获得数据集:

以下是训练集的一些示例:

必须对测试集进行完全相同的处理,并且必须将字符串转换成对 ML 模型更可读的东西( sklearn 将通过所谓的 LabelEncoder 特性为您完成这项工作):

2.机器学习模型

我们要使用的机器学习模型基本上是不同的卷积层和一些最大池操作的应用,然后它会以 softmax 结束,它会告诉你图像属于第一类的概率。

我使用的模型与我发表的这篇 文章 中的模型相同,你可以找到关于这个结构实际上如何工作的更多细节。

以下是你如何训练和测试你的模型:

正如我们所见,的最终结果是完美的。即使这听起来令人兴奋,我不得不说这个实验非常简单(我们都能够区分方框图和线条图)这个模型非常强大(这里有点矫枉过正)。

3.决赛成绩

作为对模型正确地区分箱线图线图的最后证明,下面是一些例子:

以下是情节:

4.结论

当我还是个孩子的时候,我就开始使用 PowerPoint,并且在高中的时候做了我的第一次演示。我真的可以看到这个产品在这些年中的改进,我发现他们的人工智能识别模型真的令人印象深刻。

这个笔记本只是一个非常简单的实验,关于深度学习算法如何帮助你检测图片中的内容,并使用一些(在这种情况下,非常基本的)图像分类技术。

如果你喜欢这篇文章,你想知道更多关于机器学习的知识,或者你只是想问我一些你可以问的问题:

A.在 Linkedin 上关注我,在那里我发布我所有的故事
B .订阅我的 简讯 。这会让你了解新的故事,并给你机会发短信给我,让我收到你所有的更正或疑问。
C .成为 推荐会员 ,这样你就不会有任何“本月最大故事数”,你可以阅读我(以及数千名其他机器学习和数据科学顶级作家)写的任何关于最新可用技术的文章。再见:)

探索 Python 类型提示

原文:https://towardsdatascience.com/exploring-python-type-hints-6520f478b6a

马蒂亚斯·马尔卡在 Unsplash 上的照片

探索 Python 类型提示

如何让您的代码经得起未来的考验

我最近在 Python 中发现了一些有趣的功能,我已经开始尝试在日常编程中更多地使用这些功能。在这篇文章中,我想介绍 Python 类型提示,并讨论为什么我认为它们是你编程工作流程中真正强大的补充。

如果你是一个狂热的 Python 用户,你可能会发现最初的类型提示非常奇怪,甚至可能是不和谐的,但是希望在这篇文章结束时,我会让你相信事实并非如此,实际上它们真的可以改善你的代码库,并从长远来看使你的生活更容易。

为了了解它们为什么有用,让我们看下面的代码片段,它定义了一个将两个数相加的函数。我们可以看到,当我们输入一个字符串,并尝试将它与一个整数相加时,我们会得到一个可爱的 TypeError。现在,这是一个超级简单的例子,但是如果我们使用一个更大的代码库,我们可能不会注意到这个错误,直到我们真正尝试运行代码。这通常会很成问题。

def add_two_numbers(a, b):
   return a+b>>> add_two_numbers(1, '3')Traceback (most recent call last):File "<stdin>", line 1, in <module>TypeError: unsupported operand type(s) for +: 'int' and 'str'

静态与动态类型

上面我们提供了一个简单的类型错误的例子。让我们简单讨论一下为什么 Python 中会出现这个问题。为此,我们需要讨论静态和动态类型。如果你曾经使用过像 C 或 Java 这样的编程语言,你会知道你需要为你创建的变量声明数据类型。在 Java 中,我们可以使用下面的代码创建一个字符串变量。这些变量类型不允许改变。也就是说,如果我们试图将一个整型变量重新赋值给字符串变量,我们会得到一个错误。

String string_variable;
string_variable = "This is a string";

静态类型 的第二个重要方面是当类型错误被捕获时。因为像 java 这样的编程语言是编译的,所以编译器会在运行任何代码之前检查代码的正确性。如果你的代码中有类型错误,那么这就是它们被发现的时候。这提供了一些优于 Python 等解释型语言的优势。特别是,尽早捕捉错误可以避免在调试代码上花费大量时间。

然而 Python 是 动态类型化的。这意味着我们不必显式声明我们的变量类型。这也意味着 Python 会在代码运行时检查任何类型错误。例如,如果我们在 if-else 逻辑中嵌入了这些类型的错误,如果条件不满足,它就不会被捕获。以上面的字符串变量为例,如果我们试图给它重新赋值一个 int,代码会运行得很好,我们的 string_variable 现在是 int 类型。

鸭子打字

另一个与动态类型化和 Python 密切相关的概念是 duck typing。 我听你问鸭子打字到底是什么神?嗯,我同意,这是一个奇怪的名字,但它来自短语:如果它看起来像鸭子,像鸭子一样游泳,像鸭子一样嘎嘎叫,那么它可能就是鸭子。我们不一定关心对象的参数类型,我们关心的是对象的行为。如果它的行为像一只鸭子,那么实际上我们可以认为它是一只鸭子。

我们举个例子来了解一下鸭子打字是怎么回事。因为我是一名数据科学家,所以我想看一个使用 sklearn 的实际例子。例如,如果我们想在一个建模管道中编码一些定制的转换,我们可以在 sklearn 中创建一个定制的转换器

“由于 Scikit-Learn 依赖于 duck typing(不是继承),所以你需要做的就是创建一个类,实现三个方法:fit()(返回自我)、transform()、fit _ transform()”(Geron 2019)。

下面我们写一个自定义的转换器来估算数字数据。我们可以看到,只要我们实现了 fit 和 transform 方法,这将与 sklearn 完全兼容,并且可以与其他 sklearn 转换器一起用于管道中。这是通过 duck typing 实现的,因为 python 只关心我们的类是否具有与 transformer 相同的行为,也就是说,如果它有 transform 和 fit_transform 方法,那么它就会工作。Btw,下面没有 fit_transform 方法我们从 TransformerMixin 类继承时得到这个方法。这里的很好地解释了这种行为。

注意:这并不意味着所有动态类型的语言都被解释,所有静态类型的语言都被编译。例如,我们可以拥有动态类型的解释语言,尽管据我所知,它们并不常见。

什么是 Python 类型提示,我为什么要关心?

好了,我们已经解释了动态、静态类型和鸭子类型之间的区别,但是为什么这很重要,这和类型提示有什么关系呢?尽管 Python 是一种动态类型语言,但我们可以使用类型提示来获得静态类型语言的一些好处。

类型提示(也称为类型注释)最初是在 PEP 484 中引入的,它允许我们模仿静态类型语言的行为。我说 mimic 是因为 python 解释器完全忽略了类型提示。相反,类型提示依赖于用户使用 mypy 之类的工具单独运行检查,稍后会详细介绍。

那么我们实际上如何利用类型提示呢?文档详细介绍了使用类型提示的所有不同方式,但我将讨论一些您最常使用的方式。类型提示的语法非常简单和直观,如果你曾经用静态类型语言编写过代码,那么这对你来说并不陌生。如果您想开始使用类型提示,您将与之交互的主要模块是类型模块。它包含了我们将要用到的许多类型,比如列表、字典和元组等等。下面举个简单的例子,我们声明了一些变量,并说明了库中的一些类型。如果我们看一下 process_data 中稍微做作的例子,我们可以看到我们有两个输入,一个字符串列表和一个整数列表。我们也知道我们的输出应该是包含字符串和整数的元组列表。在我看来,这使得理解代码变得非常容易,而且实现起来也不需要太多额外的努力。

请注意,我们可以使用嵌套类型提示,这可能非常有用,但如果我们需要两层或三层嵌套,也可能非常笨拙。在这种情况下,我们实际上可以给一个变量分配一个类型提示,如下所示(类型别名)。恰当地使用变量可以大大提高代码的可读性,同时保持类型提示的优势。

years = Tuple[str, int]
year_list = List[years]

重访我们的定制变压器

下面我们更新上面写的代码,加入类型提示。大多数类型提示应该是清楚的。我们可以看到,我们也可以使用来自 pandas 的类型,这显然非常有用,因为 python 中的大多数数据分析都以某种方式使用 pandas。您可能想知道为什么我们将“CustomImputer”作为字符串包含在 fit 方法的返回中。这里有一个很好的理由来讨论。它被称为前向引用,因为我们引用的是尚未创建的类型。将它作为字符串文字包含在内可以解决这个问题。除此之外,代码应该非常清晰,希望比原始代码片段更清晰。

希望您会同意,显式声明数据类型会使代码立即变得更清晰。当我们有大型复杂的代码库时,这样做的优势会更加明显,但是请相信我,如果您需要重构别人的代码或者需要在将来重新访问您自己的代码,您会感谢自己花时间添加类型提示。

Mypy:静态类型检查器

Mypy 是 Python 的静态类型检查器。它允许我们在实际运行之前检查代码中常见的类型错误。这个库和类型提示结合在一起,将 Java 等静态类型语言的优势带到了 Python 中。

让我们举一个 mypy 文档中概述的非常简单的例子。我们可以定义一个非常简单的函数,它接受一个字符串,并输出 hello,后跟我们的字符串输入。如果我们传入一个字符串并运行类型检查器,我们会正确地看到没有错误。但是,如果我们传递一个 int 或任何其他数据类型,我们会立即看到一个错误消息。同样,当我们处理较大的项目时,这个功能特别有用。

def main(name: str) -> str: return 'Hello ' + nameif __name__=='__main__':
    main('John') mypy program.py
>> Success: no issues found in 1 source filedef main(name: str) -> str: return 'Hello ' + nameif __name__=='__main__':
    main(10)mypy program.py
>> program.py:7: error: Argument 1 to "main" has incompatible type "int"; expected "str"
Found 1 error in 1 file (checked 1 source file)

mypy 的一个缺点是它不能与外部库一起工作。如果你更倾向于使用 numpy 和 pandas,那么探索一下数据科学类型pandas-stub 可能是值得的,它们允许你运行更多数据科学相关库的类型检查,比如 pandas、numpy 和 matplotlib。然而,数据科学类型库仍在开发中,所以它没有涵盖这些库中可用的所有类型。

pip install pandas-stub
pip install data-science-types

类型提示的优点和缺点

虽然我是类型提示的粉丝,使用它们有很多好处,但是它们也有一些缺点。就优势而言,我认为最大的优势之一是

  • 它迫使你思考你的函数输入和输出:也就是说,一般来说,它让你更多地思考你的代码以及它是如何被设计使用的。对我来说,更深入地思考我正在编写的代码有助于提高我的编程技能。我认为仅仅这个理由就足够让我们开始使用它们了。

此外,使用类型提示非常重要,这意味着您的代码

  • 清晰的文档。清晰的文档使你的代码更容易阅读,不仅对你自己,对其他人也是如此。如果你曾经接手过别人的代码,并且认为,我不知道这些代码在做什么,你就会明白这有多重要。拥有清晰记录的代码在数据科学中似乎并不常见,但应该如此。
  • 调试更容易:如果到现在还不清楚,现在应该清楚了。使用类型提示可以使调试代码中的问题变得容易得多,并且在很多情况下可以完全避免一些错误,特别是在使用像 mypy 这样的静态类型检查器时。

类型提示的另一个优点是,它们

  • 可以逐步实现:您可能认为,与您习惯的相比,这将在编写代码的时间方面增加大量开销,您可能是对的。好消息是,您不需要一次性重构整个代码库。类型提示可以逐步实现。

好吧,那么缺点是什么?即使你可以逐步实现类型提示,它们仍然可能是一个

  • 大量的时间投入:虽然类型提示的基础非常简单,但是还有很多我在这篇文章中没有涉及到的内容。除了学习曲线之外,使用类型提示显然涉及到编写更多的代码,因此最初可能会导致开发时间增加。然而,通过减少调试花费的时间,这可以完全不在现场。我没有这方面的经验证据,但我完全可以相信,特别是对于更大更复杂的项目。
  • 它是否背离了 python 的简单和漂亮?这与其说是一个明显的缺点,不如说是一个公开的问题,但是那些铁杆 than 爱好者可能不愿意用类型提示来亵渎他们美丽的代码。

建议和要点

应该使用类型提示吗?最终这取决于你,但希望这篇文章能给你一些启发,如果你还在犹豫不决,会让你更容易做出决定。就我个人而言,我喜欢类型提示,所以我尽量使用它们。我的建议是,如果你只是在 Jupyter 笔记本上做一些快速和肮脏的数据分析,使用它们的缺点可能大于优点,所以我可能不会打扰。然而,如果你正在做更大的项目和产品代码,我建议你试一试,看看它们是否能改善你的工作流程。

资源

我的其他一些帖子你可能会感兴趣

探索电力查询中的查询折叠

原文:https://towardsdatascience.com/exploring-query-folding-in-power-query-8288fb3c9c2f

查询折叠是 Power Query 中的一个重要特性,可以将处理步骤卸载到数据源。有了这个特性,电源查询可以减少 CPU 和 RAM 的消耗。让我们看看如何使用它。

元素 5 数码Unsplash 上拍摄

什么是查询折叠,我们如何使用它?

查询折叠是将超级查询转换推回到源的机制,以减少超级查询的负载。

这只适用于某些数据源,即关系数据库和类似于关系数据库的数据源。

例如,请看下图,其中显示了 Power BI,它从数据库中获取数据:

图 1 —来自数据库的数据(由作者提供)

在 Power 查询中添加转换步骤时,我们希望避免 Power 查询上不必要的负载。

用原生数据库语言 SQL 将这种转换推回到源数据库会很好。

但是我们为什么要拥有它呢?

为什么我们需要查询折叠?

您可能知道,关系数据库引擎在管理数据方面非常有效。

关系数据库引擎擅长的操作有:

  • 数据排序(排序依据)
  • 组合数据(连接/合并)
  • 对大量数据执行计算(计算列)
  • 只做必要的事情(优化查询)

但最关键的一点是,关系数据库引擎运行在服务器硬件上,这是为了处理大量数据而优化的。这些服务器拥有比我们简陋的笔记本电脑或个人电脑更多的 CPU 内核和内存,处理数据的限制也比我们少得多。

所有支持 SQL 的数据源都可以支持查询折叠。除了明显的关系数据库(如 SQL Server、Oracle、DB/2 等。),OData sources、Exchange、Active Directory 等都支持查询折叠。

让我们仔细看看。

让我们从 SQL Server 数据库中获取数据

现在,我使用我常用的 Contoso 数据库来查看查询折叠的运行情况。

我切换到 Power Query,并使用 Azure SQL 数据库源以导入模式从我的数据库中获取一些表:

图 2 —源表(作者提供的图)

将表加载到 Power Query 后,您可以右键单击其中一个应用的步骤,并查看“查看本地查询”项是否处于活动状态:

图 3 —获取原生查询(作者提供的图)

如果它是活动的,则使用查询折叠,您可以看到 Power Query 生成并发送到源数据库的查询:

图 4 —第一个本地查询(作者提供的图)

在这种情况下,查询很简单,直接发送到源数据库。

探索查询折叠

现在,让我们应用一些修改:

  • 删除一些列
  • 更改列的名称
  • 更改列的数据类型

当我得到本机查询时,我看到这样的内容:

图 5 —修改后的原生查询(由作者提供)

如您所见,该查询已经更改,以反映 Power Query 中的步骤。

您可以注意到,该查询不再包含已删除的列,而是直接使用该查询转换 DateKey 列。

这比在 Power Query 中这样做要高效得多,Power Query 会消耗我们计算机中的 CPU 和内存。

现在,让我们做一个更复杂的转换。

为了描述产品,我们有以下层次结构:

图 6 —产品层次结构(作者提供的图)

你可能知道,Power BI 不喜欢这样的表层次结构。Power BI 最适合事实表和维度表之间的单步关系。

目标是将这些表合并成一个产品表。

我们可以使用 Power Query 中的 Merge 转换将产品类别合并到产品子类别中,并将结果合并到产品中(是的,我们可以直接从产品表中执行此操作,因为 Power Query 可以识别数据库中的现有关系,但是让我们看看手动执行此操作时会发生什么):

图 7 —带有合并表的本地查询(由作者提供)

查询要复杂得多,因为它必须合并(连接)源表来形成结果。

但是数据库引擎是为做这类事情而优化的,它将比 Power Query 更好地完成这项任务。

不可折叠操作

不幸的是,并不是所有的转换都可以折叠。

但是很容易确定哪个不会折叠:

  1. 影响多个源(数据库)的转换
    例如,当您想要合并数据库中的表格和文本文件中的表格时,查询折叠是不可能的,因为文本文件不理解 SQL。
    遗憾的是,这同样适用于合并来自两个不同数据库的数据,即使它们驻留在同一个数据库服务器上
  2. 当您应用无法翻译成 SQL
    的复杂转换时,例如,当您使用 M 函数来操作数据时。

您可以在下面参考资料部分的文章中找到关于不可折叠转换的更多信息。

你必须意识到这些限制。因此,在查询折叠不再可能之前,您必须执行尽可能多的转换。这种方法通过将计算卸载到数据库引擎来提高负载性能。

本地查询和查询折叠

当从数据库中检索数据时,我们可以编写自己的查询。

例如,假设我们编写了一个 SQL 查询,将三个产品表连接在一起,将结果导入到 Power Query 中:

SELECT [P].[ProductKey]
,[P].[ProductLabel]
,[P].[ProductName]
,[P].[ProductDescription]
,[PSC].[ProductSubcategoryName]
,[PSC].[ProductSubcategoryLabel]
,[PSC].[ProductSubcategoryDescription]
,[PC].[ProductCategoryName]
,[PC].[ProductCategoryLabel]
,[PC].[ProductCategoryDescription]
,[P].[Manufacturer]
,[P].[BrandName]
,[P].[ClassID]
,[P].[ClassName]
,[P].[StyleID]
,[P].[StyleName]
,[P].[ColorID]
,[P].[ColorName]
,[P].[Size]
,[P].[SizeRange]
,[P].[SizeUnitMeasureID]
,[P].[Weight]
,[P].[WeightUnitMeasureID]
,[P].[UnitOfMeasureID]
,[P].[UnitOfMeasureName]
,[P].[StockTypeID]
,[P].[StockTypeName]
,[P].[UnitCost]
,[P].[UnitPrice]
,[P].[AvailableForSaleDate]
,[P].[StopSaleDate]
,[P].[Status]
  FROM [dbo].[DimProduct] AS [P]
    INNER JOIN [dbo].[DimProductSubcategory] AS [PSC]
      ON [PSC].[ProductSubcategoryKey] = [P].[ProductSubcategoryKey]
    INNER JOIN [dbo].[DimProductCategory] AS [PC]
      ON [PC].[ProductCategoryKey] = [PSC].[ProductCategoryKey];

在超级查询中,如下所示:

图 8 —用本地查询导入表(作者提供的图)

执行此操作时,会自动禁用查询折叠:

图 9 —使用原生查询禁用查询折叠(作者提供的图片)

要启用查询折叠,您必须更改 M 代码,如下面引用的文章中所述(在 Power Query Using Value 中对 SQL 查询进行查询折叠)。NativeQuery()和 EnableFolding=true(克里斯·韦伯的博客)

在我们的例子中,我必须将 M 脚本更改为以下内容:

let
Source = Sql.Databases(“sca4tvddemo.database.windows.net”),ContosoRetailDW = Source
                {[Name = “ContosoRetailDW”]}
                 [Data],RunSQL = Value.NativeQuery(
                  ContosoRetailDW,“SELECT [P].[ProductKey]
,[P].[ProductLabel]
,[P].[ProductName]
,[P].[ProductDescription]
,[PSC].[ProductSubcategoryName]
,[PSC].[ProductSubcategoryLabel]
,[PSC].[ProductSubcategoryDescription]
,[PC].[ProductCategoryName]
,[PC].[ProductCategoryLabel]
,[PC].[ProductCategoryDescription]
,[P].[Manufacturer]
,[P].[BrandName]
,[P].[ClassID]
,[P].[ClassName]
,[P].[StyleID]
,[P].[StyleName]
,[P].[ColorID]
,[P].[ColorName]
,[P].[Size]
,[P].[SizeRange]
,[P].[SizeUnitMeasureID]
,[P].[Weight]
,[P].[WeightUnitMeasureID]
,[P].[UnitOfMeasureID]
,[P].[UnitOfMeasureName]
,[P].[StockTypeID]
,[P].[StockTypeName]
,[P].[UnitCost]
,[P].[UnitPrice]
,[P].[AvailableForSaleDate]
,[P].[StopSaleDate]
,[P].[Status]
  FROM [dbo].[DimProduct] AS [P]
    INNER JOIN [dbo].[DimProductSubcategory] AS [PSC]
      ON [PSC].[ProductSubcategoryKey] = [P].[ProductSubcategoryKey]
    INNER JOIN [dbo].[DimProductCategory] AS [PC]
      ON [PC].[ProductCategoryKey] = [PSC].[ProductCategoryKey]”,
null,
**[EnableFolding = true]**
)
in
RunSQL

请注意,我已经删除了查询末尾的分号。

这是必要的,因为在执行查询折叠时,Power query 会将此查询包含在外部查询中。

这意味着这种方法只适用于不在每个查询末尾强制使用分号的数据库引擎,如 SQL Server 和 Postgres 等。

现在本地查询选项是可用的,并且在添加转换后仍然可用。因此,这些转换被合并到源数据库中:

图 10 —修改 M 代码后获得原生查询(图由作者提供)

结论

当您访问数据库时,您应该知道查询折叠是如何优化数据加载性能的。

然后,一旦将一个源中的数据与另一个源中的数据组合起来,就应该注意转换的顺序,以便将尽可能多的转换推送到源数据库中。

如果你只有几千行也没关系。但是,一旦装载了数百万行,性能就变得至关重要。

如您所见,利用查询折叠的强大功能并不需要了解 SQL。只需查看查看原生查询的选项是否可用,或者不查看查询折叠是否发生。

当然,你可以开始学习 SQL,直接在查询时进行所有的转换。

你决定什么对你最好。

感谢您的阅读。

照片由乔恩·泰森Unsplash 上拍摄

参考

有关超级查询和查询折叠如何工作的详细信息,请参阅以下资源:

一定不要错过@Nikola Ilic 关于查询折叠的文章。

我使用 Contoso 样本数据集,就像我以前的文章一样。数据集可以在 MIT 许可下自由使用,如这里的所述

下载链接在这里:从微软官方下载中心下载面向零售业的微软 Contoso BI 演示数据集。

或者,您可以使用 SQLBI 的工具 Contoso 数据生成器来生成 Contoso 数据集的副本。

https://medium.com/@salvatorecagliari/membership

探索推荐系统:矩阵分解和深度学习模型综述

原文:https://towardsdatascience.com/exploring-recommendation-systems-review-of-matrix-factorization-deep-learning-models-74d51a3b4f20

推荐系统概述(替代最小二乘法、LightFM、神经网络矩阵分解和神经协同过滤)

朱莉安娜·马尔他在 Unsplash 上拍摄的照片

1.介绍

在社交媒体网络上,有大量的半结构化数据。这项任务的数据集是从在线照片分享社交媒体网络 Flickr 上收集的。Flickr 允许用户分享照片并与其他人(朋友)交流。目标是向访问这个社交媒体平台的大量数据的每个用户推荐一个对象(图片)列表。训练数据集包含用于构建推荐系统的用户和项目(照片)之间的一组交互,并且包含评级的基本事实的验证数据被用于决定最终模型。除测试数据外,其余数据集不用于分析。

2.推荐系统

显式反馈是按特定比例排列的评级。大多数等级从 1 到 5 不等。隐式反馈以不同的形式收集,例如浏览、屏幕时间、点击、反应、查看等。,而明确的反馈是评级。当用户对一个事物的评价高于另一个时,它表达了他们的偏好。另一方面,用户的行为暗示了隐性反馈。“如果用户经常点击/查看/花费时间/对某个项目做出反应,这是他/她的兴趣的标志,”这是隐式反馈的基本思想。

显式反馈很简单,因为用户的评估可以很容易地理解为用户的偏好,使系统的预测更相关。然而,它远不如隐式反馈常见,因为用户不方便对他们交互的所有内容进行评分(他们很少这样做)。在巨大的数量中,隐式输入很容易收集。在这种情况下,评级列可以被认为是隐式反馈,因为它表示用户是否与项目交互。训练数据仅由 1 组成,表明所有可能的用户和项目组合都有交互。因此,我们将使用基于隐式的推荐系统作为初始模型。

2.1 矩阵分解

矩阵分解将一个大矩阵分解成两个乘积等于原矩阵的小矩阵。交替最小二乘法是一种矩阵分解,它将用户项目矩阵的维数减少到相当少的潜在或隐藏属性。它以非常高效的计算方式做到了这一点。

2.1.1 交替最小二乘法(ALS)

替代最小二乘法是一个迭代优化过程,每次迭代的目的是创建原始数据的良好分解表示。让我们考虑一个大小为 u x i 的矩阵 R ,其中 u 代表用户, i 代表一个项目。其思路是生成一个表示为Uxf矩阵 U 其中 f 表示隐藏特征,一个表示为fx I 的矩阵 V 。矩阵 UV 由用户和物品如何与每个特征相关的权重组成。因此,如上所述,想法是计算 UV 使得(Victor,2018)。

使用最小二乘法随机分配 UV 中的值,并且经过几次迭代,获得产生 R 的最佳近似值的最佳权重。对于交替最小二乘法,使用类似的想法,但是迭代优化 U 保持 V 固定,反之亦然。解决方案是合并一个项目的偏好 p 与置信度 c 其中用户 u 对项目 i 的偏好定义如下其中为用户对项目的未观察值(胡等 2008)。

配方一。偏好计算。作者使用 Jupyter 和 Latex 制作的图像。

信念与不同的置信水平相关联。0 值的𝑝ᵤᵢ与低信心相关联。用户没有对一个项目采取积极的行动可以归因于多种因素,而不是他们不喜欢它。同样,如果一件商品被消费,也不一定表明用户对它的偏好。

图一。说明了用于 ALS 模型的成本函数。图片由作者使用 MS Word 编写。包括围绕成本函数和正则化的讨论的快照,以表示相关的公式。

模型评估指标

归一化贴现累积收益(NDCG) —使用以下断言衡量推荐的质量(Mhaskar,2015):

  • 大多数相关结果比稍微相关的结果更有用,并且排序的结果独立于归一化
  • 如果相关结果出现在推荐列表中的较高位置,它们会更有用

配方二。 NDCG 的计算。作者使用 Jupyter 和 Latex 制作的图像。

贴现累积收益(DCG) —在推荐列表中出现在较低位置的相关文档受到惩罚,因为分级相关性值与结果的位置成对数比例地减少(Mhaskar,2015)。

三级方程式。 DCG 的计算。作者使用 Jupyter 和 Latex 制作的图像。

在前 15 项推荐中被正确分类的验证项目 —验证数据的想法是检查在使用用户和项目 id 时由 ALS 模型(根据训练数据训练)推荐的前 15 项是否来自包含用户交互的项目的验证数据,即来自验证数据的基本事实。在验证数据中,每个用户至少与一个项目有一次交互。因此,对于每个用户 id,我们取推荐的项目 id 和地面真值= 1 的项目 id 的交集,然后计算交集不为 0 的用户数量。我们可以将验证数据中正确预测的相互作用数量较多的模型视为最佳模型。

2 . 1 . 3 ALS 的超参数调谐和输出

因子(5,10,12,15,20)正则化(0.1)和 alpha (10,15,20 和 25)值的不同组合用于训练模型,然后在验证数据上进行测试,以分析 NDCG 并纠正项目的分类。结果如图 1 和图 2 所示。测试了 24 种不同的超参数组合(例如,下图中的 x 轴代表因子-正则化-α)。

图二。从具有前 15 分的超参数验证数据中正确推荐的项目。具有最高 NDCG 分数的前三个参数用于产生测试建议并在 Kaggle 上验证。

图 3 。来自验证数据的推荐项目的 NDCG 分数,跨具有前 15 分的超参数。

2.2 LightFM

Light FM 是一个针对隐式和显式反馈的开源推荐系统。使用 LightFM 创建的嵌入可以编码关于特性的有用语义信息,这些信息可以用于推荐任务。LightFM 模型的结构考虑了以下因素:

该模型能够使用交互数据来学习用户和项目表示。如果用户喜欢不止一个项目,例如薯条和可乐,模型必须知道这两个项目是相似的。针对新用户和项目的模型扫描计算建议(Maciej & Lyst,2015 年)

图 4。说明了用于 LightFM 模型的目标函数。图片由作者使用 MS Word 编写。包括围绕优化目标函数的讨论的快照,以表示相关的公式。

四个损失函数可用于 LightFM 逻辑损失函数、BPR 或贝叶斯个性化排序成对损失。弯曲或加权近似秩成对损失和 k-OS 弯曲或 k 阶统计损失。

LightFM 模型对训练数据的输出在下面的表 1 中给出(库拉,2016)。

表 1。使用 BPR、WARP 和 k-OS WARP 对训练数据建模验证指标和各自的分数。

2.3 用神经网络进行矩阵分解

矩阵分解将用户和项目描绘成潜在特征的向量。这些特征被投影到一个共享的特征空间中,并从项目评级模式中推断出来。如果项目和用户之间的对应度高,则考虑向量 qᵢ ε Rᶠ 。对于一个给定的项目I,qᵢ的元素衡量一个项目使用这些因素的好坏和程度。如果我们考虑一个用户 u ,那么 pᵤ 测量用户对相应因素高的项目的兴趣程度。 qᵢᵗ.的点积 pᵤ 捕捉用户和物品的互动——用户对物品特征的整体兴趣。用户 u 对项目 i评分用rᵤt23】表示,等于 qᵢᵗ.pᵤ 为了学习因子向量( pᵤ & q ᵢ),已知评级集合上的正则化平方误差被最小化(Koren 等人,2009)。

公式 4。误差函数。作者使用 Jupyter 和 Latex 制作的图像。

图五。说明了使用神经网络的矩阵分解模型的训练功能。图片由作者使用 MS Word 编写。包括围绕优化目标函数的讨论的快照,以表示相关的公式。

2.4 神经协同过滤

神经协同过滤(NCF)捕捉用户和项目之间的交互。NCF 使用多层模型来学习用户和项目的交互功能。输入由用户 u (vᵤ) 和项目 i (vᵢ) 的稀疏特征向量组成,输出表示为(yᵤ)=f(pᵤ,q)。输入向量可以包括分类变量,如属性或上下文,而不仅仅是用户或项目。嵌入层由用户和项目潜在向量组成。神经协同过滤层由多个隐藏层组成,其中用户和项目潜在向量被连接。接着是多层感知器层,ReLU 作为激活函数,最后是输出层。多层感知器使用非线性函数来学习潜在因素不独立的交互作用,并且使用具有更好表示能力的数据来学习交互作用函数。

图 6。NCF 框架的例子。该图摘自何湘南的演示文稿,由作者重新设计。

公式 5。神经网络架构。作者使用 Jupyter 和 Latex 制作的图像。

图 7 。使用 20 个时期的 NN 使用不同模型的训练损失。

对于使用 Pytorch 的神经网络模型,使用不同的权重值、学习速率、时期和权重衰减来检查模型性能的改进。

3.模型比较

下表(表 2)提供了不同模型及其推荐准确度的概要。

表 2。展示了实现的模型、它们的用例以及验证指标。

4。结论

从分析中可以得出以下结论:

  1. 具有超参数因子α、正则化为 10、20 和 0.1 的隐式 ALS 模型为验证和测试数据产生最佳 NDCG
  2. 对于使用神经网络(NN)和神经协同滤波的矩阵分解(MF ),输出被认为是差的
  3. 神经网络模型易受初始权重、正则化、学习速率和权重衰减的影响,需要更多的微调以获得更好的输出
  4. 使用 NN 向 MF 添加偏差提高了模型性能。这可以归因于模型的更好的概括能力,允许它捕捉观察到的信号。有偏见的 MF 可以受益于对用户行为的洞察
  5. 内积函数的选择会限制模型的表达能力,较高的潜在因子会降低泛化能力
  6. 何等人 2017 年进行的一项研究表明,如果堆叠更多的非线性层,更深的网络模型可以产生良好的性能。然而,当增加太多层时,优化困难会减少改进
  7. 神经协同过滤模型观察到由于线性层的堆叠而导致的性能下降

在验证上具有最高 NDCG 分数的隐式 ALS 模型一起在训练和验证数据上被重新训练。从验证数据中保留的用户和交互项目被添加回训练数据。然后,使用上述参数的 ALS 模型(隐式 ALS —因子= 10,reg = 0.1,alpha = 20)用于产生最终建议。数据越多,测试集的性能越好。

5.参考

1.y .科伦、r .贝尔和 c .沃林斯基(2009 年)。推荐系统中的矩阵分解技术。计算机,42(8),30–37。https://doi.org/10.1109/mc.2009.263

2.胡,科伦,杨和沃林斯基(2008)。隐式反馈数据集的协同过滤。2008 年第八届 IEEE 数据挖掘国际会议。https://doi.org/10.1109/icdm.2008.22

3.维克多。(2018 年 7 月 10 日)。ALS 隐式协同过滤。中等。https://medium . com/radon-dev/als-implicit-collaborative-filtering-5ed 653 ba 39 Fe

4.m .库拉(2016 年)。模型评估— LightFM 1.15 文档。Making.lyst.com。https://making.lyst.com/light FM/docs/light FM . evaluation . html

5.马切伊,k .,& Lyst。(2015).用户和项目冷启动推荐的元数据嵌入。https://arxiv.org/pdf/1507.08439.pdf

6.何,谢,廖,李,张,洪,聂,李,胡,谢,蔡东生(2017)。神经协同过滤。ArXiv:1708.05031 [Cs]。https://arxiv.org/abs/1708.05031

关于作者:高级分析专家和管理顾问,帮助公司通过对组织数据的商业、技术和数学的组合找到各种问题的解决方案。一个数据科学爱好者,在这里分享、学习、贡献;你可以和我在 上联系 上推特

使用 OpenStreetMap 的道路网络和街区

原文:https://towardsdatascience.com/exploring-road-networks-and-neighborhoods-with-openstreetmap-3e133becb60d

使用社区检测和 K 均值聚类等常用聚类算法,通过 OpenStreetMap 工具确定新加坡的社区

照片由 shawnangggUnsplash 上拍摄

邻里是我们生活、工作和玩耍的地方,已经成为我们身份不可或缺的一部分。街区是由各种自然和人为因素形成的,包括历史、文化、政治、人口和地理。

那么,我们如何区分社区呢?道路网络让我们能够逆向工程城市规划者如何组织社区并在它们之间划定界限。这种方法在调查城市地区的社区时特别有用,因为城市地区的连通性更高,交通网络更密集(因此有更多的节点)可供我们分析。

在这篇文章中,我们旨在研究新加坡这个城市国家的道路网络是如何影响邻里组织的。新加坡是一个东南亚小国,也是世界上城市化程度最高的城市之一。自独立以来,已经进行了大量的城市规划来发展城市,社区已经成为高度连接的微观经济,居民可以方便地获得他们的服务和设施。这极大地影响了道路网络的结构

首先,我们可以使用 OSMnx Python 包从 OpenStreetMap (OSM)导入数据,以便下载可驾驶的城市网络。我们可以用叶子来可视化下载的路网。

图 1:新加坡的道路网(使用薄层绘制,图片由作者提供)

上面的道路网络被表示为一个图形,它是节点和边的集合。被定义为节点(或点)和边(点之间的连接/关系)的集合。在地理空间环境中,每个节点表示交叉点或弯曲处,边将节点连接在一起形成道路。每个节点(或地图上的点)还包含纬度和经度等属性,为我们提供节点和边在地图上的位置。

使用我们的图,我们现在可以使用图聚类,使用我们将在以下段落中探索的一些常见算法,将地理上和结构上彼此更接近的节点和边分组。

社区检测

我们要试验的第一种聚类方法是 Louvain 社区检测方法,在划分一个图后最大化模块性(参见本文的这里的)。这种优化算法将一个图(或网络)分割成更紧密连接的社区,并且以一种相当有效的方式来完成。

在我们的分析环境中,社区检测是一种根据网络的结构特征将道路网络分成社区的方法,而不是使用坐标。我们断言,与邻里之间(通常由主干道或高速公路连接)相比,邻里之间将有更密集的(即连接更紧密的)道路网络,这种结构差异将允许我们筛选出我们的个体社区。

为了可视化不同的聚类(即邻域),我们可以将节点(交叉点或弯曲点)绘制到 OSM 图上。不同的颜色代表不同的集群,总共有 10 个集群。

图 2:使用社区检测识别的集群(Tuas 检查站的最后一个粉色集群,几乎不可见)(图片由作者提供)

k 均值聚类

我们在这里使用的 K-means 聚类算法利用节点的坐标来确定它们属于哪个邻域。首先,我们确定聚类的数量。此后,该算法通过最小化成本函数(惯性)来选择质心,以确保簇内的节点尽可能彼此靠近。更多信息,你可以在这里阅读

在我们的例子中,K-Means 聚类是一种从地理上(而不是结构上)确定我们的聚类的方法。街区通常被某些地理特征所分隔。在新加坡,这些可能是雨林、水体或空军基地。此外,邻域内的节点也可能在地理上彼此更接近。为了使用我们之前的方法进行标准化,我们将集群的数量预设为 10。

图 3:使用 K 均值聚类识别的聚类(图片由作者提供)

结果

这两种聚类方法产生了非常相似的结果,并且与当今新加坡的实际社区非常吻合。这是新加坡的区域划分图。

图 4:基于各自市议会的新加坡社区(图片来自维基媒体)

从上图中可以看出,我们的聚类算法很好地反映了新加坡的社区,并且可以很好地衡量我们应该如何根据社区之间的物理连接程度来区分不同的社区。

比较这两种不同的方法,我们看到使用 K-Means 聚类的邻域之间的分裂要整齐得多,因为更关注节点之间的地理差异。然而,社区检测方法有时可以更准确地反映邻域,因为邻域不能总是被直线分开。

我希望这是地理空间数据分析、聚类和数据可视化的一次有趣尝试。要查看本文中使用的代码,请单击此处的。

参考资料:

探索 SageMaker 画布

原文:https://towardsdatascience.com/exploring-sagemaker-canvas-8df0a90b977e

无代码机器学习

图片来自桑迪·克拉克拍摄的 Unsplash

构建机器学习模型需要知识、经验和大量时间。有时,不同的角色,比如业务分析师或其他没有 ML 经验的技术专家,可能有他们想要解决的 ML 用例,但是缺乏这样做的专业知识。即使是有 ML 经验的 ML 工程师和数据科学家也可能希望快速建立一个模型。

这就把我们带到了汽车的领域。如今,我们看到了大量的 AutoML 解决方案,从开源 API 到面向自动化 ML 空间的个人服务/平台。 SageMaker Canvas 完全从 ML 中移除了代码方面,您将在本文中看到。一切都是从可视界面完成的,我们将在本文中探索一个如何使用 Canvas 的基本示例。

画布支持什么?

目前,Canvas 支持以下数据类型 : 分类、数值、文本日期时间。这意味着您可以主要在表格时间序列域内工作,对于您的 ML 用例,目前不支持计算机视觉/图像数据。

这里的另一个要点是,唯一支持的文件格式是 csv 。您的 csv 文件必须来自以下外部数据源 : S3 桶红移数据库雪花。您还可以允许您的用户将本地文件直接上传到 Canvas。对于这个例子,我们将使用我们已经上传到 S3 桶的数据集。

SageMaker 画布示例

要设置 SageMaker Canvas,您需要创建一个 SageMaker 域。这和与 SageMaker 工作室合作的过程是一样的。最简单的入职方式是使用快速设置,您可以在下面的文档中找到。

设置完成后,您应该会看到刚刚创建的用户。点击“启动应用程序”,将会打开一个画布选项。

画布选项(作者截图)

这个应用程序应该在几分钟内启动,您将能够看到用户界面。

画布 UI(作者截图)

现在我们可以开始我们的示例画布工作了。对于这个例子,我们将采用流行的虹膜数据集。请注意,您可能需要一个大版本的 this dataset ,因为使用 Canvas 的标准构建需要 500 行和至少2 列

单击数据集图标,您可以访问 S3,在那里您已将数据集上传到一个桶中。

上传数据集(作者截图)

上传数据集后,您应该能够在数据集选项卡中看到它。Canvas 的一个很大的特点就是你可以上传多个数据集进行建模。Canvas 支持不同的 SQL join 语句,无需编写任何实际的 SQL 代码。如果您有该场景的相关用例,请查看文档这里

上传的数据集(作者截图)

我们现在将着手建立一个模型。第一步,我将选择我的目标数据集。

选择数据集(作者截图)

使用这个目标数据集,我们可以转到 Build 选项卡。在这里,我们可以查看不同的自动化可视化/EDA。我们可以看到不同的统计数据,如缺失数据唯一值特性重要性,这些通常需要 pandas、sklearn 或不同的包代码来分析。

自动化分析(作者截图)

在这里,我们还可以删除与我们的模型不一定相关的列,比如 ID 列。这反映在将用于烘焙模型的模型配方中。

降栏(作者截图)

我们还可以得到特征值分布的图形表示。

数据分布(作者截图)

最后,我们还可以过滤数据集。假设我们想要查看特定列中高于某个阈值的所有值。我们可以通过在 filter 选项卡中输入我们的值来进行调整。

过滤值(作者截图)

现在,我们已经花时间了解了我们的数据,我们可以单击“模型构建”。这里有两个选项:快速建造标准建造。快速构建需要2-15 分钟,这将尽可能快地迭代给你一个现成的模型。标准构建将花费几个小时,但是范围要大得多。它还为您提供了不同型号、度量分数和培训工作等信息。因为我们想要更大的可见性,我们将继续进行标准构建,一旦完成,您的屏幕应该如下所示。

标准构建完成(作者截图)

如果我们点击“与 SageMaker Studio 共享”,我们应该能够创建一个 SageMaker Studio 链接,我们可以复制并粘贴该链接以获得有关我们画布作业的更多信息。

在这里,我们可以看到我们使用的最佳模型和输入数据集。

工作室链接(作者截图)

如果我们单击输入数据集旁边的 AutoML Job,我们可以看到 Canvas 在幕后使用的所有模型列表。

模型画布训练(作者截图)

如果我们单击我们的最佳模型,我们可以看到不同的参数,如使用的算法/模型。

用于最佳模型的算法(作者截图)

我们可以看到,数据集的最佳算法是 SageMaker XGBoost 算法。我们还可以进一步了解模型最适用的不同超参数。

我们还得到了一个 Performance 选项卡,其中包含我们的分类问题的度量和混淆矩阵。

困惑矩阵(作者截图)

如果我们想要完全的可见性,我们可以看看 Studio 链接中的工件选项卡。这提供了诸如特征工程脚本模型数据文件的资源,如果你感兴趣的话,你可以自己打开并使用它们。

如果我们返回到 SageMaker Canvas UI,我们可以使用批量推断单个数据点来执行预测

单项预测(作者截图)

其他资源和结论

如果你想在 ML 中完全删除图片中的代码,SageMaker Canvas 是一个很好的起点。我很高兴看到这项服务带来的未来功能,因为它将作为一个新的发布继续扩展。同时,查看画布上的官方 AWS 博客了解更多信息。如果您对 SageMaker 更灵活的 AutoML 选项感兴趣,请查看 SageMaker JumpStart

我希望这篇文章是 SageMaker Canvas 的良好入门。请随意留下任何反馈,并查看我在以下列表中的其他 SageMaker/AWS 文章。

如果你喜欢这篇文章,请在LinkedIn上与我联系,并订阅我的媒体 简讯 。如果你是新手,使用我的 会员推荐 报名。

探索人类对常见事物知识的特征空间

原文:https://towardsdatascience.com/exploring-the-feature-space-of-human-knowledge-about-common-objects-e86940c1638a

人脑能够将日常生活中生动感知的事物和瞬间加工成抽象的概念和语义知识

作者图片

理解人类知识的本质一直是心理学的一个中心问题,对于人工智能领域也具有理论和实践意义。人类知识的一个关键特征是其结构化的性质,这使得新的信息片段(例如,一个人第一次看到的植物)可以通过将其整合到现有的类别(兰科- >芦苇属)中而被有效地学习。同时,这些类别是建立在人们随着时间的推移已经经历的具体信息(例如,不同的兰花种类)上的。

我们如何对语义知识进行定量理解?一种方便的方法是以无监督的方式从大的文本语料库中计算单词嵌入(例如,word2vec、GloVe ),但是完全理解嵌入空间的含义仍然是一个挑战。另一种方法,具有更好的可解释性(尽管更加劳动密集型),是从人类参与者那里获得概念的描述/标签。标记概念的结构化数据集可以用属于每个单独概念的可解释语义属性列表来管理。最近在这一领域的努力包括我目前工作的研究小组的工作(见我们的论文,由 Mariam Hovhannisyan 牵头:https://link . springer . com/article/10.3758/s 13421-020-01130-5)(如果你有进一步的兴趣,也可参见麦克雷小组的精彩作品https://sites.google.com/site/kenmcraelab/contact)。

在我们小组的研究中,566 名参与者在亚马逊机械土耳其人平台上被招募来执行关于 995 个物体概念的描述任务。对于每个物体,参与者都被展示了该物体的样本图像,并被提示使用下拉菜单和文本框来标记/描述 5 个独特的特征。然后,所有参与者的回答按对象进行汇总,这导致了对所有对象特征的 5559 个独特描述。换句话说,每个对象可以被视为位于一个 5559 维语义特征空间中的某处。此外,每个对象还被手动分类为 29 个类别中的一个,以及生物或非生物领域。

对象描述任务的示例试验。资料来源:Hovhannisyan 等人,2021,《记忆与认知》。https://doi.org/10.3758/s13421-020-01130-5CC-BY 4.0

在下文中,我将首先给出数据集的简要概述,然后讨论不同对象之间相似性的可视化和量化。

1。对 995 个现实世界对象的人类知识的结构化描述

该数据集可在开放科学基金会网站上公开获得(【https://osf.io/49zej/】T2)。请注意,数据集还包括对象图像,这可能会引起某些专业知识涉及人类/计算机视觉的读者的兴趣。对于当前的分析,我们将只关注语义特征。

下面是数据框架的一部分。“功能”列中的数字(从第 5 列开始)表示某个功能为给定对象命名的总次数。例如,木吉他被 28 位参与者描述为“木头做的”。

作者图片

这是每一类物品的数量分类。对象最多的类别包括工具、衣服、家具、哺乳动物、车辆和食物。

每个类别中的对象数量。作者图片

接下来,让我们看看电子表格中值的分布。一些事情可能是感兴趣的:1)一个特征被提及/描述了多少次(特征频率);2)多少对象共享给定特征(特征流行度);3)特征频率和患病率的联合分布;4)一个物体通常具有的特征的数量。

从上面的图中可以观察到:1)一个特征最有可能在所有参与者和所有对象中被描述 1000 次;2)一个特征很少存在于超过 200 个不同的对象中;3)一个特征被描述得越频繁,它在多个对象中存在得越普遍;4)大多数物体具有大约 20~60 个独特的特征。

2。测量对象和类别之间的语义相似度

现在,我们探索属于同一类别的对象在特征空间中是否会更相似。首先,我们将每一行特征描述视为一个表示对象的向量。然后,我们使用余弦距离来定义两个对象之间的相似性。对于分别具有特征向量 XY 的两个对象,它们之间的距离将是:

为简单起见,特征向量被二进制化,意味着 XY 中的条目将是 1 或 0(指示特征是否存在)。

然后,我们可以将两个类别 AB 之间的距离定义为给定两个类别中对象之间的平均距离:

最后,让我们将类别显著性定义为类别之间的平均余弦距离除以每个类别内的平均距离。显著性越大于 1,这些类别之间的区别就越明显。换句话说,该独特性值捕获了与其他类别中的对象相比,相同类别中的对象有多相似。

类别级相似度矩阵如下所示。注意,类别内距离(相同类别中对象之间的平均距离,表示为矩阵中的对角线条目)小于类别间距离(不同类别中对象之间的平均距离,表示为矩阵中的非对角线条目),这意味着相同类别中的对象在其语义特征上更相似。此外,视觉上很明显,生物类别与其他生物类别更相似(在右下方形成一个更暗的正方形),而非生物类别与其他非生物类别更相似(在左上方形成另一个更暗的正方形)。类别显著性(=1.21)和领域显著性(=1.08)都在 1 以上,进一步支持了视觉直觉。

类别之间的特征距离。较冷的颜色表示距离较低,即相似性较高。作者图片

在继续之前,执行数据清理以降低特征空间的维度。如第一部分所示,大多数特征很少被参与者一致描述,也很少在对象间共享,这意味着它们在描述对象时不是很有用。为了简单起见,我们排除了被提及少于 25 次的特征,以及存在于少于 5 个对象中的特征。这种方法将特征维数从 5559 急剧减少到 655。此外,有几个对象被丢弃是因为它们很少(<5) features or belong to categories of very limited size (‘baby’ and ‘reptile-amphibian’).

将特征数量限制为 655 后类别之间的特征距离。作者图片

We can see that the ‘cleaned’ feature space has higher categorical and domain distinctiveness (=1.31 and 1.12, respectively). This is perhaps because eliminating uncommon features reduced the uniqueness of each object and emphasized the commonalities between them.

3。使用降维可视化对象的分类身份

高维数据不能被直接可视化,除非它被转换到一个低维空间,那里的维数通常是 2 或 3。有许多不同的降维算法,而最著名的可能是主成分分析(PCA)。但是,PCA 基于协方差方法,最适用于连续和正态分布的数据。由于对象的特征向量是二元的(对象将具有或不具有某个特征),PCA 可能不是使用的理想方法。相反,我们使用 t-SNE 来降低数据集的维度。

来自维基百科的以下文字解释了 t-SNE 的工作原理:“t-分布式随机邻居嵌入(t-SNE) 是一种通过在二维或三维地图中给每个数据点一个位置来可视化高维数据的统计方法。”“这是一种非线性降维技术,非常适合在二维或三维的低维空间中嵌入用于可视化的高维数据。具体来说,它通过一个二维或三维点对每个高维对象进行建模,相似的对象通过附近的点进行建模,不相似的对象通过远处的点进行建模的概率很高。t-SNE 算法包括两个主要阶段。首先,t-SNE 在高维对象对上构建概率分布,使得相似的对象被分配较高的概率,而不同的点被分配较低的概率。第二,t-SNE 定义了低维地图上的点的类似概率分布,并且它最小化了关于地图上的点的位置的两个分布之间的 kull back-lei bler 散度(KL 散度)

我们现在将所有对象的特征向量(或特征矩阵𝑋X)馈送到 t-SNE 中,并获得特征空间的低维嵌入(𝑋_𝑒𝑚𝑏𝑒𝑑𝑑𝑒𝑑X_embedded ):

二维嵌入的输出可视化:

用 t-SNE 嵌入表示的物体相似性。作者图片

万岁!上面的图清楚地表明了低维空间的存在,在这些低维空间中,对象就其类别而言是可分的。

然而,有一个警告:t-SNE 不能提供从原始特征空间到低维空间的映射。这是有问题的,例如,当我后来获得一些新物体的特征向量时。在这种情况下,不能使用现有的方程或参数将这些新对象直接放入现有的二维图中。相反,人们需要将新的向量放入旧的数据集中,并再次运行 t-SNE 算法,这非常耗时,并且限制了 t-SNE 在这里的应用。那么,除了 PCA 和 t-SNE,有没有另一种降维算法更适合这个数据集,也能够提供原始特征空间和低维空间之间的显式转换?事实证明,受限玻尔兹曼机(RBM),一种具有可见单元和隐藏单元的神经网络,可能是一种合适的算法。当隐藏单元的数量小于可见单元的数量时,RBM 用作降维算法。下图显示了隐藏单元(维数=75)激活的 2D t-SNE 嵌入,其中可见单元接收 655 维特征向量作为输入。有趣的是,分类的区别不仅通过降维得以保留,而且变得更加突出。

RBM 隐藏单元激活编码的对象相似性,在 t-SNE 嵌入中可视化。作者图片

在这个数据集中,RBM 有更多的技术细节和有趣的行为,超出了故事的范围,我可能会在后续文章中谈到它们。敬请期待:)

结论

现实世界对象的概念可以通过它们的特征来标记,并在数学上表示为二进制特征向量。这种结构化描述允许我们通过将不同对象视为线性空间(即特征空间)中的点并分析它们之间的距离来测量它们的相似性。特征空间揭示了不同对象之间的分类区别。使用降维技术,我们可以在二维图中可视化这种分类差异。

使用 DAX 函数探索过滤器上下文

原文:https://towardsdatascience.com/exploring-the-filter-context-with-dax-functions-422211c1118e

在查看当前过滤器上下文时,您可以在 DAX 中找到几个有用的函数。以下是这些功能的一些例子

照片由冉贝尔科维奇Unsplash

我们将研究哪些 DAX 函数?

有几个 DAX 函数可以查看当前的过滤器上下文。

在本文中,我们将研究以下函数(按字母顺序排列):

  • 全部选定
  • 过滤
  • HASONEFILTER
  • HASONEVALUE
  • ISCROSSFILTERED
  • 被过滤
  • ISINSCOPE
  • 选定值

我将提供一个链接,链接到 DAX Guide 上的相应文章,以及关于如何使用它们以及它们如何相互比较的每个函数的例子。

什么是过滤器上下文?

如果你已经知道过滤器的内容,请跳到下一章。

一句话:

过滤器上下文是影响计算结果的所有过滤器的总和

在下图中,您可以看到标记单元格上的筛选器上下文由以下值组成:

  • 制造商= Contoso 有限公司和 Fabrikam 公司
  • 国家=美国
  • 年份= 2008 年
  • 类别=计算机
  • 月份=六月

图 1 —过滤上下文(作者提供的图片)

在浏览过滤器上下文时,您希望检查过滤器是否存在,以及过滤器在一列上的内容是什么。

这就是这里提到的函数的用途。

基本查询

对于本文,我将在 Contoso 数据模型上使用以下 DAX-Query:

DEFINE
 VAR FilterTable = 
      TREATAS({2008}, ‘Date’[Year])

EVALUATE
  CALCULATETABLE(
    FILTER(
      ADDCOLUMNS(
         SUMMARIZECOLUMNS(‘Geography’[Region Country]
                          ,’Geography’[City]
                          ,’Store’[Store])
                          ,”Online Sales (By Order Date)”
                                ,[Online Sales (By Order Date)]
                  )
              ,NOT ISBLANK([Online Sales (By Order Date)])
            )
            ,FilterTable
          )

ORDER BY
 ‘Geography’[Region Country],
 ‘Geography’[City],
 ‘Store’[Store]

下图显示了 DAX Studio 中该查询的结果:

图 2 —基本查询的结果(作者提供的图)

全部选定

ALLSELECTED() 用于获取列中所有值的列表,同时考虑所有外部过滤器,但不考虑查询中现有的过滤器。

现在,我向基本查询添加两个度量:

[CountOfCountries] = COUNTROWS(
                          ALLSELECTED(
                                ‘Geography’[Region Country]
                                )
                             )

[CountOfYears] = COUNTROWS(ALLSELECTED(‘Date’[Year]))

通过这两个度量,我可以计算 ALLSELECTED()为每一列返回多少行。

请记住:

  • 结果中的每一行都有一个国家
  • 使用 FilterTable 变量过滤年份

下面是修改后的查询(ORDER BY 被省略):

DEFINE
 MEASURE ‘All Measures’[CountOfCountries] =
                        COUNTROWS(
                            ALLSELECTED(
                                  ‘Geography’[Region Country]
                                  )
                                )

 MEASURE ‘All Measures’[CountOfYears] =
                       COUNTROWS(ALLSELECTED(‘Date’[Year]))

 VAR FilterTable = 
    TREATAS({2008}, ‘Date’[Year])

EVALUATE
  CALCULATETABLE(
    FILTER(
      ADDCOLUMNS(
         SUMMARIZECOLUMNS(‘Geography’[Region Country]
                          ,’Geography’[City]
                          ,’Store’[Store]
                      )
                      ,”Online Sales (By Order Date)”
                          ,[Online Sales (By Order Date)]
                      ,”CountOfCountries”
                          ,[CountOfCountries]
                      ,”CountOfYears”
                          ,[CountOfYears]
                    )
               ,NOT ISBLANK([Online Sales (By Order Date)]
               )
           )
           ,FilterTable
)

该查询返回以下结果:

图 ALLSELECTED()的查询结果(作者提供的图)

为什么我们会看到这样的结果?

该查询选择一年,每行只有一个国家。

这个问题的关键是在线文档中的这句话:

ALLSELECTED()从当前查询的列和行中删除上下文过滤器,同时保留所有其他上下文过滤器或显式过滤器。

因此,ALLSELECTED()返回 34 个国家,认为 Region Country 列上的实际筛选上下文是内部的。但是查询只返回一年,因为这一年的筛选器被视为“外部”筛选器。

让我们尝试一些不同的东西。

请看下面的查询:

DEFINE
 MEASURE ‘All Measures’[CountOfCountries] =
                        COUNTROWS(
                           ALLSELECTED(‘Geography’[Region Country]
                           )
                         )

 MEASURE ‘All Measures’[CountOfYears] =
                        COUNTROWS(ALLSELECTED(‘Date’[Year]))

 VAR FilterTable =
          TREATAS({2008}, ‘Date’[Year])

EVALUATE
  FILTER(
    ADDCOLUMNS(
       CALCULATETABLE(
                  SUMMARIZECOLUMNS(‘Geography’[Region Country]
                                   ,’Geography’[City]
                                   ,’Store’[Store]
                                   )
                       ,FilterTable
                   )
                   ,”Online Sales (By Order Date)”
                         ,[Online Sales (By Order Date)]
                   ,”CountOfCountries”
                         ,[CountOfCountries]
                   ,”CountOfYears”
                         ,[CountOfYears]
                  )
        ,NOT ISBLANK([Online Sales (By Order Date)])
        )

现在,我更改了将年份过滤器添加到 CALCULATETABLE() 中的过滤器上下文的顺序,用 FILTER() 括起来。

现在看看结果:

图 4 —用 ALLSELECTED()进行第二次查询的结果(图由作者提供)

为什么我们现在看到的是六年而不是一年?

我们必须看这两个度量在哪里被评估。

两者都在 CALCULATETABLE()函数中进行计算。

因此,ALLSELECTED()将由 CALCULATETABLE()注入的筛选器视为内部筛选器并将其移除。因此,CountOfYears 度量值返回 6。

当使用 ALLSELECTED()时,我们必须了解这个函数是如何工作的,以及它是如何操作过滤器上下文来返回结果的。

过滤

FILTERS() 函数返回一个表,其中包含当前过滤器上下文中指定列的过滤值。

我在基本查询中添加了一个新的度量[过滤的国家]:

DEFINE
 MEASURE ‘All Measures’[Filtered Country] =
                      FILTERS(‘Geography’[Region Country])— Parts omitted —EVALUATE
 CALCULATETABLE(
     FILTER(
         ADDCOLUMNS(
             SUMMARIZECOLUMNS(‘Geography’[Region Country]
                              ,’Geography’[City]
                              ,’Store’[Store])
                              ,”Online Sales (By Order Date)”
                                    ,[Online Sales (By Order Date)]
                              ,”Filtered Country”
                                    ,[Filtered Country]
                              )
                      ,NOT ISBLANK([Online Sales (By Order Date)]
                     )
             )
             ,FilterTable
             )

以下是查询的结果:

图 5 —使用过滤器()的查询结果(由作者提供)

现在,让我们看看在查询中添加以下度量时会发生什么:

[Filtered Months] = FILTERS(‘Date’[EnglishMonthName])

在这种情况下,我们会收到一条错误消息,指出在需要单个值的地方提供了一个包含多个值的表。

为什么?

因为我们只从日期表中筛选年,所以筛选器检测 12 个月,按年筛选。出于这个原因,我们从 FILTERS()中得到一个有 12 行的表。

当我们将测量值更改为以下值时:

MEASURE ‘All Measures’[Filtered Months] =
   CONCATENATEX(
          FILTERS(‘Date’[EnglishMonthName])
          , ‘Date’[EnglishMonthName]
          , ”, “
          )

我们得到所有过滤月份的列表:

图 6 —使用过滤器()的第二个查询的结果(由作者提供)

FILTERS()函数比 ALLSELECTED()简单得多,因为它使用当前的过滤器上下文,我们不必考虑内部和外部过滤器。

HASONEFILTER

HASONEFILTER() 函数只返回 TRUE 或 FALSE。

只要当前筛选器上下文只为一列返回一个筛选器,该函数就返回 TRUE。

让我们更改带有过滤器()的示例中的度量,以检查它是如何工作的:

MEASURE ‘All Measures’[Filtered Country] =
   HASONEFILTER(‘Geography’[Region Country])

MEASURE ‘All Measures’[Filtered Months] =
   HASONEFILTER(‘Date’[EnglishMonthName])

您可以在下图中看到这两种测量的结果:

图 7 —使用 HASONEFILTER()查询的结果(作者提供的图)

虽然列“Geography”[Region Country]在实际的筛选器上下文中只有一个筛选器,但 HASONEFILTER()返回 TRUE。但是,由于列“Date”[EnglishMonthName]在查询时不包含过滤器,因此结果为 FALSE。

让我们看另一个例子:

我将该年的筛选器更改为以下内容:

VAR FilterTable = 
 TREATAS({2007, 2008}, ‘Date’[Year])

并在 Year 列上添加一个带有 HASONEFILTER()的度量值。

结果看起来像这样:

图 8 —使用 HASONEFILTER 进行第二次查询的结果(作者提供的图)

由于我们在 year 列上引入了第二个过滤器,HASONEFILTER()返回 FALSE。

HASONEVALUE

当我们用 HASONEVALUE()替换 HASONEFILTER()时,会得到相同的结果。但是功能不同。

当 HASONEFILTER()检查过滤器是否存在时,HASONEVALUE()计算当前过滤器上下文中某一列的可用值。

我写过一篇关于如何使用 HASONEVALUE()的真实场景的文章:

ISCROSSFILTERED

对我来说, ISCROSSFILTERED() 是所有 DAX 函数中不太直观的一个。

如果指定的列或表是直接筛选的、由同一表中的另一列筛选的或由应用于相关表的筛选器筛选的,则 ISCROSSFILTERED()返回 TRUE。

当我们用 ISCROSSFILTERED()替换前面查询中的 HASONEVALUE()时,我们得到以下结果:

图 9 —用 ISCROSSFILTERED()查询的结果(作者提供的图)

这三个度量值都返回 TRUE。

原因是在查询中直接筛选了“年份”和“地区国家”列。但是“月”列是通过“年”列上的筛选器交叉筛选的。

阿尔贝托·法拉利在 https://dax.guide 的视频中做了很好的解释。

推荐看视频了解 ISCROSSFILTERED()的工作原理。

被过滤

ISFILTERED() 函数类似于 ISCROSSFILTERED()函数,但它仅在直接筛选列或表时返回 TRUE。

当我们用 ISFILTERED()替换 ISCROSSFILTERED()时,结果如下:

图 10 —使用 ISFILTERED()的查询结果(作者提供的图)

ISCROSSFILTERED()与 ISFILTERED()的区别在于,仅当给定的列或表被直接筛选时,is filtered()才返回 true。

由于 Month 列上没有显式筛选器,ISFILTERED()返回 FALSE。

ISINSCOPE

您可以使用 ISINSCOPE() 函数来检查和导航 DAX 中的层次结构,即使 DAX 没有层次结构的概念。

该函数使用一个技巧来确定层次结构在当前过滤器上下文中是否是活动的:

1.该函数检查指定列是否只有一个值

2.然后,它检查另一列中是否存在过滤器

ISINSCOPE()主要与summary zecolumns()函数一起工作。

例如,当给定的列由 SUMMARIZECOLUMNS()汇总时,ISINSCOPE()返回 true。

我将基本查询更改为以下查询:

DEFINE
 MEASURE ‘All Measures’[ISINSCOPE Country] =
                             ISINSCOPE(‘Geography’[Region Country])

 MEASURE ‘All Measures’[ISINSCOPE City] = 
                             ISINSCOPE(‘Geography’[City])

 MEASURE ‘All Measures’[ISINSCOPE Months] =
                             ISINSCOPE(‘Date’[EnglishMonthName])

 MEASURE ‘All Measures’[ISINSCOPE Years] =
                             ISINSCOPE(‘Date’[Year])

 VAR FilterTable = 
 TREATAS({2008}, ‘Date’[Year])

 EVALUATE
 CALCULATETABLE(
   FILTER(
     ADDCOLUMNS(
       SUMMARIZECOLUMNS(‘Geography’[Region Country]
                        ,’Geography’[City]
                        ,’Store’[Store])
                        ,”Online Sales (By Order Date)”
                                 ,[Online Sales (By Order Date)]
                        ,”ISINSCOPE Years”, [ISINSCOPE Years]
                        ,”ISINSCOPE Months”, [ISINSCOPE Months]
                        ,”ISINSCOPE Country”, [ISINSCOPE Country]
                        ,”ISINSCOPE City”, [ISINSCOPE City]
                        )
                 ,NOT ISBLANK([Online Sales (By Order Date)])
            )
           ,FilterTable
      )

该查询的结果如下:

图 11 —用 ISINSCOPE()查询的结果(由作者提供)

因为年份和月份不是按 SUMMARIZECOLUMNS()分组的,所以 ISINSCOPE 返回 FALSE,

而且,由于 Region Country 和 City 是按 SUMMARIZCOLUMN()分组的,因此 ISINSCOPE 对这两列返回 TRUE。

至于 ISCROSSFILTERED(),我推荐看一下 https://dax.guide 上对 ISINSCOPE()的描述,里面有一个视频,完整的描述了 ISINSCOPE()的工作原理。

选定值

我们可以使用 SELECTEDVALUE() 来检查一个列在当前过滤器上下文中是否正好包含一个值,以及我们拥有哪个值。

此外,如果没有值或多个值可见,我们可以传递一个替换值。

SELECTEDVALUE()类似于 HASONEVALUE()。但是 SELECTEDVALUE()返回实际值,而 HASONEVALUE()仅在当前筛选器上下文中只有一个值可见时返回 TRUE。

我复制了用于解释 HASONEVALUE()的查询,并将度量值更改为 SELECTEDVALUE()。我添加文本“Multiple Values”作为替换值的第二个参数。

你可以在下图中看到结果:

图 12 —带有 SELECTEDVALUE()的查询结果(作者提供的图)

如您所见,Years 和 Region Country 只有一个值,SELECTEDVALUE()返回这个值。

由于我们在当前筛选器上下文中有 12 个月(见上文),因此该月的 SELECTEDVALUE()返回替换值。

SELECTEDVALUE()非常强大,因为我们可以使用它从切片器甚至从实际查询中获取选定的值,并更改查询的行为。

结论

这里显示的所有函数对于导航过滤器上下文和确定其内容都是必不可少的。

如果没有这个函数,我们作为 DAX 开发人员的工作将会更加困难,因为我们将无法对查询中的过滤值做出反应。

在写这篇文章的时候,我学到了很多,因为我没有意识到这些函数的复杂性。

但是我希望这些描述可以帮助你更好地使用 DAX。

感谢阅读。

照片由龙之介·菊野Unsplash 上拍摄

参考

我使用 Contoso 样本数据集,就像我以前的文章一样。你可以从微软这里免费下载 ContosoRetailDW 数据集。

Contoso 数据可以在 MIT 许可下自由使用,如这里的所述

https://medium.com/@salvatorecagliari/membership

探索时间序列的 LSTM 神经网络模型

原文:https://towardsdatascience.com/exploring-the-lstm-neural-network-model-for-time-series-8b7685aa8cf

scalecast 库的实用、简单实现

作者图片

预测时间序列的最先进的模型之一是长短期记忆(LSTM)神经网络。根据 Korstanje 在他的书中所说,使用 Python 进行高级预测:

“LSTM 细胞以一种更有效的方式增加了长期记忆,因为它允许学习更多的参数。这使得它成为最强大的(递归神经网络)来做预测,特别是当你的数据中有一个长期趋势时。LSTMs 是目前最先进的预测模型之一,“ (2021)。

这是好消息。坏消息是,如果你在 TensorFlow 中使用过这个概念,你就会知道,设计和实现一个有用的 LSTM 模型并不总是简单的。网上有很多优秀的教程,但大多数都没有把你从 A 点(读取数据)带到 Z 点(从完成的模型中提取有用的、适当缩放的、未来预测的点)。我见过的很多教程在显示了训练过程中的损失图后就停止了,证明了模型的准确性。这是有用的,我感谢任何在这个问题上提供他们智慧的人,但这还不完全

还有一个办法。

https://github.com/mikekeith52/scalecast

scalecast 库托管 TensorFlow LSTM,可轻松用于时间序列预测任务。该软件包旨在消除实施时间序列预测的许多麻烦。它在引擎盖下使用 TensorFlow。以下是你应该尝试一下的一些理由:

  • 易于实施和查看结果,大多数数据预处理和后处理在后台执行,包括缩放、取消缩放和评估置信区间
  • 测试模型是自动进行的——模型一次适合训练数据,然后再次适合完整的时间序列数据集(这有助于防止过度拟合,并为比较许多方法提供了一个公平的基准)
  • 类似于 TensforFlow,在验证数据的每个训练时期验证和观察损失是可能的和容易的
  • 针对其他建模概念的基准测试,包括脸书预言家和 Scikit-learn 模型,是可能且容易的

还有一些你可能会远离的原因:

  • 因为所有的模型都适合两次,训练一个已经很复杂的模型会慢两倍
  • 您无法使用直接与 TensorFlow 合作所能提供的所有工具来干预模型
  • 对于一个鲜为人知的包,您永远不知道会出现什么不可预见的错误和问题

希望这能给你足够的时间来决定继续读下去是否值得。好了,让我们进入教程,你可以在这里找到笔记本形式的

数据预处理

首先,我们安装库:

pip install scalecast --upgrade

您还需要 tensor flow(Windows 版)或 tensor flow-MAC OS(MAC 版)。

pip install tensorflow

或者

pip install tensorflow-macos

接下来,让我们导入库并读入数据(可以在 Kaggle 上通过开放数据库许可获得):

import pandas as pd
import numpy as np
import pickle
import seaborn as sns
import matplotlib.pyplot as plt
from scalecast.Forecaster import Forecaster

df = pd.read_csv('AirPassengers.csv',parse_dates=['Month'])

该集合捕获了一家航空公司 12 年的月度航空乘客数据。它始于 1949 年 1 月,止于 1960 年 12 月。这是一个很好的预测数据集示例,因为它具有清晰的趋势和季节模式。我们来直观的看一下:

作者图片

探索性数据分析

要开始使用 scalecast 进行预测,我们必须首先调用指定了ycurrent_dates参数的Forecaster对象,如下所示:

>>> f = Forecaster(
>>>    y=data['#Passengers'],
>>>    current_dates=data['Month']
>>> )
>>> f

Forecaster(
    DateStartActuals=1949-02-01T00:00:00.000000000
    DateEndActuals=1960-12-01T00:00:00.000000000
    Freq=MS
    ForecastLength=0
    Xvars=[]
    Differenced=0
    TestLength=1
    ValidationLength=1
    ValidationMetric=rmse
    CILevel=0.95
    BootstrapSamples=100
)

让我们通过查看 PACF(部分自相关函数)图来分解这个时间序列,该图测量 y 变量(在我们的情况下,航空乘客)与它本身的过去值的相关程度,以及统计上显著的相关性存在多远。PACF 图与 ACF 图的不同之处在于,PACF 控制了过去各项之间的相关性。很高兴看到这两个,这两个都在我为这篇文章创建的笔记本中,但只有 PACF 将在这里显示。

f.plot_pacf(lags=26)
plt.show()

作者图片

从这个图中,看起来在数据中可能存在长达两年的统计上显著的相关性。这将是建模时使用的好信息。让我们进一步将该系列分解为趋势、季节和剩余部分:

f.seasonal_decompose().plot()
plt.show()

作者图片

我们在这个数据中看到了明显的线性趋势和很强的季节性。残差似乎也遵循一种模式,尽管不清楚是哪种模式(因此,为什么它们是残差)。

最后,让我们测试序列的平稳性。

>>> stat, pval, _, _, _, _ = f.adf_test(full_res=True)
>>> stat
0.8153688792060569
>>> pval
0.9918802434376411

检查序列的平稳性很重要,因为大多数时间序列方法不能有效地模拟非平稳数据。“非平稳”是一个术语,表示数据的趋势不是均值回复,而是在整个系列的时间跨度内持续稳定地向上或向下。在我们的例子中,趋势显然不是平稳的,因为它逐年上升,但扩展的 Dickey-Fuller 测试的结果为我们的肉眼所见提供了统计上的证明。由于 p 值不小于 0.05,我们必须假设序列是非平稳的。

所有这些序言有时看起来都是多余的,但是在尝试建模之前彻底研究数据是一个很好的练习。在这篇文章中,我将探索阶段减少到了最低限度,但是如果我不做至少这么多,我会觉得自己疏忽了。

LSTM 预测

要在 scalecast 中建模,我们需要完成以下三个基本步骤:

  1. 指定检验长度— 检验长度是完整时间序列中最后一次观测值的离散数。您可以将百分比或离散数字传递给set_test_length函数。在较新的 scalecast 版本中,可以通过将测试长度设置为 0 来跳过测试。
  2. 生成未来日期— 您在此步骤中生成的日期数将决定所有模型的预测时间。
  3. 选择估计量 —我们将使用“lstm”估计量,但也有其他几种估计量。

要完成这些步骤,请参见下面的代码:

f.set_test_length(12)       # 1\. 12 observations to test the results
f.generate_future_dates(12) # 2\. 12 future points to forecast
f.set_estimator('lstm')     # 3\. LSTM neural network

现在,打电话给 LSTM 天气预报。默认情况下,该模型将使用 8 大小的单个输入层、Adam 优化器、tanh 激活、用于训练的单个滞后因变量值、0.001 的学习率和无辍学来运行。所有数据都通过最小-最大缩放器进行缩放,然后输出未缩放的数据。任何可以传递给 TensorFlow 中的fit()方法的东西,也可以传递给 scalecast manual_forecast()方法。

f.manual_forecast(call_me='lstm_default')
f.plot_test_set(ci=True)

可以预见的是,这种模式表现不佳。但事实上,我们能够轻松获得结果是一个巨大的开端。对其进行微调以产生有用的东西应该不会太难。

让我们从简单的开始,给它更多的滞后来预测。我们在 PACF 看到了 24 个月的显著自相关,所以让我们使用它:

f.manual_forecast(call_me='lstm_24lags',lags=24)
f.plot_test_set(ci=True)

作者图片

我们已经看到了一些明显的改进,但这还远远没有准备好。一个明显的下一步可能是给它更多的时间来训练。在这个宇宙中,更多的时间意味着更多的纪元。让我们看看五个时代会带给我们什么。我们还在模型训练时通过指定下面的validation_split=.2来验证模型:

f.manual_forecast(
    call_me='lstm_24lags_5epochs',
    lags=24,
    epochs=5,
    validation_split=.2,
    shuffle=True,
)
f.plot_test_set(ci=True)

作者图片

作者图片

再近一点。这次有几个值甚至落在 95%的置信区间内。接下来,让我们尝试将网络中的层数增加到 3,将历元增加到 25,但监控验证损失值,并在超过 5 次迭代后告诉模型退出,如果没有改善。这就是所谓的提前停止。

from tensorflow.keras.callbacks import EarlyStopping

f.manual_forecast(
    call_me='lstm_24lags_earlystop_3layers',
    lags=24,
    epochs=25,
    validation_split=.2,
    shuffle=True,
    callbacks=EarlyStopping(
        monitor='val_loss',               
        patience=5,
    ),
    lstm_layer_sizes=(16,16,16),
    dropout=(0,0,0),
)

f.plot_test_set(ci=True)

作者图片

再次,缓慢改善。到目前为止,您可能已经厌倦了看到像这样的建模过程。给我找个能用的型号就行了!因此,我将直接跳到使用这种方法找到的最佳模型。参见代码:

f.manual_forecast(
    call_me='lstm_best',
    lags=36,
    batch_size=32,
    epochs=15,
    validation_split=.2,
    shuffle=True,
    activation='tanh',
    optimizer='Adam',
    learning_rate=0.001,
    lstm_layer_sizes=(72,)*4,
    dropout=(0,)*4,
    plot_loss=True
)
f.plot_test_set(order_by='LevelTestSetMAPE',models='top_2',ci=True)

作者图片

作者图片

这花了很长时间,比我愿意承认的时间还要长,但最终我们有了一些像样的东西。除了两个点之外,所有的实际点都在模型的 95%置信区间内。它唯一的问题是预测季节性高峰的最高点。这是一个我们可以考虑在现实世界中使用的模型。

MLR 预测和模型基准测试

现在我们终于找到了一个可接受的 LSTM 模型,让我们将其与一个简单的模型,最简单的模型,多元线性回归(MLR)进行比较,看看我们浪费了多少时间。

要在 scalecast 中从 LSTM 模式切换到 MLR 模式,我们需要遵循以下步骤:

  1. 选择 MLR 估计量 —就像我们之前选择 LSTM 估计量一样。
  2. 向模型添加回归变量—在 LSTM,我们只使用了系列自身的历史,并让模型自己参数化。使用 MLR,我们仍然可以使用序列自身的历史,但我们也可以添加关于任何给定观测值属于哪个月、季度或年份的信息,以捕捉季节性和时间趋势(以及其他选项)。我们甚至可以摄取我们自己的回归变量的数据框架(这里没有显示)。
  3. 差异非平稳数据 —这是我们如何减轻显示我们有非平稳数据的增强 Dickey-Fuller 测试的结果。我们也可以在 LSTM 身上做到这一点,但我们希望它足够复杂,不需要这一步。

这都是在下面的代码中完成的:

from scalecast.SeriesTransformer import SeriesTransformer

transformer = SeriesTransformer(f)
f = transformer.DiffTransform()

f.add_ar_terms(24)
f.add_seasonal_regressors('month','quarter',dummy=True)
f.add_seasonal_regressors('year')
f.add_time_trend()

现在,我们运行预测,并对照最佳 LSTM 模型查看 MLR 的测试集性能:

f.set_estimator('mlr')
f.manual_forecast()

f = transformer.DiffRevert(
    exclude_models = [m for m in f.history if m != 'mlr']
) # exclude all lstm models from the revert

f.plot_test_set(order_by='TestSetMAPE',models=['lstm_best','mlr'])
plt.title('Top-2 Models Test-set Performance - Level Data',size=16)
plt.show()

作者图片

绝对难以置信。用最简单的模型,我们很快就造出了比最先进的模型更好的东西。这可能是由于用户错误造成的。也许你可以用 LSTM 模型找到比我发现的更好的东西——如果是这样,请留下评论并分享你的代码。但我预测了足够多的时间序列,知道在这种情况下很难超越简单的线性模型。也许,由于数据集的规模很小,LSTM 模型从一开始就不合适。

然后我们可以看到我们的模型对未来数据的预测:

f.plot(
    models=['mlr','lstm_best'],
    order_by='LevelTestSetMAPE',
    level=True,
)

作者图片

我们还可以在样本外测试数据上看到所有模型的误差和准确性指标:

f.export('model_summaries',determine_best_by='LevelTestSetMAPE')[
    ['ModelNickname',
     'LevelTestSetMAPE',
     'LevelTestSetRMSE',
     'LevelTestSetR2',
     'best_model']
]

作者图片

scalecast 软件包使用动态预测和测试方法,通过自己的预测传播 AR/lagged 值,因此不存在数据泄漏。MLR 模型没有过度拟合。

结论

我希望你喜欢这个关于如何在 scalecast 中与 LSTM 一起建模的快速概述。希望你学到了一些东西。我的观点是,对于任何给定的问题,立即采用最先进的方法并不总是明智的。更简单的模型通常更好、更快、更容易理解。

布雷特·乔丹在 Unsplash 上的照片

引用的作品

Korstanje,J. (2021)。LSTM RNNs。在 J. Korstanje 的文章中,使用 Pyton 进行高级预测(第 243–251 页)。加州伯克利:新闻。

探索 ML 工具的前景(第 1 部分,共 3 部分)

原文:https://towardsdatascience.com/exploring-the-ml-tooling-landscape-part-1-of-3-53f8c39e6e4e

行业成熟度

附身摄影Unsplash 上拍照

这一系列的博客文章开始时是我试图掌握机器学习操作(MLOps ),然而这个任务很快变成了对机器学习(ML)的采用和工具的广泛回顾。正如我很快发现的那样,MLOps 代表了生产中 ML 的前沿,因此只有相对较少的领先科技公司(想想 FAANG)、前瞻性思维的初创公司以及越来越多的研究论文专门关注这一领域。这就引出了一个问题,为什么在 2022 年,大多数公司的 MLOps 采用以及更一般的 ML 采用都处于早期阶段?我相信解决这个问题对于全面理解 ML 工具的当前状态和不久的将来的趋势是至关重要的。

我在这一系列中要解决的关键问题是,

  1. 在工业中,ML 的成熟程度如何?
  2. ML 工具和采用的状态是什么?
  3. ML 工具的可能趋势是什么?

这篇博文关注的是的第一个问题。

这一系列的博客文章绝不是详尽无遗的,甚至在某些地方也不一定是正确的!我写这篇文章是为了组织我对最近几周阅读的思考,我希望这能成为进一步讨论的起点。这是一个绝对迷人的领域,我真的很想了解这个行业,所以请联系我们!

MLOps

MLOps 指的是用于帮助在生产中部署和维护 ML 模型的实践和工具的集合。顾名思义,它是 DevOps 的表亲,devo PS 同样涉及管理软件质量和部署的实践和工具。MLOps 的出现是由于人们越来越意识到在生产中部署和维护 ML 模型的独特挑战,以及意识到在任何部署过程中,ML 特定元素只是必要基础设施的非常小的一部分(Scully,2015)。

与 DevOps 类似,MLOps 代表了行业内的一种文化转变,促进了敏捷实践以及产品和服务的端到端所有权。特别是后一种考虑有助于解释端到端 ML 平台的普遍性,它提供了一系列涉及典型 ML 工作流所有主要组件的服务。ML 平台的效用通常遵循其抽象出较低级别细节的能力(Felipe & Maya,2021),这意味着这些平台通常部署在托管基础设施层之上,专门用于减轻工程团队的运营负担(Paleyes,2021)。这些平台旨在减少构建和交付模型所需的时间,并保持预测的稳定性和可重复性。看看这个领域中更成熟的公司,我们看到一种在内部开发 ML 平台的趋势(Symeonidis,2022),这在很大程度上是由于管道实施的高度上下文特定的性质。在下一篇博文中,我们将更加关注内部平台和第三方平台以及工具。

与 DevOps 不同,MLOps 利用三种主要的人工制品:数据、模型和代码(Felipe & Maya,2021)。ML 项目对数据有硬性要求,这不太适合现有的软件管理实践(Paleyes,2021),特别是数据准备的初始步骤遵循一种更瀑布式的方法(kinen,2021)。此外,每个产品都带来了不同的挑战,并具有不同的开发周期:数据开发周期通常比代码开发周期快得多,因为软件工程编码是最难的部分。不同工件及其伴随需求的组合在某种程度上解释了 MLOps 的复杂性和工具生态系统的规模(Symeonidis,2022)。在流程层面,MLOps 将持续培训(CT)的原则添加到 CI/CD 组合中。

此外,这只可能是我,但围绕 MLOps 术语及其范围的共识存在一定程度的混乱,特别是考虑到 ML 的迭代性质,很难在不同的 MLOps 关注点和数据 Ops 之间划清界限。与此相关,谈论 MLOps 成熟度和 ML 成熟度会变得困难。出于本博客的目的,我将使用“ML 成熟度”来描述 ML 工作流程中所有元素的不断增长的经验、标准化和操作,以及与具体操作方面相关的 MLOps 成熟度,即一旦模型投入生产。

ML 工作流

在直接讨论 ML 成熟度之前,首先介绍 ML 工作流的概念是有意义的,它是 ML 成熟度的定义元素之一。ML 工作流对应于一组正式的和可重复的过程,用于在生产中开发和部署 ML 模型。尽管这些步骤的具体步骤和编排仍有争议(Brinkmann & Rachakonda,2021),但(Ashmore,2019)给出了一个经常被引用的工作流程大纲,它强调了关键的高级阶段。

  • 数据管理:对应于模型训练、数据采集预处理、扩充、分析等获取数据状态的所有步骤。
  • 模型学习:模型训练和优化发生在这里。
  • 模型验证:根据各种业务指标和监管框架进行评估。
  • 模型部署:包括监控和更新生产模型。

所列的阶段可能被分解成更小、更明确的步骤,并且如前所述,不确定特定的顺序或次序(Paleyes,2021)。请注意,我在这里将术语“工作流”与“生命周期”互换使用,然而后者偶尔用于特别强调模型验证后的一切(Ashmore,2019)。

关于行业中 ML 工作流的具体实施,英伟达、脸书、Spotify 和谷歌的例子突出了“规范的”ML 工作流的新兴共识(Felipe & Maya,2021)。至少在架构层面上,这些差异很大程度上是特定用例以及其他组织关注点的结果,它们可能并不代表整个行业。然而,目前还没有相应的“规范的”ML 技术栈(Jeffries,2020),其中许多记录的 ML 工作流是用内部工具实现的(Chan,2021)——剧透!

ML 成熟度框架

有许多不同的框架试图说明不同的 ML/MLOps 成熟度级别,最著名的是谷歌( MLOps:机器学习中的连续交付和自动化管道,2020)和微软(机器学习运营成熟度模型——Azure 架构中心)。它们非常相似,展示了全面采用 MLOps 的途径如何需要围绕开发、部署和监控流程提高自动化水平。然而,由于这两个框架都只关注事情的运营方面,所以没有一个真正有助于澄清在公司全面采用 ML 的过程中,公司何时应该特别关注运营问题。(Algorithmia,2018)和(kinen,2021)提供了更接近这一点的框架。Algoritmia 白皮书提供了最通用的 ML 定义:“我们将 MLOps 成熟度定义为一个组织通过其 ML 模型推动重大商业价值的能力。”这是根据六个维度来衡量的:组织调整、数据、培训、部署、管理、治理,由(kinen,2021)撰写的论文简单得多,指出提高 ML 成熟度可以理解为经历以下阶段:

  • 以数据为中心:关注各种数据管理问题
  • 以模型为中心:重点是建立和生产最初的几个模型
  • 以管道为中心:在生产中有模型,关注运营问题

只有在“以流水线为中心”的阶段,MLOps 的问题才会得到具体解决。此外,这些阶段之间的运动应该看到相应的组织变化(kinen,2021)。这个框架在整体上更好地记录了 ML 成熟度,但是我要说的是这些类别并没有被很好地命名。具体来说,术语“以数据为中心”和“以模型为中心”通常是指作为一个整体的 ML 工作流的焦点,而不是 ML 采用水平的代表(Strickland,2022)。

总的来说,后两个框架适用范围更广,并强调了以下几点,

  1. ML 成熟度通常伴随着 ML 工作流程的不断进步和效率的不断提高
  2. MLOps 成熟度是 ML 成熟度的延续,在许多方面是 ML 成熟度的最终目标,也就是说,谈论一个而不谈论另一个是没有意义的
  3. 只有解决了 ML 成熟度的其他要素,才能实现真正的 MLOps 成熟度

行业成熟度

当把这些放在一起时,最令我震惊的是除了技术领导者之外,ML 普遍缺乏成熟和意识;在较大的公司中,约 70%的公司近年来才开始人工智能/人工智能投资(dimensional research,2019),这些公司通常不是人工智能/人工智能/数据公司。很难推测为什么会出现这种情况,但是尽管大数据、ML 和 AI 已经在商业上存在了十多年(Hadoop 最初是在 2006 年发布的(维基百科)),但它在最近几年才变得对大多数公司实用。这主要是由于越来越多的基于云的数据仓库和湖边小屋,以及足够的工具(Turck,2021)。这可以被理解为一个长期趋势的一部分,正如马特·图尔克所说,“每个公司都不仅仅是一个软件公司,也是一个数据公司。”(图尔克,2021 年)

就普遍采用 ML 而言,一般来说,有两类公司处于 ML 成熟度谱的两个极端:那些刚刚迈出第一步的公司和处于前沿的公司。回到上面讨论的框架,我们可以分别称之为“以数据为中心”和“以管道为中心”。无论如何,就(Ashmore,2019)给出的 ML 工作流而言,大多数公司报告称,他们项目的大部分时间都花在了数据管理阶段(Shankar,2021)。(Paleyes,2021)给出了按 ML 工作流程阶段细分的问题和顾虑的完整列表。

具体到 ML 中不太成熟的公司,针对相对较大(dimensional research,2019)和相对较小(dotscience,2019)组织的一系列调查强调,数据问题是数据项目的主要障碍,96%的受访者遇到了一些数据质量问题(dimensional research,2019)。这些问题包括数据可用性、数据质量和数量、标签和可访问性。其他经常提到的问题突出了适当的工具、专业知识或预算限制的普遍缺乏。整体来看,78%的项目在部署前就停滞了(dimensional research,2019)。

另一个有趣的发现涉及超参数优化,这是模型训练的一个关键步骤:24.6%的受访者完全忽略了这一点,59.2%的受访者手动执行,很少有受访者报告使用第三方工具(dotscience,2019)。这可能再次是这些组织在该领域不成熟的结果,在该领域,从配置空间手动选择更有效,特别是对于早期的 ML 项目。与此相关的是,计算能力是超参数优化的瓶颈,而不是工具或设置(Huyen,2020)。

总结

这篇文章讨论了行业中 ML 成熟度的当前状态以及一般的 MLOps。主要的收获是,从整体上考虑行业应用时,ML 采用的不成熟程度,以及全面采用 MLOps 所带来的技术、流程和文化挑战的程度。这两个元素与理解 ML 工具的当前状态高度相关,ML 工具是高度多样化的,并且是一个尚未找到共识的行业的象征。

参考

算法 ia。(2018).生产中的机器学习:成功路线图。

阿什莫尔等人(2019 年)。确保机器学习生命周期:需求、方法和挑战。 ACM 计算调查54 (5),1–30。

Brinkmann,d .,& Rachakonda,V. (2021,4 月 6 日)。 MLOps 投资//莎拉·卡坦扎罗//第 33 期咖啡。YouTube。2022 年 5 月 2 日从https://www.youtube.com/watch?v=twvHm8Fa5jk检索

Chan,E. (2021 年 5 月 12 日)。ML 平台上的课程——来自网飞、DoorDash、Spotify 等等。走向数据科学。2022 年 4 月 28 日检索,来自https://towards data science . com/lessons-on-ml-platforms-from-网飞-door dash-Spotify-and-more-f 455400115 C7

维度研究。(2019).人工智能和机器学习项目因数据问题受阻

网络科学。(2019).AI 应用的开发运营状况

费利佩,a .,&玛雅,V. (2021)。MLOps 的状态。

呼延,C. (2020 年 6 月 22 日)。看 200 个机器学习工具学到的东西https://huyenchip.com/2020/06/22/mlops.html

杰弗里斯博士(2020 年 10 月 13 日)。机器学习中典范栈的崛起。走向数据科学。2022 年 5 月 2 日检索,来自https://towardsdatascience . com/rise-of-the-canonical-stack-in-machine-learning-724 e 7 D2 FAA 75

机器学习运营成熟度模型——Azure 架构中心。微软文档。2022 年 5 月 2 日检索,来自https://docs . Microsoft . com/en-us/azure/architecture/example-scenario/ml ops/ml ops-maturity-model

Mä kinen,s .等人(2021 年)。谁需要 MLOps:数据科学家寻求完成什么,MLOps 如何提供帮助?https://arxiv.org/abs/2103.08942

MLOps:机器学习中的连续交付和自动化管道。(2020 年 1 月 7 日)。谷歌云。2022 年 5 月 2 日检索,来自https://cloud . Google . com/architecture/mlops-continuous-delivery-and-automation-pipelines-in-machine-learning

Paleyes,a .等人(2021 年)。部署机器学习的挑战:案例研究调查。

Scully,d .等人(2015 年)。机器学习系统中隐藏的技术债务。

s . Shankar(2021 年 12 月 13 日)。现代 ML 监控混乱:对部署后问题进行分类(2/4) 。史瑞雅·尚卡尔。于 2022 年 4 月 30 日从https://www.shreya-shankar.com/rethinking-ml-monitoring-2/检索

斯特里克兰,E. (2022 年 2 月 9 日)。吴恩达:Unbiggen AIhttps://spectrum.ieee.org/andrew-ng-data-centric-ai

Symeonidis,g .等人(2022 年)。MLOps——定义、工具和挑战。

m .图尔克(2021 年 9 月 28 日)。红热:2021 年的机器学习、人工智能和数据(MAD)格局https://mattturck.com/data2021/

维基百科。 Apache Hadoop 。维基百科。2022 年 5 月 2 日从 https://en.wikipedia.org/wiki/Apache_Hadoop 检索

探索 ML 工具的前景(第 2 部分,共 3 部分)

原文:https://towardsdatascience.com/exploring-the-ml-tooling-landscape-part-2-of-3-8e4f3e511891

当前的 ML 工具和采用

附身摄影Unsplash 上拍照

在本系列的前一篇博文中,我们考察了行业中整体机器学习(ML)的成熟度,特别关注机器学习操作(MLOps)。两个主要的问题是,作为一个整体,ML 在行业中明显缺乏成熟,以及完全接受 MLOps 所涉及的复杂性,这可以被视为 ML 成熟的最高点。在这篇博文中,我们将考虑工具在工业和更广泛的 ML 工具市场中的应用。

在这一系列博客文章中,我的目标是解决以下问题:

  1. 在工业中,ML 的成熟程度如何?
  2. ML 工具和采用的当前状态是什么?
  3. ML 工具的可能趋势是什么?

这篇博文关注的是第二个问题。

与前一篇文章一样,同样的免责声明也适用:这一系列的博客文章绝不是详尽无遗的——甚至不一定在某些地方是正确的!我写这篇文章是为了组织我对最近几周阅读的思考,我希望这能成为进一步讨论的起点。这是一个绝对迷人的领域,我真的很想了解这个行业,所以请联系我们!

地貌

谈论拥挤的 ML 工具环境绝不是夸大其词。名副其实的 MAD Landscape(即机器学习、人工智能和数据)列出了截至 2021 年底的 2000 多个(这个数字包括一些重复的)商业和开源项目和公司(图尔克,2021)。而这只是为数不多的类似综述之一:(TWIML,2021),(LF AI & Data Foundation,2022),(Hewage,2022),(Ruf,2021)。

在进一步讨论之前,有必要澄清一下这个主题的一些术语。经常发现端到端的 ML 平台被称为 MLOps 平台(thoughtworks,2021),数据科学和机器学习(DSML)平台(Turck,2020),等等。然而,根据前一篇博文中的讨论,使用术语“ML 平台”来包含所有这样的产品是有意义的,因为可以论证 MLOps 通常是 ML 成熟度的最终目标。我也倾向于去掉限定词“端到端”,因为 ML 平台通常旨在服务 ML 工作流程的所有步骤。独立于平台,术语工具用于指处理 ML 工作流中特定步骤的软件。我可能偶尔会使用工具将它们联系在一起,这在上下文中应该是清楚的,或者使用“解决方案”来将两者联系在一起。

虽然这几项审查在方法和广度上有所不同,但也有一些共同点。首先,工具生态系统本身缺乏成熟度,指的是没有任何一个平台支持完全自动化的 ML 工作流,或者至少没有一个平台可供广泛的利益相关者访问(Ruf,2021)。与此相关的一点是专家工具,根据他们的方法,可能支持一个以上的 ML 任务(TWIML,2021)。其次,一个 ML 平台被认为是“好的”,因为它覆盖了 ML 工作流的所有方面,允许自动化,并支持多种语言、框架和库(Hewage,2022)。第三,在现有的解决方案中,不同 ML 任务的实施水平存在很大差异(Felipe & Maya,2021)。正如上一篇博文中所讨论的那样,我们有理由推测,这些问题中有许多是由于在实践中对如何实现 ML 工作流缺乏共识而导致的直接后果。

此外,许多文章根据解决方案的完整性,即它支持多少 ML 工作流,以及产品的“种类”,构建了各种产品。也就是说,

  1. 它是一个平台还是专门的/零碎的工具?
  2. 它是特定于 ML 的还是适用于软件工程(SWE)的?
  3. 它适用于 ML 生命周期的哪个(些)阶段?

后一个标准特别主观,因为对于给定工具与什么特定任务相关是有争议的,例如,数据可观察性几乎触及所有事物(TWIML,2021)。(thoughtworks,2021 年)和(Miranda,2021 年 a)给出了两个这样的框架。我更喜欢后者,因为它提供了一种在更广泛的 SWE 环境中理解 ML 工具的方法,并且提供了一个简单框架的基础来理解工具成熟度的当前状态,即使它没有直接将工具链接到 ML 工作流状态。当我们考虑如何评价下面的工具选择时,这个框架将被证明是有洞察力的。

ML 工具采用

我们通过检查行业中的 ML 成熟度结束了上一篇文章,注意到企业公司中有两个不同的群体:处于 ML 前沿的成熟公司和近年来才推出 ML/AI 产品的不成熟公司。此外,我们检查内部工具的优势,至少在成熟的公司。事实上,在这个领域的成熟和不成熟的公司中,内部工具化都很突出,但原因不同。

对于成熟的公司来说,这在很大程度上是因为缺乏(成熟的)替代品——毕竟,他们是这个领域的领导者。当具体考虑 MLOps 工具时,尤其如此:特性存储、模型服务等。在对 MLOps 特定平台组件的审查中,在占主导地位的美国大型 B2C 中,只有 ML 平台的工作流程编排组件经常使用开源解决方案,通常是 Kubeflow 管道或气流(Chan,2021)。这可能是因为这是考虑的最通用的组件(dotscience,2019)。在这些公司中,开发内部 ML 平台的目标是双重的(Symeonidis,2022),首先,目标是减少构建和交付模型所需的时间,其次是保持预测的稳定性和可重复性;或者换句话说,分别处理 MLOps 的交付和部署阶段。随着工具生态系统整体的成熟,这种情况会改变吗?可能没有那么多。这有三个主要原因。首先,任何现存的工具都是直接响应给定公司的特定战略响应而出现的,如果考虑到前面给出的两个需求,可能不希望更广泛地使用这些工具,或者不容易在外部复制这些工具。其次,与此相关的是,可能无法从外部生成一个功能齐全的替代方案。第三,这一级别的成功不是由一种技术决定的,而是由它的端到端集成决定的,这给第三方工具带来了额外的障碍。正如马特·图尔克(Matt Turck)所说:“大数据(或 ML/AI)的成功不是实施一项技术……而是需要将技术、人员和流程组装成一条流水线。”(图尔克,2016)。

在不成熟的公司中,内部解决方案的趋势在很大程度上正是由于这种不成熟:他们可能没有技术技能或预算来获取第三方工具(dotscience,2019)。与此相关,他们可能会发现很难证明需要这些工具,因为没有比较基准,特别是如果考虑到这些工具在很大程度上是用来优化一个已知的过程。正如我们将在下面看到的,要么以渐进的方式创建一个 ML 工作流,要么选择一个覆盖端到端工作流的平台,这两者之间有一个不可逾越的权衡;这两种方法都必然引入技术债务(Ruf,2021)。无论哪种方式,都可能很难找到符合公司要求的产品,这源于对 ML 工作流实现缺乏共识(见上一篇文章)和缺乏功能完整的 ML 平台(TWIML,2021)。相反,围绕现有的 ML 管道实现匹配第三方选项可能太具挑战性(将在下面详细讨论)。一个相关的问题:对于这些公司中的许多来说,可用的工具可能不适合他们的需求,原因有很多,特别是由于各种各样的遵从性问题。例如,当前的数据标签解决方案通常使用外包或合同工,在许多情况下可能不适合,如金融服务等受监管领域(Vanian,2021)。对于许多企业来说,通常更希望确保对数据的完全控制和所有权,并避免将数据分发给多方。像浮潜人工智能这样的公司旨在直接解决这些问题。

综上所述,这些点可能表明当前工具环境的多样性是需要解决许多不同的实现的直接结果,这些实现可能是高度特定于公司的。除此之外,普遍的风险投资资金过剩和其他可用资金(图尔克,2021 年)使得该领域的公司和解决方案迅速扩张。

决定决定决定

考虑到前面的讨论,人们不禁要问,如何为不成熟的 ML 实现选择合适的平台和/或工具集?正如所料,没有真正正确的答案,但是可以做出明智的选择,以确保你能够在这个领域取得有意义的进展,同时尽量减少以后的问题。

全面采用 MLOps 的最快途径是关注 ML 生命周期的完整端到端,或者使用(Stiebellehner,2022a)中使用的术语,首先关注功能的深度,然后才关注功能的广度。这样做还有一个额外的好处,就是减少了与想法验证相关的时间和成本,这样就可以尽早获得有意义的反馈。

正如已经讨论过的,目前没有广泛接受的完整的端到端 ML 平台可用。这就需要在现有的 ML 平台和/或从各种独立的专业工具中拼凑一个 ML 工作流程之间做出选择。从战略角度来看,与一家平台提供商合作可能并不可取,因为他们可能不符合您的长期需求,并可能导致供应商锁定,这意味着任何后续变化都意味着更大的机会成本。相反,围绕独立工具开发过程可能意味着在内部产生比期望的更多的工作,特别是如果交付速度是主要目标的话。在任何情况下,按照上面介绍的框架,给定的工具或平台越成熟,并且在一定程度上,工具越零碎,选择就越安全(Miranda,2021b)。

特别是对于 ML 不是核心功能的企业,一般的建议是购买而不是构建,并在这些组件之间添加定制的集成器,无论这些组件是平台还是专用工具(Miranda,2021b)。工具的选择应该基于即时交付目标,重点是这些组件之间的集成和重叠;目标是选择最小的令人满意的选项集。由于关注的重点是深度而不是广度,所以诸如可伸缩性或自动化之类的因素不应该是主要关注点。要问的问题包括,每种工具支持哪种语言来帮助交互,以及一些工具的选择是否会由于它们的重叠功能而引入冗余;诸如此类的问题只能用经验来回答,因此非常需要迭代并从您的过程中学习(Ruf,2021)。Kubeflow 提供了一个工具采用的有启发性的例子,它虽然提供了对端到端 ML 平台的支持,但只看到了像 Kubeflow 管道这样的特定元素被广泛采用。

地平线上有什么?

围绕当前工具星座的一个核心争论是,我们是否以及何时应该期待看到某种形式的整合。大多数观察家会期待某种形式的合理化,然而参数远不清楚(图尔克,2021)。一种整合,即“功能整合”,已经在成熟和成功的解决方案中观察到,如 Databricks 和 Snowflake,它们有向功能齐全的端到端产品发展的趋势(Turck,2021)。这很可能是许多成功的第三方解决方案的更普遍趋势的一部分,这些解决方案通常是一个更大的生态系统的组成部分,例如雪花和 AWS。除此之外,我们可能希望看到大型云平台通过内部创新或并购提供额外的服务。

到目前为止,工具和过程的任何更广泛的合理化一般都被数据和工具日益增长的复杂性以及这种变化的速度所抵消。这在 MLOps 和 DataOps 工具方面很明显,这两种工具目前通常由内部工具处理(Turck,2020)。进一步阻碍进步的原因是广泛观察到的人才短缺,预计这种情况将持续更长时间(O'Shaughnessy,2022),尽管在一定程度上,这可以通过增加工具来缓解。

数据质量测试和可观察性工具目前在市场上取得了最大的成功,这正是由于市场在整体 ML 成熟度方面所处的位置(Stiebellehner,2022b)。然而,我们似乎正在进入 ML 工具和 ML/AI 的新阶段。鉴于致力于 MLOps 的初创公司的显著增长,可以预计运营化将在短期内占据主导地位(Shankar,2021)。然而,随着人工智能招聘的普遍降温(Huyen,2020 年)和风投资金的普遍撤出(Turck,2022 年),整合似乎即将到来。至于技术发展,我将在本系列的第三篇博文中讨论,但是我希望看到以数据为中心的人工智能、MLOps 和 AutoML 在不久的将来成为 ML 工具的主要趋势。

总结

在这篇博客文章中,我们继续我们之前关于 ML 在行业中的成熟度的讨论,展示了复杂 ML 采用的普遍低水平与 ML 工具产品的数量和不完整性之间的联系。此外,我们暗示了近期的一些关键趋势:对数据测试和可观测性的持续兴趣,以及对 MLOps 初创公司的不断增加的资助。在此基础上,本系列的下一篇博文将研究工具领域中出现的一些关键技术。

参考

费利佩,a .,&玛雅,V. (2021)。MLOps 的状态。

Hewage,n .等人(2022 年)。机器学习操作:关于 MLOps 工具支持的调查。

呼延,C. (2020 年 12 月 30 日)。机器学习工具 Landscape v2 (+84 新工具)。奇普·胡恩。2022 年 5 月 7 日检索,来自 https://huyenchip.com/2020/12/30/mlops-v2.html

人工智能和数据基金会。(2022). LF AI &数据基础互动景观。LF AI &数据景观。2022 年 5 月 6 日,从https://landscape.lfai.foundation/检索

l .米兰达(2021a,5 月 15 日)。浏览 MLOps 工具领域(第 2 部分:生态系统)。Lj 米兰达。2022 年 5 月 6 日检索,来自https://ljvmiranda 921 . github . io/notebook/2021/05/15/navigating-the-mlops-landscape-part-2/

l .米兰达(2021b,5 月 30 日)。在 MLOps 工具领域导航(第 3 部分:策略)。Lj 米兰达。2022 年 5 月 6 日检索,来自https://ljvmiranda 921 . github . io/notebook/2021/05/30/navigating-the-mlops-landscape-part-3/

奥肖内西,P. (2022,4 月 12 日)。亚历山大·巴甫洛夫·王——人工智能入门。YouTube。2022 年 5 月 8 日从 https://open.spotify.com/episode/0jFd4L8nvDROu05lk2kv6y?检索 si = 06 E4 af 52 baff 44 be&nd = 1

Ruf,p .等人(2021 年)。揭开 MLOps 的神秘面纱,展示选择开源工具的诀窍。

s . Shankar(2021 年 12 月 13 日)。现代洗钱监测混乱:对部署后问题进行分类(2/4) 。史瑞雅·尚卡尔。于 2022 年 5 月 8 日从https://www.shreya-shankar.com/rethinking-ml-monitoring-2/检索

斯蒂贝勒纳,S. (2022a,2 月 27 日)。【MLOps 工程师】纵向第一,横向第二。为什么在开发机器学习系统时应该尽早突破生产,以及 MLOps 如何促进这一点。|作者 Simon Stiebellehner | Medium 。西蒙·斯蒂贝勒纳。2022 年 5 月 7 日检索,来自https://sistel . medium . com/the-mlops-engineer-vertical-first-horizontal-second-306 fa 7 b 7 a 80 b

斯蒂贝勒纳,S. (2022b,4 月 10 日)。未来的“数据狗”。数据质量如何,监测&可观测波正在建立。2022 年 4 月,。ITNEXT。2022 年 5 月 9 日检索,来自https://it next . io/the-mlops-engineer-the-data dogs-of-tomorrow-614 a88a 374 E0

思想工厂。(2021).MLOps 平台评估指南 2021 年 11 月。

m .图尔克(2016 年 2 月 1 日)。大数据还是个东西吗?(2016 年大数据格局)。马特·图尔克。2022 年 5 月 4 日检索,来自 https://mattturck.com/big-data-landscape/

m .图尔克(2017 年 4 月 5 日)。全力以赴:2017 年大数据前景。马特·图尔克。2022 年 5 月 4 日从https://mattturck.com/bigdata2017/检索

m .图尔克(2020 年 10 月 21 日)。2020 年的数据和 AI 景观。风险投资。2022 年 5 月 6 日检索,来自https://venturebeat . com/2020/10/21/the-2020-data-and-ai-landscape/

m .图尔克(2021 年 9 月 28 日)。红热:2021 年的机器学习、AI 和数据(MAD)格局。马特·图尔克。于 2022 年 5 月 4 日从https://mattturck.com/data2021/检索

m .图尔克(2022 年 4 月 28 日)。2022 年风投大撤退——马特·图尔克。马特·图尔克。于 2022 年 5 月 8 日从https://mattturck.com/vcpullback/检索

TWIML。(2021 年 6 月 16 日)。介绍 TWIML 新的 ML 和 AI 解决方案指南。TWIML。2022 年 5 月 6 日检索,来自https://twimlai . com/solutions/introducing-twiml-ml-ai-solutions-guide/

探索 ML 工具的前景(第 3 部分,共 3 部分)

原文:https://towardsdatascience.com/exploring-the-ml-tooling-landscape-part-3-of-3-8e4480d04fe0

ML 工具的未来

帕特·克鲁帕在 Unsplash 上的照片

本系列的前一篇博文考虑了 ML 工具生态系统的当前状态,以及这如何反映在 ML 在行业中的采用。主要的收获是专有工具在该领域的公司中的广泛使用,以及相应的多样化和分散的 ML 工具市场。这篇文章最后看了一些新兴的近期趋势,强调了数据可观测性和相关工具的优势,以及 MLOps 初创公司的出现。这篇博客文章将继续讨论 ML 工具的一些关键趋势,这些趋势很可能在不久的将来占据主导地位——或者至少是我想谈论的那些!正如在之前的博客文章中所指出的,我想专注于 MLOps,AutoML 和以数据为中心的 AI。

在这一系列博客文章中,我的目标是解决以下问题:

  1. 在工业中,ML 的成熟程度如何?
  2. ML 工具和采用的当前状态是什么?
  3. ML 工具的可能趋势是什么?

这篇博文关注的是第三个问题。

与本系列中的所有其他帖子一样,同样的免责声明也适用:本系列的博客帖子绝不是详尽无遗的,甚至在某些地方也不一定是正确的!我写这篇文章是为了组织我对最近几周阅读的思考,我希望这能成为进一步讨论的起点。这是一个绝对迷人的领域,我真的很想了解这个行业,所以请联系我们!

MLOps

虽然 MLOps 一直是贯穿本系列的主题,但我想花一些空间来研究 MLOps 承诺引入的变化更普遍地代表了 ML。

MLOps 旨在解决部署和维护面向生产的 ML 产品的特定问题。与更传统的软件工程(SWE)不同,ML 模型以及为其提供动力的管道由多个高度集成的组件组成,这些组件依赖于历史输入,即“有状态的”;这意味着实时端到端监控是全面解决生产问题的唯一手段(Shankar,2021)。

“漂移”是一个只能用 MLOps 真正解决的问题的例子。漂移是一个总括术语,可以涉及一系列相关的现象;简而言之,通常通过模型的性能随着时间的推移而下降来观察,这是由于模型的训练数据与模型用于推理的数据之间不匹配。只有拥有一个真正敏捷的端到端开发管道,才能提供解决这个问题的完整方法。

更一般地说,MLOps 的核心代表了从数据导向的模型开发向更接近 SWE 的转变,在 SWE 中,操作日志记录成为监控和开发的基础(Shankar,2021)。

AutoML

自动机器学习(AutoML)是指一系列旨在消除 ML 工作流程中大多数到所有步骤的人工工作的系统。“AutoML”一词最初是由谷歌在 2017 年推广的(TWiML,2019),并在 2018 年谷歌 NASNet 的成功之后得到了巨大的推动,其表现优于所有现有的人类创造的模型(人工智能报告状态:2018 年 6 月 29 日)。

一般来说,AutoML 系统的目标是双重的。首先,AutoML 系统旨在使更多的用户能够使用 ML,否则这些用户可能不具备使用 ML 的专业知识。其次,AutoML 旨在通过使端到端开发过程尽可能无缝来加快模型开发的速度(Hutter et al .,2019)。

AutoML 本质上是组合算法选择和超参数(CASH)优化的超集。CASH optimisation 基于这样一种理解,即没有一个最大似然模型对所有任务都表现最佳(Hutter et al .,2019),它将数据准备、最大似然算法的选择和超参数优化视为一个单一的全局优化问题(Brownlee,2020)。除了这些元素之外,AutoML 在管道创建问题(即端到端 ML 问题)中引入了“管道结构搜索”:尽管 CASH 方法将返回线性管道,但 AutoML 算法可能会生成具有多个并行分支的管道,然后将这些管道重新组合(ller,2021)。

对不属于端到端平台的现有 AutoML 库的调查普遍发现,CASH 算法优于它们;至少从纯车型性能来说是这样的。此外,在对经典 ML 模型(即非神经网络)的调查中,自动 ML 生成的管道通常非常简单,仅限于监督学习,并且尚未完全解决真正自动化 ML 管道所需的所有元素(ller,2021)。为 AutoML 生成的结果应用于神经网络,神经架构搜索(NAS),返回类似的结果,观察到 NAS 可以生成新颖的,虽然简单的架构(何,2021)。跨云供应商、AutoML 平台(H2O、DataRobot 等)的 AutoML 产品。)和开源软件,尽管许多发行商声称(辛,2021);目前没有一个开源工具能够创建完全自动化的 MLOps 工作流(Ruf,2021)。

尽管经常提到的采用 AutoML 的目的是为了更广泛地实现 ML 功能,但我可以想象,至少在目前的形式下,由于资源需求和工具的黑箱特性,具有讽刺意味的是,AutoML 可以更好地服务于已经建立了 ML 能力的公司。特别是,如果 AutoML 工具希望使技术能力较差的用户能够利用 ML,它就对可解释的人工智能(XAI)技术的并行改进提出了硬性要求。不考虑这些问题,一些观察者已经建议了一种更有限的、渐进的方法,在这种方法中,AutoML 仅仅辅助 ML 工作流的元素,其中可定制性和通用性不是关键的关注点。出于战略原因,手动任务持续存在的理由可能一直存在(辛,2021)。

以数据为中心的人工智能

“以数据为中心的人工智能”一词的具体含义可能很难准确界定。然而,它通常可以被理解为倡导一种整体方法,强调支持模型性能的基础设施、过程和文化,当然包括数据本身,而不是孤立地优化模型(Kurlansik,2021)。最近以数据为中心的人工智能相关性增加的一个更具体的原因,可能部分是由于自动化标签和稳定的架构性能(人工智能报告状态:2021 年 10 月 12 日)。

即使以数据为中心的人工智能可能不属于任何专有的工具或流程,但它确实更加重视适合数据运营的技术,包括数据可观察性、数据血统、数据质量和数据治理工具。更详细地说,数据可观测性可以被认为不仅仅是典型的软件监控,而是使用户能够对历史数据进行特别分析(Hu,2022)。

另一个这样的领域与数据质量有关,数据质量通常通过某种数据验证工具来维护。有两种广泛的方法:使用一组手动维护的声明性规则,如 Great Expectations,或者使用某种 ML 层(可能在规则集之上)来自动检测数据质量问题,如 Anomalo。这两种方法各有利弊。一方面,尽管维护一组声明性规则可能很费力,但它确保了数据的预期是明确的,并有助于澄清理解——类似于代码测试如何帮助文档。另一方面,利益相关者可能很难明确表达他们对数据的要求,因此需要自动化(数据驱动的纽约,2021)。

摘要

从本系列的第一篇博文来看,我们发现绝大多数应用 ML 原则的公司在该领域还相当不成熟,而且对于所有公司来说,与数据收集和处理相关的初始步骤仍然是主要的绊脚石。在此基础上,我们预计获得牵引力的工具和解决方案将有望直接解决这些问题,以数据为中心的人工智能的兴趣证明了这一点。虽然这篇博客文章将 MLOps、AutoML 和以数据为中心的人工智能分开处理,但前两者在以数据为中心的保护伞下大致相符:合在一起,目标是推动 ML/AI 产生的商业价值。除了这些主题领域,还有一个使用人工智能来增强数据迁移和数据清理的案例。

随着时间的推移,我们看到越来越多的公司参与到人工智能/人工智能中,但作为一个比例,总的人工智能/人工智能能力保持不变,因为新来者的数量超过了更成熟的参与者。尽管如此,人们普遍认为该领域的创新是由成熟的 ML 公司的需求和经验驱动的,这也可能意味着一定程度的碎片化将持续存在,正如我们在本系列的第二部分中看到的那样。

还应考虑公司在该领域面临的问题在多大程度上可以通过另一种工具解决方案充分解决:在许多情况下,问题是由更基本的系统性问题引起的(Brinkmann & Rachakonda,2021)。虽然这可能对该领域的大多数初创公司不公平,但在许多情况下,它们都是从解决创始人自己以前经历过的问题开始的,正如我们现在所预期的那样,这些问题可能并不代表更广泛的行业(Brinkmann & Rachakonda,2022)。虽然过去的经验可以形成有效的概念证明的基础,但它并不是统一适用的,并且可能有成为所谓的“寻找问题的解决方案”的风险(Friedman,2021)。ML 采用的下一个时代也可能看到已被证明交付真正商业价值的基本原则的重申,值得注意的是结构化数据比非结构化数据更有价值,过程比工具更有价值(Brinkmann & Rachakonda,2021)。这也很可能意味着特定于数据的工具在不久的将来将继续占据主导地位。

参考

Brinkmann,d .,& Rachakonda,V. (2021,4 月 6 日)。m lops Investments//Sarah Catanzaro//第 33 场咖啡会。YouTube。检索于 2022 年 6 月 24 日,发自 https://www.youtube.com/watch?v=twvHm8Fa5jk

Brinkmann,d .,& Rachakonda,V. (2022,4 月 20 日)。穿越数据成熟度谱:创业视角//马克·弗里曼//咖啡会议#94 。YouTube。于 2022 年 6 月 24 日从https://www.youtube.com/watch?v=vZ96dGM3l2k检索

j .布朗利(2020 年 9 月 16 日)。结合算法选择和超参数优化(CASH 优化)。机器学习精通。检索于 2022 年 5 月 16 日,来自https://machine learning mastery . com/combined-algorithm-selection-and-hyperparameter-optimization/

数据驱动的纽约。(2021 年 6 月 21 日)。炉边谈话:Abe Gong(超导创始人& CEO)与 Matt Turck(first mark 合伙人)。YouTube。检索于 2022 年 6 月 24 日,来自https://www.youtube.com/watch?v=oxN9-G4ltgk

弗里德曼,J. (2021)。如何获得创业创意。YouTube。2022 年 6 月 24 日检索,发自 https://www.youtube.com/watch?time_continue=1&v = uvw-u 99 yj 8 w&feature = emb _ logo

何,X. (2021)。AutoML:最新技术水平的调查

胡,王(2022)。数据可观性:从 1788 年到 2032 年。BrightTALK。于 2022 年 6 月 24 日从https://www.brighttalk.com/webcast/18160/534019检索

哈特,f .,科特霍夫,l .,,范肖伦,j。).(2019).自动化机器学习:方法、系统、挑战。斯普林格国际出版公司。

库尔兰西克河(2021 年 6 月 23 日)。以数据为中心的平台如何解决 MLOps 面临的最大挑战。数据砖。2022 年 6 月 24 日检索,来自https://databricks . com/blog/2021/06/23/need-for-data-centric-ml-platforms . html

Ruf,P. (2021 年)。揭开 MLOps 的神秘面纱,展示选择开源工具的诀窍。

s . Shankar(2021 年 12 月 13 日)。现代洗钱监测混乱:部署后问题分类(2/4) 。史瑞雅·尚卡尔。于 2022 年 5 月 8 日从https://www.shreya-shankar.com/rethinking-ml-monitoring-2/检索

TWiML。(2019).机器学习平台权威指南

辛,丁(2021)。汽车向何处去?理解自动化在机器学习工作流中的作用。CHI’21:2021 CHI 计算系统中人的因素会议论文集。

泽勒,文学硕士(2021)。自动机器学习框架的基准和综述。人工智能研究杂志70 期

探索最流行的机器学习和深度学习 GitHub 库

原文:https://towardsdatascience.com/exploring-the-most-popular-machine-learning-and-deep-learning-github-repositories-90b9ecf12be7

实践教程

探索最流行的机器学习和深度学习 GitHub 库

收集、分析和可视化数千个与机器学习和深度学习相关的流行 GitHub 存储库的数据

图 1 :基于最流行的机器学习和深度学习 GitHub 知识库的描述生成的词云。图片作者。

目前,机器学习和深度学习是学术界和工业界广泛关注的两个主题。鉴于 GitHub 非常受欢迎,已经有成千上万的 GitHub 存储库,其中包含源代码、文档和其他与任何一个主题相关的大量项目的有用信息。在这篇文章中,我解释了我如何收集、清理和可视化一些最流行的机器学习和深度学习 GitHub 存储库的数据的过程。我还讨论了与我创建的每个可视化相关的趋势、模式和关键发现。

你可以在我自己的 GitHub 库这里找到支持本文的所有源代码。

什么是 GitHub?

首先,我将为不熟悉 GitHub 的读者提供一个简要的概述。如果您已经了解 GitHub 和 GitHub 库是如何工作的,请随意跳到本文的下一节。

GitHub 是一个免费的流行工具,许多个人和组织使用它来创建和开发软件。它主要用于在软件开发过程中执行版本控制和问题跟踪。GitHub 还支持开源软件的开发,这是一种带有源代码的软件,任何人都可以检查、修改和增强。

GitHub 仓库

GitHub 的核心概念是一个 GitHub (有时缩写为“repo”)。可以将存储库视为一个在线文件夹,其中包含与单个项目相关的所有文件。从技术上讲,在存储库中存储任何类型的文件都是可能的,但是您会发现存储在其中的两种最常见的文件类型是:

  1. 源代码文件,比如 Python(。py)或者 Java(。java)。
  2. 文本文件,如纯文本(。txt)或 Markdown(。md)。

存储库可以是公共的,也可以是私有的。一个公共存储库及其内容可以被互联网上的任何人查看,而一个私有存储库及其内容只能被拥有它的个人或组织查看。个人或组织都可以拥有存储库。

公共库是强大的,因为它们促进和支持开源软件的开发。具体来说,查看公共存储库的任何人都能够对其中包含的任何文件提出编辑、修复、改进和/或新功能的建议。

GitHub 跟踪每个存储库的元数据和统计数据,例如:

  • 从其他 GitHub 用户处收到的颗星的数量。当有人“星”一个存储库,他们基本上是把它添加到他们的“收藏夹”列表。
  • 存储库被分叉的次数。当另一个 GitHub 用户获取原始存储库本身的完整可编辑副本时,就会发生分叉。这个概念类似于复制粘贴存储库中的所有内容供您自己使用。
  • 源代码文件中使用的编程语言列表。
  • 与存储库中的工作相关的主题的列表。一些例子是“机器学习”、“神经网络”和“区块链”。
  • 由所有者提供的存储库的描述

现在我们知道了 GitHub 是什么,让我们看看我是如何从 GitHub 收集数据的,以及我收集的不同类型的数据。

从 GitHub 收集数据

为了从 GitHub 收集数据,我用 Python 创建了一个编程脚本。我使用了一个名为 PyGitHub 的库来简化我的脚本中的大部分数据收集功能。PyGitHub 是一个通过 GitHub REST API 提供高效数据访问的包装器。我在下面详细描述了我收集的数据集。

1。流行的机器学习和深度学习知识库数据

我收集的第一类数据是最受欢迎的 GitHub 知识库上的数据,当你在 GitHub 上搜索“机器学习”和“深度学习”时,可以找到这些数据。为了识别最受欢迎的星星,我使用了存储库中的星星数量。换句话说,如果你在 GitHub 上搜索“机器学习”,那么在我的分析中,返回的星级数最高的存储库将被认为是最受欢迎的。

我为每个存储库收集的数据点的一些例子是:存储库名称、描述、创建日期、使用的编程语言、星号数、分叉数和主题。总的来说,我为每个搜索查询收集了前 1,000 个存储库的数据,这样总共收集了 2,000 个存储库的数据。

2.存储库所有者数据

我收集的第二类数据是拥有上述 2000 个存储库的个人和组织的数据。我为每个存储库所有者收集的数据点的几个例子是:用户名、简历、用户类型、公司、电子邮件、位置、关注者数量和公共存储库数量。在删除重复之后,我收集数据的唯一存储库所有者的总数是 1,492。

3.前 25 名个人和前 25 名组织

接下来,使用我在上面第 2 部分中收集的用户 类型数据点,我将存储库所有者数据分成两部分,由个人拥有的存储库和由组织拥有的存储库。我随后确定了:

  • 前 25 名个人,根据个人拥有的关注者数量。
  • 前 25 个组织,就拥有获得最高星级数的前 25 个机器学习或深度学习存储库的组织而言。

然后,对于每一个小组,我收集了他们在 GitHub 上所有公共存储库的可用数据。在这个部分中,我总共收集了大约 8000 个存储库的数据。

我已经创建了一个简短的 Jupyter 笔记本,它包括一个完整的列表和我为上面的每个数据集收集的数据点的总数。

清理数据

我收集的数据是现实生活中的数据,因此远非完美。不完美的几个例子是:

  • 缺少或不完整的数据点,例如,只有一些存储库所有者提供了他们的存储库的描述;
  • 包含非英语字符和/或不必要的空白的文本数据;和
  • 我收集的每个数据集都有重复的元数据。

如果你有兴趣,可以在这里找到我的数据清理脚本

此外,在我收集的存储库所有者数据集中,包含的数据点之一是位置。这个包含一个由所有者输入的值,该值描述了他们在世界上的位置。我使用一个名为 GeoPy 的 Python 库将这些位置数据进一步解析成详细的地理位置数据(纬度、经度和国家)。

分析和可视化数据

清理完数据后,我使用 Python 中的一个名为 Altair 的库创建了几个可视化效果。我将在本文接下来的三个部分中讨论这些可视化。前两个部分着重于比较和对比我在 GitHub 上的搜索查询“机器学习”和“深度学习”中收集的存储库数据。第三部分深入研究了我收集的关于存储库所有者以及前 25 名个人和前 25 名组织的数据。

总体上最流行的存储库和编程语言

在这里,我们来看看与机器学习或深度学习相关的 10 大最流行的 GitHub 库,以及用于这些主题的 10 大最流行的编程语言。

图二。总体排名前 10 的最受欢迎的存储库,按总星级排序。图片作者。

在图 2 中,我们看到最受欢迎的存储库的明显赢家是拥有超过 160,000 颗恒星的 tensorflow 。这个存储库包含机器学习平台 TensorFlow 的源代码,这是一个端到端的系统,包含一个完整的工具生态系统,通常用于构建机器学习应用程序。

此外,我们看到图 2 中包括 5 个机器学习和 5 个深度学习知识库。这表明这两个主题都有在 GitHub 上获得高星级的存储库。

图 2 中其他一些值得注意的存储库是:

  • scikit-learn :最流行的 Python 机器学习包。
  • keras :构建在 TensorFlow 之上的 Python 深度学习包。
  • awesome-machine-learning :一个包含有用的机器学习框架、库和软件列表的存储库。

图 3 :总体排名前十的最受欢迎的编程语言,按总星级排序。图片作者。

每个 GitHub 存储库都包含一个在它所包含的源代码文件中使用的编程语言列表。上面的图 3 展示了我收集数据的存储库中使用的最流行的编程语言,按照与每种语言相关的存储库获得的星级总数。

毫不奇怪,Python 是与存储库相关联的编程语言,在这两个主题上都赢得了最多的关注。Jupyter 笔记本位居第二。值得注意的是,Jupyter Notebook 在技术上并不是一种编程语言本身,而是一种基于 web 的交互式计算平台,最常用于数据科学家。然而,GitHub 将其标记为编程语言,因此包含在上面的图中。

随着时间的推移,查看最流行的存储库

接下来,让我们看看前 1000 个机器学习存储库和前 1000 个深度学习存储库的一些趋势。具体来说,我创建了图表来显示最受欢迎的存储库是何时创建的,以及它们关注的最受欢迎的主题是如何随着时间的推移而变化的。

图 4 :根据创建日期总结的流行存储库的分布。图片作者。

在上面的图 4 中,我们看到大多数最受欢迎的机器学习和深度学习知识库都是在 2016 年至 2020 年之间创建的。这两个主题的普遍受欢迎程度的增加在图中也非常明显,并由 2009 年至 2017 年创建的存储库数量的急剧增加所证明,在此之前,随着数据接近 2021 年,存储库的数量略有减少。

图 5 :历年来机器学习和深度学习知识库标签化的热门话题。图片作者。

接下来,GitHub 存储库的所有者可以选择用相关主题标记他们的存储库。例如,本文最后一节讨论的 keras 存储库的所有者将主题“python”、“数据科学”、“机器学习”、“深度学习”、“tensorflow”和“神经网络”标记到他们的存储库中。

我收集数据的机器学习和深度学习存储库包含数百个不同的主题,它们的所有者给它们贴上了标签。为了总结这些数据,我将重点放在了根据它们被添加到存储库中的总次数排名的前 10 个最受欢迎的主题上。图 5 展示了标记有这些主题的存储库的数量是如何随时间变化的。图中每个方块的大小显示了当年有多少存储库提到了这个主题。我们在图 4 中看到了类似的趋势,从 2009 年到 2013 年创建的少量存储库解释了该图左侧几乎空白的部分。

分析流行的机器学习和深度学习知识库的所有者

正如本文前面所讨论的,GitHub 存储库可以归个人或组织所有。在这里,我将深入探讨最流行的机器学习和深度学习库的所有者。

首先,我们将看看拥有顶级机器学习或深度学习知识库的个人位于何处,然后我们将看看最受关注的前 25 名用户。之后,我们将查看拥有最高星级的库和他们使用的最流行的编程语言的前 25 个组织。

图 6 :拥有流行的机器学习或深度学习知识库,并提供有效位置信息的个人的位置。图片作者。

GitHub 为个人提供了在个人资料中包含位置信息的选项。一些用户选择包含这些信息,而另一些用户选择不包含这些信息。在我从 GitHub 收集的仓库所有者数据中,大约 50%拥有流行的机器学习或深度学习仓库的个人包括有效的位置值(总共大约 1000 个人)。

图 6 显示了所有提供有效位置信息的个人的平均纬度和经度值,按国家分类。我们可以看到有大量的个体位于美国和中国,并且有几个个体分散在欧洲各国。有趣的是,在加拿大,看起来大多数用户来自东海岸,特别是多伦多附近。

图 7 :关注人数最多的人。图片作者。

接下来,我们来看看关注最多的前 25 名用户以及他们所在的位置。图 7 展示了这些数据。由于前 25 个最受关注的用户中只有 22 个在其个人资料中提供了有效的位置,因此图中只有 22 个数据点。我们可以看到这些人中的大多数来自北美。

图 7 中包括的一些著名人士是:

图 8 :从事机器学习或深度学习的最受欢迎的组织,按其所有公共存储库收到的总星级排名。图片作者。

现在,我们将更详细地查看拥有流行的机器学习或深度学习存储库的前 25 家组织。图 8 展示了这些组织在 GitHub 上的所有公共存储库中获得的总星级。正如预期的那样,许多顶级技术公司都包括在这个数字中,如阿帕奇,阿里巴巴,脸书研究,微软和英伟达。图 8 中的许多组织也从事机器学习或深度学习以外的主题,因此他们在所有公共存储库中获得的一些星星将与其他主题相关。

图 9 :排名前 25 的组织使用的前 5 种编程语言。图片作者。

图 10 :从 2009 年到 2021 年,排名前 25 位的组织如何使用排名前 5 的编程语言。图片作者。

让我们继续关注这 25 个组织,更详细地了解一下他们使用的编程语言。图 9 展示了他们使用的前 5 种编程语言,按照实现它们的存储库总数的顺序,依次是 Java、Python、C#、C++和 JavaScript。

此外,图 10 展示了这些语言的流行程度是如何随着时间的推移而变化的。我们可以看到从 2015 年到 2020 年 Python 的受欢迎程度急剧增加,这与我们之前在图 4 中观察到的机器学习和深度学习知识库的数量增加直接对应。这是有意义的,因为 Python 已经成为用于机器学习和深度学习任务的最流行的编程语言。

总结和最终想法

使用在最流行的机器学习和深度学习 GitHub 仓库及其各自所有者上收集的数据,我们看到:

  • 总的前 10 个最受欢迎的存储库包含 5 个与机器学习相关的存储库,以及 5 个与深度学习相关的存储库。
  • 这些存储库中使用的最流行的编程语言是 Python。
  • 大多数流行的机器学习和深度学习知识库都是在 2016 年至 2020 年之间创建的。
  • 个人存储库的大多数所有者位于北美、亚洲或欧洲。
  • 从事机器学习或深度学习的最受关注的个人包括技术领域的一些知名人士。
  • 从 2009 年到 2021 年,从事机器学习或深度学习的组织越来越多地使用 Python,而其他语言的受欢迎程度略有下降。

分析来自 GitHub 的这些数据是一个有趣的项目,它让我能够使用我的数据收集、数据清理和数据可视化技能。我还喜欢检查几个 GitHub 库,在我完成这个项目时,我收集了关于这些库的更详细的数据。这让我能够为我计划从事的未来机器学习和深度学习项目汲取灵感。

感谢您花时间阅读我的文章。如果你想讨论我的分析,或者任何与机器学习或深度学习有关的事情,请随时联系我。还有,你可以在 LinkedIn 上找到我 这里

奖励部分:用几个简单的步骤重新创建这个分析!

在创建支持本文的编程脚本时,我将它们与 GNU Make 脚本相结合,这样任何人只需点击几下鼠标,就可以轻松地重新创建整个数据收集、数据清理和数据可视化过程。如果您想这样做,请遵循我的 GitHub 存储库中的自述文件“复制该分析”一节中的说明。

参考

[1]维基百科贡献者, GitHub (2021) ,维基百科

[2]opensource.com 贡献者,什么是开源? (2021),opensource.com

用 Neo4j 探索 NFT 交易

原文:https://towardsdatascience.com/exploring-the-nft-transaction-with-neo4j-cba80ead7e0b

600 万次 NFT 交易的探索性图形分析

几个月前,《自然》杂志发表了一篇文章,绘制了 2017 年 6 月至 2021 年 4 月间主要从以太坊和区块链蜡像馆获得的 610 万笔交易。这是一篇激动人心的文章,分析了市场的统计属性以及一些网络特征。作者还在 CC-BY 4.0 许可下提供了底层 NFT 事务数据集的

交易可以被描述为交易者之间的联系,那么还有什么比图形更好的方式来表示数据呢?首先,迈克尔·亨格和我将数据集导入到 Neo4j ,一个本地图形数据库。然后,我执行了一个简单的探索性图形分析,以更好地理解底层数据集,我将在这篇博文中演示。

设置环境

首先你需要下载并安装 Neo4j 桌面应用。数据集以数据库转储的形式提供,您可以通过点击此链接下载。您需要将文件复制到 Neo4j 桌面文件文件夹,然后选择从转储创建新的 DBMS

从转储创建新 DMBS。图片由作者提供。

建议选择最新版本的 Neo4j 数据库。接下来,你还需要安装 APOCGDS 库。

安装 GDS 和 APOC 库。图片由作者提供。

由于这是一个稍大的数据集,因此还建议增加堆和页面缓存内存分配。我选择 4GB 内存用于堆分配,2GB 用于页面缓存。

增加内存分配。图片由作者提供。

恭喜你,你已经成功准备好了 Neo4j 环境。

图形模式模型

NFT 事务的图形模式模型。图片由作者提供。

该数据集围绕着交易者之间的交易。每笔交易都有一个日期和价格加密和美元。由于这是一个 NFT 交易的数据集,所以每笔交易都描述了出售了哪个 NFT。有趣的是,大多数 NFT 都有一个图片 URL,这样你就可以检查互联网上出售的图片。一些 NFT 有多达四个图像 URL 用于冗余。我们还知道一幅 NFT 作品是否属于某个系列,以及它属于哪个类别。

探索性图形分析

现在我们可以从探索性的图形分析开始。和往常一样,我准备了一个 Jupyter 笔记本,里面包含了本帖中的所有问题。

首先,我们将使用apoc.meta.stats过程评估节点的数量和关系。

CALL apoc.meta.stats
YIELD nodeCount, relCount, labels

结果

apoc.meta.stats 程序的结果。图片由作者提供。

图中大约有 1100 万个节点和 2300 万个关系。数据集包含大约 460 万个 NFT 的 600 万个事务。NFT 是 4600 个集合和 6 个类别的一部分。

现在,我们将更深入地挖掘,并开始检查每年的交易计数、总交易量和非金融资产的平均价格。

MATCH (t:Transaction)
RETURN t.Datetime_updated.year AS year, 
       count(*) AS transactions, 
       sum(t.Price_USD) AS totalVolume, 
       avg(t.Price_USD) AS averagePrice
ORDER BY year

结果

2018 年,只有 45 万笔交易,而在 2021 年,截至 4 月份,有近 350 万笔交易。多年来,平均价格和总量在 2021 年的前四个月已经上升到近 7.5 亿美元。NFT 世界确实出现了繁荣。

接下来,我们将评估有多少交易的价格低于或高于一美元。

MATCH (t:Transaction)
WHERE exists(t.Price_USD)
RETURN CASE WHEN t.Price_USD > 1 THEN true ELSE false END AS moreThanDollar, count(*) AS count

大约 55%的交易价格超过 1 美元。还剩下大约 270 万笔低于 1 美元的交易。似乎大额交易并不频繁,所以当一些交易发生时,就会成为新闻。让我们用apoc.agg.statistics过程来检查超过一美元的交易的分布。

MATCH (t:Transaction)
WHERE exists(t.Price_USD) AND t.Price_USD > 1
RETURN apoc.agg.statistics(t.Price_USD) AS result

结果

一元以上 NFT 交易的价格分布。图片由作者提供。

超过一美元的交易平均价格是 266 美元。另一方面,99%的交易低于 3349 美元。这意味着只有极小比例的交易非常昂贵,最高交易价值为 750 万美元。

我们可以用下面的 Cypher 语句来检查哪些 NFT 以最高价格出售。

MATCH (n:NFT)<-[:FOR_NFT]-(t:Transaction)
WHERE exists(t.Price_USD)
WITH n, t.Price_USD as price
ORDER BY price DESC LIMIT 5
RETURN n.ID_token as token_id, n.Image_url_1 as image_url, price

结果

作为一名数据分析师,我非常怀疑两个 NFT 被估价为相同的价格,最重要的是,它们都是 750 万美元。因为我们有图片网址,你可以查看哪些图片的价值超过了 100 万美元。看起来加密朋克的收藏品价值很高。

我们可以深入挖掘,检查 750 万美元交易中涉及哪些账户。

MATCH (n:NFT)<-[:FOR_NFT]-(t:Transaction),
      (t)<-[:BOUGHT]-(buyer),
      (t)<-[:SOLD]-(seller)
WHERE t.Price_USD = 7501893.0
RETURN buyer.address AS buyer, 
       seller.address AS seller, 
       t.Datetime_updated_seconds AS date, 
       t.Price_USD AS price

结果

多么奇怪的巧合,两笔交易在同一天执行,中间只隔了大约 19 个小时。买家和卖家似乎没有关系,尽管全是零的地址引起了我的注意。经过一些调查,我了解到当有人在 OpenSea 平台上创建 NFT 时,空地址总是显示为创建者。另一方面,您也可以向空地址发送一个 NFT 来有效地删除 NFT。至少网上的一些帖子是这么说的。在我戴上夏洛克·福尔摩斯的帽子后,我在 OpenSea 上找到了的空地址简介,在那里你可以从他们那里买到 NFT。这让我更加困惑,因为我会假设向空地址出售 NFT 会有效地烧掉 NFT 令牌,但谁会送价值 750 万美元的 NFT 去烧它。也许我完全误解了,因为这是我对 NFT 生态系统的第一次分析,而我对此一无所知。无论如何,这一切似乎有点可疑。这两笔交易具有相同的价格,并在同一天执行。我已经检查了这三个地址之间是否有任何交易,但是数据集不包含这样的交易。

接下来,我们将评估 NFT 系列及其平均成本。

MATCH (collection)<-[:IN_COLLECTION]-(n:NFT)<-[:FOR_NFT]-(t:Transaction)
WHERE exists (t.Price_USD)
RETURN collection.Collection AS collection, 
       avg(t.Price_USD) AS averagePrice, 
       count(distinct n) AS numberOfNfts
ORDER BY averagePrice DESC
LIMIT 5

结果

大多数最高价值的集合在我们的数据集中只有一个 NFT。有趣的是,尽管他们周围有数百万美元的交易,但加密朋克甚至没有进入前五名。

接下来,我们将探究哪些交易者执行了最多的交易。

MATCH (t:Trader)
RETURN coalesce(t.username, t.address) AS username,
       size((t)-[:BOUGHT]->()) AS bought,
       size((t)-[:SOLD]->()) AS sold
ORDER BY bought + sold desc LIMIT 5;

结果

排名前五的交易商已经买入或卖出了超过 4 万笔 NFT。由于所有的数据都可以在互联网上找到,我们可以看看的顶级简介。似乎自 2020 年 4 月以来,他们一笔交易也没有达成。另一方面,strong OpenSea 上的 Hands 个人资料有 17000 个可供购买的 NFT。

我们已经查看了交易数量最多的交易商,现在我们将查看以美元计算的交易量最多的交易商。

MATCH (t:Trader)
OPTIONAL MATCH (t)-[:BOUGHT]->(bt)
WITH t, sum(bt.Price_USD) AS boughtVolume
OPTIONAL MATCH (t)-[:SOLD]->(st)
WITH t, boughtVolume, sum(st.Price_USD) AS soldVolume
RETURN t.username AS username, 
       t.address AS address,
       boughtVolume, 
       soldVolume
ORDER BY boughtVolume + soldVolume
DESC LIMIT 5

结果

最大的卷具有 NullAddress 帐户。我不知道为什么它有超过 5000 万美元的购买。甚至在此之前,我们有一个例子,有人发送了一个 NFT 到 4200 ETH 的 NullAddress。也许你可以选择任意一个数字的交易金额当你烧 NFT 的时候。也许一些专家可以帮我解决这个问题。

另一方面,第二个地址只对出售感兴趣,这也是奇特的。我检查了数据集中地址的最高交易,似乎这是 Sorare 项目的钱包,看起来像是带有 NFT 代币的梦幻足球。我猜他们自己铸造代币,只卖给他们的平台用户。

接下来,我们将探究哪些用户转售了利润最高的 NFT。

MATCH (t:Trader)-[:SOLD]->(st:Transaction)-[:FOR_NFT]->(nft)
WHERE st.Price_USD > 100000
MATCH (t)-[:BOUGHT]->(bt:Transaction)-[:FOR_NFT]->(nft)
WHERE st.Datetime_updated_seconds > bt.Datetime_updated_seconds
RETURN coalesce(t.username, t.address) as trader, 
       nft.Image_url_1 as nft, 
       nft.ID_token AS tokenID,
       st.Datetime_updated_seconds AS soldTime,
       st.Price_USD AS soldAmount,
       bt.Datetime_updated_seconds as boughtTime,
       bt.Price_USD AS boughtAmount,
       st.Price_USD - bt.Price_USD AS difference
ORDER BY difference DESC LIMIT 5

结果

看来隐朋克是(是?)最赚钱的代币。例如,一名用户在 2021 年 3 月 12 日以 70 万美元的价格购买了 Cyptopunk 3011 NFT,然后在一个月后以 170 万美元的价格转售。对于一个抽烟斗的家伙的像素图像来说,这是一笔不错的交易。现在,你可能会说,为什么有人会以 70 万英镑的价格出售一幅 NFT 作品,而他们可以得到 100 万英镑,但问题就在这里。那个人在 2020 年 10 月以 1.6 万美元买入,2021 年 3 月以 70 万美元卖出。实际上,从 2020 年 10 月到 2021 年 3 月,NFT 的价格上涨了 100 倍。

图形算法

最后,我们将在数据集上运行一些图形算法。我们将在交易者之间构建一个推断的有向加权交易网络。关系的方向将表示资金的流向,而权重将表示数量。我们将使用 Cypher 投影来投影一个虚拟网络,它是底层存储图的转换版本。

CALL gds.graph.create.cypher("nft", 
"MATCH (t:Trader) WHERE NOT t.username = 'NullAddress' RETURN id(t) as id",
"MATCH (t1:Trader)-[:BOUGHT]->(t)<-[:SOLD]-(t2:Trader)
 RETURN id(t1) AS source, id(t2) as target, coalesce(sum(t.Price_USD),1) as weight")

我们将执行的第一个算法是弱连通分量算法。它用于查找网络中断开的部分或孤岛。

CALL gds.wcc.stats("nft")
YIELD componentCount, componentDistribution

结果

WCC 结果。图片由作者提供。

NFT 的交易网络相当混乱。有 5287 个独立的部分,最大的部分只包含了 12%的交易者。这意味着有几个小组件,其中交易者只在一小组用户之间进行交易。更奇怪的是,超过 75%的组件由单个用户组成。这意味着发送者和接收者都是同一用户。

让我们来看看一个有自循环的样本交易者。

MATCH p=(t:Trader)-[:BOUGHT]->()<-[:SOLD]-(t)
WHERE t.username = "grake"
RETURN p LIMIT 10

结果

在交易中作为卖方和买方的用户的样本子图。图片由作者提供。

起初,我认为这是底层数据集中的一个错误。然而,我在 OpenSea 平台上检查了一个单个交易,看起来用户可以向自己出售一个 NFT。然而,我认为这个平台有一些机制,这使得日志很混乱。

NFT 代币历史截图。图片由作者提供。

最后。我们将执行 ArticleRank 算法,这是 PageRank 算法的一种变体,用于查找网络影响者。

CALL gds.articleRank.stream("nft")
YIELD nodeId, score
WITH gds.util.asNode(nodeId) AS node, score
ORDER BY score DESC
LIMIT 5
RETURN node.username as username,
      score,
      size((node)-[:BOUGHT]->()) as boughtCount,
      size((node)-[:SOLD]->()) as soldCount,
      apoc.coll.sum([(node)-[:BOUGHT]->(t) | coalesce(t.Price_USD,0) ]) as boughtVolume,
      apoc.coll.sum([(node)-[:SOLD]->(t) | coalesce(t.Price_USD,0) ]) as soldVolume

结果

结论

我们只是触及了这个数据集的可能分析的表面。我鼓励您在您的 Neo4j 实例上设置数据集,并尝试找到一些有趣的见解。你也可以看看原始文章,了解如何进行这项研究的一些想法。如果你发现有趣的东西,让我知道。

和往常一样,代码可以在 GitHub 上获得。

参考

探索 Julia 中文档的细微差别

原文:https://towardsdatascience.com/exploring-the-nuances-of-documentation-in-julia-f4153be19d3d

浏览 Julia 文档的所有奇怪之处,以及如何处理这些奇怪之处

(图片由 MediaModifierPixabay 上拍摄)

介绍

文档无疑是软件最重要的组成部分之一,尤其是在为其他计算机程序员制作模块和库的时候。在大多数情况下,对于作为依赖项加载模块的最终用户来说,文档将是他们方法的唯一参考点。这意味着如果没有足够的文档,在很多情况下,许多模块对这类用户来说是完全无用的。

也就是说,虽然文档非常重要,但它并不总是导航或编写的最显而易见的东西。这适用于许多语言,但特别是一种语言——我最喜欢的语言,它有一个相当健壮的文档系统,功能齐全,非常好用,但也有一些细微差别,可能会使普通程序员对另一种编程语言感到困惑或产生无法回答的问题。我以前写过文章,讨论 Julia 的文档,它的缺点,甚至为什么我认为 Julia 有很棒的文档字符串。如果您想对我将在本文中讨论的主题有所了解,它们可能值得一读,您可以在这里找到它们:

我认为像这样的概念

"一种使用多重分派作为范例的语言."

本质上是很难记录下来的,不管你怎么处理它。这是因为对于每个单独的调用,文档通常会有很大的不同,因为输出可能会根据输入发生很大的变化,而输入是唯一变化的东西。也就是说,我确实认为 Julia 处理得很好,但是我要第一个承认我使用 Julia 大约半年,在我意识到一些关于文档字符串系统的事情之前。在这方面,我并不孤单,我可以肯定地说,对 Julia 的一个批评是在语言的内置文档中。是的,我知道这是一个令人困惑的句子,但是在 Julia 中创建文档的文档是非常重要的——如果没有正确的文档,那么,我们在其他任何地方都会有糟糕的文档。

为了证明这种说法是正确的,让我们试着在谷歌上快速搜索一下……通过查询“Julia documentation documentation ”,我们得到了常规的 Julia 文档。我想这是有道理的,因为我们有两次列出的文档,谷歌搜索查询并不完全像我们的英语一样工作,但在我们进一步深入之前,让我们深入了解基本的文档。此外,为了演示这种语言的文档系统,有一个笔记本,记录了我编写和记录的一些代码,所以如果您想查看实际运行的代码,可以看看这里的笔记本:

https://github.com/emmettgb/Emmetts-DS-NoteBooks/blob/master/Julia/documenting Julia.ipynb

基本文件

在我们继续之前,重要的一点是,Julia 是一种主要由自身编写的语言。在一个普通的 Julia 软件组件中调用的大多数方法都包含在一个叫做 Base 的模块中。这个包包含从基本数据类型到索引的所有内容,对于今天的主题,它还包含

文档。

文件部分存放在基地。文档模块。既然我们意识到了这一点,质疑“朱丽亚基地。Google 上的“文档”文档仍然很少或没有显示关于 Julia 的文档字符串或文档系统的文档或信息..我能找到的最好的文档不是在正规的 Julia 文档网站上,而是在阅读文档:

让我们从最基本的开始。来自大多数其他语言的人可能会熟悉在他们的代码上添加一个多行字符串来记录它:

"""
The example function takes y, an Array{Int64} and x, a 64-bit integer.
"""
function examplefunction!(y::Array, x::Int64)
    x += 1
    push!(y, x)
end

对于上面的例子,这个文档工作得很好——但是,我认为这个文档字符串很糟糕。如果我们想要查看与给定模块、函数或类型相关的文档,我们可以使用?()方法。让我们看看上面的 doc-string 在使用这个方法调用时的情况:

?(examplefunction!)

(图片由作者提供)

首先,虽然这个 doc-string 解释了函数的输入,但它是以一种非常冗长的方式解释的。这对 Julia 来说也很奇怪,因为通常类型是用::,而且任何 Julia 程序员都应该能够通过函数头识别函数名和每个多态调用传递的参数。这个文档的另一个问题是没有输出的概要,我们不知道这个函数的返回是什么。我有一个简短的技术列表,我用它来提供 Julia 和其他地方的文档的基本要素,如果人们希望学习更多关于编写好的文档的知识,他们可以研究一下,所以如果你想提高这方面的技能,研究一下那篇文章中讨论的一些主题可能是有意义的。你可以在这里找到这篇文章:

</5-incredibly-useful-tips-for-writing-pristine-documentation-803155ae4f45>

关于 Julia 的文档,需要记住的一件重要事情是,它也可以用 markdown 编写。此外,这种降价是普遍的,并转移到 REPL 真的很好,只要看看这个例子从基地。推!()在 REPL:

(图片由作者提供)

减价的特点是粗体、标题、例子和其他各种吸引眼球的东西。虽然这看起来有些武断,但文档通常需要分章节完成——在某种程度上,所以使用 markdown 是一个很好的主意,这样可以使文档更容易被人理解,而不仅仅是机器人和书呆子。从我们的文档字符串的顶部开始,让我们从定义输入开始:

"""
# examplefunction!(y::Array, x::Int64)"""
function examplefunction!(y::Array, x::Int64)
    x += 1
    push!(y, x)
end

然后我们将添加输出,一个简短的描述这个方法实际做什么的描述符,然后是一个例子——都是典型的 Github 风格的标记:

"""
# examplefunction!(y::Array, x::Int64)
The example function will increment **x** by one before pushing **x** into the array **y**.
#### Example

x = 5
y = [1, 2, 3, 4, 5]examplefunction!(y, x)println(y)[1, 2, 3, 4, 5, 6]

"""
function examplefunction!(y::Array, x::Int64)
    x += 1
    push!(y, x)
end

鉴于没有输出,我们真的不需要去了,解释点!,在我们函数的末尾,通常是一个很好的提纲,说明要么没有函数的返回,要么函数的返回将是一个突变的类型。在朱莉娅,这!添加到方法的末尾意味着它将改变我们提供给它的类型。我个人喜欢做的另一件事是用粗体提供参数描述,在我的主观观点中,我觉得这使它们更容易与方法调用中的位置参数名联系起来。

这种描述输入的方法明显优于后者,因为那些习惯于用 Julia 编程的人会毫不费力地意识到在这个函数的哪个位置提供了哪些类型。再者,看起来更快。就标题级别而言,您可能已经注意到基础文档不包含任何标题级别的使用。我认为这是一个错误。请允许我详细说明…

多份发货文件

正如我前面提到的,记录一种围绕多重分派的编程语言是一项艰巨的任务。这是因为不同函数名的输入经常发生变化,这些调用中的每一个都需要在同一个别名下有不同的描述符。这使得调用。()方法的别名非常困难,因为我们必须导航所有相关的函数。让我们看看目前为止我们所拥有的,例如 function!():

?(examplefunction!)

(图片由作者提供)

这很好,但是在 Julia 中,很多时候我们会对不同的方法使用相同的别名。这使事情变得复杂,因为在同一个函数名下有两个不同方法的情况下,Julia 会怎么做呢?幸运的是,Julia 为我们将它们连接在一起,因此如果我们只单独调用方法的名称,我们将会收到包含在该函数定义中的每个方法的所有文档。请允许我向您介绍 examplefunction!(::Dict,:Int64)。

function examplefunction!(y::Dict{Int64, Int64}, x::Int64)
   x += 1
    key = maximum(keys(y)) + 1
    push!(y, key => x)
end

这需要一个字典,包含成对的 Int64 和一个整数。与之前的函数的唯一区别是,现在我们必须为推送获取一个键!()方法,我们现在不是推送整数,而是推送一对。为了得到这个键,我只需要得到字典中当前键的最大值,然后将这个值加 1。和以前一样,让我为此写一个简短的文档字符串:

"""
# examplefunction!(y::Dict{Int64, Int64}, x::Int64)
The example function will increment **x** by one before pushing **x** into **y**
with the next available key in the dictionary
#### Example

x = 5
y = Dict(1 => 5, 2 => 6)examplefunction!(y, x)println(y)Dict{Int64, Int64} with 3 entries:
2 => 6
3 => 6
1 => 5```
"""
function examplefunction!(y::Dict{Int64, Int64}, x::Int64)
x += 1
key = maximum(keys(y)) + 1
push!(y, key => x)
end


现在,终于让我们称之为?()方法在这个函数上重复一遍:

?(examplefunction!)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2022/-/raw/master/docs/img/2785bd2f7d47e5077890d88e160102f8.png)

(图片由作者提供)

现在让我们试着删除标题级别,

# /#,并用纯文本替换它,以演示为什么我认为推!()示例的分离可能有问题:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2022/-/raw/master/docs/img/1c2820226e8eddad34ded2493f247ba7.png)

(图片由作者提供)

这里的一个大问题是,虽然这个文档在大多数情况下肯定是有效的,但是很难看出我们可以在这个函数中使用哪些不同类型的参数和调用。我认为,根据方法调用的类型,使用标记来分离方法调用无疑是一个好主意。

您可能已经注意到的最后一件事是 Julia 使用逻辑右操作符来表示函数的输出。我认为这是一个伟大的想法,所以在未来,我想我会采取这一点。我认为它用一行输入和输出很好地描述了这个函数:

"""

examplefunction!(y::Dict{Int64, Int64}, x::Int64) -> y

The example function will increment x by one before pushing x into y
with the next available key in the dictionary

Example

x = 5
y = Dict(1 => 5, 2 => 6)examplefunction!(y, x)println(y)Dict{Int64, Int64} with 3 entries:
  2 => 6
  3 => 6
  1 => 5```
"""

关于这种文档,最后要注意的一点是,我们还可以通过在调用?()方法,像这样:

?(examplefunction!(::Array, ::Int64)

这将特别为该方法生成更具体的文档。

基地。文件(documents 的简写)

在这篇概述中,我想讨论的最后一个主题是基础。文档模块本身。这个模块的大部分实际上是一个宏的后端,这个宏就是@doc 宏。我们可以像这样直接导入宏:

using Base.Docs: @doc

每当我们在一个给定的定义上创建多行字符串时,这个宏实际上会被调用。让我们用幽默来娱乐自己。()来浏览记录我们代码的宏文档,以便我们可以使用?()方法在上面。

这感觉像是一个悖论。

?([@doc](http://twitter.com/doc))

(图片由作者提供)

看哪!

这是迄今为止我们所看到的关于 Julia 文档的最好的文档(我已经厌倦这么说了)!每当我们使用。()为了获得文档…等等…这给了我一个可怕的想法..

?(?)

(图片由作者提供)

Awwww

离开这个有趣的话题,让我们来看看在 Julia 中使用@doc 宏来记录代码。首先要考虑的是,这个宏通常与现有的定义一起使用。换句话说,我们需要某种已定义的名称,不管它是构造函数还是函数。@doc 宏首先接受一个字符串,即我们希望分配的文档,然后是我们希望记录的内容。在名副其实的 examplefunction 的例子中!,我们可以这样记录它:

[@doc](http://twitter.com/doc) "I'm not writing any more than this." examplefunction!(::Array, ::Int64)

一般来说,这种方法的使用非常有限,在大多数情况下,忽略@doc 宏会好得多——以前每当编写文档字符串时(Julia 1.0 之前的版本)都需要使用该宏,而只是坚持编写常规的文档字符串而不使用@doc。也就是说,我认为了解底层的方法调用很重要,这样可以更好地理解为什么有些东西不能正常工作,或者更好地理解文档系统。此外,还有一些更奇怪的 Julian 移动的场景,例如在内部构造函数的范围内定义函数并需要记录它们,这个宏当然可以方便地生成文档,而不必像通常定义的那样定义函数。

结论

尽管在 Julia 中使用多分派的全功能方法创建优秀文档的挑战肯定是存在的,但还是有一些方法可以减轻多态性带来的问题。幸运的是,Julia 已经有了很多这样的系统,非常棒,唯一的问题是,在很多情况下,和他们一起工作的人不理解这些系统。希望这篇文章有助于揭示 Julia 编程语言中一个缺乏文档记录的部分。

Base 中的很多东西都是这样的,其中有一些模块,人们几乎不知道它们是如何工作的。我发现这是一个很大的失望,因为我认为编程朱莉娅的 REPL 做一些完全不同的事情,例如,很有趣——但由于缺乏内部文档,变得更加困难。当然,这并不是说 Julia 开发人员的 Julia 文档,但是即使在那里,这些模块的文档范围也是非常有限的。由于 Julia 是一门如此伟大的语言,人们只能希望这些东西会随着时间的推移而开花结果,在它们开花结果之前,我会在这里分享我发现的知识,希望以一种有吸引力的方式。感谢您阅读我的文章,它对我来说意味着整个世界,祝您用您的文档技能自信地编写代码时愉快!

使用 Python 探索感知器算法

原文:https://towardsdatascience.com/exploring-the-perceptron-algorithm-using-python-c1d3af53a7c7

从理论到实践,这里是你需要知道的关于这个简单而有趣又强大的方法的一切。

弗拉季斯拉夫·巴比延科在 Unsplash 上的照片

好了,经典的机器学习情况。你有一个表格数据集,你必须对它进行分类。你是怎么做到的?

首先,你需要非常了解你可能会用到的工具。你可以尝试使用的一个非常著名的算法是感知器。

从理论到实践,我们将从一个简短的理论介绍开始,然后展示一个实际的实现来检验这种机器学习方法。

在这篇博文的最后,你将能够理解何时以及如何使用这种机器学习算法,对其所有的利弊有一个清晰的想法。

1.该理论

1.1 简介

感知机有生物学上的理由存在。我们的神经元不断从其他神经元接收能量,但只有当它们接收的能量大于或等于一定量时,它们才决定被“激活”并发出自己的信号。

先说最终产品。最后,给定一个四维输入,这个输入用 4 个不同的权重处理,总和进入激活函数,你得到结果。没有比这更复杂的了。😃

作者图片

让我们说得更清楚些。假设您有这个特性表(列)X1、X2、X3 和 X4。这些特征是表征数据集的单个实例(行)的 4 个不同值。

这个实例需要进行二进制分类,这样你将有一个额外的值 t,这是目标,可以是-1 或 1。

感知器算法 X1、X2、X3 和 X4 乘以一组 4 个权重。出于这个原因,我们认为感知器是一个线性算法(稍后会详细介绍)。

然后,一个激活函数将被应用于该乘法的结果(同样,稍后将详细介绍激活函数)。

下面是一个等式中的整个过程:

其中 a 是所谓的激活功能。

当然,输入可以是 N 维的(N 不必是 4),因此您也可以使用 N 个权重+ 1 个偏差。尽管如此,纯感知器算法意味着用于二进制分类(后面会有更多)。

当然,y=a(w_1x_1+…+w_4x_4)的结果需要在-1 和 1 之间。换句话说,在一天结束时,所谓的激活函数需要能够给你一个分类。

那么这个经常被讨论的激活功能是什么呢?嗯,无非是一个步进函数。什么意思?

你的 N 维输入与 N 维权重的乘积会给你一个数字。那么如果这个数是大于 0 你的算法会说“1”,否则会说-1”

作者图片

这是最终产品。这就是它的工作方式,这就是它做决定的方式。这里没什么真正神秘的:)。

我们继续吧。

1.2 损失函数

我们都知道机器学习算法带有一个损失函数。在这种情况下,损失函数不过是错误分类点的加权和。

让我们把它变得简单些。假设你有一个没有很好分类的观点。这意味着,例如,将你的参数和你的输入相乘,你将得到-0.87 的最终结果。

作者图片

好吧,但重点还是那句,分类错误,还记得吗?所以这意味着对于那个点(t=1),目标确实是“1”。这意味着如果你做这个乘法:

作者图片

你实际上得到了一个量,这个量告诉你你错了多少,你应该改变你的权重和偏差来做更好的分类工作。

通常,损失函数是所有错误分类点的负和:

作者图片

其中 S 是错误分类点的集合。
我们的想法是开始优化这个损失函数,当然我们希望最小化。

作者图片

你在上面看到的等式被称为梯度下降。这意味着我们沿着损耗达到最小值的方向,并沿着这个方向更新参数。

由于损失函数取决于错误分类点的数量,这意味着我们将慢慢开始校正实例,直到这样一个点,如果数据集是线性可分的(稍后将详细介绍),将不再有“校正”的目标,并且我们的分类任务将是完美的。😃

2.实施

当然, SkLearn 感知器是一个众所周知的现成实现。尽管如此,为了更好地理解它,让我们从头开始创建这个感知机。

让我们从图书馆开始:

让我们定义决策函数:

2.1 线性可分离数据集

让我们使用 SkLearn 创建一个线性可分的数据集。

2.2 感知器功能

使用此功能,之前解释过的所有想法都可以实际实现:

然后,我们可以使用以下代码绘制决策边界:

让我们看看玩具数据集中发生了什么:

可以看到,所有的点都被很好地分类了(甚至是红色的小三角形)。

让我们看看损失函数图:

这意味着数据集现在已经完全分类了。

2.2 非线性可分离数据集

让我们考虑一个更难被认为是“线性可分”的数据集。

让我们运行算法:

好的,现在我们可能需要一点工作来得到我们最好的分类。

让我们运行不同数量的时期和不同的学习速率(所谓的超参数调整)来获得最佳版本的感知器:

这些是最佳的时期数和学习率:

3.更多考虑

以下是一些需要考虑的事项:

  • 感知器算法很快。其实无非就是线性乘法+阶跃函数应用。它超级简单易用。
  • 当数据集不是线性可分时,算法不会根据损失函数收敛。这意味着这个感知器只能(完美地)在线性可分离数据集上工作。尽管如此,我们可以对数据集应用转换,并对转换后的数据集应用感知器算法
  • 一个超参数调整部分可以显著提高算法的性能。

4.结论

如果你喜欢这篇文章,你想知道更多关于机器学习的知识,或者你只是想问我一些你可以问的问题:

A.在 Linkedin 上关注我,我在那里发布我所有的故事
B .订阅我的 简讯 。这会让你了解新的故事,并给你机会发短信给我,让我收到你所有的更正或疑问。
C .成为 推荐会员 ,这样你就不会有任何“本月最大数量的故事”,你可以阅读我(以及成千上万其他机器学习和数据科学顶级作家)写的任何关于现有最新技术的文章。

机器学习中嵌入的力量

原文:https://towardsdatascience.com/exploring-the-power-of-embeddings-in-machine-learning-18a601238d6b

如何释放数据的全部潜力

这个例子展示了当在低维空间中可视化时,嵌入是如何捕捉单词之间的关系的。作者图片

近年来,机器学习已经取得了很大进展,而帮助推进该领域的关键技术之一是嵌入的使用。在这篇博文中,我们将探索什么是嵌入,它们是如何工作的,以及为什么它们对机器学习如此重要。

在这篇文章结束时,我希望你能理解什么是嵌入,以及如何使用它们来提高你的机器学习模型的性能。所以,让我们开始吧!

什么是嵌入?

本质上,嵌入只是一种从原始数据中自动提取和表示有用特征的方式。这在许多不同的环境中非常有用,从自然语言处理任务如情感分析,到计算机视觉任务如图像分类。本质上,嵌入允许我们获取原始的、非结构化的数据,并将其转化为更适合用于机器学习算法的形式。

考虑嵌入的一种方式是作为一种自动特征提取。当我们处理原始数据时,它通常包含大量机器学习模型难以理解的信息。通过使用嵌入,我们可以从这些数据中自动提取(“学习”)最相关和最有用的特征,并以紧凑的形式表示它们。

机器学习通常用于学习这些嵌入,然后可以大大提高其他机器学习模型在下游任务上的性能。

嵌入在自然语言处理中的应用

作者图片

自然语言处理是机器学习的一个重要领域,嵌入是许多现代语言模型的重要组成部分。过去,语言模型通常将单词表示为一次性编码向量。这意味着单词的每个向量表示必须与词汇表中的单词数(可能有数百万个)长度相同!同时,这也意味着这些模型不能捕捉更复杂的语义,比如单词之间的关系。

然而,随着嵌入技术的出现,这种情况发生了变化,语言模型突飞猛进。嵌入允许我们以一种更加复杂的方式来表示单词,在一个密集的向量中捕获语法和语义信息,这与稀疏的一次性编码相反。这意味着我们的语言模型现在可以以更加微妙的方式捕捉单词和短语的含义,使它们能够执行从情感分析到机器翻译的广泛任务。

这个例子展示了当在低维空间中可视化时,嵌入是如何捕捉单词之间的关系的。作者图片

对于任何从事 NLP 工作的人来说,嵌入都是一个必要的工具。它们允许我们捕捉语言的复杂结构,并使用这些信息来训练更强大和准确的语言模型。通过嵌入,我们可以将我们的自然语言处理应用提升到一个新的水平,并释放自然语言处理的机器学习的全部潜力。

其他使用案例

虽然嵌入在 NLP 领域特别有用,但是它们并不局限于这种应用。事实上,嵌入可以在广泛的不同环境中使用,从推荐系统金融

在 NLP 之外如何使用嵌入的一个例子是在计算机视觉领域。当处理图像时,可能很难用适合在机器学习模型中使用的方式来表示它们。嵌入可以用来从图像中自动提取有用的特征,并以紧凑和易于理解的形式表示它们。这可以极大地提高计算机视觉模型的性能,并使其更容易在广泛的任务上进行训练。

Samuele Errico PiccariniUnsplash 拍摄的照片

嵌入有用的另一个例子是在推荐系统中。当我们向用户提出建议时,我们通常希望考虑各种不同的因素,例如他们过去的行为、他们的偏好以及其他用户的偏好。用户嵌入能够以一种紧凑和容易理解的形式表示所有这些信息,允许我们训练更准确和有效的推荐系统。

简而言之,嵌入是一种通用且强大的工具,可以在机器学习的许多不同环境中使用。无论您是在 NLP、计算机视觉还是推荐系统中工作,嵌入都可以帮助您训练更准确和有效的模型,并释放您数据的全部潜力。

嵌入是如何训练的?

理解嵌入是如何被训练的对于从你的嵌入中获得最大的价值和知道它们什么时候有用是非常重要的。在这一部分,我们将探索如何训练嵌入,以及为什么这是机器学习过程中如此重要的一部分。

为了训练一个嵌入,我们首先需要定义一个目标函数。这只是一个数学公式,告诉嵌入模型应该优化什么。例如,在自然语言处理(NLP)中,目标函数可能是在给定上下文的情况下最大化单词的概率(如众所周知的 Word2Vec 框架中的情况),或者最小化具有相似含义的单词之间的距离。

作者图片

一旦我们定义了我们的目标函数,我们就可以开始训练嵌入。这通常包括向模型提供大量数据,并让它了解数据中不同元素之间的关系。例如,在 NLP 中,模型可能知道单词“cat”和“kitty”经常出现在相同的上下文中,并且应该由嵌入空间中靠得很近的向量来表示。

随着模型的训练,它将调整嵌入向量中元素的值,以便更好地满足目标函数。这个过程可能需要一段时间,因为模型需要学习许多复杂的关系,以便产生有用的嵌入。然而,有了足够的数据和计算能力,模型最终将收敛于一组向量,这些向量以有用和信息丰富的方式表示数据。

总之,训练嵌入是许多机器学习管道中的关键步骤。通过定义一个目标函数并向模型提供大量数据,我们可以训练模型来产生在下游任务中有用的信息嵌入。

嵌入的缺点

虽然嵌入是一种强大而通用的工具,但是它们也有一些需要注意的缺点。使用嵌入的一个主要缺点是它们很难解释。不像传统的特征,通常是人类可读和容易理解的,嵌入通常被表示为高维向量,这对人类来说是难以理解的。这使得很难理解嵌入代表了什么,或者它是如何从原始数据中获得的。

嵌入可能缺乏可解释性——作者的图像

嵌入的另一个潜在缺点是训练它们的计算代价很高。因为它们通常涉及学习大量不同元素之间的复杂关系,所以训练嵌入可能需要大量数据和计算能力。这使得在实时应用或计算资源有限的设备上使用嵌入式变得困难。

虽然嵌入对于许多机器学习任务来说是一个有价值的工具,但是意识到它们的潜在缺点是很重要的。通过了解嵌入的局限性,我们可以就何时以及如何在我们的机器学习管道中使用它们做出明智的决定。

结论

总之,对于机器学习实践者来说,嵌入是一个强大而通用的工具。通过从原始数据中自动提取和表示有用的特征,嵌入可以提高各种机器学习模型的性能,从 NLP 到计算机视觉等等。虽然嵌入并不总是可解释的,并且训练起来计算成本很高,但对于任何希望从机器学习模型中获得最大价值的人来说,它们都是一个必不可少的工具。通过了解嵌入如何工作以及如何有效地使用它们,我们可以释放我们数据的全部潜力,并训练更准确和有效的机器学习模型。

如果你还不是一个媒体会员,在这里注册,你的一部分会员会分给你所阅读的作家!

https://medium.com/@riandolphin/membership

如果你喜欢这篇文章,你可能也会喜欢

通过 Strava 数据探索您的健康状况

原文:https://towardsdatascience.com/exploring-your-fitness-through-strava-data-90bffe391521

如何开始锻炼数据冒险(EDA)

图片作者。

如果你像我一样是一个数据迷,并且想把锻炼从琐事变成数据冒险,那么你来对地方了。这篇文章将向您展示制作自己的练习数据集是多么容易,以及如何使用 Python 访问和打开它。

从小到大,我从来都不是一个“健康”的孩子。我有点超重,从来没有给锻炼足够的机会,让它被认为是一种乐趣,而不是一件苦差事。像许多事情一样,当 2020 年 3 月疫情来袭时,这种情况发生了变化。到了四月底,我在家里呆得太久了,需要换换环境。我不想冒险接触任何人,但我需要出去。我选择了骑自行车。

从一次短暂的跑步经历中——一件让我膝盖受伤的琐事——我知道并重新安装了 Strava 健身应用。这个应用程序能够记录你在哪里跑步或骑车,以及其他有趣的数据,如总距离、平均速度等等。我想,如果我开始骑自行车,我也可能有数字来证明这一点。我的骑行开始是在人行道上 30 分钟的旅行,慢慢探索我公寓的周围区域。过了一会儿,我变得好奇起来,探索偏僻的小路和交通不畅的道路,发现了下一个城镇。在斯特拉瓦,我达到了我的第一个里程碑:一次骑行 10 英里。从这一点上说,骑自行车不是锻炼,而是一种冒险。我在 Strava 上不断探索和追踪我的里程碑。我跑了 20 英里,然后是 30 英里、40 英里,最后是 50 英里。

到 2020 年 7 月,我已经骑了 1000 英里,骑了 76 次不同的车。我不仅感觉更好,而且我现在已经把我自己的健身之旅记录成了一个数据集。在本文中,我将展示如何为探索性数据分析(EDA)收集这些数据,并解释用于解析的 GPX 格式。通过以后的几个帖子,我会通过数据分享我的健身之旅,告诉你如何分析自己的。如果你还没有自己的健身数据,创建一些吧!无论是跑步,骑行还是其他,这篇文章将告诉你如何开始自己的运动数据冒险。

免责声明:现在有很多健身应用,所以试试你最感兴趣的吧。Strava 很早就给我留下了深刻的印象,我发现很容易与之共事。主要目标是把数据探索和锻炼结合起来!此外,我已经支付了 Strava 的订阅费,因为我很喜欢它,但是你不需要订阅来访问你的数据!

访问 Strava 上的游乐设备数据

在 Strava 上查找您的乘车数据其实很容易。假设你至少有一次乘车分析——如果你没有,出去做一次!—第一步是在 Strava 的网站上登录您的账户。一旦你这样做,你会看到你的仪表板。如果你关注其他人的活动,你会默认在中心看到他们。我们关心的是你在左上方的个人资料摘要。

作者在 Strava.com 的图片。

单击您的个人资料摘要框中的“活动编号”,转到您的活动列表。然后按距离降序排列,这样你就可以从你最长的活动开始探索。对我来说,这个旅程也不是从我的家庭地址开始,所以很容易分享,没有任何隐私问题。我们将在以后的博客中探讨如何给你的数据添加隐私气泡。

斯特拉发活动清单。作者在 Strava.com 的图片。

点击列表中的蓝色标题,就可以进入某个游乐项目的详细信息页面。我选择了“骑到明矾溪”活动。一旦详细信息加载完毕,点击省略号(…)按钮并点击“导出 GPX”来下载您的骑行数据。

如何导出活动的 GPX 文件。作者在 Strava.com 的图片。

毫无疑问,还有其他方法可以从 Strava 下载数据——包括它的 API——但是这种方法对于我们目前的目的来说已经足够好了。

GPX 格式讲解

太好了,我们刚刚下载了一个. gpx 文件,但它到底是什么?GPX 是 GPS 交换格式的简称[1]。让我们看一下. gpx 文件的内部,以获得一些直觉。下面显示了该文件的缩略版本,带有一些分层注释:

在. gpx 文件中查看。图片作者。

该文件被分解成一个 XML 树结构,其中一个节点是所有其他节点的父节点。除了贯穿始终的一些元数据(旅行开始时间、旅行名称等。),文件由一个轨道节点组成。一个轨迹包含至少一个轨迹段,该轨迹段又包含多个轨迹点。每个轨迹点都包含按时间顺序排列的骑行“故事”。它也给出了 GPS 坐标(纬度和经度)以及你当时所处的高度和时间戳。

游乐设备数据在 XML 树中建模,但是它在物理上代表什么呢?下图描述了一项潜在的身体活动:

作者图片。

一般来说,一个. gpx 文件可以包含路线轨迹。路线是一组无序的路点——至少是一对 GPS 坐标——代表从起点到终点的粗粒度路径。一个路线示例是由谷歌地图绘制的 GPS 路线,用于将您的汽车导航到某个路线终点。通常有多个航点序列可以作为您到达目的地的路线,但通常您的导航应用程序会为您选择最佳(即最短)路线。如果你错过了一个转弯,计划的路线会更新以处理这个变化[1]。

轨迹是一组按时间顺序排列的轨迹点。与包含可能的路点的路线不同,轨迹代表了你所在的时空点的精确历史。这是一条记录你如何旅行的精细路径。在上面的漫画中,你到达了一个小道的尽头,打开你的自行车,在骑上环路之前打开了 Strava。如果你在立交桥下骑车时丢失了 GPS 信号,你的轨迹会继续,但会被记录为至少两个不同的轨迹段。一个轨道至少有一个轨道段,每个轨道段包含一组连续记录的轨道点[1]。

Strava 如何为 GPX 数据服务

值得注意的是 Strava。gpx 文件似乎只包含一个音轨片段。Strava 有一个自动暂停功能,当你不动的时候它会停止记录数据[2]。这不仅有助于节省手机电池,而且最终可以更准确地显示骑自行车的移动时间和平均速度。根据轨道段的定义,无论何时在行程中发生这种情况,我们都会期望有多个轨道段。或许,Strava 在上传后,将这些多个片段组合成仅仅 1 个。

用 Python 将 GPX 转换成 CSV🐍

虽然下载乘车数据很方便。gpx 格式则不然。为了便于使用,我们将把。gpx 结构变成了普通的。csv 格式。为此,我们需要解析。gpx 并将其放入一个表格熊猫数据框架中。

自从。gpx 格式本质上是 XML,我们可以使用 Python XML 库来解析节点,但幸运的是,有一个简单的、专门构建的替代方法叫做gpxpy。要安装软件包,请使用pip install gpxpy或您环境的相关软件包管理器。此处可找到包装的参考资料

下面是将. gpx 文件读入 Pandas 数据帧的代码:

数据提取代码位于一个with块中,作为上下文管理器来打开和关闭。gpx 文件。在这个块中,gpxpy包将 XML 树解析成一个 Python 对象。提取数据归结为遍历对象中存储的所有轨迹、轨迹段和轨迹点。在初始化 Pandas 数据帧之前,将每一行的数据存储在字典列表中。

加载的 GPX 文件的熊猫视图。图片作者。

将数据保存为. csv 格式现在非常简单:df.to_csv(file_path['out'], index=False)

结论

开始锻炼并不总是容易的。动机时好时坏,但作为一名数据科学家,我的好奇心总是旺盛的。有了 Strava 应用程序,我把锻炼的方式从苦役变成了刺激的冒险。其基础是能够创建和探索我自己的健身数据集。希望这篇文章能激发你用你的数据去尝试,并向你展示如何收集你自己的数据。

我看了一下如何在 Strava 上找到并下载你的锻炼数据。它采用. gpx 格式,但是我也介绍了这种格式的模型以及它的结构。最后,我分享了一个代码片段来轻松地将格式转换成。使用 Python 中的gpxpy和 pandas 包的 csv。

除了tracksegment列之外,乘车数据实际上只有另外 4 列。虽然这看起来没什么可做的,但我的下一篇文章将讨论如何为这些数据创建 EDA 策略。有比你想象的更多的东西需要探索!

[1] hikearizona, GPS 文件——GPX 解释 (2015),YouTube

[2] Jojo,自动暂停 (2021),Strava.com

简单解释了指数分布

原文:https://towardsdatascience.com/exponential-distribution-simply-explained-349d05b1bdb8

指数分布及其起源的简明解释。

Unsplash 上由 olieman.eth 拍摄的照片

介绍

在本文中,我们将探索每个数据科学家都应该知道的基本统计分布之一:指数分布。

简而言之,指数分布推断事件之间的等待时间的概率。例如,直到有人提出保险索赔的等待时间。

起源

为了真正理解指数分布,我们需要从 泊松过程 开始。泊松过程用于描述一个计数过程,其中事件随机发生,但以给定的速率发生。例如,回到保险索赔场景,我们知道每小时有 5 起索赔,但这些索赔在该时间段内随机发生。它们可以是均匀间隔的,或者全部在最后一分钟。

泊松过程以泊松分布为特征,泊松分布具有 概率质量函数(PMF) :

由作者在 LaTeX 中生成的图像。

其中 X 是一个随机变量,它是某个时间段内发生的个事件, λ 是该时间段内个事件的预期数量。****

回到我们的索赔类比,我们有一个 1 小时的时间段,在此时间段内预计会发生大约 5 起索赔。有 1 个索赔的概率是多少?

由作者在 LaTeX 中生成的图像。

非常小。

如果我们用 Python 绘制泊松分布的 PMF:

# import packages
from scipy.stats import poisson
import numpy as np
import matplotlib.pyplot as plt

# random variable
x = np.arange(0, 15)

# poisson distribution
y = poisson.pmf(x, mu=5)

# plotting
plt.figure(figsize=(9,5))
plt.plot(x, y, marker='o', color='black')
plt.xlabel('Random Variable X', fontsize=14)
plt.ylabel('Probability', fontsize=14)
plt.xticks(fontsize=14)
plt.yticks(fontsize=14)
plt.show()

作者用 Python 生成的图。

我们看到最高的概率是在 x = 5 ,这很直观,因为这是预期的数字!

注意:你可以从二项式分布推导出泊松分布。我在这里链接了一篇很棒的文章,带你完成这个推导。

这和指数分布有什么关系?指数分布描述了泊松分布事件之间等待时间的概率。

衍生物

指数分布告诉我们泊松过程中事件之间等待时间的概率。从字里行间来看,这意味着在给定时间段内没有事件发生:

由作者在 LaTeX 中生成的图像。

现在这只是一个时间段,然而我们将此概括为时间段。因此,我们必须等待 T 个时间段才能得到第一个事件:

由作者在 LaTeX 中生成的图像。

这有道理吗?我们说我们必须等待 t 时间段(在我们的索赔类比中这是 t 小时)直到第一个事件(索赔)发生。

另一方面,事件发生的概率是:

由作者在 LaTeX 中生成的图像。

这也是 累积分布函数(CDF)的定义。

CDF 的导数是 概率密度函数(PDF) :

由作者在 LaTeX 中生成的图像。

注: PDF 用于连续随机变量,而 PMF 用于离散随机变量。

因此,我们得到了指数分布!

例子

让我们为保险索赔示例绘制一个指数分布图。我们平均每小时受理 5 起索赔,这相当于索赔之间的平均等待时间为 12 分钟:

这也是指数分布的期望值或平均值 E[X],即 1/λ。这可以用我在上一篇文章中提到的力矩生成函数来展示!

*# generate data
x = np.arange(0, 2, 0.1)
y = 5 * np.exp(-5*x)# plot
plt.figure(figsize=(9,5))
plt.plot(x, y, marker='o', color='black')
plt.xlabel('Random Variable X (Time in Hours)', fontsize=14)
plt.ylabel('PDF', fontsize=14)
plt.xticks(fontsize=14)
plt.yticks(fontsize=14)
plt.savefig('plot1.png')
plt.show()*

作者用 Python 生成的图。

第一个索赔发生在第一个小时内的概率是多少?为了计算这个,我们简单地在 0 和 1 的边界之间积分 PDF:

由作者在 LaTeX 中生成的图像。

因此,这种可能性相当高,这是有道理的,因为我们预计索赔之间的平均等待时间为 12 分钟。

结论

在本文中,我们描述了指数分布以及它是如何得出的。简而言之,它测量泊松过程中事件之间等待时间的概率。

在我的下一篇文章中,我们将扩展这个来描述伽玛分布!

和我联系!

(所有表情符号由 OpenMoji 设计——开源表情符号和图标项目。许可证: CC BY-SA 4.0

暴露稀释——是什么?还有什么时候可以无视?

原文:https://towardsdatascience.com/exposure-dilution-what-is-it-and-when-can-you-ignore-it-65d1cf5a06d8

曝光稀释重要性快速指南

由 Fulvio Ciccolo 在 Unsplash 上拍摄的图像。

暴露稀释是设置实验时经常出现的概念,但具体是什么,什么时候可以忽略?在本文中,我们快速定义了暴露稀释,讨论了一个 web 案例研究,然后解释了可以忽略暴露稀释的关键案例。

了解暴露稀释

当在一个网站上运行 AB 测试时,你必须选择一个点来决定用户将看到什么版本(控制或测试),这通常被称为暴露点。通常,您会使曝光点尽可能接近您正在进行的实际更改。例如,如果您要在结账漏斗中添加一个步骤,您应该在用户看到新屏幕之前进行曝光。

这样做是因为如果你不曝光,你可能会有曝光稀释。暴露稀释背后的概念是,你为你关心的指标(如转化或销售)测量的结果不会告诉你实验的全部情况。

酒店预订网站示例

作为一个例子,我们可以使用网站上的消息打开量,比如booking.com(酒店预订)。用户在预订酒店后可能会收到一条消息并打开它。当他们继续与酒店经营者互动时,他们也可能会打开多个信息。任何一天的消息数量并不完全取决于预订的数量,因为用户可能会继续发送几周前预订的消息。

如果我们考虑结账流程实验的指标,如果我们不小心引入了一个破坏结账流程的错误,我们将开始看到消息打开的小幅下降,因为新用户不能预订任何东西和接收消息,但所有老用户仍然可以发送消息,因此指标不会有太大变化。

这显然是有问题的,因为在现实中我们已经做了一个可怕的改变,我们应该立即停止测试,但我们的数据需要很长时间才能反映出来,因为我们没有得到正确的暴露点。

当它不适用时

这一切听起来很棒,并且是一个很好的理由来确保你的曝光点尽可能接近你正在做出的实际改变,但实际上,有几个条件必须保持真实的曝光稀释实际发生,在许多情况下他们不会。

  1. 与新用户相比,旧用户(现有/回归用户)的数量必须很大。如果他们不是,那么实际上没有多少用户来冲淡这种效果。以我们的例子为例,如果用户预订了酒店,然后查看了当天的信息,但再也没有回到网站,那么我们实际上不会看到任何暴露稀释,不管我们的暴露点。在下面的图 1 中,3 + 4 比 1 + 2 少得多。
  2. 指标不能完全依赖于所做的改变。如果我们关心的指标是预订数量,而不是消息打开,那么用户将无法在没有实际看到变化的情况下影响指标。在许多实验中,情况会是这样,因为您倾向于想要改变将影响许多用户的事情,以对度量产生最大的影响,但是对于具有从单个团队向上的目标的大型团队,这可能更常见。在图 1 中,这意味着 3 + 4 =0

因此,如果这些条件无效,那么实际上可以简单地将所有用户暴露给变更。根据你如何进行实验,以及所做的改变的类型,这有时会更容易,也更容易设置。

图 1 :把 square 看成是实验的一部分,可以影响你关心的指标的所有用户。然后,我们可以定义两个轴,首先是用户是否真正看到了变化,其次是他们是否在测试或控制中。当我们的用户看不到测试和控制中的变化时,即当我们的 3 和 4 远大于 0 时,就会发生暴露稀释。(作家创造的形象)

结论

最后,值得一提的是,即使存在暴露稀释,你从实验中得到的结果仍然是有效的,事实上,是有用的。在消息打开的情况下,我们可能想直接知道实验的效果(看到变化的用户的消息打开增加了多少%),但是我们也想知道对所有用户的影响,想知道我们对顶线目标有多少贡献。这正是暴露稀释的结果告诉我们的,尽管我们需要更大的样本量才能得到结果。在我们将暴露点设置在变更附近的情况下,我们需要手动计算整体影响。

总的来说,如果(a)你没有很多回头客,并且(b)你的指标完全依赖于你引入的变化,你就不需要担心暴露稀释。当然,调整曝光稀释永远不会有坏处,所以如果你有资源,那么将曝光点设置为尽可能接近变化是安全的。

浓缩咖啡的萃取冷却

原文:https://towardsdatascience.com/extract-cooling-for-espresso-a628d6755da6

咖啡数据科学

运用现代技术破解风味

浓缩咖啡通常是热煮的,但缺点之一是香气会不断蒸发。一般来说,有一种观念认为人们应该在煮好咖啡后立即饮用。问题是浓缩咖啡是热的,我的经验是让一杯冷却到 50C 以下会大大改善味道。不利的一面是,如果一杯放得太久,氧化会破坏味道。如果我们把冲好的酒迅速冷却会怎么样?我们可以通过休·凯利所说的抽气冷却来两全其美

历史

我的灵感来自 Nucleus tools 今年(2022 年)推出的 Paragon 滴头。然而,对于意式浓缩咖啡,这个想法在前一年的比赛中被使用。2021 年,在世界咖啡师锦标赛(WBC)上,休·凯利用一些冷却石冷却一杯浓缩咖啡的前半部分,制成了浓缩咖啡。

然而,2021 并不是 WBC 第一次使用这样的技术。来自台湾的 Berg Wu 在 2016 年 WBC 比赛中使用了 cold portafilters(喷动,不是无底),意图是冷却镜头的第一部分,他赢了。

但是等等!这不是第一次有人试图快速冷却咖啡。故事的起源至少可以追溯到 2011 年咖啡杂志上市的时候。他们的目标是将咖啡冷却到可饮用的温度,然后使用沸点接近 70℃的封装材料保持该温度。这意味着物质会从固体变成液体,吸收大量的热量。然后它会重新固化,保持温度更长时间。这家公司似乎不再营业了。

另一家名为的公司 Joeveo 于 2013 年开始在咖啡杯中使用类似技术,目标是 60 摄氏度。这个杯子对于浓缩咖啡来说很大。

这两种技术都没有专注于香气消失的想法,这是马赛丽和他的公司学到的,但这个想法的种子之前因为其他原因而形成。

我不酿造 pourover,但我想我可以做一个黑客来测试这项技术。我对此很感兴趣,因为学术结果还没有出来。

所有图片由作者提供

所以我用了一块玄武岩做的按摩石,我把它放在冰箱里。

前几次测试非常成功,我不想做通常的配对拍摄。但是,我是为了科学。

设备/技术

意式咖啡机 : 像样的意式咖啡机

咖啡研磨机 : 小生零

咖啡:家庭烘焙咖啡,中杯(第一口+ 1 分钟)

镜头准备:断奏夯实

预灌注:长,约 25 秒

输液:压力脉动

过滤篮 : 20g VST

其他设备: Atago TDS 计Acaia Pyxis 秤

绩效指标

我使用了两组指标来评估技术之间的差异:最终得分和咖啡萃取。

最终得分 是记分卡 7 个指标(辛辣、浓郁、糖浆、甜味、酸味、苦味和回味)的平均值。当然,这些分数是主观的,但它们符合我的口味,帮助我提高了我的拍摄水平。分数有一些变化。我的目标是保持每个指标的一致性,但有时粒度很难确定。

总溶解固体(TDS)使用折射仪测量,该数字结合一杯咖啡的输出重量和输入重量用于确定提取到杯中的咖啡的百分比,称为提取率(EY)** 。**

强度半径定义为 TDS vs EY 的控制图上原点的半径,所以 IR = sqrt( TDS + EY)。这一指标有助于标准化产量或酿造比的击球性能。

数据

我品尝了 20 多对样本中的 8 种咖啡。我发现凉了的饮料味道更好。他们读取的 TDS/EY 略高,但这可能是由于样品温度较低

平均味觉评分全面上升。一个 1 点的增加可能是一个更嘈杂的指标,特别是对于一个小数据集,但大多数有 2 点的平均差异。

总的来说,除了 EY 和红外,冷却样品的影响在统计上是显著的。

虽然冷却实验与其说是寻找新东西,不如说是好奇,但我发现我的浓缩咖啡日常工作的一部分已经永远改变了。我继续使用冷却石,因为我发现提取冷却是任何人都可以应用的主要方法改进。也不用花那么多钱,效果立竿见影。

对我来说,更大的问题是了解酿造和冷却过程中发生了什么,导致这种影响如此明显。

如果你愿意,可以在推特YouTubeInstagram 上关注我,我会在那里发布不同机器上的浓缩咖啡照片和浓缩咖啡相关的视频。你也可以在 LinkedIn 上找到我。也可以在关注我,在订阅

我的进一步阅读:

我的书

我的链接

浓缩咖啡系列文章

工作和学校故事集

从文本中提取知识:使用 spaCy 和 Neo4j 的端到端信息提取管道

原文:https://towardsdatascience.com/extract-knowledge-from-text-end-to-end-information-extraction-pipeline-with-spacy-and-neo4j-502b2b1e0754

了解如何使用 spaCy 实现定制的信息提取管道,并将结果存储在 Neo4j 中

自从我第一次涉足自然语言处理以来,我一直对信息提取(IE)管道有着特殊的兴趣。信息提取(IE)管道从文本等非结构化数据中提取结构化数据。互联网以各种文章和其他内容格式的形式提供了丰富的信息。然而,虽然你可能会阅读新闻或订阅多个播客,但几乎不可能跟踪每天发布的所有新信息。即使您可以手动阅读所有最新的报告和文章,组织数据以便您可以使用您喜欢的工具轻松地查询和聚合数据也将是令人难以置信的乏味和劳动密集型工作。我绝对不想把这当成我的工作。幸运的是,我们可以采用最新的自然语言处理技术来自动提取信息。

信息抽取管道的目标是从非结构化文本中抽取结构化信息。图片由作者提供。

虽然我已经实现了 IE 管道,但我注意到开源 NLP 模型中有许多新的进步,尤其是围绕空间。我后来了解到,我将在本文中使用的大多数模型都被简单地包装成一个 spaCy 组件,如果您愿意,也可以使用其他库。然而,由于 spaCy 是我玩过的第一个 NLP 库,我决定在 spaCy 中实现 IE 管道,以此来感谢开发人员制作了如此棒且易于上手的工具。

随着时间的推移,我对 IE 管道的步骤的看法保持不变。

信息提取流程中的步骤。图片由作者提供。

IE 管道的输入是文本。这些文本可能来自文章,也可能来自内部业务文档。如果你处理 pdf 或图像,你可以使用计算机视觉来提取文本。此外,我们可以使用 voice2text 模型将录音转换成文本。准备好输入文本后,我们首先通过共指消解模型运行它。共指消解将代词转换成所指的实体。通常,指代消解的例子是人称代词,例如,模型用被指代人的名字替换代词。

下一步是识别文本中的实体。我们想要识别哪些实体完全取决于我们正在处理的用例,并且可能因域而异。例如,您经常会看到经过训练的 NLP 模型可以识别人、组织和位置。然而,在生物医学领域,我们可能想要识别基因、疾病等概念。我还见过一些例子,在这些例子中,企业的内部文档被处理,以构建一个知识库,该知识库可以指向包含用户可能有的答案的文档,甚至可以为聊天机器人提供燃料。识别文本中实体的过程被称为命名实体识别

识别文本中的相关实体是一个步骤,但是您几乎总是需要标准化实体。例如,假设文本引用了相对论相对论。显然,这两个实体指的是同一个概念。然而,尽管这对您来说很简单,但我们希望尽可能避免手工劳动。并且机器不会自动将两个参考识别为相同的概念。这里是名为 实体消歧实体链接发挥作用的地方。命名实体消歧和实体链接的目标都是为文本中的所有实体分配唯一的 id。通过实体链接,从文本中提取的实体被映射到目标知识库中相应的唯一 id。在实践中,你会看到维基百科被大量用作目标知识库。然而,如果您在更具体的领域工作,或者想要处理内部业务文档,那么 Wikipedia 可能不是最佳的目标知识库。请记住,实体必须存在于目标知识库中,以便实体链接过程能够将实体从文本映射到目标知识库。如果文中提到了你和你的经理,而你们两个都不在维基百科上,那么在实体链接过程中使用维基百科作为目标知识库是没有意义的。

最后,IE 管道然后使用关系提取模型来识别文本中提到的文本之间的任何关系。如果我们坚持以经理为例,假设我们有以下文本。

艾丽西娅是扎克的经理。

理想情况下,我们希望关系提取模型能够识别两个实体之间的关系。

提取实体之间的关系。图片由作者提供。

大多数关系抽取模型被训练以识别多种类型的关系,从而使得信息抽取尽可能丰富。

既然我们很快地复习了理论,我们可以直接看实际例子了。

在空间开发 IE 管道

在过去的几周里,spaCy 有了很大的发展,所以我决定尝试新的插件,并用它们来构建一个信息提取管道。

和往常一样,所有代码都可以在 Github 上获得。

共指消解

首先,我们将使用新的跨语言共指模型,由大卫·贝伦斯坦贡献给 s paCy Universe 。SpaCy Universe 是 SpaCy 的开源插件或附加组件的集合。spaCy universe 项目最酷的一点是,将模型添加到我们的管道中非常简单。

就是这样。在 spaCy 中建立共指模型只需要几行代码。我们现在可以测试共指管道了。

正如你所注意到的,人称代词 He 被所指的人 Christian Drosten 所取代。看似简单,但这是开发准确信息提取渠道的重要一步。对 David Berenstein 的大声喊出来,感谢他持续开发这个项目,让我们的生活变得更简单。

关系抽取

您可能想知道为什么我们跳过了命名实体识别和链接步骤。原因是我们将使用 Rebel 项目,该项目识别文本中的实体和关系。如果我理解正确的话,Rebel 项目是由 Pere-Lluís Huguet Cabot 开发的,作为他与 Babelscape 和 Sapienza 大学博士研究的一部分。再次,对 Pere 大呼小叫,因为他创建了这样一个不可思议的库,为关系提取提供了最先进的结果。反叛者型号有 HugginfacespaCy 组件两种形式。

然而,该模型不做任何实体链接,所以我们将实现我们的实体链接版本。我们将简单地通过调用搜索实体 WikiData API 来搜索 WikiData 上的实体。

正如您从代码中注意到的,我们只是从第一个结果中获取实体 id。我一直在寻找如何改善这一点,偶然发现了 ExtEnd 项目。ExtEnd project 是一种新颖的实体消歧方法,可以在 Huggingface 和 s paCy 组件上作为演示使用。我对它进行了一点试验,并设法使用候选人维基数据 API 而不是最初的 AIDA 候选人来使它工作。然而,当我想让所有三个项目(Coref、Rebel、ExtEnd)在同一个管道中时,由于它们使用不同版本的 PyTorch,所以存在一些依赖性问题,所以我现在放弃了。我想我可以将管道对接以解决依赖性问题,但我想在一个空间管道中同时拥有扩展和反叛。然而,我开发的扩展代码在 GitHub 上是可用的,如果有人想帮我让它工作,我非常乐意接受拉请求。

好了,现在,我们不会使用 ExtEnd 项目,而是使用一个简化版本的实体链接,只需从 WikiData API 中取出第一个候选项。我们唯一需要做的就是将我们简化的实体链接解决方案整合到 Rebel 管道中。由于 Rebel 组件不能作为 spaCy Universe 项目直接使用,我们必须手动从他们的库中复制组件定义。我冒昧地在 Rebel spaCy 组件中实现了我版本的 set_annotations 函数,而其余代码与原始代码相同。

set_annotations 函数处理我们如何将结果存储回空间的 Doc 对象。首先,我们忽略所有的自循环。自循环是在同一实体开始和结束的关系。接下来,我们使用 regex 在文本中搜索关系的头部和尾部实体。我注意到反叛者模型有时会产生一些不在原文中的实体。因此,我添加了一个步骤,在将两个实体附加到结果之前,验证它们是否确实在文本中。

最后,我们使用 WikiData API 将提取的实体映射到 WikiData ids。如前所述,这是实体消歧和链接的简化版本,例如,您可以采用更新颖的方法,如扩展模型。

既然 Rebel 空间组件已经定义,我们可以创建一个新的空间管道来处理关系提取部分。

最后,我们可以在之前用于共指消解的样本文本上测试关系提取管道。

反叛模式从文本中提取了两种关系。例如,它识别出 WikiData id 为 Q1079331 的 Christian Drosten 受雇于 id 为 Q95 的 Google。

存储信息提取管道结果

每当我听到实体之间的关系信息时,我会想到一个图表。开发图形数据库是为了存储实体之间的关系,所以什么更适合存储信息提取管道结果。

你可能知道,我偏向于 Neo4j ,但是你可以用任何你喜欢的工具。在这里,我将演示如何将信息提取管道的实现结果存储到 Neo4j 中。我们将处理几个著名女科学家的维基百科摘要,并将结果存储为图表。

如果你想了解代码示例,我建议你在 Neo4j 沙盒环境中创建一个空白项目。创建 Neo4j 沙盒实例后,可以将凭证复制到代码中。

Neo4j 沙盒连接详情。图片由作者提供。

接下来,我们需要定义一个函数,该函数将检索著名女科学家的维基百科摘要,通过信息提取管道运行文本,并最终将结果存储到 Neo4j。

我们使用了维基百科 python 库来帮助我们从维基百科中获取摘要。接下来,我们需要定义用于导入信息提取结果的 Cypher 语句。我不会深入 Cypher 语法的细节,但是基本上,我们首先通过它们的 WikiData id 合并头部和尾部实体,然后使用来自 APOC 库的过程来合并关系。如果你正在寻找学习更多 Cypher 语法的资源,我推荐你去参加 Neo4j Graph Academy 的课程。

现在我们已经准备好了一切,我们可以继续解析几个维基百科的摘要。

处理完成后,您可以打开 Neo4j 浏览器来检查结果。

工业工程管道的结果。图片由作者提供。

结果看起来出奇的好。在这个例子中,Rebel 模型识别了实体之间的 20 多种关系类型,从奖励和雇主到用于治疗的药物。只是为了好玩,我会给你看模型提取的生物医学关系。

提取的生物医学关系。图片由作者提供。

似乎有些女士在生物医学领域工作。有趣的是,该模型确定阿昔洛韦用于治疗疱疹感染,硫唑嘌呤是一种免疫抑制药物。

丰富图表

因为我们已经将实体映射到了 WikiData ids,所以我们可以进一步使用 WikiData API 来丰富我们的图表。我将向您展示如何从 WikiData 中提取关系的INSTANCE _ 并在 APOC 库的帮助下将它们存储到 Neo4j,该库允许我们调用 web APIs 并将结果存储在数据库中。

为了能够调用 WikiData API,您需要对 SPARQL 语法有一个基本的了解,但这超出了本文的范围。然而,我写了一篇帖子,展示了更多用于丰富 Neo4j 图的 SPARQL 查询,并深入研究了 SPARQL 语法

通过执行下面的查询,我们将节点添加到图中,并将它们与适当的实体链接起来。

现在,我们可以在 Neo4j 浏览器中检查丰富的结果。

通过 WikiData API 中的类丰富的实体。图片由作者提供。

结论

我真的很喜欢 s paCy 最近在做的事情以及围绕它的所有开源项目。我注意到各种开源项目主要是独立的,将多个模型组合成一个单一的 spaCy 管道可能很棘手。例如,您可以看到在这个项目中我们必须有两条管道,一条用于共指解析,一条用于关系提取和实体链接。

至于 IE 管道的结果,我对它的结果很满意。正如你可以在 Rebel repository 中观察到的,他们的解决方案在许多 NLP 数据集上都是最先进的,所以结果如此之好并不奇怪。我的实现中唯一的薄弱环节是实体链接步骤。正如我所说的,添加类似于 ExtEnd 库的东西来实现更精确的实体消歧和链接可能会大有裨益。也许这是我下次要做的事情。

尝试 IE 的实现,请让我知道你的想法,或者如果你有一些改进的想法。有很多机会可以让这条管道变得更好!

和往常一样,代码可以在 GitHub 上获得。

使用 Python 从图像中提取文本

原文:https://towardsdatascience.com/extract-text-from-image-using-python-8e8cfbbce743

在本教程中,我们将探索如何使用 Python 从图像中提取文本

伊恩·施耐德在 Unsplash 上拍摄的照片

目录

  • 介绍
  • 样本图像
  • 使用 Python 从单个图像中提取文本
  • 使用 Python 从多个图像中提取文本
  • 结论

介绍

从图像中提取文本是企业运营部门(从发票和收据中提取信息)以及其他领域中非常流行的任务。

OCR(光学字符识别)是一种基于电子计算机的方法,将文本图像转换为机器编码的文本,然后可以提取并以文本格式使用。

要继续学习本教程,我们需要:

Tesseract 是一个开源 OCR(光学字符识别)引擎,允许从图像中提取文本。

为了在 Python 中使用它,我们还需要pyTesseract库,它是 tesserac 引擎的包装器。

由于我们正在处理图像,我们还需要为 Python 添加图像处理功能的 pillow 库。

首先,为你的操作系统搜索宇宙魔方安装程序。对于 Windows,你可以在这里找到最新版本的宇宙魔方安装程序。只需下载。exe 文件并安装在您的计算机上。

如果您没有安装 Python 库,请打开“命令提示符”(在 Windows 上)并使用以下代码安装它们:

pip install pytesseract
pip install pillow

样本图像

为了继续学习本教程,我们需要一些图片。

以下是我们将在本教程中使用的三幅图像:

作者图片

作者图片

作者图片

在本教程中,我们将使用简单的图像与文本水平对齐,不需要任何额外的图像处理。

使用 Python 从单个图像中提取文本

让我们从使用 Python 从单个图像中提取文本开始。

对于这个例子,我们将使用上一节提供的第一幅图像:sampletext1-ocr.png

下面是我的文件的结构:

作者图片

所有的图像都放在文件夹图像中,代码保存在主文件夹

我们需要的图片的路径是:images/sample text 1-ocr . png

我们需要的另一个路径是安装后创建的tessaract.exe的路径。在 Windows 上,它应该位于:C:\ Program Files \ tessera CT-OCR \ tessera CT . exe

现在,我们已经拥有了所需的一切,可以使用 Python 轻松地从图像中提取文本:

您应该得到:

Sample Text 1

使用 Python 从多个图像中提取文本

在这一节中,我们将探索如何使用 Python 从多个图像中提取文本。

我们知道所有的图像都放在文件夹 images 中,而代码驻留在 main.py

从每个图像中提取文本的一种方法是使用每个图像的文件名,并从这些图像中逐个提取文本。

但是如果文件夹里有 100 张图片呢?使用 os 库,我们可以访问给定目录中的所有文件名。

一旦我们访问了 images 文件夹中的所有文件名,我们将遍历它们并使用 Python 从每个图像中提取文本:

您应该得到:

Sample Text 1
Sample Text 2
Sample Text 3

这正是我们在图像中看到的文字。

结论

在本文中,我们探讨了如何使用 Python 和 Tesseract 从单幅图像和多幅图像中提取文本。

如果你有任何问题或对编辑有任何建议,请随时在下面留下评论,并查看更多我的 Python 编程教程。

原载于 2022 年 5 月 12 日https://pyshark.com

用 Python 从图像中提取用不同语言编写的文本

原文:https://towardsdatascience.com/extract-text-written-in-different-languages-from-images-with-python-2348ff021fe5

EasyOCR,将多语言图像转换为文本的库

埃里克·克鲁尔在 Unsplash 上拍摄的照片

介绍

在这个日益现代化的世界里,简单的截屏足以分享图像格式的文本信息。此外,全球化使得这些信息可以用不同的语言提供。能够有效地从这些图像中提取它们可能是一项至关重要的技能。因此,拥有这种技能的行业和组织可能会在竞争中遥遥领先。

几天前,我偶然发现了一个 python 库,可以用来执行这样的任务。本文通过不同语言中的一些图片示例来介绍什么是easiocr

easy ocr——是什么?

easiocr是一个开源的 python 库,用于光学字符识别,简称 OCR。它目前支持提取 80 多种语言编写的文本。

先决条件

为了能够使用easiocr,我们需要安装以下两个依赖项:Pytorch 和 OpenCV。

OpenCV 的 安装很简单,只需以下指令。

open_cv_install.py

Pytorch 的 安装过程取决于您的操作系统,所有的说明都可以在这个页面上找到。单击按钮时,会生成如下安装脚本:

Pytorch 安装过程来自官网(图片由作者提供)

下面是之前自动生成的相同代码。

pytorch_install.py

我们终于可以用这个命令行安装easiocr了。

easy_ocr_install.py

开始

由于easiocr是一个多语言库,我们需要加载模型,同时指定我们将使用哪种语言。这是通过使用来自easiocrReader 类来完成的,该类可以接受语言列表的参数。每种语言都用一个代号来表示;比如法语的 fr ,英语的 en ,捷克语的 cs 等等。整个列表可在这里获得。

easy_ocr_reader.py

值得注意的是,有些语言是不兼容的,因此在实例化一个阅读器(加载模型)时不能在同一个列表中。

在我们的例子中,我们将通过三种语言,英语、法语和汉语来说明easiocr的用法。但是我们将只需要如下所示的两个模型。

加载语言模型

加载模型可能需要更长的时间,但这是一个一次性的过程。我们不必每次都重新加载相同的模型。

  • 读者(['en ',' fr']) :这第一个模型是针对英语和法语的,因为英语兼容每一种语言。

en_fr_reader.py

  • Reader(['ch_sim']) :仅针对中文的第二款,因为不兼容法语。

ch_reader.py

文本提取—参数配置

使用以下指令 {model} 完成文本提取。read_text功能其中 {model} 是我们之前的一款车型。默认输出是一个元组列表,每个元组都是这样的格式:(【包围盒坐标】检测到的文本检测到的置信度),elow 是一个示例。

检测到的文本在蓝色框中。左边是坐标,右边是置信度。

来自 easyocr Github 的免授权示例(图片由作者改编)

获得这些细节是好的,但是我们只对蓝框中的文本信息感兴趣。为此,我们可以简单地将细节参数设置为零(0),如下图read_text(my_image, detail = 0) 还有一个必需的参数是段。

  • 如果设置为 True,提取将逐块进行,将所有内容放在同一行中。
  • 如果设置为 False,提取将按列进行。

由你来设置段落的正确值,但是设置为 True 适用于绝大多数情况。

将所有这些信息放在一起就创建了下面的 helper 函数。它返回所有文本,每一个文本占一行,而不是返回一个文本列表。

easy_ocr_read_text.py

文本提取——最后一步

现在我们可以骑在巨人的肩膀上从下面的每一张图片中提取文字,所有的 免执照

  • 图像为法语

来自法国政府的免执照图片

easyocr_fr_image.py

法语执行的输出(图片由作者提供)

我们可以看到,库成功地提取了内容,甚至是第二行第二列中的“2m”。

  • 形象为英文

来自 easyocr Github 的免授权图片

easyocr_en_image.py

执行的输出为英文(图片由作者提供)

类似于之前的案例,一切似乎又很棒了!

  • 图像为中文

来自 PaddleOCR 的免执照图片

easyocr_ch_image.py

执行脚本的输出为只有中文(图片由作者提供)

我不是中文专家,但是看起来图书馆又做了一件伟大的工作。然而,看起来一些非中文信息被错误地提取出来了(在橙色框中)。例如 OEM ODE 转化为 00 002202201 等。这个是因为模型只针对中国人。解决此类问题的一个解决方案是创建一个既能理解英语又能理解中文的模型,如下所示。

easyocr_ch_en_image.py

ch_en_reader.py

英汉模式执行的输出(图片由作者提供)

最后的结果看起来比上一个好!

结论

恭喜你!🎉 🍾您刚刚学会了如何使用easiocr从不同语言的图像中提取文本!如果你还是不愿意用easiocr来使用它,那么是时候试一试了,因为最终对那些你回避了很久的图像说 YES 可能会有很大的帮助!

尽管这个库效率很高,但是文本提取过程很慢,这可能不适合具有高实时性约束的应用。

如果你喜欢阅读我的故事,并希望支持我的写作,考虑成为一个媒体成员。每月支付 5 美元,你就可以无限制地阅读媒体上的故事。通过使用我的注册链接,我将获得一小笔佣金。

另外,你可以在 LinkedInMediumYouTube 上加我,或者在 Twitter 上关注我。讨论人工智能,人工智能,数据科学,自然语言处理的东西总是令人愉快的!

Google Colab 上文章的源代码

Pytorch 官方文档页面

信息冠状病毒

铁路安全信号

划桨 OCR 中文图像

再见🏃🏾

使用 Python 从照片中提取 GPS 数据

原文:https://towardsdatascience.com/extracting-gps-data-from-photos-using-python-e8be352acf15

提取元数据的非常简单和直接的指南

罗伯特·佩纳洛萨在 Unsplash 上拍摄的照片

如今智能手机拍摄的大多数照片都包含大量元数据,包括 GPS 数据。GPS 数据是指照片拍摄地的经纬度坐标。

当我们得到照片的 GPS 坐标时,我们甚至可以将它输入到谷歌地图中,并看到确切的位置。只需在谷歌地图的搜索栏中输入【经度】,【纬度】,我们就能立刻看到位置。

如果我们只是想查看单张照片的 GPS 坐标,那是非常容易的。坐标以及许多其他元数据都可以在图像本身的属性中找到。

Windows 中的图像属性|按作者分类的图像

然而,如果我们有数百张照片,并且我们需要提取 GPS 坐标,该怎么办?

Python 解决方案

我们将使用 GPSPhoto 库,它可以很容易地通过 pip 安装。

下面的代码将生成我们想要提取 GPS 坐标的照片列表。它将获取指定文件夹中所有以 jpg 结尾的照片。

pip install GPSPhoto
import os

os.chdir('C:\\Users\\my_personal_profile\\image_folder')
image_list = os.listdir()
image_list = [a for a in image_list if a.endswith('jpg')]

print(image_list)

您可能还需要安装库的依赖项,例如 exifreadpiexif,也可以通过 pip 安装。

如果我们打印 image_list,我们将得到所有的列表。image_folder 文件夹中的 jpg 图像。

要分析的照片列表|作者提供的图片

一旦我们验证了图像文件名的列表,我们就可以提取 GPS 坐标。

from GPSPhoto import gpsphoto

for a in image_list: 
  data = gpsphoto.getGPSData(os.getcwd() + f'\\{a}')
  print(data)

输出:GPS 坐标和其他元数据|作者图片

激动人心的使用案例

在寻找拍摄地点时,我最近在手机上浏览旧照片,发现了这张美丽的照片。

双溪布洛湿地保护区的一个豆荚里

我很想再去那里拍一张合适的照片。我知道这是双溪布洛湿地保护区的一只豆荚。然而,公园里有几个类似的豆荚,尽管型号略有不同,阳光效果也不同。为了识别它们,我在谷歌上搜索豆荚的名称,例如弹涂鱼豆荚、翠鸟豆荚、鹰角豆荚等,看看是否匹配。然而,我不能确定,因为在谷歌上找到的图片有时会被用户错误标记。

不用去谷歌街景,一个一个地探索这些地方(在公园里很多时候有谷歌街景没有覆盖的区域),这个解决方案非常有效。我刚刚从我在双溪布洛湿地保护区拍摄的许多照片中提取了 GPS 坐标,我能够得到准确的位置。这帮助我制定了一个好的摄影计划。

精确定位豆荚的确切位置:翠鸟豆荚——图片由作者提供

警告

如果你担心你拍摄并上传到社交媒体或通过信息应用分享的照片会泄露你的位置,不要担心!并非所有照片都包含此类信息。我也检查了在谷歌搜索上找到的照片,脸书上朋友上传的照片,甚至我直接在 WhatsApp 上分享的照片。它们不包含这样的信息。如果您共享照片的原始文件,那么照片很可能包含 GPS 坐标。

结论

希望这篇文章能帮助你从照片中自动提取 GPS 坐标。如果您想从照片中提取其他元数据,可以使用其他库。但是,如果您只想提取 GPS 数据,这是目前最简单的方法。

查看我的其他文章:

</7-data-visualization-best-practices-everyone-must-know-b68ebe329b1e> https://medium.com/illumination/demings-14-management-principles-every-managers-should-know-60d37ce02ad9

从历史家谱文献中提取信息

原文:https://towardsdatascience.com/extracting-information-from-historical-genealogical-documents-ab3068b10715

HTR(手写文本识别)和相关技术如何推动家庭发现

概观

这篇文章解释了机器学习(ML)技术,如 HTR(手写文本识别)和 NLP(自然语言处理)如何改善人们通过历史文献了解其家族根源的前景。它也概述了一些困难的(然而值得的)问题,这些问题仍然需要 ML 研究者去解决。

介绍

我们的世界充斥着数字内容。很有可能在某一年创作的新文本比数字时代之前的一千年里创作的还要多。例如,仅在 Twitter 上,估计每年就有 2000 亿条推文( Twitter 使用统计,2021)。假设平均推文长度为 28 个字符,那么在一个社交媒体平台上,一年就有超过 5.5 万亿个字符的新文本。相比之下,到 1975 年(现代数字时代之前),美国国会图书馆的藏书约为 1700 万册[1]。估计每本书平均有 450,000 个字符,相当于大约 7.5 万亿个字符。换句话说,在一年内,一个社交媒体平台现在产生的文本几乎相当于美国国会前数字图书馆的所有书籍!

今天网上惊人的内容数量可能会让不熟悉数字化世界宗谱记录的人认为大多数历史(非数字)内容已经被数字化并可供使用。或者,最重要的内容已经被数字化了。这根本不是真的。

将物理历史文档转换为在线可搜索文本的过程非常耗时、复杂、昂贵,并且难以复制。技术并不是唯一的问题。通常,更大的挑战是与档案的关系、所需的合同、当地法律的导航以及对源文件的物理访问。每一个重大的数字化项目都涉及大量的“定制工作”这一事实经常导致大型在线信息经纪人到别处寻找他们的内容。然而,我们低估了仍然锁在我们无法访问的旧的、未数字化的文档中的文本的价值。在许多情况下,与目前网上可获得的任何内容相比,未数字化的内容可能信息量更大、更有趣、更有用。

重要的是要记住,在个人电脑和互联网出现之前,书面交流更加困难和昂贵。因此,人们通常把写作精力集中在他们认为重要的事情上。此外,16 世纪大规模印刷的出现并没有改变大多数书面内容仍然不能以任何方式复制的事实。因此,幸存的实体文件通常包含在我们庞大的数字世界中找不到的关键信息。这些文件的发现和数字化继续改变着我们的全球历史叙事。此外,可能有文件会改变你的个人历史叙述!

举例来说,考虑一个美国的 FamilySearch 用户(碰巧是作者)的经历,他想知道他的曾祖母(Susanna Neises)在德国的什么地方出生,她的父母是谁。下面的历史婚姻记录(图 1)不仅回答了这些问题,而且也是识别和联系仍然生活在德国的亲属的起点。

图 1:婚姻记录(拉丁文),标明了苏珊娜·内塞斯的父母和出生地。图片版权https://www.familysearch.org。经许可使用。

图 2:2015 年,作者的母亲(左)与她在德国的 Neises 表妹团聚。图片作者。

进入族谱学科,是对家族历史的研究,是对一个人世系(家谱)的追溯。系谱学家和家庭历史学家依赖历史文献,如人口普查、教会和民间记录、日记、遗嘱等。研究远古的血统和祖先故事。不幸的是,到目前为止,只有一小部分历史家谱文件可以通过名字和其他领域在网上进行搜索,这使你能够找到你正在寻找的人或事。原因很简单,就是成本与收益的对比。数字扫描和手动转录仍然很昂贵,所以档案馆和家谱企业将资源集中在吸引最大数量付费客户的收藏上——这通常意味着英语记录。如果你的祖先出现在那些重要的收藏品中,这对来说很好。然而,通常你需要的信息在另一个历史文件中的某个地方,或者一种不同的语言,它还没有被转录和提供搜索。那份文件对大多数人来说可能没什么价值,但它对你来说肯定很重要,有助于解开你家族历史的额外线索。

OCR(光学字符识别)、HTR(手写文本识别)和相关的信息提取技术有望改变这一成本等式,并使几乎任何历史文档都可以在线搜索。事实上, FamilySearch 和我们行业中的其他公司已经开始利用这些技术取得良好的效果。另一方面,正如我们将看到的,历史文献可能包含最难解决的问题。在本文中,我们将概述其中的一些挑战,以及我们如何应对这些挑战。

背景:关于我们

family search International是一家非营利组织,通过其网站、移动应用程序和 5000 多个当地家族历史中心的面对面帮助,帮助人们发现他们家族的历史。由耶稣基督后期圣徒教会经营的 FamilySearch 向所有人免费提供这些服务,不论其传统、文化或宗教信仰如何。FamilySearch 资源帮助世界各地数百万人发现他们的遗产并与家人联系。

FamilySearch 起源于犹他宗谱协会,该协会由教会于 1894 年成立,旨在帮助从世界各地移民到落基山脉的一批批拓荒者为他们新家园的后代记录他们家族的历史。1938 年,该协会开始对世界范围内的教会和政府档案中发现的历史文件进行微缩摄影。

计算机辅助标引(CAI)的诞生

在 21 世纪初,在犹他宗谱学会成为家庭研究之后,我们开始将这些缩微胶片(准确地说超过 240 万卷)转换成数字格式,以便为更多的人提供更多的在线访问。我们还与其他宗谱组织合作,以扩大我们的集体控股。迄今为止,FamilySearch 在我们的网站上免费提供了超过 120 亿张历史记录图片。由于志愿者和朋友组织的努力,许多这些图像也有关键信息的文本搜索转录(我们称之为“索引”)。然而,人类转录/索引项目很难跟上图像采集的步伐。通常,为单个文档编制索引可能需要几个小时。对于我们的在线志愿者来说,旧的和非英语的收藏尤其具有挑战性。如果不从根本上改变我们的索引方法,大多数图像将在未来几年内保持未索引状态,因此对大多数人来说是不可发现的。

为此,大约在 2011 年,FamilySearch 开始在技术、研究、数据和人才方面进行大量投资,以自动转录和索引我们所有的历史文档图像。我们也在商业和学术研究团体中寻找合作兴趣来共同解决这个问题。从那时起,我们组建了一个由科学家和工程师组成的能干的内部团队,致力于我们现在所说的历史记录的“计算机辅助索引”(CAI)。

我们最早的 CAI 工作包括对 2600 万份美国报纸中的现代讣告进行自然语言处理(NLP)。在此之前,志愿者必须仔细阅读每份讣告,以提取关键的家谱信息,如姓名、家庭关系和事件日期。2015 年,我们能够使用我们内部构建的 NLP 系统自动索引和发布超过 1.7 亿条讣告。最初,我们将这些技术应用于“原生数字”讣告文本,不需要之前的 OCR。之后,我们开始开发机器学习技术来寻找、分割和转录印刷在纸上的讣告图像。

图 3:完全由我们的 CAI 系统(与 GenealogyBank 合作)索引的印刷讣告。图片版权FamilySearch.org。经许可使用。

在这一点上,值得注意的是为什么我们选择在内部构建我们的 CAI 堆栈。在我们可以使用 OCR 技术的历史文件的情况下,我们很早就发现没有商业 OCR 软件可以足够准确地读取历史报纸印刷物以产生可用的索引。事实上,这在我们的习题集中是一个反复出现的主题。优秀的商业解决方案经常存在,但是它们被调整到为解决方案提供商的客户产生收入的现代文档。相比之下,历史文献是非营利组织、学术界、教会、档案馆和少数家谱组织的领域。与医疗账单、律师事务所等领域相比,这些细分市场代表了此类服务的一小部分潜在收入来源。也就是说,FamilySearch 和我们的朋友组织在让机器学习对历史文档进行工作所需的训练数据方面非常丰富。甚至一些大型科技公司都对我们多年来积累并逐渐注释的图像数据表示惊讶。

事实证明,我们构建(而不是购买)OCR 的决定特别有益,因为我们将重点从历史报纸转向了历史手写文档。术语“OCR”(光学字符识别)有点误导,因为它意味着对每个不同字符的分割和识别。相反,我们的引擎在行级别进行分段,并识别字符序列。我们采用了一个语言模型来进一步细化实际单词上下文中的每个字符级预测。这种方法更适用于 HTR(手写文本识别),因为在草书笔迹中,不同的字符通常非常难以分割。对我们来说,向 HTR 转移只是利用新的训练数据的问题。在充分披露,我们最初建立我们的光学字符识别系统与 HTR 铭记。

图 4:2016 年我们与 HTR 一起抄写的 19 世纪地契示例。图片版权【FamilySearch.org】T21。经许可使用。

大约在这个时候,我们还与杨百翰大学的研究人员合作,他们帮助塑造了我们的机器学习(ML)识别方法。其结果是一个最先进的 HTR 系统,用于历史段落/散文风格的手写草书文档。到 2018 年底,我们在美国历史手写遗嘱、遗嘱认证和土地记录的超过 1.1 亿张图像上运行了该系统,以受益于各种各样的手写风格和样本。据我们所知,这是(并且可能仍然是)有史以来通过 HTR 处理的最大的单个语料库。FamilySearch 尚未正式发布这些记录/索引,但我们预计很快就会发布。

从那以后,我们通过为几种新的语言/脚本构建模型和创建生产 ML 管道,继续扩展我们的 OCR/HTR、NLP 和相关能力。此外,我们现在有了一个识别器,它可以在一行中在手写和打印文本之间转换。到 2021 年底,我们将发布超过 1.5 亿条西班牙语和葡萄牙语记录,如图 5-7 所示。事实上,今天我们网站上的用户已经可以获得数百万条这样的记录。

图 5:自动索引的玻利维亚西班牙洗礼记录。图片版权FamilySearch.org。经许可使用。**

图 6:来自多米尼加共和国的西班牙洗礼记录的自动索引。图片版权FamilySearch.org。经许可使用。

图 7:巴西自动索引的民事死亡记录。图片版权FamilySearch.org。经许可使用。

2021 年,我们将通过 CAI 出版比任何其他单一记录索引来源更多的新西班牙记录。我们预计这种趋势会跨语言发展。与此同时,我们认识到,即使我们最好的 ML 模型也不太可能与经验丰富的人类索引员的整体准确性和推理能力相匹配。考虑到这一点,FamilySearch 正在设计新的在线和移动体验,允许用户随时随地“及时”纠正索引错误。我们还使用自动化技术,通过相似性对人类索引任务进行预分组,以减轻志愿者的认知负担。

持续的挑战

虽然我们已经取得了显著的成功,但随着我们朝着让每张图像都可以搜索的目标迈进,并且使用越来越多的语言,ML 研究问题变得越来越困难。事实上,像我们拥有的这样的历史文档可能包含一些最难解决的文档处理问题。在下一部分中,我们将详细介绍其中的一些挑战,以及我们将如何应对这些挑战。

语言和文字

我们的目标是让每个人都有可能进行家谱研究,不管他们的语言、国籍或背景如何。FamilySearch 目前正式拥有 227 种不同的语言。非官方的数字可能更大。我们在记录图像中发现了我们团队中没有人听说过的语言!甚至这些晦涩难懂的文件也很重要,因为它们包含了某人祖先的姓名和关键生活事件。事实上,如果我们研究我们的家谱,我们所有人都会开始遇到我们不理解的语言。

图 8:满语(一种濒临灭绝的语言)旁边的汉语。图片版权FamilySearch.org。经许可使用。**

图 9:来自印度的梵文。图片版权FamilySearch.org。经许可使用。**

图 10:一个古老的英文手稿(大约。1665).图片版权FamilySearch.org。经许可使用。**

“语言”这个术语本身就把问题过于简单化了。首先,历史文献通常包含独特的子语言。在每种主要语言中,专门的主题都有自己的词汇和概念。举例来说,您可能在学校学过西班牙语会话,但尝试用西班牙语向某人描述数据科学概念!语言和书面文字之间还有一个重要的区别。说某种语言的人可能非常流利,但仍然完全看不懂剧本。事实上,如果你没有在小学学过草书,你甚至会被这篇文章中的一些图片吓到!现代草书只是在我们的文献中发现的许多不同的脚本之一。

这些因素在当今数据饥渴的监督 ML 算法的背景下复合。为了自动阅读特定语言和脚本的文档,我们需要大量用该语言编写的经过仔细注释的脚本示例。与此同时,很难找到能够完成所需注释的人。在我们目前的收藏中,甚至有一些“灭绝”的语言和文字,只有世界上少数学者能够理解。

到目前为止,我们解决这个问题的主要方法是迁移学习结合从非常规来源获取训练数据。例如,对于我们的葡萄牙语 HTR 模型,我们最初注释的训练数据只有西班牙语的 1/10。我们还选择性地将来自更大的西班牙语训练语料库的西班牙语数据合并到我们的葡萄牙语模型中。最后,我们从已经编入索引的葡萄牙语记录中修补了更多的葡萄牙语培训示例。由此产生的葡萄牙语 HTR 模型的准确性正在迅速接近西班牙语的准确性,而家庭研究的成本要低得多。虽然西班牙语和葡萄牙语确实相似,但我们注意到,即使在更不相似的语言(通常在同一语系/文字中)之间选择性地共享训练数据,仍然可以减少所需的训练数据总量。

关于古老的文字和语言,我们有一个想法是“回溯时间”FamilySearch 拥有如此庞大的资源,以至于我们有时可以在自己的文档中观察到特定语言或文字向现代(可读)方向的演变。通过以相反的顺序(通常从最容易到最难)对这些文档排序,我们可以使用半自动的“清洗-重复”方法来训练我们的识别器,直到理解了古老的文本。

各种记录类型

大约 60%的 FamilySearch 历史文档中的内容符合少量预定义的“记录类型”类别(为系谱学家所熟悉),如出生证明、人口普查等。然而,大约 40%的历史文献很难在谱系学意义上进行分类。在生成结构化的可搜索索引时,这种分类很重要。它在“记录提示”的上下文中甚至更重要,这是历史记录索引和已经记录在家谱中的经过充分研究的人之间的自动新链接。FamilySearch 用户非常依赖这些记录提示来研究他们自己的家谱。

记录类型的基本问题是它们需要根据固定的本体或模式提取信息。反过来,在某些时候,提取过程通常涉及到不灵活的基于规则的方法(理解为:硬编码的软件规则而不是 ML)。这对于我们的主要记录类型来说没问题,但是对于难以分类的长尾文档来说就有问题了。这种文档的一个例子是法庭记录,它可以是从刑事审判程序到金融交易分类账的任何内容。当然,我们可以自动转录这些文档,并提供某种程度的搜索能力,但很难用一种通用的(但有意义的)方式来解释它们。

图 11:来自一个不太结构化的集合的货币收据。图片版权*https://www.familysearch.org。经许可使用。***

这种任意文档“理解”可能无法用当前的 ML 技术完全解决,因为它可能需要人类级的推理。我们有时开玩笑说,当我们拥有可以解决这类问题的人工智能时,人工智能可能不会想去做!也就是说,我们正在探索替代的记录搜索范例,这些范例有助于结构化程度较低的数据(包括全文搜索)。此外,即使对于非结构化/不可分类的文档,我们的技术也可以准确地检测常见的实体,如人名、组织、日期、事件等。我们还可以经常以有意义的方式将这些实体相互联系起来。换句话说,我们的系统可能并不总是确切地知道一个文档是什么意思(从系谱上来说),但它仍然可以找到有用的结构化信息,比如人和他们的亲属。

复杂布局

从历史文档中提取结构化信息通常不仅仅涉及理解(NLP)转录的散文文本。许多文档通过非文本提示,如字体大小/粗细、分割线、箭头、图表等来传达额外的语义。表格就是一个很好的例子(参见图 12 和图 13)。表格根本不是“自然语言”。然而,作为人,我们很容易理解行、列、标题等之间的关系。并且可以相应地解释数据。可以肯定的是,在简单的情况下,有一些 ML 模式可以近似我们的直观视觉理解能力。然而,根据我们的经验,这些技术在更复杂的情况下会失效。

图 12:一个简单的表格布局,它易于使用 ML 和通用规则的组合进行处理。图片版权FamilySearch.org。经许可使用。**

图 13:一个复杂的表格文档,具有更难理解的视觉语义。图片版权FamilySearch.org。经许可使用。

图 14:地契附补充图。图片版权FamilySearch.org。经许可使用。**

图 15:一个视觉语义甚至对人类读者都很难理解的文档。图片版权FamilySearch.org。经许可使用。**

图 16:特别有挑战性的布局!图片版权【FamilySearch.org】。经许可使用。****

在某些方面,复杂布局的问题集类似于前面提到的非标准记录类型。我们已经可以通过 ML 和代码规则的结合来“解决”许多这样的问题,但是不能以一种通用的方式可靠地适应以前看不到的布局。尽管如此,我们的引擎仍然出色地完成了在许多复杂布局中分割和正确转录文本的工作。同样,我们仍然可以识别实体(如名称、地点等。)而不完全理解布局。

文档损坏、噪音和图像质量差

与现代办公室中扫描的大多数业务文档不同,历史文档可能已有数百年的历史。在它们漫长的一生中,它们可能会受到霉菌、昆虫、火和各种形式的损害。大多数商业文档处理系统对这类问题没有弹性。除了文件损坏之外,我们的许多图像都是早在 20 世纪 30 年代就开始微缩拍摄的。胶卷本身可能已经变质,或者曝光本来就不好。而且,在许多情况下,简单地重新扫描原始文档(可能已不存在)并不是一个选项。

图 17:虫蛀的中国甲谱。图片版权FamilySearch.org。经许可使用。

图 18:一份严重变质的文件。图片版权FamilySearch.org。经许可使用。

图 19:从反面“出血”的文件。图片版权FamilySearch.org。经许可使用。

显然,我们无法从一份不存在的文件中提取信息。也就是说,我们的语言模型在“猜测”其他文档中频繁出现的缺失/不可读文本方面做得非常合理。此外,我们发现我们的识别模型对噪声(如渗色、污点等)具有弹性。)当用足够的例子训练时。

作为一种不同的方法,在我们的识别过程开始之前,我们已经试验了从图像中去除常见噪声的模型。这些模型的训练数据是合成的。我们通过在干净的历史文档图像上叠加伪造的伪像(如邮票、杂散标记和奇怪的纸张纹理)来模拟“嘈杂”的图像。该模型是一个自动编码器架构,它接受合成图像作为输入,并产生干净的图像作为目标。这个实验在某些场景中相当成功(见图 20)。然而,我们的一般方法是训练我们的识别器直接处理噪声。

图 20:用我们的自动编码器擦除的印记(“噪声”)。图片版权FamilySearch.org。经许可使用。

一些源文档的物理损坏可能太严重,无法仅通过成像后数字清理来恢复信息。然而,技术可能会带来希望,即使一份文件对人的眼睛来说是不可读的。我们的一位业界朋友 Ancestry.com 在历史文献的多光谱成像方面做了一些有前途的研究。在这项研究中,祖先证明了他们可以恢复隐藏在可见光谱之外的重要信息。

了解当地环境

尽管我们认为大部分历史文献是“家谱文献”,但它们很少是由家谱学家创建的。大多数是为了法律、税收或宗教目的而创建的。最初的作者没有想到他们的文件会被试图寻找他们家族根源的人阅读,通常是在数百年后的另一个国家。相反,记录员认为读者会有与该地区和最初预期目的相关的当地背景。地点的缩写就是一个很好的例子。我们在巴西圣保罗州的死亡记录中包含了晦涩的地名缩写,比如“SJC”在全球谱系背景下,这个缩写几乎是不可能解析的。它不会作为巴西城市的标准缩写出现。事实上,它很容易被误认为是加州圣何塞的机场代码。然而,居住在圣保罗的民事登记员会立即认出“SJC”是圣保罗的一个主要城市“so josédos Campos”。

幸运的是,FamilySearch 已经拥有一个庞大的标准化值数据库,可以很容易地过滤到不同级别的地理边界。每当我们遇到一个新的本地变体(比如上面的“SJC”),我们目前的方法是用新的信息手动更新我们的标准数据库。

结论

代表系谱部门,FamilySearch 要感谢整个行业的 ML 从业者,他们的研究有助于发掘我们历史文献图像的价值。人工智能的进步正在帮助成千上万的人们了解他们的家庭,最终了解他们自己。我们邀请所有感兴趣的读者在 FamilySearch.org 直接体验这一点,或者直接与我们联系。

[1]科尔,约翰·杨,为国会和国家:国会图书馆编年史 (1979),国会图书馆

使用初始咖啡水分的干咖啡和浓缩咖啡的提取率(EY)

原文:https://towardsdatascience.com/extraction-yield-ey-in-dried-pucks-and-espresso-using-initial-coffee-moisture-f65ee5c2df0e

咖啡数据科学

深入探究干冰球、折射计和 ristretto 镜头

几个月前,我买了一台像样的浓缩咖啡机 (DE 代表镜头),我很兴奋,因为我可以停止镜头,而不像杠杆机器那样继续镜头。杠杆机器没有三通阀来释放圆盘内部的压力。因此,我能够干燥一些用过的咖啡球,并将提取率与我用折射计进行的测量进行比较,折射计类似于以前的数据,但侧重于 1:1 拍摄。

干燥方法

为了弄干咖啡,我做了以下简单而又能保持一致性的实验:

  1. 我把冰球放在托盘上。
  2. 把冰球切开
  3. 在 200 华氏度的烤箱中干燥 30 分钟

通常,在最初的十分钟里,你可以看到水汽在窗户上积聚,但随后就消失了。

所有图片由作者提供

测量基线湿度

首先,我通过干燥新鲜的咖啡渣来测量我正在使用的咖啡渣的湿度。之前没想到这么做是因为我没有添加水分(加湿咖啡加快脱气)。因为我知道我添加了大约 1%的水分,所以我想对现磨咖啡进行地面实况测量。

该实验包括 6 次烘烤,并且水分含量不同。烘烤后我加了 1%的水分来模拟加速脱气的湿度处理

该数据对于帮助测量干燥废橡胶圆盘的提取率很重要。

设备/技术

意式咖啡机 : 像样的意式咖啡机

咖啡研磨机:小生零

咖啡:家庭烘焙咖啡,中杯(第一口+ 1 分钟)

镜头准备:断奏夯实断奏

预灌注:长,约 25 秒

输液:压力脉动

过滤篮 : 20g VST

其他设备: Atago TDS 计Acaia Pyxis 秤

性能指标

性能的主要指标是通过干燥圆盘和折光率仪的提取率。

用折射仪测量总溶解固体量(TDS),这个数字结合咖啡的输出重量和输入重量用于确定提取到杯中的咖啡的百分比,称为提取率(EY)** 。**

通过使用干燥的用过的圆盘的重量并除以输入的重量来确定来自干燥圆盘的 EY。

答案是 42

我在 6 次烘烤中收集了 42 个样本。我从干冰球上看着 EY,然后也调整了 EY。我调整了干帕克 EY 和由 TDS 测量的 EY,以说明咖啡渣中的水分。

然后我绘制了这些数据对,如果 TDS 是一个完美的度量,那么所有的点都会落在 y=x 的黑线上。调整后的 EY 的偏移量约为 1.5%。

我们也可以通过烘烤来观察这一点,它们在很大程度上遵循类似的趋势。

我们可以通过断奏夯实(最接近常规拍摄)和断奏拍摄的方式来切割这些数据。断续拍显示偏移,而断续拍更接近 y=x 线。我不确定这是为什么,或者在断奏中是否有一些基本的东西,比如糖,与断奏相比更线性地提取。

我查看了一般统计数据,所有这些分布在双尾配对 t 检验下都具有统计学意义(p 值< 0.05)。

这类数据的有趣之处在于相对新颖,因为没有多少数据被公布。当然,已经收集了大量的数据,但是像许多咖啡一样,数据被收集数据的人保密。这让咖啡更加神秘,也促使我尽可能多地发布我收集的数据。

如果你愿意,可以在推特、 YouTubeInstagram 上关注我,我会在那里发布不同机器上的浓缩咖啡照片和浓缩咖啡相关的视频。你也可以在 LinkedIn 上找到我。也可以关注我在订阅

我的进一步阅读:

我未来的书

我的链接

浓缩咖啡系列文章

工作和学校故事集

极端流失预测:没有特征的预测

原文:https://towardsdatascience.com/extreme-churn-prediction-forecasting-without-features-8ebd4a8dc8b

研究事件频率以识别异常行为

照片由 Isravel RajUnsplash 上拍摄

如今,我们生活在一个以数据为中心的世界。我们的每一项行动都会产生大量数据,这些数据可以被收集并用于产生有价值的商业见解。大型科技公司非常了解这些动态。通过监控我们的日常活动,有可能识别我们的习惯和偏好,以定制优惠并增加参与的可能性

同时访问和利用由每个个人/用户产生的大量各种各样的数据可以增加业务成果,更好地满足客户,并授予领先的市场地位。正如我们想象的那样,产生和储存的信息是巨大的,而且种类繁多。从这个意义上来说,商业智能和机器学习在为我们处理的数据提供有价值的意义并做出最有效的决策方面发挥着至关重要的作用

在商业价值最大化的范围内,我们可以采用机器学习来检测客户何时接近于搅动,确定最佳的保留策略,根据他们的偏好推荐最佳的服务或产品,等等。将人工智能解决方案应用于客户参与的可能性有很多。拥有一套完整而丰富的数据可能会为我们的需求带来巨大的附加值。作为数据科学家,我们可以通过合并不同的数据源和构建有意义的特征来构建强大而复杂的管道,以支持我们的预测算法

这听起来像是魔法,也是每个数据科学家的梦想。由于收集和存储数据应该是每个以数据为中心的公司的必经之路,所以它可能不会那么容易和免费。使用少量观察值、低质量数据或没有有意义的预测值的工作可能经常发生。在这种情况下,我们应该重塑自我,利用我们所拥有的一切来提供最佳解决方案。

在这篇文章中,我们开发了一个检测顾客何时离开的解决方案。我们不采用标准或复杂的机器学习方法。我们模拟极端场景中的操作,其中我们只存储了每个用户的购买信息以及相对数量。我们对客户一无所知,也无法合并任何有价值的外部数据源来帮助我们丰富数据集。通过简单有效的统计技术,我们旨在获得合理的结果,这些结果也可用于更复杂解决方案的基准测试

模拟设置

我们想象自己是一家销售产品或服务的公司。我们不提供订阅。我们的顾客在需要时会自行购买。对于每个客户的订单,我们可以检索日期和相应的金额。这些是我们唯一能收集和获得的东西。

在本文的范围内,我们模拟在给定的时间范围内固定数量的客户的一些订单。当客户停止从我们这里订购并且不再购买任何东西时,我们会注册一个客户流失。

订单频率(图片由作者提供)

根据我们掌握的信息,我们可以检索两次连续购买之间的间隔天数(即订单频率)。计算两个相邻订单的天数差异是开发我们解决方案的基础。我们的目标是主要通过查看每个客户的订单频率分布来识别客户流失。如果自上次购买以来的天数与通常的客户订单频率相差甚远,我们有信心遇到客户离开。换句话说,对于每个客户,我们验证今天和最后一个订单日期之间的差异是否大于过去。

订单数量 vs 订单频率均值/标准差(图片由作者提供)

实际上,我们必须开发一种算法,通过研究订单频率分布,可以提醒每个客户在任何日期的交易风险。我们提出两种简单而有效的方法:

  • 西格玛建模
  • 累积分布函数(CDF)建模

通过 sigma 建模,我们计算了历史参考期内每个客户订单频率的平均值和标准差。在推断过程中,我们验证今天和最后一个订单日期之间的差异是否大于平均值加上 n 倍 sigma。如果发生这种情况,我们的客户不再像以前那样频繁购买,这可能表明可能会有客户流失。

使用 CDF 方法,我们将订单频率建模为一个随机变量(精确地说是一个截尾正态),根据每个客户的历史参考期构建相应的反单调 CDF。在推理时,我们可以确定今天和最后一个订单日期之间的任何差异的概率,该差异大于预定义的置信水平。和以前一样,如果发生这种情况,我们的客户不再像以前那样频繁购买。为了提高 CDF 建模的有效性,如果我们认为它对客户流失检测有意义,我们还可以在公式中包含订单量。如果我们希望更重视金额接近普通客户历史支出的采购,这一点很重要。

结果

为了测试所提出的技术是如何工作的,我们按照一种滑动窗口方法将它们应用于我们所处理的所有模拟数据。我们在每个月的第一天评估每个客户的搅动倾向。作为基本事实,我们知道客户何时向我们下了最后一笔订单(也就是说,我们知道他们何时流失)。通过这种方式,就有可能计算出准确性、精确度和召回率等标准指标。

对于这两种方法,我们只在固定的购买量(在我们的例子中是 6 个订单)后评估每个客户,以建立可靠的订单频率分布,并使程序更可信。另一方面,我们更愿意对这些客户什么都不说,等以后再评价。

回忆结果。比较方法论(图片由作者提供)

精确结果。比较方法论(图片由作者提供)

准确性结果。比较方法论(图片由作者提供)

提议的方法似乎在识别可能的混乱方面做得很好。sigma 的精度似乎最高,而 CDF 的精度更高,召回率也更高。通过调整 sigma 水平或 CDF 置信度,可以对这些方法进行可能的调整和调节。

摘要

在这篇文章中,我们介绍了两种利用事件频率研究来识别可能的异常行为的方法。我们在一个 churn 应用程序中应用了上述方法。这同样适用于所有任务,在这些任务中,对事件之间的时间的研究对于做出决策至关重要。由于其简单性和适应性,当有可能采用更复杂的解决方案时,所提出的方法也可以用作基准。

查看我的 GITHUB 回购

保持联系: Linkedin

简单解释了 f 分布

原文:https://towardsdatascience.com/f-distribution-simply-explained-45d0e6768a4

对 f 分布的简单而简明的描述

马林·图拉德在 Unsplash 上的照片

介绍

在本文中,我们将介绍常用于方差分析(ANOVA) 测试的 F 分布(Fisher–Snedecor 分布),如果您是数据科学家,这绝对值得了解!

f 分布与卡方分布密切相关。如果您不熟悉卡方分布,我强烈推荐您阅读我以前的一篇文章,其中详细介绍了这种特殊分布的复杂性:

起源

如果随机变量满足以下条件,它就是 F 分布的一部分:

作者在 LaTeX 中创建的方程。

作者在 LaTeX 中创建的方程。

其中 χ2 是来自两个独立样本的两个不同的卡方分布随机变量,分别具有自由度v1v2。换句话说,它是两个卡方分布随机变量除以其相应自由度的比率。

记住卡方分布的自由度是我们平方并求和的正态分布随机变量的数量。如果你对此不熟悉,可以参考我上面链接的“卡方分布简单解释”文章!

所有可能的 F 值的分布导致了 F 分布!

如果你一直在密切关注我的文章,你可能已经意识到 f 分布基本上是从二项分布得到的:

二项式->泊松->指数->伽马->卡方-> F-Dist。

概率密度函数

我们可以从 累积密度函数(CDF) 中推导出 概率密度函数(PDF) ,就像我们对大多数分布所做的那样。然而,由于 F 分布推导的复杂性和穷尽性,我在本文中省略了它。

有兴趣的读者可以在这里 找到一个的完整推导 ,里面包含了雅可比矩阵等很多好玩的东西!

然而,F 分布的 PDF 看起来很吓人:

作者在 LaTeX 中生成的方程。

注意所有的伽马函数,这是因为卡方分布是伽马分布的一种特定情况。因此,这就解释了为什么 F 分布在其 PDF 中有相当多的伽马函数。

情节

F 分布的形状由两个自由度值 v_1v_2 控制。

下面是我用 Python 生成的一些 f 分布图:

# import packages
import numpy as np
from scipy.stats import f
import matplotlib.pyplot as plt# get x values
x = np.linspace(0, 4.5, 1000)# get F-Distributions    
f1 = f(1, 1, 0)
f2 = f(6, 2, 0)
f3 = f(2, 6, 0)
f4 = f(10, 20, 0)# plot the distributions
plt.figure(figsize=(12, 6))
plt.plot(x, f1.pdf(x), label = 'v1 = 1, v2 = 1', color = 'blue')
plt.plot(x, f2.pdf(x), label = 'v1 = 6, v2 = 2', color = 'green')
plt.plot(x, f3.pdf(x), label = 'v1 = 2, v2 = 6', color = 'red')
plt.plot(x, f4.pdf(x), label = 'v1 = 10, v2 = 20', color = 'orange')
plt.xlim(0, 4)
plt.ylim(0.0, 2)
plt.xticks(fontsize=16)
plt.yticks(fontsize=16)
plt.xlabel('x', fontsize=18)
plt.ylabel('PDF', fontsize=18)
plt.title("F Distribution",fontsize=20)
plt.legend(fontsize=14)
plt.savefig('f_dist.png')
plt.show()

作者用 Python 生成的图。

我们看到一些有趣的特性:

  • 随着自由度变大,分布开始向正态分布收敛。
  • 这种分布通常是右偏的和重尾的
  • 它总是连续。

结论

在本文中,我们解释了 f 分布的来源及其与卡方分布的关系。这篇文章比较短,因为它是为了让读者熟悉 f 分布。在我的下一篇文章中,我们将讨论如何在方差分析测试中使用 f 分布!

和我联系!

(所有表情符号都是由 OpenMoji 设计的——开源的表情符号和图标项目。执照: CC BY-SA 4.0

脸书先知,柯维德和我为什么不信任先知

原文:https://towardsdatascience.com/facebook-prophet-covid-and-why-i-dont-trust-the-prophet-f70d367fb13a

意见

脸书预言家在时间序列预测方面非常受欢迎。让我告诉你为什么我不是一个大风扇,你还可以使用什么。

穆斯塔法·梅拉吉在 Unsplash 上的照片

介绍

脸书先知可以说是时间序列预测和相关任务最广为人知的工具之一。问任何一个处理时间序列数据的数据科学家,他们是否知道 Prophet,答案可能是肯定的,或者是恼火的肯定。

毕竟,脸书预言家已经成为解决时间序列问题的一个颇有争议的工具。有些人不想在没有它的情况下工作,有些人明显讨厌它

然而,不管你喜不喜欢,当涉及到模拟新冠肺炎冲击时, Prophet 用户似乎面临着相当大的挑战。虽然现在人们已经找到了解决方法,但我认为这些问题是由脸书先知的一个更深层次的问题引起的:

脸书先知的根本缺陷

“脸书预言家”最大的问题在于,它将时间序列建模简化为曲线拟合任务。其他方法将自回归动态作为基本假设。另一方面,Prophet 只是试图在时间上对你的数据画一条误差最小的线。

更严格地说,几乎所有动力系统的进化都依赖于过去的实现。我们可以这样写:

(图片由作者提供)

我们只考虑对最后一次观测的依赖,不考虑隐藏态。

大多数时间序列模型集中在右边。然而,脸书先知关心的是等式的左边。更糟糕的是,预言家在上面隐含地做出了以下假设(参见脸书的预言家论文,第 14 页,以供参考):

(图片由作者提供)

这是有问题的,至少有三个原因:

  1. 完全忽略对过去实现的依赖。在现实世界中,一次大的冲击会迅速改变时间序列的整个未来轨迹。这可以用一个动力学模型来解释,但不能用脸书预言家来解释。
  2. 均值函数需要在观察值范围之外进行外推。Prophet 框定建模问题的方式不可避免地导致了非分布泛化的问题。你所有的未来都将在你的训练领域之外。
  3. 方差被假定为常数。与 1 有关。—如果随机冲击对未来有影响,那么方差(作为不确定性的衡量标准)应该随着我们对未来的预测而增加。

一般的经验法则是:如果模型的预测间隔没有随着时间的推移而增长,那么它可能有问题。除非你确切地知道你在做什么,否则你应该考虑一个替代方案。

脸书先知的表现低于玩具基准

为了举例说明上述情况,我对德国经济数据进行了一个非常简单的预测基准。虽然这个例子有点人为,而且太小,不能一概而论,但其含义应该是清楚的。

我使用了以下数据集:非专业商店的零售额(例如食品)—2012 年 1 月—2022 年 5 月(每月;此处可用)。训练集由 2021 年 1 月至 2019 年 12 月的所有数据组成;测试集使用 2020 年 1 月至 2022 年 5 月的所有数据:

不含食品的德国零售销售数据。(图片由作者提供)

一个合理的预测模型至少应该能够预测随机冲击的可能性。通过增加预测间隔,这通常是可见的。毕竟,我们越往前看,发生重大事件的机会就越多。

在这种情况下,时间序列在受到日冕的冲击后不会完全失常。因此,脸书先知不应该在这里纠缠太多。让我们看看它是如何做到的:

简单的预言家预测

脸书预言家做出的点位预测和预测区间。(图片由作者提供)

因为平均预测预言家能够合理地预测样本外——至少在某种程度上。然而,预测间隔完全是荒谬的。我们的模型只是从样本内数据中粗略地提取残差,并将它们的区间投射到未来。

这清楚地表明,脸书先知并没有真正学到内在的动力,而仅仅是时间的函数。如果 Covid 对潜在动态的影响更糟,我们甚至可能看不到合理的点位预测。我敢肯定,有许多数据科学家正是如此。

一个更简单的预测模型

正如您现在可能已经听到的,Prophet 没有学到任何关于底层系统动力学的知识。因此,我们的目标是现在创造一个竞争对手,它是 a) 非常简单并且 b) 能够实际模拟动态。

从时间序列图中,我们看到有一个明显的年度季节性。通过季节差异移除后。我发现还有一个剩余的积分成分,我通过另一轮一阶差分将其移除。

显然,这不是一个完整的诊断,但对于我们简单的玩具例子来说已经足够了。此外,由于时间序列是非负的,我最初通过求平方根来转换它。这确保了重新变换的序列也将是非负的。

综上所述,我们得出以下相对简单的模型:

(图片由作者提供)

总之,我们假设,在“平方根”和差分之后,只剩下一个噪声项。这里,我们甚至假设噪声分布随时间保持不变。更复杂的模型显然应该检查时变噪声。

我们的模型现在唯一需要学习的是噪声的分布。之后,我们抽取噪声样本并重新积分(即重新变换差分运算)。最后,我们估计点和区间预测。

为了了解噪声分布,我使用了 scipy 的gaussian_kde函数。这使高斯核密度估计器适合数据。然后,我们可以使用该估计值来绘制噪声样本:

变换后时间序列的直方图和核密度估计。(图片由作者提供)

接下来,我们抽取样本,并将其重新转换为原始时间序列的预测:

使用简单玩具模型进行均值和区间预测。(图片由作者提供)

尤其是预测区间比脸书预言家更有意义。正如所期望的那样,预测间隔随着时间的推移而变大,这意味着不确定性的增加。

让我们再做一个横向比较:

玩具模型和脸书预言家预测。(图片由作者提供)

我们也可以计算两种平均预测的 T2 RMSE T3。对于脸书先知,我们得到**RMSE(Prophet) = 22.49**,而我们的玩具模型有**RMSE(Toy Model) = 20.75**。这对 Prophet 来说很成问题,因为我们的玩具竞争对手实际上只是一个游乐场。

专为 Prophet 用户准备的外卖

问题是,我们能从中得到什么?显然,《脸书先知》庞大的长期用户群表明,人们正在从中获得一些价值。此外,脸书/梅塔雇佣了一些非常聪明的人——他们不太可能创建一个完全无用的库。

回到我们最初的考虑,我们可以推断如下:

Prophet 应该工作得很好,只要它正确地描述了条件均值和条件方差。数学上,

(图片由作者提供)

当基础系统处于良好的均衡状态时,例如当经济处于非波动状态时,可能会出现这种情况。然而,一旦出现大的震荡,方差要求几乎肯定会被打破。这正是我们在上面的时间序列示例中看到的。

因此,你应该完全放弃先知吗?如果结果是好的,如果你的预测变得完全疯狂不会有很大的负面影响,我认为你应该保留它。永远不要改变一个正在运行的系统,至少不要一夜之间。

但是,如果你非常依赖一个随时会随机崩溃的模型,你可能要开始寻找替代方案了。

在我看来,脸书先知更有意义的另一个用例是异常值和变化点检测。如果你只是对偏离预期轨迹感兴趣,prophet 可以为你赢得一些快速而简单的胜利。然而,一旦预测质量成为一件事,你就应该小心了。

神经先知,又名脸书先知 2.0,会让事情变得更好吗?至少他们的 Deep-AR 模块现在考虑过去的实现来预测未来。另一方面,神经先知仍然大量使用曲线拟合。因此,你也应该警惕先知的升级。

如果你决定使用其中一个预言家,我建议你用琐碎的选择作为基准。当一个简单但理论上更合理的模型——如我们的例子——表现相当时,您可能需要重新考虑您的选择。

脸书先知的替代品

不尝试提供解决方案就不要抱怨。一方面,这些替代方案将需要更多的人工工作来找到合适的模型。另一方面,该产品很有可能比方便的Prophet().fit()更健壮。

  • Kats :虽然 Kats 是一个用于一般时间序列分析的广泛库,但它也提供了一些预测端点。就像 Prophet 一样,它也被脸书/Meta 开源了。
  • 飞镖 :专门针对预测问题。Darts 支持多种建模选项。
  • tsfresh :这个包只为你创建一大套时序汇总统计。然后,您可以在自定义预测模型中使用这些功能作为预测器。相当灵活,但也需要更多的体力劳动。

结论

尽管广受欢迎,脸书先知包含一些严重的理论问题。这些缺陷很容易使其预测变得无用。一方面,Prophet 让建立大规模预测模型变得轻而易举。然而,这种便利是以相当大的不可靠性为代价的。

综上所述:只要你希望你的时间序列保持一定的稳定性,Prophet 可以是一个有用的即插即用解决方案。然而,不要被先知多次正确所迷惑。最坏的情况是,当它突然不再存在时,你最终会破产。

原载于 2022 年 8 月 8 日 https://www.sarem-seitz.comhttps://www.sarem-seitz.com/facebook-prophet-covid-and-why-i-dont-trust-the-prophet/

脸书 SQL 面试问题演练—热门帖子

原文:https://towardsdatascience.com/facebook-sql-interview-question-walkthrough-popular-posts-614b34ec3861

我们的一系列面试问题演练继续进行!今天我们将处理高级元/脸书 SQL 面试问题。

作者在 Canva 上创建的图片

元/脸书都是关于数据的,而这些数据是你创造的。你作为用户喜欢什么,评论什么,发帖什么,都会定期收集分析。

这一分析体现在我们今天向您展示的面试问题中。为了让解释更加简单,我们制作了一个视频:

meta/脸书 SQL 面试问题

这个问题会问你以下问题。

这是问题的链接,如果你想跟我一起去的话。

你的任务是找出热门帖子,即那些被浏览超过 5 秒钟的帖子。对于所有热门的帖子,你需要找到帖子 ID 和以秒为单位的总观看时间,才能通过这个面试问题。

这个要求看起来很简单,但是这个问题被归类为困难是有原因的。我们建议你通过应用这个简单而有效的框架来解决这个问题,以及所有其他的编码面试问题。

如果你这样做了,你就不会在解决问题的过程中看到所有等待你的陷阱,从而避免做出轻率的——而且大多是错误的——决定。

解决元/脸书(和所有其他)SQL 面试问题的解决方案框架

作者在 Canva 创建的图像

该框架由三个步骤组成。我们在许多文章中使用了这个框架,并对其进行了一些修改。

这些是我们在解决面试问题时要用到的步骤。

  1. 探索数据集
  2. 写出方法
  3. 解决方案编码

首先,了解数据集。给你什么桌子,你需要所有的桌子吗?如何连接这些表?表格的列和数据类型是什么,数据显示什么,在表格中是如何表示的?这些都是这一步会帮你回答的问题。

然后考虑你将如何进行编码,你的代码的逻辑构建块,以及你将使用什么函数。如果你还没有,这是吸引面试官的必经步骤。与他们交谈,创造一个对话来验证你的逻辑是否正确。

最后,您可以开始编写您的解决方案了!

1.探索数据集

问题给出了表用户会话帖子视图

user_sessions 表包含以下数据类型的列。

您可以假设列 session_id 是表的主键。所有其他列为您提供关于特定会话的支持信息。

当分析数据集时,考虑如何创建列和表的叙述。这样,你会更好地理解你面前的数据集。这也给了你一个极好的机会与面试官交流,问问题,澄清你的假设。我们总是建议你在面试中大胆思考。一开始可能会觉得有点尴尬,但是当你看到它是如此的高效时,你很快就会习惯了。

这个表的叙述可以这样构成。每个会话 ID 都是连续的,并且对于用户和平台组合是唯一的。如果用户注销并重新登录,将会创建一个新的会话 ID。如果用户从笔记本电脑切换到移动设备会怎样?这将被记录为两个单独的会话。

由此,您可能会看到重复的用户 id 和 user_id/platform 组合。

第二个表具有以下模式。

session_id 列与第一个表中的相同,因此可以假定它是这个表的外键。可以使用这个公共列来连接这些表。

需要知道的一件重要事情是 perc_viewed 列中的数据是如何表示的。10%显示为 10.0 还是 0.1?你可以做一个假设,或者问面试官。

预览确认百分比是如何显示的。

表格:帖子 _ 浏览量

为了继续叙述,可以在单个会话中查看几个帖子。因此,上表中应该有多个会话 id。

此外,将有多个帖子 id,因为帖子可以在不同的会话中被多次查看。

2.写出方法

在考虑方法时,考虑输出应该是什么样子。然后,确定您需要什么数据,以及您需要如何操作它来获得所需的输出。

对于这个问题,输出将有两列:post_id 和 total_viewtime。

1。计算会话持续时间

持续时间是会话结束时间和开始时间之间的差值,可以在表 user_sessions 中找到。

EXTRACT()和 EPOCH 函数是获取会话持续时间(以秒为单位)的绝佳组合。

2。计算帖子在每个时段的浏览次数

可以使用以下公式计算观看后时间。

PercentViewed 是查看帖子所花费的会话百分比。这由表 post_views 中的 perc _ viewed 列表示。

另外,前面的计算必须转换成一个子查询,并与这个子查询连接。

3。计算每个帖子在所有会话中的总浏览时间

此计算需要使用 SUM()聚合函数对 PostViewingTime 求和。

要获得文章级别的值,需要按照 post_id 列对数据进行分组。

4。仅过滤热门帖子

请记住,该问题将热门帖子定义为观看时间高于 5 秒的帖子。

因为您将在聚合后过滤数据,所以使用 HAVING 而不是 WHERE。

3.解决方案编码

现在让我们使用概述的步骤来编写一个 SQL 解决方案。

1。计算会话持续时间

SELECT session_id,
 EXTRACT(EPOCH FROM session_endtime) - EXTRACT(EPOCH FROM session_starttime) AS duration
FROM user_sessions;

命令 EXTRACT(EPOCH FROM column_name)返回 Unix 时间戳或 Unix Epoch 时间。它是自协调世界时(UTC)1970 年 1 月 1 日星期四 00:00:00 以来经过的秒数。

就其本身而言,这个命令对这个分析没有太大帮助。然而,一旦演绎进入游戏,事情就不一样了。以秒为单位减去两个这样的值相当于以秒为单位获得两个日期时间值之间的时间差。你猜怎么着?这正是你解决这个问题所需要的。

运行上述代码会返回以下输出。

你可能认为有更直接的方法来做同样的事情。例如,通过直接减去结束和开始时间。

SELECT session_id,
       (session_endtime - session_starttime) AS duration
FROM user_sessions;

是的,是真的;它会给你带来同样的价值和产出——尽管只是表面上的。当直接减去两个日期时,结果是创建一个 interval 数据类型,而不是 float 或 integer。

我们还将向您展示如何使用这种方法来获得解决方案。

2。计算帖子在每个时段的浏览次数

在这一步中,添加计算文章查看时间的 SELECT 语句,并将其与前面的查询连接起来。

SELECT post_id,
       duration * (perc_viewed/100)::float AS seconds_viewed
FROM post_views p
JOIN
  (SELECT session_id,
          EXTRACT(EPOCH FROM session_endtime) - EXTRACT(EPOCH FROM session_starttime) AS duration
   FROM user_sessions) s ON s.session_id = p.session_id;

该查询将输出这些数据。

我们对数据的假设在这里被证明是正确的。每个帖子有多个条目,每个条目代表一个单独会话的一个视图。

3。计算每个帖子在所有会话中的总浏览时间

要获得所有会话中每个帖子的总查看时间,您需要在 post_id 级别聚合结果,并对总查看时间求和()。

SELECT post_id,
       SUM(duration * (perc_viewed/100)::float) AS total_viewtime
FROM post_views p
JOIN
  (SELECT session_id,
   EXTRACT(EPOCH FROM session_endtime) - EXTRACT(EPOCH FROM session_starttime) AS duration
   FROM user_sessions) s ON p.session_id = s.session_id
GROUP BY post_id;

在这个结果中,您获得了独特的职位和他们的总观看时间。在最后一步,你必须过滤数据,只显示热门的文章。

4。仅过滤热门帖子

要获得最终输出,需要使用 HAVING 子句。您不能使用 WHERE,因为您需要在聚合后应用过滤器。您可能已经知道了这一点,但是有必要提醒自己:WHERE 之前过滤数据,而 have 在聚合之后过滤数据。

输出显示了两个热门帖子及其各自的总查看时间。

可选择的解决方案

还记得我们说过日期可以直接减去吗?让我们试试看这种方法能否给出这个问题的正确答案。

SELECT post_id,
       SUM(duration * (perc_viewed/100)::float) AS total_viewtime
FROM post_views p
JOIN
  (SELECT session_id,
          (session_endtime - session_starttime) AS duration
   FROM user_sessions) s ON p.session_id = s.session_id
GROUP BY post_id
HAVING SUM(duration * (perc_viewed/100)::float) > 5;

不,它返回一个错误!

出现错误是因为 SUM(duration *(PERC _ viewed/100)::float)输出一个区间,我们将它与一个整数进行比较。

然而,这并不意味着我们不能让这种方法工作!解决方法相当简单;你得把整数转换成区间,就像这样。

SELECT post_id,
       SUM(duration * (perc_viewed/100)::float) AS total_viewtime
FROM post_views p
JOIN
  (SELECT session_id,
          (session_endtime - session_starttime) AS duration
   FROM user_sessions) s ON p.session_id = s.session_id
GROUP BY 1
HAVING SUM(duration * (perc_viewed/100)::float) > 5 * '1 sec'::interval;

这个对代码的微小修改给了你问题的答案。

最佳化

在大多数面试中,你会被问到的一个问题就是优化你的代码。看看解决方案,想想有什么可以优化的。

我想到的是通过使用公共表表达式或 CTE 使代码更具可读性。

这是优化后的解决方案。

WITH temp AS 
(SELECT session_id,
  EXTRACT(EPOCH FROM session_endtime) - EXTRACT(EPOCH FROM session_starttime) AS duration
FROM user_sessions)SELECT post_id,
       SUM(duration * (perc_viewed/100)::float) AS total_viewtime
FROM post_views p
JOIN temp ON p.session_id = temp.session_id
GROUP BY post_id
HAVING SUM(duration * (perc_viewed/100)::float) > 5;

结论

没那么难吧。

我们将这个问题归类为硬级别问题,因为它需要各种技术概念的知识,比如连接、聚合、过滤器、日期时间数据和子查询。

如果你对这些概念很熟悉,你应该很容易找到解决方案。同样重要的是了解您的数据,并预测可能会改变您的代码并使其工作或不工作的不同数据格式。

你现在需要的只是一些练习。查看类似“脸书 SQL 面试问题”和“脸书数据科学家面试问题”的帖子,练习更多真实世界的面试问题。

无人工神经网络的面部表情识别(FER)

原文:https://towardsdatascience.com/facial-expression-recognition-fer-without-artificial-neural-networks-4fa981da9724

SVM、PCA 和 HOG 联手解决了一个计算机视觉问题

照片由你好我是尼克Unsplash

介绍

数据和机器学习

当谈到机器学习时,很明显,从数据中学习的是计算机编程的科学(和艺术)[1]。但是,这个定义引发了一些问题,第一个就是:数据?Excel 电子表格?

人们首先想到的(或者至少是我首先想到的)是结构化数据,比如。xlsx。csv 文件。然而,每个人都说“数据无处不在”,我最喜欢的是图像(归根结底,图像只是一组数字)

照片由西蒙·李Unsplash 上拍摄

计算机对数字图像或视频执行的任务属于计算机视觉领域。当计算机视觉与深度学习(专注于人工神经网络的机器学习领域)相结合,令人兴奋的项目和应用就出现了。

由于卷积神经网络(CNN) 的实现,有许多计算机视觉任务已经涉及到深度学习(如图像分类和对象检测)。

照片由 Alina GrubnyakUnsplash 上拍摄

代替卷积神经网络的经典机器学习

很明显,面对任何图像分类问题,CNN 都是最合适的;然而,在这个项目中,我想通过经典的机器学习算法找到一个解决方案。

也许有些读者想知道我为什么要这样做。简而言之,我想尝试特征提取方法,探索经典机器学习算法的局限性。

放弃

在这个项目中,我旨在探索如何解决这个问题。由 Hivi Ismat Dino 和 Maiwan Bahjat Abdulrazzaq 编写的基于 SVM、KNN 和 MLP 分类器的面部表情分类中规定了该方法。

数据和维度的诅咒

你可以在这里下载图片和 CSV 文件

在小尺度下,物理现象的表现与普通尺度不同(量子物理 vs 经典物理);类似的行为发生在更高的维度。

二维向量有两个分量,并且存在于二维空间中:

三维向量有三个分量,存在于三维空间中:

以此类推:

有趣的事情发生在高维空间,例如:

  • 高维超立方体中的大多数点都非常靠近边界[1]
  • 超立方体中两点之间的平均距离是很重要的。例如,在三维立方体中,任意两点之间的平均距离为 0.66;但是在一个 100 万维的超立方体中,两点之间的平均距离是 408.25 [1]。

发生什么事了?为什么会这样?嗯,在高维空间里有很多空间。因此,数据非常稀疏,导致新实例远离训练数据,使得预测不如低维数据集可靠[1]

使用的数据集是表达两种情绪之一的面部图像的集合:积极的或消极的。这些图像是 64×64 像素,如果每个图像都被转换成一个超矢量,我们最终会得到 4096 个特征数据集,这是一个很大的维度。

怎么解决呢?

对于这种情况,有许多处理方法,但值得探索的有:

  • 特征检测。
  • 降维。

特征检测器:梯度方向直方图(HOG)

H 面向OG 的特征描述符( HOG )是 Dalal 等人在 2005 年提出的特征描述符[2]。该描述符计算特定像素周围像素亮度的变化。这种变化由梯度(变化向量)给出,其具有幅度 m 和角度𝛉(等式。1 和 Eq。2):

等式 1

等式 2

如果你想深入了解这个技巧,我推荐下面这个视频(此处)。

图一。示例:原始人脸图像

图二。示例:面部的猪图像

通过应用该技术,特征的数量从 4096 变为 1764(减少了 60%)。

HOG 可以在库上找到scikit-image **from skimage.feature import hog**

降维:主成分分析

多亏了 HOG,维度下降了,但还不够;必须采取下一步措施。

PP主成分 C 成分 A 分析( PCA )是减少数据集中特征数量的最流行方法之一。这个无监督学习算法找到了保留最大信息量的线性投影。换句话说,PCA 找到最大化数据集方差的超平面[1]。

像 K-Means 一样,我们必须声明我们想要的聚类数;使用 PCA,我们必须给出我们想要减少数据集的特征的数量。用于查找最佳特征数量的标准标准是当解释的方差没有显著增加时,类似于 K-Means 上的肘方法。

图 3。的变化解释了差异。图形未缩放。图由作者制作。

获得简化特征的最佳数量的另一种方法是给出我们想要保留的信息的百分比(或比例)。

分类器:支持向量机

SsupportVectorMachine(SVM)是机器学习中最优雅的算法之一,也是最强大的算法之一。有了正确的预处理数据,SVM 的性能可以达到人工神经网络的高度,就像文章手写数字识别的降维【3】中所说的那样

这个算法的一个特点是内核技巧。这种技术在不影响计算性能的情况下转换数据的维度,因此它可以是线性可分的[1]。

有一种处理非线性问题的技术,它增加了使用相似性函数计算的特征,该函数测量每个实例与特定地标的相似程度。高斯径向基函数** 是一个相似性函数,加上内核技巧的魔力,在 SVM 上产生了令人难以置信的结果。

图 4。高斯 RBF 如何转换数据的例子。原特征为x1x2x3 是由高斯 RBF 创建的特征。灵感来自[1]。

等式 3。高斯径向基函数

等式 3 向我们展示了高斯 RBF 核,其中 ab 是超矢量,𝛄(伽马)是超参数。增加𝛄会使钟形曲线变窄(如果模型拟合不足,则增加𝛄),从而导致每个实例的影响范围变小,而减少𝛄会使钟形曲线变宽(如果模型拟合过度,则减少𝛄 ),从而导致相反的效果。

基于 Sci-kit 学习的高斯 RBF 核 SVM。记住 C 也是一个正则化超参数。所以 C 的值越大,支持向量的边界就变得越严格。

管道

除了所讨论的过程之外,在 SVM 分类器之前,数据必须处于相同的尺度;于是有了**StandardScaler**

此外,为了在管道中实现 HOG,必须创建一个新的类

第一个模型

韵律学

精度: 0.71962
精度: 0
回忆:0
F1-得分: 0

讨论

使用该模型及其超参数获得了低性能。混淆矩阵显示了导致高准确度的高真阴性;但是,没有检测到真阳性,导致所有其他指标的值为 0。

微调模型

为了提高模型的性能,必须修改超参数。手动完成这项任务并跟踪表演是乏味和累人的;为此使用了**GridSearchCV**

指标

精度: 0.91069
精度: 0.86612
回忆:0.80606
F1-得分: 0.83502

讨论

在应用 GridSearchCV 之后,找到了 SVM 的最佳超参数,并与先前的模型进行了比较;预测到目前为止有所改善。此外,该模型实现了高百分比和良好的平衡,用于将实际上正确的正类人脸从那些预测的人脸中分类出来,而没有很多错误警报。

ROC AUC 和 ROC 曲线的形状显示了良好的预测模型。

结论

关于项目

多亏了**GridSearchCV**,找到了模型的最佳超参数,通过这种方式,模型在精确度、召回率以及 F1 分数方面都取得了高分。重要的是要澄清**GridSearchCV**不是要创造一个随机数字的网格。了解这些超参数如何影响算法,可以区分执行的好坏。

支持向量机可以做很多事情。该项目展示了这种算法如何提取 n 维空间的抽象特征,并设法进行合理的分类。

未来的工作

这个项目的下一步是在一些应用程序中使用最终的模型,或者在外部设备上实现它,例如带有网络摄像头的 Raspberry Pi。

照片由哈里森·布罗德本特Unsplash 上拍摄

关于我学到的东西(个人观点)

在这个项目中,我可以探索更多的特征提取过程,如 HOGPCA 。虽然 HOG 不再是一种最先进的技术,但是理解底层计算从来都不是一个坏主意。一旦应用到项目中,这个概念就更容易理解了。

以复杂的问题为例,这些问题已经通过深度学习进行了处理,并尝试用经典的机器学习算法来解决它们,可以帮助更好地理解所看到的概念和新概念的应用。我也相信这样做显示了对同一情况采取不同观点解决问题的能力。

贮藏室ˌ仓库

https://github.com/isaacarroyov/fer_without_ann

关于我

我是艾萨克·阿罗约,工程物理学家。我想象自己通过使用数据科学和机器学习工具来解决不同类型的问题。我对数据可视化和无监督学习感兴趣。

你可以联系我,或者通过社交媒体(Instagram、Twitter 或 LinkedIn)关注我的工作和经历这里。我也用英语和西班牙语创建内容。

参考

【1】géRon,A. (2019)。用 Scikit-Learn、Keras 和 Tensorflow 进行动手机器学习:构建智能系统的概念、工具和技术(第二版。).奥莱利媒体。

达拉勒,n .,&特里格斯,B. (2005 年 6 月)。用于人体检测的方向梯度直方图。2005 年 IEEE 计算机学会计算机视觉和模式识别会议(CVPR’05)(第 1 卷,第 886–893 页)。Ieee。

【3】Das,a .,Kundu,t .,& Saravanan,C. (2018)。手写数字识别的降维方法。EAI 认可云系统交易,4(13)。

数据科学面试失败?这里有一些帮助你成功的建议

原文:https://towardsdatascience.com/failed-in-data-science-interview-here-are-some-tips-to-help-you-succeed-2e9a6bb2b307

基于 10,000+小时的经验和多次失败!

布雷特·乔丹在 Unsplash 上的照片

首先,如果你最近面试失败。记住,失败不是终点。这是一次学习和下次表现更好的机会。这是我最喜欢的克服失败的名言之一。

在我的职业生涯中,我已经错过了 9000 多次投篮。我已经输了将近 300 场比赛。有 26 次我被信任去投决定胜负的一球,但都没投进。我一生中一次又一次地失败。这就是我成功的原因。

—迈克尔·乔丹

我在许多数据科学工作面试中失败了。我继续在许多事情上失败。我早期的失败非常令人沮丧。这甚至让我怀疑自己的能力。我最终在数据科学领域获得了成功。这篇文章不是要吹嘘我的成功。相反,它是关于从我的失败中吸取的教训。最令人沮丧的是看到人们在非常接近成功后就放弃了。我见过很多人投入大量时间学习数据科学。但是在几次失败后,他们开始怀疑自己的能力并放弃了。如果你曾经在数据科学面试中面临失败,或者你有兴趣从别人的失败中学习。我保证这篇文章不会让你失望。

有些人尝试几次就能成功。有些人需要更长的时间才能找到成功。这里的关键是要有耐心,继续专注于学习。下面是一篇关于一个人花了 475 份工作申请和 6 个月找到成功的文章。

没关系,失败过多少次。最重要的是要有一个成长的心态。在这篇文章中,我将讨论在数据科学面试中需要关注的重要领域。

1.为开幕做准备

最初的几分钟是面试中最重要的部分。根据这篇文章,33%的老板在面试的前 90 秒做出决定。

在大多数面试中,问的第一个问题是“说说你自己吧”。对这个问题做好充分的准备。你可以利用这个问题来推动对你有利的面试讨论。回答这个问题的一个简单公式是,

  • 谈谈你目前的角色和项目
  • 谈谈你的经历和成就
  • 谈谈你的计划,以及这个角色如何与你的职业目标相一致

把你的回答控制在 2 分钟以内,多练习几次。不要重复你简历中的内容,你的面试官肯定会有一份你的简历。下面是 Seek 关于准备这个问题的一篇有趣的文章。

https://www.seek.com.au/career-advice/article/how-to-answer-so-tell-me-about-yourself

大多数人几乎不花任何时间准备这个问题。对这个问题有一个好的回答的重要性经常被低估。这常常被认为是理所当然的。

无法预测面试问题。但是你可以为最有可能被问到的问题做好准备。这无疑是求职面试中经常被问到的问题之一。如果你对这个问题有充分的准备,你将会有一个令人印象深刻的开始。

2.刷新基础

一旦你在最初的几分钟内给人留下了印象,那么唯一要关注的就是不要给出拒绝你的理由。确保这一点的一个方法是不要在数据科学基础知识上犯任何错误。

您需要熟悉数据科学项目整个生命周期中的基本概念。以下是大多数数据科学项目中常见的关键步骤背后的一些概念参考。在你面试之前修改这些话题是非常重要的。

特色工程

数据从来都不够干净,无法被模型直接使用。它总是需要某种程度的改进。面试官通常很想知道你是否知道通用的特征工程技术。此外,要很好地理解何时使用哪种技术。下面是一个惊人的资源,清楚地解释了特征工程的基础。本文还解释了使用这些技术的基本原理和好处。

下面是一个 Kaggle 笔记本的链接,它实现了常用的特征工程技术。

https://www.kaggle.com/code/prashant111/a-reference-guide-to-feature-engineering-methods/notebook

功能选择

在特性工程之后,下一个明显的步骤是特性选择。我们很少最终使用所有的功能。特征选择是一个重要的步骤,它帮助我们识别关键的特征或者去掉不重要的特征。下面是一个惊人的资源来学习和修改在不同情况下用于特征选择的技术。

https://www.analyticsvidhya.com/blog/2020/10/feature-selection-techniques-in-machine-learning/

了解算法

根据角色和工作级别的不同,此处要求的最低专业技能也有所不同。仅仅列举出可以用来解决特定问题的算法是不够的。但是,理解最适合不同场景的算法是很重要的。下面是一篇有趣的文章,解释了不同的算法及其优缺点。它还涵盖了可以使用算法的场景。

基于树的集成模型在许多现实生活用例中非常流行。与传统回归算法相比,基于树的集成模型的成功率要高得多。下面是另一篇深入的文章,解释了基于树的集合模型。它讨论了它们的优点、缺点和参数,并做了比较研究。

车型评测

通常,在开发解决方案时,我们会尝试不同的算法。但最终我们会选择那些与其他公司相比表现更好的公司。模型评估指标用于衡量模型的性能。这里有一个关于不同评估技术的终极指南,可以用于不同的问题。

https://neptune.ai/blog/the-ultimate-guide-to-evaluation-and-selection-of-models-in-machine-learning

面试中常见的其他概念

除了上面的题目,这里还有一些题目需要修改。关于这些话题的问题在面试中经常被问到。

  • 降维:当数据集中有太多特征时,通常使用这种技术。当特征的数量较少时,这意味着较少的内存就足够了,并且可能也需要较少的计算时间。这有助于减少数据集中的噪音。要详细了解优势和不同的技术,请查看下面的文章。

</11-dimensionality-reduction-techniques-you-should-know-in-2021-dcb9500d388b>

  • 调整:用于防止过拟合或欠拟合。套索和脊是最常用的正则化技术。它们之间的一个关键区别是,在 Ridge 中,所有的特征都被保留,而在 Lasso 中,不重要的特征被删除。要修改这两种技术,请查看下面的文章。

https://www.analyticsvidhya.com/blog/2021/05/complete-guide-to-regularization-techniques-in-machine-learning/

  • 偏差和方差:偏差和方差对于研究模型结果非常方便。这两者有一种相反的关系。这意味着不可能有一个低偏差和低方差的模型。在两者之间找到平衡是一门艺术。要修改主题,请参考下面的文章。

3.准备项目笔记

项目是我们简历和工作面试的一个重要方面。许多面试讨论是由项目细节驱动的。随着时间的推移,我们的记忆可能会失败。我们可能会忘记项目的一些细节。例如,数据中存在的数据质量问题、项目环境的限制等等。虽然这些在更大的计划中可能是微不足道的,但这些可能是项目一些关键决策背后的原因。这些细节可能会对你的面试产生非同寻常的影响。因此,我总是建议人们记录项目、使用的技术和模型,以及它们使用背后的基本原理。

这些项目笔记不需要很大的文档。如果这是一份很大的文件,那么它对面试准备没有太大的帮助。出于面试的目的,尽量少记笔记。它不应该超过几个要点。以下是一些可以作为参考的问题,

  • 1-2 分钟的项目总结
  • 项目的关键目标
  • 团队和技能组合
  • 关键决策及其背后的基本原理
  • 技术和非技术问题
  • 项目中涉及的步骤
  • 技术和工具的详细信息及其使用原理
  • 项目的影响
  • 可以做的改进/改变

这不仅对你的面试准备有用,而且对更好地理解也很有帮助。

如果你是数据科学的新手,那么你需要首先专注于建立一个好的项目组合。你可以通过在你的文件夹里放一个巨大的项目来破解一次面试。

4.阅读工作内容,了解公司

对这个职位或公司不够了解会给面试官发出危险信号。此外,在与面试官进行一般性讨论时,研究公司和工作简介有助于提高你的自信水平。它也发出了你准备充分的明确信号。

你可以更好地了解这个职位和公司的一些地方是,

  • 公司网站
  • 搜索关于公司的最新消息
  • 看看他们的博客
  • 查看他们的社交媒体页面
  • 搜索并了解他们的比赛
  • 关于整个行业的研究
  • 浏览 Glassdoor 上关于工作文化和面试流程的员工评论

5.从你的错误中学习,并有一个导师

面试失败也没关系,只要你能从中吸取教训。面试结束后,你可以花些时间回顾一下你的回答。你可以写下本可以做得更好的回答。这将有助于你在再次被问到类似问题时做好更充分的准备。了解你表现的另一个方法是直接向招聘人员寻求反馈。

更好地准备的一个方法是与朋友或导师讨论这些问题。他们可以帮助提供你可能不知道的细节。或者,你可以请一位更有经验的专业人士进行模拟面试。模拟面试有助于提高你的自信。在真正的面试之前,这对你更好地控制压力水平很有帮助。它还可以帮助你想出正确的策略。

根据你收到的反馈,检查你的简历是否需要更新。此外,让你在数据科学领域的朋友审阅你的简历,或者让导师审阅更好。有一些惊人的技巧可以写出一份好的简历。下面是一篇此类文章的链接,这篇文章讲述了撰写极具影响力的简历的强大技巧。

导师在一个人的职业发展中起着非常重要的作用。他们不仅仅帮助提供反馈。他们提供情感支持,也让你接触到他们的网络。人际关系网对了解有趣的工作机会很有帮助。

6.更有用的准备材料

下面是一些令人惊艳的面试准备资料。

https://www.edureka.co/blog/interview-questions/data-science-interview-questions/ https://github.com/khanhnamle1994/cracking-the-data-science-interview https://www.analyticsvidhya.com/blog/2017/01/46-questions-on-sql-to-test-a-data-science-professional-skilltest-solution/

最终提示

  • 做你自己!做你自己会让你更舒服
  • 对面试公司了解不够是一个严重的错误
  • 准备好回答你为什么想加入这家公司。
  • 准备好讨论你的薪资期望
  • 准备好询问关于角色和公司的问题
  • 不要谈论你不自信的概念、技术和算法
  • 有一个在职业生涯中领先你 3-5 年的导师
  • 回答问题时,一定要保持眼神交流

保持联系

环境传播中的假新闻检测

原文:https://towardsdatascience.com/fake-news-detection-in-environmental-communication-322ad64dfaba

计算难题

照片由 Unsplash 上的 nij wam Swargiary 拍摄

在自然语言理解中,假新闻检测已经成为一个极其热门的话题。它在研究方面是相关的,在商业场景中是可销售的,它也可能被认为是在寻求传说中的通用人工智能方面向前迈出的一步。

我是一名计算语言学家,我的研究领域是概念知识图。在过去的几个月里,我一直在运行多个假新闻检测实验,采用机器学习算法以及基于规则的符号模型。我的研究目标是理解知识图的使用如何使 ML 模型能够以与使用相同图的符号模型相似甚至更好的方式执行。

正如我们所知,人类开发人员可以依赖于对世界的复杂和精密的理解,但 ML 算法能够在大量训练数据中发现隐藏的趋势,因此比较总是值得研究的。此外,与 ML 算法相反,理解人类开发人员如何依赖 KG 对于我们开发更可靠的模型和管道至关重要,同时还可以识别并最小化 KG 本身可能带来的偏差。

我研究了几周后,结果似乎已经一致了。我的支持向量机模型和我的符号模型倾向于表现相似,也就是说表现相似。事实证明,知识图提高了这两种方法的可靠性,但并不显著。我找不到任何具体的偏见。

不过,有一个细节吸引了我的注意:在处理环境新闻时,这两种模型的性能都在稳步下降,产生了大量的误报。所以我直接检查了我的符号规则,我发现许多真正的环境文件在使用情感语言的地方被标记为假的。

假新闻中一个被广泛认可的语言标记是使用情感语言。当然,情绪化的语言不会自动发出虚假的信号,但在新闻中,尤其是在普及科学数据的新闻中,情绪化的语言,与中性的技术报道相反,可以作为一个相关的指标。但是现在环境交流使用的语言越来越情绪化,而我的计算分析跟不上这种转变。

我的模型的这种故障也可以被描述为一种有偏见的行为,这种行为被知识图表的使用放大了,知识图表特别擅长于寻找情感语言。我未能察觉和理解情绪语言使用的转变,这导致我通过使用倾向于避免情绪的旧的带注释的环境文章来训练我的 ML 模型,同时我不断开发倾向于在表达情绪时发出虚假信号的符号规则。

这种转变确实发生在我们的眼皮底下。直到 20 世纪 90 年代,环境文章一直使用浅显的教育语言,当时日益令人担忧的情况促使科学家教授普通公众专业术语,如生物多样性、生态系统或复原力,以提高参与度。

当阿尔·戈尔在 2007 年开始放映他的《难以忽视的真相》幻灯片时,其内容听起来令人担忧,但其技术上的清洁和科学摆脱灾难的承诺也令人放心。

但是,虽然技术术语对于提供准确的信息是有用的,但它并不一定会使读者更有知识。如今大多数人相当自由地使用术语生物多样性,但他们并不真正理解它在生物学术语中的含义,因为他们缺乏基本的生物学概念。反过来,生态系统很快扩展到人工和数字有机体,而弹性已经成为商业管理中的一个时髦词,而生物量在很大程度上仍然模糊不清。

同样有趣的是,在生态语言学中,物质名词(生物量)、抽象概念(生态系统)和隐喻(自然资源)的使用被认为是一种背景化和消除环境话语某些方面的方式,使读者在事实和情感上都超脱自己。这意味着,原本旨在提高公众环境素养的更专业的语言,现在可能有时被用来根据特定的议程操纵读者,或者可能因无意中产生情感距离而适得其反。

2018 年,格里塔·图恩伯格彻底改变了环境新闻的传播方式。她使用了语言冲击、基于代际冲突的两极分化和非常普通的内容。她的风格通过社交网络迅速流行起来,这导致了一种新的谈话风格,也造成了一些计算上的尴尬。事实上,大多数涉及图恩伯格的文章最初都被我的符号模型标记为假的,我需要手动纠正这种行为,修改语言规则,以便在环境新闻中使用时减少情感语言的权重。这个概念很容易嵌入到符号模型中,而在 ML 模型中,它涉及添加每条新闻的一般主题的混合预分类,并根据一组新的带注释的文档重新训练模型。

虽然图恩伯格现在可能会逐渐从公众话语中消失,但她的风格会一直存在。随着气候变化成为一个主流的、有分歧的主题,越来越多地采用讲故事的方式来吸引读者,有时实现前所未有的参与,有时引发点击诱饵效应。

与此同时,科学家的语言变得更加情绪化,因为气候变化的升级速度超过了预期,我们现在已经进入了科学不确定性的未知领域。除此之外,一些记者现在公开主张增加情感语言的使用,例如 T2 的乔治·蒙比尔特。

2019 年,《卫报》正式改变了其环境传播风格,决定提升紧迫感。气候变化现在总是被称为气候危机

照片由阿玛多·洛雷罗Unsplash 上拍摄

从计算的角度来说,只要我们能够注意到并理解语言的变化,我们就能解决它们。每个现象都需要分析并编码到我们的语言学模型中,在这种情况下,当它用于环境新闻时,特别是当我们使用知识图表时,通过引入情绪语言的专门管理,知识图表在检测它方面特别强大。

总的来说,我们必须时刻保持警惕,因为我们未能与社会语言学进程同步,可能会在我们甚至没有注意到的情况下,将既定特征变成危险的偏见。

假新闻对我们的社会有巨大的影响,对它们的检测对民主机制至关重要。我认为,在计算领域,我们应该挑战非黑即白的方法,转而拥抱复杂性。一条新闻很少是完全虚假的,它更多的是一个光谱,真实的事实往往根据特定的议程被重新构建。

我们也许应该瞄准一个能帮助和授权读者的模型,指出有意义的语言选择,以提高对信息的理解。这可以通过可解释的符号模型来实现,这些模型是根据相关的语言选择、结构和模式故意编码的。这样的标记很容易在每篇文章中被追溯和强调,我们作为读者可以从中学习。我们甚至会发现它们需要被重新考虑。

人工智能可以被视为代替我们做出决定的机器,有时是在一种疏远的互动中,但实际上是我们在指导它们,当我们编辑一个 KG 时,当我们依靠这个 KG 开发语言规则时,我们自己可以从这些指令中学习,从而成为这个过程的积极参与者。

python 中的 Faker 库——数据科学家的一个有趣的权宜之计

原文:https://towardsdatascience.com/faker-library-in-python-an-intriguing-expedient-for-data-scientists-7dd06f953050

python 中“Faker”库的安装、使用和应用,它可以在短时间内为数据科学实验生成大量虚拟数据集

马库斯·斯皮斯克在 Unsplash 上的照片

“一个整洁有序的实验室是不太可能的。毕竟,这是一个错误开始和多次尝试的地方

艾萨克·阿西莫夫

目录

  1. 介绍
  2. Faker 库的安装
  3. 生成基本数据点(姓名、地址、工作、日期等。)
  4. 生成虚拟配置文件
  5. 生成唯一的数据点
  6. 生成与货币相关的信息
  7. 生成哈希和 UUIDs
  8. 生成与互联网相关的数据
  9. 生成 JSON 数据
  10. 以多种语言生成数据点
  11. 生成大型数据集
  12. python 中的类似库
  13. 结论
  14. 参考

简介

数据是任何数据科学实验的主要基础。虽然数据是丰富的,但信息将是无结构的,需要研究人员在数据获取阶段付出巨大的人工努力,通过许多昂贵的转换和计算过程将其置于结构化和有组织的格式下。

大多数时候,在机器学习研究中建立概念证明(POCs)或观点(POV)时,感兴趣的现象将是检查商业想法或问题的可行性,以测试它是否可以使用最先进的算法来解决。在这种情况下,花费在数据转换和清理上的工作优先级较低,因为总体目标在于建模及其性能评估,以检查预测能力、主要业务可行性和假设。

为了节省时间和精力,研究人员通常会尝试编写一些程序,这些程序可以根据建模过程所需的概率分布、变量和统计数据来生成一些虚拟数据集。Python 已经推出了一个名为“Faker”的有效库,以帮助数据科学社区在短时间内毫不费力地自动完成创建虚拟数据集的过程。在本文中,我们可以了解 Faker 库的优势,以及数据科学家和机器学习工程师如何利用它来减少手动工作。

安装 Faker 库

faker 库的安装非常简单。我们只需要使用一行代码,就像我们通常安装任何其他 python 库一样。

pip install Faker

在安装过程之后,我们需要创建一个 Faker 类的对象。使用这个对象,我们可以生成我们需要的任何类型的虚拟数据。

from faker import Faker
fakeobject = Faker()

生成基本数据点(姓名、地址、职务、日期等。)

Faker 库提供了许多预定义的方法,通过这些方法我们可以生成属于各种类型信息的数据点,如年龄、地址、工作、日期等。让我们看一些基本的例子来熟悉这些方法

方法'名称'可用于生成一个虚拟名称-

fakeobject.name()

代码片段的输出(在 Jupyter 笔记本中有说明)

方法'和''可以用来生成一个虚拟的名和姓-

print(fakeobject.first_name())
print(fakeobject.last_name())

代码片段的输出(在 Jupyter 笔记本中有说明)

方法'地址可用于生成虚拟地址-

fakeobject.address()

代码片段的输出(在 Jupyter 笔记本中有说明)

方法'作业'可用于生成虚拟作业-

print(fakeobject.job())

代码片段的输出(在 Jupyter 笔记本中有说明)

方法'城市'可用于生成虚拟城市-

print(fakeobject.city())

代码片段的输出(在 Jupyter 笔记本中有说明)

方法'纬度'和'经度'可用于生成虚拟经纬度-

print(fakeobject.latitude(), fakeobject.longitude())

代码片段的输出(在 Jupyter 笔记本中有说明)

方法'文本'可用于生成虚拟文本。这种方法对于生成可用于任何类型的 NLP 实验的文本数据非常有用

print(fakeobject.text())

代码片段的输出(在 Jupyter 笔记本中有说明)

方法'可用于生成虚拟字-

#This statement generates a dummy word
print(f'single word: {fakeobject.word()}')#This statement genetaes a list of 5 dummy words
print(f'list of 5 words: {fakeobject.words(5)}')

代码片段的输出(在 Jupyter 笔记本中有说明)

除了随机生成单词之外,还可以定义一个预定义的单词列表,并从该列表中选择随机的唯一单词。以下代码片段包含一个预定义的 5 个单词的列表,Faker 库从中随机选择 3 个唯一的单词-

listofwords = ['laptop', 'technology', 'science', 'mathematics', 'space']
print(f'random unique words: {fakeobject.words(3, listofwords, True)}')

代码片段的输出(在 Jupyter 笔记本中有说明)

还有一系列方法可以生成一些伪数字-

print(f'Random int: {fakeobject.random_int()}')
print(f'Random int: {fakeobject.random_int(0, 10)}')
print(f'Random digit: {fakeobject.random_digit()}')

代码片段的输出(在 Jupyter 笔记本中有说明)

下面的代码片段由一些方法组成,这些方法可以生成一些与“日期和“时间”相关的虚拟信息-

print("Faker methods related to Date and Time")
print(f'Date of birth: {fakeobject.date_of_birth()}')
print(f'Year: {fakeobject.year()}')
print(f'Month: {fakeobject.month()}')
print(f'Month name: {fakeobject.month_name()}')
print(f'Day of week: {fakeobject.day_of_week()}')
print(f'Day of month: {fakeobject.day_of_month()}')
print(f'Time zone: {fakeobject.timezone()}')

代码片段的输出(在 Jupyter 笔记本中有说明)

生成虚拟轮廓

在上面的例子中,我们试图分别生成不同的数据点,如年龄、地址等。Faker 还提供了一种方法来生成一个人的虚拟个人资料,该资料将以组合格式包含所有上述信息。

profile1 = fakeobject.simple_profile()
profile2 = fakeobject.simple_profile('M')
profile3 = fakeobject.profile(sex='F')print(profile1)
print(profile2)
print(profile3)

代码片段的输出(在 Jupyter 笔记本中有说明)

生成唯一数据点

对于上述所有方法,当我们多次执行代码片段时,我们将得到不同的输出。因此,不能保证一个虚拟数据点是唯一的,当我们在循环中执行这些方法 1000 次时,很有可能最终生成重复的条目。为了克服这一挑战,Faker 提供了一种叫做“ unique 的方法,确保我们在上下文或循环中生成的每个数据点都是唯一的。

让我们看看这个方法的代码片段

names = [fakeobject.unique.name() for i in range(10)]
for i in range (0,len(names)):
  print(names[i])

代码片段的输出(在 Jupyter 笔记本中有说明)

在某些情况下,我们可能需要在程序的多个部分重新生成相同的数据点。可以使用 seed() 方法,给出一些 id 来唯一标识虚拟数据点,并在不同的上下文中重新生成它们。这种方法在其他各种 python 包中也非常流行。让我们用一个简单的例子来理解这个概念——

Faker.seed(10)
print(fakeobject.name())

这里,我在 seed 方法中提供了参数值“10”。在下一个编码语句中,我生成了一个假名。让我们检查一下上面代码语句的输出-

代码片段的输出(在 Jupyter 笔记本中有说明)

我们得到的输出是“杰西卡·莱恩”。

现在,让我们执行不包含种子方法的第二行代码-

print(fakeobject.name())

代码片段的输出(在 Jupyter 笔记本中有说明)

我们可以看到代码现在生成了一个不同的输出(“Robert Colon”)。但是如果我们想要重新生成之前的输出,我们可以通过使用相同的参数值来引用 seed 方法来执行相同的代码片段,如下所示

Faker.seed(10)
print(fakeobject.name())

代码片段的输出(在 Jupyter 笔记本中有说明)

这里,使用具有相同参数值(10)的种子方法,我们能够重新生成我们的旧虚拟名称(“Jessica Lane”)。

生成货币相关信息

Faker 提供了各种方法来生成与货币相关的信息。下面的代码片段可以生成一些信息,如货币名称,货币代码等。

print(f'currency: {fakeobject.currency()}')
print(f'currency name: {fakeobject.currency_name()}')
print(f'currency code: {fakeobject.currency_code()}')

代码片段的输出(在 Jupyter 笔记本中有说明)

对于加密货币可以生成相同的信息

print(f'currency name: {fakeobject.cryptocurrency_name()}')
print(f'currency code: {fakeobject.cryptocurrency()}')

代码片段的输出(在 Jupyter 笔记本中有说明)

生成哈希和 uuid

Faker 库还可以生成一些虚拟的“通用唯一标识符(UUID)”。UUIDs 是 128 位标签,用于在计算机系统中识别信息。用于实时生成 UUIDs 的一些散列算法是安全散列算法(sha)、消息摘要方法(md5)等。以下代码片段生成一些假散列和一个 UUID 值-

print(f'sha256: {fakeobject.sha256()}')
print(f'md5: {fakeobject.md5()}')

代码片段的输出(在 Jupyter 笔记本中有说明)

生成互联网相关数据

Faker 还提供生成与互联网相关的虚拟数据的方法,如电子邮件地址、域信息、互联网协议信息等。

print("Domain related information")
print(f'Host name: {fakeobject.hostname()}')
print(f'Domain name: {fakeobject.domain_name()}')
print(f'Domain word: {fakeobject.domain_word()}')
print(f'TLD: {fakeobject.tld()}')
print(*f*'URL: {fakeobject.url()}')
print("")print("Email related information")
print(f'Email: {fakeobject.email()}')
print(f'Safe email: {fakeobject.safe_email()}')
print(f'Free email: {fakeobject.free_email()}')
print(f'Company email: {fakeobject.company_email()}')
print("")print("Internet protocol related information")
print(f'IPv4: {fakeobject.ipv4()}')
print(f'IPv6: {fakeobject.ipv6()}')
print(f'MAC address: {fakeobject.mac_address()}')

代码片段的输出(在 Jupyter 笔记本中有说明)

生成 JSON 数据

Faker 还提供按照 JSON 格式生成对象的功能。可以通过生成一个单独的文件来存储数据。下面的代码片段生成两个随机雇员的详细信息,包括他们的雇员 Id、姓名、地址、工作和城市,最后生成一个单独的 JSON 文件,可以在其他任何地方使用。

#Import libraries
from faker import Faker
import json
from random import randint#Initilaiize the object
fakeobject = Faker()#Method to generate dummy details of the employees
def input_data(x):
    employee_data ={} for i in range(0, x):
      employee_data[i]={}
      employee_data[i]['Employee Id']= randint(1, 10)
      employee_data[i]['name']= fakeobject.name()
      employee_data[i]['address']= fakeobject.address()
      employee_data[i]['job']= fakeobject.job()
      employee_data[i]['city']= fakeobject.city()
      print(employee_data) #dictionary dumped as json in a json file
    with open('employee.json', 'w') as fp:
      json.dump(employee_data, fp)#defining the main method
def main():
    #variable to assign the number of employees
    number_of_employees = 2
    input_data(number_of_employees)#Invoking the main method
main()

输出文件将如下所示-

代码片段的输出(在 Jupyter 笔记本中有说明)

以多种语言生成数据点

Faker 提供了在某些地区生成虚拟数据的特定方法。库中使用的默认选项是英语地区。我们可以在实例化 Faker 类的一个对象时提供一个参数,以使用我们需要生成虚拟数据的特定区域设置。

以下代码片段生成了一个日语姓名列表-

from faker import Faker
fakeobject = Faker('ja_JP')
for i in range(1,6):
    print(i," ",fakeobject.name())

代码片段的输出(在 Jupyter 笔记本中有说明)

生成大型数据集

在前面的章节中,我们讨论了生成单个数据点的方法。但是我们需要 pandas 数据框架结构中的数据,该数据框架结构由任何类型的数据科学实验的多个数据点组成。使用 Faker 创建这样的数据框非常容易。以下代码片段生成一个虚拟数据帧,其中包含 5 个不同人员的个人资料信息-

from faker import Faker
import pandas as pd
fakeobject = Faker()
person_data = [fakeobject.profile() for i in range(5)]
dataframe = pd.DataFrame(person_data)
dataframe

代码片段的输出(在 Jupyter 笔记本中有说明)

python 中的类似库

虽然 Faker 目前正在成为数据科学家的首选,但也有其他结构良好且经过测试的库可以考虑作为 Faker 的替代品。有些是-

结论

在本文中,我们讨论了数据科学实验对虚拟数据的需求和使用,以及研究人员如何利用 Faker 库来获得优势。此外,我们学习了 Faker 库的各种方法和功能的各种实时编码示例。

下面的 URL 将所有的编程示例上传到 GitHub 库,这样你就可以根据自己的需求来玩代码了- URL

我希望现在你对 Faker 库有了直观的了解,这些概念将帮助你构建一些真正有价值的项目。

您可以通过以下平台与我联系-

  1. Quora
  2. 领英
  3. Gmail—sanjayjsw05@gmail.com

参考

  1. 官方文件
  2. Python 包 URL

爱上你的环境设置

原文:https://towardsdatascience.com/fall-in-love-with-your-environment-setup-779dfbf047ba

Python 开发人员关于协作、生产就绪性和时间节约的最佳设置指南

作者图片

注意:推荐工具的设置说明/有用命令可以在python-dev-setuprepo 中找到,整篇文章都会引用到

编码班背叛了我。我开始了我的第一个专业 Python 项目,但是我的机器上什么都没有设置好:

  • 我的 Windows 命令提示符与旨在简化项目设置的 BASH shell 脚本不兼容。
  • 我没有一个好的集成开发环境(IDE)来使用。py 而不是。ipynb 文件。
  • 当我尝试运行代码时,它很快出错,因为我的 Python 包版本与我的团队成员安装的版本不同。

我习惯于在从 Anaconda 和 pip 启动的 Jupyter 笔记本上运行代码,安装任何需要的软件包。真正开发的理想环境设置不是我学到的一课。

我手忙脚乱,拼命不让自己显得无能,因为我所受教育的一个关键部分被忽略了。

照片由JESHOOTS.COMUnsplash 上拍摄

事实是,在教育环境中,您可能知道很多关于 Python 编码的知识,但是如果您对环境设置一无所知,那么当您在生产环境中开始您的第一个项目时,您将会猛然醒悟

我说的“环境设置”到底是什么意思?

我的意思是拥有高效执行以下 5 项任务所需的所有工具:

  1. 从命令行运行脚本
  2. 对代码进行版本控制
  3. 编辑和调试您的代码
  4. 管理用于运行代码的 Python 版本
  5. 管理用于运行代码的 Python 包版本

为什么环境设置很重要?

有一个好的设置是至关重要的,原因有很多:

1.团队协作

布鲁克·卡吉尔Unsplash 拍摄的照片

当多人在同一个代码库上工作时,如果所有团队成员的环境设置不一致,就很难进行协作。如果一个团队成员使用不同版本的 python 或 python 包,当另一个团队成员尝试在他们的机器上运行代码时,在另一个团队成员的机器上运行的代码可能会中断。

2.生产准备就绪

布拉登·科拉姆在 Unsplash 拍摄的照片

这个问题超越了团队协作,延伸到了生产领域。如果生产环境与您开发的机器不同,代码可能会在部署后中断。在编程中,控制尽可能多的外部变量以使生产行为尽可能可预测是至关重要的。

3.节约时间

照片由 Aron 视觉效果Unsplash 上拍摄

当您第一次开始一个新项目或测试其他人的代码时,如果环境设置不简单,您可能会浪费大量时间来准备您的机器运行他们的代码。

而且浪费的时间不仅限于项目的开始——如果设置不标准化,开发人员将继续浪费时间来排除版本不兼容错误,而这些错误本来是可以很容易避免的。

我听到了,但是我需要做什么?

环境设置可能会令人困惑和复杂。我自己也在这个过程中挣扎过很多次。

用于完成环境设置的 5 个关键任务的各种选项(参见“环境设置”的确切含义是什么?以上章节)可能会让人不知所措。

为了节省您的时间、精力和挫折,我在下面列出了我认为最有帮助的工具(以及它们的关键特性)。我已经在不同的操作系统上测试了这些工具,以确保在任何操作系统下都能实现最佳设置。请继续阅读在您的机器上创建一个良好的环境设置所需的所有内容,并参考 python-dev-setup repo 获取安装说明/技巧!

1.从命令行运行脚本

推荐:Mac 用户用终端,Windows 用户用 WSL

当在集成系统中开发时,您将不得不抛弃笔记本,习惯于从命令行运行脚本/命令。Mac 的终端应用程序非常适合这一点,因为 Mac 有一个基于 Linux 的操作系统,并且由于其成本效益,大多数应用程序都部署到生产中的 Linux 机器上。

因为 Window 不是基于 Linux 的操作系统,所以可以用 WSL 建立一个 Linux 虚拟环境。参见 python-dev-setup repo 的设置 WSL 环境 部分的说明。

格式化您的命令行界面

无论您使用哪种命令行界面(CLI ),它都有助于将您的 CLI 格式化为与 Git 协同工作,以便您知道您正在处理哪个分支,并且不会意外地将代码提交到错误的分支。

作者图片

参见 python-dev-setup repo 的 Format Your Terminal 部分以获取说明。

2.对代码进行版本控制

推荐:Git

Git 是 Github 和 Bitbucket 背后的强大软件。它不仅有助于基本的版本控制,也是以下方面的关键:

  • 团队协作——在将代码推送到团队共享的远程代码库之前,您可以在本地机器上对代码进行更改/测试。此外,您可以在主分支之外创建分支,这样您的开发工作就不会影响团队的其他成员或生产中的代码。最后,当开发完成时,您可以很容易地将其他团队成员的分支合并到您自己的分支或主分支中。
  • 发布管理——分支系统也是发布管理的关键。根据项目需求的不同,不同的增强可能会有不同的时间表来决定何时将它们部署到生产环境中。通过将新特性隔离在单独的分支中,您可以轻松地独立部署每个特性。

有关 Git 的更多信息,请参见:什么是 Git,为什么要使用它?

要开始使用 Git:

  1. 安装 Git — MacWindows WSL(Ubuntu Linux)红帽 Linux
  2. 按照这些步骤设置您的 git 配置用户名和电子邮件
  3. 按照的步骤配置 SSH 验证,这样你就不需要每次拉/推你的 Github/Bitbucket repo 时都输入你的用户名/密码
  4. 参考这个有用的 git 命令列表
  5. 下载 archive_branch.sh 脚本,并将其添加到项目的根目录,以自动化归档非活动 git 分支的繁琐过程
  6. 下载 sync_git_branches.sh 脚本,并将其添加到项目的根目录,以自动提取/更新所有远程分支,并删除不再连接到远程 ref 的本地分支。

3.编辑和调试您的代码

推荐:VS 代码

虽然有很多 IDE,但对于本地代码编辑,Visual Studio Code (VS Code)是我最喜欢的编辑器(我也尝试过 Atom、PyCharm 和 Spyder)。我喜欢用于 Python 开发的 VS 代码,因为它具有跨嵌套文件跟踪函数/类定义的卓越能力。在 PyCharm 中,随着跟踪变得越来越复杂,这个特性将停止工作。

Gif 由作者使用https://www.onlineconverter.com/

VS 代码也有很好的源代码控制特性:

  1. 你可以很容易地在屏幕的左下方看到你正在查看的回购分支

作者图片

2.如果您跨多个回购协议工作(即,使用一个回购协议作为标准工具库,作为本地可编辑的包导入),您可以轻松查看回购协议的变更,而无需多次“cd”和“git status”。例如,如果您在下面的应用程序和工具库中都添加了脚本,您可以在 VS 代码的源代码控制选项卡中同时查看这些更改。

作者图片

此外,VS Code 的调试工具非常有用,只要你知道以下技巧:

  • 将您的 Python 解释器设置为您的项目根目录中的 venv 或您的 conda venv ( 注:我们稍后将详细讨论 venv)

作者图片:venv 在项目的根目录下

作者图片:conda venv

  • 选择要运行的 Python 文件
  • 通过单击左侧空白处设置断点(如果需要)
  • 导航到调试选项卡,为调试配置
    选择“Python 文件——调试当前活动的 Python 文件”注意:要使其工作,您的 VS 代码工作区必须对脚本要运行的目录开放。因此,最简单的方法是构建从项目根目录运行的脚本。

作者图片

  • 逐句通过代码并查看过程中创建的变量/数据。

作者图片

最后,当适合使用 Jupyter 笔记本文件时(例如测试代码片段),VS 代码有一个 Jupyter 扩展来支持它。您所需要做的就是将内核设置为项目根目录下的 venv 或 conda venv,并在出现提示时安装 ipykernel 包。

作者图片

作者图片

要开始使用 VS 代码:

  1. 安装 VS 代码和密钥扩展
  2. 使用带有 WSL 的 VS 代码(仅限 Windows 用户)
  3. 配置远程 SSH 编辑(只有在远程 Linux 机器上工作时才需要)

4.管理用于运行代码的 Python 版本

推荐:曼巴福吉

Mambaforge 是一个开源包管理器,允许你在特定版本的 Python 上无缝地创建一个虚拟环境。它支持大多数 conda 命令,但与 Anaconda 不同,它可以免费用于商业用途,并且比 miniconda 更轻。

要开始使用 Mambaforge:

  1. 安装曼巴福吉— MacWindows WSL/ Linux
  2. 参考这个有用的 mambaforge 命令列表

。bashprofile vs .bashrc

在 Linux 中,您可以使用 crontab 来调度作业。执行脚本的 Cron 作业使用非交互式 shell 登录,该登录从。bashrc 文件(不是。bash_profile 文件)。在安装说明中。bash_profile 已经更新,但是如果您将使用非交互式 shell 登录,请确保您也更新了您的。bashrc 文件相应。参见本文了解更多关于。bashrc vs .bash_profile。

5.管理用于运行代码的 Python 包版本

推荐:诗歌

创建 Python 虚拟环境对于依赖性管理至关重要。关于什么是虚拟环境以及为什么你应该总是使用虚拟环境的更多信息,请查看这篇文章

虽然从指定硬编码包版本的最新 requirements.txt 文件安装 pip 总比什么都没有好,但是这种方法无法考虑您的依赖项的依赖性。例如,你可能认为你只安装了 pandas 来运行你的代码,但是 pandas 库实际上依赖于另外 5 个包。

作者图片

在从 requirements.txt 创建虚拟环境时,您很容易出错,例如:

  • 您指定的 numpy 版本与您指定的 pandas 版本不兼容
  • 您指定的软件包版本的 numpy 版本与您的 pandas 版本所需的 numpy 版本不兼容

即使在从 requirements.txt 文件创建虚拟环境时没有错误,团队成员可能会以稍微不同的子依赖版本结束,这可能会导致问题。

考虑子依赖关系很容易让你晕头转向。令人欣慰的是,poems考虑到了所有这些相互关联的依赖关系,并创建了一个“poetry.lock”文件,您可以将它推送到您的 repo 中。所有你的队友需要做的镜像你的设置是运行“诗安装”命令。

是否存在锁文件实际上可能导致团队成员之间出现问题的情况?

是的,但这次是例外。例如,如果您的代码正在加载其他回购作为本地可编辑的包,您不会希望您的团队成员被锁定在您的空间的绝对路径中,在那里您可能正在子回购的不同 git 分支上工作。

如果您遇到这样的情况,在使用 pyenv 控制您的 Python 版本之后,您总是可以从具有硬编码版本的 requirements.txt 恢复到 pip 安装依赖项。

要开始学习诗歌:

  1. 装诗
  2. 使用诗歌将项目依赖关系安装到您的 conda 环境中
  3. 参考这些有用的诗歌命令

如果您按照本文中的说明进行操作…

照片由阿格涅什卡·博斯克Unsplash 拍摄

恭喜,您现在有了一个很棒的环境设置!

您拥有高效工作所需的所有工具:

  1. 从命令行运行脚本
  2. 对代码进行版本控制
  3. 编辑和调试您的代码
  4. 管理用于运行代码的 Python 版本
  5. 管理用于运行代码的 Python 包版本

我希望这有所帮助,你会发现自己在下次开始一个新项目时已经准备好了。

Python 开发人员的终极漫游指南

原文:https://towardsdatascience.com/fall-in-love-with-your-environment-setup-vagrant-edition-40ee9313291b

注:本文引用了 流浪汉-python-setup 回购

作者图片

什么是流浪?

vagger 是一个虚拟化工具,用于创建开发环境,可以在团队成员之间一致且轻松地重新生成。这一点很重要,因为团队成员可以在本地操作系统不可知的环境中工作,消除了特定于机器的设置问题。

更多信息,请参见:https://www.vagrantup.com/intro

流浪是怎么工作的?

travel 基于 travel file 中的规范构建一个 VM。此外,它会在 VM 中的“/vagger”下创建一个共享文件夹,该文件夹会自动同步项目目录中的文件。这意味着无需担心数据可访问性/持久性的装载/卷。

流浪档案是什么样子的?

从文件中删除信息性注释,可以简化为以下代码:

如您所见,所有的动作都发生在第 4–6 行(只有 3 行代码!).

  • 第 4 行指定要使用的 VirtualBox 基本映像。“hashicorp/bionic64”是在《流浪者入门教程》中使用的 Ubuntu 机器,所以为了简单起见,我想我还是坚持使用它。
  • 第 5 行将虚拟机上的端口 80 转发到本地端口 8000。这一点很重要,例如,当使用 flask 并访问托管在 VM 上的站点时。
  • 第 6 行运行 install.sh 脚本来配置虚拟机。
    • 注意: privileged 设置为 false,这样脚本就不会以 root 用户身份运行。如果安装脚本作为根用户运行,安装的东西,如诗歌,将无法访问的流浪者用户。
      -您仍然可以在安装脚本中需要根级别访问的特定命令前指定 sudo。

install.sh 脚本中发生了什么?

install.sh 一开始可能看起来有点让人不知所措,但它可以分解为 5 个关键部分:

第 1 部分(第 3–6 行):安装 Python 安装所需的 linux 包

第 2 部分(第 8-17 行):安装指定的 Python 版本

第 3 部分(第 19–26 行):安装并激活诗歌

第 4 部分(第 28 -41 行):终端格式

  • 将“auto_activate_.venv.txt”文件中定义的函数添加到。bashrc 文件来自动激活项目根目录下的 venv
  • 获取。bash_prompt 文件在。bashrc 文件并象征性地链接。bash_prompt 文件从 repo 复制到 VM 中的相关位置。这将把终端提示符转换为以“{用户名} {文件夹名} * {git branch} > >”格式显示
  • 在登录到虚拟机时,将一个条件添加到 cd 的/vagger 文件夹(与您的本地文件同步的文件夹)

第 5 部分(第 41-43 行):使用诗歌创作项目的 venv

  • poetry env use告诉 poem 使用我们安装的特定 Python 版本
  • poetry install安装锁文件中指定的依赖项
    • 注意:依赖项中指定的 ipykernel 包需要在 VS 代码的 Jupyter 笔记本中工作

流浪汉使用烧瓶的注意事项

如上所述,从本地机器上的浏览器访问托管在 VM 中的 flask 应用程序需要端口转发。在 vantage 中使用 Flask 时,您还需要了解一些规范:

  1. 你需要使用 sudo 运行 flask 应用程序,以获得访问 80 端口的权限:sudo python flask_test.py

作者图片

2.当您在本地机器的浏览器中输入 URL 时,请确保您指定了端口“8000 ”,而不是直接复制具有端口“80”的 URL,端口“80”是应用程序在 travang VM 中运行的端口

作者提供的图片:端口 80 的输出—连接到流浪虚拟机端口 80 的注释

图片来自作者:端口 8000 的输出—实际的烧瓶站点

流浪汉和码头工人有什么区别?

从高层次上来说,vagger 是用来打造开发空间的,Docker 是用来容器化生产代码的。

更多详情请见https://www . the server side . com/answer/Vagrant-vs-Docker-How-these-cloud-native-tools-different

流浪汉听起来不错——有什么好处?

配置一个 linux VM 来满足您的需求并不像一些文章看起来那么简单。我发现安装 Python3 需要不同的 linux 包,当我尝试使用 VS Code 的调试和笔记本功能时,我尝试的每种组合都会留下一些配置错误。

为了避免您浏览无数的故障排除文章,我在这里整合了我的研究,并提供了一个示例来创建一个镜像我喜欢的本地设置的环境设置。

按照下面的步骤,看看你如何保持无缝的本地环境设置与流浪者的感觉!

安装流浪汉

  • 注意:流浪者建议 Mac 用户不要使用自制软件进行安装

安装 VirtualBox

克隆流浪者-python-setup repo

  • git clone git@github.com:jillvillany/python-dev-setup.git
    -注 1:这里假设您已经在本地配置了 Git SSH 连接。如果您没有设置这个,请参见python-dev-setup repo
    Git: Configure SSH Auth 部分-注意 2:如果您使用指定了用户名的 git ssh 配置文件,url 应该修改如下:git clone git@github-{your username}:jillvillany/python-dev-setup.git

从流浪汉文件中指定的映像创建虚拟机

  • 这可以通过运行vagrant up非常简单地完成,大约需要 10 分钟
    ——注意:可能会出现一些常见错误——如果您遇到错误,请参见下面的“排除流浪错误”部分
  • 一旦创建了 VM,您将看到已经安装的诗歌需求(VM 配置中的最后一步)。

作者图片

疑难解答向上漫游错误

  1. Mac 安全设置阻止扩展

作者图片

如果你在 Mac 上,你可能会在第一次运行vagrant up时得到“执行 VBoxManage '时出错,这是一个由 vagger 用于控制 VirtualBox 的 CLI”错误。您必须按照本文[中的说明](https://scriptcrunch.com/solved-vboxmanage-error-component-machinewrap/)在您的安全设置中允许新的系统扩展,重启您的计算机并再次运行vagrant up`。

2.端口已被使用错误

作者图片

您必须找到在指定端口上运行的活动的 PID,并终止该活动。如果使用 Mac,请遵循本文中的进行说明。

作者图片

确保你的流浪者设置和你喜欢的本地环境设置一样无缝

在之前的一篇文章爱上你的环境设置中,我展示了我发现的对完成以下 5 个关键开发任务最有用的工具:

  1. 从命令行运行脚本
  2. 对代码进行版本控制
  3. 编辑和调试您的代码
  4. 管理用于运行代码的 Python 版本
  5. 管理用于运行代码的 Python 包版本

虽然大多数建议将保持不变,但有 3 个主要区别:

  1. Windows 和 Mac 用户使用的 shell 没有区别。您将使用您启动的 Linux 机器的 bash shell。
  2. 不用使用包管理器来控制您的 Python 版本,您可以只在 VM 中安装您需要的 Python 版本。使用包管理器会增加复杂性,并可能导致内存问题。
  3. 创建一个 Python venv 来安装诗歌需求(因为您不会为 Python 版本创建 venv)。

继续读下去,看看你如何能够无缝地执行上面提到的 5 个关键开发任务。

1.从命令行运行代码:Bash shell

  • vagrant ssh
  • 这将启动虚拟机的终端(它会自动 cd 到“/vagger”同步文件夹,并根据中的规范激活项目的 venv。bashrc 文件)

作者图片

  • 注意:如果您搞不清是在本地机器上还是在流浪的虚拟机上,请检查用户名(终端提示中的第一个变量)。在流浪者虚拟机中,用户名是“流浪者”,在你的机器上它将是你的名字。

作者图片

2.版本控制你的代码:Git

您的本地项目文件和存储在浮动虚拟机的“/vagger”中的文件是自然同步的,因此您可以从本地机器自动提交到 Git。然而,为了在 vagger VM 上获得真正无缝的体验,您可以在那里设置 Git SSH 连接。

因为您将是 VM 上的唯一用户,所以使用vagrant sshSSH 进入流浪 VM,并遵循 python-dev-setup repo配置 SSH 验证部分中的私有机器指令集。

  • 将您的 git 用户名和电子邮件添加到 git 配置中,这样您就可以在 VS 代码 UI
    -git config user.name {username}-
    -git config user.email {email}中使用 git

作者图片

3.编辑和调试您的代码:VS 代码

  • 通过 SSH 到 VS 代码中的流浪虚拟机,您可以无缝地在 VS 代码中工作
  • 前置请求:安装 VS 代码远程— SSH

作者图片

  • 如果仍在上一步的漫游虚拟机中,输入命令exit退出虚拟机

作者图片

  • 运行命令vagrant ssh-config并复制输出

作者图片

  • 在 VS 代码shift + cmd + p中打开命令面板,选择“Remote-SSH:Open SSH Configuration File”
  • 选择 ssh 主文件夹中的配置文件:
    ——例如,在 Mac 上:/Users/{username}/。ssh/config
  • 将浮动 ssh-config 粘贴到文件的底部,并将主机名从“default”更改为项目文件夹的名称

作者图片

  • 导航到左侧的 Remote Explorer 选项卡,并单击带有项目名称的主机旁边的新建文件夹图标

  • 注意:第一次远程访问 VS 代码时,需要花一些时间在浮动虚拟机中安装 VS 代码

作者图片

  • 新窗口加载后,在资源管理器中选择打开文件夹,并指定路径“/vagger”。然后,按 enter 键或单击确定。

  • 安装有用的扩展(即使它们安装在您的本地机器上),因为它们必须安装在 VM
    中的 VS 代码上——参见 python-dev-setup repo安装 VS 代码和关键扩展部分以获得您可能想要安装的扩展的完整列表
  • 注意:python 扩展是 python 林挺/调试/运行笔记本所必需的,所以你必须至少安装这个扩展

作者图片

  • 安装 Python 扩展后,当您打开 Python 文件时,您会看到您的诗歌 venv 被设置为项目的 Python 解释器

作者图片

  • 通过设置断点并选择“Python 文件”调试配置,像平常一样进行调试

作者图片

  • 以 test.py 文件为例:

作者图片

  • 选择诗歌 venv 作为你的内核来运行一个笔记本

作者图片

4.管理用于运行代码的 Python 版本:VM 中安装的 Python 版本

这是在 install.sh 脚本中的虚拟机供应期间处理的:)

5.管理用于运行代码的 Python 包版本:诗歌

这是在 install.sh 脚本中配置虚拟机的过程中处理的:)

我希望这有所帮助,你现在很高兴给流浪者一个尝试!

奇妙的激活功能以及何时使用它们

原文:https://towardsdatascience.com/fantastic-activation-functions-and-when-to-use-them-481fe2bb2bde

十大激活功能,它们的优缺点,何时使用它们,以及一个备忘单

作者图片

与权重和偏差一样,激励函数是 ML 模型中的一个重要组成部分。他们在使深度神经网络训练成为现实方面发挥了重要作用,并且他们是一个不断发展的研究领域。在这篇博文中,我们将它们进行对比,观察它们的优缺点,何时使用它们,以及它们的发展。

Paperswithcode 列出了 48 个激活函数,每年都有新的和改进的激活函数被提出。在本文中,我列出了 10 个最常见的激活函数,它们代表了所有其他的激活函数。

根据在 ML 模型中的使用方式,激活函数有两种类型。

  1. ML 模型的 输出层 中用到的激活函数(想想分类问题)。这些激活函数的主要目的是将值压缩在像 0 到 1 这样的有界范围内。
  2. 用于神经网络 隐层 的激活函数。这些激活函数的主要目的是提供非线性,没有非线性,神经网络就不能模拟非线性关系。

隐藏层中使用的激活函数应该理想地满足以下条件,

  1. 非线性, 让神经网络学习非线性关系。通用逼近定理陈述了使用非线性激活函数的两层神经网络可以逼近任何函数。
  2. 无界, 使学习更快,避免过早饱和。当范围无限时,基于梯度的学习是高效的。
  3. 连续可微,这个性质虽然不是决定性的,但却是可取的。ReLU 就是一个突出的例子,它的函数不可微≤ 0,但在实践中仍然表现很好。

备忘单

为没有耐心的人准备的文章的备忘稿,

作者图片

输出层激活功能

乙状结肠的

这些激活函数于 20 世纪 90 年代初推出,其优点是将输入压缩到 0 和 1 之间的值 ,从而完美地模拟概率。函数是可微的,但是 快速饱和 ,因为在深度神经网络中使用时,有界性导致 消失梯度 。指数计算的成本很高,当你必须训练一个有数百层和神经元的模型时,这种成本就会增加。**

函数界于 0 和 1 之间,第 e 导数界于-3 和 3 之间。 输出在零附近不对称 ,这将导致所有神经元在训练期间采用相同的符号,使其不适合训练隐藏层。

聪明的老乙状结肠。作者图片

****用途:一般用于 logistic 回归,输出层的 二元分类模型

Softmax

利用 0 和 1 之间的输出范围扩展 sigmoid 激活功能。这主要用于多类、多项分类问题的输出层,具有一个有用的属性 输出概率的总和等于 1 。换句话说,这是将 sigmoid 应用于输出上的每个神经元,然后将其归一化为和 1。

功利的 softmax。作者图片

用途: 多项多类 分类。

双曲正切

在 20 世纪 90-2000 年代广泛使用,它通过 扩展范围以包括-1 到 1 克服了 sigmoid 激活功能的缺点。这导致 零居中 ,这导致隐藏层的权重的平均值接近零。这导致更容易和更快的学习。这个函数是 可微的和 平滑的,但是使用指数函数要付出 的代价 。当用于深层神经网络的隐藏层时,它很快饱和,消失梯度渗透进来。导数比 sigmoid 的更陡。

值得信赖的 tanh。作者图片

****用途:可用于 RNN 的隐藏图层。但是有更好的选择,比如 ReLU

虽然 sigmoid 和 tanh 函数可以用在隐藏层中,但由于其正有界性,训练很快饱和,并且消失的梯度使得不可能在深度神经网络设置中使用它们。

隐藏层激活功能

输入 ReLU

整流线性单元是激活功能的。这是最广泛使用的和大多数类型问题的 goto 激活功能。从 2010 年左右开始,一直 广泛研究 。负的时候有界到 0,正的时候无界。这种 有界和无界的混合创建了一个内置的正则化 ,这对于深度神经网络来说很方便。正则化提供了一种 稀疏表示 ,导致计算上高效的训练和推断。**

正无界 加速梯度下降 的收敛,同时保持 计算简单 的计算。ReLU 唯一的主要缺点是神经元死亡。由于对 0 的负有界性,在训练过程中早期被关闭的一些 死亡神经元 永远不会被打开。函数从 x >为 0 时的无界快速切换到 x ≤ 0 时的有界,使其 连续不可微 。但在现实中,由于学习率低和负偏差大,这可以被克服,而不会对性能产生任何残余影响。

摇滚明星 ReLU。图片卜作者

用途: CNN 的,RNN 的,以及其他深度神经网络。

ReLU 是隐藏层激活功能的明显赢家。自 2010 年以来,人们一直在研究 ReLU 的优缺点,并提出了新的激活函数,这些函数有助于提高 ReLU 的性能,同时解决其困难。

对 ReLU 的改进

泄漏 ReLU

2011 年引入,通过 允许负值 存在,直接解决了 ReLU 的担忧。这使得负值能够反向传播,从而 克服 ReLU 的死神经元问题 。负值被积极地缩放,这导致较慢的训练。即使有了这种改进,Leaky ReLU 也不是普遍比 ReLU 更好。

泄漏的 ReLU 。作者图片

****用途:涉及稀疏渐变的任务像

参数 ReLU

这改进了 Leaky ReLU,其中标量倍数不是任意选择的,而是根据数据训练的。这是一把双刃剑,因为来自数据的训练导致模型对缩放参数(a)敏感,并且对于不同的 a 值表现不同。

可训练的参数 ReLU。图片作者。

****用途:可用于 修复 Leaky ReLU 不起作用时的死神经元 问题。

ELU

指数线性单位,2015 年推出,正无界,使用 对数曲线表示负值 。这是一个稍微不同的处理死神经元问题的方法,不像 Leaky 和 Parameter ReLU。与 ReLU 不同的是,负值会慢慢变平滑并变得有界,从而避免死神经元。但是负斜率使用指数函数建模,这使得 成本 。当采用次优初始化策略时,指数函数有时会导致 爆炸梯度

昂贵的 ELU 。图片作者。

格鲁

高斯误差线性单元,2018 年推出,是该模块中的新成员,显然是 NLP 相关任务 的 赢家。它用于 SOTA 算法,如 GPT-3、BERT 和其他基于变压器的架构。GeLU 结合了(对稀疏网络随机清零神经元) zone out (保持先前值),以及 ReLU。它 通过百分点而不是门 对输入进行加权,从而产生更平滑版本的 ReLU。**

新潮的葛鲁。图片作者。

用途:自然语言处理、计算机视觉和语音识别

嗖嗖

2017 年推出。大的负值将具有 0 的导数,而 小的负值仍然与捕捉潜在模式 相关。可作为 ReLU 的替代产品。导数有一个有趣的形状。

谷歌嗖嗖。图片作者。

用途:在图像分类和机器翻译方面匹配或优于 ReLU。

更多小抄,
https://github.com/adiamaan92/mlnotes_handwritten

关于作者:

我是一名数据科学家,在🛢️石油和⛽.天然气公司工作如果你喜欢我的内容,请关注我👍🏽在 LinkedInMediumGitHub 上。订阅,每当我在媒体上发帖时都会收到提醒。

幻想故事提示生成器

原文:https://towardsdatascience.com/fantasy-story-prompt-generator-2f56bf98dbfa

充分利用 Python 的“随机”库

塞德里克·范登堡在 Unsplash 上拍摄的照片

白天,我是一名数据分析师。我编写 SQL 脚本来生成非常具体的报告和审计。我完全按照客户的要求构建仪表板。我遵守规则,而且做得很好。

不过,我也有创意的一面。作为一名自出版作家和自由撰稿人,我喜欢在业余时间发挥自己的想象力。

例如,今年,我开始了我的第一份奇幻小说时事通讯,你可以在这里免费注册。

无论如何,我觉得人们通常要么善于分析,要么富有创造力,但我想挑战这种思维模式。

在下面的项目中,我结合了我的 python 知识和对小说的热爱,创建了一个随机幻想故事提示生成器。此外,我还尝试重新制作了一个我喜欢的游戏——故事方块。

虽然这个过程花了我不少时间,但现在初稿已经完成,我意识到实际上只有四个步骤:

  1. 导入随机库
  2. 创建一个循环
  3. 构建您的选项/路径
  4. 相应地随机选择

我将详细介绍每一个步骤。

首先,您只需要导入适当的库。你的整个项目都将以此为基础。

import random

下一步只是设置循环,以便用户可以选择提示。我定义了一个函数 Prompt(),然后构建了基本的循环。可以在下面找到相关代码:

def Prompt():
    while True:
        # We put this here, so that the user can chose to generate another prompt or quit.
        action = input("\033[1m "+ "Press 'Enter' to generate prompts, or press 'q' to quit " + "\033[0m \n"
                      + "\n"
                      +"\n").strip()if action.lower() == "q":
            break

这是基本模板。之后,我决定我要产生什么样的故事,这需要更多的创造力。在我的第一轮中,我列出了角色的类型和他们要走的路。

adjective=["An old", "A young", "A troubled", "A wise", "An injured", "A dying", "A sick", "A persuasive", "A clever"]characters=["wizard", "sorcerer", "elf",  "dwarf", "mage", "witch", "hobbit", "bard", "knight", "barbarian", "goblin", "centaur", "giant" , "fairy",  "dragon"]actiona=["finds ",  "discovers ", "searches for ", "tracks down "]
actionb=["protects ", "saves ", "loves "]
actionc=["fights ", "destroys "]
actiond=["travels to ", "runs from ", "escapes "]objecta=["a ring ", "a treasure ", "magic ", "a secret ", "a book ", "their destiny "]
objectb=["their friend ","their leader ", "their family ", "their home ", " their powers " ]
objectc=["a monster ", "a demon ", "the enemy ", "dark magic ", "a troll "]
objectd=["their home ", "another world ", "a prison ", "the castle "]

如你所见,有 15 个角色选项,然后我根据一组随机的动作和物体创建了四条路径。

接下来,为了让用户有所思考,我让提示保持开放:

##path  a,c,d
prep1=["but loses...", "but fails to find...", "but doesn't realize..." , "and is surprised to learn..."]
##path b
prep2=["but finds...", "and discovers..", "but discovers...", "and finds...", "but loses..."]

然后,我根据我提供的选项生成路径。

patha=random.choice(actiona) + random.choice(objecta)  + random.choice(prep1)
        pathb=random.choice(actionb) + random.choice(objectb) + random.choice(prep2)
        pathc=random.choice(actionc) + random.choice(objectc) + random.choice(prep1)
        pathd=random.choice(actiond) + random.choice(objectd) + random.choice(prep1)

        paths=[patha, pathb, pathc, pathd]

最后一部分是打印最终的故事提示。我还使用加粗和换行符使输出更容易阅读。

print("\033[1m  Story Prompt: \033[0m " +random.choice(adjective), random.choice(characters), random.choice(paths) + '\n'  )

最后,我只需要调用我的函数。

Prompt()

作为用户,一旦你运行单元格,它会给你一个输入框

作者输出的屏幕截图

然后你可以决定按下回车键产生一个提示或按下' q '然后回车退出程序。

这就是你得到的:

作者的代码和输出截图

很酷,对吧?

当我正忙着的时候,我决定尝试重新创建一个我自己的游戏,用来产生故事想法。它叫做罗里的故事方块。基本上,有九个骰子,你滚动它们来得到提示你的故事的图片。

为了重现这一点,我随机掷出四个骰子,每个掷出一个单词。我还生成了流派、人物、年龄和时间/背景。以下是完整的代码:

import random def StoryCubes():
    while True:

        action = input("Press 'Enter' to generate prompts, or press 'q' to quit ").strip()if action.lower() == "q":
            break

        character=["human", "animal", "monster", "hero", "villian"]
        time=["Past", "Present", "Future"]
        genre=["fantasy", "horror", "thriller",  "fairytale", "sci-fi", "mystery", "poetry"]
        d1 = ["spaceship", "turtle", "running", "wall", "Earth", "New York", "spark", "castle", "bear", "monster", "book", "television"]
        d2=["car", "street", "hole", "light", "power", "tall", "music", "fight", "ocean", "mountains", "wall", "swim"]
        d3=["house", "beach", "school" , "walk", "trip", "stairs", "sneak", "sleep", "eat", "drink", "food", "desert"]
        d4=["toy", "dog", "cat", "produce", "dry", "sound", "fire", "princess", "frog", "monster", "capture", "escape"]

        print("\033[1m Genre: \033[0m ", random.choice(genre))
        print("\033[1m Character: \033[0m ", random.choice(character) )
        print("\033[1m Character's Age: \033[0m ", random.choice(range(10, 55)))
        print("\033[1m When:\033[0m ", random.choice(time))
        print("\033[1m  Prompt 1: \033[0m ", random.choice(d1))
        print("\033[1m  Prompt 2: \033[0m ", random.choice(d2))
        print( "\033[1m  Prompt 3: \033[0m " ,random.choice(d3))
        print("\033[1m  Prompt 4: \033[0m " ,random.choice(d4))

正如你所看到的,它与上面的故事提示生成器是相同的基本模板,但这个模板旨在给用户更多的自由,但只是使用随机单词来提示想法。

当我调用 StoryCubes()并按 enter 键时,我得到了下面的输出:

作者输出的 StoryCubes()

结论:

这个项目对我来说很有趣,因为我有机会尝试以不同的方式使用随机库。也有一个名为 Wonderwords 的库可以用于此。然而,我发现它有点小故障,我更喜欢自己编码选项。

下一步,我想为每种风格建立不同的提示生成器,并可能扩展选项。

我也在考虑随机选择图片/图像来配合提示。为此,我考虑使用 Unsplash 的 API

我希望这篇教程对那些像我一样也有创造性的数据科学家和技术专家有所帮助。

点击这里查看 github 上的基本笔记本:https://github . com/meag VO/towards data science/blob/main/Story % 20 cubes . ipynb

编码快乐,写作快乐!

用于机器学习的快速简单的数据探索

原文:https://towardsdatascience.com/fast-and-easy-data-exploration-for-machine-learning-3fbee7d9c16b

开源库 Sweetviz 是一种方式

乌尤尼盐沼的贾戈达(图片由作者提供)

厌倦了在训练机器学习模型之前花费“太多时间”进行数据探索?

在开始训练您的 ML 模型的有趣部分之前,您是否在寻找一种更快理解数据问题和模式的方法?

想学习如何通过发现和修复数据中的问题来训练更好的 ML 模型吗?

你来对地方了。

在这篇文章中,你将学习如何以光速进行数据探索

让我们来看一个你可以在 这个 GitHub 库 中找到的实际例子和代码。

问题是

你需要在每个现实世界的 ML 项目开始时生成你的训练数据。

通常,您访问一个 SQL 类型的数据库,并编写一个很长的查询,从几个表中提取数据,对其进行聚合,并将其合并到最终的训练集中。数据集包含一组要素和一个要预测的目标度量。

生成训练数据集的问题? 如果您在这一阶段陷入困境,我推荐您阅读我以前的文章关于使用 SQL 和 Python 生成数据集的最佳实践👇🏼

一旦你有了这些数据,你就非常想训练你的第一个 ML 模型。

这是一个大错误。

相反,您应该留出几分钟时间来进行数据探索。

但是,为什么我需要数据探索?

因为,改善结果的最有效的方法不是通过尝试更复杂的模型,或者通过调整超参数(真实世界的 ML!= Kaggle)。

相反,您应该专注于提高数据的质量。你可以通过数据探索来做到这一点。

浏览数据集时,您需要特别注意:

  • 数据漏洞。有没有什么奇怪的事情,可能显示数据中的错误?
  • 缺失数据。每个特征的缺失观测值的百分比是多少?
  • 数据泄露。有没有看起来极具预测性,而且“好得难以置信”的特征?

那么问题是…

有没有一种 快速 的方式来探索一个数据集?

是的,有。

它的名字叫 Sweetviz ,一个你会爱上的开源库。

让我们来看一个实际的例子和我为 ML 项目开发的 Python 脚本。

我呈现的所有源代码都可以在 这个 GitHub 资源库 中公开获得。你可以在下一个 ML 项目中随意使用它。

例子

假设您在一家电信公司(又名 Telco)担任数据科学家。

电信公司面临的一个常见问题是高客户流失率。这一领域的竞争非常激烈,这意味着客户通常会从竞争对手那里找到更有吸引力的交易,所以他们会转向其他行业。

为了减轻这种情况,营销团队向您提出了一个想法:

“你能开发一个模型来预测客户流失吗?”

有了这种模式,他们可以采取预防措施,比如向即将流失的客户发送特别优惠,并留住他们。

那听起来像一个计划。

第一步。生成训练数据

你回到你的笔记本电脑,做你在每个现实世界的 ML 项目中需要做的第一件事:你生成训练集。您可以在此处 找到我在本例中使用的确切数据集

每个客户端在数据集中都有一行,每一列都有一些分类和数字特征,加上您想要预测的二元目标Churn,它取值:

  • Churn = "Yes"意为顾客翻炒。
  • Churn = "No"表示客户没有流失。

您从数据库中提取的功能如下:

除了这些的原始特性,你还可以设计一些其他特性,比如monthdayOfMonthdayOfWeekhour,来捕捉流失率的时间模式。

总而言之,这是您最终拥有的一整套功能(原始+工程):

尽管您很想进入建模部分,但您(明智地)留出了一些时间来仔细查看数据集。

第二步。数据探索

现在您已经有了数据,可以开始研究它了。

为此,您可以使用我的 GitHub repo 中的EDA . py脚本。它使用 Sweetviz,这是一个开源库,可以在几秒钟内生成数据探索报告。

要浏览数据集,只需从命令行调用该文件,作为参数传递:

  • 您想要浏览的数据集,v1.csv
  • 目标变量的名称,Churn
$ python eda.py --file v1.csv --target Churn

几秒钟后,Sweetviz 函数analyze()为您生成了一个漂亮的 HTML 报告。

Sweetviz 报告(图片由作者提供)

问题 1。数据错误

如果你观察时间特征dayOfWeekmonthdayOfMonthhour,你会发现它们的分布非常不均衡。

时间特征(图片由作者提供)

比如,90%以上的观测值,dayOfWeek1(表示星期二)。

dayOfWeek 专题(图片由作者提供)

这看起来很奇怪,所以你去问团队中的数据工程师 Mark。

"嘿,马克!我们 90%的客户流失事件怎么可能发生在周二?

他回应道:

那一定是在流失 *date* 字段中的 bug。几周前,我不得不重新处理该表,我想我一定是用更新表中记录的日期覆盖了实际的客户流失日期。

这正是这里正在发生的事情。如果你看看其他时间特征,你会很快意识到马克在 2022 年 2 月 1 日覆盖了 90%的date记录。

您发现了一个数据错误,这个错误可以被修复,这将帮助您构建一个更强大的模型。干得好!

问题二。缺失数据

真实世界的数据集可能会受到缺失数据的困扰。有时,你不能做太多的补救。然而,通常情况下,丢失的数据可以由您的数据工程师朋友 Mark 在上游解决。

从 Sweetviz 报告中,您可以清楚地看到tenureChurn有很强的负相关性。太好了,这意味着tenure是一个预测功能。

唯一的问题是 20%的样本没有tenure

任期特征(图片由作者提供)

如果您使用数据来训练您的模型,您必须:

  • 用样本中值估算这 20%的缺失值
  • 或者干脆从我们的培训数据中去掉这 20%的客户。

无论哪种方式,您的模型结果都将比您试图在上游解决数据质量问题的结果更差。所以你去问马克:

"我们有所有客户的 *tenure* 数据吗?我这么问是因为我在客户流失预测项目的训练集中缺少很多数据。”

马克惊讶地看着你,说道:

我们有所有客户的数据。我敢打赌,你为生成训练数据而编写的 SQL 查询中有一个错误

事实证明马克是 100%正确的。

您修复了查询,缺失的tenure值的百分比变为 0。超级棒。

问题三。数据泄露

您研究数据以了解哪些特征显示与Churn高度相关。有时候,你会碰巧发现看起来好得不像真的的特征。

例如,activity是一个分类特征,有两个可能的值:

  • activity = "active"表示客户在流失率前两周使用了他们的手机。
  • activity = "inactive"否则。

如果你看一下 Sweetviz 的报告,你会发现它与Churn有极大的相关性。特别是,所有的用户都没有流失…这似乎太好了,难以置信🤨

活动特征看起来好得不像真的(图片由作者提供)

而你恰好是对的:activity是一个用户级的特性,每天都会更新,所以它反映的是你生成训练数据时用户的状态,而不是流失事件发生前的时间段。****

因此,activity不是一个可以用来训练模型的特性,因为它使用的是未来的信息。

这就是我们所说的数据泄露,也就是你认为你可以用来训练你的模型的一段数据,但是你不应该,因为在推理的时候你不会拥有它。

数据泄漏产生了 ML 模型,当你训练它们时,它们似乎工作得非常好,但当你部署它们时,它们却悲惨地失败了。

包装它

数据探索是发现您的 ML 项目中 3 大阻碍因素的唯一方法:

  • 数据错误
  • 缺失数据
  • 数据泄露

请随意使用我在这篇文章中分享的脚本,并在您的下一个 ML 项目中为您自己节省一些时间(和头痛)。

你可以在 本回购 中找到所有代码。

🔔提交人与 Sweetviz 没有任何关系🔔

想支持我吗?

你喜欢阅读和学习现实世界中的 ML、数据科学和自由职业吗?

无限制地访问我在 Medium 上发布的所有内容,并支持我的写作。

👉🏽今天使用我的 推荐链接 成为会员。

**https://pau-labarta-bajo.medium.com/membership

👉🏽订阅 datamachines 简讯

👉🏽关注我 TwitterLinkedIn

祝你愉快🤗

避寒胜地**

用 Python 实现图像中的快速异常检测

原文:https://towardsdatascience.com/fast-anomaly-detection-with-images-f612a6a897ca

我如何将速度提高 10 倍

照片由萨夫Unsplash 上拍摄

最近,我一直在为工作中的一个项目开发一个异常检测模型。我需要将我的代码速度提高 10 倍。

在这篇文章中,我将描述我是如何实现这个目标的,以及在这个过程中我遇到的一些挑战。

粗略地说,异常检测技术试图识别数据中不符合典型行为的模式。这可用于识别系统中的问题、欺诈行为或其他异常活动。在我的案例中,我们需要从视频图像中实时识别异常情况。

典型的方法是从无异常的图像中构建参考概率分布,并计算新图像和参考分布之间的距离,以找出我们是否面临异常值。

这种方法的问题是,我们假设参考分布不会随时间而改变。此外,我们还需要获得涵盖所有可能结果的整个数值范围的数据,这些数据没有出现异常。

幸运的是,有一种方法可以解决这个问题:创建一个滑动窗口并使用无监督的异常检测方法。

在我们的例子中,我们可以从相机拍摄的最后 200 张照片中创建一个参考分布,并将这个分布与新输入的照片进行比较。

但是这种方法有一个主要问题:

每次更新滑动窗口都需要训练算法。

这意味着算法应该很快,并且我们从图片中提取的特征向量应该很小——在我们的情况下只有 10 维——如果我们希望有机会在边缘设备上花费不超过几毫秒的时间来训练模型。

小波分解

小波是一种信号处理技术,可用于将信号分解成不同的频率分量。通过将图像分解成不同的频带,它可以用于图像处理。

为了让开始学习 Python 中的小波变换,我们可以使用一个名为py wavelet的库。

小波也可以用来压缩图像,通过识别和删除不必要的细节。通过这样做,小波压缩可以在不影响质量的情况下产生更小的文件。此外,小波可以用于各种其他任务,如去模糊、去噪和边缘检测。

我们不需要小波分解来发现图像中的异常,但这种技术可以在行业中使用,主要有两个原因:

  • 压缩图像以节省数据库空间并加快文件在网络上的传输,以及
  • 根据关键特征在图像中的出现频率和方向,分离出关键特征。

经验 1:通过从小波分解本身提取特征,你可以赢得一些宝贵的毫秒。这样,我们就不需要将图片重新组合回它的初始形式。

例如,下图显示了第一级分解:

  • 左上方是低分辨率图像,
  • 右上角的垂直细节,
  • 左下角的水平细节,以及
  • 右下角的对角线细节。

具有一个分解级别的小波变换示例(原始照片由萨夫Unsplash 上拍摄)

我们可以有几个分解步骤。为了便于说明,第二个分解步骤如下图所示:

具有两个分解级别的小波变换示例(原始照片由萨夫Unsplash 上拍摄)

当寻找异常时,边缘通常是提取的好特征。这些信息大多可以从水平和垂直的细节中获得。

经验之二:对于边缘检测,对角线细节主要是噪声。

为了提取边缘,我们遵循“低冗余小波熵边缘检测算法”中提出的方法[1]如下所示:

  1. 对于每个级别的分解,将水平和垂直分量组合在一起并进行归一化。例如,对于第一级分解,我们将通过对右上图像和左下图像求和来创建新的图片。
  2. 使用最小-最大归一化将新创建的图片从 0 归一化到 1。
  3. 选择最有结构的分解层次。这被认为是具有最低香农熵的水平(甚至有一个 scikit 模块来计算它)。这样,我们可以选择与我们的目的最相关的信息级别,避免在其他级别的冗余信息上浪费时间。

经验之三:分解步骤之间有冗余信息,所以我们只需要从其中一个步骤中提取特征。

特征描述符

中的特征描述符是图像或视频的表示,可用于对象检测和分类等任务。有许多不同类型的特征描述符,但它们都旨在以紧凑的方式捕捉图像或视频的重要特征。

常用的描述符包括梯度方向直方图(HOG)、亮度直方图(HIST)和尺度不变特征变换(SIFT)。

每种类型的描述符都有自己的优点和缺点,为特定的应用程序选择正确的描述符至关重要。然而,一般来说,所有特征描述符的目标是以有利于机器学习的方式来表示图像或视频。

在我们的例子中,我们使用了 HOG 描述符,但是它对于实时检测异常有两个缺点:

  • HOG 描述符维数太高,并且
  • 计算太慢了。

对于实时处理,我们需要一些东西:

  • 快速提取,
  • 低维,以及
  • 这在异常情况下变化很大。

在我们的具体项目中,如果出现异常,物体的位置和形状都会改变。这意味着我们只需要建立一个反映物体形状的特征向量。

图像时刻足以反映这些变化。

我们发现,具有面积(灰度级之和)、质心坐标(对象的中心点)和二阶矩(方差)的简单特征向量已经足以检测大多数可能的异常。

经验之四:一个简单的特征提取器比一个特别为一个项目设计的奇特的特征提取器更有效。

Python 中的实时异常检测

异常检测是识别数据中异常行为或事件的过程。它是许多系统的重要组成部分,从安全和欺诈检测到医疗保健和制造业。

实时异常检测是一个特别困难的问题,因为它需要近乎即时地识别异常,这在处理图像等高维数据时更具挑战性。

我喜欢用两个库来进行异常检测:

  • 第一个叫 PyOD。这是一个 Python 工具包,用于实现无监督的异常检测算法,并且
  • 第二种称为 PySAD——可以与 PyOD 结合使用——用于检测流数据中的异常。

B 这两个库都是开源的、轻量级的、易于安装的。

棘手的部分不是实现算法——就像 PyOD 为我们做的那样——而是选择正确的算法。

在我们的例子中,我们首先使用一种叫做隔离森林 (iForest)的算法,但是切换到另一种叫做基于直方图的异常值得分 (HBOS)的方法显著提高了速度,同时几乎保持了相同的准确性。

我们还幸运地发现,他们刚刚发布了一篇名为“ADBench:异常检测基准测试”[2]的论文,以一种非常全面的方式对他们所有的异常检测算法进行了基准测试。

经验之五:当选择一个更简单的算法时,你不一定会损失很多精度,但是速度的提高是显著的。

结论

因此,如果您正在寻找一种快速有效的方法来从图像中提取特征,小波分解结合图像矩等简单的度量可能是一个很好的选择。虽然有更复杂的特征提取算法,有时一个简单的方法就是你所需要的。

我们已经看到,从小波分解中提取特征有利于边缘检测,但对角线细节主要是噪声。此外,我们发现分解步骤之间存在冗余信息,因此特征提取器可以仅基于一个分解步骤。优选地是具有较低熵的级别,因为它是图像内具有更多边缘结构的级别。

最后,我们发现一个简单的特征提取器比一个专门为我们的项目构建的奇特的特征提取器更有效。我们还发现,当选择更简单的算法时,您不一定会损失准确性,但速度增益可能是显著的。

好奇想了解更多关于 Anthony 的工作和项目吗?在媒体LinkedInTwitter 上关注他。

需要技术写手?将您的请求发送到https://amigo CCI . io

[1]:陶,易婷,等,“一种低冗余度小波熵边缘检测算法”影像杂志 7.9 (2021): 188。

[2]:韩,,等. ADBench:异常检测基准

显微组织分析的快速傅立叶变换

原文:https://towardsdatascience.com/fast-fourier-transforms-for-microstructural-analysis-9663ddfa9931

用快速傅立叶变换分析微观结构特征

马太·亨利Unsplash 上拍照

背景

这个宇宙中所有的能量都具有粒子-波双重特性。傅立叶级数和傅立叶变换是广泛使用的数学运算,它们分解来自不同能量的波信号以提取有价值的数据。在解决一个关于热传导的问题时,法国数学家约瑟夫·傅立叶分析了热波的正弦分量,这导致了傅立叶级数和傅立叶分析的发展。

虽然这些数学运算主要用于处理电磁辐射,如无线电、音频和电信号,但它们也广泛应用于图像处理以收集信息。电磁辐射产生的信号与时间相关,而图像产生的信号与空间相关。

在这里,我将讨论为什么和如何傅立叶变换是有助于解释图像。作为一名材料科学家,我将特别强调这一工具在材料表征方面的优势。

为了便于理解这篇文章,我将从傅立叶级数和傅立叶变换的简要概述开始。

傅立叶级数、傅立叶变换和快速傅立叶变换(FFT)简介

一个 傅立叶级数 是一个,它将一个周期函数表示为正弦余弦波的和。这是描述这个数列的方程式。

作者图片:傅立叶系列

周期性函数以规则的间隔重复,称为时间周期周期。例如,下面的函数 f(x)以 2π的规则间隔重复自身:

f(x) = sin(x)

频率是周期的倒数。

傅立叶变换操作将时域的信号变换到频域或将空间域的信号变换到空间频域(也称为倒易空间)并由以下等式表示。

F(k)是频率 k 的函数;j 是虚数√-1。由于频率和时间(或空间坐标)变量是从-∞到+∞变化的连续值,上述等式表示连续傅里叶变换。此外,我们还可以对离散点/样本应用变换算子,该操作称为离散傅立叶变换(DFT)。 DFT 变换连续积分(方程式。2)变成一个离散的和:

对 N 个点或样本的总和的评估涉及与 O(N)成比例的计算复杂度,其中 O 表示复杂度的阶。 Cooley 和 Tukey 在 1965 年实现了分治算法(O(NlogN))来加速和(Eq。3).库利-图基算法是 FFT 的第一个实现。麻省理工学院的 Frigo 和 Johnson 进一步发展了 FFT 算法,并创造了在世界范围内广泛使用的 FFTW (西方最快的傅立叶变换)。(注意: pyFFTW 是 FFTW 周围的 pythonic 包装器)。

现在让我们了解如何使用 FFT 来分析数字图像。

数字图像中 FFT 的相关性

一幅数字图像由称为像素的基本单元组成,每个像素被赋予一个在 0 到 255 之间变化的特定亮度值。图像的空间域包含关于真实空间中的像素强度和像素坐标的信息。

现在让我们使用 NumPy 从 2D 周期函数 f(x,y) = sin(2πx +3πy)生成一个图像,如下所示。

图片作者:2D 由周期函数生成的图像:f(x,y) = sin(2πx +3πy)

图像的相应 3D 表示完美地捕捉了波动特征,从而证明了对图像的傅立叶变换操作是正确的。因此,通过傅立叶变换处理图像信号可以为科学家和工程师挖掘隐藏的但重要的数据。

作者提供的图像:上面图像的 3D 显示,展示了波浪的性质

点击 此处 了解 Python 中的函数生成图像。

用于微结构加工的 FFT

在材料科学中,显微照片是用来探索和挖掘最终会影响材料性能的数据的图像。

现在让我演示一个图像(显微照片)处理过程,使用傅立叶滤波器来检索微结构特征的精确边缘。我考虑了一个散焦图像(如下所示),显示边缘无法准确识别的圆形颗粒。

作者图片:散焦显微照片

我用过 NumPy 的 FFT 库,写图像处理的代码。(可以使用 pyFFTW,比较相对执行时间。pyFFTW 什么时候打败 numpy.fft?)

在这里,我写下了将 FFT 应用于上图的主要步骤:

‣我使用了 imread 将图像的 jpg 文件转换成一个矩阵 (A),它的元素存储了关于每个像素的信息(它的坐标和强度)。

实空间到傅立叶空间的变换:我将 np.fft.fft2 函数应用于图像矩阵 a,以将其从实(空间)域变换到频域,随后将偏离中心的零频率分量移回到中心。代码输出如下所示👇:

代码输出:将零频率分量移至中心后倒易空间中的图像

屏蔽图像:由于粒子的边缘对应于高频,所以只允许这样的频率通过的屏蔽被应用于从先前步骤获得的变换图像。这有助于突出边缘。

最终滤波后的图像:最后,我们需要通过对掩蔽后的图像部署 np.fft.ifft2 函数,从空间频率空间回到真实空间。我在下面分享了处理过的带有明显颗粒边缘的图像。人们可以很容易地测量具有确定边界的颗粒的尺寸。

真实空间中的滤波图像

与其他图像处理滤波器的比较

为了进行比较研究,我在上面的显微照片上应用了另外两个图像滤镜——Canny和 unsharp masking滤镜。

可以清楚地看到(如下所示),傅立叶过滤器在识别颗粒边缘以进行精确测量方面优于 Canny 和 unsharp 遮罩过滤器。傅立叶滤波器具有优势,因为它能够在信号的幅度、频率、方向和相位方面精确地对信号进行去卷积。

代码输出-处理过的图像:三种图像过滤器的比较

点击这里的 到查看全部代码。

关键要点

傅立叶级数仅可应用于周期性函数,而傅立叶变换工具也可用于非周期性函数。

图像大多是非周期性的。然而,通过考虑表示图像的信号的离散跨度,在假设周期性的情况下,傅立叶变换被广泛用于图像处理中。这个概念为 DFT 奠定了基础。DFT 是使用 FFT 算法以数字方式实现的。

FFT 将波信号从时域转换到频域,或者从实空间转换到倒易(空间频率)空间。

在图像处理中,实空间中的像素信息被转换成倒易(空间频率)空间中的像素信息。

傅立叶过滤器可以定性和定量地精确检测显微照片中的特征。

详情请访问 我的网站

感谢您的阅读!

使用 NVIDIA Omniverse 高岭土快速合成数据

原文:https://towardsdatascience.com/fast-synthetic-data-with-nvidia-omniverse-kaolin-d96c75465b80

高岭土应用程序如何在几分钟内制作转盘风格的合成数据集的美元文件

来自 Lowe's Open Builder 数据集的美元资产集合将用于 NVIDIA Omniverse Kaolin[作者使用来自 Lowe's Open Builder 的资产拍摄的照片]。

概观

对 3D 深度学习的兴趣一直在以极快的速度加速增长。随着 PyTorch3D高岭土Open3D 、SIGGRAPH、CVPR 和 ECCV 的大量论文,以及从特斯拉亚马逊宝马涌现出的工业案例研究,仅举几个例子,很明显空间计算革命已经开始。此外,以数据为中心的人工智能运动激发了人们对用模拟引导 CV 应用的兴趣。了解如何处理单视场相机、立体相机、360°相机、激光雷达、结构光扫描、地理空间数据、航空照片,以及如何将它们融合在一起,正成为一项基本技能。

NVIDIA 正在构建一个庞大的可扩展工具和应用程序集合,用于在 NVIDIA Omniverse 内部进行无缝、高保真的模拟和设计。Omniverse 不仅仅是英伟达在元宇宙的赌博。他们正在使它成为未来对 3D 内容永无止境需求的核心工具套件,渗透到游戏、工业可视化、视觉效果、自动化、空间零售、模拟和几乎所有其他行业的不断增长的市场。

他们称之为 Omniverse,因为他们的价值主张的核心是互操作性和协作。这是由 Omniverse Connect 提供支持的,这是一组扩展,允许各种 3D 应用程序与 Omniverse 实时交换数据。连接器列表包括虚幻引擎,3DS Max,Maya,Revit 和每天更多。这个特性的一个关键因素是对标准的严重依赖,特别是 MDL、PhysX 和 Pixar 的 USD,NVIDIA 首席执行官黄仁勋声称这些标准将成为“元宇宙的 HTML”

NVIDIA Omniverse 与 Maya 连接:Maya 中的编辑通过实时光线跟踪反映在 Omniverse 中。

毫无疑问,他们对于 Omniverse 作为整个 3D 资产生态系统的唯一真实来源的价值主张将是非常有价值的,如果它确实能够实现这一点的话。NVIDIA 正在投入大量资源来实现其潜力。只有时间能证明一切。现在,让我们来看看 Omniverse,特别是 Kaolin 应用程序,如何在今天被用来生成合成数据,以开发您自己的计算机视觉应用程序。

高岭土

高岭土库概述【来自 NVIDIA 的高岭土库,根据 Apache 许可证版本授权。2.0

Kaolin 是 NVIDIA 基于 PyTorch 构建的 3D 深度学习高级 Python 库。它提供了可区分的渲染器、光栅化工具、用于操纵网格、顶点、面、UV 贴图和纹理的帮助器、常见的损失函数,如切角距离和 IoU、文件 IO、各种 3D 表示的转换、图形卷积、结构化点云等等。

不要与高岭土库混淆,高岭土应用是高岭土库的伴侣,是 Omniverse 应用套件的一部分。迄今为止,它包含三个主要特性:

  • 数据集可视化器 —在 3D 界面中查看和检查 USD 模型集合。
  • 数据生成器 —从一组 USD 文件中创建用于计算机视觉应用的合成训练数据。包括用于分段的注释器、2D & 3D 边界框、法线、点云等等。
  • 训练可视化器 —查看来自深度学习会话的网格、点云以及其他 3D 数据结构随时间的训练输出。

使用高岭土应用程序的高级工作流程如下:

  1. 使用数据集可视化器检查您的 3D 资产集合。
  2. 使用数据生成器生成数据集。
  3. 使用高岭土库在数据集上训练模型。
  4. 训练可视化器将训练结果进行三维可视化。

希望当我看完一个例子后,所有的问题都会迎刃而解。首先,让我们下载一些 3D 资源来使用。

劳氏开放式建造机

NVIDIA Omniverse Kaolin 中的 Lowe's Open Builder 资产[作者使用来自 Lowe's Open Builder 的资产拍摄的照片]。

Lowe's (是的,五金店)正在元宇宙表明自己的主张。他们最近发布了 Lowe's Open Builder ,这是一个 GLB 和 USDZ 格式的超过 500 个 3D 资产的数据集,任何人都可以免费下载和使用(关于使用条款,请阅读这里的)。它包括橱柜、工作台面、水槽、灯具、地毯、花盆、桌子、架子和许多你能在劳氏商店找到的产品。该网站使搜索、检查和下载模型变得很容易,因此我们将使用这些资源中的一些来进行高岭土实验。至少找到一个你喜欢的并下载 USDZ 文件。

数据集可视化工具

现在我们有了我们的资产,让我们使用高岭土应用程序来查看它们。数据集可视化工具可以在给定目录中搜索任何。美元,。美国农业部或者。usdc 文件,并将它们自动加载到查看器中。其主要目的是快速检查 3D 资产的集合,以了解和识别训练中可能存在的问题。

目前,它不支持。usdz 文件,但是有一个简单的解决方法。如果您熟悉 USD 格式,您可能知道,. usdz 文件只是一个未压缩的归档文件,其中包含某种形式的 USD 文件及其媒体资产(在此处阅读有关 USDZ 规范的更多信息)。因此,您可以简单地使用 7zip、unzip或另一个归档工具来提取每个文件。您下载的 usdz 文件。继续拉开拉链。使用适合您系统的归档实用程序将 usdz 文件下载到它自己的目录中。在里面你应该看到一个. usdc 文件和一些纹理在一个文件夹里。现在,在 Dataset Visualizer 中打开父目录应该可以成功加载这些模型。它递归地在指定的目录中搜索任何。美元,。美国农业部或者。usdc 文件。

下面的视频将引导您使用数据集可视化工具。

数据集可视化工具演练

这个应用程序只有几个简单的选项。您可以更改对象的数量,旋转它们,调整间距,以正常大小或正常比例查看它们,以及调整上轴。例如,使用这个可视化工具来查看您的模型的比例和方向是否正确。如果“正常化尺寸”未选中,书架和花瓶的尺寸应该会有很大不同。如果选中,它们看起来应该差不多一样大。如果资产看起来不垂直,也检查向上轴。您可能需要调整 USD 文件的“upAxis”属性。所有这些资产看起来都很好,y 轴向上。

数据生成程序

现在我们知道我们的资产大小合适,并且完全纹理化,我们可以用它们生成一些训练数据。“数据生成器”选项卡就是为此而设计的。此功能用于快速连续地生成资源集合的转盘样式图像,还可以选择对照明、相机姿势和材质进行随机化。

目前,数据生成器支持以下标签类型:

  • RGB
  • 深度
  • 法线
  • 语义分割
  • 实例分割
  • 2D 边界框(紧密或松散)
  • 3D 边界框
  • 点云
  • 相机姿势

以下视频将引导您使用数据生成器。

数据生成器演练

借助 Omniverse Kaolin 中的数据生成器,您可以训练机器学习模型进行分类、对象检测、语义/实例分割、深度估计、3D 场景理解、3D 重建等。然而,您可能会问自己:为什么我可能想要生成 3D 模型的训练数据?虽然领域差距使得将合成数据用于现实世界的应用成为一项重要任务,但每天都有越来越多的合成数据解锁功能的例子,这些功能在以前是不可能或难以获得真实数据的。看看最近来自特斯拉OpenAI亚马逊Meta (他们最近收购了合成数据初创公司 AI。遐想)等等。它还可以用于增强计算机视觉应用的原型开发,而不需要在硬件或标签上进行任何投资。

培训可视化工具

顾名思义,训练可视化工具对于实时监控 ML 模型的训练非常有用。你可能想知道“这不就是 Tensorboard 的用途吗?”Tensorboard 对于监控损耗、重量和输出数据日志是不可或缺的,而 Training Visualizer 支持实时渲染 3D 数据的光线跟踪。您还可以在训练迭代中滑动,可视化模型拓扑和纹理在整个训练过程中如何演变。

下面的视频将引导您使用培训可视化工具。

培训可视化工具演练

此时,您有两个选择:您可以 a)尝试使用高岭土库对您的数据训练模型,或者 b)下载我创建的训练日志,以立即试用训练可视化工具。

选项 A:安装高岭土

为了训练一个模型,我们需要安装高岭土库。如果你喜欢冒险,继续按照安装说明进行操作,进入 DIB-R 光栅化教程。简而言之,这将使模板网格(在这种情况下是球体)变形,以通过仅使用输入图像、遮罩和姿态的优化来近似 3D 模型。您可以用刚刚创建的训练数据集的路径替换rendered_path。完成后,在培训可视化工具中打开logs_path中的输出。

选项 B:下载培训日志

如果您想让事情变得简单,请随意下载此培训课程日志自行查看结果。从该文件中提取文件夹,然后在 Training Visualizer 中打开它(确保打开顶层文件夹,因为应用程序可能对文件夹结构非常挑剔)。您应该会看到类似上面视频中的结果。

结论

希望这有助于您使用 Omniverse 和 Kaolin 应用程序为 3D 深度学习生成 USD 3D 模型的标记合成数据集。这是一种快速有效的方法,可以为计算机视觉和 3D 深度学习实验生成数据集。如果你正在寻找驱动一个更复杂的模拟 ML 训练,你也可以尝试一下 Omniverse Replicator SDK

如果一切顺利,我将发表一篇后续文章,详细介绍如何使用 Kaolin Wisp ,这是一套新发布的工具,建立在 Kaolin 库之上,专门用于神经渲染技术,以便您可以在我们创建的数据上训练 NeRF。敬请期待!

基于 StatsForecast 的快速时间序列预测

原文:https://towardsdatascience.com/fast-time-series-forecasting-with-statsforecast-694d1670a2f3

用 Nixtla 的 StatsForecast 软件包快速预测单变量时间序列

照片由皮克斯拜拍摄。

StatsForecast 是一个,它附带了一组统计和计量经济学模型来预测单变量时间序列。它与大型时间序列完美配合,不仅声称比已知的 pmdarima 包快20 倍,而且比 fb prophet500 倍

本文为您提供了 StatsForecast 软件包的第一概述如何使用它。为了展示它的超快性能以及它对单个和多个时间序列的使用,我们将使用两个数据集。

我们将使用单一时间序列的澳大利亚葡萄酒总销售额数据集。该数据集将用于比较 StatsForecast 的auto_arima函数与众所周知的 pmdarima 包中的函数。第二个是 M4 数据集的摘录,包含 1.476 个时间序列。第二个示例背后的想法是向您展示如何使用包准备数据来预测多个时间序列。

为什么这么快?

在我们开始之前,你可能会怀疑,想知道它这么快的秘密是什么。这有两个主要原因。

一、StatsForecast 使用 Numba 。Numba 是一个用于 Python 的实时(JIT)编译器,它可以很好地处理 NumPy 代码,并翻译数组、代数函数等部分。在中,快速机器代码

第二,它还使用了并行计算,在处理多个时间序列时显示了它的优势。

入门和先决条件

要安装 StatsForecast,只需运行以下命令,如果您想安装带有 pip 的软件包:

pip install statsforecast

要使用 conda run 安装它:

conda install -c nixtla statsforecast

数据结构

StatsForecast 需要具有特定结构中的时间序列数据:

+-----------+----------+-------+
| unique_id |    ds    |   y   |
+-----------+------------------+
|     0     | Jan 2021 |  100  |
|     0     | Feb 2021 |  200  |
|     0     | Mar 2021 |  150  |
+-----------+------------------+
  • 一个名为唯一标识索引列
  • 包含日期数值ds
  • y 列是我们的单变量时间序列的目标变量

索引列表示相应时间序列的索引。如果只使用一个单一时间序列,则索引始终为 0常量。如果在一个数据帧中有多个时间序列,索引用于区分它们之间的并启用并行计算。例如,第一个时间序列的索引为 0,第二个时间序列的索引为 1,依此类推。

使用统计预测进行预测

现在我们已经熟悉了所需的数据结构,让我们从建模和预测开始。

澳大利亚葡萄酒总销售额(单一时间序列)

首先,我们必须以正确的形式呈现数据。销售数据是以日期(年月)为索引的序列(行 8 )。

由于是一个单时间序列,我们将整个数据的索引设置为 0 ,为日期创建一个 ds 列,为销售额创建一个 y 列(第 11-17 行)。

在这一步之后,我们将 ds 列转换为 datetime ( 第 18 行)。总的葡萄酒数据是每月一次。当我们用日期时间进行转换时,我们得到一个年-月-日格式,总是从一个月的第一天开始。这可能会在以后使用预测方法时导致问题(结果日期总是月末)。这就是为什么我们在这里加上MonthEnd①

最后,我们将数据分为训练集和测试集。我们数据的最终结果如下所示:

图一。转换后的澳大利亚葡萄酒总销售额数据集摘录。

将数据整理成正确的形状后,我们可以开始初始化 StatsForecast:

StatsForecast 需要以下参数:

  • (训练)数据框
  • 您想要用作带有模型名称和相应参数(auto_arima,12)的元组的模型
  • 频率(“M”代表月份,“Y”代表年份,等等。)
  • 可选的是 n_jobs,可以用来在处理多个时间序列时启用并行计算。

正如开头提到的,StatsForecast 附带了一堆其他的统计计量经济学模型。您可以将模型参数(第 7 行)作为元组提供给多个模型参数及其特定参数。完整列表所有提供的型号可以在 这里 找到。

在本例中,我们仅使用auto_arima模型,并将季节长度参数设置为 12。默认情况下,n_job 参数设置为 1。只有当我们的数据集中有多个时间序列时,增加它才有意义。

现在我们已经配置了我们的预测器,我们可以预测即将到来的 26 个月。

计算时间刚好用了 2.78 秒

StatsForecast 的预测以数据帧的形式返回(图 2)。每一列(除了当时的 ds)显示由定义的模型产生的预测。

图二。使用 auto_arima 的 StatsForecast 预测摘录。

现在我们有了结果,让我们计算平均绝对误差(MAE)。各种时间序列误差指标的完整概述可在这里找到。

我们得到了的一个MAEof的一个MAEMAE】。56629 . 68686868626

与 pmdarima 包的比较

现在让我们比较一下 pmdarima 软件包的auto_arima 功能的性能和精度。

使用统计预测auto_arima方法,我们有一个的计算时间86和一个的平均时间秒****

比较两个软件包的性能,并将预测结果绘制成图表(图 3),我们可以看到 StatsForecast 的auto_arima比 pmdarima 的快 30 倍,并且比 pmdarima 的更准确。

图 3。26 个月预测结果。

M4 数据(多个时间序列)

因为我们现在已经熟悉了预测单个时间序列,所以我们现在关注一个更高级的例子。M4 的数据可以在这里找到。为了****简单演示,我们只关注微观经济时间序列的每日数据(1.476 个不同的时间序列)。如上所述,本节的目的是向您展示如何在 StatsForecast 的右侧形状中引入多个时间序列。

我们首先加载部分 M4 数据集,并将列转换为行:

原始数据(图 4)将被转换成下面的形状(图 5)。

图 4。加载的 M4 每日数据集摘录。

图 5。转换后的 M4 每日数据集摘录。

在此步骤之后,我们将关于数据集的信息(主要是其类别)添加到我们的测试和训练数据帧中(第 2–3 行)。我们还创建了一个 unique_id 索引,其中包含每个时间序列的类别和 id(第 5–6 行)。

这一争论步骤之后的结果如下所示:

图 6。操作后的训练数据集摘录。

与第一个例子不同,我们的索引现在有了多个值。每个值代表一个时间序列。这有助于软件包运行并行计算或预测。

只差最后一步了:我们必须添加或创建一个 ds 列。我们通过运行以下代码来实现这一点:

该代码为每个时间序列添加一个数字序列(从 1 开始),代表相应的日期。记住:ds-列可以包含数值日期。结果看起来像这样:

图 7。带 ds 列的训练数据集摘录。

现在我们已经有了所有需要的数据,我们可以进入最后的建模步骤。

我们将季节长度设置为 7,将频率设置为“D ”,因为我们有每日数据。与我们的第一个例子不同,我们没有将 n_jobs 设置为 1,而是设置为我们想要预测的不同时间序列的数量。n_jobs 由可用内核的数量和不同的时间序列决定。如果时间序列比可用内核多,min函数将返回可用内核的数量。

执行预测花费了3 分 11 秒的 MAE。48659 . 63838638631****

结论

StatsForecast 的表现确实令人印象深刻。正如你在他们的 github 页面上看到的,团队正在努力修复漏洞和实现新功能。
即使他们目前的文档有限,但正在制作中,你可以在他们的 github 页面上找到很多例子,以及一篇关于 towardsdatascience 的写得很好的详细文章。

如果我可以许三个愿望,那么我希望有置信区间和预测区间、模型汇总函数(提供更多关于模型的统计信息)以及 StatsForecast 在其他包中的集成。

更多链接

👉StatsForecast 的 github 页面

👉联合创始人 Federico Garza Ramírez 撰写的 TDS 文章

👉Pmdarima 的 github 页面

👉时序误差指标概述

FastAPI 对 Flask

原文:https://towardsdatascience.com/fastapi-versus-flask-3f90adc9572f

这是怎么回事?我们不是已经有姜戈了吗?

Unsplash 上由 Tharoushan Kandarajah 拍摄的照片

最近,在我看来,有一个关于作为替代 Python web 框架的 FastAPI 的讨论。我从来没有那么喜欢 Django,因为它对于我的特定用例来说似乎太重了,但是我一直喜欢 Flask 因为它构建起来又快又容易。所以现在我们有了一个敢于自称为 FastAPI 的框架,自然地,鉴于我对跑车的热爱,我只需要做一个项目,然后,嗯,带着它转一圈!。

我如何使用烧瓶

因为我已经到达了“web 框架经销店”,所以最好描述一下我通常开的车,这种思考可以为试驾提供所需的背景。

我使用带有内置开发服务器的 Flask 进行快速原型或本地开发的概念验证工作。因此,这对于有限的本地机器用户来说很好。然而,当我在公共互联网上部署到 HerokuAWS 虚拟机时,我使用了不同的方法。我用烧瓶,带 GunicornuWSGINginx 。现在,我相信你会知道这一点,我们正在谈论一个带有 API 服务的 Python 后端。Python 后端服务于我的用例,因为有像 scikit-learnnltk 这样的库。我甚至毫不费力地在 RaspberryPi 计算机上部署了我最喜欢的堆栈。

你可以在这里观看一个视频,在这里我用 Python 和 Flask 演示了整个项目。另外,我做了一个系列,从头到尾讲解了整个开发过程,这里有。最后,我在支持视频系列的媒体上写了文章

我总是在前端使用 vue.jsbootstrap 进行我的造型。我甚至写了如何让 Python 后端服务器和 vue 应用程序运行良好,而没有我在最近的许多文章中读到的所有 Docker 容器对话CORS 问题。

所以我是一个固执己见的买家。像任何潜在买家一样,我脑海中有一个小小的声音在说…

https://expressjs.com/—图片来自快报网站

停下来!好吧,毕竟我们都忽略了脑子里那些小小的声音,不是吗?毕竟,是正品。我承认我使用 Express,明显的优势是后端和前端使用相同的编码语言。然而,不情愿地,我也不得不承认 Express 的响应看起来和感觉起来比同等烧瓶配置的响应快得多。

它不是一个单一的‘网络框架经销商’;这是一个挤满经销商的拥挤商场。我看到 Java 经销店再往下,脑子里那个声音越来越大;停下来!!

去哪里转一圈?

前几天我试驾了一辆高尔夫 GTI。你打赌他们没让我走远,因为车没油了。所以试驾的路程大约是 1 英里,因为我担心汽油用完。那些家伙!后来我说不用了,谢谢!

让我们回顾一下我早期的一个项目,并带着 FastAPI 和那个用例做一个简短的介绍。

语义突出是我当前项目的一部分,利用 NLP 服务帮助人们处理他们的简历和求职。用于 spin 的 Github 库包含了这两种方法。原始的烧瓶方法和新的 FastAPI 工艺。

带烧瓶

用 Mac Mini M1 运行 Flask 后端——图片由作者提供

带有 Vue.js 的前端应用程序演示了语义突出显示——图片由作者提供

所以我们知道我们要去哪里,也知道我们在试驾中会看到什么。****

试驾

好,我们开始吧!

FastAPI 后端运行— localhost —图片由作者提供

作者的照片——精彩!是一样的!我用了不同的端口号!

最大的区别是没有来自 Flask 开发服务器的警告。最好打开引擎盖,看看发动机;也许那是不同的!我脑中的声音说,“你对发动机了解多少”停下来!!!!!!

乍一看,代码似乎没有什么不同!我们不导入 Flask,而是导入 fastapi。还有一个 app . route(“/”)现在是 app . get(“/”)。我们甚至有第 15 行,它将后端服务器指向 dist 文件夹,在那里我们有 vue.js 应用程序的构建版本。提醒一下,我们必须构建 vue.js 应用程序,它在一个名为 dist 的文件夹中创建 index.html 和相关文件。你可以阅读资源库中的自述文件中的说明。

好了,我们从试驾回来了,坦率地说,我们仍然可以做我们可以用 Flask 做的事情!打哈欠!

物质享受呢?

你一定会喜欢那些销售人员的!他们总是有一个角度。

http://localhost:8000/docs

使用 FastAPI,尝试导航到/docs,让您的下巴离开地面!

Swagger UI 界面来自/docs —图片由作者提供。

不用多说,我买了!

使用内置的 Swagger-UI 页面测试我的单个端点——作者图片

如果你做全栈开发,就像你的后端和前端工作一样,你可能知道用户界面代码库中需要的每一个数据都有许多前端和后端步骤。所以连接 API 调用和使用这些 API 会变得有点复杂,特别是如果你使用一个"Mud 设计模式 n "的大球的话。

使用 FastAPI 对我来说比 Flask 更有优势。首先,我得到了 Swagger-UI 页面,它帮助我考虑我的端点和文档,甚至使用更好的工程模式。但是,更重要的是,我可以用一种更加用户友好的方式测试我的端点,当然还有速度!

这是怎么回事?

在 FastAPI 的引擎盖下有一堆 gobblygook ,很多关于异步对同步的讨论,但是它归结为:-

  • 异步ˌ非同步(asynchronous)
  • 等待

https://medium.com/technofunnel/javascript-async-await-c83b15950a71 https://ai.plainenglish.io/django-async-vs-fastapi-vs-wsgi-django-choice-of-ml-dl-inference-servers-answering-some-burning-e6a354bf272a

在我的上下文中,我正在设计一个处理文本文档的应用程序,包括对 NLP 例程的调用,并且需要为我的用户保持快速的响应时间。长时间运行的文本处理程序会挂起前端,并很快疏远我的用户。所以现在,有了 FastAPI,我可以利用 JavaScript 的 Express 服务器的优势和 Python 库的机器学习优势,而不会对我的最终用户造成重大影响。

这是令人兴奋的,可能是时候了!

照片由雅各布·欧文斯Unsplash

https://cognitivedave.medium.com/membership

fastcoref——一个实用的共指消解包

原文:https://towardsdatascience.com/fastcoref-a-practical-package-for-coreference-resolution-bfbcb749e464

理解自然语言处理中的共指消解的 F-coref 模型背后的主要工作,以及如何通过 fastcoref 直观包使用它

fastcoref——瑞安·斯通在 Unsplash 上拍摄的照片

介绍

本周,以色列巴尔伊兰大学的 Shon Otmazgin,Arie Cattan 和 Yoav Goldberg 教授发布了一个名为'【fastcoref '【2】的共指消解包,它快速、准确且易于使用。在本文中,我们将了解这个包背后的主要工作以及如何使用它。你也可以在由 Ari Bronstein 创建的 huggingface 中看到这个伟大包的一个演示。

共指消解是识别文本提及(又名:提及检测)和链接文档中相互引用的实体(又名:共指决策)的任务。让我们看看劳拉·杨的这幅漫画,试着理解哪些实体是相同的。

劳拉·杨关于杨经济学的漫画

“爸爸”、“他”和“他的”指的是同一个实体,识别这些实体并将它们链接到它们的前身是我们在 NLP 共指解析中所说的。我假设你知道共指消解任务和模型,如果不知道的话这里是一篇很好的文章,可以给你更多的 Gal Hever 的背景知识。

共指任务是用于附加 NLP 任务的基本任务,例如:信息抽取、问题回答、摘要、机器翻译等等。尽管它作为一个基本的 NLP 任务很重要,但当前的研究未能实现快速工作或在有限资源下工作的体面模型。作者介绍的模型,F-coref’【1】,由于结合了硬目标蒸馏模型高效分批实现(他们命名为“剩余分批”)。

背景——S2E 和林姆斯模型

一般的神经协同参考模型由三个模块组成。一个语境化的编码器,将单词嵌入到向量中,一个提及记分器,一旦我们有了提及,一个共指记分器。

通用共同参考模型管道

F-coref 模型基于 S2E 模型[3]。S2E 是一个神经模型,它将每个区间表示为其开始和结束标记的函数。它的架构包括:Longformer(一个上下文化的编码器),一个参数化的提及评分函数(f_m)和一个参数化的成对先行评分函数(f_a)。

注意,为了节省计算时间,antecedent 函数只对提及分数最高的λT 区间进行评分。T-令牌数。λ-修剪超参数设置为 0.4,以实现高提及召回率。

分数计算为两个提及分数和配对前提分数之和。

分数计算为两个提及分数和配对前提分数的总和[1]

整个模型由 26 层和 494M 参数组成。

最近的工作,LINGMESS 模型[4],通过为每种类型的提及引入多个评分器来提高共指准确性。这导致了 SOTA 精确度,但是该模型不如 S2E 有效。

F-coref 模型

现在让我们来了解一下 F-coref 的要素是什么,才能达到极高的效率。我们将首先讨论知识提炼,然后讨论最大化并行性。

知识蒸馏—缩小模型尺寸

知识提炼是将知识从大模型转移到小模型的过程。当我们的目标是建立快速模型时,我们需要较少的参数。知识提炼是减少模型中的参数数量,同时仍然保持其大部分准确性的一个很好的方法。

主持人Unsplash 上拍摄的“师生蒸馏”照片

师生模式

为了训练 F-coref,作者使用 LINGMESS 作为教师模型。学生模型的构建与 S2E 模型相似,但稍有修改:层数更少,因此参数也更少,相对较慢的 Longformer 被 DistilRoBERTa 取代。总的来说,参数的数量从 494M 减少到 91M,层数从 26 层减少到 8 层。
他们用硬目标知识提炼。也就是说,教师模型充当未标记数据的注释器,学生模型从这些注释中学习,而不是学生根据教师模型的逻辑进行学习的软版本。软提取对于共指任务不起作用的原因是提及修剪和传递性的违反(这很有趣,可以帮助您选择提取模型,您可以在论文[1]中了解更多)。

最大化并行性——让它更快

作者使用了更低的λ进行修剪(0.25 而不是 0.4),他们声称这在不影响性能的情况下减少了 2.56 对的数量。他们还使用了一个新版本的动态批处理,将文档数量分批到某个阈值,他们将其命名为“剩余文件分批”

Richad BellUnsplash 上拍摄的“剩余配料”照片

剩菜配料

共指模型中最耗时的部分是编码器。传统上,长文档被分割成不重叠的 max_length 的片段,每个片段被编码。如果文档比 max_length 长,它将被分割成两个或多个片段,最后一个片段将被填充到 max_length 。这导致大量填充令牌。

作者建议的改变是创建两个单独的批次,一个用于没有填充的完整片段,另一个用于剩余片段。然后,他们将第二批填充到最大剩余长度,而不是将剩余部分填充到最大长度。注意,这种剩余的批处理对其他 ML 任务也是有用的。

传统配料与剩余配料的比较[1]

F-coref 结果

现在我们要测试新模型在推理时间和 F1 分数方面的表现。我们预计 F1 的分数会比 SOTA 联合参考模型略低,但推断时间会快得多。

实验装置使用多新闻数据集对笔记数据集训练师生模型。F-coref 的 F1 平均得分为 78.5。如果我们将其与之前讨论的两个模型进行比较, F-coref 与 LINGMESS(老师)相比下降了 2.9 F1 分,与 s2e 模型相比下降了 1.8 F1 分。

现在,作者比较了 2.8K 文档推理的每个共指模型的时间。我们看到 F-coref 比之前最快的型号平均三次跑快一个数量级。我们看到最显著的时间减少是由于蒸馏模型。后来,配料和剩余配料进一步将时间减少到只有 25 秒。

F-coref 比以前最快的模型快一个数量级[1]

对于应用数据科学来说,这种权衡看起来很好,因为在应用数据科学中,资源有限,需要快速的推理时间。

一个直观的软件包

作者还发布了一个非常直观的软件包供您使用。让我们看看如何使用它。

  1. 安装包
    包是 pip 可安装的
pip install fastcoref

2.导入模型
导入 F-coref 模型

from fastcoref import FCoref
model = FCoref(device='cuda:0')

3.预测共指

preds = model.predict(
 texts=[‘Fastcoref is a great package. I am glad Noa introduced it to me.’]
)preds[0].get_clusters()>> [['Fastcoref', 'it'], ['I', 'me']]

当比较 F-coref 和 LingMessCore 模型在 CPU 上的简单示例的推理时间时,我们看到 F-coref 实现了 1/5 的 wall 时间和 1/18 的 CPU 时间。

F-coref

CPU times: user 595 ms, sys: 22 ms, total: 617 ms
Wall time: 494 ms

凌梅斯科尔

CPU times: user 10.7 s, sys: 617 ms, total: 11.3 s
Wall time: 2.42 s

请注意,您也可以训练蒸馏您自己的模型(参见 github 的说明)

结论

如果你有一个需要大规模处理的共指任务,我相信使用 fastcoref 是合适的。该软件包易于使用,速度快,并保持同样的精度。

资源

1.F-COREF:快速、准确且易于使用的共指消解(Otmazgin 等人)

https://arxiv.org/abs/2209.04280

2.Fastcoref 软件包(Otmazgin 等人)

https://github.com/shon-otmazgin/fastcoref

3.无跨度表示的共指消解(Kirstain 等人,ACL 2021)

4.LingMess:基于语言学的多重专家打分器,用于共指消解

https://arxiv.org/abs/2205.12644

FastFlows:基于流的分子图生成模型

原文:https://towardsdatascience.com/fastflows-flow-based-models-for-molecular-graph-generation-a8327bb9bee1

高效生成建模的深度学习可逆变换

Unsplash 开始。

内森·c·弗雷

这篇文章是由深海森林科学的 Bharath Ramsundar 合著的。

规范化基于流程的深度生成模型学习简单基础分布和目标分布之间的转换。在这篇文章中,我们展示了如何使用【fast flows】对小分子数据集进行建模并生成新的分子。FastFlows 使我们能够在几秒钟内生成数以千计的有效分子,并展示了基于流的分子生成模型的优势和挑战。

一个 互动教程 伴随着这篇文章,可以通过 Google Colab 运行。

为什么我们要在化学和生物学中使用标准化流程?

使用变分自动编码器( VAEs )、递归神经网络( RNNs )、图形神经网络( GNNs )和生成对抗网络( GANs )来生成分子已经有了很多很好的工作。规范化流(NFs)可用于生成分子图,如 MoFlowGraphNVP 论文中所述。它们还可以用来加速计算小分子和蛋白质之间的结合亲和力。

在本文中,我们的目标不是取代这些方法,而是提供一个易于使用的框架,任何人都可以将其应用到兴趣分布中,并快速开始进行生成和概率建模。

什么是正常化流程?

NFs 有两个关键功能:密度计算和采样。在学习了概率分布之间的映射之后,NFs 可以精确地计算任何给定样本从目标分布中抽取的可能性。他们还可以从目标分布中生成新的样本。这使得 NFs 不同于其他生成模型,如 VAEs 和 GANs,它们只能估计可能性或根本不能计算它们。

一个示例展示了一个正态化流程如何将二维正态分布转换为目标分布。在这种情况下,点云看起来像单词“SIGRAPH”图片由埃里克·张提供。

另一个关键区别是,NF 中的层是双射变换——它们提供输入和输出之间的一对一映射,而不是将输入压缩到潜在空间中。因此,NFs 对于任何需要概率模型的应用程序都是有用的,这种概率模型需要密度计算和采样中的一种或两种。我推荐这些由 Eric Jang 和 Brad Saund 撰写的优秀博客文章,以获得关于 NFs 的更多细节和一些不错的例子。

准备自拍字符串数据集

为了展示 NFs 是如何工作的,我们将尝试从 QM9ChEMBL 数据集对分布进行建模。为了表示分子,我们将使用自引用嵌入字符串(Self ies)【1】。自拍是分子的 100%鲁棒的字符串表示——这意味着即使完全随机的自拍字符串也是化学上有效的分子。这对于设计应用来说非常棒,在这些应用中,深度学习模型(如 NFs)正在生成新的分子,而不知道决定分子是否有效的化学基本规则。借助自拍照 repo 中的函数和示例,很容易翻译为化学数据集提供的简化分子输入行输入系统(SMILES)字符串。

(A)具有微笑和自拍图像的代表性分子。(b)将输入样本从基本分布转换为目标分布的归一化流程示意图。图片作者。

我们将自拍字符串转换为独热编码向量,然后通过添加来自区间[0,0.95]的随机噪声来反量化这些向量。这为我们提供了我们的模型能够读取的连续的数字输入,我们可以通过应用简单的 floor 函数来恢复原始的自拍一键式编码。

将分子编码为 SELFIES 字符串和去量化张量,用于训练归一化流。图片作者。

训练归一化流程

NF 只是一系列的双射变换,我们可以构建深度神经网络,其中的层是双射的。这样,我们可以根据数据训练模型,并学习基本分布和目标之间的转换参数。幸运的是, TensorFlow Probabilityn flow库有许多内置的概率分布和双投影器,包括一些最流行的学习分布的架构。

基本分布的选择很简单——我们选择一个多维正态分布,它的维数与我们的一次性编码相同。这是最简单不过的了。然后我们必须建立我们的 NF。对于 fast flow[2],我们使用真实 NVP 层。

你可能想知道神经网络中的层是如何可逆的;一般来说,他们不是。真实 NVP 的工作方式是将转换分布中的每个元素 x_d+1 限制为仅依赖于基本分布中的前 d 个元素,对于某个整数 dAlpha_imu_i 是标量,通过神经网络传递基本分布的元素来计算。这给出了一个简单的缩放和移位(仿射)变换,然而它可以通过敏感地依赖于来自基本分布的先前变量来捕获复杂的目标分布。

真正的 NVP 中的向前传球。图片来自标准化流程教程

这里的关键是缩放和移位操作可以在一次通过中计算,因此 Real NVP 可以执行快速、并行的采样和密度估计。采样速度比基于因果序列的模型和屏蔽自回归流等自回归模型快几个数量级,但代价是表达能力降低。

我们交替排列 NVP 层,以便这些层可以对输入的不同部分进行操作。通过这种设置,我们可以通过反转平移和缩放操作来“撤消”变换,因此即使我们使用的是具有可学习参数的神经网络,我们也有一个可逆的变换。

对于真正的 NVP,我们必须指定层数和每个 NVP 层中隐藏单元的数量。在这个例子中,我们将使用 8 层和[512,512]个隐藏单元。我们可以增加这些数字,使更多的表达流捕捉更复杂的目标分布。

生成新分子

有了训练好的模型,很容易生成新的分子并评估它们的对数可能性。我们必须做一些后处理:应用 floor 函数并按值裁剪,以将有噪声的连续样本转换回独热编码向量。我们还必须向所有全零生成的向量添加填充字符。在那之后,

 selfies.multiple_hot_to_selfies() 

会给我们传回自拍的图像,我们可以将其解码成微笑,并用开源化学信息学软件 RDKit 进行分析。

RDKit 将查看我们生成的 SMILES 字符串,并检查它们是否是有效的分子。通过 FastFlows,我们可以在单个 GPU 上在 4.2 秒内生成 100K 个有效分子!如果您有任何尝试使用自回归模型生成有效微笑字符串的经验,这个数字是相当可观的!这就是真正的 NVP 的速度和自拍表现的鲁棒性。现在是时候实际看看我们的 NF 提出的分子了。

高通量虚拟筛选

对于 FastFlows,我们的目标不是想出将进入临床试验的确切分子,也不是确保生成的分子被精确设计以满足我们关心的所有限制。FastFlows 旨在使任何人都能够在低数据限制下进行深度生成建模,并利用计算成本低廉的采样功能。这是用 NFs 进行化学实验的一种方式,无论如何都不是一个生产就绪的系统。

我们从对生成分子的可合成性的研究中得知面向目标的深度生成模型倾向于提出在实验室中不容易制造的分子。为了确保在实验室环境中的相关性,你要么需要用合成规划直接生成分子,要么有快速的方法生成大量候选分子,并评估它们的合成可及性和复杂性以过滤掉不合理的候选分子。

在这里,为了对化学空间进行探索性的、好奇心驱动的研究,我们选择将我们的快速分子生成方法与同样快速的多目标优化相结合,以识别类似药物的可合成分子(至少通过一些简单的代理指标进行测量)。

FastFlows 工作流程图。图片作者。

FastFlows 非常擅长以比其他深度生成模型更快的速度生成化学上有效的、独特的和新颖的分子。这可能很有趣,或者这可能意味着即使这些分子在化学上是有效和独特的,它们也不是很现实。FastFlows 在像鳄梨酱摩西这样的分布学习指标上做得不好,因为它不是为这个目的而设计的。

我们可以使用快速生成的 FastFlows,并将其耦合到特设过滤器,以灵活地剔除我们的药物化学家不喜欢的分子。之后,我们计算分数,如药物相似性的定量估计、合成可及性和习得的合成复杂性——所有这些简单的代理都不会增加生成的大量时间成本,但确实给出了一些关于哪些生成的分子可能值得进一步研究的意义。

有了这些计算出来的分数,我们就找到了生成的样本的帕累托边界,这些样本最大程度地类似于药物,可以通过合成获得,并且是复杂的。通过考虑这些指标之间的权衡,我们避免挑选出对特定分数过度优化的分子,这可能导致生成的样品与现有药物过于相似(最大化 QED),过于简单和容易制造(最大化合成可及性),或者过于复杂和不现实(最大化合成复杂性)。通过平衡这些因素,我们可以探索我们喜欢的化学空间的任何领域,并找到感兴趣的分子,而不用在我们的深层神经网络架构中烘焙大量的复杂性,这使其难以训练和采样。

限制和后续步骤

FastFlows 在 QM9 上进行训练后,每秒可快速训练和采样 20,000 多个化学有效分子,在 ChEMBL 上进行更复杂分布的训练后,每秒可快速训练和采样近 500 个分子,因此深度生成建模可与同样省时的特设过滤器和多目标优化相结合,以实现高效的分子生成。但由于 FastFlows 依赖于完全双射变换,随着目标分布表示的维度增加(ChEMBL 的一个热门编码自拍的维度约为 18,000),归一化流的表达能力较低,需要增加深度来捕捉目标分布。

FastFlows 说明了稳定的深度神经网络训练(没有模式崩溃或其他深度生成模型中通常遇到的其他困难)和高通量虚拟筛选活动的快速、计算成本低廉的采样的优势。然而,低表达性和对许多双射变换的需求为架构改进和更灵活的基础分布提供了机会,以改进生成。

关键要点

  • 标准化流是一个灵活而有趣的深度学习框架,用于生成新分子。
  • 使用自拍、简单的标准化流程架构和多目标优化,可以在高通量虚拟筛选中识别新的化学有效分子。

取得联系

如果您喜欢本教程或有任何问题,请随时通过 电子邮件 联系内森,或连接上LinkedInTwitter

这项工作在 2021 年埃利斯分子发现机器学习研讨会上提出,并可在 arXiv 上获得。

你可以在他的 网站 上了解更多关于 Nathan 的项目和出版物。

参考文献

[1] Krenn,Mario 等人,“自参照嵌入字符串(自拍):100%鲁棒的分子字符串表示。”机器学习:科学与技术 1.4 (2020): 045024。

[2]弗雷、内森·c、维贾伊·加德帕利和巴拉思·拉姆松达。"快速流:基于流的分子图形生成模型."arXiv 预印本:2201.12419 (2022)。

fastgraphml:一个加速图机器学习模型开发过程的低代码框架

原文:https://towardsdatascience.com/fastgraphml-a-low-code-framework-to-accelerate-the-graph-machine-learning-model-development-9a43863299f

用低代码民主化图形机器学习

fastgraphml (图片由作者提供)

图机器学习是机器学习的一个快速发展的领域。它吸引了从社会科学到化学、生物、物理和电子商务等各个领域的大量人员。这背后的原因是图形结构的数据无处不在。今天,许多现实世界的应用程序都由 Graph ML 支持来运行它们的预测服务。例如, UberEats 利用 Graph ML 向用户建议他们下一步可能喜欢的菜肴、餐馆和美食。 Pinterest 利用 Graph ML 进行视觉推荐,Google Deep Mind 利用 Graph ML 进行流量预测。鉴于这一迷人领域的兴起,我们很自豪地发布了 fastgraphml 包(构建在 PyG 之上),它可以帮助用户仅用 3 行代码构建 graphml 模型。第一个版本集中于提供图形嵌入(或节点嵌入)作为功能,因为它充当所有图形 ML 问题(节点分类、链接预测、图形分类)的基础。此外,该框架使用 ArangoDB (下一代图形数据和分析平台)作为后端,将图形直接导出到 fastgraphml 包中。在这篇博文中,我们将探讨以下内容:

  • 为什么我们需要图形嵌入?
  • 什么是图嵌入,它们是如何工作的?
  • 什么是同构和异构图嵌入?
  • 图嵌入的应用有哪些?
  • 如何开始使用 fastgraphml 进行图形嵌入?
  • 结论

为什么我们需要图形嵌入?

一旦在合并了图的所有实体(节点)之间有意义的关系(边)之后创建了图。想到的下一个问题是找到一种方法来将关于图结构的信息(例如,关于图中节点的全局位置或其局部邻域结构的信息)集成到机器学习模型中。从图中提取结构信息(或特征)的一种方式是使用节点度、聚类系数、页面等级、核函数或手工设计的特征来计算其图统计,以估计局部邻域结构。一旦这些特征被提取,它们可以被用作 ML 分类器的输入,例如 SVM 或逻辑回归

图上的传统 ML。节点特征由特征提取器提取,然后用作 ML 算法的输入。(图片由作者提供)

然而,上述方法在某种意义上是有限的,因为它们是算法相关的,并且发现了图表中存在的特定预测信号。例如,聚集系数特征提取器将测量图中的节点倾向于聚集在一起的程度(有助于社区检测和链接预测问题)。类似地,页面排名检测图中节点的重要性。这些方法缺乏对图形特征的端到端学习,即在训练过程中不能借助损失函数来学习特征。此外,设计这些特征提取器可能是一个耗时且昂贵的过程(因为它需要手动特征工程)。

另一方面,图嵌入(又名图表示学习)寻找一组更一般化的特征来表示图,而不是捕捉特定的特征。手动调整的特征提取器和图形嵌入之间的主要区别在于它们如何处理为机器学习表示图形的挑战。第一种方法将它作为预处理步骤,第二种方法使用数据驱动的方法(机器学习训练过程的一部分)来学习概括图拓扑的嵌入。因此,通过数据驱动的方法学习嵌入比试错的手工特征工程节省了大量时间。

什么是图(节点)嵌入,它们是如何工作的?

通过端到端过程提取图特征的一种方法是采用表示学习方法,该方法将关于图的结构信息编码到 d 维欧几里得空间(也称为向量空间或嵌入空间)中。图形表示学习背后的关键思想是学习一个映射函数,它将节点或整个(子)图(来自非欧几里德)作为低维向量空间中的点嵌入(到嵌入空间)。得到的 d 维向量被称为图(节点)嵌入。

图形表示学习中的映射过程(图片鸣谢:斯坦福-cs224w

W orking:目标是优化这种映射,使得原始网络中邻近的节点在嵌入空间(向量空间)中也应该保持彼此靠近,同时将未连接的节点推开。因此,通过这样做,我们可以为图嵌入中的下游任务(例如,链接预测、节点/图分类、社区检测和节点聚类)保留原始网络的几何关系和语义。

让我们用 Zachary 空手道俱乐部社交网络的图结构中的一个有趣的例子来更直观地理解工作。在该图中,节点表示人,并且如果两个人是朋友,则在他们之间存在边。图表中的颜色代表不同的社区。图 A)表示扎卡里空手道俱乐部社交网络,B)示出了从空手道图创建的节点嵌入的 2D 可视化。如果您分析这两个图,您会发现从图结构(非欧几里德或不规则域)到嵌入空间(图 B)的节点映射是以这样的方式完成的,即嵌入空间中节点之间的距离反映了原始图中的接近程度(保留了节点邻域的结构)。例如,在空手道图中,标记为紫色和绿色的人的群体与彼此远离的紫色和海绿色的群体相比,共享很近的距离。同样的模式也可以在图 b 中看到。

图像学分:图形表示学习

同质图嵌入

齐次图是那些只由一种类型的节点和一种类型的链接(关系)组成的(无向图)。例如,亚马逊产品图 (ogbn-products),其中节点表示亚马逊产品(例如,玩具、书籍、电子产品、家庭&厨房等)。)和边对应的是一起买的产品。从这种类型的图生成的嵌入被称为同构图嵌入。

使用 GraphSage 的亚马逊产品图(节点)嵌入的 2D 可视化。图片作者。

异构图嵌入

异构图是那些能够包含不同类型的节点和链接(或关系)的图。例如,书目图(又名学术图)可以描述由四种类型的节点(即作者、论文、会议和术语)和三种类型的关系(即作者-作者-论文、论文-包含-术语和会议-发表-论文)组成的异构图。

一个有 4 种节点和 3 种边的学术图(图片来源:小王等人的异构图调查)

从这种类型的图生成的嵌入被称为异构图嵌入。下图展示了使用 DBLP 数据集(一个异构学术图)的作者节点嵌入的 2D 可视化。作者节点属于四个研究领域之一——数据库、数据挖掘、人工智能和信息检索。

使用 metapath2vec 对 DBLP 数据集中的作者节点嵌入进行 2D 可视化。图片作者。

图嵌入的应用

一旦生成了图(节点)嵌入,它们可以用于各种下游机器学习任务,例如:

  • 它可以用作下游 ML 任务(例如,社区检测、节点分类和链接预测)的特征输入
  • 我们可以从嵌入中构造一个 KNN/余弦相似图。该图表可用于提出建议(例如产品建议)
  • 通过使用 U-Map 和 t-SNE 算法(例如执行聚类)将数据减少到 2 或 3 维,对数据进行可视化探索。
  • 邻近搜索,即给定图中的任何输入节点,定位靠近该输入节点的节点(使用结构和语义信息)。
  • 药物发现
  • 欺诈检测
  • 数据集比较
  • 迁移学习

使用 fastgraphml 的图形嵌入

fatgraphml——给定一个输入图,它使用构建在 PyG 之上的低代码框架生成图嵌入。该软件包支持在支持 GPU 和 CPU 的机器上进行培训。与 CPU 相比,GPU 上的训练作业在处理大型图形时会带来更快的执行速度和更高的性能。此外,该框架提供了与 ArangoDB 的紧密集成,arango db 是一个可伸缩的、完全托管的图形数据库、文档存储和搜索引擎。一旦生成图嵌入,它们可以用于各种下游机器学习任务,如节点分类、链接预测、可视化、社区检测、相似性搜索、推荐等。

通过 fastgraphml 生成图形嵌入感觉起来轻而易举。

装置

必需的依赖关系

  1. PyTorch 1.12.*是必需的。
  • 使用与您的 CUDA 版本匹配的先前版本进行安装: PyTorch
  • 要找到您安装的 CUDA 版本,请在您的终端上运行nvidia-smi
  1. pyg

3.失败

  • 注意:对于 FAISS-CPU,需要numba==0.53.0

安装 fastgraphml

pip install fastgraphml

一旦安装了 fastgraphml,我们就可以开始使用 ArangoDB 中的图形或者只使用 PyG 图形数据对象来生成图形嵌入。

让我们看看不同的使用案例:

使用存储在 ArangoDB 中的图形生成图形嵌入:

同质图

from fastgraphml.graph_embeddings import SAGE, GAT
from fastgraphml.graph_embeddings import downstream_tasks
from fastgraphml import Datasets 
from arango import ArangoClient

# Initialize the ArangoDB client.
client = ArangoClient("http://127.0.0.1:8529")
db = client.db('_system', username='root', password='')

# Loading Amazon Computer Products dataset into ArangoDB
Datasets(db).load("AMAZON_COMPUTER_PRODUCTS")

# Optionally use arangodb graph
# arango_graph = db.graph('product_graph')

# metadata information of arango_graph
metagraph = {
    "vertexCollections": {
        "Computer_Products": {"x": "features", "y": "label"}, # mapping features attribute present in collection to x (node feature)
    },                                                        # mapping label attribute present in collection to y (node label)
    "edgeCollections": {
        "bought_together": {},
    },
}

# generating graph embeddings with 3 lines of code
model = SAGE(db,'product_graph', metagraph, embedding_size=256) # define graph embedding model
model._train(epochs=6, lr=0.0001) # train
embeddings = model.get_embeddings() # get embeddings
Homogeneous Graph Detected ........ 

{'Nodes': 13471, 'Node_feature_size': 767, 'Number_of_classes': 10, 'Edges': 491722, 'Edge_feature_fize': None, 'Graph Directionality': 'Undirected', 'Average node degree': '36.50', 'Number of training nodes': 10777, 'Number of val nodes': 1347, 'Number of test nodes': 1347, 'Has isolated nodes': False}
Training started .........
Epoch: 001, Train_Loss: 1.3626, Val: 0.7996, Test: 0.8048
Val Acc increased (0.00000 --> 0.79955).  Saving model ...
Epoch: 002, Train_Loss: 1.2654, Val: 0.8211, Test: 0.8233
Val Acc increased (0.79955 --> 0.82108).  Saving model ...
Epoch: 003, Train_Loss: 1.1866, Val: 0.8300, Test: 0.8315
Val Acc increased (0.82108 --> 0.82999).  Saving model ...
Epoch: 004, Train_Loss: 1.0630, Val: 0.8293, Test: 0.8344
Epoch: 005, Train_Loss: 1.0818, Val: 0.8352, Test: 0.8382
Val Acc increased (0.82999 --> 0.83519).  Saving model ...

此外,该库还提供了各种低代码助手方法来执行许多下游任务,如可视化、相似性搜索(推荐)和链接预测(即将添加)。

下游任务 1:图形嵌入可视化

该方法通过使用 U-Map 将生成的图形嵌入减少到二维,有助于生成图形嵌入的可视化。

class_names = {0: 'Desktops',1: 'Data Storage',2: 'Laptops',3: 'Monitors',4: 'Computer Components',
 5: 'Video Projectors',6: 'Routers',7: 'Tablets',8: 'Networking Products',9: 'Webcams'}

# emb visualization
# model.G access PyG data object
downstream_tasks.visualize_embeddings(model.G, embeddings, class_mapping=class_names, emb_percent=0.1) 

亚马逊计算机产品(图)节点嵌入的 2D 可视化。图片作者。

下游任务 2:使用 Faiss 的可扩展相似性搜索(推荐)

Faiss 是由脸书开发的一个工具,它可以在任意大小的向量集中执行相似性搜索,直到那些可能不适合 RAM 的向量。我们目前支持两种类型的搜索:

  1. 精确搜索:精确的相似性搜索,但代价是可伸缩性。
  2. 近似搜索:用于可扩展的相似性搜索,但会损失一些精度。

让我们执行推荐——给定任何一款计算机产品,哪一款产品可以一起购买?

# returns top 50 similar products (ids) along with similarity distance 
distance, nbors = downstream_tasks.similarity_search(embeddings, top_k_nbors=50) 
# Let's pick a random computer prodcut for which we want recommendation
# model.G.y access PyG node labels
class_names[model.G.y[5].item()]
'Data Storage'
# recommend computer product that can be bought together with 'Data Storage' product
class_names[model.G.y[nbors[5][40]].item()]
'Networking Products'

基于图嵌入的节点分类

在现实世界中,大多数数据集是没有标签的(或者只有很少的标签),并且经常是不平衡的。类别不平衡和稀疏标签使得监督学习成为一项具有挑战性的任务。它还会导致更高的假阴性,不平衡的数据集会导致模型出现更多的假阳性。因此,用无监督的目标训练 gnn 并在下游使用它们的潜在表示(节点嵌入)可以提供有希望的结果。一旦使用无监督学习生成了图(节点)嵌入,它们就可以被用作机器学习分类模型的特征输入,以执行节点分类的任务。

下面的代码显示,甚至更少的训练数据(带标签)即 10%也可以很好地概括看不见的数据(测试数据),这与上面的 SAGE 类形成对比,在上面的 SAGE 类中,我们使用 80%的数据作为训练来测试生成的图形嵌入的性能。

# Dataset Splitting
X_train, X_test, y_train, y_test = train_test_split(
    embeddings, model.G.y, train_size=0.1, test_size=None, stratify=model.G.y, random_state=42)
# Training with Logistic Regression
clf = LogisticRegression(max_iter=1000, solver="lbfgs")
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)
# evalute accuracy on test set
accuracy_score(y_test, y_pred)
0.8094688221709007

在 ArangoDB 中存储同构图嵌入

fastgraphml 还提供了一个助手方法 store_embeddings 来存储 ArangoDB 中生成的图嵌入。

N 注:如果 nearest_nbors_search=True, store_embeddings 方法将生成的图嵌入与 top_k 最近邻(具有相似嵌入的节点 id)及其相应的相似性得分(即余弦距离)一起保存在 ArangoDB 中。

model.graph_util.store_embeddings(embeddings, collection_name='computer_products_embeddings', batch_size=100,
                                 class_mapping=class_names, nearest_nbors_search=True)

异构图

from fastgraphml.graph_embeddings import METAPATH2VEC
from fastgraphml.graph_embeddings import downstream_tasks 
from arango import ArangoClient
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.linear_model import LogisticRegression
# Initialize the ArangoDB client.
client = ArangoClient("http://127.0.0.1:8529")
db = client.db('_system', username='root')
# Loading ArangoDB Graph
arango_graph = db.graph("DBLP")
# metadata information of arango_graph (we assume DBLP graph already exists in ArangoDB)
metagraph = {
    "vertexCollections": {

        "author": { "x": "x", "y": "y"},  
        "paper": {"x": "x"},
        "term": {"x": "x"},
        "conference": {}
    },
    "edgeCollections": {
        "to": {},
    },
}

# APCPA
metapaths = [('author', 'to', 'paper'), 
             ('paper', 'to', 'conference'),
             ('conference', 'to', 'paper'),
            ('paper', 'to', 'author'), ]
# generating graph embeddings with 3 lines of code
model = METAPATH2VEC(db, arango_graph, metagraph, metapaths, key_node='author', 
                     embedding_size=128, walk_length=5, context_size=6, walks_per_node=10, 
                     num_negative_samples=10,sparse=True) # define model
model._train(epochs=15, lr=0.03) # train
embeddings = model.get_embeddings() # get embeddings
Heterogeneous Graph Detected .......... 

{'Nodes': 26128, 'Edges': 239566, 'node_types': ['author', 'paper', 'term', 'conference'], 'edge_types': [('author', 'to', 'paper'), ('paper', 'to', 'author'), ('paper', 'to', 'term'), ('paper', 'to', 'conference'), ('term', 'to', 'paper'), ('conference', 'to', 'paper')], 'Graph Directionality': 'Directed', 'Has isolated nodes': True, 'node stats': {'Number of author nodes': 4057, 'Number of train author nodes': 3245, 'Number of val author nodes': 406, 'Number of test author nodes': 406, 'Number of classes in author nodes': 4, 'number of paper nodes': 14328, 'number of term nodes': 7723, 'number of conference nodes': 20}}
Training started .........
Epoch: 001, Train_Loss: 8.7637, Val: 0.3399, Test: 0.3842
Val Acc increased (0.00000 --> 0.33990).  Saving model ...
Epoch: 002, Train_Loss: 6.0169, Val: 0.5000, Test: 0.5369
Val Acc increased (0.33990 --> 0.50000).  Saving model ...
Epoch: 003, Train_Loss: 4.9843, Val: 0.6749, Test: 0.6650
Val Acc increased (0.50000 --> 0.67488).  Saving model ...
Epoch: 004, Train_Loss: 4.3761, Val: 0.7980, Test: 0.7956
Val Acc increased (0.67488 --> 0.79803).  Saving model ...
Epoch: 005, Train_Loss: 3.4619, Val: 0.8719, Test: 0.8522
Val Acc increased (0.79803 --> 0.87192).  Saving model ...
Epoch: 006, Train_Loss: 2.9975, Val: 0.8867, Test: 0.8695
Val Acc increased (0.87192 --> 0.88670).  Saving model ...
Epoch: 007, Train_Loss: 2.4220, Val: 0.9163, Test: 0.8818
Val Acc increased (0.88670 --> 0.91626).  Saving model ...
Epoch: 008, Train_Loss: 2.0990, Val: 0.9187, Test: 0.8867
Val Acc increased (0.91626 --> 0.91872).  Saving model ...
Epoch: 009, Train_Loss: 1.8748, Val: 0.9163, Test: 0.8793
Epoch: 010, Train_Loss: 1.6358, Val: 0.9089, Test: 0.9015
Epoch: 011, Train_Loss: 1.6156, Val: 0.9138, Test: 0.9089
Epoch: 012, Train_Loss: 1.4696, Val: 0.9261, Test: 0.9089
Val Acc increased (0.91872 --> 0.92611).  Saving model ...
Epoch: 013, Train_Loss: 1.2789, Val: 0.9163, Test: 0.8892
Epoch: 014, Train_Loss: 1.2143, Val: 0.9187, Test: 0.9138
# Metapath2Vec compute embeddings for those nodes which are present in metapath
embeddings
{'author': array([[ 0.3469685 , -0.73929137, -0.3658532 , ..., -0.07065899,
          0.01433279, -0.00440213],
        [-0.18779977,  0.0759825 , -0.38714892, ..., -0.13985269,
         -0.7717297 , -0.55180293],
        [-0.27399492, -0.1742627 ,  0.01303964, ...,  0.08810424,
         -0.4031429 ,  0.20701364],
        ...,
        [ 0.1659177 ,  0.11282699, -0.14390166, ...,  0.17577603,
         -0.28433827,  0.16120055],
        [ 0.01443969,  0.1374461 ,  0.5134789 , ...,  0.33182082,
          0.2584621 ,  0.00462335],
        [ 0.22391362, -0.50708103,  0.34233156, ...,  0.03449561,
          0.16480075,  0.39390147]], dtype=float32),
 'conference': array([[-2.1632937e-01, -5.3228494e-02,  1.5947707e-01, ...,
          5.1428860e-01,  8.5533451e-04, -3.4591302e-01],
        [ 6.9806822e-02,  5.0240862e-01, -2.3461170e-01, ...,
         -4.9915221e-01,  1.5349187e-01, -1.8434562e-01],
        [-5.0854170e-01, -9.7937733e-02, -1.0179291e+00, ...,
         -1.8171304e-01,  6.6947944e-02, -3.5466689e-01],
        ...,
        [ 6.2907688e-02, -8.9021228e-02,  3.4244403e-02, ...,
         -1.6124582e-02,  5.2124184e-01,  3.5454047e-01],
        [-1.1044691e+00,  3.7697849e-01, -3.7053806e-01, ...,
         -2.4933312e-02,  7.9877669e-01,  3.4990273e-02],
        [-8.0069518e-01,  6.9776934e-01, -5.1909280e-01, ...,
         -2.3521569e-03, -7.8969456e-02,  9.5190950e-02]], dtype=float32),
 'paper': array([[-1.6482981 ,  0.7253625 ,  1.0436039 , ...,  1.4693767 ,
         -1.5437169 , -0.0564078 ],
        [-0.22423816,  0.34060782, -0.09682338, ..., -0.3744318 ,
         -0.4454421 , -1.3889308 ],
        [-0.00360703, -1.0357887 , -0.6753541 , ..., -0.6235587 ,
         -0.2809864 , -0.6067877 ],
        ...,
        [-0.08141378,  1.0001668 ,  0.57556117, ..., -1.494264  ,
         -0.13634554,  1.0170926 ],
        [-1.0099323 ,  0.67756116,  0.5964136 , ..., -0.6101154 ,
         -1.1644614 ,  0.04493611],
        [ 0.09980668,  0.178698  ,  0.52335536, ..., -1.1220363 ,
         -1.161221  ,  0.35191363]], dtype=float32)}

相似性搜索/推荐

# returns top 10 similar authors(ids) along with similarity distance 
distance, nbors = downstream_tasks.similarity_search(embeddings['author'], top_k_nbors=10)
# recommend similar authors based on common research areas and common conferences
nbors
array([[   0,  670,   14, ..., 1132,  230, 2585],
       [   1,   14, 1132, ...,  404,   22, 1730],
       [   2, 3718, 1201, ..., 3784, 3848, 3820],
       ...,
       [4054, 1795, 2235, ..., 1389, 4012, 3991],
       [4055, 3104, 2803, ..., 2530, 1364, 3900],
       [4056, 3979, 2630, ..., 4013, 4006, 3991]])

基于图嵌入的节点分类

# Dataset Splitting
X_train, X_test, y_train, y_test = train_test_split(
    embeddings['author'], model.G['author'].y.cpu().numpy(), train_size=0.1, test_size=None, 
    stratify=model.G['author'].y.cpu().numpy(), random_state=42)
# Training with Logistic Regression
clf = LogisticRegression(max_iter=1000, solver="lbfgs")
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)
# evalute accuracy on test set
accuracy_score(y_test, y_pred)
0.9173055859802848

在 ArangoDB 中存储异构图嵌入

model.graph_util.store_embeddings(embeddings['author'], collection_name='author_embeddings', node_type='author')

使用 PyG 图生成图嵌入:

from fastgraphml.graph_embeddings import SAGE, GAT
from fastgraphml.graph_embeddings import downstream_tasks 
from torch_geometric.datasets import Planetoid

# load pyg dataset
dataset = Planetoid(root='/tmp/Cora', name='Cora')
data = dataset[0]

# generating graph embeddings with 3 lines of code
model = SAGE(pyg_graph=data, embedding_size=64) # define graph embedding model
model._train(epochs=10) # train
embeddings = model.get_embeddings() # get embeddings

结论

在本文中,我们了解了在图形上进行机器学习的传统方法——图形特征提取器,如节点度、聚类系数等。以及它们的局限性。然后,我们研究了图形嵌入相对于手工图形特征工程的重要性。此外,我解释了什么是图嵌入——在 d 维向量空间中对结构和语义信息进行编码的图的总结。之后,我们看到了同构和异构图嵌入的非常高层次的直观解释。在最后一节中,我们讨论如何开始使用 fastgraphml——一个快速构建图形机器学习模型的低代码包。fastgraphml 包提供了许多功能——用 3 行代码构建图形 ml 模型,为同构和异构图形生成图形嵌入,图形嵌入可视化,用图形嵌入进行相似性搜索,从 ArangoDB 导出图形并将图形嵌入保存到 ArangoDB,以及直接从 PyG 数据对象生成图形嵌入。ArangoGraphML 团队也在构建一个 GraphML 平台(企业就绪,以图形为动力的机器学习作为云服务),目前作为测试程序开放。

欢迎对下一版本的任何反馈和功能要求!!

感谢

我要感谢 ArangoDB 的整个 ML 团队在我编写这个包的时候给了我宝贵的反馈。

想联系我: Linkedin

用于太阳能预测的特征工程和深度学习

原文:https://towardsdatascience.com/feature-engineering-and-deep-learning-b90fc863b07

特征工程对 DL 模型有帮助吗

来源:https://unsplash.com/photos/yETqkLnhsUI

当经典的 ML 模型受到非结构化数据的挑战时,它会受到影响。一个特殊的例子是 ImageNet Challenge,最初最先进的技术将使用一些智能的手工制作的功能,然后像 SVM 一样使用强大的分类器。后来这些都被 CNN 的模特超越了。

现在这种手工制作特征的推导是非常直观的,并且是一个费力的试错过程。这是 CNN 模型在自动提取特征方面得分的地方。如果你真的从 30,000 英尺的高度来看深度学习,那么它的核心就是学习表征。隐藏图层是从输入数据中学习新表示的完美示例。到目前为止一切顺利。但是一个懒惰的头脑会用不同的想法来挑战你,也就是说,为什么不混合搭配。也许使用旧世界的直觉,然后将它们与习得的表征结合起来。

这就是我们在太阳能预测的背景下试图回答的问题。这是一个领域(太阳能预测),加尔各答大学数据科学实验室与国家风能研究所合作了一段时间,也是 LISA 实验室活动的一部分(【https://www.lisa2020.org/】T2)。)

我们已经发表了一篇关于太阳能预测的博客,其中描述了基本的问题公式以及一些设计问题和建议。(https://towards data science . com/building-lstm-based-model-for-solar-energy-forecasting-8010052 f0f 5a)。快速回顾一下动机是,太阳能预测的准确预测对于可持续利用是必不可少的。通常,全球水平辐照度(GHI)是实际太阳能电池输出的良好代表。GHI 测量水平面从上方接收的辐射量。这包括直接接收的辐射以及散射的辐射。根据预测的窗口,问题可以分为短期、中期和长期。事实证明,基于可信的天气波动的短期预测(以小时为单位)是最具挑战性的。

为简单起见,我们将此视为单变量预测问题,即 GHI 的先前值用作预测值。LSTM 和 GRU 作为模型最近被广泛用作预测机器。现在,有一个 LSTM 的流行变体,GRUs,被称为双向模型。这些带来了出色的结果以及语义,尤其是在语言预测方面。如果你试图预测一个句子中间的一个单词,你基本上要使用这个单词前面的单词和后面的单词。

在时间序列的情况下,我们没有这种奢侈,因为我们没有后继值,即未来值。有趣的是,如果我们简单地用前一个值代替后一个值,我们仍然会得到更好的结果。典型的设置如下图 1 所示。

图 1:时间序列的双向 GRU(图片来源:作者)

基本上,假设您有一个序列 15,20,22,24,并且您想要预测下一个值,您有一个 GRU,它接受输入 15,20,22,24,通常称为前向 GRU。然后您以相反的顺序使用同一序列的另一种表示,即 24,22,20 和 15,它由另一个 GRU 使用,称为后向 GRU。最终预测是两个 gru 预测的函数。前向模型的输入序列通常被称为前向上下文,后向模型的输入序列被称为后向上下文。

对我们来说,这似乎有点站不住脚,我们想的是我们能不能找到一个比前面的值更好的替代品。因此,我们想用前一天的来代替。例如,如果我们试图预测 5 月 24 日上午 08:00 的 GHI 值,我们可以使用 5 月 24 日上午 07:00、07:15 和 07:45 的值,以及 5 月 23 日上午 08:15、08:30 和 08:45 的值。

事实上,在更一般的设置中,前向输入和后向输入的长度可能不相等。下图显示了这样的设置,我们称之为具有真正双向特征的双向预测模型。

实际上,在我们提出的方法中,我们使用了更长的向前上下文,其中我们不仅使用了 5 月 24 日的 07:00 AM、07:15 AM、07:45 AM 值,还使用了 5 月 23 日的 07:00 AM、07:15 AM、07:45 AM 值。

图 2:具有真正双向特征的双向预测模型(图片来源:作者)

光有直觉是不够的,你需要通过大量的研究/实验来建立直觉。在这个实验中,2016 年的数据用于三个气候带(炎热和干燥,温暖和潮湿,寒冷和多云),六个站分别位于钦奈(泰米尔纳德邦),豪拉(西孟加拉邦),贡图尔(安得拉邦),科达达皮塔(古吉拉特)和阿杰梅尔(拉贾斯坦邦)。

这些结果和实验设置是非常广泛的。要获得“超载”版本,您可以在此访问期刊文章。我们还对提议的具有真正双向特征的双向模型(BD-BLSTM)与称为 ULSTM 的普通单向模型进行了其他几项比较,ul STM 是单向模型的一种变体,具有一些丰富的输入特征,称为 MLSTM,前向和后向模型(BLSTM)具有相同的前置序列的普通双向模型,以及 Rana 和 Abdel 最近的几项工作。

所有模型的结果都用 nRMSE 度量。nRMSE 因其与比例无关而闻名,由下式给出。

nRMSE

图 3:模型对比(图片来源:作者)

如果你在上面的箱线图中观察,很明显,具有双向特征的双向模型在所有气候带中给出了最低的平均误差(偏差)和最低的误差可变性(方差)。

这个故事的寓意是什么?显而易见的是,具有双向功能的双向模型确实有点酷,但这不是我们想要的。相反,重要的是,如果你想称赞你从 ML 到 DL 的理解(智慧的珍珠),你可以改进你的模型,而不是简单地盲目部署深度学习模型。

机器学习的特征工程(2/3)

原文:https://towardsdatascience.com/feature-engineering-for-machine-learning-434c9b4912c6

第 2 部分:特征生成

图片来自 Pixabay皮特·林福思

在关于特征工程的三部分系列的第二部分(第一部分:数据预处理,我们将看到有几乎无限多的方法从现有的构建新的特征,所以一旦你意识到下面描述的基本技术,特征生成中的艺术实际上是获得一种直觉对于给定的问题域尝试什么。

“好的特性可以让简单的模型战胜复杂的模型”

—彼得·诺维格

2.特征生成

对于本文,我们将共同描述特征提取,它通常指特定领域的降维方法,以及特征生成,通常通过 i. 将现有特征映射到新空间, ii .来完成。把多种特征结合成一个复合体, iii。汇总数据以发现模式或 iv。合并辅助数据。我们将根据方法对底层数据类型的适用性对它们进行分组。

2.1 日期和时间

事件通常表现出周期性或季节性。周期性可能表现在多个时间尺度上,因此,根据您的数据,您可能希望将一个时间戳列分解为多个列,例如:分钟、小时、星期几、工作日或周末、月中的某一天、月、季或年。这样做还可以让您使用[pd.DataFrame.groupby()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.groupby)来执行聚合,这本身就是生成新特性的最强大的方法之一。分解时间戳的一个简单方法是使用 Pandas 的字符串方法,例如[pd.Series.str.split()](https://pandas.pydata.org/docs/reference/api/pandas.Series.str.html?highlight=str):

# ‘date’ column in transactions is encoded as “01.04.2022”
transactions_date = transactions[‘date’].str.split(‘.’)# add three new columns to the dataframe
transactions[[‘day’, ‘month’, ‘year’]] = pd.DataFrame(transactions_date.tolist())

一旦创建了这些groupby()列,例如,为了预测产品的未来销售,您可以计算以下新特性并将其添加到您的模型中:I .上周同一天销售的商品数量,ii .从到上月的日均销售额,以及 iii。去年同月销售额。

可以生成的另一个非常有用的特征是时间增量,比如两个特征日期之间的差异。例如,在预测客户流失时,自服务/订购开始、合同到期或最后一次致电客户支持以来的月数。在欺诈检测中,该客户的最后一次信用卡交易可能已经过去了几天。在消费者支出中,指自上一个双周支付期(根据美国劳工统计局的数据,这是最常见的支付期)以来的天数。在医学诊断中,减去出生日期以获得年龄,然后再减去第 20 百分位目标阳性年龄以获得超过发病年龄。

当事件跨多个时区发生时,如果已知每个样本的对应位置,则对每个样本的本地时间进行编码可能是有益的。例如,一家美国在线零售商为 4 个时区(太平洋、山地、中部和东部)的客户提供服务,当预测点击率时,无论是晚上 8 点还是晚上 11 点,客户对推荐或广告的反应都会有所不同。

2.2 地理定位

对于地理定位,比如预测房价,增加新功能的一种方式是补充辅助数据。你可以将距离添加到相关地标:市中心、宗教场所、好学校等。如果地理位置数据已被匿名化(即非绝对坐标),您仍然可以执行聚类,然后计算到聚类质心的距离。

局部最小值/最大值也是用于计算距离的有用参考点,充当期望的或不期望的地理实体的代理。另一个特征是周围的建筑密度,高密度表示受欢迎程度、交通选择的融合等。

2.3 定价

图片由200 度像素点

对于一个算法来说,一件商品标价 5.00 美元和 4.99 美元几乎没有什么区别,但我们知道人类并不理性。因此,例如,如果预测销售额,您可以为以$0.49 或$0.99 结尾的价格添加一个标志(或者为价格的小数部分添加一列,让决策树自己找出模式)。同样,众所周知,某些价格点具有心理共鸣,并充当阻力位,例如 19 美元、49 美元、199 美元,因此添加一个(模 x)功能来帮助您的算法检测它们。

2.4 数值

线性回归不仅限于线性关系,它只需要对独立变量(即特征)呈线性。因此,添加多项式特征将使 LinR 更具表现力,并减少拟合偏差。使添加它们变得轻而易举,甚至支持交互功能,如下所述。

数字特征是添加交互特征(也称为交互术语)的良好候选。这些是通过在两个或多个特征之间执行加法/减法/除法/乘法而形成的。它们对于基于树的模型尤其有益,因为基于树的模型很难提取这种依赖性。

当然,对我们来说,困难在于创造这种互动的方式有无数种,只有一些是有用的。例如,在给定价格和建筑面积的情况下计算价格/平方英尺,在给定人口普查区块组规模和家庭数量的情况下计算平均家庭规模,将压力乘以温度以预测化学反应的速率。

t 型 SNE 通常用作可视化辅助工具,但你也可以使用它的投影作为特征。但是要注意,t-SNE 对超参数(困惑)值非常敏感,所以你需要实验来找到最好的方法。如果您确实使用 t-SNE 作为一个特性,不要使用 scikit-learn 的实现(sklearn.manifold.TSNE ),因为它没有. transform()方法。取而代之的是使用[openTSNE.TSNE.transform()](https://opentsne.readthedocs.io/en/latest/api/index.html),它不仅更快,更重要的是支持新点的嵌入。如果只投影到二维对你的数据来说太有限,你可以试试 UMAP

如果特征直方图中有多个不同的峰值,连续变量的分桶可能会有用。经度与房价的关系图没有显示可辨别的关系,但是绘制直方图显示了多个峰值,对应于位于纵向“带”内的城市-这些带可用作宁滨连续要素分类的阈值。

2.5 分类

分类交互特征对线性和 k-NN 模型有用,但对基于树的模型无效。它们是通过字符串连接两个分类特征以形成新的组合而形成的,例如连接“性别”∈ {M,F}和“教育水平”∈ {1,2,3,4}以给出“性别-EDC”∈{ M1,F1,M2,…}。好的候选特征是在相邻的决策树节点上频繁引用的特征。

分类目标编码(也称为似然或均值编码)在 Kaggle 竞赛上非常流行。它是每个分类类的编码,作为目标类值的某个函数。常见的功能包括:

  • 均值:P(Y=1 | X_i)
  • 证据权重(WOE): log( P(Y=1 | X_i) / P(Y=0 | X_i))
  • 计数:#(Y=1 | X_i)
  • 差值:#(Y = 1 | X _ I)#(Y = 0 | X _ I)

例如,可以使用pd.df.groupby('feature')['y'].mean()计算平均值

由于最大深度限制(在每个节点上只能走两条路中的一条),决策树在处理高分类基数(许多唯一值)时有困难——对于相同的树深度,目标编码会导致更低的损失。

目标编码的主要问题是严重的过拟合数据泄漏的风险。发生这种情况的一种方式是当训练集和验证/测试集之间的数据分布发生变化时(例如,目标平均值发生变化)。k 倍交叉验证和加法平滑是减轻这种风险的两种方法。

2.6 统计汇总

这是从现有要素创建新要素的最有效方法之一。必须做出三个选择:I .根据什么分组,ii .如何聚合各组,最后,iii。在哪个键上连接聚合统计信息。以下是一些例子:

  • 计算在同一页面(分组)上显示给用户(加入)的所有广告的最小/最大/标准偏差(聚合)成本。可用于通过提供上下文来预测特定广告的点击率,即,该页面上更昂贵的广告将被更突出地展示,因此将对放置在同一页面上的更便宜的广告产生负面影响
  • 用户在会话期间已经查看的页面数量,即推荐/广告疲劳。患者的症状数量,即任何一种症状可能不明显,但多种症状可能明显
  • 对于去年的每个客户,两次连续交易之间的中间时间、每月交易的平均次数、每个消费类别费用的平均值和标准差,所有这些都有助于预测欺诈,方法是告知卡通常的使用频率、使用内容、金额和使用模式(临时与定期自动支付)

熊猫的“T1”对于计算这些统计数据是必不可少的,但群体可能还需要根据数字特征即时合成,例如在设定半径内房屋的平均价格/平方英尺。

有时数据分散在多个表中,在这种情况下,用从其他表收集的信息补充主(如交易)表,例如,如果商家与最近有争议的交易高峰有关,则在交易表中添加一个标志。

2.7 文本

在第一部分中,我们对原始文本进行预处理,并将其标记成小块文本。现在我们需要将这些组块序列转换成数字,这是矢量器的工作。

一个词袋(BOW,也称为计数)矢量器统计每个唯一标记在文档中出现的次数。通常可以选择忽略出现频率太低或太频繁的单词。术语频率(TF)矢量器对原始计数进行归一化,以显示每个术语构成的文档比例(即矢量元素总和为 1)。TF-IDF 矢量器进一步将 TF 乘以每个术语在文档语料库中出现频率的倒数的对数。

单词和句子嵌入(例如 Word2vec、GloVe、fastText)在文本特征生成方面提供了更高层次的复杂性。注意,由于这些被训练的方式,即无监督训练,所得到的单词嵌入的数学“接近度”反映的不是语义相似性,而是单词的共现,例如“爱”和“恨”在一个句子中频繁地一起出现,因此将在嵌入空间中紧密地映射在一起,即使它们是反义词。

还要注意,这些简单的嵌入是静态的,对于每个单词,只有一个对应的嵌入。因此,它们不能进行语义消歧,即black bearbear marketbear arms中的“熊”将被分配相同的矢量嵌入。

当涉及到嵌入时(比如使用 Word2vec),您可以选择是使用预训练嵌入,还是让模型使用反向传播在您的数据上学习它自己的嵌入。如果您希望创建一个总结句子的单一特征,句子也可以有嵌入,通过将单个单词向量平均在一起,使用[CLS]标记的嵌入,或者使用类似 Doc2vec 的东西。对于短语(如“煎锅”),尝试 sense2vec

创建附加文本特征的最后一个技巧是对每段文本执行双重翻译(例如英语→西班牙语→英语),然后使用集成对两个语料库进行预测。

2.8 图像

图片由 Jan Tik 标注 CC BY 2.0

在大型数据集上训练的预训练模型(通常是 CNN)学习将整个图像表示为其最终层中的潜在表示。通过截断“头部”,但保留“身体”,这些模型可以用作特征提取器。馈入和馈出图像是图像嵌入,常见的输出尺寸为 768 或 2048。

您不仅可以从不同的模型架构(例如 VGG16、ResNet50、MobileNet)中选择,还可以根据在图像的域特定子集上训练模型来选择权重。为什么这行得通是因为没有免费的午餐定理:没有放之四海而皆准的最佳解决方案。TensorFlow Hub 提供了一系列 ResNet50 模型,这些模型具有相同的架构,但针对 ImageNet 类别的不同子集进行了培训。使用在花子树上训练的权重,我发现我能够在 Oxford102 数据集上获得比使用在整个 ImageNet-1K 上训练的权重显著更高的准确性(即相关性胜过丰度)

对于最先进的技术,正如变形金刚通过注意力的应用彻底改变了自然语言处理,人们也可以使用预训练的视觉变形金刚( ViT )来提取(768 到 1024 维)图像的矢量表示。

2.9 时间序列

对于时间序列数据,除了那些已经在【第 2.1 节】中提到的,人们可以通过添加一个或多个滞后特征来生成新的特征。简单地将数据延迟或移位(例如[pd.DataFrame.shift()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.shift))一段设定的时间。使用自相关,例如[statsmodels.tsa.stattools.acf()](https://www.statsmodels.org/stable/generated/statsmodels.tsa.stattools.acf.html),确定最具预测性的滞后期。

另一种技术也有消除时间序列趋势的额外好处,就是将时间序列编码为与某个时期的或增量。对于具有强烈趋势的时间序列,例如长期的股票价格,最好使用比率指标或百分比变化,而不是绝对变化,因为这能更好地反映价格的变化。这两种转换(差异或比率)也可以应用于目标变量(让模型预测第二天的变化,而不是绝对值)。

移动窗口聚合(也称为跟踪指示器)也可以添加上下文。例如,价格的移动平均线可以用来检测市场趋势。同样,使用不同的汇总时间跨度是有帮助的,例如交易者经常使用 50 天和 100 天的 SMAs。也可以使用扩展窗口,但不太常见。

然后是特定于领域的特征,例如添加一个特征来指示与前一天的收盘相比有多大的涨跌差距。MACD 指标是用两个指数移动平均线(EMA)的差值计算出来的,用来检测趋势何时加速。对于与天气相关的时间序列,计算露点(温度和压力的函数)。

时域数据可以转换到频域。单独执行傅立叶变换更属于特征提取的范畴,而不是特征生成的范畴,因为变换后的数据不再在时间上锚定,因此不能与时域特征一起使用,如上所述。然而,时间可以被结合回来,例如在光谱图的情况下,我们可以跟踪功率谱密度作为时间的函数的变化。

2.10 表征学习

表征学习(RL)是指使用非参数(即非统计)方法学习潜在表征,以提取特征。已经描述了一些例子,例如单词嵌入和基于 CNN/ViT 的图像特征提取器。

强化学习已经非常成功地应用于计算机视觉。例如,SimCLR 可用于使用无监督学习从无标签数据中学习视觉表示。然后,通过引入一小部分标签,可以利用学习到的表示以惊人的准确度对数据集的其余部分进行分类。

特征提取器对于执行相似性搜索特别有用。这是因为一旦被训练(或者如果使用预训练的特征向量),提取的特征向量对于一组输入是不变的。在相似性搜索中,您是根据相似性度量(如余弦相似性)将一个样本与整个数据库进行比较。通过预先计算所有对应于原始输入的特征向量一次,你可以非常有效地存储并随后使用一个特殊的数据库如 FAISS 执行最近邻相似性搜索。

本系列关于特征工程的第二部分到此结束。我们现在已经积累了大量的特性,所以在第三部分,我们将把注意力转向特性选择,在这里我们看看如何将小麦从谷壳中分离出来,以确保我们不会过度拟合我们的数据。

机器学习的特征工程(1/3)

原文:https://towardsdatascience.com/feature-engineering-for-machine-learning-a80d3cdfede6

第 1 部分:数据预处理

图片由来自皮克斯拜皮特·林福思拍摄

深度学习的时代已经普及了端到端的机器学习方法,其中原始数据进入管道的一端,预测从另一端出来。这无疑加速了某些领域中的模型推理,尤其是在计算机视觉管道中,例如,单次检测器的帧速率高于依赖区域建议然后进行对象检测的模型。复杂模型自动提取特征的能力使得牺牲计算资源以节省人力资源成为可能。

这种方法意味着机器学习实践者越来越多地通过模型而不是磨练他们的数据。但是,当轻松的收益被收获时,模型大小加倍只能勉强维持一点点的性能改进。这是手工制作功能可以获得更好回报的时候。

“应用机器学习基本上是特征工程”

—吴恩达

在某种程度上,视觉数据的丰富性、高维性和丰富性使得自动化和手工制作的特征之间的权衡成为可能。当处理缺乏数据或特征不丰富的数据时,这种情况对于数据科学家来说太常见了,他们的任务是根据十几个特征做出预测,特征工程对于补充和梳理有限数据中存在的所有可用“信号”至关重要;以及克服流行的机器学习算法的限制,例如,基于乘法或除法特征交互来分离数据的困难。

在 Kaggle 竞赛中,最优秀的团队赢得比赛不仅仅是因为模型选择、集成和超参数调整,而是因为他们设计新功能的能力,有时看似无中生有,但更多时候是源于对数据的真正理解(带来领域知识)、辅助数据的补充,以及顽强、创造性(更像艺术而不是科学)但乏味的构建和测试新功能的试错工作。

在这个由多个部分组成的系列中,我们将讨论完整特征工程管道的三个部分:

  1. 数据预处理
  2. 特征生成
  3. 特征选择

这三个步骤是按顺序执行的,但有时对于某项技术是构成数据预处理、特征提取还是生成会有歧义。但我们在这里并不拘泥于语义…相反,我们将专注于调查任何优秀的机器学习实践者和数据科学家可以在项目中运用的所有技术。

这一系列文章的目的是提高对这些有时被遗忘的问题的认识,特别是在深度学习和十亿参数模型的时代,这些技术要永远留在脑海中,并知道一些可以极大地方便其使用的库函数。描述每种技术的内部工作原理都需要一篇文章,其中很多可以在走向数据科学上找到。

1.数据预处理

1.1 数据清理

“垃圾进,垃圾出。”

在 EDA 过程中,首先要做的一件事就是检查并移除常量特性。但模型肯定能自己发现这一点吗?是,也不是。考虑一个线性回归模型,其中非零权重已被初始化为常数特征。然后,这一项作为次要的“偏差”项,看起来没有什么害处…但是如果“常数”项只在我们的训练数据中是常数,并且(我们不知道)后来在我们的生产/测试数据中呈现不同的值,那么就不是了。

另一件需要注意的事情是重复的特性。当涉及分类数据时,这可能并不明显,因为它可能表现为不同的标签名称被分配给不同列中的相同属性,例如,一个特征使用“XYZ”来表示分类类,而另一个特征表示为“ABC”,这可能是由于列是从不同的数据库或部门中挑选出来的。[pd.factorize()](https://pandas.pydata.org/docs/reference/api/pandas.factorize.html)可以帮助识别两个特征是否同义。

接下来,冗余的高度相关的特征。多重共线性会导致模型系数不稳定,并且对噪声高度敏感。除了对存储和计算成本的负面影响之外,当考虑权重正则化时,冗余特征削弱了其他特征的有效性,使得模型更容易受到噪声的影响。[pd.DataFrame.corr()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.corr.html)可用于识别相关特征。

复制可能不仅发生在列之间,也可能发生在之间。此类样本复制会导致训练期间的数据失衡和/或过度拟合。[pd.DataFrame.duplicated()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.duplicated.html)将在第一次出现之后的每个重复行中返回一个具有真值的序列。

1.2 数据洗牌

区分预处理过程中的洗牌和训练过程中的很重要。

在预处理过程中,在将数据集分成训练/验证/测试子集之前,对其进行洗牌是非常重要的。对于小型或高度不平衡的数据集(例如,在异常、欺诈或疾病检测中),利用[sklearn.model_selection.train_test_split()](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html)stratify on 功能确保您的少数目标在所有子集中的分布一致。[pd.DataFrame.sample(frac=1.0)](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.sample.html)可用于轻松洗牌。

对于训练,大多数 ML 框架将为您洗牌,但重要的是要了解它是在进行一次性洗牌,即仅在加载数据集时,还是在逐批的基础上继续这样做。后者对于获得最低的训练损失是优选的,但是会导致较慢的训练,因为小批量的数据不能被缓存并在下一个时期重新使用。

1.3 数据插补

这是个大话题!缺失的特征应仔细处理。

缺失的特征可能不会立即显现出来,所以仅仅使用[pd.DataFrame.isna.sum(axis=0)](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.isna.html)可能无法将它们全部显现出来。可以使用特殊(非空)字符串或数值(例如,“-”、0 或-999)来表示缺失字段。您正在使用的数据集可能已经由某人进行了预处理和预估算。幸运的是,检测缺失特征可以通过绘制每个特征的直方图来完成——异常的异常峰值表明使用了特殊值,而分布中间的峰值则表明已经进行了均值/中值插补。

下一个问题是如何估算缺失字段。最常见和最直接的方法是用模式(针对分类特征)、均值(针对没有大量异常值的数字特征)或中值(其中异常值明显扭曲均值)来替代缺失值。

即便如此,尤其是如果你认为这个特征很重要,不要盲目替换整个数据集的均值/中值/众数。举例来说,在泰坦尼克号的数据集中,几名乘客漏掉了他们的年龄。不要用船上所有乘客的平均年龄来估算所有这些乘客,我们可以通过认识到船上乘客等级之间的平均(和中值)年龄非常不同来得到更精确的估计。

表 1:按乘客等级和性别划分的乘客年龄中位数

事实上,由于该数据集中没有乘客性别的缺失值,因此您可以在输入时更进一步,根据 I .票价等级和 ii 替换年龄中位数。缺少年龄值的每个样本的性别。

对于一个时间序列,我们不应该使用均值/中位数替代来估算缺失样本,因为这总是会导致序列发生不切实际的突变。相反,使用值重复或插值进行估算。像中值滤波或低通零相位滤波这样的信号处理去噪方法也可以用来填充训练数据中的小间隙;但是请记住,非因果方法不能在生产过程中使用,除非模型的延迟输出是可接受的。

一种替代方案是根本不估算,而是添加二进制标志,以允许下游学习算法自行学习如何处理这种情况。这样做的缺点是,如果丢失的值分布在许多特征上,您可能必须添加更多这样的低信号特征。注意,XGBoost 开箱即用地处理NaN ,所以在使用它时不需要添加缺失数据列。一般来说,决策树可以通过将缺失值设置为决策节点可以轻松拆分的下/上限值,来处理缺失值的特殊值标签编码。

另一种流行的方法是运行 k-NN 来估算缺失值。使用神经网络进行插补是另一种流行的方法。例如,可以对自动编码器进行训练,以在输入丢失的情况下再现训练数据,一旦训练完成,其输出就可以用于预测丢失的特征值。然而,使用最大似然法学习插补可能很棘手,因为很难评估插补模型的超参数(例如 k 的值)如何影响最终模型的性能。

无论采用何种插补方法,只要有可能,在数据插补之前,始终在之前执行特征生成(在本系列的第二部分中讨论),因为这将允许更精确地计算生成的特征值,特别是在特殊值编码用于插补时。当生成新要素时,知道相关的要素值缺失就为特殊处理敞开了大门。

1.4 特征编码

序数特征可能有整数值,但与数值特征不同的是,虽然序数服从传递比较关系,但不遵守减法或除法的算术规则。

有序特征,如星级,通常具有高度非线性的“真实”映射,对应于强双极分布。也就是说,4 星与 5 星评级之间的定量“差异”通常很小,远远小于 4 星与 2 星评级之间差异的一半,这会混淆线性模型。

因此,线性模型可能受益于序数值赋值的更线性的重映射,但是另一方面,基于树的模型能够本质上处理这种非线性。最好将序号编码保留为一个单一量化特征(即“列”),而不是虚拟化,因为虚拟化会降低其他预测特征的信噪比(例如,当应用参数正则化时)。

分类特征的处理取决于你的模型是否是基于树的。基于树的模型可以使用标签编码(即表示类成员的固定字符串或整数),不需要进一步的预处理。非树方法要求分类特征是一键编码,这可以使用[pd.get_dummies()](https://pandas.pydata.org/docs/reference/api/pandas.get_dummies.html)[sklearn.preprocessing.OneHotEncoder()](http://sklearn.preprocessing.onehotencoder)来执行。避免删除第一列(即不要指定drop=’first’),除非你正在处理一个二进制类别(即使用drop=’if_binary’),因为删除产生的问题比它解决的问题还要多。

一键编码的替代方法是使用或补充频率编码。这包括计算对应于每个类别的目标变量的标准化频率。例如,如果该类别中 40%的样本导致目标值为 1,则将值 0.4 分配给二进制分类特征。当分类特征与目标值相关时,这样做是有帮助的。

编码分类特征的另一种方式是使用分类嵌入。这尤其适用于高基数分类要素,如邮政编码或产品。如同单词嵌入一样,这些嵌入使用密集的神经网络来学习。结果分析表明这些连续嵌入对于聚类和可视化也是有意义的,同时减少过拟合。

处理分类特征的最后一点是,如果在验证/测试子集中遇到一个看不见的类别,该怎么办。在这种情况下,就像对待缺失特征一样对待它,或者将其指定为“未知”保留类别。

1.5 数字特征

缩放归一化对于基于树的方法来说不是必需的,但是对于实现低训练损失、快速收敛以及为了使权重正则化正常工作来说是必不可少的。选择其中之一。

缩放[sklearn.preprocessing.MinMaxScaler()](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.MinMaxScaler.html)速度很快,通常是图像数据所需的全部。然而,最小-最大缩放会受到异常值的显著影响(即使只有一个异常值!)或编码为正常特征范围之外的值的缺失值。

只要异常值的比例很小(即,如果异常值没有显著扭曲平均值和标准偏差),归一化[sklearn.preprocessing.StandardScaler()](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.StandardScaler.html)对异常值更稳健。

数字特征通常可以受益于变换对数变换,np.log(1 + x),是一种非常强的变换,当一个特征遵循幂律关系时,或者当离群值分布中存在长尾时,这种变换特别有用。平方根变换,np.sqrt(x)不太强,可以作为有用的中间变换来尝试。由于使用了 lambda 超参数, Box-Cox [scipy.stats.boxcox()](https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.boxcox.html)变换允许从线性传递函数平滑过渡到高度非线性传递函数,并且通常用于将偏斜分布(例如,作为年龄函数的 COVID 测试阳性率)转变为更加正态的分布,这是许多传统 ML 算法(如 NB、LogR 和 LinR)做出的基本假设。[注意:x > = 0 被假定用于所有上述变换]。

1.6 地理定位功能

基于树的方法有时可以受益于地理位置坐标上的旋转变换。例如,South-of-Market (SoMa)是旧金山的一个街区,与市场街接壤。然而,市场街不是南北走向或东西走向,而是西南-东北走向。因此,决策树将很难清晰地分割出这个邻域(当树的深度受限时,这是经常需要的),因为树只能绘制与轴平行的分割线(即与经度轴或纬度轴平行)。执行旋转变换的困难在于选择旋转坐标的轴点,因为可能没有全局最优的轴点。

一种解决方案是执行笛卡尔坐标到极坐标 T2 的转换。例如,巴黎市被划分为几个区,这些区围绕市中心大致呈环形分布。或者,可以执行聚类,并创建新的分类特征来指示点属于哪个聚类,之后可以使用极坐标来编码每个点相对于其聚类质心/核的位置。

1.7 时间特征

数据集中的时间可能显示为 UTC/GMT 时间,而不是本地时间,即使所有事件都属于同一个(不同的)时区。即使时间戳以本地时间给出,对时间特征执行时移也可能是有益的。

例如,由于较高的需求和较低的供应,拼车费用往往在一天中“较晚”时(特别是 Fri/星期六/星期日)较高。然而,任何深夜狂欢者都知道,派对不会在午夜停止。由于时间的推移,模型很难辨别 00:30 是否“晚于”,甚至“接近”23:30。然而,如果执行时间转换,并且在一天中活动量最少的时间内发生棘手的 23:59H → 00:00H 回绕,那么线性模型将回归得更好,而基于树的模型将需要更少的分支级别。

1.8 文本

图片来自 PixabayGerd Altmann

可以说,文本是需要最多预处理的特性。我们从变换开始,变换有很多。

小写对于简单模型来说是必要的,它是文本标准化的最基本形式,有利于产生更强、更稳健的信号(由于出现的词频更高),同时减少词汇量。对于自带分词器的更高级的经过预训练的语言模型 (LM),最好让 LM 对原始文本进行分词,因为大写(例如用[bert-base-cased](https://huggingface.co/bert-base-cased))可能有助于模型在句子解析、命名实体识别(NER)词性(词性)标注方面表现更好。

词干词汇化提供了与小写相同的好处,但是更复杂,运行时间也更长。词干使用固定的规则来删减单词,这些规则不考虑单词在句子中的上下文和用法,例如university被删减为univers,但universal也是如此。词汇化考虑了上下文并需要使用大的 LMs,因此比词干化慢。然而,这要准确得多,例如,universityuniversal仍然是独立的词根。考虑到当今可用的计算资源, Spacy 的作者认为准确性在生产中最重要,因此该库只支持词汇化。

收缩扩展是具有相同动机的另一种形式的文本规范化。这里can’tyou’ll扩展为can notyou will。简单的基于计数/频率的模型受益于这种标准化,但是像 Spacy 中的那些 LMs 通过使用子词标记化 ( can’t被标记化为ca然后是n’t)来处理缩写。

文本规范化旨在将文本和符号转换为规范形式,以便模型可以更好地学习。他们转换缩写(如 BTW)、拼写错误(如' definately ')、音调符号(如 café/naive→café/naive)、表情符号(如|:-)|;) | 🙂→ <SMILE>,ROFL | LOL | LMAO |😆→ <LAUGH>)等。如果没有文本规范化,许多 NLP 模型将很难理解 Twitter 和社交媒体上的帖子!

接下来是过滤——停用词、标点符号、数字、多余的空格、表情符号(不执行情感分析时)、HTML 标签(例如< br >)、HTML 转义字符(例如'&amp;','&nbsp;')、网址、标签(例如#黑色星期五)和提及次数(例如@xyz)

最后的预处理步骤是标记化。简单的标记化可以使用 python 正则表达式来执行,但是 NLP 框架提供了用 C/C++或 Rust 编写的专用标记化器,性能更高。当使用预训练的 LM 时,例如来自拥抱脸的那些,使用与 LM 训练时使用的完全相同的记号赋予器(和权重)是至关重要的。

1.9 图像

随着 CNN 的流行,预处理图像现在不太常见。然而,在没有 GPU 的资源受限的硬件中,或者当需要高帧速率时,这些技术形成了传统计算机视觉处理流水线的基本功能。

色彩空间转换可以用简单的 CNN 提供轻微的性能提升。例如,这项研究发现,将 CIFAR-10 数据集转换到 Lab 颜色空间可以提高大约 2%的分类精度,但同时使用多个颜色空间可以获得最佳结果。已经发现,具有分离的色度和亮度通道的色彩空间(例如 YUV)有助于图片彩色化和风格转换。我个人发现,为特定领域定制的专门颜色转换(例如,用于组织病理学的苏木精-伊红-DAB)对提高模型性能特别有帮助。

直方图均衡,尤其是自适应直方图均衡(如 CLAHE),经常在医学成像上进行,以提高视觉对比度。当图像中的光照不均匀且区别特征相对于整个图像帧较小时,例如检测乳房 x 线照相图像中的癌组织时,这种方法特别有用。在视网膜眼底成像中,图像采集过程中图像质量的可变性很高,执行非均匀照明校正已被证明可提高分级精度。

传统的 CV 特征提取技术包括局部二元模式( LBP )、方向梯度直方图( HOG )和 Gabor 滤波器bank。在非 CNN 模型上成功使用这些特征提取器已经有很长的历史了。将这些较老的技术(例如可学习的 Gabor 滤波器)与标准卷积层相结合,可以在某些数据集(例如 D ogs-vs-Cats )上实现更快的收敛和更高的精度。

本系列关于特征工程的第一部分到此结束。在第二部分中,我们将注意力转向特征生成,在这里我们将着眼于提取和合成全新的特征。这是艺术与科学真正相遇的地方,也是将卡格尔大师与新手区分开来的地方!

R 语言中机器学习的特征工程

原文:https://towardsdatascience.com/feature-engineering-for-machine-learning-in-r-2ed684727566

从数据集中提取有价值信息的重要过程

杆长Unsplash 上拍照

本文是故事掌握 R 编程基础的续篇。在第一篇文章中,我介绍了 R 的构建模块,它将帮助你了解这门语言。理解和学习真的很直观。在这篇文章中,我将重点关注特征处理,它代表了任何数据科学项目的相关部分。如果没有干净的数据,任何机器学习模型的努力都将是徒劳的。让我们开始这段旅程吧!

目录:

  1. 转换为因子
  2. 添加和删除列
  3. 从连续特征到分类特征
  4. 查找缺失值
  5. 处理缺失值

要求

在之前的帖子里,我建议你同时安装 RR studio 。R 是一门语言,而 R studio 是一个 IDE,允许以一种更简单的方式使用 R。

介绍

让我们从从 Kaggle 导入数据集银行流失模型开始,并可视化前六行[1]。

df <- read.csv('Bank_churn_modelling.csv',header = T)
head(df)

作者插图

你能注意到的第一件事(如果你以前使用过 Python)是我们不需要导入任何库,很漂亮,不是吗?让我们尝试查看有关数据集的其他统计数据和信息:

 summary(df)

作者插图

summary是用于打印所有特性的描述性统计的功能。从输出来看,值得注意的是:

  • 大多数变量被认为是数字。但是像 Excited 和 HasCrCard 这样的变量,范围在 0 到 1 之间。然后,要把这些特征转化为因子。
  • 姓氏、地域、性别是性格变量。因此,输出会显示其他信息,包括样本数量(长度)、类的类型和模式。我们也应该把地理和性别转换成因素变量。
str(df)

作者插图

str提供了一个更紧凑的输出,总结了数据集的结构。它告诉我们有 1000 行和 14 列。大多数变量包含数值/整数值,而其余的特征是字符变量。

1.转换为因子

正如我们在上一段中看到的,我们必须进行更改,将一些变量转换为因子。你可能想知道是什么因素。在 R 语言中,因子是专门用于将元素分类的向量类型。换句话说,因素是分类变量,可以有两个或更多的层次。这些级别可以包含字符串和整数。

df$Geography <- as.factor(Geography)
df$Gender <- as.factor(Gender)
df$HasCrCard <- as.factor(HasCrCard)
df$IsActiveMember <- as.factor(IsActiveMember)
df$Exited <- as.factor(Exited)
str(df)

作者插图

如果我们再次使用str函数很好地转换了变量,我们可以很容易地检查。为了可视化因子的级别,我们可以使用 levels 函数:

levels(Geography)
# "France"  "Germany" "Spain"

该数据集仅包含法国、德国和西班牙的客户。

2.添加和删除列

添加新列的更简单的方法是给整个新变量分配一个值。例如,让我们创建一个用 NA 填充的新列,NA 是一个逻辑常数,表示 r 中缺少的值。

df$newcol <- NA
df[1:5,8:15]

作者插图

为了更容易可视化,我选择了数据集的一个子集,前 5 行和后 8 列。添加列的另一种方法是使用以下语法:

df['newcol'] <- NA

因此,我们可以在方括号中指定变量,而不是使用$运算符。要删除一个列,我们可以将其设置为 NULL,这表示 R:

df$newcol <- NULL
# alternative df['newcol'] <- NULL
head(df)

作者插图

我们打印了前五行以检查是否删除了该列。真的消失了!

3。将连续变量重新编码为分类变量

假设我想基于 EstimatedSalary 的值创建一个新变量。目标是将估计工资的范围可视化为区间。这可以通过使用cut功能来实现:

df$estsalaryclass<-cut(df$EstimatedSalary,breaks = seq(0,max(df$EstimatedSalary)+1,len=4))
levels(df$estsalaryclass)
# [1] "(11.6,6.67e+04]"     "(6.67e+04,1.33e+05]" "(1.33e+05,2e+05]" 

作者插图

为了创建间隔,应用 seq 函数来创建三个不同的级别。它接受序列的起始值、结束值和长度作为输入。

我们还可以向指定参数标签的箱添加标签:

df$estsalaryclass<-cut(df$EstimatedSalary,breaks = seq(0,max(df$EstimatedSalary)+1,len=4),
                       labels = c('poor','middle','rich'))
levels(df$estsalaryclass)
# [1] "poor"   "middle" "rich"
df[1:5,c('EstimatedSalary','estsalaryclass')]

作者插图

从图中,您可以推断出因子级别的名称是在指定界限后创建的。

我们还可以注意到,默认情况下,间隔在左边打开,在右边关闭。这意味着只有较高的值包含在界限中,而最低的值被排除。

如果我们希望区间在左边关闭,在右边打开,我们需要将参数 right 设置为 FALSE:

df$estsalaryclass<-cut(df$EstimatedSalary,breaks = seq(0,max(df$EstimatedSalary)+1,len=4),right = FALSE)
levels(df$estsalaryclass)
[1] "[11.6,6.67e+04)"     "[6.67e+04,1.33e+05)" "[1.33e+05,2e+05)"

作者插图

4.查找缺少的值

r 语言提供了is.na函数来检查数据集中是否有缺失值。要计算数据集的缺失值,我们可以对它们求和:

sum(is.na(df))
# [1] 0

由于数据框不包含缺失值,我们可以手动添加它作为练习:

df[5,'Age'] = NA
sum(is.na(df))
# [1] 1

你大概在想is.na功能到底在做什么?让我们打印这个函数的输出:

head(is.na(df))

作者插图

它返回一个包含表示缺失值的布尔值的数据框,其中 TRUE 表示我们有一个 NA 值。要返回每列缺失值的数量,我们可以使用forcat函数:

for (i in 1:length(df))
{cat(c(colnames(df[i]),':',sum(is.na(df[,i])),"\n"))}

作者插图

for用于迭代列,而cat用于打印输出。在这种情况下,cat 函数更适合打印,因为它允许在同一行显示多个值。从输出中,我们可以很容易地看到,只有年龄列中缺少一个值。

为了显示包含 NA 值的列的行索引,我们可以使用which函数:

which(is.na(df[,'Age']))
#[1] 5

该函数给出逻辑向量中真实元素的位置。出于这个原因,我们只指定列向量作为输入,而不是整个数据帧。

5.处理缺失值

处理缺失值的更简单的方法是删除包含 NA 值的行:

df_notna<-na.omit(df)
sum(is.na(df_notna))
# [1] 0

na.omit轻松删除有 NA 的行,返回一个没有丢失值的数据帧。

但是删除丢失的值并不总是最好的解决方案。另一种方法是用列的平均值代替 NA 值:

avg_age <- round(mean(df$Age,na.rm=TRUE))
df$Age<-ifelse(is.na(df$Age),avg_age,df$Age)

作者插图

ifelse(test,yes,no)返回一个与年龄变量形状相同的向量。如果测试的条件为真,则该列的值将被年龄的平均值替换。否则,返回值将与作为输入的列中的值相同。

摘要

  • strsummary用于可视化关于数据帧的信息
  • printcat都有助于显示输出。
  • as.factor用于将变量转换成因子
  • cut通过将特征范围划分为区间,将连续变量转换为分类变量
  • is.na返回包含布尔值的数据帧,其中 TRUE 表示单元格中存在 NA
  • which显示矢量中包含的真实元素的位置
  • na.omit删除数据帧中带有 NA 的行
  • ifelse(test,yes,no)是一种更简洁、更快速的 if-else 语句。

最终想法:

我希望这篇教程对你有用。我发现有必要写这篇文章,因为没有很多资源讨论 r 的特性工程。我没有涵盖所有的方面,因为我将在接下来的文章中涵盖其余的方面。感谢阅读!祝你有愉快的一天。

参考文献:

[1]https://www . ka ggle . com/sanjanavoona 1043/bank-churn/version/1

你喜欢我的文章吗? 成为会员 每天无限获取数据科学新帖!这是一种间接的支持我的方式,不会给你带来任何额外的费用。如果您已经是会员, 订阅 每当我发布新的数据科学和 python 指南时,您都会收到电子邮件!

从图像数据中提取特征的系统方法

原文:https://towardsdatascience.com/feature-engineering-for-machine-learning-with-picture-data-d7ff8554920

对于机器学习算法

解释维数灾难的插图(作者图片)

特征工程是获取原始数据并提取对建模有用的特征的过程。对于图像,这通常意味着提取颜色、纹理和形状等信息。进行特征工程有多种方法,您采用的方法将取决于您正在处理的数据类型和您试图解决的问题。

但是我们为什么需要它的图片呢?

图像封装了大量信息,但这是有代价的:高维数。例如,具有 3 个通道(红、绿、蓝)的尺寸为 200×100 像素的小图片已经表示了 60000 维的特征向量。

这需要处理很多事情,而且我们正面临着维数灾难。我们稍后会对此进行更多的讨论。

图片的维数示例(图片由作者提供)

在这篇文章中,我们将看看如何降低图片的维度来对抗维度的诅咒。

维度的诅咒

“维数灾难”是一个术语,用来描述在处理具有大量维度的数据集时出现的问题。

一个原因是,准确了解数据的基本分布所需的数据点的数量随着维度的数量呈指数增长。换句话说,如果我们有一个包含 100 个特征的数据集,我们可能需要大约 1000 甚至 10000 个数据点才能有很好的机会准确学习。

为了更好地理解维数灾难,我喜欢举一个二维 k 近邻图的例子,如下图所示。

k 近邻图可视化(图片由作者提供)

但是如果所有的点都是等距的,会发生什么呢?这是一个非常不可能的场景,但它(在某种程度上)显示了当我们试图计算具有许多维度的特征之间的欧几里德距离时通常会发生什么。

等距点的最近邻问题(图片由作者提供)

为了理解维度的数量如何影响我们的距离度量,我们可以看一下内接在超立方体中的 n 维球(n 球)内部和外部的体积之比。

超立方体中 n 球内外的体积(图片由作者提供)

我们可以在此图中观察到,n 球外部的体积将占据大部分空间。这是非常违反直觉的,不像我们习惯掌握的二维或三维空间。

如果我们在超立方体中均匀分布点,它们中的任何一个都不太可能落入内接的 n 球中。

这将给人这样的印象,即超立方体中的所有点将离 n 球的中心非常远,并且看起来是等距离的,并且集中在超立方体的长尖角上。这将导致我们的基于距离的算法容易受到输入特征上的噪声的影响。

那么,如何才能解决呢?

缩小图像尺寸

降低特征向量维数的一个简单方法是通过降低图像的分辨率,利用抽取(下采样)来减小图像的大小。

如果颜色分量不相关,我们也可以将图片转换为灰度,以将数字维度除以三。但是还有其他方法可以减少图片的尺寸,并潜在地提取特征。例如,我们可以使用小波分解。

小波分解是一种在空间和频率上分解信号的方法。就图片而言,这意味着将图像分解成水平、垂直和对角线分量。

小波分解示例(图片由作者提供)

方向梯度直方图

HOG 特征描述符是在计算机视觉和图像处理中用于检测数字图像中的对象的流行技术。在 Dalal 和 Triggs 于 2005 年展示了这种描述符的效率之后,HOG 描述符变得流行起来,该描述符专注于静态图像中的行人检测。

HOG 描述符是一种特征描述符,它通过计算图像中亮度梯度的分布来编码对象的形状和外观。

在我们的情况下,最重要的参数是每个单元的像素数,因为它将为我们提供一种方法来找到维度数量和图片中捕捉的细节数量之间的最佳平衡。

8×8 像素单元的方向渐变直方图示例(图片由作者提供)

16 乘 16 像素单元的方向渐变直方图示例(图片由作者提供)

对于上面的示例,输入图像具有 20,000 个维度(100×200 像素), HOG 特征对于 8×8 像素单元具有 2,400 个维度,对于 16×16 像素单元具有 576 个维度。分别减少了 88%和 97%。

主成分分析

我们还可以使用主成分分析(PCA)来降低特征向量的维数。PCA 是一种统计技术,可用于寻找最大化方差和最小化数据集中投影误差的方向(分量)。

方差最大的轴(绿色)和投影误差较小的轴(红色)(图片由作者提供)

换句话说,主成分分析可用于寻找代表数据中最多信息的方向。

使用 PCA 时,需要记住以下几点:

  • PCA 最好是作为降维的工具,而不是用于特征选择。
  • 使用 PCA 进行降维时,首先对数据进行归一化是很重要的。
  • PCA 是线性变换,因此它不能捕捉数据中的非线性关系。
  • 为了减少到 N 维,你至少需要 N-1 次观察

我建议阅读以下文章,以便更好地理解 PCA 及其局限性:

流形学习

流形学习在某些方面是线性方法(如 PCA)的扩展,用于降低维数,但用于数据中的非线性结构。

流形是局部欧几里得的拓扑空间,这意味着在每个点附近它都类似于欧几里得空间。流形自然地出现在数学和物理的许多领域,流形的研究是微分几何的一个中心课题。

使用多方面学习时,有几件事要记住:

  • 流形学习是降维的有力工具。
  • 它可以用来发现数据中隐藏的模式。
  • 流形学习通常是一项计算密集型任务,因此在使用这些算法之前对它们有一个很好的理解是很重要的。

现实生活中的流程很少使用其所有维度来描述其底层结构。例如下面的图片,只需要几个维度来描述杯子的位置和旋转。

具有不同位置和旋转的杯子数据集(图片由作者提供)

这种情况下,一旦使用流形学习算法(如 t-分布式随机邻居嵌入(t-SNE ))进行投影,只有两个维度能够编码杯子的位置和旋转。

编码位置:

30-cup 数据集的最近邻图(图片由作者提供)

编码旋转:

第一个位置的编码旋转(图片由作者提供)

结论

在这篇文章中,我们看到了如何使用图片的特征工程来对抗维数灾难。我们已经了解了如何通过抽取、小波分解、HOG 描述符和 PCA 来降低图片的维度。我们还看到了如何使用流形学习来发现数据中隐藏的模式。

还有许多其他方法可以减少图片的尺寸,您采用的方法将取决于您正在处理的数据类型和您试图解决的问题。

特征工程是一个迭代的过程,它有助于对不同的可能性和可用的方法有一个总体的了解。

我希望这篇文章对你有帮助!如果您对如何构建 k-NN 图有任何疑问,我建议您阅读以下文章:

好奇想了解更多关于 Anthony 的工作和项目吗?在媒体LinkedInTwitter 上关注他。

需要技术作家?将您的请求发送到https://amigo CCI . io

时间序列数据的特征工程

原文:https://towardsdatascience.com/feature-engineering-for-time-series-data-f0cb1c1265d3

现代数据堆栈上的时间序列聚合

图为唐纳德·吴Unsplash

在许多商业数据科学问题中,具有时间序列特征的数据(例如,交易、传感器读数等)。)必须汇总到个人(例如,客户、设备等)。)水平。在现代机器学习环境中这样做可能会带来麻烦,因为传统的训练测试和交叉验证分割将会失败。这是因为在训练集和测试集之间随机拆分观察结果几乎总是会在这两个集之间拆分相关的(因此也是相关的)观察结果。更有问题的是,观察将被分割,以便一些训练观察可以在测试观察之后进行。换句话说,模型将学习从未来预测过去。这通常会导致模型在投入生产时失败。

有许多方法可以处理这个问题,我在这里讨论了我的首选方法。一种常用的方法是对每个人进行一次观察。这可以通过为每个人随机选择一个观察值或选择一个日期并仅使用该日期的观察值来实现。

我们将集中精力为给定日期的每个观察创建一个单独的记录。在本例中,我们将使用天气数据并对其进行汇总,以显示多个时间段内县级的平均高温。在熊猫身上做到这一点可能很有挑战性,但我们将展示在 Rasgo 的现代数据堆栈上做到这一点是多么容易。

熊猫的单矩聚集

给定包含县代码 FIPS 、日期日期和某个县在日期高温rollinggroupby的数据帧df,可以使用它们来创建所有日期的滚动平均值。在这种情况下,将创建一周、两周和四周的滚动平均值。

首先,应该创建滚动窗口

df['HIGH_TEMP_AVG_7D'] = df.sort_values(
                              by=['FIPS', 
                                 'DATE']).set_index(
                                 'DATE').groupby(
                                 'FIPS')[
                                 "HIGH_TEMP"].rolling('7D',             
                                 closed='both').mean()
df['HIGH_TEMP_AVG_14D'] = df.sort_values(
                              by=['FIPS', 
                                 'DATE']).set_index(
                                 'DATE').groupby(
                                 'FIPS')[
                                 "HIGH_TEMP"].rolling('14D',             
                                 closed='both').mean()
df['HIGH_TEMP_AVG_28D'] = df.sort_values(
                              by=['FIPS', 
                                 'DATE']).set_index(
                                 'DATE').groupby(
                                 'FIPS')[
                                 "HIGH_TEMP"].rolling('28D',             
                                 closed='both').mean()

可以重置索引以将县代码和日期返回到数据帧中的简单列。

df.reset_index(inplace=True)

这种方法有几个问题。首先,如果数据量很大,将数据下载到工作站并进行处理会非常耗时。虽然这可以通过仅下载所讨论的日期所需的数据来加速,但是仍然要对数据中的所有日期执行额外的计算。更重要的是,生产工作流只需要聚合到当前日期,并且应该生成聚合。

RasgoQL 和现代数据栈方法

在现代数据栈上,开源包 RasgoQL 以几种方式解决了这两个问题。首先,处理保存在云数据仓库中,因此没有数据被移动到工作站。其次,RasgoQL 转换timeseries_agg利用数据仓库的能力处理比工作站上可能处理的数据量大得多的数据。

首先,获取对数据仓库中保存天气数据的表的引用。

dataset = rql.dataset('WEATHER_TABLE_NAME')

每天的滚动平均值可以通过调用转换来生成。

tsagg = dataset.timeseries_agg(aggregations={
                                'DAILY_HIGH_TEMP': ['AVG']
                               },
                               group_by=['FIPS'],
                               date='DATE'
                               offsets=[7, 14, 28],
                               date_part='day')

这些数据可以通过调用tsagg上的to_df来下载,以获得熊猫数据帧进行进一步处理。

tsagg_df = tsagg.to_df()

或者,可以将这些数据发布回云数据仓库,以创建一个视图,其他人可以在 RasgoQL 中使用该视图,也可以通过 SQL 直接从数据仓库中使用该视图。

tsagg.save(table_name="ROLLING_WEATHER_SNAPSHOT")

在现代数据栈上使用开源 Python 包 RasgoQL 的转换使得创建这种滚动窗口比在 pandas 中创建要简单得多。该包创建一个在数据库中执行的 SQL 调用,并且可以将结果保存回数据库,以便将来在现有项目或需要相同数据的其他项目中引用。通过使用 SQL,处理的数据量可能会大得多。最后,使用 pandas,使用 aggregate 函数可以允许在多个列上同时进行多个聚合。除了在每个步骤中只能考虑一个时间窗口(例如七天或十四天)。这意味着要创建 7 天、14 天和 28 天的平均值,需要三种不同的 Python 语句。在 RasgoQL 中,一个 SQL 调用可以同时生成所有三个。

如果你想查看 RasgoQL,文档可以在这里找到,在这里找到库

特征工程——揭开神秘面纱

原文:https://towardsdatascience.com/feature-engineering-unraveling-the-mystery-768e15e72dac

数据科学|机器学习|特征工程

什么是特征工程,它解决的问题,为什么它真的很重要

理论上或实际上,我们都在机器学习和人工智能领域遇到过“特征工程”这个术语。特征工程被认为是应用机器学习成功的关键。"想出新功能既困难又耗时,而且需要专业知识。 应用机器学习 基本上就是特色工程"--(吴恩达)。在本文中,您将发现什么是特性工程,它解决什么问题,以及为什么它真的很重要。

你有一些数据,有了这些数据,你就训练了一个模型。您看到了结果,并意识到需要做更多的工作来提高模型性能。您可以尝试收集更多数据,也可以花时间调整模型。然而,您并不总是有收集更多数据的奢侈,因此第三种方法是修改可用的特征以更好地捕捉隐藏的模式。特征工程帮助您从数据中获取最大价值,并从算法中获得最佳结果。您获得的结果可能是数据集中的要素和您选择的算法的直接结果。您选择的功能也会影响算法的选择。

更好的特性意味着更简单的算法和更好的结果。

为了理解这种说法,我们来看一个简单的例子。假设你有一个变量 x1,在 x 轴上有两个类,蓝色和橙色。

作者创造的形象

你能使用逻辑回归来区分类别吗?一条线或一个平面无法将这两个类别分开,因此这里不能使用逻辑回归。您可能需要创建一个非线性决策边界来分隔这两个类。可能的选项如下所示。

作者创造的形象

现在,使用特征工程,如果您创建一个只是原始值的平方的新特征,您的新特征空间将如下所示:

作者创造的形象

给定 X1 中的一个值,其在 X2 的变换值就是该数的平方。-4 变成 16,-3 变成 9,2 的平方是 4,等等。穿过转换后的数据点绘制的线现在是一个超平面,,它可以将两个类分开。最后,我们可以对这些新数据进行逻辑回归。

作者创造的形象

因此,在更高的维度中,特征工程可以帮助你从使用深度神经网络到仅使用逻辑回归模型。这样做的好处不仅是改善了结果,而且产出可以解释和说明。

特征工程是一门艺术。数据是非线性的,每次都不同,对特征工程的掌握来自实践。不能简单地通过基本算术运算生成新要素。例如,如果您有像“重量”这样的特征,您不能简单地平方这些值来生成新的特征“重量平方”。新功能“重量平方”必须有一些商业意义。然而,如果你有体重和身高等特征,你可以创建一个新的特征身体质量指数,如果这有助于你的研究。

感谢您的阅读。如果您还有其他问题,请通过 LinkedIn 联系

https://swapnilin.github.io/

使用图像数据的特征工程

原文:https://towardsdatascience.com/feature-engineering-with-image-data-14fe4fcd4353

裁剪、灰度、RGB 通道、强度阈值、边缘检测和颜色过滤器

(来源: flaticon )

有了特征工程,我们马上会想到表格数据。然而,我们也可以获得图像数据的特征。目标是提取图像中最重要的部分。这样做将更容易找到我们的数据和目标变量之间的映射。

这意味着您可以使用更少的数据和训练更小的模型。较小的模型减少了进行预测所需的时间。这在边缘设备上部署时特别有用。一个额外的好处是,您可以更加确定您的模型使用什么来进行这些预测。

我们将介绍使用 Python 进行影像要素工程的一些方法:

  • 种植
  • 灰色鳞片
  • 选择 RGB 通道
  • 强度阈值
  • 边缘检测
  • 滤色器(即提取给定颜色范围内的像素)

为了让事情变得有趣,我们将为自动驾驶汽车做这件事。如下图所示,我们想用一条赛道的图片来训练一个模型。然后,该模型将被用于预测指导汽车。最后,我们将讨论来自图像数据的特征工程的局限性。

装有摄像头传感器自动驾驶汽车(来源:作者)

特征工程与增强

在我们深入研究之前,有必要讨论一下图像增强。这种方法与特征工程有相似的目标。然而,它以不同的方式实现它们。

什么是数据增强?

数据扩充是指我们使用代码系统地或随机地改变数据。对于图像,这包括翻转、调整颜色和添加随机噪声等方法。这些方法允许我们人为地引入噪声并增加数据集的大小。如果你想了解更多关于图像增强的细节,我推荐这篇文章:

在生产中,模型需要在不同的条件下运行。这些条件由照明、摄像机角度、房间颜色或背景中的物体等变量决定。

数据扩充的目标是创建一个对这些条件的变化具有鲁棒性的模型。它通过添加模拟真实世界条件的噪声来做到这一点。例如,改变图像的亮度类似于在一天的不同时间收集数据。

通过增加数据集的大小,增强还允许我们训练更复杂的架构。换句话说,它有助于模型参数收敛。

使用图像数据的特征工程

特征工程的目标是相似的。我们想创建一个更强大的模型。除了现在,我们去除任何对准确预测不必要的噪音。换句话说,我们去掉了随不同条件而变化的变量。

通过提取图像中最重要的方面,我们也简化了问题。这允许我们依赖更简单的模型架构。这意味着我们可以使用更小的数据集来找到输入和目标之间的映射。

一个重要的区别是在生产中如何处理这些方法。您的模型不会对增强图像进行预测。然而,通过特征工程,您的模型将需要对其接受训练的相同特征进行预测。这意味着你必须能够在生产中进行特征工程。

使用 Python 进行影像特征工程

好了,记住所有这些,让我们继续特征工程。我们会检查代码,你也可以在 GitHub 上找到这个项目。

首先,我们将使用下面的导入。我们有一些标准包装(第 2-3 行)。 Glob 用于处理文件路径(第 5 行)。我们还有一些用来处理图像的包(第 7-8 行)。

#Imports 
import numpy as np
import matplotlib.pyplot as plt

import glob

from PIL import Image
import cv2

如前所述,我们将使用用于驱动自动汽车的图像。你可以在 Kaggle 上找到这些例子。我们用下面的代码加载其中一个图像。我们首先加载所有图像的文件路径(第 2–3 行)。然后加载(第 8 行)并显示(第 9 行)第一个路径的图像。你可以在图 1 中看到这个图像。

#Load image paths
read_path = "../../data/direction/"
img_paths = glob.glob(read_path + "*.jpg")

fig = plt.figure(figsize=(10,10))

#Display image
img = Image.open(img_paths[0])
plt.imshow(img) 

图 1:轨迹图像示例(来源:作者)

种植

一个简单的方法是裁剪图像以移除不想要的外部区域。目的是仅移除预测不需要的图像部分。对于我们的自动汽车,我们可以从背景中去除像素。

为此,我们加载一个图像(第 2 行)。然后,我们将这个图像转换成一个数组(第 5 行)。该阵列的尺寸为 224 x 224 x 3。图像的高度和宽度是 224 像素,每个像素有一个 R G B 通道。为了裁剪图像,我们只选择 y 轴上从位置 25 开始的像素(第 8 行)。你可以在图 2 中看到结果。

#Load image
img = Image.open(img_paths[609])

#Covert to array
img = np.array(img)

#Simple crop
crop_img = img[25:,]

图 2:裁剪图像(来源:作者)

你可能想保持长宽比。在这种情况下,您可以通过将不需要的像素变黑(第 3 行)来获得类似的结果。

#Change pixels to black
crop_img = np.array(img)
crop_img[:25,] = [0,0,0]

图 3:通过改变像素颜色进行裁剪(来源:作者)

通过裁剪,我们删除了不必要的像素。我们还可以避免模型过度拟合训练数据。例如,背景中的椅子可能出现在所有左转处。因此,模型可以将这些与左转预测相关联。

看着上面的图像,你可能会忍不住进一步裁剪它。也就是说,您可以在不移除任何轨道的情况下裁剪图像的左侧。然而,在图 4 中,你可以看到,对于其他图像,我们将移除轨道的重要部分。

#Additional cropping 
crop_img = np.array(img)
crop_img[:25,] = [0,0,0]
crop_img[:,:40] = [0,0,0]

图 4:糟糕的裁剪示例(来源:作者)

这又回到了特性工程需要在产品中完成的问题上。这里你不知道什么图像将在什么时间显示给模型。这意味着相同的裁剪功能将需要应用于所有图像。你需要确保它永远不会删除图像的重要部分。

灰度等级

对于某些应用,图像的颜色并不重要。在这种情况下,我们可以对图像进行灰度处理。我们用 OpenCV 中的 cvtColor 函数来做这件事(第 2 行)。

#Gray scale
gray_img = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)

图 5:图像灰度(来源:作者)

灰度是通过捕捉图像的颜色强度来实现的。这是通过对 RGB 通道进行加权平均来实现的。具体来说,上面的函数使用以下公式:

Y= 0.299 *R+0.587 *G+0.114 *B

我们可以通过查看每个图像的输入值的数量来理解这样做的好处。如果我们使用所有 RGB 通道,它将由 150,528 个值组成(2242243)。对于灰度图像,我们现在只有 50,176 个值(224*224)。更简单的输入意味着我们需要更少的数据和更简单的模型。

RGB 通道

其中一个渠道可能更重要。我们可以只使用那个通道,而不是灰度。下面,我们选择 R(线 6)、G(线 7)和 B(线 8)通道。每个结果数组的大小都是 224 x 224。您可以在图 6 中看到各自的图像。

#Load image
img = Image.open(img_paths[700])
img = np.array(img)

#Get rgb channels
r_img = img[:, :, 0]
g_img = img[:, :, 1]
b_img = img[:, :, 2]

图 6: RGB 通道(来源:作者)

您也可以使用通道 _ 过滤器功能。这里,通道参数(c)将根据您想要的通道取值为 0、1 或 2。请记住,有些包会以不同的顺序加载频道。我们使用的是 RGB 的 PIL。但是,如果用 cv2.imread()加载图像,通道将按照 BGR 顺序排列。

def channel_filter(img,c=0):
    """Returns given channel from image pixels"""
    img = np.array(img)
    c_img = img[:, :, c]

    return c_img

通过这些转换,您需要考虑是否从图像中删除了重要信息。对于我们的应用程序,轨道是橙色的。换句话说,轨道的颜色有助于将其与图像的其他部分区分开来。

强度阈值

使用灰度时,每个像素的值将在 0 到 255 之间。我们可以通过将输入转换成二进制值来进一步简化输入。如果灰度值高于截止值,像素值为 1,否则为 0。我们称这个截止点为强度阈值。

下面的函数用于应用该阈值。我们首先对图像进行灰度处理(第 5 行)。如果像素高于截止值,则其值为 1000(第 8 行)。如果我们将像素设置为 1,它将低于截止值。换句话说,在下一步(第 9 行)中,所有像素都将被设置为 0。最后,我们缩放所有像素,使它们取值为 0 或 1(第 11 行)。

def threshold(img,cutoff=80):
    """Apply intesity thresholding"""

    img = np.array(img)
    img = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)

    #Apply cutoff
    img[img>cutoff] = 1000 #black
    img[img<=cutoff] = 0 #white

    img = img/1000

    return img

自动汽车项目的一部分是避开障碍物。这些是涂成黑色的罐子。在图 7 中,您可以看到如何应用强度阈值函数将 tin 从图像的其余部分中分离出来。这是唯一可能的,因为锡是黑色的。换句话说,它的强度大于图像的其余部分。

图 7:具有强度阈值的特征工程(来源:作者)

截止值可以被视为一个超参数。参见图 7,截止值越大,意味着我们包含的背景噪声越少。不利的一面是我们捕获的罐头更少了。

边缘检测

如果我们想分离轨迹,我们可以使用 canny 边缘检测。这是一种用于检测图像边缘的多阶段算法。如果你想了解它是如何工作的,我建议阅读索菲安·萨希尔关于精明边缘检测的文章。

我们将该算法应用于 cv2。Canny ()函数。阈值 1阈值 2 参数用于迟滞程序。这是边缘检测算法的最后一步,用于确定哪些线实际上是边缘。

#Apply canny edge detection
edge_img = cv2.Canny(img,threshold1 = 50, threshold2 = 80)

你可以在图 8 中看到一些例子。像强度阈值处理一样,我们只剩下一个二值图——白色代表边缘,黑色代表其他。希望这个轨迹现在更容易与图像的其他部分区分开来。但是,您可以看到背景中的边缘也被检测到。

图 8: canny 边缘检测(来源:作者)

滤色器

我们可能会有更好的运气,通过使用像素颜色来隔离轨迹。我们使用下面的 pixel_filter 函数来实现。使用 cv2.inRange ()我们将图像转换成二进制图(第 10 行)。这个函数检查一个像素是否落在下面(第 5 行)和上面(第 6 行)列表给定的范围内。具体来说,每个 RGB 通道必须在各自的范围内(例如 134-t ≤ R ≤ 194+t)。

def pixel_filter(img, t=0):

    """Filter pixels within range"""

    lower = [134-t,84-t,55-t]
    upper = [192+t,121+t,101+t]

    img = np.array(img)
    orange_thresh = 255 - cv2.inRange(img, np.array(lower), np.array(upper))

    return orange_thresh

简单地说,该函数确定像素颜色是否足够接近轨道的橙色。你可以在图 9 中看到结果。测试参数引入了一些灵活性。使用较高的值,我们可以捕捉更多的轨迹,但保留更多的噪声。这是因为背景中的像素将落在该范围内。

图 9:过滤橙色像素(来源:作者)

你可能想知道我们从哪里得到下限和上限。这就是我们如何知道通道将落在[134,84,55]和[192,121,101]之间?嗯,我们使用 Python 创建的颜色选择器。我们在下面的文章中概述了这是如何创建的。

图 10 中,您可以看到拾取器正在工作。我们从多个图像中选择像素,并尝试在轨道上的不同位置选择它们。这是为了在不同条件下获得全范围的像素值。

图 10:从轨道上挑选颜色(来源:作者)

我们总共选择了 60 种颜色。这些你都可以在图 11 (带加成视错觉)中看到。所有这些颜色的 RGB 通道都存储在一个名为“颜色”的列表中。

图 11:用拾色器选择的 60 个轨迹像素

最后,我们取每个 RGB 通道的最小值和最大值。这给出了下限和上限。

lower = [min(x[0] for x in colours),
              min(x[1] for x in colours),
              min(x[2] for x in colours)]

upper = [max(x[0] for x in colours),
              max(x[1] for x in colours),
              max(x[2] for x in colours)]

特征工程的局限性

经过这一切,你可能不相信。深度学习的一个主要好处是,它可以识别复杂的模式,而不需要特征工程。这是一个很好的观点。

特征工程需要批判性思维。你需要弄清楚图像的哪些方面是重要的。然后,您需要编写代码来提取这些方面。对于某些应用程序来说,完成所有这些所需的时间毫无意义。

此外,对于一些方法,我们已经看到,我们不能消除所有的噪音。例如,强度阈值中的黑色背景。与直觉相反的是,残留的噪音现在可能更难区分什么是重要的。也就是说,剩余的噪声和对象像素具有相同的值(1)。

真的,当处理相对简单的计算机视觉问题时,好处就来了。我们的轨迹从不改变,物体的颜色也总是一样。对于更复杂的问题,你将需要更多的数据。或者,您可以在较小的数据集上微调预训练模型。

我希望你喜欢这篇文章!你可以成为我的 推荐会员 😃 来支持我

https://conorosullyds.medium.com/membership

| 推特 | YouTube | 时事通讯 —注册免费参加 Python SHAP 课程

图像来源

所有图片都是我自己的或从www.flaticon.com获得。在后者的情况下,我拥有他们的保费计划中定义的“完全许可”。

资料组

JatRacer 图片 (CC0:公共领域)https://www.kaggle.com/datasets/conorsully1/jatracer-images

参考

OpenCV,颜色转换https://docs . OpenCV . org/3.4/de/d25/imgproc _ Color _ conversions . html

基于 BERT 的文本分类特征提取

原文:https://towardsdatascience.com/feature-extraction-with-bert-for-text-classification-533dde44dc2f

照片由西格蒙德Unsplash 拍摄

使用 Pytorch 和拥抱脸从预训练的模型中提取信息

目标

让我们从定义这篇实践文章的目的开始。我们希望建立一个模型,将一个或多个文档作为输入,并设法根据它们的内容对它们进行分类。
一些类别例如:政治、旅游、体育等。
为了做到这一点,我们想使用一个预训练模型,如 BERT。

作者图片

背景

BERT 是一种基于 Transformer 编码器的语言模型。如果你对变形金刚不熟悉,我推荐你阅读这篇惊人的文章

伯特简单地说:

  • 它将一个或多个句子的嵌入标记作为输入。
  • 第一个令牌始终是一个名为【CLS】的特殊令牌。
  • 句子之间由另一个叫做【SEP】的特殊记号分隔。
  • 对于每个令牌,BERT 输出一个称为隐藏状态的嵌入。
  • 伯特接受了掩蔽语言模型下一句预测任务的训练。

屏蔽语言模型(MLM) 中,一个输入单词(或标记)被屏蔽,伯特必须试图找出被屏蔽的单词是什么。对于下一个句子预测(NSP) 任务,输入给 BERT 两个句子,他必须弄清楚第二个句子是否在语义上跟随第一个句子。

对于像我们这样的分类问题,我们只对与初始标记【CLS】相关联的隐藏状态感兴趣,不知何故比其他的更好地捕捉了整个句子的语义。因此,我们可以使用这种嵌入作为分类器的输入,我们在它的基础上构建分类器。

作者图片

从上面的图片中,你可以看到我们将使用一个叫做 DistilBERT 的较轻版本的 BERT。这个经过提炼的模型比原来的小了 40%,但是在各种 NLP 任务上仍然保持了大约 97%的性能。
你可以注意到的另一件事是,伯特的输入不是原始单词,而是标记。简单地说,BERT 关联了一个预处理文本的记号化器,以便它对模型有吸引力。单词通常被分成子词,此外还会添加特殊的标记【CLS】来指示句子的开始,【SEP】来分隔多个句子,以及【PAD】来使每个句子具有相同数量的标记。

如果您想了解更多关于 Bert 或他的 wordpartickizer 的信息,请查看以下资源:

我们来编码吧!

资料组

我们要用的数据集叫做 BBC 全文文档分类 ,可以在 Kaggle 上公开获取。

该数据集包含 2225 条记录,总共包含 5 个类别。我们想要确定的五个类别是体育、商业、政治、科技和娱乐。

直接从 colab 下载 kaggle 数据集。(记得上传您的个人密钥)

我不会详细介绍如何读取这些数据并将其转换成 dataframe,但我假设您可以创建一个包含两列的 data frame:short _ descriptioncategory。

编码标签

数据集的标签有:政治、体育等……
我们需要通过简单地使用标签编码器将这些标签转换成数字

生成文本嵌入

为每个文本生成一个嵌入向量,它可以用作我们最终分类器的输入。与每个文本相关联的矢量嵌入只是 Bert 为[CLS]令牌输出的隐藏状态。

先从 HuggingFace 导入模型和分词器开始。

现在我们必须对文本进行标记。记住定义填充符,这样每个标记化的句子将具有相同的长度,并且 截断 因此如果句子太长,它将被截断。最后一个参数是返回 PyTorch 张量。

对文本进行标记化的结果将是一个字典,其中包含以数字表示的标记input _ id,以及告诉我们该标记是否为[PAD]的 attention_mask

通过运行模型获得文本([CLS])隐藏状态。

构建分类器

至此,你可以使用你最喜欢的分类器,给它输入隐藏状态,并让它预测标签。在这种情况下,我将使用随机森林。

这个分类器的性能不会很好,因为我们使用了很少的数据,并且没有在分类器上做很多工作。但是出于好奇,我建议你将它与一个随机预测标签的虚拟分类器进行比较。

最后的想法

在这篇动手实践文章中,我们看到了如何利用预训练模型的功能在很短的时间内创建一个简单的分类器。请记住,我们训练的只是最终的分类器,即随机森林。
另一方面,Bert 只在推理中用于生成嵌入,以某种方式捕捉文本的主要特征,这就是为什么我们说我们使用了特征提取方法。但是我们能训练 Bert 自己教他如何在我们的具体案例中创建更好的文本嵌入吗?当然可以!在下一篇文章中,我将向你展示如何微调(蒸馏)伯特!

结束了

马赛洛·波利蒂

LinkedinTwitterCV

决策树中的特征重要性

原文:https://towardsdatascience.com/feature-importance-in-decision-trees-e9450120b445

基于树的机器学习算法中测量特征重要性背后的计算的完整 Python 实现和解释

约书亚·戈尔德在 Unsplash 上拍摄的照片

这篇文章的目的是让读者熟悉如何在决策树中计算特征的重要性。就我个人而言,我没有找到对这个概念的深入解释,因此本文诞生了。

本文中使用的所有代码都是公开的,可以通过以下途径找到:

https://github.com/Eligijus112/gradient-boosting

在深入研究特性重要性计算之前,我强烈建议您复习一下什么是树,以及我们如何使用这些文章将它们组合成随机森林的知识:

我们将使用决策树模型,使用各种回归变量( X )来创建加利福尼亚州中值房价( Y )之间的关系。可以使用 scikit-learn 包加载数据集:

加载加州住房数据集;作者代码

我们将在模型中使用的特性 X 是:

  • MedInc —过去 12 个月的家庭收入中位数(十万)

  • 房龄 —房龄(年)

  • 平均房间数——每个住所的平均房间数

  • AveBedrms —每个住宅的平均卧室数量

*ave occupation——平均家庭成员数

响应变量 Y 是加州各区的中值房价,以几十万美元表示。

数据的形状如下:

数据的形状;按作者分类的表格

快速浏览特征变量:

X 变量的头;按作者分类的表格

特征的描述性统计;按作者分类的表格

Y 变量的分布:

响应变量的分布;按作者分类的图表

为了匿名化数据,数据中有一个 50 万美元的收入上限:超过这个上限的仍被标记为 50 万美元的收入。这是为了确保没有人可以识别具体的家庭,因为早在 1997 年没有多少家庭是如此昂贵。

我们将数据分为训练集和测试集,拟合回归树模型,并推断训练集和测试集的结果。

拟合回归树;作者代码

打印输出如下:

准确性结果;作者照片

长成的树不会过度生长。这篇文章是关于特征的推断,所以我们不会尽力减少错误,而是试图推断哪些特征是最有影响的。

训练集上的成年树:

全回归树;按作者分类的图表

决策树由个节点、个节点组成,每个节点由一个分割规则链接。分割规则涉及一个要素和它应该分割的值。

术语“分割”是指如果满足分割规则,数据集的观测值将位于节点的左侧。如果不满足规则,则观察向右进行。

从 1 到 15 枚举每个节点。

让我们检查第一个节点和其中的信息。所有节点的逻辑都是一样的。

MedInc ≤ 5.029 —节点的拆分规则。如果一个观察的 MedInc 值小于或等于 5.029,那么我们向左遍历树(转到节点 2),否则,我们转到右边的节点(节点 3)。

squared_error —用作分割标准的统计数据。squared_error 的计算公式如下:

均方误差公式

在第一个节点中,统计值等于 1.335。

样本 —节点中观察值的数量。因为这是根节点,所以 15480 对应于整个训练数据集。

—节点的预测值。换句话说,如果观察路径在此节点停止,则该节点的预测值将为 2.074。

让我们创建一个保存所有节点中所有观察值的字典:

n_entries = {
“node 1”: 15480,
“node 2”: 12163,
“node 3”: 3317,
“node 4”: 5869,
“node 5”: 6294,
“node 6”: 2317,
“node 7”: 1000,
“node 8”: 2454,
“node 9”: 3415,
“node 10”: 1372,
“node 11”: 4922,
“node 12”: 958,
“node 13”: 1359,
“node 14”: 423,
“node 15”: 577
}

在计算特征重要性时,使用的度量之一是观察值落入某个节点的概率。概率是为决策树中的每个节点计算的,计算方法是将节点中的样本数除以数据集中的观察总数(在我们的例子中是 15480)。

让我们将字典表示为 n_entries_weighted :

n_entries_weighted = {
'node 1': 1.0,  
'node 2': 0.786,  
'node 3': 0.214,  
'node 4': 0.379,  
'node 5': 0.407,  
'node 6': 0.15,  
'node 7': 0.065,  
'node 8': 0.159,  
'node 9': 0.221,  
'node 10': 0.089,  
'node 11': 0.318,  
'node 12': 0.062,  
'node 13': 0.088,  
'node 14': 0.027,  
'node 15': 0.037
}

为了使特性重要性的定义具有数学上的严格性,让我们在本文中使用数学符号。

让我们将每个节点表示为

节点符号

每个节点,直到最终深度,都有一个左子节点和一个右子节点。让我们将它们表示为:

左右子符号

每个节点都有特定的属性。让我们将上一节中计算的重量表示为:

节点权重

让我们将均方误差(MSE)统计量表示为:

节点均方误差统计

有子节点的节点的一个非常重要的属性是所谓的节点重要性:

节点计算的重要性

上述等式的直觉是,如果子节点中的 MSE 较小,则该节点尤其是其分裂规则特征的重要性较大。

让我们用每个节点的 MSE 统计数据创建一个字典:

i_sq = {
“node 1”: 1.335,
“node 2”: 0.832,
“node 3”: 1.214,
“node 4”: 0.546,
“node 5”: 0.834,
“node 6”: 0.893,
“node 7”: 0.776,
“node 8”: 0.648,
“node 9”: 0.385,
“node 10”: 1.287,
“node 11”: 0.516,
“node 12”: 0.989,
“node 13”: 0.536,
“node 14”: 0.773,
“node 15”: 0.432
}

作者 Trevor Hastie、Robert Tibshirani 和 Jerome Friedman 在他们的巨著The Elements of Statistical Learning:Data Mining,Inference,and Prediction 中用以下等式定义了特征重要性计算:

布雷曼特征重要性方程

在哪里

t——是整个决策树

l —有问题的特征

J —决策树中内部节点的数量

I——用于分割的度量的减少

II —指示器功能

v(t)-用于分割节点的特征 t 用于分割节点

这个等式背后的直觉是,对树中所有特征的度量的所有减少进行求和。

Scikit-learn 使用前面提出的节点重要性公式。主要区别在于,在 scikit-learn 中,引入了节点权重,即观察值落入树中的概率。

让我们放大一点,进一步检查节点 1 到 3。

前三个节点;按作者分类的图表

节点重要性(以及要素重要性)的计算一次只考虑一个节点。为节点号 1 解释的后续逻辑适用于以下级别的所有节点。

只有具有分裂规则的节点才有助于特征重要性的计算。

第二个节点是节点 1 的左子节点,第三个节点是右子节点。

特征重要性背后的直觉始于分裂标准中的总体减少的想法。换句话说,我们想要测量给定的特征及其分裂值(尽管该值本身在任何地方都不使用)如何减少系统中的均方误差。上一节中定义的节点重要性等式反映了这种影响。

如果我们在根节点中使用 MedInc,将有 12163 个观察值到达第二个节点,3317 个观察值到达右节点。这转化为左节点的权重为 0.786 (12163/15480),右节点的权重为 0.214 (3317/15480)。左侧节点中的均方误差等于 0.892,右侧节点中的均方误差为 1.214。

我们需要计算节点重要性:

现在我们可以将节点重要性保存到字典中。字典键是在节点的分裂标准中使用的特征。这些值是节点的重要性。

{
  "**MedInc**": 0.421252,
  "**HouseAge**": 0,
  "**AveRooms**": 0,
  "**AveBedrms**": 0,
  "**AveOccup**": 0}

上述计算过程需要对所有具有分裂规则的节点重复进行。

让我们再做一些节点计算,以完全掌握算法:

更多的平方误差减少;按作者分类的图表

如果我们在节点 2 中使用 MedInc 特性,误差平方为:

第二节点重要性

特征重要性字典现在变成了:

{
  "**MedInc**": 0.421 + 0.10758
  "**HouseAge**": 0,
  "**AveRooms**": 0,
  "**AveBedrms**": 0,
  "**AveOccup**": 0}

要拆分的新功能;按作者分类的图表

节点 4 的重要性

{
  "**MedInc**": 0.558,
  "**HouseAge**": 0,
  "**AveRooms**": 0.018817,
  "**AveBedrms**": 0,
  "**AveOccup**": 0}

我们不能更进一步,因为节点 8 和 9 没有分裂规则,因此不会进一步减少均方误差统计。

让我们对上面几节中给出的实现进行编码。

用于重要性计算的数据

现在让我们定义一个计算节点重要性的函数。

节点重要性计算函数

将所有这些放在一起:

计算节点的代码段

上述代码片段中的内容如下:

Node importance: {
‘node 1’: 0.421, 
‘node 2’: 0.108, 
‘node 3’: 0.076, 
‘node 4’: 0.019, 
‘node 5’: 0.061, 
‘node 6’: 0.025, 
‘node 7’: 0.013
} Feature importance before normalization: {
‘MedInc’: 0.618, 
‘AveRooms’: 0.019, 
‘AveOccup’: 0.086, 
‘HouseAge’: 0, 
‘AveBedrms’: 0
} **Feature importance after normalization: {
‘MedInc’: 0.855, 
‘AveRooms’: 0.026, 
‘AveOccup’: 0.119, 
‘HouseAge’: 0.0, 
‘AveBedrms’: 0.0
}**

归一化后的最终特征字典是具有最终特征重要性的字典。根据字典,到目前为止最重要的特征是 MedInc,其次是 ave occupation 和 AveRooms。

特征 HouseAge 和 AveBedrms 没有在任何分割规则中使用,因此它们的重要性为 0。

让我们将我们的计算与功能重要性计算的 scikit-learn 实现进行比较。

Sklearn 特性重要性的实现

上面写着:

Feature importance by sklearn: 
{
‘MedInc’: 0.854, 
‘HouseAge’: 0.0, 
‘AveRooms’: 0.027, 
‘AveBedrms’: 0.0, 
‘AveOccup’: 0.12
}

与我们的计算相比:

特征重要性比较

差异很小,但这是由于舍入误差。

在本文中,我非常详细地演示了决策树的特性重要性计算。一个非常相似的逻辑适用于分类中使用的决策树。唯一的区别是度量——我们不使用平方误差,而是使用 GINI 杂质度量(或其他分类评估度量)。所有关于节点重要性的计算保持不变。

我希望在读完所有这些之后,你会对如何解释和计算特性的重要性有一个更清晰的了解。

编码快乐!

[1]作者:佩斯,r .凯利和罗纳德·巴里
年份: 1997 年
书名:稀疏空间自回归
网址:http://archive.ics.uci.edu/ml
期刊:
统计与概率快报****

[2]作者:特雷弗·哈斯蒂、罗伯特·蒂布拉尼和杰罗姆·弗里德曼**
年份: 2017
书名:统计学习的要素:数据挖掘、推断和预测
网址:http://archive.ics.uci.edu/ml
页面:
368–370******

机器学习中的特征重要性,已解释

原文:https://towardsdatascience.com/feature-importance-in-machine-learning-explained-443e35b1b284

使用 SHAP 和 Sci-Kit Learn 识别与 Python 中的模型相关的重要特性

图片由约书亚·戈德Unsplash 拍摄

本文将重点介绍与各种方法相关的直觉和 Python 实现,以识别与机器学习模型相关的重要特性。以下是文章的结构。

目录

  • 机器学习中的特征重要性是什么?
  • 基于系数的特征重要性
  • 置换特征重要性
  • 树特征重要性
  • SHAP 特征重要性
  • 实现
    -需求
    -合成数据&生成模型
    -系数
    -排列
    -树
    • SHAP
  • 结束语
  • 资源

机器学习中的特征重要性是什么?

特征重要性是模型开发中不可或缺的组成部分。它突出显示了传递到模型中的哪些要素对生成预测的影响程度高于其他要素。识别重要特征的结果可以直接反馈到模型测试和模型可解释性中。有多种方法可以计算特征的重要性,例如:

  1. 基于系数的特征重要性
  2. 基于排列的特征重要性
  3. 树特征重要性
  4. SHAP

请注意,并非所有计算特征重要性的方法都适用于所有类型的模型。这些方法主要适用于监督经典机器学习问题(如分类和回归)中的大多数模型。

基于系数的特征重要性

基于系数的特征重要性可能是最容易理解的。直观上,基于系数的特征重要性指的是将预测生成为输入值的加权和的模型。

并非所有模型都可以计算特征的重要性。这适用于线性模型,如线性回归、逻辑回归、岭回归、支持向量机(仅当核是线性时)。这些类型的模型的主要共同点是它们识别与一组系数相关联的权重,我们可以将其解释为特征重要性。您可以从高到低对与这些系数相关的特征进行排序,最高的是最重要的特征,最低的是最不重要的特征。

置换特征重要性

基于置换的特征重要性被定义为当单个特征值被随机打乱时模型得分的减少。该过程打破了特征和目标之间的关系,因此模型分数的下降指示了模型对特征的依赖程度。[2]

-http://sci kit-learn . org/stable/modules/permutation _ importance . html

置换特征重要性的结果可以是负的和正的。当置换分数对于某些特征为负时,它表明从混洗数据生成的预测碰巧比真实数据更准确。当模型认为特性应该具有重要性,但却没有时,就会发生这种情况。发生这种情况是因为随机机会导致从混洗数据生成的预测更加准确。这意味着这些特征有噪声。

树特征重要性

sci-kit 中基于树的模型学习,如决策树、随机森林、梯度增强、ada 增强等。嵌入了它们自己的特性重要性。他们根据用于选择分裂点的标准(如基尼系数或熵)的减少来计算他们的重要性分数[1]。可以通过训练模型后可用的feature_importances_属性引用这些分数。

SHAP 特征重要性

SHAP 是一个流行的研究论文,重点是模型的可解释性。SHAP 特征重要性是置换特征重要性的替代方法[3]。排列法和 SHAP 的区别在于,SHAP 着眼于特征属性的大小,而排列法着眼于模型性能的下降[3]。SHAP 图书馆内置了一系列的explainer类。它支持线性模型、内核、树、深度学习模型等的可解释性。

履行

要求

Python=3.9.12
pandas>=1.4.3
numpy>=1.23.2
shap>=0.41.0
matplotlib>=3.5.1
sklearn>=1.1.2

综合数据并生成模型

请注意,因为我们使用的是随机生成的数据,所以特性重要性的结果几乎没有意义。这只是为了展示如何通过代码为您正在处理的问题实现这些不同类型的特性重要性度量。下面的脚本将合成一个具有 5 个特征的随机数据集,并从中训练 2 个基于回归的模型。即梯度推进回归器和支持向量回归器。

系数

系数特征重要性。图片由作者提供。

排列

置换特征重要性。图片由作者提供。

基于树的特征重要性。图片由作者提供。

SHAP

线性核 SVM 回归模型的 SHAP 特征重要性。图片由作者提供。

SHAP 特征对梯度推进回归器的重要性。图片由作者提供。

SHAP 库中的汇总绘图功能允许您根据 SHAP 值直观地查看模型的最重要功能。第一个图显示了每个要素的影响分布,而第二个图是由 SHAP 值的 MAE(平均绝对值)生成的条形图。

结束语

基于对识别特征重要性的各种方法如何与模型的训练数据相关联的直观理解,以及所提供的相关代码,您应该能够为您正在处理的模型实现这一点,以查看哪些特征具有最高的影响。这对于模型测试和可解释性非常有用。

请在我的 GitHub 页面这里查看与本教程相关的资源库。

如果你想转型进入数据行业,并希望得到经验丰富的导师的指导和指引,那么你可能想看看最敏锐的头脑。Sharpest Minds 是一个导师平台,导师(他们是经验丰富的实践数据科学家、机器学习工程师、研究科学家、首席技术官等。)将有助于你的发展和学习在数据领域找到一份工作。在这里查看。

资源

如果你觉得这篇文章有用,这里有一些我写的其他文章,你可能也会觉得有用。

利用特征重要性预测 Python 中蘑菇的可食用性

原文:https://towardsdatascience.com/feature-importance-to-predict-mushrooms-edibility-in-python-5aa133fea3f8

利用特征重要性来预测蘑菇种类是可食用的还是有毒的

照片由 Jannik SelzUnsplash 上拍摄

介绍

T 本文旨在利用特征重要性来评估数据集中的所有列是否需要用于预测

秋天快到了。想象一下,你正在树林中散步,发现路边有一些蘑菇。将它们的一些特性输入到一个 ML 驱动的应用程序中不是很好吗?我个人不喜欢吃蘑菇,但我绝对喜欢食物,走了很长一段路后,我已经可以闻到面前有一道美味的“tagliolini ai funghi”。

蘑菇是真菌,是独立于植物和动物的独立王国的一部分。正如你可能想象的那样,在决定一个人是否可以食用之前,他们会给出无数的特征来评估。

您的徒步旅行团队正在离开,我们需要尽快做出决定。

哪个信息是舒适地评估蘑菇品种的可食用性的基础?

让我们找出答案

数据

数据集可以在机器学习 UCI 知识库【1】中检索。它包括关于蘑菇蘑菇家族中 23 种蘑菇的假设信息。这些记录是假设的,因为根据蘑菇指南,它们是人工输入的。作者确定了 22 个独特的特征,不包括可食用或有毒的特征,其中一些是:

  1. cap-shape:钟形=b,锥形=c,凸形=x,扁平=f,圆球形=k,凹形=s
  2. cap-surface:纤维状=f,凹槽=g,鳞状=y,光滑=s
  3. cap-color:棕色=n,浅黄色=b,肉桂色=c,灰色=g,绿色=r,粉色=p,紫色=u,红色=e,白色=w,黄色=y
  4. bruises?:淤青=t,no=f
  5. odor:杏仁=a,茴香=l,杂酚油=c,鱼腥味=y,恶臭=f,霉味=m,无=n,刺鼻=p,辛辣=s
  6. gill-attachment:附着=a,下降=d,自由=f,缺口=n
  7. gill-spacing:近=c,挤=w,远=d
  8. gill-size:宽=b,窄=n
  9. gill-color:黑色=k,棕色=n,浅黄色=b,巧克力色=h,灰色=g,绿色=r,橙色=o,粉色=p,紫色=u,红色=e,白色=w,黄色=y
  10. stalk-shape:放大=e,缩小=t
  11. stalk-root:球根=b,球杆=c,杯子=u,等号=e,根茎=z,有根=r,缺失=?
  12. stalk-surface-above-ring:纤维状=f,鳞状=y,丝状=k,光滑=s
  13. stalk-color-above-ring:棕色=n,浅黄色=b,肉桂色=c,灰色=g,橙色=o,粉色=p,红色=e,白色=w,黄色=y
  14. spore-print-color:黑色=k,棕色=n,浅黄色=b,巧克力色=h,绿色=r,橙色=o,紫色=u,白色=w,黄色=y

特征重要性

您可以将一个要素标识为数据集中的多个列之一。计算特征重要性是指每个特征在训练一个模型后所拥有的分数。你会同意我的观点,即并不是所有的特征都是相等的,它们对输出预测有贡献。

我们可以看到与帕累托法则的相似之处,其中某件事情的 20% 负责结果的 80% ,或者称为 20:80 法则。在销售环境中,帕累托原则的一个例子是,你的 20%的客户创造了你 80%的销售额。在一个机器学习场景中,我们可以把这个原则翻译成“ 20% 的特征负责 80% 的正确预测”。特征重要性允许从业者识别出 20%

你是如何解读乐谱的?一个较高的分数表明一个特性对你的模型更有影响,而一个较低的分数表明信息对模型来说不那么重要。对于我们的项目,我们有 21 个特征,我们想计算每个特征的重要性分数,并且只选择几个[2]。

模特们

特征选择考虑的模型有两个:随机森林梯度提升。每一种都有自己的特点,我将简要解释一下。

随机森林

随机决策森林属于集成学习算法的范畴。“森林这个名字来自于它“组成”的个体实体:决策树。在训练阶段,多个决策树从数据中学习,一个投票机制确保最常见的结果也是最终输出。该模型同时用于分类回归任务。

随机森林在有大量变量时表现出了显著的性能。鉴于需要调整的超参数很少,企业认为这是一个“黑箱”。很难解释为什么一个随机森林会做出某些预测。另一方面,该特征提供了适应性高精度,而不会陷入过度拟合的风险【3】。

梯度推进

梯度提升也是一种集成学习算法,可用于分类回归任务。类似于随机森林,梯度增强预测基于应用于决策树的投票机制。根本区别在于,这些决策树被定义为“或“”,这意味着一个模型具有高偏差低方差。换句话说,它利用了一致的预测(具有所有相似的结果),但是不准确(显示错误的结果)。集合的目标是减少偏差同时保持方差低,使模型输出更接近目标结果【4】。

你可以把它想象成一束指向镖靶的激光。起初,模型做出的所有预测都远离靶心,但它们都彼此接近,它们是一致的。梯度提升以减少误差为目标依次构建弱学习器,使目标越来越接近靶心,即最佳模型。与直觉相反,梯度推进仍然保留了很大的泛化能力,这使得它成为一个计算昂贵的但总体上很棒的学习模型。

Python 中的代码部署

数据探索

与大多数数据科学项目一样,代码部署的第一部分侧重于数据探索可视化。一个好的早期测试,检查数据集是否平衡。在分类问题中,重要的是两个目标变量呈现相似的计数。探索性数据分析因此是项目的第一步。

  • 我们根据需要导入pandasmatplotlib
  • 我们将 csv 文件作为熊猫数据帧读取
  • category_dist统计可食用或有毒的记录数量
  • 此时,可以定义图表及其大小颜色字体大小,以及我们是否想要一个网格。
#Importing libraries
import matplotlib.pyplot as plt
import pandas as pd#Reading dataset
df = pd.read_csv('mushrooms.csv')#Counting values within each class
category_dist = df['class'].value_counts()#Defining chart
plt.figure(figsize=(8,6))
category_dist.plot(kind='bar', color = '#89b4a1')
plt.grid()
plt.xlabel("Edible/Poisonous", fontsize = 12)
plt.ylabel("Number of Measurements", fontsize = 12)
plt.title("Distribution of Measurements", fontsize = 15)
plt.grid(False)#Generating chart
plt.show()

蘑菇可食用性的秋季主题分布——作者图表

对于蘑菇数据集,可食用物种的数量彼此之间只相差几百个。我们可以断定数据集是平衡的,我们可以继续进行项目的下一部分,标签编码。

标签编码

处理分类变量可能是几个机器学习算法的问题。在预处理阶段,标签编码通过将标签转换成数字来解决问题,以便机器能够读取它们。

流程是如何运作的?让我们以 cap-color 特性为例,有十种可能性:

  • 棕色=n,
  • buff=b,
  • 肉桂=c,
  • 灰色=g,
  • 绿色=r,
  • 粉色=p,
  • 紫色=u,
  • 红色=e,
  • 白色=w,
  • 黄色=y

标签编码算法按照字母顺序对它们进行分类:b、c、e、g……然后给每个字母分配一个从 0 开始的数字。字母“b”对应于 0,“c”对应于 1,“e”对应于 2,依此类推。

多亏了sklearn,这个过程相当容易。从业者需要导入LabelEncoder包,创建一个名为labelencoder的对象,并编写一个 for 循环语句,该对象将每一列的记录转换成一个数字形式。

from sklearn.preprocessing import LabelEncoderlabelencoder=LabelEncoder()for col in df.columns:
    df[col] = labelencoder.fit_transform(df[col])

为了更直观地了解这一过程,下面的图表显示了每一类(可食用或有毒)蘑菇的颜色。你可以看到大多数棕色和灰色蘑菇是可以食用的,但是你应该远离黄色蘑菇。

热编码前蘑菇种类的颜色和类别的秋季主题分布-作者图表

在我们对数据集进行标签编码后,你会注意到类和帽颜色特征都已经被转换成数字。食用的字母“e”现在对应于数字 0,而“p”对应于 1。关于帽子的颜色,所有的棕色蘑菇现在被归类为 4,因为它是按字母顺序排列的第 5 个字母。

热编码后蘑菇种类按颜色和类别的秋季主题分布-作者图表

型号选择

对于模型选择部分,我强烈推荐你看一下我之前的一篇文章中的,在这篇文章中,我解释了如何部署流水线并评估几个机器学习模型的性能。对于这个项目,我在将以下内容设置为输入和目标变量后应用了相同的管道:

#Defining input and target variablesx = df.drop('class', axis=1)
y = df['class']

我们的输入变量最初是数据集的所有 21 个特征。因此x 由除class之外的所有列组成。既然我们想预测一个蘑菇是否可以食用,那么目标变量就是 class,它包含了我们需要的信息。

我决定交叉验证 16 种不同的算法,以在评估特性的重要性之前识别出具有最高性能的算法(yo-yo Eminem)。

模型选择过程后算法的准确性比较—作者提供的图表

特别地,四个以最小的方差显示出最高的准确度:决策树分类器(CART)** ,随机森林(RF)AdaBoost 分类器 (ADA)梯度增强(XGB) 。**

LR: 0.839369 (0.142382) 
LDA: 0.843812 (0.159062) 
KNN: 0.908047 (0.094523) 
CART: 0.991626 (0.015547) 
NB: 0.713839 (0.189206) 
SVM: 0.824590 (0.187337) 
SGC: 0.782230 (0.159755) 
Perc: 0.760104 (0.150632) 
NC: 0.698081 (0.167803) 
Ridge: 0.843319 (0.158079) 
NuSVC: 0.746827 (0.189874) 
BNB: 0.800220 (0.136547) 
RF: 0.997168 (0.003473) 
ADA: 0.994582 (0.009653) 
XGB: 0.998277 (0.003446) 
PAC: 0.850076 (0.106792)

值得一提的是,这样的高性能可能是过度适应的迹象,这个问题我们不打算在本文中讨论。不过,在未来的项目中,这将是一个很好的解释主题。现在,让我们考虑一下将被带到下一阶段的两个最好的模型:随机森林梯度提升

特征重要性:随机森林

在这个阶段,我们知道随机森林的表现已经很出色了,下一步就是评估的表现是否能在更少的信息下保持不变。这可以通过选择几个特征来完成,这些特征是进行预测的基础:

  • 首先,让我们导入所有我们需要的sklearn子包:train_test_splitclassification_reportRandomForestClassifierGradientBoostingClassifier
#Importing libraries
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn.ensemble import RandomForestClassifier,
GradientBoostingClassifier
  • 在运行单元之前,需要再次设置输入和目标变量,以避免任何问题
  • 我们可以通过分配 80% 训练数据和 20% 测试来分割数据集。我决定将random_state=56设置为结果再现性。它可以是你想要的任何自然数。
  • 我们用RandomForestClassifier()函数创建一个对象。
  • 此时,命令 RE.fit 开始特征(X_train)和目标变量(y_train)的训练阶段
  • 一旦在 80%的数据集上训练了分类器,我们就可以通过创建predicted_RF对象在剩余的 20%上测试它的准确性
  • 最后,分类报告告诉我们经过训练的分类器的性能
#Defining input and target variable
x = df.drop('class', axis=1)
y = df['class']#Splitting dataset between training and testing with a 80-20 #allocation
X_train, X_test, y_train, y_test = train_test_split(x, y, test_size = 0.2, random_state = 56)#Classifier Object
RF = RandomForestClassifier()#Fitting classifier to data
RF.fit(X_train, y_train)#Predicting testing records
predicted_RF = RF.predict(X_test)#Printing classification report
print(classification_report(y_test, predicted_RF))

从我们在选型阶段看到的情况来看,精度有了进一步的提高。该算法能够在 100%的情况下识别蘑菇是可食用的还是有毒的。产生输出的信息目前来自所有特征

现在的问题是:

“有没有比其他更根本的特征?当我看到一个我想收集的蘑菇时,我需要特别注意什么?”

 precision    recall  f1-score   support

           0       1.00      1.00      1.00       841   
           1       1.00      1.00      1.00       784 accuracy                           1.00      1625  
   macro avg       1.00      1.00      1.00      1625
weighted avg       1.00      1.00      1.00      1625

运行下面的代码单元格后,可以确定上面的答案。这看起来很复杂,但我们可以一点一点地分解它:

  • 单元格创建两列:一列名为feature,另一列名为feature_importance,第一列列出了数据集中包含的所有列:Cap-shapeCap-surfaceCap-color
  • 第二列包含数据集每一列的所有关联要素重要性值。如果你只是想要这个值,你需要对随机森林算法使用命令RF.feature_importances_(其他分类器可能有不同的名字)
  • 然后这两列一起被转换成熊猫数据帧
  • 结果以我可以用命令to_markdown复制和粘贴的格式打印出来
##RF feature importancefeature_importance = pd.DataFrame(
{'feature':list(X_train.columns),
'feature_importance':[abs(i) for i in RF.feature_importances_]}
)print(feature_importance.to_markdown())

可以看出,要素重要性报告的值从 0 到 0.002 一直到 0.2。没有特别的原因,我选择了报告值至少为 0.1 或接近 0.1 的行。截止日期留给我们 4 个特征用于下一个模型:odorgill-sizegill-colorspore-print-color

|    | feature                  |   feature_importance |
|---:|:-------------------------|---------------------:|
|  0 | cap-shape                |           0.00488162 |
|  1 | cap-surface              |           0.00917991 |
|  2 | cap-color                |           0.013382   |
|  3 | bruises                  |           0.054723   |
|  4 | odor                     |           0.183597   |
|  5 | gill-attachment          |           0.00193266 |
|  6 | gill-spacing             |           0.03089    |
|  7 | gill-size                |           0.101708   |
|  8 | gill-color               |           0.122184   |
|  9 | stalk-shape              |           0.0202438  |
| 10 | stalk-root               |           0.0601195  |
| 11 | stalk-surface-above-ring |           0.0411767  |
| 12 | stalk-surface-below-ring |           0.040044   |
| 13 | stalk-color-above-ring   |           0.0141602  |
| 14 | stalk-color-below-ring   |           0.0147517  |
| 15 | veil-type                |           0          |
| 16 | veil-color               |           0.00194969 |
| 17 | ring-number              |           0.0151127  |
| 18 | ring-type                |           0.0839357  |
| 19 | spore-print-color        |           0.0978179  |
| 20 | population               |           0.0604895  |
| 21 | habitat                  |           0.0277208  |

现在我们知道了最重要的特性,我们可以重复训练和测试过程。这次x只有四列我们确定为最重要的特性。目标变量y保持不变。

  • 我们使用相同的方法将数据集分为训练和测试。
  • 创建RF对象
  • ****训练模型测试20%的数据
  • 打印分类报告****
##RF after feature selection #Defining input and target variable while dropping unimportant #features
x = df[['odor', 'gill-size', 'gill-color', 'spore-print-color']]
y = df['class']#Splitting dataset into training and testing
X_train, X_test, y_train, y_test = train_test_split(x, y, test_size = 0.2, random_state = 56)#Calling classifier
RF = RandomForestClassifier()#Fitting classifier to data
RF.fit(X_train, y_train)#Predicting testing records
predicted_RF = RF.predict(X_test)#Printing classification prediction
print(classification_report(y_test, predicted_RF))

足够令人惊讶的是,该模型保持了与处理 21 特征时相同的精度,这一次仅通过使用 4 个。这向我们表明,尤其是当我们将模型投入生产时,模型所依赖的特性的数量应该限制在最重要的特性上。一般来说,更多的特性对应于部署计算成本更高的模型。

 precision    recall  f1-score   support

           0       1.00      1.00      1.00       841   
           1       1.00      1.00      1.00       784 accuracy                           1.00      1625  
   macro avg       1.00      1.00      1.00      1625
weighted avg       1.00      1.00      1.00      1625

特征重要性:梯度推进分类器

在这个最后阶段,我们必须重复随机森林模型的过程,但使用不同的算法,梯度推进,在模型选择阶段表现最好。

  • 在前一个单元中,我们重新定义了xy,使它们只包含最重要的特性。我们需要重新分配所有数据集列,以评估模型的整体性能。
  • 数据集遵循通常的 80/20 分割比率,具有相同的random_state
  • 对象XGB包含函数GradientBoostingClassifier()
  • 使用命令fit,分类器开始基于训练数据进行学习
  • 命令predict()执行测试阶段
  • 我们最终可以打印分类报告来评估性能****
#Defining input and target variable
x = df.drop('class', axis=1)
y = df['class']#Splitting dataset between training and testing with a 80-20 #allocation
X_train, X_test, y_train, y_test = train_test_split(x, y, test_size = 0.2, random_state = 56)#Calling classifier
XGB = GradientBoostingClassifier()#Fitting classifier to data
XGB.fit(X_train, y_train)#Predicting testing records
predicted_XGB = XGB.predict(X_test)#Printing classification report
print(classification_report(y_test, predicted_XGB))

当对所有特征进行训练时,梯度增强分类器报告与随机森林分类器相同的分数。在这个阶段,我们可以问自己以前的问题:

“有没有比其他更根本的特征?当我看到一个我想收集的蘑菇时,我需要特别注意什么?”

两个不同的分类器可能通过使用最相关的不同特征来得到相同的结果。

 precision    recall  f1-score   support

           0       1.00      1.00      1.00       841   
           1       1.00      1.00      1.00       784 accuracy                           1.00      1625  
   macro avg       1.00      1.00      1.00      1625
weighted avg       1.00      1.00      1.00      1625

获取梯度增强算法的特征重要性的命令对于随机森林模型是相同的:feature_importances_。代码背后的逻辑和以前一样。它创建了两列,一列包含所有的特性名称,另一列包含所有的特性重要性分数

##XGB feature importance#Calculating feature importances
feature_importance=pd.DataFrame({'feature':list(X_train.columns),'feature_importance':[abs(i) for i in XGB.feature_importances_]})#Printing dataframe
print(feature_importance.to_markdown())

你可能会注意到这些值非常相似,如果我们使用我们之前建立的 > 0.1 截止值规则,同样的四个特征被确定为最相关:odorgill-sizegill-colorspore-print-color

|    | feature                  |   feature_importance |
|---:|:-------------------------|---------------------:|
|  0 | cap-shape                |           0.00458413 |
|  1 | cap-surface              |           0.0146785  |
|  2 | cap-color                |           0.0127857  |
|  3 | bruises                  |           0.0573168  |
|  4 | odor                     |           0.181369   |
|  5 | gill-attachment          |           0.00358367 |
|  6 | gill-spacing             |           0.0492609  |
|  7 | gill-size                |           0.115759   |
|  8 | gill-color               |           0.0958662  |
|  9 | stalk-shape              |           0.0229765  |
| 10 | stalk-root               |           0.0531794  |
| 11 | stalk-surface-above-ring |           0.0495843  |
| 12 | stalk-surface-below-ring |           0.0367454  |
| 13 | stalk-color-above-ring   |           0.0128033  |
| 14 | stalk-color-below-ring   |           0.0138009  |
| 15 | veil-type                |           0          |
| 16 | veil-color               |           0.00169852 |
| 17 | ring-number              |           0.0116543  |
| 18 | ring-type                |           0.0784959  |
| 19 | spore-print-color        |           0.104922   |
| 20 | population               |           0.0464761  |
| 21 | habitat                  |           0.0324597  |

我们已经为梯度增强模型确定了四个最相关的特征,所以让我们重复我们为随机森林所做的相同过程。

##XGB after feature selection#Defining input and target variable while dropping unimportant #features
x = df[['odor', 'gill-size', 'gill-color', 'spore-print-color']]
y = df['class']#Splitting dataset between training and testing with a 80-20 #allocation
X_train, X_test, y_train, y_test = train_test_split(x, y, test_size = 0.2, random_state = 56)#Calling classifier
XGB = GradientBoostingClassifier()#Fitting classifier to data
XGB.fit(X_train, y_train)#Predicting testing records
predicted_XGB = XGB.predict(X_test)#Printing classification report
print(classification_report(y_test, predicted_XGB))

具有 4 个基本特征的更新型号比具有所有 21 个特征的型号稍差。差异是 0.01,一个难以置信的小实体,这意味着大约有 16 个记录在超过 1600 个记录中被错误分类

 precision    recall  f1-score   support

           0       0.99      1.00      1.00       841   
           1       1.00      0.99      1.00       784 accuracy                           1.00      1625  
   macro avg       1.00      1.00      1.00      1625
weighted avg       1.00      1.00      1.00      1625

同样,结果与上一个极其接近。主要区别在于使用的特征数量,因此我们可以假设该模型在计算上应该更便宜,因此从 ML 操作的角度来看更好。

跟踪所有不需要进行预测和运行模型的要素可以节省万亿字节的空间。在目前的设置中,这没有什么区别,但对于大型科技公司来说,取消一整列可以节省数百万美元。

结论

很明显,在有很多特性的情况下,选择几个是很重要的。我们能够通过在两种情况下保持相同的性能来降低计算成本。我们用较少的努力获得了类似的结果。

当然,这并非没有挑战,需要解决这些挑战以进一步改进。

首先,一些基本特征甚至连专家都很难识别。更具体地说,值得一提的是“气味”。你能认出“茴香”和“杂酚油”的区别吗?我真的不会。****

最重要的是,我们不要忘记过度配合。所有模型都有令人难以置信的高总体精度分数,接近完美。明确建议将模型部署在相似数据集中的未知记录上,以进一步测试其可靠性。

****需要物种 id来将模型的范围扩展到除了蘑菇和蘑菇以外的新蘑菇家族。

我确实有一个最终免责声明给那些读完这篇文章后想尝试蘑菇狩猎的人。没有专家陪你一起采摘蘑菇是根本不推荐的。美国的一些州和一些国家要求有执照才能练习。除了法律,一个好的经验法则是不要碰它,除非你 100%确定它可以食用。每种蘑菇对生态系统都有一定的贡献,所以如果不确定,最好让它留在原地!

最后,如果您喜欢该内容,请考虑添加一个关注,以便在新文章发布时得到通知。如果你对这篇文章有什么要考虑的,写在评论里吧!我很想读读它们:)谢谢你的阅读!

PS:如果你喜欢我写的东西,如果你能通过 这个链接 订阅一个中等会员,那对我来说就是全世界。有了会员资格,你就获得了媒体文章提供的惊人价值,这是支持我的内容的一种间接方式!

参考

[1] UCI 机器学习知识库:蘑菇数据集。(2022).检索于 2022 年 9 月 13 日,来自 Uci.edu 网站:https://archive.ics.uci.edu/ml/datasets/Mushroom

[2]兹恩,a .,克雷默,n .,索南堡,s .,和勒施,G. (2009 年 9 月)。特征重要性排序度量。在关于数据库中的机器学习和知识发现的欧洲联合会议(第 694–709 页)。斯普林格,柏林,海德堡。

[3] Biau,g .,& Scornet,E. (2016)。随机森林导游。测试25 (2),197–227。https://doi.org/10.1007/s11749-016-0481-7

[4]j . h .弗里德曼(2002 年)。随机梯度增强。计算统计&数据分析38 (4),367–378。https://doi . org/10.1016/s 0167-9473(01)00065-2

功能交互:概述

原文:https://towardsdatascience.com/feature-interactions-524815abec81

介绍

当预测模型中的要素相互作用时,预测不能表示为要素效果的总和,因为一个要素的效果取决于另一个要素的值。克里斯托弗·莫尔纳尔

特征对变量预测的复杂协同效应称为特征相互作用。特征交互的另一个方面是一个特征相对于与之交互的另一个特征的变化。这些变量通常被称为交互变量

通常,我们会在数据集中遇到成对的特征交互,其中特征以 2 个为一组进行交互。例如,患心脏病的风险取决于你的身体质量指数,它被定义为体重/身高。这里, {体重,身高} 是成对交互。不太常见的高阶特征相互作用,我们看到两个以上的特征相互作用,在科学中它们有如此复杂的关系。例如, {x₁,x₂,x₃,x₄}log(x₁ + x₂ + x₃x₄ )* 中的四阶互动。

识别数据集中存在的要素交互非常有用,原因有多种,包括:

  • 了解数据集中要素之间的关系及其对预测的影响,避免仅使用主要影响而不使用交互影响来解释模型的偏见
  • 使用关于交互的信息来显式地构建表达模型
  • 提高模型性能的工程特征

分析功能交互

一种用于可视化交互效应的流行方法是部分相关图(PDP) 。我们可以使用 PDP 来可视化 2 个特征如何随预测而变化。像 ICEshapley 这样的变体也以类似的方式帮助你可视化交互效果。下面我们看一个加州住房数据集的例子(使用 pdpbox ),随着中值收入和房屋平均占有者的增加,房价也随之上涨。

PDP 交互图示例

虽然这些方法在解释交互效应方面很棒,但在自动识别数据中的所有特征交互方面,它们是相当乏味的工具,尤其是如果您有一个大的特征空间。我们可以使用的一种简单方法是对基于 F 统计的所有特征和过滤器交互组合应用 2-way ANOVA 方法。但是,它们在捕捉复杂关系方面效率不高。然而, Friedman 的 H 统计量使用之前讨论的部分相关性来识别数据集中给定要素顺序的交互强度。下图显示了加州住房数据集中前 10 个交互的 H 统计数据(使用 sklearn_gbmi 计算):

虽然这些方法对于成对的相互作用非常有效,但是它们很难用于识别更高阶的相互作用。我遇到的一个有趣的方法是神经交互检测。该方法分析前馈神经网络的权重,以识别任意阶的相互作用。从他们的例子中,给出了以下合成数据

X1, X2, X3, X4, X5, X6, X7, X8, X9, X10 = X.transpose()interaction1 = np.exp(np.abs(X1-X2))                        
interaction2 = np.abs(X2*X3)  
interaction3 = -1*(X3**2)**np.abs(X4) 
interaction4 = (X1*X4)**2
interaction5 = np.log(X4**2 + X5**2 + X7**2 + X8**2)
main_effects = X9 + 1/(1 + X10**2)Y =              interaction1 + interaction2 + interaction3 + interaction4 + interaction5 + main_effects
ground_truth = [     {1,2},        {2,3},         {3,4},         {1,4},        {4,5,7,8}     ]

该方法检测以下交互

Pairwise interactions              Arbitrary-order interactions
(1, 2)        7.8430                      (1, 2)        6.8951        
(4, 8)        3.1959                      (2, 3)        2.0953        
(5, 8)        3.0521                      (7, 8)        1.7971        
(7, 8)        3.0290                      (4, 5, 8)     1.6026        
(4, 5)        2.8506                      (1, 4)        1.5912        
(2, 3)        2.6294                      (5, 7)        1.5261        
(1, 4)        2.5037                      (3, 4)        1.3500        
(5, 7)        2.4460                      (4, 7)        1.0580        
(4, 7)        2.2369                      (4, 7, 8)     0.7727        
(3, 4)        1.8870                      (4, 5, 7, 8)  0.5467

虽然该算法并不完美,但它确实提供了很多信息。

然而,这些方法仍然没有给我们任何关于相互作用的本质的信息。如果您试图设计有助于模型性能的特性,识别交互的本质可能会特别有用。如果我们对关系有了初步的猜测,我们可以使用一些简单的试探法来选择交互。例如, pycaret 库获取所有可能的特征对的乘积(以及可选的比率),并使用随机森林、lightgbm 或相关性等方法识别最重要的交互。对于 california housing 数据集,pycaret 选择了以下交互阈值为 5%的交互:

['Longitude_multiply_MedInc', 'Latitude_multiply_AveOccup',
 'AveBedrms_multiply_MedInc', 'MedInc_multiply_Longitude',
 'HouseAge_multiply_MedInc', 'Longitude_multiply_Latitude',
 'Latitude_multiply_MedInc']

更复杂的方法是使用基于遗传算法的符号回归方法。您甚至可以在这些算法中使用自定义函数集。对于同一数据集, gplearn 的符号回归器生成以下关系:

符号回归器生成的表达式

该方法的随机性和生成表达式的复杂性是其主要缺点。类似的方法如专长规则适应也可以使用。这些方法倾向于产生更易解释的表达式。

结论

识别和理解特征间的相互作用对于开发和解释模型至关重要。然而,上面介绍的所有识别功能交互的自动化方法都远非完美,应该谨慎使用并进行严格分析。还有很多其他工具可以直接或间接地帮助检测功能交互。

特性选择:一个全面的策略列表

原文:https://towardsdatascience.com/feature-selection-a-comprehensive-list-of-strategies-3fecdf802b79

里卡多·戈麦斯·安吉尔在 Unsplash 上的照片

11 种特征选择技术的清单

假设您有一个包含 25 列和 10,000 行的数据集。经过一些特征工程,最终你得到了 45 列。在这 45 个特征中,你能保留几个?过多的特征会增加模型的复杂性和过度拟合,过少的特征会使模型欠拟合。因此,您优化您的模型,使其足够复杂,以便其性能可以推广,但又足够简单,以便易于训练、维护和解释。

“特性选择”意味着你可以保留一些特性,放弃一些其它的特性。问题是——如何决定保留哪些特征,去掉哪些特征?本文的目的是概述一些特性选择策略:

  • 删除未使用的列
  • 删除缺少值的列
  • 不相关特征
    —数字
    —分类
  • 低方差特征
  • 多重共线性
    —数字
    —分类
  • 特征系数
  • p 值
  • 差异通货膨胀系数(VIF)
  • 基于特征重要性/杂质的特征选择
  • 利用 sci-kit learn 进行自动特征选择
    —基于卡方的技术
    —正则化
    —顺序选择
  • 主成分分析

你不太可能在一个项目中同时使用这些策略,但是,手边有这样一个清单可能会很方便。

数据描述

麻省理工学院许可下发布,本次演示的数据集来自py caret——一个开源的低代码机器学习库。

数据集相当干净,但我做了一些预处理,我在这里跳过了。请注意,我使用这个数据集来演示不同的特征选择策略是如何工作的,而不是构建一个最终的模型,因此模型性能是不相关的(但这将是一个有趣的练习!).

让我们加载数据集:

import pandas as pddata = '[https://raw.githubusercontent.com/pycaret/pycaret/master/datasets/automobile.csv'](https://raw.githubusercontent.com/pycaret/pycaret/master/datasets/automobile.csv')
df = pd.read_csv(data)df.sample(5)

数据集的前几行(图:作者)

该数据集包含 202 行和 26 列,每行代表一辆汽车的实例,每列代表其功能和相应的价格。这些列包括:

df.columns>> Index(['symboling', 'normalized-losses', 'make', 'fuel-type', 'aspiration', 'num-of-doors', 'body-style', 'drive-wheels', 'engine-location','wheel-base', 'length', 'width', 'height', 'curb-weight', 'engine-type', 'num-of-cylinders', 'engine-size', 'fuel-system', 'bore', 'stroke', 'compression-ratio', 'horsepower', 'peak-rpm', 'city-mpg', 'highway-mpg', 'price'], dtype='object')

现在,让我们深入研究特性选择的 11 个策略。

移除未使用的列

当然,最简单的策略是运用你的直觉。有时很明显,一些列在最终的模型中不会以任何形式使用(如“ID”、“FirstName”、“LastName”等列)。如果您知道某个特定的列不会被使用,那么可以直接删除它。在我们的数据中,没有一列如此突出,所以在这一步中我不会删除任何列。

删除缺少值的列

具有缺失值在机器学习中是不可接受的,因此人们应用不同的策略来清理缺失数据(例如,插补)。但是,如果一列中丢失了大量数据,一种策略是将其完全删除。

在我们的数据集中,有显著缺失值的列是normalized-losses,我将删除它。

# total null values per column
df.isnull().sum()>>
symboling             0
normalized-losses    35
make                  0
fuel-type             0
aspiration            0
num-of-doors          2
body-style            0
drive-wheels          0
engine-location       0
wheel-base            0
length                0
width                 0
height                0
curb-weight           0
engine-type           0
num-of-cylinders      0
engine-size           0
fuel-system           0
bore                  0
stroke                0
compression-ratio     0
horsepower            0
peak-rpm              0
city-mpg              0
highway-mpg           0
price                 0
dtype: int64

不相关的特征

无论算法是回归(预测一个数)还是分类(预测一个类),特征都必须与目标相关。如果某个特征没有表现出相关性,那么它就是一个主要的淘汰目标。您可以分别测试数值特征和分类特征的相关性。

a)数字特征

# correlation between target and features
(df.corr().loc['price']
 .plot(kind='barh', figsize=(4,10)))

数字特征和目标之间的相关性(图:作者)

在这个例子中,诸如峰值转速压缩比、冲程、缸径、高度和象征的等特征与价格的相关性很小,因此我们可以忽略它们。

您可以手动删除列,但是我更喜欢使用相关阈值(在本例中为 0.2)以编程方式来完成:

# drop uncorrelated numeric features (threshold <0.2)
corr = abs(df.corr().loc['price'])
corr = corr[corr<0.2]
cols_to_drop = corr.index.to_list()
df = df.drop(cols_to_drop, axis=1)

b)分类特征

同样,您可以使用箱线图来查找目标特征和分类特征之间的相关性:

import seaborn as snssns.boxplot(y = 'price', x = 'fuel-type', data=df)

按燃料类型分类的汽车价格(图:作者)

柴油型车的中位价格高于燃气型车。这意味着这个分类变量可以解释汽车价格,所以我不会放弃它。您可以像这样单独检查每个分类列。

低方差特征

举个极端的例子,我们假设所有的车都有相同的公路——mpg(mpg:英里每加仑)。你觉得这个功能有用吗?没有,因为它的方差正好为 0。我们可以选择放弃这样的低方差特性。让我们检查一下我们的功能差异:

import numpy as np# variance of numeric features
(df
 .select_dtypes(include=np.number)
 .var()
 .astype('str'))

数字特征的方差(图:作者)

这里“bore”具有极低的方差,因此这是消除的理想候选。然而,在这种特殊情况下,我不愿意放弃它,因为它的值介于 2.54 和 3.94 之间,因此方差预计较低:

df['bore'].describe()

一个特性的统计概要(图:作者)

多重共线性

当任何两个要素之间存在相关性时,就会出现多重共线性。在机器学习中,期望每个特征应该独立于其他特征,即它们之间没有共线性。正如你将在下面看到的,马力大的车辆往往有大的发动机尺寸并不奇怪。所以你可能想去掉其中一个,让另一个决定目标变量——价格

您可以分别测试数值要素和分类要素的多重共线性:

a)数字特征

热图是直观检查和寻找相关要素的最简单方法。

import matplotlib.pyplot as pltsns.set(rc={'figure.figsize':(16,10)})
sns.heatmap(df.corr(),
            annot=True,
            linewidths=.5,
            center=0,
            cbar=False,
            cmap="PiYG")
plt.show()

用于检查数字要素间多重共线性的热图(图:作者)

正如你所看到的,大多数特征在某种程度上是相互关联的,但有些特征具有非常高的相关性,例如长度轴距发动机尺寸马力

您可以基于关联阈值手动或以编程方式删除这些功能。我将手动删除共线性阈值为 0.80 的要素。

# drop correlated features
df = df.drop(['length', 'width', 'curb-weight', 'engine-size', 'city-mpg'], axis=1)

请注意,您还可以使用一种称为方差膨胀因子(VIF)的方法来确定多重共线性,并根据高 VIF 值删除要素。稍后我会展示这个例子。

b)分类变量

与数值要素类似,您也可以检查分类变量之间的共线性。像卡方独立性检验这样的统计检验对它来说是理想的。

让我们检查一下数据集中的两个分类列— 燃料类型车身样式 —是独立的还是相关的。

首先,我们将选择感兴趣的分类特征:

df_cat = df[['fuel-type', 'body-style']]
df_cat.sample(5)

为独立性测试选择的两个分类特征(图:作者)

然后,我们将在每一列中创建类别的交叉表/列联表。

crosstab = pd.crosstab(df_cat['fuel-type'], df_cat['body-style'])
crosstab

两个分类特征的交叉表/列联表(图:作者)

最后,我们将对列联表进行卡方检验,这将告诉我们这两个特征是否独立。

from scipy.stats import chi2_contingencychi2_contingency(crosstab)

独立性卡方检验的结果(图:作者)

按照出现的顺序,输出是卡方值、 p 值、自由度和一组预期频率。

p 值是<0.05, thus we can reject the null hypothesis that there’s no association between features, i.e., there’s a statistically significant relationship between the two features.

Since there’s an association between the two features, we can choose to drop one of them.

我现在将换档一点……

到目前为止,我已经展示了在实现模型之前应用的特性选择策略。这些策略在构建初始模型的第一轮特征选择中非常有用。但是,一旦构建了模型,您将获得关于模型性能中每个特征的适合度的进一步信息。根据这些新信息,您可以进一步确定要保留哪些功能。

下面我将展示其中的一些方法。

但是首先,我们需要使模型适合数据集,因此需要一些数据预处理。我正在做最少的数据准备,只是为了演示特征选择方法。

# drop columns with missing values
df = df.dropna()from sklearn.model_selection import train_test_split# get dummies for categorical features
df = pd.get_dummies(df, drop_first=True)# X features
X = df.drop('price', axis=1)# y target
y = df['price']# split data into training and testing set
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)from sklearn.linear_model import LinearRegression # scalingfrom sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.fit_transform(X_test)# convert back to dataframe
X_train = pd.DataFrame(X_train, columns = X.columns.to_list())
X_test = pd.DataFrame(X_test, columns = X.columns.to_list())# instantiate model
model = LinearRegression()# fit
model.fit(X_train, y_train)

现在我们已经拟合了模型,让我们做另一轮的特征选择。

特征系数

如果你正在运行一个回归任务,那么特征适合度的一个关键指标是回归系数(所谓的 beta 系数),它显示了特征在模型中的相对贡献。有了这些信息,您就可以删除贡献很小或没有贡献的功能。

# feature coefficients
coeffs = model.coef_# visualizing coefficients
index = X_train.columns.tolist()(pd.DataFrame(coeffs, index = index, columns = ['coeff']).sort_values(by = 'coeff')
 .plot(kind='barh', figsize=(4,10)))

每个特性的 Beta 值/系数(图:作者)

如你所见,有些贝塔系数很小,对汽车价格的预测贡献不大。您可以过滤掉这些特征:

# filter variables near zero coefficient value
temp = pd.DataFrame(coeffs, index = index, columns = ['coeff']).sort_values(by = 'coeff')
temp = temp[(temp['coeff']>1) | (temp['coeff']< -1)]# drop those features
cols_coeff = temp.index.to_list()
X_train = X_train[cols_coeff]
X_test = X_test[cols_coeff]

p 值

在回归中,p 值告诉我们预测值和目标值之间的关系是否具有统计显著性。statsmodels库用特征系数和相关的 p 值给出了回归输出的漂亮摘要。

如果一些特性不重要,您可以逐个删除它们,每次都重新运行模型,直到您找到一组具有重要的 p 值并通过更高的调整 R2 提高了性能的特性。

import statsmodels.api as sm
ols = sm.OLS(y, X).fit()
print(ols.summary())

具有 beta 值和统计显著性的回归结果的部分摘要(图:作者)

差异通货膨胀系数(VIF)

正如我前面提到的,方差膨胀因子(VIF)是测量多重共线性的另一种方法。它被测量为总模型方差与每个独立特征方差的比率。某个功能的高 VIF 表明它与一个或多个其他功能相关。根据经验法则:

VIF = 1 表示无相关性,
VIF = 1–5 中度相关,
VIF > 5 高度相关

可以想象,VIF 是一种消除多重共线性要素的有用技术。在我们的演示中,让我们大方一点,保留所有 VIF 低于 10 的特性。

from statsmodels.stats.outliers_influence import variance_inflation_factor# calculate VIF
vif = pd.Series([variance_inflation_factor(X.values, i) for i in range(X.shape[1])], index=X.columns)# display VIFs in a table
index = X_train.columns.tolist()
vif_df = pd.DataFrame(vif, index = index, columns = ['vif']).sort_values(by = 'vif', ascending=False)
vif_df[vif_df['vif']<10]

基于低 VIF 选择的特征(图:作者)

基于特征重要性/杂质的选择

决策树/随机森林使用最大程度减少杂质的特征来分割数据(根据基尼杂质或信息增益来衡量)。这意味着,找到最佳特征是算法在分类任务中如何工作的关键部分。然后,我们可以通过feature_importances_属性访问最佳特性。

让我们在数据集上实现一个随机森林模型,并过滤一些要素。

from sklearn.ensemble import RandomForestClassifier# instantiate model
model = RandomForestClassifier(n_estimators=200, random_state=0)
# fit model
model.fit(X,y)

现在我们来看看特性的重要性:

#  feature importance
importances = model.feature_importances_# visualization
cols = X.columns
(pd.DataFrame(importances, cols, columns = ['importance'])
 .sort_values(by='importance', ascending=True)
 .plot(kind='barh', figsize=(4,10)))

随机森林实现中的特性重要性(图:作者)

上面的输出显示了每个特性在减少每个节点/分裂处的杂质方面的重要性。

由于随机森林分类器有许多估计器(例如,在上面的例子中有 200 棵决策树),我们可以用置信区间来计算相对重要性的估计。让我们想象一下。

# calculate standard deviation of feature importances 
std = np.std([i.feature_importances_ for i in model.estimators_], axis=0)# visualization
feat_with_importance  = pd.Series(importances, X.columns)
fig, ax = plt.subplots(figsize=(12,5))
feat_with_importance.plot.bar(yerr=std, ax=ax)
ax.set_title("Feature importances")
ax.set_ylabel("Mean decrease in impurity")

随机森林实现中具有置信区间的特征重要性(图:作者)

既然我们知道了每个特性的重要性,我们就可以手动地(或者编程地)决定保留哪些特性,放弃哪些特性。

通过 Scikit Learn 实现自动特征选择

幸运的是,在sklearn库中有一个完整的模块,只用几行代码就可以处理特性选择。

sklearn中有许多自动化的流程,但在这里我只演示几个:

# import modules
from sklearn.feature_selection import (SelectKBest, chi2, SelectPercentile, SelectFromModel, SequentialFeatureSelector, SequentialFeatureSelector)

a)基于卡方的技术

基于卡方的技术基于一些预定义的分数选择特定数量的用户定义的特征(k)。这些分数是通过计算 X(自变量)和 y(因变量)之间的卡方统计来确定的。在sklearn中,你需要做的就是确定你想要保留多少功能。如果您想保留 10 个特性,实现将如下所示:

# select K best features
X_best = SelectKBest(chi2, k=10).fit_transform(X,y)# number of best features
X_best.shape[1]>> 10

如果有大量的特性,你可以指定你想要保留的特性的百分比。假设我们想保留 75%的特性,放弃剩下的 25%:

# keep 75% top features 
X_top = SelectPercentile(chi2, percentile = 75).fit_transform(X,y)# number of best features
X_top.shape[1]>> 36

b)正规化

正则化减少了过度拟合。如果有太多的特征,正则化会通过收缩特征系数(称为 L2 正则化)或将一些特征系数设置为零(称为 L1 正则化)来控制它们的效果。

一些模型内置了 L1/L2 正则化作为惩罚特征的超参数。使用元转换器SelectFromModel可以消除这些特征。

让我们用惩罚=‘L1’来实现一个LinearSVC 算法。然后我们将使用SelectFromModel 删除一些功能。

# implement algorithm
from sklearn.svm import LinearSVC
model = LinearSVC(penalty= 'l1', C = 0.002, dual=False)
model.fit(X,y)# select features using the meta transformer
selector = SelectFromModel(estimator = model, prefit=True)X_new = selector.transform(X)
X_new.shape[1]>> 2# names of selected features
feature_names = np.array(X.columns)
feature_names[selector.get_support()]>> array(['wheel-base', 'horsepower'], dtype=object)

c)顺序选择

顺序特征选择是一种经典的统计技术。在这种情况下,您可以一次添加/删除一个特征,并检查模型性能,直到它根据您的需要进行了优化。

顺序选择有两种变体。正向选择技术从 0 个特征开始,然后添加一个最大程度地减小误差的特征;然后添加另一个特性,以此类推。

反向选择的工作方向相反。该模型从包括所有特征开始,并计算误差;然后,它消除了一个进一步减少误差的特征。重复该过程,直到剩余期望数量的特征。

# instantiate model
model = RandomForestClassifier(n_estimators=100, random_state=0)# select features
selector = SequentialFeatureSelector(estimator=model, n_features_to_select=10, direction='backward', cv=2)
selector.fit_transform(X,y)# check names of features selected
feature_names = np.array(X.columns)
feature_names[selector.get_support()]>> array(['bore', 'make_mitsubishi', 'make_nissan', 'make_saab',
       'aspiration_turbo', 'num-of-doors_two', 'body style_hatchback', 'engine-type_ohc', 'num-of-cylinders_twelve', 'fuel-system_spdi'], dtype=object)

主成分分析

主成分分析的主要目的是降低高维特征空间的维数。在这种情况下,原始特征被重新投影到新的维度(即主成分)。最终目标是找到最能解释数据方差的分量数。

# import PCA module
from sklearn.decomposition import PCA# scaling data
X_scaled = scaler.fit_transform(X)# fit PCA to data
pca = PCA()
pca.fit(X_scaled)
evr = pca.explained_variance_ratio_# visualizing the variance explained by each principal componentsplt.figure(figsize=(12, 5))
plt.plot(range(0, len(evr)), evr.cumsum(), marker="o", linestyle="--")plt.xlabel("Number of components")
plt.ylabel("Cumulative explained variance")

主成分分析解释的累积方差(图:作者)

如您所见,20 个主成分解释了 80%以上的方差,因此您可以将您的模型与这 20 个成分相匹配。您可以预先确定方差阈值,并选择所需的主成分数。

一锤定音

希望这是一个有用的指南,可以应用于特征选择的各种技术。一些技术在之前应用于拟合模型,例如删除具有缺失值的列、不相关的列、具有多重共线性的列以及使用 PCA 进行降维,而其他技术在基础模型实施之后应用,例如特征系数、p 值、VIF 等。你可能永远不会在一个项目中使用所有的策略,但是,你可以把这个列表作为一个清单。

我已经在 GitHub 上传了这里描述的所有技术的 Jupyter 笔记本。

感谢您的阅读。请随意订阅以获得我即将发表的文章的通知,或者通过 LinkedIn 与我联系。

特征选择:为你的机器学习算法选择正确的特征

原文:https://towardsdatascience.com/feature-selection-choosing-the-right-features-for-your-machine-learning-algorithm-379bda9f3e05

有时候,少即是多

选择,还是不选择…照片由edu·格兰德Unsplash 上拍摄

为什么我们要选择一些特征而忽略其余的呢?拥有更多的特征不是对我们模型的准确性有好处吗?

选择正确的特征,忽略不合适的特征,是任何机器学习项目中至关重要的一步。这可以产生良好的模型性能,并节省您的时间。它还可以帮助您更容易地解释模型的输出。但是拥有更多的特征将意味着模型有更多的数据来训练,并且应该意味着模型将更加准确,对吗?不完全是。

拥有太多的特征会导致算法容易陷入过度拟合。过度拟合是指模型推广到不相关的数据或异常值。另一个仔细选择特性的好理由是所谓的维度诅咒。通常每个特征都存储在一个维度中。算法在高维情况下变得更难设计,因为运行时间往往随着维数呈指数增长。因此,当我们选择最合适的特征而忽略其他特征时,这是有意义的,并且提供了好处。

我们如何选择最佳特征进行训练?

有两种选择特征的方法。首先,人们可以通过直方图等用图形表示来人工观察特征。第二种方式是通过自动选择最佳特征。

手动做事…

我们可以通过直方图等图形表示来手动观察特征。然后,通过识别可以相互区分的特征和相互重叠的特征,我们可以决定哪一个将是最好的。让我们看一个例子。

我们将看看虹膜数据集。它有 150 朵鸢尾花的数据,包括 3 个品种(鸢尾、海滨鸢尾和杂色鸢尾)。花的四个特征在数据集中可用(花的萼片和花瓣的宽度和长度)。数据集的摘录如下所示。

Here, you can see the **four available features** in the iris dataset for the iris flower species known as Setosa. 
(the first 5 rows of the dataset are shown) **Sepal.Length  Sepal.Width  Petal.Length  Petal.Width** Species 
1          5.1          3.5           1.4          0.2    setosa
2          4.9          3.0           1.4          0.2    setosa
3          4.7          3.2           1.3          0.2    setosa
4          4.6          3.1           1.5          0.2    setosa
5          5.0          3.6           1.4          0.2    setosaNote: When we set **dim = 0** in the below code, we are selecting the feature: **Sepal.Length**

代码加载虹膜数据集和绘制直方图的基础上,我们想要的功能。

使用上面的代码,我们为虹膜数据集的三个种类中的每一个绘制了直方图,为使用变量' dim' 选择的特定特征绘制了直方图。

我们可以使用 'iris.target' 来选择特定的物种,例如,在上面的代码中: iris.data[iris.target == 0,dim] 给出了鸢尾物种的数据特征:萼片长度。

通过查看生成的直方图,我们意识到特征重叠。这意味着我们选择的特征(萼片长度),由 dim = 0 给出,可能不足以区分不同类型的鸢尾花(Setosa,Versicolor 和 Virginica)。

上面代码的结果,功能是重叠的。

现在,让我们选择一个不同的特性。我们将使用 dim=3 选择特征 4(花瓣宽度)。下图显示了生成的直方图。

从上面的代码中获得的特性 3 的直方图。

如你所见,与我们观察到的另一个特征相比,这个特征在三种类型的花之间提供了足够好的分离。以这种方式观察直方图可以帮助我们对正在处理的数据获得更好的感觉或直觉,并识别合适的特征以及不太有用的特征。

当我们处理更多的功能时,手工的方法可能不合适。在这种情况下,我们可以利用自动特征选择方法。

注意:在我们使用的数据集中,长度用于特征。每个要素都有相同的单位(厘米)。但是一些数据集可能具有互不相同的要素。例如,一个要素可能以米为单位,而另一个要素可能是颜色。这可以引入它自己的一套复杂功能,我们将需要 标度 特性,这些我们将在本文的最后讨论。

自动特征选择

特征选择的一般程序是:

  • 通过与地面实况进行比较或通过比较每个要素的类之间的方差来计算每个要素的质量。
  • 接下来,根据计算出的质量对特征进行排序,只保留最好的。可以通过使用质量阈值或者通过简单地选择最佳 n 个特征来选择最佳特征。

为了选择特征子集,我们可以执行 正向特征选择、 逐步添加最佳尺寸或特征,或者执行 反向特征选择、 从所有特征开始,继续删除质量最差的特征。

我们如何计算一个特性的质量

我们要看的第一个质量指数叫做相关系数(又名皮尔逊相关)。相关系数是两个变量之间的协方差标准差之比。作为比值的结果,我们得到一个介于-1 和 1 之间的结果。

什么是 协方差

如果一个变量的较大值主要与另一个变量的较大值相对应,并且较小值也是如此(即变量往往表现出相似的行为),则协方差为正。

在相反的情况下,当一个变量的较大值主要对应于另一个变量的较小值时,协方差为负。

——魏斯斯坦,埃里克 W. 【协方差】数学世界

这一点通过观察下图可以看得很清楚。

两个随机变量的协方差的符号 XY

协方差可通过以下等式计算,其中 x̄和 ȳ分别代表 x 和 y 的平均值:

计算协方差的方程。来源:协方差

因此,相关系数可以计算如下:

计算相关系数的方程式

如果这两个特征是随机独立的,它们的相关性将为 0。然而,请记住,即使相关性为 0,也不一定意味着变量是独立的。可能存在相关性未捕捉到的潜在依赖关系。

还要注意,相关性并不意味着因果关系。看下面的图表。由于两起事件相似,关联度极高。但这是否意味着如果你吃了更多的奶酪,你很可能会被你的床单勒死?这里的数据纯属巧合。

食用奶酪与床单纠缠致死之间的关系。作者:泰勒·维根

特征选择相关性的缺点:

  • 相关性只查找线性关系
  • 这也只适用于两个类的问题

另一个可以使用的质量指标是费希尔比率。它测量变量的线性辨别能力,并具有以下公式。

计算费雪比的方程式。

这里,x̄和ȳ分别代表第 1 类和第 2 类的平均值,两类的方差以分母表示。这种方法的好处是,它为更复杂的标准提供了更快的计算速度。

还有许多其他可用的质量测量工具,如 Kullback-Leibler 散度、ANOVA 等,这里不做讨论。

特征选择可能存在的问题

尽管大多数算法相对简单和容易,但它们并不总是适用的。当试图确定使用哪种质量度量时,以及当试图在单个维度不产生任何结果的情况下初始化贪婪算法时,会出现困难。

此外,即使特性被看作是独立的,相互独立的,它们也常常相互依赖。结果,基于质量测量的特征选择将永远不会提供当两个特征被组合时可以观察到的相同信息。因此,利用不同维度之间共享的信息是有好处的。这可以通过变换特征空间(也称为压缩)来实现。为了实现这一点,可以使用主成分分析(PCA) 。我们将在另一篇文章中讨论 PCA。

具有非常不同的特征的问题

上面,我们讨论了拥有彼此不同的特性会带来问题。例如,一个特征的长度以厘米为单位,另一个特征是颜色。为了减轻这种情况,我们可以使用特征缩放。

缩放比例

  • 在 Iris 和 Digits 数据集中,所有要素的比例相等(单位为厘米)
  • 如果不是这样,单个特征可能会使结果产生偏差。
  • 例如,具有高方差的特征支配距离测量。

解决方案:

  • 将要素缩放至平均值为 0,方差为 1

如果已知总体平均值和总体标准偏差,则通过以下公式将原始分数 x 转换为标准分数:

用方程式计算标准分数。

其中: μ 为总体的均值σ 为总体的标准差

结论

拥有大量特征会在训练机器学习模型时引入复杂性,例如使算法易于过度拟合并增加训练次数。因此,选择运行良好的特性,忽略不能提供足够好处的特性是非常重要的。这可以通过可视化数据并观察要素如何相互作用来手动完成。此外,当可用的特征太大时,可以使用自动技术来完成。这两种方法都有好处和优点,选择合适的方法取决于手头的问题。

数据科学的特征选择:简单方法

原文:https://towardsdatascience.com/feature-selection-for-data-science-simple-approaches-e1f2527cb363

通过去除与数据集无关的特征,我们可以创建更好的预测模型。

每一个数据科学家都曾经或者将要遇到这个问题;一个庞大的数据集,有如此多的功能,他们甚至不知道从哪里开始。虽然有许多高级方法可用于为数据集选择最佳要素集合,但有时简单的方法可以为您的分析提供很好的基线,甚至是选择数据集最佳要素所需的唯一必要方法。

照片由UXUnsplash 上拍摄

特征选择:为什么重要?

要素选择非常重要,因为包含太多要素的数据集可能会导致高计算成本以及使用冗余或不重要的属性进行模型预测。通过去除与我们的数据集无关的特征,我们可以创建一个建立在强大基础上的更好的预测模型。虽然有使用机器学习算法进行特征选择的高级方法,但今天我想探索两种简单的方法,它们可以帮助引导任何分析的方向。

资料组

我们今天将使用的数据集是来自 Kaggle.com 的学生表现数据集。该数据集中有 33 个要素,它们是:

学校,性别,年龄,地址,家庭大小,p 状态,Medu,Fedu,Mjob,Fjob,原因,监护人,旅行时间,学习时间,失败,schoolsup,famsup,付费,活动,托儿所,高等,互联网,浪漫,famrel,自由时间,goout,Dalc,Walc,健康,缺勤,G1,G2,G3

如果你还没数过,这个数据集有 33 个不同的特征!让我们采取一些简单的方法来挑选出最适合我们的!

预处理

在开始之前,我们需要对数据集做一些预处理。首先,让我们看一下数据集。

import pandas as pd 
df = pd.read_csv('student_data.csv')
df.head()

从视觉上看,似乎有一些列在本质上是分类的。在转换这些列之前,我们还想检查是否有任何丢失的值。

#Checkign for null values -- False means no null values
df.isnull().values.any()

运行此代码返回“False ”,因此不需要填写空值。

df.dtypes

键入上面的代码显示了每一列的所有类型,这表明实际上有分类列需要转换成数字。我创建了一个简单的映射函数,可以很快地帮你做到这一点。

#Function that converts the categorical to numerical through a dictionary. 
def mapper(df_column):
    map_dict = {}

    for i, x in enumerate(df_column.unique()):
        map_dict[x] = i 

    print(map_dict) #Print this out to see 
    df_column.replace(map_dict, inplace = True)

    return df_column

使用这个函数,我们可以将所有的对象列都改为数字。

def categorical_converter(df):
    for i in df.select_dtypes(include=['object']):
        mapper(df[i])

    return dfcategorical_converter(df)

方法 1:评估特性的相关性

如果两个或多个特征高度相关,这可能意味着它们都以相同的方式解释因变量。这引出了从模型中移除这些特征之一的理由。如果您不确定要删除哪个特性,您可以考虑构建两个模型,每个模型包含一个特性。要获得相关矩阵,只需调用。数据框上的 corr

df.corr()

Img:相关矩阵的一部分

显然,有了这么多的特征,相关矩阵将是巨大的。

G1、G2 和 G3 的相关性

要素 G1、G2 和 G3 具有高度相关性,因此我们希望从数据集中移除其中两个要素。我去掉了 G2G3。此外,我将我的 X 数据设置为等于除了 G1 之外的所有列,这些列成为我的 Y 数据。

df.drop(['G2','G3'], axis=1, inplace=True)
X = df.drop(['G1'], axis=1)
Y = df['G1']

方法 2:移除低方差特征

任何具有低方差的要素都应被视为从数据集中移除。为什么?首先,我们来思考一下。如果我试图比较谁是更好的学生,并且两个学生每个月一起上完全相同的课,那么学生之间的“班级”特征几乎没有差异,这将归因于为什么一个学生比另一个学生表现得更好。当一个特征变得接近恒定时,我们可以保持该特征恒定并将其从数据集中移除(一如既往,这取决于!).为此,我们将使用 Scikit 学习特征选择库中的 VarianceThreshold()。

from sklearn.feature_selection import VarianceThreshold

下面的代码将创建一个方差阈值对象,该对象将转换我们的 X 数据并返回给定的最佳特性。

vthresh = VarianceThreshold(threshold=.05)selector = vthresh.fit(X)selected = vthresh.get_support()X = X.loc[:, selected]

运行此代码将返回一个包含 9 个要素的 X 数据框!

具有选定特征的 x 数据

选定的功能包括:

年龄,Medu(母亲教育),Fedu(父亲教育),Mjob(母亲工作),reason,goout,Walc,heath,缺勤。

虽然这些可能不是我们最终得出的结论,但这让我们对影响学生成绩的因素有了初步的了解。我们仅仅通过相关性和方差就能做到这一点!这两个简单的初步方法允许将数据集从 33 个特征减少到 10 个特征(不能忘记 Y!)现在我们可以开始用较小的数据集构建模型了!

如果你喜欢今天的阅读,请关注我,让我知道你是否还有其他话题想让我探讨(这对我的帮助超乎你的想象)!另外,在LinkedIn上加我,或者随时联系!感谢阅读!

引文

学生成绩数据集 - CC0:公共领域,经批准公开使用,作者放弃所有权利,无版权限制。

懒惰的数据科学家的特征选择

原文:https://towardsdatascience.com/feature-selection-for-the-lazy-data-scientist-c31ba9b4ee66

关于基于过滤器的特征选择方法的综合文献综述和代码

内森·杜姆劳在 Unsplash 上的照片

如果你是一名数据科学家,并且维数灾难袭击了你,这篇文章是为你准备的。这是一个关于特征选择算法的综合调查(有例子)。我们通过整合和评估不同特征选择器的集合来结束讨论,以得到一个全面的结论。

首先,让我们从定义什么是特征选择开始。如果你面临高维数的问题,你可能听说过“降维(或 PCA/自动编码器)”和“特征选择”在我们深入研究特性选择之前,这里有一个降维的简短描述,它将帮助您决定是否应该采用这种方法。

降维

降维通过将数据从特征空间转换到潜在空间来帮助我们减少特征的数量。这个更小的空间应该以更压缩的方式来表示学习到的特征。如果我们正确地选择了潜在空间的维数,那么我们甚至可以降低噪声,去除不相关的信息。这种方法的最大缺点是它的可解释性。从特征空间转移到潜在空间,我们不再直接看特征,只看它们的表示,它们通常不像特征那样有直观的解释或逻辑。在处理图像或信号等非结构化数据时,这种方法变得非常方便。关于潜在空间含义的进一步讨论,见此处此处

一个自动编码器架构中潜在空间的例子,作者图片

总之,如果可解释性对你的项目是必不可少的,或者出于某种原因,你可能想保持原来的表示,降维不适合你,你在正确的地方。

特征选择

要素选择方法允许您根据某些标准选择数据集中的最佳要素。听起来很明显,对吧?尽管如此,还是有很多不同的方法,每种方法都以稍微不同的方式定义了一个特性的优点,为了正确地选择最佳特性,您可能需要不止一种方法。

首先,一些术语:特征选择方法可以分为三类:

(1) 过滤方法:特征选择是预处理的一部分,即我们训练一个模型之前的。我们根据一些标准过滤掉表现不佳的特性。简单的标准是简单的相关性。这种方法在我们拥有大量数据集时大放异彩,尤其是当我们拥有大量要素时。 Hoph 和 Reifenrath (2021) 在他们的工作中发现(这将在下一节深入讨论)

..三个属性使得[filter]方法看起来特别适合某些数据集场景。这些是对噪声的鲁棒性、抵消类别不平衡的成本敏感性以及考虑用于检测冗余特征的特征组合(多变量方法)。

(2) 包装器方法:迭代选择一个特征子集,训练你的模型,选择最佳组合。正如您已经想到的,这种方法非常昂贵,而且几乎不切实际。

(3) 嵌入方法:不要与嵌入相混淆,矢量表示单词。嵌入式方法利用了算法中嵌入的特征重要性估计。例如,随机森林选择不同的特征子集,以避免过度拟合。模型定型后,我们可以查看有多少特征使预测性能受益。然而,就像在分类任务中一样,仅依赖于嵌入式方法,我们可能会使特征选择过度适应给定的算法,限制我们使用不同的算法和不同的数据集,特别是在使用像决策树这样的高方差方法时。

方法(2)和(3)成本更高。他们需要一个训练有素的模型,并隐含地假设我们可以使用全部数据来训练一个模型,但情况并非总是如此。下图显示了不同特征选择方法之间的区别。

图 4:监督特征选择方法和技术的扩展分类法, Danny Butvinik ,此处

我们的介绍到此结束,可以开始处理今天让我们来到这里的紧迫问题了。

过滤方法

过滤方法基本上是根据特定标准来衡量功能性能。有些功能在某些设置下会很出色,而在其他设置下则表现不佳。因此,使用多种标准并整合特征分数对于全面掌握我们的数据至关重要。我尽量做到兼容并蓄,从文献中收集了不同的过滤方法([ 1 ,[ 2 ,[ 3 ,[ 4 )。最终,我以这篇长文章结束,由于我想添加一些代码和示例,所以我必须过滤掉一些过滤方法(见我在那里做了什么?).换句话说,如果您想对不同的技术有更深刻的理解,我建议您浏览一下本文中的适度的文献综述。

过滤方法—方法:)

Bommert 等人[ 2 ]将基于滤波器的特征选择器分为单变量、多变量、基于 MI 的方法和基于 Relief 的方法。我在这里也会这样做。

所涉及的大多数方法都可以通过 FSM 来使用,这可以在我的 Github 这里找到。

单变量方法

根据特征与结果变量的关系对特征进行单独排序,不考虑其他变量。单变量方法可以使用统计检验,如 ANOVA,或使用预测性能,如 AUC,通过一次仅使用一个特征来预测结果。

方差分析【ANOVA】:ANOVA 特征选择器使用 F 统计量作为每个特征的得分。一般来说,F 统计量询问给定特征的均值在不同类别的结果变量之间有多远。更详细的解释可以在 Kasra Manshaei 的回答这里,或者在这篇专门的博文中找到。简而言之,在区分不同类别时,一个特性越好,这个特性的 F 值也就越大。

每个特征的类之间的间隔,X 轴上的 X 和 Y 轴上的 Y,

在这种情况下,使用 sklearn 实现非常简单。

**from** **sklearn.feature_selection** **import** [SelectKBest](https://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.SelectKBest.html#sklearn.feature_selection.SelectKBest), [f_classif](https://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.f_classif.html#sklearn.feature_selection.f_classif)
anova_filter = [SelectKBest](https://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.SelectKBest.html#sklearn.feature_selection.SelectKBest)([f_classif](https://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.f_classif.html#sklearn.feature_selection.f_classif), k=3)

以及一个使用有限状态机的示例:

selectors = FSM.FSM(k=20, filler = -1)
selectors.anova_inference(X_,y_)# Results# array(['member_id', 'loan_amnt', 'funded_amnt', 'funded_amnt_inv',
#        'int_rate', 'annual_inc', 'dti', 'inq_last_6mths',
#        'mths_since_last_record', 'pub_rec', 'revol_util', 'out_prncp',
#        'out_prncp_inv', 'total_pymnt', 'total_pymnt_inv',
#        'total_rec_prncp', 'total_rec_late_fee', 'recoveries',
#        'collection_recovery_fee', 'last_pymnt_amnt'], dtype=object)

Kruskal:对每个特征应用 Kruskal-Wallis 秩和检验[ 5 ],这是方差分析的非参数等价(即,它不假设我们的特征是正态分布的)。在我们计算 Kruskal 统计量之前,我们首先必须从最小到最大排列我们的观察值(不考虑它们相应的结果)。然后,我们对每个 I 类中的等级求和。然后,克鲁斯卡尔统计量由下式给出

克鲁斯卡尔试验

其中 T 是类(I)内秩的总和,n_i 是属于类(I)的观测值的数目,n 是观测值的总数。

同样,该统计值越高,意味着不同类别的对应特征值越不同。我们可以使用 scipy 实现 Kruskal Wallis 测试。

**from** scipy **import** stats
stats**.**kruskal**(**x_j**,** y**)**

在有限状态机中:

selectors = FSM.FSM(k=20, filler = -1)
selectors.kruskal_inference(X_,y_)# Results:# Index(['recoveries', 'collection_recovery_fee', 'out_prncp_inv', 'out_prncp',
#        'delinq_2yrs', 'pub_rec', 'total_rec_late_fee', 'acc_now_delinq',
#        'collections_12_mths_ex_med', 'inq_last_6mths', 'policy_code',
#        'revol_bal', 'dti', 'last_pymnt_amnt', 'total_rec_int',
#        'total_rec_prncp', 'total_pymnt', 'total_pymnt_inv', 'member_id',
#        'installment'],
#       dtype='object')

卡方 :以χ2 统计值作为得分。

**from** **sklearn.feature_selection** **import** [SelectKBest](https://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.SelectKBest.html#sklearn.feature_selection.SelectKBest), chi2
chi2_filter = SelectKBest(chi2, k=2)

在有限状态机中:

selectors = FSM.FSM(k=20, filler = -1)
selectors.chi2(X_,y_)# Results:# array(['member_id', 'loan_amnt', 'funded_amnt', 'funded_amnt_inv',
#        'int_rate', 'installment', 'annual_inc', 'mths_since_last_record',
#        'revol_bal', 'revol_util', 'out_prncp', 'out_prncp_inv',
#        'total_pymnt', 'total_pymnt_inv', 'total_rec_prncp',
#        'total_rec_int', 'total_rec_late_fee', 'recoveries',
#        'collection_recovery_fee', 'last_pymnt_amnt'], dtype=object)

多元方法

最大关联最小冗余(MRMR):2005 年推出,最近重新流行起来[ 6 ]。MRMR 算法是一种贪婪的迭代算法。根据下面的规则,每次迭代选择最佳的特性,并将其添加到先前选择的特性中。它被称为最大相关性-最小冗余,因为在每次迭代中,我们都希望选择与目标变量最大相关的特征,以及与先前迭代中所选特征最小冗余的特征。

由 MRMR vs 博鲁塔选择的特写,由塞缪尔·马赞蒂制作的人物,取自此处。在这个例子中,年龄(整数)机械地依赖于年龄;智商和父母的智商有很大的相关性,还有伴侣的身高和自己的身高。考虑到特征之间的高度相关性,通过分母归一化,MRMR 将导致上述三个特征,这三个特征用红线圈出。

虽然有许多方法来计算 MRMR,我只介绍 FCQ 方法。访问[ 7 ]了解更多策略。

图由塞缪尔·马赞蒂所作,取自此处

在第 i 次迭代中特征 f 的相关性(分子)被计算为特征和目标变量之间的 F 统计量。冗余(分母)计算为该特征和在先前迭代中选择的所有特征之间的皮尔逊相关的绝对值的平均值。

from mrmr import mrmr_classif
data = pd.read_csv('/Users/davidharar/Downloads/data_loan.csv')
X = data._get_numeric_data().drop(['default_ind'], axis = 1)
y = data['default_ind']selected_features = mrmr_classif(X, y, K = 14)
# K is the size of the desired subset.selected_features

预测性能

这是一种介于过滤方法和嵌入方法之间的中间地带。在这种方法下,我们迭代地运行一个模型,比方说一个随机森林,一次只有一个特征。然后,我们根据熟悉的 KPI(如 AUC 和准确性)对我们的功能进行排名。AUC 通常是首选的,因为它对不平衡的数据集更有弹性,并且通过多种阈值选择进行评估。AUC 的缺点是它仅适用于二元预测。

相互信息

互信息是两个特征之间相互依赖的度量。与皮尔逊相关不同,它不限于单调关系。互信息决定了联合分布与两个边际分布的乘积有多大的不同。回想一下,如果两个变量是独立的,它们的联合分布等于它们的边际分布的乘积。

熵是另一个重要的结构,它来源于互信息。熵测量变量的不确定性。当所有可能的值以大约相同的概率出现时,熵是高的,如果出现的概率非常不同,熵是低的。它与互信息相关—高互信息值表明不确定性大大降低,因为当我们认识到一个变量的值时,我们对另一个变量的期望值有相对较高的确定性。如果互信息为零,那么两个随机变量是独立的,我们无法推断出一个给定另一个的值的合理性。

在我们能够计算互信息或熵之前,连续特征必须被离散化。

设 X 和 Y 是两个离散变量,具有(经验的)概率质量函数s。Y 的(无条件的)熵由下式给出

给定 X,Y 的条件熵由下式给出

交互信息可以由下面的等式表示:

上述等式的证明可以在这里找到,这在上述等式的上下文中给出了交互信息的极好直觉:

..如果熵 H(Y)被视为关于随机变量的不确定性的度量,那么 H(Y|X)是 X 没有说关于 Y 的的度量。这是“在 X 已知之后关于 Y 剩余的不确定性的量”,因此这些等式中的第二个等式的右侧可以被解读为“Y 中的不确定性的量减去 X 已知之后 Y 中剩余的不确定性的量”。

几种方法使用上述理论结构并探索信息的概念,以及不同特征之间的冗余。在这一部分,我们将讨论其中的一些。

维恩图显示与相关变量 X 和 Y 相关的各种信息测量的加法和减法关系,来源:维基百科

基于互信息得分的贪婪方法

在我们开始之前,请注意以下大多数算法的计算复杂度取决于(有时是二次)所需的特征数量。大多数实现包括用于期望数量的特征的指定参数。探索它,为自己节省大量时间。

联合互信息:尽管它不是一种贪婪的或迭代的方法,我还是把它加在这里,因为你会不时地看到一些文章使用 JMI 作为特征选择的方法。JMI 有些天真,他提醒人们使用简单的相关性进行过滤。我们只计算目标和我们的每个特征之间的联合互信息,然后我们保留 k 个最高的。在 JMIM 下实施

JMI 功能排名,来源

联合互信息最大化(JMIM)和归一化联合互信息最大化(NJ mim)[8:作为 MRMR 和 CMIM,这两种算法对与目标互信息最大化的特征做贪婪的搜索。JMIM 和 CMIM 的主要区别在于,后者最大化候选特征对预选特征的信息量,而 JMIM 选择最大化新特征+预选特征与目标特征的联合互信息的特征。这里的主要观点是 JMIM 也考虑了特征的冗余,而 CMIM 只是试图最大化加入的互信息。

关于实现的注意事项 : 找到一个详细的实现并不容易,但我很幸运地在这里找到了这个伟大的。mifs包允许JMI, JMIMMRMR。在我的实验中,相应子部分的MRMR实现更快,总体来说JMIJMIM更快。最后,当你设置软件包时,记得把from sklearn.feature_selection.base import SelectorMixin改成from sklearn.feature_selection._base import SelectorMixin。除此之外,mifs灵活清晰。

import mifs# define MI_FS feature selection method
feat_selector = mifs.MutualInformationFeatureSelector(method = "JMIM", n_jobs=8)# Few important params for MutualInformationFeatureSelector:
# 1\. method, self explenatory, could be "JMI", "JMIM" and "MRMR"
# 2\. n_features: desired number of features after filtering.
# 3\. n_jobs: How many CPUs should run parallelly.
# 
# Important attributs:
# 1\. feat_selector.get_support(): Boolean vector of length p that
#    indicates whether a feature has been selected.
# 2\. feat_selector.ranking_: Vector of length p that is ordered by
#    importance, for example [52,1,53,...] indicates that feature 52 
#    was the most important one.# Both JMI and JMIM arn't compatible with NaNs
X_filled = X.fillna(-1)
feat_selector.fit(X_filled, y)# call transform() on X to filter it down to selected features
X_filtered = feat_selector.transform(X_filled)
X_filtered = pd.DataFrame(X_filtered, columns = X_filled.columns[feat_selector.ranking_])

基于快速相关性的过滤(【FCBF】):一种基于相关性的过滤方法,考虑了特征之间的冗余。如果某个特征和目标之间的相关性足够高,使其与预测相关,则该特征适合于分类任务。它和任何其他相关特征之间的相关性没有达到任何其他相关特征可以预测它的水平。由于线性相关性有一些主要的局限性,FCBF 的相关性是基于熵,特别是对称不确定性,苏。

该算法的工作原理如下:

  1. 相关特征:首先,我们为我们的每个 p 特征计算 SU。我们选择安苏门槛。让我们假设安苏分数高于阈值的特征集合。让我们按降序排列这些功能。
  2. 冗余特征:从第一个排序后的特征开始,我们为 s 中的 l 计算 SU(j,l),如果 SU(j,l) ≥SU(target,j),我们从 s 中移除 l,被移除的特征称为“特征 j 的冗余对等体”
selectors = FSM.FSM(k=20, filler = -1)
selectors.fcbf(X_,y_)# Results: (fcbf has a lower bound on SU rather than k features. The default is 0).# selectors = FSM.FSM(k=20, filler = -1)
# selectors.fcbf(X_,y_)

条件互信息最大化【CMIM】:基于特征与目标变量的联合互信息选择特征的贪婪算法。给定预先选择的特征,每次迭代选择与目标共享最大互信息的特征。也就是说,我们选择与目标变量尚未描述的部分互信息最大化的特征,而不考虑冗余(即忽略当前特征与预选特征之间的高相关性)。

CMIM 功能排名,来源

关于实现的说明 : scikit-feature 是用 Python 2 编写的。在这里的作者将大部分的 utils 函数转换成 Python 3,所以我最终使用了它的 utils 以及稍微修改过的 scikit-feature 原始函数。代码和工作示例在附带的笔记本中。

用有限状态机实现:

selectors = FSM.FSM(k=20, filler = -1)
selectors.cmim(X_,y_)# Results:# Index(['member_id', 'funded_amnt_inv', 'installment', 'open_acc', 'revol_util',
#        'total_pymnt', 'delinq_2yrs', 'annual_inc', 'dti', 'revol_bal',
#        'total_acc', 'total_pymnt_inv', 'total_rec_prncp', 'total_rec_int',
#        'total_rec_late_fee', 'recoveries', 'inq_last_6mths',
#        'mths_since_last_record', 'collections_12_mths_ex_med',
#        'mths_since_last_major_derog'],
#       dtype='object')

双输入对称相关(DISR)[9]:DISR 依赖于这样的性质,即变量的组合可以返回比每个单独变量产生的信息总和更多的输出类信息。在 DISR 下,每个要素的 JMI 根据给定要素与其他要素的互补程度进行归一化。

DISR 专题排名,来源

用有限状态机实现:

selectors = FSM.FSM(k=20, filler = -1)
selectors.disr(X_,y_)# Results:# Index(['member_id', 'dti', 'recoveries', 'collection_recovery_fee',
#        'collections_12_mths_ex_med', 'mths_since_last_major_derog',
#        'policy_code', 'annual_inc_joint', 'total_rec_late_fee',
#        'total_rec_prncp', 'dti_joint', 'acc_now_delinq', 'tot_coll_amt',
#        'tot_cur_bal', 'total_pymnt', 'total_pymnt_inv', 'revol_bal',
#        'open_acc_6m', 'open_il_6m', 'open_il_12m'],
#       dtype='object')

基于互信息的特征选择()10:使用最佳特征 w.r.t. I(i,target)的贪婪选择和对预选特征冗余的惩罚。

MIFS 功能排名,来源

这一系列基于信息的特征选择方法的其他发展包括自适应 MIFS (AMIFS) [ 11 ],条件 MIFS (CMIFS) [ 12 ],以及更多方法,由于篇幅限制,这些方法留给读者作为练习。

用有限状态机实现 MIFS:

*selectors = FSM.FSM(k=20, filler = -1)
selectors.mifs(X_,y_)# Results:# Index(['member_id', 'collections_12_mths_ex_med',
#        'mths_since_last_major_derog', 'policy_code', 'annual_inc_joint',
#        'dti_joint', 'acc_now_delinq', 'tot_coll_amt', 'tot_cur_bal',
#        'open_acc_6m', 'open_il_6m', 'open_il_12m', 'open_il_24m',
#        'mths_since_rcnt_il', 'total_bal_il', 'il_util', 'open_rv_12m',
#        'open_rv_24m', 'max_bal_bc', 'all_util'],
#       dtype='object')*

基于救济的方法

Relief [ 13 于 1992 年引入,用于二进制目标的特征选择,自从 ReliefF 将其推广到多类目标后,它开始流行。RReliefF 是一种基于 Relief 的方法,用于回归[ 14 ]、I-RELIEF、Tuned ReliefF、VLSReliefF、SURF 和 ReliefSeq。这里有一个很好的关于 RBMs 的调查。原始算法如下。假设我们有 p 个不同的特征和一个二元目标。然后,我们开始初始化一个权重向量 w,长度为 p,全为 0。然后,对于 B 次,我们

  • 从我们的数据中随机抽取一个例子,比如从 0 班。
  • 找出欧氏距离最接近的例子,属于同一类。我们称这个例子为“近击”类似地,我们取最接近的点,它属于对立的类,称之为“接近失误”
  • 更新 w:对于 m 次迭代和 p 个特征,我们按下式更新 w_j。

注意,我们通过每个示例与同类的最近示例的(平方)距离来惩罚特征 j(由 w_j 表示)的重要性。也就是说,Relief 更喜欢稀疏度较低的要素,并且同一类的示例之间距离较近的要素受到的惩罚会更少。相反,Relief 赋予来自一个类的示例离属于另一个类的示例更远的特征更高的重要性。

与通常的 KNN 估计器一样,只考虑几个邻居可能会导致有噪声的预测和过度拟合。ReliefF 算法除了将 ReliefF 推广到多类目标之外,还在估计重要性时纳入了来自 k 个邻居的信息。一般来说(对其他 RBA 也是如此),在某种程度上,更多的邻居导致更准确的分数,但是需要更长的时间来收敛。

与以前的方法相比,这种方法完全是非参数化的,并且与以前依赖于信息论的方法相比,Relief 的重要性来自于距离的概念。

I-RELIEF 建议对整个命中和未命中实例集使用实例加权函数,而不是只对每个类的关闭实例使用加权函数。SURF 采用距离阈值 T 来将实例定义为邻居(其中 T 等于数据中所有实例对之间的平均距离)。然而,与迭代救济相反,SURF 对定义为邻居的所有实例使用相同的实例权重【15】。还有其他变体,如 VLSReliefF 和 ReliefSeq,这里不做介绍。这篇中篇文章对基于救济的方法做了更深入的介绍。

虽然它们不相同,但是基于起伏的方法与用于特征选择的拉普拉斯方法有相似之处。拉普拉斯方法也假设相同类别的观测值倾向于彼此更接近。在拉普拉斯特征选择中,我们通过测量任意距离和计算权重矩阵来将数据嵌入到最近邻居的图中。然后,我们计算每个特征的拉普拉斯准则,并获得这样一个性质,即最小值对应于最重要的维度。然而,在实践中,当选择特征子集时,通常使用不同的聚类算法(k-means 方法),在该算法的帮助下,选择最有效的组[ ]。

三个版本的浮雕,由作者绘制。上图展示了在不同的地貌算法下,哪些邻域被考虑在内。左上面板显示了我们在上面介绍过的基本版本。在这个版本中,当更新权重时,我们仅采用最接近的接近命中和接近未命中情况。右上面板显示了 ReliefF,它考虑了 k 个不同的邻居,在本例中为 4 个。底部面板显示了在 SURF/SURF算法下更新权重时考虑的邻居。在这些算法中,我们不是考虑特定数量的邻居,而是定义一个边界,通过该边界将比它更近的邻居考虑在内。*

关于起伏算法的两点注意事项:

python 中有几个 Relief(及其变体)的实现(例如, sklearn-relief16 ),但这个似乎是最详细的 scikit-rebate 。或许 RBA 如此受欢迎的原因之一是其灵活性。RBA 兼容分类和连续特征的混合,以及多类分类和回归。然而,由于他们依赖于距离(和 KNN),他们深受维数灾难之苦。用户指南说:

在非常大的特征空间中,用户可以预期基于核心起伏的算法分数在自己运行时变得不太可靠。这是因为随着特征空间变得非常大,最近邻居的确定变得更加随机。因此,在非常大的特征空间(例如> 10,000 个特征)中,用户应考虑将基于核心起伏的算法与迭代方法(如 TuRF(此处实现)或 VLSRelieF 或迭代起伏)相结合。

当扩展到大数据问题时,请记住,使折扣方法速度最慢的数据方面是训练实例的数量,因为救济算法与功能的数量成线性比例,但与训练实例的数量成二次比例。这是基于起伏的方法需要计算距离数组(即训练数据集中实例之间的所有成对距离)的结果。如果您有大量可用的训练实例,那么在运行任何折扣方法时,可以考虑利用该数据集的类平衡随机采样来节省内存和计算时间。

而对于基于 Relief 的算法的具体时间复杂度,参见[ 15 中的表 5。

用有限状态机实现:

*selectors = FSM.FSM(k=20, filler = -1)
selectors.ReliefF(X_,y_)
selectors.SURF(X_,y_)
selectors.SURFstar(X_,y_)
selectors.MultiSURF(X_,y_)# Note: X_ and y_ have N=10,000, which may lead to a long computation time.* 

其他方法

虽然我们已经讨论了大量的算法,但我们只能触及皮毛。我们还没有介绍用于特征选择的无监督算法[ 17 和[ 18 ],用于特征选择的谱方法[ 19 ],以及基于图的方法[ 2021 和[ 22 ]。其他过滤方法包括 Burrata、信息片段(IF)、SOA 等。正如标题所说,这篇文章是为懒惰的数据科学家写的。如果你不懒,我希望你会对这篇文章的参考书目感兴趣。

综合

好的,如果你已经到这里了,你可能有一个问题一直困扰着你——你尝试了不同的方法,得到了不同的分数,这些分数不一定彼此一致。你该怎么办?

根据[ 23 ],当集合不同的选择方法时,我们必须考虑以下几点:

  • 使用哪种方法和多少种方法?他们发现越多越好。
  • 要使用的训练集的数量和大小—我们应该对数据进行子集划分吗?自举?正如我们在上面看到的,我们的一些算法在观察次数上是二次的。总体来说,答案是是的;我们应该重新采样并选择特征。最终,我们可以将这些信息与下面的评分方法结合起来。**
  • 我们最终想要多少功能?这个数字可以定义为我们拥有的或之前被决定的所有特征的百分比。
  • 如何评估聚合方法?我将用这一部分来回答这个问题。

假设您有不同的选定功能列表,您可以执行以下一项或多项操作。

  1. 根据选择规则将你的电子邮件列表合并成一个列表(如下例)。然后,使用组合列表训练一个模型。
  2. 使用特征选择器集成—在不同的“瘦”模型中训练 E,稍后,当新的数据集到达时,将通过使用 E 个不同的模型预测结果来进行预测。
  3. 介于 1 和 2 之间的中间点——根据 E '不同的规则,将 E 个特征列表转换为 E '组合特征列表,然后训练 E' ( <

对不同列表中的特征进行排序)可通过以下方式完成

  • Min:给每个元素分配它所达到的最小(最好)等级。
  • 中位数:为每个元素分配它所达到的中位数等级。
  • 算术平均数:给每个元素分配它所达到的等级的平均数。
  • 几何平均值:给每个元素分配它所达到的等级的几何平均值。

我们可以使用投票[24]:

*counter = Counter(features_selected_lists) # list of lists
features_voted = [k for k, v in counter.items() if v >= min_votes]*

虽然 FSM 没有告诉您如何对您的特征进行排序,但它附带了一个方便的推理函数,该函数使用 bootstrap 并返回一个特征列表,该列表根据每个分类器和每个采样的重要性进行排序。所有的预处理(离散化、规范化(例如,回想一下 chi2 不能处理负值),以及编码)都在内部完成。在下面的例子中,我只使用了 too 抽样,每个样本有 100 个观察值。

*selectors = FSM.FSM(k=20, filler = -1)
results = selectors.Bootstrapper(X_, y_, B=2,Sample_size=100)# Results:# {'ANOVA': [array(['loan_amnt', 'int_rate', 'annual_inc', 'delinq_2yrs',
#          'inq_last_6mths', 'mths_since_last_delinq',
#          'mths_since_last_record', 'open_acc', 'pub_rec', 'revol_bal',
#          'total_acc', 'out_prncp', 'out_prncp_inv', 'total_pymnt',
#          'total_pymnt_inv', 'total_rec_prncp', 'total_rec_late_fee',
#          'recoveries', 'collection_recovery_fee', 'last_pymnt_amnt'],
#         dtype=object),
#   array(['member_id', 'loan_amnt', 'funded_amnt', 'funded_amnt_inv',
#          'int_rate', 'annual_inc', 'inq_last_6mths',
#          'mths_since_last_record', 'open_acc', 'pub_rec', 'revol_bal',
#          'revol_util', 'out_prncp', 'out_prncp_inv', 'total_pymnt',
#          'total_pymnt_inv', 'total_rec_prncp', 'recoveries',
#          'collection_recovery_fee', 'last_pymnt_amnt'], dtype=object)],
#  'chi2': [array(['member_id', 'loan_amnt', 'funded_amnt', 'funded_amnt_inv',
#          'annual_inc', 'mths_since_last_delinq', 'mths_since_last_record',
#          'open_acc', 'revol_bal', 'total_acc', 'out_prncp', 'out_prncp_inv',
#          'total_pymnt', 'total_pymnt_inv', 'total_rec_prncp',
#           ...*

如何评估一组特征选择器

通常,我们会查看三个 KPI:多样性* —例如在集成决策树中,我们不需要 K 个不同的树来给出总是相同的结果,我们不需要 K 个不同的选择器来选择相同的特征,而不管数据如何。另一个 KPI 是稳定性——我们必须确保集成将为相似的数据集返回相似的排名。最后是您的 KPI(可能是准确性、AUC 或其他)。使用冗余特征可能会导致更差的性能,我们应该期待使用所选子集和更快的训练会有更好的结果。*

多样性 Kuncheva 和 Whitaker [ 25 ]提出了测量特征选择器集合多样性的附加测量的综合调查。设置是我们有两个或更多的训练模型,其中每一个都是在另一个特征子集上训练的。我们也有他们的预测,有些是正确的,有些是不正确的,有些是相同的,有些是不同的。他们提出并比较了 10 种多样性度量:Q 统计量、相关系数、不一致度量、双故障度量、Kohavi-Wolpart 方差、Interrator 一致性、熵度量、难度度量、广义多样性和重合故障多样性。然而,由于这篇文章变得太长了,我将检查一下 Q 统计,并将其余的留给好奇的读者。

Q 统计是成对检验。给定两个分类器,我们有两个 Di 预测,长度为 N(等于观察的数量)。我们交叉标记了他们的预测,并使用了以下符号:

两个不同分类器预测的交叉表。表作者。

那么一对分类器的 Q 统计量将是

一对分类器的 q 统计量,由作者提供。

如果我们有 L 个不同的分类器,那么我们将返回平均 Q 统计量:

L 个不同分类器的平均 Q 统计量,由作者提供。

对于统计上独立的分类器,Q(i,j)的期望值是 0。q 在 1 和 1 之间变化。倾向于正确识别相同对象的分类器将具有正的 Q 值,而那些在不同对象上出错的分类器将使 Q 为负。

稳定性确保集成将为相似的数据集返回相似的排名。

计算稳定性有几种方法(例如[ 26 ],和[ 27 ])。我将从[ 28 开始呈现一个更新的。使用[ 29 ]演示:假设我们有 p 个原始特征,我们想从中选择总共 k 个特征。我们将数据分成 m 个不同的子集(或从中重新取样)。将 h_j 定义为特征 j 被选为整个 m 个子集中最重要的 k 个特征之一的次数。将 q 定义为 p 个特征的总和(即,它计算选择特征 1+选择特征 2+…+选择特征 p 的次数),然后如下

Nogueira 等人(2018 年),来自 Hopf 和 Reifenrath 2021 年的公式

是完全定义的、严格单调的、有上下限的特征选择集合的稳定性度量,以及当所有特征集相等时它的最大值。

性能是我们这里的主要目标,使用冗余功能或不重要的功能会降低我们模型的性能。我们可以通过查看选择下的 KPI,并与输入所有变量的基本场景进行比较,来衡量选择方法的成功。[ 24 ]进行 t 检验,比较选择后模型和没有选择后模型的 KPI。

文献学

  1. 霍普夫,康斯坦丁和萨沙·莱芬拉斯。"监督机器学习应用中特征选择的过滤方法——综述和基准测试."arXiv 预印本 arXiv:2111.12140 (2021)。
  2. 《高维分类数据中特征选择的过滤方法的基准》计算统计&数据分析* 143 (2020): 106839。*
  3. 余、雷、。“高维数据的特征选择:一种快速的基于相关性的过滤器解决方案。”第 20 届机器学习国际会议论文集(ICML-03)* 。2003.*
  4. 皮尔宁斯基尼基塔和伊万·斯梅坦尼科夫。"作为 python 数据分析工具之一的特征选择算法."未来互联网* 12.3 (2020): 54。*
  5. 谢尔登·m·罗斯统计学导论。学术出版社,2017。
  6. “MRMR”准确地解释了你希望别人如何向你解释。
  7. 赵,陈振宇,拉迪卡·阿南德和马洛里·王。"营销机器学习平台的最大相关性和最小冗余特征选择方法." 2019 IEEE 数据科学与高级分析国际会议(DSAA) 。IEEE,2019。
  8. Bennasar,Mohamed,Yulia Hicks 和 Rossitza Setchi。"使用联合互信息最大化的特征选择."专家系统与应用42.22(2015):8520–8532。
  9. 迈耶、帕特里克·e 和吉安卢卡·邦坦皮。"在癌症分类中使用可变互补性进行特征选择."进化计算应用研讨会。施普林格,柏林,海德堡,2006。
  10. 罗伯托·巴蒂蒂。"使用互信息在监督神经网络学习中选择特征."IEEE 神经网络汇刊 5.4(1994):537–550。
  11. 特斯默、米歇尔和巴勃罗·埃斯特韦斯。" AMIFS:利用互信息的自适应特征选择."2004 年 IEEE 国际神经网络联合会议。№04CH37541) 。第一卷。IEEE,2004 年。
  12. 基于条件互信息的协同和冗余特征选择分析。Etri 期刊 33.2(2011):210–218。
  13. 基拉,肯吉和拉里·a·伦德尔。"一种实用的特征选择方法."《机器学习学报》1992 年。摩根·考夫曼,1992 年。249–256.
  14. rob Nik-iko nja、Marko 和 Igor Kononenko。"减免的理论和实证分析."机器学习 53.1(2003):23–69。
  15. 基于地形的特征选择:介绍和评论。生物医学信息学杂志85(2018):189–203。
  16. Yash Dagli,使用起伏算法的要素选择与 python 示例。,中等。
  17. 陈,,等,〈基于分层特征加权的监督特征选择方法〉。 IEEE 访问6(2018):15087–15098。
  18. 王、石平、朱威廉。"稀疏图嵌入无监督特征选择." IEEE 系统、人和控制论汇刊:系统48.3(2016):329–341。
  19. 赵,郑阿兰,。用于数据挖掘的光谱特征选择。泰勒弗朗西斯,2012 年。
  20. 一种新的图形特征选择方法。 2020 年第六届 IEEE 信息科学与技术大会(CiSt) 。IEEE,2021。
  21. 张志宏和埃德温·r·汉考克。“基于图形的特征选择方法。”模式识别中基于图形表示的国际研讨会。施普林格,柏林,海德堡,2011。
  22. 胡,荣耀,等。“无监督特征选择的图自表示方法”神经计算220(2017):130–137。
  23. 博隆-卡内多、韦尔尼卡和安帕罗·阿朗索-贝当佐斯。"特征选择的集成:回顾和未来趋势."信息融合52(2019):1–12。
  24. Cohen,Cohen 和 Atlas,结合特征选择方法, vatvengers ,Medium。
  25. 昆切娃,柳德米拉和克里斯托弗·惠特克。"分类器集成中多样性的测量及其与集成精度的关系."机器学习51.2(2003):181–207。
  26. 《特征选择的稳定性指数》人工智能及应用。2007.
  27. 排名列表中的堪培拉距离。NIPS 09 研讨会进展会议录。Citeseer,2009 年。
  28. 诺盖拉、萨拉、康斯坦丁诺斯·塞希迪斯和加文·布朗。"特征选择算法的稳定性."j .马赫。学习。第 18.1 号决议(2017 年):6345 至 6398。
  29. 霍普夫,康斯坦丁和萨沙·莱芬拉斯。"监督机器学习应用中特征选择的过滤方法——综述和基准测试." arXiv 预印本 arXiv:2111.12140 (2021)。

特征选择方法以及如何选择它们

原文:https://towardsdatascience.com/feature-selection-methods-and-how-to-choose-them-1e7469100e7e

特性选择的原因、方式和时机,以及一些方便的技巧和提示

本文首发于 海王艾的博客

你有没有发现自己坐在屏幕前想知道什么样的功能将帮助你的机器学习模型最好地学习它的任务?我打赌你有。数据准备往往会消耗大量数据科学家和机器学习工程师的时间和精力,准备好数据以供学习算法使用是一项不小的壮举。

数据准备流程中的一个关键步骤是特征选择。你可能知道一句流行的谚语:垃圾进,垃圾出。你用什么来喂养你的模型至少和模型本身一样重要,如果不是更重要的话。

在本文中,我们将探讨特征选择在数据准备管道中其他与特征相关的任务中的位置,并讨论它对于任何机器学习项目的成功如此关键的多种原因。接下来,我们将回顾不同的特性选择方法,并讨论一些技巧和提示来改善它们的结果。然后,我们将一瞥 Boruta(最先进的特征选择算法)的幕后,最后看看一种结合不同特征选择方法的聪明方法。让我们开始吧!

什么是特征选择,什么不是?

让我们从定义感兴趣的对象开始。

什么是特征选择?简而言之,它是选择用于训练机器学习模型的特征子集的过程。

这就是特征选择是什么,但理解特征选择不是什么同样重要:它既不是特征提取,也不是特征工程,更不是降维。

特征提取和特征工程是描述基于领域知识从现有特征创建新特征的相同过程的两个术语。这会产生比原来更多的特性,应该在特性选择之前执行。首先,我们可以进行特征提取,以获得许多潜在有用的特征,然后我们执行特征选择,以挑选出确实会提高模型性能的最佳子集。

降维是另一个概念。它有点类似于特征选择,因为两者都旨在减少特征的数量。然而,它们在实现这一目标的方式上有很大的不同。虽然特征选择选择原始特征的子集来保留并丢弃其他特征,但是维度减少技术将原始特征投影到更少维度的空间上,从而创建全新的特征集。如果需要的话,降维应该在特征选择之后运行,但是在实践中,它不是这个就是那个。

现在我们知道了什么是特征选择,以及它如何对应于其他与特征相关的数据准备任务。但是我们为什么需要它呢?

我们需要特性选择的 7 个原因

一个流行的说法是,现代机器学习技术在没有特征选择的情况下做得很好。毕竟,一个模型应该能够知道特定的特性是无用的,它应该关注其他的特性,对吗?

嗯,这个推理在某种程度上是有道理的。理论上,线性模型可以给无用的特征分配零权重,而基于树的模型应该很快学会不对它们进行分割。然而,在实践中,当输入不相关或多余时,训练中会出现许多问题——这两个术语将在后面详述。除此之外,还有许多其他原因可以解释为什么简单地将所有可用的特性都转储到模型中可能不是一个好主意。我们来看看最突出的七个。

1:不相关和多余的功能

有些功能可能与手头的问题无关。这意味着它们与目标变量没有关系,与模型设计要解决的任务完全无关。丢弃不相关的特征将防止模型拾取它可能携带的虚假相关性,从而避免过度拟合。

冗余特征是另一种动物。冗余意味着两个或更多特征共享相同的信息,并且除了一个之外,所有特征都可以被安全地丢弃而不会丢失信息。注意,在存在另一个相关特征的情况下,一个相关特征也可以是冗余的。应丢弃冗余要素,因为它们可能会在训练过程中造成许多问题,例如线性模型中的多重共线性。

2:维度的诅咒

特征选择技术在特征很多但训练样本很少的场景中尤其不可或缺。这种情况存在所谓的维数灾难:在一个非常高维的空间中,每个训练样本与所有其他样本相距如此之远,以至于模型无法学习任何有用的模式。解决方案是降低特征空间的维数,例如通过特征选择。

3:培训时间

功能越多,训练时间越多。这种权衡的细节取决于所使用的特定学习算法,但是在需要实时进行再训练的情况下,人们可能需要将自己限制在几个最佳特性上。

4:部署工作

功能越多,机器学习系统在生产中就变得越复杂。这带来了多种风险,包括但不限于高维护成本、纠缠、未申报的消费者或修正级联

5:可解释性

有了太多的特征,我们就失去了模型的可解释性。虽然并不总是主要的建模目标,但是解释和说明模型的结果通常是重要的,并且在一些受管制的领域中甚至可能构成法律要求。

6:奥卡姆剃刀

根据这个所谓的节俭定律,只要性能相同,简单的模型应该比复杂的模型更受青睐。这也和机器学习工程师的克星,过度拟合有关。不太复杂的模型不太可能过度拟合数据。

7:数据模型兼容性

最后,还有数据模型兼容性的问题。虽然原则上这种方法应该是数据优先,这意味着收集和准备高质量的数据,然后选择一个适合这些数据的模型,但现实生活可能正好相反。

你可能试图复制一篇特定的研究论文,或者你的老板可能建议使用特定的模型。在这种模型优先的方法中,您可能被迫选择与您开始训练的模型兼容的特性。例如,许多模型无法处理数据中的缺失值。除非你非常了解你的插补方法,否则你可能需要删除不完整的特征。

不同的特征选择方法

所有不同的特征选择方法可以分为四类,每一类都有其优点和缺点。有无监督和有监督的方法。后者可以进一步分为包装器、过滤器和嵌入式方法。让我们逐一讨论。

不同的特征选择方法。图片由作者提供。

无监督方法

就像无监督学习是在无标签数据中寻找模式的学习类型一样,无监督特征选择方法也是不利用任何标签的方法。换句话说,他们不需要访问机器学习模型的目标变量。

你可能会问,如果不分析一个特性与模型目标的关系,我们怎么能说它对模型不重要呢?嗯,在某些情况下这是可能的。我们可能希望放弃以下功能:

  • 零或接近零的方差。(几乎)不变的特征提供的学习信息很少,因此是不相关的。
  • 许多缺失值。虽然删除不完整的特征不是处理缺失数据的首选方式,但这通常是一个好的开始,如果缺失太多条目,这可能是唯一明智的做法,因为这些特征可能是不相关的。
  • 高度多重共线性;多重共线性意味着不同要素之间的相关性很强,这可能表示存在冗余问题。

包装方法

包装器方法是指一系列受监督的特征选择方法,这些方法使用模型来对不同的特征子集进行评分,以最终选择最佳的一个。每个新的子集用于训练一个模型,然后在保留集上评估该模型的性能。选择产生最佳模型性能的特征子集。

包装方法的一个主要优点是,它们倾向于为特定的模型类型提供性能最佳的特性集。

然而,与此同时,这也是一种限制。包装器方法很可能会过度适应模型类型,如果想在不同的模型中尝试它们,它们产生的特性子集可能不会通用化。

包装器方法的另一个显著缺点是它们需要大量的计算。它们需要训练大量的模型,这可能需要时间和计算能力。

流行的包装方法包括:

  • 逆向选择,我们从包含所有可用功能的完整模型开始。在随后的迭代中,我们一次删除一个特征,总是在模型性能度量中产生最大增益的那个,直到我们达到期望的特征数量。
  • 正向选择,反向工作:我们从一个零特征的空模型开始,一次贪婪地添加一个特征,使模型的性能最大化。
  • 递归特征消除,或 RFE,精神上类似于逆向选择。它也从一个完整的模型开始,一个接一个地迭代消除特征。区别在于选择要丢弃的特征的方式。RFE 并不依赖于拒不接受的模型性能指标,而是基于从模型中提取的特征重要性来做出决策。这可以是线性模型中的特征权重、基于树的模型中的杂质减少或排列重要性(适用于任何模型类型)。

过滤方法

受监督家族的另一个成员是过滤方法。可以认为它们是计算包装器的更简单、更快速的替代方法。为了评估每个特征的有用性,他们简单地分析其与模型目标的统计关系,使用诸如相关性或互信息之类的度量作为模型性能度量的代理。

过滤器方法不仅比包装器快,而且更通用,因为它们是模型不可知的;他们不会过度适应任何特定的算法。它们也很容易解释:如果一个特征与目标没有统计关系,它就会被丢弃。

然而,另一方面,过滤方法有一个主要缺点。他们孤立地看待每个特征,评估它与目标的关系。这使得它们倾向于丢弃有用的特征,这些特征本身是目标的弱预测器,但是当与其他特征结合时,为模型增加了很多价值。

嵌入式方法

我们将讨论的最后一种特征选择方法是将其嵌入学习算法本身。这个想法是结合两个世界的优点:过滤器的速度,同时获得特定模型的最佳子集,就像从包装器中一样。

最典型的例子是套索回归。它基本上只是正则化的线性回归,其中特征权重在损失函数中向零收缩。因此,许多要素的权重最终为零,这意味着它们将从模型中被丢弃,而权重非零的其余要素将被包括在内。

嵌入式方法的问题在于,没有多少算法内置了特征选择。LASSO 旁边的另一个例子来自计算机视觉:带有瓶颈层的自动编码器迫使网络忽略图像中一些最无用的特征,而专注于最重要的特征。除此之外,例子不多。

过滤方法:技巧和提示

正如我们所看到的,包装方法速度慢,计算量大,并且是特定于模型的,并且没有多少嵌入式方法。因此,过滤器通常是特征选择方法的首选。

同时,他们需要最专业的知识和对细节的关注。虽然嵌入式方法开箱即用,包装器实现起来也相当简单(尤其是当人们只调用 scikit-learn 函数时),但过滤器需要一点统计复杂性。现在让我们把注意力转向滤波方法,并更详细地讨论它们。

复习一下你的统计数据

过滤方法需要评估每个特征和目标之间的统计关系。虽然听起来很简单,但事情远比看起来简单。有许多统计方法来衡量两个变量之间的关系。为了知道在特定情况下选择哪一个,我们需要回想一下我们的第一个 STATS101 类,并复习一下数据测量级别

数据测量级别

简而言之,变量的测量水平描述了数据的真实含义以及对这些数据有意义的数学运算的类型。有四种测量级别:标称、顺序、间隔和比率。

数据测量级别。来源:【链接

标称特征,例如颜色(“红”、“绿”或“蓝”)在值之间没有排序;他们只是根据他们对的观察。

序数特征,如教育水平(“初级”、“中级”、“高级”)表示顺序,但不是特定水平之间的差异(我们不能说“初级”和“中级”之间的差异与“中级”和“高级”之间的差异相同)。

间隔要素(如以摄氏度为单位的温度)保持间隔相等(25 度和 20 度之间的差异与 30 度和 25 度之间的差异相同)。

最后,比率特性,如以美元表示的价格,以有意义的零为特征,这允许我们计算两个数据点之间的比率:我们可以说 6 美元是 2 美元的两倍。

为了选择正确的统计工具来度量两个变量之间的关系,我们需要考虑它们的度量水平。

测量各种数据类型的相关性

当我们比较的两个变量,即特征之一和目标,都是区间或比率时,我们可以使用最流行的相关性度量:T4 皮尔逊相关性,也称为皮尔逊相关性。

这很好,但是皮尔逊相关性有两个缺点:它假设两个变量都是正态分布的,并且它只测量它们之间的线性相关性。当相关性是非线性时,皮尔逊的 r 不会检测到它,即使它真的很强。

你可能听说过由 Alberto Cairo 编译的 Datasaurus 数据集。它由 13 对变量组成,每个变量都具有相同的非常弱的皮尔逊相关性-0.06。一旦我们把它们标绘出来,就很快变得显而易见,这些对实际上有很强的相关性,尽管是以非线性的方式。

Alberto Cairo 的 Datasaurus 数据集。

当预期非线性关系时,应考虑皮尔逊相关性的替代方法之一。最受欢迎的两个是:

  • 斯皮尔曼秩相关(斯皮尔曼ρ),
  • 肯德尔秩相关(Kendall Tau)。

对于比率/区间变量,Spearman 等级相关是 Pearson 相关的替代方法。顾名思义,它只查看等级值,即它根据变量中特定数据点的相对位置来比较两个变量。它能够捕捉非线性关系,但没有免费的午餐:由于只考虑排名而不是确切的数据点,我们丢失了一些信息。

另一种基于等级的相关性度量是肯德尔等级相关性。它在精神上类似于 Spearman 的相关性,但表述方式略有不同(Kendall 的计算基于一致和不一致的值对,与 Spearman 基于偏差的计算相反)。肯德尔通常被认为对数据中的异常值更稳健。

如果至少有一个被比较的变量是序数型的,Spearman 或 Kendall 等级相关法是可行的。由于序数数据只包含关于等级的信息,所以它们都是完美的匹配,而皮尔逊的线性相关性用处不大。

另一种情况是两个变量都是名义变量。在这种情况下,我们可以从几个不同的相关性度量中进行选择:

  • Cramer 的 V ,它将两个变量之间的关联捕捉到一个从零(没有关联)到一(一个变量完全由另一个变量决定)的数字中。
  • 卡方统计量,常用于检验两个变量之间的相关性。缺乏依赖性意味着特定的特性没有用。
  • 互信息,衡量两个变量之间的相互依赖性,试图量化人们可以从一个变量中提取的关于另一个变量的信息量。

选哪个?没有放之四海而皆准的答案。通常,每种方法都有一些优点和缺点。众所周知,克拉默的 V 字高估了该协会的实力。互信息作为一种非参数方法,需要更大的数据样本来产生可靠的结果。最后,卡方检验不能提供关系强度的信息,而只能提供关系是否存在的信息。

我们已经讨论了这样的场景,其中我们比较的两个变量都是区间或比率,当它们中至少有一个是序数时,以及当我们比较两个名义变量时。最后可能遇到的是比较一个名义变量和一个非名义变量。

在这种情况下,两种最广泛使用的相关性度量是:

  • ANOVA F-score ,当一个变量是连续的而另一个是名义变量时的卡方当量。
  • 点-双列相关,一种专门用于评估二进制变量和连续变量之间关系的相关性度量。

再说一次,没有灵丹妙药。F 分数只捕捉线性关系,而点-双列相关作出一些强正态假设,在实践中可能不成立,破坏了它的结果。

说了这么多,在特定情况下应该选择哪种方法呢?下表有望在这个问题上提供一些指导。

常见的相关措施,由作者编制。

转换您的变量

正如我们已经看到的,可以与过滤器特征选择方法一起使用的每个相关性度量适合于特定的数据类型。同时,每一种都有一些优点和缺点。如果您认为某个特定的方法非常适合您的用例,但是它不适合您的数据类型,或者它的假设没有得到满足,该怎么办?不用担心,一个聪明的数据转换将会扭转局面。

例如,假设您的数据集中有一个比率特征和一个比率目标。但是,您担心使用 Pearson 相关性不起作用,因为该特征是非正态分布的。在这种情况下,您可以使用 z 得分来归一化您的要素,以确保满足正态假设。

现在想象一个不同的情况:目标是名义上的,特征是一个比率。基于领域知识,你期望它们之间的关系是非线性的,这禁止了 F 分数的使用。同时,该特征是非正态的,这排除了使用点-双列相关。怎么办?您可以将要素离散化到多个条柱中,并尝试一种名义-名义测量方法,如互信息。

从这两个例子中可以看出,通过转换数据,我们可以获得比原来可行的更多的相关性度量。

sci kit-学习和超越

就像大多数其他机器学习任务一样,scikit-learn 包很好地完成了特征选择,尤其是它的sklearn.feature_selection模块。然而,在某些情况下,一个人需要接触到其他地方。对于本文的其余部分,让我们用X来表示一个数组或数据框,所有潜在的特性都是列,观察值是行,用y来表示目标向量。

让我们从无监督的特征选择方法开始:

  • sklearn.feature_selection.VarianceThreshold变压器将默认移除所有零方差特性。我们还可以给它传递一个阈值,让它移除方差低于阈值的特征。
from sklearn.feature_selection import VarianceThresholdsel = VarianceThreshold(threshold=0.05)
X_selection = sel.fit_transform(X)
  • 为了删除缺少值的列,可以在数据框上使用 pandas 的dropna(axis=1)方法。
X_selection = X.dropna(axis=1)
  • 要移除具有高度多重共线性的要素,我们首先需要测量它。一种流行的多重共线性测量方法是方差膨胀因子或 VIF。它是在 statsmodels 包中实现的。
from statsmodels.stats.outliers_influence import variance_inflation_factorvif_scores = [
    variance_inflation_factor(X.values, feature)
    for feature in range(len(X.columns))
]

按照惯例,VIF 大于 10 的列被视为存在多重共线性,但如果另一个阈值看起来更合理,则可以选择该阈值。

谈到包装器方法,scikit-learn 为我们提供了:

  • 向后和向前特征选择可以通过 SequentialFeatureSelector 转换器实现。例如,为了使用 k-最近邻分类器作为正向选择中的评分模型,我们可以使用以下代码片段:
from sklearn.feature_selection import SequentialFeatureSelectorknn = KNeighborsClassifier(n_neighbors=3)
sfs = SequentialFeatureSelector(knn, n_features_to_select=3, direction=”forward”)
sfs.fit(X, y)
X_selection = sfs.transform(X)
  • 递归特征消除以非常相似的方式实现。下面是一个基于支持向量分类器的特征重要性实现 RFE 的片段。
from sklearn.feature_selection import RFEsvc = SVC(kernel=”linear”)
rfe = RFE(svc, n_features_to_select=3)
rfe.fit(X, y)
X_selection = rfe.transform(X)

现在让我们来看看如何实现各种过滤方法。这些将需要更多的粘合代码来实现。首先,我们需要计算每个特征和目标之间适当的相关性度量。然后,我们将根据结果对所有特征进行排序,并保留所需数量(前 K 个,或前 30%)的相关性最强的特征。幸运的是,scikit-learn 提供了一些实用程序来帮助这一努力。

  • 为了保留与目标具有最强 Pearson 相关性的前两个特征,我们可以运行:
from sklearn.feature_selection import r_regression, SelectKBest
X_selection = SelectKBest(r_regression, k=2).fit_transform(X, y)
  • 类似地,为了保留前 30%的特性,我们将运行:
from sklearn.feature_selection import r_regression, SelectPercentileX_selection = SelectPercentile(r_regression, percentile=30).fit_transform(X, y)

SelectKBestSelectPercentile方法也适用于自定义或非 scikit-learn 相关性测量,只要它们返回长度等于特征数量的向量,每个特征的数量表示其与目标的关联强度。接下来,让我们看看如何计算我们之前讨论过的所有不同的度量。

  • Spearman 的 Rho、Kendall Tau 和点-双列相关都可以在 scipy 包中获得。这就是如何获得 x 中每个特征的值。
from scipy import statsrho_corr = [stats.spearmanr(X[:, f], y).correlation for f in range(X.shape[1])]tau_corr = [stats.kendalltau(X[:, f], y).correlation for f in range(X.shape[1])]pbs_corr = [stats.pointbiserialr(X[:, f], y).correlation for f in range(X.shape[1])]
  • 卡方、互信息和 ANOVA F-score 都在 scikit-learn 中。请注意,互信息有一个单独的实现,这取决于目标是否是名义上的。
from sklearn.feature_selection import chi2
from sklearn.feature_selection import mutual_info_regression
from sklearn.feature_selection import mutual_info_classif
from sklearn.feature_selection import f_classifchi2_corr = chi2(X, y)[0]
f_corr = f_classif(X, y)[0]
mi_reg_corr = mutual_info_regression(X, y)
mi_class_corr = mutual_info_classif(X, y)
  • Cramer 的 V 可以从最近的 scipy 版本(1.7.0 或更高版本)获得。
from scipy.stats.contingency import associationv_corr = [association(np.hstack([X[:, f].reshape(-1, 1), y.reshape(-1, 1)]), method=”cramer”) for f in range(X.shape[1])]

不要俘虏:博鲁塔不需要人类的参与

说到特性选择,不能不提到 Boruta。早在 2010 年,当首次将作为 R 包发布时,它很快就因革命性的特征选择算法而闻名。

到目前为止,我们讨论的所有其他方法都需要人类做出任意的决定。无监督方法需要我们为特征移除设置方差或 VIF 阈值。包装器要求我们决定想要保留的特性的数量。过滤器需要我们选择相关度和要保留的特征数量。嵌入式方法让我们选择正则化强度。博鲁塔不需要这些。

Boruta 是一个简单但统计优雅的算法。它使用来自随机森林模型的特征重要性度量来选择特征的最佳子集,并且它通过引入两个聪明的想法来做到这一点。

首先,特性的重要性分数不能相互比较。相反,每个特征的重要性与其随机化版本的重要性相竞争。为了实现这一点,Boruta 随机排列每个特征来构建它的“影子”版本。然后,在整个特征集上训练随机森林,包括新的阴影特征。阴影特征中的最大特征重要性用作阈值。在原始特征中,只有那些重要性高于这个阈值的特征才得分。换句话说,只有比随机向量更重要的特征才会被加分。

上述过程迭代重复多次。由于每次随机排列不同,阈值也不同,因此不同的特征可能得分。经过多次迭代后,每个原始特征都有一些指向其名称的点。

最后一步是根据每个特性的得分来决定是保留还是丢弃它。博鲁塔的两个聪明想法中的另一个出现了:我们可以使用二项式分布来模拟分数。

每一次迭代都被认为是一次独立的试验。如果该特性在给定的迭代中得了分,它就是一个保留它的投票;如果没有,那就投票决定放弃它。先验地,我们不知道某个特征是否重要,所以该特征得分的预期试验百分比是 50%。因此,我们可以用 p=0.5 的二项式分布来模拟分数。如果我们的特征得分明显高于这个次数,它就被认为是重要的并被保留。如果得分次数少得多,它就被认为不重要并被丢弃。如果它在大约 50%的试验中得分,它的状态是未解决的,但是为了保守起见,我们可以保留它。

例如,如果我们让 Boruta 运行 100 次试验,那么每个特性的预期得分将是 50。如果它接近零,我们丢弃它,如果它接近 100,我们保留它。

博鲁塔的决策过程。图片由作者提供。

Boruta 在许多 Kaggle 比赛中已经证明非常成功,总是值得尝试。它还被成功用于预测建筑供暖能耗预测空气污染

有一个非常直观的 Python 包来实现 Boruta,叫做 BorutaPy (现在是scikit-learn-contrib的一部分)。这个包的 GitHub readme 演示了用 Boruta 运行特性选择是多么容易。

为自己构建一个投票选择器

我们已经讨论了许多不同的特征选择方法。每一种都有自己的长处和短处,做出自己的假设,并以不同的方式得出结论。选哪个?还是我们必须选择?在许多情况下,将所有这些不同的方法组合在一起会使最终的特性选择器比它的每个子部分都更强大。

一种方法是受集合决策树的启发。在这类模型中,包括随机森林和许多流行的梯度增强算法,人们训练多个不同的模型,并让它们对最终预测进行投票。本着类似的精神,我们可以为自己构建一个投票选择器。

想法很简单:实现我们已经讨论过的几个特性选择方法。您的选择可能会受到您的时间、计算资源和数据测量水平的影响。只要你能负担得起,就尽可能多的运行不同的方法。

然后,对于每个特征,写下建议将该特征保留在数据集中的选择方法的百分比。如果超过 50%的方法投票支持保留该特性,那么就保留它——否则,就放弃它。

这种方法背后的思想是,虽然一些方法可能由于其固有的偏见而对一些特征做出错误的判断,但是方法的集合应该正确地得到有用的特征集。让我们看看在实践中如何实现!

让我们构建一个简单的投票选择器,它集成了三种不同的特征选择方法:基于 Pearson 相关性的过滤方法、基于多重共线性的非监督方法和包装器,即递归特征消除。让我们看看这样一个投票选择器可能是什么样子。接下来,我们将详细讨论代码。

我们的 VotingSelector 类在 init 构造函数之上包含四个方法。其中三个实现了我们想要集成的三种特征选择技术:_select_pearson()用于皮尔逊相关滤波,_select_vif()用于基于方差膨胀因子的无监督方法,_select_rbf()用于 RBF 包装器。

这些方法中的每一种都将特征矩阵 X 和目标 y 作为输入。基于 VIF 的方法不会使用目标,但是我们仍然使用这个参数来保持所有方法的接口一致,这样我们可以方便地在以后的循环中调用它们。除此之外,每个方法都接受一个关键字参数字典,我们将使用它来传递依赖于方法的参数。

解析完输入后,每个方法调用适当的 sklearn 或 statsmodels 函数,返回要保留的特性名称列表。

投票魔术发生在select()方法中。在这里,我们简单地迭代三个选择方法,对于每个特征,我们记录它是否应该根据这个方法被保留(1)或丢弃(0)。最后,我们对这些投票取平均值。对于每个特性,如果这个平均值大于投票阈值 0.5(这意味着三个方法中至少有两个投票保留了一个特性),我们就保留它。

让我们看看它在实践中的效果。我们将加载臭名昭著的波士顿住房数据,这是内置的 w scikit-learn。

现在,运行特征选择就像这样简单:

vs = VotingSelector()
X_selection = vs.select(X, y)

结果,我们得到的特征矩阵只剩下三个特征。

 ZN  CHAS     RM
0    18.0   0.0  6.575
1     0.0   0.0  6.421
2     0.0   0.0  7.185
3     0.0   0.0  6.998
4     0.0   0.0  7.147
..    ...   ...    ...
501   0.0   0.0  6.593
502   0.0   0.0  6.120
503   0.0   0.0  6.976
504   0.0   0.0  6.794
505   0.0   0.0  6.030
[506 rows x 3 columns]

我们还可以通过打印vs.votes来一瞥我们的每个方法是如何投票的。

CRIM  ZN  INDUS  CHAS  NOX  RM  AGE  DIS  RAD  TAX  PTRATIO  B LSTAT
pearson  0   1   0   1   0   1   0   1   0   0   0   1   0
vif      1   1   0   1   0   0   0   0   0   0   0   0   0
rfe      0   0   0   1   1   1   0   0   0   0   1   0   1

最初的 13 个专栏只剩下 3 个,我们可能会不高兴。幸运的是,我们可以很容易地通过修改特定方法的参数来减少选择的限制。这可以通过简单地向 select 调用添加适当的参数来实现,这要感谢我们如何传递 kwargs。

皮尔逊和 RFE 方法需要保留预定数量的特征。默认值为 5,但我们可能希望将其增加到 8。我们还可以修改 VIF 阈值,该阈值是方差膨胀因子的值,高于该值时,由于多重共线性,我们会丢弃某个要素。按照惯例,这个阈值被设置为 10,但是增加到 15 会导致更多的特性被保留。

vs = VotingSelector()
X_selection = vs.select(X, y, n_features_to_select=8, vif_threshold=15)

这样,我们还剩下七个特征。

我们的 VotingSelector 类是一个简单但通用的模板,您可以将其扩展到任意数量的特征选择方法。作为一种可能的扩展,您还可以将传递给select()的所有参数视为您的建模管道的超参数,并对它们进行优化,以便最大化下游模型的性能。

大技术公司的功能选择

大型科技公司,如 GAFAM 等,拥有数以千计的生产中的机器学习模型,是如何在野外操作特征选择的主要例子。让我们看看这些科技巨头对此有什么看法!

ML 的规则是谷歌机器学习最佳实践的便利汇编。在其中,谷歌的工程师指出,该模型可以学习的参数数量大致为

与它可以访问的数据量成比例。因此,我们拥有的数据越少,需要丢弃的特征就越多。他们粗略的指导方针(来源于基于文本的模型)是使用十几个特征和 1000 个训练样本,或者 100,000 个特征和 1000 万个训练样本。

文档中的另一个关键点涉及模型部署问题,这也会影响特性选择。首先,可供选择的特性集可能会受到推理时产品中可用特性的限制。如果一个很棒的特性在模型上线时不存在,你可能会被迫放弃它。第二,一些特性可能容易出现数据漂移。虽然解决漂移是一个复杂的话题,但有时最好的解决方案可能是从模型中完全删除有问题的特性。

参考

感谢阅读!我希望这篇概述文章已经使您相信特性选择是数据准备过程中的一个关键步骤,并为您提供了一些关于如何实现它的指导。不要犹豫,在社交媒体上联系我,讨论这里涵盖的主题,或任何其他机器学习主题。快乐精选!

如果你喜欢这篇文章,为什么不订阅电子邮件更新我的新文章呢?并且通过 成为媒介会员 ,可以支持我的写作,获得其他作者和我自己的所有故事的无限访问权限。

需要咨询?你可以问我任何问题,也可以在这里 为我预约 1:1

你也可以试试我的其他文章。不能选择?从这些中选择一个:

</8-tips-for-object-oriented-programming-in-python-3e98b767ae79>

使用遗传算法的特征选择

原文:https://towardsdatascience.com/feature-selection-using-genetic-algorithms-d3f5fc7bbef1

通过将遗传算法应用于特性优化过程,了解其工作原理

国家癌症研究所Unsplash 上拍摄的照片

F 由于高维数据量的增加【1】,特征选择已经成为训练机器学习模型的数据处理的基本步骤。

有大量最先进的算法旨在优化特征选择(最佳性能技术的综述可在【2】中找到),包括遗传算法。虽然遗传算法不是表现最好的技术,但它提供了一种基于进化(因此本质上是随机的)的令人兴奋的解决方案,并被广泛用于机器人、营销或医学等领域【3】,因此知道如何使用它们会非常有用。出于所有这些原因,本文展示了遗传算法的逻辑及其应用,特别是针对特性优化过程。

首先,所有需要的库都被导入以备将来使用。

遗传算法

遗传算法旨在复制遗传进化的行为,即最适合环境的个体的遗传基因会随着时间的推移而持续存在。

根据目标函数或启发法来评估群体中的个体,该目标函数或启发法用于在每次迭代中选择要繁殖的个体。从目标函数中获得更好结果的那些个体将以更高的概率被选择用于繁殖(在自然界中,具有更好遗传的个体活得更长更好,这允许他们繁殖更多他们的基因)。值得一提的是,选择个体进行繁殖是随机的,因此最好的个体不会总是被选择,这有助于算法不会陷入局部最小值。经过几代后,选出最佳个体作为最终结果。

既然已经在高层次上解释了算法,更多的焦点将放在进化过程的每一步上。

个体的表象

第一步是找到一种方法来代表每一个人。目标是从初始特征中找到特征的最佳子集,因此每个个体必须是其所具有的特征子集的代表。同样为了寻找尽可能低的内存成本,个体将被表示为长度等于特征数量的字符串,其中字符串的每个字符对应于一个特征,并且将具有值 1 或 0,这取决于该特征是否是活动的。这样,每个个体将占用 n 个字节,其中 n 是特性的初始数量(Python 需要 1 个字节来存储一个 char)。下面是 7 个要素的数据集如何表示个体的示例。

图片作者。个人代表

生成人口

下一步是生成一个具有一定数量个体的群体,作为算法的起点。个体的产生可以完全随机,也可以稍微控制。如果只找到特征的最佳子集,个体的产生可以是完全随机的。然而,如果除了寻找最佳子集之外,还需要减少数据集的维数,那么强制个体生成器创建最大数量为 1 的个体是很有趣的。通过这种方式,所有个体将拥有最大数量的活动要素,从而降低数据集的维度。下面的代码展示了随机生成和受控生成的个体生成器的实现。

个体的生产者

获取群体中每个个体的权重

为了获得权重,将使用仅包含该个体的活动要素的数据集为每个个体训练模型。

这种训练将通过用 tensorflow 构建的神经网络来进行,该神经网络由分别为 32、64 和 1 个神经元的 3 个密集层组成。前两个图层使用 ReLu 激活函数,而输出图层使用 sigmoid 函数,通常用于二元分类。损失度量是二进制交叉熵,Adam 用作优化器。关于模型的输入形状,这将根据个体子集中的特征数量而变化。因此,所有模型将具有相同的层,但它们的输入形状会有所不同。

模型的创建

一旦模型在每个个体的特征子集上被训练,每个模型的准确度被计算。因为这篇文章的目的是在介绍的水平上介绍遗传算法在特征选择中的应用,所以权重是以一种非常基本的方式从模型精度中计算出来的。为了计算个体的权重,其模型的精度将除以总体精度的总和。这样所有的权重加起来就是 1,我们可以用它们作为选择繁殖个体的概率。

在执行这个最后的函数( fill_population() )之后,得到的群体是元组的列表,每个个体(字符串)是元组的第一个元素,第二个元素是其相应的权重。

繁殖个体

按照从先前计算的权重获得的分布,选择 N 个个体,其中 N 是群体的大小,并且从每对个体中产生两个新的个体。这样,每一代都将拥有与上一代相同数量的个体,因此该算法可以根据需要运行多次迭代。

按照与进化的相似性,生殖包括结合父母的基因。为此,将随机生成一个介于 1 和 n -1 之间的数( n 仍然是群体的大小)。这个数字将被用来把父母的基因分成随机大小的块。第一个新个体将拥有来自父代 A 的第一个块和来自父代 B 的第二个块。第二个新个体将由父代 B 的第一个块和父代 A 的第二个块组成。下面显示了繁殖过程的直观解释。

图片作者。复制过程

一旦产生了两个新个体,就该对它们应用突变了。这些突变有助于在个体中产生轻微的变异,从而避免产生相同个体的群体(局部最小值)。每个个体的所有字符将被遍历,并根据作为参数设置的概率进行变异。例如,通过将概率设置为 0.15,每 100 个字符将发生大约 15 次突变。

重复 的过程

一旦新的种群被创建,每个个体的权重被重新计算,繁殖和变异过程被再次执行。每次迭代产生具有更好个体的群体,并且在一定数量的代/迭代之后,将从所有生成的代中提取具有最佳特征子集的个体。

注意,当随机生成第一个群体时,特征的数量被设置为 65。这是因为用于的数据集有 65 个要素,但可以根据要优化的数据集将其更改为任何其他值。

特征优化的应用

首先应该提到的是,无论是数据的预处理还是模型超参数的选择都不在本文的考虑范围之内,因此将使用一个预处理的数据集(没有丢失值,所有变量都是数值型的,并在 0 到 1 之间归一化)和一个简单的二元分类器,该分类器与上一节中介绍的分类器非常相似。

通过使用上一节中介绍的遗传算法,在所有代中实现最高准确度的个体被提取出来。这个个体代表了特征的子集,所以剩下要做的就是从数据集中提取那些相关的特征,并训练提到的模型。

直观显示要素选择过程对模型的贡献的一个很好的方法是首先用整个数据集训练模型,而不移除任何要素。这样,可以在选择特征之前和之后比较模型的性能,从而获得可靠的结果。当使用相同的模型和数据集时,两个模型之间任何明显的性能差异都是由特征优化引起的,这使得它成为确认改进的非常有效的方法。

evaluate_model()函数显示 Keras 二元分类器的性能指标,因此它可用于评估使用完整数据集训练的模型和使用优化数据集训练的模型。

在我的例子中,我已经通过运行 GA 50 次迭代,并使用 20 个个体的群体,进行了特征优化。从两个训练模型获得的准确度、精确度、召回率和 F1 分数度量可以在下面看到。

图片作者。两种模型的指标

显然,在优化数据集上训练的模型所获得的结果已经改善了在完整数据集上训练的模型的结果。

结论

结果显示,使用优化数据集(已应用特征选择)训练的模型的准确性有了相当大的提高。通过对两次训练使用相同的模型架构和相同的超参数,结果中的差异以无偏的方式显示了特征优化过程的效果。所获得的度量,除了准确性之外,也显示出改进,因此可以确认算法的有效性。

值得注意的是,该模型的体系结构非常简单,因此无法充分捕捉特征之间的关系。因此,这两个模型获得的指标都不是最优的,事实上还有很多工作要做。然而,正如整篇文章中所提到的,要点是对遗传算法的介绍以及它们在特性优化中的应用,因此,度量中的可见改进足以证明优化方法的有效性,即使模型不是最优的。

完整代码

在上面显示的代码的某些部分中,调用了文章中不存在的函数。所有这些函数都可以在我的 GitHub 存储库中找到,还有一个真实的运行示例 Jupyter Notebook 和用于训练的数据集。

尽管如此,尝试理解缺少的函数所提供的功能,并亲自对它们进行编程,这是一个很好的练习!

如果你喜欢这篇文章和/或觉得它有用,请关注我以后的文章,分享这篇文章,这样其他人也可以学习。非常感谢您的阅读和支持!

GitHub 库:

https://github.com/JavierMtz5/ArtificialIntelligence

参考

【1】卡鲁西斯,亚历山大;朱利安·普拉多斯;希拉里奥,梅勒妮。特征选择算法的稳定性:高维空间的研究。知识与信息系统,2007 年,第 12 卷,第 1 期,第 95–116 页

【2】库马尔,Vipin 明兹索纳查里亚。特征选择:文献综述。 SmartCR ,2014 年,第 4 卷,第 3 期,第 211–229 页

【3】https://www.baeldung.com/cs/genetic-algorithms-applications

本文和 GitHub 中使用的数据集是电信客户流失(cell2cell) 数据集的预处理版本,可在以下链接中找到:

https://www.kaggle.com/datasets/jpacse/datasets-for-churn-telecom

Python 中模拟退火的特征选择,解释清楚

原文:https://towardsdatascience.com/feature-selection-with-simulated-annealing-in-python-clearly-explained-1808db14f8fa

为机器学习选择最佳特征的全局搜索算法的概念和实现

约翰尼斯 W 在 Unsplash 上的照片

特征选择在机器学习中至关重要,因为它通过只保留最相关的预测器来提高计算效率和预测性能。

除了过滤器和包装器方法等流行的特征选择类之外,模拟退火等全局搜索方法是我们可以使用的强大技术。

这个简单的一步一步的指南深入研究了模拟退火特性选择的理论和应用。

内容

1) 什么是退火?2)门外汉对模拟退火的解释3)利弊对模拟退火进行特征选择

你可以在这里 找到这个项目 的 GitHub 回购。

(1)什么是退火?

术语“退火”来自材料科学领域。这是一个过程,其中金属或玻璃等材料被加热并保持在高温,然后以受控方式缓慢冷却。

退火的目的是将有利的物理特性(例如延展性)引入材料,以便更顺利地进行下游制造。

热量导致材料中原子的随机重排,这消除了内部的弱连接和残余应力。

随后的冷却使材料凝固,并确保所需的物理性能。

克莱门特·菲利普在 Unsplash 上拍摄的照片

(2)模拟退火的外行解释

那么这个看似不相关的物理退火是如何与特征选择联系起来的呢?你会惊奇地发现模拟退火是一种模仿退火工作方式的全局搜索方法。

在特征选择的上下文中,模拟退火在许多可能的子集组合中找到给出最佳预测模型性能的** 特征子集。**

这种想法就像物理退火旨在为材料产生高性能的物理特性。

为了想象模拟退火与物理退火的关系,我们可以想象以下比较:

  • 一个物质粒子→一个特征
  • 材料本身→全套功能
  • 粒子排列的当前状态→选定的特征子集
  • 材料物理特性的变化→模型性能的变化

模拟退火中重复的“加热”和“冷却”阶段有助于我们找到最佳的全局特征子集。

以下是加热和冷却阶段在算法中的含义:

  • ****加热:随机改变特征子集,评估模型性能的变化,并设置接受较差性能子集而非较好子集的高概率。这个阶段被认为是'勘探'。
  • ****降温:逐渐降低保留不良子集的概率,使高性能子集保留的可能性越来越大。这个阶段被认为是'开采'。

基本原理是初始加热让算法自由地探索搜索空间。随着冷却开始,算法被激励去利用 T21,并聚焦于全局最佳特征子集。

(3)用于特征选择的模拟退火的利弊

赞成的意见

在三种常见的特征选择类(即内在、过滤器、包装器)中,包装器方法非常流行,因为它们比其他两种方法搜索更广泛的特征子集。然而,缺点是这些包装器方法是贪婪的方法。

贪婪的方法选择搜索路径,以可能的长期收益为代价,追求每一步的最佳即时收益。结果是搜索可能陷入局部最优。

维基共享许可下使用的全球和本地最小|图像插图

相反,模拟退火是一种概率全局优化方法,采用由算法中赋予的随机性驱动的非贪婪方法。

非贪婪方法可以重新评估以前的子集,如果从长远来看似乎有潜在的好处,则朝着最初不利的方向前进。

因此,模拟退火具有更强的能力来摆脱局部最优并找到特征的全局最佳子集。

此外,它的非贪婪本质创造了捕获关键特征交互的更高概率,特别是如果这些交互只有在特征在子集中同时出现时才是重要的。

骗局

一个缺点是模拟退火是计算密集型的,你将在后面的算法细节中看到。

因此,最好首先利用领域知识来缩小整个特性集的范围。对于较小的特征集,使用模拟退火进行进一步的特征选择变得更加有效。

另一个缺点是有许多算法参数需要调整,这可能是一个挑战。

(4)算法细节

注:您可以参考本GitHub repo中该演示的代码和数据。**

(一)概述

为了让算法更容易理解,我们把它一步步分解,并配以实例。

为了将算法情境化,我们将在 【泰坦尼克】 数据集上使用随机森林模型构建一个二元分类器(以预测乘客存活率)并将 ROC-AUC 分数作为性能度量。

预处理后的训练数据共有九个预测器特征和一个二元目标变量(**Survived**)。

预处理过的泰坦尼克号数据集样本|作者提供的图片

步骤 1 — 生成特征的随机初始子集,以形成当前状态。这个步骤可以通过随机选择 50%的原始特征来任意完成。

例如,假设我们最初的四个特征的随机子集是**Pclass****Age****Parch****Title**

绿框所示的初始特征子集|作者图片

步骤 2 — 指定要运行的迭代的最大次数。这个数字是一个可调参数,但是为了简单起见,我们可以从一个整数(例如 50)开始。

步骤 3 — 评估当前子集的模型性能,以获得初始性能指标。对于这种情况,我们在过滤到当前 4 特征子集(**Pclass****Age****Parch****Title**)的数据上训练随机森林分类器,并检索交叉验证的 AUC 分数。

以下步骤( 步骤 4 至 7 )代表 单次迭代 。要运行的最大迭代次数已经在步骤 2 中定义了。

模拟退火中的单次迭代流程图(步骤 4 至步骤 7** )**

步骤 4 — 随机改变当前子集中的特征列表,通过添加、替换或删除一个特征来生成一个新的子集

例如,一个随机的改变产生了一个新的 5 特征子集,现在包括了**FamilySize**

下一次迭代的新特征子集。添加的新功能由蓝框表示|图片由作者提供

注意:如果一个子集之前已经被访问过,我们重复此步骤,直到生成一个新的未被访问的子集。

步骤 5 —新子集上运行模型,并且性能指标(即 AUC 分数)与**当前子集进行比较。**

步骤 6 — 如果**新子集性能更好,接受并更新新子集为当前状态,结束迭代。如果性能差,继续步骤 7。**

步骤 7 — 通过首先计算一个接受概率来评估是否接受表现最差的新子集(更多细节在后面)。接下来,在范围[0,1]内统一生成一个随机数

如果随机数大于接受概率,则拒绝新子集并保留当前子集。否则,接受并更新新的子集作为当前状态。****

一个迭代的例子,其中新子集具有更差的性能,但仍然被接受并更新为当前状态,因为随机数比接受概率小

在每次迭代结束时,接受概率被调整以建立一个“冷却”计划。让我们看看这是如何工作的。

㈡接受概率

我们之前(在步骤 7 中)看到了如何使用接受概率来决定是否接受一个性能更差的新子集(从而做出非改进移动)。****

接受概率计算如下:

接受概率公式|作者图片

  • E 术语指的是性能指标,即 AUC 分数。 E new 是来自在新子集上训练的模型的交叉验证的 AUC 分数,而 E current 基于当前子集。这两项之间的差异给出了模型性能的变化。
  • T 代表迭代 i 时的温度。虽然初始温度( Tₒ )是可调的,但我们可以先将其设置为默认的高(最大)值 1 来启动加热阶段。****
  • 随着算法的进行,温度应该冷却并从初始的 Tₒ 降低。一个流行的策略是几何缩减,在每次迭代后,温度由冷却因子 alpha (α) 缩放。由于 α 的典型范围在 0.95 和 0.99 之间,因此 α 值可以默认设置为 0.95****

几何缩减计划的温度更新公式,其中 alpha 是介于 0 和 1 之间的因子值|图片由作者提供

以下是参数如何影响接受概率:

  • 随着温度降低,接受概率降低。这意味着随机数大于接受概率的可能性更大。这意味着我们更有可能拒绝表现不佳的新子集。

随着温度降低,接受概率降低|图片由作者提供

  • 随着新子集模型性能恶化到更大程度(即E当前与E新之间的差异更大),则接受概率降低。同样,这意味着我们更有可能拒绝表现不佳的新子集。****

随着(E当前 — E 新)的增加,接受概率降低|图片由作者提供****

从高温到低温的受控降低使得差的解决方案在搜索的早期具有更高的被接受的概率,但是稍后更有可能被拒绝。

(三)终止条件

包含终止条件(又名停止标准** ) 也是有帮助的,这样算法就不会不必要地迭代。******

终止条件的一些例子包括:

  • 达到可接受的性能阈值
  • 达到特定的最终温度(例如 T=0.01 )
  • 达到预定数量的连续迭代而性能没有提高

(四)算法伪代码

在线搜索模拟退火将会产生许多代表该算法的令人生畏的伪代码。这里有一个例子:

模拟退火算法的伪代码示例

有了前面几节的解释,不管使用什么符号和缩写,你现在都可以很好地欣赏和理解这些代码。

(5) Python 的实现

理论概念建立后,让我们看看如何将模拟退火付诸实践。

下面是用 Python 实现该算法的代码。你也可以在这里查看完整的 Python 脚本。

上面的函数**train_model**使用三重交叉验证运行随机森林分类器,以获得 AUC 分数。

随意查看 本笔记本 查看完整输出。

在 Titanic 数据集上运行模拟退火函数后,我们获得了如下结果:

我们可以观察到最好的 AUC 得分是 0.867 ,对应迭代 4 ,特征集为【0,1,2,5,8】。当索引被映射到列名时,五个特征是**Pclass****Sex****Age****Fare****Title******

需要注意的是,这种实现假设较高的度量分数与较好的性能相关(例如,AUC、准确性)。然而,如果我们使用像 RMSE 这样的指标,分数越低越好,那么不等式符号需要相应地反转,例如,metric **<** prev_metric而不是metric **>** prev_metric

(6)包装

到目前为止,我们已经介绍了 Python 中用于特征选择的模拟退火的概念和基本实现。

你会很高兴地知道,先进的实现是可用的,使算法更健壮。

一个例子是重启的概念,其中如果在 n 次迭代后没有找到新的最优解,则搜索重置为最后已知的最优解。它的目的是提供一个额外的保护层,防止搜索停留在性能不佳的局部最优解。****

这个项目的 GitHub repo 可以在 这里找到 ,还有的引用。一如既往,期待您对这个话题的反馈!****

在你走之前

欢迎您来到加入我的数据科学学习之旅!点击此 Medium 页面,查看我的 GitHub ,了解更多精彩的数据科学内容。与此同时,运行模拟退火进行特征选择也很有趣!****

****** ******

特性不仅仅是数据科学家的专利

原文:https://towardsdatascience.com/features-are-not-just-for-data-scientists-6319406ac071

特色商店起源故事

照片由 Mikael Blomkvist 拍摄:https://www . pexels . com/photo/simple-workspace-at-home-6476588/

起初

很久以前,在一个很远很远的地方,我是一家财富 50 强公司的数百名数据分析师之一。幸运的是,我在 2014 年被提升为该公司首批数据科学家之一,旁边还有一些拥有博士学位和多年预测建模经验的新员工。我以为我完全超出了我的能力范围。

没过多久,我就发现我的 SQL 知识和业务专长比我意识到的要有价值得多。如果您不知道数据中的所有细微差别,或者不知道如何编写 SQL 来正确避免客户时数据设置的泄漏,那么流失模型是没有用的。因此,我成了团队中一名有价值的成员。其他数据科学家和我有一种共生关系:他们教我预测建模,我为他们编写他们的 SQL。

辉煌的日子

因此,我的 SQL 片段变成了一个脚本,然后我的脚本变成了一个团队项目。作为一个团队,我们开始构建一个主 SQL 脚本,将 20 多个表连接在一起,并计算每个客户在任何给定时间点的信息指标:

  • 自客户更换包装后的天数
  • 在过去 365 天内,客户账单上涨超过 5 美元的次数
  • 客户收入与同一 ZIP 平均收入的比率 3
  • 在过去 5 年里,同一栋房子里不同顾客的数量
  • 产品变化是否算作升级、降级、降级的标志

如果你是一个开始一个新模型的数据科学家,你只需要带来 3 列:客户、日期和目标。主脚本会立刻给你 150 个特性。这大大节省了时间。它允许数据科学家花更多的时间想出新的和 有创意的功能,然后可以添加到主脚本中。作为这个主剧本事实上的“主人”,所有的工作都落到了我的身上。然而,生活是伟大的。每位数据科学家在 6 周内准时部署模型。

成功的痛苦

然后它打电话来了。随着我们的团队发展到 10 名数据科学家,我们对数据库基础设施的影响花费了大量资金。我们积累的主脚本运行起来非常昂贵,每个数据科学家必须为每个模型运行 3 次(训练、OOT1、OOT2)。按照传统的 IT 方式,他们没有帮助我们解决问题。他们只是通过将我们放在一个单独的资源队列中来限制我们的处理能力,在那里我们不得不象征性地在史诗般的笼子里战斗,争夺谁有权首先运行他们的查询。要么这样,要么给他们 300 万美元来扩展系统。那是不会发生的。

替代方案

因此,我们在一个房间里集思广益,我们意识到每月运行相同的查询 70 次是多么多余(这是 10 x 3,加上 40 个用于评分的部署模型)。如果我们每月运行一次这个查询会怎么样?我们不能继续将结果追加到一个大表中,准备好按 CustomerID 和快照日期连接吗?于是,我们的第一家特色店诞生了。然而,那个术语还不存在。

回到辉煌的日子

一切又变得美好了。我们的模型变得越来越好。我们从 150 个功能增加到 400 个。我们甚至将 20%的产能用于重新开发我们已经生产的旧型号——并通过新功能获得更好的结果。一帆风顺……至少我们是这么认为的。

如果你建造了它,他们就会来

有一天,就像其他任何一天一样,我们意识到,如果我们把税收从支付指标中剔除,它会更有预测性。所以我们把税收分成不同的部分继续。

然后,我老板的老板接到市场部 SVP 的电话。谁敢毫无征兆地更改数据?显然,通过口口相传,来自另一个团队的一些分析师已经发现了我们的客户特征宝库。他们用这些数据建立了 Tableau 仪表盘,并定期制作报告。

不知不觉中,我们宝贵的内部表受到了很多限制。营销部门希望为新功能制定一个 3 个月的路线图,以便它们能够产生影响。他们还想要一个健壮的具有血统的数据字典。我们甚至发现运营部门已经开始将我们的表复制到他们自己的数据库中,并基于我们的特性构建他们的特性。依赖性变得令人困惑。仅仅几个月后,我们的灵活建模特性库就陷入了依赖和官僚主义的泥沼。

我当时并没有意识到,但一些重要的事情正在发生。

我是数据科学家,别烦我

我在网上读到,如果你想激怒一个数据科学家,告诉他们记录一切。作为一个数据科学团队,我们的反应没有什么不同。我们的第一反应是占有欲:“这是我们的数据集。让他们自己做吧!这将影响我们建立模型的能力和速度。难道他们没有意识到公司可能会损失数百万美元吗?”此时,我已经被提升为经理,我注意到在功能工程方面完全缺乏创造力。如果添加功能会成为一种负担,那么没有人会添加更多的功能。

不同的视角

我非常感激的另一位经理,我永远不会忘记他,他把我拉到一边,用一种我从未考虑过的新观点启发了我。他向我展示了良好数据的巨大价值。公司内数百名分析师快速获得洞察力的能力远远超过我们模型的影响力。分析师们蜂拥至我们的数据,因为有真正的需求。我们没有与之抗争,而是有机会以一种的方式帮助公司,改变了公司的数据文化。

因此,作为一个跨职能团队,我们联手实施了我在公司中见过的最成功的数据计划。营销部门想出了一个好主意,给这个特色商店起了一个朗朗上口的名字“罗塞塔”它看到了效率和标准化以及专用计算和监控工具的优势。高管们也看到了好处,并自上而下地鼓励他们的分析师使用它。

一年后,我们拥有了两个世界的精华。真正擅长数据处理的分析工程师拥有 ETL 和基础设施。数据科学家拥有逻辑和需求,并最终拥有 16,000 个预先计算好的现成功能。业务单元选择了 400 个特性的子集,并仔细地将它们放在分析师的分析特性存储库中(也称为 Rosetta)。

事实上,数据可以在一个标准化的地方获得,这使该公司进入了一个分析的黄金时代。呼叫中心分析师发现了营销活动在实现他们的 KPI 中发挥巨大作用的细微差别。营销分析师发现了对客户产品使用的大量洞察。金融发现,光纤升级可以针对特定的社区,以减少流失。如果没有功能库,这些团队都不会有专业知识或时间将这些数据集汇集在一起进行分析。

经验教训

后来我离开了那家公司,去了更好的地方,但我一直记得那些教训。在接下来的几年里,我从事咨询工作,在那里我意识到我有这样的经历是多么幸运。最近,我加入了 Rasgo 的一个伟大团队,我们正在积极开发一个免费产品,帮助人们跟随我经历的相同旅程。当我与其他公司的领导会面时,我最常被问到的问题是,你在这一过程中学到了什么?

这是团队的努力

大型组织以各自为政而闻名。他们也因重大的集中化努力以悲惨的失败而闻名。成功的关键是不要完全摇摆不定。我坚信技术、计算资源和“卓越中心”的集中化,但与此同时,我们也必须接受分散分析团队的力量,他们是各自领域的专家。从构建功能商店的角度来看,您需要弄清楚如何让集中式数据工程和分散式分析以协同的方式一起工作。

定义一次

下面是冷酷无情的事实:特性和度量的逻辑需要集中化。如果你点头同意,你可能已经经历了分散分析师不得不重新发明轮子的灾难。如果您不同意,那么您可能经历过同样灾难性的情况,即定义和创建新的度量标准受到集中式工程过程的限制。定义的集中化是关键——但是您必须使用技术和业务流程来创建一个有效的反馈循环,以允许分散的分析师为指标创建过程做出贡献。我所说的“有效的反馈循环”并不是指:(1)投入一张 JIRA 门票,(2)为一项新功能等待 6 个月。如果你今天这样做,你需要重新评估。

高效计算

尽可能在现代数据堆栈中处理。根据我的经验,我们有太多可用的工具,这实际上伤害了我们。数据不断地从仓库转移到 Alteryx、Tableau、SAS、Databricks、hdfs、S3 等等。这大大增加了 IT 成本、基础架构要求和管理复杂性。在扩展之前,将所有主要处理集中到一个地方。只有在特殊情况下,您才需要将数据卸载到不同的基础架构进行处理(例如,流和 IOT 数据)。

随处使用

起初,你可能会注意到一个功能商店出售自己。如果您创建了正确的指标和特性,那么分析师自然会开始使用它们。然而,长期成功的秘诀是避免创建这些指标的孤岛和变体的诱惑。同样,关键是使用技术和业务流程来创建一个高效的反馈回路。您希望分析师能够进行试验,但是您必须提供一种快速而简单的方法来将新的指标推入商店。

入门的战术建议

巩固

你应该先挑一个仓库技术。当您做出此决定时,有许多与 IT 和最终用户相关的问题需要考虑。在大公司中,您可能有合理的理由保留多个数据存储解决方案。尽管如此,我们的目标应该是将尽可能多的数据整合到一个单一的数据仓库中,作为分析的唯一数据源。

过去几年的流行选择是像雪花这样的云解决方案。有时,公司仍然需要辅助系统来使用 spark 进行专门的数据处理,但最终结果是将最终结果存储在云仓库中。这方面的一个很好的例子是 IOT 传感器数据:分布式存储和 spark 是将数据解析成有意义的表格表示所必需的,这些表格表示随后被加载到仓库中。

雇佣优秀的工程师

整个计划背后的驱动力将是您的工程团队。如果我可以从头开始,我会推荐知道骨骼埋藏在哪里的内部雇员,以及可以带来经验和思想多样性的外部专家。

整合计算负载的工作对工程师的影响最大。在分散工作中,我最常看到的一件事是工程师制作一些简单的东西,如“虚拟变量”,并建立一个管道,将数据从雪花通过网络传输到 hdfs,然后通过 spark 加载到内存中。从那里,它运行几行 scala,将数据帧写回 hdfs,然后通过网络将结果加载回 Snowflake。这既昂贵又过于复杂。

如果你组建一个工程英雄团队,他们都会理解将数据处理整合到适当的基础设施上的好处,并一起工作。最后,当你的工程师推荐有助于协调他们疯狂复杂的世界的技术时,一定要听他们的。我注意到最近很流行。那时候它还不存在,但是不管工程师们说什么,相信他们。我们不得不使用一种叫做 UC4 的管道自动化技术,我可以有把握地说没有一个工程师喜欢使用这种技术。

不要煮沸海洋

您应该采用帕累托原则,关注代表您业务核心的关键数据元素。当然,整体的成功取决于用户的采用,所以你可能需要选择能为你赢得一些支持者的数据元素。

在我的例子中,我们的业务主要由订阅收入驱动。因此,与客户相关的订阅数据位于列表的顶部,因为“客户流失”是每个人都关注的指标。然而,营销部门(及其数百名分析师)需要成为测试和采用这一新概念的盟友。因此,我们与他们合作,找出哪些数据源和指标是他们所必需的。事实证明,第三方细分和受众分数至关重要,因此我们将它们作为第一阶段的必备要素。

另一件要记住的事情是,你可以选择从简单开始。例如,当我们构建第一个客户功能商店时,我们添加的一个元素是一个 source,它让我们知道客户在之前的 30 天、60 天和 90 天打了多少电话。还有一些更复杂的元素需要更多的工程设计——比如它们排在哪个队列中?通话持续了多长时间?他们等待了多长时间?我们知道我们最终需要这些数据元素,但是我们从简单的东西开始。

建造所有的管道

根据您的公司和现有的基础设施,这可能从相对简单到极其复杂。在我的例子中,工程师需要从大约 25 个不同的来源构建许多提取-加载管道,这样就可以从数据仓库中访问它们。

这也是一个关键的技术决策,应该与选择仓库的决策齐头并进。Airbyte、Fivetran、Integrate 和 Segment 是一些现代的例子,它们是 Pentaho、SSIS 或 Talend 等更传统解决方案的云原生替代方案。

定义一次

成功的关键之一是为您的度量和特性找到合适的定义。这比看起来更难。例如,流失率可能听起来很简单,但是那些不支付账单并因此自动断开连接的客户怎么办?你应该把这些算作客户流失吗?那些因为死亡而断开连接的客户呢?或者搬到你公司不服务的区域?也许你真正需要的是一个自愿流失指标和一个非自愿流失指标合并成一个总流失指标。

这里的要点是企业需要参与进来。显然,工程师拥有幕后的管道和处理代码,但是您需要一种方法让分析师来指导这个过程。

使民主化

最后一步是在任何地方使用这些数据。有时候,用户会自己涌向数据,因为数据本身就说明了一切。其他时候,你将不得不付出巨大的努力去追踪那些需要转变的报告、系统和遗留的“习惯”。此外,追踪和迁移遗留流程的工作无疑会发现您不知道的额外需求。所以,用一些问题来挑战自己,比如,为什么提交给董事会的季度总结不能建立在新数据的基础上?

像这样的项目最终失败的最大原因是因为公司输掉了民主化的战斗。我见过几次,由于之前所有步骤的沉没成本,它总是一场灾难。有时是因为对计算缺乏信任(见上文定义一次)。有时是由于糟糕的技术决策导致了技能差距(参见上文的整合)。

失败的另一个重要原因是缺乏反馈回路。不幸的是,这需要一段时间才能显现出来,所以最初成功的项目可能会在几个月后失败。事实是,业务总是在移动和变化,因此需要一个灵活的流程来控制未来的增强和发展。

例如,当我们推出我们的第一个功能商店时,该公司只销售了 3 条业务线。拥有所有 3 种功能的客户被确定为“三网合一”客户。不久,我们推出了第四个业务系列。于是,“四合一”的客户就诞生了。然而,度量定义需要仔细考虑是否需要更新,并且必须创建新的度量。如果你没有一个有效的反馈回路,新产品团队中的分析师将会出于必要开始报告他们自己的流失率。其他业务线可能希望开始排除和例外,因此他们将开始构建新指标的孤岛。这就是技术和业务流程需要让分析师更容易参与度量定义过程的地方。

结论

作为一名年轻的数据科学家,在这个术语普及之前开发一个功能商店是令人兴奋的。然而,我目光短浅,不知道这个概念对于企业级转变为数据驱动的文化有多重要。我非常感谢那些有远见的人,让我能够和他们一起工作,参与这样的旅程。我希望分享我的故事对那些正在经历类似旅程的人有所帮助和鼓励。想聊天随时伸手;你通常可以在空闲时找到我。我在本地乐观数据会谈中特别活跃。俱乐部,你可以随时在拉斯戈直接 ping 我。

二月版:关注数据可视化

原文:https://towardsdatascience.com/february-edition-all-eyes-on-data-visualization-d38964d57603

提高你的视觉化技能,你就能讲更好的故事,做出更好的决定。

照片由 Faizan SaeedUnsplash 上拍摄

“数据讲故事”对不同的人意味着不同的东西;数据科学家分享他们的发现、预测和见解的方式会因环境的不同而有很大差异。如果所有有效的数据故事都有一个共同点,那就是好的视觉效果。也许是我们大脑的连线方式,或者是我们不愿意阅读 100 页的报告;也许图表和情节只是天生…好玩?

无论哪种方式,经验丰富的数据从业者不断得出相同的结论:如果你的同事和利益相关者不明白它为什么重要,那么使用最前沿算法的最花哨的 ML 模型也不会有多大用处。通常,帮助他们看到光明的最快方法是制作精美的图片。因此,这个月,我们收集了一些关于数据可视化的策略和实践的最佳文章。

正如你们可能已经知道的,这是一个巨大的话题——总有更多的东西需要学习和探索。所以把这个广泛的选择作为一个起点,一个更长旅程的起点。如果你读过(或写过!)如果您想与我们的社区分享另一篇关于数据可视化的帖子,请发表评论!

掌握数据可视化的简单而有效的 5 步框架

这是一个很好的起点,使用一个示例对所提议的框架进行了彻底的分解,并包含了多个屏幕截图。

Anushiya the vaplan(6 分钟)

数据可视化技术背后的心理学

对人类视觉信息处理世界的短暂探索。

伊莲娜·V·卡扎科娃 (13 分钟)

Viz for Social Good Community—使用 Python 进行分析& Tableau

了解面向社会公益志愿者的 Viz,为你的下一次可视化获得有用的提示,并了解如何参与其中。

帕亚尔·帕特尔 (7 分钟)

可视化顶级 Python 库:入门指南

Python 中散点图、热图、脊线图和线图绘制指南。

迈克尔扎布洛基 (8 分钟)

你使用数据可视化工具错误的迹象

如今有强大的可视化工具可供数据科学家使用,但你需要确保充分利用它们。

泰莎谢 (6 分钟)

误导图

概述了好看的可视化仍然会将我们引入歧途的方式,以及我们如何能够并且应该修复它们。

马腾·格罗登斯特 (6 分钟)

用 Pybaobabdt 可视化决策树

一个用于决策树可视化和模型解释的开源包。

帕鲁尔·潘迪(7 分钟)

如何用 Python 从地理空间数据创建地图

使用 Folium 将印度尼西亚火山的位置数据绘制成地图。

莉娅·里斯蒂安娜 (5 分钟)

如何轻松绘制神经网络架构图

使用无代码 diagrams.net 工具通过图表可视化展示您的深度学习模型。

梁建华 (5 分钟)

如何使用 LaTeX 创建发布就绪的地块

使用 LaTeX 启动你的绘图之旅,使用 5 种基本的绘图变化。

阿鲁纳·皮沙洛迪 (18 分钟)

用 Python 制作精美的地形图

当您可以用 Python 构建引人注目的 3D 地形图时,谁还需要 GIS 呢?

亚当·赛明顿 (8 分钟)

奖励精选如果你想给你的可视化效果注入更多的乐趣:

我们希望您喜欢我们这个月的选择——如果您渴望更多,请务必浏览我们的数据可视化页面,在那里您将找到我们在该主题上的最新贡献。

在我们结束之前,请和我们一起欢迎过去一个月在 TDS 上发表了第一篇文章的出色的新作者——他们包括马特奥·萨弗恩米拉·夏尔马哈齐布·卡迈勒克里斯托弗·格林阿卡什卡德尔洛克·雷根特尼科·范·登·胡夫苏尼塔商城https://medium.com/u/74f95879b66?source=post_page-----d38964d57603-------------------------------- 科斯塔斯·斯科拉基斯尼古拉斯·雅克卡德克里斯托弗·阿里扎雅各布·h·马尔克斯谭念威纳齐娅·沙赫林查克·康奈尔扎因·艾哈迈德弗朗西斯科·桑托斯里维克·奎拉 托马斯·里亚兰阿琼·巴拉苏布拉曼尼安查理·奥尼尔苏埃拉·伊萨伊陈伶俐·金凯·简·王霍莉·达利根安德里亚·古斯塔夫森拉杰什·西格德尔https://medium.com/u/ee6653ed5c61?source=post_page-----d38964d57603-------------------------------- 克里斯·休斯格里·克里斯蒂安·翁科弗朗切斯科·马里尼贾伦·R·哈伯莉亚·里斯蒂安娜凯瑟琳·拉拉塔梅尔·特韦托格鲁梅贝尔·冈萨雷斯·卡斯特利亚诺斯保·吉罗 如果你也想和我们分享你的作品,你可以!

神经网络如何工作—实例(神经网络系列)—第 2 部分

原文:https://towardsdatascience.com/feed-forward-neural-network-with-example-neural-network-series-part-2-eeca7a081ef5

本文将构建到本系列的前一部分。我们将涵盖前馈神经网络(FF-NN),集中讨论神经网络所做的计算。

本系列的前一部分:神经网络的基础知识(神经网络系列)——第一部分

神经网络设计(概述)

神经网络是由许多层叠的神经元组成的系统。第一层,输入层(我们称之为第 0 层)除了传递输入值之外不执行任何计算。因此,在计算神经网络的层数时,我们忽略输入层。因此,下面的图 1 是一个两层网络。

输出层计算网络的最终输出。输入层和输出层之间的层称为隐藏层。下面图 1 中的神经网络被描述为 3–4–1 网络,输入层有 3 个单元,输入层有 4 个单元,输出值为 1。

神经网络的层数决定了网络的深度。基于此,具有多个隐含层的神经网络被称为深度神经网络。

通过层数和每层中神经元的数量来解释神经网络的设计,通常被称为神经网络的架构。我们在本系列中交替使用这些术语(神经网络设计和神经网络架构)。

图 1:一个有 3 个输入特征的神经网络,一个有 4 个节点的隐藏层,一个单值输出。节点是密集连接的——每个节点都连接到上一层的所有神经元。每个连接都有权重,表示任意两个节点之间的连接强度(来源:作者)。

前馈神经网络

前馈网络,也称为前向传递,逼近某个函数
y=f( x |θ)的输入值 x 和已知输出 y。网络学习θ中最逼近函数 f 的参数,以建立良好的映射ŷ=f( x |θ)。ŷ是一个预测的模型。在 NN 中, wb∈θ——也就是我们在模型训练时优化的参数是 2 个权重( w )和偏差( b )。

前馈神经网络的关键特征 —前馈网络只允许信息单向流动(无反馈回路或连接)。

定义:多层感知器(MLP) MLP 是前馈 NN 的特例。在 MLP 中,所有节点都是密集连接的,也就是说,每个神经元/节点都连接到上一层的所有节点。事实上,图 1 中的神经网络是一个多层感知器。

前馈神经网络(FF-NN)-示例

本节将展示如何执行由 FF-NN 完成的计算。本节要掌握的基本概念是描述不同参数和变量的符号,以及实际计算是如何进行的。我们将使用图 1 所示的神经网络结构。

1.建筑和符号

让我们重新绘制图 1,以显示神经网络的基本变量和参数。注意,在这个图中(下面的图 2),节点之间的其他连接被删除了,只是为了使图不那么混乱;否则,这个神经网络是一个多层感知器(任何两个相邻层中的所有节点都是互连的)。

图 2:带有变量和参数的 3–4–1 神经网络我们需要在给定输入值的情况下计算输出ŷ(来源:作者)。

其中:

  • x⁰ᵢ-iᵗʰ输入值。输入层(层 0)的特征 I 的值,
  • wˡⱼᵢ —权重来自第 l-1 层的神经元 I 到当前第 l 层的神经元 j,
  • fˡⱼ —层 l 中单元 j 的输出。这成为下一层(层 l+1)中单元的输入,
  • 第一层中 jᵗʰ神经元的 zˡⱼ加权输入,
  • bˡⱼ——l 层 jᵗʰ神经元上的偏置,
  • nˡ——第一层神经元的数量,
  • f ˡ
  • l —给定的层。对于,l =0,1,…,L。在我们的例子中,神经网络为 2 层,因此 L=2(记得我们说过不计算输入层)

以下是一些解释参数和变量的示例:

  • x⁰₂ —第二个输入值,
  • w₄₃——从第 0 层中的神经元 3 到第 1 层中的神经元 4 的连接的权重,
  • z ₃ —第 1 层中单元 3 的加权输入,
  • g(z₃)-在 z ₃.上应用激活函数 g
  • 每层中的单元数-输入层为 3 个单元(n⁰=3),隐藏层有 4 个单元(n =4),最后一层为一个神经元(n =1),以及
  • b .₁——第 2 层(本例中为输出层)中神经元 1 的偏置。

2.数据

我们将在本例中使用的数据包含 3 个特征 G1、G2 和 G2 (顺便说一下,这就是我们在架构的输入层选择 3 个神经元的原因)目标为通过(我们称之为y),分别为 0 或 1,表示失败和通过。这意味着我们正在处理一个二元分类问题。

原始数据包含 30 个特征和 395 行(数据点),但是我们将只使用 3 个特征来有效地显示必要的计算。我们将在本系列的后面处理整个数据集。

同样,为了使概念易于理解,我们将展示如何在单次正向传递中通过网络传递单个数据点(训练示例)。

在我们的示例中,我们将考虑索引 2 处的训练示例(来源:作者)。

3.参数初始化

我们将用 0 到 1 之间的值随机初始化权重,而 bias 将总是用 0 初始化。我们将在后面的系列文章中对此进行更多的讨论,请记住,权重最好初始化为 0–1,而不是零,偏差最好在开始时保持为 0。

4.隐含层神经元的计算

对于隐藏层中的第一个神经元,我们需要计算 f ₁,这意味着我们需要三个权重 w ₁₁、w ₁₂和 w ₁₃.的初始值

让我们初始化他们如下 w ₁₁=0.3,w ₁₂=0.8 和 w ₁₃=0.62.如前所述,我们将设置偏差,b ₁=0.让我们引入一个称为整流线性单位(ReLU)的激活函数,我们将使用它作为函数 g(这只是一个任意的选择)。如前所述,我们将在后面讨论更多关于激活函数的内容,但是现在,我们可以定义 ReLU 并使用它。

ReLU 激活功能。

因此,

对层=1 的第一个神经元的计算。

你可以用同样的方法计算 f ₂,f ₃和 f ₄,假设

  • w·₂₁=0.9,w·₂₂=0.1,w·₂₃=0.1 和 b·₂=0,计算 f·₂,
  • w·₃₁=0.7、w·₃₂=0.2、w·₃₃=0.4 和 b·₃=0,用于 f·₃的计算,
  • w·₄₁=0.01,w·₄₂=0.5,w·₄₃=0.2 和 b·₄=0,计算 f·₄.

确认₂=8.1,₃=10.5 和₄=6.07.

5.最后一层的计算

在最后一层,让我们初始化参数(权重)和偏差:w ₁₁=0.58,w ₁₂=0.1,w ₁₃=0.1,w ₁₄=0.42,和 b ₁=0.

关于该层中的激活函数-由于我们正在处理二元分类,我们可以使用 sigmoid/logistic 函数,因为该函数输出 0 到 1 之间的值,因此可以解释为类的预测概率。Sigmoid 函数定义为:

Sigmoid 函数

因此,

网络最后一层的计算。

由于最后一层的输出是由 Sigmoid 生成的(范围从 0 到 1),所以结果可以解释为一个概率。y ₀=0.999997502 意味着通过的可能性几乎是 1。从数据来看,真值为 1,意味着正向传递使预测正确。然而,这不仅仅是一个巧合,因为没有训练。权重是随机生成的,所有偏差值都设置为 0。

我希望这篇文章为理解神经网络中发生的计算打下良好的基础。这是对系列文章上一篇文章的补充。本系列的下一篇文章在这里

以每月 5 美元的价格注册 medium 会员资格,以便能够阅读我和其他作者在 medium 上的所有文章。

你也可以订阅,以便在我发表文章时将我的文章发送到你的邮箱

感谢您的阅读,欢迎下次光临!!!

机器学习系统中的反馈回路

原文:https://towardsdatascience.com/feedback-loops-in-machine-learning-systems-701296c91787

在机器学习系统设计中设计反馈回路

Unsplash 上由Tine ivani拍摄的照片

介绍

在机器学习系统中,我们经常从模型的环境中接收某种反馈,然后反馈到系统中。这可以采取多种形式,例如使用模型的输出来训练模型的新版本,或者使用用户对模型决策的反馈来改进模型。

虽然许多反馈循环是有用的,并且随着时间的推移会提高模型的性能,但随着时间的推移,一些反馈循环会严重降低机器学习系统的性能。设计有用的反馈回路是机器学习系统设计的重要组成部分,需要深思熟虑地完成,以确保您的系统是可持续的。

在这篇文章中,我将回顾有益的和有害的反馈循环的例子,并解释为什么每种类型都会有这样的结果。

有用的反馈循环

一个有益的反馈循环通常涉及将不带偏见的外部信息引入你的机器学习系统。这通常以通过与机器学习模型的输出不强烈相关的来源获得标签的形式出现。

这些反馈机制允许系统获得关于系统当前行为的非自我强化的信息。这确保了随着时间的推移,模型不会由于在不反映真实数据分布的有偏数据上重新训练而退化。

在许多情况下,这些外部数据提供了关于模型何时正确、何时错误的反馈。这通常通过隐式或显式地允许用户以结构化的方式纠正系统的错误来实现。

用户报告

在用户生成内容的平台上,通常有用户报告内容为无关内容、垃圾邮件或攻击性内容的功能。这允许最终用户向机器学习排名和内容审核系统提供关于算法发送给他们的内容片段的反馈。

贾斯汀·摩根在 Unsplash 上拍摄的照片

这方面的一个例子是,Gmail 允许你将收件箱中的邮件报告为垃圾邮件。如果邮件进入了你的收件箱,而不是垃圾邮件文件夹,那么这意味着谷歌的垃圾邮件分类系统不认为这是垃圾邮件。通过自己举报该邮件为垃圾邮件,您向 Google 提供了有价值的反馈,表明该邮件是误报。下一次他们的模型被重新训练时,它现在可以考虑这个反馈,并希望在未来对这种类型的垃圾邮件表现得更好。

用户交互日志

在任何涉及内容排名或购物的平台上,通常都有某种形式的内容排名系统来决定哪些项目最符合用户的搜索查询或历史参与度。然而,在许多情况下,算法的建议并不完美,用户可能会选择使用未被推荐的项目,或者使用排名较低的项目而不是排名较高的项目。

照片由马克斯·托马斯Unsplash 上拍摄

来自这些用户交互的日志为排名系统提供了用户真正感兴趣的基本事实。当用户与算法排名不高的东西进行交互时,它会为系统的下一次重新训练提供有价值的反馈。此外,平台拥有的用户交互数据越多,它就越能够针对用户的特定兴趣和特定需求建立档案。

有害的反馈循环

机器学习系统中有害的反馈回路通常通过消除无偏数据的存在来阻止系统随着时间的推移而改进

当用于训练模型的数据仅由先前模型的输出确定时,系统无法随着时间的推移而改进。事实上,随着时间的推移,这种情况最有可能导致系统性能下降,因为它将继续根据越来越偏向其自身输出的数据进行训练。

在这种情况下,系统根本无法纠正其错误。随着时间的推移,这些误差累积起来,对系统性能的影响越来越大,随着模型被重新训练,其性能逐渐降低。

干预

在许多机器学习系统中,模型会触发某种类型的干预,从而改变用户体验。当干预被触发时,一些用户如果无法或不愿意绕过干预,自然会掉线。随着时间的推移,这些用户的减少可能会显著改变标记数据的数据分布。

例如,在欺诈检测系统中,具有高风险分值的用户可能需要完成额外的验证。如果验证是有效的,并导致欺诈用户在没有解决它的情况下放弃,那么这些用户将永远不会有机会实际实施欺诈并被贴上欺诈标签。

这个来自 Stripe 的视频解释了他们是如何处理这种类型的反馈回路的。他们采用了抵制小组方法,并能够解除他们的机器学习训练和评估数据的偏见。

如果不明确处理这一点,模型的未来训练数据将会有偏差,并且将只包括关于欺诈用户的积极标记的数据点,这些欺诈用户要么 1)解决了验证挑战,要么 2)低于模型的阈值并且从未被挑战。随着时间的推移,这将逐渐使模型的训练数据偏向更“困难”的欺诈,因为“容易”的欺诈会被干预阻止。它还减少了训练数据中(已经很少的)正面例子的数量,因为现有的系统可能会阻止大多数欺诈的发生。

解决方案:我们可以通过使用不受干预的小型(例如 1%的流量)维持组来解决这个问题。在抵制小组中,我们不进行干预,让所有用户在没有挑战的情况下通过,即使他们有风险。然后我们可以看到当我们不需要任何验证时会发生什么;一些用户会真的实施欺诈,而另一些则不会。这个小群体为我们提供了用于训练和测量的无偏数据,而不会因为其规模小而对业务造成重大损害。

位置偏差

搜索排名系统通常使用用户交互日志来创建带标签的训练数据。在二元分类框架下,如果用户决定与某样东西互动,那么这个标签就是正面的,如果不是,这个标签就是负面的。

这种标记方法会导致偏差,因为与其他内容相比,先前模型排名较高的项目更有可能被交互,即使排名较高的项目实际上并不相关。如果不进行偏差调整,这将导致模型在很大程度上只是记住它过去的决策逻辑(以及它过去的错误),而不是了解用户的真实口味。

Christian Wiediger 在 Unsplash 上拍摄的照片

解决方案:这个问题可以通过修改模型来解决。有几种方法可以模拟位置偏差的影响,然后在推理时消除这种影响。例如,推荐接下来看什么视频:多任务排名系统的文章解释了谷歌是如何为 YouTube 实现这一点的。通过学习对位置的影响进行建模,这些方法可以在推断时传入空值或静态值,以向模型发出信号,表明所有内容都具有相同的位置因素,而是应该基于内容本身进行排序。

谷歌论文作者的这段视频对论文进行了更详细的描述,描述了 YouTube 的整体内容推荐系统。

结论

反馈回路是现实世界机器学习系统的关键元素。它们使模型能够改进我们的时间,并帮助收集关于模型哪里出错的反馈。在大多数情况下,这种改进需要您的系统的反馈循环包括获得不纯粹由模型本身产生的无偏数据。

希望本文能让您更好地了解什么样的反馈循环会帮助或损害系统的性能。在任何行业中,设计反馈回路都是机器学习系统设计的重要组成部分,因此这篇文章中的知识应该适用于各种各样的环境。

如果你对更广泛地学习机器学习系统设计感兴趣,斯坦福有一门很棒的课程,它涵盖了构建和部署机器学习系统的许多方面。

费曼的餐馆问题

原文:https://towardsdatascience.com/feynmans-restaurant-problem-57121af0bb92

从 RecSys 的角度介绍和解决费曼的餐馆问题

照片由 shawnangggUnsplash 上拍摄

你在度假,接下来的几天你将在太平洋的一个偏远岛屿上度过。这里有几家餐馆,你会喜欢品尝最地道的菜肴。你面临的问题是,先验的你不知道哪些餐厅是你要去享受的,哪些不是,你也找不到 Yelp 上的餐厅,所以你不能用别人的意见来决定去哪些餐厅。还有,餐馆的数量比你要在岛上呆的天数还多,所以你不可能试遍所有的餐馆,找到最好的一家。然而,由于你热爱数学,你决定寻找最佳策略来优化你的假期体验。这就是所谓的费曼餐厅问题

同样的问题可以从餐厅的角度来解释,厨师想向客户推荐菜肴,但他们不知道客户会喜欢或不喜欢哪些菜肴。所以这个问题属于推荐系统的范畴。更一般地说,这是从一组评价未知的 N 个项目中推荐 M 个项目(有重复)的问题。

这篇文章的内容很大程度上受到了这个解决方案的启发。我试图解释一些对我来说晦涩难懂的细节,我还添加了一些情节和代码,让我对这个问题有更多的直觉。在这里你可以阅读更多关于这个问题的历史。

数学公式

让我们试着用数学来形式化这个问题。首先,让我们定义 D 为你要在这个城市待的天数,定义 N 为餐馆的数量。让我们假设你可以根据你的口味对所有的餐馆进行排名,让我们称 r_i 对餐馆 i 的排名。让我们假设你可以每天去同一家餐馆而不感到厌倦,这意味着如果你知道这个城市最好的餐馆,你会一直去那里。

请注意,因为你不能尝试这个城市的所有餐馆,所以你永远不会知道你是否去过最好的餐馆。

注意,你永远不会知道实际的评级 ri。你只有在那一刻才知道一家餐厅是不是最好的。你可以对某个时刻你尝试过的餐馆进行排名,但是这个“部分”排名可能和“绝对”排名不一样。例如,如果你只尝试了 10 家餐馆中的 4 家,你可以得到排名 *[3, 2, 1, 4, ?, ?, ?, ?, ?, ?]* ,但实际排名可能是 *[5, 4, 3, 6, 1, 2, 7, 8, 9]*

您想要优化的函数是

其中 r_i 是您在 i 日去过的餐厅评分。

解决办法

分析的

你在这个城市的每一天都有两种选择:(1)尝试一家新餐馆,或者(2)去你之前去过的最好的餐馆。我们可以把这个问题想成一个探索-开发问题,也就是说,你在第一个 M 天探索这个城市,之后,在接下来的D M个晚上,你总是去那个时刻最好的地方。

因此,我们可以将函数拆分为

其中 b_M,N 是你在第 M 天尝试过的最好餐厅的排名。

我们方程中唯一的自由参数是 M ,所以你要求期望利润最大化的 M 的值。这是

对于第一项,应用线性并知道 < r_i > = (N+1)/2 我们得到

现在我们需要计算 ⟨b_M,N⟩ ,它是 m 从区间 (1,N) 中抽取后得到的期望最大值。

一方面,我们知道如果你只尝试一家餐馆,期望的排名是 ⟨b_1,N⟩ = (N+1) / 2。另一方面,如果你尝试了所有的餐馆,期望的最高排名当然是 ⟨b_N,N⟩ = N.

我们还可以计算出 ⟨b_2,N⟩ 在这种情况下,只存在 1 对餐厅,其中 2 是最大值,即您选择餐厅 (1,2)。最多只有 2 对餐厅,即 (1,3)(2,3) 。只有 3 对餐厅,其中最大值为 4,即 (1,4)(2,4)(3,4) 。诸如此类。总共有N(n1)/2个可能的对。因此

现在考虑 ⟨b_N−1,N⟩ 。这是,你尝试了城市里所有的餐馆,除了一家。在这种情况下,你会在n1种情况下参观最好的餐馆,只有一种情况下你会跳过最好的餐馆。因此,预期值为

从所有这些结果中,人们可以看出模式并猜测

把这些放在一起,我们终于有了

其最大值在

注意,结果不依赖于 n。这意味着你不关心城市里有多少不同的餐馆,这听起来——至少对我来说——有点违反直觉。

还要注意的是,如果你想在不降低预期利润的情况下尝试这个城市的所有餐馆,你需要在这个城市呆 D≥(N+1)^2/2−1 天。因此,如果这个城市有 10 家餐馆,你需要在这个城市呆至少 60 天:头 10 天探索这个城市,在接下来的 50 天去最好的餐馆。 请不要用这些结果来计划你接下来的假期。

数字的

在上一节中,我们导出了问题的解析解。现在让我们运行一些模拟来获得关于这个问题的更多直觉。尤其令人惊讶的是,解决方案并不依赖于 N 。所以让我们看看模拟是否支持这种说法。

使用下面的代码片段,可以通过一组参数模拟预期利润 ⟨F⟩

**import** numpy **as** np

**def** **expected_profit**(n_days: int, n_restaurants: int, n_experiments**=**10000):
    """
    Computes the average profit at each 
    possible m \in range(1, n_days) over n_experiments.

    :param n_days: number of times one can visit the restaurant.
    :param n_restaurants: number of restaurants in the city.
    :param n_experiments: number of experiments to perform.
    """

    results **=** {}

    **for** m **in** range(1, n_days **+** 1):
        results[m] **=** []
        **for** i **in** range(n_experiments):
            ranks **=** x **=** list(range(n_restaurants))
            np.random.shuffle(ranks)
            profit **=** sum(ranks[:m]) **+** (n_days **-** m) ***** max(ranks[:m])
            results[m].append(profit)
    results **=** {k: np.mean(v) **for** k, v **in** results.items()}
    **return** results

使用这个片段,我们生成了下面的图,使用了 N=(100,110,120)D=10 。注意三条曲线的最大值是如何重合的,这支持了违反直觉的分析结果。

预期利润与勘探天数。原著

结论

在本帖中,我们探讨了费曼的餐馆问题。首先,我们导出了最优探索策略的解析解,然后我们用一些模拟来检验解析结果。尽管这些结果从数学的角度来看是有意义的,但没有一个头脑正常的人会遵循最优策略。这很可能是由我们做出的不切实际的假设造成的,即:你不可能一生中每天都去同一家餐厅而不感到厌倦。一个可能的解决方案是改变一家餐馆的评级,使之与你去过的次数挂钩,即 T21。然而,这超出了本文的范围,我们不打算这样做,但也许它可以作为另一篇文章的灵感。

这个故事最初贴在这里

2022 年世界杯:数据驱动的理想球队阵容

原文:https://towardsdatascience.com/fifa-world-cup-2022-a-data-driven-approach-to-ideal-team-line-ups-f4c555dcd7a3

使用 Python 为 2022 年世界杯的每个国家队找到梦之队、最佳阵型和理想的首发 XI

图片来自 Shutterstock,授权给 Frank Andrade

2022 年世界杯已经开始,我们可以从这场比赛的数据中获得许多见解。

像 2022 年世界杯梦之队,每个国家队的最佳 26 人阵容,以及他们理想的首发 XI 都可以使用 Python 获得。

但我们不仅会这么做!我们还将添加一些数据可视化,使这种分析更容易理解,甚至使用 Python 绘制一个具有理想阵容的足球场的图形。

**Table of Contents**
1\. [Dataset Overview](#8ac5)
2\. [Adjusting the Dataset FIFA 22 to the World Cup 2022](#a57d)
3\. [The Metric To Use for This Analysis](#409f)
4\. [Dream Team World Cup 2022](#92e8)
5\. [The Players with The Highest Rating on each National Team](#0017)
6\. [The Best 26-Man Squad for each National Team](#4e34)
7\. [Best Starting XI and Formation](#0c8f)
 - [Spain: Best Starting XI (4–2–3–1)](#0690)
 - [Portugal: Best Starting XI (4–2–3–1)](#12f5)
 - [England: Best Starting XI (4–4–2)](#7575)
 - [Brazil: Best Starting XI (4–3–3)](#d734)
 - [France: Best Starting XI (4–2–3–1)](#c481)
 - [Argentina: Best Starting XI (4–3–3)](#90d6)
 - [Germany: Best Starting XI (4–2–3–1)](#9c3c)

数据集概述

我们将用于此分析的数据来自游戏 FIFA 22,其中包含了世界上大多数足球运动员的信息。你可以点击下载这个数据集

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
sns.set_style('darkgrid')

df = pd.read_csv('players_22.csv', low_memory=False)

这个数据集包含 100 多列,但是对于这个分析,我们只使用其中的几列。

df = df[['short_name', 'age', 'nationality_name', 'overall', 'potential',
         'club_name', 'value_eur', 'wage_eur', 'player_positions']]

需要记住的是,player_positions列有多个位置,因此我们应该只选择一个位置进行分析。此外,我们必须丢弃 NaN 数据。

# selecting only one position
df['player_positions'] = df['player_positions'].str.split(',', expand=True)[0]

# dropping nan
df.dropna(inplace=True)

这里是df数据帧此时的样子。

根据 2022 年世界杯调整数据集 FIFA 22

现在,我们将调整数据集 FIFA 22 以适应 2022 年世界杯。这意味着我们将只考虑那些有资格参赛的国家,以及那些被召入国家队的球员。

# dropping injured players
players_missing_worldcup = ['K. Benzema', 'S. Mané', 'S. Agüero', 'Sergio Ramos', 'P. Pogba',
                            'M. Reus', 'Diogo Jota', 'A. Harit', 'N. Kanté', 'G. Lo Celso', 'Piqué']

drop_index = df[df['short_name'].isin(players_missing_worldcup)].index
df.drop(drop_index, axis=0, inplace=True)

# filtering only national teams in the world cup
teams_worldcup = [
    'Qatar', 'Brazil', 'Belgium', 'France', 'Argentina', 'England', 'Spain', 'Portugal',
    'Mexico', 'Netherlands', 'Denmark', 'Germany', 'Uruguay', 'Switzerland', 'United States', 'Croatia',
    'Senegal', 'Iran', 'Japan', 'Morocco', 'Serbia', 'Poland', 'South Korea', 'Tunisia',
    'Cameroon', 'Canada', 'Ecuador', 'Saudi Arabia', 'Ghana', 'Wales', 'Costa Rica', 'Australia'
]

df = df[df['nationality_name'].isin(teams_worldcup)]

用于此分析的指标

在这个分析中,我们将使用国际足联对每个球员的评分。评级由overall列表示。

让我们按overall对数据帧进行排序(如果多个玩家评分相同,我们也将按potentialvalue_eur列进行排序)

df.sort_values(by=['overall', 'potential', 'value_eur'], ascending=False, inplace=True)

这是数据帧现在的样子。

现在,让我们来看看 2022 年世界杯所有球员之间的收视率(又名整体)是如何分布的。

import numpy as np
fig, ax = plt.subplots(figsize=(12, 5), tight_layout=True)

sns.histplot(df, x='overall', binwidth=1)

bins = np.arange(df['overall'].min(), df['overall'].max(), 1)
plt.xticks(bins)
plt.show()

作者图片

似乎大多数玩家都有 65 和 67 的评分。对于我们的梦之队,我们将只考虑每个位置得分最高的球员。

2022 年世界杯梦之队

获得梦之队的一个简单方法是删除player_positions栏中的所有重复项(T7 是按整体排序的,因此“非重复项”将是那些评分最高的玩家)

df.drop_duplicates('player_positions')

如果我们只选择列short_nameoverallclub_nameplayer_positions,我们会得到下面的数据帧,它代表我们的梦之队。

现在我们有了每个位置的最佳球员,我们可以使用这个 Python 工具来制作足球场的图形,并选择我们想要的任何球员(您只需要编辑脚本底部的球员姓名)

这是我的梦之队。

来源:小饰品

每个国家队中得分最高的运动员

现在让我们创建一个数据框架df_best_players,展示每个国家队的最佳球员。我们将提取nationality_name列的前 3 个字母,以了解每个玩家来自哪里。

df_best_players = df.copy()
df_best_players = df_best_players.drop_duplicates('nationality_name').reset_index(drop=True)
country_short =  df_best_players['nationality_name'].str.extract('(^\w{3})', expand=False).str.upper()
df_best_players['name_nationality'] = df_best_players['short_name'] +' (' + country_short + ')'

让我们制作一个柱状图来可视化df_best_players数据框架。

fig, ax = plt.subplots(figsize=(10, 6), tight_layout=True)

sns.barplot(df_best_players, x='overall', y='name_nationality',
            palette=sns.color_palette('pastel'), width=0.5)
plt.show()

作者图片

每个国家队的最佳 26 人阵容

让我们创建一个函数,返回每个国家队的最佳阵容。为此,我们将为每个国家队的每个位置挑选最好的 2 名球员。一旦我们有了最佳阵容,我们将按player_positionsoverallpotential排序。

def best_squad(nationality):
    df_best_squad = df.copy()
    df_best_squad = df_best_squad.groupby(['nationality_name', 'player_positions']).head(2)
    df_best_squad = df_best_squad[df_best_squad['nationality_name']==nationality].sort_values(['player_positions', 'overall', 'potential'], ascending=False)
    return df_best_squad

让我们来看看什么是最适合巴西的球队

best_squad('Brazil')

正如你所看到的,我们得到了超过 26 名球员,因为我们每个位置选择 2 名球员,大约有 15 个位置。你可以做一些调整,从这个数据框中只选择 26 名球员。

现在让我们看看每个国家队的平均得分是多少。然后我们按average_overall降序排序。

average_overall = [best_squad(team)['overall'].mean() for team in teams_worldcup]

df_average_overall = pd.DataFrame({'Teams': teams_worldcup, 'AVG_Overall': average_overall})
df_average_overall = df_average_overall.dropna()
df_average_overall = df_average_overall.sort_values('AVG_Overall', ascending=False)
df_average_overall

以下是总体平均得分最高的 10 支国家队。

让我们用柱状图来想象一下。

fig, ax = plt.subplots(figsize=(12, 5), tight_layout=True)

sns.barplot(df_average_overall[:10], x='Teams', y='AVG_Overall',
            palette=sns.color_palette('pastel'))
plt.show()

作者图片

最佳首发 XI 和阵型

现在我们有了每个国家队最好的 26 人阵容,我们可以看看什么是最好的首发 XI 和阵型。

这是我想出来的所有形式(如果你愿意,你可以添加更多)

dict_formation = {
    '4-3-3': ['GK', 'RB', 'CB', 'CB', 'LB', 'CDM', 'CM', 'CAM', 'RW', 'ST', 'LW'],
    '4-4-2': ['GK', 'RB', 'CB', 'CB', 'LB', 'RM', 'CM', 'CM', 'LM', 'ST', 'ST'],
    '4-2-3-1': ['GK', 'RB', 'CB', 'CB', 'LB', 'CDM', 'CDM', 'CAM', 'CAM', 'CAM', 'ST'],
}

现在我们创建一个best_lineup函数,根据我们想要的阵型返回最佳起始 XI。

def best_lineup(nationality, lineup):
    lineup_count = [lineup.count(i) for i in lineup]

    df_lineup = pd.DataFrame({'position': lineup, 'count': lineup_count})
    positions_non_repeated = df_lineup[df_lineup['count'] <= 1]['position'].values
    positions_repeated = df_lineup[df_lineup['count'] > 1]['position'].values

    df_squad = best_squad(nationality)

    df_lineup = pd.concat([
        df_squad[df_squad['player_positions'].isin(positions_non_repeated)].drop_duplicates('player_positions', keep='first'),
        df_squad[df_squad['player_positions'].isin(positions_repeated)]]
    )
    return df_lineup[['short_name', 'overall', 'club_name', 'player_positions']]

最后,让我们循环遍历世界杯前 7 名球队,返回平均得分最高的阵型。

for index, row in df_average_overall[:7].iterrows():
    max_average = None
    for key, values in dict_formation.items():
        average = best_lineup(row['Teams'], values)['overall'].mean()
        if max_average is None or average>max_average:
            max_average = average
            formation = key
    print(row['Teams'], formation, max_average)

太好了!现在我们有了每个国家队的最佳阵型。

Spain 4-2-3-1 85.1
Portugal 4-2-3-1 84.9
England 4-4-2 84.45454545454545
Brazil 4-3-3 84.81818181818181
France 4-2-3-1 83.9
Argentina 4-3-3 83.54545454545455
Germany 4-2-3-1 84.1

让我们来看看什么是最适合西班牙、葡萄牙、英国、巴西、法国、阿根廷和德国的 XI。

1.西班牙:最佳开局 Xi(4-2-3-1)

best_lineup('Spain', dict_formation['4-2-3-1'])

2.葡萄牙:最佳开局 Xi(4-2-3-1)

best_lineup('Portugal', dict_formation['4-2-3-1'])

3.英国:最佳首发 Xi(4-4-2)

best_lineup('England', dict_formation['4-4-2'])

4.巴西:最佳开局 Xi(4-3-3)

best_lineup('Brazil', dict_formation['4-3-3'])

5.法国:最佳开局 Xi(4-2-3-1)

best_lineup('France', dict_formation['4-2-3-1'])

6.阿根廷:最佳开局 Xi(4-3-3)

best_lineup('Argentina', dict_formation['4-3-3'])

7.德国:最佳开局 Xi(4-2-3-1)

best_lineup('Germany', dict_formation['4-2-3-1'])

就是这样!你可以在我的 GitHub 上找到完整的代码。

用 Python 学习数据科学? 加入我的 20k+人电子邮件列表,获取我的免费 Python for Data Science 备忘单。

如果你喜欢阅读这样的故事,并想支持我成为一名作家,可以考虑报名成为一名媒体成员。每月 5 美元,让您可以无限制地访问数以千计的 Python 指南和数据科学文章。如果你使用我的链接注册,我会赚一小笔佣金,不需要你额外付费。

https://frank-andrade.medium.com/membership

反击算法不透明

原文:https://towardsdatascience.com/fighting-back-on-algorithmic-opacity-30a0c13f0224

责任人工智能系列

对提高算法决策系统透明度的现有工具和政策的回顾

来源:作者图片

算法系统被不透明性所困扰,并且通常只有在它们的危害出现后才会被公众看到。

让我们举两个不透明的高风险算法系统的突出例子。

在荷兰,一个名为 SyRI 的黑箱算法系统被用来检测福利欺诈。该系统被发现有严重的种族偏见,并且在检测欺诈方面无效。该系统的部署给被错误标记为欺诈的家庭造成了严重伤害。低收入家庭被迫偿还他们不欠的钱,导致驱逐和负债。活动家和记者多年来游说让叙利亚退休,这最终被发现是非法的,因为它不符合欧洲人权公约规定的隐私权。

在美国,一种名为 COMPAS 的累犯预测算法被法院用来评估被告成为累犯的可能性,从而影响监禁判决和保释金额。一篇里程碑式的调查文章利用外部审计发现了 COMPAS 存在偏见的证据,因为黑人被告比白人被告更有可能被错误地标记为具有更高的累犯风险。研究还显示, COMPAS 在预测个人再犯风险方面并不比从网上随机招募的志愿者更好。

在这两个案例中,活动家、调查记者和学者(一个我称之为 公共利益团体 )为实现这些系统性能的某种程度的透明做出了重大努力。

算法的不透明可以在多个层面上体验。在最基本的层面上,该系统是不可见的,意味着受影响的个人不知道它的存在。接下来是与流程相关的不透明,系统的设计和操作它的流程不为公众所知。最后是与结果相关的不透明。这些算法系统的性能、有效性和准确性通常不会公开共享,受影响的个人也不会获得明确的补救途径。

为什么关注透明度?

透明度是保证负责任地使用算法系统的重要前提。透明度提供了关于系统设计和性能的关键信息,有助于实现问责制、机构和追索权。

管理负责任使用广告的一级和二级原则。来源:作者图片

透明度也可能是一个难以衡量的模糊术语。

如何确定一个算法系统是否足够透明?将大型数据文件、源代码和文档公开会使系统变得透明吗?

也许吧,但是这种类型的透明度对一般公众来说没有意义,因为文档可能不直接相关或不可理解。数据转储还会导致信息过载,因为人们可能不知道从哪里开始理解它们是如何受到系统影响的。

相反,我们应该提倡有意义的透明度。

有意义的透明度是由利益相关者的信息需求驱动的。这意味着以最适合他们理解的方式交付与每个涉众群体相关的信息。

例如,监督机构或外部审计员可能需要访问源代码、数据和深入信息,以验证算法系统的负责任的使用;而受影响的个人会关心系统会如何影响他们,以及有什么渠道可以获得反馈和补救。

从社会的角度来看,有三个层次的有意义的算法透明性:

  • 0 级:能见度基线。这可能包括系统存在、范围和所有者的基本信息。
  • 第一级:流程可见性。这包括披露系统的设计和管理它的过程。这些信息有助于评估系统对负责任使用保障措施的执行情况。
  • 第 2 级:结果可见性。这包括与系统产生的结果相关的披露。应对这些信息进行评估,以了解系统是否符合负责任的使用原则:公平性、可解释性、安全性、健壮性和隐私性。

在社会层面实现有意义的算法透明的途径。来源:作者图片

实现透明度的现有努力

实现透明度意味着:

  1. 定义透明度要求及其适用时间;
  2. 创造和采用有助于遵守透明度要求的工具;和
  3. 验证是否符合透明度要求。

政府对于实现算法透明至关重要,因为从理论上讲,它们必须有办法监管算法系统的使用,并实施制衡。

事实上,算法监管仍处于初级阶段。大多数寻求规范算法的政府都致力于制定标准,并对公共部门使用的算法系统进行编目。其他由于缺乏能力和技术专长而难以监管算法系统

迄今为止提出的最全面的算法法规是 2021 年 4 月共享的欧盟委员会的人工智能法案。从许多方面来看,这都是一项具有里程碑意义的提案:它要求建立一个高风险系统的公共数据库,并披露合规性评估。欧盟人工智能法案有望促进公共和私营部门在算法透明度方面的不断变化,并有可能产生全球影响,类似于 GDPR 如何影响全球隐私监管

《欧盟人工免疫法》也受到了几个著名的公共利益团体的批评,主要是因为它在风险水平的定义以及如何实施这些定义方面含糊不清。其他批评包括没有为民间社会参与进程创造有意义的空间,以及没有包括补救和问责条款

在监管范围之外,私营和公共机构提出并采用了一些实现透明度的工具。这些包括自我管理的影响评估、外部审计和记录机制。

算法透明度工具和政策的详尽列表可以在下表中找到。

学分:开放政府伙伴关系。要添加缺失条目,请填写此表格:https://airtable.com/shr7mxNbn7xus2pEy

持续的挑战

除了讨论的监管挑战之外,还有几个问题需要解决:

  • 固有模型不透明度。随着黑箱模型的使用激增,我们如何确保结果的可解释性?
  • 商业秘密当涉及透明度披露时,算法解决方案提供商经常引用“知识产权问题”。一个新出现的问题是,通过公开决策系统的内部运作,可能会产生外部性,不诚实的代理人可以利用该系统为自己谋利。
  • 合规成本。大多数开发算法系统的组织需要投入资源来记录、评估和遵守提议的需求。这造成了采纳摩擦。

走向有意义的透明

基于这一回顾,显然需要一种全面的方法来创建有意义的算法透明性。

首先,我们需要一个健壮的算法系统风险评估框架。

接下来,我们需要定义整个系统生命周期中每种风险类型所需的披露。考虑创建一个披露范围,仅通过特许访问渠道与审计人员共享最敏感的数据,可能会有所帮助。

最后,我们需要正确的激励机制来确保公民社会的遵守和追索权。

更深入:算法寄存器

我的论文主要关注算法寄存器在实现透明性方面的潜在作用。最简单的形式是,算法登记册是一个实体使用的算法决策系统的日志,包括对相关利益相关者的相关披露。

在过去几年里,已经部署了一些登记册。这些包括由当地政府机构发布的登记册,如在阿姆斯特丹赫尔辛基南特的登记册,以及由公共利益团体创建的登记册,如意大利隐私网络创建的登记册。

基于对第一代算法寄存器的回顾,我发现算法寄存器是一个多功能的工具,如果仔细设计的话:

  • 通过满足不同利益相关方群体的信息需求,实现有意义的透明度;
  • 可以激励系统所有者实施更好的内部“负责任的使用”控制;
  • 能够形成公民反馈回路,扩大公共利益团体的作用,同时减少透明度负担;
  • 可以补充现有的问责机制,让组织为不断变化的监管环境做好准备。

算法寄存器在负责任地使用算法决策系统中的潜在作用。来源:作者图片

https://medium.com/@mayamurad/ai-registers-101-7e2f58719781

基于我的研究生论文“ 超越黑盒”(MIT 2021)的一系列关于负责任的 AI 的一部分。提出的想法是基于几个在管理、部署和评估人工智能系统方面有直接经验的从业者的反馈和支持而发展起来的。我正在分享和开源我的发现,以使其他人能够轻松地研究并为这个领域做出贡献。

与二重身战斗

原文:https://towardsdatascience.com/fighting-doppelgängers-2fc28762e169

如何去除数据中的邪恶双胞胎,减少特征空间

图片由艾托夫Pixabay 上拍摄

摘要

给定一个包含许多变量的大型数据集,其中一些变量可能代表相同的现象,或者彼此带来重叠的信息。面对这个问题的一个常见的预处理策略是分析相关性。在本文中,我描述了一种策略,用于扫描线性相关性网络,搜索要保留的最佳变量,并丢弃多余的变量。此外,我提供了一个 R 包来轻松地执行这项工作。

当处理由记录机械事件的传感器产生的数据时,包含成百上千个变量的大型数据集是常见的。在这些情况下,许多变量可以作为预测某些目标度量的候选变量。然而,尤其是在工业环境中,数据可以包括完全线性相关或非常相关的变量。

例如,传感器可以从相同的过程中提取几个特征,作为相同基的线性变换(如一组记录的总和、它们的平均值等)。).在其他情况下,有真正不同的测量,但本质上相关,或代表同一现象的两个相反方面(想象一种化学混合物的两个互补元素)。

非常相关的变量是多余的,通常它们不会带来额外的信息。而且,完全因变量会让一些机器学习算法崩溃。一般来说,这些“分身”使模型构建过程变得复杂,增加了计算量,在某些情况下会产生过度拟合。

所以,问题是:如何修剪数据集以去除邪恶的二重身?

设置相关性的阈值

我们用来识别重复或近似重复变量的有力武器是线性相关指数。

当两个变量的相关性为~|1|时,保留其中一个变量从纯统计学的角度来看是无关紧要的。

当相关性低于|1|时,情况变得复杂,但是仍然相关,并且基于理论的选择是不切实际的。在这些情况下,我们需要一个标准来确定相关性是否相关。一种策略是对相关值设置阈值。

给定一个阈值,我们可以关注强关系来实施修剪策略。

修剪策略

修剪的关键思想是丢弃尽可能多的变量,保留尽可能多的信息。

想象一种情况,其中三个变量 A、B 和 C 有很强的关系。b 与 A 和 C 都具有超过阈值的相关性,而 A 和 C 彼此具有低于阈值的相关性。下图恢复了这些关系,将每个变量表示为网络的一个节点,如果两个变量的相关性高于设定的阈值,则连接这两个变量。

图片来自作者——在 CC0 许可下发布

面对这种情况,修剪的方法可以是去掉 B ,保留相关性较低的 AC 。然而,还有一种更为节俭的方法:只保留 B ,去掉 ACB 可以被认为是网络的代表,它可以作为整个社区的代言人。

因此,正如您所看到的,选择并不是唯一的。

为了更好地理解这两种方法之间的差异,我引入了一个具有更复杂关系的数据集。

一个更复杂的例子

下图是七个模拟变量( alphabetagammadeltaepsilonzetaeta )得到的网络关联。变量在图中的空间分布是根据它们之间关系的强度:相邻的变量之间的相关性更强。仅表示高于阈值|0.7| 的关系。

源数据在我的 R 包分身中包含的数据帧测量中可用。

图片来自作者——在 CC0 许可下发布

我手工构建了上面的图,但是如果你是一个 R 用户,可以考虑使用包[qgraph](http://sachaepskamp.com/qgraph/examples)将一个关联矩阵可视化为一个网络。如果你是 Python 用户,我建议看一下这篇关于 TDS 的文章。从现在开始,我使用 R 语言来构建例子。

我在下面报告完整的相关矩阵。

r <- cor(doppelganger::measures)
diag(r) <- NA
round(r, 3)
 alpha  beta gamma delta epsilon  zeta   eta
alpha      NA 0.129 0.833 0.815   0.715 0.207 0.645
beta    0.129    NA 0.152 0.108   0.056 0.770 0.097
gamma   0.833 0.152    NA 0.984   0.620 0.193 0.702
delta   0.815 0.108 0.984    NA   0.588 0.167 0.711
epsilon 0.715 0.056 0.620 0.588      NA 0.072 0.519
zeta    0.207 0.770 0.193 0.167   0.072    NA 0.137
eta     0.645 0.097 0.702 0.711   0.519 0.137    NA

该图显示了两个社区的存在:一个是对 zeta - beta 的社区,另一个包括剩余的变量。与前一个天真的例子相比,情况更加混乱。如何进行?

区分变量的优先级

我们可以根据变量的中心度对变量进行排序,中心度意为一个节点与其他节点的连接强度。最中心的节点对应于网络中最具代表性的变量。

我们可以将中心度计算为与变量相关的相关性绝对值的平均值。下面的 R 代码计算每个节点的中心性,并按降序排列。

sort(colMeans(abs(r), na.rm=TRUE), decreasing=TRUE)
 gamma     delta     alpha       eta   epsilon      zeta      beta 
0.5805754 0.5620824 0.5572697 0.4685961 0.4282394 0.2575334 0.2188217

根据中心度的排序允许我们在选择保留什么和丢弃什么时对变量进行优先级排序。我们面前有两条路:

  1. 保留最中心的变量,以它们的代表性的名义(中心性准则);
  2. 保留最外围的变量,以它们独立的名义(外围性判据)。

无论如何,我们可以应用相同的修剪程序,但是:

在“中心性”情况下,我们按照中心性程度向量以降序扫描变量,而在“边缘性”情况下,我们按照升序扫描变量。

我们开始保留排名中的第一个变量,去掉它的二重身。然后,让我们保留第二个变量,去掉它的二重身。等等,直到结束。很简单,不是吗?

算法应用

现在,将这个过程应用到上面显示的例子中。我描述了遵循中心性标准的操作。

第一步。最中心的变量是伽马。因此,我们“开启”伽马和“关闭”德尔塔阿尔法埃塔,它们与伽马具有过阈值相关性。在下图中,“关闭”的变量用浅灰色标记,它们的修正用虚线表示。

第二步。伽玛之后,按照优先级顺序,第一个未被丢弃的变量是ε。然而,ε与其余变量的相关性没有超过阈值。它的复制品已经被丢弃,所以不需要任何操作。

步骤三。以下变量为ζ,与 beta 有很强的相关性。所以,我们去掉了贝塔,保留了泽塔

图片来自作者——在 CC0 许可下发布

在迭代结束时,我们将继续使用伽玛ε泽塔。三个变量而不是七个。

中心性对边缘性

中心性标准利用了变量总体中孤立社区的存在。从理论的角度来看,当我们在社区内部有强连接而在社区之间有弱连接时,这种方法发挥了最大的作用。相反,外围性标准可以在包含一些子群的更同质的网络中发挥最大作用。

中心性标准倾向于保留更少但更相关的变量。边缘性标准倾向于保留更多的变量,但相关性较低,然而,它们不一定是每个亚组的最具代表性的。

R 的二重身套装

使用 R 包二重身只用一行代码就可以完成前面的步骤。

加载包和数据集:

library(doppelganger)
measures # comes with the package

# A tibble: 100 × 7
     alpha     beta   gamma  delta epsilon    zeta     eta
     <dbl>    <dbl>   <dbl>  <dbl>   <dbl>   <dbl>   <dbl>
 1  0.0185 -0.564   -0.526  -0.368  -0.934 -0.878   0.0913
 2  0.120   0.00233 -0.414  -0.515  -0.193 -0.464  -0.324 
 3 -0.767   0.0641  -1.51   -1.26   -1.25  -0.0825 -1.70  
 4 -2.12    0.105   -2.38   -2.37   -1.75  -0.323  -0.426 
 5 -1.48   -0.126   -0.681  -0.340  -1.87   0.0678 -0.791 
 6  1.69    0.268    2.39    2.59    1.06   0.115   1.44  
 7  1.26   -1.17     0.290   0.231   1.93  -0.683  -0.253 
 8  1.23    1.40     1.10    0.997   0.717  1.07    0.265 
 9  0.295  -0.0263  -0.0221 -0.115  -0.125  0.179  -0.978 
10  0.157   0.268    0.215   0.454   0.531  1.25   -0.0989
# … with 90 more rows

再现上述变量的修剪过程:

dg <- doppelganger(measures, priority="c", threshold=0.7)

同名函数doppelganger创建一个包含一些槽的列表对象,包括keepdrop,分别收集变量的名字来保存和删除。

dg$keep

[1] "gamma"   "epsilon" "zeta"

如果您需要检查特定变量的相关性,该包提供了函数inspect_corrs:

inspect_corrs(dg, "gamma")

# A tibble: 6 × 3
  variable is_alias   cor
  <chr>    <lgl>    <dbl>
1 delta    TRUE     0.984
2 alpha    TRUE     0.833
3 eta      TRUE     0.702
4 epsilon  FALSE    0.620
5 zeta     FALSE    0.193
6 beta     FALSE    0.152

非缺失数据的加权

软件包doppelganger通过用可用于指数计算的观察值数量对每个相关性进行加权来计算中心度。这种策略在存在缺失数据的情况下是有效的,因为它允许“奖励”具有许多与其他变量的填充记录相匹配的填充记录的变量。

我们希望保留最好的变量,但也保留尽可能多的记录!

对候选预测器池的修剪可以有效地帮助建立一个简单有效的模型,尤其是用于推理目的。最佳实践是将选择程序建立在潜在预测者的理论假设或预测能力的基础上。然而,通常,由于缺乏信息或数据集的维度,这是不切实际的。在这些情况下,一个不太精确的方法——就像本文中描述的方法——可以派上用场。

最后,记住什么是精确和回忆,不要在面试中害怕这些问题

原文:https://towardsdatascience.com/finally-remember-what-precision-and-recall-is-and-stop-being-afraid-of-these-questions-in-f61981930c67

一个直观的指南,一步一步地绘制混淆矩阵,并推导出精确度、召回率和 F1 分数的定义

预览。作者图片

理解混淆矩阵、精确度和召回率的概念对于评估任何分类算法的质量是最重要的。而且虽然这在现实任务中并不那么重要(首先,你会在 90%的情况下使用 F1-score,其次,你会花 10 秒钟谷歌一下来刷新你的记忆),但是理解这些东西还是很有用的。另外,这个问题在数据科学和机器学习职位面试中极其常见。

我(以及我认识的一些更有经验的人)仍然需要花几秒钟来记住什么是什么。因此,我向你展示我的一步一步的指导,如何记住如何绘制混淆矩阵,并从中推导出精确度、召回率和 F1 分数的定义。

如果你已经知道什么是精确或者回忆,但是仍然经常在定义上感到困惑,你应该读读这篇文章。

这篇文章并不解释什么是精确或召回。这篇文章解释了如何记住什么是精确或回忆。

一步一步画困惑矩阵

当我们开始画混淆矩阵时,让我们画一个 2x2 的矩阵。

我们记得在某个地方一定有一个实际的类,和一个预测的类。取决于你如何排列它们,你的矩阵可能会相对于主对角线镜像。请记住,你在其他来源看到的矩阵可能与我画的不同。

为了避免混淆,让我们将预测的类放在的上面(使用直觉,单词Predirect 中的字母 P 是由一个竖条组成的,上面有一个圆圈)。

之后,让第一个元素(实际类的情况下为上,预测类的情况下为左)为负例,第二个元素(实际类的情况下为下,预测类的情况下为右)为正例。这里我用的直觉是,我们是从左到右,从上到下,从一个较小的数向一个较大的数移动(而负类是 0,正类是 1)。

画出混淆矩阵。第一步。作者图片

第二步也很简单——让我们填充主对角线上的元素。这些是我们的分类器正确识别的元素——真阳性和真阴性(在这里意味着我们的分类器是)。

画出混淆矩阵。第二步。作者图片

  • 真阳性(TP) 是被分类为阳性且实际为阳性的元素——预测阳性和实际阳性。**
  • 真阴性(TN) 是已经被归类为阴性的元素,实际为阴性——预测阴性和实际阴性。**

之后,我们还要在矩阵中放置假阳性和假阴性(这里指我们的分类器是错的)。这就是问题开始出现的地方。

为了记住假阳性和假阴性的位置,记住在这些预测中分类器是错误的。这意味着,尽管它们不正确,但它们是预测的值,因此它们对应于预测的类。

画出混淆矩阵。第三步。作者图片

让我们给出正式的定义:

  • 假阳性(FP) (也称为 I 型错误)是一个已经被归类为阳性但实际为阴性的元素——预测阳性,实际阴性。**
  • 假阴性(FN) (又称 II 型错误 ) 是已经被归类为阴性但实际为阳性的元素——预测阴性,实际阳性。**

为了快速理解它们之间的区别,不至于混淆,只要记住分类器的预测是包含在题目中的,并且这个预测是错误的就够了。比如假。它是正的,因为我们的分类器是这样预测的,但它是错误的。所以预测类是,而实际类不是正的,所以

为了不混淆 TN、TP、FN 和 FP,问两个问题就足够了:

  1. 分类器预测了什么?负或正
  2. 分类器正确吗?真或假

两个答案都包含在问题中。

如何永远不要混淆 TN,TP,FN,FP?作者图片

现在我们有一个现成的混淆矩阵,这已经是一半了!

混乱矩阵。作者图片

如何停止恐惧,开始理解精密和回忆

精确度和召回率公式都很简单。它是真阳性与真阳性加上某个值的比率。分母(真阳性加上某个值)是实际阳性或预测阳性。那有什么意义?让我们弄清楚。

精度公式

记住精度公式中的所有项都包含字母 P ( P 精度— P ,很容易记忆)。
所以精度是 TP(TP + FP) 的比值,其中 (TP + FP)预测阳性

精确公式。作者图片

回忆公式

另一方面,召回是 TP(TP + FN) 的比值,其中 (TP + FN)实际阳性

回忆公式。作者图片

这些到底有什么意义?

我不认为有必要给出奇怪的定义来解释一切,但只会使其复杂化(比如回忆是一种检测概率)。我不否认它们是有用的,但它们往往弊大于利。最后,你可以很容易地发现他们在阅读其他文章。

我会尽可能直观地解释一切。我建议你在阅读下面两条语句时,保持精确度,并在眼前回忆公式。

  • 如果 FP = 0,则精度等于 1。
    所以
    精度高关系到****假阳性率低或者说I 型错误量小。****
  • 如果 FN = 0,召回等于 1。
    所以高召回率低假阴性率少量 II 型错误有关。

如何记住这些?高精度—很少的假阳性—很少的 I 型错误。记住精度总是精度-召回对中的第一个(I 类型错误);我们已经记住的是——精度公式中的所有项都包含字母 P (很少有误)。****

这是让您理解何时使用特定指标的基础。

  • 如果 FP 价格高,用精度(预测借款人会还贷,虽然他破产了;“好”的借款人是正类);
  • 而如果 FN 价格高,用召回(预测病人是健康的,虽然他生病了;病是正类)。

这些定义取决于对类的选择(哪个类是负的,哪个是正的)——所以要时刻注意这个。例如,交换上面例子中的类,看看会发生什么。

f1-分数

F1-score 是一种将精确度和召回率结合成一个指标的方法。我们需要这个,因为只用一个数字评估质量很容易,而不是两个。我们不能使用简单平均值,因为它不考虑极小的值。

例如,如果我们让 F1-score 是精度和召回率的平均值,则相同的值得到:
精度= 0.5 和召回率= 0.5 的分类器 1 和
精度= 1 和召回率= 0 的分类器 2。
两个分类器都将得到 F1 分数= 0.5,尽管很明显第一个分类器要好得多。当然,这是个玩具例子,但离真相不远。

事实上,我们想要这样一个表达式,如果两个元素中至少有一个比一个小得多,那么这个表达式就是小的。这样的表达式称为加权平均值,或调和平均值。****

f1-得分公式。作者图片

这个表达式的分子是乘积,这是合乎逻辑的。如果其中一项比一项小得多,那么它们的乘积也将分别比一项小得多。需要乘以 2,以便 F1 分数像所有常用指标一样从 0 变为 1。

请记住,还有其他分类指标。比如非常受欢迎的AUC-ROCROC(受试者工作特性)曲线下的区域(你可以在这里了解一下)或者不太受欢迎的 AUC-PRC精确召回曲线下的区域**

结论

让我总结一下我们下面列出的所有概念:

  • 真阳性(TP) 是被分类为阳性且实际为阳性的元素——预测阳性,实际阳性;****
  • 真阴性(TN) 是已经被归类为阴性的元素,实际上是阴性的——预测阴性和实际阴性;****
  • 假阳性(FP) (也称为 I 型错误)是已经被分类为阳性但实际为阴性的元素——预测阳性,实际阴性;****
  • 假阴性(FN) (也称 II 型错误 ) 是已经被归类为阴性但实际为阳性的元素——预测阴性,实际阳性;****
  • 精度意味着低 FP 率(少数 I 型错误);
  • 召回意味着低 FN 率(少数 II 型错误);
  • F1-score 是一个将精度和召回率结合成一个数字的好方法。

总结。作者图片

可能对你有用的资源

感谢您的阅读!

  • 我希望这些材料对你有用。在 Medium 上关注我以获得更多类似的文章。
  • 如果您有任何问题或意见,我将很高兴得到任何反馈。在评论中问我,或者通过 LinkedInTwitter 联系。
  • 为了支持我作为一名作家,并获得数以千计的其他媒体文章,使用我的推荐链接获得媒体会员资格(不收取额外费用)。

使用 Upgini 查找机器学习模型的信息特征

原文:https://towardsdatascience.com/find-informative-features-for-machine-learning-models-with-upgini-17489158ffaa

用于丰富特性的 Python 库

Kushagra Kevat 在 Unsplash 上拍摄的照片

特征工程是构建机器学习模型的重要组成部分。我们通常会花费大量时间来寻找新的功能,为机器学习模型增加信息能力。

找到一个有助于预测目标变量的特征并不是一件容易的事情。我们最终可能会创建出对模型没有或增加很少价值的特性。另一方面,如果我们最终创建了一个增强模型的准确性和健壮性的特征。找到这样的特征几乎总是比超参数优化更有帮助。

没有免费的午餐,所以我们可能需要搜索大量的数据源或执行广泛的探索性数据分析,以便能够找到将产生重大影响的功能。

Upgini 正是为此目的而创建的开源 Python 库。它所做的是搜索成千上万的公共和社区数据源,然后创建将提高模型性能的要素。

特征工程可以被认为是一个两步任务。第一步是找到数据(即特征),第二步是检查它与问题的相关性。Upgini 完成了这两个步骤。它不仅发现特征,而且评估它们。

Upgini 的 enricher 对象返回现有功能和新功能的 SHAP 值,以便我们了解新功能有多有用。SHAP 值经常用于机器学习模型的可解释性和可解释性。

让我们看一个例子来演示如何使用 Upgini 来丰富特性。第一步是安装 Upgini,可通过 pip 完成,如下所示:

pip install upgini

我们将使用 OpenML 网站上有 CCO 许可的 intuit 数据集。该任务是电子邮件响应预测,因此数据集包含一些要素和一个二进制目标变量。我们将使用 Pandas 来读取和清理数据集。

import pandas as pddata = pd.read_csv("csv_result-intuit.csv")data.head()

(图片由作者提供)

res1 是目标变量,取值为 0 和 1。数据集需要清理一下。

  • id 功能是多余的,因此我们将删除它们。
  • 邮政编码 99999 无效,因此我们也将删除这些行。
data = data.drop(["id","id.1"], axis=1)data = data[data.zip != 99999]

搜索关键字

Upgini 通过搜索关键字找到特征。它目前支持以下功能:

  • 日期/日期时间
  • 邮政编码
  • 国家
  • 电话号码
  • 散列电子邮件
  • IP 地址

当创建一个 enricher 对象时,我们需要指出包含搜索关键字的列,在我们的例子中是邮政编码。需要提及的重要一点是,在使用邮政编码时,我们还需要定义国家。因此,我们将创建一个列来显示这些邮政编码所在的国家,即美国。

data["country"] = "US"

数据清理和预处理

有些行具有重复的特征值,但目标值不同。我们还将使用 Pandas 的删除重复项功能来删除它们。

cols = list(data.columns)
cols.remove("res1")data = data.drop_duplicates(subset=cols)

原始数据集包含 20000 个观察值(即行),就目标值而言,这是非常不平衡的。大约 95%的目标值为 0,这意味着没有响应。处理不平衡数据集有不同的方法,但这不是本文的主题。因此,我们将从数据集中提取一个不那么不平衡的样本。

data_1 = data[data.res1==1]
data_0 = data[data.res1==0].sample(n=4000)data = pd.concat([data_0, data_1], axis=0, ignore_index=True)data["res1"].value_counts(normalize=True)**Output**
0    0.807591
1    0.192409

现在% 80.76%的目标值是 0。

列车测试分离

下一步是将数据分成训练集和测试集。我们将通过使用 Scikit-learn 的列车测试分割功能来执行此操作。

from sklearn.model_selection import train_test_splitX = data.drop(columns=["res1"])
y = data["res1"]X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.25, random_state=42
)

使用 Upgini 查找功能

我们现在将创建一个 Upgini 的 enricher 对象。

from upgini import FeaturesEnricher, SearchKeyenricher = FeaturesEnricher(
    search_keys = {
      "zip": SearchKey.POSTAL_CODE,
      "country": SearchKey.COUNTRY
    },
    api_key = "WRITE YOUR API KEY HERE"
)

搜索键是通过将列名和搜索键类型写成 Python 字典中的键值来定义的。另一个参数是 api 密匙,你可以通过注册 Upgini 免费获得。

下一步是使训练集适合刚刚创建的 enricher 对象。

enricher.fit(X_train,
             y_train,
             eval_set=[(X_test, y_test)]
)

(图片由作者提供)

发现了 3 个新特性。我们还可以看到现有要素的 SHAP 值和 SHAP 值。其他特性的 SHAP 值为 0,所以我没有把它们包含在上面的截图中。

衡量绩效

最后一步是衡量新特性对模型性能的影响。我将使用一个随机的森林分类器来完成这个任务,但是你可以随意使用任何你喜欢的算法。让我们首先创建模型。

from sklearn.ensemble import RandomForestClassifierclf = RandomForestClassifier(
    n_estimators=100, 
    max_depth=3, 
    random_state=0
)

我们将使用 enricher 对象的计算度量方法来评估新特性。

enricher.calculate_metrics(
    X_train, y_train, 
    eval_set = [(X_test, y_test)],
    estimator = clf,
    scoring = "accuracy"
)

(图片由作者提供)

性能改进显示在提升列中。训练集的精度提高了%6.8,而测试集的精度提高了%1.2。考虑到获得这些特性是多么简单,这实际上是一个很大的改进。

结论

在某些任务中,1%的精度改进可能至关重要。考虑一个有数百个位置的零售连锁店。需求预测增加 1%可以在库存规划、供应链运营和其他运营工作中节省数千美元。

正如我们在上面的例子中所看到的,用 Upgini 搜索新特性只需要几个简单的步骤。因此,考虑到它的潜力和易用性,它绝对值得一试。

你可以成为 媒介会员 解锁我的全部写作权限,外加其余媒介。如果你已经是了,别忘了订阅https://sonery.medium.com/subscribe如果你想在我发表新文章时收到电子邮件。

感谢您的阅读。如果您有任何反馈,请告诉我。

使用 Python 找到两个角度之间的差异

原文:https://towardsdatascience.com/find-the-difference-between-two-angles-using-python-ac553a1ef5c0

因为在角度从 355 度变为 5 度之前,这都是一种乐趣和游戏

照片由 Sunil RayUnsplash 拍摄

在我的业务领域(海上风力),我花了很多时间分析风力数据,但直到最近我才尝试使用 python 来分析风向随时间的变化。所以直到最近我才意识到我不知道该怎么做。

看起来很简单,如果方向从 350 度变到 320 度,从另一个中减去一个,得到绝对值,这就是 30 度的变化。但是等一下,等一下…

从 350 度到 5 度的变化是 15 度或 345 度的变化,这取决于变化发生的方向。同样,从 250 度到 200 度的变化可以是 50 度,也可以是 450 度。如果您正在处理大型数据集(或者只是通常重视您的时间),打开巨大的文件,手动检查每个文件并编辑正确的结果是不可行的。你和你的电脑都可能会认输,所以需要一个自动化的解决方案。

在整篇文章中,我将使用风向作为例子,但这适用于任何使用角度或弧度的东西,并寻求随时间的变化。

目录

1。必要的假设

2。代码

3。解释

必要的假设

如前所述,当方向通过北方,或零度时,我们的简单方法就失败了。将度数转换成弧度也不能解决问题(相信我,我试过了)。相反,我们需要对方向行为进行假设。

如果方向从 350 度变为 5 度,那就是 15 度的变化,只有如果,是顺时针方向。即如果风向从 350 度变化到 351 度、352 度…..359,0,1 … 5 度。也有可能风向已经从 350 度变成了 349 度,348 度…6、5 度或逆时针方向。这两个选项如下所示。

角度方向可以逆时针(红色)或顺时针(蓝色)改变。作者提供的图片-未按比例绘制。

这两种情况实际上是否可能取决于数据类型和数据粒度。例如,一艘船的航向有可能在三秒钟内改变 190 度吗?极端天气会导致极端风向改变吗?

为了使建议的解决方案起作用,我们必须假设不可能在给定的周期内方向改变超过 180 度。即,如果数据是一分钟粒度的时间序列,从分钟 1 到分钟 2,超过 180 度的真正方向改变是不可能的。

如果这对您的数据集不起作用,请格外小心!考虑你拥有的可以证明或反驳这一理论的任何其他数据点,如果可能的话,获取更高频率的数据,以便这一假设可以成立。

代码

这不是一个完美的 pythonic 解决方案,但是对于我的用例来说,它完成了工作。下面的片段使用了熊猫图书馆,关于它的文档可以在这里找到。

**# find diff between min and max wind direction**df['delta'] = df.max_winddirection - df.min_winddirection

**# check for if difference minimun < max - 180, if so, use different equation to get degree change
**  
df.loc[df.min_winddirection < df.max_winddirection - 180, 'delta'] = 360 - df.max_winddirection + df.min_winddirection

解释

以 350 度到 5 度为例。

  1. 上面的代码首先为所有行分配基本的 delta 方程“最大角度-最小角度”。这将应用 350 作为该行的增量。
  2. 代码检查是否满足这些“穿过北方”情况的标准。这将检查是否:最小角度<最大角度—180”。在这种情况下,5 小于(350–180 ),因此为真。
  3. 该代码应用了一个新的公式,当δ为真时为“360-最大角度+最小角度”。导致 15 度。

如果不满足“穿过北方”标准,将毫无问题地应用基本最大值减去最小值公式。

希望这对你有所帮助。如果你有一个更干净的替代解决方案,我很乐意从中学习,请随时在评论中提出来。

用 Python 求矩阵的逆矩阵

原文:https://towardsdatascience.com/find-the-inverse-of-a-matrix-using-python-3aeb05b48308

如何在 Python 中使用行运算求矩阵的逆矩阵

介绍

本文跟随Python 中的高斯消去算法。介绍了一种利用行归约求逆矩阵的方法。

查看下面的文章,了解高斯消去法的必要介绍。

https://levelup.gitconnected.com/gaussian-elimination-algorithm-in-python-4e90cb3a0fd9

照片由 Linus MimietzUnsplash 上拍摄

背景

矩阵代数基础|第二部分呈现逆矩阵。回想一下并非所有矩阵都是可逆的A 必须是平方 ( n×n )且有一个非零行列式

本质上,矩阵的乘以它的得到单位矩阵I ,如等式 1 所示。

等式 1 —计算矩阵的逆矩阵(图片由作者提供)

以等式 2 中的 3×3 矩阵 A 为例。

等式 2 —矩阵 A(图片由作者提供)

等式 3 等同于等式 1,变量替换为

等式 3 —参数替换(图片由作者提供)

下面计算的 结果 是未知数 A⁻

算法

从等式 3 的分量创建一个扩充的矩阵。这个新矩阵包含 A 串联的 列式I ,如等式 4 所示。

等式 4 —扩充矩阵(图片由作者提供)

通过对增广矩阵应用行运算获得逆矩阵

对增广矩阵进行 高斯消去 过程,得到 中的 A 降排梯队形式(rref)同时跃迁 IA

总而言之:

  • A 转换成rref。于是,A 变成了*单位矩阵。*****

a .转换到单位矩阵(图片由作者提供)

  • I 运行上面的等价行运算,就变成了逆矩阵 A ⁻。

单位矩阵转换为逆矩阵(图片由作者提供)

例子

图 1 描述了逐步 操作改变扩充矩阵的前三列以实现 rref 的必要步骤。**

图 1 —实现简化的行梯队形式的行操作(图片由作者提供)

结果在意料之中。 A 成为单位矩阵,而 I 变换成以前未知的逆矩阵。**

Python 实现

有了 Python 中的编程高斯消去算法,代码只需要微小的修改就可以得到的逆**

使用 Gist 1 将等式 2 中的 A 定义为 NumPy 数组。

要点 1 —使用 Numpy 定义 A

同样,实例化一个新的变量 I ,与 A 相同的方形**

要点 2 —定义单位矩阵

使用 NumPy 的列连接操作创建增广矩阵,如要点 3 所示。**

要点 3 —创建身份矩阵

在不考虑某些边缘情况的情况下,下面在要点 4 中提供的代码是获得 所必需的行操作的幼稚实现。**

要点 4 —在 Python 中寻找逆矩阵

与高斯消去算法相比,对代码的主要修改代替终止于行梯队形式,操作继续到达缩减行梯队形式。****

因此,不是只迭代枢轴下面的,而是枢轴上面的行也被遍历操作**

执行脚本返回与图 1 中相同的答案。**

图 2-逆矩阵 Python 控制台输出

结果

给定任意数量的可逆矩阵和任意大小的,上述算法均适用。增加矩阵的大小也是可能的。**

Gist 5 提供了在 NumPy 中创建一个随机方阵的代码。**

要点 5 —大型随机矩阵

比较自定义算法运行时NumPy 当量突出了速度差。Gist 6 中的代码是一个简单的方法来记录时间**

要点 6 —比较方法运行时间

NumPy 比 T21 快一秒来反转矩阵。这个巨大的时差只会随着矩阵维度的扩大而增加。

结论

这篇文章概述了矩阵代数中使用的一个基本方法来计算一个矩阵的逆矩阵。**

使用概述的理论矩阵代数方法和等效的 Python 代码来理解操作如何工作。然而,Python 中的 NumPy 等库经过优化,可以高效地解密逆矩阵。在实践中,使用健壮的、维护良好的数学库。**

如果你对 Python、工程和数据科学感兴趣,可以看看我的其他文章。

***https://medium.com/@andrewdaviesul/membership

在 Gist 7 中找到所有 Python 代码。

要点 7——完成 Python 代码以找到矩阵的逆***

参考

[1] 工程师矩阵代数杰弗里·查斯诺夫

求正定矩阵的最小拉伸方向

原文:https://towardsdatascience.com/find-the-minimum-stretching-direction-of-positive-definite-matrices-79c2a3b397fc

Python 中图像形成和相机校准综合教程系列的第 4 部分

在进入摄像机校准之前,让我们讨论一下正定矩阵和一般矩阵的一些性质。我们将在校准摄像机时使用这些属性。

特征值和特征向量

设𝐴是形状为𝑚×𝑛矩阵,𝑥⃗是大小为𝑛.的向量那么𝑥⃗就是𝐴的特征向量如果𝐴𝑥⃗ = 𝜆𝑥⃗,其中𝜆是一个标量叫做𝑥⃗.的特征值特征值和特征向量的性质取决于矩阵𝐴.

假设矩阵𝐴有𝑛独立特征向量,那么𝐴可以因式分解为:

其中,𝑆是以特征向量为列的特征向量矩阵,λ是特征值矩阵,它是沿对角线具有特征值的对角矩阵。注意,𝑆在这里是可逆的,这只有在列是独立的情况下才有可能,这意味着特征向量应该是独立的。

这里𝑥⃗1,𝑥⃗2,…,𝑥⃗𝑛是𝐴的特征向量;而𝜆1,𝜆2,…,𝜆𝑛是它们对应的特征值。

对称矩阵

𝐴是一个对称矩阵如果𝐴=𝐴⊺,其中𝐴⊺是𝐴.的转置我们将使用符号⊺来表示转置。对称矩阵将总是具有特征值,并且特征向量可以被选择为正交的。

我们看到:

由于对称矩阵的特征向量可以选择正交,我们可以将特征向量矩阵 s 表示为𝑄,其中𝑄的列彼此正交。同样,𝑄的逆也是它的转置,因为它是正交的。因此,我们可以将𝐴分解为:

正定矩阵

如果在一个对称矩阵中所有的特征值都是正的,那么这个矩阵叫做正定矩阵。如果𝐴是正定矩阵,𝜆1,𝜆2,𝜆3…是𝐴的特征值,那么𝜆𝑖 > 0 和𝜆𝑖 ∈ 𝐑对于 i = 1,2,3,…

椭圆体

正定矩阵有一个有趣的性质:如果𝐴是正定矩阵,那么𝑥⃗⊺𝐴𝑥⃗ = 1 代表𝐑𝐧中以零为中心的椭球。𝐑𝐧是 n 维实空间,𝑥⃗ ∈ 𝐑𝐧.

这个椭球的主轴由矩阵𝐴.的特征值和特征向量决定

让我们看一个例子。

例子

设矩阵𝐴 = [[5,4],[4,5]]。𝐴的特征值是 1 和 9,它们都是正的。因此 A 是正定矩阵。接下来,让我们计算𝑥⃗⊺𝐴𝑥⃗.这里是𝑥2].的𝑥⃗=[𝑥1

所以我们得到了𝑥⃗⊺𝐴𝑥⃗ = 5𝑥1 +8𝑥1𝑥2+5𝑥2。等等,那看起来不像椭圆。椭圆的方程具有以下形式:

那么是哪里出了问题呢?让我们用𝐴.的特征向量基来表示向量𝑥⃗本质上,我们需要在𝑥⃗上执行基变换的改变,并且我们在系列的第 2 部分中讨论了基变换的改变。基矩阵的变化是特征向量矩阵𝑄.的逆由于𝑄是一个标准正交矩阵,𝑄的逆是𝑄⊺,这是我们的基变换矩阵。

让𝑦⃗ = 𝑄⊺𝑥⃗.𝑦⃗是向量𝑥⃗ wrt 的特征向量基。现在让我们看看能否得到一个椭球体:

consider 𝑥⊺𝐴𝑥
=        𝑥⊺(𝑄Λ𝑄⊺)𝑥    (𝐴 = 𝑄Λ𝑄⊺)
=       (𝑥⊺𝑄)Λ(𝑄⊺𝑥)  (Matrix Multiplication is associative)
but,     𝑦 = 𝑄⊺𝑥 and 𝑦⊺ = 𝑥⊺𝑄
substituting y in the equation, we get:
         𝑥⊺𝐴𝑥 = 𝑦⊺Λ𝑦

让我们看看𝑦⊺λ𝑦是什么样子的:

这里𝑦1,𝑦2,…,𝑦𝑛是矢量𝑦⃗.的分量或系数我们可以看到,𝑦⊺λ𝑦= 1 看起来像一个椭球的方程。我们可以将这个等式改写为:

这个方程明确地表示了一个椭球体,其中 1/√𝜆1,1/√𝜆2,… 1/√𝜆𝑛是主轴长度的一半。

回到我们的例子,𝐴 = [[5,4],[4,5]],𝐴的特征值是 1 和 9。将它们代入上述方程,我们得到 y1 + 9y2 = 1,这就是我们的椭圆方程。让我们画出这个:

+= 1

我们可以看到主轴的长度是 0.66 和 2,也就是 2 * 1/√𝜆1 和 2 * 1/√𝜆2.

接下来,让我们从特征向量基转换回标准的欧几里德基。转换到我们乘以𝑄⊺的特征向量基。为了从特征向量基转换回来,我们乘以𝑄⊺的逆,也就是𝑄.

𝑦⃗ = 𝑄⊺𝑥⃗ ⟹ 𝑥⃗ = 𝑄𝑦⃗

𝐴的特征向量的归一化形式为[-1/√2,1/√2]和[1/√2,1/√2]。所以𝑄的特征向量矩阵是:

请注意,这些列是正交的。我们将上面椭圆上的每一点乘以𝑄,然后像这样绘制变换后的点:

注意特征向量是如何沿着椭圆的主轴的。我们可以说拉伸的方向是沿着矩阵的特征向量,这些特征向量是椭圆的主轴。如果一个点沿着具有最大特征值的特征向量,它将被拉伸到最大,如果它沿着具有最小特征值的特征向量,它将被拉伸到最小。

正定矩阵的这个性质有一个重要的应用,我们将在相机校准中使用。

在此之前,有一个重要的定理你需要知道:如果𝐴是任意一个矩形矩阵,那么𝐴⊺𝐴就是一个正定矩阵。

设𝐴是一个形状为𝑚 x 𝑛的矩形矩阵,我们想找出|𝐴𝑥⃗|的最小值,其中𝑥⃗是任何大小为𝑛的向量,|𝐴𝑥⃗|代表𝐴𝑥⃗.的大小让我们看看如何计算:

We want to find the minimum value of |𝐴𝑥⃗|,
which is the same as finding the minimum value of |𝐴𝑥⃗|².
Now, |𝐴𝑥⃗|² can be written as (𝐴𝑥⃗)⊺(𝐴𝑥⃗),
which in turn can be written as 𝑥⃗⊺𝐴⊺𝐴𝑥⃗.
Now, 𝑥⃗⊺𝐴⊺𝐴𝑥⃗ = 𝑥⃗⊺(𝐴⊺𝐴)𝑥⃗  (associative property of Matrices),
But remember, 𝐴⊺𝐴 is a positive definite matrix.
⟹ 𝑥⃗⊺(𝐴⊺𝐴)𝑥⃗ = 1 represents an ellipsoid with the 
eigenvectors of 𝐴⊺𝐴 along the principal axes.
So the direction of minimum stretching will be along 
the eigenvector of 𝐴⊺𝐴 with the smallest eigenvalue.

因此,如果𝑥⃗沿着𝐴⊺𝐴的具有最小特征值的特征向量,那么|𝐴𝑥⃗|将是最小的。

结论

我希望你喜欢这篇文章。这篇文章的代码可以在这里找到。在的下一篇文章中,我们将执行摄像机校准。如果你有任何疑问或问题,请在下面的评论中告诉我。

参考

  1. 吉尔伯特·斯特朗的线性代数讲座

图像制作者名单

本文中的所有图片和数字,除非在标题中明确提及其来源,否则均由作者提供。

查找 ARIMA 模型的顺序

原文:https://towardsdatascience.com/find-the-order-of-arima-models-b4d99d474e7a

了解并找到时间序列基本建模的最佳参数

图片由 @m_____me

ARIMA 是开始单变量时间序列实验的最佳模型之一。它提供了最先进的性能,特别是在小数据集的情况下,深度学习模型尚未处于最佳状态。

这是一个简单的,可解释的模型,但 ARIMA 是一个参数模型。这意味着在拟合模型之前需要设置特定的参数。事实上,模型的自回归、移动平均和平稳部分分别需要参数 p、q 和 d

在本文中,您将了解这些参数是什么,以及如何使用 ACFPACF 图BIC/AIC 信息标准找到最佳参数

了解 ARIMA 车型

首先,我们需要对这些模型有个基本的了解。

时间序列中“线性回归”或“经典模型”的等价物是 ar 和 MA。这些基本模型通常表现良好。它们是可解释的、轻量级的,是开始任何数据科学项目的良好基础。

ARMA 模型有一个严重的限制。它假设输入数据是稳定的(时间序列的均值和方差不依赖于时间序列被观察的时间)。如果您的数据是非平稳的,您可以使用 AR I MA 模型,其中 I 代表“集成的”。积分部分说明了“微分”,这是一种去除趋势并使时间序列平稳的方法。

1)自回归模型

订单 pAR 是一个回归自身 p 过去值的模型。换句话说,系列 Vt 的当前值可以解释为 p 个过去值与随机误差的线性组合。我们假设下一个值与前 p 个值相关。用于预测下一个值的先前输入的数量被称为“顺序”。我们通常称之为“p”。这些用来计算下一个值的先验值被称为“滞后变量”。

作为滞后变量线性组合的 Vt 方程为:

AR(p):Vt = ao+a1V { t-1 }+…+apV { t-p }+Nt。

当我们拟合 AR 模型时,我们在[0,p]中估计 I 的{ai}。 Nt 是一个白噪声过程(我们称之为“白噪声过程”是一系列均值为 0、方差恒定且误差不相关的随机值)和 ao 均值。

比如,当 p=3 时,为了预测下一个时间戳(和时间序列均值 a0),我们代入最后三个值,分别乘以系数 a1,a2,a3。

您可以看到如何使用下面的代码片段模拟订单 p 的 AR 模型:

该模型将以下内容作为输入:

  • 随机变量的实现列表 V
rand_v_list = np.random.normal(size=N)
  • p 系数列表{ao,…,ap}。

模拟的 AR 模型是将 V 的 p 个连续值乘以其 p 个系数来创建一个时间序列。

我们的目标是:给定一个模拟的 AR 时间序列,如何找到 p,用来生成它的参数?

2)移动平均模型

移动平均模型利用观测值和应用于滞后观测值的移动平均的残差之间的相关性。换句话说,将预测值建模为到 q 步的过去误差项的线性组合。误差或残差定义为 res =预测值-真值。

它利用回归方法中以前的预测误差来预测未来的观测值。在这种情况下,每个未来观测值都是以前预测误差的加权平均值。

MA(q):Et = B0+B1 * Et-1+…+BP * Et-q+Nt

我们估计{bi}在[0,q]中,Nt 是白噪声(均值为 0 且方差有限的不相关随机变量的集合)。

如果残差和预测值之间仍然存在相关性,这意味着我们仍然可以从误差中获得信息。实际上,我们可以认为误差是随机的。MA 过程只是来自白噪声过程的值 E 的加权组合。

您可以通过下面的代码片段看到该模型是如何工作的:

该模型采用与 ar 流程相似的输入。

3) ARMA

自回归移动平均 ARMA (p,q)结合了 AR (p)和 MA (q)过程,考虑了时间序列的滞后或过去值以及误差项。它是平稳时间序列最有效的线性模型[1]。

4) ARIMA

当输入数据不稳定时,用一个自回归综合移动平均代替 ARMA 模型。

在 ARIMA,积分部分将时间序列“固定化”[2]。当积分的阶数为 d=0 时,ARIMA 的行为类似于 ARMA 模型。当 d=1 时,模型将从 t 处观察到的值中减去 t-1 值。当数据中存在长期趋势时,您可以添加微分。术语综合指的是建模的时间序列必须不同多少次才能产生平稳性。

当你使用 ARIMA 模型时,不要手动进行微分,你可以直接在非平稳时间序列上拟合 ARIMA 模型。

图片由 @tezos

分析

现在我们了解了这些过程是如何工作的,以及它们的顺序意味着什么,让我们看看如何在实践中找到参数。为了分别找到模型的 AR、integrated 和 MA 部分的参数 p、d 和 q,我们可以使用:

  • ACFPACF 剧情。
  • 领域知识
  • 各种适合的度量标准 (BIC,AIC)

我们提醒 p 是模型中滞后观测值的数量(也称为滞后阶数),d 是原始观测值的差分次数,q 是移动平均窗口的大小。

我们将在下一节介绍如何使用 ACF、PACF 图、BIC 和 AIC 标准。

自相关函数

时间序列过程的一个重要方面是自相关。自相关是一种统计属性,当一个时间序列与其自身的先前版本或滞后版本线性相关时,就会出现自相关。它还用于检测时间序列中可能的季节性。

我们使用自相关函数来评估时间序列中的依赖程度,并选择适当的模型(MA、AR 或 ARIMA)。

自相关函数( ACF)和偏自相关函数 (PACF)可以针对任何时间序列(不仅仅是平稳的)进行计算。

在实践中,我们使用这两个图的组合来确定 ARMA 过程的顺序。

我如何知道我的时间序列遵循哪个过程?

通用流程:

  • ARIMA(0,0,0)是一个白噪声模型。(Vt=Nt)
  • ARIMA(0,1,0)是随机游走(Vt-V{t-1}=c+Nt,c 是均值)
  • ARIMA(0,1,1)指数平滑法

但是除了常见的模式之外,我们使用 PACF 和 ACF 图来可视化要识别的模式:

过程识别表。作者图片

在下图中,我们展示了阶为 1 的 AR、MA 或 ARMA 过程中 ACF 和 PACF 的行为。如果你的时间序列是 AR 或 MA 或 ARMA,你可以很容易地使用这个表来识别任何订单。在 AR 或 MA 过程的情况下,您可以计算图表中突然下降的峰值数量。在 ACF 和 PACF 中,0 阶滞后总是等于 1(该值与其自身完全相关),因此我们在第一个峰值后开始计数。

1) ACF

我们使用自相关函数 ACF 来了解时间序列与其滞后值的相关程度。

我们使用 ACF 来标识 ARMA 模型的 MA(q) 部分。

事实上,我们确定哪个滞后变量与产出有很强的相关性。这些滞后变量对时间序列的下一个值有很强的预测能力,应该用于预测。

在实践中,我们计算与输出值有显著自相关的滞后数,以找到 MA 模型的 q 值。

让我们针对 500 个模拟随机观察值,模拟顺序为 q=1、q=3、q=5 和 q=7 的四个 MA 过程。

绘制这四个不同的模拟数据:

顺序递增的不同 MA 过程。作者图片

现在,让我们用 ACF 和 PACF 图绘制 MA(q=5)模拟数据。

在右图中,我们可以看到 PACF 图上的阻尼下降(正的和负的)。即使在滞后 10 年之后,滞后仍然很明显。而在左侧的 ACF 图上,在 1+5 个显著滞后之后,所有随后的滞后都不显著。我们可以看到一个并购过程。

为了找到 q,我们可以计算 ACF 图上显著滞后的数量(蓝带之外)。除了第一个滞后对应于值与其自身的相关性之外,我们可以看到与序列的接下来 5 个滞后的相关性。

ACF 和 PACF 用于 MA(q=5)。我们可以在 ACF 中读取 5 个显著或“高”峰,左图。作者图片

2) PACF

直觉

偏自相关函数(PACF) 表示在我们考虑一些其他变量集合的值的假设下,两个变量之间的相关性。在回归中,这种部分相关性可以通过关联两个不同回归的残差来找到。

我们使用 PACF 来寻找残差与下一个滞后的相关性。如果我们发现残差和下一个滞后中隐藏的信息具有合理的相关性,我们将使用下一个滞后作为建模的特征。

换句话说,目标时间戳和先前时间戳之间的自相关值由两个值之间的直接相关性加上间接相关性组成。我们认为这些间接相关性是观察值相关性的线性函数。

我们可以使用 PACF 来计算 AR 流程中显著滞后的数量。

实验

首先让我们模拟 p=1,p=3,p=5,p=7 的移动平均 AR。

订单可变的不同 AR 流程。作者图片

我们可以在上面的图中看到,随着 p 的增加,我们也增加了时间序列的振荡性质。当时间序列增长过快时,自回归分量会产生一种自然趋势,使其回到平均值。现在它在平均值 0 附近振荡,但也可能是任何值。因为时间序列既取负值也取正值,所以 ACF 和 PACF 图也取正值和负值。

现在我们可以画出这些 AR 过程的 ACF 和 PACF 函数,并读出显著滞后的数目作为 p 的值

ACF 和 PACF 用于 AR(p=7)。我们可以在右边的 PACF 图上看到七个重要的峰值。图片由作者提供。

3) AIC/BIC 标准

绘制 ACF/PACF 对于识别 AR 和 MA 过程是有效的。但是对于 ARIMA 进程,更常见的是使用 auto_arima 函数。Auto arima 是一种强力方法,它尝试不同的 p 和 q 值,同时最小化两个标准:AIC 和 BIC。

评估正则化拟合优度的最常见度量是:

  • 贝叶斯信息准则(BIC)
  • 赤池信息标准(AIC)。

这些度量提供了考虑模型复杂性的模型性能的度量。AIC 和 BIC 将一个反映模型与数据拟合程度的术语与一个根据参数数量按比例惩罚模型的术语结合起来[3]。

作为一种正则化技术,我们希望根据模型中参数的数量进行惩罚。事实上,p 和 q 越大,你用来预测下一个值的延迟就越多,你就越有可能过度拟合你的数据。

自动 ARIMA 过程旨在确定一个**ARIMA**模型的最佳参数,确定一个单一的拟合 ARIMA 模型。[…]

为了找到最佳模型,自动 ARIMA 为给定的**information_criterion**(分别为‘AIC’,‘aicc’,‘BIC’,‘hqic’,‘OOB’)(Akaike 信息标准、修正的 aka ike 信息标准、贝叶斯信息标准、Hannan-Quinn 信息标准或“出袋”–用于验证评分)之一进行优化,并返回使值最小化的 ARIMA。

在实践中,我们使用现成的工具 auto_arima 从包 pmdarima 中自动找到时间序列的顺序。

让我们尝试 auto_arima 来找出我们模拟的几个 ma 过程的顺序:

q=1
Performing stepwise search to minimize aic
 ARIMA(0,0,0)(0,0,0)[0] intercept   : AIC=1605.796, Time=0.01 sec
 ARIMA(1,0,0)(0,0,0)[0] intercept   : AIC=1493.552, Time=0.03 sec
 ARIMA(0,0,1)(0,0,0)[0] intercept   : AIC=1461.981, Time=0.03 sec
 ARIMA(0,0,0)(0,0,0)[0]             : AIC=1604.553, Time=0.01 sec
 ARIMA(1,0,1)(0,0,0)[0] intercept   : AIC=1463.723, Time=0.05 sec
 ARIMA(0,0,2)(0,0,0)[0] intercept   : AIC=1463.755, Time=0.05 sec
 ARIMA(1,0,2)(0,0,0)[0] intercept   : AIC=1465.600, Time=0.13 sec
 ARIMA(0,0,1)(0,0,0)[0]             : AIC=1460.398, Time=0.02 sec
 ARIMA(1,0,1)(0,0,0)[0]             : AIC=1462.121, Time=0.03 sec
 ARIMA(0,0,2)(0,0,0)[0]             : AIC=1462.155, Time=0.02 sec
 ARIMA(1,0,0)(0,0,0)[0]             : AIC=1491.861, Time=0.01 sec
 ARIMA(1,0,2)(0,0,0)[0]             : AIC=1463.988, Time=0.06 sec

Best model:  ARIMA(0,0,1)(0,0,0)[0]          
Total fit time: 0.468 seconds
Optimal order for is: (0, 0, 1) 

q=3
Performing stepwise search to minimize aic
 ARIMA(0,0,0)(0,0,0)[0] intercept   : AIC=1702.731, Time=0.01 sec
 ARIMA(1,0,0)(0,0,0)[0] intercept   : AIC=1570.816, Time=0.03 sec
 ARIMA(0,0,1)(0,0,0)[0] intercept   : AIC=1628.147, Time=0.04 sec
 ARIMA(0,0,0)(0,0,0)[0]             : AIC=1701.862, Time=0.01 sec
 ARIMA(2,0,0)(0,0,0)[0] intercept   : AIC=1528.848, Time=0.04 sec
 ARIMA(3,0,0)(0,0,0)[0] intercept   : AIC=1519.618, Time=0.06 sec
 ARIMA(4,0,0)(0,0,0)[0] intercept   : AIC=1485.096, Time=0.06 sec
 ARIMA(4,0,1)(0,0,0)[0] intercept   : AIC=1484.876, Time=0.11 sec
 ARIMA(3,0,1)(0,0,0)[0] intercept   : AIC=1509.277, Time=0.13 sec
 ARIMA(4,0,2)(0,0,0)[0] intercept   : AIC=1464.510, Time=0.17 sec
 ARIMA(3,0,2)(0,0,0)[0] intercept   : AIC=1465.074, Time=0.15 sec
 ARIMA(4,0,3)(0,0,0)[0] intercept   : AIC=1465.187, Time=0.28 sec
 ARIMA(3,0,3)(0,0,0)[0] intercept   : AIC=1464.135, Time=0.20 sec
 ARIMA(2,0,3)(0,0,0)[0] intercept   : AIC=1462.726, Time=0.23 sec
 ARIMA(1,0,3)(0,0,0)[0] intercept   : AIC=1462.045, Time=0.17 sec
 ARIMA(0,0,3)(0,0,0)[0] intercept   : AIC=1460.299, Time=0.09 sec
 ARIMA(0,0,2)(0,0,0)[0] intercept   : AIC=1507.915, Time=0.06 sec
 ARIMA(0,0,4)(0,0,0)[0] intercept   : AIC=1462.121, Time=0.09 sec
 ARIMA(1,0,2)(0,0,0)[0] intercept   : AIC=1467.963, Time=0.08 sec
 ARIMA(1,0,4)(0,0,0)[0] intercept   : AIC=1463.941, Time=0.23 sec
 ARIMA(0,0,3)(0,0,0)[0]             : AIC=1458.689, Time=0.12 sec
 ARIMA(0,0,2)(0,0,0)[0]             : AIC=1506.487, Time=0.03 sec
 ARIMA(1,0,3)(0,0,0)[0]             : AIC=1460.415, Time=0.11 sec
 ARIMA(0,0,4)(0,0,0)[0]             : AIC=1460.498, Time=0.04 sec
 ARIMA(1,0,2)(0,0,0)[0]             : AIC=1466.278, Time=0.07 sec
 ARIMA(1,0,4)(0,0,0)[0]             : AIC=1462.305, Time=0.11 sec

Best model:  ARIMA(0,0,3)(0,0,0)[0]          
Total fit time: 2.717 seconds
Optimal order for is: (0, 0, 3) 

q=5
Performing stepwise search to minimize aic
 ARIMA(0,0,0)(0,0,0)[0] intercept   : AIC=1659.497, Time=0.01 sec
 ARIMA(1,0,0)(0,0,0)[0] intercept   : AIC=1570.804, Time=0.03 sec
 ARIMA(0,0,1)(0,0,0)[0] intercept   : AIC=1613.884, Time=0.03 sec
 ARIMA(0,0,0)(0,0,0)[0]             : AIC=1658.949, Time=0.01 sec
 ARIMA(2,0,0)(0,0,0)[0] intercept   : AIC=1495.855, Time=0.04 sec
 ARIMA(3,0,0)(0,0,0)[0] intercept   : AIC=1482.804, Time=0.05 sec
 ARIMA(4,0,0)(0,0,0)[0] intercept   : AIC=1484.509, Time=0.07 sec
 ARIMA(3,0,1)(0,0,0)[0] intercept   : AIC=1484.564, Time=0.11 sec
 ARIMA(2,0,1)(0,0,0)[0] intercept   : AIC=1484.926, Time=0.07 sec
 ARIMA(4,0,1)(0,0,0)[0] intercept   : AIC=1486.509, Time=0.15 sec
 ARIMA(3,0,0)(0,0,0)[0]             : AIC=1481.204, Time=0.03 sec
 ARIMA(2,0,0)(0,0,0)[0]             : AIC=1494.160, Time=0.02 sec
 ARIMA(4,0,0)(0,0,0)[0]             : AIC=1482.892, Time=0.03 sec
 ARIMA(3,0,1)(0,0,0)[0]             : AIC=1482.953, Time=0.05 sec
 ARIMA(2,0,1)(0,0,0)[0]             : AIC=1483.270, Time=0.03 sec
 ARIMA(4,0,1)(0,0,0)[0]             : AIC=1484.892, Time=0.08 sec

Best model:  ARIMA(3,0,0)(0,0,0)[0]          
Total fit time: 0.824 seconds
Optimal order for is: (3, 0, 0) 

q=7
Performing stepwise search to minimize aic
 ARIMA(0,0,0)(0,0,0)[0] intercept   : AIC=2171.867, Time=0.01 sec
 ARIMA(1,0,0)(0,0,0)[0] intercept   : AIC=1789.289, Time=0.03 sec
 ARIMA(0,0,1)(0,0,0)[0] intercept   : AIC=1931.174, Time=0.04 sec
 ARIMA(0,0,0)(0,0,0)[0]             : AIC=2172.420, Time=0.01 sec
 ARIMA(2,0,0)(0,0,0)[0] intercept   : AIC=1788.083, Time=0.04 sec
 ARIMA(3,0,0)(0,0,0)[0] intercept   : AIC=1779.499, Time=0.07 sec
 ARIMA(4,0,0)(0,0,0)[0] intercept   : AIC=1778.438, Time=0.07 sec
 ARIMA(4,0,1)(0,0,0)[0] intercept   : AIC=1773.792, Time=0.26 sec
 ARIMA(3,0,1)(0,0,0)[0] intercept   : AIC=1780.497, Time=0.10 sec
 ARIMA(4,0,2)(0,0,0)[0] intercept   : AIC=1695.057, Time=0.32 sec
 ARIMA(3,0,2)(0,0,0)[0] intercept   : AIC=1738.073, Time=0.35 sec
 ARIMA(4,0,3)(0,0,0)[0] intercept   : AIC=1691.378, Time=0.51 sec
 ARIMA(3,0,3)(0,0,0)[0] intercept   : AIC=1711.992, Time=0.25 sec
 ARIMA(4,0,4)(0,0,0)[0] intercept   : AIC=1694.119, Time=0.72 sec
 ARIMA(3,0,4)(0,0,0)[0] intercept   : AIC=1701.593, Time=0.27 sec
 ARIMA(4,0,3)(0,0,0)[0]             : AIC=1689.749, Time=0.27 sec
 ARIMA(3,0,3)(0,0,0)[0]             : AIC=1710.347, Time=0.19 sec
 ARIMA(4,0,2)(0,0,0)[0]             : AIC=1693.396, Time=0.15 sec
 ARIMA(4,0,4)(0,0,0)[0]             : AIC=1692.698, Time=0.49 sec
 ARIMA(3,0,2)(0,0,0)[0]             : AIC=1736.557, Time=0.16 sec
 ARIMA(3,0,4)(0,0,0)[0]             : AIC=1699.989, Time=0.16 sec

Best model:  ARIMA(4,0,3)(0,0,0)[0]          
Total fit time: 4.481 seconds
Optimal order for is: (4, 0, 3)

我们对订单 1、3、5 和 7 的 ma 过程使用 auto arima。对于小订单 q=1 和 q=3,Auto_arima 准确地识别 ma 过程及其订单,但是对于订单 q=5 和 q=7,它混合了 AR 和 MA。

结论

当您开始时间序列分析时,从可能满足用例需求的简单模型开始是一个好的实践。ARIMA 模型简单而透明,你可以推导出严格的统计特性。它们在小数据集上表现良好,构建和重新训练都很便宜。

如果您需要使用它们,您需要了解它们是如何工作的,并明确地设置它们的参数。本文为您提供了充分自信地调整模型顺序的技术。

本文笔记本可用 此处

参考资料:

[1]使用 Python 进行时间序列分析:从基础到前沿技术https://www . Amazon . com/Hands-Time-Analysis-Python-Techniques/DP/1484259912(非附属)

[2]https://people . cs . Pitt . edu/~ Milos/courses/cs 3750/lectures/class 16 . pdf

[3][https://www . science direct . com/topics/psychology/Bayesian-information-criterion #:~:text = The % 20 a kaike % 20 information % 20 criterion % 20(AIC,to % 20 its % 20 number % 20 of % 20 parameters。](https://www.sciencedirect.com/topics/psychology/bayesian-information-criterion#:~:text=The Akaike information criterion (AIC,to its number of parameters.)

查找数据库中排名靠前且最慢的查询

原文:https://towardsdatascience.com/find-the-top-n-most-expensive-queries-48e46d8e9752

找到降低数据库处理速度的瓶颈查询

在这篇文章中,我们将寻找慢速查询(图片由 Nicolai Dürbaumunsplash 上提供)

当您的数据库增长时,很容易失去对它正在执行的所有进程的跟踪。跟踪阻碍操作的缓慢查询不是很好吗?

在本文中,我们将创建一个查询,为您提供分析和优化数据库所需的所有工具:它选择有问题的查询,提供这些查询的相关信息,并为您提供查找和改进它们的方法。阅读本文后,您将能够揭示前 n 个查询以及每个查询的信息:

  • 在哪个数据库和对象中查找查询(例如在Coffee数据库中的FreshPot存储过程中)
  • 实际的查询本身
  • 查询计划
  • 创建和最后执行的时间
  • 执行次数
  • 返回的行数的总数、最小值、最大值和平均值、运行时间和 CPU 时间

注意,本文分析了 SQL Server 数据库,但是类似的功能也存在于 Postgres 数据库中。查看本文中关于 Postgres 数据库中所有查询的统计数据。

搜寻慢速查询

我们将编写一个查询,提供哪些查询速度慢的信息,并为我们提供分析查询的工具。那我们可以

  1. 检测:哪些查询有问题?
  2. 丰富:增加更多信息,让我们了解缓慢的原因
  3. 分析:在哪里可以找到查询,问题出在哪里?
  4. 优化:我们如何进一步改进我们的查询和数据库?

完整查询可在本文底部这里 。注意,我们将要使用的一些视图需要VIEW DATABASE STATE的许可。

1.查找有问题的查询

在第一部分中,我们使用 CTE 来选择我们感兴趣的查询。我们想从sys.dm_exec_query_stats获取一些数据;这将跟踪 SQL Server 中缓存查询计划的性能统计信息。

这里的目标是选择我们感兴趣的记录。在本例中,我们选择的记录是新的(自上次执行后不到 30 天)和频繁使用的(在过去 30 天内超过 100 次)。我们不介意很少执行的慢速查询。接下来,我们按照平均 CPU 时间对查询进行排序,然后返回前 10 个最慢的查询。

当然,我们可以根据许多标准进行筛选:

  • 执行时间变化很大的记录(例如,最小和最大 CPU 时间相差很大)
  • 运行时间和 CPU 时间(CPU 实际执行的时间)相差很大的记录;可能查询浪费了很多等待的时间)
  • 按返回的 avg_rows 或总 cpu 时间排序。

有些虫子伪装得很好(图片由 id23Unsplash 上拍摄)

2.提供有关查询的更多信息

在上一部分中,我们选择了频繁执行且执行时间很长的查询;这些是我们的问题查询。这一部分的目标是尽可能多地收集关于这些查询的相关信息。让我们看一下代码

上面的代码很长,但它只做了几件事:

  • 使用第 34 行的视图sys.dm_exec_sql_text添加实际的 SQL 语句(并清除第 21 到 31 行的语句)
  • 使用视图sys.dm_exec_query_plan添加查询计划(第 35 行)
  • 使用视图sys.dm_exec_plan_attributes获取我们稍后需要的数据库 id 和对象 id。在第 37 到 41 行中,我们将 dbid 和 objectid 记录从行转换为列,这样我们可以更容易地在第 36 行交叉应用它们。

这是输出(带有匿名声明文本):

我们的数据库分析语句的输出(不是所有的列都适合,但最重要的列在这里,图片由作者提供)

3.分析我们的问题查询

我们现在可以开始分析查询;以下是一些建议:

  1. 检查 cpu 时间和运行时间之间的差异;可能查询等了很多?
  2. 检查最小和最大 cpu 和执行时间之间的差异;也许将某些作业安排在晚上服务器有更多可用内存的时候?
  3. 分析语句文本(格式化 vscode 中的 sqlcntrl - shift - pformat document withsql
  4. 单击并签出 query_plan

一旦您发现了问题或改进查询的机会,我们需要找到查询的位置。我们已经有了数据库名称;让我们找到查询所在的对象的名称(例如,在存储过程中)。我们可以通过在下面的查询中插入db_nameobjectid 来做到这一点:

SELECT * FROM CoffeeDB.sys.objects WHERE object_id = 808389949

这将告诉您我们正在寻找的对象的类型和名称。例如:

现在我们可以在 CoffeeDB 中搜索一个名为‘My _ Stored _ Procedure’的存储过程,并加快查询速度!

4.进一步优化

查看一下 这些文章 来改善你的查询,尤其是 这一条

随着所有拥塞的消失,我们的数据库进程再次自由流动(图片由 Alexander Schimmeckunsplash 上提供)

结论

通过这篇文章,您将完全有能力优化您的数据库!我们已经了解了代码的工作原理以及如何使用它,现在是时候将它应用到您的情况中了。查看 完整查询此处

如果你有建议/澄清,请评论,以便我可以改进这篇文章。同时,看看我的其他关于各种编程相关主题的文章,比如:

编码快乐!

—迈克

页(page 的缩写)学生:比如我正在做的事情?跟我来!

**https://mikehuls.medium.com/membership **

发现数学背后的美

原文:https://towardsdatascience.com/finding-beauty-behind-all-the-math-844c8e39472d

作者聚焦

Hannah Roos 如何利用她的数据科学、商业和心理学背景帮助人们解决数据问题

在 Author Spotlight 系列中,TDS 编辑与我们社区的成员谈论他们在数据科学领域的职业道路、他们的写作以及他们的灵感来源。今天,我们很高兴与 汉娜·鲁斯 分享我们的对话。

Hannah Roos是一位热衷于数据科学的心理学家。受她在管理咨询和行为科学领域工作的启发,她撰写了动手编程教程,并深入研究了 R 和 Python。她被积极弥合循证研究和商业世界之间的鸿沟的使命所驱使。

你进入数据科学的切入点是什么?

在我的心理学学士学位期间,我们被告知对研究问题采取合理的方法的重要性,特别是在“软”科学中,这让我对大多数学生最害怕的部分感兴趣:统计和假设检验。

我意识到,我们的大脑可能无法直观地理解这些事情,但这实际上激发了我的雄心:我想了解如何通过数据解决问题。

你如何处理这个领域中更难的话题?

我喜欢数据科学具有挑战性的方面,因为一旦你经过长时间的深思熟虑和努力工作后掌握了一项任务,你会有一种巨大的成就感,你最终会看到所有数学背后的美。

在我的研究结束时,我担任视觉认知实验的研究助理。我所有的同事似乎都更擅长编程和复杂的数据分析:这可能是我旅程中特别具有挑战性的部分。似乎他们可以进入一个充满逻辑思想的平行世界,而且他们有合适的词汇来辩论它们。但在那个阶段,这个世界不知何故对我关闭了。也许我根本就不是为这个而生的?

但是我不再关注我是否“足够聪明”,而是继续学习变得越来越熟练。到目前为止,我已经完成了 60 多门关于 Datacamp 的课程,扩展了我关于 R、Python 和 SQL 的知识,以及统计学和机器学习中的常见概念。

读你的文章,你会感觉到你的心理学背景经常影响你的工作。

是啊,那是真的!作为一名心理学家,我总是试图通过数据来找出是什么让人们滴答作响,这不是一项简单的任务。

我对发生在心理学和商业世界之间的实际问题有一种感觉,这些真的激发了我的写作。例如,我最近写了一篇关于使用 AI 预测公司员工流动率的文章。当然,你可以建立一个机器学习算法,将员工分为 1)面临离职风险的员工和 0)可能留下的员工。但老实说,影响一个人在特定公司工作的动机有很多方面,这使得很难超越样本内预测进行概括——例如,与你的主管的关系、市场动态、学习机会……所有这些都可能在相对较短的时间内发生变化。那么,你如何在实践中准确预测如此复杂的决策呢?

虽然我相信在现实世界中使用数据来推动决策,但我认为我们也需要使用我们的常识和领域知识。这就是我们如何自信地说数据能告诉我们关于未来的什么,以及它不能告诉我们什么。

通过数据工作,你最想解决哪类问题?

我喜欢专注于数据的项目,这些项目完美地满足了我作为一名科学家以及广大公众的好奇心。总的来说,我想更深入地研究一下心理测试,也就是说,使用统计学来改进测量我们无法直接测量的特征(例如,性格)的方法。这有可能告诉你一些关于人们如何在一个非常深刻的层面上不同的事情。

目前,我正在分析 2020 年 COVID 爆发早期的心理影响数据——这就是为什么我的下一篇文章将包括时间序列分析和 Python 编码示例的方面。从更广泛的角度来看,我对跨时间的分析感兴趣,以调查变化和发展。

是什么促使你开始公开写你的工作和其他数据相关的话题?

我开始写关于 p 值和进行假设检验的真正含义。这是因为我意识到我已经错了很长一段时间,并且感觉学生和专业人士对这个概念仍然有很多误解。我想分享“啊哈!”我终于和其他同样在挣扎的人有了这样的时刻:如果我能写一篇文章,让人们更容易理解,会怎么样?

我喜欢写与数据相关的话题,因为从事我热爱的事情令人惊叹,但我也想生活在一个可以免费分享知识的世界里。希望我能以这种方式为这样一个世界做出贡献。

作为一名作家,看起来你已经有意识地选择了追求彻底性和深度,而不是产量。你的文章背后的流程是什么样子的?

我想对一个问题提供一个完整和整体的观点,而不是匆忙地通过编程部分。通常,我会从一个我想更深入理解的概念开始——比如说贝叶斯统计或结构方程建模。然后,我开始阅读一些科学论文,并寻找一个公共数据集,我可以用它来进行并行实验。

一旦我觉得我已经从我的学习项目中获得了一些关键的见解,一个好的用例,以及一个其他人也可以从中受益的有效的编码方法,我实际上就开始写作了。为了使它更容易,我从一个包含我想提出的关键点的普通 word 文件上的项目符号开始,然后一步一步地用一个连贯的文本替换它。

你有什么实用的建议给那些想把自己的工作写下来的数据科学家吗?

对于初学者,我会说你不需要用你的文章证明什么。也许只是探索一个有趣的话题,并写下你的见解。想象一下,你会把这些告诉你的朋友,他实际上并不太关心数据科学,但仍然礼貌地听你说。问问你自己:我能激发一点兴趣吗?如果是这样,你可能有一个好故事要讲。如果没有,你至少有你自己的发现之旅。

数据科学是一个不断变化的领域,你希望在未来几个月或几年看到什么特别的变化吗?

我希望看到数据科学变得更加包容,让每个人都可以使用,而不是询问来自行业和学术界的专家,我认为每个人都应该有机会成为这样的专家,并从数据中获得自己的见解。

希望像“人工智能”这样的术语不会引发一种不祥的黑匣子的想法,这种黑匣子利用我们的个人信息来赚取更多的利润——在理想的未来,来自更广泛公众的人们最终会理解算法如何工作,以评估它们在多大程度上可能是有益的。

对于更广阔的技术世界,我希望看到单调乏味的工作流程实现更多自动化,这样人们就可以更多地关注对他们真正重要的事情。我相信,一些科技初创公司已经有了与数据相关的伟大创新,能够彻底改变我们的生活方式,让我们成为更加自主的个体——如果以深思熟虑的方式设计和使用的话。

您可以通过媒体跟踪 Hannah,了解她的最新作品;为了体验 Hannah 过去的 TDS 深潜和教程,这里有一些亮点:

想和广大观众分享一些你自己的作品吗?我们很乐意收到你的来信。

这个 Q & A 是为了长度和清晰而稍加编辑的。

posted @ 2024-10-18 09:29  绝不原创的飞龙  阅读(361)  评论(0)    收藏  举报