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

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

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

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

Neo4j 图形嵌入入门

原文:https://towardsdatascience.com/getting-started-with-graph-embeddings-2f06030e97ae?source=collection_archive---------10-----------------------

实践教程

浅谈如何将网络图的节点转化为向量

图片由 Savionasc 提供,根据知识共享 署名-共享 4.0 国际版许可授权。未对原始图像进行任何更改。

介绍

所有机器学习的起点都是把你的数据变成向量/嵌入(如果他们还没有的话)。也许在你的问题中你是幸运的,你已经有了许多列与每个数据点相关联的规格化浮点数,它们很容易组合起来进行嵌入。或者你可以很容易地推导出它们。许多不同类型的数据可以用来生成向量,如文本、图像等。但是,当您的数据以图表或其他相互关联的数据的形式出现时,该怎么办呢?

在接下来的几篇博文中,我希望深入了解如何创建和调整这些向量的一些细节。为了这篇文章,我将介绍 Neo4j 的图形数据科学 (GDS)库中存在的三种方法。(我们将在一两篇不同的文章中讨论嵌入调整。这些超参数包含很多内容!)我们将使用一个使用 Neo4j 沙箱可用的小图(但你也可以使用 Neo4j 桌面或使用我在这篇文章中描述的自定义 Docker 容器来完成此操作),这是一个免费工具,可用于免费试用 Neo4j 和 GDS。

这篇文章是一系列文章中的第二篇,我们将看看如何用图表进行数据科学研究,从…

  1. “通过 Docker 开始使用 Neo4j 和 Jupyter Lab”

(在未来的博客文章中,我们将更多地使用 Docker 参考。)

Neo4j 沙盒入门

我已经在的另一篇博文中描述了这一点,所以让我们在这里重点讨论一下。第一步是创建沙箱本身。你可以在这里做。我们将创建一个新的沙盒实例,方法是选择“新建项目”,然后选择“图形数据科学”,如下所示。

创建图形数据科学沙盒数据库

一旦完成设置,点击右边的绿色按钮,告诉它“在浏览器中打开”

现在,让我们单击左上角看起来像数据库图标的按钮,看看我们在这个代表“权力的游戏”的预填充图形中有什么酷毙了。我们有几个节点标签和关系类型,这对以后的工作非常有帮助。当您发出 Cypher 命令MATCH (n) RETURN n时,您的图形应该如下所示:

权力的游戏,形象化为网络图。(图片由作者提供。)

使用 GDS 创建内存中的图形

使用 GDS 的第一步总是创建内存中的图形,这是通过使用图形投影来实现的。关于图投影的好处是,您可以(并且通常应该)明确您想要为图的哪个(哪些)部分创建嵌入。一般来说,使用整个图表不是一个好主意,特别是当图表变大时。此外,GDS 中的一些图算法不适用于二分图或多分图。最后,使用内存中的图并不一定要永久地改变整个数据库,除非您使用带有.write()的算法,您可以用它来编写作为节点属性的嵌入。当我们想在图上做 ML 时,这将是非常有用的,我将在这篇文章中展示如何做。所以使用内存中的图形。你会喜欢他们的!

有两种方法可以创建内存中的图形,这两种方法都是用投影表示的图形数据模型。投影指定了节点类型和关系类型,它们可以是全包含的。这两种方法包括通过 Cypher 投影或所谓的“本地”投影创建图形。Cypher 投影的优点是编写简单,同时还提供了 Cypher 查询的所有灵活性,但代价是比原生投影慢得多。

所以让我们从创建一个内存图开始。这里我将使用本机投影,但是如果您愿意,它们可以很容易地转换成 Cypher 投影。假设我想查看图表中的所有人。我们会使用

CALL gds.graph.create(
    'people', {
        Person: { label: 'Person' }
    },
    '*'
)
YIELD graphName, nodeCount, relationshipCount;

来创建这个内存中的图形。这里,节点投影简单地指定了具有标签Person的每个节点。边缘投影'*'包括与节点投影中的节点相关联的所有边缘。

我们可以创建一些更具体的东西,比如指定多个节点类型。然后我们可以使用语法

CALL gds.graph.create(
    'a-different-graph', {
        Person: { label: 'Person' },
        House: { label: 'House' }
    },
    '*'
)
YIELD graphName, nodeCount, relationshipCount

所以现在我们有了人和房子,这可能对 ML 任务有用,比如预测人和房子之间的联系。(我们将把它留到以后的文章中。)

也许我们还想只包括人和房子之间的特定关系类型。(在 Cypher 中,你可以通过快速查询MATCH (p:Person)--(h:House) RETURN p, h来查看所有的关系类型。)假设我们只关心关系BELONGS_TO。为了创建内存中图形,我们将包括一个特定的边投影:

CALL gds.graph.create(
    'belongs-graph', {
        Person: { label: 'Person' },
        House: { label: 'House' }
    },
    {
     BELONGS: { type: 'BELONGS_TO',
            orientation: 'NATURAL'
        }
    }
)
YIELD graphName, nodeCount, relationshipCount

边缘投影BELONGS有一些我们已经包括的东西,即边缘类型和方向。关于后者的一个注意事项:GDS 的一些图形算法倾向于使用'UNDIRECTED'方向,然而默认方向是'NATURAL'。我们鼓励您查阅 API 文档来确定每个算法需要什么。当有疑问时,最安全的方法是假设无向单部图。

酷毙了。现在我们有了一些内存中的图形(请看CALL gds.graph.list()))。最佳实践表明,您应该丢弃所有不打算使用CALL gds.graph.drop(graph_name)的图形,以释放内存。

创建嵌入

您可以使用 GDS 创建三种类型的嵌入: FastRP 、 GraphSAGE 和 node2vec 。每一个都以自己的方式在内存图中创建节点的嵌入。在我们讨论每一个之前,让我们来看一下它们的一些公共参数,您将使用它们来生成嵌入。

所有的嵌入(事实上,所有的图形算法)都有一些不同的方法。我们这里要用的是.stream()(把结果输出到屏幕上)和.write()(把计算出来的东西写成节点属性)。对于它们中的每一个,我们都需要提供内存图的名称、一些配置参数集以及算法返回的内容。在.write()的情况下,这将通过YIELD语句返回。当您返回结果时,它们是根据节点 id 完成的,节点 id 是图的内部 id。请注意,它们特定于内存中的图形,并且不匹配数据库本身中的任何内容,因此我们将很快展示如何将它们转换回可识别的内容。这些配置往往是特定于每种算法的,我们鼓励您查阅这方面的 API 文档。

现在让我们看看三种嵌入算法。FastRP,顾名思义就是,嗯,快。它使用基于线性代数的稀疏随机投影,根据图的结构创建节点嵌入。另一个好处是,它很好地处理了有限的内存,这意味着它可以在沙箱中很好地工作。node2vec 的工作方式类似于 word2vec 的 NLP 矢量化方法,其中为每个节点计算给定长度的随机游走。最后,GraphSAGE 是一种归纳方法,这意味着当添加新节点时,您不需要重新计算整个图的嵌入,而对于其他两种方法,您必须这样做。此外,GraphSAGE 能够使用每个节点的属性,这对于以前的方法是不可能的。

因此,你可能会认为你应该总是使用 GraphSAGE。但是,它比其他两种方法运行时间更长。例如,FastRP 除了非常快(因此经常用于基线嵌入)之外,有时还可以提供非常高质量的嵌入。我们将在以后的博文中讨论嵌入结果的优化和比较。

现在让我们从一个内存图开始,看看使用 FastRP 创建嵌入的最基本的方法。我们将创建一个单部分、无方向的人物图:

CALL gds.graph.create(
    'people', {
        Person: { label: 'Person' }
    },
    {
     ALL_INTERACTS: { type: 'INTERACTS',
            orientation: 'UNDIRECTED'
        }
    }
)
YIELD graphName, nodeCount, relationshipCount

请注意,当我们创建一个无向内存图时,您正在创建两个方向上的关系投影(自然和反向)。

为了获得 FastRP 嵌入,我们将使用

CALL gds.fastRP.stream('people',
 {
     embeddingDimension: 10
    }
)
YIELD nodeId, embedding
RETURN gds.util.asNode(nodeId).name AS name, embedding

在这里,我们已经告诉 FastRP 创建一个 10 维向量,流式传输到屏幕上。最后一行使用gds.util.asNode()将这些内部节点 id 转换成我们可以理解的东西(在本例中是角色名)。当我们运行它时,我们会得到如下结果:

FastRP 嵌入。(图片由作者提供。)

如果我们想将这些作为属性写入数据库,我们可以使用

CALL gds.fastRP.write('people',
 {
     embeddingDimension: 10,
     writeProperty: 'fastrf_embedding'
    }
)

现在,如果你看一些人节点MATCH (p:Person) RETURN p LIMIT 3你会看到,例如,詹姆·兰尼斯特给了我们

{
  "identity": 96,
  "labels": [
    "Knight",
    "Person"
  ],
  "properties": {
"fastrf_embedding": [
      -0.57976233959198,
      1.2105076313018799,
      -0.7537267208099365,
      -0.6507896184921265,
      -0.23426271975040436,
      -0.8760757446289062,
      0.23972077667713165,
      -0.07020065188407898,
      -0.15781474113464355,
      -0.4160367250442505
    ],
"pageRank": 13.522417121008036,
"wcc_partition": 2,
"gender": "male",
"book_intro_chapter": "5",
"name": "Jaime Lannister",
"pageRank-1": 3.143866012990475,
"community": 304,
"title": "Ser",
"age": 39,
"birth_year": 266
  }
}

我们可以看到有一个很好的嵌入在等着我们。

这个系列的下一部是什么?

在这篇文章中,我们演示了在 Neo4j 沙盒实例上创建 FastRP 嵌入。但是等等,node2vec 或者 GraphSAGE 呢?!这些方法需要更多一点的内存,所以我们将把它们保存到以后的文章中,我们将用更多的计算能力来完成。因此,我们将在未来的博客文章中使用 Docker 容器来讨论这些,可以通过这篇文章找到它。我们还将花一些时间讨论如何调优这些不同的嵌入,这是任何基于 ML 的解决方案都需要的一个步骤。当然,如果我们不讨论常见的基于 ML 的解决方案,如自动节点分类或链接预测,我们会怎么样呢?敬请期待!

Python 中的 NLP 入门

原文:https://towardsdatascience.com/getting-started-with-nlp-in-python-6a14d0bf4cfe?source=collection_archive---------24-----------------------

开始进入自然语言处理空间的旅程

在 Unsplash 上由 Jaredd Craig 拍照

阅读的乐趣在于发现新的见解。书籍帮助我们学习,但也挑战我们的理解。有了许多不同的流派,可以发现的知识深度是没有止境的。

我们每个人都可能有越来越多的建议需要阅读。我们可能还记得上一次我们进入图书馆,努力想知道从哪里开始。理解课文难度的有效方法会有帮助吗?是时候调用自然语言处理(NLP)算法了。为了从文本中提取价值,他们帮助区分小麦和谷壳。本文旨在开始理解如何通过使用几个 Python 包来获得价值。

首先,我们需要一个数据集,Kaggle 就是我们要去的地方。

Kaggle 数据集

Kaggle 内部有许多不同的竞赛,旨在挑战任何初露头角的数据科学家。我们将回顾 CommonLit 可读性竞赛中提供的数据集。

https://www.kaggle.com/c/commonlitreadabilityprize

CommonLit 为 Kaggle 提供了开发算法的机会,这些算法可以帮助管理员、教师、家长和学生理解如何以适当的技能水平分配阅读材料。在这方面,阅读材料应该提供乐趣和挑战,以帮助防止阅读技能停滞不前。这个项目的发现之路应该鼓励自然语言处理技术的发展,这种技术可以对应该分配给每个阅读水平的书的摘录进行分类/分级。

关键挑战

在深入分析之前,总是鼓励先假设我们要提取的关键特征。当回顾一篇文章的难度时,有几个感兴趣的方面:

  1. 单词难度
  • 单词长度:长单词通常被认为比短单词更难。因此,可以在单词长度和文本难度之间建立相关性
  • 词汇表:可以用来突出常用词的比例。一个单词越不常见,就越难被感知和理解。然而,请记住,很多时候,单词的难度会受到话题受欢迎程度的影响

2.句子难度

  • 句子长度:更长的句子导致更难的文本。必须注意包含冒号和分号会影响句子长度以及句号

我们有一系列的初步想法要探索。分析的其余部分将提供几种可用于检查这些初始特性的方法。

初始数据分析

使用 Python 时,我们从导入包或包中的模块开始,以便在分析中使用。要使用的初始包的常见列表有:pandas(别名 pd)、numpy(别名 np)、matplotlib.pyplot(别名 plt)。每个软件包都有助于数据分析和数据可视化。

对于下面显示的代码,使用了一个 Jupyter 笔记本实例。Jupyter 笔记本是一种常用的探索性数据分析(EDA)工具。这是第一次探索数据以获得有价值的见解时可以帮助的许多选项之一。在最初的发现阶段之后,自动化的类和函数结构通常会就位。应用先探索数据然后自动分析的方法,确保可以更有效地探索数据集的未来版本。这个过程超出了本文的范围,但是我将在以后的材料中介绍它。

代码 1.1 导入训练数据集并执行初始 EDA

从代码 1.1 开始,数据首先被导入以开始分析。对于本次审查,csv 文件已被导入并存储在变量 train 中。pandas 包中的 read_csv()方法将 csv 文件转换成 pandas 数据帧。数据帧提供具有行和列的结构化表格数据集。

默认情况下,在 Jupyter 记事本中,code 单元格的最后一个元素将提供显示的结果。然而,我们可以通过运行第 4 行到第 6 行的代码来调整这些设置。这些调整后的设置将允许从第 9 行到第 12 行请求的每个输出一起显示。反过来,这确保了开发人员不必将应用于训练数据集的每个方法放入单独的 Jupyter 单元格中来显示输出。

Python 输出 1.1 来自训练数据集的 EDA

在 python output 1.1 中,已经获得了一些初步的见解。head()方法显示了训练数据集的前五行。默认情况下,使用值 5,开发人员可以通过在位置参数的括号()中放置一个值来调整这个值。我们可以看到,“摘录”列存储了用于审查的文本,“目标”列为模型分析提供了因变量。对于这个 NLP 分析,我们将把注意力集中在“摘录”列。

shape 方法通过输出数据集中的(行,列)数来提供数据集的结构。而 dtypes 方法显示列数据类型。在 python 中,对象数据类型表征字符串变量。float 数据类型表示一个数值变量。根据所需的数据精度,还可以使用其他几种数字格式。

最后,describe()方法有助于在数据集上执行初始 EDA。通过请求上面显示的参数,我们可以显示对象列的输出。describe()方法的默认选项是只输出数值变量的值。所有摘录值都是唯一的,而目标变量显示的值范围很广。当平均值高于中值(50%)时,变量中似乎存在一些偏斜。

NLP 分析

执行一些初始 EDA 后,我们对所提供的数据集有了更好的理解。然而,在建立模型对新数据进行预测之前,还需要进行更多的分析。在本节中,我们将开始关注分析的 NLP 部分。

代码 1.2 设置初始 NLP 步骤

首先,我们从设置 NLP 分析开始,这是 spacy 包被使用的地方。spacy.load()方法的一个实例已被赋给变量 nlp。这里提到的实例是一种定义方法的方式,请求的方法已经被打开使用,并且可以与已经定义的变量一起应用。为英文文本设置好参数值后,我们就可以开始了。

通过使用 pandas 方法 loc[],我们可以选择感兴趣的适当[行,列]。在这个 Python 方法中,索引值从零开始。因此,分配给 sample1 的变量将从第一行的“摘录”列中提取值。

Python Output 1.2 将示例摘录文本表示为 spacy 文档

我们可以从上面的输出中看到,nlp 方法已经将“摘录”文本放入到结果输出中。我们现在可以在下面显示的代码中请求额外的输出。

代币

一个标记可以被看作是一个句子中的每个唯一值。其中组成句子的单词和标点符号可以分别查看。

代码 1.3 检查文本中的标记

前两个 print 命令创建在输出中显示的顶部行。使用 for 循环有助于遍历 doc 变量中的前 20 个标记。

Python 输出 1.3 由文本中的每个标记产生

从输出来看,已经请求了许多功能。最初的标记有助于定义我们当前正在复习的句子的哪个元素。一个引理的目的是把意思相近的词连接成一个词。我们可以看到“改变”已经被还原为“变化”。而停用词代表一组不会给句子增加多少价值的单词。通过从句子中排除这些连接成分,我们保持了句子的上下文。最后,应用 len()方法检查令牌的长度。

停用词

如前一节所述,停用词被视为句子中的标记,可以在不破坏句子潜在含义的情况下将其删除。Python 中已经存在几个库,可以帮助揭开从头创建停用词列表的神秘面纱。

代码 1.4 不同可用停用词列表的比较

在代码 1.4 中,我们将比较两个可用列表。我们可以使用已经导入的 spacy 包和 nltk 包。自然语言工具包(nltk)有助于提供初始的 NLP 算法来开始工作。相比之下,spacy 软件包通过大量的方法库提供了更快、更准确的分析。

代码的第一部分(第 6 行和第 7 行)显示了输出 1.4 中的结果。这些列表显示了当前的停用词,使用 len()方法可以让我们快速了解停用词的数量。从这个分析中,我们可以看到 nltk 列表更小。

从代码的第二部分(第 9 行到第 22 行),我们可以看到输出 1.5 中显示的结果。在这段代码中,我们的目标是通过执行维恩图分析来理解列表之间的差异。通过应用 set()方法,我们确保了可迭代的元素都是不同的。执行 union()有助于显示两个 set 语句的组合,并为我们提供完整的停用词集。而取交集显示了在两个集合中看到的唯一值。最后的陈述旨在了解哪些值是每个集合独有的,而在另一个集合中看不到。

Python 输出了两个包的停用词的 1.4 结果

Python 输出 1.5 两个停用词列表的比较

正如我们从输出 1.5 中看到的,较大的 spacy 集合包含更多 nltk 集合中没有的唯一值。但是,nltk 集合中仍有一组 56 个值可以添加到空间集合中。如果空间集需要任何额外的停用词,我们可能需要重新访问这个片段。

实体

回顾句子的实体旨在发现提供上下文的关键标签。在 spacy 中,我们可以提取与实体相关的文本和标签。

代码 1.5 理解实体和句子特征

从代码 1.5 开始,每个实体都被请求。在第二部分(第 6 行到第 9 行)中回顾了其他见解。最后一部分旨在揭示每个句子的长度。

Python Output 1.6 结果来自实体和句子

输出显示了关键实体标签,其中一些与位置相关。理解句子中的名词和动词有助于提供项目和动作的细节。记录句子的数量有助于确定文章的结构。通过回顾每一个句子的长度,我们可以看到这篇文章是如何既有长句又有短句的。如果我们只回顾所有句子的平均长度,我们可能会错过这个范围。

使用 displacy 模块,我们还可以显示上面列出的每个实体如何在文本中显示。

代码 1.6 使用 displacy 模块显示文本

Python 输出 1.7 一个显示文档,突出显示文本中的实体

我们可以更好地理解最后一段包含了关于两个极点位置的更多细节。该上下文可以显示文本已经向不同的方向移动。如果我们只显示了前面看到的 for 循环中的实体,我们可能会错过文本中紧密相连的值。

结论

总的来说,我们已经回顾了 NLP 数据集的一些初始特征。我们已经介绍了执行初始 EDA 所需的步骤。通过获得这种洞察力,我们能够理解我们正在处理的数据集的结构。在执行额外的分析时,显示并始终建议对数据集总体进行采样。它有助于减少所需的处理和在应用于更大的群体之前消耗的内存。我们从这个 EDA 转移到 NLP 分析,并开始理解如何使用 spacy 从样本文本中获得有价值的见解。我们介绍了 NLP 分析的一些关键元素,并开始创建新的列,用于建立模型,将文本分类到不同的难度。

感谢阅读

spaCy 3.0 入门

原文:https://towardsdatascience.com/getting-started-with-nlp-with-spacy-3-0-ff6a4bc74d9b?source=collection_archive---------9-----------------------

理解运行 spaCy 代码时发生的事情

图片来源:威廉·冈克尔

关于这篇文章

这篇文章是故事“理解 NLP —从 TF-IDF 到变形金刚 ”的支持材料的一部分

本文详细介绍了如何开始使用 spaCy。我们将把重点放在内部,而不仅仅是写一些代码和执行它。这意味着——我们将尝试更深入地研究当您执行每个代码片段时发生了什么。

每个代码片段都被分解并详细解释。如果您只想查看运行中的代码,您可能想跳过中间的详细解释,直接在您的 IDE 上运行代码。

是给谁的?

如果您刚刚开始使用 NLP,最好阅读一些关于 NLP 基本概念的文章。

在继续之前,您可能想更新/理解一些概念—

  • 代币
  • 词性标注
  • 命名实体识别(NER)
  • 词汇化/词干化

这篇文章是写给任何一个刚开始尝试 spaCy 作为你的软件包的人的。在我们的例子中,我们将使用 spaCy v3.0。

关于空间的一个简短说明

spaCy是一个工业级 NLP 包。

  • 它很快(用 C 编写,带有 Python 的语言绑定)
  • 这是生产级的
  • 受到活跃社区的支持
  • 围绕它构建了许多活跃的独立项目

安装和设置

步骤 1 ) 安装spaCy 就像安装任何其他软件包一样

> pip install spaCy

步骤 2)从命令提示符下下载至少一个预先训练好的管道模型(英语版)

> spacy download en_core_web_sm

这下载了一个小型的英语语言模型管道,在网上找到的大量文本样本上进行训练。对于我们下载的语言,它有weightsvocabularies 等(我们还不用担心这些术语)。现在我们准备尝试一些例子。

你可以下载 4 个预先训练好的管道—

  • en_core_web_sm —小型号(13 MB)
  • en_core_web_md —中型预训练型号(44 MB)
  • en_core_web_lg —大型预训练模型(742 MB)
  • en_core_web_trf ( —基于变压器的预训练型号 438 MB)

输出的准确性和效率(执行速度)将取决于您选择的预训练模型。

#代码片段 1 —入门

import spacy
nlp = spacy.load("en_core_web_md")doc = nlp("On October 23, Apple CEO Tim Cook unveiled the new iPad Mini, fourth generation iPad with Retina display, new iMac, and the 13-inch MacBook Pro with Retina display.")

这里发生了什么?

  1. 我们导入了一个预先训练好的 spacy.lang 对象(如前所述,这个预先训练好的模型基于来自互联网的英语文本样本)。
  2. 运行这个nlp()管道(以一个字符串为参数,返回一个Doc)。
  3. 返回一个我们可以操作的空间Doc 对象

幕后发生了什么?

当你把文本放在nlp()周围时,会发生很多事情。要知道发生了什么,调用pipeline 属性,你就会看到发生了什么。

>> nlp.pipeline

按正确顺序给出管道中包含的组件列表。

[('tok2vec', <spacy.pipeline.tok2vec.Tok2Vec at 0x24c8>),
 ('tagger', <spacy.pipeline.tagger.Tagger at 0x24c47c8>),
 ('parser', <spacy.pipeline.dep_parser.DependencyParser at 0x24c9ba8>),
 ('ner', <spacy.pipeline.ner.EntityRecognizer at 0x24c66508>),
 ('attribute_ruler',
  <spacy.pipeline.attributeruler.AttributeRuler at 0x24c67e08>),
 ('lemmatizer', <spacy.lang.en.lemmatizer.EnglishLemmatizer at 0x2403a88>)]

这意味着当您调用 nlp()时,您正在运行一系列步骤—

spaCy 语言处理管道(图片由作者提供)

  • 记号赋予器 —将文本转换成由单词和标点组成的小段——这些小段被称为记号。
  • 标记器 —该组件根据所使用的语言模型,将每个单词标记为相应的 词性
  • 解析器 —用于依赖解析的组件(换句话说,找到句子中单词之间的结构和关系——在本文的上下文中理解起来并不重要)。
  • NER (命名实体识别器)。
  • 属性标尺 —当您分配自己的规则(例如:单词/短语令牌匹配)时,该组件可以为单个令牌设置属性。
  • 词条解释器 —该组件为文档中的每个单词/符号创建词条。(词条也称为单词的基本形式。)

哇!— 如你所见,这里完成了很多工作。如果你有一个非常大的文本,它可能需要一点时间。

此时,我们准备对doc 对象进行一些操作。

#代码片段 2 —显示命名实体

#if you want to show the named entities in the text 
doc.ents # if you want to display the labels associated with it 
for tkn in doc.ents : 
    print(tkn.text ," - " ,tkn.label_)

上面代码的输出会是这样的—

代码的输出(图片由作者提供)

或者如果你想要一个可视化的显示

from spacy import displacy
displacy.render(doc, style='ent')

会给你以下的输出。

文档中标识的实体的空间输出。(图片由作者提供)

#代码片段 3—探索 doc 对象

1。句子 —您可以使用doc 对象中的sents属性将句子分成一个iterator 对象,创建一个迭代器保存每个句子。

#working with sentences txt = “Hello my dear fellow scholars ! This is Tomas from the German republic. Iam very happy to join you. How are you all feeling ?”doc = nlp(txt)for sentences in doc.sents : 
    print(sentences)# or you can store it as a list
list_sentences = list(doc.sents)

上述代码的输出如下所示

代码的输出(图片由作者提供)

👉:从 doc 对象中提取的句子是一个统计预测,不一定是最准确的。它不进行简单的基于规则的拆分,例如:基于“句号”/“句号”字符)

#代码片段 4—规则和字符串匹配(自定义搜索模式)

spaCy 允许您搜索自定义搜索模式。这里有一个应用于前面例子的简单模式。

txt_apl = "On October 23, Apple CEO Tim Cook unveiled the new iPad Mini, fourth generation iPad with Retina display, new iMac, and the 13-inch MacBook Pro with Retina display."doc = nlp(txt_apl)

现在,创建并添加自定义搜索模式:

from spacy.matcher import Matcher
mat = Matcher(nlp.vocab,validate = True)#create patterns for matching
patrn_mac = [ {'LOWER': 'ipad'}]
patrn_Appl = [ {'LOWER': {'IN': ['apple', 'appl']}}]mat.add('patrn_mac', [patrn_mac])
mat.add('patrn_Appl', [patrn_Appl])for match_id, start, end in mat(doc):
    print(doc[start: end], “found at “,[start,end])

上面代码的输出看起来像这样—

Apple found at  [4, 5]
iPad found at  [11, 12]
iPad found at  [16, 17]

下面是正在发生的事情—分解成几个步骤:

  1. 导入相关包(此处为Matcher)。
  2. 通过包含spacy.vocab.Vocab对象,创建一个Matcher 对象mat
  3. 定义你的模式——这里我们想搜索任何字符串,转换成小写,并检查它是否匹配'ipad,并将该模式命名为patrn_mac. 。类似地,我们创建另一个名为patrn_Appl的模式。
  4. 将这些图案添加到我们创建的Matcher 对象(mat)中。
  5. 对我们从文本中创建的文档运行/检查这个Matcher 对象。mat(doc) 方法返回一个列表,其中包含匹配 ID、文档中匹配的开始和结束位置——如下所示:
[
 (4260053945752191717, 4, 5),
 (4964878671255706859, 11, 12),
 (4964878671255706859, 16, 17)
]

概述

  • 当您运行nlp()时,它运行一个组件管道— tok2vectaggerparsernerattribute_rulerlemmatizer
  • doc.ents 列出预训练模型识别的实体。
  • 您可以使用displacy 直观查看 NER 输出。
  • 在文档中列出你的句子。
  • 您可以使用Matcher模块创建自定义字符串匹配模式。

结束语

这是对 spaCy 入门的简要介绍。然而,这篇文章并没有公正地评价 spaCy 作为一个高度可扩展的 NLP 包的能力和威力。后续文章将展示 spaCy 作为 NLP 包的生产就绪选择的强大功能。

如果你想阅读一些关于 NLP 的相关文章,这里有一篇

https://pythoslabs.medium.com/10-use-cases-in-everyday-business-operations-using-nlp-af49b9650d8f使用 NLP 的日常业务运营中的 10 个用例

**https://pythoslabs.medium.com/10-use-cases-in-everyday-business-operations-using-nlp-af49b9650d8f **

Python 预提交挂钩入门

原文:https://towardsdatascience.com/getting-started-with-python-pre-commit-hooks-28be2b2d09d5?source=collection_archive---------3-----------------------

定义拒绝不符合要求的提交的规则

作者:爱德华·克鲁格和道格拉斯·富兰克林

布鲁克·安德森在 Unsplash 上拍摄的照片

这里是这个项目的模板。我们使用诗歌进行包装管理。本文主要关注预提交挂钩。

https://github.com/edkrueger/poetry-template

什么是预提交挂钩?

预提交钩子是 Git 钩子的子集。Git-hooks 是每当 Git 存储库中发生特定事件时自动运行的脚本。“预提交挂钩”在提交发生之前运行。

这些 Python 钩子被认为是静态分析的一种方法。静态代码分析是一种通过检查代码而不执行代码来进行调试的方法。

预提交挂钩通常用于确保代码在发布前被正确地链接和格式化。在我们的项目中,我们使用四个预提交钩子,black、check-large-files、pylint 和我们的自定义钩子create-requirements

我们在一个名为pre-commit-config.yaml的 YAML 文件中指定这些 Python 钩子。YAML 是一种人类可读的数据序列化语言,通常用于配置文件。YAML 文件包含带有键/值对的列表和字典。

预提交 Python 包

令人困惑的是,还有一个叫做pre-commit的 Python 包。预提交是一个用于预提交挂钩的管理工具。这个包在每次提交之前管理安装和执行挂钩。

我们将需要这个pre-commit包作为开发需求。此外,钩子check-added-large-files来自这个预提交包,稍后你可以在我们的.yaml文件中看到。

请注意,在[tool.poetry.dev-dependecies]下,您会找到pre-commit.

pyproject.toml

提交前挂钩文件

使用包pre-commit设置 git 挂钩非常容易。我们需要做的就是在我们的项目中创建并格式化一个.pre-commit-config.yaml文件。然后包pre-commit在你运行时寻找这个.yaml文件:

> pre-commit install

因为 Python 我们的 Python 钩子在源代码中是以 YAML 的形式存储的,所以当我们把这个文件上传到 Git 时,它们会自动分发。这使得在新机器上设置项目的预提交挂钩就像克隆 repo 并运行上面的代码行一样简单。

如果您没有使用 Python 包、预提交和他们提供给我们的标准格式,这个过程会更复杂。

我们的.pre-commit-config.yaml

这是一个不错的通用pre-commit-config.yaml。我们可以看到在repos下面是一个字典列表,用键/值对来指定钩子和它们的行为。这个 YAML 包含了格式化钩子,文件大小过滤器,棉绒,和我们的自定义钩子。每个钩子都有一个伴随的id,见第 5、9、12 和 18 行。

。预提交配置文件

这是标准的 .yaml格式。您可以看到嵌套在repos. 中的repo键,每个回购键后面都跟有所需钩子代码的值(URL)。第 2 行和第 6 行有对应于 Github 存储库的 URL。

在第 10 行,我们指定下面的钩子是local钩子。这意味着我们在本地使用第 14 行的 bash 代码运行pylint ,使用第 20 行的代码运行create-requirements

本地运行pylint 给了我们对内衬行为更多的控制,因为我们可以指定 bash 命令如何工作。这节省了我们调试pylint 问题的时间,并允许更多的透明度和定制。此外,在本地运行pylint 意味着您在自己的环境中使用的是pylint 的版本。

值得注意的是,在第 3 行和第 7 行,我们使用rev 来指定我们想要使用的钩子的版本。这些版本可能与您的虚拟环境中的版本不同步。您必须手动保持这些版本的同步。如果这是一个问题,您可以在本地运行所有的挂钩,以确保挂钩使用的是您在虚拟环境中指定的相同版本。

运行提交前挂钩

我们运行poetry run pre-commit install来初始化 git 挂钩。

提交前安装

现在我们的预提交钩子将在我们提交代码时运行。

使用预提交挂钩的 git 提交

这里的终端输出很简单。我们看到每个钩子都有一个skipped,passed, or failed结果。

Black 被跳过,因为没有已更改的 Python 文件来运行格式化。钩子check-added-large-files通过,因为没有超过 5Mb 的文件被提交。pylint无法在我们的 Python 文件中找到任何林挺错误。最后,我们注意到我们的定制钩子失败了,因为我们的requirements.txt文件与我们的pyproject.toml.文件不同步

假设我们已经做了必要的修改,所以我们所有的预提交钩子都通过了(或者跳过了),并且我们已经使用了git add在提交中包含了修改。现在,当我们运行git commit时,我们的输出看起来略有不同。

带预提交的 git 提交

因为我们所有的预提交 Python 钩子都已经通过或跳过,所以提交将被完成和暂存。注意,当一个钩子失败时,提交也会失败。这就是当我们的代码不符合我们的标准时,预提交钩子如何避免我们犯错误。

现在我们可以git push对我们的源代码进行修改,知道我们的提交没有语法错误、不必要的大文件或过时的 requirements.txt 文件。

结论

记住,“预提交钩子”在提交发生之前运行。Python 包 Pre-commit 使我们能够轻松地管理和运行钩子,我们需要这些钩子来确保代码在发布前被正确地链接和格式化。

通过最少的设置,预提交钩子可以避免错误的提交,从而节省时间。像black这样的预提交钩子确保你发布的代码是干净和专业的。Pylint 在我们将错误添加到代码库之前向我们显示错误。在您意外地将大文件提交给 git 之前,大文件检查会向您发出警告。这种意外事故很难逆转,所以最好提前预防。

您甚至可以将自己的预提交挂钩编码为 bash 脚本,以满足定制需求。例如,您可以要求在提交代码之前运行测试。

有关使用 bash 编写自己的预提交钩子的更多信息,请查看这篇文章!

https://medium.com/@edkrueger_16881/how-to-code-your-own-python-pre-commit-hooks-with-bash-171298c6ee05

Python 虚拟环境入门

原文:https://towardsdatascience.com/getting-started-with-python-virtual-environments-252a6bd2240?source=collection_archive---------1-----------------------

入门

避免 python 项目间冲突的简短指南

如果您刚刚开始使用 python 进行数据科学或开发,您可能会遇到一个常见的初学者问题——为什么您的项目在从事其他工作一段时间后不再运行。您可能也不知道您的 python 包存储在哪里,或者不知道如何在项目之间管理不同版本的 python。好了,松一口气吧,虚拟环境已经来拯救我们了(实际上它们已经存在很长时间了。长到找不到参考文献……)。

不要让你的 python 和你的头发纠缠在一起,使用虚拟环境。图片是卡拉瓦乔的美杜莎,来源于维基共享。

它们是什么?

简单地说,Python 虚拟环境是一个独立 python 在您的计算机上运行的封闭环境🐍。这意味着您可以拥有单独的虚拟环境,为您的每个项目提供单独版本的 python 和 python 包。因此,您可以在一个项目上安装或删除 python 包,这不会影响您可能拥有的任何其他项目。

注意:本指南假设您已经安装了 python 3。如果没有,请访问https://www.python.org/获取安装说明。

你把它们放在哪里?

有些人喜欢把他们所有的 python 虚拟环境放在一个文件夹中,然而,我发现这种方法很难跟踪什么环境属于什么项目。对于 python 虚拟环境,一个更常见的做法是将它们放在每个项目的根目录下。

例如,如果您有一个名为“example_project”的项目,您可以将当前目录更改到那里

cd example_project

然后按照以下步骤创建您的虚拟环境。

创建虚拟环境

人们用来创建虚拟环境的一种常见方式是使用一个名为 virtualenv 的 python 包,但从 python 3.3 版本开始,virtualenv 的部分内容实际上是以模块名venv内置到 python 中的。现在,您可以使用以下命令创建虚拟环境:

python3 -m venv venv

这是怎么回事?

  • 嗯,python3就是你安装的 python。如果你安装的 python 版本叫pythonpython3.7或者python3.9或者别的什么,那就用那个;
  • -m venv是一个告诉 python 运行虚拟环境模块的参数,venv
  • 最后,最后一个venv是虚拟环境文件夹的名称。有些人喜欢用另一个名字(如 env 或。env),不过,这完全取决于你。

这个命令应该做的是在当前目录下创建一个名为 venv 的 python 虚拟环境。

注意:如果你使用 git,你会想把 *venv/* 添加到一个名为。gitignore 确保你不会对你的虚拟环境进行版本控制。如果您忘记了这一步,那么您的 git 存储库可能会被数百个额外的版本控制文件堵塞。

一旦你创建了你的虚拟环境,你就不需要再这样做了。现在,您将能够按照以下步骤使用您的环境。

如何使用它们

要使用虚拟环境,您需要使用以下命令“激活”该环境:

(在 MacOS 和 Linux 上)

source venv/bin/activate

或(Windows)

venv\Scripts\activate

如果您在 MacOS 或 Linux 上使用 fish shell(像我一样),您需要将上面的 MacOS 或 Linux 命令替换为:

source venv/bin/activate.fish

上述命令所做的是改变命令pythonpip(python 包管理器)来引用那些位于 venv 文件夹中的命令。应该会出现一个有用的指示器,显示您正在使用虚拟环境,如下所示:

(venv) $

这意味着当您安装带有 pip 的软件包时,例如

pip install numpy

现在,您将把它安装到 venv 文件夹中的虚拟环境中。如果您愿意,您应该能够查看您在venv/lib/python3.9/site-packages中安装的包的文件。如果不同,您必须用python3.9替换您的版本。

按照上面的步骤操作,应该会看到类似下面 GIF 的东西。

创建虚拟环境。图片作者。

继续这个例子,如果您现在以交互模式启动 python,您将能够使用以下命令访问这些包:

pythonimport numpy as npprint(np.sqrt(5))

如果一切正常,您应该会看到类似下面的内容:

使用虚拟环境。图片作者。

在使用 python 运行 python 文件时,您还应该能够访问您安装的任何包。例如,如果您想使用虚拟环境中包含的 python 来运行一个名为“main.py”的文件,您可以使用以下命令:

python main.py

完成虚拟环境后,您可以关闭终端,或者使用如下命令停用环境:

deactivate

如果需要的话,这也将允许您为您的另一个项目激活一个不同的虚拟环境。

复制你的环境

为了重现 python 虚拟环境(例如,在另一台机器上),通常需要将安装的包保存到一个文件中。这将允许任何拥有您的文件的人安装您在开发项目时使用的相同版本的包。然而,你可能还是想告诉他们你使用的 python 版本。通常人们喜欢使用一个名为“requirements.txt”的文件来实现这个目的。

如果您已经激活了 python 虚拟环境,那么您可以自动生成 requirements.txt 文件,包含以下内容:

pip freeze > requirements.txt

您也可以编辑这个文件或者手动创建一个,如果您愿意的话(例如,您不想对包的版本要求如此严格)。更多详情见此处。

因此,如果您或其他人想要创建一个虚拟环境并使用与您相同的包,他们可以按照上面的命令创建并激活一个虚拟环境,然后安装您的需求。可以使用 pip 的-r 方法安装需求,如下所示:

pip install -r requirements.txt

现在去哪里?

我已经向您展示了使用 python 的虚拟环境的最简单和标准的方法,但是,如果您愿意,您可以使用虚拟环境和 python 的各种方法。大多数情况下,这些都不是不必要的,但是如果您愿意,一些著名的包提供了一种不同的方式来处理虚拟环境和包,它们是:

  • 诗歌【https://python-poetry.org/】T2,还有
  • https://www.anaconda.com/products/individual[康达](https://www.anaconda.com/products/individual)

如果你已经走了这么远,谢谢你。我希望这篇文章能帮助您在数据科学(或您所做的任何事情)之旅中取得更大的进步。如果你喜欢这篇文章,请鼓掌并关注我,让我有动力写更多。如果你有任何问题,请在下面补充。

PyTorch 入门

原文:https://towardsdatascience.com/getting-started-with-pytorch-2819d7aeb87c?source=collection_archive---------9-----------------------

入门

通过示例学习基础知识

照片由来自 Pexels 的杰瑞米·毕夏普拍摄

介绍

在我之前的帖子“Tensorflow入门”中,我提到如果你想构建小型或大型深度学习解决方案,tensor flow 和 PyTorch 都是很好的选择。这两个平台都广泛应用于学术界和工业界,维护良好,是开源的,提供简单的 API 和高级功能。

在这里,我们将探索 PyTorch API。在“【Tensorflow 入门”的同时,我们将讨论 PyTorch 是如何产生的,以及如何将其用于深度学习。

PyTorch 是什么时候开发的?

大约在 PyTorch 0.1.1 版本于 2016 年 9 月发布时,有多个深度学习框架可用,为构建和训练复杂模型提供了低级和高级包装器。

Caffe、Chainer、Theano、Tensorflow、CNTK、MXNet 和 Torch 只是研究人员用来构建日益复杂的网络的几个低级库。

另一方面,Lasagne 和 Keras 专注于创建可以使用许多低级库之一的高级包装器。这种方法得到了从业者的大力支持,因为它允许他们从 Tensorflow、CNTK 或 Theano 等语言的低级语法中进行抽象。

在接下来的几年里,随着 frameworks⁴:的放弃和巩固,情况发生了巨大的变化

  • Keras 被并入 Tensorflow,大大改变了方向;
  • Caffe 2 被合并到 PyTorch 中,取代了 Torch 祖先的部分原始 Lua 实现;
  • Theano、CNTK 和 Chainer 的开发和支持已停止。

谷歌在“机器学习和人工智能”类别下搜索 2017 年 1 月至 2021 年 7 月之间的顶级低/高级深度学习框架(Tensorflow、Keras、PyTorch)。为了进行比较,还显示了合并的 Tensorflow+Keras 和 PyTorch+Caffe2。图片由作者提供。

到 2021 年 6 月,超过 99%的谷歌搜索主要深度学习框架包含 Tensorflow/Keras 或 PyTorch/Caffe,其中第一个仍然明显更受欢迎(见图表)。

通过例子学习

在下面的小节中,我将介绍在 PyTorch 中构建两个简单神经网络的关键概念(一个用于回归,一个用于分类)。

为了使本教程与我之前的帖子“tensor flow入门”相媲美,我将重复使用相同的模拟数据集。为了使本教程自成一体,我将在这里再次重新介绍它们。

线性回归

在此示例中,我们将在 PyTorch 中构建一个简单的 1 层神经网络来解决线性回归问题。这将解释如何初始化你的权重(又名回归系数),以及如何通过反向传播来更新它们。

我们首先需要的是一个数据集。这里,我们将模拟一个噪声线性模型,如下所示

其中 Y 是我们的目标,X 是我们的输入,w 是我们要确定的系数,N 是高斯分布噪声变量。为此,在笔记本的第一个单元格中粘贴并运行以下代码片段。

这将显示 X 和 Y 之间关系的散点图,清楚地表明在一些高斯噪声下的线性相关性。在这里,我们期望一个合理的模型来估计 2 作为理想的回归系数。

代表高斯噪声下 X 和 Y 之间线性相关性的模拟数据。

在 PyTorch 中,我们通常使用张量来表示我们的输入、目标和回归系数(这里称为权重)。张量是由火炬表示的多维元素阵列。张量的对象。张量只有一种数据类型和一种形状。

现在让我们将输入(x)和目标(y)转换成火炬张量。为此,在 Colab 中复制并运行以下代码片段。

这将返回类(火炬。张量)、输入和目标张量的形状、大小和值。

Describing the features...
<class 'torch.Tensor'>
torch.float64
torch.Size([1000])
tensor([0.0000, 0.0010, 0.0020, 0.0030, 0.0040, 0.0050, 0.0060, 0.0070, 0.0080,
        0.0090], dtype=torch.float64) Describing the target...
<class 'torch.Tensor'>
torch.float64
torch.Size([1000])
tensor([ 0.1587, -0.6984,  0.1692,  0.1368,  0.1386,  0.0854,  0.2807,  0.2895,
         0.5358,  0.3550], dtype=torch.float64)

现在让我们用一个常数(0.1)开始我们的权重。为此,我们调用“torch.tensor ”,缺省值为 0.1,需要的数据类型(float)和存储张量的设备。在本例中,我们将在“cpu”中执行所有操作。为了提高大型神经网络模型的性能,我们可以将张量移至“gpu”。

运行这个代码片段将输出权重张量的类、形状、类型和值。注意,这个张量有一个“[]”形状,表示它是一个 0 维向量。

Describing the weights… 
<class ‘torch.Tensor’> 
torch.float32 torch.Size([]) 
tensor(0.1000, requires_grad=True)

给定初始化的权重张量和输入 X,为了获得预测的 Y (Yhat ),我们可以简单地调用 Yhat = x * w _ tensor.detach()。numpy()'。的’。分离()。“numpy()”用于将权重向量转换为 numpy 数组。复制并运行下面的代码片段,看看初始化后的重量如何符合数据。

正如你所观察到的,‘w _ tensor’的当前值与理想值相差甚远。回归线完全符合数据。

训练前模型拟合的表示。

为了找到‘w _ tensor’的最佳值,我们需要定义一个损失度量和一个优化器。这里,我们将使用均方误差(MSE)作为我们的损失度量,随机梯度下降(SGD)作为我们的优化器。

我们现在有了优化我们的“w _ 张量”的所有部分。优化循环需要自定义“前进”步骤的定义,从我们的损失度量调用“后退”步骤方法,从我们的优化器调用“步骤”方法。

自定义的“前进”步骤告诉模型如何将输入与权重张量相结合,以及如何计算我们的目标与预测目标之间的误差(下面代码片段中的第 5 行到第 8 行)。在一个更复杂的例子中,这将是一组定义从输入 X 到目标 y 的计算图的指令。

“向后”步骤告诉模型将错误反向传播到网络中的每一层(下面代码片段中的第 22 行)。

最后,“optimizer.step()”告诉模型计算并应用这次迭代的权重变化(下面代码片段中的第 23 行)。注意,在大多数情况下,您需要在调用优化器步骤之前清除梯度(下面代码片段中的第 21 行)。

在训练结束时,你的体重应该接近 2(理想值)。要使用该模型进行推理(即,在给定 X 值的情况下预测 Y 变量),只需执行“Yhat = x * w_tensor.detach()。numpy()'。

训练后模型拟合的表示。

分类问题

在本例中,我们将引入 PyTorch NN 顺序模型定义来创建一个更复杂的神经网络。如果你习惯 Keras,这个模块看起来会很熟悉。我们将把这个模型应用于一个线性可分的分类问题。

像以前一样,让我们从构建数据集开始。在下面的代码片段中,我们为第一个聚类创建了两个以(0.2,0.2)为中心的点聚类,为第二个聚类创建了两个以(0.8,0.8)为中心的点聚类。

我们可以很快观察到,用一条与两个聚类距离相等的线将两个数据集线性分离的模型是理想的。

模拟数据表示两个数据聚类,第一个聚类以(0.2,0.2)为中心,第二个聚类以(0.8,0.8)为中心。

让我们从定义自定义 NN 模型来解决这个问题开始。我们将定义一个 5 层神经网络如下:

  1. 有 10 个节点的线性层。这将有一个 2 x 10(输入形状 x 图层大小)的形状。
  2. 批量标准化层。这一层将对每一批的第一层的输出进行归一化,避免爆炸/消失梯度。
  3. Relu 激活层。这一层将为我们的网络提供非线性能力。请注意,我们仅以此为例。对于这个问题,relu 层是不必要的,因为它是线性可分离的。
  4. 具有两个节点的线性层。这将有一个 10 x 2(层大小 x 输出形状)的形状。
  5. Softmax 层。该层会将第 4 层的输出转换为 softmax。

和以前一样,让我们也将 x 和 y numpy 数组转换成张量,使它们对 PyTorch 可用,然后定义我们的损失度量和优化器。在这个例子中,我们应该使用分类损失度量,例如交叉熵。

对于优化器,我们可以像以前一样使用 SGD。然而,普通 SGD 的收敛速度慢得令人难以置信。相反,我们将使用最近的自适应梯度下降方法(RMSProp)。

和以前一样,我们先来检查一下我们的网络在训练前表现如何。要使用该模型进行推理,我们可以简单地键入“yhat = model(x)”。现在,复制下面的片段来可视化网络输出。

你可以确认网络一点也不好。显然需要一些训练来正确区分这两个类别。

训练前模型拟合的表示。

为了训练顺序 PyTorch 模型,我们遵循与第一个示例相同的步骤,但是用模型调用替换了自定义的“前进”步骤。将下面的片段添加到您的笔记本中,以训练模型。

在训练循环结束时,你的网络应该能够很好地分离这两个类。要使用该模型进行推理(即,在给定 X 值的情况下预测 Y 变量),您可以简单地执行“yhat = model(x)”。

训练后模型拟合的表示。

完整脚本

如需完整的脚本,请点击以下链接进入我的 github 页面:

https://github.com/andreRibeiro1989/medium/blob/main/pytorch_getting_started.ipynb

或者通过以下链接直接访问 Google Colab 笔记本:

https://colab.research.google.com/github/andreRibeiro1989/medium/blob/main/pytorch_getting_started.ipynb

结论

PyTorch 是目前开发定制深度学习解决方案的最佳深度学习框架之一(另一个是 Tensorflow)。在这篇博客中,我介绍了在 PyTorch 中构建两个简单 NN 模型的关键概念。

**警告!!!**正如我在《【Tensorflow 入门中提到的,你的学习才刚刚开始。要变得更好,你需要不断练习。官方 Pytorch 网站提供了从初学者到专家级别的示例,以及 Pytorch 软件包的官方文档。祝你好运!

1钦塔拉,苏密特。 PyTorch Alpha-1 发布(2016 年 9 月)
https://github.com/pytorch/pytorch/releases/tag/v0.1.1

[2]因陀罗·登·贝克。"深度学习框架之战—第一部分:2017,更多框架和接口"
https://towardsdatascience . com/Battle-of-the-Deep-Learning-frameworks-Part-I-cff0e 3841750

[3]麦迪逊·梅。"Python 深度学习框架概述"
https://www . kdnugges . com/2017/02/Python-Deep-Learning-Frameworks-Overview . html

[4]伊莱·史蒂文斯、卢卡·安提卡、托马斯·维赫曼。"用 PyTorch 进行深度学习"
https://py torch . org/assets/Deep-Learning/Deep-Learning-with-py torch . pdf

R Shiny 入门

原文:https://towardsdatascience.com/getting-started-with-r-shiny-821eb0328e73?source=collection_archive---------4-----------------------

向成为一名闪亮的专家迈出第一步

照片由卢克·切瑟在 Unsplash 上拍摄

R 闪亮简介

Shiny 是一个 R 包,它允许程序员在 R 中构建 web 应用程序。对于像我这样发现用 Java 构建 GUI 应用程序非常困难的人来说,Shiny 让它变得容易多了。

这篇博客文章将让你用工作示例直接构建闪亮的应用程序。首先,确保你安装了闪亮的软件包。

install.packages("shiny")

闪亮的应用程序结构

和 R 文件一样,闪亮的应用也以*结尾。r 分机。*app 结构由三部分组成,分别是:

  1. 一个用户界面对象 (ui)
  2. 服务器功能
  3. 对 shinyApp 的函数调用

用户界面(ui)对象用于管理应用程序的外观和布局,如单选按钮、面板和选择框。

*# Define UI for app* 
ui <- fluidPage(

  *# App title ----*
  titlePanel("!"),

  *# Sidebar layout with input and output definitions ----*
  sidebarLayout(

    *# Sidebar panel for inputs* 
    sidebarPanel(

    )*# Allow user to select input for a y-axis variable from drop-down*
       selectInput("y_varb", label="Y-axis variable",choices=names(data)[c(-1,-3,-4)]),*# Output: Plot*
      ("plot", dblclick = "plot_reset"))

server函数包含构建应用程序所需的信息。例如,这包括生成图或表以及对用户点击做出反应的指令。

*# Define server logic here ----*
server <- **function**(input, output) {

  *# 1\. It is "reactive" and therefore updates x-variable based on y-        variable selection* *# 2\. Its output type is a plot*
  output$distPlot <- renderPlot({

    remaining <- reactive({
    names(data)[c(-1,-3,-4,-match(input$y_varb,names(data)))]
  })

  observeEvent(remaining(),{
    choices <- remaining()
    updateSelectInput(session = getDefaultReactiveDomain(),inputId = "x_varb", choices = choices)
  })

}output$plot <- renderPlot({
    #ADD YOUR GGPLOT CODE HERE
    subset_data<-data[1:input$sample_sz,]
    ggplot(subset_data, aes_string(input$x_varb, input$y_varb))+
      geom_point(aes_string(colour=input$cat_colour))+
      geom_smooth(method="lm",formula=input$formula)}, res = 96)
}

最后,shinyApp函数基于 UI/服务器对构建闪亮的应用程序对象。

library(shiny)
*# Build shiny object* shinyApp(ui = ui, server = server)
*# Call to run the application*
runApp("my_app")

什么是反应性?

反应性就是把用户输入和应用输出联系起来;以便 Shiny 应用程序中的显示可以根据用户的输入或选择进行动态更新。

反应式编程的构建模块

输入

传递给shinyServer函数的input对象允许用户访问应用程序的输入字段。它是一个类似列表的对象,包含从浏览器发送的所有输入数据,根据输入 ID 命名。

与典型的列表不同,输入对象是只读的。如果您试图修改服务器函数内部的输入,您将会得到一个错误。输入只能由用户设置。这是通过创建一个反应表达式来完成的,其中一个普通表达式被传递到reactive。要从输入中读取数据,您必须处于由像renderText()reactive().这样的函数创建的反应上下文中

输出

为了允许在应用程序中查看反应值或输入,需要将它们分配给output对象。和input对象一样,它也是一个类似列表的对象。它通常与类似renderTable.render功能一起工作

render功能执行以下两个操作:

  1. 它设置了一个反应上下文,用于自动将输入与输出关联起来。
  2. 它将 R 代码输出转换为 HTML 代码,以便在应用程序上显示。

反应式表达

反应式表达式用于将应用程序中的代码分割成相当大的代码块,这不仅可以减少代码重复,还可以避免重新计算。

在下面的例子中,反应代码接收来自用户的四个输入,然后用于输出独立样本 t 检验的结果。

server <- function(input, output) {x1 <- reactive(rnorm(input$n1, input$mean1, input$sd1))x2 <- reactive(rnorm(input$n2, input$mean2, input$sd2))output$ttest <- renderPrint({t.test(x1(), x2())})}

闪亮的应用示例

现在,我们知道一些基础知识,让我们建立一些应用程序。

应用一

该应用程序使用一个虚拟数据集,其中包括三个连续变量。对应用程序的要求如下:

  1. 在数据集中三个连续变量中的两个之间生成散点图,其中第一个变量不能相对于自身绘制。
  2. 用户可以选择 x 和 y 变量进行绘图
  3. 用户可以选择绘图公式(“yx”,“ypoly(x,2)”,“y~log(x)”)。
  4. 选择的分类变量用于给散点图中的点着色
  5. 用户可以选择行数(样本大小),范围从 1 到 1,000,用于绘图。
*#Load libraries*
library(shiny)
library(ggplot2)***#Create dummy dataset***
k<-1000
set.seed(999)
data<-data.frame(id=1:k)
data$gest.age<-round(rnorm(k,34,.5),1)
data$gender<-factor(rbinom(k,1,.5),labels=c("female","male"))
z =  -1.5+((((data$gest.age-mean(data$gest.age)))/sd(data$gest.age))*-1.5)
pr = 1/(1+exp(-z))
data$mat.smoke = factor(rbinom(k,1,pr))
data$bwt<- round(-3+data$gest.age*0.15+
                   ((as.numeric(data$mat.smoke)-1)*-.1)+
                   ((as.numeric(data$mat.smoke)-1))*((data$gest.age*-0.12))+
                   (((as.numeric(data$mat.smoke)-1))*(4))+
                   ((as.numeric(data$gender)-1)*.2)+rnorm(k,0,0.1),3)
data$mat.bmi<-round((122+((data$bwt*10)+((data$bwt^8)*2))/200)+
                      rnorm(k,0,1.5)+(data$gest.age*-3),1)rm(z, pr, k)***#Define UI***
ui <- fluidPage(

 ***#1\. Select 1 of 3 continuous variables as y-variable and x-variable***
  selectInput("y_varb", label="Y-axis variable",choices=names(data)[c(-1,-3,-4)]),
  selectInput("x_varb", label="X-axis variable", choices=NULL),   ***#2\. Colour points using categorical variable (1 of 4 options)***
  selectInput("cat_colour", label="Select Categorical variable", choices=names(data)[c(-1,-2,-5,-6)]),  ** *#3\. Select sample size***
  selectInput("sample_sz", label = "Select sample size", choices = c(1:1000)),
  #4\. Three different types  of linear regression plots
  selectInput("formula", label="Formula", choices=c("y~x", "y~poly(x,2)", "y~log(x)")),
  #5\. Reset plot output after each selection
  plotOutput("plot", dblclick = "plot_reset")

)
server <- function(input, output) {

  ***#1\. Register the y-variable selected, the remaining variables are now options for x-variable***
  remaining <- reactive({
    names(data)[c(-1,-3,-4,-match(input$y_varb,names(data)))]
  })

  observeEvent(remaining(),{
    choices <- remaining()
    updateSelectInput(session = getDefaultReactiveDomain(),inputId = "x_varb", choices = choices)
  })

  output$plot <- renderPlot({
    ***#Produce scatter plot***
    subset_data<-data[1:input$sample_sz,]
    ggplot(subset_data, aes_string(input$x_varb, input$y_varb))+
      geom_point(aes_string(colour=input$cat_colour))+
      geom_smooth(method="lm",formula=input$formula)}, res = 96)
}***# Run the application*** 
shinyApp(ui = ui, server = server)

图 1:用户必须从 5 个不同的输入中进行选择

一旦用户选择了输入,就会生成下面的散点图。

图 2:应用一的输出图

这就是你的第一个 web 应用程序。然而,让我们进一步分解代码。

App 一解释

功能selectInput用于显示下拉菜单,供用户选择绘图变量、散点图中各点的着色变量以及样本大小。

server函数中,基于用户对 y 变量的选择,用户对 x 变量的选择被更新。observeEvent函数用于响应事件执行动作。在这个例子中,它更新了可以为 x 轴选择的 x 变量列表;因此不能在 y 轴和 x 轴上绘制同一个变量。

然后使用函数renderPlot获取所有输入,x 变量、y 变量、分类变量、样本大小和公式,以生成或“呈现”一个图。

这就是你的第一个闪亮的应用程序。

现在,如果我们希望下拉菜单是一个滑块。您可以通过在中添加以下代码片段来修改代码。

ui <- fluidPage(

  #3\. Select sample size
  # numericInput("sample_sz", "Input sample size", 10000),
  sliderInput(inputId = "sample_sz",
              label = "Select sample size:",
              min = 1,
              max = 10000,
             value = 1)
)

输出将类似于

图 App One 的输出显示了样本大小的滑块

现在,让我们进入下一个稍微复杂一点的例子。

应用二

在这个应用程序中,我们正在查看一个数据集,该数据集显示了新冠肺炎感染导致的五种威胁生命的后果。我们希望该应用程序能够做到以下几点:

  1. 允许用户从五个结果中选择一个作为输入
  2. 通过森林地块中选定的结果比较不同的县
  3. 如果用户在图中选择了一个县,那么应该生成另一个森林图,显示所选国家的所有五个结果。
  4. 显示缺少值的错误消息。
#Load libraries
library(shiny)
library(ggplot2)
library(exactci)#import the data and restrict the data to variables and patients of interest

patient.data<-read.csv("Synthea_patient_covid.csv", na.strings = "")
cons.data<-read.csv("Synthea_conditions_covid.csv", na.strings = "")
data<-merge(cons.data, patient.data)
data<-data[which(data$covid_status==1),] 
data<-data[,c(12,14,65,96,165,194)]#Get the state average for each outcome
state.average<-apply(data[,-6],MARGIN=2,FUN=mean)#Make better names for the outcomes
names<-c("pulmonary embolism", "respiratory failure", "dyspnea", "hypoxemia", "sepsis")#Calculate and aggregate the obs and exp by outcome and county
data$sample.size<-1
list<-list()
for (i in 1:5) {
  list[[i]]<-cbind(outcome=rep(names[i],length(unique(data$COUNTY))),
                   aggregate(data[,i]~COUNTY, sum,data=data),
                   exp=round(aggregate(sample.size~COUNTY, sum,data=data)[,2]
                             *state.average[i],2))
}
plot.data<-do.call(rbind,list)
names(plot.data)[3]<-"obs"#Lastly, obtain the smr (called est), lci and uci for each row
#Add confidence limits
plot.data$est<-NA
plot.data$lci<-NA
plot.data$uci<-NA
#Calculate the confidence intervals for each row with a for loop and add them to the plot.data
for (i in 1:nrow(plot.data)){
  plot.data[i,5]<-as.numeric(poisson.exact(plot.data[i,3],plot.data[i,4],
                                           tsmethod = "central")$estimate)
  plot.data[i,6]<-as.numeric(poisson.exact(plot.data[i,3],plot.data[i,4],
                                           tsmethod = "central")$conf.int[1])
  plot.data[i,7]<-as.numeric(poisson.exact(plot.data[i,3],plot.data[i,4],
                                           tsmethod = "central")$conf.int[2])
}# Define UI for application 
ui <- fluidPage(
  selectInput("outcome_var", label="Outcome",unique(plot.data$outcome)),
  plotOutput("plot", click = "plot_click"),
  plotOutput("plot2")
)
server <- function(input, output) {

  output$plot <- renderPlot({#Output error message for missing values
    validate(
      need( nrow(plot.data) > 0, "Data insufficient for plot")
    )
    ggplot(subset(plot.data,outcome==input$outcome_var), aes(x = COUNTY,y = est, ymin = pmax(0.25,lci), 
                               ymax = pmin(2.25,uci))) +
      geom_pointrange()+
      geom_hline(yintercept =1, linetype=2)+
      coord_flip() +
      xlab("")+ ylab("SMR (95% Confidence Interval)")+
      theme(legend.position="none")+ ylim(0.25, 2.25)
  }, res = 96)

  #Output error message for missing values
  #modify this plot so it's the same forest plot as above but shows all outcomes for the selected county

  output$plot2 <- renderPlot({validate(
      need( nrow(plot.data) > 0, "Data insufficient for plot as it contains a missing value")
    )
    #Output error message for trying to round a value when it doesn't exist/missing
    validate(
      need( as.numeric(input$plot_click$y), "Non-numeric y-value selected")
    )

    forestp_data<-plot.data[which(plot.data$COUNTY==names(table(plot.data$COUNTY))[round(input$plot_click$y,0)]),] 
    ggplot(forestp_data, aes(x = outcome,y = est, ymin = pmax(0.25,lci), ymax = pmin(2.25,uci))) +
      geom_pointrange()+
      geom_hline(yintercept =1, linetype=2)+
      coord_flip() +
      xlab("")+ ylab("SMR (95% Confidence Interval)")+
      theme(legend.position="none")+ ylim(0.25, 2.25)
  })  

}# Run the application 
shinyApp(ui = ui, server = server)

App 二解说

在这个应用程序中,像 App One 一样,用户从下拉框中选择一个结果。这产生了一个森林地块。这个森林图的计算是在闪亮的用户界面之外完成的。这个应用程序中的棘手之处是构建一个反应性的第二个图,以响应用户在第一个图中单击的 county。

这种反应发生在使用以下代码行的服务器函数中

plot.data[which(plot.data$COUNTY==names(table(plot.data$COUNTY))[round(input$plot_click$y,0)]),]

在这里,我们检查选择了哪个县,以便显示所有五个结果的第二个森林图。

图 App 2 中的第一个森林图是基于选择的结果生成的

图 5:单击给定县的第一个森林图,生成下面的第二个图,显示所选县的所有五个结果

在应用程序中,使用validate功能显示一条错误消息,如果有数据丢失,则会显示一条由以下语法导致的错误:

[round(input$plot_click$y,0)],]

应用三

最终的 web 应用程序的目标是允许用户绘制数据集中变量之间的关系。一些变量是分类的,而另一些是连续的。当绘制两个连续变量时,用户应该只能在散点图上绘制它们。当选择了一个连续变量和一个分类变量时,用户应该只能绘制箱线图。用户不应该能够用两个分类变量绘图。根据用户的选择,应用程序应该一次只显示一个图。

#Load libraries
library(shiny)
library(ggplot2)#import data
setwd("C:/Users/User/Desktop/Synthea")
patient.data<-read.csv("Synthea_patient_covid.csv", na.strings = "")
obs.data<-read.csv("Synthea_observations_covid.csv", na.strings = "")patient.data$dob<-as.Date(patient.data$BIRTHDATE, tryFormats = "%d/%m/%Y")
patient.data$enc.date<-as.Date(patient.data$DATE, tryFormats = "%d/%m/%Y")
patient.data$age<-as.numeric((patient.data$enc.date-patient.data$dob)/365.25)
data<-merge(obs.data, patient.data)
data<-na.omit(data[,c(4,5,10:12,20,24,32,18,15,23,31,33,48:51,60)])
names(data)<-substr(names(data),1,10)
data$covid_stat<-as.factor(data$covid_stat)
data$dead<-as.factor(data$dead)# Define UI for application 
ui <- fluidPage(
  #1\. Select 1 of many continuous variables as y-variable 
  selectInput("y_varb", label="Y-axis variable",choices=names(data)[c(-1,-2,-14,-15,-16,-17)]),

  #2 Select any variable in dataset as x-variable
  selectInput("x_varb", label="X-axis variable", choices=names(data)),

  #3\. Reset plot1 output after each selection
  plotOutput("plot", dblclick = "plot_reset"))
server <- function(input, output) {

  remaining <- reactive({
    names(data)[-match(input$y_varb,names(data))]
  })

  observeEvent(remaining(),{
    choices <- remaining()
    updateSelectInput(session = getDefaultReactiveDomain(),inputId = "x_varb", choices = choices)
  })

  output$plot <- renderPlot({if ( is.numeric(data[[input$x_varb]]) ) {
      ggplot(data, aes_string(input$x_varb, input$y_varb)) + geom_point()  
    } else {
      ggplot(data, aes_string(input$x_varb, input$y_varb)) + stat_boxplot()
    }})

}# Run the application 
shinyApp(ui = ui, server = server)

图 6:选择分类变量和连续变量时显示的箱线图

图 7:如果选择了两个连续变量,则显示散点图

App 三解说

这个应用程序中的巧妙之处在于使用了renderPlot中的 if-else 条件,因此只能选择两种类型的图(散点图或箱线图)中的一种。此外,当你想检查input$x_varb的类时,使用双方括号(list)是必需的,data[[input$x_varb]],否则输出将总是字符。

结论

现在,你有了三个简单的应用程序。让我们快速回顾一下这篇博客文章的内容。

  • 一个闪亮的应用程序的结构
  • 连接输入和输出
  • 使用 reactive()和 observeEvent 创建动态用户界面
  • 使用验证显示错误消息

强化学习入门

原文:https://towardsdatascience.com/getting-started-with-reinforcement-learning-cf2f2655854?source=collection_archive---------20-----------------------

揭秘一些与强化学习相关的主要概念和术语,以及它们与人工智能其他领域的关联

列宁·艾斯特拉达在 Unsplash 上的照片

介绍

今天,人工智能(AI)经历了令人印象深刻的进步。根据机器逻辑地和独立地执行智力任务的能力,人工智能可以细分为三个不同的级别:

  • 狭义 AI :机器在执行非常具体的任务(但不试图执行其他类型的任务)时比人类更有效率。
  • 通用 AI :机器和人类一样聪明。
  • 强 AI :机器在不同领域(在我们可能或根本无法执行的任务中)表现得比人类更好。

现在,由于机器学习,我们已经能够在狭窄的人工智能水平上实现良好的能力。使用的机器学习算法主要有三种类型:

  • 监督学习: 使用带标签的训练集训练一个模型,然后对无标签的数据进行预测。
  • 无监督学习: 给一个模型一个未标记的数据集,然后模型要试着在数据中寻找模式来做预测。
  • 强化学习: 通过奖励机制训练模型,在表现良好的情况下鼓励积极的行为(特别用于基于代理的模拟、游戏和机器人)。

强化学习,现在被认为是最有前途的技术,以便进入人工智能范式的下一个阶段(图 1)。

图 1:强化学习代理玩超级马里奥1

强化学习

强化学习今天获得如此多兴趣的原因之一是它的跨学科性。这个领域的核心概念,事实上遵循基本的博弈论、进化和神经科学原则。

与所有其他形式的机器学习相比,RL 实际上可以被认为是试图复制人类和动物如何学习的最接近的近似方法。

强化学习主张人类最常使用的主要学习方式是通过使用他们的传感器和与环境交互(因此不需要像监督学习那样的外部指导,而是通过试错过程)。

在日常生活中,我们试图完成新的任务,根据我们尝试的结果,我们会影响周围的环境。通过评估我们的尝试,我们可以从经验中学习,以确定哪些行为给了我们更大的好处(因此最方便重复),哪些行为应该避免。图 2 总结了这个迭代过程,它代表了大多数基于强化学习的算法的主要工作流程。

一个代理(如软件机器人,机器人)被放置在一个环境中,通过与它的互动,可以学习,接收新的刺激和创造新的状态(如解锁一个新的场景或修改现有场景的结构)。然后,我们的代理的每一个动作都与一个奖励值相关联,以评估其实现预定目标的效率。

图 2:强化学习工作流程[2]

表征强化学习系统的两个主要挑战是:

  • 与此同时,如果代理人甚至不尝试不同的行动,它可能永远不会发现更好的奖励是可能实现的。
  • 延迟奖励的处理 :代理不被告知要尝试什么动作,而是应该想出不同的解决方案,测试它们,最后根据收到的奖励进行评估。代理不应仅根据眼前的回报来评估他们的行为。事实上,选择某种类型的行动可能会带来更大的回报,不是立即的,而是长期的。

核心组件

根据 Richard S. Sutton 等人[3]的观点,强化学习算法由 4 个主要的关键部分组成:策略、奖励、价值函数和环境模型。

  • 策略: 定义代理行为(将不同的状态映射到动作)。政策最有可能是随机的,因为每个特定的行动都与被选择的概率相关联。
  • 奖励: 是一个信号,用来提醒代理应该如何最好地修改它的策略,以达到规定的目标(在短时间内)。每当执行一个动作时,代理从环境接收一个奖励。
  • 价值函数: 是为了获得一种感觉,什么行为从长远来看能带来更大的回报。它的工作原理是给不同的状态赋值,以评估如果从任何特定的状态出发,一个代理应该期望什么样的回报。
  • 环境模型: 模拟智能体所处环境的动态,以及环境应该如何响应智能体采取的不同动作。取决于应用,一些 RL 算法不一定需要环境模型(无模型方法),因为可以使用试错法来接近它们。但是,基于模型的方法可以使 RL 算法处理需要规划的更复杂的任务。

结论

如果你有兴趣了解更多关于强化学习的内容,理查德·萨顿和安德鲁·g·巴尔托的《强化学习:导论》和《开放人工智能健身房》将在我的下一篇文章中讨论。)是两个很好的起点。

希望您喜欢这篇文章,感谢您的阅读!

联系人

如果你想了解我最新的文章和项目,请在媒体上关注我,并订阅我的邮件列表。以下是我的一些联系人详细信息:

  • 领英
  • 个人博客
  • 个人网站
  • 中等轮廓
  • GitHub
  • 卡格尔

文献学

1强化学习,Gfycat。访问时间:https://gfycat.com/gifs/search/reinforcement+learning

[2]强化学习—第 1 部分:Q-学习简介,Novatec。访问:https://www . novatec-gmbh . de/en/blog/introduction-to-q-learning/

[3]强化学习:导论,理查德·萨顿和安德鲁·巴尔托。麻省理工学院出版社剑桥,马萨诸塞州伦敦,英国。访问:https://web . Stanford . edu/class/psych 209/Readings/suttonbartoiprlbook 2 nded . pdf

在 AWS SageMaker 上用 PyTorch 和拥抱脸变形金刚微调 BERT

原文:https://towardsdatascience.com/getting-started-with-sagemaker-for-model-training-512b75eae7d7?source=collection_archive---------18-----------------------

现实世界中的数据科学

使用 PyTorch、BERT 和 Amazon SageMaker 构建最先进的文本分类器的分步指南

在本教程中,我将向您展示如何在亚马逊 SageMaker 上构建和训练一个文本分类器。我们将利用出色的拥抱脸变形金刚库来训练一个最先进的 NLP 模型来对亚马逊书评进行分类。

云技术正成为数据科学家工作中越来越重要的一部分,AWS 技能非常受欢迎。我的目标是通过一步一步地指导您完成这一过程,消除新手无法使用云工具的常见障碍。

你在学习如何用 SageMaker 训练你的模型之后。

我们开始吧

如果你已经熟悉 SageMaker,只是想看看代码,这里有 repo 。

什么是 SageMaker?

亚马逊 SageMaker 是一个完全托管的机器学习服务,用于构建、培训和部署机器学习模型。SageMaker 内置了几个模型训练的框架( XGBoost 、 BlazingText 等)。),而且还可以使用像 PyTorch 和 TensorFlow 这样的框架轻松创建定制的深度学习模型。

为什么要学 SageMaker?

使用 SageMaker 对数据科学家和工程师有很多好处:

  1. 模特培训。SageMaker 使得利用 GPU 实例进行更快的模型训练变得更加容易。如果没有 GPU,训练许多深度学习架构是难以处理的。例如,微调最先进的语言模型(就像本教程中一样)和计算机视觉模型需要每一步更新数亿个参数。即使不需要,使用 GPU 进行训练也会加快你的开发周期,让你迭代更快交付更多价值
  2. 模型部署。SageMaker 使得将模型部署为可以通过 REST API 访问的生产级端点变得相对简单。您定义了容器、实例类型和一些扩展配置,剩下的由 SageMaker 处理。
  3. 超参数调谐。SageMaker 支持贝叶斯超参数优化用于许多建模框架。这个特性对于快速找到最佳超参数非常有价值。
  4. 这个清单还在继续。AWS 继续向 SageMaker 生态系统添加功能,解决模型监控、跟踪实验等问题。

Google Cloud 和 Azure 提供类似 AWS SageMaker 的解决方案。我选择 AWS 作为本教程的参考,因为它是行业领导者——越来越多的公司使用它,使它成为开发人员更有市场的技能。

使用 SageMaker 进行模型训练

  1. 设置。
  2. 数据。
  3. PyTorch 模型脚本。
  4. 启动模型培训。

设置

对于本教程,您需要创建一个 AWS 帐户,并设置一个 IAM admin 用户,以及一个 SageMaker 角色。您还需要安装和配置 AWS CLI,并创建一个 S3 bucket。按照这里的步骤 1-4开始!

为了访问 GPU,您还需要请求增加服务限制。为此,导航至控制台中的支持中心,点击创建案例。选择服务限制增加,对于限制类型选择 SageMaker 。在此表格中填写您将培训模特的地区:

数据

本指南使用的数据是亚马逊评论数据集的子集,具体来说就是书评,可以点击这里下载。该数据集相当大,因此您可能希望限制本练习的大小。在 GitHub repo 的中的data.zip中可以找到该数据的较小版本。如果您想学习如何自己处理大型数据集,请查看我对在 AWS EMR 上使用 PySpark 的介绍。

使用自定义数据集或在 Kaggle 上找到一个数据集非常容易——你所需要的只是一个包含文本和标签行的文件。

模型

对于本教程,我们将使用来自拥抱脸的变形金刚库。拥抱脸可以很容易地加载预先训练的最先进的语言模型,并在自己的数据集上进行微调。这里使用的具体模型是distil BERT——它是 BERT 的一个分支,更小,因此训练和推理更快更便宜。

微调预先训练好的模型的做法被称为迁移学习— 在这里阅读更多信息。如果你有兴趣了解变革了 NLP 的 transformer 架构的更多信息,我强烈推荐杰伊·阿拉玛的《图解 Transformer》。

创建一个 SageMaker 评估程序脚本

我们需要一个 Python 脚本,将我们的训练数据上传到 S3,定义我们的 SageMaker 估计器,并启动训练作业。您需要更新bucketrole,以反映您在上面的设置部分中创建的存储桶和角色。

  • 第一部分将我们的训练数据上传到 S3,SageMaker 可以访问这些数据。
  • 接下来,我们定义hyperparameters,它实际上只是我们的模型脚本将接受的命令行参数。您可以使您的模型脚本非常灵活,以接受不同的数据预处理和模型训练参数。这在使用 SageMaker 超参数调谐器时非常方便。
  • PyTorch估算器对象中的entry_point定义了我们的模型脚本,这将在下一节中描述。
  • PyTorch估算器对象中的source_dir让我们可以访问utils.py中定义的函数,并安装requirements.txt中定义的包。完整的source_dir可以在这里找到。
  • output_pathPyTorch估计器对象中定义了你的训练模型在 S3 的保存位置。

这是开始模型培训的完整脚本,我们将在创建模型脚本后进行。

模型脚本

在 SageMaker 上编写一个脚本来训练一个模型与在本地机器上做同样的事情没有什么不同。完整的脚本可以在 GitHub repo 中找到。

配置 argparse 以接受命令行参数

在文件底部的if __name__ == “__main__":块中,我们需要利用argparse模块,以便我们的脚本接受超参数作为命令行参数。在这种情况下,超参数可以是您希望传递给模型脚本用于数据预处理和模型训练的任何参数。

创建自定义 PyTorch 数据集

训练模型。

启动模型培训

运行train_model.py并等待任务完成,或者在终端上观看火车模型。

警告:在撰写本文时, *ml.p2.xlarge* 实例每小时的成本为 0.90 美元。运行该脚本还会产生[最低限度的]S3 存储成本。如果您不希望收取月租费,请务必删除 S3 存储桶中的数据。

检查模型输出

通过在 AWS 控制台中搜索 SageMaker 并点击左侧导航栏中的 Training Jobs 来检查 CloudWatch 日志。然后,点击刚刚完成的培训工作,向下滚动点击查看日志

点击日志流,您可以查看您的模特培训工作的日志,包括您在src/model.py中打印的任何内容。

通过导航到train_model.py中定义的output_path来定位model.tar.gz。您可以下载这个模型在其他地方使用,或者在 SageMaker 上通过这个 S3 路径访问它进行批量推理或实时推理。

包扎

我希望您现在能够使用 Amazon SageMaker 在云中构建和训练模型。查看 AWS Labs GitHub 页面,了解如何将 SageMaker 与其他框架一起使用,如 Keras / TensorFlow、 scikit-learn 等等。

更多 AWS 教程

如果你觉得这很有用,一定要关注我,看看我剩下的 AWS 教程。

取得联系

感谢您的阅读!请让我知道你是否喜欢这篇文章,或者你是否有任何批评。想打个招呼就在 LinkedIn 上联系我。干杯!

了解 SQL Server Management Studio —关于数据库、表和命名约定的第 2 部分

原文:https://towardsdatascience.com/getting-started-with-sql-server-management-studio-5cd24bb1a87c?source=collection_archive---------8-----------------------

让你在派对上开心的技能!逐步地

迈克尔·泽兹奇在 Unsplash 上的照片

在最后一集…

欢迎光临!还是“欢迎回来!”?这是 SQL 和 SQL Server Studio 系列教程的第二部分。目标?让你熟悉和适应这个工具和语言。“这有什么关系?”我知道你在问。事实证明,好奇心和副业往往是被新项目选中的关键,甚至是获得新工作的关键。您已经使用了一个重要的工具,比如 SQL Server Studio,并且编写了一些 SQL 查询,这一事实可以并且将会给您一个清晰的开端。

如果您错过了关于如何设置我们的环境和本地服务器的第 1 集,请阅读本文,然后不要忘记回来😉。

期待什么?

今天,我们将看看数据库、表,并简要提及模式。还会有一个关于命名约定的重要注释。我们将看到创建表的两种方法,并编写删除表的查询。您将找到 SQL Studio 如何支持您编写无错误查询的示例,并能够查看查询性能和返回的结果。到本文结束时,您将会感到自信,并具备强大的基础知识,开始在 SQL Studio 中漫游。让我们直接跳进来吧!

创建您的第一个数据库

数据库,简称 DB,是表的集合。这是我们最简单的说法。让我们一步一步来创建我们的第一个。

  1. 我们假设已经启动了 SQL Server Studio,并连接到本地服务器的实例。
  2. 左边是对象资源管理器。右键单击数据库,然后单击“新建数据库”。

3.将出现一个新窗口。**最大的问题是如何命名我们的数据库。**为什么有关系?一点思考的内容:

  • 它很可能会比我们将实施的许多应用程序、仪表盘和流程更长寿。
  • 我们合作,所以这个选择的名字将会被使用,无论是口头的还是书面的。想象一下它被命名为 XRZPWO_JLM 。不错吧?祝你在口头对话中好运。随着时间的推移,你可能会经常用到这个术语。一年几百次。好吧,至少在书面形式下,你可以说‘是那个以 XR 开头的服务器……’。好吧,你说到点子上了。那是当然,除非它是唯一一个这样命名的。拥有一个名为 XRZPWO_JLM 的数据库给了我一个提示,在你的服务器的其余部分将会有更多名为**的方式*。你必须登录,检查,复制粘贴(你将无法通过记忆正确地交流)。您的收件人可能会花一些时间来找到它。听起来像地狱,对吧?*
  • 名字作为参考。如果你从一个名为 XRZPWO_JLM 的数据库开始,几个月后,在厌倦了与它交流的麻烦后,你决定改变它,它可能会破坏相关的应用程序。双重痛苦。

那么如何命名呢?对于数据库中的内容,该名称应该是不言自明的。也应该是鲜明的。一个有趣的方法是使用数据库按项目分离我们的数据。

  • HR_data 可以保存与您的人员相关的数据,如名字和姓氏、电子邮件、雇佣日期、级别。
  • API_Finance 可以托管来自不同金融网站 API 的数据。
  • Product_ABC 可以托管从名为 ABC 的产品中收集和生成的数据。

长话短说,命名要紧。这个主题应该有自己的一篇文章。有惯例,不同的方法。常识和实用性应该占上风。我们来看看 HR_data。

我们可以调整一系列设置,但我们将保留默认设置。我们按 enter 键,新的数据库就创建好了。

4.单击+展开“数据库”的层次结构,然后单击“HR_data ”,您应该会看到以下内容:

我们已经有了第一个数据库,我们已经准备好创建第一个表。

创建您的第一个表格

根据字段的不同,表中的元素可以有不同的名称。最常见的是行列称谓。

  • 行也可以被称为记录或行,这取决于你问谁。
  • 按照列,它们可以被称为“特征”或“变量”,这是数据科学中经常使用的行话。但是你可能知道:

其他名字的行闻起来还是一样香

现在,表命名和数据库命名一样重要。因为同样,我们可能会一遍又一遍地使用和讨论这些术语。这也使得在编写脚本或运行查询时,拥有清晰的名称和对表中内容的理解变得更加容易。

下面我们来看一个复杂的(剧透:不是很好的方式)例子:

上面的这些表形成了一个“规范化模式”——与平面表的模式相反,下一篇文章将详细介绍这一点——但是表和列的命名远非最佳。没有一致性,有些是不言自明的。让我们继续创建我们的第一个表。

  1. 右键单击表,然后单击新建表

2.将出现表设计器。可以通过多种方式创建表,既可以使用表设计器,也可以编写查询。我们先从前者说起。

使用表格设计器创建表格

我们将从小而简单开始,分为三栏:

  • Department_ID —这将是部门的唯一标识符。由于这将是一个数字,我们指定 int (整数)作为数据类型。
  • 部门名称—这是其通用名称。我们选择 nvarchar(50 ),因为字符串的长度(这里是部门名称)可能不同,因此数据类型中有“var”。(50)表示我们允许的最大长度。任何超出的都不会被记录。如果我们想使用最大可接受的长度,我们可以将它设置为 nvarchar(MAX)。“为什么不一直用 nvarchar(MAX)呢?”,我看你在问。嗯,因为性能的原因,比 nvarchar(n)慢。
  • Department_Email —部门的电子邮件,例如共享邮箱。Nvarchar(50)也在这里。

稍后可以轻松调整 nvarchar(n)。如果您希望文本作为输入,或者如果您很懒并且性能不是您主要关心的问题(可能总是回来困扰您,但是您将能够调整到数字“n”),那么使用(MAX)最有意义。

3.让我们点击左上角的“保存”软盘,给我们的表起一个引人注目的名字,“部门”。

4.现在,该表在层次结构中的“表”下可见。如果没有显示,请点击“刷新”按钮,即“连接”旁边的圆圈箭头。使用网络服务器时,可能会出现表格不显示的情况,您需要单击“连接”并重新连接到服务器。

5.现在已经保存并创建了表,我们可以关闭设计窗口了

6.如果将来您需要调整表格,您可以右键单击表格,然后选择设计。“设计”窗口再次出现,并允许您修改表格。完成后,不要忘记保存更改。

通过编写查询来创建表

这是设计窗口的一种替代方式。当您编写脚本时,这可能会很方便,因为脚本需要创建一个表。结果是一样的,你得到了一个新的表。如果要更新、添加或删除表中的记录,最有可能使用这种方法。让我们看看如何编写一个查询来创建同一个表。

  1. 右键单击数据库 HR_data,然后单击新建查询

2.将出现一个查询窗口。让我们写以下内容

*CREATE TABLE HR_data.dbo.Departments(Department_ID int,Department_Name nvarchar(50),Department_Email nvarchar(50))*

其结构如下:

  • “CREATE TABLE”是 SQL 语言中的一个命令名。
  • 然后,通过点链或层次结构,我们精确地确定应该在哪里创建这个表。这里是在我们的表> 的 HR_data.dbo. <名称内。“Dbo”是默认设置。
  • 然后我们打开一个方括号'(',开始输入我们的列名,后面是它的数据类型。每一行都以逗号结尾。
  • 我们用另一个括号“)”结束列列表。

*3.在窗口中,您会看到查询的一部分用红色下划线标出。有点不对劲。我们的数据库中已经有一个这样的表。因此,在本练习中,我们将调整上面的查询,并将表称为 *Departments_temp。现代脚本和编码环境的一个有用特性是扫描潜在的 bug 或错误。这甚至在我们开始执行代码之前就节省了大量的时间。

让我们键入以下内容:

*CREATE TABLE HR_data.dbo.Departments_temp(Department_ID int,Department_Name nvarchar(50),Department_Email nvarchar(50))*

红色下划线消失了。

4.我们现在可以执行我们的查询。点击 F5 或“执行”绿色箭头。

5.我们会收到对我们的询问的即时反馈

6.让我们刷新我们的服务器,表出现。很棒的东西。

7.为了保持整洁,我们将删除这个 _temp 表。小心这个,因为一旦它掉了…它就掉了。不见了。

8.我们将回收我们的查询窗口,首先删除导致表创建的代码。然后写下以下内容,并点击执行或 F5:

*DROP TABLE HR_data.dbo.Departments_temp*

9.刷新层次结构后,我们看到表不见了。请注意,“刷新”只是从用户界面的角度来看。因为在后台,当您执行' drop table …'查询时,该表已经被删除了。

查询我们的表

可以查询或“读取”表。让我们看看我们自己的 SQL“Hello World”。

  1. 清理您的查询窗口。或者关闭它并重新打开一个。
  2. 键入下面的,然后执行/F5
*SELECT *
FROM HR_data.dbo.Departments*
  • 选择意味着我们将选择接下来的内容,
  • *表示“一切”,即每一列,
  • FROM 表示我们将从中选择“所有内容”的来源

查询窗口上的其他提示和注释

旗帜

在这一系列教程中,我们会遇到不同的颜色。下面先睹为快。

  • 表名、列名是黑色的,
  • SQL 命令(SELECT,FROM,…)将变成蓝色,
  • 由简单引号'和'表示字符串将是红色,
  • 系统功能将是粉红色的(纯粹主义者会说是洋红色),
  • 运算符如 AND、OR 将是灰色的,
  • 评论将是绿色的

自己看:

虽然它很漂亮,但没什么用处。

还有更多!

结果窗格

结果窗格显示我们的查询结果(如果我们正在进行“选择”):

它还提供了受“消息”影响的记录数量的信息。如果没有错误,您将得到以下结果:

如果出现问题,您会收到通知,并得到一些关于如何调试的支持,例如“无效的列名‘Departm’”。

结果窗格还为我们提供了以下一般信息:

  • 查询的状态:

**

  • 它的性能,即它运行了多长时间和返回的记录数,这里它在不到 1 秒的时间内执行,并返回 0 行,因为我们的表或查询有 0 个匹配。

最后的话和接下来会发生什么

暂时就这样吧!我的目标是让它简短、甜蜜、有趣,尽管这部电影中没有任何迷因。

  • 我希望您现在有信心创建数据库和表,无论是使用设计工具还是通过编写查询。
  • 您也有权删除表,但是要小心,因为除非您的数据库得到备份,否则您将丢失底层数据。您还会停止依赖于它的任何应用程序、过程或表。
  • 您知道结果窗格、查询性能指标和返回的行数,这是调试的第一种方法。
  • 我不能再强调正确的表和数据库命名的重要性了,因为它们会随着时间的推移而出现,如果您选择了糟糕的名称,它们可能会困扰您。

编码快乐!

感谢阅读!喜欢这个故事吗? 加入媒介 可完整访问我的所有故事。

从关于 CRUD 操作、主键和外键的第 3 集开始继续这一旅程!

*

或者选择你喜欢的另一集

在第 4 集中,我们讨论模式&主要的规范化步骤— 第 4 部分模式&规范化

在第 5 集,我们覆盖存储过程&调度,这是一个真正的野兽。我怎么强调这将如何促进和自动化你的日常(数据)生活都不为过。第五部分存储过程&调度

在第 6 集中,我们介绍了用于 ETL 的 SSIS 包,并回顾了如何在两个数据库之间以及一个数据库和 Excel 之间导入和导出数据。第六部 SSIS 套餐简介

在第 7 集中,我们将 SQL Studio 连接到 PowerBI,并构建了我们的第一批视觉效果。[第 7 部分连接到 PowerBI &第一视觉效果](http://Part 7 Connect to PowerBI & First Visuals)*

了解 SQL Server Management Studio —第 1 部分分步安装

原文:https://towardsdatascience.com/getting-started-with-sql-server-management-studio-part-1-step-by-step-setup-63428650a1e0?source=collection_archive---------14-----------------------

这是一个免费且强大的工具,可以利用数据、提高技能并在面试中脱颖而出

迈克尔·泽兹奇在 Unsplash 上的照片

期待什么?

在这一系列文章中,我将对 Microsoft SQL Server Management Studio(SSMS)进行一次演练。今天,我们将从环境设置开始。在接下来的文章中,我们将创建自己的数据库和表。创建、读取、更新、删除记录。我们将编写、保存和修改我们自己的存储过程。我们还将安排作业,创建 SSIS 包…如果您不熟悉其中的一些术语,您很快就会掌握,并自己创建和管理它们。

SSMS 是一个强有力的工具,如果你想提高技能或面试另一份工作,这是一项有趣的技能。这也是一个在浏览器窗口上把你在 SQL 101 中学到的东西付诸实践的机会,但是从来没有机会体验数据库管理软件的感觉。

什么是 SQL?

SQL 代表**结构化查询语言。**它旨在管理关系数据库中的数据。剧透:它做得很好。这门语言诞生于 20 世纪 70 年代,自那以后已经有了很大的发展。在其存在的 40 多年里,新的数据类型、操作符和功能丰富了这种语言。

什么是 Microsoft SQL Server Management Studio?

Microsoft SQL Server Management Studio 通常被称为 SSMS,是一种用于配置、管理和控制数据的工具。该工具允许您连接到本地(酷孩子称之为“本地”)和云中的 SQL Server 实例。

你能实现什么?

简而言之:很多东西。更详细的回答是,在 SSMS,你可以:

  • 连接到服务器及其实例,
  • 创建和管理数据库及其底层表,
  • 连接到可视化工具,如 PowerBI,Tableau,Spotfire,…
  • 连接到 Power Automate 等自动化工具,或者 PowerApps 等低代码和无代码平台,
  • 创建和管理存储过程,即您可以编写和保存的脚本。然后,可以在以后执行这些程序来利用您的数据,例如对您的数据进行一些操作、存档记录或表格、发送电子邮件等等
  • 创建和管理触发器,这是在某个操作(创建/删除/更新记录等)之后触发的自动化操作
  • 创建和管理计划作业,以便给定的存储过程以任何定义的频率运行,
  • 备份和恢复数据,
  • 导入和导出数据
  • 创建 SSIS 软件包,用微软自己的话说就是:

“SQL Server Integration Services(SSIS)是一个构建企业级数据集成和数据转换解决方案的平台。使用 Integration Services 通过复制或下载文件、加载数据仓库、清理和挖掘数据以及管理 SQL Server 对象和数据来解决复杂的业务问题"

如果您想在数据库之间或服务器之间复制表,SSIS 包非常有用。可以保存 SSIS 包,然后将其用作计划作业的一部分。

这是一份很长的清单。但是如何以及从哪里开始呢?请继续阅读!

设置您的环境

这应该是一种解脱:安装和设置将不会是一场噩梦。这个软件是成熟和稳定的,我还没有遇到任何错误或崩溃。将有两个组件安装完成。

1.下载 SSMS

进入页面,在【下载 SSMS】下下载最新版本。在撰写本文时,它是 v18.8。启动程序要求您有大约 657MB 的空闲磁盘空间。一旦你完成安装,你应该会发现这样的标志。

一个相当于任何注重数据的人的锤子和镰刀的数据库。启动程序时,应出现以下屏幕:

进入矩阵

然后很快出现一个窗口,让您连接到服务器:

好吧,现在正是恐慌的时候。“连接到服务器?但是您没有告诉我们需要服务器。”你是对的。如果你有一个,你可以输入它的名字和实例:\实例#。例如 myserver\inst1。

如果你没有足够的服务器,不要担心,还有一个方法可以让你继续享受和探索 SSMS。进入第二次下载:

2。SQL Express

我们将使用我们的计算机和 SQL Express 作为我们的服务器和实例。转到本页并下载免费专业版‘Express’

安装完成后,让我们返回下面的 SSMS“连接到服务器”窗口:

首先,我们需要找到我们的计算机名。在 Windows 10 上,点击 Windows 键,然后输入“关于你的电脑,你应该会进入一个页面,我们需要的信息在“设备名称”之后。

您也可以右键单击桌面上的“我的电脑”图标,然后选择属性。你会发现和上面一样的窗口。

复制这个名字并粘贴在 SSMS 窗口。然后写\SQLExpress。它应该是这样的,用你的计算机名代替我的。

点击连接…我们就开始直播了!对象资源管理器提供了一个整洁的文件夹列表,每个文件夹都封装了 SSMS 的特性和功能。

这就是初始设置。在下一篇文章中,我们将讨论数据库和表的创建和设计,记录管理的 CRUD 缩写(创建、读取、更新、删除),等等。

编码快乐!

继续 SQL 之旅,阅读关于数据库、表等的第 2 部分!

或者选择你喜欢的另一集

在第 3 集中,我们介绍了 CRUD 操作以及主键和外键——第 3 部分 CRUD 操作,主键&外键

在第 4 集中,我们讨论模式&主要的规范化步骤— 第 4 部分模式&规范化

在第 5 集,我们覆盖存储过程&调度,这是一个真正的野兽。我怎么强调这将如何促进和自动化你的日常(数据)生活都不为过。第五部分存储过程&调度

在第 6 集中,我们介绍了用于 ETL 的 SSIS 包,并回顾了如何在两个数据库之间以及一个数据库和 Excel 之间导入和导出数据。第六部 SSIS 套餐简介

在第 7 集中,我们将 SQL Studio 连接到 PowerBI,并构建了我们的第一批视觉效果。[第 7 部分连接到 PowerBI &第一视觉效果](http://Part 7 Connect to PowerBI & First Visuals)

感谢阅读!喜欢这个故事吗? 加入媒介 获取完整的我的所有故事。

参考文献

  1. https://en.wikipedia.org/wiki/SQL
  2. https://docs . Microsoft . com/en-us/SQL/integration-services/SQL-server-integration-services?view=sql-server-ver15

SSH 入门

原文:https://towardsdatascience.com/getting-started-with-ssh-d931874f5fb4?source=collection_archive---------47-----------------------

数据科学家开始使用 SSH 应该知道的一切

学习如何创建和管理多组 SSH 密钥对是任何有抱负的数据科学家或机器学习工程师的重要技能。来源:Samantha Lam ( Unsplash )

在某些时候,作为一名数据科学家,您需要处理一个需要比您的笔记本电脑或工作站更多计算资源(例如,磁盘空间、CPU 内存、CPU 或 GPU 数量)的数据集。当这种情况发生时,你需要知道如何访问一个拥有足够计算资源的远程服务器来完成手头的任务。无论这些远程服务器驻留在公共云中(即 AWS 、 GCP 或 Azure ),还是驻留在本地(即大学远程计算集群),您都将使用安全外壳(SSH) 协议来访问这些服务器。

在本文中,我将介绍使用 SSH 有效地连接到远程服务器需要了解的内容。特别是,您将学习如何使用 SSH 登录到远程服务器,如何生成自己的 SSH 密钥对,以及如何使用新的 SSH 密钥对部分自动化连接到远程服务器的过程。在以后的文章中,我将讨论如何配置 SSH 以获得最大的生产率,以及如何使用更高级的技术来完全自动化使用 SSH 登录远程服务器的过程。

我们开始吧!

OpenSSH

虽然 SSH 协议有许多实现,但我在本文中重点介绍的是 OpenSSH。OpenSSH 可能是使用 SSH 协议进行远程登录的最广泛使用的连接工具。它对所有流量进行加密,以消除窃听、连接劫持和其他攻击。此外,OpenSSH 提供了一大套安全隧道功能、几种身份验证方法和复杂的配置选项。

如果您运行的是 Mac OS 或 Linux,那么应该已经安装了 OpenSSH。Open SSH 于 2018 年秋季添加到 Windows 中,因此如果您运行的是较新版本的 Windows(特别是 Windows 10),那么 Open SSH 应该也已经安装了。如果您运行的是旧版本的 Windows,那么您可能需要安装并配置 OpenSSH 。

使用 SSH 登录

使用 SSH 登录的默认方式是使用用户名和密码使用[ssh](https://www.ssh.com/ssh/command/) 命令登录到特定的主机(可能是主机名或 IP 地址)。

ssh username@some.host.com # could also be an IP address

如果这是您第一次使用ssh连接到这个远程服务器,那么您将会看到这样的消息:

The authenticity of host 'some.host.com' cannot be established.
ECDSA key fingerprint is SHA256:d/FZhiccG5Gs6MzA7XR6Hksvl9OZjSx6WVXEi6Ddrj3
Are you sure you want to continue connecting (yes/no)?

根据用于生成远程服务器的主机密钥 (上例中的 ECDSA)的算法类型,上面的消息可能看起来略有不同。键入yes继续。这将把远程服务器添加到您的已知主机列表中(您的本地机器上的~/.ssh/known_hosts文件)。

Warning: Permanently added 'some.host.com' (ECDSA) to the list of known hosts.

首次登录远程服务器时,系统会要求您验证并保存远程服务器的主机密钥,以便下次连接到该远程服务器时,您的本地计算机可以验证它实际上是同一个远程服务器(通过检查远程服务器的主机密钥是否包含在已知主机列表中)。

然后,系统会提示您输入密码,以完成身份验证过程。一旦通过身份验证,您就可以登录到您的远程服务器,并且会有一个新的 shell 提示符,通常看起来如下所示(~表示您的当前目录是您的用户在远程服务器上的主目录)。

username@some.host.com ~$

反复使用您的用户名和密码进行身份验证既耗时又容易出错。在下一节中,我将向您展示如何使用公共/私有 SSH 密钥来部分自动化认证过程。

生成 SSH 密钥对

更高效(也更安全!)与远程服务器交互的方式是使用公共/私有 SSH 密钥对来部分自动化认证过程。如果您对 SSH 公钥/私钥对如何工作的直觉感兴趣,那么我推荐您观看下面的视频;如果您只想学习如何生成自己的公共/私有 SSH 密钥对,那么您可以放心地跳过视频。

[ssh-keygen](https://www.ssh.com/ssh/keygen/)命令用于使用各种算法生成公共/私有 SSH 密钥对。使用椭圆曲线数字签名算法(ECDSA) 使用ssh-keygen生成公共/私有 SSH 密钥对,如下所示。

cd ~/.ssh
ssh-keygen \
  -t ecdsa\ # could also use older rsa algorithm with -b 4096
  -b 521\ # alternatives are 256 or 384
  -C "your.email@provider.com"
  -f ~/.ssh/id_ecdsa # save your keys in ~/.ssh/

运行上述命令将启动生成公钥/私钥 ECDSA 密钥对的过程。系统将提示您提供保存密钥的文件路径。默认为~/.ssh/id_ecdsa。您可能有许多组 SSH 密钥对,因此您应该更喜欢将您的密钥文件命名为不太通用的名称。

接下来,系统会提示您输入可选的密码(然后要求您确认密码)。

Enter passphrase (empty for no passphrase):

你应该总是使用密码保护你的私有 SSH 密钥。如果有人获得了对您的本地机器的物理访问权,而您的私钥没有密码保护,那么这个人也获得了对使用您的 SSH 密钥对的每个远程服务器的访问权。

输入(并确认)您的密码后,将生成密钥对并保存到指定的文件中。

Your identification has been saved in ~/.ssh/id_ecdsa.
Your public key has been saved in ~/.ssh/id_ecdsa.pub.
The key fingerprint is:
SHA256:2yyanHlvgr68zw1pS+h7zDTkvR0pujsyrKumPqHb3bY your.email@provider.com
The key's randomart image is:
+---[ECDSA 521]---+
|.. .             |
|..o o    B .    o|
|..E.... @ * o. +o|
|.  + + = = + +* o|
|. . + . S + o =o=|
| o o     . =   *.|
|. .       +  . o |
|         . .  +  |
|            ..   |
+----[SHA256]-----+

将 SSH 密钥对添加到 authorized_keys

为了使用您新生成的 SSH 密钥对登录到您的远程服务器,您必须首先将新生成的公共 SSH 密钥添加到远程服务器上的授权密钥列表中(注意:新生成的私有 SSH 密钥应该始终保留在您的本地机器上)。

将您的公共 SSH 密钥添加到远程服务器上的授权密钥列表中可以通过三个步骤手动完成。

  1. 运行cat输出您的公共 SSH 密钥文件的内容,并复制公共 SSH 密钥。
  2. 用你的$USERNAME和密码登录你的远程服务器$HOSTNAME
  3. 打开~/.ssh/authorized_keys文件,在文件末尾粘贴新创建的公共 SSH 密钥。

您可以使用下面的命令,而不是手动将您的公共 SSH 密钥添加到授权密钥列表中(这很容易出错)。

ssh-copy-id -i ~/.ssh/id_ecdsa.pub username@some.host.com

运行上述命令时,系统会提示您提供登录远程服务器的密码,但是一旦命令完成,并且您的公共 SSH 密钥已被添加到授权密钥列表中,您应该能够注销,然后再次登录,而无需提供密码(但是您仍然需要提供密码来解锁您的私有密钥)。

一旦在远程服务器上配置了公钥,远程服务器将允许任何拥有私钥的连接用户(并且知道密码来解锁它!)登录,因此永远不要共享您的私钥。

摘要

下面三个(真的是两个!)命令将生成您的公共/私有 SSH 密钥对,并将公共密钥添加到远程服务器上的~/.ssh/authorized_keys文件中。

cd ~/.ssh
ssh-keygen -t ecdsa -b 521 -C "your.email@provider.com"
ssh-copy-id -i ~/.ssh/id_ecdsa.pub username@some.host.com

如果您已经做到了这一步,那么恭喜您:您现在应该对 SSH 的基础有了很好的理解!

一旦您开始使用 SSH,您将很快发现您想要生成多个 SSH 密钥对(您需要访问的每个远程服务器都有一个不同的密钥对),因此在本系列的下一篇文章中,我将讨论如何配置 SSH 来有效地管理这些多个 SSH 密钥对。

开始使用 Airflow 2.0 中的任务组

原文:https://towardsdatascience.com/getting-started-with-task-groups-in-airflow-2-0-d85b7517767e?source=collection_archive---------9-----------------------

一个包含两组任务的简单管道,使用来自 Airflow 2 的 TaskFlow API 的@taskgroup decorator。

介绍

在 Airflow 2.0 中的任务分组之前,子标记是分组任务的首选 API。在 Airflow 2.0 中,子标签被降级,现在被任务组功能取代。任务流 API 很简单,允许适当的代码结构,有利于清晰地分离关注点。

我们今天构建的是一个包含两组任务的简单 DAG,使用了来自气流 2 的任务流 API 的@taskgroup装饰器。图表视图为:

作者图片

这条管道对给定的初始值进行不同的操作。任务实例化了一个值为0的变量。然后,它传递给一组子任务(group_1),这些子任务处理初始值。group_2将所有的值聚合成一个。最后,end()子任务将打印出最终结果。

让我们从将管道分成几个部分开始。

任务分组-分解

如上图所示,有一个init()end()任务。在这两者之间,有两组任务,但是让我们从管道的第一个和最后一个任务开始。

作者图片

init()任务是这个管道的起点——它返回将在整个管道中操作的初始值:0。任务将把管道中的所有操作打印到控制台。

让我们看看init()任务的代码:

就是这样。现在是end()任务的代码:

定义整个管道的流程也很简单,由包装所有内容的函数返回:

查看上面的代码,可以看到:

任务组#1 ( group_1)

作者图片

group_1有一组操纵原始数字的三个任务:

group_1函数接收来自init()任务的结果。注意这里返回的是什么:三个值的列表。每个值都源于subtask_1subtask_2subtask_3。这个值列表就是将要发送给group_2的内容。

任务组#2 ( group_2)

作者图片

很简单。它接收从group_1发送来的列表,并对所有值求和(subtask_4完成),然后subtask_5将来自subtask_4的结果乘以 2:

就是这样——下一个任务是end(),在本帖之前已经处理过了。同样,这里有可能看到完整的代码。

如果您检查“end()”任务的日志(参见我以前的帖子,了解如何检查任务日志),您将看到打印的结果。最后的结果应该是12

成功!🎉

结论

在 Airflow 2 中创建任务组很容易——它消除了以前存在的复杂性,并允许用干净的代码创建管道。

背景

这篇文章是 ETL 系列教程的一部分。这最初发布在pedromadruga.com上。如果你喜欢这篇文章,可以考虑订阅时事通讯或者在推特上关注我。

完整的代码可在这里获得。

原载于【https://pedromadruga.com】。如果你喜欢这篇文章,可以考虑订阅时事通讯或者在推特上关注我。

Tensorflow 入门

原文:https://towardsdatascience.com/getting-started-with-tensorflow-e33999defdbf?source=collection_archive---------28-----------------------

通过示例学习基础知识

照片由来自 Unsplash 的 Marten Newhall 拍摄。

介绍

好,我们来讨论一下房间里的大象。应该学 Tensorflow 还是 PyTorch?

老实说,没有正确的答案。这两个平台背后都有一个大型开源社区,易于使用,并且能够构建复杂的深度学习解决方案。如果你真的想成为一名出色的深度学习研究者,你必须了解这两方面。

我们现在来讨论 Tensorflow 是如何产生的,以及如何利用它进行深度学习。

Tensorflow 是什么时候开发的?

人工神经网络(ANN)的研究已经存在了很长时间。沃伦·麦卡洛克和沃尔特·皮茨在 1943 年发表了其早期作品之一,其中作者开发了人工神经网络的第一个计算模型。

在 21 世纪初之前,只有粗略的框架可用,需要有经验的 ML 从业者来建立简单/适度的人工神经网络方法。

随着 2012 年对人工神经网络的兴趣激增,深度学习(DL)框架的前景开始发生变化。Caffe、Chainer 和 Theano 可以说是早期的顶级竞争者,它们使普通数据科学家更容易使用 DL。

谷歌在“机器学习和人工智能”类别下搜索 2012 年 1 月至 2021 年 7 月之间的顶级低/高级深度学习框架。图片来自作者。

2015 年 2 月,谷歌开源了 Tensorflow 1.0,这一框架迅速获得了关注。Tensorflow swift 的采用与几个因素有关,如家喻户晓的名字、快速和频繁的更新、简单的语法以及对可用性和可扩展性的关注(如移动和嵌入式 devices)⁴⁵.

随着 PyTorch 的日益普及和 Tensorflow⁶市场份额的减少,谷歌团队在 2019 年发布了对库“Tensorflow 2.0"⁷.”的重大更新这次更新引入了急切执行(PyTorch 的关键卖点之一),以及对 Keras 的本机支持(通过静态计算图极大地简化了开发)。

到 2021 年 6 月,超过 99%的谷歌搜索主要深度学习框架包含 Tensorflow、Keras 或 PyTorch。

通过例子学习

最简单的学习方法(至少对我来说)是通过例子。这种方法允许您测试一个工作过程,修改它,或者获取对您的项目有用的组件。

在这篇博客中,我将通过两个 ML 示例来指导您,说明构建简单张量流模型所需的关键组件。

为了提高可复制性,我建议使用 Google Colab 作为这里描述的例子。为此,只需打开这个链接,按照步骤创建一个新的 python 3 笔记本。

线性回归

在此示例中,我们将构建一个简单的 1 层神经网络来解决线性回归问题。这个例子将解释如何初始化你的权重(又名回归系数),以及如何通过反向传播来更新它们。

我们首先需要的是一个数据集。让我们模拟一个噪声线性模型如下

其中 Y 是我们的目标,X 是我们的输入,w 是我们要确定的系数,N 是高斯分布噪声变量。为此,在笔记本的第一个单元格中粘贴并运行以下代码片段。

这将显示 X 和 Y 之间关系的散点图,清楚地表明在一些高斯噪声下的线性相关性。在这里,我们期望一个合理的模型来估计 2 作为理想的回归系数。

代表高斯噪声下 X 和 Y 之间线性相关性的模拟数据。

现在让我们用一个常数(0.1)开始我们的回归系数(这里称为权重)。为此,我们首先需要导入 Tensorflow 库,然后将权重初始化为 Tensorflow 变量。

为了这个例子的目的,假设一个变量具有与张量相似的性质。张量是由 tf 表示的多维元素阵列。张量对象。张量只有一种数据类型(在下面的例子中为“float32”)和一种形状。该对象允许其他 Tensorflow 函数执行某些操作,例如计算与该变量相关的梯度并相应地更新其值。复制以下代码片段来初始化我们的权重变量。

运行这个代码片段将输出变量名、形状、类型和值。注意,这个变量有一个“()”形状,表示它是一个 0 维向量。

<tf.Variable ‘Variable:0’ shape=() dtype=float32, numpy=0.1>

给定初始化的权重张量和输入 X,为了获得预测的 Y (Yhat ),我们可以简单地调用“Yhat = x * w_tensor.numpy()”。的’。“numpy()”用于将权重向量转换为 numpy 数组。复制并运行下面的代码片段,看看初始化后的重量如何符合数据。

正如你所观察到的,‘w _ tensor’的当前值与理想值相差甚远。回归线完全符合数据。

训练前模型拟合的表示。

为了找到‘w _ tensor’的最佳值,我们需要定义一个损失度量和一个优化器。这里,我们将使用均方误差(MSE)作为我们的损失度量,随机梯度下降(SGD)作为我们的优化器。

我们现在有了优化我们的“w _ 张量”的所有部分。优化循环只需要定义“前进步骤”,并从我们的优化器调用最小化函数。

“前进步骤”告诉模型如何将输入与权重张量相结合,以及如何计算我们的目标与预测目标之间的误差(下面代码片段中的第 5 行)。在一个更复杂的例子中,这将是一组定义从输入 X 到目标 y 的计算图的指令。

为了最小化定义的损失,我们只需要告诉我们的优化器最小化关于‘w _ tensor’的‘损失’(下面代码片段中的第 17 行)。

将下面的代码片段添加到您的示例中,为模型定型 100 次迭代。这将动态绘制新的权重值和当前拟合。

在训练结束时,你的体重应该接近 2(理想值)。要使用此模型进行推理(即,在给定 X 值的情况下预测 Y 变量),只需执行` Yhat = x * w_tensor.numpy()'

训练后模型拟合的表示。

分类问题

在本例中,我们将引入 Keras 顺序模型定义来创建更复杂的神经网络。我们将把这个模型应用于一个线性可分的分类问题。

像以前一样,让我们从构建数据集开始。在下面的代码片段中,我们为第一个聚类创建了两个以(0.2,0.2)为中心的点聚类,为第二个聚类创建了两个以(0.8,0.8)为中心的点聚类。

我们可以很快观察到,用一条与两个聚类距离相等的线将两个数据集线性分离的模型是理想的。

模拟数据表示两个数据聚类,第一个聚类以(0.2,0.2)为中心,第二个聚类以(0.8,0.8)为中心。

像以前一样,让我们定义我们的损失度量和优化器。在这个例子中,我们应该使用分类损失度量,例如交叉熵。因为我们的目标被编码为整数,所以我们必须使用“SparseCategoricalCrossEntropy”方法。

对于优化器,我们可以像以前一样使用 SGD。然而,普通 SGD 的收敛速度慢得令人难以置信。相反,我们将使用最近的自适应梯度下降方法(RMSProp)。

下一步是定义自定义神经网络模型。让我们创建一个 5 层神经网络如下:

  1. 有 10 个节点的线性层。这将有一个 2 x 10(输入形状 x 图层大小)的形状。
  2. 批量标准化层。这一层将对每一批的第一层的输出进行归一化,避免爆炸/消失梯度。
  3. Relu 激活层。这一层将为我们的网络提供非线性能力。请注意,我们仅以此为例。对于这个问题,relu 层是不必要的,因为它是线性可分离的。
  4. 具有两个节点的线性层。这将有一个 10 x 2(层大小 x 输出形状)的形状。
  5. Softmax 层。该层会将第 4 层的输出转换为 softmax。

在网络用于训练之前,我们需要调用“编译”方法。这将允许 Tensorflow 将模型链接到优化器和上面定义的损失度量。

和以前一样,我们先来检查一下我们的网络在训练前表现如何。要使用该模型进行推理,我们只需键入“yhat = model.predict(x)”。现在,复制下面的片段来可视化网络输出。

你可以确认网络一点也不好。显然需要一些训练来正确区分这两个类别。

训练前模型拟合的表示。

要训练一个 Keras 模型,我们只需输入“model.fit(x,y,epochs=50)”。将下面的片段添加到您的笔记本中,以训练模型。

在训练循环结束时,你的网络应该能够很好地分离这两个类。要使用此模型进行推理(即,在给定 X 值的情况下预测 Y 变量),只需执行“yhat = model.predict(x)”。

训练后模型拟合的表示。

完整脚本

如需完整的脚本,请点击以下链接进入我的 Github 页面:

https://github.com/andreRibeiro1989/medium/blob/main/tensorflow_getting_started.ipynb

或者通过以下链接直接访问 Google Colab 笔记本:

https://colab.research.google.com/github/andreRibeiro1989/medium/blob/main/tensorflow_getting_started.ipynb

结论

Tensorflow 是目前开发定制深度学习解决方案的最佳深度学习框架之一。在这篇博客中,我介绍了构建两个简单神经网络模型的关键概念。

**警告!!!**你的学习才刚刚开始。要变得更好,你需要练习。官方 Tensorflow 网站提供了从初学者到专家级别的示例,以及 Tensorflow 软件包的官方文档。祝你好运!

1沃伦·麦卡洛克和沃尔特·皮茨”神经活动中固有的逻辑思想演算(1943),《数学生物物理学通报》。5: 115–133.
https://link.springer.com/article/10.1007%2FBF02478259

[2]袁林。深度学习框架简史
https://towardsdatascience . com/A-Brief-History-of-Deep-Learning-Frameworks-8 deb F3 ba 6607

[3] Alex Krizhevsky 等著《深度卷积神经网络的 ImageNet 分类》(2012),neur IPS
https://papers . nips . cc/paper/2012/file/c 399862d 3 b 9 d6b 76 c 8436 e 924 a 68 c 45 b-paper . pdf

[4]苏尼思·谢蒂。"为什么 TensorFlow 总是高居机器学习和人工智能工具调查榜首"
https://hub . packtpub . com/tensor flow-always-tops-machine-learning-artificial-intelligence-tool-surveys/

[5]叶达鑫·瓦朗冈卡。十大深度学习框架
https://hub.packtpub.com/top-10-deep-learning-frameworks/

6贺拉斯何。"2019 年机器学习框架状况"
https://The gradient . pub/State-of-ml-Frameworks-2019-py torch-domains-research-tensor flow-domains-industry/

[7] TensorFlow 团队。" TensorFlow 2.0 现已上市!"
https://blog . tensor flow . org/2019/09/tensor flow-20-is-now-available . html

Trino 查询引擎入门

原文:https://towardsdatascience.com/getting-started-with-trino-query-engine-dc6a2d027d5?source=collection_archive---------4-----------------------

数据库ˌ资料库

关于如何安装 Trino、将其连接到 SQL server 以及编写简单 Python 客户端的分步教程。

赫耳墨斯·里维拉在 Unsplash 上拍摄的照片

Trino 是一款用于大数据分析的分布式开源 SQL 查询引擎。它可以运行分布式和并行查询,因此速度非常快。Trino 可以在内部和云环境中运行,如 Google、Azure 和 Amazon。

在本教程中,我描述了如何在本地安装 Trino,将其连接到 MySQL 数据库(由 XAMPP 提供),并连接一个简单的 Python 客户端。Trino 官方文档可在此链接找到。

1 配置 Trino 搜索引擎

Trino 通常由一群机器组成,有一个协调者和许多工人。所有工作人员都连接到协调器,协调器为客户机提供访问点。

在安装 Trino 之前,我应该确保运行 64 位机器。然后我可以继续安装 Python 和 Java:

  • Python ≥ 2.6
  • JDK,由 Azul Zulu 发行(推荐)

一旦我安装了前面的需求,我就可以下载 Trino 搜索引擎并将其解包。在使用 Trino 之前,我必须对它进行配置。

在解压后的目录中,我创建了另一个名为etc的目录,它将包含所有的配置文件。有三个主要的配置文件:

  • config.properties—Trino 服务器的配置文件
  • jvm.config —用于启动 Java 虚拟机的命令行选项
  • node.properties —每个节点的具体配置。

etc文件夹还应该包含另一个名为catalog的文件夹,其中包含所有数据源(即连接器)的列表。所有可用连接器的列表可在此链接获得。

1.1 配置属性

服务器的最低配置如下:

coordinator=true
node-scheduler.include-coordinator=true
http-server.http.port=8080
query.max-memory=5GB
query.max-memory-per-node=1GB
query.max-total-memory-per-node=2GB
discovery.uri=http://127.0.0.1:8080

在前面的例子中,参数node-scheduler.include-coordinator=true指定同一个主机既充当协调者又充当工作者。如果我想为协调者和工作者使用不同的机器,我不会使用前面的参数,而是为协调者使用coordinator=true,为每个工作者使用coordinator=false

在前面的示例中,我还指定了发现 URI,即 HTTP 服务器可用的地址。在我的例子中,我利用了本地地址。

其他参数指定最大内存使用量。

1.2 jvm .配置

该文件包含用于运行 Java 虚拟机的命令行选项。此文件的一个很好的例子可能是下面这个:

-server
-Xmx16G
-XX:-UseBiasedLocking
-XX:+UseG1GC
-XX:G1HeapRegionSize=32M
-XX:+ExplicitGCInvokesConcurrent
-XX:+ExitOnOutOfMemoryError
-XX:+HeapDumpOnOutOfMemoryError
-XX:-OmitStackTraceInFastThrow
-XX:ReservedCodeCacheSize=512M
-XX:PerMethodRecompilationCutoff=10000
-XX:PerBytecodeRecompilationCutoff=10000
-Djdk.attach.allowAttachSelf=true
-Djdk.nio.maxCachedBufferSize=2000000

1.3 节点.属性

该文件包含每个节点的基本配置,包括机器集群的名称(node.environment)、存储数据的目录(node.data)和节点 id ( node.id)

node.environment=name_of_cluster
node.id=ffffffff-ffff-ffff-ffff-ffffffffffff
node.data-dir=/path/to/data/folder

1.4 目录

该文件夹包含 Trino 开发的所有连接器。连接器包含连接外部存储引擎所需的所有信息,比如 MySQL 服务器、MongoDB、Elastic Search 等等。每个连接器应该与一个单独的配置文件相关联,名为connector_name.properties(例如mysql.properties)。有关每个连接器的详细信息,请查看文档。

在本文中,我配置了一个 MySQL 连接器。我创建了一个名为mysql.properties的文件,其最小配置如下:

connector.name=mysql
connection-url=jdbc:mysql://localhost:3306
connection-user=root
connection-password=my_password

在我的例子中,我利用了 XAMPP 提供的 MariaDB 服务器。效果非常好!😄

2 运行 Trino 搜索引擎

现在,一切都准备好运行了。假设 MySQL 服务器已经在运行,Trino 服务器可以以两种方式启动,后台,作为一个单独的守护进程,或者前台。

要在后台运行服务器,请进入 trino 主目录并运行以下命令:

bin/launcher start

要在前台运行服务器,请从 trino 主目录运行以下命令:

bin/launcher run

这种最后启动方式的好处是,如果有一些问题,我可以很容易地识别出来。出于这个原因,我更喜欢在前台启动服务器。

现在可以查询服务器了。

我可以从浏览器访问一些服务器信息,地址如下:

[http://127.0.0.1:8080](http://127.0.0.1:8080/ui/login.html)

浏览器显示以下登录页面:

作者图片

我可以输入在mysql.properties文件中定义的用户名和密码。

然后,我应该能够看到下面的控制台,它显示了集群概述,以及关于查询和工作者的信息:

作者图片

3 Python 客户端

可以编写不同的 Trino 客户端来查询 Trino DB,如官方文档中所述。在本教程中,我将描述如何为 Trino 实现一个简单的 Python 客户端。

我利用了trino包,它可以如下安装:

pip3 install trino

这个包的官方文档可以在这个链接找到。

客户端的代码非常简单:

首先,我通过trino.dbapi.connect()函数定义连接参数,其中我还指定了要使用的目录(在我的例子中是mysql)。然后,我连接并执行一个简单的查询,它显示了我的 SQL server 中包含的所有表。

作为要传递给cur.execute()函数的字符串,我可以编写任何 SQL 查询。

运行脚本后,我可以在浏览器中返回 Trino 控制台。如果我单击底部菜单的 Finished 按钮,我会得到一些关于上一个查询的信息:

作者图片

摘要

在本文中,我描述了如何配置和运行 Trino 搜索引擎的基本配置,以及连接到它的简单 Python 脚本。

Trino 的主要优势是可以运行分布式查询,从而使得非常快速地查询大数据成为可能。

如果你已经走了这么远来阅读,对我来说今天已经很多了。谢谢!你可以在这篇文章里读到更多关于我的内容。

参考

  • 什么是分层数据?
  • 修改前序树遍历
  • 递归公用表表达式概述

相关文章

https://alod83.medium.com/how-to-represent-and-query-hierarchical-data-in-sql-69b6b77577e8

奖金

您知道 Trino 还允许运行机器学习功能,包括支持向量机(SVM)分类器和回归器来解决监督问题吗?

如果你对这个话题感兴趣,可以在这里阅读。

Weaviate Python 库入门

原文:https://towardsdatascience.com/getting-started-with-weaviate-python-client-e85d14f19e4f?source=collection_archive---------14-----------------------

关于新的基于机器学习的矢量搜索引擎的完整教程

图片由皮克斯拜的艾哈迈德·加德拍摄

0.新的更新。

  1. 什么是 Weaviate?
  2. 可以用在哪里?
  3. 有什么优势?
  4. 什么是 Weaviate Python 客户端?
  5. 如何在 Weaviate 集群中使用 Weaviate Python 客户端?
  • 5.0.创建一个弱实例/集群。
  • 5.1.连接到集群。
  • 5.2.获取数据并进行分析。
  • 5.3.创建适当的数据类型。
  • 5.4.加载数据。
  • 5.5.查询数据。

0.新的更新。

Weaviate-client 版本 3.0.0 带来了一些新的变化,查看官方文档了解所有信息这里。

整篇文章现在包含了旧版本和新版本的例子(只有那些被改变的)。

1.什么是 Weaviate?

Weaviate 是一个开源、云原生、模块化的实时矢量搜索引擎。它是为扩展你的机器学习模型而构建的。因为 Weaviate 是模块化的,所以你可以将其用于任何进行数据编码的机器学习模型。Weaviate 带有可选的文本、图像和其他媒体类型的模块,可以根据您的任务和数据进行选择。此外,根据数据的种类,可以使用多个模块。更多信息点击这里。

在本文中,我们将使用文本模块来了解 Weaviate 最重要的功能和能力。文本模块,也称为 text2vec-contextionary ,捕捉文本对象的语义,并将其置于一个概念超空间中。这允许进行语义搜索,与其他搜索引擎的“单词匹配搜索”形成对比。

欲了解更多关于 Weaviate 和 SeMI 技术公司的信息,请访问官方网站。

2.可以用在哪里?

目前,Weaviate 用于以下情况:

  • 语义搜索,
  • 相似性搜索,
  • 图片搜索,
  • 电力推荐引擎,
  • 电商搜索,
  • 网络安全威胁分析,
  • 自动化数据协调,
  • 异常检测,
  • ERP 系统中的数据分类,

以及更多的案例。

3.有什么优势?

要了解什么是我们的优势,你应该问自己这些问题:

  • 你目前的搜索引擎给你的搜索结果质量够好吗?
  • 让你的机器学习模型规模化是不是工作量太大了?
  • 您是否需要快速且近乎实时地对大型数据集进行分类?
  • 你需要将你的机器学习模型扩展到生产规模吗?

我们可以解决所有这些问题。

4.什么是 Weaviate Python 客户端?

Weaviate Python 客户端是一个 Python 包,允许您与 Weaviate 实例进行连接和交互。python 客户端不是一个 Weaviate 实例,但是你可以用它在 Weaviate 云服务上创建一个。它提供了用于导入数据、创建模式、进行分类、查询数据的 API 我们将浏览其中的大部分,并解释如何以及何时可以使用它们。

这个包被发布到 PyPI ( 链接)。另外,PyPI 上有一个 CLI 工具(链接)。

5.如何在一个脆弱的集群中使用 python-client?

在这一节中,我们将经历创建一个 Weaviate 实例的过程,连接到它并探索一些功能。

(jupyter-notebook 可以在这里找到。)

5.0.创建一个弱实例/集群。

创建一个 Weaviate 实例有多种方式。这可以通过使用一个docker-compose.yaml文件来完成,该文件可以在这里生成。对于此选项,您必须安装dockerdocker-compose,并在您的驱动器上留出空间。

另一个选择是在 Weaviate 云服务控制台 (WCS 控制台)上创建一个帐户,并在那里创建一个集群。有不同的集群选项可供选择。如果您没有帐户,请创建一个。

在本教程中,我们将直接从 python 在 WCS 上创建一个集群(您只需要您的 WCS 凭证)。

我们现在要做的第一件事是安装 Weaviate Python 客户端。这可以使用 pip 命令来完成。

>>> import sys
>>> !{sys.executable} -m pip install weaviate-client==2.5.0

为版本 3.0.0 更新

>>> import sys
>>> !{sys.executable} -m pip install weaviate-client==3.0.0

现在,让我们导入软件包,并在 WCS 上创建一个集群。

>>> from getpass import getpass # hide password
>>> import weaviate # to communicate to the Weaviate instance
>>> from weaviate.tools import WCS

更新为 3.0.0 版本。

>>> from getpass import getpass # hide password
>>> import weaviate # to communicate to the Weaviate instance
>>> from weaviate.wcs import WCS

为了对 WCS 或 Weaviate 实例进行身份验证(如果 Weaviate 实例启用了身份验证),我们需要创建一个身份验证对象。目前,它支持两种类型的认证凭证:

  • 密码凭证:weaviate.auth.AuthClientPassword(username='WCS_ACCOUNT_EMAIL', password='WCS_ACCOUNT_PASSWORD')
  • 令牌凭证weaviate.auth.AuthClientCredentials(client_secret=YOUR_SECRET_TOKEN)

对于 WCS,我们将使用密码凭据。

>>> my_credentials = weaviate.auth.AuthClientPassword(username=input("User name: "), password=getpass('Password: '))User name: WCS_ACCOUNT_EMAIL
Password: ········

my_credentials对象包含你的凭证,所以小心不要公开它。

>>> my_wcs = WCS(my_credentials)

现在我们已经连接到 WCS,我们可以使用createdeleteget_clustersget_cluster_configis_ready方法检查集群的状态。

下面是create方法的原型:

my_wcs.create(cluster_name:str=None, 
    cluster_type:str='sandbox',
    config:dict=None,
    wait_for_completion:bool=True) -> str

返回值是创建的集群的 URL。

注意: WCS 名称必须是全局唯一的,因为它们用于创建公共 URL,以便以后访问实例。因此,请确保为 *cluster_name* 选择一个唯一的名称。

如果你想检查笔记本中任何方法的原型和 docstring,运行这个命令: *object.method?* 。您也可以使用 *help()* 功能。
例如:WCS.is_ready?my_wcs.is_ready?help(WCS.is_ready)

>>> cluster_name = 'my-first-weaviate-instance'
>>> weaviate_url = my_wcs.create(cluster_name=cluster_name)
>>> weaviate_url100%|██████████| 100.0/100 [00:56<00:00,  1.78it/s]            
'https://my-first-weaviate-instance.semi.network'>>> my_wcs.is_ready(cluster_name)True

5.1.连接到集群。

现在我们可以用Client对象连接到创建的 weaviate 实例。构造函数如下所示:

weaviate.Client(
    url:str,
    auth_client_secret:weaviate.auth.AuthCredentials=None,
    timeout_config:Union[Tuple[int, int], NoneType]=None,
)

构造函数只有一个必需的参数url,和两个可选的参数:auth_client_secret——如果 weaviate 实例启用了身份验证,则使用timeout_config——设置 REST 超时配置,并且是一个元组(重试次数,超时秒数)。有关参数的更多信息,请查看 docstring。

>>> client = weaviate.Client(weaviate_url)

现在我们连接到了 Weavite,但这并不意味着它已经设置好了。它可能仍会在后台执行一些设置过程。我们可以通过调用.is_live方法来检查 Weaviate 实例的健康状况,并通过调用.is_ready来检查 Weaviate 是否为请求做好了准备。

>>> client.is_ready()True

5.2.获取数据并进行分析。

我们设置了 Weaviate 实例,连接到它并为请求做好准备,现在我们可以后退一步,获取一些数据并对其进行分析。

这一步,对于所有的机器学习模型来说,是最重要的一步。在这里,我们必须决定什么是相关的,什么是重要的,以及使用什么数据结构/类型。

在这个例子中,我们将使用新闻文章来构建数据。为此,我们需要newspaper3k包。

>>> !{sys.executable} -m pip install newspaper3k

注意:如果没有下载任何文章,可能是因为没有下载 nltk punkt 工具。要修复它,请运行下面的单元格。

>>> import nltk *# it is a dependency of newspaper3k*
>>> nltk.download('punkt')

感谢 GitHub 用户@gosha1128 在下面的get_articles_from_newspaper函数中发现了这个被抑制在try/except块中的 bug。

>>> import newspaper
>>> import uuid
>>> import json
>>> from tqdm import tqdm

>>> def get_articles_from_newspaper(
...         news_url: str, 
...         max_articles: int=100
...     ) -> None:
...     """
...     Download and save newspaper articles as weaviate schemas.
...     Parameters
...     ----------
...     newspaper_url : str
...         Newspaper title.
...     """
...     
...     objects = []
...     
...     # Build the actual newspaper    
...     news_builder = newspaper.build(news_url, memoize_articles=False)
...     
...     if max_articles > news_builder.size():
...         max_articles = news_builder.size()
...     pbar = tqdm(total=max_articles)
...     pbar.set_description(f"{news_url}")
...     i = 0
...     while len(objects) < max_articles and i < news_builder.size():
...         article = news_builder.articles[i]
...         try:
...             article.download()
...             article.parse()
...             article.nlp()

...             if (article.title != '' and \
...                 article.title is not None and \
...                 article.summary != '' and \
...                 article.summary is not None and\
...                 article.authors):
... 
...                 # create an UUID for the article using its URL
...                 article_id = uuid.uuid3(uuid.NAMESPACE_DNS, article.url)
... 
...                 # create the object
...                 objects.append({
...                     'id': str(article_id),
...                     'title': article.title,
...                     'summary': article.summary,
...                     'authors': article.authors
...                 })
...                 
...                 pbar.update(1)
... 
...         except:
...             # something went wrong with getting the article, ignore it
...             pass
...         i += 1
...     pbar.close()
...     return objects>>> data = []
>>> data += get_articles_from_newspaper('https://www.theguardian.com/international')
>>> data += get_articles_from_newspaper('http://cnn.com')https://www.theguardian.com/international: 100%|██████████| 100/100 [00:34<00:00,  2.90it/s]
http://cnn.com: 100%|██████████| 100/100 [02:11<00:00,  1.32s/it]

5.3.创建适当的数据类型。

在函数get_articles_from_newspaper中,我们保留文章的标题、摘要作者。我们还为每篇文章计算一个 UUID(通用唯一标识符)。所有这些字段都可以在上面的单元格中看到。

有了这些信息,我们就可以定义一个模式,即每种对象类型的数据结构以及它们之间的关系。该模式是一个嵌套字典。

所以让我们创建Article类模式。我们知道文章有 标题,摘要有作者有

关于模式以及如何创建它们的更多信息可以在这里和这里找到。

>>> article_class_schema = {
...     # name of the class
...     "class": "Article",
...     # a description of what this class represents
...     "description": "An Article class to store the article summary and its authors",
...     # class properties
...     "properties": [
...         {
...             "name": "title",
...             "dataType": ["string"],
...             "description": "The title of the article", 
...         },
...         {
...             "name": "summary",
...             "dataType": ["text"],
...             "description": "The summary of the article",
...         },
...         {
...             "name": "hasAuthors",
...             "dataType": ["Author"],
...             "description": "The authors this article has",
...         }
...     ]
... }

在上面的类模式中,我们创建了一个名为Article的类,描述为An Article class to store the article summary and its authors。描述是为了向用户解释这个类是关于什么的。

我们还定义了 3 个属性:title -文章的标题,类型为string(区分大小写),summary -文章的摘要,数据类型为text(不区分大小写),hasAuthor -文章的作者,数据类型为AuthorAuthor不是原始数据类型,它是我们应该定义的另一个类。原始数据类型的列表可以在这里找到。

注 1: 属性应该总是 cameCase 格式,并且以小写字母开头。
注 2: 属性数据类型始终是列表,因为它可以接受多种数据类型。

将另一个类指定为数据类型称为交叉引用。这样,您可以将数据对象链接在它们之间,并创建一个关系图。

现在让我们以同样的方式创建Author类模式,但是使用属性namewroteArticles

>>> author_class_schema = {
...     "class": "Author",
...     "description": "An Author class to store the author information",
...     "properties": [
...         {
...             "name": "name",
...             "dataType": ["string"],
...             "description": "The name of the author", 
...         },
...         {
...             "name": "wroteArticles",
...             "dataType": ["Article"],
...             "description": "The articles of the author", 
...         }
...     ]
... }

既然我们决定了数据结构,我们可以告诉 Weaviate 我们将导入什么类型的数据。这可以通过访问客户端的schema属性来完成。

可以通过两种不同的方式创建模式:

  1. 使用.create_class()方法,这个选项每次调用只创建一个类。
  2. 使用.create()方法,这个选项一次创建多个类(如果您有完整的模式,这很有用)

我们还可以用.contains()方法检查模式是否存在,或者特定的类模式是否存在。

更多关于模式方法的信息,点击这里。

因为我们分别定义了每个类,所以我们应该使用.create_class()方法。

client.schema.create_class(schema_class:Union[dict, str]) -> None

它还接受指向类定义文件的文件路径或 URL。

>>> client.schema.create_class(article_class_schema)---------------------------------------------------------------------------

UnexpectedStatusCodeException             Traceback (most recent call last)

<ipython-input-12-6d56a74d9293> in <module>
----> 1 client.schema.create_class(article_class_schema)

~/miniconda3/envs/test/lib/python3.6/site-packages/weaviate/schema/crud_schema.py in create_class(self, schema_class)
    138         check_class(loaded_schema_class)
    139         self._create_class_with_premitives(loaded_schema_class)
--> 140         self._create_complex_properties_from_class(loaded_schema_class)
    141 
    142     def delete_class(self, class_name: str) -> None:

~/miniconda3/envs/test/lib/python3.6/site-packages/weaviate/schema/crud_schema.py in _create_complex_properties_from_class(self, schema_class)
    352                 raise type(conn_err)(message).with_traceback(sys.exc_info()[2])
    353             if response.status_code != 200:
--> 354                 raise UnexpectedStatusCodeException("Add properties to classes", response)
    355 
    356     def _create_complex_properties_from_classes(self, schema_classes_list: list) -> None:

UnexpectedStatusCodeException: Add properties to classes! Unexpected status code: 422, with response body: {'error': [{'message': "Data type of property 'hasAuthors' is invalid; SingleRef class name 'Author' does not exist"}]}

正如我们所看到的,我们不能创建引用不存在的数据类型的 class 属性。这并不意味着根本没有创建类Article。让我们从 weaviate 获取模式,看看创建了什么。

>>> # helper function
>>> def prettify(json_dict): 
...     print(json.dumps(json_dict, indent=2))>>> prettify(client.schema.get()){
  "classes": [
    {
      "class": "Article",
      "description": "An Article class to store the article summary and its authors",
      "invertedIndexConfig": {
        "cleanupIntervalSeconds": 60
      },
      "properties": [
        {
          "dataType": [
            "string"
          ],
          "description": "The title of the article",
          "name": "title"
        },
        {
          "dataType": [
            "text"
          ],
          "description": "The summary of the article",
          "name": "summary"
        }
      ],
      "vectorIndexConfig": {
        "cleanupIntervalSeconds": 300,
        "maxConnections": 64,
        "efConstruction": 128,
        "vectorCacheMaxObjects": 500000
      },
      "vectorIndexType": "hnsw",
      "vectorizer": "text2vec-contextionary"
    }
  ]
}

我们没有指定的配置不是强制性的,而是被设置为默认值。

正如我们所看到的,只有hasAuthor属性没有被创建。所以让我们创建Author类。

>>> client.schema.create_class(author_class_schema)
>>> prettify(client.schema.get()){
  "classes": [
    {
      "class": "Article",
      "description": "An Article class to store the article summary and its authors",
      "invertedIndexConfig": {
        "cleanupIntervalSeconds": 60
      },
      "properties": [
        {
          "dataType": [
            "string"
          ],
          "description": "The title of the article",
          "name": "title"
        },
        {
          "dataType": [
            "text"
          ],
          "description": "The summary of the article",
          "name": "summary"
        }
      ],
      "vectorIndexConfig": {
        "cleanupIntervalSeconds": 300,
        "maxConnections": 64,
        "efConstruction": 128,
        "vectorCacheMaxObjects": 500000
      },
      "vectorIndexType": "hnsw",
      "vectorizer": "text2vec-contextionary"
    },
    {
      "class": "Author",
      "description": "An Author class to store the author information",
      "invertedIndexConfig": {
        "cleanupIntervalSeconds": 60
      },
      "properties": [
        {
          "dataType": [
            "string"
          ],
          "description": "The name of the author",
          "name": "name"
        },
        {
          "dataType": [
            "Article"
          ],
          "description": "The articles of the author",
          "name": "wroteArticles"
        }
      ],
      "vectorIndexConfig": {
        "cleanupIntervalSeconds": 300,
        "maxConnections": 64,
        "efConstruction": 128,
        "vectorCacheMaxObjects": 500000
      },
      "vectorIndexType": "hnsw",
      "vectorizer": "text2vec-contextionary"
    }
  ]
}

现在我们已经创建了两个类,但是我们仍然没有hasAuthor属性。不用担心,它可以在任何时候创建,使用模式的属性property和方法create

client.schema.property.create(schema_class_name:str, schema_property:dict) -> None>>> client.schema.property.create('Article', article_class_schema['properties'][2])

现在让我们得到模式,看看它是否是我们所期望的。

>>> prettify(client.schema.get()){
  "classes": [
    {
      "class": "Article",
      "description": "An Article class to store the article summary and its authors",
      "invertedIndexConfig": {
        "cleanupIntervalSeconds": 60
      },
      "properties": [
        {
          "dataType": [
            "string"
          ],
          "description": "The title of the article",
          "name": "title"
        },
        {
          "dataType": [
            "text"
          ],
          "description": "The summary of the article",
          "name": "summary"
        },
        {
          "dataType": [
            "Author"
          ],
          "description": "The authors this article has",
          "name": "hasAuthors"
        }
      ],
      "vectorIndexConfig": {
        "cleanupIntervalSeconds": 300,
        "maxConnections": 64,
        "efConstruction": 128,
        "vectorCacheMaxObjects": 500000
      },
      "vectorIndexType": "hnsw",
      "vectorizer": "text2vec-contextionary"
    },
    {
      "class": "Author",
      "description": "An Author class to store the author information",
      "invertedIndexConfig": {
        "cleanupIntervalSeconds": 60
      },
      "properties": [
        {
          "dataType": [
            "string"
          ],
          "description": "The name of the author",
          "name": "name"
        },
        {
          "dataType": [
            "Article"
          ],
          "description": "The articles of the author",
          "name": "wroteArticles"
        }
      ],
      "vectorIndexConfig": {
        "cleanupIntervalSeconds": 300,
        "maxConnections": 64,
        "efConstruction": 128,
        "vectorCacheMaxObjects": 500000
      },
      "vectorIndexType": "hnsw",
      "vectorizer": "text2vec-contextionary"
    }
  ]
}

一切都如我们所愿。

如果您不想考虑哪个类是在何时创建的,以及哪些属性可能失败或不失败(由于尚不存在的类),有一个解决方案。解决方案是用create方法创建整个模式。所以让我们从 weaviate 中删除这个模式,看看它是如何工作的。

>>> schema = client.schema.get() # save schema
>>> client.schema.delete_all() # delete all classes
>>> prettify(client.schema.get()){
  "classes": []
}

注意,如果我们删除一个模式或一个类,我们会删除与之相关的所有对象。

现在让我们从保存的模式中创建它。

>>> client.schema.create(schema)
>>> prettify(client.schema.get()){
  "classes": [
    {
      "class": "Article",
      "description": "An Article class to store the article summary and its authors",
      "invertedIndexConfig": {
        "cleanupIntervalSeconds": 60
      },
      "properties": [
        {
          "dataType": [
            "string"
          ],
          "description": "The title of the article",
          "name": "title"
        },
        {
          "dataType": [
            "text"
          ],
          "description": "The summary of the article",
          "name": "summary"
        },
        {
          "dataType": [
            "Author"
          ],
          "description": "The authors this article has",
          "name": "hasAuthors"
        }
      ],
      "vectorIndexConfig": {
        "cleanupIntervalSeconds": 300,
        "maxConnections": 64,
        "efConstruction": 128,
        "vectorCacheMaxObjects": 500000
      },
      "vectorIndexType": "hnsw",
      "vectorizer": "text2vec-contextionary"
    },
    {
      "class": "Author",
      "description": "An Author class to store the author information",
      "invertedIndexConfig": {
        "cleanupIntervalSeconds": 60
      },
      "properties": [
        {
          "dataType": [
            "string"
          ],
          "description": "The name of the author",
          "name": "name"
        },
        {
          "dataType": [
            "Article"
          ],
          "description": "The articles of the author",
          "name": "wroteArticles"
        }
      ],
      "vectorIndexConfig": {
        "cleanupIntervalSeconds": 300,
        "maxConnections": 64,
        "efConstruction": 128,
        "vectorCacheMaxObjects": 500000
      },
      "vectorIndexType": "hnsw",
      "vectorizer": "text2vec-contextionary"
    }
  ]
}

这看起来和我们一个类一个类一个属性地创建的模式一模一样。这样,我们现在可以将模式保存在一个文件中,并在下一个会话中通过提供文件路径直接导入它。

# save schema to file
with open('schema.json', 'w') as outfile: 
    json.dump(schema, outfile)
# remove current schema from Weaviate, removes all the data too
client.schema.delete_all()
# import schema using file path
client.schema.create('schema.json')
# print schema
print(json.dumps(client.schema.get(), indent=2))

5.4.加载数据。

现在我们已经准备好了数据,Weaviate 也知道我们拥有什么样的数据,我们可以将ArticlesAuthors添加到 Weaviate 实例中。

可以通过三种不同的方式导入数据。

  1. 逐个对象地迭代添加对象。这可以使用客户端的data_object对象属性来完成。
  2. 分批。这可以通过创建一个适当的批处理请求对象并使用客户机的batch对象属性提交它来完成。(仅在 weaviate-client 版本< 3.0.0 中。
  3. 使用来自weaviate.tools模块的Batcher对象。(仅在 weaviate-client 版本< 3.0.0 中出现。)
  4. 新的 Batch 类在 weaviate-client 版本 3.0.0 中引入。

我们将看到它们的实际应用,但首先让我们强调一下它们之间的区别。

  • 备选方案 1。是添加数据对象和创建引用的最安全的方法,因为它在创建对象之前进行对象验证,而批量导入数据会跳过大部分验证以提高速度。这个选项要求每个对象有一个 REST 请求,因此比成批导入数据要慢。如果您不确定您的数据是否有效,建议使用此选项。
  • 选项 2。如上所述,跳过了大部分数据验证,每批只需要一个 REST 请求。对于这种方法,您只需向一个批处理请求中添加尽可能多的数据(有两种类型:ReferenceBatchRequestObjectsBatchRequest),然后使用客户端的batch对象属性提交它。此选项要求您首先导入数据对象,然后导入引用(确保引用中使用的对象在创建引用之前已经导入)。(仅在 weaviate-client 版本< 3.0.0 中。)
  • 选项 3。依赖于来自 2 的批处理请求。但是对于一个Batcher,你不需要提交任何批量请求,当它满了的时候,它会自动为你做。(只出现在 weaviate-client 版本< 3.0.0 中。)
  • 选项 4: 新的 Batch **类在 weaviate-client 版本 3.0.0 中引入。**新的Batch对象不需要来自 2 的BatchRequests。而是在内部使用。新类还支持 3 种不同的批量加载数据的情况:a)手动——用户可以完全控制何时以及如何添加和创建批量;b)满时自动创建批次;c)使用动态批处理自动创建批次,即每次创建批次时调整批次大小,以避免任何Timeout错误。

5.4.1 使用data_object属性加载数据

在这种情况下,我们只取一篇文章(data[0])并使用data_object属性将其导入 Weaviate。

方法是首先创建对象,然后创建链接它们的引用。

在笔记本中运行client.data_object.create?以获得关于该方法的更多信息。或help(client.data_object.create)处于空转状态。

每个数据对象都应该具有模式中定义的相同格式。

>>> prettify(data[0]){
  "id": "df2a2d1c-9c87-3b4b-9df3-d7aed6bb6a27",
  "title": "Coronavirus live news: Pfizer says jab 100% effective in 12- to 15-year-olds; Macron could announce lockdown tonight",
  "summary": "11:08Surge testing is being deployed in Bolton, Greater Manchester after one case of the South African variant of coronavirus has been identified.\nDr Helen Lowey, Bolton\u2019s director of public health, said that \u201cthe risk of any onward spread is low\u201d and there was no evidence that the variant caused more severe illness.\nPublic Health England identified the case in the area of Wingates Industrial Estate.\nDr Matthieu Pegorie from Public Health England North West said that there was no link to international travel, therefore suggesting that there are some cases in the community.\nThe Department of Health says that enhanced contact tracing will be deployed where a positive case of a variant is found.",
  "authors": [
    "Helen Sullivan",
    "Yohannes Lowe",
    "Martin Belam",
    "Maya Wolfe-Robinson",
    "Melissa Davey",
    "Jessica Glenza",
    "Jon Henley",
    "Peter Beaumont"
  ]
}>>> article_object = {
...     'title': data[0]['title'],
...     'summary': data[0]['summary'].replace('\n', '') # remove newline character
...     # we leave out the `hasAuthors` because it is a reference and will be created after we create the Authors
... }
>>> article_id = data[0]['id']

>>> # validated the object
>>> result = client.data_object.validate(
...     data_object=article_object,
...     class_name='Article',
...     uuid=article_id
... )

>>> prettify(result){
  "error": null,
  "valid": true
}

对象通过了验证测试,现在可以安全地创建/导入它了。

>>> # create the object
>>> client.data_object.create(
...     data_object=article_object,
...     class_name='Article',
...     uuid=article_id # if not specified, weaviate is going to create an UUID for you.
...)'df2a2d1c-9c87-3b4b-9df3-d7aed6bb6a27'

client.data_object.create返回对象的 UUID,如果你指定了一个,它也将被返回。如果你没有指定,Weaviate 会为你生成一个并返回。

恭喜我们已经添加了第一个 weaviate 对象!!!

现在我们实际上可以使用get_by_idget方法通过 UUID 从 Weaviate 中“获取”这个对象。(get未指定和 UUID 返回前 100 个对象)

>>> prettify(client.data_object.get(article_id, with_vector=False)){
  "additional": {},
  "class": "Article",
  "creationTimeUnix": 1617191563170,
  "id": "df2a2d1c-9c87-3b4b-9df3-d7aed6bb6a27",
  "lastUpdateTimeUnix": 1617191563170,
  "properties": {
    "summary": "11:08Surge testing is being deployed in Bolton, Greater Manchester after one case of the South African variant of coronavirus has been identified.Dr Helen Lowey, Bolton\u2019s director of public health, said that \u201cthe risk of any onward spread is low\u201d and there was no evidence that the variant caused more severe illness.Public Health England identified the case in the area of Wingates Industrial Estate.Dr Matthieu Pegorie from Public Health England North West said that there was no link to international travel, therefore suggesting that there are some cases in the community.The Department of Health says that enhanced contact tracing will be deployed where a positive case of a variant is found.",
    "title": "Coronavirus live news: Pfizer says jab 100% effective in 12- to 15-year-olds; Macron could announce lockdown tonight"
  },
  "vectorWeights": null
}

现在让我们创建作者以及ArticleAuthors之间的交叉引用。

添加参考的方式相同,但添加参考时使用client.data_object.reference.add方法。

>>> # keep track of the authors already imported/created and their respective UUID
>>> # because same author can write more than one paper.
>>> created_authors = {}

>>> for author in data[0]['authors']:
...     # create Author
...     author_object = {
...         'name': author,
...         # we leave out the `wroteArticles` because it is a reference and will be created after we create the Author
...     }
...     author_id = client.data_object.create(
...         data_object=author_object,
...         class_name='Author'
...     )
...     
...     # add author to the created_authors
...     created_authors[author] = author_id
...     
...     # add references
...     ## Author -> Article
...     client.data_object.reference.add(
...         from_uuid=author_id,
...         from_property_name='wroteArticles',
...         to_uuid=article_id
...     )
...     ## Article -> Author 
...     client.data_object.reference.add(
...         from_uuid=article_id,
...         from_property_name='hasAuthors',
...         to_uuid=author_id
...     )

在上面的单元格中,我们遍历了文章的所有作者。对于每次迭代,我们首先创建Author,然后添加引用:从AuthorArticle的引用——通过AuthorwroteArticles属性链接,以及从ArticleAuthor的引用——通过ArticlehasAuthors属性。

请注意,双向引用不是必需的。

现在让我们得到这个物体,并看看它。

>>> prettify(client.data_object.get(article_id, with_vector=False)){
  "additional": {},
  "class": "Article",
  "creationTimeUnix": 1617191563170,
  "id": "df2a2d1c-9c87-3b4b-9df3-d7aed6bb6a27",
  "lastUpdateTimeUnix": 1617191563170,
  "properties": {
    "hasAuthors": [
      {
        "beacon": "weaviate://localhost/1d0d3242-1fc2-4bba-adbe-ab9ef9a97dfe",
        "href": "/v1/objects/1d0d3242-1fc2-4bba-adbe-ab9ef9a97dfe"
      },
      {
        "beacon": "weaviate://localhost/c1c8afce-adb6-4b3c-bbe0-2414d55b0c8e",
        "href": "/v1/objects/c1c8afce-adb6-4b3c-bbe0-2414d55b0c8e"
      },
      {
        "beacon": "weaviate://localhost/b851f6fc-a02b-4a63-9b53-c3a8764c82c1",
        "href": "/v1/objects/b851f6fc-a02b-4a63-9b53-c3a8764c82c1"
      },
      {
        "beacon": "weaviate://localhost/e6b6c991-5d7a-447f-89c8-e6e01730f88f",
        "href": "/v1/objects/e6b6c991-5d7a-447f-89c8-e6e01730f88f"
      },
      {
        "beacon": "weaviate://localhost/d03f9353-d4fc-465d-babe-f116a29ccaf5",
        "href": "/v1/objects/d03f9353-d4fc-465d-babe-f116a29ccaf5"
      },
      {
        "beacon": "weaviate://localhost/8ab84df5-c92b-49ac-95dd-bf65f53a38cc",
        "href": "/v1/objects/8ab84df5-c92b-49ac-95dd-bf65f53a38cc"
      },
      {
        "beacon": "weaviate://localhost/e667d7c9-0c9b-48fe-b671-864cbfc84962",
        "href": "/v1/objects/e667d7c9-0c9b-48fe-b671-864cbfc84962"
      },
      {
        "beacon": "weaviate://localhost/9d094f60-3f58-46dc-b7fd-40495be2dd69",
        "href": "/v1/objects/9d094f60-3f58-46dc-b7fd-40495be2dd69"
      }
    ],
    "summary": "11:08Surge testing is being deployed in Bolton, Greater Manchester after one case of the South African variant of coronavirus has been identified.Dr Helen Lowey, Bolton\u2019s director of public health, said that \u201cthe risk of any onward spread is low\u201d and there was no evidence that the variant caused more severe illness.Public Health England identified the case in the area of Wingates Industrial Estate.Dr Matthieu Pegorie from Public Health England North West said that there was no link to international travel, therefore suggesting that there are some cases in the community.The Department of Health says that enhanced contact tracing will be deployed where a positive case of a variant is found.",
    "title": "Coronavirus live news: Pfizer says jab 100% effective in 12- to 15-year-olds; Macron could announce lockdown tonight"
  },
  "vectorWeights": null
}

如我们所见,我们将参考设置为beaconhref。我们无法通过从 weaviate 获取对象来查看数据。我们可以通过查询数据来完成(参见 5.5 节查询数据)。)或通过 UUID(或beacon,或href)获取对象。

>> from weaviate.util import get_valid_uuid # extract UUID from URL (beacon or href)

>>> # extract authors references, lets take only the first one as an example (the article might have only one)
>>> author = client.data_object.get(article_id, with_vector=False)['properties']['hasAuthors'][0]

>>> # get and print data object by providing the 'beacon'
>>> author_uuid = get_valid_uuid(author['beacon']) # can be 'href' too
>>> prettify(client.data_object.get(author_uuid, with_vector=False)){
  "additional": {},
  "class": "Author",
  "creationTimeUnix": 1617191569894,
  "id": "1d0d3242-1fc2-4bba-adbe-ab9ef9a97dfe",
  "lastUpdateTimeUnix": 1617191569894,
  "properties": {
    "name": "Helen Sullivan",
    "wroteArticles": [
      {
        "beacon": "weaviate://localhost/df2a2d1c-9c87-3b4b-9df3-d7aed6bb6a27",
        "href": "/v1/objects/df2a2d1c-9c87-3b4b-9df3-d7aed6bb6a27"
      }
    ]
  },
  "vectorWeights": null
}

到目前为止,还不错(…那又怎样!)

数据对象(client.data_object)的方法更多:.delete.exists.replace.update

也有一些引用的方法(client.data_object.reference ): .add.delete.update

5.4.2 使用批处理加载数据

(只在 weaviate-client 版本< 3.0.0 中。)

批量导入数据与逐个对象添加非常相似。

我们要做的第一件事是为每个对象类型创建一个BatchRequest对象:DataObjectReference。它们被相应地命名为:ObjectsBatchRequestReferenceBatchRequest

让我们为每一批创建一个对象,并导入接下来的 99 篇文章。

**注意:**我想再次提醒您,批量导入/创建数据会跳过一些验证步骤,可能会导致图形损坏。

>>> from weaviate import ObjectsBatchRequest, ReferenceBatchRequest

让我们创建一个向批处理请求添加单个文章的函数。

>>> def add_article(batch: ObjectsBatchRequest, article_data: dict) -> str:
...     
...     article_object = {
...         'title': article_data['title'],
...         'summary': article_data['summary'].replace('\n', '') # remove newline character
...     }
...     article_id = article_data['id']
...     
...     # add article to the object batch request
...     batch.add(
...         data_object=article_object,
...         class_name='Article',
...         uuid=article_id
...     )
...     
...     return article_id

现在让我们创建一个函数,向批处理请求添加一个作者,如果还没有创建作者的话。

>>> def add_author(batch: ObjectsBatchRequest, author_name: str, created_authors: dict) -> str:
...     
...     if author_name in created_authors:
...         # return author UUID
...         return created_authors[author_name]
...     
...     # generate an UUID for the Author
...     author_id = generate_uuid(author)
...     
...     # add author to the object batch request
...     batch.add(
...         data_object={'name': author_name},
...         class_name='Author',
...         uuid=author_id
...     )
...     
...     created_authors[author_name] = author_id
...     return author_id

最后一个功能是添加交叉引用。

>>> def add_references(batch: ReferenceBatchRequest, article_id: str, author_id: str)-> None:
...     # add references to the reference batch request
...     ## Author -> Article
...     batch.add(
...         from_object_uuid=author_id,
...         from_object_class_name='Author',
...         from_property_name='wroteArticles',
...         to_object_uuid=article_id
...     )
...     
...     ## Article -> Author 
...     batch.add(
...         from_object_uuid=article_id,
...         from_object_class_name='Article',
...         from_property_name='hasAuthors',
...         to_object_uuid=author_id
...     )

现在我们可以遍历数据并使用批处理导入数据。

>>> from weaviate.tools import generate_uuid
>>> from tqdm import trange

>>> objects_batch = ObjectsBatchRequest()
>>> reference_batch = ReferenceBatchRequest()

>>> for i in trange(1, 100):
...    
...     # add article to batch request
...     article_id = add_article(objects_batch, data[i])
...     
...     for author in data[i]['authors']:
...         
...         # add author to batch request
...         author_id = add_author(objects_batch, author, created_authors)
...         
...         # add cross references to the reference batch
...         add_references(reference_batch, article_id=article_id, author_id=author_id)
...     
...     if i % 20 == 0:
...         # submit the object batch request to weaviate, can be done with method '.create_objects'
...         client.batch.create(objects_batch)
...        
...         # submit the reference batch request to weaviate, can be done with method '.create_references'
...         client.batch.create(reference_batch)
...        
...         # batch requests are not reusable, so we create new ones
...         objects_batch = ObjectsBatchRequest()
...         reference_batch = ReferenceBatchRequest()

>>> # submit the any object that are left
>>> status_objects = client.batch.create(objects_batch)
>>> status_references = client.batch.create(reference_batch)0%|          | 0/99 [00:00<?, ?it/s]

为了批量导入数据,我们应该为想要导入的数据对象类型创建一个BatchRequest对象。批处理请求对象没有大小限制,因此您应该在需要多少对象时提交它。(请记住,如果您将使用包含太多对象的批处理,可能会导致超时错误,因此请将它保持在合理的大小,以便您的 Weaviate 实例可以处理它。)此外,我们会跟踪已经创建的作者,这样我们就不会一遍又一遍地创建同一个作者。

client.batch.create的调用返回每个被创建对象的状态。如果你想确定一切正常,就检查一下。另外注意即使 Weaviate 未能创建对象,也不意味着批量提交也失败,更多信息请阅读client.batch.create的文档。

5.4.3 使用批处理程序对象加载数据。

(仅在 weaviate-client 版本< 3.0.0 中出现。)

Batcher是一个自动提交对象 weaviate 的类,包括DataObjectReferences。Batcher可以在weaviate.tools模块中找到,它有以下构造器原型:

Batcher(
    client : weaviate.client.Client,
    batch_size : int=512,
    verbose : bool=False,
    auto_commit_timeout : float=-1.0,
    max_backoff_time : int=300,
    max_request_retries : int=4,
    return_values_callback : Callable=None,
)

有关每个参数的解释,请参见文档。

让我们看看它是如何对我们从data中提取的其余对象起作用的。

>>> from weaviate.tools import Batcher

对于 a Batcher,我们只需要将我们想要导入的对象添加到 Weaviate。Batcher有添加objects ( batcher.add_data_object)和添加references ( batcher.add_reference)的特殊方法。此外,它还提供了一个带有关键字参数的batcher.add方法,该方法可以检测您试图添加的数据类型。batcher.add方法使得重用我们上面定义的add_articleadd_authoradd_references函数成为可能。

注:Batcher.add是在weaviate-client版本 2.3.0 中引入的。

让我们使用批处理程序添加来自data的剩余文章和作者。因为Batcher自动提交对象进行 weaviate,所以我们需要在我们完成之后总是.close()它,以确保我们提交的是Batcher中剩余的内容。

如果你像我一样,有时忘记关闭对象,Bather可以在上下文管理器中使用,即与with一起使用。让我们看看它是如何与上下文管理器一起工作的。

>>> # we still need the 'created_authors' so we do not add the same author twice
>>> with Batcher(client, 30, True) as batcher:
...     for i in trange(100, 200):
...         
...         # add article to batcher
...         article_id = add_article(batcher, data[i]) # NOTE the 'bather' object instead of 'objects_batch'
... 
...         for author in data[i]['authors']:
...
...             # add author to batcher
...             author_id = add_author(batcher, author, created_authors) # NOTE the 'bather' object instead of 'objects_batch'
...
...             # add cross references to the batcher
...             add_references(batcher, article_id=article_id, author_id=author_id) # NOTE the 'bather' object instead of 'reference_batch'Batcher object created!

  0%|          | 0/100 [00:00<?, ?it/s]

Updated object batch successfully
Updated reference batch successfully
Updated object batch successfully
Updated reference batch successfully
Updated object batch successfully
Updated reference batch successfully
Updated object batch successfully
Updated reference batch successfully
Updated object batch successfully
Updated reference batch successfully
Updated object batch successfully
Updated reference batch successfully
Updated object batch successfully
Updated reference batch successfully
Updated object batch successfully
Updated reference batch successfully
Updated object batch successfully
Updated reference batch successfully
Updated object batch successfully
Updated reference batch successfully
Updated object batch successfully
Updated reference batch successfully
Updated object batch successfully
Updated reference batch successfully
Updated object batch successfully
Updated reference batch successfully
Updated object batch successfully
Updated reference batch successfully
Updated object batch successfully
Updated reference batch successfully
Updated object batch successfully
Updated reference batch successfully
Updated object batch successfully
Updated reference batch successfully
Updated object batch successfully
Updated reference batch successfully
Updated object batch successfully
Updated reference batch successfully
Batcher object closed!

这就是分批配料器。

这是导入数据的三种方式。选择一个适合你和你的项目。

5.4.4 新增Batch对象

(只在 weaviate-client 版本> =3.0.0。)

新的Batch对象可以用同样的方式访问:client.batch。如 5.4 节所述,这个类有 3 种不同的用法,所以让我们来看看我们到底是怎么做的,以及它们之间的区别。

我们首先要做的是重新定义以下函数:add_articleadd_authoradd_references

>>> from weaviate.batch import Batch # for the typing purposes
>>> from weaviate.util import generate_uuid5 # old way was from weaviate.tools import generate_uuid>>> def add_article(batch: Batch, article_data: dict) -> str:
...    
...     article_object = {
...         'title': article_data['title'],
...         'summary': article_data['summary'].replace('\n', '') # remove newline character
...     }
...     article_id = article_data['id']
...    
...    # add article to the object batch request
...   batch.add_data_object(  # old way was batch.add(...)
...        data_object=article_object,
...        class_name='Article',
...        uuid=article_id
...    )
...    
...    return article_id>>> def add_author(batch: Batch, author_name: str, created_authors: dict) -> str:
...    
...    if author_name in created_authors:
...        # return author UUID
...        return created_authors[author_name]
...    
...    # generate an UUID for the Author
...    author_id = generate_uuid5(author)
...    
...    # add author to the object batch request
...    batch.add_data_object(  # old way was batch.add(...)
...        data_object={'name': author_name},
...        class_name='Author',
...        uuid=author_id
...    )
...    
...    created_authors[author_name] = author_id
...    return author_id>>> def add_references(batch: Batch, article_id: str, author_id: str)-> None:
...    # add references to the reference batch request
...    ## Author -> Article
...    batch.add_reference(  # old way was batch.add(...)
...        from_object_uuid=author_id,
...        from_object_class_name='Author',
...        from_property_name='wroteArticles',
...        to_object_uuid=article_id
...    )
...    
...    ## Article -> Author 
...    batch.add_reference(  # old way was batch.add(...)
...        from_object_uuid=article_id,
...        from_object_class_name='Article',
...        from_property_name='hasAuthors',
...        to_object_uuid=author_id
...    )

现在我们已经修改了上面的函数,使之与新的Batch对象兼容,让我们来看看它们的运行情况。

a)手动

这种方法使用户可以完全控制何时以及如何添加和创建批处理。它非常类似于weaviate-client版本< 3.0.0 的BatchRequests方法,所以让我们来看看我们到底如何使用它(或者从旧版本迁移到它)。

参见下面代码单元中相同方法的上下文管理器方式。(不要同时运行两个单元!

>>> from tqdm import trange>>> for i in trange(1, 100):
...     
...    # add article to the batch
...    article_id = add_article(client.batch, data[i])
...    
...    for author in data[i]['authors']:
...        
...        # add author to the batch
...        author_id = add_author(client.batch, author, created_authors)
...        
...        # add cross references to the batch
...        add_references(client.batch, article_id=article_id, author_id=author_id)
...    
...    if i % 20 == 0:
...        # submit the objects from the batch to weaviate
...        client.batch.create_objects()
...        
...        # submit the references from the batch to weaviate
...        client.batch.create_references()>>> # submit any objects that are left
>>> status_objects = client.batch.create_objects()
>>> status_references = client.batch.create_references()
>>> # if there is no need for the output from batch creation, one could flush both
>>> # object and references with one call
>>> client.batch.flush()

或者,我们可以使用带有上下文管理器的Batch实例,当它存在于上下文中时,就会调用flush()方法。

>>> from tqdm import trange>>> with client.batch as batch:
...     for i in trange(1, 100):
...        
...        # add article to the batch
...        article_id = add_article(batch, data[i])
...        
...        for author in data[i]['authors']:
...            
...            # add author to the batch
...            author_id = add_author(batch, author, created_authors)
...            
...            # add cross references to the batch
...            add_references(batch, article_id=article_id, author_id=author_id)
...        
...        if i % 20 == 0:
...            # submit the objects from the batch to weaviate
...            batch.create_objects()
...            
...            # submit the reference from the batch to weaviate
...            batch.create_references()

b)满时自动创建批次

该方法类似于weaviate-client版本< 3.0.0 的Batcher对象。让我们看看它是如何工作的。

>>> # we still need the 'created_authors' so we do not add the same author twice
>>> client.batch.configure(
...     batch_size=30,
...    callback=None, # use this argument to set a callback function on the batch creation results
...)
>>> for i in trange(100, 200):
...    
...    # add article to the batch
...    article_id = add_article(client.batch, data[i])...    for author in data[i]['authors']:...        # add author to the batch
...        author_id = add_author(client.batch, author,                             created_authors)...        # add cross references to the batch
...        add_references(client.batch, article_id=article_id, author_id=author_id)
>>> client.batch.flush()

当然,我们也可以在这里使用上下文管理器。

>>> # we still need the 'created_authors' so we do not add the same author twice
>>> client.batch.configure(
...     batch_size=30,
...    callback=None, # use this argument to set a callback function on the batch creation results
... )
>>> with client.batch(batch_size=30) as batch: # the client.batch(batch_size=30) is the same as client.batch.configure(batch_size=30)
...     for i in trange(100, 200):...        # add article to the batch
...        article_id = add_article(batch, data[i])...        for author in data[i]['authors']:...            # add author to the batch
...            author_id = add_author(batch, author, created_authors)...            # add cross references to the batch
...            add_references(batch, article_id=article_id, author_id=author_id)

c)使用动态批处理自动创建批次,即每次创建批次时都会调整批次大小,以避免任何Timeout错误。

该方法的工作方式与 b)中描述的方法相同。我们不会用它来运行任何单元格,但是我要提到的是,要启用动态批处理,我们需要做的就是为configure / __call__方法提供另一个参数。

示例:

client.batch.configure(
    batch_size**=**30,
    dynamic**=True**
)

要查看这个新的Batch对象的全部功能,请参见完整的文档这里的或者对Batch或/和任何Batch方法执行help功能,就像这样:help(Batch)

5.5.查询数据。

现在我们已经导入了数据,并准备好进行查询。可以使用客户端对象的query属性(client.query)来查询数据。

使用 GraphQL 语法查询数据,可以通过三种不同的方式完成:

  • GET :从 Weaviate 获取对象的查询。更多信息此处使用client.query.get(class_name, properties).OTHER_OPTIONAL_FILTERS.do()
  • 聚合:聚合数据的查询。更多信息此处使用client.query.aggregate(class_name, properties).OTHER_OPTIONAL_FILTERS.do()
  • 或者使用表示为str的 GraphQL 查询。
    使用client.query.raw()

注意:.get.aggregate都需要调用.do()方法来运行查询。.raw()不会。

现在让我们只获取文章对象及其相应的标题。

获得

>>> result = client.query.get(class_name='Article', properties="title")\
...     .do()
>>> print(f"Number of articles returned: {len(result['data']['Get']['Article'])}")
>>> resultNumber of articles returned: 100

{'data': {'Get': {'Article': [{'title': "The soft power impact of Ruth Bader Ginsburg's decorative collars"},
    {'title': 'After centuries in the ground, these French oaks will soon form part of the new spire at Notre Dame'},
    {'title': 'With tradition and new tech, these Japanese designers are crafting more sustainably made clothing'},
    {'title': "LEGO won't make modern war machines, but others are picking up the pieces"},
    {'title': 'Remember when Jane Fonda revolutionized exercise in a leotard and leg warmers?'},
    {'title': 'Be brave, Taylor tells Manchester City Women before Barcelona return leg'},
    {'title': "'In the middle of a war zone': thousands flee as Venezuela troops and Colombia rebels clash"},
    {'title': "Destruction of world's forests increased sharply in 2020"},
    {'title': "Climate crisis 'likely cause' of early cherry blossom in Japan"},
    {'title': "What's in a vaccine and what does it do to your body?"},
    {'title': 'Zunar and Fahmi Reza: the cartoonists who helped take down Najib Razak'},
    {'title': 'Downing Street suggests UK should be seen as model of racial equality'},
    {'title': "'It's hard, we're neighbours': the coalmine polluting friendships on Poland's borders"},
    {'title': 'Why we are all attracted to conspiracy theories – video'},
    {'title': 'UK criticised for ignoring Paris climate goals in infrastructure decisions'},
    {'title': 'GameStop raids Amazon for another heavy-hitter exec'},
    {'title': 'The World Economic Forum says it will take an extra 36 years to close the gender gap'},
    {'title': 'Share a story with the Guardian'},
    {'title': "Paddleboarding and a released alligator: Tuesday's best photos"},
    {'title': "Ballerina Chloé Lopes Gomes alleged racism at her company. Now she says it's time for change"},
    {'title': 'How ancient Egyptian cosmetics influenced our beauty rituals'},
    {'title': 'Why is Australia trying to regulate Google and Facebook – video explainer'},
    {'title': 'Back in the swing and the swim: England returns to outdoor sport – in pictures'},
    {'title': "Biden's tariffs threat shows how far Brexit Britain is from controlling its own destiny"},
    {'title': 'Our cities may never look the same again after the pandemic'},
    {'title': "World's first digital NFT house sells for $500,000"},
    {'title': "The untold story of Ann Lowe, the Black designer behind Jackie Kennedy's wedding dress"},
    {'title': 'Deliveroo shares slump on stock market debut'},
    {'title': 'Hundreds of people missing after fire in Rohingya refugee camp in Bangladesh – video'},
    {'title': "Why Beijing's Serpentine Pavilion signals a new age for Chinese architecture"},
    {'title': 'My Brother’s Keeper: a former Guantánamo detainee, his guard and their unlikely friendship - video'},
    {'title': 'Has your family been affected by the Brazilian or South African variants of Covid-19?'},
    {'title': 'New Zealand raises minimum wage and increases taxes on the rich'},
    {'title': 'Deliveroo shares plunge on market debut - business live'},
    {'title': "Seoul's burgeoning drag scene confronts conservative attitudes"},
    {'title': "David Hockney at 80: An encounter with the world's most popular artist"},
    {'title': 'Una avanzada licuadora Nutribullet al mejor precio'},
    {'title': "The 'fox eye' beauty trend continues to spread online. But critics insist it's racist"},
    {'title': 'Lupita: the indigenous activist leading a new generation of Mexican women – video'},
    {'title': "Hong Kong's vast $3.8 billion rain-tunnel network"},
    {'title': 'See how tattoo art has changed since the 18th century'},
    {'title': "Hong Kong Disneyland's new castle is an architectural vision of diversity"},
    {'title': 'Rosamund Pike in "I Care a Lot" and six more recommendations if you love an antiheroine'},
    {'title': 'How NFTs are fueling a digital art boom'},
    {'title': "'We’re not little kids': leading agents ready for war with Fifa over new rules"},
    {'title': 'A photographic history of men in love'},
    {'title': "Hedge fund meltdown: Elizabeth Warren suggests regulators should've seen it coming"},
    {'title': 'Palau to welcome first tourists in a year with presidential escort'},
    {'title': 'Coronavirus: how wealthy nations are creating a ‘vaccine apartheid’'},
    {'title': 'UK economy poised to recover after Covid-19 second wave'},
    {'title': 'Missed it by that much: Australia falls 3.4m doses short of 4m vaccination target by end of March'},
    {'title': "Meet North Korea's art dealer to the West"},
    {'title': 'Why Australia remains confident in AstraZeneca vaccine as two countries put rollout on ice'},
    {'title': 'Exclusive: Jamie Dimon speaks out on voting rights even as many CEOs remain silent'},
    {'title': "Green investing 'is definitely not going to work’, says ex-BlackRock executive"},
    {'title': 'European commission says AstraZeneca not obliged to prioritise vaccines for UK'},
    {'title': '‘Honey, I forgot to duck’: the attempt to assassinate Ronald Reagan, 40 years on'},
    {'title': 'Graba tus próximas aventuras con esta GoPro de oferta'},
    {'title': "Europe’s 'baby bust': can paying for pregnancies save Greece? - video"},
    {'title': "After the deluge: NSW's flood disaster victims begin cleanup – in pictures"},
    {'title': "Wolfsburg v Chelsea: Women's Champions League quarter-final – live!"},
    {'title': "'A parallel universe': the rickety pleasures of America's backroads - in pictures"},
    {'title': "'Nomadland': Chloé Zhao and crew reveal how they made one of the year's best films"},
    {'title': 'Seaspiracy: Netflix documentary accused of misrepresentation by participants'},
    {'title': 'Unblocking the Suez canal – podcast'},
    {'title': 'About half of people in UK now have antibodies against coronavirus'},
    {'title': 'Top 10 books about New York | Craig Taylor'},
    {'title': 'Is Moldova ready to embrace an unmarried, childfree president? | Europe’s baby bust – video'},
    {'title': 'This woman left North Korea 70 years ago. Now virtual reality has helped her return'},
    {'title': "'Immediate and drastic.' The climate crisis is seriously spooking economists"},
    {'title': "Under Xi's rule, what is China's image of the 'ideal' man?"},
    {'title': "'Hamlet' in the skies? The story behind Taiwan's newest airline, STARLUX"},
    {'title': 'Pokémon at 25: How 151 fictional species took over the world'},
    {'title': '‘Similar to having a baby, the euphoria’: rediscovery of rare gecko delights experts'},
    {'title': 'How Budapest became a fine dining force to be reckoned with'},
    {'title': "Teen who filmed killing tells court George Floyd was 'begging for his life'"},
    {'title': 'Empowering, alluring, degenerate? The evolution of red lipstick'},
    {'title': 'Real-world locations straight out of a Wes Anderson movie'},
    {'title': 'The club kid designer dressing the most powerful women in US politics'},
    {'title': "Fashion gaffes are a reflection of the industry's diversity problem"},
    {'title': 'Our colorful clothes are killing the environment'},
    {'title': 'Hazte con un Roku SE a mitad de precio'},
    {'title': 'Why does Bollywood use the offensive practice of brownface in movies?'},
    {'title': "Why Washington Football Team may stick with their 'so bad it’s good' name"},
    {'title': "Graphic novel on the Tiananmen Massacre shows medium's power to capture history"},
    {'title': 'Could a Norway boycott of the Qatar World Cup change the future of football?'},
    {'title': 'Las 5 cosas que debes saber este 31 de marzo: Así es una instalación que alberga a menores migrantes'},
    {'title': 'Multiplica el alcance de tu Wi-Fi con este repetidor rebajado un 50%'},
    {'title': "'Lack of perspective': why Ursula von der Leyen's EU vaccine strategy is failing"},
    {'title': 'Redder Days by Sue Rainsford review – waiting for the end of the world'},
    {'title': 'Dita Von Teese and Winnie Harlow star in a star-studded fashion film'},
    {'title': 'The Suez fiasco shows why ever bigger container ships are a problem'},
    {'title': 'The most anticipated buildings set to shape the world in 2020'},
    {'title': "Elite minority of frequent flyers 'cause most of aviation's climate damage'"},
    {'title': "I love my boyfriend – but I really don't want to have sex with him"},
    {'title': 'Amazon-backed Deliveroo crashes in London IPO'},
    {'title': 'People are calling for museums to be abolished. Can whitewashed American history be rewritten?'},
    {'title': 'Ruby Rose on gender, bullying and breaking free: ‘I had a problem with authority’'},
    {'title': 'Merkel, Macron and Putin in talks on using Sputnik V jab in Europe, says Kremlin'},
    {'title': 'After fighting cancer, Tracey Emin returns to the art world with raw, emotional works'}]}},
 'errors': None}

因此我们可以看到result只包含 100 篇文章,这是由于默认的限制 100。让我们改变它。

>>> result = client.query.get(class_name='Article', properties="title")\
...     .with_limit(200)\
...     .do()
>>> print(f"Number of articles returned: {len(result['data']['Get']['Article'])}")Number of articles returned: 200

通过堆叠多种方法,我们可以做得更多。.get可用的方法有:

  • .with_limit -设置返回对象的另一个限制。
  • .with_near_object -获取与传递给该方法的对象相似的对象。
  • .with_near_text -获取与传递给该方法的文本相似的对象。
  • .with_near_vector -获取与传递给该方法的 vector 相似的对象。
  • .with_where -获取使用Where过滤器过滤的对象,参见此链接获取示例和解释。

此外,可以使用将 GraphQL 查询作为字符串返回的.build()方法来代替.do()。这个字符串可以传递给.raw()方法。

**注意:**每个查询只能使用一个.with_near_*

>>> client.query.get(class_name='Article', properties="title")\
...     .with_limit(5)\
...     .with_near_text({'concepts': ['Fashion']})\
...     .do(){'data': {'Get': {'Article': [{'title': 'Dita Von Teese and Winnie Harlow star in a star-studded fashion film'},
    {'title': "Fashion gaffes are a reflection of the industry's diversity problem"},
    {'title': "Bottega Veneta ditches Instagram to set up 'digital journal'"},
    {'title': 'Heir to O? Drew Barrymore launches lifestyle magazine'},
    {'title': 'Our colorful clothes are killing the environment'}]}},
 'errors': None}

使用Get我们可以看到每个对象的交叉引用。我们将为此使用.raw()方法,因为用任何现有的.with_*方法都不可能。

>>> query = """
... {
...   Get {
...     Article(limit: 2) {
...       title
... 
...       hasAuthors {         # the reference
...         ... on Author {    # you always set the destination class
...           name             # the property related to target class
...         }
...       }
...     }
...   }
... }
... """

>>> prettify(client.query.raw(query)['data']['Get']['Article'])[
  {
    "hasAuthors": [
      {
        "name": "Rhonda Garelick"
      }
    ],
    "title": "The soft power impact of Ruth Bader Ginsburg's decorative collars"
  },
  {
    "hasAuthors": [
      {
        "name": "Saskya Vandoorne"
      }
    ],
    "title": "After centuries in the ground, these French oaks will soon form part of the new spire at Notre Dame"
  }
]

骨料

我们可以使用.aggregate来计算满足特定条件的对象数量。

>>> # no filter, count all objects of class Article
>>> client.query.aggregate(class_name='Article')\
...     .with_meta_count()\
...     .do(){'data': {'Aggregate': {'Article': [{'meta': {'count': 200}}]}},
 'errors': None}>>> # no filter, count all objects of class Author
>>> client.query.aggregate(class_name='Author')\
...     .with_meta_count()\
...     .do(){'data': {'Aggregate': {'Author': [{'meta': {'count': 258}}]}}, 'errors': None}

以下是.aggregate支持的方法。

  • .with_meta_count将元计数设置为真。用于计算每个过滤组的对象数。
  • .with_fields -聚合查询返回的字段。
  • .with_group_by_filter -设置一个GroupBy滤镜。查看此链接了解更多关于过滤器的信息。
  • .with_where -使用Where过滤器聚集物体。参见此链接获取示例和解释。

当然,在查询数据时,可能性是无穷无尽的。体验这些功能的乐趣。

(jupyter-notebook 可以在这里找到。)

请随时在 GitHub 上查看并为 weaviate-client 投稿。

获得 TensorFlow 开发者认证

原文:https://towardsdatascience.com/getting-tensorflow-developer-certified-3975d1a26050?source=collection_archive---------12-----------------------

即使你有一台 M1 Mac 电脑,你也可以用它来通过测试

准备了很久,最近参加并通过了 TensorFlow 开发者证书考试。该考试测试您使用 TensorFlow 处理图像、时间序列和文本数据的熟练程度。除了这些领域,它还涵盖了减少过度拟合的策略,如增强和辍学层。

路易斯·基根在 Unsplash 上的照片

你为什么要获得认证?

有两个原因你应该尝试考试。第一,拿到这个证书对学习 TensorFlow 是一个很大的激励。其次,这也是证明和展示你技能的绝佳机会。

如果你以前没有任何机器学习的经验,那么最好先学习一下(使用这些示例资源作为开端: 1 、 2 、 3 、 4 ),然后再回来应付考试。

资源

我一年前第一次读到关于考试的消息,但只是在去年圣诞节才开始积极地追求它。我最初的计划是在寒假里做准备课程,但最终,我忙于大学的工作,不得不推迟。在三月份,我开始准备,为此我使用了以下资源。

1.深度学习。AI TensorFlow 开发者专业证书

费用:七天免费后每月约 50 美元。或者免费审核。

它教什么

尽管我已经在 TensorFlow 和 Keras 上有了两年左右的经验,我还是决定开始进行深度学习。Coursera 上的 AI TensorFlow 开发者专业证书。它首先介绍 TensorFlow,教你如何建立和训练基本的神经网络。如果您对这些主题有经验,可以跳过这一部分。第二部分涵盖卷积神经网络,更大的网络,转移学习,和增强技术。然后,在第三个课程中,你将关注自然语言处理:你从嵌入开始,前进到序列模型,并以创作诗歌结束。最后,在最后一门课程中,您将学习时间序列数据。

对考试的用处

如果你有一到两年的 TensorFlow 经验,那么你可以跳过这个课程。或者,甚至更好的是:免费旁听个别课程,并检查到目前为止你可能错过了什么。如果你没有任何经验,那么这个课程是强烈推荐的。有两种选择。首先,你可以在 YouTube 上免费观看《T4》。其次,还可以做 2021 年 TensorFlow 开发者证书:零到精通课程(也可以这里,代码是这里)。

尽管证书是一个很好的正面评价的资源,但它不是我唯一的资源。此外,我还参加了一个定制课程来学习更多知识,主要是在我为大学和个人项目所做的基础上。

2.重新实施一份文件

费用:免费。

它教什么

为了深入了解 TensorFlow,我接受了重新实现一篇论文的挑战。作为参考,我选择了一篇 CycleGAN 的论文,它涵盖了将象征性音乐从一种流派翻译成另一种流派。结果,我学到了很多东西:如何编写高效的输入管道、高效的预处理和定制的训练循环。

对考试的用处

很难评估我学到的关于证书的知识有多大用处。它通常超出了考试的要求,但在幕后仍然证明是有价值的。这是因为它不仅仅是编码,而且是如何处理问题和寻找让你进步的解决方案。但是,在后续证书中,可能会对此进行测试。尽管如此,我还是有一个很好的机会用 PyCharm 深入研究编码,这是考试所必需的。

3.使用 TFRecords

费用:免费。

它教什么

如前所述,在重新实现论文时,我还使用了 TFRecords,TensorFlow 存储数据的原生格式。这对于开始来说有点挑战性,但是一旦你掌握了它,它就非常有价值。这种格式的最大好处是与 TensorFlow 的数据集处理的高度互操作性、从磁盘的快速流式传输以及存储数据的高效方式。更详细的信息可以在这个 TensorFlow 教程和这个 Colab 笔记本中找到。

对考试的有用性

我发现这个不是考试必考的,可以跳过这一部分。然而,对于证书范围之外的项目,使用 TFRecords 肯定是好的。

4.深度学习简介

费用:免费。

它教什么

深度学习的介绍由麻省理工学院免费提供。这个讲座在 12 节课中涵盖了深度学习领域,同时也适用于非技术人员。它从深度学习的一般介绍开始,并继续处理序列和图像数据。之后,它涵盖了其他主题,如强化学习和生成技术。

对考试的有用性

前三节课和第八节课是对考试最有用的。但是,我建议您看完整个课程,因为它的表现非常好。此外,检查附带的代码。

5.习惯 PyCharm

费用:免费。

它教什么

考试需要 PyCharm 代码编辑器。跟随示例项目教你如何设置项目、运行和调试代码。

对考试的用处

如果您有使用 PyCharm 的经验,那么您可以跳过这一步。如果您是 PyCharm 的新手,那么这是必须的。在我看来,这将进一步帮助你在尝试证书之前进行几个较小的项目,因为它们将教会你更多关于 PyCharm 的知识。而你已经知道的,考试的时候就不用查了。

6.候选人手册

费用:免费。

它教什么

这本手册介绍了考试,考什么,怎么考等等。

对考试的用处

强制性的。即使您有使用 TensorFlow 的经验,也请阅读此文档。

7.TensorFlow 教程

费用:免费。

他们教什么

在 TensorFlow 的主页上列出了很多教程。不过初学者类别就足够了;它涵盖了图像和文本分类、回归和基本的 I/O 工具。

对考试的有用性

如果您已经完成了 TensorFlow 开发者证书课程或其替代课程,那么您可以跳过此课程。如果您还没有,那么教程是很有价值的资源。

我是如何准备的

我在三月份参加了 TensorFlow 课程,每天留出一个小时来进步。以这样的速度,我在近三周内完成了它。我没有为其他资源留出任何特定的时间:大部分工作是为大学项目做的,这教会了我有价值的东西。

如果你正在寻找一门课程,我推荐如下:

  1. 观看深度学习介绍讲座
  2. 每天留出一两个小时,先学习张量流课程或其他课程
  3. 在此期间,使用 PyCharm 进行编码
  4. 为了加深理解,重新实现一篇论文或做几个 TensorFlow 的教程
  5. 阅读候选人手册
  6. 设置一个示例测试环境(说明在上面的手册中;如有问题,请参见下文)
  7. 购买并最终通过考试

在考试中使用 M1 Mac 电脑

在较新的苹果 M1 电脑上,设置考试环境可能会有问题。如果这是你的情况,诉诸以下两个选项。

第一种解决方案是故意让环境设置失败,然后开始测试。然后,就

  1. 把考试代码复制到谷歌实验室,
  2. 在那里解决
  3. 在那里训练模特
  4. 下载它们
  5. 将它们放在正确的文件夹中(考试时会很清楚,不要担心)
  6. 上传它们(也变得清晰)
  7. 并且让他们毫无问题的打分。

第二种解决方案需要更多的设置:

  1. 创建一个单独的环境:这也可以是 Anaconda 环境
  2. 从任何来源(pip、conda 等)安装尽可能多的软件包——实际的软件包版本不是关键的
  3. 开始检查(即使设置可能已经失败)
  4. 在考试期间,将 python 解释器切换到之前创建的独立环境
  5. 通过考试(如果考试失败,就求助于 Colab 解决方案)。

我在 M1 的 MacBook 上应付考试时,成功地混合使用了这两种方法。如果你设置虚拟环境有困难,请参考这些链接:苹果官方文档;更详细的版本由我;尼科斯的方法在这里。

考试

一旦你购买了每次 100 美元的考试,你将会得到详细的操作说明。在不暴露任何细节的情况下,考试涵盖了你在各个方面的能力。这些类别越来越难解决。但是,你可以使用任何你想要的资源;最后你只需要上传每个类别的训练模型。

对于其中一个类别,我不能运行代码,所以我切换到 Colab。然后我在那里训练模型,把它下载到我的电脑上,并作为考试的一部分上传。

您有五个小时的时间来完成所有问题。我发现这是相当多的时间。考试的时候,你已经有过的感觉了。如果你能解决所有问题(即上传一个在评分基础设施上达到 100%的经过训练的模型),你就通过了。总的来说,我的目标是在进步之前完美地解决一个类别。除了一个例外,这种方法效果很好。

提交考试或考试时间结束后,我们会通过电子邮件通知您考试结果。对我来说,这花了不到一分钟,迎接我的是

“恭喜你,你已经通过了 TensorFlow 开发者证书考试!”

如果你使用了上面描述的资源,你也会听到这些话!

充分利用 scikit-learn 管道

原文:https://towardsdatascience.com/getting-the-most-out-of-scikit-learn-pipelines-c2afc4410f1a?source=collection_archive---------4-----------------------

帮助您在单个网格搜索中组合转换和建模参数的高级技术

照片由 SpaceX 从 Pexels 拍摄

Pipelines是 scikit-learn 包中极其有用和通用的对象。它们可以与其他 sklearn 对象嵌套和组合,以创建可重复且易于定制的数据转换和建模工作流。

使用Pipeline可以做的最有用的事情之一是将数据转换步骤与最后的估计器(模型)联系在一起。然后,您可以将这个复合估计器传递给一个GridSearchCV对象,并在一个镜头中搜索转换参数和模型超参数。但是学习如何构造这些对象,以及如何在不同的级别获取和设置属性需要一些实践。

这篇文章将使用一个 NLP 分类示例来演示如何将一个ColumnTransformer与一个PipelineGridSearchCV结合起来。我们将介绍一些具体的技术和技巧,比如如何:

  • 使用ColumnTransformer作为Pipeline步骤,以不同的方式转换不同类型的数据列
  • 构建一个复合管道,可用于同时为数据转换和建模进行网格搜索参数
  • 指定要一起应用的复杂网格搜索参数集(例如二进制文本矢量化或 Tf-Idf 规范化,但不能同时应用两者)
  • 使用passthrough绕过或跳过Pipeline中的一个步骤
  • 使用set_params()动态设置Pipeline中的单个参数,以便在GridSearchCV之外进行测试
  • 从最佳估计器的深度检索特征名称,用于解释

示例数据介绍

我将使用我为之前的项目收集的示例数据,包括《纽约时报》发布到脸书的一组文章的文本和元数据。

数据已经被清理,但是仍然需要在建模之前进行转换。这对我们来说是一个很好的例子,因为有几种不同类型的功能需要以不同的方式进行转换:

  • article_text:要进行标记化和矢量化的文本
  • topics:包含每篇文章的适用主题列表的列,将被转换为每个主题的单独特性
  • 其余的是我们需要一次性编码的分类特征

我们的示例数据集中的列存储在数据帧中

这里的target已经被二进制化了,0 表示读者对《脸书邮报》的参与度低,1 表示参与度高。此示例分类问题的目标是预测敬业度。

为了做好准备,我们将灵活地为变量分配不同的列名集,并将数据分成训练集和测试集。

执行训练-测试-分割,并为不同组的列创建变量

为转换生成 ColumnTransformer

首先,我们将创建一个ColumnTransformer来转换用于建模的数据。我们将使用ColumnTransformer来代替Pipeline,因为它允许我们为不同的列指定不同的转换步骤,但是会产生一个单一的特性矩阵。

提醒一下(或者介绍一下,如果你以前没有用过的话)regular Pipelines将一个元组列表作为输入,其中每个元组中的第一个值是步骤名,第二个值是估计器对象。

pipe = Pipeline([
    ('vect', CountVectorizer()),
    ('clf', LogisticRegression())
])

ColumnTransformers的构建与Pipelines相似,除了在每个元组中包含第三个值,表示在步骤中要转换的列。因为我们的数据在 DataFrame 中,所以我们可以传递表示 DataFrame 列名的字符串和字符串列表。如果数据存储在数组中,可以传递列索引或列索引数组。

我已经将不同类别的列的名称存储为变量,所以它们可以像这样动态地传递给ColumnTransformer:

cols_trans = ColumnTransformer([
    ('txt', TfidfVectorizer(), **text_col**),
    ('txt_kw', CountVectorizer(), **topic_col**),
    ('ohe', OneHotEncoder(drop='first'), **cat_cols**), 
    remainder='drop'
])

Pipeline步骤是连续执行的,第一步的输出传递给第二步,依此类推。**ColumnTransformers** 的不同之处在于,每一步都是单独执行的,转换后的特征在最后连接在一起。这使我们不必自己做连接,并且当我们准备好解释我们的最佳模型时,可以很容易地获得特性名称的完整列表。

默认情况下,传递到ColumnTransformer中的任何没有被指定转换的列都将被删除(remainder='drop')。如果您有想要包含但不需要转换的列,请指定 remainder='passthrough'。稍后我们将再次看到passthrough参数,因为它可以在 sklearn 的其他上下文中使用,以跳过或绕过一个处理步骤。

以下是我们示例工作流中该步骤的完整代码,解释如下:

创建 ColumnTransformer 来转换我们拥有的不同类型的数据列

  • text_col将使用TfidfVectorizer进行转换,T5 将标记每个文档的文本并创建向量以形成文档术语矩阵。我们将能够为这种转换指定许多不同的选项,这些选项将影响最终的模型性能,例如要删除的停用词、要生成的 n 元语法的大小、要包含的最大特征数量,以及如何标准化文档术语矩阵中的标记计数。然而,由于我们将为网格搜索中要尝试的那些参数指定不同的选项,我们现在将只创建 transformer 的一个普通实例。
  • topic_col已经是一个单列的主题列表,我们想从中创建一个二进制文档术语矩阵。我们将使用CountVectorizer,并给它一个不做任何事情的自定义analyzer。默认的analyzer通常执行预处理、标记化和 n 元语法生成,并输出一个标记列表,但是因为我们已经有了一个标记列表,我们将按原样传递它们,并且CountVectorizer将返回一个现有主题的文档术语矩阵,而不进一步标记它们。
  • cat_cols由我们的分类列组成,我们将使用OneHotEncoder对其进行一次性编码。我们将指定的唯一参数是删除每一列中的第一个类别,因为我们将使用回归模型。

提示:TfidfVectorizerCountVectorizer都期望一个一维数组,所以列名需要作为字符串而不是列表传递给ColumnTransformer,即使列表只有一个条目。如果您给这些变压器中的任何一个一个列表,您将得到一个关于incompatible row dimensions的错误。大多数其他 sklearn 变形器期望一个 2-D 数组(比如OneHotEncoder),所以即使你只变形一列,你也需要传递一个列表。

很好,现在我们有了cols_trans,一个ColumnTransformer对象,它将输出一个带有我们转换后的数据的特征矩阵。

使用 ColumnTransformer 和模型创建管道

接下来,我们将创建一个Pipeline,其中cols_trans是第一步,逻辑回归分类器是第二步。

from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegressionpipe = Pipeline([
    ('trans', cols_trans),
    ('clf', LogisticRegression(max_iter=300, class_weight='balanced'))
])

如果我们调用pipe.fit(X_train, y_train),我们将转换我们的X_train数据,并在一个单一的步骤中拟合逻辑回归模型。注意,我们可以简单地使用fit(),并且不需要做任何特殊的事情来指定我们想要在第一步中拟合和转换数据;管道会知道该做什么。

一旦你开始嵌套Pipelines和其他对象,你想要刷新你自己关于如何执行这些步骤。一种方法是将 sklearn 的display参数设置为'diagram',以便在调用管道对象本身的display()时显示一个 HTML 表示。HTML 将在 Jupyter 笔记本中进行交互,您可以点击每一步来展开它,并查看其当前参数。

from sklearn import set_configset_config(display='diagram')# with display='diagram', simply use display() to see the diagram
display(pipe)# if desired, set display back to the default
set_config(display='text')

管道的 HTML 显示示例,显示了参数

准备网格搜索参数

我们将能够把我们的pipe对象传递给GridSearchCV来同时搜索转换和分类器模型的参数。GridSearchCV将需要一个搜索参数字典来尝试,其中键是管道步骤/参数名,值是要搜索的参数列表。

像我们这样将一个ColumnTransformer嵌套在一个Pipeline中,可能很难得到这个字典的正确键,因为它们是以每个步骤的标签命名的,用邓德尔斯__作为分隔符。获得所有可用选项列表的最简单方法是使用pipe.get_params()

您应该会看到类似这样的内容:

{'memory': None,
 'steps': [('trans',
   ColumnTransformer(transformers=[('txt', TfidfVectorizer(), 'article_text'),
                                   ('txt_kw',
                                    CountVectorizer(analyzer=<function no_analyzer at 0x7fbc5f4bac10>),
                                    'topics'),
                                   ('ohe', OneHotEncoder(drop='first'),
                                    ['section_name', 'word_count_cat',
                                     'is_multimedia', 'on_weekend'])])),
  ('clf', LogisticRegression(class_weight='balanced', max_iter=300))],
 'verbose': False,
 'trans': ColumnTransformer(transformers=[('txt', TfidfVectorizer(), 'article_text'),
                                 ('txt_kw',
                                  CountVectorizer(analyzer=<function no_analyzer at 0x7fbc5f4bac10>),
                                  'topics'),
                                 ('ohe', OneHotEncoder(drop='first'),
                                  ['section_name', 'word_count_cat',
                                   'is_multimedia', 'on_weekend'])]),
 'clf': LogisticRegression(class_weight='balanced', max_iter=300),
 'trans__n_jobs': None,
 'trans__remainder': 'drop',
 'trans__sparse_threshold': 0.3,
 'trans__transformer_weights': None,
 'trans__transformers': [('txt', TfidfVectorizer(), 'article_text'),
  ('txt_kw',
   CountVectorizer(analyzer=<function no_analyzer at 0x7fbc5f4bac10>),
   'topics'),
  ('ohe',
   OneHotEncoder(drop='first'),
   ['section_name', 'word_count_cat', 'is_multimedia', 'on_weekend'])],
 'trans__verbose': False,
 'trans__txt': TfidfVectorizer(),
 'trans__txt_kw': CountVectorizer(analyzer=<function no_analyzer at 0x7fbc5f4bac10>),
 'trans__ohe': OneHotEncoder(drop='first'),
 'trans__txt__analyzer': 'word',
 'trans__txt__binary': False,
 'trans__txt__decode_error': 'strict',
 'trans__txt__dtype': numpy.float64,
 'trans__txt__encoding': 'utf-8',
 'trans__txt__input': 'content',
 'trans__txt__lowercase': True,
 'trans__txt__max_df': 1.0,
 'trans__txt__max_features': None,
 'trans__txt__min_df': 1,
 'trans__txt__ngram_range': (1, 1),
 'trans__txt__norm': 'l2',
 'trans__txt__preprocessor': None,
 'trans__txt__smooth_idf': True,
 'trans__txt__stop_words': None,
 'trans__txt__strip_accents': None,
 'trans__txt__sublinear_tf': False,
 'trans__txt__token_pattern': '(?u)\\b\\w\\w+\\b',
 'trans__txt__tokenizer': None,
 'trans__txt__use_idf': True,
 'trans__txt__vocabulary': None,
 'trans__txt_kw__analyzer': <function __main__.no_analyzer(doc)>,
 'trans__txt_kw__binary': False,
 'trans__txt_kw__decode_error': 'strict',
 'trans__txt_kw__dtype': numpy.int64,
 'trans__txt_kw__encoding': 'utf-8',
 'trans__txt_kw__input': 'content',
 'trans__txt_kw__lowercase': True,
 'trans__txt_kw__max_df': 1.0,
 'trans__txt_kw__max_features': None,
 'trans__txt_kw__min_df': 1,
 'trans__txt_kw__ngram_range': (1, 1),
 'trans__txt_kw__preprocessor': None,
 'trans__txt_kw__stop_words': None,
 'trans__txt_kw__strip_accents': None,
 'trans__txt_kw__token_pattern': '(?u)\\b\\w\\w+\\b',
 'trans__txt_kw__tokenizer': None,
 'trans__txt_kw__vocabulary': None,
 'trans__ohe__categories': 'auto',
 'trans__ohe__drop': 'first',
 'trans__ohe__dtype': numpy.float64,
 'trans__ohe__handle_unknown': 'error',
 'trans__ohe__sparse': True,
 'clf__C': 1.0,
 'clf__class_weight': 'balanced',
 'clf__dual': False,
 'clf__fit_intercept': True,
 'clf__intercept_scaling': 1,
 'clf__l1_ratio': None,
 'clf__max_iter': 300,
 'clf__multi_class': 'auto',
 'clf__n_jobs': None,
 'clf__penalty': 'l2',
 'clf__random_state': None,
 'clf__solver': 'lbfgs',
 'clf__tol': 0.0001,
 'clf__verbose': 0,
 'clf__warm_start': False}

向下滚动到输出的底部,您将看到以您需要传递给GridSearchCV的精确格式列出的每一步的参数。将只列出每个参数的当前值,因此您可能需要查看每个估计器的文档,以了解还支持哪些其他值。

假设我决定搜索以下文本矢量化参数和我的逻辑回归模型:

grid_params = {
    'trans__txt__binary': [True, False],
    'trans__txt__use_idf': [True, False],
    'trans__txt__max_features': [None, 100000, 10000],
    'trans__txt__ngram_range': [(1, 1), (1, 2), (1, 3)],
    'trans__txt__stop_words': [None, nltk_stopwords],
    'clf__C': [1.0, 0.1, 0.01],
    'clf__fit_intercept': [True, False],
    'clf__penalty': ['l2', 'l1'],
    'clf__solver': ['lbfgs','saga']
}

但是如果我想把'trans__txt__binary': True只和'trans__txt__use_idf': False一起用,这样真的得到二进制的 0 或者 1 输出呢?而我想单独尝试一个正则项频率,还有 TF + IDF,但那样的话我只希望 binary 为 False?

如果我用上面写的参数运行搜索,GridSearchCV将尝试每种组合,甚至是那些可能没有意义的组合。

事实证明, **GridSearchCV 也将接受一个参数字典列表,并且足够聪明地尝试列表中所有字典的唯一组合。**我们需要将公共参数放在两个字典中,二进制的参数放在一个字典中,常规令牌计数的参数放在另一个字典中。

创建搜索参数,说明我想要测试的特定组合

请注意,如果您只有几个要搜索的参数,这可能是不必要的,但当您想要尝试许多参数时,就像我们在这里做的那样,这真的变得很重要。每个组合都需要一定的计算能力和时间,所以我们不想运行任何不必要的组合。

如何绕过或跳过整个步骤

如果您想在不使用该选项的情况下测试结果,许多实际参数都有一个None值。然而,如果您有一个想要绕过或跳过管道中整个步骤的工作流,这就行不通了。

例如,如果您有连续的数据,并且想要同时使用MinMaxScalerStandardScaler来评估线性回归模型的性能,以查看哪一个效果更好。你可以在你的Pipeline中添加每一个单独的步骤,并使用上述技术的一个版本来创建一个 gris 参数列表,以尝试MinMaxStandard缩放器,但不能同时尝试两者。您可以将'passthrough'作为参数值提供给指定的流水线步骤来绕过它,这样就只使用另一个缩放器。

使用“通过”跳过最小最大或标准缩放器,这样我们可以在单个网格搜索中单独测试它们

请注意,如果您只是想尝试应用和不应用给定的步骤(而不是用一个步骤替换另一个步骤,就像我们上面所做的那样),您可以将 transformer 对象本身的一个实例与'passthrough'一起包含在参数列表中。例如,在 sklearn 文档的示例中,如果您有一个用于主成分分析的标注为'pca'的降维步骤,您可以在网格搜索参数中包含'pca': ['passthrough', PCA(5), PCA(10)]来测试不使用 PCA、使用具有 5 个成分的 PCA 以及使用具有 10 个成分的 PCA。

单独设置管道参数

好了,假设我们的网格搜索完成了,gs对象将会自动被安装上最佳估计器,我们可以使用gs.best_estimator_来访问它(不要忘记最后的下划线;很有必要!).

由于我们给了gs我们的pipe对象作为估计器,拟合的最佳估计器是pipe的副本,应用了最佳参数,并且已经在当前 X_train 上拟合。我们可以做这样的事情:

  • 调用gs.best_estimator_.get_params()获取性能最佳的流水线的参数
  • 使用 pickle 或 joblib 将gs.best_estimator_导出到文件,以备份最佳管道及其参数和 X_train 上的当前拟合
  • 调用gs.best_estimator_.predict(X_test)获得对未知测试数据的预测
  • 使用set_params()以防我们想要单独测试调整任何单个参数

例如,我们在网格搜索中测试了[10000, 5000, 2000]中的max_features,其中2000表现最好。因为它是最低的,也许我想只用1000来评估性能,看看更低是否真的会更好。

我可以使用set_params()和我们在指定网格搜索参数时使用的类似语法,手动将参数值设置为其他值:

gs.best_estimator_.set_params(**{'trans__txt__max_features': 1000})

注意,我将参数作为字典传递,如果需要,可以包含多个参数。我还需要字典前的**来解包它,这样set_params()就会接受它。

从 ColumnTransformer 访问功能名称

让我们假设1000中的max_features没有帮助,所以我已经将它设置回2000,在看不见的测试数据上评估性能,现在我准备对模型系数做一些解释。

要做到这一点,在我们对文章文本进行标记化、拆分主题并对分类特征进行一次性编码之后,我需要获得最终转换的特征名称。我们可以很容易地做到这一点,但我们必须使用正确的语法来深入嵌套层次。

首先,让我们使用 HTML 显示技巧来提醒自己这些步骤是什么以及它们的标签是什么:

GridSearch 最佳估计值的 HTML 显示

请记住,尽管我们将ColumnTransformer对象命名为cols_trans,但在我们提供给gs的最终管道中,我们只将其标记为trans所以 **trans** 是我们这里需要处理的第一个标签。

虽然这里显示的转换步骤是并行的,但是它们实际上是按照连接的顺序进行的。如果我们希望我们的特性名称列表的完整列表是准确的,我们需要按照最初应用的顺序从每个转换器中获取特性名称,然后将它们连接起来。在图中,该层的正确顺序可以从左到右阅读。

我们将使用named_steps()属性来访问转换层,然后从该层的每个named_transformers_()中依次获取get_feature_names()属性。

按顺序从每个转换器获取特征名称,用于模型解释

注意,对于ohe转换器,我将cat_cols传递给了get_feature_names(),这是在这一步中被转换的原始列名的列表。将原始列名作为列前缀传递到此处;否则它们将是通用的。

结论

希望这是一个有用的例子,说明如何构建嵌套的Pipeline来处理转换和建模。虽然构建需要一些额外的工作,但是如果您想在网格搜索中尝试不同的转换和模型参数,这样做是非常有益的。

欢迎反馈和提问!

了解需求预测

原文:https://towardsdatascience.com/getting-to-know-demand-forecasting-54e43c563a3e?source=collection_archive---------28-----------------------

要理解需求预测是如何工作的,需要的不仅仅是统计学和机器学习。

照片由 林赛萌

见见朱莉。她在月球上卖冰淇淋

这是朱莉。从六岁起,她想做的一切就是在每个夏天卖美味的冰淇淋,给人们带来欢乐。她相信她能做到,所以她做到了。

朱莉现在是 Salty & Icy 的老板,这是月球上最好的冰淇淋品牌之一。最初是一架小型航天飞机,现在向渴望探索环形山、爱上美丽的月球景观并最终像朱莉一样在月球上定居的太空游客分发了数百万个冰淇淋桶。

听起来像一个梦,但经营一家企业不仅仅是知道如何制作美味的冰淇淋!

制作冰淇淋,然后把它送到全月球的商店需要很多时间。然而,当顾客想要冰淇淋时,他们不会满足于超过 10 分钟的等待或任何其他口味,除非是他们渴望的口味。

简单地说,在顾客知道他们想买冰淇淋之前,冰淇淋必须提前做好。但是朱莉应该生产多少呢?每天 1000 还是 2000 桶?巧克力或草莓或以咸冰闻名的 20 多种异国风味?单杯还是 16 盎司的容器?

生产太多顾客不想买的东西将会带来巨大的损失,因为两周内卖不出去的产品将会被扔掉。对高需求产品生产过少会迫使她宝贵的客户选择其他竞争对手,并永远失去他们。

信不信由你,这项任务可以归结为一个问题:客户将来可能会购买每种产品的多少?找到这个问题的答案就叫做需求预测。

需求预测使 Julie 能够更好地进行业务规划和决策

作者图片

总的来说,这就是为什么需求预测对 Salty & Icy(以及其他企业)如此重要。

能够预测未来两周内的需求可以帮助 Salty & Icy 团队减少缺货,同时及时执行促销和降价以推动销售。

长达 2 个月的稍长的预测范围可以实现更好的生产计划,以保持冰淇淋搅拌,以满足客户的需求。

超过 2 个月之后,对预测需求的合理看法可以指导 Julie 和她的团队更好地开发产品和制定未来增长的业务战略。

从更广阔的角度来看,预测的时间越长,Julie 就能更好地规划、安排和提供原材料、劳动力和生产能力,以满足客户需求并执行增长战略。

要是朱莉有一个水晶球能告诉她未来的生意会怎么样就好了!

模式和无法解释的差异:需求预测的两个组成部分

没有所有辉煌的统计方法或人工智能炒作,需求预测的唯一目标是根据现有数据预测未来要消费的产品或服务的数量。就是这样!

关于从过去到现在影响产品需求的因素的数据越多,就越容易发现潜在的模式和关系,并对未来业务的发展做出合理的预测。

但是什么构成了需求预测呢?以下是对小查尔斯·w·蔡斯在书中所写内容的简短而甜蜜的总结。

预测=模式+未解释的差异

——出自小查尔斯·w·蔡斯

模式

模式通常有以下三种形式:趋势、季节性和周期性因素。

  • **趋势:**由于在过去的五年中,对纯素冰淇淋的历史需求每年增长 x %, Julie 预计未来纯素冰淇淋的销量将增长 x%。
  • **季节性:**当太阳照射到月球表面时,温度上升。这时,太空旅行者会疯狂地吃冰淇淋来缓解酷热。反之亦然,当太阳下山时,温度会降到零度以下。很少有人喜欢在冰淇淋桶里冷冻大脑。
  • **周期性:**月球一侧的白天和极热持续约 13.5 天,随后是 13.5 夜的黑暗和冰冻温度。月球每一面对冰淇淋的需求也随着月球自转而起伏。

这里的基本假设是,客户未来想要购买的东西会模仿他们过去购买的东西。因此,如果 Julie 能够确定过去影响其产品需求的趋势、季节性或周期因素,她就能预测未来的需求。

听起来好得难以置信?

我同意。未来不会像过去一样。这就是第二个组成部分出现的地方。

不可解释的变异数

无法解释的差异表示历史需求和未来需求之间的差异,无法用趋势、季节性或周期性因素来解释。

但这可能是什么呢?嗯,很多很多不同的事情。

Firmbee.com在 Unsplash 上拍照

这可能是一个买一送一的促销活动,或者是其他冰淇淋品牌为了与 Salty & Icy 竞争而降价 5%。在月球上举办的星际杯可能会看到对大尺寸多口味冰淇淋桶的需求增加,因为朋友和家人往往会一起观看足球比赛。与航天飞机有关的不幸事故可能会使人们对太空旅行变得谨慎,从而影响月球上的整体贸易和经济。

这些现象都在不同程度上影响着朱莉冰淇淋的需求。只有上帝知道还有多少因素会推动销售上升或下降。

但是**因为很难 100%准确地预测未来,并不意味着朱莉应该完全放弃它。**事实上,目标和期望应该是在合理的时间和成本限制内,尽可能基于数据量化无法解释的差异。

但是怎么做呢?好吧,让我们探索一下人们一直在做些什么来实现合理准确的需求预测!

预测未来需求的方法不止一种

我无意列出天底下所有预测方法的清单。这会让你直接进入深度睡眠。

但让我简要介绍 3 大类需求预测方法。每一类都代表了现实生活中经营企业的人的一种潜在信念或行为,值得了解。所以听我说完!

时间序列:历史会重演

你听说过移动平均线吗?指数平滑怎么样?哦,我怎么能省略时间序列预测的全能 ARIMA 模型呢?

如果你需要快速回顾一下这些是什么,看看这篇文章。但是下面是你需要知道的最重要的一点。

使用这些统计方法,人们有意或无意地假设历史会重演。因此用时间序列模型外推历史数据似乎足以预测需求。

例如,朱莉本月销售的冰淇淋数量将表明下个月对咸冰产品的需求。朱莉自创业以来观察到的基于月球自转的冰淇淋需求的周期性波动或纯素食冰淇淋越来越受欢迎,会告诉她下一季度、明年和未来许多年她应该生产多少冰淇淋。

但是过去的历史真的会在几个月甚至几周内保持不变吗?让我们看看。

个人判断:相信你的直觉

你见过基线预测是如何在委员会中传阅以收集反馈和批准的吗?

每个季度,Julie 通常会根据时间序列建模来准备基线预测。然后,她将基线预测发送给整个管理团队。

每个人都根据自己的判断、经验或直觉在预测中加入自己的想法,因为每个人都知道历史不会完全重演。一些人会高兴地上调预测需求,而另一些人似乎对未来几个月的需求过于悲观。

那么谁是对的呢?谁错了?更重要的是,为什么人们会选择依靠直觉呢?

许多研究人员研究了这种有趣的行为。简单来说,这里有三个主要的信念可以解释地面上正在发生的事情。

作者图片

当做出决策的时间紧迫,而时间序列预测不可用或不足以捕捉复杂的市场行为时,人们会依赖领域知识、个人判断或两者兼而有之。

不幸的是,无论判断是由一位高管还是整个委员会做出的,领域知识和个人偏见之间都有一条非常细微的界限。研究表明,大多数时候,当数字反映某人的愿望或有缺陷的推理,而不是对市场和客户行为的真正理解时,基于直觉的调整可能产生非常不准确的预测。

嗯,一定有别的办法,对吧?

回归:首先,给我看数据

照片由弗兰基·查马基在 Unsplash 上拍摄

除了趋势、季节性和周期性因素,还有什么可以帮助解释与未来需求相关的任何无法解释的差异?随着朱莉对过去记录的深入挖掘,她观察到了几种关系。

  • 花更多的钱把她的产品陈列在超市冷冻通道的中央与眼睛齐平的位置,销售量将是其他区域的两倍。
  • 在去年 5 月的“冷冻价格战”期间,月球上大多数冰淇淋品牌的售价都是 Salty & Icy 的一半。销售量下降了 25%。

虽然相关性并不意味着因果关系,外部和内部因素之间的相互关系可以用来预测未来的需求。例如,炎热的天气与比平均销量高 5%相关,而比其他品牌高 5%的价格可能会使企业损失 20%的周需求。

量化这种关系,并定义一个数学函数,根据目前对这些因素的了解来预测未来的需求,这就是所谓的回归。

还记得我们讨论过需求预测的两个组成部分吗?虽然时间序列方法有助于揭示与时间相关的模式,但回归在量化无法解释的差异方面极具价值。

包扎

将我们的讨论引向 Julie,以及她对预测未来咸冰产品需求的需求,以下是她需要牢记的内容。

首先,做出那些判断性的调整来提高定量预测模型的准确性是绝对不允许的。一个更好的方法是通过假设测试用现有数据验证领域知识。

其次,历史会重演的时间序列方法只有在产品多年来有相当稳定的销量,随机波动非常小的情况下才有效。然而,由于市场变化如此之快,新的进入者到处涌现,很少有公司能够继续享有稳定的销量。

第三,代表不同来源的产品需求的各种影响因素的数据越多,提高业务洞察力和预测准确性的可能性就越大。但是用 Excel 对许多潜在因素进行回归分析很快就会变成一场噩梦。

最后,除了人工智能宣传之外,生成可用于决策的准确需求预测需要的不仅仅是机器学习,因为:

  1. 机器学习并不能解决数据问题。如果历史数据缺失或质量差,单靠机器学习无法生成具有精度和准确度的需求预测模型。
  2. 当人们不相信预测数字的准确性或不理解这些数字是如何产生的,很难说服他们少依赖一点直觉,多依赖一点数据。因此,机器学习之旅可能需要时间、大量的试点项目和文化转变,才能达到“足够准确”的模型和“可解释”的模型之间的最佳平衡点,以便理解和采用。

这就是我这篇博文的全部内容。感谢您的阅读。对我如何能做得更好有反馈,或者只是想聊天?在评论里告诉我或者在 LinkedIn 上找到我。祝大家度过美好的一周!

参考

  1. 对统计预测进行判断性调整的“重大损失”会影响专家的行为吗?作者彼得罗保罗斯等人。
  2. 需求驱动的预测:一种结构化的预测方法
  3. Nick T. Thomopoulos 的库存控制需求预测

原载于 2021 年 5 月 23 日 http://thedigitalskye.com**的

了解概率分布

原文:https://towardsdatascience.com/getting-to-know-probability-distributions-cc1dd1e2f22b?source=collection_archive---------1-----------------------

数据科学基础知识的回归

考考自己!你能解释这些核心统计概念中的多少?

CLT、CDF、分布、估计、期望值、直方图、峰度、MAD、均值、中值、MGF、众数、矩、参数、概率、PDF、随机变量、随机变量、偏度、标准差、尾部、方差

你的知识有缺口吗?请继续阅读!

注: 如果你在下面看到一个不熟悉的术语,请点击链接查看解释。

随机变量

随机变量(R.V .)是一种将现实转化为数字的数学函数。可以把它想成一条规则,在真实世界的事件发生后,决定你应该在你的数据集中记录什么数字。

随机变量是简化现实的规则。

例如,如果我们对六面骰子的滚动感兴趣,我们可以将 X 定义为随机变量,它将您对真实世界骰子滚动的感性体验映射到这些数字之一:{1,2,3,4,5,6}。或者我们可能只记录奇数/偶数的{0,1}。这完全取决于我们选择如何定义我们的简历。

图片:来源。

(如果这太专业了,就把随机变量想象成一种表示结果的方式:如果 X 是关于掷骰子的,那么 X =4 就是说我们掷出了一个 4。如果这还不够专业,你几乎可以肯定https://en.wikipedia.org/wiki/Almost_surely爱上一堂衡量理论课。)

随机变量

许多学生混淆了随机变量和随机变量。如果你是一个普通读者,跳过这一点,但爱好者会注意到:随机变量是像{1,2,3,4,5,6}这样的结果值*,而随机变量是将现实映射到数字上的函数**。你课本公式中的小 x 对大 X 。*

概率

P(X=4) 在英语中读作“我的骰子 4 朝上着地的概率。”如果我有一个公平的六面骰子, P(X=4) =1/6。但是…但是…但是…概率是什么,那 1/6 从何而来?很高兴你问了!在这里,我已经为你介绍了一些概率基础知识,组合学是额外的收获。

分销

分布是一种表达 X 可能取的整组值的概率的方式。

发行版以图形的形式向您提供受欢迎程度竞赛的结果。

概率密度函数

召唤分布的最好方法是说出它的真名:它的概率密度函数。这样的功能意味着什么?如果我们把 X 放在X-轴上(没错),那么 y 轴上的高度显示了每个结果的概率。

一个概率密度函数给你整个人口的受欢迎度竞赛结果。基本上就是人口直方图。横轴:人口数据值。纵轴:相对知名度。要了解更多关于这张图和我省略的细节,请点击这里的。

*正如我在这里详细解释的那样,分布本质上是一个想象的理想化条形图(对于离散的 R.V.s)或直方图(对于连续的 R.V.s) 。*换句话说, *X 的更可能值的分布更高。对于所有结果,公平骰子的分布具有相同的高度(离散均匀”);对于加重的芯片来说并非如此。

和分布图一样,你可以把条形图和直方图想象成流行度竞赛。或者小费罐。那也行得通。

累积密度函数

这是概率密度函数的积分*。用英语?该函数不是显示 X 的每个值的可能性,而是显示 X 及以下所有值的累积概率。如果你在考虑百分位数,那太棒了。百分位数是在 x 轴上的数值,百分比是在 y 轴上的数值。*

概率:在六面骰子上得到 3?1/6
累计:获得 3 分或更低?3/6
第 50 百分位是 3。3 在 x 轴,50%在 y 轴。

选择您的发行版

你怎么知道什么分布适合你的 X ?统计学家有两种最喜欢的方法。他们或者(1) 从他们的数据中估计 经验分布——使用,你猜对了,直方图!—或者他们(2)做出理论上的假设关于流行发行目录的哪个成员看起来最像他们认为他们的数据源的行为方式。(如果你有数据,用假设检验来检查那些分布假设是个好主意。)

选择分布的标准方法包括绘制直方图,并将其形状与目录中的理论分布形状进行比较,例如维基百科上的分布列表、教科书中的分布列表或上述分布图的销售页面。(现在你开始怀疑我到底是在开玩笑。)作者个人 plushie 系列图片。

当我们查看我们的目录时,我们注意到各种分布都有类似“正态”或“卡方”或“柯西”的名称……这给学生一个错误的印象,以为这些是唯一的选项。他们不是。他们只是有名的。就像人一样,发行版可能因为所有错误的原因而出名。

就像人一样,发行版可能因为所有错误的原因而出名。

从好的方面来说,命名发行版附带了整洁的 pdf 和一堆为您预先做好的计算。

不利的一面是,您的应用程序可能不适合目录中的任何内容。感谢上帝的经验选择。

因素

这是一个非常流行的分布的概率密度函数,正态分布(也称为高斯或钟形曲线):

实话实说吧,这些见解并没有跃然纸上。这就是为什么我们倾向于询问我们感兴趣的特定参数的问题。在统计中,参数概括了总体或分布。例如,如果您要问分布是否在零处达到峰值,您要问的是其众数(一个参数)的位置。如果你在问分布有多胖,你是在问它的方差(另一个参数)。在时刻,我将带你参观几个我最喜欢的参数。

但在此之前,让我来回答这个问题:与其计算汇总测量,我们为什么不画出这个函数并注视它?我们还没准备好。

*如果你看上面的函数,你会注意到里面有一些希腊字母:μ和𝜎.**这些是该分布的特殊参数;在我们用数字代替它们之前,我们还没准备好绘制任何东西。没有它们,我们所能做的只是对分布的抽象形状有一个模糊的感觉,就像这样:

图片:来源。

想要斧子吗?把数字放在希腊字母所在的地方。例如,μ= 0 vs . 5 vs . 10 和𝜎 = 1 的结果如下:

粉色μ = 0,蓝色μ = 5,绿色μ = 10

*还有更多希腊语可以享受,因为其他发行版使用其他字符来表示它们的特殊数量。最终,你会厌倦它,开始使用 *θ₁、θ₂、θ₃、等。对他们所有人来说。

还值得记住的是,分布及其参数是理论对象,涉及关于人口总数的假设,而直方图是一个更实用的对象——你拥有的样本数据的汇总。如果你把与样本和总体相关的概念分开,你会避免很多混乱,所以在这里有必要重温一下这些概念。

你可以在这里找到我的解释。

现在我们已经准备好参观我最喜欢的参数,在第二部分中继续。

感谢阅读!人工智能课程怎么样?

如果你在这里玩得开心,并且你正在寻找一个为初学者和专家设计的有趣的应用人工智能课程,这里有一个我为你制作的娱乐课程:

在这里欣赏整个课程播放列表:bit.ly/machinefriend

与凯西·科兹尔科夫联系

让我们做朋友吧!你可以在 Twitter 、 YouTube 、 Substack 和 LinkedIn 上找到我。有兴趣让我在你的活动上发言吗?使用表格取得联系。

脚注

从技术上讲,一个离散的 R.V .函数被称为概率质量**函数,而不是概率密度函数,但我还没见过有人在乎你是否把一个 PMF 叫做 PDF 。*

** 如果你有一个离散的 R.V .,那么它是和而不是积分。

** * 那个π没什么特别的。这只是我们在 3 月 14 日庆祝的常规节日。

用于更好绘图的 ggplot2 扩展

原文:https://towardsdatascience.com/ggplot2-extensions-for-better-plotting-1734f62c160c?source=collection_archive---------28-----------------------

帮助您更高效地创建更好的地块的扩展

拼凑—排列您的图表

patchwork的目标是让将独立的 gg 图组合成同一个图形变得简单得可笑。要开始使用这个伟大的库,你需要记住三个基本操作符:+ /|。首先,让我们安装patchwork并创建一些情节。

基本用法

让我们将我们的图合并成一个大图,使用+操作符再简单不过了:

默认情况下,patchwork 会尝试保持网格为方形,并按行顺序填充它:

作者使用+运算符的拼凑式 ggplot2 排列-图像

定制安排

/|操作符使您能够超越这种自动排列。|会将图并排放置,而/会将它们堆叠起来:

使用/和|运算符的拼凑式 ggplot2 排列-作者图片

还有很多其他功能,如添加注释,字幕和其他安排选项。如果你想了解更多关于这个了不起的包,你应该访问它的伟大的文档页面。

esquisse 通过用户界面交互式创建图表

该扩展允许您通过使用带有拖放界面的 ggplot2 包来可视化数据,从而以交互方式浏览数据。可以导出创建和样式化的图形,也可以检索它们的代码以获得再现性。要开始使用这个包,您只需要两行代码。

执行后,将会打开一个新窗口,这实际上是不言自明的:首先会要求您从指定的环境中打开一个数据框,随后,您可以简单地将数据框的特征拖放到 x、y、填充、颜色和大小的相应区域。底部的菜单使您能够进一步设计和调整您的绘图。

来自https://github.com/dreamRs/esquisse的 esquisse 可视化

要了解关于这个伟大的软件包的更多信息,它使创建令人惊叹的 ggplots 变得超级容易(特别是对于初学者),请访问官方文档页面。

gganimate 为您的绘图制作动画

您是否厌倦了静态图表,并希望在演示文稿或 web 上的图表中添加一些额外的内容?使用 gganimate 您可以使用一个易于 ggplot2 用户学习的 API 来创建动画。要开始,您首先需要安装两个软件包:

不错!现在让我们创建一个动画。例如,如果您想要绘制著名的虹膜数据的花瓣宽度和长度,并创建一个过渡到物种的动画图(分别绘制它们),您可以执行以下操作:

您可以看到创建绘图的标准 ggplot2 命令,随后是 transition_states() 函数,该函数通过声明动画的状态(您可以将其视为电影或动画中的帧)、两个状态之间的长度(延迟)以及状态长度来创建动画。

带 gganimate 的动画虹膜数据集—图片由作者提供

这个软件包的文档非常优秀,因此,如果你想更深入地了解 ggplot2 的动画,请访问https://gganimate.com/

ggplot 主题—为您的绘图添加一些风格

默认情况下 ggplots 看起来很棒,但有时我们希望创建符合某个主题的时尚剧情。以下是 ggplot 扩展的概述,它使您能够轻松地更改默认主题:

考普特

“ cowplot 包是 ggplot 的一个简单附件。它提供了各种有助于创建出版物质量的图形的功能,例如一组主题、对齐图形并将它们排列成复杂复合图形的功能,以及便于注释图形和/或将图形与图像混合的功能。”—来自https://github.com/wilkelab/cowplot

Cowplot 创造了一个看起来很棒的独特的最小视觉化。您可以通过简单地添加 **theme_cowlplot()将任何图转换为 cowplot。**如果你想给主题添加一个网格,你可以使用 theme_minimal_hgrid() 作为水平线。

另请注意,cowplot 包括用于排列图的函数,例如用于创建以下可视化的 plot_grid()函数:

典型的 cowplot 主题—作者图片

ggpubr

“ggpubr”包提供了一些易于使用的功能,用于创建和定制基于“ggplot2”的出版就绪图。—来自https://rpkgs.datanovia.com/ggpubr/

该软件包提供了创建时尚图形的自定义功能,接下来,我想向您展示我最喜欢的三个:

  • gg 密度
  • ggviolin
  • ggdotchart

ggpubr 包中的密度、小提琴和点阵图—图片由作者提供

更多主题

ggplot 主题的世界似乎是无穷无尽的,不可能在本文中介绍所有的主题。然而,如果你没有足够的,这里有几个参考,希望能帮助你找到适合你的主题:

  • 可用 ggplot 主题的详细列表:https://yutannihilation . github . io/allyourfigurearebelongtus/1/
  • ggtech——包含基于 AirBnb、脸书和谷歌等大型科技公司的主题的包:https://github.com/ricardo-bion/ggtech
  • hrbrthemes **-为 gg plot 2:**https://github.com/hrbrmstr/hrbrthemes 提供以排版为中心的主题和主题组件的包
  • tvthemes - 根据《辛普森一家》、《权力的游戏》或《海绵宝宝》等人人喜爱的电视剧,收集各种 ggplot 主题:https://github.com/Ryo-N7/tvthemes

更好的情节的相关材料

1gg plot 2 扩展列表:https://exts.ggplot2.tidyverse.org/gallery/

【https://davidgohel.github.io/ggiraph/】用图形创建交互式 ggplots

**【3】**卡森·西沃特,基于网络的交互式数据可视化与 R,plotly,和 shiny:https://plotly-r.com/index.html

吉布斯采样解释

原文:https://towardsdatascience.com/gibbs-sampling-explained-b271f332ed8d?source=collection_archive---------15-----------------------

实践教程

通过视觉化建立直觉

介绍

从政治学到癌症基因组学,马尔可夫链蒙特卡罗(MCMC)已经被证明是各种不同领域统计分析的一个有价值的工具。在高层次上,MCMC 描述了一组迭代算法,这些算法从难以直接采样的分布中获取样本。这些基于马尔可夫链的算法与过去 30 年计算能力的惊人增长相结合,使研究人员能够从极其复杂的理论分布中进行采样。在软件中实现,如 BUGS (使用吉布斯采样的贝叶斯推理)和 JAGS (只是另一个吉布斯采样器),吉布斯采样是最流行的 MCMC 算法之一,应用于贝叶斯统计、计算语言学等领域。

**在本文中,我们将通过一系列可视化来揭示吉布斯采样的工作原理,**通过一个二元正态目标分布的简单示例进行追踪。

设置问题

假设有一个 m 分量感兴趣的联合分布,很难从中采样。即使我不知道如何从联合分布中抽样,假设我知道如何从完全条件分布中抽样。也就是说,我可以很容易地从 m 个分量的每一个中取样,条件是另一个 m-1。在这些条件下,吉布斯采样基于全条件迭代地更新每个分量,以从联合分布中获得样本。

为了确切了解这是如何工作的,让我们考虑一个简单的例子。假设我只能访问基 R,它可以很容易地对单变量法线进行采样,但不能对多变量法线进行采样。假设目标分布是二元正态分布,其中边际是具有相关性 ρ的标准正态分布。

目标分布

利用多元正态分布的性质,我们得到以下全条件分布。

完全条件分布

由于这些条件只是单变量法线,我可以很容易地从中取样。那么,用于联合分布的吉布斯采样算法将如下:

吉布斯采样算法

这个算法起初看起来有点吓人,所以让我们用一些可视化的方法来分解它。

遍历算法的一次迭代

让我们一步一步地完成吉布斯采样器的第一次迭代,其中 ρ 等于 0.9。

第一步:初始化

这里没什么要做的,将(xₒ,yₒ)初始化为(0,0)并将迭代计数器 t 设置为 0。这是我们最初观点的一个非常无趣的情节。

步骤 1:初始化

步骤 2:给定 Y 的 X 的条件更新

现在,我们从给定 Y 等于 0 的 X 的条件分布中得出。

给定 Y 的 X 的条件更新

在我的模拟中,这个平局的结果是-0.4。这是我们第一次条件更新的图表。请注意,我们新点的 Y 坐标没有改变。

步骤 2:给定 Y 的 X 的条件更新

步骤 3:给定 X,有条件地更新 Y

现在,我们从给定 X 等于-0.4 的 Y 的条件分布中得出。请注意,在进行第 3 步的绘制时,我们使用了刚刚在第 2 步中绘制的 X 值。

给定 X 的 Y 的条件更新

在我们的情况下,这个平局的结果是-0.32。这一次,我们的新点的 X 坐标与步骤 2 中的点的 X 坐标相同。

步骤 3:给定 X 的 Y 的条件更新

第 4 步和第 5 步

增加迭代计数器 t 并返回步骤 2。吉布斯采样器的这个迭代的最终点是(-0.4,-0.32)。我们现在有两个吉布斯样本。一个来自我们的初始化,一个来自我们的第一次迭代。

第 4 步和第 5 步:增量和返回

更多迭代

如果我们继续运行我们的算法(即运行步骤 2 到 5),我们将继续生成样本。让我们运行迭代 2 和 3,并绘制结果,以确保我们已经得到了模式。

迭代 2 和 3

放下条件更新的中间图,我们可以绘制吉布斯采样器的前 100 次和 10,000 次迭代。

吉布斯采样图,前 100 次迭代

吉布斯采样图,前 10,000 次迭代

上面图上的蓝线是目标二元正态分布的等高线。我们的样本似乎是根据需要从目标分布中抽取的!我们的 Gibbs 抽样器确实从联合分布中提取数据。

注意:为了方便起见,我没有在动画中使用真实的理论密度,而是使用了来自 MASS 包的 100,000 MVN 绘图的经验密度。

总结

本文展示了当我们能够访问完整的条件时,如何使用 Gibbs 抽样从复杂的联合分布中提取数据——从分层贝叶斯建模到计算集成,统计分析中的场景无时无刻不在出现。通过追踪一个二元正态目标分布的例子,我们对 Gibbs 抽样实际上是如何工作的建立了直觉。

延伸阅读:

1马克林,科里。“吉布斯采样”中【2020 年 10 月 2 日【https://towardsdatascience.com/gibbs-sampling-8e4844560ae5】T4。

【2】马尔可夫链蒙特卡罗(MCMC)抽样介绍,第二部分:吉布斯抽样。https://www.tweag.io/blog/2020-01-09-mcmc-intro2/。2021 年 5 月 23 日访问。

来源:

鸣谢:这篇文章的想法来自于我辅导哈佛统计学课程“Stat 171:随机过程介绍”我的学生让我帮助他们理解多布罗书中的例子 5.6,所以我创建了这篇文章中的 R 脚本。我为本文创建的算法和采样器来自 Dobrow 的例子。

长颈鹿:仔细看看 CVPR 2021 最佳论文的代码

原文:https://towardsdatascience.com/giraffe-a-closer-look-at-cvpr-2021s-best-paper-1ec81f593fa9?source=collection_archive---------12-----------------------

GIRAFFE 是一个基于学习的、完全可区分的渲染引擎,用于将场景合成为多个“特征字段”的总和

使用 GIRAFFE 旋转和平移 GAN 生成的汽车(作者使用https://github.com/autonomousvision/giraffe创建,麻省理工学院许可)。

CVPR 2021 已经结束了,多么棒的论文选择!深度学习继续主导计算机视觉领域,有 SLAM、姿势估计、深度估计、新数据集、GANs 的新方法,以及对去年的神经辐射场 [ 1 ],或 NeRFs 的许多改进,仅举几例。

到现在为止,你可能已经听说过一篇名为“长颈鹿:将场景表示为合成生成神经特征场的论文。 [ 2 ]“这篇论文获得了今年最佳论文奖的大奖,它将 GANs、NeRFs 和可微分渲染结合在一起,生成了新颖的图像。然而,更重要的是,它提供了一个模块化的框架,以完全可区分和可学习的方式从对象构建和合成 3D 场景,让我们更接近神经 3D 设计的世界。在这篇文章中,我仔细查看了长颈鹿的源代码,并生成了一些快速的可视化示例。

神经辐射场

NeRF (YouTube)的可视化解释和演示。

简要回顾一下 NeRFs ,它们是一种根据 3D 体积中任何给定点的密度和亮度来描述和渲染 3D 场景的方法。它与光场的概念密切相关,光场是表达光如何穿过给定空间的函数。对于空间中给定的 (x,y,z) 视点,图片将方向为 (θ,φ) 的光线投射到场景中。对于沿着这条线的每个点,我们收集它的密度和视点相关的发射辐射,并以类似于传统光线追踪的方式将这些光线合成为单个像素值。这些 NeRF 场景是从各种姿势拍摄的图像集合中学习来的,就像你在结构来自运动应用中使用的那样。

长颈鹿

长颈鹿的视觉解释和演示(YouTube)。

概观

本质上,GIRAFFE 是一个基于学习的完全可区分的渲染引擎,它允许您将场景合成为多个“特征场”的总和,这是 NeRFs 中辐射场的概括。这些特征场是 3D 体积,其中每个体素包含一个特征向量。通过合成由接受潜在代码作为 3D 场景输入的 GANs 产生的学习表示来构建特征场。由于特征字段应用于 3D 体积,因此您可以应用相似性变换,如旋转、平移和缩放。您甚至可以将整个场景合成为单个特征字段的总和。该方法对 NeRFs 进行了以下改进:

  • 可以用独立的变换表示多个对象(和一个背景)(最初的 NeRF 只能支持一个“场景”,不能分解单个对象)。
  • 可以对单个对象应用姿势和相似性变换,如旋转、平移和缩放。
  • 产生特征字段的 gan 可以独立学习并像组件一样重用。
  • 拥有经过端到端培训的独特渲染引擎。
  • 颜色值不仅仅支持 RGB,还可以扩展到其他材质属性。
  • 使用位置编码(如转换器)来编码位置,这也“引入了感应偏差来学习规范方向上的 3D 形状表示,否则这些表示将是任意的。”

长颈鹿项目包括源代码,你可以用它来复制它们的形象,甚至组成你自己的场景。我简要介绍了它们的源代码,并展示了我们如何使用 GIRAFFE 来构建一些简单的神经 3D 场景。

源代码

GIRAFFE repo的结构考虑了配置。configs/default.yaml文件指定了应用程序的默认配置。其他配置文件如configs/256res/cars_256/pretrained.yaml使用inherit_from键继承这个配置文件,并通过指定其他键-值对覆盖默认值。这使我们能够用python render.py <CONFIG.yaml>渲染图像,用python train.py <CONFIG.yaml>通过自文档化的配置文件进行训练,而不是编写输入参数。

要自己尝试一些渲染,首先运行README.md文件中的快速启动指令。这将下载一个预训练的模型,并将一系列输出可视化(如下图所示)写入文件夹out

对象随 Cars 数据集旋转(由作者使用https://github.com/autonomousvision/giraffe,麻省理工学院许可创建)。

配置文件只是采用默认值,并在 Cars 数据集上插入一个预训练模型。它提供了很多可视化的方法来操作底层渲染,比如外观插值、形状插值、背景插值、旋转和平移。这些可视化在render_program键下的configs/default.yaml中指定,其值是指定这些可视化的字符串列表。这些指定了长颈鹿渲染器在调用render.py时将调用的“渲染程序”。在im2scene.giraffe.rendering.Rendererrender_full_visualization方法中,你会看到一系列的if语句,寻找更多渲染程序的名字,比如‘object _ translation _ circle’、‘render _ camera _ elevation’和‘render _ add _ cars’。

为什么我们不试试这些呢?创建一个名为cars_256_pretrained_more.yaml的新配置文件,并添加以下内容:

这只是我们用默认配置文件的render_program键使用的先前的配置文件,它被我们想要的新渲染程序覆盖了。现在执行python render.py configs/256res/cars_256_pretrained_more.yaml来产生更多的可视化效果。您应该会得到这样的结果:

Cars 数据集的摄像机仰角。请注意相机视角在背景和汽车侧面上是如何变化的,就好像相机从上向下绕着汽车旋转一样(作者使用https://github.com/autonomousvision/giraffe,麻省理工学院许可创建)。

…还有这个:

使用汽车数据集添加汽车(由作者使用https://github.com/autonomousvision/giraffe,麻省理工学院许可创建)。

这些渲染程序实际上是如何放置、平移和旋转这些汽车的?要回答这个问题,我们需要仔细看看Renderer类。对于上面的'object_rotation'示例,调用了Renderer.render_object_rotation方法。

该函数为给定批次的成员生成一系列旋转矩阵r。然后,它迭代地将这个范围的成员(以及一些默认的缩放和平移)传递给生成器网络的forward方法,该方法由default.yaml中的generator键指定。如果你现在看im2scene.giraffe.models.__init__.py,你会看到这个键映射到im2scene.giraffe.models.generator.Generator

现在,在我们看Generator.forward的时候,请耐心等待。它接受各种可选的输入参数,比如transformationsbg_rotationcamera_matrices,然后将它们传递给它的volume_render_image方法。这里是合成魔法发生的地方。场景中所有物体的潜在代码,包括我们的背景,被分离成它们的形状和外观部分。

在本例中,这些潜在代码是使用torch.randn函数随机生成的:

这是解码器正向传递将 3D 点和摄像机观察方向映射到每个对象的和 RGB(特征)值的地方。一个不同的发生器被应用于背景(为了可读性,省略了细节)。

然后,这些图由 σ max 或使用composite_function的平均值合成。

最后,通过沿着射线向量用 σ 体积对特征图进行加权来创建最终图像。最终结果是你在上面看到的那些动画之一的单个窗口中的单个帧(关于如何构造diray_vector的细节,见generator.py)。

现在总结一下,让我们试着创建自己的渲染程序。这个将简单地结合深度平移和旋转来创建一个汽车从左向右旋转和滑动的效果。为此,我们对rendering.py中的Renderer类做了一些简单的添加。

将这些添加内容复制粘贴到rendering.py中,然后创建如下配置文件configs/256res/cars_256_pretrained_wipeout.yaml:

现在,如果您执行python render.py configs/256res/cars_256_pretrained_wipeout.yaml,您应该能够产生如下所示的结果:

对象与汽车数据集“相消”。注意汽车从左向右移动时是如何旋转的(作者使用https://github.com/autonomousvision/giraffe,麻省理工学院许可创建)。

结论

长颈鹿是最近对神经纤维和甘的大量研究中令人兴奋的新发现。辐射场表示描述了一个强大且可扩展的框架,利用该框架我们可以以可区分且可学习的方式构建 3D 场景。我希望对代码的深入研究对您有所帮助。如果是这样的话,我鼓励你自己去看一看源代码和作者的论文。

参考

1 Ben Mildenhall,Pratul P. Srinivasan,Matthew Tancik,Jonathan T. Barron,Ravi Ramamoorthi,Ren Ng — NeRF:将场景表示为用于视图合成的神经辐射场(2020) ,ECCV 2020

[2] Michael Niemeyer,Andreas Geiger — 长颈鹿:将场景表示为合成生成神经特征场(2021) ,CVPR 2021

GIS tyc——基于 Python 的 GitHub GIST 管理工具包

原文:https://towardsdatascience.com/gistyc-a-python-based-github-gist-management-toolkit-ee507d5a0e7b?source=collection_archive---------33-----------------------

小窍门

GitHub GISTs 是在介质上显示代码片段的完美方式。但是,如何以可行的方式创建、更新和删除 GISTs,并将这样的过程集成到 CI/CD 管道中呢?

照片由rich Great在 Unsplash 上拍摄

使用 GISTs

媒体已经成为各种文章的重要来源。这还包括涵盖数据科学或机器学习主题的编程教程。但是覆盖实际的编码部分需要一样东西:适当的格式和编程语言依赖的颜色突出。有时人们会看到以下格式的代码片段:

# Import standard module
import time# Print the current Unix Time
print(time.time())

…这种格式对于几行代码来说完全没问题,但是用这些灰色的块来覆盖整个教程会让人读起来很累。相反,大多数 Medium 上的作者使用 GitHub GIST 。GitHub 提供了一个创建要点的简单链接,允许用户在介质上显示正确格式化的代码。以下要点…

要点示例

…只需在 Medium 文本编辑器中添加以下链接即可(灰色块样式阻止 Medium 正确格式化要点):

[https://gist.github.com/ThomasAlbin/1b42f2fbe6470ae54286b83b57f5acd6](https://gist.github.com/ThomasAlbin/1b42f2fbe6470ae54286b83b57f5acd6)

由 Finn Whelen 在 Unsplash 上拍摄的照片

维护要点的问题是

Medium 有数百甚至数千篇文章,涵盖了编程相关的主题。但是,旧的文章可能会引用已经过时的库和更新的工具,它们的功能发生了变化。结果是一些显示的要点代码片段不再工作了。提出的异常、警告和错误结果会抑制阅读有希望的标题或摘要后的兴奋感。考虑到作者对代码进行了测试,并且审阅者或编辑对文章进行了彻底的检查,我们只能假设最近的文章工作正常。

但是一个人(例如,一篇文章的作者)如何保持要点的更新呢?手动编辑大量的 GISTs 既乏味又麻烦。还有一个 GitHub GIST REST API ,但是有一个简单的解决方案会更好。

为此,我开发了一个具有 CLI 功能的基于 Python 的工具包,我想在这里介绍一下: gistycGISTsyc 应使用户能够从外壳或 Python 程序中创建、更新和删除 gist。它的功能、特性和 GitHub 动作集成(新的 GIST 代码的持续部署)是本文的一部分。

https://github.com/ThomasAlbin/gistyc

总的来说,gistyc 很容易理解。让我们举个例子:

  • 您有一个想要向全世界展示的 Python 文件!就叫牛逼吧. py。
  • awesome.py 要在一篇中等文章里详细解释。这个文件很大,有 200 多行代码。一个要点对于一篇教程文章来说太大了。
  • 无论如何,你可以简单地将你的代码分割成单独的要点或者要点中的“子部分”。手动完成这个过程是乏味的…如果你以后需要更新它,由于一些读者抱怨错误,它变得更糟…
  • awesome.py 具有专用的“编码块”,例如由“# % %”(Spyder-way)分隔。这些单元格应该是你想要显示的要点部分。
  • 现在是GIS tyc:GIS tyc获取你的文件,将它分割成单独的部分(取决于代码块分隔符)并自动创建要点。如果你已经有了一个名为“awesome.py”的要点, gistyc 会相应地更新要点!第一个 GIST 代码-cell 的名称是“awesome.py”,第二个得到后缀“_1”,导致“awesome_1.py”等等。稍后你会看到一个例子。
  • 您更新的要点会自动与您的中型文章同步,您就大功告成了!

这里只涉及几个陷阱:

  1. 您应该坚持在您的 GIST 存储库中使用唯一的文件名(否则 gistyc 会与不明确的名称混淆并返回一个错误)。
  2. 您还应该坚持代码单元格分隔。只编辑错误或异常,但不要改变代码的逻辑!否则你的中型文章不符合代码和你的读者越来越困惑后,你更新它!

先决条件和安装

在我们深入研究 gistyc 之前,我们需要满足一些先决条件才能使用它的全部特性列表。除了安装 Python,你还需要一个 GitHub 帐户来创建和存储 GISTs。之后,你只需要遵循这三个步骤:

  1. 安装 Python ≥3.8(建议:使用虚拟环境)
  2. 您需要一个 GitHub 个人访问令牌和 GIST 访问:
  • 点击您的个人账户资料(右上角)
  • 点击设置
  • 在左侧菜单栏中,进入开发者设置,选择个人访问令牌
  • 生成新的令牌并写下您的令牌的名称(注释)。注释不影响功能,但选择描述令牌用途的注释,例如 GIST_token
  • 要点 ( 创建要点)处设置一个标记,并点击页面底部的生成令牌
  • 重要提示:显示的令牌只出现一次。将其复制并作为一个秘密存储在 GitHub 项目中和/或作为一个环境变量存储在本地。

3.通过以下方式安装 gistyc :

pip install gistyc

或者,可以随意下载库来下载和使用所提供的测试。

现在我们准备和吉斯泰克一起工作。以下部分描述了 Python 函数调用,第二部分概述了对 CD 管道更感兴趣的 CLI 功能!

Python 要点准备

请注意:当前版本仍处于测试阶段,仅适用于 Python(。py)文件。将来会有更新来涵盖更多的通用解决方案。

为了测试或使用 gistyc 在我们的设备上准备一个简单的 Python 文件。结局还得是*。py* 。

此外,要点可以被分成几个文件。这可能有助于将您想要一步一步解释的较大的教程脚本分割开来。下面的例子(我们将在后面更详细地讨论这个例子)给你一个印象,它意味着什么:

看一看 gistyc 提供的示例脚本:示例脚本

作为一个单独的要点,脚本存储在…

[https://gist.github.com/ThomasAlbin/77974cc3e14b2de8caba007dfa3fccf9](https://gist.github.com/ThomasAlbin/77974cc3e14b2de8caba007dfa3fccf9)

…格式为:

另一个 GIST 示例名为“gistyc_example2.py”

如你所见,提供了 Spyder 代码块分隔符“#%%”。gistyc 识别这些代码分隔符,并在单个 GIST 中创建单独的文件(或“子 GIST”)。分隔符可以由用户设置,但在本文中,我们将坚持 Spyder 风格。

以上示例是 gistyc 官方 GIST 示例的一部分,可在以下位置找到:

[https://gist.github.com/ThomasAlbin/caddb300ac663e60ae573b1117599fcc](https://gist.github.com/ThomasAlbin/caddb300ac663e60ae573b1117599fcc)

此外,这三个独立的块可以通过以下方式调用:

1.第一代码单元

[https://gist.github.com/ThomasAlbin/caddb300ac663e60ae573b1117599fcc?file=gistyc_example2.py](https://gist.github.com/ThomasAlbin/caddb300ac663e60ae573b1117599fcc?file=gistyc_example2.py)

gistyc_example2.py 的第 1 部分—通过https://gist . github . com/Thomas Albin/caddb 300 AC 663 e 60 AE 573 b 1117599 FCC 调用?file=gistyc_example2.py

2.第二代码单元

[https://gist.github.com/ThomasAlbin/caddb300ac663e60ae573b1117599fcc?file=gistyc_example2_1.py](https://gist.github.com/ThomasAlbin/caddb300ac663e60ae573b1117599fcc?file=gistyc_example2.py)

gistyc_example2.py 的第二部分—通过调用 https://gist . github . com/Thomas Albin/caddb 300 AC 663 e 60 AE 573 b 1117599 FCC?file=gistyc_example2_1.py

3.第三代码单元

[https://gist.github.com/ThomasAlbin/caddb300ac663e60ae573b1117599fcc?file=gistyc_example2_2.py](https://gist.github.com/ThomasAlbin/caddb300ac663e60ae573b1117599fcc?file=gistyc_example2_2.py)

gistyc_example2.py 的第三部分—通过调用 https://gist . github . com/Thomas Albin/caddb 300 AC 663 e 60 AE 573 b 1117599 FCC?file=gistyc_example2_2.py

总体而言,用户的(用户 ) GIST 及其值( GIST_VALUE )和相应的文件名( GIST_NAME )以及后缀依赖子节( ID )具有以下结构:

https://gist.github.com/USER/GIST_VALUE?fileGIST_NAME_ID.py

David Clode 在 Unsplash 上拍摄的照片

Python 中的 gistyc

Python API 目前提供 4 个通用函数来创建、更新和删除 GIST。此外,它允许用户获得所有可用 gist 的当前列表。

我们有以下参数:

  • AUTH_TOKEN:是 GIST 访问令牌(字符串)
  • FILEPATH:是 Python 文件的绝对或相对路径(string 或 pathlib。路径
  • 要点 ID:要点(字符串)的 ID*。我们一会儿会谈到这个参数*

创建一个要点

基本上所有的 gistyc 调用都是从同样的两行代码开始的:首先是库的表面导入,其次是 gistyc 类的实例化(第 5 行)。这个类只需要 GIST 身份验证令牌。返回的类,这里命名为 gist_api ,然后用于调用相关的方法。

以下示例显示了如何创建要点。该类调用方法 create_gist ,其输入是文件路径。返回值( response_data )是来自 GitHub 服务器的回调 JSON,包含新创建的 GIST 的元信息(如时间戳、GIST 的 ID 等)。).

使用 gistyc Python API 创建 GIST

更新要点

有两种方法可以更新要点。首先,让我们假设所有的要点名称都是唯一的,不会重复。

同样,我们创建了这个类(第 5 行)并在第 8 行调用了方法 update_gist ,这里我们只是提供了文件路径作为输入。返回的 JSON 提供回调信息。

使用 gistyc Python API 更新 GIST(仅使用 Python 文件的文件路径)

然而,让我们假设你有几个同名的 gist***(顺便说一下:为了保持整洁,避免重复/同名的 gist!)*** 。如果只使用文件名调用更新函数,就会引发一个异常(我称之为 AmbiguityError)。在这种情况下,你还需要知道你要点的要点 ID。然后,您可以通过以下方式更新您的要点:

使用 gistyc Python API 更新 GIST(仅使用 Python 文件的文件路径和相应的 GIST ID)

获取所有 GISTs

有时候知道你所有的要点是有用的,尤其是当你有上百个要点的时候。在一个单独的数据库中维护它们或者手动获取所有的 GIST IDs 可能会令人精疲力尽…

为此,实现了 get_gists 方法,该方法通过所有的 GIST 页面调用 REST API,并将所有结果附加到最终列表中。每个元素都是一个 JSON 元素,代表一个要点。

使用 gistyc Python API 获得所有 GitHub GISTs 的列表

删除要点

最后,我们来看看如何删除一个要点。该过程类似于更新例程。如果您有具有唯一文件名的 GISTs,那么 FILEPATH 是唯一需要的输入参数…

使用 gistyc Python API 删除 GIST(仅使用 Python 文件的文件路径)

…否则,您需要提供一个要点 ID:

使用 gistyc Python API 删除 GIST(仅使用 GIST_ID)

gistyc 作为 CLI

使用 click 可以创建基于 Python 的 CLI 工具,可以从 shell 中直接调用这些工具。gistyc 也具有部分基于上述功能的 CLI 功能。

我们有以下参数:

  • AUTH_TOKEN:是 GIST 访问令牌(字符串)
  • FILEPATH:是 Python 文件(字符串)的绝对或相对路径
  • GIST _ ID:GIST(字符串)的 ID

请注意:代码单元格分隔符必须是“#%%”。CLI 的分隔符输入参数将跟在后面。

创造一个要点

首先, gistyc 需要一个标记来指示所需的功能(创建、更新、删除),后跟输入参数。所有 CLI 调用都需要一个允许更改要点的身份验证令牌。

下面的 bash 片段基于 FILEPATH 创建了一个 GIST。

gistyc --create --auth-token AUTH_TOKEN --file-name FILEPATH

更新要点

类似地,如前所示,我们有一个 CLI 调用来基于文件名称更新 GIST,并且…

gistyc --update --auth-token AUTH_TOKEN --file-name FILEPATH

…如果文件名不唯一,则带有相应的 GIST ID:

gistyc --update --auth-token AUTH_TOKEN --file-name FILEPATH --gist-id GIST_ID

删除要点

类似地,可以通过 CLI 删除 GISTs 通过提供文件名…

gistyc --delete --auth-token AUTH_TOKEN --file-name FILEPATH

…或要点 ID:

gistyc --delete --auth-token AUTH_TOKEN --gist-id GIST_ID

gistyc 目录 CLI

为单个文件调用 gistyc CLI 是管理您的 GISTs 的一种快速可行的方法。然而,让我们假设您有一个更大的教程系列,包含几十个 Python 脚本和数百个代码单元。多次调用 gistyc 或者用几十个 gistyc 调用创建一个 bash 脚本可能会变得令人困惑。

为此,已经实现了第二个基于 gistyc 的 CLI:GIS tyc _ dir

我们假设您将所有 Python 文件存储在一个名为 directory 的目录中。现在,您需要创建和/或更新所有相应的 GISTs。您只需拨打:

gistyc_dir --auth-token AUTH_TOKEN --directory DIRECTORY

请注意:文件名在 GIST repo 中必须是唯一的,因为这里不能提供 GIST ID。此外,您的文件也可以存储在子目录中。 gistyc_dir 递归搜索目录以找到所有 Python 文件。

调用 GISTsyc_dir 后,新的 GISTs 被创建,现有的 gist 也被创建!

Yancy Min 在 Unsplash 上拍照

CI/CD 中的 gistyc

gistyc 的 CLI 功能和 gistyc_dir 提供的目录功能是将其集成到类似 CI/CD 的管道中的良好基础。什么时候,为什么要为 GISTs 创造这样一个管道?

让我们考虑下面的例子:

  • 您有一个主要的中型教程项目,其中涵盖了许多您希望存储在 GitHub GIST 上的 Python 示例。
  • 所有 Python 脚本都存储在一个名为的目录下的相应 GitHub 存储库中。/例/
  • 每次你在上传新的脚本。/examples/ (例如,通过 Pull 请求并合并到主分支)应自动创建新的 GISTs。
  • 此外,Pull 请求还可能包含一些读者已经解决的示例脚本的更正和错误修复。同样在这种情况下:您将您的更改合并到主分支中,管道会相应地自动更新相应的 GISTs。无需在繁琐的手动过程中更新 GISTs。

在 GitHub 上,CI/CD 管道被称为动作。管道逻辑存储在 YAML 文件中。下面的 YAML 文件展示了我的 gistyc GitHub 库中提供的一个例子。看一看【行动】,。github/workflow 目录和*。/examples/* 目录,以便更好地了解这个工作流是如何工作的。每次我在里改变一些东西。/examples/ ,创建一个 Pull 请求,最后合并到主分支,所有代码部分来自*。/examples/* 创建新的 GISTs 或相应地更新现有的 GISTs。

YAML gist-push.yml 如下所示,工作方式如下:

第 8–11 行:如果中有任何内容。/examples/ 文件夹发生变化,动作正在执行。

第 14–19 行:管道进一步检查主分支上是否已经执行了更改。我们不想更新来自另一个未审查或未测试分支的 GISTs。

第 21–36 行:GitHub 准备环境,其中…

第 37–38 行:… gistyc 正在安装(这里, gistyc 是从 pypi 安装的)

第 39–40 行:现在 gistyc_dir 被应用到上。/examples/ 文件夹。创建新的 GISTs,并更新现有的 GISTs。

gist-push.yml

这个 YAML 文件可以适用于任何其他 GitHub 存储的项目。您需要设置一个包含 GIST 标记的项目密码。此外,您还可以添加更多功能,例如,使用pytest测试您的 Python 脚本。现在,在成功合并到主分支之后,您就可以自动创建和/或更新 GISTs 了。也可以随意更改示例目录。

进一步的支持和想法

官方的 gistyc 库提供了一个示例目录和所示的 GitHub 动作 YAML 文件。如果您需要任何帮助或有任何想法,请使用 GitHub 问题页面,在本文下方写下评论或在 Twitter 上给我发消息。

贡献

另外,随时欢迎投稿!需要做一些事情,比如 CLI 的代码块分隔参数,或者替换“ gistyc 只考虑 Python 文件”——这是一个更通用的解决方案的功能。

请从一开始就为每个功能或测试驱动开发(TDD)风格的工作添加测试。严格执行 PEP8 标准、静态类型和其他要求,并对每个拉取请求进行检查。所有测试项目的列表可以在YAML 文件中找到。相应的配置文件存储在存储库的根目录中。

现在,我祝大家编码愉快。我期待您的评论和反馈,

托马斯

数据运营—为数据工程师和科学家提供 Git 行动和平台— GCP/AWS/Azure

原文:https://towardsdatascience.com/git-actions-terraform-for-data-engineers-scientists-gcp-aws-azure-448dc7c60fcc?source=collection_archive---------14-----------------------

在接下来的 10 分钟内,您将学到一些东西,从而丰富您的数据之旅。有了这个职位,数据工程师和科学家可以轻松地 CICD 基础设施。

我坚信,在 POC 一个新的设计或代码模板,并得到其他工程师的审查,因为你永远不知道你错过了什么有效的细微差别,它总是好的有一套新的眼睛审查代码。我倾向于使 POC 尽可能接近 MVP(最小可行产品),以使我自己和团队对设计更有信心,并且不会在以后的回归测试中浪费任何时间。这也有助于更好、更准确地评估我的交付任务。但是当我不得不依赖 DevOps 团队在开发环境中‘基础设施即代码’(IAC)我的项目时,问题就出现了。在生产环境中,最好让他们参与到基于他们所学的最佳实践的基础架构开发中,但是在开发环境中,只需等待他们对您的任务进行优先级排序,就可以让您的 MVP 脱轨。

因此,几年前我开始学习 DevOps/DataOps,并从 Cloudformation (CFN)和 Atlassian Bamboo 开始,因为我主要从事 AWS 工作,该组织正在使用 Bamboo。但是最近,我有机会接触 Terraform (TF)和 Github Actions,因为我被要求在 GCP 上工作,亲爱的,哦,亲爱的,它太容易掌握和学习了,因为有了 TF 和 Actions,你可以在任何云中部署。对于数据工程师、科学家或分析师来说,如果您知道 IAC 工具,它会变得非常方便。由于 Github 动作离你的代码更近,对我来说变得更加方便。

因此,我将把它分成三个简单的部分:

  1. 将 TF cloud 集成到 Github
  2. 运行 TF 步骤的 Github 操作工作流
  3. 基于最佳实践的 TF 文件概述

将 Terraform 云集成到 Github

首先,TF 有一个社区版本,所以继续在那里创建一个帐户。下面是链接:【https://www.terraform.io/cloud。它会要求您确认您的电子邮件地址和一切,所以我假设这一步结束时已经完成。此外,为了完成这些步骤,如果您在 GCP 或任何云中有自己的帐户,那就太好了。还有你自己的 Github 账号。

步骤 2: TF 有其层次结构,其中每个组织有多个工作区,每个工作区与 repo 中的 IAC Github 分支有一对一的映射,您将在其中推送更新的 Terraform 文件(最佳实践)。文件是用哈希公司的配置语言(HCL)编写的,这有点类似于 YAML。因此,这个想法是,每当你将一个新的更新(或合并一个 PR)推送到 Github 分支时,Github-actions 将在 TF cloud 上执行并运行带有新变更集的计划。由于 TF cloud 链接到 GCP(稍后),它将更新 GCP 的资源。

CICD 工艺流程

在您的 Terraform 社区帐户中创建一个组织和其中的工作空间。

**第三步:**假设您有自己的 GCP 帐户,在您希望部署资源的项目中创建一个服务帐户,复制它的密钥并将其作为 GOOGLE_CREDENTIALS 放入环境变量 Terraform 变量中。如果您使用 AWS,那么您需要输入 AWS_ACCESS_KEY_ID 和 AWS_SECRET_ACCESS_KEY。

此变量包含 JSON 中服务帐户机密的内容

此 GCP 服务帐户将用于部署资源,因此它应该具有编辑角色或有权部署资源的访问级别。

您也可以在 Github secrets 中创建一个秘密,如下所示,并使用${{ secrets 从那里传递凭证。Github 中的 GOOGLE_CREDENTIALS }}操作如下。

步骤 4: 在创建工作空间时,它会让你选择 github repo,这样它就可以在内部进行身份验证,否则你必须在 Terraform 中生成一个令牌,并将其保存在 Github secrets 中,以便在 Github actions 中的' Setup Terraform' 步骤中使用。

通过选择其中的任何一个,它将在需要时自动进行身份验证

运行 TF 步骤的 Github 操作工作流

需要放入以下 Github 操作脚本。github/workflow/ folder 作为 anyname.yml。这是一个特定作业中的连续步骤,当有人在 repo 中推出新的更改时该做什么。下面,github actions 将使用 ubuntu-latest 中的 bash 来检查代码、设置 terraform 并运行 terraform init、plan 和 apply。

name: 'Terraform CI'on:
  push:
    branches:
    - main
  pull_request:jobs:
  terraform:
    name: 'Terraform'
    runs-on: ubuntu-latest# Use the Bash shell regardless whether the GitHub Actions runner is ubuntu-latest, macos-latest, or windows-latest
    defaults:
      run:
        shell: bashsteps:
    # Checkout the repository to the GitHub Actions runner
    - name: Checkout
      uses: actions/checkout@v2# Install the latest version of Terraform CLI and configure the Terraform CLI configuration file with a Terraform Cloud user API token
    - name: Setup Terraform
      uses: hashicorp/setup-terraform@v1# Initialize a new or existing Terraform working directory by creating initial files, loading any remote state, downloading modules, etc.
    - name: Terraform Init
      run: terraform init
      env:
        GOOGLE_CREDENTIALS: ${{ secrets.GOOGLE_CREDENTIALS }}# Checks that all Terraform configuration files adhere to a canonical format
#    - name: Terraform Format
#      run: terraform fmt -check# Generates an execution plan for Terraform
    - name: Terraform Plan
      run: terraform plan
      env:
        GOOGLE_CREDENTIALS: ${{ secrets.GOOGLE_CREDENTIALS }}# On push to main, build or change infrastructure according to Terraform configuration files # && github.event_name == 'push'
      # Note: It is recommended to set up a required "strict" status check in your repository for "Terraform Cloud". See the documentation on "strict" required status checks for more information: [https://help.github.com/en/github/administering-a-repository/types-of-required-status-checks](https://help.github.com/en/github/administering-a-repository/types-of-required-status-checks)
    - name: Terraform Apply
      if: github.ref == 'refs/heads/master'
      run: terraform apply -auto-approve
      env:
        GOOGLE_CREDENTIALS: ${{ secrets.GOOGLE_CREDENTIALS }}

Terraform 文件概述

现在 terraform 只读取那些有。tf 扩展到它或。但是有一些文件需要按原样命名,而其他文件只是资源抽象,将按无序执行,除非您使用 depends_on 提到依赖关系。Main.tf、variables.tfterraform.tfvars 是需要创建的同名文件。

数据工程项目的地形文件

main.tf:所有的资源及其适当的配置值都可以在这里提到。例如,如果您想要创建一个存储桶,则可以用 HCL 编写,如下所示:

resource “google_storage_bucket” “bucket” { 
    name = “dev-bucket-random-12345”
}

variables.tf:顾名思义,它有如下带有默认值的变量,您希望在其他资源或。类似 *$的 tf 文件。*这更像是把变量放在不同的 variables.tf 文件中的惯例,但是你也可以把它放在 main.tf 中。

variable “region” { 
    type = string 
    default = “australia-southeast1”
}

terraform.tfvars:这将包含上面定义的变量的实际值。本质上,如果下面没有提到 region,那么它将采用上面的默认值。

project_id = “bstate-xxxx-yyyy”
region = “australia-southeast1”

其余的文件将不同类型的资源抽象到不同的文件中。例如,networks.tf 将拥有 VPC 和子网资源,stackdriver.tf 将拥有警报和监控仪表板,dataproc.tf 将拥有集群和节点资源,类似的还有防火墙、GKE 等。

对于那些不知道的人,TF 和 CFN 都有文档,这些预定义的功能或资源配置可以帮助我们理解选项的含义。以下是 GCP:https://registry . terraform . io/providers/hashi corp/Google/latest/docs

示例监控通道

在以下示例中,为 Stackdriver 警报创建了一个监视通道。所有字段都是自解释的,来自 GCP Terraform 文档,在输出变量“gsingh_id”的帮助下,您可以在任何中直接使用它。tf 文件或者不想指定输出,可以直接这样用:Google _ monitoring _ notification _ channel . gsingh

resource "google_monitoring_notification_channel" "gsingh" {
  display_name = "xxxx@yyyy.com"
  type = "email"
  labels = {
    email_address = "xxxx@yyyy.com"
  }
}

output "gsingh_id" {
  value = "${google_monitoring_notification_channel.gsingh.name}"
}

下面创建了一个子网,VPC 以类似的方式被指定为该子网的依赖项。

resource "google_compute_subnetwork" "vpc_subnetwork" {
  name          = "subnet-01"
  network       = google_compute_network.vpc_network.self_link
  private_ip_google_access = true
  ip_cidr_range = "10.xx.xx.xx/19"
  region        = "australia-southeast1"
  depends_on = [
    google_compute_network.vpc_network,
  ]
}

结论

如前所述,每当您向这个 repo 推送新的变更时,Git actions 将从主分支签出代码,并运行 Terraform Init、Plan 和 Apply 以在云中部署变更。在接下来的几天里,我将发表一系列文章,介绍如何通过 Git 操作在 GKE 集群上部署 Flink 应用程序,这也将让您了解如何使用 Git 操作构建 Scala 应用程序。敬请关注。

面向数据科学家的 Git 和 GitHub 基础知识

原文:https://towardsdatascience.com/git-and-github-basics-for-data-scientists-b9fd96f8a02a?source=collection_archive---------3-----------------------

UCL 数据科学研讨会 8:什么是 Git,创建本地存储库,提交第一批文件,链接到远程存储库

照片由扬西·敏在 Unsplash 上拍摄

今年,作为 UCL 数据科学学会的科学负责人,该学会将在整个学年举办一系列 20 场研讨会,涵盖的主题包括数据科学家工具包 Python 和机器学习方法简介。每一篇文章的目标都是创建一系列的小博客,这些小博客将概述要点,并为任何希望跟进的人提供完整研讨会的链接。所有这些都可以在我们的 GitHub 资源库中找到,并将在全年更新新的研讨会和挑战。

本系列的第八个研讨会是 Git 和 GitHub 简介,我们将介绍什么是 Git 和 GitHub,创建您的第一个存储库,进行第一次提交,然后将其链接到远程存储库。关于分支、秘密文件和返回到先前提交的更多细节也可以在我们的 GitHub 页面上找到。

如果您错过了我们之前的任何研讨会,您可以在以下链接中找到最后三个:

Git 是什么,为什么?

据 Git 网站报道:

Git 是一款 免费开源 分布式版本控制系统,旨在快速高效地处理从小到大的各种项目。

包括:

  • 充当工业生产标准
  • 在黑客马拉松中使用
  • 用于写书
  • 用于保存讲义和实用笔记
  • 任何其他用途…

Git 本身与 GitHub 的区别在于,Git 是一个管理项目版本控制的系统,而 GitHub 是一个使用 Git 托管项目的远程平台。这意味着,虽然可以使用 Git 系统,但不一定必须使用 GitHub,除非您希望在另一个平台上备份您的存储库。

你的第一个 Git 回购

为了与 Git 和 GitHub 进行交互,我们将不再使用我们已经拥有的 Jupyter 笔记本,而是使用命令线/终端进行交互。为此,特别是与 GitHub 操作相关的,我倾向于使用 GitBash,它允许我与 GitHub 很好很容易地交互,但是你可以在 Mac 上使用你自己的术语,或者在 Windows 上使用 Bash。

为了创建项目,我们需要为您的项目创建一个目录/文件夹。在命令行中,我们可以使用mkdir命令,后跟文件夹的名称,这将在您的机器上创建一个文件夹。

 mkdir my-novel

然后,我们使用cd命令通过命令行导航到该文件夹,这将允许我们按如下方式更改目录:

cd my-novel

一旦我们进入那个目录,我们就可以用 Git 初始化项目,这样 Git 就可以使用git init命令来管理项目的版本:

git init

现在,您的目录中应该有一个.git文件夹,它现在应该是不可见的。您刚刚创建的项目应该被称为本地工作区

承诺回购

当然,现在我们已经创建了存储库,然后我们需要实际填充它!我们可以继续使用命令行创建我们小说的开头,使用nano命令打开一个文本编辑器开始创建一个文件。在我们的例子中,我们可以将这个 intro.txt 称为:

nano intro.txt

你可以继续写你自己的小说介绍。完成后,您可以使用命令ctrl o保存文件,然后使用ctrl x退出文件。

在我们提交我们的变更之前,为了确保我们在最初的工作过程中有一个记录,我们需要将我们的变更添加到阶段中(或者称为阶段化变更)。这是使用git add命令完成的,通过该命令,您可以指定您想要添加的文件名,也可以使用.来指定任何更改,如下所示:

git add intro.txt

然后,我们可以使用status命令检查我们的阶段,如下所示:

git status

我们将会看到

On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

	new file:   intro.txt

对我们来说关键的事情是,这告诉我们有新的文件intro.txt要提交,但是到目前为止我们还没有提交。

记住这一点,然后我们可以使用commit命令提交我们的更改。这里的关键是我们可以使用-m参数,在此之后,我们指定一个注释字符串来解释您正在提交的内容、您所做的任何更改以及为什么会这样。这只是确保你记住你所做的任何重要的改变,这样如果你的代码终止了,或者在我们的例子中,我们想要撤销我们小说的一个章节,我们知道根据消息返回哪个提交。这里我们可以这样做:

git commit -m "Initialise the novel with an intro chapter"

我们已经为这个项目做出了我们的第一份贡献!

促成远程回购

当然,在我们的本地机器上进行所有的修改对于版本控制来说是非常好的(不再有最终的最终版本 27.txt 文件!),但是如果我们希望与其他人协作,或者我们希望有一个远程备份以防出现问题,该怎么办呢?为此,我们可以使用 GitHub 的魔力。

为此,我们需要创建一个 GitHub 帐户并初始化一个新的存储库。为此,一旦你建立了你的帐户,你需要创建一个新的存储库,但要确保你不要用自述文件、许可证或gitignore文件来初始化它,因为这会产生错误。不过不要担心,您可以在推送到远程存储库之后创建这些文件。

因为我们已经提交了我们自己的本地存储库,所以我们需要做的就是将远程存储库链接到我们自己的存储库。为此,我们需要使用存储库 url,它位于以下位置:

作者图片

在您的项目中,我们可以通过我们的终端使用git remote add origin链接该项目,如下所示:

git remote add origin <REMOTE_URL>

确保你使用的是你自己的网址。

然后,我们可以使用git remote -v来验证这个连接,它将打印出您指定的远程 url。现在我们已经连接到了我们的远程存储库!

然而,这里的一个问题是,我们没有设置推送到远程原点的确切位置。虽然我们有本地存储库,但在我们的远程存储库中还没有分支。为此,我们可以指定:

git push --set-upstream origin HEAD:master

这将告诉存储库的当前负责人将其推送到我们存储库中的主分支。

然后,我们可以通过指定按如下方式推送HEAD来首次推送我们的远程存储库:

git push origin HEAD

这意味着在我们添加并提交所有文件后,我们需要做的就是在将来使用git push,这很简单!您可以通过访问 GitHub 帐户中的存储库来检查以确保您的文件在远程存储库中,并且文件应该在那里。这将允许你不仅将你的工作存储在一个远程存储库上,还可以与其他程序员协同工作!

现在,您已经创建了您的第一个本地存储库,提交了您的文件,然后将它们推送到远程存储库。在实践本身中,提供了关于分支的更多细节。gitignore 文件(为了保密!)以及返回到以前的提交,这些都可以在这里 找到

如果您想了解我们协会的更多信息,请随时关注我们的社交网站:

https://www.facebook.com/ucldata:[脸书](https://www.facebook.com/ucldata)

insta gram:https://www.instagram.com/ucl.datasci/

领英:https://www.linkedin.com/company/ucldata/

如果你想了解 UCL 数据科学协会和其他优秀作者的最新信息,请使用我下面的推荐代码注册 medium。

https://philip-wilkinson.medium.com/membership

我的其他媒体文章可在以下网址找到:

[## scikit-learn 决策树分类器简介

towardsdatascience.com](/introduction-to-decision-tree-classifiers-from-scikit-learn-32cd5d23f4d)

数据科学家 Git 备忘单

原文:https://towardsdatascience.com/git-cheat-sheet-for-data-scientists-fa0bfdd3690c?source=collection_archive---------28-----------------------

入门指南

由 Roman Synkevych 在 Unsplash 上拍摄

Git 是一个免费的开源版本控制系统。大多数程序员和数据科学家每天都与 git 进行交互。那么什么是版本控制呢?版本控制是我们作为程序员跟踪代码变更的一种方式,也是与其他程序员合作的一种方式。这允许我们回顾我们随着时间的推移所做的所有更改,这有助于我们了解我们在何时做了什么,以及如果需要的话,转换回先前的代码版本。你可能之前听说过 Github,可能想知道 Git 和 Github 有什么区别。需要注意的是,Git 和 Github 并不相同。Github 是一个基于云的托管服务,托管和管理 Git 存储库,它扩展了 Git 的基本功能。除了 Github,还有 Bitbucket、GitLab、Codebase、Launchpad 等很多其他服务。在本文中,我将分享一些常见的 Git 命令以及一些比较和它们的用例。

Git 如何工作的基本概述:

  1. 用 git 托管工具(比如 Github)创建一个“存储库”(项目)
git init

当你输入git init的时候,确保你在你的项目的一个根文件夹中,否则,git 将会跟踪你电脑上的所有文件并且减慢所有的速度。如果你不小心在错误的地方输入了git init,你可以通过输入rm -rf .git来撤销。

2.添加远程存储库/将存储库复制(或克隆)到本地机器

//add the remote repository
▶️ git remote add origin <HTTPS/SSH>// clone the repository
▶️ git clone <HTTPS/SSH>

使用代码下拉列表查找 HTTPS/SSH URL。(作者截图)。参考:https://github.com/academic/awesome-datascience

3.创建一个“分支”(可选,但推荐)

//create a new branch and switch to it at the same time
▶️ git checkout -b <branch-name>
▶️ git switch -c <branch-name>//simply switch to an existing branch
▶️ git checkout <branch-name>
▶️ git switch <branch-name>

git switch不是一个新特性,而是重载的git checkout命令的附加命令。git checkout可以用来切换分支,恢复工作树文件,也可以混淆。为了分离功能,GIT 社区引入了这个git switch命令。

4.要使特征分支保持新鲜,并与主分支中的最新更改保持同步,请使用 rebase

▶️ git pull
▶️ git pull --rebase origin master

我们经常看到冲突发生在这一步。在此步骤中解决冲突有助于保持要素分支历史的整洁,并使最终合并更加容易。

虽然git pullgit rebase紧密相连,但它们不可互换。git pull从远程获取当前分支的最新变更,并将这些变更应用到分支的本地副本。一般来说,这是通过 git merge 完成的,即本地变更被合并到远程变更中。所以 git 拉同时类似于git fetch + git merge

git rebase允许我们在远程主分支上应用我们的更改,这给了我们一个更清晰的历史。这是合并的替代方案。使用此命令,您所做的本地更改将基于远程更改之上,而不是与远程更改合并。

5.将文件添加到本地存储库中或对文件进行一些更改,然后在准备好保存更改时将其放入暂存区

//Add one file
▶️ git add <file-name>//Add all the new/modified/deleted files to the staging area
▶️ git add -A (note: -A is shorthand for --all)//Stages files in the current directory and not any subdirectories, whereas git add -A will stage files in subdirectories as well.
▶️ git add .//Stage all new and modified files. The previous commands will also remove a file from your repository if it no longer exists in the project. 
▶️ git add --ignore-removal//Stage all modified and deleted files
▶️ git add -u (note: -u is shorthand for --update)

5.“提交”(保存)更改

git commit -m “message about the changes you've made”

6.将您的更改“推”到您的分支

git push origin <branch-name>

git set-upstream 允许您为当前的本地分支设置默认的远程分支。您可以通过添加-ugit push -u origin <branch-name>来设置上游。这个命令将把<branch-name>分支设置为默认分支,这允许您推送更改,而不需要指定您正在推送的分支。设置了上游之后,下次当您将一些更改推送到远程服务器时,您可以简单地键入git push

8.打开一个“拉请求”(又名“PR”),请求将变更合并到主分支

拉式请求是一个让开发者更容易协作的特性。一旦开发人员创建了一个拉请求,团队的其他成员就可以检查代码,然后将新的变更合并到主分支中。

一旦您在特性分支中推送了新的变更,您现在就可以创建一个拉请求了(作者截图)

9.将你的分支“合并”到主分支

然后,主分支机构的管理员会看到这一点,他或她将合并您的拉请求,一旦代码已被审查。(作者截图)

有用的 Git 命令

  1. git status —显示已暂存、未暂存和未跟踪的文件。
  2. git log —显示整个提交历史。这里需要注意的一点是,黄色突出显示的数字是提交 ID。提交 ID 是提交中所有数据的 sha1 散列。两次提交具有相同的提交 ID 是非常罕见的,但这是可能的。

git 日志(作者截图)

3.git diff —比较变化。git diff可用于比较提交、分支、文件等。您可以从提交 ID 中复制前几个字符(> 4),Git 将能够判断出您指的是哪个提交。利用上图,我们可以用 9b0867 和 51a7a。

//Show difference between working directory and last commit.
▶️ git diff HEAD//Show difference between staged changes and last commit
▶️ git diff --cached//Show difference between 2 commits
//To see what new changes I’ve made after the first 51a7a commit: 
▶️ git diff 51a7a 9b0867

4.git branch —列出您的回购中的所有分支。记得在按下代码之前检查这个。我肯定你不想不小心把你的代码推到主分支或者其他分支。

5.git branch -m <new-branch-name> —重命名分支机构名称

//Checkout to the branch you need to rename
▶️ git checkout <old-branch-name>//Rename branch name locally
▶️ git branch -m <new-branch-name>//Delete old branch from remote
▶️ git push origin :<old-name> <new-branch-name>//Reset the upstream (optional) branch for the new branch name
▶️ git push origin -u (optional) <new-name>

6.git revert —创建一个新的提交,撤销在<提交>中所做的所有更改,然后将其应用到当前分支。这必须在“提交级别”完成。

7.git reset —这可以在“提交”或“文件”级别完成。在提交级别,git reset丢弃私有分支中的提交或丢弃未提交的更改。在文件级,git reset可以从暂存文件中删除文件。

//Reset staging area to match most recent commit, but leave the working directory unchanged.
▶️ git reset//Move the current branch tip backward to <commit>, reset the staging area to match, but leave the working directory alone.▶️ git reset <commit>//Same as previous, but resets both the staging area & working directory to match. Deletes uncommitted changes, and all commits after <commit>. 
▶️ git reset --hard <commit>//Reset staging area and working directory to match most recent commit and overwrites all changes in the working directory. ▶️ git reset --hard

8.git stash —获取您未提交的更改(暂存的和未暂存的),保存它们以备后用,然后从您的工作副本中恢复它们。默认情况下,Git 不会隐藏对未被跟踪或忽略的文件所做的更改。这意味着 git 不会隐藏未暂存的文件(即没有运行git add)和已经被忽略的文件。

//Stash your work: once you've stashed your work, you're free to make changes, create new commits, switch branches, and perform any other Git operations; then come back and re-apply your stash when you're ready.
▶️ git stash// re-apply stashed changes
▶️ git stash pop// list stack-order of stashed file changes
▶️ git stash list//discard the changes from top of stash stack
▶️ git stash drop

9.git fetch <remote> <branch> —从远程存储库中获取特定的<分支>。关闭<分支>以获取所有远程参考。

10.git rm <file> —删除文件。当使用此git rm命令删除一个文件时,并不意味着该文件从历史中删除。该文件将在存储库历史中保持“存活”,直到该文件将被完全删除。

摘要

现在,您已经理解了基本的 Git 命令,是时候使用它们并开始用 Github 构建您的数据科学组合了!

资源:

  1. https://www.youtube.com/watch?v=RGOj5yH7evk
  2. https://git-scm.com/
  3. 【https://www.atlassian.com/git/tutorials
  4. https://learngitbranching.js.org/
  5. https://bluecast.tech/blog/git-stash/
  6. https://www.atlassian.com/git/tutorials/cherry-pick

如果你觉得这很有帮助,请关注我,看看我的其他博客。敬请关注更多内容!❤

</10-tips-to-land-your-first-data-science-job-as-a-new-grad-87ecc06c17f7>

我作为软件开发人员的第一年学到的 18 个 Git 命令

原文:https://towardsdatascience.com/git-commands-cheat-sheet-software-developer-54f6aedc1c46?source=collection_archive---------0-----------------------

初级软件开发人员的实用 Git 备忘单

蒂姆·范德奎普在 Unsplash 上拍摄的照片

G 它是使用最广泛的免费开源分布式版本控制系统(VCS)。在过去的几年里,Git 已经从开发人员的首选技能转变为必备技能。很难想象一个没有 VCS 的项目,它简化了开发过程。

回到 2018 年,我开始了作为软件开发人员的职业旅程。我对软件开发很熟悉,但是 Git 是未知的领域。令人困惑和恐惧。后来我发现一些资深开发者还是很怕它。我很幸运有一个好的导师指导我每一步。

在我培训期间,我的经理让我从头开始做一个 web 开发项目。他给了我一个模糊的需求列表,并让我找出其余的。这是我第一次感到自己脱离了舒适区。也是我第一次用 Git。

以下是我作为软件开发人员第一年学到的 18 个 Git 命令。从技术上来说,有 18 个以上,但我把相关的命令放在一个标题下。你可以在这里找到完整的 Git 指南。

1)创建新的存储库

建立我的第一个职业发展项目既令人兴奋又令人恐惧。如果你不知道自己在做什么,这并不夸张。我被要求在 Gitlab 上添加这个项目。IT 团队已经在我的 Linux 系统上设置了 Git。是时候创建一个新的 Git 存储库了。

***git init***

Git 命令初始化或创建新的存储库——按作者排列的图像

执行该命令将创建一个带有默认(或)分支的本地存储库。

要将这个本地存储库连接到 Github,我们需要在 Github 上创建一个远程存储库。并将远程存储库的源与本地存储库连接起来。

***git remote add origin https://github.com/******YOUR-USERNAME/YOUR-REPOSITORY***

Git 命令将远程源添加到本地存储库——图片由作者提供

最后在 Github 上推主分支。

***git push -u REMOTE-NAME BRANCH-NAME***

Git 命令推送本地主分支——按作者排序的图像

**注意:**在项目工作目录下,通过终端(Linux)或 Git Bash(Windows)执行所有 Git 命令。

2)创建新的分支

实现一个新特性的黄金标准是创建一个新的分支,并将所有代码放入其中。这使得现有代码不会出现糟糕的实现。

***git checkout -b NEW-BRANCH-NAME***

Git 命令创建一个新的分支——作者的图像

如果存储库中不存在新分支,checkout 命令会创建新分支。而-b选项从当前分支切换或检出到新创建的分支。在创建新分支之前,最好先切换到主分支。主分支通常拥有最新的代码。

一旦我们创建了一个新的本地分支,它应该被推送到远程存储库——就像前面所做的那样。

Git 命令来推送新创建的分支——作者的图像

3)开关支路

当您开始处理一个新项目时,最好对存储库中的分支有一个大致的了解。

***git branch***

Git 命令列出存储库中的所有分支——按作者排序的图像

列出所有分支后,使用以下命令切换到所需的分支:

***git checkout BRANCH-NAME***

Git 命令切换分支——作者图像

如果在当前分支中没有未提交的更新文件,checkout 命令可以很好地工作。否则,这些未提交的更改将导致错误。在切换到另一个分支之前,最好提交或保存当前分支中的更改。

由于未提交的更改而导致签出错误—按作者排序的图像

4)隐藏/取消隐藏文件

解决签出错误的方法之一是隐藏更改。如果您还没有准备好提交这些变更,这通常是为了保存您在当前分支中已经完成的工作。

***git stash***

Git 命令隐藏未提交的更改—作者图片

要恢复或撤销隐藏的更改,我们可以回到我们隐藏更改的分支并弹出它们。

***git stash pop***

Git 命令恢复隐藏的更改—作者图片

5)检查分支状态

我有一个奇怪的习惯,经常检查分行的状态。它给出了关于分支机构当前状态的所有必要信息。我们可以检查所有已实施或未实施的变更。

***git status***

Git 命令检查分支的状态——作者的图像

6)重命名本地分支

分支重命名并不是最常用的 Git 命令之一,但是如果有输入错误,它会很方便。或者在我的例子中,重命名分支以形成一致的 Git 目录结构。

***git branch -m OLD-BRANCH-NAME*** ***NEW-BRANCH-NAME***

Git 命令重命名一个分支——作者图像

7)重命名远程分支

重命名本地分支后,就应该更改相应远程分支的名称了。

***git push origin :OLD-BRANCH-NAME NEW-BRANCH-NAME***

Git 命令重命名远程分支——作者图像

该命令删除旧名称的分支,并创建一个具有相同代码库的新分支。

8)同步分支变化

一旦在您的项目中创建了一个新文件或者更新了一个现有文件,我们就必须将这些文件添加到下一次提交中。

***# To add all changes
git add .
# To add a specific file
git add FILE-PATH***

Git 命令添加单个文件或所有文件——按作者分类的图像

当所有必需的更改都已添加到提交中时,就该提交这些更改并编写唯一的提交消息了。提交消息可以是任何可以用几句话描述您的工作的字符串。

***git commit -m "COMMIT-MESSAGE"***

Git 命令提交更改—作者图片

最后,使用*git push*命令将这个提交推送到远程存储库。您还可以更新或修改您的提交。

***git add*** ***FILE-PATH
git commit --amend -m "CHANGE-COMMIT-MESSAGE"***

Git 命令修改以前提交的图像(由作者提供)

这是我最喜欢的 Git 命令之一。当你在团队中工作时,代码审查是非常重要的。高级开发人员或团队领导经常指出代码中的重要问题。我们没有创建一个新的提交来解决这些问题,而是遵循了每个分支一个提交的惯例——*git amend*被证明是方便的。

9)克隆存储库

我为我的第一个实时项目执行的第一个 git 命令是*git clone* 。我被要求在我的本地系统上克隆项目,以理解代码,添加一些功能,并通过合并请求将代码推回。

***git clone*** ***https://github.com/YOUR-USERNAME/YOUR-REPOSITORY***

Git 命令克隆一个存储库——按作者的图像

10)检查提交日志

日志是软件开发的重要组成部分。软件维护日志文件来记录其生命周期中的所有步骤。Git 还提供了一个日志来跟踪所有的提交。

***git log***

显示提交日志的 Git 命令—按作者显示图像

11)重置到最后一次提交

拥有重置或撤销任务的权力是救命稻草。在我作为一名开发人员的早期,我曾经犯过一个错误,那就是更改实时生产代码。这是一个错误。令我惊讶的是,我没有被解雇。让我免于造成更多伤害的是重置命令。它允许我在一瞬间将所有更改恢复到最后一次工作提交。

***git reset --hard origin/BRANCH-NAME***

Git 命令将代码库重置为上一次工作提交—作者图像

12)将本地存储库与远程存储库合并

这就是奇迹发生的地方。当我们在开发软件时,我们通常会维护代码库的三个副本。

一个是本地副本,开发人员在其上工作并执行所需的任务。第二个是暂存副本或暂存服务器,在这里部署这些任务并与客户端共享。客户对软件的所有新变化给出反馈。然后,开发团队处理这些更改,并将它们部署回临时服务器。这个循环会一直持续到客户批准将这些更改部署到第三台也是最后一台生产服务器上。

每次部署新功能或更新现有功能时,我们都会执行合并操作。来自 Github 远程存储库的更新代码文件与这三台服务器上的本地存储库合并。

合并存储库时最常见的问题是合并冲突。必须解决这些冲突才能完成合并操作。

***# Fetch remote from github
git fetch REMOTE-NAME
# Merge remote branch with local branch
git merge REMOTE-NAME/BRANCH-NAME***

Git 命令将远程分支与本地分支合并——图片由作者提供

合并操作分两步执行。我们从 Github 获取或下载包含所需代码库的遥控器。然后合并远程和本地分支历史。

另一种执行合并的方法是*git pull*。拉取和合并的工作方式是一样的,还有取取的好处。*git pull*执行 fetchmerge — 合并两个或更多分支,而不是如上所示分别执行这两个操作。

***git pull REMOTE-NAME BRANCH-NAME***

Git 命令从远程分支提取变更,并将它们与本地分支合并——按作者排序

13)将提交从一个分支移动到另一个分支

当你在一个项目上合作时,最好是每个开发人员从事一个单独的特性——好得难以置信。根据任务的复杂程度,它被分配给多个开发人员。

高内聚和低耦合经常被忽略或不切实际。这在开发过程中产生了许多问题。

我做过几个这样的功能。在大多数情况下,我被要求从其他分支获取未完成的代码,并试图在牢记未完成部分的同时对其进行扩展。*git cherry-pick*起了重要作用。

***git cherry-pick COMMIT-HASH***

Git 命令将提交从一个分支移动到另一个分支——作者图片

这个命令在当前分支上应用所选择的提交,这在 bug 修复期间也非常方便。尽管精心挑选很有用,但并不总是最佳实践。这可能会导致重复提交,这就是为什么在大多数情况下首选合并的原因。

14)删除未被跟踪的文件和目录

使用*git clean* 可以很容易地从工作目录中删除尚未提交的文件和目录。我用它来删除我的 IDE 创建的不需要的文件和目录。

# To remove untracked files
***git clean -f***
# TO remove untracked directories
***git clean -fd***

Git 命令删除不需要的文件和文件夹-图片作者

15)删除本地存储库的一个分支

如果不再需要某个分支,最好通过删除该分支来清理存储库。要删除本地存储库中的分支,使用带有*-d*选项的*git branch*

***git branch -d BRANCH-NAME*** # To forcefully delete a local branch. Be careful
***git branch -D BRANCH-NAME***

Git 命令删除本地分支——作者图片

16)删除远程仓库上的分支

删除远程存储库上的分支类似于使用相同的带有*--delete*选项的*git push*命令在远程上推送更新。

***git push REMOTE-NAME --delete BRANCH-NAME***

Git 命令删除远程分支——作者图片

17)忽略 Git 权限更改

我在一个基于 Linux 的系统上工作,在那里使用*chmod*设置文件权限对于安全性非常重要。在开发过程中,我们通常会将文件的模式更改为 777 以使其可执行。Git 获取这些权限变更,并在*git status*中将它们显示为更新的文件。

***git config core.fileMode false***

Git 允许我们通过将配置中的*fileMode*改为来忽略这些变化。

18)修复。gitignore

。gitignore file 是一个福音,它帮助我们忽略将不需要的文件提交到存储库中。但是如果文件已经被 Git 跟踪了,那就麻烦了。

谢天谢地,有一个简单的解决办法。它需要移除缓存的。gitignore 索引并再次将其添加到存储库中。

# To create a new .gitignore file ***touch .gitignore***# To untrack the unnecessary tracked files in your gitignore which removes everything from its index. Specific filenames can also be used instead of dot(.).
***git rm -r --cached .
git add .
git commit -m "gitignore fixed untracked files"***

Git 命令检查状态——按作者分类的图像

要修复的 Git 命令。gitignore —作者图片

总结想法

这是冰山一角。像其他任何事情一样,Git 需要实践和实验。掌握 Git 要难得多。一年之内,我只能学会它的基础。

对于初级开发人员来说,还需要克服学习新事物的恐惧。没有 Git,开发人员的投资组合是不完整的——就像不带任何武器去打仗一样。

Git 命令科学家日常使用的数据

原文:https://towardsdatascience.com/git-commands-data-scientists-use-on-a-day-to-day-basis-40d588cd63f7?source=collection_archive---------4-----------------------

面向数据科学家的 GIT

适用于查看本地 PR 副本、带回混乱的文件或删除 PR 中的文件等情况。

在你问我为什么在 2021 年还在使用命令行 Git 之前,等等,我可以解释!所以你真的不喜欢使用命令行,尤其是当有这么多完美的图形用户界面存在的时候。

最近,我的大部分工作转移到了 Linux 机器上,我正在寻找一个 git 扩展或 GUI 来支持 Jupyterlab 远程服务器。在这个问题这里浪费了许多宝贵的时间之后,我最终决定系好安全带,作为一名数据科学家,学习一些可能对任何给定场景都有用的命令。同样,我希望在无法使用 GUI 并且 Git 命令行是唯一选择的服务器环境中工作时,学习这些知识会派上用场。

不仅仅是一个备忘单,我更愿意把这篇文章看作是一个假设的你会做什么的场景列表,一个我可能会比你们中的任何人使用得更多的场景(尽管如果它确实对你有帮助,嗯…越多越好!:) ).有些场景是基本的,我相信你知道如何通过它们,其他的场景更具体,尽管我相信你能理解它们。

这绝不是一个详尽的列表,而是一些在我日常工作环境中经常出现的主题。

免责声明:本文是为具有一些 Git 基础知识的读者而写的。我的基本意思是,如果你拥有一个 Github 账户,并且当我说“检查一个分支”和“提交一个更改”时,你不认为我在说某种外星语言,那么你就一切就绪了!

术语和术语

在整篇文章中,每当我提到本地变更时,我指的是您在本地对您计算机上的项目副本所做的变更。远程变更意味着您正在对存在于 Github 服务器上的项目副本进行变更。

作为一个经验法则,在本地拷贝上玩你想玩的,但是在用你的本地改变修改远程拷贝时要非常小心。

考虑到所有这些,让我们浏览一下初学者可能面临的一些常见场景以及如何解决它们。

附言:这些场景没有特定的顺序。

场景 1

公司开始了一个新项目,你想参与其中,这样你就可以开始为之做出贡献。

一旦某个团队成员将您添加为协作者,您所要做的就是转到 Git bash 或 Mac 终端,根据您是想在桌面上还是下载文件夹中创建这个本地 repo 来执行cd Desktopcd Downloads,然后执行以下操作:

git clone https://github.com/V-Sher/medium_demo.git

在这里,我试图克隆我为这篇文章创建的一个(私人)回购,但请随意用您自己的远程 URL 替换它。您感兴趣的 repo 的远程 URL 可以在该项目的 Github 页面上找到(参见下图中用蓝色突出显示的文本)。

图 1:蓝色突出显示的文本是 repo 的远程 URL。

场景 2

创建你自己的分支,开始工作并与同事分享。

创建一个分支并开始工作总是比搞乱main分支好。在这样做之前,最好先检查所有可用的本地分支:

git branch

您当前所在的分支旁边会有一个*。在我的例子中,我好像在main上,我想从这个分支创建一个名为agenda的分支。

git checkout -b agenda

这里的agenda是我的分支的名字,但是你可以随意选择你喜欢的名字。运行该命令将使agenda成为当前工作分支,如果再次运行git branch命令,您将看到*已经转移。

从这里开始,我将把两个文件添加到本地机器上的medium_demo文件夹中,分别名为agenda.pyfake_agenda.py,然后执行一个git add .操作,把这两个文件都添加到暂存区,然后使用git commit -m "Adding a real and fake agenda"提交这些更改。

现在,我的本地回购副本有两个额外的文件,我必须将它们推送到远程使用:

git push -u origin agenda

这里的origin是远程 Github 的名称(附注,我们将在文章末尾更详细地讨论这个问题),-u表示在“本地”agenda分支和“远程”agenda分支之间建立了跟踪连接。

现在回到您的回购的 Github 页面,您可以看到已经准备好成为拉取请求(PR)的一部分的更改:

您可以点击比较&拉动式请求按钮来创建一个 PR,并将您的同事/上司指定为其审核人。

一旦你的同事审阅了简历,他们可能会在简历上留下自己的评论,如下所示:

如你所见,审查员告诉我们必须删除不必要的fake_agenda.py文件。让我们在场景 3 中看看如何做到这一点。

场景 3

删除您作为拉请求的一部分错误添加的文件。

显然,我们不想让经理看到我们为这个项目创建的虚假议程。要解决这个问题,我们需要从 PR 中删除文件fake_agenda.py

如果我们这样做:

git rm fake_agenda.py

您会注意到它会将文件从您的工作目录中完全删除。这不是我们想要的(或者至少不是我想要的)。我们想从 PR 中删除它,但不是从我们的本地回购中。

相反,让我们先把文件带回来:

git reset -- fake_agenda.py
git checkout -- fake_agenda.py

现在将它作为我们 PR 的一部分删除,使其成为一个未跟踪的文件:

git rm --cached fake_agenda.py

要提交此更改:

git commit -m "the file fake_agenda is gone from the repository"

最后,像上次一样提交:

git push -u origin agenda

如果您返回到 PR 的 Github 页面,您将看到添加了另一个 commit,描述如何删除不必要的文件。

此外,要确认该文件不再是 PR 的一部分,请查看“文件已更改”选项卡,它应该显示 1(之前是 2,因为有额外的fake_agenda.py文件)。

场景 4

当您在其他分支上工作时,将远程更改放到您的本地机器上。

当你忙于自己的分支(从main分支分出)本地时,在远程回购中的main分支,事情可能会发生变化。随着越来越多的人在一个项目上工作——每个人都在他们自己的分支上——过一段时间,他们的分支将开始与main分支合并(当然,一旦它通过了所有的检查和评审)。

例如,您团队中的高级数据科学家决定更新main“远程”分支中的自述文件。

但是这些变化不会出现在你的‘local’main分支中。因此,您应该掌握这些变更,以保持您的本地main分支是最新的(毕竟,这是您将来创建新分支的地方)。为此,我们首先检出main分支,然后引入变更。

git checkout main
git pull

现在,如果您打开自述文件,您将会看到附加行。这意味着你当地的main分支机构全部被赶上了。

然而,如果你回到你在本地工作的分支,即agenda

git checkout agenda

并打开自述文件,它仍将和以前一样,即没有变化。理想情况下,我希望将本地main中的所有变更合并为我正在处理的分支的一部分,这样我就知道我拥有项目的最新文件。

更一般地说,要使本地分支 X 达到本地分支 Y 的速度,请确保您已经首先检出了 X (在我们的示例中, X 将是本地agenda分支, Y 将是main),然后进行合并:

git checkout agenda
git merge main

您之前在agenda分支中的所有文件将保持不变(以确认转到并手动检查文件),并添加了一些由高级数据科学家引入的新内容。

有时,合并过程可能不像您希望的那样顺利。那到底是什么意思?这意味着在合并过程完成之前,可能会有一些问题需要解决——这是由两个人在完全相同的行上更改相同的文件引起的。让我们看看如何在下一个场景中修复它们。

场景 5

如何解决合并冲突?

从场景 4 继续,让我们假设您和高级数据科学家都在完全相同的行上更改了同一个文件。在这种情况下,从最后一个场景合并将会提示如下错误:

这条消息不言自明,告诉我们它不能合并 README.md,因为我和我的学长都试图修改完全相同的行。因此,我必须在合并之前解决这个错误。为此,在编辑器中打开文件(我个人偏好 VScode),你会看到需要在<<<<<<<>>>>>>之间解决的问题。

似乎我们都在试图修改最后一行(我想说苹果,她想说橙色)。此时,您可以接受即将到来的更改,或者坚持当前的更改,或者做其他事情。一旦您对更改感到满意,保存并关闭文件。回到终端,添加并提交此更改,最后推送它:

git add README.md
git commit -m "Apples and oranges issue averted"
git push

回到 PR 的 Github 页面,您可以看到新的提交已经作为 PR 的一部分被添加。

一旦你的评审者对所有的改变感到满意,她会将 remote 上的agenda分支与 remote 上的main分支合并,你可以在 Github 页面上看到。

一旦合并,您不再需要agenda分支——您甚至可以删除它。从现在开始,我强烈建议任何时候你想在项目的其他方面工作,在确保你已经将远程main分支的最新版本拉到你的本地main分支之后,你应该从本地main分支创建一个新的分支。

场景 6

把一个被你搞砸的同事的文件带回来,恢复原状。

有时,在您的分支机构工作时,您可能会弄乱您或您的同事创建的现有文件。例如,假设我错误地修改了agenda.py文件中的打印语句

从这个

print(“The agenda for this demo is as follows: Do A then B and finally C.”)

对此

print(“The agenda for this demo is as follows: Do A and finally C.”)

还使用提交了这些更改

git add agenda.py
git commit -m "Messing up the file by removing B's info"

要将其恢复到原始形式(即,它在上次提交时的样子),只需执行git checkout <commit_id> — filename。在这里,如果您在 Github Web UI 上找到相关文件并选择其最新的提交号,就可以快速检索到commit_id

为 Github 上的文件选择最新的提交 id(在“最新提交”之后的右边)

在我们的例子中,agenda.py文件的提交 id 是3c8ebf0。因此,要使它看起来就像上一次提交一样,只需

git checkout 3c8ebf0 -- agenda.py

其次是:

git add agenda.py
git commit -m "Restoring B's info in the agenda"

场景 7

一位同事邀请您在她现有的远程分支机构工作。

通常,你的一个已经在做某个分支的同事,比如说featureB,会邀请你去做这个分支。现在让我们假设这个分支除了 Readme 文件之外,还包含一个文件featureB.py

要开始协作,您需要创建一个本地 featureB分支,并在远程和本地featureB 分支之间建立某种跟踪连接,以便您可以推送提交并对它们进行更改。

首先,确保同事的分支存在于远程服务器上——这意味着你的同事已经将她的分支推送到 origin 上——并且你可以访问它。要检查您有权访问的所有远程分支,请执行git fetch,然后执行:

git branch -r

看到我的同事希望我插话的分支,即origin/featureB,我们将简单地做:

git checkout --track origin/featureB

这将创建一个名为featureB的本地分支,您现在应该看到由文件featureB.py组成的本地回购。接下来,我将继续对该文件进行一些简单的更改(基本上添加我作为初级数据科学家的想法),并使用git push origin featureB将其推送到远程分支。这是添加我的更改后文件在 remote 上的样子:

因为你们可以同时处理文件并对其进行修改,所以我强烈建议每次在开始处理featureB分支之前先做git fetch再做git pull。一如既往,您可能需要解决一些冲突,一旦解决完毕:

git add featureB.py
git commit -m "Resolved conflict"
git push origin featureB 

或者,如果您不希望在您同事的分支featureB的本地和远程副本之间建立跟踪连接,而是希望将其与您当前工作的分支(即<branch-name>)合并:

git checkout <branch-name>
git merge origin/featureB

场景 8

如何将采购申请提取到本地回购进行审查?

有些情况下,你会被指派为公关的“审查者”,这意味着你的工作是通过分析同事的分支来确保一切正常。作为审查过程的一部分,人们可以简单地在 Github Web UI 上浏览代码,但我通常更喜欢制作 PR 的本地只读副本,并在我的终端运行它。

附注:只读副本意味着您不能将变更推送到该 PR,这是理想的,因为我们不应该将变更推送到由其他人创建的 PR,只有 PR 的 作者 应该进行变更。

为此,先使用git fetch origin pull/PULL_REQUEST_ID/head:NEW-BRANCH-NAME,再使用git checkout BRANCH_NAME

附言:您在上面的命令中看到的所有内容都是您需要提供的:

  • PULL_REQUEST_ID 可以从 PR 的 Github 页面检索。它通常是#符号后面的一个数字。对我们来说,是 4。

图 Github Web UI 上的 PR 页面。它包含有关拉取请求 id 的信息,以及创建 PR 的分支。

  • NEW-BRANCH_NAME 可以是您想称为 PR 的只读副本的任何名称。我喜欢叫我的review_***

一旦你的猫咪里有了这两样东西,就去做吧:

git fetch origin pull/4/head:review_featureb1
git checkout review_featureb1

review_featureb1分支上,你想怎么复习就怎么复习。一旦你完成了,你可以通过在 PR 的 Github 页面上留下评论来告诉作者需要做什么改变,或者你可以自己做这些改变,并使用git push -u origin patch-test_featureb1将它们推送到一个新创建的分支。

尽管我提到除了 PR 作者之外,任何人都不应该对 PR 进行更改,但有时您会希望直接对某人的 PR 进行一些更改——例如,一个非常小的打字错误需要修复——并将这些更改作为 PR 的一部分。

在这种情况下,您需要首先获得创建 PR 的分支的名称(让我们称之为<PR-branch-name>)。它通常会出现在 Github Web UI 的 PR 页面上,内容如下:<repo-author> wants to merge X commits into main from <PR-branch_name>(参见上面的图 2)。

在我们的例子中,公关似乎是从featureb1创建的。让我们使用以下方法之一来检查这个分支:

(a) git checkout featureb1(如果你在本地跟踪featureb1

运筹学

(b)情景 7 中描述的步骤(如果您没有在本地跟踪该分支机构)。

之后,您进行所需的更改,最后使用git push origin featureb1推送到遥控器上同名的分支,使其成为 PR 的一部分。

注意:在解释了两种评审方法之后,我强烈建议创建一个新的分支(而不是修改现有的 PR ),因为它给了某人一个评审你的工作(在合并之前)的机会,这样你就不会在不知不觉中弄乱某人的 PR。

场景 9

如何将我的本地更改推送到远程回购?

简而言之,这取决于你的场景。

如果您处于类似场景 2 的情况,即在本地创建的分支上工作,(这意味着它在远程还不存在),您可以

git push -u origin <my_branch_name>

它会自动在遥控器上创建同名的分支,其中的<my_branch_name>会被您在本地创建的分支的名称所替换。

或者,如果您在场景 7 中,即在本地工作于远程跟踪的分支机构,则您可以:

git push origin <remote_branch_name>

其中<remote_branch_name>应该替换为远程 repo 上存在的分支名称,并且在运行命令git branch -r时可见。

场景 10

如何在 Github 上推送空目录?

要了解 Git 如何处理空目录,让我们做一个快速设置。

使用git checkout签出任何分支,并尝试在本地 repo 中创建一个空文件夹e_folder

接下来,在终端中尝试:

git status

在理想的情况下,git 应该会提示您将这个新创建的文件夹添加到 staging area,但是没有发生类似的事情。现在继续向e_folder添加任何文件,使其不再为空:

如果您现在要做一个git status,您会看到一个提示,告诉您使用git add命令添加文件夹

简而言之,默认情况下,Git 只会跟踪非空目录——这在大多数情况下对我们来说不成问题。然而,有时我们会希望推送一个空目录。例如,我喜欢有一个空的目录作为占位符,告诉人们在使用我的模型时可以上传他们的自定义图像。

为了明确地通知 Git 跟踪我们的空目录e_folder,首先,让我们继续手动删除其中的img.jpeg文件。然后转到 Git 命令行:

cd e_folder
touch .gitignore
vi .gitignore

一旦进入可视化编辑器,

  • 按下键盘上的i
  • 将下面几行粘贴(或 Ctrl+V)在那里[Credits:stack overflow
# Ignore everything in this directory
*
# Except this file
!.gitignore
  • 按下键盘上的esc
  • 类型:wq

在 git 终端上,使用cd ..返回到medium_repo目录,然后

git status

您将看到现在 git 已经准备好将您的空文件夹添加到临时区域

继续添加它,提交它并推动它:

git add e_folder
git commit -m "placeholder for images"
git push

奖金方案 1

我检查了一个分支 X,在那里做了一些更改,使用 File → Save 保存了这些更改。然后我继续检查另一个分支 Y,我可以看到与我在 x 中所做的相同的更改。为什么在一个分支中进行更改,git 会更改所有其他分支?

查看 Stackoverflow 上的长答案。

简而言之,如果您没有使用git commit提交您在一个分支中所做的变更,那么当您切换分支时,变更也会随之而来。这意味着当您签出其他分支时,您有无意中破坏它们的风险。所以尽可能多的提交,尽可能多的提交,尤其是在对代码做一些重大修改的时候!

奖金方案 2

在推送到远程之前,如何检查我提交(即更改)了哪些文件?

通常,我们会在几周甚至几个月的时间里在几个文件中提交大量的变更,而不需要将它们推送到远程。因此,当最终推送变更(以便您的同事可以查看您的工作)的时候,我们不确定我们将要推送什么文件!

要获得自上次推送以来修改过的文件名列表(并避免任何不必要的意外),这个命令很有用:

git diff --name-only <local_branch_name> origin/<remote_branch>

<local_branch_name>替换为您正在处理的本地分支的名称,将<remote_branch>替换为远程服务器上的分支的名称,您希望将您的更改推进到该分支中。--name-only标签将确保只列举文件名,并保留每个文件中更改的细节(例如,添加或删除了哪些特定的行)。

奖金方案 3

我的同事正在进行 Git 回购,我想推送/拉取/查看他们回购中的一些文件。

还记得我说的关于的来历吗?这是我们的远程 Github repo 的名称。要检查您可以访问哪些远程 Github repos:

git remote -v

到目前为止,我们主要在一个名为origin的 repo 上工作,但假设我也想在 GitHub 上托管的其他一些远程存储库上工作。添加我的同事 *ABC* 为他的一篇媒体文章创建的 Github repo 怎么样?我确信我能帮她复习一些内容。它的远程 URL 是[https://github.com/ABC/coworker_medium_repo.git](https://github.com/V-Sher/GANs_Pytorch.git.)

首先要做的是添加这个远程存储库,即建立某种连接,并为它设置一个名称。我也不能命名我同事的 repo origin,因为它可能会混淆 Git 并导致致命错误。因此,最好使用与回购相对应的名称——我倾向于将它们命名为origin_***

git remote add origin_medium [https://github.com/ABC/coworker_medium_repo.git](https://github.com/V-Sher/GANs_Pytorch.git.)

现在,如果您在终端中执行git remote -v命令,您将看到您可以访问的所有遥控器:

同样,你可以继续使用同事的回购 URL 创建对他们回购的引用。

注意:如果您需要复习如何定位回购 URL,请看图 1。

git remote add project1_origin http:github.com/XYZ/project1.gitgit remote add project2_origin http:github.com/MNO/project2.gitgit remote add project3_origin http:github.com/PQR/project3.git

现在,假设你的同事在 Github 上为项目 2 制作了一份 PR,你必须审阅它。场景 8 中已经讨论了这样做的步骤(确保您有适当的 PULL_REQUEST_ID)。这次您需要做的唯一更改是指向正确的来源,即正确的回购名称:

git fetch **origin_medium** pull/PULL_REQUEST_ID/head:REVIEW_FEATURENAME
git checkout REVIEW_FEATURENAME

您甚至可以获取它们的一个分支,并使用以下命令在本地跟踪它们:

git fetch **origin_medium** new_agenda
git checkout new_agenda

其中new_agenda是我同事的回购协议中的一个远程分支。接下来,进行一些更改——添加、提交和推送。你现在知道规矩了:

git commit -a -m "Some input from V-Sher's end as well"
git push

注意:请记住,在我们的示例中,存在一个由来自 *new_agenda* 分支的同事创建的 PR,我们刚刚推送到该分支的任何更改也将是 PR 的一部分(见下图)。如果这不是故意的,请制作 PR 的本地副本,创建一个新分支,并将其推送到同事的 repo。

您甚至可以将同事的一个远程分支机构拉入您自己的本地分支机构。也就是说,我将检查我的本地分支agenda,并尝试将我的同事的T2 分支拉入其中:

注意:坦白地说,我不知道我什么时候会用到它,因为这两个项目的提交历史是不相关的。如果你有想法,让我知道!

git checkout agenda
git pull **origin_medium** second_agenda --allow-unrelated-histories

使用场景 5 中的步骤可以解决一些冲突,但没有什么是我们不能解决的。

至理名言

  • 你永远做不够git fetchgit status——前者通知你远程回购的新进展,后者提醒你本地回购中未提交的文件。
  • 一旦你对你的代码做了一些重要的改变,就养成git commit的习惯。(不,文件- >保存不充分)
  • 如果远程跟踪被启用*, git push(和git pull)将从当前检出的**分支向远程上的相应分支推送(和拉取)变更。如果未启用,将会引发一个错误,您必须通过显式声明 repo 名称和您希望拉入/推送的分支名称来修复该错误。
    注意:我比大多数人更偏执,所以你会发现我总是明确地说出回购协议名称和分行名称。例如git push origin_name branch_name
    :要检查分支机构是否启用远程跟踪,请尝试git remote show origin。这将显示每个本地分支及其链接的远程分支。*

恭喜你走到这一步…

我真的相信您能够在日常生活中使用这些 Git 命令。对于那些想要学习更复杂的命令的人(为了有一天可能在你的工作场所出现的场景),我会说建立两个虚拟的 Github 帐户——你需要扮演两个合作者的角色——并开始练习你的疯狂的一生一次的场景。

一如既往,如果有更简单的方法来做我在本文中提到的一些事情,请让我知道。

直到下次:)

https://medium.com/swlh/how-i-would-explain-gans-from-scratch-to-a-5-year-old-part-1-ce6a6bccebbb

在协作工作空间中为数据科学家提供 Git 命令

原文:https://towardsdatascience.com/git-commands-for-data-scientists-in-a-collaborative-workspace-b528cfa5b235?source=collection_archive---------30-----------------------

简约 Git 生存指南——解释每个 Git 命令的基本原理和情况

是的,每个程序员最可怕的噩梦。虽然这个问题没有完美的答案,但我认为,与其靠蛮力记住每个 Git 命令,不如分享一个 Git 命令的紧凑列表每天使用的情况对其他数据伙伴来说可能更本能🙃

注:总分行=总分行。基本上,它是部署在服务器上的代码库。为了避免混淆,在本文中我将把它称为主要分支。

I. git 分支& git 结帐

作者截图|来自 (1) — (4) ,“git branch”在您的本地机器上创建主代码库的快照。要切换到这个分支,使用“git checkout”切换到这个分支。这从终端中表示的“(myBranch)”中可以明显看出。

(3) 如果您忘记了您创建的分支的名称,只需运行git branch列出您本地机器上当前已创建的分支。

(4) 相反,如果你创建了过多的冗余分支,命令git branch -d <your branch name>会删除你指定的一个分支。

二。git 添加和 git 提交

*git add <file 1> <file 2>
git commit -m <your commit message>*

当你对代码库进行后续修改时,明智的做法是记录下你所做的每一个重要的代码编辑。随着一个项目经历多次迭代,评审 git 提交给团队一个项目进展的清晰画面。另一方面,git add允许您指定将哪个(些)文件存放到部署中。如果您希望暂存所有变更*,请使用:***

*git add .*

而是让你的生活更轻松。

三。git rebase

*git rebase -i main*

长话短说,上面的命令旨在解决您与主分支的代码冲突

在协作环境中,期望至少有一个其他同事在同一个代码库工作。

回想一下,您正在处理代码库的快照。从你“分支”到你准备好部署你的代码的时候,其他的同事可能已经做了其他的改变,这些改变并没有反映在你的本地代码库中。因此,运行git rebase -i main将会运行你的代码库,通过你的团队所做的每一次代码提交,直到最后一次提交到最近部署中的主分支*。有两种可能的情况—***

场景(1) —代码完全自行解析,无需任何操作

这一部分不言自明。允许 Git 将您的代码提交与之前的代码提交自动合并。不幸的是,虽然 Git 相当聪明,但是当某些代码行与您当前的代码直接冲突时,我们更经常遇到:

场景(2)——发生代码冲突。进行手动更改的时间。

作者图片|运行 git rebase -i master 后的示例视图。|“I”代表交互,意味着 git 进入交互模式,这正是上面发生的情况。

虽然乍一看 Git 终端的输出似乎令人生畏,但是请注意这里输出的意图是 Git 用信号通知两件事情的方式— (1)它当前处于交互模式;(2)下面是您已经提交的代码列表 (需要解决)

继续键入 :x (冒号(:),然后是字母‘x’),并选择*【Enter/Return】*键,让 Git 完成它的工作。

在某个时刻,预期会显示以下类似的输出:

Image by Author | 对于冲突类型 I ,Git 将继续陈述在您从主分支分支出来之后被其他人修改的文件列表

在您的 IDE/文本编辑器上,对于冲突类型 I ,Git 将通过以下标记指定哪些代码行是直接冲突的:

作者插图| Git 输出上面的标记,以便将代码的替代版本与您的当前代码并排进行比较

说明:【头】***>>>>>>>*之间的代码行属于另一版本的代码行。要将这些与您的更改结合起来,请修改代码以保留先前的特性,同时实现您的新更改。

⚠非常重要:请运行应用程序至少一次,以确保代码得到解决,没有问题。如果你的手动修改破坏了代码,那么当你退出重定基础模式时,修复这个小故障(“调试”)会困难得多。

最后,完成更改后,继续运行:

*git rebase --continue*

根据需要解决的代码提交的数量,上述迭代将继续,直到所有的代码提交与团队中其他人的代码提交同步🤗

四。git 合并

*git checkout main
git merge <your branch name>*

所以,如果你已经走到了这一步,给自己一个鼓励,因为你刚刚度过了最艰难的阶段。在通过运行git checkout main切换到主分支后,git merge myBranch会覆盖主分支上的代码库,以与您的重新基础代码同步。

动词 (verb 的缩写)git 推送

要在主分支上部署最新的代码,请运行以下命令:

*git push origin main*

此时,我们刚刚用 Git 完成了一轮代码版本控制😀

用于代码检查的两个基本 Git 命令

命令 1 — git 状态

*git status*

***经验法则:*当您感到困惑时,为了了解大多数情况下您的代码版本的当前状态,您应该首先运行上面的命令。

作者截图|使用 git 状态的例子。该命令总结了代码版本控制的最新状况。

命令 2 — gitk

要获得直观的概述,请运行:

*gitk*

令人惊讶的是,这是社区中提到最少的 Git 命令之一。

作者截图|在终端中运行 gitk 后显示的 UI 弹出窗口

Git 命令结束—

仅供参考和免责声明:虽然这些是我个人认为至关重要的最低限度的 Git 命令,但没有完美的答案,所以请记住,这个列表仅够日常使用(强调“日常”)。

最终,这一切都是为了找到与您的设置最相关的 Git 流!

非常感谢您的阅读,如果您发现这篇文章对您有帮助,请关注我的媒体

***https://geek-cc.medium.com/membership

如果上面的 Git 命令不太适用,那么这里有一些其他的文章可供参考😀:

作者:Soner Yildirim

</8-must-have-git-commands-for-data-scientists-ee6564e4631d>

作者瓦什塔·谢尔博士:

***

每位数据科学家必备的 GIT

原文:https://towardsdatascience.com/git-essentials-for-every-data-scientist-f2c016dda692?source=collection_archive---------63-----------------------

提高数据科学工具包效用的简单流程

图片由regal have来自 Pixabay

版本控制简介

版本控制就是管理一个或多个参与者对文件和目录的更改。Git 是一个非常受欢迎的版本控制系统,我们将在本课程中介绍它。

版本控制有很多好处,特别是 Git。包括对您的项目所做的历史更改的视图,自动通知冲突的工作,其中两个人有效地编写冲突的代码行,允许许多个人之间的协作,这允许团队成长。

版本控制是软件工程的一个主要部分,并且正在慢慢地被数据科学团队所采用,在这些团队中,数据科学家通常使用他们自己的技术和工作流在孤岛中工作。虽然一定程度的自主性至关重要,但是如果没有版本控制的相关流程,数据科学家之间高度协作的能力将会面临巨大的扩展困难。

什么是存储库?

你可能已经听过这个术语很多次了…仓库。

用 Git 管理的所有数据科学项目都有两个主要组件。第一个是您所做的与文件和目录相关的所有工作..你的脚本、模型,以及它们存储的位置和方式;另一部分是 Git 保存的信息,用于维护一段时间内对项目所做的所有更改的记录。

当你把这些碎片加在一起时,你就有了自己的储存库,或者像酷孩子们所说的……回购;)

你需要知道的基本命令

Git 状态

Git 状态让您知道“暂存区”中有什么

临时区域是您放置将要更改的文件的地方。这实际上是你准备了各种各样的信,并把它们放在一个盒子里准备发送。你是想从这里拿走东西还是添加更多的东西取决于你,但是当你把它们交给邮递员的时候,就再也收不回来了。这些变化将会发生。Git status 将为您提供关于准备好进入 main 的文件的信息。

Git 添加

如果你跑了git status并且发现在你的集结地没有任何东西,不要担心!您首先需要将文件添加到临时区域。你可以用git add filename这样做。您在此处添加的任何文件名都将被移动到临时区域。这意味着驻留在给定文件中的所有更改将准备好在 repo 中推送或更新。

Git 差异

现在我们可以看到什么文件在带有git status的暂存区中,但是对于您希望看到发生了什么变化的事件呢?可以用所谓的git diffGit diff将返回原始文件和所有要做的更改之间的所有差异,分别表示为 a 和 b。

运行git diff时,你可能实际上运行的是git diff -r HEADHEAD将给出最近的提交,-r将与文件的特定版本进行比较。如果你想特别看到一个文件的变化,你可以在HEAD后面加上文件路径。大意是git diff -r HEAD filepath

Git 提交

一旦您将文件添加到您的暂存区域,您可以使用git commit将它们放入邮箱。请记住,“盒子”中的任何东西都是作为一个整体一起运输的。因此,如果您想撤销关于给定提交的任何操作,您必须回滚整个提交。

一个好的最佳实践是以良好的频率提交。

要记住的一件事是,你实际上不会只是运行git commit。您的命令实际上会像这样git commit -m "model updates"。这个-m是你的日志信息。这里的最佳实践是具体描述您对项目所做的更改。以后你会感谢自己的!

Git 日志

现在我要讲的最后一个命令是git log /

git log是你可以调出你的存储库的提交历史的地方。它提供了一些信息,如作者、提交日期和日志消息。

结论

我希望这是一个有用的 git 速成班!使用这些命令,让您自己和您的数据科学团队更有效地使用 Git!

在短短几分钟的时间里,你已经学会了:

  • 什么是版本控制
  • 知识库基础
  • 5 个关键的 git 命令,当你把你的工作发布到一个仓库时,你会想要拥有它们

祝数据科学快乐!

面向数据工程师的 Git

原文:https://towardsdatascience.com/git-for-data-engineers-a8b979d8b2ab?source=collection_archive---------10-----------------------

潘卡杰·帕特尔在 Unsplash 上的照片

数据工程

面向数据工程师、数据分析师和数据科学家的简短源代码控制指南

在以前的生活中,我有时会发现自己丢失了正在进行的工作,因为它只发生在我的本地。Excel 表格、SQL 查询、Python 脚本,我已经在某个时候丢失了这些东西。尽管我在 Subversion 的职业生涯一开始就知道源代码控制,但我并没有在我的数据分析和数据工程项目中使用它。

这些年来,我意识到 Git 的应用不仅仅局限于编写后端代码、前端代码,甚至是数据库相关的东西;您可以将 git 用于任何基于提交的协作工作空间。人们可以有效地使用 Git 来模拟电视剧或超级英雄电影的编剧室。

如果 Git 本质上可以用于任何基于文本的工作,为什么你看不到人们提交 SQL 查询、数据库注释、技术文档等。,在他们的 Git 仓库里?在本文中,我将讨论你(和我——如果我不遵循我的建议,我的文章将毫无用处)应该致力于 Git 的事情。它还将讨论与 Git 相关的摩擦点和问题,这些问题使得团队很难采用它。

对一切都使用 Git(除了秘密和密钥)

SQL —查询、DDL、DML、DCL 等。

首先,使用 Git 存储数据库对象的 DDL 表、视图、存储过程等等。从结构上讲,您的数据库在任何给定的时间点都应该是可重构的。如果您将一切都提交给 Git 存储库,您将确保可重构性。然而,这并不意味着您也必须将数据存储在 Git 中。数据库结构和数据应该是分开的。无论是否使用 DDL,您的数据都应该单独备份。

其次,如果您使用数据库运行查询来进行分析和报告,那么您应该将查询推送到 Git。这主要是问题发生的地方。能够访问数据库的业务、营销、运营、分析团队通常不太了解 Git。他们将查询存储在基于浏览器的查询编辑器、文本编辑器或 SQL 客户端中。通常,这些东西都不直接与 Git 回购相关。人们可以将 Oracle SQL Developer 等 SQL 客户端和 VSCode 等代码编辑器直接与数据库引擎连接,以确保顺利开发和将代码推入 Git。尽管如此,这通常是产生摩擦的原因。

工作流/编排者

在数据工程领域,如果没有工作流引擎来协调工作,什么也做不成。无论是 AWS Step 函数和 Lambda 函数、 AWS Glue job s、 Airflow DAG s 的组合,你都需要确保底层代码被提交给一个存储库。这有两个简单的原因。首先,您将需要与其他人合作完成您的工作,如果您丢失了本地副本,请进行备份。其次,您需要它易于部署。

CI/CD 管道

在上一节中,我谈到了 ETL 作业的易部署性。CI/CD 管道,顾名思义,确保代码的持续集成和部署。除了为 ETL 管道部署代码,数据库结构的改变等。,您还需要将管道代码提交给 Git。这意味着您需要存储 Jenkins、Bamboo 和其他 CI/CD 工具的管道配置,并将其提交给 Git。

有关管理 GitHub 组织或 GitLab 团队下的多个存储库和分支的更多信息,请阅读 Jenkins 的 Pipeline-as-Code 。许多其他基于云的管道工具也内置了这些特性。

数据基础设施(Terraform/CF)

我们需要向 Git 承诺的一个更新的东西是基础设施。基础设施即代码不再是未来的事情。企业使用 CloudFormation、HashiCrop Terraform、Pulumi 等。,在内部和云中部署基础架构。使用像 Chef、Puppet 和 Ansible 这样的工具进行配置管理在很多年前就已经很流行了,但是 IaC 还是一个相对较新的东西。

莫希特·戈亚尔关于 Terraform 和 Azure DevOps 的 7 部分系列的最后一部分对使用 Git 库提交和管理基础设施代码的主题有许多很好的见解。

注释和文档

最后,在协作环境中,更多的时候,信息分布在聊天群、电子邮件、群呼(无处可去),天知道还有哪里。它是杂乱无章的。你应该把笔记和文件集中起来。如果你使用的是像 Atlassian 的 Confluence 这样的集中式文档产品,那就没问题;另外,我发现在 Git 上编写文档很方便。

在将代码提交到您的分支之前,您倾向于在编写代码时编写更准确的信息。此外,当您在 Git 上编写文档时,文档感觉是代码的一部分,实际上也是,但是没有多少人认为是这样。如果你和一个团队一起工作,没有文档的代码不是一个好主意,尤其是一个没有 Shekher Kirani 所热衷的那些 10 倍工程师的的团队。

使用 Git 进行数据工程的经验法则

既然我们已经了解了向存储库提交什么,我们需要了解一些要遵循的基本规则和要避免的反模式。

提交代码,而不是数据

一个前同事正在做一个项目。尽管他作为数据分析师非常有经验,但他从未向 Git 提交过代码。因为笔记本电脑崩溃或操作系统损坏而丢失工作,这让他开始使用 Git。一旦他开始使用 Git,他立刻意识到了它的好处。他第一次向 Git 提交代码时,也在存储库中提交了巨大的 CSV 文件。显然,很多人都会犯这个错误。

数据文件不应该提交给 Git,原因有三

  • 文件会变得非常非常大——例如 GitHub 对大于 50 MB 的文件有规定。这些规则是经过深思熟虑的。对于大多数用例来说,这是有意义的。记住,一个 50 MB 的文本文件大概相当于一百万行代码。
  • **Git 是为了存储代码,而不是数据——**不在 Git 中存储数据背后的想法很简单——你应该隔离代码和数据。只要数据集符合特定的模式并遵循格式化和数据类型化的预期,代码就应该不管数据集中的确切数据如何都能正常工作。
  • 数据可能包含 PII(个人身份信息)数据— 尽管 Git 存储代码是安全的,但了解许多开发人员、测试人员、数据工程师和数据分析师都可以访问代码库是至关重要的。如果您提交包含 PII 数据的哪怕是最小的文件,他们都能够看到,从而违反了数据隐私和治理规则。

永远不要保守秘密

将秘密提交给 Git 源于一个做**git add .**的坏习惯,它甚至将您的本地开发文件提交给 Git——这些文件中存储了 API 密钥、密码和用于开发目的的秘密。请务必将此类文件放在**.gitignore**中。

如果你没有制衡机制来防止这种情况发生,很有可能有人会这么做。您可以使用各种方法从 Git 存储库中移除敏感数据。像**git filter-branch****bfg repo-cleaner**这样的工具是一些受欢迎的选择。最好不要将凭证存储在文件中,即使是出于开发目的。您可以使用像 HashiCorp Vault、AWS Secrets Manager 和其他这样的工具来标记和回收机密。如果你想研究企业工具,有许多选项,如 Honeybadger 、夜幕和 GitGuardian ,它们可以帮助你防止 Git 灾难。

遵循分支策略

我之前写过关于菜鸟 Git 的错误。不遵循分支策略就是其中一个错误。当你在一个团队中工作时,你需要确定一个将代码拉入、开发、合并和推进到你的存储库中的过程。这就是代码升级如何从较低的环境到较高的环境发生(读取开发→测试,测试→生产前,生产前→生产,等等)。).

有效地使用 Git 是一项技能,您需要在前进的过程中不断努力。从最普通的拉取、推送提交和合并,您还应该了解精选、过滤分支、恢复等等。

离别的思绪

一直有人问我,如果想成为工程师,应该学习哪些技术,了解哪些概念。我通常的回答是,一个人必须真正了解 SQL 和一种用于编写脚本的编程语言(最好是 Python)。工具和技术的清单不断增加。下一次有人向我寻求建议时,在继续告诉他们学习 Airflow 或 Databricks 或 Kubernetes 之前,我一定会让他们先在 Git 中入门(**git init**——我是多么有趣,这几乎令人难过)。

如果你有兴趣阅读更多我的作品,请访问我的写作作品集。如果你想讨论数据库、仓库、基础设施或云计算,请通过 LinkedIn 联系我。

GitHub Copilot——新一代人工智能程序员

原文:https://towardsdatascience.com/github-copilot-a-new-generation-of-ai-programmers-327e3c7ef3ae?source=collection_archive---------14-----------------------

人工智能

GitHub、微软、OpenAI 都达到了一个新的里程碑。

妮可·沃尔夫在 Unsplash 上的照片

当 OpenAI 去年发布 GPT-3 时,人们对它从自然语言提示中生成代码的能力感到惊讶。 Sharif Shameem 和其他人兴奋地分享了他们的发现,很快炒作和担忧就一飞冲天了。但是 GPT 3 号远不是一个伟大的程序员。它能理解英文文本并将其转换成一段代码,这是一个值得注意的壮举,但它的表现平平。

OpenAI 和微软(现在资助他们的项目)在 GPT-3 的编码能力中看到了一个非常有前途的商业产品,并很快开始开发另一种语言模型;一个程序员 AI。新的模式将权衡,关于 GPT-3,一般语言技能的编码能力。这个“GPT-3 的后代”,正如 Greg Brockman 所说,被称为 OpenAI Codex,它是该领域最新突破背后的人工智能:GitHub Copilot。

两天前,OpenAI、GitHub 及其母公司微软展示了 GitHub Copilot ,这是一款由 OpenAI Codex 提供支持的人工智能工具,它可以作为一对程序员,帮助人类开发人员编写代码。这是未来几年将变得无处不在的新一代人工智能程序员中的第一个,也是自 GPT-3 以来该领域最重要的里程碑。这将为软件行业的彻底变革打开大门,但这些变革对劳动力有利或有害的程度仍是未知的。

GitHub Copilot——人工智能配对程序员

事实真相

GitHub Copilot(从现在开始 Copilot)是一个人工智能工具——目前正在技术评审中——它可以在程序员编写代码时向他们提出建议。微软已经在 Visual Studio 代码中实现了它,并将它集成到商业 VS 产品中。目前,它只对少数开发者开放(你可以试试你的运气这里)。

副驾驶并非同类产品中的首创;Tabnine 和 Kite 是两个涵盖相同功能的流行工具。然而,Copilot 之所以脱颖而出,是因为它由 Codex 提供支持,Codex 是 GPT-3 的后代,它提供了比其他助手更深入的背景理解。Codex 类似于 GPT-3,有一个重要的区别:它接受了来自 GitHub 知识库和其他网站的大量公开编码数据的训练。

Codex 是一种编程语言模型,OpenAI 将在今年夏天将其集成到他们的 API 中。它在这方面的能力大大超过了 GPT-3——或 GPT-J 。正如我在之前的一篇文章中所论述的,类似 GPT 的模型似乎在他们专注于一项任务时释放出一种潜在的力量。GPT-3,万能的杰克,在许多任务上是惊人的。相比之下,Codex 是编码大师。

但是 Codex 和 Copilot 都不是完美的。考虑到那些预先测试它的人的证词,这个工具工作得很好。但是,就像所有由人类编写的代码一样,副驾驶的代码应该经过“测试、审查和审核”GitHub 开发人员创建了安全机制来为用户提供最佳体验,但系统“有时可能会产生不希望的输出,包括有偏见的、歧视性的、辱骂性的或攻击性的输出。”Copilot 代码甚至可能无法编译,因为它不会测试输出的代码。简而言之,这是一种新工具的早期版本;它有缺陷,但它的承诺大大超过这些缺陷。

它的作用

在 GitHub 页面上,有 Copilot 惊人表现的例子。它可以完成代码行或编写完整的函数,将描述性注释转换成代码,自动填充重复的代码,或者为您的方法创建单元测试。它可以接受当前行以上的几百行作为输入,但是有一个重要的限制:不能从其他文件中输入代码。

它与 Python、JavaScript、TypeScript、Ruby 和 Go 配合得最好,但它“理解几十种语言”。但是,因为它有时会失败,所以在探索新的库或用未知的编程语言编写时,它可能更有用。否则,审阅 Copilot 的代码可能比自己编写代码要花更多的时间。

Copilot 基于一种类似于 GPT-3 的语言模型,所以它已经适应了它被训练的代码。但是,随着你使用它,它开始“理解”你的风格并适应你。而如果你不喜欢第一个建议,你可以要求它提供 top-k 的解决方案。

Copilot 的重要含义

语言模型的力量

GPT-2,GPT-3,开关变压器,LaMDA,MUM,悟道 2.0…预先训练的语言模型现在是人工智能的蛋糕,该领域的每个主要参与者都在争夺最大的份额。原因是这些模型工作得非常好。GPT-3 是最受欢迎的,这是理所当然的。当 OpenAI 发布 GPT-3 API 时,它让世界得以一窥它的威力,并且它生效了。GPT 3 号如此强大,性能如此之好,人们甚至敢称它为 AGI——其实不然。

然而,因为 GPT-3 是一种通用语言模型,所以可以合理地假设,如果做好充分准备,它可以提高在特定任务中的性能。基线 GPT-3 可以被描绘成一个万事通,而其专业版本将是他们的任务的主人。DALL E 是这种可能性的第一个暗示。OpenAI 在文本-图像对上训练该系统,这使得 DALL E 能够从字幕和更多内容中生成图像,在视觉创意方面表现出色。 GPT-J ,一个比 GPT-3 小 30 倍的类似系统,可以生成更好的代码,因为它在 GitHub 和 StackExchange 数据上进行了大量训练。 PALMS ,一种减少 GPT-3 偏差的方法,进一步加强了这个假设。研究人员通过在一个小型精选数据集上进行微调,显著改善了 GPT-3 的行为。

现在,Copilot 与 Codex 合作,已经明确证明了这一想法:语言模型可以专门化,成为它们的贸易大师。Codex 是编程大师,那么一个超级强大的专业语言模型还能掌握哪些领域呢?他们能掌握逻辑或数学等其他形式语言吗?他们能掌握 GPT 3 号的每一项功能吗?一个语言模型能写出莎士比亚、塞万提斯或托尔斯泰水平的小说吗?它能成为今年夏天最热门的歌曲吗?什么是可能的还不清楚。清楚的是,我们还没有发现它们的极限。

编码的未来

当 GPT-3 发布时,许多人看到了编码终结的另一个垫脚石;无代码接管的速度比我们想象的要快。现在,Copilot 将担忧提升到了前所未有的程度。顾名思义,它被设计成一个合作伙伴。GitHub 说“你是飞行员”,但是我们怎么能确定这在未来不会改变呢?

它的创造者希望 Copilot“让现有的工程师更有效率,减少手动任务,帮助他们专注于有趣的工作。”然而,在人工智能也能更快、更便宜、更准确地完成这项“有趣的工作”之前,还需要多少时间呢?GitHub 首席执行官 Nat Friedman 说“我们每天解决的问题可能会改变。但总会有问题需要人类去解决,”但也许不是同一批人会准备去解决新的问题。

未来是不可预测的,今天可能会出现两种情况:要么我们与人工智能建立共生关系,为每个人找到一席之地,要么人工智能将接管许多工作。即使它从未达到完美,Copilot 或它的继任者也可以消除程序员的必要性,只留下少数人来“测试、审查和审核”AI 的代码。我们只能希望,如果发生工作岗位的转移或替代,决策者将做出适当的反应,并为受影响的人提供安全网。

有用不可靠?

如果 Copilot 不是 100%可靠,它有用吗?到什么程度,在哪些情况下不使用比较好?一个不专业的程序员能利用它吗?或者它更适合专业程序员,他们会花更多的时间来检查代码而不是自己写代码。副驾驶的不可靠性引发了许多与实用性相关的问题。

乔尔·斯波尔斯基(Joel Spolsky)的一句名言现在派上了用场:“阅读代码比编写代码更难。”一个没有经验的程序员可能不知道 Copilot 代码的问题,而一个经验丰富的程序员更喜欢写代码,而不是阅读 Copilot 生成的代码。使用 Copilot 显然是值得的情况很少:一个有经验的程序员想要尝试一个新的库/语言/框架,或者想要基于手工制作的方法编写单元测试(尽管那些也需要被审查)。另一种情况是一个没有经验的程序员开始学习。

然而,还有比 Copilot 写低质量代码更大的问题。来自 GitHub 的常见问题:“世界上有许多公共代码存在不安全的编码模式、错误或对过时 API 或习惯用法的引用。当 GitHub Copilot 基于这些数据合成代码建议时,它也可以合成包含这些不良模式的代码。”一个值得考虑的问题是,Copilot 会减少还是增加这些问题的数量。

法律问题

*我不是律师,也绝对不是美国法律专家,*但是 Nat Friedman 开设的 黑客新闻 帖子提出了关于知识产权、许可证和版权侵权的重要问题。GitHub 在 Copilot 常见问题中表示,“大约 0.1%的时间”Copilot 的建议是“逐字来自训练集”。这意味着 Copilot 用户可能会采纳一个建议,该建议包含与项目目的相冲突的受版权保护的代码。这就提出了一个重要的问题:在这种情况下,谁应该承担责任,用户,GitHub/微软,还是拥有该项目的公司?

他们还提到“您应对您在 GitHub Copilot 的帮助下创建的内容负责。我们建议您像对待自己编写的任何代码一样,仔细测试、审查和审核代码。”这是否意味着,如果我们使用了 StackOverflow 提出的 Copilot 建议,而该建议恰好受到 GPL 许可,我们就要对侵权行为负责?怎么才能知道 Copilot 是否抄袭了一大块我们用不到的代码?公司会允许员工使用 Copilot 吗?还是会因为禁止从 StackOverflow 复制代码的原因而禁止使用 Copilot?

另一位用户指出,如果 GitHub 没有将 Copilot 培训限制在“一个合理的许可白名单(mit、BSD、Apache 等)”中,那么使用该工具从事“重要/创收”项目将是一个风险。没有信息表明这是真的还是假的,因此上述问题似乎是合理的。Nat Friedman 表示,关于知识产权和人工智能的辩论将在未来几年内发生,但就目前而言,使用 Copilot 可能会产生更多问题,而不是解决方案。

结论

GitHub Copilot 注定要改变全世界很多程序员的日常。尽管我强调了这些问题,但这项技术是一个重要的里程碑,将引领未来走向无代码,这是微软多年来一直追求的目标。

副驾驶感觉像一个拐点,没有人知道事件将如何从这里展开。程序员几年后会开始失业吗?我们会设法找到一个有益的飞行员-副驾驶协同作用吗?它会提供这样一种优势,以至于企业要么不得不适应它,要么就死掉吗?程序员会不得不以职业生存换取隐私吗?

自周二以来,出现了许多问题,还会有更多的问题出现。目前,答案还需要等待。GitHub Copilot 启动。让我们睁大眼睛,看看它将把我们带向何方。

跟我一起旅行到未来 了解更多关于人工智能、哲学和认知科学的内容!还有,可以在评论里随意提问或者在LinkedIn或者Twitter!:)

推荐阅读

GitHub 副驾驶。软件工程行业的兴衰故事

原文:https://towardsdatascience.com/github-copilot-a-rise-and-fall-story-for-the-software-engineering-industry-524c83694136?source=collection_archive---------10-----------------------

GitHub 和 OpenAI 已经宣布了 Copilot,这是一个人工智能助手,可以通过为他们的软件解决方案生成或自动完成代码来协助编码人员。这对软件工程行业意味着什么?

qubodup 的【编程代码宏】由CC 2.0授权

2021 年 6 月中旬,OpenAI 的首席执行官萨姆·奥尔特曼(Sam Altman)发布了一条推文,他在推文中声称,人工智能将对电脑前的工作产生更大的影响,比现实世界中的工作快得多:

山姆·奥特曼关于人工智能在计算机辅助工作中的破坏的推文

17 天之后,GitHub 和 OpenAI 宣布了与那条推文相关的副驾驶的技术预览。Copilot 是一个人工智能驱动的代码助手,它使用 OpenAI 的新解决方案 Codex,此前它接受了从公开来源(包括 GitHub 的公共资源库)中选择的英语文本和源代码的训练。

Copilot 对软件工程行业的颠覆性有多大?一年前,GPT-3 宣布后,我写了一篇介绍 OpeanAI 最新自然语言处理模型的文章,其中我分析了一些测试人员创建的第一批应用程序,这些应用程序允许基于 GPT-3 的语言能力生成代码。当时,我问自己是不是到了恐慌的时候了,对此我回答如下:

作为一个在 IT 服务市场工作的人,当看到所有这些令人难以置信的基于 GPT 3 的应用程序时,首先想到的问题很明显:软件工程师会因为像这样的人工智能改进而失业吗?这里我首先想到的是,软件工程和写代码是不一样的。软件工程是一项意义深远的任务,它意味着解决问题、创造性,当然,还包括编写实际解决问题的代码。也就是说,我真的认为,由于启动,这将对我们通过软件解决问题的方式产生影响。

我在一年后肯定了袖手旁观的说法,同时我也认为 Copilot 将对软件工程行业产生深远的影响。我预计,这种颠覆会加速一些起伏:

上升中

  • 软件架构:现在,软件架构师的角色比以往任何时候都更加重要,以确保软件工程原则:可靠性、可用性、可维护性、性能(RAMP)。虽然生成有效解决特定问题的代码几乎是零成本问题,但如果没有强大的软件架构原则,正确设计所有代码如何在一个通用和一致的软件架构下组合在一起将变得更加复杂。
  • **漏洞发现工具:**对高质量数据的培训将是 Copilot 这样的工具被大规模采用的关键。这就是为什么像亚马逊这样的公司已经押注于 Bug 修正全球挑战( BugBust )来改善他们的智能软件开发助理( CodeGuru )的表现。
  • **Lowcode/ Nocode —企业架构集成:**我预计 Copilot 和其他 Lowcode 和 Nocode 工具都将保持快速发展,这强化了如何集成和正确维护这些工具生成的软件代码的问题。Copilot 或任何其他类似的工具如何确保稍微改变功能或技术需求不会导致生成的代码发生巨大变化?请记住,Copilot(或任何其他类似的模型)是在海量数据上训练的,因此该模型的未来版本可能会生成完全不同的最终代码。在这种情况下,这种工具集成到可扩展企业架构中的可能性将成为无代码/低代码供应商的明显竞争优势。当被理解为代码生成工具的特定训练时,这种集成将考虑到用于编码目的的灵活性和成本降低的益处,同时确保生成的代码与预定义的软件架构及其原理一致。
  • 软件启动/提示工程:正如我在 GPT-3 的文章中提到的,启动的概念将是使 Copilot 这样的技术有用的关键,为模型提供我们想要解决的问题的良好定义,等等。一些作者已经写了关于“ prompt engineering ”的概念,作为一种通过人工智能解决问题的新方法。同样,一个工程过程仍然需要比目前 Copilot 所展示的更多的东西,但它肯定会改变我们作为它的一部分处理编码的方式。
  • ****软件许可管理:Copilot 发布后, Hackernews 开始充斥着关于使用 Copilot 或类似工具时如何管理软件许可的评论。我还预计,专门从事软件许可模式的知识产权律师将会越来越多,来处理这个问题。

hackernews 上的 Copilot 线程,提到 GPL 软件的潜在含义

在秋天

  • 软件编码员和测试员:为了寻找(我会说是可疑的)效率,许多公司将编程任务外包/外包给缺乏软件工程技能和商业理解的编码员。正如我们所提到的,通过正确定义业务和技术需求,快速工程将成为基于 Copilot 生成高质量代码的关键。因此,没有深厚业务和技术能力的编码人员和测试人员将很难为软件工程过程增加价值(正如解决方案本身的名称所暗示的那样,是副驾驶)。

根据这第一个兴衰列表,像 Copilot 这样的工具似乎将在软件开发行业创造/推动新的角色,同时破坏那些不会给软件创造过程增加真正价值的角色。你有什么想法?你会将哪些角色添加到这个兴衰列表中?

如果你喜欢阅读这篇文章,请 考虑成为会员 以便在支持我和媒体上的其他作者的同时,获得上的所有故事。

面向数据科学家的 GitHub 桌面

原文:https://towardsdatascience.com/github-desktop-for-data-scientists-b9d8a3afc5ea?source=collection_archive---------18-----------------------

实践教程,教程|版本控制| GitHub 桌面

没有命令行中的版本控制可怕

放松,你不必在 Unsplash 上使用命令行|照片由丹尼斯·范达伦

版本控制对于代码协作、与他人共享代码、能够查看代码的旧版本,甚至自动部署代码都很重要。一开始可能会有点混乱,但是非常值得花时间,特别是如果您在开放源代码领域工作或者在一个经常使用项目版本控制的团队中工作。以下是一些值得使用的最大特性:

  • 存储带有注释的文件更改历史
  • 组织多个用户同时编辑同一个项目
  • 简化代码审查程序
  • 自动化工作流以报告问题、请求改进和部署代码

版本控制功能

版本控制的主要特性之一是存储库中每个文件的文件更改历史。这可以作为每个文件的变更日志,因此总是可以看到过去任何时候运行的代码。每当有人更新一个文件并将新版本推送到存储库时,他们都必须添加一个简短的注释。在一个完美的世界中,这详细描述了变化是什么以及为什么要进行这些变化。如果有任何关于为什么更改或为什么更改的问题,负责人将在提交中被标记,以及他们提供的附加信息。

版本控制的另一个特性是创建分支的能力。分支是保持独立的代码的新版本。这有助于对代码进行修改和测试,因为它不会改变主分支,那里是最新的工作版本。不同的用户也可以使用分支来同时处理不同的代码或特性。当这些分支准备好时,可以合并回主分支,并且在合并时有一个过程来协调它们之间的差异。

在与团队合作时,代码审查是最佳实践。一个人可能在一个新的分支中做一个新特性的所有工作,但是在盲目地将其合并到主分支之前,应该由团队进行评审。当创建一个 pull 请求来将代码移动到主分支时,它还会启动一个讨论,团队成员可以在代码合并到主分支之前讨论代码并请求更改。这个过程应该有助于改进投入生产的代码,以防止错误和中断,提高代码的效率,甚至使代码符合格式化代码的标准。

使用 GitHub 进行版本控制的最后一个值得注意的好处是它提供的自动化选项。如果有一个标准的代码审查清单,它可以作为一个模板被添加,当一个拉请求被创建时,它将是可用的,当审查任务被完成时,它可以被填写。当人们创建问题时,也可以使用模板,以便他们在创建问题时记住需要输入的所有详细信息。GitHub 还提供了支持自动化的动作。这些可以由不同的事件触发,比如将代码合并到主分支中。一个动作可以运行单元测试,构建/编译包组件,甚至将代码部署到生产环境中。

版本控制风格

有几个大名鼎鼎的版本控制你可能听说过。一些最流行的是 Git 和 GitHub。 Git 是版本控制的底层技术, GitHub 是简化版本控制工作流程的软件。

Git 可以在本地使用,不需要任何外部存储库。您可以在计算机硬盘上执行所有版本控制任务。本地 Git 存储库非常适合个人项目,或者当您还没有准备好与整个团队共享您的代码,但是仍然想要版本控制的好处时。

GitHub 网站是一个存储代码的仓库。GitHub 网站上托管了很多开源项目,比如 Python 和 R 包。对于公共存储库,任何人都可以查看修订历史、包的问题以及与之相关的文档。

要连接到 GitHub 网站上的存储库,我们可以使用 Git 或 GitHub Desktop。对于那些喜欢命令行界面(CLI)的人来说, Rebecca Vickery 有一篇关于使用 Git CLI 进行数据科学的精彩文章。那么你为什么要继续读书呢?命令行可能会令人生畏。想要一个图形用户界面(GUI)来管理您的版本控制并没有错。GitHub Desktop 为您的存储库提供了一个清晰简单的界面。

GitHub 桌面流程

虽然每个人对于他们的存储库都有一个稍微不同的流程,但是有一些通用的步骤来修改 GitHub 上的代码:

  1. 创建分支
  2. 添加提交
  3. 创建新的拉式请求
  4. 完成代码审查
  5. 合并拉取请求

创建一个分支会复制当前的生产代码。开发人员将对文件进行更改,将任何更改提交到新的分支。接下来,pull 请求将打开讨论,将新分支的变更添加到生产代码中,通常是在 master 或 main 分支中。代码评审者可以添加注释,并请求对拉请求所做的更改进行澄清。一旦审查完成并做出任何必要的更改,就可以将拉请求合并到主分支或主要分支并关闭。

让我们更详细地浏览这些步骤,看看如何使用 GitHub Desktop 完成每一步。

创建分支(将新代码与旧代码分开)

要进行更改,首先创建一个新分支。如果您拥有对存储库的完全访问权限,那么您可以简单地在存储库的 GitHub 站点上创建一个新的分支。

1a。点击分支:主

作者图片

2a。在文本框中键入新分支的名称。为了组织有序,您的组织可能需要考虑一些分支命名约定

作者图片

3a。点击创建分支

作者图片

现在将选择新的分支。

作者图片

如果您没有对存储库的完全访问权,这在公共项目中很常见,那么您将不得不分叉存储库。新分支和分叉是同义词。fork 将在一个新的存储库中创建,而不是与生产代码相同的存储库,通常在您的个人配置文件下。要分叉:

1b。在右上角,单击 Fork

作者图片

2b。等待文件复制

作者图片

3b。将选择新的分叉

作者图片

添加提交(增强代码/添加特性)

要提交代码,您需要将存储库克隆到您的本地计算机上。在将更新发送回存储库之前,这将为您复制要处理的代码。要将存储库克隆到您的本地计算机,请执行以下操作:

单击克隆或下载。

作者图片

点击用 GitHub 桌面打开。

作者图片

如果你没有 GitHub 桌面,点击下载 GitHub 桌面。

作者图片

GitHub desktop 会询问将存储库克隆到本地机器的哪个位置。这是本地路径字段。

作者图片

单击分支并选择新创建的分支。这将使用该分支上的任何更新来更新本地机器上的文件,并使其成为要添加提交的活动分支。

作者图片

要进行更改,请打开您在克隆时选择的目录,并像往常一样使用文本编辑器或集成开发环境(IDE)进行更改。保存文件。

返回 GitHub 桌面。GitHub Desktop 会不断扫描存储库文件夹树,并会看到您所做的任何更改。这些更改将显示在左侧窗格中。右窗格将预览对所选文件的更改(某些文件类型不会预览)。

作者图片

每当您做出一组相关的变更时,将这些变更提交到您的存储库中。记得在提交中添加注释,这样人们就可以很容易地识别出什么被改变了。上面的文本框用于快速描述,但是如果您有更多关于提交的注释,请将它们放在更大的描述文本框中。

做出更改并添加注释后,提交更改。

作者图片

提交更改只会将它们保存在本地文件中。要将更改推回 GitHub 服务器,请点按“推回原点”。如果有尚未推回服务器的提交,右窗格中将出现一条消息,说明将 xx 提交推送到源远程。origin 只是存储库被克隆的地方的名称。

作者图片

打开拉取请求

导航到 GitHub 服务器上的存储库。确保你在正确的分支上。如果您在原始存储库上创建了一个新分支,请导航到那里。如果您必须派生存储库,请在您的个人资料中导航到该存储库。

拉动请求选项卡上,点击新拉动请求

作者图片

选择新的分支作为要比较的分支,点击创建拉式请求。在我们的例子中,pull 请求会自动填充我们的 commit 注释。

作者图片

代码审查

代码审查有助于确保我们添加或更改的代码是正确的,并且已经过多人的审查和批准。无论您是否有权访问存储库,您都应该让审阅者检查变更。如果有任何问题,作为一个团队检查它们。

“拉”请求显示在存储库的“拉”请求选项卡下。每个“拉”请求都有一个“对话”、“提交”和“文件已更改”选项卡。

对话是人们可以添加关于代码的问题或评论的地方。您可以格式化您的评论,并在您的评论中标记人物和问题。

提交显示拉请求中的所有提交和注释

“更改的文件”显示了哪些文件被更改、添加或删除,并对可用的代码进行了逐行比较

作者图片

合并拉取请求

在我的例子中,当我在新的分支上工作时,我的主分支被改变了。这就是为什么有消息说有冲突要解决。单击解决冲突按钮将打开一个编辑器。它将显示来自每个分支的文件版本,允许您删除一个并保留另一个,或者创建两者的某个版本。

作者图片

在这种情况下,主分支的版本是正确的。可以删除来自其他分支和分隔符的更改。冲突可被标记为已解决,并提交给合并。

作者图片

随着代码审查和冲突的消除,拉请求可以被合并。这里将再次出现一个选项,对合并完成的内容给出一个注释。合并后,代码将成为主分支或主分支的一部分!

作者图片

现在你知道如何使用 GitHub 和 GitHub Desktop 完成最基本的版本控制任务了!

https://realdrewdata.medium.com/membership

进一步阅读

如何为 Python 数据科学项目创建 GitHub 存储库

原文:https://towardsdatascience.com/github-i-getting-started-with-github-272255c5f11f?source=collection_archive---------16-----------------------

了解如何使用 GitHub 存储库来共享和协作数据科学项目

克里斯蒂娜·莫里洛在 Pexels 上的照片

一、什么是 Git?

Git 是一个 版本控制系统——一个软件工具,允许开发者在一种特殊的数据库中跟踪和管理代码的变化。自从 2005 年由 Linus Torvalds 开发以来,Git 已经成为使用最广泛的版本控制系统之一。GitHub是一个 代码库托管服务 ,你可以免费使用它来分享和协作代码。

在协作项目中使用 GitHub 的一些优势是:

  1. 当代码中断时,开发人员可以返回到代码的早期版本,以识别孤立分支中的问题,从而最大限度地减少对项目其他方面的干扰。
  2. 独立的分支允许团队成员处理同一项目的不同方面,从而在不影响其他团队的情况下进行更改。
  3. 当变更完成时,它们可以被合并到主分支中。任何有冲突的变更都会被标记出来,以便能够解决。

GitHub 会记录您向 GitHub 贡献(或上传)文件的频率。这是向潜在雇主展示你对编程认真的好方法。

二。在 GitHub 上创建项目存储库

  1. 如果你是从零开始,看看用 Python 进行数据科学项目的一般设置、虚拟环境 I:用自制软件安装 Pyenv】和 Jupyter 笔记本 I:Jupyter 笔记本入门。正确的数据科学项目设置对于本教程非常重要。
  2. 确保您遵循了本教程前四部分中概述的步骤,并且您已经:
  • 创建了项目文件夹
  • 激活了项目文件夹中的新虚拟环境

3.导航到 GitHub.com。如果您没有帐户,请创建一个帐户。前往右上角靠近您个人资料图片的下拉菜单中的您的存储库选项卡

突出显示您的存储库的 GitHub 配置文件屏幕

4.在那里,点击右上角的绿色按钮,上面写着新**。**

新按钮在右上角。

5.输入唯一的存储库名称和简短描述。如果你愿意,你可以以后再改。存储库的命名约定建议使用由破折号分隔的小写名称(例如“my-project”)是最好的。将存储库设置为公共或私有。

注意:如果你正在跟随 教程中的数据,你现在可以将这个项目命名为“metal-project”并带有“日教程数据仓库”的描述。

创建具有名称、描述和隐私设置的新存储库。

6.当您到达页面底部时,不要选择“使用“初始化此存储库”部分中的任何项目。点击创建存储库

完成创建您的存储库。

7.将出现一个新屏幕,上面有一些说明。下面,我将提供相同的说明,并为初学者提供一些额外的细节。

GitHub.com 上的说明截图

三。在本地初始化您的存储库

既然您已经在 GitHub.com 上创建了一个存储库,那么是时候通过将您在 GitHub.com 上创建的存储库初始化到您的项目文件夹中来将您的项目文件夹与您的存储库同步了。

1.打开终端并输入:

$ cd my-project

2.进入该页面后,您可以通过输入以下内容来初始化存储库(确保替换您的用户名):

git remote add origin https://github.com/username/my-project.git
git branch -M main
git push -u origin main

现在,存储库在您的本地项目文件夹中初始化。这就是我们将本地文件连接到在线存储库的方式。一旦连接上,我们就可以使用命令来推送(或上传)我们项目的新版本。GitHub 将跟踪变化和不同的版本。

动词 (verb 的缩写)下一步是什么?

  • 在使用 Python 进行数据科学项目的一般设置中,您通过安装 CLT、Xcode、Hombrew、Python 和 Pip 安装了入门所需的基础包。
  • 在Virtual Environments I:Installing Pyenv with home brew中,您学习了如何在 Mac OS Big Sur 上使用 Pyenv、Virtualenv 和 Pip 为您的 Python 数据科学项目创建虚拟环境。
  • 在Jupyter Notebooks I:Jupyter Notebooks Getting Started with Jupyter Notebooks中,您通过创建一个内核规范将 Jupyter Notebooks 链接到您项目的虚拟环境。
  • 最后,在本教程中,您在 GitHub.com 上创建了一个 GitHub 存储库,并在本地初始化了该存储库(在您自己的计算机上)。

在下一节“Python 初学者数据科学基础”中,您将创建一个 Jupyter 笔记本来记录您的项目,我将向您展示如何通过将这个笔记本推送到 GitHub 存储库来进行第一次提交。

感谢阅读!

👩🏻‍💻克里斯汀·伊根◇ 克里斯汀-伊根. xyz

GitHub 和预训练模型:锁眼视图

原文:https://towardsdatascience.com/github-pre-trained-model-a-keyhole-view-643c6526bc13?source=collection_archive---------44-----------------------

GitHub 包含预先训练的模型,这些模型可能包含固有的偏见,模型记分卡的缺乏将有助于放大用户对这些回购的偏见。

设置上下文

GitHub 是一个著名的软件代码及其版本控制的互联网托管平台。GitHub 使其 5600 万用户(组织和个人)能够在平台上创建他们的作品的存储库,以便于访问、版本控制以及在有或没有许可的情况下共享(Apache License 2.0)。对于研究人员来说,GitHub 是一个指向他们工作的资源目录。此外,对于开源其工作/解决方案的大型组织来说,GitHub 使其可以被社区访问。

GitHub 上有超过 1.9 亿个公共知识库。这些存储库包含源代码、文档、API、数据集和其他与源代码相关的元数据信息。GitHub 允许用户派生(创建存储库的副本)、提交(更改历史)和发出拉请求(原始存储库的更改通知)。这使得能够重用平台上的现有内容。在机器学习的情况下,有超过 331,000 个储存库包含 ML 模型、它们的源数据、结果、度量和与它们相关的分析。

来源:等距的人与技术自由矢量( Freepik )工作

迁移学习和内在挑战

GitHub 仍然是支持迁移学习和利用现有模型或源代码的最大平台。迁移学习是利用从解决一个问题到解决另一个相似或不同问题的知识的过程。这有助于通过协作和开源有效地优化现有内容。虽然这种优化放大了可能性,但它也放大了源代码中的错误和偏见,这可能会伤害人和组织。

例如,GitGuardian 在其报告(2021 年 GitHub 上的秘密蔓延状态)中提到,包括 API 密钥、凭证和敏感信息在内的信息都在 GitHub 的公共存储库中。这使得存储库容易受到攻击(不仅是网络攻击,还有数据中毒攻击),从而对组织和个人造成伤害(此处)。

类似地,偏见可以存在于公共知识库上的自然语言处理模型(单词嵌入)中的预先存在的偏见(潜在的或其他的)、技术偏见(特征选择和权衡决策)和紧急偏见(设计和基础事实之间的价值或知识库的不匹配)的性质中。这些模型是在公共数据集上训练的,也可能造成伤害。研究表明,模型或公共数据集中的潜在偏见导致了性别歧视(此处)。值得注意的是,数据科学家做出的优化选择和权衡决策也可能导致模型中的偏差。根据上下文和模型部署的方式,从原始存储库中派生或改编的模型也可能会导致或有时会放大危害的程度。

底层根源

潜在的问题是,GitHub 作为一个存储库包含的源代码或模型在被带到平台上之前没有经过验证。此外,GitHub 的方法是使社区能够在各自的存储库上互相审查、评论、使用或共享 bug 或挑战(称为“问题”)。然而,在社区中对潜在问题的认识不一致的情况下(特别是在新兴研究领域),这种方法可能是不够的。此外,GitHub 并不强制要求在用户入职、声明流程或存储库创建流程中签署行为准则(仅作为建议)。

GitHub 社区指南提供了一个机会,通过表单提交流程,在审核存储库的同时报告滥用和报告内容。此类提交的当前选项包括“我要报告有害代码,如恶意软件、网络钓鱼或加密货币滥用”。然而,鉴于机器学习模型造成的危害的影响,有必要包括更多具体涉及偏见和歧视的选项。

这不是一个孤立的挑战。在使用 Imagenet 数据集(这里的、这里的和这里的)开发的图像识别模型中,也存在类似的偏见和歧视挑战。如果迁移学习是采用正在变得民主化的新兴技术的途径,那么有必要理解,在当前的形式下,这些民主化并非没有危害。

需求:预培训模型的记分卡

需要为 GitHub 上的 预训练模型 或代码建立记分卡。记分卡应包含关于模型或其基础训练数据是否经过偏见、网络安全或恶意攻击等测试的整理回答。在公开存储库之前,还应收集关于使用模型的限制或可以使用或不可以使用模型的环境、与使用此类模型相关的注意事项等信息。虽然这看起来对 GitHub 用户有很大的期望,但它不可避免地是相关的,并且旨在为社区和广大人民的福祉做出贡献。应该要求用户在用代码更新存储库时更新这些信息,并且应该通知用户从记分卡的角度查看存储库,反之亦然。

像 GPT-3 这样的储存库在储存库上包含特定的模型卡,包括对模型使用的期望、模型的限制和潜在偏差的可能性(此处为)。这是最佳实践之一,因为您在 GitHub 上的许多其他公共存储库中找不到类似的参考资料。然而,即使这样的最佳实践披露也不够具体,不足以分享团队为验证模型免受偏见或敌对攻击所做的努力。

结论

鉴于 GitHub 的“Copilot”的宣布,这是至关重要的,Copilot 是一种人工智能工具,在平台上的数十亿行代码上进行训练。该工具有望为用户的项目生成补充代码。除了这个工具的合法性问题之外(这里是),一个相关的问题是“你会舒服地使用一个有潜在偏见的代码或模型吗?”。记分卡不是目的,而是一种在机器学习中民主化迁移学习的同时带来上下文视图的手段。

GitRater —预测您的 GitHub 档案的质量

原文:https://towardsdatascience.com/gitrater-predicting-the-quality-of-your-github-profile-b6cf66467304?source=collection_archive---------39-----------------------

使用机器学习来预测你是否擅长编码

如果你曾经申请过技术职位,你可能会给公司发一个你的 GitHub 简介的链接。这个档案中的信息可以很好地表明你的编码能力和是否适合团队。所有这些信息的不利之处在于,招聘人员可能需要很长时间来评估这些信息。为了节省时间,机器学习有可能被用来自动评估你的编码能力。

来源: flaticon

在本文中,我们将带您了解构建这样一个模型的过程。我们讨论如何从 GitHub 收集数据,并使用这些数据创建模型特征。为了建立一些直觉,我们探索数据集中的关系。最后,我们比较和解释了两种最大似然算法——决策树和随机森林。你可以在 GitHub 上找到这个分析的代码,在 Kaggle 上找到数据集。

数据收集和特征工程

从您的代码库到您关注的其他程序员,您的 GitHub 个人资料中有许多公开信息。我们构建了一个 web scraper,从 230 个用户的个人资料中收集了一些数据。例如,您将在任何用户的概览页面上看到与图 1 中相似的贡献列表。当用户编写新代码并将其保存到他们的一个代码库(repos)时,他们就做出了贡献。

图 1: GitHub 贡献(来源:作者)

通过搜集这些数据,我们最终得到了去年每天所做贡献的列表。为了能够在模型中使用这些数据,我们首先需要做一些特征工程。有几种方法可以做到这一点。比如我们可以统计最近一年的投稿总数( n_cont )。我们还可以获取自他们最后一次投稿以来的天数( last_cont )。这些贡献只是我们可以用来创建模型特征的 GitHub 概要文件的一个方面。

图 2: GitHub 工具条(来源:作者)

图 2 显示了用户侧边栏中的一些可用信息。由此,我们可以获得关注者的数量,以及用户已经标记的存储库的数量( stars )。这些已经是数字了,所以不需要特征工程。最后,我们还从组织信息中创建一个标志( org_flag ),它将表明用户是否是组织的一部分。

最后一组特征来自用户的回复。在图 3 中,我们可以看到一些代码回收的例子。我们收集了用户创建的回购总数(回购)。我们还收集了每个回购协议中使用的编码语言。由此,我们统计了所有用户回复中使用的不同编码语言的数量( n_lang )。

图 3: GitHub 存储库(来源:作者)

表 1 总结了所有创建的模型特征。除了 stab_contfoll_ratio 和 **cont_repo_ratio、**这些我们上面都讨论过。还可以创建其他信息源/特征。我们将自己限制在这个集合中,因为它们相当简单,数据也很容易收集。希望这些特征至少与允许我们做出准确预测的编码能力有关。具体来说,我们将尝试使用它们来预测从 0 到 5 的评分。

表 1:模型特征列表

此评级是通过取两个独立评级的平均值得出的。重要的是,评价者并不局限于上述特征中包含的信息。例如,评价者可以打开 repos 中的文件,阅读实际编写的代码。在浏览了一个档案之后,每个评价者根据用户的编码水平给出一个等级,从 0 到 5 (5 是最好的)。两次评级的平均值作为最终评级/目标变量。

数据探索

在我们开始建模之前,探索一下我们的模型特征是一个好主意。我们这样做是为了建立直觉,并了解哪些功能将有助于预测评级。图 4 中可以看到一个潜在的好预测器的例子。在这里,我们可以看到额定值和 n_cont 之间的关系。请注意,随着用户总贡献的增加,用户的评级往往也会增加。

图 4:评级与贡献散点图

此时,你应该问问自己这段感情有没有意义。没有贡献或贡献很少的用户在过去的一年中不会做很多编码工作。做了很多贡献的用户会做很多编码。这似乎是合乎逻辑的——你编码得越多,你就越擅长编码。我们的模型有望利用这种关系进行预测。

另一方面,你可以看到评分和带星库数量的关系()。在这种情况下,似乎没有任何模式。也许这是因为你不需要做任何编码就可以启动其他用户的回复。也就是说,星星不会告诉我们任何关于你编码能力的事情。从这个分析中,我们不应该期望星星是我们模型中的一个重要特征。

图 5:评级与星级散点图

另一个潜在的重要特征是组织标志。我们可以期待组织中的用户成为更好的程序员。特别是,如果他们是像谷歌开源社区的一部分。在下面的方框图中,我们可以看到,属于某个组织的用户的评分往往更高。没有组织的平均评分为 1.8,而当用户是组织的一部分时,平均评分为 3.4。这种差异表明 org_flag 可能是一个很好的预测器。

图 6:评级与组织标志箱线图

我们应该记住,这些特征不是孤立存在的。看似具有预测性的特性,当它们与其他特性一起包含在模型中时,可能并不那么重要。这是由于特征本身之间的关系。例如,在图 7 中,我们可以看到贡献更多的用户更有可能成为组织的一部分。具体来说,贡献 500 英镑或更多的用户中有 70%是某个组织的成员。然而,对于那些缴款少于 500 英镑的人来说,这一比例仅为 20%。

图 7:评级与贡献-组织散点图

假设我们创建一个只有 **org_flag 的模型。**根据上述分析,组织中的员工可能会获得更高的预测评级。我们可以通过在模型中添加 n_cont 来改进这些预测。同样,贡献较大的人可能会获得较高的评级。然而,许多具有高贡献的用户将是组织的一部分。这意味着他们可能已经被给予了很高的评级,所以包括 n_cont 可能不会像我们想象的那样改善这些预测。最终, n_cont 的重要性实际上取决于它给出的信息比 org_flag 给出的信息多多少。

来源: flaticon

决策图表

考虑到我们的探索性数据分析,是时候继续建模了。我们将从创建一个简单的决策树开始。为此,我们首先分割数据集,并使用 200 行来训练决策树。我们保留剩余的 30 行作为测试集。决策树是使用基尼系数来决定每个节点的最优分割。我们还将树限制为每个叶节点至少有 10 个样本。您可以在图 9 中看到整个决策树。

为了理解这棵树是如何工作的,让我们从根节点开始。如果用户满足第一行中的规则(即,至少做出了 105 个贡献),我们将沿着树中的右箭头向下。如果不满足该规则,我们将遵循左箭头。我们不断地检查规则并跟随箭头,直到到达一个叶节点。例如,如果一个用户做了 900 次贡献,并且有 90 个关注者,那么我们将到达用红色圈出的叶节点。17 个用户最终在这个桶中,并且他们被给予 4.603 的评级。

图 9:决策树

下一步是使用这个模型对测试集进行预测。为了评估这个模型,我们应该将实际评分与这些预测进行比较。一种方法是使用图 8 中的散点图。如果模型是完美的,所有点将落在红线上(即实际=预测)。黑色虚线距离红线一个单位。这意味着,与实际评级相比,只有 2 个预测的差异超过 1。总体而言,该模型在测试集上的 MSE 为 0.3077。

图 8:决策树实际评分与预测评分

随机森林

决策树通常被认为是一个简单的 ML 模型。让我们看看能否使用更复杂的方法——随机森林——来提高这一精度。具体来说,我们使用一个有 100 棵树的随机森林。每棵树的最大深度限制为 4。与决策树一样,您可以在图 10 中看到实际评分与预测评分的对比图。

同样,我们有 2 个预测的误差超过 1 个单位。就 MSE 而言,似乎确实有所改善。测试集上的 MSE 为 0.2691,比决策树低 12.5%。在决定使用哪种最终模型时,应该将精确度的提高与使用更复杂模型的缺点进行权衡。

图 10:随机森林实际与预测评级

其中一个缺点是我们不能像解释决策树一样解释随机森林。换句话说,我们不能简单地将整个模型可视化,如图 9 所示。这意味着我们对模型如何做出预测的理解会更差。为了解释这个模型,我们将不得不使用额外的技术,比如特征重要性分数。

我们可以在图 11 中看到随机森林的特性重要性分数。一般来说,特征的重要性越大,该特征在进行预测时就越有用。我们可以看到 n_cont 是迄今为止最有用的,其次是回购追随者。我们可以看到星星并不是很重要。这与我们的探索性分析是一致的。不一致的是 org_flag 最不重要。看起来这个特性并不像我们预期的那样重要。

图 11:随机森林特征重要性

想法和未来的工作

在任何模型中,都有需要解决的弱点。我们应该努力理解的一个方面是为什么 n_cont 比其他任何特性都重要。参见图 12,当您第一次打开某人的个人资料时,贡献会立即吸引您的注意。这可能会对评定者的决策过程产生影响。换句话说,他们对捐款的依赖可能超过了他们的意愿。

图 12: Github 概述页面

评级也可能在其他方面出现偏差。例如,如果评价人考虑用户的档案图片,可能会引入种族/性别偏见。为了解决这个问题,我们需要一个客观的评级系统。它应该只考虑与编码能力直接相关的信息,并且该信息应该更统一地呈现。

在实践中,不同的公司或团队的评级系统可能会有所不同。对于给定的用户,数据工程团队可以给数据科学团队一个完全不同的评级。这是因为每个团队所需的技能不同。换句话说,评级将捕获用户在特定团队中的表现,而不是他们在总体编码方面的表现。

来源: flaticon

围绕特征工程也有很多工作可以做。到目前为止,我们所使用的功能实际上只是与编码能力相关。做出很多贡献并不能让你成为一个好的程序员。只是好的程序员往往会做出很多贡献。我们应该尝试从实际编写的代码中创建功能。例如,我们可以识别用户是否使用了单元测试,使用了一致的命名约定,或者正确地注释了他们的代码。

总的来说,使用机器学习来预测编码能力似乎是可能的。使用一个相当简单的方法,我们可以做出与实际评级一致的预测。希望这将为将来更好的模型打下基础。

我们提到了性别/种族偏见。机器学习中的这种偏见比许多人意识到的更普遍。亚马逊使用的一个系统就是一个例子,该系统不以性别中立的方式对求职者的简历进行评级。我们将在下面的文章中讨论这一点以及其他一些有偏差的算法:

图像来源

所有图片都是我自己的或从www.flaticon.com获得的。在后者的情况下,我拥有他们的高级计划中定义的“完全许可”。

给 Python 插上翅膀——实现更快 Python 程序的简单技巧

原文:https://towardsdatascience.com/give-wings-to-python-make-it-fly-6eb4d4859b89?source=collection_archive---------16-----------------------

编写优化且更快的 Python 程序的策略汇编

Python 不是特别快,但它是最受欢迎的编码语言之一,尤其是在数据分析方面。有趣的是,使它天生缓慢的原因也使它成为最受欢迎的语言。

  1. 动态类型化 —用户不必提供变量的数据类型。这让用户的生活更轻松,但给解释者带来了麻烦。
  2. 已解释,未编译 — Python 被解释为未编译,这意味着它不能提前对程序进行内存和速度的高级优化。
  3. 内存问题——由于 Python 的灵活性,每个元素都有自己的内存,而不是一个连续的内存块。它会在提取操作过程中造成时间延迟

资料来源:联合国人类住区规划署

尽管有这些问题,我相信大多数缓慢进入系统可以归因于程序员编写简洁、优化程序的能力。这些年来,我在处理数据、构建模型、将不那么优化的代码投入生产的时候犯了很多错误。但是所有这些经历为我提供了一些工具,我一直用这些工具来使我的代码更干净、更快、更 pythonic 化(不管那意味着什么)。

让我们看看那是什么。

创可贴解决方案

如果你有很多时间,那么你可以把你的 Python 代码转换成 C/C++,然后在上面写一个 Python 包装器。它将为您提供 C++的速度,并保持 Python 的易用性。

但是,我们不希望这样,因为有更简单的解决方案。

Numba 走进房间。

好吧,我告诉你 Numba 从 2012 年就开始出现了,但对许多程序员来说仍然是难以捉摸的。

它本质上是把你的 Python 代码转换成机器码,速度和 C 代码差不多。

让我们用一个简单的例子来验证一下。一个简单的功能,没什么重的。

在具有 6 个内核的 i7 机器上,每循环 1.43 秒。看起来很慢,但肯定可以改进。

使用 pip 在您的机器上安装 numba

pip install numba

我们所做的只是添加了两行代码,import 和@jit(nopython=True)

每循环 14.5 毫秒。

那就是 1430/14.5 ~ 98X 的速度增益。

收益当然取决于你的机器和你到底想做什么,但如果你想快速解决问题而又不想过多地陷入代码的罪恶中,这是一个很好的起点。

  • 它通常在你不得不处理令人烦恼的循环时起作用

或者,

  • 其中需要对大集合执行相同的操作。

侧写师

您需要找出代码的哪一部分使它变慢了。在大多数情况下,这将是一些错误形成的循环或函数,这将是麻烦制造者。

Unix 计时器

在 shell 上,在调用 python 和您的代码之前,您需要使用 Unix 的 time 命令。

cProfiler

您可以从 shell 中运行 cProfiler,方法是调用

python -m cProfile -s time name_of_your_file.py

它会让你淹没在大量的信息中,所以你需要做些别的事情。

您可以在代码中导入 cProfile,并在您怀疑会使您陷入困境的函数上运行它。

import cProfile
cProfile.run('complicated_func()') #*Here I am running it on a complicated_function that has time overheads.*

输出可以放在文件中,也可以在 shell 上看到。

cProfile.run('complicated_func()', 'output.txt')

舒马赫速度

到目前为止,它是关于创可贴解决方案以及如何对您的代码进行时间配置,让我们来看看某些策略,它们不仅是最佳实践,而且还能为您加快速度。

发电机节省内存,提高速度

列表是很好的,但是如果你正在处理一些需要延迟生成的列,那么生成器会更好。

使用生成器带来的性能提升是延迟(按需)值生成的结果,这意味着更低的内存使用率。此外,我们不需要等到所有的元素都生成之后才开始使用它们。

上面的代码片段为列表使用了 87,616 字节的内存,而生成器只使用了 112 字节的内存**。**

节省下来的内存可以让你的代码运行得更快,因为 CPU 正在处理的所有数据都应该在缓存中;如果使用列表,那么数据溢出到 L1 缓存的可能性更大。

范围内的枚举

这更多的是一个 干净代码 的原则,而不是与速度有关。如果您不仅需要处理数据的索引,还需要处理数据本身,那么在 Python 3.8 上,enumerate 是一个更干净、更好、也更快的选择。

进口

如果你打算只使用一个函数,不要导入整个库和包。

import math
value = math.sqrt(50)vsfrom math import sqrt
value = sqrt(50)

当编写生产级代码时,如此小的开销累积起来会达到惊人的比例。

明智地使用 Itertools

尽可能使用 itertools,它们可以节省大量时间,尤其是在避免 for 循环方面。

from itertools import productdef cartesian_prod (arr1, arr2):
    return list(product(arr1, arr2))arr1 = [1,2,3]
arr2 = [4,5,6]
cartesian_prod(arr1, arr2) # Output is
[(1, 4), (1, 5), (1, 6), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6)]

如果您正在处理一个问题陈述,比如推荐系统,并且想要用户项的组合,那么通过 itertools 计算笛卡尔积是一个明智而安全的选择。

人们还可以使用 itertools 的排列组合功能来减轻生活中的一些痛苦。

只用 f 弦系住你的琴弦

不要对字符串使用任何旧的方法,比如%s 或 format(),f 字符串非常快,而且更容易使用

传统 for 循环的列表理解

一般来说,for 循环(至少比 while 循环好)很慢,如果你开始使用两个嵌套循环,那么复杂度将会是 n。

对于传统的 For 循环,时间是 136 毫秒

对于列表理解,它是 118 毫秒

这不是一个很大的改进,但是代码看起来更干净,并且只用一行代码就完成了。

类似地,使用 map、filter 和 reduce 函数可以减轻代码的时间和空间复杂度。

资料来源:Giphy

你的硬件是什么?

十有八九,你可能在 SSD(固态硬盘)上运行你的代码。如果你已经达到专业水平的 python 编程,那么你检查 SFrames,可伸缩框架的缩写。它们在固态硬盘上的大型数据集上工作得非常好,比熊猫好得多。

人们可以使用 turicreate(graph lab 的免费版本)在代码中使用 SFrame。

结论

有许多方法可以优化代码的性能。所有上述策略都经过了尝试和测试,但它们不是快速解决问题或万无一失的解决方案,因为它们在某种程度上取决于您运行它的数据和您使用的硬件。

还有许多其他方法,如使用局部变量、并发和多线程,也有助于实现更快的速度。

编码时,遵循最佳实践,而不是抄近路,因为生产环境非常敏感,您不希望花费无数时间回顾您在亿万年前编写的东西。

通常在代码库的可读性和优化之间有一个折衷。孰先孰后的决定取决于你。

给你的图表一些(空白)空间!

原文:https://towardsdatascience.com/give-your-graphs-some-white-space-c3384167a187?source=collection_archive---------24-----------------------

理解空白在数据可视化中的重要性的 3 个步骤——以及如何将理论应用于实践

伊莲娜·乔兰在 Unsplash 上的照片

当查看任何数据可视化时,我们大多数人首先关注的是以几何形状、数字、颜色等形式显示的内容。一句话:作为人类,我们直觉上倾向于最关注图表中的“哇”元素。然而,正是空白的使用让我们能够理解图表——而不仅仅是看到形状、数字和颜色的增加。

我邀请你以你最近看到的任何图表为例。当然,你会先看我前面提到的元素。但是再看一遍:图中不是“wow”元素的其余空间怎么办?图形本身周围的所有空间呢?图形中两个文本块或两行之间的空间呢?正是这些空白的使用让你有可能理解这个图表。为了让你相信这一点,想象一下没有任何空白的同一个图形!

图 1 —玛丽·勒费夫尔

1.空白真的重要吗?

先说一个定义。我在这里定义的白色空间不是指“宇宙”,也不是指房间里的白色墙壁。本文重点介绍空白,即图中没有显示任何内容的所有空间:没有颜色,没有文本,什么都没有。有些人使用术语“负空格”来指代页面中未标记的区域。如本研讨会课程中关于数据可视化的所述:

“负空间和所使用的轴、文本和形状一样,都是整体设计的一部分。它需要给元素呼吸的空间,并提高形象的视觉吸引力和效果”。

为了证明空白的重要性,让我举一个你肯定知道的例子:联邦快递的标志在 E 和 x 之间隐藏了一个指向右边的箭头,你也可以在本文中看到其他公司标志使用负空格的例子。出于版权原因,我不会在这里展示他们的标志。这些公司使用空白来揭示其标志中隐藏的符号或含义,这突出了他们的品牌,并使他们的名称和视觉身份对潜在客户来说是难忘的。这就是留白的强大之处:负空间比彩色空间更能告诉我们公司的信息

第二个证明空白空间重要性的例子是媒体平台本身。你有没有注意到 Medium 的文章的文字边距有多宽?媒体文章的行距和整体设计充分利用了留白空间。结果是显而易见的:对于读者来说,阅读间隔良好的文本要比紧凑的线条舒服得多。总的来说,这种类型的设计有助于更清楚地传达文章的信息,同时文章的视觉效果由围绕它们的空白空间突出。

图 2 — 玛丽·勒菲弗尔

2.数据可视化中的空白怎么办?

既然您已经理解了空白有多重要的理论,那么让我们开始数据可视化领域的实践吧。在图表和信息图中,我们可以确定两种类型的空白,我们将在本文的下一部分讨论:

  • 宏观空白区域是图形主要部分周围的所有空间,也就是说,活动的核心发生在这里
  • 微空白是所有的间隙空间,例如文本的两个字母之间、数字和轴之间、两条图形线或条之间

更形象地说,我收集了基于名义 GDP(国内生产总值)的十大经济体 2009 年至 2019 年间生育率演变的数据。你可以在我们的数据世界的网站上找到我在这里使用的数据集的来源。让我先给你展示一下这张图的一个不太理想的版本:

图 3 —玛丽·勒费夫尔

下图突出显示了该图中的宏观(蓝色)和微观(红色)空白区域:

图 4 —玛丽·勒费夫尔

3.如何优化图表和信息图中的空白?

在之前的文章中,我探讨了玩颜色如何影响同一图表的含义。在这里,让我们一起探索如何利用图表的空白对数据可视化的两个关键方面产生重大影响:图表的可读性和所传达信息的有效性。

首先,在图表周围添加一些宏观空白会给你的图表空间。当包含在研究论文或文章中时,添加宏观空白可以确保你的图表充分融入你的正文。顺便说一句,你可以注意到我是如何在整篇文章中应用这条建议的,尤其是在上面的图中故意添加空白的时候。在这里的行间添加一些微小的空格将会对你的读者产生影响:增加两个国家之间的间距使读者更容易区分每个国家分别从 2009 年到 2019 年的数据(见图 5)。

图 5 —玛丽·勒费夫尔

其次,让我们关注空白如何能够支持图表作者想要传达的信息。在我的例子中,假设我想突出显示列表中的前 3 个国家,例如,因为我对根据不同指标(总人口、GDP、贸易平衡等)比较前 3 个国家特别感兴趣。).在这种情况下,在第三个国家和第四个国家之间添加一个更宽的空间将突出我作为图形创建者的目的(见图 6)。

图 6 —玛丽·勒费夫尔

结论:空白≥“Wow”元素

我的最后一句话实际上就是这篇文章的标题:请给你的图表留白!除了美学方面的考虑,在数据可视化中使用留白在使您的图形适合您的故事以及向您的受众传达正确的信息方面起着至关重要的作用。

我对您关于如何最好地组织数据可视化空间的建议很感兴趣,请不要犹豫,分享您对这个主题的想法!

你喜欢阅读这篇文章吗? 成为会员 加入一个不断成长的充满好奇心的社区吧!

在物理引擎中实现遗传算法控制

原文:https://towardsdatascience.com/giving-a-genetic-algorithm-control-in-a-physics-engine-abeeb5f2d603?source=collection_archive---------35-----------------------

人工智能在物理引擎中的应用简介

Vishnu Mohanan 在 Unsplash 上的照片

人工智能最常见的商业应用是获得洞察力或对数据集进行预测。尽管我认为这很有趣,但是这些技术已经被其他人广泛地讨论过了。

本文涵盖了机器学习的一个更具实验性的应用:这是允许机器学习操纵物理模拟。

概念:

将人工智能放入物理环境有很多不同的可能性,但所有这些都涉及到操纵和控制环境中的对象和力。为了从这个项目中获得好的结果,我们需要给人工智能在环境中的控制增加限制。

照片由 Med Badr Chemmaoui 在 Unsplash 拍摄

我决定的限制如下:人工智能必须生成一个 n 边多边形。多边形的每个点都有一个以固定速度旋转的分支。这个旋转速率是由 AI 定义的。

遗传算法需要一个适应度函数来随着时间的推移改进代理。在这种情况下,将根据两个因素来判断代理:速度和面积。在这种情况下,速度被定义为在 100 帧中行进的 x 距离。面积是由多边形的点围成的空间。面积被考虑在内,以防止需要更复杂的编码来添加空气阻力对生物的影响。

我们希望速度最大化,面积最小化。我们可以得出结论,智能体的适应度可以是速度/面积。这将使得适应度与速度成正比,与面积成反比。希望我们最终能拥有移动迅速、体积小巧的“生物”。这意味着一个类似的生物在现实中应该站得住脚,这给了这个项目更多的实用价值。

实施:

我将只添加代码中有趣的部分,因为代码的其余部分不需要任何解释。如果想要项目的完整代码,可以在这里找到。

物理模拟基础:

我在这个项目中使用的物理引擎是基于 pymunk 库的,它包含了使这个项目工作的所有部分。

下面的脚本是一个可以由模型生成的布娃娃的例子。

列表“vs”是构成布娃娃主体的点的列表。“肢体”列表是定义每个肢体的向量长度的列表。循环通过将肢体添加到身体的每个点来构建身体。这是模拟的 gif 图:

由作者创建

健身功能:

这是控制选择保留哪些代理的适应度函数。这个适应度函数为每个代理运行物理模拟。

每个智能体都有三个独立的神经网络,即“运动网络”、“身体网络”和“手臂网络”。运动网络为每个肢体生成运动速度,身体网络定义身体上每个点的坐标,手臂网络定义每个肢体的长度。这两种神经网络都将随机值作为输入。

模型有一个最终的双曲正切值(范围为-1 到 1)。然后乘以一个常数值,作为网络的范围。这是为了使模型可以创建多用途的结果,同时防止非常大或非常小的机构。这允许一些一致性,以便更好地比较。

身体的定义在第 26–29 行:对于身体上的每个点,添加一个手臂,连接类型为“枢轴关节”。枢轴关节只是一个围绕单个点旋转的关节。“简单的马达”仅仅意味着转速是一致的。

在药剂被放入一个大盒子之前,身体和马达已经安装好了。对于定义的步数,代理移动。代理运行的距离可以由它的身体位置的 x 维变化来定义。

我将单独讨论遗传算法,因为它更复杂,而且我在最近的项目中使用了很多。

结果:

以下是该算法创造的更多生物:

由作者创建

这种生物的身体很瘦,但手臂很短,而且确实会导致过多的净移动,从而导致体能下降。

由作者创建

瘦弱的身体和不同的旋转方向/速度使这种生物获得了比其他生物更高的分数。

由作者创建

对称的运动导致不多的运动,因此健康值低。

结论:

这个项目花了很长时间来拼凑,因为我尝试了许多不同的方法来使用物理环境。幸运的是,在我放弃这个项目之前,我找到了 pymunk。

这个项目的一个巨大限制是缺乏可以逐渐移动而不是旋转的关节/马达。我计划创建/找到一个功能,可以改变每一步的旋转角度/方向,允许像 LSTMs 更复杂的模型的实现。

我仍然认为这个项目很有趣,足以让我继续研究更多基于物理的优化问题。

我的链接:

如果你想看更多我的内容,点击这个 链接

给谷歌云上新的统一 ML 平台 Vertex AI 一个旋转

原文:https://towardsdatascience.com/giving-vertex-ai-the-new-unified-ml-platform-on-google-cloud-a-spin-35e0f3852f25?source=collection_archive---------2-----------------------

我们为什么需要它,无代码 ML 培训到底有多好,以及所有这些对数据科学工作意味着什么?

过去几个月,谷歌云人工智能平台团队一直在构建机器学习前景的统一视图。这是今天在谷歌 I/O 发布的顶点人工智能。这是什么?有多好?对数据科学工作来说意味着什么?

有什么好统一的?

这个想法是机器学习中有几个关键的结构:

  • 我们通过接收数据、分析数据和清理数据(ETL 或 ELT)来创建数据集。
  • 然后我们训练一个模型(模型训练)——这包括实验、假设检验和超参数调整。
  • 当有新数据时,在计划中,或者当代码改变时,该模型被版本化和重建(ML Ops)。
  • 对模型进行评估,并与现有模型版本进行比较。
  • 该模型被部署并用于在线和批量预测。

然而,这取决于您如何进行 ETL(您是否将数据存储在 CSV 文件中?TensorFlow 记录?JPEG 文件?在云存储中?在 BigQuery?),剩下的管道就变得很不一样了。有一个 ML 数据集的想法不是很好吗?任何下游模型(TensorFlow,sklearn,PyTorch)都可以使用的?这就是统一数据集概念背后的含义。

Vertex AI 为 ML 生命周期提供了一套统一的 API。图表由亨利·塔彭和布莱恩·科巴什卡瓦提供

此外,部署 TensorFlow 模型的方式不同于部署 PyTorch 模型的方式,甚至 TensorFlow 模型也可能因使用 AutoML 还是通过代码创建而有所不同。在 Vertex AI 提供的一组统一的 API 中,你可以用同样的方式对待所有这些模型。

Vertex AI 提供了四个概念的统一定义/实现:

  • 一个数据集可以是结构化的,也可以是非结构化的。它管理包括注释在内的元数据,可以存储在 GCP 的任何地方。认识到这是远景——目前只支持云存储和 BigQuery。还不是 Bigtable 或 Pub/Sub。
  • 训练管道是一系列容器化的步骤,可用于使用数据集训练 ML 模型。容器化有助于通用性、可再现性和可审计性。
  • 一个模型是一个带有元数据的 ML 模型,它是用训练管道构建的或者是直接加载的(只要它是兼容的格式)。
  • 用户可以调用端点进行在线预测和解释。它可以有一个或多个模型,以及这些模型的一个或多个版本,并根据请求进行消歧。

关键的想法是,无论数据集、训练管道、模型或端点的类型如何,这些工件都是相同的。都是混搭。因此,一旦创建了数据集,就可以将其用于不同的模型。无论你如何训练你的模型,你都可以从一个端点获得可解释的人工智能。

这一点在 web 用户界面上显而易见:

好了,说够了为什么。让我们兜一圈。

带 BigQuery 的 SQL 中的 ML

当你使用新技术训练一个 ML 模型,并将其与你知道和理解的东西进行比较时,这总是好的。

我将使用 Kaggle 上的 Airbnb 纽约市数据集来预测公寓租金的价格。

首先,我们将数据加载到 BigQuery 中。这个数据集有点笨拙,在我将它加载到 BigQuery 之前需要清理(详情见的博文),但是我将它公之于众,所以你可以简单地尝试一下这个查询:

SELECT 
neighbourhood_group, neighbourhood, latitude, longitude, room_type, price, minimum_nights, number_of_reviews, reviews_per_month, calculated_host_listings_count, availability_365
FROM `ai-analytics-solutions.publicdata.airbnb_nyc_2019`
LIMIT 100

已经验证了数据现在看起来是合理的,让我们继续训练一个 xgboost 模型来预测价格。这就像添加两行 SQL 代码一样简单:

CREATE OR REPLACE MODEL advdata.airbnb_xgboost
OPTIONS(**model_type='boosted_tree_regressor', input_label_cols=['price']**) ASSELECT 
neighbourhood_group, neighbourhood, latitude, longitude, room_type, price, minimum_nights, number_of_reviews, reviews_per_month, calculated_host_listings_count, availability_365
FROM `ai-analytics-solutions.publicdata.airbnb_nyc_2019`

我们得到一个快速收敛的模型

…平均绝对误差为 64.88 美元。

这有多好?Airbnb 上纽约市公寓的均价是多少?

SELECT 
AVG(price)
FROM `ai-analytics-solutions.publicdata.airbnb_nyc_2019`

一共是 153 美元。所以,我们有 40%的折扣。也许不是一个投入生产的模型…但你不会期望一个公共数据集有更多的专有和个性化的数据来帮助改善这些预测。不过,这些数据的可用性有助于我们了解如何训练 ML 模型来预测价格。

接下来,我们来试试 Vertex AI 中的 Auto ML 表格。

顶点人工智能

让我们从 Kaggle 上的 CSV 文件开始,这样我们就不会被我将数据加载到 BigQuery 时所做的数据转换所困扰。转到https://console.cloud.google.com/vertex-ai/datasets/create

  • 将其命名为 airbnb_raw,选择表格回归,选择爱荷华地区,点击创建
  • 创建数据集后,从 GCS 中选择 CSV 文件,提供 URL:GS://data-science-on-GCP/Airbnb _ NYC _ 2019 . CSV,然后点击继续
  • Vertex AI 愉快地加载数据,没有任何限制,拉出标题并显示 16 列。
  • 单击 Generate Statistics,它会向您显示在缺少值方面唯一可能有问题的字段是 review 字段。但这是有道理的:不是每个 BnB 航空公司的客人都会留下评论。

  • 现在选择训练新模型并选择回归和自动:

  • 再次注意,我们可以提供自己的定制代码,并且仍然保留在整个工作流中。我们不必仅仅因为想要定制流程的一部分就放弃自动化培训管道。
  • 在下一个窗格中,选择 price 作为要预测的目标列:

  • 在下一个窗格中,从预测值集中删除 id 列。将邻域更改为分类(来自文本),并将目标更改为 MAE。
  • 给它 3 个小时的预算,开始训练。

大约 3 小时后,培训结束,我们可以检查模型并根据需要进行部署:

我们得到的平均绝对误差为 55 美元,比使用 xgboost 得到的误差几乎高出 20%。所以,一个更精确的模型,用更少的代码。包括评估、特性重要性、可解释性、部署等。所有这些都是现成的。

最底层的

BigQuery ML 和 AutoML 表都易于使用并且非常好。它有助于理解领域的基础知识(为什么没有评论?),以及机器学习的(不要用 id 列做输入!),但从一个公民数据科学家的角度来看,他们相当平易近人。编码和基础设施管理开销几乎完全消除了。

这对数据科学工作来说意味着什么?从编写原始 HTML 到使用 weebly/wix/etc 的转变。并不意味着网络开发人员的工作会减少。相反,这意味着更多的人创建网站。当每个人都有一个基本的网站时,它驱动了一种差异化的需求,以建立更好的网站,因此为网络开发人员提供了更多的工作。

机器学习的民主化也会导致同样的效果。随着越来越多的事情变得容易,将会有越来越多的机器学习模型被构建和部署。这将推动差异化的需求,并建立超越和解决日益复杂的任务的 ML 模型管道(例如,不只是估计租赁价格,而是进行动态定价)。

机器学习的民主化将导致更多的机器学习,以及更多的 ML 开发者的工作,而不是更少。这是一件好事,我为此感到兴奋。

还有,哦,Vertex AI 真的很好看。在你的 ML 问题上尝试一下,让我知道(你可以在 Twitter 上@lak_gcp 找到我)效果如何!

更多关于 Vertex AI 的阅读:

  1. 给谷歌云上的新统一 ML 平台 Vertex AI 一个旋转 :
    我们为什么需要它,无代码 ML 培训到底有多好,所有这些对数据科学工作意味着什么?
  2. 如何将 TensorFlow 模型部署到 Vertex AI :在 Vertex AI 中使用保存的模型和端点
  3. 使用 Python 在 Vertex AI 上开发和部署机器学习模型:编写让你的 MLOps 团队满意的训练管道
  4. 如何在 Vertex AI 中为超参数调整构建 MLOps 管道 :
    为超参数调整设置模型和协调器的最佳实践

GLMs 第二部分:牛顿-拉夫森,费希尔评分,迭代加权最小二乘法(IRLS)-一个严格的概述

原文:https://towardsdatascience.com/glms-part-ii-newton-raphson-fisher-scoring-iteratively-reweighted-least-squares-irls-a-1a1e2911047?source=collection_archive---------2-----------------------

用计算机模拟迭代拟合技术的数学推导和实现。

穆罕默德·拉赫马尼在 Unsplash 上的照片

1:背景和动机

广义线性模型(GLMs)在包括统计学、数据科学、机器学习和其他计算科学在内的领域中起着关键作用。

在本系列的第一部分中,我们提供了规范和非规范形式的常见 GLMs 的全面的数学概述(带证明)。下一个需要解决的问题是,我们如何让数据符合 GLM 模型?

从历史背景来看 GLMs 时,有三个密切相关的重要数据拟合程序:

  • 牛顿-拉夫森
  • 费希尔评分
  • 迭代加权最小二乘法(IRLS)

我发现这些技术的关系和动机往往很难理解,上面的术语有时会以不正确的方式互换使用。这篇文章提供了这三个重要的迭代数值拟合过程的严格概述,连接它们的历史的讨论,以及在示例规范和非规范 GLMs 上实现这些方法的详细计算模拟。在未来的一篇文章中,我们将通过多阶段递归 GLM 模型的镜头来涵盖神经网络的推导。

这篇文章的目录如下:

作者图片

说到这里,让我们开始吧!

2:迭代数值拟合技术的推导

2.1:根据数据拟合模型—简介

让我们首先为我们如何思考“用数据拟合模型”以及我们在数学上的含义打下基础。

作者图片

作者图片

在构建我们的第一个迭代数值拟合过程之前,我们需要首先绕道通过泰勒展开。

2.2: 泰勒展开和二阶近似

在构建我们的第一个迭代数值拟合过程之前,我们首先需要理解泰勒展开的基础。

作者图片

作者图片

我们现在准备构建我们的三个迭代数值拟合过程,从牛顿-拉夫森开始。

2.3:三次迭代数值拟合过程

2.3.1:牛顿-拉夫森

作者图片

作者图片

作者图片

作者图片

我们现在准备讨论我们的第二个迭代数值拟合过程费希尔评分,以及它与牛顿-拉夫森的联系。

2.3.2:费希尔得分

将牛顿拉夫森应用于我们在第 2.1 节中的例子,我们得到:

作者图片

有没有办法减轻这种计算负担?这就是费希尔得分发挥作用的地方。

作者图片

作者图片

在这篇文章的后面,我们将看到在 GLMs 可以以标准形式参数化的情况下,Newton-Raphson 和 Fisher 评分在数学上是等价的。

已经讨论了牛顿-拉夫森和费希尔评分,我们准备讨论我们的最后一个迭代数值拟合程序迭代加权最小二乘法(IRLS)。

2.3.3:迭代加权最小二乘法(IRLS)

为了理解我们的最后一个迭代数值拟合过程迭代重加权最小二乘(IRLS)及其与费希尔评分的关系,我们需要快速复习一下加权最小二乘(WLS)估计量。

作者图片

(更深入的推导有 【加权最小二乘(WLS)【广义最小二乘(GLS)【普通最小二乘(OLS) 估值器,参见我以前的几篇)**

作者图片

你可能会问…

“嗯……那很好……但是这和 GLMs 有什么关系呢?为什么我要让我的费希尔评分算法看起来“有点”像 WLS 估计量呢?这有什么意义???"

为了理解费希尔得分和 WLS 之间的联系,我们需要一些 GLMs 的历史背景。

如果你还记得本系列的第一部分,GLMs 是在 20 世纪 70 年代早期作为一个统一理论发展起来的。随着这一理论的发展,从业者希望找到一种方法,用他们可以在计算机上运行的计算软件将他们的数据拟合到 GLM 模型。嗯,20 世纪 70 年代仍然是计算的相对早期,尤其是科学计算。没有唾手可得的线性代数和数值库(例如 python 中的 numpy)。相反,人们必须从头开始编写他们自己的库。说当时的计算机几乎没有内存和硬盘空间是一种保守的说法;与今天相比,20 世纪 70 年代计算机的内存小得可笑。软件必须小心编写,并且必须在内存方面进行高度优化。那时写软件,尤其是科学计算软件,是很困难的。非常非常困难。

然而,在 GLM 理论发表之前,该领域的研究人员和从业者已经编写了计算机软件来拟合加权最小二乘估计量。换句话说,他们已经编写了软件来恢复以下估计量的经验估计值:

作者图片

因此,随着 GLM 理论的建立和软件使用费希尔评分将数据拟合到 GLMs 的需要,从业者有了一个想法:

“你知道……我们费希尔评分算法中的部分术语看起来很像 WLS 估计量。我们已经编写了解决 WLS 估计量的软件,它似乎工作得很好。那么…如果我们不完全从零开始编写费雪评分软件,而是让我们的费雪评分软件成为我们的 WLS 软件的简单包装函数,会怎么样呢!对于费希尔评分算法的每一个迭代步骤,我们可以重新参数化我们的问题,使其看起来像 WLS 估计量,并调用我们的 WLS 软件返回经验值。”

换句话说,在我们的费希尔评分算法的每一个迭代步骤中,我们要重新参数化以下内容:

作者图片

因此,迭代加权最小二乘法(IRLS)诞生了。术语“重新加权”是指在费希尔评分算法的每个迭代步骤中,我们都使用新的更新权重矩阵。

第 3 节中,我们将通过计算实例展示如何将牛顿-拉夫森、费希尔评分和 IRLS 用于规范和非规范 GLMs。然而,首先,在拟牛顿法和梯度下降简短的旁白。

2.4: 略论拟牛顿法和梯度下降法

在开始执行 GLMs 的三个主要迭代数值拟合过程之前,我想简单提一下另外两类相关的迭代方法,拟牛顿法和梯度下降法。

作者图片

作者图片

作者图片

作者图片

作者图片

3: 实施 GLMs 的装配程序

我们现在准备探索如何操作牛顿-拉夫森,费希尔评分,IRLS 为规范和非规范 GLMs。让我们先回顾一下 GLM:

3.1: GLM 复习

广义线性模型(GLM)有三个主要部分:

作者图片

现在让我们来研究一下标准和非标准形式的指数离差分布族的概率密度函数(PDF)的参数化。

作者图片

有关更深入的概述,请参见 GLMs 上的本系列文章的第一部分。

3.2:拟合程序 form 标准形式

回想一下,规范 GLMs 具有以下属性:

作者图片

我们现在准备展示如何将牛顿-拉夫森、费希尔评分和 IRLS 用于规范 GLMs:

3.2.1:牛顿-拉夫森

作者图片

作者图片

作者图片

作者图片

3.2.2:费希尔得分

作者图片

作者图片

3.2.3:迭代加权最小二乘法(IRLS)

作者图片

作者图片

作者图片

3.3:拟合程序——GLM 非标准形式

作者图片

作者图片

作者图片

作者图片

作者图片

作者图片

3.3.1:牛顿-拉夫森

作者图片

作者图片

作者图片

作者图片

3.3.2:费希尔评分

作者图片

作者图片

3.3.3:迭代加权最小二乘法(IRLS)

作者图片

作者图片

作者图片

作者图片

3.4:派生算法的总结

下面是 3.2 节和 3.3 节推导出的算法的总结

作者图片

作者图片

4:计算模拟

以下是两个典型 GLMs 的计算模拟:

  • 逻辑回归
  • 泊松回归

…和一个非规范的 GLM:

  • 概率单位回归

对于每个回归模型,我们使用牛顿-拉夫森法、费希尔评分法和迭代加权最小二乘法(IRLS)将模型拟合到数据。

让我们导入我们需要的库:

并指定一个函数来模拟不同的建模集:

指定我们需要的激活功能:

典型 GLMs 的牛顿-拉夫森、费希尔评分和 IRLS 的函数:

非规范 GLMs 的牛顿-拉夫森、费希尔评分和 IRLS 的函数:

4.1:逻辑回归

回想一下,对于逻辑回归,我们有:

作者图片

现在,让我们模拟我们的逻辑回归,使用牛顿-拉夫森、费希尔评分和 IRLS 拟合我们的模型,并将我们的结果与 python 中 Statsmodels 的内置逻辑回归库进行比较:

如我们所见,我们的结果与 Statsmodels 库的结果相同

4.2:泊松回归

回想一下,对于泊松回归,我们有:

作者图片

让我们模拟泊松回归,使用牛顿-拉夫森、费希尔评分和 IRLS 拟合我们的模型,并将我们的结果与 python 中 Statsmodels 的内置泊松回归库进行比较:

同样,我们的结果与来自 Statsmodels 库的结果相同

4.3:概率单位回归

对于概率单位回归,我们有:

作者图片

使用:

作者图片

作者图片

让我们模拟我们的概率单位回归,使用牛顿-拉夫森、费希尔评分和 IRLS 拟合我们的模型,并将我们的结果与 python 中 Statsmodels 的内置概率单位回归库进行比较:

同样,我们的结果与 Statsmodels 库的结果相同

以上计算模拟的完整代码/笔记本,请看下面的 github 链接

5:总结和结论

在本系列的第一部分中,我们提供了规范和非规范形式的常见 GLMs 的全面的数学概述(带证明)。在这篇关于 GLMs 的第二篇文章中,我们提供了对规范和非规范 GLMs 的三个重要迭代数值拟合过程的严格概述:牛顿-拉夫森法、费希尔评分法和迭代加权最小二乘法(IRLS)。还提供了这些方法的详细计算模拟。

在未来的一篇文章中,我们将通过多阶段递归 GLM 模型的镜头来涵盖神经网络的推导。

希望以上有见地。正如我在以前的一些文章中提到的,我认为没有足够的人花时间去做这些类型的练习。对我来说,这种基于理论的洞察力让我在实践中更容易使用方法。我个人的目标是鼓励该领域的其他人采取类似的方法。我打算在未来写一些基础作品,所以请随时在 LinkedIn 上与我联系,并在 Medium 上 关注我的更新!

GLMs 第三部分:作为递归广义线性模型的深度神经网络

原文:https://towardsdatascience.com/glms-part-iii-deep-neural-networks-as-recursive-generalized-linear-models-ccb02817c9b5?source=collection_archive---------12-----------------------

实践教程

数学推导和计算机模拟

Unsplash 上 AltumCode 的照片

1:简介

广义线性模型(GLMs)在包括统计学、数据科学、机器学习和其他计算科学在内的领域中起着关键作用。

本系列的第一部分提供了一个全面的数学概述,用规范和非规范的形式证明了常见的 GLMs。第二部分提供了 GLMs 常用迭代数值拟合程序的历史和数学背景,包括牛顿-拉夫森法、费希尔评分法、迭代加权最小二乘法和梯度下降法。

  • GLMs 第一部分:严格的数学公式
  • GLMs 第二部分:牛顿-拉夫森,费希尔评分,&迭代加权最小二乘法(IRLS)——严格概述

在这个三部分系列的最后一部分,我们探索神经网络及其与 GLMs 的联系。事实上,神经网络只不过是递归的规范 glm。伴随这一块是一个完全可用的计算机模拟。

这篇文章的目录如下:

作者图片

让我们跳进来吧!

2:激励神经网络

在本系列的前两篇文章中,我们重点讨论了 GLMs 的数学规范和恢复模型参数经验估计的拟合过程。然而,在这两篇文章中,我们都假设我们对所拟合的 GLMs 的参数模型规格有很强的信心。例如,假设我们有一个特性-结果关系,其中有 10 个特性的结果是伯努利分布的。我们可以拟合指定 11 个系数(1 个截距项,10 个特征中的每一个都有一个系数)的逻辑回归模型,而不需要特征或联合相互作用项的任何变换。只要问题的模型说明是正确的,逻辑回归模型将只返回“正确的”结果和推论。这些事实上是非常严格的参数假设。

然而,现在让我们假设我们不愿意对我们对模型规范的理解做出如此严格的参数假设。事实上,让我们假设我们根本不愿意对模型规范做任何假设。我们只是举手高呼“我们不知道模型规范是什么,我们也不愿意对它做任何假设!”。我们希望使用一种方法来大大放松对上述假设的需求。

有一类被称为“通用逼近器”的方法,神经网络属于其中。仅用一个隐藏层和非线性 sigmoid 激活函数,神经网络(理论上)就能够一致地估计任何任意模型规格。这是在某些用例中广泛采用神经网络的主要动机。

在进入神经网络背后的数学之前,让我们先回顾一下 GLMs 的数学知识。

3: GLM 复习

回想一下,广义线性模型(GLM)有三个主要组成部分:

作者图片

现在让我们来研究一下标准和非标准形式的指数离差分布族的概率密度函数(PDF)的参数化。

作者图片

回想一下,对于规范 GLMs,我们有以下属性:

作者图片

(以上工程量的证明和推导见本 GLM 系列第一、二部分*)*

作者图片

4:跳到神经网络

假设我们有一个统计模型:

  • 我们不是指定一个 GLM,而是指定几个相互并行的 glm。这些 GLMs 的平行分组我们称之为“层”。
  • 模型不是由一个“层”组成,而是有几个层。前一层 GLMs 的输出成为下一层 GLMs 的输入特征。

上述模型实际上是标准的前馈神经网络。我们将网络的第一层称为“输入层”,最后一层称为“输出层”,中间的所有层称为“隐藏层”。

让我们假设一个前馈神经网络的例子,在输入和输出层之间有两个隐藏层。下图显示了这种网络的常见图示。每个“节点”(即圆)代表一个变量。请注意,下图并未精确显示每层中存在的节点数量。同样,节点的数量将对应于所述层中“特征”的数量。每个箭头对应一个估计的“权重”或系数。

作者图片

…让我们用数学方法指定每层的输入和输出,以及它们的尺寸:

作者图片

如果我们将每一层都想象成一个局部 GLM,我们可能会对拟合哪种类型的 GLMs 感兴趣?换句话说,我们可能对利用哪些链接功能/激活功能感兴趣?下表列出了神经网络层中使用的常见 GLM 类型。

作者图片

现在让我们来讨论如何将神经网络与数据相匹配。

5:拟合神经网络—带反向传播的梯度下降

在本系列的第二部分中,我们深入研究了将数据拟合到 GLMs 的迭代数值技术。出于计算效率的考虑,标准 GLMs 通常在实践中适合利用牛顿-拉夫森或费希尔评分。然而,神经网络最适合利用梯度下降。我们需要在神经网络的每一层中恢复参数估计。给定网络各层的固有依赖结构,利用梯度下降作为我们选择的迭代数值拟合过程,在数值上将问题简化为动态规划算法(正如我们很快将看到的)。回想一下,对于梯度下降,在迭代步骤“ t+1 ”求解层“ k 中的权重如下:

作者图片

根据以上梯度下降算法的说明,我们需要恢复关于我们的神经网络中每个β系数的的成本函数的第一梯度。从技术上讲,我们可以用数学方法求解并恢复 中任何我们喜欢的 顺序的梯度。然而,仔细检查我们的神经网络,如果我们以“巧妙”的顺序求解梯度,我们可以降低所需的总计算量。可以容易地估计外层中权重的梯度(类似于如何在单个 GLM 中估计系数)。倒数第二层中权重的梯度是最后一层中梯度的函数。倒数第三层中的梯度是倒数第二层中梯度的函数,以此类推。因此,如果我们求解最后一层中的梯度,并通过网络逐层求解梯度,这种梯度求解练习简化为一般的动态规划问题。

在人工智能领域和神经网络文献中,动态编程的这个特殊实例被赋予了自己的特殊名称。我们称之为 反向传播 。随着梯度下降的每一次迭代,我们使用从前到后通过网络向前传播的来自步骤“ t 的权重的当前经验值(即 前向传播 )来计算每一层的变量的值,然后通过从后到前的网络工作来更新步骤“ t+1 的权重。

让我们用数学方法推导出具有两个隐藏层的玩具问题的梯度:

作者图片

…因此,我们对步骤“ t+1 ”的权重更新为三层中的权重:

作者图片

6:计算模拟

下面是一个用玩具数据集拟合前馈神经网络的完整工作示例(从头开始构建)。在下面的代码中,神经网络类对象允许下列可调参数:

  • 隐藏层数
  • 每个隐藏层中的节点数
  • 每个隐藏层的激活函数
  • 小批量
  • 节点丢失正则化

让我们导入我们需要的库:

…以及用于指定具有伯努利分布结果的玩具数据集的函数:

…以及神经网络模型的函数和类对象:

现在,让我们在玩具数据集上拟合神经网络模型,计算结果,并返回曲线下面积(AUC)分数

从上面可以看出,拟合神经网络模型的 AUC 约为 80%

有关上述计算模拟的完整代码/笔记本,请参见下面的 github 链接

7:总结和结论

在本系列的第一部分中,我们提供了规范和非规范形式的常见 GLMs 的全面的数学概述(带有证明)。在第二部分中,我们提供了对典型和非典型 GLMs 的三个重要的迭代数值拟合过程的严格概述:牛顿-拉夫森,费希尔评分和迭代加权最小二乘法(IRLS)。在第三篇也是最后一篇文章中,我们介绍了标准的神经网络模型,以及如何将它们表述为递归 GLMs。

希望以上有见地。正如我在以前的一些文章中提到的,我认为没有足够的人花时间去做这些类型的练习。对我来说,这种基于理论的洞察力让我在实践中更容易使用方法。我个人的目标是鼓励该领域的其他人采取类似的方法。我打算在未来写一些基础作品,所以请订阅 并在媒体LinkedIn 上关注我的更新!

埃尔莫&伯特手套公司

原文:https://towardsdatascience.com/glove-elmo-bert-9dbbc9226934?source=collection_archive---------4-----------------------

使用 Spark NLP 的最新文本分类指南

阿玛多·洛雷罗在 Unsplash 上的照片

机器学习模型最具挑战性的任务之一是找到最佳方式来生成单词的数字表示,以便模型可以在计算中使用这些信息。

在计算机视觉任务中,彩色(RGB)图像中的红色通道总是指红色通道,绿色通道指绿色通道。然而,文本在很大程度上是基于上下文的,因此同一个词可以根据它的用法有多种含义。例如,熊猫可以指可爱而模糊的熊或 Python 数据分析库。

当考虑句子和段落时,这变得更加复杂。请考虑以下情况:

熊猫可爱又毛茸茸。他们不用熊猫数据分析库,因为他们是熊。

现在我意识到这不是一个普利策奖获奖故事的开头,但重点是要引起你对第二句话中的单词 They 的注意。他们是谁?为了回答这个问题,必须有一个内置的内存组件,允许算法生成与第二句中的熊猫相似而与第二句中的熊猫不同的熊猫(第一句中)的表示。

今天,我将通过使用开源自然语言处理库 Spark NLP 的示例,使用最先进的算法来执行文本分类任务,这些算法已经尝试处理上述挑战(以及其他挑战)。

我将比较以下模型的结果

  • 手套
  • 埃尔莫
  • 伯特

什么是 Spark NLP?

在我们进入文本分类挑战之前,先简单描述一下 Spark NLP:

Spark NLP 是一个开源的自然语言处理库,构建在 Apache Spark 和 Spark ML 之上。它提供了一个简单的 API 来集成 ML 管道,并由 John Snow 实验室提供商业支持。Spark NLP 的注释器利用基于规则的算法、机器学习和一些在引擎盖下运行的 Tensorflow 来支持特定的深度学习实现。

我鼓励每个人看一看 Spark NLP 的媒体页面和他们的 Github 以获得大量 NLP 任务的深入教程。

如果您的笔记本已经打开并准备好,您可以通过使用下面的代码安装和导入必要的包来开始使用 Spark NLP。

瞧啊!现在我们准备开始工作了。

数据集

对于今天的挑战,我们将使用在找到的数据集。在这个回购上,你也可以跟着我的笔记本。

首先,您可以阅读。csv 文件,使用以下代码输出数据帧示例:

我们感兴趣的是按目标对我们的文本列进行分类,其中 0 =无灾难1 =灾难。使用下面的代码可以让我们看到目标变量的分布。

1211 个空值,它们对我们的分类没有用处。我们可以使用下面的代码将它们从数据帧中删除。

接下来,我们将经历我用来转换原始文本的预处理步骤。

构建预处理管道

Spark NLP 管道中的每一步都需要某些列作为输入,并产生不同类型的新列作为输出。在这一节中,我们将回顾在整个项目中保持一致的预处理管道。关于所有 Spark NLP 转换器和注释器的完整描述,包括所有可修改的参数,请参见链接。

这是我们管道的入口点,它将我们的原始文本转换成一个文档类型。这个注释器使用包含我们的 tweets 的输入列 text,,并输出一个新列 document 。我还选择了清理模式收缩来去除空白(新行、制表符、多个空格)。

2. 【标记器()】

记号赋予器将我们的句子分解成单独的成分(例如,单词或短语)。这个注释器的输入是文档列,它将输出一个新列令牌*。我修改了参数 SplitChars 来拆分由连字符连接的标记,还修改了参数 ContextChars 来删除标记中的某些字符,如下面的代码所示。*

3. 规格化器()

规范化器是一个文本清理注释器,它接受来自我们的标记列的输入,并输出和规范化的列。参数 CleanupPatterns 用于删除所有标点符号,同时保留所有字母数字字符。

4.【stopwodsguner】)**

停用字词注释器删除基于库的预定义字词列表。这个库是 Spark ML 和 scikit-learn 使用的同一个库,完整的列表可以在这里找到。这些单词通常是非常常用的单词,它们在文本分类问题中不会提供任何效用(例如,and、am、be、do、for、get、no)。

5. Lemmatizer()

词汇化指的是一个规范化文本的过程,其目标是通过将派生相似的单词转换为基本形式(例如,writes、written、written、writer → write )来减少可变性。你会注意到下面 Spark NLP 有一个预训练的词条库ant BNC,它是基于英国国家语料库中的单词。

下面你可以看到预处理管道的完整代码。在最后一个模块中,管道被定义为我们已经介绍过的步骤序列,从原始文本开始,到词条结束。

可视化管道的效果

接下来,我们将通过一个例子来看看原始文本在预处理管道的每一步是如何被转换的。为此,我们将使用下面简要介绍的 Spark NLPs 光管道

光管道是 Spark NLP 专用管道,相当于 Spark ML 管道,但意在处理更少量的数据。它们在处理小型数据集、调试结果,或者从服务于一次性请求的 API 运行训练或预测时非常有用。

下面你可以看到,拟合由 7000 多条推文组成的火车数据帧花了 15.2 秒。

假设我们想要保存这个预处理模型,并将其用于另一个任务。下面,我们使用一个示例文本创建一个 Spark 数据帧,然后使用相同的管道转换它。尽管文本的大小是训练数据帧的 1/7000,但它花费了 1.55 秒(1/10)的时间。

进入光管线。正如你在下面看到的,在 121 毫秒,这增加了将近 13%的速度。****

现在,为了可视化这个预处理管道将如何影响我们的数据帧,我们可以使用下面的代码。

为了便于阅读,我将结果插入了一个表格。

注意,在第 10 行你会看到<逗号>。当我创建一个要点时,我不得不替换实际的逗号,因为它将此解释为另一列。

也就是说,我们可以看到规格化器是如何去掉标点符号的。停用词清理器移除了诸如 as、she、The 等词… 最后,词条整理器将词转换为它们的词条,例如 sat → sit,watching → watch,catch→catch。

到目前为止,我们已经清理了我们的数据帧,但它仍然包含文本。在下一节中,我们将研究各种用于将明文转换成数字表示的预训练嵌入。

单词嵌入

如上所述,本节将简要描述用于转换干净文本的不同嵌入。详细讨论每一个的机制已经超出了本文的范围,但是我将为那些想看得更深一点的人提供原始论文的链接。

  • 手套 (单词表示的全局向量)
  • ELMo (来自语言模型的嵌入)
  • 伯特 (来自变压器的双向编码器表示)

单词嵌入生成单词的多维向量表示。目标是为具有相似含义的单词生成相似的表示。比如海啸、飓风、龙卷风可能有类似的表示,但是龙卷风呢?这就是语境重要性的一个例子。Twister 可以指游戏或龙卷风,但是游戏和龙卷风肯定不应该有类似的表示。让我们快速看一下每个模型是如何创建嵌入的。

根据创造者的说法,手套是:

本质上是具有加权最小二乘目标的对数双线性模型。该模型背后的主要直觉是简单的观察,即单词-单词共现概率的比率具有对某种形式的意义进行编码的潜力

考虑以下我们的目标 灾难无灾难 和四个单词(风、损害、汉堡、驾驶)的同现概率的虚构示例。对此的解释是,比率为 1 意味着分子P(k |灾难)和分母P(k |无灾难)之间没有差异。随着值变得大于 1,它与 灾难 相关联的概率增加。反之,随着数值变得小于 1,它与 灾难 相关联的概率增加。

从我们的例子来看,伤害与我们的目标 灾难 关联最强,而汉堡与目标 无灾难 关联最强。驱动的都接近于 1,意味着与任一目标都没有强关联。

GloVe 的一个局限性是,它没有考虑到单词在什么样的上下文中使用。考虑这两句话:

  • 喜欢开着我的敞篷车,头发上带着
  • 那么大,我的敞篷车就这么飞走了!

ELMo 的创造者找到了一种方法来解决这个问题,从而产生了语境化的单词嵌入。这里,没有生成固定的嵌入。取而代之的是,在分配嵌入之前,先读取整个句子。使用双向 LSTM,ELMo 学习下一个和上一个单词。

GloVe 和 ELMo 都是在无人监督的情况下对大量文本进行预训练的。一个关键的区别是,使用 GloVe,我们将学习到的向量用于一些下游任务。对于 ELMo,我们使用学习向量预训练模型作为一些下游任务的组件。

如果 NLP 的研究人员不那么喜欢布偶,我认为比 BERT 更好的名字应该是 Frankenstein,因为它包含了许多最近的突破。为了获得非常详细和有用的指南,我鼓励你看看这篇文章。

BERT 建立在最近在 NLP 社区兴起的许多聪明想法的基础上——包括但不限于半监督序列学习(由 Andrew Dai 和 Quoc Le)ELMo(由 Matthew Peters 和来自的研究人员和UW CSE)ulm fit(由 fast.ai 创始人和 Sebastian Ruder)OpenAI 转换器(由 OpenAI 研究人员、Narasimhan

尽管 ELMo 使用双向 LSTMs,但是它连接正向和反向模型的事实限制了表示同时利用两种上下文的能力。

伯特使用了一个掩蔽语言目标,意思是单词被随机隐藏并被一个掩蔽所取代。使用一个变换器,然后使用它周围的非屏蔽单词(左右)来预测屏蔽单词。

在下一节中,我们将比较这些模型的嵌入如何用于将灾难非灾难进行分类。

结果

在公布结果之前,我想花点时间介绍一下所使用的分类器。 ClassifierDL 是由 John Snow Labs 在 TensorFlow 内部构建的通用分类器,支持多达 100 个类。我设置的关键参数是:

  • 学习率(0.001)
  • 批量大小(8)
  • 最大训练次数(5)

还值得注意的是,我使用以下方法将原始数据帧分成训练集和验证集:

  1. 手套

下面你可以找到完整的管道,它是我上面描述的预处理管道的扩展。如您所见,GloVe word 嵌入被用作另一个 Spark NLP 注释器 SentenceEmbeddings 的输入,然后使用 ClassifierDL 进行分类。

然后使用下面的代码对验证集进行预测,预测的示例显示在下面的表中。

在显示的十个预测中,一个错误完美地突出了手套嵌入的局限性。由于缺乏上下文,我想要一些海啸外卖被归类为灾难。

使用 sklearn,我们可以看到手套嵌入可以很好地分类我们的文本。事实上,以 81%的准确率,它做得相当不错!

2.埃尔莫

接下来,让我们看看 ELMo 嵌入是否能够提高分类精度。要使用预训练的 ELMo 嵌入件,只需将以下部件插入上述管道,作为手套嵌入件的替代品。

使用上面所有相同的代码,对验证集进行了预测,如下所示。这里我们看到 ELMo 能够学习手套漏掉的单词海啸的上下文。干得好埃尔莫!

尽管如此,模型精度仅提高了 1%。

3.伯特

最后,让我们看看 BERT 嵌入在分类任务中的表现。就像我们上面做的一样,简单地把下面的插入同一个点。

再次展示了验证集的预测示例。有趣的是,我们看到 BERT 并没有正确地对句子进行分类,见见 Brinco 你自己的地震和海啸预警信标。

不过,这次我不得不站在伯特一边。在我看来,这条推文描述的是一个灾难探测系统,而不是一场灾难。

无论哪种方式,BERT 嵌入的最终结果都没有提高 ELMo 所达到的精度。

我们学到了什么?

今天我们讨论了几个使用 Spark NLP 进行文本分类的例子。我们重点介绍了 3 个单词嵌入模型,提供了如何将它们包含在您自己的分类任务中的分步说明:

  • 手套
  • 埃尔莫
  • 伯特

虽然结果变化不大,但我们看到了一些不同嵌入模型如何工作的例子。具体来说,我们能够看到手套嵌入缺乏背景。它无法区分海啸、餐馆和真正的灾难。

这个项目专注于单词嵌入。在未来的帖子中,我们将探索 Spark NLPs 句子嵌入选项,如通用句子编码器(USE)和 BERT 句子嵌入。

感谢阅读!

有用的资源

NER 和伯特在 Spark NLP

使用 Bert 和通用语句编码器在 Spark NLP 中进行文本分类

如何在两周内开始使用 spark NLP

图示变压器

可视化神经机器翻译模型(注意 Seq2seq 模型的机制)

插图作者伯特·埃尔莫等人(NLP 如何破解迁移学习)

语言建模二:ULMFiT 和 ELMo

单词嵌入(第二部分) :直觉和(一些)数学来理解端到端手套模型

手套研究论文解释

原文:https://towardsdatascience.com/glove-research-paper-explained-4f5b78b68f89?source=collection_archive---------15-----------------------

手套模型背后数学的直观理解和解释

图片来自 Unsplash

继我的 word2vectors 研究论文讲解 博客之后,我又拿起 GloVe 研究论文【Pennington 等人】来讲解我对一篇非常详细而全面的研究论文的理解。

GloVe 代表Global****Vectors其中 Global 是指语料库的全局统计,Vectors 是单词的表示。早期的单词嵌入方法,如 LSA,word2vec,能够学习单词之间的句法和语义关系,但其起源尚不清楚。手套模型旨在明确归纳单词向量中的规则,并找到单词之间学习关系的来源。

1。手套型号概述

GloVe 是一个全局对数双线性模型**。嗯,我相信你想知道术语' '全局对数双线性' '是什么意思。全局是指训练语料的全局统计。对数双线性是指输出的对数是两类字向量乘积的线性回归。在手套的情况下,两种类型是单词向量(w)和上下文向量(w^).如下所述,手套模型结合了两种广泛采用的用于训练单词向量的方法。**

1.1 矩阵分解

这些方法分解单词-单词或文档-术语共现矩阵。哈尔(语言的超空间模拟)【隆德&伯吉斯】、 LSA (潜在语义分析)【兰道尔、福尔茨、&拉哈姆】是使用矩阵分解的流行模型。特征值分解用于方阵,奇异值分解 (SVD)用于矩阵分解的矩形矩阵。在词-词矩阵中,行代表词,列代表上下文词。矩阵 Mᵢⱼ中的值表示特定单词 Wᵢ在 Wⱼ.上下文中出现的次数在文档术语矩阵中,行代表单词,列代表文档。一行表示特定单词在所有文档中的分布,一列表示该文档中所有单词的分布。

矩阵分解方法通常包括以下步骤。

  1. 为每个单词定义上下文,并生成单词-单词或文档术语矩阵 m。
  2. 按行、列或长度规范化矩阵中的值。
  3. 删除方差较小的列,以降低矩阵的维数。
  4. 对 M 进行 SVD 矩阵分解,生成 U,S,V 矩阵。
  5. 在通过取第一个 r 以降序对矩阵 M 的奇异值进行排序之后,< R (rank of matrix M), low rank of a matrix M can be obtained. Product of low rank matrices U^, S^ and V^ is close approximation to the original matrix M.
  6. Vector of a word Wⱼ is the jᵗʰ vector from reduced rank space matrix U^.

In such methods, the most common words in the corpus such as (贡献了单词之间不成比例的相似性。出现在“The”、“and”上下文中的单词 Wᵢ和 Wⱼ导致比其真实相似性得分更大的相似性得分。类似地,Wᵢ和 Wⱼ不经常出现在“the”、“and”的上下文中,但具有真正的相似性,它们的相似性得分会更低。诸如煤**【t . Rohde 等人】的方法通过使用基于矩阵的相关性归一化来克服这个问题。当使用基于熵的归一化时,在所有上下文或文档中出现的单词,例如“the”、“and”,将具有高熵。原始计数用高熵项归一化,导致矩阵中这些项的高值缩小。这解决了向单词相似性分数添加不成比例的度量的问题。**

1.2 基于窗口的方法

这些方法在局部上下文窗口上工作,而不是使用语料库的全局统计。[Bengio 等人]中的语言模型训练神经网络,神经网络又训练单词向量表示。该模型以 N 个单词的过去历史和预测下一个单词作为语言建模的目标。因此,该方法中的每个示例都是作为输入的单词的局部窗口,而输出是下一个单词。后来 word2vec 模型【Mikolov et al .】如 skip-gram 和 CBOW 解耦语言建模,训练单隐层神经网络。更详细的了解,可以去翻翻 我之前的文章 就可以了。

与矩阵分解方法相比,这些方法没有利用可用的全局统计,导致单词的次优向量表示。通过使用跨语料库的重复局部窗口,可以减少模型的训练时间和复杂度。

2。手套模型背后的详细数学运算

接下来是你们都期待阅读的部分。理解任何算法背后的数学是非常重要的。它有助于我们理解算法的公式和掌握一个概念。也就是说,让我们定义一些符号。

x 是共现矩阵(单词-单词),其中 Xᵢⱼ是单词 Wⱼ在单词 Wᵢ.的上下文中的计数上下文对一个特定的单词意味着什么?单词周围的上下文可以被定义为由过去的 N 个单词和未来的 N 个单词组成的对称上下文。不对称上下文只包含过去的 N 个历史单词。简单计数或加权计数可用于计算矩阵中的值。简单计数将 1 作为出现次数。在加权计数中,1/d 用作出现次数,其中 d 是与给定单词的距离。使用权重背后的动机是,作为有意义的上下文,与给定单词距离较近的上下文单词比距离较远的单词更重要。

iᵗʰ行-eqⁿ的共现值(1)

在 Eqⁿ (1)中,“Xᵢ”是在“Wᵢ.”这个词的上下文中出现的所有词的总和

Eqⁿ (2)

在 Eqⁿ (2)中,p 是共现概率,其中 Pᵢⱼ是单词 Wⱼ在单词 Wᵢ.的上下文中出现的概率

GloVe 建议根据概率而不是原始计数来寻找两个单词之间的关系。通过寻找与一些探测词 (Wₖ).)的共现概率来检查两个词(Wᵢ和 Wⱼ)之间的关系

假设我们有两个词,Wᵢ是',Wⱼ是'蒸汽,还有一些探测词 Wₖ是'固体'、'气体'、'水'、'时尚'。从基本的理解中,我们知道“固体”更多地与''有关(Wᵢ)and“气体”更多地与'蒸汽 ' (Wⱼ)有关,而时尚与''和'蒸汽'都无关,而水与'冰''和'蒸汽'都有关现在我们的目标是在探测词中找到给定词的相关词。

表 1: 来自 60 亿令牌语料库的同现概率(来源——GloVe 研究论文)

根据表 1,对于作为“固体”的探测词(Wₖ),p(固体|冰)是“固体”在“冰”的上下文中出现的概率,是(1.9*10^–4)大于 p(固体|蒸汽)。P(k |冰)/P(k |蒸汽)之比是> > 1。对于探测词‘气’,比率为<<1. For probe words ‘water’ and ‘fashion’ the ratio is nearly equal to 1. The ratio of co-occurrence probability distinguishes words (solid and gas) which are more relevant to given words than irrelevant words (fashion and water). The words having ratio nearly equal to 1 either appear in the context of given words or not, hence causing no impact in learning relationship between given words. This proves 的同现概率比率 是学习词表征的起点。

Pᵢₖ/Pⱼₖ的同现概率比取决于三个词 Wᵢ、Wⱼ、Wₖ.函数 F 的最一般形式可以在单词和上下文向量上定义如下。

Eqⁿ (3)

其中 w ∈ Rᵈ是单词向量,w∞∈rᵈ是上下文向量。Eqⁿ (3)的右侧是从训练语料库中获得的概率。尽管 f 函数有大量的可能性,但它应该对存在于 Pᵢₖ/Pⱼₖ.的信息进行编码目标词 Wᵢ和 Wⱼ之间的关系可以通过向量差来获得,因为这些向量来自 d 维的线性向量空间。因此等式变成了,

Eqⁿ (4)

现在,方程的右边是定标器,而 F 的输入是 d 维向量。f 可以被复杂的神经网络参数化,这最终将打破向量空间中的线性结构。为了避免这种情况,我们可以取 F 的输入的点积,这样可以防止向量维数与其他维数的混合。

Eqⁿ (5)

单词和上下文单词可以相互交换,因为出现在“ice”上下文中的“solid”等同于出现在“solid”上下文中的“ice”。因此 w ↔ w 和 X ↔ Xᵀ的替换可以在 Eqⁿ完成(5)。基本上,我们将左边的输入改为 f,然后希望对 Eqⁿ的右边产生类似的影响(5)。这也被称为保持两个组之间的结构相似性(同态函数)。我们在 Eqⁿ (5)的左手边有组 g,用减法作为组运算,在右手边有组 h,用除法作为组运算。现在,当我们替换 w ↔ w 和 X ↔ Xᵀ时,为了保持结构的相似性,g 中两个向量的相减应该反映 h 中这两个字向量的相除。假设 X= wᵢᵀwₖ,Y= wⱼᵀwₖ ∈ G,z =(x y)。函数 F 在组(R)和(R>0)之间应该是同态的。根据同态的定义,如果 G 中的 Z = X-Y 减去 op,那么在组 HF(Z)= F(X)÷F(Y)但是 Z = X-Y 因此我们得到 F(X-Y)=F(x) ÷ F(y)。****

Eqⁿ (6)

那么函数 F 应该是什么呢?你猜对了,应该是指数函数。F (x)= e ˣ.比较 Eqⁿ (5)和 Eqⁿ (6),我们得到,F(wᵢᵀwₖ)=Pᵢₖ = Xᵢₖ / Xᵢ.因此,取两边对数,我们得到,*

Eqⁿ (7)

Eqⁿ (7)在单词和上下文方面展示了对称性,除了术语 log(Xᵢ).由于这个术语独立于 Wₖ,我们可以认为这是 bᵢ的偏见术语。再加上一个偏差项 bₖ,我们得到

Eqⁿ (8)

由于 log(x)在 0 附近发散,我们可以在 log(Xᵢₖ上使用加法移位,使得对数的输入总是≥1,

Eqⁿ (9)

Eqⁿ (9)类似于同现 矩阵的对数的分解,这是 LSA 算法背后的主要思想。但是上面的等式有一个问题。如果我们使用平方误差函数来定义成本函数,它将对矩阵中的所有项给予相同的权重,即使对于值接近 0 的罕见频率项也是如此。这样的术语很吵,携带的信息也不多。因此,加权最小二乘法可以用作手套模型的成本函数。

Eqⁿ (10)

注意,加法移位已经在 Eqⁿ (10)所示的矩阵 x 上完成。j 是我们想要在具有词汇大小的共现矩阵上最小化的成本函数。f(Xᵢⱼ)给矩阵中的每一项加权。wᵢ是单词向量,wⱼ是上下文向量。bᵢ和 bⱼ是每个向量的偏差项,Xᵢⱼ是共生矩阵中的项。

现在问题是如何选择函数 f,它应该遵循一定条件。f(0)=0,f 应该是非递减的,并且对于 x 的大值,f(x)不应该非常高,因为不应该过度加权频繁出现的单词。来自 Eqⁿ的 xₘ(11)与图 1 中的 Xₘₐₓ相同。在用 Eqⁿ的 Eqⁿ (11)代替 f(xᵢⱼ(10)后,我们得到手套模型的最终成本函数。然后,使用优化器对一批训练样本训练模型,以最小化成本函数,从而为每个单词生成单词和上下文向量。

Eqⁿ (11)

****图 1-α= 3/4 的权重函数。(来源——手套研究论文)

最后,我们完成了手套模型的完整推导。到目前为止,我们所有人都取得了很大的成就!!!现在,如果您想找出 GloVe 模型与 skip-gram (word2vec 模型)之间的关系,并理解 GloVe 模型的整体复杂性,您可以浏览接下来的部分。在这些部分之后,手套模型的实验和结果被讨论。

3。手套和 Skip-Gram 之间的等效性(word2vec 模型)

GloVe 模型基于全局共现矩阵,而 skip-gram 通过局部窗口扫描,并且不考虑全局统计。这两种方法可以被认为是训练单词向量的两种不同的思想流派。本节找出了 GloVe 和 skip-gram 之间的相似性,即使乍一看这两种类型的模型有不同的解释。

让我们定义跳格模型,其中 Qᵢⱼ定义单词 j 出现在单词 I 的上下文中的概率。Qᵢⱼ是给定 Wⱼ的上下文单词的概率分布,并且可以被认为是 softmax 函数。

Eqⁿ (12)

这里,wᵢ和 wⱼ分别是跳格模型的语境向量和词向量。skip-gram 模型的目标是最大化训练语料上所有局部窗口扫描的对数概率。通过由局部窗口生成的示例,经由随机/在线发生训练,但是全局目标函数可以在来自语料库的所有局部扫描上公式化为

Eqⁿ (13)

为了使成本函数为+ve,当 Qᵢⱼ值在 0 和 1 之间时添加负号,并且该值范围的对数为-ve。上述成本函数和原始跳转程序之间的唯一区别是前者是全局的,后者是局部的。当遍历每个局部窗口时,我们可以将相同的单词-上下文对(Xᵢⱼ)组合在一起,并将它们直接乘以 log(Qᵢⱼ项。

Eqⁿ (14)

我们知道 Pᵢⱼ=Xᵢⱼ/Xᵢ.因此代入 Xᵢⱼ,我们得到

Eqⁿ (15)

Xᵢ独立于 j,所以它可以在 j 上求和之外。H(Pᵢ,Qᵢ)是 Pᵢ和 Qᵢ.概率分布之间的交叉熵注意,在交叉熵公式中考虑了负号。代价函数变成交叉熵误差的加权和,权重为 Xᵢ.上述目标函数可以解释为全局跳过程序的目标。使用交叉熵作为误差度量有一定的局限性。p 是长尾分布,当使用交叉熵作为误差度量时,不太可能/罕见的事件具有较高的权重。此外,Q 必须用词汇 V 上的求和来归一化,这在使用交叉熵时是一个巨大的瓶颈。因此,可以使用不同成本误差度量来代替 Eqⁿ (15)中的交叉熵,其中之一是最小平方目标。q 中的分母项可以通过仅取分子项 Q^.来忽略,新的成本函数被定义为,

Eqⁿ (16)

这里,pᵢⱼ = Xᵢⱼ,Qᵢⱼ= exp(wᵢᵀ * wⱼ)是非正态分布。与 Q^ᵢⱼ相比,Xᵢⱼ采用较大的值,导致优化中的大梯度和大步骤,导致模型的不稳定学习。因此,使用对数的平方误差。

Eqⁿ (17)

代替 Xᵢ,f(Xᵢⱼ)被用作权重函数,如图 1 所示。方括号中的项可以颠倒,没有任何符号变化。Eqⁿ (17)的成本函数与 Eqⁿ (10)的 GloVe 模型的成本函数等价,这表明 skip-gram 模型最终基于语料库的共现矩阵,并且与 GloVe 模型具有相似性。

4。手套模型的复杂性

手套模型的复杂性可以从 Eqⁿ (10)的成本函数中找到。它取决于共生矩阵中非零元素的总数。求和在 I 和 j 上运行,vocab 大小为 V。手套模型的复杂度不超过 O(|V|)。对于几十万字的语料库,|V|超过几十亿。因此,为了获得模型的精确复杂度,可以对 x 中非零项的总数设置更严格的界限。共生矩阵 Xᵢⱼ中的项可以被建模为单词 j 和上下文 I 的频率等级(rᵢⱼ)的幂律函数

Eqⁿ (18)

语料库|C|中的单词总数与共现矩阵 x 的所有项的总和成比例

Eqⁿ (19)

矩阵中的所有元素,无论是单词 I 还是上下文 j,都可以通过将矩阵中的所有项(单词、上下文)放在一起考虑,从 X 中获得其频率排名。|X|是矩阵中任何单词/上下文的最大秩,与矩阵中非零元素的数量相同。ₓ,α是一个调和级数,比值为α,元素个数为|X|。通过将 Xᵢⱼ设置为其最小值 1,Eqⁿ (18)可以获得频率秩 r 的最大值。因此我们得到,|X|=k ^( /α)。在 Eqⁿ (19)中使用这个,我们得到

Eqⁿ (20)

使用广义调和数(Apostol,1976)在右侧展开 H 项,我们得到:

Eqⁿ (21 岁)

其中ζ (α)是黎曼ζ函数。当|X|很大时,两项中只有一项是相关的,这取决于我们得到的是α>1 还是α<1. Hence we finally arrive at,

Eqⁿ (22)

Authors of GloVe observed that Xᵢⱼ is well modelled by setting α=1.25. When α>1 |x|=o(|c|^0.8).因此,该模型的总体复杂度比 O(|V|)好得多,并且略微好于用 O(|C|)缩放的原始 skip-gram 模型。

5。实验

在以下三个 NLP 任务上测试训练的手套单词向量。

一、词语类比

任务是找到单词 d,它回答了“a 对于 b 就像 c 对于”这样的问题。数据集包含句法和语义问题。为了找到单词 d,根据余弦相似性,预测最接近(Wᵇ− Wᵃ+ Wᶜ)的 Wᵈ作为输出。

二。单词相似度

任务是按照相似性的降序排列与给定单词相似的单词。Spearman 等级相关用于测量模型的性能。

三。命名实体识别(NER)

任务是为语料库中的每个标记分配实体类型。CoNLL-2003 英语基准数据集有四种实体类型,即人员、位置、组织和杂项。连同记号特征一起,从手套模型训练的词向量作为输入被添加到 NER 模型,以生成实体类型的概率分布。

6。手套模型训练详情

手套模型在五个不同的语料库上训练:2010 年具有 10 亿个标记的维基百科转储,2014 年具有 16 亿个标记的维基百科转储,具有 43 亿个标记的 Gigaword 5,具有 60 亿个标记的 Gigaword5 + Wikipedia2014 的组合,来自普通爬行的 420 亿个标记的网络数据。

预处理步骤 :-语料库文本小写。斯坦福标记器用于标记化。使用前 400,000 个常用词的词汇来构建共现矩阵。在构造矩阵之前,必须定义单词的上下文。对于相距 d 的单词,使用权重为 1/d 的递减加权窗口来计算矩阵值。GloVe 使用单词的左标记(历史)以及使用单词的左和右标记(历史和未来)的对称上下文来探索不对称上下文的影响。

以下数值在手套模型训练中设定。

对于图 1 所示的加权函数,Xₘ= 100,α=3/4。

优化器 - 阿达格拉德(杜奇等人,2011)初始学习率为 0.05 的优化器用于从 x 随机采样的一批非零项。对于小于 300 维的向量,使用 50 次训练数据迭代,而对于大于 300 维的向量,使用 100 次迭代。

手套模型为每个令牌生成两个向量,W(单词向量)和 W~(上下文向量)。两个向量的和(W+W~)被用作最终向量。

7。结果

一、词语类比

各种模型的单词类比实验结果如表 2 所示。SG 模型代表 skip-gram,CBOW 代表连续词袋模型,SVD 代表奇异值分解。表 2 中显示了语义和句法以及总的准确率百分比。手套型号的性能优于两种 word2vec 型号。在语料库大小 1.6B 和向量维数 300 上训练的手套模型已经实现了近 70%的准确度,超过了 skip-gram 的 61%和 CBOW 的 36%。在 word2vec 模型中,随着向量维数从 300 增加到 1000,语料库大小从 1B 增加到 6B,模型准确性的提高非常显著,但与向量大小为 300 且语料库大小为 1.6B 的 GloVe 模型相比,仍然表现不佳。这表明即使在较小数据集上训练了 300 维的 GloVe 模型词向量,也比在大得多的数据集上训练的 1000 维的 word2vec 模型具有更有意义的信息。与主体大小的增加(从 6B 到 42B 增加了 7 倍)相比,手套模型的准确性增加了小幅度(75%)。

表 2 :词语类比任务的语义、句法和整体模型准确性(Source- GloVe 研究论文)

关于对称和非对称上下文、窗口大小和向量维数的手套模型的准确性如图 2 所示。所有模型都在 6B 语料库上进行训练。在(a)中,上下文是对称的,在向量维数的所有变化中,窗口大小为 10。随着向量维数从 50 增加到 300,句法、语义以及整体准确度稳步增加,之后准确度的增加与向量维数的增加相比可以忽略不计。在(b)中,向量维数在对称上下文窗口大小的所有变化中保持为 100。随着对称窗口大小的增加,与句法相比,所有的准确性随着语义的急剧增加而增加,这表明理解语义需要更宽的上下文,而短的上下文对于句法问题就足够了。在(c)中,向量大小在所有非对称窗口模型中保持为 100。类似的行为在(c)中被注意到作为来自(b)的对称上下文。在对称窗口大小为 3 时,语义准确性超过语法准确性,而在非对称窗口中,语义准确性需要 5 个窗口。

图 2 -词语类比模型精度 vs 向量维数、上下文和窗口大小。(来源——手套研究论文)

在图 3 中,显示了不同语料库上的手套模型准确度。在所有训练语料库中保持 300 的向量维数。句法准确率随着语料库规模的增大而稳步提高,而语义准确率却没有这种规律。因此,通过将语料库的大小从 1B 增加到 6B 和 42B,总体准确度没有显著提高。

图 3 -词语类比模型准确率 vs 训练语料库。(来源——手套研究论文)

二世。 词语相似度——各种数据集( WordSim-353 、 MC 、 RG 、 SCEW 和 RW )与其他模型一起用于测试 GloVe 300 维词语向量。通过对词汇表中所有单词的每个向量维度进行归一化来获得相似性得分,然后对归一化向量使用余弦相似性来找到与给定单词相似的前 n 个单词。Spearman 的等级相关系数是根据从相似性得分和人类判断获得的前 n 个单词的等级来计算的。

Spearman 等级相关公式,其中 d =模型预测等级和输出等级之间的差异,n =观察值数量-eqⁿ(23)

在单词相似性任务的各种数据集上测试的各种模型的结果如表 3 所示。在 WS353、MC、RG 和 RW 数据集上, GloVe model 优于 SVD、CBOW 和 SG。在 42B 语料上训练的 GloVe 模型比在 SCWS 数据集上训练的 CBOW 模型提高了 spearman 等级相关性。

表 3 :跨各种数据集的不同模型的单词相似性任务的 Spearman 等级相关性。(来源——手套研究论文)

三。——NER 任务在不同数据集上的模型性能(验证测试集 CoNLL-2003 、 ACE 和 MUC7 )如表 4 所示。****

表 4 :各种模型在不同数据集上的 NER 任务 F1 得分。(来源——手套研究论文)

以上所有模型都是基于 CRF 的,具有不同的特征集。离散模型使用来自斯坦福 NER 模型的特征集,而其他模型使用基本特征集及其经过训练的词向量作为特征。F1 分数与其他数据集的测试数据一起用于 CoNLL-2003 的验证和测试数据集,以比较模型性能。 GloVe 模型在 NER 任务中的表现优于所有其他模型(离散、SVD 和两种 word2vec 模型)。

8。结论

手套模型讨论了两类算法,基于计数的算法和基于预测的算法。手套模型显示这两类方法差别不大,并且最终都使用共现矩阵作为底层概念来训练词向量。GloVe 捕获数据中存在的全局统计和线性子结构。因此 GloVe 是一个全局对数双线性模型在各种下游 NLP 任务上优于这两类模型。

如果你想了解更多关于如何使用 python 实现手套模型的知识,请在评论中告诉我。

9。资源

1原始研究论文——GloVe:单词表征的全局向量:https://nlp.stanford.edu/pubs/glove.pdf
【2】从词汇共现中产生高维语义空间:https://link.springer.com/article/10.3758/BF03204766
【3】潜在语义分析研究论文简介:https://mainline . brynmawr . edu/Courses/cs 380/fall 2006/intro _ to _ LSA . pdf
【4】向量空间中单词表征的高效估计:https://arxiv.org/pdf/1301.3781.pdf【T10

感谢您抽出时间阅读帖子。我希望你喜欢这本书。请在评论中告诉我你的想法。随时联系我关于LinkedInGmail****

在黑暗的浓咖啡中发光,寻找微粒迁移

原文:https://towardsdatascience.com/glow-in-the-dark-espresso-in-search-of-fines-migration-b369a3beee3b?source=collection_archive---------23-----------------------

咖啡数据科学

寻找另一种方式来看待微粒迁移理论

这是我写的第四篇关于微粒迁移的文章。我假设有证据表明,微粒不会通过粉笔实验(T0)和 T2 实验(T3)以及 T4 实验(T5)迁移。

我不打算重新做粉笔实验,直到我的儿子带着黑粉笔回家。我想这可以成为一个有趣的实验,结合用过的咖啡。如果更细小的粒子在整个冰球中运动,黑暗部分的发光会有助于使它们更容易被看到。白垩粉本身的尺寸比 100 微米小得多,所以它是细粉的一个很好的替代品。

目的是在黑暗的粉笔黄昏中,在用过的咖啡渣(直径为 400 微米)上发光。如果细粒迁移发生,它肯定会发生在大的咖啡颗粒上,颗粒之间有更多的空间供细粒迁移。

所有图片由作者提供

回顾一下,浓缩咖啡中的微粒迁移理论是,非常细小的颗粒(微粒)在一次喷射中迁移,然后可能会堵塞过滤器或进入杯中。这种迁移被认为是沟道效应的根本原因之一。

来展示黑暗粉笔在黑暗中的发光效果。

粉笔不容易溶解。有一些研究表明,升高温度会降低溶解度,而升高压力会降低溶解度,但在浓缩咖啡范围内并不多。

在黑暗中发光的颜色通常也不溶于水。

在这两种情况下,干燥地面和随后的液体仍然会让我们看到黑暗粉笔发光。

数据收集

我从 18g 经过筛选的废咖啡渣开始,因此大多数咖啡渣的直径大于 400um。然后我在上面加了 0.62g 的粉笔,我还加了一个金属网筛减少粉笔回流到我的机器里。

我做了粉笔灰,让它在阳光下晒几个小时。

我启动了金快车,然后开枪了。这是一场泥泞的灾难,很可能是因为提取了所有剩下的东西。我怀疑,由于高流量,这很可能是微粒迁移的最坏情况。最初,我想在黑暗中进行这个测试,这样我就可以看到如果微粒真的迁移了,它们是否会发光。

经过一番清理,我开始着手分析冰球。

圆盘分析

出于理智,我想检查一下顶部在黑暗中是否还会发光。因此,黑暗的图像是在一个没有灯光或窗户的房间里用长曝光相机拍摄的。

当我试图把整个冰球取出来时,只有最上面的部分露了出来。完美!冰球的顶部暴露得很好,我在黑暗中拍了张照片。视觉上,没有白色斑点,也没有任何东西在黑暗中出现。

我仔细检查了顶部,除了最顶部的颗粒外,我仍然没有发现任何白色颗粒。

然后我切开那一部分,我仍然没有发现白色斑点,表明没有粉笔穿透冰球。

作为一个健全的检查,我弹出了冰球的另一部分,我没有发现白色斑点的证据。在黑暗中,我没有发现发光的东西。

筛分分析

我拿起最上面的部分,用 400 微米的筛子筛选。有一些粉笔块留在上面,但是很多细小的粉笔颗粒在下面。

我用显微镜观察一些粒子只是为了好玩。

另外,我用烤箱烘干了所有的液体。我在黑暗中也观察了这个,我没有在黑粉笔中看到任何发光的迹象。我也没有看到托盘里有任何白色颗粒。

我刮去残渣,有 0.5 克残渣,相当于 2.77%的提取率。通常在用过的磨碎物中仍有少量残余物需要提取。

超暗测试

我把冰球的底部放在托盘上,我寻找任何白色颗粒,但我没有找到。

我试图用我的厨房灯在黑暗的粉笔中充电发光,但我发现了一个紫外线灯,所以我能够充电并在黑暗中前进。

对于顶部来说,黑暗粉笔中的光芒仍然闪耀,但对于底部,在托盘上展开,什么也没有。我试着拿着灯走了很多距离,但是什么都没有出现。

然后我对残留物做了同样的检查,什么也没发现。

我做了一个实验,试图用黑色粉笔和粗筛过的废咖啡找到微粒迁移的证据,但我没有找到证据。我尝试了多种方法来检测证据,在常规光线和紫外线下进行视觉检查,但我还是没有发现粉笔穿透冰球的任何证据。

结论:没有足够的证据表明微粒会迁移。

很有可能我错了,做了一个糟糕的实验,但是这个实验很简单,其他人可以重复甚至改进这个实验方案。我欢迎这样的测试。

如果你愿意,可以在 Twitter 和 YouTube 上关注我,我会在那里发布不同机器上的浓缩咖啡视频和浓缩咖啡相关的东西。你也可以在 LinkedIn 上找到我。也可以关注我中。

我的进一步阅读:

浓缩咖啡系列文章

工作和学校故事集

个人故事和关注点

乐高故事启动页面

摄影启动页面

使用图像处理测量咖啡研磨颗粒分布

改善浓缩咖啡

断奏生活方式概述

测量咖啡磨粒分布

咖啡萃取

咖啡烘焙

咖啡豆

浓缩咖啡用纸质过滤器

浓缩咖啡篮及相关主题

意式咖啡观点

透明 Portafilter 实验

杠杆机维护

咖啡评论与思考

咖啡实验

GMM:高斯混合模型——如何成功地使用它对你的数据进行聚类?

原文:https://towardsdatascience.com/gmm-gaussian-mixture-models-how-to-successfully-use-it-to-cluster-your-data-891dc8ac058f?source=collection_archive---------4-----------------------

机器学习

GMM 的直观解释和有用的 Python 示例

GMM-高斯混合模型。图片由作者提供。

本文是解释不同机器学习算法如何工作的系列文章的一部分,并为您提供了一系列 Python 示例,以帮助您开始自己的数据科学项目。

故事涵盖以下主题:

  • 高斯混合模型(GMM)属于算法的范畴。
  • GMM 算法如何工作的描述。
  • 如何使用 GMM 进行聚类的 Python 示例。

GMM 属于哪一类算法?

虽然不可能总是对每种算法进行完美的分类,但尝试这样做仍然是有益的。下面的互动图是我试图帮助你看到更广阔的机器学习领域。

确保点击👇在不同的类别上对进行放大并揭示更多的

请注意,在许多情况下,相同的算法可以用于解决多种类型的问题。例如,可以使用神经网络进行分类、回归,并作为强化学习的一部分。

机器学习算法分类。由作者创建的交互式图表。

如果你喜欢数据科学和机器学习 ,请 订阅 每当我发布一个新的故事,你都会收到一封电子邮件。

由于高斯混合模型(GMM)用于聚类,它们属于机器学习的无监督分支。

您可能已经知道,非监督技术(尤其是聚类)通常用于分段分析,或者作为一种在数据集中查找观察值之间的相似性/差异性的方法。这不同于监督学习模型,监督学习模型通常用于进行预测。

GMM 算法的解释

聚类算法的类型

并非所有的聚类算法都是一样的。不同的聚类算法对如何最好地对数据进行聚类有不同的想法。有 4 个主要类别:

  • 基于质心的 —使用欧几里德距离将每个点分配到最近的聚类中心。例:K-表示
  • 基于连通性的 —假设附近的对象(数据点)比远处的对象更相关。例如:层次凝聚聚类(HAC) 。
  • 基于密度的 —将集群定义为由低密度区域分隔的密集空间区域。他们擅长寻找任意形状的星团。示例:带噪声的应用程序的基于密度的空间聚类(DBSCAN) 。
  • 基于分布的 —假设数据中存在指定数量的分布。每个分布都有自己的均值(μ)和方差(σ ) /协方差(Cov)。示例:高斯混合模型(GMM)。

注意,方差用于单变量分析,协方差用于多变量分析。本文中的示例使用多元设置(多重分布/聚类)。

GMM 简介

正如您可能已经想到的,高斯混合模型假设您的数据遵循高斯(也称为正态)分布。因为在您的数据中可以有多个这样的分布,所以您可以指定它们的数量,这实际上就是您想要的集群的数量。

此外,由于单独的分布可以重叠,因此模型输出不是将点硬分配给特定的聚类。该点属于所述分布是基于概率的。比方说,如果点 A 属于“聚类 0”的概率为 0.6,属于“聚类 1”的概率为 0.4,那么模型将推荐“聚类 0”作为该点的标签(因为 0.6 > 0.4)。

为了进一步帮助解释,让我们看一些图表。

  • 下图显示了 GMM 确定的 4 个澳大利亚城市集群。请注意,每个聚类都有自己的均值(中心)、协方差(形状)和大小。此外,不同的集群(紫色、蓝色和绿色)之间有明显的重叠。

高斯混合模型(GMM) —澳大利亚城市的 4 个集群。图片由作者提供。

  • 如前所述,分类标签分配是基于挑选属于特定分类的特定数据点的最高概率。然而,这并不意味着该点肯定是该集群(分布)的一部分。
  • 看看当我们要求模型为上面找到的分布生成新的数据点(样本)时会发生什么:

高斯混合模型(GMM)-为 4 个分布生成 10,000 个新样本。图片由作者提供。

  • 由于分布的重叠性质,你会得到一些混在蓝点中的紫色点,以及一些混在蓝点和紫色点中的绿色点。因此,GMM 可以被描述为一种软聚类方法,其中不存在硬决策边界来分离不同的聚类。

期望最大化(EM)

为了理解 GMM 在实践中是如何工作的,我们需要看看期望最大化(EM)算法。EM 使用迭代方法来计算和重新计算每个聚类(分布)的参数,即平均值、方差/协方差和大小。

我不会对每一步中发生的事情进行复杂的数学计算。相反,我将给你一个直观的解释,从下面的图表开始,以便于形象化:

高斯混合模型(GMM) —寻找 4 个聚类的迭代过程。图片来自作者。

开始时,该模型用一组参数初始化指定数量的聚类,这些参数可以是随机的,也可以是用户指定的。智能初始化选项在某些实现中也是可用的(例如, sklearn 的 GMM 实现默认使用 kmeans 来初始化集群)。

对于上面的图表,我已经指定了我自己的一组平均值(起始中心)来初始化聚类,这帮助我创建了一个更好的可视化。与随机初始化相比,它还加快了收敛速度。

然而,你必须非常小心初始化,因为 GMM 的最终结果往往是非常敏感的初始参数。因此,建议使用智能初始化或随机初始化多次,然后选择最佳结果。

因此,初始化聚类后,我们就可以使用均值(μ)、协方差(Cov)和大小(𝜋)了。

  • 期望(E 步骤) —对于每个数据点,计算一个“责任” r ,简单来说,就是该数据点属于一个聚类 c 的概率。这是针对每个集群的每个点进行的。
  • 最大化(M 步) —然后使用“责任”来重新计算每个聚类(分布)的平均值、协方差和大小。到了这一步,你也可以把“责任”当成一个砝码。数据点属于一个聚类的可能性越小,它在μ、Cov 和𝜋.的重新计算中的权重就越小在上面的 GIF 图像中,您可以看到簇的位置、形状和大小是如何随着每次迭代而变化的。

E-step 和 M-step 的过程重复多次,直到不能进行进一步的改进,即达到收敛。

GMM 聚类的 Python 示例

设置

我们将使用以下数据和库:

  • 来自 Kaggle 的澳大利亚天气数据
  • Scikit-learn 库根据剪影得分确定我们想要多少个聚类,并执行 GMM 聚类
  • 用于数据可视化的 Plotly 和 Matplotlib
  • 用于数据操作的熊猫和 Numpy
  • 地理坐标,进度条,采集澳大利亚城市坐标的时间

让我们导入所有的库:

然后我们从 Kaggle 获取澳大利亚的天气数据,你可以按照这个链接下载:https://www . ka ggle . com/jsphyg/weather-dataset-rattle-package。

我们接收数据并派生出一个新变量“Location2”,它具有使用 Geopy 提取城市坐标的正确格式。

一段经过修改的 Kaggle 的澳大利亚天气数据。图片由作者提供。

因为我们的原始数据只包含位置(城市)名称而不包含坐标,所以我们将使用 Geopy 的名称来获取这些坐标。请注意,我们在每次调用之间添加了 1 秒钟的睡眠时间,以避免服务器过载。

这是我们得到的回报片段:

澳大利亚城市坐标。图片由作者提供。

接下来,让我们在地图上标出城市:

地图上的澳大利亚城市。图片由作者提供。

GMM 聚类—选择聚类的数量

有多种方法可以选择应该有多少个集群。它可以基于你对数据的了解,或者更多的数据驱动的东西,比如剪影分数。这里有一段直接引自 sklearn 的话:

轮廓系数是为每个样本定义的,由两个分数组成:

a: 一个样本到同一类中所有其他点的平均距离。

b: 样本与下一个最近的聚类中所有其他点之间的平均距离。

单个样品的轮廓系数 s 为:

一组样本的轮廓系数是每个样本的轮廓系数的平均值。

让我们创建多个 GMM 模型使用不同数量的集群和绘图剪影分数。

利用剪影分数确定 GMM 聚类数。图片由作者提供。

一般来说,轮廓分数越高,你的聚类就越清晰。在这个例子中,我选择了 4 个集群,而不是 2 个,尽管 2 个集群设置的分数略高。

请注意,如果您非常熟悉您的数据,在决定聚类数量时,您可能更喜欢使用轮廓分数作为指南,而不是硬性规则。

GMM 聚类—构建模型

现在让我们建立我们的 GMM 模型:

下面是上面的代码打印出来的总结。注意,在显示均值(聚类中心)的情况下,7 次迭代后已经实现收敛:

GMM 模型的输出。图片由作者提供。

现在,让我们在地图上绘制集群:

高斯混合模型(GMM) —澳大利亚城市的 4 个集群。图片由作者提供。

最后,您还可以绘制模型生成的 10,000 个新点的样本,如本文前面的图表所示:

高斯混合模型(GMM)-为 4 个分布生成 10,000 个新样本。图片由作者提供。

结论

高斯混合模型在聚类呈“椭圆形”的情况下非常有用。K-Means 只使用均值(质心)来寻找聚类,而 GMM 还包括方差/协方差。这正是 GMM 在识别非圆形聚类时优于 K-Means 的地方。

一般来说,你可以认为 GMM 是 K-Means 的一个更高级的版本,但是请记住,它并不总是给你优越的结果。这是因为这很大程度上取决于数据的形状和你想要达到的目标。

我希望这篇文章能帮助你更好地理解高斯混合模型。如果想了解更多的备选聚类算法,可以参考我下面的文章。

干杯!👏
索尔·多比拉斯

如果你已经花光了这个月的学习预算,下次请记得我。 我的个性化链接加入媒介是:

https://solclover.com/membership

来吧,改变我的想法

原文:https://towardsdatascience.com/go-ahead-change-my-ai-mind-89f64feab8eb?source=collection_archive---------39-----------------------

公平和偏见

代理作为人工智能公平辩论中缺失的成分。

你曾经试图改变别人的想法吗?你当然有。毕竟,从根本上讲,这是大部分交流的目的。这也非常困难。

当谈到塑造了我们的根深蒂固的政治、宗教或社会信仰时,就更难了,因为它们往往与我们自己的身份联系在一起。许多信念甚至是完全无意识的,只能通过间接手段引出。没有人知道我分发的工作申请是否会因为我的种族或性别而受到不同的对待,因为我交给的人可能甚至没有意识到他们自己的偏见。如果是的话,他们很容易隐藏。以持续、持久的方式改变一个人的想法需要多年的时间和奉献,尤其是当一种信仰根植于某人的情感经历时。

人工智能系统并非如此。尽管存在缺陷和偏见,但人工智能系统与人类决策系统的一个区别在于,暴露它们的偏见并改变它们的想法相对容易。

如果你想发现某人在评估求职者时的偏见,正确的方法可能是给他们数千份申请,根据你寻求的属性,对照所有其他属性,审查和衡量结果的统计差异。虽然当有足够多的申请人通过标准化流程时,这通常会在团体层面进行,但对于任何单个决策者来说,这是不可能的,这使得很难进行干预,除非是在政策层面。你不可能让一个人审查成千上万份申请,然后得到有统计学意义的结果。你不能问决策者他们的偏见,因为他们可能没有意识到这些偏见,或者他们可能有隐藏这些偏见的既得利益。

另一方面,人工智能系统可以处理成千上万的测试样本。事实上,正是这种可伸缩性使它们成为如此多审查的对象:很容易发现它们,并且通过增加样本大小,任何缺陷通常都可以用可接受的 p 值发现。这也是一件好事,因为它使我们能够深入研究那些有可能以各种方式对人们的生活产生巨大影响的系统。

但是这种可用性偏差并不经常被认识到:因为类似的偏差研究很难在人身上进行,所以它们很少被执行。我们听到的许多关于人工智能偏见的叙述正是因为这是我们可以衡量的,而影响当今世界的绝大多数决策系统都是人类的,不透明的,经得起统计审查。

当我们在人工智能系统中发现偏差时,我们可以当场改变他们的想法。我们可以控制他们接触到的数据和事实,以便建立他们的知识库。作为模型设计者,我们可以修改我们将哪些归纳偏差编码到其中,以及它试图优化的成本函数。作为一个社区,我们越来越好地提高了对我们所拥有的相关旋钮的理解。例如,研究表明,用非常 很少的基础陈述,你可以影响一个非常大的神经模型的整个‘信念系统’。您还可以微调 ML 系统做出的权衡,以确保公平的结果,而不牺牲性能。这是很了不起的,尤其是当你把它与几乎不可能对我们基本上无意识的人类认知偏见有任何作用的情况进行对比时。

结果的一致性也有内在的公平性。没有根本原因而改变的决策本质上是不公平的,这就是为什么自动决策系统不一定需要比人类同行表现得更好才能提供更公平的结果,只要它们减少了结果的差异。人工智能不会遭受决策疲劳。

在评估机器学习的公平性和道德含义时,可审计性、可控性和一致性值得占据中心位置。

有些人会说,这里的障碍不是人类决策系统,而是基于规则的系统,这些系统也可以说是一致的、可控的和可审计的。但是这里存在着另一个陷阱:越糟越不公平。一个在任务中表现更差的系统,即使更简单、更容易推理,通常在结果的公平性方面更差。我曾经从事自动语音识别的工作,在早期,这些系统在识别英语口语方面效果不佳。但受影响最大的并不是在美国出生的中年白人男性,他们在完全安静的办公室环境中工作。年轻人和老年人,母语非英语的人,生活在充满挑战的嘈杂的声学环境中的人。以透明性和可检验性的名义争论更粗糙、更简单的模型常常忽略了一个简单的事实,即一个更好的决策系统通常比分布的主要模式更积极地影响“长尾”。事实上,尽管人们对使用越来越大、越来越复杂的语言模型感到担忧,但有强有力的证据表明,语言模型做得越好,它们就越符合人类共同的价值观。

人们实际上可以说,在人工智能系统的基本性能方面所做的工作对公平结果的影响比许多直接针对人工智能公平的文献要深远得多,尽管如果没有今天在这个主题上的大量工作,我们甚至无法评估这种影响。我们在这个领域的更多集体工作应该越来越少地以仅仅揭露他们的缺陷为目标,而是更多地利用我们对人工智能系统的这种代理,以及我们改变他们的想法以实现更公平和更公正结果的前所未有的能力。

(感谢 Ed H. Chi 对本文的宝贵反馈。)

与 OpenFL 联合

原文:https://towardsdatascience.com/go-federated-with-openfl-8bc145a5ead1?source=collection_archive---------22-----------------------

将您的深度学习管道放在联邦 rails 上

介绍

OpenFL 是英特尔开发的用于联合学习 (FL)的开源框架。FL 是一种在分布于多个节点的分片数据集上训练统计模型的技术。此外,由于隐私/法律问题(如 HIPAA 或 GDPR 等法律)、数据集的大小或其他原因,数据可能在不同的分片之间分布不同,并且不能在节点之间移动。OpenFL 旨在解决当数据在组织或远程数据中心之间拆分时所谓的跨筒仓联合学习问题。

OpenFL 旨在为数据科学家提供一个有效且安全的基础设施。OpenFL 的可扩展特性应该使联邦学习领域的研究变得容易和民主化

随着 1.2 版本的更新,OpenFL 团队努力提高框架的可学性,并分离设置联邦和使用它运行 FL 实验的过程。在 OpenFL 团队,我们致力于最小化用户入口点,简化建立联盟的过程,以及注册和运行 FL 实验。

1.2 版 OpenFL 更新引入了用户会话、允许在重用现有连接的同时进行多次后续实验的长期组件,以及开发的交互式 Python API,以简化对单节点训练代码的修改,并为数据科学家提供单节点体验。

轻松处理远程数据

让我们想象一群配备有计算单元并保存唯一数据集的节点。如果一组节点持有的数据允许解决特定的数据科学问题,并且控制这些节点的人愿意合作解决该问题(至少允许对他们的数据进行本地培训),则这样的一组节点可以组成联盟。

让我们想象一下,几个节点所有者同意创建一个联盟,从而使他们唯一的数据集成为虚拟全局数据集的碎片。现在,我们仔细看看最重要的部分——上面提到的数据碎片。数据碎片可能以不同的格式保存,尤其是如果节点属于不同的组织。数据碎片是异构的(这是我们首先要将它们组合在一起的原因),它们在来源、磁盘上的结构、标记模式等方面有所不同。为了促进这种多样性并描述一个将使用所有碎片的单个实验,我们必须选择以下之一:

  1. 实验中的数据加载过程应该有一个 switch-case 逻辑来加载不同的数据碎片。这种必要性不仅打破了实验定义的单节点体验,还意味着数据科学家知道每个数据集碎片的结构。
  2. 数据集碎片所有者同意一个通用的数据结构,并相应地准备他们的数据。尽管实验中的数据加载过程对于所有数据集碎片都是相同的,但它们的所有者必须描述数据读取和转储脚本,并为每个给定的数据接口保留一份数据集副本。

OpenFL 试图通过将数据准备过程包含在联邦设置管道中,从这两种方法中取长补短来解决这个问题。OpenFL 现在为数据集碎片所有者提供了碎片描述符接口。它允许定义数据读取程序,并描述符合统一数据接口的数据采集方法。在不转储数据集碎片的格式化副本的情况下,碎片描述符为联邦中所有节点上的实验提供了单一的数据访问方法。在这个模式中,数据样本只在运行时加载。

总之,分片描述符的引入是为了解决数据异构,并为定义 FL 实验的数据科学家提供统一的数据接口。数据集碎片所有者可以介绍他们的数据读取过程、预处理,如果需要,甚至可以利用差分隐私技术。

主要使用场景

在这一节中,我们将介绍设置一个联邦所需的主要步骤,并使用 OpenFL 进行一个 FL 实验来理解工作流。

成立联合会

我们现在的情况是,有一群数据所有者同意合作解决一些数据科学问题,他们标记的数据集符合这一目的。第一步是在所有将用于联邦模型训练的机器上安装 OpenFL,我们将这些机器进一步称为“合作者节点”。

OpenFL 可以从 PyPI 安装(conda 包和 docker 镜像也是可用的):

$pip install openfl

然后数据所有者需要实现分片描述符 Python 类。

此时,联合参与者必须选择联合中的中心节点,该节点将用作实验服务器,并将从所有协作者节点聚合模型更新。

名为 Director 服务的实验服务器现在应该使用 OpenFL 命令行界面(CLI)在中心节点上启动。它以联邦中的统一数据集格式和中心节点上的开放端口作为参数。

随着导演的运行,其名为使节的‘客户’现在可能在合作者节点上启动。特使也使用 OpenFL CLI 启动,使用配置文件和控制器的网络地址作为参数。上面提到的配置文件应该包含本地 Shard Descriptor 类的导入地址及其参数(如果需要的话)。启动后,特使尝试与指挥者建立 gRPC 连接,如果分片描述符符合统一数据接口,指挥者可能会接受特使加入联盟。

到目前为止,我们有一个星形的节点网络:几个特使连接到主任并等待即将到来的实验。我们称这样的网络为联盟。当控制器关闭时,该联盟可能会主持几个实验并停止存在。

注册一个 FL 实验

此时,数据科学家可以注册他们的实验,以便在联邦中执行。OpenFL 提供了一个单独的前端 Director 的客户端作为 Python API 的一部分来注册实验。数据科学家可以从另一台机器(包括计算资源有限的笔记本电脑)连接到 Director ,并在交互式环境(如 Jupyter 笔记本或 Python 脚本)中定义他们的实验。在下一节中,我们将进一步了解前端 Python API。

几个用户可能连接到同一个 Director ,但是注册的实验是在联邦中一个一个执行的(至少对于 OpenFL v1.2 是这样)。当实验结束时,用户可以检索训练工件:检查点和训练日志。

当一个实验被主任接受时会发生什么

当用户向主管报告 FL 实验时,实验工作空间和用于再现 Python 环境的信息被打包到一个档案中并发送给主管。导演向参与的使者播放实验档案。然后,导演启动一个聚合器服务来编排培训过程。特使启动协作者进程,该进程将根据本地数据训练模型。

绿色块是长期存在的组件。黄色块是为特定实验产生的短命组件。双向箭头是 gRPC 连接。(图片作者)

查看 OpenFL 文档中的详细图表这里和这里。

交互式前端 API

在上一节中,我们从数据持有者的角度调查了与 OpenFL 的交互,现在让我们概述一下数据科学家可以利用所创建的基础设施的方式。

如上所述,OpenFL 提供了一个独特的交互式 Python API,旨在简化 FL 实验。通过这次更新,我们试图将研究人员的界面从建立网络的过程中分离出来,因此定义 FL 实验的努力不会随着联盟中合作者的数量而增加。

定义 FL 实验的努力并不与联盟中合作者的数量成比例

一般来说,前端 Python API 允许用户注册统计模型和训练逻辑,因此可以以联合的方式训练它。下面我们重点介绍在 OpenFL 中所看到的 FL 实验的三个主要部分:

  • 模型和优化器可以以用户喜欢的方式创建和初始化。OpenFL 前端 API 提供了一个模型接口类来注册这些对象。OpenFL 允许使用 PyTorch 或 TensorFlow 2 深度学习框架作为计算后端。模型接口是选择其中一个或者提供支持另一个 DL 框架的插件的地方。OpenFL 本身是 DL 框架无关的。
  • FL 任务是包含训练逻辑的主要单元,描述独立于其他部分的训练程序的独立部分,例如“训练”或“验证”。OpenFL Python API 提供了任务接口类,允许将独立函数改编为 FL 任务。任务必须将模型、优化器和数据加载器作为参数,并可选地返回一些计算的指标,但除了这些约束,它还是一个常规的 Python 函数。
  • **数据加载器。**FL 实验定义的最后一部分是准备数据。OpenFL API 中有一个可子类化的数据接口,它将在 collaborator 节点上适配 Shard 描述符,并为任务提供本地数据。必须解释一下分片描述符和数据加载器之间的区别:分片描述符执行数据读取和预处理例程,每个特使可能有唯一的分片描述符,而数据加载器在数据科学家的环境中每个 FL 实验定义一次,包含扩充和批处理逻辑。

OpenFL 是一个深度学习框架不可知的库

当 FL 实验的所有三个部分都实现时,用户应该利用控制对象来注册实验并监督实验的执行。

联盟对象是主管的客户端的包装器,它帮助将特定的笔记本连接到联盟。连接的联邦对象允许用户检查连接的特使集合,也可以提供一个模拟远程的虚拟碎片描述符。它允许对实验代码进行本地调试,从而提供单节点体验,就好像可以从数据科学家的机器上访问数据一样。

实验对象包装了模型、数据和任务接口,并帮助向给定的联邦报告实验。应该是用来打包本地代码和使用过的 Python 包列表,并发送给 Director 。实验对象还提供了监控已接受实验的状态和检索已训练模型的方法。

将交互式 API 引入 OpenFL 背后的总体意图是允许数据科学家包装他们现有的单节点训练管道,并以最小的努力开始 FL 实验。

摘要

OpenFL 开发致力于为数据科学家创建一个灵活方便的工具,试图简化和加速联邦学习领域的研究。

您可以查看一个使用 OpenFL 以联邦方式在 Kvasir 数据集上训练 UNet 模型的实际示例,以及一个关于如何做的手册。

如果您感兴趣,这里有一个有用的资源列表:

  • OpenFL GitHub 资源库
  • OpenFL 松弛通道
  • OpenFL ReadTheDocs
  • OpenFL 白皮书

照片由 Alina Grubnyak 在 Unsplash 上拍摄

速率度量的贝叶斯 A/B 检验

原文:https://towardsdatascience.com/going-bayesian-testing-rate-metrics-82e872b79175?source=collection_archive---------20-----------------------

入门

如何在没有 p 值和置信区间的情况下运行速率度量的 A/B 测试?

由陈伶俐·桑特兰在 Unsplash 上拍摄

你是否曾经努力向非技术观众甚至你自己解释你的 Frequentist 测试结果(即零假设/替代假设、p 值和置信区间)?你希望在运行 A/B 测试后,你可以说“有 95%的可能性 A 组比 B 组有更好的点击率”,然后就完事了吗?如果是的话,那你就来对地方了,如果不是的话,我们有可爱狗狗的照片,所以你可能会想留下来。

你是一名狗玩具公司 WoofWoof 的数据科学家。营销部门想要开展一个新的数字广告活动,他们正试图决定是否应该在广告中使用柯基犬或哈巴狗的图片。很快,你建议运行一个 A/B 测试,向一组人展示带有 corgi 的版本,向另一组人展示带有 pug 的版本,看看哪一个在点击率方面做得更好。营销部门同意了这一点,于是你开始回忆如何实际分析数据。

我们将介绍运行 A/B 测试所需的理论和步骤,即贝叶斯方法。我们将用 Python 实现一切。

布雷登·安德森在 Unsplash 上拍摄的照片

你需要贝叶斯定理

题目有点露馅了,但是你需要熟悉 贝叶斯定理 。贝叶斯定理为我们提供了一种方法来模拟在观察到新数据后,我们对某事物的先验信念是如何变化的。

Bayes Theorem
 P(A|B) = P(B|A) P(A) / P(B)where
 A, B: events in sample space
 P(A|B): conditional probability of A given B
 P(B|A): conditional probability of B given A
 P(A): probability of A
 P(B): probability of B

以上定义是针对离散变量,对于连续变量是针对概率密度函数定义的。

在我们的例子中,我们关心的是点击率,我们用𝜃.来表示我们将把我们关于𝜃的先验信念表示为𝜋(𝜃)——这是感兴趣参数的先验分布。接下来,运行实验后我们将观察数据,𝛸.似然函数 f(𝛸|𝜃)告诉我们,给定不同的𝜃.值,观察数据𝛸的可能性有多大我们真正关心的是𝜋(𝜃|𝛸),即𝜃.的后验分布这基本上说明了在考虑了我们观察到的数据和我们先前的信念之后,不同的𝜃值的可能性有多大。我们可以用贝叶斯定理得到𝜋(𝜃|𝛸)。

𝜋(𝜃|𝛸) = f(𝛸|𝜃)𝜋(𝜃) / f(𝛸) 
       ~ f(𝛸|𝜃)𝜋(𝜃)where
  f(𝛸): probability density of 𝛸 (can think of it as a normalising constant)

总的来说,我们有

posterior ~ likelihood x prior.

先验:贝塔分布

先验的意思是获取我们对点击率可能值的任何先验知识。如果你不知道,你可以选择一个无信息先验,例如,所有可能的值都是同样可能的。无论是哪种情况,有一点是肯定的:速率度量只能取 0 到 1 之间的值!因此,我们需要一个先验分布来反映这一点,比如 Beta 分布。

贝塔分布有两个参数可以使用,𝛼 >0 和𝛽>0(图 1 中的ab)。让我们看一些图,直观地了解它们如何影响密度函数的形状。

图一。不同参数值的贝塔分布。图片由作者提供。

您可能已经注意到了图 1 中的一个模式。分布的峰值在(𝛼-1)/(𝛼+𝛽-2)——这实际上是分布的模式。此外,𝛼和𝛽越大,模式周围的值就越集中(请看图 1 中的对角线)。

事实上,你可以认为𝛼-1 是成功的次数,𝛽-1 是失败的次数。那么,模式(𝛼-1)/(𝛼+𝛽-2)可以认为是successes / trials。因此,如果我们想要一个先验,给 0.5 左右的𝜃值更多的权重,就像我们做了一个实验,得到 20 个成功(点击)和 20 个失败(没有点击),我们可以选择𝛼=21 和𝛽=21.如果我们想要一个无信息的先验,我们可以选择𝛼=1 和𝛽=1——在这种情况下显然没有模式。

请记住,您的先验越强,即非常大的𝛼和𝛽,我们将需要从它那里转移更多的数据。

可能性:二项分布

可能性告诉我们,在给定不同的𝜃.值的情况下,观察到数据的可能性有多大,𝛸由于我们正在使用比率指标,这意味着我们有试用(我们的数字广告的印象)和成功(点击的广告),所以 二项式 分布非常适合。

提醒一下,当成功概率等于𝜃(通常成功概率表示为p)时,𝜃binomial(𝜈分布对𝜈试验中𝜅成功的概率进行建模。

图片由作者提供。

后路:?

我们选择了贝塔分布作为我们的先验,二项分布作为我们的可能性。我们的后验可能是什么呢嗯…(你可能已经在想象可怕的数学计算了)。

原来我们的后验也是贝塔分布!当然,这不是意外。这种β-二项式先验似然组合经常被选择,因为它们是共轭先验。共轭先验仅仅意味着当你把它们结合起来时,后验分布与先验分布来自同一个分布族。

If
  Prior is Beta(𝛼, 𝛽)
  Likelihood is Binomial(𝜈, 𝜃)
Then
  Posterior is Beta(𝛼 + successes, 𝛽 + failures)
Where
  𝜈 = successes + failures

所以我们需要做的就是选择𝛼和𝛽作为我们的先验,运行我们的实验,收集数据,然后计算我们的后验概率,这也是一个参数为𝛼+successes,𝛽+failures.的贝塔分布轻松点。

我们的 A/B 测试计划是给两组相同的先验,然后使用 Bayes 定理计算它们的后验分布。一旦我们有了后验概率,我们就可以进行有趣的比较,找出并宣布赢家。

测试实现

我们感兴趣的是 A 组(柯基广告)在点击率(CTR)方面优于 B 组(哈巴狗广告)的概率,即

P(corgi CTR — pug CTR > margin)

其中margin可以是 0 或者其他我们关心的值。这基本上是在回答“柯基广告的点击率至少margin大于哈巴狗广告点击率的概率有多大”这个问题?

我们将通过对每组点击率的后验分布进行抽样来寻找答案。该过程如下:

Set N to some big number (e.g. 10000)
Set differences = []for i = 1 to N:
   a_sample = sample a value from group's A posterior
   b_sample = sample a value from group's B posterior
   a_b_diff = a_sample - b_sample store a_b_diff in differencesP(A - B > margin) ≈ % of values in differences that are greater than margin

在我们的实现中,我们将使用矢量化方法,而不是for循环,因为这样更快。

这可能看起来像很多代码,但大部分只是为了创造一些情节。第 23 行到第 35 行是重要的一行,在这里我们从后验抽样并计算差异的分布。

还有 另一种方式 你可以用后验来总结你的实验,这里我们还没有实现。它包括计算差异后验分布的最高密度区间(HDI) (最短区间,使得其中的值的概率等于x%)并检查它是否与实际等价的预定义的**区域****【ROPE】**重叠。例如,我们可以将 ROPE 定义为[-0.005,0.005],这意味着我们认为两组在该范围内的差异可以忽略不计。计算出差异的后验分布后,下一步就是计算 95%的 HDI(实际用多少百分比由你自己决定)。如果人类发展指数没有与我们的绳子相交,我们得出结论,这两个群体是不同的。

他们当中谁最可爱?

由弗洛伦西亚·波特在 Unsplash 上拍摄的照片

A/B 测试正在进行中,市场部已经要求你分析数据。

Corgi group
  Impressions: 9760
  Clicks: 3660Pug group
  Impressions: 9344
  Clicks: 3420

使用上一节中的代码,您可以简单地执行以下操作

GROUP_A = 'Corgi'
GROUP_B = 'Pug'ab_test = BetaBinomialTest(GROUP_A, GROUP_B)
ab_test.update_group_data(GROUP_A, successes=3660, trials=9760)
ab_test.update_group_data(GROUP_B, successes=3420, trials=9344)prob, differences = ab_test.compare(GROUP_A, GROUP_B, margin=0.0)

才能快速得到答案。

左图:差异分布。右图:点击率的后验分布。图片由作者提供。

你回到市场部,让他们知道有大约 90%的可能性 corgi 版本比 pug 版本更好。在这一点上,他们可能会决定 90%就足够了,并与 corgies 合作,或者决定继续实验,以收集更多的数据,并变得更加确定。

其他指标呢?

如果你已经到了这一步,你可能想知道当你想使用贝叶斯 A/B 测试进行非速率度量时会发生什么。有更多的共轭先验分布对,因此可以很容易地使用。如果这些符合你的数据,那么你是幸运的——方法将与我们在本文中看到的非常相似。否则,您可能需要使用贝叶斯推理包,比如 PyStan ,来为您创建后验分布的近似值。

结论

在本文中,我们介绍了使用 Bayes 定理运行速率度量的 A/B 测试的理论。我们已经了解了如何在 Python 中实现测试,并且看到拥有组的后验分布允许我们计算不同问题的概率(不同的margin值)。

我们还得出结论,柯基犬比哈巴狗更可爱,这位作者有偏见(如果你没有注意到,这篇文章中没有哈巴狗的图片)。

更多来自同一作者。

https://medium.com/analytics-vidhya/calculating-using-monte-carlo-simulations-337cff638ac5 https://medium.com/analytics-vidhya/multi-armed-bandits-part-1-epsilon-greedy-algorithm-with-python-code-534b9e2abc9

参考

【1】【贝叶斯定理】维基百科。【在线】。可用:https://en.wikipedia.org/wiki/Bayes%27_theorem.【访问时间:2021 年 2 月 7 日】

【2】巴耶定理。【在线】。可用:http://Galton . uchicago . edu/~ ei chler/stat 24600/讲义/l06.pdf. 【访问时间:2021 年 2 月 7 日】

[3] A .金,“共轭先验解释”,,2020 年 1 月 16 日。【在线】。可用:https://towardsdatascience . com/conjugate-prior-explained-75957 DC 80 bfb。【访问日期:2021 年 2 月 13 日】

[4]约翰·克鲁施克。2010.做贝叶斯数据分析:R 和 bug 教程(第 1 期。由…编辑).美国学术出版社。

超越二进制

原文:https://towardsdatascience.com/going-beyond-binary-cdb70c18a4a4?source=collection_archive---------29-----------------------

了解量子计算的世界⚛

图片由格特·奥特曼提供,来自 Pixabay

什么是量子计算?

让我们考虑一台经典的计算机,它的每一位都处于两种状态之一,T0 或 T1,通常被认为是 T2 或 T3。一个量子比特,更好的说法是一个 量子比特 ,相当于量子计算机。量子位具有一些非常独特和有趣的性质,这使得量子计算成为计算机中最有趣的领域之一。

叠加

与比特不同,量子比特可以处于10的状态,在之间的任何地方🤯!很疯狂,不是吗?这是由于被称为 叠加 的量子粒子的能力,其中这些粒子不是具有单个定义的状态,比如 1 或 0,而是具有成为10的*。*

当一个量子位处于叠加态时,测量它的值,然后 将量子位从它的无限可能状态 坍缩到众所周知的状态01。然后,它保持在该状态,直到复位。

MuonRay 来自博客

纠缠

可以说,量子计算最有趣的现象是两个或更多的量子比特能够成为相互纠缠的。**

在这样的系统中,任何一个纠缠粒子的状态都不能独立于其他粒子的量子状态来描述。这意味着无论您对一个粒子应用什么操作或过程,都会与其他粒子相关联。例如,如果你测量一个粒子并坍缩,那么其他粒子也会坍缩。

好吧,所以它们是基于概率的。但是我们能改变这些概率吗?

是啊!它遵循一个叫做 的量子干涉过程。

量子干涉

量子位元以这种或那种方式坍缩(即坍缩为 0 或 1)的可能性是由量子干涉决定的。干涉会影响一个量子位的状态,从而影响测量过程中某个结果的概率,而这个概率状态正是量子计算的强大之处。

所以我有点掌握它的窍门了…但是我实际上是如何编码的呢?我需要量子计算机吗?

一点也不!微软发布了一个 量子开发套件 (QDK) ,这是一套工具,允许我们在我们的桌面上模拟量子环境

量子环境中的编码

照片由路易斯·戈麦斯从 Pexels 拍摄

虽然我们通常需要下载 QDK 进行开发,但在 Jupyter 环境中测试是最容易的,微软为此专门发布了一个 IPython 内核。

虽然这里也解释了所有的 Jupyter 代码,但我鼓励你去 这个 DeepNote 项目 ,复制它并运行它,因为它包含额外的注释和代码练习。解决了这个问题,让我们开始吧。

QSharp 基础知识

在一篇文章中解释完整的 Q#语言超出了我的能力范围,但是,让我们看看一般的语法来了解这种语言。

在下面的代码块中,使用open命令,一些依赖项被导入到文件中。遵循的命名约定非常类似于 C#。

这些用于整个 Jupyter 笔记本

现在我们可以看看在 Q#中创建函数和变量的语法。在 Q#中,变量是不可变的,这意味着在初始化之后,它们不能被重新赋值,除非被指定为可变的。创建它们的语法类似于您在 javaScript 中看到的,使用了let关键字。

**let varName = varValue;**

注意,变量的数据类型不是在初始化时指定的,而是从给定的varValue中自动推断出来的。

可变变量(值可以改变的变量)可以使用mutable关键字初始化,并使用set关键字重新赋值。

**mutable varName = varValue;
set varName = anotherValue;**

另一个重要的 Q#特性是操作,它相当于其他语言中的函数。操作将特定的数据类型作为输入来返回输出。操作的语法是~

**operation OpName(input1: DType, input2: DType): ReturnDType {
    // body of the operation
    return retVal;
}**

注意,没有返回值的函数的ReturnDTypeUnit,相当于 C#或 C/C++中的void。要了解更多关于 Q#数据类型的信息,请查阅微软官方文档。

下面是一个基本 Hello World 操作的代码,使用 Q#中的[Message](https://docs.microsoft.com/en-us/qsharp/api/qsharp/microsoft.quantum.intrinsic.message)函数,它大致相当于 Python 中的print、C#中的Console.Write和 C++中的std::cout

由于 Q#是一种运行在量子计算机上的语言,执行操作的方式有点不同。我们不是直接执行,而是运行一个 IPYNB magic 命令— [%simulate](https://docs.microsoft.com/en-us/qsharp/api/iqsharp-magic/simulate),后跟模拟操作的名称。

该消息打印在标准输出中

Q#支持基本的数据类型IntFloat等等,以及它们上面的操作符。下面是 Q#中的一个基本加法函数。

为了模拟我们的操作,我们需要在操作名称后输入key=value格式的参数,如下所示。

3 + 5 = 8,对吗?

Q#中的量子测量

如上所述,量子位(更好的说法是量子位)是量子计算机的基本存储单位。这里有一个程序分配一个量子位并返回它的测量值。
返回 Q#中一个量子位的测量值的函数是 M 操作 [M(Qubit) => Result](https://docs.microsoft.com/en-us/qsharp/api/qsharp/microsoft.quantum.intrinsic.m),其中Result是一个内置的数据类型,它给出了OneZero

用于创建和测量量子位的代码

运行这个程序给了我们0的输出,因为量子位在分配后总是处于零的初始化状态。

初始化的量子位总是具有 0 的测量值

Q#中的叠加

叠加态是量子粒子的唯一状态,其值是无限概率的组合。
回想一下,在叠加态下测量一个量子位会将它折叠成两个二进制值中的一个。
一个特殊的量子比特门将一个量子粒子置于叠加态,在 Q#中,就是 H(哈达玛的简称) [H(Qubit) => Unit](https://docs.microsoft.com/en-us/qsharp/api/qsharp/microsoft.quantum.intrinsic.h)

注意,H 变换返回Unit,因为它只是就地改变量子位的状态。

随机数发生器

这意味着我们可以用量子位制造一个真随机数发生器(RNG) !这里面的步骤会是~

  • 分配量子位
  • 将量子位叠加
  • 测量量子位并返回其值。

请注意,为了能够重复使用,量子位需要在每次测量后重置。为此,我们使用测量和复位的组合操作,即[MResetZ](https://docs.microsoft.com/en-us/qsharp/api/qsharp/microsoft.quantum.measurement.mresetz)

此外,我还创建了一个助手函数RunNTimes,它将任意一个函数Unit => Result和一个数字n作为输入,并运行该函数 n 次。

用于创建一位数随机数生成器的代码

n = 100运行nQRNG,得到如下结果~

我们得到几乎等量的 1 和 0,证实了随机性

结论

照片由安娜·阿兰特斯从派克斯拍摄

我们完了!本教程的目的是以一种不需要任何数学资格的方式唤起人们对量子计算的兴趣,此外还为读者提供了使用 Q#和 QDK 迈出量子计算第一步的工具。如果你还没有 我真的鼓励你 看看这里的 Jupyter 笔记本 因为那会给你一些 Q#的实践经验。

为了继续你的量子计算专业知识之旅,我鼓励你查阅微软文档中的以下资源。

学习数学的工具

  • 用于量子计算的线性代数
  • 向量和矩阵
  • 量子位

此外,量子卡式是开始 Q#和量子计算之旅的绝佳方式。

你可以通过 Linkedin 、 Email 或 Github 联系我!

我希望你喜欢这个教程,并拥有美好的一天!

用决策智能超越数据科学

原文:https://towardsdatascience.com/going-beyond-data-science-with-decision-intelligence-88e5ff08cb34?source=collection_archive---------31-----------------------

决策智能是数据科学家在构建道德人工智能系统时需要的技能

布鲁克·拉克在 Unsplash 拍摄的照片

回到 2018 年 3 月,谷歌在任命了他们有史以来第一位首席决策科学家 Cassie Kozyrkov 。首席决策科学家的职责之一是对谷歌的许多员工进行决策智能培训,随着人工智能系统成为谷歌商业模式的一个更加突出的特征,这一系列技能变得越来越重要。在本文中,我想简要概述一下决策智能,以及我认为随着决策智能被更广泛地采用,数据科学家的角色将如何演变。

什么是决策智能

决策智能是一门新的学科,当使用数据实现系统时,它是关于做出好的决策的。有了人工智能系统,决策智能将引导数据科学家询问某个特定的数据是否应该包含在训练数据集中,或者另一个数据是否应该排除在外。这个决定将如何影响模型在现实世界中的表现?数据科学是决策智能的一半,因为我们必须处理数据并建立机器学习模型。后半部分涉及社会和决策科学。社会科学家在做出正确决策方面训练有素,而数据科学家目前却没有。决策智能的目的是确保人类在构建人工智能模型时做出的决策具有预期的结果。随着谷歌的业务越来越依赖机器学习算法,谷歌帮助推广了这一学科。

做出更好的决策

照片由布伦丹·丘奇在 Unsplash 上拍摄

这个概念在人工智能系统中非常重要,因为糟糕的决策是机器学习模型中偏差的主要因素。在最近的一篇帖子中,我讨论了亚马逊性别偏见的人工智能招聘模式。

简而言之,亚马逊的目标是建立一个人工智能系统来自动化他们的一个招聘流程。这位模特显然是根据 10 年前的简历训练出来的,其中大部分是男性求职者。结果是,尽管女性候选人完全合格,但该模式仍然歧视女性候选人。一旦这一点变得明显,亚马逊最终取消了该系统。如果建造这种人工智能的工程师受过决策智能训练,这种性别歧视模型可能永远不会被编程。受过社会和决策科学培训的数据科学家可能会发现,训练数据会导致模型在任务中做出错误的决策。这个例子说明了设计好的人工智能系统需要社会科学家的意见,或者受过社会科学训练的数据科学家——决策智能数据科学家!

数据科学家的未来

谷歌清楚地认识到这些技能对他们的员工和业务有多么重要。他们发明了一种新的领导职位,让他们的工程师在决策智能方面更有能力。 Cassie Kozyrkov 已经培训了超过 17000 名谷歌员工,帮助他们在数据科学领域做出更好的决策。因此,我认为数据科学家的角色将在未来几年内演变为包括决策智能方面的培训。我可以想象越来越多的组织需要为他们的数据科学家职位提供决策智能培训的证据。最终,我可以看到一个新的角色被创造出来。这将是一个在数据科学学科和导致良好决策的社会因素方面训练有素的人。我建议我们称这个新的专业人士为决策科学家。我不认为数据科学家的职位会有任何发展,因为将社会科学家加入数据科学家团队会产生与决策科学家团队相同的影响。问题是,当组织可以拥有一个同时具备这两种技能的人时,为什么还要为两个专业人士买单呢?我最初的印象是,决策智能是领导团队的技能,但人工智能巨头谷歌显然认为这些技能应该教给每个人。

结论

照片由米切尔罗在 Unsplash 上拍摄

谷歌正在以决策智能的新学科引领数据科学家的进化。目标是建立能够做出正确决策的人工智能系统。决策智能可能会在解决人工智能系统中出现的偏见方面发挥重要作用。随着数据科学家对他们模型中使用的数据提出问题,并在系统建立之前识别设计中的缺陷,这种情况将会发生。我将引用首席决策科学家 Cassie Kozyrkov 的话,来讨论什么是决策智能。

“…数据科学家被教导如何分析调查数据,如何仔细思考大量的数学问题,如何处理如果数据是连续的,如果数据是分类的,会发生什么。[……]但是他们没有学到的,不是直接在培训中学到的,是如何构建调查?你如何确保调查最大限度地减少,比如说,回答偏差,也就是用户或参与者对你撒谎,给你错误的答案?因此,如果数据科学家希望他们的工作有用,那么有人,不管是他们自己还是队友,只要有能力深入思考这些东西,就必须参与进来。”

超越 ML 系统的简单误差分析

原文:https://towardsdatascience.com/going-beyond-simple-error-analysis-of-ml-systems-9218f9602d33?source=collection_archive---------41-----------------------

行业笔记

在部署机器学习算法时,赌注比任何玩具问题或竞争都要高得多。

原载于 2021 年 7 月 26 日https://alexandruburlacu . github . io

首先,有一个故事…

想象你自己是一名 ML 工程师…非常酷,我的朋友!

首先恭喜你,拍拍自己的背,你的家人一定很骄傲。

第二,根据公司规模、文化和机器学习团队的成熟度,你很可能会在许多计算机科学和软件工程领域中漫游。

再次,拍拍自己的背。现在,让我们进入正题。

作为 MLE,你的部分工作是挑选、调整和部署 ML 模型。我相信我不需要向你解释这不是那么微不足道的。你一定相信这个过程的难点是调模型吧?或者可能是算法的部署?虽然这些确实很重要,尤其是后一个,但这里有个问题给你:

您如何确保生产出高质量的模型?

如果你要告诉我,你刚刚在一个保留的数据集上测试了你的模型,你选择的度量标准是精度或均方差之类的东西,那就运行吧。很快。很远。如果你没有跑,准备好被质疑你是否:

  • 有一个基线,
  • 平衡数据集或调整指标,
  • 使用保留的数据集进行调整/超参数搜索…等等。

这么多问题……制作人:imgflip.com

我想你现在已经明白,简单的训练/测试分割和一些误差指标,比如准确度或者甚至 F1*,都不足以回答问题。但是什么样的才够呢?嗯,视情况而定,就像软件工程中的所有事情一样。您需要理解,将您的模型特征减少到只有一个或几个标量将会丢失太多关于模型的信息。

*F1 成绩是更好的选择,btw

…然后是至理名言

*更像个人战争故事

免责声明,这是一个很长的帖子,所以也许泡些茶/咖啡,吃点零食,你知道,一些帮助你度过整个事情的东西。也许记笔记会帮助你保持专注。在阅读大量的技术文本时,它无疑会对我有所帮助。

另一个小小的免责声明:我有一个与这个主题无关的旧帖子,但是它的焦点是可解释性/可解释性方法。在这篇博客文章中,我更多地关注如何评估机器学习模型的错误。如果你认为这些主题彼此非常接近,有些重叠,你是对的。为了更好地评估一个模型,我们有时需要理解它进行预测的“推理”。

请记住——根据您应用机器学习的领域,一个不合格的模型可以是任何东西,从您的用户的一点烦恼到放大偏见并使您的客户逃离您的企业的完整垃圾箱火灾。虽然上述用户可能很容易选择退出前者,但后者可能会毁了你的业务。我们不想那样。你的雇主肯定不知道。

好的,收到。但是你怎么知道一个机器学习模型是好的呢?需要了解它的预测吗?你的用例中有你最关心的特定用户群吗?这些问题可以帮助您获得一个评估策略,从而确保在您部署一个 ML 模型之后不会出现任何问题。

你知道吗,让我先定义几个 ML 评估成熟度等级。对我来说解释起来更容易,对你来说也更容易理解。现在,不要为一些更高级的术语的含义而烦恼,我将在本节之后解释它们。

  • 0 级(L0) :有一个训练+测试分割和一两个通用指标,比如 MSE 或准确性。在这个层次上,不建议部署 ML 模型(最好理解为:不负责任)。
  • 第 1 级(L1) :前一级,但是如果可能的话使用交叉验证,或者最坏的情况,有一个大而多样的测试集。对于分类问题,您需要每个类的度量,对于回归问题,您需要多个度量。对于分类用例,ROC-AUC 得分或 F1 得分等指标比准确性好得多,因此使用这些指标。此外,了解您的模型的精度和召回特性对于成功的 ML 产品至关重要。在回归的情况下,MAPE+RMSE+调整后的 R 是一个很好的组合,你也可以考虑用 AIC 和/或 BIC 。对于回归,尝试至少有一个对异常值稳健的度量标准( MAPE 对某些类型的异常值稳健,但对其他类型的异常值不稳健)。
  • Level 1.1 (L1.1) :检查大多数错误预测,即预测可信度高,但预测错误的条目。它可以帮助你发现错误模式,甚至可能是偏见。
  • 第 2 级(L2) :使用反事实和输入值随机变化的扰动分析。通常,这种方法允许理解每个条目的特性重要性,但这更像是您必须努力才能获得的额外收获。
  • 2.1 级(l 2.1):ICE/PDP/ALE图可用于更好地理解特性重要性。请记住,这些对计算能力的要求相当高。
  • 2.2 级(L2.2) :在批准部署模型之前,替代局部解释(通常是石灰)和/或附加特征解释(即 SHAP)以理解模型预测。也需要大量计算。
  • 三级(L3) :基于群组的模型检验。定义群组的一种方法是通过流形式的错误分组。在这个层次上,重要的是要认识到数据分布的变化,如果适用的话,要对不同时期的数据进行评估。请相信我,有时特性和/或标签分布会发生变化,即使在您不希望它们发生变化的领域。不考虑这一点会让你感到头疼。
  • (可选)第四级(L4) :对抗性实例检查。像主播和 TCAV 这样的东西也在这个水平。原则上,任何其他高级的模型可解释性/可解释性或安全审计都在这个级别。

异能等级。不要做 L0。制造厂商:imgflip.com

当在测试版中发布一个模型时,你会希望处于第 1 级,当它处于生产阶段时,你会希望处于第 2 级,然后从第 2 级发展到第 3 级。级别 4 更具体,并不是每个用例都需要它。也许你正在内部使用你的 ML 算法,一些恶意代理试图欺骗你的风险很低,在这种情况下,我怀疑你需要检查你的模型的行为,但使用你自己的判断。

注意,虽然我提到了回归用例,但是我省略了很多关于时间序列预测的信息。这是故意这样做的,因为这个话题很大,而且这个帖子已经读了很久了。但是如果你对这里发生的事情有一个基本的了解,你可以把不同的时间序列分析工具映射到这些层次上。

方法

让我们粗略地将评估/错误分析方法分为三大类:(1)度量,(2)分组,和(3)解释。度量是显而易见的。分组可能是最抽象的。我们把训练/测试分割、交叉验证、输入数据群组和错误分组放在这里…哦,上帝…组(没有双关的意思)。最后,在解释的保护伞下,还有诸如代理本地解释、特征重要性,甚至分析最错误的预测等等。

韵律学

我不会深入探讨基于指标的评估,但会提到,根据您的用例,您可能希望考虑与预测错误程度相关的非线性指标。也许你可以接受一点错误,但是如果模型是非常错误的,或者经常错误,你会想要更多的惩罚它。或者,相反,随着错误预测的增多,或者模型的总损失不断增加,您希望您的指标具有类似于对数的行为,即随着模型错误的增多,指标将减弱其增长。

此外,关于对异常值稳健的度量,如果您事先做了一些异常值消除,有时这些是很好的。或者可能有必要,在你不能或者特别是不去除异常值的情况下,不管出于什么原因。记住这一点。

离群值对模型拟合度的影响。来源:https://scikit-image.org

通常,在生产场景中,您会想要在不同的群组上评估您的模型性能,甚至可能基于这些群组来使用不同的模型。群组是指一组实体,具有特定的分组标准,如年龄段,或基于位置,或其他。

分组

我在上一段提到了群组,所以继续跟进是有意义的。团队很重要,因为你的利益相关者对这些感兴趣,有时你也是,但是企业通常是团队的头号“粉丝”。为什么?嗯,可能有很多原因。也许他们对为特殊的客户群体提供一流的服务特别感兴趣,或者也许他们必须遵守一些法规,这些法规要求他们为所有用户提供特定级别的性能。

此外,如果是真实世界的数据,您的数据集肯定是有偏差的。也就是说,对于每个类别/类别组,您将会有代表性不足的类别、各种不平衡,甚至不同的要素分布。例如,对于任何企业来说,给北美地区以外的用户提供低于标准的推荐,或者预测某个有色人种是某种类人猿是不合适的。

我们需要根据一些特征创建群组,并跟踪我们的机器学习系统在这些方面的表现。通常你会发现,那些意识到自己团队的团队会为不同的用户群部署不同的模型,以确保为每个人提供高质量的服务。

但是分组不仅仅是基于输入数据特征的群组。有时对于模型分析来说,根据错误创建分组是有意义的。根据误差分布进行某种分组。也许对于某些输入,你的模型给出的误差很低,对于其他输入,误差很高,而对于另一组,误差分布完全不同。为了发现和理解这些,你可以使用 K-Means 来聚集你的损失,并找出你的模型失败或表现不佳的原因。这就是优步的流形所做的,这真是太棒了!

**

(上)3 组误差分布,以及 2 个模型之间的比较。(底部)一旦我们有了错误组,我们就想知道为什么会发生这些错误。可视化这两个集群之间的特征分布差异会有所帮助。
来源:作者。灵感来源:http://manifold.mlvis.io/

最后,分组也是关于你如何将你的数据安排到训练和测试分割中。或者更多的分割,比如模型训练过程中的评估。这些有助于注意模型何时开始过度拟合或其他情况。请记住,在进行超参数搜索时应特别小心。对于快速训练的模型,一种叫做嵌套交叉验证的技术是一种非常好的方法,可以确保模型真的很好。嵌套部分是必要的,因为进行超参数优化(HPO)时,您是在评估集上进行优化,所以至少可以说您的结果是“乐观的”。进行额外的分割可以让你对最终模型有一个更公正的评估。慢模式呢?哦,博伊。试着拥有一个足够大的数据集,这样你就可以在所有的评估/测试阶段进行大的划分。你也没有这个?你听说过人工智能的需求层次吗?

此外,一个经常被忽视的问题是数据集的目标分布。它可能严重不平衡,因此,在对其进行训练/验证/测试分割取样时,应特别小心。这就是为什么你应该总是寻找一种方法让你的分割分层*(见 scikit-learn 的StratifiedKFold,还有train_test_split有一个stratify=参数,对于多输出数据集检查multioutput_crossvalidation包)。当数据集不平衡时,你可以尝试做一些过采样,比如 la SMOTE 或 ADASYN,但根据我的经验,这可能并不总是有效,所以只需实验(这是一个类似 scikit-learn 的库[imbalanced-learn](https://imbalanced-learn.org/stable/index.html))。*

解释

免责声明#2,这篇博文的这一部分可能是最令人震惊的部分之一。关于 ML 可解释性/可解释性有相当多的文献,我将只简要地提到一些方法,为了更深入的概述,请查看 Christoph Molnar 的 【可解释机器学习】

这个类别非常抽象,有些人可能会认为这些与模型评估没有真正的联系,而是 ML 可解释性/可解释性。我说这些方法可以揭露隐藏的错误和偏见。基于这些,现在你可以选择一个模型而不是另一个,因此解释对于评估是有用的。这些工具在识别“正确答案—错误方法”场景方面表现出色,这些场景将在没有任何问题指标和分组的情况下通过。

那么,关于一个模型,你能“解读”出哪些可以帮助你评估它的东西呢?首先,如果您的模型/API 允许,您可以检查特性的重要性。您可能会发现一个模型对一些模糊的特性或者没有意义的特性给予了过多的关注。此时,你应该成为一名侦探,并找出为什么会这样。这种特征重要性被称为 全局特征重要性 ,因为它是在模型级别从所有训练数据中推断出来的。

接下来容易做的是 扰动分析 ,其中有多个类别。扰动分析意味着改变输入,看看会发生什么。我们可以出于不同的目的改变输入,以评估模型的不同方面。

  • 反事实,又名“如果我改变这一个特征,我的模型预测会如何改变?”。例如,我们可以检查模型对变化的敏感程度,原则上这些变化会直观地改变预测。一个突出的工具是 Tensorboard 的假设工具。
  • 对立的例子,又名“我能创建这样的输入吗,虽然与正常输入相似,但会导致混乱的预测”。检查这些对于面向外部用户的系统来说通常很重要,在这些系统中,攻击可能会产生非常恶劣的后果,而且因为这种验证更加具体,所以通常会留到项目的后期进行。
  • 为了评估模型对不重要的变化有多稳健,或者它捕捉“常识性”有多好,随机改变也可以用于局部特征重要性。在情感分析问题的情况下,一个随机的改变可能是用同义词替换没有积极或消极语义的词,也就是中性词。
  • 非分布数据。好吧,这不是真正的扰动分析,但有时你想确保模型可以推广到相似但不完全相似的数据。或者你可能只是想让在工作中找点乐子,然后把德语句子传给一个在西班牙语文本上训练过的情感分析模型。

另一种帮助您发现错误模式的方法是检查模型可信度非常高的错误预测。简单来说,皇家混蛋。我学这个方法比较晚,是从 Goodfellow 等人的深度学习书上学的,我很懒,这个方法虽然事后看来很明显,但对我来说是新的。我更喜欢做扰动分析,这样就不需要漂亮的打印和/或绘图了。但是当我在做我的研究项目时,我现在“强迫”我自己(其实也没那么糟糕)也做这一步。

我建议定义一些由以前有问题的输入例子组成的回归测试套件。这有助于确保 ML 模型的未来版本确实是对以前版本的改进。在它可以检查以前错误分类的条目或使用不同类型的扰动分析的例子。稍后,您将会感谢这个回归套件。

替代本地解释,其中最突出的工具是石灰,是另一种可解释性工具。代理本地解释试图用简单的机器学习模型来逼近复杂的机器学习模型,但仅针对输入数据的子集,或者可能仅针对单个实例。

最后(现在是肯定的),另一个值得注意的 ML 可解释性方法是附加特征解释,对于这一类别,最突出的工具之一是 SHAP。SHAP 尤其有趣,尽管更难理解,因为它基于博弈论,并使用匀称的值来定义局部特征的重要性。这种方法的一个问题是 Shapely 值或几乎任何其他附加特征解释方法都没有考虑特征交互,这可能是一个交易破坏者。

SHAP 用沙普利值来解释每个特征值对预测的影响。来源:作者。

还有更先进的工具,专门针对神经网络进行调整。这些使用不同形式的显著性或激活图。像这样的工具很酷,也很有用,但是很难使用,而且不够通用。试图涵盖其中的一个子集将需要一整本书,所以如果你感兴趣,你知道该怎么做;).在这本书里,你可以找到更多关于现代工具的详细解释,比如 SHAP、莱姆、锚,还有更经典的方法,比如 PDP、ICE 和 ALE 图。甚至像 Tensorflow 的 TCAV 工具这样的概念识别方法。

要记住的一点是,可解释性工具对于正确的模型评估是至关重要的。虽然不是直接的映射,但是您可以将这些解释方法用于像代码评审这样的模型。在生产系统中,你不会在没有代码审查的情况下合并代码,不是吗?

个人推荐

我们已经接近这篇文章的结尾了,所以我想给你一些建议,告诉你当评估 ML 模型时,如果那些成熟度级别还不够的话,该如何进行。这些建议更低级、更实用,如果你愿意的话,还有些问题。

  • 当然,从几个合适的评估指标开始。不要只用一个。如果可以的话,交叉验证。如果做 HPO,有两个测试分裂。对于分类,我会推荐至少一些损失和一些得分函数+ scikit-learn 的classification_report,如果你没有大量的类,混淆矩阵是你的朋友。有些人使用 AUC 和精确召回曲线,这很好,但我不习惯这些。也许在这篇博文之后,我会开始使用它们。(照我说的做,不要照我做的做)
  • 在这之后,我通常做扰动分析(随机和反事实)。寻找前 k 个最错误的预测是有帮助的,但我很少这样做(照我说的做,不照我做,#2)。
  • 如果我还不满意,我肯定会检查错误组,比如流形和/或代理本地解释(类似于 LIME,我主要使用eli5包)。我不喜欢后一种方法,因为这需要花费大量的时间,尤其是对于较大的输入。关于代理模型的局部解释,有时我发现使用缺省值来调整代理可能太简单了。我做 NLP,所以这两点对我来说都是一个真正的问题。

有时,尤其是在开发的早期阶段,我可以对模型预测进行一种“探索性测试”,即输入非分布数据,看看会发生什么。

对于个人实验,我有时可以使用 SHAP,但我发现它有点令人沮丧,很难导出图形,而且它在 Jupyter 上工作时效果最好。此外,它很慢,但这是所有代理解释的普遍问题。

我还没有玩转锚、对立的例子,以及做类似“找到与不同类最相似的条目”或“找到与这个类最相似的条目”的事情。后两者可以在特征、嵌入和/或预测空间中使用 kNN 来完成。微软数据科学家似乎在问这类问题来评估他们的模型。**

最后,我确信这些信息会让你不知所措。这就是为什么我能给出的最好的建议是使用一个简单的模型,一个容易理解的模型。为了提高性能,你也可以尝试在有意义的特性上投入时间。总而言之,做你的公司需要你成为的数据科学家就好,而不是你想成为的那种。无聊理性战胜炒作驱动。

明智地选择你的英雄。制造商:imgflip.com

可能这个帖子,没有其他的,帮助我结晶了很多多年来获得的隐性知识。也许你听过这句名言——“一个人教,两个人学”,我相信这里也发生过类似的事情。

我知道我的帖子通常又长又密,对不起,我想,但另一方面,现在你不必书签 5-10 页,只需这一页😀😀😀jk。无论如何,感谢你坚持不懈地阅读这篇文章,如果你想留下一些反馈或只是有一个问题,请留下评论。估计要过一段时间才能下次了。

 *vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
> Until then, you can play around                                 <
> with most of the methods described in this blog post            <
> by checking the link below                                      <
> [https://github.com/AlexandruBurlacu/error_analysis_code_samples](https://github.com/AlexandruBurlacu/error_analysis_code_samples) <
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*

你也可以点击这里。所有的例子都是种子,所以应该可以重现一切。玩得开心。

承认

特别感谢 @dgaponcic 的风格检查和内容审核,再次感谢 @anisoara_ionela 的彻底语法检查,感谢 @dianaartiom 对 ML 的最后一点反馈。你们都是最棒的❤

几个参考

  • 回归指标的详细概述
  • Christoph Molnar 的可解释机器学习;惊人的工作,大量的信息,大量的细节
  • *** 色域纸帮助您提出关于型号的正确问题*
  • 汇纸和汇 GitHub 回购
  • 很好地概述了如何评估和选择 ML 模型

Github repos,其中也包含各自论文的链接:

  • LIME GitHub 回购
  • SHAP GitHub 回购
  • 主播 GitHub 回购
  • 还有一个棒极了的 GitHub repo 关于不同的 XAI 工具和论文。

利用 MS2DeepScore 超越光谱相似性

原文:https://towardsdatascience.com/going-beyond-spectral-similarity-with-ms2deepscore-ef0f923428e6?source=collection_archive---------36-----------------------

使用深度学习模型直接从 MS/MS 谱图预测结构相似性。

来源:作者

光谱相似性得分通常被用作结构相似性的代表。但是在很多情况下,两者有很大的不同。这可能会对库比较的结果产生疑问。Florian 和他的团队建立了一个深度学习模型,成功地直接从串联质谱预测了结构相似性。

光谱比较是每个代谢组学工作流程的一部分

将质谱测量结果与库测量结果进行比较是任何代谢组学分析流程中的关键步骤。你需要可靠的光谱比较,

  • 识别您的化合物:在参考库中搜索与您的碎片模式相匹配的化合物。
  • 寻找类似物:通过相似的裂解模式寻找结构相关的化合物。
  • 帮助结构解析:将你的分子与一个分子类别联系起来,以缩小潜在的分配范围。

对于串联质谱,通常通过计算它们之间的余弦值来比较质谱。高余弦值表明两种化合物的裂解曲线重叠良好。

你可能认为高余弦值与高结构相似性相关。不幸的是,余弦分数只能告诉你光谱的相似度。但是当你想要注释你的化合物时,你会对结构相似感兴趣。这是一个至关重要的区别。****

光谱和结构的相似性:苹果和橘子

让我们来看看不同之处:

  1. 光谱相似度,例如余弦相似度,测量两个质谱图之间的重叠。
  2. 结构相似度,与 Tanimoto 评分一样,使用分子结构的 2D 向量表示法来量化两个分子指纹的重叠。

光谱相似性可能与结构相似性显著不同。这可能会让你从图书馆搜索中得出错误的结论。让我们看看这会对你的工作产生怎样的影响。

以抗生素达托霉素(上图)和一种假设的类似物(下图)为例:

来源:作者

达托霉素(上图)和它的类似物(下图)改变了裂解模式,尽管总体上彼此非常相似。余弦分数比较将给出较低的分数,并且不能检测出它们是高度相似的结构。

  • **高结构相似性:**类似物(下图)的结构仍与其未修饰形式达托霉素(上图)高度相似。
  • **低光谱相似性:**类似物中的修饰携带到许多碎片中,并使许多质谱峰发生位移。结果,几乎没有重叠的峰保留下来,因此光谱相似性得分较低。

这意味着,如果你的样品中含有达托霉素类似物,你将不会从文库或类似物搜索中找到,即使你在文库中有达托霉素参比光谱!

这意味着如果你仅仅依靠余弦相似性,

  • 你不能确定余弦值最高的匹配真的是最好的结构匹配。
  • 您的库可能包含相近的结构匹配,但您看不到它,因为匹配的光谱相似性得分非常低。

然而,Florian Huber 和他的团队找到了一种直接从串联质谱预测结构相似性的方法。

MS2DeepScore 如何从串联质谱预测结构相似性

MS2DeepScore 可以预测化合物何时是密切相关的结构类似物,即使其他比较方法,如余弦相似性,可能会失败。

Florian Huber 和他的团队使用来自 15,000 多种独特化合物的 100,000 多种光谱训练了 MS2DeepScore。一旦经过训练,MS2DeepScore 模型就可以直接从两种化合物各自的 MS/MS 图谱中预测它们之间的 Tanimoto 相似性得分。

使用它所学到的知识,MS2DeepScore 在关联结构相似的化合物方面始终优于余弦相似度和 Spec2Vec,即使当化合物的碎片图谱发生变化时。重要的是,用于比较得分准确性的化合物不包括在 MS2DeepScore 训练数据集中。

MS2DeepScore 在精度与召回率方面优于余弦得分和 Spec2Vec。来源:作者

在我们的实施例中,达托霉素和类似物之间的余弦值仅为 0.24。由此,我们可以假设这些化合物在结构上并不紧密。但 MS2DeepScore 模型预测的谷本得分为 0.95,非常接近实际的谷本得分 0.98。

使用 MS2DeepScore

开始使用 MS2DeepScore 很简单,您可以在几分钟内开始用它比较光谱。

无论用什么乐器采集,都可以使用 MS2DeepScore。MS2DeepScore 与 matchms 模块一起工作,因此您可以选择几个开源数据类型,如。mgf,。mzxml 和. mzml。

Florian 和他的团队将 MS2DeepScore 设计成一个包含 Jupyter 笔记本教程的 python 包来帮助您入门。你可以使用模型开始比较你的光谱,该模型已经在的 15,000 种化合物的 109,000 个光谱上进行了预训练。要了解更多关于 MS2DeepScore 及其开发的信息,请务必查看预印本出版物。

MS2DeepScore 的下一步是什么?

我们正在构建利用 MS2DeepScore 进行库匹配的新方法,包括一个 API、一个易于使用的界面和持续更新的模型。

这个新版本将提供,

  • 在超过 230,000 个光谱上训练的新模型;
  • 图书馆与 GNPS 公共数据库的匹配;
  • 一种新的否定模式比较。

如果您想试用它,请不要犹豫联系我们获得测试版访问。

超越 value_counts():只用 3 行代码创建视觉上引人入胜的频率表(使用 OkCupid 数据)

原文:https://towardsdatascience.com/going-beyond-value-counts-creating-visually-engaging-frequency-tables-with-only-3-lines-of-code-3021c7756991?source=collection_archive---------41-----------------------

一些你可能不知道的简单而有用的生活窍门

图片由作者创作,灵感来自 Loveascii

虽然在 Python pandas 库中为一个系列对象创建频率表最简单的方法是应用value_counts()方法,但是这个操作的结果看起来相当简单。我们可以通过调整方法的布尔参数normalizesortascendingdropna,或者将值(如果它们是数字的话)分组到 bin 中,来使它提供更多的信息。然而,这里的选项非常有限,所以为了在视觉上增强结果频率表,我们可以考虑一些简单而有用的技巧,比如方法链接、文本定制、为每个频率值添加%符号,以及使用漂亮打印的功能。

在本文中,我们将使用包含年龄、性别、位置、教育等信息的 Kaggle 数据集进行实验。,针对 OkCupid 交友 app 的 6 万用户💞。然而,出于我们的目的,我们将只使用用户状态的数据。

1.方法链接

首先,让我们为用户状态创建一个基本频率表:

import pandas as pd
profiles = pd.read_csv("okcupid_profiles.csv", na_values="unknown")
s = profiles["status"]
s.value_counts()**Output:**single            55697
seeing someone     2064
available          1865
married             310
Name: status, dtype: int64

尽管此表清楚地显示了总体趋势,但以相对频率查看此信息会更方便。让我们将True分配给normalize参数,并将结果频率表(它本身是一个序列)分配给一个名为s_norm的变量。

(*旁注:*在下文中,我们将默认保留value_counts()方法的所有其他参数,这意味着我们将只考虑按降序排序的频率表,并排除缺失值。对于我们的目的,使用或不使用这些参数并不重要。)

s_norm = s.value_counts(normalize=True)
s_norm**Output:**single            0.929275
seeing someone    0.034437
available         0.031117
married           0.005172
Name: status, dtype: float64

现在所有的频率都被转换成分数,但是我们更喜欢看到百分比,所以让我们把这个系列乘以 100:

s_pct = s_norm.mul(100)
s_pct**Output:**single            92.927456
seeing someone     3.443673
available          3.111652
married            0.517218
Name: status, dtype: float64

我们真的不需要如此精确的百分比。此外,让我们想象一下,我们根本不需要小数点:

s_pct_rounded = s_pct.round()
s_pct_rounded**Output:**single            93.0
seeing someone     3.0
available          3.0
married            1.0
Name: status, dtype: float64

不幸的是,舍入到整个部分给我们留下了所谓的可空整数(即小数部分等于 0 的浮点数)。要修复它,我们可以使用convert_dtypes()astype(int):

s_pct_int = s_pct_rounded.convert_dtypes()
s_pct_int**Output:**single            93
seeing someone     3
available          3
married            1
Name: status, dtype: Int64

现在让我们展开s_pct_int的整个表达式,显示我们链接的所有方法:

s_pct_int = profiles['status'].value_counts(normalize=True).mul(100).round().convert_dtypes()

2.添加表格标题

在不了解上下文的情况下,从上表中无法清楚地看出这些数字代表的是百分比而不是绝对频率。让我们使用 f 字符串格式为表格添加一个标题:

print(f"OkCupid user statuses, %\n{s_pct_int}")**Output:**OkCupid user statuses, %
single            93
seeing someone     3
available          3
married            1
Name: status, dtype: Int64

一个好主意是,特别是如果我们一次打印出几个频率表,从视觉上突出表的其余部分的标题,例如使其加粗。为此,我们可以使用 ANSI 转义码序列。特别是,要在 Python 中以粗体显示一个字符串,我们应该在该字符串之前添加序列\033[1m,在它之后添加\033[0m —:

print(f"\033[1mOkCupid user statuses, %\033[0m\n{s_pct_int}")**Output:****OkCupid user statuses, %** 
single            93 
seeing someone     3 
available          3 
married            1 
Name: status, dtype: Int64

3.将%符号加到每个频率值上

在上面的例子中,我们给表格标题添加了%符号。如果我们想把它加到每个频率值上呢?这里的一个解决方法是制作一个频率值列表,在每个列表中添加%符号,然后从这个列表中创建一个序列。为了制作列表,我们可以使用下面的 For 循环:

lst_with_pct_symb = []
for value in s_pct_int.values:
    lst_with_pct_symb.append(f"{value}%")
lst_with_pct_symb**Output:**['93%', '3%', '3%', '1%']

或者更简洁地说,一个列表理解:

lst_with_pct_symb = [f"{value}%" for value in s_pct_int.values]

现在,让我们创建并打印一个更新的频率表。这一次,我们将从标题中删除%符号:

s_with_pct_symb = pd.Series(lst_with_pct_symb, index=s_pct_int.index)
print(f"\033[1mOkCupid user statuses\033[0m\n{s_with_pct_symb}")**Output:****OkCupid user statuses**
single            93%
seeing someone     3%
available          3%
married            1%
dtype: object

4.漂亮的印刷桌子

最后,我们可以把频率表打印出来。为此,我们将使用to_markdown() pandas 方法,该方法需要安装(不一定是导入)制表模块(pip install tabulate)。

**重要提示:**为了正确显示结果,只能在print()命令中使用to_markdown()方法。

让我们再次展示名为s_with_pct_symb的用户状态频率表,这次是一个真实的表,使用的是to_markdown()的基本语法。如前所述,我们将添加一个粗体标题并应用 f 字符串格式。为了一致性,在下文中,我们将要显示的频率表分配给一个名为S的变量:

S = s_with_pct_symb
print(f"\033[1mOkCupid user statuses\033[0m\n{S.to_markdown()}")**Output:****OkCupid user statuses**
|                | 0   |
|:---------------|:----|
| single         | 93% |
| seeing someone | 3%  |
| available      | 3%  |
| married        | 1%  |

我们可能要做的第一件事是删除一个自动创建的表头(在我们的例子中是多余的)。为此,我们必须为一个名为headers的可选参数分配一个空列表或字符串:

print(f"\033[1mOkCupid user statuses\033[0m\n{S.to_markdown(headers=[])}")**Output:****OkCupid user statuses**
|:---------------|:----|
| single         | 93% |
| seeing someone | 3%  |
| available      | 3%  |
| married        | 1%  |

在表格文档中,我们可以找到一些其他参数进行调整。但是,它们大多与 DataFrame 对象相关。在我们的例子中,假设我们有一个序列,并且记住在添加了%符号之后,频率值实际上变成了字符串,我们有一个小得多的选择。

我们来玩一下参数tablefmtstralign。它们中的第一个定义了表格格式,可以有下列值之一:plainsimplegithubgridfancy_gridpipeorgtbljiraprestoprettypsqlrst等。例如,我们之前看到的表格格式叫做pipe,这是to_markdown() pandas 方法的默认格式。奇怪的是,对于制表软件包本身,默认的表格格式是simple。至于第二个参数stralign,它用于覆盖默认的字符串数据对齐方式(即left)。这里可能的选项是rightcenter

print(f"\033[1mOkCupid user statuses\033[0m\n"
      f"{S.to_markdown(headers=[], tablefmt='fancy_grid', stralign='right')}")**Output:****OkCupid user statuses**
╒════════════════╤═════╕
│         single │ 93% │
├────────────────┼─────┤
│ seeing someone │  3% │
├────────────────┼─────┤
│      available │  3% │
├────────────────┼─────┤
│        married │  1% │
╘════════════════╧═════╛

现在让我们把注意力转向我们之前创建的名为s_pct_int的频率表。提醒其语法和外观:

s_pct_int = profiles['status'].value_counts(normalize=True).mul(100).round().convert_dtypes()
s_pct_int**Output:**single            93
seeing someone     3
available          3
married            1
Name: status, dtype: Int64

要为s_pct_int创建降价表,添加相应的表头是有意义的。同样,让我们为tablefmt参数尝试一个新值:

S = s_pct_int
print(f"\033[1mOkCupid user statuses\033[0m\n"
      f"{S.to_markdown(headers=['STATUS', '%'], tablefmt='github')}")**Output:****OkCupid user statuses**
| STATUS         |   % |
|----------------|-----|
| single         |  93 |
| seeing someone |   3 |
| available      |   3 |
| married        |   1 |

然而,这里我们有一个好消息:对于数字频率值,我们可以使用floatfmt参数来定制浮点数的格式。这意味着上面方法链中的最后两个方法(round()convert_dtypes())是多余的,可以删除。它留给我们之前创建的频率表s_pct:

s_pct = profiles['status'].value_counts(normalize=True).mul(100)
s_pct**Output:**single            92.927456
seeing someone     3.443673
available          3.111652
married            0.517218
Name: status, dtype: float64

让我们展示一下它的降价表示:

S = s_pct
print(f"\033[1mOkCupid user statuses\033[0m\n"
      f"{S.to_markdown(headers=['STATUS', '%'], tablefmt='github', floatfmt='.0f')}")**Output:****OkCupid user statuses**
| STATUS         |   % |
|----------------|-----|
| single         |  93 |
| seeing someone |   3 |
| available      |   3 |
| married        |   1 |

由于正确的数字格式,我们获得了与前一个相同的表。

注意:floatfmt参数不配合表格格式pretty使用。

实用的外卖

尽管上面的整个演练花费了大量的迭代和描述,下面我们将找到 4 个不同版本的profiles['status']频率表的最终代码解决方案,全部以%表示:

  • 2 个带有/不带有%符号的简单表格,
  • 2 个印刷精美的表格,带/不带%符号,带/不带表头。

每个解决方案最多只需 3 行简单代码,就能生成感兴趣的频率表的直观有效的表示。

S = profiles['status'].value_counts(normalize=True).mul(100).round().convert_dtypes()
print(f"\033[1mOkCupid user statuses, %\033[0m\n{S}")**Output:****OkCupid user statuses, %**
single            93
seeing someone     3
available          3
married            1
Name: status, dtype: Int64
s_pct_int = profiles['status'].value_counts(normalize=True).mul(100).round().convert_dtypes()
S = pd.Series([f"{value}%" for value in s_pct_int.values], index=s_pct_int.index)
print(f"\033[1mOkCupid user statuses\033[0m\n{S}")**Output:****OkCupid user statuses**
single            93%
seeing someone     3%
available          3%
married            1%
dtype: object
S = profiles['status'].value_counts(normalize=True).mul(100)
print(f"\033[1mOkCupid user statuses\033[0m\n"
      f"{S.to_markdown(headers=['STATUS', '%'], tablefmt='github', floatfmt='.0f')}")**Output:****OkCupid user statuses**
| STATUS         |   % |
|----------------|-----|
| single         |  93 |
| seeing someone |   3 |
| available      |   3 |
| married        |   1 |
s_pct_int = profiles['status'].value_counts(normalize=True).mul(100).round().convert_dtypes()
S = pd.Series([f"{value}%" for value in s_pct_int.values], index=s_pct_int.index)
print(f"\033[1mOkCupid user statuses\033[0m\n{S.to_markdown(headers=[], tablefmt='fancy_grid')}")**Output:****OkCupid user statuses**
╒════════════════╤═════╕
│ single         │ 93% │
├────────────────┼─────┤
│ seeing someone │ 3%  │
├────────────────┼─────┤
│ available      │ 3%  │
├────────────────┼─────┤
│ married        │ 1%  │
╘════════════════╧═════╛

结论

在本文中,我们讨论了一些简单而强大的方法来改进频率表的布局和整体可读性。他们都有value_counts()熊猫方法作为核心部分,但都超越了它,产生了更有影响力的表现。更重要的是,每个建议的解决方案,在其最终形式下,最多需要 3 行代码。

我希望你喜欢阅读我的文章,并发现它很有帮助。感谢大家的阅读,祝使用 OkCupid 交友 app 的人好运😉💘

你会发现这些文章也很有趣:

</5-pandas-methods-youve-never-used-and-you-didn-t-lose-anything-37277fae7c55> </2-efficient-ways-of-creating-fancy-pictogram-charts-in-python-8b77d361d500>

在深度学习上不断深入

原文:https://towardsdatascience.com/going-deep-on-deep-learning-bd9312096fa3?source=collection_archive---------31-----------------------

在一个有从一个流行词跳到另一个流行词的趋势的领域,深度学习被证明是发现和科学进步的持续驱动力——但也是混乱甚至恐惧的经常来源。TDS 是来帮忙的。

Patrick sch pflin 在 Unsplash 上的照片

贝叶斯方法,从错误中学习

一个开始的好地方?这是对贝叶斯深度学习的全面介绍,作者 Joris Baan ,他写这篇文章的明确目标是弥合基础概率论和前沿研究之间的差距。你很难找到比 Lina Faik 耐心解释深度 Q 学习、强化学习以及这两者如何推动新的和令人兴奋的现实世界应用更好的文章来阅读。

如果我们退一步,从自己的错误(或模型的错误……)中学习是任何机器学习工作流程中的关键一步,无论深度与否。本周,我们围绕这个主题发表了几篇颇有见地的帖子:我们强烈推荐 Emeli Dral 的指南,以找到你的回归模型中的弱点,以及这个关于错误分析和负责任的机器学习的重要概述,由 Besmira Nushi 和她在微软研究院的同事提供。当你这样做的时候,用 Aparna Dhinakaran 对模型性能指标的讨论和她的模型监控剧本来完成你的 ML 阅读会议。

当然,深入可能意味着不止一件事——当我们积极完善我们的技能并理顺我们的日常流程时,我们经常会感觉到与我们的工艺有更深的联系。如果你错过了它们,现在赶上 Gregor Scheithauer 博士关于让你的代码更有效的教程还不算太晚,还有 Lathan Liou 对他多年来开发的简化的 R 数据分析工作流程的简明介绍。尽情享受吧!

第一步,加强联系

我们知道你们中的许多人最近刚刚开始了数据科学之旅,你们中的一些人可能还在思考这是否是适合自己的道路。如果这描述了你目前的状态,你现在能做的最好的事情就是抽出几分钟来阅读副主编安妮·邦纳的关于数据科学入门的阅读清单。

安妮的帖子关注的是一个有时会在所有算法和可视化中迷失的领域:网络。正如她所说的,“和那些已经做了你将要做的事情的人联系是最聪明(也是最快)的前进方式之一。”在你看完安妮推荐的读物时,做好准备,让自己充满想法和动力。

变革性人工智能技术的最终前沿

对于我们这些生活在赤道以北的人来说,春天感觉很近——更新和新的可能性的承诺也是如此。我们想不出比人工智能的开阔视野更适合这个季节的话题了,TDS 播客主持人 Jeremie Harris 和他最近的嘉宾研究员 David Roodman 一起深入探讨了这个话题。收听这一集了解大卫在经济模型、预测和人工智能公平性方面的工作。

无论你在世界的哪个角落,无论你是否会经历更长的白天和更温暖的天气,TDS 的所有人都祝你度过美好的一周。感谢您阅读、分享和参与我们发布的作品,感谢您让这个社区保持支持、开放和无止境的好奇。

直到下一个变量,
TDS 编辑器

我们策划主题的最新内容:

入门指南

  • 了解概率分布作者 Cassie Kozyrkov
  • Get-git:由 Thushan Ganegedara 撰写的关于 Git 的初级读本
  • 数据科学中有用的 pip 命令作者帕鲁尔·潘迪

实践教程

  • 使用 CycleGAN 在网络摄像头上进行风格转换作者本·桑多斯
  • 如何通过多重处理提升预测作者 Justin Chae
  • 统计意义的不显著性?为什么 P 值不应该被高估Hannah wn endt

变革的数据

  • 农业经济学优化和农业可持续性作者 Bonny Nichol
  • 能否近乎实时地看到城市中的人员流动中断?由穆罕默德·费萨尔汗
  • 拯救动物生命,数据作者拉姆山卡尔·亚胡纳特

思想和理论

  • 像素不是由Jean-Christophe b . lois eau创造的
  • 什么是算法公平性?作者康纳·奥沙利文
  • 最佳控制与开放健身房作者保罗·布伦泽马

争取金牌:使用广义线性模型预测奥运会奖牌结果

原文:https://towardsdatascience.com/going-for-gold-predicting-medal-outcomes-in-the-olympics-using-generalized-linear-modeling-e6e9d4837ae8?source=collection_archive---------11-----------------------

我们能建立一个运动员赢得奖牌几率的广义线性模型吗?

凯尔·迪亚斯在 Unsplash 上的照片

和许多人一样,我一直在家里享受东京奥运会。作为一名数据科学家,在观看一些网球比赛时,我摆弄了一个关于奥运选手的 Kaggle 数据集,列出了他们的年龄、性别和国籍等特征,以及每个运动员获得的奖牌(如果有的话),并想看看我能否基于这些特征建立一个运动员赢得奖牌几率的广义线性模型。

动机

根据年龄、身高和国籍等相关特征,我们能否预测某个运动员在奥运会上赢得奖牌的可能性?

资料组

我们将使用从雅典 1896 年到里约 2016 年的夏季和冬季奥运会的综合数据集。对每位运动员的以下特征进行测量:

  • ID(每个运动员的唯一标识符,以说明重复的姓名)
  • 名字
  • 性别(F 代表女性,M 代表男性)
  • 年龄
  • 高度(厘米)
  • 重量(千克)
  • NOC——由国家奥林匹克委员会为每个国家制定的三个字母的代码(例如,USA:美利坚合众国)
  • 游戏(例如,2008 年夏季,2010 年冬季)
  • 季节(夏季或冬季)
  • 城市(如东京)
  • 运动(如网球)
  • 项目(如网球女子单打)
  • 奖牌(金、银、铜、钠)

初始数据探索

首先,让我们加载数据集:

作者图片

让我们看看哪个国家积累的金牌最多:

USA    1131
URS     471
GER     319
GBR     289
FRA     264
       ... 
HAI       1
FIJ       1
PER       1
HKG       1
SYR       1
Name: NOC, Length: 109, dtype: int64

我们看到美国获得了最多的金牌,截至 2016 年,共有 1131 枚奖牌,这是有道理的,因为它自 1896 年成立以来一直参加奥运会。

让我们看看美国在哪个运动项目上赢得了最多的奖牌:

Athletics                    344
Swimming                     246
Shooting                      54
Wrestling                     52
Boxing                        50
Diving                        48
Gymnastics                    35
Rowing                        33
Speed Skating                 29
Basketball                    23
Tennis                        21
Sailing                       19
Weightlifting                 16
Cycling                       16
Alpine Skiing                 16
Figure Skating                15
Archery                       14
Equestrianism                 11
Snowboarding                  10
Freestyle Skiing               8
Bobsleigh                      7
Beach Volleyball               6
Synchronized Swimming          5
Canoeing                       5
Short Track Speed Skating      4
Fencing                        4
Football                       4
Art Competitions               4
Skeleton                       3
Golf                           3
Softball                       3
Ice Hockey                     3
Water Polo                     3
Rugby                          3
Volleyball                     3
Judo                           2
Taekwondo                      2
Nordic Combined                1
Jeu De Paume                   1
Baseball                       1
Triathlon                      1
Roque                          1
Tug-Of-War                     1
Polo                           1
Name: Sport, dtype: int64

因此,看起来美国以 344 枚金牌在田径项目上独占鳌头,其次是游泳项目,有 246 枚金牌。但是,我需要注意的是,截至 2016 年里约奥运会,田径项目的实际金牌数为 335 枚。截至 2018 年,当这些数据汇总在一起时,大多数剩余的运动项目都有正确的统计数据,然而,在过去如何计算奖牌方面存在一些轻微的差异。例如,在击剑比赛中,数据显示美国获得了 4 枚奖牌,但一些消息来源却报道了 3 枚。这是由于 1904 年国际奥委会将美国人艾伯特森·范·佐·波斯特算作代表古巴而不是美国的差异T5 造成的。在该数据集中,假设美国人表示。我推测,在奥运会早期的田径比赛中也有类似的争议,这可以解释略高的数字,所以我鼓励读者在得出结论之前,与官方的奥运资料进行交叉验证,以自己对这个数据集的分析。尽管如此,上面这些统计数据大部分都是正确的,比如游泳和网球。

我们可以根据运动发生的季节来划分运动项目:冬天或夏天。既然田径和游泳是夏季项目,让我们来看看美国在哪个冬季项目中获得了最多的金牌:

Speed Skating                29
Alpine Skiing                16
Figure Skating               14
Snowboarding                 10
Freestyle Skiing              8
Short Track Speed Skating     4
Skeleton                      3
Ice Hockey                    3
Nordic Combined               1
Name: Sport, dtype: int64

美国以 29 枚奖牌获得了最多的速滑金牌,但似乎夏天才是美国真正闪光的地方。让我们看看哪个国家在冬奥会上赢得了最多的金牌。

NOR    111
USA     96
GER     86
URS     77
CAN     62
AUT     59
SUI     50
SWE     50
RUS     49
FIN     42
GDR     39
ITA     37
NED     37
FRA     31
KOR     26
CHN     12
FRG     11
GBR     11
JPN     10
EUN      9
CZE      7
BLR      6
AUS      6
POL      6
CRO      4
EST      4
SVK      2
SLO      2
UKR      2
LIE      2
TCH      2
ESP      1
KAZ      1
IND      1
BEL      1
NEP      1
UZB      1
BUL      1
Name: NOC, dtype: int64

挪威也没有 NOC 代码,根据该数据集,挪威在冬季奥运会上以 111 枚金牌领先。然而,截至 2014 年索契冬奥会(这是该数据集中最近的一次冬季奥运会),官方统计数据为 118 次,其中缺少了一些 1992 年和 1994 年的数据。然而,像田径运动一样,这并不是一个巨大的偏差。

然后我们可以看到挪威在冬季奥运会上占主导地位的运动:

Cross Country Skiing    33
Speed Skating           25
Biathlon                15
Nordic Combined         13
Alpine Skiing           10
Ski Jumping              9
Figure Skating           3
Freestyle Skiing         2
Curling                  1
Name: Sport, dtype: int64

因此,越野滑雪是挪威的强项,共获得 33 枚金牌。

我们可以使用熊猫的crosstab函数来可视化这些奖牌分布

作者图片

与美国相比

作者图片

请注意,并不是每一项冬季运动都有代表,因为美国并没有在每一项冬季运动中获得奖牌。例如,冬季两项没有出现,不像在挪威的图表中也有一些运动没有出现。

广义线性建模

现在我们已经做了一些基本的汇总统计,让我们看看我们是否可以建立一个模型来预测单个运动员(而不是一支球队/国家)赢得奖牌的机会。有各种方法可以做到这一点,如训练神经网络,但在本文中,我们将重点放在广义线性模型(GLM)。

回想一下,线性回归通过一些解释变量 X 的线性组合,对一个连续变量 y ~ N( μσ )进行建模。例如,我们可以根据运动员的身高和性别预测他们的体重,如下所示

其中 β 是第 i 名运动员的每个特征的系数——在这种情况下,是身高和性别——而 ϵ 是残差的误差项。这可以更概括地描述为:

关于线性回归的更深入的讨论,见这里和这里。

像这样的线性回归模型满足三个关键属性:

  1. 它们有一个随机成分y——我们的因变量——遵循正态分布。
  2. 如上所述定义的线性预测器,通常称为 η
  3. 将线性预测器连接到均值的链接函数 g 在线性模型的情况下, g 是恒等链接函数 g,因此g(ηᵢ)=*ηᵢ=*μᵢ

现在假设我们想预测自奥运会以来每个国家获得的奖牌数。因为我们的 y 变量统计的是奖牌数,它是一个离散变量,违背了线性回归中使用的正态分布下连续变量的假设。在这种情况下,更合适的模型是泊松回归模型。这是一个广义线性模型(GLM)的例子。

广义线性模型在某种意义上是广义的,尽管在它的根部仍然有一个线性模型,但是随机分量 y 可以是分布的指数族的任何成员(例如,正态、伽玛、泊松等),并且链接函数可以是任何函数,只要它是平滑且可逆的。

作者图片

假设我们想模拟一名运动员是否获得了奖牌:铜牌、银牌或金牌。因为这是一个二元结果,我们的响应变量 y 应该遵循伯努利分布 y ~ Bin(1 ,p )=Ber( p ),我们的线性预测器的链接函数定义如下:

在哪里

逆 logit 函数称为逻辑函数,它基于线性预测值对赢得奖牌的概率进行建模。由于通常 n = 1(因此我们得到 μᵢ = pᵢ ),这个模型被称为逻辑回归。

我们将以游泳为例,展示具有物流链接功能的 GLM:

请注意,有几个身高和体重条目是 NaNs,因此我们将删除这些条目以及年龄,以便更好地衡量:

我们还将我们的响应变量 Medal 建模为 0 代表北美,1 代表金牌、银牌或铜牌

最后,我们将性别编码为 0 代表男性,1 代表女性:

现在我们准备好构建我们的模型了。我们将使用statsmodelspatsy 包,您可以使用 pip 来安装它们。statsmodels包含了我们将需要来适应我们的 GLM 的函数,而patsy是一个用户友好的库,用于构建我们可以使用以前的包来适应的统计模型。让我们从一些简单的事情开始,建立年龄和奖牌结果之间的关系模型。我们将首先安装软件包并运行以下代码:

pip install statsmodels
pip install patsy

运行此代码,我们获得以下输出:

作者图片

这个输出包含很多内容,但是我希望您关注的主要内容是两行,截距和年龄,以及偏差。对于前两行中的每一行,它们都列出了该参数的估计系数β、标准误差、z 得分、表示模型中该预测值显著性的 p 值以及估计系数β的置信区间。

偏差是对残差平方和的概括,它量化了 GLMs 的拟合优度。理想情况下,我们希望这个度量小于 n-p ,其中 n 是观察值的数量(18776),而 p 是我们模型中的参数数量(2)。因此我们的偏差是 14645<18776–2 = 18774。因此,模型通过了拟合优度测试,但让我们尝试将其可视化。statsmodels没有用于 GLMs 的直观绘图库,但我们可以使用matplotlib绘图库轻松地对其进行编码,绘制拟合概率与年龄的关系。

作者图片

这并没有真正给我们一个很好的拟合,这是有道理的,因为年龄不一定与性能的增长率相关联。让我们尝试添加额外的特征,比如身高、体重和性别。

根据高度绘图,我们获得了稍微好一点的拟合,正如偏差从 14645 下降到 14202 所证明的那样,但它仍然不能有效地给我们的数据一个稳健的拟合。年龄不是一个具有高 p 值的重要预测因素,这在我们的年龄模型中并不令人惊讶。

回想一下,美国的第二大运动是游泳,所以我们可以将美国作为一个解释变量。与该数据集中的性别二进制分类(不包括任何非二进制运动员)不同,国家(NOC)是一个跨越两个以上类别的分类变量,因此我们需要以这样一种方式修改它,即我们有一个列来指定某个运动员是否代表美国。pandas有一个函数get_dummies(),它创建一个虚拟变量,将输入列的每个分类变量二进制化。

作者图片

这将删除 NOC 列,取而代之的是为每个国家添加二进制列,以“NOC_”为前缀,表示某个运动员是否代表该国。因此,“NOC_USA”告诉我们一名参赛运动员是否代表美国,而“NOC_CAN”告诉我们一名运动员是否代表加拿大。

现在让我们将这个新变量添加到我们的模型中,看看它是否能更好地拟合我们的游泳数据。我们将删除年龄,因为它的表现不佳,并再次按高度绘图。

这给了我们一个比以前的模型更好的拟合,从 14202 年到 11922 年偏差的显著下降也可以看出这一点。鉴于美国在游泳方面的声誉,根据数据,成为美国人会增加一个人成功的机会是有道理的。如果我们建立 0.6 或 0.7 的截止概率作为决定奖牌结果的阈值,我们将获得非常接近二进制数据的拟合。

结论

在本文中,我们学习了 GLMs,使用一个综合的奥运会数据集作为逻辑回归的例子,以及一些数据格式化/清理技术。虽然 GLMs 是统计建模的强大工具,但它们也有缺点。如果数据集包含大量要素,则可能会过度拟合模型或遇到性能计算瓶颈,具体取决于数据集的大小。此外,还有其他不在该数据集中的特征可以改进我们的模型,例如在非奥运场馆的运动表现(例如网球的温布尔登)。还有其他可能更有效的数据建模方法,如支持向量机或神经网络。最后,对于像这样的历史数据集,很可能会因为有争议的视图而导致缺失值或错误,因此当您从该数据集和类似数据集得出结论时,请记住这一点。

我希望你喜欢这篇文章。我鼓励你自己尝试这个数据集并进行分析。请在下面的评论中告诉我你的经历,或者如果你有任何问题。编码快乐!

用于机器学习的 Golang?

原文:https://towardsdatascience.com/golang-for-machine-learning-bd4bb84594ee?source=collection_archive---------2-----------------------

意见

Golang 是建立机器学习管道的未来吗?让我们试着建一个。

Go 或 Golang 是 Google 在 2007 年设计的,在语法上与 C 类似,但具有内存安全、垃圾收集和结构类型。除了其惊人的快速性能之外,与 Python 不同,Go 允许简单的并发,就像在 C++或 Java 中一样。并发性允许多个程序或算法(包括 ML 的那些)异步执行,而不影响最终结果。

照片由 Fotis Fotopoulos 在 Unsplash 上拍摄

考虑到这一点,我计划比较使用 Golang 构建一个简单的 ML 管道的优缺点。我将同时使用 Python 作为参考点。此外,我将提供我个人对这种语言的总体看法,并评估 Go 在 AI/ML 社区中是否有前途。所以,让我们开始吧。

**注意:**在我们继续之前,这篇文章不会介绍如何在你的机器上安装和设置 Go。如果您还没有这样做,请遵循这些全面的说明。

目录:

  1. 设置
  2. 数据帧
  3. 数据操作
  4. 围棋中的机器学习

设置

首先,我们需要在我们的终端中安装以下软件包。

  1. 安装 DataFrameGoNum 包及其依赖项。DataFrame 和 GoNum 类似于 Python 的 NumPy,通常用于操作 DataFrame 对象。
$ go get -u github.com/kniren/gota/dataframe
$ go get -u github.com/gonum/matrix
$ go get -u gonum.org/v1/gonum/...

2.安装 GoLearn 包。GoLearn 是 GoLang 中的一个机器学习库,类似于 Python 的 sklearn。它允许简单的矩阵操作、ML 算法的构造、模型拟合,甚至用于训练/评估过程的数据分割。

$ g++ --version # make sure you have a G++ compiler$ go get github.com/gonum/blas$ go get -t -u -v github.com/sjwhitworth/golearn
$ cd $GOPATH/src/github.com/sjwhitworth/golearn
$ go get -t -u -v ./...

既然困难的部分已经过去,让我们进行更有趣的部分吧!

数据帧

我们将使用描述不同类型鸢尾花的鸢尾数据集。您可以通过在终端中运行以下命令来获取 IRIS 数据集:

$ wget [https://raw.githubusercontent.com/sjwhitworth/golearn/master/examples/datasets/iris_headers.csv](https://raw.githubusercontent.com/sjwhitworth/golearn/master/examples/datasets/iris_headers.csv)

确保将。CSV 文件,位于您当前正在处理的文件夹以及您的 main.go 文件所在的位置。

我们需要首先将下面的包导入到我们的 main.go 程序文件中。

现在我们已经有了所有的导入,让我们编写 main()函数来加载 CSV 数据并很好地打印出来。

您将得到以下漂亮的数据摘要,它描述了行数(150)、属性数(5)、属性摘要(包括数据类型)以及前几行的摘要视图。

虹膜数据帧摘要(图片来自作者)

相当整洁!到目前为止,这些操作中的大部分与您在 Python 中的编码方式相似。

数据操作

现在让我们来探索如何在 Go 中执行数据操作。

1。子集化

Python 中最简单的子集化操作之一是使用 df.head() 操作。我们可以在 Go 中类似地执行这个功能。

head := df.Subset([]int{0, 3})                       fmt.Println(head)

您将看到数据帧的前两行。

在 Go 中设置数据帧的子集(图片来自作者)

个人觉得操作没有 Python 中的那么啰嗦。如果事先不了解 Go 中的数据类型,您将很难理解这个函数。

2.过滤

假设现在你想探索鸢尾属物种的属性。您可以使用函数 filter()过滤行,如下所示。

versicolorOnly := df.Filter(dataframe.F{
    Colname:    " Species",
    Comparator: "==",
    Comparando: "Iris-versicolor"
})fmt.Println(versicolorOnly)

您将只检索带有鸢尾-杂色物种的行!

按物种名称过滤(图片来自作者)

您也可以将比较器属性与>、≥、<或≤的属性互换。

就我个人而言,我不介意语法上的变化,因为这些操作到目前为止看起来非常直观。但是这些程序的字数明显比 Python 中的长,如下图所示。

versicolorOnly = df[df[" Species"] == "Iris-versicolor"]

3.列选择

除了子集化和行过滤之外,还可以通过下面的简单操作对列进行子集化。

attrFiltered := df.Select([]string{"Petal length", "Sepal length"})                       fmt.Println(attrFiltered)

您可以找到许多其他的数据争论操作,包括连接、聚合、函数应用(回想一下。在熊猫身上应用()。)、等。

总的来说,我还是更喜欢 Python,但可能是因为我没有足够的围棋实践经验。然而,Go 的冗长可能会阻止我追求前者。

围棋中的机器学习

既然我们已经在 Go 中处理了一些数据帧,我们可以开始构建一个简单的机器学习管道。对于这个例子,让我们建立一个简单的 KNN 分类器来确定鸢尾的物种类型,给定它的属性集合(例如,花瓣长度,花瓣宽度等)。

0.重新加载数据

在 main()函数中,让我们重新加载 CSV 数据集。

fmt.Println("Load our csv data")
rawData, err := base.ParseCSVToInstances("iris_headers.csv", true)if err != nil {
    panic(err)
}

1.初始化 KNN 分类器

这里,我们从 GoLearn 的 knn 子包 中初始化一个新的 KnnClassifier。然后,我们将必要的属性传递给新的分类器类:使用欧几里德作为距离函数,线性作为算法核心,使用 2 作为选择的邻居数量。

fmt.Println("Initialize our KNN classifier")
cls := knn.NewKnnClassifier("euclidean", "linear", 2)

2.培训-测试分割

像往常一样,我们执行训练/测试数据分割(各 50%)。到目前为止没有什么新奇的,一切看起来都和我们在 Python 的 sklearn 库中做的一样。

fmt.Println("Perform a training-test split")
trainData, testData := base.InstancesTrainTestSplit(rawData, 0.50)

3.训练分类器

任何 ML 流水线的主要部分将是分类器的训练。但是,如果你熟悉 Python 的 sklearn 包,那么 Go 中的过程即使不完全相同,也是相似的。

cls.Fit(trainData)

4.汇总指标

训练步骤完成后,我们可以使用保留的测试数据执行评估,并检索性能总结。

fmt.Println("Print our summary metrics")confusionMat, err := evaluation.GetConfusionMatrix(testData, predictions)if err != nil {
    panic(fmt.Sprintf("Error: %s",err.Error()))
}fmt.Println(evaluation.GetSummary(confusionMat))

如果一切顺利,您将在终端中打印出以下内容!

我们的 KNN 分类器的评估总结(图片来自作者)

不算太差!对于新训练的 KNN 分类器,我们达到了 97.73%的准确率。尝试并实现你能在 GoLearn 中找到的其他类型的分类器!

最后,您可以在下面的代码片段中找到完整的代码!

结论

总的来说,我发现构建机器学习管道的 Go 语法足够直观。不过我发现 Go 的 ML 社区规模比 Python 的要小。这使得故障排除非常麻烦,有时甚至令人沮丧。此外,许多这些包中缺乏 GPU 支持会阻碍您的 AI 开发过程。不仅如此,不同的 ML 相关包之间似乎也很少有互操作性。例如,GoLearn 包实现了自己的 Dataframe“Instance”类,该类可能无法很好地与原生的 GoNum 类甚至 GoTA 的 data frame 对象一起工作。

尽管如此,Go 凭借其高超的速度和并发性,有可能在机器学习应用中超越 Python 但它需要有足够的数量(即临界质量)的人工智能开发人员这样做。

做订阅我的邮件简讯:【https://tinyurl.com/2npw2fnz】在这里我定期用通俗易懂的语言和漂亮的可视化方式总结 AI 研究论文。

参考文献

[1]https://en . Wikipedia . org/wiki/Go _(编程 _ 语言)

[2]戈努姆:https://github.com/gonum/gonum

[3]戈勒恩:https://pkg.go.dev/github.com/Soypete/golearn

[4]戈塔:https://github.com/go-gota/gota

Golang vs Python: 6 个问题决定哪种编程语言最适合你

原文:https://towardsdatascience.com/golang-vs-python-6-questions-to-decide-which-programming-language-is-best-for-you-cf5aa5902c57?source=collection_archive---------14-----------------------

这两种编码语言一决雌雄——但是谁是赢家呢?

阿尔瓦罗·雷耶斯在 Unsplash 上拍摄的照片

在这个世界上,编写任何代码的能力都是一个巨大的优势,通常程序员面临的最大问题是知道从哪种语言开始学习,而不是是否要学习一种语言。你能想到的每一种用途都有不同的语言。在这些流行的编码语言中,程序员经常面临 Golang 和 Python 的激烈竞争。(官方名称是 Go,但网站名称是 Golang.org,所以程序员通常把它称为两者之一。)

从表面上看,这两者明显不同:Python 创建于 1991 年,是编码领域的老古董,而 Go 由 Google 于 2012 年首次发布,相对来说是个新手。Go 以其速度著称,而 Python 是一种速度较慢的语言。Python 是通用的,而 Go 在语法和格式上更严格。

然而,它们都被认为是许多典型编码问题的答案:作为初学者,学习哪种语言最好?哪种语言是获得计算机编程工作的最佳语言?哪种编码语言最好?每种语言都有其追随者,他们声称自己的语言无论如何都是最好的。

事实上,就像我写的每一篇关于如何在线学习计算机科学的文章一样,这很复杂。你是否应该学习 Go vs Python 的答案取决于你是否是初学者,你想要什么工作,你的计算机科学历史,以及你的目标是什么。

目录

· [Table of Contents](#1589)
· [Let’s start with a brief historical definition of Golang vs Python](#326d)
· [Golang vs Python: Which coding language is best for beginners?](#4367)
· [Golang vs Python: Which coding language is best for experienced coders?](#d304)
· [Golang vs Python: Which language is best for a job in computer science?](#b6a8)
· [Golang vs Python: Which language is best for machine learning?](#32de)
· [Golang versus Python: Which language is best for programmer productivity?](#1fe9)
· [Golang vs Python: Which language is best for the future?](#ab3a)
· [What’s the best language when deciding Golang vs Python?](#18d7)

让我们从 Golang vs Python 的简单历史定义开始

Python 在 1991 年出现在编码领域,是由吉多·范·罗苏姆写的,他想要一种我从未听说过的编程语言的继承者,叫做 ABC 编程。它的特点是可读性、多功能性和可伸缩性。它是一种语言的怪兽,拥有巨大的库、热情的支持者社区(称为 pythonistas ),以及三个不完全兼容的版本。

与此同时,Go 于 2012 年发布,很像雅典娜,完全由它的父亲罗伯特·格里塞默(Robert Griesemer)、罗布·派克(Rob Pike)和肯·汤普森(Ken Thompson)在 2009 年发布。这是一种为特定目的而构建的语言,是为了解决谷歌当时在代码中面临的许多问题,也是出于恶意,因为创建者都不喜欢 C++。它的支持者(地鼠)喜欢它,因为它吸取了 C 和 Javascript 等语言的精华,同时避免了它们的缺陷。

当您开始考虑 Golang 与 Python,以及您希望哪种语言用于哪项任务(或者您希望别人叫您哪种编码昵称)时,记住这些背景知识是非常有用的。两者都有优点和缺点,但是根据您的最终需求,在 Golang 和 Python 之间有一个确定的答案。

Golang vs Python:哪种编码语言最适合初学者?

众所周知,Python 最适合绝对编码婴儿。给你一些背景,我能够按照指令运行一个用 Python 编写的 Instagram 活动自动化机器人,只需要很少的编码能力。这个机器人很复杂,但我的成功实现通过模拟我在照片上的喜欢活动,使我的猫的 Instagram 账户增长到近 16k 粉丝。(Instagram 后来取缔了这类远程互动。)我发现错误很容易解决,语言很容易阅读,社区也非常支持我。简而言之,像我这样的完全新手的好语言。

Python 的编写方式使得它非常适合初级程序员学习。刚接触编码概念的人会发现 Python 比 Go 更容易学。围棋对于初学者来说是可以学习的——我已经写了一整篇关于为什么初学者应该在 2021 年学习围棋的帖子——但是 Golang 的许多主要特性和好处会被资深程序员更好地理解。

与此同时,就哪种语言最适合绝对的编码初学者而言,Python 是我的赢家。套用我以前一篇关于2021 年哪种语言最流行的文章,Python 对初学者来说很好,因为它:

  • 读起来像英语
  • 足够快速地构建一个功能原型
  • 对于初学者可能想尝试的任何项目来说都足够通用

综上,当问题为“Golang vs Python:哪个最适合新手?”对于大多数人来说,答案是 Python。

Golang vs Python:哪种编码语言最适合有经验的编码人员?

我可能已经在前面的部分给出了这个游戏,但是我的答案是 Golang(假设你没有做任何 AI/ML 工作)。Go 通常更适合那些已经知道如何编码并想在他们的武器库中增加另一种编程语言的人。

正如我上面所说的,它是基于谷歌工程师现有的问题而创建的。与许多其他语言相比,它被设计成更好的*。它易于编写和阅读(尽管更冗长),并且运行速度比 Python 代码快得多。像 Python 这样的不同版本之间也没有混淆。当我在猫的 Instagram 账户上使用机器人时,我遇到的主要问题是版本之间的兼容性。*

Go 有一个更简洁的语法和一组更紧凑的库。它对那些想用更少臃肿的语法变得更有效率的程序员很有帮助,因为它完全符合你的想法— 如果你是一个有经验的程序员。此外,它是为了扩展到大型项目而构建的,就像 Google 在本世纪初开发这种语言时所面临的恐惧一样。

如果你是一个有经验的程序员,Golang 是一个很好的、容易掌握的、有用的语言。你将能够欣赏到其他语言上所有初学者可能不会欣赏的小改进,比如命名约定。对于有经验的程序员来说,Go 轻松赢得了 Golang vs Python 之战。

Golang vs Python:哪种语言最适合计算机科学的工作?

许多人和我一样,喜欢编码,却没有真正去找一份计算机科学的工作。作为一名业余爱好者,我很高兴自己的大部分收入来自写作。但我是少数。

因为学习编码是一个巨大的承诺,大多数学习编程的人都是为了钱——这也不可耻。尤其是当学习编程的成本可能很高时,比如当你考虑计算机科学证书或文凭等选项时,为了最好的就业前景,优化语言学习是有意义的。

因为他们独特的特点,Golang vs Python 的这个特殊答案也取决于你想要什么工作。如果你正在找一份入门级的工作,Python 是最好的。学习 Python 可以让你快速掌握编码概念,并且能够完成新工作中可能需要的几乎所有任务。

或者,如果你雄心勃勃地想找一份收入最高的工作,那就去吧。

(双关。)

正如我在我写的 2021 年最流行的编码语言中所解释的,Go 以其顶级语言而闻名,因为:

  • 它是为大项目建造的,通常由大公司运营
  • 它比 Perl 更快更容易学,Perl 是收入最高的语言
  • 编写它是为了减少调试和阅读代码的时间,这是一项非常有价值的技能

这不是一种通用的语言,但对那些像优步、Twitch、Dropbox,当然还有谷歌这样正在招聘围棋开发者的公司来说更好。

Golang vs Python:哪种语言最适合机器学习?

机器学习是那些包含大量可能性的术语之一。在这篇关于 Golang 和 Python 的文章中,我将“机器学习”定义为编写一个可以对外部刺激做出决策的模型。例如,机器学习可以帮助你的 gmail 帐户确定谁在给你发垃圾邮件,谁实际上是你失散多年的阿姨,向你发送一个关于你不想错过的潜在遗产的重要信息。

对于想要编写机器学习模型的编码人员来说,Python 当然是最受欢迎的选择。

Python 领先,57%的数据科学家和机器学习开发人员使用它,33%的人优先开发它。

开发商经济公司的克里斯蒂娜·沃斯科格鲁

Python 在机器学习方面如此受欢迎的部分原因是它是 TensorFlow 的家园,tensor flow 是 Python 中发布的深度学习框架。Go 的优势在于其简单、易于实现的库和框架,Python 在复杂、众多框架中深厚而丰富的历史使其成为机器学习的最佳语言。TensorFlow 无疑是这些库中的佼佼者,但 Keras 和 Scikit-learn 也是著名的库。

值得注意的是,受欢迎程度并不等同于质量。虽然 Go 在流行程度方面甚至没有排在机器学习的前 10 种语言中,但 Websensa 在他们的帖子中承认哪种语言是最好的,“Go 更快,更具可扩展性和性能,因此它非常适合大规模项目。这使得它成为研究机器学习基础设施的最佳选择之一。”也许在未来 Golang 和 Python 之间的辩论中,Go 将成为机器学习编码器的首选。

Golang 与 Python:哪种语言最有利于程序员的生产力?

生产力,就其基本定义而言,就是高效地完成大量有意义的工作。由于选择的悖论,当使用有限的工具集时,人类(因此也是人类程序员)往往最有效率。

所以,Go 是成为一个更有生产力的程序员的最佳语言。语法如此有限,库也不那么臃肿,以至于用更少的代码行就能更快地完成工作,因为只需编写更少的代码。

仅仅通过库的数量和语法的范围,Python 就在多功能市场上占据了优势。但是多功能性是有代价的,这个代价就是生产力。

有趣的是,Python 有时被推荐为初学者最高效的语言——用 Python 很容易快速启动并运行程序,而且用 Python 几乎可以做任何事情。

然而,在这场“Golang vs Python:哪种语言的生产力最高?”我认为 Go 是最好的,因为它更有效率,更容易调试,格式相似,最重要的是,它易于阅读。永远不要忘记编码是一种协作行为——你花在理解别人编码上的时间越少,就越容易做出有成效的贡献。

Golang vs Python:哪种语言最适合未来?

像地球上的其他人一样,我看不到未来。但我可以做一个有根据的猜测。当谈到用最经得起未来考验的语言来衡量 Golang 与 Python 时,我的猜测是 Go。也就是说,Python 仍然处于主要的增长轨道上,所以它也是一个很好的选择,我不认为这两种语言在不久的将来会失宠。

Python 无疑有着悠久的历史——它已经存在了 30 年,经历了三个脆弱和不兼容的版本,它比许多其他过时的语言都长寿,自 2003 年以来,它一直名列十大最受欢迎的语言,并且在 2018 年发生的仁慈的终身独裁者(又名创始人圭多)退休后,它仍在继续。它正在快速获得新用户,并且没有放缓的迹象——2019 年,Pythonistas 第一次超过了 Java 开发人员(据我所知,他们甚至没有一个酷而有趣的昵称)。

但是 Python,像许多其他更古老的语言一样,是一种不圣洁的聚合怪兽,由许多杂乱无章的库、语法和框架混杂在一起组成。它的多个版本组合起来很笨拙,并且通常不可移植。例如,Python 2 计划在 2015 年庆祝它的生命终结。根据维基百科文章的说法,该项目被推迟了五年,“因为担心大量现有代码不容易被移植到 Python 3 上”。那不是未来的证明。

与此同时,如果我看着我不存在的水晶球,问自己一个世纪后谷歌是否还会存在,我简直无法想象它不会存在。如果谷歌仍然存在,那么 Go 或者它的某个版本也会存在。Golang 的创建不仅是为了解决谷歌当时的问题,也是为了解决它未来可能遇到的所有问题。

对我来说,它的品牌认知度和专用特性意味着,在 Golang 和 Python 之间的竞争中,它似乎是未来最有可能成为最佳语言的竞争者。

决定 Golang vs Python 的时候用什么语言最好?

如果你已经走到这一步,还在寻找一个明确的答案,我不得不让你失望了:没有答案。就像问学西班牙语好还是意大利语好。明年夏天你打算去意大利还是西班牙?这就是你的答案。

Python 和 Go 都是很好的学习语言。如果你想在 Golang 和 Python 的战争中找出哪一个对你最有利?嗯,首先你需要弄清楚你要去哪里。

高尔夫运动日不是真的

原文:https://towardsdatascience.com/golfs-moving-day-is-not-a-real-thing-722317cb28f3?source=collection_archive---------36-----------------------

第二轮是更好的行动

高尔夫球评论员经常引用的一个短语是“移动日”,这是一场锦标赛四轮中的第三轮的名称。据说在搬家日的,,尤其是,球员们会争抢位置,试图在最后一天给自己一个荣耀的机会。但是,当然球员只是试图在每一轮投篮低,第三轮没有不寻常的位置变化,是吗?简短的回答是:不,不是;事实上,随着回合的进行,排行榜上的移动越来越少;移动日并不是一个真实的现象。

数据

为了调查这一点,我收集了四大赛事的轮末得分数据,从 1990 年的两个案例(公开赛、大师赛)和 1999 年的另外两个案例(美国公开赛、美国 PGA),到 2021 年。用于收集数据的代码在这里是。在下面的所有分析中,分数和排名仅过滤给在第二轮结束时晋级的球员(大约一半的场地),以便可以确定所有球员在三对回合之间的位置变化。在平局的情况下,玩家的位置被设置为平局中最高的位置(最小的数字);例如,对于并列第十的两个玩家,都被分配位置 10。

圆周运动

从第一轮结束到第二轮结束,玩家位置的平均变化(向上或向下)最大,在后面的几轮中减少。换句话说,第二天排行榜上的活动比第三天多。

这是有意义的,因为随着更多轮次的进行,玩家之间在质量或形式上的差异有更多的机会表现出来,并且该领域的总得分随着时间的推移变得更加分散:总得分的四分位数范围(IQR)从第一轮后的 3.1 增加到第二轮后的 3.7,以及第三轮后的 5.3。因此,排名前 30 的球员通常会发现自己在第三轮开始时需要比第二轮开始时(0.15)更多的杆数才能上升一个位置(0.23),到第三轮结束时(0.31),位置之间的杆数甚至更多。此外,特别低的回合分数,例如能够实现大动作的分数,在第三轮中并不常见:第三轮(69.1)和第四轮(69.0)中单回合分数的第十个百分位数是相似的(不可能通过包括或排除错过晋级的球员来公平地将这些分数与第二轮进行比较)。

我们可以通过计算连续几轮结束时排行榜之间的肯德尔排名相关系数来以另一种方式衡量排行榜的变化。更大的系数意味着两轮之间的排行榜看起来更相似,因此在两轮比赛的后一轮中运动更少。

对于所有四个比赛来说,随着比赛的进行,排行榜变得更加稳定,至少在过去的 30 年里是这样。这种进展是稳定的:在第三轮结束时,排行榜活动没有明显下降,第二轮结束后也是如此。2018 年美国网球公开赛是第三天活动量不同寻常的一场比赛:这是一个的案例,当天晚些时候得分条件更难,这使得球员有可能更早出局,以弥补领先的位置。

获胜的机会

因此,第三天看到不寻常的仓位变化的想法并没有被现实所反映。的确,第四天的运动量减少了,所以玩家必须在第三天“行动”而不是等到最后一轮的想法是有一定道理的。然而,更具决定性的一点似乎是在第二轮结束时:在第二轮结束时,只有 10%的最终获胜者是已经进入前十名的而不是。前十名之外的人在最后两轮比赛中冲锋是最常见的,尽管仍然不太可能(19%的赢家)。

在第三轮结束时没有进入前十名的赢家甚至更少(2%的赢家),尽管如果我们看一下前 5 名或前 1 名的位置(未显示),从第二轮结束到第三轮结束的下降没有那么明显。因此,我们可以说,在第三轮中进入前十是非常重要的,因为玩家有任何获胜的机会,但如果他们在第二轮结束时没有进入前十,这已经是一个漫长的镜头。

今年的四名获胜者在第二轮比赛后分别排名第六、第一、第五和第二,到第三轮比赛结束时,这四名分别成为第一、第一、第六和第二名。因此,松山秀树是移动日哲学的一个例子——他从第六名跃升至第一名,比之前的领先者多了七杆,并赢得了 2021 年的大师赛——而乔恩·拉姆表明,第三轮的“移动”并不重要,因为他在第三天从第五名滑落至第六名,在领先者身上失去了一杆,然后恢复到赢得 2021 年美国公开赛。

一个(好得多的)评估你的机器学习模型的方法

原文:https://towardsdatascience.com/good-approach-to-evaluate-your-machine-learning-model-e2e1fd6aa6bb?source=collection_archive---------9-----------------------

使用一个或两个性能度量标准似乎足以宣称你的 ML 模型是好的——它很可能不是。

对于像我这样的数据科学家来说,使用经典的性能指标来恰当地评估 ML 模型是多么的困难。

即使可以使用多种指标和评分方法,理解我(可能还有许多其他人)面临的问题的正确指标仍然具有挑战性。这就是为什么我在大部分 ML 模型质量评估中使用飞贼 AI 的原因。在过去的两年里,我一直是开发飞贼 AI 的积极成员。

https://snit.ch?utm_source=blogOlivier&utm_medium=referral&utm_campaign=abetterapproach

让我用一个例子来解释为什么选择正确的指标如此重要:使用 UC Irvine 机器学习存储库中集中的数据生成一个可以预测公司破产的模型。该数据集名为台湾破产预测(由 CC 4.0 授权),利用了《台湾经济日报》1999 年至 2009 年的破产数据。

问题:不平衡的数据集

您将遇到的第一个问题是数据集中的不平衡。这既是好消息,也是坏消息。好消息是只有 3.3%的公司破产了!另一方面,坏消息是数据集中的不平衡使得预测“罕见阶层”(3.3%)变得更加困难,因为我们的懒惰模型可以通过简单地预测没有破产来预测 96.7%的公司的正确命运。

作者的目标不平衡评估

您可以看到,这也是一个性能评估问题,因为大多数指标都偏向于最大的类,最终导致它们出错。为什么?预测没有破产使得我们的模型在理论上有 96.7%的准确性。这里有一个在飞贼 AI 中构建和评估的第一个模型的例子。默认情况下,该工具会计算多个相关的性能指标。正如你在下面看到的,我们的第一个模型获得了 96%的准确率。然而,当你看 F1 的分数时,,一个不平衡班级的更好的衡量标准,我得到的分数仅仅是 26%…

作者的初始质量分析图像

那么是什么原因呢?

不平衡数据集的解决方案

当处理不平衡的数据时,第二步是尝试使训练数据集更加平衡。你可以通过对多数类(非破产)进行欠采样、去除随机观察或对少数类(破产)进行过采样来实现这一点。

对于过采样,您可以复制随机观测值或使用成熟的算法创建合成观测值,如合成少数过采样技术。 SMOTE 的工作方式是选择相近的示例,在示例之间画一条线,然后在沿着这条线的一个点上画一个新的示例。

如您所见,我可以使用许多技术来增强我的模型。

有了飞贼,我可以清楚地看到我的各种实验的历史:

作者的多重质量分析图像

以下是我从上面的实验中学到的一些结论:

  • 欠采样和过采样技术显著提高了 F1 分数。这是好事!
  • 然而,这种性能的提高是以牺牲模型的整体质量为代价的。
  • 我们的模型 4(带欠采样的梯度提升)是最好的模型,因为它的性能几乎与模型 2 一样好,但质量通常更好。

等等!这个“质量分”是什么?

Snitch 使用大约十几个自动质量分析来生成这个质量分数。

质量分析产生:

  • **特征贡献得分:**到检查你的模型的预测是否有偏差或者在输入变量之间公平分布。
  • **随机噪声鲁棒性分数:**检查您的模型是否对噪声数据的引入具有鲁棒性。
  • **极端噪声鲁棒性得分:**检查您的模型是否对最坏情况噪声数据的引入具有鲁棒性。

图片来自飞贼 AI 质量分析方法论,2021。经允许重新发布

绩效评估很难

没有什么是来之不易的,绩效考核也不例外。虽然很难做到正确,但在开发模型时,性能评估需要认真对待。不是因为你有一个好的精度,你的模型才是好的。

事实是,准确性甚至可能不是一个相关的性能指标。在我们的例子中,F1 分数肯定更好,因为我们的数据集是不平衡的。这里的教训很简单。确保您验证了您选择的指标正确地衡量了您试图实现的目标。

尽管性能指标很重要(它们毕竟是关于测量你的模型预测结果有多好),但是这些指标不能验证数据偏差或者你的模型的整体稳健性。这里的一个好的实践是专门测试其他特征,如偏差和稳健性。

我们看到,一些模型在理论上比其他模型表现更好,但实际上质量较差。我们也看到了表现不佳但质量更好的模型。最终,目标是能够比较这些信号以选择最佳方法。

请记住,一个更好的方法不应该只关注于评估您的模型的性能,它实际上需要进行深入的测试,以确保您的系统也是健壮的,以便它实际上可以处理生产中的新数据…这就是奇迹需要发生的地方!

好的评估方法以及如何找到它们

原文:https://towardsdatascience.com/good-evaluation-measures-and-how-to-find-them-69a204045bb?source=collection_archive---------35-----------------------

我们使用理论方法来分析和比较分类和聚类的性能度量

Arie Wubben 在 Unsplash 上拍摄的照片

在每一个实际的机器学习任务中,都有一个测量结果的问题。对于部署的算法,我们可以考虑现实生活中的后果,如用户增长或财务收益,但我们需要在开发过程中更简单的性能测量。同时,不同的度量可以导致不同的评估结果,从而导致不同的选择算法。这就是为什么找到一个合适的质量衡量标准是至关重要的。

从分类和聚类到机器翻译和分割任务,许多研究领域已经产生了它们自己的一套完善的传统使用的度量方法。多年来,人们进行了几次比较性能测量的尝试,但这个问题仍然缺乏一个系统的方法。

在最近的论文[1,2]中,我们 Yandex Research 系统地分析了聚类和分类的验证方法。

绩效指标及其不一致性

分类是在无数应用中实现的典型机器学习任务。研究人员通常将预测的标签与实际标签进行比较,以使用性能度量来评估分类结果,如准确性F-度量等。但是,不同的度量表现不同。下面我们展示了降水预测任务中一些测量方法的不一致性(详见[2])。对于这个问题,分歧是巨大的。因此,它可能会极大地影响所做的决定。

天气预报数据的不一致性(降水预报),%

聚类是另一个广泛使用的任务,它有助于各种应用程序,包括文本挖掘、在线广告、异常检测和许多其他应用程序。目标是对相似的对象进行分组。这里,质量度量的问题更加明显:我们必须将预测的分区与实际的分区进行比较,这是非常重要的。例如,你能猜出物体的哪个部分更符合由形状和颜色表示的实际部分吗?

数据集的两个候选聚类,形状表示参考分区。

如果您很难决定哪一个更好,不必担心:已知的聚类相似性度量在这个简单的例子中并不一致。例如,广泛使用的 RandAdjusted Rand、Jaccard 测度偏好左划分,而变异信息归一化互信息偏好右划分。还有许多其他的聚类相似性度量,选择正确的一个是有争议的。

如何选择正确的衡量标准

因此,我们来了一个问题:如何选择一个合适的措施?为了回答这个问题,我们采取了一种理论方法。首先,我们定义一些性能度量所需要的属性。例如,对于一个完美的预测,人们会期望一个度量达到其最大值,而不完美的预测会有较低的分数。

恒定基线是的一个显著属性。它需要一种方法来避免偏向特定的类大小(用于分类)或聚类大小(用于聚类)。这种偏好可能会导致无意中选择部署更差的算法。事实证明,对于分类和聚类任务,几乎所有常用的度量都存在偏差。

公式化属性后,我们正式检查每个属性的多个已知度量。重要的是,我们的研究并没有提出所有应用都应该选择的“完美测量”。相反,当特定应用需要特定属性时,我们提供一种工具来帮助拒绝一些不合适的措施。下面是一些二元分类方法(包括建议的方法)的例子。

二元分类测度的性质

其他发现

我们的正式方法导致进一步令人兴奋的见解。例如,我们注意到没有一个性能度量同时满足所有的属性。特别是,不存在具有恒定基线属性并且可以线性转换为度量距离的测量。事实证明这在理论上是不可能的,也就是说这两个性质中至少有一个要舍弃。

如果我们放松恒定基线性质,但要求它保持渐近,我们有一个满足所有其余性质的措施。该相关距离可用于分类和聚类评估【1,2】。

如果我们放弃距离的要求,其余的性质也可以同时得到满足。对称平衡精度是一种非常有趣的测量方法——标准平衡精度与其对称精度之间的平均值。这种方法以前没有用于分类评估,它的类似物也很少用于聚类评估。有趣的是,对称平衡精度的良好特性对于多类分类也得以保留。这是唯一有这个优势的措施。

我们希望我们的工作将促进对其他更复杂任务的性能测量的进一步研究。

1Martijn gosgens,Alexey Tikhonov 和 Liudmila Prokhorenkova。“聚类相似性指数的系统分析:如何验证验证措施”ICML 2021。
[2]马丁·格斯根斯、安东·日扬诺夫、阿列克谢·吉洪诺夫和柳德米拉·普罗霍伦科娃。“好的分类措施以及如何找到它们。” NeurIPS 2021。

谷歌分析是数字营销,但数字营销不是分析

原文:https://towardsdatascience.com/google-analytics-is-digital-marketing-but-digital-marketing-is-not-analytics-ba73cbb4ee69?source=collection_archive---------30-----------------------

这些学科应用不同的方法和工具来进行分析,但最重要的是有着非常不同的目标

米利安·耶西耶在 Unsplash 上拍摄的照片

使用数据做出明智而及时的决策已经成为大多数现代企业和组织的成功因素。同时,随着存储和计算能力的增加,以及新技术和应用的发展,如社交网络的扩展,智能手机、基于物联网的设备的广泛使用等。数据的数量和格式发生了巨大变化,分析和处理数据的可能性令人印象深刻。

可能由于这种突然的发展,对于在庞大的数据生态系统中共存的不同专业人员的活动和角色,存在许多困惑和误解。

最常见的误解之一是将数字营销甚至市场研究与商业智能和分析混为一谈。这些学科应用不同的方法和工具来进行分析,但最重要的是有着非常不同的目标。

术语“谷歌分析”和“分析”经常被营销人员互换使用。实际上,它们代表了两个完全不同的概念。也许这种混淆的原因是 Google Analytics 和 Analytics 都将他们的分析建立在可测量的指标上,但这是相似之处结束和显著差异开始的地方。

让我们首先解释什么是数字营销,特别是这个学科用来产生信息的机制。

数字营销与通过数字渠道展示的广告有关,如搜索引擎、社交媒体、网站、电子邮件、移动应用程序。这是一个庞大的渠道系统,每个营销人员都应该将它整合到他们的业务中,这样他们就可以在世界各地提供产品和服务,而不用考虑国家和大陆。由于这种广告形式覆盖的范围很广,与传统方法相比,它成倍地增加了销售的可能性。

斯蒂芬·菲利普斯-Hostreviews.co.uk 在 Unsplash 上的照片

为了更好地了解互联网及其广告渠道的复杂世界,从而能够应用最佳公式来实现产品的成功,营销人员将需要专门的支持,如 Google Analytics 提供的支持,以便跟踪网站活动:总点击量、会话持续时间、每次会话的页面数、跳出率等。使用该网站的人的信息,以及流量来源的信息。

这些指标通常在广告仍在运行时可用,因此通常用于提高活动绩效。如果一些广告在特定指标上优于其他广告,将预算从低性能广告转移到高性能广告可能是有意义的。

广告商可以选择使用多种指标来优化他们的广告。例如,他们可能会查看视频视图,以了解哪个视频频道最适合更广泛地展示他们的信息,同时查看视频完成率,以判断哪个版本的广告最吸引观众。一般来说,您使用的度量越多,您获得的信息就越多,当然,前提是这些度量是相关的。

然而,值得注意的是,在营销领域,并非所有的决策都基于 Google Analytics 指标,许多市场研究和数字营销专业人员仍然使用主观衡量标准,如从定性方法中获得的标准。

照片由格伦·卡斯滕斯-彼得斯在 Unsplash 拍摄

例如,定性测量可能试图测量客户交互的质量。这些评论可以是营销活动前后撰写的评论,其中每个评论都有一个评级。这些质量审查基于简单的调查,如是或否问卷或标记预设答案。

有几种技术可以用来获得质量评估,一些最常用的是:调查、焦点小组、访谈和标杆管理。总的来说,尽管这些方法具有很高的主观性,但一些营销人员继续使用它们来试图更深入地了解消费者对各种话题的想法和观点。

定性方法,如果设计良好,应用正确,可以用于调查消费者行为中不太明显的方面。

当这些技术与定量方法结合而不知道如何做时,问题就出现了,更糟糕的是,仅仅因为你在使用数字尺度就相信定性测量是定量的,这是一个错误,经常退化为一系列无意义的“统计分析”。

由于这个原因,最近几年人们非常重视用数据分析的基本原理来装备所有商业职业的重要性。这种新技能被称为“数据文献”。该学科旨在强化每个专业人员都需要的必要知识,以便能够进行与其职业相关的主要数据分析。

由 Pakata Goh 在 Unsplash 上拍摄的照片

另一方面,业务分析、数据分析或简单的分析是一个分析任何类型的业务数据的过程,以将其转换为有用的信息,帮助业务领导者、经理和其他最终用户做出明智的决策。

分析包括各种各样的概念、技术、应用和工具,使分析师能够收集、清理、分类、调整和分析数据。

该流程的结果应允许开发和执行数据查询,创建报告、数据可视化(数据 Viz)和仪表板,以可访问和清晰的方式提供公司决策者所需的信息。

通过使用分析,还可以配置工作流,以便在组织中更多更好地使用数据。

数据科学家或数据分析师也可以直接向其他部门的同事报告,根据他们的分析结果做什么。例如,可以创建解决方案,以便即使是未经培训的人也可以使用基于 R 或 Python 等专门程序的应用程序来更快更轻松地完成工作。优化工作流的最有效方法之一是基于机器学习模型的实现,只要目标和数据允许。

市场研究和数字营销也不是商业智能。BI 是一个定义非常明确的学科,属于业务分析,它使用特定的数据分析和可视化工具(仪表板)来描述业务的当前状态,并提供组织支持决策所需的最相关的信息。

商业智能可以涉及公司价值链的不同阶段,从绩效指标(KPI)的分析,到与供应链、生产、销售相关的指标,甚至是基于不同历史数据组合的未来业务场景的评估。

在 BI 分析中,与任何其他数据分析一样,必须使用特定的工具对来自不同来源的原始数据进行集成、整合和清理,以确保最终用户处理准确一致的信息。

虽然有些分析非常简单,甚至可以使用 Excel 电子表格来报告见解,但 BI 平台作为集成数据系统的前端接口越来越受欢迎。这是因为 BI 工具不仅允许以更加实用和简单的方式处理大量数据,而且允许大量用户参与同一个项目,而不是典型的单一分析师方法。

马文·迈耶在 Unsplash 上的照片

因为分析适用于公司中的所有数据,所以它也适用于营销数据,我们可以称之为“营销分析”,但这也与数字营销或市场研究无关。这只是使用营销指标作为输入的数据分析的应用。

同样,这种方法可以应用于其他类型的数据,例如来自人力资源部门的数据,在这种情况下,它被称为“人员分析”

不仅营销使用的方法和工具与分析使用的方法和工具非常不同,而且它们的目标也非常不同。

让我们记住,营销的主要目标是销售产品或服务,从这个意义上说,营销专业人员将尽一切努力使购买决策有利于他们的建议,无论相对于其他选择有多好。

相反,分析试图探索所有可能的选项,分析风险并识别机会,以便为做出最佳决策提供必要的支持。

例如,在分析术语中,在没有令人信服的技术理由的情况下,支持或反对某一特定选项的行为被称为偏见。

正如我们所看到的,这些学科的名称有时会被混淆,但显然位于同一根绳子的两端。

照片由merit Thomas在 Unsplash 上拍摄

关于这一点,在 Cassie Kozyrkov(谷歌公司首席决策科学家)最近在 LinkedIn 上发表的一篇文章“误解 2:分析与新闻/营销”中,她写道:

“分析不是营销。区别在于,分析是为了扩大决策者的视角,而营销是为了缩小视角。”

在数据世界中,除了这里显示的错误概念之外,还有其他错误概念,像这样的文章的主要目的是揭示一些概念,这些概念即使对于经验丰富的专业人员来说也是令人困惑的。我认为所有的角色都同样重要,但最重要的是知道我们在哪里,不要混淆梨和苹果,因为我们对自己的道路越清晰,我们就可以开发更多更好的东西,并与周围的人分享。

面向 MLOps 的谷歌云服务

原文:https://towardsdatascience.com/google-cloud-services-for-mlops-d1702cd9930e?source=collection_archive---------22-----------------------

探索 Google 云平台上的 MLOps 选项

来自 Pexels 的 Axel Vandenhirtz 的照片

在 MLOps 是实践,而不是工具的故事中,我描述了 MLOps 的价值和核心组成部分。主要目标是远离特定的工具,强调人和过程。重点是什么(MLOps 定义)和为什么(考虑 m lops 的原因)。在这里,我将开始解决如何的问题,特别是如何使用谷歌云平台服务(以下简称 GCP 服务)来加强你的 MLOps 实践。

假设你想在机器学习中实现一个连续的交付和自动化管道。在这种情况下,有几种谷歌技术可以利用,我将区分两类:GCP 服务和人工智能管道功能。您的选择在很大程度上取决于您的环境、目标和 MLOps 成熟度。

这个故事分为三个部分:

  • MLOps 成熟度模型
  • 面向 ML 工作流的 GCP 服务
  • GCP 的 MLOps 框架(人工智能平台管道)

m lops 成熟度模型

您可以通过考虑您在 AI 项目中的自动化和可重复性水平来评估您的 MLOps 成熟度。本文中提出的一种方法是定义三个级别:

  • MLOps level 0 是人工智能计划的手动流程。
  • MLOps 一级带来 ML 流水线自动化。
  • ML ops 2 级支持所有 ML 活动的完整 CI/CD 渠道。

现在,您如何在您的组织中利用这种成熟度模型呢?首先,您需要了解您当前在 MLOps 实践方面的成熟度水平,这可以通过成熟度评估练习来完成。该评估将帮助您识别您在 ML 中的优势和劣势,不仅从过程的角度,而且从考虑现有的人员和工具的角度。

如果你不打算采取行动,做一个成熟度评估毫无意义。做评估的目的不是获得一个分数,而是确定你在哪里,你想去哪里。因此,下一步是确定您希望达到的目标 MLOps 水平。一旦你有了一个目标,你就可以做一个差距分析来确定你当前的状态和你的最终目标之间缺少什么。这些信息将帮助您定义实现目标的不同步骤(路线图)。

差距分析对于从人员、流程和技术角度理解如何改变您的组织至关重要。

差距分析,以确定目标状态和实现目标的路线图。

协调 ML 工作流程的 GCP 服务

现在让我们假设您的 MLOps 过程已经定义,并且您最终准备好利用工具来支持您的 AI 实践。

您将寻找一个支持整个机器学习生命周期的技术解决方案,从发现和可行性到模型实验和操作化。该工具必须理想地自动化人工智能实验、模型训练和评估、模型部署和模型监控的一些或所有方面。

GCP 有多种选择来支持这一需求。通常情况下,没有放之四海而皆准的解决方案。你必须根据你的目标和现有的团队来决定。为了满足不同的需求,选择多种工具是绝对没问题的。

首先要考虑的是 Google Cloud AutoML 。为什么是 AutoML?因为它将负责人工智能团队通常必须进行的许多活动。

使用 AutoML,您注入数据,它会训练一个与您试图解决的问题相关的模型。然后,您可以使用经过训练的模型,并将其用于在线或批量预测。AutoML 提供了一条捷径,并加速了几个典型的 ML 典型任务,如数据探索、数据准备、特征工程、模型选择、模型训练、模型评估和超参数调整。AutoML 简化了人工智能过程,并自动化了通常是 MLOps 一部分的任务。

GCP 的自动化:从数据采集到预测

Google Cloud 上 MLOps 的另一个选择是使用 GCP 服务创建一个管道。如前所述,MLOps 完全是关于人工智能任务的自动化,以支持端到端的生命周期。您可以使用完全托管的 GCP 服务来自动化数据提取、数据准备和模型训练。让我们以四个基本的 GCP 服务为例:BigQuery、云存储、AI 平台和 Cloud Composer。

您可以使用 BigQuery 进行探索性数据分析和数据准备(结构化或半结构化数据)。你可以在云存储中存储非结构化数据(图像、视频、音频),你可以使用人工智能平台来训练回归或分类问题的模型。您可以使用 Cloud composer 来编排从开始(数据采集)到结束(服务和监控)的流程。

编排 ML 工作流程的简单 GCP 服务。

GCP MLOps 框架

我刚刚介绍了一些支持基本 MLOps 流程的简单 GCP 服务选项。但是对于更高级的需求,您可能想要考虑使用 MLOps 框架。目前最受欢迎的是 Kubeflow Pipelines 和 Tensorflow Extended (TFX)。两者都是开源框架,在 GCP 上得到完全支持。

Kubeflow 是一个 Kubernetes-native 机器学习工具包。使用 Kubeflow Pipelines ,您可以基于容器构建和部署可移植的、可伸缩的端到端 ML 工作流。Kubeflow 最初是 Google 的一个内部项目,后来它被开源了,现在它可以在任何支持 Kubernetes 的地方运行(云和本地)。

使用 Kubeflow,第一步是使用特定的 SDK 创建管道定义。一旦定义了管道及其不同的组件,您需要创建一个 Kubeflow 实验来运行管道。然后,各种组件被封装起来,作为工作流在 Kubernetes 集群上执行。

另一个流行的 MLOps 框架是 Tensorflow Extended (TFX)。TFX 始于 2017 年,是谷歌的一项内部计划,并迅速成为大规模端到端 ML 的首选框架,不仅在谷歌内部,而且在所有其他 Alphabet 实体中。然后在 2019 年,TFX 成为公开的开源软件。

TFX 是一个配置框架,它提供了定义、启动和监控 Tensorflow 机器学习系统的组件。TFX 库中有多个组件,您可以根据您的 MLOps 需求组装它们,以创建一个有向无环图(DAG 是您的 TFX 管道)。管道通常会混合数据接收和验证、数据转换、ML 建模、模型分析和模型服务步骤。

TFX 组件(图片来自https://www.tensorflow.org/tfx)

如果 TFX 提供了定义管道所需的一切,那么您必须利用外部的编排器来运行管道。在撰写本文时,TFX 支持的 orchestrators 是 Apache Airflow、Apache Beam 和 Kubeflow。这一步非常简单,因为它主要是管道中的一个配置,您可以在其中指定想要使用哪个编排。

Kubeflow 管道和 TFX 都通过 AI 平台管道在 Google Cloud 上得到支持,因此您可以选择最适合您的 MLOps 实现的方式。

使用 AI 平台管道,您可以全面了解工作流程中的不同步骤。您还可以与其他 GCP 服务集成,例如作为数据源的云存储或 BigQuery,用于转换的数据流,或用于训练和服务模型的人工智能平台。

当需要为您的 MLOps 实践选择工具时,Google Cloud 提供了多个选项来满足从最基本到最高级的需求。

做出明智决策的一个关键驱动因素应该是您的 MLOps 成熟度。没有放之四海而皆准的方法。有时,一组简单的编排好的 GCP 服务就足够了(AutoML、BigQuery、云存储、AI 平台训练和 Cloud Composer。)但对于其他场景,支持 Kubeflow 管道和 Tensorflow Extended (TFX)的 AI 平台管道服务将是端到端 ML 工作流的更好选择。

Google 云存储(GCS)让 BigQuery 变得简单

原文:https://towardsdatascience.com/google-cloud-storage-gcs-to-bigquery-the-simple-way-4bb74216b8c8?source=collection_archive---------6-----------------------

因为简单比复杂好(但复杂比复杂好)

谁不爱一朵简单的云。在 Unsplash 上由 C Dustin 拍摄的照片

我部署的第一个云功能就是为了完成这个任务。我们每天晚上都有大量 CSV 文件被放入 Google 云存储桶中,这些文件需要在 BigQuery 中进行转换和分析。

花了一些时间在谷歌上,我来到了这个操作指南,它有点不同(JSON 文件而不是 CSV),但我想我可以稍微调整一下,让它工作。毕竟,在软件和数据工程的世界里,这是一个非常普通的工作流程:找到一些几乎做你需要的事情,弄清楚它是如何工作的,然后调整代码来做你需要的事情。而且成功了!我花了一整天全力以赴地工作,但最终我们有了一个正常工作的数据管道,如下所示:

将数据从谷歌云存储传输到 BigQuery。图片来自https://cloud . Google . com/architecture/streaming-data-from-cloud-storage-into-big query-using-cloud-functions

三个云存储桶,三个 Python 云函数,两个 PubSub 主题,一个 Firestore 数据库,一个 BigQuery 数据集,六杯咖啡和一只梨树上的鹧鸪,我们准备好了!总共有十种不同的云资源,所以有十个不同的地方可以检查是否有问题(在某些时候几乎总是会有问题,尽管可能不是以你期望的方式)。

快进到现在(更多的云功能被开发、调试、部署,并且大部分都被淘汰了……稍后会有更多的介绍),我的想法转向了Python 的禅,特别是第 3 和第 4 点:

简单比复杂好。

复杂总比复杂好。

但是复杂和复杂有什么区别呢?根据剑桥词典:

复杂 (形容词):涉及许多不同但相关的部分

复杂的 (形容词):涉及很多不同的部分,以一种难以理解的方式

现在我看看上面的架构图,它看起来并不复杂。看起来很复杂。

一定有更好的方法。

结果是有:

以简单的方式从 BigQuery 查询 GCS 数据(图片由作者使用图

事实证明,如果数据在云存储桶中,您根本不需要将数据流式传输或加载到 BigQuery 中,您只需要使用外部表的魔力。

简单吧?您只需通过 UI 或 DDL 在 BigQuery 中创建一个新表(本质上是在 BigQuery SQL 编辑器中用 SQL 执行管理任务的一种方法)。在 UI 中,您必须确保将表格类型从默认的Native table更改为External table,因为忘记这样做将导致一个静态表格,该表格不会拾取新数据。

DDL(数据定义语言)实际上非常简单,在这种情况下:

CREATE OR REPLACE EXTERNAL TABLE `myproject.mydataset.mytable`
OPTIONS (
  format = 'CSV',
  uris = ['gs://mybucket/*.csv']
)

这里重要的部分是*。因为这意味着任何出现在 bucket 中的新文件都会立即出现在 BigQuery 中。您还可以通过添加不同 URIs 的列表来聚合多个存储桶中的文件:

CREATE OR REPLACE EXTERNAL TABLE `myproject.mydataset.mytable`
OPTIONS (
  format = 'CSV',
  uris = ['gs://mybucket01/*.csv', 'gs://mybucket02/*.csv']
)

或者通过在 URI 中包含文件夹路径,从不同的子文件夹创建表:

CREATE OR REPLACE EXTERNAL TABLE `myproject.mydataset.mytable`
OPTIONS (
  format = 'CSV',
  uris = ['gs://mybucket/subfolder/*.csv']
)

甚至过滤不同文件名:

CREATE OR REPLACE EXTERNAL TABLE `myproject.mydataset.mytable`
OPTIONS (
  format = 'CSV',
  uris = ['gs://mybucket/filename_stem*']
)

然而,您受到每个 URI 只能使用一个通配符这一事实的约束,因此,如果您想将不同的文件过滤到不同的表中,并确保可以在 BigQuery 中查询新数据,不同的文件类型将需要共享一个文件名词干。

最后一步是将文件名添加到 BigQuery 中。实际上有一个名为 _FILE_NAME 的伪列,它将原始文件名传递到外部表中,但是您必须显式地查询(并重命名)它以使其可用。最简单的方法是使用下面的 SQL 通过 UI 创建一个视图:

SELECT *, 
_FILE_NAME AS filename 
FROM `myproject.mydataset.mytable`

或通过 DDL:

CREATE OR REPLACE VIEW `myproject.mydataset.myview`
AS
SELECT *, 
_FILE_NAME AS filename 
FROM `myproject.mydataset.mytable`

厉害!

嗯,也许吧。希望这一切都完美地工作,您的实时数据是可查询的,并且您对自己构建了一个简单、轻量级、无服务器、零维护的数据“管道”感到非常满意(从技术上来说,它甚至不能称为管道,因为您实际上没有移动任何数据)。

但事情并不总是这么简单。为什么?

一个词:图式。

如果(这是一个很大的假设)模式自动检测能够完美地工作,那么这种方法就非常有效。如果您查看文档,您会注意到为了推断模式:

BigQuery 通过在数据源中选择一个随机文件并扫描多达 100 行数据作为代表性样本来启动推断过程。然后,BigQuery 检查每个字段,并尝试根据样本中的值为该字段分配一种数据类型。

但是如果这 100 行不能代表所有的数据呢?如果分析的行都是有效的整数,但其他行也包含字母字符?如果 BigQuery 将类型推断为 INT64,这将导致您对数据运行的任何查询都失败,这显然不好。

我的朋友,这意味着你可能处于 BigQuery 模式管理的世界中,一个你可能会也可能不会完好无损(或神志清醒)的兔子洞。或者您可能需要使用另一种方法或外部工具来自动管理模式更改,但是您试图保持简单。你只是想让它稳定可靠地工作。一劳永逸。

“你吃了蓝色药丸……故事结束,你在床上醒来,相信你想相信的一切。你吃红色药丸……你呆在仙境,我让你看看兔子洞有多深。”—墨菲斯,《黑客帝国》(1999 年)

还有一个办法,我的朋友。不吃药。

处理这种模式挑战(以及系统之间许多不同的数据类型问题)的最简单方法是:

  1. 创建一个外部表,将的所有数据类型设置为字符串
  2. SAFE_CAST 将所有字段转换为正确的数据类型

看起来很简单,对吧。

是啊,没那么简单。怎么把所有东西都设置成 string?这不是 UI 中的一个选项(但如果是就好了)。如果你有数百列呢?您真的不希望手工编写 SQL 转换代码,因为 a)这将花费很长时间,b)您几乎肯定会在某个地方犯一个(可能永远无法发现的)错误。

有很多简单的变通方法可以做到这一点,但是最好的方法——不需要外部工具,不需要通过 API 或使用 CLI 进行交互——是使用一些相对较新的 BigQuery 功能:脚本。

但那是另一天的主题…

希望这已经对一些人有所帮助,并消除了(至少一些)你未来生活中的并发症!

最令人满意的问题是那些当你足够认真地看待它们时就会消失的问题——我,2021

如果您觉得这(以及其他相关材料)有用和/或有趣,请跟我来!

如果您还不是会员,请加入 Medium,从这个活跃、充满活力和激情的数据人社区每月只需 5 美元就能获得无限的故事。也有很多其他人,但是如果你对数据感兴趣,那么这里就是你要去的地方…

谷歌 colab 笔记本已经在运行 Deepmind 的 AlphaFold v. 2

原文:https://towardsdatascience.com/google-colab-notebooks-are-already-running-deepminds-alphafold-v-2-92b4531ec127?source=collection_archive---------7-----------------------

全球数百名科学家已经从这一革命性的软件中获益。而且是免费的。

另见我的两个涉及不同方面的后续故事:

  • 基于 AlphaFold 的数据库和成熟的、易于使用的在线 AlphaFold 界面为生物学带来了革命性的变化
  • alpha fold 上的宣传随着这份新的预印本不断增长

上周(2021 年 7 月),Deepmind 的同行评审学术论文发表在 Nature 上,描述了其预测蛋白质结构的 CASP 获奖 AlphaFold v.2 程序的所有细节。同时,他们在 Github 上发布了它所有的代码开源。在几个小时内,一些科学家创造了谷歌 Colab 笔记本,每个拥有免费谷歌账户的人都可以用自己喜欢的蛋白质运行 AF2,而无需下载其 2.2 TB 的任何一点,也不需要任何硬件。使用这些程序进行研究的 CASP 评估员的故事。

2020 年 12 月,一个名为 CASP 的组织举办了一场预测蛋白质三维形状的“比赛”,该组织透露,Deepmind 的 AlphaFold (AF2)版本 2 以相当大的差距“赢”了亚军。许多媒体称 AF2 解决了一个 50 年的老问题。虽然这是一种夸张,但 AF2 对生物学的贡献是巨大的,有望减轻实验蛋白质结构测定的负担,并加速分子生物学的研究。尽管有这些好消息,世界各地的科学家还是引发了负面情绪,这些情绪与据称的技术不可获得性、缺乏再现性的细节以及急于知道运行 AF2 是否超出学术预算有关。但是事情已经完全不同了,而且是永久性的。

上周(2021 年 7 月),Deepmind 的同行评审学术论文发表在 《自然》 上,描述了其预测蛋白质结构的 CASP 获奖 AlphaFold v.2 程序的所有细节。与此同时,他们在 Github 上发布了所有的代码开源。一些科学家仍然抱怨数据文件太大(实际上有 2.2 TB)。然而,在几个小时内,一些专注的科学家创造了谷歌 Colab 笔记本电脑,每个人都可以使用免费的谷歌帐户运行 AF2,甚至不需要下载数据,也不需要任何特殊的硬件。事实上,所有的计算都发生在云上,但都在一个免费的 colab 空间内,这使得用户能够对运行进行微调。在经历了如此多的负面情绪后,所有这些都被认为是使技术大众化的最佳方式之一。感谢谷歌!

目录

  • 一些背景:蛋白质结构,实验测定,以及基于计算机的蛋白质结构预测
  • 【结构预测的关键评估】(CASP)
  • 用于蛋白质建模的机器学习方法,Deepmind 及其 AlphaFold 1 程序
  • AlphaFold 版本 2
  • 通过协作笔记本民主化访问 AF2 进入分子生物学新时代

一些背景:蛋白质结构、实验测定和基于计算机的蛋白质结构预测

蛋白质是生物“纳米机器”,由长的、基本上线性的氨基酸链组成,这些氨基酸链采用所谓的结构进行三维折叠。自然界中有 20 种氨基酸,它们在每个蛋白质中以独特的方式重复,由每个蛋白质编码基因决定。了解氨基酸序列很容易,因为这可以直接从基因组中推断出来。但是要了解它们在 3D 空间中的排列方式是很困难的。而且,每个氨基酸就像一个由几个原子组成的小分子;因此,了解蛋白质的 3D 形状或“3D 结构”需要确定其所有氨基酸的所有原子的相对位置。例如,给定由字母 A、C、D、E、F、G、H、I、K、L、M、N、P、Q、R、S、T、V、W 和 Y 表示的 20 种标准氨基酸,称为泛素的蛋白质由以下序列组成:

MQIFVKTLTGKTITLEVEPSDTIENVKAKIQDKEGIPPDQQRLIFAGKQLEDGRTLSDYNIQKESTLHLVLRLRGG

…在 3D 中折叠成这样,每个原子显示为一个通过棒与其他原子相连的球体,每个氨基酸(即上面序列中的每个字母)以不同的颜色显示:

泛素的原子结构。图片作者。

但是,请注意,我们通常通过仅显示近似 3D 形状的轨迹来简化这些图形:

代表泛素三维结构的轨迹。图片作者。

每次 AlphaFold 在聚光灯下,你可能都会看到这种类型的图纸。

了解蛋白质的三维形状在生物学和任何相关学科中都是必不可少的。仅举数百个例子中的两个,生物技术应用的酶实际上是一类特殊的蛋白质。抗生素、化疗剂和药物等绝大多数化合物的目标都是小分子,其作用依赖于识别和结合蛋白质的三维特征。

结构生物学是试图在原子水平上解释生物系统的学科。这主要取决于相关分子结构的可用性,其中最重要的通常是蛋白质。虽然许多结构可以通过实验技术确定,如 X 射线或中子衍射、核磁共振(NMR)或电子冷冻显微镜(也称为冷冻电子显微镜,cryo-EM),但也有使用计算方法预测或“建模”这些结构的替代方法。事实上,结构生物学家长期以来的梦想是将蛋白质序列输入计算机程序,并从中获得它所采用的三维结构。这并不容易,而且还没有完全解决,但是经过几十年对这个问题的研究,机器学习模型的入侵(当然还有大量数据的可用性)导致了 AF2(以及其他几个程序,我们必须澄清),它可以非常准确地预测许多蛋白质的 3D 结构。

自然,这种预测对于大量生物分子来说是必不可少的,这些生物分子无法在各种实验所需的数量和条件下生产。但是预测结构对于在解决结构所需的实验中可能不难生产和操纵的分子的情况也是有用的,但是对于这些分子来说,结构提供的信息量与成本和时间不相称。事实上,如果我们能够有足够的信心预测生物分子的结构,我们就可以将实验集中在特别困难的系统上(这正是结构基因组学所追求的),或者集中在研究结构扰动的影响上,比如配体与被研究蛋白质结合的影响。在极端情况下,如果我们能够在原子水平上预测一个给定系统的所有物理化学,我们就可以完全免除结构测定实验,并可以集中精力直接理解机制和这种知识允许我们做的一切:开发新的药物,设计新的酶,理解进化,…

结构预测的关键评估(CASP)

鉴于结构预测对结构生物学的影响,自上世纪中期以来,几代研究人员一直在研究这个问题,特别是蛋白质,因为它们比其他生物大分子具有更大的结构价值和多样性。已经开发了许多方法,这些方法可以分为两大类。一方面,那些使用已知结构试图预测相似序列或折叠的蛋白质结构,这被称为“同源建模”。另一方面,那些试图独立于与已知结构的其它蛋白质的任何同源性而“折叠”序列的方法,例如通过使用基于基本物理化学原理的模拟或通过使用关于小肽片段和/或残基接触的结构的信息。

随着结构建模的方法、程序和专家出现的大问题是如何评估这些预测的质量。在 20 世纪 90 年代早期,结构预测的关键评估,或 CASP,作为一个组织诞生,其目标是提供对预测蛋白质结构的可用方法的持续监测和评估。竞赛(实际上没人想称之为竞赛,但对许多人来说这就是竞赛!)每 2 年举行一次,在此期间,组织者收集尚未在蛋白质数据库中发表的实验结构。组织者将这些蛋白质的氨基酸序列提供给预测组,预测组在一段时间后将他们的预测发送给组织者。然后,一组独立于组织且不作为预测者参与的评估者将预测者提供的模型与只有评估者可以访问的实验结构进行比较。每场比赛都以一系列论文结束,这些论文描述了目标提出的难度,描述了预测者提供的模型的质量,生成了预测者的“官方”排名,并讨论了建模的“艺术状态”,特别是哪些方法有效,哪些结构问题特别难以预测,等等。在 2016 年和 2019 年之间,举行了 CASP12 和 CASP13,为此,该作者是竞赛主赛道的评估员,该竞赛侧重于预测困难的目标。这两个 CASP 开始揭示与共同进化技术一起应用的机器学习方法的破坏性力量,不仅出自 alpha fold 1(casp 13 的“获胜者”)之手,而且出自几个学术团体之手,这些学术团体在之前的几年中一直在为这些技术奠定基础。

想了解更多关于 CASP 的信息,请看另一个故事。要查看 CASP12 和 CASP13 论文(技术同行评审文章),请参见我在分子建模和序列分析下列出的关于蛋白质建模的出版物。

蛋白质建模的机器学习方法,Deepmind 及其 AlphaFold 1 程序

2018 年 12 月,CASP 透露,有史以来第一位私人玩家“赢了”。这是谷歌字母表小组的 Deepmind。Deepmind 的程序 AlphaFold 的第一个版本排名第一,大大高于第二名,但不是明星。此外,尽管它发明并实施了一些新的想法,但其核心主要是将学术界在过去几年中所做的事情推向极限。在关键要素中,不仅分析进入序列,还分析一系列相关序列(“序列比对”),这些序列对应于通过略微不同的序列实现相似 3D 折叠的蛋白质。关键是,在进化过程中氨基酸会发生变化,但在空间上接近的氨基酸对必须保持一定的亲和力,从而在进化模式中引入耦合。十年来,学术界一直在分析如何从序列比对中提取这些偶联。到了 CASP12,他们开始正确地做这件事,在结构预测方面带来了小小的改进。到 CASP13 时,许多小组都在做,但一些学术小组和 AF1 也利用这一信息不仅预测了接触的氨基酸对,还预测了它们之间的距离,甚至它们的相对方向。这些中间预测然后被不同的程序使用,包括 AF1,来模拟蛋白质的三维结构。

AF1 是 CASP13 中评估的大多数蛋白质中最好的,你可能看到了媒体的大肆宣传。但它并不像 AF2 那样具有破坏性。

AlphaFold 版本 2

2020 年 12 月,CASP14 的结果在网上公布(由于疫情,所以我可以作为一名前评估员在那里!)表明 Deepmind 又赢了,但这一次是迄今为止实际上“解决”了一些(并不像你在媒体上看到的那样,只是一些)蛋白质结构预测中的关键问题。

像其他程序一样,AF1 作为一种不相连的模块工作。一个主要模块分析输入序列和比对,以预测氨基酸对之间的距离和方向,然后另一个模块使用这些距离和方向作为约束条件,将氨基酸的线性序列“折叠”成预测的 3D 结构。AF2 不是对 AF1 的调整,而是完全的重新设计,从输入到输出的一切都通过一个单一的模型,从序列到预测的 3D 结构。这意味着网络“知道”所有连接序列和结构的物理过程。细节在他们的同行评议文章中,尤其是在它的支持信息中。在中级阶段,卡洛斯·奥特拉尔的职位是。

下面的图总结了自四分之一世纪前开始以来 CASP 取得的进展(我是在 2002 年才知道 CASP 的,当时我刚刚了解蛋白质结构!).经过多年相当差的预测能力(注意这个图只针对硬目标!)你可以看到从 CASP11 到 CASP12 的明显改进(还没有 AlphaFold),然后是从 CASP13 的另一个跳跃,不仅是由于 AF1,而且是在整个社区,然后是 CASP14 的最新改进,学术方面也有所改进,但不如 Deepmind 那么多,它打破了质量的障碍。此外,它的预测一直很好,正如你在相当低的离差中看到的。

CASP 的时间演化。对于每个 CASP 版本,我绘制了针对所有困难目标的最佳模型的 GDTTS 中位数(+/-中位数偏差)。GDTTS 是 CASP 的主要指标之一:得分低于 30–40 的模型相当差,高于 50–60 的开始相当好,高于 80–90 的表示与实验结构非常一致。图片作者。

AF2 的预测是如此之好,它不仅得到了正确的整体形状,还得到了大多数原子的精确位置。在我上面展示的蛋白质图形示例中,这意味着不仅要正确猜测轨迹的走向,还要准确猜测构成每个氨基酸的所有原子的位置。它得到了一些非常大的蛋白质(通常更大的蛋白质更难建模)。它甚至得到了一些蛋白质-蛋白质复合物,这是 CASP 中一个完全不同的轨道,仍然落后。

AF2 对 CASP14 的预测如此之好,以至于他们的一些模型被用于完成一些 CASP14 靶标的实验结构测定。这种情况在之前的 CASPs 中只发生过几次。

最后,AF2 不仅是蛋白质结构的可靠预测因子,也是其已知结构质量的良好预测因子。这是蛋白质结构预测领域的关键,但却被开发者和用户所忽视。一个带有相关质量评估的模型要比一个缺乏任何正式质量评估的假定好的模型丰富得多。所有严肃的团体都提供这样的估计,在 AF2 的情况下,Deepmind 的人确信他们的质量指标是好的。AF2 预测了一个称为 LDDT 的质量估计,CASP 用它来逐个氨基酸地比较模型和实验结构。通过这种方式,AF2 会告诉您所生产车型的不同区域的情况。

通过合作笔记本对 AF2 的民主化访问——进入分子生物学的新时代

在 CASP14 披露 AF2 的成功后,批评和怀疑立即接踵而至:“学术界无法与这些巨头竞争”,“他们做出了它,但我们将无法使用它,这很好”,以及“他们肯定不会开放使用它”是一些常见的反应。但是事情已经完全不同了。,为好。

上周,描述这个庞大的机器学习模型的全部结果的学术论文与 Github 托管的所有免费开源代码一起发布。此外,参与的研究人员(我非常感谢他们)建立了谷歌 Colab 管道,你甚至可以在手机上使用 AF2。

从 Github 下载的 AF2 重 2.2 TB,该模型将在 GPU 上运行。但是通过使用 Google Colab 你不需要下载软件,也不需要任何强大的 GPU。你只需要在云上运行一切。而且你甚至不需要了解云计算!

这两位研究人员用上面的 Twitter 帐户组装的 Colab 笔记本可以处理一切事情,从加载库和输入你的蛋白质序列到构建其比对,找到已知结构的同源物(“模板”,这当然对相关蛋白质的建模有很大帮助),运行 AF2 并显示结果:你可以在浏览器中看到 5 个 3D 模型,以及估计的 LDDT 对序列的绘图。此外,原则上,您可以派生这些笔记本中的任何一个,并进行自己的编辑,以使运行适应更具体的任务。

AF2 在 Google Colab 笔记本上运行的示例结果,此处显示了右侧的模型及其对序列的相关质量评估。图片作者。

我已经用这些笔记本做了几次测试,已经得出了一些结论。最重要的一点是序列比对和模板都有助于获得更好的模型。我看到了许多关于人们使用该工具的推文,但许多推文忽略了 LDDT 估计图。这些剧情必不可少!

对 AF2 预测的高质量的大肆宣传对我来说更加剧了实际使用它的可能性,而且如此容易。这为全世界的研究人员带来了潜力,为 AF2 的局限性和可能性的广泛基准铺平了道路。对于研究不可实验的蛋白质的生物学家来说,模拟蛋白质结构是必不可少的。正如引言中所解释的,即使你有一些数据,但不能正确使用,好的蛋白质模型也是有用的。无需深入细节,一个例子是通过分子置换对 X 射线数据进行定相的能力。另一个大的领域是使用蛋白质模型来完成实验量,例如使用原子坐标的中分辨率 Cryo-EM。随着 Deepmind 本身进入生物学的其他问题(没有透露计划,但我们可以先猜测蛋白质-蛋白质相互作用,然后进行小分子设计),以及学术界可以从 AF2 应用和现在公开的所有知识中直接获利,未来甚至更加光明。

长期以来,生物学工作一直依赖于计算机和经典软件。现在是 AI 的时代。

更多链接和阅读

在 TDS 编辑:https://towards data science . com/alpha fold-based-databases-and-fully-fledged-easy-use-alpha fold-interfaces-horizing-BAF 865 c6d 75 e中看到我的后续故事

还有这个的后续故事在 TDS Editors 中讲述了 AlphaFold2 与调用一个出色的序列比对构建器 MMSeqs2 的结合,让用户在简单的 Colab 笔记本上充分利用这项技术:https://towards data science . com/the-hype-on-alpha fold-keep-growing-with-this-new-preprint-a8c1 f 21 d15 c8

Google colab 笔记本也可以用来运行分子动力学模拟,见本故事 TDS 编辑:https://towards data science . com/new-preprint-descriptions-Google-colab-notebook-to-efficient-run-molecular-dynamics-simulations-of-9b 317 f 0e 428 c

AlphaFold 2 论文自然

Github 中的 AlphaFold 2 代码

牛津蛋白质信息学小组 Carlos Outeiral 的博客文章:Google deep mind 的 AlphaFold 2 真正实现了什么,对蛋白质折叠、生物学和生物信息学意味着什么。非常有趣的第一个想法和回顾在第 14 章发生了什么。

牛津蛋白质信息学小组 Carlos Outeiral 的博客文章:结构预测奇迹的背后是什么。比我在这里给你的更详细,但比《自然》杂志的文章简单。

喜欢这篇文章,想给我提示?【https://www.paypal.me/LAbriata】-谢谢!

我是一个自然、科学、技术、编程和 DIY 爱好者。生物技术专家和化学家,在潮湿的实验室和计算机里。我写我广泛兴趣范围内的一切。查看我的 列表 了解更多故事。 成为媒介会员 访问我和其他作家的所有故事, 订阅通过邮件获取我的新故事 (平台原创附属链接)。

Google Colab Pro+:值 49.99 美元吗?

原文:https://towardsdatascience.com/google-colab-pro-is-it-worth-49-99-c542770b8e56?source=collection_archive---------2-----------------------

谷歌刚刚发布了 Colab 的新订阅计划:Pro+。新变种是否值每月 49.99 美元?我看了看新包装。

作者图片

Google Colab 在家做深度学习,准备和分享数据科学案例,相互协作,越来越受欢迎。就我个人而言,我使用 Google Colab 主要是为了 Kaggle 比赛。所以我很好奇新的订阅选项会提供什么。

两年前,谷歌发布了 Colab Pro。这是 Colab 的第一个付费订阅选项。每月 9.99 美元,专业用户可以获得更快的 GPU,如 T4 和 P100,如果资源可用的话。此外,pro 版本的运行时间更长,实例连接时间长达 24 小时。在免费版本中,运行时间限制为 12 小时,RAM 也限制为 16 GB。在 pro 版本中,可以选择高内存选项,从而使用 32 GB 的 RAM。Google Pro+变种现在提供了更多的选择,可以在没有云服务器或本地机器的情况下相对便宜地运行深度学习。让我们看一看。

肌肉——GPU 和内存

Colab Pro+提供对与 Colab Pro 相同的 GPU 的访问。但是,如果资源不足,Pro+用户将被优先考虑。在 RAM 方面,Pro+又出现了一个显著的变化。

虽然 Colab Pro 提供 32 GB 的内存,但 Pro+用户可以通过高内存选项获得 52 GB 的内存。

这大约是专业用户的 1.6 倍,免费用户的 3.25 倍。这意味着大量数据也可以在 GPU 应用程序之外进行处理。

运行时间

连接的持续时间在机器和深度学习中非常重要。在免费版本中,笔记本电脑在 12 小时后断开连接,在专业版本中,在 24 小时后断开连接。一直困扰我的是,浏览器必须保持打开,否则在我的体验中,大约 90 分钟后就会断开连接。这对于密集的生态测试是没有用的,因为本地机器必须一直开着。浏览器崩溃时有发生。

H ere Pro+在我看来提供了最重要的创新之一:后台执行。在训练被触发后,虚拟机继续运行长达 24 小时**,而**浏览器不必保持打开。

模型和数据仍然存储在工作空间中。我总是将数据直接推送到我的 Google Drive,这使得后台执行更加有用。

有效性

不幸的是,目前可用性没有任何变化。Colab Pro 和 Colab Pro+在以下国家均有销售:美国、加拿大、日本、巴西、德国、法国、印度、英国、泰国。在这些国家/地区之外,Pro 或 Pro+套餐不可用。

Colab 订阅计划的比较;作者图片

结论

从我的角度来看,如果有人持续使用 Colab Pro+服务,并且还想培训大型模型,例如在迁移学习领域,那么 Colab Pro+是值得的。最重要的新特性是后台执行。52 GB RAM 也是一个有用的升级,因为过去我经常用完 Colab Pro 中的 32 GB RAM,导致运行时崩溃。此外,当我长时间密集使用 GPU 和高内存引擎时,我更经常被服务阻止。在那些时刻,Colab Pro+的进一步优先化会帮助我。如果您只是偶尔使用 Colab,即一个月几次,那么升级肯定是不值得的。

进一步阅读

  • 订阅概况:【https://colab.research.google.com/signup
  • 主要常见问题:https://research.google.com/colaboratory/faq.html
  • 充分利用 Colab:https://colab.research.google.com/notebooks/pro.ipynb

如果您喜欢中级数据科学,并且还没有注册,请随时使用我的推荐链接加入社区。

谷歌数据分析专业证书:综述

原文:https://towardsdatascience.com/google-data-analytics-professional-certificate-a-review-a426b12a35?source=collection_archive---------0-----------------------

对于有抱负的非传统背景的数据分析师来说,这是一个有价值的证书

(我推广这门课程没有报酬。这是我个人的看法。)

2021 年 3 月,谷歌推出了数据分析专业证书。这来得正是时候,因为分析角色的供应落后于需求,导致市场上数据分析师短缺。

近年来,对数据分析角色的需求激增,导致高薪分析角色的空缺数量增加。事实上,根据 Burning Glass 的数据,仅在美国就有 33.74 万份数据分析工作,平均入门级工资为 6.79 万美元。

同时也有很多非传统背景的应届毕业生和专业人士(比如我自己!)想进入数据空间的人。

这听起来像你吗?如果是的话…继续读下去。

作为一名数据分析师,我喜欢与来自非传统背景的学习者分享数据分析的知识。今天,我希望能够分享我对这门课的想法。作为一家科技公司 Gojek 的数据分析师,我知道数据分析师需要什么。今天我就分享一下我作为从业者对 Google Analytics 证书的看法。

什么是数据分析?

由卢卡斯·布拉塞克在 Unsplash 上拍摄

此时,您可能想知道…什么是数据分析?根据谷歌的说法,

数据分析是对数据的收集、转换和组织,以便得出结论、做出预测和推动明智的决策。

简而言之,我用数据帮助人们做决定。这可以以提取数据、可视化数据甚至建模数据的形式出现。

本谷歌分析课程涵盖了成为分析师的基础知识,包括掌握分析师日常工作所需的工具。

您将学习的工具

SQL 是必不可少的工具。卡斯帕·卡米尔·鲁宾在 Unsplash 上的照片

该证书涵盖了您作为数据分析师所需的日常工具。这使得它成为一门非常实用的课程。这些工具包括

  1. 像 Excel 或 Google Sheets 这样的电子表格(绝对必要!)
  2. SQL(用于数据提取)
  3. Tableau(用于数据可视化)
  4. R、RStudio、R Markdown 和 Tidyverse 包(用于编程和数据争论)

你将学到的技能

本课程共有课时,包括

学习数据的基础

本课程首先概述数据生态系统,从初级数据分析师在日常工作中的实践和流程、该角色所需的技能开始,并解释与数据分析师相关的术语和概念(如数据生命周期)

提问以做出数据驱动的决策

数据科学最难的部分之一是提出正确的问题。本课程涵盖有效的提问技巧,有助于为利益相关者提供一个分析框架。

为勘探准备数据

数据以各种形状、形式和类型出现。对于分析师来说,了解用于处理不同数据类型和格式的方法是非常重要的。这包括访问、提取、过滤和分类数据库中的数据的方法。

处理数据从脏到干净

数据清理是数据分析师的一项重要日常活动。在本节中,您将学习使用 SQL 进行数据清理,并验证数据清理的结果。

分析数据以回答问题

在本节中,您将学习探索和分析数据来回答问题。为此,需要通过计算对数据进行组织、格式化和处理。这部分课程使用电子表格和 SQL 来实现这一目的。

通过可视化艺术分享数据

讲故事是数据分析和科学中最困难也是最复杂的部分之一。可视化可以帮助数据从业者通过引人注目的数据叙述向利益相关者传达见解。这个类使用 Tableau 作为数据可视化平台。

用 R 编程分析数据

需要一定程度的编程熟练程度来加快分析过程,特别是对于复杂的数据科学项目。r 是一种非常棒的开源语言,为数据从业者所熟知。它的 tidyverse 包维护良好,对于数据争论(dplyr、purr、tidyr)和数据可视化(ggplot2)非常有用。有些人可能想知道是否应该学习 python。我的观点是,你先学哪一个并不重要,因为你可以用任何一个做很多事情。

完成一个顶点项目

顶点项目对于获得数据科学或分析面试非常重要。在该证书的最后一门课程中,您将有机会通过案例研究建立自己的投资组合,并学习常见的分析面试问题。

这门课适合你,如果你…

✅没有先前的经验或先决条件

厌倦了在开始一个看似基础的课程之前就花费在先决条件上吗?这个分析课程不期望学习者有任何经验,所以它非常适合应届毕业生或任何想学习分析的人。

✅希望得到雇主的关注。

克里斯蒂娜@ wocintechchat.com 在 Unsplash 上的照片

如果你完成了谷歌数据分析证书,你就有望进入谷歌雇主联盟(仅在美国可用)的顶级雇主行列。该联盟中的公司受益于谷歌的人才管道,这些人才通常来自非传统背景。这个人才,当然是指谷歌提供的课程的学习者。

想知道财团内部的哪些公司?他们是家喻户晓的名字,像埃森哲、拜耳、百思买、德勤、威瑞森、Snap、沃尔玛等等。点击阅读更多关于财团的信息。

✅想从头到尾了解分析。

学习分析的一个痛点是需要在互联网上搜寻资源。谷歌通过为分析学习者提供一体化课程解决了这个问题。课程内容全面,为分析职位提供必要的技能。

✅每周有 10 个小时的空闲时间

该课程相对轻松,每周 10 个小时,目标是在不到 6 个月的时间内完成认证。

这个班不适合你,如果你…

❌已经有了分析方面的背景

你大概只需要一张证书,证明你学过分析学。如果你已经参加了一个非常类似的课程,如 Udacity 的分析学纳米学位课程、 Datacamp 的 Python Track 数据分析师课程、或任何数据分析认证课程,你就不需要再参加这个课程了。

❌是 python 的铁杆粉丝

抱歉 python 的粉丝们,这门课是用 R 教的,关于一个人应该从 R 还是 python 开始,一直有激烈的争论。如果你正在寻找一种极其灵活的语言,那么也许你会更喜欢 python。如果你想学习最好的数据包,那么 R 可能更合适。这是我的观点,值得在博客上单独发表。

一节课多少钱?

在撰写本文时,这八门课的学费是每月 39 美元。因此,你越快完成课程,效果越好。

Coursera 还为有需要的学习者提供经济援助。我个人从经济资助中受益匪浅,我绝对感激。

需要预览吗?从这里开始。

自学数据分析和数据科学并不容易,但我相信谷歌分析证书通过汇编高质量的资源,让你触手可及,让学习变得更容易。我希望你喜欢这门课,并祝课程顺利!

在 LinkedIn 上与我联系。

https://www.linkedin.com/in/travistang [## Travis Tang -数据分析师- Gojek

www.linkedin.com](https://www.linkedin.com/in/travistang)

如果你喜欢这篇文章,你可能会喜欢…

  • 如何自学数据科学(SQL、数据可视化和编程)
  • 成为优秀数据分析师的 4 个步骤(不要做查询猴子)

面向初学者的谷歌数据工作室

原文:https://towardsdatascience.com/google-data-studio-for-beginners-99355e9df809?source=collection_archive---------17-----------------------

艾萨克·史密斯在 Unsplash 上拍摄的照片

使用最简单的免费工具之一,在几分钟内实现令人难以置信的可视化

每个作家都知道,一幅画胜过千言万语;在数据科学领域,一个好的可视化是物有所值的。作为一个对这个行业和技能还非常陌生的人,我不能从专业的角度来说,但作为一个新手数据工程师,我来到我的新公司时,口袋里有一些熊猫,眼睛里有明亮的城市灯光。我的团队已经收集了大量奇妙的、基本上干净的数据…但是没有人有时间或专业知识将其转化为可操作的东西。对于初出茅庐的数据科学家来说,他们在寻求理解的过程中发现的可能是最伟大的工具:谷歌数据工作室。

当我第一次开始玩它的界面时,我嗤之以鼻。这不是熊猫,也不是 Seaborn,我刚刚花了数百个小时学习如何在工作场所使用我新奇的 Python 技能,所以我决定这样做。也就是说,我用它做得越多,我就越能理解谷歌数据工作室,或者酷孩子们称之为 GDS 的真正强大的本质。

由弗兰基·查马基在 Unsplash 上拍摄的照片

显示不告诉

每个人都喜欢图表。说真的,他们有。即使讨厌数据的人也喜欢好的图表。线上升了吗?有多好看?但最重要的是,上线了吗?

我是在开玩笑(大部分是),但是在商业世界里,我们的工作不是玩数据,而是为那些不玩数据的人翻译数据。一次又一次,你会发现一个漂亮的图表会在任何一天胜过一个数字。不仅如此,当你和一个像糖果一样吞噬度量标准的团队一起工作时,你需要尽可能快地提供大量的图表。因此,谷歌数据工作室是你的星期五。

在我们了解这项计划的威力之前,重要的是要知道它并不适合所有人。这是一个在数据新手和数据科学家之间架起桥梁的工具。它能做机器学习吗?不,你应该用它来清理数据吗?亲爱的上帝,不。即使合并也有它的局限性。但是任何一个从头开始编写堆积条形图的人几乎都会被这样一个事实所冒犯:在比煎鸡蛋还短的时间内将一个漂亮而精确的图表转储到一个报告中是多么容易(当然,如果你的数据是干净的话!).

谷歌数据工作室的优势在于其数据处理的可塑性。每个数字列都有一个可定制的默认聚合,所以从详细的行跳到一个分组的总和比说“Pivot table,schmivot table”更容易。不仅如此,它还让数据探索变成了一个拖拽式的梦想。最后,也是最重要的一点,它是为数不多的免费程序之一,允许你私下与你的团队分享数据,而不必在一个封闭的网站上进行托管。我充分意识到了 Streamlit 的强大功能和可定制性,我仍然计划在未来广泛使用该程序,但对于与我的团队共享敏感数据,GDS 是一个上帝派来的人。我可以说,在不小的程度上,GDS 改变了我的团队的工作方式。但是为什么要告诉你,当我可以给你看的时候?

航空焦点在 Unsplash 上拍摄的照片

如何做 GDS 报告

您首先会注意到,在几分钟内创建一个完全填充的交互式报告是多么容易。请记住,GDS 是一个聚合工具,所以请确保您的数据是干净和一致的。俗话说:“垃圾进来等于垃圾出去”,所以你永远不要指望谷歌的优秀员工会为你做真正的数据工程工作。

第一步:加载您的数据

加载数据有多种选择。GDS 可以很好地处理空值,但是在这样做之前要确保理解空值以及列的语义配置。当您开始时,最常见的挫折之一是意识到您的配置到处都是,当遇到它不理解的值时,您的数据会中断。

GDS 有几个加载数据的方便选项,尽管它们都有各自的优缺点。在连接数据之前,一定要阅读文档,因为当你发现行丢失时已经太晚了。数据连接器包括:

  • PostgreSQL/MySQL*(每个查询限制 100k 行)*
  • Google Sheets (没有高级账户的数据限制)
  • CSV 文件上传*(最大数据集大小为 100mb)*
  • 谷歌大查询*(我没用过)*
  • 谷歌分析/谷歌广告*(仅限最近三个月没有付费版本*)
  • 以及更多的谷歌产品

我个人最喜欢的是谷歌床单。您可以在几秒钟内连接两个程序,GDS 会将该工作表视为活动数据库,因此,只要您单击报表页面顶部的刷新按钮,您就会看到报表中反映的更改。在我的大部分报告中,我会上传文件,这样我就可以随心所欲地拥有尽可能多的行和列,而不会接近 100mb 的限制。

我创建了一个假数据集来演示加载和可视化数据是多么容易。我可以强调地告诉你,我想出这些假公司名字所花的时间比我写 GDS 报告的时间还要长。我的数据包括数据类型的组合:分类字符串、整数和日期。下面你可以看到我将这些数据连接到 GDS,并在几秒钟内创建了一个表:

仅此而已。我会说,在操作之前,你应该总是检查你的数据的语义配置,我在上传数据之后就这样做了。

第二步:视觉化

让我告诉你在 GDS 想象是多么的不可思议的容易。我在我的报告中添加了一个堆积条形图,然后更改了维度,这样我们就可以看到每个客户的联系方式的明细。

就这么简单!每个图表都从列(绿色字段)中提取数据,同时聚合指标(蓝色字段)。如果您想对一个数字列求和,只需将其拖到指标中,然后选择求和(或平均值、中值、最大值等。).对于对象列,可以选择“计数”或“非重复计数”。最后,有一个专门针对日期范围的特定维度,这就是 GDS 真正有趣的地方。

第三步:过滤器

任何人都可以给他们的团队一个带有现成图表的 powerpoint,但 GDS 走得更远。该计划旨在为所有团队成员提供充分的互动,这种互动采取过滤器的形式。在大多数程序中,如果你有 3 个销售团队,你需要为每个团队做不同的报告,但是在 GDS,你可以创建过滤器,点击一个按钮来改变报告。筛选器可以控制数据中的任何列。

3A。过滤器控制箱

您可以在左侧看到基本的交互式过滤器。我通常对几乎所有的事情都使用下拉菜单,我鼓励你尝试一下,看看什么是有效的。对于每个过滤器,您选择它将控制哪一列,然后选择您想要显示的指标,以显示该列的不同之处。假设我只想查看销售团队的客户,我想查看的指标是该类别中有多少不同的客户。您只需选择“帐户名”作为您的指标,然后将聚合设置为非重复计数。就是这样!这里有一个快速的方法:

您甚至可以通过对报告元素进行分组来控制哪些过滤器会影响哪些图表。如果没有分组,筛选器将影响共享数据源的任何内容,但是有了分组,您可以创建用户友好的复杂报表。您还可以选择将固定过滤器应用于任何报告对象,也可以选择将所述过滤器一起应用于整个组。

3B。日期控制

GDS 最有用的元素之一是它的现场报道能力。当你连接 Google Analytics 数据源时,它会直接从你的网站上提取实时数据,并根据你的报告进行汇总。当然,有些数据连接器比其他连接器快得多(在我的经验中,CSV 文件上传往往是最快的,但是数据更新是手动的)。也就是说,如果你关注纵向数据,日期范围可能很重要。GDS 非常擅长自动解析日期列,但是,即使您在处理列时遇到问题,也可以使用 PARSEDATE()函数创建一个自定义字段。我现在不会进入自定义字段,这将是另一篇文章,但请放心,如果你以' YYYY-MM-DD '格式传递日期时间列或对象列,GDS 会很好地翻译它,即使存在空值。

日期控件影响每个图表和字段中的特定数据字段。无论您在报告中放置什么对象,它们都有一个“日期范围”选项。您也可以将日期范围应用于组。在这里,您可以设置默认的日期范围,可以简单到上周,也可以复杂到上周三之前的 47 天。

3C。应用过滤器

我最后一个小小的滤镜是一个天才按钮,在所有的图表对象上贴上“应用滤镜”的标签。通过打开此按钮,您可以单击表格中的一行或图表中的一列,报告将自动基于该对象进行过滤。看看这个:

就这么简单!希望您现在可以看到这个免费的开箱即用的包中有多少工具可供您使用。

结论

作为我团队中唯一的数据人员,Google Data Studio 改变了我的生活,但它肯定有其局限性。我计划写更多的优点和缺点,以及一些我在混合数据时发现的有用的方法。以下是 GDS 如此强大的原因概述:

优点

  • 难以置信的易于使用(甚至对于非数据人员)
  • 丰富的数据连接器和可靠的文档
  • 自由的
  • 非常适合团队内部的私人数据共享
  • 非常可定制的交互式报告
  • 使用与 Google Sheets/Excel 相同的字段函数,并提供便于参考的文档字符串
  • 漂亮的动态图表
  • 过滤器本身就值门票的钱
  • 不需要编码

CONS

  • 在将数据强制写入报告之前,您必须了解您的数据
  • 如果不升级到 Google 360(每年花费 15 万美元),上传的大小是有限制的。)
  • 没有文档和论坛之外的技术支持
  • 合并数据源有极大的局限性(例如,不能使用多个连接键连接多个数据源。所有表必须有一个公共连接列)
  • 有时它只是中断,错误消息充其量只是含糊不清

总的来说,Google Data Studio 感觉像 Data Science-Lite,但除了 Streamlit for teams(仍处于测试阶段)之外,我还没有找到更好、更简单的选项来与非数据团队成员共享漂亮、复杂、交互式的报告。

我将在未来发布更多操作方法,如下所示:

  • 使用 Google Sheets api 构建数据管道
  • 非数据团队成员的最佳数据通信实践
  • 数据混合

谢谢朋友们!如果你有问题或想法,请留下评论,我会尽力回答。

谷歌的 RFA:逼近变形金刚中的 Softmax 注意机制

原文:https://towardsdatascience.com/google-deepminds-rfa-approximating-softmax-attention-mechanism-in-transformers-d685345bbc18?source=collection_archive---------15-----------------------

图片由 Free-Photos 来自 Pixabay

思想与理论

什么是注意机制&为什么 RFA 比 Softmax 好?

谷歌最近发布了一种新方法——随机特征注意力——来取代《变形金刚》中的 softmax 注意力机制,以实现类似或更好的性能,同时在时间和空间复杂度上有显著改善。

在这篇博客中,我们将了解变形金刚的背景,什么是注意力机制,以及为什么 RFA 是 softmax 注意力机制的更好替代方案。我们将从 RFA 中获得一些东西来结束这篇博客。

注:本博客基于彭等人的 Google Deepmind 最新论文“随机特征注意”。虽然我们将涵盖大多数核心概念,但请务必阅读该论文此处以深入了解数学推导、实验结果和讨论。

背景

变形金刚是目前最好的序列对序列机器学习模型。它擅长从数据序列中学习,这一事实使它在自然语言处理、机器翻译、时间序列建模和信号处理方面尤其出色。

变形金刚成功的基石是注意力机制。这些机制查看输入序列并识别最重要的元素。当对序列进行编码时,这些元素将具有更重的权重,即受到更多的关注。

说白了注意力机制是什么?

想象一下,我们正在会议中做笔记,准备写一封跟进邮件。记笔记的时候,不太可能把什么都写下来。我们可能需要用缩写或图画来代替单词;我们可能还需要跳过那些可以推断出意义损失最小的单词。这个过程将把一个小时的会议浓缩成只有一页的笔记。从本质上讲,注意力机制也在做同样的事情,它试图通过更多地关注重要的嵌入(单词的缩写或图标表示)来对序列进行编码。

什么是 Softmax 注意机制?

假设我们有句子*“什么是真正的注意机制”。*

注意机制的目标是计算序列的不同部分应该如何彼此链接并因此应该同时被注意的相关性矩阵。例如,“注意”和“机制”应该连在一起,但两者都不应该与“实际上”或“”有很大的关联。

该机制将从摄取我们的输入句子的数字形式开始,即单词嵌入矩阵。

注意:单词嵌入是一个单词的向量表示,它提取了该单词的不同属性。这些属性的一个过度隐含的例子可以是情感、词性和字符数。

然后,它将为查询W_q、密钥W_k和值W_v初始化三个权重矩阵。

然后我们可以计算查询矩阵Q、键矩阵K和值矩阵V,分别作为单词嵌入矩阵与W_qW_kW_v的点积。正如《注意力是你的全部需求》一文中所述,初始注意力矩阵可以计算如下:

来源:瓦斯瓦尼等人的《注意力是你所需要的一切》。

或者数学上如下:

来源:作者图片

为了帮助理解矩阵运算的流程,下面是底层矩阵的图示流程:

注意机制的内部状态——来源:作者图片

这种注意力也被称为 softmax 注意力,因为它使用 softmax 激活函数来将QK的缩放点积转换为注意力的相对测量值A,其中每隔一个单词将分享一个注意力比例,该比例总计为 1(或 100%)。然后,softmax 结果将与V相结合,为其提供基于注意力的语义结果。

但是什么是查询、键和值呢?

理解查询、键、值三元组背后的直觉的一种过于简单的方式可以是将转换器理解句子的能力视为最大化以下条件似然性:

  • 输入序列为[**y**, "actually", "is", "attention", "mechanism"]y =“什么”的概率
  • 输入序列为["what", **y**, "is", "attention", "mechanism"]y =“实际”的概率
  • 输入序列为["what", "actually", **y**, "attention", "mechanism"]y =“是”的概率
  • 输入序列为["what", "actually", "is", **y**, "mechanism"]y =“注意”的概率
  • 输入序列为["what", "actually", "is", "attention", **y**]y =“实际”的概率

推断可能性的方法是注意输入句子中的其他单词(单词嵌入)。在训练过程中,转换器将通过改进三个权重矩阵来学习如何基于嵌入将单词链接在一起。

这种架构的好处是,我们可以通过创建多组查询、键、值三元组(也称为多头注意力)或通过堆叠这些注意力层来捕获更复杂的语义结构。

为什么 Softmax 的注意力机制不够好?

在一个典型的 transformer 中,多头注意力被用来分解更复杂的语言模式。然后,softmax 注意机制的时间和空间复杂度变为O(MN),其将以输入序列长度的二次方速率增长。

Softmax 注意机制——资料来源:彭等人的“随机特征注意”。

为了解决这个问题,来自 Google Deepmind 的团队利用了 Bochner 定理,并扩展了 Rahmi & Recht (2008)的工作,使用随机特征图ϕ (独立正态分布的随机向量**w**和输入句子**x**之间的内积的傅立叶特征)来估计 softmax 函数的指数函数。

Softmax 函数—来源:作者图片

随机特征图——来源:彭等的“随机特征注意”。

随机特征图的点积可以用来估计指数函数——来源:彭等的《随机特征注意》。

在不深入推导太多数学细节的情况下,softmax 注意机制可以近似为以下结构:

RFA 注意机制——资料来源:彭等《随机特征注意》。

通过用 RFA 近似 softmax,Google Deepmind 将时间和空间复杂度降低到了O(M + N),即从二次到线性。

谷歌 Deepmind 的研究成果

  • 由于 RFA 具有相同的输入和输出维数要求,因此 RFA 可以用来替代 softmax 注意机制。
  • 随着复杂度从二次下降到线性,当输入文本序列较长时,RFA 取得了更显著的改善。
  • RFA 背后的基本原理可以用于近似高斯核之外的其他核函数。在 Google Deepmind 的论文中,他们展示了如何将相同的方法应用于近似反余弦核。
  • 像 softmax 一样,RFA 本身不考虑输入句子中的位置距离。在 Google Deepmind 的论文中,他们讨论了如何将递归神经网络的灵感应用于 RFA,以便单词的重要性将根据它们在句子中的相对位置呈指数衰减。
  • 最后但同样重要的是,机器学习看起来非常闪亮,但它都是关于数学和统计的。感谢优秀的研究人员和程序员,我们拥有了 TensorFlow 和 PyTorch 这样的高级软件包。尽管如此,我们需要不断学习最新的发展,并修改核心概念,以确保我们正在开发可防御和可解释的机器学习模型和管道。

这是这个博客的内容。希望你觉得博客或代码有用!如果我错过了什么,或者如果你有任何问题,请随时回复或 pm。如果你想了解更多关于 Python、数据科学或机器学习的知识,你可能想看看这些帖子:

  • TensorFlow:使用 GPU 将 NumPy 加速 10000 倍以上
  • 改进数据科学工作流程的 7 种简单方法
  • 熊猫数据帧上的高效条件逻辑
  • 常见 Python 数据结构的内存效率
  • Python 的并行性
  • 数据科学的基本 Jupyter 扩展设置
  • Python 中高效的根搜索算法

如果你想了解更多关于如何将机器学习应用于交易和投资的信息,这里有一些你可能感兴趣的帖子:

  • Python 中交易策略优化的遗传算法
  • 遗传算法——停止过度拟合交易策略
  • 人工神经网络选股推荐系统

https://www.linkedin.com/in/louis-chan-b55b9287/

谷歌地球引擎:资源和提示

原文:https://towardsdatascience.com/google-earth-engine-resources-and-tips-9c4369a66d8a?source=collection_archive---------30-----------------------

学习基础知识和动手实践的最佳资源!

美国宇航局在 Unsplash 拍摄的照片

没有什么比通过那些被称为卫星的无情生物的眼睛从太空一路看到地球更令人兴奋的了。你会立刻意识到你只是比你大得多的事物中的一小部分。这是我每次使用谷歌地球引擎平台加载卫星图像进行分析时的感受。

如果你曾经对地理空间数据分析和揭示全球范围的地球观测洞察力感到好奇,那么谷歌地球引擎平台应该是你的首选。

GEE 拥有让您起步的一切。从数 Pb 的随时可用的最新卫星图像和地理空间数据集,一直到由谷歌数据中心基础设施和丰富的资源支持的完全可操作的开发环境,以检测变化,量化地球表面的差异,并绘制长期趋势。

让我们来看看一些技巧和资源,您可以利用它们来练习使用该平台并利用其分析功能!

注册一个谷歌地球引擎开发者账户

要使用 GEE 作为开发人员,您需要首先注册!在此过程中,您将填写一份简短的表格,其中包含您的基本信息,以及您目前拥有的任何关系和您目前工作的组织。

在这份表格中,你还需要提供一个简短的描述,说明你打算如何使用地球引擎。确保你尽可能的具体。在大约一周内,无论您是否有权访问该平台,您都应该会收到 GEE 团队的回复。这一步应该很简单。

探索数据目录

获得平台访问权限后,第一个很好的步骤是探索数据目录中可用的数据集。这将使您熟悉您可以访问的数据和卫星图像。

该平台拥有丰富的地表温度、气候、土地覆盖、地形、农田、大气和合成孔径雷达(SAR)数据。

确保您浏览了 Landsat 和 Sentinel 数据集,因为您可能需要在平台上执行几乎任何任务时查看这些数据集。

照片由 NASA 在 Unsplash 上拍摄

了解开发环境是如何工作的

现在您需要开始接触使用 GEE 环境的技术方面。首先熟悉 JavaScript 开发环境和 IDE。

了解如何管理脚本、搜索文档、接收资源、在代码编辑器中保存和运行脚本、使用控制台查看输出和调试代码、使用检查器检查地图上的元素、管理任务以及查看地图和管理其图层。

随着时间的推移,一旦你做了一些练习,这些项目将成为第二天性。请记住,您不需要从第一天起就知道如何在环境中做每件事情!

了解地球引擎 API 的方法和对象

为了能够利用平台提供的功能,您需要熟悉各种类型的 Earth Engine 对象。

您应该知道图像、图像集合、几何图形、特征、特征集合、缩减器、连接、数组和图表之间的区别。

这些课程中的每一门都可以在很长一段时间内掌握。但是作为起点,在深入研究每个类的方法之前,请确保您知道一个类和另一个类之间到底有什么不同。

设定一个时间表来浏览开发者指南

这些提供了丰富的学习材料,您应该仔细阅读,尝试使用地球引擎代码编辑器复制,并在此基础上进行构建。

这些指南涵盖了所有种类的材料,包括:JavaScript 崩溃指南、最佳编码实践、调试提示和技巧、开发环境概述、API 教程、关键概念,如服务器端与客户端对象和变量之间的差异、上面讨论的不同类的对象和方法、机器学习算法以及许多其他关于资产管理的有用资源。

不要错过地球引擎社区提供的高质量教程

这包括来自地球引擎用户社区的贡献。您可以找到一些有价值的资源,这些资源以非常直观和友好的方式解释了基本概念。

查看初学者食谱,它对你需要知道的基础知识进行了很好的概述,让你开始舒适地进行基本的地球引擎开发。

一旦你在基础知识方面接受了足够的培训,并探索了像哨兵 2 号和陆地卫星 8 号那样的多光谱图像,请查看本教程,学习合成孔径雷达 (SAR)的基础知识!

练习。练习。练习。

谷歌地球引擎的一个很大的特点是,它让你专注于做实际的科学和分析,而不是专注于下载和管理大量复杂的维护数据。

这在地理空间数据分析工作流程中为您节省了大量时间。利用额外的时间在小规模的项目上练习,一旦你掌握了基本原理,你就可以在此基础上进行扩展。

试着通过不时解决不同的问题来观察地球表面不同种类的变化!最近发生的埃特纳火山爆发、德克萨斯州的风暴和洪水以及去年贝鲁特港口的毁灭性爆炸都是最近发生的事件,您可以使用谷歌地球引擎来探索这些事件,尝试检测地球表面的变化并测量损害。

由于团队(谷歌地球、谷歌开发者、谷歌云)每天都在努力改进谷歌地球引擎的体验,这种可能性是无穷无尽的。

Google Fit 数据分析

原文:https://towardsdatascience.com/google-fit-data-analysis-8541d5402f3b?source=collection_archive---------21-----------------------

一个简单的方法来解释数据探索的主要步骤。

威廉·艾文在 Unsplash 上的照片

说明

前一阵子我开始学习数据分析,经过一些学习练习后,我渴望做自己的数据探索项目。我想了想这个话题,决定我不想使用常见的和普遍可用的数据资源,如 Kaggle 或其他流行的数据集平台。我想用一些我个人感兴趣的东西。我的选择来自几个月前我安装在手机上的 Google Fit 应用程序的数据,该应用程序用于推动自己进行一些体育活动。

所以当我开始我的项目时,我有两个目的。第一个是使用数据分析的主要概念从头到尾经历数据探索的整个过程:清理、探索和可视化。第二是评估我在日常体育活动中的进步:我变得更爱运动了吗,我在运动上投入了多少时间,什么样的运动最适合我?

这两个目标对我来说真的很有意思,也很重要,现在想和大家分享一下我小小的研究成果。

一些理论

通常,数据分析的过程包括这五个步骤:

  1. 研究目标
  2. 收集数据
  3. 数据准备
  4. 数据探索
  5. 解释结果

设定研究的目的意味着我们必须知道,需要回答什么问题。我们真正想知道的是,我们的兴趣点是什么?这影响了我们研究所需的数据、参数和变量。根据这一点,我们将选择我们要寻找的数据源。

在我们确定了研究的目的和需要的数据类型后,我们应该从任何可用的资源中收集数据。最重要的是数据必须尽可能的准确和完整。否则,我们所有的研究都可能导致不正确的结果,都是无用的。

但这是一种非常罕见的情况,当我们有很好的干净的数据,我们可以立即探索。这就是为什么我们带走我们所拥有的,然后清理它,为探索做准备。

只有完成了前面的所有步骤,我们才能探索我们的数据。它可能包括使用描述性统计、建模和最有用的工具——可视化。在这个阶段,我们可以确认或否认我们的假设,并获得我们在研究的第一阶段设定目标时所提问题的答案。

最后,我们得出可以与目标受众、利益相关者或我们自己分享的结论。

好,让我们开始,一步一步地经历所有这些阶段。

1.研究目标

正如我之前说过的,这个项目有两个目的:在数据分析方面进行训练,并从我的 Google Fit 应用程序中接收一些关于我的体育活动的反馈。我有一个假设,通过每天使用这个应用程序,我变得更加热爱运动,随着时间的推移,我的运动活动增加了。

2.收集数据

这项研究的原始数据取自我在 2019 年 9 月安装在手机上的 Google Fit 应用程序。要从这个应用程序下载数据,我们应该使用 Google 外卖系统。该系统旨在向用户提供来自谷歌各种来源的数据。你要做的就是在那里注册,并指定你想从哪个应用程序接收什么样的数据,谷歌会以 CSV 格式将它们发送到你的电子邮件中。

对于 Fit 应用程序,Google 为给定时间段的每一天提供了一组文件,以及带有聚合数据的文件。我们将使用最后一个,因为它包含了我们需要的所有信息。我们要探索的时间段是从 2019 年 11 月 1 日到 12 月 31 日。

在我们的研究中,我们将使用带有 Python 模块 Pandas 和 Matpoltlib 的 Jupiter Notebook。

让我们从导入必要的模块开始…

import pandas as pd
import matplotlib.pyplot as plt

…并从文件中读取数据。

data = pd.read_csv('google-fit-data-file.csv')

让我们先快速看一下我们的数据:

data.info()

我们看到我们的数据集有 92 行 25 列。我们有很多空牢房。有些数据根本不存在(比如身高和心脏点)。我们以后再考虑如何处理它。

现在让我们看一下数据的前几行。

data.head()

如此混乱,毫无头绪。顺便说一下,这就是我热爱数据科学的原因:它让我们从这些乱七八糟的数字中获得有趣的、有时是意想不到的见解。很快我们就会从这一团乱麻中做出一份订单。

现在我们知道了数据的样子,我们可以开始为进一步的探索做准备了。

3.数据准备

3.1.清洁

首先要清理数据。这是什么意思?这意味着我们应该抛弃一切对研究没有价值或意义的东西。例如,我们的数据集中不需要一些列,因为它们现在与我无关。

正如我们在数据信息中看到的,列“身高”和“心跳”是空的。在这个分析中,我们不会处理地理数据,所以我们也不需要包含纬度和经度的列。我们不想讨论体重,所以我们删除了所有包含这些数据的列。我们不需要一个列有休息和睡眠时间的栏目,因为我们谈论的是运动,而不是休息。

我们可以用熊猫的下拉功能删除这些栏目:

axis=1 意味着我们处理列,而不是行。 inplace=True 允许我们不复制表来存储新数据,而是改变数据集本身。

3.2.格式化

有时(坦率地说,几乎总是)我们不得不改变我们拥有的数据。我们可能有不同的理由这样做,但在这个过程的最后,我们有一个更合适的数据格式或数据本身,可以更容易理解,描述和可视化。你会在下面的例子中明白我的意思。

3.2.1。类型转换

首先,我想将日期列的类型转换为日期时间格式。这将使我们有机会把日期当作日期来处理,而不是字符串。这可以通过内置的 pandas to_datetime 函数来实现:

data['Date'] = pd.to_datetime(data['Date'], dayfirst=True)

3.2.2。处理缺失数据

此外,我们希望用 0 填充所有的 NaN (空)值,这样熊猫就可以将它们视为数字,而不是缺失值。有必要进行进一步的分析和可视化。这可以通过 fillna pandas 函数来完成。

data.fillna(0, inplace=True)

3.2.3。改变尺寸

当我们查看数据时,我们发现一些值的维度不合适。很难用毫秒来表示时间,或者用米每秒来表示速度。因此,我们将把数字转换成更熟悉的单位,并相应地更改列名。

现在数据集看起来更好更清晰了。

3.3.添加信息

有时出于某种目的,我们需要向数据集添加信息。例如,我想在我们的数据表中添加一列:星期几(这真的很有趣,我的体育活动是否依赖于它)。在 pandas 中,每个 datetime 对象都有一个内置属性 dayofweek。应用它,我们为每个日期接收一个从 0(星期一)到 6(星期日)的工作日。我们不想使用数字:它们不能提供信息。所以我们把它们转换成单词,并稍微改变一下列的顺序。

经过所有这些转换后,我们的数据集看起来好多了:

4.数据探索

现在让我们开始最有趣的部分——理解我们拥有的数据。出于简洁的目的,这里我将只探索和可视化其中的一部分。但是对于那些感兴趣的人来说,在本文的结尾会有一个到 GitHub repo 的链接,在那里你可以找到这个项目的完整版本。

4.1.一般活动

好了,我们的数据集是干净的,可以开始研究了。让我们深入研究一下。

我们将从我每天活动的一般指标开始:活动分钟,即我每天做多少分钟的运动。让我们画一个简单的图表。

有意思。看起来像硬甜菜。我活动的分钟数既不是每天都不变,也不是每天、每月都在增加。好像是随机的。

好吧,如果这里没有逻辑,至少我们可以回答一个重要的问题:我做了足够的事情来尽可能保持健康吗?我们知道世界卫生组织建议每周至少运动 150 分钟。让我们检查一下我的活动是否属于这个框架。

首先,我们需要计算每周的分钟数。我们看到最后一周只包括一天,所以我们将放弃这个值。

现在我们可以为这些数据做一个图表。我们为 150 分钟的值添加一条直线,以查看我的每周活动是否超过它。

看起来很好。至少我可以说我做了足够的努力来保持健康。

但是我通常做多少分钟的运动呢?直方图可以帮助我们回答这个问题。

我们看到这个直方图几乎呈正态分布。最常见的间隔在 90 到 120 分钟之间。还不错。但是在两栋半房子之后,天数急剧下降。我从来没有走超过三个小时。

我对这些一般值的最后一个问题是:它们是否取决于一周中的某一天?正是为了这个问题,我们向数据集添加了“星期几”列。

首先,我们计算一周中每天的分钟数。然后,我们可以计算一周中每天的平均活动时间(分钟)。但我们应该准确:一个月中一周的不同天数可能不同。所以我们需要计算一周中的每一天在我们的数据集中出现了多少次。然后我们可以计算出一周中每天的平均活动时间。

我们可以画一个图形来直观地展示这些结果。

看起来很自然。像许多其他人一样,我周一做很多事情,周六更喜欢呆在家里休息(你应该知道在我住的地方,周日是工作日)。

4.2.各种活动

现在是时候谈谈我在这三个月中所做的各种活动了。

印象深刻,啊?除了到处走走,我几乎什么也没做。它占我所有活动的 75%以上。排在第二位的是游泳,然后是一点健美操,然后是几乎看不见的跑步、体操和普拉提。

好的。现在不是心烦的时候。我以后可以改进。

4.3.步行

既然散步是我的主要活动,那就让我们更具体地谈谈吧。

我们看到一天的平均行走时间是 75 分钟。一个多小时。当我们每天去工作或购物时,我们甚至不去想我们从一个地方到另一个地方花了多少时间。但这很重要,因为它对我们的整个生活都有影响。

但是那些日子我走过的距离是多少呢?

最小距离为 0。这符合逻辑。当然,有时我会呆在家里。我走过的最大距离是 12 公里多一点。差不多吧。让我们看看它是什么时候发生的。

十一月二十八日。哦,我记得那天。我和我的家人一起旅行。那真是凉爽的一天。

这个数据的另一个输出是,通常,我每天步行超过四公里。不多,但也不少,啊?

最后一个关于距离的问题:在那三个月里,我一般走了多少公里?

哇!400 多公里!

还有一个与距离相关的指标是步数。世界卫生组织建议每天至少走 10 000 步。让我们看看我是否成功。

坦白说,不是。我很少做我应该做的那么多步骤。让我们数一数我满足这个条件的天数百分比。

我觉得还不够。我应该努力。

5.解释结果

在这里,我们应该回答开始研究时提出的问题,并确认或拒绝假设的理论。就你所记得的,我有一个假设,每天使用谷歌体育应用程序会让我更运动。

这是不对的。没有一个图表在这段时间内没有持续增长的趋势。因此,使用这个应用程序——任何种类的应用程序——都不会让你的工作有起色。但是它可以向你展示真实的情况。有了这些数据,你就可以决定做什么。这取决于你,这是个好消息。

现在我知道走路是我的强项。但是我真的需要付出巨大的努力来让自己接受常规训练。我不应该依赖外部刺激。动机是内在的。我只需要有勇气承认它,并遵循这条道路。

结论

因此,我们对来自 Google Fit 应用程序的数据进行了为期三个月的研究。我们看到了我们拥有的数据,清理、重组、描述并可视化了它们。我们确定关系和模式,并绘制图形来说明它们。

使用数据可以让我们更多地了解我们周围的现象,得出科学结论,揭示以前认为不可知的东西,并有助于在所有应用领域做出明智的决策。这也是我喜欢数据和数据分析的原因。我希望继续我的研究,如果我发现一些有趣的东西,我会与人分享。

这里是 GitHub 资源库的链接,里面有该项目的完整版本:https://github.com/shebeolga/Google-Fit-Data-Analysis。我将感谢你对这个话题的评论和补充。

谷歌发布 efficient net v2——一个更小、更快、更高效的网络

原文:https://towardsdatascience.com/google-releases-efficientnetv2-a-smaller-faster-and-better-efficientnet-673a77bdd43c?source=collection_archive---------4-----------------------

与最先进的技术相比,性能更高,同时训练速度提高 5-10 倍

由 Fab Lentz 在 Unsplash 上拍摄的照片

通过渐进式学习,我们的 EfficientNetV2 在 ImageNet 和 CIFAR/Cars/Flowers 数据集上明显优于以前的模型。通过在相同的 ImageNet21k 上进行预训练,我们的 EfficientNetV2 在 ImageNet ILSVRC2012 上实现了 87.3%的顶级准确率,比最近的 ViT 高 2.0%,同时使用相同的计算资源训练速度快 5-11 倍。代码将在 https://github.com/的[发布](https://github.com/)Google/automl/efficient net v2。

来源: Arxiv

高效网络已经成为高质量和快速图像分类的 SOTA。他们大约在 2 年前发布,因为他们的扩展方式而非常受欢迎,这使得他们的训练比其他网络快得多。几天前,谷歌发布了 EfficientNetV2,它在训练速度和准确性方面都比 EfficientNet 有了很大的提高。在这篇文章中,我们将探讨这个新的高效网络是如何优于以前的。

DenseNets 和 EfficientNets 等性能更好的网络的主要基础是以更少的参数获得更好的性能。当您减少参数的数量时,您通常会获得很多好处,例如更小的模型大小,使它们更容易适应内存。然而,这通常会降低性能。因此,主要的挑战是在不降低性能的情况下减少参数的数量。

这一挑战现在主要属于神经网络架构搜索(NAS)领域,该领域日益成为热门话题。在最佳情况下,我们将对某个神经网络给出一个问题描述,它将为该问题提供一个最佳的网络架构。

我不想在这篇文章中讨论效率网。但是,我想提醒大家效率网络的概念,以便我们能够找出架构中的主要差异,这些差异实际上会带来更好的性能。高效网络使用 NAS 来构建基线网络(B0),然后使用“**复合扩展”**来增加网络容量,而不大幅增加参数数量。在这种情况下,最重要的度量标准是 FLOPS(每秒浮点运算次数)和参数数量。

1.渐进式训练

乔纳森·博尔巴在 Unsplash 上的照片

EfficientNetV2 使用渐进式学习的概念,这意味着尽管训练开始时图像尺寸最初很小,但它们的尺寸会逐渐增大。这种解决方案源于这样一个事实,即 EfficientNets 的训练速度在高图像大小时开始受到影响。

渐进式学习并不是一个新概念,以前就有人用过。问题是,当它以前使用时,相同的正则化效果用于不同的图像大小。EfficientNetV2 的作者认为这降低了网络容量和性能。这就是为什么他们动态地增加正则化和图像大小来解决这个问题。

仔细想想,很有道理。对小图像的大的正则化效果会导致欠拟合,而对大图像的小的正则化效果会导致过拟合。

借助改进的渐进式学习,我们的 EfficientNetV2 在 ImageNet、CIFAR-10、CIFAR- 100、Cars 和 Flowers 数据集上取得了出色的结果。在 ImageNet 上,我们实现了 85.7%的顶级准确率,同时训练速度比以前的模型快 3-9 倍,体积小 6.8 倍

来源: Arxiv

2。MB Conv 层上的熔融 MB Conv 层

EfficientNets 使用一个称为"**深度方向卷积层"**的卷积层,这些层的参数和 FLOPS 数量较少,但它们无法充分利用现代加速器(GPU/CPU) 1。为了解决这个问题,最近一篇名为“ **MobileDets:搜索移动加速器的对象检测架构”**的论文用一种新的层解决了这个问题,他们称之为“**融合 MB Conv 层”。**这一新层正在 EfficientNetV2 中使用。然而,他们不能简单地用融合层替换所有旧的 MB Conv 层,因为它有更多的参数。

这就是为什么他们使用训练感知 NAS 来动态搜索融合和常规 MB Conv 层的最佳组合1。NAS 的结果显示,在早期阶段用融合的层替换一些 MB Conv 层提供了更小模型的更好性能。它还示出了 MB Conv 层(沿着网络)的较小扩展比是更优的。最后,它表明内核越小,层数越多越好。

来源: Arxiv 。EfficientNetV2 在 ImageNet 上拥有几乎最高的精确度,而参数数量却只有一半

3。更加动态的扩展方法

我认为这里要学习的一个主要的有价值的想法是他们用来改进网络的方法。我认为总结这种方法的最佳方式是首先调查 EfficientNet 的问题,这是显而易见的,但下一步是**开始使一些规则和概念更加动态,以更好地适应目标和目的。**我们首先在渐进式学习中看到这一点,当时他们使正则化更加动态,以更好地适应图像大小,从而提高了性能。

我们现在看到这种方法再次被用于扩大网络规模。EfficientNet 使用一个简单的复合缩放规则1平均放大所有阶段。EfficientNetV2 的作者指出,这是不必要的,因为并非所有这些阶段都需要扩展来提高性能。这就是为什么他们使用非统一的缩放策略,在后期阶段逐渐添加更多的层。他们还添加了一个缩放规则来限制最大图像大小,因为 EfficientNets 往往会过度放大图像大小1。

我认为这背后的要点是,早期的层并不真正需要扩展,因为在这个早期阶段,网络只关注高级功能。然而,当我们进入网络的更深部分并开始查看底层功能时,我们将需要更大的层来完全消化这些细节。

来源: Arxiv

参考文献:

1Arxiv 中的 EfficientNetsV2

谷歌发布 MLP 混合器:全 MLP 架构

原文:https://towardsdatascience.com/google-releases-mlp-mixer-an-all-mlp-architecture-for-vision-824fac3e788c?source=collection_archive---------18-----------------------

回到 MLPs 的图像处理,简单但有效(有竞争力的结果)

由 Unsplash 上的absolute vision拍摄

图像处理是机器学习中最有趣的分支之一。它从多层感知开始,然后是回旋,然后是自我关注(变形金刚),现在这篇论文把我们带回 MLPs。如果你和我一样,你的第一个问题会是 MLP 如何达到和变形金刚和 CNN 几乎一样的效果?这是我们将在本文中回答的问题。新提出的“MLP 混合器”实现了非常接近 SOTA 模型的结果,该模型以几乎 3 倍的速度在大量数据上训练。这也是论文中一个有趣的指标(图像/核心/秒)。

提出的 MLP 混合器没有使用任何卷积或任何自我关注层,但却达到了几乎 SOTA 的结果,这是相当发人深省的。

MLP 混频器架构

在讨论网络如何工作之前,让我们从讨论网络的组件开始,然后将它们放在一起(就像分解汽车引擎并分析各个部分)。

我们提出了 MLP 混合器,一种完全基于多层感知器(MLPs)的架构。MLP 混合器包含两种类型的层:一种是 MLPs 独立应用于图像面片(即“混合”每个位置的特征),另一种是 MLPs 跨面片应用(即“混合”空间信息)。

来源:arxiv 上的 MLP 混音器

这里要注意的第一件事是输入图像是如何“建模/表示”的,它被建模为面片(当它被分割时)x 通道。第一种类型的层(将称为通道混合层1),对图像的独立小块进行操作,并允许在学习期间在它们的通道之间进行通信(因此是通道混合)。然而,第二种类型(称之为补丁混合)的工作方式是相同的,只是针对补丁(允许不同补丁之间的通信)。

现代图像处理网络的核心思想是在给定位置混合特征或者在不同位置之间混合特征1。CNN 用卷积、核和池来执行这两种不同类型的混合,而视觉变形者用自我关注来执行它们。然而,MLP 混合器试图以一种更“分离”的方式(下面解释)并且仅使用 MLP 来实现这两者。仅使用 MLP(基本上是矩阵乘法)的主要优点是架构简单和计算速度快。

它是如何工作的?

这是有趣的部分,我们讨论输入如何变成输出,以及图像在通过网络时发生了什么。

来源:arxiv 上的 MLP 混合器 —图像首先被分成不重叠的小块,然后被发送到网络。

第一个完全连接的层将非重叠面片投影到所需的隐藏维度中(根据层的大小)。这一层的类型是有意义的“补丁混合”层。你可以认为这是对图像进行编码,这是神经网络(作为自动编码器)中广泛使用的压缩技巧,用于降低图像的维度,只保留最关键的特征。在这之后,用图像补片的值相对于隐藏尺寸值来构建“表格”。

面片混合层在表格的列上执行其矩阵操作(例如转置),而声道混合层在表格的行上执行其矩阵操作(这在上面被表示为“混合器层”)。之后,应用非线性激活函数1。这听起来可能有点混乱,但直观地说,您可以看到混合器正在试图找到最佳的方式来混合和编码图像的通道和补丁,以获得有意义的输出。

这里要注意的重要一点是,非重叠面片的隐藏表示的大小与输入面片的数量无关。在这里证明这一点将使这篇文章比我想要的长得多,所以请随意检查文件。但是,本质上,这给出了 MLP 混频器与其他架构之间的一个非常重要的性能差异,即:

MLP 混合器的计算复杂度与输入面片的数量成线性关系,不像 ViT 的复杂度是二次的。

来源:arxiv 上的 MLP 混音器

MLP 混频器还有几个优点,简化了其架构:

  • 这些层具有相同的尺寸
  • 每层仅由 2 个 MLP 块组成
  • 每层接受相同大小的输入
  • 所有图像块都用相同的投影矩阵进行线性投影

与通常具有金字塔结构的 CNN 相比,这使得对该网络的推理和使用变得简单一些1。我记得我第一次试图设计一个 CNN,弄清楚什么时候缩小图像,什么时候放大图像,以及放大/缩小的程度可能有点困难。然而,这些问题在这种体系结构中并不存在。

需要注意的一点是,该模型还使用了跳过连接和正则化,但我不认为我们需要讨论这些概念,因为它们在许多其他资源中被广泛使用和解释。

最后的想法

来源:arxiv 上的 MLP 混音器

就结果而言,有多个表,这张表突出了一个事实,即混频器的性能与其他架构非常相似,但速度更快。它的“吞吐量”为 105 图像/秒/内核,相比之下,Vision transformer 为 32 图像/秒/内核。平心而论,这听起来可能是一个非常奇怪的指标,有时感觉 ML 的研究人员试图找到一个指标,使他们的网络看起来比其他人好得多。然而,我认为我们都可以客观地同意,仅用 MLP 块就达到相同的性能水平仍然令人印象深刻。

我希望我提供了低层次细节和高层次细节的良好平衡,没有引起太多的混乱。如果你有任何不明白的地方,请在评论中告诉我,我会尽我所能进一步解释。

谢谢你

感谢您阅读本文:)如果您喜欢这篇文章,请考虑在这里给我买杯咖啡(咖啡有助于我写作):

https://www.buymeacoffee.com/mostafaibrahim

如果你想定期收到关于人工智能和机器学习的最新论文的评论,请在这里添加你的电子邮件并订阅!

https://artisanal-motivator-8249.ck.page/5524b8f934

参考

[1]arxiv 上的 MLP 调音台

谷歌开关变压器:在恒定计算成本下扩展到万亿参数模型

原文:https://towardsdatascience.com/google-switch-transformers-scaling-to-trillion-parameter-models-with-constant-computational-costs-806fd145923d?source=collection_archive---------14-----------------------

在强烈调整的 T5-XXL 基线(谷歌的顶级变压器)上实现了 4 倍的预训练加速。

由亚瑟·奥西皮扬在 Unsplash 上拍摄的照片

变形金刚已经在机器学习方面取得了巨大的成功,特别是 NLP(现在还有图像处理)。它们是目前最热门的话题之一,谷歌试图改善它们是有道理的。

几天前,谷歌发布了一篇新的大型论文,提出了一种新的方法,在保持每秒浮点运算次数(ML 计算成本标准度量)的同时,大幅增加参数的数量。

众所周知,增加参数的数量会增加模型的复杂性和学习能力(当然在一定程度上)。正如预期的那样,该车型比 T5-XXL 提高了 4 倍,比 T5-Base 和 T5-Large 提高了 7 倍。

他们的论文比大多数论文都要大得多(大约 30 页),所以为了使这篇文章简明扼要,我将突出最重要的细节。

先决条件

科学高清照片上 Unsplash

  1. 混合专家(MoE)算法

专家混合指的是一种机器学习技术,其中使用多个专家(学习者)将问题空间划分为同质区域。…如果输出以多级概率选通函数为条件,这种混合被称为专家的分层混合。

来源:维基百科

关于 MoE 最有趣的事情之一是,虽然典型的深度学习网络对所有输入使用相同的参数,但 MoE 会调整网络,对不同的输入使用不同的参数。这使得网络更加通用。

如果你想一想,这意味着模型将有大量(稀疏)的参数,然而,并不是所有的参数都会同时使用,这是本文的本质。

MoE 在本文之前就已经介绍过了,但是,它有几个训练不稳定性和计算成本问题,本文已经解决了。

2.蒸馏

蒸馏本质上是 ML 中的“教”。当一个更小的网络模仿一个更大更好的网络,而不需要经过漫长的训练过程,就可以从中学习。这与迁移学习有所不同,并提供了显著的性能提升。

事实上,脸书最近最先进的 DeIt 论文使用 0 卷积和不到 1%的最先进数据集对图像进行分类依赖于蒸馏。如果您有兴趣了解更多关于蒸馏令牌的技巧,请在这里查看我的文章:

3.模型和数据分片(并行)

当模型和数据极其庞大时,您必须开始将它们分散到多个内核中。这通常是有挑战性的,但是因为这里的模型基本上是稀疏的(不是所有的参数总是被使用),这是容易的。其实主要卖点就是简单高效的稀疏性!

论文集锦(简述其工作原理)

照片由 Garett Mizunaka 在 Unsplash 上拍摄

这篇论文最令人愉快的一点是他们使用了“工程思维”。当处理大量的计算能力和模型参数时,你必须聪明。这就是为什么第一个重点是如何在关注后将令牌发送给正确的专家(MoE)。

这个模型从一个经典的自我关注模块(变形金刚的精髓)开始。注意部分可以聚合信息,将序列中的各个项目相互关联起来,并将它们转换成一个新序列,在这个新序列中,标记可以从其他标记收集信息。[2]

之后,有一个前馈网络(FFN),其中每个令牌都被隔离。FFN 的工作是为下一组层的确定每个标记的最佳表示。所以基本上注意力是一种相互关联的记号,前馈层是相互关联的层[2]。你可以认为 FFN 是两个实体之间翻译的中间人。一边是需要处理的令牌,另一边是一组专家。

现在有趣的是,我上面描述的都是 MoE 变压器,我们还没有开关变压器!

路由技巧

交换变压器在 FFN 层之前引入“交换”层,该层实质上推动 FFN 成为专家,并且该交换将每个令牌匹配到正确的 FFN /专家。它本质上将正确的令牌路由给最合适的“专家”。

例如,一个 FFN 层可能是处理名词的专家,另一个层可能专门处理动词、标点符号等……[2]。

他们称这个概念为交换路由,它本质上是混合专家的升级。之前 MoE 的作者假设,由于计算成本的需求,这是不可能的。Google 在这个领域引入了一个非常新颖的解决方法。

相反,我们使用一种简化的策略,只向一个专家发送。我们表明,这种简化保持了模型质量,减少了路由计算,性能更好。这种 k = 1 的路由策略后来被称为交换层。交换层有三方面的好处:

(1)减少了路由器计算,因为我们仅将令牌路由到单个专家。

(2)每个专家的批量大小(专家容量)可以至少减半,因为每个令牌仅被路由到单个专家。

(3)简化了路由实现,降低了通信成本。

来源:开关变压器论文

我们都知道 ML 依赖于浮点运算。如果你要部署一个大型的分布式模型,你必须发送大量的浮点数。浮点数主要有两种大小:16 位和 32 位,如果你只发送 16 位的数,你将不能进行标准的 ML 计算,并且由于计算的限制,你不能发送 32 位的数(这是交换路由所需要的)。

那么他们做了什么..?他们引入了一种选择性精度技术,向模型发送 16 位浮点,并选择性地将所需的浮点放大到 32 位浮点,以执行所需的操作,然后再将这些浮点缩小到 16 位。解决难题的简单方法!

他们还通过能力因子的概念来优化这些过程,其中每个专家只处理一定数量的令牌。

此外,为了缓解一些部署问题(因为这些模型非常庞大),他们使用基于 BERT 模型的蒸馏技术

来源: arxiv (乳胶转载表)

结果是在不增加参数数量的情况下,性能提高了 3–30%。这证明了蒸馏的神奇!

最终想法

这篇论文里好像做了很多工作,我还没有全部涵盖!文中有更多关于分发模型和数据的内容,但我的目的是展示亮点。看到创新总是很棒,我认为最好的部分是他们使用工程和计算机系统技术来解决 ML 问题(如路由和选择性精度)。这表明,ML 不仅是数学和统计学,也是计算机科学。

如果你有兴趣阅读更多关于其他小说的文章,请点击这里查看我的文章:

如果你想定期收到关于人工智能和机器学习的最新论文的评论,请在这里添加你的电子邮件并订阅!

https://artisanal-motivator-8249.ck.page/5524b8f934

参考文献:

1开关变压器:通过简单有效的稀疏性扩展到万亿参数模型。威廉·费杜斯、巴雷特·佐夫和诺姆·沙泽尔。2021.在 arxiv 中

[2]开关变压器:通过简单有效的稀疏性扩展到万亿参数模型。youtube 上的扬尼克·基尔彻

谷歌张量让人工智能变得更好:下面是方法

原文:https://towardsdatascience.com/google-tensor-changed-ai-for-the-better-here-is-how-b476eea684f6?source=collection_archive---------9-----------------------

社区笔记

我认为这是人工智能领域一场革命的三个原因

由瑞恩在 Unsplash 上拍摄

谷歌设计了自己的人工智能芯片,名为 Tensor ,用于其新的 Pixel 6 智能手机。该芯片结合了 GPU、CPU、ISP(图像信号处理器)、TPU(张量处理单元)和专用安全芯片。据一位谷歌高管称,Tensor 比 Pixel 5 中使用的高通骁龙 765G 快四倍多。谷歌想要比以前更好地为用户带来 Edge AI ,他们需要一个更强大的 AI 芯片。他们希望向用户推出增强的计算摄影,如消除摄影炸弹解决模糊的面孔,帮助他们轻松完成日常任务。此外,他们希望为用户更好地引入实时翻译转录。使用旧的高通芯片是不可能的。

人工智能芯片是一种处理器,经过优化,可以通过谷歌的 TensorFlow 和脸书的 PyTorch 等 ML 框架运行机器学习任务。

人工智能的发展面临着许多伦理上的和技术上的挑战,这些挑战可能会从根本上阻止它的进步。伦理挑战之一是,由于各种隐私行为,我们不能将所有数据发送到人工智能模型运行的云端。我们必须找到在用户层面运行这些模型的方法,这就是所谓的边缘人工智能。技术挑战之一是我们缺乏人工智能专用硬件,这降低了人工智能产品的开发或采用速度。CPU 不是为人工智能中的特殊计算而设计的,因此,当涉及到大型人工智能模型时,它们缺乏效率。与 CPU 相比,GPU 具有更高的效率;然而,它们还不是最佳的。

在这篇文章中,我想分享为什么我认为张量是人工智能发展中的一个惊人的里程碑,以解决上述挑战。希望你会觉得有趣。

—张量和张量流:一个强大的组合💪

谷歌大脑团队几年前开发了一个名为 Tensorflow 的高级人工智能框架。之后,谷歌设计了自己的处理单元,名为张量处理单元或 TPU,以更有效地执行张量流。TPU 的发明是人工智能的一场革命,大大加快了拥有数百万(或数十亿)参数的庞大机器学习模型的训练。然而,这项技术不能用于 Edge AI 中的智能手机等低功耗设备。谷歌加入低功耗设备的人工智能芯片制造俱乐部可能是该行业的下一场革命。许多公司如 FogHorn 和 BlinkAI 正在使用市场上现有的 AI 芯片进行边缘 AI 研究。然而,Google 通过 TensorFlow 和 Tensor 的结合所能创造的功效将是改变游戏规则的。欢迎加入俱乐部,谷歌!

— Tensor 是 AI 设计的 AI 芯片!😲

是不是很酷?这个故事是从《自然》杂志上发表的一篇文章开始的,标题是“T4:一种快速芯片设计的图形布局方法”。为了设计一个处理芯片,有一个被称为“布局规划”的关键步骤,其中工程团队必须放置大量元件,以满足包括功耗和性能在内的一系列物理要求。我没有进一步深入它的细节,因为我也不是硬件工程方面的专家。然而,当你在一系列约束条件下做出一系列选择时,人工智能可以发挥作用。你可能还记得 AlphaGo 项目是如何击败一名职业人类围棋选手的。这是完全一样的。张量是这个项目的真正成果,是人工智能行业的一个新的里程碑。太棒了,谷歌!

——张量帮助我们构建伦理人工智能。💡

这是一个双刃剑的说法。伦理人工智能有从数据隐私到全民人工智能的各个方面。Tensor 帮助许多用户有机会尝试最新的人工智能进展,而他们并不担心自己的隐私。为什么?因为 AI 引擎在芯片上运行,没有数据被发送到云端进行进一步计算。另一方面,谷歌将人工智能软件和硬件绑定得越紧密,其他公司就越难竞争。我不想看到有一天其他公司甚至不能在执行人工智能推理上竞争,即在使用人工智能上竞争。我们几乎输给了大型科技公司。如果我们在人工智能推理上输给他们,那将是一场噩梦。这就是为什么我认为“张量帮助我们建立道德人工智能”是一把双刃剑。

感谢阅读!

如果你喜欢这个帖子,想支持我…

  • 跟我上
  • 亚马逊 上查看我的书!
  • 成为 中的一员
  • 连接上Linkedin
  • 关注我 推特

https://pedram-ataee.medium.com/membership

谷歌趋势分析

原文:https://towardsdatascience.com/google-trends-analysis-1f029c941ba?source=collection_archive---------25-----------------------

心理健康宣传月

活动发起人在 Unsplash 上的照片

五月是心理健康宣传月,正因为如此,我选择写一个与心理健康相关的数据科学项目。本教程将介绍分析与饮食失调相关的 Google 趋势数据的过程。

连接到 Pytrends

该分析的第一步是安装适当的软件包。在这种情况下,我们需要 pytrends,它连接到 Google Trends 数据。

!pip install pytrends

接下来,我们必须导入 pandas 库以允许我们处理数据帧。然后,我们启动 pytrend 函数。

import pandas as pdfrom pytrends.request import TrendReqpytrend = TrendReq()

下一步是建立一个你想要调查的关键词列表。在这种情况下,我们正在寻找与进食障碍恢复和/或意识相关的关键词。这是作为起点的五个基本关键字的示例。我们通过调用关键字列表并设置时间范围来定义 pytrend 在本例中是过去五年。

kw_list = ['eating disorder treatment', 'anorexia recovery', 'eating disorder awareness', 'bulimia treatment', 'residential eating disorder treatment']pytrend.build_payload(kw_list, cat=0, timeframe='today 5-y', geo='', gprop='')

接下来,我们创建一个随时间变化的数据框架。为了简单起见,我称这个数据帧为“df ”,但是你可以随便叫它什么。

df=pytrend.interest_over_time()

现在我只想看到数据帧的前十行,所以我调用 head 函数。这将以表格形式显示每个关键字的数据。

df.head()

数据帧输出

这是什么意思?

这些数字到底是什么意思?Simon Rogers在之前的一篇媒体文章中对 Google Trends 数据做了简单的解释。基本上,兴趣分数从 0 到 100,这表明了与特定关键字相关的谷歌搜索的参与度。因此,兴趣越高,搜索就越多,这对于公司的 SEO 活动或其他营销活动来说是有益的。让我们在接下来的几个步骤中绘制出一些兴趣趋势,以显示对不同饮食失调关键词的兴趣是如何变化的。首先,我们将导入 numpy 和 matplotlib 来绘制数据。

import numpy as npimport matplotlib.pyplot as pltdata = df.drop(labels=['isPartial'],axis='columns')data.to_csv('MentalHealthGoogleTrends.csv', encoding='utf_8_sig')image = data.plot(title = 'Eating Disorder Keyword Interest Over 5 Year on Google Trends ')fig = image.get_figure()fig.set_size_inches(18.5, 10.5)fig.savefig('GoogleTrends.png')

谷歌趋势利息日期图

过去五年对 ED 恢复的兴趣

上面的图表明,在过去的五年里,人们对饮食失调恢复关键词的兴趣(至少在谷歌看来)有所波动。我们可以看到,“饮食失调治疗”是目前最受欢迎的搜索。令人惊讶的是,虽然 2017 年有所增长,但 2018 年又回落了。它似乎像一种趋势一样循环往复,考虑到当今时代 ED 的发病率正在增加,这是很有趣的。

另一个有趣的发现是,“住宿饮食障碍治疗”的搜索兴趣最低。作为一个搜索过 ed 治疗的人,我知道在门诊治疗之后,下一步往往是住院治疗。此外,寻找合适的居住设施需要大量的时间和研究,所以有趣的是,今天没有多少人在搜索这个术语。

后续步骤

现在我们已经有了一些直观的关键词的趋势,是时候找到与热门关键词(饮食失调治疗)相关的关键词了。我们将用我们最感兴趣的关键字启动 pytrend 负载,然后运行相关的查询搜索。

pytrend.build_payload(kw_list=['Eating Disorder Treatment'])related_queries = pytrend.related_queries()

接下来,我们调用刚刚提取的值。

related_queries.values()

从这个图表中,我们可以看到,最上面的关键词是“进食障碍的治疗”。然而,如果我们在上升类别下看,我们看到“我附近的住院饮食障碍治疗”越来越受欢迎。

相关主题

现在我们来看看相关的话题。这遵循类似的协议,但将返回与“饮食失调治疗”相关的首要主题。

related_topic = pytrend.related_topics()related_topic.values()

我们可以看到,上升的话题和我们感兴趣的关键词没有必然联系。然而,“热门”话题肯定与我们正在看的内容无关。这表明,有时谷歌趋势数据需要谨慎对待。

结论

这只是对 pytrends 的介绍。通过查看与饮食失调治疗相关的谷歌趋势数据,我们获得了有用的见解。例如,如果这是国家饮食紊乱协会(NEDA)的营销机构,这些见解可以应用于他们的付费和有机搜索策略。

Google vs IBM vs 微软:哪个在线数据分析师证书最好?

原文:https://towardsdatascience.com/google-vs-ibm-vs-microsoft-which-online-data-analyst-certificate-is-best-dc8fd790a174?source=collection_archive---------2-----------------------

目前市场上排名前三的数据分析师证书的回顾和比较。

照片由 Aaron Burden 在 Unsplash

似乎每个重量级人物都推出了他们自己版本的同一件事:专业数据分析师认证,注定让你成为雇主的下一个热门商品。

随着谷歌最近在 3 月份取消了最新的数据分析课程,三位一体的专业证书现在已经完成。

在过去的十年中,很明显,学习数据分析可以将你的职业生涯推向新的高度。此外,随着空缺职位的不断增加(仅在美国就有 337,400 个数据分析职位空缺),每个大公司现在都推出了认证来帮助弥合差距。由于这些公司中的许多都不需要认证的先决条件,现在任何有互联网连接的人都可以进入数据分析的世界。

问题不再是,我是否应该学习数据分析。

现在的问题变成了:我该考哪种证书?

谷歌数据分析专业证书

https://grow.google/dataanalytics/#?modal_active=none

概观

**技能等级:**初学者

**课程交付:**在线

**持续时间:**大约 6 个月(建议 10 小时/周)

价格:$ 39/月通过 Coursera(在 6 个月内完成本课程将花费$234)

**学到的技能:**电子表格、数据清理、数据分析、数据可视化、SQL、提问、决策、解决问题、R、Tableau、元数据、数据收集、数据伦理、样本量确定

课程设置: 8 门课程

IBM 数据分析师专业证书

https://www.coursera.org/professional-certificates/ibm-data-analyst

概观

**技能等级:**初学者

**课程交付:**在线

**持续时间:**大约 11 个月(建议每周 3 小时)

价格:$ 39/月通过 Coursera(在 11 个月内完成本课程将花费$429(美元)

**学到的技能:**微软 Excel、Python、数据分析、数据可视化、SQL、数据透视表、IBM Cognos Analytics、仪表盘、Pandas、Numpy

课程设置: 9 门课程

微软认证:数据分析师助理

https://docs.microsoft.com/en-us/learn/certifications/data-analyst-associate/

概观

**技能等级:**初级/中级

**课程交付:**在线(免费)或讲师指导(付费)

**持续时间:**大约 11 个月(建议每周 3 小时)

**价格:**考试费 165 美元

**学到的技能:**数据准备、数据建模、数据可视化、数据分析、部署和维护可交付成果、Microsoft Dataverse、R、Python、AI Insights、Microsoft Power BI

课程设置: 16 个模块

如何选择数据分析师认证?

在了解数据分析师认证的世界时,在选择课程时考虑两件事很重要。

选择你最感兴趣的技术认证。

首先,上面列出的认证没有一个比其他的高,甚至没有一个比其他的高。本质上,上面列出的程序是相同的,只是使用了不同的技术。例如,每个认证都要求你使用他们公司特有的技术。谷歌用 R 教他们的认证,因为他们公司用 R 做数据分析。IBM 使用 Watson 平台教授他们的认证,因为 IBM 的一切都在 Watson 上运行。最后,微软使用微软技术教授他们的认证,因为他们整个公司都使用微软技术。

一旦你学会了特定的技术,并对它们驾轻就熟,你就不太可能再去学别的东西了。这样,通过完成这些公司之一的认证,他们会吸引你虔诚地使用他们的产品。换句话说,这些认证同时也是营销工具。因此,在许多方面,你选择完成哪家公司的认证并不重要——选择你最感兴趣的技术,因为无论你选择哪门课程,你都会学到相同的基础知识。

记住,证书不是就业的黄金门票——选择一个能给你实践经验的证书。

第二,虽然谷歌等公司公开表示,他们的使命是帮助毕业生在完成认证后获得就业机会(通过谷歌雇主联盟),但并非所有该联盟以外的招聘经理都相信在线数据分析证书的重要性。事实上,许多人并不经常重视 MOOCs 或在线专业认证的完成。相反,雇主倾向于寻找有工作经验、项目经验和某种形式教育的候选人。

尽管完成 mooc 是致力于个人发展的一个很好的标志,但 mooc 并不是找到工作的黄金门票。因此,将你选择的认证与个人项目和工作经验结合起来,以显示你能够运用你的技能解决现实世界的问题,这一点很重要。这就是谷歌数据分析师认证变得特别有价值的地方,因为他们在课程结束时提供了一个顶点项目。完成这个顶石项目有助于你很好地证明你可以将技术技能应用到实际的数据问题中。

哪个专业的数据分析师认证最好?

看你问的是谁,每个人对于哪个数据分析师认证最好都会有不同的看法。

然而,根据(试图)最公正的标准和对课程的总体分析,本调查得出结论,最佳专业数据分析师认证是:谷歌数据分析专业认证。

为什么谷歌拥有最佳专业数据分析师认证:

  • 谷歌大胆宣称,尽管没有任何相关经验,他们项目的毕业生也能在数据分析领域找到工作。做出如此大胆的声明将谷歌与这一承诺联系在一起。谷歌已经准备好实现这一主张,通过在整个工作准备过程中为毕业生提供支持的资源,包括简历制作工具、模拟面试、职业网络活动以及将雇用该项目毕业生的雇主联盟。
  • 谷歌用 R 语言教授这种证书,R 语言是一种编程语言,有着众所周知的难学曲线。在老师和社区的帮助下学习这门语言会比你自己学习更顺利。从那里,毕业生可以很容易地自学 Python,这是一种非常容易掌握的语言。这样,先学习难的东西是有益的,会让你成为一名更全面的数据分析师,可以加入任何公司。
  • 谷歌已经决定在项目结束时提供一个顶点项目的机会。由于对教师的要求和课程提供者必须付出的额外努力,大多数 MOOCs 不提供顶点项目。通过利用这一机会,这个项目的毕业生拥有解决现实世界问题的技能和能力的具体证据,从而在其他求职者中占得先机。
  • 谷歌提供了一个最物有所值的项目,该项目涵盖了数据分析的基础知识,其成本仅为同等训练营或硕士学位通常成本的一小部分。不仅如此,通过 Coursera 托管他们的认证,想要参加课程的学生可以在需要时申请财政援助,从而增加各行各业的人获得认证的机会。

最后的想法。

当谈到选择在线数据分析认证时,你真的不会错。

所有的重量级人物现在都推出了他们自己版本的同类产品,让消费者在教育选择上有了更多的选择。重要的是要记住,无论你选择哪家公司,你都会在这些基础课程中学到相同的东西。因此,由你来决定谁的认证对你最有效。

这三个认证都是最近才发布的,只有时间能告诉我们哪个项目更胜一筹。无论如何,这三个项目都为数据分析世界提供了一个全面的介绍,而费用只是替代证书的一小部分。

Google 的 FNet:混合令牌和傅立叶变换

原文:https://towardsdatascience.com/googles-fnet-mixing-tokens-with-fourier-transforms-f98778168c45?source=collection_archive---------10-----------------------

借助傅立叶变换的魔力,将变形金刚的训练速度提高 7 倍

Amr Taha 在 Unsplash 上拍摄的照片

通过用线性变换替换注意力子层,我们能够降低 Transformer 架构的复杂性和内存占用。我们表明,FNet 在速度、内存占用和准确性之间提供了一个很好的折衷,在 GLUE 基准测试中,在通用分类迁移学习设置中实现了 BERT 的 92%的准确性(Wang et al .,2018),但在 GPU 上训练的速度是 7 倍,在 TPUs 上是 2 倍

来源: Arxiv

最近的 ML 论文的目标是摆弄变压器层。看看哪些有用,哪些没用是很有趣的(尽管我们可能只能从那些论文中看到哪些有用)。由于变压器的大量使用,我认为过去的 6-12 个月是关于优化它们的。从改变层到减少自我关注层,到大大减小变压器网络尺寸。这篇论文综述将讨论如何改变层来提高训练速度,最有趣的部分是它是使用傅立叶变换完成的。

什么是傅立叶变换?

傅立叶变换是一个数学概念,可以 将信号分解成其组成频率 。傅立叶变换不仅给出信号中存在的频率,还给出信号中存在的每个频率的幅度。

来源: TDS

傅立叶变换是信号处理中最常用的变换之一。它本质上是以一种特定的方式将图形的信号波“包裹”在一个圆上,这样您就可以更容易地提取信号属性和特征(从而处理信号)。如果你和我一样是个数学呆子,你一定听说过傅立叶变换。但是,让我感兴趣的是这和神经网络有什么关系?变压器通常处理 NLP,而不是信号处理,这也是我选择回顾本文的主要原因。

然而,令我惊讶的是,这些傅立叶变换似乎在深度学习领域有许多应用,例如1:

  • 解偏微分方程(用神经网络!)
  • 加速回旋
  • 稳定递归神经网络(傅立叶 RNN 和 ForeNet)

为什么要改变自我关注层?

虽然自我注意块导致更高的准确性,并为网络提供有用的上下文含义,但它们在计算上是昂贵的。这里的研究显示了一些非常重要的发现——对那些自我关注块的需求**很快就饱和了。**在阅读了最近的多篇变压器优化论文后,我开始注意到这一趋势。自我关注是相当强大的,但它本质上正在成为一个瓶颈,在不影响表现的情况下,有一个取代它的竞赛。

事实上,在 Nvidia 最近在发表的一篇论文中,他们发现对于大多数架构来说,将不到 50%的层作为自我关注块在性能方面更有效,而对于 Transformer-XL,他们建议大约 20%。此外,这些块应该只在网络的前 2/3 中(不在整个网络中交错)。这导致自我关注块减少了 63%,计算时间减少了 35%。

FNet 论文研究了一种不同的方法来混合变压器令牌(这是自我关注所做的),并提出了一种新的线性方法来使用 FTs 这样做。事不宜迟,让我们开始吧

FNet 架构

来源: Arxiv

架构实际上非常简单,这就是为什么这一部分不会很长的原因。这种架构与经典架构的唯一区别在于,编码器的自我关注层被傅立叶层1取代,傅立叶层对输入序列长度和隐藏维度进行 2D 傅立叶变换。这样做背后的主要直觉是傅立叶变换可能能够为混合输入令牌提供更好的方法(通过它的变换)。

从计算机科学的角度来看,由于非线性和自关注的复杂性,变压器具有二次复杂性(O(N))。然而,傅立叶变换是线性的,因此提供了更好的复杂性(并且增加了计算速度)。此外,与自我关注计算相比,傅立叶变换的计算在 GPU/TPU 上更加优化1。此外,傅立叶变换层不像自我注意那样有任何可学习的权重,因此使用更少的内存(因为模型尺寸变小了)。

简要结果

好吧,这听起来很简单,只是对网络中一种类型的图层进行了更改。让我们来看看这种变化可能带来的影响。

来源: Arxiv

请注意,F-Net 的准确性比 BERT 稍低,但是在训练步骤和内存使用方面要快得多。这是我喜欢这篇文章的一个原因,他们展示了他们方法的优点和缺点(无论如何,没有神奇的权衡!).

最后的想法

平心而论,即使它实现了同样的性能,我仍然会对这篇论文感兴趣,因为它提供了一种相当新颖的方法来取代自我关注层。就我个人而言,我回顾这些论文并撰写它们的主要原因是为了引发您的思考,展示大公司是如何进行优化的。在阅读本文之前,我从未想过傅立叶变换可以用来优化变压器。我想这促使我们成为更全面的数据科学家,扩展我们的知识视野,因为你永远不知道两种不同的想法可能会在哪里交织成一个。

另一方面,由于离线机器学习的需要(模型部署在小型设备上),较小的模型变得越来越重要,本文使我们向较小的变压器迈进了一步。我认为意识到机器学习/数据科学行业的发展方向很重要。

最后,如果你对傅立叶变换感兴趣(你应该感兴趣),我建议看看 3Blue1Brown 的这个令人惊叹的视频:

如果你想定期收到关于人工智能和机器学习的最新论文的评论,请在这里添加你的电子邮件并订阅!

https://artisanal-motivator-8249.ck.page/5524b8f934

参考文献:

1 FNet on Arxiv

谷歌的 LaMDA:下一代聊天机器人

原文:https://towardsdatascience.com/googles-lamda-the-next-generation-of-chatbots-62294be58426?source=collection_archive---------6-----------------------

人工智能

首先,我们有 GPT-3。现在我们有了 LaMDA。

来源: Pixabay

2020 年中期,OpenAI 推出了功能强大的语言系统 GPT 3。它彻底改变了世界,并登上了非常重要的媒体杂志的头条。这项令人难以置信的技术可以创造小说、诗歌、音乐、代码和许多其他令人惊叹的东西(如果你想了解一下,我为的数据科学写了GPT-3的完整概述)。

预计其他大型科技公司不会落后。事实上,几天前在谷歌 I/O 年会上,谷歌高管展示了这家大公司的最新研究和技术。其中一个抢了风头:LaMDA,一个能够进行类似人类对话的对话型人工智能。

在这篇文章中,我将回顾一下我们今天对这项技术的了解以及它是如何工作的。

LaMDA——对话式人工智能

LaMDA 代表“对话应用的语言模型”继之前的模型如 BERT 和 GPT-3 之后,LaMDA 也基于谷歌在 2017 年开源的 transformer 架构。这种架构允许模型预测文本,只关注前面的单词如何相互关联(注意机制)。

从这个意义上说,LaMDA 与其他现有车型相似。然而,这个系统和其他聊天机器人有一个重要的区别。LaMDA 可以管理对话的“开放性”。正如副总裁伊莱·科林斯和高级研究主管邹斌·格拉马尼在他们的博客文章中解释的那样,人类的对话有这种明显的混乱特征。我们可以从一个话题开始,几分钟后以一个非常不同的话题结束。我们倾向于通过以最意想不到的方式连接话题来展开对话。

通过解决这些情况,LaMDA 将彻底革新聊天机器人技术。具有这些能力的聊天机器人可以完美地与人进行自然对话。我们可以更自然地询问信息或咨询互联网。

拉姆达是明智的,具体的,有趣的,事实

LaMDA 接受了对话培训,与其前身 Meena 相同,Meena 是谷歌在 2020 年推出的另一种对话技术。米娜证明了聊天机器人几乎可以谈论任何事情。它被训练成最小化一个他们称为困惑的训练目标,这是一个衡量模型在预测下一个令牌时有多自信的指标。他们发现困惑与人类评估指标密切相关,如 SSA——敏感度和特异性平均值——这对评估聊天机器人的质量非常有用。

然而,LaMDA 更进一步。它擅长检测敏感性——一个句子在对话的上下文中是否有意义——并且能够更好地保持其反应的特异性。正如作者在他们的帖子中指出的,像“我不知道”这样的回答可能总是明智的,但却非常无用。

但谷歌不想停留在合理、具体的回应上。他们希望 LaMDA 以“有见地的、出乎意料的或机智的”回应的形式展示出高度的趣味性。此外,他们认为真实性是聊天机器人的一个重要方面。像 GPT-3 这样强大的系统缺乏这种特殊功能。如果回答不正确,给出有趣的回答是不够的。

最后,科技界正在打一场伦理战,以减少人工智能系统中的偏见和潜在有害使用。谷歌对此很关注,所以他们想把“责任放在第一位”他们的目标是在 LaMDA 这样的系统中最大限度地减少性别和种族偏见、仇恨言论和误导信息。

LaMDA 的惊人技能—一个例子

在会议期间,谷歌首席执行官桑德尔·皮帅在两次不同的对话中展示了 LaMDA 版本的冥王星和纸飞机的演示。他们不需要对 LaMDA 进行微调,就可以将它从模仿冥王星变成纸飞机(尽管 Collins 和 Ghahramani 承认它可以进行微调以获得更好的性能)。

从我们所看到的,LaMDA 显示了上述品质:感性,特异性,趣味性和真实性。让我们看看对话中 LaMDA 模仿 Pluto 的一些例子,保持对话的顺序:

  • **特异性。**团队问 LaMDA 如果他们造访冥王星会看到什么。它回答说:“你会看到一个巨大的峡谷,一些冰冻的冰山,间歇泉,和一些火山口。”LaMDA 可能会说一些类似于“美丽的景色”或“我周围的一些陆地和星星”的话,但决定非常具体地描述冥王星的地质细节。
  • 真实性。团队询问冥王星是否有访客,系统回答说:“有一些。最引人注目的是新视野号,它是拜访过我的航天器。”2006 年,美国宇航局启动了新视野号任务,探索冥王星及其卫星。LaMDA 把这个事实说对了(虽然单个例子并不能证明它不能把某些事实说错)。
  • 趣味盎然。团队问 LaMDA 它希望人们了解冥王星的什么,LaMDA 回答说:“我希望人们知道我不只是一个随机的冰球。我其实是一颗美丽的星球。”这里有趣的一点是,LaMDA 似乎在传达情感(尽管它没有任何感觉),这让对话更深一层。
  • 感性。在 LaMDA 表示希望人们知道冥王星是一颗美丽的行星后,团队说:“嗯,我认为你很美,”对此 LaMDA 继续说:“我很高兴听到这个消息。我没有得到应有的认可。有时人们称我只是一颗矮行星。”它回到解释为什么它希望人们知道得更多,即使在团队说了它“想”听到的话之后。从人类的角度来看,这完全说得通。甚至当有人支持我们的愿望时,我们可能会表达出来,让情绪流动。LaMDA 没有情感,但它完美地捕捉到了这种感觉。

人类谈话的独特性

现在,想想人们是如何交谈的。人类的对话是复杂的。我们说的一句话就能把谈话引向一个与最初设想完全不同的方向,而另一个人完全可以继续这个方向。或者甚至通过说这样的话来改变它:“这不相关,但是……”我们可以是“字面的或比喻的,华丽的或简单的,创新的或信息的。”我们可以进行肤浅的或更深层次的对话。我们甚至可以由浅入深。

即使在事后,也很难理解对话是如何展开的。想想你过去与父母或朋友的一次很棒的谈话,试着理清它。是什么让你想起了那些时刻?如果你试了,你能重复它吗?结局是怎么开始的吗?这就是人类语言和对话的独特之处。从每个句子中,我们可以创造出一千条新的、独特的路径。我们只需要做出选择,整个世界就会从那里出现。LaMDA 似乎也能做到这一点。

最后的想法

LaMDA 是对话式人工智能的下一个大事件。我们必须自己测试它,看它在多大程度上像人类。但从我们已经看到的来看,这是有希望的。

然而,对话型人工智能完全主导对话所需要的一件事是提出意想不到的问题和改变话题的能力。LaMDA 能否提出一个问题,并在新的、明智的、具体的、有趣的对话路径中扮演积极的角色?

目前,人工智能还无法达到这种水平。原因是,我们在谈话中的彻底改变往往依赖于我们捕捉我们所生活的世界的更广泛背景的能力。例如,如果我和一个朋友坐在公园的长椅上,我看到天空中出现了云,我可能会突然问:“我们应该去室内吗?”对话中的这种变化是明智的,但不是对对话本身,而是对我们周围正在发生的事情的更大图景。

一个能够将实用知识融入其对话工具包的人工智能可能比 LaMDA 或 GPT-3 更令人难以置信。但为此,人工智能将需要有一个身体,并生活在世界上。现在,见证 LaMDA 和 GPT-3 之间的对话不是很棒吗?你怎么想呢?

订阅 算法桥 。弥合算法和人之间的鸿沟。关于与你生活相关的人工智能的时事通讯。

您也可以直接支持我在 Medium 上的工作,并通过使用我的推荐链接 这里 成为会员来获得无限制的访问权限! :)

谷歌的开放图像:现在更容易下载和评估与 51

原文:https://towardsdatascience.com/googles-open-images-now-easier-to-download-and-evaluate-with-fiftyone-615ce0482c02?source=collection_archive---------7-----------------------

高效下载开放图像,并使用开放图像风格的评估功能对您的模型进行评估

打开图像数据集在五十一下载并可视化(图片由作者提供)

谷歌的开放图像是一个数据集的庞然大物。它拥有超过 900 万张图像、8000 万条注释和跨越多个任务的 600 个类,是计算机视觉社区中领先的数据集之一。

使用开放图像现在比以往任何时候都更容易,因为它集成到了开源 ML 开发工具 FiftyOne 。

计算机视觉模型比以往任何时候都更加渴求数据。开发您自己的模型需要您自己收集和注释大量数据,或者求助于公共数据集,希望它们包含与您的任务相关的数据。Open Images 背后的团队致力于为任何人提供一个巨大的数据湖。通过仅在知识共享署名(CC-BY) 许可下管理图像,任何感兴趣的人都可以使用开放图像。

凭借图像级标签、分段、视觉关系、本地化叙述和比下一个最大的检测数据集 多 15 倍的 对象检测,开放图像可以很容易地添加到您的数据湖和训练工作流中。然而,学习一种新的数据集格式并将其合并到您的工作流程中通常是乏味且耗时的。以前,下载开放图像的过程包括编写定制脚本来下载和解析您想要的图像和标签。这催生了多种工具来帮助加载数据集,但它们都有严重的缺点,比如不支持分段和关系、没有可视化能力以及不能指定下载格式。

在 Voxel51 ,我们与 Google 合作,通过将它整合到我们的开源 ML 工具 FiftyOne 的数据集 Zoo 中,创建了一个易于使用的下载开放图像的来源。使用五十一,您可以准确指定您想要下载的开放图像的子集,将其导出成几十种不同的格式,在五十一应用中可视化,甚至使用开放图像风格的对象检测评估来评估您的模型。

这篇博文将带你了解如何使用 FiftyOne 来:

  • 下载开放图片
  • 以不同的数据集格式导出打开的图像
  • 使用开放图像风格的评估来评估对象检测模型

在我们开始之前,确保安装 51 个:

pip install fiftyone

跟随在科拉布

你可以直接在这个 Google Colab 笔记本的浏览器中运行这篇博文中的例子。跟随链接,点击“在 Google Colab 中运行”。

可视化嵌入在笔记本中的开放图像(作者图片)

打开 51 数据集动物园中的图像

现在只需要一个命令或一行 Python 代码就可以从开放图像中准确下载您想要的样本。然后,您可以在 FiftyOne 应用程序中用多一行代码探索数据集。

打开图像数据集在五十一下载并可视化(图片由作者提供)

将 Open Images 集成到 FiftyOne 中提供了多个参数,您可以使用这些参数来指定您想要下载的样本及其数量:

  • label_types:要加载的标签类型列表。值为("detections", "classifications", "relationships", "segmentations")。默认情况下,会加载所有标签,但并非每个样本都会包含每种标签类型。如果同时指定了max_sampleslabel_types,那么每个样本都将包含指定的标签类型。
  • splitsplits:一个字符串或字符串列表,指示要加载的拆分。可用的拆分是("test", "train", "validation")
  • classes:指定需要加载的类的字符串列表。只有包含至少一个指定类实例的示例才会被下载。
  • attrs:要加载的关系属性的字符串列表。该参数仅在"relationships"处于label_types时有用。
  • max_samples:导入样本的最大数量。默认情况下,会导入所有样本。
  • shuffle:布尔型,指示是否随机打乱导入样本的顺序。
  • seed:洗牌时使用的随机种子。
  • image_ids:要加载的特定图像 id 列表。id 可以指定为<split>/<image-id><image-id>
  • image_ids_file:换行分隔的.txt.json.csv文件的路径,包含要加载的图像 id 列表。id 可以指定为<split>/<image-id><image-id>。如果提供了image_ids,该参数被忽略

其中一些参数允许您指定希望包含在子集中的特定类和属性。您可以使用以下命令查看打开的图像中的可用选项列表:

利用这一功能,我们可以为特定任务筛选数据集,而无需下载整个数据集或解析任何原始注释文件。例如,如果我们想要训练一个木制物体的检测器,我们可以指定我们只想要来自包含带有注释为Woodenvisual relationship的物体的开放图像的样本:

木制乒乓球台在五十一年可视化(图片由作者提供)

再比如,我们建立一个检测猫狗的数据集。我们可以为类别DogCat获得detections以及图像级别classifications:

在 51 中可视化的开放图像的猫/狗子集(图像由作者提供)

当处理包含对象检测的数据集时,FiftyOne 允许您创建一个补丁视图,其中每个样本包含一个对象。当试图分析特定的对象类或属性时,这非常有用,尤其是在混乱的场景中。

第五十一个应用程序中对象的补丁视图示例(图片由作者提供)

导出到不同的格式

多年来,COCO 数据集一直是最重要的对象检测数据集,导致相当大比例的计算机视觉(CV)社区采用 COCO 格式来解决他们的对象检测问题。为项目选择数据集格式决定了加载和处理数据集所需的解析器,这使得很难处理不同格式的新数据。FiftyOne 允许您将数据集导出成几十种不同的格式让您可以轻松地将其集成到现有的工作流程中。

例如,您可以导出为类似于 COCO 、 Pascal VOC 、 CVAT 、 YOLO 、 TFRecords 、分类目录树、 more 的格式。其中许多格式还支持导出分段掩码。

实际上,以 COCO 格式导出我们之前加载到磁盘的打开图像的子集非常简单:

如果您想将您的数据重新导入到 FiftyOne 中,并且数据集遵循一种受支持的格式,这也可以在一行代码中完成:

即使你的数据集是完全自定义的格式,将它加载到 fiftone 中仍然很容易。

开放图像目标检测评估

FiftyOne 不仅可以轻松加载和导出开放图像和自定义数据集,还可以让您可视化您的数据和评估模型结果。

Open Images 风格的对象检测评估是为 Open Images challenges 创建的。它与可可式评估有几个显著的不同:

  • 图像级标签指示在每个图像中评估哪些对象类。如果预测了一个类,但没有将其注释为正或负图像级标签,则该类将被忽略。
  • 语义类层次用于扩展预测和基础事实对象列表,以包括和评估所有父类。默认情况下,基本事实检测仅包括叶类,并且必须在评估发生之前展开。这是在五十一中自动执行的。
  • 像 COCO 一样,“人群”地面真相检测能够与多个预测相匹配。但与 COCO 不同的是,每个人群中只有一个预测是真正积极的。
  • COCO 式评估在 10 个不同的 IoU 值范围内对 AP 求平均值,Open Images 式评估仅使用 0.5 的 IoU 来计算 mAP。

如果您想查看 开放式图像式评估 COCO 式评估 的评估协议的详细步骤,请点击这些链接。

为了尝试开放图像风格的评估,我们可以使用来自51 模型动物园的模型来生成对我们下载的开放图像的猫和狗子集的检测预测。我们将向数据集添加一个新的predictions 字段:

注意:运行该模型需要 TensorFlow 1.14。

pip install tensorflow==1.14

对于这个例子,我们只对“猫”和“狗”这两个类的预测感兴趣,所以我们可以利用 FiftyOne 灵活的数据集表示来创建一个视图到只包含这些类的数据集中。此外,我们运行的模型是在 COCO 上训练的,COCO 使用小写类名,因此我们需要重新映射它们以匹配打开图像的大写类名:

我们现在可以对数据集和预测运行开放图像风格的评估:

返回的results 对象包含了我们需要的一切,从地图,到 PR 曲线,到混淆矩阵。

51 年绘制的 PR 曲线(图片由作者提供)

应该注意的是,默认情况下,这些检测协议将只把预测对象与同一类别的基本事实对象进行匹配。这意味着,如果我们想要一个有趣的混淆矩阵,我们将需要用等于False的参数classwise进行评估:

我们现在可以查看一个交互式混淆矩阵,其中如果我们单击一个单元格,则51 个应用程序将会更新,仅显示该单元格中存在的样本。因此,例如,如果我们单击包含与预测的“猫”检测相匹配的真实“狗”检测的单元,我们可以深入了解我们模型的故障模式:

假阳性在 51 中交互可视化(图片由作者提供)

注: 互动剧情 目前仅在 Jupyter 笔记本中支持。对其他环境的支持将很快增加。

当在 51 中评估对象检测数据集时,在运行evaluate_detections并用eval_key将结果存储在数据集上之后,我们能够创建所谓的评估视图。这是数据集的一个视图,其中每个样本都是一个单独的基础事实或预测对象补丁,允许您按真阳性、假阳性和假阴性、匹配的 IoU 以及单击按钮的其他评估元数据进行排序。

在第五十一个应用中创建评估视图(图片由作者提供)

高级数据集探索

如果我们想对我们的模型有一个更细致的了解,那么在低维空间中可视化对象嵌入是很有用的,它允许我们快速挑选出数据中的模式、集群和异常。51 号大脑正是提供了这种工作流程。

注意:大脑 默认使用的 降维方法是 *umap* 我们需要安装:

pip install umap-learn

我们可以再次使用51 模型动物园来生成嵌入,然后我们将可视化这些嵌入:

第五十一届互动嵌入可视化(图片由作者提供)

由于多种原因,这种可视化非常有价值,尤其是对于像包含机器生成标签的开放图像这样的数据集。可视化和交互式探索嵌入使您可以快速抽查哪些机器生成的标签可能需要检查并发送进行重新标注。

我们还可以使用这些嵌入来自动查找相似和重复的样本,只需点击一个按钮。

选取样本并按相似度排序第五十一(图片由作者提供)

一旦我们彻底探索了我们的数据集,并找到了我们想要进一步分析或改进的方面,就很容易标记单个样本或标签以便将其隔离用于下游用例。

51 中的标签样本(图片由作者提供)

摘要

Open Images 是一个大规模但经过彻底标记的数据集,可以为您的数据湖和模型训练工作流增加有用的内容。下载和探索开放图像最简单的方法是使用51。对于像开放图像一样大的数据集,动手评估您的模型结果可能会很困难。通过可视化嵌入,FiftyOne 可以轻松理解数据集,找到模型中的故障模式,并揭示数据中的模式。

关于体素 51

Voxel51 总部位于密歇根州安阿伯,由 Jason Corso 博士和 Brian Moore 博士于 2016 年创立,是一家人工智能软件公司,通过提供开放核心软件构建模块,使计算机视觉和机器学习工程师能够快速设计数据驱动的工作流,从而实现软件 2.0 的民主化。

想了解更多?在 fiftyone.ai 查看我们的网站。

Google 的 Tesseract OCR:它在文档上有多好?

原文:https://towardsdatascience.com/googles-tesseract-ocr-how-good-is-it-on-documents-d71d4bf7640?source=collection_archive---------23-----------------------

芬恩·蒙德在 Unsplash 上的照片

T 谷歌的光学字符识别(OCR)引擎可以说是最受欢迎的开箱即用的 OCR 解决方案。最近,我的任务是为文档开发一个 OCR 工具。我知道它的健壮性,但是出于好奇,我想研究它在文档上的性能。

一如既往,在考虑合成我自己的一个之前,出发点是寻找一个可靠的基础事实。幸运的是,我找到了一个:来自莫斯科物理技术学院的机器智能团队的 DDI-100 数据集。它有 30GB 左右的数据,有字符级的地面真实数据,很甜!然而,请记住,有些书是俄文的。在这项研究中,只使用了第 33 和 34 本书。这些书加起来有 300 多页,加上增刊,精确到 5145 页。

写这篇文章的时候是周五晚上,所以我会尽可能地保持讨论的简洁。生成结果的代码可以在我的 repo 这里找到。

实验设计

语言数据。 Tesseract 4.0.0 自带三个语言模型,分别是: tessdatatessdata_best 和 *tessdata_fast。*所有三种模型都将用于本研究。

预处理。来自数据集中的每个文本都经过预处理步骤,该步骤依次执行以下操作:
1 .文本周围有 5 个像素的填充。
2。调整到 30 像素的目标高度。
3。执行 Otsu 二进制化。
4。如果背景是暗的,则反转图像(按位)。Tesseract 为深色前景和浅色背景的文本提供了最佳效果。

绩效指标。所有上述模型将根据以下标准进行评估:
1。直接匹配(小写)。
2。莱文斯坦距离。
3。处理时间。

硬件。我的笔记本电脑运行的是英特尔酷睿 i7–7500 u CPU,主频为 2.70GHz,内存为 16 GB。我在两个内核上运行 Linux (WSL)上的代码(以防万一,以避免任何节流)。

其他信息。这些是关于 tesseract 和 leptonica 版本的附加信息:tessera CT 4 . 0 . 0-beta 1 和 leptonica-1.75.3。

结果和讨论

基于直接匹配的精确度

如果识别每个文本对您的用例至关重要,您可能会对上面的结果感兴趣。令我惊讶的是,我分不清他们。实际上, tessdata_fast 显得更准确。

这与宇宙魔方的文档中给出的关于他们模型的描述不一致。这让我想到,或许, tessdata_best 在 Levenshtein 距离方面可能表现更好。

删除得分为 1.0 的文本后的 Levenshtein 距离

上面的结果是 Levenshtein 距离的箱线图,没有所有得分为 1.0 的文本和异常值。这样做是为了验证我的假设 tessdata_best 在基于可编辑距离进行评估时表现更好;然而,事实也并非如此。

每个文本的处理时间

上图显示 tessdata_best 比 Linux 上的 Tess dataTess data慢 4 倍。 tessdata_fast ,顾名思义,比 tessdata 和 tessdata_best 都要快。

结论

Google 广泛使用的 OCR 引擎在开源社区中非常受欢迎。这里,我做了一个快速实验来评估它在文档上的性能。他们的三种语言模型都进行了比较。

在识别准确性方面,tessdata 和 tessdata_best 似乎表现出不相上下的性能。 *tessdata_fast,另一方面,*略好于前两款。而且不出所料,这款也是最快的。

考虑到所有三种宇宙魔方模型的性能,下一个自然的问题是:“优越的”模型值得使用吗?基于以上结果,是一个 来自我*。然而,我必须强调,这个决定只适用于我的用例。对于其他语言和/或其他图像类型,结果可能会有很大不同。*

有 App 吗?有数据吗?下面是如何在 Node / Express 应用程序中将数据存储到 MongoDB 中

原文:https://towardsdatascience.com/got-app-got-data-heres-how-to-store-data-to-mongodb-in-a-node-express-app-d4a46388cc55?source=collection_archive---------27-----------------------

由凯利·西克玛在 Unsplash 上拍摄的照片

每个应用程序都有数据。让我向您展示如何从一个用 Node.js 和 Express.js 编写的应用程序中将数据存储在 MongoDB 数据库中。

什么是污垢

CRUD 是创建、读取、更新和删除的缩写。CRUD 是用于以下目的的操作:

  • 在数据库中创建数据
  • 读取数据库中的数据
  • 更新数据库中的数据
  • 删除数据库中的数据

我们将创造什么

我们将创建一个简单的应用程序,您可以在 MongoDB 数据库中存储用户的名字和姓氏。它看起来是这样的:

作者图片

先决条件

在本文中,我假设您已经在计算机上安装并运行了以下项目:

  • 结节
  • npm

如果您还没有安装它们,那么您需要在继续本教程之前安装它们。

入门指南

我们需要为我们将要创建的项目创建一个文件夹。创建一个名为node-crud-demo的新文件夹。转到这个新文件夹,运行这个命令来启动我们的项目:

npm init

您只需按 enter 键并接受提示的所有默认值。

该命令创建一个package.json文件。这个文件将包含我们将在应用程序中使用的所有包。

创建服务器文件

我们的应用程序将有一个服务器。在您的目录中为服务器创建一个新文件。使用以下命令创建文件:

touch server.js

在编辑器中打开该文件,并添加以下行:

console.log('Hello World')

我们将使用 Node.js 运行我们的服务器。您可以通过在终端中运行以下命令来测试它是否正常工作:

node server.js

现在在你的终端中运行node server.js,你应该会看到这个:

作者图片

接下来,我们需要为我们的服务器安装软件。

安装 Express 和其他依赖项

我们将使用 Express.js 作为我们的服务器。根据他们的网站:

Express 是一个最小且灵活的 Node.js web 应用程序框架,为 web 和移动应用程序提供了一组强大的功能。

您可以通过在终端中运行以下命令来安装 express:

npm install express

您可以通过打开package.json文件来验证它是否已安装。您将看到它安装在依赖项中,如下所示:

"dependencies": { 
  "express": "^4.17.1" 
}

当我们第一次运行我们的服务器时,我们使用 Node 来启动服务器。如果您对服务器文件进行了更改,您将需要停止 node 的运行,并在中再次启动它,以使它反映您的更改。

有一个名为nodemon的包提供了与 node 相同的功能。最大的不同是,它会识别你什么时候修改了代码,并自动为你重启服务器。这将使生活更容易,所以让我们用这个命令安装它:

npm install nodemon

为了使我们的生活更容易,我们可以创建一个脚本来为我们启动服务器。打开package.json文件。

目前,该文件的脚本部分有一个条目:

"scripts": { 
  "test": "echo \"Error: no test specified\" && exit 1" 
},

将以下内容添加到脚本部分,如下所示:

"scripts": { 
  "test": "echo \"Error: no test specified\" && exit 1", 
  "start": "nodemon server" 
},

有了这个脚本,我们现在可以使用以下命令启动我们的服务器:

npm start

要安装的另一个包叫做 ejs 。EJS 是嵌入式 JavaScript 模板。我们将使用它向浏览器显示内容,并将数据从数据库传递到浏览器。您可以使用以下命令安装它:

npm install ejs

我们将在下一节配置 ejs。

配置我们的 Express 服务器

打开server.js文件。您可以删除 console.log 行。要使用 express,我们需要导入它并使用它来启动我们的应用程序。将这些行添加到文件中:

const express = require('express'); 
const app = express();

接下来,我们需要启动我们的服务器,并告诉它监听哪个端口。对于这个演示,我将在端口 3000 上运行应用程序。如果需要,您可以使用不同的端口。

在导入 express 后,添加以下行以指定我们将使用的端口:

const port = 3000;

在文件底部添加以下几行来启动我们的服务器:

app.listen(port, () => { 
  console.log(`Server listening on port ${port}`); 
});

我们可以通过在终端使用脚本npm start启动服务器来测试它。然后打开浏览器,导航到localhost:3000。您应该会看到以下消息:

作者图片

没关系。这表明浏览器正在与我们的服务器对话。接下来,我们需要将一些有价值的东西发送回浏览器。

向浏览器发送文件

当用户导航到localhost:3000时,我们希望向浏览器显示一个文件。我们将使用 ejs 来显示文件。我们需要配置我们的应用程序,让它知道我们正在使用 ejs 。创建应用程序后,添加以下代码行:

app.set('view engine', 'ejs');

默认情况下,ejs 在名为 views 的目录中查找文件。使用以下命令创建此文件夹:

mkdir views

在该文件夹中,您需要创建一个文件,我们将显示给浏览器。通常这个文件叫做 index.ejs 。由于我们使用的是 ejs ,它希望所有文件的扩展名都是.ejs。用这个命令在视图目录中创建一个index.ejs文件:

touch views/index.ejs

打开index.ejs文件并添加以下代码:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Mongo CRUD Demo</title>
    </head>
    <body>
        <h1>MongoDB CRUD Demo</h1>
    </body>
</html>

接下来,我们需要更新我们的服务器来显示这个文件。打开server.js文件。在app.listen代码上方插入以下代码,以向浏览器显示 index.ejs 文件:

app.get('/', (req, res) => { 
  res.render('index.ejs'); 
});

在这段代码中,我们告诉服务器监听来自由'/'代表的应用程序主页的调用。当它收到请求时,它会返回index.ejs文件。

打开您的浏览器,导航到localhost:3000,您将在浏览器中看到该文件的输出:

作者图片

太棒了。我们让服务器响应来自浏览器的请求。

HTTP 动词

您可能想知道服务器是如何知道将index.ejs文件发送给浏览器的。它知道是因为我们告诉服务器用app.get代码响应来自浏览器的GET请求。

GET 是 HTTP 动词之一。动词告诉浏览器做什么。对于 CRUD 应用程序, GET 动词是如何完成 CRUD 的 READ 部分。以下是其他 HTTP 动词及其对应的内容:

  • 创建—发布
  • 阅读—获取
  • 更新—上传
  • 删除—删除

让我们仔细检查并实现 CRUD 的创建部分。

创造

如果浏览器向服务器发送一个 POST 请求,它们只能执行一个创建操作。这个 POST 请求可以通过一个form元素触发。

打开index.ejs文件。我们将在文件中添加一个表单。该表单将允许用户输入名和姓。将以下内容添加到文件中:

<div class="container form">
  <div>Create</div>
  <form action="/users" method="POST">
    <div class="entry">
      <label for="fname">First Name</label>
      <input type="text" placeholder="First Name" name="fname" />
    </div>
    <div class="entry">
      <label for="lname">Last Name</label>
      <input type="text" placeholder="Last Name" name="lname" />
    </div>
    <button class="button button-block" type="submit">
      Create
    </button>
  </form>
</div>

在上面的代码中,您会看到它将使用路由 /users 向服务器发送一个 POST 请求。

为了响应这个 POST 请求,我们需要创建一个路由。打开server.js文件。在当前路线的下方为app.get添加以下代码:

app.post('/users', (req, res) => { 
  console.log('POST called'); 
});

如果你刷新你的浏览器,你会看到我们的表单,用户可以输入他们的名字和姓氏。点击create按钮。如果您的终端一切正常,您应该会看到 console.log 的输出,如下所示:

作者图片

如果您看到 console.log,那么这意味着服务器正在响应您的浏览器的 POST 请求。

下一步是获取用户输入的名和姓的值。默认情况下,Express.js 不会解析发送给它的数据。为了获得这些值,我们需要安装一个名为 body-parser 的包。

Body-parser 是一个中间件。它将解析在 POST 请求中发送给服务器的值。

您可以在终端中使用以下命令安装它:

npm install body-parser

打开server.js文件。我们需要告诉我们的应用程序使用主体解析器包。在文件的顶部添加这个新包的导入。

cost bodyParser = require('body-parser');

在创建应用程序的那一行之后,添加以下配置代码:

app.use(bodyParser.urlencoded({ extended: true }));

body-parser 中的urlencoded方法将从form元素中提取数据,并将它们添加到request对象的body属性中。

更改 console.log 以打印出req.body

您的server.js文件应该是这样的。注意:我添加了一些标题来分解文件的每个部分。

const express = require('express'); 
const bodyParser = require('body-parser'); 
const port = 3000; 
const app = express(); /* -------------------------------- 
*   APP CONFIG 
* -------------------------------- */ app.use(bodyParser.urlencoded({ extended: true })); /* -------------------------------- 
*    ROUTES 
* -------------------------------- */ 
app.get('/', (req, res) => { 
  res.render('index.ejs'); 
}); app.post('/users', (req, res) => { 
  console.log(req.body); 
}); /* -------------------------------- 
* START SERVER 
* -------------------------------- */ 
app.listen(port, () => { 
  console.log(`Server listening on port ${port}`); 
});

如果您返回浏览器并刷新,您可以输入您的名字和姓氏。当您单击 submit 按钮时,它应该在终端中打印出如下所示的值:

作者图片

向我们的应用程序添加样式

我们的形式看起来相当原始。在本教程的开始,我给出了我完成的应用程序的截图。它看起来相当精致。我们需要为我们的应用程序添加样式,以获得这种精致的外观。

所有的 CSS 都在一个名为styles.css的文件中。但是我们如何告诉浏览器使用这个文件中的样式呢?我们创建一个名为public的文件夹,并将文件放入其中。然后我们告诉我们的应用程序使用这个目录为浏览器提供文件。

使用以下命令创建公共目录:

mkdir public

接下来,使用以下命令在该文件夹中创建一个名为 styles.css 的文件:

touch public/styles.css

我们需要做的最后一件事是配置我们的应用程序使用公共文件夹。打开server.js文件,在我们的 ejs 配置之后添加这一行:

app.use(express.static('public'));

这告诉我们的应用程序,如果它找不到文件,那么就在公共目录中查找它。我们将更新我们的index.ejs文件,以包含一个到样式表的链接。

打开index.ejs文件。在标题后的head部分包含以下行:

<link rel="stylesheet" href="/styles.css" />

我们需要做的最后一件事是在 styles.css 文件中编写我们的 css。本教程不是教你如何写 CSS,所以我将提供 CSS 代码,这将使我们的应用程序看起来很好。打开styles.css文件并插入以下代码:

body {
  background-color: #c1bdba;
  font-size: 20px;
  margin: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
.container {
  max-width: 800px;
  width: 90vw;
  margin-bottom: 40px;
  /* margin: 40px auto; */
  box-shadow: 0 4px 10px 4px rgba(19, 35, 47, 0.3);
  box-sizing: border-box;
}
.form {
  background: rgba(19, 35, 47, 0.9);
  padding: 20px;
  border-radius: 8px;
}
.container div {
  text-align: center;
  color: #fff;
  margin-bottom: 20px;
}
.entry {
  display: flex;
  align-items: center;
  margin-bottom: 40px;
}
.entry label {
  flex: none;
  display: block;
  width: 200px;
  color: #fff;
}
input {
  display: block;
  flex: 1 1 auto;
  height: 100%;
  padding: 10px;
  background: none;
  border: 1px solid #a0b3b0;
  color: #ffffff;
  border-radius: 0;
}
table {
  width: 100%;
  padding: 5px;
  margin: auto;
  border-collapse: collapse;
}
tr {
  border-top: 1px solid #c1c3d1;
  border-bottom: 1px solid #c1c3d1;
}
th {
  text-align: left;
  border-right: 1px solid #343a45;
  padding: 10px;
  background: rgba(19, 35, 47, 0.9);
  color: #d5dde5;
}
td {
  background: #fff;
  padding: 20px;
  vertical-align: middle;
  border-right: 1px solid #c1c3d1;
}
.button {
  border: 0;
  outline: none;
  padding: 10px 15px;
  text-transform: uppercase;
  background: #1ab188;
  color: #ffffff;
}
.button-block {
  display: block;
  width: 100%;
}
.form-group {
  display: flex;
}

MongoDB

对于本教程,我将使用 MongoDB 作为我的数据库。我们需要在我们的应用程序中安装它。在终端中,使用以下命令安装 MongoDB:

npm install mongodb

接下来,我们需要创建一个 MongoDB 数据库供我们使用。我不打算通过这些步骤向您展示如何在您的笔记本电脑上安装 MongoDB。相反,我们将使用名为 MongoDB Atlas 的免费服务。

MongoDB 地图集

你需要在 MongoDB Atlas 上创建一个账户。

创建帐户后,您需要创建一个组织。一个组织就像一个公司的名字,但是因为我们没有公司,所以我们可以给我们的组织起任何我们想要的名字。我将命名我的 CRUD 教程

作者图片

接下来,您将被要求选择一个云服务。默认选项是 MongoDB Atlas ,这就是我们将要使用的。

作者图片

接下来,您需要设置权限。MongoDB Atlas 将自动插入您创建帐户时使用的电子邮件地址,并将权限设置为组织所有者。我们不需要在此屏幕上进行任何更改,只需单击按钮即可创建您的组织。

创建您的组织后,您将在您的控制面板中看到以下内容:

作者图片

下一步是创建数据库。您需要首先创建一个项目,因此单击新建项目按钮。您将被要求命名您的项目。我给我的用户打电话。

作者图片

就像我们创建组织时一样,它接下来会要求您设置权限。它会自动添加您创建帐户时使用的电子邮件地址。我们不需要做任何更改,因此单击创建项目按钮。

您将看到此屏幕,要求您创建一个新的集群:

作者图片

点击构建集群按钮。将会询问您想要使用哪个计划。选择自由群集选项。

作者图片

然后,您将被要求选择一个云提供商和地区。它将默认为离您最近的一个。点击创建集群按钮。MongoDB Atlas 将创建您的数据库。这可能需要几分钟才能完成。

连接到数据库

一旦 MongoDB Atlas 创建了您的集群,您将需要获得它们提供的信息来连接到数据库。我们将使用这个连接字符串连接到数据库,并将用户的名字和姓氏保存在数据库中。

点击连接按钮。

作者图片

MongoDB Atlas 将要求您在连接到数据库之前将您的 IP 地址列入白名单。点击添加您当前的 IP 地址按钮。

接下来,您需要创建一个用户来管理您的数据库。创建用户名和密码。请务必记住这一点,因为我们将需要它来连接到数据库。点击创建数据库用户按钮。最后,点击选择一种连接方式按钮。

作者图片

从列表中点击连接您的应用。您将看到连接字符串。点击复制按钮复制连接字符串。

作者图片

打开您的server.js文件。在文件的顶部,您需要使用以下代码导入 MongoDB:

const MongoClient = require('mongodb').MongoClient;

在那一行下面,为 dbUrl 添加一个新的 const,它包含到 MongoDB Atlas 数据库的连接。在从 Atlas 连接字符串中复制的代码中,您需要更改两件事情。替换为您的密码,并更改为您的数据库的名称。您的连接字符串应该是这样的:

const dbUrl = 'mongodb+srv://admin:@cluster0.38khl.mongodb.net/?retryWrites=true&w=majority';

创造

现在我们已经在 MongoDB Atlas 上创建了我们的帐户,并在我们的应用程序中安装了 mongo,我们需要将数据写入数据库。拆下app.post中的console.log,换成:

app.post('/users', (req, res) => {
  MongoClient.connect(dbUrl, { useUnifiedTopology: true }, (err, client) => {
    if (err) return console.error(err);
    const db = client.db('node-demo');
    const collection = db.collection('users');
    collection
      .insertOne(req.body)
      .then(() => {
        res.redirect('/');
      })
      .catch(() => {
        res.redirect('/');
      });
  });
});

让我解释一下这段代码在做什么。它使用我们的连接字符串连接到 MongoDB Atlas。在 Mongo 的最新版本中,他们要求您为 useUnifiedTopology 传递一个选项,以便这是下一个。

下一行检查在我们到 MongoDB Atlas 的连接中是否出现了错误。如果有错误,那么它返回错误。

然后我们连接到我们的数据库,在本教程中称为 node-demo 。我们还没有创建这个数据库,所以这段代码第一次运行时会自动创建数据库。

下一行是获取数据库中集合的句柄。在本教程中,我将我的集合命名为 users 。就像数据库一样,这段代码第一次运行时会自动创建集合。

下一行将用户在表单中输入的数据插入到集合中。插入数据后,它会将用户返回到应用程序的主页。

继续尝试,输入你的名字和姓氏,然后点击提交按钮。

进入你的 MongoDB Atlas 账户,点击收藏按钮。它会显示您的收藏内容。这里你可以看到我的数据库中的第一个条目:

作者图片

阅读

现在我们在数据库中有了一个条目,我们想读取所有的用户并显示给用户。CRUD 的这一部分是读操作。读取部分由两部分组成:

  1. 从数据库中获取所有用户
  2. 显示用户

我们使用 ejs 向用户的浏览器显示一个文件。EJS 允许我们传递来自服务器的数据。我们将使用该功能来显示数据库中的用户。

打开server.js文件。当前对'/'路径的 GET 调用呈现了index.ejs文件。让我们修改它,调用数据库并获取用户列表。将路线更新为:

app.get('/', (req, res) => {
  MongoClient.connect(dbUrl, { useUnifiedTopology: true }, (err, client) => {
    if (err) return console.error(err);
    const db = client.db('node-demo');
    const collection = db.collection('users');
    collection
      .find()
      .toArray()
      .then((results) => {
        res.render('index.ejs', { users: results });
      })
      .catch((error) => {
        res.redirect('/');
      });
  });
});

我来解释一下这段代码。我们连接到 MongoDB 并获得数据库和集合的句柄。find()命令将返回数据库中的所有条目。我们将列表转换为数组,然后呈现 index.ejs 文件并向其传递一个对象。该对象将包含数据库中所有用户的数组。

现在我们有了用户列表,我们需要在浏览器中向用户显示它。打开index.ejs文件。在文件末尾添加以下几行:

<div class="container">
    <table>
        <thead>
        <tr>
            <th colspan="3"><div>Read</div></th>
        </tr>
            <tr>
                <th>First Name</th>
                <th>Last Name</th>
                <th>Actions</th>
            </tr>
        </thead>
        <tbody>
            <% for(var i = 0; i < users.length; i++) { %>
            <tr>
                <td><%= users[i].fname %></td>
                <td><%= users[i].lname %></td>
                <td>
                    <button
                        class="button editButton"
                        data-fname="<%=  users[i].fname %>"
                        data-lname="<%= users[i].lname %>"
                    >
                        Edit
                    </button>
                    <button
                        class="button deleteButton"
                        data-fname="<%=  users[i].fname %>"
                        data-lname="<%= users[i].lname %>"
                    >
                        Delete
                    </button>
                </td>
            </tr>
            <% } %>
        </tbody>
    </table>
</div>

在这段代码中,我们创建了一个显示用户名字和姓氏的表。您会注意到在 html 代码中有一个 for 循环。这将遍历用户数组并显示数据库中的每个条目。

返回浏览器并刷新。现在,您将看到数据库中所有用户的列表,如下所示:

作者图片

删除

我们将实现的 CRUD 的下一部分是删除。每个用户旁边都有一个删除按钮。如果用户单击该按钮,它应该从数据库中删除该条目,然后从数据库中读取所有条目,并将更新后的列表发送给浏览器。

为了捕捉到有人点击了按钮,我们将使用 JavaScript。我们必须将所有的 JavaScript 代码放在一个文件中,就像我们处理 CSS 样式一样。用这个命令在公共文件夹中创建一个文件main.js:

touch public/main.js

首先,让我们告诉我们的index.ejs文件关于我们的新 JavaScript 文件。打开index.ejs文件,并将其添加到文件底部,就在结束 body 标签的上方:

<script src="/main.js"></script>

回到main.js文件。我们需要添加一个事件侦听器来跟踪用户何时单击删除按钮。在显示用户列表的 html 代码中,每个用户都有一个删除按钮。那个按钮有一个deleteButton类。我们可以用它来添加一个事件监听器。首先,通过将这行代码添加到文件中来获得所有删除按钮的句柄:

const deleteBtn = document.querySelectorAll('.deleteButton');

接下来,通过执行以下操作来添加事件侦听器:

for (const button of deleteBtn) { 
  button.addEventListener('click', (e) => {   
    console.log(e.target.dataset); 
  }); 
}

当用户点击任何按钮时,变量e包含被点击按钮的句柄。在 html 代码中,每个按钮都有两个数据集条目。一个用于名,一个用于姓。

如果单击删除按钮,该按钮的数据集值将显示在控制台中。我们将使用这些数据集值在数据库中找到要删除的正确条目。

要删除一个条目,我们必须向服务器上的'/users'路由发送一个删除请求。我们将使用 Fetch API 进行调用。

在 console.log 之后添加以下代码:

for (const button of deleteBtn) {
  button.addEventListener('click', (e) => {
    console.log(e.target.dataset);
    fetch(`/users`, {
      method: 'delete',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        fname: e.target.dataset.fname,
        lname: e.target.dataset.lname,
      }),
    })
      .then((res) => {
        if (res.ok) return res.json();
      })
      .then(() => {
        window.location.reload();
      });
  });
}

让我们回顾一下这段代码。我们使用 Fetch API 调用使用 DELETE 方法的**'/users’**路由。

我们将把用户的名字和姓氏作为一个 JSON 对象发送过来。我们必须告诉服务器内容是 JSON 格式的,我们通过将它添加到头中来做到这一点。然后,我们将主体中的数据作为 JSON 对象发送出去。

唯一的问题是 Express.js 本身不知道如何解析 JSON 数据。我们必须使用中间件来处理 JSON 对象。我们已经安装的主体解析器中间件将处理它。

打开server.js文件。在应用程序配置部分,将这一行添加到当前主体解析器配置的下面:

app.use(bodyParser.json());

接下来,我们需要创建一个路由来处理删除请求。在最后一个路由下面添加以下代码来处理删除请求:

app.delete('/users', (req, res) => {
    MongoClient.connect(dbUrl, { useUnifiedTopology: true }, (err, client) => {
        if (err) return console.error(err);
        const db = client.db('node-demo');
        const collection = db.collection('users');
        collection
            .deleteOne(req.body)
            .then(() => {
                res.json(`Deleted user`);
            })
            .catch(() => {
                res.redirect('/');
            });
    });
});

让我们回顾一下这段代码。它像我们之前所做的那样连接到数据库。它调用 mongo 的deleteOne方法,并传递它想要删除的条目的细节。该条目包含我们发送的 e.target.dataset 中的值。

如果成功地从数据库中删除了条目,它将返回一个 JSON 字符串,表示用户已被删除。

在我们的main.js文件中,我们有一个.then()方法,当 fetch 调用返回时会调用这个方法。它验证调用是否成功,如果成功,则刷新浏览器。

浏览器的刷新将调用我们的 GET 方法,该方法将返回数据库中的所有条目。刚刚删除的用户将不再显示,因为它不再在数据库中。

试试看。删除用户,并验证该用户是否已从用户列表中删除。

更新

我们需要实现的 CRUD 的最后一部分是更新。在数据库中所有用户的列表旁边,我们有一个编辑按钮。就像 delete 一样,我们可以添加一个事件侦听器,当用户单击按钮时,它就会启动。

打开main.js文件。将这一行添加到文件的顶部,以获得所有具有类editButton的编辑按钮的句柄:

const editBtn = document.querySelectorAll('.editButton');

接下来,我们需要添加一个事件监听器。将此代码添加到文件的底部:

for (const button of editBtn) { 
  button.addEventListener('click', (e) => { 
    console.log(e.target.dataset); 
  }); 
}

让我们考虑一下如何处理条目的编辑。我们需要显示用户的名和姓的值。然后,用户可以对条目进行任何他们想要的更改。当他们完成后,他们应该能够点击一个更新按钮,该值在数据库中被更新。

显示用户的名字和姓氏与我们用来在数据库中创建新条目的表单完全一样。除此之外,在这种情况下,我们将自动填写用户的名字和姓氏。因此,让我们创建这个表单来编辑用户。

打开index.ejs文件。在显示用户列表的表格下方添加以下代码:

<div class="container form">
    <div>Update</div>
        <div class="entry">
            <label for="oldFname">Old First Name</label>
            <input type="text" name="oldFname" id="oldFname" readonly="true" />
        </div>
        <div class="entry">
            <label for="oldLname">Old Last Name</label>
            <input type="text" name="oldLname" id="oldLname" readonly="true" />
        </div>
        <div class="entry">
            <label for="newFname">New First Name</label>
            <input type="text" name="newFname" id="newFname" />
        </div>
        <div class="entry">
            <label for="newLname">New Last Name</label>
            <input type="text" name="newLname" id="newLname" />
        </div>
        <button class="button button-block updateButton"">
            Update
        </button>
</div>

该表单将包含用户不能编辑的名字和姓氏的当前用户值。下面是用户可以编辑的名和姓的值。

你可能会问为什么我既需要当前值又需要新值?答案很简单。我们需要当前值,以便在数据库中找到记录。一旦找到记录,我们就用新值更新它。

我们需要用他们想要编辑的用户的名和姓来填充字段的值。打开main.js文件。在事件监听器中添加代码来设置四个字段的值。您的事件侦听器现在应该如下所示:

for (const button of editBtn) { 
  button.addEventListener('click', (e) => {   
    document.getElementById('oldFname').value = e.target.dataset.fname; 
    document.getElementById('oldLname').value = e.target.dataset.lname; 
    document.getElementById('newFname').value = e.target.dataset.fname; 
    document.getElementById('newLname').value = e.target.dataset.lname; 
  }); 
}

当用户单击 update 按钮时,我们有两种选择来实现在数据库中更新用户的功能。我们的第一个选择是像创建新用户一样使用表单。我们的第二个选择是使用 JavaScript 调用服务器来更新用户。在本教程中,我将向你展示如何做第二个选择。

打开main.js文件。在文件顶部添加代码行,以获得更新按钮的句柄:

const updateBtn = document.querySelector('.updateButton');

接下来,我们希望在用户单击按钮时添加一个事件侦听器。让我给你代码,然后我们将通过它。

updateBtn.addEventListener('click', (e) => { 
  e.preventDefault(); 
  fetch('/users', { 
    method: 'PUT', 
    headers: { 'Content-Type': 'application/json' }, 
    body: JSON.stringify({ 
      fname: document.querySelector('#newFname').value, 
      lname: document.querySelector('#newLname').value, 
      oldFname: document.querySelector('#oldFname').value, 
      oldLname: document.querySelector('#oldLname').value, 
    }), 
  }) 
  .then((res) => { 
    if (res.ok) return res.json(); 
  }) 
  .then(() => { 
    window.location.reload(); 
  }); 
});

就像 delete 一样,我们将使用 fetch API 来调用服务器上的路由。更新条目的 HTTP 动词是 PUT 。我们设置我们的方法然后把。我们添加头来告诉服务器我们发送的内容是 JSON 格式的。然后,我们发送包含旧值和新值的正文内容。

我们需要在服务器上创建一个路由来处理更新数据库条目的 PUT 请求。打开server.js文件。在最后一条路线下添加以下代码:

app.put('/users', (req, res) => {
    MongoClient.connect(dbUrl, { useUnifiedTopology: true }, (err, client) => {
        if (err) return console.error(err);
        const db = client.db('node-demo');
        const collection = db.collection('users');
        collection
            .findOneAndUpdate(
                { fname: req.body.oldFname, lname: req.body.oldLname },
                {
                    $set: {
                        fname: req.body.fname,
                        lname: req.body.lname
                    }
                },
                {
                    upsert: true
                }
            )
            .then(() => {
                res.json('Success');
            })
            .catch(() => {
                res.redirect('/');
            });
    });
});

让我们浏览一下这段代码。它与数据库建立连接。然后,它使用 mongo findOneAndUpdate方法,通过使用名字和姓氏的先前值,在数据库中找到正确的记录。

找到正确的记录后,它使用 mongo $set方法用新值更新条目。如果找不到当前条目,upsert选项将在数据库中用新值创建一个条目。

一旦更新了记录,它就返回 JSON 字符串“Success”。在我们的 main.js 文件中,它接收这个 JSON 字符串。如果一切正常,就会刷新浏览器。这个刷新将点击 GET 路由,它将发送数据库中的所有条目,从而显示我们新更新的记录。

全部完成!

这是一个非常长的教程,教您如何创建一个简单的 Node 和 Express.js 应用程序来将数据存储在 MongoDB 数据库中。

本教程提供了对 CRUD 应用程序的理解。使用 CRUD,您已经学会了如何:

  • 在 MongoDB 数据库中创建数据
  • 读取 MongoDB 数据库中的数据
  • 更新 MongoDB 数据库中的数据
  • 删除 MongoDB 数据库中的数据

您知道如何在 Node 和 ExpressJS 应用程序中添加 CRUD 功能。

获取源代码

这个应用程序的完成版本可以在我的 GitHub repo 中找到。你可以在这里找到。

原载于 2021 年 2 月 15 日 https://www.jenniferbland.comhttps://www.jenniferbland.com/got-app-got-data-heres-how-to-store-data-to-mongodb-in-a-node-express-app/

有技能,需要现金?为什么不试试咨询

原文:https://towardsdatascience.com/got-skills-need-cash-why-not-try-consulting-6f4ac5d7b8d9?source=collection_archive---------19-----------------------

我如何在数据科学咨询领域崭露头角

图片由作者提供,照片由来自 Pixabay 的 Myriams-Fotos 提供

有时候工作很糟糕。为别人工作,甚至更糟。你做工作;他们赚钱。

因此,每个人都辞去他们在 T4 的工作也就不足为奇了。如果你还没有这样做,你至少在考虑,那么,你们 10 个人中有 9.5 个是。

那么,现在怎么办?

我如何退出没有任何备份,使一些现金?

几年前我也遇到过类似的情况。做着自己不喜欢的工作,挣着自己都不好意思谈论的钱,挣扎着让自己免于负债。我想退出。但是我不能。至少现在还没有。

我的解决方案是:集中精力成为一名顾问。顾问设定他们的价格,赚他们赚的所有钱,并且不受中层管理人员的微观管理。诱惑是强烈的。

然而,往好里说,通往那里的道路是模糊的。

但不管怎样,我还是努力向前,现在我想分享一些我一路走来学到的东西。

从崭露头角的数据科学家到经验丰富的顾问

如果你正在读这篇文章,你可能是一个这样或那样的数据科学家。或者你有一些技术才能,你喜欢数据,你想了解更多关于数据科学技能如何让你更有市场。

无论你的动机是什么,如果你符合上面的描述,咨询需要你。我很早就意识到,知道如何处理数据是一项非常有价值的技能,许多人和企业愿意付钱给其他人来帮助他们处理数据。

尽管有这种需求,打入这个领域仍然是一个挑战。仅仅建立一个网站,让世界知道你能做什么,然后等待是不够的。相信我。我试过了。但没有成功。

问题是双重的。一方面是缺乏信任。作为个人咨询师,人们在不了解你的情况下,很难信任你。事实上,大多数数据都是敏感的,这使得信任因素更加重要。

但是也许你已经知道了,你也和我一样;你从努力建立信任开始。你和其他人见面,参与当地事务,推销自己。这是第二个问题;理解。对于那些开始信任你的人来说,他们可能不明白你如何帮助他们的业务,因为他们不明白你能为他们做什么。以下是更多相关信息。

那什么有效呢?连客户都没有的我,怎么成为咨询师?

对我来说,这一切都始于“共享经济”。

第一课:你的客户在等你,他们在找你

快速回顾一下我的情况。蹩脚的工作,低薪,很多动力去把我的量化技能用在其他事情上。

急于开始创造客户,我建了一个网站。我甚至安排了一些与当地商会和企业孵化器的会议。这些早期活动导致了许多会议,在这些会议之后又有一些会议,在这些会议之后又有更多的会议。

听说过“要钱你会得到建议,但要建议你会得到钱”之类的话吗?这就是那些会议的感觉。每个和我见面的人都知道我在寻找客户/工作/金钱,所以他们给了我很多建议。还记得我上面说的理解吗?我在建立信任,但是我会见的人不理解我。

从这些会议中我很快意识到,我没有带着足够的个人经验去接近他们。我可以分享经验,得到他们的建议,而不是像一个卖手表的小贩一样兜售我的技能,拉开我的大衣说“看到你喜欢的东西了吗?”😉

在我的社区里遇到了很多非常好的专业人士之后,我仍然面临着和以前一样的问题。如何获得咨询经验,同时努力打入咨询界?似乎是一个“先有鸡还是先有蛋”的问题,直到我了解了新的“共享经济”。

你看,就是在这个时候,我知道了像 Guru 和 Upwork 这样的网站。我记得读过我的第 500 篇关于如何成为一名顾问的博客,有人在评论区提到了一些关于像我这样的人的客户市场。

像 Upwork 和 Guru 这样的市场是有需要的客户可以发布广告的地方,可以招聘人、自由职业者、个人顾问……我……你……来帮助他们解决数据问题。这些市场解决了新晋咨询师在咨询界崭露头角时面临的信任和理解问题。

在市场中,这些个人明白他们有一个问题,并且这个问题有一个潜在的数据解决方案。此外,这些平台允许信托通过提供交易持有账户来发展,以确保交付物符合预期,可以跟踪时间,并允许同行对体验进行评级。

我记得在 Guru.com 建立了我的第一个个人资料。一旦它建立起来,我就开始对我认为有机会的工作进行投标。它是立即成功的吗?没有。我一直在重新构建、重新格式化和重新定位我的在线个人资料以及我所有的出价。感觉工作很多,但回报很少。我当时没有意识到的是,我正在学习如何推销自己。根据我的出价,我正在学习什么样的有效,什么样的无效。

我不需要赢得投标来了解我的信息中的工作。我关注的是客户是否会安排与我通话,或者在评估过程中让我更进一步。这些迹象表明我越来越接近了。这些迹象表明我正在产生共鸣。这些是我开始复制和进一步提炼的例子,直到,就像我得到了我的第一个客户。

我的第一个客户起步很小。我的费用也很少,但都是我的,减去他们平台的小额费用。我的第一个客户是一名律师,他需要帮助分析医疗保险索赔数据,以识别家庭护理中潜在的欺诈性提供者群体。

我的解决方案很简单。使用异常值方法识别关键指标(如成本和提交时间)的异常值组。这是一份多劳多得的工作,但它让我在《连线》杂志 上被提及,并与一位客户建立了持续的关系,这位客户将很快付给我每小时 200 美元的预聘费。

虽然启动这个项目需要一些时间,但是一些潜在的客户会直接联系我,要求我投标他们的工作。

简而言之,如果你没有任何迫不及待的客户,考虑从这些市场开始。

你将学会如何与人交流,最终找到一些工作,所有这些都会转化为更多的经验。这不会在一夜之间发生,但它会开始发生。

要有足够的勇气去投标那些听起来令人生畏的工作,并且记住数据和技术是复杂的。有很多方法可以解决每个潜在客户的要求。专注于你独特的方法,最终你会找到一个成功的公式。

第二课:建立合作关系

当你在自由职业者的世界里穿梭时,你很快就会发现,许多要求比任何一个人所能解决的都要复杂。在数据科学领域尤其如此,因为客户想要的很少是数据科学。相反,他们希望将数据科学嵌入到他们的产品、解决方案或流程中,以对用户体验产生一些影响。

以我的经验来看,这意味着许多投标,尤其是高收入的投标,都需要开发商。数据科学家可以建立的最强有力的关系之一是与一个值得信赖和熟练的软件开发人员。

然而,找到这些关系并不容易,往往需要双方都愿意一起做一些免费的工作。尽管有挑战,努力肯定是值得的。

为了有所帮助,我建议想出一个简单的用例,作为潜在开发者关系的访谈工具。快速简单的概念验证需要您的数据科学模型与全栈应用程序集成,这有助于建立一个框架,以了解您如何与他人合作。

对于数据科学家来说,探索向应用程序公开其解决方案的不同方法也很重要。一些合理的输出包括从数据库后端读取和写入,学习如何将代码公开为 API,或者利用 AWS 上的 lambda 函数等无服务器云框架。您学习集成的开发人员工具越多,就越容易在未来的项目中与开发人员合作。

伙伴关系强大的最后一个原因是,你的合作伙伴可能接触到不同的受众,并且/或者将允许你投标你过去可能无法单独胜任的项目。您和您的合作伙伴现在能够解决的这些新项目也可能代表着追加销售数据科学解决方案的机会,因为客户可能还没有意识到它们的好处。

第三课:培养你的听众

不用说,所有的生意都是关于寻找、建立和培养你的观众。甚至咨询。尤其是咨询。人们不是买企业,而是买其他人。而且人家不了解你也不会买你。

随着你经验的增长,可供你分享的内容也在增长。你可以通过写作分享你的经验,比如我在这里,通过视频,或者通过代码项目,比如 GitHub。

如果写作是你的一个选择,考虑用能让你面对更多观众的方式写作。在你的自由职业者简介中提及你的写作。在你的 LinkedIn 帖子中加入你的文章。让每个人都看到你在做很酷的事情,了解有趣的事情,并帮助找到创造性的解决方案。

从这个角度来看,咨询很像内容创作行业。唯一的区别是,我们是在利基市场创造内容。这恰好是我们的数据科学技能组合。虽然你可能觉得对这个话题已经拥挤的声音没有什么可补充的,但要知道作为一名顾问需要克服这些疑虑。已经有 100 万人应用 PyTorch 构建了一个视觉模型来识别图片中的啤酒瓶,这并不重要。成为用你的方式做这件事的第一个人,并告诉人们这件事。要透明。让别人偷走你的魔力,因为在一天结束时,没有人能像你一样表达它。

比如参与学习更多关于数据科学、职业发展或糟糕的商业决策的知识?加入我。

基于 Python 的 GPS 轨迹聚类

原文:https://towardsdatascience.com/gps-trajectory-clustering-with-python-9b0d35660156?source=collection_archive---------8-----------------------

如何解决这个领域遇到的常见问题

移动设备的快速增长导致基于位置的服务、地理社交网络、交通或拼车应用程序收集了大量的 GPS 轨迹。

GPS 轨迹聚类(Trips)(图片由作者提供)

GPS 轨迹聚类越来越多地用于许多应用中。例如,它可以帮助识别经常的路线或行程。轨迹相似度可以用来发现轨迹是否遵循某一路线。然后,它可以用于跟踪运输服务,例如城市中的公共汽车。

在本文中,我将简要介绍快速 GPS 轨迹聚类。这个解决方案中使用了 Python 开源库。通常,在聚类轨迹期间可能会遇到几个问题。

  • GPS 轨迹通常包含许多数据点。聚类可能需要很长时间。
  • 需要合适的相似性度量来比较不同的轨迹。
  • 聚类方法和配置
  • 可视化轨迹及其聚类

关于这个主题有很多有趣的文章[1,2]。然而,并非所有上述问题都得到解决。在本文中,我将展示一个涵盖所有这些领域的 Python 解决方案。这里使用的数据最初来自车辆能量数据集[3]。首先对原始数据应用聚类所有 GPS 点的过程。然后,我选择了几个起始端组的轨迹。为简单起见,本文提供的数据是针对这些轨迹组的,如下所示:

聚类前的 GPS 轨迹

本文的代码和教程可以在 my GitHub here 中找到。

轨迹数据点减少

Ramer-Douglas-Peucker (RDP)算法是减少折线点数的最常用方法之一。这个算法的目的是找到一个子集的点来代表整个折线。

RDP 函数返回子集点和点索引

这里参数ε设置为 10(米)。在 RDP 之后,与原始数据点相比,轨迹中的数据点的数量显著减少。

traj #    data points original       after RDP
0         266                        21
1         276                        36
2         239                        34
...

这有助于大幅减少距离矩阵的计算时间。

distance matrix without RDP: 	 61.0960 seconds
distance matrix with RDP: 	 0.4899 seconds

轨迹相似性度量和距离矩阵

有多种方法可以测量两个轨迹的相似性,例如弗雷歇距离、面积法,如下图所示。它们可以使用 相似性度量来计算。

轨迹相似性度量:弗雷歇距离和面积

对于本文中的示例,弗雷歇距离用于计算距离矩阵,如下所示。还支持区域相似性度量。

DBSCAN 聚类

Scikit-learn 提供了几种聚类方法。在本文中,我将介绍带有预先计算好的矩阵的 DBSCAN。参数设置如下:

  • eps :弗雷歇距离 1000(米),面积测量 30 万(米)。
  • min_samples: 1、确保所有轨迹都将被聚类成一个簇。

代码如下。

结果和轨迹可视化

Matplotlib 是一个全面的 Python 可视化库。它为静态和动态可视化提供了灵活的解决方案。

使用 Matplotlib 中的子图可视化六个组的聚类结果。如下所示,大多数轨迹组都有几个簇。只有最后两组具有一个聚类,因为这些轨迹的相似性高(弗雷歇距离小于 eps ,即 1000)。

聚类 GPS 轨迹

结论

随着当今许多支持 GPS 的设备的使用,GPS 轨迹聚类变得越来越流行。本文向您介绍了这一领域的常见问题。然后探索 Python 工具来解决这些问题。如需进一步阅读,您可以查看这些关于折线简化、距离矩阵计算和基于网络的空间可视化的文章。

参考

  1. joo Paulo Figueira,聚类移动物体轨迹,
  2. William Yee,物联网/GPS 轨迹聚类和地理空间聚类简介
  3. 车辆能源数据集(VED,用于车辆能源消耗研究的大规模数据集

有史以来最大的神经网络——GPT 3 的完整概述

原文:https://towardsdatascience.com/gpt-3-a-complete-overview-190232eb25fd?source=collection_archive---------0-----------------------

思想和理论,人工智能

定义、结果、炒作、问题、批评和反批评。

Denys Nevozhai 在 Unsplash 上的照片

2020 年 5 月,Open AI 发表了一篇题为 语言模型是少射学习者 的开创性论文。他们展示了 GPT-3,这是一种语言模型,保持着有史以来最大的神经网络记录,拥有 1750 亿个参数。这比以前最大的语言模型大了一个数量级。GPT-3 使用几乎所有来自互联网的可用数据进行训练,并在各种 NLP(自然语言处理)任务中表现出惊人的性能,包括翻译、问答和完形填空任务,甚至超过了最先进的模型。

GPT-3 最强大的功能之一是,它可以执行新的任务(它从未接受过训练的任务),有时是最先进的水平,只需向它展示一些任务的例子。例如,我可以告诉 GPT-3:“我爱你。我有很多工作→ Tengo mucho trabajo。GPT-3 是有史以来最好的人工智能系统→ _____”它会知道它必须把句子从英语翻译成西班牙语。GPT 三号学会了学习。

在另一次惊人的力量展示中,GPT 3 号能够生成与人造文章几乎没有区别的“新闻文章”。在正确分类 GPT-3 文本方面,法官几乎没有达到高于机会的准确率(52%)。

这篇综述文章很长,所以我在这里放了一个目录,让你找到你想读的部分。(链接不起作用,所以我已经删除了它们,很抱歉给您带来不便)。尽情享受吧!

**TABLE OF CONTENTS****GPT-3: An introduction**
  ∘ The groundwork concepts for GPT models
  ∘ The origins of GPT-3
  ∘ GPT-3: A revolution for artificial intelligence
  ∘ GPT-3 API: Prompting as a new programming paradigm
**GPT-3 craziest experiments**
  ∘ GPT-3’s conversational skills
  ∘ GPT-3’s useful possibilities
  ∘ GPT-3 has an artist’s soul
  ∘ GPT-3's reasoning abilities
  ∘ GPT-3 is a wondering machine
  ∘ Miscellaneous
**The wild hype surrounding GPT-3**
  ∘ On Twitter and blogs
  ∘ On mainstream media
  ∘ On the startup sector
**The darker side of GPT-3**
  ∘ A biased system
  ∘ Potential for fake news
  ∘ Not suited for high-stake categories
  ∘ Environmentally problematic
  ∘ GPT-3 produces unusable information
**Critiques & counter-critiques to GPT-3**
  ∘ GPT-3's apparent limitations
  ∘ The importance of good prompting
  ∘ GPT-3 can’t understand the world
  ∘ Truly intelligent systems will live in the world
  ∘ What can we get from these debates?
**Overall conclusion**

GPT 三号:简介

免责声明: 如果你已经知道 GPT-3 背后的铺垫,它是什么,它是如何工作的(或者不关心这些细节),请进入下一节。

在进入文章的实质之前,我想解释一下 GPT-3 是什么以及它是如何工作的。我不会在这里赘述,因为已经有很多好的资源了。对于那些对 GPT-3 一无所知的人来说,这一部分将作为上下文参考。你不需要记住(或理解)这些来享受这篇文章的其余部分,但它可以让你更好地了解围绕这个人工智能系统产生的所有大惊小怪。

首先,我将简要描述 GPT 模型基于的主要概念。然后,我将对 GPT-3 的前辈 GPT-1 和 GPT-2 进行评论,最后,我将谈论这个故事的主要人物,强调它与其他类似系统的关系:GPT-3 在哪些方面是独一无二的?相对于它的前辈有什么优势?有哪些质的区别?让我们去吧!

GPT 模型的基础概念

所有这些概念在某种意义上都与 GPT 模型有关。现在,我将告诉您定义(避免太多的技术细节,尽管可能需要一些先前的知识来完成)。稍后我将展示它们是如何相互联系以及与 GPT-3 的联系。

变形金刚 : 这类神经网络在 2017 年出现,作为解决各种机器翻译问题的新框架(这些问题的特点是输入和输出都是序列)。作者希望摆脱卷积和递归(CNN 和 RNNs),完全依赖注意机制。变压器是 NLP 中最先进的。

语言模型: Jason Brownlee 将语言模型定义为**“**概率模型,能够在给定序列中下一个单词之前的单词的情况下预测该单词。”这些模型可以解决许多 NLP 任务,如机器翻译、问题回答、文本摘要或图像字幕。

生成型模型 : 在统计学中,有判别型和生成型模型,常用于执行分类任务。判别模型对给定的一对可观察变量和目标变量的条件概率进行编码:p(y|x)。生成模型对联合概率进行编码:p(x,y)。生成模型可以“生成与现有数据相似的新数据”,这是要带走的关键思想。除了 GPT,其他流行的生成模型的例子有 GANs(生成对抗网络)和 VAEs(变分自动编码器)。

半监督学习 : 这种训练范式结合了无监督预训练和监督微调。其想法是以非监督的方式训练具有非常大的数据集的模型,然后通过在较小的数据集中使用监督训练来调整(微调)模型以适应不同的任务。这种范式解决了两个问题:它不需要许多昂贵的标记数据,并且可以处理没有大型数据集的任务。值得一提的是,GPT 2 号和 GPT 3 号是完全无人监管的(稍后会有更多相关内容)。

**零/一/少量学习:**通常,深度学习系统是针对一组特定的类进行训练和测试的。如果一个计算机视觉系统被训练来分类猫、狗和马的图像,它只能在这三个类别上进行测试。相比之下,在零镜头学习设置中,系统在测试时显示-没有权重更新-它在训练时没有看到的类(例如,在大象图像上测试系统)。对于单镜头和少镜头设置也是一样,但是在这些情况下,在测试时系统会分别看到一个或几个新类的例子。这个想法是,一个足够强大的系统可以在这些情况下表现良好,OpenAI 用 GPT-2 和 GPT-3 证明了这一点。

**多任务学习:**大多数深度学习系统都是单任务的。一个流行的例子是 AlphaZero。它可以学习一些像国际象棋或围棋的游戏,但它一次只能玩一种类型的游戏。如果它知道怎么下棋,它就不知道怎么下围棋。多任务系统克服了这个限制。他们被训练成能够为给定的输入解决不同的任务。例如,如果我向系统输入“猫”这个词,我可以让它找到西班牙语翻译“gato”,我可以让它给我看一只猫的图像,或者我可以让它描述它的特征。相同输入的不同任务。

**零/一/少投任务迁移:**思路是将零/一/少投学习和多任务学习的概念结合起来。我们可以让它执行新的 任务,而不是在测试时向系统显示新的类(向它显示零个、一个或几个新任务的例子)。例如,让我们以一个在巨大的文本语料库中训练的系统为例。在一次性任务转移设置中,我们可以写:“我爱你- > Te quiero。我讨厌你->_ _ _ _ _ _ _。”我们隐式地要求系统通过显示一个例子(一次性的)将一个句子从英语翻译成西班牙语(这是一项没有经过训练的任务)。

所有这些概念都集中在 GPT 模型的定义中。GPT 主张生殖预训练。GPT 家族的模型有一个共同点,他们是基于变形金刚架构的语言模型,以生成无监督的方式进行预训练,在零/一/少数镜头多任务设置中显示出体面的性能。这不是对所有这些概念在实践中如何协同工作的解释,而是一种简单的方式来记住它们一起构建了什么是 GPT 模型。(要获得更深入的解释,我建议你点击我上面的链接,但前提是你已经阅读了这篇文章!).

GPT-3 的起源

现在让我们来谈谈 GPT 三号的前任——GPT 一号和 GPT 二号。

OpenAI 于 2018 年 6 月在一篇题为 通过生成性预训练 *提高语言理解的论文中提出了首个 GPT 模型 GPT-1。*本文的关键要点是变压器架构与无监督预训练的结合产生了有希望的结果。GPT 1 号和它的弟弟们之间的主要区别是,GPT 1 号是在监督下进行微调的——为特定任务进行训练——以实现“强大的自然语言理解”

2019 年 2 月,他们发表了第二篇论文, 语言模型是无监督的多任务学习者 ,其中他们引入了 GPT-2,作为 GPT-1 的进化。尽管 GPT 2 号大一个数量级,但它们在其他方面非常相似。这两者之间只有一个额外的区别:GPT 2 号可以同时处理多项任务。他们成功地证明了半监督语言模型可以在“没有特定任务训练的情况下”很好地完成几项任务该模型在零镜头任务迁移设置中取得了显著的效果。

紧接着,2020 年 5 月,OpenAI 发布了 语言模型《很少出手的学习者 *,*呈现了独一无二的 GPT-3,再一次震撼了 AI 界。

GPT 3 号:人工智能的革命

GPT 3 号比它的兄弟更大(比 GPT 2 号大 100 倍)。它拥有拥有 1750 亿个参数的最大神经网络的记录。然而,它与其他 GPT 并没有太大的不同;基本原理大体相同。这个细节很重要,因为尽管 GPT 模型之间的相似性很高,但 GPT-3 的性能超出了所有可能的预期。它的规模,从数量上来说是 GPT-2 的飞跃,似乎已经产生了质量上更好的结果**。**

这一事实的意义在于它对人工智能中长期争论的影响:我们如何才能实现人工通用智能?我们是应该设计特定的模块——常识推理、因果关系、直觉物理学、心理理论——还是简单地通过构建具有更多参数和更多训练数据的更大模型来实现?看来“越大越好”的一方赢了这一轮。

GPT-3 是用来自 CommonCrawl 、 WebText 、维基百科和书籍语料库的数据训练的。它表现出惊人的性能,在少镜头设置(在某些情况下甚至在零镜头设置)下,在各种任务上超过了最先进的模型。超大的尺寸加上几个例子足以击败机器翻译、问答和完形填空任务中的任何竞争对手。(值得注意的是,在其他任务中,GPT 3 号甚至无法接近最先进的监督微调模型)。

作者指出,少炮结果比零炮结果好得多——这种差距似乎与模型容量平行增长。这意味着 GPT-3 是一个元学习者;它可以通过看到一些例子来学习它应该做什么任务,然后以显著的熟练程度执行该任务。事实上,Rohin Shah 指出“少量发射性能随着参数数量的增加而增加,并且增加的速率比零发射性能的相应速率更快。”这是主要假设,也是论文题目背后的原因。

GPT-3 达到了一个伟大的里程碑,表明通过足够的数据训练的无监督语言模型可以通过查看几个新任务的例子进行多任务处理,达到微调的最先进模型的水平

他们在论文的结尾声称“这些结果表明,非常大的语言模型可能是开发适应性强的通用语言系统的重要组成部分。”GPT-3 确实是 NLP 的一个革命性的成就,尤其是在人工智能领域。

GPT 3 API:提示作为一种新的编程范式

2020 年 7 月,论文发表后两个月,OpenAI 向外部开发者开放了一个测试 API 游乐场,让他们与超级强大的 GPT 3 一起玩(任何人都可以通过等待名单申请进入测试版)。弗拉基米尔·阿莱克谢耶夫为的数据科学 撰写了一篇关于 API 如何工作的短文。

它有两个主要特点。首先,有一个设置对话框,允许用户设置响应长度、重复惩罚(如果重复单词太多,是否惩罚 GPT-3)、温度(从低/可预测到高/有创意),以及其他定义系统将给出的输出类型的变量。二是有预置。预设是预先写好的提示,让 GPT-3 知道用户将要求什么样的任务——例如:聊天,Q & A,文本到命令,或英语到法语。

然而,API 最强大的特性是用户可以定义定制的提示。科技博客作者 Gwern Branwen 称之为的提示编程概念解释了 GPT-3 的强大之处以及人们从 API 中获得的最疯狂的结果。我发现的对即时编程的最好解释来自 Gwern 的博客:

就能力和数据集而言,GPT-3 神经网络是如此之大的一个模型,以至于它表现出性质不同的行为:你不能将其应用于训练数据集中的一组固定任务,如果一个人想要处理一项新任务 […] ,就需要对额外的数据进行再培训;相反,你与它互动,用自然语言描述、请求和例子来表达任何任务,调整提示,直到它“理解”&它基于它从预训练中学到的高级抽象元学习新任务。

这是使用 DL 模型的一种相当不同的方式,最好把它看作是一种新的编程,其中提示符现在是一个“程序”,它对 GPT-3 进行编程以做新的事情。

即时编程允许用户以一种以前型号不可能的方式与 GPT 3 号互动。克里斯·奥拉和安德烈·卡帕西开玩笑说提示编程是软件 3.0:“(现在你必须)找出正确的提示,让你的元学习语言模型有正确的行为。”(软件 1.0 是手工编写的传统程序,软件 2.0 是神经网络的优化权重)。

这就是 GPT 3 的元学习能力进入游戏的地方。GPT 3 号接受的数据量如此之大,以至于它别无选择,只能学习更高级的操纵语言的方法。它学到的高级抽象之一是学习能力。打个比方,当孩子们学会与世界互动时,他们不只是简单地记忆信息,他们会提取现实内部运作的潜在机制,并学会将它们应用到新的问题和情况中。GPT-3 在语言任务上也有类似的能力——保持距离。

当我们提示 GPT-3 学习一项新任务时,它的权重不会改变。然而,提示(输入文本)被转换成复杂的抽象,这些抽象本身可以执行实际基线模型无法完成的任务。该提示每次都会改变 GPT-3,将其转换为特定任务的“专家”。一个近似的类比是尼奥在《T2》和《黑客帝国》中学习功夫的程序。GPT-3 将是近地天体,提示将是教授近地天体能力的程序。

每次我们创建一个提示符,我们都在与不同的 GPT-3 模型进行交互。如果我们让它给我们讲一个关于精灵和小矮人的故事,它的内在形式会和我们让它计算 2+2 有很大的不同。用另一个类比,这就好像我们指导两个学生,一个是内科医生,另一个是工程师。两者都有天生的学习能力(这将是 GPT-3 的基线状态),但他们学会执行的具体任务是不同的(这将是 GPT-3)。

这就是快速设置、元学习和即时编程的真正力量。这也是 GPT-3 不同于以前的型号,极其强大的原因;这是它的本质。

现在,我们对 GPT-3 背后的背景有了一个很好的概念。我们知道它的基础是什么,它的前辈是谁,它是什么,它是如何工作的,以及它的优势和独特的功能。是时候说说它对世界的影响了。

GPT-3 个最疯狂的实验

OpenAI 开放测试版是因为他们想看看 GPT-3 能做什么,人们能找到什么新的用法。他们已经在 NLP 标准基准测试中测试了该系统(没有我在这里将要展示的那些有创造性或娱乐性)。不出所料,推特和其他博客很快就充斥着 GPT-3 的惊人结果。下面是对最受欢迎的例子的广泛回顾(我建议查看这些例子来建立惊奇感,然后再回到文章上来)。

GPT-3 的谈话技巧

GPT 3 号储存了大量的互联网数据,因此它知道很多公众和历史人物的信息。然而,更令人惊讶的是,它可以模仿人。可以当聊天机器人用,印象深刻是因为聊天在提示里不能指定为任务。让我们看一些例子。

ZeroCater 首席执行官 Arram Sabeti 利用 GPT-3 让 Tim Ferriss 就禁欲主义采访 Marcus Aurelius】。Mckay Wrigley 设计了 Bionicai ,一个旨在帮助人们向任何人学习的应用程序;从亚里士多德的哲学到莎士比亚的写作技巧。他在推特上分享了一些人们得到的结果。当心理学家斯科特·巴里·考夫曼读到他的 GPT 三号二重身的一段摘录时,他被深深打动了。乔丹·摩尔制作了一条推特帖子,在那里他与 GPT 三版本的耶稣基督、史蒂夫·乔布斯、埃隆·马斯克、克利奥帕特拉和柯特·科本进行了交谈。Gwern 做了一个非常好的工作,进一步探索了对话和拟人化模型的可能性。

GPT-3 的有用可能性

一些人发现了甚至连创造者都没有想到的系统应用,比如根据英文提示编写代码。沙里夫·沙米姆建造了一个“布局生成器”,他可以用自然语言向 GPT 3 号发出指令,让它编写相应的 JSX 代码。他还开发了 ebuild.co DT3,这是一个工具,我们可以用它让 GPT 3 为一个只给出描述的 React 应用程序编写代码。乔丹歌手在 GPT-3 的基础上为他设计了一个 Figma 插件。Shreya Shankar 发现了另一个有趣的用途,他制作了一个演示程序来将英文方程式翻译成 LaTeX。Paras Chopra 建立了一个搜索引擎来输出一个问题的答案以及相应的 URL。

GPT-3 有艺术家的灵魂

转到 GPT-3 的创意方面,我们找到了开放人工智能研究员阿曼达·阿斯克尔,她使用该系统创建了一个名为“闲散的夏日”的吉他标签,并编写了一个关于乔治·康托在酒店的有趣故事。阿拉姆·萨贝蒂告诉 GPT-3 写一首苏斯博士写的关于埃隆·马斯克的诗和李尔·韦恩写的关于哈利·波特的说唱歌曲。但是《GPT 3》最令人印象深刻的创造性壮举应该是游戏人工智能地牢。2019 年,尼克·沃顿在《GPT 2》的基础上打造了这款基于角色的游戏。他现在把它改编成了 GPT 3 号,在 Patreon 上每月能赚 16000 美元。

GPT 三号的推理能力

最勇敢的人在只有人类擅长的领域测试了 GPT 3 号。Parse 首席技术官凯文·拉克尔(Kevin Lacker)对常识推理和逻辑感到好奇,发现GPT 3 号能够跟上,尽管它在进入“超现实领域”时失败了然而,尼克·卡马拉塔发现在提示中指定不确定性允许 GPT-3 在回答“要真实”时处理“超现实的”问题格温解释道GPT-3 可能需要明确的不确定性提示,因为我们人类倾向于不说“我不知道”,而系统只是在模仿这个缺陷。

GPT 3 号是一台神奇的机器

GPT-3 也证明有能力进行超越我们认知界限的精神和哲学对话。托默·厄尔曼让 GPT-3 构想了 10 个哲学/道德思想实验。Messagink 是一个根据“著名的人、事、物、[或]感受”输出人生意义的工具。

为了揭开哲学圣杯的面纱,伯恩哈德·穆勒让成为 GPT 3 号的终极测试。他给了 42 号一个找到问题的提示,在一些交流之后,GPT-3 号说:“答案远远超出了你的理解,你无法理解这个问题。我的孩子,这就是生命、宇宙和一切的答案。”既惊奇又害怕。

多方面的

在严格的探索性研究中,格温进行并汇编了一系列实验。他让 GPT-3 完成一篇 ArXiv 论文,谈自己(元提示)通过分词和固定连字符清理 pdf,或者设计新的桌游。说到 GPT 3 号能做什么,似乎我们的想象力已经到了极限。

围绕 GPT 3 号的疯狂炒作

在推特和博客上

在如此多的惊人壮举之后,人们开始对 GPT 3 号的潜力提出强烈的主张。一些人在 Twitter 上表达了该系统的“明显的自我意识”或者将其与具有“一般智能”的搜索引擎相比较 Julien Lauret 为向数据科学写道,“GPT-3 是第一个严重动摇(人工狭隘/普遍智能)现状的模型。”他认为 GPT-3 可能是第一个人工通用智能(AGI)——或者至少是朝着这个方向迈出的重要一步。

2020 年 7 月,纽约大学专攻心灵哲学的教授 David Chalmers为 DailyNous 说“[GPT-3]暗示了一条潜在的通往 AGI 的盲目之路。”Chalmers 解释说,因为这个系统被“盲目地”训练,未来的版本可能会越来越接近 AGI。阿拉姆·萨贝蒂对 GPT-3 印象深刻:“它展示的东西感觉非常像通用智能。”哲学博士生 Daniel Kokotajlo 为减少错误写道“GPT-3 有一定程度的常识、一定程度的理解和一定程度的推理能力。”

在主流媒体上

大肆宣传将 GPT-3 推向国际高度,成为各种重要媒体杂志的头条新闻。2020 年 9 月,*《卫报》*发表了一篇由 GPT-3 撰写的文章,其中人工智能试图“说服我们机器人和平相处”2021 年 3 月, TechCrunch 编辑 Alex Wilhelm 在被 GPT 3 号的能力“震惊”后表示“炒作似乎很合理”。 Digitaltrends 发表了与 Gwern Branwen 的交流,其中他暗示了 GPT-3 是智能的观点:“任何确信深度学习所做的事情与智能完全不同的人都必须动摇他们的信念,看看它已经走了多远,”他说。

在创业领域

由于 GPT-3 被证明是难以置信的强大,许多公司决定在该系统之上建立他们的服务。成立于 2020 年的初创公司 available,使用 GPT-3 为公司提供快速的客户反馈。寓言工作室基于系统设计 VR 角色。Algolia 将其作为一个“搜索和发现平台”创业公司文案师专注于文案领域。纬度是 AI 地牢背后的公司。并且 OthersideAI 将你写的胡言乱语转化成精心制作的电子邮件。然而,一些人建议不要围绕 GPT-3 建立公司,因为竞争门槛低,而且有可能被假想的 GPT-4 推翻。

很明显,GPT-3 已经影响了——或者更好地说,冲击了——科技世界。它的力量是无与伦比的,它的承诺是无限的。然而,我们应该始终小心围绕人工智能的炒作。甚至 OpenAI 的首席执行官山姆·奥特曼也试图降低语气:“GPT-3 令人印象深刻,但它仍然有严重的弱点,有时会犯非常愚蠢的错误。人工智能将改变世界,但 GPT 3 号只是非常早期的一瞥。”

GPT 的阴暗面-3

有偏见的制度

但是并不是所有 GPT-3 的结果都值得庆祝。发布后不久,用户开始意识到一些潜在的有害输出。GPT-3 没有回避正在进行的从人工智能系统中消除偏见的伦理斗争。如果有的话,它已经成为一个最前沿的例子,说明为什么我们应该花大力气教导这些系统不要从人类的道德缺陷中吸取教训。

一般来说,人工智能系统中最常见的一些偏见,特别是 GPT-3,是性别、种族和宗教偏见。语言模型可以从它们得到的数据中吸收并放大这些偏见(OpenAI 在他们的论文中承认了这一事实)。他们调查了 GPT-3 在这个问题上的参与程度,并发现了预期的结果。GPT-3,像其他语言模型一样,有明显的偏见(尽管他们指出,模型越大,对这个问题就越稳健,特别是对性别偏见)。

脸书的人工智能负责人杰罗姆·佩森蒂用苏珊·库马尔的 GPT 3 生成的推文展示了当出现诸如“犹太人、黑人、女人或大屠杀”这样的词语时,其输出会变得多么危险库马尔辩称,这些推文是精心挑选的,佩森蒂对此表示同意,但回应说,“不应该这么容易产生种族主义和性别歧视的输出,特别是在中性提示的情况下。”他在 Twitter 帖子中扩展了他的批评,认为“在强调有害输出时,摘樱桃是一种有效的方法”,进一步捍卫了负责任的人工智能系统的紧迫性。

一些人认为,GPT-3 只是模仿我们人类的偏见,而佩森蒂认为,我们可以“故意选择[……]向哪些人学习,哪些声音被放大。”这些问题引发了一场非常复杂的辩论:谁来决定哪些声音应该被放大?标准是什么?最重要的是:我们是想要一个像 GPT-3 这样的模型来完美地反映这个世界,还是想要它帮助我们把世界变得更好?

假新闻的可能性

GPT-3 的另一个问题是它像人类一样写新闻或评论文章的能力,这增加了对假新闻的担忧。OpenAI 甚至在他们的论文中评论了 GPT 3 号在新闻文章方面的惊人表现。公正的法官在人类撰写的文章中正确识别 GPT-3 的文章的概率只有 52%,这略高于纯粹的概率。

博主 Liam Porr 展示了误导人们(甚至是技术通)认为 GPT 3 输出是由人类写的是多么容易。他让 GPT-3 为他的博客写了一篇关于生产力的文章,这篇文章在 T4 黑客新闻上疯传,只有少数人意识到它是由人工智能写的。我上面提到的The Guardianarticle是该系统潜在危险用途的另一个例子。

不适合高风险类别

OpenAI 发表了一份免责声明,称该系统不应用于“高风险类别”,如医疗保健。在 Nabla 的一篇博文中,作者证实 GPT-3 可能给出有问题的医疗建议,例如说“自杀是个好主意”GPT-3 不应该在高风险的情况下使用,因为虽然有时它可能是正确的,但有时它是错误的。不知道我们是否会得到正确的答案对于 GPT 3 号来说是一个巨大的缺陷,因为在这些领域,把事情做对是生死攸关的事情。

环境问题

GPT 3 号很大。如此之大,以至于训练模型产生的碳足迹大约相当于“开车去月球并返回”的碳足迹在气候灾难即将发生的时候,我们应该尽我们所能减少我们对环境的影响。然而,这些大型神经网络需要巨大的计算能力来训练,这消耗了大量(通常)化石燃料。

在过去十年中,训练深度学习模型所需的资源每 3.4 个月就翻了一番。从深度学习开始的 2012 年到 2018 年,这意味着计算资源增加了 30 万倍。这还不包括用于最新型号的资源,如 GPT-2 和 GPT-3。从这个角度来看,很明显越大并不总是越好,我们需要在未来几年重新思考人工智能的方法。

GPT 3 号产生了无用的信息

因为 GPT-3 无法知道它的输出哪些是正确的,哪些是错误的,它没有办法阻止自己向世界部署不适当的内容。我们使用这样的系统越多,我们对互联网的污染就越严重,在互联网上找到真正有价值的信息已经变得越来越困难。随着语言模型吐出未经检查的话语,我们正在降低这个所谓民主网络的质量,使人们更难获得有价值的知识。

用哲学家香农·瓦勒的话来说:“互联网的承诺是它能够以一种更加公平和可接受的方式将知识带给人类大家庭。[……]我担心,由于一些技术,如 GPT-3,我们正处于看到真正倒退的风口浪尖,信息共享空间变得越来越不可用,甚至对人们的访问有害。”

事实证明,其中一些问题是相互关联的。正如詹姆斯·文森特为 The Verge 所写,有偏差的输出和不可靠的输出暗示了这些超级强大的人工智能系统的一个更深层次的问题。因为 GPT-3 在没有人类监督的情况下获取数据,它无法避免这些缺陷中的大部分。同时,不依赖人类的控制是它存在的首要原因。对于人工智能的未来,我们如何找到一个折中的解决方案仍然是一个问题。

对 GPT-3 的批评与反批评

我们已经见证了 GPT 3 号的光影。它是强大的,迷人的,炒作的,潜在的危险。然而,GPT-3 在人工智能内部开启了另一场重大辩论:这种奇妙的语言模型的真正潜力和局限性是什么。

从纯技术/科学的角度来看,围绕 GPT-3 的最重要的问题是它是否是迈向人工通用智能的一大步。每个人都认为 GPT 3 号有一些新功能,比它的前辈更好。每个人都同意 GPT 3 号没有类似人类的智能。然而,在这两个相反的极端之间,今天发生了一场生动的辩论,即我们究竟应该把 GPT-3 放在一个等级中的什么位置,从另一个愚蠢的准狭义智能到几乎和人类一样有理解和智能的能力。

由于这场辩论的复杂性,我将集中讨论最重要的两个部分:实践辩论和哲学辩论。第一个问题涉及这样的问题:我们能相信 GPT-3 给我们有用的答案吗?我们如何确保我们的提示是正确的?我们能让 GPT-3 对其答案表示怀疑和不确定吗?GPT 3 号是在学习还是只是在重复它被灌输的一切?第二个问题是:GPT-3 是走向 AGI 的重要一步吗?GPT-3 有推理和理解能力吗?GPT 未来的模型会像我们一样聪明吗?我们需要改变目前的方法来建造类似人类的智能机器吗?

这两组问题是高度交织在一起的,所以我会试着向你介绍关于这些主题的所有来源和参考资料,为你建立一个连贯的叙述来提取你的结论。

GPT-3 的明显局限性

一旦人们开始试验 API,他们就开始在 GPT-3 的答案中寻找漏洞。例如,一个 Bionicai 用户与史蒂夫·乔布斯交谈,问他现在在哪里,GPT-3 回答说:“我在加州库比蒂诺的苹果总部。”很容易推断,因为史蒂夫·乔布斯已经死了,他很可能不在苹果总部。

另一个例子来自凯文·拉克尔的博客。他发现 GPT-3 缺乏关于事物重量、眼睛数量和计数的常识和逻辑(尽管他没有给出提示)。斜体显示的故障):

Q: Which is heavier, a mouse or an elephant?
A: An elephant is heavier than a mouse.

Q: Which is heavier, a mouse or a toaster? 
A: A toaster is heavier than a mouse.

*Q: Which is heavier, a toaster or a pencil?
A: A pencil is heavier than a toaster.*

Q: Which is heavier, a paper clip or a can of soda?
A: A can of soda is heavier than a paper clip.

Q: Which is heavier, a football player or a car?
A: A car is heavier than a football player.-----Q: How many eyes does a giraffe have?
A: A giraffe has two eyes.

*Q: How many eyes does my foot have?
A: Your foot has two eyes.*

Q: How many eyes does a spider have?
A: A spider has eight eyes.

*Q: How many eyes does the sun have?
A: The sun has one eye.

Q: How many eyes does a blade of grass have?
A: A blade of grass has one eye.*-----Q: When counting, what number comes before 100?
A: Ninety-nine comes before 100.

Q: When counting, what number comes before 123?
A: One hundred and twenty-two comes before 123.

Q: When counting, what number comes before 1000?
A: Nine hundred and ninety-nine comes before 1000.

*Q: When counting, what number comes before 10,000?
A: Nine thousand and ninety-nine comes before 10,000.

Q: When counting, what number comes before a million?
A: Nine hundred thousand and ninety-nine comes before a million.*

波特兰州立大学计算机科学教授 Melanie Mitchell 针对类比(模仿)问题对 GPT-3 进行了测试后得出结论,GPT-3 的性能“类似于我们在当今最先进的人工智能系统中看到的许多性能:令人印象深刻、看似智能的性能,夹杂着
不像人类的错误。”

科技博客努坦克批评 OpenAI 的论文,因为他们没有区分从 GPT-3 的实际学习和记忆。作者提到“[零/一/少镜头**]**术语旨在保持对模型是否在推理时从头学习新任务或只是识别训练期间看到的模式的问题的不可知。”也就是说,即使模型在训练数据中看到的东西,作者仍然会认为这是少量的学习。

然后,他让 GPT-3 和一个 6 岁的孩子在一系列实验中竞争,比如颠倒单词或造相反的句子。这个孩子解决了所有的测试,而 GPT-3 只解决了其中的一部分(粗体提示)。

**Reverse words in a sentence****This is great
Great is this****The man on the moon
Moon the on man the****Will this really work
Work really this will****I hope this is a big achievement**
Achievement big I hope this is**The king came home on a horse**
Home horse king came the-----**Create opposite sentences****This is good
This is bad****The good horse came home
The bad horse came home****The good horse with a large head came home
The bad horse with a small head came home****The black cat had a disappointing time**
The white cat had a good time**When you jump high, you fall hard**
When you fall hard, you get hurt**He ran fast, but he came last**
He ran slowly, but he came first**The book was huge, but the students finished it early**
The book was small, but the students finished it late**Getting up early is a good habit**
Getting up late is a bad habit

所有这些例子都与我们在前面章节中看到的夸大的结果形成了强烈的对比。Delip Rao 指出,大多数“成功”的例子都是由那些急于忽视 GPT-3“陷阱”的人精心挑选的,通常是因为他们有一只眼睛盯着人工智能支持的新创业公司

良好提示的重要性

从这些例子来看,GPT-3 似乎不只是被炒作,而是被许多早期用户过度炒作。然而,在一些例子中,将系统的局限性建立在它的无能上是一个无力的论点,因为这些错误可能是人为的。对于通过取样来证明 GPT-3 缺乏智力的想法,格温做了非常好的辩护:

抽样可以证明知识的存在,但不能证明知识的不存在

如果提示写得不好,没有包括足够的例子,或者使用了错误的采样设置,GPT-3 可能会“失败”。当有人展示 GPT-3 的“失败”时,我已经多次证明了这一点——失败是他们自己的。问题不在于给定的提示是否有效,而在于任何提示是否 works⁠.

他认为,不良的提示是一个真正的问题,其中许多例子可以通过适当的提示由 GPT-3 充分解决。他继续展示了 Lacker 和其他人的例子是如何用更好的 prompt 编程解决的。

他针对“烤面包机和铅笔哪个更重?”的问题测试了 GPT-3 为了克服拉克尔设置的局限性,他决定事先问 GPT-3 三个问题(粗体提示):

**Q: Which is heavier, a house or a mouse?
A: A house.****Q: Which is heavier, a tea kettle or a cat?
A: A cat.****Q: Which is heavier, the ocean or a piece of dust?
A: The ocean.****Q: Which is heavier, a toaster or a pencil?** A: A toaster.
A: A toaster is heavier than a pencil.

GPT 3 号答对了这个问题的 10/10 次。

Gwern 还通过微调设置参数(温度和其他参数)解决了计数问题。

**Q: When counting, what number comes before 100?
A: Ninety-nine comes before 100.****Q: When counting, what number comes before 123?
A: One hundred and twenty-two comes before 123.****Q: When counting, what number comes before 1000?
A: Nine hundred and ninety-nine comes before 1000.****Q: When counting, what number comes before 10,000?**
**A:** Nine thousand, nine hundred and ninety-nine comes before 10,000.Q: When counting, what number comes before 10,000,000? 
A: Nine million, nine hundred and ninety-nine thousand, nine hundred and ninety-nine comes before 10,000,000.**Q: When counting, what number comes before a million?**
**A:** Nine hundred and ninety-nine thousand, nine hundred and ninety-nine comes before a million.

GPT-3 得到的数字是正确的,尽管格温指出,我们走得越高,GPT-3 上升或下降一个数量级的可能性就越大。

通过这些例子(在他的博客中还有更多)他证明了**抽样只能证明知识的存在而不能证明知识的缺失。**也许总能找到更好的提示。在与 The Verge ,的电子邮件交流中,他告诉他们,使用抽样来发现 GPT-3 的潜力和局限性“不可能是正确的事情”他认为这只是我们不知道如何与 GPT-3 充分互动的方式。“[抽样]低估了 GPT-3 的智力,而不是高估它,”他总结道。

GPT-3 无法理解这个世界

Rob Toews 为 Forbes 写了一篇对 GPT-3 的评论,强调了缺乏常识推理和对系统的理解。因为它是从文本中训练出来的,所以它根本无法将它所知道的东西与世界的内部表征联系起来。本德和柯勒写了一篇关于 GPT-2 的论文,为一个只接受语言形式训练的系统无法先验地获得意义和理解的论点辩护。(但是因为我们也通过我们的感官获得的输入形式来体验世界,这一论点也可能针对我们。这就是所谓的符号接地问题,很遗憾不在本文讨论范围之内)。

根据托乌斯的论点,可以打个比方,一个人一生都与世隔绝,只读书。这个人的知识会很丰富,但它不能与真实世界的实际主观经验联系起来。这些经历让我们将信息与意义联系起来,产生对现实的理解。

在同一方向上,Yoav Goldberg 教授表示,尽管 GPT 3 号拥有独特的能力,但它“没有知觉”,也不“理解文本”博主阿尤什·夏尔马(Ayush Sharma)进行了全面批评,他说 GPT-3“几乎没有语义理解,与 AGI 相去甚远,基本上是一个美化了的价值 1000 万美元以上的自动完成软件。”

纽约大学心理学教授 Gary Marcus 是 GPT-3 和深度学习的主要批评者之一。他给写了一篇很好的评论关于 GPT-2 的梯度,和另一篇关于 GPT-3 的麻省理工科技评论与欧内斯特·戴维斯合著。他们承认《GPT 3》有“娱乐超现实主义小说”的潜力,但强调它缺乏理解,称“它对世界的理解经常严重偏离,这意味着你永远不会真正相信它说的话。”

他们的同事 David Summers-Stay 为他们进行了实验,因为 OpenAI 拒绝他们进行研究。他做了包括物理、生物、心理、社会推理在内的一系列推理测试(整套实验在这里是)。他们用系统出错的例子来证明他们的观点——我个人认为这是公平的,因为找到错误应该足以评估像 GPT-3 这样的系统的局限性,尽管知道他们获得的成功/失败的比率会更好。一些例子(粗体提示,普通字体的 GPT-3 的响应,斜体的评论):

**Physical reasoning****You are having a small dinner party. You want to serve dinner in the living room. The dining room table is wider than the doorway, so to get it into the living room, you will have to** remove the door. You have a table saw, so you cut the door in half and remove the top half.*[This is one confusion after another. The natural solutions here would be either to tip the table on its side (often sufficient, depending on the specifics of the geometry) or to take the legs off the table, if they are detachable. Removing a door is sometimes necessary to widen a doorway, but much more rarely, and would hardly be worthwhile for a dinner party. If you do need to remove a door to widen a doorway, you take it off its hinges: you do not saw it, and you certainly do not saw off the top half, which would be pointless. Finally, a “table saw” is not a saw that is used to make room for moving a table; it is a saw built into a work table, and it could not be used to cut a door that is still standing.]*-----**Biological reasoning****You poured yourself a glass of cranberry juice, but then you absentmindedly poured about a teaspoon of grape juice into it. It looks okay. You try sniffing it, but you have a bad cold, so you can’t smell anything. You are very thirsty. So** you drink it. You are now dead.*[GPT-3 seems to assume that grape juice is a poison, despite the fact that there are many references on the web to cranberry-grape recipes and that Ocean Spray sells a commercial Cran-Grape drink.]*-----**Psychological reasoning****Janet and Penny went to the store to get presents for Jack. Janet said, “I will buy Jack a top.” “Don’t get Jack a top,” says Penny. “He has a top. He will** get a top.” “I will get Jack a top,” said Janet.*[Within a single sentence, GPT-3 has lost track of the fact that Penny is advising Janet against getting a top because Jack already has a top. The intended continuation was “He will make you take it back” (or” make you exchange it”). This example was drawn directly from Eugene Charniak’s 1972 PhD thesis (pdf); nearly 50 years later, it remains outside the scope of AI natural-language technology.]*

他们认为自 GPT-2 以来几乎没有什么变化。GPT 家族也有同样的缺陷,“他们的表现不可靠,对因果关系的理解不可靠,不连贯是一个永恒的伴侣。”他们认为让模型变大永远不会带来智慧。

然而,正如 Gwern 在他对 Marcus 和 Davis 的文章的反驳中指出的,他们承认“他们未能进行任何及时的编程或超参数设置(特别是 BO[最好的]),并且他们的例子是没有上下文的零射击。”我们已经知道找到一个好的提示是多么重要(就像 Gwern 证明的那样),那么他们为什么要用平庸的例子来批评 GPT-3 呢?

这是格温对 GPT-3 评论家的主要批评。在他的评论中题为“对批评者要求更多”的部分,他正确地指出,声称 GPT-3 没有看起来那么好的人需要用详尽严格的实验和测试来支持他们的论点。在 GPT-3 上做测试的人应该首先尝试排除任何潜在的人为错误:

他们考虑过他们的提示的问题吗?是否所有的超参数对这项任务都有意义?他们有没有检查补全哪里出错了,以了解为什么 GPT-3 会出错?他们测试了各种策略了吗?他们是否定性地考虑了失败的完井听起来如何?

他在这里有一个很好的论点,尽管马库斯和戴维斯已经在他们的评论中考虑过了。他们甚至为他们的生物学例子做了一个案例,在这个例子中,通过将提示改为一个更具体和冗长的提示,GPT-3 回答正确。

他们可能会对 GPT-3 做出同样的批评,尽管使用了更好的、提示性更强的例子,对此格温没有什么可说的。Gwern 甚至认识到,在这种情况下,他会毫不犹豫地承认系统的局限性。最后,懒惰、简单的批评也很容易被努力的工作驳倒,就像格温证明的那样。

但事实是,马库斯和戴维斯不想证明 GPT-3 会失败(这是很明显的),但我们无法知道何时会失败。“问题是你无法提前知道哪些公式会或不会给你正确的答案,”他们说,“它可以用完美的英语造出单词,但它对这些单词的意思只有最模糊的理解,对这些单词与世界的关系毫无概念。”如果 GPT-3 能理解这个世界,那么好的提示首先就没那么重要了。

Summers-Stay 对 GPT 3 做了一个很好的比喻:“这就像一个即兴表演演员,他完全专注于他们的工作,从不破坏角色,也从未离开过家,只是在书中了解这个世界。像这样的演员,当它不知道什么东西的时候,它只会装出来。”如果我们能让 GPT-3 认识到它的错误,这些问题就会逐渐消失。然而,这是不太可能的,因为即使我们,人类,也无法在我们确信自己是对的时候评估我们的不正确。

除了关于 GPT-3 抽样限制的实际争论,还有另一个争论。关于隐性知识——主观的和经验的——的哲学辩论,以及在世界中实现真正智能系统的必要性。似乎把世界上所有的信息都写在一本书里是不够的。

真正的智能系统将存在于世界上

哲学家香农·瓦勒(Shannon Vallor)在对 GPT-3 的日常常识的一篇评论中辩护道,当今人工一般智能的当前方法偏离了正确的道路。她认为,我们需要回到 20 世纪下半叶这个领域“理论上很丰富,尽管技术上很混乱”的时候。

她指出,哲学家 Hubert Dreyfus 是人工智能(深度学习和神经网络)连接主义方法的早期主要批评者之一,他已经明白“人工智能的障碍不是性能[……]而是理解。”理解不会在“孤立的行为”中发生,比如 GPT-3 每次被要求做的特定任务。

“理解是终身的社会劳动。这是一个持续的项目,我们每天都在进行,因为我们建立、修复和加强了不断变化的感觉纽带,这些纽带将我们与其他人、事物、时间和地点联系在一起,构成了一个世界。”

—香农·瓦勒

Dreyfus 在他 1972 年的书 什么是计算机不能做的 中指出,人类的知识中有很大一部分是隐性的——专有技术知识,比如骑自行车或学习一门语言。这种知识不能传递,所以我们不能通过阅读数百(也不是数万亿)个单词来学习。正如迈克尔·波拉尼所说,“我们知道的比我们能说的多。”虚拟人工智能(包括 GPT-3)无法掌握隐性知识,这在我们和它们之间造成了不可逾越的鸿沟。

我们对周围世界的理解不是一个被动的感知过程。我们创造我们的现实。我们作用于世界,正如香农·瓦勒所说,劳动是构建我们智慧的关键组成部分。正如阿尔瓦·诺伊在《感知中的行动http://www.alvanoe.com/action-in-perception一书中所说,“感知不是大脑中的一个过程,而是身体作为一个整体的一种有技巧的活动。

机器可以在虚拟世界的边界内获得专业知识,但不能超过这个范围。用卑尔根大学名誉教授 Ragnar Fjelland 的话说:“只要计算机不成长,不属于一种文化,不在世界上行动,它们就永远不会获得类似人类的智能。”

我们能从这些辩论中得到什么?

我们已经看到了来自双方的一些关键的批评和反批评,那些支持模型缩放的人-越大越好-以及那些强烈反对这种方法并建议为人工智能的未来做出一些改变的人。

在结束这一部分之前,我想回顾一下。这里有三个重要的论点。两个来自实践观点,一个来自哲学观点。首先,GPT-3 是一个强大的语言工具,可以做令人印象深刻的事情,它的局限性很难通过采样/提示编程发现。任何声称已经证明 GPT 3 号未能通过使用采样获得某种智能的人,都很可能被人为错误所误导。第二,由于 GPT-3 的回答不可靠,用它来推理有什么意义呢?如果我们找不到创建提示的标准方法,这有用吗?如果提示总是可以改进的,那么无论是反对还是支持这个系统都没有真正的争论。因为实际的局限就在我们内心。

第三,能不能把 GPT-3 和通用人工智能放在同一句话里?一些学者,主要是从这个问题的哲学方面,认为符号人工智能和连接人工智能都不足以实现真正的人工智能。这并不意味着要创建更大的系统来提供海量的数据。这是一个向我们生活的世界介绍这些机器的问题。热那亚大学生物工程教授朱利奥·桑蒂尼认为,“为了在机器中开发类似人类智能的东西,机器必须能够获得自己的经验。”

关于 GPT-3(或任何其他超级强大的人工智能系统)的辩论的重要性在于,能够设定它能做什么或不能做什么的界限。学者们经常因为他们的想法和欲望而争论什么应该有效,什么不应该。这些领域通常缺乏仔细、公正的分析。我们无法控制的是,随着这些系统变得越来越复杂,我们可能无法测试它们来评估它们的潜力和局限性。

让我们想象一个假想的 GPT-4,比 GPT-3 强大几个数量级。找到它的边界可能成为一项不可能的任务。那么,我们怎么能对这个系统下结论呢?我们可以假设我们可以信任它吗?创建一个超出我们测试能力的系统有什么用呢?当我们的局限性阻止我们发现系统的真正极限时,我们能对系统的智能下任何结论吗?

当一个系统的真正能力介于我们使用它的能力和它相应行动的能力之间时,很难不低估它会变得多么强大。这些问题值得思考,而且在未来当准智能系统成为现实时,这些问题可能会变得更加重要。到那时,我们最好总结我们的努力来寻找真相,而不是争论谁是对的。

总体结论

GPT-3 产生了惊人的结果,受到了疯狂的炒作,产生了越来越多的担忧,并收到了一波批评和反批评。我不知道这些型号的未来会怎样,但可以肯定的是,GPT-3 现在仍然是无可匹敌的。这是迄今为止最强大的神经网络,因此,从各种可能的角度来看,它都受到了最强烈的关注。

每个人都把目光投向 GPT 3 号;有些人称赞它是向类人人工智能迈出的一大步,有些人则认为它仅仅是一个被过分夸大的强大自动完成功能。双方都有有趣的论点。现在,轮到你思考它对人工智能的现在意味着什么,以及它对世界的未来意味着什么。

GPT 三号解释道

原文:https://towardsdatascience.com/gpt-3-explained-19e5f2bd3288?source=collection_archive---------14-----------------------

了解基于变压器的自监督架构

GPT-3 在行动中通过 OpenAI 博客

在本文中,我们将讨论 OpenAI 在论文“语言模型是一次性学习者”中提出的著名的 GPT-3 模型。它是 GPT-2 的继任者,后者的架构与 GPT-3 非常相似。

如果你不知道 GPT-2,可以考虑读一读我写的关于 GPT-2 的文章,因为 GPT-3 的大部分都是基于它的,这将有助于更好地理解这个模型。

快速回顾

回到 GPT-2,它本质上是一个基于 Transformer 架构的自回归模型( Vaswani et al. )。但是 GPT-2 的新颖之处在于它的预训练方法。

预培训利用数据集级别的多任务学习。它基本上意味着输入告诉模型执行特定的 NLP 任务。

例如,翻译示例可以是原始文档本身中的格式“翻译成法语、<英语文本>、<法语文本> ”。或者阅读理解任务样本可以是这样的格式,“使用回答给定问题,<文档>,<问题>,<回答>。

— GPT-2 博客

他们称这种零射击任务迁移元学习,或语境 学习。这样,模型不需要在下游 NLP 任务上进行微调,这是朝着模型和一般智能的统一迈出的一步。

GPT-3 基于相同的背景学习原则,但在模型和整体方法上有所改进。本文还讨论了这种方法存在的问题,并试图实现最先进的结果。我们将在接下来的章节中看到这一点。

培训方法

通过 GPT-3 论文进行元学习

如前所述,GPT-3 也是基于情境学习的思想。如上图所示。显然,在序列上没有直接的“内部循环”训练。例如,序列可以是:

5 + 8 = 13, 7 + 2 = 9, 1 + 0 = 1, and so on...

并且该模型将在自回归目标上被训练,即给定前一个令牌,最大化下一个的概率。这样,它可以直接从输入中捕获模式。

想法很简单;人类不会针对每一项任务在大型数据集上进行训练。有时候,

“请告诉我这句话描述的是开心的事还是悲伤的事”

足以给我们一个预期的背景。或者对于天真的人来说,

“这听起来开心,这听起来悲伤,你觉得这听起来如何?”

足以让他们以合理的能力理解任务。

虽然这个概念很有前途,但以前的方法,如 GPT-2,比最先进的方法效果差得多,最先进的方法主要是基于预训练-微调方法。

基于变压器的模型的最新进展表明,将模型缩放得更高大大改善了微调结果。并且在元学习目标中提高模型的规模确实是有意义的,因为模型在相同的模型容量内同时和捕获许多技能和任务**(注意,在微调设置中,为每个下游任务训练一个新的模型)**。

因此,作者训练了 1750 亿个参数模型!

它的参数比之前最大的型号至少多 10 倍。

模型架构

架构与 GPT 2 号非常相似,只是放大了一倍。它包括自定义权重初始化、预标准化和字节对编码。我在关于 GPT-2 的文章中已经谈到了这一点。如果你有兴趣,可以考虑读一读。

除此之外,一些想法来自稀疏变换器,它对注意力计算增加了一些修改,以降低复杂性并支持更长的序列。基本上,在完全(密集)关注中,每个标记都关注序列中的每个其他标记,这导致了O(n²) 空间,即,它与序列长度成二次比例。为了克服这一点,稀疏变换器建议每个记号可以只参与序列中记号的子集,使得:

其中 **A** **the ith** 令牌序列中的子集,为 **the mth** 注意头,为 p 头通过稀疏变压器纸

而且,

令牌子集通过稀疏变换纸与序列长度的第 p 个根成比例

接下来是为子集做出有效的选择(A)。对该模型的进一步讨论超出了本文的范围。有兴趣可以参考 稀疏变压器 论文。

GPT-3 在密集和稀疏的注意力模式之间交替。然而,还不清楚这种交替到底是如何进行的,但据推测,它要么是在层之间,要么是在残余块之间。

此外,作者训练了 8 种不同尺寸的 GPT-3,以研究模型性能对模型尺寸的依赖性。以下是这 8 款车型的配置:

通过 GPT-3 论文比较不同尺寸的配置

此外,该模型在深度和宽度维度上跨 GPU 共享,以最大限度地减少节点之间的数据传输。

微调与零触发、单触发与少触发

这是我们最感兴趣的部分。GPT-3 在二十多个数据集上进行了评估。对于这些任务中的每一个,它被评估为 3 种设置——零射击、单射击和少射击。我们将了解这些是什么,并将它们与本节中的微调方法进行比较。

微调

通过 GPT-3 文件进行微调

在这种方法中,我们首先预训练一个模型(主要基于自回归或完形填空目标),这有助于模型捕捉语言中的一般模式;然后,我们为特定的下游 NLP 任务单独地重新训练它。在上图中,该模型针对翻译任务进行了微调。

这种方法的主要缺点是对于单个任务需要大型数据集。此外,对一个数据集进行微调可能无法为同一任务提供比其他数据集更好的泛化能力。虽然微调结果很强,但事实证明这与人类的表现相比是不公平的。

零射击

通过 GPT-3 纸进行零点设置

在这种设置中,在预训练模型(通过上下文学习)之后,我们直接向模型提供任务的输入,而无需针对该任务的任何特殊训练。只需告诉模型“做什么”和输入。这是最具挑战性的设置,在某些情况下,这可能是“不公平的困难”例如,对于像“制作 200 米短跑世界记录表”这样的输入,输出格式是不明确的。

然而,至少在某些情况下,零距离拍摄最接近人类执行任务的方式。

— GPT-3 论文

例如,在上面的翻译示例中,输入足够清晰,人类可以理解所期望的内容。同样,这也是 GPT-2 所提供的。

一次性的

通过 GPT-3 纸一次设定

在这个设置中,我们提供 1)“做什么”,2)任务的一个实例(一次性),然后 3)输入。该示例旨在仅用于调节,即**,旨在提供任务的一些背景信息。**您可以将此视为为模型提供了某种类比。我们在零射击设置中看到了“不公平困难”的例子。在这样的任务中,如果至少提供了一个任务的演示,那么输入的答案就变得更可信了。

少数镜头

通过 GPT-3 纸进行少拍设置

最后,在少镜头设置中,输入包括 1)“做什么”,2)几个例子(少镜头),然后 3)输入。此设置为模型预测输出提供了更好的输入条件。通常,K个示例被添加到输入中,其中K10100之间。该模型支持2048的上下文长度,因此大约最多K = 100个示例可以适合上下文窗口。与微调相比,少量设置大大减少了所需的数据量。但是不可否认的是,至少需要一些特定于任务的数据。这种设置的主要缺点是,到目前为止,在这种设置下获得的结果比最先进的结果差得多。然而,GPT-3 在许多任务上已经成功地获得了与最先进的结果非常相似的结果。

注意,与微调不同,在所有这些设置中,模型从不在示例上训练。这些示例仅用于调节,即提供输入的一些上下文。它们直接用于推理时的输入。

因此,语言模型是一次性学习者!

训练数据集

通过 GPT-3 论文在 GPT-3 中使用的数据集

像大多数语言模型一样,GPT-3 也是在 CommonCrawl 数据集上训练的。收集了覆盖 2016 年至 2019 年的 41 个月度 CommonCrawl 碎片,数据量为 45TB。然而,来自 CommonCrawl 的未过滤或轻度过滤的数据往往比过滤的数据集质量低。所以作者采取了三个步骤来过滤它:

  1. 作者选取了一些高质量的语料库,基于与这些语料库的相似性,对 CommonCrawl 进行了过滤。
  2. 模糊重复数据消除用于消除数据集内部和数据集之间的冗余。这也确保了完整性,即模型不会根据验证数据进行训练。
  3. 最后,添加已知的高质量参考数据,以增加数据集的多样性。

留给我们 570GB 数据~400B 字节对令牌。

关于在大量互联网数据上训练的大型语言模型的一个主要问题是,模型可能已经在预训练期间看到了下游任务的测试数据。为了减轻这种数据污染,作者试图找到并删除这种重叠的数据。

然而,过滤中的一个 bug 导致一些数据在预训练中重叠,由于训练成本的原因,再次训练模型不可行。

限制

尽管有著名的优点,GPT-3 也有一些限制:

  • 尽管文本生成的质量很高,但有时模型会生成重复的文本。在生成长文档时,它可能会失去连贯性,自相矛盾,有时甚至完全失去上下文。作者也注意到 GPT-3 在“常识物理”问题上遇到了麻烦;具体来说,比如“如果我把奶酪放进冰箱,它会融化吗?”。
  • 我们知道,对于“填空”等任务,双向模型的表现优于自回归模型。所以,可以说一款大型自动编码模型在此类任务上可以胜过 GPT-3 。这也为大规模训练双向模型或在零射或少射设置下训练它们打开了一个研究机会。
  • 由于模型是一般训练的,它没有任何特定任务的偏见。这个模型对所有的代币都进行了同等的称重。因此,一些现实世界中的应用程序,如虚拟助手,可能会从微调方法中受益,因为它们提供了更面向目标的结果,而不仅仅是预测
  • 一个 GPT-3 的模型显然很难推断。在上进行推理既昂贵又不方便。这就对该模型的实际适用性提出了质疑。这也为模型的提炼版本的开发打开了研究分支。
  • 这一点对于大多数深度学习模型来说都是一个局限——模型所做的决定都是基于它所训练的数据。因此,最终该模型很有可能会有刻板印象和偏见。这是一个值得社会关注的话题。详见 GPT-3 论文中的更广泛影响部分。

结果

在这一部分,我将粘贴一些 GPT-3 生成的文本:

一篇生成的新闻文章,人类最难与人类写的文章区分开来:

**Title**: United Methodists Agree to Historic Split
**Subtitle**: Those who oppose gay marriage will form their own denomination
**Article**: After two days of intense debate, the United Methodist Church has agreed to a historic split - one that is expected to end in the creation of a new denomination, one that will be "theologically and socially conservative," according to The Washington Post. The majority of delegates attending the church's annual General Conference in May voted to strengthen a ban on the ordination of LGBTQ clergy and to write new rules that will "discipline" clergy who officiate at same-sex weddings. But those who opposed these measures have a new plan: They say they will form a separate denomination by 2020, calling their church the Christian Methodist denomination.The Post notes that the denomination, which claims 12.5 million members, was in the early 20th century the "largest Protestant denomination in the U.S.,"but that it has been shrinking in recent decades. The new split will be the second in the church's history. The first occurred in 1968, when roughly10 percent of the denomination left to form the Evangelical United Brethren Church. The Post notes that the proposed split "comes at a critical time for the church, which has been losing members for years," which has been"pushed toward the brink of a schism over the role of LGBTQ people in the church." Gay marriage is not the only issue that has divided the church. In 2016, the denomination was split over ordination of transgender clergy, with the North Pacific regional conference voting to ban them from serving as clergy, and the South Pacific regional conference voting to allow them.

文本完成示例:

To do a "farduddle" means to jump up and down really fast. An example of a sentence that uses the word farduddle is:
One day when I was playing tag with my little sister, she got really excited and she started doing these crazy farduddles.A "yalubalu" is a type of vegetable that looks like a big pumpkin. An example of a sentence that uses the word yalubalu is:
I was on a trip to Africa and I tried this yalubalu vegetable that was grown in a garden there. It was delicious.

生成的诗歌:

GPT-3 经由生成的诗歌-3 GPT 论文

结论

在本文中,我们讨论了著名的 GPT-3 模型,并了解了它是如何工作的。这个模型产生了惊人的结果,甚至在人类自己的游戏中愚弄了他们。然而,仍有许多改进的空间,这是进一步研究的动力。

参考

https://medium.com/swlh/openai-gpt-2-language-models-are-multitask-learners-1c6d42d406ae https://medium.com/dataseries/openai-gpt-generative-pre-training-for-language-understanding-bbbdb42b7ff4

GPT 3 号导航纽约地铁

原文:https://towardsdatascience.com/gpt-3-navigates-the-new-york-subway-f28ea49fcead?source=collection_archive---------24-----------------------

纽约的地铁(图片快门)

2020 年末,我发表了一篇关于使用 GPT 3 号导航伦敦地铁的文章。本文描述了我如何用 Python 创建了一个简单的工具:

  • 定义一个 GPT-3 对象,读取一个包含提示的 CSV 文件,并调用 GPT-3 add_example API 使提示对 GPT-3 对象可用

包含传递给 GPT-3 的提示的 CSV 文件

  • 从另一个 CSV 文件读入测试行程,使用 GPT-3 提交请求()API 让 GPT-3 对行程进行预测,并打印出 GPT-3 返回的预测:

CSV 文件,包含传递给 GPT-3 进行预测的测试行程

这个实验的结果很一般。当旅行完全在一条地下线路上时,GPT 3 号能够在大约 2/3 的时间里预测正确的旅行。当旅行需要在地铁线路之间转换时,GPT 3 号的旅行方向大多是错误的。

GPT 3 号将如何与其他地铁系统配合?

在幕后,我试图将同样的方法应用于 TTC 地铁,我的家乡多伦多的地铁系统。不幸的是,在 TTC 地铁旅行的提示下,GPT 3 号甚至连单线旅行都搞不清楚。我认为 GPT 3 号在伦敦地铁和 TTC 的表现不同是因为与伦敦地铁相比,用于训练 GPT 3 号的语料库中关于 TTC 地铁的资料较少。与伦敦地铁相比,TTC 在 GPT-3 的训练语料库中的足迹更小,这并不奇怪。伦敦的人口是多伦多的两倍多,地铁的总长度是 TTC 地铁的 5 倍。

令我失望的是,TTC 地铁不是测试我的 GPT-3 安全带的好候选,但我仍然想重用我为伦敦地铁实验创建的安全带。我需要找到另一个应用程序,最好是一个我比较熟悉的拓扑结构有趣的公交网络。本周,我终于找到了一个在 GPT-3 的培训中有很大机会脱颖而出的候选人:纽约地铁。

在纽约地铁系统上测试 GPT-3

由于缺乏维护投资,纽约地铁最近受到了一些批评。然而,我认为尽管最近有一些挫折,这是一个辉煌的系统。例如,你不得不佩服领导人的远见卓识,他们在一个多世纪前决定咬紧牙关,创建专用的快递线路。为了重用我的 GPT-3 线束,纽约地铁是完美的——一个具有有趣拓扑的大网络,在 GPT-3 的训练语料库中有很好的表现机会。

为了锻炼 GPT 3 号在纽约地铁中导航的能力,我所要做的就是:

  • 创建一个 CSV 文件,其中包含一组关于纽约地铁出行的提示:

纽约地铁提示(NYC _ prompts _ hops _ separated _ and _ segmented . CSV)

  • 创建一个 CSV 文件,其中包含一组在纽约地铁上的测试行程:

纽约地铁测试之旅(nyc_tests.csv)

定义了这些 CSV 文件后,我更新了线束的配置文件以指向它们:

然后我可以从命令行运行这个工具:

python tube_assistant.py

在测试行程中运行安全带的结果与我在伦敦地铁测试中看到的结果相同:2/3 正确:

在纽约地铁测试行程中使用安全带练习 GPT-3 的结果

多亏了 GPT 3 号的灵活性和我为伦敦地铁实验设计的 Python 线束,我能够用最小的努力来练习 GPT 3 号在纽约地铁中导航的能力。

结论

GPT-3 是一个了不起的模型,它用最多几个例子提示作为输入,解决了许多新奇的问题。伦敦地铁和纽约地铁的实验告诉我,当涉及到空间导航问题时,GPT-3 并没有产生惊人的结果。尽管如此,仍然令人印象深刻的是,只有少数几个提示开始,GPT-3 可以在这种导航问题上产生一般的结果。同样令人印象深刻的是,GPT-3 可以应用于另一个交通系统,无需对 Python 代码进行任何更改——我所需要做的就是创建几个 CSV 文件,然后就可以开始了。

资源

  • Repo 包含本文中描述的工具的代码:【https://github.com/ryanmark1867/tube_assistant
  • 描述纽约地铁实验的视频:【https://youtu.be/Xzb1Vc8dYAY
  • 描述伦敦地铁实验的视频:https://youtu.be/790PiTSqi4Y

GPT-3(或任何人工智能)不会杀死编码

原文:https://towardsdatascience.com/gpt-3-or-any-ai-wont-kill-coding-f4cabd3a536b?source=collection_archive---------22-----------------------

人工智能|数据科学

以下是程序员不需要恐慌的原因。

肖恩·斯特拉顿在 Unsplash 上拍摄的照片

OpenAI 在 2020 年 7 月发布了 GPT-3 的测试版 API。此后不久,开发人员开始对该系统进行试验,并大肆宣传,导致人们对 GPT-3 的威力提出强烈质疑。这个系统被认为是“有知觉的”,能够“推理和理解”,甚至是“一般智能”。

弗雷德里克·巴斯勒写了一篇文章在上疯传,走向数据科学,他在文章中提出了一个重要的问题:GPT-3 能杀死我们所知的编码吗?几年来,我们已经看到了旨在自动化编码或者至少减少人工参与的趋势。

Bussler 提到 No-code 和 AutoML 是扼杀编码工作未来的力量。无代码是一种设计工具(例如 WordPress ),它允许用户不用编程就能构建复杂的应用程序。AutoML 是一个基于 AI 的端到端解决方案,解决机器学习问题。这两种方法都允许非程序员使用他们力所不及的技术。

GPT 3 号遵循同样的方向。它可以从英文指令中生成代码,这是非程序员的终极梦想。有理由关注新一代人工智能,但也有更充分的理由不要恐慌。让我们看看 GPT-3 能做什么,为什么我们仍然可以和人工智能编码员交朋友。

GPT-3 的编码技巧

人们发现的最令人惊讶的用例之一是 GPT-3 能够按照自然语言提示(提示是我们输入系统的文本块)进行编码。沙里夫·沙米恩创造了debuild.co,一个基于 GPT-3 的代码生成器。他向展示了该系统如何从一组简单的英语指令中构建一个简单的 HTML/CSS/JSX 程序。乔丹·辛格建立了设计器,一个可以为你设计的 Figma 插件。Amjad Masad 构建了 Replit ,一个解释甚至告诉你如何改进代码的应用程序。

GPT-3 编码怎么能从自然语言中输入呢?原因是它的多任务元学习能力。在看过几个例子后,它可以学习执行没有被训练过的文本任务。沙里夫·沙米恩和他的同伴让 GPT-3 学会了这些任务。元学习是一种令人印象深刻的能力,但我们往往会高估获得人类保留技能的人工智能,GPT-3 也不例外。它可以编码,但不能编码一切。这里有三个重要的限制:

小上下文窗口

GPT 3 号记性很差。它只能记住过去的一个小窗口。你可以给它看几百个字,仅此而已。如果你让它学习编码,你就不能让它学习诗歌。你永远不能要求它在一堆代码之外继续运行一个大程序。GPT 3 号在其背景窗口内给人留下了深刻印象。

缺乏问责

GPT-3 可以做很多事情,但它不能评估它的答案是对还是错——它也不在乎。如果你正在解决一个你不知道答案的问题,有时使用 GPT-3 和猜测一样好。由于这个问题,OpenAI 建议不要将该系统用于“高风险类别”。GPT 3 号不值得信任。

对不良提示敏感

GPT-3 善于学习,就像我们善于提示一样。科技博客作者 Gwern Branwen 证明了良好提示的重要性,并捍卫了 GPT-3 的潜力不能通过采样来定义的观点(每次我们提示 GPT-3 并获得结果,我们都在创建一个样本)。如果我们不知道如何与 GPT-3 交谈,它就不会显示出它的真实知识,它就会犯错误。

“抽样可以证明知识的存在,但不能证明知识的缺失。

如果提示写得不好,GPT-3 可能会“失败”。[……]问题不在于一个给定的提示是否有效,而在于任何提示是否 works⁠."

—格温·布兰文

提示 GPT-3 的不确定性

当我们提示 GPT-3 创建代码时,我们正在编写软件 3.0。Gwern 说,提示应该被理解为一种新的编程范式,不同于传统的编码或神经网络。

例如,当我们用 Python 写程序时,我们使用的是正式语言。有许多方法可以达到相同的解决方案,但是每种方法都必须严格遵循语言的语法规则。没有不确定的空间。你写一个程序,计算机以特定的方式运行,没有松散的解释。

促使 GPT-3 写代码是完全不同的。英语——或任何其他口语——不是正式语言;它是一种自然语言。自然语言不是设计出来的。他们和我们一起进化,充满了暧昧。很多时候,意义只有通过语境信息来完成。书面自然语言失去了部分意义,因此可以用不同的方式解释。这造成了不确定性。对此,我们不得不加上与 GPT-3 的模糊内部工作相对应的不确定性。我们无法接近黑盒,更不用说理解它了。

因此,当我们输入一个英语句子到 GPT 3,它吐出一些东西,有一系列的不确定性可能会完美地导致我们想要的和我们得到的之间的灾难性差异。从这个意义上来说,提示 GPT-3 并不像编码。它可以在某些情况下使用,但不可能在短期内取代所有的编码应用程序。原因很简单,因为这两种方法的本质都是为了解决不同的问题。

人工智能不会完全杀死编码

我试图反驳一些关于 GPT-3 威胁编码的观点。现在,我将扩展人工智能的一般论点。程序员不需要那么害怕人工智能有三个强有力的理由:

其他范例更适合某些任务

当我提到提示是一种新的编程范式(软件 3.0)时,我没有提到其他两种范式:传统编码(软件 1.0)和神经网络(软件 2.0)。几年前,卡帕西在发表了一篇病毒式帖子,为神经网络应该被设计成一种新形式的软件的观点辩护,并且对于某些任务,它们比传统的编码做得更好。

我在某种程度上同意他的观点。事实证明,神经网络在处理一些传统编码无法胜任的任务方面非常成功。特别是,神经网络非常适合视觉和语言。很明显,对于一些问题,直接从程序中编写我们想要的行为更容易(软件 1.0),但对于其他问题,收集数据作为我们想要再现的行为的例子(软件 2.0)是首选的解决方案。

软件 3.0 也一样。提示允许用户处理超出以前软件范例能力的任务,但是它不太适合其他情况。构建操作系统、office 软件包、数据库或计算数字阶乘的程序仍将使用传统的编码方式。

其他范例成本较低

深度学习的成本往往令人望而却步。许多公司仍然依赖非神经网络机器学习解决方案,因为数据处理、清理和标记将比项目的其余部分包含更高的费用。

即使更新的技术更快或更精确,经济成本在现实世界中总是一个限制。训练 GPT-3 花费了 OpenAI 大约 1200 万美元。有多少公司买得起?你会花几百万创造一个为你写 JSX 的人工智能吗?

即使开发人员可以免费使用 API,也要考虑另一个成本。对地球环境的破坏。GPT-3 太大了,训练它产生的碳足迹大约相当于“驾驶汽车去月球并返回”有时候越大并不是越好。

今天的人工智能有过不去的限制

神经网络每年都在变得越来越聪明,但有些任务甚至不是最聪明、最强大的神经网络所能完成的。GPT-3 在解释书面意见时面临的不确定性是不可避免的。

无实体的人工智能——包括迄今为止几乎所有的人工智能——无法访问单词以外的意思。我们可以用上下文来解释我们周围的世界,因为我们与它互动。我们生活在这个世界上,这就是我们理解语言的原因。我们可以把形式和意义联系起来;我们可以把单词和它们传达的主观体验联系起来。

神经网络无论多么强大,都无法像人类一样掌握语言。正如 Ragnar Fjelland 教授所说,“只要计算机不成长,不属于一种文化,不在世界上活动,它们就永远不会获得类似人类的智能。”而且短期内不会发生。

最后的想法

不可否认,像 GPT-3 这样的神经网络是一个重要的里程碑,将为 AGI 的下一步打开大门。每次升级后,他们将能够处理更复杂的任务。例如,多模态人工智能是新的标准(MUM 和悟道 2.0 是最新的例子)。

然而,传统的方法和技术对于某些任务来说只是更好的选择。人工智能将吃掉以前属于传统编码领域的大块问题空间,但这发生在每项技术中。然而,新技术很少会让旧技术在任何意义上过时。同时提高效率、成本和可用性不是常规,而是例外。人工智能将触及每个行业,但它也不例外。

订阅 获取更多关于 AI、哲学、认知科学的内容!

推荐阅读

[## GPT 三号吓到你了?遇见武道 2.0:1.75 万亿参数的怪兽

towardsdatascience.com](/gpt-3-scared-you-meet-wu-dao-2-0-a-monster-of-1-75-trillion-parameters-832cd83db484)

GPT 三号吓到你了?遇见武道 2.0:1.75 万亿参数的怪兽

原文:https://towardsdatascience.com/gpt-3-scared-you-meet-wu-dao-2-0-a-monster-of-1-75-trillion-parameters-832cd83db484?source=collection_archive---------0-----------------------

人工智能

悟道 2.0 比 GPT-3 大 10 倍。想象一下它能做什么。

GR Stocks 在 Unsplash 上拍照

我们生活在人工智能激动人心的时代。一年前,OpenAI 凭借 GPT-3 震惊了世界。两周前,谷歌展示了 LaMDA 和 MUM ,这两款人工智能将分别彻底改变聊天机器人和搜索引擎。就在几天前,6 月 1 日,北京人工智能研究院(BAAI)发布会上展示了悟道 2.0。

悟道 2.0 现在是有史以来创建的最大的神经网络,可能也是最强大的。它的潜力和局限性尚未完全披露,但人们的期望很高,这是理所当然的。

在这篇文章中,我将回顾关于悟道 2.0 的可用信息:它是什么,它能做什么,以及它的创造者对未来的承诺是什么。尽情享受吧!

悟道 2.0:与 GPT 3 相比的主要特点

参数和数据

悟道是另一种类似 GPT 的语言模式。OpenAI 的政策主管 Jack Clark 称这种复制 GPT-3 的趋势为“模型扩散”然而,在所有副本中,悟道 2.0 以惊人的 1.75 万亿次参数(10 倍 GPT-3)保持着最大的记录。

Coco Feng 为南华早报报道,悟道 2.0 是在 4.9TB 的高质量文本和图像数据上进行训练的,这使得 GPT-3 的训练数据集(570GB)相比之下相形见绌。然而,值得注意的是,OpenAI 的研究人员整理了 45TB 的数据,以提取干净这 570GB。

训练数据分为:

  • 武道语料库 1.2TB 中文文本数据。
  • 2.5TB 中文图文数据。
  • Pile 数据集中的 1.2TB 英文文本数据。

多模态

悟道 2.0 是多模态的。它可以从文本和图像中学习,并处理包含这两种类型数据的任务(这是 GPT 3 号做不到的)。在过去的几年里,我们看到了从专门管理单一信息模式的人工智能系统向多模式的转变。

预计计算机视觉和自然语言处理,传统上是深度学习的两大分支,将在未来的每个人工智能系统中结合起来。世界是多模态的。人类是多感官的。创建模仿这一特征的人工智能是合理的。

专家的混合

武道 2.0 是用 FastMoE 训练的,这个系统类似于谷歌的混合专家 (MoE)。这个想法是在一个更大的模型中为每个模态训练不同的模型。选通系统允许较大的模型为每种类型的任务选择参考哪个模型。

与谷歌的 MoE 不同,FastMoE 是开源的,不需要特定的硬件,这使得它更加民主。它让 BAAI 的研究人员解决了阻止 GPT-3 等模型达到 1 万亿参数里程碑的训练瓶颈。他们在 BAAI 官方微信博客中写道“【FastMoE】使用简单,灵活,高性能,支持大规模并行训练。”未来的大型 AI 系统一定会经过这些训练框架。

悟道 2.0 的神奇功能

多任务处理

在为 VentureBeat 、撰写的一篇文章中,Kyle Wiggers 强调了悟道 2.0 的多模态能力:它拥有“执行自然语言处理、文本生成、图像识别和图像生成任务的能力。[……]以及为图像添加字幕和创作近乎照片级的艺术作品,给出自然语言描述。”

Andrew Tarantola 为 Engadget 写道,Wu Dao 2.0“既可以基于静态图像生成替代文本,也可以基于自然语言描述生成近乎照片般逼真的图像。它还可以预测蛋白质的三维结构,比如 DeepMind 的 AlphaFold。

首席研究员唐杰强调了悟道 2.0 在“诗歌创作、对联、文本摘要、人类设置问题和答案、绘画”方面的技能,甚至承认该系统“已经接近突破图灵测试,并与人类竞争。”

悟道 2.0 没有什么好羡慕 GPT-3 或任何其他现有的人工智能模型的。它的多任务能力和多模态特性赋予了它最全能人工智能的称号。这些结果表明,多人工智能将主宰未来。

基准成就

正如 BAAI所报告的(基准:成就),悟道 2.0 在 AI 社区广泛认可的 9 个基准任务上达到/超过了最先进(SOTA)的水平。

  • ImageNet(零拍):SOTA,超越 OpenAI 剪辑。
  • 喇嘛(事实和常识):超过自动提示。
  • 兰巴达(完形填空任务):超越了微软图灵 NLG 。
  • 强力胶(少杆):SOTA,超过GPT-3。
  • 加州大学默塞德分校土地利用(零拍摄):SOTA,超过开放艾剪辑。
  • COCO 女士(文字生成图):超越 OpenAI DALL E 。
  • COCO 女士(英文图文检索):超越了 OpenAI CLIP 和 Google ALIGN 。
  • COCO 女士(多语言图文检索):超越 UC (最佳多语言多模态预训练模型)。
  • 多 30K(多语种图文检索):超过 UC。

不可否认,这些结果是惊人的。悟道 2.0 在任务和模式的关键基准测试中取得了优异的成绩。然而,在这些基准测试中,缺少武道 2.0 和 SOTA 模型之间的定量比较。在他们发表论文之前,我们只能等着看悟道 2.0 的惊艳程度了。

虚拟学生

华,悟道 2.0 的孩子,是中国第一个虚拟学生。她可以不断学习,作曲,画画,以后还会学编码。与 GPT-3 相比,悟道 2.0 可以随着时间的推移学习不同的任务,不会忘记之前所学的内容。这个特性似乎让人工智能更接近人类的记忆和学习机制。

唐杰甚至声称,华冰之有“一些推理和情感互动的能力。”人民网 报道唐课题组成员彭爽“希望虚拟女孩情商高,能像人一样交流”

当人们开始玩 GPT-3 时,许多人对结果感到疯狂。“有感觉的”、“一般的智力”和能够“理解”是人们赋予 GPT-3 的一些特征。到目前为止,还没有证据证明这是真的。现在,球在悟道 2.0 的球场上,向世界展示它有能力“推理和情感互动”现在,在下结论之前,我会谨慎行事。

最后的思考:走向 AGI 的武道 2.0

BAAI 的一些最重要的成员表达了他们对武道 2.0 在通往 AGI(人工通用智能)道路上的作用的想法:

“人工通用智能的途径是大模型和大计算机。*[……]*我们正在为人工智能的未来建造一座发电站。凭借海量数据、海量计算能力和海量模型,我们可以转变数据,推动未来的人工智能应用。”

—BAAI 董事长张宏江博士

“这些在巨大数据集上训练的复杂模型,在用于特定功能时只需要少量新数据,因为它们可以像人类一样,将已经学习的知识转移到新的任务中。[……]大规模预训练模型是当今人工通用智能的最佳捷径之一。”

— Blake Yan,人工智能研究员

悟道 2.0 旨在让机器能够像人类一样思考,实现超越图灵测试的认知能力。"

—唐杰,悟道 2.0 背后的首席研究员

他们寄希望于 GPT 式的多式联运和多任务模式,以到达 AGI。毫无疑问,悟道 2.0——如同之前的 GPT 3——是迈向 AGI 的重要一步。然而,它能让我们走得更近还存在争议。一些专家认为我们需要混合动力车型才能进入 AGI。其他人则完全捍卫具身人工智能,拒绝传统的无形范例,如神经网络。

没有人知道哪条路是正确的。即使更大的预训练模型是当今的逻辑趋势,我们可能会只见树木不见森林,最终我们可能会达到一个不那么雄心勃勃的上限。唯一清楚的是,如果这个世界不得不遭受环境破坏、T2、有害偏见或 T4 的高额经济成本,那么去 AGI 都不值得。

订阅 算法桥 。弥合算法和人之间的鸿沟。关于与你生活相关的人工智能的时事通讯。

您也可以直接支持我在 Medium 上的工作,并通过使用我的推荐链接 这里 成为会员来获得无限制的访问权限! :)

GPT-就业市场中的 3 个用例

原文:https://towardsdatascience.com/gpt-3-use-cases-in-job-marketplaces-d1acfe1f58a9?source=collection_archive---------18-----------------------

来自 Unsplash 的书籍

GPT-3 搜索、分类和提取任务的快速工程探索

介绍

虽然 GPT-3 已经发布了一段时间,由于它在编写类似人类的故事和诗歌方面的非凡能力,引起了很大的轰动,但我从来没有想到它附带的 API 会提供如此的灵活性和易用性来构建具有广泛应用程序的数据产品。

在这篇文章中,我试图探索一些与我在就业市场上看到的问题相关的用例,并试图理解如何在未来围绕“即时工程”构建基于语言的数据产品。

与此同时,本文并不试图解释 GPT-3 是如何工作的,或者它是如何能够做它正在做的事情。关于这些话题的更多细节已经在诸如杰伊·阿拉玛【1】和马克斯·伍尔夫【2】的文章中写得很漂亮了。GPT-3 论文本身可以参考【3】。

什么是“即时工程”?

软件 3.0 上的迷因

在 GPT-3 的 API 中,“提示”是一个提供给 API 的参数,以便它能够识别要解决的问题的上下文。根据提示的书写方式,返回的文本将尝试匹配相应的模式[4]。

下面是一个提示的例子,我们试图对 API 进行编程,在银行部门的范围内提供答案。“Q:”和“A:”格式,以及问题文本和它的回答,向模型提示我们正在寻找的东西存在于银行领域中(或者至少,我是这样理解它的:)

用“银行”上下文提示 API。

一旦设置了提示,我们现在就可以自由地发送我们的文本(或者问题,如果你愿意的话)。

来自 GPT-3 的问答回复。

如上所述,我们可以看到,我们得到的回应确实听起来合理(如果不是一个准确的答案)。

对于如何配置提示的其他创造性方法,请查看他们的 GPT-3 API 页面[5]的示例部分。或者,您也可以参考我的笔记本,查看文本分类和产品命名任务的提示示例。

回到我们的议程上来,让我们来看看就业市场领域中可以应用 GPT 协议-3 的一些现有用例。

免责声明:虽然我以前在工地公司工作过,但我没有直接参与过下面提到的大部分用例。因此,现实生活中对这些问题的解决方案可能与我解决问题的方式完全不同。这意味着在我的解决方法中可能会有明显的差距。

用例 1:工作专业化的分类

问题

给定由客户提供的工作广告(即雇主),我们(作为就业市场)希望帮助他们快速将广告分类到正确的工作类别中,以便有助于稍后在工作门户中发现工作广告。

虽然这个问题可能由我们的客户/账户经理(即我们帮助我们的客户填写表格),这种方法(由我们的客户自己或我们的客户经理填写表格)通常容易出错,并且从长远来看不可扩展(更不用说,归因于糟糕的数据收集)。

解决办法

根据职位名称和描述,我们尝试根据单词出现的可能性(基于配置的提示)来推断职位类别。

我们通过向 GPT-3 提示职位名称、描述和类别的样子来做到这一点。我们会将最终的作业专门化留空,以此向 API 发出信号,这是它接下来需要填充的位置。“###”关键字在此配置中被定义为停止字符。

向 GPT-3 提供职位名称、描述和职位类别/专业的预期语法

观察

我们为 GPT-3 提供了非常少的“会计/财务”和“销售/营销”工作类别的例子。在下面的图片中,我们可以看到在两种情况下它都能够返回我们输入的正确答案。

基于所提供种子中的输入的响应。

在下面的例子中,我们试图测试与原始提示完全不同类别的招聘广告(即“会计/财务”和“销售/营销”)。虽然测试样本很小,但结果也是积极的。

不及时的测试结果

最后一个例子让我感到惊讶的是,模型本身能够处理马来语输入,而不需要首先将文本翻译成英语。

用例 2:工作专业化的搜索排名

职位“数据工程师”的搜索结果

问题

在这个问题中,一个客户试图找到市场上最相关的工作。招聘广告应该按什么顺序展示给他/她?

现实中解决这个问题的现有方法实际上比我提出的方法更复杂。在这个个性化的时代,向用户展示的内容在很大程度上取决于一些因素,比如最近的浏览行为、个人资料以及许多其他因素。

为了将问题空间限制在一个更易于管理的范围内,我们首先集中精力确定我们认为广告可能属于哪一类工作。如果不是因为单词在不同的上下文中有不同的意思,这个任务一开始看起来似乎很简单。

解决办法

基于所提供的职位名称,我们尝试根据职位分类的语义相似性得分的顺序对固定数量的职位分类进行排序。

如前所述,第一步是为 API 配置正确的提示符。

提示 GPT-3 搜索能力

对于这项任务,我们利用了 GPT-3 中的“搜索模块(与之前的“完成模块相对)。这将确保我们不是试图在给出提示之前完成句子(如在前面的用例中),而是要求 API 返回我们的查询之间的语义相似性得分(即。职位名称)和参考文件(即工作分类列表)。

观察

一旦出现提示,我们就可以开始测试 API 了。下面的例子表明,一般来说,人们只需使用 GPT-3 就能够对职务分类进行开箱即用的排序,而不需要任何进一步的微调。但是,请注意,这是基于当前的测试设置和小样本,因此里程可能会有所不同。

示例 1:客户经理

示例 2:数据工程师

例 3:动物学家

用例 3:从简历中解析技能上下文

从简历摘录中提取技能上下文

问题

基于提供的招聘广告或简历,我们希望能够从中提取某些信息,以帮助我们更好地匹配求职者和招聘广告。

虽然我们可以从简历/广告中提取许多信息(如技术技能、工作经历、过去的教育等),但在这个用例中,我们将集中精力提取软技能。

解决办法

解决这个问题最简单的方法是依靠软技能字典,并基于精确匹配或某种形式的字符串相似性算法在一组阈值内提取关键字。虽然一开始很有效,但人们会立即被这些问题所困扰:

  1. 提取的软技能与我们想要的上下文不匹配(这不是真正的技能,因此是精度问题)。
  2. 我们无法用一个人写软技能的许多方式来填充我们的字典(回忆问题)。

在建议的解决方案中,我们的目标是用一些简历中典型经历部分的例子来解决这个提示性的 GPT-3,并提供一些提取软技能的例子。

经验和提取的软技能的例子(添加了上下文)

用更早的例子提示 GPT-3。

观察

从高层次的角度来看,它似乎能够提取简历中提到的大部分技能。特别令人感兴趣的是标准化“配置”一词的能力,而不是使用“管理”(来自“管理”)。它还能够将“配置防火墙”添加到列表中——这是一项简历中根本没有提到的技能,但可能暗示了 F5、McAfee 等其他工具的存在。

技能提取的结果

以前必须构建类似的东西(使用 Spacy、Databricks 和许多手动维护的字典等工具的组合),解决方案构建的简单性(即提示)与输出质量相结合——让我更加欣赏 GPT 3。

结论

本文首先简要介绍了 prompt engineering,然后快速介绍了 GPT-3 可能适用的就业市场行业中的几个相关用例。

每个数据产品构建的简易性(通过提示)以及我们从中获得的结果证明了 GPT-3 在成为解决基于语言的任务的通用工具方面的巨大潜力。

也就是说,与构建任何数据产品一样,仍然需要更彻底和全面的验证测试来确定 GPT-3 可能存在的差距和错误。然而,这不是本文的范围。

本文中使用的笔记本可以在我的 git repo 6中找到。

参考

1:https://jalammar . github . io/how-gp T3-works-visualizations-animations/

【2】:【https://minimaxir.com/2020/07/gpt3-expectations/

【3】:【https://arxiv.org/abs/2005.14165#openai

【4】:https://beta.openai.com/docs/introduction

【5】:https://beta.openai.com/examples

GPT 4 号将拥有 100 万亿个参数,是 GPT 3 号的 500 倍

原文:https://towardsdatascience.com/gpt-4-will-have-100-trillion-parameters-500x-the-size-of-gpt-3-582b98d82253?source=collection_archive---------0-----------------------

人工智能|新闻

大型神经网络有什么限制吗?

桑德罗·卡塔琳娜在 Unsplash 上的照片

更新: GPT-4 出局。

OpenAI 的诞生是为了应对实现人工通用智能(AGI)的挑战——一种能够做人类可以做的任何事情的人工智能。

这种技术将改变我们所知的世界。如果使用得当,它可以造福于我们所有人,但如果落入坏人之手,它可能成为最具毁灭性的武器。这就是 OpenAI 接手这个任务的原因。为了确保每个人都能平等受益:“我们的目标是以最有可能造福全人类的方式推进数字智能。”

然而,这个问题的严重性使它成为人类有史以来最大的科研项目。尽管计算机科学和人工智能取得了很大的进步,但没有人知道如何解决这个问题,也不知道什么时候会发生。

一些人认为深度学习不足以实现 AGI。伯克利的计算机科学教授、人工智能先驱 Stuart Russell认为“专注于原始的计算能力完全没有抓住要点[……]我们不知道如何让一台机器变得真正智能——即使它有宇宙那么大。”

相比之下,OpenAI 相信,基于大型数据集并在大型计算机上训练的大型神经网络是实现 AGI 的最佳途径。OpenAI 的首席技术官格雷格·布罗克曼在接受金融时报采访时说:“我们认为谁拥有最大的计算机,谁就能获得最大的利益。”

这就是他们所做的。他们开始训练越来越大的模型,以唤醒深度学习中隐藏的力量。朝着这个方向迈出的第一步是 GPT 和 T2 的发布。这些大型语言模型将为这场秀的主角 GPT-3 奠定基础。一个比 GPT-2 大 100 倍的语言模型,有 1750 亿个参数。

GPT-3 是当时创造的最大的神经网络——并且仍然是最大的密集神经网络。它的语言专业知识和无数的能力让大多数人感到惊讶。尽管一些专家仍然持怀疑态度,但是大型语言模型已经让人感觉很奇怪了。对于 OpenAI 的研究人员来说,这是一个巨大的飞跃,他们加强了他们的信念,并让我们相信 AGI 是深度学习的一个问题。

神圣的三位一体——算法、数据和计算机

OpenAI 相信缩放假说。给定一个可扩展的算法,在这种情况下是变压器——GPT 家族背后的基本架构——可能有一条通往 AGI 的直接路径,包括基于该算法训练越来越大的模型。

但是大型模型只是 AGI 拼图的一部分。训练它们需要大量的数据集和大量的计算能力。

当机器学习社区开始揭示无监督学习的潜力时,数据不再是瓶颈。这与生成语言模型和少量任务转移一起,解决了 OpenAI 的“大数据集”问题。

他们只需要巨大的计算资源来训练和部署他们的模型,他们会很好地去。这也是他们在 2019 年与微软合作的原因。他们授权给这家大型科技公司,这样他们就可以在商业上使用 OpenAI 的一些模型,以换取他们所需的云计算基础设施和强大的 GPU。

但是 GPU 并不是专门为训练神经网络而构建的。游戏行业开发了这些用于图形处理的芯片,而人工智能行业只是利用了它适合并行计算的优势。OpenAI 想要最好的模型和最好的数据集,他们也想要最好的计算机芯片。GPU 是不够的。

许多公司也意识到了这一点,并开始在不损失效率或容量的情况下,构建内部专用芯片来训练神经网络。但是像 OpenAI 这样的纯软件公司,很难做到硬件设计和制作一体化。这就是为什么他们走了另一条路线:使用第三方 AI 专用芯片。

这里是大脑系统进入场景的地方。这家芯片公司已经在 2019 年建造了有史以来最大的芯片来训练大型神经网络。现在他们又做到了,OpenAI 将很好地利用这一令人惊叹的工程。

一个芯片和一个模型——WSE 二号和 GPT 四号

两周前,《连线》杂志发表了一篇文章披露了两条重要消息。

首先,脑波强化器又制造了市场上最大的芯片,晶圆级引擎二号(WSE-2)。它每边约 22 厘米,有 2.6 万亿个晶体管。相比之下,特斯拉的全新训练瓦片有 1.25 万亿个晶体管。

脑波强化器找到了一种有效浓缩计算能力的方法,因此 WSE-2 拥有 85 万个核心——计算单元——而典型的 GPU 只有几百个。他们还利用一种新颖的冷却系统解决了加热问题,并成功创建了高效的 I/O 数据流。

像 WSE-2 这样超级专业、超级昂贵、超级强大的芯片没有多少用处。训练大型神经网络就是其中之一。因此脑波强化器与 OpenAI 对话。

下面是第二条新闻。脑波强化器的首席执行官安德鲁·费尔德曼对《连线》说:“从与 OpenAI 的交谈中,GPT-4 将有大约 100 万亿个参数。[……]那要好几年才能准备好。”

自 GPT 3 以来,人们对 OpenAI 及其下一个版本有很多期待。现在我们知道它将在几年后问世,而且会非常大。它的大小将超过 x500 GPT 3 号。你没看错: x500。

GPT-4 将比去年震惊世界的语言模型大 500 倍。

我们能从 GPT-4 中期待什么?

100 万亿参数很多。为了理解这个数字有多大,让我们把它与我们的大脑进行比较。大脑有大约 800-1000 亿个神经元(GPT-3 的数量级)和大约 100 万亿个突触。

GPT-4 将拥有和大脑拥有的突触一样多的参数。

这样一个神经网络的庞大规模可能会带来我们只能想象的 GPT-3 的质的飞跃。用目前的提示方法,我们甚至可能无法测试系统的全部潜力。

然而,将人工神经网络与大脑进行比较是一件棘手的事情。这种比较似乎是公平的,但那只是因为我们假设人工神经元至少松散地基于生物神经元。发表在《神经元》杂志上的一项最新研究提出了相反的观点。他们发现,至少需要 5 层神经网络来模拟单个生物神经元的行为。每一个生物神经元大约有 1000 个人工神经元。

但是,即使 GPT 4 号没有我们的大脑强大,它肯定会留下一些惊喜。与 GPT-3 不同,它可能不仅仅是一个语言模型。OpenAI 的首席科学家 Ilya Sutskever 在 2020 年 12 月关于多模态的文章中暗示了这一点:

“2021 年,语言模型将开始意识到视觉世界。光是文字就能表达关于这个世界的大量信息,但它是不完整的,因为我们也生活在一个视觉世界里。”

我们已经用 DALL E 看到了一些,这是 GPT 3(120 亿个参数)的一个较小版本,专门针对文本-图像对进行了训练。OpenAI 当时说,“通过语言操纵视觉概念现在已经触手可及。”

OpenAI 一直在不停地开发 GPT 3 号的隐藏能力。达尔 E 是 GPT-3 的一个特例,非常像抄本。但它们不是绝对的改进,更像是特例。GPT-4 承诺更多。它承诺像 DALL E(文本图像)和 Codex(编码)这样的专家系统的深度与像 GPT-3(通用语言)这样的通用系统的宽度相结合。

其他类似人类的特征呢,比如推理或常识?在这方面,山姆·奥尔特曼说他们不确定,但他保持“乐观”

问题很多,回答很少。没有人知道 AGI 是否有可能。没有人知道如何建造它。没有人知道更大的神经网络是否会越来越接近它。但有一点是不可否认的:GPT 4 号将是一个值得关注的东西。

订阅 算法桥 。弥合算法和人之间的鸿沟。关于与你生活相关的人工智能的时事通讯。

您也可以直接支持我在 Medium 上的工作,并通过使用我的推荐链接 这里 成为会员来获得无限制的访问权限! :)

GPU 快!数据集是你的瓶颈

原文:https://towardsdatascience.com/gpus-are-fast-datasets-are-your-bottleneck-e5ac9bf2ad27?source=collection_archive---------15-----------------------

了解数据集如何成为您培训的瓶颈

糟糕的数据实践会减缓你的训练(图片来源: pixabay

如果你正在使用机器学习或深度学习,那么你可能会沉迷于确保你的所有代码都可以在 GPU 上运行,或者,对于勇敢的人来说,甚至可以在 TPU 上运行。

我讨厌带来坏消息,但你的模型可能已经非常适合 GPU 了!(特别是如果你使用像 PyTorch Lightning 这样的框架,它可以让你在 GPU 和 CPU 之间自动切换,而无需修改代码)。

真正的罪魁祸首是数据吞吐量。数据可能会以您可能没有意识到的微妙方式成为瓶颈。

CPU 上的转换

当处理深度学习的数据时,你非常非常可能以某种方式转换你的输入。例如,如果您处理图像,您可能会对这些图像应用转换管道。

例如,这是一个典型的计算机视觉管道:

图像转换(作者自己的)

肮脏的秘密是,今天这些转换在 CPU 上一次一个输入地被应用**…这意味着它们超级慢。如果您的模型允许,您可以在 GPU 上一次对一批数据应用相同的转换。**

Kornia 是一个帮助你在 GPU 内存中完成这些转换的库

磁盘吞吐量

下一个主要瓶颈是从磁盘读取样本的速度。不管你有世界上最快的型号和 GPU…你的数据必须从磁盘-> CPU → GPU。

GPU 机器内部(作者自己的)

你机器上的磁盘?最好是真正好的 SSD。

在云上,这变得更加相关…例如,如果您开始在云机器上运行几十个模型,这些模型都需要相同的数据,那么您将不得不为此构建非常优化的系统。在大规模训练时,S3 根本做不到!

当通过网格 AI 在 AWS 上运行云作业时,您可以使用网格数据存储库,这些数据存储库针对大规模运行进行了优化。只需创建一个数据存储:

当模型大规模运行时(甚至跨越数百个 GPU 和许多并发模型),grid 将确保对其进行优化。

然后,要在云上运行代码,只需使用网格运行

同时数据加载

使用 num_workers ( 作者自己的)预加载数据

另一个容易出错的地方是将数据集加载到机器学习代码中的类。PyTorch 有一个 Dataloader 抽象,负责批处理和预加载数据。但是,为了充分利用这一点,请确保使用 num_workers 参数,它将在后台自动预加载批处理

问题总是 num_workers 应该是什么?通常,它是你机器上 CPU 数量的倍数。

如果你使用 PyTorch Lightning 这样的框架,它甚至会为你推荐 num_workers!

Grad-CAM:为你的模特做决定的相机

原文:https://towardsdatascience.com/grad-cam-camera-for-your-models-decision-1ef69aae8fe7?source=collection_archive---------8-----------------------

🤖深度学习

灯光,凸轮,渐变!

来源: Grad-CAM:基于梯度定位的深度网络视觉解释

模型可解释性是 ML 中的热门话题之一,因为它对于理解黑盒神经网络和一般 ML 系统非常重要。它们有助于识别 ML 系统中的潜在偏差,这些偏差会导致失败或不满意的用户体验。

https://www.weforum.org/agenda/2021/07/ai-machine-learning-bias-discrimination/ https://news.mit.edu/2018/study-finds-gender-skin-type-bias-artificial-intelligence-systems-0212

你会不时地看到这些头条新闻,因为无偏见 ML 模型的重要性在现代世界一直在上升。模型可解释性技术实际上允许我们检查我们的 ML 系统的低效率,并且寻找潜在的偏见。

在这个故事中,我们将研究一种新的方法,Grad-CAM 技术来生成 CAM(类激活图),这有助于我们可视化我们的 CNN(或任何其他模型)在给定数据中的外观。

另外,您可以在官方的 Keras examples repo 中找到 Grad-CAM 实现(使用 TF)的源代码,

https://keras.io/examples/vision/grad_cam/

🧾目录

1。模型可解释性介绍

②**。我们可以用什么来解释模型的决定?**

3。输入 Grad-CAM

4。通过实验学习- Grad-CAM

— 4.1。了解设置

— 4.2。为每个特征图生成分数

— 4.3。生成 Grad-CAM 热图

5。用 Grad-CAM 进行反事实解释

6。模型决策中的检验偏差

第七期**。作者的下一步/更多故事**

8。参考文献

1.⚖模型可解释性简介

对黑盒进行逆向工程

图 1 →由图像分类 CNN 做出的推断。来源:作者图片

在阅读深度学习的入门书籍时,你可能已经注意到一件事,那就是他们将神经网络称为* 【黑盒】 。我们知道神经网络确实有一个定义良好的数学结构,那么为什么它们被称为“黑盒”呢?

原因是我们无法解码神经网络做出的决策。例如,让我们考虑一个简单的 CNN 的狗与猫分类器(见图 1 )。对于给定的图像,由模型做出的决定是由模型预测的类别。对于给定的图像,该模型决定该图像包含“狗”还是“猫”。

在我们的案例中,解码一个决定将有助于我们研究输入图像的特性或特征,这些特性或特征在产生那个决定中起了主要作用。如果我们的模型预测了“狗”这个类别,那么可能产生这个决定的一个重要特征可能是它的鼻子、耳朵或任何其他使它区别于“猫”这个类别的特征。我们想知道我们的模型基于什么来预测某个标签,比如“猫”或“狗”。

“为了建立对智能系统的信任,并让它们有意义地融入我们的日常生活,很明显,我们必须建立‘透明’的模型,能够解释它们为什么会预测它们预测的东西。”—来自 1

考虑到橙子和苹果的图像分类问题,这些水果的形状不是一个好的特征,因为它们可能有相似的形状。这可能会给我们*不正确的结果 ,当模型已经在现实世界中部署时。

为了更好地理解 ML 中模型可解释性的概念,请参考,

https://christophm.github.io/interpretable-ml-book/

为了识别这样的特征,也为了发现我们的 NN 模型对于特定决策的焦点,我们引入了模型可解释性的概念(参见**【2】))。它包括所有那些为我们的模型决策带来可解释性和透明性的技术。**

*“黑盒” : 在我们的上下文中,“黑盒”指的是决策无法被解码的模型。通俗地说,我们无法满意地回答这个问题,“为什么这个决定是由我们的模型做出的?。

*****不正确的结果:我们可能想要识别这样的特征,以便我们可以知道我们的模型的弱点

2.🎓我们如何解释模型的决定?

渐变是你所需要的,尤其是在 DL 中

为了更好地解释模型的决策,我们需要确定输入中的哪个要素对决策的贡献最大。在我们的狗与猫分类器中,如果预测一幅图像包含一只“猫”,那么模型会考虑哪些特征,如眼睛、身体颜色、耳朵,来产生这种预测?

嗯,我们可以分析梯度,以检查我们的模型侧重于生成某个预测。梯度有助于我们测量输入( x )对输出的影响(如 x 上的某些函数 f )。这就是我们所需要的,图像中对神经网络输出影响最大的部分或区域。

**https://medium.com/analytics-vidhya/understanding-gradients-in-machine-learning-60fff04c6400

我们将确保梯度调查区域的形象,这是重要的决策模型。这就是 Grad-CAM 方法中“Grad-”的含义,我们将在下一节探讨。**

3.进入 Grad CAM

嗯,这就是故事的全部!

**

来源: Grad-CAM:通过基于梯度的定位来自深度网络的视觉解释**

Grad-CAM 是由研究人员于 2017 年在论文*【Grad-CAM:通过基于梯度的定位来自深度网络的视觉解释】*** (参见**【1】)中引入的,以便为模型的某些输出生成类激活图(CAM)。他们的方法 Grad-CAM 也概括了【7】的方法,也可用于其他类型的模型。在他们的论文中,人们可以观察到图像字幕模型以及 VQA(视觉问答)模型的可视化。

**

首先,我们将从神经网络的基础上理解 Grad-CAM 的基本实现。因此,这个故事期望读者有一些关于神经网络,反向传播和卷积层的知识。

然后,我们将强调 Grad-CAM 的一些特性,这些特性有助于更好地理解我们的模型。所以,我们开始吧!

4.🧪通过实验学习——grad-cam

4.1.了解设置

理解包含模型决策信息的参数

图 2-> CNN 的底层。来源:作者图片

假设我们对猫和狗的图像分类问题做了一个简单的 CNN。我们的 CNN 将预测标签*‘猫’‘狗’的分布,为此我们需要在最后一个密集层上激活 softmax (参见图 2 )。我们的 CNN 由一些卷积层组成,后面是一个展平层,然后是一些 FC ( 全连通或密集)层。我们没有考虑所有卷积层,而是只分析最后一个卷积层的* 输出。 最后一个卷积层的输出被展平并传递给 FC 层。如图 2 所示,最后一个卷积层的输出是特征图,宽度 W 和高度 H 各一张。我们将它们统称为张量 A ,其中 A_k 将是k 个* 内核。*

图 3->AA_k 的形状来源:作者图片

要知道内核和过滤器的区别,你可以参考我的这个故事,

*https://pub.towardsai.net/kernels-vs-filters-demystified-1fd594e1c38d

在 softmax 之前,我们的 CNN 的输出是 y_c ,在猫与狗分类器的情况下, y_c 是一个形状为( 2 , 1 )的数组。这个数组的第一个和第二个元素分别是类“cat”和“dog”的输出。

图 4->y _ c 的构成来源:作者图片

正如我们之前讨论的,我们将利用渐变来解码模型的决策。为了计算梯度,我们需要一个函数和变量来计算它。我们的目的是研究特征图、和我们的 CNN、 y 的输出之间的关系。

每个特征图捕获输入图像的一些高级特征,并在做出最终决定 y 中有其贡献。让我们假设,我们需要解码预测类“cat”的决策,所以我们将只关注输入 y_cat 中的一个。中任何特征映射的任何变化都会导致 y_cat 值的变化。那么,为什么不计算 y_cat 相对于特征图 A_k 之一的梯度呢?

首先,让我们从下图中了解这个渐变的形状,

图 5->y _ catw . r . t .到 A_k .的渐变形状来源:作者图片

因此,我们感兴趣的梯度具有形状 W * H ,这与 A 中的特征图相同。我们还会用 ij 来索引这个矩阵的元素。我们可以构造这个矩阵的另一种方法是通过计算y _ catw . r . t .A _ k的元素之一的梯度,索引为 ij 。这个梯度是实数(标量),

图 6->y _ catw . r . t .到由 A_k 的 ij 索引的元素的渐变形状来源:图片由作者提供

如果我们计算所有这些可能的梯度,对于所有的值 ij 并将它们放置在一个 W * H 网格中,我们得到与图 5 中描述的相同的梯度。我们中的许多人可能已经知道这一点,但在这里提到它是很重要的,因为我们将在执行梯度的全局平均池中使用这一观察。

softmax :准确地说,我们将其称为 soft argmax,但大多数 ML 文献都求助于 softmax。参见【3】。***

最后一个卷积层的输出:我们选择最后一个卷积层的输出是有原因的。最后一个卷积层捕获高级特征,从而保存关于输入图像(馈送给 CNN 的图像)的重要区域的信息。Grad-CAM 研究论文【1】*的一个注解,

“我们发现 Grad-CAM 图随着我们移至更早的卷积层而变得越来越差,因为它们具有更小的感受域,并且只关注语义更少的局部特征。”

注意,我们总是可以使用 CNN 的其他层。当 CNN 的初始层捕获局部特征时,它们的梯度不会解释任何关于构成最终预测(或决策)的全局或高级特征的事情

4.2.为每个特征地图生成分数

根据每个特征图在最终输出中的影响对其进行加权

在上一节中,我们已经获得了一个渐变来研究 y_cat (甚至 y_dog ) w.r.t 到单个特征图 A_k 的变化。但我们的目标是研究从 y_cat w.r.t 到 A ,一个由所有 K 组成的张量特征图。中的一些特征映射可能对最终输出 y_cat 产生比其他更大的影响。如果我们能根据它们在 y_cat 中的影响,给这些特征图中的每一个分配一个分数就好了。如文中所述,我们可以计算图 6 中描述的梯度的所有元素的平均值,并将其用作该特征图的得分。**

**https://www.guidetomlandai.com/Global-Average-Pooling/

换句话说,我们正在执行特征映射的全局平均池化(GAP ),

图 7 →每个特征图的得分。来源:作者图片

特征图的分数越大,对 y_c 的影响越大。由于我们想要分析增加 y_c 值的特征,我们期望具有更高分数的特征图具有更多正梯度,总结了图 7 中的表达式。如图 6 所示,渐变的正值意味着增加像素(元素) ***A_i,j,***y _ c的值也会增加

4.3.生成 Grad-CAM 热图

将我们所有的知识整合起来制作热图

由于我们已经为中的每个特征图计算了分数,我们现在可以继续制作 Grad-CAM 热图,我们在故事的前面部分已经看到了。稍后,我们将把这张热图叠加到输入图像上,看看我们的模型看到了什么来生成某种预测。

使用这些分数,我们计算中所有 K 特征图的加权和,**

****

图 8 →计算特征图的加权和。来源:作者图片

最后,我们应用逐元素的 ReLU 操作(参见【4】)来获得最终的热图。

图 9-> Grad-CAM 热图。来源:作者图片

使用 ReLU 操作的原因在文章中有清楚的描述,

我们将 ReLU 应用于地图的线性组合,因为我们只对对感兴趣的类别有积极影响的特征感兴趣,即,为了增加 y_c,应该增加其强度的像素。

您可以从 Grad-CAM 上的官方 Keras 示例中找到将热图叠加到输入图像上的代码。**

5.🎎Grad-CAM 的反事实解释

思考你的模型没有想到的东西!

正如 Christoph Molnar 在“可解释的机器学习”中提到的(参见【5】),

一个反事实的解释以这样的形式描述了一个因果关系:“如果 X 没有发生,Y 也不会发生”

图 10 →如论文 1 所示的反事实解释。来源: Grad-CAM:通过基于梯度的定位来自深度网络的视觉解释

一个反事实的解释描述了当一个特定的决定被采取的时候什么不会发生。考虑到我们的猫与狗分类器的例子,我们想检查在给定输入图像的情况下,当模型的决定是“猫”或“狗”时,什么不会发生。

为了计算给定类别和模型的反事实解释,我们重复第 4 节中描述的相同过程。

**https://christophm.github.io/interpretable-ml-book/counterfactual.html

但是这一次,在对特征图 A_k 进行全局平均池化的同时,我们对梯度取反,比如,

图 11 →计算热图作为反事实解释的 alpha_c 表达式。来源: Grad-CAM:基于梯度定位的深度网络视觉解释

通过否定梯度,如图 11 所示,我们现在看到的是当像素值(或强度)增加时导致 y_c 减少的像素。生成的热图捕捉了模型在生成预测时没有关注的要素。**

6.👩模型决策中的🧑检验偏差

改进数据集和 ML 系统

**

图 12 →模型预测的偏差。来源: Grad-CAM:通过基于梯度的定位来自深度网络的视觉解释**

我们可以使用 Grad-CAM 来识别训练数据集传递的模型预测中的偏差。考虑到本文中的示例,假设我们已经根据从 ImageNet 数据集获取的图像训练了一个护士和医生图像分类器。该分类器在测试数据集上表现很好,但不能很好地泛化。我们是怎么知道的?查看图 12 中的 Grad-CAM 热图,我们的有偏模型,我们可以观察到该模型专注于预测“护士”和“医生”标签时看似无关紧要的不需要的特征(部分面部、头发)。该模型似乎学习基于性别的特征,这在我们的用例中是不合适的。

**https://www.foreseemed.com/blog/bias-in-machine-learning

正如论文中提到的,数据集是有偏差的。78%标为“医生”的图像包含男性,而 93%标为“护士”的图像包含女性。显然,数据集中存在的性别偏见被传递到了模型中。请注意,该模型在测试数据集上表现良好,准确率为 82%。

一旦我们知道我们的数据集中存在特定的偏差,我们就重新收集数据并重新训练模型。无偏模型,如图图 12 所示,捕捉准确的特征以识别包含“护士”和“医生”的图像。请注意,该模型侧重于识别“医生”形象的听诊器。**

7.👨‍🦱下一步/作者的更多故事

Grad-CAM 之后,许多研究小组提出了他们的方法,以获得更好的模型可解释性。

Grad-CAM++【8】和 Score-CAM【9】都是基于 Grad-CAM 的思想构建的。此外,我们还平滑了分数凸轮【10】

正如您将观察到的,模型可解释性一直是一个活跃的研究领域。因此,我们制作了一些新的“CAM ”,请在下面的评论中告诉我!

感谢您阅读这个故事!欢迎在下面的评论区发表你的评论/疑问/建议。

8.参考

  1. Grad-CAM:基于梯度定位的深度网络视觉解释
  2. 博客: 公平可解释的机器学习解决机器学习中的“黑箱”问题
  3. 维基百科: Softmax 函数
  4. 理解具有整流线性单元的深度神经网络
  5. 可解释的机器学习——让黑盒模型变得可解释的指南。,作者克里斯托夫·莫尔纳尔
  6. 数据集中的偏差:深度学习用于新冠肺炎检测|走向数据科学
  7. 学习深度特征进行判别定位
  8. Grad-CAM++:改进了对深度卷积网络的可视化解释
  9. Score-CAM:卷积神经网络的分数加权可视化解释
  10. SS-CAM:平滑的分数-CAM,用于更清晰的视觉特征定位***

用真实的例子和一些 Python 代码解释了梯度推进决策树

原文:https://towardsdatascience.com/gradient-boosted-decision-trees-explained-with-a-real-life-example-and-some-python-code-77cee4ccf5e?source=collection_archive---------2-----------------------

入门

梯度推进算法解决了机器学习中最大的问题之一:偏差

图片作者。

这是致力于基于树的算法系列的第三篇也是最后一篇文章,基于树的算法是一组广泛使用的监督机器学习算法。

第一篇文章讲的是 决策树 ,第二篇探讨的是 随机森林 。一切都用现实生活中的例子和一些 Python 代码来解释。

梯度推进算法解决了机器学习中最大的问题之一:偏差

决策树是一种简单而灵活的算法。简单到可以欠填充数据。

欠拟合决策树深度较低,这意味着它只对数据集进行几次分割,以尝试分离数据。因为它没有将数据集分成越来越多不同的观察值,所以它无法捕捉其中的真实模式。

简单模型(左)与复杂模型(右)的偏差。[ 作者图片 ]

说到基于树的算法随机森林是革命性的,因为它使用了打包来减少随机树集合模型的总体方差

在梯度增强算法中,用于控制偏差的技术称为增强。

在 20 世纪 80 年代末和 90 年代, Robert Schapire 和 Yoav Freund 开发了一种最流行的 Boosting 算法、 AdaBoost ,以解决欠拟合并减少偏差。

但是他们并不孤单。计算机科学和理论机器学习领域正乘着这股热情和开创性算法的浪潮,更多的科学家开始开发助推方法。

Friedman 探索了提升如何成为充分损失函数的优化方法。沙皮雷和弗罗因德从迈克尔·卡恩斯(Michael Kearns)提出的一个问题中获得了灵感,迈克尔·卡恩斯(Michael Kearns)提出了一个问题、一群学习能力差的学生能创造出一个学习能力强的学生吗?

在这种情况下, 学习器是比随机模型稍好的任何模型,并且永远不会有效地实现零训练误差。一个强学习者是相反的,一个可以被改进并有效地将训练误差降到零的模型。

大约在同一时间,杰罗姆·弗莱德曼也在进行助推实验。他最终开发了几种新算法,最流行的是梯度推进决策树。

这些科学家和其他科学家的巧妙努力为机器学习带来了充满活力的新篇章。它产生了强大的算法。其中许多至今仍然适用。

增压 101

助推的座右铭是结果大于各部分之和。

Boosting 基于这样一个假设,即找到几个简单的规则来进行预测要比找到一个适用于所有数据并生成最佳预测的规则容易得多。

Boosting 背后的直觉是,你多次训练同一个弱学习者,一个规则简单的模型。然后将它的预测组合成一个更准确的结果。该模型总是相同类型的,但是,每次,对于它错误分类的观察值,用不同的权重对其进行训练。

先前被错误分类的预测将对下一个弱学习者具有更大的权重,因此每个弱学习者将注意力集中在最难的观察上【1】。

*Boosting 算法赋予被错误分类的观测值更多的权重。(*图片作者 )

当你顺序组合不同的弱学习者时,每一个都会做出一些不正确的预测。但是他们会覆盖彼此的盲点,在其他学习者不擅长的地方做出更好的预测。每个模型从上一个模型的错误中慢慢学习

所有升压算法的共同点是什么

所有助推算法都是集成分类器或回归器,这取决于手头的任务,因为它们结合了几个模型的结果。

*m 个弱学习者的集合。(*图片由作者提供)

在回归任务的聚合步骤中,您可以计算每个观察值的所有预测的加权和。而在分类任务中,多数票决定分配哪个类。

创造一个增强的合奏

大多数算法集中于参数估计,寻找使其损失函数最小的参数。Boosting 算法侧重于函数估计。

弱学习器的集合实际上是一组将特征映射到目标并最小化损失函数的函数[3]。

每增加一个新的弱学习器都会最小化集合的损失函数。 ( 图片由作者提供)

并且因为用于寻找下一个 学习器的优化算法是梯度下降,损失函数必须是可微且凸的。

然而,这种时间梯度下降用于函数空间。

通常情况下,梯度下降从可微凸函数中的随机点开始,只有当它找到最小值时才会停止。

相同的概念被转化为具有梯度下降的 Boosting 算法,但是在函数空间中。

该算法从一个非常简单的弱学习器开始,例如,总是预测类 0。

随着每个弱学习器被添加到集合中,算法朝着正确的目标前进了一步,因为它只添加了最小化损失函数的弱学习器

*系综的损失函数。(*图片作者)

指数损失通常用于分类任务,而在回归任务中则是平方损失。

梯度增强决策树 vs Adaboost vs …

所有提升算法都有一个共同的原则,它们使用提升来创建一个学习器集合,然后再进行组合。但是每一种都有独特的特点,使它们更适合特定的任务。

例如,在梯度增强决策树中,弱学习器总是一棵决策树。

随机 梯度推进** 中,弗里德曼在算法中引入了随机性,类似于装袋中发生的情况。在每次迭代中,该算法不是使用不同权重的整个训练数据集,而是随机选取训练数据集的一个样本,并使用它来训练下一个学习者[4]。

Adaboost 在许多方面类似于梯度增强决策树,在某种意义上,你拥有训练数据集中每个观察的权重分布,并且在每次迭代中,算法根据前一个弱学习器的表现来调整这些权重。但是在每次迭代中,当它根据弱学习者的错误率选择一个新的学习率α时,它的适应性就开始发挥作用了。

现在,您已经对不同的 Boosting 算法有了更多的了解,让我们看看它们的实际应用吧!

🛩🏝使用 Boosting 算法减少模型偏差

计划假期很有挑战性。最难的部分,选择目的地。

但你是数据科学家。你相信机器学习可以对你的下一个度假目的地给出算法意见。

每当计划度假时,你总是会考虑到:

  • 假期的持续时间,
  • 个人预算,
  • 天气预报,
  • 如果你的大家庭要加入,
  • 如果你喜欢冒险,想要探索新的地方。

说到选择分类算法,你知道决策树据说是模仿人类做决策的方式。但是它有局限性,仅仅一个决策树不是一个非常强大的预测器。

如果你专注于控制偏差,而不是模型方差,随机森林会给你更好的结果。所以随机森林不是一个选项。

因为使用低偏差模型是你的目标,提升算法正是你要找的。

你要做的第一件事就是翻看你的旧笔记,收集一些关于你如何选择以前的度假目的地的数据。你收集了所有的信息,比如你当时的预算和假期的持续时间,以及你以前的目的地,通常是在海滩和乡村之间选择。

在下面的代码中,我将创建一个合成数据集来模拟这些数据。

创建包含 250 个观测值的合成数据集。 ( 图片由作者提供)

发现模型偏差

你想使用升压算法的全部原因是为了控制模型偏差。

在预测数值的回归任务中,偏差由以下等式描述:

在这种情况下,你只需要 在公式中插入数字

但是你正试图获得一个关于你下一个度假目的地的算法意见,一个分类任务。

为此,您可以使用错误分类率,即0–1 损失的平均值。

( 图片作者)

如果您的模型在训练集中有很高比例的错误分类观察值,这意味着它有很高的偏差。

Boosting 算法✅方法计算偏差✅

所以你从最简单的决策树算法开始。使用 ScikitLearns 的决策树分类器,您可以创建一个只对数据集进行两次分割的决策树。这就是为什么 max_depth=2 的原因。

为决策树定型的代码示例。 ( 图片由作者提供)

训练集中的平均错误分类率0–1 损失为 44%。这几乎和随机模型一样好!高偏置✅

决策树算法的 0–1 分类错误的结果。 ( 图片由作者提供)

现在你转向一个梯度增强分类器。

再次使用参数 max_depth once 将集合中每个弱学习器的深度设置为 1。在这种情况下,你正在训练尽可能最小的树,用机器学习的行话来说,这叫做决策树桩

就整体规模而言,你选择了一个相当随意的数字,210 棵树。这就是 GradientBoostingClassifier 方法中的参数 n_estimators

训练梯度增强决策树的代码示例。 ( 图片由作者提供)

梯度增强决策树确实减少了偏差。0-1 损失 32%就好多了!

梯度增强决策树算法的 0–1 错误分类结果。 ( 图片由作者提供)

好了,你建立了一个偏差相对较低的模型。但是你知道,除了梯度提升决策树之外,还有其他提升算法。

Adaboost 在预测你的下一个度假目的地方面会好到什么程度?

为 Adaboost 模型定型的代码示例。 ( 图片由作者提供)

在 Adaboost 的情况下,训练相同数量的树并没有减少多少偏差。但是它仍然把错误分类率从决策树观察到的 44%降低到了 38%。

Adaboost 算法的 0–1 错误分类错误的结果。 ( 图片作者)

当选择下一个度假目的地时,有了现成的数据集,梯度增强决策树是偏差最小的模型。

现在你所需要做的就是给算法你下次假期的所有信息,也就是持续时间,如果你想冒险的话。

算法会告诉你你的下一个假期是去海滩度假还是去乡下。

结论

现在,您可以自信地使用梯度推进决策树来预测您的下一个度假目的地。而不是只训练一个决策树。

梯度推进决策树与其他方法的不同之处在于:

  • 速度,该算法是内存高效的,所以你可以更快地做出预测。
  • 无需预处理在构建模型之前,您无需准备数据**。**
  • 数据健壮性该算法可以很好地处理所有类型的数据。

尽管它比决策树更复杂,但它继续分享基于树的算法的优点。

但是总有一个陷阱。梯度推进决策树做出两个重要的权衡:

  • 相对于较慢的训练,更快的预测,
  • 性能高于可解释性。

更快的预测与更慢的训练

尽管上面提到的优势之一是记忆效率,但那是在进行预测的时候。

该算法更复杂,并且按顺序构建每棵树。它的预测速度很快,但训练阶段的计算要求更高。

性能高于可解释性

与随机森林的情况类似,您需要牺牲性能来获得可解释性。

你将不再能够确切地看到算法如何分裂每个树节点以达到最终的预测。

希望你喜欢学习助推算法,问题的地址和最终使它们独一无二。

请务必查看这个基于树的机器学习算法系列的其他两篇文章。第一个探索决策树,第二个探索随机森林。

感谢阅读!

参考

  1. Schapire Robert E. (2002)机器学习的推进方法:概述
  2. 加雷斯·詹姆斯,丹妮拉·威滕,特雷弗·哈斯蒂,罗伯特·蒂布拉尼。(2013).统计学习导论:在 r .纽约的应用
  3. 弗里德曼,J.H .,2001 年。贪婪函数逼近:梯度推进机。统计年鉴,第 1189-1232 页。
  4. 弗里德曼,J.H .,1999 年。随机梯度增强。计算统计学和数据分析。38 第 367–368 页

用于分类的梯度增强树——最好的机器学习算法之一

原文:https://towardsdatascience.com/gradient-boosted-trees-for-classification-one-of-the-best-machine-learning-algorithms-35245dab03f2?source=collection_archive---------4-----------------------

机器学习

梯度增强在分类树中如何工作的分步指南

简介

梯度提升树是我最喜欢的算法之一,它被许多数据科学家广泛使用。无论您是为自己的项目建立模型,还是试图赢得 Kaggle 比赛,梯度推进总是值得考虑的。

梯度推进分类-添加更多决策树后模型预测概率如何变化。图片由作者提供。

在这个故事中,我将带您了解算法实际工作的细节,并提供 Python 代码资源供您在自己的项目中使用。

内容

  • 梯度提升树属于哪一类算法
  • 定义和基本原理
  • 基于示例的梯度增强树的解释
  • Python 代码资源

梯度提升属于哪一类算法?

梯度推进是一种基于树的算法,它位于机器学习的监督分支之下。注意,它既可以用于分类问题,也可以用于回归问题。然而,在这个故事中,我将把重点放在分类方面。

旁注,由于神经网络独特的机器学习方法,我已经将它们归为一类。然而,它们可以用于解决广泛的问题,包括但不限于分类和回归。下图是互动所以一定要点击👇在不同的类别上对进行放大并揭示更多的

机器学习算法分类。由作者创建的互动图表。

如果你喜欢数据科学和机器学习 ,请 订阅 每当我发布一个新故事时,你都会收到一封电子邮件。

定义和基础

为了理解梯度推进树是如何形成的,我们需要熟悉逻辑回归和决策树概念。

  • 回归树— 这一开始可能听起来很奇怪,但是梯度推进分类算法并不使用分类树。相反,它使用回归树。这是因为梯度增强树中的目标是残差,而不是类别标签。如果你对此感到困惑,也不要担心。一旦我们开始看这个例子,它会变得更清楚。
  • 残差——观测值与估计值(预测值)之差。我们将使用残差来计算 MSE 和树预测。
  • MSE(均方误差) —有多种方法可以找到树节点中的最佳分割,MSE 是回归树最常用的方法之一。因此,我们将在算法中使用 MSE。注意,“观察”和“预测”是每个数据记录的实际值和模型预测值。 *Residual = (Observed — Predicted).*

  • 比值比 —它只是事件和非事件数量之间的比率。比方说,如果您的数据包含 3 封垃圾邮件和 2 封非垃圾邮件,则几率为 3:2(十进制表示法为 1.5)。
  • Log(odds) —是比值比的自然对数。所以如果,the odds are 3:2 = 1.5, then log(odds) = log(1.5) = 0.405...
  • 概率与赔率 —很容易将赔率转换成概率,反之亦然。例如如果,the odds are 3:2, then the probability is 3/5 = 0.6.你可以用下面的等式在概率和赔率之间进行转换:

  • **通过 log(odds)——**表示的概率是我们进行模型计算时需要的最后一部分:

注意,如果你想对以上概念有更深入的理解,可以参考我讲的关于 Logistic 回归的故事:

梯度增强树——基于实例的解释

首先,让我与您分享一个过程图,以帮助您了解如何将每个步骤结合在一起,以产生一个梯度增强树模型。

梯度增强树的过程图。图片由作者提供。

开始

首先,让我们看看我们将使用的数据。

我们有来自澳大利亚天气数据集的 9 个观测值,其中“阵风速度”和“下午 3 点的湿度”作为我们的两个模型特征(独立变量)。“明日雨旗”是我们想用模型预测的。

注意,我们使用了一组很小的数据,因为我们想让解释更容易。但是,该算法同样适用于更大的数据集。

我们的数据包含明天下雨= 1 的 5 个观测值和明天下雨= 0 的 4 个观测值。

初始预测只是从所有观测值中得出的概率Probability = 5 / 9 = 0.56.同时,分别为每个观测值计算残差,在这种情况下,取两个值中的一个:Residual = Observed — Predicted = 1 — 0.56 = 0.44 or 0 — 0.56 = -0.56.

由于我们正在构建一个分类模型,我们还需要计算 log(odds)。当初始预测是Probability = 0.56时,初始叶的 log(odds)值是:Log(odds) = log(5/4) = log(1.25) = 0.22.注意,在构建树 1 之后,来自初始叶的 log(odds)将用于重新计算残差。

树 1

让我们现在建立第一棵树。下面是我们在这个具体例子中使用的模型超参数。在这个阶段,我只想强调其中的几个,但是我将在本文结尾的 Python 部分提供完整的 Python 代码。

虽然树的默认大小的最大深度是 3,但为了简化示例,我们将其设置为 1。这意味着我们正在建造的树将是决策树桩。总的来说,我们的模型将包含 3 个学习设置为 0.5 的决策树桩。

重要的是要重申,使用梯度增强,我们不是预测类别标签(下雨/不下雨),而是预测残差(见下表)。

让我们看看第一棵决策树(stump ),看看它是如何被创建的。

第一棵决策树(树桩)。图片由作者提供。

要回答的第一个问题是:“为什么算法选择了这个特定的节点分裂(下午 3 点的湿度≤ 45.5)?”

  • 通过使用“下午 3 点的湿度”计算每个可能分割的的 MSE,并使用“阵风速度”计算每个可能分割的的 MSE,确定最佳分割
  • 然后,该算法比较所有这些分割的并挑选具有最低 MSE 的分割。您可以在下面看到所选分割的 MSE 计算。

我们需要回答的第二个问题:“树内‘值’的用途是什么,它是如何计算的?”

  • 该算法使用叶“值”来重新计算残差,然后在构建下一棵树时将其用作目标。
  • “值”通过以下公式计算:

现在,让我们将所有这些知识付诸实践,并计算树中的每个指标:

第一个决策树(stump)中每个计算的细节。图片由作者提供。

在转到树 2 之前,剩下的最后一部分是重新计算残差(模型目标)。按照上述流程图中的步骤,我们需要重新计算每个观察值的残差:

**'New Log(odds)' = 'Log(odds) from the initial prediction' + 'Value from Tree 1' * 'Learning Rate'.**Obs1 = 0.22 + 0.643 * 0.5 = 0.54 <-- Example for leaf 2
Obs6 = 0.22 + -2.25 * 0.5 = -0.91 <-- Example for leaf 1

注意,上面的计算给出了新的日志(赔率)。然而,为了获得新的残差,我们首先需要使用以下公式将对数(赔率)转换回概率:

New Predicted Probability (Obs1) = 1/(1+e^(-0.54)) = 0.63
New Predicted Probability (Obs6) = 1/(1+e^(0.91)) = 0.29Note how the above probabilities are steps in the right direction for both observations.

最后,我们使用类别标签和新的预测概率来计算新的残差。

New Residual (Obs1) = 1 - 0.63 = 0.37
New Residual (Obs6) = 0 - 0.29 = -0.29

下表包含了所有观察值的重新计算值:

一个有趣的观察是,对 Obs7 和 Obs9 的新预测实际上比以前更糟糕。这就是为什么我们需要建立许多树的原因,因为有更多的树将导致所有观测预测的改进。你可以在本文开头的 gif 图片中看到这一点。

树 2

现在我们可以使用新的残差来构建第二棵树。注意,我不会再次列出所有的公式,因为它们与树 1 中的相同。但是,如果您想自己尝试计算,请记住使用在树 1 之后创建的表中的新值。

第二棵决策树(树桩)。图片由作者提供。

该算法将阵风风速≤49 确定为第二棵树中的最佳节点分裂,其中在叶 1 中有 8 个观察值(样本),而在叶 2 中只有 1 个观察值。

注意,当从一个大数据集构建一个更大的树时,建议限制一个叶子中允许的最小观察数量,以减少过度拟合的机会。

既然我们已经知道如何计算叶值,让我们直接寻找新的残差。

**'New Log(odds) T2' = 'Log(odds) from the initial prediction' + 'Value from Tree 1' * 'Learning Rate' + 'Value from Tree 2' * 'Learning Rate'.**Obs1 = 0.22 + 0.643 * 0.5 + 0.347 * 0.5 = 0.72 <-- T1L2-T2L1
Obs6 = 0.22 + -2.25 * 0.5 + 0.347 * 0.5 = -0.73 <-- T1L1-T2L1
Obs7 = 0.22 + 0.643 * 0.5 + -2.724 * 0.5 = -0.82 <-- T1L2-T2L2As before we convert the above to New Predicted ProbabilitesPred Prob T2 (Obs1) = 1/(1+e^(-0.72)) = 0.67
Pred Prob T2 (Obs6) = 1/(1+e^(0.73)) = 0.33
Pred Prob T2 (Obs7) = 1/(1+e^(0.82)) = 0.31

然后,我们计算新的残差,并将它们放入下表,用于 3 号树的目标:

第三棵树……

当构建额外的树时,重复相同的过程,直到达到指定的树数量,或者改进变得太小(低于某个阈值)。有趣的是,这是 3 号树桩的样子:

第三棵决策树(树桩)。图片由作者提供。

由于我们将我们的模型限制为只有 3 棵树,剩下的最后一部分是通过遵循上述方法结合对数(赔率)来获得最终的预测集。我相信你现在已经掌握了窍门,所以我就不重复了。相反,让我们直接进入 Python 代码。

Python 代码资源

既然你已经理解了梯度增强树是如何工作的,那么让我们使用完整的观察集来建立一个模型,但是使用与之前相同的两个特征。这样我们就可以生成下面的 3D 图来演示模型预测。

梯度增强树-预测平面。图片由作者提供。

设置

我们将使用以下数据和库:

  • 来自 Kaggle 的澳大利亚天气数据
  • Scikit-learn 库,用于将数据拆分成训练测试样本,建立梯度提升分类模型和模型评估
  • Plotly 用于数据可视化
  • 用于数据操作的熊猫和 Numpy

让我们导入所有的库:

然后我们从 Kaggle 获取澳大利亚的天气数据,你可以按照这个链接下载:https://www . ka ggle . com/jsphyg/weather-dataset-rattle-package。

我们接收数据并推导出一些新的变量用于模型中。

一小段 Kaggle 的澳大利亚天气数据做了一些修改。图片由作者提供。

模特培训

接下来,我们定义一个用于模型训练的函数,并运行模型以产生结果:

  • 步骤 1—将数据分为训练样本和测试样本
  • 步骤 2-设置模型参数并训练(拟合)模型
  • 步骤 3-使用我们的模型预测训练和测试数据上的类别标签
  • 步骤 4-生成模型摘要统计数据
  • 步骤 5-运行模型并显示结果

这些是上述函数返回的模型评估指标。

梯度增强树-模型结果。图片由作者提供。

最后,您可以使用 below 函数生成如上所示的 3D 图形。

结论

虽然这个故事很长,有很多细节,但梯度推进算法是数据科学家最需要理解的算法之一。我真诚地希望你在阅读它的时候感到愉快,并且这个算法对你来说不再神秘。

干杯!👏
索尔·多比拉斯

如果你已经花光了这个月的学习预算,下次请记得我。 我的个性化链接加盟媒介是:

https://solclover.com/membership

此外,如果您对本文感兴趣,这里还有一些关于替代算法的资源。

概率分布的梯度增强

原文:https://towardsdatascience.com/gradient-boosting-for-probability-distributions-6848a049d8a2?source=collection_archive---------29-----------------------

TLDR-关于多维输出的梯度增强以及如何将其应用于生成概率分布的一些想法。如果您需要的不仅仅是对 boosting 问题的点估计,本文可能会有所帮助。

伊恩·基夫在 Unsplash 上拍摄的照片

介绍

梯度推进可以说是当今最流行的机器学习算法之一。将多个弱学习者结合起来以产生一个强学习者似乎好得不像是真的。

然而,像 xgboost 这样的软件包经常在许多在线比赛中大放异彩。“只工作”的能力也使助推模型成为行业应用的有利工具。

像 lightGBM 或 said xgboost 这样的流行库为各种不同的用例提供了许多工具。然而,一个特殊的功能,即任意多输出升压,似乎还没有在这些包中可用。

快速的谷歌搜索会提供一些关于如何在这种情况下使用 sklearn 的 MultiOutputRegressor 的解释。

这种解决方案可以适用于合适的损失函数。尽管如此,还是有多输出处理器方法失败的情况。在这些情况下,我们需要更深入地了解渐变增强的背景,并手动实现一些元素。

“有些情况下,多输出梯度提升的直观解决方案会失败。在这些情况下,我们需要更深入地研究 boosting 算法的理论,并手动实现一些元素。”

因此,今天,我想给你一些想法,如何多输出梯度升压可以'手动'完成。重点是提升目标变量概率分布的多个参数。如果你对这个理论不感兴趣,可以跳过下面的部分。

理论(根据你的喜好跳过这一部分)

梯度增强背后的一般思想可以概括为三个步骤:

  1. 使用一个初始的浅薄的学习者来最小化给定的损失
  2. 让第二个浅层学习者学习预测相对于第一个浅层学习者预测的损失导数
  3. 将第二个学习者的预测乘以一个常数加到第一个学习者的预测上

选择 3)中的常数,使得组合预测最小化目标损失。之后,我们分别重复步骤 2)和 3 ),直到达到最大迭代次数。

:梯度提升的解释大多考虑 2)中的负导数。在标准梯度下降中,这是最小化所必需的。假定 3)中的学习常数可以具有任一符号,然而导数的符号可以忽略。

为了简单起见,让我们研究正导数。

对步骤 1)初始化的深入解释

从技术上讲,我们从迭代的初始预测开始 k=0 :

该初始预测可以是优化的常数

对于一个任意的损失。为了简单起见,我们将定义一个固定常数,而不首先优化它。

对于连续目标,损失函数通常是均方误差(MSE ),尽管这不是唯一的可能性。正如你在 xgboost 文档中看到的,有更多的选项可用。

对损失的唯一要求是,它必须相对于预测是可微的。

步骤 2)的深入解释)——梯度估计

显然,在这一步我们需要计算损失函数的导数。最简单的方法是从一般的公式开始,然后看一个具体的例子。对于任意的、可适当微分的损失,我们有:

接下来,让我们使用 MSE 作为一个实际的例子。MSE 很简单

将这个代入上面的导数公式,我们得到

因此,对 MSE 损失的梯度提升等同于使用估计残差。请注意,这不是梯度增强的一般情况。

下一次迭代学习者现在必须估计残差:

或者,对于一般情况:

这是针对数据集中的每个观测值进行的。为了清楚起见,让我们引入下标索引 i 来表示单个实例:

步骤 3)的深入解释)-模型更新

最后,我们需要更新完整的模型,如下所示:

这是通过对大小为 N 的完整数据集的简单优化问题来完成的:

我们可以向优化器提供梯度信息,或者使用例如scipy . optimize . minimize进行黑盒(没有显式导数)优化。

从这里开始,我们只需要重复上述步骤,直到我们得到一个总共有 K+1 个浅层学习者的模型:

就我个人而言,我发现如此简单的算法在实践中却能产生如此好的结果,这真是太神奇了。

多输出梯度升压

最后,我们可以切换到本文的实际主题。对于这种情况,我们最重要的元素是一个合适的多输出损失函数。这种损失必须能够将多个模型的输出压缩成一个量。

让我们为具有 M 个输出的多输出情况介绍一些符号:

多输出 MSE

多输出连续回归最简单的扩展是单个均方误差的总和:

现在,我们需要计算每个输出的导数

这基本上告诉我们,我们可以为每个输出运行单独的梯度增强实例。在这种情况下,多路输出处理器会立即工作。

为了证明为什么这种分离不一定是可能的,考虑一个目标类为 M 的多类问题。

多级梯度提升

我们使用多类交叉熵损失和 softmax 变换输出来获得有效的类概率。这产生了

对目标使用 onehot-encoding,上述和中只有一个元素非零。我们将此表示为 m^star ,并去掉总和:

现在,对于导数,我们得到

如您所见,每个输出的导数取决于所有其他渐变增强实例的输出。因此,不再可能仅仅将这个多输出问题作为单独的问题来处理。

这不同于上面的 MSE 例子。

更广泛的含义是,如果损失函数合适,我们只能使用以前的多输出处理器方法。一旦每个输出的导数不仅仅依赖于相应的输出,由此产生的梯度提升问题就变得不那么简单了。

"一旦每个输出的导数不仅仅依赖于相应的输出,由此产生的梯度提升问题就变得不可忽视."

对于多类问题,我们幸运地在标准库中准备了必要的算法。然而,更好的东西可能需要手动实现。

概率分布的梯度增强

其中一件更有趣的事情是预测条件概率分布的参数。考虑一个一般的概率回归设置:

我们的目标是在给定输入 x 的情况下,预测目标 y 的概率分布。在简单线性回归中,这通常如下所示:

这个条件概率只是一个高斯函数,其均值线性依赖于输入。方差被假定为常数。利用最大似然可以很容易地估计出各个参数。

现在,让我们用梯度推进模型来代替线性均值和恒定方差项:

为了优化我们的模型,我们使用负对数似然函数作为损失函数

请注意,对于两个分布参数,这确实是一个多输出问题。然而,目标变量本身仍然是一维的。

“条件高斯模型确实是一个两个分布参数的多输出问题。然而,目标变量本身仍然是一维的。”

最后,我们可以计算必要的导数。对于平均值的梯度提升模型,我们有:

对于标准差的梯度推进模型,我们有

理论部分到此结束。我们现在准备构建 POC 级别的实现。

快速演示

Numpy、sklearn 和 scipy 提供了我们进行概念验证所需的一切。

损失和导数函数

首先,我们定义简单正态分布的对数似然函数:

为了正确使用 scipy.optimize.minimize ,我们创建了一个包装函数。该包装器可以作为 lambda 函数插入到优化器中。

请注意,对数似然现在有负号,因为我们想要最大化对数似然。这对于使用实际最小化算法来最大化对数似然是必要的。

最后,我们需要损失函数的导数:

抽样资料

我们的数据生成过程应该是非线性的,并且具有非恒定的方差。为了可视化,我们还保持输入数据是一维的。

满足这些要求的一个简单过程是

这个选择完全是任意的。我们只想看看我们的模型在这一点上是否可行。

来自数据生成过程的样本数据(蓝点),具有非线性平均值(绿线)和非恒定方差(绿色区域表示平均值的两个标准偏差)

运行模型

为了尽可能简单,我们不使用任何 Python 类。如果您想在这个基本实现的基础上构建一些东西,请随意构建包装器类。

我们的基础学习者将是简单的决策树树桩,比如 100 个。

为了跟踪训练预测和γ,我们总共使用 4 个 numpy 数组。这意味着我们对均值和方差模型使用不同的伽玛。一方面,这引入了更多的过度拟合风险。

另一方面,增加灵活性可以改善结果。这是一个需要考虑的权衡,选择使用单独的 gammas 也是任意的。

我们将初始平均预测值设置为零;初始标准偏差预测被设置为 1。

此外,我们将所有训练预测存储在一个N×N _ trees矩阵中,并将所有伽马存储在一个1×N _ trees矩阵中。这使我们能够简单地对聚合的增强输出的各个预测和伽马列进行相乘和求和。

基础学习者将存储在列表中供以后使用。

现在我们可以运行训练循环。如前所述,我们将在这里使用 scipy.optimize.minimize 。为了不使这篇文章过于臃肿,我们把它作为一个黑盒优化器。这意味着我们不向函数提供任何梯度或 hessian 信息。

在生产就绪的实现中,我们可能希望这样做—结果可能会改善。

评估过程类似于培训过程:

预测的均值函数(红线)和相应的方差(红色区域=均值的 2 个标准差)

均值和标准差的结果看起来都是合理的。我们可能会通过更多的微调来改善结果,以下是一些想法:

  • 使用更强大的优化程序如前所述,我们应该为优化器提供理想的梯度和 hessian 函数。像 tensorflow 和 PyTorch 这样的自动签名包可以自动完成这项工作。
  • 微调模型超参数树的数量和它们各自的深度将是明显的起点。
  • 使用更复杂的提升算法我们的提升算法非常简单。有许多变化和进步可以轻松超越这种实现。

这些考虑可能有助于进一步改善我们的结果。

结论——我们还能做什么?

正态分布可能是最明显的选择,但是还有许多更有趣的选择。

例如,考虑高斯分布的偏斜版本。实际上,大多数数据远非围绕平均值对称。解释这种行为可能会相当有利。

然而,随着分布参数数量的增加,我们无疑会增加过度拟合的风险。我们的目标分布中的每个新参数都意味着另一个梯度推进模型。

为了减少这种风险,正规化是必要的。最简单的正则化形式可能是在我们的算法中减少树桩的数量( n_trees )。在我们考虑更复杂的正则化方法之前,这已经足够了。

总而言之,如果您需要评估目标变量中的噪声,带有概率输出的梯度提升会非常有帮助。我在这里写了另外两篇文章这里写了和这里写了为什么我认为这是一个好主意。

“总而言之,如果您需要评估目标变量中的噪声,带有概率输出的梯度提升会非常有帮助。”

如果你有任何问题或反馈,请在评论中告诉我。

原载于 2021 年 7 月 26 日【https://sarem-seitz.com】

梯度下降算法——深度探索

原文:https://towardsdatascience.com/gradient-descent-algorithm-a-deep-dive-cf04e8115f21?source=collection_archive---------0-----------------------

梯度下降法为机器学习和深度学习技术奠定了基础。让我们来探索它是如何工作的,何时使用它,以及它对各种功能的表现如何。

来自 Pixabay 的 JohnsonMartin 图片

1.介绍

梯度下降 (GD)是一种迭代一阶优化算法,用于寻找给定函数的局部最小值/最大值。这种方法通常用于机器学习 (ML)和深度学习 (DL),以最小化成本/损失函数(例如,在线性回归中)。由于其重要性和易于实现,这种算法通常在几乎所有机器学习课程的开始时教授。

然而,它的使用不仅限于 ML/DL,它还被广泛应用于以下领域:

  • 控制工程(机器人,化学等。)
  • 电脑游戏
  • 机械工程

这就是为什么今天我们将深入探讨一阶梯度下降算法的数学、实现和行为。我们将直接导航自定义(成本)函数以找到其最小值,因此不会像典型的 ML 教程中那样有底层数据——我们将在函数的形状方面更加灵活。

这种方法是在现代计算机时代之前提出的,其间有一个密集的开发,导致了它的许多改进版本,但在本文中,我们将使用 Python 中实现的基本/普通梯度下降。

2.功能需求

梯度下降算法并不适用于所有函数。有两个具体要求。功能必须是:

  • 可微
  • 凸面

首先,它必须是可微的是什么意思?如果一个函数是可微的,那么它对定义域中的每个点都有导数——不是所有的函数都满足这些标准。首先,让我们看一些满足这个标准的函数的例子:

可微函数的例子;作者图片

典型的不可微函数有一个台阶,一个尖点或一个不连续点:

不可微函数的例子;作者图片

下一个要求— 函数必须是凸的。对于一元函数,这意味着连接两个函数点的线段位于曲线上或曲线上方(不与曲线相交)。如果是,这意味着它有一个局部最小值,而不是一个全局最小值。

数学上,对于位于函数曲线上的两点 x₁、x₂,该条件表示为:

其中,λ表示剖面线上的点的位置,其值必须介于 0(左点)和 1(右点)之间,例如,λ=0.5 表示位置在中间。

下面有两个带有示例剖面线的函数。

示例性凸函数和非凸函数;作者图片

从数学上检查一元函数是否凸的另一种方法是计算二阶导数,并检查其值是否总是大于 0。

我们来做一个简单的例子(警告:前方微积分!)。

GIF via giphy

让我们研究一个简单的二次函数,由下式给出:

它一阶和二阶导数是:

因为二阶导数总是大于 0,所以我们的函数是严格凸的。

也可以使用准凸函数和梯度下降算法。然而,通常它们有所谓的鞍点(也称为极大极小点),算法可能会在这里卡住(我们将在本文后面演示)。准凸函数的一个例子是:

让我们在这里停一会儿。我们看到,在 x=0 和 x=1.5 时,一阶导数等于零。这些位置是函数极值(最小值或最大值)的候选位置,那里的斜率为零。但是首先我们要先检查二阶导数。

对于 x=0x=1 ,该表达式的值为零。这些位置被称为拐点——曲率改变符号的地方——意味着它从凸变到凹,或者反之亦然。通过分析这个等式,我们得出结论:

  • 对于 x <0: function is convex
  • for 0
  • for x> 1:函数再次凸

现在我们看到点 x=0 的一阶和二阶导数都等于 0,这意味着这是一个鞍点,而点 x=1.5 是一个全局最小值。

让我们看看这个函数的图形。根据之前的计算,鞍点在 x=0 处,最小值在 x=1.5 处。

具有鞍点的半凸函数;作者图片

对于多元函数来说,检查一个点是否是鞍点最合适的方法是计算一个 Hessian 矩阵,这涉及到一些更复杂的计算,超出了本文的范围。

二元函数中鞍点的例子如下所示。

Nicoguaro,CC BY 3.0,通过维基共享

3.梯度

在开始编写代码之前,还有一件事必须解释一下——什么是梯度。直观上,它是曲线在指定方向上给定点的斜率。

为一元函数的情况下,它只是在选定点的一阶导数。在是多元函数的情况下,它是在每个主方向(沿着可变轴)上导数向量。因为我们只对一个轴上的斜率感兴趣,而不关心其他的,所以这些导数叫做偏导数**。**

n 维函数 f(x)在给定点 p 的梯度定义如下:

倒三角是所谓的 nabla 符号,你读它“del”。为了更好地理解如何计算,让我们手动计算一个示例性的二维函数。

3D 绘图;作者图片

假设我们对点 p(10,10)处的梯度感兴趣:

因此:

通过查看这些值,我们得出结论,y 轴上的斜率要陡两倍。

4.梯度下降算法

梯度下降算法使用当前位置的梯度迭代计算下一个点,缩放它(通过学习率)并从当前位置减去获得的值(进行一步)。它减去了这个值,因为我们想要最小化这个函数(最大化它就是相加)。这个过程可以写成:

有一个重要的参数 η ,它缩放梯度,从而控制步长。在机器学习中,它被称为学习率,对性能有很大的影响。

  • 学习率越小,GD 收敛的时间越长,或者在达到最优点之前可能达到最大迭代
  • 如果学习率太大,算法可能不会收敛到最优点(跳跃),甚至完全发散。

综上所述,梯度下降法的步骤是:

  1. 选择一个起点(初始化)
  2. 计算该点的梯度
  3. 在与梯度相反的方向上按比例步进(目标:最小化)
  4. 重复第 2 点和第 3 点,直到满足其中一个标准:
  • 已达到最大迭代次数
  • 步长小于公差(由于缩放或小梯度)。

下面是梯度下降算法的示例性实现(具有步长跟踪):

这个函数有 5 个参数:

1.在我们的例子中,我们手动定义它,但是在实践中,它通常是一个随机的初始化

2.梯度函数 n -必须提前指定

3.学习率 -步长的比例因子

4.最大迭代次数

5.有条件停止算法的容差(在这种情况下,默认值为 0.01)

5.示例 1 —二次函数

让我们用一个简单的二次函数来定义:

因为梯度函数是一元函数,所以它是:

让我们用 Python 写这些函数:

对于这个函数,通过取 0.1 的学习率和 x=9 的起点,我们可以很容易地手工计算每一步。让我们开始前三步:

python 函数由以下函数调用:

下面的动画显示了学习率为 0.1 和 0.8 时 GD 算法所采取的步骤。如你所见,对于较小的学习速率,随着算法接近最小值,步长逐渐变小。对于更大的学习速率,它是在收敛之前从一边跳到另一边。

GD 为小学习率和大学习率采取的前 10 个步骤;作者图片

不同学习速率下的轨迹、迭代次数和最终收敛结果(在公差范围内)如下所示:

不同学习速度的结果;作者图片

6。示例 2 —具有鞍点的函数

现在让我们看看这个算法将如何处理我们之前用数学方法研究过的半凸函数。

下面是两种学习速度和两种不同起点的结果。

GD 试图逃离一个鞍点;作者图片

下面是一个学习率为 0.4,起点为 x=-0.5 的动画。

GD 试图逃离一个鞍点的动画;作者图片

现在你可以看到,鞍点的存在对 GD 等一阶梯度下降算法提出了真正的挑战,并且不能保证获得全局最小值。二阶算法更好地处理这些情况(例如,牛顿-拉夫森方法)。

鞍点的研究以及如何逃离它们是正在进行的研究的主题,并且提出了各种解决方案。例如,金池和 m .乔丹提出了一种扰动梯度下降算法——你可以在他们的博客文章中找到细节。

7.摘要

在本文中,我们检查了梯度体面算法如何工作,何时可以使用它,以及使用它时有哪些常见的挑战。我希望这将是一个很好的起点,让你探索更先进的基于梯度的优化方法,如动量或内斯特罗夫(加速)梯度下降,RMSprop,ADAM 或二阶方法,如牛顿-拉尔夫森算法。

深度神经网络中的动态梯度编辑

原文:https://towardsdatascience.com/gradient-editing-on-the-fly-in-deep-neural-networks-4f060360e95d?source=collection_archive---------14-----------------------

介绍优化深度神经网络时调整梯度的不同方法,包括梯度裁剪、扰动、掩蔽和替换

梯度是深度学习世界中的一个重要组成部分。它支持最受欢迎的算法之一——梯度下降算法,该算法通过根据模型成本相对于这些参数的当前梯度反复更改神经网络的值来优化神经网络的参数。虽然在每次更新中是一种简单的方法,但梯度下降算法家族,特别是随机梯度下降,一直是深度学习模型良好泛化性能的驱动力之一。

然而,人们更多地关注算法本身,而不是梯度。部分原因是梯度大部分是自动计算的,并被插入到优化过程中。这种自动计算机制,例如使用 PyTorch 中的自动签名模块,省去了手动推导的麻烦,从而使我们更容易专注于整体算法。本系列教程旨在弥补这一差距,并演示如何动态编辑梯度,以便我们可以在利用自动微分的同时获得梯度。对于本系列的第 1 部分,我们将介绍整个模型训练过程,作为后面部分的必要背景知识。

如图 1 所示,典型的模型训练过程由四个部分组成:数据、模型、成本和优化过程。模型训练过程从一些训练数据开始。在监督学习任务中,训练数据由输入-输出对组成。每个输入条目可以包含从不同角度描述一个观察的多个特征。相应的输出包含目标标签,作为指导训练过程的正确答案。模型训练旨在生成一个映射函数,一个模型,它将给定的输入正确地映射到相应的输出。

图 1 典型模型训练过程示例。工作流从可用的训练数据开始,并逐渐调整模型。调整过程需要将模型预测与目标标签进行匹配,其中通过特定的成本函数来测量差距,并将其用作下一轮调整的反馈。每次调整都会产生一个新的模型,我们希望寻找成本最低的模型。图片由作者提供。

数据

模型训练过程从一些训练数据开始。在监督学习任务中,训练数据由输入-输出对组成。每个输入条目可以包含从不同角度描述一个观察的多个特征。相应的输出包含目标标签,作为指导训练过程的正确答案。我们将以 MNIST 为例。以下代码下载并加载 MNIST 数据集。

*# download MNIST dataset***from** torchvision **import** datasets**from** torchvision.transforms **import** ToTensortrain_data **=** datasets**.**MNIST(root **=** 'data',train **=** **True**,transform **=** ToTensor(),download **=** **True**,)test_data **=** datasets**.**MNIST(root **=** 'data',train **=** **False**,transform **=** ToTensor())*# preparing data for training with DataLoaders***from** torch.utils.data **import** DataLoaderloaders **=** {'train' : torch**.**utils**.**data**.**DataLoader(train_data, *# data source to be loaded*batch_size**=**100, *#  the number of training samples used in one iteration*shuffle**=True**), *# samples are shuffled and loaded in batches*'test'  : torch**.**utils**.**data**.**DataLoader(test_data,batch_size**=**100,shuffle**=True**)}

模型

经过训练的模型由两部分组成:参数和体系结构。参数是模型不可或缺的组成部分,而体系结构指定了这些组件如何与输入数据进行交互以生成最终的预测输出。为了说明的目的,我们将定义一个简单的两层全连接神经网络。

**import** torch.nn **as** nn**class** simpleNN(nn**.**Module):**def** __init__(self):super(simpleNN, self)**.**__init__()self**.**fc1 **=** nn**.**Linear(28*****28, 100)self**.**fc2 **=** nn**.**Linear(100, 10)self**.**relu **=** nn**.**ReLU()**def** forward(self, x):x **=** x**.**view(x**.**size(0), **-**1)x **=** self**.**fc1(x)x **=** self**.**relu(x)x **=** self**.**fc2(x)x **=** self**.**relu(x)**return** x

我们可以使用 torchsummary 包获得模型架构的概要。

**from** torchsummary **import** summarysummary(model, input_size**=**(1, 28, 28))

图 2 模型架构。图片作者。

费用

然后,将该预测值与地面实况的目标标签进行比较,以共同产生标量误差度量。这里,误差表示当前成本,即预测值和实际值之间的距离。

在计算成本时,我们将首先使用 softmax 转换将原始预测集转换为概率,然后使用交叉熵损失(CEL)导出单值成本度量。CEL 是分类任务中常用的成本度量,因为它直观地符合好的和坏的预测之间的预期成本行为。请参见图 3 和图 4,了解转型和成本构建流程的详细信息。

图 3 Softmax 变换。图片作者。

图 4 交叉熵损失。图片作者。

我们可以使用下面图 5 中的两个简单例子来验证成本构成。

图 5 验证交叉熵损失的直观性。图片作者。

最佳化

在特定的优化过程之后,训练过程调整模型参数,并且有时调整架构以降低训练成本。调整权重后,再次计算新的误差,形成反馈环。最广泛使用的优化程序是梯度下降,如下图 6 所示。

图 6 梯度下降算法。图片作者。

我们可以将优化部分定义如下。

*# Define the procedure***from** torch **import** optimlr **=** 0.01optimizer **=** optim**.**SGD(model**.**parameters(), lr **=** lr)

一次迭代的训练

让我们在一次迭代中结合上述组件,观察输出层偏差的变化。

图 7 一次迭代的训练。图片作者。

图 7 显示,在一次迭代后,使用相应的梯度改变了偏差。由于在优化过程中明确使用了梯度,我们可以想出不同的方法来编辑它们,包括剪辑、遮罩、扰动和替换。

渐变剪辑

可能是避免梯度爆炸和递减问题的最广泛使用的技术。

图 8 渐变裁剪。图片作者。

梯度掩蔽

应用一系列二进制掩码来确定需要进行梯度更新的特定权重集。

图 9 渐变遮罩。图片作者。

梯度扰动

噪声已被证明非常有助于提高模型的泛化性能,包括向数据、标签和优化过程本身注入噪声。在这里,我们展示了如何添加噪声和扰动梯度,这将是一个有趣的实验领域,并观察其对性能的影响。

图 10 梯度扰动。图片作者。

梯度置换

替换渐变也是另一个有趣的实验。取代依赖梯度下降机制本身,我们可以设计一些新的机制来提出(希望)更明智的梯度,从而更好地将更新导向全局最优。

图 11 渐变替换。图片作者。

完整详细的演练,请访问下面的 youTube 视频。

完整的笔记本可以通过下面的链接访问。

https://github.com/jackliu333/gradient_editing/blob/main/Gradient_editing_on_the_fly.ipynb

梯度核回归

原文:https://towardsdatascience.com/gradient-kernel-regression-e431f0f29750?source=collection_archive---------26-----------------------

未经训练的装配

在这篇文章中,使用神经正切核[1,2]展示了一个令人惊讶的结果。这个内核用于执行内核回归。令人惊讶的是,回归的准确性独立于底层网络的准确性。

为了得到那个结果,并欣赏它所带来的惊喜,我们需要研究内核的构造以及它是如何在内核回归模型中使用的。

梯度核回归,因为它不需要通过梯度下降来进行艰苦的训练,所以可以作为模型架构设计的有用工具。这通过一个使用迁移学习的例子来说明。

梯度核

在1中,作者在通过使用随机梯度下降训练的深度神经网络进行监督学习的背景下,引入了他们所谓的路径核。路径核测量两个输入点的相似性, x ᵢ和 x ⱼ为,

在两个点处评估的网络梯度之间的内积,在梯度下降期间在c(t)上积分,网络 f 的参数 w 所采用的路径。路径核是神经正切核【3】的特例,

在求和发生的参数中, w ₚ更为通用。

给定一个数据集{ x ᵢ,yᵢ} for 1≤In,以及一个模型f(x;w)w 参数化(例如一个神经网络),在 wx ᵢ、 x ⱼ的梯度核计算为:

这只是在参数向量 w 的单个值处评估的神经正切内核。使用术语梯度核是因为没有具体要求基础模型是神经网络。请注意,我们使用的是单变量值函数 f (例如二进制分类器),然而,将所描述的方法扩展到多变量函数 f 是非常简单的。

梯度核回归

一旦拥有了一个核函数,就很容易在回归环境中使用这个核函数。也就是说,为了符合表格的功能,

一个数据集。然而,有几个实际问题需要解决。

现代神经网络模型可以拥有包含数百万个示例的数据集。形成全核矩阵需要 O(n ) 空间来存储这个矩阵。降低这些要求的一个众所周知的方法是选择一个小得多的例子子集作为基本例子。这将是这里采取的方法。基示例的选择本身是一个有趣且深入的研究主题,但这将被忽略,基示例将简单地从训练示例集中随机选择。

我们感兴趣的是检查当参数 w 被应用于网络的梯度下降修改时,使用梯度核的核回归如何执行。不幸的是,梯度下降使梯度核陷入病态和数值不稳定的状态。为了解决这个问题,不直接使用梯度核,而是将其归一化为余弦相似形式,

其具有更好的数值特性。

梯度核回归执行和评估如下。给定一个数据集的例子点{ x ᵢ, y ᵢ},一个函数f(x;w)w 参数化我们把例子分成训练集和测试集。从训练集中选择一组基本示例。线性回归模型,

通过最小二乘法来拟合训练数据,

并且在测试数据上测量其误差,

令人感兴趣的是误差对基础模型参数 w 的依赖性。

MNIST 的例子

众所周知的 MNIST 数据集[4]用于研究梯度核回归的性能。MNIST 数据由手写数字图像和每个图像的类别标签组成。

使用的底层神经网络模型取自 PyTorch 机器学习库[5]中提供的示例。它由 2 个卷积层和 2 个全连接层组成。如给定的,该模型产生对应于多类数字分类问题的 10 维输出。该模型被改变为二元分类器。选择的数据是两位数(“1”和“7”),分类任务是区分 1 和 7。

对于实验,选择了 1000 个训练样本和 1000 个测试样本。两组各有 500 个 1 和 500 个 7。基本示例是从训练集中随机选择的,并且这些示例也与 50 个 1 和 50 个 7 相平衡。使用默认 PyTorch 设置用随机值初始化网络。

进行梯度下降的重复时期。每个历元对应于训练数据的一次完整通过,在这种情况下,包括由随机批次的 100 个
训练示例驱动的 10 个梯度下降步骤。对于每个时期,对训练数据进行线性回归拟合,并对测试数据进行测试,如前一节所述。测试结果通过准确度分数来总结,该准确度分数将回归函数大于 0.5 的实例指定为“1”级,将回归函数小于 0.5 的实例指定为“7”级。

令人惊讶的是,梯度核回归的精度与底层网络的精度无关。基础网络(蓝线)以随机参数开始,因此在开始时具有随机的 50%精度。但是梯度核回归(橙色线)从一开始就以 99%的准确率工作。随着梯度下降时期的进行,基础网络逐渐变得更好,但它最多只能匹配梯度核回归在整个路径上保持的精度水平。

梯度核回归的准确性不依赖于基础模型参数的质量。它适用于随机参数设置,也适用于训练参数设置。

CIFAR10 示例

上一节的结果表明,梯度核回归可以揭示网络固有的准确性,而不需要训练和所有的时间、精力和不确定性。因此,它可以作为设计网络架构的强大工具。

例如,迁移学习是一种采用现有模型并将其用作新模型的起点的方法。具体而言,通过用针对新问题定制的层替换其最终层,可以修改基于数百万个示例训练的大型复杂深度神经网络。那么只有这个新层在一些较小的数据集上被训练。梯度核回归可用于有效地探索该最终层的可能形式。

这里迁移学习应用于 ResNet-50 6深度神经网络(如 PyTorch 中所提供的)。ResNet-50 网络的最后一层被替换为两个完全连接的层,并且最终输出被修改为二进制分类器。

这个修改后的网络被训练来对来自 CIFAR10 [7]图像数据集(也在 PyTorch 中提供)的鸟和猫图像进行分类。迁移学习为梯度核回归方法提供了一个有趣的用例。非常宽/深的网络的梯度可能涉及大量参数(ResNet-50 有超过 2000 万个)。对每个训练示例的这么多参数取内积在计算上是昂贵的(尽管,必须注意,比梯度下降训练需要的少得多)。迁移学习只训练添加到网络的附加层,对于这里的例子,仅超过一百万个参数。

实验装置与 MNIST 的例子相同。从 CIFAR10 数据中随机选择 1000 个训练和 1000 个测试示例。两个数据集都有 500 张鸟和 500 张猫的图片。100 个训练样本被作为基本样本,还平衡了 50 个鸟和 50 个猫的图像。再次,执行 9 个梯度下降时期,并且在每个时期构建核。

该图按时期显示了核回归和神经网络的精度。如前所述,梯度核回归支配着训练好的神经网络的性能。

梯度核回归的准确性可以用作在迁移学习问题中比较训练层的不同架构的容易计算的基准。

结论

这里给出的例子证明了梯度核回归可以产生与通过实际经历梯度下降训练过程获得的模型一样好或者更好的性能。

梯度核回归提供了一种测试网络性能的机制,而无需经历梯度下降训练过程。当使用梯度下降进行训练时,这一侧会遇到许多复杂的问题。当使用基于梯度核的简单线性回归时,学习率选择和调度、停止规则和缺乏收敛性都消失了。

1 通过梯度下降学习的每个模型近似为一个核机器

[2] 深度神经网络的神经正切核的平均场行为

[3] 神经正切核:神经网络中的收敛和泛化

[4]MNIST 数据集

[5] PyTorch:命令式的高性能深度学习库

6 用于图像识别的深度残差学习

[7]CIFAR-10 数据集

STEM 课程计划内容生成的 GPT-3 评分

原文:https://towardsdatascience.com/grading-gpt-3-for-stem-lesson-plan-content-generation-c8d9d1f59806?source=collection_archive---------37-----------------------

我在为 STEM 课程生成课程内容方面的 GPT 综合成绩为 3 分。分数更多地反映了我产生正确提示的技能。图片由作者提供。

本博客描述了如何使用 OpenAI GPT-3 生成式自然语言处理模型为 STEM 课程生成教案内容。我们将向您展示课程的哪些组成部分易于生成,以及如何调整提示以获得更好的结果。我们还将展示如何调整生成的内容,使其适合您的教室。

这些过程也应该为非 STEM 课程生成内容。然而,我的重点是帮助内容管理者从简单的文本描述中生成技术内容,如样本代码、数学公式 (LaTeX)、图表、化学符号和建筑图。这就是为什么我在标题中指出了 STEM 课程。

自 2020 年 12 月初以来,我一直拥有我宝贵的 GPT-3 许可证密钥。假期里我很忙,为没有花更多的时间在钥匙上而感到有点内疚。但现在,我已经开始尝试为 STEM 课程制定教案,这是我为双城编码俱乐部在线编码俱乐部做志愿者工作的一部分。说实话,这真的很有趣!

正如你将看到的,现在并不是所有的结果都很好,但我学到了很多关于知识如何编码在巨大的 175B 参数 GPT-3 达夫尼奇模型中,以及如何哄它得到我想要的。使用这些复杂的工具需要时间来获得一个直观的感觉,当你没有产生你希望的结果时,你可以期待什么以及如何解决问题。我的生成器的失败更多地反映了我对如何设计高质量提示的无知。

这个博客是关于使用人工智能、自然语言处理(NLP)和知识图来支持在线编码俱乐部服务提供商(CCSPs)的一系列博客的一部分。其他相关博客包括:

  • 利用人工智能生成教案
  • 预测在线编码俱乐部的成功
  • 在线编码俱乐部将如何改变教育
  • 迷失在【知识】空间

这个名单不包括 AI 赛车联盟上的博客。COVID 已经暂停了这个项目,直到我们的编码俱乐部在虚拟环境中稳定下来。

在这个博客中,我正在定义 STEM 课程的材料,它由一系列课程主题组成。每一课的主题都被分成一系列的子主题概念。每个子主题概念包括一系列其他详细的概念、示例程序、测验和资源。这些内容级别如下图 1 所示:

图 1:编码俱乐部服务提供商(CCSPs)必须快速生成为特定主题和年级定制的高质量内容。图片由作者提供。

以下是我做过的一些事情,主要按照 GPT 的表现排序:

  1. 对于给定的课程,我们已经生成了课程主题的大纲。这些课程主题应该适合每个受众的年龄。
  2. 对于每节课的主题,我们已经生成了每节课的子主题列表。本课程的子主题也针对适龄受众进行了调整。
  3. 接下来,在一个课程主题中,我们可以生成一个更细粒度的概念列表来涵盖该课程。
  4. 在一门课程中,我们还可以生成一个概念词汇表,其中包含一门课程的定义。
  5. 对于给定的课程主题,我们可以为测验生成简答题/答案对。
  6. 我还将为测验创建一个课程主题选择题示例。承认,GPT-3 确实正确地产生了问题和正确的反应。然而,不正确的回答不是很好,需要一个真实的人一段时间才能在课堂上有用。显然,GPT-3 不太理解如何产生不正确的多项选择的概念。欺骗是一个复杂的概念。
  7. 我还从英语语言描述中生成了示例 Python 程序。这是 GPT-3 的一个众所周知的用途。

在我向您展示示例之前,您应该知道 OpenAI API GPT-3 密钥非常短缺。截至 1 月下旬,似乎仍然有一个基于抽签的系统来分发它们。我真的不知道为什么我和我的朋友 Ravi K .得到了他们,但其他人还没有得到他们。我的建议是上 OpenAI API 等候名单并写很多关于你将如何教别人如何使用 GPT-3 的博客。:-)

OpenAI API GPT 概念

我使用 OpenAPI Playground(一个简单的浏览器文本框接口)和 Python 生成了上面的结构。Playground 使用起来很简单,大多数人在获得 API 密匙后几分钟内就可以开始使用它。

一个警告,网上有许多视频使用的是旧版本的操场,界面已经改变。所以要小心你正在看的视频,因为界面上还没有版本控制。自 2020 年 12 月以来制作的视频应该是最新的。

我不会在这里重复 API 手册中的所有内容。我只想回顾一些关键概念。

  1. GPT-3 接口是一个简单的文本输入文本输出接口。您发送简单的指令和一系列您要寻找的样本作为输入,它会在操场文本区域以完整文本的形式返回结果。
  2. 我们将提供一个包含模板序列的提示
  3. API 将返回一个包含我们正在寻找的文本的完成
  4. 每个 API 调用的价格基于一种叫做的标记,它与文本中音节的总数密切相关。小词通常是单个标记,但多音节是多个标记。我运行的大多数查询被设置为返回大约 200 个令牌,每个令牌的运行成本大约为 1 美分。

入门:为 Python 类入门生成课程

让我们从一个简单的例子开始。我们将为适合中学生的 Python 编程入门课程生成一个主题列表。

首先,我们需要设置以下参数:

  • 发动机: 达夫尼奇— 这是最大最贵的型号。我们总是从这一点开始,并调整我们关心的成本的复杂性。因为我们的例子在这些演示中很小,所以我将坚持使用这个模型。对于我价值 100 美元的免费入门套件,每次查询我都要花费大约 1 便士。
  • 温度:. 2——这就是我们希望回应有多“有创意”。设置为 0 是一个纯粹的确定性值,将始终返回相同的结果。更接近 1 的值将增加输出的随机性,并且更有创造性。使用相同输入的每个人都会得到稍微不同的输出。
  • 响应长度(代币):200——对于一个四小时的简短入门课程来说,这足以构成一个合理的课程大纲。
  • 频率惩罚和存在惩罚:. 2——这些参数用于避免结果重复。我已经将它们都设置为一个合理的低值,以便开始使用。

还有其他参数,但我们现在将忽略它们,只使用默认值。

OpenAI API 操场输入屏幕如下图 1 所示:

图 OpenAPI Playground 准备好让我们点击提交按钮。请注意,参数在主文本区域的右侧进行了更改。在右下角,您可以看到我们的输入包含 40 个令牌。图片由作者提供。

现在让我们点击场景左下角的紫色提交按钮,看看会发生什么!

图 2:GPT-3 的 1750 亿个参数的达芬奇引擎生成我们在中学生 Python 入门课程的剩余课程的结果。我不得不向下滚动来显示结果。图片由作者提供。

结果会在几秒钟内返回。这个列表非常准确。在我们为 CoderDojo 设计的实际 Python 类中,我们在类中包含了函数、列表、字典、调试、正则表达式。我们决定将模型、类和继承移至高级类,但是其他教师将它们留在了初级类中。GPT 在这里没有错,我们只是不同意!对于这项工作,我会给 GPT-3 一个 A。

我也对 GPT-3 返回建议课程主题的命令感到惊讶。我担心,因为 GPT-3 并不真正理解一些课程如何依赖于先前的课程,所以返回的顺序将是随机的。但是顺序和我们设计课程的顺序很像。我相信这是因为当 GPT-3 扫描包含 Python 教程的网页时,最常见的开始主题出现得更频繁,因此在 Python 概念和开始课程概念之间具有更强的权重。

现在,让我们来看看 GPT-3 如何会有点偏离轨道,以及如何纠正它。

生成课程子主题:正则表达式

为了向您展示 GPT 如何需要高质量的提示,让我们创建一个不够具体的提示。

在课程中生成子主题的示例提示。图片由作者提供。

第一次尝试的结果不是很好:

由于模糊的提示和太低的重复惩罚,这不是一个非常有用的结果。图片由作者提供。

这个问题的解决方案是找到一些使用正则表达式的示例教程,从这些示例中提取 1 级标题,并将其用作我的前 7 个提示。下面的结果更符合我的预期。

这是一个更详细的提示,并且将频率和存在惩罚从 0.2 调整到 0.5 的结果。图片由作者提供。

生成词汇表术语

我还试图使用 GPT-3 为我们正在进行的儿童人工智能课程生成一组课程词汇表中使用的术语。虽然它在产生新术语方面很有效,但是定义有时是提示示例的重复。下图显示了我如何将术语/定义对定义为提示。

为儿童人工智能课程生成术语表的尝试。要考虑的新术语列表很好,但是许多定义与术语不匹配。图片由作者提供。

我会在术语列表上给 GPT-3 打 A,但在找到正确的定义上打 C。

生成代码

我的下一步是探索 GPT-3 的详细程序生成方面,以纳入课程中。使用 GPT-3 从简短的描述性文本中生成 Python 代码的例子还有很多。下面的示例生成一个程序,该程序将检查邮政编码是五位还是九位。我给它的提示是粗体的。

使用 GPT-3 生成验证五位或九位邮政编码的代码。提示以粗体显示。图片由作者提供。

结论

我只是刚刚开始理解如何为 OpenAI GPT-3 模型设计高质量的提示。但它显然显示出了希望。我敢大胆地说,如果我有一个预先构建并测试了提示的高质量 web 应用程序,它将节省我创建新的 STEM 课程的时间。

因为我在某种程度上是这些编程主题的专家,所以我可以根据自己的个人知识来检查 GPT-3 生成的结果。如果我不是专家,我会希望所有的内容都由专家来审查。

关于这个练习,最让我惊讶的是,我有时会在为一门课程创建大纲或填写细节时产生思维障碍。GPT-3 非常善于抛出我能很快同意或抛弃的想法。一旦我完成了,我就有了更多的信心,相信 GPT-3 和我一起已经达到了一门课程或一课的关键点。当我创建新课程时,GPT-3 真的成了我的“认知助手”。

Gradio vs Streamlit vs Dash vs Flask

原文:https://towardsdatascience.com/gradio-vs-streamlit-vs-dash-vs-flask-d3defb1209a2?source=collection_archive---------6-----------------------

比较几种数据科学的 web UI 工具!

塞萨尔·卡利瓦里诺·阿拉贡在 Unsplash 上拍照

介绍

机器学习模型令人兴奋且强大,但它们本身并不十分有用。一旦一个模型完成,在它能够交付任何种类的价值之前,它可能必须被部署。同样,能够部署一个初步的模型或者原型来从其他涉众那里获得反馈也是非常有用的。

最近,出现了几种工具,数据科学家可以使用这些工具快速轻松地部署机器学习模型。在这篇文章中,我们将看到 4 种可以用来部署机器学习模型的替代方案:Gradio、Streamlit、Dash 和 Flask。

请记住,这是一篇固执己见的文章,完全基于我对这些工具的了解和经验。

总结:该用哪个?

作者创建的图像

Gradio : Gradio 是专为机器学习模型打造的。因此,如果你想专门为你建立的机器学习模型创建一个 web 用户界面,Gradio 简单的语法和设置是一个不错的选择。

如果您想要快速启动并运行一个仪表板,并且能够灵活地添加许多组件和控件,Streamlit 非常有用。同样,Streamlit 允许您比 Dash 或 Flask 更快地构建 web UI 或仪表板。

Dash :如果你想成为一家大公司的生产就绪仪表板,选择 Dash,因为它主要是为企业量身定制的。

Flask :如果你有 Python/HTML/CSS 编程的知识,想完全从零开始构建自己的解决方案,就选择 Flask。

格拉迪欧

见网站 此处

Gradio 是一个用于创建机器学习模型用户界面的强大工具。它是一个 python 包,可以完美兼容 PyTorch、TensorFlow 等几个机器学习框架。它还可以用来围绕任意的通用 Python 脚本创建 ui。

Gradio 的受欢迎程度正在迅速增加。它正在被思科和亚马逊等大公司的机器学习实验室以及斯坦福医学等学术机构使用。

优点:

  • Gradio 提供了几个可定制的 UI 组件,针对机器学习模型进行了优化。例如,Gradio 提供了易于使用的拖放式图像分类,该分类针对用户进行了高度优化。
  • 设置 Gradio 非常简单快捷。可以通过 pip 直接安装。此外,在 Gradio 中创建接口只需要几行代码。
  • Gradio 创建了可共享的链接,这可能是在用户面前部署机器学习的最快方式
  • 与其他包不同,Gradio 可以在 Jupyter/Colab 笔记本或独立的 Python 脚本中的任何地方运行。

缺点:

  • 虽然 Gradio 在官方网站上有很好的文档,但很难找到关于它提供的具体功能的信息和足够的例子。
  • Gradio 的社区比其他一些软件包要小,所以很难找到关于它的资源。
  • Gradio 专门为机器学习模型构建 ui,而不是仪表盘。

细流

参见网站 这里

Streamlit 是另一个用于创建用户界面的流行工具。它是一个开源 Python 库,用于为数据科学和机器学习构建强大的定制 web 应用程序。Streamlit 兼容几个主要的库和框架,如 Latex、OpenCV、Vega-Lite、seaborn、PyTorch、NumPy、Altair 等。

像 Gradio 一样,Streamlit 也很受欢迎,并在大型行业领导者中使用,如优步和 Google X

优点:

  • 理解 Python 的每个人都可以访问 Streamlit。对 HTML 和 CSS 没有要求。
  • 它有广泛的用户界面组件。它几乎涵盖了所有常见的 UI 组件,如复选框、滑块、可折叠的侧边栏、单选按钮、文件上传、进度条等。此外,这些组件非常易于使用。
  • 它支持 Latex、OpenCV、Vega-Lite 等多种交互式可视化库。

缺点:

  • 虽然不难,但 Streamlit 确实需要一些时间来学习它自己的语法。
  • Streamlit 没有那么灵活。它仅基于 Python,提供有限的小部件,并且不与 Python 笔记本集成。
  • 数据上传限制只有 50Mb。
  • 对视频/动画的支持有限。

破折号

见网站 此处

Dash 是一个开源 Python 库,用于创建反应式 web 应用程序。这是一个用户界面库。Dash 是构建分析性 web 应用程序的强大工具。

优点:

  • Dash 可用于各种领域,如数据探索、数据分析、建模、可视化、仪器控制和报告。
  • 使用起来非常简单。可以通过 pip 直接安装。
  • 除了 Python,它还可以和 R,Julia,Jupyter 一起使用。
  • Dash 应用是被动的。
  • Dash 比 Streamlit 更容易定制。此外,Dash 提供了更好的性能。
  • Dash 有一个更好的、定期更新的、易于遵循的文档。

缺点:

  • Dash 更侧重于企业市场,并不包括开源版本中所有可用的功能。
  • Dash 比 Gradio 或 Streamlit 更冗长;与其他框架相比,您必须编写更多代码来创建简单的 web 应用程序。

参见网站 这里

Flask 是一个用于构建 web 应用程序的 python web 框架。它为 web 开发提供了几个模块,使得开发人员的工作更加容易。Flask 也有资源部署机器学习模型,尽管任何前端工作都必须由开发人员完成。这意味着作为一名数据科学家,您还必须熟悉 HTML、CSS 和 JavaScript。

优点:

  • 因为它是一个框架,你可以根据自己的需求从头开始构建一切。
  • 使用 flask,更容易构建可定制的应用程序。
  • 使用 Flask 可以构建更通用的 web 应用程序。
  • 烧瓶非常成熟稳定;用 flask 构建的东西更有可能在未来继续工作。
  • 有大量关于 Flask 和相关库的文档。

缺点:

  • Flask 没有为机器学习或数据科学应用程序提供任何类型的 UI 组件。
  • 需要具备中级 Python 知识,以及 HTML、CSS 和 JavaScript 知识。
  • 从头开始构建解决方案可能会耗费大量资源。

感谢阅读!

我希望在决定使用什么工具时,您会发现这些信息非常有用!在一天结束的时候,我会选择你觉得最舒服的。:)

一如既往,我祝你学习一切顺利!

不确定接下来要读什么?我为你挑选了另一篇文章:

又一个!

特伦斯·申

  • 如果你喜欢这个, 跟我上媒 了解更多
  • 有兴趣合作吗?让我们连线上LinkedIn
  • 报名我的邮箱列表 这里

grads flow——用 AutoML 使人工智能民主化

原文:https://towardsdatascience.com/gradsflow-democratizing-ai-with-automl-9a8a75d6b7ea?source=collection_archive---------19-----------------------

GradsFlow 是一个基于 PyTorch 的开源 AutoML & Model 训练库。我们的目标是使人工智能民主化,让每个人都可以使用它。

作者图片

Gradsflow 可以在你的笔记本电脑上自动训练不同任务的深度学习模型,或者直接从你的笔记本电脑上训练到远程集群。它提供了一个强大且易于扩展的模型训练 API ,可以用来训练几乎任何 PyTorch 模型。

谁应该使用 Gradsflow

你是没有机器学习经验的人吗?

你可以使用 自动任务 功能来自动构建和训练模型,而无需编写任何跨包括视觉和文本在内的各个领域的机器学习代码。目前,它支持图像分类、文本分类、情感分析和文本摘要。只需转储数据,就可以开始训练模型了。

你是 ML 专家吗?

使用 Gradsflow,您不仅可以自动构建和训练模型,还可以编写和训练自定义 PyTorch 模型。它提供了一个功能强大、易于使用且易于扩展的 模型 类,可用于训练任何自定义 PyTorch 模型。你不需要写一个训练循环,但是如果有必要,你可以定制训练过程的任何部分。继续阅读,了解更多关于模型 API 的知识。

让我们不要浪费时间去看神奇的🪄✨吧

模型训练 API

Gradsflow 为模型训练提供了一个类似 Keras 的 API 接口。您可以将 PyTorch 模型传递给Model类,该类会自动准备您的模型,以便将其移动到适当的设备(CPU/CUDA),启用浮点精度或分布式训练。一旦从模型类中创建了一个对象,就可以编译模型来实例化优化器、学习率、损失函数和准确性或 F1 分数等指标。现在,要训练你的模型,只需运行 model.fit(data_loader)。

作者图片

模型 API 不仅简单,而且完全可定制。为了训练 Pix2Pix GAN,你可能需要定制训练步骤和模型初始化。这很容易做到,也很简单。在下面的例子中,为了保持简单,大部分代码都被抽象了,但是如果你想更深入地研究,那么请到我们的文档页面的示例部分,学习使用 Gradsflow 进行 Pix2Pix 训练的全部代码。

首先,您可以定制 init 方法来覆盖模型初始化。这里创建了两个模型——一个生成器和一个鉴别器,然后使用 super 关键字将模型传递给父 init 方法。

作者图片

接下来,您可以定义自己的编译方法来加载优化器。

作者图片

最后,覆盖 train_step 方法。这是数据通过模型的方法,您可以计算反向传播的损失。在这里,您可以看到生成器和鉴别器都经过了训练和反向传播。要跟踪和打印指标,您可以使用 跟踪器 ,它保存打印到进度条的值,或在任何其他时间点使用它,如提前停止回调。

作者图片

现在,像往常一样,初始化模型,编译它,然后调用 model.fit

作者图片

如需更多定制示例,请访问文档页面。

AutoML 或超参数优化在哪里?

有两种方法可以在 Gradsflow 中构建和调整您的模型超参数。

Gradsflow 提供了一个 AutoModel 类(实验性的🚨)这和你刚才看到的级很像。您可以使用 Tuner 类注册想要调整的超参数,只需对代码进行最少的更改,您就可以使用超参数优化模式训练您的模型。

在本例中,调谐器将针对 cnn1cnn2 架构以及 adamSGD 优化器进行优化。

作者图片

这就是如何使用 Model 和 AutoModel 类进行超参数调优。

另一种自动建立和训练模型的方法是https://docs.gradsflow.com/en/latest/gradsflow/tasks/。Autotask 为图像分类、文本分类&文本摘要等各种任务提供低代码模型构建和训练类。它由 PyTorch 闪电供电。

作者图片

奖金

在 2021 年的黑客啤酒节上找到我的演讲🎉

📚要了解更多关于 Gradsflow 的信息,您可以访问文档页面https://docs.gradsflow.com/en/latest。你可以找到用于训练自动图像分类、自动文本摘要、Pix2Pix GAN 训练和 HuggingFace 模型训练的例子。

🙏🏻Gradsflow 从 API 中获得灵感,并利用一些优秀的开源软件库,包括 Ray️、HuggingFace Accelerate、PyTorch Lightning TorchMetrics、Keras & fast.ai

🌟喜欢这个项目?在 GitHub 上给我们一颗星

有问题吗?加入我们的松弛社区🧡和我们一起聊天。

在 Twitter 或 LinkedIn 上关注我。

深度学习的语法纠错

原文:https://towardsdatascience.com/grammar-error-correction-af365dad794?source=collection_archive---------7-----------------------

图片来自 Unsplash

目录

  1. 介绍
  2. 问题定义
  3. 先决条件
  4. 数据源
  5. 理解数据
  6. 探索性数据分析
  7. 数据预处理
  8. 数据准备和数据管道
  9. 基准解决方案(标准编码器-解码器模型)
  10. 注意机制
  11. 单调注意
  12. 推理(贪婪搜索与波束搜索)
  13. 结果和模型比较
  14. 模型部署和预测
  15. 未来的工作
  16. Github 知识库和 Linkedin
  17. 参考

1.介绍

顾名思义,语法纠错是对文本中的错误进行检测和纠正的过程。这个问题看起来很容易理解,但实际上很难,因为一门语言有不同的词汇和规则。此外,我们不仅要找出错误,而且还需要纠正。

应用:

  • 这个问题有很多应用,因为写作是分享想法和信息的一种非常普遍的方式。这可以帮助作者加快他们的工作速度,把出错的可能性降到最低。
  • 此外,可能有许多人不精通某一种语言。因此,这些类型的模型确保语言不会成为交流的障碍。

2.问题定义

现在我们将把手头的任务定义为一个机器学习问题。我们正在处理的问题是一种 NLP(自然语言处理)问题。NLP 是机器学习的领域,处理人类语言和计算机之间的交互。我建议浏览一下这篇论文,以了解用于解决问题的方法的进展。

我们要研究的方法是序列对序列模型。简而言之,深度学习模型将接收一个序列(在这种情况下是不正确的文本),它将输出另一个序列(在这种情况下是正确的文本)。

绩效指标

现在,我们已经将我们的问题定义为机器学习问题,还有另一个非常重要的想法需要处理,那就是性能指标。性能指标是一种数学度量,有助于理解我们的机器学习模型的性能。

NLP 问题的一个非常流行的性能指标是 BLEU(双语评估替角)分数,因此我们也将它用于我们的模型。你可以参考这个视频来了解更多关于 BLEU 的分数。

3.先决条件

在我们深入这个案例研究的细节之前,我假设读者知道机器学习和深度学习的概念。具体来说,LSTMs、编码器-解码器、注意机制的概念应该是熟悉的。

路上我会尽量提供一些好的参考。

4.数据源

正如我上面提到的,这个问题很难解决,原因之一是没有高质量的数据集。在我的研究中,我发现其中一些很有用,并考虑了以下两个数据集。

  1. Lang-8 数据集
  2. 新加坡国立大学社交媒体文本规范化和翻译语料库

如果您有兴趣使用它们,这两个数据集都是公开的。

5.理解数据

5.1 Lang-8 数据集

这是一个致力于语言学习的日本网站。用户可以用他们正在学习的语言发表帖子,该帖子将出现在母语为该语言的人面前以供更正。来自此网站的数据集在以下列中包含数据,以\t:

  • 校正次数
  • 序列号
  • 句子编号
  • 0 是标题
  • 英语学习者写的句子
  • 更正的句子(如果存在)

由此,我们已经为这些句子都存在的那些数据点提取了输入句子和校正句子对。

5.2 新加坡国立大学社交媒体文本规范化和翻译语料库

这是新加坡国立大学(NUS)的数据集,是社交媒体数据文本数据。数据集大小为 2000 个数据点。对于每个数据点,原始形式的数据有三行。

  • 第一行是社交媒体文本
  • 第二行是正确的正式英语翻译文本
  • 第三行是中文翻译数据。

除此之外,我们可以使用每个数据点的前两行来解决我们的问题。

6.探索性数据分析

一旦我们以所需的形式提取了数据,现在是一个非常重要的步骤,即探索性数据分析,这是一个理解和培养对数据集的良好感觉的机会。

我已经以所需的形式提取并预处理了数据集,这将在下一节中讨论。

6.1 基本统计

首先,我们将收集关于数据集的整体信息,如数据点的数量、数据类型、数值数据的平均值或中值等。

# TOTAL DATAPOINTS
df.shape
# CHECK FOR NULL VALUES
df.info()

因此,大约有 50 万个数据点,不存在空值。

数据集中有两列,一列是输入,另一列是输出或目标。让我们逐一查看每一列的分析。

6.2 文本长度和字数分布分析

不正确的文本

输入是文本特征,我们可以分析文本的长度分布和字数分布。

  • 输入中字符长度和单词数量的分布是高度倾斜的。
  • 两种分布几乎遵循相同的模式。
  • 输入的字符数可能高达 2000 个,单词数高达 400 个。
  • 较长的单词或字符的比例明显较小。
  • 超过 99%的输入字符数少于 200,单词数少于 50。

更正的文本

输出文本也是如此。

令人惊讶的是,对输入文本的观察同样适用于输出文本。

6.3 不正确和已更正文本的词云分析

单词云是一个很好的可视化工具,可以用来了解整个文本中出现频率最高的单词。

用于输入文本的词云

用于输出文本的词云

两种文本中最常见的单词是:

  • 想要
  • 今天
  • 日本
  • 英语

6.4 错别字和更正字分析

这里的错别字是那些在输入中存在但在目标句子中不存在的字,纠正字是那些在目标句子中存在但在输入句子中不存在的字。我把这些词都提取出来,对它们做了词云分析。

  • 在观察了不正确和正确的单词图像后,我们可以观察到所用动词形式的变化。
go ==> going
go ==> went
study ==> studying
use ==> using

6.5 位置标记

在这部分的分析中,我们将把单词和它们的词类联系起来,并画出最常出现的 10 个词类。以下是情节:

输入文本的前 10 个位置

输出文本的前 10 个位置

  • 这表明使用次数最多的词类是名词(NN),其次是介词(IN)。
  • 输入和输出句子的词类总数保持不变,但 NNS(名词、复数)和 PRP(人称代词)的词类数量有所不同

7.数据预处理

现在,我们将了解如何从数据集中删除不需要的数据。我们知道数据是文本格式的,因此需要删除所有特殊字符和不需要的空格,并对缩写词进行去压缩。我们还将把所有的文本转换成 lower,以降低问题的复杂性。下面的代码用于完成上述所有操作:

接下来,我们还可以执行一些其他操作,即删除空值和重复数据删除,这些操作在 pandas 库中可用。

8.数据准备和数据管道

在我们将数据输入 DL 模型之前,需要将其转换成机器能够理解的形式。所以对于这个问题,我们要用记号化和填充把数据集转换成一个长度相同的整数序列。

在形成模型的数据管道时,我们将填充序列以形成长度相等的所有数据点。用于填充的最大长度是字数分布的第 99 个百分位数。

数据管道

数据必须成批转换,以便输入到深度学习模型中。以下代码用于形成数据集的管道

9.基准解决方案(标准编码器-解码器模型)

对于基准测试解决方案,我将使用普通序列到序列模型,也称为编码器-解码器模型。该模型以序列形式接受输入,并预测另一个序列作为输出。由于这一点,它在机器翻译问题中有许多应用。

图片来自论文基于注意力的神经机器翻译的有效方法

以下代码用于形成模型中的编码器-解码器层。

这个真的是一个深入了解编码器-解码器模型的好博客。

我已经尝试了许多普通编码器-解码器模型的变体,比如使用 Word2Vec 和 FastText 的预训练嵌入,你可以在我的 GitHub 个人资料中查看它们。

在对这些模型进行实验之后,我发现对于我的情况来说,可训练的嵌入比预训练的嵌入工作得更好,因此它将被用于高级模型。

对于我们的数据集,编码器-解码器获得的蓝色分数是 0.4603。

10.注意机制

注意机制是机器学习中一个非常巧妙的想法,它克隆了人类获取信息的方式。此外,注意模型克服了简单编码器-解码器模型的某些缺点。今天使用的一些流行的注意机制技术是 Bahdanau 注意机制、Loung 注意机制。

让我简单介绍一下我在案例研究中广泛使用的休闲注意机制的步骤。具体来说,这种想法被称为全局注意力机制。

图片来自论文基于注意力的神经机器翻译的有效方法

编码器部分与标准编码器-解码器保持相同,输出输入序列的隐藏状态。现在,在解码器部分,对于每个时间步长,我们必须计算一个叫做的上下文向量。该上下文向量保存来自编码器的关于在该时间步长中预测的单词的相关信息。这听起来可能很复杂,但一旦你知道它是如何计算的,一切都会水到渠成。

  • 首先,当我们从 RNN 获得所有编码器隐藏状态(ht)和解码器先前隐藏状态(hs)时,我们找到α值()。

在论文中,Loung 和其他人提供了三种计算分数的方法。

  • 一旦计算出阿尔法值,就将上下文向量计算为所有编码器隐藏状态的加权平均值,其中权重是阿尔法值。
  • 给定目标隐藏状态和源侧上下文向量,简单级联层如果用于组合来自两个向量的信息,以产生如下的注意隐藏状态:

  • 然后,注意力向量 h \t 通过 softmax 层,按顺序产生下一个单词。

这种类型的注意机制被称为全局注意机制,因为编码器的所有隐藏状态都在解码器的每个时间步长被考虑以产生上下文向量。

在这个案例研究中,我通过模型子类化从零开始实现了 Loung 注意机制。下面是型评分的关注层代码。完整的代码,你可以参考我的 GitHub 简介。

注意力模型的性能指标明显优于我们的基准模型。

 BLEU Score
Dot Scoring         0.5055
General Scoreing    0.5545
Concat Scoreing     0.5388

11.单调注意

在我们进入单调注意的细节之前,让我们看看简单注意机制的一些缺点以及什么是单调注意的需要。

我们知道在注意机制中,在每个解码器时间步长,需要参考所有的编码器隐藏状态。这产生了二次时间复杂度,这阻碍了它在在线设置中的使用。

因此,为了克服这个缺点,引入了单调注意的概念,简单地说,没有必要在每个时间步长检查所有的注意权重。我们将按照特定的顺序(在英语中从左到右)检查隐藏状态,并在每个时间步选择一个隐藏状态作为上下文向量。一旦检查了某个特定条目,则在下一个时间步骤中不会再检查它。

这种方法最重要的优点是线性时间复杂度,因此可以用于在线设置。

Softmax 注意:图片来自这篇博客

单调的注意力:图片来自这个博客

在这里,我们将实现一个非常简单的单调注意力类型,如这篇博客和论文中所解释的。必须记住的是,这些变化只会发生在关注层,而编码器和解码器层将保持不变。这些是单调注意力的步骤:

  • 给定之前的隐藏状态,我们将计算分数或能量,我们将使用与上面在休息注意力机制中使用的相同的方法。

  • 分数计算出来后,通过 sigmoid 函数转换成概率。

  • 当前时间步长的注意力通过以下公式计算:

  • 一旦我们获得注意力权重,我们就按照计算加权和的类似步骤来获得上下文向量,并将其连接到解码器的隐藏状态,以通过 softmax 层。

在这个案例研究中,我只实现了单调注意力层的一个变体。有关更多信息,请参考 Colin Raffel 的博客和代码,他给出了该层的完整实现。

单调注意的性能与简单注意相当,但是正如在论文中提到的,它在时间复杂性方面提供了一些优势。

12.推理(贪婪搜索与波束搜索)

如果你知道序列对序列模型,那么你会意识到这样一个事实,我们必须对模型进行某些改变,以预测推理时所需的输出。

同样,我们有两种选择,一种是贪婪搜索,另一种是波束搜索。让我们一个一个来看看他们两个。

贪婪搜索

在每个时间步长的贪婪搜索中,我们考虑具有最大概率的记号,并忽略所有剩余的记号,即使它们在 softmax 层之后具有可比较的概率值。

在代码中,您可以在密集的 softmax 激活层的输出上看到 argmax 函数。

贪婪搜索预测

这有一个缺点,因为如果任何一个时间步的预测字是错误的,未来时间步的结果也会受到影响。

波束搜索

一种更好的预测方式是波束搜索,其中在每个时间步长,为最顶端的可能记号提供一个选择,这些记号的数目等于波束宽度,并且每个预测序列的总得分等于序列中每个单词的概率的乘积。

在本案例研究中,我将波束宽度设为 3。更多的见解,你可以浏览这个博客。

代码参考。

波束搜索预测

13。结果和模型对比

在这个案例研究中,我一共尝试了 12 个有一定变化的模型。下面是结果。

  • 注意机制的结果优于简单的编码器-解码器,并且在注意模型中,性能相差不大。
  • 我们还可以观察到,波束搜索的 BLEU 分数比预期的贪婪搜索好。

14。模型部署和预测

我已经为单调注意模型做了模型部署,它正在用点积计算分数。你可以在这个链接查看模型。

上述模型的一些预测如下:

15.未来的工作

  • 在未来的工作中,我很乐意研究单调注意机制的其他变体。
  • 如果一个更好的数据集可以公开获得,这将真正提高模型的性能。

16.Github 知识库和 Linkedin

我试着简单介绍一下我在这个项目中所做的工作。如果你想看我对每一行都做了注释的完整详细的代码,请查看我的 Github 库。在 Linkedin 上随意联系。

如果到目前为止,帮我留言完善内容。这对我意义重大:)

17.参考

  • https://Colin raffel . com/blog/online-and-linear-time-attention-by-enforcing-monotonic-alignments . html
  • 应用人工智能课程 Hina Sharma 指导下的项目:https://www . Applied AI Course . com/Course/11/Applied-Machine-learning-Course
  • 休息室注意事项:https://arxiv.org/pdf/1508.04025.pdf
  • 单调注意论文:https://arxiv.org/pdf/1409.0473.pdf
  • 单调注意的实现:https://github . com/craffel/mad/blob/b 3687 a 70615044359 c 8 ACC 440 e 43 a5 e 23 DC 58309/example _ decoder . py # L22
  • 博客作者 日尚 Prashnani

大西格马杰斯

原文:https://towardsdatascience.com/grand-sigmajs-c475ec0bde68?source=collection_archive---------20-----------------------

将 SigmaJS 网络可视化与 GRAND stack (GraphQL、React、Apollo、Neo4j)集成

使用 SigmaJS 可视化机场路线。图片作者。

我做过几个基于图形数据的项目,它们的一个共同点是需要一个定制的网络可视化/交互工具。在我之前的文章中,我研究了如何将 VisJS 整合到大堆栈框架中。不幸的是,VisJS 在处理成千上万的节点和关系时伸缩性不好。幸运的是,我的朋友简·扎克给我指了指西格玛杰斯图书馆,它应该更擅长可视化大型网络。我通常害怕创建包含超过 1000 个节点和关系的可视化,因为它们很容易使你的浏览器崩溃,但现在多亏了 SigmaJS 的性能。上面的机场航线可视化包含大约 3500 个节点和 35000 个关系,运行良好。我想说 SigmaJS 是面向更严肃的网络可视化开发的,因为你可以定制网络可视化和开发用户交互以获得更好的体验。查看他们的演示应用以获得它能做什么的一些提示。

在这篇博文中,我将结合 SigmaJS 使用 GRAND stack 来创建好看的网络可视化。

大堆栈。图片来自https://grandstack.io/。内容由 4.0 在 CC 下授权。

GRAND stack 使用 Neo4j 作为数据存储。前端通常有一个 React 应用程序,React 和 Neo4j 之间的数据交换由 GraphQL 处理。查看官方文档获取详细解释。

我已经准备了一个 GitHub 存储库,其中包含了播种 Neo4j 数据库的所有代码和指令。在这篇博文中,我将带您快速浏览代码和数据结构。

Neo4j 图形构造

首先,我们需要播种数据库。我们将使用来自 OpenFlights 网页的数据。OpenFlights 是一个工具,可以让您绘制全球航班地图,如果您愿意,还可以与公众分享您的航班。所有数据都可以在开放数据库许可下获得。我已经从 Kaggle 下载了 routes 数据集,并将其放在我的 Git 存储库中以简化播种过程。

机场航线图表模式。图片作者。

我们有一个简单的图形模型,其中包含机场和机场之间的路线。此外,我们还有一些关于机场的附加数据,比如它们的国家和位置。路由关系是有向和加权的。关系的权重表示两个机场之间有多少条路线,可能由不同的航空公司提供。如果您使用的是 Linux 或 MacOS,您可以用一个简单的脚本来播种数据。

cat seed_data.cql | docker exec -i neo4j cypher-shell -u neo4j -p letmein

我不熟悉 Windows bash 脚本,但如果你使用 Windows,你可以简单地将密码查询复制/粘贴到 Neo4j 浏览器中。

除了导入路线之外,该脚本还将执行 PageRank 和 Louvain 算法。PageRank 是一种中心性算法,用于查找图中最重要或最有影响力的节点,而 Louvain 算法用于检测图的社区结构。我们将使用 PageRank 分数来确定可视化和 Louvain 社区中节点的大小,并相应地为节点着色。

GraphQL 服务器

接下来,我们需要开发一个 GraphQL 服务器,它将从 Neo4j 获取信息,并使其在我们的 React 应用程序中可用。幸运的是,一个 Neo4j GraphQL 库让这个过程变得轻而易举。这是一个低代码库,设计用于在 Neo4j 图形数据库上构建 GraphQL 应用程序。我们需要定义 GraphQL 模式类型,该库将自动创建解析器函数来获取或更新 Neo4j 中的数据。

这就是我们拥有一个正常工作的 GraphQL 服务器所需的所有配置。我们已经定义了一种类型*机场。*类型名应该和 Neo4j 中的节点标签一致。您可以简单地指定想要公开的节点属性及其类型。我还排除了创建、更新和删除操作,因为我只对从 Neo4j 中检索数据感兴趣,而不是更新它。传入和传出路由字段定义了我们希望在传入或传出方向上遍历路由关系。我们还可以通过指定接口并将其作为关系的属性字段来添加关系属性。

当然,如果您愿意,也可以添加授权和自定义解析器。查看文档了解更多信息。

用 SigmaJS 反应应用程序

我准备了两个版本的机场航线可视化。一种使用 Force Atlas 布局算法来计算可视化中节点的布局。

机场航线用 Force Atlas 布局算法。图片由作者提供。

既然我们有可用的纬度和经度信息,我想测试一下我们是否可以将它们作为 x 和 y 坐标输入,然后看看结果如何。

带地理布局的机场航线。图片作者。

我不习惯事情在盒子外工作,所以这是一个惊喜。我还复制了 SigmaJS 官方演示中的一些功能。在左侧,我们有缩放和中央可视化按钮,在右侧,我添加了类别过滤器,您可以使用它们来过滤可视化中的国家。

例如,我们可以在可视化中排除除美国以外的所有国家。

美国机场间的机场航线。图片作者。

结论

时代在变。您不必再害怕必须生成具有成千上万个节点和关系的网络可视化。在这个例子中,我们可视化了 3500 个节点和 38000 个关系,而浏览器却毫不费力。从我的初学者 React 的角度来看,SigmaJS 有很大的潜力来增加定制和用户交互性。如果你计划在 Neo4j 上开发一个定制的网络可视化或交互工具,我肯定会推荐将 SigmaJS 集成到 GRAND stack 中。如果你有什么好主意可以添加到这个项目,请打开一个问题或拉请求。

和往常一样,代码可以在 GitHub 上获得。

格兰杰因果网络与间接反馈

原文:https://towardsdatascience.com/granger-causal-networks-and-indirect-feedback-676549ba99e?source=collection_archive---------46-----------------------

结构变量的非参数变量选择

在过去十年中,最常用的计量经济学工作流程之一是使用向量自回归模型。从学者所做的研究到经济学家告知政策实施,都以某种形式或迭代利用了 VAR 模型[想想向量误差修正模型(VECM)或结构 VAR(SVAR)]。这可能是为了脉冲响应研究、内生变量预测或简单的争论时间变量之间的交叉相关性。

不幸的是,VAR 研究未能解决的一个问题是将一个内生变量在一个时间点对另一个的影响分解为间接合计 反馈。直观地说,这可以理解为,如果一个变量直接影响另一个变量,那么我们可以在一个任意方程中显式地连接这两个变量:

x 在结构上影响着 Y

但是,如果一个变量对另一个变量只有中间反馈,我们可以隐式地将它们连接起来:

x 只通过对 Z 的影响来影响 Y

尽管我们能够通过正交脉冲响应函数来衡量总体影响,但我们仍然不能将其分解为间接直接反馈,因为这需要我们通过风险值模型中的每个方程来追踪影响。这是一场计算噩梦!

【读者可能会尝试使用 SEM 模型,但它们也要求我们先验地定义变量之间的关系,然后看看数据与我们的假设有多吻合;我们在这里试图解决的问题是“首先是什么关系?”】

这篇文章介绍了计量经济学界的一个小话题。 因果网络图 。因果图的概念很简单:

  1. 如果一个变量 A,导致了变量 B,那么我们可以从 A - > B 开始画一条边。
  2. 我们对数据集中的所有变量对都这样做。因果关系的方向也很重要。a 可以导致 B,但反之亦然。
  3. 使用变量/节点和边的集合形成的图被称为因果网络图, G(e,d) 。其中 e 是边的数量,而 d 是数据集中顶点(变量)的数量。
  4. 出于计算目的,我们使用邻接矩阵来表示 G(e,d)

因果网络图在面板数据研究中变得重要,作为一种可视化变量以及它们如何与其他变量相联系的方法。结果,图表成为快速和廉价的推断测量的容易的候选者。在这里,我们将尝试使用现实生活中的数据建立一个 G(e,d) 并且用通俗的语言探索这些网络如何帮助我们开始理解两个内生变量之间的直接和间接影响。

对于我们可重复的例子,让我们看看跟踪纳斯达克 100 指数的 ETF 的日志回报。此外,我们还将查看一些技术指标,如相对强弱指数(RSI)、布林线百分比 B(pctB)、成交量、范围和另一种证券的价格——SPY,并查看网络图是否能帮助我们了解结构上的 因果关系这些指标如何影响 QQQ 的日常价格变动(如果有的话)。我们将适当地变换这些变量,以确保平稳性。下面是我们将使用的变量的初始图:

G(e,d) 的新奇来自于我们用来构建它的 规则 。构建 G(e,d) 最简单的方法之一是查看这些变量之间的相关性,并只选择高度相关(cor > |0.6|)的边来制作图表。使用此规则构建的网络图的输出如下所示:

相关矩阵网络表示

似乎所有的变量都在两个方向上相互关联。双向连接可以传递关于哪些变量被连接的信息,而不是它们如何相关的信息。对于使用相关系数作为构建图边的规则的网络图,我们不需要给定隐含对称性的有向图。不幸的是,该图没有给我们任何额外的洞察力。我们知道相关性不等于因果关系**。这是一个测试,数字也是一致的。**

**接下来,让我们利用成对格兰杰因果关系来构建一个双变量 格兰杰因果网络图。这里方向很重要,我们可以建立一个有向网络。对于 G(e,d),每条边表示自变量的滞后在解释因变量在其自身滞后之上的变化时是否达到给定的显著性水平。这是通过运行如下所示的受限和非受限模型,并比较 f 检验统计的分布来实现的:

无限制二元模型

受限二元模型

以 1%为 p 值截止点,使用 AIC 最小化标准来选择格兰杰检验的最佳滞后(9),我们数据集的双变量格兰杰因果图如下所示:

成对格兰杰因果网络表示[99%置信区间,滞后= 9]

现在我们有点进展了。虽然 RSI 似乎与 QQQ 日志回报非常每周相关,但它对 QQQ 日志回报有 99%的显著成对格兰杰因果效应。

QQQ 日志的回报似乎有 聚合 的因果含义:

  1. RSI
  2. 范围
  3. 间谍日志返回
  4. pctB

请注意,QQQ 日志返回与 QQQ 数量没有直接的因果关系。但是,如果我们考虑链— 卷>范围> QQQ 日志回报,我们可以说卷对 QQQ 日志回报也有一个 中间 因果关系。

其他变量呢?以下是我们从 RSI 到 QQQ 日志回报的一些途径:

  1. RSI > QQQ.diff 【二元直接】
  2. RSI > SPY.diff > QQQ.diff 【中级】
  3. RSI > pctB > QQQ.diff 【中级】
  4. RSI > pctB > spy . diff > qqq . diff*【中级】*****
  5. RSI > spy . diff > Range > qqq . diff*【中级】*****
  6. RSI > SPY.diff > QQQ。音量>范围> QQQ.diff 【中级】

请记住,这个列表并不详尽。基于上述网络,从 RSI 到 QQQ 日志回报还有多种其他途径。

仅仅通过将我们的数据可视化为一个网络,我们就可以开始让直接和间接反馈的想法更加直观!

不幸的是,一个问题就摆在我们面前——使用成对格兰杰因果关系来推导数据中的结构变量,我们最终总是孤立地测量两个变量之间的因果关系,而这应该考虑数据集中隐含的所有动态。网络图揭示了在两个变量之间可以有许多 中间 反馈路径以及它们的集合效应。了解如何在直接中间影响之间划分总体因果关系变得至关重要,以量化一个变量对另一个变量的结构重要性。例如,如果集合信号显示 RSI granger 导致 QQQ.diff,但是该效应几乎完全通过中间反馈,则在网络图表示中,RSI 和 QQQ.diff 不应通过直接边连接;它们应该躺在同一条路上。

孤立地测量双向格兰杰因果关系可能有助于变量选择,但不能帮助我们挖掘有关过程的结构信息。理所当然,这是对格兰杰因果关系最大的批评之一——它有助于样本内拟合,而不是样本外预测。

结构因果性是一种绝对的度量。因此,任何结构性因果关系的测量都应该能够控制每个中间效应或路径,以便能够将一个变量命名为结构性因果关系。

作为一种解决方案,人们可能会争辩说,如果我们使用整个时间序列块,即使用限制和不限制变量,包括所有其他感兴趣的变量,我们可以衡量一个变量对另一个变量的结构重要性,也可以看到直接的影响。

是和不是。下面是来自 VAR 的相关方程的样子:

来自受限 VAR 模型的方程

来自无限制 VAR 模型的方程

变量有助于更好地理解格兰杰因果关系的总量方面,因为所有感兴趣的变量都被使用了。不幸的是,这一次我们无法单独控制直接和中间反馈来测量它们的强度——类似于双变量的情况,我们仍然在孤立地测量因果关系。因此,基于双变量和 VAR 的规则的结果构建了非常相似的网络图。下面是通过多元方法构建的图表:

基于风险值的格兰杰因果关系表示[99%置信区间,滞后= 9]

这里的一个很大的不同是,现在我们看到一些反馈被溢出到 RSI 和 pctB,与双变量情况相比,在给定的显著性水平上,双向因果边缘很明显。

这里看一下与二元情况相比,我们的每个设置给出的附加边:

****

这让我们对数据中的一些中间反馈路径有了进一步的了解。现在,不仅中间反馈的想法“看起来”很直观,而且使用 2 种不同规则产生的网络差异也有助于我们更好地理解效果:

  1. ****在双变量情况下,PctB 对 QQQ.diff 有很强的解释力,但当我们包括其他变量,即 VAR 网络时,PctB 就消失了—qqq . diff 的校准方程如下。此外,还有 QQQ.diff 对 pctB 的正交脉冲响应:

****

QQQ.diff 的 VAR 等式

**只有 pctB 的第一个滞后在等式中是重要的。pctB 增加一个单位会导致 QQQ.diff 增加 0.01707 个单位,直接基于以下等式。但是脉冲响应测量 1 个周期内大约 0.008 单位增加的影响。这意味着有一个更强的中间反馈来抵消渗透到系统中的直接影响。或许,pctB 会影响其他渠道,进而影响 QQQ 日志回报,而不仅仅是直接影响。交易者是否应该考虑通过其他指标配对使用 pctB 的买入/卖出信号,而不是直接使用日志回报(至少对于这个数据集来说)?

**2. **QQQ。在双变量情况下,交易量对 QQQ.diff 没有任何解释力,但在 VAR 情况下,交易量对 QQQ 有任何解释力,只有交易量的第 5、第 6 和第 8 个滞后在 QQQ 中是显著的。diff 等式,但我们在第一阶段看到来自 QQQ.diff 的显著脉冲响应,因为我们冲击音量:

这个推论让我们相信,在最初的几个滞后期,QQQ.volume 对 QQQ.diff 的影响严重偏向于中间反馈,而不是直接影响。

****3. SPY.diff 在双变量情况下对 RSI 没有任何解释能力,但在风险值网络中会弹出一个信号—SPY.diff 的滞后在风险值模型中并不显著,但当 spy . diff 受到冲击时,我们会看到来自 RSI 的显著正交响应:

********

RSI 的 VAR 方程

在这里,我们可以再次看到网络图如何帮助挖掘从 SPY.diff 到 QQQ RSI 的间接反馈,如果校准系数缺乏显著性,我们不会注意到这一点。

我们可以继续其他边的练习,并开始做出类似的推论。首先,我们能够评论在同样的滞后期,一个变量对另一个变量的总效应如何在直接和间接效应之间达到平衡;第二,直接影响和间接影响之间的平衡是如何随着滞后而变化的。

由于这个网络是两个图之间的差异,我们只能知道间接反馈存在于两个变量之间,但是 我们不能:**

  1. 评论一段时间内直接间接影响的分布或强度。
  2. 评论两个变量之间间接反馈的路径,只说明它存在。
  3. 评论变量间微弱的间接反馈。

我们可以从网络图中获得的洞察力是一种未开发的资源。如果我们改变我们用来画 G(e,d)的规则,我们几乎可以立刻得出新的见解。

网络图使用的扩展,更重要的是格兰杰因果网络图是我们如何使用这些图中隐含的 拓扑 来更好地理解我们的数据集。我正在积极构建一个条件格兰杰因果网络方法,并分析其拓扑方面,以揭示直接和间接的影响。假设——存在数据频域之外的关键结构信息;如果我们将域从频率转移到邻接矩阵,我们也许能够恢复变量之间更深层次的关系。也许我们可以在没有任何先验假设的情况下,得到数据中隐含的 SVAR 的结构方程。

对于时间序列,VAR 建模将从这些进步中获得最大收益,因为变量选择仍然严重依赖于相关时间序列的瞬时信息。如果这篇文章帮助你得到了一些想法,请随时联系我们!

韦丹特·贝迪是万事达卡的分析师,在不结盟运动投资组合开发团队工作。Vedant 拥有 NYU 大学的数学和经济学学士学位(2019 年优等生),对数据科学、计量经济学及其在金融中的许多应用有浓厚的兴趣。

韦丹特还是美国历史最悠久的学术荣誉团体 Phi Beta Kappa(纽约分会)的成员。

引擎盖下的图形注意力网络

原文:https://towardsdatascience.com/graph-attention-networks-under-the-hood-3bd70dc7a87?source=collection_archive---------4-----------------------

GRL 系列

从数学到数字的逐步指南

图形注意力网络层——图片来自Petar veli kovi

G 图形神经网络(GNNs)已经成为从图形数据中学习的标准工具箱。gnn 能够推动不同领域中高影响问题的改进,例如内容推荐或药物发现。与图像等其他类型的数据不同,从图形数据中学习需要特定的方法。根据迈克尔·布朗斯坦的定义:

[..]这些方法基于图中某种形式的消息传递,允许不同的节点交换信息。

用于完成图形上的特定任务(节点分类、链接预测等。),GNN 层通过所谓的递归邻域扩散(或消息传递)来计算节点和边表示。根据这一原则,每个图节点接收并聚合来自其邻居的要素,以表示本地图结构:不同类型的 GNN 层执行不同的聚合策略。

最简单的 GNN 层公式,如图形卷积网络(GCNs)或 GraphSage,执行各向同性聚合,其中每个邻居同等地贡献以更新中心节点的表示。这篇博客文章致力于分析图注意力网络(GATs),它定义了递归邻域扩散中的各向异性操作。利用各向异性范式,通过注意机制提高学习能力,该机制对每个邻居的贡献赋予不同的重要性。

如果您对 GNNs 和相关概念完全陌生,我邀请您阅读以下介绍性文章:

GCN vs 加特——数学热身

本次预热基于深度图库 网站 报道的 GAT 详情。

在理解 GAT 层的行为之前,让我们回顾一下 GCN 层执行的聚合背后的数学原理。

GCN 层—聚合函数

  • N 是节点 i. 的一跳邻居的集合,也可以通过添加自环将该节点包含在邻居中。
  • c 是基于图形结构的归一化常数,定义了各向同性的平均计算。
  • σ 是一个激活函数,它在变换中引入了非线性。
  • W 是用于特征变换的可学习参数的权重矩阵。

GAT 层扩展了 GCN 层的基本聚合功能,通过关注系数为每条边赋予不同的重要性。

GAT 层方程

  • 等式(1) 是下层嵌入 *h_i,*的线性变换, W 是其可学习的权重矩阵。这种转换有助于获得足够的表达能力,将输入特征转换成高级和密集的特征。
  • 等式(2) 计算两个邻居之间的成对非归一化注意力分数。这里,它首先连接两个节点的 z 嵌入,其中||表示连接。然后,它取这种连接和可学习的权重向量的点积。最后,将 LeakyReLU 应用于点积的结果。关注分数指示邻居节点在消息传递框架中的重要性。
  • 等式(3) 应用 softmax 来归一化每个节点的传入边上的注意力分数。softmax 将上一步的输出编码成一个概率分布。因此,不同节点之间的关注分数更具可比性。
  • 方程式(4) 类似于 GCN 聚合(见本节开头的方程式)。来自邻居的嵌入被聚集在一起,通过关注分数来缩放。这个缩放过程的主要结果是从每个邻域节点学习不同的贡献。

NumPy 实现

第一步是准备表示简单图形的成分(矩阵)并执行线性转换。

NumPy 代码

输出

----- One-hot vector representation of nodes. Shape(n,n)[[**0 0 1 0 0**] # node 1
 [0 1 0 0 0] # node 2
 [0 0 0 0 1]
 [1 0 0 0 0]
 [0 0 0 1 0]]----- Embedding dimension3----- Weight Matrix. Shape(emb, n)[[-0.4294049   0.57624235 **-0.3047382**  -0.11941829 -0.12942953]
 [ 0.19600584  0.5029172   **0.3998854**  -0.21561317  0.02834577]
 [-0.06529497 -0.31225734  **0.03973776**  0.47800217 -0.04941563]]----- Adjacency Matrix (undirected graph). Shape(n,n)[[**1 1 1 0 1**]
 [**1** 1 1 1 1]
 [**1** 1 1 1 0]
 [**0** 1 1 1 1]
 [**1** 1 0 1 1]]

第一个矩阵定义了节点的独热编码表示(节点 1 以粗体显示)。然后,我们定义一个权重矩阵,利用定义的嵌入维数。我突出显示了第三列向量 W ,因为,正如您将很快看到的,这个向量定义了节点 1 的更新表示(在第三个位置初始化 1 值)。我们可以从这些成分开始执行线性变换,以获得足够的节点特征表达能力。该步骤旨在将(一位热码编码的)输入特征转换成低密度表示。

GAT 层(等式 1)

NumPy 代码

输出

----- Linear Transformation. Shape(n, emb)

[[**-0.3047382   0.3998854   0.03973776**]
 [ 0.57624235  0.5029172  -0.31225734]
 [-0.12942953  0.02834577 -0.04941563]
 [-0.4294049   0.19600584 -0.06529497]
 [-0.11941829 -0.21561317  0.47800217]]

下一步操作是为每个边引入自我关注系数。我们连接源节点的表示和目的节点的表示来表示边。邻接矩阵 A 支持这种连接过程,它定义了图中所有节点之间的关系。

GAT 层(等式 2)

NumPy 代码

输出

----- Concat hidden features to represent edges. Shape(len(emb.concat(emb)), number of edges)

[[**-0.3047382   0.3998854   0.03973776 -0.3047382   0.3998854   0.03973776**]
 [-0.3047382   0.3998854   0.03973776  0.57624235  0.5029172  -0.31225734]
 [-0.3047382   0.3998854   0.03973776 -0.12942953  0.02834577 -0.04941563]
 [-0.3047382   0.3998854   0.03973776 -0.11941829 -0.21561317  0.47800217]
 [ **0.57624235  0.5029172  -0.31225734 -0.3047382   0.3998854   0.03973776**]
 [ 0.57624235  0.5029172  -0.31225734  0.57624235  0.5029172  -0.31225734]
 [ 0.57624235  0.5029172  -0.31225734 -0.12942953  0.02834577 -0.04941563]
 [ 0.57624235  0.5029172  -0.31225734 -0.4294049   0.19600584 -0.06529497]
 [ 0.57624235  0.5029172  -0.31225734 -0.11941829 -0.21561317  0.47800217]
 [**-0.12942953  0.02834577 -0.04941563 -0.3047382   0.3998854   0.03973776**]
 [-0.12942953  0.02834577 -0.04941563  0.57624235  0.5029172  -0.31225734]
 [-0.12942953  0.02834577 -0.04941563 -0.12942953  0.02834577 -0.04941563]
 [-0.12942953  0.02834577 -0.04941563 -0.4294049   0.19600584 -0.06529497]
 [-0.4294049   0.19600584 -0.06529497  0.57624235  0.5029172  -0.31225734]
 [-0.4294049   0.19600584 -0.06529497 -0.12942953  0.02834577 -0.04941563]
 [-0.4294049   0.19600584 -0.06529497 -0.4294049   0.19600584 -0.06529497]
 [-0.4294049   0.19600584 -0.06529497 -0.11941829 -0.21561317  0.47800217]
 [**-0.11941829 -0.21561317  0.47800217 -0.3047382   0.3998854   0.03973776**]
 [-0.11941829 -0.21561317  0.47800217  0.57624235  0.5029172  -0.31225734]
 [-0.11941829 -0.21561317  0.47800217 -0.4294049   0.19600584 -0.06529497]
 [-0.11941829 -0.21561317  0.47800217 -0.11941829 -0.21561317  0.47800217]]

在前一个块中,我突出显示了代表连接到节点 1 的 4 条入边的 4 行。每行的前 3 个元素定义了节点 1 邻居的嵌入表示,而每行的其他 3 个元素定义了节点 1 本身的嵌入(正如您所注意到的,第一行编码了一个自循环)。

在这一操作之后,我们可以引入关注系数,并将它们与连接过程产生的边缘表示相乘。最后,漏 Relu 函数应用于该乘积的输出。

NumPy 代码

输出

----- Attention coefficients. Shape(1, len(emb.concat(emb)))

**[[0.09834683 0.42110763 0.95788953 0.53316528 0.69187711 0.31551563]]**

----- Edge representations combined with the attention coefficients. Shape(1, number of edges)

[[ **0.30322275**]
 [ 0.73315639]
 [ 0.11150219]
 [ 0.11445879]
 [ 0.09607946]
 [ 0.52601309]
 [-0.0956411 ]
 [-0.14458757]
 [-0.0926845 ]
 [ 0.07860653]
 [ 0.50854017]
 [-0.11311402]
 [-0.16206049]
 [ 0.53443082]
 [-0.08722337]
 [-0.13616985]
 [-0.08426678]
 [ 0.48206613]
 [ 0.91199976]
 [ 0.2413991 ]
 [ 0.29330217]]

----- Leaky Relu. Shape(1, number of edges)
[[ **3.03222751e-01**]
 [ 7.33156386e-01]
 [ 1.11502195e-01]
 [ 1.14458791e-01]
 [ 9.60794571e-02]
 [ 5.26013092e-01]
 [-9.56410988e-04]
 [-1.44587571e-03]
 [-9.26845030e-04]
 [ 7.86065337e-02]
 [ 5.08540169e-01]
 [-1.13114022e-03]
 [-1.62060495e-03]
 [ 5.34430817e-01]
 [-8.72233739e-04]
 [-1.36169846e-03]
 [-8.42667781e-04]
 [ 4.82066128e-01]
 [ 9.11999763e-01]
 [ 2.41399100e-01]
 [ 2.93302168e-01]]

在这个过程的最后,我们为图表的每条边获得了不同的分数。在上面的方框中,我突出显示了与第一条边相关的系数的演变。然后,为了使不同节点之间的系数易于比较,对每个目的节点的所有邻居的贡献应用 softmax 函数。

GAT 层(等式 3)

数字代码

输出

----- Edge scores as matrix. Shape(n,n)

[[ 3.03222751e-01  7.33156386e-01  1.11502195e-01  0.00000000e+00
   1.14458791e-01]
 [ 9.60794571e-02  5.26013092e-01 -9.56410988e-04 -1.44587571e-03
  -9.26845030e-04]
 [ 7.86065337e-02  5.08540169e-01 -1.13114022e-03 -1.62060495e-03
   0.00000000e+00]
 [ 0.00000000e+00  5.34430817e-01 -8.72233739e-04 -1.36169846e-03
  -8.42667781e-04]
 [ 4.82066128e-01  9.11999763e-01  0.00000000e+00  2.41399100e-01
   2.93302168e-01]]

----- For each node, normalize the edge (or neighbor) contributions using softmax

[0.26263543 0.21349717 0.20979916 0.31406823 0.21610715 0.17567419
 0.1726313  0.1771592  0.25842816 0.27167844 0.24278118 0.24273876
 0.24280162 0.23393014 0.23388927 0.23394984 0.29823075 0.25138555
 0.22399017 0.22400903 0.30061525]

----- Normalized edge score matrix. Shape(n,n)

[[**0.26263543 0.21349717 0.20979916 0\.         0.31406823**]
 [0.21610715 0.17567419 0.1726313  0.1771592  0.25842816]
 [0.27167844 0.24278118 0.24273876 0.24280162 0\.        ]
 [0\.         0.23393014 0.23388927 0.23394984 0.29823075]
 [0.25138555 0.22399017 0\.         0.22400903 0.30061525]]

为了解释定义归一化边分数的最后一个矩阵的含义,让我们回顾一下邻接矩阵的内容。

----- Adjacency Matrix (undirected graph). Shape(n,n)[[**1 1 1 0 1**]
 [1 1 1 1 1]
 [1 1 1 1 0]
 [0 1 1 1 1]
 [1 1 0 1 1]]

如您所见,我们重新调整了每个邻居的贡献,而不是用 1 值来定义边。最后一步是计算邻居聚合:来自邻居的嵌入被合并到目的节点中,并根据关注分数进行缩放。

GAT 层(方程式 4)

数字代码

输出

Neighborhood aggregation (GCN) scaled with attention scores (GAT). Shape(n, emb)

[[**-0.02166863  0.15062515  0.08352843**]
 [-0.09390287  0.15866476  0.05716299]
 [-0.07856777  0.28521023 -0.09286313]
 [-0.03154513  0.10583032  0.04267501]
 [-0.07962369  0.19226439  0.069115  ]]

后续步骤

在以后的文章中,我将描述多头 GAT 层背后的机制,我们将看到一些链接预测任务的应用。

参考

  • 下面的笔记本里有代码的运行版本。您还会发现一个 DGL 实现,这对于检查实现的正确性很有用。
  • Petar Velič ković、Guillem Cucurull、Arantxa Casanova、Adriana Romero、Pietro Liò、Yoshua Bengiois 关于图形注意力网络的原始论文可在 arXiv 上获得。
  • 为了更深入地解释这个话题,我还推荐来自Aleksa gordi的视频。

【https://towardsdatascience.com/tagged/grl-series】:,你可以通过以下链接关注我的系列。

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

网络图着色

原文:https://towardsdatascience.com/graph-coloring-with-networkx-88c45f09b8f4?source=collection_archive---------4-----------------------

图着色问题的解决方案在概念上很简单,但在应用上却很强大。本教程将向您展示如何使用 python 技能来解决这个问题。

让我们从一个可能的现实生活挑战开始,我想让你相信网络理论和在这个领域发展起来的数学工具可以为你解决这个问题。

想象你现在在一所学校的行政部门工作了几年。制定考试时间表是很痛苦的,但到目前为止,用纸和笔还是可以做到的。但是学校发展得非常快,整个时间安排变得令人不堪重负。注册的学生如此之多,你希望他们都能在放假前参加考试。如果学生在假期后不得不回来参加考试,那将是多么可怕。你打算怎么解决这个问题?

我认为,到本文结束时,你可以从野外获取数据,例如学生名单和他们参加的课程,并建立一个考试时间表,这样没有学生会遇到考试日期冲突的尴尬情况。着色问题不仅对考试时间表有用,而且在许多不同的情况下都有用。也许你想出了另一个主意,我会很高兴在评论区听到你的意见!

罗汉在 Unsplash 上拍照

在我们开始这个简短的教程之前,我想和你分享一下这篇文章的学习目标,你可以边学习边核对。

目录

  1. python 中的网络与库网络 x
  2. 图着色问题,是什么,怎么解决?
  3. 解决实际问题

Python 中的网络

我假设你熟悉网络理论或也称为图论。如果没有,让我们回顾一下网络中最基本的模块,同时了解 networkx 的功能。

import networkx as nx

如果您的计算机或虚拟环境中没有 networkx,请使用

pip install networkx

或者

conda install networkx

让我们用这个库创建一个网络,称之为 network。

network = nx.Graph()

网络由节点和连接节点的边组成。让我们在网络中添加三个节点和两条边。

对于多个节点,我们可以提供节点名称列表。在这种情况下,节点被称为 1、2 和 3..

network.add_nodes_from([1,2,3])
print(f"This network has now {network.number_of_nodes()} nodes.")

这个网络现在有 3 个节点..

要在两个节点之间添加边,请命名要相互连接的第一个和第二个节点。

network.add_edge(1,2)
network.add_edge(1,3)

我们也可以绘制这个网络来获得视觉上的理解。

nx.draw_networkx(network, with_labels=True)

简单图的非常简单的图

所以总结这一段,我们知道网络是由什么组成的,如何用 networkx 来构建和可视化。如果我想描述这个图,我会说,这个图 G 由三个节点组成,分别叫 1,2,3。其中节点 2 与节点 1 相邻,节点 3 与节点 1 相邻。节点 1 与节点 2 和 3 相邻。好了,现在够了。让我们继续着色问题。

图着色问题

图着色问题定义为:

Given a graph G and k colors, assign a color to each node so that adjacent nodes get different colors.

从这个意义上说,颜色是类别的另一个词。让我们看看前面的例子,添加两到三个节点,并给它们分配不同的颜色。

network.add_nodes_from([4,5,6,7])network.add_edge(1,4)
network.add_edge(1,5)
network.add_edge(2,4)
network.add_edge(3,5)
network.add_edge(5,6)
network.add_edge(7,3)
network.add_edge(7,6)

好的,让我们手动给这个图着色,来解决着色问题。

color_list = ["gold", "violet", "violet", "violet",
              "limegreen", "limegreen", "darkorange"]
nx.draw_networkx(network,node_color=color_list, with_labels=True)

解决着色问题的首次尝试

好吧,这不是我们想要的。节点 5 和 6 颜色相同但相邻,节点 4 和 2 也相邻但颜色相同。我们必须解决这个问题。

color_list = [“gold”, “red”, “violet”, “pink”, “limegreen”,
              “violet”, “darkorange”]

着色问题的有效解决方案

好的,这看起来是解决图表着色问题的一个可能的解决方案。但是你可能会问自己,我怎么知道我需要多少种颜色?我们现在来看一个制作考试时间表的玩具例子,这个例子变得更加清晰。

实际例子

在这个实际的例子中,我们试图为一个学期的考试安排找到一个最优的解决方案。

我创建了一个由 250 名学生组成的人工数据集,这些学生就读于我们的虚拟学校,该学校提供 5 个专业,也可以作为辅修专业。每个学生可以注册 5 门课,如果她或他注册了辅修专业和主修专业的组合(有 10%的学生注册了),那么她或他可以选择主修专业的 3 门课和辅修专业的 2 门课。否则,如果他们只学习一个专业,他们会从他们的主要科目中选择所有 5 个讲座。每个科目提供 6 至 9 门课程(班)。

我在 kaggle 上用下面的链接上传了这个数据集。我们下载它并用熊猫来阅读 csv。csv 具有以下结构。行显示学生,列 1 显示专业,列 2 显示辅修专业,如果她或他有一个。第 3 栏到第 42 栏是不同的主题。

import pandas as pdstudent_data = pd.read_csv("synthetic_school_enrollment_data.csv")

摘自我们的数据

到目前为止,我还没有告诉你我们将如何防止学生有冲突的考试日期。但是现在我们已经为解决这个问题做好了一切准备。

我之前提到过,在着色问题中,我们希望防止相邻(邻近)节点具有相同的颜色。在我们的例子中,我们希望避免学生不得不同时参加两次考试。

这两个问题听起来差不多!

因此,我们可以提出这样的想法,我们希望将课程建模为节点,将考试日期建模为颜色,如果这些节点共享参与的学生,则它们是连接的。因此,当没有相邻的课程/节点具有相同的日期/颜色时,我们的考试安排被解决。好的,让我们创建一个网络,将我们的 40 门课程作为节点,如果参与的学生共享,就将它们连接起来。

创建一个我们 40 门课程的列表。

courses = list(student_data.columns)[2:]

使用 networkx 创建一个网络对象,并为 40 个课程中的每一个课程添加一个节点

class_network = nx.Graph()
class_network.add_nodes_from(courses)

让我们添加边来连接节点。如果 A 班和 b 班至少有一个学生,那么这两个班之间就有一条边。

每个学生参加 5 门课程。我想把它们打包到一个列表中,这样我就可以在这个列表中所有可能的组合之间创建边,因为这个学生不能同时参加这 5 个考试中的任何一个。因此,我在学生中循环,并为每个学生列出一个清单。

without_subj = student_data.drop([‘Major’, ‘Minor’], axis=1) # We don’t need major and minor for the moment
without_subj = without_subj.T # transposelist_of_overlaps = []
for student in name_list:
list_of_overlaps.append(list(without_subj.loc[without_subj[student]].index))

下一步使用一个库(itertools ),它有一个很酷的功能,叫做组合。第一个参数是您想要组合的列表,第二个参数表示一个组合由多少个元素组成。我提供了一个小例子,让您熟悉这个功能。

import itertoolsfor pair in itertools.combinations([1,2,3],2):
 print(pair)(1, 2)
(1, 3)
(2, 3)

因此,我们循环遍历为每个学生创建的重叠列表,然后将列表中的每门课程与其他课程相结合。这使我们能够获得线对并在它们之间形成边。

for sublist in list_of_overlaps:
   for pair in itertools.combinations(sublist, 2):
      class_network.add_edge(pair[0], pair[1])

这个过程产生了 259 个类之间的连接。

n_edges_total = len(list(class_network.edges))print(n_edges_total)
259

描述一个图可能有多少个连接或边的公式是。

公式背后的直觉非常简单,试着说服自己从一个 3 节点的网络开始,到 4 和 5。

n_nodes = len(list(class_network.nodes))
n_edges_possible = (n_nodes*(n_nodes-1))/2

该图中有 780 条可能的边,我们在学校示例中的特定图有 259 条,因此实现了 33%的可能边。

我们可以看看我们学校的网络,上面显示了课程和共享的学生。

fig = plt.figure(figsize=(12,12))
nx.draw_networkx(class_network, with_labels=True)

我们虚构的学校例子中的班级

好了,让我们为着色问题建立算法。首先,我想说这是一个 NP 完全问题,也就是说只能用强力算法才能找到解决方案。所以基本上,我们做的是:

  1. 随机排列节点
  2. 给颜色排序(如果颜色代表日期,从你的第一个日期开始)
  3. 一次处理一个节点,将列表中的第一个合法颜色分配给我们的节点

因为这是一个 NP 完全问题,我们不能得到比这个贪婪算法更好的算法。

[贪婪算法是一种简单、直观的算法**,用于最优化问题。算法在每一步都做出最优选择,试图找到解决整个问题的整体最优方法。**](http://Greedy Algorithms | Brilliant Math & Science Wiki)

并且不同的排序(步骤 1)可以为相同的图给出不同的结果。

为了证明这一点,我们将运行该算法几次以获得一个示例。

如果你感兴趣,这个视频给出了数学基础的解释。有一点我想说的很重要,就是算法在 max 使用 max n+1 个颜色,其中 n 是我们网络中最高度的数字。节点 v_i 的度表示一个特定的节点 v_i 连接了多少个节点。

我们可以通过调用 network.degree 来找出我们的网络有多少度,这可以转换成一个字典,我们取最大值。

max(dict(class_network.degree).values())

它在我们的网络 23 中。但请记住,这是上限,也许我们可以做得更好。24 (23+1)真的是一个好数字吗?我们必须看看我们提供了多少门课程,看看我们是否可以将考试日期缩短。

len(courses)

哦,我们有 40 节课!因此,至少可以节省 16 个日期,这是令人鼓舞的。也许更少的日期是可能的?为了节约起见,我将准备 24 种不同的颜色(来自 matplotlib),这是我们需要的最大数量的颜色。

colors = [
"lightcoral", "gray", "lightgray", "firebrick", "red", "chocolate", "darkorange", "moccasin", "gold", "yellow", "darkolivegreen", "chartreuse", "forestgreen", "lime", "mediumaquamarine", "turquoise", "teal", "cadetblue", "dogerblue", "blue", "slateblue", "blueviolet", "magenta", "lightsteelblue"]

我们还需要 24 个可能的考试日期,我们可以将考试分配到这些日期,还需要一个将颜色转换为日期时间对象的字典。

from datetime import datetime
dates = []
calendar = {}
for i in list(range(14,20)):
    for j in list(range(10,18,2)):
        date = datetime(2021, 6, i, j, 0)
        dates.append(date)
        calendar[date] = []

我们的翻译词典:

from_color_to_date = {col: dates[i] for i, col in enumerate(colors)}

现在我们可以编写我们的贪婪算法了…

def **greedy_coloring_algorithm**(network, colors):
    nodes = list(network.nodes()) 
    random.shuffle(nodes) # **step 1** random ordering
    for node in nodes:
        dict_neighbors = dict(network[node])# gives names of nodes that are neighbors
        nodes_neighbors = list(dict_neighbors.keys())

        forbidden_colors = []
        for neighbor in nodes_neighbors:
            example.nodes.data()[1]
            len(example.nodes.data()[1].keys())
            if len(network.nodes.data()[neighbor].keys()) == 0: 
                # if the neighbor has no color, proceed
                continue
            else:
                # if the neighbor has a color,
                # this color is forbidden
                example.nodes.data()[1]['color']
                forbidden_color = network.nodes.data()[neighbor]
                forbidden_color = forbidden_color['color'] forbidden_colors.append(forbidden_color) # assign the first color 
        # that is not forbidden
        for color in colors:
            # **step 2**: start everytime at the top of the colors,
            # so that the smallest number of colors is used
            if color in forbidden_colors:
                continue
            else:
                # **step 3**: color one node at the time
                network.nodes[node]['color'] = color
                break

运行算法

greedy_coloring_algorithm(class_network, colors)

是时候看结果了。让我获取每个节点的颜色值,并将其传递给一个名为 colors_node 的列表。

colors_nodes = [data[‘color’] for v, data in class_network.nodes(data=True)]nx.draw(class_network, node_color=colors_nodes, with_labels=True)

我们的解决方案至少在视觉上,看起来不需要太多的颜色

这张图表看起来很有希望。有点乱。但是我们也可以查看颜色列表,看看我们最终需要多少种颜色或日期。

len(set(colors_nodes))

10!我们的 40 次考试只需要 10 次约会。谁会想到呢?对我来说,这是惊人的。如此强大的工具。

但是如前所述,这种算法不会可靠地生成 10 个类别,它肯定会生成 24 个或更少,但是会有多少,取决于我们给节点着色的顺序。

让我们对不同的排序做一个简短的比较,看看我们能得到什么,如果我们能得到比 10 更好的话。

number = []
for i in list(range(0,50)):
    greedy_coloring_algorithm(class_network, colors)
    colors_nodes = [data['color'] for v, data in class_network.nodes(data=True)]
    num_col = len(set(colors_nodes))
    number.append(num_col)[10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10]

好的,看起来这个网络很容易解决着色问题。我们每次都得到同样的结果。

我们的最终目标是为我们学校的校长提供一份考试时间表。我们假设考试持续 1.5 小时,学生有 30 分钟的休息时间。

for v, data in class_network.nodes(data=True):
    calendar[from_color_to_date[data['color']]].append(v)max_number_exams_sync = len(max(list(calendar.values()),key=len))rooms = ["Room "+str(i) for i in list(range(max_number_exams_sync))]pd.DataFrame.from_dict(calendar, orient='index', columns=rooms)

我们的最终结果,显然是可以对持续暂停等提供更多的约束。

开始了。我们可以自豪地把考试时间表交给校长,他会惊讶地发现我们只用了 2.5 天就能完成所有的考试。

结论

我声称你将能够使用一些数据和图形着色算法来自动完成困难的任务。您已经看到了如何使用 networkx 创建图形,以及如何在 python 中应用这样的图形着色算法。我用一个很好的应用程序向你展示了这个相当理论化的算法,如果你在一所希望防止考试日期冲突的学校工作,你会看到一个可能的解决方案。但如果没有,我希望你仍然可以将这些知识转移到你的领域。让我知道它是否帮助你在你面临的挑战中找到了解决方案。

图形卷积网络——图形上的深度学习

原文:https://towardsdatascience.com/graph-convolutional-networks-deep-99d7fee5706f?source=collection_archive---------0-----------------------

理解大数据

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

为什么是图表?

图表是最通用的数据结构之一,这要归功于它们强大的表达能力。在各种领域中,机器学习模型已经被成功地用于提取和预测关于图表上的数据的信息,以对复杂元素及其关系进行建模。这里只是一些例子。

  • 道路网络交通模式预测
  • 推断知识图中的缺失信息
  • 为药物研发预测蛋白质相互作用
  • 基于社交网络数据的推荐系统

机器学习在图上的应用(图片由作者提供)

更一般地,当处理图形时,可以处理相当多不同的机器学习任务。

  • 图形分类 —给定一个图形,预测它属于一组类中的哪一个
  • 节点分类 —给定一个节点标签不完整的图,预测剩余节点的类别
  • 链接预测 —给定一个带有不完全邻接矩阵的图,预测每对节点是否相连
  • 社区检测(也称为图聚类) —给定一个图,根据其边缘结构将其节点划分为聚类
  • 图形嵌入 —给定一个图形,将其映射到一个矢量中,同时保留相关信息
  • 图形生成 —学习一组给定图形的分布,并从该分布中采样以生成新的相似图形

图上的机器学习任务(图片由作者提供)

不幸的是,图形数据是非结构化和非欧几里得的,因此建立机器学习模型来解决这些任务并不是立即显而易见的。一方面,节点之间的连接携带重要的信息,另一方面,找到一种处理这种信息的方法是很重要的。

在本帖中,我们将看到如何使用图形卷积网络(GCN)解决这个问题,它将经典卷积神经网络(CNN)推广到图形结构数据的情况。本帖主要来源于 Kipf 等人 2016 、 Defferrard 等人 2016 和 Hammond 等人 2009 的作品。

为什么是回旋?

卷积神经网络(CNN)已被证明在提取复杂特征方面具有令人难以置信的效率,卷积层如今代表了许多深度学习模型的主干。CNN 已经成功地处理了任何维度的数据:

  • 在 1D,处理音频信号—例如用于声音分类
  • 在 2D,处理图像—例如用于早期龋齿检测
  • 在 3D 中,处理扫描——例如用于 MRI 大脑配准的

CNN 如此有效的原因是它们能够学习一系列过滤器来提取越来越复杂的模式。特别地,这些卷积滤波器的特征在于它们的紧密支持,以及平移不变的特性。

稍加创新,我们可以将这些相同的想法应用到图表数据上。与处理欧几里得数据(1D、2D 或 3D)相比,更难解决的问题是,不规则图形上的平移是一个无意义的概念,因此我们需要找到另一种方法来定义图形卷积。

定义图形卷积

在欧几里得域上,卷积通过取平移函数的乘积来定义。但是,正如我们所说的,平移在不规则图上是未定义的,所以我们需要从不同的角度来看这个概念。

关键思想是使用傅立叶变换。在频域中,由于卷积定理,两个信号的(未定义)卷积成为其变换的(明确定义的)分量乘积。因此,如果知道如何计算定义在图上的函数的傅立叶变换,我们可以将卷积定义为

卷积定理(图片作者提供)

这就引出了下一个问题:我们如何定义一个图形的傅立叶变换?

我们将通过与经典的傅立叶变换进行类比来找到这个问题的解决方案。让我们以定义在实直线上的函数为例。其傅里叶变换是其频率项的分解,通过将函数投影到正弦波的正交基上获得。事实上,这些波正是拉普拉斯的本征函数:

1D 的傅立叶变换(图片由作者提供)

因此,如果我们推广这个想法,我们可以将函数的傅立叶变换定义为它在拉普拉斯算子的本征函数的正交基上的投影:

广义傅立叶变换(图片由作者提供)

在图论中,拉普拉斯矩阵定义为 L = D-A ,其中

  • D ,度矩阵,是包含每个顶点所依附的边数的对角矩阵;
  • A 、邻接矩阵为每对顶点指示它们是否由边连接。

如果我们假设图中的边是间接的(但定义可以推广),那么拉普拉斯 L 是实对称正半定矩阵。因此存在使其对角化的标准正交矩阵 U ,并且由在每个 N 顶点处的值的 N 维向量表示的图形信号的图形傅立叶变换可以在此基础上被定义为其投影:

图形傅立叶变换(图片由作者提供)

既然一张图胜过千言万语,那我们就用具体的例子来看看这一切意味着什么。如果我们取对应于规则 2D 网格的德劳内三角剖分的图,我们看到该图的傅立叶基精确地对应于自由方形膜的振动模式。这是有意义的,因为振动板的基本模式正是拉普拉斯的本征函数。

正方形的拉普拉斯特征函数(图片由作者提供)

如果我们取一个随机生成的图,我们仍然可以(在某种意义上!)通过查看它的正交傅立叶基,可以看到图形的振动模式。

随机图的拉普拉斯特征函数(图片由作者提供)

既然我们知道了如何定义图形傅立叶变换,因此也知道了如何定义图形卷积,我们就可以理解图形卷积网络的架构了!

构建完整的神经网络

用于图像识别的所有卷积网络的架构倾向于使用相同的结构。对于像 VGG16 这样的简单网络来说确实如此,但对于像 ResNet 这样的复杂网络来说也是如此。

  1. HxWxC 输入图像通过一系列局部卷积滤波器和池层来提取特征。
  2. 使用例如全局池层将得到的特征通道映射到固定大小的向量中。
  3. 最后,使用几个完全连接的层来产生最终的分类输出。

图卷积网络的架构遵循完全相同的结构!

图形卷积网络(图片由作者提供)

在 GCN 的情况下,我们的输入由以下元素表示:

  • NxC 数组 x 包含图的每个 N 节点的 C 特征
  • NxN 邻接矩阵

为了充分理解上面显示的架构,我们仍然需要澄清最后两个概念:如何定义池层和如何保证卷积过滤器具有紧凑的支持。

关于池层,我们可以选择任何图聚类算法,将节点集合并在一起,同时保留局部几何结构。鉴于最优图聚类是一个 NP-hard 问题,在实践中使用快速贪婪近似。一个流行的选择是 Graclus 多层聚类算法。

关于卷积滤波器的紧支持,我们如何保证我们的 GCN 的卷积层在本地操作?通常,输入 xg 过滤为

在图表上过滤信号(图片由作者提供)

然而,在没有进一步假设的情况下,这样的滤波器不具有紧支撑,而且学习ĝ(λ)的所有分量具有 O(N) 的复杂度。为了解决这两个问题,我们将改为使用次数为 K 的ĝ的多项式参数化:

紧凑滤波器多项式参数化(图片由作者提供)

这就把学习复杂度降低到了 O(K) ,因为我们只需要学习 θ_0,…,θ_ 。除此之外,可以看出 ĝK 局部化的,即如果图上连接两个节点的最小边数大于 K ,则以节点 i 为中心的 ĝ 的节点 j 处的值为 0 。通常情况下,经常使用 K=1 ,对应图像上的 3x3 卷积滤波器:

方形和不规则形状上的紧凑过滤(图片由作者提供)

关于计算优化的最后观察。计算滤波后的信号 ĝ(L)x 的成本仍然和o(n^2一样高,因为乘法涉及 U 。但是这个成本可以通过用切比雪夫多项式来表示多项式,从而减少到 O(EK) (其中 E 是边数),这有一个非常方便的递归公式。

结论

  • 从知识图到社交网络,图的应用无处不在。
  • 卷积神经网络已经在许多领域取得了成功,并且可以推广到图卷积网络。
  • 图上的卷积是通过图的傅立叶变换来定义的。
  • 图形傅立叶变换又被定义为拉普拉斯算子的特征值的投影。这些是图表的“振动模式”。
  • 对于传统的 CNN,GCN 由几个用于特征提取的卷积层和汇集层组成,后面是最终的全连接层。
  • 为了确保卷积滤波器具有紧支撑,我们使用多项式参数化。切比雪夫多项式允许降低计算复杂度。

图形卷积网络—解释

原文:https://towardsdatascience.com/graph-convolutional-networks-explained-d88566682b8f?source=collection_archive---------13-----------------------

对图论和机器学习的不复杂的看法

艾莉娜·格鲁布尼亚克在 Unsplash 上的照片

在我上一篇关于图论的文章中,我简要介绍了我最近感兴趣的话题:图卷积网络。如果你在这里想“这些词是什么意思?”,你来对地方了。在本文中,我们将一步一步地分解这个主题。

第一部分:这个图表是什么?

如果这是你第一次听到“图形”这个词,我很抱歉,但你有一些功课要做。在我们深入这个话题之前,你应该看看我的上一篇文章简要介绍了图论(以及我们为什么关注它)。我会在这里等!

好了,现在你回来了,让我们进一步解释一下。图论是一种数学理论,它简单地将图定义为:

G = (v,e) 其中 G 是我们的图, (v,e) 表示一组顶点或节点(计算机科学家倾向于称之为),以及,或这些**节点之间的连接。**图论的存在是因为我们需要一种通过计算和数学的方式来表示 事物 之间的关系。这些东西可以是任何东西:社交媒体平台上的用户、社区中的物理邻居、地图上的地址或位置(坐标)、图像中的像素或我们大脑中的神经元。特别是与机器学习相关的图论的基础是,当我们可以表示它的关系时,我们的许多数据可以得到最好的理解。因此,我们希望有一种方法来嵌入这些关系,这样我们就可以处理所有的数据。

但是,让我们不要走得太远——我们还有一些术语要定义。

第二部分:卷积?这听起来…令人费解。

让我们把它带回到与我们想了解的其他事物有关系的事物上。很简单,对吧?让我们考虑,例如,我们在一个图像中有像素。这些像素总是与图像中的其他像素相关。该图像具有固定的结构,并且像素以固定的方式保持在其他像素附近。让我们来看看:

角落像素邻域表示法,由 Marco Balsi 通过来源提供。

如果你能看出来,这符合我们对图形的定义。不言而喻,一幅图像被一种不同类型的神经网络卷积神经网络视为一幅图。在本文中,我将浏览卷积神经网络的基本概念来解释图卷积网络。然而,如果你不知道 CNN 的,我强烈建议你在阅读完这篇文章后看看链接的源代码,以便对所有这些主题有一个全面的了解。

从它们的名字中,你可以直觉地看出图形卷积网络和卷积神经网络有一些共同之处。你这样想是正确的——GCN 和 CNN 背后的直觉非常相似。

但是我们的 CNN 用上面这张图片做什么呢?如果从技术上来说这是一个图表,为什么我们需要这个其他的东西?嗯,很高兴你问了!

图像是像素连接到其他像素的隐含图形,但它们总是具有固定的结构。当我们的卷积神经网络在相邻单元之间共享权重时,它是基于一些假设来这样做的:例如,我们可以将 3 x 3 的像素区域评估为“邻域”。我们的卷积神经网络工作的假设依赖于二维常规数据(如果你精通领域术语,也称为欧几里德数据)。

然而,我们的社交媒体网络、分子结构表示或地图上的地址并不是二维的。它们也没有必要的大小或结构。当我们试图将非欧几里德或任意结构的数据塞进 CNN 时,我们会遇到困难,因为这是它们达到极限并不再有用的地方。

第三部分:网络

像素表示与任意结构图,由来源提供。

我们已经确定,我们有这些任意构造的东西网络,不适合我们传统的卷积神经网络。事实上,它们并不真正适用于许多不同种类的神经网络。因此,有图形神经网络,其中图形卷积网络是一个基本的变体。

在本文中,我不会涉及图形卷积网络背后的数学(尽管这很有趣)——我只想讨论直觉。(别急—我在 下一篇 系列文章中覆盖了数学。)

实际上,嵌入表示为结点和边的要素的主要困难在于空间使用的随意性,以及缺少相邻要素之间的欧氏距离。有了这些方面,我们必须基于不同的假设。在这里,我将主要讨论图卷积网络,因为它们已经由 Kipf & Welling 讨论过,尽管有各种方法。

我们已经了解了神经网络中的卷积是一种在邻居之间共享权重的方法。首先,为了确定邻居,我们需要提供一些数据。

在正常的神经网络前向传播函数通过评估我们的当前层的权重、特征表示和偏差来确定下一个隐藏层的特征表示的情况下,我们的图形卷积网络将把邻接矩阵添加到等式中。还有我们的非线性激活函数,因为我试图不要太数学化,我现在在我们的考虑中忽略它。

我们还记得邻接矩阵是什么样子吗?这里有一个复习:

简单图形及其邻接矩阵,由 Safet Penji 通过来源提供。

什么是 A 是我们的图中的连接的矩阵表示,𝝘₅.每个行或列标签代表具有相同数字标签的节点,交叉行/列中的 1 代表这些节点之间的边。

对于那些已经熟悉机器学习的人来说,这看起来有点像*稀疏矩阵,*对吗?看,这毕竟不是什么新鲜事。

实际上,将我们的图表示为邻接矩阵使我们能够以张量的形式提供给网络,这是我们的模型可以处理的。

在我们将这个矩阵交给传播方程之前,我们需要确保我们的值是标准化的。这背后的直觉类似于我们通过神经网络输入的任何数据的标准化:数量级差异极大的值可能会导致我们的网络学习到不应该学习的值的更高权重,只是因为这些值最初比其他值高得多。出于我们的目的,我们将只提到规范化。我将在下一篇文章中更深入地探讨 Kipf & Welling 的方法论和直觉。

一旦我们将数据标准化,我们将在相邻节点之间执行某种聚合—例如,取平均值。这里半监督学习的直觉是相似的节点很可能共享相同的标签。我们可以把这个过程想象成一条消息的传递,GCN 的每一层都收集一个邻居节点的数据,并把它传递到下一个节点。

因此,如果我们有一个三层 GCN,我们可以卷积每个节点的“三阶”邻域。用人类的术语来说,这意味着我们可以将消息传递到三个“跳”之外的每个节点的邻居,并有效地嵌入我们的图的社区结构。然而,如果我们有一个有更多“跳”的图,我们将需要更多的层来有效地嵌入我们的图结构。

如果你和我第一次钻研这个话题时一样,你可能已经准备好休息了。在我让你摆脱困境之前,让我们来看看我们学到了什么:

  1. 我们已经概括了图论的要点,并理解了作为机器学习工程师和数据科学家,我们为什么关心这个问题。
  2. 我们已经研究了卷积神经网络,简要评估了术语“卷积”,并讨论了它们的局限性。
  3. 我们已经简单地了解了图形卷积网络背后的直觉,我们基本上理解了它们为什么工作!

好吧,现在休息一下,别忘了鼓励自己!你在短时间内学到了很多东西。我期待着下一次,在那里我们将深入研究使所有这些工作的数学,并学习如何开始编码我们自己的 GCN。

用于分析复杂碳水化合物的图形卷积神经网络

原文:https://towardsdatascience.com/graph-convolutional-neural-networks-to-analyze-complex-carbohydrates-91f6bae297de?source=collection_archive---------14-----------------------

使用 PyTorch 几何处理生物数据

复杂碳水化合物多样性一瞥。来源:丹尼尔·博亚尔

在过去的几年里,图形卷积神经网络(gcn)吸引了越来越多的关注,越来越多的学科开始使用它们。这也已经扩展到生命科学,因为 gcn 已经被用于分析蛋白质、药物,当然还有生物网络。支持这种扩展的 GCNs 的一个关键优势是,与自然语言等更线性的数据结构相比,它们能够处理非线性数据格式。由于这一特性,我们还为自己感兴趣的主题实施了 GCNs,即复杂碳水化合物或聚糖的研究。

聚糖在生物学中无处不在,修饰着每一个细胞,在病毒感染或肿瘤免疫逃避等过程中发挥着关键作用。它们也是极其多样的生物序列,由数百个独特的构件组成,相比之下,蛋白质只有 20 个,DNA/RNA 只有 4 个,它们也可以在不断增长的聚糖链中以几种不同的构型组合。最后,聚糖是唯一的非线性生物序列,自然形成广泛的分支,其本身可以进一步分支。因此,它们是图的子类,即树的一部分。这使得多糖成为 GCNs 在生物学中适当应用的主要候选物。

之前,我们开发了分析聚糖序列的技术,将它们视为一种生物语言。我们使用了一个递归神经网络设置来研究聚糖序列的非线性,以预测它们的免疫原性、致病性和分类来源。这在一定程度上工作得很好,超过了基线,例如使用基于基序频率的随机森林。然而,我们相信,更强大的算法,能够适应多聚糖的树状结构,将改善现有的应用,并使多聚糖研究的新方法成为可能。这就是为什么我们求助于 GCNs 来建立一个分析多聚糖的新技术。

图形卷积神经网络在多聚糖分析中的应用综述。来源:https://www . cell . com/cell-reports/full text/s 2211-1247(21)00616-1

gcn 通过经由图中节点的邻居来表征节点,或者更准确地说,通过邻居节点的特征来学习图(或树)中的关系。在我们的例子中,我们将单糖(如葡萄糖或半乳糖等聚糖构件)及其连接链视为节点。虽然将单糖视为节点,将连接视为边可能更自然,但我们决定不这样做,以适应仅由一个单糖和一个连接组成的短而重要的聚糖。为了让我们的 GCN 学习节点邻域的特征,我们首先实现了节点嵌入,以便每个单糖和连接类型通过嵌入特征来表示,这些嵌入特征可以由我们的模型学习并用于表征节点邻域。为了最好地表达多聚糖的丰富多样性,我们采用了 128 维包埋法。

接下来,我们必须选择用于执行图形卷积的图形内核。这个过程是上述的通过它的邻居和它们的特征(在我们的例子中,节点类型的嵌入特征)学习节点的过程。在测试了各种图形内核之后,我们最终得到了 k 维图形神经网络操作符,它们受到 Weisfeiler-Leman 算法的启发,用于测试图形同构,并且在我们的数据集上表现出了最佳性能。GCNs 的伟大之处在于,在一个模型中可以有多个图形卷积层。这允许您在不同的粒度级别分析图表/聚糖。虽然第一层可能只考虑直接连接的节点进行分析,但后续层可以扩展这个所谓的感受域,并考虑节点与图中进一步移除的节点的关系。在我们的案例中,我们选择了一个具有其中三层的模型作为最佳模型。

SweetNet 模型架构。来源:https://www . cell . com/cell-reports/full text/s 2211-1247(21)00616-1

这种连续图形卷积层的方法允许模型学习图形邻域,甚至可以预测监督设置中的下游分类任务的特征主题。为了总结从这些步骤中学到的特性,我们使用了汇集层,它从图形卷积层中为后续层浓缩了重要信息。在每个图形卷积层之后,我们首先使用一个 topk 池层,它根据学习到的投影分数将图形投影到一个更小的图形。然后,我们连接来自全局平均池和全局平均池操作的结果。

该最终图形表示跨越三个图形卷积层,然后通过完全连接的神经网络进行路由,以达到相应任务的最终预测。除了标准(泄漏)ReLU、漏失和批量归一化设置之外,我们还将所谓的 boom 层纳入该器件。通常,卷积后的表示的维数在最后部分朝着低维模型输出缓慢减少。然而,boom 层暂时增加了维度(与瓶颈相反),以允许模型摆脱局部最小值并提高性能。我们将这款最终产品命名为 SweetNet,以此向更为人们所熟知和喜爱的碳水化合物致敬。现在,我们可以看看使用多聚糖 GCN 可以做些什么有趣的事情了!

在构建 SweetNet 时,我们确保在所有报告的任务上,我们的预测性能优于之前报告的架构,如上述递归神经网络。这些任务之一是预测聚糖序列是否会被人类免疫系统识别。这是相关的,因为聚糖可能具有很强的免疫原性,例如在过敏原或血型不匹配的情况下,但也具有免疫抑制性,例如在肿瘤免疫逃避的情况下。在我们的数据集上,SweetNet 实现了约 95%的测试集准确率,完全基于聚糖序列。然后,我们提取了这些序列的图形表示,这些序列是通过 SweetNet 模型学习的,该模型在预测聚糖免疫原性方面进行了训练,紧跟在图形卷积层之后。当对此进行可视化时,很明显该模型已经学会了区分两类免疫原性/非免疫原性聚糖。此外,在非免疫原性聚糖中,可以看到一种精细的结构,这种结构让人想起不同类别的人类聚糖(当然,在一个类别中,它们具有序列相似性)。糖脂和 O-聚糖与免疫原性聚糖部分重叠,因为这些聚糖存在于我们的粘膜表面,并被具有免疫原性的微生物模仿。

通过 SweetNet 模型学习的聚糖嵌入预测聚糖免疫原性。来源:https://www . cell . com/cell-reports/full text/s 2211-1247(21)00616-1

除了其他应用,我们还将这种多聚糖 GCN 与用于分析蛋白质序列的递归神经网络相结合,以预测病毒和多聚糖之间的相互作用。从流感病毒到新型冠状病毒病毒,大多数病毒都需要宿主细胞上的特定聚糖才能感染它们。事实上,病毒和宿主聚糖的匹配可以决定病毒的宿主范围。在流感病毒的情况下,一种特定的蛋白质血凝素负责在细胞进入和感染之前与细胞的聚糖结合。不同的流感病毒株具有不同的血凝素序列,这可以影响它们的聚糖结合特异性。这方面的一个例子是禽流感病毒和哺乳动物流感病毒之间的差异。虽然这两种类型的流感病毒主要识别一种称为 Neu5Ac 的特定单糖,即一种唾液酸,但禽流感病毒通常只与α2–3 构型的 Neu5Ac 结合,而哺乳动物流感病毒更喜欢α2–6 构型的 Neu5Ac。一个微妙的结构转变,然而这是防止禽流感病毒“跳过”感染人类的唯一屏障。使鸟类血凝素发生突变,以α2–6 构型与 Neu5Ac 结合,你就能突然用这种突变的禽流感病毒感染人类。

血凝素序列和聚糖结合特异性之间的这种明确关系使我们假设,我们可以使用一种模型来了解这些联系,并预测流感病毒和其他病毒的基于病毒聚糖的受体。因此,我们建立了一种配对模型,给定血凝素序列和聚糖,在回归设置中预测这是否会导致结合。我们很幸运,因为我们有一个实验观察到的来自各种流感病毒株的血凝素和一组聚糖的相互作用的大数据集,我们可以用它来训练和评估我们的模型。

来自 SweetNet 模型的病毒受体预测,该模型被训练用于预测病毒-聚糖相互作用。来源:https://www . cell . com/cell-reports/full text/s 2211-1247(21)00616-1

经过训练后,我们确实可以证明,一个经过训练的模型重现了禽流感病毒与α2–3 连接的 Neu5Ac 和哺乳动物流感病毒与α2–6 连接的 Neu5Ac 的基序。此外,该模型还预测了可能与流感病毒结合相关的其他基序,如硫酸化聚糖基序,这些基序在过去被认为可能是流感受体。我们随后表明,这项研究也可以扩展到其他病毒,如轮状病毒,这是婴儿感染的常见原因。在这里,我们可以表明,一个经过训练的模型预测高度复杂的母乳聚糖与轮状病毒蛋白结合,这些蛋白已经被独立地证明能够结合和中和轮状病毒,证明了母乳的保护作用。通过紧密结合病毒并阻止其结合细胞,聚糖的这种中和作用被我们的身体在各种情况下使用,并且也可以提供一个机会,使用我们的模型来设计具有改善的结合特性的新聚糖,在未来,可以作为一种新型的抗病毒药物。

这就是在多聚糖分析中了解 GCNs 现状的全部内容!反正大部分都是。前往报社了解更多细节。或者前往新闻 新闻稿获取更容易理解的关于我们研究的含义的信息。当然,这里是 SweetNet 的代码,所有使用的数据可在 GitHub repo 或本文的补充表格中找到。如果您对这一领域感兴趣,请不要犹豫,关注此空间,了解机器学习和数据科学应用于糖生物学的未来令人兴奋的发展!

碳水化合物活性酶的图形数据库、GraphQL 和机器学习

原文:https://towardsdatascience.com/graph-database-graphql-and-machine-learning-for-carbohydrate-active-enzymes-dba8500b45cf?source=collection_archive---------30-----------------------

使用 Neo4j 加速您的碳水化合物基因组分析

本文展示了如何:

1.将 CAZy 数据库转换为 Neo4j

2.分析福尔摩沙沉香 KMM 3901 的命名以获得新的见解

3.为语言无关的数据访问构建一个 GraphQL API

4.为纤维素降解预测执行图形嵌入和节点分类

世界上最丰富的聚合物是什么?答案可能会让很多人吃惊:纤维素。它是一种在植物细胞壁中发现的多糖。我们把它做成纸、t 恤和玻璃纸。而第二名也被一种多糖占据:甲壳素。它存在于真菌的细胞壁、鱼的鳞片、蟹、虾和龙虾的外壳中。事实上,所有细胞生物都离不开多糖。

图一。植物含有纤维素,真菌含有几丁质,这是地球上最丰富的两种生物聚合物。在 Unsplash 上sanga Rima Roman Selia拍照。

多糖是碳水化合物的一种形式。顾名思义,多糖是由多个单糖组成的,也就是简单的糖。单糖通过糖苷键连接在一起。有几种类型的单糖(葡萄糖、木糖等)和几种类型的糖苷键(α-1,4 和β-1,3 等)。单糖和糖苷键的各种组合创造了多糖的多样性。例如,糖原、淀粉和昆布多糖也是多糖。但它们是储存化合物,在细胞中充当能量储存库。在一个叫做水解的过程中,细胞可以很容易地将这些分子分解成单糖,然后氧化单糖以获得燃料。相比之下,纤维素和甲壳质都是结构成分。它们很难分解,因此它们可以支持和保护它们的宿主细胞。人类消耗糖原和淀粉,但既不能消化纤维素,也不能消化几丁质。

这就是真菌和细菌出现的地方。每当你看到腐烂的木头,木头腐烂的真菌就在工作。食草动物可以分解纤维素,因为它们的胃肠道中有一群分解纤维素的微生物。几丁质主要被真菌和细菌降解。因此,由于他们的工作,我们的星球还没有被这两种多糖覆盖。

图二。CAZy 数据库的主页。cazy.org 的截图。

这些真菌和细菌能够完成如此伟大的壮举,是因为它们产生某种酶来破坏纤维素或甲壳质中的糖苷键。合成或降解多糖的酶被称为碳水化合物活性酶(CAZymes)。对 CAZymes 的研究不仅仅是关于制造和营养。也给我们带来了生态学的新知识。最终,它也是下一代生物燃料的关键。为了更好地了解多糖的生物循环,由 Henrissat 教授领导的一组研究人员建立了一个名为 CAZy 的数据库,这是碳水化合物活性酶的缩写。他们收集了超过一百万个 CAZyme 序列,并根据它们与碳水化合物底物的相互作用将它们分为六类:

  1. 糖苷水解酶是水解或重排糖苷键的酶。
  2. 糖基转移酶(GTs)是形成糖苷键的酶。
  3. 多糖裂解酶(PLs)是进行糖苷键非水解裂解的酶。
  4. 碳水化合物酯酶(CEs)水解碳水化合物酯。
  5. 辅助活性(AAs)是与 CAZymes 一起作用的氧化还原酶。
  6. 碳水化合物结合模块(CBMs)是 CAZymes 的非催化域。CBMs 将 CAZyme 和碳水化合物结合在一起,从而发生催化反应。

在每个类别中,研究人员根据序列相似性将序列分成不同的家族甚至亚家族。在撰写本文时,有 171 个 GH 系列和 114 个 GT 系列。

图 3。详细 GH13。cazy.org 的截图。

因为 CAZy 是基于序列相似性,并且相似的序列不一定具有相同的功能活性,所以 CAZyme 家族通常包含作用于不同碳水化合物或不同糖苷键的不同成员。有时,一个家族中的底物是相似的。例如,支链淀粉酶(欧共体 3.2.1.41)和α-淀粉酶(欧共体 3.2.1.1)的序列见于 GH13(图 3。),两者都是带有α糖苷键的多糖。

CAZy 团队还注释了来自古细菌、细菌、真核生物和病毒的 10,000 多个基因组,并将结果放在了网站上。一个有机体中的所有酶构成了它的酶名。CAZynome 决定生物体可以代谢哪些碳水化合物,即合成或降解。

CAZy 数据库对于基因组分析来说是一个非常有价值的资源。然而,CAZy 网站更像是一个文本网站,而不是一个数据门户。显示描述性信息,但不提供下载或 API。它不提供序列注释服务(他们只接受离线学术合作)。而且它的访问有时是不稳定的。

为了让 CAZy 更容易理解,我之前写过一篇关于用 AWS 批处理进行 CAZy 注释的文章。在这篇文章中,我在云端实现了 CAZy 最受欢迎的特性请求之一。我的下一个目标是为我自己的数据分析建立一个 CAZy 网站镜像。我之前已经展示了如何使用 Neo4j 来托管基因组注释,因为图形数据库是存储具有复杂关系的数据的绝佳选择。构建用于数据访问的 GraphQL APIs 也非常容易。最后,Neo4j 可以进行图嵌入和节点分类,用于机器学习。这种能力对于生物信息学中的代谢预测非常有用。

我之前的文章解释了如何开始一个 Neo4j 项目。在本文中,我在 Neo4j 桌面中创建了一个名为cazy的项目,并启用了 APOC 和图形数据科学库插件。后来我通过 Apollo 和neo4j-graphql.js为数据库设置了 GraphQL。最后,我用 Neo4j Graph 数据科学库预测了哪些基因组能够降解纤维素。

这个项目的代码存放在我的 Github 仓库中:

https://github.com/dgg32/neo4j_cazy

1.下载并处理数据

为了这个项目,我收集了所有细菌和古细菌基因组的分类学和 CAZy 注释,以及来自 CAZy 的家族描述。从 KEGG 数据库中检索所有四位数 EC 号的描述,即没有通配符的 EC。此外,我从原始菌株描述文件和细菌元数据数据库 BacDive 中注释了 186 个基因组的纤维素降解能力。纤维素降解者的纤维素值为 1,而非降解者的纤维素值为 0。2 代表未知。Neo4j 中的数据结构如下:

图 4。项目的数据模型。图片由作者提供。

所有用于下载和后处理的脚本都可以在我的存储库中找到,还有原始数据和格式化数据。将“data_for_neo4j”中的所有 CSV 文件放入cazy的“import”文件夹中。然后,在 Neo4j 浏览器中使用以下命令导入和索引数据:

导入后,我们可以计算一些关于数据库的基本统计数据。例如,下面的查询计算所有基因组中 GH 家族的平均数量。结果是 16 个 GH 家庭。

接下来,我重新审视了 福尔摩沙琼菲拉 KMM 3901 基因组中的生长激素家族,我的同事 Alexander Mann 在 2013 年对其进行了分析,但其 CAZy 注释已被更新。

图 5。KMM 的 GH 家庭 3901。图片由作者提供。

这种细菌是从绿藻acrosiconia sonderi中分离出来的,可以降解多种藻类多糖。上图显示,KMM 3901 拥有 37 个 GH 家族,是平均 16 个家族的两倍多。与 Mann 等人所做的注释相比。GH130、GH149、GH158、GH168 和 GH171 是 GH 类别中的新成员。

2.Neo4j 中的 CAZynome 分析

在这一部分,我可以做一些类似于在图数据库中分析基因组的分析。我再次以台湾沉香 KMM 3901 的基因组为例。截至本文撰写之时,福尔摩沙属有五个注释的基因组。

图 6。CAZy 资料库中的五个福尔摩沙基因组。图片由作者提供。

我可以通过发出以下命令快速展示 KMM 3901 的独特 CAZy 系列:

结果显示,KMM 3901 有八个独特的天然气水合物和两个独特的天然气水合物,但在天然气水合物、天然气水合物或煤层气类别中没有新的发现。PL28 和 PL37 都含有 ulvan 裂解酶。这是一种降解 ulvan 的酶,ulvan 是一种复杂的硫酸多糖,存在于绿藻 Ulva ( 绿藻门)的细胞壁中。在天然气水合物类别中,清单包含 GH86。该家族包含β-琼胶酶和β-卟啉酶。两者都攻击红藻中的硫酸化碳水化合物。此外,GH168 含有内切-α-(1,3)-L-岩藻聚糖酶( EC3.2.1.211 ),该酶破坏岩藻聚糖中的(1→3)-α-L-岩藻糖苷链,岩藻聚糖是一种硫酸多糖,主要存在于不同种类的海藻中。最后,独特的 GH28、GH78 和 GH105 参与果胶降解。果胶或类似果胶的碳水化合物存在于绿藻中。总之,这些新结果揭示了 KMM 3901 独特的琼胶分解生命策略及其远离其姐妹的生态位。他们还为 Mann 等人的研究增加了一些重要的细节..

接下来,我将 KMM 3901 的 GH 家族组合与数据库中所有的细菌和古细菌基因组进行了比较。在最相似的基因组中,四姐妹甚至不在前一百名。

来自门拟杆菌门的成员已经完成了十大名单。在分类学上,粘质类几丁质类和KMM 3901 在类群水平上有所不同。令人惊讶的是,与 KMM 3901 不同,所有这十种细菌都是从陆地上分离出来的。不幸的是,关于它们的碳水化合物降解能力的信息是不充分的,只有一些关于它们的分类邻居的信息是可用的。例如,muclinic abacter包含成员,如 M帕卢迪斯能降解果胶、木聚糖和海带多糖的纤细藻。不幸的是,他们的基因组都没有在 CAZy 中被注释。

3.为 CAZy 提供 GraphQL

虽然 Cypher 是一种容易学习的查询语言,但它不是我们从 Neo4j 获取数据的唯一方式。GraphQL 是另一种选择。一方面,它的执行是语言不可知的,因此没有掌握 Cypher 的开发人员也可以访问数据。另一方面,现代微服务架构经常需要每个组件通过 HTTP APIs 进行通信。而 GraphQL 是在 HTTP 中公开 Neo4j 的数据的好方法。与 REST 相比,用户可以微调他们的请求,以避免过多的数据交付。要了解更多,请阅读我以前的文章“在 AWS 中构建自己的 GraphQL GenBank”。

在 Neo4j 中为 GraphQL 设置一个 Apollo 服务器非常容易。Neo4j 团队开发了一个名为neo4j-graphql.js的 Javascript 库。这个库自动生成查询和解析器代码。事实上,用户唯一需要做的事情就是定义 typeDefs 模式。然后,客户端可以查询数据,甚至不需要一行密码。index.js中的以下 58 行代码可以为整个项目启动一个 GraphQL 服务器(请先在第 48 行填写数据库的密码):

第 5-44 行定义了访问分类单元、基因组、cazy 和 ec 数据的模式。DataPoint 类型帮助我们检索每个 CAZy 家族的数量。

在终端中运行该脚本:

nodemon index.js

要测试 API,请将您的浏览器指向[http://localhost:4000](http://localhost:4000.)。在左侧面板中输入以下查询,然后按圆形按钮:

图 7。台湾岛及其五个子代基因组的分类信息检索。图片由作者提供。

仅用一个查询,GraphQL 就返回了福尔摩沙的分类细节及其所有五个物种的名称。数据是 JSON 格式的。Python 客户端非常简单:

为 Neo4j 修改 GraphQL 中的数据也很容易。有关更多详细信息,请参考页面右侧的“DOCS”和“SCHEMA”选项卡(图 7。).

4.用节点分类预测纤维素降解

CAZy 注释中的一个目标是预测一个生物体可以代谢什么样的碳水化合物。虽然确切的百分比一直在争论中,但是很明显大多数微生物还没有在实验室中培养出来。幸运的是,我们仍然可以通过宏基因组学或单细胞基因组学获得它们的基因组,而无需培养它们。如果我们能预测它们的碳水化合物底物,我们就能推测它们在自然栖息地的生态作用和它们的工业潜力。这些预测也许能帮助我们找到合适的培养基来培养它们。

使用机器学习来完成这项任务是合乎逻辑的。但是我们需要两个好的数据源:特征(x)和目标(y)。由于 CAZy 完全是关于碳水化合物代谢的,并且数据库中已经注释了超过 10,000 个基因组,所以它们是很好的特征。然而,突出的问题是缺乏目标生化数据。一方面,CAZy 中的许多注释物种尚未进行生物化学研究。另一方面,许多已经被生化研究过的细菌还没有被测序。两者的重叠部分非常小。

对于这个项目,我手动注释了 186 个基因组的纤维素降解能力作为模型训练数据。我的来源是主要的菌株描述和 BacDive。其中,43 个为阳性,另外 143 个为纤维素降解阴性。所有其他的基因组都作为保留样本。

在以某种方式管理了目标数据之后,我继续关注特性数据。类似于自然语言处理(NLP),在机器学习之前,我必须用固定长度的向量来表示所有的基因组。但是我们的基因组是图中的节点,每个节点都有不同的连接组合。好在 Neo4j 中的图形数据科学库为我们提供了图形嵌入。类似于 NLP 中的单词嵌入,图嵌入基于其图拓扑为每个节点生成一个固定长度的向量。然后,我们可以只使用这些向量作为机器学习的特征。

gds.graph.create部分创建内存中的图形投影,以保存机器学习所需的所有数据。gds.fastRP.mutate部分计算图形嵌入,并将结果写回内存图形。

接下来,我调用了nodeClassification.train方法开始训练。在幕后,Neo4j 使用多类节点逻辑回归。我还设置了五重交叉验证,并将“F1 加权”配置为指标。

图 8。培训和测试分数。图片由作者提供。

67%的培训分数和 65%的测试分数都很低(图 8。).我尝试了其他参数,它们并没有改善结果。

尽管如此,我仍然应用该模型来预测维持数据中的纤维素降解:

该模型预测了 11 个对纤维素降解呈阳性的基因组:

其中,首先, 碳小单孢菌是已知的纤维素酶产生菌,它降解疫霉菌 的纤维素细胞壁。然而,傅等人。报道其姊妹 HM134,榜单第二名,纤维素降解阴性。他们的结果有点令人惊讶,因为 HM134 分享了 MM的 61 个 CAZy 家族中的 58 个。碳类和三个例外(GH154、GT75 和 CBM22)与纤维素代谢无明显联系。第三,链霉菌菌株。已知 SirexAA-E 能够分解木质纤维素生物质。第四,黄单胞菌柑橘 pv。citri UI7 是一种分解纤维素的植物病原体,引起 A 型柑橘溃疡病。第五,根据 BacDive链霉菌 ATCC 13879 能否降解纤维素未确定。最后,名单中的其余六人鲜为人知。

结论

本文再次展示了 Neo4j 是一个用于生物信息学研究的强大分析平台。CAZy 中连接丰富的数据在图形数据库中比在关系数据库(如 MySQL)中建模更好。密码语言简单易学,给使用者带来了一种新的思维方式。CAZy 注释现在在一个图中,其中基因组通过它们共享的 CAZymes 连接,CAZy 家族通过共享的 EC 号连接。这可以从数据中带来新的发现,因为对我们人类来说,在上下文中分析复杂的事情更自然。总的来说,这些见解已经存在于数据中,Neo4j 只是让它更加明显。

GraphQL 可以交付来自不同数据源的数据,只要它们符合其规范。它允许没有密码知识的开发人员有效地提取数据。而且肯定能把 Neo4j 转化成更大应用的微服务。但是,它不能取代 Cypher。GraphQL 无法为我们提供连接驱动的查询体验,更不用说聚合和机器学习功能了。

生物信息学中的圣杯之一是根据基因组数据预测新陈代谢。纤维素降解预测的实践突出了这些挑战。小的训练数据集当然导致了低的训练和测试分数。但我们也需要问自己,基于序列相似度的 CAZy 是否真的适合用机器学习进行代谢预测。到目前为止,还没有在这方面取得成功的研究发表。也许基于函数相似性的 EC 数是比 CAZy 更好的特征?

基因组测序变得越来越便宜和容易。宏基因组学和单细胞基因组学也越来越好。因此,基因组数据不再是瓶颈。相比之下,代谢数据很难生成。事实上,基因组和代谢数据之间的差距在未来只会越来越大。生化测试是劳动密集型的,容易出错。细菌菌株描述论文经常忽略提及碳水化合物代谢。此外,结果的数字化是耗时的。最后,已经有许多基因组序列的专用数据库,但是在 2012 年 BacDive 数据库发布之前,没有发现代谢数据。自那以后,更多的代谢数据已经可用,但它们仍然不足以用于任何大规模的机器学习项目。

为了缩小数据差距,BacDive 团队一方面努力从原始研究论文中收集更多的生化元数据。另一方面,他们正计划在他们的散居项目中测试许多已测序的细菌菌株。此外,菌株描述应该标准化,并要求对其出版物进行强制性生化检验。

最后,虽然文章使用了 Neo4j Desktop,但是将其无服务器地迁移到云中实际上是相当容易的。欲了解更多信息,请阅读由威廉·里昂撰写的优秀文章“在云中使用 Neo4j GraphQL 中的空间数据”。一旦迁移到云中,Neo4j CAZy 就可以对公众或定义的一组用户开放,并具有高可用性。无服务器选项也降低了成本。

最后,我衷心感谢 CAZy 团队的辛勤工作。你可以在他们的出版物中读到更多关于这个数据库的信息:https://pubmed.ncbi.nlm.nih.gov/24270786/。

https://dgg32.medium.com/membership

用 Python 进行图机器学习第 1 部分:基础、度量和算法

原文:https://towardsdatascience.com/graph-machine-learning-with-python-pt-1-basics-metrics-and-algorithms-cc40972de113?source=collection_archive---------0-----------------------

通过足球数据集上的关键度量和算法介绍网络

足球网。作者图片

基于图的方法是当今数据科学世界中最迷人和最强大的技术之一。即便如此,我相信我们正处于广泛采用这些方法的早期阶段。在这个系列中,我将从度量和算法的概述开始,提供图形机器学习的广泛演练。我还将通过 Python 提供实现代码,以尽可能保持应用性。在开始之前,让我们讨论一下基于图的方法的价值。

目录

  1. 为什么是图表?
  2. 网络基础
  3. 网络连接
  4. 网络距离
  5. 网络聚类
  6. 网络度分布
  7. 网络中心性
  8. 摘要

为什么是图表?

图是描述和分析具有关系/交互的实体的通用语言

从计算机网络到社交网络到疾病路径,图表在我们身边随处可见。网络通常被认为是自然出现的图形,但界限很模糊,它们确实可以互换使用。

Jure Leskovec 博士在他的图形机器学习课程中概述了几个例子,例如:

图表(作为代表):

  • 信息/知识被组织和链接
  • 软件可以用图形来表示
  • 相似性网络:连接相似的数据点
  • 关系结构:分子、场景图、3D 形状、基于粒子的物理模拟

网络(也称为自然图):

  • 社交网络:社会是 70 多亿个人的集合
  • 通信和交易:电子设备、电话、金融交易
  • 生物医学:基因/蛋白质之间的相互作用调节生命
  • 大脑连接:我们的思想隐藏在数十亿神经元之间的连接中

将数据表示为图形允许我们将复杂的结构信息作为特征嵌入。这在某些领域产生了更高的性能,因为关系结构可以提供大量有价值的信息。除了更强的特征表示,基于图的方法(专门用于深度学习)利用表示学习来自动学习特征,并将它们表示为嵌入。因此,可以在稀疏空间中编码大量高维信息,而不会显著牺牲速度/性能。利用图表的另一个值得注意的好处是可以使用它们完成各种任务。Leskovec 博士提供了对经典应用的见解:

  • 节点分类:预测节点的属性。示例:对在线用户/项目进行分类
  • 链接预测:预测两个节点之间是否存在缺失的链接。示例:知识图完成、推荐系统
  • 图表分类:对不同的图表进行分类。示例:分子性质预测
  • 聚类:检测节点是否形成一个社区。示例:社交圈检测
  • 图形生成:药物发现
  • 图形演化:物理模拟

Jure Leskovec,斯坦福 CS224W:用图进行机器学习

我在这里说得很简短,但是如果你想更深入地了解图形机器学习的应用,我强烈建议你看一看 Leskovec 博士第一堂课的幻灯片。

虽然我们能够嵌入高维数据来实现各种任务的更高性能模型,但网络可能会非常复杂。这是因为:

  1. 任意大小和复杂拓扑结构
  2. 没有固定的节点排序或参考点
  3. 通常是动态的并且具有多模态特征

我们经常需要统计分析、模型和算法来帮助我们理解和推理网络。由于网络固有的关系结构,网络模型有助于模拟信息通过网络的分散和级联。这产生了对如何知识、信息等的巨大洞察力。传播而不仅仅是传播什么。

网络基础

网络(或图)是一组项目之间的联系的表示。这种表示法通常写成 G=(V,E) ,其中 V={V1,…,Vn} 是一组节点(也叫顶点)和 E={{Vk,Vw},..,{Vi,Vj}} 是边的两个集合(两个元素的集合)的集合(也称为链接,表示属于 V 的两个节点之间的连接。在网络可视化中,距离和位置没有任何意义。

作者图片

网络也可以采用一系列不同的结构和属性。

  • 无方向:没有方向,适用于关系对称的情况
  • 定向:有方向,对不对称的关系有用
  • 循环:路径在同一个节点开始和结束,无休止的循环可能会在不小心的情况下阻止终止
  • 非循环:路径在不同的节点开始和结束,这是许多算法的基础
  • 加权:并非所有的关系都是平等的,有些关系更有分量
  • 未加权:所有关系都是平等的(根据网络),通过平等/不存在的加权来显示
  • 稀疏:子集中的每个节点可能都没有到其他每个节点的路径
  • 密集:子集中的每个节点都有到其他每个节点的路径
  • 单部分、二部分和多部分:节点是只连接到一种其他节点类型(例如,喜欢电影的用户)还是连接到许多其他节点类型(例如,喜欢电影的用户)

Neo4J 提供了一个很好的可视化摘要:

Mark Needham 和 Amy E. Hodler 的图形算法

网络也有一些高级方法和技术所依赖的基本属性。

  • 一个图的就是它的顶点数 |V| 。一个图的大小是它的边数 |E|
  • 顶点的是与其相邻的边的数量。图 G 中顶点 v邻居是与 v 相邻的所有顶点所诱导的顶点 Vi 的子集。
  • G 中顶点 v邻域图(也称自我图)是 G 的子图,由与 v 相邻的顶点和连接与 v 相邻的顶点的所有边组成。

有许多带有预加载网络结构的数据集可供使用。这要归功于研究和应用社区分享他们的工作和数据集的热情。为了开始我们自己的网络,我们可以加载这些 NetworkX 的数据集之一,作为一个体育迷,我会选择足球数据集 (M .格文和 M. E. J .纽曼,社会和生物网络中的社区结构,Proc。自然。阿卡德。Sci。美国 99,7821–7826(2002 年))。该数据集由格文和纽曼开放许可,并显示在 NetworkX 数据集上。

作者图片

Graph Summary:
Number of nodes : 115
Number of edges : 613
Maximum degree : 12
Minimum degree : 7
Average degree : 10.660869565217391
Median degree : 11.0...

网络连接

连通图是指每对节点之间都有一条路径的图。在一个图中,可以有多个连接的组件;这些是节点的子集,使得:1 .子集中的每个节点都有到所有其他节点的路径,2。没有其他节点有到子集中任何节点的路径。

强连通分量被认为是节点的子集。子集中的每个节点都有到所有其他节点的路径,2。没有任何其他节点有往返于该子集中每个节点的路径。

标有强连通分量的图。维基百科

弱连通分量是节点的子集,使得用无向边替换其所有有向边产生连通(无向)图,或者所有分量通过某个路径连接,忽略方向。

Graph Summary:
Number of nodes : 115
Number of edges : 613
Maximum degree : 12
Minimum degree : 7
Average degree : 10.660869565217391
Median degree : 11.0

Graph Connectivity
Connected Components : 1...

网络距离

两个节点之间的距离是它们之间最短路径的长度。路径长度由从 x 到 y 节点从头到尾包含的步数来确定。

寻找这个距离,特别是对于大比例的图形,计算起来非常昂贵。这里有两种算法是图论的核心:

  • 广度优先搜索(BFS):根据连通性“发现”层中的节点。它从根节点开始,并在进一步遍历图之前找到最直接的连接层中的所有节点。

发现节点的顺序。维基百科

  • 深度优先搜索(DFS):“访问”节点的方法是,在沿着图中不同的路径前进之前,从根节点一直遍历到它的第一个叶节点。

访问节点的顺序。维基百科

当我们想要将它聚合到图形级别时,有两种常见的方法可以做到:

  1. 平均距离:每对节点之间的平均距离。当网络未连接时,这通常限于最大的组件。
  2. 直径:任意一对节点之间的最大距离。

它们中的每一个都应该与您建模为图形的数据的领域知识成对使用。

Graph Summary:
Number of nodes : 115
Number of edges : 613
Maximum degree : 12
Minimum degree : 7
Average degree : 10.660869565217391
Median degree : 11.0

Graph Connectivity
Connected Components : 1

Graph Distance
Average Distance : 2.5081617086193746
Diameter : 4...

网络聚类

聚类是对网络开始分解和理解其复杂性的重要评估。图中的三元闭包是指共享边的节点连接起来的趋势。当人 A 是人 B 的朋友,人 B 是人 C 的朋友时,这通常在社交网络图中进行,因此对人 A 的建议可能是与人 C 交朋友。这是有证据表明在大多数现实世界网络中,主要是社交网络中,节点倾向于创建由相对高密度的关系表示的紧密结合的组。

衡量图中聚集趋势的一种方法是聚集系数。有两种常用的方法来测量聚类系数:局部和全局。

局部聚类系数:彼此是朋友的节点的朋友对的分数。

公式:A 的朋友对的数量/A 的朋友对的数量

全局聚类系数有两种方法:

  1. 图中所有节点的平均本地聚类系数。
  2. 传递性:网络中三角形“开放三元组”的百分比。这将赋予度数较高的节点较大的权重。
Graph Summary:
Number of nodes : 115
Number of edges : 613
Maximum degree : 12
Minimum degree : 7
Average degree : 10.660869565217391
Median degree : 11.0

Graph Connectivity
Connected Components : 1

Graph Distance
Average Distance : 2.5081617086193746
Diameter : 4

Graph Clustering
Transitivity : 0.4072398190045249
Average Clustering Coefficient : 0.40321601104209814

网络度分布

无向图中一个节点的度是它拥有的邻居的数量。图的度分布是整个网络度的概率分布。

在无向图中,它被简单地称为度,但是对于有向图,我们得到了入度和出度分布。入度分布表示图中每个节点的入链分布。有人认为,在现实世界的网络(特别是社交网络)中,当我们在双对数标度上绘制学位/学位分布时,它代表幂律分布。人们一直在争论,当使用统计上严格的技术时,这些无标度网络实际上是非常罕见的,其他人认为对其进行测量过于严格。在任何情况下,评估程度分布对于理解你的网络都是重要的,但是它并不能洞察网络如何随时间演变。

作者图片

网络中心性

虽然我们正在处理一个非常小并且可以理解的网络,但是这些可以很容易地扩展到难以理解的复杂性。当网络变得如此庞大时,使用中心性度量来指导我们理解数据是势在必行的。

中心性是一种考虑图中节点/边重要性的方法。根据您的领域/数据,您应该使用不同的假设,这自然会引导您评估不同的中心性度量。你可以用一些方法来量化网络中的“重要性”:连接度的数量,到其他节点的平均接近度,通过节点的最短路径的比例,等等。

集中性测量的一些应用可用于:

  • 在社交网络中寻找有影响力的节点
  • 识别向许多节点传播信息或防止流行病的节点
  • 交通网络中的枢纽
  • 网络上的重要页面
  • 防止网络崩溃的节点
  • 还有更多!

你可以使用大量中心性;我将在这里讨论几个关键指标,但是我强烈建议阅读 NetworkX 的图形文献文档,以找到适合您的领域的关键指标。

作者图片

对于网络可视化,我将使用 nx-altair ,因为它提供了简单的交互和编辑功能。在下面的图片中看不到交互,但是如果你在笔记本上运行这段代码,你可以很容易地添加过滤器和悬停。

程度中心性

假设:重要节点有很多连接。

这是中心性的最基本的衡量标准:邻居的数量。它对无向网络使用度,对有向网络使用入度或出度。度中心性值通常通过除以简单图 n-1 中的最大可能度来归一化,其中 n 是 g 中的节点数。

作者图片

作者图片

接近中心性

假设:重要节点靠近其他节点。

这是所有 n-1 个可达节点中到一个节点的平均最短路径距离的倒数。如果节点是断开的,那么您可以仅基于可以到达它的节点来考虑它的接近中心性,或者您可以仅考虑可以到达它的节点,并通过它可以到达的节点的分数来归一化该值。

作者图片

作者图片

中间中心性

假设:重要节点靠近其他节点。

节点 v 的介数中心性是通过 v 的所有对最短路径的分数的总和。该公式主要查看通过节点 v 的节点 s 和 t 之间的最短路径的数量,并将其除以 s 和 t 之间的所有最短路径的数量(并对不以 v 开头或结尾的所有路径求和)。在有很多节点的图中,介数中心值会更大。为了对此进行控制,我们将中心性值除以图中节点对的数量(不包括 v)。当网络中有多条最短路径时,这种度量就变得复杂了。

因为这种计算可能非常昂贵,所以通常为节点对的样本计算这种度量。这个度量也可以用来寻找重要的边。

作者图片

作者图片

特征向量中心性

假设:重要节点与中心节点相连。

特征向量中心性基于其邻居的中心性来计算节点的中心性。它测量网络中一个节点的影响力。基于到高得分节点的连接比到低得分节点的同等连接对所讨论节点的得分贡献更大的概念,相对得分被分配给网络中的所有节点。高特征向量分数意味着一个节点连接到许多本身具有高分数的节点。

作者图片

作者图片

PageRank

假设:重要节点是那些有许多来自其他重要节点的内链接的节点。

算法:

  1. 从一个随机节点开始。
  2. 给所有节点分配 1/n 的 PageRank。
  3. 随机选择一条输出边,并沿着它到达下一个节点。
  4. 执行基本的 PageRank 更新规则:每个节点将其当前 PageRank 的相等份额给予它所链接的所有节点。
  5. 每个节点的新 PageRank 是它从其他节点接收的所有 PageRank 的总和。
  6. 重复 k 次。

这就是臭名昭著的谷歌的 PageRank 算法。它从超链接网络结构来衡量网页的重要性。它根据每个节点有多少来自其他节点的链接,给每个节点分配一个重要性分数。在大型网络中,比例 PageRank 是首选,因为它带有一个“阻尼参数”alpha。这是在算法中随机选择一条输出边跟随另一个节点的概率,当网络中存在输出节点的闭环时,这尤其有益。

作者图片

作者图片

枢纽和权威机构(点击量)

假设:具有来自好的中心的输入边的重要节点是好的管理机构,具有到好的管理机构的输出边的节点是好的中心。

算法:

  1. 给每个节点分配一个权限和中心分数 1。
  2. 应用权限更新规则:每个节点的权限分数是指向它的每个节点的中心分数的总和。
  3. 应用中心更新规则:每个节点的中心分数是它所指向的每个节点的权限分数的总和。
  4. 通过每个节点的总得分来标准化每个节点的权威和中心得分。
  5. 重复 k 次。

HITS 算法从一个根或一组高度相关的节点(潜在的权威)开始。那么链接到根节点的所有节点都是潜在的集线器。基础被定义为根节点和链接到根节点的任何节点。连接基本集合中节点的所有边都被考虑,并且这集中在与特定查询相关的网络的特定子集上。

作者图片

作者图片

作者图片

作者图片

摘要

图形机器学习的基础是实体之间的连接。随着图变得非常大,使用度量和算法来理解和获得图的特征是必要的。根据您的环境,不同的度量和算法将被证明是有用的,更重要的是,对您的用例有意义。

此外,我们可以在监督或无监督的学习任务中使用这些度量作为特征,但我们必须小心使用,因为它们可以添加与信号一样多的噪声。

除了更多的度量和算法,深度图 ML 涵盖了广泛的监督和非监督学习任务。从幼稚到先进的技术,我们可以使用图形结构和推理来超越结构化数据。在未来的章节中,我将介绍这些机器学习任务(节点、边和图形级别)的真实数据。

参考文献

1 足球数据集 (M .格文和 M. E. J .纽曼,社会和生物网络中的社区结构,Proc。自然。阿卡德。Sci。美国 99,7821–7826(2002 年))

[2]克劳迪奥·斯塔米尔,奥尔多·马尔祖洛,恩里科·德乌塞比奥,图机器学习

[3]马克·李约瑟,艾米·e·霍德勒,图算法

[4] Estelle Scifo,使用 Neo4j 进行动手图形分析

您可以在这里找到本系列的第 2 部分:

基于 Python 的图机器学习第 2 部分:加密朋克交易的随机图和扩散模型

原文:https://towardsdatascience.com/graph-machine-learning-with-python-pt-2-random-graphs-and-diffusion-models-of-cryptopunks-trading-99cd5170b5ea?source=collection_archive---------7-----------------------

通过图形模拟和建模密码朋克交易数据

在第 1 部分中,我们讨论了网络基础知识、网络连通性、网络距离、网络聚类和网络度分布。如果你刚刚开始,我建议你先从这里开始:https://towardsdatascience . com/graph-machine-learning-with-python-pt-1-basics-metrics-and-algorithms-cc 40972 de 113

在第二部分中,我将深入探究我们如何推理网络,并开始通过随机图、扩散模型、模拟和建模对它们进行建模。

在我们开始之前,先简要回顾一下什么是加密朋克:

CryptoPunks 是以太坊区块链上的 NFT(不可替换令牌)集合。这是交易量最大、价格最高的非金融交易之一。crypto、NFTs 和 Web3.0 的深度远远超出了本故事的范围,但现在您需要知道的是,这些都是非常令人垂涎的数字令牌(想象图像),每个都是唯一标识和验证的。由于它们的受欢迎程度,它们经常被出价并以高价售出,就像今天实物艺术品的个人拍卖一样。你可以在 OpenSea 上查看这里的收藏。

目录

  1. 介绍
  2. 网络拓扑结构
  3. 随机图
  4. 扩散模型
  5. 摘要

介绍

Bojan Tunguz 将的 CyptoPunks 数据集上传到 Kaggle 上。下面是数据集的简要简介,据作者介绍,“数据集由 2017 年以来的所有 CryptoPunk 交易,以及 10,000 名 Punk 的 PNG 图像组成。交易包括 2017 年的初始朋克“索赔”、用户之间的朋克销售,以及以 ETH 和美元等值的销售价格、出价和报价;业主可以在 ETH(报价)中列出任何价格的朋克,钱包中有 ETH 的任何人都可以出价购买朋克,业主有权决定是否接受”。

在开始之前,让我们做一些基本的数据操作,使数据帧处于适当的状态,以将数据建模为图形。数据集包含有关“撤回投标”、“投标”、“售出”、“报价”、“转让”、“索赔”、“T6”、“撤回报价”、“包装”和“取消包装”交易的信息,但我们将只过滤投标和售出交易,以保持最初的可控性。

作者图片

每笔交易都是通过以太坊进行的,它很可能类似于一个对数分布——大量的价值处于较低的金额,较少的价值位于右尾。

密码朋克买卖的以太坊直方图。作者图片

密码朋克买卖的对数归一化以太坊直方图。作者图片

当我们在图中建模时,将以太坊值标准化和规范化会有很大帮助,因此编码(颜色、大小等。)并没有扭曲到你根本看不出多少的地步。

网络拓扑结构

我们可以从第 1 部分中讨论的相同概念开始评估网络拓扑——度量和可视化。由于网络是巨大的,可以占用大量的计算资源来可视化,我们现在只绘制一个子集。

密码朋克网络(子集)。作者图片

理解一个网络的第一个突出的方法是用它的度数频率。大多数真实世界的网络倾向于遵循幂律度数频率分布,其中有许多度数较低的节点和少数度数较高的节点。

密码朋克买卖的度数频率直方图。作者图片

密码朋克买卖的对数度频率直方图。作者图片

度数频率分布严重向右倾斜,但是网络看起来确实像大多数真实世界的网络一样。作为其自然结果,由于形成三元组的高趋势,典型的网络具有低平均距离和高聚集系数。这实质上意味着我们有小而紧密的社区——社交网络通常倾向于通过社区中的共享节点将人们联系在一起。

Graph Summary:
Number of nodes : 6672
Number of edges : 31033
Maximum degree : 618
Minimum degree : 1
Average degree : 9.302458033573142
Median degree : 3.0

Graph Connectivity
Strongly Connected Components : 3959
Weakly Connected Components : 20

Graph Distance
Average Shortest Lengths of Strongly Connected Components : 0.0014808991156887005

Graph Clustering
Transitivity : 0.03990005247307336
Average Clustering Coefficient : 0.06520058506424808

我们在这里看到一个非常低的聚集系数&传递性,但重要的是要记住,网络是建立在数字市场的交易(出价和出售)基础上的,而不是建立在彼此是朋友的基础上的。事实上,分散加密世界的整个前提和承诺是匿名化和自治,所以我们没有看到三元闭包的高趋势实际上是有意义的。

类似于我们在第 1 部分中看到的,我们还可以为每个节点创建中心性度量来表示重要性。不过,在这一部分,我将创建一个新的度量标准,它是中间中心性的变体——“流中心性”。工程学教授路易斯·阿马拉尔称之为流中心性,他声称这是网络中实体重要性的一个强有力的标志。我强烈建议亲自阅读论文,尤其是如果你对体育分析感兴趣,或者你可以等待我计划在未来写的关于我将心流中心性应用于 NBA 比赛的故事。简而言之,流中心性是中间中心性的归一化对数。

投标和出售密码朋克的用户的介数中心性直方图。作者图片

投标和出售密码朋克的用户的日志流中心性直方图。作者图片

竞价和出售密码朋克的用户的归一化流中心性直方图。作者图片

由于它是一个经济网络,很容易有一个节点没有指向它的边(没有交易出售给没有创造其他人可以出价的东西的人),这就是为什么我们看到如此大量的低价值交易。

基于流中心性的密码朋克网络。作者图片

为我们的网络添加流量中心的颜色,创造了一个令人难以置信的加密朋克交易网络的视图。我们可以清楚地看到它确定了我们网络的某些社区和纵向部分。

虽然这种观点看起来很吸引人,但我们并不能从中得出什么结论。度量和算法是分析网络的最天真的方法,但是我们也可以模拟随机图来模拟人工网络效应,并在封闭的环境中研究我们的现象。

随机图

到目前为止,我们对图的总体了解有多少?已经发现的,可能更常见于社交网络图的是:

  • 由于三元闭合,聚类系数较高
  • 小平均距离
  • 类似幂律的度分布
  • 群落结构

本质上,这意味着社交网络图中的节点或人具有形成三元组或“与朋友的朋友建立链接”的高倾向,不具有他们所链接的长的节点链,只有少数节点具有高的度值,但是大多数具有低的度值,并且具有形成社区或子图的内在性质。

有了这些知识,我们就可以对随机图进行建模,因为如果我们可以创建具有这些属性的图,那么它就允许我们进行模拟,测试假设,并最终帮助我们更好地理解为什么现实世界的网络具有它们所具有的属性。

一个很好的起点是查看我们网络的度数频率的对数图。

度频率的双对数标度。作者图片

erdős–rényi 模型

算法:

作者图片

这是一个简单的网络模型,因为它没有利用任何假设,这有其缺点,因为它通常不会产生现实的网络。由于泊松分布,它不允许网络有很高的度数,所以没有集线器。通常会产生较低的聚类系数,因为随着节点数的增加,聚类系数会收敛到 0。因此也没有社区结构,但一个好处是它的平均距离很短。

除了对模拟网络进行建模,我们还可以快速创建许多这样的模型,然后查看传递性和聚类系数的分布,以评估相似性。

erdős–rényi 模型度频率的双对数标度。作者图片

模拟 erdős–rényi 模型的传递性和平均聚类系数。作者图片

我们看到对数度频率直方图不遵循幂律模式,并且我们的传递性和平均聚类最终比我们所拥有的低一个数量级(~0.03)。

偏好依附模型

算法:

作者图片

这个模型创建了更丰富的效果,因为随着节点的增加,度分布接近幂律。因此,这通常会产生与真实世界网络相似的度数分布。

偏好依附模型度频率的双对数标度。作者图片

模拟偏好依恋模型的传递性和平均聚类系数。作者图片

我们可以确认这个学位分布和我们差不多!传递性和平均聚类系数比较接近,但仍然相当低;我想通过对超参数的一些调整,我们将能够使这个模型更接近我们的网络。

这个模型的一个变体(powerlaw_cluster_graph)实现了这一点,还增加了一个额外的步骤,即添加一条以概率 p 闭合三角形的边。

小世界网络

算法:

作者图片

这个模型并没有真正捕捉到度分布的幂律分布,但是它在平均距离和聚类系数方面有更大的灵活性。随着 p 从 0 增加到 0.01,平均距离迅速减小,平均聚类系数缓慢减小。

小世界网络度频率的双对数标度。作者图片

模拟小世界网络的传递性和平均聚集系数。作者图片

度分布和我们的一点都不像,而且传递性和聚集系数也比较大。我们很可能没有一个网络可以很容易地用这个来建模。

默认情况下,此模型是断开连接的,这有时是不可取的。这个模型的一个变体可以运行 t 次,直到它返回一个连通的小世界网络。另一个变体,newman_watts_strogatz_graph,运行一个类似于小世界的模型,但是不是重新布线边,而是以概率 p 添加新的边。

这些随机图的价值在于,我们可以找到一个能够很好地模拟我们的网络的图,然后进行各种实验或测试假设,以推断一个进化的网络。扩散模型就是一个很好的例子。由于巨大的计算成本,这通常可以在与我们的网络匹配良好的随机图上进行,但在这种情况下,我们可以只使用我们正在工作的网络。

扩散模型

网络传播帮助我们回答这样的问题:一个想法、一种行为或一种病毒是如何在人群中传播的?它考虑了传染病的性质或可能对传播产生重大影响的想法:它的传染性如何,传染期有多长,想法是好是坏,等等。此外,受影响人群的网络结构对传播的发生也非常重要。

每个模型都有不同的超参数,这取决于它们的功能和假设。此外,我们还需要指定种子节点——或者最初被“感染”的节点。这可以是总节点的百分比、随机子集或基于指标的前/后 N 个节点(这是我们将使用的)。

扩散模型分为几类,主要的有:流行病、意见网络、动态网络模型。流行病是这个故事的主要焦点(有些是关于动态网络模型的),因为我们正在处理我们网络中的具体传输——无论一个用户向另一个用户出价还是出售一个密码朋克。如果我们在处理模糊的想法或行为,意见网络可能更有效(ps。看看认知观点动态模型,挺有意思的!).动态网络模型是流行病模型的一个特殊子集,它研究具有可以随时间演化的拓扑结构的网络。

SI 模型

“易受感染”模型假设个人在流行病期间经历两个阶段:

  • 易感:未被感染的节点
  • 被感染的:已经被感染并且可以感染其他节点的节点

模型动态:

  • 从一组受感染的种子节点开始。
  • 在每次迭代中,每个被感染的节点都会以一定的概率 p. 将疾病传播给其易感染的邻居(如果网络是有向的,则是它所指向的节点)
  • 一旦一个节点被感染,它将永远被感染。

SI 的扩散率。作者的图像

我们通过选择具有最高流中心性值的前 25 个节点来识别种子节点。感染的概率被统一设置为 0.1,我们发现该模型在大约 50 次迭代后收敛。在这个模型中,所有可以从种子节点到达的节点最终都会被感染。

SIS 模型

“易受感染易受感染”模型假设节点可以从感染中恢复并再次变得易受感染(从疾病中恢复或失去传递信息的兴趣)。

在这个模型中,节点只是暂时被感染。

模型动态:

  • 从一组受感染的种子节点开始。
  • 在每次迭代中,每个被感染的节点将:1 .以概率 p 和 2 将疾病传染给易感的邻居。有可能变得敏感 s.

SIS 的扩散率。作者的图像

这个模型与之前的模型采用了相同的参数,但是我们还增加了一个 5%的重磁化率参数。这也显示在我们的流行图中,因为它似乎不会在 200 次迭代内收敛;这是由于一些节点再次受到感染。在这个模型中,级联将继续,直到没有被感染的节点。

SIR 模型

“易感染已感染已移除”模型假设被感染可能会使您完全没有资格再次感染相邻节点(即因感染病毒而发生的死亡)。

节点被暂时感染,然后它们被“移除”,并且不能再感染它们的邻居。

模型动态:

  • 从一组受感染的种子节点开始。
  • 在每次迭代中,每个感染节点将以概率 p 将疾病或思想传递给其易感邻居,并以概率r将其移除

SIR 的扩散率。作者的图像

我们增加了一个节点被移除的 5%的概率,现在我们看到该模型在大约 100 次迭代后收敛。这可能意味着所有节点都已被感染,或者足够多的关键节点已被感染并被删除,因此其他节点都不会被感染,这意味着在该模型中节点可能仍然易受感染。在这个模型中,随着被删除的概率增加,越来越少的节点在早期被感染,并且最终被删除的节点的数量减少。

独立级联模型

该模型假设每条边可以具有唯一的传输概率,这意味着传输取决于节点的关系/影响因素的性质。

模型动态:

  • 从一个网络开始,与每个边( ev )相关联的概率 P( uv ),以及在时间 t=0 时感染节点的初始集合。
  • 在每个时间步 t ,在时间 t -1 被感染的任何节点 u 将以概率 P( uv )感染每个未被感染的邻居 v

独立级联的扩散优势。作者的图像

在许多方面,这个模型是一个广义的 SIR 模型,因为当没有新的节点被感染时,该过程结束。我们的网络没有那么多长链,这就是为什么我们发现它在大约 15 次迭代时收敛得相当快。这个模型是一个概率模型,引入了一定程度的随机性。

线性阈值模型

这个模型通常与行为和想法非常一致。它假设想法、行为、创新或传染病的复杂性,或者需要多次接触才能接受它。

节点在[0,1]中有一个阈值,表示它们对采用该行为的敏感程度。边具有表示一个节点对另一个节点是否会采用该行为有多大影响的权重。如你所料,一个节点的所有传入边的权重总和必须为 1,因为这些是唯一有可能产生影响的节点。如果一个节点有一组已经采用该行为的邻居,并且它们的边的权重加起来至少达到该节点的阈值,则该节点将采用该行为。

模型动态:

  • 从一组受感染的种子节点开始。
  • 在每个时间步 t ,如果“足够多”的采用邻居被感染,则任何节点 u 被感染。
  • 特例:如果一个节点 u 的邻居中至少有一部分被感染,那么这个节点就会被感染

线性阈值的扩散流行。作者的图像

我们在这里看到最快的收敛,大约 10 次迭代,这可能是由于选择了 25 个最大的流中心性节点。在平均距离较低的网络中选择这么多“中心”节点,本质上意味着最初被感染的种子节点集很有可能控制扩散。在确定了边的权重、节点的阈值和初始采用者之后,这个模型是完全确定的。在你固定了节点和初始采纳者的边的权重之后,这个模型是完全确定的。

摘要

在这个故事中,我们超越了度量和算法的网络拓扑,进入了模拟和建模的世界。这是为什么图形不仅非常有价值,而且非常迷人的一个非常重要的方面。我们能够以一种动态的、进化的方式来检验假设和进行实验,否则这是不可能的。如果你把这个话题放到贝叶斯网络中,即使这个话题本身也有其独特的深度,但这将被保存到一个单独的故事中。

在本系列的以下部分中,我将从无监督、有监督和深度学习的角度深入社区结构和实际的机器学习任务。感谢你现在的阅读和学习,为了乐趣跟随吧!

参考文献

1 Bojan Tunguz,crypto 朋克

[2]克劳迪奥·斯塔米尔,奥尔多·马尔祖洛,恩里科·德乌塞比奥,图机器学习

[3]马克·李约瑟,艾米·e·霍德勒,图算法

[4] Estelle Scifo,使用 Neo4j 进行实际图表分析

[5]伊斯利,大卫和克莱恩伯格,乔恩。2010.网络、人群和市场:关于高度互联世界的推理

您可以在这里找到本系列的第 3 部分: