TowardsDataScience-博客中文翻译-2021-四十三-

龙哥盟 / 2024-10-22 / 原文

TowardsDataScience 博客中文翻译 2021(四十三)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

从埃隆·马斯克的推特图中我们能学到什么?

原文:https://towardsdatascience.com/graph-mining-2dd6c4c1f1b1?source=collection_archive---------20-----------------------

只有几行代码的图形挖掘

图形挖掘允许我们从任何给定的实体集合中收集数据并构建节点和边的图表。像 Louvain method 或 PageRank 这样的算法提供了有意义的工具来分析经过挖掘和构建的图。这篇文章用几行 Python 代码描述了构建图表的过程。

图表分析是一个令人难以置信的令人兴奋和快速发展的数据分析领域。它从社区检测延伸到其他复杂的任务,如模式识别。Graph analytics 也可以被视为使搜索引擎巨头能够将额外的相互关联的结果维度添加到您的搜索结果中的动力之一(基本上,他们依赖于所谓的知识图)、在您的手机上弹出的相关每日新闻或您最喜欢的在线商店的购买推荐。

附带说明:谷歌的搜索是基于以前开发的 Freebase,虽然已经停止,但是仍然可以部分访问——链接这里。

虽然有许多算法可用于分析,但当想到图形时,Louvain 方法和 PageRank 可能是人们首先想到的算法。Louvain 方法允许检测各种网络中的社区,而 PageRank(以 web pages 命名,而不是其共同发明人和谷歌联合创始人拉里·佩奇)发现了在整个图中的节点之间随机跳跃时到达节点的稳态概率(马尔可夫链)——后者可能是该科学领域最知名的算法,因为它被视为谷歌搜索的基础工作。

另一种流行的分析方法是查看通过大量三角形连接来表征的图表。找到这样的图表是一个现实世界的问题,猎头、社交媒体和营销专家可能会特别感兴趣。

“三角形计数在社交网络分析中变得流行起来,它被用来检测社区并测量这些社区的凝聚力。它还可以用来确定一个图的稳定性,并经常被用作计算网络指数的一部分,如聚类系数— Neo4j

一篇令人难以置信的来自斯坦福大学的 6 页论文可以在本文最后的附录中找到。在你的程序中集成三角形计数的一个简单方法在这里解释:

起点

为了给这种分析提供有意义的数据,本文允许您遵循几个简单的步骤从 Twitter 中挖掘真实世界的图表。下面显示的函数从“根节点”埃隆马斯克开始,迭代他的追随者,追随者的追随者,等等。

如果你想使用自己的帐户作为起点,你需要先获得你的起始 ID。这不能通过前端完成,但是 Twitter 的 GitHub 上有一个简单的脚本(用户查找)可以帮助你。

与 Elon 的直接联系 Argo Lite 中作者提供的图片

对于这个项目,我使用了 Elon 的跟随。使用 follows 是有意义的,因为我们想探索 Elon 的网络,而不是 Elon 只是其中一部分的其他人的网络。这个逻辑同样适用于所有其他节点——我们只关心关注者,不关心关注者。要知道,通过 Twitter 收集节点需要相当长的时间,因此,图中所示只是 Elon 整个网络的一小部分。“埃隆·马斯克图表”可以通过简单地点击节点来可视化地浏览 ( 链接)——拖动它们以更好的方式组织它们。节点大小被表征为具有较高的 PageRank 值,这也通过着色来表达。较暗(蓝色)的颜色表示较高的 PageRank 分数,黄色、较亮的颜色表示较低分数的节点。如果需要,还可以通过节点的度数(outdegree)来表示节点。

感谢 Duen Horng Chau 教授(佐治亚理工学院)提供可视化工具。如果你对 Argo Lite 如何工作感兴趣(它使用的是 D3), 关注 GitHub 资源库。

在浏览图表和/或进入挖掘功能之前,请考虑以下约束条件:

  1. Twitter 每 15 分钟只允许 15 次 API 调用。这是一个非常小的数字。在初始迭代中从 40 个用户开始,这意味着我们在这次运行中只能分析 14 个用户(1 次运行用于根节点)。所以你最好准备好你的覆盆子馅饼。
  2. 对于根节点获得的用户必须有一个限制
  3. 对于节点的节点。这个极限应该比第一个还要小。经验法则是≤5——否则图形会 变得非常大,API 调用会 不堪重负。

作者在 Argo Lite 中对“局部”图形图像的整体提取

这一切都从探索 Twitter API 开始。我不是他们文档的最大粉丝(特别是这个 v1.0v2.0 有时会令人困惑),但是他们在 GitHub 上的示例代码很棒。

要开始您的项目,您需要以下两个构件:

  1. Twitter 开发人员页面上的一个现成项目——这是稍后获取授权 API 调用的密钥所必需的。
  2. 根节点的 ID——这是脚本遍历所有“follows”的起点

下面显示的代码只是从 Twitter dev 的 GitHub 复制的,并为我们的程序构建起点。额外的导入(比如日志记录)并不是必需的,但是,当需要跟踪更大图形的进度时,可能会很有用。再次提醒,Twitter 只允许数量少得令人不满意的 API 调用——所以日志在某些时候可能会派上用场。

感谢推特开发者

鉴于上述前提条件,我简单地将样板代码打包到一个函数中,每次迭代都要调用这个函数。代码基本上接受我们传递给函数的节点标识符( id ),并检索节点/人员的关注者的完整列表。

我们还需要设置限制参数。这是必要的,因为对于一个普通甚至高度参与的用户来说,由于 Twitter 网络的规模,这个挖掘任务将会花费难以置信的长时间。

  1. 迭代:这允许我们定义多长时间跟踪一次节点,并选择这些节点作为下一次迭代的起点。参见下面的 *****
  2. 迭代= 0 简单定义一个计数器变量。
  3. request_count :限制调用次数所需。这个计数器确保我们不会触及(非常小的)API 限制
  4. start_limit 定义在第一次迭代中检索的节点数
  5. 限制定义任何后续迭代的节点数
* Iterations:
0 — [RootNode -> **n Users**]
1 — [RootNode -> n Users -> **m Users** ], 
2 — [RootNode -> n Users -> m Users -> **m Users**]# where n is the *start_limit* and m is *limit*.
# You can push this iterative process to any number you like, 
# just make sure it comes to end within the next decade.

第一块代码基本上只定义了用户的检索( get_follows )以及为挖掘过程设置参数。

现在真正有趣的事情开始了,我们获得了初始节点(RootNode)的第一批追随者。为了再次强调这一点,我使用了 Python 的内置日志库,这是一种跟踪进度和识别程序可能遇到的问题的可靠方法——只是要注意您的程序可能会运行许多小时、几天...—所以“print”很可能不是一个好的选择。

这个函数的另一个重要方面是我们仔细观察了传播节点。我们使用 follows_checked 来跟踪我们已经访问过的节点,并将它们从堆栈 ( new_nodes )中移除,否则我们创建了一个无限循环。

我们基本上是迭代一个用户列表,并将所有元素添加到边和节点中。主要的挑战是跟踪我们已经用来获取用户列表的节点。为此,我们保持:

  1. follows _ check只是一个排除列表。这里的每个条目将不再被用来调用数据检索
  2. 节点 是所有节点的列表,在所有迭代中追加
  3. new_nodes :跟踪我们刚刚介绍的节点
  4. next_nodes :只是一个我们用来和排除列表进行比较的临时数组。

第一次迭代很简单,我们只需遍历所有节点并添加节点和边列表。请注意,该列表中的节点可能不是唯一的。如果您的用例需要的话,请确保您准备好清除重复的输出。

当我们看到想要跟随的附加“层”时,更复杂的任务出现了。这里很重要的一点是跟踪检查过的节点,并且我们单独存储新引入的节点。再仔细想想。

结论

这篇短文展示了如何迭代地收集数据并将其存储在一个可用于构建图表的结构中。关键是,大数据时代给我们带来了各种新的挑战,图表是更好地了解数据的一种主要方式。

无论是在简单的 CSV 文件中(对于小型图表),还是在数据库中,甚至是分布在几台计算机上(例如 Spark GraphX ),图表都可以轻松存储,并且可以使用强大且经过验证的算法来探索其内容。

进一步延伸内容

如果 PageRank 是你正在寻找的,我推荐阅读这篇文章,它不是太难理解,而且抓住了要点:

如果你不仅对用户之间的联系感兴趣,而且对 T2 发了什么样的推文、推文的情感或者用户写的内容感兴趣,你可能会想看看 T4 的自然语言处理和/或相似性度量。我曾经创建了一个迭代方法来评估文本中某些单词的重要性,这可能对你的项目有用:

{下次再见,注意安全}

再次衷心感谢 Duen Horng (Polo) Chau 教授和所有参与的同学(佐治亚理工学院),他们提供了在线图形可视化工具 Argo Lite-Polo 教授也是真正激发我对图形分析兴趣的人。

佐治亚理工学院#CS 6242 数据和可视化分析

附录

计算三角形(CS167) —斯坦福大学出版

克林特·王茂林在 Unsplash 上拍摄的照片

2022 年的图表 ML:我们现在在哪里?

原文:https://towardsdatascience.com/graph-ml-in-2022-where-are-we-now-f7f8242599e0?source=collection_archive---------3-----------------------

思想和理论,最新技术文摘

热门趋势和主要进展

对于 Graph ML 来说,这是不平凡的一年——数以千计的论文、无数的会议和研讨会……我们如何跟上身边发生的这么多有趣的事情呢?嗯,我们也感到困惑,并决定呈现一个结构化的图形 ML 高亮显示🔥趋势和主要进展。

图像是由 ruDALL-E 生成的,并带有提示“图形漂浮在太空中”。

无论您正在研究一个更窄的主题,还是刚刚开始使用 Graph ML——我们希望这篇文章是一个很好的参考点。

当然,这个领域是如此之大,以至于任何这样的评论都有点短视,所以如果我们错过了一些重要的东西,请在评论中告诉我们!

目录: 1。图形变形金刚+位置特征
2。等变 GNNs
3。生成模型为分子
4。GNNs +组合优化&算法
5。子图 GNNs:超越 1-WL
6。可扩展和深度 GNNs: 100 层及以上
7。知识图表
8。一般酷研用 GNNs
9。新的数据集、挑战和任务
10。课程和书籍
11。库&开源
12。如何保持更新

图形转换器+位置特征

gnn 在普通(通常是稀疏的)图上操作,而图转换器(GTs)在全连接图上操作,其中每个节点都连接到图中的每个其他节点。一方面,这带来了节点数量 N 的 O(N)复杂度。另一方面,GTs 不会遭受长距离消息传递的常见问题——过度平滑。全连通图意味着我们有来自原始图的“真”边和从全连通图转换中添加的“假”边,我们想要区分它们。更重要的是,我们需要一种方法来赋予节点一些位置特征,否则 GTs 就会落后于 GNNs(如 Dwivedi 和 Bresson 的 2020 论文所示)。

也许今年最引人注目的两个图形转换器模型是三(光谱注意力网络)和图形转换器。 by 克罗伊泽、比艾尼等人 采用拉普拉斯算子的前 k 个特征值和特征向量,表明仅谱特征就可以区分被 1-WL 检验认为同构的图。由于将光谱特征与输入节点特征连接在一起,SAN 在许多分子任务上优于稀疏 gnn。

来源: 克罗伊泽、比艾尼等人

英等人https://openreview.net/pdf?id=OeWooOxFwDa的笔形器采用了不同的方法,利用了空间特性。首先,用中心性编码丰富了节点特征——可学习的入度和出度嵌入。然后,注意力机制有两个偏置项:节点 ij 之间最短路径的 1️⃣距离;依赖于一条可用最短路径的 2️⃣边要素编码。

笔形位置编码方案。来源: 应等人

🏅Graphormer 完成了 2021 年 Graph ML 大满贯:在 OGB 大型挑战赛Open Catalyst 挑战赛的图形回归任务中获得第一名!(下面将详细介绍这些挑战)

🤔未决问题:可扩展性计算开销。SAN 和 Graphormer 在分子任务上进行了评估,其中图相当小(平均 50-100 个节点),例如,我们可以运行 O(N ) Floyd-Warshall 所有对最短路径。此外,图转换器仍然受到 O(N)注意机制的限制。放大到比分子更大的图形会解决这些问题。你刚才是不是想到了 NLP 的线性变压器?😉是的,他们可能会帮忙,但由于他们从来没有实现注意力矩阵,你需要找到一个聪明的方法来把边缘特征放在这样的模型中。当然,我们会在 2022 年看到更多关于这方面的研究!

等变 GNNs

Geoffrey Hinton 承认 equivariance 的独特之处是什么?

一般来说,等方差定义在某些变换群上,例如,三维旋转形成的 SO(3)群,三维中的特殊正交群。等变模型风靡了 ML🌪2021 年,在 Graph ML 中,它在许多分子任务中特别具有破坏性。应用于分子,等变 gnn 需要节点特征的额外输入-即,将在 n 维空间中旋转/反射/平移的分子的物理坐标的一些表示。

有了等变模型,不管变换的顺序如何,我们都会到达相同的最终状态。来源: 萨托拉斯、胡格博姆、韦林

Satorras、Hoogeboom、Welling 提出 EGNN 、E(n)等变 GNNs,其与 vanilla GNNs 的重要区别在于在消息传递和更新步骤中加入了物理坐标。情商。3👇将相对平方距离与消息 m 和 Eq 相加。4 更新位置特征。EGNN 在建模 n 体系统、作为自动编码器以及在量子化学任务(QM9 数据集)中显示出令人印象深刻的结果。

与普通 GNNs 的重要区别:等式 3 和 4 将物理坐标添加到消息传递和更新步骤中。来源: 萨托拉斯、胡格博姆、韦林

另一种选择是结合原子之间的角度,就像 T2、克利茨佩拉、贝克尔和 T4、T5 在 GemNet 中所做的那样。这可能需要将输入图转换为线图,例如边的图,其中原始图的边成为线图中的节点。这样,我们可以将角度作为边缘特征合并到新的图形中。

使用角度作为主要坐标。来源: 克利茨佩拉、贝克尔、居内曼

GemNet 在分子动力学任务上显示了强大的结果:COLL、MD17 和 Open Catalyst20。很明显,等方差区只是🛫的起飞,我们将在 2022 年看到更多的进步!

分子的生成模型

药物发现(DD)的整个领域得到了显著的推动🚀2021 年感谢几何 DL。DD 的许多关键挑战之一是生成具有所需属性的分子(图形)。这个领域很大,所以我们只强调模型的三个分支。

  • 规范流程。
    Satorras、Hoogeboom 等人应用上述等变框架创建能够生成具有位置和特征的 3D 分子的 E(n)等变归一化流💪

资料来源: Satorras,Hoogeboom 等人

  • 概率模型。石,罗等研究给定一个图,生成三维构象体,即三维结构的问题。模型 ConfGF 估计原子坐标对数密度的梯度场。这些场是旋转平移等变的,作者提出了一种将这种等变性质纳入估计量的方法。Conformer 采样本身是通过退火的 Langevin dynamics 采样完成的。

资料来源:石、罗等

  • RL 方法。用一种非常非科学的方式描述,这些方法通过一步一步地添加“积木”来生成分子。我们可以从某种程度上对这些方法进行分类,它们决定了这个构建过程。

例如,高、梅尔卡多和科利将合成能力作为构建过程的条件,即我们是否能在实验室中实际创造出这种分子。为此,他们首先学习如何创建积木的合成树(一种模板)。

来源:【高、梅尔卡多、科利】

由 Yoshua Bengio 领导的 Mila 和 Stanford 研究人员团队提出了一个更加通用的框架,他们引入了生成流网络(GFlowNets) 。很难用几句话来概括——首先,当我们想要对多样化的候选对象进行采样时,GFlowNets 可以用于主动学习案例中,采样概率与一个奖励函数成正比。此外,他们最近的 NeurIPS'21 论文显示了 GFlowNets 应用于分子生成任务的好处。查看 Emmanuel Bengio 的博客文章,这篇文章更详细地描述了这个框架,并提供了更多的实验证据。

GNNs +组合优化和算法

2021 年是这个新兴子领域的重要一年!

徐等人 在他们杰出的 21 论文中研究了神经网络的外推,并得出了几个惊人的结果。利用算法比对的概念(由相同的作者在聚焦 ICLR 的 20 篇论文中介绍),作者表明 gnn 与动态编程(DP) 很好地对齐(查看图示👇).与 ICLR 20 的论文相比,这里作者讨论了一个更强的外推条件— 线性排列到 DP。事实上,比较寻找最短路径的经典贝尔曼-福特算法的迭代和消息通过 GNN 的聚合-组合步骤,你会发现许多共性。此外,作者表明,在对特定的 DP 算法建模时,为 GNN 选择合适的聚合函数至关重要,例如,对于 Bellman-Ford,我们需要一个min-聚合器。我还推荐看一下斯蒂芬妮·杰格尔卡的一个非常有说明性的演讲,他解释了这项工作在深度学习和组合优化 2021 研讨会上的主要成果。

来源:徐等

为了更全面地介绍这个领域,我想强调一下 Cappart 等人 所做的 IJCAI'21 综合调查,它涵盖了组合优化中的 gnn。这篇文章首次展示了神经算法推理蓝图,该蓝图后来由veli kovi 和Blundell 以 Patterns 的形式在立场文件中进行了描述。****

来源:veli kovi 和 Blundell

📘蓝图解释了神经网络如何在嵌入空间中模仿和授权通常离散的算法的执行过程。在编码-处理-解码方式中,抽象输入(从自然输入中获得)由神经网络(处理器)处理,其输出被解码成抽象输出,然后抽象输出可以被映射到更自然的特定任务输出。例如,如果抽象的输入和输出可以用图形表示,那么 gnn 可以是处理器网。离散算法的一个常见预处理步骤是将我们所知道的任何关于问题的信息压缩到标量中,如“距离或“边容量,并在这些标量上运行算法。相反,矢量表示和神经执行使得启用高维输入而不是简单的标量变得容易,并附加了一个用于优化处理器的反向投影。欲了解更多信息,请参见 Petar Velič ković的演讲🎥。

这个蓝图越来越多地被采用——neur IPS ' 21 展示了一些很酷的作品! Xhonneux 等人 研究迁移学习是否可以应用于将学习到的神经执行器推广到新任务; Deac 等人 发现了强化学习中算法推理和内隐规划之间的联系。2022 年还会有更多!

子图 GNNs:超越 1-WL

🤝如果 2020 年是第一次尝试离开 GNN 的 1-WL-兰迪亚的一年,我们可以确认 2021 年是在beyond-1WL-兰迪亚与外星人建立稳固联系的一年👾。这种联系无疑证明了它们是有用的,因为我们现在已经有了一些强大的和更具表现力的架构,它们将消息传递扩展到更高阶的结构,如单纯复形(网、和王等人)、细胞复形( CW 网)或子图。****

对于后者,看看这篇由迈克尔·布朗斯坦、莱昂纳多·科塔、法布里齐奥·弗拉斯卡、哈盖·马龙、和赵在子图 GNNs 上发表的 新的精彩博文

如果你想真正深入研究 WL 最近的研究,请查看克里斯多夫·莫利斯、亚龙·李普曼、哈盖·马龙和合著者的最新调查 韦斯费勒和莱曼围棋机器学习:迄今为止的故事

可伸缩性和深度 GNNs: 100 层以上

如果你在使用 2-4 层的 gnn 时,对 100 层以上的深网或巨大的变形金刚感到嫉妒,那么是时候庆幸了🤩!2021 给我们带来了两篇论文,它们随意地训练了100-1000 层的 gnn,以及一篇关于几乎恒定大小的邻域采样的工作。

李等人 提出了两种机制,在训练极深度超参数化网络时,将 GPU 内存消耗从 L 层的 O(L) 大幅降低到 O(1) 。作者展示了如何在 CV 中使用多年的 1️⃣可逆层或高效变压器架构,如重整器;2️⃣在各层之间分享重量(捆绑重量)。然后可以训练多达 1000 层的 gnn👀。下面的图表展示了在 GPU 需求适中的情况下,层的数量的不断扩展。

可逆(Rev)和重量捆绑(WT) GNNs 的良好缩放。来源:【李】等

Godwin 等人 介绍了一种利用递归学习深度 GNNs 的方法——消息传递步骤按块组织,每个块可以有 M 个消息传递层。然后,循环应用 N 个块,这意味着块共享权重。如果你有 10 个消息传递层和 10 个块,你会得到一个 100 层的 GNN。一个重要的组件是噪声节点正则化技术,该技术扰动节点和边缘特征并计算额外的去噪损失。该架构适合更好的分子任务,并在 QM9 和 OpenCatalyst20 数据集上进行了评估。

来源: 戈德温等人

最后,如果我们想要将任意的 GNN 缩放到非常大的图,除了采样子图,我们没有其他选择。通常,采样 k 跳子图会导致指数的内存开销和计算图大小。

PyG、 的作者 Matthias Fey 等人 创建了 GNNAutoScale ,这是一个在常数时间内扩展 GNNs 的框架,利用了历史嵌入(以前消息传递步骤的缓存的一个奇特版本)和图聚类(在这种情况下是一个众所周知的 METIS 算法)。在预处理过程中,我们将图划分为 B 个聚类(小批量),使得聚类之间的连通性最小化。然后,我们可以在这些集群上运行消息传递,跟踪缓存中更新的节点特性。实验表明,深度网络的 GNNAutoScale(最多 64 层)的性能与整批设置一样好,但内存需求却大大降低(大约小 50 倍),因此您可以在商品级 GPU 上运行深度 gnn 和大型图形💪

GNNAutoScale。来源: Fey 等人

知识图表

KGs 上的表征学习终于突破了传导型的天花板。

在 2021 年之前,模型被清楚地分为直推式和归纳式,具有不同的归纳偏差、架构和训练机制。换句话说,直推模型没有机会适应看不见的实体,而归纳模型太昂贵,无法在中大型图上训练。2021 年带来了两种架构

  • 在直推式和感应式环境下工作,
  • 不需要节点特征,
  • 可以以与直推模式相同的方式在感应模式中被训练,
  • 可扩展到现实世界的千克大小。

第一个是神经贝尔曼-福特网由朱等人组成。作者找到了一种非常优雅的方式来将经典的贝尔曼-福特推广到更高层次的框架,并展示了我们如何通过用特定的运算符实例化框架来获得其他众所周知的方法,如卡茨指数PPR最宽路径。更重要的是,他们表明广义贝尔曼-福特本质上是一种关系 GNN 架构(GNNs 和动态编程之间的算法一致性的另一个确认)。NBFNet 不学习实体嵌入(只学习关系和 GNN 权重),这使得模型通过设计归纳并推广到看不见的图。该模型在关系图和非关系图上的链接预测任务上工作得非常好。应用于 KGs,NBFNet 从 2019 年起为 FB15k-237 和 WN18RR 提供了最大的性能提升,同时参数减少了 100 倍💪。

从香草贝尔曼-福特到神经贝尔曼-福特 GNN。来源: 朱等

🍰另一种方法由 Galkin 等人 (声明:本文作者之一是该论文的作者)受 NLP 中的标记化算法的启发,该算法具有固定的标记词汇表,能够标记任何单词,甚至是那些在训练时间看不见的单词。应用于 KGs, NodePiece 将每个节点表示为一组 top-k 最近锚节点(可选地在预处理步骤中采样)和围绕该节点的 m 唯一关系类型。锚和关系类型被编码成可用于任何下游任务(分类、链接预测、关系预测等)和任何归纳/直推设置的节点表示。NodePiece 特性可以由 RotatE 等非参数解码器直接使用,或者发送到 GNNs 进行消息传递。该模型在归纳链接预测数据集上的表现与 NBFNet 不相上下,并在大型图上表现出高参数效率——在 OGB 维基 2 上的节点模型需要的参数比浅的纯直推模型少约 100 倍。如果你想了解更多,请查看关于 NodePiece 的完整博文!

节点标记化。来源: 加尔金等人

用 GNNs 进行总体上很酷的研究👀

这一节提到了几个特别酷的作品,它们使用了 GNNs,但并没有具体归入某一类别。

黄,何,等人在 21 上提出了正确&平滑——一种用标签传播改进模型预测的简单方法。与一个 MLP 配对,这种方法在没有使用任何 gnn 和更少参数的情况下,以最高分冲击了 OGB 排行榜!今天,几乎所有在 OGB 的节点分类赛道上的顶级模特都使用正确的&平滑来多挤一点点。

资料来源:黄、何等

11 月,🪄 克尼亚泽夫等人one forward pass 中预测各种神经网络架构参数的工作震动了 ML 社区。也就是说,不是随机初始化模型,而是有可能立即预测好的参数,并且这样的模型已经比随机模型好得多👀。当然,如果你用 n SGD 步骤优化一个随机初始化的网络,你会得到高得多的数字,但是这篇论文的一个主要贡献是,通常不需要 训练这个特定的架构就可以找到合适的参数。****

参数预测实际上是一项图形学习任务——任何神经网络架构(ResNet、ViT、Transformers 等)都可以表示为计算图形,其中节点是具有可学习参数的模块,节点特征是这些参数,我们有一系列节点类型(例如,线性层、Conv 层、Batch Norm,作者使用了大约 15 种节点类型)。然后,参数预测是一项节点回归任务。用 GatedGNN 对计算图进行编码,并且将其新的表示发送到解码器模块。为了训练,作者收集了一个 1M 架构的新数据集(图)。该方法适用于任何神经网络架构,甚至适用于其他 gnn!

欲了解更多信息,请查看带有示例和 Jupyter 笔记本的官方回购,以及鲍里斯·克尼亚泽夫与扬尼克·基尔彻的采访。

预测未知模型的参数:管道。来源: 克尼亚泽夫等人

🗺DeepMind 和谷歌通过将道路网络建模为超分段的图形并在其上应用 GNNs,极大地提高了谷歌地图中 ETA 的质量。在 Derrow-Pinion 等人 的论文中,该任务被设计为节点级和图级回归。除此之外,作者描述了为了在谷歌地图规模上部署该系统需要解决的众多工程挑战。一个应用 GNNs 解决数百万用户面临的实际问题的完美例子!

来源: 德罗-皮恩等人

GNNs 在癌症研究中的另一个潜在应用是最近由转基因和 NEC 宣布的。根据 NEC 首席研究员 Mathias Niepert 的说法,gnn 被用于通过嵌入传播来估算缺失的患者数据(查看最近关于该方法的 Twitter 帖子),以及对候选肽进行评分以引发免疫反应。

最后,来自 DeepMind 的 Davies 等人最近使用 GNNs 来帮助制定关于核心数学问题的猜想(关于他们工作中的🪢结🪢),并且实际上发现并证明了一个新的定理!你看,GNNs 也可以处理相当抽象的事物👏

新的数据集、挑战和任务

如果你厌倦了 Cora、Citeseer 和 Pubmed——我们理解你。2021 年带来了大量不同规模和特征的新数据集。

  • OGB 在 KDD 21 年组织了 大规模挑战赛 ,用 3 个非常大的图进行节点分类(2.4 亿个节点)、链接预测(整个维基数据,9000 万个节点)和图回归(4 百万个分子)。在 KDD 杯比赛中,大多数获胜团队使用 10-20 个模特的组合——查看研讨会录音以了解更多关于他们的方法。新版本的 LSC 数据集现已推出新的排行榜!
  • Meta AI 的 Open Catalyst neur IPS ' 21 Challenge提供了一个大分子任务——给定一个具有原子位置的初始结构,预测松弛态能量。数据集非常庞大,需要大量的计算,但组织者暗示将发布一个较小的版本,对 GPU 预算有限的小型实验室更友好一些。结果和记录是可用的——等变模型和变压器达到了顶端。事实上,Graphormer 在 OGB LSC 和 OpenCatalyst'21 中都获得了前 1 名,几乎囊括了 2021 年 Graph ML 的大满贯🏅
  • 关于图学习基准的研讨会https://graph-learning-benchmarks.github.io/@ web conf 2021 带来了一系列新的数据集,包括由 Lim 等人的非同构图,由 Tsitsulin 等人的图模拟,由 Rozemberczki 等人的时空图,以及更多****
  • NeurIPS 的 21 个数据集&基准测试跟踪 就像一个新数据集的 SXSW 节日:今年我们有MalNet——图分类,平均图大小是 15k 个节点和 35k 条边,大大大于分子; ATOM3D —新 3D 分子任务集合; RadGraph —从放射学报告中提取信息。最后, Liu 等人报告了创建图学习数据集分类的挑战——这是一项期待已久的工作,社区肯定会从中受益。**

课程和书籍

新的和值得注意的课程和书籍:

  • 几何深度学习原型书 & 课程由迈克尔·布朗斯坦、琼·布鲁纳、塔科·科恩和佩塔尔·韦利奇科维奇主讲。包含 12 个讲座和实践教程&研讨会。如果你喜欢视频记录,迈克尔的 ICLR 21主题演讲是今年发布的关于图表的最佳视频。
  • 关于知识图谱的新开卷由 18(!)作者。整本书在网络上是免费的;它包含了很多关于方法、模式和查询的细节。

威廉·哈密顿《图形表示学》一书。虽然技术上是在 2020 年发布,但从现代深度学习的角度来看,它仍然是对 GML 的最佳简短介绍。

库和开源

2021 年发布的新库:

  • 张量流 GNN —作为张量流世界一等公民的 GNNs。
  • TorchDrug —基于 PyTorch 的 GNN 库,用于分子和 KG 任务

已建立的图形 ML 库得到更新:

  • https://www.pyg.org/PyG 2.0——现在支持异构图、GraphGym 以及一系列改进和新模型
  • DGL 0.7 —在 GPU 上进行图形采样,更快的内核,更多的模型
  • 皮克 EN 1.6 —训练 KG 嵌入的最佳库:更多的模型、数据集、指标和节点件支持!
  • Jraph——GNNs 对于 JAX 的爱好者来说,看看这篇由王俐人(DeepMind)和尼古拉·约万诺维奇(ETH Zurich)关于构建和评估 GNNs 的最新介绍

如何保持更新🤓

2021 年到此为止!很可能,我们忽略了你的图形表示学习子领域中的一些重要的东西——让我们在评论中知道你认为我们错过了什么。

如何及时了解 Graph ML 中出现的所有新的酷东西:

  • 图机学习通道中的电报
  • 米拉 GRL 阅读小组(加拿大东部时间【美国时间】下午)
  • LoGaG 阅读小组(英国时间下午)
  • 迈克尔·布朗斯坦在媒体上的博客
  • 在 Twitter 上关注我,并在 Medium 上订阅;)

你坚持读完了长篇小说——你应该得到一张迈克尔·布朗斯坦与圣诞老人同构的照片!🎅

感谢 安东·齐苏林 、安瓦尔·库尔穆科夫 谢尔盖·伊万诺夫 对博文内容的帮助,以及 佩塔尔·韦利奇科维奇 对少数不精确提法的修正。

推荐系统的图形神经网络(GNN)结构

原文:https://towardsdatascience.com/graph-neural-network-gnn-architectures-for-recommendation-systems-7b9dd0de0856?source=collection_archive---------3-----------------------

高级建议的 GNN 技术回顾

阿丽娜·格鲁布尼亚在 Unsplash 上的照片

推荐系统无处不在,几乎指导着我们做出的每一个决定。从下一个节目我们将狂吃网飞到下一个我们将尝试的外卖食物,复杂的算法学习我们是谁,并使用这些知识来推动某些结果。在 B2B 领域,推荐系统正在赶上它们的 B2C 姐妹,我们在 Slimmer AI 开发的几个产品都包含推荐组件。

对于我自己的研究,我被图形神经网络(GNN)所吸引,这是最近流行的,许多问题都是用基于 GNN 的模型来解决的。gnn 的吸引力还在于开源工具和库的可用性,如 Pytorch Geometric 和 Deep Graph Library (DGL) ,使得实现这些模型变得容易。

在本文中,我概述了如何使用 GNNs 实现推荐系统,并简要回顾了一些更流行的可用模型。要详细了解推荐系统中的 GNNs,请查看吴、等人的 2020 年调查【2】,这有助于我对该领域的理解。在详细介绍 GNN 在推荐中的应用之前,我将从一些关于图和 GNNs 的基础知识开始。

关于“图形”的复习

是由一组代表实体的节点/顶点和一组连接代表实体间关系的节点的组成的结构。它有几个特点,包括:

  • 边缘可以是有向(图 1a)或无向(图 1b)。即,对于有向图,关系是单向的,对于无向图,关系是双向的。
  • 在许多情况下,实体之间的关系具有不同程度的重要性,这可以在图中使用权重来区分(图 1a)。如果未指定重要性,则假设每条边都具有相同的重要性。
  • 在某些情况下,图形可以由多种类型的实体组成。例如,推荐图可以由用户和项目节点组成。这样的图被称为异构图(图 1b),而不区分节点类型的图被称为同构图(图 1a)。
  • 有许多特殊种类的图。对本文特别重要的一个图是二分图(图 1b),这是一个由两个不相交的节点集组成的异构图,边只存在于相对节点集的节点之间。

举例说明图形的不同属性。图片作者。

关于图形神经网络(GNNs)的综述

图形拓扑/结构编码了大量信息。使用传统的学习技术很难捕捉这种隐性知识。因此,将数据表示为图形有助于使底层关系清晰可见。GNNs 关注于利用这些知识的学习机制,以便为下游任务获得更好的性能,如评级预测(推荐系统中流行的任务之一)、相似内容检索等。

GNNs 的目标是使用邻域信息更好地学习实体/节点的表示 / 嵌入。GNNs 也可以用来学习 表示法,但为了简单起见,本文中我将重点介绍节点表示法。说了这么多,让我们简单看看 GNNs 是如何工作的:

  • GNNs 迭代地聚集来自邻居的特征信息,以更新每个节点的当前表示
  • 聚合函数确定如何组合从邻居收集的特征,例如平均池最大池等。
  • 下图显示了流行的 GNN 模型之一的图卷积网络(GCN)【3】的更新函数 f ,用于在时间 t+1 更新节点 i 的表示 h
  • 对于每个迭代,节点的当前表示被用作下游任务的输入,其损失函数更新可训练参数

在上面的更新函数中, h 代表节点 it 代表时间步长, N(i) 代表节点 iUW 是训练时更新的参数,c _ ij图片作者。灵感来自 AI 与 Letitia 的茶歇。**

因此,gnn 属于表示学习技术的范畴,该技术除了内容信息之外,还专注于捕获拓扑信息。

总而言之,GNNs 背后的三个主要思想是:

  1. 消息(信号)通过:信息传播
  2. 聚合(更新):处理接收到的信息的功能
  3. 迭代:确定信号的幅度

现在,让我们仔细看看 GNNs 的推荐。

GNNs for recommendation

推荐系统用于为给定用户生成推荐项目的列表。推荐是从可用的项目集合(例如,电影、杂货、网页、研究论文等)中提取的。、)并根据以下内容为个人用户量身定制:

  • 用户的偏好(隐式或显式),
  • 项目功能,
  • 和/或用户项目过去的交互。

用户和项目数据的数量和质量决定了推荐的质量。大多数当前最先进的推荐系统使用深度学习技术。关于这些技术的全面概述,请查看张,帅等人 2019 年的调查论文【4】

根据上面对推荐系统的描述,可以将数据建模为图:用户和项目作为节点,边表示节点之间的关系。这些关系可以从大多数推荐系统的输入数据中提取/推断出来。

有模型可用于处理顺序推荐【2】,其中系统试图基于用户与前一时间步中的项目之间的“交互顺序”来推荐下一个项目。为了简单起见,我只关注一般的建议(建议的顺序是独立的)。

根据我们如何将可用数据建模为图形,有几种类型的基于 GNN 的模型可用于解决推荐问题。这些模型可以大致分为 3 种类型:

  1. 使用用户-项目交互信息的 GNNs
  2. 用社交网络信息增强的 GNNs
  3. 用知识图增强的 GNNs

为了说明推荐的三种类型的 GNN 模型,考虑向专家推荐内容的问题,这将在本文中使用。目标是推荐与专家之前撰写的出版物相似的内容。标题简介关键词等信息。,有可能被用作内容的特征。此外,我们可以通过利用专家的研究兴趣、参加的会议等来模拟专家。

仔细观察:使用用户-项目交互信息的 GNNs

在这类模型中,数据被建模为二分图。在我们的示例中,专家构成一组节点,内容构成另一组节点,如果专家是内容的原始作者之一,则节点之间存在边。

上图显示了一个用户-项目交互图的例子,这是一个由专家节点和内容节点组成的二分图,其中表示专家是否是内容的作者之一。图片作者。

首先,下面是使用用户-项目交互的 GNNs 类别中的流行模型,它们的实现是可用的,并且易于实验:

GCN

【3】【GCN 图卷积网】是 GNN 最早的作品之一。神经图协同过滤(NGCF)【5】是一种 GCN 变体,它使用用户-项目交互来学习揭示用户之间行为相似性的协同信号,以改进推荐。在 Yelp2018 和亚马逊图书数据集上的评分预测被用来衡量模型的性能。

实现 : GCN — PyG ,NGCF: Tensorflow

图表语法

graph sage【6】是一个提出采样固定大小的邻域,而不是使用每个节点的所有邻居进行聚合的框架。它还提供了 minmax、sum pooling 作为聚合器的选项,并使用串联操作来更新节点/边/图表示。PinSage【7】是 GraphSage 的一个变种,作为处理 web 级图形的解决方案而提出。Pinterest 的 PinSage 引入了一种采样技术,根据最高访问量对固定大小的社区进行采样。或者,可以用区分节点重要性的任何特征来代替访问计数。

实现 : GraphSage — PyG ,PinSage — DGL

GAT

图形注意网络【8】使用注意机制来学习邻居的影响力;这个影响用于确定邻居在聚合步骤中的贡献。多分量图卷积协同过滤(MCCF)【9】就是这样一种方法,它使用注意机制来学习潜在的购买动机,并将其与来自显式用户-项目交互的特征相结合,以获得更好的推荐。作者对 MCCF 在 MovieLens 、亚马逊产品推荐和 Yelp 数据集上的表现进行了基准测试。

实现 : GAT — PyG ,MCCF — Pytorch

细看:GNNs 增强了社交网络信息

在这类模型中,数据建模为:

  1. 两个图:一个二分图用户项目图和一个单独的社交网络图,由用户和表示他们之间某种关系的边组成,或者
  2. 由用户和项目组成的异构图,通过用户-用户和用户-项目边相互连接。

回想一下我们将内容与专家匹配的例子。我们可以根据他们的兴趣,他们可能属于的共同群体,或者任何其他社会或职业联系来建立一个社交网络图。以这种方式定义社交网络图,并使用学习到的特征,已经显示出对包括推荐【2】在内的许多下游任务是有益的。

上图展示了一个社交网络图的例子。图片作者。

以下是这一类别中一些有趣的模型(带有社交网络信息的 GNNs ),其源代码是可用的:

DiffNet++

diff net++【10】提出了一种网络,该网络从两个独立的图中更好地学习用户嵌入,其中潜在的用户兴趣信号来自用户-项目图,而用户影响信号来自用户-用户图。在 Yelp 、 Epinions 和 Dianping 上进行基准测试。

实现:diff net++—tensor flow

GraphRec

graph rec【11】是另一个框架,它利用用户的社交网络来获得更好的推荐。在这种方法中,该模型从同一用户-项目异构(非二分)图中捕获用户-项目交互和用户意见。该框架执行:

  1. 用户建模,丰富用户嵌入,利用用户-项目聚合和用户-用户嵌入(社会关系),以及
  2. 项目建模,其中项目嵌入使用用户-项目嵌入(即多个用户对该项目的看法)来丰富。

对于评级预测的下游任务,用户和项目嵌入的串联被用作输入。在 Epinions 和 Ciao 数据集上的框架基准。

实现 : GraphRec — PyTorch

细看:用知识图增强的 GNNs

该类别中的模型专注于改进项目表示,这进而导致基于用户过去与可比项目的交互的更好的项目推荐。知识图常见于推荐领域,它根据项目的属性对项目进行链接或分组。然而,由于项目之间多类型关系的复杂结构,这些图形的处理可能具有挑战性。

回到我们将内容与专家相匹配的例子,可以使用内容的各种属性(比如共同的主题或题目)来形成知识图。

上图展示了一个知识图的示例,其中的节点是通过不同关系相互链接的内容。可以利用这种关系来丰富专家和内容节点的表示。图片作者。

在用知识图增强的 GNNs 类别中,一个特别有趣的模型是 KGAT:

KGAT

推荐用知识图注意力网络(KGAT)【12】基于 GAT。它构建了一个异构图,由作为节点的用户项目属性组成。它进一步递归地传播来自节点邻居的嵌入,以聚集和更新每个节点嵌入。邻居可以是任何类型的节点(例如,用户、项目或属性),并使用注意机制来学习邻居的重要性。评分预测任务用于性能分析,并在亚马逊图书、 Yelp2018 和 Last-FM 数据集上进行测量。

实现 : KGAT — 张量流

选择合适的型号

我选择上面提到的模型来说明各种类别的主要原因是因为在写这篇文章时它们的可访问性(开源实现、数据集的可用性等)。,).因此,我想强调的是,这个列表并不是绝对的,我只是触及了表面。

虽然每种类型的模型都有自己的优势,但选择正确的模型取决于可用数据的多样性。虽然来自社交网络图的信息已经被证明可以改善推荐【10】,但是并不是所有的域都可以容易地获得这样的信息。另一方面,在我们的数据时代,知识图谱非常丰富(例如,维基百科, DBpedia 等)。),但是维护这样的图是资源密集且耗时的。

由于上述原因,比较不同的模型类型变得困难。在用于基准测试的各种数据集当中,Yelp 数据集是广泛使用的基准数据集,因此我将在下面使用它来比较这些模型。下面是 Yelp 数据集上 NDCG 分数(排名质量的标准衡量标准之一)的对比:

所有上述实验使用 64 的嵌入维数和预处理的 Yelp 数据集,该数据集具有 17237 个用户、38342 个项目和 143765 个交互(边)。吴,乐等实验【10】

从以上结果可以看出,从社交网络图中获取辅助知识的 DiffNet++在比较的模型中表现最好。虽然 KGAT【12】也在 Yelp 数据集上进行了基准测试,但它使用了由 45919 个用户、45538 个项目和 1185068 个交互(边)组成的不同的更大版本的数据集,因此,它与上述模型不可比。使用辅助知识源已被证明可以提高推荐的质量,因此,如果使用社交网络和知识图是可行的,应该选择混合模型。

收尾思路

B2C 体验完全重塑了我们对推荐系统的期望,B2B 的门槛也大大提高了。出于这些原因以及更多原因,高级推荐系统需要智能和直观的解决方案,以充分利用可用数据。

推荐数据——由用户和商品组成——可以自然地建模成一个图表,而不需要太多的努力。GNNs 具有从节点信息(个体信息)和边信息(关系信息)学习的优点,并进一步与利用流行的知识图和社会网络图的模型相结合,使得 GNNs 成为推荐的有前途的解决方案。

作为一个非常活跃和动态的研究领域,新技术经常在各种会议上介绍。当然,当我们进一步将 GNNs 应用到我们自己的推荐系统中来取悦用户并提高他们对我们产品的满意度时,我会关注这个空间。

我错过了你最喜欢的 GNN 推荐技巧了吗?或者您在 B2B 软件产品中尝试过以上任何一种吗?我很想收到你的来信!请跟随更苗条的人工智能创新团队:https://medium.com/slimmerai/innovation/home。

参考文献

吴,,等图神经网络综述 (2020),IEEE 神经网络与学习系统汇刊 32.1(2020):4–24。

****【2】吴,,等,图神经网络在推荐系统中的应用综述 (2020),arXiv 预印本 arXiv:2011.02260。

****【3】Kipf,Thomas N,和 Max Welling,利用图卷积网络的半监督分类 (2016),arXiv 预印本 arXiv:1609.02907。

****【4】张,帅等,基于深度学习的推荐系统:综述与新视角 (2019),ACM 计算调查()52.1(2019):1–38。

****【5】,王,向等,神经图协同过滤 (2019),第 42 届国际 ACM 信息检索研究与发展会议论文集。

****【6】汉密尔顿,林子幸,Rex Ying,Jure Leskovec,大型图上的归纳表征学习 (2017),第 31 届神经信息处理系统国际会议论文集。

****【7】应,Rex,等,面向 web 规模推荐系统的图卷积神经网络 (2018),第 24 届 ACM SIGKDD 知识发现国际会议论文集&数据挖掘。

****【8】veli kovi,Petar,et al .图注意网络 (2017),arXiv 预印本 arXiv:1710.10903。

****【9】,王,肖等,多分量图卷积协同过滤 (2020),人工智能会议论文集。第 34 卷。№04.

****【10】吴,乐等, Diffnet++:一种面向社会推荐的神经影响和兴趣扩散网络 (2020),IEEE 知识与数据工程汇刊。

****【11】范,,等,面向社会推荐的图神经网络 (2019),环球网大会。

****【12】王,向等, KGAT:知识图注意网络推荐 (2019),第 25 届 ACM SIGKDD 知识发现国际会议论文集&数据挖掘。

图形神经网络:2008 年以来的学习之旅——深度行走

原文:https://towardsdatascience.com/graph-neural-networks-a-learning-journey-since-2008-deep-walk-e424e716070a?source=collection_archive---------23-----------------------

图形神经网络之旅的第三部分。今天,佩罗齐 2014 年论文《深度行走:社会表征的在线学习》的理论背景

图片由 Wladislaw Sokolowskij 在 Unsplash 上拍摄

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

在本系列的第一篇文章中,我们学习了图形神经网络模型是如何工作的。我们看到,GNN 返回基于节点和基于图形的预测,它有坚实的数学背景支持。特别地,转移函数和输出函数满足 Banach 不动点定理。然而,尽管成功的 GNN 应用,也有一些障碍,如解释1。GNN 模型的主要思想是建立状态转换,函数 f𝓌g𝓌 ,并迭代直到这些函数收敛在一个阈值内。这是一个强约束,可能会限制模型的可扩展性和表示能力。其次,GNN 不能利用表示学习,即如何从低维特征向量中表示图形。第三,GNN 基于迭代学习过程,其中标签是混合的特征。这种混合可能会导致一些级联错误,如[6]所示

为了解决这些问题,DeepWalk 2在 2014 年出现,作为 GNN 的一个可能的增强。DeepWalk 是第一个实现嵌入方法的图,它基于表示学习和语言建模——skip gram 模型[3]

深度行走模型

定义

DeepWalk 通过对一系列短距离随机行走建模来学习图顶点的社会表现。社会表征是跨越图形顶点的隐藏连接,可以解码为潜在特征。因此,DeepWalk 读取输入图形并输出图形的潜在表示。

如何获得图形的潜在表示?嗯,这里我们有与斯卡塞利的方法的主要区别。斯卡塞利的 GNN 是一种有监督的方法,而 DeepWalk 是一种无监督的方法,因此它必须从图的特征中学习,以理解和捕捉图的结构和目标,独立于节点或图的标签。这种映射方法已被证明比其他社会维度分类器更有效[4,5],将微观 F1 分数的分类性能提高了 5-10%,甚至在训练数据少 60%的情况下也优于“竞争对手”。最后,DeepWalk 框架允许简单的可伸缩性,以处理网络规模的图表,如脸书,Twitter 或 Youtube。

数学洞察 I:定义

DeepWalk 基于节点的社会属性返回输入图的有洞察力的潜在表示。图定义为数学函数 G=(V,E) ,是由 V 顶点和 E 边组成的。顶点可以部分标记, Y 标记,并由属性/特征 X 描述。属性/特征是实数域的一部分,其维数为 S,和标记由实数向量定义。

给定输入真实域,DeepWalk 将节点的特征 X 转换为潜在域,其维度为 d. 这种映射描述了具有较小特征子集的社会现象,这有助于更好地理解底层数据的关系,并在摄取到 PCA 或 t-SNE 算法中时具有即时的视觉答案。

为了理解 DeepWalk 的理论和过程,在处理实际实现之前,我在这里提供了一个空手道俱乐部图的例子。图 1 示出了输入图 G,其中顶点是 34,边是 78。

图 1 输入空手道俱乐部图表

输入特征矩阵 X 描述了节点之间的关系,我们希望使用 DeepWalk 找到图形的潜在表示,以找到俱乐部中的最佳分组。例如,潜在表示维度可以是 10,因此 DeepWalk 将产生 10 个新特征来将图细分成组。

数学洞察 II:随机漫步的产生

为了实现潜在表示,DeepWalk 开始从输入图创建γ(例如 100)个随机行走。随机游走 Wvᵢ 从顶点 vᵢ 开始,随机选择 k (例如 10 个)其他图的顶点 vₖ (例如见图 2)

图 2:顶点 22 和 31 的截断随机行走的例子。随机漫步允许轻松地同时探索多个图形区域

随机漫步的选择允许算法从网络中提取信息,一方面保证计算的容易并行化,另一方面保证探索图形的动态方式,一旦图形改变,可以封装新的信息。后一方面允许从单个图子集迭代更新模型训练,而没有整个图计算的问题。

数学洞察 III:语言建模

一旦收集了γ(例如 100)“截断的”随机游走,就有可能利用一些语言建模来提取输入社会表征的潜在描述。特别地,随机漫步的集合可以被看作是由 k 单词 w : Wvᵢ = (w₀,w₁,…wₖ).)组成的句子的编码集合(图 3 显示了 10 个随机漫步的例子)从这里,DeepWalk 计算所有输入语料库 G 的单词嵌入或节点嵌入表示。这是一个值得注意的点,因为这是在图形世界中第一次有人写节点嵌入的概念。

图 3:从顶点 22、13、31、16、10、5、17、16、24 和 18 开始的 10 次随机漫步。

单词嵌入可以由一个函数φ来描述,该函数的值位于实数域中。φ是一个矩阵,它的维数是顶点数 V 和潜在维数 d (在这个例子中是 34 x 10)。目标是在给定所有先前访问过的顶点嵌入的情况下,检索观察到顶点 vᵢ 的可能性:

等式 1:给定所有先前的顶点嵌入,顶点 vi 被观察到的可能性

然而,这种计算取决于图的维数和随机游走的长度,因为它们在增长。等式 1 是计算性的,效率不高。在[7] [8]中提出了一个解决方案,其中问题是相反的。如图 4 所示,我们将计算一个单词在给定上下文中作为邻居出现的可能性,而不是预测一个句子中缺失单词的出现

图 SkipGram 方法的直观示例。给定一个句子,我们希望预测一个单词与给定单词相邻的可能性(例如 walk)。

这种方法称为 skip gram[7–11],旨在解决这一优化问题:

等式 SkipGram 的优化问题。目的是在给定单词 v_i 的映射的情况下,通过估计上下文单词的对数似然来最小化嵌入表示

从等式 2 可以描述 d 维潜在表示中的顶点,使得相似的顶点具有相似的表示。

数学洞察 IV:分层 Softmax

仔细观察 SkipGram 算法,我们可以获得以下“成分”:

  • 尺寸为 w 的窗口滑过输入序列
  • 单词嵌入潜在维度 d
  • 一个 2 层神经网络,接收输入语料库
  • 计算单词概率分布的激活层

对于给定随机漫步中的每个顶点 vᵢ ,我们有一个表示向量φ(vᵢ。给定这个顶点表示,我们希望在随机行走中最大化它的邻居的概率(等式 2)。这样的后验分布可以通过几种算法来学习。在 DeepWalk 中,该模型使用分层的 Softmax 方法[12,13],这减轻了计算成本并加快了训练时间,从而逼近概率分布。计算后验概率可能会导致巨大的工作量,这等于图中顶点的数量(在某些情况下高达数十亿)。

分级 Softmax 基于一个二叉树,即霍夫曼树/编码,它确保了属于任何树节点每一侧的点的分布之间的平衡。来自等式 2 的顶点 vᵢ 是根节点。从那里,我们可以从随机漫步到最后一个顶点创建分支。最终的后验概率是通过从词根开始遍历树来计算我们遇到的每个单词的概率之和。

最后备注:想象嵌入

最后会有什么?一旦 DeepWalk 已经运行,Skipgram Word2Vec模型将返回我们的输入图的潜在空间描述,即一个图嵌入文件:

图 5:空手道俱乐部图的最终嵌入示例。数字 34 和 10 是图的节点数和潜在表示维度。对于每个顶点节点(每行的第一个数字,例如 34,1,33,3,2),我们可以找到相关的潜在表示坐标

对于每个顶点,该文件报告模型的嵌入,即顶点在潜在表示空间中的位置。我们如何使用这种表示法?嗯,我们可以使用至少两种分解算法来获取这样一个空间的“人类”表示。第一个是 t-SNE 方法【14】,第二个是主成分分析(PCA) 。图 6 显示了空手道俱乐部输出嵌入的 PCA 分解。正如你所看到的,根据输入特征/节点间的关系,DepeWalk 可以检索至少 3 个空手道俱乐部细分的主要组。这使得人们可以分析巨大的图表,例如脸书网页,了解网页之间的社会关系,而不用担心处理表示和标签。

图 6:空手道俱乐部深走嵌入的 PCA 2 维表示

请继续关注我们的下一篇文章:DeepWalk 的两个实际应用,以全面了解 Python 实现:)

如果有任何问题或意见,请随时给我发电子邮件,地址是:stefanobosisio1@gmail.com,或者直接在 Medium 这里。

文献学

  1. 周,解,等,“图形神经网络:方法与应用综述”艾公开赛1(2020):57–81。
  2. 佩罗齐、布莱恩、拉米·艾尔弗和史蒂文·斯基纳。"深度行走:社交表征的在线学习."第 20 届 ACM SIGKDD 知识发现和数据挖掘国际会议论文集。2014.
  3. 《向量空间中单词表征的有效估计》arXiv 预印本 arXiv:1301.3781 (2013)
  4. 唐、雷、。"通过潜在社会维度的关系学习."第 15 届 ACM SIGKDD 知识发现和数据挖掘国际会议论文集。2009.
  5. 唐、雷、。“利用社交媒体网络进行分类。”数据挖掘和知识发现23.3(2011):447–478。
  6. 内维尔,詹妮弗和大卫·延森。"使用集体推理的模型偏差/方差分解."机器学习73.1(2008):87–106。
  7. 《向量空间中单词表征的有效估计》 arXiv 预印本 arXiv:1301.3781 (2013)。
  8. 单词和短语的分布式表征及其组合性。神经信息处理系统的进展。2013.
  9. 大卫·格思里等着,〈跳过语法建模的更近距离观察〉。 LREC 。第六卷。2006.
  10. Gittens,Alex,Dimitris Achlioptas 和 Michael W. Mahoney。" Skip-Gram Zipf+Uniform =矢量可加性."计算语言学协会第 55 届年会会议录(第一卷:长篇论文)。2017.
  11. 明诺、大卫和劳雷·汤普森。"负抽样跳跃图的奇异几何."自然语言处理中的经验方法。2017.
  12. Mnih,Andriy 和 Geoffrey E. Hinton。"一个可扩展的分层分布式语言模型."神经信息处理系统进展21(2008):1081–1088。
  13. 莫林,弗雷德里克,还有约舒阿·本吉奥。"分层概率神经网络语言模型."人工智能与统计国际研讨会。PMLR,2005 年。
  14. 辛顿、杰弗里和萨姆·t·罗伊斯。“随机邻居嵌入。”钳口。第 15 卷。2002.

图形神经网络:2008 年以来的学习之旅——图形卷积网络

原文:https://towardsdatascience.com/graph-neural-networks-a-learning-journey-since-2008-graph-convolution-network-aadd77e91606?source=collection_archive---------15-----------------------

图形卷积网络(GCN)在数学上很难理解,但是让我们跟随我的第四篇文章,一步一步地分解 GCN

约翰·罗德恩·卡斯蒂略在 Unsplash 上拍摄的图片

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

我以前关于图形和 ML 的帖子:

  • 图形神经网络:2008 年以来的学习之旅——第一部分
  • 图形神经网络:2008 年以来的学习之旅——第二部分
  • 图形神经网络:2008 年以来的学习之旅——深度行走
  • 图形神经网络:2008 年以来的学习之旅——Python&深度行走

在我们之前的文章中,我们看到了斯卡塞利的图形神经网络思想[1–4]如何彻底改变了构建典型 ML 问题的方式。自 2008 年以来的几年中,图上的 ML 已经成为一个热门话题,越来越完善和改进了 Scarselli 的第一个开创性方法。上一次我们看到了 Perozzi 的 DeepWalk 方法[5]对 GNN 的改进,社区第一次开始讨论“节点嵌入”[6–8]。

今天要给大家展示一个非常流行的算法:图卷积网络[9]。这篇文章涵盖了 2014 年至 2017 年间的出版物。在这 3 年里,科学家们投入了大量的精力将著名的卷积神经网络方法应用于图形。事实上,为什么卷积在图像上非常有效?为什么不能直接应用到图中?如何将图转化为卷积项?有什么数学方法可以让我们达到这个目的吗?

在这篇文章中,我们将涵盖 GCN 的理论方面,从定义卷积运算到图形卷积。下一次,我们将介绍 Kipf GCN 算法的 Tensorflow 实现。

卷积什么?

神经网络是一个连续的仿射变换【15,16】:给定一个输入向量,网络将其乘以一些矩阵,生成一个输出。输入向量可以是 1D 信号、图像、视频,并且通常是多维数组。该阵列具有不同的轴,例如,图像具有专用于 RGB 通道的轴,另一个轴定义高度,另一个轴定义宽度。仿射变换中不使用轴,这里卷积开始发挥重要作用,以帮助神经网络输出产品。离散卷积[17]是一种线性变换,,其中输入特征图和卷积核相乘

图 1:图像卷积的例子。A)3×3 像素大小的核乘以给定图像(输入特征图,例如 10×10)中的重叠区域。橙色阴影区域定义了与卷积(黑色)内核相乘的输入要素地图区域。b)对于重叠的 3x3 区域,点积返回 1 个单值。基于步距值,卷积继续下一个输入区域(例如,这里我们将卷积核移动 3 个像素)。作者图片

每个重叠的输入特征地图片是具有滑动卷积核的点积,返回最终的输出图像/矢量。为了固定一些关于卷积的一般概念,我们可以用数学方法将卷积定义为积分:

等式 1:卷积积分。在时域中,在输入特征矩阵 f 上执行的卷积是输入 f 的域上的积分

其中 f 为输入特征图,圆星为时域卷积运算, g 为输入卷积核。卷积是在输入特征映射域τ上的积分,由 定义(例如,这可以是立方体、由图像定义的平面、向量等), g(t- τ) 是卷积核,其在输入特征映射上滑动τ步 f(τ) 。这个积分可以转换成一个和,得到一个离散的卷积。这里,内核可以基于以下参数化:

  • n 输出特征地图的数量
  • m 输入特征地图的数量
  • k 轴上定义的ⱼthe 内核尺寸 j

卷积层沿轴 j 的输出大小 oⱼ 受以下因素影响:

  • Iⱼ*t31】输入沿轴尺寸 j*
  • kⱼ 沿轴线的内核尺寸 j
  • sⱼ 沿轴的步幅 j
  • pⱼ 沿轴补零 j

我们可能会发现这些术语不时出现在我们的卷积码中,为了使它更清楚:

  • 步幅是内核的两个连续位置之间的距离
  • 零填充是添加到图像中的零的附加“帧”,通常是为了使图像大小达到 2 的幂

卷积与神经网络配合得很好,提供了输入信号的线性变换。然而,卷积只有且仅当:

  • 可以在网格上描述输入信号(例如向量、图像、3D 立方体)
  • 输入具有主要的局部统计(例如,一组像素主导图像的信息内容)

当处理 3D 网格或社交媒体数据,即图形时,这是一个很大的问题。这些对象没有基于网格的数学域,因此卷积不能将图形作为输入信号进行处理。然而,数学可以帮助我们,提供一个绝妙的解决方案。

图表:数学见解

为了在图上应用卷积,第一个技巧是获得地图位置 [10]的新定义。在图像情况下,局部性可以被认为是主要的局部统计。在图中,G=(N,E) (或 G=(V,E) 根据 Kipf 的论文【9】),给定阈值δ,局部性可以基于节点的邻域来表示:

等式 2:图中的局部性。给定节点特征必须满足的阈值,我们可以定义节点 j 的局部性,查看满足给定特征值 Wij 阈值的所有节点 I

在给定一个节点 j 的情况下,邻域局部性可以被表示为其特征 W ᵢⱼare 大于给定阈值的所有那些节点 i

由此,有可能得到该图的紧凑表示,其中节点的邻域平均值可以用作节点特征值,如图 2 所示

图 2:图中的位置。通过等式 2 定义局部性可以通过将其特征与其所有相邻(红色圆圈)特征的值进行平均来获得红色节点的隐藏表示。图片由作者提供,灵感来自吴等人【18】

对于平均局部性,卷积滤波器可以接受邻域主导统计,输入层的大小最大为 O(Sn)* ,其中 S 是给定 n 个节点的邻域大小的平均值。

第二个基本技巧是从图的数学表示中提取属性,拉普拉斯矩阵L【19】。一个拉普拉斯定义为 L = D — A ,其中 D 为度矩阵, A 为邻接矩阵。 D 矩阵指出每个节点有多少个连接,而 A 哪些节点相互连接(图 3)

图 3 左边的示例图,每个节点的度 D 矩阵,邻接矩阵 A 和拉普拉斯 L,其中 L=D-A。

因此,Laplacian 是描述图以及节点的连接如何影响图的动力学的一种伟大的、简洁的和高度信息化的方式。为了进一步欣赏和理解拉普拉斯在图上的作用,我们可以看到一个经典的例子,它解释了热量如何在给定的图上扩散。给定一个热变量φ,其中φᵢ是节点 i 和节点 jφⱼ的热量,从经典物理学中我们知道从 i 传递到 j 的热量与材料热容 κ 成正比,如κ(φᵢ—φⱼ)。因此,热量随时间在曲线图中的演变可以通过以下等式来描述:

方程 3:图上的热量方程。节点 I 和 j 之间的热传递可以容易地分解成图的拉普拉斯算子

这个等式可以用 Python 代码实现,我们可以得到热扩散:

图 4:通过拉普拉斯热方程在图上的热扩散。随着时间的推移,热量在节点的邻居之间平稳地扩散。图片由 Ctralie 、知识共享许可、链接

正如你所看到的,拉普拉斯矩阵 L 告诉我们热量如何从(本例中为三个)起始点均匀地扩散到整个图表中。

填补空白:拉普拉斯和傅立叶变换

L 可以表示为对称正交矩阵(等式 4)

等式 4:拉普拉斯算子可以表示为对称正交矩阵

其中 I 是单位矩阵, -1/2 是度矩阵 D 的幂, A 是邻接矩阵。对称正交 L 矩阵是半正定的,这保证了它有实的特征向量和特征值。

该条件允许通过频谱分解(等式 5)来表达 L

等式 5:拉普拉斯矩阵的频谱分解

其中 U 是正交矩阵基,λ是具有正特征值的对角矩阵, T 幂代表转置。构成实数域中的标准正交基。由此可见, L 的每个特征向量可以与图中的相应节点相关联。如果节点改变位置,那么特征向量将相应地重新排列— 排列不变。其次, L 的本征函数可以进一步重排为复指数。

此时,你的脑海中应该会响起一个铃声。通过欧拉公式,复指数可视为时域中的一系列正弦曲线。这意味着傅立叶变换和拉普拉斯特征值之间存在关系。在傅立叶域中,卷积(等式 1)是输入信号 x 和卷积核 gϑ:之间的乘法

等式 6:输入信号的拉普拉斯算子(图)和傅立叶域中的卷积之间的关键关系

其中 F 代表傅立叶变换, U 是归一化图拉普拉斯的特征向量的矩阵(等式 5)。这意味着拉普拉斯算子定义了傅立叶基,因此它返回输入图的傅立叶基视图,因此拉普拉斯算子可用于计算图上的卷积。具体而言,通过计算图的拉普拉斯算子的特征向量,可以在给定图的频谱上计算卷积及其权重[20]。

Thomas Kipf 和 Max Welling 在 2017 年发表的《图形卷积网络》

现在,所有这些数学框架都很棒,我们可以考虑将拉普拉斯谱分解应用于一个图,将其传递给一些神经网络层和激活函数,工作就完成了。不幸的是,通过拉普拉斯算子的卷积在计算上是不可行的,并且非常昂贵。为了解决这个问题,Kipf 和 Welling 以及 Hammond 在 2011 年的论文中提出了傅立叶卷积滤波器 gϑ:的切比雪夫多项式 Tₖ(x) 的截断展开

方程 7:用切比雪夫多项式逼近卷积滤波器

其中θ’表示切比雪夫多项式系数的向量, Tₖ 是切比雪夫多项式的递归公式,λ是基于图拉普拉斯矩阵的最大特征值的重定标常数。将等式 7 并入等式 7,可以获得卷积的最终切比雪夫近似:

等式 8:图形卷积的切比雪夫近似

等式 9:重新缩放的拉普拉斯算子

其中 tilded L 是重新缩放的图拉普拉斯算子(等式 9)。该表达式是 K 局部化的,即它是拉普拉斯算子中的第K阶切比雪夫多项式,因此它仅依赖于距离中心节点最多 K 步的节点 N (重新定义图的局部性)。然后计算复杂度降低到 O(E) ,所以依赖于边数。

给定等式。8 上图卷积网络可以通过堆叠多个卷积层来实现,每层之后是逐点非线性。因此,对于给定的层 l+1 ,图的逐层传播将是:

等式 10:GCN 的逐层传播规则

其中 H 是第ll+1层的激活矩阵,σ是类似于 ReLu 的激活函数, W 是特定层的可训练权重矩阵。这是图卷积神经网络的核心公式,由 Kipf 在 2017 年提出。现在让我们看看空手道俱乐部的 Python 实现!

空手道俱乐部和 GCN

首先,让我们直接从networkx Python 库加载空手道俱乐部:

图 5:导入库并创建空手道幼崽

其次,我们可以创建图邻接矩阵adj和一个简单的一键编码图特征矩阵X :

图 6:创建空手道俱乐部邻接表和特征(一键编码矩阵)

然后,我们将创建度矩阵deg,通过一个自连接邻接矩阵adj_self,即带有自项连接的邻接矩阵:

图 7:邻接自连接矩阵和归一化度矩阵

现在,是时候实现 GCN 方法了,如图 8 所示。最初,我们需要定义 ReLu 函数,这只是np.maximum(input_value, 0)。其次,我们可以定义 GCN 中的逐层传播规则,即等式 10。该函数将邻接矩阵、度矩阵、图形特征矩阵和第 I 层权重作为输入。最后,初始化层权重,设置 2 层——但是你可以设置任意多的层——给 GCN 一个机会!

图 8: GCN 实现:ReLu 函数、分层传播、权重初始化和模型运行。

请继续关注我们的下一篇文章:我们将深入研究 Kipf 使用 Tensorflow 的 GCN 实现。

如果有任何问题或意见,请随时给我发电子邮件,地址是:stefanobosisio1@gmail.com,或者直接在 Medium 这里。

文献学

  1. 《网页排序的图形神经网络》。2005 年 IEEE/WIC/ACM 网络智能国际会议(WI'05) 。IEEE,2005 年。
  2. 戈德堡,安德鲁 v,和克里斯哈里森。"计算最短路径:搜索符合图论."汽水。第五卷。2005.
  3. 《网页排序的图形神经网络》。2005 年 IEEE/WIC/ACM 网络智能国际会议(WI'05) 。IEEE,2005 年。
  4. 《图形神经网络模型》 IEEE 神经网络汇刊20.1(2008):61–80。
  5. 佩罗齐、布莱恩、拉米·艾尔弗和史蒂文·斯基纳。"深度行走:社交表征的在线学习."第 20 届 ACM SIGKDD 知识发现和数据挖掘国际会议论文集。2014.
  6. 《向量空间中单词表征的有效估计》arXiv 预印本 arXiv:1301.3781 (2013)
  7. 唐、雷、。"通过潜在社会维度的关系学习."第 15 届 ACM SIGKDD 知识发现和数据挖掘国际会议论文集。2009.
  8. 唐、雷、。“利用社交媒体网络进行分类。”数据挖掘和知识发现23.3(2011):447–478。
  9. 基普夫,托马斯 n,和马克斯韦林。"图卷积网络的半监督分类." arXiv 预印本 arXiv:1609.02907 (2016)。
  10. 琼·布鲁纳等着《图上的谱网络和深局部连通网络》第二届学习代表国际会议,ICLR 。第 2014 卷。2014.
  11. 阿特伍德,詹姆斯和唐·陶斯利。"扩散卷积神经网络."神经信息处理系统的进展。2016.
  12. 迪费拉德、米歇尔、泽维尔·布列松和皮埃尔·范德盖恩斯特。"具有快速局部谱滤波的图上的卷积神经网络."神经信息处理系统进展 29(2016):3844–3852。
  13. 学习分子指纹的图形卷积网络。 arXiv 预印本 arXiv:1509.09292 (2015)。
  14. 哈蒙德、大卫·k、皮埃尔·范德盖恩斯特和雷米·格里邦瓦尔。"通过谱图论研究图上的小波."应用和计算谐波分析30.2(2011):129–150。
  15. 学习仿射变换。模式识别32.10(1999):1783–1799。
  16. 李,文静,和唐利。"仿射不变匹配的 Hopfield 神经网络."IEEE 神经网络汇刊 12.6(2001):1400–1410。
  17. 离散傅立叶变换和卷积的算法。斯普林格,1989 年。
  18. 吴,,等,“图神经网络综述” IEEE 神经网络和学习系统汇刊32.1(2020):4–24。
  19. 《拉普拉斯矩阵》 https://mathworld。 沃尔夫拉姆。com/ (1999)。
  20. Singh,Rahul,Abhishek Chakraborty 和 B. S. Manoj。"基于有向拉普拉斯的图形傅立叶变换." 2016 国际信号处理与通信会议(SPCOM) 。IEEE,2016。

图形神经网络:2008 年以来的学习之旅——第一部分

原文:https://towardsdatascience.com/graph-neural-networks-a-learning-journey-since-2008-part-1-7df897834df9?source=collection_archive---------17-----------------------

图形神经网络获得了越来越多的成功,但它们到底是什么?它们是如何工作的?让我们一起来看看这些故事中的图表吧!今日:斯卡塞利关于图形神经网络的开创性论文

图片由张秀坤·施罗德在 Unsplash 上拍摄

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

数据通常很容易被形象化并解释为图表。除了揭示数据点之间的潜在关系,图表还有助于在复杂的模式中找到隐藏的答案。因此,图形应用无处不在也就不足为奇了,从社交媒体分析[1–5]到神经科学[6,7],页面排名[8–10],最短路径理论[11–14]和化学[15–19]。

自 2006 年以来,随着图形神经网络应用的新概念,图论与机器学习有了密切的联系。Scarselli 和 Gori [20]在 2006 年发表了第一个建议,随后在 2008 年[21]通过论文“图神经网络模型”对其进行了概括。在这里,作者为现代图形神经网络奠定了数学基础。从那以后,文献中出现了 graph ML 作品[22–28]的高峰,这使得图形世界越来越进化,更精确地定义了这些数学结构的关键元素,以及如何将它们与更精确的机器学习算法联系起来。

我认为每一篇关于图论和 ML 的论文都是一次冒险,作者们正在建立他们的术语和数学发展。因此,我想开始这一系列关于图形的教程,用严密的数学和 Python 中的计算例子给出一个简单的解释。今天,我们将从斯卡塞利的主要论文“图形神经网络模型”开始这一旅程。让我们开始吧!

图形神经网络模型

定义

图形神经网络(GNN)源于两种 ML 技术:递归神经网络(RNN)【30–32】和马尔可夫链【33–35】,其中的基本思想是使用图形编码数据,利用节点之间的关系。特别地,RNN 方法是图集中的,其中用户的目标是在用带标签的图训练之后给给定的图加标签。马尔可夫链方法是以节点为中心的,其中每个节点都被标记,用户正在寻找节点级的预测。GNN 模型封装了从这些以前的模型中获得的知识,适用于以图形和节点为中心的应用程序。

此外,GNN 推广了基于图的计算,以处理对称非对称 图,图 1。如果在修改节点位置后,节点之间的属性不变,则该图被定义为对称的,即您总是获得相同的图。相反,在非对称图中,顺序非常重要,因为通过改变节点的位置可以获得不同的图。在不对称的情况下,一对节点定义了一条称为的边,并且该图被称为有向——即,它具有特定的方向。

图 1:A)对称图形和 B)不对称图形的例子。在前一种情况下,如果改变节点的顺序,图形不会改变,而在不对称情况下,图形在节点中具有特定的顺序。作者图片

计算洞察力

至于计算图,每个节点都被赋予了一些属性,这些属性被收集到一个标签。标签是具有预定义维度的向量,其编码描述每个节点的特征(例如,图像中像素的平均颜色、对象的形状等)和节点-边缘之间的关系(例如,图像识别中感兴趣的点之间的距离等)。).给定基本的特征条件,图结构与简单的神经网络显著不同。事实上,每个节点都可以知道在其邻居中正在发生什么,并且可以看到相邻节点的当前状态(或特征)(图 2)

图 2:让我们检查一个图形网络。所有节点都有它们自己的标签(l1,l2,l3,l4)以及状态向量 x (x1,x2,x3,x4)和边信息(l12,l13,l14,l15)。由于转移函数 fw,每个节点的状态,例如节点 1 x1,是所有相邻节点的状态的函数。作者图片

因此,可以将一个图定义为一个数学对象。每个节点都有一个定义的状态 x ₙ,其中包含节点的特征以及邻居的特征。此外,每个节点具有相关联的局部转移函数 f𝓌 ,其对特征 x ₙ相对于节点 n 的上下文的依赖性进行建模,以及描述每个节点的输出如何产生的局部输出函数 g𝓌

情商。1:图形网络的位置形式。节点 n 的状态 x_n 取决于节点标签 ln、边标签 l_co[n]、邻居状态 x_ne[n]和邻居节点标签 l_ne[n]。上的输出取决于本地输出函数 gw,它是通过节点 n 的状态 x_n 和标签 l_n 计算的。

到目前为止一切顺利,但在处理与 f𝓌.的关系时有问题根据邻域大小或邻居集合未排序的情况,可能会有数量可变的自变量。因此 f𝓌.应该是不变量对邻域中节点的排列。为了满足这种数学和技术上的约束,可以将 f𝓌 推广为 h𝓌.的函数这个最后的转移函数对于图中的节点位置和节点数量是不变的,并且它取决于节点 nu 之间的弧线的给定标签

情商。2:方程 1 的非正形式。在这种情况下,我们可以通过一般的转移函数 h_w 来定义节点 n 的状态 x_n,该转移函数依赖于节点标号 l_n、节点 n 和节点 u 之间的弧标号 l_(n,u)、节点 u 的状态 x_u 和节点 u 的标号 l_u。

一个要求:Banach 不动点定理

一旦定义了一个图的主要函数和结构,就需要一个状态 x ₙ的计算——我们需要定义 a .斯卡塞利处理 GNN 计算的核心点是 巴拿赫不动点定理 Banach 不动点定理也叫 c 压缩映射定理。该定理建立了在定义的度量空间中压缩映射函数的不动点的存在唯一性。这是什么意思?

  • 数学中的不动点是给定函数 F 的解,即当函数是恒等式时
  • 然后,考虑距离的概念,即两点 ab 相距多远。给定一组数字 X,,可以计算这些点之间的距离。距离度量定义了一个新的空间,称为度量空间,由集合 X 和距离函数 (X,d) 的结果表示
  • 现在,在这个度量空间中,我们可能有一个数学函数 F ,它可以应用到点 ab 来检索另一个度量。如果结果点 F(a)F(b) 之间的距离小于 ab 之间的真实距离,则 F收缩图
  • 如果 F 是一个压缩映射,那么 Banach 证明了对于这样一个函数存在一个不动点解

这样一个定理的结果是,有可能用迭代方案计算当前节点的状态。我们可以说,基本上每次都更新节点状态,以便找到正确的标签。

此时,我们几乎准备好进入生产阶段。但是,对于 f𝓌/h𝓌g𝓌 要有什么函数才能满足巴拿赫不动点定理呢?惊喜,惊喜,这里是 GNN 的第二个重要部分:这些功能可以是简单的多层感知器(MLP)。事实上,MLP 可以利用通用近似理论,所以他们满足巴拿赫的要求。最初,每个单元都启动了随机状态。 f𝓌/h𝓌 函数将更新这些状态,直到实现收敛,即找到定点解。然后,可以使用 g𝓌 进行最终的 MLP 计算,这将依次返回每个节点或图形本身的输出预测。

既然我们已经从理论上了解了 GNN 是如何工作的,请继续关注下一篇文章,我们将通过计算实现 GNN!

图 3:图形神经网络(GNN)的最终视图。原始图可以被看作是从时间 T 到时间 T+步骤的时间上的步骤的组合,其中每个功能接收输入的组合。fina 展开图每一层对应一个时刻,并有一个先前步骤的所有单位的副本。

如有任何问题或意见,请随时发送电子邮件至:stefanobosisio1@gmail.com 或直接发送至 Medium。

文献学

  1. 艾索普斯、福蒂斯、乔治·帕帕达基斯和提奥多拉·瓦里古。“使用 n 元图对社交媒体内容进行情感分析。”第三届 ACM SIGMM 社交媒体国际研讨会论文集。2011
  2. 威廉·坎贝尔、查理·k·达格里和克利福德·j·温斯坦。"带有内容和图表的社会网络分析."林肯实验室期刊20.1(2013):61–81。
  3. 《推特对话图的重建和分析》首届 ACM 跨学科社会网络研究热点国际研讨会论文集。2012.
  4. 推特时间演变分析:比较事件和话题驱动的转发图。 IADIS 国际计算机科学杂志&信息系统 11.2 (2016)。
  5. 伊曼纽·罗西等人,《动态图上深度学习的时态图网络》arXiv 预印本 arXiv:2006.10637 (2020)。
  6. 丹尼尔·s·巴塞特、佩里·朱恩和约书亚·I·戈尔德。"网络神经科学中模型的本质和使用."自然评论神经科学19.9(2018):566–578。
  7. 斯波恩斯,奥拉夫。"图论方法:在大脑网络中的应用."临床神经科学对话 20.2 (2018): 111。
  8. 阿贝丁、巴巴克和巴巴克·索拉比。"图论在网站链接结构改进中的应用及网页排序."行为&信息技术28.1(2009):63–72。
  9. 乔治·梅加布。"谷歌的网页排名适用于不同的拓扑网络图结构."美国信息科学与技术学会杂志52.9(2001):736–747。
  10. 《网页排序的图形神经网络》。2005 年 IEEE/WIC/ACM 网络智能国际会议(WI'05) 。IEEE,2005 年。
  11. 戈德堡,安德鲁 v,和克里斯哈里森。"计算最短路径:搜索符合图论."汽水。第五卷。2005.
  12. 盖洛、乔治和斯特凡诺·帕洛蒂诺。"最短路径算法。"运筹学年鉴13.1(1988):1–79。
  13. 博格瓦德,卡斯滕 m,和汉斯-彼得克里格尔。"图上的最短路径核."第五届 IEEE 数据挖掘国际会议(ICDM 05)。IEEE,2005 年。
  14. 网格图的最短路径算法。网络 7.4(1977):323–334。
  15. 图论在化学中的应用。化学信息和计算机科学杂志 25.3(1985):334–343。
  16. 拓扑量子化学的图表理论数据。体检 E 96.2 (2017): 023310。
  17. 拓扑量子化学的能带连接性:作为图论问题的能带结构。体检 B 97.3 (2018): 035138。
  18. 预测化学反应性的图形卷积神经网络模型。化学科学10.2(2019):370–377。
  19. 基于自我注意的信息传递神经网络预测分子亲脂性和水溶性。化学信息学杂志 12.1(2020):1–9。
  20. 《网页排序的图形神经网络》。2005 年 IEEE/WIC/ACM 网络智能国际会议。IEEE,2005 年。
  21. 《图形神经网络模型》IEEE 神经网络汇刊 20.1(2008):61–80。
  22. 佩罗齐、布莱恩、拉米·艾尔弗和史蒂文·斯基纳。"深度行走:社交表征的在线学习."第 20 届 ACM SIGKDD 知识发现和数据挖掘国际会议论文集。2014.
  23. 李,,等,“门控图序列神经网络” arXiv 预印本 arXiv:1511.05493 (2015)。
  24. 量子化学的神经讯息传递。机器学习国际会议。PMLR,2017。
  25. 基普夫,托马斯 n,和马克斯韦林。"图卷积网络的半监督分类." arXiv 预印本 arXiv:1609.02907 (2016)。
  26. 图卷积网络的简化。机器学习国际会议。PMLR,2019。
  27. 汉密尔顿、林子幸、Rex Ying 和 Jure Leskovec。"大型图上的归纳表示学习."第 31 届国际神经信息处理系统会议录。2017.
  28. 彼得·w·巴塔格利亚等人,《关系归纳偏差、深度学习和图形网络》 arXiv 预印本 arXiv:1806.01261 (2018)。
  29. 小团体中冲突和分裂的信息流模型。人类学研究杂志 33.4(1977):452–473。
  30. 弗拉斯科尼、保罗、马尔科·戈里和亚历桑德罗·斯佩尔杜蒂。"数据结构自适应处理的通用框架."IEEE 神经网络汇刊 9.5(1998):768–786。
  31. 斯珀杜蒂、亚历山德罗和安东尼娜·斯塔丽塔。"用于结构分类的监督神经网络."神经网络 IEEE 汇刊 8.3(1997):714–735。
  32. 哈根布奇纳,马库斯,亚历桑德罗·斯佩尔杜蒂和阿忠蔡。“自组织映射,用于结构化数据的自适应处理。”IEEE 神经网络汇刊 14.3(2003):491–505。
  33. 布林、谢尔盖和劳伦斯·佩奇。“大规模超文本网络搜索引擎的剖析。”计算机网络和 ISDN 系统30.1–7(1998):107–117。
  34. 《超链接环境中的权威来源》汽水。第 98 卷。1998.
  35. 蔡,阿忠,等,〈网页的适应性排序〉。第 12 届万维网国际会议论文集。2003.

图形神经网络:2008 年以来的学习之旅——第二部分

原文:https://towardsdatascience.com/graph-neural-networks-a-learning-journey-since-2008-part-2-22dbf7a3b0d?source=collection_archive---------34-----------------------

关于斯卡塞利图形神经网络的第二个故事。今天,让我们来实现我们所学的:Python 中的 GNN

布雷迪·贝里尼在 Unsplash 上拍摄的照片

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

我们在本系列的第一部分中学习了斯卡塞利图形神经网络的理论背景。特别是,我们了解到:

  • GNN 既适合基于节点的预测,也适合基于图的预测。在前一种情况下,我们希望预测图中的每个节点,在后一种情况下,我们希望预测整个图
  • 每个节点可以用一个转移函数 f𝓌 和一个输出函数 g𝓌 来表示。
  • 为了收敛到一个解,转移函数和输出函数都必须满足 Banach 的不动点解
  • 多层感知器(MLP)确实满足巴拿赫的要求,因此 f𝓌g𝓌 可以实现为简单的神经网络层

记住这几点,让我们一步一步地看看如何用 Python 实现这个框架,并把它应用到一个简单的问题上,这个问题叫做“空手道俱乐部”。

空手道俱乐部

我们以扎卡里的空手道俱乐部问题为例。这个问题可以追溯到 Zachary 的论文“小群体中冲突和裂变的信息流模型”[29],其中对一个空手道俱乐部网络进行了三年(1970–1972)的研究。该网络由 34 名成员组成,包括空手道俱乐部管理员“约翰 A”和教练“嗨先生”,以及在俱乐部外互动的成对成员之间的联系(他们聚在一起喝啤酒,散步……)。在管理者和指导者之间的一场争论之后,俱乐部分裂成两半,因此两个新的组被创建。扎卡里用福特-富尔克森算法正确预测了成员如何重新安排他们的社交网络/每个成员的决定。这个问题引起了图形爱好者社区的注意,它被广泛用于测试 GraphNN。斯卡塞利 2009 年的论文应用图形神经网络正确预测了空手道俱乐部成员在分裂后的决策。

Github 回购和安装

主要脚本存储在此存储库中:

https://github.com/Steboss/learn_graph_ml/tree/master/Scarselli_GNN

在继续之前,我建议您在一个工作目录中创建一个虚拟环境(只需输入您的终端python -m venv venv,就会创建一个venv文件夹)。然后,您可以安装这些软件包:

  • dgl是 Deep Graph Library,一个专门从事图形计算的库。在培训步骤中,我们将使用它来可视化我们的图表。要安装dgl,请在此页面插入您的硬件信息:https://www.dgl.ai/pages/start.html(例如None CUDA、Pip(stable)包、Mac Os 和Python 3.8版本,这样我就可以用下面的命令pip install dgl -f https://data.dgl.ai/wheels/repo.html)安装dgl。如果您在使用pip时遇到问题,只需使用pip install --upgrade pip进行升级,一切都会正常工作。
  • pip install torch
  • pip install tensorflow
  • pip install matplotlib
  • pip install seaborn

脚本和图形介绍

正如你在 Github repo 中看到的,有几个脚本。以下是对它们的简单描述:

  • create_and_visualize.py允许创建初始图形并在训练期间绘制图形
  • prepare_edge_nodes_mat.py提供了边、标签和节点的特征。创建两个矩阵:E边矩阵和图形 id,N节点特征矩阵和图形 id
  • prepare_GNN.py变换EN矩阵作为图形神经网络的输入。输出是一个inp矩阵,其形式为[source_node, destination_node, features of the source node, features of the destination node]arcnode矩阵,一个稀疏矩阵,节点之间有边连接,例如[source_node, destination_node, 1 at source index position 0 otherwise]
  • input_and_output_funcitons.py定义了 f𝓌g𝓌 神经网络,以及验证指标和损失
  • GNN.py主图形神经网络类,其中定义了训练条件,以及收敛性检查。最终输出是训练损失、节点预测、节点在训练期间的位置以及收敛的迭代次数。
  • karate.py是主脚本,创建空手道数据集并训练 GNN。

作为第一步,我们可以运行create_and_visualize.py来可视化空手道俱乐部图。您可以在一个ipyhton shell 中运行这个脚本:

图 1:在 Python shell 中,只需输入上面的命令就可以显示输入的空手道俱乐部图

该图是通过build_karate_club_graph()函数中的dgl.DGLGraph()创建的。visualize_karate_club()通过转换输入图to_networkx()产生输出(图 2)

图 2:作为图表的空手道俱乐部。该俱乐部由 34 个人组成,在分裂后,他们决定根据自己的特点分成两组。

图解说明

图 3 示出了计算步骤的图形研究。从初始图创建两个矩阵:节点特征 N 矩阵和边矩阵 e。然后这两个矩阵被转换为图神经网络的输入。特别地,矩阵 e 和来自矩阵 n 的特征被用作转移函数 f𝓌 的输入。这个神经网络输出与 arcnode one-hot 编码矩阵相乘,以更新节点的状态。最终输出用作函数 g𝓌 的输入,以产生最终预测

图 3:计算方法的图示。输入图被细分为矩阵 N 和 e。从那里,GraphNN 的输入矩阵被创建。矩阵 inp 是边矩阵和特征的组合,而 arcnode 将边连接定义为一个一键编码矩阵。然后,inp 矩阵被用作 NN fw 的输入。节点状态由 matmul 用 arcnode 矩阵更新。通过输出函数 gw 产生最终输出

1.输入预处理:边、标签和要素

https://github.com/Steboss/learn_graph_ml/blob/master/Scarselli_GNN/prepare_edge_nodes_mat.py

prepare_edge_nodes_mat.py允许创建两个矩阵:边矩阵E和节点特征矩阵N

为了创建边,我在data/edges.txt中提供了一个输入文件:

图 edges.txt 文件的前 8 行,节点 1 的边

边的矩阵E是从边输入加上定义了graph_id的最后一列创建的,在这种情况下graph_id是 0,因为我们想要节点聚焦的预测。如果您正在执行基于图形的预测,您将添加一个graph_id

矩阵E的最终内容是[source_node, destination_node, graph_id]:

图 5:从输入边创建 E 矩阵并与图 id 值连接

使用sp.eye(np.max(edges+1), dtype=np.float32).tocsr()将节点的特征创建为一个热编码矩阵:

  • sp.eyescipy.sparse矩阵,
  • np.max(edges+1)定义了我们想要的索引的值为 1、
  • tocsr()是压缩稀疏行格式

将特征与graph_id连接,以创建最终节点的特征矩阵N,其内容为[ node's features, graph_id],维度为[number_of_nodes, number_of_nodes+1]:

图 6:前 3 个节点的矩阵 N 内容

在这种情况下,标签(0 或 1)被分配为:

图 7:为每个节点分配标签的代码

最后,脚本随机选取 4 个节点作为监督训练的标记节点。

2.从矩阵到 GNN 输入

https://github.com/Steboss/learn_graph_ml/blob/master/Scarselli_GNN/prepare_GNN.py

prepare_GNN.py帮助从EN矩阵创建神经网络的输入。

第一个输出是inp矩阵。第 22–36 行显示了如何创建输入矩阵,它是边矩阵E和节点特征N.的串联,最终内容是[source_node, destination_node, source_features, destination_features]。例如,对于第一条边,在节点 0 和 1 之间,inp的内容是:

图 8:节点 0 和 1 的 GNN 的输入矩阵。前两个数字指的是节点 0 和 1,接着是节点 0 的功能[1,0,0,…]和节点 1 的功能[0,1,0,…]

第二个输出是 [arcnode](https://github.com/Steboss/learn_graph_ml/blob/9f4868264d41f44495f0acf7e8a8d6d890d4e2c4/Scarselli_GNN/prepare_GNN.py#L46),以SparseMatrix格式对边缘信息进行编码,其尺寸为[number_of_nodes, number_of_edges](本例中为 34x78)。稀疏格式允许节省内存,并且只标识值为 1 的行列索引对,否则为 0。

3.定义输入和输出函数

https://github.com/Steboss/learn_graph_ml/blob/master/Scarselli_GNN/input_and_output_functions.py

input_and_output_functions.py将底层转换和输出函数定义为 MLP。class Net的核心函数是netStnetOut,分别为 f𝓌g𝓌 创建神经网络,定义了一个 2 层神经网络。netSt接收维数为 70 的节点特征,并使用tanh激活函数,用 3 个隐藏节点重新映射这些特征。netOut具有类似的架构,它接收 2 维输入,通过 3 个节点重新映射,并在softmax应用后返回最终预测输出:

图 9:图形 NN 的转换和输出函数。

4.几乎准备好了:主 GNN

https://github.com/Steboss/learn_graph_ml/blob/master/Scarselli_GNN/GNN.py

最后一步是GNN.py,我们将定义神经网络架构应该如何工作。功能convergenceconditionLoop是整个架构的核心部分,在这里更新节点的状态

训练环节从行 293 开始,Loop功能封装在self.loss_op中。在【T23、线 221 ,被称为运行conditionconvergence。最后一个函数更新当前节点的状态:

图 10:更新节点状态的函数收敛

图 10 中的a[:,1]是输入矩阵inp[:,1],即所有的destination_node索引。tf.gather返回每个目的节点的所有old_state值,得到一个 78x2 的矩阵,其值在第一次迭代时为零——因为old_state最初被初始化为一个零矩阵,np.zeros((ArcNode.dense_shape[0], self.state_dim)) ( [行 261](http://self.state: np.zeros((ArcNode.dense_shape[0], self.state_dim)),) )。

sl = a[:, 2:]返回所有的source_nodedestination_node特征(尺寸 78x68),然后连接为inp用于转换神经网络功能。通过矩阵乘法sparse_tensor_dense_matmul用边缘连接更新来自 f𝓌 的输出状态。新状态被传回Loop功能(行 237 ),然后被用作 g𝓌 输出功能的输入:out=self.net.netOut(stf)

空手道俱乐部在行动

您现在可以运行karate.py了!!!

https://github.com/Steboss/learn_graph_ml/blob/master/Scarselli_GNN/karate.py

最终的输出没有什么意义,但它是一个显著的例子,可以看到图形神经网络的力量以及图形如何被用作我们预测的输入。

karate.py脚本的主要部分在第 61 行,在此执行训练步骤。如果您想将最终结果保存为gif,如果您想在tensorboard中可视化神经网络结果,这是打开tensorboard的命令,带有最终输出:

venv/bin/tensorboard --logdir tmp/path/to/folder_with_out.tfevents

将您的浏览器连接到http://localhost:PORT,这里端口被定义为终端中的输出,以充分工作tensorboard

主输出形式g.Trainloop_val。此变量报告:

  • loop_val[0]节点的预测值
  • loop_val[1]为更新状态而执行的迭代次数
  • loop_val[2]当前节点的位置
  • loop_val[3]节点的特性

图 11 将训练运行动画化,从没有节点预测的初始猜测,直到节点之间有线性间隔的结束。

图 11:基于来自 GraphNN 的预测,通过时期的节点细分

今天就到这里吧!请继续关注关于图形和 ML 的新帖子!!!!

如果有任何问题或意见,请随时发送电子邮件至:stefanobosisio1@gmail.com 或直接发送至 Medium。

图形神经网络:2008 年以来的学习之旅——Python 和 Deep Walk

原文:https://towardsdatascience.com/graph-neural-networks-a-learning-journey-since-2008-python-deep-walk-29c3e31432f?source=collection_archive---------31-----------------------

实践教程

本系列的第四部分。今天,深度行走的实际实现🐍看看脸书的大型页面数据集👍

图片由弗朗西丝卡·霍钦在 Unsplash 上拍摄

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

欢迎回到我们在图形机器学习世界的旅程的第四部分。在之前的帖子中,我们看到了deep walk 算法如何工作及其数学背景。今天,我们将深入研究该算法的 Python 实现,从一个简单的例子(空手道俱乐部)开始,在Numpy中有一个简单的 DeepWalk 版本,然后我们将跳转到一个更有趣的场景,使用脸书大型页面数据集。

以下是前几集的列表:

  • 斯卡塞利·GNN 的理论背景
  • 斯卡塞利 GNN 实际实施
  • DeepWalk 理论背景

串联所有深走数学步骤

生成“序列”的语料库

现在我们知道了 DeepWalk 在数学上是如何工作的,让我们一起一步一步地看看空手道俱乐部将会发生什么,在跳到更大的应用之前修正我们的想法。当前的应用程序基于一个简单的numpy嵌入式神经网络应用程序。代码和输入文件可在以下位置找到:

https://github.com/Steboss/learn_graph_ml/tree/master/Perozzi_DeepWalk

输入数据集是data/karate.adjlist,空手道俱乐部的邻接表,graph.py是读取输入文件的实用程序,karate.py是我们的主要 DeepWalk 算法文件。这些计算远非正确,但它们是具体理解正在发生的事情的一个很好的方法。

图 1 空手道俱乐部图表。该俱乐部由 34 名成员组成,我们可以定义 78 种相互之间的交互。

在这个例子中,我们有 34 个节点和 78 条边。对于每个节点,随机行走的次数是number_walks=5,因此总共 170 次随机行走,即从一个起点开始探索一个walk_length=5顶点。在第 378 行,我们正在创建初始语料库:

图 2:长度为 5 的随机游走的“句子”语料库的生成

从这里我们会有一个随机漫步的列表:

图 3:从顶点 22、17、13、18、11 和 15 开始的长度为 5 的随机行走的例子。

Skipgram 模型

一旦生成了语料库,我们就可以继续使用 SkipGram 模型。在这个例子中,我没有实现层次化的 Softmax,但我只是使用了一个简单的 softmax 层,因为问题很小。这些是我们需要的步骤:

  • 生成训练数据:对于每个输入序列,我们需要为训练阶段生成一对 (X,y)X 是当前顶点,而 y 是来自 X 的一个window_size内的字
  • 参数初始化:随机初始化一个单词嵌入矩阵,并执行 2-隐层神经网络的前向步骤
  • 神经网络:更新权重和返回训练成本的函数,以向正确的嵌入收敛。

生成训练数据

训练数据强调了 SkipGram 模型的目标:X是输入单词,并且该模型预测在最大window_size距离处的单词成为X的邻居的可能性。最终的训练数据集将是一组对(X, y)。例如,给定输入序列22, 1, 13, 4, 3wind_size=5,对(X,y)将是(例如):(22, 1), (22, 13), (22, 4), (22, 3), (1, 22), (1, 13), (1, 4), (1, 3), (13, 22), (13, 1), (13, 4)等。函数 [generate_training_data](https://github.com/Steboss/learn_graph_ml/blob/e0c7f6e319919c7a9a75edd8204f8c4163ef2d9c/Perozzi_DeepWalk/karate.py#L105) 完成了这个目标,循环遍历所有输入random_walks及其元素,选择左右索引idxs_leftidxs_right

图 4:生成训练数据功能。Skipgram 模型的对(X,y)是通过迭代所有随机行走及其元素,每次选择相对于起始顶点 I 的左和右索引

最终向量Xy的大小为(1, 3400),其中3400来自随机漫步的总数(170)乘以每次随机漫步的配对数,即20

参数初始化

第二步是初始化以下参数:

  • representation_size这是潜在特征尺寸,即 SkipGram 应该返回多少潜在“坐标”。在本例中,该值固定为 2
  • vocab_size、词汇大小,即图中顶点的总数(vocab_size=34+1=35)
  • 目标y的一键编码矩阵。热编码矩阵的大小为35, 3400,每次目标词出现时,其值为 1:

图 5:将目标向量转换为热编码矩阵,其大小来自词汇大小(+1)和目标大小。

  • epochs为 SkipGram 模式。记住 SkipGram 是一个神经网络,所以我们必须指定我们想要循环通过整个数据集的次数(在本例中是epochs=2)
  • batch_size,神经网络训练的每次迭代应该使用多少数据块(这里batch_size=4096,因为我想立即处理整个数据集)
  • learning_rate,设置为0.001
  • 神经网络的嵌入和权重矩阵,通过函数param_init初始化。在该函数中,我们为单词嵌入创建一个随机矩阵,其大小为vocab_sizerepresentation_size——即对于每个节点,我们将有representation_size坐标。其次,神经网络权重被随机初始化为:np.random.randn(out_size, inp_size)其中inp_size是图顶点的数量,out_sizerepresentation_size

神经网络

至此,我们可以通过以下步骤旋转嵌入神经网络:

  • 从输入数据中定义一块batch_size
  • 运行神经网络的正向传播部分(forward_propagation)
  • 通过反向传播计算梯度(backward_propagation)
  • 更新参数、嵌入矩阵和权重矩阵(update_parameters)
  • 通过交叉熵计算成本(cross_entropy)

SkipGram 的这个numpy实现可以帮助我们理解主 DeepWalk 中隐藏了什么。

图 5:对于每个时期,我们从训练数据集中导出组块,我们执行正向传播、反向传播,并且我们更新所有参数。

首先,forward_propagation检索每个单词的嵌入,node_to_embedding返回训练数据集的所有 3400 个X输入的初始随机嵌入表示。然后,调用linear_dense函数,更新神经网络权重:

图 6:神经网络计算的核心。在每次正向迭代中,单词嵌入与网络权重进行点乘

核心神经网络仅将乘以神经网络权重的单词嵌入作为输入:np.dot(weights, node_vector)最后一步是通过softmax函数计算前一产品的 softmax 层。图 7 示出了输入单词嵌入如何通过网络计算而改变。

图 7:正向传播。让我们花点时间来看看输入数据的演变。随机初始化的单词嵌入通过神经网络。在输入嵌入和网络权重之间计算点积。最后一层是对网络输出的 softmax 计算。

计算出的嵌入和权重需要通过反向传播来更新。函数 [backward_propagation](https://github.com/Steboss/learn_graph_ml/blob/e0c7f6e319919c7a9a75edd8204f8c4163ef2d9c/Perozzi_DeepWalk/karate.py#L308) 计算 softmax 层梯度、神经网络权重梯度和嵌入梯度,因为我们想要训练神经网络和单词嵌入表示。

最后,反向传播输出用于更新输入参数,即单词嵌入和网络权重

图 8:反向传播的更新过程。基于在嵌入层计算的学习速率和梯度来更新单词嵌入和网络权重。

干得好!这些是 deep walk skip program 部分包含的所有步骤。

一个大图数据集分类:脸书大页面-页面网络

为了证明 DeepWalk 获得社会潜在表征的能力,在这个例子中,我们将使用一个大规模数据集,即脸书大型页面-页面网络,可以在这里免费下载1。这是包含 22470 个脸书页面的数据集,根据它们的内容被标记为tvshowgovernmentcompanypolitician以及 171002 个边。边缘描述了社会互动,例如一个页面喜欢另一个页面的内容。处理这个图的代码可以在这里找到:https://github . com/ste boss/learn _ graph _ ml/blob/master/Perozzi _ deep walk/Facebook . py

图 9:脸书数据集一瞥。id 定义节点 id,facebook_id 是唯一的脸书标识符,page_name 是页面的名称,page_type 用作定义节点所属的类的目标。

[代码的第一部分打开1中提供的所有输入文件](https://github.com/Steboss/learn_graph_ml/blob/58454b34333cb7c470ae47425bab1947f2801280/Perozzi_DeepWalk/facebook.py#L49),并将边信息转换为networkx图:

图 10:用 networkx 打开输入数据并转换成图形

其次,我们将从输入图中创建 80 个长度为 10 的随机行走。输出是 224'700(节点*行走长度)次随机行走,这将是 SkipGram 的输入序列:

图 11:在给定输入图、要创建的步数及其长度的情况下,创建随机步的函数。

一旦建立了语料库,我们就可以开始制作[gensim](https://github.com/Steboss/learn_graph_ml/blob/58454b34333cb7c470ae47425bab1947f2801280/Perozzi_DeepWalk/facebook.py#L66)skip program 模型——已经有一个模型多好?—如图 12 所示

图 12:深度行走的核心,一旦随机行走的语料库被创建,我们可以从 Gensim 运行 Word2Vec 算法

Word2Vec接收输入:

  • 句子语料库walks
  • 潜在维度的大小representation_size=100
  • 为给定单词寻找邻居的窗口大小window_size=5
  • 在训练过程中考虑一个单词的最少次数。在这种情况下,0 意味着Word2Vec将把所有的单词作为输入
  • 触发 skip program 模式的选项sg=1
  • 触发分级 softmax hs=1的选项
  • 我们想要运行的迭代次数,可选。在这个例子中是 1
  • CPU 的数量
  • 再现性的随机种子seed=42

这将需要一点时间来运行,但最终我们将得到给定输入图的最终嵌入,可以很容易地保存在文件中,如下所示:

图 13:word 2 vec 的嵌入输出 sved 的例子。22470 表示节点数,100 表示潜在维度。第 2–4 行的第一列是节点索引,而后面的数字是嵌入表示

从这里,我们可以直接询问模型,寻找与给定页面相似的页面。例如,让我们使用索引14,即页面Nasa's Marshall Space Flight Center,并使用model.wv.most_similar()查询模型。model.wv_most_similar(14)返回与页面14相似页面的所有索引及其概率得分

图 14:找到所有与第 14 页相似的页面,美国宇航局马歇尔太空飞行中心

查询输出将是:

图 15:给定页面的 Word2Vec SkipGram 模型的输出

值得注意的是,该模型返回与给定页面高度相似的页面,而没有关于页面正在处理什么的信息。令人印象深刻的是,DeepWalk 可以利用单词模型的简单相似性来询问大输入图!

今天就到这里吧!请继续关注关于图形和 ML 的新帖子!!!!

如有疑问或意见,请随时发送电子邮件至:stefanobosisio1@gmail.com 或直接发送至 Medium。

文献学

  1. Rozemberczki,Benedek,Carl Allen 和 Rik Sarkar。"多尺度属性节点嵌入."复杂网络杂志 9.2 (2021): cnab014。

作为神经扩散偏微分方程的图形神经网络

原文:https://towardsdatascience.com/graph-neural-networks-as-neural-diffusion-pdes-8571b8c0c774?source=collection_archive---------7-----------------------

思想和理论,重新思考 GNNs

图神经网络(GNNs)与控制图上信息扩散的微分方程密切相关。将 gnn 视为偏微分方程(PDEs)会产生一类新的 gnn,它们能够以原则性的方式解决当前图 ML 模型的一些突出问题,如深度、过度平滑、瓶颈和图重布线。

这篇博文与本·张伯伦(Ben Chamberlain)和詹姆斯·罗博顿(James Rowbottom)合著,基于我们的论文 b·张伯伦(B. Chamberlain)、j·罗博顿(J. Rowbottom)等人的论文GRAND:Graph Neural Diffusion(2021)ICML。

“Scala graduum Caloris”的第一页,这是艾萨克·牛顿爵士于 1701 年匿名发表在《皇家学会哲学会刊》上的论文。图中显示的是一个温标,0 表示“冬天空气中的水开始结冰时的温度”(aqua incipit gelu rigescere),12 表示“与人体接触时”测得的温度(contactum corporis humani)。210 的最高温度是“风箱催灶火”的温度。

1701 年3 月,英国皇家学会的哲学会刊发表了一篇匿名的拉丁文笔记,题为“热度的等级”【1】。虽然没有指明名字,但艾萨克·牛顿是作者已经不是秘密了(四年后他将成为“艾萨克爵士”)。在一系列实验中,牛顿观察到

热物体在给定时间内失去的温度与物体和环境之间的温差成正比

—今天以他的名字命名的法律的现代表述2。从数学上来说,牛顿冷却定律产生了热扩散方程,这是一个偏微分方程(PDE ),其最简单的形式如下

x .

这里, x ( ut )表示某一区域上时间 t 和点 u 的温度,lhs(时间导数 )是“温度变化率”,rhs(空间二阶导数或拉普拉斯δx)表示某一点与其周围温度的局部差异该 PDE 是线性的,其解可以封闭形式给出,作为初始温度分布与时间相关的高斯核的卷积[3],

x ( ut)=x(u,0)﹡exp(−|u|/4t)。

更一般地说,必须考虑物体不同的热传导特性,从而得到形式如下的偏微分方程

( ut)= div(a(ut)∇x(ut ))

编码更一般的傅立叶传热定律【4】。

根据牛顿冷却定律(上),物体的温度变化率( )与自身温度和周围温度之差成正比。所得微分方程的解具有指数衰减的形式。傅立叶热传递定律(底部)提供了一个更细粒度的局部模型:温度是一个标量场 x ,它的(负)梯度是一个矢量场−∇ x,代表热量从较热的区域(红色)流向较冷的区域(蓝色),散度 div( −∇ x)是矢量场 −∇ x 通过一个点周围无限小区域的净流量。

扩散偏微分方程出现在许多物理过程中,包括“物质”(无论是能量还是物质),或者更抽象地说,信息的转移。在图像处理中,可以利用上述扩散解释作为图像去噪的线性低通滤波。然而,在去除噪声的同时,这种滤波器也不希望地模糊了不同颜色或亮度的区域(“边缘”)之间的过渡。Pietro Perona 和 Jitendra Malik [5]的一个有影响力的见解是考虑一个与图像梯度|∇x的范数成反比的自适应扩散系数:这样,扩散在“平坦”区域(其中|∇x|≈0)很强,而在亮度不连续的情况下很弱(其中|∇x|很大)。结果是一个非线性滤波器能够从图像中去除噪声,同时保留边缘。

左图:原始图像,中图:高斯滤波器,右图:非线性自适应扩散(图中所示为 Q. Yang,“递归双边滤波” (2012)【的概念上类似的滤波器)。

佩罗娜-马利克扩散和类似的方案创造了一个完整的基于偏微分方程的技术领域,它也从几何学、变分法和数值分析中获得了灵感和方法[6]。对我个人来说,Ron Kimmel 关于图像的数值几何的著作[7]是我爱上微分几何并以此为主题攻读博士学位的原因。变分法和基于偏微分方程的方法统治了图像处理和计算机视觉领域近二十年,在 2000 年代的第二个十年让位于深度学习[8]。

在我们最近在 Twitter [9]的工作中,我们依靠同样的哲学来重新审视图形神经网络。gnn 通过以消息传递的形式在相邻节点之间交换信息来运行,这个过程在概念上等同于扩散。在这种情况下,基础空间是图表,扩散沿着边发生,其中空间导数的类比是相邻结点要素之间的差异。

从形式上看,将扩散过程推广到图形几乎是简单明了的:方程看起来是相同的,

(t)= div(a(x(t))∇x(t))

其中X(t)现在是在时间 t 的节点特征的 n × d 矩阵,梯度是给每个边 u ~ v 分配各自节点特征向量的差的算子, (∇x)ᵤᵥ=xx节点 u 处的散度是从其发散出来的边的特征的总和,(div(x)ᵤ=∑*ᵥwᵤᵥ* 扩散率由形式为a(x)= diag(a(xx )的矩阵值函数表示,其中,如前所述, a 是确定沿边缘扩散强度的函数**

节点和边特征分别类似于图上的标量场和矢量场。渐变产生形状的边缘特征(∇x)ᵤᵥ=x-xᵤ.发散产生形式为(div(x)ᵤ=wᵤᵥxᵤᵥ.的节点特征**

图形扩散方程可以方便地写成如下形式的矩阵微分方程

(t)=(a(x(t)—I)x(t)。**

在大多数情况下[12],这个微分方程没有封闭形式的解决方案,必须数值求解。有大量的数值技术用于求解非线性扩散方程,主要区别在于空间和时间离散化的选择。

T 最简单的离散化用正向时差代替时间导数**

x(k+1)x(k)]/𝜏=[a(x(k)I****x(k)**

其中 k 表示离散时间指数(迭代次数),𝜏是步长,使得 t = k 𝜏.将上面的公式重写为

x(k+1)=[(1−𝜏)I+𝜏a(x(k)】x(k)=q(k)x()**

我们得到一个显式或前向欧拉 方案的公式,其中下一次迭代 X ( k +1)是通过应用线性算子Q(k)【13】从某个 X (开始)从前一次迭代 X ( k )计算出来的只有当时间步长足够小时,𝜏 < 1,该方案在数值上稳定(在某种意义上,输入 X (0)的小扰动会导致输出 X ( k )的小扰动)。**

用后向时差离散时间导数得到(半) 隐式 格式,**

【(1+𝜏)I−𝜏a(x(k)】x(k+1)=b(k)x(k+1)=x*(k【k***

这样命名是因为从前一个迭代推导下一个迭代需要求解一个线性系统,相当于 B 的逆(在大多数情况下,通过线性解算器的几次迭代近似实现)。这个方案是无条件稳定的,这意味着我们可以使用任何𝜏 > 0 而不用担心迭代会失败。**

这些是概念上最简单的离散化技术,在实践中不一定是最好的。在 PDE 文献中,通常使用多步方案,例如龙格-库塔【14】,其中后续迭代被计算为几个先前迭代的线性组合。显式和隐式情况都可以是多步骤的。此外,步长可以根据近似误差【15】进行自适应**

图形扩散方程不同离散化方案的框图表示(从左到右:单步显式欧拉,多步四阶龙格-库塔,单步隐式)。a 表示扩散算子;𝜏是时间步长。

具有针对给定任务优化的参数扩散函数的扩散方程定义了一大类类似图形神经网络的架构,我们称之为图形神经扩散(或者,不客气地说,简称为 GRAND)。输出是扩散方程在某个结束时间T的解 X ( T )。许多流行的 GNN 架构可以被形式化为大参数离散图形扩散方程的实例。具体来说,上面提到的显式方案具有图形注意力网络[16]的形式,其中我们的扩散性扮演了注意力的角色。**

绝大多数 GNN 使用显式单步欧拉方案,其中离散时间索引 k 对应于图形神经网络的卷积或注意力层,并且多次迭代运行扩散相当于多次应用 GNN 层。在我们的形式中,扩散时间参数 t 充当层的连续类比【17】——这种解释允许我们开发更有效和稳定的数值方案,这些方案使用时间上的自适应步骤。特别是,GRAND 允许解决广泛认可的问题深度 gnn 中的性能下降。**

在图形神经扩散中,显式 GNN 层被扩散时间的连续模拟代替。该方案允许训练深度网络(长时间运行扩散)而不会经历性能下降。

T21:有限方案允许使用更大的时间步长和更少的迭代(“层”),代价是迭代的计算复杂性,这需要扩散算子的反演。扩散算子(我们方程中的矩阵 A 与图的邻接矩阵(1 跳滤子)结构相同,而它的逆通常是稠密矩阵,可以解释为 多跳滤子

由于矩阵求逆的效率主要取决于矩阵的结构,因此在某些情况下,将用于扩散的图与输入图分离可能是有利的。这些技术统称为图重布线,已经成为 GNNs 中处理可伸缩性或信息瓶颈的流行方法。扩散框架通过将图形视为某个连续对象(例如流形)[18]的空间离散化,提供了图形重新布线的原则观点,并且某些离散化在数值上更有利。**

2D 拉普拉斯算子的不同离散化(这些离散化的任何凸组合也是有效的)。选择一个离散化,可能在每一点都不同,这是一个欧几里得的“图形重新布线”的类比。

G 图神经扩散为研究许多流行的图形深度学习架构提供了一个原则性的数学框架,也为开发新的架构提供了蓝图。这种思维方式为 GNNs 的一些常见问题提供了新的思路,如功能过度平滑和设计深度神经网络的困难,以及启发式技术,如图形重新布线。更广泛地说,我们相信探索图 ML、微分方程和几何之间的联系,并利用这些主题的大量文献,将在该领域产生新的有趣的结果。

1无名氏, Scala graduum Caloris。calorum descriptions et signa(1701)Philosophical Transactions22(270):824–829 描述了一种新的温标和一种测量它的油基装置,称为“温度计”。在整篇论文中,牛顿使用了 calor (“热”,在现代物理学中具有热能流动的含义,以焦耳为单位测量)一词,而不是更合适的术语“温度”(分子的平均动能,以开尔文度为单位测量),后者尚未被创造出来。S. Maruyama 和 s .御名方守矢,牛顿冷却定律:跟进和探索 (2021) 国际传热传质杂志 164 最近准确地再现了牛顿的实验工作,并认为作者无法解释的多个因素可能是匿名发表论文的原因。**

2很明显,牛顿不了解温度和热量之间的区别,因此基于传热系数概念的“冷却定律”的现代形式是错误的。E. F. Adiutori,传热系数的起源 (1990) 机械工程激烈地争辩说,牛顿不应该被归功于以他的名字命名的定律的发现,而应该将荣誉授予约瑟夫·布雷克和约瑟夫·傅立叶。

[3]通过将 x 展开成傅立叶级数,并将其代入等式的两边,这很容易看出。事实上,解热方程是 j . Fourier(1824 年)开发这个仪器的动机之一,这个仪器今天以他的名字命名。我们公式中的热核还应该有一个额外的依赖于维数的归一化系数,为了简单起见,我们省略了它。

[4]根据傅立叶定律,热梯度∇ x 产生一个热通量h=-ax满足连续性方程ẋ=-div(h),这编码了一个假设,即温度的唯一变化是由于热通量(由发散算子测量的),即这个原理在化学上也被称为菲克定律,源自 a .菲克über 扩散(1855)Annalen der Physik94。有趣的是,阿道夫·弗利克的职位被称为“苏黎世的专业人员”,这是一个值得怀疑的职位,他在成为教授之前的前三年里一直担任这个职位,先是在苏黎世,然后在维尔茨堡。

[5] P .佩罗娜和 j .马利克,“使用各向异性扩散的尺度空间和边缘检测” (1990),12(7):629–639 是一篇开创性的论文,提出了一种基于偏微分方程的自适应图像滤波,错误地命名为“各向异性”严格地说,佩罗纳-马利克非线性扩散方程= div(a(u)∇x),其中 a 是位置相关的扩散系数常数,是非均匀的(意味着扩散系数是非恒定的)但是各向同性的(与方向无关,因为 a 是简单缩放梯度的标量);真实的各向异性扩散方程具有形式= div(a(u)∇x)其中 A ( u )是位置相关的 2×2 矩阵(扩散张量),其根据方向对梯度进行不同的缩放。****

[6]参见 J. Weickert 的《图像处理中的各向异性扩散》一书 (1998) Teubner 对这些方法的教学介绍。遵循佩罗娜和马利克的类似范例的一些有影响力的图像处理框架是由 N. Sochen 等人介绍的 Beltrami 流将图像建模为嵌入式流形,低级视觉的通用框架 (1998) IEEE Trans .图像处理7(3):310–318;c . Tomasi 和 R. Manduchi 的双边滤波器,灰度和彩色图像的双边滤波(1998)ICCV;而非局部指的是 A. Buades 等人的,一种图像去噪的非局部算法 (2005), ICCV 。这些方法的各种版本在图像处理硬件中实现;我甚至在英特尔实感相机的早期版本中自己开发了一个。基于 PDE 的低级计算机视觉方法包括图像完成技术,如 M. Bertalmio 等人的图像修补 (2000) 计算机图形和交互技术活动轮廓分割技术,如 V. Caselles 等人的测地线活动轮廓(1997)IJCV22(1):61–79 和 T. F. Chan 和 l 图像处理 10(2):266–277。****

[7] R. Kimmel, 图像的数值几何 (2004)施普林格。

[8]基于偏微分方程的方法和变分方法之间的联系源于这样一个事实,即许多偏微分方程可以作为一些泛函的最优性条件(称为 欧拉-拉格朗日方程 )导出,例如测量结果图像的“质量”。例如,齐次扩散方程是狄利克雷能量的最小化流(粗略地说,是变分问题中梯度下降的连续类比)。设计一个泛函,导出一个最小化它的偏微分方程,并在图像上运行它的范例在概念上非常吸引人;然而,大多数这种“手工制作”的泛函往往是理想化的,与深度学习相比表现较差,这是过去十年基于偏微分方程的方法消亡的主要原因。然而,一些想法仍然存在(通常没有适当的归属):例如,从概念上讲,人们可以考虑佩罗娜-马利克方案中的自适应扩散性,该方案根据像素之间的关系聚集像素中的信息,作为注意机制的先驱。

[9] B. Chamberlain,J. Rowbottom 等人, GRAND:图形神经扩散 (2021) ICML 。历史上公平地说,不同风格的图扩散方程以前在过多的应用中使用过,所有这些都被命名为hanc marginis exi guitas non caperet在计算机图形学中,由于流形上的扩散方程的基本解(热核)与其高斯曲率之间的关系,离散流形(网格)上的热方程长期以来被用作形状描述符(例如,参见我以前的 EUROGRAPHICS 2012 教程,其中我提到了扩散在几何处理和图形学中的许多应用)。在图形信号处理中,低通滤波器可以用扩散过程来识别(例如,L. Stankovi 的综述论文,《图形信号处理简介》 (2019)提到了这种关系),并且已经用于从数据中恢复图形(例如,参见 D. Thanou 等人,学习热扩散图 (2017) IEEE Trans。网络上的信号和信息处理3(3):484–499)。P. Milanfar,现代图像滤波之旅(2013)IEEE Signal Processing Magazine30(1):106–128 中介绍了从图形的角度对经典图像滤波器的解释,包括一些概括。在机器学习中,一类称为扩散图的流形学习(非线性降维)技术由 R. R. Coifman 等人引入,几何扩散作为调和分析和数据结构定义的工具:扩散图(2005)PNAS102(21):7426–7431 实现了扩散度量的欧几里德嵌入,与图中一对节点之间的热传播相关。最后,在 GNN 文献中,扩散方程已经在 F. Scarselli 等人的经典论文《图形神经网络模型(2009)《IEEE Trans。神经网络27(8):61–80 以及最近 m .等人的图神经常微分方程 (2019) arXiv:1911.07532,j .庄的图网络上的常微分方程 (2019) arXiv:1911.07532,f .顾等人的隐式图神经网络 (2020)【神经网络****

[10]我们使用一个标准的符号:图 Gn 个节点和 m 条边, W 是具有 wᵤᵥ= 1 的 n × n 邻接矩阵,如果 u ~ v 则为零。给定 d 维节点特征排列成 n × d 矩阵 X ,梯度∇ X 可以表示为大小为 m × d. 的矩阵,类似地,给定大小为 m × d 的边缘特征矩阵 Y ,散度这两个运算符是伴随 w.r.t .适当的内积,⟨∇ XY ⟩=⟨ X ,div( Y )⟩.我们稍微滥用了用xt54】ᵤ表示节点特征(类似于连续情况下的标量场)和用xt58】ᵤᵥ表示边缘特征(类似于矢量场)的符号;从上下文来看,区别很明显。

[11]我们假设 a 是归一化的,∑ aᵤᵥ =1。

[12]对于一个常数 A ,扩散方程的解可以封闭形式写成X(t)= exp(t(AI)X(0)= exp(t【T80)拉普拉斯δ图的指数被称为热核,并且可以被解释为具有低通滤波器的广义(频谱)卷积。****

[13]注意 Q 依赖于 X (因此每次迭代都会改变),但是它对 X 的应用是线性并且采用矩阵乘积的形式。这与 GNNs 的“注意力”味道有着精确的相似之处。**

[14]以 C. Runge,über die numerische auflsung von differentialgleichungen(1895)Mathematische Annalen46(2):167–178 和 W. Kutta,Bei trag zur naherungsweisen integration totaler differentialgleichungen(1901)z . Math。Phys 。46:435–453,龙格-库塔法实际上不是一种单一的方法,而是一类数值格式。具体来说,在我们的论文中,我们使用了流行的 Dormand-Prince 方案。****

[15]通常,近似误差计算为两个后续近似级之间的差异。

[16]p . veli kovi 等人,图注意网络 (2018) ICLR 。更具体地说,我们假设层之间没有非线性,并且跨层共享注意参数(对应于与时间无关的扩散率)。后者是一个很大的优势:在我们的实验中,我们在大多数情况下获得了优于 GAT 的结果,而使用的参数却少了 20 倍。

[17]“神经微分方程”,或将残差神经网络解释为常微分方程的欧拉离散化,由几个小组提出,包括 E. Haber 和 L. Ruthotto,深度神经网络的稳定架构(2017) 逆问题 34 (1),Y. Lu 等人,超越有限层神经网络:桥接深度架构和数值微分方程(2018),以及可能是其中最著名的 R. Chen 等人,【T10 我们的方法可以被认为是“神经偏微分方程”。**

[18]这当然是无标度图的情况,例如社会网络可以在具有双曲几何的空间中实现。图作为连续空间的几何解释是网络几何学领域的主题,参见例如 m .博古纳等人的网络几何学 (2021) 自然评论物理学3:114–135。将图解释为一些空间的采样是证明谱图滤波器一般化的中心机制,例如在 R. Levie 等人的谱图卷积神经网络的可转移性 (2019) arXiv:1907.12972 中。

我们感谢 Nils Hammerla 校对了这篇文章,也感谢 Peyman Milanfar 从图形的角度指出了对图像滤镜的解释。有关图形深度学习的其他文章,请参见 Michael 在《走向数据科学》中的 其他帖子 订阅他的帖子 YouTube 频道 ,获取 中等会员资格 ,或关注 Michael 在 Twitter 上的

从微分几何和代数拓扑的角度看图形神经网络

原文:https://towardsdatascience.com/graph-neural-networks-through-the-lens-of-differential-geometry-and-algebraic-topology-3a7c3c22d5f?source=collection_archive---------0-----------------------

重新思考 GNNs

微分几何和代数拓扑在主流机器学习中不是很经常遇到。在这一系列的文章中,我将展示如何使用这些领域的工具来重新解释图形神经网络,并以有原则的方式解决它们的一些常见困境。

对称,无论你如何定义它的含义,都是一种观念,古往今来人类一直试图通过它来理解和创造秩序、美和完美。

赫尔曼·魏尔1对对称性的描述颇具诗意,强调了对称性在科学中的基石作用。费利克斯·克莱因 1872 年的"埃尔兰根计划 " 2通过对称群刻画几何图形。这不仅是数学上的一个突破,统一了“几何动物园”,而且导致了现代物理理论的发展,这些理论可以完全从对称性的第一原理中推导出来[3]。在几何深度学习的保护伞下,类似的原则也出现在机器学习中,这是一个通过群不变性和等方差推导出大多数流行神经网络架构的通用蓝图【4】。

图形神经网络可以被认为是几何深度学习蓝图的一个特例,它的构建块是一个具有对称群的域(在这种情况下是具有置换群的图形),域上的信号(节点特征),以及这些信号上的群等变函数(消息传递)。

几何深度学习蓝图可以应用于不同的领域,如网格、网格或图形[5]。然而,虽然前两者有明确的连续类比对象(网格可以被认为是欧几里德或更一般的均匀空间(如球体)的离散化,网格是二维流形的常见离散化),但对于图形没有直接的连续类比【6】。这种不平等有点令人不安,并促使我们更仔细地研究图形学习的连续模型。

网格、网格和图形是几何深度学习蓝图中处理的域的示例。然而,虽然前两者有连续的相似性(例如,网格可以被视为欧几里得空间的离散化,而网格是二维流形或表面的常见离散化),但图形没有直接的连续相似性。

神经扩散图。图形神经网络(GNNs)通过在图形上执行某种形式的消息传递来学习,由此特征通过边从节点传递到节点。这种机制与图上的扩散过程有关,可以用称为“扩散方程的偏微分方程(PDE)的形式来表示。在最近的一篇论文[7]中,我们表明,这种具有非线性可学习扩散函数的偏微分方程的离散化(称为“图形神经扩散”或非常谦虚地说,GRAND)概括了一大类 GNN 架构,如图形注意力网络(GAT) [8]。

PDE 思维模式提供了多种优势,例如可以利用高效的数值解算器(例如隐式、多步、自适应和多重网格方案),并保证稳定性和收敛性。这些解算器中的一些在流行的 GNN 架构动物园中没有直接的类比,潜在地承诺新的有趣的图形神经网络设计。由于我们考虑的扩散偏微分方程可以被视为一些相关能量的梯度流[9],这样的结构可能至少比典型的结构稍微更容易解释。

同时,虽然 GRAND 模型提供了连续时间来代替传统 GNNs 中的层,但是方程的空间部分仍然是离散的并且依赖于输入图。重要的是,在这个扩散模型中,域(图)是固定的,在其上定义的一些属性(特征)是演化的。

微分几何中常用的一个不同的概念是几何流,演化出域本身的属性【10】。这个想法是我的博士导师 Ron Kimmel 和他的合著者在 20 世纪 90 年代在图像处理领域采用的[11]。他们将图像建模为嵌入在联合位置和颜色空间中的流形,并通过最小化嵌入谐波能量的偏微分方程对其进行演化[12]。这种称为 Beltrami 流的 PDE 具有各向同性非欧几里德扩散的形式,并且产生边缘保持图像去噪。

我们将这一范式应用于“Beltrami 神经扩散”(BLEND)框架中的图表[13]。图中的节点现在由位置坐标和特征坐标来表征,都是演化的,并且都决定了扩散率属性。在这种思维模式中,图本身变成了一个辅助角色:它可以从位置坐标中生成(例如作为一个k-最近邻图)并在整个进化过程中重新布线。下图说明了这种同步进化过程:

通过重新布线的 Beltrami 流,Cora 图的位置和特征分量的演变(颜色表示特征向量)。动画:詹姆斯·罗博特姆。

S 在最近的工作中,图形神经网络的表达能力受到了极大的关注。消息传递 gnn 等同于 Weisfeiler-Lehman 图同构测试【14–16】,这是一种试图通过迭代颜色细化来确定两个图在结构上是否等价(“同构”)的经典方法。这个测试是一个必要但不充分的条件:事实上,Weisfeler-Lehman 可能认为一些不同构的图是等价的。下图说明了消息传递 GNNs“看到”了什么:两个突出显示的节点看起来没有区别,尽管图形显然具有不同的结构:

Weisfeiler-Lehman 测试不能区分的两个不同构图的例子。图改编自 Sato [18]。

位置编码。解决这个问题的一个常用方法是给节点“着色”,给它们分配一些额外的特征,代表节点在图中的角色或“位置”。位置编码方法在 Transformers [17](这是注意力 GNNs 在完整图形[4]上操作的一种特殊情况)中得到普及,已经成为增加图形神经网络表达能力的一种常用方法。

位置编码为图的节点分配额外的特征,允许消息传递获得比 Weisfeiler-Lehman 测试更高的表达能力。然而,在位置编码的多种可能选择中,没有“规范的”选择。图改编自 Sato [18]。

也许最直接的方法是赋予每个节点一个随机特征[18];然而,虽然这种方法更具表达性,但它的泛化能力很差(因为不可能在两个图中重现随机特征)。图拉普拉斯算子[19]的特征向量提供了图的邻域保持嵌入,并且已经被成功地用作位置编码。最后,我们在与乔尔戈斯·布里特萨斯和法布里齐奥·弗拉斯卡[20]的论文中表明,图形子结构计数可以用作一种位置或“结构”编码的形式,可以证明这种编码比基本的魏斯费勒-雷曼测试更有效。

然而,对于位置编码有多种选择,对于如何选择一个没有明确的方法,对于哪种方法在哪种情况下更好的问题也没有明确的答案。我相信像 BLEND 这样的几何流可以根据这个问题来解释:通过非欧几里得扩散来进化图的位置坐标,位置编码适合于下游任务。因此,答案是“视情况而定”:最佳的位置编码是手头数据和任务的函数。**

高阶信息传递。另一种表达方式是停止用节点和边来思考图形。图是称为细胞复合体的对象的例子,细胞复合体是代数拓扑领域的主要研究对象之一。在这个术语中,节点是 0 单元,边是 1 单元。我们不必就此打住:我们可以构建如下图所示的 2 单元格(面),这使得上一个示例中的两个图形完全可以区分:

在最近与克里斯蒂安·博德纳尔和法布里齐奥·弗拉斯卡合著的两篇论文[21–22]中,我们证明了构建一个“提升变换”是可能的,这种“提升变换”用这种更高阶的单元来扩充图形,在此基础上可以执行更复杂形式的分层消息传递。该方案可以证明比 Weisfeiler-Lehman 测试更具表达性,并在计算化学中显示出有希望的结果,在计算化学中,许多分子显示出更好地模拟为细胞复合体而不是图形的结构。

AGNNs 的另一个常见困境是“过度压制现象,或由于输入图的某些结构特征(“瓶颈”)导致消息传递无法有效传播信息【23】。过度平息通常发生在具有指数体积增长的图中,例如小世界网络[24]以及依赖于长程信息的问题中。换句话说,GNNs 运行的输入图对于消息传递并不总是友好的。

“小世界”图中快速增长的邻居数量通常是在 GNNs 中观察到的过度挤压现象的来源。

过度挤压、瓶颈和图形重布线。从经验上看,将输入图与计算图分离,并允许在不同的图上传递消息有助于缓解问题;这种技术通常被称为“图形重布线”。**

公平地说,许多流行的 GNN 架构实现了某种形式的图重连,它可以采取邻域采样(最初在 GraphSAGE 中提出以应对可扩展性[25])或多跳过滤器 [26]的形式。上面讨论的拓扑消息传递也可以被看作是一种重新布线的形式,由此远距离节点之间的信息流可以通过更高级别的单元而被“捷径”化。Alon 和 Yahav [23]表明,即使像使用全连通图这样简单的方法也可能有助于改善图 ML 问题中的过度挤压。克利茨佩拉和合著者热情地宣称“扩散改善了图形学习”,提出了 GNNs 的通用预处理步骤(命名为“DIGL”),包括通过扩散过程对图形的连通性进行去噪[27]。总的来说,尽管有重要的实证研究,过度挤压现象一直难以捉摸,也没有得到充分的理解。

在最近的一篇论文【28】中,我们表明导致过度挤压的瓶颈可以归因于图的局部几何属性。具体来说,通过定义一个瑞奇曲率的图形类比,我们可以表明负弯曲的边是罪魁祸首。这种解释导致了类似于“逆向 Ricci 流”的图重新布线过程,该过程通过外科手术去除了有问题的边,并产生了一个在结构上类似于输入图的更有利于消息传递的图。

使用基于扩散的方法(DIGL,中)和基于曲率的方法(Ricci,右)重新布线康奈尔图(左)的示例。基于曲率的方法更显著地减少了瓶颈,同时更忠实于原始图形结构。

T 这些例子表明,微分几何和代数拓扑为图形机器学习中的重要和具有挑战性的问题带来了新的视角。在本系列的后续文章中,我将进一步详细展示如何使用这些领域的工具来解决前面提到的图形神经网络问题。第二部分将讨论拓扑空间上的消息传递如何改进 GNNs 的理论和计算。第三部分将处理 GNN 公式作为梯度流,导致几何扩散偏微分方程。第四部分将展示过度挤压现象如何与图形曲率相关联,并提供受瑞奇流启发的图形重布线的几何方法。[第五部分](http://and topological message passing)将处理细胞束上的学习,以及这种形式主义如何解决 gnn 倾向于遭受的嗜异性设置。

1 H .韦勒,《对称性》(1952),普林斯顿大学出版社。

2F .克莱因,Vergleichende Betrachtungenüber neuere geometrische for schungen(1872 年)。

[3] J. Schwichtenberg,来自对称性的物理学(2018),施普林格。

[4] M. M .布朗斯坦,j .布鲁纳,t .科恩,p .韦利奇科维奇,几何深度学习:网格、群、图、测地线和量规(2021);见随附的帖子和项目网站。

[5]在上面的 GDL 原型书中,我们将这些称为几何深度学习的“5G”。

[6] 几何图形自然产生于生活在连续空间中的物体的离散模型。一个突出的例子是分子,建模为图形,其中每个节点代表一个具有 3D 空间坐标的原子。另一方面,有可能将嵌入一般的图到一个连续的空间中,从而利用某个空间的度量结构(近似)实现它们的连通性。

[7] B. Chamberlain,J. Rowbottom 等人,GRAND:Graph Neural Diffusion(2021)ICML。

[8]p . veli kovi 等人,图形注意网络 (2018) ICLR。

【9】一个梯度流可以看作是变分问题中梯度下降的连续类比。它源于泛函的最优性条件(变分法中称为欧拉-拉格朗日方程)。

【10】几何流是定义在流形上的泛函的梯度流。其中最著名的可能是格里高里·佩雷尔曼在证明百年庞加莱猜想时使用的瑞西流。Ricci 流发展了流形的黎曼度量,并且在结构上类似于扩散方程(因此,通常经过粗略简化,表示为“度量的扩散”)。

[11] N. Sochen 等人,低层视觉的一般框架 (1998) IEEE Trans。图像处理 7(3):310–318 使用一个几何流最小化一个流形的嵌入能量作为图像去噪的模型。得到的 PDE 是线性非欧几里德扩散方程x(这里δ是表示为嵌入流形的图像的拉普拉斯-贝尔特拉米算子),与 P. Perona 和 J. Malik 早先使用的非线性扩散= div(a(x)∇x),尺度空间和使用各向异性扩散的边缘检测(14

[12] Beltrami 流将弦理论中称为 波利亚科夫作用 的泛函最小化。在欧几里得的例子中,它简化为经典的狄利克雷能量 T21。

[13] B. P. Chamberlain 等人, Beltrami 流和图上的神经扩散 (2021) NeurIPS。

[14] B. Weisfeiler,A. Lehman,将一个图简化为标准形式以及其中出现的代数(1968)Nauchno-Technicheskaya informatisia 2(9):12–16。

[15] K. Xu 等,图神经网络到底有多强大? (2019) ICLR。

[16] C. Morris 等人, Weisfeiler 和 Leman go neural:高阶图神经网络 (2019) AAAI。

[17] A. Vaswani 等人,注意力是你所需要的一切 (2017) NIPS。

[18] R. Sato,关于图形神经网络表达能力的调查 (2020)。arXiv: 2003.04078。使用随机特征进行位置编码。

[19] V. P. Dwivedi 等人标杆图神经网络 (2020)。arXiv: 2003.00982。使用拉普拉斯特征向量作为位置编码,尽管谱图嵌入的思想更为古老,并且已经广泛用于非线性维度减少,例如 M. Belkin 和 P. Niyogi 的经典工作,拉普拉斯特征图和用于嵌入和聚类的谱技术 (2001),NIPS。

[20] G. Bouritsas 等,通过子图同构计数提高图神经网络表达能力 (2020)。arXiv:2006.09252。使用图形子结构计数作为位置编码;参见随附的帖子。

[21] C .博德纳尔,f .弗拉斯卡等,魏斯费勒和雷曼 go 拓扑:消息传递单纯网络 (2021) ICML。

[22] C .博德纳尔、f .弗拉斯卡等人,魏斯费勒和雷曼 go cellular:CW Networks(2021)neur IPS。

[23] U. Alon 和 E. Yahav,关于图神经网络的瓶颈及其实际意义 (2020)。arXiv:2006.05205

[24]在这样的图中,随着k的增加,达到k跳的邻居的大小增长得非常快,导致“太多的邻居”必须将它们的更新发送到一个节点。

[25] W. Hamilton 等人,大型图上的归纳表征学习 (2017) NIPS。

[26] F .弗拉斯卡等人, SIGN:可扩展的初始图神经网络 (2020)。ICML 图形表示学习研讨会。使用多跳筛选器;见一个随行的帖子。

[27] J .克利茨佩拉等人,扩散改善图形学习 (2019) NeurIPS。通过计算个性化页面等级(PPR)节点嵌入,然后在嵌入空间中计算一个 k -NN 图,来重新连接该图。

[28] J. Topping,F. Di Giovanni 等人,通过曲率理解图的过度挤压和瓶颈 (2021) arXiv:2111.14522。参见附带的博文。

感谢克里斯蒂安·博德纳尔、本·张伯伦、法布里齐奥·弗拉斯卡、弗朗切斯科·迪·乔瓦尼和尼尔斯·哈默拉校对了这篇文章。关于图的深度学习的附加文章,参见《走向数据科学》中我的 其他帖子 订阅我的帖子 ,获取 中等会员 ,或者关注我的Twitter。**

DWave 量子退火机上运行的离散二次模型图划分

原文:https://towardsdatascience.com/graph-partitioning-with-discrete-quadratic-model-running-on-dwave-quantum-annealer-6c2e821d646e?source=collection_archive---------37-----------------------

思想和理论

量子退火器是一类量子计算机,可以帮助解决 NP 难和 NP 完全问题。这里有一个对社交网络、推荐系统等有实际意义的例子。

图是由一组通过边连接的节点组成的数据结构。图形无处不在:它们可以代表友谊的网络,工厂和商店、机场等等之间的联系。在可以应用于图形以提取有用信息的许多操作(其本身就是一个巨大的兔子洞)中,可能最明显的一个是分割,,即基于一些相似性或距离标准将 N 节点分成 K 组。主要思想是,一旦组被识别,属于给定组的节点彼此之间的关系比属于其他组的节点之间的关系更紧密。

一种成熟的聚类方法被称为无监督的 K-means ,其中每个观察值被分配到质心最近的簇(簇的多维平均)。在 scikit-learn python 库中可以找到该算法的一个常见实现。

然而,K-means 并不是故事的结尾。我想在这篇文章中讨论的方法是基于一种叫做 二次无约束二元优化 (曲波)的优化方法,这是用量子绝热退火程序解决 NP 难题的主力,这要归功于它与伊辛能量函数的联系,后者反过来描述了这种计算机背后的物理学。在曲波公式中,问题由一组二元变量 q_i ( 例如 0 或 1,-1 或 1)、常数权重的方阵 C 以及我们希望通过找到最优的 q_i: 来最小化的目标(成本、损失)函数来描述

二次无约束二元优化 (曲波)的数学公式。图片作者。

在图划分方面,权重 C_ij 是预先计算的,例如它们表示[地理距离](http://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.haversine_distances.html#:~:text=The Haversine (or great circle,the longitude%2C given in radians.)或余弦相似度在 TF-IDF 文档嵌入之间。 q_i 是在最小化过程中找到的,代表解。人们经常不得不处理退化解,不同组的 q_i 同样好地最小化 y

这些讨论的一个关键点是“无约束”这个词。无约束意味着目标函数…不受约束。举个例子,一个约束看起来像( q_i — 1) =1。在 Glover 等人的臭名昭著的曲波模型指南中可以找到一长串的例子。无约束意味着人们必须在原始方程中添加一项以纳入约束,乘以常数拉格朗日乘数 β,例如y' = y + β*(x — 1) 。问题是,y’的最终方程必须仍然是曲波方程,使得约束可以被重新吸收到更新的权重矩阵C’的定义中。

要用曲波术语建立图划分问题,第一步是确定二进制变量代表什么。在这种情况下,一种常见的方法是将 K 个二进制变量分配给每个节点,并将它们解释为一个热码向量,也就是说,如果对于第 i 个节点,第 j 个比特为 1,而所有其他比特为 0,则该节点被分配给集群( j +1)。

Node | q_i0 | q_i1 | q_i2 |
 1   |  0   |  1   |  0   |
 2   |  1   |  0   |  0   |
 3   |  0   |  1   |  0   |
 4   |  0   |  0   |  1   |

首先,我们需要定义要最小化的目标函数。在一种常见的方法中,它被证明是不同集群之间连接 的简单数量。我们会让集群内连接的数量不受限制。这简单地通过询问对于一对节点 ij ,它们两个必须属于集群 k 或者不属于集群k来实现,这是一个 XOR 逻辑门。在曲波的世界里,相当于异或门的东西有点棘手。我们想要最小化由两个变量 q_ikq_jk 构成的量。它们的和不是 2 就是 0,它们的积不是 0 就是 1。因此,以下组合满足要求:

y = q_ik + q_jk - 2 * q_ik * q_jkq_ik | q_jk | sum | -2*prod | y
  0  |   0  |  0  |     0   | 0
  1  |   0  |  1  |     0   | 1
  0  |   1  |  1  |     0   | 1
  1  |   1  |  2  |    -2   | 0

然后,我们需要定义约束。

首先,我们希望 K 集群是平衡的每个集群必须包含相似数量的节点,大约等于 N/K

其次,如果我们正在进行二元二次模型设置,我们需要进一步的约束来确保在 q 变量中,只有 1 被设置为 1,而所有其他的都是 0。对于每个节点 i ,该约束将简单地是𝚺_ j q_ij = 1。然而,这是这篇文章的重点,DWave 在他们的软件中引入了一个新的功能来处理这种情况,作为一个离散的类索引(例如红色、绿色或蓝色),而不是二进制。有趣的是,这种模型的解算器是混合类型的,这意味着它利用量子计算来改进对目标函数最小值的经典搜索。根据他们的声明:

这种混合求解器接受多达 5,000 个离散变量的问题,每个变量可以表示多达 10,000 个值的集合,以及 20 亿个线性加二次偏差

因此,总的目标函数+约束如下所示:

使用离散二次模型的图划分问题的曲波目标函数。图片作者。

这个表达式可以扩展然后简化为从二次项(乘积 C_ij * q_i * q_j )中分离线性项(每次涉及一个 C_ii * q_i ),这是一个繁琐但却是定义权重矩阵 C 的系数所必需的操作。感兴趣的读者可以在 DWave 网站上的这个例子中找到更多细节。

作为一个实际的用例,我使用了一个大学空手道俱乐部的社交网络扎卡里的空手道俱乐部图,在韦恩·w·扎卡里的论文“小团体中冲突和分裂的信息流模型”中有所描述。这个由 34 个人组成的小型网络的结构可以在 python 库中找到。成对成员之间的联系代表了俱乐部之外的互动,他们最终分成两个独立的小组。为了展示如何从networkx中读取图形结构,然后用 DWave ocean 库对其进行分析,我们将把可能的子组数量增加到 2 个以上。

完整的代码可以在我的 GitHub 库中找到。简而言之,以下是解决问题所必需的一系列操作:

然而,为了运行它,需要访问闰 DQM 解算器,所以基本上需要访问闰。别担心,这是免费的,但使用量仅限于每月一定的数量。

一旦您获得了 Leap 的访问权,您就可以使用 LeapIDE 开发环境了。要启动一个工作区,你只需将浏览器指向一个以*https://ide.dwavesys.io/#*开头的地址,然后是 GitHub 库的地址。例如:

https://github.com/rdisipio/classify_dqm_qubo/blob/main/karate.py

*https://ide.dwavesys.io/#*[https://github.com/rdisipio/classify_dqm_qubo](https://github.com/rdisipio/classify_dqm_qubo)

如果一切正常,它应该是这样的:

然后,您可以打开一个终端窗口(终端>新终端)并键入命令python karate.py。输出将显示为新的。名为graph_partitioning_result.png的 png 文件,看起来应该类似于用于 K =4 个集群的文件:

将空手道俱乐部图分成 4 组的结果。图片作者。

总之,图划分是一个突出的问题,有许多不同的方法可以解决它。曲波方法已经存在有一段时间了(也可参见 Ushijima-姆维西瓦等人的这篇好论文),但是它们的定义对我来说似乎总是很麻烦,因为必须处理簇变量的方式,尤其是因为在某些情况下缺乏唯一的赋值。这通过使用具有离散二次模型的混合方法得到了很好的解决,这允许用户通过利用经典和基于量子的计算之间的相互作用来解决大型问题。

图表查询和影院预订

原文:https://towardsdatascience.com/graph-queries-and-cinema-bookings-cfb8fe02db25?source=collection_archive---------38-----------------------

知识图商业语言子查询变得简单

在 Unsplash 上由 Myke Simon 拍摄的照片。皇家自由形象。

我的业务被称为 FactEngine,这是一项从根本上改变人们对数据库和知识图查询语言的看法的举措。

假设您想在一家电影院预订一个座位,该影院使用一个数据库来跟踪这些预订。如果你想找到那个座位,你应该问:

FactEngine 查询语言中的图形查询。图片作者。

以上是 FactEngine 中的图表查询,对以下图表进行操作:

显示电影院中会话属性的属性图模式。图片作者。

子查询

对于 initiated,该查询包含一个子查询,该子查询将首先找到那些已经预订的座位,并返回该集合之外的座位,或者相反地使用一个相关子查询,其中“座位的预订计数为零”针对电影院中的每个座位进行操作。

由于 FactEngine 查询引擎位于将所有数据库概念模型首先视为对象-角色模型(如下)的架构内,因此该查询既是图形查询又是自然语言查询。

在我们的对象-角色模型中,会话是“电影日期时间电影院上映”的地方,这允许在我们的子查询中进行简单的图形横切,即:

使用对象-角色模型的事实类型读数的图遍历。图片作者。

点击放大。电影院订票的对象-角色模型。图片作者。

也就是说,在我们的模型的图形表示中,日期时间是一个 属性 ,在我们的图形查询中,日期时间成为一个有效的 节点 ,其中对象角色建模中的对象类型是超图中的有效节点。

我们示例中的子查询受单词“NO”的影响。即哪个座位没有预订。

一个词彻底改变了查询

与自然语言一样,FactEngine 查询中的一个单词就可以从根本上改变查询的含义。

将“无预订”更改为“有预订”,将返回所有已预订的座位:

通过更改查询中的一个单词来删除子查询需求。图片作者。

也就是说,我们已经有效地去除了对任何子查询的需求,现在我们的查询变成了简单的图遍历。

我觉得这很有趣。人类自然明白,句子中的一个单词就能从根本上改变他们处理信息的方式。让一台计算机在没有机器学习的情况下做那件事是我的动力所在。

为什么是图形查询?谁在乎呢。

事实引擎目前在关系数据库上运行,关系数据库通常使用 SQL 进行查询。如果您必须为本文顶部的查询编写 SQL,您将会遇到一些麻烦。这是:

选择[座位]。Cinema_Id,[座位]。RowNr,[座位]。字母,[行]。Cinema_Id,[Row]。RowNr
从【座位】,
【Row】
那里【座位】。Cinema_Id = [Row]。Cinema_Id
和【座位】。RowNr = [Row]。RowNr
和 1 >(从【预订】、
【场次】、
【电影】、
【影院】
、bookinghaseat
中选择 COUNT(
)
)其中【bookinghaseat】。person _ Id =[预订]。Person_Id
和【BookingHasSeat】。film _ Id =[预订]。Film_Id
和【BookingHasSeat】。日期时间=[预订]。日期时间
和【BookingHasSeat】。CinemaId =[预订]。Cinema_Id
和【BookingHasSeat】。RowNr = [Seat]。RowNr
和【BookingHasSeat】。Cinema_Id = [Seat]。Cinema_Id
和【BookingHasSeat】。字母=[座位]。信
和【预订】。Film_Id = [Session]。Film_Id
和【预约】。日期时间=[会话]。日期时间
和【预约】。Cinema_Id = [Session]。Cinema_Id
和【会话】。Film_Id = [Film]。Film_Id
和【会话】。Cinema_Id=[Cinema]。Cinema_Id
和【电影】。Name = 'Rocky'
和[Session]。DateTime = '12/08/2020 10:00'
和【影院】。CinemaName = '大西部电影院'
)*

可能只有我,但我更愿意这样写查询:

事实引擎中的自然语言查询。图片作者。

我觉得关系数据库供应商有很大的机会通过使关系数据库的查询更容易来夺回图形数据库的失地。

下一步是实现机器学习和复杂的机制不一定是计算机解释和理解大量自然/商业语言查询所必需的。

对于门外汉来说,子查询总是一个学习曲线,所以我觉得,任何可以使生活变得简单的工具都是好东西。

感谢您的阅读。如果时间允许,我会写更多关于图形查询、图形数据库、关系数据库和对象角色建模的文章。

NB 本文表达的模型的原始版本版权归 DataConstellation 所有,在 GitHub 上的 ActiveFacts 项目下共享:https://github.com/cjheath/activefacts

——————End————

图形表示学习——网络嵌入(上)

原文:https://towardsdatascience.com/graph-representation-learning-network-embeddings-d1162625c52b?source=collection_archive---------18-----------------------

GraphEDM 系列

主要概念的热身

节点嵌入的表示—作者修改的来自 Excalidraw 库的图像

这个系列总结了一个关于图的机器学习的综合分类法,并报告了 GraphEDM(横山雅美等。al),一个统一不同学习方法的新框架

图是建模关系数据的通用结构。从社会网络连接到蛋白质相互作用,图结构强调数据点之间的联系,使新一代基于网络的系统的开发成为可能。考虑到图在真实场景中的广泛应用以及最近表征学习技术的成功,图表征学习(GRL)方法已经大量涌现。因此,鉴于这种令人印象深刻的增长,有一个在一个可理解的框架内总结和统一 GRL 方法的巨大需求。因此,在这一系列中,我报告了我个人对以下论文的综合:

I .横山雅美、s .阿布埃尔海贾、b .佩罗齐、réc .、k .墨菲(2020 年)。图的机器学习:一个模型和综合分类法。arXiv 预印本:2005.03675。

这份手稿为理解 GRL 方法背后的主要直觉提供了坚实的基础。此外,所提出的分类法对于获得可用应用程序的广泛概述和支持为给定问题选择最佳工具特别有用。在这个新系列中,我将重点关注Graph Encoder Decoder Model(graphe DM)的一般思想,它能够描述一系列监督和非监督的方法,用于学习图形数据的表示(有关单一方法的详细信息,可以直接参考该论文)。

该系列的结构如下:

  1. GRL 背景下的嵌入问题概述(本文有报道)。
  2. GraphEDM 框架的 描述 ,包括其主要组件的摘要。
  3. A 详细解释 框架中定义的目标(或损失)函数、编码方法和监督应用。

图形表示学习中的嵌入

GRL 方法的主要目标是从离散图形数据中学习低维连续表示,即所谓的嵌入。图的属性必须保留在嵌入空间中:例如,在原始图中由相似连接表征的节点在学习过程结束时实现了接近的向量表示(在几行中,我们将看到这对于结构嵌入是如何正确的)。从另一个角度来看,节点嵌入学习可以被视为用于可伸缩性目的的降维过程。事实上,学习向量的维数严格低于原始图中的节点数。

以下小节提供了直观的定义,以便清楚地说明 GRL 的问题设置。特别是,这些小节讨论了以下各项之间的重要差异:

  1. 欧几里得与非欧几里得几何。
  2. 位置嵌入与结构嵌入。
  3. 直推式学习与归纳式学习。
  4. 无人监督和有人监督的任务。

欧几里得几何与非欧几里得几何

在大多数表示学习方法中,嵌入使用欧几里德空间中的向量建模。2000 多年来,直到 19 世纪,这是唯一已知的物理空间的概念,它仍然是最适合模拟日常世界的方式。根据大英百科全书,欧几里得空间被定义为:

欧几里得几何的公理和假设适用的二维或三维空间;也指任何有限维数的空间,其中的点用坐标来表示(每一维一个坐标),两点之间的距离由距离公式给出。

从第 0 维到第 4 维欧几里得空间—作者图片

《大英百科全书》在其定义的开头解释说,欧几里得空间通过定义满足欧几里得几何的公理。欧几里得几何的独特公理之一是平行公设。为了清楚直观地理解这一假设,请看下图。

平行公设的图示—作者的图像

在这幅图中,一条线段与两条直线相交。这个交点在同一边形成两个内角 αβ ,内角之和小于两个直角之和(<180°)。根据公设,如果这两条线无限延伸,它们将在α和β边上的某一点相交。平行公设可以通过等价陈述来定义,这对于更好地理解网络嵌入表示是更有趣的。例如,这些陈述包括公平竞赛公理:

至多有一条线可以通过一个外部点平行于另一条给定的线

三角形假设:

每个三角形的角之和是 180 度

虽然欧几里得嵌入对于表示网格结构或顺序数据特别有效,但是对于图形来说,人们对非欧几里得表示学习的兴趣越来越大。在这种情况下,主要目标是学习非欧几里得空间中的嵌入,例如球面和双曲空间。在非欧几里得空间中,平行公设及其等价陈述不成立:例如,在双曲空间中, Playfair 公理被反驳,因为:

至少有两条线可以通过一个外部点平行于另一条给定的线

通过观察三角形公设在非欧几里得空间中如何不被满足,可以获得清楚的直觉:

球面、欧几里德和双曲空间中三角形公设的图形表示—图片由作者提供

在 GRL 的背景下,非欧几里得方法似乎很有前途。这些方法背后的主要思想是在连续的嵌入空间中映射图形数据表示,这能够类似于输入的底层图形结构(例如,双曲空间表示树的连续版本)。例如,称为知识图(KGs)的语义网络的特定实现展示了分层和逻辑模式,这些模式可以通过双曲嵌入高保真地保留。以下文章和相关系列中提供了有关 kg 的更多信息:

位置嵌入与结构嵌入

RL 技术旨在学习保持输入图结构的低维表示。矩阵分解或随机行走等技术倾向于保留全局结构,重建图中的边并保持距离,如原始网络中的最短路径。关注全局结构的方法的目标是学习所谓的位置嵌入。

包括图形神经网络(GNNs)在内的其他技术旨在捕捉局部图形结构:图形中具有相似邻居的中心节点应该具有相似的嵌入,而不管原始网络中节点的距离。这些结构感知方法的目标是学习所谓的结构嵌入。

直推式学习与归纳式学习

对嵌入方法进行分类的一种特定方式与它们对未知数据的泛化能力有关。直推式设置假设在训练过程中观察到所有的图节点:该设置的要求是固定的图,不考虑新节点、边或子图结构形式的新实例。直推式方法允许我们在训练过程中推断分析的节点之间的新信息。例如,给定部分标记的节点,我们可以对未标记的节点进行分类。或者,在其他情况下,我们可以预测在训练期间观察到的图节点之间的新边。

在归纳设置中,我们期望模型能够推广到在训练过程中没有看到的节点和边。因此,归纳学习可能特别适合于动态的和时间演化的图。节点特征在归纳图表示学习方法中起着至关重要的作用。事实上,与直推式方法不同,这些特征可以用来学习参数映射的嵌入。通过优化这种参数映射而不是直接优化嵌入来实现学习目标。这意味着学习映射可以应用于任何节点,甚至是那些在训练过程中没有看到的节点。

无人监督与有人监督的任务

无监督的任务中,图结构是唯一可用的信息。因此,嵌入学习过程的目标是保持图形结构,优化重建损失。这个损失函数测量学习的嵌入能够多好地逼近原始图。

在监督任务中,提供了有关节点或图形标签的附加信息。在这些情况下,嵌入学习过程旨在处理下游任务,包括节点、边或图属性的预测。因此,该模型被优化以达到这一特定目的。正如我在下面的文章中已经报道的,在 GNNs 的情况下,您可以向网络架构添加一个预测层,以便达到您的学习目标,从节点分类到链路预测。

下一步是什么

在本系列的下一篇文章中,我将提供 GraphEDM 的细节,这是一个通用框架,封装了无监督和有监督的方法、图正则化和 GNNs。

对于 GraphEDM 框架上的所有文章,你可以使用下面的链接:【https://towardsdatascience.com/tagged/graphedm-series】T4。

关于图形表示学习的进一步阅读,你可以通过以下链接关注我的系列:https://towardsdatascience.com/tagged/grl-series。

如果你喜欢我的文章,你可以支持我使用这个链接https://medium.com/@giuseppefutia/membership成为一名中等会员。

图形表示学习——目标函数和编码器(第三部分)

原文:https://towardsdatascience.com/graph-representation-learning-objective-functions-and-encoders-aef3a65bbf81?source=collection_archive---------19-----------------------

GRAPHEDM 系列

让我们了解如何优化 GRL 模型以及它们整合不同网络功能的能力

Graph Vis —原图来自 NYU 上海网站

这个系列总结了一个关于图的机器学习的综合分类法,并报告了 GraphEDM(横山雅美等人)的细节,这是一个统一不同学习方法的新框架。

最近几年,图形表示学习(GRL)技术有了大规模的发展。这些技术的主要目标是学习将图形数据的离散结构映射到向量空间中的连续表示的函数。在之前的文章中介绍的 GraphEDM 框架能够在 GRL 环境中统一 30 多种方法来学习这些连续的表示,也称为嵌入

在无监督的设置中,GRL 技术的学习目标是保持图形结构。在监督设置中,目标是解决特定的下游任务。不同的学习方法意味着不同的优化方法和不同类型的编码器来生成节点嵌入。因此,本文的第一部分致力于 GraphEDM 中实现的目标函数。第二部分关注不同类型的基于图形的编码器。要简要回顾 GraphEDM 框架,我建议阅读本系列的前几篇文章。

横山雅美等人在文章中报道了所有的框架细节:

横山雅美岛、阿布-埃尔-海贾岛、佩罗齐岛、雷岛、&墨菲岛(2020 年)。 图的机器学习:一种模型和综合分类法 。arXiv 预印本:2005.03675。

目标函数

在机器学习中,目标函数,或标准,是我们在模型参数优化过程中想要最小化(或最大化)的一般函数。如果我们要最小化输出,对于单个训练示例,目标函数被表示为损失函数,而当考虑整个训练集时,它被称为成本函数。

因此,损失函数是在数据点上定义的:它将来自模型的预测标签与目标标签进行比较,并计算惩罚。成本函数可以是单个惩罚加上复杂性惩罚的总和或平均值,定义为正则化。正则化允许模型稳定学习过程并增强其泛化能力。在正则化中,模型参数被约束(或正则化),阻碍噪声信号的学习并避免过拟合。

正如我们将很快看到的,在 GRL 的具体情况下,图结构也可以在学习过程中作为正则项使用。

损失函数

GraphEDM 框架中的损失函数(经许可后发布)

在 GraphEDM 框架中包含 GRL 技术的情况下,我们希望优化三个不同的参数类(参见本系列的上一篇文章了解更多详细信息):

  • θ^e 代表编码器网络的参数;
  • θ^d 代表解码器网络的参数;
  • θ^s 代表分类网络的参数。在这种特定情况下, S 是包括节点、边和图的特征和标签的监督信号的集合: S ∈ {N,E,G}。

所有这些参数都通过组合监督损失项、图形正则化损失项和权重正则化损失项来优化。

监督损失

监督损失项计算预测标签和目标标签之间的损失。

图形表示学习——监督损失项(转自横山雅美等人的手稿)

该损失项中涉及的图形信号 S 与涉及模型训练阶段的下游任务严格相关。如果要执行的任务是节点分类,那么 S = (N)。对于任务集中于链路预测的情况, S = (E) 。否则,在图级别执行任务的情况下, S = (G) 。在这个数学形式化中, ŷ^S 代表预测空间,而 y^S 代表标签空间。

图正则化损失

图正则化损失项的目标是通过利用网络结构来正则化 GRL 模型的参数。

图形表示学习——图形正则化损失项(来自横山雅美等人的手稿)

惩罚计算基于重构的相似性矩阵ŵT4 和目标相似性矩阵 s(W) 之间的距离。矩阵ŵW 的维数都等于|V|×|V|,其中|V|是节点数。 d 执行ŵs(W)之间的距离计算。

为了更好地理解 GRL 相似矩阵的一般概念,考虑下面的说明。图正则化最简单的用法是重构邻接矩阵,它的维数是|V|×|V|。正如我在关于 GNNs 的介绍性文章中用一个例子描述的那样,邻接矩阵描述了节点之间的(加权)边。

我们可以说邻接矩阵决定了两个节点之间的一阶接近度。为了澄清这个方面,考虑两个不同的节点 vᵢvⱼ :这些节点的局部相似性值,根据一阶接近度,由边权重 wᵢⱼ.定义因此,一阶近似能够捕获两个不同节点之间的边的存在和有效性。

然而,我们可以扩展这个一阶邻近概念,尝试从图结构中封装进一步的信息。例如,两个节点之间的二阶接近度不考虑基于它们的加权边的两个节点之间的一致性,而是基于它们的相邻节点的同质性。换句话说,如果两个节点倾向于具有许多共同的邻居,则它们根据二阶接近度实现更接近的表示。

节点邻近的概念对于学习图嵌入是至关重要的,因为许多 GRL 模型的训练目标是保持一个或多个邻近顺序。

重量规则化损失

权重正则化损失项是一种传统方法,用于在训练步骤中一般正则化模型参数。

图形表示学习——权重正则化损失项(来自横山雅美等人的手稿)

权重正则化概念背后的主要思想是在模型中注入少量的偏差,以获得方差的显著下降。因此,在拟合稍差的情况下,我们可以用真实数据提供更好的预测。最常见的正则化是 L2 ,其中 θ 参数的平方值使得预测对训练数据的变化不太敏感。

损失项组合

正如本节开头所解释的,为 GraphEDM 框架中封装的模型定义的损失包括所有前面的组件。为此,损失计算如下。

图形表示学习—损失项组合(转自横山雅美等人的手稿)

αβγ 是可以在训练过程中学习的超参数。可以猜测,在图嵌入学习的监督设置中 α ≠ 0,而在非监督设置中 α = 0 以排除监督损失项的贡献。

GraphEDM 编码器

GraphEDM 编码器(经许可后发布)

编码器网络的主要目标是将图中的每个节点映射到低维向量中。基于生成节点嵌入的编码器,不同的 GRL 方法显著不同。GraphEDM 框架总结了四个主要类别:浅层嵌入方法、图正则化方法、图自动编码方法和邻域聚合方法。

浅层嵌入方法

在浅嵌入方法的情况下,编码器功能是简单的投影操作。

浅层编码器网络(转自横山雅美等人的手稿)

因此,模型的参数被直接用作节点嵌入(在数学公式中, |V| x d 对应于模型参数的数量)。

考虑到它们的性质,这些方法在直推式设置中特别有用,直推式设置假设在训练过程中观察到所有的图节点。与归纳设置不同,直推设置的要求是一个固定的图形,不会随着时间的推移而演变。要具体理解投影步骤,你可以看我在 GNNs 上的介绍相关的文章(“输入层”一节)。

图正则化方法

在图正则化方法的情况下,编码器仅利用节点特征和标签。

图形正则化编码器网络(张贴自横山雅美等人的手稿)

即使它不直接用于传播到编码网络中,图结构也被用作正则化约束( β ≠ 0 以保留图正则化损失项)。作为主要结果,使用训练步骤来学习节点特征,但是同时,使用图结构来正则化它们。

图形自动编码方法

在图形自动编码方法的情况下,编码器组件只利用图形结构。

图形自动编码网络(转自横山雅美等人的手稿)

与浅层嵌入方法相比,图形自动编码器能够利用深度学习架构来学习非线性特征。在这种特定情况下,图结构没有被用作图正则化项,而是作为邻接矩阵 W 被直接注入(使用自动编码器)编码器组件中。

邻域聚合方法

在邻域聚合方法的情况下,在传播步骤中利用了节点特征( X )和图结构( W )。

邻域聚合编码器网络(转自横山雅美等人的手稿)

这些 GRL 方法利用消息传递框架(参见我以前的一篇文章以获得清晰的直觉)用其邻居的特性更新节点特性。在这种情况下,邻居特征通过边作为消息传递到目标节点。作为主要结果,嵌入能够编码图的局部结构。值得一提的是,图卷积网络(GCNs)是邻域聚合方法的一个有效示例。

对于 GraphEDM 框架上的所有文章,可以使用以下链接:https://towardsdatascience.com/tagged/graphedm-series。

关于图形表征学习的进一步阅读,你可以通过以下链接关注我的系列:https://towardsdatascience.com/tagged/grl-series。

如果你喜欢我的文章,可以支持我使用此链接https://medium.com/@giuseppefutia/membership成为一名中等会员。

图形表示学习——编码器-解码器模型(下)

原文:https://towardsdatascience.com/graph-representation-learning-the-encoder-decoder-model-part-2-ed8b505af447?source=collection_archive---------13-----------------------

GraphEDM 系列

深入探究 GraphEDM 架构

GraphEDM 框架的表示——作者修改的原始纸质图像(经允许后发布)

这个系列总结了一个关于图的机器学习的综合分类法,并报告了关于 GraphEDM 的细节(横山雅美等人。al ,一个统一不同学习方法的新框架。

图是无处不在的结构,能够编码不同领域中不同元素之间的关系,从社交网络到金融交易。图嵌入是来自网络结构化数据的低维连续表示,可以通过应用图表示学习(GRL)技术来学习。

在本系列的前一篇文章中,我从不同的角度提出了对网络嵌入的讨论,进行了不同的比较,包括欧几里德几何与非欧几里德几何,位置嵌入与结构嵌入,以及直推式学习与归纳式学习。

[## 图形表示学习——网络嵌入(上)

towardsdatascience.com](/graph-representation-learning-network-embeddings-d1162625c52b)

在第二篇文章中,我们将详细介绍 GraphEDM 架构,从编码器-解码器的角度来看,它在一个独特的框架中连贯地包含了不同的 GRL 技术。横山雅美等人在文章中报道了所有的框架细节。艾尔:

I .横山雅美、s .阿布埃尔海贾、b .佩罗齐、réc .、k .墨菲(2020 年)。图的机器学习:一个模型和综合分类法。arXiv 预印本:2005.03675。

编码器的目标是将数据点的特征转换成低维表示。解码器将该表示作为输入,并试图重建原始数据。如果在训练过程中计算的嵌入能够捕获核心信息,该核心信息能够编码数据中的最高方差,则该架构的性能增加。因此,编码器-解码器架构的学习目标是在重建过程中最小化信息损失。

在网络的情况下,该重建过程旨在恢复原始图形结构(无监督设置)或实现解决特定任务的表示,例如节点或边分类(有监督设置)。与现有的研究工作相比,GraphEDM 定义了一个端到端的模型,能够封装监督和非监督学习方法。以下各节描述了该框架的主要组成部分,该框架能够在 GRL 的背景下归纳出 30 多种方法。

投入

GraphEDM 框架的输入

GraphEDM 框架认为输入是一个无向加权图, G=(N,E) ,其中 N 是节点集,而 E 表示边集。这个无向图是使用两种不同类型的矩阵定义的:邻接矩阵 W 和描述节点特征的可选矩阵 X

邻接矩阵 W 是一个维数为|N|x|N的方阵,它对图中节点之间的关系进行编码。在未加权图形的情况下, W 包括 0 和 1 之间的值。否则,对于加权图,这些值对应于边权重。 X 矩阵的行数对应于图中的节点数| N |,列数对应于特征尺寸 d ₀.以下文章提供了此类维度的示例:

对于(半)监督设置,我们需要包括目标标签,用于在特定的下游任务上训练模型。为节点 NE 和/或整个图形 G 提供训练目标标签。监控信号的集合在 GraphEDM 论文中表示为 S∈{N,E,G}

图形编码器网络

GraphEDM 编码器

属于 GraphEDM 架构的第一个组件是图形编码器网络,表示为 ENC(W,X;θ^e).编码器将以下内容作为输入:

  1. 图的结构形式为邻接矩阵W→|N|x|N|;
  2. 该节点特征以特征矩阵 X →| N | x d₀.的形式出现

该输入由θ^e参数化,以便产生节点嵌入矩阵 Z = ENC(W,x;θ^e)Z 的维数为| N | x d ,其中 d 对应节点嵌入维数。根据编码器的类型,在训练过程中生成并在矩阵 Z 中编码的节点嵌入可能捕获不同的图形属性。例如,在本系列的前一篇文章中报道的,矩阵分解和随机漫步等技术旨在学习低维表示,以保持输入图的全局结构。包括图形神经网络(GNNs)在内的其他技术旨在捕捉局部图形结构:具有相似局部表示的节点应该具有相似的嵌入,而不管原始网络中节点的距离如何。

图形解码器和分类网络

图形解码器网络

解码器组件DEC(Z;θ)将捕捉到的图形特征作为输入,并将其转换成由θ参数化的低维表示。对于无监督的任务,图解码器网络的目标ŵ=dec(z;θ^d)是从节点嵌入 Z 中重建邻接矩阵ŵ,以计算所有节点对的相似性(或不相似性)得分。

分类网络

在监督设置中,分类网络产生标签值ŷs=dec(z;θs)对应于与下游任务相关的输出。如输入部分所介绍的, S 包括被监控信号的采集 {N,E,G}

输出

GraphEDM 框架的输出

GraphEDM 框架能够根据具体的问题设置产生双重输出。事实上,模型的输出对应于训练无监督嵌入算法的邻接矩阵,以及有监督任务的输出标签。直观来看,ŵ的维数与w(|n|x|n|)的维数相同。另一方面, ŷ^S 的维数为|n|x|υ|,其中 Y 为标签空间。取决于受监督的应用,标签输出空间可以不同,以表示节点标签空间、边标签空间和图标签空间。

损失函数

GraphEDM 框架中的损失函数

不同类型的损失项用于优化 GRL 环境中的模型,包括监督损失图正则化损失权重正则化。GraphEDM 模型能够通过学习前面章节中提到的参数组合这些术语θ∈{θe、θd、θ^s}

监督损失项 Lₛᵤₚ^S 将预测标签 ŷ^S 与目标标签 y ^S 进行比较,这取决于下游任务(例如节点分类)。

图正则化损失项 L 𝓰 ᵣₑ利用图结构对模型的权重施加正则化约束。与监督损失不同,图正则化比较解码的邻接矩阵ŵ和地面真实邻接 W 。这种类型的正则化施加了例如相邻节点共享相似嵌入的约束。

权重正则化 L ᵣₑ传统上包括一套技术,可以防止神经架构中的过拟合,提高它们的泛化能力。这使得能够学习正则化系数,其在最小损失函数的方向上定义约束边界。因此,在训练阶段,优化被阻止达到损失函数的最小值,这可能导致过拟合。

下一步是什么

在本系列的下一篇文章中,我将详细介绍 GraphEDM 架构的不同组件,包括不同类型的编码器和损失函数。

对于 GraphEDM 框架上的所有文章,您可以使用以下链接:https://towardsdatascience.com/tagged/graphedm-series。

关于图形表征学习的进一步阅读,可以关注:https://towardsdatascience.com/tagged/grl-series的相关系列。

图形搜索,对遍历和搜索行为的直观介绍。

原文:https://towardsdatascience.com/graph-search-an-intuitive-introduction-to-both-traversal-and-search-behaviour-e9c5f4dd230?source=collection_archive---------20-----------------------

我们几乎不知道,遍历和搜索的行为,以及它们在算法方面的差异,都可以通过使用图搜索从概念上学习!

说到算法和图论,人们首先想到的不是硬核编程,就是复杂的数学。如果你问一个非程序员或普通的平民,他们会把一个算法描绘成一些复杂的计算过程,需要聪明的人来开发。然而,他们不知道他们实际上被误导了。在过去的几十年里,电影、电视节目、游戏和故事都把算法描绘成只有擅长数学的人才能理解的东西。但现实中,事实并非如此。当然,随着越来越多的在线课程出现在网络上,如 Coursera 或 Youtube 上的视频,越来越多的人接触到了算法开发。然而,大多数程序员或开发人员仍然认为算法是最有声望的程序员和数学家的专利。

IT 行业的多个职业都涉及算法开发,比如机器学习(正在兴起)、后端开发等。然而,尽管多种职业(其中许多正在上升)涉及数据结构和算法的工作,但仍然没有足够的兴趣,因为尽管如前所述,职业在上升,但前端开发仍然存在。职业之间的工资仍然保持不变;技能组合可能会因公司和职业而异,但在某些方面对所有开发人员/程序员来说都是一样的,所有程序员都必须经历面试过程(取决于公司,但大多数都是如此)。不同部门的方案编制似乎没有什么不同。公司可能不需要很多算法或者机器学习开发者,但真正的问题是对算法的误解。由于对算法“复杂”的误解,没有多少开发人员像前端开发这样对机器学习或人工智能领域感兴趣。

然而,对许多人来说,是什么让算法变得“难”了呢?让人们理解起来乏味的不是数学或编程;它更多的是关于算法的概念行为。换句话说,人们很难了解算法在概念上是如何工作的,而不是所有编程和数学的理论部分,具有讽刺意味的是,这总是在好莱坞电影中涉及算法的编程场景中描绘,以显示“硬核编程”。

在编程世界中有许多类型的算法,每种算法都有自己的目的和应用。例如,您不能应用冒泡排序算法而不是二分搜索法算法,并期望它在每种情况下都以相同的速度和相同的效率运行。这是不可能的,因为它们被创造的方式和它们的目的。然而,如果我们扩大算法的范围,并根据它们的行为在一般尺度上比较它们,我们会得到三种类型的算法;排序、遍历和搜索。由于排序遵循相同的遍历协议,但只是比较前一个或下一个值,对于这种情况,由于我们是在谈论一般情况,我们将假设排序行为模仿遍历算法的相同行为(在某些方面确实如此)。因此,当学习和试图理解算法的工作方式时,归结起来更多的是关于它们如何遍历为参考或比较而存储的某些值,并在给定的数据集中搜索某些值。

如果你知道这两个基本行为,并理解它们是如何工作的,学习任何算法对你来说都会容易得多。但是对于那些还没有的人,不用担心。使用两种图搜索算法(是的,我们将通过算法本身学习基本的算法行为),我们将了解它们的工作和应用。我决定使用图形,因为它最容易直观地理解,这最终会导致更好的概念理解。

参考文献中使用的两种图搜索算法是广度优先搜索和深度优先搜索。那些读过我之前关于著名的编码问题的文章的人(如果你还没有读过的话,看看),或者知道树遍历的人,可能对这两个基本的,但是高效的算法很熟悉。它们都以线性时间运行,并且可以使用递归或迭代来实现。它们都使用数据结构作为参考(广度优先使用队列,深度优先使用堆栈),最重要的是,它们都可以用于搜索和遍历。但是你可能会想,如果这两个算法都有那么多相似之处,那么用两个算法而不是一个算法有什么意义呢?这些算法可能有许多相似之处,但它们的工作和行为方式是不同的,这将有助于我们理解不同类型的算法如何在更广泛的范围内工作。

对于那些首先不知道什么是图数据结构的人来说,它本质上像树一样工作,但是没有通用的遍历顺序,直到开发人员或用户声明。它们由保存数据的节点或顶点和连接两个顶点的组成。

有向图示例|作者图片

图有不同程度的联系。边与顶点的比率越高,图的连通性越好。在这种情况下,根据上面的例子,我们可以说该图是高度连通的,因为顶点与边的比率是 6:9,相当于 2:3。图表的酷之处在于你可以给每条边添加权重。使用权重,您可以创建高效的搜索和寻路算法,我们将在后面讨论。然而,加权图是具有边的典型图,这些边具有与在顶点之间行进相关联的特定数量或成本。通常,在大多数应用中,需要此成本来评估两个特定对象的最有效路径或距离。最后但同样重要的是,关于本文中的图,您需要知道的最后一件事是图的类型。图的两种最基本的类型是有向和双向的。有向图是边限制顶点之间移动方向的图。看一下上面的图表。边缘只通向一个方向。然而,另一方面,如果它是一个双向图,边可能会导致两条路径。例如,一个从边 A 到边 B,另一个从边 B 到边 A。

双向图示例|作者图片

这两种图都有自己的应用,但是在本文中,为了简单明了,我们将使用有向图。

在继续学习算法行为之前,我们将设置的下一个基本定义是广度优先算法更深入的内容,以及它在图中的工作方式。广度优先被认为是一种强力算法,它在移动到另一个深度级别之前检查所有相邻顶点的值。当顶点被搜索或遍历时,它们的子节点被添加到被称为边界的队列中。该队列遵循 FIFO 结构(先入先出)来跟踪当前顶点和仍有未访问邻居的顶点。

BFS 第一次迭代|作者图片

当某个顶点的所有相邻顶点都被访问过时,队列将退出队列。广度优先是查找两点间任意路径的一种非常低效的方法,但它是比较两个顶点间路径的一种很好的方法。正因为如此,BFS 有助于找出从一个地方到另一个地方的方向。而且说到这个算法的性能,它运行在O(no. vertices + no.edges)。由于性能取决于顶点的数量和图形的大小,因此输入,我们可以考虑这个线性时间。

BFS 第二次迭代|作者图片

最后但同样重要的是,我们需要设置的最后一个定义是什么是深度优先搜索以及它是如何工作的。深度优先搜索算法在横向移动到另一条路径之前检查沿着顶点路径的值。这些类型的算法有利于确定两个顶点之间是否存在路径。为了完成这个路径查找任务,深度优先算法使用堆栈数据结构,或者更常见的是使用递归来跟踪搜索的路径和当前顶点。

DFS 首次迭代|作者图片

如果我们已经到达路径的末端,那么堆栈将继续弹出,直到有一个顶点有未访问的边。这个过程将继续,直到堆栈为空。性能与O(no. vertices + no. edges)时的 BFS 相同,我们已经在线性时间考虑过了。

DFS 第二次迭代|作者图片

为了在本文的其余部分反映算法及其行为,我们将使用这两个函数来反映上面定义的算法:

现在我们有了基本的定义,让我们从谈论搜索行为开始。搜索算法本质上是不断遍历数据直到找到所需值的算法。当然,可以考虑各种参数,但这是基本的通用定义。以线性搜索为例。它将不断遍历列表,直到找到所需的值。如果没有,它将不会返回或打印任何内容。大多数图搜索算法在线性时间运行,因为它们是蛮力算法(这意味着它们易于实现,但性能效率低),但有些运行在日志时间,如二分搜索法。作为一名程序员,让搜索算法在日志时间运行可能是你能做的最好的事情,因为在每个数据集中找到一个普遍的重要模式对我们的眼睛来说是不可见的。然而,让我们来看看搜索是如何更直观地在代码中工作的。以上是深度优先和广度优先搜索图的代码。先说深度优先搜索。我们的算法将不断添加顶点(根据它们在上面定义深度优先搜索时所遵循的路径),直到我们到达期望的顶点。

深度优先搜索递归搜索值为 4 的顶点|按作者排序的图像

如果我们没有到达期望的顶点,那么我们递归地调用顶点的边,直到我们找到顶点的“位置”如果根本没有位置,意味着两个顶点之间没有路径,算法会返回None

深度优先搜索递归尝试查找值为 0 的顶点|按作者排序的图像

请注意该算法如何遍历和评估不同的路径,但仍然无法找到值为 0 的顶点。这是因为从来没有值为 0 的顶点!然而,我们可以注意到算法的排列和算法在每个深度遍历的顺序。

模拟自己的图形搜索或深入了解:【https://github.com/GEEGABYTE1/GraphSearch

既然我们现在知道了搜索在概念上是如何工作的,我们就可以继续遍历了。如果我用一句话来总结遍历,那就是它和搜索一个值是一样的,但是,没有一个实际的目标值来搜索。当试图直观地找出一些东西或发现未来的可能性时,遍历算法是很棒的。大多数遍历算法以不同的方式遍历数据集,直到它们到达数据集的末尾或者满足特定的条件,例如,只遍历路径特定的次数。例如,让我们用深度优先搜索和广度优先搜索来考虑我们的遍历。

我们一直走,直到我们到达了路的尽头,或者已经访问了每一个可能的边缘。在广度优先搜索中,当我们的 BFS 队列为空时,我们知道我们已经到达了终点;对于深度优先搜索,当路径为None(意味着没有更多可能的边要遍历)并且函数自身返回None,结束递归。

BFS 穿越|作者图片

请注意,该算法如何穷尽我们图形中的每个可能的边,直到它达到一个新的深度。深度优先遍历遵循相同的打印和遍历过程,但根据其定义。

深度优先遍历|作者图片

注意深度优先遍历,就像 BFS 一样,遍历相同的路径,就好像它试图搜索一个值。然而,遍历版本不是只打印或返回一条路径,而是打印它们已经走过的每一条不同的路径,直到它们到达终点(在这种情况下,如果它们到达了没有边的顶点)。但是,我们是如何得到不同的抽象路径的呢?信不信由你,获取抽象路径是非常直观的。从根顶点开始,在每次递归和迭代之后,我们弹出在当前路径中从根顶点开始遍历的边。

随着遍历的进行,我们不断弹出已经使用过的根顶点的边,确保没有任何重复的路径。这也可以被认为是另一种结束情况,其中我们继续弹出并遍历图,直到根顶点不再是图的一部分,或者换句话说,不再有根顶点的边需要遍历。

查看更深入的遍历算法:https://github.com/GEEGABYTE1/GraphSearch-Traversal

现在,就应用而言。遍历和排序算法有很多应用。作为人类,我们知道算法是我们今天使用的技术的基本组成部分。它们让我们的任务变得更容易,更容易完成,等等。想一想,仅广度优先搜索和深度优先搜索就有多种应用,从寻路、GPS 系统、文件系统、跟踪优步等等!例如,让我们更深入地看看 GPS 系统,以及遍历和搜索是如何使用我们之前使用的两种算法工作的。

我已经创建了一个名为 SkyRoute 的 GPS 模拟系统,它对温哥华的车站和地标进行采样,以及哪个车站通向哪个地标。用户可以输入起点和终点,程序将使用广度优先和深度优先输出需要作为最佳路径的站点。

SkyRoute 输出从伯纳比湖到萨姆森五世博物馆的最佳路径|图片由作者提供

深度优先算法用于查看是否存在对应于地标的站。SkyRoute 的另一个特点是用户可以添加正在建设中的相应站点(查看下面的 GitHub 链接了解更多信息)。因此,由于用户可以添加正在建设中的电台,电台仍然运行并成为一个选项没有任何意义。因此,为了使程序流适应这些变化,如果有一个车站正在建设中,我们将使用 DFS 来查看从起点到终点是否有另一条路径。如果有,程序会将可能的路线作为路径返回;否则,程序将断定没有可能的路径。本质上,我们的结论是 DFS 不返回路径,因为每个地标至少有一个站。当一个车站正在建设中时,程序会将该车站从每个地标中移除(这个过程相当于我们从一个顶点(如根顶点)中弹出一条边来打印抽象路径)。因此,在起点和期望的目的地之间可能没有路径。

但是如果车站不在建设中呢?这就是 BFS 算法的用武之地。由于我们的 BFS 版本附加了每个可能路径的列表(也是一个数组),我们希望返回最短路径,因为这是当今高效 GPS 或地图应用程序的全部要点。在程序在两个目的地(起点和终点)运行 BFS 后,它将比较路径的每个长度,并返回长度最短的一个,假设选择最少的站点意味着快速和容易的路线。然而,就像 DFS 一样,如果它们之间没有可能的路径,那么算法将返回None,这将向用户指示没有找到路径。

就遍历而言,也许添加一个用户可以看到两点的多条路径的功能对这个项目的未来来说是一个很好的想法,因为它允许用户看到不同的路径,以防碰撞,天气,乘客数量等。遍历算法也将与上面遍历模拟中所示的相同。

不过,这就是地图应用和 GPS 系统的工作方式。使用遍历和搜索算法,GPS 系统和地图应用程序可以在不到一秒钟的时间内输出到达目的地的不同路径!例如,Google Maps 可以基于某些变量(如燃料、交通、运输方式等)输出不同路径的唯一方法是使用遍历和搜索算法。当然,由于效率和性能的原因,他们可能不会使用广度优先或深度优先,但他们的算法基于相同的逻辑运行。

亲自体验一下 sky route:https://github.com/GEEGABYTE1/SkyRoute

所以,算法看起来并没有那么难懂。当然,理解它们是如何工作的可能需要一些时间,但它们并非完全不可能。最重要的是,它们不适合那些只擅长数学的人;任何人都能理解他们。学习和理解算法就像在学校学习一门新的学科或参加烹饪课程。学习一天,你不会有你想象的那么好。不断的练习和学习会使你提高对这门学科的知识和理解。这就是学习数据结构和算法的方式。没有一些基础的数学背景,不能只学算法。如果你想真正理解它们,你必须有时间和耐心去研究它们(概念上的和编程中的)并实践它们。你要记住的是,如果一个人能做到,那么你也能做到!我本人非常喜欢算法和数据结构,因此,它对我来说很容易。然而,如果你现在没有,不要担心,我会继续写算法以及我们如何更好地学习它们,因为开发算法和开发前端一样有趣。

图论基础

原文:https://towardsdatascience.com/graph-theory-basics-88a89863e3c1?source=collection_archive---------24-----------------------

随着图论应用的不断发展,你需要知道的是

诺德伍德主题公司在 Unsplash 上拍摄的照片

在编程和数学术语中,图论真的不是什么新东西,但是它在代码中的实现和使用随着机器学习和人工智能的进步而增长。一个很大的原因是大规模模型的计算能力的进步允许开发复杂的模型来表示任何事物之间的关系。图论技术中最著名和最早的实现之一是 Google 的页面排名算法。页面排名算法是谷歌搜索算法的最初版本,植根于图论,基于一种有效的方法来衡量互联网网页如何通过链接和用户点击/流量连接,以及哪些网页最受欢迎。此外,近年来,图论已被应用于知识图,以帮助理解系统内变量的相互联系(例如,工厂和其中的所有机器和因素,以及它们如何相互影响)。此外,图论已被应用于经济模型,以了解股票市场如何表现,以及区块链的内部工作是由图论支持的。因此,通过图形方式计算和创建极其复杂的模型的广泛能力只会继续增长,学习和理解基础知识对于将其应用于其他用例至关重要。

照片由劳伦·里奇蒙在 Unsplash 拍摄

图论基础和术语

在数学中,图论是对图形的研究,图形是用于建模对象之间成对关系的数学结构。这个上下文中的图由个顶点(也称为个节点个点)组成,这些顶点由条边(也称为条链接条线)连接。—维基百科

快速的维基百科搜索会给你这个图论的定义,下面我们将开始分解它是什么以及它是如何工作的

定义:

  • 顶点/节点——这些对象通常具有自身的属性,然后连接到图形中的其他对象。对象可能具有的属性的一个简单示例是权重或值,在更复杂的对象中,这还可能包括成本、描述性属性(颜色、大小、重量)、能力、概率等。这都取决于图网络是如何构建的以及它试图完成什么
  • 边缘/链接-边缘本质上是对象之间的关系或连接它们的道路。相互之间有边的对象有关系,而没有连接的对象没有关系。
  • 有向/无向图-理解有向图和无向图之间的区别的最简单的方法是将对象之间的边视为双向道路或单向道路。有向图显示了从一个对象到另一个对象的关系,这种关系传递了与另一个对象的关系中的任何东西,并且不是对等的。无向图是两个对象之间的连接,但关于其关系的信息可以在它们之间双向流动。需要指出的一个关键点是,在有向图中,一对节点之间可以有两条边来模拟这两个节点之间的“无向”性质。
  • 循环/无环图形-循环图形是一种具有一组连接成闭环的节点的图形,无环图形不具有闭环属性。

图形在计算机中是如何表示的?

计算机图形表示中两个最常见的主题是邻接矩阵(有时称为关联矩阵)或邻接表。

邻接矩阵——在这种方法中,图形被转换成图形的矩阵表示。该矩阵将是一个 n×n 形状的矩阵,其中 n 表示节点的数量,矩阵中的值表示节点之间的边,如下所示。值得注意的是,无向图的矩阵表示将是其自身沿对角线的镜像。

无向图邻接矩阵的可视化表示。图片作者。

邻接表——这个版本的图被表示为顾名思义的列表。它是一个无序列表,描述了图中顶点(或边)的邻居。

无向图的邻接表的可视化表示。作者图片

将图形放入这两种形式,允许我们对图形进行计算编程,这样我们就可以设置图形的规则、关系、属性和变化。

有了这些基本术语和概念,我们可以探索一些用图论来解决基本问题的例子,并希望用它们作为更复杂系统的构建模块的例子。

苏珊·尹在 Unsplash 上的照片

最短路径

关于图网络,您可能想知道的最基本的事情之一是路径之间的距离以及它们之间的最佳或最短路径。这可能有用的一些例子是查看电网或寻找社会网络中的分离度(凯文·贝肯)。

BFS(广度优先搜索)和 DFS(深度优先搜索)

在几乎所有的学习平台中,图论引入的前两个算法是 DFS 和 BFS。它们都是遍历图形的算法。从本质上讲,DFS 和 BFS 都在努力实现相同的目标,只是方式略有不同。

从 BFS 开始,该算法背后的原理是在移动到下一个节点之前,从一个起点调查所有相邻节点。队列用于帮助指示哪些节点已经被访问,一旦该路径完成,它将转到下一个未被访问的节点,并像以前一样开始遍历图,标记所有被访问的节点。这个循环将对整个图形重复,直到所有节点都被访问过。在队列中,可以确定从起点到目标端点的最短路径。下面是 BFS 搜索算法的伪代码示例。

 1  procedure BFS(G, root) is
 2      let Q be a queue
 3      label root as discovered
 4      Q.enqueue(root)
 5      while Q is not empty do
 6          v := Q.dequeue()
 7          if v is the goal then
 8              return v
 9          for all edges from v to w in G.adjacentEdges(v) do
10              if w is not labeled as discovered then
11                  label w as discovered
12                  Q.enqueue(w)

DFS 或深度优先搜索是一种非常类似于 BFS 的算法,但它的行为略有不同。当遍历该图时,一旦到达 DFS 中的死胡同,该算法将回溯到与未被访问的节点相连接的前一个节点,并在该路径上继续。然后,它将只去一个随机的节点,如果它没有从图的原始网络连接。这两种方法都是最先教授的沿着图遍历并找到最短路径的方法。潜在的应用将是将其应用于社交网络的图表,以确定具有相似背景、朋友或爱好的人的潜在建议。下面是一个 DFS 伪代码的例子。

1 procedure DFS_iterative(G, v) is
2    let S be a stack
3    S.push(v)
4     while S is not empty do
5        v = S.pop()
6         if v is not labeled as discovered then
7             label v as discovered
8             for all edges from v to w in G.adjacentEdges(v) do
9                 S.push(w)

还有更高级的图遍历方法,例如 Bellman-Ford、Djikstra 和 Kruskal。每一种方法都尝试并解决在 BFS 或 DFS 中使用的方法无法解决的额外问题,例如,具有负权重/长度的边、循环图等…

照片由艾米-利·巴纳德在 Unsplash 拍摄

其他图论问题:

  • 枚举——换句话说,就是对满足特定条件的图形进行评估和计数,或者换句话说,就是解决组合数学问题。
  • 子图——查看图形以确定一个图形的组件是否是另一个图形的子组件,或者查看图形之间的“遗传”特征
  • 图表着色—类似于枚举,但是将着色应用于图表问题,这样您就不会在图表的着色顶点上碰到相似的颜色
  • 统一——评估约束更多(或信息更多)的图表,以及它们如何汇总成约束更少(或更一般化)的图表或模型
  • 网络流量——这类问题的一个例子是评估一个能源网格,以确定整个系统的能量流量
  • 可见性问题——尝试解决一个类似于博物馆警卫问题的问题,这样你可以计算出参观整个博物馆画廊的最少警卫人数。
  • 分解——查看特定条件下的分解图。
  • 路线问题——最短路径就是一个这样的问题,另一个是旅行推销员问题或哥尼斯堡七桥问题。

照片由吕山德·袁在 Unsplash

为什么学习这个很重要

如前所述,图论正慢慢成为一种更有效的方式来表示现实世界的问题。解决任何系统的极其复杂的关系和细节的计算能力现在可以通过编程的方法来完成。本文旨在真正充当图论的初级读本,并鼓励您继续学习评估和实现图来解决现实世界问题的不同方法。

我个人最喜欢的课题之一是区块链,在某种程度上,你可以从图论的角度来看待区块链。

如果您对本文有任何问题或意见,请留下您的评论。

图变换器:图变换器的推广

原文:https://towardsdatascience.com/graph-transformer-generalization-of-transformers-to-graphs-ead2448cff8b?source=collection_archive---------2-----------------------

这篇博客是基于与 Xavier Bresson 在 2021 年 AAAI 关于图的深度学习:方法和应用研讨会(DLG-AAAI’21)上发表的论文。

我们提出了 Graph Transformer,这是一个可以对任意图形进行操作的转换器神经网络。

博客大纲:

  1. 背景
  2. 目标
  3. 图形转换器的关键设计方面
  4. 提议的图形转换器架构
  5. 来自实验的评论

1.背景

让我们从两个关键词开始,变形金刚图形作为背景。

变形金刚(电影名)

基于 Transformers 1的神经网络是自然语言处理(NLP)中表示学习的最成功的架构,克服了顺序处理引起的递归神经网络(RNNs)的瓶颈。作为变压器的核心构件,存在多头关注机制,由以下公式表示:

图 5:使用多头注意机制的单词“I”的特征更新等式。这些符号代表通常的含义。

使用多头注意力,一个单词关注句子中的每个其他单词,并组合接收到的信息以生成其抽象特征表示。

图表

图是无处不在的数据结构。数据集可以用图形来表示的应用领域非常广泛。比如化学中的分子图,物理中的粒子间相互作用,医学中的药物蛋白质相互作用,社交媒体中的用户及其社交和商业联系,组合优化中的问题等。

图 2:具有图结构数据集的代表性领域.链接

对于图上的学习,图神经网络 (GNNs)已经成为深度学习中最强大的工具。

简而言之,GNNs 由几个参数化的层组成,每个层接受具有节点(和边)特征的图,并通过考虑可用的显式连接结构(图结构)来构建节点(和边)的抽象特征表示。这样生成的特征然后被传递到下游分类层,通常是 MLPs,并且目标属性被预测。

2.目标

现在,目标是将 transformer 神经网络推广到图形,以便它可以学习具有任意结构的图形和数据集,而不仅仅是顺序的(可以解释为由 NLP Transformers 完成)。

为了实现目标,我们着重于将变压器的关键设计原则从 NLP 扩展到一般的图形。

3.图形转换器的关键设计方面

我们发现,使用图稀疏性和位置编码的注意力是将转换器推广到任意图的两个关键设计方面。

现在,我们从 NLP 和图的上下文来讨论这些,以使 Graph Transformer 的扩展更加清晰。

图形稀疏性

在 NLP 中,转换器在构建单词的特征表示时考虑全部注意力。也就是说,转换器将一个句子视为一个单词的全连接图。这种全神贯注的选择是合理的,原因有两个:

首先,很难在一个句子中的单词之间找到有意义的稀疏交互或联系。例如,一个句子中的一个单词对另一个单词的依赖性会随着上下文、用户的视角和手边的应用而变化。在一个句子中的单词之间可能存在许多似是而非的基本事实联系,因此,句子的文本数据集通常不具有显式的可用单词交互。因此,让模型决定单词如何依赖于其他单词是有意义的。

第二,NLP 中如此解释的全连通图,节点往往少于几十上百个(句子往往少于几十或几百个单词)。在这种大小的图中,关注每个节点在内存和时间上是可行的。

由于这两个原因,可以在 NLP 转换器中进行充分的关注,随后的工作[2,3,4]表明它在语言建模和几个 NLP 任务中卓有成效。

图 3:全神贯注的注意力被限制在本地附近。

然而,在实际的图数据集的情况下,图具有基于应用领域的任意可用连接结构,并且具有高达数百万甚至数十亿的节点大小。在神经网络中学习时,可用的结构为我们提供了丰富的信息源,而节点大小实际上使得不可能有这种数据集的完全连接的图。

基于这些原因,拥有一个图转换器是实际的(为了可行性)和有利的(为了利用稀疏结构信息),其中一个节点关注本地节点邻居,类似于图关注网络(GATs)[5]。

事实上,局部信息聚集是 GNNs 的核心,表明稀疏性是泛化的良好归纳偏差。

位置编码

Transformer 中的注意机制对于节点的排序是不变的。它不知道单词在序列(或句子)中的位置。这意味着,转换器考虑多组单词,而不是 NLP 中的单词序列,如下面的比较所示:

图:对于多头注意机制,输入可以解释为多组单词。

那将意味着丢失一些关于单词排序的信息,不是吗?

为了避免这种情况并使 transformer 知道顺序信息,在 Transformer 中需要某种位置编码。Vaswani 等人1的原始变换器使用正弦位置编码,在输入端添加到每个单词的特征向量。这有助于将单词之间必要的普遍(顺序)关系编码到模型中。

我们扩展了图形转换器位置信息编码的关键设计模块。事实上,GNNs [6,7,8]中的一系列研究最近表明,位置信息改善了 GNNs,并克服了 GNNs 在几个基本任务中的失败。

因此,我们利用了 GNNs 中位置信息的最新成果,并在 Graph Transformer 中使用拉普拉斯位置编码[8]。我们使用预先计算的拉普拉斯特征向量[9]来添加到第一层之前的节点特征中,类似于在原始变换器中如何添加位置编码1。

图:原始转换器 v/s 建议的图形转换器中的位置编码(PEs)

拉普拉斯 PEs 是原始变压器中使用的正弦 PEs 的自然推广,因为正弦 PEs 可以被解释为线图的特征向量,即 NLP 中的句子。

因此,在将转换器推广到任意图时,注意力期间的稀疏图结构和输入处的位置编码是我们考虑的两个重要因素。

4.提议的图形转换器架构

现在,我们将介绍所提出的架构——图形转换器层和具有边缘功能的图形转换器层。如下所示的层示意图由主要组件组成——带 PEs 的输入、关注限于本地邻居的多头关注机制以及前馈模块。

与 Vaswani 等人1的标准转换器相比,将 transformer 概括为图形以产生图形转换器的关键区别(或扩展)是:

I)注意机制是每个节点的邻域连接性的函数,由公式表示:

ii)位置编码由拉普拉斯 PEs 表示。特别地,在训练之前为每个图预先计算图拉普拉斯的特征向量,并且将节点的k-最小非平凡特征向量指定为该节点的 PE。

iii)前馈模块使用批量归一化【10】代替原始变压器1中使用的层归一化【11】。我们的经验证据支持了这一点,即使用批标准化代替层标准化会产生更好的性能。

iv)图形转换器扩展为具有边缘表示(参见架构图右侧的具有边缘特征的图形转换器层)。这种架构对于具有丰富信息的数据集至关重要,例如,分子图中沿边缘的键信息,或者知识图中的关系类型。在这种边缘扩展架构中有两件事需要注意:边缘特征被融合到相应的成对隐式注意力分数,并且在每一层都有指定的边缘特征流水线,如以下层更新等式所示:

这结束了对所提出的图形转换器的描述。关于完整的层更新方程,我们参考该论文。

5.来自实验的评论

我们在基准数据集上评估了 Graph Transformer,并验证了我们的设计选择,同时试图回答一些公开的研究问题:I)对于将 Transformer 推广到图形,是局部注意还是完全注意,ii)如何编码稀疏结构信息?iii)位置编码候选。

我们备注以下结果:

a)如已经讨论的,图稀疏性是关键的,并且与使用完全注意相比,在注意机制中使用图稀疏性总是给出更好的性能。GNNs 在几个应用领域的成功已经证明了稀疏度对于图形数据集是一个很好的归纳偏差。

b)在注意力、PEs 使用、标准化候选等设计选择的几种组合中。架构使用 i)关注本地邻居、ii)拉普拉斯 PEs 和 iii)前馈模块中的批量归一化层,在用于评估的所有数据集上具有最佳性能。这从经验上验证了使用这些组件来有针对性地推广变压器的选择。

c)由于拉普拉斯 PE 具有期望的属性,具有 I)距离感知信息,ii)可区分的节点特征,以及 iii)原始变换器的 PE 对一般图形的概括,因此与用于研究图形变换器的文献中使用的 PE 候选相比,根据经验,它是用作图形变换器的合适的 PE 候选,甚至(论文中详细讨论了相关工作)。

d)总体而言,与评估数据集相比,Graph Transformer 在 gnn 中实现了有竞争力的性能。所提出的架构性能明显优于基线 GNNs (GCNs [12]和 GATs [5]),并有助于缩小原始转换器和图形转换器之间的差距。因此,图形转换器作为一种新的强大的基于注意力的 GNN 基线出现,我们希望它可以很容易地扩展到未来的研究中,只要它简单明了,并能从转换器中直接概括出来。

数值实验的表格在论文里,代码实现在 GitHub 上开源,附带的视频演示在 YouTube 上,对应链接如下:

论文:【https://arxiv.org/abs/2012.09699
GitHub:https://github.com/graphdeeplearning/graphtransformer
视频:https://youtu.be/h-_HNeBmaaU?t=240

1 瓦斯瓦尼,a .,沙泽尔,n .,帕尔马,n .,乌兹科雷特,j .,琼斯,l .,戈麦斯,A.N .,凯泽,日,和 Polosukhin,I. (2017)。你需要的只是关注。

2 Devlin,j .,Chang,M.W .,Lee,k .和 Toutanova,k .(2018 年)。Bert:用于语言理解的深度双向转换器的预训练。

[3]拉德福德、纳拉辛汉、萨利曼斯和苏茨基弗(2018 年)。通过生成性预训练提高语言理解能力。

[4] Brown,T.B .,Mann,b .,Ryder,n .,Subbiah,m .,Kaplan,j .,Dhariwal,p .,Neelakantan,a .,Shyam,p .,Sastry,g .,Askell,a .,Agarwal,s .(2020 年)。语言模型是一次性学习者。

[5]韦利奇科维奇、库库鲁勒、卡萨诺瓦、罗梅罗、莉雅和本吉奥(2018 年)。图形注意力网络。

[6]斯里尼瓦桑和里贝罗(2019 年)。位置节点嵌入和结构图表示的等价性。

[7] You,j .,Ying,r .和 Leskovec,j .(2019 年)。位置感知图形神经网络。

[8] Dwivedi,V. P .,Joshi,C. K .,Laurent,t .,Bengio,y .,和 Bresson,X. (2020 年)。基准图神经网络。

[9] Belkin,m .和 Niyogi,P. (2003 年)。用于降维和数据表示的拉普拉斯特征映射。

[10] Ioffe,s .和 Szegedy,c .(2015 年)。批量标准化:通过减少内部协变量转移加速深度网络训练。

[11] Ba,J.L .,Kiros,J.R .和 Hinton,g . e .(2016 年)。图层规范化。

[12]基普夫和韦林(2016 年)。基于图卷积网络的半监督分类。

使用 D3 的图形数据可视化

原文:https://towardsdatascience.com/graphical-data-visualization-using-d3-ae0ee82ae2e2?source=collection_archive---------27-----------------------

使用 MPLD3 创建交互式数据可视化

粘土银行在 Unsplash 拍摄的照片

D3 是一个基于 Javascript 的数据可视化库,用于在浏览器中创建交互式数据可视化。它基于 HTML5 和 CSS,使得可视化更加动态和吸引人。它支持 2D 和三维可视化。因为它是一个 Javascript 库,我们可以在任何框架上使用它,比如 Angular。JS 反应过来。JS 等。

使用某些库可以在 Python 中创建基于 Javascript 的可视化。其中一个库是 MPLD3,这是一个基于 D3 的开源 Python 库。JS 并构建在 Matplotlib 之上。它用于创建交互式数据可视化。

在本文中,我们将探索 MPLD3 并使用它创建一些可视化。

让我们开始吧…

安装所需的库

我们将从使用 pip 安装来安装 MPLD3 开始。下面给出的命令将使用 pip 安装 MPLD3。

pip install mpld3

导入所需的库

在这一步中,我们将导入创建交互式数据可视化所需的所有库。

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import mpld3
from mpld3 import plugins 

创建图表

现在我们将开始创建不同类型的图表。默认情况下,如果我们希望使用 mpld3 生成每个图表,我们需要运行下面给出的命令。

mpld3.enable_notebook()
  1. 泡泡剧情
# Scatter points
fig, ax = plt.subplots()
np.random.seed(0)
x, y = np.random.normal(size=(2, 200))
color, size = np.random.random((2, 200))
ax.scatter(x, y, c=color, s=500 * size, alpha=0.9)
ax.grid(color='lightgray', alpha=0.3)

泡泡图(来源:作者)

创建的图具有高度的交互性,可以使用图表下方提供的不同选项进行控制。

2.直方图

fig = plt.figure()ax = fig.add_subplot(111, facecolor='#EEEEEE')
ax.grid(color='white', linestyle='solid')x = np.random.normal(size=1000)
ax.hist(x, 30, histtype='stepfilled', fc='lightblue', alpha=0.9);

直方图(来源:作者)

3.折线图

# Draw lines
fig, ax = plt.subplots()
x = np.linspace(-5, 15, 1000)
for offset in np.linspace(0, 3, 4):
    ax.plot(x, 0.9 * np.sin(x - offset), lw=5, alpha=0.9,
            label="Offset: {0}".format(offset))
ax.set_xlim(0, 10)
ax.set_ylim(-1.2, 1.0)
ax.text(5, -1.1, "Here are some curves", size=18, ha='center')
ax.grid(color='lightgray', alpha=0.3)
ax.legend()

折线图(来源:作者)

4.支线剧情

fig, ax = plt.subplots(3, 3, figsize=(6, 6))
fig.subplots_adjust(hspace=0.1, wspace=0.1)
ax = ax[::-1]X = np.random.normal(size=(3, 100))
for i in range(3):
    for j in range(3):
        ax[i, j].xaxis.set_major_formatter(plt.NullFormatter())
        ax[i, j].yaxis.set_major_formatter(plt.NullFormatter())
        points = ax[i, j].scatter(X[j], X[i])

plugins.connect(fig, plugins.LinkedBrush(points))

次要情节(来源:作者)

在这里,您可以清楚地看到我们使用 MPLD3 创建的不同图表和图形。所有这些图表都具有高度的互动性和视觉吸引力。继续尝试不同的数据集,创建不同的可视化效果,并让我知道您在回复部分的评论。

本文是与 Piyush Ingale 合作完成的。

在你走之前

感谢 的阅读!如果你想与我取得联系,请随时通过 hmix13@gmail.com 联系我或我的 LinkedIn 个人资料 。可以查看我的Github*简介针对不同的数据科学项目和包教程。还有,随意探索* 我的简介 ,阅读我写过的与数据科学相关的不同文章。

死亡率图表

原文:https://towardsdatascience.com/graphing-mortality-a39fc504bf7a?source=collection_archive---------41-----------------------

仿效国家统计局的死亡率图表。

国家统计局的每周报告展示了一张死亡登记的图表。读者可以看到 2015 年至 2019 年的注册范围,以及最近一年。我们可以为其他国家仿效这个图表。

这些数字是死亡登记的数字。(图片: ONS )

我们的数据世界整理了两个来源的全因死亡率数据。加州大学的研究人员维护着人类死亡率数据库。该数据库依赖欧统局和各国统计局。Ariel Karlinsky 和 Dmitry Kobak 收集了世界死亡率数据。

例子国家是瑞典。瑞典统计局每周发布死亡档案更新。与国家统计局不同的是,初步数据显示的是死亡发生的日期——某人死亡的时间。存在死亡日期未知的死亡。对于这些死亡中的大多数,瑞典当局知道月份。

搭建桌子

我们可以通过 R 中的步骤来制作这种风格的图形。我们首先从我们的数据世界网站下载基本数据文件:

owid_all_cause_deaths_df <- read_csv(file = "excess-mortality-raw-death-count.csv")

然后我们对行进行过滤,得到瑞典的死亡数字:

sweden_deaths_df <- owid_all_cause_deaths_df %>%
  filter(Entity == "Sweden") %>%
  mutate(Day = as_date(Day))

为了获得 2015 年至 2019 年的范围,我们制定了一个总结框架。然后,fill函数将第 52 周的值复制到第 53 周。大多数年份没有 53 周:

sweden_summ_df <- sweden_deaths_df %>%
  select(Day, 6:10) %>%
  pivot_longer(2:6,
               names_to = "owid_measure",
               values_to = "deaths_all_ages") %>%
  group_by(Day) %>%
  summarise(deaths_2015_2019_min = min(deaths_all_ages, na.rm = FALSE),
            deaths_2015_2019_max = max(deaths_all_ages, na.rm = FALSE)) %>%
  fill(deaths_2015_2019_min,
       deaths_2015_2019_max)

我们将这些汇总统计数据加入到主要的每周数据中,创建了一个“整洁”的表格:

sweden_deaths_tidy_df <- full_join(sweden_deaths_df,
                                   sweden_summ_df,
                                   by = "Day") %>%
  select(Day, average_deaths_2015_2019_all_ages,
         deaths_2020_all_ages, deaths_2015_2019_min,
         deaths_2015_2019_max) %>%
  pivot_longer(2:3,
               names_to = "owid_measure",
               values_to = "deaths_all_ages")

创建图表

最后,我们创建图表。我们从它的核心开始:

sweden_deaths_gg <- sweden_deaths_tidy_df %>%
  ggplot(aes(x = Day)) +
  geom_line(aes(y = deaths_all_ages,
                colour = owid_measure,
                linetype = owid_measure),
            size = 1.5) +
  geom_ribbon(aes(ymin = deaths_2015_2019_min,
                  ymax = deaths_2015_2019_max,
                  fill = owid_measure),
              alpha = 0.3) +

我们希望 2015 年至 2019 年的平均值是一条虚线。这个系列的色调较浅。2020 年的死亡线应该是实线,有明显的颜色:

scale_linetype_manual(values = c("dotted", "solid")) +
  scale_fill_manual(values = c("white", "#0AFFFF")) +
  scale_colour_manual(values = c("#008080", "#800000")) +

接下来,我们更改轴刻度,使其看起来更好,带有漂亮的断点:

scale_x_date(date_labels = "%d-%b",
               breaks = sweden_breaks,
               expand = c(0,0)) +
  scale_y_continuous(labels = label_comma(),
                     breaks = pretty_breaks(),
                     limits = c(0,2700)) +

标签是下一部分,关闭图例:

labs(title = "Sweden suffered two waves of high deaths in 2020.",
       subtitle = "Number of deaths reported to Statistics Sweden by week. Excludes deaths with unknown dates.",
       x = "Week of death",
       y = "",
       caption = "Source: Our World in Data: Excess mortality during the Coronavirus pandemic (COVID-19).") +
  theme(legend.position = "none") +

最后,我们添加了带有geom_text的直接标签,分别采用两种颜色:

geom_text(data = filter(sweden_deaths_tidy_df,
                          Day == as_date("2020-06-28") &
                            owid_measure == "deaths_2020_all_ages"),
            aes(x = Day, y = deaths_all_ages, label = "Deaths in 2020"),
            color = "#800000", vjust = -2, size = 5, fontface = "bold") +
  geom_text(data = filter(sweden_deaths_tidy_df,
                          Day == as_date("2020-06-28") &
                            owid_measure == "deaths_2020_all_ages"),
            aes(x = Day, y = deaths_2015_2019_min,
                label = "Average and range of deaths\n2015 to 2019"),
            color = "#008080", vjust = 1.5, size = 5, fontface = "bold")

瑞典的死亡率图表在这里:

第 53 周的平均值和范围与第 52 周相同。(图片: R 酒馆)

完整的 R 代码可以在 R Pubs 和 GitHub 上获得。

GraphQL —使用 TypeGraphQL 和 typegoose 的代码优先(解析器优先)

原文:https://towardsdatascience.com/graphql-code-first-resolver-first-using-typegraphql-and-typegoose-747616223786?source=collection_archive---------26-----------------------

斯科特·格雷厄姆在 Unsplash 上拍照

G raphQL 是一种开源的查询和数据操作语言,由脸书在 2015 年创建。尽管它被社区定义为 REST 的可能替代品,但根据每个 API 的架构和需求,有些项目可能适合 GraphQL API,而有些项目可能适合 REST API。但是由于它在过去几年的流行,一些大公司已经将他们的 API 迁移到 GraphQL APIs,而一些公司选择了同时使用 REST 和 GraphQL 的混合方法。

图片由 GraphQL 提供

在创建 GraphQL API 时,可以使用许多工具来管理 API 的创建。目前可用于创建 GraphQL APIs 的一些主要和流行的工具有

  • graph QL()graph QL/graph QL-js)
  • 阿波罗( )阿波罗/阿波罗服务器 )
  • express graph QL(/express-graph QL)
  • 普里斯马(https://www.prisma.io/)
  • AWS AppSync

除此之外,在我写这篇文章的时候,还有很多工具正在开发中。所有这些工具都有各自的优点和缺点。本文不打算对这些工具进行比较,所以让我们继续讨论 GraphQL 的创建。

创建 GraphQL API 时,我们需要做的主要工作是定义 GraphQL 模式。有两种常见的方法可以做到这一点。

  • 模式优先开发
  • 代码优先开发

图式优先发展

在模式优先开发中,我们首先定义模式,然后实现与已定义模式上的定义相匹配的代码。为了定义模式,我们将使用模式定义语言,这是 GraphQL 团队推出的一种查询定义语言。下面是一个我们如何使用模式优先开发来定义模式的例子。

代码优先开发

在代码优先开发中,我们首先开始创建解析器,而不是首先创建模式。因此,解析器会自动生成模式。因此,在这里我们不必手动创建模式。但是缺点是仅仅看代码很难理解模式。

如上所示,我们可以看到,对于类型,我们可以使用 GraphQLObjectType 和属性作为字段来定义。解析器也是如此。

您可以选择用于创建 GraphQL API 开发的开发方法。这种选择需要在开发之初完成,并且可能取决于几个因素,如语言支持、开发人员经验等...在本文中,我们将探讨代码优先的开发方法。

使用 TypeScript 进行代码优先开发

Typescript 是一种基于 Javascript 的语言,我们可以在其中使用静态类型定义。通过使用静态类型检查,我们可以理想地在编译时移除许多错误,而不是在运行时将它们识别为错误,这在大型应用程序中非常有用。除了静态类型检查之外,使用 Typescript 还可以获得更多的开发人员功能,如 IntelliSense。由于这些特性,许多大型 Javascript 项目选择在其 Javascript 项目之上使用 Typescript 来增强其用途。对于 GraphQL APIs 也是如此。

让我们再来看看如何使用 TypeScript 实现 GraphQL 的代码优先开发。

正如您所看到的,当我们使用 Typescript 时,我们需要定义用户类型,因此之后我们可以将这个静态类型用于我们的其他实现和验证。此外,我还添加了一个模拟用户列表,用作模拟数据,它也使用创建的类型 user。但是在大多数应用程序中,这些数据将来自数据库。让我们使用 MongoDBas 作为我们的数据库,使用 mongoose 作为我们的 ODM 工具。那么完整的模式实现将如下所示。

在上面的代码中,我们可以看到,对于 mongoose,我们使用 user 类型定义了 UserModel,在解析器中(第 17 行),我们调用 MongoDB 并直接从数据库中获取结果。

上述解决方案运行良好,并提供了我们期望从 GraphQL API 获得的所需功能。但是现在让我们假设我们需要向我们的用户类型添加一个电子邮件字段。让我们检查上面的代码,并确定我们需要在哪里进行代码修改,以便进行这个简单的修改。经过调查,您可能已经发现我们需要在 3 个位置进行代码修改。

  • 在 UserType GraphQLObjectType 中,我们需要添加
email: { type: GraphQLString }
  • 在 Typescript 接口定义中,我们需要添加
email: string
  • 在 mongoose 模式定义中,我们需要添加
email: { type: String, required: true }

这在我们的例子中可能看起来不多,但是在大型应用程序中,这些定义将位于不同的文件中,开发人员需要跟踪所有这些文件来进行这些修改。那么,有没有一种方法可以让我们只在一个地方修改就能处理这些场景呢?答案是是的,这就是我们介绍 TypeGraphQLtypegoose 的地方。

TypeGraphQL 和 TypeGoose

图片来自 类型图 QL

TypeGraphQL 是一个库,可以用来使用 TypeScript 创建 GraphQL APIs。它提供的主要特性是在 GraphQL 模式和 Typescript 静态类型之间保持同步。

Typegoose 是一个使用 Typescript 轻松编写 mongoose 模式的包装器。

首先,让我们看看如何使用 TypeGraphQL 来转换我们定义的模式。

如你所见,我们在代码中引入了一些装饰器。主要是 @ObjectType@Field decorator。通过使用@Field 这个装饰器,我们指定这个字段也应该在我们的 GraphQL 模式中可用。因此,如果我们希望在静态类型中有一个属性,而这个属性不需要在 GraphQL 模式中,我们可以忽略为这个属性提到这个@Field 装饰器。

下一个问题是,我们应该在哪里为 GraphQL 类型定义数据类型。为此,我们可以使用相同的 @Field 装饰器。但是在上面的代码中,我们从来没有使用这个 decorator 来定义 GraphQL 类型的数据类型,我们只为我们的 Typescript 类型定义了类型。这是因为对于字符串,布尔数据类型 TypeGraphQL 足够智能,可以为 GraphQL 类型识别相同底层数据类型。当 Typescript 类型和 GraphQL 类型不同时,我们可以使用@Field decorator 来表示数据类型,如下所示。

@Field(() => Int, description: "Age of the user")
age: Number;@Field(() => String)
createdAt = new Date().toUTCString()

正如您所做的,除了指定类型,我们还可以使用 decorators 指定其他选项。(描述等……)

接下来,让我们尝试将 typegoose 集成到同一个模式中。

在这里,你可以再次看到我们引入了另一个名为 @props 的装饰器。这个装饰器和 @Field 装饰器的作用是一样的,只是针对猫鼬。它指定这个字段应该在我们的 mongoose 模式中可用,并最终在我们的 MongoDB 数据库中可用。和上面的@prop 一样,我们也可以传递将被映射到数据库集合中的选项。同样,如果我们需要在数据库中存储不同的数据类型,我们可以像下面这样定义它们。

@prop({ type: () => [String] })

@prop({ type: () => Job })

集成 TypeGraphQL 后,我们的解析器将如下所示。

这里我们使用 @Query decorator 来定义一个查询,并通过使用 typegoose 定义来查询我们的数据库并返回数据。

现在让我们来看一下我们的场景,我们的 GraphQL 模式需要一个新的 email 字段。你能确定哪些地方我们需要改变吗?是的,现在我们只需要改变一个位置,如下所示。

@Field()
@prop({ required: true })    
email!: string;

现在不需要找到每个位置,因为我们的 GraphQL 模式、Typescript 类型和 mongoose 模式都是从一个位置同步的。

这是一个简单的介绍,其中我们使用代码优先方法中的 TypeGraphQL 和 typegoose 来创建 GraphQL。显然,这些工具比我在本文中使用的用例更强大。因此,如果您对如何在您的下一个项目中安装这两个非常棒的库更感兴趣,或者需要找到相关指南,请务必访问它们的官方文档,以便在您的下一个 GraphQL API 项目中增强更多功能。

谢谢:)

GraphQL 演练:如何查询加密(使用 Uniswap 和 DeFi)

原文:https://towardsdatascience.com/graphql-walkthrough-how-to-query-crypto-with-uniswap-defi-e0cbe2035290?source=collection_archive---------2-----------------------

学习 GraphQL,从比特币和以太坊等区块链网络中搜索数据

(照片信用

如果在 2021 年你是一名网络开发人员,那么你很有可能听说过 GraphQL。自从脸书在 2015 年公开发布这种查询语言以来,它的受欢迎程度已经飙升。虽然有些人声称这意味着“REST APIs 的死亡”,但从谷歌搜索趋势来看,这种炒作仍然有点言过其实。

(图像源)

由于 GraphQL 越来越受欢迎,今天我们将通过另一个令人兴奋的技术:加密货币的例子来看看这项令人兴奋的技术。

使用 GraphQL,我们将查询和过滤世界上最大的区块链网络上的数据。我们将探索 Uniswap ,市场上最热门的新 DeFi 加密交易所,我们将直接查看交易所的实时订单和交易量。

到本文结束时,您将能够查询 Uniswap 并找出哪两个加密令牌是最受欢迎的交易令牌。

首先,快速总结一下

让我们定义我们的术语,以便熟悉我们将使用的工具。

GraphQL :一种查询语言,用于从数据库或公共 API 端点请求数据。与 SQL(用于 REST APIs)不同,这种语言使用 JSON 符号,并允许您在同一个网络请求中进行多个查询。没有更多的 API 垃圾来访问深度嵌套的数据!

Uniswap:aDeFi加密货币交易所。“DeFi”代表“去中心化金融”,这是一个引人入胜的在线运动,但是细节不在本文的讨论范围之内。你需要知道的是,这个交易所让你在以太网上购买&出售密码,而不需要通过一个像比特币基地或币安这样的集中中间人注册账户。

:一种“查询以太坊、IPFS 等网络的索引协议”我们将使用这个网站,这是一个开放的 API-explorer ,梳理实时区块链数据,看看有多少人通过 Uniswap 交换加密令牌。这就是 GraphQL 的用武之地——它是 Graph 用来搜索区块链数据的查询语言。

好了,我们开始吧!

步骤 1:在 Uniswap 上搜索所有令牌

对于我们的第一个查询,让我们对 Uniswap 上列出的所有加密令牌进行基本搜索。通过这种方式,我们可以看看新的语法,看看它是如何工作的,以及它为我们提供了什么。我们在查询结果中找到的任何代币都是你可以在交易所买卖的代币。

如果你在家跟着,这里的是 Uniswap explorer,我们的查询在下面截图的左边。这里什么都没有:

在左边,您将看到我们的查询!我们正在访问 Uniswap 的令牌 对象,我们只对三个字段感兴趣:“符号”、“名称”和“小数”。

右侧列出了我们的查询结果,在这里我们可以看到一个很长的加密令牌列表,我们可以在这个交易所进行买卖。其中大部分是陌生的,但在这个数千枚代币的列表中,有一个物体上写着“比特币”和“BTC”

说到这里。

我们仍在查询令牌对象,但这次我们只过滤比特币。我们的过滤器来自“ where :”子句,我们的结果是返回 name field = "Bitcoin "的所有匹配项出于某种原因,Uniswap 有多个令牌与名称“比特币”完全匹配,因此我们将只返回一个示例(使用 first :子句)。

注意我们的查询看起来有多简单和易读?

没有特定于语言的语法(比如 SELECT *或 FROM TABLE),就像我们使用 SQL 查询 REST API 时要编写的那样。

为什么?那是因为 GraphQL 是围绕 对象类型构建的,所以它读起来像 JSON 符号。您不是描述您想要访问的数据库表,而是描述数据本身的形状

不是描述您想要访问的数据库表,而是描述数据本身的形状

GraphQL 也是独一无二的,因为只有一个端点供我们访问。另一方面,REST APIs 是围绕资源组织的,这些资源通常位于单独的不同的URL 上。但是使用这种语言,您的数据是围绕单个实体图、 组织的,结果只有一个端点:

https://exampleapi/graphql

当我们调用端点时,我们选择我们感兴趣的对象类型(“用户”、“文章”、“令牌”等)。)然后我们描述我们想要包含的字段。

步骤 2:查看“数据库”模式

接下来,让我们看看图表的模式,这样我们就有了这个区块链探索者提供的所有数据的大图视图。但是请记住,我们这里不是在使用数据库模式。图为直接查询区块链上的数据,追踪比特币、以太坊等等!

左边是我们的模式。这里列出的每一项都被称为对象类型。我们很快就会更深入地了解 Pair 对象,但是让我们停下来欣赏一下我们可以访问多少数据。

加密货币从“钱包”中存储和发送,这是一种简单的软件应用程序。这些钱包与用户的姓和名、银行账号、地址等无关。但是如果我们想深入研究用户对象,我们仍然可以探索个人帐户余额、交易数量等等。

此外,我们可以查看 Uniswap 处理的每一笔代币交易(T30、T31),或者为流动性提供者创造的费用(T32、T33、T36、T32、T33、T36、T36、T33、T33)等等。

令人惊奇的是,所有这些数据都是公开的。如果你愿意,你可以建立一个由区块链分析提供支持的网站,仅仅使用这个网站

第三步:看“配对”对象

到目前为止,我们已经为 Token 对象编写了简单的查询,并且浏览了图中的整个沙盒 API(我们的模式)。

现在,让我们深入了解一下 Pair 对象,看看我们可以查询的所有字段:

没有任何交易对,加密货币交易所就不会存在。

任何给定的配对都由两个令牌组成:如果你和我交易加密,那么我可能会用我的以太来交换你的比特币。这意味着当我们查询 Pair 对象时,查询结果中的每个条目都将包括 Token0 和 Token1(例如,“ETH”和“BTC”)。

但是我们还需要每个代币的价格,以便我们知道公平交易的价值——这来自于代币 0 价格代币 1 价格字段。

图形的 API 得到的方式比那个更详细。继续我们的例子,我们可以检查已经为 ETH/BTC 对进行了多少交易 (txCount)

然后,我们可以看到迄今为止与流动性生产者(或"农民")共享的流动性代币总数(总供应量),Uniswap 上仍然可用的储备代币数量(reserve 0&reserve 1)(因为如果只有 4 个可用,我就买不到 5 个 BTC)…

…你明白了。

好了,现在我们已经大致了解了我们可以调查多少数据,我们为什么不看看我们的查询能做多少呢?

第四步:寻找交易最活跃的货币对

在 Uniswap 上交易的所有代币中,哪一对交易最活跃?哪两种加密令牌最受欢迎?

这就是我们的 API 变得真正强大的地方。

就像前面一样,我们的查询写在屏幕的左侧,查询结果显示在右侧。我们正在探索 Pairs 对象类型,我们正在过滤以查看一个列表,其中只包含前五个结果、,按整个交易所最高交易数排序

在右侧, token0 显示“包裹以太网”,而 token1 显示“系绳美元”。我们不会深究细节,但这些代币都是合成的、基于加密的金融工具,分别用于以太(以太坊网络的代币)和美元。

要点:

Uniswap 上的交易者交换乙醚和美元是任何对代币中最多的

这正是我们所期待的!为什么?

Uniswap 是围绕以太坊网络构建的。我们之前提到过这一点,但是你不能在以太坊网络上兑换美元或比特币,除非它被 【包装】 为基于以太坊的合成资产

因为以太是以太坊网络的燃料,而你必须拥有以太才能交易任何 ERC-20 代币,所以交易以太和美元是整个交易所最受欢迎的事情是完全有道理的。

为了结束我们的查询,这里是我们看到的字段的完整列表:

  • 名称:令牌名称(其他例子有“包裹比特币”、“戴”等。)
  • 交易量(美元):所有对的代币交易量(历史)
  • 总流动性:所有对之间作为流动性提供的代币总量
  • 代币价格:一个代币的价格,以另一个代币的货币表示
  • 交易计数:该对交易的所有时间金额
  • “创建于”时间戳:合同(对)的创建时间

不要忘记,如果我们认为我们的数据丢失了一些东西,或者如果我们看到了比我们需要的更多的信息,那么更新我们的查询就像从我们前面看到的模式中添加或删除任何字段一样简单。

步骤 5: GraphQL 与 SQL/REST 的比较

在结束本演练之前,让我们比较一下我们在简介中谈到的两种不同类型的查询。我们将继续第 4 步的示例查询,即“Uniswap 上最受欢迎的交易对”

左边是我们的 GraphQL 查询,右边是在 Oracle 数据库中使用 SQL 对相同数据的假设请求。通常我们会使用某个版本的 SQL 来搜索来自 REST API 或后端应用程序中的数据库的结果。

你会注意到的第一件事是,使用 SQL,无论何时你从两个或多个表中查询数据,你都需要以某种方式 连接 数据。由于 Pair 由两个标记组成,我们将标记和 Pair 表内部连接在一起。这样,我们的 ETH-TUSD 对将不会显示 Uniswap 上进行的每一笔 ETH 交易…只有 ETH 交换了 Tether。

但是,为什么我们不在 GraphQL 查询中进行任何“连接”呢?记住,我们正在查询一个整体的 图形对象每一条数据记录都在图表内的某处。因此,我们的查询语言让我们挑选我们想看的内容。使用 SQL/REST,我们不得不在数据库表之间建立连接。记住我们之前说过的:

您不是描述您想要访问的数据库表,而是描述数据本身的形状。

除了所有内部连接的复杂性之外,应该清楚哪种查询语言对人眼来说更具可读性和可理解性。由于我们在 GraphQL 中使用 JSON 符号,并且我们只写我们想要查看的字段的名称,所以我们的查询很简单,看起来像普通的英语。

结论

本演练的目的不是涵盖 GraphQL 能做的一切。那需要一整个系列!但是让我们记住,尽管它很强大,但有很多很好的理由不使用这种语言,因为它在某些方面肯定是有限的。

不管怎样,我希望这个例子是一个有用的介绍!你可以想象,如果我们运行这些数据,我们可以使用 GraphQL 的图形 API 为加密货币交易者构建一个非常强大的分析仪表板。我鼓励你自己去玩一玩,看看你能做些什么!

如果你还在了解区块链(说实话,谁不是呢?),我希望这篇文章有助于演示区块链如何像数据库一样工作。只是碰巧是公开的、分布式的……但是你可以像运行任何集中式&私有数据库一样运行搜索结果。

请在 Twitter 上关注我,了解更多编程/加密技巧,如果您有任何问题或想要一些建议,请联系我。感谢您的阅读!

图表 101:航空运输网络

原文:https://towardsdatascience.com/graphs-101-airline-transportation-network-5548739fd22e?source=collection_archive---------23-----------------------

真实世界数据集的实践概述

美国运输统计局(BTS)发布了大量与运输相关的数据。其中一个名为“ T-100 国内航段(美国航空公司)的数据集被描述为:

此表包含美国航空公司报告的国内直飞航段数据,包括承运人、始发地、目的地、飞机类型和运送乘客的服务等级、货运和邮件、可用容量、计划出发、已执行的出发、飞机小时数以及当始发地和目的地机场都位于美国及其领地边界内时的客座率。

这实际上是一个很大的 csv 文件,其中每一行对应一个单独的航班,包括航空公司、始发地和目的地机场、登机的乘客数量、日期和时间等。如果我们把机场作为节点,把航班作为边,那么我们就有了自己的网络!

飞行情报

当下载包含 2019 年所有航班的文件时,我们发现覆盖一年 365 天的 391,114 个独特航班。当我们合计在相同起点和目的地之间旅行的所有乘客时,我们发现我们减少到 27,302 行。按照乘客数量排序,我们发现 2019 年排名前五的航空公司是:

每人超过 160 万乘客!

这个缩减数据集的每一行现在都对应于一条单独的边。这种格式被称为“边列表”,是表示一个图的最常见的形式之一,只是一个边列表,每行一个。如果你曾经看过一个典型的网络科学教程或在线网络数据仓库这可能是你处理过的数据集的格式。

仅仅通过这个简单的例子,我们就可以引入更多的概念。我们没有任何起点和终点相同的边(谁会想不着陆就从起点飞回他们出发的机场呢?).这种边被称为“自循环”,在大多数分析中会被丢弃。为了以防万一,我们检查是否有这样的边,发现了超过 200 个自循环:

其中一些似乎归因于空中旅行(例如大峡谷和),而另一些则不那么明显。无论如何,我们将它们从边列表中删除,剩下 E=27,072 条边。

边也有明确定义的方向,即从起点到目的地,使其成为一个“有向网络”。如果我们考虑的不是航班,比如说州际高速公路,那么我们就会有一个“无向网络”(因为高速公路通常允许双向交通)。

我们的网络为每条边关联一个数值(飞行该路线的乘客数量)。这意味着我们定义的航空运输网络是一个“加权网络”。在一般情况下,边权重可以表示与边相关联的任何种类的数字属性,例如乘客数量、距离、最大流量等。

此外,当我们将所有航班的乘客数量相加时,我们在任何节点对之间都只有一条边。这意味着我们构建的这个网络是一个“简单图”(没有多条边,也没有自循环)。如果我们对区分不同航空公司的航班感兴趣,我们可以在同一对节点之间允许多条边(每家航空公司一条)。在这种情况下,我们将处理一个“多重图”。

机场信息

既然我们已经探索了网络的边缘,我们将注意力转向节点。我们通过组合起点和终点来提取图中的节点列表。我们发现我们有 N=1,318 个唯一节点。谁知道仅在美国就有这么多机场?

节点通常有一个与之相关联的 ID(在本例中是 IATA 代码)并且大量信息可以与所使用的特定 ID 相关联,例如位置、大小、颜色、重量等。就机场而言,我们可以从另一个 BTS 表中下载每个机场的额外信息,该表被古怪地命名为“主坐标”表,BTS 将其描述为:

该表包含航空数据库中使用的机场的历史(基于时间的)信息。它提供了国内和国外机场代码及其相关的世界区号、国家信息、州信息(如果适用)、城市名称、机场名称、城市市场信息以及经度和纬度信息的列表。

我们对每个机场的纬度经度坐标特别感兴趣,因为当我们试图可视化网络时,这将使我们的生活更容易。BTS 的好心人让我们的生活变得更轻松,他们为我们提供了纬度和经度列,以及一个标志,表明这些是否是最新的可用坐标:

谁知道机场会移动这么多?在我们过滤出最近的机场坐标后,我们发现有分布在世界各地的 6,572 个机场的信息。

因为我们的航班网络只包括美国境内的航班,所以我们通过组合用作始发地或目的地的机场集来提取航班数据集中包含的节点集。美国共有 1318 个机场。当我们从机场纬度/经度数据库中筛选出这些机场时,我们就可以最终将它们绘制在地图上了!

由于我们的网络嵌入在真实空间中,我们能够轻松获得每个节点的空间坐标。情况并不总是这样,在我们能够可视化网络之前,我们必须为每个节点计算足够的 X 和 Y 坐标。在网络术语中,这被称为“图布局,有一整个家族的算法致力于计算它们。我们将在以后的文章中讨论其中的一些。

正如我们所见,BTS 数据库非常完整,包括美国所有领土和岛屿上的机场。为了让我们的生活更容易,我们把自己限制在美国 48 个相邻的州。通过进一步的限制,我们只剩下 N=962 个节点和 E=22,691 条边。

我们现在不仅可以看到节点,还可以看到这个简化网络的边:

网络分析

随着我们的网络被完全定义,我们现在可以开始更深入地探索它。一个节点最基本的特征之一是它的度,k(T9):它所属的边的数量。在像我们这样的有向网络的情况下,我们区分输入和输出连接的数量,分别为输入/输出度。对于我们的网络,我们有:

我们注意到两个要点。首先。平均入度和出度是相同的。这总是正确的,并且是一个节点的输出边必须是另一个输入边的事实的直接结果。我们还可以使用以下表达式轻松计算总体平均度:

在我们的例子中,平均度数是 47.27,或者正好是平均进/出度数的两倍。基础数学还没有让我们失望!😃

其次,也许更令人惊讶的是,我们注意到有几个节点的入度或出度为 0。这意味着有些机场有航班起飞,但没有航班返回(反之亦然)!我们总共有 60 个这样的机场。在维基百科上快速查找机场代码发现,这些似乎是军事基地和其他通常不接待商业航班的机场。也许这些对应于紧急着陆?

我们还可以看到哪些机场的进出航班数量最多:

毫不奇怪,这些都是大型航空枢纽,如芝加哥奥黑尔、达拉斯沃斯堡或亚特兰大的哈兹菲尔德-杰克森。

从该表中,我们还可以看到,虽然接近,但传入和传出边的数量并不相同。当我们绘制 k_in 对 k_out 时,我们发现一些节点具有较高的 kin 值,而其他节点具有较高的 kout 值,这两者之间存在很强的相关性(尽管并不完美)。总体而言,皮尔逊相关系数为 0.986171。

总结网络连通性的更好方法是绘制度分布图,即 kin/kout 的每个值的相对频率:

我们注意到,程度分布相当广泛,跨越两个数量级。这种分布(对数-对数标度上的线性)是经验网络的典型,有时被称为“无标度”。我们将在以后的文章中对此进行更多的探讨。

你可以在我们的伙伴 GitHub 知识库中找到这篇文章中分析的所有代码,如果你喜欢这篇文章,你应该订阅数据科学子堆栈的图表!

数据科学巨著 2

原文:https://towardsdatascience.com/great-books-for-data-science-2-e722c0c19b43?source=collection_archive---------17-----------------------

11 本处理复杂性和数据的非技术性书籍

作者图片

第一篇文章中的许多书籍都是关于数据从业者的经历,以及人们和企业面临的数据问题的类型。对于第二套书来说,重点更多的是放在具体的工具和想法上,这些工具和想法可以在这个领域中使用。

读到一个想法或方法,并意识到它有直接的应用,这是令人兴奋的。也许在另一个领域有一个类似的概念,也许它是你解决你正在处理的问题所需要的工具,或者也许它只是你想了解更多的东西。在阅读这些书的时候,我发现这种情况经常发生,我希望你也会这样。

1.为什么之书

作者朱迪亚·珀尔

在统计研究和数据科学工作中,我们的重点通常是揭示特征和结果之间的相关性。相关性是有用的,因为它们可以在算法或映射中被捕获,以便根据新数据更快地做出决策。事实上,相关性是系统中某处因果关系的第一个迹象。《为什么》 这本书是对这些因果关系的研究——它们采取的形式,它们为什么相关,以及最重要的是,我们如何导航数据和混淆变量来证明因果关系的断言。

《为什么 这本书分享了简单、几乎直观的想法,感觉像是一个重大突破。当然,观察到的结果是有原因的,但通常我们认为这是理所当然的,并把注意力集中在简单的相关性上。在进行评估时,我们经常使用“相关性并不意味着因果关系”的论点来证明完全放弃因果关系的合理性。但是将系统分解成有向因果图比一堆模糊的相关性给我们提供了更多有用的信息。

本书中提出的因果分析的新方法易于理解,令人兴奋,可以为数据科学和分析打开许多新的大门。

2.黑暗数据

出自戴维·j·汉德之手

我们每天都面临着无法获得做出明智决策所需信息的情况。黑暗数据对模糊信息的不同原因进行分类——从没有发生的事件到偏见和启发。

黑暗数据中的第一个例子谈到了反疫苗接种运动的吸引力(该书在冠状病毒流行之前出版)。因为在接种疫苗的世界里,由病毒引起的死亡很少发生,所以人们没有足够的信息来做出是否接种疫苗的明智决定。我们没有的黑暗数据是由于高疫苗接种率而没有发生的死亡。

黑暗数据不仅仅是替代现实和缺失数据。这本书的一个主题是,作为数据科学家,我们可以通过识别和利用我们不知道或无法知道的信息来极大地改进我们的方法和模型。在一个数据缺失的世界里,能够利用黑暗数据*中的思想的数据科学家是不可或缺的。*

3.模范思想家

作者斯科特 e .佩奇

模型思考者背后的前提是,没有一个单一的模型可以适用于所有情况。如果你的工具箱里只有一把锤子,你永远也不会建造一个聚变反应堆。让数据科学家成为企业宝贵资产的是,他们能够识别哪套工具对处理给定问题有意义。通常,最好的方法需要几个模型协同工作。

如果我们从不学习可用的方法,当新的情况出现时,我们很可能会选择次优的工具。当处理真正复杂的问题时,你知道并能实现的方法越多,你的选择就越多,组合和修改的数量就越多。从头到尾阅读模型思考者是填补空白的好方法,(但是记得标记章节,这样当新的挑战出现时你可以回去参考它们)。

4.不可能

作者约翰·D·巴罗

不可能性展示了我们如何对科学发现采取相反的观点,新的见解不仅揭示了现实的机制,也揭示了局限性。物理科学不仅研究现实如何运作,也研究现实如何不运作。在这种背景下,不可能性*探索了混沌系统、科学发现和时间的含义。*

虽然这本书是哲学性的,但它确实对数据研究和一般科学有直接的影响。不可能性为追求知识打开了一个外部视角,可以产生科学家因专注于手头的问题而可能错过的洞察力。

5.规模

作者杰弗里·韦斯特

《规模》是一本信息量极其丰富的书,是圣达菲研究所复杂性理论研究的成果。它以对标度律的解释和它们在物理和生物系统中经常被忽视的作用开始,但是很快继续揭示复杂标度模式在每个其他领域中的作用。

到了本书的结尾,很明显比例定律是结构出现的关键,人类今天面临的许多问题都是由于缺乏对比例定律的理解。你不能真的责怪人性,因为这是一个新的研究领域,只有这本书成为主流。

没有人比数据科学家更适合利用等级中的洞察力。

6.系统思维

作者多内拉·h·梅多斯

看着世界上正在发生的各种各样的事情,并思考它们之间的相互关系是很困难的。在系统中思考是寻找以简单且可重复的方式捕捉系统动态的方法。这本书首先为捕捉动态系统的行为设计了一个框架,然后应用系统思维的基本工具来揭示发生在许多领域的基本模式。

一旦你对产生自我强化行为、混乱、成长和平衡的系统模式有了一些经验,你就可以在任何地方看到它们。系统思维向我们展示了同样的基本框架如何同样适用于物理学、生态系统、电路和全球经济。它不仅是工作中的强大工具,也是日常生活中的强大工具。

7.快速思考和慢速思考

作者丹尼尔·卡内曼

思考快与慢是将行为经济学推上地图的书。这是一本基于一个简单论点的强有力的书:个人和群体的复杂行为根植于快速的“系统 1”思维和慢速的“系统 2”思维的相互作用。

两件事让思考的快与慢在这个话题上脱颖而出。第一,文笔很脚踏实地,容易消化。虽然这本书很长,主题也很复杂,但每一部分都相对独立。第二,它充满了详细的实验程序,为作者的断言提供了可信度。

实验设计在大众科学中经常被忽视,所以看到它被谨慎地应用于广泛的行为研究是令人兴奋的。当阅读思考快与慢时,我们可以从实验和结果中学习。

8.统计智慧的七大支柱

斯蒂芬·h·斯蒂格勒

统计智慧的七大支柱将统计的历史和应用分为 7 个基本概念。不是用数学术语框定统计,每章提出在现代统计学的发展中一直是至关重要的一种基本方法。

第一章着重于聚合,这是一个我们认为理所当然的基本概念。聚合并不是一个需要记忆的复杂函数,它是一种可以用多种方式描述数据的思想。大多数章节以这种方式构建统计工具——与最先使用它们的人使用的术语相同。

统计智慧的七大支柱通过历史追溯数据科学方法的发展,并揭示个人发现背后的思维过程。我发现这是一种有用的方法,可以支持对这些方法的理解,也可以理解它们为什么存在。对于任何想要理解工具背后概念的发展的人来说,这是一本很棒的书。

9.预见信息

作者爱德华·塔夫特

在爱德华·塔夫特写的四本关于视觉化的书中,我发现对信息的视觉化是最吸引人和最有洞察力的。它不仅为最佳实践提供了解释,而且对历史上可视化的发展提供了相当全面的说明。

每一页本身就是一件艺术品,整本书设计得非常好。我绝对推荐至少参考一下爱德华·塔夫特写的其他关于这个话题的书,尤其是量化信息的可视化展示,更密集,更专注于技术从业者。展望信息是一本很好的读物,其中充满了历史和强大的工具,可以用来创建易于理解的数据表示。

10.日常用品的设计

唐·诺曼

日常用品的设计对我如何看待产品和设计产生了重大影响。我曾经相信,知道如何与事物互动是我的责任。当事情没有按照我预期的方式发展时,我很沮丧,因为我不明白。阅读这本书,你会发现好的设计应该为用户提供他们使用产品所需的所有信息。今天,如果我不能直观地理解如何操作某样东西,我会把它退回去,寻找一个更聪明的替代品。

同样的原则也适用于数据科学家和工程师如何为他们的项目设计报告和界面。如果商业用户不能直观地理解如何利用你展示的信息,那么你们都是在浪费时间。每个人都可以从理解设计原则中受益,但在数据科学中,这是一项没有得到足够重视的重要技能。

日常用品的设计通过案例研究和例子展示设计理念,让概念变得容易理解。它从心理学和学习的角度来设计,关注用户的期望和反馈如何融入设计,而不是产品的实用性和功能。这本书本身就是一个好设计的证明,因为叙述的流程和想法驱使你从头到尾地阅读。

11.形状

作者乔丹·艾伦伯格

数学通常是通过数字来进行概念教学的。形状不是关于数学应该如何被教授,但它确实为我们学习思考数学的方式提供了一种空间选择。

在《形状》中,乔丹·艾伦伯格讲述了数学中的不同主题,同时还讲述了数学作为一个领域的几何起源。使用巧妙的视觉和例子,许多看似复杂的概念被显示为简单的几何问题。在数据科学中,我们习惯于与数字打交道,然后试图将结果整理成一个整洁的可视化图形。形状提醒我们数学中许多主题的几何和视觉起源,以及我们学习用数字方法解决的事物通常具有整洁的空间表示,更容易消化。

这本书不仅仅是一套整洁的几何例子。它促进空间推理作为一个重要的工具,在每个领域都有应用。几何学不仅仅是数字和多边形,它是研究形状的

远大的期望:永远知道从你的数据中可以期待什么

原文:https://towardsdatascience.com/great-expectations-always-know-what-to-expect-from-your-data-51214866c24?source=collection_archive---------1-----------------------

入门

使用 Python 确保数据按预期工作

动机

假设你的公司正在训练一个机器学习模型,利用从用户那里收集的数据来预测用户是否会点击广告。2021 年 9 月,你训练的模型在 90%的情况下正确预测了一个用户是否点击了一个广告。万岁!

然而,在 2021 年 10 月,同一模型仅在 70%的情况下正确预测了用户是否点击了广告。发生了什么事?

作者图片

您怀疑模型性能的变化可能是由数据的变化引起的。因此,您决定比较 2021 年 9 月和 2021 年 10 月收集的数据的每日现场时间分布。

作者图片

你是对的!这两个数据在每天花费在现场的时间分布上有显著差异。

作者图片

由于每天花在网站上的时间是你的模型中最重要的特征之一,这种特征分布的变化会导致你的模型性能的下降。

除了每月手动检查数据的分布是否有变化之外,有没有一种方法可以在将数据输入模型之前自动检查分布的变化?

作者图片

这就是“远大前程”派上用场的时候。

什么是远大前程?

Great Expectations 是一个领先的 Python 库,允许您验证、记录和分析数据,以确保数据符合您的预期。

远大前程通过一个检查表来确保数据在使用前通过所有这些测试。

作者图片

有很多工具可以让你创建测试来验证你的数据。然而,我喜欢《远大前程》有几个原因:

  • 为你的数据自动创建一组测试:为你的数据创建一组全面的测试可能会很痛苦。Great Expectations 通过建议一些基于数据特征的测试来消除这种痛苦。

作者图片

  • 通过笔记本创建您的期望并配置您的数据源:对于一些人来说,使用 JSON 创建期望也是很困难的。《远大前程》让你用 Jupyter 笔记本轻松创造你的期望!
  • 创建良好的数据文档:巨大的期望创建干净的、人类可读的文档,使您能够快速理解您的数据和验证结果。

作者 GIF

  • 与 DAG 执行工具无缝集成:Great expectations 与 DAG 执行工具无缝集成,如 Airflow 、 dbt 、提督、 Dagster 、 Kedro 等。

在本文中,我将向您展示如何开始使用 Great Expectations,并回答您可能对这个工具有一些疑问。

要安装远大前程,请键入:

pip install great_expectations

入门指南

创建数据上下文

数据上下文管理您的项目配置。要使用 V3(批处理请求)API 创建新的数据上下文,请键入:

$ great_expectations --v3-api init

并且将在您的当前目录中创建具有以下结构的新目录!

作者图片

这些目录的功能:

  • 文件great_expectations.yml包含您的部署的主要配置。
  • 目录expections将您所有的期望存储为 JSON 文件。
  • 目录plugins保存了你可能有的任何定制插件的代码。
  • 目录uncommitted包含了不应该在版本控制中的文件。

远大前程工作流程

伟大的期望通常包括 3 个步骤:连接数据,创造期望,验证你的数据。

作者图片

在接下来的部分中,我们将了解每个步骤的样子。

连接到数据

作者图片

作为演示,我将从 Kaggle 下载的广告数据集拆分成两个数据集:first_data.csvsecond_data.csv。具体来说,

  • first_data.csv包含 2016 年 1 月至 2016 年 4 月的数据
  • second_data.csv包含 2016 年 5 月至 2016 年 7 月的数据

这些数据集存储在目录data下。

作者图片

要连接到我们的数据,请键入:

$ great_expectations --v3-api datasource new

在建立连接时,您会被问一些类似下面的问题。

作者图片

我们可以将巨大的期望与我们系统或 SQL 上的文件联系起来。在这里,我们选择:

  • 把它和我们系统上的文件连接起来
  • 用熊猫处理我们的文件
  • 指定data作为存储所有数据文件的目录。

回答完所有这些问题后,将会自动为您创建一个笔记本!此笔记本允许您配置新的数据源。Datasource 告诉了人们对您的数据存在于何处以及如何获取数据的极大期望。

GIF 作者—点击查看笔记本。

在这个笔记本中,您可以通过编辑变量datasource_name的值来指定数据源的名称。

这个代码块允许我们创建和定制数据源的配置。

在上面的配置中,InferredAssetFilesystemDataConnector将使用您提供的正则表达式在基本目录中搜索文件。

例如,由于文件first_data.csvsecond_data.csv都在data目录中,InferredAssetFilesystemDataConnector将检测这些文件并连接到它们。

Available data_asset_names (2 of 2):   
    first_data.csv (1 of 1): ['first_data.csv']   
    second_data.csv (1 of 1): ['second_data.csv']

执行完该笔记本中的所有单元格后,您的数据源的配置将被添加到great_expectations.yml中!

在这里找到配置你的数据源的其他方法。

创造你的第一个期望

作者图片

现在到了激动人心的部分:创造你的第一个期望!我们将从创建一个新的期望套件开始。期望套件是期望的集合。要创建新的期望套件,请键入:

$ great_expectations --v3-api suite new

作者图片

您可以使用样本批次数据手动或自动创建期望值。在这里,我想根据数据自动创建期望first_data.csv

完成所有问题后,将自动为您创建另一个笔记本。在这个笔记本中,您可以选择您关心的列和其他因素,并让分析人员为您写下一些候选期望。

作者 GIF

该笔记本的第一个单元格将加载数据源中指定的数据。这非常方便,因为您可以可视化并了解数据集的一些特征。

您还可以指定要忽略哪些列,这样高期望值就不会对这些列产生期望。

运行笔记本中的其余单元格后,将为您创建一个类似于下面的报告!

GIF by Author —点击此处查看文档

我们想要的期望可能比远大期望所创造的期望少一些或多一些。没关系!我们可以通过键入以下内容来编辑这些期望:

$ great_expectations --v3-api suite edit first_data.csv.warning

first_data.csv.warning是我们期望套件的名称。运行该命令后,将创建另一个笔记本,允许我们编辑我们的期望套件。

作者 GIF

在这个笔记本中,我们可以为整个表格和每一列创建期望。所有的期望都以.expect_开始,这使得自动完成很容易。让我们看看这些期望是怎样的。

表期望

在这里,我们可以指定与整个表相关的期望,比如期望表列按照一定的顺序排列。

列期望

您可以为不同的列创建期望。让我们从为专栏Daily Time Spent on Site创造期望开始。

在创建期望之前,您可能想要了解列Daily Time Spent on Site的分布。“远大前程”允许你像分析普通熊猫数据框架一样分析数据。

接下来,我们将基于列Daily Time Spent on Site的分布创建一些期望。

我们还希望该列不为空,并且是 float 类型。

我们还可以确保列City中唯一值的比例在 0.9 到 0.99 之间。

由于这些期望中有许多是自动创建的,所以我们不需要花费太多的精力来编辑函数以适应我们的期望。在此找到所有内置期望。

恭喜你!您刚刚创建了您的第一个期望套件。该套件将保存在下面目录下的文件warning.json中:

great_expectations/expectations
└── first_data
    └── csv
        └── warning.json

warning.json的前几行。

现在,您可以轻松地使用这个文件来编辑一些期望,而无需重新运行整个笔记本!

使用检查点验证您的数据

既然您已经创建了预期,那么您如何验证新数据呢?

这就是 Checkpoint 派上用场的时候。检查点将批量数据与相应的期望套件捆绑在一起进行验证。

作者图片

要创建第一个检查点,请键入:

$ great_expectations --v3-api checkpoint new first_checkpoint

并且将为您创建一个如下所示的笔记本!

GIF 作者—点击查看笔记本。

在此笔记本中,您可以配置您的检查点。具体来说,

  • datasource_name指定数据源
  • expectation_suite_name指定期望套件的名称
  • data_asset_name指定要验证的数据集

在取消注释并运行该笔记本的最后一个单元格之后,您将看到一个表格,显示您的验证是失败还是成功。幸运的是,数据second_data.csv通过了所有测试!

作者图片

要查看测试结果的详细信息,请单击运行时下的链接,您将看到如下所示的报告:

GIF 作者——点击查看完整报告。

您的新检查点现在保存在:

great_expectations/checkpoints
└── first_checkpoint.yml

将来,如果您想使用同一个期望套件来验证另一个数据,比如说third_data.csv,您可以将second_data.csv切换为third_data.csv:

您可以在您的终端中运行检查点,而不是回到笔记本并重新运行最后一个单元!

$ great_expectations --v3-api checkpoint run first_checkpoint

作者图片

很酷,不是吗?

一次验证两个不同的数据集

有时,您可能希望使用同一个 expect Suite 同时验证两个不同的数据集。这可以通过添加另一个batch_request来轻松实现:

让我们试着再跑一次,看看我们会得到什么。

作者图片

不错!

问与答(Question and Answer)

远大前程没有我想要的期望怎么办?

如果没有一个内置期望是您正在寻找的,您可以轻松地创建自定义期望。

使用 Jupyter 笔记本有什么好处?

使用 JSON 文件创建您的第一个期望可能很有挑战性。Jupyter 笔记本让您轻松编辑笔记本单元格中的预设期望。你也可以在写期望之前将你的数据可视化。

我需要一直使用 Jupyter 笔记本吗?

不,Jupyter Notebook 让初学者更容易建立期望,但是当你掌握它时,你可以在 JSON 文件中创建新的期望,在 YAML 文件中创建新的检查点。

如果你不喜欢这些方法中的任何一种,我推荐你查看一下的《远大前程》文档,了解其他创建期望和检查点的方法。

为什么《远大前程》有这么多定制?

这些定制允许用户轻松地将巨大的期望与他们现有的框架集成在一起。不要害怕这些定制。我建议您从基础开始,然后一次定制一段代码来满足您的目标。

结论

恭喜你!您刚刚学习了如何使用巨大的期望来创建测试并验证您的数据。通过确保您的新数据符合您的预期,您将有信心将这些数据用于下游流程。

随意发挥,并在这里叉这篇文章的源代码:

https://github.com/khuyentran1401/Data-science/tree/master/data_science_tools/great_expectations_example

我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以在 LinkedIn 和 Twitter 上与我联系。

如果你想查看我写的所有文章的代码,请点击这里。在 Medium 上关注我,了解我的最新数据科学文章,例如:

远大前程:数据测试工具——这是我们数据质量需求的答案吗?

原文:https://towardsdatascience.com/great-expectations-the-data-testing-tool-is-this-the-answer-to-our-data-quality-needs-f6d07e63f485?source=collection_archive---------5-----------------------

数据工程-数据质量-伟大的期望系列

我的评估远大前程的旅程,数据质量框架-第 1 部分

米卡·鲍梅斯特在 Unsplash 上的照片

我是一名数据工程师,目前在银行业工作。我在交付一个重要项目中发挥了重要作用,该项目侧重于风险评估,以保护机构及其客户免受金融犯罪的影响。编制准确、完整、一致、时间相关和标准化的定期风险报告尤为重要,以便进行正确的分析并降低固有风险。如果做不到这一点,不仅会给银行,也会给其利益相关者和个人客户带来严重后果。在数据管道中整合一个强大的数据质量流程是必须的,选择一个有效的工具来实现这一目的肯定会改变游戏规则。

远大前程 是一个帮助团队通过数据测试、文档和概要分析来消除管道债务的工具。我一直打算探索和评估这个工具,以确定它是否可以与我们现有的环境集成,以及它是否有可能改善我们当前流程中的明显约束,并在我们未来迁移数据平台时防止重大的重构工作。

我们目前的做法

为了交付下游指标进行分析,我们必须处理来自各种源系统的数以亿计的数据,这些数据经过不同的转换层。我们利用适用于大数据的存储和计算,如 AWS S3 和 AWS EMR ,使用 Jupyter 和 Pyspark 作为 ETL 工具,并将最终指标加载到 AWS 红移。

数据平台—作者图片

管道做五件主要的事情:准备依赖关系,确定执行的顺序,执行笔记,验证测试结果,最后,将最终的指标加载到数据仓库中。

数据管道—按作者分类的图像

每个笔记本创建一个单独的数据实体。为了运行一些质量检查,聚集的数据被查询并加载到 DataFrame 中,然后对其执行单元测试。测试结果被记录到 S3 中,并在测试验证阶段加载以评估覆盖率。

笔记本 ETL 脚本—作者图片

这个过程目前有效,但我认为还有一些事情可以做得更好。

警告

代码的重复

每个笔记本中都有单元测试代码。但是大多数笔记本都在运行完全相同的单元测试。这导致了代码的重复。

没有数据质量文档

如果有一个用户友好的静态网站在整个团队中共享就好了,它可以显示我们的数据在任何环境中到底发生了什么。在我们当前的设置中,当执行管道时,我们得到的只是控制台中输出的一长串测试结果。

即将迁移到雪花

我们期待着从红移和火花环境到雪花的大迁移,这意味着我们将不得不抛弃我们主要用 Pyspark 写的笔记本和单元测试当前驻留的地方,并可能切换到 DBT 来做我们的数据转换。我们必须找到一种方法对新的数据源进行测试。

当然,我们总是可以重构代码来生成一个可重用的测试模块,这个模块是解耦的,并且实现了依赖注入,所以即使数据源发生变化也没有关系。另一方面,文档的实现并不简单。如果有这样一个工具可以帮助克服当前的限制,并提供更多有益的功能,那就太好了。

数据质量工具:我在寻找什么?

  1. 单元测试或期望直接转化为文档
  2. 添加关于单元测试的额外信息
  3. 文档可以在 S3 托管
  4. 现成的通用数据质量测试功能
  5. 支持我们已经进行的大部分数据质量检查
  6. 支持多个 Pandas/Spark 数据框架和雪花数据源
  7. 可扩张的
  8. 与气流或 DBT 等编排工具集成

决策寄存器

单元测试或期望直接转化为文档

我们知道文档是多么强大和方便,但是没有人想维护单独的文档,只是为了确保它与最新的代码同步。我更喜欢从已定义的单元测试中生成文档的现成特性。

Great expectations: **Supported**; Score: **1/8**

添加关于单元测试的额外信息

我希望能够详细说明到底在测试什么,而不是泛泛的描述,以便让任何检查数据质量报告的人都能理解。

根据风格指南,推荐使用 google 风格的 docstrings。

Great expectations: **Supported**; Score: **2/8**

文档可以在 S3 托管

AWS S3 是托管静态网站的一个方便的位置,因为我们已经使用了 S3,不妨使用相同的部署共享文档。

默认情况下,文档存储在本地,但也可以部署在包括 S3 在内的云 blob 存储中。

Great expectations: **Supported**; Score: **3/8**

现成的通用数据质量测试功能

如果已经有了原生单元测试函数,我们可以利用它来避免从头开始编写动态测试,这将大大加快重构过程。

Great expectations: **Supported**; Score: **4/8**

支持我们已经进行的大部分数据质量检查

我已经搜索了可用的期望,它们可能至少在语义上匹配我们最常见的数据质量检查。

Great expectations: **Mostly supported**; Score: **5/8**

支持多个 Pandas/Spark 数据框架和雪花数据源

它应该可以在我们当前和未来的环境中工作,只需很少的重构工作。

支持的数据源: Pandas DataFrame 、 Spark DataFrame 和 Snowflake via SQLAlchemy

Great expectations: **Supported**; Score: **6/8**

可扩张的

尽管它支持我们开箱即用的大多数数据质量期望,但它应该足够灵活,能够为那些它本身不支持的测试编写定制测试。

Great expectations: **Supported**; Score: **7/8**

与气流或 DBT 等编排工具集成

它应该支持与我们数据生态系统中现有编排平台的集成。

验证可以通过 BashOperator 或 PythonOperator 经由气流运行。也有一个扩展包用于 DBT 。

Great expectations: **Supported**; Score: **8/8**

裁决

看起来《远大前程》在理论上看起来不错,但实际上能起作用吗?让我们来了解一下!在我的旅程中,请跟随我尝试这个工具并探索它的功能。请关注本博客系列的下一部续集。

  • py spark 中使用远大前程的数据质量单元测试

参考

  • https://docs.greatexpectations.io/docs/

绿色如爱尔兰:爱尔兰风能的 Choropleth 地图

原文:https://towardsdatascience.com/green-like-ireland-choropleth-map-of-irish-wind-energy-26603106fe3e?source=collection_archive---------25-----------------------

谈到可再生能源,爱尔兰有多大热情?

向基于可再生能源系统的中期过渡,爱尔兰普尔比都柏林(图片来源:Fatemeh Naderifar、Sara Pejhan 和 Saeed Misaghian)

简介

应对气候变化的巨大挑战需要彻底转变,为子孙后代创造一个清洁、安全和可持续的社会。爱尔兰的全岛电力系统在脱碳方面处于领先地位,为 2030 年设定了雄心勃勃的目标,你可以在这里阅读更多。爱尔兰共和国输电系统运营商 EirGrid ,负责向爱尔兰人民提供安全、可持续和绿色的电力,是实现电网去碳化的领跑者。让我们看看爱尔兰迄今为止在电力系统中容纳可再生能源方面有多成功。让我们快速看一下迄今为止的进展吧!

“让他们[人民]迎接可持续发展目标的挑战,并采取行动,不是出于私利,而是出于共同利益。我非常清楚时间的宝贵。抓住时机。立即行动。''

斯蒂芬·霍金,重大问题的简要回答

在详细介绍之前,我应该澄清一下,当我们谈论风力涡轮机或太阳能电池板等可再生能源时,我们可以谈论大型项目,这些项目需要被称为风力/太阳能农场的巨大土地,也可以谈论你可能在屋顶或花园中安装的较小设备。在这里,我们谈论的是大规模可再生能源发电机,它产生大量的电力。

准备数据

EirGrid 在其网站【1】上定期发布电力系统信息和技术报告。你还可以在 EirGrid 智能仪表盘上找到关于爱尔兰电力系统的有趣图表和数据,点击此链接【2】。我从 Eirgrid 的网站上获得了数据(从 PDF 文档和 Excel 文件中),并根据我的兴趣每年对它们进行修改,因为我想了解可再生能源发电在过去几年中取得了怎样的进步。

呈现数据

技术上和细节上我都不想说。我只是想给那些可能有兴趣了解电网中可再生能源进展的人一些启示。作为工程师,我们正在努力寻找解决方案,以适应网络中越来越多的可再生能源份额。看看下面这张 GIF,展示了爱尔兰如何在生产方面容纳更多的风力发电变得更加绿色;绿色越深,风力发电在爱尔兰电网中的份额就越高。平均而言,2014 年,爱尔兰总需求量的 19.89%由风力提供,到 2020 年底,这一比例将跃升至约 38%。

爱尔兰风电在电网中的渗透率,占总需求的%

现在我想向你展示爱尔兰大多数风力涡轮机的位置。看下面的 GIF,显示了从 2008 年到 2020 年的风机安装进度,每个圆圈代表一个风机。红圈代表每年新增的风力涡轮机,蓝圈代表前几年累积的风力涡轮机。此外,地图的绿色背景显示了每个地区风力涡轮机的装机容量,颜色越深,该地区的装机容量越大。

作为一名在爱尔兰的国际居民,我总是听说爱尔兰西部的大风天气。使用数据集后,我现在对爱尔兰多风的地方有了很好的认识。此外,我应该承认,我认为我们没有任何城市比都柏林风更大!

看看西边的克里县、科克县和戈尔韦县,它们有多绿!它们是爱尔兰顶级风力涡轮机的家园,正在帮助爱尔兰电网变得更加绿色!

2008 年至 2020 年期间风力涡轮机装机容量和数量

但这并不是故事的全部。有许多技术和财务障碍阻止系统运营商容纳越来越多的可再生能源,这就是为什么我们称之为一个雄心勃勃的目标,在我们的电力网络中拥有大量的可再生能源,如风力涡轮机。具体来说,当我们谈到像爱尔兰这样的电网时,由于其地理位置,与其他欧盟国家相比,它与邻国的联系更少,这当然需要付出更大的努力来应对未来的技术挑战。

一点技术性的谈话

对于那些可能有兴趣了解更多细节的人,我想谈谈术语 SNSP,即系统非同步穿透。简而言之,SNSP 实际上显示了与总电力需求相比,与转换器接口的发电机组(如 HVDC 互联器、电池、风能和太阳能电池板)的渗透水平,这是保护系统安全的一个代理。SNSP 限制的必要性是阻碍电力系统运营商接纳更多可再生能源的障碍之一,因为电力系统的安全性和可靠性受到非常高的威胁,而这始终是第一要务!SNSP 越高,系统对故障和断电的鲁棒性越差。爱尔兰最近达到了 2021 年 70%可变可再生电力瞬时目标,这确实是一个伟大的成就,这意味着该国可以通过可再生能源供应其 70%的电力需求!让我们来看看爱尔兰最近几年的 SNSP 比率。在下面的 GIF 中,我展示了每年的最大 SNSP。我们在这里选择最大值,因为它代表了系统的瞬时渗透率,以及 EirGrid 在管理系统安全性的同时拓展其边界以获得更多可再生能源的能力。今年的最大 SNSP 已经从 2014 年的 53.55%提高到 2020 年的 67.4%和 2021 年的 70%,这对爱尔兰来说是一个巨大的进步!

2014-2020 年间系统非同步渗透率

Python 代码

你可能会对绘制 choropleth 图感兴趣,因为它们不仅具有说明性,而且非常漂亮,这是可视化数据的两个主要基础。在我的下一篇文章中,我将一步一步地解释如何用 Python 制作 choropleth 地图。值得注意的是,我受到了这两篇关于走向数据科学的文章[3,4]的启发。

贡献者

希亚拉·奥德威博士通过对这项工作提出建议和意见,帮助准备了这篇简短的文章。

确认

我要感谢 UCD 能源研究所和 ESIPP 集团对我的支持。另外,我推荐你看看我的同事们在这个研究所的有趣作品。

免责声明

这项工作只是基于显示爱尔兰电网在可再生能源方面改善的公共在线数据,作者并不保证这项工作的结果。

参考文献

[3]:用 Python 创建 Choropleth 地图的完整指南,走向数据科学;2020 年 10 月 4 日https://towards data science . com/a-complete-guide-to-creating-choropleth-maps-in-python-728 ee 2949 db4

【4】我们来做个地图吧!利用 Geopandas、pandas 和 Matplotlib 制作 Choropleth 图;2018 年 6 月 25 日。https://towards data science . com/let-make-a-map-using-geo pandas-pandas-and-matplotlib-to-make-a-chlorolethmap-dddc 31 c 1983d

浓缩咖啡的研磨设置

原文:https://towardsdatascience.com/grind-settings-for-espresso-e92d07da05c8?source=collection_archive---------28-----------------------

咖啡数据科学

数据驱动指南

浓缩咖啡是迄今为止制作咖啡最丰富的方法,但也是最困难的方法。每一个镜头都有挑战,因为多个变量汇集在一起形成了一个美丽的东西。研磨设置、夯实压力、水温、压力、预注入、剂量、篮子、研磨机和机器都起作用。对于初学者来说,最具挑战性的障碍是能够理解他们应该根据其他镜头的运行方式做出什么调整。

我一直在看我为我的浓缩咖啡拍摄做失败分析的所有方法,我认为看几个变量会很有趣。在开始,我想分别看看这些变量,并展示我所看到的,希望它能帮助其他人更好地看到他们的投篮输出,并理解从那里去。

本文重点介绍 3 种研磨设置。对于每一个,我把地面放在一个篮子里,用牙签分发,并用自动校平机夯实。我把中心做得不那么密集,以对抗杠杆机器固有的噪音。我也用同样的篮子和同样的豆子拍了三张照片。

磨成篮子,分配,夯实。所有图片由作者提供

我使用了三种设置:8,10,12。

左栏:设置 8,中间:设置 10,右栏:设置 12

我为每个镜头都拍了视频。每一行都是 5 秒的时间。列设置为 8、10 和 12。

设置 8 ……。设置 10……设置 12

从图中可以看出,设置 12 拍跑得更快。我们可以观察一段时间内的流量:

在拍摄之后,我通常会对冰球的底部进行成像,设置 8 看起来在外侧有一个更暗更宽的环,这表明沟道效应更差。

设置 8,设置 10,设置 12

绩效指标

我使用两个指标来评估技术之间的差异:最终得分和咖啡萃取。

最终得分 是评分卡上 7 个指标(辛辣、浓郁、糖浆、甜味、酸味、苦味和回味)的平均值。当然,这些分数是主观的,但它们符合我的口味,帮助我提高了我的拍摄水平。分数有一些变化。我的目标是保持每个指标的一致性,但有时粒度很难确定。

品味和 EY

就性能而言,设置 10 和 12 在 TDS 和 EY 方面是相似的,但是基于味道,设置 10 大大优于其他 2 个。

在拍摄时间方面,我保持预输注恒定,但 TCF(覆盖过滤器的时间)在设置 12 时比其他两个快得多。正如预期的那样,研磨越粗,总时间越短。

制作好的浓缩咖啡的关键在于实验。尝试几个不同的变量,并试图了解如何进行调整,直到你得到天堂的味道。然后不断调整你所有的变量,直到你到达天堂的下一层。

如果你愿意,可以在 Twitter 和 YouTube 上关注我,我会在那里发布不同机器上的浓缩咖啡视频和浓缩咖啡相关的东西。你也可以在 LinkedIn 上找到我。也可以关注我中。

我的进一步阅读:

浓缩咖啡系列文章

工作和学校故事集

个人故事和关注点

乐高故事启动页面

摄影启动页面

使用图像处理测量咖啡研磨颗粒分布

改善浓缩咖啡

断奏生活方式概述

测量咖啡研磨分布

咖啡萃取

咖啡烘焙

咖啡豆

浓缩咖啡用纸质过滤器

浓缩咖啡篮及相关主题

意式咖啡观点

透明 Portafilter 实验

杠杆机维护

咖啡评论和想法

咖啡实验

使用研磨 TDS 的浓缩咖啡圆盘的提取潜力

原文:https://towardsdatascience.com/grounds-tds-across-the-espresso-puck-1581825ddcac?source=collection_archive---------26-----------------------

咖啡数据科学

探索一个用过的咖啡球

之前,我讨论过通过将咖啡渣(新鲜的或用过的)放入含有少量水的折光仪来测量 gTDS 或渣 TDS 。为了进一步探索这个想法,我想在一个有问题的圆盘上进行空间测量。我想了解 GTD 中的黑点是如何测量的。

我拍了一个断续夯实的照片,我能够在顶部和底部分开冰球,因为我在两层之间有一个布过滤器。所以我有了一个有趣的方法来检查冰球上的 GTD。高 gTDS 意味着该区域在拍摄过程中没有被完全提取。圆盘上的不平整表明发生了沟道效应。

按作者分类的所有图像

我用一个橡胶小冰块托盘来帮助分割用过的冰球。

我用一把锋利的刀沿着网格线切割圆盘。

然后我横向切割。

然后我仔细检查并测量了每个样本的 GTD。这一过程需要一些时间,但通常样品测量比 TDS 测量更快。

我把尺寸放在这个格子里,我添加了一些颜色规则。上半部分和下半部分的颜色标准化是不同的。

让我感兴趣的是,在第 4 行第 5 列的顶部和底部有一个点,那里有一个高 gTDS。这意味着该区域的流动缓慢(顶部为 3.91%,底部为 4.28%)。

我将这些信息叠加到圆盘上,这样您就可以比较圆盘的颜色和 gTDS 值。和黑点不太吻合。事实上,对于上半部分,很难在整个圆盘上分辨出任何颜色差异。

我们可以看到 gTDS 顶部和底部的不同,这可以让我们了解当水通过圆盘时流量是如何变化的。

以更高的分辨率估算 gTDS

通过这些初始测量,我很好奇它们在获得整个图像的更高分辨率测量时会有多精确。首先,我计算了每个网格点的平均颜色值:

然后,我绘制了每个细胞的 gTDS 与强度(红色、蓝色和绿色的平均值)的关系。

顶部没有很好的趋势线 R,但底部有,所以我用了上下像素界限。然后,我根据圆盘底部的图像创建了一个估计的 gTDS 图像。

然后我形成了基于原始网格的估计 gTDS 来查看误差。

这是一个很大的偏差,可能是因为在 gTDS 较高的地方没有足够的样本。

我真的很喜欢用像 gTDS 这样的定量工具来看冰球后分析。通常,浓缩咖啡让人感觉如此神秘。很难看到冰球的内部,通常我们的理解来自于击球后的视觉证据或度量。我希望像 gTDS 这样的东西可以帮助检查视觉上没有这个不同的冰球,但这个例子通过数据告诉我们,外表可能具有欺骗性。

如果你愿意,可以在 Twitter 和 YouTube 上关注我,我会在那里发布不同机器上的浓缩咖啡视频和浓缩咖啡相关的东西。你也可以在 LinkedIn 上找到我。也可以关注我中。

我的进一步阅读:

浓缩咖啡系列文章

工作和学校故事集

个人故事和关注点

乐高故事启动页面

摄影启动页面

改进浓缩咖啡

断奏生活方式概述

测量咖啡磨粒分布

咖啡萃取

咖啡烘焙

咖啡豆

浓缩咖啡用纸质过滤器

浓缩咖啡篮及相关主题

意式咖啡观点

透明 Portafilter 实验

杠杆机维护

咖啡评论与思考

咖啡实验

熊猫、SQL 和 NoSQL 中的分组依据

原文:https://towardsdatascience.com/group-by-in-pandas-sql-and-nosql-db60ce730437?source=collection_archive---------25-----------------------

数据分析中普遍存在的操作

马库斯·斯皮斯克在 Unsplash 上的照片

group by 操作通常用于探索性数据分析。几乎每个数据分析工具和框架都提供了 group by 操作的实现。

group by 操作包括根据离散或分类变量的值对数值进行分组,然后应用某种形式的转换或聚合。

例如,查找一个城市不同社区的平均房价是一个分组操作。价格根据邻近区域进行分组,并应用均值函数。

下图说明了典型的 group by 操作是如何执行的。

按操作分组(图片按作者)

在本文中,我们将看到如何在 Pandas、SQL 和 MongoDB (NoSQL 数据库)中完成 group by 操作。每个工具都有一个单独的部分,我们将在每个部分中做相同的示例。

熊猫

Pandas 是一个非常流行的 Python 数据分析和操作库。groupby 操作是使用“group by”函数完成的。

数据集存储在名为 marketing 的数据框架中。

(图片由作者提供)

我们先来算一下每个年龄段的平均消费金额。我们选择要聚合的列和要用于分组的列。分组列被传递给 groupby 函数。然后,我们应用期望的集合函数,在这种情况下是均值函数。

marketing[['Age','AmountSpent']].groupby('Age').mean() AmountSpent                 
Age     
---------------------                         
Middle    1501.690945                 
Old       1432.126829                 
Young      558.623693

平均而言,中年顾客往往花费最多。

我们可以按多列分组。group by 函数接受列表中的多列。让我们也在组中添加性别列,使前面的例子更加详细。

marketing[['Age','Gender','AmountSpent']]\
.groupby(['Age','Gender']).mean() AmountSpent                 
Age          Gender
-------------------------------------                             
Middle       Female       1301.339806                 
               Male       1638.354305                 
Old          Female       1279.310078                 
               Male       1691.513158                 
Young        Female        501.257310                 
               Male        643.189655

似乎在所有年龄组中,男性的花费都比女性多。

我们已经看到了用于分组的多个列。另一种常见的情况是聚合多个列。例如,我们可以计算“自己的家”列中类别的平均工资和总支出金额。

完成这项任务有多种方法。最简单的一个如下:

marketing[['OwnHome','Salary','AmountSpent']]\
.groupby('OwnHome').agg({'Salary':'mean', 'AmountSpent':'sum'}) Salary     AmountSpent                 
OwnHome 
---------------------------------------                                   
Own        69758.720930          796258                 
Rent       41546.280992          420512

我们向 agg 函数传递一个字典,指示应用于每一列的聚合。但是,我们不能从结果中判断出哪个聚合函数应用于列,因为它只显示列名。

解决这个问题的一个方法是使用 NamedAgg 方法。

marketing[['OwnHome','Salary','AmountSpent']]\
.groupby('OwnHome').agg( avgSalary = pd.NamedAgg('Salary','mean'),
     totalSpent = pd.NamedAgg('AmountSpent','sum')
) avgSalary     totalSpent                 
OwnHome 
---------------------------------------                                   
Own        69758.720930          796258                 
Rent       41546.280992          420512

结构化查询语言

SQL 是一种用于管理关系数据库中的数据的编程语言。它允许以高效和通用的方式过滤、转换和分析存储在数据库中的数据。

有许多关系数据库管理系统使用 SQL。尽管它们之间的大多数 SQL 语法是相同的,但可能会有一些小的差异。我将使用 MySQL。

数据集存储在名为 marketing 的表中。

(图片由作者提供)

第一个示例包括在 age 列中查找类别的平均花费金额。我们将 select 语句与 group by 子句一起使用。首先选择列。选择列时指定了聚合函数。然后,我们将 group by 与 age 列一起使用。

mysql> select Age, avg(AmountSpent)
    -> from marketing
    -> group by Age;+--------+------------------+
| Age    | avg(AmountSpent) |
+--------+------------------+
| Middle |        1501.6909 |
| Old    |        1432.1268 |
| Young  |         558.6237 |
+--------+------------------+

在第二个示例中,我们添加了另一个用于分组的列。对于 SQL,我们向 group by 子句添加多个列,用逗号分隔。

mysql> select Age, Gender, avg(AmountSpent)
    -> from marketing
    -> group by Age, Gender;+--------+--------+------------------+
| Age    | Gender | avg(AmountSpent) |
+--------+--------+------------------+
| Middle | Female |        1301.3398 |
| Middle | Male   |        1638.3543 |
| Old    | Female |        1279.3101 |
| Old    | Male   |        1691.5132 |
| Young  | Female |         501.2573 |
| Young  | Male   |         643.1897 |
+--------+--------+------------------+

第三个示例包括多个聚合。我们计算“自己的家”列中类别的平均工资和总支出金额。

mysql> select OwnHome, avg(Salary) as avgSalary,
    -> sum(AmountSpent) as totalSpent
    -> from marketing
    -> group by OwnHome;+---------+------------+------------+
| OwnHome | avgSalary  | totalSpent |
+---------+------------+------------+
| Own     | 69758.7209 |     796258 |
| Rent    | 41546.2810 |     420512 |
+---------+------------+------------+

对于 Pandas,我们使用了 NamedAgg 方法来重命名聚合列。对于 SQL,我们可以使用“as”关键字来更改名称。

NoSQL 数据库

NoSQL 指的是非 SQL 或非关系数据库设计。NoSQL 也提供了一种有组织的方式来存储数据,但不是以表格的形式。

数据科学生态系统中使用了几个 NoSQL 数据库。在本文中,我们将使用 MongoDB,它将数据存储为文档。MongoDB 中的文档由字段-值对组成。文档被组织在一个称为“集合”的结构中。打个比方,我们可以把文档想象成表格中的行,把集合想象成表格。

数据集存储在一个名为 marketing 的集合中。这是 marketing 集合中的一个文档,它表示一个观察(即表中的一行)。

> db.marketing.find().limit(1).pretty()
{
 "_id" : ObjectId("6014dc988c628fa57a508088"),
 "Age" : "Middle",
 "Gender" : "Male",
 "OwnHome" : "Rent",
 "Married" : "Single",
 "Location" : "Close",
 "Salary" : 63600,
 "Children" : 0,
 "History" : "High",
 "Catalogs" : 6,
 "AmountSpent" : 1318
}

数据库指的是当前数据库。我们需要在点号后指定集合名称。

MongoDB 为过滤、转换、过滤等数据分析操作提供了聚合管道。对于 group by 操作,我们在聚合管道中使用“$group”阶段。

第一个例子是计算每个年龄组的平均消费金额。

> db.marketing.aggregate([
... { $group: { _id: "$Age", avgSpent: { $avg: "$AmountSpent" }}}
... ]){ "_id" : "Old", "avgSpent" : 1432.1268292682928 }
{ "_id" : "Middle", "avgSpent" : 1501.6909448818897 }
{ "_id" : "Young", "avgSpent" : 558.6236933797909 }

用于分组的字段(即表中的列)通过关键字“_id”传递到分组阶段。我们为每个包含要聚合的字段和聚合函数的聚合指定一个名称。

下一个示例包含两个用于分组的字段。我们用关键字“_id”指定这两个字段,如下所示:

> db.marketing.aggregate([
... {
...   $group:
...    {
...      _id: {OwnHome: "$OwnHome", Gender: "$Gender"},
...      avgSpent: { $avg: "$AmountSpent" }
...    }
... }
... ]).pretty(){
 "_id" : {
  "ownhome" : "Rent",
  "gender" : "Male"
 },
 "avg_spent" : 996.1238532110092
}{
 "_id" : {
  "ownhome" : "Own",
  "gender" : "Male"
 },
 "avg_spent" : 1742.0036231884058
}{
 "_id" : {
  "ownhome" : "Own",
  "gender" : "Female"
 },
 "avg_spent" : 1314.4375
}{
 "_id" : {
  "ownhome" : "Rent",
  "gender" : "Female"
 },
 "avg_spent" : 764.5
}

最后一个示例包含两个要聚合的字段。我们在小组阶段分别指定如下。

> db.marketing.aggregate([
... { 
...   $group:
...     {
...       _id: "$OwnHome",
...       avgSalary: { $avg: "$Salary" },
...       totalSpent: { $sum: "$AmountSpent" }
...     }
... }
... ]){ "_id" : "Own", "avgSalary" : 69758.72093023256, "totalSpent" : 796258 }
{ "_id" : "Rent", "avgSalary" : 41546.28099173554, "totalSpent" : 420512 }

结论

我们已经做了三个例子来演示如何在 Pandas、SQL 和 MongoDB 中进行分组。本文的目标是介绍 group by 操作背后的思想,并涵盖每个工具的基本语法。

对于每个工具,我们可以执行更复杂的分组操作。例如,可以基于聚合列对结果进行排序。所有的工具都提供了一种很好的方式来按照操作对组的结果进行排序。

感谢您的阅读。如果您有任何反馈,请告诉我。

使用 Python 而不是 SQL 进行分组

原文:https://towardsdatascience.com/group-by-in-python-not-sql-dfdc31db77b4?source=collection_archive---------39-----------------------

意见

数据科学家如何整合他们的数据

Jefferson Santos 在Unsplash【1】上拍摄的照片。

目录

  1. 介绍
  2. SQL vs Python
  3. Python 数据帧创建
  4. Python 分组依据
  5. 摘要
  6. 参考

介绍

数据科学家通常在学习 SQL 之前先学习 Python,因此 SQL 要么让人不知所措,要么只是一种不受欢迎的不同体验。当 SQL 和 Python 中有相似的函数时,了解哪种方法最适合使用是很重要的。最终,这将取决于您的偏好,而且,如果您是 Python 鉴赏家,使用 Python 对您的数据进行分组或聚合可能会更有好处。为了知道为什么 Python 比 SQL 更好用,我们将首先研究如何在 SQL 中对数据进行分组。然后,我们将探索如何创建一个示例数据集,以便您可以遵循本 Python 教程。最后,也是最重要的,我们将讨论如何在 Python 中分组或聚合数据,这将在 Jupyter 笔记本中举例说明。如果你想知道为什么以及如何在 Python 中分组,请继续阅读。

SQL vs Python

照片由卡斯帕·卡米尔·鲁宾在Unsplash【2】上拍摄。

我的首选当然是 Python,但是 SQL 仍然有用,而且执行分组非常简单。然而,当查询变长,分组列的数量增加,并且很难看到分组的确切依据时,SQL 可能会更令人头疼。

**-- 1 = name of a numeric column
-- 2 = name of another numeric column****SELECT** Day, Ocean, *AVG*(1), AVG(2)
**FROM** df_example
**GROUP BY Day**, **Ocean**

当您想使用 SQL 而不是 Python 时

  • 当您有针对数据科学模型的定型查询,并且不想在查询后对数据进行特殊预处理时
  • 当您有一个整体较小的查询时
  • 如果您喜欢 SQL 格式

当您想在 SQL 上使用 Python 时

  • 当您已经有了来自非 SQL 查询的数据集时
  • 当您想更清楚地了解分类列如何对数字数据进行分组时
  • 如果您喜欢 Python 格式

Python 数据帧创建

示例数据帧。作者截图[3]。

首先,我们将使用 Python、pandas 和 numpy 在 Jupyter 笔记本中创建一个数据帧。我将包括 2 个代码块,它们解释相同的代码,但是,第一个代码块更容易复制,第二个代码块版本更容易直观地看到 Python 代码及其各自的格式。请记住,这只是随机创建的数据,有两个类别列简单地显示示例string值,以及随机生成的数值列的数值( 1 和 2 )。

首先,我们将导入必要的库。接下来,我们创建具有从 1 到 100 的随机整数值的数字列。然后,我们将创建分组依据的分类列,它们是列OceanDay。这些将有一组类别(例如: *Atlantic* *Monday*),我们将通过以下的mean对数值进行分组:

# import libraries
import pandas as pd
import numpy as np# creating numeric data for columns "1" and "2"df_example = pd.DataFrame(np.random.randint(0,100,size=(100, 2)), columns=list('12;))# creating your categorical columns that will be grouping byoceans = ['Pacific','Atlantic'] 
days = ['Monday', 'Tuesday', 'Wednesday']
df_example['Ocean'] = np.random.choice(list(oceans), len(df_example))
df_example[‘Day’] = np.random.choice(list(days), len(df_example))# displaying your data
df_example.head()

Python 分组依据

重置最终分组数据帧的索引之前和之后。作者截图[4]。

用 Python 聚集你的熊猫数据框架可能会涉及更多的代码,但是,我相信它比 SQL 提供了更多的可见性。它还可以为向同一组代码添加不同的聚合值提供更多的空间。例如,您可以将min作为聚合函数,而不是使用meanAVG

首先,我们将隔离我们想要使用的列,然后我们将选择我们想要应用的聚合类型。接下来,我们将重命名这些列,以便知道我们是根据什么对它们进行分组的。在上面左边的截图中,我们看到了DayOcean列及其各自的数字平均值。在右边的截图中,我们可以看到重设索引后最终的熊猫数据帧是什么样子。这个 dataframe 版本可以用于您为您公司的数据科学模型选择的任何机器学习算法。或者,这些数据可以简单地用于数据分析和洞察。

# what columns you want to group by
cols = ['Day', 'Ocean']# picking the aggregation type ex: 'mean'
group = df_example.groupby(cols).agg({
 '1': ['mean'],
 '2: ['mean']})# rename the column names with their respective aggregation type
group.columns = ["_".join(x) for x in group.columns.ravel()]# look at the groupings
group.head()# see how it looks on the original dataframe level 
grouped_df = group.reset_index()
grouped_df.head()

摘要

SQL 与 Python 函数可以用多种方式量化,比如速度和成本。然而,有时偏好可以赢得使用哪一个和何时使用的战斗。我们展示了如何首先在 SQL 中对数据进行分组,然后在 Python 中进行分组。该数据是随机/示例数据,因此您可以将该代码重新应用于您的特定数据及其各自的分类和数值字段。无论是 SQL 还是 Python,这种分组或聚合代码对于数据的探索性数据分析(如构建洞察力)或创建最终将在数据科学模型中获取的数据集都非常有用。

总而言之,在考虑 Python 优于 SQL 时,我们考虑了以下几点:

*** SQL vs Python** - benefits of one over the other*** Python Dataframe Creation** - for tutorial purposes*** Python Group By** - code to aggregate your pandas dataframe

由于本文展示了如何主要基于偏好执行 Python 聚合,为什么 you 想要使用 SQL 呢?我们还可以在 SQL 和 Python 代码之间做什么比较?你更喜欢哪一个?我希望你觉得这篇文章既有趣又有用。感谢您的阅读!作者代码。

请随时查看我的 个人资料——马特·普日比拉、等文章,也可以在 LinkedIn 上联系我。

参考

1照片由 Jefferson Santos 在Unsplash(2017)拍摄

2照片由 Caspar Camille Rubin 在 Unsplash 上拍摄,(2017)

[3] M.Przybyla,示例数据帧截图,(2021 年)

[4] M.Przybyla,在重置您的最终分组数据帧截图的索引之前和之后,(2021)

Pandas 和 SQL 中的日期分组

原文:https://towardsdatascience.com/grouping-dates-in-pandas-and-sql-5d067ab52b99?source=collection_archive---------21-----------------------

如何使用 Python 和 SQL 对数据进行分组

来源:图片由tiger ly 713发自 Pixabay

使用数据集时,经常会出现数据格式不适合进行适当分析的情况。

例如,如果我们希望进行时间序列预测,但在同一时间段内存在许多数据点,该怎么办?

在本例中,我们将使用 Antonio、Almeida 和 Nunes 的酒店预订需求数据集 (2019)来探索如何使用 Python 的 pandas 和 PostgreSQL 将各个数据点分组到一个时间序列中。

熊猫

在这个特定的数据集中,每个预订酒店的客户都有单独的条目,提供了到达的年份和星期:

来源:Jupyter 笔记本输出

此外,当滚动到数据集的右侧时,我们会看到平均日费率(ADR)或客户每天支付的平均费率也显示出来:

来源:Jupyter 笔记本输出

考虑一下这个场景。假设我们希望获得所有客户每周的平均 ADR。我们将如何在熊猫身上实现这一目标?

我们要做的第一件事是连接到达的年份和星期的值。

>>> df1 = df['ArrivalDateYear'].map(str) + df['ArrivalDateWeekNumber'].map(str)>>> print (df1)>>> df1=pd.DataFrame(df1)0        201527
1        201527
2        201527
3        201527
4        201527
          ...  
40055    201735
40056    201735
40057    201735
40058    201735
40059    201735
Length: 40060, dtype: object

ADR 值数组存储在单独的数据帧中:

df2 = DataFrame(c, columns= ['ADR']) 
df2

来源:Jupyter 笔记本输出

这两个数据帧又可以连接成一个新的数据帧:

df3=pd.concat([df1, df2], axis = 1)
df3
df3.columns = ['FullDate', 'ADR']
df3.sort_values(['FullDate','ADR'], ascending=True)

来源:Jupyter 笔记本输出

现在, groupby 可用于计算 FullDate 变量的所有相同条目的平均值;即具有相同年数和周数的那些。

df4 = df3.groupby('FullDate').agg("mean")
df4
df4.sort_values(['FullDate'], ascending=True)

来源:Jupyter 笔记本输出

我们现在有了一个可以用于预测目的的每周时间序列!

一种数据库系统

现在,假设我们想使用 PostgreSQL 完成同样的事情。我们将如何着手实现这一目标?

为此,我们将首先在 PostgreSQL 中创建一个表,然后从 CSV 文件中导入相关变量(只有相关变量保存在 CSV 文件中)。

注意,在下面的代码中,ADR 最初被指定为一个 decimal(4,2) 数据类型。但是,发现某些值需要比 decimal(4,2)更大的存储空间。

因此,使用如下 ALTER TABLE 将数据类型修改为 decimal(6,2)

hotel=# create table h1 (
hotel(# IsCanceled int,
hotel(# ArrivalDateYear int,
hotel(# ArrivalDateMonth varchar(10),
hotel(# ArrivalDateWeekNumber int,
hotel(# ADR decimal(4,2));
CREATE TABLEhotel=# alter table h1 alter column ADR type decimal(6,2);
ALTER TABLE
hotel=# copy h1 (IsCanceled, ArrivalDateYear, ArrivalDateMonth, ArrivalDateWeekNumber, ADR)
hotel-# from 'H1.csv'
hotel-# DELIMITER ','
hotel-# CSV HEADER;
COPY 40060

与 Python 不同,不需要将年份和周数连接起来。相反,我们可以简单地按年份分组并按周数排序,如下所示:

select arrivaldateweeknumber, avg(adr) from h1 where arrivaldateyear='2015' group by arrivaldateweeknumber order by arrivaldateweeknumber limit 5;

来源:PostgreSQL 输出

假设我们现在希望按 2016 年的所有周分组。我们可以这样做:

select arrivaldateweeknumber, avg(adr) from h1 where arrivaldateyear='2016' group by arrivaldateweeknumber order by arrivaldateweeknumber limit 5;

来源:PostgreSQL 输出

现在,我们已经用和在 pandas 中一样的方式在 SQL 中形成了时间序列。在现实世界中,人们可以选择使用熊猫来操纵数据。但是,如果从 SQL 数据库导入,这将需要从表中提取过多的数据。

在这种情况下,可以使用 SQL 简单地执行原始数据格式化,然后使用 SQLAlchemy 之类的库进行导入,以便在 Python 中进行进一步的分析。

结论

在本文中,您已经看到:

  • 如何使用熊猫连接
  • 如何将 CSV 数据集导入 PostgreSQL
  • 在 PostgreSQL 中使用 GROUP BY 和 ORDER BY 来形成时间序列

非常感谢您的宝贵时间,非常感谢您的任何问题或反馈。

免责声明:本文是在“原样”的基础上编写的,没有任何担保。它旨在提供数据科学概念的概述,不应被解释为专业建议。本文中的发现和解释是作者的发现和解释,不被本文中提到的任何第三方认可或隶属于任何第三方。作者与本文提及的任何第三方无任何关系。

Grover 算法:数据库搜索的银弹

原文:https://towardsdatascience.com/grovers-algorithm-a-silver-bullet-for-database-search-e30bec4d227?source=collection_archive---------24-----------------------

一种量子算法,对非结构化数据库搜索非常有效

由 Unsplash 上的克里斯托佛罗拉拍摄的照片

还记得旧的电话号码簿吗?

如果有人问你 XYZ 先生的电话号码。

你将直接进入索引页,搜索姓名以 X 开头的页码,然后按升序搜索 XY,再搜索 XYZ。

没那么糟吧。

但是,如果有人给你电话号码,并要求从同一个电话号码簿中查找那个人的名字,那该怎么办呢?

照片由亚历山大·克里维茨基在 Unsplash 上拍摄

你的第一反应会是 OMG(天啊)。

这是一个艰难的选择。

有点像大海捞针。

在非结构化数据库中搜索非常相似。

将上面的表格视为 N 个条目的数字干草堆。

你在寻找那个绿色的条目。

经典算法在最坏的情况下(假设绿条在末尾),将花费 O(N)次来搜索该绿条,如果它尝试随机搜索,则可能花费 O(N/2)次来搜索该条目。

这是一个巨大的数字大海。

科迪·多尔蒂在 Unsplash 上拍摄的照片

如果我告诉你有一种量子算法,可以让你的速度提高一倍。

是的,有一种叫做格罗弗搜索算法的算法可以在 O(N^.5).进行搜索

因此,如果任何经典算法需要 100 万次来搜索一个特定的结果,格罗弗的算法只需要 1000 次。

萨夫在 Unsplash 上拍摄的照片

似乎印象深刻,对吧!

但是格罗弗的搜索算法是什么呢?

这个算法是根据创作者 Lov Kumar Grover 命名的。

简单来说,该算法包括两个步骤:

  1. 相转化
  2. 均值反演

并且这些步骤应该在迭代中执行。一次迭代由这两个步骤组成。

但是这是如何工作的呢?

最初考虑将所有数据项叠加到量子电路中。它们都有相同的振幅。

现在,oracle 或函数知道我们的搜索结果是那个黄色条目。

所以现在就出现了基于格罗弗算法的电路的作用。

第一步是相位反转,即在轴上反转特定输入的幅度。

先别庆祝:)

然后下一步是平均反转,有时称为振幅放大。数学上,每个条目(或上图中的条形)可以表示为:

平均值+(平均值-振幅)

它是所有条目的平均值的两倍减去每个条目的幅度。

所以我们寻找的入口的振幅被放大了。

这是一次迭代,即:

相位反转+平均反转

像这样,需要执行多次迭代。直到我们的搜索结果的幅度达到 1 除以 2 的平方根。

概率是振幅的平方,也就是 1/2。

现在是庆祝的时候了。

伊恩·斯托弗在 Unsplash 上拍摄的照片

是的,最终我们得到了预期的搜索结果。

Grover 的算法是解决 NP 完全问题的福音,在这里我们可以找到一个模式。

什么模式?

假设有一个函数 f:{0,1,2,…n-1} → {0,1}

其中 f(x) = 1,求 x。

这个 x 可能是一个非常复杂的模式,比方说一个非常非常复杂的布尔模式。

照片由迭戈 PH 在 Unsplash 拍摄

在这种情况下,格罗弗的算法可以发挥神奇的作用。

最后的想法

Grover 算法的应用在于约束满足问题,例如八皇后难题、数独、类型推理、数字矩阵和其他逻辑问题陈述。

格罗弗的算法被认为是量子计算的一大成就,并吸引公司将其视为计算的未来趋势之一。

在像这样的用例中,量子计算机肯定可以对经典计算机说:“拿着我的啤酒!”

格罗弗搜索算法|简化

原文:https://towardsdatascience.com/grovers-search-algorithm-simplified-4d4266bae29e?source=collection_archive---------11-----------------------

在这篇博客中,我将试图让你明白格罗弗的搜索算法到底是如何工作的,以及它与经典计算算法的不同之处

量子计算

参观:amitnikhade.com

当你改变看待事物的方式时,你看待的事物也会改变。——马普

照片由迈克尔·泽兹奇在 Unsplash 上拍摄

我试着将算法简化到最大程度,让初学者也能理解。

介绍

就解决复杂问题的速度而言,量子计算已经击败了经典计算机。量子计算机利用量子物理学的现象来存储数据和执行计算。量子记忆的基本单位是量子比特,类似于经典计算机中的比特 0 和 1。但是,仍然存在经典计算机击败量子计算机的问题,所以根据计算需要使用它们将是加速计算的一种优越组合。

让我们深入了解量子计算中最重要的算法之一 Lov Kumar Grover ,他在 1996 年发现了 Grover 的搜索算法,这位印度科学家被称为印度最杰出的计算机科学家之一。

算法

Grover 算法,即量子算法,解决了计算领域中的一个复杂场景。这是为量子计算提出的第二个主要算法。它解决了搜索非结构化数据的问题。让我们再深入一点。

让我们考虑这样一种情况,你有一个未排序的数 N 的列表,如下图所示,你想从中找出一个值 w(红框),它具有一些独特的属性。那么你怎么能找到 w 呢?

图 1n 个数字列表

经典方法:在经典计算中,我们必须检查列表中平均 N/2 的项目。简单地说,你必须一个接一个地验证它们,这需要 N 个步骤,即 O(N)。如果添加随机访问和预排序来对有序数据实现二分搜索法,则需要 log(N)个步骤,即 O(log(N))。然而,使用量子算法大约需要√N 步,即 O(√N)为了找到 w,例如,我们有一个 25 个元素的列表,我们想从列表中搜索一个值,传统上需要 N 步,而使用量子算法需要√N 步,即传统上需要 25 步,平方需要√25=5 步。

它利用叠加和相位干涉来改进搜索。在搜索我们想要的元素时,振幅放大起着非常重要的作用。让我们想象一下振幅放大。

振幅放大是增加要搜索的值的概率振幅并减少其余概率振幅的过程

考虑下面的 Kets ( k1,k2,k3,…..kn )在平衡叠加中,我们想要搜寻 kw ,因此通过执行振幅放大,我们和当 kets 被发送用于放大过程时,第一个先知将 kw ket 从 0 . 0 到 0 . 5 的概率颠倒为负相位,这将其与其他 kets 分开。

图 2 甲骨文

第二个神谕通过计算其平均值(即平均值)来反演所有振幅。这导致振幅 A∉千瓦的减少。并增加 kw ket,使 kw 变为 1,其余 ket 变为 0

图 3 扩散器

在最后阶段,用与列表中的项目相关的编码值来测量来自第二个预言的状态。并将结果状态映射回数据库。如果答案不正确,重复这些步骤。错误概率为 O(1/N)。

  • 这里你可以假设 oracle 和 diffuser 只是两个黑盒,它们对量子位执行特定的操作。

首先将 oracle 表示为 Uf,第二个表示为 Uφ,这是 Grover 的扩散算子。这些神谕重复√N 次。如果匹配是 m 的倍数,那么神谕被重复√(N/t)次。Grover 搜索也可以用于搜索多个元素。

图 4 格罗弗算法电路[ 来源

上图是遵循下面算法的格罗弗算法电路。

让我们快速浏览一下格罗弗的量子算法

该算法总结如下:

  1. 从量子位中选择一个你想搜索的随机值。
  2. 将所有的量子位传递到 Hadamard 门 h,使其叠加。

  1. 构造翻转待搜索对象的振幅的 oracle f。
  2. 构建围绕平均值反转的扩散器。

  1. 对单个目标重复 oracle √N 次,对多个目标重复√(N/t)。
  2. 最后,用数据库中的值验证状态。
  3. 喝一口咖啡。你完了。
  • 叠加是量子系统同时处于多个状态的能力

注意:如果增加迭代次数,性能会下降。

事实

  1. 量子电路对电磁场、碰撞、空气分子和热量很敏感,这些都会导致量子位失去量子属性
  2. 量子计算机被保存在极其寒冷的环境中,因为亚原子粒子必须尽可能接近静止状态。

结论

Grover 算法通过二次加速已经优于经典的搜索方法。量子计算机具有在极短的时间内完成复杂计算的趋势,与经典计算机相比,这需要数年时间。

参考

这些链接对我理解算法帮助很大,请访问它们。

https://qiskit.org/

关于我

https://www.linkedin.com/in/theamitnikhade/ https://github.com/AmitNikhade https://amitnikhadeofficial.medium.com/?source=your_stories_page-------------------------------------

GSDMM:社交媒体帖子和评论的主题建模

原文:https://towardsdatascience.com/gsdmm-topic-modeling-for-social-media-posts-and-reviews-8726489dc52f?source=collection_archive---------8-----------------------

自然语言处理

面向大胆的 NLP 初学者的实践教程

比诺勒在 Unsplash 上拍摄的照片

警告! 这是一篇史诗般的帖子。我真的希望读者能够按照本文概述的步骤,从头到尾重复这个过程。我附上了很多截图,让事情变得清晰易懂。

在本帖中,我们将查看一组推文,并尝试确定其主题。但首先,有一点背景。

什么是主题建模?

正如 yamini5 在 Analytics Vidhya 上所写的,“主题建模【原文】指的是识别最能描述一组文档的主题的任务。”简单地说,主题建模指的是摄取一堆非结构化和无标签的文本数据,然后将它们分类到它们所代表的不同主题中的过程。例如,我们可能有艾米莉·狄金森的诗集。当我们试图对它们进行分类时,我们可能会以生命、死亡和爱情为主题。主题建模指的是计算机如何使用一些奇特的数学来完成所有这些(我们不会谈论这些,LOL)。

一种流行的主题建模算法是 LDA 或潜在的狄利克雷分配。然而,LDA 有两个主要限制:1)它假设文本是主题的混合,2)它在短文本(< 50 个单词)上表现不佳。

进入我们的主角:GSDMM。

GSDMM 是 Gibbs Sampling Dirichlet Multinomial Mixture 的缩写,是由尹建华和王建勇提出的比 vanilla LDA 更好的模型。它假设一个文档只涉及一个主题,对于像 tweets 和电影评论这样的短文本非常有用。如果你想要算法背后的直觉,Matyas Amrouche 有一篇很棒的文章。或者,如果你愿意,你可以在这里阅读原文。

https://dl.acm.org/doi/10.1145/2623330.2623715

数据

今天,我们将采用前总统唐纳德·特朗普的一系列推文,并尝试应用主题建模。这个实践教程旨在为前总统特朗普的每一条推文分配一个主题。

让我们开始吃吧。

首先,转到thetrumparchive.com,点击“转发过滤器”和“隐藏转发”按钮,从我们的分析中排除这些转发。

然后,点击“日期过滤器”,设置日期范围从 2020 年 11 月 7 日到 2021 年 1 月 7 日。

接下来,我们将把 tweets 导出到一个 json 文件中。点击“导出”按钮。

单击“开始导出”继续该过程。

这是你在处理过程中看到的。

完成后,单击出现的框的右下角,并将其向右拖动,使其更大,更容易看到。

单击文本框内的某个位置,然后按 CTRL+A(同时按下 CTRL 键和键盘上的字母“A ”)来选择文本框内的所有内容。

一旦选择了所有内容,框内的所有内容都将高亮显示。

将光标放在蓝色突出显示区域上,然后右键单击。选择“复制”复制所有突出显示的内容。

接下来,打开你最喜欢的文本编辑器(Notepad,Sublime,notepad++),创建一个新文档,粘贴所有内容。

接下来,点击主菜单中的文件并选择“另存为…”

然后,将文件保存为 json 文件。

下一步,我们将下载并设置 GSDMM。

GSDMM 设置

对于这一步,让我们来看看 Ryan Walker 在 Github 上实现的 GSDMM。

找到标有“Code”的绿色按钮,单击它以显示下拉面板。寻找“下载 ZIP”并点击它。

将 zip 文件保存在工作文件夹中。

然后,提取其内容。

有时我喜欢保持简单,所以我将子文件夹重命名为“gsdmm ”,如下所示:

不要忘记注意到目前为止你的目录/文件夹结构。

在这种情况下,文件“setup.py”位于目录“GSD mm-short-text-topic-modeling \ GSD mm-master \ GSD mm”下,因此我在那里安装了 cd 并执行了下面一行:

python setup.py install

现在我们已经准备好用 Python 摇滚了!

代码

让我们启动 jupyter 笔记本,开始编码吧!

首先,让我们完成所有的导入并设置笔记本环境。

然后,让我们从之前保存的 json 文件中引入数据。

下面是一些用于预处理文本的函数。在这里,我们清理特殊字符,删除停用词,并堵塞令牌。然后,我们在一个名为 docs 的列表中逐个添加清理过的单词(或记号)。

在下面的要点中,我们将调用 MovieGroupProcess 来为我们进行主题聚类。

这就是奇迹发生的地方。要记住的一件事是将 alphabeta 值调整到最适合数据的值。此外,将 n_iters 调整到一个足够高的数值,以使模型收敛并稳定。最后,将 K 调整到一个足以覆盖您认为将要拥有的集群数量的数字。在这种情况下,我们从 15 个集群开始,到最后的 7 个集群结束。

让我们看看我们有什么。

下面的数组表示分配给每个 K 主题的文档(或 tweets)数量。我们有 15 个,但注意到有些是 0。我们只关心那些不是 0 的主题。

让我们按照重要性的顺序重新排列集群。

下面,第九个簇(或索引 8)是最重要的,因为它内部有 606 个文档。第二重要的是第一个集群(索引 0 ),它有 239 个文档。

让我们试着弄清楚这些主题群是关于什么的!

如上所述,下面的函数调用产生每个主题群中出现的顶部单词。

接下来,我们将集群重命名为主题#1 到主题#15,主题#1 最重要,主题#15 最不重要。

下面的代码片段定义了一个函数,该函数将使用原始文本及其指定的主题创建一个 dataframe。

在上述功能中,未达到 0.3 阈值的主题将被合并到“其他”类别中。

做一个快速的 value_counts,我们会看到每个主题的分布。

瞧啊。

就这样,伙计们!我们已经成功地为数据集中的每条推文分配了一个主题。

谢谢你过来看我的帖子。我希望它能激发你学习更多关于 GSDMM 的知识,并在其他社交媒体帖子和评论中试用它:-)。

如果你想了解更多关于我从懒鬼到数据科学家的旅程,请查看下面的文章:

如果你正在考虑改变方向,进入数据科学领域,现在就开始考虑重塑品牌:

敬请期待!

你可以在 Twitter 或 LinkedIn 上找到我。

GSoC 2021 与 ML4SCI |核磁共振项目

原文:https://towardsdatascience.com/gsoc-2021-with-ml4sci-the-nmr-project-1a5e8995af9?source=collection_archive---------29-----------------------

对我的谷歌 2021 代码之夏项目、体验、重要收获和对即将到来的年轻开发者的建议的简短总结。

这篇博客是我在 ML4SCI 组织下谷歌代码之夏 (GSoC) 2021 项目的简短总结。GSoC 是一个为期 10 周的全球项目,旨在让更多的学生开发人员参与开源软件开发。今年是谷歌代码之夏 17 周年,来自全球 103 个国家的 4,795 名学生提交了 6,991 份提案,其中 1,286 名学生获得了与 199 个开源组织合作的机会。1

GSoC 致力于开源软件|图片来自 Unsplash

项目描述和动机

本部分面向普通观众。更详细的物理治疗可在以下章节。

在低温下,许多材料转变成电子相,这不能被归类为简单的金属或绝缘体。超导体和自旋液体等物质的新量子相由于其脆弱的性质而更难研究,这使得非侵入性和间接测量变得重要。科学家因此使用核磁共振(NMR),一种非侵入性的方法从外部探测这些物质。核磁共振是一种实验技术,主要用于质量控制和科学研究,以确定任何样品的分子结构、纯度和含量。GSoC 项目的想法是通过核磁共振的模拟来探索这些材料中电子相与原子核之间的联系。我们分析了由于外部磁脉冲引起的核自旋的时间演化,并使用合适的机器学习模型对它们进行分类。2

项目的工作流程:我们使用不同的材料参数模拟 NMR 自旋回波实验,以获得材料的平均核磁磁化强度作为时间的函数(如 NMR 实验期间所见)。然后,我们在数据集上使用机器学习来依次预测和分类材料的参数和类型

ML4SCI 和核磁共振项目

图像演职员表:GSoC&ML4SCI

组织描述

与参加 Google 代码之夏的大多数其他组织不同,我觉得 ML4SCI 在方法和目标上都是独一无二的。虽然大多数组织都在寻找开发人员来建立他们的代码库,解决 bug 和更新新功能,但 ML4SCI 的主要目标是通过使用机器学习开发/使用免费和开源软件来解决基础科学中的开放式研究问题。今年的项目类型从重力物理学的深度学习、天文学、量子机器学习、机器学习到流体湍流、新型量子材料等。

项目代码库

我已经将我的工作编译成一个单独的开源库。标题为“用 NMR 解码量子态”,我们有一套从 NMR 模拟数据中读取、预处理和提取特征的教程。我们还描述了如何训练随机森林分类/回归模型,然后分析特征的重要性,以解释时间序列中的潜在特征。

为什么是 ML4SCI?

作为一名物理学专业的学生,我相信我在凝聚态物理、量子力学和人工智能领域的背景和兴趣与 ML4SCI 小组的理念和兴趣,特别是 NMR-GSoC 研究项目非常契合。我以前从事过深度学习在基础科学领域的应用,并且相信 Python 是科学、工程领域开源软件的巨头。最后,作为自由和开源软件的倡导者,为开放的科学和社会构建工具总是一种绝对的荣誉。

核磁共振中的自旋回波(某些物理学)

这一节是给深奥的人看的,初读时可以忽略。

当磁偶极子暴露在两个外部磁场中时,量子系统中会发生磁共振:(1)静态磁场和(2)振荡电磁场。然后,振荡场可以使偶极子以一定的概率在其能量状态之间跃迁,并且当振荡场的频率导致任意两个能量状态之间最大可能的跃迁概率时,就可以说已经实现了磁共振。在核磁共振中,我们利用这一基本现象来测量所需材料的各种特性。[3]

一种用于探测核磁共振中分子特性的常用技术被称为“自旋回波”。核自旋被排列、释放,然后重新聚焦,形成原始排列的尖锐峰,或“回声”。当自旋通过自旋-自旋耦合相互作用时,磁化中重新聚焦的回波会变得高度失真。科学家和研究人员经常使用这种研究磁化曲线以确定电子相位的技术。我们使用这些模拟的核磁曲线来训练机器学习模型,以预测模型参数和底层材料的种类。

虽然核磁共振“自旋回波”技术听起来可能很复杂,但下面由加文·W·莫利(【https://en.wikipedia.org/wiki/Spin_echo】)创作的动画让它变得清晰多了!

模拟电子和核自旋

大多数材料可以根据它们的电子性质分为三类:金属、绝缘体和半导体。这些电子通过超精细相互作用与材料的核自旋(非常非经典的东西)相互作用,如果电子-核耦合变得足够强,一个不可忽略的两步过程可以使整个材料中的原子核相互耦合。这个两步过程是当一个核自旋耦合到一个电子并改变它的运动时,然后这个电子在材料的其他地方“散射”出另一个核自旋。我们通过位置 r_j 和 r_i 处的原子核之间的有效自旋-自旋耦合来表示这种两步散射过程,由下式给出:

材料中两个核自旋之间的有效耦合|作者图片

其中,α为耦合强度,ξ为耦合长度。一般来说,α和ξ取决于核-电子耦合的细节和电子的量子状态,但在我们的工作中,我们将使用它们来查看自旋回波实验是否可以提供足够的信息,以从单个 M(t)曲线精确地“逆向工程”这些值。我们的模拟还包括核自旋的耗散:由于与环境的耦合,自旋信息可能会“丢失”。这发生在时间尺度 t(decay)≃√γ.我们的目标是开发一个 ML 模型,它可以从一条 M(t)曲线中精确地确定上述三个变量(α、ξ和γ)。

数据集(一些数据科学和一些物理学)

今年夏天,我们努力将核磁共振扩展到感测强电子自旋-自旋关联和原子核之间的非耗散自旋-自旋相互作用。为了研究广泛的物理现象,我们在具有不同种类的核间相互作用和耦合强度的 2D 自旋的晶格上模拟了典型的 NMR 自旋回波实验的行为。我们采用径向高斯、RKKY 和幂律型核来模拟长程(来自有隙自旋激发)和短程(来自无隙自旋激发)相互作用。由于在自旋回波期间测量的平均磁化强度是局部相互作用类型和底层材料的电子磁化率的函数,我们旨在理解材料类型,并仅基于回波曲线的形状从机器学习分类和回归模型预测耦合强度。我们使用的数据集是在多次自旋回波模拟期间测量的作为时间函数的平均核磁化强度的大小。

from NMR_ML import Dataset# Create the dataset object
gaussian_data=Dataset(data_directory_path="data//2021-08-14_gauss/")# Load rawdata and get the desired time-window
rawdata = gaussian_data.load_data()
rscl_df, echo_pulse = gaussian_data.get_window(rawdata, center_ratio=2/3, width=150)# Repeat the process for the Power-Law and RKKY datasets

我们用于机器学习实验的数据集。顶部面板显示了整个时间序列数据集。中间部分显示了三种径向内核类型和在 interst 区域中的相应自旋回波曲线。在下图中,我们看到了 NMR 实验旋转坐标系中时间序列的频率分布。|作者图片

方法

为了实现更高水平的可解释性,我们使用不同的特征空间,即逐点时间序列、逐点频率分布和多项式特征。我们通过一种叫做多尺度多项式特征化的技术从时间序列中提取特定特征。这里,我们将时间序列划分为等长的仓,并在每个仓中拟合一个三次多项式。我们使用这些系数作为曲线的新特征。最后,我们对新特征执行回归和分类等任务。[4]

所用方法的总体流程。我们同时使用逐点和多项式特征以获得更高的可解释性|作者图片

多尺度多项式特征化: (a)我们将时间序列分成相等的 4、5 或 10 个部分的仓,称为“多项式域”,以及(b)在每个仓中拟合三次多项式。我们使用每个这样的拟合多项式的系数作为新提取的特征数据集| 图像由作者 | 从 Torrisi 等人的“用于可解释的 X 射线吸收近边缘结构光谱-性质关系的随机森林机器学习模型”得到启发 npj 计算资料6.1(2020):1–11。

from NMR_ML import Dataset, PolynomialFeatures# Create the dataset object
gaussian_data = Dataset(data_directory_path="2021-08-14_gauss/")# Load rawdata and get the desired time-window
rawdata = gaussian_data.load_data()
rscl_df, echo_pulse = gaussian_data.get_window(rawdata, center_ratio=2/3, width=150)# Obtain the polynomial features dataset
polynomial_features = PolynomialFeatures(n_splits=[4,5,10], order_fits=[3,3,3])

结果

我们建立了两个分类模型来将磁化时间序列分类为三种相互作用类型,并建立了回归模型来预测相互作用参数(αx,αz,ξ)或整个自旋集的总核积分(W =σK(r(I,j))。我们使用集成学习并结合许多弱决策树学习器来构建随机森林分类器/回归器。此外,我们从时间序列和频域数据中提取基本特征,以理解回波脉冲期间对理解材料最有用的子部分。关于特征提取方法和 ML 技术的更多细节可在“ /Tutorial-nbs ”部分获得。

  • 有了相互作用类型的知识,我们就能够预测 R 约为 0.8 的核积分(W)的值。我们观察到,回归的最重要特征是回波前区域的平均值(x⁰)和正好在回波脉冲(x,x)处的磁化的斜率和曲率

回归结果:这里,我们使用数据集的四个版本。我们使用来自作者的时域和频域|图像的逐点和多项式特征

  • 使用随机森林分类器,我们能够在对幂律与非幂律类型的回波曲线进行分类时获得~0.9 的良好 F1 分数。本质上,我们能够在核磁共振实验中仅通过观察样品的平均磁化强度来对材料原子核之间的相互作用类型进行分类。

分类结果:使用混淆矩阵,我们看到在较高的核积分(W)上,分类器在区分幂律和非幂律类型方面工作得更好

未来工作

尽管我们能够实现项目建议书中提到的大部分目标,但我们认为仍有改进的空间,并将更多地关注以下方面:

  • 基于结果部分描述的结果,我们希望进一步探索深度学习是否可以在分类/回归方面提供更好的性能,而不会损害模型的可解释性。尽管这将需要更大的数据集和计算能力,但获得的新见解将非常有助于识别新的物理学,并进一步有助于利用数据革命来构建和探索新的量子材料。
  • 我们还想探索在计算机上优化和调整所施加的磁脉冲,以设计一个能够以更高精度预测耦合强度的实验。

我希望这个项目和 NMR_ML 脚本有益于试图解决类似问题的人。虽然不是完美的解决方案,但我希望这些脚本可以让您了解如何处理这个问题。如果你发现了一些有用的东西,请考虑主演库,创造一个问题,或者只是下降一个消息!

最后的想法和信息

我要感谢我的项目导师斯蒂芬·卡尔博士、查尔斯·斯奈德维斯纳·米特洛维奇教授、钱德拉舍卡·拉马纳森教授和布拉德·马斯顿教授、整个 NMR 研究小组和整个 ML4SCI 社区,感谢他们不断的支持、激励和指导。我在这个超级令人兴奋的项目上度过了一个美好的夏天,我期待着在追求知识和重新兴奋的过程中继续合作!

最后,对未来的程序员和希望参加 GSoC 的学生的一些建议,请将 GSoC 视为一个你本来就想从事的项目,而不是为了一个证书或一个荣誉的象征而做的事情。如果与你的长期目标和职业抱负保持一致,这将是一个更有回报的过程。它是关于学习、创造和回馈一个由优秀开源开发者组成的社区,并成为原创科学研究的一部分(就我而言)。如果你有合适的技术技能和背景,找到符合你兴趣的利基项目并不像听起来那么难。一个人在夏天需要掌握的最重要的非技术技能是交流、交流和沟通!

来自我的导师斯蒂芬·卡尔博士的信息:

SOC 为学生提供了有价值的结构和目标。这对于相对短暂的夏季研究经历至关重要,因为大多数传统的研究项目会持续数月或数年。申请过程提供了大量有不同背景和兴趣的热情学生的选择,帮助确保每个学生找到一个很适合他们的项目(反之亦然!).

感谢 ML4SCI,感谢布朗大学,感谢谷歌,给了我这么美好的学习机会。

参考资料:

[1]https://open source . Google blog . com/2021/05/Google-summer-of-code-2021-students-are . html

2https://ml4sci.org/gsoc/2021/proposal_NMR.html

[3]c .科恩-坦努吉、b .迪乌和 f .拉罗(1986 年)。量子力学,第二卷。量子力学2 ,626。

[4] Torrisi,Steven B .等人,“可解释的 X 射线吸收近边缘结构光谱-性质关系的随机森林机器学习模型。” npj 计算材料6.1(2020):1–11。

TensorFlow 和 PyTorch 的 Conda 指南

原文:https://towardsdatascience.com/guide-to-conda-for-tensorflow-and-pytorch-db69585e32b8?source=collection_archive---------4-----------------------

了解如何为不同版本的 CUDA、TensorFlow 和 PyTorch 设置 anaconda 环境

维多利亚博物馆在 Unsplash 上拍摄的照片

真的很遗憾,大多数人对深度学习的第一次体验是不得不花几天时间试图找出为什么他们从 GitHub 下载的模型就是…不能…运行…

当试图运行现成的模型时,依赖性问题非常普遍。其中最大的问题是需要为 TensorFlow 安装正确版本的 CUDA。TensorFlow 多年来一直很突出,这意味着即使是新发布的模型也可以使用旧版本的 TensorFlow。除了感觉 TensorFlow 的每个版本都需要一个特定版本的 CUDA,而其他任何版本都不兼容之外,这不是一个问题。可悲的是,在同一台机器上安装多个版本的 CUDA 真的很痛苦!

TensorFlow CUDA 版本匹配

经过多年的头痛,感谢 Anaconda 的帮助,我终于意识到安装 TensorFlow 和正确的 CUDA 版本可以像下面这样简单:

conda create --name tf
conda activate tf
conda install tensorflow-gpu

Conda 与 pip 虚拟环境

由于对pipconda之间的区别理解错误,我之前只用过pip。真的只是知道pip是“官方”的 Python 包管理器。

两者之间的主要区别是conda环境不仅仅是针对 Python 包的。像 CUDA 这样的库可以安装在您的隔离环境中。另一方面,有些包在conda中不存在,你必须通过pip安装它们,这是人们可能会偏离conda的一个原因。同时使用condapip有时会很棘手,但是我会在这篇文章的后面提供一些技巧来解决这个问题。

如果您想开始使用conda,请遵循链接中的 anaconda 安装说明。在pipconda之间,创建、激活和删除环境的基本命令非常相似。

创造环境

*# pip* virtualenv env_name*# conda* conda create --name env_name

激活环境

*# pip* source /path/to/env_name/bin/activate*# conda* conda activate env_name

注意:安装 anaconda 后,它会自动创建并激活一个基础环境。建议您自己创建新环境。使用以下命令关闭自动激活:

conda config --set auto_activate_base false

删除环境

*# pip* cd /path/to/env_name
rm -rf env_name*# conda* conda env remove -n env_name

例子

下面是一些如何加载存在于五十一模型动物园中的 TensorFlow 和 PyTorch 模型的例子。 FiftyOne 是一款开源工具,用于机器学习工程师以一种易于修改、可视化和分析的方式存储他们的数据、标签和模型预测。包含在51中的是一个计算机视觉模型的动物园,它们只有一行代码,将用于轻松测试我们的conda环境设置。

第五十一模型动物园中的模型子集(图片由作者提供)

:安装带 GPU 功能的 TensorFlow 需要支持 CUDA 的卡。这里是一个支持 CUDA 的 GPU 列表。

使用 Tensorflow 2。x 型号

conda create --name tf2
conda activate tf2
conda install tensorflow-gpu

FiftyOne 支持各种格式的图像和视频数据集。在这些例子中,我只有一个图像目录,我将把它加载到 FiftyOne 来生成模型预测。如果您传入/path/to/dataset并指定您使用的数据集类型为fiftone.types.ImageDirectory,那么您可以使用自己的图像目录。

这个例子中的大部分工作,我使用的是51 命令行界面(CLI) 。

pip install fiftyone*# Create a dataset from the given data on disk*
fiftyone datasets create \
    --name my_dataset \
    --dataset-dir /path/to/dataset \
    --type fiftyone.types.ImageDirectory

我可以下载我想要使用的模型,然后检查它是否满足要求。

*# Download a model from the zoo* fiftyone zoo models download centernet-hg104-512-coco-tf2*# Ensure you installed all requirements* fiftyone zoo models requirements \
    --ensure centernet-hg104-512-coco-tf2*# This model is from the TF2 Model Zoo which must be installed*
eta install models

然后,我会将该模型应用到数据集,以生成预测并在 FiftyOne 应用程序中可视化它们。

*# Apply a model from the zoo to your dataset*
fiftyone zoo models apply \
    centernet-hg104-512-coco-tf2 \  
    my_dataset \                    
    predictions *# Launch the FiftyOne App to visualize your dataset*
fiftyone app launch my_dataset

查看带有来自 centernet-Hg 104–512-coco-tf2 的预测的数据集(图片由作者提供)

使用 TensorFlow 1。x 型号

conda create --name tf1
conda activate tf1

您可以搜索可用的软件包,然后选择要安装的 TensorFlow 版本。这将在您的conda环境中安装相应的 CUDA 版本。

conda search tensorflow-gpu
conda install tensorflow-gpu=1.15

除了使用 TensorFlow 1 的模型之外,我将使用与 TensorFlow 2 示例中相同的过程。

pip install fiftyone*# Download a model from the zoo* fiftyone zoo models download mask-rcnn-resnet101-atrous-coco-tf*# Create a dataset from the given data on disk*
fiftyone datasets create \
    --name my_dataset \
    --dataset-dir /path/to/dataset \
    --type fiftyone.types.ImageDirectory*# Apply a model from the zoo to your dataset*
fiftyone zoo models apply \
    --error-level 1 \
    mask-rcnn-resnet101-atrous-coco-tf \     
    my_dataset \                              
    predictions *# Launch the FiftyOne App to visualize your dataset*
fiftyone app launch my_dataset

查看带有 mask-rcnn-resnet 101-atrous-coco-TF 预测的数据集(图片由作者提供)

使用 PyTorch 模型

安装 PyTorch 稍微容易一点,因为它是用多个版本的 CUDA 编译的。这给了我们使用任何版本 CUDA 的自由。撰写本文时(2021 年 1 月)的默认安装说明推荐 CUDA 10.2,但 PyTorch 有一个 CUDA 11 兼容版本。

conda create --name pyt
conda activate pyt
conda install pytorch torchvision torchaudio cudatoolkit=10.2 \
    -c pytorchpip install fiftyone

对于这个例子,我将使用 Python API 来执行与我们之前使用命令行几乎相同的步骤。唯一的区别是我们使用的模型,我们正在从51 数据集动物园加载数据集。

查看来自 key point-rcnn-resnet 50-fpn-coco-torch 的带有预测的数据集(图片由作者提供)

注意:如果你用的是 Mac,需要 GPU 支持,从源码安装 PyTorch。

常见问题

当我从pip切换到conda时,出现了三个问题,这需要一点时间来解决。

1) Pip 可以在 conda 内部运行

如果您想要使用的包只存在于pip中,您可以使用pip将其安装在您的conda环境中。然而,pipconda 在一起并不总是打得好。

主要问题是conda不能控制它没有安装的包。因此,如果在conda环境中使用pip,那么conda不会意识到这些变化,可能会破坏环境。

当一起使用pipconda时,请遵循张克帆·赫尔默斯的提示:

  • 千万不要在 **pip**后使用 **conda** 。用conda安装你能安装的所有东西,然后用pip安装剩余的软件包
  • 创造新的conda环境。使用pip会导致环境崩溃,所以在安装pip包之前,一定要创建一个新的隔离的conda环境。
  • 如果你在使用了pip之后需要安装一个conda包,最好是创建一个新的环境,并按照正确的顺序重新安装所有的东西。

2)康达环境并不是全球孤立的

创建pip虚拟环境时的默认行为是,在新环境中,您不能访问全局安装的pip包。如果您想要访问全局包,您需要使用以下内容初始化您的虚拟环境:

virtualenv env --system-site-packages

另一方面,conda允许您默认访问全局系统软件包。如果您希望环境与这些全局包完全隔离,就像使用pip一样,您可以基于一个空的 pip virtualenv 的克隆来创建conda 环境。

virtualenv empty_env
conda create -n env --clone empty_env

理想情况下,你应该避免安装全局pip包,所以这不应该是一个问题。

3)需要指定 CUDA 路径

如果您在系统范围内安装了 CUDA,那么在您的conda环境中安装 CUDA 后,LD_LIBRARY_PATH环境变量可能会指向错误的位置。

要解决这个问题,当您进入您的conda环境时,您需要更新LD_LIBRARY_PATH以指向在conda中包含cuda的目录(通常该目录是/path/to/conda/pkgs/)。然后,当您离开conda环境时,您会希望将它指向 CUDA 的系统级安装。

首先,导航到您的conda环境位置并创建以下文件和文件夹:

cd /path/to/anaconda/envs/my_env
mkdir -p ./etc/conda/activate.d
mkdir -p ./etc/conda/deactivate.d
touch ./etc/conda/activate.d/env_vars.sh
touch ./etc/conda/deactivate.d/env_vars.sh

activate.d/env_vars.sh中添加以下几行。用在您的conda环境中安装 CUDA 的路径替换/your/path

#!/bin/bashexport OLD_LD_LIBRARY_PATH=${LD_LIBRARY_PATH}
export LD_LIBRARY_PATH=/your/path:${LD_LIBRARY_PATH}

一般来说,这个/your/path应该是这样的:

export LD_LIBRARY_PATH=/home/user/conda/pkgs/cudatoolkit-10.2/lib:${LD_LIBRARY_PATH}

然后在deactivate.d/env_vars.sh中添加以下几行:

#!/bin/bashexport LD_LIBRARY_PATH=${OLD_LD_LIBRARY_PATH}
unset OLD_LD_LIBRARY_PATH

摘要

conda只用几个命令就能安装非 Python 包,比如 CUDA,这简直是天赐之物。结合使用conda和51 模型动物园意味着你可以在几分钟内从几十个模型中生成预测。然而,如果您没有做好准备,从pip虚拟环境切换到conda环境可能会导致一些意想不到的行为。

在 Veusz 中创建科学地块的指南

原文:https://towardsdatascience.com/guide-to-creating-scientific-plots-in-veusz-cb843e68bd59?source=collection_archive---------31-----------------------

实践教程

为 Veusz 的专业和学术期刊创建图表的综合指南。

由迪诺·瑞奇穆斯在 Unsplash 上拍摄的照片

eusz 是一个图形程序,旨在为学术和专业期刊制作出版就绪的图形。它是免费提供的,并与 Python 很好地集成在一起。凭借创建 2D 和 3D 图形的强大能力,Veusz 帮助研究人员可视化他们在社会科学、工程、生物、医学等领域使用的所有类型的数据结构。

在学术期刊中,编辑需要高度发展的图表,但是一些统计程序并不能提供高质量的图表在像样的期刊上发表。Veusz 是一个简单而强大的工具,用于准备高质量的图形,研究人员可以使用它来可视化他们的结果。尽管有这些好处,但数据科学家和研究人员似乎并没有很好地意识到 Veusz 提供的所有可能性。因此,这篇文章表明:

  • Veusz 工作空间简介
  • 一些不太常见的图表示例
  • 与其他程序相比,使用 Veusz 的好处。

最后,我还将提到用户在使用该程序时会发现的一些缺点。

Veusz 工作空间

Veusz 允许以三种方式格式化图表:

  • 在 Veusz GUI 中手动格式化
  • 命令行
  • 用作 Python 模块。

手动格式化包括导入数据和手动编辑图表以构建 2D 或 3D 产品。在 Veusz 中,通过构建绘图小部件、特定元素(图表、轴、文本标签等)来创建绘图。)用户在编辑窗口中添加或移除。小部件的属性在属性窗口中编辑,它们的外观和形式(字体、轴线颜色、标签颜色等。)在格式化窗口中。

以下是 Veusz GUI 的外观:

来源:自己的工作与一个 Veusz 的例子。

命令行界面

控制 Veusz 的另一种方法是通过它的命令行界面。因为 Veusz 是用 Python 编程的,所以它使用 Python 作为它的脚本语言。因此,您可以在命令行中自由混合使用 Veusz 和 Python 命令。当命令在 Veusz 窗口的命令提示符中输入时,它支持简化的命令语法,其中命令名称后面的括号可以由 Veusz 命令中的空格替换。

Veusz 还可以从文件中读取 Python 脚本。NumPy 包已经导入到命令行界面中。

用作 Python 模块

Veusz 可以用作绘制数据的 Python 模块。因此,标准 python 库(如 Matpotlib、Seaborn 或 Plotly)又多了一个竞争对手。例如,这段代码构建了一个简单的 x 平方图,它变成了 x 立方图(引用自官方文档):

**import** **veusz.embed** **as** **veusz**
**import** **time***#  open a new window and return a new Embedded object*
embed = veusz.Embedded('window title')*#  make a new page, but adding a page widget to the root widget*
page = embed.Root.Add('page')*#  add a new graph widget to the page*
graph = page.Add('graph')*#  add a function widget to the graph.*
function = graph.Add('function', function='x**2')function.function.val = 'x**3'

图形导出可能包括 TIFF 格式和其他标准格式(JPG、PNG 和其他几种格式)。

维尤兹的精彩剧情

三维绘图

与其他一些图形软件包相比,Veusz 最大的竞争优势可能是它能够绘制复杂的 3D 图形。让我们用一个简单的例子来演示一下。

K-means 聚类算法通常用于将客户群聚类为具有相似特征的离散客户组。类似地,它可以将国家、家庭或其他单位聚集成更一致的组。聚类通常出现在 2D 散点图中。为了让它更有趣,我添加了 Z- 轴,其中包含了回答者的年龄。

Veusz 提供了输出数据的出色的 3D 可视化。作为一个例子,我使用的是商场客户细分数据集,该数据集可从 Kaggle 免费获得,用于学习目的:

https://www.kaggle.com/vjchoudhary7/customer-segmentation-tutorial-in-python

彩色 3D 散点图显示:

  • 客户在 X- 轴上的消费得分
  • Y- 轴上的客户年收入
  • Z 轴上的客户年龄
  • 使用 K-means 识别客户群。

来源:自己的作品。

这个图是彩色的,但是编辑通常想要灰度图。例如,通过使用主 GUI 中的格式化窗口,它可以被快速转换成灰度图像。

Matlab 漏斗图

漏斗图是一种图表,用于检查系统综述和荟萃分析中是否存在发表偏倚。这是一个 2D 图,在 x 轴上绘制了调查研究的回归系数,在 y 轴上绘制了观察数量(或估计的标准误差)。

大多数在经济研究中使用元分析的文章都在 STATA 中格式化他们的图表,这产生了相当平均质量的漏斗图。另一方面,Veusz 制作的漏斗图看起来更整洁、更精致。它们类似于 Matlab 图形,我认为这是学术期刊绘图质量的黄金标准。

以下漏斗图显示了 Veusz 在为系统评价和荟萃分析准备图表方面的可能性。他们揭示了一篇文章中的出版偏见,这篇文章现在正在一家高级期刊上进行修订。

资料来源:Koráb,Fidrmuc,Dibooglu (2021 年),正在修订中。

缺点和局限性

由于 Veusz 是一个免费提供的程序,它有几个缺点值得一提:

  • 几个情节没有实现,或者他们的制造是费时的。例如,这些可能是小提琴图或简单的热图
  • 我没有找到一些基本的功能,比如在 Y 轴上的水平编号。这可能有点令人沮丧,但我总能找到一些变通方法来根据需要准备图表
  • 有些功能可能不是很直观,所以需要一些时间来学习所有必要的细节。

结论

Veusz 是一个简单但功能强大的工具,用于可视化数据并为学术和专业期刊准备出版就绪的图。与其他类似的软件包相比,如适马图,Veusz 是免费的,它也定期更新新的功能和图表类型。它需要一些初始时间投资,但最终,它会带来回报,并创建非常好的图形。使用 Veusz 的一大好处是主 2D 和 3D 图表已经准备好了,可供任何用户使用。只需导入您的数据,稍作编辑,图表就完成了。尽管有几个缺点,用户可以利用许多格式选项和“玩”图形,直到他们得到完美的结果。

顺便说一下,它的名字应该读作“views”…

PS:你可以订阅我的 邮件列表 在我每次写新文章的时候得到通知。如果你还不是中等会员,你可以在这里加入https://medium.com/@petrkorab/membership

ggplot2 数据可视化指南

原文:https://towardsdatascience.com/guide-to-data-visualization-with-ggplot2-in-a-hour-634c7e3bc9dd?source=collection_archive---------16-----------------------

扬·巴布拉克在 Unsplash 上拍摄的照片

介绍

我一直是 Matplotlib 和 Seaborn 的忠实用户,因为它们在创建漂亮的图形方面简单方便,满足了您在传达想法方面的期望。在 R 里,我找到了一个类似的包,是 ggplot2。它漂亮的默认图表选项给我留下了深刻的印象,帮助我减少了大量定制可视化的时间,只需专注于创建最能表达数据信息的图表。关于 ggplot2 的另一个有趣的地方是,一旦理解了它在图形设计中的逻辑,学习起来并不困难。在今天的这篇文章中,我将帮助您了解 ggplot2 的概况。

资料组

对于数据可视化示例,我将使用 dplyr 包中的默认数据集。您可以安装 dplyr 包,并获得如下代码所示的数据:

install.packages(dplyr)
library(dplyr)
data = storms

了解图层

ggplot2 在层中构建图形是您需要了解的第一件也是最重要的事情。您可以从显示原始数据的层开始,然后继续添加其他元素以生成您想要的图形。这种方法将帮助你缩小你头脑中的预期结果和现实中的图表之间的差距。

Ggplot

ggplot 函数包含两个主要部分,分别是:

  • 数据:您想要可视化的信息
  • 映射:变量如何映射到可视属性(映射在 aes 函数中)
install.packages("ggplot2")
library(ggplot2)# specify dataset and mapping
ggplot(data = data,
       mapping = aes(x = pressure y = wind))

图 1:指定数据框架

我确定了 x 和 y 是什么,但是我没有指定如何绘制图形。因此,图 1 仍然是空的。现在,我将继续向我的图表添加下一个元素。

Geoms

几何图形是几何对象(例如:线、条等。)来决定如何呈现观察结果。图层通常从创建几何图形开始。

这是一个带有 geom_point 的散点图示例。

您还可以创建

  • 的条形图geom _ bar()
  • 带有 geom_path()geom_line() 的线图
  • 带有geom _ box plot()的方框图
  • 一个带有geom _ histogram()geom _ freqply()的直方图

注意,在代码中,我使用“+”来连接最终图形的元素。

ggplot(data = data,  
       mapping = aes(x = pressure, y = wind)) +
 geom_point()

图 geoms 散点图

我可以在 geom_ponit 中用不同的属性自定义我的图形。其他控件属性包括大小、颜色、形状、alpha 等。让我们将它们添加到我们的图表中,看看有什么不同。

ggplot(data = data,
       mapping = aes(x = pressure, y = wind)) +
  geom_point(color = "pink", 
             alpha = .9,     
             size = 2)

图 3:定制后的散点图

Alpha 控制图形的透明度,其范围从 0(完全透明)到 1(完全不透明)。可以通过调整透明度来可视化重叠点。

面状

分面是一种有助于显示变量的每个类的技术。我将尝试使用 facet_wrap 属性在图形中显示每种风暴的压力和风力。

ggplot(data = data,
       mapping = aes(x = pressure, y = wind)) +
  geom_point(color = "blue", 
             alpha = .9,
             size = 2) +
  facet_wrap(~status)

图 4:具有 facet_wrap 属性的图形

流畅的

在许多情况下,您的数据有很多噪音,很难观察到模式。您可以选择在图表中添加一条平滑线。

例如:

ggplot(data = data,
       mapping = aes(x = pressure, y = wind)) +
  geom_point(color = "blue", 
             alpha = .5,
             size = 2) +
  geom_smooth(span = 1)

图 5:跨度= 1 的平滑线

根据 跨度 参数(0–1)的范围决定线的抖动。 geom_smooth() 中另一个有趣的事情是,你可以陈述用来拟合平滑曲线的方法。在下图中,我使用了【lm】的方法,这是线性模型,给出了最佳拟合的线。

ggplot(data = data,
       mapping = aes(x = pressure, y = wind)) +
  geom_point(color = "blue", 
             alpha = .5,
             size = 2) +
  geom_smooth(method = "lm")

图 6:使用线性方法平滑线条

还有 method =【rlm】类似于【lm】但是忽略了离群值的影响。

变量也可以映射到不同的颜色。在下面的代码中,我在 aes 属性中给我的变量分配了颜色。

ggplot(data = data,
       mapping = aes(x = pressure, y = wind, color = status)) +
  geom_point( alpha = 0.3,
              size = 2)

图 7:给组分配颜色

标签和主题

为了有一个完整的图形,定制主题和标签是必不可少的步骤。我们可以通过控制各种元素来调整视觉效果的主题,比如字体、网格线、图例位置等。此外,自定义标题、副标题和题注可以用功能 labs()修改。

ggplot(data = data,
       mapping = aes(x = pressure, y = wind, color = status)) +
  geom_point(alpha = 0.3,
             size = 2) +
  labs(title = "Relationship Between Wind and Pressure of Storms",
       subtitle = "By Chi Nguyen",
       caption = "Source: dplyr package",
       x = " Pressure",
       y = "Wind",
       color = "Type of Storms") + 
  theme_set(theme_bw())

图 8:调整图表的主题和标签

熟悉一些基本的图表

基本上,当你记住了这些元素后,你就可以轻松地为自己绘制一个漂亮的图形。现在,让我们看看该怎么做。

折线图

前面说过,我们可以用 geom_line 来画折线图。这是计算每年风暴数量的代码。

count_storms <- 
  data %>%
  group_by(year) %>%
  summarise(number_of_storms = n())ggplot(data = count_storms,
        mapping = aes(x = year, y = number_of_storms)) +
  geom_line(size = 1.5,
            color = 'pink') +
  geom_point(size = 2,
             color = 'black') +
  labs(title = "Number of Storms by Years",
       subtitle = "By Chi Nguyen",
       x = "Year",
       y = "Number of Storms") + 
  theme_set(theme_bw())

图 9:每年的风暴数量

条形图

从 1975 年到 2015 年的 40 年间,让我们看看每年有多少风暴发生。我们将使用 geom_bar() 来创建图表。

storms_no <-  
  data %>%
  group_by(status) %>%
  summarise(number_of_storms = n()) %>%
  arrange(desc(number_of_storms)) %>%
  mutate(prop = round(number_of_storms * 100 / count(status), 1))ggplot(storms_no, 
       aes(x = reorder(status,number_of_storms),
           y = number_of_storms)) + 
  geom_bar(stat = "identity", 
           fill = "indianred3", 
           color = "black") +
  geom_text(aes(label = number_of_storms), 
            vjust = -0.25) +
  labs(x = "Types of Storms", 
       y = "Number of Storms", 
       title  = "Number of Storms During The Period of 40 Years")

图 10:条形图

如果想要有水平条形图,我们可以添加【coord _ flip()】来变换图形。

ggplot(storms_no, 
       aes(x = reorder(status,number_of_storms),
           y = number_of_storms)) + 
  geom_bar(stat = "identity", 
           fill = "indianred3", 
           color = "black") +
  geom_text(aes(label = number_of_storms), 
            vjust = +0.25,
            hjust = 0
           ) +
  labs(x = "Types of Storms", 
       y = "Number of Storms", 
       title  = "Number of Storms During The Period of 40 Years") +
  coord_flip()

图 11:水平条形图

圆形分格统计图表

现在,我要用饼状图计算 1975 年发生的每种风暴的百分比。

count_storm_75 = length(data$status[which(data$year == '1975')])#Calculate the percentage
storm_pct = 
  data %>%
  filter(year == '1975') %>%
  select(status) %>%
  group_by(status) %>%
  summarise(number_of_storms = n()) %>%
  arrange(desc(number_of_storms)) %>%
  mutate(pct = round(number_of_storms * 100 / count_storm_75, 1))#Plot the Pie chart
ggplot(storm_pct, 
       aes(x = "", 
           y = pct, 
           fill = status)) +
  geom_bar(width = 1, 
           stat = "identity", 
           color = "black") +
  coord_polar("y", 
              start = 0, 
              direction = -1) +
  ggtitle("Percentage of Storms Happened in 1975")+
  theme(plot.title = element_text(hjust = 0.5))+
  guides(fill=guide_legend(title="Types of Storms")) +
  theme_void()

图 12:饼图

结论

我自己发现与 Python 中的其他包相比,ggplot 很容易上手。通过学习这个包的基础知识,您可以根据自己的喜好定制图形,而不必过多考虑从哪里开始以及如何编写代码。此外,我认为这也是可视化统计报告并获得有用见解的有力工具。虽然我已经知道它几天了,但我发现它很方便,并决定在未来进一步了解它。你也可以和我一起阅读下面的文档:

https://ggplot2-book.org/annotations.html

祝你好运!

文本生成模型微调指南:GPT 新协议、GPT 新协议和 T5

原文:https://towardsdatascience.com/guide-to-fine-tuning-text-generation-models-gpt-2-gpt-neo-and-t5-dc5de6b3bc5e?source=collection_archive---------1-----------------------

通过大规模语言模型的基础,我们了解了不同的开源模型,然后通过针对情感检测任务对每个模型进行微调来比较它们。

照片由 Marija Zaric 在 Unsplash 上拍摄

本文使用的代码可以在这里找到——http://mohitmayank.com/a_lazy_data_science_guide/natural_language_processing/GPTs/#finetuning-gpt-2-for-sentiment-classification和* T5 。要阅读更多关于文本生成模型的内容,请参见http://mohitmayank.com/a_lazy_data_science_guide/natural_language_processing/text_generation/。更多此类文章请访问我的网站https://mohitmayank.com/blog/**或者看看我的 最新数据科学简书 。也可以在LinkedIn上和我联系。***

介绍

最近在自然语言处理方面的研究导致了多个大规模预训练文本生成模型的发布,如 GPT-{1,2,3},GPT-{Neo,J}和 T5。如果观众(包括你和我)对他们的可调参数大小达到数十亿没有印象,我们会被他们可以轻松地用于一个全新的看不见的任务而着迷,而无需任何训练!虽然这对于快速实验来说是可以的,但是对于任何实际的生产部署来说,仍然建议为特定的任务进一步训练模型。这被称为微调,在本文中,我们将实际学习微调一些目前可用的最好的语言模型的方法。我们还将通过在 Twitter 情感检测数据集上进行微调来比较它们的性能。我们开始吧!

文本生成模型

在 NLP 中,文本生成是一项有趣的任务,其目的是在输入提示时生成文本。通常,我们应用某种形式的序列到序列模型来完成这项任务。它们被称为语言模型,因为它们可以用来根据前面的句子预测下一个单词。最近对该领域的兴趣激增是由于两个主要原因,(1)几个高性能预训练模型的可用性,以及(2)很容易将大量基于 NLP 的任务转换为文本输入文本输出类型的问题。T5 作者非常直观地展示了这一点,他们可以使用相同的模型进行语言翻译、文本回归、摘要等。

T5 文本到文本框架示例。来源:谷歌 AI 博客

在本文中,我们将关注以下模型,

  • GPT-2: 是 OpenAI 发布的原系列语言模型的第二次迭代。事实上,这一系列的 GPT 模型使语言模型出名了!GPT 代表“生成式预训练变压器”,目前我们有 3 个版本的模型(v1,v2 和 v3)。其中只有 GPT 1 号和 GPT 2 号是开源的,因此我们将选择最新的版本进行实验。在技术方面,GPT-2 的体系结构由变压器体系结构的解码器部分组成。
  • ****GPT-尼奥:该模型由 EleutherAI 发布,以对抗未开源的 GPT-3 模型。该架构与 GPT-3 非常相似,但训练是在 825 GB 大小的文本数据集上进行的。
  • T5: 代表“文本到文本转换转换器”,是谷歌对开源语言模型的回应。T5 论文展示了使用完整的编码器-解码器架构(变压器的)比仅使用解码器(如 GPT 系列所做的)更好,因此他们保持了原始变压器架构的真实性。

不同型号的简要比较如下所示。需要注意的一点是,每个模型根据可调参数大小进一步发布了几个版本。对于这篇文章,我们将选择 117 米大小的 GPT-2,125 米大小的 GPT-Neo 和 220 米大小的 T5。

比较不同的文本生成模型。来源:[ 一个懒惰的数据科学指南

情感检测任务和数据集

为了测试不同语言模型的性能,我们将在一个简单的任务——情感检测上进行微调后,比较模型的准确性。这里,我们将使用 Twitter 情感数据集,可以从这里下载。它总共包含超过 160 万条推文,他们的情绪可能是积极的,也可能是消极的。为了提高计算效率,我们将对 10k 条 tweetss 进行采样,这些 tweet 的情感类别分布几乎相等。然后,我们将使用 95%的数据训练模型,将剩余的 5%用于测试目的。为了公平比较,我们将对所有三个模型使用相同的测试和训练分割。最后,我们将执行 3 次分割和训练每个模型的试验——这是一种复制 3 重验证测试的方法。我们将报告单独的和合计的(平均)f1 宏观分数,该分数可用于模型的性能比较。

Twitter 情感数据集示例。按作者。

现在,下一个明显的问题应该是,我们如何将情感检测任务转换为文本生成任务?答案很简单,我们所要做的就是创建一个直观的提示(带有数据的模板),它可以反映类似的表示如何出现在 web 上。让我们这样理解吧,我们希望提供 tweet 作为输入,希望将情绪作为输出。因此,在我们的提示中,我们应该在Tweet: 前缀后传递一条 tweet,并期望模型预测Sentiment: 前缀后下一行的情绪。这种创建有效提示的过程被称为提示工程,事实证明,仅仅通过改变提示,语言模型就能表现得更好!对于我们的用例,我们可以从一个非常简单的提示格式开始。我们将有两个不同的提示,一个用于培训,一个用于测试。示例如下所示。

训练提示(就像我们希望模型学习这种“模式”来解决“任务”)

**Tweet: I am not feeling well.
Sentiment: Negative**

测试提示(现在我们希望模型已经学习了“任务”,因此可以完成“模式”)

**Tweet: I am feeling well.
Sentiment:** 

因此,在测试过程中,我们将提取前缀Sentiment:后由模型预测的单词,并将该单词视为预测的情感标签。现在让我们深入到实现中!

微调 GPT 2 号和 GPT 近地天体

需要注意的一点是——GPT-2 和 GPT-近地天体共享几乎相同的架构,因此大部分微调代码保持不变。因此,为了简洁起见,我将只分享 GPT-2 的代码,但我会指出使其适用于 GPT-近地天体模型所需的更改。好了,让我们从处理数据集开始,为此我们将从创建 Pytorch Dataset类开始,它定义了我们如何为训练准备数据。

这包括 3 个模块:

  • __init__:我们基本上标记和存储数据的地方。
  • __len__ :这里我们返回总数据集的长度。这是每个时期内步长计算所需要的。
  • __getitem__ :获取一个数据,然后返回。

一些附加点— (1)在第 8 行,我们定义了用于将原始数字情感标签转换为文本标签的映射,(2)在第 12 行,我们将数据转换为我们决定的训练提示,以及(3)在第 14 行,我们执行了标记化(将 tweet 拆分为标记+用它们唯一的 id 替换它们)。

接下来,我们用Dataset类连接数据。代码分解如下所示,

  • Line 4-8:我们从加载数据集开始。你可以从这里下载,并在第 4 行修改本地路径。接下来,我们只需对相关的列进行子集划分,并对它们进行重命名。在第 8 行,我们为这个实验采样了 10k 条 tweets。
  • Line 10–13:我们将数据拆分为训练和测试,分别有 95%和 5%的拆分。我们使用stratify标志,使得分裂在情感类别分布中是均匀的。
  • Line 16:我们将列车数据传递给SentimentDataset类。注意,我们可以对测试数据做同样的事情,但是我只是以原始形式返回测试数据。

现在我们将为模型的训练做准备。代码分解如下:

  • 我们加载标记器,添加一些特殊的标记来表示 tweets 的不同部分,最后加载模型。注意,model_name 是在第 5 行定义的。还要注意的是,我们添加了特殊的标记,以便模型知道提示的开始和结束。这将有助于稍后的测试阶段,因为我们不希望模型继续写下一个单词,但它应该知道何时停止这个过程。这可以通过设置eos_token 并训练模型在标签后预测它来完成,如这里所做的。
  • Line 16:使用我们之前定义的函数加载并准备数据集。
  • Line 21–24:我们为培训流程设置配置。简而言之,我们用batch_sizewarmup_stepsweight_decay定义了在哪里和什么时候保存模型、训练多长时间和在哪里保存日志以及训练策略。
  • Line 27–31: 我们通过将模型与训练数据集相连接来开始训练。我们还定义了如何在data_collator中处理训练数据。排序器中的前两个元素是input_ids —标记化的提示和attention_mask —一个简单的 1/0 向量,表示标记化向量的哪一部分是提示,哪一部分是填充。最后一部分非常有趣,我们将输入数据作为标签传递,而不仅仅是情感标签。这是因为我们正在训练一个语言模型,因此我们希望模型学习提示的模式,而不仅仅是情感类。在某种意义上,模型学习预测输入 tweet +提示中结构化的情感的单词,并在这个过程中学习情感检测任务。

这将开始训练。根据您的计算机规格,这可能需要一些时间。

最后,我们定义测试块,在这里我们获取训练好的模型,并将其应用于保留的测试数据。代码细分如下:

  • Line 5:我们打开模型上的评估模式。
  • Line 8–15:对于每个测试数据,我们首先准备提示,但有一个很大的不同,我们不包括情绪标签,因为这是我们希望模型预测的。此外,记住eos_token——我们希望模型能够预测情感标签,然后通过打印eos_token来中断操作。最后,我们对测试提示进行标记。
  • Line 17:我们采用测试提示,预测下一组单词。这个函数中有很多参数定义了如何预测下一个单词。关于它们中每一个的详细内容,请参考这个,或者为了更好地理解下一个单词预测的不同策略,请参考这个。
  • Line 20–30:我们从解码预测文本开始,即将预测标记 id 重新转换为文本。然后,我们提取预测的情感标签并将所有相关信息存储到列表中。
  • Line 33–37:我们首先将所有提取的信息合并到一个 pandas 数据帧中以获得更好的可读性,然后使用 sklearn 包中的f1_score 函数来计算整个模型的性能。

在运行 GPT-2 的代码并在数据集分割代码中使用不同的random_state执行该操作三次时,我们观察到该模型实际上能够如预期的那样完美预测。它能够预测标签,然后使用eos_token中断标签的执行。f1 宏观表现平均分 81.7% !这与我们预期的专用情感检测模型的表现相当,并且这继续强调了在 NLP 中使用文本生成模型进行迁移学习是多么容易。

符合 GPT-尼奥标准的代码

为了使 GPT-2 号代码适用于 GPT-近地天体,我们必须做以下修改,

  • 进口GPTNeoForCausalLM
  • model_name 设置为"EleutherAI/gpt-neo-2.7B" (从任何可用尺寸型号中选择)
  • 加载模型时,使用GPTNeoForCausalLM 代替GPT2LMHeadModel

就是这样!在运行 GPT-尼奥的修改代码,并遵循相同的训练策略时,平均 f1 宏观性能得分为 80.7%

微调 T5

T5 的架构不同于 GPT 模型,因为它保持了原始变压器的架构,而 GPT 模型只保留了解码器部分。对于培训 T5,我们将使用一个名为 SimpleT5 的优秀包装器包,它从培训阶段移除了大部分样板文件。现在请记住,虽然培训的语法会发生变化,但总体流程和直觉保持不变。先说数据部分。

这里,大部分代码与我们之前为 GPT 模型所做的一样。一个主要的变化是我们不需要Dataset类,因为 SimpleT5 直接在 pandas 数据帧上工作。因此,我们加载数据,做一些初步的预处理,分割数据,并返回熊猫数据帧。(无需令牌化,创建 *Dataset* 类,这不是很棒吗!?)

还有一点需要注意的是,我们不需要为这个包创建提示格式。这样,我们可以将输入的 tweet 和情感标签分离到不同的列中,这里分别是source_texttarget_text

加载和训练模型也非常简单,只需 3 行代码(如果你可以忽略我漂亮的换行)。

接下来,我们在测试数据集上测试微调后的 T5 模型。如你所见,推理部分也非常简单,在第 11 行,我们使用了predict 函数,只需传递source_text 就可以得到预测的情感标签。我们稍后将它与original_label 进行比较,以在第 18 行生成性能分数。

在运行 T5 代码并遵循与之前相同的训练策略时,f1 宏观表现的平均得分为 80.7%

结果

将所有结果合并到一个表中,我们得到,

GPT-2、GPT-尼奥和 T5 在情感探测任务上的比较。

我想讨论的一点是,我根本没有玩过超参数。除此之外,prompt 工程方法学,我认为仅仅通过研究这两个方面,我们就可以进一步提高所有模型的性能指标。我会把它留给读者做练习(如果你得到了更好的分数,一定要让我知道!)

结论

虽然 GPT-2 可能赢得了这一轮,但结果表确实显示了文本生成模型的整体实力。他们所有人在情感检测任务上都表现得非常好,所需要的只是几个时期的训练。即使这个实验是为一个单一的任务而做的,我希望这有助于展示使用 TG 模型来完成全新的任务是多么容易。在某种程度上,如果我们可以将 NLP 问题转化为文本生成问题,请放心,预先训练的模型不会失败,至少不会彻底失败:)这使得它们成为许多任务的完美基线,如果不是最先进的。

参考

  • 科林·拉弗尔,诺姆·沙泽尔,Adam Roberts,凯瑟琳·李和莎兰·纳朗。用统一的文本到文本转换器探索迁移学习的局限性。2020. arXiv:1910.10683
  • 亚历克·拉德福德、杰弗里·吴、雷文·柴尔德、大卫·栾、达里奥·阿莫代伊、伊利亚·苏茨基弗等。语言模型是无人监督的多任务学习者。 OpenAI 博客,1(8):9,2019。
  • GPT 近地天体
  • Ashish Vaswani、Noam Shazeer、Niki Parmar、Jakob Uszkoreit、Llion Jones、Aidan N. Gomez、Lukasz Kaiser 和 Illia Polosukhin。你需要的只是关注。2017. arXiv:1706.03762 。

干杯。

热切的数据科学家用 Dask 评估懒惰的指南

原文:https://towardsdatascience.com/guide-to-lazy-evaluation-with-dask-543b48a0aa74?source=collection_archive---------59-----------------------

在 Unsplash 上由 Manja Vitolic 拍摄的照片

懒惰评估不必令人困惑或复杂——在本指南中,学习入门所需的基本概念!

声明:我是 Saturn Cloud 的一名高级数据科学家,Saturn Cloud 是一个支持使用 Dask 对 Python 进行简单并行化和扩展的平台。如果你想了解更多关于土星云的信息,请登陆网站 www.saturncloud.io 访问我们。

Dask 是什么?

Dask 是一个开源框架,支持 Python 代码的并行化。这可以适用于各种 Python 用例,不仅仅是机器学习。Dask 设计用于单机设置和多机集群。您可以将 Dask 与 pandas、NumPy、scikit-learn 和其他 Python 库一起使用。

为什么要并行?

对于机器学习,Dask 并行化在几个领域可能有助于我们更快更好地工作。

  • 加载和处理大型数据集(尤其是当它们太大而无法保存在内存中时)
  • 同时快速运行时间或计算繁重的任务(例如,考虑超参数调整或集合模型)

延迟任务

并行计算使用所谓的“懒惰”评估。这意味着您的框架将把转换或计算集合排队,以便它们准备好以后并行运行。这是一个你会在很多并行计算框架中发现的概念,包括 Dask。你的框架不会评估请求的计算,直到被明确告知。这不同于“急切”评估函数,后者在被调用时立即计算。许多非常常见和方便的函数被移植到 Dask 中,这意味着它们将是懒惰的(延迟计算),甚至不需要你去问。

然而,有时您会有用 pandas、scikit-learn 甚至是基本 python 编写的复杂的定制代码,而这些代码在 Dask 中是不可用的。其他时候,如果需要利用原生 Dask 元素进行编辑,您可能没有时间或精力将代码重构为 Dask。

如果是这种情况,你可以用@dask.delayed修饰你的函数,它会手动建立函数应该是懒惰的,直到你告诉它才求值。您可以用下一节中描述的过程.compute().persist()来告诉它。

示例 1

def exponent(x, y):
    '''Define a basic function.'''
    return x ** y# Function returns result immediately when called
exponent(4, 5)

1024

import dask@dask.delayed
def lazy_exponent(x, y):
    '''Define a lazily evaluating function'''
    return x ** y# Function returns a delayed object, not computation
lazy_exponent(4, 5)

延迟(' lazy _ exponent-05d 8b 489–554 c-44 E0–9a2c-7a 52 b 7 B3 a 00d ')

# This will now return the computation
lazy_exponent(4,5).compute()

1024

示例 2

我们可以利用这些知识并扩展它——因为我们的惰性函数返回一个对象,我们可以对它赋值,然后在以后以不同的方式将它链接在一起。

这里我们从第一个函数返回一个延迟值,并将其称为 x。然后我们第二次将 x 传递给该函数,并将其称为 y。最后,我们将 x 和 y 相乘以产生 z。

x = lazy_exponent(4, 5)
y = lazy_exponent(x, 2)
z = x * y
z

延迟(' mul-2257009 fe1a 612243 C4 b 28012 eddd 1 ')

z.visualize(rankdir="LR")

作者

z.compute()

1073741824

持久与计算

我们应该如何指示 Dask 运行我们已经懒洋洋地排队等候的计算?我们有两个选择:.persist().compute()

计算

如果我们使用.compute(),我们要求 Dask 对我们排队等候的数据进行所有的计算和调整,然后运行它们,并把它们全部带到这里。

这意味着如果它是分布式的,我们现在就想把它转换成一个本地对象。如果它是一个 Dask 数据帧,当我们调用.compute()时,我们说“运行我们排队的转换,并立即将它转换成 pandas 数据帧。”但是要小心——如果你的数据集非常大,这可能意味着你没有足够的内存来完成这个任务,你的内核可能会崩溃!

坚持

如果我们使用.persist(),我们要求 Dask 对我们排队的数据进行所有的计算和调整,并运行它们,但是对象将保持分布式,并将驻留在集群上(如果您在一台机器上,则为 LocalCluster),而不是 Jupyter 实例或其他本地环境上。

因此,当我们使用 Dask 数据帧执行此操作时,我们会告诉我们的集群“运行我们已排队的转换,并将其作为分布式 Dask 数据帧。”

因此,如果您想处理应用于 Dask 对象的所有延迟任务,这两种方法都可以。区别在于你的对象最后会住在哪里。

理解这一点真的有助于告诉你什么时候.persist()可能有意义。考虑这样一种情况,您加载数据,然后将数据用于许多复杂的任务。如果您使用从磁盘上的 CSV 加载的 Dask 数据帧,您可能希望在将该数据传递给其他任务之前调用.persist(),因为其他任务将在每次引用它时反复运行数据加载。如果您首先使用.persist(),那么加载步骤只需要运行一次。

分布式数据对象

除了延迟单个函数之外,我们还需要讨论另一个工作领域——这就是 Dask 数据对象。其中包括 Dask bag(一个基于列表的并行对象)、Dask array(一个基于 NumPy 数组的并行对象)和 Dask Dataframe(一个基于 pandas Dataframes 的并行对象)。

为了展示这些对象能做什么,我们将讨论 Dask 数据帧。

假设我们有很多年的相同数据,我们想一次加载所有数据。我们可以用 Dask 轻松地做到这一点,这个 API 非常像 pandas API。Dask 数据帧包含许多 pandas 数据帧,它们分布在集群中。

作者

示例 3

import dask
import dask.dataframe as dd
df = dask.datasets.timeseries()

这个数据集是 dask 安装附带的示例之一。请注意,当我们查看它时,我们只获得了部分信息!

df

这是因为我们的 dask 数据帧分布在我们的集群中,直到我们要求它被计算。但是我们仍然可以将延迟的计算排队!让我们使用我们的熊猫知识来应用一个过滤器,然后按一列对数据进行分组,并计算另一列的标准偏差。

请注意,这些代码在常规 pandas 数据帧的计算中不会出现任何问题。

df2 = df[df.y > 0]
df3 = df2.groupby('name').x.std()
df3

Dask 系列结构:
npartitions = 1
float 64

名称:x,dtype: float64
Dask 名称:sqrt,157 任务

这返回给我们的不是熊猫系列,而是 Dask 系列。这里有一个分区,所以它不会被不同的工人分割。它很小,所以这对我们来说没问题。

如果我们在上面运行.compute()会发生什么?

computed_df = df3.compute()
type(computed_df)

pandas . core . series . series

这使得我们的结果成为熊猫系列,因为它不再是一个分布式对象。结果内容实际上是什么样的?

computed_df.head()

姓名
爱丽丝 0.579278
鲍勃 0.578207
查理 0.577816
丹 0.576983
伊迪丝 0.575430
姓名:x,dtype: float64

实例 4

让我们回到上一个例子中使用的 df 对象。这里我们将使用npartitions属性来检查我们的数据帧被分成了多少部分。

import dask
import dask.dataframe as dd
df = dask.datasets.timeseries()
df.npartitions

所以我们的 Dask 数据帧有 30 个分区。因此,如果我们在这个数据帧上运行一些计算,我们仍然有一个具有许多分区属性的对象,我们可以检查它。我们将对其进行过滤,然后使用 groupby 进行一些汇总统计。

df2 = df[df.y > 0]
df3 = df2.groupby('name').x.std()
print(type(df3))
df3.npartitions

现在,我们已经将对象简化为一个系列,而不是一个数据帧,因此它更改了分区号。

如果我们想的话,我们可以看这个系列!

df4 = df3.repartition(npartitions=3)
df4.npartitions

如果我们在这些对象上使用.persist().compute()会发生什么?

正如我们下面看到的,df4是一个 Dask 系列,有 161 个排队任务和 3 个分区。我们可以在同一个对象上运行两个不同的计算命令,并看到不同的结果。

df4

Dask 系列结构:
npartitions = 3
float 64



名称:x,dtype: float64
Dask 名称:重新分区,161 任务

%%timedf4.persist()

CPU 时间:user 1.8 s,sys: 325 ms,total:2.12s
Wall time:1.25s
Dask 系列结构:
npartitions = 3
float 64



Name:x,dtype:float 64
Dask Name:repartition,3 tasks

那么,当我们运行.persist()时,发生了什么变化?请注意,我们从屏幕底部的 161 项任务减少到只有 3 项。这表明每个分区都有一个任务。

现在,我们来试试.compute()

%%time
df4.compute().head()

CPU 时间:user 1.8 s,sys: 262 ms,total:2.06s
Wall time:1.2s
Name
Alice 0.576798
Bob 0.577411
Charlie 0.579065
Dan 0.577644
Edith 0.577243
Name:x,dtype: float64 【T36

我们得到的是熊猫系列,而不是 Dask 对象。

结论

至此,您已经有了使用 Dask 所需的基本概念!

  • 您的定制代码可以通过@dask.delayed实现并行化
  • Dask 的生态系统对 pandas、NumPy 和 scikit-learn 功能提供了强大的本地支持,赋予了它们并行化能力
  • Dask 数据对象可以使你的数据分布,防止数据过多/内存过少的问题

通过结合这些强大的特性,您可以使用我们用于 pandas、NumPy 和 scikit-learn 的相同 API 来生成强大的、生产质量的数据管道。要了解 Dask 的更多功能,请访问我们的 Saturn Cloud,了解我们的客户在 Dask 上取得的成功!

R 降价指南

原文:https://towardsdatascience.com/guide-to-r-markdown-8468e6464bb4?source=collection_archive---------20-----------------------

如果你正在寻找一个工具来呈现一个整洁有效的报告,R markdown 是一个理想的选择!

科琳·库兹在 Unsplash 上的照片

简介

为了我的研究,我已经做了很多报告,包括用 R 编码和注释我的代码。R markdown 是完成这些报告的一个很好的支持工具。它可以把你的代码、结果和你的评论放在一个地方。然后,只需点击一个按钮,它就可以帮助以 pdf、Word 等不同格式呈现输出。

除了是我研究的一个很好的工具,R markdown 也是决策者的理想选择,他们希望从结果中寻求洞察力,但不想深入研究背后的代码。因此,在本文中,让我们来探索这个方便的工具。

如何开始

您可以创建一个新的。RStudio 中的 Rmd 文件,方法是转到文件>新建文件> R Markdown。

降价基础

如果您理解了下面的基础知识,那么您已经成功地生成了第一个 R markdown 文件:

  1. 代码块
  2. 不同类型的文本格式:标题、字体等。

HTML 格式的降价示例如下:

图 1:来自 RStudio 的默认 R markdown 文件

现在,让我们进入每一部分。

文本格式

Markdown helps to create different text formats, such as:- **Headings**# 1st Level Header
## 2nd Level Header
Markdown helps to create different text formats, such as:- **Headings**# 1st Level Header
## 2nd Level Header
### 3rd Level Header
#### 4th Lever Header- **Italic**  
*italic* or _italic_- **Bold**  
**bold**   __bold__- **Superscript**  
superscript^2^- **Subscript**  
subscript~2~We can also use markdown to make:- **Latex Equation**  
$\frac{1}{n} = n^{2}$- **Bibliography, footnotes, citations**  
[rmarkdown cheatsheet]([https://rmarkdown.rstudio.com/authoring_quick_tour.html#Overview](https://rmarkdown.rstudio.com/authoring_quick_tour.html#Overview)) [^1][^1]: R-base- **Table**Col1          | Col2
------------- | -------------
Content Col1  | Content Col2
Content Col1  | Content Col2

输出:

图 1

更多参考,可以在这个链接了解。

代码块

要添加新的代码块,您可以使用 Ctrl + Alt + I 或通过以下方式手动创建它:

```{r}
code

若要执行此代码,请单击“运行”或按 Ctrl + Shift + Enter。

代码块有以下本地选项:

`include = FALSE`不允许代码及其结果出现在最终文件中。R Markdown 仍然运行代码片段中的代码,并且结果可以被其他代码片段使用。

`echo = FALSE`不允许代码,但允许结果出现在最终文件中。

`message = FALSE` 不允许代码生成的消息出现在最终文件中。

`warning = FALSE` 不允许代码生成的警告出现在最终文件中。

`fig.cap = "..."`给最终图形添加标题。

我将向您展示所有这些是如何工作的示例。

library(ggplot2)data = stormsggplot(data = data,
       mapping = aes(x = pressure, y = wind, color = status)) +
  geom_point( alpha = 0.3,
              size = 2) +
  labs(title = "Relationship Between Wind and Pressure of Storms",
       subtitle = "By Chi Nguyen",
       caption = "Source:dplyr package",
       x = " Pressure",
       y = "Wind",
       color = "Type of Storms") + 
  theme_set(theme_bw())```

图 2:大块代码

使用 R 参数

R Markdown 文档可能包括许多在报告时设置的参数。当您想要使用新的输入值重新呈现类似的报表时,参数非常有用,例如:

  • 运行特定于部门或地理区域的报告。
  • 运行涵盖特定时间段的报告。
  • 等等。,

例如,在下面的减价中,params年= 1975 年。然后,在格式params$<paramname>下的代码中使用。

---
title: "R markdown"
author: "Chi Nguyen"
date: "9/17/2021"
output: html_document
params: 
  year: '1975'
---```{r, message = FALSE}library(dplyr)
data = storms 
count_storm_75 = length(data$status[which(data$year == params$year)])
count_storm_75 ```

图 3:使用参数

您还可以为参数设置约束:

图 4:为参数设置约束

结论

R markdown 中有大量有趣的特性,你可以在这本有用的食谱链接中详细阅读它们。R markdown 可以执行很多其他语言的代码,比如 Python、SQL、Bash、Rcpp、Stan、JavaScript、CSS 等。我觉得这是一个很好的学习工具,以后一定会帮助你完成很多工作。

Python 中海量三维点云实时可视化指南

原文:https://towardsdatascience.com/guide-to-real-time-visualisation-of-massive-3d-point-clouds-in-python-ea6f00241ee0?source=collection_archive---------0-----------------------

3D Python

Python 中大点云数据的高级可视化和交互教程。(奖金)学习如何创建一个交互式分割“软件”。

数据可视化是一个大难题🌶️:通过使用可视元素制作信息的图形表示,我们可以最好地呈现和理解数据中的趋势、异常值和模式。你猜对了:对于表示真实世界形状的 3D 点云数据集,这是强制性的🙂。

本文中处理和可视化的无人机 3D 点云。您将学习特征提取、交互式和自动分割,同时实时可视化和创建动画。F. Poux

然而,当从激光扫描仪或 3D 重建技术(如摄影测量)收集时,点云对于经典渲染来说通常过于密集。在许多情况下,数据集将远远超过 1000 万大关,这使得它们对于经典的可视化库(如 Matplotlib)来说不切实际。

你可以注意到左边(Open3D)比右边(PPTK)慢多了,后者使用八叉树结构来加速可视化。Matplotlib 会更糟😅。F. Poux

这意味着我们经常需要跳出 Python 脚本(因此使用 I/O 函数将数据写入文件)并在外部可视化它,这可能会成为一个超级麻烦的过程🤯。我不会说谎,我在论文的第一年就是这么做的,试图猜测特定 algorithms🥴.的结果

在你的脚本中直接可视化这些点云不是很好吗?更好的是,将视觉反馈与脚本联系起来?想象一下,现在有了 iPhone 12 Pro 有了激光雷达;您可以创建一个完整的在线应用程序!好消息是,有一种方法可以在不脱离 Python 环境和 IDE 的情况下实现这一点。☕准备好了吗?

步骤 1:启动您的 Python 环境。

在下面的前一篇文章中,我们看到了如何使用 Anaconda 轻松地设置环境,以及如何使用 IDE Spyder 管理您的代码。如果你准备成为一名完全成熟的 python 应用程序开发人员,我建议你继续这样做😆。

如果您使用 Jupyter Notebook 或 Google Colab,脚本可能需要一些调整,以使可视化后端工作,但提供不稳定的性能。如果您想继续使用这些 IDE,我建议您看看第 4 步中给出的库的替代品。

步骤 2:下载点云数据集

在之前的教程中,我展示了通过使用摄影测量和来自开阔地形的航空激光雷达获得的 3D 数据集上的点云处理和网格划分。我将跳过下面文章中涉及的激光雷达 I/O 细节,直接使用高效的。las 文件格式。

只是这一次,我们将使用空中无人机数据集。它是通过摄影测量获得的,让一架小型 DJI 幻影 Pro 4 在我们的大学校园内飞行,收集一些图像,并进行摄影测量重建,如这里所解释的。

以下链接提供的 3D 点云来自 DJI Phantom 4 飞行,随后是摄影测量重建过程。F. Poux

🤓 注意 : 对于这个操作指南,你可以使用这个库中的点云,我已经过滤和转换过了,这样你就处于最佳状态了。如果你想在不安装任何东西的情况下预先可视化并使用它,你可以查看一下 webGL 版本。

步骤 3:在脚本中加载点云

我们首先在脚本中导入必要的库(NumPy 和 LasPy),并加载。las 文件中一个名为point_cloud的变量。

import numpy as np
import laspy as lp
input_path="D:/CLOUD/POUX/ALL_DATA/"
dataname="2020_Drone_M"
point_cloud=lp.file.File(input_path+dataname+".las", mode="r")

很好,我们差不多准备好了!最棒的是,LasPy 库还为变量point_cloud提供了一个结构,我们可以使用简单的方法来获取,例如,X、Y、Z、红色、蓝色和绿色字段。让我们这样做来分离坐标和颜色,并把它们放在 NumPy 数组中:

points = np.vstack((point_cloud.x, point_cloud.y, point_cloud.z)).transpose()
colors = np.vstack((point_cloud.red, point_cloud.green, point_cloud.blue)).transpose()

🤓

步骤 4(可选):最终预处理

如果您的数据集太大,或者您想在二次抽样版本上进行试验,我建议您查看下面的文章,它给出了实现这一任务的几种方法:

**

或以下形成广泛的点云训练:

https://learngeodata.eu/point-cloud-processor-formation/

为了方便起见,如果您有超过 1 亿个点的点云,我们可以使用以下方法快速切片您的数据集:

factor=10
decimated_points_random = points[::factor]

🤓 注意 : 运行这个将每 10 行保留 1 行,从而将原始点云的大小除以 10。

第五步:选择你的观想策略。

现在,让我们选择如何可视化我们的点云。老实说,虽然可视化本身可以避免繁琐的 I/O 操作,但是能够在 Python 中包含一些可视化交互和处理工具是一个很好的补充!因此,我推荐的解决方案是使用一个点云处理工具包,它可以实现这一点甚至更多。如果你想探索其他的可能性,我还是会给你其他的选择,⚖️.

解决方案 A(保留):PPTK

PPTK 包有一个三维点云查看器,它直接将一个 3 列的 NumPy 数组作为输入,可以交互式地可视化 1 千万到 1 亿个点。它通过使用八叉树来剔除视见体外部的点并将远处的点组近似为单个点,从而减少了每帧中需要渲染的点的数量。

模拟八叉树结构中的平截头体剔除。来源:虚拟现实(VR)环境下海量 3D 点云的分类与集成。

首先,您可以使用 Pip 管理器简单地安装该库:

pip install pptk

然后,您可以通过输入以下命令,从点云中可视化您之前创建的points变量:

import pptk
import numpy as np
v = pptk.viewer(points)

在启动时,查看器将输入点组织成八叉树。当视点被操纵时,八叉树被用于将远处的点组近似为单个点,并在视见平截头体之外剔除点,从而显著减少了被渲染的点的数量。一旦视点不再有变化,观察者就开始执行更耗时的点的详细渲染。F. Poux

你不认为我们漏掉了一些颜色吗?让我们通过在控制台中键入以下命令来解决这个问题:

v.attributes(colors/65535)

PPTK 查看器中带有颜色信息的 3D 点云。F. Poux

🤓 : 我们的颜色值是从。las 文件。我们需要[0,1]区间内的值;因此,我们除以 65535。

这是更好的方式!但是,如果我们也想可视化额外的属性呢?嗯,你只要把你的属性链接到你的路径上,它就会动态更新。

预先计算的几个属性的可视化示例。

💡 提示: 不要最大化窗口大小,以保持 30 FPS 以上的良好帧率。目标是拥有最好的执行运行时,同时拥有可读的脚本

您还可以将窗口参数化,以显示与特定色带相关的每个属性,管理点大小,将背景设为黑色,不显示网格和轴信息:

v.color_map('cool')
v.set(point_size=0.001,bg_color=[0,0,0,0],show_axis=0,show_grid=0)

备选方案 B:开放 3D

对于想用 Python 读取和显示点云的优秀替代方案的人,我推荐 Open3D。您也可以使用 Pip 软件包管理器来安装必要的库:

pip install open3d

如果您想扩展 3d 网格操作的知识,我们已经在下面的教程中使用了 Open3d:

</5-step-guide-to-generate-3d-meshes-from-point-clouds-with-python-36bad397d8ba>

这将在您的机器上安装 Open3D,然后您将能够通过执行以下脚本来读取和显示您的点云:

import open3d as o3dpcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(points)
pcd.colors = o3d.utility.Vector3dVector(colors/65535)
pcd.normals = o3d.utility.Vector3dVector(normals)o3d.visualization.draw_geometries([pcd])

在 Open3D 中可视化的三维点云。请注意法线是如何很好地用来增强几何图形的视觉效果的。F. Poux

Open3D 实际上正在发展,您可以通过一些有趣的方式来显示点云,以填充最终的孔洞,如创建体素结构:

voxel_grid = o3d.geometry.VoxelGrid.
create_from_point_cloud(pcd,voxel_size=0.40)o3d.visualization.draw_geometries([voxel_grid])

点云的 3D 体素表示,其中每个体素表示一个 40×40cm 的立方体。F. Poux

🤓 : 为什么 Open3d 不是此时的选择?如果您处理的数据集少于 5000 万个点,那么这就是我推荐的。如果您需要这个阈值以上的交互式可视化,我建议要么出于可视化目的对数据集进行采样,要么使用 PPTK,这对于可视化更有效,因为您已经为此目的创建了八叉树结构。

其他(对 Colab 友好的)替代品:Pyntcloud 和 Pypotree

如果您希望能够对点云数据进行简单和交互式的探索,而不管使用哪种传感器来生成它,也不管用例是什么,我建议您查看 Pyntcloud 或 PyPotree 。这些将允许你在你的笔记本上观想点云,但是要小心表演!Pyntcloud 实际上依赖于 Matplotlib,PyPotree 要求 I/O 操作;因此,两者实际上都不是超高效的。尽管如此,我还是想提到它们,因为对于小的点云和 Google Colab 中的简单实验,你可以整合可视化。一些例子:

### PyntCloud ###
conda install pyntcloud -c conda-forge
from pyntcloud import PyntCloudpointcloud = PyntCloud.from_file("example.ply")
pointcloud.plot()### PyntCloud ###
pip install pypotreeimport pypotree 
import numpy as np
xyz = np.random.random((100000,3))
cloudpath = pypotree.generate_cloud_for_display(xyz)
pypotree.display_cloud_colab(cloudpath)

步骤 6:与点云交互

回到 PPTK。要进行交互式选择,比如停车场上的汽车,我将移动我的相机俯视图(快捷键是7),我将拖动一个矩形选择按住Ctrl + LMB进行选择。

💡 提示: 如果您对选择不满意,一个简单的 RMB 将擦除您当前的选择。是的,您可以进行多项选择😀。

做出选择后,您可以返回 Python 控制台,然后获取赋值的点标识符。

selection=v.get('selected')

这实际上会返回一个 1D 数组,如下所示:

选择是一个数组,包含每个选定点的索引。F. Poux

您实际上可以扩展这个过程,一次选择多个元素(Ctrl + LMB),同时细化选择,删除特定的点(Ctrl + Shift + LMB)。

从点云创建多个选择。F. Poux

在此之后,在保存所选点索引的selection变量上交互应用一系列过程变得毫不费力。

让我们复制一个场景,其中您自动在地面和非地面元素之间优化您的初始选择(汽车)。

步骤 7:走向自动分段

在包含完整点云的查看器中,存储在变量v中,我做出如下选择selection=v.get('selected'):

步骤 1:我们从初始三维点云中选择点。F. Poux

然后计算每个点的法线。为此,我想说明使用 PPTK 的另一个关键要点:函数estimate_normals,它可用于基于半径搜索或 k 最近邻获得每个点的法线。不用担心,我将在另一个指南中深入说明这些概念,但目前,我将使用 6 个最近的邻居来运行它,以估计我的法线:

normals=pptk.estimate_normals(points[selection],k=6,r=np.inf)

💡 提示: 记住 selection 变量保存点的指数,即点云中的“线号”,从 0 开始。因此,如果我只想在这一点子集上工作,我将把它作为 points[selection]传递给。然后,我为每个点选择仅使用 6 个最近邻居的 k-NN 方法,通过也将半径参数设置为 np.inf ,这确保我不使用它。我也可以同时使用这两个约束,或者将 k 设置为 -1 ,如果我想进行纯半径搜索的话。

这将基本上返回以下内容:

每个点的法线示例。F. Poux

然后,我要对进行过滤,返回法线与 Z 轴不共线的原始点的指数。我建议使用以下代码行:

idx_normals=np.where(abs(normals[...,2])<0.9)

🤓 注释:The【,是 NumPy 的一种说法,说我只在我的 3×n 点矩阵的第三列工作,持有法线的 Z 属性。它相当于 normals[:,2] 。然后,因为我的法线没有取向(因此可以指向天空或地心),所以我以绝对值作为比较点,并且将使用功能np.where()仅保持符合条件 <0.9的那个。

为了使结果可视化,我创建了一个新的查看器窗口对象:

viewer1=pptk.viewer(points[idx_normals],colors[idx_normals]/65535)

自动正常过滤后的 3D 点云段。看看有些点是怎么在车顶和整个汽车结构上掉下来的。F. Poux

可以看出,我们还过滤了一些点部分的汽车。这可不好🤨。因此,我们应该将该过滤与另一个过滤相结合,以确保仅选择接近地面的点作为法线过滤的主体:

idx_ground=np.where(points[...,2]>np.min(points[...,2]+0.3))
idx_wronglyfiltered=np.setdiff1d(idx_ground, idx_normals)
idx_retained=np.append(idx_normals, idx_wronglyfiltered)viewer2=pptk.viewer(points[idx_retained],colors[idx_retained]/65535)

3D 点云会针对垂直法向接近初始段的最低 Z 值的点进行过滤。F. Poux

这真好!现在,您可以探索这种强大的思维方式,并结合任何过滤(例如在 RGB 上播放以消除剩余的草……)来创建一个完全交互式的分割应用程序。更好的是,可以结合 3D 深度学习分类!吼吼。但那是以后的事了😉。

步骤 8:用函数打包你的脚本

最后,我建议把你的脚本打包成函数,这样你就可以直接重用其中的一部分作为块。我们可以首先定义一个preparedata(),它将把任何.las点云作为输入,并格式化它:

def preparedata():
    input_path="D:/CLOUD/OneDrive/ALL_DATA/GEODATA-ACADEMY/"
    dataname="2020_Drone_M_Features"
    point_cloud=lp.file.File(input_path+dataname+".las", mode="r")
    points = np.vstack((point_cloud.x, point_cloud.y, point_cloud.z) 
    ).transpose()
    colors = np.vstack((point_cloud.red, point_cloud.green,
    point_cloud.blue)).transpose()
    normals = np.vstack((point_cloud.normalx, point_cloud.normaly, 
    point_cloud.normalz)).transpose()
    return point_cloud,points,colors,normals

然后,我们编写一个显示函数pptkviz,它返回一个查看器对象:

def pptkviz(points,colors):
    v = pptk.viewer(points)
    v.attributes(colors/65535)
    v.set(point_size=0.001,bg_color= [0,0,0,0],show_axis=0,
    show_grid=0)
    return v

此外,还有一个额外的好处,这里有一个函数cameraSelector,可以从打开的浏览器中获取相机的当前参数:

def cameraSelector(v):
    camera=[]
    camera.append(v.get('eye'))
    camera.append(v.get('phi'))
    camera.append(v.get('theta'))
    camera.append(v.get('r'))
    return np.concatenate(camera).tolist()

我们定义了computePCFeatures函数来自动细化您的交互式分割:

def computePCFeatures(points, colors, knn=10, radius=np.inf):
    normals=pptk.estimate_normals(points,knn,radius)
    idx_ground=np.where(points[...,2]>np.min(points[...,2]+0.3))
    idx_normals=np.where(abs(normals[...,2])<0.9)
    idx_wronglyfiltered=np.setdiff1d(idx_ground, idx_normals)
    common_filtering=np.append(idx_normals, idx_wronglyfiltered)
    return points[common_filtering],colors[common_filtering]

好了😁现在,您只需启动包含上述功能的脚本,并开始使用computePCFeaturescameraSelector和更多您的作品与您的选择进行交互:

import numpy as np
import laspy as lp
import pptk*#Declare all your functions here*if __name__ == "__main__":
    point_cloud,points,colors,normals=preparedata()
    viewer1=pptkviz(points,colors,normals)

然后很容易调用脚本,然后使用控制台作为实验的工作台。例如,我可以保存几个摄像机位置并创建一个动画:

cam1=cameraSelector(v)
*#Change your viewpoint then -->* cam2=cameraSelector(v)
*#Change your viewpoint then -->* cam3=cameraSelector(v)
*#Change your viewpoint then -->* cam4=cameraSelector(v)poses = []
poses.append(cam1)
poses.append(cam2)
poses.append(cam3)
poses.append(cam4)
v.play(poses, 2 * np.arange(4), repeat=True, interp='linear')

点云 PPTK 内 4 个关键帧之间的线性插值。F. Poux

结论

您刚刚学习了如何导入、可视化和分割由 3000 多万个点组成的点云!干得好!有趣的是,直接在 GPU 上执行的点云片段和单个点的交互选择现在可以用于点云实时编辑和分割。但这条路并没有到此为止,未来的帖子将更深入地探讨点云空间分析、文件格式、数据结构、分割[2–4]、动画和深度学习1。我们将特别关注如何管理大点云数据,如下面的文章中所定义的。

我的贡献旨在浓缩可操作的信息,以便您可以从零开始为您的项目构建 3D 自动化系统。你可以从今天开始在地理数据学院参加一个编队。

https://learngeodata.eu/point-cloud-processor-formation/

参考

  1. Poux,F. ,& J.-J Ponciano。(2020).三维室内点云实例分割的自学习本体。国际摄影测量与遥感学会。拱门。Pho 的。&雷姆。B2,309–316;https://doi . org/10.5194/ISPRS-archives-XLIII-B2–2020–309–2020

  2. Poux,F. ,& Billen,R. (2019)。基于体素的三维点云语义分割:无监督的几何和关系特征与深度学习方法。ISPRS 国际地理信息杂志。8(5), 213;https://doi.org/10.3390/ijgi8050213

  3. Poux,F. ,纽维尔,r .,纽约,g .-a .&比伦,R. (2018)。三维点云语义建模:室内空间和家具的集成框架。遥感10 (9)、1412。https://doi.org/10.3390/rs10091412

  4. Poux,F. ,Neuville,r .,Van Wersch,l .,Nys,g .-a .&Billen,R. (2017)。考古学中的 3D 点云:应用于准平面物体的获取、处理和知识集成的进展。地学7 (4),96。https://doi.org/10.3390/GEOSCIENCES7040096**

Python 环境设置指南&理解 Python IDLE

原文:https://towardsdatascience.com/guide-to-setup-python-environment-understanding-python-idle-7ff3e00941d6?source=collection_archive---------12-----------------------

为您的第一个 Python 代码创建环境并开始编码

照片由 Hitesh Choudhary 拍摄自 Unsplash

介绍

在您的计算机上设置 python 环境是启动第一个 Python 脚本的第一步。有许多方法可以开始设置和安装,但是在本文中,我们将通过从官方 python 发行版—【python.org】下载来学习设置我们的 Python 环境。在设置好我们的 Python 环境之后,我们将会了解更多与 Python 安装捆绑在一起的 Python IDLE。( **本教程使用的操作系统是 Windows 上的*)

让我们开始设置我们的 Python 环境!

第 1 步—导航至 Windows 的python.org下载页面。

用于 Windows 的 Python 下载页面

步骤 2 —选择最新的 Python 3 版本(截止到本文,最新的 Python 版本是 Python 3.9.6 )

选择最新的 Python 3 版本

第 3 步—滚动到页面底部,选择并下载 64 位 Windows x86–64 可执行安装程序(如果您的电脑使用 32 位,则选择 32 位 Windows x86 可执行安装程序)

选择并下载 Windows Installer

第 4 步—双击下载的文件运行安装程序

  • 运行 Python windows 安装程序后会弹出一个对话框

Python 安装-对话框

  • 勾选“将 Python 3.9 添加到路径中” (此框默认未勾选)

通过将 Python 添加到 PATH,您可以从命令提示符(cmd)运行 Python。总之,您可以通过在命令提示符下键入“python”来运行 Python 脚本。

选中选项-将 Python 添加到路径

第 5 步—单击“立即安装”

Python 安装

如果安装成功,您将收到消息“安装成功”

Python 安装-设置成功消息

步骤 6-在 Windows 搜索栏下,输入“Python”并选择“IDLE (Python 3.9 64 位)”

Windows 搜索栏:python

空闲的 shell 窗口将会打开,您可以开始编写您的第一个 Python 脚本。

Python 空闲外壳

步骤 7 —编写您的第一个 Python 脚本(“Hello,World!”)

打印“你好,世界!”在 Python 空闲 shell 上

干得好!现在,您已经在计算机上安装了 Python 环境,并编写了第一个 Python 剪贴画。在本文的下一部分,我们将了解更多关于 Python IDLE 的内容。

Python 空闲是什么?

Python IDLE 是一个 Python 开发和学习环境,IDLE 代表:

有两个主要窗口,即“外壳窗口”和“编辑器窗口”。“外壳窗口”提供对 python 交互模式的访问,“编辑器窗口”允许您创建或编辑现有的 Python 文件。让我们首先看看如何配置我们的 Python 空闲环境。

在您的空闲 shell 环境中,导航到选项→配置空闲。

配置空闲

“设置”菜单将弹出,标签“字体/标签”显示一个字体列表,您可以为您的 Python 空闲环境选择字体和字体大小。

空闲-设置菜单:字体/标签

在“Highlights”选项卡上,您可以为 Python 空闲环境选择一个主题。例如,我会换成深色的,因为这样对我们的眼睛更舒服。

空闲—设置菜单:突出显示

在“窗口”选项卡中,您可以指定您的窗口首选项,如宽度、高度等。但是让我们注意一下启动时的窗口首选项,默认情况下是“打开 Shell 窗口”。

空闲-设置菜单:窗口

在前面的部分中,我们从窗口搜索栏中打开了“ IDLE (Python 3.9 64 位)】,默认情况下,当设置中默认选择了选项“ Open Shell Window ”时,会打开空闲的“Shell Window”。但是如果选择了选项“打开编辑窗口,会发生什么呢?—让我们尝试选择此选项,并观察不同之处。

空闲-设置菜单:窗口-切换到“打开编辑窗口”

观察在“外壳窗口”中选择“打开编辑窗口”选项时的区别。“外壳窗口”显示关于安装的 Python 版本和操作系统的信息,而“编辑窗口”是一个空文件。

Python 空闲的“外壳窗口”和“编辑窗口”

“外壳窗口”是一个交互式环境,当您只需要执行一行命令时非常有用,但是如果您正在编写一个完整的 python 程序,它就不实用了。因此,“编辑窗口”将会更有用,因为您可以编写 Python 脚本并保存代码。让我们看一个打印“Hello,World!”使用“编辑窗口”的消息。

Python 空闲的“编辑窗口”

请注意,“编辑窗口”不会在输入时运行脚本。要运行该脚本,您需要导航到运行→运行模块。

Python 空闲“编辑窗口”——运行模块

将弹出一条对话框消息,要求必须保存文件。用您喜欢的文件名保存 Python 文件(确保用。py 扩展)。保存后,将执行您的 Python 文件,并将结果打印在一个空闲的“Shell 窗口”中

空闲“外壳窗口”中显示的 Python 脚本的结果

结论:

建立自己的 Python 环境很容易,只需要几个步骤,您就可以开始编写第一个 Python 脚本了。作为一个初学 Python 的人,Python IDLE 是开始你的旅程的好地方。然而,随着您的深入,您将会探索其他工具,如 Pycharm、Eclipse、Microsoft Visual Studio 等。尽管如此,祝贺你第一次探索 Python!

参考和链接

[1]https://realpython.com/installing-python/

2https://realpython.com/python-idle/

[3]https://geek-university.com/python/idle-editor/

Python 中的 SQL 及其等效命令指南

原文:https://towardsdatascience.com/guide-to-sql-and-its-equivalent-commands-in-python-445e134adaba?source=collection_archive---------9-----------------------

对于那些想将 SQL 代码转换成 Python 中的等效命令的人来说,这是一个快速而详细的备忘单!

照片由洛佩兹罗宾在 Unsplash 拍摄

介绍

从头开始学习从来都不是一件容易的事情。原因之一是我们不知道自己不知道的事情。当我第一次学习 Python 的时候也是这样。我对它的逻辑、语法等感到沮丧,因为要记住它们太难了。最后,我发现了自己学习 Python 的方法,那就是通过 SQL。由于 SQL 是我在日常工作中经常使用的工具,我试图将我在 SQL 中学到的一切应用到 Python 中。这种学习方式帮助我同时研究、练习和记忆。

在本文中,我将向您展示一些重要的 SQL 查询和它们在 Python 中的对等物,具体来说是 Pandas。这被认为是对那些想用和我一样的方法学习 Python 的人的一个指导。希望它能成为那些想买熊猫的人的有用的小抄。

数据

我将创建一个简单的数据集如下:

data = {'product_name': ['pencil', 'eraser', 'pen', 'desk', 'laptop'],
        'price': [2, 1, 1, 50, 678], 
        'owner': ['Chi','Joe','Dan','Lisa','Rose']}
df = pd.DataFrame(data) 

图 1:测向数据集

现在,让我们开始吧!

选择

下面是 SQL 的一些简单的select语句和 Python 中的等效命令。

您可以通过调用数据集的名称(在我的示例中为 df )来轻松选择所有的列和行。

在另一种情况下,您只需要从数据中提取特定的列,您可以考虑一些简单的方法,例如使用loc & iloc.进行切片和索引。在我下面的示例中,我向您展示了从 df 数据集获取列 owner 的三种不同方法。

如果我想查看我的数据中存在的独特产品?很简单,只需从 df 数据集提取 product_name 列,并应用unique()函数即可。

带条件选择

在 Pandas 中,有几种方法可以选择特定的条件行。我们可以用 Python 的切片方法,索引,应用查询函数或者 lambda。

在下面的例子中,我将向您展示一些解决方案,通过对列值的一个或多个约束来获得所需的数据。通常,当在条件论元中处理数值数据时,我们必须处理不同的比较(例如:col_number > 2,total_people ≥ 10 等)。作为参考,在 Python 中,对数值数据的比较运算符描述如下:

  • 等于==
  • 不等于!=
  • 大于>
  • 不到<
  • 大于或等于>=
  • 小于或等于<=

此外,如果您想要提取特定类别等于字符串或对象的行,您应该用==操作符指定它。我选择所有product _ name为 pen 的行的情况如下表所示。让我们来看看。

选择其值与特定模式相似的行

假设您在一个数据中有数千个产品列表,但您只想选择产品名称与 相关的数据。在这种情况下,使用contains()功能是一个很好的选择。

有时,当您确切地知道所需类别的开始和结束字符时,您可以借助于功能startswith()endswith()来指定它。

选择其值在确定集合中的行

如果要选择特定列值在某个范围或集合内的行。isin()命令可以帮你做到。例如,我想选择 product_name 为钢笔或铅笔的数据。我将调用如下命令:

计算函数

与 SQL 类似,Python 也提供不同的函数来计算聚合或生成描述性摘要。

在我的例子中,我只用一行代码就可以很容易地找到产品的总数、所有产品的总价格、产品价格的范围(例如:最大值、最小值、中间值等)。

分组依据

Group by 很简单。只需在想要分组的列上使用groupby()功能。例如,从我的 df 数据中,为了计算每个人为他/她的产品支付的钱,我将数据按每个人的名字分组,然后计算相应的产品价格总额。

排序值

基本上,sort_values默认按升序排列值。因此,如果您想按降序排列值,只需在sort_values()参数中声明ascending = 'FALSE'

为了查看谁付了最多的钱,我用groupby()sum()函数计算每个人付的钱,然后按降序排列价格总和。

加入

我将创建另一个名为 df2 的数据帧来描述join命令。

*data1 = {'class': ['A','A','C','B','E'],
        'teacher':['Mona','Mila','Laurel','Wes','Connor'], 
        'owner': ['Chi','Joe','Dan','Lisa','Rose']}
df2 = pd.DataFrame(data1)*

图 2:数据帧 df2

基本连接包括左连接、右连接、外连接和内连接。在不同的情况下,根据我们的需要,我们可以选择合适的join.

让我们看看如何用四种类型的join.转换我们的数据

结论

通过与你熟悉的东西联系起来,我认为你可以更好地学习和记忆新的东西。我希望这些技巧能够在将来当你开始钻研 Python 中的数据操作时作为有用的备忘单。祝你好运!

应用研究设计用词云指南

原文:https://towardsdatascience.com/guide-to-using-word-clouds-for-applied-research-design-2e07a6a1a513?source=collection_archive---------18-----------------------

发现文本数据可视化在应用研究中的基本应用,并将其用于您的项目

作者图片

作者:彼得·科拉布 (布拉格,Lentiamo 德国齐柏林大学)雅尔科·菲德姆克 (德国齐柏林大学)大卫·什特尔巴 (布拉格兰蒂莫)

介绍

在应用经济研究中,经常分析各种形式的文本数据,包括陈述、演讲、公告及其效果。由于文本可以量化并用于建模和预测,研究人员使用各种技术来钻取它并将其用于他们的实证设计。

更具体地说,单词 cloud 是一个简单但广泛使用的图形,用于显示和理解文本数据的结构。所有主要的统计程序如 R 、 SPSS 、 Python 、 STATA 、 MATLAB 以及商业智能工具如 Tableau 、 Looker 、 Power BI 都包含一个 word cloud 实现。Word clouds 还开发了更具吸引力的功能,包括各种形状和背景。

这个简短的指南将向您介绍 word cloud 在设计应用研究和数据科学项目中的四个主要应用,以及一个 Python 实现。您将学习如何:

  • 使用词云理解数据的结构
  • 选择模型的基本特征
  • 理解文本数据中的上下文
  • 用词云让数据讲故事

什么是词云?

词云是由特定文本中使用的词组成的图像,其中每个词的大小表明其频率或重要性。这是一个在商业和学术界经常使用的简单图表。从技术上来说,词云是基于计算语言学中的 n 元语法和来自文本或语音样本的 n 项的概率场序列。这些项目可以是音节、字母或单词。

使用拉丁数字前缀,大小为 1 的 n 克被称为“一元格】,大小为 2 的是“二元格”,大小为 3 的是“三元格”N=1 时,单字实质上就是句子中的单个单词。例如,在句子“牛跳过月亮”中,如果 N = 2 ,那么 N 个字母组是:“牛”、“牛跳”、“跳过”、“越过”等。若 N = 3 ,则 N 个字母组分别为:“牛跳”、“牛跳”、“跳过”和“跳过月亮”。

许多数据应用程序实际上都使用克数。其中之一是Google Books Ngram Viewer,这是一个在线搜索引擎,它使用在 Google Books 的数字化资源库中找到的 n-gram 的年度计数来绘制任何一组搜索字符串的频率。

在学术界,研究人员最近使用词云来显示文本数据中的频率。在金融领域, Feldkircher 和他的同事们收集了欧洲各国央行行长的讲话,并对其内容进行了分析。在《经济文献杂志》的文章中,鲍尔斯和卡林用文字云来说明经济学教学改革的必要性。早在 2018 年,艾伦和麦卡里尔就探索了关于全球变暖、气候变化和天气的 Twitter 数据,并使用词云来绘制美国前总统唐纳德·特朗普发布的推文中最突出的词。

数据汇总

词云旨在总结文本数据。让我们用欧洲央行(ECB)行长克里斯蒂娜·拉加德(Christine Lagarde)在 2021 年 9 月央行行长论坛上的一次演讲来证明这一点。该讲座可在欧洲央行的网站上获得。即使不读书,我们也能一眼看懂欧洲央行行长的话题。为了实现这一点,的关键问题是:

  • 数据的结构是什么?
  • 数据中需要重点关注的关键话题是什么?

我们将使用 Python 的 matplotlibwordcloud 库:

文章文本被复制到一个字符串变量:

最后,我们用摘要文本生成一个词云。

通过几行代码,我们看到欧洲央行行长主要关注通胀,而通胀与疫情、复苏、衰退、工资和供给有关。这些显然是欧洲经济在科维德危机两年后面临的话题。

作者图片

这个词云应用的好处随着数据量的增加而显著增加。如果数据集包含几十或几百 MB,那么读取这样的文本会消耗大量时间。另一方面,运行 python 脚本只需几秒钟,可以自动化,并为潜在决策提供最相关的信息。

F 特征选择

超越简单的数据汇总,但遵循相同的原则,我们可以选择最关键的因素,并将其用于进一步建模。特征选择是机器学习中常用的术语,指的是为模型选择必要的变量。词云显示词频(或 n -1 克)或词共现(高阶n-克),它们本质上对文本数据也是如此。

****关键问题在这里:

  • 与特定主题相关的最重要的因素是什么?

这个例子的数据集是冠状病毒新闻标题数据集,可以在 Kaggle 免费获得。在这里,更具体地说,我们可以讨论以下问题:

  • 在新冠肺炎疫情期间,讨论最多的话题是什么?

我们只从包含 Covid 危机开始的数据集中选取前 2000 个标题。这个子集就是上一个例子中相同 python 代码的源数据。

作者图片

我们可以看到,Covid 19 爆发后,媒体关注的是它的起源:中国,武汉,以及它向其他国家的传播。任何关注 Covid 危机开始的社会和经济研究都应该反映这些关键因素。

动画词云

词云通常表现为没有时间维度的的静态图。另一方面,动画单词云将动态特征添加到分析中,并有助于讲述有关数据的故事。将数百张图片组合成一个 MP4 视频,我们可以看到话题随着时间的发展所具有的意义。****

迈克尔·凯恩和他的同事引入了这种原始的方法,收集了在科学杂志摘要中发现的 250 个最常用的单词,并开发了一个名为 the Word Swarm 的动态版本的单词云。Python 代码可以从他们的 GitHub 中免费获得。

我们优化了 Python 3.8 的原始代码。并用它来分析发表在五个最著名的经济期刊上的文章标题。我们的数据由从这些期刊的文章标题中构建的词频(即单字)组成。动画单词云以激动人心的视频演示方式展示了数据中的研究趋势。文章可从这里获得。

资料来源: Koráb、trba、Fidrmuc (2021 年)。一种新颖的词频可视化方法。In: Python 直白的英语。

文字网络可视化

词云用于生成文本数据的可视摘要;然而,他们可能会忘记上下文。存在得到错误结果和对基础数据做出错误假设的风险。文本网络分析通过考虑“单词”的共现(即高阶 n -grams)来解决这个问题,并提出了一种不同的文本思维方式:不是概念云,而是概念之间关系的云

InfraNodus 是另一个以文本网络分析为核心框架进行文本挖掘和文本数据分析的工具。文本网络方法可以概括为以下步骤:

  • 从各种来源导入数据
  • 生成网络结构
  • 创建一个与其他相关主题相关的单词云

我们之前的文章提供了对 InfraNodus 的详细介绍,包括在新冠肺炎危机期间对 google 查询的深入分析。要了解更多详细信息,也请阅读 InfraNodus 文档和一个 word cloud 案例研究。

资料来源:科拉布(2021 年)。InfraNodus:文本数据分析的优秀工具。In:走向数据科学。

结论

互联网和其他数字数据源提供了大量的文本信息。例如,政策制定者的演讲可以在网上免费获取,既面向公众,也面向投资者和研究人员等决策者。处理和可视化这些标准方法无法处理的大量信息(阅读和手动总结)变得非常重要。

本文提出了词云在静态、动态和文本网络形式的应用研究设计中的三种应用。我们证明了这些方法对于在早期阶段设计研究或者在后期阶段展示结果是非常有用的。它们还可以用于各种使用文本数据的数据科学项目,无论是在公司还是在其他地方。在不久的将来,工具的数量及其在各个领域的应用肯定会增加。

PS:你可以订阅我的 邮件列表 在我每次写新文章的时候得到通知。如果你还不是中等会员,你可以在这里加入https://medium.com/@petrkorab/membership****

作为数据科学家开始第一次实习前的指导方针

原文:https://towardsdatascience.com/guidelines-before-starting-your-first-internship-as-a-data-scientist-791f435ff709?source=collection_archive---------38-----------------------

在一家瑞士咨询公司做了一年的 ML 工程师

在这里你会找到一些我在开始实习前就知道的提示和建议!

丹尼尔·麦金尼斯在 Unsplash 上的照片

帖子的目的:

这篇文章将引导你完成我的第一次实习之旅。您将找到数据科学家必备工程材料的相关信息,更重要的是,它将帮助您迅速成为同事的可靠伙伴。

在开始我作为一名 ML 工程师的第一次实习之前,我在网上查了一下哪些工具我可能会日常使用。事实证明,找到简明的信息比预期的要难。因此,我决定分享一些我希望在我出生前就知道的建议!

根据你将要工作的公司,你不一定会用到所有这些工具。但是,了解它们会让你成为更好的程序员!

指南:

  • 如何在远程服务器上工作?ssh 协议对话,用 tmux 工作。
  • 如何和多个工程师一起开发代码? Github 就是你的一切。
  • 如何部署你的项目? Docker 是你部署的第一步。

如何在远程服务器上工作?

今天,许多公司都在云服务器上工作。了解远程访问协议的基础知识会给你的主管留下深刻印象,并在你实习的头几天为你节省宝贵的时间。你不需要掌握所有的东西,但是能够使用主要的命令会让你很快上手!

照片由 Kvistholt 摄影在 Unsplash 拍摄

什么是宋承宪?

SSH(或安全外壳)是一种远程管理协议,允许用户控制和更改他们的远程服务器。赫尔辛基理工大学的研究员塔图·伊洛宁创建了这个协议,以确保所有与远程服务器的通信都以加密的方式进行。

你需要什么

  • 服务器及其 IP 地址
  • 使用 sudo 访问的服务器设置
  • 本地计算机

Mac/Linux 用户如何使用 SSH 协议

如果您只需要一个密码就可以进行基本的服务器访问,那么使用下面的命令和您的用户名以及 IP 地址。

ssh <user>@<IP-Address>

如果您需要在服务器上打开一个端口,您可以使用 -p 选项轻松完成:

ssh -p 24601 <user>@<IP-Address>

如果您需要使用一个 SSH 密钥(它是一个带有锁定语句的散列密钥),您将需要首先生成一个 SSH 密钥:

ssh-keygen -t rsa

上面的命令为非对称加密创建了两个密钥——一个用于加密的公共密钥和一个用于描述的私有密钥,并要求您选择存储密钥的路径。我鼓励你保持预设的路径。然后,您将能够通过添加-i 选项和您的公钥的路径来访问您的远程服务器。

ssh -i path/id_rsa.pub <user>@<IP-Address>

对于 Windows 用户,可以使用 Putty。可以关注这个网站。

你知道 Tmux 吗?

它是一个终端管理器,允许你在后台运行程序。这是它最初的主要目的,但是随着我对它的特性了解越来越多,我开始在每次打开终端时使用它!这个终端管理器允许您以高效的方式同时设置许多终端。其结构类似于 Vim 代码编辑器。因此,通过避免使用鼠标,你将比以往任何时候都编程更快!

它可以在 Mac OS 和 Linux OS 上使用。因此,即使你有 Windows,仍然可以使用虚拟机来设置 tmux!

安装:

对于 Mac 用户

brew install tmux

适用于 Linux Ubuntu 或 Debian

sudo apt install tmux

开始使用 tmux:

要开始你的第一个疗程,写下:

tmux

或者,如果您想用预定义的名称创建一个新的:

tmux new -s session_name

如你所见,它就像一个新的终端!但是它可以做得更多。例如,要获得所有命令的列表,您可以键入:Ctrl+b ?

如果要离开当前会话:Ctrl+b

如果你需要继续治疗。首先,列出所有可用的会话:

tmux ls

然后,在会话名称后附加:

tmux a -t session_name

或者,如果您想终止一个会话:

tmux kill-session -t myname

为什么要深入?

如前所述,使用 tmux 作为终端管理器,您可以做的不仅仅是简单的终端界面!如果你看一看这个网站,你会发现你将能够同时管理不止一个而是多个终端(称为窗格)!

如何与多名工程师一起开发代码

Github 是最知名的源代码管理器。它为每个项目提供了代码历史、安全控制、更新跟踪、特性请求、任务管理、持续集成和 wikis。

你需要尽快了解如何使用 GitHub!这是你需要快速变得敏锐的最重要的技能之一。它的技术是独一无二的,它的结构使它非常坚固。它创造的真实故事是非凡的,如果你渴望了解它,我给你链接!

扬西·敏在 Unsplash 上的照片

你需要意识到的主要是 GitGithub 的存在。仅仅放;Git 是一个分布式版本控制系统,可以让你管理和跟踪你的源代码历史。GitHub 是其基于云的托管服务,使您能够与其他人一起管理 Git 存储库。这个软件可能会在你作为工程师的整个职业生涯中跟随你!可以比作程序员的脸书,很多公司会尝试/要求访问你在 Github 上的项目。在这个网站上,招聘人员可以很容易地收集到很多信息,帮助他们建立你的个人资料。因此,不要忘记清理你的代码,如果你认为你的项目可以卖得更好,分享你的项目!

安装:

Linux:

sudo apt install git

Mac 用户:

brew install git

Windows:跟随网页链接

现在让我们试一试:

尝试下面的步骤来了解 Git/GitHub 中的主要流程!让我们从一个例子开始:

假设一个 python 代码在某个特定的功能上有一点小问题:您正在使用一个 python 包,它会向您发送关于代码进度的通知。您意识到当代码失败时还不可能发送错误消息。因此,你肯定喜欢这个工具的想法,你想通过增加这个小特性来改进它!

由于它的源代码在 GitHub 上是开源的,您可以执行以下步骤:

  1. 在本地机器上克隆存储库:
git clone https://github.com/lolilol/package.git

2)然后,创建你的源代码的 分支 并发送到你的个人 GitHub

git checkout -b issue123
git remote add upstream https://github.com/my_name/demo.git
  1. 更新丢失的代码并运行一些测试

  2. 提交推送 您的变更到您的新分支。

git commit -a -m 'Fixed issue 123'
git push -u origin issue123

5)打开一个 拉请求 给仓库的维护者:一旦你将变更推送到你的仓库,GitHub 中就会出现比较&拉请求按钮。点击创建拉动请求按钮,打开拉动请求。

6)如果资源库的维护人员欣赏该代码,就会将 合并 到主分支!

提示和警告:

正如您可能已经听说的那样,许多合并问题和 git 问题很难用很少的经验来解决。因此,我在这里分享一些技巧来避免 Git 可能产生的主要问题。

提示 1: 在每个 git 命令后使用以下命令行来检查您对 Git 行为的预期:

git status

提示 2: 如果您在一些文件之间有合并问题,请不要紧张!Git 将精确地指定由新版本的源代码更新的代码行。您只需要更改需要丢弃的代码部分,然后重新提交您的更改。那么,合并就成功了!这里有一个很好的例子。

提示 3: 不要犯提交和推送超过 GitHub 限制 100MB 的大小的文件的错误!下面两个命令中的一个应该就可以了,但是请记住,您已经在 GitHub 中重写了提交的故事。你需要了解发生了什么,以采取最佳解决方案。检查那两个帖子:链接1&链接 2

git filter-branch --tree-filter 'rm -rf path/to/your/file' HEADgit filter-branch --index-filter 'git rm -r --cached --ignore-unmatch <file/dir>' HEAD

提示 4: 使用 gitignore 文件管理不想推送到 GitHub 的文件夹/文件。这将避免与 3 号提示相关的任何问题!当你在 GitHub 上创建一个新的存储库时,你可以自动为特定的编程语言生成一个 gitignore 文件!

如何部署您的项目

在这个阶段,您能够在服务器上进行通信、工作和协作。您可以在远程机器上设置工作流。最后一步就是要知道怎么部署!

有多种选择,根据项目的重要性,你可能会比我在这篇文章中做得更深入。我主要讲包管理、bash 脚本和 docker。但是你可以自由地去追求你的知识,比如说 Kubernetes!

照片由张秀坤·吕克曼在 Unsplash 上拍摄

为什么使用 bash 脚本?

Bash shell 脚本是可以在终端中执行的命令行。它们将允许你以一种用户友好的方式设置你的应用程序,因为所有奇怪的和不可理解的命令将被收集在一个文件中。

下面是一个下载数据并运行 python 应用程序的 bash 脚本示例。

# create directory.
mkdir models # Download data and deep learning model
wget https:nvjovt/model.zip
cd models && unzip model.zip && rm model.zip && cd ..wget https:nvjovt/data.zip
unzip data.zip && rm data.zip# Run python code
python3.7 app.py

一个简单的命令可以用一个来运行这个脚本。sh 扩展:

bash setup_app.sh

包管理和虚拟环境

打包和虚拟环境密切相关,因为它们都关注包的依赖性。因此,建立一个项目最简单的方法是创建一个虚拟环境并在其中安装软件包。但是你可以用不同的包装来简化你的生活。

下面的包管理器创建了一个虚拟环境,它们还负责包之间的依赖关系!它使用起来更舒服,但是它需要花费时间!下载软件包通常需要更多的时间,但是您可以相信它们会有更简单的部署。

python 最著名的管理器叫做 pipenv。因此让我们以此为例向你展示他们的特色。你可以用一个 pip 命令安装它:

pip install pipenv

使用一个简单的命令,您将创建虚拟环境和包管理器:

pipenv shell

您将看到一个文件名为 Pipfile 的文件,包就保存在这里。这个管理器的一个很大的特点是可以设置一些开发包,这些开发包只能因为开发的原因而安装。

要下载软件包,请使用以下命令之一:

pipenv install package_name 
pipenv install "package_name~=2.2"

要在开发阶段下载它,请使用:

pipenv install package_name --dev

然后,当您想要使用正确的库和正确的版本部署应用程序时,您需要使用以下内容锁定包依赖关系:

pipenv lock

这将创建/更新您的Pipfile.lock。这个文件冻结了你当前的包和它们的依赖关系。现在任何人都可以访问这个文件,您可以运行pipenv install --ignore-pipfile来创建相同的环境!或者pipenv install --dev如果有人需要访问开发包。

提示 1: 尽管这需要一些时间,但是如果不使用这样的打包管理器,您很可能会遇到依赖问题。他们真让人头疼!

提示 2: 它们还有额外的功能,可以帮助你在 Heroku 或 Flask 上部署应用!检查下面的连杆。

提示 3: 还有其他的打包管理器,你可以查看一下poem,因为它可能有比 pipenv 更适合你的特性。

为什么应该使用 Docker?

Docker 是一个你可能已经听说过的开源软件。它使用其操作系统创建容器,以避免在其他机器上部署解决方案时出现软件依赖性问题。我鼓励你学习 Docker,因为如果你从事计算工程,你将会使用它或者其他类似的软件。

总结其复杂的层次,Docker 可以运行与虚拟机目标相同的容器。在每个容器中运行一个独特的操作系统及其环境。你可能会问,为什么大多数人更喜欢 Docker 而不是虚拟机?因为它设置起来容易多了,而且相比 VM 也优化的很好!

首先,你需要学习图像,我们将一起看一个例子!然后,您将了解 Docker Hub,它遵循与 Github 相同的理念。最终,您将能够使用一个命令在任何 Linux 操作系统上部署应用程序!干杯!

如何下载 docker:

  • 对于 Mac 用户:跟随这个链接。
  • 对于 Linux 用户:跟随这个链接。
  • 对于 Windows 用户:跟随这个链接。

主要命令有:构建运行。第一个命令创建图像。第二个在你的机器上运行。但是在玩命令之前,让我们先了解一下会做一切的 Dockerfile!

什么是 Dockerfile

当您的项目完成并准备部署时,您可以从在工作目录中创建 Dockerfil 开始。这个文件是特殊的,它将定义你的 docker 图像的工作方式!如果你的应用程序需要大量内存,你可以优化这个文件,以确保你没有任何无用的包或数据。

如上所述,这个文件生成操作系统,导入源代码,并设置容器动作。以下是 Dockerfile 文件的可能结构示例:

FROM ubuntu:18.04
COPY . /app
RUN make /app
CMD python /app/app.py

请记住:

  1. FROM:您将始终基于另一个图像创建一个图像。
  2. 复制:Docker 从基础映像创建一个操作系统,你需要将源代码复制到
  3. 运行:Docker 允许你在操作系统内部运行命令来设置你的容器(例如,bash 脚本、包安装、导入数据集、数据库等。)
  4. CMD:您还需要指定启动应用程序将执行的启动命令。它将在您运行容器时使用。

如果你对一个你可以在家尝试的例子感兴趣,这里有一个链接。

当您的 docker 文件准备好时,您可以运行以下命令来构建映像:

docker build folder_path_of_dockerfile -t name_your_image

如果代码没有任何错误地完成了,这意味着您的第一个图像已经准备好了!因为您可能需要在不同的机器上部署解决方案,所以您应该将这个新的映像推送到 Docker Hub 存储库中。它将允许您仅通过互联网连接访问图像。因此,您需要:生成一个 Docker Hub 帐户,创建一个存储库,并将其链接到您的本地机器。

docker login --username=yourhubusername

然后,标记您的图像:

docker images
docker tag image_id username/reponame:tagname

并将其推送到您的 Docker Hub 存储库:

docker push account_name/repo_name:tag_name

现在,您可以在任何安装了 Docker 的机器上只运行一个命令来启动您的应用程序:

docker run account_name/repo_name:tag_name

维护您的图像/容器:

图像:

  • 显示所有图像:docker images ls
  • 擦除图像:docker rmi -f image_id
  • 擦除所有图像:docker rmi $(docker image -a -q)

容器:

  • 显示所有图像:docker container ls -a
  • 擦除一个容器:docker rmi -f container_id
  • 擦除所有容器:docker rmi $(docker container -a -q)

结论:

如果你已经到了终点,那就意味着你要为实习的第一周做好准备了!祝你好运,年轻的学徒。

图形用户界面或编码:生产与操作

原文:https://towardsdatascience.com/guis-or-coding-production-vs-operation-fc1de9e483a8?source=collection_archive---------42-----------------------

随着我们更深入地进入数据和计算机科学的时代,一场关于我们使用的工具的辩论开始了,是关于 GUI 软件还是编码软件。到底应该用哪一个?

许多从未想过处理数据和分析的研究人员或专业人士在过去几年中发现自己陷入了这一不断扩展的数据科学学科。即使是上个世纪的科学研究也需要许多学术研究人员在小得多的规模上处理数据分析,对于他们来说,构建甚至简单的线性模型都不是一项直观的任务,而是为他们自己提供了一系列 GUI 软件选项来执行这些任务。

由于我们对数据科学的知识从未像现在这样扎实,我们还发现自己在开发数据科学项目时,澄清了执行分析任务的心态和我们的文化。这就是选择使用 GUI 构建我们的分析还是对它们进行编码的时候了。

用户友好的软件从它自己的名字中发现了它的优点,它是为那些没有扎实编程背景的研究人员设计的,以使他们能够执行分析任务。在数据科学中,它可以包括一个漂亮的可视化或者一个汇总表。然而,当谈到数据科学时,我们不再意味着只提供一个数字或一个表格,我们指的是构建管道,对输入观察执行一系列不同的任务。在这方面,我们的最终产品是复杂的,因此我们构建产品的工具也需要健壮。

使用 GUI 软件没有什么本质上的错误,但是我们需要理解它什么时候可以使用,什么时候不满足健壮性。

数据科学的生产与运营。(图片由作者提供)

用户友好的软件不是一个强大的生产环境

在讨论 GUI 软件的使用与编码时,需要考虑的主要区别是开发/生产一个分析管道和操作一个已建成的管道或将其投入使用之间的区别。对于 DevOps 实践下的计算机科学家和软件开发人员来说,这种区别在历史上一直非常明显,现在是时候开始为数据科学家/统计学家或任何发现自己正在进行数据分析的研究人员澄清这一点了。

为了使用一个数据分析实例,我们可以考虑构建一个预测模型。处理线性模型以发布 p 值的经典统计学家或研究人员可以将自己置于此处,因为计算 p 值是构建线性模型的副产品。构建模型需要多种方法,例如清理数据、过滤信息、测试不同的模型架构、可能在不同标准下进行优化等。许多 GUI 软件都包含执行这项任务的工具,不同方面的面板,不同选项的下拉菜单,最后,由用户测试(许多)不同的选项并保存输出以做出最终决定。

上面描述的场景相当于在高速公路旁边建一辆汽车,上面有一个帐篷,可以存放所有必要的工具。类似的是在办公室的办公桌上搭建一台电脑。这是可以做到的,但应该这样做吗?在这两个例子中,很容易区分这两种环境:有一个生产环境,它通常根据构建它的任务(构建片段、集合等)被分成不同的环境。),还有一个操作环境,就是高速公路或者办公室的办公桌。

编程是每个人的

即使一个模型的生产可以很好地在 GUI 软件中进行,这也不能破坏我们通过编程构建分析工具时的健壮性和准确性。随着计算和数据科学的飞速发展,编程或编码正成为本世纪的一项必要技能。为数据分析构建我们的模型或管道需要开始从他们的操作环境中获得独立的位置。我们越是致力于一个清晰和健壮的环境来生产我们的模型,我们将为以后的部署构建更精确的机器。

制作一个模型并不是一个用户友好的任务,但是操作它肯定是。

尽管编程对于许多专业人士来说仍然是一个难以理解的概念,但这个概念现在比以往任何时候都更加用户友好。像 Python 和 R 这样的编程语言在语法和范式上都非常容易理解,更不用说开放访问设施了。它们不是轻轻一点就能出现的,但与学习 c 等低级语言相比,它们付出的努力要少得多。请注意,这里的“显著”没有 p 值来证明。

GUI:操作环境

因此,并不是说图形用户界面一点用都没有。用户友好的软件,正如它的名字所声明的,是用来完成用户友好的任务的。制作一个模型并不是一个用户友好的任务,但是操作它肯定是。从这个角度来看,我们可以并且可能仍然应该依赖 GUI 作为我们的模型或数据科学管道的部署模式。

GUI 在编码方面无法超越的一个方面:再现性

讨论中不能忽略的另一个方面是再现性原则,这在通过计算机发展的科学中特别重要。再现性是学术界和工业界许多领域讨论的一个新兴话题。在不同的讨论中,我们发现关于对人工智能来说可再现性意味着什么、科学和它所代表的价值的争论。尽管一种编码文化并不能保证流畅的可再现性,因为还需要更多的东西,但是它确实克服了 GUI 的缺点,比如完全依赖于用户。

随着我们渴望成为更好的数据科学家,以及该领域的持续增长,特别是以如此高的速度增长,事实证明有必要为发展新技能腾出空间,并将我们的工作文化从更快的生产结果转变为数据科学的稳健生产环境。

HAC:层次凝聚聚类——比 K-Means 更好吗?

原文:https://towardsdatascience.com/hac-hierarchical-agglomerative-clustering-is-it-better-than-k-means-4ff6f459e390?source=collection_archive---------8-----------------------

机器学习

HAC 算法的详细介绍,以及 Python 代码和几个有用的图表

层次凝聚聚类(HAC)。图片由作者提供。

介绍

如果你想成为一名成功的数据科学家,了解不同的机器学习算法是如何工作的是至关重要的。

这个故事是解释每个算法的细微差别的系列的一部分,并提供了一系列 Python 示例来帮助您构建自己的 ML 模型。

故事涵盖以下主题:

  • 层次凝聚聚类(HAC)属于算法的范畴。
  • HAC 算法如何工作的细节。
  • Python 示例,使用 HAC 对澳大利亚城市进行聚类。

层次凝聚聚类属于哪一类算法?

答案就藏在它的名字里。由于 HAC 是一种聚类算法,它位于机器学习的无监督分支之下。

无监督技术,尤其是聚类,通常用于细分分析,或作为更复杂项目的起点,这些项目需要了解数据点之间的相似性(例如,客户、产品、行为)。

下面的图表是我对各种不同算法进行分类的尝试。在许多情况下,一个算法可以用来解决多种类型的问题。例如,由于神经网络独特的机器学习方法,我将神经网络归为一类。然而,神经网络可以用于广泛的问题,如分类,回归,或作为强化学习的一个组成部分。

下图是互动,所以请点击不同类别放大并展示更多👇。

机器学习算法分类。由作者创建的互动图表。

如果你喜欢数据科学和机器学习 ,请 订阅 每当我发表一个新的故事,你都会收到一封电子邮件。

分层凝聚聚类(HAC)算法是如何工作的?

基础知识

HAC 不像 K-Means 那样广为人知,但它非常灵活,通常更容易解释。它使用“自下而上”的方法,这意味着每个观察从它自己的集群开始,随着一个集群在层次结构中向上移动,集群对被合并。

为了帮助说明这一点,我制作了一些图表。第一个演示了该算法如何一步一步地合并最近的点,直到只剩下一个聚类。

等级凝聚聚类(HAC)的作用。图片由作者提供。

注意,上面的 HAC 实现使用了“平均”链接,我将在本节稍后解释这一点。

第二张图被称为树状图。它给出了所采取的路径的全貌,从所有单独的点(图形的底部)移动到一个单独的点/簇(图形的顶部)。

层次凝聚聚类(HAC)树状图。图片由作者提供。

注意,我添加了一条水平虚线来表示我选择的集群的数量。一般来说,一个好的经验法则是确定 y 轴上没有垂直线与任何水平线相交的最大部分。让我进一步解释一下。

y 轴上的值是点/簇之间接近程度的度量。水平线表示那些点/簇被合并的地方。

上图表明您可能需要考虑 2 个集群,因为没有集群合并的最大距离在 24 和 30 之间(30–24 = 6)。

然而,在这种情况下,我决定选择 4 个集群,这是一个稍微不太理想的解决方案(大约。19.5–14.5=5).因此,我的集群是红色,亮绿色,蓝色,诺福克岛独自坐在角落里。

这是星团在地图上的样子:

用 HAC 算法进行澳大利亚城市聚类。图片由作者提供。

链接类型

有多种方法将这些点连接在一起。我在上面的例子中使用了“平均”链接,因为它易于说明和理解。但是,熟悉其他链接类型也很重要。注意,本文末尾的 Python 部分将向您展示如何指定您想要使用的链接方法。

  • ‘Average’:使用两个集合的每个观察值的距离的平均值,即找到观察值之间的中点(如图所示)。
  • “Single”:使用两个集合的所有观察值之间的最小距离,即在该阶段的点群中寻找最近的点(而不是“average”中使用的群中点)。
  • “完整”或“最大”:使用两组所有观察值之间的最大距离。例如,如果该点比聚类 B 的最远点更接近聚类 A 的最远点,则这样的点将被添加到聚类 A 中
  • ‘Ward’:最小化被合并的聚类的方差。这非常类似于 K-Means 使用的最小化类内平方和(WCSS)。

沃德连杆通常是最常用的一种。它也是 sklearn 实现 HAC 的默认选项,我们将在下面的 Python 部分中探讨。

HAC 优于 K 均值聚类

使用 HAC 最吸引人的部分是分析树状图的能力,它提供了对任意两个数据点之间相似性水平的洞察。

只需看一眼树状图,就能看出皮尔斯-布斯布鲁克离诺福克岛很“远”,而悉尼和悉尼机场离得很近。鉴于我们的位置数据,这是相当明显的,当我们使用更抽象的属性时,它变得非常有益。

一般来说,您可以使用 HAC 和 K-Means 生成非常相似的聚类,但是能够查看每个数据点的路径,使得 HAC 在分析各个数据点或聚类之间的相似性和差异时更有用。

使用澳大利亚城市位置数据的 Python 中的层次凝聚聚类(HAC)

设置

我们将使用以下数据和库:

  • 来自 Kaggle 的澳大利亚天气数据
  • Scikit-learn 库执行 HAC 聚类
  • Scipy 库创建树状图
  • 用于数据可视化的 Plotly 和 Matplotlib
  • 熊猫用于数据操作
  • 地理坐标,进度条,采集澳大利亚城市坐标的时间

让我们导入所有的库:

然后我们从 Kaggle 获取澳大利亚的天气数据,你可以按照这个链接下载:https://www . ka ggle . com/jsphyg/weather-dataset-rattle-package。

我们接收数据并派生出一些新的变量,比如 Location2,它具有使用 Geopy 提取城市坐标的正确格式。

经过一些修改的 Kaggle 的澳大利亚天气数据片段。图片由作者提供。

因为我们的原始数据只包含位置(城市)名称而不包含坐标,所以我们将使用 Geopy 的名称来获取这些坐标。请注意,我们在每次调用之间添加了 1 秒钟的睡眠时间,以避免服务器过载。

这是我们得到的回报片段:

澳大利亚城市坐标。图片由作者提供。

让我们在地图上标出这些城市:

地图上的澳大利亚城市。图片由作者提供。

HAC 聚类—树状图

为了决定聚类的数量,我们将首先绘制一个类似于我们前面分析的树状图。请注意,我们将绘制其中两个,一个使用“平均”链接,另一个使用“沃德”链接,这样您就可以看到结果的差异。

平均联动:

使用平均联动的 HAC 树状图(同上)。图片由作者提供。

病房联动:

HAC 树状图使用 ward 联动。图片由作者提供。

如你所见,当使用“ward”链接时,我们得到了完全不同的结果。之前的蓝色星团已经一分为二,孤独的诺福克岛已经并入紫色星团。

HAC 聚类—生成聚类标签

既然我们已经决定有 4 个聚类,让我们运行 scikit learn 的 HAC 算法来为“平均”和“区”链接方法生成聚类标签。

附加了聚类标签的位置数据片段。图片来自作者。

最后,让我们在地图上画出结果。

平均联动:

使用平均链接的澳大利亚城市 HAC 聚类(同上)。图片由作者提供。

病房联动:

为了使用' ward '绘制聚类,我们使用了与上面相同的 Python 代码,只是我们将第 5 行和第 8 行中的' Clusta4 '更改为' Clustw4 '。

使用 ward 链接的澳大利亚城市 HAC 聚类。图片由作者提供。

结论

分层凝聚聚类的好处在于,它让您可以通过树状图了解所有数据点的接近程度。当您通过使用两个以上的属性将聚类带到多维空间时,这变得更加重要。

总结一下,我想重申我在 K-Means 文章里说过的话:聚类很少是你分析的终点;通常,这只是一个开始。因此,一定要探索如何使用新创建的聚类来提高对数据的理解,并了解它如何帮助开发其他类型的模型。

祝您在项目中使用 HAC 愉快,如果您有任何问题或建议,请随时告诉我!

干杯!👏
T3【索尔·多比拉斯】T4

如果你已经花光了这个月的学习预算,下次请记得我。 我的个性化链接加入媒介是:

https://solclover.com/membership

如果您喜欢这篇文章,您可能也会喜欢对其他类型的聚类算法的内部工作原理的详细解释:

决策深度强化学习下象棋

原文:https://towardsdatascience.com/hacking-chess-with-decision-making-deep-reinforcement-learning-173ed32cf503?source=collection_archive---------12-----------------------

用机器学习创造国际象棋冠军

作者图片

下图是人工智能算法在 Chess.com 引擎上应用的将死棋,该引擎模拟了 2650(这是相当高的)特级大师——丹尼尔·纳罗迪茨基“丫蛋”。

在本文中,我将介绍为这种深度强化学习算法开发的概念,以及它如何赢得这场激烈的机器大战!

作者图片:查尔斯·谢赛 x·丫蛋——将军

“呜..你打败了丫蛋。希望你自我感觉良好:)”——丫蛋发动机

国际象棋是一种非常古老的战略棋类游戏,它的传统已经将它转变为一项运动、一门艺术,最终成为一门科学。

由于其复杂性,人类多年来一直试图创建模型来破解国际象棋,并一劳永逸地找到一种变得不可战胜的方法。今天,随着计算的巨大进步,我们有了可以提前几个步骤计算并取得优异结果的模型,如谷歌的 alpha-zero 模型。

我对国际象棋充满热情,没有谷歌的巨大资源,现在是我展示对国际象棋知之甚少但对算法知之甚多的时候了,我们可以创造一个国际象棋冠军,并尝试挑战该领域一些最强的算法。

决策深度强化学习

决策深度强化学习是一个概念,它使用深度强化学习通过先前定义的策略来优化决策。主要的想法是,从一组不同的好策略中,算法可以为面临的每种情况选择最佳策略。

深度强化学习模型观察环境中的每个状态,并使用神经网络来选择特定的动作。然后在被改变的环境中采取这个动作,然后代理对新状态进行新的观察并准备下一个动作。每个行为都会给代理人带来一个奖励,代理人的目标总是选择一个行为,使每个状态下的奖励最大化。

作者图片:CharlesChessAI 建筑

随着国际象棋游戏、深度 Q 学习、LSTM 和引擎的混合,CharlesChessAI 诞生了!

模拟环境——Python Chess 和 Gym-AI

第一步是创建一个模拟环境,以便模型可以观察状态并采取行动,基本上是一个下棋的操场。为此,我使用了 Python 中的几个库:chess、gym 和 gym chess。这些库允许我复制和观察棋盘上的所有移动,模拟一场比赛,除了获得分析分数和状态和移动的良好定义,还有检查,将死,可能的移动等等。

Charles chesai——智慧

CharlesChessAI 的智能基于 3 个预定义的策略:

  • id:0——人类长期记忆:使用人类玩的 20,000 个游戏的序列,仅过滤在将死中完成的游戏。这个选项着眼于长远,因为它总是以算法的将死而告终。
  • id:1-人类短期记忆:LSTM 的下一个单词预测器先前在大型游戏基础上训练,考虑 10 个移动的序列。该模型使用国际象棋运动作为字符串,并将游戏中的运动解释为句子中的单词。国际象棋表现得像玩家之间的对话。这种选择着眼于短期,因为它基于最后 10 个步骤,只产生下一个步骤。
  • id: 2 —引擎:引擎 Stockfish 的使用。Stockfish 是一个免费的开源国际象棋引擎,它分析游戏并提前计算一些走法以选择最佳走法。

夏尔·谢赛十世·丫蛋

下面是一段完整的视频,展示了 CharlesChessAI 在对阵丫蛋的比赛中的所有动作,这场比赛持续了大约 60 个动作 10 分钟。

查尔斯·谢赛 x·丫蛋——作者视频

在与 Danny 的比赛中,该模型存储了他的所有决定,我们可以在下图中分析这些决定,并了解比赛中的行为和决策。

作者图片:CharlesChessAI Choices

在游戏的开始,直到第 25 步,我们看到这个模型在策略之间做了很好的平衡切换,但是在 LSTM 身上使用了很多短期记忆策略。在游戏的中间,直到第 45 步,我们看到模型比开始时更多地使用引擎,更多地与长期人类记忆交替,这保证了良好的移动将游戏带到有利的结局。在游戏的最后,我们看到这个模型使用了大量的人类记忆选项来将死。

仍在开发中的代码在下面我的 GitHub 库中:

https://github.com/octavio-santiago/CharlesChess_Reinforcement_Learning

结论

决策模型使算法为每种游戏情况选择最佳策略,多样化策略的组合为一个引擎带来了来自伟大玩家的额外创造力,这是人和机器之间的一种优秀组合。这种算法也是非常动态和自适应的,因为根据玩更多游戏和面对新情况的模型,它学习如何针对每种情况优化决策。

以同样的方式,这种类型的模型应用于国际象棋,它可以应用于其他不同的决策环境。

我留给你们另一个国际象棋游戏,它是在 CharlesChessAI(白棋)和一个名为 Chess Lv100 的 Windows 应用程序引擎之间进行的,难度最大。现在这个模型在与引擎和人类的比赛中都是不败的,我会与他们进行更多的比赛,并在同一频道上发布。“塔之舞”是这场比赛的好名字,你可以更好地跟随视频。

查尔斯想要赢!

我希望这是一本好书!我将提供更多的信息和 CharlesChess 匹配,并将在 LinkedIn 上联系:https://www.linkedin.com/in/octavio-b-santiago/

黑掉惠普调优来执行自动型号选择

原文:https://towardsdatascience.com/hacking-hp-tuning-to-perform-automatic-model-selection-ef11d4c08ea2?source=collection_archive---------41-----------------------

瓦伦丁·彼得科夫在 Unsplash 上的照片

超参数调整的任务是选择与目标相关的最佳模型配置。我们在之前的帖子中已经看到,尽管这看起来是一项具有挑战性的任务,但是当使用基于模型的方法时,编码并不困难。

但是等等!如果惠普调优可以为给定的 ML 任务选择最佳参数,我们是否可以重用它来选择最佳模型?也就是说,是否有可能创建一种方法,像使用其他参数一样使用模型类型作为参数,并让超级参数优化为我们选择正确的参数?

这难道不是解决 ML 问题的巨大加速吗?答案不仅是肯定的是的!而且,实现起来也不是很复杂。

我们将在本文中详细探讨这一点。

基于型号的惠普调整快速提醒

超参数调整(HPT,有时也称为 HPO 超参数优化)的目标是找到最大化或最小化给定目标的配置。有各种方法来执行超参数调整:蛮力,随机搜索,贝叶斯搜索,或基于模型的方法。

我以前提倡使用基于模型的方法,这在我遇到的一些问题上证明是非常有效的。你可以在这里找到更多关于 SMAC 的细节,这是一个高效的 HPO 图书馆:

您可能也有兴趣更好地理解这些方法是如何工作的,并构建自己的超参数优化库。

这里有一个有趣的方法,利用你对 XGBoost、CatBoost 或 RandomForest 等标准模型的了解:

[## 用 XGBoost 调优 XGBoost:编写自己的 Hyper Parameters 优化引擎

towardsdatascience.com](/tuning-xgboost-with-xgboost-writing-your-own-hyper-parameters-optimization-engine-a593498b5fba)

除了令人兴奋之外(使用 ML 模型来调整 ML 模型),基于模型的超参数优化提供了一个优于其他解决方案的非常有趣的优势:它支持分类参数。这意味着我们可以将模型类型编码为分类参数。

也就是说,让我们看看如何破解标准的超参数调整来执行模型选择和加速模型构建。

超级模型

正如介绍中所提到的,这次黑客攻击背后的想法是这样的:我们能否像其他任何一个参数一样,将 model_type (即 XGBoost,Prophet,S/ARIMA……)视为一个参数,并让 Hyper Parameter Tuning 方法为我们完成这项工作?

令人高兴的是,如上所述,使用基于模型的方法的超参数优化支持分类参数。毕竟,他们的底层模型通常是一个增强的(或者不是)决策树。

这个属性的一个直接结果是,我们可以创建一个 超级模型 ,它将由模型类型以及其他参数来定义。 model_type 将对用于训练的底层模型进行编码。在 python 中,这给出了:

一个超级模型,它将底层模型类型作为一个参数。作者代码。

超模型的实现遵循 scikit-learn 模型接口,即它提供了 fit、predict、set_paramsget_params 方法。为了简单起见,我们只支持两个模型:XGBoost 和 RandomForest,但是再增加一个只会多几行。例如,您应该尝试一下 SVR。

您可能已经注意到,我们使用白名单来只保留那些适用于给定模型的参数。这不是支持参数因模型而异这一事实的最佳方式。正确的做法是使用条件配置。ConfigSpace python 库支持这一点,但 scikit 并不支持这一点。

使用我们的新类进行训练和预测是立竿见影的。假设我们想使用 XGBoost 作为底层模型。这给出了:

用我们的超模。作者代码。

我们现在要做的就是在 HPT/HPO 步骤中使用这个模型,并让它选择最佳候选模型类型。

寻找最佳模型

有了主参数是模型类型的超级模型,我们可以使用标准的超级参数调整方法来识别最佳模型。

需要记住的重要一点是,绝对没有“最佳模式”。当我写“最佳模型”时,我指的是给定分数的最佳模型。在本文中,我们将使用平均绝对误差作为得分。

尽管在我之前的两篇关于这个主题的文章中,我一直在使用(并建议)SMAC 或一个定制的超参数优化实现来执行 HP 调优,但在本文中,我们将尝试另一种方法。不要错过尝试新事物的机会:)

这一次,我们将使用 BayesSearchCV 来探索配置空间。贝叶斯搜索的基本原理是使用高斯过程建立一个代理模型,估计模型得分。

每个新的训练更新代理模型的后验知识。然后为这个代理提供随机挑选的配置,给出最佳分数的配置被保留用于训练。

因为它使用高斯过程模型来学习超参数和候选模型的分数之间的关系,所以它可以被认为是基于模型的方法。

将所有这些放在一起会产生以下代码行:

使用我们的超级模型来确定波士顿数据集的最佳模式。作者的代码。

配置空间主要使用参数的均匀分布来定义。这意味着在给定范围内选择一个值的概率在任何地方都是相同的。例如, max_featuresn_estimatorsmax_depth 就是这种情况。相反,跨越多个数量级的 gammalearning_rate 使用对数均匀分布选取。

运行这段代码将向您展示 XGBoost 似乎是这个数据集的最佳选择。

检查

像我一样,你可能不相信一个算法的结果,在执行一些检查之前。

幸运的是,许多其他数据科学家已经研究了波士顿数据集挑战。更具体地说,在 Kaggle 这里由 Shreayan Chaudhary 研究过,他得出了与我们的算法相同的结论。这是好消息。

然而,我们再谨慎也不为过。让我们执行另一个简单的检查,以确保如果我们对 HP Tuning exploration 进行更多迭代,并且只针对随机森林进行优化,RandomForest 不会优于 XGBoost:

这次调优单一模型:RandomForestRegressor。作者代码。

我们简单地重用了我们的超模型,但是这一次我们强制将探索集中在一个模型上:RandomForestRegressor。我们也允许更多的迭代:随机森林 50 次,而以前两个模型都是 50 次。

结论是一样的。就平均绝对误差而言,XGboost 精度保持得更好:随机森林为 2.68,而 XGBoost 为 2.57。

我们也可能是“幸运的”,XGBoost 优于 RandomForestRegressor 的事实可能完全是随机的,并且与用于初始化贝叶斯搜索的初始种子相关: random_state=0。

使用各种 random_states 多次运行代码应该会让你相信我们并不幸运,在这种情况下,XGBoost 是关于我们选择的分数的最佳选项:平均绝对误差。

我们的自动模型选择丢弃坏选项的速度有多快?

另一个要考虑的非常有趣的方面是我们的模型选择丢弃跛脚鸭的速度。为了说明这一点,我们将向超模型支持的模型列表中添加另一个模型:LinearRegression。

直觉上,这是最糟糕的选择。让我们看看我们的自动模型选择花了多少时间来探索这种可能性。首先,我们将它添加到超模:

向超级模型添加 LinearRegression。作者代码

我们将使用一个肮脏的黑客来测量探索一个给定配置所花费的时间。我们只在第 42 行打印它(信不信由你),并对它执行一些 greps,得到以下统计数据:

  • 线性回归研究了 3 次。
  • 随机森林 17 次。
  • XGBoost 30 次。

值得注意的是,在仅仅 50 次迭代中,我们的模型选择已经学会关注最有前途的模型:XGBoost,并且在仅仅 3 次迭代中就放弃了线性回归。

如果我们使用 ConfigSpace 的条件配置,而不是使用允许参数的白名单,我们可以更快地排除线性回归。这就人为增加了不必要的审判。

结论

扩展模型选择的超参数调整。用几行代码演示它非常容易。

我们一直使用贝叶斯搜索来探索配置空间,但我们也可以使用任何其他有效的超参数调整方法。

另一个值得尝试的想法是使用超参数优化方法进行特征选择。很有可能它也能有效工作。

带有 GCP Dataproc 的 Hadoop

原文:https://towardsdatascience.com/hadoop-with-gcp-data-proc-3c402065f769?source=collection_archive---------11-----------------------

Hadoop、其服务和架构简介

理查德·雅各布斯在 Unsplash 上的照片

今天,大数据分析是世界上发展最快的领域之一,因为人们可以从中获得大量好处。随着其巨大的增长和大量的好处,也带来了自己的一系列问题。存储大数据的一个主要问题是,您需要一个大空间来存储数千万亿字节的数据,这是您无法通过个人计算机实现的。即使你设法存储了大数据的一部分,也需要数年时间来处理它。作为对此的解决方案,Hadoop 是由 Apache 软件基金会开发的。

介绍

先说:Hadoop 是什么?

Hadoop 是一个开源的框架,为存储处理大数据而设计。

因此,Hadoop 提供了两个主要功能,存储大数据处理大数据。我们使用 HDFS (Hadoop 分布式文件系统)存储大数据,使用 MapReduce 处理大数据。在本文的其余部分,我们将更多地讨论 HDFS。

在谈论 HDFS 之前,让我们先来看看 DFS。在分布式文件系统(DFS)中,您将数据分成小块,分别存储在几台机器上。

HDFS 是专门设计的分布式文件系统,用于在商用硬件集群中存储大型数据集。

注:商品硬件是廉价硬件。比如你日常使用的笔记本电脑就是商品硬件。

一般来说,你把文件和目录存储在电脑的硬盘上。一个 HD 分为磁道,然后是扇区,最后是块。通常,硬盘中一个这样的块的大小是 4 KB。

注意:块是操作系统可以指向的一组扇区。

大小为 500 GB 的硬盘中的一组块(图片由作者提供)

如果我想在硬盘上存储一个大小为 2 KB 的文件,它会存储在一个块中,但是会有剩余的 2 KB 空间。HD 无法将剩余空间再次用于其他文件。因此,该空间将被浪费。

现在,在这个硬盘之上,我们将安装带有 HDFS 的 Hadoop。

在 Hadoop 2.x 中,HDFS 的块大小默认为 128 MB(在 Hadoop 1.x 中为 64 MB)

如果我想在 HDFS 存储一个大小为 300 MB 的文件( example.txt ),它将跨三个块存储,如下所示。在块 3 中,将只使用 44 MB。它将有 84 MB 的可用空间,剩余的空间将被释放出来供其他文件使用。

Hadoop 中 300 MB 大小文件的数据分布(作者图片)

因此,Hadoop 比 HD 更有效地管理数据存储。

注意:这里我取了一个 300 MB 大小的文件,仅仅是为了解释这个概念。通常,Hadoop 处理的是太字节大小的非常大的文件!

HDFS 服务

HDFS 有两个主要的服务,即 NameNodeDatanode

NameNode :运行在高端主机上的主守护进程。

DataNode :运行在商用硬件上的从守护进程。

注意:我们为什么对 NameNode 使用高端机器是因为所有的元数据都存储在 NameNode 上。如果 NameNode 出现故障,我们将丢失有关文件每个部分存储位置的所有信息,这最终可能导致无法访问整个 Hadoop 集群。因此,即使数据节点处于活动状态,也不会再使用群集,因为我们将无法访问存储在那里的数据。为了解决这个问题,最常见的做法是使用第二个 NameNode 作为备份。

NameNode

  • 主守护进程
  • 维护和管理数据节点
  • 记录元数据(例如,存储块的位置、文件的大小、权限、层次结构等。)
  • 从所有数据节点接收心跳和数据块报告

注意:Heartbeat 告诉 NameNode 这个 DataNode 还活着。

数据节点

  • 从属守护进程
  • 存储实际数据
  • 为客户端发出的读写请求提供服务

HDFS 的街区复制

为了实现容错,Hadoop 在不同的数据节点上存储数据块的副本。默认情况下,复制因子为 3。也就是说,它将跨数据节点保留集群中任何数据块的三份拷贝。

让我们以之前的 300 MB 文件为例。

HDFS 数据块复制的高级表示(图片由作者提供)

Hadoop 如何决定将创建的块的副本存储在哪里?

它使用机架感知算法。

当客户端请求在 Hadoop 集群中进行读/写操作时,为了最大限度地减少流量,NameNode 会选择离它更近的 DataNode。这称为机架感知。

支持容错的块及其副本在机架中的分布(作者图片)

不应在原始拷贝所在的同一机架中创建数据块的副本。这里,不应在机架 1 中创建数据块 1 的副本。它们可以在机架 1 以外的任何其他机架中创建。如果我将数据块 1 的副本存储在机架 1 中,并且如果机架 1 出现故障,那么我将丢失数据块 1 中的数据。

注意:机架是 30 或 40 个节点的集合,这些节点在物理上紧密地存储在一起,并且都连接到同一个网络交换机。机架中任意两个节点之间的网络带宽大于不同机架上两个节点之间的带宽。

为什么将数据块 1 的两个副本存储在同一个机架(机架 2)上?

这有两个原因。首先,两个机架(机架 1 和机架 2)同时出现故障的可能性最小。其次,将数据文件从一个机架中的一个数据节点移动到同一机架中的一个数据节点所需的网络带宽比将数据文件从另一个机架中的一个数据节点移动要少得多。当不需要额外带宽时,消耗额外带宽是没有意义的。

写 HDFS 的建筑

再回到我们之前的例子,假设我们有一个客户想要存储一个名为 example.txt 的文件,大小为 300 MB。由于他在本地机器上没有足够的空间,他想把它放到 Hadoop 集群中,但是客户端不知道哪些数据节点有空闲空间来存储他的数据。所以客户端首先联系 NameNode。客户机向 NameNode 发送一个请求,说他想把 example.txt 文件放到集群中。

HDFS 书写体系结构的高级视觉表示(作者图片)

现在,NameNode 查看了 example.txt 的文件大小,计算了需要多少个块,以及如何将该文件分割成多个 128 MB 的块。因此,300 MB 的文件将被分成 3 个块,每个块分别容纳 128 MB、128 MB 和 44 MB。我们把文件的每一个拆分叫做 a.txtb.txtc.txt 。之后,NameNode 会快速检查哪些 DataNode 有空闲空间,然后向客户端返回一个响应,说请将 300 MB 的文件存储在 DataNode 1、3 和 5 中。

现在,客户端首先直接访问 DataNode1,在那里存储 a.txt 文件。默认情况下,集群会再保留两个 a.txt 的备份文件。一旦存储了 a.txt ,DataNode1 就将该文件的副本发送到另一个有一些空闲空间的 DataNode,比如 DataNode2。类似地,DataNode2 将该文件的副本提供给另一个 DataNode,比如 DataNode4。一旦 DataNode4 将该文件存储在他那里,他就向 DataNode2 发送一个确认,表示您发送的文件已经存储在我的本地 DataNode 中。同样,DataNode2 向 DataNode1 发出确认,表示您发送的文件已经存储在我的 DataNode2 和 DataNode4 中。现在,DataNode1 将向客户端返回一个确认,表示发送的文件已经存储在 DataNode1、2 和 4 中。

数据节点和客户端之间的相互通信(作者图片)

但是 NameNode 如何知道 a.txt 文件的确切存储位置呢?所有的 datanode 每隔一小段时间就向 NameNode 提供块报告,告诉 NameNode 在各自的 datanode 中有多少块被占用。

注:A 块报告 包含服务器托管的每个块副本的块 ID、代戳和长度。

通过这些块报告,NameNode 相应地更新元数据中的信息。同样的, b.txt 文件, c.txt 文件也会存储在集群中。

当一个 DataNode 关闭时会发生什么?

所有的 DataNode 不时地给 NameNode 一个心跳,这有助于 NameNode 判断 DataNode 是否还活着。如果任何一个 DataNode 没有给出正确的心跳,那么 NameNode 就认为这个 DataNode 死了。假设 DataNode1 死亡。然后 NameNode 会将它从元数据中的 a.txt 文件中删除,并将该文件分配给另一个有空闲空间的 DataNode。假设它被发送到 DataNode7。然后 DataNode7 向 NameNode 发回 block 报告,NameNode 会为 a.txt 更新元数据。

Heartbeat 如何在 Hadoop 集群中工作(作者图片)

阅读 HDFS 的建筑

假设客户想要读取他之前存储的 example.txt 文件。客户端首先联系 NameNode,说他想读取 example.txt 文件。NameNode 将查看它拥有的关于所述文件的元数据,选择每个存储的分割的最接近的副本给客户端,并且将那些数据节点的相关 IP 地址发送回客户端。然后,客户端将直接访问存储数据块的数据节点并读取数据。一旦客户端获得所有需要的文件块,它将组合这些块以形成文件, example.txt

注意:当服务于客户端的读取请求时,HDFS 选择离客户端最近的副本。这减少了读取延迟和网络带宽消耗。

HDFS 里德建筑的高级视觉表现(图片由作者提供)

在开始动手操作之前,让我简要地告诉您关于 Dataproc 的情况。

Dataproc 是用于运行 Hadoop & Spark 作业的托管服务(它现在支持 30 多种开源工具和框架)。可用于大数据处理和机器学习。

下面的实践是关于使用 GCP Dataproc 创建一个云集群并在其上运行 Hadoop 任务。

亲自动手

我将使用谷歌云平台和 Ubuntu 18.04.1 来实现这一点。

首先,您需要设置一个 Hadoop 集群。

  • 选择或创建 Google 云平台项目
  • 您需要创建一个云 Bigtable 实例。首先,启用云 Bigtable 和云 Bigtable 管理 API
  • 现在通过 GCloud shell 创建一个云 Bigtable 实例
gcloud bigtable instances create INSTANCE_ID \
    --cluster=CLUSTER_ID \
    --cluster-zone=CLUSTER_ZONE \
    --display-name=DISPLAY_NAME \
    [--cluster-num-nodes=CLUSTER_NUM_NODES] \
    [--cluster-storage-type=CLUSTER_STORAGE_TYPE] \
    [--instance-type=INSTANCE_TYPE]

通过 GCloud shell 创建 Bigtable 实例

注意:确保使用有云 Bigtable 的集群区域。

  • 启用云 Bigtable、云 Bigtable Admin、云 Dataproc 和云存储 JSON APIs。
  • 通过运行 gcloud components install gsutil安装gsutil工具
  • 安装 Apache Maven ,它将用于运行一个示例 Hadoop 作业。
    sudo apt-get install maven
  • 克隆 GitHub 存储库Google Cloud platform/Cloud-bigtable-examples,其中包含一个使用云 Bigtable 的 Hadoop 作业的示例。 git clone [https://github.com/GoogleCloudPlatform/cloud-bigtable-examples.git](https://github.com/GoogleCloudPlatform/cloud-bigtable-examples.git)
  • 现在创建一个云存储桶。Cloud Dataproc 使用一个云存储桶来存储临时文件。 gsutil mb -p [PROJECT_ID] gs://[BUCKET_NAME]

创建云存储桶

注意:云存储桶名称在所有桶中必须是全局唯一的。请确保为此使用唯一的名称。如果您得到一个 *ServiceException: 409 Bucket hadoop-bucket already exists,* ,这意味着给定的 bucket 名称已经被使用。

  • 您可以通过运行gsutil ls来检查项目中创建的存储桶

检查创建的 Gcloud 存储桶

Gcloud 存储桶

  • 创建一个包含三个工作节点的云 Dataproc 集群。

转到导航菜单,在“大数据”组类别下,您可以找到“Dataproc”标签。单击它并选择“集群”。单击“创建集群”按钮。为您的集群取一个合适的名称,将 Worker nodes 改为 3。点击页面底部的“高级选项”,找到“云存储暂存桶部分”,点击“浏览”并选择您之前制作的桶。如果全部完成,单击“创建集群”并等待几分钟,直到集群创建完毕。

成功创建集群后,它将显示如下。

创建一个 Dataproc 集群

  • 您可以进入创建的集群,然后单击“VM Instances”选项卡。在那里,您可以找到为集群创建的节点列表。

集群中的主&工作者节点

  • 转到目录java/dataproc-wordcount
  • 用 Maven 构建项目
mvn clean package -Dbigtable.projectID=[PROJECT_ID] \
    -Dbigtable.instanceID=[BIGTABLE_INSTANCE_ID]

用 Maven 建造

  • 项目完全构建完成后,您会看到一条“构建成功”的消息。
  • 现在开始 Hadoop 作业 ./cluster.sh start [DATAPROC_CLUSTER_NAME]
gcloud dataproc jobs submit pig --cluster test-hadoop --execute ‘fs -ls /’

Hadoop 作业执行的详细信息

Hadoop 作业的输出

您可以通过以下方式删除云 Dataproc 集群

gcloud dataproc clusters delete [DATAPROC_CLUSTER_NAME]

资源

1 GCP Dataproc 文档

2 GCP 大表例题

干杯!🙂

MLOps 的 Hagakure:合理规模的 ML 的四大支柱

原文:https://towardsdatascience.com/hagakure-for-mlops-the-four-pillars-of-ml-at-reasonable-scale-5a09bd073da?source=collection_archive---------25-----------------------

在启动阶段有效地进行 ML

没有太多操作的 MLOps 第 3 集

与安德里亚·波洛尼奥利和雅格布·塔利亚布埃

朱伟在 Unsplash 上拍照

"不要用弓箭杀死蚊子."

孔子

在本系列的上一集中,我们探讨了我们所谓的“合理规模”(RS),给出了一个有点松散的定义,旨在把握我们认为许多公司目前在 ML 方面所处的状况。

鉴于 RS 公司必须面对的许多重大挑战,本文将阐述一个基于四个主要哲学支柱的框架,同时将这些原则应用到现实世界的问题中。

在提出我们在不断变化的现代传销环境中对传销从业者的实践和精神指导之前——我们对合理规模的传销的haga kure——让我们简单回顾一下 RS 公司面临和解决的主要挑战。**

当在真实的公司中做出实际的选择时,我们在上一篇文章中描述的约束有无数的分支。这部分是由于制约因素的异质性。RS 公司必须始终考虑工程资源、数据量、数据质量、团队规模、用例以及此类用例的货币影响等一系列问题。一个特定组织内部的确切图景可能取决于许多因素,我们应该期望它对该组织来说是有些独特的,这使得很难提出一个单一的成功秘诀。

令人眼花缭乱的 MLOps 供应商并没有让事情变得更简单(见这里和这里)。虽然一些公司倾向于可以在整个 ML 堆栈中采用的端到端解决方案,如 Databricks ,但该行业最近见证了一场快速而无情的功能整合运动。换句话说,越来越多的公司(目前主要是初创公司)正在为 ML 周期的所有步骤开发更成熟的解决方案,从数据仓库到模型部署。现在,这种前景的发展总体上有助于提供一套连贯的解决方案,这些解决方案可以相互集成,但事实是,这个领域的大多数参与者都是独立行动的,这给 ML 从业者留下了一个艰巨的任务,即找到正确的方法来选择他们的工具,并以连贯的方式将它们组合在一起。

因此,再一次,就像每一次对智慧的追求一样,我们的任务是制定一个原则性的框架,而不是指向一个具体的解决方案。由于我们全心全意地赞同精神指导只有在实践中有用才是好的这一观点,我们希望确保这样一个框架能够解决遥感公司的现实问题。

规模合理的 ML 四大支柱

杰里米·珀金斯在 Unsplash 上拍摄的照片

Data is superior to modeling.

Log then transform.

PaaS & FaaS is preferable to IaaS.

Vertical cuts deeper than distributed.

一 DATA IS SUPERIOR TO MODELING

RS 公司更大的边际收益总是在于拥有干净和可访问的数据:好的数据比建模和模型架构的相对改进更重要。

总的来说,行业似乎进入了一个新的阶段,模型功能变得越来越商品化,可能是因为我们在建模方面变得越来越好,开箱即用的模型变得足够引人注目。这一点很重要,因为在内部构建非常有竞争力的模型已经成为 RS 公司的一项更大的投资,而 ROI 可能没有太大意义。

在这种情况下,从战略角度来看,专有数据流至关重要,尤其是对于遥感公司。举个例子,由 Chris Re 和最近由吴恩达倡导的以数据为中心的人工智能框架,它专注于数据集优化以提供一个坚实的基础,其中数据收集受到限制,训练样本天生稀缺,迭代不可能超快(你可能记得我们的第二集,这是 RS 的关键原则)。

这一原则的第一个结果是,数据摄取是您的 MLOps 周期的一等公民,获得清晰的数据应该是最终目标。

简单地说,数据摄取必须包括通过标准获取数据。你可以选择一个已经存在的特定领域的协议(例如 Google Analytics 用于浏览事件),或者如果你的数据对你的业务来说有些独特,你可以提出自己的标准。

然而底线是相同的:两个描述完全相同事物的事件绝不会有不同的结构。例如,假设我们正在构建一个推荐系统,我们正在从不同的电子商务网站收集添加到购物车的操作:在任何情况下,来自网站 A* 的添加到购物车事件都不应该与来自网站 B 的添加到购物车事件不同。对于这条规则的每一个例外,迟早都要付出代价。*

与标准化这一点密切相关,我们可以补充一点关于严格验证和拒绝。一般来说,即使事件不符合约定的标准格式,也不应该被拒绝。系统应该标记所有格式错误的事件,将它们发送到不同的路径,并通知警报系统。虽然形式不良的事件不会出现在我们的表中是非常重要的,但知道什么时候出错也是非常重要的。

二 Log then transform

数据接收和处理之间的明确分离产生了可靠且可重复的数据管道。数据仓库应该包含系统在任何给定时间的每个状态的不可变的原始记录。

因此,数据管道应该总是从原始事件构建,并在流和处理之间实现明显的分离。前者的作用是保证任何给定系统状态的真实快照,后者是为最终目的准备数据的引擎。

关键的区别在于,流的输出是不可变的,而处理的输出总是可以撤消和修改的。如果您从小就认为数据库是关于写入和转换数据的,那么这里的想法有些违反直觉,但是它的核心非常简单:模型总是可以固定的,而数据却不能。

这个原则的北极星是你的系统是否允许可重复性。主要的问题是:你能在数据转换、查询或模型中改变一些东西,然后重放自时间开始以来你摄取的所有数据,而没有任何大问题(时间除外)吗?如果答案是肯定的,那么您成功地将这一原则应用到了您的数据基础架构中。如果答案是否定的,你真的应该试着把它变成肯定的,在不可能的情况下,尽可能地接近它。

在我们系列的下一集,我们将更详细地讨论数据摄取以及流和处理之间的分离,我们还将分享基于雪花 + dbt 的开源实现。

三 PaaS & FaaS is preferable to IaaS

专注是 RS 的精髓。不要构建和管理 ML 管道的每个组件,而是采用完全托管的服务来运行计算。

RS 公司的主要特点是,它们在 ML 计划的资源方面受到这样或那样的限制。当然,当资源有限时,将资源投入到最重要的业务问题中是一种很好的做法。例如,假设您正在构建一个推荐系统,您可能希望尽可能地专注于提供好的推荐。就这么简单。

当然,倾向于完全托管服务的方法在硬成本方面往往更昂贵,但与此同时,数据科学家可以不必担心停机、复制、自动扩展等问题。所有这些都是必要的,但这并不意味着它们是您的 ML 应用程序的中心,根据我们的经验,让您的组织专注于核心业务问题的好处往往超过低成本的好处(当然,在合理的范围内)。因为由专门的人员维护和扩展基础设施仍然很昂贵,所以最终很容易就会比支付和管理少数新提供商的费用高得多。

此外,建设和维护基础设施最糟糕的一点是,随着时间的推移,实际成本是不可预测的。不仅很容易低估长期所需的全部努力,而且每次你为了构建一个基础设施而创建一个团队时,你都引入了人的因素的典型的不可预测性。

最终需要多少人?他们会在一年后被公司吸收吗?组织内的护城河是因为角色的过度分离还是因为一些团队的唯一目的是保持基础设施的正常运行?

消费账单很少有积极的方面,但有一点是肯定的,那就是它们很容易预测。如果你想更大规模地预测成本,你可以将你的账单乘以任何你认为能抓住你成长道路下一阶段的数字。

四 Vertical cuts deeper than distributed.

RS 公司不需要在每一步都进行分布式计算。高效的垂直设计可以实现很多目标。

这可能是我们做出的最有争议的声明,但是坚持我们的观点,这是有原因的。分布式系统,如 Hadoop 和 Spark ,在大数据革命中发挥了关键作用。仅仅在五年前,Spark 几乎是大规模进行 ML 的唯一选择。世界各地的初创公司都使用 Spark(我们也不例外)进行流传输,SparkSQL 进行数据探索,MLlib 进行功能选择和构建 ML 管道。

然而,它们使用起来很麻烦,很难调试,而且它们还强制许多科学家不熟悉的编程模式,这对新员工的增加时间有非常负面的影响。

我们想表达的观点很简单:如果你是一家 RS 公司,你要处理的数据量不需要无处不在的分布式计算:有了好的垂直设计,就有可能在显著改善开发人员体验的同时完成大部分工作。

总的想法是,您的 ML 管道应该被视为贯穿许多模块化步骤实现的 DAG。现在,虽然其中一些可能需要更多的计算能力,但是重要的是从 ML 开发的过程和经验中抽象出计算部分。

分布式计算应该用于它真正的用途:解决大量复杂的数据问题。对于其他所有事情,更实际的做法是在单独的盒子中运行管道中的步骤,在云基础设施中扩展计算,并且只在中扩展需要的步骤,例如 Metaflow 允许这样做。

在我们的经验中,这种观点的转变对任何 ML 团队的开发人员体验都有巨大的影响,因为它会给数据科学家一种在本地开发的感觉,而不必一直经历处理分布式计算的重重困难和障碍。

爱你的开发者:关于垂直独立性的推论。

最后两点旨在尽可能地从 ML 开发者那里抽象出基础设施。这种哲学有很好的理由存在。

我们希望鼓励 ML 团队的纵向独立性。ML 中的许多工作在很大程度上取决于所解决问题的类型,因此数据科学家需要能够根据数据集、数据类型、算法和安全约束对工具、架构和建模做出合理的独立选择。此外,ML 系统不是针对静态环境部署的,因此数据科学家需要了解数据中的变化、模型中的变化、敌对攻击等等。我们倾向于纵向独立,而不是嵌入到高度条块化的组织中,因为在这种情况下过度专业化会导致高协调成本、低迭代率和适应环境变化的困难。最后,我们痛苦地意识到,在 RS 公司必须进行预算的所有资源中,最稀缺的是优秀的工程师。

我们认为,在吸引和留住 RS 公司的关键人才方面,垂直独立性非常重要。我们经常听到数据科学家仍然将相当大一部分时间投入到低影响任务中,例如数据准备、简单分析、基础设施维护以及更普遍的跳过繁琐流程的束缚。

根据我们的经验,优秀的工程师和数据科学家会对使用最好的工具做前沿工作感到兴奋。糟糕的开发体验以及无法看到他们的工作在生产中的影响是数据科学家感到沮丧的主要原因之一。我们都知道,沮丧的工程师更有可能在 LinkedIn 上回复招聘人员的信息。

纵向独立在创新速度、最小化、精简和自由方面获得回报:RS 组织最有价值的硬币。让您的数据科学家拥有从获取数据到生产测试的整个周期的可能性,让他们尽可能容易地在整个端到端管道的不同阶段来回移动,并赋予他们权力。这样做,他们会开发出具有真正商业价值的可靠应用程序,让你大吃一惊。

无耻的下一个帖子的悬念

这些是我们在 RS 规模生产中 ML 的原则。采用它们使我们能够成功地大规模工作,同时最大限度地减少所有可能的基础架构问题,否则我们将不得不处理这些问题。请记住,我们所做的一切都是受 RS 公司所受约束的激励。最终目标永远是做 DataOps 和 MLOps,而不做太多的 Ops。

在下一篇文章中,我们将更深入地探讨前两个原则,并设计出一个具体的数据接收和数据处理管道示例,它完全可以用无服务器、雪花和 dbt 来重现。

承认

如果没有我们开源贡献者的承诺,这个系列是不可能的:

  • Patrick John Chia :局部流量和基线模型;
  • Luca Bigon :通用工程和基础优化;
  • Andrew Sutcliffe :远程流;
  • Leopoldo Garcia Vargas :质量保证和测试。

优雅地处理聊天机器人故障

原文:https://towardsdatascience.com/handling-chatbot-failure-gracefully-466f0fb1dcc5?source=collection_archive---------3-----------------------

用 Rasa 构建聊天机器人——第三部分

作者图片

不管你训练 Rasa 聊天机器人有多好,总会有机器人不知道如何处理的情况。我们的目标不是制造一个完美的防故障聊天机器人,因为这甚至是不可能的。事实上,作为人类,我们自己也经常要求澄清。更确切地说,我们的目标是在事情变糟时让系统就位。

比起被误解,人们更喜欢被要求澄清。当然,要求用户重复五次并不理想,这也是为什么要有后备系统的原因。

在本帖中,我们将讨论如何处理你的机器人不太明白用户想说什么的情况。在 Rasa 术语中,这被称为回退。

快速注释

这是我关于 Rasa 系列的下一篇文章。您可以查看以下系列的前几篇文章:

在那里,我们讨论了 Rasa 和聊天机器人的基本组成部分,如果你是 Rasa 新手,通读前两篇文章肯定会有所帮助。

目录

- An example
- The Fallback Classifier
- Simple Fallback
- Single-stage Fallback
- Two-stage Fallback
- Handling Human Handoff

一个例子

我们将看一个没有后备机制的简单例子,然后我们将从那里开始。

让我们继续使用本系列中使用的聊天机器人——它要求用户提供联系信息。我们将通过减少我们的DIETClassifier的训练次数来模拟回退场景,它试图理解用户在说什么。

缺省情况下,缺省配置文件(运行 rasa init 时获得)有一个FallbackClassifier组件。我们将在这里做两处更改:

  • 我们将删除FallbackClassifier组件,看看会发生什么。
  • 我们也将减少DIETClassifier2的训练周期,所以模拟一个难以察觉的短语。
language: enpipeline:
- name: WhitespaceTokenizer
- name: RegexFeaturizer
- name: LexicalSyntacticFeaturizer
- name: CountVectorsFeaturizer
- name: CountVectorsFeaturizer
  analyzer: char_wb
  min_ngram: 1
  max_ngram: 4
- name: DIETClassifier
  **epochs: 2 # reduced epochs**
  constrain_similarities: true
- name: EntitySynonymMapper
- name: ResponseSelector
  epochs: 100
  constrain_similarities: true
**# removed the FallbackClassifier from here**policies:
- name: MemoizationPolicy
- name: TEDPolicy
  max_history: 5
  epochs: 100
  constrain_similarities: true
- name: RulePolicy

训练完机器人后,我们将使用

rasa shell --debug

对话大概是这样的:

user: Hi
bot: Sorry, you'll have to provide your information to proceed.

这完全没有意义。仔细查看调试日志,我们看到了以下内容:

Received user message 'hi' with intent '{'id': -4215159201959237708, 'name': 'deny', 'confidence': 0.37452369928359985}' and entities '[]'

机器人预测用户的消息“嗨”是一个deny意图,而不是greet意图。机器人的响应可能会让用户感到困惑,这在实际项目中会更加明显,在实际项目中,您通常会有许多意图和大量数据,在某些情况下,这些数据可能会有点相似。

现在,让我们看看当我们只在配置中包含FallbackClassifier而没有实际设置整个机制时会发生什么。

添加到管道末端:

- name: FallbackClassifier
  threshold: 0.5
  ambiguity_threshold: 0.1

和重新训练,当用户说“嗨”时,我们看到日志中的变化:

Received user message 'hi' with intent '{'name': 'nlu_fallback', 'confidence': 0.5}' and entities '[]'

它不再预测具有最高置信度的意图,即使它真的很低。现在,FallbackClassifiernlu_fallback覆盖了这个意图。在我们继续回退机制之前,我们将讨论回退分类器。

回退分类器

回退分类器实现两个阈值:

  • 民盟的退路threshold
  • ambiguity_threshold

后退分类器阈值-按作者分类的图像

在您的配置文件中,它是在意图分类器之后定义的,如下所示:

language: en
pipeline:
   ..
   ..
   # intent classifier like DIETClassifier defined here
   - name: FallbackClassifier
         threshold: 0.7
         ambiguity_threshold: 0.1

(NLU 回退)阈值

threshold键用于指定config.yml中 NLU 回退的阈值。如果 top intent 的置信度低于这个值,则回退分类器忽略它并继续进行nlu_fallback

模糊阈值

该键指定了前两个意图的置信度应该是多少,以继续常规对话流。如果置信度得分的差值比这里指定的值少,则不管是否满足threshold条件,回退分类器都使用nlu_fallback

简单的退路

简单的退路——作者图片

这种回退是最基本的:当你的机器人预测用户的意图低于某个阈值(nlu_fallback_threshold)时,我们将简单地将聊天转移到一个人类代理。

现在,将聊天转移到人工代理的实际机制,称为“人工移交”,取决于您的聊天机器人部署的方式和位置。为了让这适用于每个人,我们将创建一个占位符自定义动作,该动作将返回一个transferred_to_human标志,只是为了让我们知道它正在工作。

我们来实施吧。

添加规则

我们首先需要定义一个rule,每当nlu_fallback被预测时,运行action_default_fallback。将此添加到rules.yml:

# simple fallback:
- rule: Implementation of the simple-Fallback
  steps:
  - intent: nlu_fallback
  - action: action_default_fallback

履行

接下来,我们将覆盖action_default_fallback。简单地将这个类添加到actions.py:

class ActionDefaultFallback(Action):def name(self) -> Text:
        return "action_default_fallback"def run(self, dispatcher, tracker, domain):
        # output a message saying that the conversation will now be
        # continued by a human.

 **message = "Sorry! Let me connect you to a human..."
        dispatcher.utter_message(text=message)**# pause tracker
        # undo last user interaction
        return [ConversationPaused(), UserUtteranceReverted()]

我们还将在actions字段下的域中定义它。

测试

我们现在有了更好的体验。

user: Hi
bot: Sorry, couldn't understand that! Let me connect you to a    
     human...

请记住,经过适当训练的机器人几乎肯定能够对“嗨”做出反应。在这里,我们只是模拟一个机器人无法理解的用户消息。

如果您查看日志,可以看到 Rasa 正确地应用了我们定义的规则。

**rasa.core.policies.rule_policy -** There is a rule for the next action 'action_default_fallback'.

单阶段回退

单阶段回退机制—图片由作者提供

简单的退路比继续进行几乎肯定会失败的对话要好。

但是我们可以做得更好。如果你的机器人不太确定用户想说什么,我们可以让机器人通过提供建议来澄清用户的意思,而不是仅仅执行移交。

当然,即使在这之后,如果机器人仍然没有得到用户想要说的话,我们可以进行切换。

这将更加有用,因为

  • 它减轻了人类的负担
  • 它让用户参与的时间更长,因为如果目前没有人可用,他们很可能没有耐心等待。

默认情况下,当请求澄清时,机器人会以最高的可信度暗示意图。

The utter_ask_rephrase response —图片作者使用 carbon.now.sh

您可能会注意到这里有两件事:

  • 仅建议最高意图,而不是提供,比如说,前 3 个预测
  • 使用 NLU 定义的意向名称。对用户来说不是一个很好的体验,特别是对于那些有更多隐晦措辞的意图。

我们可以通过覆盖一个叫做action_default_ask_affirmation的方法来解决这两个问题。

让我们实现这一点。

添加相关规则

这比前一个案子要复杂一点。我们将在这里定义两条规则。

nlu_fallback →向用户提供建议

一旦机器人无法理解用户,它将提供用户可能想要表达的意思的相关建议。这里,我们将执行被覆盖的action_default_ask_affirmation自定义动作,稍后我们将实现它。

- rule: Single stage fallback | ask user to choose what they meant
  steps:
  - intent: nlu_fallback
  - action: action_default_ask_affirmation

用户不喜欢建议→人工交接

第二个规则是当用户不想继续任何提供的建议并点击一个类似“这些都不要”的选项时(我们也将实现这个选项)。它被映射到默认的out_of_scope意图。

当这种情况发生时,我们希望将用户直接连接到人,所以我们将调用action_default_fallback

- rule: Single stage fallback | call default fallback if user is not ok
  steps:
  - action: action_default_ask_affirmation
  - intent: out_of_scope
  - action: action_default_fallback

覆盖默认确认自定义操作

我们将做两件事来解决上面提到的问题:

  • 在意图和易读的措辞之间建立一个映射。类似于:supply_contact_info --> "Supply Contact Information"
  • 向用户提供前三个意向预测作为建议,而不仅仅是前一个,这样用户更有可能找到他们想要的。
class ActionDefaultAskAffirmation(Action):def name(self):
        return "action_default_ask_affirmation"async def run(self, dispatcher, tracker, domain):
 **# select the top three intents from the tracker**        
        **# ignore the first one -- nlu fallback**
        predicted_intents = tracker.latest_message["intent_ranking"][1:4]**# A prompt asking the user to select an option**
        message = "Sorry! What do you want to do?"**# a mapping between intents and user friendly wordings
**        intent_mappings = {
            "supply_contact_info": "Supply Contact Information",
            "affirm": "Agree",
            "deny": "Disagree",
            "goodbye": "End conversation"
        }**# show the top three intents as buttons to the user**
        buttons = [
            {
                "title": intent_mappings[intent['name']],
                "payload": "/{}".format(intent['name'])
            }
            for intent in predicted_intents
        ]**# add a "none of these button", if the user doesn't
        # agree when any suggestion**
        buttons.append({
            "title": "None of These",
            "payload": "/out_of_scope"
        })dispatcher.utter_message(text=message, buttons=buttons)return []

注意对于某些意图,您可能不希望它们作为建议出现。“你想问候我吗?”听起来不错。如果这样的意图是前三个中的一个,可以添加一个简单的检查来确保用户不会把它看作是一个建议。

记得将action_default_ask_affirmation作为注册动作添加到您的域中。

测试

我们将尝试与之前相同的对话流程。

测试单级回退机制—图片由作者使用 carbon.now.sh 提供

这比以前好多了。现在让我们尝试第三种策略。

两阶段回退

两阶段回退是最近才引入的。它让用户两次阐明自己(通过向他们建议可能的行动),然后开始最终的后退。

两阶段回退机制—作者图片

虽然看起来很复杂,但是 Rasa 已经实现了,所以设置起来要容易得多,特别是因为我们已经用前两种方法完成了一半的工作。

添加要求用户重新措辞的响应

Rasa 提供了名为utter_ask_rephrase的默认响应。当然,还有一个名为action_default_ask_rephrase的默认自定义动作,您可以覆盖它来实现自定义行为,就像我们之前对action_default_fallbackaction_default_ask_affirmation所做的那样。

现在,我们将只使用响应。我们将在domain.ymlresponses字段下定义它。

utter_ask_rephrase:
  - text: I'm sorry, I didn't quite understand that. Could you rephrase?

添加两阶段回退规则

我们将用这个替换以前的单阶段回退方法的规则。

# two stage fallback:
- rule: Implementation of the Two-Stage-Fallback
  steps:
  - intent: nlu_fallback
  - action: action_two_stage_fallback
  - active_loop: action_two_stage_fallback

没有必要进行其他更改。

测试

流程是这样的:

测试两阶段回退策略—图片由作者使用 carbon.now.sh 提供

当人工交接不成功时你会怎么做?

有时,即使在用户多次澄清后,你的机器人可能不明白他们想说什么。在这种情况下,明智的做法是让用户知道他们现在将连接到一个人,然后将对话转移到一个人可以访问的地方。

发送跟踪器和帮助,因为人类现在已经有了对话的上下文,这意味着用户不必从头开始他们的请求。

即使在这之后,也可能没有人来照顾这个用户。可能用户处于不同的时区,或者所有客户服务代理都被占用。有时,将用户连接到代理的机制可能会中断。在这种情况下,与其让用户等待不知道如何继续,不如通知他们这个问题是有意义的。

除了一条简单的消息,说明人工代理目前不可用,以及一些功能,让用户留下消息或提供他们的联系方式,以便以后可以联系到他们。

示例代码

https://github.com/Polaris000/BlogCode/tree/main/FallbackExample

该系列的其他文章(这是第三篇)

第一部分:用 Rasa 构建聊天机器人

第二部分:槽和实体一样吗?

第四部分:聊天机器人是如何理解的?

结论

不管你的机器人有多好,总会有机器人不理解用户想说什么的情况,尤其是在开发的早期。你可能有很好的数据来训练你的机器人,但它可能不代表真实用户会如何交谈。

在构建聊天机器人时,学习如何优雅地失败是很重要的。毕竟,即使作为人类,由于从语言到糟糕的网络质量等过多的沟通问题,我们也可能经常不得不这样做。

最终,我写这篇文章的目的是让你知道在为你的机器人设计后备策略时可能会发生什么。

希望有帮助!

更新

20.3.2022

添加到系列中其他帖子的链接

处理数据偏差

原文:https://towardsdatascience.com/handling-data-bias-9775d07991d4?source=collection_archive---------29-----------------------

走向伦理人工智能的旅程

由路易斯·里德在 Unsplash 上拍摄的照片,由作者编辑

如果你也有一个愿景,那就是确保你正在开发的产品遵循“人工智能永远有效”的所有书面规则,那么你肯定会遇到你的数据有偏差的情况。

有偏见的模型、有偏见的数据或有偏见的实现——是数据科学家生活中的典型悲哀。因此,首先我们需要理解并承认偏见的存在,并且可以采取任何形式。

是的,偏差是一个宽泛的术语,它可以出现在数据收集、算法中,甚至出现在 ML 输出解释阶段。

由作者使用 PowerPoint 创建

偏见为什么会伤人?

基于种族、年龄或性别等人类特征的偏见会导致不同的机会,应该予以制止

根据斯坦福大学的人工智能指数报告,人工智能/人工智能组织认为以下风险在行业中普遍存在,并且正在努力减轻这些风险,因为它们对他们的业务和人类普遍有害。

AI 指数报告

数据偏差可以有多种形式:

  • 结构偏差:数据可能会有纯粹的偏差,因为它是由结构差异决定的。女性代表护士、厨师、教师,这显然是从社会结构中衍生出来的。一家电子商务巨头试图建立一个招聘工具,以获取他们现有员工的细微差别,这不用说,是有偏见的。许多属性,如运动、社交活动、成就等,都是由机器挑选的,这导致了一个偏向男性的工具。
  • 数据收集:数据收集偏差的可能原因可能基于一天中的时间、人群的年龄组、原籍国、阶级阶层等。输入算法的数据应该不断更新,以反映我们生活的世界的真实情况,进而反映我们想要预测的世界的未来状态。
  • 数据操作:更容易删除没有附加标签或缺少值的实例。但重要的是要检查被剔除的观察值是否会导致性别、种族、国籍和相关属性的错误数据。
  • 算法偏差:算法将学习数据模式建议它学习的内容。该算法要么反映了普遍的偏见,要么放大了这些偏见,这是我们最担心的。如果判断偏向于特定人群,那么机器也会从训练数据中学习。算法中的偏差源于数据,这些数据要么不是正确的代表,要么是源于现存的偏见。如果输入数据是不平衡的,那么我们需要确保算法仍然看到足够多的少数类实例,以便对其执行良好。有多种方法可以实现数据重新平衡,主要方法包括创建合成数据,或者分配类权重,以便算法对少数类的每个错误预测施加更高的惩罚。
  • 实现偏差:所有的 ML 模型都建立在训练和测试数据集应该属于相似分布的基本假设之上。根据夏季数据训练的模型可能具有不同的特征分布,因此不适合预测冬季的消费者行为。只有当新数据与过去观察到的数据相似时,该模型才会表现良好。不仅仅是执行,解释也可能有偏差。如果我们在分析算法输出的过程中,试图叠加我们的信念并支持我们的(有偏见的)观点,会怎么样呢?

虽然偏见是我们追求道德人工智能框架时需要改善的因素之一,但减轻它肯定不是小事。

构建“人工智能为善”生态系统的一些重要方面是:

  • 数据收集者、开发人员和产品经理通常是在现场工作的人,他们更接近数据。对于组织来说,重要的是提高员工的敏感性,并传播对偏见的可能原因以及如何减轻偏见的认识
  • 拥有一位擅长识别偏见来源的专家(人工智能伦理学家)可以帮助企业将他们的愿景与道德框架相一致
  • 一个由来自不同团队的人组成的治理团队,如隐私、道德、合规、产品和工程,将有助于提供一个新的视角来识别可能被忽略的偏见。

没有一个规则手册可以立刻阅读和实施,它是一个不断发展的框架。

此外,值得称赞的是,维护一个不偏不倚、公平和可信的人工智能框架的努力不再被视为深奥的东西,而是在全世界范围内获得了正确的关注。

构建机器学习应用程序时处理数据稀缺

原文:https://towardsdatascience.com/handling-data-scarcity-while-building-machine-learning-applications-e6c243b284b0?source=collection_archive---------16-----------------------

启动应用程序的实用技术

图 1 模型生长模拟:从幼苗到健康植物(图片来源: Pixy

数据稀缺是指 a)标记的训练数据数量有限或完全缺乏,或 b)与其他标签相比,某个标签缺乏数据(也称为数据不平衡)。较大的技术公司倾向于访问丰富的数据,尽管他们可能会遇到数据不平衡的问题。较小的技术公司通常会受到标记训练数据可用性有限的困扰。在这篇文章中,我将分享我如何处理可用训练数据量很低的情况的笔记。

当训练机器学习模型时,一般的经验法则是在你的数据集中每个自由度至少有 10 个例子(这篇文章很好地概述了什么是自由度)。随着自由度的增加,对训练合理模型所需的数据量的需求也在增加。

此外,在选择模型类型时,考虑可用的训练数据量也很重要。图 2 比较了传统机器学习模型(示例:逻辑回归)v/s 深度学习方法的离线模型性能度量。当有更多训练数据时,深度学习的表现会好得多。另一方面,当数据量很小时,这种类型的模型过拟合的可能性很高。

图 2 深度学习 v/s 传统 ML 方法相对于数据集规模的性能。

让我们来看一些场景和适合它们的方法。

从启发式开始

图 3 一株幼苗(图片来源: Freepik )

让我们考虑几个数据可用性可能较低的例子:1)一家初创公司正在尝试将机器学习模型添加到其产品中,2)一家大公司的团队创建了一个相当新的产品,并希望应用机器学习来优化某个问题。幼苗的比喻恰当地描述了这种情况(图 3)。在这种情况下,如何构建机器学习模型呢?经历过类似的情况后,我认识到从简单的启发式开始很有效。启发式有几个优点:

  1. 它们不需要大量的数据,可以通过直觉或领域知识来创建。
  2. 它们具有高度的可解释性。通常的问题是“为什么一个模型预测某个东西是垃圾邮件?”可以通过查看代码或记录给定查询触发的代码路径来回答。
  3. 一般来说,它们不会遇到典型的机器学习流水线的问题和复杂性:数据偏斜、代码偏斜、模型陈旧、对特征分布变化的敏感性等。

为了进一步解释这一点,让我们更深入地研究一下这家初创公司的例子——假设这家初创公司的主要产品是一款移动应用程序,它可以根据设备的地理位置来获取相关的本地新闻。在这里建立一个机器学习模型会很难,因为没有带标签的数据。然而,启发式模型仍然是可能的。我们可以考虑几个信号来确定给定新闻文章的排名:1)地理位置匹配后的相关性分数(由底层 IR 系统如 ElasticSearch 返回的分数),2)基于发布时间的文章新近度,以及 3)发布者的预定流行度分数(假设范围是[1,5],其中 5 是最受欢迎的,1 是最不受欢迎的)。这些信号可以用一个线性函数来组合:

w1 * f1 + w2 * f2 + w3 * f3

其中{w1,w2,w3}表示特定信号的强调(也称为权重)的数字概念,而{f1,f2,f3}是上面提到的 3 个信号。检索新闻文章并对其进行排名的逻辑可以用两个阶段来表达:

  1. 检索给定地理位置的匹配新闻文章(及其相关性分数)。删除相关性分数低于阈值的文章(阈值可以使用轶事示例来选择)
  2. 对新闻文章的结果集应用线性启发式模型以生成“分数”。根据该分数对文章进行排序,以生成最终结果。

启发式模型中的权重可以被适当地调整,直到新闻馈送的定性分析看起来是最优的。这种方法可以很好地将产品推出市场。随着更多的数据变得可用,直觉/领域知识可以与来自数据的洞察力相结合,以进一步调整启发式模型。一旦你有了足够的用户交互数据,你可以运行逻辑回归来找到正确的权重。接下来的步骤是建立一个模型再培训管道。您的设置越复杂,您就越需要关注数据质量、模型性能质量等。从这一节中要学到的关键点绝对可以接受用试探法来优化某种产品体验,尤其是当数据量很低的时候。

外部 API

图 4 从农民手中购买水果(图片来源: Pxhere

有些场景需要使用最先进的技术来解决特定产品的问题,而启发式方法不是开始的选择。例如,图像中的对象识别——给定一张图像,识别人、动物、建筑物、车辆等。在这种情况下,有几个 API 提供者: AWS Rekognition , Google Cloud 的 Vision AI 仅举几个例子,它们提供的 API 可以用来检测图像中的对象,执行人脸识别,检测图像中的文本等。用一种可以利用这些 API 的方式来分解你的问题可能是一个起步的好方法。图 4 为这种情况提供了一个类比:你可以从农民那里购买水果,而不是自己种植。这里举个例子:你想构建一个应用程序,识别一个图像中人穿的鞋的具体品牌(让我们把品牌限定为 Adidas、Nike 和 Puma)。设计这个问题的解决方案的一种方法是使用视觉 API 来检测图像中的鞋子以及鞋子上的文本。您可以使用结果信息(鞋上的文本加上检测到的鞋对象)来推断鞋属于特定品牌。与另一种方法相比,这种方法更容易实现,后者需要建立一个模型,在给定输入图像的情况下,直接检测特定品牌的鞋子。考虑到流行的 API 提供商提供的免费层的可用性,成本影响通常很小。

综合数据

图 5 施于土壤以帮助植物生长的肥料(图片来源: Pixabay

解决标签数据缺乏的一个方法是为你的特定问题人工制造合成数据。在机器学习中使用合成数据来捕捉在训练数据集中看不到但理论上可能存在的示例。例如,在构建对象识别应用程序时,用户可能会将相机以某个角度指向某个对象(比如一只鹿),而不是直接指向它。为了正确识别对象,可以旋转原始对象图像,并将其作为具有相同标签的新示例插入到数据集中。这将有助于模型了解在不同角度拍摄的图像对应于同一物体。

合成数据有用的另一种情况是当数据集严重不平衡时,即与其他类相比,某个特定类的代表性过高。这方面的一个例子是垃圾邮件检测问题,其中正面例子的数量比负面例子少(垃圾邮件令人讨厌但很少)。通常,垃圾邮件占整个数据集的 0.1%到 2%。在这种情况下,使用类似于 SMOTE 的技术对于在您的数据集中生成更多稀有标签示例非常有用。但是,这样做也有不好的一面-生成的数据可能不代表真实世界的数据,这可能会导致模型性能出现问题。

迁移学习

图 6 嫁接樱桃树(图片来源:维基百科)

如果您可以使用大量可用的非特定领域数据,并训练一个能够为特定领域任务工作的模型,这不是很神奇吗?这可以通过迁移学习来实现。这项技术本身就值得写一整篇博文,但是我将在这里提供一个简要的概述。

考虑一个例子:你想训练一个分类器,将一条推文分为积极、消极或中性情绪。你只有为数不多的 100 条正面、负面和中性的推文,这些推文是你手动标记的(由你自己或使用外部标记服务,如亚马逊土耳其机械)。你的目标是训练一个与最先进的情感分类模型不相上下的模型。

在这种情况下,你可以利用在 ULMFiT 论文中描述的迁移学习技术(我过去也使用过 ULMFiT)。这个想法是首先学习一个基础语言模型。语言模型本质上是在给定单词输入序列的情况下预测序列中下一个单词的概率的模型。维基百科数据集可以用来训练语言模型(截至 2021 年 1 月,的最新数据集拥有超过 37 亿个单词)。在第一步中,生成的语言模型学习通用领域(维基百科)中的语言表示。第二步是“微调”目标数据集上的第一个模型(使用您的 100 个 tweet 示例)。微调步骤包括与第一步相同的设置(语言建模),不同之处在于模型现在被训练以捕捉目标数据集(tweets)中的特质。这里的直觉是推文中的语言不同于维基百科文章中的语言,因此有必要捕捉这种差异。第三步也是最后一步是训练微调后的模型能够对情绪进行分类,而不是预测下一个单词。一种方法是删除微调模型的最终分类层,代之以用于特定任务的分类层——情绪预测,由用于多类分类问题的 Softmax 层处理。图 7(取自 ULMFiT 论文的图像)显示了训练神经网络的 3 个步骤。更多细节请参考论文【1】。

图 7 乌尔姆菲特的三个阶段(图片来源:乌尔姆菲特论文【1】)

研究表明,迁移学习有助于大幅度提高目标任务的准确性。直觉上,这是有道理的。一个类比是,一个知道如何走路/跑步的人可以比一个试图直接学习如何滑冰/滑雪的人更快地学习如何滑冰/滑雪。

最后,以一个植物类比来结束,图 6 显示了一棵樱桃树被嫁接。嫁接具有类似的优点:a)增强植物对某些疾病的抵抗力 b)通过利用适应的宿主植物等使品种适应不利的土壤或气候条件。

结论

总之,以下是我在处理少量训练数据时遵循的一组通用步骤:

  1. 尽可能使用启发式方法。例如,由领域专家手动调整权重来优化项目排名是一个良好的开端。
  2. 如果可能的话,委派。以一种可以利用外部 API 的方式分解问题。
  3. 试验合成数据,尤其是在数据集严重不平衡的情况下。
  4. 尝试迁移学习。要知道这一步的时间投入可能很高。

你如何处理数据稀缺的问题?请随意留下你的想法。

参考

  1. 霍华德,j .,&鲁德,S. (2018)。用于文本分类的通用语言模型微调。 arXiv 预印本 arXiv:1801.06146 。https://arxiv.org/abs/1801.06146v5

在 AWS 中处理地理空间数据

原文:https://towardsdatascience.com/handling-geospatial-data-in-aws-a82ae364f80c?source=collection_archive---------13-----------------------

美国宇航局在 Unsplash 拍摄的照片

数据工程

简要介绍如何使用 AWS 存储、处理、分析和可视化地理空间数据

随着数据库、仓库、分析和可视化工具扩展其处理地理空间数据的能力,我们比以往任何时候都更有能力捕捉和使用 GIS 数据。虽然单个产品支持 GIS,但云提供商并没有在早期提供完整的 GIS 解决方案。随着时间的推移,这种情况已经发生了很大变化。像 AWS 这样的云提供商在任何需要的地方都提供支持。对于像 AWS 这样的软件公司来说,我们需要理解他们构建的产品的选择直接受到通常是他们的高收入客户的需求的影响。

现在,许多公司看到了对地理空间数据的需求,并且这些公司能够以合理的低成本获取和存储地理空间数据(因为位置数据无处不在,存储变得越来越便宜),我们已经看到地理空间数据库、分析和可视化工具被更广泛地采用。虽然 AWS 没有一个成熟的地理空间数据解决方案,但它确实在不同的服务中提供了一些很好的功能。在这篇文章中,我们将对此进行一些讨论。

关系数据库

AWS 有两个托管关系数据库服务— RDS 和 Aurora。很明显,您可以使用 EC2 安装自己的关系数据库,但这不是一个托管解决方案,所以我们在这里不做讨论。地理空间数据的高效存储对于我们今后想用这些数据做的任何事情都非常重要。

AWS RDS 只支持它正在运行的任何版本的关系数据库服务,因此对 GIS 的支持取决于数据库的版本。例如,如果您运行 MySQL 的 RDS,那么您将拥有该 MySQL 版本支持的 PostGIS 特性。如果您运行 PostgreSQL,您将需要在 RDS 上运行的 PostgreSQL 上安装 PostGIS 扩展。

在 AWS RDS PostgreSQL 上安装 PostGIS 扩展的示例脚本。

另一方面,使用 Aurora,它是 AWS 为不同的关系数据库编写的一个引擎,您可以在最初版本的关系数据库所支持的通常特性的基础上获得一些额外的特性、改进和优化。例如,阅读Aurora 如何通过使用 Z 顺序曲线优化地理空间索引。

仓库、湖泊和可视化

红移虽然基于红移,但最长时间没有支持地理空间数据,终于在 2019 年推出了对它的支持。目前,在 Redshift 中,我们可以使用 find 和使用原生 GIS 数据类型。这里是 GIS 数据红移支持的函数的完整列表。

https://aws.amazon.com/blogs/aws/using-spatial-data-with-amazon-redshift/

这是针对红移的,但是当你把地理定位数据存储在 S3 时会发生什么呢?你如何质疑这一点?假设您已经以 GeoJSON 格式存储了地理位置数据,那么您应该能够使用 nature GIS 类型在 Athena 中创建一个外部表,并使用 Athena 查询数据。更多细节见下例。

对地理空间数据使用 Lambda & Step 函数的完整数据湖解决方案。

还有一个关于可视化的快速说明——通过 AWS,您可以使用 Quicksight 使用 Athena 和其他地方的数据创建地理/地理空间图表。虽然不如 Looker 和 Tableau 等成熟的可视化工具丰富和强大,但在需要简单的可视化时,Quicksight 确实很有用。

像 SNS,SQS 这样的服务不关心他们收到的是什么样的数据,只要是规定格式的。这意味着如果有一个地理位置数据的生产者,那么它可以被 AWS 中的事件/流服务消费。话虽如此,AWS 物联网事件使处理地理位置数据(一般来说是物联网事件)变得非常容易。

亚马逊定位服务

我不知道这一说法是否适合亚马逊定位服务(ALS),该服务将在不损害数据隐私和安全的情况下,与谷歌地图等公司竞争,因为将有数据永远不会离开 AWS 网络的规定,尽管这可能会产生额外的成本。

https://techcrunch.com/2020/12/16/aws-launches-amazon-location-a-new-mapping-service-for-developers/

我们还没有看到这项服务有多成熟。它也将提供地址转换、细化和规范化吗?几天前,我遇到了一个叫 Placekey 的神奇服务,它试图以极高的准确性解决地址规范化的问题。我们将拭目以待亚马逊是否有锦囊妙计。目前,亚马逊位置服务正在预览中。

https://aws.amazon.com/blogs/aws/amazon-location-add-maps-and-location-awareness-to-your-applications/

结论

随着亚马逊定位服务已经进入预览版,AWS 是否会更加专注于获取更多地理定位数据特定服务,也许是专门的地理定位数据库或可视化引擎?在过去的几年里,AWS 在时间序列、图形、文档数据库市场上占据了一定的份额。更多的地理定位服务可能真的会出现。

从业务驱动的角度处理不平衡的数据分类

原文:https://towardsdatascience.com/handling-imbalanced-data-classification-with-business-driven-perspectives-6132cc23bd9f?source=collection_archive---------46-----------------------

Elena Mozhvilo 在 Unsplash 上的照片

我认为数据科学家应该获得的一项关键技能是将实际业务问题转化为数据科学问题的能力。了解所有的机器学习(ML)技术是一件重要的事情;而知道如何将商业洞察力注入 ML 建模则是另一回事。到目前为止,我已经从事了几个不平衡数据集的数据科学项目,我想与您分享一些我从最佳实践中学到的策略。

我注意到许多关于不平衡数据分析的在线资源(博客和教程)主要集中在技术技巧上,包括采样、参数调整和 ML 模型的选择。因此,在这篇博客中,我将更多地从 DS 生产的角度来谈论,并重点关注商业知识将如何帮助建模。我希望你会喜欢阅读它!

1.商业世界中的不平衡数据建模

不平衡的数据集在商业世界中并不少见。通常,在对大目标人群中的低概率事件建模时,会出现这种不平衡。一些例子包括欺诈检测、缺陷产品识别、保险索赔等。大部分不平衡是内在造成的,这是由事件的性质造成的(即像欺诈这样的自然低概率事件)。然而,由于收集数据时的限制,一些数据集可能具有外部不平衡。例如,如果数据收集设备仅限于在白天工作,那么即使事件在白天以恒定的频率发生,在晚上收集的数据观察值也会少得多。

在没有商业知识的情况下,数据科学家通常会开发旨在优化 F1 分数、ROC- AUC、混淆矩阵、精确度和召回率的机器学习模型。然而,在处理业务问题时,实际上,包括成本和/或收入在内的业务背景知识可能会改变游戏规则。考虑到时间、成本等因素和限制,平衡假阳性(1 型错误)和假阴性(2 型错误)可能非常复杂。然而,利用业务知识可以帮助处理不平衡的数据建模。

2.处理模型开发过程中的不平衡

通常,我们可以通过以下步骤开发 ML 模型:

作者图片

实际上,业务驱动视角可以应用于所有的步骤。在接下来的部分中,我将介绍如何使用业务知识来创建一个更好的具有不平衡数据的 ML 模型。

2.1 数据准备

在训练模型之前,我们需要很好地理解数据结构。数据操作和特征工程对模型开发至关重要。对于不平衡数据,我们可以考虑潜在分割。这包括以下方面的细分:

1)响应变量

如果响应变量的一个类是多数类,而其他类都是少数类,我们可以考虑合并少数类。例如,当预测一个月内严重龙卷风的数量时,我们可能会看到大多数数据条目有 0 个龙卷风,少数数据条目有 1、2 或 3 个龙卷风。在这种情况下,我们可以通过预测是否会有严重的龙卷风,将响应变量从多类分类变量变为二元变量。

2)独立变量

探究数据总体,找出导致不平衡的原因。例如,如果年轻员工比年长员工更有可能离开公司,我们可以尝试根据年龄对员工进行细分。

除了分段,另一种预处理数据的技术是执行采样方法。你可能已经知道欠采样过采样、以及其他一些方法,比如 SMOTE(合成少数过采样技术)。在对数据进行抽样时,了解业务知识,如假阴性(FN)假阳性(FP) 的成本,可以帮助确定抽样权重。基本上,较高的权重将给予少数阶级,而较低的权重将给予多数阶级。

例如:

  • 假设在原始数据中,正负比例为 1:100
  • 假设 FP 的成本:10 美元,FN 的成本:100 美元
  • 当执行欠采样时,我们可以使用 1:10 的正负权重来表示成本

2.2 模型调整

一些 ML 方法库提供了与权重相关的参数进行调整。例如,在 Python 中,随机森林分类器的一个常用参数是“class_weight”。通过设置' class_weight='balanced ',模型使用 y 值来自动调整与类频率成反比的权重。或者,我们可以再次使用成本数据,通过惩罚模型中的分类错误来设置权重。与选择采样权重的想法类似,我们希望调整模型,使其符合降低成本和/或增加潜在收入的现实考虑。

2.3 模型评估

对于不平衡数据,在比较模型性能时,使用精确召回(PR)曲线优于 ROC AUC 曲线(参考文献 1):

从上图可以看出,虽然 ab 具有相同的 ROC 曲线,但是 b 的 PR 曲线要比 a 的好很多,说明 a 使用的模型在 a 数据不平衡的情况下并没有很好的表现。

此外,我强烈建议分析混淆矩阵,计算预期损失和/或收入,如果相关业务知识可用的话。同时处理 FP 和 FN 总是困难的,但是分析预期的损失/收益可以将这种权衡情况变成一个优化问题。下面是一个使用商业知识评估模型的二元分类示例:

故障摄像机示例分析

  • 问题描述:

项目目标:摄像机的故障检测

二进制响应变量:1 有故障,0 无故障

不平衡数据集: 1% 的摄像机出现故障(响应变量= 1)

  • 业务背景:

日产 50k 摄像机,测试产能为 1k 摄像机

每台摄像机的测试费用: $10

检测失败时的损失: $200

  • 车型性能:

召回=0.1,因此该模型可以在 1000 个预测中正确检测出 100 个故障摄像机

业务信息如何影响建模?

如上所述,根据现有的业务背景,我们可以通过计算预期损失来回答这个问题,这是我们希望最小化的目标。下表计算了 3 种情况下的预期损失:

作者图片

通过将场景 3 与场景 1(基线)进行比较,可以看出,该模型使用这种 ML 模型可以节省 100k-90k = 10k 。因此,如果我们已经训练了多个 ML 模型,我们可以通过减少这里计算的预期损失来比较它们的性能

从给定的商业信息中,我们还能了解到什么?

值得注意的是测试容量1k 相机。有了建模结果,只有预测为阳性的相机才会被测试(这就是使用 ML 模型的目的)。所以测试容量实际上决定了 FP+TP 的上限,也就是模型预测的阳性。选择< = 1k 预测阳性的型号是有意义的,因为我们被限制测试最多 1k 摄像头。如果模型预测超过 1k 个阳性,我们将没有能力在现实中测试所有预测的相机。

2.4 模型输出

我个人认为交付模型输出是最需要与业务伙伴合作努力的阶段,尤其是当数据科学模型导致一个产品的时候。模型的最终输出应该满足我们想要实现的业务目标。

一般来说,业务背景主要在以下几个方面影响模型输出和后处理:

2.4.1 输出格式

根据模型用户是谁,对输出格式的要求可能会有所不同。就分类而言,交付模型输出的常见格式是类别标签被分配到某个标签的概率。有时候模型用户只需要知道给出了哪个标签,但是在某些情况下知道概率是必要的,尤其是结果需要排名

2.4.2 成绩排名

受时间、资源和成本的限制,交付按优先级排序的模型结果更有意义。同样,这也是 DS 和业务合作伙伴应该讨论的地方 1)什么是限制和 2)什么是优先级

会员制营销实例分析:

  • 问题描述:

项目目标:接触有可能购买 VIP 会员资格的客户

二元响应变量:1 潜在客户,0 非潜在客户

不平衡数据集: 10% 的客户愿意购买(响应变量= 1)

  • 商业背景:

不同的客户如果加入会员,带来的收益量是不一样的,所以要对模型输出进行排序,使收益最大化。

  • 先联系谁?

假设我们有以下 3 个客户的示例模型输出,我们如何根据预测的概率和业务知识对他们进行排序?

作者图片

由于的目标是最大化收益,我们可以根据建模结果计算预期收益。这里我建议一个 EDA 是热图图。在本例中,预期潜在收入的计算方法是模型给出的概率乘以客户购买的收入。下面是基于玩具收入数据创建热图的 python 代码。

```python
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
prob = np.arange(0.1, 1.1, 0.1)
col_prob = ['10%','20%','30%','40%','50%','60%','70%','80%','90%','100%',]
revenue = np.arange(100, 1100, 100)
df = pd.DataFrame(np.outer(prob, revenue), columns=col_prob)
df.index = revenue.copy()
a4_dims = (11.7, 8.27)
fig, ax = plt.subplots(figsize=a4_dims)
ax = sns.heatmap(df.astype('int32'),
                cmap='coolwarm',
                annot=True,
                fmt="d",
                annot_kws={'size':12},
                cbar_kws={'label':'Potential Revenue'},
                square=True)
plt.title('Expected Potential Revenue from New VIP Members')
ax.set(xlabel='Prob. of Purchasing VIP Membership', ylabel='Revenue bought by Customers')

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/bdf79f59d42e90f7749c5cef3a49f224.png)

作者图片

从这张热图中,我们可以清楚地看到,虽然客户 A 加入 VIP 俱乐部的概率最高,客户 C 带来的潜在收入最多,但我们想先接触客户 B!

* **进一步的想法**

显然,这里给出的例子是从真实的业务问题中简化而来的。实际上,在绘制热图和排列模型输出时,可能需要更多的考虑。例如,如果接触客户的成本不同,那么这个成本应该是预期收入分析中涉及的另一个因素。

# 3.摘要

用不平衡的数据集建模从来都不是一件容易的事情。但幸运的是,在商业世界中,我们可以注入商业见解,以多种方式帮助模型开发过程。除了你已经尝试过的提高模型性能的所有技术策略之外,我希望这篇博客从不同的角度来看是有用的。感谢阅读!

## 💖喜欢这个故事吗?请随时[订阅 DS 和 ML 粉丝的邮件列表](https://mingjie-zhao.medium.com/subscribe),并且[成为会员](https://medium.com/@mingjie-zhao/membership)!🤩

## 这篇博客最初发表在我的个人网站上。

**参考**
【1】Lever 等人(2016) Nat 方法:分类器性能的图形表示避免了对结果设置精确的阈值,但可能对数据的重要方面不敏感。

# 使用 Synapse SQL 处理 Power BI 中的区域设置字母

> 原文:<https://towardsdatascience.com/handling-locale-letters-in-power-bi-using-synapse-sql-336113b34f76?source=collection_archive---------52----------------------->

## 在 Power BI 中,特殊的字母表字母可能很难处理。还是没有?使用 Synapse 无服务器 SQL 池检查这个简单的解决方案!

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/860f2893442934433f33e9b06a6cb19f.png)

[https://unsplash.com/photos/lNpo-WNqBo0](https://unsplash.com/photos/lNpo-WNqBo0)

如果你经常关注我的博客,你已经意识到我更喜欢描述现实生活中的用例,而不是写一些纯理论的东西……不要误解我的意思——当然,在投入真正的乐趣之前,你应该能够理解特定解决方案背后的核心理论和概念基础,但是解决现实世界的问题最终是有价值的。

## 方案

由于我生活在一个除了“常规”字母表之外还有特殊字符的语言区(对于那些不知道的人,我住在奥地利,那里讲德语),我最近在为一个客户创建 Power BI 报告时遇到了一个有趣的问题。

这个“问题”与德语“元音字母”的具体处理有关,这些字母是特殊的字母 ***、ü、o、*** ,它们是德语字母表的“版本”所特有的。事情是这样的,这些字母有时是按“原样”写的,但有时是按发音写的:ae,ue,oe,ss(例如,奥地利汽车驾驶员协会叫做 AMTC,但他们的网站是[https://www . OEA MTC . at](https://www.oeamtc.at)——只是为了说明我的意思)。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/d150e69e2cb98dd62f90724ba3cc8f4d.png)

[https://unsplash.com/photos/MP88Ac7oOqU](https://unsplash.com/photos/MP88Ac7oOqU)

回到客户最初的请求:他们正在分析奥地利和德国不同城市的特定商店的汽车销售情况。数据被收集到一个 CSV 文件中(我知道,我知道:),然后送到 Power BI 进行进一步分析。

为了清楚起见,这个 CSV 文件只是最终报告中不同数据源之一。

然而,具有挑战性的部分来了:有时,城市名称使用“元音字母”书写,有时使用“发音”逻辑——例如——münich 和 Muenich 杜塞尔多夫和杜塞尔多夫等。

下面是我为本文准备的简化文件中的数据:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/66623b68ad953cd2c9211a894a24a5a2.png)

作者图片

现在,当我在 Power BI 中导入这个 CSV 文件时,我得到的结果如下:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/4ea90d1289f3c607bcfeca53bb143d0f.png)

作者图片

如您所见,Power BI 对数据进行了“原样”解释:这意味着,即使实际上在杜塞尔多夫销售了 83 辆汽车,我们也无法在报告中看到这一数字,因为它是在杜塞尔多夫和杜塞尔多夫之间划分的!同样的情况也适用于名字中包含“元音字母”的其他城市。只有汉堡的结果是正确的,因为这个城市的名称中没有特殊字符。

## 尝试在 Power BI 中寻找解决方案

Power BI Desktop 为您的数据提供了很多设置和调整功能。然而,没有(或者至少我不知道)一个选项来以适当的方式处理这些特殊字符。

在将数据导入 Power BI 桌面之前,我曾尝试将文件来源更改为德语,但发生的情况是元音字母被问号替代:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/1fc84afd3d790807d4f0156f30943698.png)

作者图片

然后,我试图调整当前文件的区域设置,却发现只有数字、日期和时间会受到此设置的影响!

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ac662f2515fc4b02aed60024038723a0.png)

作者图片

我这边有一个重要的声明:我绝不是超级查询专家,也许 PQ 中有一个变通的解决方案来处理这个挑战,但是我在网上找不到任何类似的东西…

因此,看起来我的客户需要清理源端的数据(这当然是所有情况下可能的最佳解决方案,并且应该尽可能地应用),但是现实是残酷的,客户通常希望您代替他们做所有艰苦的工作:))

## Synapse 无服务器 SQL 拯救您!

在为这个问题绞尽脑汁的时候,我决定尝试在 Synapse 无服务器 SQL 池中处理数据。我已经写了这个集成分析平台提供的的[巨大可能性,特别是在与 Power BI](https://datamozart.medium.com/power-bi-synapse-part-1-the-art-of-im-possible-aee1cec5ebfa) 的[协同中,所以让我们看看是否可以利用 Synapse 无服务器 SQL 来解决我们的“变音”问题!](/power-bi-synapse-part-2-what-synapse-brings-to-power-bi-table-4592a03b1b74)

由于它利用常规的 T-SQL 语法从多个不同的源(如 CSV、Parquet 文件或 Cosmos DB)中检索数据,因此无服务器 SQL 带来的一个好处是(几乎)拥有“普通”SQL Server 中的全部功能。

在“普通的”SQL Server 中,可以通过更改数据库排序规则来处理类似的请求,以便能够“识别”德语中的特殊字符。更多关于校勘本身和具体校勘类型可以在[这里](https://docs.microsoft.com/en-us/sql/relational-databases/collations/collation-and-unicode-support?view=sql-server-ver15)找到。

由于我的客户已经在使用 Azure Synapse Analytics 处理各种数据工作负载,并且激活了一个无服务器 SQL 池,因此我决定冒险使用与本地 SQL Server 类似的策略!

但是,首先,我已经从 Synapse Studio 中将我的 CSV 文件上传到 Azure Data Lake Storage Gen2 帐户:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/904b559e18dd2e22e419ccf2425a6ace.png)

作者图片

如果我从 Synapse Studio 运行以下脚本…

SELECT
    TOP 100 *
FROM
    OPENROWSET(
        BULK 'https://nikolaiadls.dfs.core.windows.net/nikolaiadlsfilesys/Data/Umlauts.csv',
        FORMAT = 'CSV',
        PARSER_VERSION='2.0',
HEADER_ROW = TRUE
) AS [result]


我会得到和以前完全一样的结果…

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/babf3152f4813c188f95cd6b5c884047.png)

作者图片

因此,让我们更改数据库的排序规则,以便能够识别德语字母:

ALTER DATABASE CURRENT collate German_PhoneBook_100_CI_AI_SC_UTF8;


让我们看看在我运行以下脚本后是否发生了变化:

SELECT
    City
,SUM([Sales Qty]) AS TotalSalesQty
FROM
    OPENROWSET(
        BULK 'https://nikolaiadls.dfs.core.windows.net/nikolaiadlsfilesys/Data/Umlauts.csv',
        FORMAT = 'CSV',
        PARSER_VERSION='2.0',
HEADER_ROW = TRUE
)

 AS [result]
 GROUP BY City

以下是结果…

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/3909d5695d27e6e6f3c35405ea9c5171.png)

作者图片

瞧啊。!!这看起来正是我想要实现的!让我们在该数据集上创建一个视图,并在 Power BI Desktop 中使用该视图:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/bc81bdcdcb8ae0138950e4fa6ccb5415.png)

作者图片

现在,当我将两个视图放在一起时——一个基于直接来自 CSV 文件的数据,另一个基于 Synapse 无服务器 SQL 池中“整理”的数据,我得到以下结果:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/23232a2d5f44b02e0597b0801d379e2a.png)

作者图片

不需要说哪个视觉提供了正确的和预期的结果!

## 结论

正如您所看到的,您不需要使用 Synapse Analytics 和其中的无服务器 SQL 池来管理一些常见的通用任务,例如查询来自各种不同来源的数据(CSV、JSON、Parquet 文件;Cosmos DB 火花表)。

您可以充分利用无服务器 SQL 池的特性来解决一些特殊的挑战,比如我最近在现实生活中遇到的这个问题!

当然,我的场景需要找到德语“元音变音”的特定解决方案,但是如果您正在处理斯堪的纳维亚语、土耳其语或世界上任何包含非标准字母的字母表,您可以执行相同的方法!您只需要为正在处理的各个字符集找到合适的排序规则。

现在,我的问题解决了,客户满意了,所以我可以享受一品脱明希纳啤酒了:)!

感谢阅读!

# 处理缺失数据

> 原文:<https://towardsdatascience.com/handling-missing-data-5be11eddbdd?source=collection_archive---------33----------------------->

## 一个统计学家关于如何(不)做它来保持你的机器学习工作流程的观点。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/8d0627daae87398e0da76e518485ef11.png)

劳尔·纳杰拉在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上的照片

最近,我不禁注意到一些关于流行的机器学习书籍的惊人之处。即使是在解释算法及其应用方面做得很好的最好的标题,也往往会忽略一个重要的方面。在需要统计的严格性来正确做事的情况下,他们经常建议危险的过度简化的解决方案,给像我这样的训练有素的统计学家带来严重的头痛,并对机器学习工作流产生不利影响。

> 即使是最好的机器学习书籍也往往会忽略需要统计严密性才能正确做事的主题,而是提出危险的过于简化的解决方案。

几周前,我写了一篇关于数据测量水平的文章,解释了一种经常被推荐的分类变量编码方式如何与统计理论形成对比,从而导致模型可解释性和易学性的潜在问题。不要犹豫走弯路:

</data-measurement-levels-dfa9a4564176>  

还有一个:处理丢失的数据。平视:拜托,不要吝啬——估算,不要落下不完整的观察!

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/d7f59696522ba02c49e9d9bffeed41b6.png)

## 不要删除不完整的行

由于大多数机器学习算法不接受 NaN 输入,许多文本建议简单地从数据中删除包含缺失值的行。只要你有大量的数据,也就是说。如果是这样的话,去掉几行就解决问题了,不会有太大影响吧?不对!我敢说,大错特错。

第一,良性原因。不完全完整的行通常也不是完全 NaN。删除它们是摆脱坏 nan 的捷径,但同时也删除了一些非常有效的数据点。一个数据科学家究竟为什么要扔掉有用的数据?

第二,恶性原因。这与所谓的*缺失数据机制有关。*在统计学理论中,它们是遗漏的可能原因。有三种情况:数据可能完全随机丢失(MCAR)、随机丢失(MAR)和非随机丢失(MNAR)。如果你对数据中包含它们的含义以及如何区分它们感到好奇,看看我在 DataCamp 上教的[处理缺失数据的课程](http://datacamp.com/courses/handling-missing-data-with-imputations-in-r)。这里重要的是,只有当数据是 MCAR 时,才能删除不完整的行,这意味着绝对不会影响丢失的数据点。如果数据不是 MCAR(当一个变量中的缺失可以用其他变量来预测时,就会发生这种情况),丢弃不完整的行会给数据带来偏差,这种偏差会转移到基于这些数据构建的任何机器学习模型。

> 如果遗漏的原因不完全是随机的,丢弃不完整的行会给数据带来偏差,这种偏差会转移到基于这些数据建立的任何机器学习模型。

区分 MCAR 和其他机制并不简单。有一些统计测试,人们也需要大量的领域知识。但是为了安全起见,最好完全放弃删除不完整行的做法。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/d7f59696522ba02c49e9d9bffeed41b6.png)

## 不意味着-估算

在顶级机器学习书籍中经常找到的另一个建议是,用这个变量的观察值的平均值来替换每个变量中所有缺失的值。其背后的逻辑是,通过输入平均值,我们不会对模型产生太大影响。拜托,千万别这么做!通过均值估算,我们产生了两个问题:我们减少了均值估算变量的方差,破坏了这些变量与其余数据之间的相关性。

> 通过均值估算,我们产生了两个问题:我们减少了均值估算变量的方差,破坏了这些变量与其余数据之间的相关性。

考虑下面的散点图。它根据健康调查数据显示了人们的身高(厘米)和体重(千克)。这两个变量显然是正相关的,但两者都有一些缺失值。让我们用平均身高(166 cm)来估算所有缺失的身高,用平均体重(67 kg)来估算所有缺失的体重。估算的数据点以橙色显示。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/2a858b209d9a01985970a3538d3e9cdd.png)

图片来自作者在 DataCamp 教授的 R 课程[用插补处理缺失数据。](http://datacamp.com/courses/handling-missing-data-with-imputations-in-r)

这里发生了什么事?估算值通常是异常值。任何在这些数据上训练的机器学习模型都会被它们忽悠,会产生有偏差的结果。机器学习就是在数据中寻找模式。均值插补通常是在数据中引入人为的错误模式。他们应该如何携手共进?

> 机器学习就是在数据中寻找模式。均值插补通常是在数据中引入人为的错误模式。它们并不齐头并进。

改做什么?这取决于你有多少时间和计算资源。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/d7f59696522ba02c49e9d9bffeed41b6.png)

## 当你有时间的时候做些什么

如果时间和计算资源都很充足,你能做的最好的事情就是运行多重插补。实现这种技术的一种方法是自举。我们来看看是怎么做到的。下图最能说明这一过程:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/d9417a34f51c3d57d308fb0372ffbd25.png)

图片来自作者在 DataCamp 教授的 R 课程中的[用插补处理缺失数据。](http://datacamp.com/courses/handling-missing-data-with-imputations-in-r)

首先,我们通过替换从数据行中取样来创建许多(比如说一千个)数据副本。这叫做自举。然后,我们对每个拷贝应用插补算法。常用的插补算法有 kNN、随机森林或基于迭代模型的插补。这样,我们就有了一千份不同的、完全完整的数据集。接下来,我们对每个副本的原始数据做任何我们想做的事情:训练一个模型,计算一些汇总统计数据,你能想到的。最后,不管我们最后的结果是什么(模型预测,一个描述性统计?),我们对所有自举和估算数据集的值进行平均,以获得结果的分布。

这可能看起来有点让人不知所措,但实际上实现起来相当容易,Python 和 R 中都有包可以做到这一点。查看[我的课程](http://datacamp.com/courses/handling-missing-data-with-imputations-in-r),学习如何自己动手。

在多重插补的诸多优点中,最重要的一个优点是您可以获得结果的概率分布,这允许量化您的模型或分析的不确定性,包括插补的不确定性(毕竟,插补只是一个有根据的猜测,而猜测伴随着不确定性)。我在这里写了更多:

</uncertainty-from-imputation-8dbb34a19612>  

多重插补的缺点是速度会很慢。如果没有那么多时间呢?

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/d7f59696522ba02c49e9d9bffeed41b6.png)

## 当你没有时间的时候,该做些什么

一个快速但合理的解决方案是所谓的热卡插补。要估算变量中的缺失值,您可以选择一个或多个与所讨论的变量相关的其他变量。然后,通过这些选定的变量对数据集的行进行排序。最后,从上到下循环遍历这些行,用同一个变量中以前的非缺失值替换每个缺失值。

这样,从中借用值的行与粘贴值的行相似。这避免了均值插补的大部分缺点,而且速度也相当快。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/d7f59696522ba02c49e9d9bffeed41b6.png)

感谢阅读!如果您有兴趣了解关于缺失数据、各种插补方法以及如何将插补不确定性纳入建模的更多信息,请查看 DataCamp 上的 [**我的课程**](https://datacamp.com/courses/handling-missing-data-with-imputations-in-r) 。

如果你喜欢这篇文章,为什么不 [**订阅邮件更新**](https://michaloleszak.medium.com/subscribe) 我的新文章呢?并且通过 [**成为媒介会员**](https://michaloleszak.medium.com/membership) ,可以支持我的写作,获得其他作者和我自己的所有故事的无限访问权限。

需要咨询?你可以问我任何事情,也可以在这里 为我预约 1:1 [**。**](http://hiretheauthor.com/michal)

也可以试试 [**我的其他文章**](https://michaloleszak.github.io/blog/) 中的一篇。不能选择?从这些中选择一个:

</monte-carlo-dropout-7fd52f8b6571>  </calibrating-classifiers-559abc30711a>  </working-with-amazon-s3-buckets-with-boto3-785252ea22e0> 

# 机器学习中缺失数据的处理

> 原文:<https://towardsdatascience.com/handling-missing-data-in-machine-learning-d7acac44bef9?source=collection_archive---------24----------------------->

## 构建 ML 模型时如何处理缺失数据

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/b21e247eabddec0ed9d4bb37b7ef76f8.png)

凯利·西克玛在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上的照片

在真实的(表格)数据集中,您通常会意识到并非所有的特性都适用于您的所有行。学习处理这种现象将允许你仍然利用你的数据集,甚至当一些数据丢失的时候。

## 缺失数据的类型

有多种原因可能导致数据丢失,例如数据损坏、在特定时间段内缺乏数据可用性或数据收集过程中的偏差(例如,调查中特定类别的受访者将答案留空)。

这里要做的重要区分是你丢失的数据是否是随机发生的*。*

*缺失数据有三种情况:*

*   ***完全随意失踪(MCAR)。**对于所有可能的数据点,数据缺失的概率是相等的。*
*   ***随机失踪(MAR)。**数据丢失的概率在所有数据点上并不相等,但是*在*已知的数据类别中,丢失数据的概率是相等的。例如,只有在特定国家的答复中,数据缺失的概率可能是相等的。*
*   ***不随意遗漏(MNAR)。**数据丢失的概率在所有数据点上并不相等,并且不存在已知的数据分组,其中丢失数据的概率相等。*

## *删除方法*

*处理缺失数据的第一类方法是从数据集中删除数据。这些通常都是简单的方法,旨在删除因损坏太严重而无法使用的数据点或列。*

1.  ***删除缺少太多列值的行。**在 MCAR 和火星方案中,这可能在不显著改变整个数据集分布的情况下完成。但是,在 MNAR 场景中,这可能会使您的数据集产生偏差,因为数据移除过程会偏向于导致较高数据丢失率的过程所生成的点。这并不一定是坏事,尤其是在丢失了太多可用数据的情况下,但这是需要注意的。*
2.  ***删除缺少太多值的列。**一些特征可能仅仅是低质量的,并且具有过高的空率以至于不能用它们来建立模型。特别是在生产机器学习设置中,删除通常不可用或低质量的功能通常是一个好主意。*

## *插补方法*

*另一类处理缺失数据的方法包括尝试填充或估算缺失数据。这通常包括学习对数据集进行建模,以便推断出缺失的值应该是什么。*

1.  *常数/平均值/中位数插补。这些是最简单的插补方法,最多只是计算一些简单的列统计数据。对于每一列,以及在 MAR 方案中的每一组中,您可以用常数值或可用特征值的某一列统计数据(例如,平均值或中值)来替换缺失值。*
2.  ***回归插补。**一种更复杂的数据输入方法包括建立一个预测模型,该模型可以推断缺失数据的值。这些方法更强大,能够理解数据的底层结构,以便为缺失数据提供更智能的猜测。因此,例如,如果我们有 5 个特征和 1 个缺失,我们建立一个模型,在给定其他 5 个特征的情况下预测缺失的 1 个。这种方法的一个警告是,它可以人为地加强数据中的关系,并产生“好得难以置信”的估计,这只会加强数据集中的偏差和相关性。因此,这些估算值可能低估了数据集中的方差。*
3.  ***多重插补。**该方法是为估算值创建更稳健估计的一种方式,可以利用上述两种方法。在多重插补中,您创建 N 个不同版本的插补数据集,然后将 N 个值汇集在一起,以产生一个最终数据集(通过简单的方法,如平均,或一些更复杂的统计方法)。多重插补的结果比单一插补的结果偏差更小,更能代表数据集的方差。*

# 像专家一样处理“缺失数据”——第 1 部分——删除方法

> 原文:<https://towardsdatascience.com/handling-missing-data-like-a-pro-part-1-deletion-methods-9f451b475429?source=collection_archive---------15----------------------->

## 数据科学。分析。统计学。Python。

## 面向 21 世纪数据科学家的基本和高级技术

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/3db29d4add07ae4fca3bfd4244471ec1.png)

艾米丽·莫特在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上的照片

正如我们在致力于缺失数据系列的[第一篇文章](/the-three-types-of-missing-data-every-data-professional-should-know-d988e17d6ace)中提到的,关于“缺失”的机制或结构的知识是至关重要的,因为我们的反应将依赖于它们。

虽然处理缺失数据的技术越来越多,但我们在下面讨论一些最基本到最著名的技术。这些技术包括数据删除、常数单和基于模型的插补,等等。

在我们开始讨论它们之前,请注意这些技术的应用需要数据科学家的洞察力。即使我们可以确定遗漏的机制,也需要其他信息,如数据收集和方法学来选择最合适的技术。

因为我们将要讨论的技术范围相当广泛,所以让我们把它们分割开来,使它们更容易理解。对于文章的这一部分,我们将关注:**删除方法**。

# 成人收入数据集

为了加强我们的理解,让我们使用一个数据集,特别是来自 [UCI](https://archive.ics.uci.edu/ml/datasets/adult) 的成人收入数据集。

在我们开始之前,为这个数据集执行 EDA 是很重要的。变量密度的知识将在选择合适的技术时派上用场。[关于这个](/dramatically-improve-your-exploratory-data-analysis-eda-a2fc8c851124)见我的文章。

## 预赛

import random
import numpy as np
import pandas as pd#For data exploration
import missingno as msno #A simple library to view completeness of data
import matplotlib.pyplot as pltfrom numpy import random
%matplotlib inline


## 加载数据集

df = pd.read_csv('data/adult.csv')
df.head()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e48f3a07a72b52d5d927377cb8c0746a.png)

通过缺失 no 包实现完整性可视化。我们的数据在分类变量中缺少一些值。

## 模拟失踪

让我们模拟一些连续变量的缺失:*年龄*和 *fnlwgt* 。注意,这里的收入是目标变量,是分类变量。

Random Seed

random.seed(25)#Percentage Missing
percentage_missing_1 = 0.15
percentage_missing_2 = 0.10#Number of Observations
obs = df.shape[0]#Simulation
df["fnlwgt"] = random.binomial(1,(1-percentage_missing_1), size=obs)df['fnlwgt']
df["age"] = random.binomial(1,(1-percentage_missing_2), size=obs)
df['age']
df["fnlwgt"] = df["fnlwgt"].replace(0, np.nan)
df["age"]= df["age"].replace(0, np.nan)msno.matrix(df)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/413e89bcc861f147e45e35748bd1927a.png)

在我们模拟了一些缺失数据后的完整性可视化。

“最终重量”变量的缺失数据最多。这与我们的缺失数据模拟是一致的。请注意,我们采用的机制仅仅是 MCAR。

“最终重量”变量的缺失数据最多。这与我们的缺失数据模拟是一致的。

既然我们有了丢失数据的数据集,我们现在可以继续检查我们的不同技术如何影响数据集,以及使用这样的数据集的结果。

# 数据删除方法

所有数据科学博客(*甚至一些发表的文章*)中最简单的数据处理方法是数据删除。但是正如我们在引言中提到的,数据删除会降低我们的模型的有效性,特别是如果丢失的数据量很大的话。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/d7f1833980d0e0ec8005d142e3f73c3a.png)

缺失数据的数据删除方法总结

## 列表法\完全案例法

从名称本身来看,只要缺少一个值,listwise 或 complete 方法就会删除一个观察值。如果应用不小心,回顾一下这是如何减少我们的观察的:

df1 = df.copy()
df1.dropna(inplace=True)
df1.shape[0]


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/10722856a5309a97fd546cf1f99d93d2.png)

我们的观察失去了 30%的原始价值。

我们失去了 30%的观测数据,这是一个很大的数字!这是显而易见的,因为整个数据集中使用的 *dropna()* 会丢弃所有的观察值,只要有一列丢失。

这种方法有一些优点,例如简单高效,但请注意,这种方法仅适用于 MCAR 数据集。

**应用列表删除前**

在决定如何处理缺失数据之前,尤其是如果您计划应用列表式删除,您需要首先确定研究的相关变量。

如果不需要该变量,则特定项是否丢失并不重要,并且应该在应用列表式删除之前将其排除在 dataframe 的子集中。

例如:如果我们认为最终权重与我们的研究无关(例如*预测收入等级*),我们可以将其从我们的特征数据框架中排除。

df2 = df.copy()
df2 = df2.loc[:, df2.columns != 'fnlwgt']


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/86f4284abdaa90fc85b6c40c14402769.png)

排除一个变量只会导致总观察值的 17%下降。

通过这一额外的步骤,我们能够从浪费的删除中节省额外的 6,182 个观察值。对于一些研究来说,这一小步可能是你所追求的目标精确度的差异制造者。

列表删除主要用于 MCAR 数据。由于数据是以完全随机的方式丢失的,假设我们没有删除大量的观测数据,那么我们可以假设删除操作几乎没有丢失任何信息。

列表删除在大多数回归和监督学习方法中使用,包括主成分分析。(PCA)

## 成对删除\可用案例方法

与列表删除相比,可用案例方法使用所有可用的观察值。也就是说,如果观察的特征/变量丢失,使用该特征/变量的方法或技术仅丢弃具有丢失信息的变量,而不是整个观察。

例如,如果我们的数据框架中的上述观察值不包含“最终重量”值,则不会为该观察值计算需要最终重量值的测量/指标或参数。其他一切都将继续利用这个观察。

这种方法如此不受重视,以至于大多数人都没有意识到这是相关性分析中使用的方法。要了解这一点,请访问:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/0eb2a7db2b6732013e7a3c825c3a6bf8.png)

请注意,我们使用了带有缺失值的原始数据帧,并且仍然可以计算相关性。

除了相关性分析,成对方法还用于因子分析。对于那些正在计算的人

## **可用项目**

用于复合变量的**创建的方法是可用项方法。这种方法与可用案例方法一样,使用所有可用的信息。**

可用项目方法通过以下方式汇总**相关项目**:

1.  首先应用标准化方法,例如 z 分数。
2.  此后,**变换后的变量不是被相加,而是对每个观察值进行平均。**

因此,现在可以创建一个综合分数。

现在,这被称为删除方法,因为**它没有试图替换丢失的值。**

如果您计划创建综合分数,可以简单地应用此算法。

# 结束语

本文介绍了用于处理缺失数据的第一类技术——删除。

删除的主要优点是简单,而主要缺点是失去了统计能力。但正如我们将在下一篇文章中看到的,另一类技术,即插补,在某些情况下也有缺点,即缺失数据专家宁愿使用删除方法。

最后,我们上面提到的任何技术的应用,需要由研究者的目标、数据收集方法和遗漏的潜在机制所引导的判断。

在下一篇文章中,我们将讨论插补方法。

[像专家一样处理“缺失数据”——第 2 部分:插补方法](/handling-missing-data-like-a-pro-part-2-imputation-methods-eabbf10b9ce4)

[像专家一样处理“缺失数据”——第 3 部分:基于模型的&多重插补方法](/handling-missing-data-like-a-pro-part-3-model-based-multiple-imputation-methods-bdfe85f93087)

# 参考

麦克奈特,P. E. (2007)。*缺失数据:温柔的介绍*。吉尔福德出版社。

# 像专家一样处理“缺失数据”第 2 部分:插补方法

> 原文:<https://towardsdatascience.com/handling-missing-data-like-a-pro-part-2-imputation-methods-eabbf10b9ce4?source=collection_archive---------4----------------------->

## 数据科学。分析。统计学。Python。

## 面向 21 世纪数据科学家的基本和高级技术

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/574d8fbab3378ff5bc178220c8f7de4d.png)

乔恩·泰森在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上的照片

正如我们在致力于缺失数据系列的[第一篇文章](/the-three-types-of-missing-data-every-data-professional-should-know-d988e17d6ace)中提到的,关于“缺失”的机制或结构的知识是至关重要的,因为我们的反应将依赖于它们。

在[像专家一样处理“缺失数据”——第 1 部分——删除方法](/handling-missing-data-like-a-pro-part-1-deletion-methods-9f451b475429)中,我们已经讨论了删除方法。

对于文章的这一部分,我们将关注**插补方法**。我们将比较对数据集的影响,以及每种方法的优缺点。

# 加载数据集并模拟缺失

加载成人数据集并模拟这篇文章[中的 MCAR 数据集。](/handling-missing-data-like-a-pro-part-1-deletion-methods-9f451b475429)

# 插补方法

现在我们有了一个数据集来实践我们的插补,让我们开始讨论这些是什么。

以下是我们在研究中可以采用的现代插补方法的总结:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/42f3063f39c50f18171168b6f40e20d5.png)

现代缺失值插补的技术类别和方法

当我们将讨论背后的理论和概念时,让我们使用 *Scikit-learn* 来为我们做脏活。

## 常数替换方法

常数插补是处理缺失数据时最常用的单一插补方法。

常数插补方法在替换观察中的缺失数据时插补一个常数值。很简单,这种技术有各种各样的变化,数据科学家也有一些方法让这种技术更有效。

**表示替换**

对于平均值替换,缺失值将替换为要素的算术平均值。

Import the imputer

from sklearn.impute import SimpleImputer

Initiate the imputer object

imp = SimpleImputer(missing_values=np.nan, strategy='mean')

Isolate the columns where we want to import

X = df[['age', 'fnlwgt']]#Fit to learn the mean
imp.fit(X)#Impute
imp.transform(X)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ea6406350078ba3210cad7b6b064c945.png)

向量间的平均插补比较

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/9d0c5ceef96d271de7bddf945a1f3c7c.png)

均值插补保留缺失值数据集的均值。然而,这种方法的一个很大的缺点是降低了方差。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/0d6ed6c15ebf294051881a01693e82c8.png)

估算数据集的方差显著较低。

均值插补保留了缺失值数据集的均值,正如我们在上面的例子中看到的。然而,只有当我们假设我们的数据是正态分布时,这才是合适的,因为通常假设大多数观察值都在平均值附近。对于少量丢失数据的情况,这也非常有用。

均值插补的主要缺点是,它往往会对某些参数,尤其是方差产生有偏估计。这个事实影响了置信区间的构建,这对于一些研究人员来说是一个严重的问题。

有一种方法可以稍微弥补这一点,这适用于所有的常数替换方法:人们可以为不同的子群估算不同的平均值。例如,对于“年龄”值插补,您可以选择为所有缺少年龄值且属于男性组类的观察值插补男性的平均年龄。

**注意,对于用整数表示的变量,如年龄,您可以在插补后向上或向下取整**。

**最大似然均值替代**

最大似然(ML)法是一项惊人的技术,它具有最大的**恢复真实总体参数**的能力。

ML 方法被高度赞扬和使用,因为它们利用数据集的每一个观察来估计总体参数。**因此,如果您的数据集是 MCAR,它具有最大的收敛概率。**

我们将在“基于模型的”数据扩充文章中详细讨论这一点及其背后的数学原理,但现在,让我们来计算数据集的最大似然均值。

from scipy import stats
from scipy.optimize import minimizedef fnlwgt_ML_mean(params):
mean = params[0]
sd = params1# Calculate negative log likelihood
nll = -np.sum(stats.norm.logpdf(df['fnlwgt'].dropna(), loc=mean, scale=sd))return nllinitParams = [7, 12]fnlwgt_results = minimize(fnlwgt_ML_mean, initParams, method='Nelder-Mead')
mle_fnlwgt = fnlwgt_results.x[0]


这导致对平均值和标准偏差的以下估计:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/cd7b356594f50791c14ebf9d9a271c4d.png)

看估算;它们是我们完整数据集的近似估计。

如果你比较一下我们所拥有的:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/adc19dad7a8a0c6d3dd0628debc21fc1.png)

这些估计值可以与 MCAR 数据集的估计值进行比较。这种差异是由于我们过于简化的分布假设(回想一下,年龄变量是右偏的)。

对于较小的数据集,只要我们得到正确的分布假设,那么均值的最大似然估计实际上可能比普通均值估计更好。

得到估计值后,你可以把它作为常数代入估算值。

使用最大似然法的一个特别的缺点是我们需要假设数据的分布。在这方面,预先了解发行版或一些初步的 EDA 可能会有所帮助。此外,与平均值和中值常数替换不同,对每个特征进行单独的 MLE 计算。

**中位数替代**

对于中位数替代,中位数而不是平均值被用作缺失观察值的替代值。

Median Imputer

imp = SimpleImputer(missing_values=np.nan, strategy='median')
imp.fit(X)


中位数替代虽然可能是偏斜数据集的一个好选择,但会使数据集的均值和方差都有偏差。因此,这将是研究者需要考虑的因素。

**零插补**

对于某些类型的研究,更自然的做法是将缺失变量估算为零(“0”)。零分对于本质上是社会性的变量来说可能是有意义的,比如“兴趣的消退”,或者对于那些在考试中没有出现的人来说,他们自然得到了零分。

当然,只有零是有效值的变量才有可能,所以这对于参与者不是真正的新生儿的年龄变量是不可能的。

**模式插补**

从名称本身来看,模式插补估算特定变量的“最频繁”值,对于正态分布变量来说,这可能是一个不错的方法选择。

## 随机替换方法

与常量值替换方法相反,随机替换方法用随机生成的值替换丢失的数据。

有两种方法可以实现这一点:

1.  **使用经验数据**——如果你熟悉 bootstrap 方法,那么你可以把这个看作类似于那个。这意味着用于替换缺失值的观测值来自数据集本身的可用数据。
2.  **使用统计分布** —如果我们知道一个变量的分布,我们可以从理论/统计分布中抽取样本(又称为*参数化*)。为此,我们可以用最大似然估计代替参数,因为它们被认为更稳健。

下面我们试着讨论一下*经验*随机替换的一些方法。

**热甲板法**

热卡方法是用从当前数据集中随机选择的值替换缺失值的方法。这与冷盘方法形成对比,在冷盘方法中,您可能有一个单独的数据集可以从中随机提取值。

例如,对于我们的成人数据集,如果一个人忘记报告他/她的年龄,这种方法将从那些已经报告了年龄的数据中选取一个随机值。

random.seed(25)
df4 = df.copy()#For Weight
df4.loc[:,'fnlwgt'] = [random.choice(df4['fnlwgt'].dropna()) if np.isnan(i) else i for i in df4['fnlwgt']]df4.loc[fnlwgt_missing,'fnlwgt']


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ffd2fad1d6714e7ed2ed657d9703f954.png)

该算法使用从该变量的可用数据中随机选择的方法来估算缺失值。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/d1ea5c990d82774be9fa5ee363d6aacf.png)

热卡插补可能导致标准差高于原始值。

热卡插补可能导致标准差高于(或低于)我们的完整数据集,当然,这并不比用于置信区间构建的低估(或高估)值更好。

与均值插补一样,您可以使用亚组进行热卡插补(例如,不是从整个数据集,而是从该数据集的子集,如男性亚组、25-64 岁亚组等,进行随机选择插补。).

**冷甲板方法**

可以从一个单独的数据集中引入一个替换值,该替换值类似于带有缺失值的数据集。

例如,您可能想要研究两个群体,其中的人口是同质的,但您只是碰巧将他们分成两组(例如,星期一组和星期二组)。如果您有星期二组的缺失值,比如说年龄,*,前提是两个组都是同质的并且随机分配*,那么可以使用来自星期一组的随机选择的年龄值来填充缺失的年龄。

可以使用训练数据集的两个子组来实现冷甲板,正如我们对验证所做的那样。注意不要使用测试数据集中的数据,以避免数据泄漏。

## 基于模型的替换方法

基于模型的替换方法用于生成参数估计,条件是我们拥有的给定数据、观察到的变量之间的关系以及基础分布所施加的约束。

因为我们利用了底层的分布,我们称这些方法为“基于模型的”。

基于模型的方法包括马尔可夫链蒙特卡罗(MCMC)、最大似然、期望最大化算法和贝叶斯岭。

也可以使用决策树和额外的树,尽管它们没有包含在原始方法中(那些严重依赖数据分布的方法)。我们将在这里包括这些,因为它们无论如何都是机器学习中的有效模型。

由于这些都是美丽而复杂的技术,我们需要在一篇单独的文章中讨论它们,这样我们才能更深入地欣赏它们。

## 非随机替换:一个条件

**组均值/组中值**

我们已经在常数替换方法一节中讨论了非随机替换。

对于组均值和组中值,我们不是为所有缺失值输入单个值(均值或中值),而是将观察值分成子组,并为这些子组中的缺失值输入均值/中值。

性别分组的例子有男性和女性分组,对于年龄变量(*,正如我们所看到的可能是正偏态的*),我们可以使用定制的年龄组。

例如,如果我们示例中的最终权重值缺失,那么我们可以将子组划分为工作类别,获得相应的平均值/中值,并分别估算子组中缺失的值。

df5 = df.copy()#Accomplish Using Transform Method
df5["age"] = df5['age'].fillna(df.groupby('workclass')['age'].transform('mean'))df5["fnlwgt"] = df5['fnlwgt'].fillna(df.groupby('workclass')['fnlwgt'].transform('mean'))


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/038b8003fcf748cef99a20090e322a3d.png)

使用“工作类别”变量,您可以获得每个工作类别的平均值,并将平均值“年龄”或“fnlwgt”替换为这些类别的缺失值。

使用 *groupby()* 方法,您可以创建多个分组级别,比如在工作班之后,您可以进一步按教育级别分组。

只要有助于你的研究,你可以在小组讨论中发挥创造力和探索性。

**上次观察结转(LOCF)**

对于一些时间序列数据,丢失数据的主要原因是“损耗”。例如,假设你正在研究一个特定人的减肥计划的效果。如果在最后一次观察之前,您看到了持续的改进,那么第一次遗漏的观察可以假定为与最后一次观察值大致相同。这里的自然减员是因为那个人已经达到了他/她的理想体重。

假设您的行是每年排列的:

Just assuming the the variable below is a time series data

df['column'].fillna(method='ffill')#Another implementation but combined with groupmeans method

df['age'] = df.groupby(['workclass'])['age'].ffill()


如果您将此方法应用于非时间序列数据集,则此方法被视为“热卡”方法,因为它使用数据集的实际观测值。然而,应小心谨慎,因为这可能并不完全适用于许多情况,因为它已被证明会使参数估计产生偏差并增加 1 类误差。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/c95330e07bf728cf29a075a3c719da62.png)

组均值插补的均值和标准差计算。

**下一次观测向后进行(NOCB)**

在精神上类似于 LOCF,“下一个观察结转(NOCB)”携带随后的值,但不是向前,而是向后。如果你听说过术语“回填”,这基本上就是那个过程。

如果你仔细想想,有很多这样的例子。比方说,你正在研究不同测试对象的工资增长。如果你知道公司在某一年没有给员工加薪(例如,在 T2 的 COVID-疫情法案期间),你可以用当年的工资来填充过去的几年。

与 LOCF 一样,这适用于时间序列数据,但也有同样的缺点。

Assuming a time-series variable

df['variable'].fillna(method='backfill')#Another implementation but combined with groupmeans method

df['age'] = df.groupby(['workclass'])['age'].ffill()


## 非随机替换:多个条件

**平均先前/平均后续观察值**

在某些情况下,我们可以做的不是只依赖于一个先前的或一个向后的观察,而是对几个观察进行平均。

例如,对于涉及股票或证券价格的研究,这无疑是首选。

假设您想要计算三(3)个周期的平均值并将其结转,您应该使用的代码是:

df6[['age', 'fnlwgt']]= df6[['age', 'fnlwgt']] = df6[['age', 'fnlwgt']].fillna(df6[['age', 'fnlwgt']].rolling(3,min_periods=0).mean())


相反,如果我们想要回填的三(3)个周期的平均值:

df7 = df.copy()#Rough codes as I can't find a more elegant solution to thisdf7[['age', 'fnlwgt']] = df7[['age', 'fnlwgt']].iloc[::-1].rolling(3, min_periods=0).mean().iloc[::-1]


**回归和带误差的回归**

回归和带误差的回归方法通过基于数据集中的其他变量预测变量来填充变量的缺失值。

在某种程度上,您可以将其视为线性回归模型中作为目标变量的缺失值。想想看,当你使用任何监督学习模型时,你是在试图预测或找到一个未被观察到的结果。和缺失数据本身都是无法观察到的结果。

预测值可以使用数据集中的所有其他变量,或者只是其中的一个子集。

我们可以从头开始编写一个代码来完成这项工作,但是让我们简单地使用一个可用的包: ***autoimpute*** 。

在您的终端上运行`pip install autoimpute`之后,我们可以运行下面的代码:

from autoimpute.imputations import SingleImputer, MultipleImputerdf8 = df.copy()# create an instance of the single imputer and impute the data

with autoimpute, you can choose a strategy per category or variable

si_dict = SingleImputer(strategy={"age":'least squares', "fnlwgt": 'least squares'})
si_data_full = si_dict.fit_transform(df8[['age', 'fnlwgt']])


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/7675b3280d02b6fb3b90ab2d3bcb4e27.png)

具有最小二乘回归模型估算值的数据集。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/0b8db0d0d7def829c1aa406f09f07482.png)

虽然这种技术很奇特,但在参数估计方面,它似乎与其他方法不相上下。当然,数据集可能与实际的机器学习训练不同,这是我们需要自己测试的东西。

在某些情况下,向回归预测中添加误差会允许更大的随机性,这可能会改善模型的参数估计,尤其是方差。不幸的是,这不能通过 autoimpute 来完成,但是如果回归模型是从零开始的,我们可以这样做。

使用相同变量进行插补的一个潜在缺点是,它可能会给参数估计带来一些偏差。这意味着,最好使用一组不包括在您当前正在研究的机器学习模型中的变量来执行回归插补。

**K-最近邻(KNN)**

与我们刚刚讨论的回归和带误差模型的回归类似,KNN 可用于填充数据集中的缺失值。

这背后的直觉是,一个点的值可以由最接近该缺失点的点来近似。

我们可以使用 scikit-learn 中的 KNNImputer 来完成这项工作:

df9 = df.copy()# importing the KNN from fancyimpute library
from sklearn.impute import KNNImputer# calling the KNN class
knn_imputer = KNNImputer(n_neighbors=3)

imputing the missing value with knn imputer

df9[['age', 'fnlwgt']] = knn_imputer.fit_transform(df9[['age', 'fnlwgt']])


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/8928bb9ac582aa9fafacb86e4abfd97d.png)

KNN 插补与其他插补方法的比较。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/877ca419cac4119c74f090be1cb16b88.png)

均值和方差估计,包括 KNN 插补

正如我们在上面看到的,KNN 似乎比其他插补方法表现更好的地方是方差的估计。

鼓励尝试不同的邻居数量公式,以获得比上面更好的结果。

# 最后的想法

虽然没有一种方法可以处理缺失数据,但本文揭示了可以用来处理缺失数据的各种技术和方法,以及它们的弱点和专业评论。

这一研究领域正在令人惊讶地、理所当然地发展,并且正在开发新的方法来处理缺失的数据。最终,选择的方法应该牢记研究目标,数据丢失的机制,以及数据集偏差的可能性。排除所有这些因素,一些数据从业者得出结论,对于简单的 MCAR 缺失,删除方法可能是首选。

鼓励数据科学家探索一种或多种方法,甚至组合使用这些方法来实现更好的模型。

虽然我们测试了不同插补方法对参数估计的影响,但最终我们希望看到这些方法如何改善机器学习模型及其预测能力。

在下一篇文章中,让我们看看处理缺失数据的一些最先进的方法:**基于模型和多重插补方法**。

[像专家一样处理“缺失数据”——第 3 部分:基于模型的&多重插补方法](/handling-missing-data-like-a-pro-part-3-model-based-multiple-imputation-methods-bdfe85f93087)

完整的代码可以在我的 [Github 页面上找到。](https://github.com/francisadrianviernes/Data-Preprocessing-and-Feature-Engineering/blob/master/Handling%20Missing%20Data%20Like%20a%C2%A0Pro.ipynb)

# 参考

麦克奈特,P. E. (2007)。*缺失数据:温柔的介绍*。吉尔福德出版社。

# 像专家一样处理“缺失数据”——第 3 部分:基于模型的多重插补方法

> 原文:<https://towardsdatascience.com/handling-missing-data-like-a-pro-part-3-model-based-multiple-imputation-methods-bdfe85f93087?source=collection_archive---------9----------------------->

## **数据科学。分析。PYTHON**

## 面向 21 世纪数据科学家的基本和高级技术

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/131fbf6c21946bdfeba4695f3a31e1cc.png)

[迈特·沃尔什](https://unsplash.com/@two_tees?utm_source=medium&utm_medium=referral)在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍照

正如我们在专门研究缺失数据系列的第一篇文章[中所提到的,关于“缺失”的机制或结构的知识是至关重要的,因为我们的处理方法将主要依赖于它。](/the-three-types-of-missing-data-every-data-professional-should-know-d988e17d6ace)

在[像专家一样处理“缺失数据”——第 1 部分——删除方法](/handling-missing-data-like-a-pro-part-1-deletion-methods-9f451b475429)中,我们已经讨论了删除方法。

在[像专家一样处理“缺失数据”——第 2 部分:插补方法](/handling-missing-data-like-a-pro-part-2-imputation-methods-eabbf10b9ce4)中,我们讨论了简单的**插补方法**。虽然某些插补方法被认为适用于特定类型的数据,例如 n *正态分布数据、MCAR 缺失等。*,这些方法主要是因为我们的估计和模型有偏差而受到批评。因此,有些人认为删除方法在某些情况下更安全。

幸运的是,新的插补方法类别**解决了简单插补和删除方法**的这些弱点。

这些是基于模型的多重插补方法。

# 加载数据集并模拟缺失

加载成人数据集并模拟本文[中的 MCAR 数据集。](/handling-missing-data-like-a-pro-part-1-deletion-methods-9f451b475429)

# 基于模型的插补方法

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/1c3c95e448a56dda702d9a68756b1a2b.png)

本文中讨论的方法的总结

在我们的主要参考文献中,McKnight (2007)对基于模型的方法进行了不同的定义。在这种情况下,使用这些方法不是为了估计缺失数据,而是为了生成参数估计,就像观察到缺失数据一样。因此,它们被更恰当地称为*数据增强方法*。

对我们来说,我们称之为基于模型,因为它们使用机器学习/统计模型来估计缺失数据。事实上,回归估计应该属于这里(来自我们的上一篇文章),但我们已经将下面的方法分开,因为它们被视为复杂得多(因此数据科学家较少使用)。

我们已经开始讨论最大似然均值的产生。让我们再讨论其中的两种,EM 算法和马尔可夫链蒙特卡罗方法。

## 期望值最大化算法

EM 算法是在数据缺失时获得最大似然估计的通用方法(Dempster,Laird & Rubin,1977)。

基本上,EM 算法由两个步骤组成:期望步骤(E)和最大化步骤(M)。这是一个为处理潜在(未观察到的)变量而设计的漂亮算法,因此适用于缺失数据。

要执行此算法:

1.  使用最大似然法估算缺失数据的值。使用每个观察值的**非缺失**变量计算缺失值的最大似然估计。
2.  根据步骤 1 为“模拟的”完整数据集生成参数估计值。
3.  基于从步骤 2 获得的参数估计值(或“更新的”参数估计值)重新估算值。
4.  根据步骤 3 中的估算数据重新估计参数。

当我们的参数估计“不再改变”或不再更新时,迭代过程停止。(*技术术语是,当前值减去更新值的误差小于某个ε。*)

与许多使用迭代的机器学习方法一样,EM 算法产生的估计偏差较小。

要用一个包来估算,首先安装`impyute`到`pip install impyute.`

与我们的线性回归一样,最好在计算最大似然估计值时包括您的研究中没有包括的变量,以免使模型产生偏差。

假设像 KNN 一样,我们希望使用下列项目的观测值来估计缺失数据:'**年龄**'、 **fnlwgt** '、**教育人数**'和'**每周工作时间**'。

代码应该是:

df10 = df.copy()# importing the package
import impyute as impy# imputing the missing value but ensure that the values are in matrix formdf10[['age', 'fnlwgt', 'educational-num', 'capital-gain', 'capital-loss',
'hours-per-week']] =
impy.em(df10[['age', 'fnlwgt', 'educational-num', 'capital-gain', 'capital-loss',
'hours-per-week']].values, loops=100)#Simulate New Comparison Container (So we can separate these new categories)
comparison_df = pd.concat([orig_df[['age', 'fnlwgt']], X], axis=1)#Rename so We can Compare Across Datasets
comparison_df.columns = ["age_orig", "fnlwgt_orig", "age_MCAR", "fnlwgt_MCAR"]
cols = comparison_df.columns.to_list()comparison_df = pd.concat([comparison_df, df10[['age', 'fnlwgt']]], axis=1)
comparison_df.columns = [*cols,'age_EM.imp', 'fnlwgt_EM.imp']#View the comparison across dataset
comparison_df.loc[fnlwgt_missing,["fnlwgt_orig","fnlwgt_MCAR",
'fnlwgt_EM.imp']]


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/d870a27eb2ed6c4d255c180bf732b468.png)

与 EM 算法插补的比较。

如我们所见,只需几行代码,我们就能执行 EM 插补。那些一直关注这个系列的人会立即看到,这是最接近我们理想想要的标准差参数的方法。

然而,这种特殊的方法假设我们的数据是多元正态的。然而,我们缺少值的特征不能被假定为正态分布。年龄和最终体重通常是正偏的,不会变成负的。

> **因此,盲目应用代码导致年龄和最终体重的插补值为负值,这是不可能的!**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/830efcfb2f3f2c3362f1c0070e93ef7e.png)

EM 方法估算的负最终权重

因此,在应用上面的代码之前,我们必须找到一种规范化值的方法。

我们可以简单地应用对数变换,并检查我们的算法对这些新变换的变量的效果。

df11 = df.copy()# imputing the missing value but ensure that the values are in matrix formdf11[['age', 'fnlwgt', 'educational-num', 'capital-gain', 'capital-loss',
'hours-per-week']] =
np.exp(impy.em(np.log(df10[['age', 'fnlwgt', 'educational-num', 'capital-gain', 'capital-loss',
'hours-per-week']].values), loops=100))


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e282181d34d9497cd623d9d89eee00d1.png)

原始数据集和对数变换数据集上 EM 代码的比较。

虽然我们的标准差较低,但与我们讨论过的其他单一插补方法相比,它仍具有更好的估计值。平均估计值也更接近原始值。

## 马尔可夫链蒙特卡罗方法

基于最大似然法的模型的一个局限性是,它们需要数据的分布假设(例如多元正态性)。

越来越流行的马尔可夫链蒙特卡罗(MCMC)程序可以在缺乏这种知识的情况下使用。该过程本质上是贝叶斯过程,最终目标是获得后验分布。

我们需要把这个概念分解成什么是马尔可夫链,蒙特卡洛与它有什么关系,但是我们把这个问题留给另一篇文章,这样这篇文章就简短了。但是像 EM 算法一样,MCMC 增加了观测数据来处理参数的估计。

从`NumPyro`开始,这些也可以采用一个包。由于这种方法使用的代码比其他方法长得多,我们将读者引向 NumPyro 的官方文档:[http://num . pyro . ai/en/latest/tutorials/Bayesian _ attribute . html](http://num.pyro.ai/en/latest/tutorials/bayesian_imputation.html)

## 其他 SCIKIT 估算器:贝叶斯岭、决策树、额外树、K 邻居

对本文中讨论的所有方法进行分类的一种方法是称它们为“多元估算器”。也就是说,它们基于数据集中存在的所有其他变量的值进行估算。

由于大多数读者被认为熟悉机器学习,另一种看待它的方式是使用数据集内的可用数据作为预测器来估算缺失数据的机器学习模型。

因为每个方法的过程都非常相似,所以让我们简单地为上面的四个方法创建一个循环。

from sklearn.experimental import enable_iterative_imputer #MUST IMPORT THIS
from sklearn.impute import IterativeImputerfrom sklearn.linear_model import BayesianRidge
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import ExtraTreesRegressor
from sklearn.neighbors import KNeighborsRegressor#STEP 1 - Choosing Variables and Create a Matrix of Values
df12 = df.copy()[['age', 'fnlwgt', 'educational-num', 'capital-gain', 'capital-loss',
'hours-per-week']]X = df12.values #Matrix of Values# STEP 2 - INITIALIZE ESTIMATORS
estimators = {
"bayesianridge":BayesianRidge(),
"DTrees": DecisionTreeRegressor(max_features='sqrt'),
"ETrees":ExtraTreesRegressor(n_estimators=10),
"KNreg":KNeighborsRegressor(n_neighbors=15)
}# STEP 3 - RUN IMPUTATIONS AND STORE IMPUTED VALUES
for key, value in estimators.items():
imputer = IterativeImputer(random_state=19, estimator=estimators[key])
imputer.fit(X)
transformed = imputer.transform(X)

#Temporarily Store
temp_df = pd.DataFrame(np.column_stack(list(zip(*transformed))), columns=df12.columns)
#Get updated columns list

cols = comparison_df.columns.to_list()

#Combine for Comparison 
comparison_df = pd.concat([comparison_df, temp_df[['age', 'fnlwgt']]], axis=1)
comparison_df.columns =  [*cols,f'age_{key}.imp', f'fnlwgt_{key}.imp']

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/10023e550adb583e9a97a6b62401fe25.png)

不同 scikit 插补的比较。

请注意,我们可以尝试的估计量并不局限于上面的估计量。这些只是在这里找到的官方文档中讨论的:[https://sci kit-learn . org/stable/auto _ examples/impute/plot _ iterative _ import _ variants _ comparison . html](https://scikit-learn.org/stable/auto_examples/impute/plot_iterative_imputer_variants_comparison.html)

# 多重插补方法

多重插补(MI)是目前处理缺失数据最受欢迎的方法。这些方法提供了无偏的(因此是可推广的)估计,并恢复了总体方差,这对于统计推断是至关重要的。

单一插补方法的主要区别在于,不是为缺失的观察值输入一个值,而是输入几个值(比如 3 到 10)。**其平均值被视为最终估算值。**

MI 不仅仅是一种方法,而是处理多重价值估算的许多方法的术语。这些多个值是从一个迭代过程中得到的,该迭代过程使用了:

1。观察数据和
2。迭代期间生成的样本值。

每组估算值随后被用来替换缺失值以创建一个完整的数据集。因此,如果我们选择估算 3 个值,这些值会产生三个完整的数据集。

这些多个估计值被组合以获得感兴趣的参数的单个最佳估计值。例如,如果我们的方法是多元回归模型,则构建三个回归模型,每个完整数据集一个。得到的模型有它们相应的参数和系数估计值,这些估计值的平均值将是我们的最终值。

在 Python 中实现这一点的一个包是 **MICEFOREST。—通过链式方程(小鼠)**和随机森林(`pip install miceforest`)进行多重插补。

回想一下,在我们之前的例子中,决策树在恢复群体特征方面表现相对较好。因此,该软件包将使用随机森林方法应用多重插补,因此,让我们希望这将产生比我们之前更好的性能。

import miceforest as mfdf13 = df.copy()df13 = df.copy()[['age', 'fnlwgt', 'educational-num', 'capital-gain', 'capital-loss',
'hours-per-week']]# Create kernel.
kernel = mf.MultipleImputedKernel(
df13,
datasets=4,
save_all_iterations=True,
random_state=1989
)# Run the MICE algorithm for 3 iterations on each of the datasets
kernel.mice(3)#View Last Dataset Imputedkernel.complete_data(2).loc[fnlwgt_missing]


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/37097f35a4ab5b03dcc031b8b1558a0f.png)

来自 MICEFOREST 的结果

在生成这些多次迭代之后,我们还需要做一件事:**我们需要对它们进行平均**。

mi_results = pd.concat([kernel.complete_data(i).loc[:,["age", 'fnlwgt']] for i in range(3)]).groupby(level=0).mean()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/853985a494f8ad6f0d39efcbbb76d28f.png)

最终比较,包括 MICE 森林估算

正如我们所看到的,我们的 MI 程序在恢复群体参数方面做得非常好。MI 的一个不言而喻的优点是,我们摆脱了上面讨论的一些方法,特别是 ML 方法所带来的分布假设。

因为 MI 方法产生渐近无偏的估计,所以它们可以被实现用于 MAR 和 MNAR 机制!这对我们数据科学家来说是一个巨大的胜利。

还有很多关于 MICE 方法的讨论,我们可以在这里回顾一下:[https://onlinelibrary.wiley.com/doi/epdf/10.1002/sim.4067](https://onlinelibrary.wiley.com/doi/epdf/10.1002/sim.4067)

# 结束语

虽然我们在这一系列文章中展示了许多备受推崇的现代技术,但我们必须记住以下几点:

1.  这些技术并不全面。新技术不断发展,推进了我们处理缺失数据的方式;
2.  该应用因用例及研究目标而异;在我们的案例中,我们只是通过参数估计来进行研究。
3.  尽管我们在这里讨论的方法很复杂,但是没有比避免缺失数据更好的方法来处理缺失数据。研究者应该对适当的研究设计、收集、储存和提取给予适当的考虑。

完整代码可以在我的 [Github 页面](https://github.com/francisadrianviernes/Data-Preprocessing-and-Feature-Engineering/blob/master/Handling%20Missing%20Data%20Like%20a%C2%A0Pro.ipynb)找到。

# 参考

麦克奈特,P. E. (2007)。*缺失数据:温柔的介绍*。吉尔福德出版社。

<https://github.com/AnotherSamWilson/miceforest#Simple-Example-Of-Multiple-Imputation>  <https://onlinelibrary.wiley.com/doi/epdf/10.1002/sim.4067> 

# 在烧瓶应用程序中处理 ML 预测

> 原文:<https://towardsdatascience.com/handling-ml-predictions-in-a-flask-app-1ccfeff06326?source=collection_archive---------37----------------------->

## 不要让长时间运行的代码拖慢你的 Flask 应用程序

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/285997d2ce2fc1551a64deb8a9347475.png)

[HalGatewood.com](https://unsplash.com/@halacious?utm_source=medium&utm_medium=referral)在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍照

我为 Metis 数据科学训练营做的一个项目涉及创建一个 Flask 应用程序的 MVP,向用户显示电影推荐(想想网飞主屏幕)。

我的建议包括模型预测与 SQL 查询的结合——所有这些都是在请求进来时、响应发出之前完成的。演示日到来时,加载网站主页大约需要 30 秒。

我的 Flask 应用程序的简化版代码

公平地说,这是我在*数据科学*训练营的一个很短的期限内创建的一个 MVP 不是网络开发训练营。尽管如此,30 秒的等待时间并不太好。

毕业后,一旦我有了更多的时间,我就重新审视我的项目,看看我还能改进什么。

这里有两个我可以探索的选项,它们可以大大加快我的页面加载时间,而不必改变我的预测算法。

# 1)加载页面,然后进行预测

不要在返回主页之前进行预测(就像上面的代码一样),而是将预测代码与 Flask 应用程序中的页面响应代码分开。返回没有预测的页面。然后,加载页面后,使用 JavaScript 调用 API。下面是更新后的 Flask 应用程序代码的样子:

更新 Flask 应用程序,其中 ML 预测被移动到单独的路线

下面是 JavaScript 代码的样子:

用于查询 Flask API 的 JavaScript 代码片段

这是对初始代码的一个小改动,但对用户来说却有很大的不同。该页面最初可以加载占位符图像或加载栏,以便用户在等待加载预测时仍然可以与您的站点进行交互。

# 2)把工作交给芹菜

通过在 Flask 响应函数中运行 ML 预测或复杂的 SQL 查询等缓慢的过程,您会使 Flask 服务器陷入困境。这可能不是你关心的问题,取决于你期望得到多少流量。也许这只是一个概念验证,或者一次只有少数人会使用你的服务。在这种情况下,只要使用我们的 API 方法就可以了。否则,您可能需要考虑一个可以水平扩展的解决方案。

进入[Celery](https://docs.celeryproject.org/en/stable)——一个用于创建“分布式任务队列”的 python 库。使用 Celery,您可以创建一个工人池来处理收到的请求,这就像在 python 函数中添加一个装饰器一样简单。

对于我们新的 Celery 工作流,我们将把 API 路径分成两部分:一部分用于安排预测,另一部分用于获取预测结果。

让我们来看看更新后的 Flask 片段:

这是新的芹菜片段:

以及更新后的 JavaScript:

现在我们开始加载页面,然后 JavaScript 将安排模型预测,并继续检查结果,直到它们准备好。

诚然,这增加了我们解决方案的复杂性(您需要添加一个像 Redis 这样的代理,并启动一个单独的芹菜工人进程),但它允许我们通过向我们的池中添加所需数量的芹菜工人来横向扩展我们的应用程序。

要查看完整的示例,请查看 GitHub repo:

<https://github.com/a-poor/flask-celery-ml>  

感谢阅读!我很想听听你的反馈。让我知道你使用什么技术来添加 ML 到 Flask 应用程序中。请在下面留下你的评论,或者在 Twitter 或 LinkedIn 上联系我。

# 在 Python 中处理绘图轴脊线

> 原文:<https://towardsdatascience.com/handling-plot-axis-spines-in-python-f143b8554da2?source=collection_archive---------9----------------------->

## matplotlib 和 seaborn 中一些有用的方法和技巧

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/9dc086d1919135fa6c7086f8603d29cb.png)

来自 [Unsplash](https://unsplash.com/photos/UaB91-kVLb4)

轴脊线是限制绘图区域的线。根据不同的情况,我们可能要删除一些(或全部)它们,改变它们的颜色,使它们不那么明显,调整它们的宽度/样式,或者改变它们的位置。在本文中,我们将探索一些处理轴刺的简便方法。

# 移除脊椎

很多情况下,我们只需要去掉棘突。让我们假设我们有下面的情节:

import numpy as np
import matplotlib.pyplot as pltx = np.arange(0, 5, 1)
y = 2 * x
plt.plot(x, y)
plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/20bfc031f8e6e65263f815de13daf109.png)

作者图片

我们想从轴上去掉顶部的脊椎。为此,我们可以使用*面向对象 API 接口*的`set_visible()`方法(即当我们使用`ax.plot`而不是`plt.plot`时)。语法如下:`ax.spines['top'].set_visible(False)`。要删除几根刺,使用 For 循环是有意义的:

fig, ax = plt.subplots()
ax.plot(x, y)
for spine in ['top', 'right']:
ax.spines[spine].set_visible(False)
plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/c6196bbc5b91304e5042522eaa62fee0.png)

作者图片

更直接的方法是使用 seaborn 实用函数`sns.despine()`。在这种情况下,我们是使用面向对象的 API 还是 pyplot 接口并不重要。如果没有传入参数,默认情况下,顶部和右侧的脊线将被移除:

import seaborn as snsplt.plot(x, y)
sns.despine()
plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/c6196bbc5b91304e5042522eaa62fee0.png)

作者图片

可以移除任何剩余的脊线(如`left=True`)或恢复默认移除的脊线(如`right=False`)。

要一次移除所有 4 根刺,我们可以使用`set_visible()`或`sns.despine()`,但有一种更短的方法:使用`plt.box()`方法。

plt.plot(x, y)
plt.box(on=False)
plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/2ccda64d4ae6e27057df34fd5cad9c75.png)

作者图片

# 更改书脊颜色和透明度

`set_color()`和`set_alpha()`方法与面向对象的 API 接口相关,语法类似于`set_visible()`的语法。当我们想要保留脊线但使其不明显时,`set_alpha()`方法很方便:

fig, ax = plt.subplots()
ax.plot(x, y)
ax.spines['left'].set_color('red')
ax.spines['bottom'].set_alpha(0.2)
plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/f2a54a12d669076b0dc80021f5115362.png)

作者图片

# 调整书脊宽度/样式

现在让我们试着用方法`set_linewidth()`和`set_linestyle()`改变我们的绘图的宽度和样式,其中后者可以接受以下值:`'solid'`(默认)、`'dashed'`、`'dashdot'`或`'dotted'`。

fig, ax = plt.subplots()
ax.plot(x, y)
ax.spines['left'].set_linewidth(3)
ax.spines['bottom'].set_linestyle('dashed')
plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/6cea318611c88cfed6057fd82abf8b85.png)

作者图片

看来`set_linestyle()`的方法没有起到预期的效果。我们可以通过改变同一脊柱的宽度来解决这个问题:

fig, ax = plt.subplots()
ax.plot(x, y)
ax.spines['bottom'].set_linewidth(4)
ax.spines['bottom'].set_linestyle('dashed')
plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/61f4bab5d3c2a11e82105d344d3a1ec5.png)

作者图片

现在看起来更好,但破折号彼此太近。为了进一步修复它,我们可以调整轴脊的另一个属性:capstyle,即每个虚线或圆点的结束样式。柱帽可以是凸出的*、*对接的*或圆形的*。为了理解它们之间的区别,让我们来看下面的示意图,该示意图显示了长度相同但顶样式不同的破折号:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/50462ac444f5cc0072a4ce4e6af4112f.png)

作者图片

我们看到*平头*帽型是最不“占用空间”的,而轴棘的默认帽型是*凸出*。让我们应用`set_capstyle()`方法并传入一个新值来调整我们的绘图:

fig, ax = plt.subplots()
ax.plot(x, y)
ax.spines['bottom'].set_capstyle('butt')
ax.spines['bottom'].set_linewidth(4)
ax.spines['bottom'].set_linestyle('dashed')
plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/fc0e10c8df8c640ae5a04af469e2438b.png)

作者图片

还有一种提供书脊样式的替代方法:向`set_linestyle()`传递一个以下形式的元组: *(offset,onoffseq)* ,其中*偏移量*通常为 0, *onoffseq* 是一个以磅为单位的偶数长度的开/关墨迹元组。这种方法甚至更方便,因为它不需要调整任何其他参数,如宽度或 capstyle。我们可以用它来制作虚线、点线或任何其他图案的脊柱:

fig, ax = plt.subplots()
ax.plot(x, y)
ax.spines['top'].set_linestyle((0, (10, 10)))
ax.spines['right'].set_linestyle((0, (10, 10, 1, 10)))
plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/436517bfd23dcbd2afe0533eaf0bf093.png)

作者图片

# 改变位置

我们可以使用`set_position()`方法将任意脊柱放在任意位置,并传入以下形式的元组:*(位置类型,数量)*。可能的职位类型有:

*   `'outward'` —在绘图区域之外(或在绘图区域之内,如果以点为单位的数量为负值),
*   `'axes'` —在指定的坐标轴坐标上,可以取 0 到 1 的值,
*   `'data'` —在指定的数据坐标上。

例如,最后一个选项对于在 0:

x1 = np.arange(-5, 5, 0.1)
y1 = np.sin(x1)
fig, ax = plt.subplots()
plt.plot(x1, y1)
ax.spines['left'].set_position(('data', 0))
sns.despine()
plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/6ef09c841bdcdd3ec6469af76bd3c425.png)

作者图片

`'outward'`位置类型在`sns.despine()`函数中有一个等价类型,我们可以传入可选的`offset`参数。该参数可以接受一个整数作为所有可见脊线的偏移量,也可以接受一个字典来分别指定每个可见脊线的偏移量。以下两个图是相同的:

fig, ax = plt.subplots()
ax.plot(x, y)
ax.spines['left'].set_position(('outward', 20))
sns.despine()
plt.show()fig, ax = plt.subplots()
ax.plot(x, y)
sns.despine(offset={'left': 20})
plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/293abd1b191a16603f7abf444cd26f98.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/293abd1b191a16603f7abf444cd26f98.png)

作者图片

最后,谈到定位 spines,在某些情况下,还有一种方法是有用的:`set_zorder()`。向它传递 0,我们可以在情节后面“隐藏”一个脊柱。下面我们来对比一下剧情:

fig, ax = plt.subplots()
plt.plot(x1, y1, color='red', linewidth=5)
ax.spines['left'].set_position(('data', 0))
ax.spines['left'].set_linewidth(5)
sns.despine()
plt.show()fig, ax = plt.subplots()
plt.plot(x1, y1, color='red', linewidth=5)
ax.spines['left'].set_zorder(0)
ax.spines['left'].set_position(('data', 0))
ax.spines['left'].set_linewidth(5)
sns.despine()
plt.show()


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/6d6f5aff3a8c73c1daf4ec0520add8a8.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/d3e6a8189e42ae123bcd274482790ebc.png)

作者图片

# 结论

在本文中,我们探讨了在 matplotlib 和 seaborn 库中处理轴刺的不同方法和技巧,包括删除它们、更改它们的颜色和透明度、调整宽度/样式或更改位置。

感谢阅读!

**你会发现这些文章也很有趣:**

</how-to-fill-plots-with-patterns-in-matplotlib-58ad41ea8cf8>  </an-unconventional-yet-convenient-matplotlib-broken-barh-function-and-when-it-is-particularly-88887b76c127>  </how-to-fetch-the-exact-values-from-a-boxplot-python-8b8a648fc813> 

# 使用 Google AutoML 进行自动机器学习

> 原文:<https://towardsdatascience.com/hands-off-machine-learning-with-google-automl-e63b079f09d1?source=collection_archive---------6----------------------->

## Google 表格数据的 AutoML 简介

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e0e82088b0790c09a492935dc1eeb8f2.png)

[Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上 [AltumCode](https://unsplash.com/@altumcode?utm_source=medium&utm_medium=referral) 拍摄的照片

# **为什么是 AutoML?**

如今,表格数据无处不在,可以为我们提供对业务和工程问题的有意义的见解。提取这些见解的一种常见方法是对这些数据应用机器学习(ML)技术。将 ML 应用于数据集的过程由各种步骤组成,*例如,*数据预处理、特征工程和超参数优化,这些步骤中的每一个通常都是耗时的反复试验过程。此外,一个人需要成为 ML 领域的专家,以便在这些步骤中的每一步都高效和有效。对于一个组织来说,要么从外部找到这些领域专家,要么在内部培养这种专业技能,这可能需要相当长的时间。

进入[谷歌的 AutoML 平台](https://cloud.google.com/automl),*,该平台使开发者(具有有限的 ML 专业知识)能够针对他们的需求训练高质量的模型*。作为谷歌统一 ML 平台 Vertex AI 的一部分,它提供了在视觉(图像和视频)、文本和结构化数据上自动训练模型的能力。在本教程中,我们将使用结构化数据的 AutoML 表格来训练预测[加州房价](https://www.kaggle.com/camnugent/california-housing-prices)、的模型。关于本文讨论主题的更多细节,我们参考[顶点人工智能文档](https://cloud.google.com/vertex-ai/docs/datasets/prepare-tabular)。该文档非常广泛,还包含其他 AutoML 产品的指南,*即*培训视觉和文本模型。

# 数据准备

在开始培训之前,我们必须确保培训数据采用平台支持的格式。AutoML 表格支持两种导入培训数据的方式;如果我们已经在使用 Google 的 BigQuery 平台,我们可以直接从 BigQuery 表中导入数据,或者上传一个逗号分隔值(CSV)文件到云存储中。对于本教程,我们将通过第二种方法。我们在下表中总结了 CSV 文件的要求。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/577f74aab2588ac45c5fdc39c73944e9.png)

AutoML 表格培训数据格式摘要(图片由作者提供)

# 创建数据集

可以通过谷歌云平台(GCP)控制台导入数据集。在顶点人工智能部分有一个数据集页面,我们可以在那里管理我们的数据集。在这里,我们可以创建一个表格数据集,并为该数据集选择一个数据源。一旦提供了数据源,将显示一个显示数据一般统计信息的页面。这些步骤如下图所示;左边是数据集创建,中间是数据源选择,右边是统计视图。对于我们的例子,我们上传了包含[加州房价数据集](https://www.kaggle.com/camnugent/california-housing-prices)的 *housing.csv* 。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/b025fe684c703aedaecaa25ea1f43cc8.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/9b306196643ae5c4eb25f9fb82d91456.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/b2011a9a58a55fdd2b6f203294d55387.png)

顶点人工智能数据集创建、源选择和统计页面(图片由作者提供)

# 训练模型

一旦数据集被创建,我们就可以开始训练我们的第一个模型。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/79fb384045654c9bc2f7086dfe803f20.png)

训练方法选择对话(图片由作者提供)

我们通过点击统计页面上的*训练一个新模型*来启动这个过程。然后,我们会看到一个对话框,允许我们**选择培训目标**,以及我们是使用 AutoML 来培训模型,还是使用定制的培训解决方案。对于我们的示例,我们选择回归作为训练目标,选择 AutoML 作为训练方法。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/2fb14f1375ee1cb04ef096cd97eab552.png)

模型细节对话(图片由作者提供)

接下来,我们被要求**选择我们想要训练我们的模型来预测的目标变量/列**。在高级选项下,我们还可以控制如何在训练集、验证集和测试集之间拆分数据。

这种拆分可以通过随机分配、手动分配和基于所选列的按时间顺序分配来完成。对于我们的示例,我们选择*中值房屋价值*作为目标,并保留高级选项的默认值。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/76484658852ac05311b934ad0819641d.png)

培训选项对话(图片由作者提供)

之后,系统会提示我们检查 AutoML 为我们的数据推断的数据类型。**对于每一列,我们可以选择一个转换,*即*数据类型(分类、文本、时间戳或数字),以及我们是否希望它被** **包含在训练过程中**。在高级选项下,我们可以额外选择一个列,我们希望将其用作行的权重和优化目标。对于回归,这些目标包括 RMSE、MAE 和 RMSLE。[任何额外的预处理和/或特征工程最好留给 AutoML。](https://cloud.google.com/vertex-ai/docs/datasets/bp-tabular#tabular_data_preparation_best_practices_for_models)

对于我们的数据集,推断的数据类型是正确的。我们还在培训过程中包括所有列,并保留高级选项的默认值。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/af2ec1c8f8a8df85fdf4d24815039d5c.png)

培训预算对话(图片由作者提供)

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/567221bfd7dcfa904e9ffe61822f6795.png)

基于数据集大小的建议训练次数(图片由作者提供)

最后,要求**提供培训预算**、*,即*用于培训的最大节点小时数。我们根据谷歌建议的培训时间来选择我们的培训预算。培训预算设定后,培训过程将开始,并可通过 GCP Vertex AI 部分的培训页面进行监控。培训时间可能会比设定的培训预算长,但是,您将只需支付实际节点时间的费用,该时间受您设定的预算限制。一旦训练过程完成,最终的模型将出现在 Vertex AI 的模型页面上。从那里我们可以观察到各种性能指标和最终模型的特性的重要性,如下图所示。可以检查特性重要性图,以确保最重要的特性对我们的数据/业务问题有意义。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/2ff659b089fd99d2a873d5f76ff18daa.png)

根据表格数据训练的自动回归模型的模型概述(图片由作者提供)

对于我们的例子,我们可以看到均方根误差约为 48.000,这看起来似乎很多,但实际上可以与人类训练的[模型的性能相媲美](https://www.kaggle.com/shtrausslearning/bayesian-regression-house-price-prediction)(数据集非常旧,不包含最佳特征集)。在性能指标下面,我们可以看到每一列的分数,表明它在进行预测时的重要性。我们可以看到, *total_rooms* 和 *population* 列被模型视为两个最重要的特性。

# 部署、测试和可解释性

然后,由 AutoML 生成的训练模型可以以两种方式部署;我们可以将模型导出为保存的 TensorFlow (TF)模型,然后我们可以在 Docker 容器中为自己服务,或者我们可以将模型直接部署到 GCP 端点。这两个选项都可以在模型页面上的*部署和测试*选项卡下找到。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/933d8e8a67d43c31df41b8304d41021b.png)

(图片由作者提供)

我们将示例中的模型部署到 GCP 端点,以便通过 GCP 控制台进一步测试它。一旦模型部署完毕,我们就可以开始通过 GCP 提供的[不同方式之一进行测试。我们使用了 GCP 控制台提供的 web 界面,它可以在前面提到的*部署和测试*选项卡的底部找到。在那里,我们可以处理模型的输入值,并观察它做出的预测。](https://cloud.google.com/vertex-ai/docs/predictions/online-predictions-automl)

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/e4869b63f41bb184cad8c0eaf98bce1f.png)

部署的 AutoML 模型预测+解释(图片由作者提供)

有趣的是,这个 web 界面不仅显示预测,还通过局部特征重要性值提供解释。对于 AutoML 表格(分类和回归)模型,使用[采样 Shapley 方法](https://cloud.google.com/vertex-ai/docs/explainable-ai/overview#compare-methods)计算这些值。这些解释值也可以在 GCP 控制台之外通过使用 Vertex AI 的[解释 API](https://cloud.google.com/vertex-ai/docs/predictions/online-predictions-automl#explanations-api) 来请求。

# 摘要

在本文中,我们展示了如何使用 Google AutoML 来训练、测试和部署一个 ML 模型,而不需要很多 ML 领域的专业知识。这使得 ML 民主化,允许 ML 专业知识有限的团队将 ML 应用到他们的数据中,并毫不费力地将结果模型部署到生产中。对于经验丰富的 ML 从业者,Google 的 AutoML 提供了有趣的高级配置选项,可以用来简化现有的 ML 工作流程。

# 使用可变自动编码器进行实际异常检测

> 原文:<https://towardsdatascience.com/hands-on-anomaly-detection-with-variational-autoencoders-d4044672acd5?source=collection_archive---------1----------------------->

## 使用贝叶斯式重构方法检测表格数据中的异常

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/572dfe0da8561aba92b65e620531b6da.png)

Pawel Czerwinski 在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上的照片

# 一.导言

异常检测是机器学习产生如此影响的领域之一,以至于今天几乎不用说,异常检测系统必须基于某种形式的自动模式学习算法,而不是基于一组规则或描述性统计(尽管许多可靠的异常检测系统使用这种方法非常成功和有效地运行)。

事实上,在过去十年左右的时间里,各种异常检测的 ML 方法变得越来越流行。一些方法,如一类 SVM,试图识别数据分布的维度空间中的“正常”区域或平面,然后将位于该区域之外的任何样本标记为异常。其他方法试图估计代表训练数据的分布(或混合分布)的参数,然后将任何看起来不太可能出现异常的样本指定为异常。每种方法都有自己的假设和需要考虑的弱点,这也是为什么测试异常检测算法并使其适合特定领域很重要的部分原因。

另一种流行的异常检测方法是基于 r *重建方法*,随着深度学习变得更加广泛,这种方法已经获得了很大的吸引力。潜在的想法是基于这样的假设,如果模型可以学习压缩和重建正常数据的函数,那么当遇到异常数据时,它将无法这样做,因为它的函数只在正常数据上训练。因此,重建数据的失败,或者更准确地说,重建误差的范围,可以表示异常数据的存在。

已经使用深度自动编码器(AE)实施了异常检测的重建方法,并取得了非常好的结果,尽管越来越多的文献表明使用更复杂的概率变分自动编码器可以改善结果,该编码器首先由 Diederik Kingma 和 Max Welling (2014 年)提出。尽管 VAEs 主要是作为图像和文本生成的生成模型而设计的,但是我们将会看到它们的一些特性也可以在异常检测领域得到利用。

有很多关于 VAEs 理论和数学的文章。然而,这篇文章的目的是采取一种更实际的或动手操作的方法,使读者只需要一点背景知识和一些代码就可以快速地构建一个可测试的模型。完整的实现链接在一个使用 KDDCup99 数据集的可复制笔记本中,该数据集通常用作异常检测文献中的基准,并显示接近 SOTA 的结果。

文章如下:第二部分非常简要地讨论了自动编码器和异常检测的重构方法。请注意,本部分旨在快速复习,并假设读者了解自动编码器的工作原理。如果没有,我不久前写了一篇关于自动编码器的[短文](/a-keras-based-autoencoder-for-anomaly-detection-in-sequences-75337eaed0e5),作为开始可能会有帮助。第三节集中在变型自动编码器和它们与传统自动编码器之间的区别。第四节深入研究了代码和实现细节。第五节得出结论。

# 二。自动编码器和异常检测

自动编码器是一种深度学习模型,通常基于两个主要组件:学习输入数据的低维表示的*编码器*,以及试图使用编码器生成的低维表示以原始维度再现输入数据的*解码器*。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/a8a9b2061a21948c09799a8fb305e306.png)

来源:[https://towardsdatascience . com/generating-images-with-auto encoders-77fd 3a 8 DD 368](/generating-images-with-autoencoders-77fd3a8dd368)

这种架构的基本思想与图像压缩非常相似:一个训练有素的编码器学会以这样一种方式对输入数据进行编码,这种方式将捕获它包含的最重要的信息,从而足以(或尽可能接近足以)由解码器再现它。

AE 通过尝试最小化*再现误差*或原始输入向量与解码器从编码数据再现的输出向量之间的差异来学习对输入数据进行编码。如下图所示,尽管使用自动编码器重新生成的图像缺少一些细节,但其总体形状得以保留,这意味着编码器至少捕获了输入图像中包含的一些重要信息。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/15e26488898aa280482242a554f555a4.png)

来源:[https://en.wikipedia.org/wiki/Autoencoder](https://en.wikipedia.org/wiki/Autoencoder)

这和异常检测有什么关系?简单明了的答案是,如果我们的 AE 经过充分训练,能够很好地再现其接受训练的输入数据,并且假设它接受了足够多的数据训练,那么当它被输入了与其接受训练的数据“相似”的数据时,它会产生或多或少稳定且最小的再现误差。然而,这也意味着不寻常的或极端的再现错误可能意味着 AE 遇到了与它被训练的输入非常不同的输入向量,因此它不能正确地再现它。如果显示给我们的 AE 的数据应该与它被训练的数据相似,那么产生极端再现误差的输入很可能是异常。

例如,如果我们在猫的图像上训练 AE,那么它可能很难再现大象的图像,并且如果这种大象的图像将被提供给在猫的图像上训练的 AE,那么它可能产生相对较高的再现误差,这可能正确地指示异常。当数据的维度很高,并且很难识别正常数据的行为以及哪些行为过于极端而不能被视为正常时,这种方法的最大好处就来了。

# 三。可变自动编码器

AE 以它认为最有效的方式将输入数据编码到潜在空间中,以便再现它。简而言之,编码器学习一个“函数”,该函数获取大小为 *n* 的向量,并输出大小为 *m* 的向量(使得*m<n*),*解码器*函数可以容易地使用该向量来再现原始输入向量。这意味着,例如,即使两个数据点非常相似,编码器也可以选择将它们放置在潜在空间中彼此相对较远的位置,如果这样可以最小化重建损失的话。这种架构中的编码器功能的输出产生非常离散的潜在空间,并且通常类似于过度拟合的模型。因此,虽然 AE 可以形成一个潜在空间,使其能够非常准确地完成任务,但对于它所产生的潜在空间的分布和拓扑结构,或者数据在那里是如何组织的,我们没有多少可以假设的。

在 VAE 中,编码器类似地学习将大小为 *n.* 的向量作为其输入的函数,然而,VAE 学习生成两个向量(大小为 *m)* ,这两个向量表示分布的参数(均值和方差),从该分布中对潜在向量进行采样,并且解码器函数可以将其转换回原始输入向量,而不是像传统 AEs 那样学习如何生成解码器函数可以再现的潜在向量。简而言之,AE 的学习任务*是学习将数据转换为解码器可以轻松再现的潜在向量的函数*,而 VAE 的学习任务*是学习生成分布参数的函数,解码器可以轻松再现的潜在向量可以从该分布参数中进行采样* d。更具体地说:

In an AE: () encoder(input_vector[]) => latent_v[]latent_v[] is our latent features vectorIn a VAE: () encoder(input_vector[]) => latent_v_mu[], latent_v_lvar[]So that - latent_v[0] ~ N(latent_v_mu[0], latent_v_lvar[0])and latent_v1 ~ N(latent_v_mu1, latent_v_lvar1)As the other elements in the latent feature vector, latent_v[0] is sampled from a distribution parameterized by the mean and variance produced by the encoder (and which are forced by the KL loss function to be closer to N(0, 1))


因此,VAE 的潜在空间实际上是从编码器为每个潜在特征学习的分布中采样的。上面没有提到的另一个重要细节是,VAE 使用由两个部分组成的损失函数:(1)一个*重建损失部分*——它迫使编码器生成最小化重建损失的潜在特征,就像 AE 一样,否则它会受到惩罚;(2)*KL 损失分量*——其迫使编码器生成的分布类似于假设为正态的输入向量的先验概率,并因此将潜在特征空间推向正态。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/76391c483a55431ebdf5299477441889.png)

来源:维基百科—[https://en.wikipedia.org/wiki/Variational_autoencoder](https://en.wikipedia.org/wiki/Variational_autoencoder)

因此,VAE 产生的潜在空间更加“驯服”并趋于正常。因为编码器被高度正则化以生成正态分布,并且潜在向量本身是从正态分布采样的,所以潜在空间将更加连续和平滑。下图清楚地显示了(1)编码器的潜在空间,该编码器仅基于重建损失产生潜在空间;(2)仅试图最小化 KL 损失并对分布(即,均值 0 和 var 1)施加正态性的编码器,这就是为什么所有数据点都被分组在相同的中间区域周围;(3)结合了重建损失和 KL 损失的 VAE 的潜在空间。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/178f43153ebe0375b0bd28e73e184778.png)

鸣谢:Irhum Shafkat,来源:[https://towards data science . com/直观-理解-变分-自动编码器-1bfe67eb5daf](/intuitively-understanding-variational-autoencoders-1bfe67eb5daf)

所有这些并不一定意味着 VAE 在每个异常检测任务中都会比人工智能表现得更好。vae 主要作为生成模型而闪耀,但是生成平滑且连续的潜在空间的优点对于异常检测任务来说也是有价值的,因为它的结果将以这种任务通常要求的方式更加稳定和可预期。

# 四。履行

这一部分的目的是快速探究可以检测异常的 VAE 的实现代码。我使用了 KDDCup99 cup 异常检测数据集,它经常被用作异常检测文献中的基准。这里我展示了代码的主要部分,而完整的实现可以在链接的笔记本中找到。

对于这个实现,我基本上遵循了 VAE 上的 Keras 博客中的代码示例,并进行了一些调整。我们将从模型的实现开始,然后寻找异常。

## VAE 模式

*编码器*:第一个重要的部分是编码器,它将大小为 *n* 的向量作为输入,并生成潜在向量( **z** )。然而,回想一下,在 VAE 中,编码器首先学习构成潜在向量的分布的参数,然后通过从该分布中采样来生成潜在向量 **z** 。如下图所示(第 5–6 行),编码器首先学习 **z** 分布的均值和(对数)方差(即分别为 z_mean 和 z_log_var)。然后,它使用 lambda 层从该分布中采样 **z** ,调用函数 *sample(z_mean,z_log_var)* ,我们稍后将看到该函数,它返回采样向量 **z** 。

*sample()* 函数的目的是通过返回正态分布的 **z** 的*平均值+sigma***ε*来对其进行采样。正如 Francois Chollet 所解释的,ε的作用是确保潜在空间的连续性:

> 因为 epsilon 是随机的,这个过程确保了靠近你对[输入向量](z_mean)进行编码的潜在位置的每一个点都可以被解码成类似于[输入向量]的东西,从而迫使潜在空间持续有意义。潜在空间中的任意两个接近点将解码为高度相似的图像。连续性与潜在空间的低维度相结合,迫使潜在空间中的每个方向对数据变化的有意义的轴进行编码,使得潜在空间非常结构化,因此非常适合于通过概念向量进行操作(使用 Python 的深度学习,第 2 版。).

Chollet 显然试图让事情变得简单,尽管没有过多地进入理论(我自己也不完全理解),但据称*ε*引入的正态随机性对于网络通过反向传播不断校正其参数也是必不可少的。

*解码器*:解码器相当简单。就像在传统的自动编码器中一样,它将采样的潜在向量 **z** 作为其输入,并试图再现它,只是在 VAE 的情况下,它实际上是生成组件。

以及最终的模型。

VAE 的主要组成部分之一是损失函数,如上所述,该函数试图在两个优化任务之间取得平衡:(1)最小化重建误差——这可以通过误差项来实现,例如我在下面使用的 MSE,或者通过其他差分函数来实现;(2)最小化 KL 散度——这实质上迫使 **z** 的分布趋于正态(例如,参见[这里的](https://forums.fast.ai/t/intuition-behind-kl-divergence-regularization-in-vaes/1650))。这可能是您希望根据结果进行调整的参数。两者之间的适当平衡将迫使 **z** 中的分布趋于常态,同时还确保网络能够再现输入向量。这将确保我们创建一个平滑和连续的潜在空间(由于强加的正态性),并形成我们可以用来检测异常和测量相似性的数据的准确表示。

然后,我们用组合损失函数拟合模型。

## 发现异常

异常检测的重建方法通过其相对较高的重建误差来识别异常。因此,当模型可以首先根据正常数据或大部分正常数据进行定型时,这些方法最有效。这样,我们可以增加我们的信心,即相对较高的重建误差是由真正的异常引起的。

具体来说,以下通常是一个良好的开端:

1.  测量原始训练(干净/正常)集和模型输出之间的误差,并生成表示每个样本的误差项的误差向量。
2.  在向量上找到一个相对极端的值作为你的误差阈值。假设一些异常可能会在训练集中引入一些噪声,因此选择 99%作为阈值(而不是最大的极值)是一个好主意。
3.  在测试或真实数据上运行模型,其中异常数据可能与正常数据混合在一起。
4.  测量重建误差并将表现出高于误差阈值的误差项的样本标记为异常。

正如您在下面所看到的,在 KDDCup99 数据集上使用这个非常简单明了的模型产生了一个非常令人印象深刻的结果(其中一些与该数据集的 SOTA 结果相差不远)。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/15d6e2d939faa57fdc6f14f0c39d4821.png)

我们还可以通过仅使用编码器模型而不使用解码器来检查编码器生成的潜在空间。

from sklearn.decomposition import PCAX_encoded = encoder.predict(X_test)pca = PCA(n_components=2)
X_transform = pca.fit_transform(X_encoded)


下图显示了编码器生成的潜在空间的散点图(在减暗至 2 暗后)。每个点的颜色反映了其相关的重建误差项(在 mae_vector 中)。暗点意味着更大的误差项。我们可以清楚地看到一大群看起来很正常的点(误差项相对较小),被 3 个误差项相对较大的主要点群所包围。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/cdd2228427927f059b93b46fb70c6a86.png)

我们可以用下面的图来证实这一点,该图在将每个超过误差阈值的点标记为异常(橙色)后,绘制了上面相同的点。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/0c7c1a768573f5479b81e651bea88bad.png)

最后,我们可以将上面的图与下面的真实图进行比较,后者实际上显示了数据的真实标签。也就是说,图中橙色的点实际上是异常点——网络攻击期间发送的网络数据包。我们可以看到,虽然我们正确识别了绝大多数异常(98%),但仍有一小部分我们未能识别,如图所示,这可能是因为与正常点有些相似。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ea8ae2b75dbe85b06bd09e4755dc052b.png)

# 动词 (verb 的缩写)摘要

变型自动编码器被广泛认为对各种机器学习任务极其有效。有很多关于变分自动编码器的文章,但是在异常检测领域没有太多的实际例子。这篇文章的目的是通过提供一个简单的例子来帮助填补这个空白,这个例子可以用来原型化和测试它。

VAEs 的最大优点来自于对生成的潜在空间施加的正则化。使用更平滑、更连续的向量空间的能力可以产生更稳定、更准确的结果,因为它可以确保相似的数据点靠得更近,并使相似性度量更可靠。在提出一个简单的架构后,我展示了 VAE 网络的这些特性如何通过相对较少的调整产生令人印象深刻的结果,尽管我试图强调如果结果不令人满意,需要在哪里进行调整和实验。

我认为,在异常检测领域,能够试验和有效测试不同的方法是非常重要的,因为每个领域都有自己的“特征”,有时允许我们做出某些假设,有时禁止我们做出其他假设。我希望这篇文章能让一些人在他们的工具箱中添加另一个工具,并鼓励更丰富的实验。

>>可复制笔记本可在我的 git 上获得[此处](https://github.com/a-agmon/anomaly_det/blob/master/AnomalyDetectorsVAE-KDD-original.ipynb)

>>一些非常好的参考资料:

[1]原论文:迪德里克·P·金马,马克斯·韦林,*自动编码变分贝叶斯*(2014)【https://arxiv.org/abs/1312.6114 

[2][https://towards data science . com/understanding-variable-auto encoders-vaes-f 70510919 f 73](/understanding-variational-autoencoders-vaes-f70510919f73)

[3][https://www.jeremyjordan.me/variational-autoencoders/](https://www.jeremyjordan.me/variational-autoencoders/)

[4][https://towards data science . com/直观-理解-变分-自动编码器-1bfe67eb5daf](/intuitively-understanding-variational-autoencoders-1bfe67eb5daf)

[5][https://wise odd . github . io/tech blog/2016/12/10/variation-auto encoder/](https://wiseodd.github.io/techblog/2016/12/10/variational-autoencoder/)

# 使用 Python 通过深度学习实践气候时间序列分类

> 原文:<https://towardsdatascience.com/hands-on-climate-time-series-classification-with-deep-learning-using-python-6d5de81004c9?source=collection_archive---------4----------------------->

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ff2c46f811a9c0b7aecf287b7493938a.png)

照片由[萨夫](https://unsplash.com/@saffu?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)在 [Unsplash](https://unsplash.com/s/photos/time?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 上拍摄

## 下面介绍如何用几行代码构建一个深度神经网络进行时间序列分类

**时间序列是我们生活中很大的一部分**。基本上**一切**都可以被建模为随着时间增加(在 x 轴上)而变化的某个量(在 y 轴上)。

另一方面,**分类是机器学习的一个重要应用。事实上,我们很容易将许多目标视为分类任务。**

把这两件事结合在一起我们就有了**时间序列分类。**我们的目标很容易确定:

> 我们想要一个模型,给定一个时间序列(即一个随时间变化的量),能够输出一个类。

有大量的文章解释了这个目标背后的理论(在我看来,Marco Del Pra 在这篇文章中做得非常好)。本文不会关注理论,但会给出一个实用指南**关于如何对现实世界的时间序列进行分类,使用 Python 从头开始构建你的分类器。**

在我们的具体例子中,我们希望根据温度的时间序列来区分一个国家的大陆(欧洲、亚洲或非洲)。

所以让我们开始吧!

> 请注意:本文意在跟随您,**循序渐进,**走向解决方案。如果您对**预处理部分、**不感兴趣,请直接跳到**机器学习模型部分**或**结果部分。**

## 0.图书馆

我们首先要做的是打电话求助一些朋友:)

下面是我们完成工作所需的东西:

## 1.数据集

在我们的实验中,我使用了一个我非常熟悉的[数据集](https://www.kaggle.com/berkeleyearth/climate-change-earth-surface-temperature-data?select=GlobalLandTemperaturesByCountry.csv),它可以用于我们的目标。这是一个由各国收集的地表温度数据组成的时间序列。

这里有一个直接来自英国的例子:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/78b6745b32d614fda7560b16ec06e9c9.png)

英国时间序列。[图片由作者使用 Python 制作]

## 2.数据预处理

现在您已经下载了您的。csv 该看了,有**熊猫**。

通过查看第一行,我们有一些东西需要考虑:

A.**我们还没有“大陆”信息,**我们想称之为“目标”
B. **我们必须处理平均温度列上的一些 NaN 值**,这是我们将认为是时间序列的 y 轴的值

让我们一步一步地解决这些问题。
我们首先要用的是我们导入的一个魔法库,即 **pycountry_convert** 。

通过下面几行代码,我们能够从一个国家名称中获取“大陆”:

country_code = pc.country_name_to_country_alpha2(c, cn_name_format="default")
continent_name = pc.country_alpha2_to_continent_code(country_code)


但是,遗憾的是,这并不适用于整个数据集,我们可以从这些代码在我们的数据上的应用中看到:

很多国家不被 pycountry_convert 识别,所以我自己手动添加了大洲(稍后感谢;) ):

**我们可以看到,现在所有国家都有一个相关的洲,这就解决了一个点!**

一些国家来自南极洲,但它们形成了一个非常小的数量,在这个阶段,与添加到我们的数据集无关(顺便说一下,确定一个国家是否在南极洲是非常容易的,不是吗?).

所以我们最终需要将这些国家从我们的数据集中剔除。此外,我们还有那个问题要解决。我们就用神奇的 **pd.fill_na()** 函数来做!

代码如下:

**而且它解决了 B 问题!** 不幸的是,我们还没有完成。我们需要确保每个国家在时间序列中有相同数量的条目。在我们的数据集中,有些国家以 **1743** 为元年,有些国家以 **1948** 为元年。我们必须**将**数据集标准化到相同的**起始年**,以便拥有**相同数量的条目。**特别是,我们将使用**最近的年份**作为整个数据集的起始年份。

这是我们标准化之前的条目数:

这是**标准化代码和标准化数据集:**

**这是标准化后的条目数直方图:**

好了,让我们来看看我们的**类**:

让我们考虑三个人口最多的阶层:**欧洲,亚洲**和**非洲。**此外,让我们收集数据集的所有**标签**:

另外,让我们介绍一些我们将用来绘制数据的**函数**:

通过绘制我们三个国家的数据可以看出,**我们的任务一点也不轻松!**

**最后,让我们为机器学习模型准备数据集:**

## 3.机器学习模型

该模型是一个 1D 卷积神经网络。该结构非常容易理解,并且计算量小。此外,其细节由 Keras [在这里](https://keras.io/examples/timeseries/timeseries_classification_from_scratch/)提供。

**这里是模型:**

**及其摘要:**

**我们来训练模型:**

## 4.结果是:

已经获得了 79%的准确度;

以下是其他**指标**:

这里是**混淆矩阵:**

## 最终考虑:

虽然越来越大的模型通常是为了解决难以置信的复杂问题而构建的,但有时一个相当小的神经网络能够在有限的计算资源下获得可接受的结果。

如果你喜欢这篇文章,你想知道更多关于机器学习的知识,或者你只是想问我一些你可以问的问题:

A.在 [**Linkedin**](https://www.linkedin.com/in/pieropaialunga/) 上关注我,在那里我发布我所有的故事
B .订阅我的 [**简讯**](https://piero-paialunga.medium.com/subscribe) 。这会让你了解新的故事,并给你机会发短信给我,让我收到你所有的更正或疑问。
C .成为 [**推荐会员**](https://piero-paialunga.medium.com/membership) ,这样你就不会有任何“本月最大数量的故事”,你可以阅读我(以及成千上万其他机器学习和数据科学顶级作家)写的关于最新可用技术的任何内容。

# 带代码示例的 Git 实践工作流

> 原文:<https://towardsdatascience.com/hands-on-git-workflow-with-code-example-a89ec2b3110b?source=collection_archive---------21----------------------->

## 通过动手实践一步一步地完成 Git 工作流(代码示例)

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/30a85adfbb97c40888ac197dddea812f.png)

由[杰佛森·桑多斯](https://unsplash.com/@jefflssantos?utm_source=medium&utm_medium=referral)在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄的照片

继之前的[**Git 和 Github 初学者入门**](https://medium.com/swlh/an-intro-to-git-and-github-for-beginners-157c4374deff) 之后,今天我们将亲自动手。这个故事将通过实际的代码示例向您展示 Git 工作流程。由于 Github 是托管 Git 库的最受欢迎的网站,我们将用它作为例子。我们将使用 Git 的命令行界面,因此不考虑 Github CLI。

## 先决条件

1.  您必须在本地机器上安装 Git。你可以按照[官方文档](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)来做。
2.  有一个 [Github](https://github.com/) 账户(免费版就够了)。

# 从 Github 克隆存储库

有两种方法可以获得一个资源库,创建你自己的或者从 Github 或者类似的地方获得。我们将在这里着重从 Github 克隆一个。如果您对如何在自己的项目中启用 Git 并将其发布在 Github 上感兴趣,[这是一篇帮助您做到这一点的优秀文章](https://www.digitalocean.com/community/tutorials/how-to-push-an-existing-project-to-github)。

您首先需要转到您希望在终端中放置存储库的目录。假设我们想把它放在主目录的文档下。当你进入 Github 的一个资源库时,你可以在“`”标签下找到一个彩色的“代码”底部。在那下面,有三个选项,HTTPS、SSH 和 Github CLI。这是您可以克隆存储库的三种不同方式。`

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/6dae29cae6f0d08a5f6aced6ef9927e6.png)

语法是相同的,它们都是选项中的`git clone`+URL。

\(cd ~/Documents/# HTTPS \)git clone https://github.com//# SSH
$git clone git@github.com:/.git


区别在于您的本地机器如何访问远程存储库。如果您选择“HTTPS ”,当您与远程数据库交互(如拉、推、取等)时,如果它是一个私有存储库,系统会提示您键入用户凭据。另一方面,通过 SSH 访问可以省去很多麻烦,尤其是当存储库是私有的时候。但是您必须将本地机器的 SSH 密钥添加到您的 Github 帐户中。

将存储库克隆到本地机器上之后,您需要创建自己的分支来工作。

# 创建新分支

让我们首先通过运行`git status`来检查状态。

$git status

On branch master
Your branch is up to date with 'origin/master'.nothing to commit, working tree clean


现在我们可以从这个最新的主分支(主要是开发分支)中分支出来。要实现,我们需要`git branch`命令。

$git checkout -b "new_branch_name"

Switched to a new branch 'new_branch_name'


显然,您可以随意更改分支的名称。

现在,您已经建立了您的分支,您可以开始工作了,您想改变文件。

# 重设基础并提交

一旦你做好了一切准备提交你的作品,一定要记得调整基础。为了重新基于最新的主或者开发分支,我们需要首先获取最新的版本。

Commit your changes first

\(git add (this step is called staging, to add changes to the commit) \)git commit -a -m "Your commit message"# Switch to develop/master branch
\(git checkout develop>>Switched to branch 'master' Your branch is up to date with 'origin/master'.# Use 'fetch' to check (just check, we haven't pulled yet)if there are updates in remote \)git fetch# If nothing comes out, your develop is up to date. If there are updates, pull those updates to your local machine
$git pull


现在我们本地机器上的 develop/master 分支是最新的。然后,我们可以在这个分支上重新建立基础

$git checkout new_branch_name

Switch to branch 'new_branch_name'$git rebase -i develop


# 推至远程

回想一下,到目前为止,我们只在本地机器上创建了分支,在远程机器上没有这样的“new_branch_name”分支。如果您只是运行`git push`,您将得到以下消息的错误:

fatal: The current branch test has no upstream branch.
To push the current branch and set the remote as upstream, use git push --set-upstream origin new_branch_name


这个错误消息抱怨说,它找不到一个远程分支,将您的提交推送到这个分支。解决方案很简单,完全按照它建议你做的去做:

$git push --set-upstream origin new_branch_name


这一行将在 remote 上创建一个分支,并将当前分支(包括所有提交)推送到 remote。

# 创建拉式请求

最后要做的事情是创建一个拉请求。一般的做法是在 Github 上创建一个 pull 请求,这里的界面比使用 CLI 更容易创建 PR。您可以在团队中指定一个特定的人来审核您的 PR,将它作为一个 PR 草案,以便您可以继续处理它,并审核您在此 PR 中所做的所有更改。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/918cae91f250c8a3a0470d3717430d1b.png)![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/9f657ac98f1f9f0dd5a6fba06f04b845.png)

*我的 Git 系列故事:*

## [**Git 和 Github 初学者入门**](https://medium.com/swlh/an-intro-to-git-and-github-for-beginners-157c4374deff)

## [Rebase 和 Merge 的区别](https://hoooching.medium.com/the-differences-between-rebase-and-merge-30c91cd18f30)

## [我发现最有用的 5 个 Git 实践](https://hoooching.medium.com/5-git-practices-i-found-most-useful-af7410f390dd)

# 解决了!谷歌的文本到文本转换转换器(T5)瓶颈

> 原文:<https://towardsdatascience.com/hands-on-googles-text-to-text-transfer-transformer-t5-with-spark-nlp-6f7db75cecff?source=collection_archive---------5----------------------->

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/6b22a85243ff5549ae7d7ac0da9e1ad1.png)

作者图片

## 探索极限:

## 使用 Spark NLP

我用 Google 的 T5 探索 NLP 已经有一段时间了。所以我决定更进一步。在这篇文章中,我简要介绍了 Google 的 T5,解决了围绕其*繁重的资源需求*和的挑战,如何使用最先进的自然语言处理库 [**Spark NLP**](https://nlp.johnsnowlabs.com/) 来克服这一障碍。

那么让我们来看第一个问题:

# 这篇文章是给我的吗?

这篇文章是写给任何想构建一个简单、高性能和精确的 NLP 管道,并能在分布式环境中轻松扩展的研究人员、数据科学家或学生的。

现在,我试图让这篇文章对初学者友好,但是,我建议你参考 [Spark NLP 文档](https://nlp.johnsnowlabs.com/docs/en/quickstart)或滚动到这篇文章的末尾,阅读博士[维塞尔·科贾曼](https://medium.com/u/eab5d8ce9651?source=post_page-----6f7db75cecff--------------------------------)关于 Spark NLP 的介绍性文章,如果你不熟悉 Spark NLP 环境,否则,拉把椅子,拿些爆米花,享受阅读的乐趣。

# 简介:统一文本到文本转换转换器的兴起(T5)

让我们回到那个我们可以握手问候的时代。2019 年,谷歌的一组研究人员通过引入一个统一的框架,将所有基于文本的语言问题转换为**文本到文本**格式,探索了 NLP 的迁移学习技术的前景。该模型在 *GLUE* 、 *SQuAD* 和 *CNN/Daily Mail* 数据集上展示了最先进的性能;并且在强力胶语言基准测试中获得了令人印象深刻的 88.9 分——仅比人类基准的 89.8 分差一点点。

但是真正将 T5 与 BERT 风格的模型区分开来的区别在于,它不输出标签或输入句子的输入范围,而是输出文本字符串**。**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/8b4d6ff5cf496ccdf61e82636091b962.png)

Gif 作者[http://arxiv.org/abs/1910.10683](http://arxiv.org/abs/1910.10683)

这篇[论文](https://arxiv.org/pdf/1910.10683v3.pdf)背后的团队在过去十年中极其努力地评估和过滤各种 NLP 研究和论文,这些研究和论文基本上代表了相同的想法:**在大量未标记的文本上训练大型神经网络,然后针对非常具体的任务在标记的文本上对它们进行微调**。

他们的实验包括一些有趣的观察结果:

*   M *模型架构:*他们发现编码器-解码器模型通常优于“只有解码器”的语言模型
*   P *重新训练目标:*他们确认填空式去噪目标(训练模型以恢复输入中缺失的单词)效果最佳,并且最重要的因素是计算成本
*   u*n 标记的数据集:*他们表明对域内数据的训练可能是有益的,但对较小数据集的预训练可能会导致有害的过度拟合
*   T *培训策略:*他们发现,多任务学习可以与先训练后微调的方法相媲美,但需要仔细选择模型在每项任务上的训练频率
*   S *cale:* 他们比较了模型规模、训练时间和集合模型的数量,以确定如何充分利用固定的计算能力[2]

# 问题:这项研究的难点在哪里?

这就是事情变得有趣的地方。**这个研究有一个巨大的瓶颈**。从研究人员和学生的角度来看,他们想利用这个辉煌的模型的力量,它的大小是一个巨大的障碍。这个庞大的模型是像 BERT 这样的通用 NLP 模型的 30 多倍,这些早期的模型已经足够昂贵,可以在商用 GPU 硬件上使用!

# 解决方案:我们如何解决这个问题?

这就是 **Spark NLP** 介入的地方,它为*文本到文本转换转换器(T5)* 提供了广泛的功能,并能够快速有效地处理它,因为它从其基础 [**Apache Spark**](https://spark.apache.org/) 中借用了并行性、并发性和分布式计算。

由于 Spark NLP 使用 [**Tensorflow**](https://www.tensorflow.org/) 进行各种操作,它还利用了更强大的硬件提供的性能优势。相比之下,其他遗留库可能需要重写才能达到同样的效果。[5]

现在事不宜迟,让我们潜入 Spark NLP 的世界,征服 Google 的 T5。

# 实现:Google 的 T5 如何配合 Spark NLP 使用?

首先,Spark NLP 有各种型号的 T5,如[谷歌 T5(文本到文本转换转换器)底座](https://nlp.johnsnowlabs.com/2021/01/08/t5_base_en.html)和[谷歌 T5(文本到文本转换转换器)小型](https://nlp.johnsnowlabs.com/2021/01/08/t5_small_en.html)。

T5 模型在 18 个不同任务的几个数据集上进行训练,这些任务主要分为 8 类。

1.  文本摘要
2.  问题回答
3.  翻译
4.  情感分析
5.  自然语言推理
6.  共指消解
7.  句子完成
8.  词义消歧

## 每个 T5 任务都有解释

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/b2f6ad18637c2b72aaf791e932d39f03.png)

Google T5 的 NLP 任务

因此,让我们快速获取一个任务,并在 Spark NLP 中分解它的代码。

## 可乐——如果一个句子语法正确,就分类

可乐涉及到对一个给定的句子在语法和句法上是否可接受进行分类。语言可接受性语料库(CoLA)由 23 种语言学出版物中的 10657 个句子组成,由原作者对可接受性(语法性)进行了专业注释。

以下是您如何在 Spark NLP 中实现它:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/d73374839c56d050062de560a5ae7d96.png)

作者图片

迷茫?:P

别担心,我会支持你的,

## **让我们来分解一下:**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ca1aa1781bc524f9eebd264ab78b77ce.png)

➡In Spark NLP,*文件汇编员*是我们最好的朋友*。*它是一个关键的**转换器**,作为任何 Spark 数据帧的 Spark NLP 的初始入口点。

> (Psst…转换器是一种可以将一个数据帧转换为另一个数据帧的算法)

➡:然后,我们有一个*t5 变压器*,它从我们的*文件汇编器*获取输出`documents`,并将其通过我们预先训练好的 *T5。*就像我之前说的*,* Spark NLP 对于 T5 有各种型号,为了这个教程我选择了 *T5 小*。

➡我还使用了*任务*参数设置器`.setTask('cola sentence:')`来为 *T5* 指定我们的任务,在本例中是可乐。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/100839525429760333d1cb46a322fbb0.png)

➡现在,我们通过指定 Spark NLP *流水线*的组件,如*文档组装器*和 *T5* 来构建它。

> (Psst…管道只是按顺序执行的一系列步骤)

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/a4ef1c6854b323fe3404dbfd3ed64571.png)

➡:然后,我们定义我们的数据,用列`text`创建我们的 Spark 数据框架。这个`text`专栏将会反馈给我们的朋友*文档汇编者。*

> 人们可以查看 Spark NLP 参考资料,了解 Spark NLP 世界的更多信息。我已经在这篇文章的末尾链接了它们。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/f4af563472f74ec1b815da3bc9e8781f.png)

➡接下来,我们用 spark 数据帧`(df)`在流水线上`.fit()`。这是我们的变压器与 spark 数据框架的融合。

最后,我们得到以下输出!

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/cce7059c3d1f16ce72a51e6d1c4b83d5.png)

> 瞧啊。我们刚刚学习了如何使用谷歌的 T5 和 Spark NLP。

类似地,使用 Spark NLP 库,只需调整任务类型和输出列,就可以完成其他任务。

> 关于从导入库和启动 spark 会话到用 Spark NLP 实现所有 18 个可用的 Google T5 任务的完整代码,请参考这个[笔记本](https://github.com/JohnSnowLabs/spark-nlp-workshop/blob/master/tutorials/Certification_Trainings/Public/10.T5_Workshop_with_Spark_NLP.ipynb)。

# **参考文献**

*   [1] Raffel,c .,Shazeer,n .,Roberts,a .,Lee,k .,Narang,s .,Matena,m .,周,y .,Li,w .,& Liu,P. J. (2020)。[用统一的文本到文本转换器探索迁移学习的极限](http://arxiv.org/abs/1910.10683)。 *ArXiv:1910.10683 [Cs,Stat]* 。
*   [2] [用 T5 探索迁移学习:文本到文本的迁移转换器](https://ai.googleblog.com/2020/02/exploring-transfer-learning-with-t5.html)
*   [3] [Spark NLP 文档:Google T5(文本到文本转换转换器)库](https://nlp.johnsnowlabs.com/2021/01/08/t5_base_en.html)
*   [4] [Spark NLP Docs: Google T5(文本到文本转换转换器)Small](https://nlp.johnsnowlabs.com/2021/01/08/t5_small_en.html)
*   [5][Spark NLP 的优势](https://www.analyticsinsight.net/benefits-of-spark-nlp/)

我为那些希望开始使用 Spark NLP 并通过这个艺术图书馆探索自然语言处理的无限可能性的人提到了一些资源。

# **SparkNLP 资源**

*   [Spark NLP 文档和快速入门指南](https://nlp.johnsnowlabs.com/docs/en/quickstart)
*   [Spark NLP 简介:基础和基本组件](/introduction-to-spark-nlp-foundations-and-basic-components-part-i-c83b7629ed59)
*   [Spark NLP 简介:安装和入门](https://medium.com/spark-nlp/introduction-to-spark-nlp-installation-and-getting-started-part-ii-d009f7a177f3?source=your_stories_page---------------------------)
*   [Spark NLP 101:文档汇编器](https://medium.com/spark-nlp/spark-nlp-101-document-assembler-500018f5f6b5?source=your_stories_page---------------------------)
*   [Spark NLP 101:光管道](https://medium.com/spark-nlp/spark-nlp-101-lightpipeline-a544e93f20f1?source=your_stories_page---------------------------)
*   [使用 Bert 和通用语句编码器在 Spark NLP 中进行文本分类](/text-classification-in-spark-nlp-with-bert-and-universal-sentence-encoders-e644d618ca32)
*   [Spark NLP 中带 BERT 的命名实体识别(NER)](/named-entity-recognition-ner-with-bert-in-spark-nlp-874df20d1d77)

> 感谢您的阅读,祝您咖啡愉快!☕

# 实践如何对时间序列预测模型进行基准测试

> 原文:<https://towardsdatascience.com/hands-on-how-to-benchmark-your-timeseries-prediction-model-ce473a91fd0f?source=collection_archive---------39----------------------->

## 利用时间卷积网络(TCN)预测风速的个例研究

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/6c2045e4f7f0d076b8a4d13b830c7076.png)

乔纳森·博尔巴在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上的照片

确定你的模型性能有多好的标准是非常重要的。我们通常用于回归情况的标准之一是均方根绝对误差(MAE)。在本文的其余部分,我们将使用 MAE。

标准取决于我们建模的案例。**首先,标准取决于案例的可能值的范围**。我们不能一概而论,认为 MAE 的某个值是绝对好的,而不管我们建模的情况如何。例如,当我们想要预测每天的温度和降雨量时。它们的可能值的范围是不同的,即雅加达的日温度可以从 25 度变化到 36 度(注意:实际上我不知道,这只是为了举例),但是对于降雨量,在极端天气的情况下,它可以从 0 度变化到 100 度甚至 200 度。

如果您想在不考虑范围值的情况下轻松确定模型的性能,只需将值的范围重新调整到您想要的比例即可。通常,你只用这个公式

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/c868e90427ab9046390b3c2819decfbf.png)

其中,μ是数据集的平均值,σ是数据集的标准差。**这个公式假设我们的数据集是正态分布的**,因此 **MAE like 1 或以上是一个非常糟糕的分数**,不管范围值如何。您必须调整模型的超参数或使用数据集。

**第二,标准取决于你案件的可预见性**。不同的情况有不同的可预测性水平。像风速预测这样的现实世界案例(我们将在本文中演示的案例)往往具有较低的可预测性,因为现实世界是混乱的。可预测性是一个抽象的概念,我们无法得到可预测性水平的真实值。例如,在一种情况下,假设我们使用第一个公式重新调整数据集,MAE 为 0.2 是可以的,但在另一种情况下,这是一个糟糕的分数。为什么我们会得出这样的结论?用**与现有模型或方法**进行比较。**这就是我们所说的标杆管理**。而这正是我们讨论的重点。所有的数据集和代码都在下面。

<https://github.com/genomexyz/benchmark_timeseries>  

在我之前的文章[这里](/significant-wave-prediction-using-neural-network-7e5ee1b7f674)中,我已经演示了如何使用数据集的参数(平均值、中值、modus)对我们的模型进行基准测试。这一次,我们将尝试对时间序列模型进行基准测试。我们将尝试建模的是风速预测。事实上,当这篇文章写出来的时候,还没有现有的标准模型或方法(除了使用数值天气预报)来预测风速。因此,为了确定“现有模型或方法”的角色,让我们看一下我们的数据集。这些是大量的风速时间序列数据。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/574c54686a0a50fd3d4466bc2b273306.png)

Kecepatan angin 是风速,arah angin 是风向,waktu 是时间。风速单位为米/秒。图片由作者提供

如您所见,相邻时间段的风速值相似。因此,我们可以选择的“现有模式或方法”是

> 未来的风速与当前条件下的风速相同

例如,现在的风速是 5 米/秒,那么未来 30 分钟的风速(我们的数据集具有 30 分钟的时间分辨率)也是 5 米/秒。

我们将评估的模型是时间卷积网络(TCN)。因此,首先我们将重建数据集的维度形状,以将其提供给 TCN。我们将数据分为两组,即训练数据和测试数据,就像任何其他 ML 模型一样。这是代码。

从这段代码中,我们将得到这样一个 excel 文件。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/ea9b589dd4c98f46b62b5936ca308f23.png)

作者图片

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/a6f8e3b809e92f894f069c0007578c6c.png)

作者图片

这里我没有重新调整我的数据集,这里显示的是风预测的真实值。让我们计算所有的误差,误差平均值,并绘制出来

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/7796d9f0f762bca1634b450140f4f5d8.png)

误差平均值。作者图片

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/7d26c99dd1b062899ba75f59e34f6543.png)

无论是从误差平均值还是从图表来看,我们的模型性能看起来都不错。这样真的好吗?让我们运行我们的基准模型并进行比较。

将`benchmark_error_wind.xlsx`中的内容复制并粘贴到`wind.xlsx`中,以便我们进行比较。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/5d71ffbdde6264822274f06a10d96d9e.png)

作者图片

这里是误差平均值

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/87160e698ca6764c51830484dd00c27a.png)

作者图片

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/692ff707793b972ef04218727cff6047.png)

整个情节。作者图片

由此我们知道,我们只提高了基准模型的精度(缩小误差平均值)大约 **9.3%** ,也就是**不太好**。看起来我们需要再次调整 TCN 的超参数或者重新排列我们的数据集。

这就是如何测试你的模型。这次我们的讨论很短,因为讨论的内容实际上很简单,但在我看来这很重要,所以我把它放在一篇单独的文章里。下一篇文章再见。

# 手动马尔可夫链示例,使用 Python

> 原文:<https://towardsdatascience.com/hands-on-markov-chains-example-using-python-8138bf2bd971?source=collection_archive---------1----------------------->

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/969978aae4410eacbf86666326f1fddd.png)

马库斯·斯皮斯克在 [Unsplash](https://unsplash.com/s/photos/chain?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 上的照片

## 一次解开一行代码中的马尔可夫链。

刚开始学物理的时候,我不喜欢**概率**这个概念。这个想法让我很兴奋,用物理可以模拟整个世界,不确定性的想法让我很愤怒:)

事实是,当我们想要研究真实的现象时,我们迟早必须处理一定程度的不确定性。处理它的唯一方法是获得一个精确的概率估计,这个概率决定了我们的过程。

马尔可夫链是一个很好的方法。马尔可夫链背后的思想非常简单:

> 未来会发生的一切只取决于现在正在发生的事情

用数学术语来说,我们说有一个随机变量序列 X_0,X_1,…,X_n 可以取某个集合 a 中的值。然后我们说,如果一个事件的序列是一个马尔可夫链,我们有:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/cc0a8d290864649055619aadfc3f0d5e.png)

我使用[乳胶](https://latex2png.com/)生成的图像

这听起来可能很复杂,但它只不过是上面表达的概念。

另一个假设是,该方程对每一步都有效(不仅仅是最后一步),并且概率总是相同的(即使形式上,这只对**齐次马尔可夫链**成立)。

现在,可能状态 A 的集合通常表示为样本空间 S,你可以用所谓的**转移概率来描述从 S 中的状态 x 到 S 中的状态 y 的概率。**

但是我向您保证,这将是一篇“动手”文章,所以让我们开始将这些概念形象化吧!

公平地说,Python 并不是执行数值模拟的最佳环境。专业研究人员使用更复杂的语言,在某种程度上也更可靠,比如 C 语言或 Fortran 语言。

尽管如此,这个博客的目标是介绍一些非常简单的概念,使用 Python 可以使这个学习过程更容易。

所以让我们开始吧:这是你需要的:

所以就是一堆主流库像 **pandas** , **matplotlib,seaborn,numpy。**

让我们从最简单的场景开始:

## 1.随机漫步

简单随机漫步是随机漫步的一个极其简单的例子。

第一个状态是 0,然后你以概率 0.5 从 0 跳到 1,以概率 0.5 从 0 跳到-1。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/af9cac5e29989baa817b79f2fb28823b.png)

我用 Power Point 制作的图像

然后你对 x_1,x_2,…,x_n 做同样的事情。

你认为 S_n 是 n 时刻的状态。

有可能证明(其实很容易)在 t+1 时刻处于某个状态的概率,即一个整数 x,只取决于 t 时刻的状态,简而言之,**就是一个马尔可夫链。**

这是如何产生它的:

结果是:

现在随机漫步的想法是模拟如果我们决定从一个点开始,通过投掷一枚完美的硬币随机选择向上或向下会发生什么。

这个过程非常简单,但就其理论应用和性质而言,却非常有趣。

这个过程的第一个合理的扩展是考虑一个随机行走,但是使用一个不完美的硬币。意思是上升的概率和下降的概率不一样。这被称为**有偏见的随机漫步。**

让我们考虑以下几个概率:

[0.1,0.9] , [0.2,0.8], [0.4,0.6], [0.6,0.4], [0.8,0.2],[0.9,0.1]


所以我们有 6 种可能的随机漫步。请注意,概率必须为 1,因此考虑“向上”或“向下”的概率就足够了。

以下是您的操作方法:

这就是我们想象它时发生的事情。

## 2.赌徒的破产链

扩展随机漫步的另一个简单方法是赌徒的破产链。
从概念上讲,它非常类似于随机漫步:你从一个状态 x 出发,你可以以概率 p 到达一个状态 y=x+1,或者以概率 1-p 到达一个状态 y=x-1

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/14eb9a92fba4ace1965c93b206e6dd26.png)

我用 Power Point 制作的图像

有趣的是,当你到达 1 或 N 时,你基本上被卡住了。除了永远保持那种状态,你什么也做不了。

这个函数,给定:

*   a **起点**(例如 3)
*   **第一个可能值**(例如 0)
*   以及**最后一个可能值**(例如 5)
*   **步数**(如 10000)

给你最后的状态:

现在,在尝试这个功能之前,让我们考虑一个更有趣的情况。

> 假设我们从状态 3 开始。两步后进入状态 5 的概率是多少?

这是从状态 3 到状态 4,然后从状态 4 到状态 5 的概率:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/50d3832b98efc3bc586cdc289e571e1e.png)

我用[乳胶](https://latex2png.com/)制作的图像

**在我们的例子中,它只是 0.25。**

如果现在我们问这个等式:

> 假设我们从状态 3 开始。两步后结束于状态 1 的概率是多少?

同样,它是从状态 3 到状态 2,然后从状态 2 到状态 1 的概率:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/4745d12d025dc605ed370c7a41ce9e0b.png)

我用[乳胶](https://latex2png.com/)制作的图像

**同样,在我们的例子中,它只是 0.25。**

唯一的另一种选择是在两步之后从状态 3 进入状态 3。我们可以用一种非常简单的方法来计算这个概率。由于总概率必须为 1,因此:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/5f1d3b4cd0c988548ed146fbf3e560b4.png)

我用[乳胶](https://latex2png.com/)制作的图像

如果 p=0.5,它也是 0.5

同样,概率的概念是,如果我们重复一个实验无限次,我们应该能够验证概率值所暗示的事件。

## 3.自定义马尔可夫链

前面的模型是众所周知的,并被用作马尔可夫链的介绍性例子。让我们发挥创意,建造一个全新的非现有模型,就像下图中的**一样。**

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/3f05ec4a6291e3c26818348617f78798.png)

我用 Power Point 制作的图像

我画画很糟糕,但模型本身很简单。

当你看到两个节点(比如 A 和 B)之间有一个箭头时,这意味着你可以从节点 A 开始到节点 B,这个箭头用黑色表示。

*例如,从状态 A 到状态 B 的概率为 0.5*

一个重要的概念是,模型可以用转移矩阵来概括,这解释了你的马尔可夫链中可能发生的一切。这是我们模型的**转换矩阵**:

如果你仔细观察这个模型,你会发现一些非常特别的东西。假设你从状态 2 跳到状态 3。你能回到状态 2 吗?答案是否定的。

这同样适用于状态 3 和状态 1。状态 1、3 和 2 因此被定义为**瞬态。**

另一方面,如果你从状态 4 开始,总有可能在某个时候,你会回到状态 4。这同样适用于状态 5。这些状态被称为**循环状态。**

让我们做些实验,以便能正确理解这个概念。

直观上,我们可以看到,从状态 2 开始不回到状态 2 的概率,随着步数趋于无穷大而趋于 0。

事实上,从状态 2 开始,经过 N 步后,我们发现自己处于状态 2 的概率如下:

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/c16f9ee309be507b3e2e055158b864c6.png)

我用[乳胶](https://latex2png.com/)制作的图像

事实上,如果我们从状态 2 到状态 3,我们不可能回到状态 2。让我们将这个理论函数定义为 t(N ),并绘制成图:

现在,让我们使用马尔可夫链,看看我们是否验证了同样的结果。

我们从状态 2 开始,并在 N 步后验证处于状态 2 的概率。**概率,在这种情况下,就是最终状态的 2 的个数和出现次数的比值。**为了保持一致,出现的次数需要趋于无穷大。让我们考虑 1000 次测试。

这是我们将要使用的函数:

让我们对不同的 N 使用这个函数,称之为 p(N):

可以看到,我们使用了**转移矩阵**来进行模拟。我们可以使用转移矩阵来评估我们正在考虑的马尔可夫链的所有属性。

## 4.结论

在这本笔记本中,我们已经看到了非常著名的模型,如**随机漫步**和**赌徒的毁灭链**。然后,我们创建了我们自己的全新模型,并对其进行了一点小小的改动,发现了一些重要的概念,如**转换矩阵、循环状态和瞬态。最重要的是,我们已经看到了如何使用 Python 和众所周知的库以非常简单的方式验证这些概念。**

如果你喜欢这篇文章,你想知道更多关于机器学习的知识,或者你只是想问我一些你可以问的问题:

A.在 [**Linkedin**](https://www.linkedin.com/in/pieropaialunga/) 上关注我,我在那里发布我所有的故事
B .订阅我的 [**简讯**](https://piero-paialunga.medium.com/subscribe) 。这会让你了解新的故事,并给你机会发短信给我,让我收到你所有的更正或疑问。
C .成为 [**推荐会员**](https://piero-paialunga.medium.com/membership) ,这样你就不会有任何“本月最大数量的故事”,你可以阅读我(以及成千上万其他机器学习和数据科学顶级作家)写的任何关于现有最新技术的文章。

再见:)

# 实践:优化和基准身体姿势估计模型

> 原文:<https://towardsdatascience.com/hands-on-optimizing-nvidia-body-pose-net-model-e27da4a9f8ec?source=collection_archive---------24----------------------->

## Nvidia Body Pose Net 与 OpenPifPaf 模型

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/413edb9e3b75fe7e7677e83898224160.png)

来自 [Pexels](https://www.pexels.com/photo/photo-of-code-projected-over-woman-3861969/?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels) 的 [ThisIsEngineering](https://www.pexels.com/@thisisengineering?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels) 摄影

伊西多拉·斯坦科维奇,内韦娜·米勒托维奇,戈兰·贝纳克**,**德贝马尔亚·比斯瓦斯— [瑞士达尔文边缘](https://darwinedge.com/)

**摘要** *。Nvidia 最近宣布推出* [*2D 身体姿势估计模型*](https://developer.nvidia.com/blog/training-optimizing-2d-pose-estimation-model-with-tao-toolkit-part-1/) *作为迁移学习工具包 3.0 的一部分。在本文中,我们提供了一个详细的教程来训练和优化模型。我们进一步提供了另一个广泛用于感知任务的开源模型的基准测试结果:*[*OpenPifPaf*](https://github.com/openpifpaf/openpifpaf)*——允许您决定何时使用哪个模型。*

在之前的一篇文章[4]中,我们通过将身体姿势模型应用于现实生活中的医疗保健应用程序,展示了它的实际效用。该应用程序在病人家中监控病人,并在有人从床上摔下来、发生事故等情况时发出警报。这对于医院和养老院的居民来说是个大问题。

![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2021/-/raw/master/docs/img/6071ba4996d727d0c1bbd7eea216331e.png)

实践中的身体姿态检测(图片由作者提供)

# 训练身体姿态网络模型

在本节中,我们将介绍训练和优化 Nvidia 身体姿势网络模型所需的所有步骤。该模型使用 TAO Toolkit 进行训练,TAO Toolkit 使用预训练的模型和自定义数据集来构建新的 AI 模型[1]。

第一步是安装和运行 TAO 工具包。遵循此链接中的步骤:

[陶工具包快速入门指南—陶工具包 3.0 文档](https://docs.nvidia.com/tao/tao-toolkit/text/tao_toolkit_quick_start_guide.html)

登录到 NGC docker 注册表后,运行以下命令:

mkdir Programs
cd Programs/
wget -O ngccli_linux.zip https://ngc.nvidia.com/downloads/ngccli_linux.zip && unzip -o ngccli_linux.zip && chmod u+x ngc
mkdir ngccli_linux
cd ngccli_linux/
chmod u+x ngc
echo "export PATH="$PATH:$(pwd)"" >> ~/.bash_profile && source ~/.bash_profile
cd ..
ngc config set
ngc registry model list


我们使用 conda 虚拟环境(按照[链接](https://docs.anaconda.com/anaconda/install/linux/)中的步骤安装 Anaconda)。要创建并激活虚拟环境,请运行以下两个命令:

conda create -n 'env_name' python=3.7
conda activate 'env_name'


该工具包现在可以使用了,培训准备工作可以继续进行。在[这一页](https://developer.nvidia.com/blog/training-optimizing-2d-pose-estimation-model-with-tao-toolkit-part-1/)中,解释了强制步骤。第一步是环境设置,其中下载了最新的示例(用于设置培训的配置文件),设置了 env 变量并创建了挂载文件。最后,安装所需的依赖项。下一步是下载预先训练好的模型。

> 用来训练这个模型的数据集是 COCO 数据集,它是从[这个链接](https://cocodataset.org/#download)下载的。

应该是这样组织的:

├──tlt-experiments ├──bpnet ├──data ├──annotations ├──test2017 ├──train2017 └──val2017 ```

数据集需要为训练做准备,因此分段掩码与 tfrecords 一起生成。配置文件和所用命令的详细解释可在这里找到。

下一步是为训练配置 spec 文件,它包含六个组件:训练器、数据加载器、增强、标签处理器、模型和优化器。我们使用默认的规范文件,即/workspace/examples/BP net/specs/BP net _ train _ m1 _ coco . YAML。

现在可以开始训练了。

我们在 Nvidia GeForce RTX 2080 GPU 上的培训过程持续了 104 个小时。

用于评估模型的度量是精确度和召回率。这些值按以下方式计算:

其中 TP 是真阳性的数量,FP 是假阳性的数量,FN 是假阴性的数量。针对交集/并集(IoU)的不同阈值计算精度和召回率。IoU 是基于预测边界框和地面真实边界框之间的重叠计算的参数。

例如,如果 IoU 阈值为 0.5,并且用于预测的 IoU 值为 0.7,则该预测被分类为真阳性。反之,如果 IoU 为 0.3,则归类为假阳性。假阴性是未能预测图像中的对象的预测。

在评估结果中,IoU 阈值为 0.5:0.95。这意味着精度和召回率是通过对 0.5 和 0.95 之间的不同阈值以特定步长平均精度和召回率来计算的。

我们在验证集上得到的准确率和召回率是:

最佳化

使用 TAO Toolkit 对模型进行的优化在此处解释。优化模型的一种方法是修剪。它消除了低量级的权重,从而产生压缩模型,占用较少的内存资源2。

修剪后的准确率和召回率不明显降低,因此使用修剪模型是合理的。

修剪后,建议重新训练模型,因为修剪会导致精度下降。在同一个 GPU 和数据集上的再训练持续了 99 个小时。重新训练模型的评估结果是:

OpenPifPaf 基准测试

OpenPifPaf [3]是一种通用的神经网络架构,它使用复合场来实时检测和构建时空姿态。我们使用自然人体运动的几何学来计算和检测预先确定的感兴趣区域中的身体位置,以检测一个人是否站着、坐着、躺着、摔倒等。

OpenPifPaf 和 Body Pose Net 模型都是自底向上的实现,这意味着它们检测图像中的所有关节,然后将属于不同人的部分关联起来。另一方面,自上而下的方法首先检测人,然后对每个人执行单人姿势估计以预测人体关节[5]。

自下而上的方法更适合有人群的图像,以及复杂的姿势和人们互相遮挡的情况。

OpenPifPaf 模型也在 COCO 数据集上进行了训练。评估是在与身体姿态网络模型相同的验证集上进行的。以下是我们在相同输入量下得到的结果:

用于训练 OpenPifPaf 模型的参数与用于身体姿势网络的参数略有不同。学习率是 0.001,而在身体姿势网络模型中,基本学习率是 2e-5,最小学习率是 8e-8。动量为 0.95,而 BP 网络使用 0.9。最后,批量大小是 8,而不是 BP 网络中的 10。

事实证明,OpenPifPaf 模型为每个 IoU 阈值提供了更好的结果。IoU=0.5:0.95 的平均精度是 0.621,而身体姿势网络模型中的相同度量是 0.487。

结果

为了模型的视觉比较,我们使用了新的数据集— Halpe 全身人体关键点 数据集。

此处描述的两个模型从未见过该数据集。选择某个子集来可视化这些模型提供的预测结果。

Nvidia Body Pose Net 与 OpenPifPaf 的基准测试

参考

1 概述— TAO 工具包 3.0 文档

2开尔文。通过修剪进行模型压缩。https://towards data science . com/model-compression-via-pruning-ac9b 730 a 7 c 7 b

[3]克里斯、贝尔托尼和阿拉希:OpenPif-Paf: 语义关键点检测和时空关联的复合字段。arXiv,abs/2103.02440,2021。

[4] M. Vuletic 等人。艾尔。面向医疗保健应用的 Edge AI 框架。2021 年 8 月,关于人工智能用于老龄化、康复和智能辅助生活的第四届 IJCAI 研讨会( ARIAL )。https://medium . com/Darwin-edge-ai/edge-ai-framework-for-rapid-prototyping-and-deployment-cabf 466 DD def

[5] 深度学习的人体姿态估计概述——beyond minds

动手操作 PostgreSQL:基本查询

原文:https://towardsdatascience.com/hands-on-postgresql-basic-queries-a5f1249bba78?source=collection_archive---------17-----------------------

世界上最先进的开源关系数据库

南安在 Unsplash 上的照片

SQL 提供了许多函数和方法来管理以表格形式存储的数据。关系数据库管理系统(RDBMS)是一个使用 SQL 来管理存储在关系数据库中的数据的程序。

关系数据库包含许多通过共享列相互关联的表。有许多不同的 RDBMSs,如 MySQL、PostgreSQL、SQL Server 等等。

我之前写了一篇文章作为对 PostgreSQL 的介绍,解释了如何设置 PostgreSQL 数据库和创建表。在本文中,我们将讨论几个演示如何查询关系数据库的例子。

第一步是创建一个我们可以查询的表。一种选择是创建表,并使用 insert 语句手动填充它。更实用的方法是从 csv 文件中复制数据。

我有一个 csv 文件,其中包含了 Kaggle 上提供的墨尔本住房数据集的一些列。我们需要在从文件上传数据之前创建表。

CREATE TABLE houses (                                                                      HouseId SERIAL,                                                                                     Type VARCHAR(20),                                                                                   Date date,                                                                                          Rooms INT,                                                                                          Distance real,                                                                                      Landsize real,                                                                                      Price real,                                                                                         PRIMARY KEY (HouseId)                                                                               );

表格中的列必须与 csv 文件中的列兼容。第一个字表示列名,第二个字表示数据类型。

我们现在可以将 csv 文件中的数据复制到 houses 表中。

\COPY houses(HouseId, Type, Date, Rooms, Distance, Landsize, Price)                        FROM '/Users/sonery/Downloads/melb_sql/houses.csv'                                                  DELIMITER ','                                                                                       CSV HEADER;

第一行包括表名和列名。然后,我们写入将用于复制数据的文件的路径。最后两行是关于 csv 文件的特征。

我们现在可以开始查询 houses 表。让我们首先检查表中有多少观察值(即行)。

SELECT COUNT(1) FROM houses;count
-------
13580(1 row)

我们使用 count 函数来计算行数。因为每一列都包含相同数量的行,所以我们可以将任何一列传递给 count 函数。

我们可以通过显示前 5 行来看看这个表。

SELECT * FROM houses LIMIT 5;

(图片由作者提供)

SQL 也可以被认为是一种数据分析工具。它提供了多种过滤、分析和转换数据的功能和方法。

例如,我们可以查看价格超过 100 万英镑的房屋数量。我们只需要使用 where 语句添加一个条件。

SELECT COUNT(1) FROM houses
WHERE price > 1000000;count
-------
5743(1 row)

where 语句接受多个条件。我们来求 h 型,距离大于 2 的房子的最高价。

SELECT MAX(price) FROM houses                                                              WHERE distance > 2 AND type = 'h';max
-------
9000000(1 row)

我们在价格列上使用 max 函数。过滤条件与“and”关键字相结合。

SQL 函数提供了极大的灵活性和多功能性。考虑前面的例子。结果集中的聚合列显示了函数名,但实际上并没有告诉我们它代表什么。

“as”关键字可用于为聚合列分配别名。我们也可以用 1000000 除以百万来表示价格。

SELECT MAX(price / 1000000) AS price_million FROM houses                                   WHERE distance > 2 AND type = 'h';price_million
---------------
9(1 row)

数据分析中常用的函数是 group by。它根据列中的不同值对行进行分组,然后允许对数值执行聚合。

例如,我们可以计算每种房屋类型的平均价格。

SELECT type, AVG(price) AS avg_price FROM houses                                           GROUP BY type;type |     avg_price
-----+-------------------
t    | 933735.0538599641
h    | 1242664.761138745
u    | 605127.4845873384(3 rows)

该查询的作用是选择 type 和 price 列,然后根据 type 列中的类别对行进行分组。avg 函数计算每个类别的平均房价。

我们还可以使用 order by 语句对结果集中的值进行排序。我们来看看最近公布的 5 栋房子的身份证号码。为了使情况稍微复杂一点,我们还将在距离列上添加一个条件进行过滤。

SELECT houseid, date FROM houses
WHERE distance BETWEEN 2 AND 3
ORDER BY date desc
LIMIT 5;houseid |    date
--------+------------
  10879 | 2017-12-08
  10880 | 2017-12-08
  10877 | 2017-12-08
  10878 | 2017-12-08
  10973 | 2017-12-08(5 rows)

我们首先实现过滤条件,然后对结果进行排序。默认情况下,order by 语句按升序对结果进行排序。我们可以用 desc 关键字改变它的行为。

结论

我们已经做了几个例子来演示如何编写基本查询来从表中检索数据。全面理解基本 SQL 语句至关重要。高级查询是在基本查询的基础上创建的。

我计划通过逐渐增加复杂性来写更多关于 PostgreSQL 的文章。敬请关注更多内容!

感谢您的阅读。如果您有任何反馈,请告诉我。

实践强化学习课程:第 1 部分

原文:https://towardsdatascience.com/hands-on-reinforcement-learning-course-part-1-269b50e39d08?source=collection_archive---------3-----------------------

实践教程

从零到英雄,一步一个脚印。

凯(图片作者提供)

欢迎来到我的强化学习课程!❤️

让我们一步一步地走在这条从基础到前沿强化学习(RL)的美丽道路上,一起用 Python 编写代码示例和教程吧!

这第一部分涵盖了开始这一旅程所需的最基本的概念和理论。然后,在接下来的每一章中,我们将解决一个不同的问题,难度越来越大。

最终,最复杂的 RL 问题涉及强化学习算法、优化和深度学习的混合。

您不需要了解深度学习(DL)来学习本课程。我会给你足够的背景,让你熟悉 DL 哲学,并理解它如何成为现代强化学习的一个重要组成部分。

第一部分

在第一课中,我们将通过例子、数学和一点 Python 知识来讲述强化学习的基础。

内容

  1. 什么是强化学习问题?🤔
  2. 政策👮🏽和值函数。
  3. 如何生成训练数据?📊
  4. Python 样板代码。🐍
  5. 重述✨
  6. 家庭作业📚
  7. 下一步是什么?❤️

开始吧!

1.什么是强化学习问题?🤔

强化学习(RL)是机器学习(ML)中与学习问题相关的一个领域,其中

一个智能代理 🤖需要学习,通过试错,如何采取 行动 内心和 环境 🌎为了最大限度地获得的累计奖励。

强化学习是最接近人类和动物学习方式的一种机器学习。

什么是代理?还有一个环境?代理可以采取的具体行动是什么?奖励呢?为什么说累积奖励?

如果你问自己这些问题,你就在正确的轨道上。

我刚刚给出的定义引入了一堆你可能不熟悉的术语。其实他们是故意暧昧的。这种普遍性使得 RL 适用于广泛的看似不同的学习问题。这是数学建模背后的哲学,它停留在 RL 的根源。

让我们来看看几个学习问题,并通过强化学习的视角来看待它们🔍。

例子 1:学习走路🚶🏽‍♀️🚶🏿🚶‍♀️

作为一个刚刚开始走路的孩子的父亲,我不禁问自己,他是怎么学会的?**

凯和保罗(图片由作者提供)

作为一名机器学习工程师,我幻想着用软件和硬件来理解和复制那条不可思议的学习曲线。

让我们尝试使用 RL 成分来模拟这个学习问题:

  • 经纪人是我的儿子凯。他想站起来走路。他的肌肉在这个时候足够强壮,有机会尝试。对他来说,学习的问题是:如何顺序调整他的身体位置,包括他的腿、腰、背和手臂上的几个角度,以平衡他的身体,不摔倒。
  • 环境是他周围的物理世界,包括物理定律。其中最重要的是重力。如果没有重力,学会走路的问题将会彻底改变,甚至变得无关紧要:为什么你想要在一个你可以简单地飞翔的世界里行走?这个学习问题中的另一个重要定律是牛顿第三定律,用简单的话来说就是,如果你摔倒在地板上,地板将以同样的力度回击你。哎哟!
  • 动作是这些身体角度的所有更新,当他开始追逐周围的东西时,这些角度决定了他的身体位置和速度。当然,他可以同时做其他事情,比如模仿奶牛的声音,但这些可能不会帮助他实现他的目标。我们在我们的框架中忽略了这些动作。添加不必要的动作不会改变建模步骤,但是会使问题以后更难解决。
  • 他收到的奖励是来自大脑的刺激,让他快乐或感到痛苦。当他摔倒在地板上时,会有负面的回报,那就是身体上的疼痛,随后可能会感到沮丧。另一方面,有几件事对他的快乐有积极的影响,比如更快到达目的地的快乐👶🚀或者是当我和我的妻子贾戈达说“干得好”时的外部刺激。或 Bravo!“对每一次尝试和边际改善他都表现出来。

一个重要的(也是显而易见的)备注是,Kai 不需要学习牛顿的物理学来站立和行走。他将通过观察环境的状态来学习,采取行动,并从这个环境中收集奖励。他不需要学习环境的模型来实现他的目标。

关于奖励的更多信息💰

奖励对凯来说是一个信号,他一直在做的事情对他的学习是好是坏。随着他采取新的行动,经历痛苦或快乐,他开始调整自己的行为,收集更多积极的反馈,减少消极的反馈。换句话说,他学会了

有些动作在开始时对宝宝来说可能看起来很有吸引力,比如试着奔跑来获得刺激。然而,他很快了解到,在一些(或大多数)情况下,他最终摔倒在地,并经历了一段时间的痛苦和眼泪。这就是为什么聪明的代理人最大化累积报酬,而不是边际报酬。他们用长期回报换取短期回报。一个能立即得到回报,但却让我的身体处于即将倒下的位置的行动,并不是一个最佳的行动。

巨大的快乐伴随着更大的痛苦并不是长期幸福的秘诀。这是婴儿通常比我们成年人更容易学会的东西。

奖励的频率和强度是帮助代理学习的关键。很少(稀疏)的反馈意味着更难学习。想想看,如果你不知道你做的是好是坏,你怎么能学习呢?这是为什么有些 RL 问题比其他问题难的主要原因之一。

对于许多现实世界的 RL 问题来说,奖励塑造是一个艰难的建模决策。

示例 2:学习像职业玩家一样玩大富翁游戏🎩🏨💰

小时候,我花了很多时间和朋友、亲戚玩大富翁。谁没有呢?这是一个令人兴奋的游戏,结合了运气(你掷骰子)和策略。

大富翁是一款两人至八人的房地产棋盘游戏。你掷两个骰子在棋盘上走来走去,购买和交易房产,开发房子和酒店。你从你的对手那里收取租金,目的是让他们破产。

图片来自 Pexels

如果你对这个游戏如此着迷,以至于你想找到玩这个游戏的聪明方法,你可以使用一些强化学习。

4 RL 成分是什么?

  • 经纪人是你,一个想在大富翁游戏中获胜的人。
  • 你的动作就是你在下面这张截图上看到的动作:

垄断中的行动空间。 阿勒夫·阿塞法

  • 环境是游戏的当前状态,包括每个玩家拥有的财产、位置和现金数量的列表。还有对手的策略,这是你无法预测的,也是你无法控制的。
  • 奖励是 0,除了你最后一步棋,如果你赢了游戏就是+1,如果你破产就是-1。这种奖励方式有道理,但却让问题难以解决。我们上面说过,更稀疏的奖励意味着更难的解决方案。正因为如此,才有了 其他方式 来塑造奖励,让它们更吵但不那么稀疏。

当你和另一个人玩“大富翁”时,你不知道她或他会怎么玩。你能做的就是和自己玩。当你学着玩得更好时,你的对手也一样(因为是你),迫使你提高游戏水平以保持胜利。你可以看到正反馈循环。

这一招叫自玩。它为我们提供了一条无需使用专家玩家的外部建议就能引导智能的途径。

自玩是 AlphaGoAlphaGo Zero 的主要区别,这两个由 DeepMind 开发的模型比任何人类都玩围棋。

示例 3:学习驾驶🚗

几十年后(也许更短),机器将驱动我们的汽车、卡车和公共汽车。

照片由 张瑞阳 发自 Pexels

但是,如何?**

学开车不容易。司机的目标很明确:从 A 点到 B 点,让她和车上的乘客都感到舒适。

对驾驶员来说,有许多外部因素使驾驶变得具有挑战性,包括:

  • 其他驾驶员行为
  • 交通标志
  • 行人行为
  • 路面状况
  • 天气状况。
  • …甚至燃料优化(谁愿意在这上面多花钱?)

我们如何用强化学习来解决这个问题?

  • 代理人是想舒适地从 A 地到达 B 地的司机。
  • 驾驶员观察到的环境的状态有很多东西,包括汽车的位置、速度和加速度、所有其他汽车、乘客、路况或交通标志。可以想象,将如此巨大的输入向量转化为适当的行动是多么具有挑战性。
  • 动作基本就是三个:方向盘方向、油门力度、刹车力度。
  • 每次行动后的奖励是驾驶时你需要平衡的不同方面的加权总和。到 B 点的距离减少会带来积极的回报,而增加则会带来消极的回报。为了确保不发生碰撞,与另一辆车,甚至行人靠得太近(甚至碰撞)应该有非常大的负面奖励。此外,为了鼓励平稳驾驶,速度或方向的急剧变化会导致负面奖励。

在这 3 个例子之后,我希望 RL 元素的以下表示以及它们如何一起发挥作用是有意义的:

强化学习成分(图片由作者提供)

既然我们知道了如何用公式表示一个 RL 问题,我们需要解决它。

怎么会?

继续读下去!

2.政策和价值函数

政策

代理根据环境的当前状态选择她认为最好的操作。

这就是代理人的策略,通常被称为代理人的政策

一个 策略 是一个从状态到动作的学习映射。

解决强化学习问题意味着找到最佳策略。

策略或者是确定性的,当它们将每个状态映射到一个动作时,

或者当他们将每个状态映射到所有可能行为的概率分布时,称为随机

**随机是你在机器学习中经常读到和听到的一个词,本质上是指不确定随机。在具有高度不确定性的环境中,比如你正在掷骰子的垄断,随机政策比确定性政策更好。

存在几种方法来实际计算这个最优策略。这些被称为策略优化方法

价值函数

有时,根据问题的不同,可以尝试找到与最优策略相关的值函数,而不是直接尝试找到最优策略。

但是,什么是价值函数

在那之前,

在这个上下文中,价值是什么意思?

是与环境的每个状态相关联的数字,用于估计代理处于状态有多好。**

从状态开始,根据策略【π】选择动作时,代理收集的累计奖励。****

价值函数是从状态到价值的学习映射。

政策的价值函数通常表示为

值函数也可以将(动作、状态)对映射到值。在这种情况下,它们被称为 q 值函数。

最优值函数(或 q 值函数)满足一个数学方程,称为贝尔曼方程

这个方程是有用的,因为它可以被转换成一个迭代过程来寻找最佳值函数。

但是,为什么价值函数有用?
因为你可以从一个最优 q 值函数中推断出一个最优策略。

如何?
最优策略是在每个状态 s 时,代理选择使 q 值函数最大化的动作 a 的策略。

所以,你可以从最优策略跳到最优 q 函数,反之亦然😎。

有几种 RL 算法专注于寻找最佳 q 值函数。这些被称为Q-学习方法

强化学习算法的动物学🐘🐅🦒

有许多不同的 RL 算法。一些人试图直接找到最优策略,另一些人试图找到 q 值函数,还有一些人试图同时找到两者。

RL 算法的动物学是多样的,有点吓人。

谈到 RL 算法,没有“一刀切”的。每次你解决一个 RL 问题时,你都需要尝试其中的一些方法,看看哪种方法适合你的情况。

在学习本课程的过程中,您将实现其中的几种算法,并深入了解在每种情况下什么效果最好。

3.如何生成训练数据?📊

强化学习代理非常需要数据。

karst en wine geart 拍摄的照片

为了解决 RL 问题,你需要大量的数据。

克服这一障碍的方法是使用模拟环境。编写模拟环境的引擎通常比解决 RL 问题需要更多的工作。此外,不同引擎实现之间的变化会使算法之间的比较变得毫无意义。

这就是为什么 OpenAI 的家伙们在 2016 年发布了 健身房工具包 。OpenAIs 的 gym 为不同问题的环境集合提供了一个标准化的 API,包括

  • 经典的雅达利游戏,
  • 机械臂
  • 或者登月(嗯,一个简化的)

也有专有环境,像 MuJoCo ( 最近被 DeepMind 收购)。MuJoCo 是一个你可以在 3D 中解决连续控制任务的环境,比如学习走路👶。

OpenAI Gym 还定义了一个标准的 API 来构建环境,允许第三方(比如您)创建您的环境并让其他人可以使用。

如果你对自动驾驶汽车感兴趣,那么你应该看看卡拉,这是最受欢迎的开放式城市驾驶模拟器。

4.Python 样板代码🐍

你可能会想:

到目前为止,我们讨论的内容很有趣,但是我如何用 Python 来写这些内容呢?

我完全同意你的观点😊

让我们看看这一切在 Python 中是怎样的。

有没有发现这段代码有什么不清楚的地方?

23 号线呢?这个ε是什么?

不要惊慌。我以前没有提到这一点,但我不会没有解释就离开你。

Epsilon 是一个关键参数,确保我们的代理在得出每个状态下最佳行动的明确结论之前,充分探索环境。

它是一个介于 0 和 1 之间的值,代表代理选择随机行动而不是她认为最好的行动的概率。

探索新策略和坚持已知策略之间的权衡被称为探索-开发问题。这是 RL 问题中的一个关键因素,也是 RL 问题与监督机器学习的区别。

从技术上讲,我们希望代理找到全局最优,而不是局部最优。

良好的做法是以较大的值(例如 50%)开始训练,并在每次训练后逐渐减少。通过这种方式,代理在开始时探索了很多,随着她策略的完善,探索的越来越少。

5.重述✨

第一部分的关键要点是:

  • 每个 RL 问题都有一个代理(或多个代理)、环境、动作、状态和奖励。
  • 代理人依次采取行动,目标是最大化总报酬。为此,她需要找到最佳策略。
  • 价值函数是有用的,因为它们为我们提供了寻找最优策略的另一种途径。
  • 在实践中,您需要针对您的问题尝试不同的 RL 算法,看看什么效果最好。
  • RL 代理需要大量的训练数据来学习。OpenAI gym 是一个很好的工具,可以重复使用和创建你的环境。
  • 在训练 RL 代理时,探索与利用是必要的,以确保代理不会陷入局部最优。

6.家庭作业📚

没有一点家庭作业的课程就不是课程。

我想让你选择一个你感兴趣的现实世界的问题,你可以用强化学习来建模和解决。

挑一个你关心的问题。这些是你想把宝贵的时间花在上面的。

定义什么是代理、行动、状态和奖励。

如果您有任何问题,请随时在【plabartabajo@gmail.com】给我发电子邮件,我会给您反馈。

7.下一步是什么?

第二部分 中,我们使用 Q-learning 解决了第一个强化学习问题。

那里见!

想支持我吗?

你喜欢阅读和学习关于 ML、AI 和数据科学的知识吗?

无限制地访问我在 Medium 上发布的所有内容,并支持我的写作。

👉🏽今天使用我的 推荐链接 成为会员。

**https://pau-labarta-bajo.medium.com/membership

👉🏽订阅 datamachines 简讯

👉🏽关注我 推特LinkedIn

👉🏽给我很多掌声👏🏿👏🏽👏在下面

祝你愉快🤗

避寒胜地**

实践强化学习课程:第 2 部分

原文:https://towardsdatascience.com/hands-on-reinforcement-learning-course-part-2-1b0828a1046b?source=collection_archive---------10-----------------------

实践教程

表格 Q 学习

来自 Pexels 的海伦娜·扬科维奇

欢迎来到我的强化学习课程❤️

这是我强化学习实践课程的第二部分,带你从零到英雄🦸‍♂️.

如果您错过了 part 1 ,请阅读它,以便将强化学习术语和基础知识掌握到位。

今天我们要解决第一个学习问题…

我们将训练一名代理人驾驶出租车🚕🚕🚕!

嗯,一个简化版的出租车环境,但是一天结束的时候出租车。

我们将使用 Q-learning,这是最早和最常用的 RL 算法之一。

当然,还有 Python🐍。

本课所有代码在 本 Github repo 中。 Git 克隆它,跟随今天的问题。

第二部分

内容

  1. 出租车驾驶问题🚕
  2. 环境、行动、状态、奖励
  3. 随机代理基线🤖🍷
  4. q-学习代理🤖🧠
  5. 超参数调谐🎛️
  6. 重述✨
  7. 家庭作业📚
  8. 下一步是什么?❤️

1.出租车驾驶问题🚕

我们将使用强化学习来教一个智能体驾驶出租车。

首先,在现实世界中驾驶出租车是一项非常复杂的任务。因此,我们将在一个简化的环境中工作,该环境包含一名优秀出租车司机所做的三件重要事情,即:

  • 接载乘客并把他们送到他们想要的目的地。
  • 安全驾驶,意味着没有碰撞。
  • 在尽可能短的时间内驾驶它们。

我们将使用 OpenAI Gym 中的一个环境,称为[**Taxi-v3**](https://gym.openai.com/envs/Taxi-v3/)环境。

出租车环境(图片由作者提供)

在网格世界中有四个指定的位置,分别用 R(ed)、G(reen)、Y(ellow)和 B(lue)表示。

当这一集开始时,出租车在一个随机的广场出发,乘客在一个随机的位置(R,G,Y 或 B)。

出租车开到乘客所在地,接乘客,开到乘客的目的地(四个指定地点中的另一个),然后让乘客下车。在这样做的时候,我们的出租车司机需要小心驾驶,以避免撞到任何墙壁,标记为 | 。一旦乘客下车,这一集就结束了。

这就是我们今天将构建的 q-learning 代理如何驱动:

优秀的出租车司机

在我们到达那里之前,让我们很好地理解什么是这个环境的行动、状态和回报。

2.环境、行动、状态、奖励

👉🏽notebooks/00 _ environment . ipynb

让我们首先加载环境:

在每个步骤中,代理可以选择哪些操作

  • 0往下开
  • 1开车过来
  • 2向右行驶
  • 3向左行驶
  • 4搭载乘客
  • 5让乘客下车

表示

  • 25 个可能的滑行位置,因为世界是一个 5x5 的网格。
  • 乘客的 5 个可能位置,即 R、G、Y、B,加上乘客在出租车中的情况。
  • 4 个目的地位置

这给了我们 25×5×4 = 500 个状态

那么奖励呢?

  • -1 默认每步奖励。
    为什么-1,而不是简单的 0?因为我们希望通过惩罚每一个额外的步骤来鼓励代理花费最短的时间。这就是你对出租车司机的期望,不是吗?
  • +20 将乘客送到正确目的地的奖励。
  • -10 在错误地点执行取货或卸货的奖励。

可以从env.P.读取奖励和环境转换(状态,动作)→ next_state

顺便说一句,你可以在每个状态下渲染环境来仔细检查这个env.P向量是否有意义:

来自state=123

州= 123

代理向南移动action=0到达state=223

州=223

奖励是-1,因为这一集既没有结束,也没有司机错误地选择或放弃。

3.随机代理基线🤖🍷

👉🏽notebooks/01 _ random _ agent _ baseline . ipynb

在您开始实现任何复杂的算法之前,您应该总是建立一个基线模型。

这个建议不仅适用于强化学习问题,也适用于一般的机器学习问题。

直接跳到复杂/花哨的算法中是非常有诱惑力的,但是除非你真的很有经验,否则你会失败得很惨。

让我们使用一个随机代理🤖🍷作为基准模型。

我们可以看到这个代理对于给定的初始state=198的表现

3804 步很多!😵

请在此视频中亲自观看:

行动中的随机代理

为了获得更有代表性的性能度量,我们可以重复相同的评估循环n=100次,每次从随机状态开始。

如果你画出timesteps_per_episodepenalties_per_episode,你可以观察到它们都没有随着代理完成更多的剧集而减少。换句话说,代理没有学到任何东西。

如果您想要性能的汇总统计,您可以取平均值:

实现代理学习是强化学习的目标,也是本课程的目标。

让我们使用 Q-learning 实现我们的第一个“智能”代理,Q-learning 是现存的最早和最常用的 RL 算法之一。

4.q-学习代理🤖🧠

👉🏽notebooks/02_q_agent.ipynb

Q-learning (by 克里斯·沃金斯 🧠和 彼得·达扬 🧠)是一种寻找最优 q 值函数的算法。

正如我们在第 1 部分中所说的,与策略 π 相关联的 Q 值函数 Q(s,a) 是代理人在状态 s 采取行动 a 并随后遵循策略 π 时期望得到的总报酬。

最优 Q 值函数 Q*(s,a) 是与最优策略 π*相关联的 Q 值函数。

如果你知道 Q*(s,a) 你可以推断π:也就是说,你选择一个最大化当前状态 s 的 Q(s,a)的动作作为下一个动作。

Q-learning 是一种迭代算法,从任意初始猜测 Q⁰(s,a) 开始,计算最佳 q 值函数 Q*(s,a) 的越来越好的近似值

在类似于Taxi-v3的表格环境中,状态和动作的数量有限,q 函数本质上是一个矩阵。它的行数与状态数一样多,列数与动作数一样多,即 500 x 6。

好的,但是你如何准确地从 Q⁰(s,a)计算下一个近似值 Q (s,a)?

这是 Q-learning 的关键公式:

q-学习公式(图片由作者提供)

当我们的 q-agent 导航环境并观察下一个状态s’和奖励 r 时,你用这个公式更新你的 q-值矩阵。

这个公式中的学习率 𝛼 是多少?

学习率(通常在机器学习中)是一个小数字,它控制 q 函数的更新量。你需要调整它,因为太大的值会导致不稳定的训练,太小的值可能不足以避开局部最小值。

还有这个折现因子 𝛾

折扣因子是一个介于 0 和 1 之间的(超)参数,它决定了相对于近期的回报,我们的代理人对远期回报的关心程度。

  • 当𝛾=0 时,代理人只关心眼前报酬的最大化。正如生活中发生的那样,最大化眼前回报并不是获得最佳长期结果的最佳方法。这也发生在 RL 特工身上。
  • 当𝛾=1 时,代理人根据其所有未来报酬的总和来评估其每一个行为。在这种情况下,代理人同等重视眼前的回报和未来的回报。

折扣因子通常是中间值,例如 0.6。

总而言之,如果你

  • 训练足够长的时间
  • 有着不错的学习率和折扣系数
  • 代理在状态空间中探索了足够多的时间
  • 你用 Q 学习公式更新 Q 值矩阵

你的初始近似最终会收敛到最优 q 矩阵。瞧啊。

那么让我们为 Q-agent 实现一个 Python 类。

Q-agent 的 API

它的 API 与上面的RandomAgent相同,但是多了一个方法update_parameters()。该方法采用转移向量(state, action, reward, next_state),并使用上面的 Q 学习公式更新 Q 值矩阵近似值self.q_table

现在,我们需要将这个代理插入到一个训练循环中,并在代理每次收集新的经验时调用它的update_parameters()方法。

此外,记住我们需要保证代理充分探索状态空间。还记得我们在第一部分中谈到的勘探-开采参数吗?这就是epsilon参数进入游戏的时候。

让我们为n_episodes = 10,000培训代理,并使用epsilon = 10%

还有剧情timesteps_per_episodepenalties_per_episode

不错!这些图表看起来比RandomAgent好得多。这两个指标都随着训练而下降,这意味着我们的代理正在学习🎉🎉🎉。

我们实际上可以看到代理是如何从与我们用于RandomAgent相同的state = 123开始驱动的。

好棒的车!

如果你想比较硬数字,你可以评估 q-agent 的性能,比如说,100 个随机事件,并计算时间戳和招致的惩罚的平均数。

一点点关于ε贪婪政策

评估代理时,使用正的epsilon值而不是epsilon = 0.值仍然是一个好的做法

为什么会这样?我们的特工不是训练有素吗?为什么我们在选择下一个行动时需要保留这种随机性的来源?

原因是防止过度拟合。即使对于这样一个小州,在Taxi-v3(即 500 x 6)中的行动空间,很可能在培训期间我们的代理没有访问足够的特定州。

因此,它在这些状态下的性能可能不是 100%最佳的,导致代理“陷入”次优操作的几乎无限循环中。

如果 epsilon 是一个小正数(例如 5%),我们可以帮助代理摆脱这些次优行为的无限循环。

通过在评估时使用小ε,我们采用了所谓的ε贪婪策略

让我们使用epsilon = 0.05.来评估我们在n_episodes = 100上训练过的代理,观察这个循环看起来几乎与上面的训练循环完全一样,但是没有调用update_parameters()

这些数字看起来比RandomAgent.好得多

我们可以说我们的代理已经学会开出租车了!

q 学习为我们提供了一种计算最优 q 值的方法。但是,超参数 alphagammaepsilon呢?

我为你选择了它们,相当随意。但是在实践中,您将需要针对您的 RL 问题来调整它们。

让我们探索它们对学习的影响,以获得对正在发生的事情的更好的直觉。

5.超参数调谐🎛️

👉🏽notebooks/03 _ q _ agent _ hyperparameters _ analysis . ipynb

让我们使用不同的值alpha(学习率)和gamma(折扣因子)来训练我们的 q-agent。至于 T2,我们保持在 10%。

为了保持代码整洁,我将 q-agent 定义封装在[src/q_agent.py](https://github.com/Paulescu/hands-on-rl/blob/50c61a385bbd511a6250407ffb1fcb59fbfb983f/01_taxi/src/q_agent.py#L4)中,并将训练循环封装在[src/loops.py](https://github.com/Paulescu/hands-on-rl/blob/50c61a385bbd511a6250407ffb1fcb59fbfb983f/01_taxi/src/loops.py#L9)train()函数中

让我们为每个超参数组合绘制每集的timesteps

这张图看起来很艺术,但有点太吵杂了😵。

不过你可以观察到,当alpha = 0.01时,学习速度变慢。alpha(学习率)控制我们在每次迭代中更新多少 q 值。值太小意味着学习速度较慢。

让我们放弃alpha = 0.01,对每个超参数组合进行 10 次训练。我们使用这 10 次运行,对从 1 到 1000 的每个剧集编号的timesteps进行平均。

我在src/loops.py中创建了函数[train_many_runs()](https://github.com/Paulescu/hands-on-rl/blob/50c61a385bbd511a6250407ffb1fcb59fbfb983f/01_taxi/src/loops.py#L121)来保持笔记本代码的整洁:

看起来alpha = 1.0是效果最好的值,而gamma似乎影响较小。

恭喜你!🥳,你已经在本课程中调整了你的第一个学习率

调整超参数既费时又乏味。有一些优秀的库可以自动完成我们刚刚完成的手动过程,比如【Optuna】,但是这是我们将在课程的后面部分使用的。暂时享受一下我们刚刚发现的训练提速。

等等,我告诉你要相信我的这个epsilon = 10%怎么了?

现在的 10%值是最好的吗?

我们自己检查一下。

我们选择找到的最好的alphagamma,即

  • alpha = 1.0
  • gamma = 0.9(我们也可以选择0.10.6)

和训练用不同的epsilons = [0.01, 0.1, 0.9]

并绘制产生的timestepspenalties曲线:

如你所见,epsilon = 0.01epsilon = 0.1似乎都工作得很好,因为它们在勘探和开发之间取得了恰当的平衡。

另一方面,epsilon = 0.9是一个太大的值,导致训练过程中“太多”的随机性,并阻止我们的 q 矩阵收敛到最优值。观察性能如何稳定在每集大约250 timesteps的水平。

一般来说,选择epsilon超参数的最佳策略是渐进ε衰变。也就是说,在训练开始时,当代理对其 q 值估计非常不确定时,最好访问尽可能多的州,为此,大的epsilon是很好的(例如 50%)

随着训练的进行,代理改进了它的 q 值估计,探索那么多不再是最佳的。相反,通过减少epsilon,代理可以学习完善和微调 q 值,使它们更快地收敛到最优值。太大的epsilon会导致我们看到的epsilon = 0.9的收敛问题。

我们会在课程中不断调整,所以我暂时不会坚持太多。再次,享受我们今天所做的。这是非常了不起的。

B-R-A-V-O!(图片由作者提供)

6.重述✨

恭喜你(可能)解决了你的第一个强化学习问题。

这些是我希望你能记住的关键知识:

  • 强化学习问题的难度与可能的动作和状态的数量直接相关。Taxi-v3是一个表格环境(即有限数量的状态和动作),所以它是一个简单的环境。
  • Q-learning 是一种学习算法,非常适合表格环境。
  • 无论您使用什么 RL 算法,都有一些超参数需要调整,以确保您的代理了解最佳策略。
  • 调整超参数是一个耗时的过程,但必须确保我们的代理了解。随着课程的进展,我们会在这方面做得更好。

7.家庭作业📚

👉🏽notebooks/04_homework.ipynb

这是我要你做的:

  1. Git 克隆 把 repo 到你的本地机器上。
  2. 设置 本课的环境01_taxi.
  3. 打开[01_taxi/otebooks/04_homework.ipynb](https://github.com/Paulescu/hands-on-rl/blob/main/01_taxi/notebooks/04_homework.ipynb)并尝试完成 2 个挑战。

我称之为挑战(不是练习),因为它们并不容易。我希望你尝试它们,弄脏你的手,并且(可能)成功。

在第一个挑战中,我谅你也不敢更新train()函数src/loops.py来接受一个依赖于剧集的 epsilon。

在第二个挑战中,我希望您升级 Python 技能并实现并行处理,以加快超参数实验。

像往常一样,如果你遇到困难,需要反馈,请给我写信plabartabajo@gmail.com.

我将非常乐意帮助你。

8.下一步是什么?❤️

在下一部分,我们将解决一个新的 RL 问题。

更难的一个。

使用新的 RL 算法。

有很多蟒蛇。

还会有新的挑战。

而且好玩!

回头见!

想支持我吗?

你喜欢阅读和学习关于 ML、AI 和数据科学的知识吗?

无限制地访问我在 Medium 上发布的所有内容,并支持我的写作。

👉🏽今天使用我的 推荐链接 成为会员。

https://pau-labarta-bajo.medium.com/membership

👉🏽订阅 datamachines 简讯

👉🏽 跟着我 上媒。

👉🏽给我很多掌声👏🏿👏🏽👏在下面

祝你愉快🤗

避寒胜地

实践强化学习课程:第 3 部分

原文:https://towardsdatascience.com/hands-on-reinforcement-learning-course-part-3-5db40e7938d4?source=collection_archive---------9-----------------------

表格 SARSA

贝尔格莱德萨瓦马拉(图片由作者提供)

欢迎来到我的强化学习课程❤️

这是我强化学习实践课程的第三部分,带你从零到英雄🦸‍♂️.

我们仍处于旅程的起点,解决相对容易的问题。

在第 2 部分中,我们实现了离散 Q 学习来训练Taxi-v3环境中的代理。

今天,我们将进一步解决MountainCar环境问题🚃使用 SARSA 算法。

让我们帮助这辆可怜的车赢得对抗地心引力的战斗!

本课所有代码都在 本 Github repo 中。 Git 克隆它,跟随今天的问题。

第三部分

内容

  1. 山地汽车问题🚃
  2. 环境、行动、状态、奖励
  3. 随机代理基线🚃🍷
  4. 萨尔萨特工🚃🧠
  5. 停下来喘口气,⏸🧘
  6. 重述✨
  7. 家庭作业📚
  8. 下一步是什么?❤️

1.山地汽车问题🚃

山地汽车问题是一个重力存在的环境(多么令人惊讶),目标是帮助一辆可怜的汽车赢得与它的战斗。

汽车需要逃离它被困的山谷。这辆车的引擎不够强大,无法单程爬上山,所以唯一的办法就是来回行驶,建立足够的动力。

让我们来看看它的实际应用:

你刚刚看到的视频对应于我们今天要建造的SarsaAgent

很有趣,不是吗?

你可能想知道。这个看起来很酷,但是当初为什么会选择这个问题呢?

为什么会有这个问题?

本课程的理念是逐步增加复杂性。循序渐进。

与第 2 部分中的Taxi-v3环境相比,今天的环境在复杂性方面有了微小但相关的增加。

但是,这里到底什么更难?

正如我们在 第二部分 中看到的,一个强化学习问题的难度与问题的大小直接相关

  • 行动空间:代理在每一步可以选择多少个行动?
  • 状态空间:代理可以在多少种不同的环境配置中找到自己?

对于动作和状态数量有限的小环境,我们有强有力的保证像 Q-learning 这样的算法能够很好地工作。这些被称为表格或离散环境

q 函数本质上是一个矩阵,其行数与状态数相同,列数与动作数相同。在这些的世界里,我们的代理人可以轻松地探索各州并制定有效的政策。随着状态空间和(尤其是)动作空间变得更大,RL 问题变得更难解决。

今天的环境是不是表格化的。但是,我们将使用一个离散化“技巧”将其转换为表格形式,然后求解。

我们先熟悉一下环境吧!

2.环境、行动、状态、奖励

👉🏽notebooks/00 _ environment . ipynb

让我们加载环境:

并绘制一帧:

两个数字决定了汽车的状态:

  • 其位置范围从 -1.20.6
  • 其速度范围从 -0.070.07

状态由两个连续的数字给出。这是Taxi-v3环境与第二部分的显著区别。我们将在后面看到如何处理这个问题。

有哪些动作

有 3 种可能的操作:

  • 0向左加速
  • 1无所事事
  • 2向右加速

奖励

  • 如果汽车位置小于 0.5,则奖励-1。
  • 一旦汽车的位置高于 0.5,或者达到最大步数,本集就结束:n_steps >= env._max_episode_steps

默认的负奖励-1 鼓励汽车尽快逃离山谷。

总的来说,我建议你直接在 Github 中检查开放 AI 健身房环境的实现,以了解状态、动作和奖励。

该代码有很好的文档记录,可以帮助您快速了解开始 RL 代理工作所需的一切。MountainCar的实现是这里以为例。

很好。我们熟悉了环境。

让我们为这个问题建立一个基线代理!

3.随机代理基线🚃🍷

👉🏽notebooks/01 _ random _ agent _ baseline . ipynb

强化学习问题很容易变得复杂。结构良好的代码是控制复杂性的最佳盟友。

今天我们将提升我们的 Python 技能,并为我们所有的代理使用一个BaseAgent类。从这个BaseAgent类,我们将派生出我们的RandomAgentSarsaAgent类。

父类和子类(图片由作者提供)

BaseAgent是我们在[src/base_agent.py](https://github.com/Paulescu/hands-on-rl/blob/main/02_mountain_car/src/base_agent.py)中定义的一个抽象类

它有 4 种方法。

它的两个方法是抽象的,这意味着当我们从BaseAgent:派生出RandomAgentSarsaAgent时,我们必须实现它们

  • get_action(self, state) →根据状态返回要执行的动作。
  • update_parameters(self, state, action, reward, next_state) →根据经验调整代理参数。这里我们将实现 SARSA 公式。

其他两种方法允许我们将经过训练的代理保存到磁盘或从磁盘加载。

  • save_to_disk(self, path)
  • load_from_disk(cls, path)

随着我们开始实现更复杂的模型和训练时间的增加,在训练期间保存检查点将是一个很好的主意。

下面是我们的BaseAgent类的完整代码:

从这个BaseAgent类,我们可以将RandomAgent定义如下:

让我们评估一下这个RandomAgent而不是n_episodes = 100,看看它的表现如何:

而我们RandomAgent的成功率是…

0% 🤭…

我们可以用下面的直方图来看代理在每集中走了多远:

在这些100运行中,我们的RandomAgent没有越过 0.5 标记。一次都没有。

当你在本地机器上运行这段代码时,你会得到稍微不同的结果,但是在任何情况下,0.5 以上的完成剧集的百分比都不会是 100%。

你可以使用[src/viz.py](https://github.com/Paulescu/hands-on-rl/blob/37fbac23d580a44d46d4187525191b324afa5722/02_mountain_car/src/viz.py#L52-L61)中的show_video功能观看我们悲惨的RandomAgent行动

一个随机的代理不足以解决这种环境。

让我们试试更聪明的方法😎…

4.萨尔萨特工🚃🧠

👉🏽notebooks/02 _ sarsa _ agent . ipynb

SARSA (由 Rummery 和 Niranjan 提出)是一种通过学习最优 q 值函数来训练强化学习代理的算法。

它于 1994 年出版,是 Q-learning(由克里斯·沃金斯和彼得·达扬出版)的两年后。

SARSA 代表 S 状态 A 动作Re 前进 S 状态 A 动作。

SARSA 和 Q-learning 都利用贝尔曼方程来迭代地寻找最佳 Q 值函数的更好的近似 Q*(s,a)

但是他们的做法略有不同。

如果您还记得第 2 部分,Q-learning 的更新公式是

这个公式是一种计算 q 值的新估计值的方法

这个数量是一个目标🎯我们想把原来的估计修正为。这是我们应该瞄准的最佳 q 值的估计,它随着我们训练代理和我们的 q 值矩阵的更新而改变。

强化学习问题通常看起来像有监督的 ML 问题,但是带有移动的目标🏃 🎯

SARSA 有一个类似的更新公式,但有一个不同的目标

SARSA 的目标

也取决于代理将在下一个状态s’采取的动作a’这是非典A’s 中最后一个 A 的名字。

如果你探索足够的状态空间并用 SARSA 更新你的 q 矩阵,你将得到一个最优策略。太好了!

你可能会想…

Q-learning 和 SARSA 在我看来几乎一模一样。有什么区别?🤔

有一个关键区别:

  • SARSA 的更新取决于下一个动作a’,并因此取决于当前策略。随着您的训练和 q 值(以及相关策略)的更新,新策略可能会针对相同的状态s’产生不同的下一个动作a’。你不能用过去的经验 (s,a,r,s’,a’)来提高你的估计。取而代之的是,你用一次经历来更新 q 值,然后把它扔掉。因此,SARSA 被称为基于策略的方法。
  • 在 Q-learning 中,更新公式不依赖于下一个动作a’,,而只依赖于 (s,a,r,s’)。您可以重用使用旧版本策略收集的过去经验 (s,a,r,s’),,以提高当前策略的 q 值。Q-learning 是一种非政策方法。

策略外的方法比策略内的方法需要更少的经验来学习,因为您可以多次重用过去的经验来改进您的估计。他们更样高效

然而,当状态、动作空间增长时,非策略方法具有收敛到最优 Q 值函数 Q*(s,a)的问题。他们可能很狡猾,而且不稳定。

当我们进入深度 RL 领域时,我们将在课程的后面遇到这些权衡🤓。

回到我们的问题…

MountainCar环境中,状态不是离散的,而是一对连续的值(位置s1,速度s2)。

连续在这个上下文中实质上是指无限可能的值。如果有无限个可能的状态,不可能把它们都访问一遍来保证 SARSA 收敛。

为了解决这个问题,我们可以使用一个技巧。

让我们把状态向量离散成一组有限的值。本质上,我们并没有改变环境,而是改变了代理用来选择其动作的状态的表示。

我们的SarsaAgent通过将位置[-1.2 … 0.6]四舍五入到最近的0.1标记,将速度[-0.07 ...0.07]四舍五入到最近的0.01标记,将状态(s1, s2)从连续离散化。

该函数正是这样做的,将连续状态转化为离散状态:

一旦代理使用离散化状态,我们可以使用上面的 SARSA 更新公式,随着我们不断迭代,我们将更接近最佳 q 值。

这是SarsaAgent的全部实现

注意👆q 值函数是一个 3 维矩阵:2 维表示状态(位置、速度),1 维表示动作。

让我们选择合理的超参数,并为n_episodes = 10,000训练这个SarsaAgent

让我们用它们的 50 集移动平均线(橙色线)来绘制rewardsmax_positions(蓝色线)

超级!看起来我们的SarsaAgent正在学习。

在这里你可以看到它的作用:

如果你观察上面的max_position图表,你会意识到汽车偶尔无法爬山。

这种情况多长时间发生一次?让我们评价一下1,000随机集上的代理:

并计算成功率:

95.2% 还算不错。尽管如此,并不完美。请记住这一点,我们将在本课程的稍后部分回来。

注意:当您在您的终端上运行这段代码时,您会得到稍微不同的结果,但是我敢打赌您不会得到 100%的性能。

干得好!我们实现了一个SarsaAgent来学习🤟

这是一个暂停的好时机…

5.停下来喘口气,⏸🧘

👉🏽notebooks/03 _ momentum _ agent _ baseline . ipynb

如果我告诉您,MountainCar环境有一个更简单的解决方案会怎么样…

100%的时间都有效?😅

要遵循的最佳政策很简单。

跟着势头走:

  • 当汽车向右移动时向右加速velocity > 0
  • 当汽车向左移动时,向左加速velocity <= 0

这个策略看起来像这样:

这是你如何用 Python 写这个MomentumAgent:

你可以仔细检查它是否完成了每一集。百分之百的成功率。

另一方面,如果你画出受过训练的SarsaAgent的政策,你会看到这样的东西:

这与完美的MomentumAgent策略有 50%的重叠

这意味着我们的SarsaAgent只有 50%的时间是正确的

这很有意思……

为什么 **SarsaAgent** 经常出错却仍能取得好成绩?

这是因为MountainCar仍然是一个小环境,所以 50%的时候做出错误的决定并不那么关键。对于更大的问题,经常犯错不足以构建智能代理。

你会买一辆 95%都正确的自动驾驶汽车吗?😱

另外,你还记得我们用来应用 SARSA 的离散化技巧吗?这是一个对我们帮助很大的技巧,但也给我们的解决方案带来了错误/偏见。

我们为什么不提高对状态和速度离散化的分辨率,以获得更好的解呢?

这样做的问题是状态数量的指数增长,也称为维数灾难。随着每个状态分量分辨率的增加,状态总数呈指数增长。状态空间增长太快,SARSA 代理无法在合理的时间内收敛到最优策略。

好吧,但是有没有其他的 RL 算法可以完美解决这个问题?

是的,有。我们将在接下来的课程中讨论它们。总的来说,对于 RL 算法,没有一种方法是万能的,因此您需要针对您的问题尝试几种算法,看看哪种效果最好。

MountainCar环境中,完美的策略看起来如此简单,以至于我们可以尝试直接学习它,而不需要计算复杂的 q 值矩阵。一种策略优化方法可能效果最好。

但是我们今天不打算这样做。如果您想使用 RL 完美地解决这种环境,请按照课程进行操作。

享受你今天的成就。

谁在找乐子?(图片由作者提供)

6.重述✨

哇!我们今天讨论了很多事情。

这是 5 个要点:

  • SARSA 是一种基于策略的算法,可以在表格环境中使用。
  • 使用状态的离散化,可以将小型连续环境视为表格,然后使用表格 SARSA 或表格 Q-learning 进行求解。
  • 由于维数灾难,更大的环境不能被离散化和求解。
  • 对于比MountainCar更复杂的环境,我们将需要更先进的 RL 解决方案。
  • 有时候 RL 并不是最佳方案。当你试图解决你关心的问题时,请记住这一点。不要和你的工具结婚(在这种情况下是 RL),而是专注于找到一个好的解决方案。不要只见树木不见森林🌲🌲🌲。

7.家庭作业📚

👉🏽notebooks/04 _ homework . ipynb

这是我要你做的:

  1. Git 克隆repo 到你的本地机器。
  2. 设置 本课的环境02_mountain_car
  3. 打开[02_mountain_car/notebooks/04_homework.ipynb](http://02_mountain_car/notebooks/04_homework.ipynb)并尝试完成 2 个挑战。

在第一个挑战中,我要求你调整 SARSA 超参数alpha(学习率)和gamma(折扣系数)以加速训练。可以从第二部中得到启发。

在第二个挑战中,尝试提高离散化的分辨率,并使用表格 SARSA 学习 q 值函数。就像我们今天做的一样。

让我知道,如果你建立一个代理,实现 99%的性能。

8.下一步是什么?❤️

在下一课中,我们将进入强化学习和监督机器学习交叉的领域🤯。

我保证会很酷的。

在那之前,

在这个叫做地球的神奇星球上多享受一天吧🌎

爱❤️

不断学习📖

如果你喜欢这门课程,请分享给你的朋友和同事。

你可以通过plabartabajo@gmail.com找到我。我很乐意联系。

回头见!

你想成为(甚至)更好的数据科学家,接触关于机器学习和数据科学的顶级课程吗?

👉🏽订阅 datamachines 简讯

👉🏽 跟着我 上媒。

祝你愉快,🧡❤️💙

避寒胜地

第一手评论:BYOL

原文:https://towardsdatascience.com/hands-on-review-byol-bootstrap-your-own-latent-67e4c5744e1b?source=collection_archive---------16-----------------------

最近,自我监督学习方法已经成为无监督视觉表征学习的基石。最近推出的一个这样的方法BootstrapYourOwnLatent(BYOL)在这篇文章中被评论。我已经介绍了其他有趣的基于对比学习的自我监督学习方法,这些方法出现在 BYOL 之前,如 SimCLR,MoCo 等。在另一个职位彻底,并应考虑理解这个职位的基本原则。请在这里找到它们。

与其他对比学习方法不同,BYOL 在不使用任何负面样本的情况下实现了最先进的性能。基本上,像一个连体网络,BYOL 使用两个相同的编码器网络,称为在线和目标网络,用于获得表示,并减少两个表示之间的对比损失。

网络架构

BYOL 网络的架构如下所示。θ和ϵ分别代表在线和目标网络参数,f_θ和 f_ϵ分别是在线和目标编码器。目标网络权重是在线网络权重的缓慢移动平均值,即

想法是在第一步中训练在线网络 f_θ,并在第二步中使用这些学习到的表示用于下游任务,并使用标记的数据进一步微调它们。第一步,即 BYOL,可以总结为以下 5 个简单的步骤。

  1. 给定输入图像 x,通过对 x 应用两个随机增强,生成同一图像 v 和 v’的两个视图
  2. 给定在线编码器和目标编码器的 v 和 v ’,得到矢量表示 y_θ和 y'_ϵ。
  3. 现在,这些表示被投影到另一个子空间 z。这些投影的表示在下图中由 z_θ和 z'_ϵ表示。
  4. 因为目标网络是在线网络的慢速移动平均,所以在线表示应该是目标表示的预测,即 z_θ应该预测 z'_ϵ,因此另一个预测器(q_θ)被放在 z_θ之上。
  5. <q_ z="">之间的对比损失减少。</q_>

图片来源: Grill,Jean-Bastien 等人,“引导你自己的潜能:自我监督学习的新方法”arXiv 预印本 arXiv:2006.07733 (2020)。

数学上,对比损耗计算为 q_θ(z_θ)和 z'_ϵ.之间的均方误差在计算均方误差之前,标签 z'_ϵ和目标 q_θ(z_θ)是 L2 归一化的。等式是,

对比损失

z_ϵ棒是 L2 归一化的 z_ϵ,而 q_θ(z_θ)棒是 L2 归一化的 q_θ(z_θ)。

为什么是 BYOL?

第一个问题是,为什么以及在哪里应该使用 BYOL?

BYOL 方法有助于学习各种下游计算机视觉任务的有用表示,如对象识别、对象检测、语义分割等。一旦以 BYOL 方式学习了这些表示,它们可以与任何标准的对象分类模型一起使用,例如 Resnet、VGGnet,或者任何语义分割网络,例如 FCN8s、deeplabv3 等,或者任何其他特定于任务的网络,并且它可以获得比从头开始训练这些网络更好的结果。这是 BYOL 受欢迎的主要原因。下图显示了使用 Imagenet 图像学习的 BYOL 表示击败了所有以前的无监督学习方法,并在线性评估协议下使用 Resnet50 实现了 74.1%的分类准确度。如果你不确定线性评估协议,它在我的上一篇帖子中有详细描述。

线性评估方案下的 BYOL 结果。图片来源:烧烤店,让-巴斯蒂恩

在密集的预测任务中,BYOL 的能力得到了更有效的利用,由于数据标注任务复杂且成本高昂,因此通常只有少数几个标注可用。当 BYOL 用于一个这样的任务,即使用带有 FCN8s 网络和 Resnet50 主干的 cityscapes 数据集的语义分割时,它优于从零开始训练的网络版本,即具有随机权重。下图比较了 cityscapes 数据集上 3 个主要网络的性能。

  • Resnet50 根据 Imagenet 权重进行训练,并使用 3k 城市风景标记的图像(红色虚线)进行微调。
  • 仅使用 3k 城市风景图像(黑色虚线)从随机权重训练 Resnet50。
  • Resnet50 使用 20k 未标记的城市景观图像在 BYOL 上进行预训练,然后使用 3k 城市景观图像(蓝色实线)进行微调。

下图清楚地显示了 BYOL 极大地有助于学习该任务的有用表示,并提示它应被视为其他计算机视觉工业应用的预训练步骤,在这些应用中,由于许可法规而不能使用 Imagenet 权重,并且存在大量未标记的数据用于无监督训练。

BYOL 增益(图表由作者提供)

实施细则

对于图像放大,使用以下一组放大。首先,从图像中选择一个随机裁剪,并将其大小调整为 224x224。然后应用随机水平翻转,接着是随机颜色失真和随机灰度转换。随机色彩失真由亮度、对比度、饱和度和色调调整的随机序列组成。以下代码片段在 PyTorch 中实现了 BYOL 增强管道..

from torchvision import transforms as tfmsbyol_tfms = tfms.Compose([
    tfms.RandomResizedCrop(size=512, scale=(0.3, 1)),
    tfms.RandomHorizontalFlip(),
    tfms.ToPILImage(),
    tfms.RandomApply([
            tfms.ColorJitter(0.4, 0.4, 0.4, 0.1)
    ], p=0.8),
   tfms.RandomGrayscale(p=0.2),
   tfms.ToTensor()])

在实际的 BYOL 实现中,Resnet50 被用作编码器网络。对于投影 MLP,首先利用批范数将 2048 维的特征向量投影到 4096 维的向量空间,然后进行 ReLU 非线性激活,最后将特征向量缩减到 256 维。预测器网络使用相同的架构。以下 PyTorch 代码片段实现了基于 Resnet50 的 BYOL 网络,但它也可以与任何任意编码器网络结合使用,如 VGG、InceptionNet 等。没有任何重大变化。

BYOL 的运作方式

另一个有趣的事实是,虽然为 BYOL 策划的任务存在一个崩溃的解决方案,但该模型安全地避免了它,其实际原因是未知的。塌陷的解决方案意味着,模型可能通过学习任何图像的任何视图的恒定向量而逃脱,并且达到零损失,但是它没有发生。

原始论文1的作者推测,这可能是由于主干中使用的复杂网络(具有跳跃连接的深度 Resnet ),该模型从未得到直接的折叠解决方案。但是在 SimSiam2 Chen、Xineli 和 He 最近发表的另一篇论文中,他们发现不是复杂的网络结构,而是“停止梯度”操作使模型避免了折叠表示。“停止梯度”意味着网络永远不会直接通过梯度来更新目标网络的权重,因此永远不会得到崩溃的解决方案。他们还表明,没有必要使用动量目标网络来避免折叠表示,但如果使用的话,它肯定会为下游任务提供更好的表示。

这是对 BYOL 和 PyTorch 代码的简要总结。如需全面实施,可参考 https://github.com/nilesh0109/self-supervised-sem-seg 的 GitHub 回购。

下面是这篇文章中使用的参考文献列表。

  1. 引导你自己的潜能:自我监督学习的新方法。 arXiv 预印本 arXiv:2006.07733 (2020)。
  2. 陈、和何。"探索简单的暹罗表象学习."arXiv 预印本 arXiv:2011.10566 (2020)。

实践逐步指导增加你的工作机会

原文:https://towardsdatascience.com/hands-on-step-by-step-guidance-to-grow-your-job-opportunities-fe0c757fb966?source=collection_archive---------22-----------------------

职业建议

如何战略性地利用 Meetup 会议获得你梦寐以求的数据科学工作

图片来自 Pixabay 的 Gerd Altmann

你是一名有抱负的数据科学家,你会努力遵循更有经验的同事给出的所有建议。

  • 你正在用所有推荐的免费和付费在线书籍和课程学习数据科学。
  • 你可以阅读所有最新的数据科学博客。
  • 你钻研所有被推荐的研究论文。
  • 你参加了卡格尔比赛。
  • 你建立了一个 GitHub 项目组合。
  • 你浏览所有张贴的面试问题。

但是当你最终申请工作时,你会面临许多拒绝。你写了 100 多份申请,如果有一次你得到了一些关于你为什么没有得到这份工作的反馈,那就是“我们决定和另一个更适合的候选人一起前进。”

这是许多有抱负的数据科学家面临的常见情况。他们经常把这当成比赛的一部分,像往常一样前进。

在我的职业生涯中,我参加过数百次面试。未被选中的原因通常分为以下两类。

  • 技能,以及
  • 不适合这个团队。

本文将重点放在第二个方面,因为这一点不太明确,而且经常不被考虑。

许多候选人都在问,他们必须改变什么才能成为一个合适的人,他们应该参加什么课程。但这部分和技术技能无关。这是关于对你的看法。

  • 那个人给我们团队带来了什么精神?
  • 员工喜欢和她/他一起工作吗?
  • 我们信任这个人吗?

这种“不适合团队”的原因不能通过参加另一个在线课程和自己做另一个项目来消除。你无法改变人们在面试中对你的看法。

但可以改变的是,你会找到适合你的团队和公司。

要解决它们,你需要走出你孤立的自学世界,与外面的环境联系起来。你必须在申请工作之前解决这个问题。

随着疫情和越来越多的远程工作,数据科学职位的竞争加剧。

另一方面,还有 Oscar,一个有经济学背景,只有一点编程知识的数据治理专家。不久前,他搬进了一家跨国公司的数据科学部门,开始了他的数据科学之旅。

他没有申请招聘广告。他没有令人讨厌的招聘流程,你最终听不到任何反馈,而是直接通过主要的招聘步骤。

奥斯卡是真实的。我雇了他。

区别在于对网络的战略性使用。得到一份数据科学的工作,不仅仅是知识、技能、证书。它是一个网络的集成。

嵌入这样一个网络并解决拒绝原因的一个简单且负担得起的选择是 Meetup 会议。

所以,让我们来分解一下战略性地使用 Meetups 找工作的过程,这样你也可以应用它。

Meetup 会议的秘密

什么是 Meetup 会议?

Meetup 是一个为兴趣小组提供在线服务的平台。个人可以创建对特定主题感兴趣的团体,他们组织面对面或虚拟的活动。活动包括人们展示项目的会议、技术会议、徒步旅行、语言课、创业推介等。它是所有数据科学主题的完美平台,因此,可以找到数千个与数据科学相关的群组。

在数据科学领域寻找 Meetup 群组时,搜索以下关键词。

  • 数据科学
  • 机器学习
  • 深度学习
  • AI 或人工智能
  • 自然语言处理
  • 物联网、云、边缘计算
  • 金融科技、教育科技、医疗科技等等
  • 人工智能开发者
  • 编程;编排
  • Python、Julia、Java、Js、KNIME、C/C++等等
  • 等等

你可以从你的位置选择半径,你会发现所有的团体靠近你的地方。

作者截图:搜索半径的选择

Pro tip : 特别是在疫情期间,许多 Meetup 会议转变为在线会议,你可以在全球范围内参加。因此,选择“任何距离”,然后在全球范围内寻找虚拟会议。

自从疫情启动以来,我在硅谷参加了许多(在线)会议,并结识了几个新的商业伙伴。我现在有项目合作,甚至和斯坦福大学合作。一家大型科技公司也联系了我,让我出演一个角色。

谁会参加聚会?

80%的参与者希望进入数据科学领域,或者是数据分析师、业务分析师、有抱负的数据科学家、学生、学者以及没有团队领导角色的经验丰富的数据科学家。20%的与会者是担任团队领导职务的高级数据科学家、招聘经理和首席数据科学家。

为什么你既需要 80%又需要 20%的网络?

那 80%可以算是“同行”同行是必不可少的,原因有三:

  1. 为了你的未来。你们一起成长,你们将独立经历相同的发展步骤和相似的职业水平。这些同事支持你在五年、十年或十五年内从一个职位或公司转到另一个职位或公司。它们是你今天投资的关系资本的利息。
  2. 讨论方法、项目挑战以及何时需要数据科学相关问题的意见。这不仅仅是你作为初学者的时间。此外,当数据科学领导者面临尚未找到解决方案的问题时,他们也会这样做。
  3. 为团队和公司打开大门。当人们熟悉你和你的技能并信任你时,他们愿意为你辩护。许多公司都有所谓的推荐计划,这意味着如果一名现有员工推荐了一名候选人,而这名候选人被录用了,她/他就可以获得一笔可观的现金奖励。

这 20%是你短期和中期工作目标的机会。他们雇人,并且雇佣他们信任的人。他们需要熟悉你。

和金融投资一样,你应该两者都投资。平均来说,你应该用 50%的时间与每个小组交流。

你应该多久参加一次?

参加聚会和建立关系网是销售。你推销自己。销售研究表明,一个人至少要有八次互动才能达成交易。所以,和一个人见一两次面并不会给你带来工作机会。你必须参加许多 Meetup 会议才能见到同一个人至少八次,尤其是一位有其他任务的资深科学家。

但是在你停止阅读之前,请等待。Meetup 的诀窍是建立一个连接,让你能够在 Meetup 平台之外建立关系网。我稍后将回到如何做这件事。

有哪些类型的 Meetup 会议?

在研究数据科学领域时,我将它们大致分为:

  • 申请,即来自不同行业和公司的从业者的项目演示。
  • 研究,即最新的机器学习或 AI 研究和方法。
  • 软件公司/工具提供商,也就是说,他们通常会亲自动手,在指导下对工具进行测试
  • 特定技术和主题,如 Kubernetes、加密、云计算等。
  • 编程类,例如 Python 或 C/C++ / live 编码类。
  • 将多样性引入技术领域的团队,例如数据科学/机器学习领域的女性。
  • 特定行业会议,即技术、数据和数字化会议,关注特定行业。
  • 初创企业推介,即初创企业可以向投资者或正在寻找联合创始人的初创企业推介。

你有各种各样的会议,你可以随时找到你感兴趣的会议。

建立你的 Meetup 组合

如何决定参加哪个 Meetup 会议?

关于如何选择会议,又有两个选项:主题或行业,以及公司相关。

首先,按主题呈现,即主题或行业。如果你想进入物联网相关的数据科学或客户分析,请选择物联网相关或客户分析聚会。如果你想进入制药和生命科学领域,选择一个有生命科学和健康数据科学主题的专业。

在这样的聚会上,你会找到在那个领域工作的人。

在第二种情况下,你的目标是扩大你的关系网,以便有一个专家交流或潜在的职位,提出的主题是次要的。

然后,您可以根据主持人、与会人员和召开 Meetup 会议的公司来选择会议。

看看演讲者来自哪家公司,如果是与公司合作完成的,看看他们是否是学者。找出聚会的地点。当一家公司举办这种活动时,通常会有不少员工参加。

根据您希望加入的行业或主办公司选择 Meetup 会议。

专业提示:如果主持人是年长的,可以预期观众也是年长的。让几个合适的人参加聚会比尽可能多的人参加更重要。

如何充分利用聚会?

参加之前要做好准备!

许多人没有任何准备就参加会议。他们很少了解演讲者或主持的公司——只知道这是一个众所周知的品牌或话题,会议结束后,他们很失望,因为他们没有从那次会议中受益。

我如何准备 Meetup 会议?

我为主持人做研究:LinkedIn、Google 和其他搜索工具。

  • 谁是主持人,他们的职业道路是什么?
  • 他们在公司中扮演什么角色?
  • 他们是否已经有了其他演讲,主题是什么?
  • 他们在这个话题上有多资深,在这次会议上听众有什么期望?
  • 他们的网络是什么样的?我认识与他们有联系的人吗?我在哪里可以找到他们?

我了解这个话题,以便进行有意义的讨论。

  • 它是做什么用的?在哪些行业或公司?
  • 主题是独特的还是标准的?它是否提出了重大问题的解决方案?

通过对这两个问题的分析,你可以深入了解从事相同主题工作的其他公司将会参加哪些会议。

  • 该领域常用的方法是什么?
  • 还有哪些问题和那个话题有关?

你不需要写一篇关于这个的论文,但是你需要基本的知识来进行(积极的)持久的互动。

我收集关于公司的信息。

  • 公司是做什么的?(如果不是知名品牌。)
  • 我认识那家公司的人吗?(专业提示:检查你在 LinkedIn 上的关系。)
  • 公司招人吗?他们招聘什么职位?(看对应的招聘广告。)
  • 那家公司的战略主题是什么?提出的案例是其中之一吗?

这样,你就可以评估该公司的切入点可能在哪里。

然后,我查看其他已经注册的参与者。您点击一个 Meetup 事件,然后您可以向下滚动并查看与会者列表。

然后,我查看他们的个人资料——并非所有人都输入了个人资料信息或看到了全名,但这让我第一次看到了谁在参加。如果有全名,我会在 LinkedIn 上寻找潜在的附加信息。

你应该和谁交往?

如上所述,你应该用一半的时间和可以被视为同事的人交往,用另一半的时间和负责招聘的人交往。所以,你应该和所有可能的人交往。

基于对简介的回顾,你对受众有一个大致的了解。如果你想和某个特定的人交谈,你可以特别留意这个人。

你不需要整个晚上都和一个人呆在一起。进行自然的讨论,询问她/他为什么参加,这个人在哪个领域工作,如果你对更深入的讨论不感兴趣,你可以继续。

我通常会告诉对方,我要开始另一场讨论了,但还是要感谢他们有趣的谈话,祝他们有一个愉快的夜晚,并说“我们希望在下次聚会时再见。”敞开大门是很重要的,因为情况可能会改变,这个人以后可能会对你至关重要。

如果你对一个人感兴趣,想进行后续互动,你可以问她/他是否在 LinkedIn 上,或者可以分享联系方式。我还会问一个人多久参加一次 Meetup 会议,参加哪些会议,是否已经有参加下一次会议的计划。然后,你知道在哪里可以再遇到那个人。

专业提示:我建议和主办方谈谈。也可以在活动页面上找到它们。他们有一个广泛的网络,因为活动和知道许多人参加,并可以指出你的人来讨论。而且他们往往在一个公司里处于领导地位。他们是建立你的社交网络的倍增器。

最后,与演讲者建立联系。不管你是不是绝对的初学者。有意义的讨论是必要的,为此,你做了准备。

你可以通过让演示者知道你是一个初学者,但阅读了这个主题来开始讨论。你可以就此引用一两点,并就如何进一步深入这个主题征求意见。你可以询问是否有可用的数据集,以便你可以尝试这些方法,或者她/他是否最终有一些代码示例。你可以进一步问这个话题对她/他的公司是否重要,有多少人在做这个,以及他们正在做的其他事情。

如果你表现出真诚的兴趣,你就会建立信任,人们会回答你的问题并支持你。当你们进行这样的对话时,你也可以询问联系方式,以及是否有可能进行跟进。大多数情况下,当你准备充分时,他们会支持你。

会后你应该做什么?

答案很简单:人脉,人脉,人脉。

你之前读到过你至少需要八次互动。那么,你如何得到它们呢?

如果你知道这个人的名字,而且他在 LinkedIn 上,那就联系他/她。重要事项:添加一条信息,如“我们在 XYZ 见过面,我想再次感谢您的有趣讨论,”或“感谢您在 XYZ 的有趣讨论,正如所讨论的,我想跟进 ABC,”这样,对方会觉得已经熟悉您了。然后你可以用准备好的问题继续跟进。但是至少要等两个星期。没有比两天后再发一条信息而被人忽视更大的机会了,除非你已经同意了。

如果你和一个人分享了联系方式,你也应该看看 LinkedIn。利用这些联系,进一步拓展人脉。

您还可以在 Meetup 平台上向 Meetup 成员发送消息。在 Meetup 会员名称的右侧,您可以查看是否可以发送消息。组织者通常会在个人资料中提供更多的联系方式。

使用此功能联系其他参与者。

作者截图:启用消息传递的成员

亲提示:部分会员已禁用消息功能。然而,在 LinkedIn 上可以找到很多。然后,我在 LinkedIn 上联系他们,在联系邀请中添加一条之前看到的信息,因为——同样——你需要与这个人建立信任。

我在 LinkedIn 上收到很多邀请,大多数情况下,我不认识那个人。每当有人写一条短信,比如“我已经读过你写的 XYZ 关于数据科学的文章”或者“我们都参加了 ABC 会议”,那么在几秒钟内,我就接受了邀请。

另一方面,为了让别人能够联系到你,选择相应的设置。

作者截图:其他成员联系的设置

做完所有这些,你就可以开始自然而有规律的互动了。

如何在网络活动中建立关系网?

在网络事件中建立关系网确实有点困难,但是用一些技巧,还是可以的。

在大多数活动中,在线活动期间可以看到与会者。所以,我做了一个参与者名单的截图。我记下是谁在问什么问题,以便联系。

如果你觉得舒服,你可以问一个问题,或者对之前的一个回答或问题进行评论。如果我对与一个特定的人建立关系感兴趣,并且那个人问了一个问题,我会问一个我可以向他提及的问题,比如“我发现这是一个很好的问题,但是在 ABC 的情况下我们会有什么?”有时,甚至有可能在活动中以这种方式与他人联系。

组织者和演讲者通常都有详细的联系方式,如上所述,你可以在会后与他们联系。在大多数情况下,他们主动向他们伸出援手,他们会有所回应。

然后,我像上面提到的那样表演:我在 LinkedIn 上和他们联系,给他们发消息。

如何让你的互动增加 10 倍?

组织 Meetup 会议!

你可以选择演讲者,这应该是有策略的。问问那些你想在哪里找到工作的人。作为组织者,你有一连串的互动:最初的接触(社交媒体、电子邮件),关于会议主题和期望的简报,在他们陈述之前和陈述期间的帮助,活动结束后的感谢电子邮件,简报,以及最终对其中一个主题的个人跟进。通过自然地这样做,你可以很快产生六到十次互动。

回到奥斯卡,他完全做到了这些。他还借此机会组织了一次 Meetup 会议,在会上他联系我做了一个演示。通过所有的互动,我熟悉了他的技能和潜力。互动是建立在信任的基础上的。

将所有这些整合在一起

Meetup 会议是最被低估的机会,它能让你在求职中获得竞争优势。

战略性地使用它们来与你想工作的公司建立关系,与同行建立信任的交流,并建立你未来的机会。

也要做好准备,人们也可能会接近你。不要因为一个人的知识比你少而拒绝他。作为一名数据科学家,我并不是仅仅通过向他人学习而成长起来的;我最大的收获是给予。

你应该什么时候开始参加 Meetup 会议?从您踏上数据科学之旅的第一步开始!

成功的数据科学家并不是技术更好,也不是证书更多。他们有一个更大的网络。

你喜欢我的故事吗?在这里你可以找到更多。

</10-mistakes-you-should-avoid-as-a-data-science-beginner-ec1b14ea1bcd> [## 作为数据科学初学者应该避免的 10 个错误

towardsdatascience.com](/10-mistakes-you-should-avoid-as-a-data-science-beginner-ec1b14ea1bcd) </5-concrete-real-world-projects-to-build-up-your-data-science-portfolio-ef44509abdd7>

使用 Python 进行实际生存分析

原文:https://towardsdatascience.com/hands-on-survival-analysis-with-python-270fa1e6fb41?source=collection_archive---------6-----------------------

公司能从员工流动数据中学到什么

照片由盒装水更好上 Unsplash

生存分析是一种流行的统计方法,用于调查感兴趣的事件发生之前的预期持续时间。我们可以从医学中回忆起病人的生存时间分析,从工程学中回忆起可靠性分析或无故障时间分析,从经济学中回忆起持续时间分析。

除了这些学科之外,生存分析还可以被人力资源团队用来了解和创造关于他们的员工参与度、保留率和满意度的洞察力——这是当今的一个热门话题🌶 🌶 🌶

根据 Achievers的员工参与度和保留率报告,52%的员工计划在 2021 年寻找新工作,最近一项由 31 个国家的 30,000 多名员工参与的调查显示,40%的员工正在考虑辞职。《福布斯》将这种趋势称为“离职海啸”,主要是由疫情的倦怠和 Linkedin 专家预测大规模人才迁移的到来,并在#大辞职和#大洗牌主题下进行讨论。

一如既往,数据有助于了解员工敬业度&保留率,以减少人员流动,建立更敬业、更投入、更满意的团队。

人力资源团队可以从员工流动数据中挖掘的一些示例如下:

  • 留下/离开的员工的某些特征是什么?
  • 不同员工群体之间的流失率有相似之处吗?
  • 员工在一定时间后离职的概率有多大?(即两年后)

在本文中,我们将构建一个生存分析来帮助回答这些问题。您也可以在我的 GitHub 上查看 Jupyter 笔记本以获得完整的分析。开始吧!☕️

照片由丹妮尔·麦金尼斯在 Unsplash 上拍摄

数据选择👥

我们将使用一个虚构的员工流失率&绩效数据集来探索员工流失率和重要的员工特征,以预测当前员工的生存时间。

背景

在对生存函数建模之前,让我们先了解生存分析背后的一些基本术语和概念。

  • 事件是感兴趣的体验,如生存/死亡或留下/辞职
  • 存活时间是指感兴趣事件发生前的持续时间,即员工离职前的持续时间

审查问题🚫

如果某些个体的事件没有被记录,则删失观察发生在事件时间数据中。这可能是由于两个主要原因:

  • 事件尚未发生(即存活时间未知/对尚未辞职的人具有误导性)
  • 丢失数据(即丢失)或失去联系

有三种类型的审查:

  1. 左删截: 存活持续时间小于观察持续时间
  2. 右删: 生存持续时间大于观察持续时间
  3. 区间-删失: 存活持续时间无法确切定义

最常见的类型是右删失型,通常由生存分析来处理。但是,另外两个可能表明数据中存在问题,可能需要进一步调查。

生存函数

T 是事件发生时, t 是观察期间的任意时间点,生存 S(t)T 大于 t. 的概率,换句话说,生存函数是个体在时间 t. 后存活的概率

S(t) = Pr(T > t)

生存曲线的图示:

个体存活超过 2 年的概率是 60%——图片由作者提供

生存函数的一些重要特征:🔆

  • T ≥ 0 且 0 < t < ∞
  • It is non-increasing
  • If 【 , then 【 (survival probability is 1 at time 0)
  • If 【 ∞, then 【 (survival probability goes to 0 as time goes to infinity

Hazard Function

Hazard function or hazard rate, **和 0h(t)**是存活到时间 t 并且恰好在时间 t 经历感兴趣事件的个体的概率。危险函数和生存函数可以通过下面的公式相互推导。

冒险函数

卡普兰-迈耶估计量

作为一个非参数估计量,Kaplan-Meier 不需要对数据的分布进行初始假设。它还通过从观察到的存活时间计算存活概率来处理右删失观察。它使用来自概率的乘积法则,事实上,它也被称为乘积限估计量。

生存概率作为时间 t

其中:

  • d _ I:t _ I 时刻发生的事件数
  • n_i :存活到时间 t_i 的受试者人数

我们可以认为在时间 t_i 的生存概率等于在先前时间 t_i-1 的生存概率和在时间 t_i 的生存几率百分比的乘积。👇

t=2 的生存概率是 t=1 的生存概率乘以 t=2 时生存的百分比机会。

KMF 的生存函数

我们可以用卡普兰-迈耶钳工模型使用lifelines包。在对数据进行 kmf 拟合时,我们应该指定持续时间(在公司度过的年数)和事件观察值(损耗值:1 或 0)。

from lifelines import KaplanMeierFitter# Initiate and fit
kmf = KaplanMeierFitter()
kmf.fit(durations=df.YearsAtCompany, event_observed=df.Attrition)# Plot the survival function
kmf.survival_function_.plot()
plt.title('Survival Curve estimated with Kaplan-Meier Fitter')
plt.show()

# Print survival probabilities at each year
kmf.survival_function_

时间线一直延续到第 40 年。

我们可以看到,个人在公司存活超过 2 年的概率是 92%,而存活超过 10 年的概率下降到 77%。

我们也可以用置信区间画出生存函数。

# Plot the survival function with confidence intervals
kmf.plot_survival_function()
plt.show()

请注意,较宽的置信区间表明模型在那时不太确定,通常是因为数据点较少。

KMF 不同人群的生存功能

我们可以绘制不同群体(如性别)的生存曲线,看看概率是否会改变。

让我们根据环境满意度栏来做,我们有以下输入:

1= '低'
2= '中等'
3= '高'
4= '非常高'

为了简单起见,我将把“低环境满意度”下的“低”和“中”放在一起,把“高环境满意度”下的“高”和“非常高”放在一起。

# Define the low and high satisfaction
Low = ((df.EnvironmentSatisfaction == 1) | (df.EnvironmentSatisfaction == 2))High = ((df.EnvironmentSatisfaction == 3) | (df.EnvironmentSatisfaction == 4))# Plot the survival function
ax = plt.subplot()kmf = KaplanMeierFitter()
kmf.fit(durations=df[Low].YearsAtCompany,
event_observed=df[Low].Attrition, label='Low Satisfaction')
kmf.survival_function_.plot(ax=ax)kmf.fit(durations=df[High].YearsAtCompany, event_observed=df[High].Attrition, label='High Satisfaction')
kmf.survival_function_.plot(ax=ax)plt.title('Survival Function based on Environmental Satisfaction')
plt.show()

正如我们所见,高环境满意度的个体比低满意度的个体有更高的生存概率。

我们也可以对“性别”和“工作-生活平衡”进行同样的分析。

在上面的工作生活平衡图中,我们可以看到,与工作生活平衡度低的人相比,工作生活平衡度高的人倾向于在公司呆得更久。

然而,在性别情节中,男性和女性的生存曲线几乎是齐头并进的,这使得很难理解是否存在差异。为了研究这个问题,我们可以运行一个对数秩假设检验

零假设表明男性和女性生存曲线是相同的,替代假设表明它们不相同。如果对数秩检验的 p 值低于 0.05,我们可以拒绝零假设。

from lifelines.statistics import logrank_test# Define logrank test
output = logrank_test(
durations_A = df[male].YearsAtCompany,
durations_B = df[female].YearsAtCompany,
event_observed_A = df[male].Attrition,
event_observed_B = df[female].Attrition)output.print_summary

p 值= 0.18

p 值大于 0.05,我们 不拒绝 的零假设。换句话说,我们不拒绝男性和女性生存曲线相同的假设。☑️

如果我们对“工作-生活平衡”进行对数秩检验;我们发现 p 值是 0.04。它低于 0.05,所以我们拒绝零假设。换句话说,我们拒绝低工作-生活和高工作-生活平衡的个体的生存曲线相同的假设。

如果我们有两个以上的组(如低、中、高工作-生活平衡),我们可以使用pairwise_lograng_test()multivariate_logrank_test().

Cox 比例风险模型

Cox-PH 模型是发现个体的存活时间和预测变量之间的关系的回归模型。它适用于分类和数字预测变量。我们将使用 Cox-PH 模型不仅调查哪些因素对生存有高低影响,而且预测当前员工未来的生存概率。

用 Cox-PH 模型预测生存时间

让我们选择一组我们想要研究的列。出于个人好奇,我挑选了以下几个:

columns_selected = ['Attrition', 'EnvironmentSatisfaction', 'JobInvolvement', 'JobLevel', 'JobSatisfaction', 'PercentSalaryHike', 'RelationshipSatisfaction', 'StockOptionLevel', 'TrainingTimesLastYear', 'YearsAtCompany']df = df[columns_selected]

让我们将选择的数据拟合到CoxPHFitter,并指定生存持续时间和事件列。

from lifelines import CoxPHFitter# Initialize and fit the model
coxph = CoxPHFitter()
coxph.fit(df, duration_col='YearsAtCompany', event_col='Attrition')# Print model summary
coxph.print_summary()

模型摘要

在模型总结中,exp(coef)是风险比,它表示由于相应因子的一个单位变化,基线风险变化的程度。例如,如果环境满意度改变一个单位:

  • 危险比率:0.79
  • 危险变化:0.79–1 =-0.21
  • 存活时间变化:(1/0.79)-1 = 0.26 →存活时间增加 26%

模型总结还显示了因素变量的重要性。查看 p 我们可以了解到“加薪百分比”和“关系满意度”并不显著。我们也可以从下面的因素效应图中看到这一点。

# Plot factor effects 
coxph.plot()

因子效应(较低的效应接近于 0)

为了预测员工的生存概率,我们需要创建一个包含当前员工的新数据框架:其中自然减员为 0,数组指定“在公司的年数”。之后,我们可以预测存活时间。我们需要在predict_survival_function中指定在公司工作的年数,以便相应地开始每个人的时间表。

# Current employees
df_new = df.loc[df['Attrition'] == 0]# Years at the company of current employees
df_new_obs = df_new['YearsAtCompany']# Predict survival probabilities 
coxph.predict_survival_function(df_new,conditional_after=df_new_obs)

预测—列是员工,索引是时间线

员工 1 在 10 年后的预计生存概率是 80%,而员工 4 的生存概率是 53%

像其他回归模型一样,Cox-PH 模型也对数据进行初始假设。为了检查假设是否成立,我们可以使用check_assumptions.

# Check the Cox-PH model assumptions
coxph.check_assumptions(df)

比例风险假设看起来不错。

我们很好!🌴

否则,我们可能需要操纵一些变量。

结论

在这篇文章中,我们回答了一些公司可能会有的关于他们的员工特征和对自然减员的影响的重要问题。我们使用 Kaplan-Meier fitter 计算并绘制生存概率,使用 Cox-PH 模型预测当前员工未来几年的生存概率。这些预测非常有见地,因为它们让我们知道哪些因素降低和增加了生存概率,以及谁是短期内处于风险中的员工。利用这些预测,公司可以付出额外的努力来防止员工流失,并最终建立更积极、更高效、更快乐的团队!🙌

奖金

我们已经了解了如何分析不同群体之间生存曲线的差异。我们可以在 A/B 测试中使用这个特性——在这里我们可以调查一个新的特性/变化是否会导致存活率的显著变化。

如果你对 A/B 测试感兴趣,你可以阅读我下面的文章🌠

我希望你喜欢阅读生存分析,并发现这篇文章对你的分析有用!

如果你喜欢这篇文章,你可以 在这里阅读我的其他文章和* 关注我上媒*如果有任何问题或建议,请告诉我。✨

喜欢这篇文章吗? 成为会员求更!

参考

  1. 劳动力研究所——2021 年雇佣和保留报告

  2. 微软调查

  3. Linkedin——伟大的辞呈在这里

  4. 救生索包

条形图动画制作完全指南

原文:https://towardsdatascience.com/hands-on-tutorial-f2ee5dc4d0a8?source=collection_archive---------25-----------------------

制作两种不同风格的条形图动画的分步指南

作者图片

图和信息图形式的数据可视化是传达故事的方式。如果这些故事有实质内容并且不言自明,那么它们对大众是有吸引力的。信息图或演示之所以比单纯的情节更受欢迎,是因为它们传达了一个故事,并且是自给自足的。情节只讲述了故事的一部分。为了使情节更有意义,人们可以将一系列的情节堆叠在一起,或者堆叠一系列的情节来创建动画。一个很好的例子是由汉斯·罗斯林创作的动画,其中他比较了预期寿命和收入。

在这里,我将使用 1960 年至 2019 年间 10 个最大国家的 GDP 支出数据创建一个条形图竞赛。本教程的重点是:

  1. 使用 GDP 支出数据创建从 1960 年到 2019 年每个财年前 10 个国家 GDP 的动画。
  2. 清楚地展示如何提高默认ggplot图的质量。
  3. 提供创建两种不同风格的竞赛条形图的步骤。

我们将创建两种不同风格的条形图比赛,一个具有固定轴,另一个具有动态轴。完整的代码可以在我的 Github 库中找到。

创建条形图比赛动画的灵感来自约翰·伯恩-默多克的推特帖子,他在那里制作了世界上人口最多的 10 个城市的动画。在本教程中,条形图比赛动画是使用世界银行的世界 GDP 数据重新创建的。

数据准备

如果您打开数据文件,您会注意到相关的列从第 5 行开始。所以你需要去掉前四行。要么我们可以手动删除它们,要么我们可以在读取 CSV 文件时编写一个参数,让计算机为您删除它们。让我们走后一条路。要读取 CSV 文件,加载readr包,并使用函数read.csv()skip = 4参数跳过文件的前四行。数据由国家名称、国家代码和 GDP 值组成。为了确保国家名称和国家代码列属于 string 类,我们将参数设置为stringsAsFactors = False

gdp <- read.csv("C:/Users/amalasi/Documents/R/Blog post/Blog 14-animate/GDP/GDP.csv", 
                skip = 4,stringsAsFactors = F)

在预览gdp变量时,我们注意到一些列是多余的,可以删除。因为我们对使用时间索引创建动画感兴趣,所以我们需要将当前数据表从宽到长重新排列,以增加包含年份和 GDP 值的列。使用tidyr包中的gather()函数,一个新变量gdp_long被定义为两个名为 YearGDP_dollar 的新列(GDP 值以美元为单位)。

作者图片

# removing reduncdant columns
gdp %<>% select(-c(2:4,65,66))# converting the wide table to long
gdp_long <- gdp %>% gather(Year,GDP_dollar,c(2:61))

将数据转换为长格式后,列值显示年值前的 X 。为了去掉 X ,我们将使用gsub()函数。我们调用gsub()函数,第一个参数是我们想要替换的字符串,第二个参数是我们想要替换的字符串,第三个参数是动作发生的数据。我们使用as.integer()函数将列转换为整数。这种到整数变量的转换将在以后制作动画时派上用场。

gdp_long$Year <- as.integer(gsub("X","",gdp_long$Year))

最后一个清理步骤是从国家中删除几个特定值。名称列。国家有几个值。Name 代表一组国家或地区的列,如阿拉伯世界、加勒比海小国、中欧和波罗的海、海峡群岛等。最好的方法是使用国家的标准 ISO 代码来删除不需要的数据。由于所有的国家都被分配了一个 ISO 代码,我们可以利用它。为此,我们将使用countrycode包中的countrycode()函数。使用mutate()函数定义了一个名为 Code 的新变量。要将国家名称转换成 ISO 代码,第一个参数是我们想要处理的数据。对于当前情况,发送的数据是国家名称,因此countrycode()的第二个参数将被设置为country.name,第三个参数将被设置为iso3c。这样做的目的是将国家名称转换成 3 个字母的国家代码。

gdp_long %>% mutate(Code = countrycode(gdp_long$Country.Name,
                                            "country.name","iso3c"))

所有不必要的地区或国家集群没有 ISO 代码,将被赋予NA值。我们现在可以过滤数据,删除不必要的数据。

gdp_long %>% mutate(Code = countrycode(gdp_long$Country.Name,
                                            "country.name","iso3c")) %>% 
  filter(!is.na(Code))

对于动画来说,我们需要以某种方式排列数据。我们首先将数据按年份分组,并按 GDP 支出的降序排列。rank()函数中的负号按降序排列 GDP_dollar 值。我们定义了一个新的变量,通过将 GDP 值除以 10⁹,将 GDP 值转换为十亿美元。最后一步是过滤数据,提取 GDP 支出最高的前 10 个国家,并取消数据分组。

c <- gdp_long %>% mutate(Code = countrycode(gdp_long$Country.Name,
                                            "country.name","iso3c")) %>% 
  filter(!is.na(Code)) %>%
  group_by(Year) %>% 
  mutate(top_10 = rank(-GDP_dollar), GDP_bil_dol = GDP_dollar/1e9) %>% 
  group_by(Country.Name) %>% 
  filter(top_10 <= 10) %>% 
  ungroup()

静态条形图

在数据准备之后,让我们创建一个静态图,以确保我们的图中有我们想要的一切。要创建动画帧,请将数据过滤到年份= 1960,以绘制 GDP 支出排名前 10 位的国家。

c %>% filter(Year==1960) %>% 
  ggplot(aes(desc(top_10),GDP_bil_dol, fill = Country.Name)) +
  geom_bar(stat = "identity", alpha = 0.3) +
  coord_flip()

作者图片

所以,我们有一个需要润色的柱状图。我们能做的改善情节外观的几件事是去除灰色背景和图例。添加描述性文本,使其不言自明,并增加字体大小。

我们可以做的第一件事是使用theme_set()函数改变ggplot的主题。如果有兴趣了解更多关于 R 中的 theme()函数的信息,请查看这篇文章。

geom_text(aes(y=ifelse(GDP_bil_dol<1000, 500,GDP_bil_dol/2),
                label = paste0(Country.Name,": ",round(GDP_bil_dol,1)," bn USD"), 
                hjust = 0),color = "gray30") +
  theme(panel.grid = element_blank(),
        legend.position = "none",
        axis.title = element_text(size = 12),
        axis.title.x = element_text(vjust = -1.5),
        axis.text.y = element_blank(),
        axis.ticks.y = element_blank(),
        axis.text.x = element_text(family = "Roboto", size = 12),
        plot.subtitle = element_text(size = 12),
        plot.caption = element_text(size = 10, face = "italic")
        ) + 
  labs(x="", y="GDP, bn USD", caption = " Data: World Bank") +
  ggtitle("Global GDP Ranking", subtitle = "Top 10 ranked countries for year: {frame_time}") 

我们所做的是过滤数据并绘制出 1960 年前 10 个 GDP 值。这里是添加到ggplot的图层列表以及使用它们背后的想法。

在绘图面板中添加文本时,geom_text() 很有用。为了在条形旁边显示 GDP 值,使用 ifelse语句定义 y 坐标,因为文本的长度可以变化。我想确保文本保持在大 GDP 值的绘图边界内。为此,我将 GDP 的临界值定义为 1000。对于低于 1000 的 GDP 值,从 500 值开始打印文本,否则从当前 GDP 值的中点开始打印。然后使用paste0()函数定义标签,因为我想将运行变量与预定义文本合并。接下来,我使用hjust = 0来确保文本不会从绘图的左边界超出绘图区域。最后,选择color = "gray30"来匹配轴刻度的颜色。

theme() :使用 theme 函数,我们负责字体大小、字体类型、颜色,如果我们想要网格线、主要和次要刻度、图例、调整文本等。

labs() :所有的轴标题和标题都是用这个函数定义的。

ggtitle() :我用这个函数定义了剧情的标题和副标题。 {frame_time} 来自gganimate包,将显示运行时间指数。

在最终确定了情节的美感之后,我们将完整的情节表达分配给一个对象xx。一旦这一步完成,我们就可以制作情节动画了。

xx <- c %>% group_by(Year) %>% 
  ggplot(aes(y = desc(top_10),x = GDP_bil_dol)) +
  geom_barh(stat = "identity", aes(fill = Country.Name),alpha = 0.3) +
  geom_text(aes(x=GDP_bil_dol/2,label = paste0(Country.Name,": ",round(GDP_bil_dol,1)," bn USD"), 
                hjust=0), color = "gray30") +
  theme(panel.grid = element_blank(),
        legend.position = "none",
        axis.title = element_text(size = 12),
        axis.title.x = element_text(vjust=-1.5),
        axis.text.y = element_blank(),
        axis.ticks.y = element_blank(),
        axis.text.x = element_text(family = "Roboto", size = 12),
        plot.subtitle = element_text(size = 12),
        plot.caption = element_text(size = 10, face = "italic")
  ) + 
  labs(y="", x="GDP, bn USD") +
  ggtitle("Global GDP Ranking", subtitle = "Top 10 ranked countries for year: {frame_time}") + labs(caption = " Data: World Bank")

制作条形图动画

我们有两种可能来激活条形图。在第一种情况下,我们保持轴不变,让棒线随着时间增长。为此,我们需要加载gganimate包,并开始向 ggplot 函数添加层。通过添加transition_time()层,ggplot 函数知道哪个变量是运行指数。transition_time()的参数是定义时间索引的变量,在我们的例子中,它是列。我们定义了一个新的对象p2,并为它分配了更新后的动画参数。

p2 <- xx + transition_time(Year)

一旦定义了过渡时间,我们可以使用animate()函数创建一个 gif 动画。

带固定轴的动画(图片由作者提供)

第二种情况是,具有 GDP 值的轴随着时间的推移自动调整。我们为第一种情况添加了另一层代码,使用固定的轴。该层由来自gganimate包的view_follow()函数组成。view_follow()功能让您定义哪个轴需要是动态的。默认值设置为两个轴都是动态的。要仅设置一个轴动态,我们可以将参数设置为fixed_x = TRUE。这样view_follow()功能知道 x 轴是固定的。同样,我们可以通过设置参数fixed_y = TRUE来设置 y 轴。我们可以使用参数fixed_x = c(0, NA)设置动态轴的起始范围(类似于 y 轴)。取决于数据,向量中的第一个值可以是任何起始值,但最终值必须是NA。用户也可以使用ease_aes()功能来定义运行动画时数值如何变化。

p2 <- xx + transition_time(Year) + 
  # ease_aes('linear', interval = 0.1) +
  view_follow(fixed_x = c(0,NA), fixed_y = TRUE)

在创建 gif 时,我们可以在animate()函数中提供参数来定义nframesfpsnframes为帧数(默认为 100),而fps为每秒显示帧数的帧率(默认为 10 fps)。

# if using magick for saving gif files
anim <- animate(p2, nframes = 240, fps = 10)# using gganimate for saving gif files
animate(p2, nframes = 240, fps = 10)

在使用 view_follow()运行修改后的代码时,我们看到轴刻度上的数据在闪烁,轴标题正在交换位置,如下所示。

作者图片

由于view_follow()功能与coord_flip()不兼容,所以出现了问题。此的修正是不使用coord_flip()并手动切换 ggplot 美学中的 x 轴和 y 轴或使用ggstance()包中的geom_barh()

修复这个问题后,动画 gif 应该是这样的。

动态 x 轴(图片由作者提供)

保存动画

生成的 gif 文件可以使用magick包或gganimate包保存。

# using magick packagemagick::image_write(anim, path="myanimation.gif")# using gganimate package
anim_save("myanimation.gif")

下面是创建这两个动画 gif 的完整代码。

结论

在上面的教程中,我们实现了:

  1. 从 GDP 数据创建 gif 文件。
  2. 改进了默认的绘图质量。
  3. 展示了为相同数据创建 gif 文件的两种不同方法。
  4. 找到了一个解决同时使用view_follow()coord_flip()的限制的方法。

我希望你喜欢这个关于创建动画条形图的简短教程。最好的方法是探索 gganimate 来测试可以使用 r 创建的动画的极限。

对使用 ggplot 创建地块感兴趣,请查看以下帖子:

链接到 Github 库。

你可以在LinkedInTwitter上与我连线,跟随我的数据科学和数据可视化之旅。

用于数据处理的便捷 Python 模块

原文:https://towardsdatascience.com/handy-dandy-python-modules-for-data-processing-3a85d6806d39?source=collection_archive---------8-----------------------

一些我最喜欢的 Python 数据处理模块,你可能不知道

https://pixabay.com/images/id-2167835/

介绍

用于数据操作的 Python 模块——大多数数据科学家可能知道用于此目的的标准工具。我们如此习惯于把熊猫作为 pd 导入,以至于在这一点上我们不用键盘或鼠标也能做到。虽然我们通常用来操作和处理数据的标准工具当然是一套很好的工具,但实际上在 Pythonic 数据科学生态系统中还有更多模块可供我们使用。这个生态系统非常庞大,在 Python 包索引(PIP)中有超过 300,000 个注册包。请让您的朋友 PIP 做好准备,因为您将想要添加这些令人兴奋的软件包来增强您的数据处理工作流程!

笔记本

数字计算器

一个相当有趣的 Python 模块是一个叫做 numerizer 的小模块。numerizer 模块有一个非常简单的目的,那就是将字符串形式的数字转换成整数。在很多情况下,这可能非常有用,但我发现这个模块最有用的领域很可能是自然语言处理。也就是说,我可以肯定地看到,这也适用于数据框中的一些字符串数据,由于某种原因,这些数据被存储为单词而不是数字。我们都知道这是怎么回事,数据是不可预测的。幸运的是,大量的 Python 工具(如 Numerizer)通常在这方面为我们提供了帮助!

sudo pip install numerizerfrom numerizer import numerize
print(numerize('one two three'))
print(numerize('One Hundred and five'))
print(numerize('twenty point one'))
print(numerize('six and three fifths'))
print(numerize('one quarter'))
print(numerize('one million billion'))

作者图片

骗子

在我的数据科学职业生涯中,有很多情况下我需要构建一个原型或概念证明,但却找不到任何基础数据来处理。没必要害怕,因为 Faker 模块在这里!Faker 模块可用于快速有效地生成各种伪造数据。我决定用它来生成一个新的熊猫数据框架:

sudo pip install fakerfrom faker import Faker
import pandas as pd
fake = Faker()

注意,我们必须初始化 Faker()类。

df = pd.DataFrame({"Name" : [fake.name() for x in range(1, 200)],
                   "Website" : [fake.url() for x in range(1, 200)]
                  })
df.head(20)

作者图片

我想我真的认识一个叫凯瑟琳·邓恩的人,她是我的高中同学,所以这很现实。不确定她是否有一个叫 cunningham.com 的网站。

缺少编号

Missingno 是一个简单但非常棒的库,可以在缺少值时快速评估数据的健康状况。这个软件包的独特之处在于,它提供了一个矩阵,可以形象地显示您丢失了多少数据。

sudo pip install missingno
import missingno as mi
import numpy as npdf = pd.DataFrame({"A" : [5, np.NaN, 10, np.NaN], 
                  "B" : ["eight", "seven", "two", "three"]})mi.matrix(df, figsize = (10,5));

作者图片

情感

Emot 是一个 Python 模块,可以非常有效地用于从表情符号中获取真实数据。随着表情符号的流行,这一点变得更加重要。我们可以利用这个模块进行情感分析和一般的自然语言处理。这个模块将从本质上改变我们的表情符号的文本到他们做什么的描述。这将允许算法实际分析文本的这些部分,并寻找一致性。

sudo pip install emot
import re
from emot.emo_unicode import UNICODE_EMO, EMOTICONS
def convert_emoticons(text):
    for emot in EMOTICONS:
        text = re.sub(u'('+emot+')', "_".join(EMOTICONS[emot].replace(",","").split()), text)
    return textconvert_emoticons("Hi :3, how are you? :P")

作者图片

不确定第二个需要包含“_ 或 _ 吹 _ 一个 _ 覆盆子”。奇怪。

枕头

Pillow 是一个非常基本且易于使用的 Python 图像处理模块。不用说,可能有一千种不同的情况,这可能会派上用场。这个模块最好的部分是,它仍然在大多数方面保持相对用户友好!

sudo pip install pillow
import pillow as pil
im = pil.Image.open("logo.png")
im.show()

至少对我来说,这使用了 xgd-open 来打开我的系统的图像查看器。也很奇怪。

im.rotate(45)

作者图片

Python 有很多非常棒的 datetime 模块。比如 datetime 模块(讽刺地读那个。)当然还有 datetime 类型的 Pandas 实现,我认为这是我最常使用的,也是最值得注意的。然而,我发现很多这种类型有时仍然有点乏味,Pandas 实现可能是最好的…也就是说..除了 Arrow!Arrow 是一个模块,它为 Python 语言提供了一些更好的日期时间功能。这个包的另一个很酷的特性是“人性化”功能,我实际上已经使用过了!请允许我解释。当我比现在年轻很多的时候,我在学校有一个创建在线聊天应用程序的任务,为此我使用了 Django。我使用了人性化功能,以便将我的计算机语言和不太人性化的时间转换成我们实际上可以在对话中说的简单短语。

sudo pip install arrow
import arrow
utc = arrow.utcnow()
local = utc.to('US/Eastern')
local.humanize()

作者图片

我们甚至可以通过使用本地关键字参数来更改语言!

local.humanize(locale='fr')

作者图片

结论

使用 Python 编程语言的最大好处之一是,无论出于何种目的,通常都有一个工具可以完成。进一步说,Python 生态系统是如此之大,以至于学习新的包是 Python 程序员的一个持续的乐趣来源。很有可能你还没有听说过这个列表中的每一个模块,这正说明了人类可能学不完的东西。当然,这是好事,不是坏事!数据科学领域或 web 开发领域也有很多优秀的数据处理工具。不用说,显而易见,为什么 Python 是程序员和数据科学家中最受欢迎的选择。感谢您阅读我的文章,我希望它能帮助您学习一些有用的新模块!

基于图形嵌入的硬件加速余弦相似度

原文:https://towardsdatascience.com/hardware-accelerated-cosine-similarity-with-graph-embeddings-521d725d0e86?source=collection_archive---------32-----------------------

使用 TigerGraph 图形数据科学库

许多行业都普遍需要高质量和快速的推荐,如医疗保健、零售和娱乐。这些推荐应该能够考虑不同的数据来源,比如用户的朋友、兴趣、位置等等。

TigerGraph 是能够存储大量用户信息并对其进行实时分析的主要候选产品。在此示例中,使用了国家提供商标识符(NPI)分类数据。该数据包含所有医疗保健提供者及其专业,如麻醉学或肿瘤学。这些专业被组织在一个分类树中,因此一个儿科麻醉学分类单元属于更一般的麻醉学分类单元。提供者和分类法都被加载到 TigerGraph 中,以便使用嵌入和余弦相似性来执行提供者相似性计算。提供者之间的相似性分数是基于他们在专业树中的位置来确定的。

例如,两个在麻醉学分类下有子专业的提供者比一个是儿科麻醉师和另一个是全科儿科医师的提供者更相似。余弦相似性过程随后通过使用 HPE 参考架构中的 Xilinx Alveo U50 数据中心加速卡进行加速图形分析。进一步的实现细节可以在 GitHub 库中找到。

数据流概述(图片由作者提供)

嵌入将高维数据转换到低维空间。例如,所有地图都是地球的嵌入图,将 3D 空间转换为 2D 空间。图形嵌入技术将一个非常高维的空间(图形中的顶点数)转化为开发人员选择的低维向量(通常在 100-500 维左右)。降维是有益的,原因有两个:稀疏的高维数据对于机器学习算法来说更难解释并做出良好的预测,并且通过使用密集的低维表示可以显著改善时间和内存。此外,嵌入技术不需要耗时且昂贵的人工特征创建来进行机器学习。相反,嵌入算法会自动确定如何最好地表示低维空间中的数据。这使得数据科学家能够花费更少的时间清理和手动构建数据中的要素。

专业分类摘录(图片由作者提供)

GraphStudio 中的数据示例。紫色顶点是提供者专业,而绿色顶点代表提供者。(图片由作者提供)

FastRP 图嵌入算法用于创建表示 NPI 数据库中每个提供者和分类代码的嵌入。FastRP 使用一种称为随机投影的技术,其中矩阵稀疏地填充随机值。这个矩阵是维度 NxD,其中 N 是数据的原始维度,D 是降维后的维度。将邻接矩阵(维数为 N)乘以随机矩阵得到每个顶点的 D 维表示,这就是顶点的嵌入。TigerGraph 通过消息传递算法实现这种乘法。在 TigerGraph 图形数据科学 Github 资源库中查看 FastRP。

一旦为每个顶点创建了嵌入,我们希望使用余弦相似性来比较它们。在这种情况下,使用 FastRP 创建了 200 维嵌入,目标是在给定一个输入提供者的情况下获得 10 个最相似的提供者。这个过程需要比较一个嵌入和 530 万个其他嵌入之间的余弦相似性得分。TigerGraph 可以使用图形数据科学库中的嵌入相似性代码在数据库中完成这项工作,但也可以与 Xilinx 加速卡结合使用。这些 FPGAs 可以在其高带宽存储器中缓存嵌入,并以高度并行的方式计算输入提供者和所有其他提供者之间的余弦相似性。

FPGA 实现的这种高度并行性带来了大约 1300 倍的性能提升。非加速性能仍然令人钦佩,但如果需要实时提供建议,例如在网站加载期间,或者在患者与医疗保健提供商互动期间,FPGA 加速可以大规模实现这种实时功能。

给定目标嵌入,找到前 10 个相似嵌入的平均时间(图片由作者提供)

这种方法的一些扩展包括在其他机器学习算法中使用余弦相似性作为距离度量,例如用于分类的 k-最近邻和用于图形内顶点的无监督聚类的 k-均值。此外,嵌入和余弦相似性加速可以用于推荐算法,例如协同过滤。将来,可以使用诸如图形神经网络之类的更先进和精确的嵌入方法来生成嵌入,然后可以使用硬件加速的相同流水线来比较它们。

这里介绍的算法和演示只是 TigerGraph 正在研究的可扩展图形机器学习方法的开始。很快,将发布 TigerGraph 机器学习工作台,使数据科学家能够轻松连接到他们的 TigerGraph 实例,运行他们喜欢的图形算法,并使用 Python 和 Jupyter 笔记本训练图形神经网络。我们还将建立一个像这样的教程和演示库,以展示图形算法、图形特征工程和图形机器学习的可能性。有想法或反馈?伸出手去tgds-feedback@tigergraph.com。

资源:

【https://github.com/TigerGraph-DevLabs/provider-similarity】医疗保健提供商相似性知识库:

TigerGraph 图形数据科学库:https://github.com/tigergraph/gsql-graph-algorithms

本演示图+AI 峰会录制:https://info . tiger Graph . com/Graph-AI-Summit-fall-session-using-Graph

Xilinx with tiger graph:https://www . Xilinx . com/products/acceleration-solutions/tiger graph . html

加速图分析的 HPE 参考架构:【https://www.hpe.com/psnow/doc/a50004892enw?】T22section=Document%20Types

收获互信息的力量,在你的 NLP 数据集中发现偏差

原文:https://towardsdatascience.com/harvesting-the-power-of-mutual-information-to-find-bias-in-your-nlp-dataset-c172c0dddebe?source=collection_archive---------27-----------------------

直观的数学介绍

局部互信息来发现 NLP 数据集中有偏见的术语,以及为什么它应该优先于逐点互信息

文森特·莱德维纳在 Unsplash 上拍摄的照片

[在我的上一篇文章中,我试图了解 NLP 中有偏见数据集的一些不同原因。请随意去看一看,因为这篇文章是在它的基础上构建的!]

如前所述,当某些术语与某个特定标签相关联时,数据集往往会有偏差。我们在这些数据集上训练的模型开始捕捉这种关联,当这些术语的上下文颠倒时,表现很差。例如,一个模型已经看到了术语在“仇恨”推文中的用法,将偏向预测任何包含该术语的新推文为“仇恨”而不是“非仇恨”。

在本文中,我将进一步隔离数据集中最有可能引入偏差的术语。

识别有偏见术语的 2 个指标

我将通过互信息的两个常见衍生来量化术语与标签的相关性。

逐点互信息(PMI)

让我们逐一剖析这个等式,并尝试理解为什么 PMI 有助于找到术语-标签相关性:

  1. p (术语|标签):给出我们看到术语出现在属于标签的样本(或推文或文档,选择你最喜欢的)中的概率
  2. p (术语):给出在任何样本中看到一个术语的概率(即跨越所有标签)
  3. 日志:为了更好的理解,让我们简化日志

可能有两种情况值得关注

  • p(term | label)>p(term):当项相对于整个数据集 更有可能出现在标签的样本中时,项与*标签正相关。在这种情况下,得出的 PMI 也将是***
  • p (项|标签)< p (项):当项与整个数据集 相比,在标签样本中出现的可能性较低时,项与标签负相关。在这种情况下,得出的 PMI 将是负的**

因此,我们看到 PMI 捕捉到了术语-标签相关性的影响。

我们用一些例子来了解一下。

  • “最差”两个标签的 PMI 值都为 0,因为它的出现不会给出任何关于标签可能是什么的信息
  • “愚蠢”为仇恨标签获得正值,因为它只出现在该标签中
    ,为非仇恨标签获得负值,因为它从未出现在该标签中

  • 对于仇恨标签,“最坏”获得的 PMI 低于“愚蠢”,因为它出现在较少的仇恨样本中;对于这个标签,两个术语都获得正值,因为两个术语都与其相关度高于另一个标签
  • 对于非仇恨标签,“最坏”比“愚蠢”获得更高的 PMI,因为“愚蠢”与仇恨标签更密切相关

等等,你发现这个例子有问题吗?我们在“最差”和“愚蠢”这两个词上得到了相同的分数,因为这两个词都与憎恨这个标签密切相关。但是我认为这不公平因为“最坏”在整个数据集中只出现一次!这是很糟糕的,因为一个词在整个数据集中只出现一次就可能成为最有倾向性的词。

作为一个具体的例子,我在来自(Basile 等人,2019 年)的仇恨言论检测数据集(Hateval)上找到了仇恨标签的前 15 个有偏见的术语。经过检查,我发现所有这些术语都带有相同的 PMI 值,因为它们只出现在这个标签上。请注意,该列表还包含许多拼写错误,这些错误很可能在整个数据集中只出现一次!

当地共同信息(LMI):一个重新加权的采购经理人指数

我们刚刚看到了 PMI 的一个重要警告:它可能无法解释术语频率,给数据集中很少出现的术语赋予很高的权重,如许多拼写错误。

解决办法是重新加权 PMI 值。

LMI 的 PMI 是根据任期发生率调整的

  1. p (术语,标签):为调整系数

请注意,每一项的分母都是常数,但分子直接取决于该项的频率。这就是我们一直在寻找的缺失部分。

重新调整示例 3 使用 LMI,现在术语“最坏”被正确地分配了比更频繁的“愚蠢”小得多的值。

将 LMI 应用到前面的具体例子中,最具偏见的憎恨标签的术语实际上是如此的可恶,以至于我不得不将它们探测出来👶

下一步是什么

在本文中,我们看到了如何在我们的 NLP 数据集中分离出引起偏见的术语。既然我们知道了谁是我们的敌人,我们可以开始计划如何打败它了,⚔️

AI 是不是已经走进死胡同了?

原文:https://towardsdatascience.com/has-ai-hit-a-dead-end-897dbeeb6ab5?source=collection_archive---------8-----------------------

意见

一个新的 AI 冬天要来了,和 AI 无关

乔纳森·法伯在 Unsplash 上拍摄的照片

围绕人工智能(AI)及其子领域(机器学习、深度学习等)有很多炒作。)已经有相当一段时间了。然而,我们可能正处于另一个人工智能冬天的边缘——这是一个人工智能研究资金和兴趣减少的时期——尽管算法和基础设施取得了重大进展,即使我们拥有大量的信息和数据。

尽管算法和基础设施取得了巨大进步,尽管我们拥有大量的信息和数据,但我们可能正处于另一个人工智能冬天的边缘。

然而,AI 本身并不对这种失望负责。这一次,技术正进入幻灭的低谷,因为我们不知道如何从中受益。我们还没有一个强大的方法将突破性的研究想法转化为实际应用。

是的,许多算法已经“毕业”,消费者甚至在没有注意到的情况下使用它们,但是,将模型投入生产仍然是艰巨的。从学术背景来看,我很清楚这个问题:是时候开始开发解决方案了,而不仅仅是原型。

学习率是为那些对 AI 和 MLOps 的世界感到好奇的人准备的时事通讯。你会在每周五收到我关于最新人工智能新闻和文章的更新和想法。在这里订阅!

红旗

冠状病毒的爆发让我们措手不及。技术,尤其是人工智能领域,没有达到投资者和政策制定者的预期,不是因为我们投资不够,而是因为我们没有有效投资。不要只资助研究;基金解决方案公司的伊兰·古尔在他的《麻省理工科技评论》文章“美国如何在创新上迷失方向”中说道。

事实上,尽管我们可以利用人工智能来帮助我们预防、诊断甚至治疗像新冠肺炎这样的疾病,但在中国爆发近两年后,我们只是谈论想法和开发解决方案的原型。

此外,试图利用公众恐慌的人发现初创公司的方法和产品有问题。Elise Reuter 在为 MedCity News 撰写的文章中警告说,为疫情提出了数百种人工智能解决方案,但很少得到证实。

我们即将失去这个展示人工智能的力量和价值的大好机会,这不仅是一种耻辱,还可能让投资者在未来更加怀疑。

毫无疑问,当涉及到医疗领域的机器学习时,我们应该格外小心;然而,我们现在并没有比一年前更接近于部署辅助机器学习解决方案。我们即将失去这个展示人工智能的力量和价值的绝佳机会,这不仅是一种耻辱,还可能让投资者在未来更加怀疑。

未决问题

现在,我们已经定义了问题,并目睹了我们在疫情期间的反射反应不佳,让我们看看我们可以做些什么。

关注未来

我们的研究议程停留在过去十年有意义的研究重点和方法上。世界正以前所未有的速度前进。例如,在气候变化这样的问题上几乎没有做什么。我们应该如何处理核废料?如何让可持续能源满足当今的需求?我们应该如何为即将到来的风暴做准备,减轻其影响并调整我们的经济?

与此同时,我们应该研究方法,让我们能够更快地弥合研究和产业之间的差距,找到人工智能和基础设施之间的最佳结合点,以更快地将想法转化为实际应用。

目前有一些项目正在解决这些问题(例如 Kubeflow 或 AWS Sagemaker)。然而,我们应该更快地行动,让更多的声音参与对话,并将我们的注意力集中在这些努力上。

这些问题是我们不能通过稍微调整电子表格中的研究预算来解决的。我们应该删除文件,从头开始。我们应该改变我们的思维方式,设计一个新的行动方案。

提供不同的激励

人工智能和机器学习领域的突破大多来自研究人员,他们的职业生涯取决于他们撰写的出版物数量和他们在会议上的陈述。通常,为了通过一篇论文,研究人员试图将一些基准测试的结果提高几个小数点。

这种进行研究的方式很少能推动创新。如果我们期望有意义和可应用的结果,我们不应该太在意新的 Imagenet 最先进的模型是否超过旧模型 0.5%。不要误会我的意思,这可能是一个令人印象深刻的结果,需要大量的思考。但我们也应该考虑如何把它投入生产。如何直接利用一个新的好主意。这方面的一个例子是 OpenAI 的新 API,你可以在下面的故事中读到更多。

最后,如果我们想要不同的、更切实的结果,我们应该提供不同的激励。

改变研究剧本

我认为创业公司和大学衍生公司是推动创新和提供当今人工智能实用解决方案的主导力量之一。因此,也许是时候开始资助这些企业了,不仅作为研究框架的一部分,也作为个体实体。

通过这种方式,我们可以让知道如何实现技术的业界人士更接近研究人员。总而言之,我们应该克服对资助行业研究的厌恶。

结论

在这个故事中,我认为一个新的人工智能冬天即将到来,这一次,它与人工智能无关。标准已经存在,机器学习和深度学习已经提供了伟大的想法,我们今天可以投入生产。

为了实现这一目标,我们需要做出一些改变:着眼于未来,为研究人员提供不同的激励,并改变资助策略。我们不应该让 AI 进入另一个死胡同。

关于作者

我叫 Dimitris Poulopoulos ,我是一名为 Arrikto 工作的机器学习工程师。我曾为欧洲委员会、欧盟统计局、国际货币基金组织、欧洲央行、经合组织和宜家等主要客户设计和实施过人工智能和软件解决方案。

如果你有兴趣阅读更多关于机器学习、深度学习、数据科学和数据操作的帖子,请关注我的 Medium 、 LinkedIn 或 Twitter 上的 @james2pl 。

所表达的观点仅代表我个人,并不代表我的雇主的观点或意见。

DevOps 是否扼杀了 BA/QA/DBA 角色?

原文:https://towardsdatascience.com/has-devops-killed-the-ba-qa-dba-roles-fbc187abdde?source=collection_archive---------0-----------------------

看看软件开发人员如何承担更多的责任,这对传统的技术角色意味着什么

彼得·冈博斯在 Unsplash 上拍摄的照片

从历史上看,IT 部门是跨技术线构建的,如应用程序、UX 和数据库团队。最近, 2-pizza DevOps 团队已经出现,并围绕业务线宣传重组。现在,单个团队负责端到端的特定业务功能。这开启了全栈开发人员的时代——可以为系统的任何方面做出贡献的工程师。数据库连接丢失?开发人员正在调查此事。基础设施瘫痪?戴夫正在处理。

随着开发人员的职责范围扩大,BA/QA/DBA 等传统技术工作还剩下什么?在 DevOps 时代,他们还有作用吗?

商业分析师

业务分析师是用户和技术团队之间的混合角色。开发者),CIO.com 描述如下:

业务分析师(BAs)负责使用数据分析来评估流程,确定需求,并向高管和利益相关者提供数据驱动的建议和报告,从而弥合 IT 和业务之间的差距(来源)。

根据美国劳工统计局的数据,英国航空公司的就业前景预计在未来十年增长 11%。尽管有这样的增长,许多开发人员认为 BA 角色在 DevOps 复兴之后已经过时,基本上是多余的。

针对 BAs 的案件

针对 BAs 的案例在这个办公空间的经典场景中得到了完美的总结。

来自办公空间的这个剪辑形成了反对 BAs 的争论的症结,并且可能不公平地使许多开发人员对业务分析师产生偏见。

英国航空公司的工作本来就很困难。他们是技术熟练的开发人员和领域熟练的用户之间的中间人。不知何故,人们期望助理能与两者的专业知识相匹配,在他们的直接沟通中进行调解,并凭空变出额外的价值——哎呀。

当 BA 出问题时,通常是组织出了问题,BA 转变为中继。换句话说,BA 只是把所有用户的问题都推给了开发者,反之亦然。对于一个开发者来说,给建筑协会发一封电子邮件,却收到一字不差的抄送,这是很烦人的。当电子邮件缺乏上下文、截图或任何其他 BA 应该捕捉到的明显信息时,这就更令人恼火了。当这种情况再次出现时,我只是直接与用户交谈。

BAs 的案例

此时,您可能会想“为什么开发人员不总是与用户交流?”。当然,这是一种选择。例如,在初创公司中,可能没有理由需要 BAs。但是随着组织、应用程序和团队的成长,开发人员和用户之间的反馈环也在增长。当然,与用户的一次性聊天是好的,但实际上能为此节省多少时间呢?例如,您是否经常与几十个用户建立电话来审查功能请求?一个好的 BA 应该每天花几个小时与几十个用户交谈,建立一个网络和融洽的关系。通过这种方式,BAs 获得了对系统的整体理解,例如,一个屏幕对一个团队来说很好,但对另一个团队来说就不好了。只有在他们整理了这些信息之后,他们才应该把它们交给开发人员。开发人员应该参与到与 BAs 和用户的讨论中,但只能以预先计划好的系统方式进行。

作为开发人员,我们并不总是对我们的资源有多贵敏感。如果一个开发人员每年挣 12 万美元,一个 BA 挣 6 万美元,那么把同样多的非技术性工作交给其他人无疑是有意义的。此外,过多的上下文切换的负面影响严重阻碍了开发效率。最后,这可能令人震惊,但是许多开发者根本不擅长用户关系。我见过许多人,他们认为自己的用户愚蠢透顶。有一次在工作面试中,我的面试官直截了当地告诉我,他们内部 SAAS 平台的用户都是白痴,尽管他们中的大多数都是博士。很难理解得出这样的结论所需要的错觉,即一个博士团队是愚蠢的,而不是你的软件很烂并且不用户友好。

数据库管理员

该角色可概括如下:

数据库管理员(DBA)是信息技术人员,负责指导或执行与维护成功的数据库环境相关的所有活动。数据库管理员确保一个组织的数据库及其相关的应用程序能够有效运行(来源)。

根据劳工统计局的数据,2019-2029 年的十年就业前景预计将增长 10%——低于所讨论的其他角色,但仍高于全国平均水平。

反对数据库管理员的理由

随着大多数行业迁移到云,管理数据库的开销正在快速下降。例如,在下面的视频中,GCP 的 Postgres 数据库在 5 分钟内就完成了。此外,云产品内置了身份和访问管理解决方案。随着开发人员在数据/基础设施级别(即后端),他们开始质疑为什么数据操作需要专门的角色或团队。

在 5 分钟内启动一个 GCP 实例

在一家大银行的前一份工作中,我花了两个月的时间试图为一个新的应用程序启动一个 Mongo 实例。一个官僚 DBA 每一步都和我作对。在某一点上,他甚至坚持认为我的应用程序不需要对数据库进行写访问。如果一个应用程序不能写入数据库,它怎么能工作呢!?最后,他给我当了两个星期的鬼,后来我发现他正要离开公司,已经精神检查过了。这一经历让我对 DBA 产生了多年的偏见。

数据库管理员案例

虽然开发人员通常对基础设施和 SQL 有足够的了解来构建有状态的应用程序,但是一个好的 DBA 会带来更广泛的知识和视角。DBA 通常是 SQL 方面的专家,可以帮助开发人员优化查询和与数据库相关的任务。然而,数据库不仅仅是查询。作为应用程序开发人员,我们有时会忘记这一点。

例如,一个 DBA 曾经提出一个触发函数作为一个棘手问题的解决方案。在这之前,我从未听说过触发函数。还有一次,我们不得不在不停止生产版本的情况下从 Linux 服务器备份中恢复一个旧表。要做到这一点而不耗尽数据库资源,需要 DBA 付出相当多的精力和专业知识。对于 DBA 除了编写查询之外所做的所有工作,我们都没有给予足够的信任。

最后,我们不要忘记过去十年数据技术的寒武纪大爆发。想想无数的数据库引擎(CouchDB、RocksDB、Aurora 等...),以及数据仓库的进步(即雪花)、人工智能和数据科学。在这个新世界中,很难夸大数据专业知识的价值。

质量保证工程师

QA 工程师是一个技术人员,他确保发布的软件可供最终用户使用。从文章“一个软件质量保证工程师做什么?”,他们的职责包括:

  • 发现新的和预先存在的错误(回归)
  • 执行手动和自动测试
  • 检查用户界面的一致性和功能性。

由于 QA 和开发人员的职责重叠,很难获得单独的工资统计数据。事实上,这种重叠形成了针对 QA 工程师的核心案例。

针对 QA 的案例

对 QA 工程师的一个普遍看法是,他们仅仅是“测试人员”,或者充其量是初级开发人员。他们发现错误并运行测试,通常是手动的。那么,难道软件开发人员不应该自己编写自动化测试并发现错误吗?当 bug 进入生产时,最终是开发人员接受修复的指责和责任。

此外,QA 过程减缓了发布周期。当一个简单的特性花了几个小时开发,但却在等待 QA 几天时,这可能会令人沮丧。通常需求是不清楚的(咳咳,BAs ),因此 QA 可能测试错误的东西,报告非问题,或者仅仅需要大量的指导。当 QA 过程以这种方式受到损害时,开发人员将不可避免地采取的心态,我会自己测试它

我有过的最糟糕的 QA 经历是在 2015 年,当时我们的 QA 团队在离岸,只有短暂的时区重叠。他们会在我们喝咖啡之前就给我们打电话,浏览过时的手工 UI 回归案例的电子表格。95%的问题是不相关或不相干的,整个过程变成了徒劳无益的令人沮丧的练习。这让我对 QA 团队产生了很长一段时间的偏见,而实际上这是一个沟通的问题。

质量保证的案例

反对 QAs 的理由成立;然而,它包含了几个假设。首先,一切都可以/应该自动化的想法对于绿地项目是有意义的。但是在实践中,尤其是在大公司,大多数软件都是遗留的,缺乏测试覆盖率。此外,最初的开发人员可能已经离开很久了,大多数关于系统的知识都在 QA 团队中。在这种情况下,QA 团队将能够提供关于系统的无价的上下文、视角和想法。

第二个假设是 QAs 的工作仅仅是发现 bug。但是真正优秀的 QA 工程师往往能够识别出超越代码的用户陷阱。例如,虽然一个新按钮可能工作正常,但 QA 可能意识到公司的一些用户使用较低分辨率的显示器。在紧凑视图中,在复制旁边的文本时,按钮很容易被误点击;他们过去见过。这在单元测试中并不容易捕捉到…

图片来源:https://meme generator . net/instance/60318094/good-guys-a-team-QA-team

让我们也挑战自动化测试可以排除所有错误的假设——考虑以下几点。

  1. 有些变化甚至不需要测试。例如,某些用户界面的改变很容易被人验证,但是很难自动化。对于具有高变动和大部分美学变化的 ui,测试套件是一个速度阻力。
  2. 有些事情是无法预料的。系统总会有不可预测的方面。代码审查可能会有所帮助,但是没有什么可以代替实际的人施加压力。一个好的 QA 人员仍然会发现各种各样的东西。你有没有不耐烦地向 QA 团队坚持说你的特性很好,只是一个基本的改变,结果却让他们增加了一些东西?我确信我脸上的蛋。

展望未来

这些角色会持续下去吗?

随着行业继续向 DevOps 和云发展,这些领域将变得越来越少。每个角色都将趋向于更加专业化,特别是 DBA ,因为维护数据库的运营开销正在迅速降低。他们会在大公司呆得更久,但是对表现差的人的容忍度会急剧下降。然而,与此同时,对数据专业知识的需求将继续加速增长,如下文预测所示。仓储和数据科学的发展应该确保数据专业化仍然有利可图,数据库管理员也做好了转型的准备。

在 Pamela Fox 的文章中,她预测到 2025 年数字数据的总大小将超过 175 兆字节。如果一粒米=一个字节,那么一个 ZettaByte 将会充满整个太平洋。

在这三者中,BA 角色似乎最安全。普通的软件开发人员根本没有时间(通常也没有能力)去维护一个强大的 BA 的社交网络。然而,随着更多的公司迁移到 DevOps/Agile,用户和开发人员之间的反馈障碍将继续缩小。事实上,没有技术能力的 BAs 将会被淘汰。

QA 角色是最难预测的。随着自动化程度的提高,对 QA 人员运行手动脚本和“捕捉错误”的需求将会消失。然而,现代系统日益增长的复杂性和性能要求意味着质量保证比以往任何时候都更加重要。对许多 SaaS 公司来说,即使很短的停机时间也是有害的。 Slack 最近宕机一小时,这成了新闻。因此,能够发现用户界面陷阱和恶化的人才将继续受到欢迎。QA 是否仍然是一个真正的角色,还是退化为专业化,很难预测。

关于开发者的偏见

如果你两年前问我这些角色,我的想法会是“不想要他们也不需要他们”。我刚刚离开了一个沉闷的官僚机构,去了一家只有开发人员的初创公司。相比之下,这似乎是一个乌托邦。然而,当我因为 Covid 而失去工作,转到一家中型公司时,我的偏见暴露无遗。

在新的工作中,BA/DBA/QA 人员很有帮助。回顾过去,我意识到过去的大部分摩擦可归因于以下几点:

  • 沟通不畅(例如,团队成员跨越重洋工作)。
  • 受限制的责任,例如不能进行数据库查询的 BAs 或不能查看/运行代码的 QA 人员。
  • 缺乏认同:好的团队不分角色,一起赢,一起输。

最后,软件开发人员倾向于认为他们自己可以做任何工作。他们可以戴上分析师的帽子,但反过来通常是不正确的,这种不对称助长了自我。重要的是要记住,仅仅因为我们可以做一些事情,这样做可能不划算,而且我们可能不像自己认为的那样擅长。

你怎么看?得到了不同的拍摄;我全弄错了吗?留下评论让我知道。

Hash2Vec:单行单词向量

原文:https://towardsdatascience.com/hash2vec-one-liner-word-vectors-c8ec39ff1dfe?source=collection_archive---------13-----------------------

我最近做了一个有趣的实验,试图把单词向量和 LSH 拼在一起

图片来自 Pixabay 的 Markus Spiske

我们现在就跳进深水区吧。那样会很有趣。假设你有一个文本语料库。

[“dog barked at the tree”, “cat drank milk”]

现在将每个单词/标记表示为一个 ngram 包向量。为此,首先我们需要所有令牌中的所有 n 元语法。让我们取 1 & 2 克向量。

[d, o, g, b, a, r, k, e, d, …, m, i, l, k, do, og, ba, ar, …, mi, il, lk]

现在将每个单词表示为一个 ngram 向量

dog   —>[1, 1, 1, 0, 0, 0, 0, 0, 0, …, 0, 0, 0, 0, 1, 1, 0, 0, …, 0, 0, 0]barked->[0, 0, 0, 1, 1, 1, 1, 1, 1, …, 0, 0, 0, 0, 0, 0, 1, 1, …, 0, 0, 0]…milk  ->[0, 0, 0, 0, 0, 0, 0, 0, 0, …, 1, 1, 1, 1, 0, 0, 0, 0, …, 1, 1, 1]

一旦你有了每个单词的 n 元向量,计算如下。

w = xR-xR

这里,x是大小为(V , d)的 ngram 矩阵,R是大小为(d ,(b/2))的随机正规矩阵。所以我们以一个(V , b)结束。这里,V是词汇大小,b是超参数(散列箱的数量)。换句话说,我们为每个令牌准备了一个大小为b的向量。

你可以使用像 T-SNE 这样的降维技术来可视化这些向量,你会得到下面的结果。

转换后学习单词向量。我们可以看到有相似成分的单词(例如 up,UP?、up 或 i.ll、I.ll)聚类在一起(图片由作者提供)

仔细看看,

watch ['wat.', 'always', 'Wat', 'wat', 'Was']
Free ['free', 'FREE', 'here,', 'fine.', 'alone']
My ['my', 'MY', 'whole', '&lt;DECIMAL&gt;', '&lt;#&gt;']
sending ['Send', 'send', 'end', 'dinner', 'seeing']
May ['may', 'mayb', 'mail', 'well', 'Well']
was ['was', 'WAS', 'office', 'wan', 'wana']
Enjoy ['Enjoy', 'write', 'wit', 'sorry', 'Sorry']

你可以看到有相似成分的单词最终会组合在一起。

插入令人惊叹的迷因

代码: 此处

霍勒普。刚刚到底发生了什么?

图片来自 Pixabay 的克里斯蒂扬·普杰克

不要害怕!我不会把你丢在一个没有解释的悬崖上。这种可能性背后的核心思想在于位置敏感散列(LSH)。现在让我告诉你我最初是如何意识到这个有趣的属性的故事。

序言

前阵子我在看改革者(变形金刚模型的一个变种)的论文。那篇论文中最引人注目的特性是 LSH (Locality Sensitive Hashing)算法,他们用它来绑定查询和 Transformer 模型的键。我对它的简单和强大感到惊讶。对 LSH 最简单的解释(我猜)是,

LSH 做的与普通哈希函数相反。哈希函数试图减少唯一项目的冲突,而 LSH 算法试图最大化相似项目的冲突(基于某种输入表示)。

但对我来说,真正的灯泡时刻是不同的。我在想,是否有一种方法可以使用重整器中的 LSH 算法来产生粗糙而快速的单词向量。事实上,我花了很多时间在单词向量上(对此我不能给出一个很好的理由为什么?)可能已经种下了种子。

现在我们有了背景,让我们进入它的症结!第一站,LSH。

LSH 背后的想法

LSH 源于一个非常恼人的常见问题寻找近似最近邻居(安)。近似 NN(最近邻)意味着通过牺牲一定程度的准确性来快速找到 NN。例如,推荐模型在 ANN 上蓬勃发展,因为从数以亿计的用户群中找到与给定用户相似的用户不是在公园里散步!不要忘记这样一个事实,这需要一个快速的用户触发(例如,点击按钮,滚动页面,等等)。).

好的,回到 LSH。有许多不同的 LSH 算法可用,包括像 minhash 这样的流行算法。这个想法是想出一个散列函数,

对于高度相似的输入,增加冲突(相同散列输出)的概率

不过 Minhash 有点复杂,不在我们的讨论范围之内。为引擎盖下的重整器提供动力的算法要简单得多。该算法被称为角度 LSH (或球面 LSH )。事实上,如果你去掉多余的脂肪,可以用一行程序来表达。现在,让我们深入研究一下 Reformer 论文中使用的 LSH 算法的细节。

bins = 32R = np.random.normal(size=(5, bins//2))
inputs = np.array([[1,1,0,0,1], [1, 1, 1, 0, 0], [0, 0, 1, 1, 0]])h_x = np.dot(inputs, R)# The crux of the computation is a single line
# outs is a hash bin that is similar for similar inputs
hash_bins = np.argmax(np.concatenate([h_x, -h_x], axis=-1), axis=-1)

这就是你所需要的!哦,对了,我猜你想让我相信冰淇淋也来自冷冻的奶牛?不,真的,有用。原因如下?

直觉:球形 LSH

球形 LSH 围绕一个单位长度的球体(在某个 D 维中)和一个相同维 D 的查询向量旋转,

如果在这个球体上有 B 个随机旋转的顶点,具有相似表示的查询向量将得到与它们最近的邻居相同的顶点

这正是上面的计算所做的,具体来说,

获取查询的哈希桶的公式。";"表示串联操作

R ( r_j)中的每一列都可以被认为是我们的超球体的一个随机旋转的顶点(这是一个你可以保持原样的细节——但是对于相当精通数学的人来说,这里有一个小附录)。x_i.r_j就是简单的取点积。点积的另一个名称是“相似性”(点积越高,越相似)。然后argmax 给出顶点的索引,这是查询的神经网络。这有时被解释为“分配给一个容器”,但原理是一样的。是啊,就这么简单!

需要注意的一件重要事情是实体x_i.r_j这是一个向量,表示给定的查询与空间中的任意顶点有多相似。并且类似的查询将被放置在附近。当你在许多随机的顶点上这样做的时候,你最终会得到每个查询的向量。

与随机矩阵相乘如何在 2D 空间旋转形状(图片由作者提供)

我如何配合 LSH 获得良好的词向量?

很高兴你问了。首先,LSH 和词向量都瞄准了相似的目标,“在一个大的语料库中找到相似的输入单元”。所以我在这里试图回答的问题是,我们能不能想出一个 LSH 机制来得到一些快速单词向量?

我们简单地把argmax从等式中去掉。因为这给我们留下了到高维空间中每个随机顶点的距离向量。对于相似的单词(每个单词被表示为一个单词包),这些向量是相似的。

为什么我们不保留一包向量呢?

所以另一个问题是,我们正在利用我们的 ngram 包表示中已经存在的相似性。为什么首先要进行这种转变?有两个主要原因

  • n-gram 向量的包可以变得任意大,因为大小由语料库中不同 n-gram 的数量控制,其中在该方法中,b控制向量的大小
  • 强迫高维 n-grams 在一个较低的维度,迫使它学习更多的相似性。同样的原理也适用于单词向量。当维度很小时,它迫使单词向量学习单词中的相似性。

垃圾邮件分类任务的性能

评估单词向量的典型方法是在下游任务中使用它们。在这里,我在一个垃圾邮件分类数据集上评估了以下内容。

  • Hash2vec 载体
  • ngram 包向量
  • 实际单词向量

你可以在这里找到实验的代码。该模型是基于向量的简单逻辑回归模型。经过 10 次试验(每次训练 10 个时期),我得到以下结果。

  • Hash2vec: 82.18 +/- 0.93 %
  • 多宿主:83.99 +/- 0.28%
  • Word2vec: 92.04 + /- 0.36%

我们可以看到 Hash2vec 不是神谕。但是它的性能相当不错,尽管比多孔(网袋)方法的尺寸要小。这里我们结束了对方法的讨论。你可以看到这个实验的代码:这里。

为什么和为什么没有 Hash2Vec

为什么选择 Hash2Vec

  • 仅捕获成分相似性-这是确保具有相似结构的单词(例如 walk 和 walked)或具有较小拼写错误的单词(例如 third vs thrid)映射到相似向量的好方法
  • 没有训练的简单单词向量——不需要训练。简单的矩阵乘法给出向量
  • 适用于任何模型——与词向量不同,它们不需要处于端到端的可区分架构中(例如,可用于像 xgboost 这样的模型)
  • 散列法可能出错——在 LSH,没有人能保证完全相反的东西会在完全不同的垃圾箱里。在极少数情况下,它们可以映射到同一个 bin。这就是为什么我对这个实验进行了多次试验。

为什么不是 Hash2Vec

  • 捕获语义——单词向量将捕获语义(例如,猫对猫),而上述方法不会。
  • 没有矢量运算——与 Word2vec 不同,您不能用 Hash2vec 执行矢量计算(例如,king — man = queen — woman ),因为它不捕获语义。
  • 准确性——word 2 vec 比这种方法更有效。因此,如果您追求准确性,Word2vec 是一个更明智的选择。

如果你不能打败他们,就加入他们

这些方法(Hash2vec & Word2vec)不需要互斥。他们也可以互相授权。举个例子,

  • 你可以用 Hash2vec 给词向量提供一个很好的初始化,然后正常训练词向量。
  • 您可以使用 LSH 开发一个简单的拼写纠正机制。因为 LSH 将相似的单词映射到相似的桶,所以您可以使用该属性开发一个简单的拼写纠正查找字典。然后将相同桶中的单词映射到 word2vec 层中的相同向量。

结论

本文的目的不是介绍 word2vec 的竞争对手,而是展示简单 LSH 机制的威力,并通过单词向量练习巩固它。它给了我们一种不需要任何训练就能得出低维单词向量的方法。此外,这些向量可以捕捉单词之间的组成相似性。最后,这些方法也可以相互受益。

PS: 我没见过类似这样的技术被实验过,以前也没用过。这就是驱使我写这篇文章的原因。但是由于迷失在大量发表在空间中的 ML 论文中,类似的工作被忽视的情况并不少见。如果你看到一篇论文在做类似的工作。请随意发表关于他们的文章。

https://thushv89.medium.com/membership

附录

随机旋转和矩阵乘法

我们一直在说h(x) = argmax(xR;-xR)中的R代表一个超维空间中随机旋转的结构。为了理解为什么会这样,我们必须把注意力转向论文“单位超球面上近似最近邻搜索的球面 LSH”。在本文中,实际的计算看起来像这样,

其中R是一个随机矩阵(本文使用A),v_j代表一个正则超球面的j^th顶点。所以这里我们特别使用一个随机旋转矩阵来旋转一个规则超球面的顶点。那么我们如何将x_i(R v_j)缩小到xR;-xR(where“;”是串联)。诀窍在于我们用什么作为我们的形状。这里我们使用一种特殊的多面体(一种高维多边形的推广),称为“正多面体”。一个正射曲面的顶点仅仅是所有{+/- 1, 0, 0, 0,…}的排列。例如,在 2D 空间中是[1, 0], [0, 1], [-1, 0][0, -1]

2D 和 3D 空间中的 Orthoplex(图片由作者提供)

换句话说,顶点是I-I,其中 I 是单位矩阵。所以用I-I代替v_j,我们得到xR— xR。一个简单的整形将给出xR;-xR

有 SQL 面试吗?使用谷歌 Colab!

原文:https://towardsdatascience.com/have-a-sql-interview-coming-up-ace-it-using-google-colab-6d3c0ffb29dc?source=collection_archive---------8-----------------------

只需 2 个辅助函数,即可在 Google Colab 中设置和运行 SQL!

格伦·卡斯滕斯-彼得斯在 Unsplash 上拍摄的照片

如今,编码测试几乎是数据科学面试过程中的标准。作为一名数据科学招聘经理,我发现一个 20-30 分钟的现场编码测试,加上一些准备好的任务,可以有效地识别出能够成功胜任我通常招聘的职位的候选人。

Google Colab [ 链接 ]由于其熟悉的笔记本环境和方便的分享选项,是各种离线和现场数据科学编码面试的优秀工具。但是 Colab 很大程度上局限于 Python(和一些黑客的 R)。

以我个人的经验,SQL 是成为一名成功的数据科学家的重要技能。深度学习很棒,但是如果你不能编写 SQL 查询,你可能会永远停留在你的猫和狗的分类器上😜(如果你想学习如何做,可以查看这个链接)。

因此,我开始寻找进行实时 SQL 编码测试的方法,瞧!我偶然发现了这种在 Colab(或任何 Python 环境)中运行 SQL 的简单方法,只需要两个助手函数。

在这篇文章中,我将介绍我们可以用来在 Google Colab 中设置和运行 SQL 的两个 Python 函数,具体来说就是:

  1. 创建一个数据库,并上传一个熊猫数据帧到谷歌 Colab 的数据库表中
  2. 在 Google Colab 中对数据库和表编写和执行 SQL 查询。

所有代码都可以在我的 Github 账户上获得。也可以直接在 Google Colab 上打开代码(下次面试不要多此一举了😎)点击此链接:[ 链接

https://colab.research.google.com/github/stephenleo/medium-python-hacks/blob/main/02_sql_on_colab/main.ipynb

SQLite

需要是 i̶n̶v̶e̶n̶t̶i̶o̶n̶发现之母

当我对 SQLite 有了更多的了解后,我的灵光一现。剩下的就是简单的 Python 编码来创建 2 个辅助函数。在这次搜索之前,我只是模糊地听说过 SQLite,但从未需要更深入地研究它。根据 SQLite 官方网页[ 链接 ]

SQLite…实现了一个小,快,完备,高可靠,全功能,SQL 数据库引擎。SQLite 是世界上最常用的数据库引擎。SQLite 内置于所有手机和大多数计算机中,并捆绑在人们每天使用的无数其他应用程序中。

听起来很有希望!SQLite 的工作原理是创建一个本地.db文件,我们可以像连接一个普通的 SQL 数据库一样连接它。然后,我们可以在这个.db文件上创建表格、上传数据和查询数据。很简单!

事实证明,创建 SQLite 并与之交互的 Python 模块(sqlite3)是 Python 标准库的一部分。所以它在 Colab 上开箱即用。多方便啊!

首先,让我们导入sqlite3pandas模块,这是我们任务的唯一需求

导入需求

功能 1: Pandas 数据帧到 SQL 数据库表

我们的第一个任务是创建一个数据库,并将熊猫数据帧上传到数据库中的一个表中。

下面的代码将它实现为一个函数,我将一步一步地介绍它。该函数将一个input_df数据帧、table_namedb_name ( .db文件名)作为输入,并运行以下步骤。

  1. 设置一些日志来跟踪函数的执行
  2. 找到数据框中的所有列。这是必要的,因为我们需要在创建表和向表上传数据时提供这些信息。
  3. 如果存在,连接到一个.db文件。如果该文件不存在,请在本地创建一个新文件。
  4. 在我们在上一步中连接到(或刚刚创建)的.db文件中创建一个表
  5. 将数据行从input_df上传到我们在上一步刚刚创建的表中
  6. 提交更改并关闭与数据库的连接

功能 1:创建一个数据库,并上传一个熊猫数据帧到数据库中的一个表中

功能 2:对熊猫数据框架的 SQL 查询

我们的第二个任务是在第一个任务中创建的数据库和表上编写和执行 SQL 查询。

下面的代码将它实现为另一个函数,我也将一步一步地介绍这个函数。该函数将一个sql_query_stringdb_name ( .db文件)作为输入,运行以下步骤,并返回一个熊猫数据帧作为输出。

  1. 连接到.db文件中的 SQL DB
  2. 执行sql_query_string中的 SQL 查询
  3. 运行 SQL 查询后,获取结果数据和输出的列名
  4. 关闭与数据库的连接
  5. 以熊猫数据帧的形式返回结果

功能 2:在数据库和表上编写和执行 SQL 查询

差不多就是这样!我们现在有两个功能,可以粘贴到任何 Colab 笔记本上来解决我们的两个任务。让我们通过一个例子来看看如何使用这两个函数

使用 2 个函数在 Colab 中运行 SQL

由于 COVID 基本上是我们这些天谈论的唯一话题,我从 Kaggle [ Link ]下载了一个样本 COVID19 疫苗接种数据集,以测试我们的两个令人敬畏的函数。这些函数的用法非常简单,如下所示

  1. 将下载的 csv 文件加载到熊猫数据框架中
  2. 使用我们的第一个函数pd_to_sqlDB将我们在上一步中加载的数据帧上传到一个名为default.db的 DB 中的一个名为country_vaccinations的表中
  3. 在名为sql_query_string的字符串变量中编写一个 SQL 查询。正如您在下面的代码片段中看到的,我们可以编写任何我们能想到的复杂 SQL 查询。
  4. 使用我们的第二个函数sql_query_to_pddefault.db上执行上一步的 SQL 查询,并将结果保存在result_df数据帧中

测试两个功能

“测试两个函数”代码片段的输出。图片作者。

从结果中,我们可以看到(在撰写本文时),中国在接种疫苗的人数方面领先世界,其次是印度和美国。我们通过在 Google Colab 中对一个数据库执行 SQL 查询得到了这些结果!

这就是了。你现在可以在下一次面试中展示你高超的 Python 和 SQL 知识了!此外,节省一些时间,直接使用我在本文开头链接的 Google Colab 笔记本,它包含了上面的函数和示例查询。

我希望这篇文章对你有用。感谢您的阅读!

你曾经这样评价过你的模型吗?

原文:https://towardsdatascience.com/have-you-ever-evaluated-your-model-in-this-way-a6a599a2f89c?source=collection_archive---------8-----------------------

用麦克内马检验评价分类模型

费尔南多·席尔瓦在 Unsplash 上的照片

模型评估是模型开发过程的辅助部分。这是决定模型是否表现更好的阶段。因此,根据每种可能的评估方法考虑模型结果至关重要。运用不同的方法可以提供不同的视角。

有不同的度量标准(或方法),如准确度、召回率、精确度、F1 分数。这些是分类中用于模型评估的最常用和已知的度量。他们每个人都以不同的方式评估这个模型。例如,准确性提供了对模型如何正确预测的洞察,而回忆提供了对模型如何对正类敏感的洞察。在这篇文章中,我将解释另一种叫做麦克纳玛测试的方法。这种方法也可以提供另一个角度来评估你的模型。

分类模型的模型评估

分类模型用于通过给定的输入变量预测某些类别。然而,它们的结果是由名义数据或离散数据组成的。因此,在评估模型结果时,混淆矩阵是最优选的。它确保根据单元格值正确比较实际类别和预测类别。下图中有一个 2x2 混淆矩阵的例子。这是一个混淆矩阵,显示了预测类和实际类。

混淆矩阵示例(由作者创建)

正如你从上表中看到的,有两种类型,积极和消极。它们也可以表示为 0 和 1,或者 A 和 b,这没有任何区别。标记为 True 的单元格表示已被正确预测的类的数量。标记为假的单元格正好相反。评价你的模型,不如对这个困惑矩阵问几个问题,了解你的实际期望。每个问题都可以用不同的评估标准来回答。让我们来看看这些问题,

1-预测所有类别时模型的准确性如何?
2 —模型在预测阳性类别时有多敏感?
3 —模型在预测阳性类别时有多精确?
4 —预测负面类别时,模型的敏感度如何?

第一个问题可以用最常用的“准确性”来回答。第二个可以通过使用一个叫做“召回”的指标来找到。第三个问题可以用“精确”来回答,第四个问题可以用“特异性”来回答。还有其他相关的问题和指标,但我想重点谈谈要求 McNemar 使用的问题。

使用 McNemar 进行模型评估

评估分类模型时的一个错误是只考虑真实案例。这意味着只寻找模型如何正确地估计实际情况。因此,当结果不令人满意时,人们试图应用不同的方法或不同的变化来获得令他们满意的结果,而不考虑导致该结果的主要原因。不要忘记,准确性也取决于假预测,就像它取决于真预测一样。因此,在作出某种判断之前,也必须考虑错误的预测。这些是我们希望尽可能少的预测。通过考虑错误案例,称为召回和精确度的度量稍微解释了肯定类别(或否定类别)的性能。但是,我想说的是,假阳性和假阴性应该进行比较,就像它们在真实情况下进行比较一样。这就是应该使用麦克内马检验来获得假阴性和假阳性之间的差异概率的地方。

与其他指标一样,有一个问题麦克纳玛测试也可以回答。这个问题是 “你的模型对于错误(错误)预测的表现如何? 。如果统计上有差异,你可能会想把注意力放在造成更大差异的那个阶层上。您可以重新检查您的训练过程或数据集,以减少或平衡错误预测的数量。

注意:在相同的情况下,当模型使用不平衡的类进行训练时,会出现不平衡的假阴性和阳性预测。

麦克内马试验

McNemar 检验适用于 2x2 列联表,以确定成对样本的行和列边际频率是否相等1。对于混淆矩阵来说,行和列的边际频率意味着正类和负类的错误预测数。它使用卡方分布来确定差异的概率。让我们来看看下面的表格,并试着理解它们是如何产生差异的。

列联表(由作者创建)

在上表中,“b”和“c”单元格代表边际频率。麦克内马检验的零假设为( p 为比例)*p*a + *p*b = *p*a + *p*c*p*c + *p*d = *p*b + *p*b。如果我们在这里做数学计算,我们可以从两个方程得到*p*b = *p*c。所以,零假设是 b 细胞的比例等于 c 细胞的比例,另一个假设是 b 细胞的比例不等于 c 细胞的比例。下面的公式给出了麦克内马统计量。

麦克内马的统计数据(由作者创建)

麦克内马检验在混淆矩阵中的应用

在二进制分类模型上预测之后获得的混淆矩阵也是 2×2 表格的形式。因此,边际频率之间的差异可以通过使用麦克纳默测试来获得。让我们看看下面的混淆矩阵,并尝试找出错误预测之间是否有区别。

应用麦克内马检验的混淆矩阵(由作者创建)

从上表可以看出,假阴性和假阳性之间的差异是 10(45–35)。不要忘记,这个结果来自您用来开发模型的样本测试集或训练集。当模型进入生产阶段时,它可能会得到更多不同的输入值。因此,我们需要找出这种差异在统计上是否显著。如果差异在统计上是显著的,则预计在生产中会得到相同的差异。这就是为什么需要一个概率值的原因。

我将使用 Python 来应用 McNemar 的测试。计算起来真的很简单,从前面的公式可以看出。此外,我们需要通过使用麦克纳玛统计量从卡方检验中获得 p 值。可以通过使用来自“scipy.stats”模块的两种方法chi2.cdfdistributions.chi2.sf来找到它。为了使用这些方法,我们还需要自由度的值。它是由行和列(2–1)*(2–1)的减一的乘积得到的。对于 McNemar 检验,零假设是边际频率之间没有差异,另一个假设是边际频率之间有显著差异。因此,如果 p 值大于 0.05,可以得出结论,假阴性和假阳性之间没有显著差异。并且,如果 p 值小于或等于 0.05,则意味着存在显著差异。

发现 p 值为 0.26。因为 p 值大于 0.05,所以不能拒绝零假设。这意味着在 95%的置信水平上,假阳性和假阴性的频率没有显著差异。那 0.26 和成为差异的概率呢。1–0.26 给出差异的概率。因此,在概率为 0.74 的情况下,我们可以说,假阴性和假阳性之间可能存在差异。

结论

本文测试了错误案例之间的差异。真阳性和真阴性之间的差异也可以通过使用麦克内马检验来检验。这也可以提供一个不同的视角来评估你的模型。在应用麦克内马检验之前,最重要的事情是确定两个类别的数量大致相同。否则,可能会导致不可靠的结果。McNemar 的测试只适用于 2x2 表。当存在多类模型时,可以在混淆矩阵可以划分为子 2x2 表之后使用 McNemar。

参考

[1]https://en.wikipedia.org/wiki/McNemar%27s_test,麦克纳玛的测试,维基百科

你听说过英伟达的 AI GauGAN2 吗?

原文:https://towardsdatascience.com/have-you-ever-heard-of-nvidias-ai-gaugan2-e08a12c8c6b9?source=collection_archive---------23-----------------------

将图画和文字转换成照片/照片级图像的人工智能

英伟达凭借 GauGAN2 AI 再次展示了为什么他们是人工智能和数据科学领域的顶级公司之一。他们的深度学习模型 GauGAN 将单词和类似油漆的图画渲染成照片级的图像2。一个现在仍处于起步阶段的应用程序,但可能会在未来对不同的领域产生巨大的影响,例如设计师。

GauGAN2 是关于什么的?

老实说,surface 让我想起了 windows 98,而不是 2021 年的 AI,但它仍然是一个演示,所以前端现在不是重点。在右上方,可以输入描述图像上场景的文字。在我的例子中,我输入了“山湖云太阳”。在输入字段旁边,您可以选择输入可视化的类型-分段、草图或图像。下面你可以选择画笔大小颜色,铅笔,橡皮,和其他类似绘画的工具。

GauGAN2 的选项和设置。来源:自己截图

GauGAN2 不能正常工作?

您可以通过选择想要绘制的元素来开始绘制。在左侧,您可以找到一个下拉菜单,从中您可以选择您的图像应该包含什么。首先,我选择了云,这将自动导致你的铅笔的灰色。然后就可以开始画云彩了。重要的是,你不只是概述元素。你还需要用颜色填充它们。这可以通过手动填充或选择填充工具来完成。如果你不填充你的元素,人工智能创建的图像看起来会有点奇怪,人工智能不知道该做什么。因此,目前,填充所有元素很重要。完成湖光山色后,可以继续下一步。(由于下拉列表中没有太阳元素,因此不能直接描绘太阳本身。)

我的绘画和 GauGAN2 的输入。来源:自己的图像。

完成书写和绘图后,您需要向下滚动到演示工具的底部,选中“如果您同意下面描述的条款和条件,请选中此框”。

启动 GauGAN 所需的复选框。来源:自己的图像。

下一步也是最后一步是单击红色轮廓箭头。在右侧,您可以看到某些类别的图像。如果你选择其中之一,创建的图像将基于所显示图像的情绪/灯光。如果你不能决定,你也可以选择骰子随机选择一个。

开始 Gaugan 和不同的心情。来源:自己的图像。

你准备好结果了吗?

Tada,这就是我们由 AI GauGAN2 创建的图像。是的,这些山都不存在。它们是由人工智能自由创造的,我认为这非常令人印象深刻。尽管元素和选项的数量仍然受到限制,GauGAN2 和 Nvidia 表明,未来还会有更多的东西出现,这只是人工智能真实感创作的开始。

这是 GauGAN2 的图像。来源:自己的图像。

我的画和结果的比较。来源:自己的图像。

在这里,您可以看到相同绘图和输入的一些不同情绪:

高更的不同心情 2。来源:自己的图像。

不同的灯光,亮蓝色。来源:自己的图像。

冰和冰川,GauGAN2 创造。来源:自己的图像。

AI GauGAN2 背后是什么模型?

正如我之前提到的,GauGAN2 是基于生成性对抗网络的。当然,GAN 模型已经存在一段时间了,但是这个模型的新之处在于它将文本、语义分段、草图和样式结合到一个 GAN 中。“GauGAN2 背后的人工智能模型使用英伟达塞勒涅超级计算机在 1000 万张高质量的风景图像上进行训练,该超级计算机是英伟达 DGX 超级计算机系统,是世界上 10 大最强大的超级计算机之一。研究人员使用一个神经网络来学习单词和它们对应的视觉效果之间的联系,如“冬天”、“有雾”或“彩虹”。" 1

结论

凭借 GauGAN2,Nvidia 将其 2019 年发布的 GauGAN 推向了一个新的高度2。该系统现在更加准确,产生的逼真图像往往无法与真实照片区分开来。我尝试了许多不同的设置,只有在某些情况下,当输入绘制得不好时,人工智能很难创建一个好的图像。我敢肯定,这仅仅是人工智能创造的真实感图像的开始。在未来,这样的系统将帮助不同领域的设计师。看到几年后可能发生的事情令人兴奋。

你怎么想呢?你试过人工智能了吗?如果没有,我推荐去做。绝对令人着迷。我们走吧

http://gaugan.org/gaugan2/

https://medium.com/@hucker.marius/membership

来源

1萨利安·伊莎(2021)。'给我画一幅画':英伟达研究显示 GauGAN 人工智能艺术演示现在可以对文字做出反应。https://blogs . NVIDIA . com/blog/2021/11/22/gaugan 2-ai-art-demo/

2 Prathmaseh Ingle (2021)。NVIDIA 推出 GauGAN2:一种将文本转换为图像的人工智能模型。https://www . marktechpost . com/2021/11/25/NVIDIA-introduces-gaugan 2-an-ai-model-that-converting-text-into-images/

有没有想过用 Python virtualenv?

原文:https://towardsdatascience.com/have-you-ever-thought-about-using-python-virtualenv-fc419d8b0785?source=collection_archive---------18-----------------------

环境设置

在终端和 Jupyter 笔记本上安装和使用 Python virtualenv 的实用指南。

图片来自 Pixabay 的 klimkin

通常,一个初学者开始在主 Python 环境中安装所有需要的库。随着项目数量的增长,安装的库也在增长。在不同的项目中,可能会发生库冲突。

例如,可能会发生两个不同的项目需要同一个库的两个不同版本,所以在单个 Python 环境中,不能安装同一个库的两个版本。

如何解决这个问题?Virtualenv 可能会有所帮助。

Python virtualenv 是一个独立的 Python 环境,您可以在其中仅安装项目所需的包。

安装和运行虚拟环境

首先,你需要安装virtualenv包。例如,这可以通过以下命令在pip中完成:

pip install virtualenv

然后,您可以创建一个目录,在那里您将存储所有的虚拟环境。一旦创建了目录,您就可以访问它,并且只需运行以下命令就可以创建虚拟 env

virtualenv my_virtual_env

其中my_virtual_env可以是你想要的任何名字。通常,新的虚拟 env 是干净的,因为它不包含任何全局库。

您可以通过终端激活您的虚拟环境,只需进入虚拟环境目录并运行source命令:

cd my_virtual_env
source bin/activate

现在你的虚拟环境是活跃的。您可以在终端行的左侧看到虚拟环境名称,如下所示:

(my_virtual_env) my_pc:

一个非常有用的功能是列出虚拟环境的所有库:

pip list --local

所有已安装库的列表也允许快速写下项目所需的库。

要退出(停用)虚拟 env,只需运行以下命令:

deactivate

从 Jupyter 笔记本运行虚拟环境

虚拟 env 也可以在 Jupyter 中使用。首先,您需要在您的虚拟环境中安装ipykernel。因此,您激活您的虚拟 env,然后从您的虚拟 env 运行以下命令:

pip install ipykernel

现在您可以告诉 Jupyter 在哪里可以找到虚拟 env。通过指定要连接到 Jupyter 的虚拟 env 的名称,运行以下命令:

python -m ipykernel install --name=my_virtual_env 

您可以运行 Jupyter 服务器,当您选择 New 时,您会看到虚拟 env 的名称出现,如下图所示:

作者图片

如果你想从 Jupyter 单元安装一些库,你不能利用传统的方法!pip install <library_name>,因为这将运行全局软件包管理器。相反,您可以运行以下命令:

import sys
!{sys.executable} -m pip install <library_name>

无论如何,如果前面的代码看起来太复杂,您总是可以从命令行安装库。

移除虚拟环境

如果只想从 Jupyter 中删除虚拟 env,可以从终端运行以下命令:

jupyter kernelspec uninstall my_virtual_env

如果您想从全局系统中删除虚拟环境,首先您必须停用虚拟环境,然后您可以删除包含虚拟环境的文件夹。

或者,您可以通过以下命令删除所有已安装的包,并保持虚拟 env 活动

virtualenv --clear path_to_my_venv

摘要

在本教程中,我解释了如何安装和运行 Python 虚拟 env。显然,您可以创建任意多的虚拟 env。

我希望这篇文章能帮助你建立一个更有组织的编码策略:)

相关文章

[## 如何在 Android 设备上安装 Python 和 Jupyter Notebook

towardsdatascience.com](/how-to-install-python-and-jupyter-notebook-onto-an-android-device-900009df743f) https://medium.com/analytics-vidhya/basic-statistics-with-python-pandas-ec7837438a62 https://alod83.medium.com/how-to-design-a-data-journalism-story-b2e421673b6e

参考

https://medium.com/@shivangisareen/for-anyone-using-jupyter-notebook-installing-packages-18a9468d0c1c https://stackoverflow.com/questions/42449814/running-jupyter-notebook-in-a-virtualenv-installed-sklearn-module-not-available https://janakiev.com/blog/jupyter-virtual-envs/

你见过这款 AI 牛油果椅吗?

原文:https://towardsdatascience.com/have-you-seen-this-ai-avocado-chair-b8ee36b8aea?source=collection_archive---------12-----------------------

DALL-E 可以从文本中生成几乎任何东西的图像

由 DALL-E 生成的鳄梨扶手椅。OpenAI 提供的图像1

Dall-E 是什么?

DALL-E 从文本中创造图像。它是一个 transformer 语言模型,是 OpenAI 在 2020 年 1 月 5 日发布的成果。

DALL-E 结合了 GPT-3 执行文本生成任务的能力和图像 GPT 生成图像的能力,代表了这两个非常成功的神经网络进展的汇合。

Dall-E 能做什么?

有趣的部分来了。

Dall-E 创造真实可信图像的能力是超现实的。Dall-E 理解语言并使用提示作为生成图像的指令。

Dall-E 可以组合概念并生成新颖的图像

令人惊讶的是,它能够组合多个概念并修改一个对象的属性。现在,想象一把鳄梨形状的扶手椅。

正如人类可以将扶手椅和鳄梨的概念结合起来,并将这些概念串联成一个图像,DALL-E 也可以,尽管 DALL-E 可能从未见过八角形的紫色井盖。

鳄梨形状的扶手椅。图片由 OpenAI 1提供

DALL-E 生成的黄瓜制成的大象。OpenAI 提供的图像1

Dall-E 会画画

在模仿某些艺术家的风格方面,我们已经看到了像生成对抗网络(GAN)这样的深度神经网络的先前进展。DALL-E 更进一步,将文本命令转化为图像。

DALL-E 也懂艺术。图片由 OpenAI 1提供

Dall-E 可以说明

Dall-E 还能够生成拟人化的插图,甚至表情符号。

我们都需要这个表情符号。图片由 OpenAI 1提供

达尔了解地理和历史

最有趣的是,Dall-E 似乎穿越了时空,了解了世界的地理和历史事实。

DALL-E 在太空中旅行得很好…图片由 OpenAI 1提供

…还有时间。图片由 OpenAI 1提供

Dall-E 不能做什么?

现在,Dall-E 可能看起来很迷人,但它绝不是完美的。下面是 Dall-E 失败的三个具体例子。

Dall-E 可能会在一些文本上失败。

Dall-E 可能在某些短语上工作得很好,但在语义等价的文本上可能会失败。这就是为什么 Dall-E 的作者有时需要在提示中重复自己,以提高图像生成任务的成功率。

Dall-E 可能在不熟悉的物体上失败

Dall-E 有时无法渲染现实生活中不太可能出现的对象。例如,它不能呈现五边形停车标志的照片,而是显示传统的八角形停车标志的结果。

一个困惑的 Dall-E 不知道五边形停止标志看起来像什么。图片由 OpenAI 1提供

Dall-E 可能会走捷径

当提示合并对象时,Dall-E 可能会选择分别绘制图像。例如,当提示画一只由水龙头组成猫的图像时,它会将水龙头和猫并排画出来。

猫+水龙头=?图片由 OpenAI 1提供

下一步是什么?

OpenAI 先前将 GPT 3 技术授权给微软。类似地,OpenAI 可能会将 DALL-E 授权给拥有资源来有效部署和管理 DALL-E 的科技巨头。

Dall-E 非常强大,可以想象它有着巨大的社会影响。如果生成性对抗网络(GANs)可以用来生成深度假货,那么想象一下 DALL-E 在生成假货图像和扩散假货新闻方面可能产生的负面反响。

我们需要一种方法来规范 DALL-E 在假新闻和照片的时代。由马库斯·温克勒在 Unsplash 上拍摄

Dall-E 需要解决的一些伦理问题既棘手又模棱两可。在我们期望这种人工智能技术在我们的日常生活中广泛采用之前,这些问题需要得到解决。这些复杂的问题包括

  1. 模型输出中的潜在偏差(如果 DALL-E 没有充分代表少数群体怎么办?)
  2. 模型安全和事故(即,我们如何防止人工智能意外地做某事
  3. 人工智能校准(即让模型做你想让它做的事情)
  4. 对某些职业的经济影响(想想那些插画师,他们的工作可能会被这种技术取代。)

除此之外,深度学习和机器学习领域现在是一个非常令人兴奋的地方。在他们的页面查看更多关于 OpenAI 的信息。

如果你喜欢这个帖子,你可以看看我的其他帖子,或者在 LinkedIn 上与我联系。

https://www.linkedin.com/in/travistang/

https://www.linkedin.com/in/travistang/ [## Travis Tang -数据分析师

www.linkedin.com](https://www.linkedin.com/in/travistang/)

引文

所有图片来自以下博客帖子。

1拉梅什、巴甫洛夫、戈和格雷。(2021 01 06)。DALL E:从文本中创建图像。检索于 2021 年 1 月 7 日,来自https://openai.com/blog/dall-e/

机器学习是数据质量的未来吗?

原文:https://towardsdatascience.com/have-you-started-using-machine-learning-for-data-quality-yet-c0136e0957ac?source=collection_archive---------9-----------------------

提高数据质量的一些机器学习技术

照片由西格蒙德在 Unsplash 上拍摄

“垃圾进,垃圾出”,在数据世界中,我们经常听到这个短语,意思是如果你的数据是“坏的”,你就永远无法做出“好的”决策(打赌你没有看到这一天的到来:P )。

从“差”到“好”的旅程就是数据质量。现在,坏数据可能意味着很多事情,例如:

  • 数据不是最新的,及时性
  • 数据不准确,准确性
  • 数据对不同的用户有不同的价值,或者没有单一的真实来源,一致性
  • 数据不可访问。可用性
  • 数据不可用,可用性

这篇文章很好地定义了数据的各个维度,请继续阅读,了解更多信息。

数据质量对所有领域的工作都很重要,也很关键,但作为一名数据工程师,我们在交付数据的同时也要承担主要责任,我们要交付“好”的数据。

我的经历:

为了确保数据质量,我还实施了基于规则的解决方案来处理:

  • 错误的模式
  • 重复数据
  • 后期数据
  • 异常数据

这主要围绕着清楚地了解我将向系统提供什么样的数据,当然反过来对整个数据管道框架进行概括。

虽然自动化系统有助于从被动方法转变为主动方法,但基于规则的系统的问题是

  • 对于高基数、多维数据,它可能有太多的规则。
  • 对于每一个新的错误,每一个新的异常,数据质量框架需要一些定制的实现,即在这样的解决方案中,人工干预是不可避免的

为了克服基于规则的场景中的人为干预,我们需要寻找一个完全自动化的系统。随着许多最近的发展,ML 是可能有助于实现这一目标的领域之一。

让我们看看机器是如何帮助我们确保自动化数据质量或超越表面现象的?

在讨论如何之前,我们先讨论为什么?

为什么机器学习是为了数据质量?

  • ML 模型可以从大量的数据中学习,并且可以发现其中隐藏的模式。
  • 能处理重复性任务
  • 不需要维护规则
  • 可以随着数据的发展而发展

但是我还想指出,虽然上面的列表看起来像是 ML 作为候选人的选举横幅,但使用它取决于用例与用例之间的关系,而且 ML 通常不适合小型数据集或不显示任何模式的数据集。

说到这里,让我们看看一些 ML 应用程序的数据质量:

  • 识别错误数据
  • 识别不完整的数据
  • 识别敏感数据以实现法规遵从性(可能是 PII 识别)
  • 通过使用模糊匹配技术进行重复数据删除(有时只对数据进行唯一性处理不起作用)
  • 通过评估历史模式来填补缺失的数据
  • 通过使用历史信息对 SLA 的潜在违反发出警报(假设使用历史信息,系统检测到可能影响 SLA 的数据量急剧增加)
  • 可以帮助有效地开发新的业务规则(定义 apt 阈值)

可以用于数据质量的一些 ML 技术

降维

降维是用于识别数据中的模式和处理计算量大的问题的 ML 方法。该方法包括一组算法,旨在通过确定每列的重要性来减少数据集中的输入变量数量。

它可以用来识别和删除在过多的列中带来很少或没有信息的列,从而消除维数灾难(阅读更多信息)

在为任何其他数据质量算法馈送数据之前,它通常可以用作第一算法。在处理涉及语音、视频或图像压缩的视频和音频数据时,降维非常有用。

例如:UMAP、 PCA

聚类

聚类根据数据的相似性和不相似性将数据组织成组(聚类)。

示例:DBSCAN

异常检测

异常检测算法本身并不独立。它通常伴随着降维和聚类算法。通过使用降维算法作为异常检测的前置阶段,我们首先将高维空间转换到低维空间。然后我们可以计算出这个低维空间中主要数据点的密度,这可能被确定为“正常”那些远离“正常”空间的数据点是异常值或“异常值”

例如:ARIMA

关联规则挖掘

关联挖掘是一种无监督的 ML 算法,用于识别大型数据集中频繁出现的隐藏关系。

这种算法通常用于识别事务数据库、关系数据库或任何类似数据库中的模式和关联。例如,可以构建 ML 算法,该算法将通过处理来自条形码扫描仪的数据来分析购物篮,并定义一起购买的商品。

嗯,大概就是这样吧!讨论了使用机器学习提高数据质量的各种方法后,我想强调的是,没有一种适合所有 DQ 需求的解决方案。它可能因用例而异,在某些情况下,基于规则的系统可能是完美的,但随着数据的增长和的变化最终转向机器学习方法来提高数据质量可能会帮助我们超越显而易见的东西。欢迎来到未来!

我还会写一篇关于科技巨头如何利用机器学习提高数据质量的后续文章。

下次再见,
JD

推荐人:

https://eng.uber.com/monitoring-data-quality-at-scale/ https://netflixtechblog.com/tracking-down-the-villains-outlier-detection-at-netflix-40360b31732

https://engineering . LinkedIn . com/blog/2020/data-sentinel-automating-data-validation

https://medium.com/data-science-at-microsoft/partnering-for-data-quality-dc9123557f8b https://medium.com/airbnb-engineering/data-quality-at-airbnb-870d03080469 https://medium.com/airbnb-engineering/anomaly-detection-for-airbnb-s-payment-platform-e3b0ec513199

拥有学位已经不足以在数据科学领域找到工作了

原文:https://towardsdatascience.com/having-a-degree-isnt-good-enough-to-get-a-job-in-data-science-anymore-a5705239174b?source=collection_archive---------8-----------------------

一个学位不会让你领先于其他 100 名申请者。你必须做得更多。

庞的照片

如果我们回到 5-10 年前,这种说法是错误的。当时,数据科学领域刚刚起步,几乎没有培养有抱负的数据科学家的项目。

如果你有幸获得这些有限项目的学位,那么世界就是你的了。低竞争加上数据驱动的决策激增的等式在很大程度上相当于一份工作。

你认为现在还是这样吗?

几天前,亚马逊在 LinkedIn 上发布了一个数据科学实习生的职位,看看在短短 4 天内有多少人申请。

图片来自 LinkedIn

如果你认为仅仅拥有一个学位就能让你超越 1100 名其他申请者,那你就大错特错了!

学位到底能说明什么

我确信我们都听说过这样一句话,学位只是一张纸。现在你们中的许多人可能认为这是真的,许多人可能认为远不止如此。

我认为没有人会不同意的一个方面是,它显示了承诺。

那张纸表明你投入了 4 年的时间来学习获得那个学位。那 4 年也不是在公园散步,我的经历是含咖啡因的不眠之夜和每周 2-3 次放弃的想法。

那是地狱,但我们成功了。

这就是学位的问题。对雇主来说,你的学位表明你上过学,你学到的足够通过你的课程。

我说够了,因为我们都知道即使是 C 也能拿到学位。

那个学位没有显示的是申请

你坐在教室里学习材料,但是如果你没有把它应用到任何地方,雇主怎么知道你是否真的了解你的材料。这就是为什么许多人很难在数据科学领域找到工作,因为他们除了学位什么也没有。

任何人都可以在数据科学领域找到工作

不要因为你有数据科学、计算机科学或统计学学位,就认为你是少数几个有资格做这些工作的人之一。

事实是许多著名的数据科学家并没有技术学位。事实上,许多人拥有与数据科学和/或计算机科学毫不相关的其他领域的学位。

  • Hadoop 框架的开发者 Doug Cutting 拥有语言学学位。
  • 奥莱利媒体是最著名的编程和数据资源出版商之一,其所有者蒂姆·奥莱利拥有经典文学学位。

这些学位与他们在技术领域的资格相去甚远。

你需要摆脱这样的想法:你属于某个小众群体,是唯一有资格获得这些工作的人。

没有学位,你如何找到工作

说真的你会怎么做?

如果你很难在数据科学领域找到工作,请认真考虑这个问题。如果没有那张纸,你将如何向雇主表明你满足了他们的所有要求?

这不是不可能的,以前那些没有学位但仍能找到工作的人就这么做过。

那么他们是怎么做到的呢?

他们推销自己。

那些没有学位的人不能只拿着那张纸说

嘿,这证明了我有能力完成这份工作

不,他们需要做的是充分推销自己,让雇主相信他们拥有工作所需的适当技能。

如果你能很好地推销自己,你将在竞争激烈的市场中拥有更高的知名度和曝光率,并在竞争中占据优势。

推销自己的 4 种方式

市场营销随处可见,最有效的市场营销活动能为公司带来数亿美元的收入。每个人都可以通过营销被愚弄和影响。

正确地推销你自己,你会减少你收到的拒绝邮件的数量。

这里有 4 种方法可以帮助你推销自己。

1)创建一个投资组合

向雇主展示你具备必要技能的最佳方式是通过申请。这意味着将你学到的东西应用到你自己的个人项目中。

几个小型或中型的数据科学项目是一个好的投资组合。创建一些项目,向雇主展示你拥有他们所需要的知识和技能

如果你申请的数据科学职位有“了解机器学习”作为一项资格,向公司推销自己,做基于机器学习方法的项目,如回归、分类、聚类等。

投资组合可以有效地替代某人缺乏的工作经验,或者某人没有的学位。

2)加入基于数据科学的网络圈子

认识合适的人比任何简历都更有力量。

这么想吧。

如果我推销自己是一名专业的空气吉他演奏者,你可能不会相信我。但是如果其他领域的专业人士出来给我一个好的参考呢?现在我的名字更可信了。

关键是,试着建立一个强大的网络基础,在那里其他人可能会伸出援手帮助你。

您可以通过执行以下任一操作来实现这一点:

  • 加入基于数据科学的小组。你可以在 LinkedIn 或脸书上找到这些团体。参与其中,展示你的专业知识,这可能会导致推荐,让你接触到招聘经理。
  • 找一个你将来想做的导师。一位导师会在你的道路上帮助你,提供并指导你如何获得他们的职位。
  • 通过参加围绕你想进入的领域的讲座、活动和谈话,建立一个由志同道合的人组成的专业网络。

3)参加比赛、峰会、参加招聘会

想象一下这些事件,就像一个推销员走到你的门前,试图向你推销下一个很棒的房屋清洁产品。

在他们说任何话之前,你都想当着他们的面把门关上,但是如果他们向你展示了这个设备到底是做什么的,并且你喜欢你所看到的,那该怎么办呢?你开始感兴趣,你知道他们刚刚做了一笔交易。

成为一名推销员,从事一切可能的职业活动。你永远不知道谁会参加这些活动,并且对你的产品也就是你的技能感兴趣。

以下是您应该参加的一些事件和活动:

  • 招聘会让你很快接触到很多公司。四处走走,与招聘人员交流,把每次谈话都当成一次小型面试。我见过很多同事通过这种方式找到工作。
  • 每年都有数以百计的黑客马拉松来展示未来的程序员、数据科学家和软件工程师的技能。参加这些活动,通过向赞助这些活动的科技公司展示你的技能和能力,你将获得更多的曝光率。
  • 参加 Quora 或 Reddit 上的数据科学论坛。通过回答问题和熟悉社区来展示您的专业知识。

4)在媒体上写博客

我在这里可能有点偏见,因为这对我来说很好,但相信我,我在任何方面都不特别,所以这也可以为你工作。

在媒体上写博客的好处是任何人都可以偶然发现你的文章,你也可以把链接发给任何人。

这就是我今天所做的贡献,它让我得到了一份工作,作为一名体育分析师为加拿大奥运队工作。

在我得到那份工作之前,我没有经验。我知道我的简历有所欠缺,所以我想创造一些可以向雇主展示的东西。我决定做一些关于体育分析的项目,并在媒体上写下它们。

如果你回顾我最早的文章,你可以看到这些项目

当我写完这些文章后,我会把链接发给体育行业的一些雇主,你知道吗,我可以和加拿大队的人通电话…

正如他们所说,剩下的就是历史了。

Medium 是一个展示你技能的绝佳平台,你可以在这里建立一个投资组合。试试吧,因为你永远不知道谁会读你的文章。

感谢阅读!

我希望这能为您的数据科学事业提供一些指导和帮助。找工作并不容易,但如果你能在校外做一些能让你脱颖而出的事情,事情会变得容易一些。

与 1k+人一起加入我的电子邮件列表,免费获得完整的 Python for Data Science 备忘单小册子。

有数百个时间序列要探索,却不知道从哪里开始?

原文:https://towardsdatascience.com/having-hundreds-of-time-series-to-explore-and-not-knowing-where-to-start-5e7873fd2028?source=collection_archive---------48-----------------------

在本文中,我将为致力于大规模时间序列探索的框架奠定基础。

安特·罗泽茨基在 Unsplash 上的照片

在本文中,我将继续探索多元工业时间序列。如果您需要重温一下在处理这些问题时可能会遇到的一些特殊挑战,您可以看看我以前的一篇关于这些挑战的文章:

语境

假设你是一名流程工程师或数据科学家,在一家能源公司工作。您所使用的一些工业资产可能是压缩机、泵、燃气轮机、膨胀机……这些设备中的任何一个都可以收集数百个甚至数千个时间序列信号。

此外,这些都是重要的资产:任何计划外停机都可能造成数百万美元的损失(维护和维修工作、更换零件、罚款、收入损失……)。这种事件很少发生,如果你想改进你的预测性维护实践,你可能需要多年的数据来研究每一个分钟级(甚至是秒级)的信号采样。

有一天,我从一条电工钢生产线上以 10 毫秒的采样率收集了 5500 个时间序列。我有 3 年的历史数据,我知道在这个数据集中有数百个异常,但是当它们发生时,操作员没有办法轻松地捕捉它们,所以数据集到达我的桌子上(实际上,因为它是在硬盘中交付的……)没有任何标签

不幸的是,这种情况在工业环境中是正常的:一个工厂的主要目标…是生产(洗发水瓶子,铝线圈,汽车,…你能想到的!),而不是对生产过程中实时发生的任何异常进行精确的时间标记和分类…

在这篇文章中,我的目标是揭示如何探索类似的数据,假设你有一个云托管的笔记本电脑,有足够的马力来处理和可视化你的数据。我将把重点放在实现快速探索上,而不是创建一个内存高效的数据处理管道。

数据集概述

我正在玩的数据集是体育 4 亿个数据点,分布在 5 年的 100 个信号之间,最初以 1 分钟的速率采样。我收到的原始文件是一个 20 GB 的 CSV 文件,包含以下三列:

  • 时间戳
  • 标签名称
  • 价值

每个信号都与一个测量单位相关联(例如,以摄氏度为单位的温度、以毫米为单位的位移、以 RPM 为单位的转速……):这在以后会很方便…

为了在 Jupyter 笔记本上轻松处理这个数据集,我使用了一个 Amazon SageMaker 笔记本实例,它有 16 个 vCPU 和 64 GB 内存。

为我想要的“舒适”程度建立一个基线

为了感受我们面对的是什么,我进行了以下基本操作:

  • 加载熊猫的 20 GB CSV 文件:大约 3 分钟
  • 提取数据帧中的一个信号并执行一些基本的预处理(应用时间索引并向下采样到 1 小时):大约 20 秒

如果我想要可视化所有 100 个信号,这将需要相当长的时间,并且它的交互性不足以遵循数据科学家的思维过程:

用 Matplotlib 绘制 100 个图将花费 30 分钟到一个小时的时间,并且这些图本身不是交互式的:如果我想放大某一年、月、周或天,我将不得不为我感兴趣的每个时间范围经历这个过程。

当然,我可以遍历不同时间范围内的所有信号并导出数百个 PNG 文件…只能说这看起来不是很有效…即使我继续这样做,我也不能说我有信心我的探索会足够彻底…

我的框架

预处理

出于探索目的,通常没有必要停留在 1 分钟采样。如果您想要利用这些时间序列来改进您的预测性维护或异常预测实践,将采样时间降低到 1 小时可以为您提供足够精细的数据集。

  • 第一步 :加载原始 CSV 文件后,我分离出每个信号,并确保以 1 小时的速率对它们进行重新采样。
  • 第二步: 我还会将它们在 0 和 1 之间归一化,以允许在同一图上绘制信号,同时共享同一 y 轴。

储存;储备

从 Pandas 加载和写入 CSV 文件太慢:有几种方法和文件格式可以使用,都比这快一个数量级(HDF5,Dask dataframe,利用 numpy)。为了保持使用熊猫数据框的舒适性,我对 HDF5 和拼花地板非常满意。根据您的管道,这两种格式都是不错的选择。

  • 第三步: 我将每个信号都存储在本地或 Parquet 中的 S3 桶中。提取,调整采样率和保存每个信号一劳永逸地在大约 30 分钟内完成。现在装载全部需要 不到 5 秒

形象化

我现在将使用 plotly 来启用 Jupyter 笔记本的交互功能。

  • 第四步 :我首先创建一个带有几个导航控件的布局。

默认情况下,我希望显示前 6 个月的数据,并希望快速选择不同大小的时间窗口来浏览我的数据(1 个月、6 个月或 1 年):

  • 第 5 步 :然后我为我想要绘制的每个时间序列添加一个轨迹

在我的例子中,这是一个 100 时间序列:是的,这将是繁忙的,但你会发现这实际上是重点!).我使用 Plotly 散点图的 WebGL 版本( Scattergl ),因为当使用这个可视化包的交互功能时,它快了几个数量级:在 5 年内有 100 个信号,使用标准散点图会使笔记本无法使用…

我还根据每个时间序列的测量单位对图例进行了重新分组:在不知道传感器在设备上的位置的情况下,我可以很容易地过滤出具有潜在相似趋势和行为的信号。如果您可以访问您的设备的 P&ID(管道和仪表图),您将能够根据信号所连接的子部件对信号进行重新分组。为了在plotly的图例中轻松识别我的组,我只创建了一个虚拟的空信号:

3 分钟之后,我有了一个交互式图表,我可以查看任何我想要的比例(1 天或 5 年),我可以过滤掉信号以关注其中的一些信号,或者只是查看一下以确定值得关注的时间段。这是一年的数据:

按照杰森·布拉克的风格,将我所有的信号同时以相同的比例可视化,可以让我快速了解全局:

  • 我可以看到 2019 年 12 月发生了一些事情,2020 年 4 月发生了突然的变化,因为多个信号受到了明显的影响。
  • 我还可以分离出一些表现与其他信号非常不同的信号:在上图中,红色信号属于这一类别,需要进行更详细的调查:是质量差的传感器给我们的研究增加了噪声吗?或者实际上是潜在行为的一个很好的预测者?
  • 在几秒钟内,我可以选择 1 个月的时间范围,并使用滑块浏览 5 年的数据,以找出我想进一步研究的任何感兴趣的时期。

结论和未来工作

在本文中,我展示了一个简单的框架,该框架支持快速探索高度多元的时间序列信号。让我知道您自己探索大型时间序列数据集的最佳实践:我只是触及了表面,并将继续探索如何将它变成一个更健壮的框架,包括一些自动时间序列分析功能。敬请期待!

使用 Neo4j 进行 HDBSCAN 聚类

原文:https://towardsdatascience.com/hdbscan-clustering-with-neo4j-57e0cec57560?source=collection_archive---------16-----------------------

理解大数据

HDBSCAN 是一种聚类算法,可在大量嘈杂的异常值中识别出密切相关的元素孤岛。

我最近偶然看到了利兰·麦金尼斯的文章“【HDBSCAN 如何工作”,我被他解释复杂的机器学习算法的信息丰富、易懂的方式所打动。

用 HDBSCAN 标识的集群

与像 k-means 这样的聚类算法不同,使用 HDBSCAN,您不必预先决定您期望在数据中找到多少个聚类。在我看到 Maarten Grootendorst 在从文本中提取主题的教程中使用 HDBSCAN 后,我想了解更多。

麦金尼斯对 HDBSCAN 内部工作方式的描述会引起 Neo4j 用户的共鸣。他谈到了项目之间的关系图,以及作为过程的一部分,该算法如何找到最小生成树。

他的“graph ization”描述让我怀疑我是否可以用 Neo4j 实现 HDBSCAN。当我在工作中使用 HDBSCAN 时,我使用 Python 包而不是在 Neo4j 中实现算法。我认为没有理由重新发明轮子,特别是当我可以轻松地将工件从 hdbscan 包输出到 networkx ,然后将 graphml 导入到 Neo4j 时。

https://pypi.org/project/hdbscan/

然而,试着向别人解释一个概念是加深你自己理解的好方法。向计算机“解释”一个概念可能比向人解释更难,而且可能会提供一些有趣的见解。

通过在 Neo4j 中构建 HDBSCAN,我们还可以练习使用有用的 Neo4j 图形数据科学算法和 APOC 过程。让我们开始吧!

麦金尼斯将他对 HDBSCAN 的描述分为 5 个部分:

  1. 变换空间
  2. 建立最小生成树
  3. 构建集群层级
  4. 压缩聚类树
  5. 提取聚类

这是一个有点冗长的过程,但每个部分都很简单。当我们在 Neo4j 中追溯他的脚步时,我们将跟随他的轮廓。

设置您的环境

为了完成这个练习,我推荐使用一个免费的 Neo4j 沙盒,它预装了一个《权力的游戏》数据集。登录 Neo4j 沙盒,选择图形数据科学项目,启动。

启动 Neo4j 沙盒项目

当您的沙盒准备就绪时,选择“用浏览器打开”

改造空间

HDBSCAN 需要我们知道在某种度量空间中,我们数据集中的元素相互之间相距多远。HDBSCAN Python 包可以使用许多现成的距离度量。

对于我们的《权力的游戏》数据集,我们将使用图形数据科学库中的 节点相似度 算法创建一个自定义距离度量。节点相似性算法通常在二分图上工作得最好,但我认为它在这个应用程序中仍然有意义。

如果两个角色交互的字符集有明显的重叠,我们就说这两个角色是相似的。这将有助于我们的相似性分数反映人物的社会地位。例如,一个领导和一个下属可能彼此之间有频繁的互动,但是在他们更广泛的社交圈中几乎没有共同点。

在运行节点相似性算法之前,让我们创建一个包含Person节点和:INTERACTS关系的内存中图形投影。:INTERACTS关系的权重属性表示角色的交互次数。该图包含每本《权力的游戏》书的单独的:INTERACTS关系。我们将对内存图中所有书籍的权重求和。

CALL gds.graph.create(
'gotGraph',    
'Person',    
{INTERACTS: 
 {
     type: 'INTERACTS',
     orientation: 'UNDIRECTED',
     aggregation:'SUM',
     properties:{
            weight:{property:'weight'} 
        }    
 }    
}) YIELD graphName, nodeCount, relationshipCount

现在我们调用节点相似性算法,并将结果写回到我们的主图中,作为一个:SIMILAR_TO关系,其similarity得分在 0 到 1 的范围内。因为我们想要一个紧密连接的图,所以我们设置参数topK来为每个节点写多达 50 个:SIMILAR_TO关系。

CALL gds.nodeSimilarity.write('gotGraph', 
{
    writeRelationshipType: 'SIMILAR_TO',
    writeProperty: 'similarity',
    topK:50
})
YIELD nodesCompared, relationshipsWritten

HDBSCAN 需要距离的度量,其中较大的数字对应于关系较远的项目。我们的相似性得分是相反的,其中较高的数字对应于更密切相关的项目。我们可以通过从 1 中减去来将相似性转换为距离。

MATCH (:Person)-[rel:SIMILAR_TO]->(:Person)
SET rel.distance = 1 - rel.similarity

让我们来看看创建的距离分数的分布。

MATCH (p1:Person)-[s:SIMILAR_TO]-(p2:Person)
WHERE id(p1) < id(p2)
RETURN round(s.distance*10)/10.0 AS roundedDistance, 
count(*) as pairs
ORDER BY roundedDistance

这是结果的图表。

距离直方图

看起来我们有几对非常接近的字符,一个大约 0.5 的潜在有趣的组,以及 0.8-0.9 范围内的大量字符。

现在我们已经建立了一个度量空间,我们准备好转换它。我们想知道每个节点是生活在人口密集的还是人口稀少的邻居中。估计的一种方法是找到到第 k 个最近邻居的距离。我们称这个距离为 核心距离

您可以试验不同的 k 值。因为我们的许多Person节点的邻居数量相当少,所以我将 k 设置为 3。

:param k=> 3

现在我们可以计算每个Person节点的核心距离。如果一个Person的邻居少于 3 个,我们默认它们的核心距离为 2。

MATCH (p1:Person)-[s:SIMILAR_TO]-(p2:Person)
WITH p1, p2, min(s.distance) AS distance order by distance
WITH p1, collect(distance) AS neighbors
SET p1.coreDist = coalesce(neighbors[$k-1], 2)

空间转换的最后一步是计算每对Person节点的相互可达性
相互可达性是三个值中最大的:节点间的距离和两个节点的核心距离。

*MATCH (m1:Person)-[s:SIMILAR_TO]->(m2:Person) 
SET s.mutualReachability =  apoc.coll.max([m1.coreDist, m2.coreDist, s.distance])*

以这种方式转换空间强调了生活在图中人口稀少区域的节点的隔离。

让我们看看,对于图中密集部分的人,瑟曦·兰尼斯特,我们的相互可达性分数的分布结果如何。

*MATCH (p:Person {name:"Cersei Lannister"})-[s:SIMILAR_TO]-(p2)
RETURN DISTINCT p2.name as character,
round(p2.coreDist * 1000)/1000.0 as p2CoreDist, 
round(s.distance*1000)/1000.0 as distance, 
round(s.mutualReachability*1000)/1000.0 as reachability
ORDER BY round(s.distance*1000)/1000.0
LIMIT 5╒═══════════════════╤════════════╤══════════╤══════════════╕
│"character"        │"p2CoreDist"│"distance"│"reachability"│
╞═══════════════════╪════════════╪══════════╪══════════════╡
│"Joffrey Baratheon"│0.636       │0.544     │0.64          │
├───────────────────┼────────────┼──────────┼──────────────┤
│"Sansa Stark"      │0.644       │0.613     │0.644         │
├───────────────────┼────────────┼──────────┼──────────────┤
│"Tyrion Lannister" │0.678       │0.64      │0.678         │
├───────────────────┼────────────┼──────────┼──────────────┤
│"Robert Baratheon" │0.683       │0.683     │0.683         │
├───────────────────┼────────────┼──────────┼──────────────┤
│"Jaime Lannister"  │0.692       │0.689     │0.692         │
└───────────────────┴────────────┴──────────┴──────────────┘*

我们可以看到,虽然她的儿子乔佛里·拜拉席恩瑟曦的距离最小,但他们的相互可达性得分却上升到了与瑟曦第三接近的人,她的哥哥提利昂·兰尼斯特。在与珊莎·史塔克、提利昂·兰尼斯特、劳勃·拜拉席恩詹姆·兰尼斯特的关系中,相互的可达性是由 第二 人的核心距离决定的,而不是瑟曦的。

*MATCH (p:Person {name:"Cersei Lannister"})-[s:SIMILAR_TO]-(p2)
WITH DISTINCT p2, s.mutualReachability - s.distance as difference
RETURN avg(difference)*

对于瑟曦的关系,距离和相互可达性值之间的平均差值为 0.01

这样的次要角色反差太大了。

*MATCH (p:Person {name:"Thistle"})-[s:SIMILAR_TO]-(p2)
RETURN DISTINCT p2.name as character,
round(p2.coreDist * 1000)/1000.0 as p2CoreDist, 
round(s.distance*1000)/1000.0 as distance, 
round(s.mutualReachability*1000)/1000.0 as reachability
ORDER BY round(s.distance*1000)/1000.0
LIMIT 5╒══════════════╤════════════╤══════════╤══════════════╕
│"character"   │"p2CoreDist"│"distance"│"reachability"│
╞══════════════╪════════════╪══════════╪══════════════╡
│"Bump"        │0.875       │0.0       │0.875         │
├──────────────┼────────────┼──────────┼──────────────┤
│"Haggon"      │0.875       │0.0       │0.875         │
├──────────────┼────────────┼──────────┼──────────────┤
│"Harma"       │0.6         │0.875     │0.875         │
├──────────────┼────────────┼──────────┼──────────────┤
│"Mance Rayder"│0.765       │0.97      │0.97          │
├──────────────┼────────────┼──────────┼──────────────┤
│"Jon Snow"    │0.807       │0.991     │0.991         │
└──────────────┴────────────┴──────────┴──────────────┘*

他的几个邻居不是很近就是很远。k 值为 3 将所有邻居的相互可达性设置为高值。

*MATCH (p:Person {name:"Thistle"})-[s:SIMILAR_TO]-(p2)
WITH DISTINCT p2, s.mutualReachability - s.distance as difference
RETURN avg(difference)*

蓟的距离和相互可达性值之间的平均差值为 0.35

*MATCH (p1:Person)-[s:SIMILAR_TO]-(p2:Person)
WHERE id(p1) < id(p2)
RETURN round(s.mutualReachability*10)/10.0 AS roundedMutualReachability, 
count(*) as pairs
ORDER BY roundedMutualReachability*

这是转换数据的图表。

相互可达性直方图

我们看到,作为转换的结果,分布向范围的高端移动了一点。和一些次要角色的关系已经在 2.0 区域结束了。较高的 k 值会使分布偏移更多。

构建最小生成树

“DBSCAN 如何工作”中的下一节描述了为我们转换的度量空间构建最小生成树。这是一组覆盖每个节点的关系,关系中没有循环,并且关系的总权重最小。图形数据科学库中的 最小权重生成树 算法会为我们找到这棵树。

我们将一个新的图表加载到图表目录中,该图表目录包括带有mutualReachability属性的Person节点和:SIMILAR_TO关系。

*CALL gds.graph.create(
    'gotSimilarity',
    "Person",
    { 
     SIMILAR_TO: {
        type: 'SIMILAR_TO',
        properties: 'mutualReachability',
        orientation: 'UNDIRECTED'
     }
    }) YIELD graphName, nodeCount, relationshipCount*

我们调用最小生成树算法,并将结果作为:MST关系写回到我们的图中。我们必须为算法的运行指定一个起始节点。我任意选择了T5【珊莎·史塔克】T6。你可以尝试一个不同的Person,基于 Prim 的算法的执行生成一个略有不同的树。起始节点的选择应该不会对最终的集群产生很大的影响,因为每个节点最终仍然会链接到最小生成树中其最近的邻居之一。

*MATCH (m:Person {name:"Sansa Stark"})CALL gds.alpha.spanningTree.minimum.write('gotSimilarity', {startNodeId: id(m),
relationshipWeightProperty:'mutualReachability', writeProperty:'MST',
weightWriteProperty:'minTreeDistance'}) 
YIELD effectiveNodeCount, createMillis, computeMillis, writeMillis RETURN **

在这一点上, Neo4j Bloom 网络可视化提供了一种查看我们数据的好方法。从 Neo4j 沙盒项目页面,选择“用 Bloom 打开。**

点击“打开 Bloom”按钮附近的按键图标显示登录凭证。登录后,选择《权力的游戏》视角。

我们对:MST的关系感兴趣。在搜索框中单击,键入“MST”,然后选择 MST 关系。

按“ <返回> ”,Bloom 将执行查询。点击可视化右下角的激活分层布局按钮,可以很好地查看我们的树。您可能需要使用“层次关系”按钮旁边的“旋转”按钮,使树的根出现在顶部。Person节点的颜色和大小已经用基于规则的格式进行了设置,这在我们的练习中是不需要的。如果愿意,您可以删除该格式。

开花时可视化的最小重量生成树的一部分

构建集群层次结构

算法的下一步是基于最小生成树创建集群。HDBSCAN 是一种分层(也称为凝聚)聚类算法。分层聚类用于多种聚类算法,包括图形数据科学库中的 Louvain 社区检测算法。

基本的分层聚类算法如下:

  1. 将数据集中的每一项都想象成一个大小为 1 的簇。
  2. 找到彼此最接近的两个集群,并将它们合并成一个集群。
  3. 重复步骤 2,直到将所有集群合并成一个大集群
  4. 决定步骤 1 和步骤 3 之间的哪些中间聚类对您的分析有意义。

这里有一个集群关系树的可视化,称为树状图,它表示当我们向可视化顶部移动时,可视化底部的小集群合并成越来越大的集群。

使用 HDBSCAN 生成的单个连接树树形图示例

在上面的层次聚类描述的第 2 步中,当我们说聚类彼此“接近”时,定义我们的意思是很重要的。在 HDBSCAN 中,我们使用最小生成树中的关系来定义“关闭”。**

我们从树中具有最低权重的关系开始,并在该关系的合并聚类。我们将移动到下一个最低权重的关系,并继续以这种方式合并,直到我们穷尽了树中的所有关系。

HDBSCAN 还有助于我们在层次聚类描述的第 4 步中确定哪些聚类“对我们的分析有意义”。我们将在本练习的最后部分 中看到这是如何发生的,提取集群

返回 Neo4j 浏览器执行以下命令。首先,我们将创建一个 APOC 自定义函数来标识对于任何给定节点来说在层次结构中最远的集群。然后,我们可以使用该函数来构建我们的集群层次结构。

**call apoc.custom.asFunction('getLastCluster',
"MATCH (n) where id(n) = id($n)
WITH n MATCH clustPath = (n)-[:IN_CLUSTER*0..]->(c)
WITH clustPath order by length(clustPath) desc
LIMIT 1
RETURN nodes(clustPath)[-1] as lastCluster",
"NODE",
[["n","NODE"]],
false,
"Starting from a given node, get the node at the end of the longest path of IN_CLUSTER relationships")**

赛弗声明如下:

  1. 查找最小生成树中尚未计算的最短边。
  2. 然后,它为生成树边缘两端的节点找到最深的现有集群。
  3. 它创建一个新的集群,并将节点连接到该集群。
  4. 计算新群集的大小
  5. 将生成树边标记为已评估。
**MATCH (a)-[m:MST]->(b)
WHERE m.evaluated is null
WITH a, b, m
ORDER BY m.minTreeDistance
LIMIT 1
WITH custom.getLastCluster(a).lastCluster as cluster1, custom.getLastCluster(b).lastCluster as cluster2,
m
CREATE (cluster1)-[r1:IN_CLUSTER]->(c:Cluster)
                <-[r2:IN_CLUSTER]- (cluster2)
SET r1.splitDistance = m.minTreeDistance,
r2.splitDistance = m.minTreeDistance,
c.size = coalesce(cluster1.size, 1) + coalesce(cluster2.size, 1),
m.evaluated = True
RETURN ***

Gurn 的儿子 gun thor 和被笼罩的领主是第一个加入集群的两个角色。如果我们将鼠标悬停在:MST关系上,我们会看到minTreeDistance为 0.0。运行这个查询来查看 Gunthor 和 closed 与之交互的一组人。

**MATCH (p1:Person {name:"Shrouded Lord"})-[:INTERACTS]->(p2)
RETURN p1, p2
UNION ALL
MATCH (p1:Person {name:"Gunthor son of Gurn"})-[:INTERACTS]->(p2)
RETURN p1, p2**

冈恩之子冈瑟和神秘领主的互动

他们都只和一个人互动,提利昂·兰尼斯特。这使得它们的相邻集之间有 100%的重叠,所以根据我们的距离测量,它们是尽可能接近的。至少还有另外两个角色也只和提利昂互动,所以冈瑟笼罩主的相互可达性为 0.0。

您可以继续运行上面的集群查询,一次创建一个新的集群。这样做几次后,运行下面的语句,该语句使用 apoc.periodic.commit 过程来完成集群的创建。它一次处理一个最小关系,直到结果计数返回零。

**call apoc.periodic.commit(
"MATCH (a)-[m:MST]->(b)
WHERE m.evaluated is null
WITH a, b, m
ORDER BY m.minTreeDistance
LIMIT 1WITH 
custom.getLastCluster(a).lastCluster as cluster1, custom.getLastCluster(b).lastCluster as cluster2, mCREATE (cluster1)-[r1:IN_CLUSTER]->(c:Cluster)
                <-[r2:IN_CLUSTER]- (cluster2)
SET r1.splitDistance = m.minTreeDistance,
r2.splitDistance = m.minTreeDistance,
c.size = coalesce(cluster1.size, 1) + coalesce(cluster2.size, 1),
m.evaluated = True
RETURN count(*)", {})**

当你完成后,你可以回到 Neo4j Bloom 查看我们的聚类树。点击左上方侧边栏中的侧边栏图标来展开透视图编辑器,然后单击刷新透视图按钮来获取最新的数据。

滚动到类别列表的底部,为“集群”添加一个类别

单击左侧的齿轮微件打开设置,并将节点查询限制增加到 2,000 以上。

节点查询限制设置

再次点按齿轮 widget 以关闭“设置”边栏。右键单击画布并清除场景。现在,如果您在搜索框中搜索 IN_CLUSTER 关系,随着每个人的加入,您可以很好地看到我们的聚类树。

开花的丛树片段

压缩聚类树

该过程的下一步是压缩聚类树。最小集群大小是运行 HDBSCAN 时可以控制的重要参数之一。如果我们设置一个低的最小集群大小,我们将得到更多更小的集群。如果我们设置更高的最小集群大小,我们将得到更少、更大的集群。

在 Neo4j 浏览器中执行该命令,将 minClusterSize 参数设置为 20。

**:param minClusterSize => 20**

下一个命令将把任何连接到 20 个或更少节点的集群的Person节点分配给它们的第一个大于最小大小的祖先集群。

**MATCH (c1:Cluster)-[r:IN_CLUSTER]->(c2:Cluster)
WHERE c1.size < $minClusterSize and c2.size >= $minClusterSize
WITH c1, r, c2
MATCH (m:Person)-[:IN_CLUSTER*]->(c1)
CREATE (m)-[:IN_CLUSTER {splitDistance:r.splitDistance}]->(c2)**

然后,我们可以删除规模过小的集群。

**MATCH (c:Cluster) where c.size < $minClusterSize detach delete c**

如果我们从树的顶部开始向下,我们会看到许多分支代表一个或两个脱离主集群的节点。

我们可以认为这是一个继续存在的主集群,只是减少了一些成员。其他分裂表示较大的集群分裂成两个可行的子集群。我们将这些可行的子集群的开始标记为“集群出生”。

**MATCH (c1:Cluster)-[r:IN_CLUSTER]->(c)<-[:IN_CLUSTER]-(c2:Cluster)
WHERE c1.size >= $minClusterSize and c2.size >= $minClusterSize
AND id(c1) < id(c2)
WITH r.splitDistance as splitDistance, [c1, c2] as clusters
UNWIND clusters as cluster
WITH cluster, 1/splitDistance as lambda
SET cluster:ClusterBirth, cluster.birthLambda = lambda
RETURN ***

我们还想把树根算作一个集群的诞生。

**MATCH (c:Cluster) where not (c)-[:IN_CLUSTER]->()
SET c:ClusterBirth, c.birthLambda = 0
RETURN ***

在上面的第一个ClusterBirth赋值查询中,我们将名为 lambda 的值设置为 1/splitDistance。

回想一下,我们的聚类树的根附近的节点对应于最小权重生成树中的最大距离,而聚类树的叶节点对应于最小权重生成树中的最小距离。

作为分割距离的倒数,λ值在根部开始变小,并向叶子方向增加。稍后我们将使用 lambdas 来决定保留哪些聚类作为最终结果。

接下来,我们将在集群分裂成子集群或低于最小集群大小之前将节点标记为“集群死亡”

*MATCH (c:Cluster) where not (c)<-[:IN_CLUSTER]-(:Cluster)
OR (c)<-[:IN_CLUSTER]-(:ClusterBirth)
SET c:ClusterDeath
RETURN c*

我们在这一部分的最后一个任务是将从集群诞生到集群死亡路径中的所有节点合并成一个集群

为此,我们将使用两个 APOC 过程。 apoc.path.expand 过程允许我们沿着:IN_CLUSTER关系搜索,直到到达:ClusterDeath节点。

apoc.refactor.mergeNodes 过程将多个节点合并成一个节点,同时保留节点的关系。

*MATCH (cb:ClusterBirth)
CALL apoc.path.expand(cb, "<IN_CLUSTER", "/ClusterDeath", 1, 800) YIELD path
with nodes(path) as mergeList
CALL apoc.refactor.mergeNodes(mergeList, {properties: "discard", mergeRels:true}) YIELD node
RETURN node*

因为我们合并了两个以上的节点来创建我们的一些压缩集群,所以我们以一些不必要的自我关系结束。使用此查询删除它们。

*match (c:Cluster)-[r:IN_CLUSTER]->(c)
DELETE r*

提取聚类

现在我们有了一个压缩的集群层次结构。您可以返回到 Bloom,清除场景,并搜索簇-簇模式来查看结构。

集群层次结构

剩余的每一个聚类都高于最小大小阈值,我们希望选择质量最高的进行输出。我们使用λ,我们计算为 1/splitDistance 来指导我们的选择。**

对于集群中的每个节点,我们计算集群诞生时的 lambda 与节点离开集群时的 lambda 之间的差异,这是因为节点脱离了集群,或者是因为集群已经分裂为可行的子集群。群集中所有节点的这些λ值的 之和称为 群的稳定性 。使用此查询来计算我们的集群的稳定性。

*MATCH (c:Cluster)<-[ic:IN_CLUSTER]-(n)
WITH c, sum((1/ic.splitDistance - c.birthLambda) * coalesce(n.size, 1)) as stability
SET c.stability = stability*

我们暂时将所有的叶簇设置为“选中”

*MATCH (c:Cluster)
WHERE NOT (c)<-[:IN_CLUSTER]-(:Cluster)
SET c:Selected
RETURN c*

从离根最远的分裂开始,我们现在考虑每个集群分裂,以决定是选择分裂的子节点还是父节点。我们将对聚类分割进行编号,以跟踪评估顺序。

*MATCH p = (:Cluster)-[:IN_CLUSTER]->(c:Cluster)-[:IN_CLUSTER*]->(:Cluster) 
WITH c, length(p) as pathLength
WITH c, max(pathLength) as distanceToRoot
ORDER BY distanceToRoot desc
WITH collect(c) as clusters
UNWIND range(1, size(clusters)) AS rank
WITH clusters[rank-1] as cluster, rank
SET cluster.evaluationOrder = rank*

在每次集群分裂时,我们比较父稳定性和子稳定性的总和* 。如果子稳定性较大,我们将父稳定性设置为子稳定性的总和。
如果父类稳定性更大,我们将父类设置为选中,取消选择子类。*

apoc . periodic . iterate过程让我们按照求值顺序遍历拆分。我们使用apoc . do . when过程来处理条件更新逻辑。

*call apoc.periodic.iterate("
MATCH (c:Cluster) where c.evaluationOrder is not null 
RETURN c.evaluationOrder as evaluationOrder 
order by evaluationOrder",
"MATCH (c:Cluster  {evaluationOrder:evaluationOrder})<-[:IN_CLUSTER]-(child)
WITH c.stability as parentStability, sum(child.stability) as childStability, 
c AS parent, 
collect(child) as children
call apoc.do.when(parentStability < childStability,
'set parent.stability = childStability',
'set parent:Selected FOREACH(child in children | REMOVE child:Selected)',
{parent:parent, childStability:childStability, children:children}) YIELD value
RETURN value", 
{batchMode:"SINGLE"})*

保留Selected标签的集群是 HDBSCAN 的最终输出。您可以使用该查询返回集群成员。

*MATCH (s:Selected)<-[:IN_CLUSTER*]-(m:Person)
return id(s), s.size, collect(m.name) as names*

我预计角色会倾向于与同一所房子里的人互动,因此一些房子会倾向于主导我们的输出集群。根据这个查询,似乎有几个集群是这种情况,而其他集群则更像是一个大杂烩。

*MATCH (c:Selected)<-[:IN_CLUSTER*]-(p:Person)-[:BELONGS_TO]->(h:House)
WITH c, h, count(*) as houseCount ORDER BY houseCount DESC
RETURN id(c), c.size, 
  collect({name: h.name, count:houseCount, 
           percent:houseCount*100/c.size})[..5] as houses╒═══════╤════════╤════════════════════════════════════════════╕
│"id(c)"│"c.size"│"houses"                                    │
╞═══════╪════════╪════════════════════════════════════════════╡
│3062   │438     │[{"name":"None","count":74,"percent":16},{"n│
│       │        │ame":"Stark","count":55,"percent":12},{"name│
│       │        │":"Night's Watch","count":45,"percent":10},{│
│       │        │"name":"Lannister","count":35,"percent":7},{│
│       │        │"name":"Baratheon","count":31,"percent":7}] │
├───────┼────────┼────────────────────────────────────────────┤
│3137   │59      │[{"name":"Night's Watch","count":31,"percent│
│       │        │":52},{"name":"Wildling","count":10,"percent│
│       │        │":16},{"name":"None","count":3,"percent":5},│
│       │        │{"name":"Stark","count":2,"percent":3},{"nam│
│       │        │e":"Kingswood Brotherhood","count":1,"percen│
│       │        │t":1}]                                      │
├───────┼────────┼────────────────────────────────────────────┤
│2892   │114     │[{"name":"None","count":24,"percent":21},{"n│
│       │        │ame":"Stark","count":22,"percent":19},{"name│
│       │        │":"Baratheon","count":16,"percent":14},{"nam│
│       │        │e":"Tully","count":9,"percent":7},{"name":"L│
│       │        │annister","count":8,"percent":7}]           │
├───────┼────────┼────────────────────────────────────────────┤
│3008   │41      │[{"name":"Greyjoy","count":16,"percent":39},│
│       │        │{"name":"None","count":5,"percent":12},{"nam│
│       │        │e":"Bolton","count":5,"percent":12},{"name":│
│       │        │"Stark","count":5,"percent":12},{"name":"Goo│
│       │        │dbrother","count":3,"percent":7}]           │
├───────┼────────┼────────────────────────────────────────────┤
│2923   │43      │[{"name":"Lannister","count":14,"percent":32│
│       │        │},{"name":"Tyrell","count":5,"percent":11},{│
│       │        │"name":"None","count":5,"percent":11},{"name│
│       │        │":"Baratheon","count":3,"percent":6},{"name"│
│       │        │:"Redwyne","count":2,"percent":4}]          │
├───────┼────────┼────────────────────────────────────────────┤
│3063   │25      │[{"name":"Lannister","count":10,"percent":40│
│       │        │},{"name":"None","count":10,"percent":40},{"│
│       │        │name":"Clegane","count":6,"percent":24},{"na│
│       │        │me":"Brotherhood without banners","count":4,│
│       │        │"percent":16},{"name":"Stark","count":2,"per│
│       │        │cent":8}]                                   │
└───────┴────────┴────────────────────────────────────────────┘*

我们运行的算法将 463 个字符放在一个簇中。然而,至少有一个:INTERACTION关系的 332 个字符仍然在所选的聚类之外,包括一些主要字符。

*MATCH (p:Person) where not (p)-[:IN_CLUSTER*]->(:Selected)
AND (p)-[:INTERACTS]-()
RETURN p.name order by p.pageRank desc limit 10╒════════════════════╕
│"p.name"            │
╞════════════════════╡
│"Jon Snow"          │
├────────────────────┤
│"Stannis Baratheon" │
├────────────────────┤
│"Daenerys Targaryen"│
├────────────────────┤
│"Arya Stark"        │
├────────────────────┤
│"Robb Stark"        │
├────────────────────┤
│"Eddard Stark"      │
├────────────────────┤
│"Catelyn Stark"     │
├────────────────────┤
│"Theon Greyjoy"     │
├────────────────────┤
│"Tywin Lannister"   │
├────────────────────┤
│"Samwell Tarly"     │
└────────────────────┘*

这是 HDBSCAN 的特性,不是 bug。我们在数据中发现了密集的星团。

之后,我们可以决定如何处理边缘案例。也许这些未分类的角色中的一些不适合普通的交互模式。

HDBSCAN 文档建议调整参数以减少未聚类的数据元素的数量,并建议根据软聚类将未聚类的数据元素分配给聚类。

我希望使用 Neo4j 学习 HDBSCAN 算法让您对该算法的工作原理有了更深入的了解。

您可以将这种方法与其他社区检测和聚类算法进行比较。我希望 HDBSCAN 证明是您的数据科学工具包中的一个有用工具。

数据科学工作流程的 HDFS 简单 Docker 安装指南

原文:https://towardsdatascience.com/hdfs-simple-docker-installation-guide-for-data-science-workflow-b3ca764fc94b?source=collection_archive---------4-----------------------

使用 Docker 映像,在您的系统上轻松逐步安装和使用 HDFS。

卢克·切瑟在 Unsplash 上的照片

在这篇小文章中,我们将讨论如何在你的计算机上设置基于 Docker 的 Hadoop 分布式文件系统,并将讨论一个简单的例子来演示这个用例。此外,一旦安装准备就绪,您就可以开始构建自己的 map-reduce 作业来使用 Hadoop DFS。

从克隆 HDFS 项目开始

首先,你需要克隆下面的 Git 库 到你系统中你想要的目录。我更喜欢把它克隆到家里,以便演示和方便使用。

git clone [https://github.com/big-data-europe/docker-hadoop](https://github.com/big-data-europe/docker-hadoop)

然后使用更改目录命令进入项目库:

cd docker-hadoop

现在执行一个" ls -l "命令,您可以看到这个存储库中的所有文件,如下所示。

命令“ ls -l 的输出

获取 Docker 图像并创建容器

之后,您需要启动在您的系统上设置 HDFS 所需的容器。为此,项目目录中有一个 docker-compose.yml 文件,您需要使用" docker-compose up "命令从 Docker hub 下载并安装所需的映像,并基于 docker-compose.yml 文件配置容器。“ -d ”标志以分离模式运行容器。如果在本地找不到图像,Docker 会从 DockerHub 下载它们,但是如果您想要手动下载它们,您可以使用“ docker-compose pull ”。

注意:如果出现权限错误,请使用“ sudo ”作为这些命令的前缀。

# download images required for setting up HDFS and spin up necessary # containers.
docker-compose up -d

命令" sudo docker-compose up -d 的输出

上面的命令将从 docker hub 下载设置 HDFS 容器所需的所有 Docker 映像。根据您的网速,下载图像可能需要一点时间。

现在,要查看当前正在运行的 Docker 容器,使用命令列出所有活动的容器。

# List all the available running docker containers.
docker container ls

命令" sudo docker 容器 ls "的输出

与 namenode 连接

一旦您将所有文件复制到 Hadoop 集群中的一个目录中(注意:在本例中,我已经将文件复制到了 /tmp ),现在您可以在 bash 模式下的交互式终端模式中使用以下命令进入 namenode 中。

# Enter inside namenode and open its bash
docker exec -it namenode /bin/bash

例:sudo docker CP my _ input . txt NameNode:/tmp/

复制必要的 JAR 和输入文件

现在我们需要复制包含我们的 map-reduce 作业的 jar 文件,并使用以下 Docker 命令将它们复制到 HDFS 的 namenode(将运行您的作业)中:

docker cp <file_name> namenode:/<path>

与 namenode 交互

在交互式终端中输入名称节点后,使用以下 HDFS 命令与名称节点进行交互。

# HDFS list commands to show all the directories in root "/"
hdfs dfs -ls /# Create a new directory inside HDFS using mkdir tag.
hdfs dfs -mkdir -p /user/root# Copy the files to the input path in HDFS.
hdfs dfs -put <file_name> <path># Have a look at the content of your input file.
hdfs dfs -cat <input_file>

上述命令的输出

运行 Hadoop Map Reduce 作业

现在,您可以使用以下命令运行地图缩减作业:

# Run map reduce job from the path where you have the jar file.
hadoop jar <jar_file_name> <class_name> input output

例:Hadoop jar word _ counter . jar org . Apache . Hadoop . examples . word count 输入输出

一旦该命令成功运行,您会注意到 map-reduce 作业完成了它的执行,并在控制台上显示了关于该进程的一些信息。

检查你的输出

作业成功执行后,您可以在 HDFS 使用 cat 命令检查输出:

# Check the content of the output file after running the job
hdfs dfs -cat <output_file>

命令"HDFS DFS-cat output _ file/*的输出

您将看到您的单词计数器作业的词频应该打印在控制台上。

****恭喜!您已经成功配置并创建了您的第一个 Hadoop HDFS map-reduce 作业!

额外小费

您可以在本地主机的端口 9870 上访问 HDFS namenode 的 UI 仪表板。使用以下链接:

http://:9870

NameNode UI:http://:9870****

结论:

因此,基本上 HDFS 的设置对于简单的数据科学工作流来说很简单,并且您在阅读本文后已经了解到,设置一个基于本地 Docker 的 HDFS 设置并开始编写自己的 map-reduce 作业来执行各种任务是多么简单。如果你不是很熟悉地图减少工作,所以我附上了一些有用的链接。尽情享受吧!

  1. https://en.wikipedia.org/wiki/MapReduce
  2. https://hadoop.apache.org/docs/r1.2.1/mapred_tutorial.html
  3. https://hadoop.apache.org/docs/r1.2.1/hdfs_user_guide.html

希望这篇文章对你有帮助!
谢谢!

使用 Python 进行头部姿态估计

原文:https://towardsdatascience.com/head-pose-estimation-using-python-d165d3541600?source=collection_archive---------3-----------------------

您所需要的只是 OpenCV 和 Mediapipe 库。

玛利亚·特内娃在 Unsplash 上拍摄的照片

介绍

头部姿态估计是现有的计算机视觉任务之一。在这个任务中,我们想从物体的平移和旋转中知道物体的姿态。

这项任务有很多应用。例如,我们可以检测驾驶员是否在注意道路。第二个例子是,我们可以检查学生是否从学习中分心。我们可以用它做很多应用。

如你所知,我们只有二维图像。如何依靠图像本身来估计物体的姿态?我们可以使用一种称为 n 点透视(PnP)的解决方案。

PnP 问题方程看起来像这样:

从这个方程,我们可以检索旋转和平移矩阵。但是在我们得到这些矩阵之前,这个方程需要三个输入,例如:

  • 图像空间中的 2D 坐标
  • 世界空间中的 3D 坐标
  • 相机参数,如焦点、中心坐标和倾斜参数

从这个等式中,我们得到两个主要问题:

  • 我们如何获得这些输入?
  • 我们如何根据这些输入来估计物体的姿态呢?

这篇文章将告诉你如何做。在本文中,我们将使用 Python 作为编程语言。此外,我们使用 mediapipe 库来检测面部关键点,使用 OpenCV 库来估计头部的姿态。

这是我们将创建的预览:

图片由作者捕捉。

没有别的了,让我们开始吧!

履行

安装库

在我们开始实现之前,第一步是安装库。在这种情况下,我们将使用 pip 安装 OpenCV 和 Mediapipe 库。在您的终端上,请编写以下命令:

**pip install opencv-python
pip install mediapipe**

加载库

安装完库之后,下一步是将库加载到我们的代码中。我们将导入 NumPy、OpenCV 和 Mediapipe 库。请添加这行代码:

初始化对象

加载完库之后,下一步是初始化几个对象。我们初始化了两个对象。它们是:

  • Mediapipe 库中的 FaceMesh 对象。该对象将检测人脸,也检测一个或多个人脸的关键点。
  • OpenCV 库中的 VideoCapture 对象。该对象将用于从网络摄像机中检索图像。我们将对象的参数设置为 0,用于从网络摄像头中检索图像。

请添加这几行代码:

捕捉图像

现在我们已经初始化了对象。下一步是从网络摄像头捕捉图像。为此,请添加以下代码行:

处理图像

在我们捕获图像之后,下一步是处理图像。供您参考,OpenCV 和 Mediapipe 库读取它们的图像是不同的。

在 OpenCV 库上,图像在 BGR 颜色空间中。同时,mediapipe 库需要一个具有 RGB 颜色空间的图像。

因此,我们需要首先将颜色空间转换为 RGB,应用人脸标志检测,然后将其转换回 BGR 颜色空间。

请添加以下代码行(注意缩进):

检索 2D 和三维坐标

处理完图像后,下一步是检索关键点坐标。供您参考,mediapipe 的面部标志检测算法可以从面部捕捉大约 468 个关键点。每个关键点都在三维坐标上。

对于头部姿态估计,我们不必使用所有的关键点。相反,我们选择至少能代表一张脸的 6 个点。这些点在眼睛的边缘,鼻子,下巴和嘴巴的边缘。

要访问这些点,我们可以参考 BlazeFace 模型中使用的索引。我已经标记了索引。这是它的照片:

这张图片是从 TensorFlow 的 GitHub 库中检索出来的,并由作者进行了编辑。

现在让我们提取这些关键点。对于 2D 坐标,我们将只取 x 和 y 轴坐标。对于三维坐标,我们检索所有的轴。

但是在我们提取这些关键点之前,我们必须用图像的宽度乘以 x 轴。此外,我们将 y 轴乘以图像的高度。

此外,我们将获得机头坐标。我们这样做是为了显示我们鼻子在图像空间的投影。

现在让我们添加这几行代码,注意缩进:

获取摄像机矩阵

现在我们有了面部关键点的 2D 和 3D 坐标。下一步是得到相机矩阵。让我们再次回忆一下相机矩阵。

正如你从上面看到的,我们需要几个参数。第一个是重点。我们可以通过获取图像的宽度来获得焦点(fx 和 fy)。

我们将采用的第二个参数是偏斜参数。该参数的符号为 gamma。对于这个参数,我们将值设置为 0。

第三个参数是我们图像的中心坐标。我们将用图像的宽度设置 u0,用图像的高度设置 v0。

现在让我们通过生成一个 NumPy 数组来创建矩阵。现在让我们添加这几行代码:

应用 PnP 问题

在应用 PnP 问题之前,我们需要添加另一个矩阵。这是一个距离矩阵。这个矩阵只包含零,它的形状是 4x1。现在,让我们通过添加这行代码来创建矩阵:

我们有所有的输入,从 2D 坐标,三维坐标,相机参数矩阵,和空距离矩阵。让我们通过添加这行代码将 PnP 应用于我们的问题:

将旋转向量转换成矩阵

从这个过程中,我们得到了平移向量和旋转向量。等等,旋转部分不是矩阵格式的。我们不能用它来恢复旋转角度。

别担心。我们可以用 cv2 把向量转换成矩阵。罗德里格斯函数。

现在让我们添加这行代码:

获取角度

现在我们有了旋转矩阵。现在让我们检索每个轴上的旋转角度。为此,我们可以使用 cv2。RQDecomp3x3 函数用于提取角度。

现在让我们添加这行代码:

捕捉头部的方向并显示结果

我们现在要做的最后一步是确定我们的方向。我们显示方向并创建一条线来查看我们的鼻子在图像空间上的投影。

现在让我们添加这几行代码:

通过组合所有这些代码行,结果将如下所示:

GIF 是作者捕获的。

结束语

干得好!我们已经使用 Python 实现了头部姿态估计。我希望它能帮助你建立你的计算机视觉解决方案,尤其是头部姿态估计问题。

如果你对我的文章感兴趣,可以在 Medium 上关注我。如果有任何问题,可以在 LinkedIn 上联系我。

如果您在编写代码时遇到了困惑,您可以在这里查看完整的代码来帮助您:

感谢您阅读我的文章!

参考

[1]https://medium . com/analytics-vid hya/real-time-head-pose-estimation-with-opencv-and-dlib-e8dc 10d 62078
【2】https://learnopencv . com/head-pose-estimation-using-opencv-and-dlib/

健康数据投资可能被浪费?

原文:https://towardsdatascience.com/health-data-investments-potentially-wasted-32c33b4ec9f9?source=collection_archive---------53-----------------------

我们如何才能更好地实现投资数字健康研究和解决方案的潜力?

[图像信用](https://www.freepik.com/vectors/people'>People vector created by katemangostar - www.freepik.com)

在新冠肺炎疫情的推动下,的数字医疗采用速度加快了三年。从 2019 年到 2020 年,企业融资增加了 103%,仅在美国就达到 219 亿美元。那么,为什么参与度指标——尤其是关于健康行为改变的指标——仍然如此令人失望呢?

资源的涌入为数字健康研究和商业创造了大量的机会,但也暴露了其功效的局限性。

通过智能手表、手机和大量其他设备,我们似乎可以为一个人提供他们可能需要的所有测量,以全面了解他们当前的健康状况和未来的健康风险。但是当我们设计数字健康产品时,我们希望人们不仅仅是参与其中。我们还希望人们能够改变自己的行为,过上更幸福、更健康的生活。

许多数字健康和医疗保健数据科学文化基于这样一种假设,即个性化健康数据本身可以通知和激励或“推动”数字健康用户做出更健康的生活方式选择。然而,我们可能会经历一点点“发光物体综合症”,寄希望于个性化的健康数据带来现实生活中的行为改变。事实上,我们经常被低采用率和低参与率所困扰。只有一小部分的数字健康产品被用户以任何方式实现,给他们足够的输入来成功地改变行为。

事实上,在 2020 年疫情来袭之前,数字医疗的采用率实际上已经下降,从前一年的 48%下降到 35%。这似乎部分是由于用户所认为的“低质量的数字体验”。要改变人们的健康行为,我们必须首先让他们充分参与。让他们充分参与进来,采用数字健康工具。然后让他们更多地继续使用它以获得长期利益。

[形象信用](https://www.freepik.com/vectors/people'>People vector created by katemangostar - www.freepik.com)

数据够吗?

问题是,为什么数字健康创造者和用户可以获得的所有健康数据分析没有有效地吸引足够多的人?

答案可能在于我们经常对人类行为做出的另一个假设。

行为科学是从心理学和经济学发展而来的一门学科,致力于预测和解释人类行为。人们如何行动通常被认为是由他们是“理性”还是“非理性”决定的。例如,你可能听说过“系统 1 和系统 2”,这是诺贝尔奖获得者丹尼尔·卡内曼在他的开创性文章“思考的快慢”中带给我们的自动和有意识的思维过程?

健康的生活方式被认为是合理的,不健康的被认为是不合理的。几乎可以说,当人们不知何故失去了对自己和决策的控制时,就会做出不健康的选择。理性选择被视为明智的决策,最有可能基于可靠的数据。

如果我们应用这一行为科学框架,那么健康数据必然会帮助人们变得更加理性,从而做出更加健康的决定。还有什么比更多的数据更能提高理性,让理性的决策建立在更多的数据基础上呢?

但数字医疗解决方案的低采用率和参与率表明,这并不是全部情况。

房间里的情绪大象

准确和个性化健康数据的存在甚至承诺不足以让人们做出并保持健康的选择。对访问数字健康数据的人类行为的准确预测需要将该行为的更深层次的决定因素构建到我们的预测分析中。

比起认知问题的解决,情感更经常是人类行为的主导因素。情绪也是我们如何经历生活的特征,是我们生活故事中不可或缺的一部分。此外,情绪通常在人类功能的潜意识或无意识层面运作,并在我们没有意识到的情况下指导我们的行动、决定和行为模式。

也许我们在数字健康中的预测数据模型中缺少的是情感指标,这可能有助于我们解释更大比例的人类行为驱动因素,更有效地预测行为,并更可持续地让用户参与数字健康体验。

所以,让我们把情绪写进我们的预测模型。这是怎么回事?

情绪的度量

将情绪整合到我们的健康行为预测模型中可能会让我们更接近实现数字健康的潜力,但我们如何测量情绪并大规模进行大数据分析呢?

在数字健康中,情绪大多被概念化,并以面部表情来衡量。这源于发展心理学的通用面部表情理论,从中我们可以推断出其他人的感受。这种情绪指标的伟大用例是像临床决策支持系统这样的工具,在这些工具中,健康专家可以根据患者的面部表情更准确地识别他们的感受。有时,我们觉得我们不能安全地表达情感,有时我们可能不知道自己的感受,尤其是当我们处于病人这一脆弱的角色时。

然而,旨在帮助人们改变健康行为模式的数字健康技术,不会从其用户识别他人情绪的过程中获得同样多的价值。将情绪融入数字健康工具的一种通用方法是尝试预测人们使用该工具时的情绪反应。有助于个人层面行为改变的是将自己的情绪带入有意识的意识中。

在数字健康产品中创造隐含的积极情感体验会更好,我们可以通过以用户为中心的技术设计中的深度情感设计,借鉴品牌创建和用户参与中的客户忠诚度构建技术来做到这一点。

谷歌心脏框架

[图像信用](https://www.freepik.com/vectors/clouds'>Clouds vector created by vectorjuice - www.freepik.com)

如果你正在考虑在预测人类行为变化的数字健康数据模型中包含情绪,你可能想使用谷歌心脏框架作为起点。

开发该框架是为了增加用户对基于网络的产品的参与,它也可以适用于其他类型的技术。HEART 框架构建了我们对用户参与度的思考,将用户“快乐”放在首位。首字母缩写代表:快乐、参与、采纳、保持和任务成功。

对于每个度量类别,该框架还要求您确定与该度量一致的目标、信号和度量。

当考虑如何将情绪纳入预测模型时,使用框架中的快乐类别,但扩展用户满意度的定义,超出通常的 5 点李克特量表问题“您对该功能/产品的满意度如何?”。

相反,确定你的用户认同的价值观,他们信任的信息类型,并以此为基础建立你的幸福指数。

你已经离增加用户参与度更近了一步,创造积极的情感体验和对你产品的忠诚度,这将帮助人们实现长期健康行为的改变。

[形象信用](https://www.freepik.com/vectors/business'>Business vector created by jcomp - www.freepik.com)

推荐

你不需要知道所有的答案。

这可能是一个难以接受的说法。作为科学家、数据分析师或技术设计师,我们很好奇,我们想要答案。

我们写这篇文章是为了帮助数据科学家创建更有效的人类行为模型,并帮助他们提高新数据驱动技术的采用潜力。但是我们也没有所有的答案。我们确实相信,通过提出正确的问题,我们可以让事情变得更好。

我们建议您从问自己以下问题开始:

  • 你的模型的预测是否依赖于人们做出严格理性的——合乎逻辑的、明智的、理性的——决定?(如果是这样,你目前还没有一个准确的行为模型。你需要带着整个模型回到绘图板)
  • 在实践中,您的模型的采用或实现是否依赖于人们做出严格理性的——合乎逻辑的、明智的、理性的——决策?(如果是这样的话,你目前还没有一个有潜力改变任何事情或帮助人们的模型。您需要带着您的采纳和实施计划回到绘图板。)
  • 你的用户/研究人群经历了什么样的情感体验,你如何在数据中表达出来?
  • 哪些同事,也许是跨学科和国际合作者,可能能够帮助你进一步将情感体验整合到你的模型中?
  • 在你的下一次资金申请中,你将如何展示你对情感体验在决定行为中的重要性的理解?
  • 在您的资助申请中,您如何强调用户/参与者的参与,以强调功效/效果潜力?

不管你现在是否能肯定地回答这些问题,这都可以成为你改善情绪在数据科学中的作用的框架。

鉴于疫情所创造的势头,对数字健康工具的学术和商业研发的投资可能会以前所未有的速度持续增长。个性化健康数据分析和健康行为改变仍然是数字革命的重要目标。如果我们想避免浪费投资的失望,现在是时候更多地关注情绪在参与和行为改变中的作用了。

医疗保健人工智能的公平问题

原文:https://towardsdatascience.com/healthcare-ais-equity-problem-fca16998a48e?source=collection_archive---------18-----------------------

公平和偏见

为什么数据公平不仅仅是公平

图片来自托德在 Unsplash

我们目前正处于一些人所说的人工智能的“狂野西部”之中。尽管医疗保健是监管最严格的部门之一,但这一领域的人工智能监管仍处于初级阶段。规则被写成我们说。我们正在迎头赶上,学习如何获得这些技术带来的好处,同时在这些技术已经部署后最大限度地减少任何潜在的危害。

医疗保健中的人工智能系统加剧了现有的不平等。我们已经看到了现实世界的后果,从美国司法系统的种族偏见、信用评分、简历筛选和性别偏见。旨在为我们的系统带来机器“客观性”和易用性的程序最终会复制和支持偏见,却没有任何责任。

算法本身很少是问题。值得关注的往往是用于技术编程的数据。但这远不止是道德和公平的问题。构建考虑医疗保健全貌的人工智能工具是创建有效解决方案的基础。

算法和数据一样好

从我们人类系统的本质来看,数据集几乎总是不公正的,很少是公平的。正如 Linda Nordling 在《自然》杂志的一篇文章中评论的那样,人工智能在医疗保健中更公平的前进方式,“这场革命取决于这些工具可以学习的数据,这些数据反映了我们今天看到的不平等的医疗系统。”

以调查结果为例,美国急诊室的黑人接受止痛药的可能性比白人低 40%,西班牙裔病人低 25%。现在,想象一下这些发现所基于的数据集被用来训练一个人工智能工具的算法,该工具将被用来帮助护士确定他们是否应该服用止痛药物。这些种族差异将会重现,而支持这些差异的隐性偏见将不会受到质疑,甚至变得自动化。

我们可以尝试通过删除我们认为导致训练偏差的数据来改善这些偏差,但仍然会有隐藏的模式与人口统计数据相关联。一个算法不能考虑到全局的细微差别。它只能从提供给它的数据模式中学习。

偏差蠕变

数据偏见以意想不到的方式蔓延到医疗保健领域。考虑到世界各地实验室中用于发现和测试新止痛药的动物模型几乎全部是雄性。因此,包括止痛药在内的许多药物都不适合女性。因此,即使像布洛芬和萘普生这样的普通止痛药也被证明对男性比女性更有效,而且女性比男性更容易遭受止痛药带来的副作用。

事实上,雄性啮齿动物也不是完美的测试对象。研究还表明,雌性和雄性啮齿动物对疼痛程度的反应因在场人类研究人员的性别而异。啮齿动物对一名男性研究人员的嗅觉引起的压力反应足以改变它们对疼痛的反应。

虽然这个例子看起来似乎偏离了人工智能,但事实上它有着深刻的联系——在治疗进入临床试验之前,我们目前可以获得的治疗选择隐含着偏见。人工智能公平的挑战不是一个纯粹的技术问题,而是一个非常人性化的问题,始于我们作为科学家做出的选择。

不平等的数据导致不平等的利益

为了让全社会享受人工智能系统可以给医疗保健带来的诸多好处,全社会必须在用于训练这些系统的数据中得到平等的代表。虽然这听起来很简单,但这是一个很难完成的任务。

来自某些人群的数据并不总是能够进入训练数据集。发生这种情况的原因有很多。由于现有的系统性挑战,如缺乏获取数字技术的途径或仅仅被认为不重要,一些数据可能无法获取,甚至根本无法收集。预测模型是通过以有意义的方式对数据进行分类而创建的。但是因为一般来说数据较少,“少数”数据往往是数据集中的异常值,为了创建一个更清晰的模型,经常被当作虚假数据剔除。

数据源很重要,因为这个细节无疑会影响医疗保健模型的结果和解释。在撒哈拉以南非洲,年轻女性被诊断出患有乳腺癌的比率要高得多。这揭示了为这一人口群体量身定制的人工智能工具和医疗保健模型的需求,而不是用于检测乳腺癌的人工智能工具,这些工具只在全球北方的乳房 x 光片上进行训练。同样,越来越多的工作表明,用于检测皮肤癌的算法对于黑人患者来说往往不太准确,因为它们主要是在浅色皮肤患者的图像上进行训练的。这样的例子不胜枚举。

我们正在创造有可能彻底改变医疗保健行业的工具和系统,但这些发展的好处只会惠及数据中显示的那些人。

那么,有什么办法呢?

消除数据偏见的部分挑战是,大量、多样和有代表性的数据集不容易访问。公开可用的训练数据集往往非常狭窄、数量少且同质——它们只捕捉到社会的一部分。与此同时,许多医疗机构每天都要捕获大量不同的健康数据,但数据隐私法使得访问这些更庞大、更多样的数据集变得困难。

数据保护当然至关重要。在负责任地使用数据方面,大型科技公司和政府没有最好的记录。然而,如果医疗数据共享的透明度、教育和同意得到更有目的的监管,更加多样化和高容量的数据集可能有助于在人工智能系统中实现更公平的表示,并为人工智能驱动的医疗工具带来更好、更准确的结果。

但是数据共享和访问并不能完全解决医疗保健的人工智能问题。通过人工智能实现更好的个性化医疗保健仍然是一个极具挑战性的问题,需要一大批科学家和工程师。我们希望教会我们的算法做出好的选择,但我们仍然在弄清楚好的选择对我们自己来说应该是什么样的。

人工智能为医疗保健带来了更大的个性化机会,但它也带来了巩固现有不平等的风险。我们面前有机会采取一种经过深思熟虑的方法来收集、监管和使用数据,这将提供一个更全面、更公平的画面,并实现人工智能在医疗保健中的下一步。

医疗保健价格?Fuhgeddaboudit!

原文:https://towardsdatascience.com/healthcare-prices-fuhgeddaboudit-f642b0e1ae9c?source=collection_archive---------40-----------------------

纽约市公立医院系统价目表的启示

点击此处进入 GitHub威风凛凛 中的项目。

想象一下,你打算买一部新的 iPhone。首先你上网去www.apple.com。可以看到最新的 iPhone 型号,但是没有列出价格。你知道相机好的那台可能比相机差的那台贵,大的那台可能比小的那台贵,但你不知道价格到底有多大差别。于是,你打电话给苹果的客服专线,询问你最喜欢的 iPhone 的价格是多少。他们说,这取决于你去哪家苹果商店。这也取决于你有什么手机计划。如果你参加的是威瑞森家庭计划,手机将是一个价格,如果你参加的是 Sprint 个人计划,手机将是另一个价格,以此类推。即使我们知道你的手机计划和你要去的商店,我们可能也不会告诉你手机的价格,除非你已经买了。

这听起来完全就是个骗局!但是这就是美国人每天购买医疗保健的方式——而且我们都对此没什么意见。

思考医疗保健价格,比如…

来源:https://knowyourmeme.com/memes/math-lady-confused-lady

幸运的是,联邦政府已经采取了一些小措施,试图给这个错综复杂的市场带来更多的透明度和清晰度。有一项法律于 2021 年 1 月在 T21 生效,该法律要求医院以机器可读的格式公布他们手术的价格。这(理论上)包括所有程序的标价、现金折扣价格(即未投保者支付的价格)和保险公司协商的价格。在这项法律之前,医院和保险公司可以对他们协商的费率保密。这些都应该是公开的信息。

这个新法太棒了!理论上。实际上,每家医院每天的违规费用仅为 300 美元。这个费用实在太低,不足以激励大多数医院系统遵守。我住在纽约市,所以我一直对纽约市的大多数医院是否会很快遵守这一规定特别感兴趣。不幸的是,答案是…不!在 Gothamist 查看这篇关于它的文章(可悲的是,自从 1/18/21 发表文章以来,情况并没有太大变化)。

一个已经公布了非常有用的数据的医院系统是纽约市公立医院系统: 纽约市健康+医院 。有了这些数据,我对价格差异做了一个非常简单的分析:

  1. 按每个程序的标价、现金价格和协商价格(在同一家医院内)
  2. 纽约市公立医院系统内不同医院相同手术的价目表价格和现金价格

这是一个非常高层次的数据,进一步的分析应该深入到程序级别的结果。这种粒度分析的例子可以在《华尔街日报》对加州萨特医疗系统剖腹产价格的深入调查中找到。SparkNotes:根据你的保险计划,价格从 6k 美元到 60k 美元不等。

数据准备

这个项目中使用的所有数据都可以在纽约市健康+医院设施收费页面上找到(尽管我是使用 pandas read_csv 函数自动获取数据的)。我将医院名称添加到每个医院的价格表中,合并数据集,并根据程序代码将每个程序标记为“住院”或“门诊”程序。我排除了所有标价为 1 美元的程序,因为我注意到它们似乎主要是奇怪的医疗保险专用代码,只是扭曲了数据。

接下来,如果现金价格不为空,并且低于价目表价格,则使用现金价格导出“调整后的现金价格”,否则使用价目表价格。现金价格高于标价对我来说没有意义。从数据来看,现金价格的设定似乎没有标价那么细致。例如,与某个高级医疗代码相关的每个程序可能有 500 美元的现金价格,即使属于同一医疗代码的单个程序有 25 美元的标价。对于这个 25 美元的程序,我将调整后的现金价格设为 25 美元,而不是 500 美元。你可能认为这是一个糟糕的假设,但是,唉…我做到了。

只需一个快速喊出: np.where()震撼我的世界 为了区分住院/门诊程序,并为了计算调整后的现金价格,我想创建一个新列,其值取决于几个标准。我在熊猫上尝试了很多方法,但是 np.where()是最简单和最快的。

仅 np.where()共鸣

接下来,对于我的数据框架中的每一行,我计算协商价格与标价、现金价格与标价以及协商价格与现金价格之间的百分比差异。在这些计算中,我假设如果协商价格为空,我应该使用价目表价格来代替(因为保险计划没有为该程序协商价格)。

作为最后的数据清理步骤,对于我在分析的第 1 部分中使用的数据框架,如果它们在每个医院的每个保险计划中没有至少出现一次,我就放弃所有的程序。我想确保如果我在比较不同保险计划的数据,我是在比较不同的程序。对于我在分析的第二部分中使用的数据框架,我再次放弃了不是每个医院都提供的所有程序。同样,我希望我的比较是苹果与苹果之间的比较。

第 1 部分:清单、现金和议价

现在我的数据已经准备好了,我可以通过保险计划计算所有程序中的平均和中间协商价格与现金价格、现金价格与标价以及协商价格与现金价格。然后,我只对那些保险计划已经协商了费率的程序/计划组合执行相同的计算(以防他们没有为不常见的程序进行协商,这可能只是扭曲了更有意义的结果)。我还计算了每个计划协商了费率的程序的百分比。我将所有这些结果合并到一个数据框架中,并对住院病人和门诊病人的程序进行重复。结果如下所示。

住院结果

住院保险计划(&现金)议定费率差异

上图显示了不同保险计划在住院患者数据集中的协商价格以及调整后的现金价格。

  • 协商价格与价目表平均值/中值:我们可以看到,平均而言,Metroplus Medicaid 和 UHC 社区计划协商了与价目表价格相对应的最佳价格,其次是调整后的现金价格,然后是第一保健全面保护和医疗保险 AB。然而,当我们看中位数时,只有 Metroplus Medicaid 的表现优于调整后的现金价格。
  • 协商与现金平均值/中值:当进行面对面比较时,平均而言,只有 Metroplus 优于调整后的现金价格,而当我们查看中值差异时,Metroplus 和 UHC(略微)优于调整后的现金价格。
  • %

住院患者直方图:标价、现金和议价

上面,我们深入研究了数据的分布,看看我们的均值/中位数是否掩盖了任何有趣的趋势。对于每个类别,我们显示完整的直方图,然后显示一个仅集中在-100%到+100%范围内的直方图,以忽略可能的异常值。

  • 协商价格与标价(蓝色图表):虽然有时协商价格高于标价,但最常见的差异是 0%(未协商)。在谈判价格中,大部分价格似乎在-80%到-50%之间。
  • 调整后的现金价格与清单(绿色图表):大多数程序要么有 0%的折扣,要么有~-60%的折扣。
  • 协商价格与调整后现金价格(橙色图表):有相当数量的程序,其协商价格是调整后现金价格的倍数(> +100%)。然而,大多数似乎都在-100%和 100%之间。我们看到另一个 0%的峰值,可能是因为某些程序的现金价格等于标价,没有协商的价格。在那种情况下,它们都是同样的价格。

住院病人,所有程序:保险计划费率与现金相比如何

我想总结每个保险计划与调整后的现金价格相比的表现,所以我创建了上表。最终,Metroplus Medicaid(如预期)的协议价格优于调整后现金价格的程序比例最高(73%),而 Medicare AB 的比例最低(19%)。

住院病人,仅协商程序:保险计划费率与现金相比如何

我们知道,不是所有的程序都有一个协商好的价格,这可能是因为它们可能非常不常见,因此只是噪音。因此,我检查了每个计划在调整后的现金价格下的表现,只检查了那些他们协商了价格的程序。使用这一指标,保险计划确实看起来更好,Metroplus Medicaid 现在 89%的时间优于现金,而 Medicare AB 现在 29%的时间优于现金。

门诊结果

下面的图表与上面住院病人部分的图表相同,只是我们现在使用的是门诊病人数据集(其中包括一些额外的保险计划)。

门诊保险计划(&现金)议定费率差异

上图显示了不同保险计划在门诊数据集中的协商价格以及调整后的现金价格。请注意,FFS 联邦医疗保险计划和 UHC 社区计划对门诊程序没有任何议价。因此,他们的大米完全符合标价。

  • 协商价格与价目表平均值/中值:我们可以看到,平均而言,Aetna 协商了最佳费率与价目表价格,其次是调整后的现金价格,然后是 1199SEIU 福利基金、Metroplus Medicaid、第一保健全面保护和 Medicare AB。然而,当我们看中位数时,只有 Metroplus Medicaid 的表现优于调整后的现金价格。
  • 协商价格与现金平均值/中值:当进行面对面比较时,所有计划的协商价格平均都高于(低于)调整后的现金价格,尽管当我们查看中值差异时,Metroplus Medicaid 明显优于调整后的现金价格。当我们查看中间值差异时,Aetna 和 1199SEIU 福利基金也优于调整后的现金价格。
  • %

门诊直方图:标价、现金和议价

上面,我们深入研究了数据的分布,看看我们的均值/中位数是否掩盖了任何有趣的趋势。对于每个类别,我们显示完整的直方图,然后显示一个仅集中在-100%到+100%范围内的直方图,以消除可能的异常值。

  • 协商价格与价目表价格(蓝色图表):虽然协商价格很少高于价目表价格(第一个直方图范围从-1 到+140),但最常见的差异是 0%(未协商)。在协商价格中,它们相当均匀地分布在-10%和-100%之间(我不确定为什么在数据集中有相当数量的协商价格为$0 的过程;这是来自医院系统的值,我不确定它是否是有意的)。
  • 调整后的现金价格与清单(绿色图表):大多数手术要么有 0%的折扣,要么有-60%的折扣(与住院手术相同)。
  • 协商价格与调整后现金价格(橙色图表):有少数程序的协商价格是调整后现金价格的倍数(> +100%)。然而,大多数人似乎在-100%和 100%之间。我们在 0%处看到了另一个峰值(原因与之前相同),但是其余的峰值相当均匀地分布在-100%和+100%之间,在-20%处有一个小峰值。

门诊病人,所有程序:保险计划费率与现金相比如何

我想总结每个保险计划与调整后的现金价格相比的表现,所以我创建了上表。最终,Metroplus Medicaid(如预期)的协商价格优于调整后现金价格的程序比例最高(80%),而 Medicare AB 的比例最低(10%),除了 UHC 社区计划/FFS Medicaid 没有协商价格。

门诊病人,仅协商程序:保险计划费率与现金相比如何

同样,我们知道不是所有的程序都有协商好的价格,这可能是因为它们可能非常不常见,因此只是噪音。因此,我们可以根据调整后的现金价格检查每个计划的执行情况,只检查那些他们协商了费率的程序。使用这一指标,一些保险计划看起来确实更好,如 Medicare AB 和第一保健完全保护(这两个保险计划的< 25% of procedures) shooting up from ~10% to ~70% of the time better than Cash. The stats remain steady for 1199SEIU Benefit Fund, Aetna, and Metroplus Medicaid — which makes sense because they negotiated nearly every procedure.

Part 2: List & Cash Prices Across Hospitals

We now turn to the List Prices and Adjusted Cash Prices across the NYC Public Hospital System. We calculate the mean and median List and Cash Prices for each procedure across all eleven hospitals. We then calculate the difference between these means/medians and the List/Cash Price for each procedure at each hospital, to see how the hospital’s price stacks up against the competition. Since this is all data about the same hospital system, we wouldn’t expect to see massive differences across hospitals.

INPATIENT RESULTS

Inpatient: Mean Variation in Prices by Hospital

In the chart above, we plot the 谈判价格意味着住院手术的医院价格差异。

  • 标价与平均值/中值:各个医院的住院病人标价没有太大差异。
  • 现金价格对比均值/中值:这个比较有意思。看起来 11 家医院中有 4 家医院的现金价格比其他医院高得多。平均而言,康尼岛、艾姆赫斯特、哈莱姆和雅各比的现金价格都比整个医院系统的现金价格中值高出 140%以上。然而,当我查看这些医院的原始数据集时,我可以看到它们没有列出任何折扣现金价格。只需列出价格和协商价格。不确定这是为什么——可能只是没有报告他们的现金价格?

住院病人:各医院价格的中位数变化

在上面的图表中,我们绘制了医院的中值价格差异,用于住院治疗。

  • 标价与平均值/中值:同样,各个医院的住院病人标价没有太大差异。
  • 现金价格与均值/中值:康尼岛、埃尔姆赫斯特、哈莱姆和雅各比的现金价格都远高于整个医院系统的现金价格中值。在这种情况下,所有四家医院的中位数差异约为 150%。(同样,这可能只是一个数据报告问题)。

住院患者直方图:纽约市公立医院每项手术的现金价格与中间价格

为了更好地了解不同医院之间每项手术的现金价格差异,我们为每家医院创建了一个直方图,显示其现金价格与医院系统中值现金价格的分布。我们的四家昂贵的医院呈现出相似的分布,与其他七家有很大的不同。

门诊结果

下面的图表与上面住院病人部分的图表相同,只是我们现在使用的是门诊病人数据集。

门诊病人:医院价格的平均变化

在上图中,我们绘制了医院门诊手术的平均价格差异。

  • 标价与平均值/中值:不同医院的门诊标价没有太大差异。
  • 现金价格与平均值/中位数:不同医院的门诊现金价格也没有太大差异。(貌似所有医院都在提供门诊打折现金价格)。

门诊病人:医院价格的中位数变化

在上图中,我们绘制了医院门诊流程的中值价格差异。由于变化非常有限,所有医院所有这些指标的中值差异为零,因此该图表为空白。

结论

最终,这是一个有趣的练习,但我最大的收获是这仅仅是开始。首先,这个数据集似乎缺少纽约许多著名商业保险计划的协商费率:帝国蓝十字蓝盾、信诺、徽健、联合医疗保健等。此外,这只是一个城市中的一个医院系统。这可能是这个城市最便宜的系统之一,因此也可能是最没意思的。我们需要全国所有医院系统(公立和私立)的相同信息,并且我们需要一种易于比较的格式。

现在我不再是黛比·唐纳了,我们从这个不完美但仍然有用的数据集中学到了什么?

住院亮点

  • 迄今为止费率最高的计划是 Metroplus Medicaid。除此之外,其他计划并不比现金价格好太多!
  • 由于协商的价格往往比现金价格更差…对于任何一个每年有很高免赔额的人来说,他们认为他们不会满足,当你最好支付现金时,每月保费的意义是什么?
  • 纵观纽约市系统的 11 家医院,康尼岛、埃尔姆赫斯特、哈莱姆和雅各比医院的现金价格由于某种原因比其他医院高得多(因为它们没有现金价格!).然而,这可能只是一个数据报告问题。

门诊亮点

  • Metroplus Medicaid 费率最优惠。1199SEIU 福利基金和 Aetna 比现金稍好,其余的计划要么相当于,要么比调整后的现金价格差。
  • 同样,对于某些程序,免赔额非常高的患者考虑现金价格与保险计划的协商价格似乎很重要。
  • 纵观纽约市系统的 11 家医院,清单和现金价格基本相同(不出所料!).

感谢阅读,现在让我们向更多的医院系统施加压力,公布他们的费率!

医疗保健的人工智能未来——与和费的对话

原文:https://towardsdatascience.com/healthcares-ai-future-conversation-with-andrew-ng-and-fei-fei-li-a6eacb6aaaf1?source=collection_archive---------19-----------------------

与两位领先的人工智能专家在数据科学和医疗保健的交叉领域进行炉边交谈,获得了四个关键收获

卡米洛·希门尼斯在 Unsplash 上拍摄的照片

深度学习。AI 和斯坦福海最近组织了一次与两位世界上最杰出的计算机科学家和费的虚拟炉边聊天。

在对医疗保健的 社会使命和对人类的重要性的强烈信念的驱动下,他们近年来将努力和专业知识集中在医疗保健行业。

这篇文章从人工智能和医疗保健交叉的角度和观点来看四个关键要点

关于扬声器

费-李非 是斯坦福大学计算机科学系的首任红杉教授,也是斯坦福大学以人为中心的人工智能研究所的联合主任。她在 2013 年至 2018 年担任斯坦福大学人工智能实验室的主任。

Andrew NG是 deeplearning.ai 的创始人,Coursera 的联合创始人,目前是斯坦福大学的兼职教授。他也是百度公司的首席科学家和谷歌大脑项目的创始人。

照片由艾伦·龚在 Unsplash 上拍摄

四个关键的信息

(1)在医疗保健领域采用人工智能的最大障碍

尽管医疗保健领域对人工智能进行了大肆宣传,但这种人工智能解决方案的现实实施比预期要慢得多,只有少数孤立的成功。

Andrew 认为,技术和非技术方面的变革管理仍然是一个严峻的挑战。从技术角度来看,团队需要学习如何更好地管理机器学习项目的整个生命周期

飞飞强调,医疗保健领域的人工智能仍然缺乏“人类胜利”,无法创造行业的分水岭时刻。她提到,仍然缺乏经过验证的故事和产品来展示人工智能解决方案如何给患者或医疗保健提供商带来根本性的变化。

照片由张诗钟乔吉亚迪斯在 Unsplash 上拍摄

(2)最重要的未解决的医疗保健问题

数据科学的目标是利用数据和高级技术来解决业务问题。因此,听听小组成员认为哪些是值得应对的重大挑战会很有意思。

飞飞分享了一个惊人的统计数据,吸引了观众的注意力——据估计,美国每年有 25 万人死于医疗事故。

虽然医疗创新为开发新药和程序以更有效地治疗患者铺平了道路,但人为错误、疲劳和系统资源不足等问题仍然是医疗保健系统中伤亡事故的重要原因。

Andrew 强调了这一点,他提到虽然医疗保健中的人工智能通常与诊断和治疗相关联,但对运营方面的关注和研究相对较少

他认为,在医疗保健的运营优化方面,有一些被忽视的重大问题,如为有限的资源(如核磁共振成像设备)安排患者和医疗保健人员的配备。

Alex Mecl 在 Unsplash 上拍摄的照片

(3)同理心和协作的重要性

数据科学是一项团队运动,需要紧密的合作和一致的目标才能取得成功。

飞飞认为,数据科学家(技术成员)和医疗从业者(非技术成员)都必须培养一种理解对方语言的移情意愿。

例如,飞飞会让她的学生在医院跟随斯坦福医生几天,通过见证病人和医疗服务提供者的脆弱、同情和尊严来了解医疗保健领域的人性。

Andrew 分享了他在构建姑息护理推荐系统方面的经验。他很好奇这个系统是如何激励更多的提供者开始对话推荐某些患者进行姑息咨询,而在其他情况下可能不会讨论。

这种机器学习应用程序打开了以前的层级结构,为医院中的一种方法铺平了道路,这种方法更具多利益主体、互动性和同理心

照片由蒂姆·马歇尔在 Unsplash 拍摄

(4)避免偏见的永久化

近年来,偏见进入人工智能系统并导致有害结果的问题受到了关注。

Andrew 建议多学科团队应该聚在一起集思广益,找出机器学习应用中可能出错的所有事情,并围绕它们设计指标以实现透明监控。

此外,数据应相应地** 切片以分析机器学习模型对不同组的影响,作为系统审计的一部分。**

飞飞强调,在编写任何代码之前,伦理应该是设计人工智能解决方案的核心考虑因素。在她管理的团队中,她让伦理学家、法律专业人士、患者和医疗保健提供者参与讨论这些潜在的偏见,作为解决方案设计过程的一部分。

机器学习系统中包含的偏见是最终成为** 人类的责任。因此,认识到我们人类对任何形式的系统偏差都负有责任是至关重要的,我们需要设置护栏来尽可能减轻偏差。**

杰森·古德曼在 Unsplash 上的照片

完整的对话

你可以在这里观看整个对话的视频:

在你走之前

欢迎您加入我的数据科学学习之旅!点击此媒体页面,查看我的 GitHub ,了解更多精彩的数据科学内容。同时,尽情探索医疗保健和数据科学的交集吧!

美国最健康的城市:第一部分,食物

原文:https://towardsdatascience.com/healthiest-cities-in-the-us-part-1-food-62b9724467e8?source=collection_archive---------26-----------------------

美国城市有多健康?

在 Unsplash 上由 Haseeb Jamil 拍照

我一直在思考在城市分析的背景下使用数据科学和统计学,特别是关于美国城市有多健康的问题。在这些由多个部分组成的故事中,我们将使用数据科学来分析这个问题。此刻,我打算这样划分故事:美食休闲空间工作生活平衡。在第一部分,我们将关注食物:即快餐连锁店在美国各城市有多普遍,以及美国人民在杂货店购买食物有多容易。让我们开始吧:

数据:

  • 快餐数据:https://www.kaggle.com/datafiniti/fast-food-restaurants

工具:

  • Jupyter 笔记本
  • 熊猫(一个数据帧处理包)
  • Stats (Python 统计分析库)
  • Seaborn 和 Matplotlib(可视化库)

1.方便食品

让我们首先尝试围绕数据收集一些基本事实:

  • 有多少独特的城镇:

  • 结果: 2764 个独特的城镇

  • 对于每个快餐条目,数据集包含哪些列/数据?

  • 结果:索引(['id ',' dateAdded ',' dateUpdated ',' address ',' categories ',
    ,' country ',' keys ',' latitude ','经度',' name ',' postalCode ',【T21 ','省',' sourceURLs ',' websites'],
    dtype='object ')

  • 最常见的品牌是哪个?

  • 结果:麦当劳(1898 家餐厅),塔可钟(1032 家),汉堡王(833 家),赛百味(776 家),Arby's (663 家)。

  • 有多少快餐?

  • 结果:10000

计算美国最健康城市的一个主要问题是每个城市有多少家快餐店。要回答这个问题,我们可以使用熊猫按城市名称对数据进行分组,然后按每个城市的快餐数量对数据框进行排序,如下所示:

不足为奇的是,像休斯顿和拉斯维加斯这样的大城市拥有最多的快餐店,因为它们规模庞大。因此,简单地使用餐馆数量是不够的:我们需要一个变量来量化基于人口的数量。为了做到这一点,让我们设计一个新的指标,快餐数量除以每个城市的人口。如果一个城市有许多快餐,但人口很少,这个变量将有一个高值,反之亦然,为低值。将该指标添加到数据帧的代码如下:

以下是我们设计的指标值最高的前 20 个城镇:

你可以看到像恩西诺(加利福尼亚)、吉尔福德(北卡罗来纳)和王国城(密苏里)这样的城镇在列表的顶部。有趣的是,所有这些城市/城镇似乎在规模和人口上都更小,这意味着最大的城市有更少的快餐服务更多的顾客,按照我们的标准,使他们更健康。我们来看看实际情况是否如此。首先,这是数据集中所有城市的人口数量和相应的快餐数量的散点图:

虽然对于 250,000 人以下的城镇来说,人口和快餐数量之间的关系似乎是线性的,但随着人口的增加,这种关系似乎不那么明显了。这是人口与我们设计的指标的散点图:

在这种情况下,实际上看起来这种关系有点负面:随着人口的增长,人们可以吃的快餐越来越少。

为了真正了解人口较少的城市和人口较多的城市在快餐店方面是否存在实际差异,我们可以对这两种人群进行一些统计分析。对于这个故事,我们将定义两种不同的城市规模:小于或等于 25,000 和大于 25,000。在我们测试这两个群体的差异之前,我们需要决定我们将使用的测试。为此,首先我们必须看看人口是否正态分布。这可以通过使用 QQ 图和夏皮罗-维尔克正态性检验来实现:

qqplot

QQ 图是一个散点图,绘制两组分位数之间的关系。如果两组分位数来自相同的分布,我们应该看到这些点形成一条大致笔直的线。下面的代码将数据集分成两个预定义的城市大小。

这是较大(超过 25,000 人)城市的 qqplot:

这是较小城镇的 QQ 图:

正如你所看到的,这两个群体都不符合直线,这使我们倾向于说群体不是正态分布的。

夏皮罗-维尔克

检验正态性的夏皮罗-维尔克检验通过设定两个假设来工作:

  • 零假设:数据呈正态分布。
  • 替代假设:数据不是正态分布的。

以下是针对较大城镇的夏皮罗-维尔克测试结果:

这是针对小城镇的夏皮罗-维尔克测试结果:

曼-惠特尼试验

既然我们已经确定数据不是正态分布的,那么一个合适的测试就是曼-惠特尼测试来确定我们两个群体之间的差异。对于这个检验,我们还应该陈述一个无效假设和另一个假设:

  • 零假设:两个群体来自同一个基础群体。
  • 替代假设:两个群体不来自同一个潜在群体。

该测试的代码如下:

曼·惠特尼测试告诉我们,小城镇和大城镇的快餐数量确实存在差异,这对于根据美国人居住的城市来理解他们可获得的食物类型是很有趣的。

2.食品杂货通道

对于这个故事的第二部分,我们将看看美国哪些县最容易获得食品杂货。数据取自经济研究署的食品环境图集(https://www . ers . USDA . gov/data-products/Food-Environment-Atlas/)。

如您所见,数据集包含了县一级的各种指标的信息。我们将使用的是“LACCESS_POP10”,它指的是 2010 年每个县获得食品杂货的人数。让我们首先过滤数据集,并查看每个州的这一指标的平均值:

“值”列包含获得食品杂货的平均人数,最高值属于马萨诸塞州,其次是康涅狄格州和新泽西州,这可能有点令人惊讶,因为它们都是拥有大片城区的州。就像我们对快餐所做的那样,我们应该将这些数字换算成该州的人口数,并用一个比率来表示,所以让我们使用下面的变量:很少接触食品杂货的人数除以该州的人口数。代码如下:

为了解释这些结果,该变量的大值意味着每个州拥有低访问权限的人口比例较高,而小值意味着拥有低访问权限的人口较少。以下是按变量降序排列的前 10 个州:

倒数 10 个州是:

得克萨斯州是食品杂货收入低的人口比例最小的州,而特拉华州是最高的,其次是罗德岛州和夏威夷。这些结果让你感到惊讶吗?它们对我来说有点小,因为我原本预计美国中部农村人口较多的州会在列表中占主导地位,因为杂货店可能在这些州很少。然而,有趣的是,似乎事实并非如此。

希望你喜欢这个小故事,如果你想看完整的代码,可以在这里找到:https://github . com/DeaBardhoshi/Data-Science-Projects/blob/main/_ Urban % 20 health % 20 analysis % 20 part % 201% 20-% 20 food . ipynb

感谢阅读!

听我说完:我发现了一个更好的估计中位数的方法

原文:https://towardsdatascience.com/hear-me-out-i-found-a-better-way-to-estimate-the-median-5c4971be4278?source=collection_archive---------10-----------------------

人们经常使用百分位数来汇总数据。中位数是第 50 个百分位数,众所周知,它对数据中的异常值非常稳健(与平均值相反)。此外,它代表了一个“典型样本”,平均值并不一定如此。有时,人们觉得他们需要追求分布的极端,并开始使用高百分位数(如第 95 和第 99)。与较低的百分位数相比,这些具有一些不期望的特性。此外,人们从一组数据中计算百分位数的简单方法并不完美,如果我们愿意增加一点复杂性,还可以改进。关于这个主题有一篇 arxiv 论文,在结论部分有很多数学内容。

I)中间值和其他百分位数

照片由 Josh Harper 在 Flickr 上拍摄

中位数是一个非常简单的概念。将数据集或分布从中间分开的值。分布的一半概率质量(或数据中的一半样本)低于中位数,一半高于中位数。这个可以一概而论。我们也可以问一个点,30%的数据在它下面。一般来说,数据中 x%的数据低于它的点被称为第 x 百分位(因此第 50 百分位是中间值)。

II)有限样本和形式理论

形式的理论是一个来自柏拉图的想法,柏拉图认为物质世界不像永恒的、绝对的、不变的想法或形式那样真实或真实。我们在物质世界中看到的任何东西都不过是对这些形式的不完美的模仿。在统计学中,这些形式是潜在的概率分布,永远无法触及。我们能看到的只是这些分布产生的数据。我们从有限的真实世界样本中推断出的任何东西都只是对产生样本的分布的真实性质的估计。

分布有许多特性,百分位数是其中的一部分。我们如何估计分布的百分位数(或其他属性)?从分布中抽取一个样本(我们假设这是可能的),并将其压缩成一个单一的描述性统计。描述性统计是将观察样本转换成单个数字的函数(详细处理见此处)。百分位数就是一个例子;样本均值是另一个。那么,什么样的描述性统计对于百分位数是最好的呢?

II-A)估算百分位数

先说中位数。同样,它是这样一个点,一半分布在它的下面,一半在它的上面。如果我们知道分布,它就是在 0.5 计算的反 CDF。这是因为分布的 CDF(或累积分布函数)将该分布可以接受的任何值作为输入,并返回该分布低于该值的概率质量。所以,这个函数的反函数将把概率质量作为输入,把我们得到的低于它的概率质量作为输出。在 0.5 处的反向 CDF 将是分布的点,使得一半的概率质量低于它,或中值。

但这是在我们知道分布的反向 CDF,或者可以得到分布本身的情况下。实际上,我们只是从分布(比如说x1,x2,…,xn)中得到几个样本(比如说 n )。为了估计样本的 x 百分位数,一个合理的做法是找到一个点,使得其中的 x %在该点以下,其余的在该点以上。

为此,我们可以对样本进行分类。

  1. 这个排序列表中的第一个样本(称之为 X_(1) )或者是 X_1,X_2,… 的最小值,没有比它更小的了。因此,它应该是第 0 百分位或最小值的一个很好的估计器。
  2. 排序列表中的第二个样本(称之为 X_(2) )恰好具有比它小的( n-1) 个样本中的一个。换句话说, 100/(n-1) 百分比的样本低于它,因此它应该对第 100/(n-1) 百分位数进行很好的估计。
  3. 第三个样本的 200/(n-1) 百分比低于它,依此类推。
  4. i 个样本( X_(i) )具有其下样本的(I-1) 100/(n-1)*%。

脚注-1:如果你真的在乎效率,可以避免排序,使用快速选择算法在 O(log(n)) 时间内找到所需的订单统计。

X_(1),X_(2),…X_(n) 被称为顺序统计量,它们都是一种描述性统计量(因为它们取整个样本并给出一个数字)。

它们代表的顺序统计量和百分位数。

问题是,这些顺序统计量将只给出( i-1)100/(n-1)* 形式的百分位数。如果 n=11 例如, X_(1) 是第 0 百分位, X_(2) 是第 10 百分位, X_(3) 是第 20 百分位,以此类推。所以我们只能得到 10 的倍数的百分点。如果我们想要 75%呢?我们知道 X_(8) 是第 70 百分位, X_(9) 是第 80 百分位。用他们的中点来估计 75 度是有道理的。

我们在这里做的是在已知的两个百分点之间进行线性插值。这是 python-numpy 中的 percentile 等所有库方法对不能很好地映射到顺序统计数据的百分点所做的事情(大多数情况下都是这样)。

一般来说,这种线性插值用于计算q-百分点(比如说u;此处 q01 之间的分数,而不是百分比)结果在下面的公式(1)中。这里我们用 x 的小数部分来表示 {x} (所以 {1.2}=0.2{2.9}=0.9 等等)。这一点的证明(很容易理解)在附录 A 中给出。

等式(1-a):当我们进行线性插值时,q 百分位的一般表达式。

其中:

等式(1-b):等式 1-a 中 I 的定义。

让我们考虑一些简单的例子来看看这个公式的作用。当 q=.5 时,我们要中值。现在,如果 n 是奇数, {q(n-1)} 将为零,因为 q(n-1) 将变成整数。因此,只有等式(1)中的X(I)项将保留。对于 n=3 ,并且 q=.5 ,我们得到:

代入等式 1-a,得出:

这是有意义的,因为在一个由三个元素组成的有序数组中,第二个元素将是中间的一个元素,前后各有一个元素,将数组一分为二。

类似地,对于 n=4q=0.5 ,我们将得到:

II-B)用指数模型研究偏差

我们在等式(1)中描述的是从某个分布的有限样本中计算q-百分点的方法。这是我们真实世界的描述性统计数据。当计算任何有限样本量时,这个描述性统计量本身具有某种分布, n 。也就是说如果我们做多次抽取 n 个样本并计算的实验,每次都会得到不同的答案。这个描述性统计的分布会有一些平均值,一些中位数等等。然后是我们从中抽取的 n 个样本的基础分布中值的实际值。描述性统计分布的平均值(此处为样本百分位数)和实际百分位数之间的差异被定义为描述性统计的偏差。在其他条件相同的情况下,我们希望这个偏差为 0 。不幸的是,对于大多数百分位数来说,情况并非如此。

让我们用一个简单的分布来演示这一点。因为百分位数通常用于延迟之类的东西,所以让我们使用一个只能取正值的分布。最简单的这种分布是指数分布。它只有一个参数(rate 参数),但是让我们通过将它设置为 1 (标准指数分布)来进一步简化事情。

事实上,我们有一个很好的表达式来描述它的顺序统计量。在维基百科关于顺序统计的文章中,我们得到了 Renyi 提供的关于指数分布的第 i 次顺序统计的公式(来自于 n 的样本量):

在这里, Z_j 是独立同分布指数本身,速率为 1。取两边的期望值,当基础分布为指数分布时,我们得到基于 n 个样本的顺序统计量的分布的期望值。

等式(2)指数分布的顺序统计量的期望值。

使用这个和等式(1),我们可以找到任何顺序统计量的分布的期望值,从而找到任何百分位。

为了找到q-百分位数,首先将等式 1-b 中的 i 代入等式(2)中,得到我们需要的两个有序统计量:

并且根据等式 1-a 将它们组合,除了 E(X_(i+1)) 中的最后一项不常见,意味着它仍然存在之外, {q(n-1)} 因子抵消了两者的所有常见项。

现在,我们可以用百分位数的真实值减去它,我们也知道标准指数分布的真实值:

并通过以下方式获得指数分布的 q 百分位中的偏差( b_q )(当使用线性插值策略时):

等式(3)当使用大多数软件包中使用的流行线性插值策略时,指数分布的 q 百分位偏差。

当抽取等式(3)中描述的大小为 n 的样本时,指数分布的 q 百分点的偏差在以下 python 函数中实现:

代码片段(1)测量指数分布的百分比偏差

除了测量偏差,上面的代码片段还可以帮助我们比较从有限样本中估计百分位数的各种策略的偏差。

例如,我们甚至需要线性插值吗?如果我们不做呢?当我们的q-百分位数落在 X_(i)X_(i+1) 顺序统计量之间时,简单地使用 X_(i) 作为例子。它会不会对大样本量不再有影响?让我们绘制偏差作为线性插值和无插值策略的样本大小的函数,用于各种百分位数( q )和样本大小( n=15 )。

图 1:指数分布的不同百分位数的偏差

图 1 中的关键要点:

  1. 偏差在低百分位开始为负,逐渐增加到 0 (在中位数仍然为负)。在大约第 67 百分位时,它变为零。从那里开始,它急剧增加,在最右边大约为 1.5 (第 99 百分位)。请注意,指数分布的第 100 个百分位数(最大值)的偏差总是∞。这表明我们应该避免高百分位数,因为那里有很大的偏差。
  2. 对于线性插值策略,存在偏差变为零的百分点。这不是第 50 个百分位数(或中位数),那里仍然有一些负面的偏见。非常接近 66.67 百分位。
  3. 除了在不需要线性插值的百分点处,无插值策略比线性插值策略具有更差的偏差。

现在,让我们研究样本大小( n )增长时的行为,如下图 2 所示。

图 2:与图 1 相同,但是我们改变了样本大小(n)。

从图 2 的电影情节中可以得到的关键信息:

  1. 随着样本量的增加,两种策略的偏差都减小。然而,线性插值策略总是比无插值策略有优势。
  2. 随着样本量 n 的增加,偏差达到零的百分位数向 66.66%(或三分之二)收敛。但是即使对于小样本量,它也非常接近这个值。
  3. 随着样本大小的增加,线性插值和无插值策略之间的偏差差异存在周期性。不知道是什么引起的。如果你有想法,也许可以留下评论?

从上面两张图可以清楚地看出,线性插值策略总是比无插值策略好。但是,在减少偏见方面,有没有其他更好的策略呢?事实上,至少对于指数分布来说,有一个完美的策略。

线性插值的替代方法

注意线性插值没有什么特别的,只是简单直观而已。我们可以同样容易地在 X_(i)X_(i+1) 之间进行另一种插值。

我们可以使用等式(3)来提出消除偏差的策略,而不是简单地测量偏差。负责线性插值的项是 {q(n-1)}。让我们用其他的因子来代替它,然后,我们可以明确地选择 f,以消除指数分布任何百分位的偏差。

等式(4)插值因子 f,用于消除指数分布任何百分位的偏差。

这个想法在下面的 python 方法中实现,该方法给出了给定百分位、 q 和样本大小、 n 的插值因子 f :

代码片段(2):实现“低偏差插值”策略。这是流行的线性插值策略的竞争对手。

让我们称这个策略为“低偏差插值”策略。在图 1 和图 2 的曲线图中描绘这种策略并没有多大意义,因为根据其定义,它只是紧挨着 x 轴。

只有当我们从指数分布中抽取样本时,这个零偏差结论才是正确的,但如果该分布是其他分布,则不是正确的(因为在推导它时使用的所有数学都假设了指数分布)。然后将这种“低偏差插值策略”与针对其他底层分布的无处不在的标准“线性插值策略”进行比较将会很有趣(我们可以放弃“无插值策略”,因为它明显不如标准线性插值策略)。

我们将在下一节中这样做,但我们没有其他分布的顺序统计的封闭形式(指数分布是少数存在封闭形式的分布之一)。所以,我们不得不求助于模拟。

III)代码和视觉模拟

詹姆斯·哈里逊在 Unsplash 上拍摄的照片

III-A)平行宇宙的无限矩阵

从有限的样本量(比如说 n )进行估计的问题是,你的估计是有噪声的。如果你重复这个实验,你会得到不同的估计。这是一个问题,因为科学的基本租户是,结论应该是可重复实验验证的。

处理不确定性的方法是研究与不确定性相关的基本分布。我们可以想象平行宇宙,其中生成底层数据的过程完全相同,并且基于 n 个样本(独立且同分布)的实验在每个宇宙中进行。所有的数据都存储在一个巨大的矩阵中。来自第一个宇宙的数据位于矩阵第一行的数组中,来自第二个宇宙的数据位于第二行的数组中,依此类推,如下图所示。

然后,我们可以计算每个宇宙中的百分位数或其他描述性统计数据,并沿着列折叠矩阵。我们将留下一个由 m 个数据点组成的数组,代表我们的汇总统计在宇宙中的分布。我们可以让 m 尽可能大,这样我们就可以研究从小样本( n )计算的汇总统计分布的行为。例如,我们从 100,000 个平行宇宙中的各种样本大小中找到 Lomax 分布的估计中值( m ),并将这些中值绘制在下图 3 的直方图中。我们还有一条黄线,描绘了这个洛马克斯分布的中间值的真实值。我们可以看到跨越平行宇宙的估计值的平均值远离真实的中值(但是随着我们增加 n 而变得更接近),但是跨越中间值的平行宇宙的中值总是在实际中值的正上方。稍后我们将对此进行更深入的探讨。

图 3:不同样本量的 Lomax 分布的计算中间值分布。

对于一些汇总统计数据,某些结论是显而易见的。例如,考虑样本均值。首先对每一列取平均值,然后对得到的数组的行取平均值,这与对所有的 m×n 条目取平均值是一样的。由于 m→∞ ,我们可以调用大数定律,该定律认为这个平均值将与所有这些数字产生的分布的真实平均值相同。因为这正是无偏的定义,我们已经证明了样本均值总是无偏的,无论基础分布如何(只要分布的均值存在)。

对于百分位数,事情并不那么明显。例如,与样本均值不同,如果我们首先取每个 m 数组的中值,然后取所有 m 结果条目的中值或均值,这与一次取所有 m×n 数的中值是不同的。所以,是时候使用核选项了,模拟。我们将模拟本节中描述的 m×n 数(其中 m 非常大),然后通过图表得出关于百分点的各种结论。

III-B)模拟矩阵

马库斯·斯皮斯克在 Unsplash 上拍摄的照片

我在下面提供了 python 模拟器的基本版本(以及详细的注释),以演示我们描述的模拟是如何工作的。

代码片段(3)模拟一个非常大的平行宇宙矩阵。

在第二节中,我们得到了广泛使用的线性插值策略下指数分布的偏差的封闭形式。为了热身,让我们从指数模拟,看看我们的模拟器是否工作。

但是为什么仅仅停留在偏差上,我们还可以绘制一系列其他的度量标准。我们将为每个百分点(以及各种基本分布)绘制图表:

  1. 两种策略的偏差。
  2. 标准偏差:了解我们的估计在平行宇宙中有多大差异。我们不希望这个价格太高。
  3. 中位数的差异:我们描述了样本均值是真实均值的无偏估计量(根据大数定律)。另一方面,样本中位数是真实中位数的有偏估计量。也就是说,如果我们取平行宇宙的中间值的平均值,我们会得到与真实中间值不同的结果。有人会说这对中间值不公平。为什么要取平行宇宙的平均值?为什么不是中间值呢?当我们这样做的时候,中位数(在平行宇宙中)就变成了真正的中位数。我们将为中位数证实这一点,但也为其他百分位数看看它。我们称这种差异为“DelMedian”。
  4. 均方差:在偏差和方差之间经常有一个权衡,一个策略可能有较高的偏差,但方差较小。一个流行的做法是将它们合并成一个称为均方误差的单一指标。我们也会策划这个。

在下面的图 3 中,我们展示了这四个指数分布图。

图 4:从指数分布生成数据时,线性插值策略和低偏置策略的比较。

图 4 中的关键要点:

  1. 两种插值策略的偏差在顶部图中。当数据从指数分布生成时,低偏差策略具有零偏差,因为这正是它的设计目的。因此,黄线环绕 x 轴。另一方面,线性插值策略的偏差仅在第 66 百分位附近为零,并且对于高百分位来说非常高(我们在下图中上升到第 95 百分位)。
  2. 在第二个图中,我们取平行宇宙中计算出的百分位数的中间值,并取该百分位数真实值的差值。该图的行为类似于偏差图(是平行宇宙平均值的差异,而不是中值)。除了第 50 百分位附近的窄带(用两条红线标记)之外,低偏差策略的性能优于线性插值策略。
  3. 第三个图显示了两种策略的标准偏差。对于高百分位数(大约从第 85 位开始),低偏差策略的标准偏差高于线性插值策略的标准偏差。在此之前,两者颇为相似。
  4. 第四个也是最后一个图比较了两种策略的均方误差(MSE)。对于高百分位数(80+),这是由方差决定的,因此看起来非常像标准差图(第二个)。对于从低值到大约 60 的百分位数,MSE 由偏倚决定。因此,在这个指标上,低偏差策略比标准线性插值策略稍好。

这都是针对指数分布的,但这对于线性插值策略是不公平的,因为低偏差策略是在此基础上训练的。现在让我们为不同的分布绘制相同的图。我选择了对数正态分布,因为它也模拟了从 0 的延迟。它比指数分布有更重的尾部。大多数结论仍然有效,并继续适用于各种其他分布(我没有包括这里的所有实验),包括均值爆炸的重尾分布(例如:Lomax 分布)。你可以自己玩代码。具有所有附加功能的完整版本是这里(首先查看代码片段-3 以了解发生了什么)。

图 5:与图 3 相同,但是分布从指数分布切换到对数正态分布。

图 5 中的关键要点:

  1. “低偏差策略”的偏差现在对于所有百分位数(尤其是高百分位数)都不为零。然而,就偏差而言,对于大多数百分位数,它仍然比标准线性插值策略好得多。因此,低偏置策略名副其实。另一个观察结果是低偏置策略的偏置与线性插值策略的偏置具有相反的符号。
  2. 正如指数分布一样,对于高百分位数(也是 80+),低偏差策略比线性插值策略具有更高的方差。

对于标准差和 MSE,其行为与我们对指数分布的行为非常相似。

总之,“低偏差策略”具有更好的特性(偏差、MSE 等。)对于我测试的所有分布,只要你计算的百分位数低于 60(包括最常用的中位数)。对于更高的百分位数,它继续是更好的偏差标准。

在所有这些模拟中观察到,第二个图显示了中位数的跨宇宙的中位数始终是真实的中位数(对于线性插值策略,第二个图似乎总是通过 (0,0) ,也参见图 3)。这是普遍适用的吗?关于这一利用测试版的优雅证明,见本帖(Stats stack exchange;“大量中位数的中位数是否总是等于真中位数”)。

四)结论

这篇文章的要点是:

  1. 对于取正值的分布(如延迟、收入等。)避免使用高百分位数(90+)。它们有很大的方差和很大的偏差,这使得它们几乎没有用,除非你有一个非常大的样本量。
  2. 就像均值取决于真均值一样,中值取决于真中值。因此,虽然样本中值是真实中值的有偏估计,那只是因为我们取了平均值(根据偏差的定义)。
  3. 用于估计不适合顺序统计的百分位数的线性插值策略不一定是我们能做到的最好的。在本文中,我们提出了一个替代策略,消除了指数分布简单情况下的偏差。在偏差和均方误差方面,对于各种百分位数和分布,所得到的插值策略优于线性插值策略。当你计算第 60 个或更低的百分位数时,尤其如此。

下面是一篇有更多细节的论文:【2201.01421】用指数模型(arxiv.org)减少分位数估计中的偏差和方差。


如果你喜欢这个故事,成为推荐会员:)

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

附录

a)对精确的百分位数估计进行线性插值

在大小为 n 的样本中,q-百分位是顺序统计量 X_(i) ,如果:

如果我们幸运的话, q(n-1) 将是一个整数,那么 q- 百分位将很好地位于顺序统计量( X_(i) )上,并且等式成立。但是一般来说,我们总是可以选择两边的发言权,这将允许我们为任何 q 找到一个 i

但是,对应于 i 的顺序统计量不会对应于我们想要的精确百分位数。不过没关系,我们知道百分位数 X_(i) 对应的和 X_(i+1) 对应的比高 1/(n-1)。

我们现在可以通过使斜率相等来进行线性插值(如果百分位数 q 是 T30 u T31):

重新排列术语,

如果我们用 x 的小数部分来表示 {x} (所以 {1.2}=0.2{2.9}=0.9 等等),并注意到:

我们可以写:

这与等式(1)相同。

心脏病分类—第二部分

原文:https://towardsdatascience.com/heart-disease-classification-part-ii-9271af7c05af?source=collection_archive---------44-----------------------

分类加上使用集成方法实现约 92%的总体准确度得分

由马库斯·斯皮斯克在 Unsplash 上拍摄的照片

作为我上一篇文章的后续(在这里找到),我将在这里展示我使用 UCI 的心脏病数据集建立分类模型的步骤,以及利用集成方法实现更好的准确性评分。

通过创建能够更准确地对心脏病进行分类的合适的机器学习算法,将对卫生组织以及患者非常有益。

我们开始吧!

首先,我导入必要的库,并读入清理过的库。csv 文件:

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from collections import Counter
from sklearn.preprocessing import StandardScaler
# data splitting
from sklearn.model_selection import train_test_split, cross_val_score, GridSearchCV
# data modeling
from sklearn.metrics import confusion_matrix,accuracy_score,roc_curve,roc_auc_score,classification_report,f1_score
from sklearn.linear_model import LogisticRegression
from sklearn.naive_bayes import GaussianNB
from xgboost import XGBClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.svm import SVC
#ensembling
from mlxtend.classifier import StackingCVClassifier
import xgboost as xgb
import itertools
from sklearn.dummy import DummyClassifier
from sklearn import metricsdf=pd.read_csv('Data/cleaned_df.csv',index_col=0)

接下来,我执行了训练测试分割,并对我们的数据进行了缩放。回顾一下,我们必须训练-测试-分割我们的数据,以评估我们的模型,缩放我们的数据使我们的自变量的值的范围正常化。

y = df["target"]
X = df.drop('target',axis=1)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state = 0)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

然后,我使用 sklearn 的 DummyClassifier 来确定我们的基线准确性——即使只是猜测,也应该达到的成功率。

dummy_clf = DummyClassifier(strategy="stratified")
dummy_clf.fit(X_train, y_train)
DummyClassifier(strategy='stratified')
dummy_clf.predict(X_test)
dummy_clf.score(X_test, y_test)

这给了我们 49.18%的准确性,这是一个有用的衡量比较我们的模型。

接下来,我采用了不同的机器学习模型,以找出哪种算法的准确度最高。

  1. 逻辑回归
  2. k-最近邻
  3. 朴素贝叶斯
  4. 随机森林分类器
  5. 极端梯度增强
  6. 决策图表
  7. 支持向量分类器

逻辑回归

#INSTANTIATE LOGISTIC REGRESSION
logreg = LogisticRegression()
logreg.fit(X_train, y_train)
y_pred_log = logreg.predict(X_test)
lr_acc_score=metrics.accuracy_score(y_test, y_pred_log)
lr_f1_score=metrics.f1_score(y_test, y_pred_log)
lr_conf_matrix = confusion_matrix(y_test, y_pred_log)
# checking accuracy
print('Test Accuracy score: ', lr_acc_score)
print('Test F1 score: ', lr_f1_score)
print("confusion matrix")
print(lr_conf_matrix)
print("\n")
print(classification_report(y_test,y_pred_log))

作者图片

k-最近邻

#INSTANTIATE KNN MODEL
knn = KNeighborsClassifier()
knn.fit(X_train, y_train)
# make class predictions for the testing set
y_pred_knn = knn.predict(X_test)
knn_acc_score=metrics.accuracy_score(y_test, y_pred_knn)
knn_f1_score=metrics.f1_score(y_test, y_pred_knn)
knn_conf_matrix = confusion_matrix(y_test, y_pred_knn)
# checking accuracy
print('Test Accuracy score: ', knn_acc_score)
print('Test F1 score: ',knn_f1_score )
print("confusion matrix")
print(knn_conf_matrix)
print("\n")
print(classification_report(y_test,y_pred_knn))

作者图片

决策图表

# INSATNTIATE DECISION TREE MODEL
tree = DecisionTreeClassifier()
tree.fit(X_train, y_train)
y_pred_tree = tree.predict(X_test)
tree_acc_score=metrics.accuracy_score(y_test, y_pred_tree)
tree_f1_score=metrics.f1_score(y_test, y_pred_tree)
tree_conf_matrix=confusion_matrix(y_test,y_pred_tree)
# checking accuracy
print('Test Accuracy score: ', tree_acc_score)
print('Test F1 score: ', tree_f1_score)
print("confusion matrix")
print(tree_conf_matrix)
print("\n")
print(classification_report(y_test,y_pred_tree))

作者图片

随机森林

#INSTANTIATE RANDOM FOREST MODEL
rfc = RandomForestClassifier()
rfc.fit(X_train, y_train)
y_pred_forest = rfc.predict(X_test)
rfc_acc_score=metrics.accuracy_score(y_test, y_pred_forest)
rfc_f1_score = metrics.f1_score(y_test, y_pred_forest)
rfc_conf_matrix=confusion_matrix(y_test,y_pred_forest)
# checking accuracy
print('Test Accuracy score: ', rfc_acc_score)
print('Test F1 score: ', rfc_f1_score)
print("confusion matrix")
print(rfc_conf_matrix)
print("\n")
print(classification_report(y_test,y_pred_forest))

作者图片

极端梯度推进

# Instantiate the XGBClassifier: xg_cl
xg_cl = xgb.XGBClassifier(learning_rate=0.01, n_estimators=10, seed=25)
# Fit the classifier to the training set
xg_cl.fit(X_train,y_train)
# Predict the labels of the test set: preds
y_pred_xgb = xg_cl.predict(X_test)
xgb_acc_score=metrics.accuracy_score(y_test, y_pred_xgb)
xgb_f1_score = metrics.f1_score(y_test, y_pred_xgb)
xgb_conf_matrix=confusion_matrix(y_test,y_pred_xgb)
# Compute the accuracy: accuracy
# checking accuracy
print('Test Accuracy score: ',xgb_acc_score)
print('Test F1 score: ', xgb_f1_score)
print("confusion matrix")
print(xgb_conf_matrix)
print("\n")
print(classification_report(y_test,y_pred_xgb))

作者图片

朴素贝叶斯

nb = GaussianNB()
nb.fit(X_train,y_train)
y_pred_nb = nb.predict(X_test)
nb_conf_matrix = confusion_matrix(y_test,y_pred_nb)
nb_acc_score = metrics.accuracy_score(y_test, y_pred_nb)
nb_f1_score=metrics.f1_score(y_test, y_pred_nb)
print('Test Accuracy score: ',nb_acc_score)
print('Test F1 score: ', nb_f1_score)
print("confusion matrix")
print(nb_conf_matrix)
print("\n")
print(classification_report(y_test,y_pred_nb))

作者图片

支持向量分类器

svc =  SVC(kernel='rbf', C=2)
svc.fit(X_train, y_train)
y_pred_svc = svc.predict(X_test)
svc_conf_matrix = confusion_matrix(y_test, y_pred_svc)
svc_acc_score = metrics.accuracy_score(y_test, y_pred_svc)
svc_f1_score = metrics.f1_score(y_test, y_pred_svc)
print('Test Accuracy score: ',svc_acc_score)
print('Test F1 score: ', svc_f1_score)
print("confusion matrix")
print(svc_conf_matrix)
print("\n")
print("Accuracy of Support Vector Classifier:",svc_acc_score,'\n')
print(classification_report(y_test,y_pred_svc))

作者图片

正如你在上面看到的,我打印了每个模型的准确度分数和 F1 分数。这是因为我不确定哪个指标最适合我的业务案例。在阅读了 Purva 的这篇伟大的文章后,我决定使用准确性作为我的分类标准,因为在类别分布上没有很大的差异,并且因为在确定谁有或没有心脏病时,真正的积极和真正的消极很重要。

此外,我们看到上面的准确度分数在 70-80 之间,我们如何提高这个准确度分数?我们可以用合奏法!集成方法是创建多个模型并组合它们以产生改进结果的技术。与单一模型相比,集成方法通常表现更好。有不同类型的集合方法可以被利用,关于集合方法的更多信息请参见这篇文章。

对于当前的项目,我使用了一个堆叠 cv 分类器,它通过一个元分类器组合了多个分类模型,并使用交叉验证来为二级分类器准备输入数据。对于分类器,我检查了每个模型的准确度分数:

model_ev = pd.DataFrame({'Model': ['Logistic Regression','Random Forest','Extreme Gradient Boost',
                    'K-Nearest Neighbour','Decision Tree','Naive Bayes', 'Support Vector Classifier'], 'Accuracy': [lr_acc_score,
                    rfc_acc_score,xgb_acc_score,knn_acc_score,tree_acc_score,nb_acc_score, svc_acc_score]})
model_ev

作者图片

然后,我选择了表现最好的 3 个模型,并将它们输入到堆叠 cv 分类器中:

scv=StackingCVClassifier(classifiers=[logreg,nb,svc],meta_classifier=nb,random_state=22)
scv.fit(X_train,y_train)
scv_predicted = scv.predict(X_test)
scv_conf_matrix = confusion_matrix(y_test, scv_predicted)
scv_acc_score = accuracy_score(y_test, scv_predicted)
scv_f1_score = f1_score(y_test, scv_predicted)print("confusion matrix")
print(scv_conf_matrix)
print("\n")
print("Accuracy of StackingCVClassifier:",scv_acc_score*100,'\n')
print(classification_report(y_test,scv_predicted))

作者图片

如上所述,我们使用堆叠 cv 分类器获得了大约 92%的准确率。

让我们对系综模型的混淆矩阵有一个更好的了解

作者图片

正如我们所看到的,集合模型稍微超出了非主导类的预测。

接下来,让我们绘制所有模型的 ROC 曲线。

# Generate ROC curve values: fpr, tpr, thresholds
fpr_log, tpr_log, thresholds_log = roc_curve(y_test, y_pred_log)
fpr_knn, tpr_knn, thresholds_knn = roc_curve(y_test, y_pred_knn)
fpr_tree, tpr_tree, thresholds_tree = roc_curve(y_test, y_pred_tree)
fpr_rfc, tpr_rfc, thresholds_rfc = roc_curve(y_test, y_pred_forest)
fpr_xgb, tpr_xgb, thresholds_log = roc_curve(y_test, y_pred_xgb)
fpr_nb, tpr_nb, thresholds_log = roc_curve(y_test, y_pred_nb)
fpr_svc, tpr_svc, thresholds_log = roc_curve(y_test, y_pred_svc)
fpr_ens, tpr_ens, thresholds_ens = roc_curve(y_test, scv_predicted)# Plot ROC curve
plt.plot([0, 1], [0, 1], 'k--')
plt.plot(fpr_log, tpr_log,label = 'Logistic')
plt.plot(fpr_knn, tpr_knn,label = 'KNN')
plt.plot(fpr_tree, tpr_tree,label = 'Decision Tree')
plt.plot(fpr_rfc, tpr_rfc,label = 'Random Forest')
plt.plot(fpr_xgb,tpr_xgb,label= 'XGB')
plt.plot(fpr_nb,tpr_nb,label= 'Naive Bayes')
plt.plot(fpr_svc,tpr_svc,label= 'Support Vector Classifier')
plt.plot(fpr_ens, tpr_ens,label = 'Ensemble')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.legend()
plt.title('ROC Curve no GridSearch')
plt.show()

作者图片

从我们的可视化中,我们可以清楚地看到集合模型在我们测试的所有模型中表现最好。

最后,我计算了特征重要性,这是根据独立变量在预测目标变量时的有用程度给它们打分。

feature_importance = abs(logreg.coef_[0])
feature_importance = 100.0 * (feature_importance / feature_importance.max())
sorted_idx = np.argsort(feature_importance)
pos = np.arange(sorted_idx.shape[0]) + .5featfig = plt.figure()
featax = featfig.add_subplot(1, 1, 1)
featax.barh(pos, feature_importance[sorted_idx], align='center')
featax.set_yticks(pos)
featax.set_yticklabels(np.array(X.columns)[sorted_idx], fontsize=10)
featax.set_xlabel('Relative Feature Importance')plt.tight_layout()   
plt.show()

作者图片

从上图可以看出,变量 ca 对预测一个人是否患有心脏病最有影响。变量 ca 指荧光镜着色的主要血管数(0-3)。主要血管的数量越少,流向心脏的血液量就越少,增加了心脏病的发病率。

摘要

从这个分类项目中,我们可以看到,与使用单独的分类模型相比,使用堆叠 cv 分类器提高了整体准确性。我们的基本模型表现为大约 49%,而我们的集合模型表现为大约 92%的准确性。我还试图使用网格搜索方法来改进单个模型,并使用堆叠 cv 分类器,但只能达到与当前集成模型相同的精度。

感谢您的阅读:)所有代码都在我的 GitHub 上!

心脏病分类项目—第一部分

原文:https://towardsdatascience.com/heart-disease-classification-project-part-i-eee6301121bf?source=collection_archive---------43-----------------------

对 UCI 心脏病数据集的探索性数据分析

比尔·牛津在 Unsplash 上的照片

在美国,心血管疾病或心脏病是女性和男性以及大多数种族/民族的主要死亡原因。心脏病描述了一系列影响心脏的情况。心脏病范围内的疾病包括血管疾病,如冠状动脉疾病。根据疾病预防控制中心的数据,每年大约有四分之一的死亡是由于心脏病。世卫组织指出,人类的生活方式是这种心脏问题背后的主要原因。除此之外,还有许多关键因素提醒人们,这个人可能有患心脏病的机会,也可能没有。

我们将使用在这里发现的 UCI 心脏病数据集进行探索性数据分析(EDA),在第二部分中,我们将构建分类模型,并使用集成方法来产生高度精确的模型。在目前的数据集中,这项研究的出版物包括 303 名患者,并从 76 个与预测心脏病相关的特征中选择了 14 个。

变量描述

  1. 年龄:以年为单位的年龄
  2. 性别:性别(1 =男性;0 =女性)
  3. cp:胸痛类型—值 1:典型心绞痛,值 2:非典型心绞痛,值 3:非心绞痛性疼痛,值 4:无症状
  4. trestbps:静息血压(入院时单位为毫米汞柱)
  5. chol:血清胆固醇,单位为毫克/分升
  6. fbs:(空腹血糖> 120 mg/dl) (1 =真;0 =假)
  7. restecg:静息心电图结果-值 0:正常,值 1:ST-T 波异常(T 波倒置和/或 ST 抬高或压低> 0.05 mV),值 2:根据 Estes 标准显示可能或明确的左心室肥大
  8. thalach:达到最大心率
  9. exang:运动诱发的心绞痛(1 =是;0 =否)
  10. oldpeak =运动相对于休息诱发的 ST 段压低
  11. 斜率:峰值运动 ST 段的斜率-值 1:上坡,值 2:平,值 3:下坡
  12. ca:荧光镜染色的主要血管数(0-3)
  13. thal: 3 =正常;6 =修复缺陷;7 =可逆转缺陷
  14. 目标:1 =疾病,0 =无疾病

变量类型

  1. 连续-年龄,trestbps,chol,thalach,oldpeak
  2. 二进制—性别、fbs、exang、目标
  3. 分类— cp、restecg、斜率、ca、thal

让我们从 EDA 开始吧!

首先,我们导入必要的库并读入数据集

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.graph_objects as go # To Generate Graphs
import plotly.express as px # To Generate box plot for statistical representation
%matplotlib inline
import plotly.express as pxdf=pd.read_csv('heart.csv')
df.head()

作者图片

上面提供了变量的描述,只是为了重申,目标是我们的因变量,其中 0 =无心脏病,1 =心脏病。

让我们检查是否有任何错误数据值,以便分类变量具有正确的类别数,如上所述。检查完所有变量后,我们发现 thalca 各有一个额外的类别。我们将用 NaN 值替换这些值,然后用中值替换这些值

df.thal.value_counts()
#3 = normal; 6 = fixed defect; 7 = reversable defect# OUTPUT
2    166
3    117
1     18
0      2
Name: thal, dtype: int64# Replace 0 with NaN
df.loc[df['thal']==0, 'thal'] = np.NaNdf.ca.value_counts()
# number of major vessels (0-3) colored by flourosopy# OUTPUT
0    175
1     65
2     38
3     20
4      5
Name: ca, dtype: int64# Replace 4 with NaN
df.loc[df['ca']==4, 'ca'] = np.NaN# Replace NaN with median values
df=df.fillna(df.median())

接下来,让我们通过可视化箱线图来检查异常值

作者图片

从这个图像中我们可以看到, chol 有一个极值,我们将用它的中值来代替。

现在,我们将使用 plotly 创建更多的可视化来更好地理解数据。首先让我们看看我们的目标变量的分布:

y=df.target.value_counts()
x=['Disease','No Disease']fig=go.Figure(
    data=[go.Bar(x=x,y=y,text=y, textposition='auto',)],
                    layout=go.Layout(title=go.layout.Title(text='Target Variable (Heart Disease) Distribution')))
fig.update_xaxes(title_text='Target')
fig.update_yaxes(title_text='Number of Individuals')
fig.show()

作者图片

存在轻微的类不平衡,但没有严重到需要上采样/下采样方法。

让我们看看数据集中年龄的分布:

fig = px.histogram(df, x='age',color_discrete_sequence=['coral'])
fig.update_xaxes(title_text='Age')
fig.update_yaxes(title_text='Count')
fig.update_layout(title_text='Distribution of Age')fig.show()

作者图片

从上图中,我们可以看到当前数据集中的大多数患者年龄在 50-60 岁之间。

让我们看看性别目标变量中的分布:

female=df.loc[df['sex']==0]
female_values=female.target.value_counts()
male=df.loc[df['sex']==1]
male_values=male.target.value_counts()
target=['No Disease','Disease']fig = go.Figure(data=[
    go.Bar(name='female', x=female_values.index, y=female_values, text=female_values, textposition='auto'),
    go.Bar(name='male', x=male_values.index, y=male_values, text=male_values, textposition='auto'),
])
fig.update_xaxes(title_text='Target')
fig.update_yaxes(title_text='Count')
fig.update_layout(title_text='Distribution of Sex According to Target Variable')
fig.update_layout(barmode='group')
fig.show()

作者图片

从上图我们可以看出,在心脏病组(1)中,男性患者多于女性患者。

接下来,让我们看看胸痛或心绞痛( cps )在我们的目标变量中是如何变化的。当心肌没有获得足够的富氧血液时,就会发生心绞痛,导致胸部不适,通常还会蔓延到肩部、手臂和颈部。

cp=['Typical Angina','Atypical Angina','Non-Anginal Pain','Asymptomatic']
y1=df.loc[df['target']==0].cp.value_counts()
y2=df.loc[df['target']==1].cp.value_counts()fig = go.Figure(data=[
    go.Bar(name='Disease', x=cp, y=y2),
    go.Bar(name='No Disease', x=cp, y=y1)
])
fig.update_layout(barmode='group')
fig.update_xaxes(title_text='Chest Pain Type')
fig.update_yaxes(title_text='Count')
fig.update_layout(title_text='Distribution of Target Variable According to Chest Pain Type')fig.show()

作者图片

从上图中可以看出,大多数非疾病患者经历了典型的心绞痛,与疾病患者相比,心绞痛被描述为胸闷。在经历过非典型心绞痛和非心绞痛的患者中,似乎也有一种平衡。

现在让我们看看空腹血糖( fbs )在目标变量中是如何变化的。空腹血糖是一项糖尿病指标,空腹血糖> 120 毫克/天被视为糖尿病(正确):

dis=df.loc[df['target']==1]
dis_values=dis.fbs.value_counts()
nodis=df.loc[df['target']==0]
nodis_values=nodis.fbs.value_counts()
target=['No Disease','Disease']
d=['False','True']fig = go.Figure(data=[
    go.Bar(name='Disease', x=d, y=dis_values, text=dis_values, textposition='auto'),
    go.Bar(name='No Disease', x=d, y=nodis_values, text=nodis_values, textposition='auto'),
])
fig.update_layout(barmode='group')
fig.update_xaxes(title_text='Fasting Blood Sugar (fbs)')
fig.update_yaxes(title_text='Count')
fig.update_layout(title_text='Distribution of Target Variable According to Fasting Blood Sugar')fig.show()

作者图片

在这里,我们看到,与类 false 相比,类 true 的数量更低。这表明 fbs 可能不是区分心脏病患者和非疾病患者的强有力特征。

摘要

在本文中,我们展示了一些 EDA 技术,可以在 UCI 的心脏病数据集上进行,为建立分类模型做准备。我们还创建了一些可视化工具来进一步理解数据,并确定哪些变量可能对区分疾病和非疾病患者有影响。在第二部分,我将建立一个分类模型,并使用集成方法来创建一个更准确的模型。

感谢阅读:)所有代码都在我的 Github 上提供。

PyTorch 中使用变压器的心脏病分类

原文:https://towardsdatascience.com/heart-disease-classification-using-transformers-in-pytorch-8dbd277e079?source=collection_archive---------20-----------------------

心脏病是一个重要的问题,深度学习可以解决问题。变形金刚是未来:当我们把一切结合起来会发生什么?

在本文中,将实现并讨论使用心电图(ECG/ EKG)数据的心房颤动(AF)分类系统。分类系统将是二元的(正常窦性心律,AF ),并将基于使用 PyTorch 框架的变压器网络。本文的结构如下:首先,将介绍手头的问题以及所用的数据;其次,将介绍网络的技术细节;第三,将介绍网络的实施和培训;最后,将介绍结果和讨论。这个项目的资源库可以在这里找到:https://github.com/bh1995/AF-classification。

心房颤动分类问题

心脏病是全球死亡的主要原因之一1。心脏病通常会导致心脏行为的不规则,称为心律不齐。在所有类型的心律失常中,心房纤维性颤动(AF)是最常见的心律失常,估计其在 2%至 4%的人群中流行;随着人口平均年龄的增加,预计将来流行率将线性增加。根据目前的统计数据,任何一个欧洲血统的人一生中患房颤的概率约为 37%2。标准的心脏监测技术是心电图(ECG/ EKG),它监测心脏中的电信号,因此对于临床医生诊断心律失常非常有用。这个项目的目的是利用真实的、公开可用的、已经被临床医生标记的心电图数据来训练深度学习模型。

本项目中使用的数据来自多个来源,即 2018 年中国生理信号挑战赛(CPSC2018)[3]、圣彼得堡英卡特 12 导联心律失常数据库[4]、佐治亚州 12 导联心电图挑战赛数据库(CinC2020)[5]、2017 年心脏病挑战赛生理网络计算(CinC2017)数据集[5]、背景心律失常数据库(CACHET-CADB)[6]。

所使用的数据源以不同的采样率收集他们的 ECG 数据,并且使用不同的设备(有些使用 Holter 监护仪,有些使用医院级 12 导联 ECG),这导致每个数据源的性质略有不同。为了增加深度学习模型的学习能力,明智的做法是以规范化的方式处理所有数据。在这个项目中,所有信号都使用了带通滤波器(FIR 滤波器),因此只保留了[0.5,40]范围内的频率。信号还以 300 Hz 的速率被重新采样,并被分成长度为 10 秒的单个片段(因此模型的每个输入是长度为 3000 个数据点的一维数组)。然后对每 10 秒的片段进行归一化,使得所有值都在 0 和 1 之间。下图显示了两个原始(raw)信号(一个 AF 和一个 normal)以及预处理后的两个相同信号。

显示房颤(左)和健康正常窦性心律(右)原始信号的图。

显示房颤(左)和健康正常窦性心律(右)的预处理信号的图。

第一幅图像中的信号图显示了标准、清晰的 10 秒长 ECG 记录。图中的 y 轴代表电压差,x 轴代表采样速率,本例中为 300 Hz。从图中可以看出,一个人的心脏电压与另一个人的不同。对于我们人类来说,显然是在 x 轴上寻找一种模式,而不是在 y 轴上看振幅。然而,深度学习模型以无偏见的方式计算特征,因此会天真地使用所有给定的信息(即使幅度通常与心律失常分类无关)。这就是为什么将数据标准化到给定的时间间隔(例如[-1,1]或[0,1])。上图显示了一个房颤的例子,这可以从一些心跳之间的不规则间隔中看出。这种情况是一个“简单”的例子,因为即使是业余爱好者也能清楚地看到 AF 信号的异常。

本项目使用的完整数据集可通过 链接 下载。数据全部经过预处理,以数组的形式保存在 .h5 文件格式中。下面的代码片段显示了如何加载数据集的示例。

为此项目加载数据集。

型号描述

本项目测试了两个模型,它们都遵循相同的基本架构,但使用不同的输入。第一种模型使用预处理的 ECG 信号作为其唯一的输入,而第二种模型使用预处理的 ECG 信号以及该信号的所谓 RRI (RR-interval)。RRI 是一个心跳和连续心跳之间的估计时间,以秒为单位。通过使用泛汤普金斯算法[10]估计信号中的 R 峰(每个心跳的中间位置),然后使用以下等式来计算 RRI。

其中 Rn 为给定峰值, fs 为频率(采样率)。为了保持模型的输入 RRI 序列的固定长度,使用总 RRI 的前 10 个,并且如果发现少于 10 个,则补零。

项目中使用的模型受到了[8]工作的启发。该模型由以下模块组成:1)由一系列卷积层组成的嵌入网络,2)变换器编码器层的堆叠,3)由一系列全连接层组成的分类头。模型架构和模型训练的代码可以在这里找到。

嵌入:嵌入网络将一维卷积应用于原始 ECG 信号,这导致一系列嵌入表示( x[0],…,x[n] )。这些嵌入的表示与位置编码( p[0],…,p[n] )相加,以表示每个序列的顺序,如原始 transformer 论文中所做的那样[7]。结果是位置编码嵌入, e = ( x[0]+p[0],…,x[n]+p[n] ),然后用作堆叠变换器编码器层模块的输入。

转换器编码器层:转换器模块由堆叠的转换器编码器层组成,其中每个编码器由多头自关注机制子层组成,经过反复试验,发现四个编码器层和头产生了良好的结果。同样,经过反复试验,编码器内的嵌入维数被选择为 64 ,编码器层内的前馈网络的维数被选择为 512 。转换器模块的输出是具有形状、[序列长度、批量大小、嵌入]的注意力权重的张量。必须以某种方式转换输出,以便将其输入分类头模块,即需要将其转换为形状[批量大小,嵌入]。尝试了两种方法,第一种是简单地取序列维度上张量的平均值,第二种是使用自我注意力集中层,如[9]的工作中所建议的。两种方法都表现出良好的性能,然而,利用自我注意池层产生了最好的结果。自我注意力集中层被应用于变换器模块的输出,该变换器模块产生嵌入,该嵌入是编码器序列中特征的学习平均。

分类头:自我注意力池的输出被用作最终分类头的输入,以产生用于预测的逻辑。最终的分类头是两个完全连接的层,中间有一个分离层。

培养

使用二进制交叉熵作为损失函数,AdamW 算法作为优化器来训练该模型( β1=0.9,β2=0.98,ε=10^(-9) )。10^(-3 的初始学习速率),并且使用学习调度器来在前 30 个时期之后开始每五个时期将学习速率降低 5%。该数据集总共有 52 370 个 10 秒长的 ECG 信号,其中正常与房颤标记的比例大致相等。随机选择数据集的 85% (44 514)用于训练,剩余的 15% (7 855)用于测试。使用的批量大小为 10,并且在云计算环境中使用特斯拉 P100 GPU 进行训练。

结果

两种模型的结果将在下面给出,首先是仅使用原始 ECG 信号的模型,然后是使用原始 ECG 信号以及该信号的 RRI 的模型。

使用原始 ECG 信号:

如下图所示,该模型显示了各时期的一致学习,没有任何相当大的过度拟合。测试准确度也持续增长。由于这项任务是对疾病的二元分类,敏感性和特异性可以说是一个更好的性能指标。训练结束时测试数据上的灵敏度特异性分别为 85.692.7 。训练时间大约是每个时期 178 秒。

各时期的训练(橙色)和测试(蓝色)数据的损失曲线。

跨时期测试数据模型的准确性。

使用原始 ECG 信号和 RRI:

当在训练/推断期间使用 RRI 特征时,模型性能提高。下图显示,模型显示出明显的过度拟合迹象,但是,这种过度拟合不会对各时期测试数据的模型准确性产生负面影响。训练结束时测试数据的灵敏度特异性分别为, 96.995.6 。训练时间大约是每个纪元 1550 秒。

各时期的训练(橙色)和测试(蓝色)数据的损失曲线。

跨时期测试数据模型的准确性。

结论

从结果可以清楚地看出,基于变换器编码器的网络在对 10 秒长的 ECG 信号中的 AF 进行分类方面工作良好。同样清楚的是,使用 RRI 特征以训练和推理时间增加近九倍为代价,提供了模型性能的巨大改进。这种时间增加归因于用于执行 R 峰检测的泛汤普金斯算法很慢的事实。

参考

1心脏病和中风统计 2018 年更新:来自美国心脏协会的报告。美国心脏协会,1,2018。

2与欧洲心胸外科协会(EACTS)合作制定的 2020 年欧洲心脏病学会房颤诊断和管理指南:欧洲心脏病学会(ESC)房颤诊断和管理特别工作组在 ESC 欧洲心律协会(EHRA)的特殊贡献下制定。欧洲心脏杂志,2020 年 8 月。ehaa612。

[3]刘芳芳、刘春燕、赵良英、张晓燕、吴晓林、徐晓燕、刘延林、马春燕、魏胜生、何志清、李俊卿和郭念英。一个用于评估心电图节律和形态学异常检测算法的开放式数据库。医学影像与健康信息学杂志,2018,8(7):1368–1373。

[4] Goldberger,a .,Amaral,l .,Glass,l .,Hausdorff,j .,Ivanov,P. C .,Mark,r .,& Stanley,H. E. (2000 年)。生理银行、生理工具包和生理网:复杂生理信号新研究资源的组成部分。循环[在线]。101 (23),第 e215–e220 页。

[5]佩雷斯·阿尔代·埃、古·阿、沙阿·阿吉、罗比肖·阿吉、黄艾、刘·阿吉、刘·阿吉、拉德·阿吉、埃罗拉·阿吉、塞耶迪·阿吉、李 q、沙尔马·阿吉、克利福德 GD 、雷纳·马。12 导联心电图的分类:2020 年心脏病学挑战中的生理网络/计算。生理测量。41 (2020).

[6] Devender Kumar、Sadasivan Puthusserypady 和 Jakob Eyvind Bardram。CADB 纪念印。2021 年 5 月 5 日。https://doi.org/10.11583/dtu . 14547264 . v1

[7]瓦斯瓦尼,a .,布雷恩,g .,沙泽尔,n .,帕尔马,n .,乌兹科雷特,j .,琼斯,l .,戈麦斯,A. N .,凯泽,l .,&波洛苏欣,I .注意力是你所需要的一切,。arXiv:1706.03762v5。

[8] A .纳塔拉扬,..用于 12 导联心电图分类的宽深度变压器神经网络。 2020 年心脏病学计算,2020 年,第 1–4 页,doi: 10.22489/CinC.2020.107

[9]萨法里出版社,印度,m .,&赫尔南多,J..说话人识别的自我注意编码和汇集。arXiv:2008.01077v1

10 潘杰和汤普金斯。一种实时 QRS 检测算法。IEEE 生物医学工程汇刊,BME-32 卷,第 3 期,第 230-236 页,1985 年 3 月,doi: 10.1109/TBME.1985.325532

激烈的讨论:使用气候数据预测冲突强度

原文:https://towardsdatascience.com/heated-discussions-predicting-conflict-intensity-using-climate-data-7084d623f8d2?source=collection_archive---------35-----------------------

变更数据

使用一个世纪的气候变化数据建立一个机器学习模型来预测冲突的强度

图片来自 iStock,授权给 Richard Pelgrim

这个故事是追踪我第一个独立数据科学项目进展的系列报道的一部分。找到上一篇 这里 和 Jupyter 笔记本 这里

TL;博士;医生

一些研究人员推测,气候变化正在导致政治紧张局势加剧,因此正在推动世界各地武装冲突的增加。该项目试图建立一个机器学习模型,根据周围地区的可用降水和温度数据预测印度的冲突强度(以每天死亡人数衡量)(< 300km). The project concludes that 使用当地气候数据不可能准确预测冲突强度)。尽管如此,它还是偶然发现了一些有趣的信息。

问题是

气候变化越来越多地导致全球极端天气模式。这些极端天气情况,如高温、干旱、洪水等。在世界的一些地方,正导致大规模的人口流动和对土地和其他自然资源的竞争加剧。这种竞争可能导致政治紧张,并可能以武装冲突的形式出现。

这一领域的现有研究暗示了气候变化和武装冲突增加之间的可能关系;比如这里的和这里的。然而,大多数专家指出,这种关系在很大程度上仍然是推测性的,很难证明,因为还有许多其他因素推动冲突,如地缘政治和/或社会经济因素。

在这种背景下,我决定使用我的第一个顶点项目(作为跳板数据科学职业跟踪的一部分完成)来研究是否可以在气候测量和冲突强度测量之间建立直接关系。建立这种关系对以下方面很有价值:

  1. 说明了另一个尽快努力减缓气候变化原因,
  2. 预期人道主义援助和/或军事干预,以应对预期的冲突事态发展。

数据

该项目结合了来自两个独立数据集的数据:

  1. 乌普萨拉冲突数据计划全球武装冲突数据集,包含 1989 年至 2019 年间 220,000 多起冲突事件的信息,以及
  2. 全球历史气候网络数据集包含 1889 年至 2020 年间全球 115,000 多个站点的天气测量数据。

仅仅是绘制冲突事件和气象站就已经构成了一幅迷人的地图:

作者生成的图像

很明显,总的来说,有很多冲突事件的国家只有很少的气象站,除了像印度、南非和土耳其这样的少数国家。

浑身脏兮兮的

现在我们进入了项目中真正有肉和最令人满意的部分(记住:我喜欢肉丸——尤其是当它们出现在正确的地方时)。我在项目的探索性数据分析阶段花了 70 多个小时;掌握大型数据集,掌握用于处理空间数据的 geopandas 包,并找出哪些肉丸真正值得关注。指数学习曲线。

我将分享项目这一部分的三个很酷(也很重要)的发现:

肉丸# 1——气候数据的可用性

这是一个难以接受的事实,但对接下来的事情非常重要:不是所有的气象站都有全年的气候数据。一个气象站可能只记录了 20 年的降雨量,然后只记录了几年的平均温度,然后一段时间什么都没有…你明白了。

特别是 1950 年之前和 2012 年之后的几年显示覆盖面很差,这将影响我们能够对 1989 年至 2019 年之间发生的冲突事件进行的比较。

作者生成的图像

肉丸# 2——季节性高峰

第二个肉丸更有趣:绘制整个观察期(1989 年至 2019 年)内每月武装冲突事件的数量显示:

  1. 冲突事件数量的总体增加——这可能是由于实际冲突的增加或(更有可能)报道和记录的增加,以及
  2. 持续的季节性高峰

季节性天气模式会增加冲突事件的可能性吗?

作者生成的图像

肉丸# 3——地图的力量

这最后的肉丸特别给力。下面的地图显示了所有的冲突事件,按照事件发生的年份进行着色,标记的大小根据事件的总死亡人数而增加。图像中心巨大的紫色斑点是构成卢旺达种族灭绝事件的叠加。其他暴行,如斯雷布雷尼察大屠杀和 911 袭击也跳了出来。

作者生成的图像

我必须承认,当这个情节在凌晨 2 点出现在我的屏幕上时,我真的哽咽了。这尖锐地提醒我们地图传达信息的力量 事实上,我们用来指我们电脑上的大量信息的非个人化、枯燥的四个字母的单词总是与实际的人类生活(或死亡)联系在一起——换句话说:它很重要。

Hocus Pocus by Focus(歌唱印度)

如果你没有得到那个史诗般的亚文化参考,那么请暂停一下,进入这个链接,欣赏 6 分 42 秒改变人生的音乐插曲。

你回来了?

不用谢我。

当然,所有这些全球模式都很迷人,但在项目的这一点上,我被大量的意大利面条和可能的路线所困扰(事实证明,并非所有的意大利面条都通向罗马)。所以我决定将项目范围缩小到一个国家和一个焦点。是时候去印度了。

我选择印度作为案例研究,因为它有冲突和气候数据的必要重叠:15000 多起冲突事件和 3800 多个气象站。巨大的潜力……

….不是!事实证明,在 3800 多个气象站中,只有 25 个有足够的冲突事件发生年份的气候数据。幸运的是,这 25 个监测站均匀分布在全国各地,在每个可识别的冲突事件群附近至少有一个监测站。

作者生成的图像

我运行了一个 CkdTree 分类器 将每个冲突事件与这 25 个气象站中最近的气象站进行匹配。然后,我可以计算出一系列新的气候特征,让我们了解每个冲突事件周围地区的气候变化模式。

我们来关联一下。

需要另一个插曲吗?我明白你的意思,嘘——你知道三角形也是我最喜欢的形状。

深入研究我们的原始功能和新功能之间的关联揭示了三件重要的事情:

  1. 总死亡人数和任何气候特征(新的或旧的)之间没有明显的关联。这意味着很难建立一个预测模型…
  2. 在冲突事件的总死亡人数和持续时间(以天为单位)之间有一些关联。这是有道理的——更长的冲突更有可能导致更多的死亡。
  3. 气候特征几乎都是高度相关的。

作者生成的图像

死亡总数和持续天数都可以作为冲突强度的指标,这也是我们试图预测的。为了将这两者合并成一个变量,同时考虑到它们之间的相关性,我决定将我们的目标特征重新表述为死亡率:冲突事件每天的死亡人数。

我们的最终数据框架有 14364 个观察值和 33 个特征(1 个目标,32 个预测值)。

超级名模

我们现在准备开始构建我们的预测模型。我构建了 6 个不同的模型来比较性能:

  1. 一个虚拟回归变量,简单地预测每个冲突事件的平均死亡率——这将是我们用来比较实际模型性能的基线模型,
  2. 现成的线性回归模型
  3. 使用选择最佳特征优化的线性回归模型
  4. 现成的随机森林回归模型
  5. 使用超参数调谐优化的 RF 回归模型,以及
  6. 使用超参数调整优化的 Lasso 回归模型。

下图包含了一大串数字,基本上告诉我们,我还不如在第一步就停止了。出于所有实际目的,5 个机器学习模型中没有一个比基线模型做得更好,基线模型基本上只是一个有根据的猜测。

因此,该项目的结论是

使用选定的气候特征不可能准确预测印度的冲突强度。

关键要点

令人失望?一点点。出乎意料?不完全是。该领域的现有研究已经警告我们,这种关系将很难确定,在项目的 EDA 阶段生成的相关性热图基本上已经证实了这一点。

所以…浪费时间?肯定不是。这个项目给我们留下了一些重要的收获:

首先,气候数据本身可能不足以预测冲突强度,但可能证明是包含其他特征(社会经济、政治等)的冲突预测模型的有用补充。).与基线模型相比,预测能力略有提高;

其次,我认为最重要的发现之一是在这篇文章的顶部,在气象站和冲突事件的地图上。显而易见的是,武装冲突发生的地方和气候数据主要收集的地方不匹配。这是主张在世界上持续经历武装冲突的地区开展更多研究工作的有力理由。

下一步是什么?

当然,工作永远不会结束。

图片来自 https://giphy.com/memecandy/

我要说的是,这种当前模式有三种主要的改进方式:

首先是扩大项目的范围,不仅将印度的案例研究扩展到其他国家,也不仅仅使用气候数据来包括社会经济和政治因素。其他国家的模式可能更强,包括除气候数据之外的数据肯定会提高性能。

第二是获取额外的气候数据。我们看到,在印度的例子中,虽然我们一开始有近 4000 个气象站,但其中只有 25 个有我们感兴趣的年份的足够的气候记录。额外的数据将使气候模式的模型更加精细,这将大大提高模型的预测能力。

最后,重新构建分析并将有冲突的区域与没有冲突的区域进行比较将会很有趣。在目前的模型中,我们将冲突事件相互比较,但很可能在发生武装冲突的地区和没有发生武装冲突的地区之间存在更明显的差异。这意味着将我们的观察单位从“冲突事件”改为“国家”或其他单位区域。然后我们可以建立一个模型来预测每单位面积的事故数量。这将允许我们调查我们上面呈现的季节性峰值(如肉丸#1),这些峰值在 冲突事件计数 中,而不在死亡计数中。我的直觉是,如果我们以这种方式重新构建问题,可能会有更强的信号。

伙计们,就这样吧。如果您有任何问题或反馈,请联系我们,尤其是如果您是一位对该主题充满热情的数据科学家(或一般的研究人员),我很乐意与您联系!

下面是一个链接,链接到我对这个项目的介绍,请随时与任何人分享,它可能是有用的或有启发性的。

最后但同样重要的是,我要大声感谢我的导师盖伊·马斯卡尔一路走来给予我的宝贵支持和积极反馈!

你好,“Covid”世界:Python Dash 和 R Shiny 对比

原文:https://towardsdatascience.com/hello-covid-world-python-dash-and-r-shiny-comparison-cc97afef9d82?source=collection_archive---------11-----------------------

比较 Dash 和 Shiny 在最简单但交互的仪表板实现中的差异

在数据科学领域,项目的最终目标通常是以某种仪表板或 web 应用程序来可视化您的结果。Python 和 R 这两种广泛使用的数据科学语言都有自己的包来解决这个问题。

r 有一个名为 Shiny 的主包,它使得直接从 r 构建交互式 web 应用程序变得容易。另一方面,Python 有几个根据项目强度而广泛使用的包。

Python web 应用程序的三个主要包是 Django、Flask 和 Dash。Django 是一个高级 Python Web 框架,它鼓励快速开发和干净、实用的设计。Flask 是一个轻量级的 web 应用程序框架。它旨在快速轻松地开始使用,并能够扩展到复杂的应用程序。

根据 Dash 网站的介绍:

Dash 基于 Flask、Plotly.js 和 React.js 编写,非常适合用纯 Python 构建具有高度自定义用户界面的数据可视化应用程序。它特别适合任何使用 Python 处理数据的人。

通过几个简单的模式,Dash 抽象出了构建基于 web 的交互式应用程序所需的所有技术和协议。Dash 非常简单,您可以在一个下午的时间里围绕您的 Python 代码绑定一个用户界面。

Shiny 和 Dash 都有一个共同的目标,那就是用最少甚至不需要像 JavaScript 这样的 web 开发技能来制作一个 web 应用仪表板。尽管两者都允许使用 JavaScript、HTML、CSS 栈进行更好的定制。

正如许多开发人员所知,每当你开始学习一门新的编程语言或工具时,你要做的第一件事就是尝试编写一个“Hello,World”程序。这只是简单地展示了语法的最简单形式和新语言的内部工作方式。

本文通过 Python Dash 和 R Shiny 之间的比较来比较这种想法,比较两种语言中非常简单的 dashboard web 应用程序。当然,它也是以新冠肺炎数据为中心的,就像过去一年世界其他地区一样。

免责声明:我对 Python 和 R 都有经验,但是我想在我相对公正地学习 Dash 和 Shiny 的同时写这篇文章,以便进行公平的比较。

Dash 和 Shiny 的交互式应用程序的准系统

Dash 和 Shiny 使用类似的结构,首先在组件的层次树中定义整体界面和页面布局。接下来是根据动作改变布局的函数。

我选择展示最基本的交互应用程序,因为没有交互就很难描述结构。

破折号

这是一个几乎一行一行找到的例子这里。值得注意的是,Dash 在该网站上发现了惊人的文档。

在这个例子中,我们可以看到第一步是如何声明app.layout的,其中 HTML 部分是按照 web 应用程序从上到下的顺序定义的。有一个破折号核心组件(dcc)接收文本,然后最后的html.Div是输出文本。为了将这两者联系在一起,有一个@app.callback,这就是 Dash 如何创建一个动作和反应。回调将组件 ID 和属性/值作为输入,并将其传递给函数,然后将结果返回给已定义的html.Div组件。

发光的

这是一个同样简单,互动闪亮的应用程序。我们马上注意到一些相似之处。首先,如前所述,这两个程序都继承了相似的结构,首先定义 UI,然后定义反应性元素。一个不同之处是,对于这个闪亮的应用程序,所有输入都被传递给通用函数,每个输入都由input$input_value调用。

作为一个快速的比较,我们可以看到 Shiny 可以用更少的代码和更简单的代码交付相同的功能。部分原因是 Dash 是在 Flask 上构建的,Flask 是无终结的,这意味着它更加开放,并且没有标准的构建方式,因为这是开发人员的决定。此外,从上面的例子可以看出,Dash 集成了更多的 HTML。

让我们通过添加一些数据来显示常用的元素,如图表、下拉菜单、地图和滑块,从而进一步深入这种比较。

元素比较

所有的代码都可以在我的 GitHub 这里 中找到,但是为了节省本文的篇幅,我将主要关注这些元素的具体代码。

条形图和下拉菜单

Dash 附带了一个核心组件库,允许轻松声明常见的 HTML 组件,如DropdownsGraphs。由于 Plotly 和 Dash 非常紧密地交织在一起,几乎所有的图表和图形都是用 Plotly 的graph_objects完成的。因此,一旦选择了一个下拉值,数据集就会变成一个条形图,将阳性新冠肺炎病例叠加到测试总量上,以显示两者在 2020 年底之前如何随时间变化。

Plotly 的graph_objects与 Dash 连接的一个便利之处是,你无需额外代码就能自动获得 Plotly 的特性。这包括缩放,悬停功能,悬停比较,下载选项等。

这个代码块描述了如何实例化一个下拉菜单,并使用 Python 和 Dash 显示一个条形图。

此代码生成下面的条形图,该条形图由下拉菜单值决定,用于描述单个特定状态或所有状态的合计。

仪表板下拉菜单和条形图仪表板示例

Shiny 也有一个简单的 UI 元素声明,但是在使用输入时,你必须将它存储在一个新的变量中,以便能够与其他元素进行比较。这是因为输入是电抗元素,不能与非电抗变量(如字符串)进行比较。

Shiny 的好处是大多数用 R 编写代码的人已经使用了ggplot2包进行所有的绘图,所以很容易在 Shiny 应用程序中实现相同的绘图。

下面是一个类似程序的 R 实现,用于下拉菜单和条形图。

这段代码生成了闪亮的下拉菜单和条形图,以显示一段时间内的总数和阳性病例。

闪亮的下拉菜单和条形图仪表板示例

总的来说,下拉菜单在外观和功能上几乎是一样的。另一方面,我不得不给 Dash 一个现成的条形图,因为它附带了很多 Plotly 的有吸引力的特性。

旁白:有一个 Plotly R 库,但它不像 Dash 和 Plotly 那样自然地交织在一起。

地图和滑块

在本节中,我们将创建一个滑块,显示从新冠肺炎首次出现到 12 月 31 日的 2020 年的日期。然后,一旦选择了日期,我们将在美国地图上显示总病例汇总数据。Plotly 再次将 choropleth 地图作为其 graph objects 包的一部分。

滑块是另一个标准的dcc元素,但是一个巨大的抱怨和不便是它不允许输入日期。因此,我们必须有点创意,将滑块用作从 0 开始的数字输入。然后,使用选择的值和datetime Python 包,我们将这些天数添加到开始日期。也就是说,需要花更多的时间来确定哪些标记代表新的一个月的开始。

此代码块描述了如何实例化一个滑块,并使用 Dash 在选定的日期显示地图。

这将生成下面的图,该图显示了 choropleth US 图中按滑块选择的日期显示的所有测试用例。

Shiny 也有类似的实现,但是我找不到任何超级简单的方法来绘制美国地图。有几个不同的例子,他们使用了传单,但这似乎比我想要的简单地图有更多的定制。因此,我使用了来自城市研究所名为 urbnmapr 的 GitHub 包。

对于这个用例,我更喜欢 Shiny 的 slider,而不是 Dash 的,特别是因为它允许将日期作为值传入。因此,将选择的值传递给映射不需要预处理。此外,有一个动画选项,使地图可以逐步改变一天。

这个代码块描述了如何实例化一个滑块,并在选定的日期用 Shiny 显示一幅地图。

这将生成以下地图,该地图按滑块选择的日期显示 choropleth US 地图中各州的阳性病例总数。

结论

总的来说,我希望作为读者的你已经大致了解了如何为 Python Dash 和 R Shiny 制作简单的组件和反应式 web 应用程序。这是我的第一个正式项目,所以对我来说也是一个学习的过程。对于我最初的想法,我看到了两者在数据科学领域是如何有用的,并且从我目前的观点来看,它们可以互换,足以选择您喜欢的。也就是说,如果你更习惯使用 R,坚持使用它,Python 也是一样。我认为学习这两门课程会很有用。

也就是说,如果我必须选择一个继续,我可能会选择 Dash,原因如下。贯穿本文的第一个原因是,与 Plotly 交织在一起有很多优点,比如缩放、平移、悬停等。其次,Python 仍然是一种更受欢迎的语言,因此对于项目生命周期来说,用同一种语言继续仪表板阶段可能更容易。最后,Dash 是建立在 Flask 之上的,所以如果你想进一步扩展你的 web 应用来解决一个更大、更复杂的问题,你不必重启。

感谢大家的阅读!如果有什么让你惊讶或感兴趣的,请随时在评论中告诉我。😃

你好!我是 PAMI

原文:https://towardsdatascience.com/hello-i-am-pami-937439c7984d?source=collection_archive---------11-----------------------

面向数据科学的新模式挖掘 Python 库

图 1:跨越人工智能、数据挖掘、机器学习和深度学习的学习算法的广泛分类

大数据分析代表了一套发现隐藏在大型数据库中的知识的技术。这些技术可以大致分为四种类型:

  • 模式挖掘—旨在发现数据中隐藏的模式
  • 聚类—旨在对数据进行分组,使得组内的对象具有高的类内相似性和低的类间相似性。
  • 分类——旨在从学习的模型中为测试实例找到合适的类别标签
  • 预测—旨在从学习的模型中预测测试实例的值

如图 1 所示,模式挖掘和聚类是无监督学习技术,而分类和预测是监督学习技术。

一些 Python 库(例如,Sklearn、PyTorch、TensorFlow 和 Keras)已在文献中描述用于执行大数据分析。这些库主要关注聚类、分类和预测。据我们所知,不存在旨在发现隐藏在数据中的模式的 Python 库。有了这个动机,我们开发了一个新的 Python 库,叫做 PAMI。在这篇博客中,我们涵盖了以下主题:

  1. 什么是 PAMI?它的执照是什么?以及如何安装?
  2. PAMI 的组织结构是怎样的?
  3. 如何利用 PAMI 来发现频繁模式?
  4. 位置了解更多信息。

什么是 PAMI?它的执照是什么?如何安装?

PAMI 代表模式挖掘。这个库包含几个模式挖掘算法来发现隐藏在大量数据集中的知识。目前,PAMI 有 50 多种算法来寻找不同类型的基于用户兴趣的模式。示例包括频繁模式、相关模式、周期模式、频繁邻域模式和模糊周期模式。

PAMI 目前是在 GNU V3 许可下提供的。这个库的源代码可以在GitHub【3】获得。通过发出以下命令,可以从 PyPI 存储库直接安装 PAMI 库:

pip install -y pami

PAMI 的组织结构是怎样的?

PAMI 的算法是以分层的方式组织的。这个层次结构的格式是,

pami . pattern mining model . type of pattern . algorithm

  • patternMiningModel —表示需要发现的模式类型,如频繁模式、相关模式、模糊频繁模式等。
  • typeOfPattern 表示模式的分类。目前,PAMI 实施四种模式。(I)基本-查找数据中的所有模式,(ii)封闭-仅查找数据中的封闭模式,(iii)最大-仅查找数据中的最大模式,以及(iv)topK-查找数据中的前 k 个模式。
  • 算法—表示用于发现模式的技术。

一个例子是

PAMI.frequentPattern.basic.FPGrowth

其中frequency pattern是模型, basic 是模式类型, FPGrowth 是挖掘算法。

如何利用 PAMI 来发现频繁模式?

频繁模式挖掘是大数据分析中一种重要的知识发现技术。它包括识别数据中频繁出现的所有项目集(或模式)。一个典型的应用是购物篮分析。它包括识别客户经常购买的项目集。频繁模式的一个例子是:

{Beer, Cheese}     [support=10%]

上面的模式表明,10%的客户一起购买了商品“啤酒”和“奶酪”。这种信息对于用户放置产品和库存管理非常有用。关于频繁模式挖掘的更多信息可以在[5,6]找到。

我们现在使用 PAMI 图书馆和 Jupyter 笔记本一步一步地进行频繁模式挖掘。

  1. 点击此处【7】下载交易零售数据集。
  2. FP-growth 是一种著名的频繁模式挖掘算法。让我们首先通过在 Jupyter 中执行以下命令来导入这个算法:
from PAMI.frequentPattern.basic import FPGrowth as alg

3.通过提供文件、最小支持(minSup)和分隔符作为输入参数来初始化 FP-growth 算法。

obj = alg.FPGrowth('[transactional_retail.csv',100,'\t'](https://www.u-aizu.ac.jp/~udayrage/datasets/transactionalDatabases/transactional_retail.csv',100,'\t'))# '[transactional_retail.csv'](https://www.u-aizu.ac.jp/~udayrage/datasets/transactionalDatabases/transactional_retail.csv',100,'\t') is the input file downloaded from the URL
#100 is the minimum support count. 
#\t is the separetor that exist between the items in a transaction

4.开始采矿过程

obj.startMine()

5.通过执行以下代码将模式保存在文件中:

obj.savePatterns('frequentPatters_100.txt')
# 100 is the minSup count

在输出文件中,比如 frequentPatters_100.txt,第一列是模式,第二列是支持。

6.用户可以通过执行以下代码将发现的模式作为数据帧读取:

df = obj.getPatternsAsDataFrame()

7.挖掘算法的运行时和内存要求可以通过执行以下代码得出:

print('Runtime: ' + str(obj.getRuntime()))
print('Memory: ' + str(obj.getMemoryRSS()))

上述步骤的完整代码如下所示:

from PAMI.frequentPattern.basic import FPGrowth as algobj = alg.FPGrowth('[transactional_retail.csv',100,'\t'](https://www.u-aizu.ac.jp/~udayrage/datasets/transactionalDatabases/transactional_retail.csv',100,'\t'))
obj.startMine()obj.savePatterns('frequentPatters_100.txt')
df = obj.getPatternsAsDataFrame()print('Runtime: ' + str(obj.getRuntime()))
print('Memory: ' + str(obj.getMemoryRSS()))

我在哪里可以找到更多关于 PAMI 的信息?

访问 https://udayrage.github.io/PAMI/index.html了解更多信息。

结论

在这篇博客中,我们讨论了不同类型的学习算法,并讨论了现有的 python 库如何无法为用户提供发现数据中隐藏模式的工具。接下来,我们介绍了我们的 PAMI Python 库,它旨在填补现有库留下的空白。接下来,我们讨论了 PAMI 算法的组织结构。最后,我们展示了如何利用 PAMI 发现隐藏在零售数据中的频繁模式。

参考文献:

1https://plato.stanford.edu/entries/logic-ai/

2人工智能中的逻辑:https://www . researchgate . net/publication/46666490 _ Logic _ in _ AI

[3]https://github.com/udayRage/PAMI 源代码:PAMI

[4]https://udayrage.github.io/PAMI/index.htmlPAMI 用户手册

[5]频繁模式挖掘:当前状况和未来方向,作者 J. Han、H. Cheng、D. Xin 和 X. Yan,2007 年数据挖掘和知识发现档案,第 15 卷第 1 期,第 55-86 页,2007 年

[6]频繁模式挖掘,编辑。Charu Aggarwal 和 Jiawei Han,Springer,2014 年。

[7]交易零售数据集:https://www . u-aizu . AC . jp/~ udayrage/datasets/Transactional databases/Transactional _ Retail . CSV

使用 Python 自动执行会计任务

原文:https://towardsdatascience.com/help-your-finance-team-to-automate-accounting-tasks-using-python-68bcefe7524c?source=collection_archive---------6-----------------------

构建解决方案来自动化财务审计的重复性任务,并与您的财务同事分享,以提高他们的工作效率

Excel 自动化—(图片由作者提供)

如果你是数据分析师,想要访问大量的非结构化数据,你有影响的愿望,并且你痴迷于自动化重复的任务:去你的财务部门。

我将在本文中分享一个解决方案,它基于我从非常不结构化的 Excel 文件中提取数据来执行运营和财务审计的经验。

💌新文章直接免费放入您的收件箱:时事通讯

1.如何用 python 实现会计任务的自动化?

问题陈述

你是一家大型物流公司的数据分析师,你的财务团队同事请求你帮助建立一个模型来预测仓库运营的损益。

2017 年 5 月月度成本报告示例—(图片由作者提供)

您需要从会计团队构建的月度报告中提取信息,这些报告按类别列出了所有详细的成本

  • 您的研究中包含的 20 个仓库
  • 最近 36 个月的审计
  • 共 720 个 Excel 文件
  • 60 项费用跟踪
  • 3 类成本:投资、租赁、采购

目标

您的目标是构建一个工具,自动从这 720 个 Excel 文件中提取数据,对其进行格式化,并将所有内容合并到一个报告中。

审计报告示例—(图片由作者提供)

财务部门将使用此报告来分析过去 3 年的成本,并了解趋势。您的工具将有助于在单个报告中获得可见性,而无需使用额外的资源来手动执行。

http://samirsaci.com

2.你的解决方案

您将设计一个简单的 python 脚本,该脚本将执行:

  1. 打开文件夹中的每个 Excel 报表
  2. 处理和清理数据
  3. 按照上述格式建立月度报告
  4. 将月度报告与全球数据框合并
  5. 将最终结果保存在 Excel 文件中

导入每月 Excel 报告并处理数据

这里有几个要点:

  • 表头熊猫的参数只取第 5 位(对 excel 文件非常有用)
  • 用 0 填充 nan以对数值进行计算
  • 修剪列名称:在人们进行手工输入的情况下非常有用(‘单位成本’和‘单位成本’对用户来说看起来是一样的)

格式化列并执行计算

这部分和我处理的报表非常链接,我在这里分享代码供参考(链接)。

3.共享此工具

关注我,了解更多与供应链数据科学相关的见解。

现在您已经构建了工具,您想与财务团队分享它。供您参考,在我以前的公司,花了 2 周的时间(1 人)来完成这些任务。

如果您能实现这个简单的工具,您能想象会有什么影响吗?

如果你感兴趣,我写了一篇关于如何分享你的 python 脚本的文章,供没有任何 Python 经验的同事使用。

https://www.samirsaci.com/build-excel-automation-tools-with-python/

如果您遵循本文中解释的不同步骤,您将获得一个可执行文件(。exe)准备好与将运行该脚本的同事共享(即使他们没有安装 python)。

超越:自动化数据提取

在开始构建报告之前,您需要从 ERP 中收集数据。如果您正在使用 SAP,您可能会对这一系列关于 ERP 自动化的文章感兴趣

https://www.samirsaci.com/sap-automation-of-orders-creation-for-retail/ https://www.samirsaci.com/sap-automation-of-product-listing-for-retail/ https://www.samirsaci.com/sap-automation-for-retail/

关于我

让我们在 Linkedin 和 Twitter 上连线,我是一名供应链工程师,正在使用数据分析来改善物流运作和降低成本。

如果你对数据分析和供应链感兴趣,可以看看我的网站

https://samirsaci.com

利用深度学习帮助非洲农民提高产量

原文:https://towardsdatascience.com/helping-african-farmers-increase-their-yields-using-deep-learning-93a8d70dff36?source=collection_archive---------31-----------------------

利用迁移学习识别木薯叶部病害

一棵健康的木薯,由 malmanxx 在 Unsplash 上拍摄

如果你和我一样,那么大部分时间你都记不起自己做了什么梦。今天早上,我想起了一切。我梦见我收到一封电子邮件,宣布我赢得了木薯叶疾病比赛。除此之外,我在 Kaggle 网站上的状态显示我已经成为了 Kaggle 大师。

Kaggle 是一个由数据科学家和机器学习实践者组成的在线社区。根据你赢得的比赛数量,Kaggle 会给你分配一定的排名。

当我醒来时,仍然有点困惑,我登录了 Kaggle 网站。我还是一个卡格尔新手。我在木薯叶疾病竞赛的公共排行榜上的排名是 2343。到目前为止,梦想成真…

在我通过了开发者认证考试后,我才开始参加木薯叶病竞赛。我想看看我是否可以通过参加这个比赛来提高我的深度学习技能。

在之前的文章中,我使用迁移学习为狗和猫的比赛创建了一个模型。建立这个模型很有趣,但是它在现实世界中没有直接的用途。

和我参加的这个 Kaggle 比赛不一样。Kaggle 将这场比赛命名为木薯叶疾病分类。目标是从图像中识别木薯叶上的疾病类型。

木薯是非洲的主要食物,由小农种植。他们种植木薯是因为它能承受恶劣的环境。但是病毒性疾病是低产的主要原因。

为了对抗这些疾病,农民需要昂贵的农业专家的帮助。这些专家首先诊断病情。然后他们和农民一起制定了一个控制疾病的计划。

我们可以通过创造一种可以检测疾病的解决方案来帮助农民。例如,使用用他们的移动照相机拍摄的照片。该解决方案应该能够处理低质量图像和低带宽。

使用图像识别和深度学习的解决方案将是理想的候选方案。

在本文中,我们将使用 TensorFlow 2.4.1 和 Python 3.8 开发一个模型。我们将从一个卷积神经网络开始,让我们登上排行榜。然后,我们将使用 DenseNet201EfficientNetB3 预训练模型来改进我们的模型。最后,我们将使用测试时间增加 (TTA)来改进我们的预测。

如果你对代码感兴趣,请看这个 Github 库。

培训用数据

训练数据由 21.397 张木薯叶的 jpeg 图像组成。专家们在乌干达进行定期调查时收集了这些照片。这种格式真实地表现了农民在现实生活中需要诊断的内容。

来自比赛的图像分为以下五类。

  • 0 一片显示木薯白叶枯病的叶子(CBB)
  • 1 一片显示木薯褐条病的叶子(CBSD)
  • 2 一片呈现木薯绿色斑点(CGM)的叶子
  • 3 一片显示木薯花叶病(CMD)的叶子
  • 4 一片健康的叶子

从左至右, CBBCBSDCGMCMD 和一片健康的叶子。训练图像,由 Kaggle 提供

组织培训数据

Kaggle 将所有训练数据存储在一个文件夹中。每个图像的名称代表它的 id。id 和标签之间的映射存储在单独的 CSV 中。下面你可以看到一个 CSV 文件的例子。

train.csv 包含图像和标签之间的映射

我们需要重组图像,因为我想使用ImageDataGenerator类。我们还需要保留一部分训练图像进行验证。你可以在下面看到ImageDataGenerator需要的文件夹结构。

适用于 ImageDataGenerator 的文件夹结构

我们必须读取 CSV 文件,并将图像复制到正确的文件夹中。此外,我们必须在训练集和验证集之间划分图片。函数distribute_images接受单个参数。该参数定义了训练图像和验证图像之间的比率。值 0.7 选择 70%的图像用于训练,30%用于验证。

函数来重新组织适合 ImageDataGenerator 的图像

我们读取第 4 行的 CSV,然后使用train_df数据帧的unique()方法遍历标签。

创建和训练模型

我们将从一个小的卷积神经网络开始,而不是像我们在猫对狗比赛中那样使用迁移学习。虽然 TL 可能会让我们在排行榜上排名更高,但让我们在排行榜上获得第一个分数,以确保一切正常。

创建图像数据生成器

ImageDataGenerators 用于将训练和验证图像发送到深度学习管道。用于提供训练数据的 ImageDataGenerator 使用图像增强来增加图像的多样性。验证数据的 ImageDataGenerator 仅重新缩放图像。

创建 ImageDataGenerator

猫和狗竞争的区别在于 class_mode 是绝对的,因为我们有两个以上的输出标签。

构建和编译 CNN 模型

我们要训练的第一个模型是一个小型卷积神经网络。该模型使用四个卷积层、一个下降层和一个 512 个单元的隐藏密集层。

CNN 的定义

为了能够预测五个不同的类,输出层有五个单元。

训练模型

我们设定训练 50 个纪元,尽管使用的回调可能会更早停止。

训练模型

你看到我们使用create_callbacks()方法设置回调参数了吗?create_callbacks()方法返回三个不同回调的数组。见下文。在每个时期之后,TensorFlow 都会调用这些回调。

TensorFlow 在每个时期后调用三个回调

如果验证精度不再提高,则EarlyStopping回调停止训练。当 TensorFlow 看不到任何进展时,我们耐心地设置停止之前等待的纪元数。

ReduceLROnPlateau回调如果看不到任何提升,会自动降低学习率。

ModelCheckpoint如果验证损失小于前一个时期,则在一个时期后自动保存模型。有时,训练结束时的模型不如一个或两个时期前的模型准确。如果你使用这个回调,它将总是保存最好的一个。

可视化培训结果

在我的机器上,这个模型实现了 0.71 的最大验证精度和 0.79 的验证损失。

模型上的 fit 方法返回一个历史对象。TensorFlow 将每个历元的结果保存在这个历史对象中。我们可以使用 Matplotlib 库来可视化训练。

我们看到,训练和验证的准确性是相辅相成的。验证精度有一点波动,但是没关系。

训练和验证的准确性与我们的 CNN 时代,由作者的图像

训练和验证损失也是如此。一个优秀的第一基线,我们可以提交给竞争。

训练和验证损失 vs 我们 CNN 的时代,图片由作者提供

提交模型以获得分数

这就是这次比赛与以往不同的地方。你没有提交你的预测,而是提交了一个笔记本。

这个笔记本应该创建和训练您的模型,并创建预测。然后 Kaggle 在一个隔离的环境中运行笔记本。在这种环境下,笔记本可以访问所有的测试图像。

额外的限制是笔记本不能上网。此外,笔记本必须在不到 9 个小时内完成训练和预测。

创建和保存预测

在训练过程中,我们使用ModelCheckPoint来保存表现最好的模型。为了创建预测,我们使用load_model加载这个模型。然后,为了向模型提供图像,我们使用 ImageDataGenerator。我们只调整图像的大小。

计算预测

最后一步是使用熊猫将预测保存到一个名为submission.csv的文件中。这个文件的格式由 Kaggle 规定。Kaggle 将阅读该文件,并使用它来评分您的提交。

使用 pandas 保存 submission.csv 文件

我在让 Kaggle 拿起提交文件时遇到了一些麻烦。我发现我把文件放错了文件夹。

结果

提交笔记本一小时后,Kaggle 显示了分数,果然是 0.703。

笔记本的结果,图片由作者提供

这个分数让我在公共排行榜上名列第 2996 位——这是我们第一次尝试的良好开端。

放置在 Kaggle 排行榜上,图片由作者提供

如果你想知道公共排行榜的第一名是什么?这时是 0.911 ,所以我们还有很长的路要走:)

一个木薯根,由安妮·斯普拉特在Unsplash上拍摄

使用迁移学习改进我们的模型

之前,在猫和狗的比赛中,我们使用迁移学习改进了我们的模型。我们将尝试在这里做同样的事情。

然而,还有一个额外的复杂性。如果您使用默认的 Keras 应用程序,它会从互联网下载权重文件。在这个比赛中,我们的笔记本不能上网,所以那不行。稍后我们将看到如何解决这个限制。让我们首先尝试增加我们模型的准确性。

我们唯一要改变的是模型的架构。create_cnn_model函数看起来是这样的。

使用预训练的 DenseNet201 模型来改进我们的模型

我们创建了一个DenseNet201的实例,并将其作为模型的第一部分。然后我们Flatten结果,添加一个有 512 个单位的Dense层。输出层仍然是同一个有五个单元的Dense层。每个类别一个。

当我们训练模型时,精确度增加了 23 个时期。训练和验证准确性很好地相互跟随,这显示了一个健康的模型。训练和验证损失也是如此。验证准确度攀升至约 0.76,而验证损失在 0.70 处变平。

使用 DenseNet201 训练和验证我们的 TL 模型的准确度与时间,图片由作者提供

使用 DenseNet201 的 TL 模型的训练和验证损失与时期,图片由作者提供

当我们将这个模型提交给 Kaggle 时,它的得分是 0.772,这使我们在公共排行榜上上升到 2927 名。向上的一大步。

投稿结果,图片由作者提供

排行榜上的位置,作者图片

将模型提交给 Kaggle

当你想提交一个使用迁移学习的笔记本时,你必须拆分你的笔记本。第一部分训练并保存模型。这个笔记本可以上网检索重量。这样做的结果是保存的模型。使用此模型创建 Kaggle 数据集。

第二部分是你提交的笔记本。该笔记本从 Kaggle 数据集中加载保存的模型。然后,该模型用于创建预测。

使用不同的预训练模型 EfficientNet 进行优化

目前,表现最好的模型之一是 EfficientNet。EfficientNet,顾名思义,是最高效的模型之一。它需要最少的计算能力来进行推理。下图显示了 EfficientNet 与其他预训练模型的比较。

EfficientNet:反思卷积神经网络的模型缩放(Tan 等人,2019 年)

从 B0 到 B7,EfficientNet 有八种不同的变体。每个变体都更精确,使用更多的参数,见上图。

我们使用 EfficientB3 模型,这是精度和参数数量之间的一个很好的平衡。

我们创建了一个EfficientNetB3的实例,并将其作为模型的第一部分。然后我们使用一个GlobalAveragePooling2D层来调整结果的大小,并添加一个有 256 个单元的Dense层。一个Dropout层防止过度拟合。输出层仍然是同一个Dense层,有五个单元——每个类别一个。

使用 EfficientNetB3 创建模型

我们改进模型的另一件事是增加输入图像的尺寸。以前我们使用 150x150,但对于 EffientNet,我们使用 512x512。

当我们训练模型时,精确度增加了 25 个时期。训练和验证准确性很好地相互跟随,这显示了一个健康的模型。训练和验证损失也是如此。验证准确度攀升至约 0.87,而验证损失在 0.33 处变平。

使用 EfficientNetB3(图片由作者提供)训练和验证我们的 TL 模型的准确度与时间

使用 EfficientNetB3 的 TL 模型的训练和验证损失与时期,图片由作者提供

提交该模型后,我们将 2343 放在了公共排行榜上。又向前迈进了一大步。

投稿结果,图片由作者提供

我在排行榜上的位置,图片由作者提供

使用测试时间增加进行优化(TTA)

我们在训练过程中用来将图像输入网络的ImageDataGenerator随机转换照片,以增加训练图像的数量和变化。当我们创建预测时,我们也使用一个ImageDataGenerator,但是不增加图像。如果我们改变这个会发生什么?

测试时间增加(TTA)是一种提高预测准确性的技术。我们不再直接使用测试图像。首先,我们对图片进行不同的变换,如旋转裁剪、翻转、增强对比度等。然后我们得到了每一个被改变的图像的预测。

测试时间增加解释,图片由作者提供

然后我们对预测进行平均。这将为我们提供图像的预测。大多数情况下,这将提高你预测的准确性。

在我们的笔记本中实现 TTA

因为我们已经在使用 ImageDataGenerator 向模型提供测试图像以进行预测,所以我们只需向生成器添加增强选项,并通过测试集进行多次迭代。

在我们的笔记本上实现测试时间增加

从第十六行开始,我们在所有测试图像中迭代十次并保存预测。我们计算第 33 行预测的平均值。

我重用了评分 0.880 的模型。通过使用 TTA,预测的准确度达到了 0.889,如下图所示。

将 TTA 加入我们的笔记本的结果,图片由作者提供

使用 TTA 后我在排行榜上的位置,图片由作者提供

结论和进一步优化

我们从一个简单的卷积网络开始,这个网络的准确率为 71%。在我们改用使用 DenseNet201 和 EfficientNet 的迁移学习后,准确率提高到了 88%。通过使用测试时间增加,我们几乎将它提高了一个百分点,达到 88.9%。源代码可以在这个 Github 资源库中找到。

如果把我们的分数和排行榜的第一名 91.1%相比,还是有 2.2%的差距。通过阅读 Kaggle 社区共享的笔记本,我看到了一些提高准确性的附加技术。下面我就提一下,简单解释一下。

使用更大、更准确的预训练模型,如 EfficientNetB7 。更大意味着你将需要更大的 GPU 或更大内存的 TPU,训练将需要更长的时间。

使用 K 倍交叉验证。这是将你的数据拆分成训练集和验证集的不同方法。您将图像集合分成 K 个大小相等的部分。然后训练 K 个模型,每次都使用不同的训练和验证集。若要创建预测,请组合每个模型的预测。

使用 CutMix 进行图像放大。这是一种在训练图像之间剪切和粘贴随机补丁的新策略。它还调整图片的标签。通过这种方式,它迫使模型关注木薯叶中不太容易区分的部分。

使用 Mixup 进行图像放大。使用 Mixup,您可以使用线性插值来组合两个图像及其标签。研究表明,Mixup 提高了神经网络架构的泛化能力。

多模型预测或集合模型结合来自多个模型的预测,以提高整体性能。

这些东西大部分对我来说都是新的。但是由于我喜欢学习,我将尝试这些技术来提高我的模型的准确性。我将在下一篇文章中告诉你进展如何。

感谢你的阅读,记住永远不要停止学习!

已用资源

谭明星和郭诉乐。EfficientNet:反思卷积神经网络的模型缩放。《机器学习国际会议论文集》(ICML),2019 年。

黄高、刘庄和基利安·q·温伯格。密集连接的卷积网络。arXiv 预印本 arXiv:1608.06993,2016a。

克里热夫斯基、苏茨基弗和辛顿。用深度卷积神经网络进行 Imagenet 分类。在 NIPS,2012 年

通过 Tala 的提升建模帮助逾期借款人还款

原文:https://towardsdatascience.com/helping-late-borrowers-repay-with-uplift-modeling-at-tala-a1541aceffe4?source=collection_archive---------32-----------------------

Tala 的数据科学团队如何通过提升建模改善借款人体验和业务 KPI

图片来自塔拉

这篇文章是对我关于隆起建模力学的深入研究的后续,有一个成功的例子。在这里,我描述了我们在 Tala 的数据科学团队如何应用提升模型来帮助逾期借款人偿还贷款。Tala 提供世界上最容易获得的消费信贷产品,通过一个智能手机应用程序,立即为从未有过正式信用记录的人承保,然后发放贷款。

介绍

在机器学习可以为企业创造价值的许多方式中,提升建模是鲜为人知的一种。但是对于许多用例来说,它可能是最有效的建模技术。在任何情况下,如果企业可以针对不同的客户有选择地采取代价高昂的行动,希望影响他们的行为,那么提升建模应该是找到受该行动影响最大的客户子集的有力候选。这对于在商业策略中最大化投资回报是很重要的。

在本帖中,我将概述我们在 Tala 通过抬升建模解决的业务问题、抬升模型的基础以及我们如何构建抬升模型、如何解释抬升模型的预测、如何扩展抬升概念以提供直接的财务见解,以及在生产中监控抬升模型性能的注意事项。

Tala 的用例:逾期借款人

当借款人贷款逾期时,他们会将自己的财务健康以及向他们放贷的企业的健康置于风险之中。Tala 联系逾期借款人并鼓励他们偿还贷款的主要手段之一是通过电话。然而,这是一个昂贵的过程,必须与电话呼叫将带来的预期收入增长相平衡:如果我们打电话给借款人,他们付款的可能性有多大?

从数学上来说,我们感兴趣的是由于打电话给借款人而提高的支付概率。这被定义为如果借款人被要求偿还和如果他们没有被要求偿还的可能性的差异。

作者图片

隆起建模的前提是,它可以帮助我们确定借款人谁将有最大的还款概率增加,如果给一个电话。换句话说,那些更有说服力的人。如果我们能够确定这些借款人,我们就可以更有效地优先考虑我们的资源,以最大限度地提高借款人和 Tala 的财务健康。

关注机会

现在我们知道了隆起建模的目标,我们如何实现它呢?提升模型依赖于随机、受控的实验:我们需要一个有代表性的样本,包括所有不同类型的借款人,一个是接到电话的治疗组,另一个是没有接到电话的对照组。

图片来自塔拉

一旦我们获得了这个数据集,我们观察到治疗组的借款人还款比例明显高于对照组。这提供了证据,证明电话是“起作用的”,因为平均而言,电话有效地鼓励了所有借款人的还款。这就是所谓的平均治疗效果 (ATE)。量化 ATE 是 A/B 测试的典型结果。

然而,可能只有治疗组中的一部分借款人对我们观察到的大部分 ATE 负责。举个极端的例子,也许治疗组中一半的借款人负责整个 ATE。如果我们有办法提前确定这部分借款人,他们会更容易对治疗做出反应,那么我们就能够将我们的电话资源集中在他们身上,而不是浪费时间在那些电话对他们几乎没有影响的人身上。我们可能需要找到其他方法来吸引不响应者。确定因人而异的治疗效果的过程取决于这些人的不同特质,这意味着我们在寻找条件平均治疗效果 (CATE)。这就是机器学习和预测建模发挥作用的地方。

构建和解释提升模型

在机器学习中,我们可以通过特征描述借款人之间的差异,这些特征是特定于一个借款人的各种数量。我们设计了与借款人付款历史相关的功能,以及过去电话通话和与 Tala 应用程序交互的结果。这些特征试图描述借款人还款的意愿和能力,以及他们对与 Tala 建立和维持关系的承诺。借款人会听取并向我们学习,并给我们机会向他们学习吗?

有了上面描述的特性和建模框架,我们就可以构建我们的提升模型了。我们使用了一种叫做 S-Learner 的方法。有关这方面的详细信息,请参见我之前关于隆起建模的博文。一旦构建并测试了 S-Learner,我们就在训练集上训练一个单独的回归模型,其目标变量为提升(给予治疗和不给予治疗的预测概率的差异),并且使用相同的特征来训练 S-Learner(除了治疗标志,它被认为是 S-Learner 方法中的一个特征)。使用该回归模型的测试集 SHAP 值,我们能够深入了解哪些模型特征对隆起预测的影响最大。

虽然这里的功能名称是匿名的,但对最具预测性的功能的解释都是有意义的,因为那些表现出支付意愿、有借款经验并可能想再次借款、愿意接受电话联系的借款人是值得鼓励通过电话还款的借款人。

隆起模型的 SHAP 值,表示影响预测的前五个匿名因素。特征是基于借款人的支付和通话记录。图片作者。

设计使用和监控模型的策略

知道预测的概率上升是我们模型导向策略的第一步。然而,我们感兴趣的不仅仅是某人付款的可能性有多大,还包括由于电话推广而可能增加的付款额。为了确定这一点,我们将概率的提高与借款人所欠金额和可能支付金额的信息结合起来。这将预测的概率上升转化为对由于电话呼叫而导致的收入上升的估计,使我们能够根据给借款人打电话的价值对借款人进行排名。

通过计算实际收入增长,可以看出根据预测收入增长对借款人进行排名所代表的机会,实际收入增长是不同预测收入增长箱的治疗组和对照组之间平均收入的差异。这种分析类似于此处详述的上升十分位数图表的想法。我们为此使用了模型测试集。

收入增长十分位数图:根据预测收入增长对账户进行排序时,治疗组和对照组之间平均收入的差异。图片作者。

结果表明,预测的收入增长有效地识别了电话呼叫更有价值的客户。通过呼叫所有借款人可获得的增量收入的一半以上可以通过仅呼叫以这种方式排名的前 10%的借款人来获得,而增量收入的 90%可以通过呼叫前一半的借款人来获得。事实上,当考虑每个借款人的平均电话联系成本时,显示为绿线,很明显只有前 50%的借款人打电话是有利可图的。

考虑到使用预测收入增长来指导电话拓展的明显机会,我们部署了该模型来指导我们的战略。为了监控部署后的模型性能,我们创建了两个小组,使我们能够在预测增长的整个范围内检查电话呼叫的真实增长。我们这样做是通过给随机选择的 5%的借款人打电话,不管他们的预期增长是多少,并且不给另外的 5%打电话。基于这些测试的结果,我们能够得出结论,使用这里和我的同伴博客文章中显示的相同类型的模型评估指标,模型在生产中按预期运行。

总之,提升建模允许 Tala 将还款工作集中在最容易接受这些工作的借款人身上,从而节省时间和金钱。我希望 Tala 关于隆起建模的经验对你的工作有所帮助。

原载于 2021 年 1 月 14 日【https://tala.co】

帮助您的孩子像数据科学家一样思考

原文:https://towardsdatascience.com/helping-your-kids-think-like-data-scientists-f218e7c24631?source=collection_archive---------39-----------------------

使用这些简单的活动来促进年轻学生的数据科学思维。

数据科学的未来取决于下一代。虽然数据科学工具箱中的许多工具非常复杂,远远超出了大多数儿童的理解能力,但我们可以通过一些方式开始在当今的年轻人中巩固数据科学思维、方法和实践。这是有利的,因为它有助于儿童在早期发展批判性思维技能。然而,这样做的困难在于,许多孩子不喜欢整天看数字,更重要的是,试图灌输对数学或哲学意义上的线性回归或聚类的理解是完全不可能的。只要有一点创意,就有可能减轻教授数据科学原理的困难,我决定在下面分享一些我自己的方法。

线性回归变得简单

线性回归是一种用于模拟两个变量之间关系的技术。它既简单又复杂。简单是因为它的应用和数学公式很容易表达。复杂是因为有许多规则决定了您是否正确地应用了线性回归。

Y = a + bX

其中 a 是截距(x = 0 时 Y 的值),b 是指直线的斜率(或直线的一步中预期的变化量),X 是你的自变量(也叫“解释变量”),Y 是你的因变量(你所测量的)。用通俗的话来说,这最好描述为:“给定我们对一个特定事件的全部知识,Y 与 X 的关系是什么?”回归对于估计未来值也很有用。如果你们的关系非常好,你可以在你的已知数据之外继续建立你的生产线。虽然这种方法看似简单,但上述信息对孩子来说并不容易消化。

然而,这里有一种非定量的解释线性回归的方法,这是我自己设计的,步骤如下:

  1. 拿一张纸和三到四种不同颜色的笔、蜡笔或马克笔(如果你想增加难度,可以添加更多颜色)。
  2. 在那张纸上画一个 X 和 Y 轴(你可以把它们标成我在图 1 中的样子)。

图一。活动设置示例显示 XY 线,并指向其上的图形(图片由作者制作)。

  1. 现在,您可以要求您的数据科学学生从图形的一端到另一端绘制一条线,同时在一条线上捕捉相同颜色的大多数点(参见图 2 中的示例)。
  2. 让他们描述变化(关系)是积极的还是消极的,然后你可以让他们计算在这些点上发生了多少变化。为了好玩,你可以让他们数出不在线上的点的数量,以及每个点在图上有多远。

图二。通过点绘制的线的例子说明了我们的两个变量之间的关系(图片由作者制作)。

对于非常年轻的学习者来说,这项技术可能需要相当长的时间才能掌握正确,但这是一种有趣的学习方式。毕竟,他们仅仅是在一堆点上画线而已!为了把事情搞混,你可以让它们从直线变成曲线(曲线回归)。本练习的要点应该是识别点内的模式、准确绘制线和捕捉最多的点,以及了解不在线附近的其他点如何影响整体结果。

集群变得简单

现在来看集群。有几种聚类方法。K-means 聚类,ward 的层次凝聚聚类,基于密度的聚类方法,最近邻,等等。虽然这些方法看起来很复杂,但它们都有一个目标,那就是根据给定数据集中的相似特征对信息进行分组。我个人认为最容易教的是最近邻聚类,因为它假设附近的值比那些相距较远的值更可能相似。K-means 聚类可能是我第二喜欢教的,因为它强调根据均值的相似性进行聚类(因此 5 个组每个都有自己的“质心”或分组值,所有相似的值都放在该组中)。

这里有一个简单的活动来帮助教授最近邻聚类和 k-means 聚类。最好使用一个写字板或者一个带手写笔的电子平板,但是纸和笔也可以。

  1. 用 4 或 5 种不同的颜色在一张纸上画尽可能多的点。您应该尽量保持每种颜色的点数相同,或者分成两组,每组多一个或两个点数(例如,6 个红色点数、5 个蓝色点数、4 个绿色点数、3 个紫色点数;参见图 3)。

图 3。举例说明你如何考虑在一张纸上随机分配你的分数(图片由作者制作)。

  1. 一些颜色相同的点应该彼此靠近。
  2. 指导您的数据科学学生用相同的颜色圈出彼此距离最近的点(表示最近的邻居;图 4a),并在具有相同颜色的组周围形成更大的圆(对于 k-均值;图 4b)。

图 4。在左边(4a ),我们可以看到在最近邻聚类技术下这些点是如何绘制的。在右边(4b ),我们看到如何使用 k-means 聚类技术绘制点(图片由作者制作)。

在此活动中,您不仅让学生了解了如何识别相似且彼此接近的点,还让他们了解了如何根据这些点的共同相似性对它们进行分组。你可以通过添加更多的颜色,增加点的数量,使点更密集(这将使组之间更难区分)来混合东西。

建模变得简单

在线性回归部分,我们讨论了一点建模,但是还有更多。建模的核心是构建现实生活事件的数学表示。这可能类似于监测温度的变化。由于我们已经使用了线性回归,我们也将使用它来练习建模。

  1. 使用您在线性回归活动中所做的相同设置。
  2. 让您的数据科学学生画线后,让他们评估线的终点当前位于何处(高值或低值)。
  3. 根据他们对直线和两个变量之间关系的了解,让他们画出直线下一步应该移动的点,然后让他们朝着新的点画直线(见图 5)。

图 5。一个事件建模的例子。在这种情况下,我们看到,随着冰淇淋数量的不断增加,需要吃冰淇淋的人数也在增加(图片由作者制作)。

  1. 为了使活动更加困难,你可以使一些点更加分散。

这项活动需要在年轻时就有敏锐的批判性思维,因为它需要对 X 轴和 Y 轴之间的关系有牢固的理解,以及在给定先验信息的情况下对线下一步应该移动到哪里的即时估计。通过以更随机和分散的模式绘制点,可以增加这一练习的难度,您也可以合并变量,例如全年的温度,这将需要曲线来拟合数据。此外,通过将点放置在远离预期位置的位置,然后仍然要求一条线(例如,由于点在图表上的分散性较大,因此很难确定线应该位于何处),也可能会在此练习中引入误差。

虽然上述练习不会使个人成为数据科学专家,但它有助于在早期增强数据科学技术知识,并增强批判性思维。人类擅长识别模式,人们越早开始运用这种技能,一旦他们接触到更难的概念、术语和方法,这种技能就会越强。

赫尔辛基城市自行车:探索性数据分析

原文:https://towardsdatascience.com/helsinki-city-bikes-exploratory-data-analysis-e241ce5096db?source=collection_archive---------24-----------------------

第一部分

介绍

插图由: pch.vector 上的 Freepik

什么是赫尔辛基城市自行车?

赫尔辛基城市自行车是赫尔辛基和埃斯波大都会地区向公众提供的共享自行车。赫尔辛基城市自行车系统的主要目标是解决所有分销网络中存在的所谓的最后一英里问题。城市自行车于 2016 年作为试点项目推出,赫尔辛基只有 46 个自行车站。在受到市民欢迎后,赫尔辛基市决定逐步扩大自行车网络。在 2017 年至 2019 年期间,每年约有一百个台站加入网络。到 2019 年,自行车网络达到完整状态,2020 年仅增加 7 个站点。截至 2020 年,赫尔辛基和埃斯波共有 3510 辆自行车和 350 个站点。

自 2016 年以来,已经进行了超过 10,000,000 次乘坐。行程总距离为 25.291.523 公里。客观地说,2530 万公里是到月球距离的 65 倍。所有居民骑自行车的总时间约为 280 年零 4 个月。

为了使用城市自行车,市民购买一天、一周或从 4 月到 11 月的整个自行车季节的使用权。所有通行证包括不限次数的 30 分钟自行车骑行。额外支付 1€/小时的费用,您可以使用自行车更长时间。自行车被取走并送回位于赫尔辛基和埃斯波周围的站点。

探索性数据分析

数据集结构

基础数据集具有以下结构。

底层数据集可以在 这里 下载。

一般的游乐设施是什么样的?

自 2016 年以来,城市自行车系统有了显著增长,然而,城市自行车的使用方式没有发生实质性变化。如果我们看看过去 5 年中的个人出行,我们会发现平均乘车时间约为 13 分钟,而平均行驶距离约为 2242 米 (1.4 英里)。鉴于数据的右偏分布,平均值略有偏差,大多数行程实际上持续 4-8 分钟,距离为 1700 米(约 1 英里)。

左:2016-2020 年出行距离分布。右图:2016-2020 年间的乘坐时长分布。图片由作者提供。

正如我们在上面看到的,绝大多数游乐设施都不到 30 分钟。然而,3.2%的用户最终超过了半小时的限制。那些超过 30 分钟限制但没有超过 60 分钟限制的用户集体付费是 €261.715 自 2016 年城市自行车推出以来。

城市自行车什么时候使用?

2016 年至 2020 年间的每日自行车出行次数。图片由作者提供。

上面你可以看到自城市自行车系统推出以来的每日自行车出行次数。正如我们所见,扩大网络覆盖范围对市民出行数量有着巨大的影响。也可以看出,2020 年是自行车使用率下降的第一年。有多种可能的解释。这种下降可能是由于新冠肺炎疫情或因为城市自行车网络达到了其增长阶段的结束。

如果我们看下面的热图,我们可以看到一个很好的日常使用模式。最密集的自行车使用发生在工作日的 6:00 至 8:00 和 16:00 至 18:00。这表明自行车在工作日的开始和结束时被通勤者积极地使用。

该热图显示了 2016 年至 2020 年期间工作日和一天中的小时数。图片由作者提供。

然而,在周末,使用模式是不同的。看起来赫尔辛基斯的市民更喜欢晚一点开始周末。最活跃的时段是 15:00-17:00。有趣的是,周末午夜时分,城市自行车的使用率更高。这可能意味着在周末,当其他形式的公共交通不再可用时,城市自行车被用作替代品。

由于通勤者积极使用城市自行车,很自然地认为 Covid 疫情和向远程工作的过渡对城市自行车的使用产生了一些影响。下图显示了过去三年(2018 年至 2020 年)的自行车使用模式。

2018-2020 年自行车使用热图。图片由作者提供。

这些图表已经说明了 2020 年自行车使用模式的一些差异。除了自行车总使用量的减少,高峰时间的出行次数也减少了。

哪个站最受欢迎?

左:2016 年以来出发最受欢迎的前 20 个车站右:2016 年以来返回最受欢迎的前 20 个车站。图片由作者提供。

可以预料,并非所有的站都被同等地使用。2016 年,紧邻 Kamppi 地铁站(赫尔辛基市中心)的车站是最受欢迎的。然而,自 2017 年以来,itmerentori 已成为无可争议的使用冠军。将 itmerentori 和 nlahdenkatu 视为最受欢迎的车站可能会令人惊讶,但是,这种受欢迎程度是由它们在城市自行车网络中的位置来解释的。虽然这些车站并不在赫尔辛基的中心,但它们都聚集在自行车网络的“中心”周围。2016 年,当有不到 50 个站时,Kamppi 处于网络的结构中心。然而,随着网络向赫尔辛基北部扩展,自行车网络的中心也向北移动。因此,itmerentori 和 nlahdenkatu 站在整个网络中发挥了更“重要”的作用。

可能影响该列表的一个边界条件是给定站点中的自行车可用性。如果没有自行车可用,那么数据集将不会反映自行车的需求,而是反映自行车的可用性。itmerentori 和 nlahdenkatu 站之所以热闹,是因为它们是出发和返回的热门车站。这确保了自行车随时可用,并增加了车站的使用率。

2020 年热门始发站热图。互动版可以在 这里找到 。图片由作者提供。

另一个有趣的观察是,自行车站的受欢迎程度在一年中没有实质性的变化。这种趋势在上面的动画热图中得到了说明。

哪些旅行最受欢迎?

下表显示了前 6 个最常见的始发地-目的地对。前两行说明了城市自行车在阿尔托大学校园中的重要作用。自从阿尔托大学旁边的地铁站开放以来,城市自行车成为连接校园住宅和交通枢纽的重要交通流。

2016 年以来的热门出发地-目的地对。图片由作者提供。

下面的热图显示了 2016 年和 2020 年的始发地-目的地配对及其出现频率。如前所述,扩大城市自行车网络对整体使用模式有巨大影响。

左:【2016 年始发地-目的地热图右:【2020 年赫尔辛基城市自行车网络始发地-目的地热图。图片由作者提供。****

与芬兰国旗的任何相似之处纯属巧合。

天气会影响城市自行车的使用吗?

一个直观的假设表明,气温和城市自行车的使用之间应该有联系。下图说明了大多数游乐设施发生在气温在 10 到 21 度之间的时候。

乘坐次数与平均温度。图片由作者提供。

然而,没有足够的证据可以肯定地得出骑自行车与气温有关的结论。鉴于可能影响游乐设施的潜在因素众多,无法确定这些测量值之间的具体因果关系。例如,在赫尔辛基,气温可能很高,但可能伴随着降雨或高风速。图表中显示的趋势可能是其他外部因素的结果。不幸的是,底层数据集不包含关于其他环境因素的信息。

此外,重要的是要注意,城市自行车是从四月到十月,而不是全年。这意味着自行车的使用,一般来说,总是会发生在大致相同的温度范围内。较冷的温度将与自行车使用量通常较低的骑行季节的开始和结束相一致。另一方面,夏季和七月假期的气温将会变暖。有趣的是,在这个时间段内的所有假期中,只有https://fi.wikipedia.org/wiki/Juhannus(仲夏)对城市自行车的使用有明显的影响(如下图)。

2017–2020 年的每周乘坐次数。图片由作者提供。

结论

在这篇文章中,我们通过描述性统计的视角来观察赫尔辛基的城市自行车系统。本文仅仅触及了可以在底层数据集上执行的所有可能分析的表面。那些对自己的探索感兴趣的人可以在 Kaggle 上找到数据集。文章的第二部分 将赫尔辛基城市自行车系统作为一个复杂的交通网络进行分析。

Jupyter 笔记本

这篇文章背后的代码可以在这里找到:

  • GitHub
  • 摇摇晃晃

赫尔辛基城市自行车:网络分析

原文:https://towardsdatascience.com/helsinki-city-bikes-network-analysis-512cc7f121cd?source=collection_archive---------26-----------------------

第二部分

本文的 第一部分 从描述性统计的角度看赫尔辛基城市自行车系统。在本文中,城市自行车系统将作为一个复杂网络来分析。

介绍

在过去的几十年里,运输系统通常被作为网络来分析。这种抽象允许减少可用的信息量,并主要关注底层系统的内部结构。

左图:柯尼斯堡地理地图。右图:卡米洛·西特,现代城市规划的诞生(1986)

这个想法当然不是 数学 或者 城市规划 中的。然而,计算技术和 GIS 框架的最新进展使得图论思想在地理移动性领域的新的实际应用成为可能。

在交通运输的背景下,术语网络指的是位置系统内的路线框架,被识别为节点。路由是两个节点之间的单个链接,这两个节点是更大网络的一部分,该网络可以指有形的路由(如公路和铁路)或不太有形的路由(如空中和海上走廊)。

赫尔辛基城市自行车网络 2020。图片由作者提供。

运输网络通常表示永久性的物理轨道,如公路和铁路,或者定期服务。与集体交通(定期巴士和火车)不同,个人交通(步行、自行车共享)按需发生,在空间上更加灵活。由于这一点,共享移动系统拥有巨大的自我组织https://en.wikipedia.org/wiki/Self-organization#:~:text=Self-organization%2C also called (,control by any external agent.的潜力。需要强调的是,城市自行车网络的边缘不是预先确定的,它们是由用户生成的。于是,网络的结构** 从穿过城市的人流中浮现 居民的重复出行逐渐形成了使用模式,并形成了自行车共享网络的结构。反过来,该信息可以用于网络发展的反馈回路中。自行车需求的上升或下降可以提供对某些地区更广泛的社会、经济和地理因素的洞察。下图显示了 2020 年赫尔辛基不同地区的自行车使用情况。**

2020 年按用途划分的始发站。互动版可以在** 这里找到 。图片由作者提供。**

正如所料,赫尔辛基市中心是地理流动性最活跃的地区。然而,正如本文第一部分所指出的,赫尔辛基的地理中心和赫尔辛基自行车网络的中心并不相同。

赫尔辛基城市自行车网络的中心在哪里?

网络中心性度量

根据定义,复杂网络是高度异构的结构。这通常导致网络的某些部分比其他部分信息更丰富。例如,在社交网络中,一些人可能有大量的联系,可以比其他人更快地传播信息。因此,在社交网络分析%20that%20connect%20them.)的上下文中,代表它们的节点被认为更重要(中心)。在交通网络的背景下,人口流入量高于其他地区的城市区域可被视为中心区域。然而,给定网络的中心性可能会随着时间的推移而改变,这是底层系统增长和演变的结果。因此,中心性的定义不是绝对的,而是取决于特定的上下文和抽象的目的。考虑到这种相关性,已经提出了几种集中于节点之间不同类型关系的中心性度量。

程度中心性

节点 I 的 C D( i )度中心性

度中心性 是理解和计算最简单的中心性度量。节点的“度”是指给定节点所连接的节点的数量。在城市自行车的上下文中,这指的是用户从目标站点前往的自行车站点的数量。正如我们在下图中看到的,位于赫尔辛基市中心的车站有更多的连接。越靠近网络的外围,节点的度数逐渐减小。

****

图片由作者提供。

赫尔辛基城市自行车网络中一个节点的平均度162 。这意味着一个自行车站平均连接到 162 个不同的站点。中心度最高的站是:

**Haukilahdenkatu:**    312 connections
**Paciuksenkaari**:     272 connections
**Huopalahdentie**:     267 connections 
**Laajalahden aukio**:  262 connections
**Munkkiniemen aukio**: 262 connections
**Töölöntulli**:        260 connections
**Tilkanvierto**:       259 connections
**Paciuksenkatu**:      258 connections
**Pasilan asema**:      258 connections 
**Esterinportti**:      256 connections 

Haukilahdenkatu 站在这个名单的首位,这一事实表明来自不同地区的大量市民定期往返于这个车站。

图片由作者提供。

这可能意味着该车站要么靠近大型交通枢纽,要么靠近重要的兴趣点。快速谷歌搜索会发现它位于一个大型教育机构和一个劳动改造中心的街对面。这解释了旅行的规律性和来自不同郊区的人口流入。

中间中心性

其中 gjk 是连接单元 jk 的测地线的数目, gjk ( i )是单元 i 占据中间位置的那些测地线的数目。

中间中心性捕获了给定节点有多少处于其他节点之间。该度量计算网络中所有节点之间的最短路径,并根据经过目标节点的最短路径数为每个节点分配一个度量。下图通过中间中心性展示了城市自行车站点。

图片由作者提供。

具有最高介数中心性的节点代表 Lehtisaarentie 站。这是地理限制影响空间网络结构的一个典型例子。该站位于 Lehtisaari 岛上,将阿尔托大学校园与 Munkkiniemi 和赫尔辛基连接起来。由于赫尔辛基群岛的特殊性,从一个城市到另一个城市的交通流量主要通过位于两者之间的岛桥系统。这使得 Lehtisaari 岛和 Lautasarri 岛成为连接埃斯波市和赫尔辛基的重要交通枢纽。

接近中心性

接近中心性是一种检测能够在网络中有效分配流的节点的方法。接近中心性计算为其所有 测地线距离 的归一化平均值。在城市自行车的上下文中,具有高接近中心性的节点将指示可能充当网络内的多功能中间站的站。

图片由作者提供。

如上图所示,大量车站直接连接到 Haukilahdenkatu 车站。这导致 Haukilahdenkatu 站在网络中具有最高的接近中心度。具有高接近中心性的其他节点位于托洛和帕西拉地区。对于网络优化,特别是对于较大的网络,接近中心性可能是有趣的度量。在更大的自行车共享网络中,用户可能会在中间自行车站停车,以避免额外的费用。然而,正如我们在本文前面所看到的,长途旅行在赫尔辛基并不常见。

特征向量中心性和 PageRank

特征向量中心性度量节点在网络中的重要性,同时考虑其邻居的重要性。与到低得分节点的同等连接相比,到高得分特征向量中心性节点的连接对得分的贡献更大。换句话说,如果具有大量连接的节点的所有连接都是低得分节点,则该节点可能具有低特征向量得分。特征向量中心性的一个流行变体是 Google 的 PageRank 。从本质上讲,PageRank 是归一化特征向量中心性与随机跳跃 s 相结合的变体。因此,Pagerank 产生与特征向量相当的结果也就不足为奇了(下图)。使用这种方法,中央火车站、Pasila、Lehtisaarentie 和 Haukilahdenkatu 等车站将作为网络的中心节点出现。

****

图片由作者提供。

特征向量和 PageRank 在城市环境中的应用是一个持续争论的主题。有人提出,这些在城市环境中应用的指标往往会导致误导性的结果,因为它们忽略了许多可能有助于城市内节点重要性的城市品质。虽然这些限制在服务路线是预先确定的集体运输系统中可能是一个问题,但这肯定不是个体运输的情况。如前所述,个人交通网络的结构是由用户生成的,因此其中已经嵌入了一些关于城市质量的信息。事实上,用户有选择权,选择走一条路而不是另一条路,这就产生了一种琐碎的投票机制,对城市的不同区域进行评级。因此,在这种网络中,对网络结构的研究也是对用户行为及其更好的城市品质的研究。此外,单个交通网络中的特征向量中心性不仅可以突出显示重要的单个节点,还可以突出显示城市中地理位置重要的区域。这是可能的,因为它不仅承认单个站的重要性,而且承认与其相邻的站的重要性。特征向量中心性表明,城市自行车站点(节点)的重要性与其说来自它们的固有属性(位置、站点大小),不如说来自它们与网络中其他节点 的 关系。中心站和与其相邻的节点一起形成小的活动飞地。复杂网络环境中这种节点分组的识别通常被称为社区检测。

社区检测

网络中的社区指的是内部紧密连接的节点组。社区发现通常是理解复杂网络结构的关键过程。在城市自行车网络的情况下,社区检测可以帮助更好地了解自行车使用模式,并确定适当的定价模型。有许多算法可用于社区检测。

组合方法

大多数现有的社区检测策略迭代地执行以下操作之一:合并两个小社区(凝聚的),将一个大社区分成两个(分裂的),在两个不同的社区之间移动节点。在 麻省理工学院明智城市实验室 开发的 组合 算法将所有三种策略组合成一个序列。创建初始单个社区后,对于每个源社区,计算所有源节点的最佳可能重新分布,然后应用最佳分组。这些步骤反复重复,直到达到给定的适合度标准。下图说明了应用于赫尔辛基城市自行车网络的组合方法。

应用于赫尔辛基城市自行车网络的社区检测组合方法。图片由作者提供。

这一分组揭示了两个截然不同的社区,它们大致按照现有的市政区划分开。这可能不是非常有用的信息,因为这种划分仅仅通过看地图就可以假定。基于本文的第一部分,直观的理解表明,自行车更有可能在短距离的城市内使用。因此,如果存在其他社区,它们应该在更局部的范围内被发现。

卢万法

由于先前的社区检测方法没有产生深刻的结果,我们可以应用专门关注网络的 模块性 的不同方法。 Louvain 社区检测由于其漂亮的简单性和计算效率而成为很好的候选。它有效地处理了所有社区检测任务中存在的图 的 最大割的 NP 完全可计算性问题。将 Louvain 方法应用于赫尔辛基城市自行车网络揭示了四个不同的社区。

卢万社区检测方法在赫尔辛基城市自行车网络中的应用。图片由作者提供。

这意味着这四个社区内的自行车使用率高于这四个社区之间的自行车使用率。具有高介数中心性的节点通常是社区可能被分成模块的地方。如果我们回到我们的中间中心图,这种关系将变得更加明显。社区的边界大致通过具有高介数中心性的节点。此外,考虑到赫尔辛基群岛的地理特征,这种划分并不令人惊讶。大块陆地和它们被大片水域分割开来,对群落的形成有重大影响。必须强调的是,所有交通网络都是空间网络,其结构和演变与物理限制密切相关。一个有趣的发现是,Leppavara 地区尽管是 Espoo 市的一部分,但它与 Munkiniemi 和 pitjnmaki 的联系比与 Otniemi 或 Tapiola 地区的联系更紧密。类似的趋势也可以在索宁附近的一些站点看到,这些站点与 Herttoniemi 区域的连接更加紧密。

****流体群落

流体群落算法是一种基于在非均匀环境中引入多种流体的思想的群落检测算法,在非均匀环境中,流体将在环境拓扑的影响下膨胀并相互推动,直到达到稳定状态。该算法执行以下操作。首先,它定义了图中随机节点的每个起始社区。然后,该算法以随机顺序在所有节点上迭代,基于每个节点自己的社区及其邻居的社区来更新每个节点的社区。这个过程反复执行,直到收敛。

应用于赫尔辛基城市自行车网络的社区检测的流体方法。图片由作者提供。

我们可以看到,流体群落检测方法确认了用 Louvain 方法识别的群落,并识别了一个额外的群落。

  • Eastern Espoo(Magenta 社区)是一个独特的社区,受地理条件的限制,沿着地铁线向西延伸。
  • leppvaara、pitjanmaki、Munkiniemi 和 Etelä Haaga(绿色社区)形成了另一个自行车社区,尽管市政分区将这些地区分开。
  • 瓦利拉、Kapyla 和 Oulunkyl 地区形成了另一个群体(粉色社区),通过中央公园与绿色社区隔开。这个社区沿着赫尔辛基北部的铁路延伸。
  • 赫尔辛基南部(蓝色社区)包括赫尔辛基的地理中心和主要车站,如 Kammpi、中央火车站,并向南部海岸线延伸。
  • 与此同时,Herttoniemi 位于另一个飞地(黄色社区)的中心,该飞地沿着地铁线从 Sornainen 延伸到 Vuosaari。

结论

在文章的这一部分,赫尔辛基城市自行车网络作为一个复杂网络进行了简要分析。对网络应用了多种中心性测量,并确定了重要的中心。树社区检测算法揭示了网络中节点的不同可能分组。文章的下一部分将着眼于如何应用机器学习方法来进一步增强对网络内关系的理解。

Jupyter 笔记本

这篇文章背后的代码可以在这里找到:

**https://github.com/Geometrein/helsinki-city-bikes

  • https://www.kaggle.com/geometrein/helsinki-city-bike-network-analysis

参考

  • 复杂网络中高质量社区发现的通用优化技术 (Combo 方法)
  • Python 的组合
  • Fluid Communities:一个有竞争力的、可扩展的、多样化的社区检测算法。**

这就是 SQLAlchemy 如此受欢迎的原因

原文:https://towardsdatascience.com/here-is-the-reason-why-sqlalchemy-is-so-popular-43b489d3fb00?source=collection_archive---------8-----------------------

将 flask 应用程序直接连接到 postgresql 数据库的权威指南,它将帮助您理解为什么 SQLAlchemy 是将 python 应用程序连接到关系数据库的首选方式

卡斯帕·卡米尔·鲁宾在 Unsplash 上的照片

介绍

有两种方法可以将 python 应用程序连接到关系数据库:低级方法和高级方法。低级方法包括在本地机器上安装和设置关系数据库管理系统,并编写实际的 SQL 命令来执行数据库操作。另一种方法是使用对象关系映射器(简称 ORM)。ORM 是一个数据库抽象层,是您和数据库引擎之间的中介。它允许您定义常规的 Python 对象和方法,并将其翻译成低级 SQL 数据库指令。SQLAlchemy 是 python 中处理关系数据库的 ORM 选择。

SQLAlchemy 如此受欢迎的原因是因为它实现起来非常简单,可以帮助您更快地开发代码,并且不需要 SQL 知识就可以开始。这也是为什么网上几乎所有的编程教程和课程都在教授高级方法。大多数执业软件工程师似乎也更喜欢使用 SQLAlchemy。

本文是一篇教程,介绍如何在不使用 SQLAlchemy 的情况下将一个简单的 flask 应用程序连接到 postgresql 数据库。是的,你没看错,所以我来告诉你:一旦你理解了如何使用数据库这种低级方法,你不仅会对 SQLAlchemy 有更深的理解,而且会真正理解在你使用它时幕后发生了什么!

我们的研究将涉及构建一个 web 应用程序,它通过一个表单接收用户输入,并将其存储在 postgresql 数据库中。我们开始吧!

步骤 1:项目设置

创建一个项目目录,在终端中导航到该目录,然后为项目创建一个虚拟环境。激活虚拟环境后,安装 flask 和 psycopg2。psycopg2 是 python 中最流行的 PostgreSQL 适配器。它允许您直接从 python 代码访问本地机器上的 postgresql 数据库。确保将您在虚拟环境中安装的所有 python 包写入 requirements.txt 文件。

$ py -3 -m venv venv
$ venv/Scripts/activate
$ pip install flask
$ pip install psycopg2
$ pip freeze > requirements.txt

你也可以继续创建一个名为 app.py 的空 python 脚本,一个名为 templates 的文件夹,以及一个名为index.html的空白 html 文档。项目文件夹的结构应该如下所示:

|- app.py
|- requirements.txt
|- templates
   -index.html
|- env

步骤 2:创建数据库

您需要在本地机器上安装 postgres。你可以从 https://www.postgresql.org/download/.下载适合你操作系统的版本

安装完成后,运行 postgres 的 SQL Shell(psql)并进入数据库服务器。如果您使用默认设置安装 postgres,您可以将所有字段留空(每次只需按 enter 键,以便选择器移动到下一个字段),并且只需输入您选择的密码。当 SQL Shell 终端在前面加上数据库名称(默认情况下应该是默认的 postgresql 数据库,postgres=#)时,您将知道您在数据库服务器中。

SQL Shell (psql)截图(作者自己的)。

如果你愿意,你可以使用默认的“postgres”数据库作为你项目的数据库,但是我更喜欢创建我自己的数据库。要在服务器上创建数据库,请在 SQL shell 中运行下面显示的命令。这个命令指示服务器创建一个名为 python_app 的数据库。确保不要忘记命令末尾的分号,否则命令不会执行。

postgres=# CREATE DATABASE python_app;

服务器将用一条确认消息作出响应,表明它创建了一个数据库。要查看服务器上的所有数据库,请运行下面显示的命令。您应该看到 python_app 被列为存储在服务器上的数据库之一。

postgres=#\l

这就是我们将在 SQL Shell 中完成的所有工作。其余的数据库操作(创建表和添加条目等)将在我们的 python 应用程序中执行。

步骤 3:从 python 应用程序连接到数据库,并创建一个用户表

在您的 app.py 文件中,导入 psycopg2 模块。您还希望从 psycopg2 导入 Error 对象,以便可以直接在 python 代码中处理任何数据库错误。

psycopg2 模块公开了一个 connect()方法,该方法将用于在 SQL Shell 中登录 postgres 数据库服务器的参数的键值对作为参数:主机、数据库、端口、用户、密码。connect()方法的输出是一个 connection 对象,它允许您创建到 postgres 数据库的连接。一旦建立了连接,您需要某种方式来告诉数据库要执行哪些 SQL 命令。这就是光标对象的用武之地。connection 对象公开了一个 cursor()方法,该方法可用于创建一个 cursor 对象,该对象的任务是执行您希望数据库执行的任何 SQL 命令。

使用 python 代码连接到 postgres 数据库的工作流如下:

  1. 创建连接对象
  2. 使用 connection 对象创建一个游标对象
  3. 使用游标对象执行 SQL 命令
  4. 关闭游标对象和数据库连接

由于此工作流涉及到与外部系统的连接,因此一个好的做法是在 try-catch-finally 块中实现此工作流,以便您可以处理由于连接问题或代码中的错误而引起的任何异常。

在数据库上执行 SQL 命令是一个两步过程:首先通过 cursor 对象的 execute()方法将查询字符串传递给它。然后,您必须使用连接对象的 commit()方法将 SQL 命令提交给数据库,以使更改反映到数据库中。您可以将“cursor.execute()”理解为“git add x ”,将“connection.commit()”理解为“git push”。

我发现首先将查询字符串定义为一个变量,然后将其作为一个参数传递给 execute 方法更容易,但是如果您愿意,也可以将完整的查询作为一个参数来编写。

在数据库中创建一个用户表的代码如下所示。要告诉数据库创建一个表,您可以使用命令关键字“CREATE TABLE ”,后跟表的名称,然后在参数中输入组成表的列的名称。每一列都有定义其预期数据类型和约束的关键字。

如果代码运行成功,postgres 服务器上的 python_app 数据库现在应该包含一个 users 表。要确认这一点,您可以打开 SQL shell 并访问 python_app 数据库,然后运行\dt命令来查看该数据库中的所有表。如果您想查看您定义的所有列及其约束,您可以运行\d users命令。同样,如果出于某种原因,你想从数据库中删除这个表,你可以运行DROP TABLE users;命令。最后,如果您发现自己在默认的 postgres 数据库中,您可以通过运行`\c python_app``命令轻松切换到 python_app 数据库。

SQL Shell 的屏幕截图,确认已经创建了 users 表(作者自己的)。

步骤 4:创建一个简单的 flask 应用程序来呈现注册 web 表单

首先实例化一个 flask 应用程序对象。接下来,定义一个路由和视图函数,该函数将处理对 webform 的 url”的请求。当用户提交表单时,这个视图函数应该在收到 GET 请求时呈现表单,在收到 POST 请求时处理表单。处理部分暂时留为空白,因为我们将在下一步中定义它。

您的 app.py 文件代码应该如下所示:

您的index.html文件应该包含以下代码:

在终端中运行命令$ python app.py以调试模式打开 flask development server。在您的浏览器中访问网址[http://127.0.0.1:5000/](http://127.0.0.1:5000/)应该会打开注册表。

报名表截图(作者本人)

我们现在有了一个在浏览器中呈现的表单,它允许用户向服务器提交输入,但是在用户按下 submit 按钮后什么也没有发生。让我们改变这一点。

步骤 5:将用户输入存储在数据库中

首先定义一个名为“add_new_user”的函数,它接收一组用户数据(姓名、电子邮件、散列密码)并将其写入数据库。

然后修改视图函数,以便当接收到“POST”请求时,它调用“add_new_user”函数,以便将数据保存到数据库中。

当您填写注册表单并按 submit 时,该信息应该被写入您本地机器上的 postgres 数据库!为了确认这一点,打开 SQL shell 并访问 python_app 数据库。要查看给定数据库表中的数据,您需要运行查询。因为我们想要查看存储在 users 表中的所有数据,所以我们将运行SELECT * FROM users;

您应该看到您在表单中输入的详细信息被捕获为 users 表中的一个新条目。

数据库中新条目的截图(作者自己的)

完整代码

为了方便起见,完整的 app.py 代码如下所示:

与 SQLAlchemy 的比较

这是使用 SQLAlchemy 的相同应用程序的外观:

结论

现在你知道了。一个简单的 flask 应用程序,它直接连接到 postgres 数据库来存储用户信息。如您所见,使用这种方法写入数据库是一个非常繁琐的过程。尽管非常可行,但它并不十分 pythonic 化。

SQLAlchemy 允许您继续以您习惯的方式编写代码,即使是在使用数据库时。您定义了一个表示特定实体类型的类,并直接映射到数据库中的一个表。您定义的所有类属性都映射到表中的列,然后该类的任何实例都作为表中的新条目存储在数据库中。使用 SQLAlchemy 会产生更简单、更清晰的代码,编写起来会更快。现在您知道为什么 SQLAlchemy 是 python 中处理数据库的实际方式了吧!

以下是 OpenAI Codex 将如何革新编程(和世界)

原文:https://towardsdatascience.com/heres-how-openai-codex-will-revolutionize-programming-and-the-world-e8432aafc5f7?source=collection_archive---------4-----------------------

观点,人工智能|新闻

“Codex 接近于我们大多数人真正希望从计算机中获得的东西——我们说我们想要什么,他们就做什么。”—山姆·奥特曼

由布鲁克·卡吉尔在 Unsplash 拍摄的照片

直到现在,如果我们想与计算机交流,我们必须学习它的语言。我们必须适应它。从现在开始,计算机将适应我们

OpenAI 又做到了。去年 7 月,他们发布了同类产品中的首款 GPT-3 。这个人工智能系统展现了前所未有的语言能力。模仿莎士比亚的诗歌天才,用李尔·韦恩的风格写一首关于哈利波特的说唱歌曲,或者写一些生产力文章,这些都是 GPT 3 的能力。

当时,GPT-3 是有史以来最大的神经网络。对于 OpenAI 和世界其他地方来说,考虑到其他人迅速效仿他们的例子,很明显,大型预训练语言模型是人工智能对人类语言秘密的答案。

然而,GPT 3 号拥有一些甚至连 OpenAI 的研究人员都没有想到的能力。沙里夫·沙米姆是第一批注意到 GPT-3 编码技巧的人之一。他成功地让系统构建了一个生成器,由为他编写代码。世界正处于我们这个时代最重要的人工智能革命之一的边缘。

上个月,OpenAI 与微软和 GitHub 合作,推出了 GitHub Copilot ,这是一个人工智能对程序员,旨在帮助开发人员完成枯燥的日常任务。阅读文档?副驾驶会帮你做的。编写单元测试?副驾驶会帮你做的。这个系统就像一个超级强大的自动完成功能。它是由 OpenAI 的最新明星:Codex 推动的。

GPT 3 的弟弟 Codex 是另一种语言模型。但是,法典委员会不是像 GPT-3 那样的万金油,而是大师。编码大师。它精通数十种编程语言,可以理解自然语言,并解释它来创建计算机可以理解的明确命令。

昨天,OpenAI 通过一个新的 API 发布了新版本的 Codex(我们可以通过在一个等待列表上签名来访问它)。他们还创造了一个新的挑战,在这个挑战中,人们将与 Codex 一起编码(你可以在这里注册)。除此之外,两位知名 OpenAI 研究人员 Greg Brockman 和 Ilya Sutskever 进行了一次现场演示,展示了 Codex 的能力,并暗示了它目前的潜力以及未来的前景。

在这篇文章中,我将回顾 OpenAI 在演示中展示的令人印象深刻的 Codex 技能集示例。最后,我将谈谈我对这项技术的影响以及它如何重塑未来的想法。

为什么食品法典委员会不仅仅是另一个 GPT-3

GPT 3 号是先驱。当它问世时,大多数人从未听说过语言模型、Transformer 架构、无监督学习或预训练技术。它向世界展示了人工智能系统的语言能力。它成为了一个人工智能名人,非常像 IBM Watson,或者在它之前的 AlphaZero。

但是在它的哥哥的阴影下写法典是不公平的。Codex 本身就是一个人工智能超级明星。这不仅仅是 GPT-3 在数量上的改进。Codex 对我们世界的影响更接近于 iPhone 在 2007 年的表现,而不是 AlphaZero 在 2017 年的表现。我们的生活方式与前 iPhone 时代截然不同,Codex 承诺以一种可以媲美的方式改变世界。

GPT 3 号的主要缺点之一是内存不足。上下文窗口——当您与它交互时,它可以访问的以前的信息量——很小,导致系统提交错误。它会在长篇论文中对其论点进行分歧,进入无休止的循环,或提出不一致的论点。Codex 通过增加内存存储解决了这个问题——从 4KB 增加到 14KB,是 GPT-3 的 3 倍多。这使它能够更好、更广泛地理解手头的任务。

GPT-3,令人印象深刻,生活在一个虚拟的世界里,永远被限制在不可感知的 1 和 0 的现实的边界内。正如 OpenAI 的首席技术官 Greg Brockman 所说,“通过读者的思想”,GPT 3 号只能以间接的方式影响世界。相比之下,Codex 可以通过从英语提示中创建命令来让计算机做一些事情,从而直接影响世界。法典委员会可以采取行动,在现实世界中产生(我希望是有益的)后果。

“Codex 精通十几种编程语言,现在可以解释自然语言中的简单命令,并代表用户执行它们——这使得为现有应用程序建立自然语言界面成为可能。”

食典委能做什么的 3 个例子——重点

看了现场演示后,我只能说 Codex 看起来令人印象深刻。不是因为它可以用几种语言编写代码,也不是因为它做得相当好。而是因为它对英语提示的推断可以被定性为深刻、细致、有创造性和精确——尽管我们永远不应该忘记它不能像我们一样理解语言。

看着 Codex 解释自然语言命令让我惊讶了好几次。模棱两可的命令,非正式的语言,甚至隐喻。Codex 克服了这些障碍,用一个绰绰有余的 JavaScript 实现了它的目标。它只是简单地将一个英文提示——类似于传统程序中的注释——作为输入,然后编写代码并将其发送到计算机,计算机在屏幕上显示输出。

以下是三个例子的精选(来自的演示和的博客文章)和我的印象。

1.你好世界

他们想展示基本功能,所以除了“hello world”之外,没有其他方法可以开始演示输入以粗体显示,输出以常规字体显示。

**Say Hello World.**
Hello World**Now say it with feeling!**
Hello World!!!**Even louder please.**
HELLO WORLD!!!

我们首先注意到的是模型可以自我引用。它可以在内存中(在同一会话中)存储以前的命令,并充分使用它们。它理解“它”指的是“Hello World”,这需要对语法和上下文有一定的理解。最后一个提示更加复杂,因为它有一些省略号。一个独立的“请大声点”命令没有任何意义。在实践中,这就好像我们在与法典进行对话,它可以记住并在未来使用。

然后,他们想“向全世界传播这个信息”,所以他们要求 Codex 创建一个网页,然后用一个服务器来托管这个网页。他们要求观众在 openai.com/c 订阅,参加演示,这样法典委员会就可以给我们发送一个“你好,世界”的信息而且,为了让邮件更有趣,他们还添加了比特币的价格。为了发送这封邮件,他们使用了 Mailchimp API——Codex 通过阅读中间的两个句子就学会了使用它。

**Look up the current Bitcoin price, and save it to a variable.****Here's a new method you can use.
codex_chimp.send(subject, body)-> sends Mailchimp email blast****Now send everyone an email, telling them (a) hello world and (b) the current Bitcoin.**

几秒钟后,我收到了这封电子邮件。太神奇了。

OpenAI Codex 发给我的电子邮件

2.创建游戏

对于这个例子,他们决定编写一个更大、更复杂的程序。他们没有用一行命令来测试 Codex,而是创建了一个游戏:主角是一个人,他必须通过在屏幕上左右移动来躲避落下的巨石。首先,他们导入一个人的图像,调整大小以适应屏幕,并将其放在屏幕的底部。

他们想让这个人用键左右移动,所以他们提示 Codex:“现在用左右箭头键控制它。”Codex 如何正确解释这个命令?“使之可控”是什么意思?这是一种非常模糊的方式来表达“当按下左/右键时,向左/右移动 X 个像素。”

Codex 正确地解释了一个相当模糊的命令——open ai demo(已编辑)

不过,Codex 设法解释了指令,并生成了代码,以便在按键时将图像向左和向右移动 10 个像素。处理像这样的细微订单是食品法典委员会最显著的能力之一。如何编写 JavaScript 代码是不是很多人都有的技能,但任何人都知道用键左右移动人意味着什么。法典缩小了我们的欲望——我们甚至经常无法用自然语言精确表达——和我们的期望之间的差距。

此外,系统必须持有正在进行的事情的概念,以遵循指令。我们可以使用屏幕来帮助理解正在发生的事情,但是模型只能访问以前的代码。

然后,他们包括一个人必须躲避的巨石的图像。然而,由于它太大了,他们要求食品法典委员会“把它变小”系统不仅要理解“小”的含义,还要对这个形容词的相对性质有一个相当好的理解。一只蚂蚁对我们来说很小,但对一个原子来说却不小。房子对地球来说很小,但对我们来说不是。然而,对于手头的任务,法典委员会将巨石转换成了合理的大小。

Codex 改变了巨石的大小,使其相对较小——open ai 演示

最后,在调整了巨石的大小后,他们希望它从空中落下,并在击中屏幕底部后出现在随机位置。他们要求食品法典委员会“将它的位置设置在屏幕的顶部,一个随机的水平位置。现在让它从天而降,缠绕。”这将巨石的图像向下发送,直到它到达底部,然后再次出现在顶部。

注意“从天上掉下来”这句话是一个比喻。没有天空,也没有真正的坠落。Codex 必须明白“下落”意味着图像在特定方向上(向下)不断移动。它必须明白“天空”指的是屏幕的顶部。

3.与您的电脑交谈

为了进一步强调 Codex 的潜力,他们决定使用一个真实世界的例子。在一天结束时,大多数人不知道如何编程,或者甚至不关心人工智能系统可以帮助他们做到这一点。但是,正如我在开始时所说的,Codex 的承诺并不局限于人工智能/技术世界。codex——及其未来的继任者——将改变我们与计算机的互动方式。

在这个例子中,他们使用 JavaScript Microsoft Word API 来允许 Codex 对 Word 文档进行修改。最重要的是,他们包括一个语音识别系统。

想象一下:你对着电脑说话,语音系统识别你的声音并将其转换成文本。文本被发送到 Codex——它已经知道如何使用 Microsoft API——它将命令转换成 JavaScript 代码,并对文档执行您想要的操作。

Codex 通过语音命令在 Microsoft Word 文档中进行更改— OpenAI 演示(已编辑)

Codex 学习如何利用 API 的简单性是另一大优势。编程世界正在变得“API 化”,所以随着时间的推移,这些系统将变得更加有用。

“技术发展到足够好还需要很长时间,但最终我们可能会忘记计算机的其他用途。随着更多的事情变得 API 化,编写代码的 AI 系统可以轻松地让世界上发生很多事情。”—山姆·奥特曼

想象一下在一个可编程的世界里,法典能做什么。自从计算机科学开始以来,编程语言已经变得越来越高级。法典是人类和计算机语言之间缺失的一环。我们将能够表达一个想法,计算机将理解我们的意思,没有不确定性。任何人都能够以一种对我们来说很自然的方式与计算机交流。

法典是 J.A.R.V.I.S .的原始版本。

“你在这里看到的是未来的味道。随着神经网络在将指令转化为正确的 API 代码方面变得越来越擅长,只要告诉它做什么,就有可能用你的软件做越来越复杂的事情。”——伊利亚·苏茨科夫

关于法典的思考

改善人机交流

从打卡到 Python,人机交流的历史从来没有偏袒过我们。我们总是不得不牺牲商品来适应机器。由于这个原因,与计算机通信工作密切相关的人被认为是高技能、高价值的工作者。即使在今天,当编程被认为是一项必须知道的技能时,大多数人也不知道如何创建程序来让计算机做事情。

然而,由于像 Codex 这样的系统,这种情况在未来几年可能会改变。他们可能不会取代程序员,但肯定会成为一种催化剂,使外行人能够进入编程世界,并与我们的朋友计算机发展健康的关系。

高度可解释性

对神经网络的一个合理的批评是它们缺乏责任性和可解释性。这些系统做了惊人的事情,但也有灾难性的失败。失败本身不是问题。主要问题是神经网络是黑箱。无论什么进去,都留在里面。我们没有办法偷看一眼,更好地了解正在发生的事情。调试极其困难。

在这里,法典与 GPT-3 形成对比。这两个系统都被训练成黑盒,但在测试时,Codex 让我们看到它根据我们的提示编写的代码。我们不仅仅是从计算机中得到输出,还有 Codex 解释了什么。它允许我们检查代码,删除代码,或者在必要时让系统重写代码。这一点对开发者来说很关键。没有一个专业程序员会使用代码隐藏的代码生成系统。

消除编程中枯燥的一面

Greg Brockman 谈到了编程的两个方面。首先,你需要明白你要解决的问题,以及如何把它分成更小的块。然后,您需要将这些片段映射到现有的代码中。正如布罗克曼在博文中写道,“后一种活动可能是编程中最没有乐趣的部分(也是入门门槛最高的部分),也是 OpenAI Codex 最擅长的地方。”

Codex 并不意味着让程序员离开他们的工作,而是减少他们必须做的无聊任务,让他们专注于他们工作中需要更高水平认知努力的那些方面。将问题改编成计算机能理解的语法是很无聊的。面对一个看似无法解决的问题,一点一点地理解它,并朝着解决方案迈出一小步,这就是编程的乐趣所在。

【抄本】用起来真的很好玩,给我带回了早期编程的快乐。”—山姆·奥特曼

我们日常生活的彻底改变

山姆·奥特曼说过这项技术应用在尿布上。但这是未来的第一个暗示,似乎有可能的是,法典及其继任者将横向改变我们的生活方式。一件事是彻底改革人工智能。另一件非常不同的事情是彻底改变世界,让我们每个人每天做的小事都发生改变。

Codex 不仅仅是发生在人工智能中的事情,世界上大部分人甚至不会注意到。如果成功的话,它将最终改变我们与计算机的互动方式。就像 iPhone 彻底改变了我们与手机的交互方式一样。

订阅我的免费每周简讯 明日之心 获取更多关于人工智能的内容、新闻、观点和见解!

您也可以在这里 成为中等会员 直接支持我的工作,获得无限权限!😃

推荐阅读

[## GPT-3 —全面概述

towardsdatascience.com](/gpt-3-a-complete-overview-190232eb25fd)

以下是如何在数据块中显示 HTML

原文:https://towardsdatascience.com/heres-how-to-display-html-in-databricks-c36d9cb47607?source=collection_archive---------20-----------------------

阿列克谢·图伦科夫在 Unsplash 上的照片

以及它如何增强你的分析

当我在一个 Python/R 项目上工作并希望交付输出时,我希望它非常闪亮。然而,有时分析的交付支持将是笔记本本身,或者是出于时间限制,或者是为了方便。

我一直认为我必须使用静态降价和一些图表来说明我的结果。但是,如果你像我一样使用数据块,有一个简单的解决方案,DisplayHTML 函数。这个函数将允许你在笔记本上显示比简单的代码行和图形更多的东西。

对于那些不知道它的人来说,Databricks 是一个统一的数据和分析平台,由 Apache Spark 的创始人创建。免责声明,我与这家公司没有任何关系,我只是为他们的产品工作。

在这篇文章中,我将详细说明使用这个功能可以显示什么,并给出几个例子。

你可以随时参考 Databricks 可视化文档来获得基础知识。

displayHTML 的第一个也是最常见的用途是显示文本。指出指导方针、你的结果的摘录或引导读者通过你的发现可能是有用的。

要做到这一点,您可能已经猜到了函数的名称,您只需要使用众所周知的 HTML 语言。我们将在下一部分看到你需要的最有用的 HTML 标签。

HTML 基本标签

1。标题和段落

使用标题将你的文本分成带有标题和副标题的小节。这将使你看起来像一个真正的文本,而不仅仅是一连串的句子。

标题的标签是,xxx 是一个数字,数字越小,文本越大。

displayHTML("""
<h1>This is heading 1</h1>
<h2>This is heading 2</h2>
<h3>This is heading 3</h3>
""")

查询输出。作者截图

HTML 标签

允许你写不同的段落

displayHTML("""
<p>Write in one paragraph.</p>
<p>And in another paragraph.</p>
""")

查询输出。作者截图

2。内嵌标签

你也可以使用内嵌标签,如粗体、斜体和其他标签。

displayHTML("""
<b> Bold </b> 
<i> Italic </i>
<mark> Marked text </mark> 
<del> Deleted text </del> 
<ins> Inserted text </ins> 
<sub> Subscript text </sub> 
<sup> Superscript text </sup>
""")

查询输出。作者截图

3。列表

当然,您可以使用

  • 标签在列表中显示项目,如下所示:
displayHTML("""<p>If you want to display a list</p>
<ul>
  <li> You </li>
  <li> can </li>
  <li> do </li>
  <li> it </li>
</ul>
""")

查询输出。作者截图

4.颜色;色彩;色调

使用段落和样式标签以几种不同的颜色显示文本。

displayHTML("""<p style=”color:red”>Let’s try a color</p>
<p style=”color:blue”>and another one.</p>""")

查询输出。作者截图

5.外部资源

你不必局限于纯文本,因为你也可以引用外部资源,可以是纯 URL,甚至是图片。

正如在官方文档中提到的,如果你引用一个外部资源,你应该总是使用 https://而不是 http://来避免呈现错误。

displayHTML("""
<p> This is a <a href=”https://www.medium.com"> link</a> to medium.com </p>
""")

查询输出。作者截图

6.形象

您还可以显示图像,但前提是这些图像存储在与数据块相连的数据库中,例如之前分析的图形保存为 jpg 格式。

displayHTML("""<img src =’files/image.jpg/’>""")

奖励:表情符号

最后但同样重要的是,如果你想让你的测试更精彩一点,可以添加表情符号:)

作者图片

查询输出。作者截图

If 语句和参数

现在我们已经完成了基本命令,不要忘记我们仍然处于 python 环境中,这意味着我们可以有条件地显示文本。

假设您想要显示一个基于计算结果的建议,那么您可以使用一个 if 语句并向 displayHTML 函数传递一个参数。在 Python 中,可以使用{}和将变量传递给函数。最后格式化。

以下函数允许您根据结果值显示不同的消息。

if my_result>50:
  sentence = "the result passed the condition with a value of"
  +   str(my_result)else:
  sentence = "Unfortunately a result of <b>" + str(my_result) +   
  "</b>is too low"displayHTML( """{} """.format(sentence))

查询输出。作者截图

动态内容

能够以闪亮的方式编写测试是很好的,但是如果我们想要一些更动态的东西呢?幸运的是,displayHTML 并不局限于您可以使用来自 D3.js 的 D3 可视化来创建数据或模型结果的动态图形。

D3.js 是一个 JavaScript 库,用于在 web 浏览器中生成动态的、交互式的数据可视化

下面是一个使用 python 库 mpld 3(Matplotlib 和 D3.js 的组合)可以做什么的示例。这可以帮助您创建动态和非常好看的图表来增强您的报告。

查询输出。作者截图

限制

目前存在的一个限制是每个单元格只能使用一个 displayHTML 函数。这意味着如果你想显示各种图像或文本,这个函数会变得非常拥挤。然而,这不应该限制你太多,一个笔记本电池(输入和输出)的最大大小是 16MB,远远不够。

在一些包中,正如我们在 mpld3 中看到的,你可以显示动态图形来呈现函数的输出。这在数据块中有时会变得有点复杂,因为根据格式的不同,它可能不会自动工作,并且您可能必须使用 JS 代码,如果您对它不是很熟悉,这可能会有点棘手。

也就是说,正如您在本文中看到的,这个 displayHTML 工作得非常好,并且显著地修饰了您可以交付的工作。

我希望这篇文章对您有所帮助,并且您能够在将来应用它。如果您有任何反馈,请随时联系我们。

以下是如何在 Deepnote 上使用 Jupyter 笔记本的方法

原文:https://towardsdatascience.com/heres-how-to-use-jupyter-notebooks-on-steroids-with-deepnote-c35251222358?source=collection_archive---------22-----------------------

在本教程中,了解 Google Colab 的完美替代品

照片由石页·康让在 Unsplash

这个想法

你可能知道并经常使用的最好的数据科学工具可能是 Google Colab。你有什么不喜欢 Colab 的——轻松访问 Google Drive 和文件系统以获得数据,免费访问 GPU 以完成更繁重的深度学习任务,以及像在 Google Docs 和其他类似应用程序中一样与他人协作的能力。

问题出在更小但却被极大忽视的事情上,比如当实时协作成为你和你的团队的一个需求时——你和你的队友面对面协作的方式。使用 Colab,不幸的是,您无法实时看到彼此的变化。

你需要的是刷新你的浏览器标签。然后需要再次加载笔记本,之后你们就可以看到彼此的变化了。如果一个队友在一个单元格上给你留言,你也需要这样做。

另一个要问自己的问题是——您是否曾经想要添加一个数据源用于您的项目,而使用 API 或将其上传到您的驱动器会带来额外的麻烦?还是每次合上笔记本都不重新安装 google drive?

我来说说 Deepnote 的便利吧。

Deepnote 作为一个替代品表现如何?

就像 Colab 一样,Deepnote 是一个运行在浏览器中的 Jupyter 笔记本,具有一些附加功能。

其中一些包括:

  • 与 GitHub、谷歌云平台、亚马逊 S3、谷歌驱动等平台的简单集成。
  • 熊猫数据帧的一键可视化
  • 易于共享和实时协作
  • 从笔记本构建报告的更好方法

最好的特点是—

  • 能够保持单个项目在整个月、每个月不间断运行

够兴奋了吧?让我们来发现运行一个新的 Deepnote 项目的基本原理!👇

创建新项目

登录后,只需导航至您的控制面板,然后单击“新建项目”按钮:

作者图片——如何在 Deepnote 中创建新项目

你将被带到一个屏幕,询问你是否想要连接到一个现有的 GitHub 库并从那里导入你的代码,或者只是从你的本地机器上传一个你选择的笔记本。选择任何一个立即开始。为了这个教程,我用我在这个教程中的 Jupyter 笔记本来描述在熊猫中使用许多日期时间函数的基本技巧。

在侧面板中,有用于上传数据文件和其他文件的文件视图:

作者图片——如何在 Deepnote 中上传文件

您还可以选择在一个地方查看所有的全局变量,因此当您稍后想要清理项目以共享或发布报告时,可以从侧面板轻松完成。

安装依赖项并制作需求文件

如果你在笔记本上输入一行代码,比如:

!pip install <dependency-name>

它会自动将它安装到您当前的环境中。

现在,如果您想将这个包移动到您的 requirements.txt 文件中,您通常会这样做:

pip freeze > requirements.txt

或者如果你像我一样使用pipenv,你会这样做:

pipenv run pip freeze > requirements.txt 

但是 Deepnote 让它变得更容易,并为你提供了一个更快捷的方法来做到这一点。此外,在安装任何新的包之后,您还可以选择将它添加到您的需求文件中,而不需要上述额外的步骤。

作者图片—安装新的软件包

真的就这么简单!

在代码中使用环境变量

环境变量(有时也称为秘密)可以用来存储 API 密钥、数据库秘密、bot 令牌等信息。

这些通常只在环境变量的帮助下在代码中使用,而不是硬编码,以避免像 GitHub 那样的版本控制。你通常会以的形式知道。env 文件。

我还有一篇完整的博客文章,专门描述如何在代码中有效地利用环境变量。

在此找到它们:

使用 Deepnote,只需点击侧面板中的 Integrations 选项卡,然后点击环境变量,即可插入环境变量。

按作者分类的图像—添加环境变量

然后,您将获得在项目中包含环境变量的选项,然后可以从项目中包含的任何脚本或笔记本中访问这些变量。

实现项目共享和实时协作

我在上面的介绍中描述了在 Deepnote 笔记本中使用实时协作是多么容易。您在任何单元格旁边所做的评论都会立即显示给与您共享该笔记本的所有人。

添加新的合作者就像输入队友的 Deepnote 电子邮件并将权限更改为“编辑”或“完全访问”一样简单

按作者分类的图片-共享您的项目

配置共享数据集

借助 Deepnote 中的“共享数据集”,可以很容易地在一个团队中就一个共享数据源的单个项目开展工作。

这是 Integrations 选项卡中的另一个有用功能,您可以上传自己的数据集,项目中的所有协作者都可以访问它。

按作者分类的影像-创建共享数据集

从 Google Drive 轻松访问文件

当试图访问文件时,您必须非常熟悉将 Google Drive 安装到您的 Colab 项目中的过程。这个过程很简单,如果当你没有任何选择,只能再次安装 Google Drive 来运行你的笔记本时,当运行时被搁置一段时间后断开连接,这有点不方便。

在 Deepnote 中,您只需通过集成连接您的驱动器。这样,每次你打开硬件时,你所有的文件都可以被访问

以下是将 Google Drive 连接到项目的方法:

按作者分类的图片—连接驱动器

一旦你做到了这一点,从驱动器中访问文件和数据集就是用几行简单的代码完成的。

现在,您只需通过屏幕截图中显示的文件夹结构连接数据集即可使用。它的路径总是“datasets/your-integration-name/”,您可以从那里简单地访问您的共享文件。

使用:

!ls /datasets/drive-integration

给出输出:

‘Arxiv Text Summarization’

因为我们用共享数据创建了一个文件夹。

最后,让我们讨论两个最有趣的特性…

只需一次点击即可可视化数据框:

简单地打印df.head()df就可以得到数据帧中简单的熊猫信息。

作者图片——可视化熊猫数据框架

为了以 Deepnote 提供的方式可视化它,只需点击这个带有df语句的单元格上的小 visualize 按钮。

之后,您将看到代码单元格下方的一个完整的可视化子窗口:

按作者分类的图像-数据框的可视化单元格

用你的笔记本写一份报告

向您的经理演示或进行强调演示时,您的 Jupyter 笔记本在展示您的辛勤工作时具有无限的功能。Deepnote 让你更容易用两种方式以报告的形式展示你的笔记本:

  1. 文章方式—以 PDF 格式分享,
  2. 仪表板方式——像使用一块空白画布一样使用您的报告,然后用它制作一个漂亮的仪表板。

从侧边栏中,只需选择发布编辑器,你将被带到一个页面,以获得一篇文章或一个仪表板布局。

例如,下面是我的熊猫约会探索笔记本的文章布局:

按作者排序的图像-笔记本中的文章报告预览

对于不需要它的代码单元格,您还可以选择在报表中隐藏代码或单元格的输出。

按作者分类的图像—文章布局选项

只需重命名您的文章,然后点击发布,使其对任何人都是可共享和可见的。

几句临别赠言…

是时候表扬一下你自己了,因为你一路陪着我!

我希望这是一个有用的教程,可以帮助你开始更好地在云上运行笔记本电脑。对于未来,我希望这能启发你创建一些精彩的数据探索项目,并通过 Deepnote 笔记本和报告进行分享。

感谢您的阅读!我们下次再见在我的另一篇文章里!

如果你想留在圈子里,阅读我的更多数据科学文章,我恳请你考虑成为一名中等会员。只需每月 5 美元,你就可以获得我所有的文章,同时支持我的写作。😃 👇

https://ipom.medium.com/membership

也在推特上找我。

下面是如何用 Java 在 Excel 中自动调整数据表的范围

原文:https://towardsdatascience.com/heres-how-you-can-auto-adjust-your-datatable-range-in-excel-with-java-d00502d336d?source=collection_archive---------35-----------------------

使用 Apache Poi 3.15 JAR lib 的分步说明

由于一些国家正处于向❝Endemic❞国家过渡的过程中,过去两年应对疫情冠状病毒的工作不可避免地在公共医疗保健部门的信息传输和当前低效率的数据流方面留下了很大的改进空间。因此,当❝Pandemic❞的事情在我居住的地方安定下来后,公司领导的大量请求几乎立即淹没了我的电子邮件收件箱时,我并不感到惊讶。长话短说,我的任务是在当前定期手动更新&编辑 Excel 报告的工作流程中改进和引入自动化。

考虑到这一点,与其他许多致力于不断创新和强化技术文化的公司不同,另一方面,我的工作场所目前没有运行过于复杂的技术解决方案所需的设置。因此,由于编程语言的平台无关性,这最终导致我本能地选择以 Java 应用程序的形式实现我的最终交付成果。

虽然我之前的文章主要关注的是 Java 编程语言中的 Excel & Outlook 数据提取(考虑到前面提到的完全相同的约束):

相反,本文旨在展示 Apache POI 的另一项功能——这是一个操作 Microsoft Office 文档的开源 Java 库。更具体地说,我计划演示它的一个鲜为人知的功能,即嵌入在 Microsoft Excel 电子表格中的数据表范围的自动调整。

注意事项:

  • 该功能针对扩展名为的 excel 文件。xlsx)仅。这与第一部分不同,第一部分的功能对两者都适用。xlsx 和。xls 扩展。
  • 使用的 Java 库依赖项列表与第一部分没有什么不同(即所有 JAR 依赖项的版本也是一致的):

作者图片|用于读写 Microsoft Excel 文件的 Java 库列表|请注意,所使用的 apache poi 的具体版本是 3.15。不同版本的 apache poi 有不同的依赖版本。

用例解释:

为了最大限度地减少繁琐的 excel 报表手动更新,我从工作场所的用户那里收到的一个常见请求是定期将输入的记录追加并输入到同一个 Excel 数据表中。

Image by Author |说明 Excel 中呈现的数据表的示例|请注意,表格范围为 $A\(1:\)J$31 。因此,在第 31 行之后追加的新记录不会输入到数据表中。

第一部分.追加新的传入数据行

在我的特定用例中,由于传入的数据记录是以 CSV 格式指定的,所以我实现的 Java 代码读入一个 CSV 文件,并附加到在所选 excel 文件中检测到的第一个电子表格中:

为了使用户能够轻松地运行它,它已经被合并到一个 Java Swing 应用程序(该应用程序与上一篇文章 中构建和说明的应用程序相同)。我强烈建议其他人查看它,因为这篇文章是对的直接跟进,如下图所示:

作者截图|在【更新 excel 中的数据表】选项卡中,应用模块的第一部分允许用户选择一个要更新的 Excel 文件和另一个包含最新数据记录的 CSV 文件

作者截图|选择【追加数据>>】后,应用程序读入 2 个文件输入。CSV 中的数据记录成功附加到 excel 文件中。如上所述,文件日志输出消息“附加数据”。

第二部分。更新数据表范围

虽然新的数据记录已经包含在第一部分的 excel 表中,excel 表读取的数据范围保持不变。因此,数据透视表、图表等。它们基于相同的数据表呈现数据,也保持不变。

为了反映最新的数据范围,下面的代码片段继续读入 excel 文件的数据表范围。如果 excel 表格的最后一个行号大于数据表的当前范围,该表应扩展其范围,以包括电子表格的最后一个行号。

与之前类似,这个功能被整合到 Java Swing 应用程序中,可在 my GitHub 获得。用户可以一次输入多个 excel 文件来更新所有数据表:

作者截图|请注意,应用程序的输出有一个表 datatable 范围,其中包含先前附加到文件中的记录

以下是运行 Java 应用程序的步骤说明:

作者截图|选择带有附加数据记录的 excel 文件。更新表格范围后,应用程序会提示用户保存一个输出 ZIP 存档,其中包含所有相应的更新 excel 文件。

如果您想要该应用程序的副本,目前可从 my GitHub 获得。先前的可运行 JAR 应用程序现在被重命名为"DataDocUtility _ v1",而本文中引用的 JAR 应用程序被声明为"DataDocUtility _ v2"。只要双击它,Java Swing GUI 就会自动显示出来。以防您忘记,第一篇文章可从获得😛:

此外,本演示中使用的所有示例 数据文件 输出文件 以及 源代码 都可以在我的 GitHub 资源库中找到。请随意为您自己的用例分叉/调整代码☺

非常感谢您的阅读,如果您发现此内容有用,请在 Medium 关注我。会非常感激的!😃

https://geek-cc.medium.com/membership

以下是将职业转向数据科学的真相。

原文:https://towardsdatascience.com/heres-the-honest-truth-about-making-a-career-switch-into-data-science-2e5a42d24879?source=collection_archive---------2-----------------------

有志成为数据科学家的必读书目。

马库斯·温克勒在 Unsplash 上的照片

2018 年初,我很想成为一名数据科学家。我认为这个标题听起来很有声望,我认为构建“机器学习模型”听起来很不错,而且这是一个很热门的职业。

如果以上任何一点引起了你的共鸣,那么我鼓励你继续阅读。

经常有人问我,如何从完全不相关的职业转向数据科学,比如会计或化学工程。

这个问题我想了很多。一,因为当我想进入数据科学时,这是我过去常常问自己的问题。第二,因为我认为对数据科学有一种强烈的误解,而这正是本文的主要目的。

闯入数据科学的真相。

数据科学的真实情况是:

1。不是每个数据科学家都做“数据科学”的工作。

“数据科学”一词涵盖了如此广泛的技能和工作职责,以至于一家公司的数据科学家可能看起来与另一家公司的数据科学家完全不同。根据我的经验,几乎没有任何数据科学家纯粹花时间构建机器学习模型。许多数据科学家还扮演数据工程师和/或数据分析师的角色。

2。不是每个从事“数据科学”工作的人都有数据科学家的头衔。

另一方面,我认识很多从事数据科学项目的数据分析师和数据工程师,比如预测模型、异常检测模型和推荐系统。

所以,你可以从中得到一些启示:

  1. 思考数据科学家角色的哪一部分让你感兴趣,而不是职位本身。你喜欢建立机器学习模型的想法吗?你想深入统计的世界吗?现在,我意识到,虽然我最初想成为数据科学家的理由并不是无效的,但它们也让我一开始就陷入了错误的心态——理解这一点将为你的职业生涯提供更多的方向和意义。
  2. 任何与数据相关的工作都是进入数据科学的良好开端。除了找“数据科学”的岗位,我还推荐看看数据分析师岗位、Python 开发者岗位、产品分析师岗位等等。原因是你仍将发展核心数据科学技能,如 SQL 和 Python,这也为你自己打开了许多机会。

下一步是什么?开始一个项目。

一旦你发现数据科学激发了你的兴趣,接下来要做的就是开始你自己的项目。我个人认为,完成一个个人项目比完成一个在线证书更有价值 100 倍,因为它让你为数据科学家的实际工作做更好的准备。

我也明白想出一个项目创意可能很难,所以我会在下面留下一些想法:

  • 如果你是一个篮球迷,你能收集数据,看看什么因素最能代表一个球队赢得比赛吗?是 3 分命中率最高的球队吗?是主队吗?等等…
  • 如果你喜欢烹饪,看看你是否能找到一个食谱数据集(或收集你自己的数据),并创建一个模型,为缺失的成分建议一种替代成分。
  • 如果你想进入深度学习的世界,你能创建一个检测某人是否戴着面具的模型吗?(YouTube 上有很多教程!)
  • 对于更多的项目想法,我会检查如下:

</12-data-science-projects-for-12-days-of-christmas-aff693f5ed2b>

如果你还没有为一个项目做好准备…

如果你觉得自己还没有准备好开始自己的项目,这里有一些切实可行的后续步骤,可以用来指导你的学习:

  1. 从统计数据开始。我认为统计学非常重要,因为大多数机器学习概念和数据科学应用都围绕着统计学。如果你害怕统计,数据科学可能不适合你。我会查看佐治亚理工学院名为统计方法的课程,或者汗学院的视频系列。
  2. 学习 Python 和 SQL 。如果你更像 R 型的人,那就去吧。我个人从未和 R 合作过,所以我对此没有意见。您对 Python 和 SQL 掌握得越好,数据收集、操作和实现就越容易。我也熟悉 Python 库,如 Pandas、NumPy 和 Scikit-learn。我还建议您学习二叉树,因为它是 XGBoost 等许多高级机器学习算法的基础。
  3. 学习线性代数基础知识。当你处理任何与矩阵相关的事情时,线性代数变得极其重要。这在推荐系统和深度学习应用中很常见。如果这些听起来像是你将来想要学习的东西,不要跳过这一步。
  4. 学习数据操作。这至少占了数据科学家工作的 50%。更具体地说,了解更多关于特征工程、探索性数据分析和数据准备的知识。

最后,这里有几个资源可以帮助你开始:

💔-ways-to-get-real-life-data-science-experience-before-your-first-job-545db436ef12>

感谢阅读!

我希望你发现这很有见地!这是一篇固执己见的文章,但我认为许多人会同意我关于数据科学家的两个真理:

1.不是每个数据科学家都做“数据科学”的工作。

2.不是每个从事“数据科学”工作的人都有数据科学家的头衔。

一如既往,我祝你学习一切顺利!😃

不确定接下来该读什么?我为你挑选了另一篇文章:

又一个!

特伦斯·申

  • 如果你喜欢这个, 跟我上媒 了解更多
  • 有兴趣合作吗?让我们连线上LinkedIn
  • 报名我的邮箱列表 这里

这是遍历熊猫数据框架的最有效的方法

原文:https://towardsdatascience.com/heres-the-most-efficient-way-to-iterate-through-your-pandas-dataframe-4dad88ac92ee?source=collection_archive---------0-----------------------

数据帧迭代速度提高 280 倍

(图片由作者提供)

Pandas 是数据科学社区中最受欢迎的 Python 库之一,因为它为数据探索和可视化提供了大量具有灵活数据结构的 API。Pandas 是清理、转换、操作和分析数据的首选库。

庞大 API 的存在使 Pandas 易于使用,但当处理大规模数据集时,它无法在所有 CPU 核心上扩展计算。Dask、Vaex 是开源库,它们可以缩放计算以加快工作流程。

要素工程和要素探索需要遍历数据框。有多种方法可以遍历数据框,**iterrows()**是其中之一。使用**iterrows()**遍历数据帧的计算时间较慢。

有时候,仅仅为了加快迭代过程,从 Pandas 转移到其他可扩展的库是一项单调乏味的任务。在本文中,我们将讨论各种数据帧迭代技术,并对它们的时间数进行基准测试。

Iterrows():

Iterrows()是 Pandas 的内置函数,用于遍历数据框。应该完全避免使用它,因为与其他迭代技术相比,它的性能非常慢。Iterrows()在迭代时进行多次函数调用,并且迭代的每一行都具有数据框的属性,这使得它更慢。

(图片由作者提供),Iterrows()用法

iterrows()花费 790 秒遍历一个有1000 万条记录的数据帧。

有各种各样的技术(将在下面讨论)比 iterrows()表现得更好。

Itertuples():

Itertuples() 是 Pandas 的内置函数,用于遍历数据框。与 iterrows()相比,Itertuples()调用函数的次数相对较少,并且开销也小得多。Itertuples()通过将每一行数据转换为元组列表来遍历数据帧。

(图片由作者提供),Itertuples()用法

itertuples()花费 16 秒遍历一个包含 1000 万条记录的数据帧,比 iterrows()大约快50 倍

阅读下面提到的文章,深入理解为什么 iterrows()比 itertuples()慢

https://medium.com/swlh/why-pandas-itertuples-is-faster-than-iterrows-and-how-to-make-it-even-faster-bc50c0edd30d

Numpy 数组迭代:

迭代打败了使用熊猫的整个目的。矢量化永远是最佳选择。熊猫自带的**df.values()**功能可以将数据帧转换成列表格式的列表。

(图片由作者提供),Numpy 数组迭代

花了 14 秒遍历一个包含 1000 万条记录的数据帧,比的 iterrows()快了 56 倍

字典迭代:

现在,让我们来看看遍历数据框的最有效的方法。熊猫自带**df.to_dict('records')**函数,将数据帧转换成字典键值格式。

(图片由作者提供),字典迭代

遍历一个包含 1000 万条记录的数据帧花费了 8.8 秒,比 iterrows()快了大约90 倍

基准:

我比较了使用上述技术遍历数据帧的基准时间数。

这一表演被记录在谷歌的一个实验室里。

(图片由作者提供),基准迭代时间

结论:

不建议使用**itertools()**来遍历数据帧,因为它会带来很大的开销并进行大量的函数调用。Itertuples 将数据帧转换为元组列表,然后遍历它,这使得它相对更快。

矢量化永远是首选和最佳选择。您可以将数据框转换为 NumPy 数组或字典格式,以加快迭代工作流。遍历字典的键-值对是最快的方法,对于 2000 万条记录,速度提高了大约 280 倍。

参考我关于加速 Python 工作流的其他文章:

  • 用几行代码将 Python 函数执行速度提高 30 倍
  • 速度快 10 倍的熊猫应用程序只需更改一行代码

参考资料:

[1]https://medium . com/swlh/why-pandas-ITER tuples-is-fast-than-ITER rows-and-how-to-make-it-even-fast-BC 50 c 0 edd 30d

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一小部分会员费,不需要你额外付费。

https://satyam-kumar.medium.com/membership

感谢您的阅读

以下是我对 Sklearn.resample 的了解

原文:https://towardsdatascience.com/heres-what-i-ve-learnt-about-sklearn-resample-ab735ae1abc4?source=collection_archive---------8-----------------------

解释上采样、下采样和一些要避免的错误

安德里亚斯·布鲁恩在 Unsplash 上拍摄的照片

对于数据科学家来说,处理不平衡的数据集可能是一个棘手的问题。处理不平衡数据集的方法之一是使用 sklearn.resample 进行重采样,即向上采样少数类或向下采样多数类。

Sklearn.resample 是 Scikit learn 用于上采样/下采样的函数。

根据 sklearn 文档,函数 sklearn.resample,r 以一致的方式对数组或稀疏矩阵进行采样,默认策略实现引导程序的一个步骤。简单来说, sklearn.resample 不仅仅是神奇地为数据集生成额外的数据点,它基本上是为你的数据集创建一个随机重采样(有/无替换)。这种均衡过程防止机器学习模型倾向于数据集中的多数类。

接下来,我在一个例子中展示了上采样。在下面的例子中,我们创建了一个包含 3 列的数据框架:年龄、性别和商店。

#import libraries
import pandas as pd
from sklearn.utils import resample,shuffle#create a dataframe
df = {'age':['a','b','c','a','b'],'sex':['e','f','g','f','e'],'store':[1,2,3,3,2]}df = pd.DataFrame(df)df.head()

df.head()

我们首先分离少数民族阶层,然后对少数民族阶层进行抽样。少数民族班级的人数被上采样到其他班级的人数。

#set the minority class to a seperate dataframedf_1 = df[df['store'] == 1]#set other classes to another dataframeother_df = df[df['store'] != 1] #upsample the minority class
df_1_upsampled = resample(df_1,random_state=42,n_samples=2,replace=True)#concatenate the upsampled dataframe
df_upsampled = pd.concat([df_1_upsampled,other_df])
df_upsampled

df _ 上采样

多酷啊!😉 😊现在我们有更多的数据来训练我们的模型。此外,当我们训练模型时,可以观察到数据中的 3 个商店类别(1、2 和 3) 中的每个类别的数量相等。

然而,当您进行上采样或下采样时,请避免这些错误!

  1. 在机器学习问题中,确保只有在分成训练、测试(如果你愿意,还可以验证)之后,才进行上采样/下采样。如果您在拆分为定型和测试之前对数据集进行了向上采样,那么您的模型很有可能会出现数据泄漏。参见下面的示例。
from sklearn.model_selection import train_test_splitX = df_upsampled.drop('store',axis=1)
y = df_upsampled.storeX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1,shuffle=True)X_train.head()

x _ 火车

X_test.head()

x _ 测试

注意数据泄露!我们在 X_trainX_test 中有完全相同的数据点。这样做可能会让我们对我们的 机器学习 模型的实际表现产生错误的认识。

Claudio Schwarz | @purzlbaum 在 Unsplash 上的照片

2.在您的机器学习模型建立之后,建议在您的非上采样训练数据集上测试您的指标。在非上采样数据集上测试你的指标,比在上采样数据集上测试它,给你一个更真实的模型评估。就我个人而言,我总是喜欢保留一个未经上采样的训练数据集版本。

结论:
上采样/下采样
是处理不平衡数据的非常好的方法。然而,重要的是要了解它们是如何工作的,以便能够正确使用它们。还要注意,由于额外的信息,上采样机制会在系统中引入偏差。

还可以了解一下 imbean 库的 SMOTE 操作符。它基于knarestneighbors算法工作,综合生成落在已经存在的寡不敌众的组附近的数据点。点击阅读更多信息。

我希望这对你有帮助。期待您的评论,同时您也可以在 twitter 和 Linkedin 上关注我。

如果你喜欢这篇文章,你可以考虑给我买杯☕️.咖啡

谢谢😊

这就是为什么我们可能需要重新思考人工神经网络

原文:https://towardsdatascience.com/heres-why-we-may-need-to-rethink-artificial-neural-networks-c7492f51b7bc?source=collection_archive---------4-----------------------

人工智能|新闻|评论

一项新的研究证明人工神经元过于简单

Jr Korpa 在 Unsplash 上拍摄的照片

如果我告诉你一个生物神经元用一个完整的人工神经网络来表示比用单个人工神经元来表示更好呢?

在大规模训练数据集和巨大计算资源的帮助下,深度学习在 2010 年代初取得了前所未有的成功。很快,人工智能、机器学习和深度学习成为了一场技术革命的中心。与它们一起的是另一个概念:人工神经网络(ann)。

大多数人不知道的是,这两个概念一点都不新。艾未未出生于 1956 年。ML 和 DL 分别在 1959 和 1986 推出。人工神经网络——一个从当时不成熟的神经科学领域借用的术语——出现在 1943 年,伴随着沃伦·s·麦卡洛克和沃尔特·皮茨的开创性工作。

他们的工作现在被认为是有史以来第一个关于人工智能的研究。作为人工智能的一个子领域,人工神经网络经历了不感兴趣和默默无闻的时代,直到深度学习革命将它们提升到人工智能历史上的最高峰。

第一个人工神经网络

正是在计算机科学的早期——人工智能甚至还没有名字——第一个人工神经网络诞生了。神经科学家几十年前就已经在模拟生物神经元,但麦卡洛克和皮茨的工作是第一次用命题逻辑来描述生物神经元。

熟悉人工神经网络的人会认出这张照片:

MCP 神经元。作者图片

这是大约 80 年前构思的麦卡洛克和皮茨神经元模型(MCP)。在很大程度上,这是每个现代入门课程或深度学习书籍中教授的相同模型。这不是因为 MCP 是一个不需要细化的精确模型,而是因为自 1943 年以来,深度学习在这个元素级别上没有发生一点变化。

MCP 神经元旨在仅代表生物神经元的简化神经生理学版本:一系列输入进入神经元进行处理,然后产生输出或不产生输出。它有一个阈值激活功能——如果输入的和为负,输出为 0。否则就是 1。

当前的人工神经网络具有加权输入和更复杂的非线性激活函数,以允许有意义的学习和更精确的 I/O 映射。但它们只是 MCP 模型的略微改进版本。基础是一样的;一些深思熟虑的输入被转换成输出。神经元学习得好不好与这些模型不像——甚至不太像——真实的生物神经元这一事实无关。

当前人工神经网络神经元模型。作者图片

主要的简化,也是最伤害 MCP 模型的一个简化是,人工神经网络中的每个神经元都被折叠成空间中的一个点。这足以模拟一些神经元的行为,但其他更复杂的神经元的生物物理性质过于微妙和复杂。

电流通过树突、胞体,并通过空间和时间流向轴突。并非所有树突的功能都一样。并非所有的输入都参与产生输出,电压沿树突下降。树突树形态、突触模式和不同类型的受体都会影响神经元的行为。还有许多更基本的机制和过程构成了最终提升我们智慧的基础。

这些特征在 MCP 或当前的 ANN 模型中都没有描述。

当 MCP 神经元被构思出来的时候,神经科学已经知道神经元具有不可简化为空间点神经元的特性。麦卡洛克和皮茨简化了复杂性,以便建立一个基于逻辑的模型。

在这个过程中,他们奠定了整个领域的基础,这个领域再也不会屈尊去审视自己的前提,并将它们与神经科学的相关发现进行对比。

生物神经元的复杂性

MCP 模式创建于近 80 年前。从那时起,神经科学得到了巨大的发展,我们对神经元的理解已经到了不能再继续称人工神经元为“神经元”的地步。让我们回顾一些关于这个主题的最相关的研究,以说明人工智能与认知科学的分歧有多大。

神经元和树突——处理器中的处理器

在 80 年代,Christof Koch 和其他人发现树突形态和突触模式可以影响神经元内部处理输入的方式。长期以来,科学家认为树突表现一致,被动地汇总输入。科赫的实验得出的结论是,神经元远比这复杂。

最近,神经科学家研究了单个树突的作用,发现它们本身也充当处理单元:树突有自己的阈值来产生尖峰(称为树突尖峰),这与整个神经元的阈值不同。

也就是说,神经元并不像 MCP 模型所暗示的那样是简单的“逻辑门”。树突本身似乎能够充当逻辑门。因此,生物神经元是一个处理系统,而处理系统又由独立的处理系统组成。

为了在人工神经网络中表现这一点,神经元之间的连接需要有不同的形态,这将影响神经元每次产生输出时的作用。这些连接会在内部充当处理系统:到达神经元的每个输入连接都会在内部产生或不产生尖峰信号,从而彻底改变神经元的整体输出。

这意味着人工神经元可以更好地理解为一个分层网络,其中的层(树突)起到非线性中间 I/O 映射的作用。然后,根据“连接树”的形态对所得到的中间输出求和,以产生最终输出。

基于这些惊人的发现,艾伯特·吉登和他的同事去年在《科学》杂志上发表了一篇突破性的论文。他们在人类锥体神经元中发现了一种新的 I/O 特征,这种特征是目前的模型无法描述的。来自这些神经元的树突产生一种类型的尖峰,其中强度在阈值水平的刺激下最高,当输入电流增加时最低。

他们的发现证明了一些树突可以充当 XOR 逻辑门——当且仅当其中一个输入为真时,输出为真。1969 年明斯基和 Papert 证明了单层感知器——人工神经网络的基本早期类型——不能进行这种类型的计算。现在,很明显单个生物树突可以。复杂程度高了两级。从单个树突到单个神经元,再到简单的人工神经网络。

如果树突可以在人工神经网络水平上工作,那么生物神经元比人工神经元复杂多少?

模拟一个生物神经元需要 1000 个人工神经元

几天前,大卫·贝尼格夫和他的同事在Neuron杂志上发表了一篇论文,证明了这些年来一直提出的观点:人工神经元根本不能准确地代表生物神经元。

为了证明这一点,他们决定使用现代机器学习技术来模拟人类金字塔神经元的 I/O 行为。他们想要测试两件事:当在真实 I/O 对上训练时,人工神经网络是否可以精确预测神经元输出,以及人工神经网络需要多大才能准确捕捉生物神经元的整体复杂性。

他们发现,至少需要一个 5 层 128 单元的 TCN——时间卷积网络——来模拟毫秒分辨率(单个尖峰精度)的金字塔神经元的 I/O 模式。他们修改了深度和宽度,发现 8 层 256 个单元的 TCN 可以实现最佳性能。

做一个粗略的比较:这意味着单个生物神经元需要 640 到 2048 个人工神经元才能被充分模拟。这并不意味着一个生物神经元有这么多的计算能力或复杂性。然而,这是一个明显的迹象,表明这两种类型的神经元在形式和实质上比以前认为的更加分离。

研究人员能够确定生物神经元如此难以模拟的确切机制:树突形态和一种称为 NMDA 的特定类型突触受体的存在。两者都是长期以来在神经科学中众所周知的神经元的结构和功能方面,但在现代人工智能和人工神经网络中完全被忽略。

这些结果引发了一些问题:为什么人工智能社区没有试图重塑其基础,以更好地适应他们试图模拟的现实?在那些基础被推翻并从头开始重建之前,AI 在实现 AGI 的探索中注定要失败吗?在这样一个元素级别改变 AI 会有什么后果?

让我们看看这一切是如何展开的。

人工智能和神经科学——分叉路径

我们大脑中的神经元——尽管不是全部——比它们的人造对应物要复杂得多。尽管最近在神经科学领域有所发现,但通过检查人工智能和深度学习建立的假设是否仍然成立,来处理这个问题是合理的。

可能的情况是,人工智能仍然可以在不改变任何东西的情况下完美地工作。尽管数字神经结构和生物神经结构之间存在明显差异,但它将继续朝着 AGI 前进。然而,在人工智能领域,似乎几乎没有人会在意甚至去检查它。

原因是,从很早的时候起,神经科学和人工智能就分道扬镳了——尽管这两个领域都在试图回答紧密相关的问题。神经科学与智力、大脑和思维有关。神经科学家决定向内看,看我们所知的唯一智能实例;我们。相比之下,人工智能关注的是使用人工手段复制智能。他们关心设计和建造能够感知世界并据此行动的智能代理。

神经科学是一门旨在发现真理的纯科学。它是由好奇心和求知欲驱动的。人工智能——至少是短期人工智能——在很大程度上是由金钱和有用性驱动的。业内人士并不担心,如果我们仔细分析,所有深度学习的基础可能会崩溃。他们关心人工智能不断吸引资金,他们的模型似乎以某种方式工作,即使不合理。

神经科学不断审查其基础,但人工智能选择了另一种方式:他们做出假设,然后头也不回地往前走。

这两个领域的工作和发展水平是不一样的,但说人工智能中的每个人都从技术和金钱驱动的角度看待它是不公平的。人们非常努力地工作,以推动该领域成为一门科学。那些仍然将领域视为解决智能和完成 AI 创始人最初使命的手段的人:人工通用智能。

他们承认有用的人工智能和具有挑战性的人工智能之间的区别,前者适用于简单、狭窄的任务,并被部署在任何地方,而后者需要重大突破才能达到下一个水平。在后一种情况下,有一个关于什么是最佳路径的持续辩论。虽然一些认为深度学习是一种方式——它可能需要一些调整,但最终会奏效——,其他认为它本身永远不够。

但这是他们应该争论的吗?

AI 社区关注的是错误的问题吗?

当且仅当所有较低级别的辩论结束并达成一致时,才应该进行这种辩论。然而,事实并非如此。深度学习被认为是人工智能未来之路的最低可能基石仍然存在疑问:人工神经元可能与生物神经元太不相似,永远不会产生复杂的认知过程和类似人类的智能。

我们可以通过更大的模型、巨大的计算能力和庞大的数据集来弥补人工神经元的复杂性不足,但这种效率太低,无法成为这一探索的最终步骤。

然而,这些是人工智能行业的优先事项。他们如何在保持效率的同时,做出不损失带宽的芯片?他们要么堆积 GPU,要么制造/购买专门的 芯片(只有最有钱的人才买得起)。他们如何提取和管理越来越多的数据集?无监督学习和自动标注。他们如何创建和训练更大的模型?他们要么是一家大型科技公司,要么需要向一家公司申请资金。

他们一直在寻找解决方案,但这种趋势是可持续的吗?好像不是吧。我们可能需要回到基础。不仅因为我们无法像这样建设 AGI,还因为我们开始感受到否认当今人工智能低效的间接负担。

但是这里有一个问题:如果他们发现他们真的需要做出改变,我们所知的整个人工智能领域将需要一个完全的恢复。他们就是不愿意接受这一点。人工智能行业的领导者甚至可能知道人工智能的瓶颈是不可逾越的。但他们可能只是喜欢表现得好像这无关紧要,这样他们就不必面对在错误假设的基础上建立这一切的成本。

不过,这里有一个重要的澄清。一些人工智能系统工作得很好,不会污染那么多。人工智能仍然是一个非常有用的技术学科,为许多行业带来了大量创新。我不否认。但这是规则的例外。创造更强大的人工智能的竞赛正在进行,每个主要的参与者都在那里,为分一杯羹而战。

正如我之前所说的,进步不应该以任何代价来获得。

人工神经网络应该更多地基于神经科学,原因有两个,一个着眼于未来,一个着眼于现在:首先,生物和人工神经元之间的复杂性差异将导致结果的差异——AGI 不会没有改革——其次,我们追求这一目标的低效率正在损害我们的社会和地球。

值得吗?

后果——对人工智能和世界

即使人工智能社区不考虑我在这里概述的事实,人工智能作为一个肥沃的产业,仍然会每年带来大量新的研究项目和有用的应用。

尽管人工智能没有更接近神经科学,但狭义人工智能系统仍将成功完成它们为之而生的简单任务。无论人工智能社区是否接受生物神经元比人工神经元复杂得多,人工神经网络仍将受到欢迎。无论最终是否实现,人工智能行业仍将从追求 AGI 中受益匪浅——接近 AGI 的人工智能也可以改变世界,不管是好是坏。继续提高发达国家特权阶层生活水平的愿望也将继续存在。

但是代价是什么呢?

人工智能中的伦理问题正处于鼎盛时期,模型似乎没有变得更好。就在几天前,纽约时报报道脸书的人工智能系统将一群黑人标记为灵长类动物。谷歌制造的另一个人工智能在 2015 年显示了同样的有害偏见。难道我们要忽略这一切,像谷歌从训练数据集中删除大猩猩那样,给问题贴上创可贴吗?

让人工智能变得可解释、可诠释、可问责是解决这些问题的关键。这些都是人工智能的热门领域,但他们的目标是解决问题后验。如果人工神经网络背后没有强有力的理论支撑,我们怎么能做到呢?没有任何神经模型可以解释神经网络的行为。我们用它们来预测和预报,因为它们有效,但我们不知道为什么。

随着地球的一半被烧毁,另一半淹没在 T2 意想不到的洪水中,气候灾难即将来临。而人工智能也帮不上忙。它的总体碳足迹站不住脚。

2019 年,来自马萨诸塞大学阿姆赫斯特的研究人员研究了大型语言模型(LLM)的环境影响——如今以 GPT-3 为先锋越来越受欢迎——发现训练这些大型模型之一会产生约 30 万公斤的二氧化碳排放;同样是 125 个纽约-北京的往返航班,Payal Dhar为自然而言。一些大型科技公司(谷歌、脸书)正在努力减少这个问题,并逐渐转向可再生能源。

与这个问题相关的是人工神经网络效率极低。为了学习最简单的任务,他们需要巨大的计算能力。这就是这些系统产生如此大的碳足迹的原因。低效率导致更高的资源开发,从而产生更多的污染。

人类大脑只污染了其中的一小部分,而且在学习或做同样的事情时消耗的能量也不尽相同。大脑是一个极其高效的器官。当大脑使用如此少的能量时,我们怎么能做如此复杂的事情呢——更不用说它比计算机还慢。这种极端差异的原因可能是亚神经元结构的复杂性比人工神经网络高很多倍吗?是的,可能是。

LLM 是为最大的玩家保留的,是那些吸引投资者和大众媒体注意的人。原因是这些模型总是被一种传播给公众的宣传所包围:“机器人现在比人类更能阅读、 GPT-3 […]出奇地擅长模仿人类、一个机器人写了整篇文章。你害怕了吗,人类?”

过度承诺和交付不足是 AI 的行业商标。但并不是所有的人工智能社区都参与销售他们没有的东西,唯一的目的是产生宣传和吸引资金。

用华盛顿大学计算语言学教授艾米丽·m·本德的话来说:“相关的过度承诺会把氧气从房间里吸出来,用于所有其他类型的研究。”除了法学硕士,还有一些被资助机构和媒体忽视的重要研究。

“因为这些大的声明是存在的,并且因为 LLM 通过操纵形式成功地推平了基准,所以其他更仔细界定范围的工作,可能基于非常具体的应用环境,而不会做出疯狂的过度声明,则更难发布。”

艾米莉·本德

也许有些被遗忘的研究正试图提醒那些只看到闪闪发光的 LLM 的人,我们做的都是错的。也许有些人对我描述的这些问题一无所获。

如果人工神经网络的基础很差,只有 LLM 似乎很重要,而且只有大型科技公司才能建造和部署它们,那么就存在一个非常现实的风险,即人工智能行业实际上是一个专注于错误目标的寡头垄断。没有人能够提高他们的声音,让那些负责的人知道他们是多么的错误。

不管你怎么看,人工智能,尤其是人工神经网络,似乎有一些至关重要的问题需要解决。即使我们从根本上重新思考它们,这些问题也不太可能马上得到解决。

如果我们想了解更大的图景,并揭示可能暗示我们一直在走向局部极大值的新路径,那么查看神经科学并承认其发现是第一步。

也许解决办法是不要试图给计算机灌输智能。进化找到了更好的方法。我们正试图以数字方式复制物理领域的成果。为什么不尝试创建硅基物理人工神经网络?使用计算机是图灵的提议,但自 20 世纪 50 年代以来,我们已经走过了漫长的道路。也许神经形态计算有我们应该寻找的答案。

人工智能社区可能不会从头开始重建一切,但至少他们应该采取这两个行动:首先,承认当前人工智能范式(主要是人工神经网络)的局限性和缺点,并在未来的研究和承诺中考虑它们。第二,努力在理论和实践上做出相应的调整。

他们可能会决定像今天一样继续使用人工智能和人工神经网络,但至少不会是因为故意的无知,而是因为诚实的不愿意。

如果你喜欢这篇文章,可以考虑订阅我的免费周报https://mindsoftomorrow.ck.page!每周都有关于人工智能的新闻、研究和见解!

您也可以直接支持我的工作,使用我的推荐链接 这里 成为媒介会员,获得无限权限!😃