TowardsDataScience-博客中文翻译-2022-七-

TowardsDataScience 博客中文翻译 2022(七)

原文:TowardsDataScience

协议:CC BY-NC-SA 4.0

最著名的随机数发生器研究

原文:https://towardsdatascience.com/a-study-of-the-most-famous-random-number-generator-13925cd55783

解释线性同余生成器及其缺点

Unsplash 上的 Edge2Edge 媒体拍摄

如果你从事编程已经有一段时间了,那么你很可能在某个项目中从事过随机数生成的工作。

当我第一次在程序中使用随机数时,我没有质疑随机数生成是如何工作的。我一直假设生成的数字是真正随机抽取的。

然而,一个简单的想法就可以提出这个问题。

任何程序都是由特定的指令序列组成的。如果我们向它提供一个输入,我们每次提供那个输入都会得到相同的输出。我们称这个属性为决定论。试图用程序生成随机数是试图从确定性工具中获得随机行为,这有点自相矛盾...

意识到用计算机不可能得到一个真正的随机数生成器,研究人员有了一个想法:得到看起来随机的序列就足够了。

毕竟,没有人能够说出一个数字序列是否是随机抽取的。只要每个数字都落在生成器正在处理的范围内,总是有非零的概率得到我们能想到的任何数字序列。

例如,随机数生成器可能会连续一千次返回相同的数字。概率确实低,但是还是有可能的

普通人不会对连续几次返回相同数字的随机数发生器满意,也不会对如下序列满意:

  • 3 -> 4 -> 5 -> 6 -> 7 -> …
  • 2 -> 6 -> 18 -> 54 -> 162 -> …
  • 2 -> 4 -> 16 -> 256 -> 65536 -> …

这样的例子有哪些共同点让我们不满足?它们有一个易于检测的图案。

这可能会让你吃惊,但是你知道大多数随机生成器并不比这更复杂吗?

直到最近还被广泛使用的最著名的随机数发生器并不返回前一个数的增量、乘以 3 或*方,而是执行以下操作:

其中 ab 都是选择的常量。 M 定义了我们生成的数字的范围。

使用此功能,我们能够生成如下序列:

72 -> 5 -> 614 -> 37 -> 140 -> …

作为用户,我们在这个序列中看不到任何模式。所以我们可以说它是随机的。如果有人对这个函数足够熟悉,这可能是一种模式,让他们说这个序列可能是用这个特定的函数绘制的。

这个随机数发生器被称为线性同余发生器

在接下来的章节中,我们将讨论这个随机发生器有多糟糕,并尝试改进它。

线性同余发生器是好的随机发生器吗?

为了评估随机数生成器的质量,我们将使用两种可视化效果:位图随机漫步。这两种方法都评估我们生成的数字的特定位。

我们先通过固定abM来选择一个直线发电机。已经证明,最佳线性同余生成器满足以下条件:

  1. Mb 互质
  2. a-1 能被 M 的所有质因数整除
  3. a-1 能被 4 整除如果 M 能被 4 整除

让我们为函数选择 C 语言中使用过的值(显然满足上述条件)。

最高有效位 的位图给出如下内容:

最高有效位的位图

每个生成数 Xn+1 由一个像素表示。如果数字的最高有效位等于 0,则该像素为黑色,否则为白色。

位图确实是随机的,我们没有任何模式。

让我们看看 2D 随机漫步给出了什么。

使用第 31 位和第 30 位的随机游走

通过 2D 随机游走,我们同时评估 2 位。两位给 四个 可能值。基于该值,我们在四个 方向上、下、左、右中的一个方向上移动。这里我们评估的是 Xn+1 的两个最高有效位(第 31 位和第 30 位)。

随机漫步看起来真的是随机的,没有任何模式。我们可以说这是一个很好的随机数生成器吗?在评估其他位之前。

我们来评价一下中间的,比如 15 号。以下是该位的位图和随机游走。

第 15 位位图

使用第 15 和第 16 位的随机游走

这次情况不同,我们可以看到一些模式。在位图中,你可以看到一些相同颜色的线条。在随机漫步中,你可以看到这个形状在一个对角线轴上是对称的,并且永远重复...对于所谓的“随机”行为来说,这不是好消息。

让我们看看第一位(最右边的位)会发生什么。

第一位位图

使用第 1 和第 2 位的随机游走

嗯,这两个结果中没有什么随机。如果放大位图,会发现黑白像素交替出现。在随机漫步中,它会上、下、右、左,并且永远重复。为什么会这样?

第一位是奇偶校验位,它表示数字是奇数还是偶数。如果你用这个随机数发生器产生任意的序列,你会看到每个奇数后面跟着一个偶数,每个偶数后面跟着一个奇数,就像我们在本文前面看到的序列。因此,第一位在值 0 和 1 之间交替。这解释了位图图形。对于随机游走,方向由第一位和第二位决定。正如我们将在接下来的章节中看到的,在四个步骤之后有一个循环。**

如果你对剩下的比特做同样的操作,你会得出结论,当我们向右移动比特时,模式变得更清晰,随机性变得更差。

在下一节中,我们将研究为什么会发生这种情况。

第一点有什么问题

利用线性同余发生器, X{n+1} 的第一位仅由 aXn* 和 b 的第一位决定。对于奇数 a 和奇数 b ,我们从等式得到:*

  • 如果 Xn 是奇数那么* X{n+1} 是偶数*
  • 如果 Xn 是偶数那么* X{n+1} 是奇数*

这证明了上一节中位图的结果。

因此,也许不同的奇偶校验 ab 可以解决第一位的问题?让我们看看下表。

从这个表中,只有奇数 a 和奇数 b 能够给我们所有可能的数字。因此,我们不能做得比我们得到的结果更好。我们说第一位的周期长度为2,因为我们有一个长度为 2 的序列,它永远重复。

第二点怎么样

类似地,让我们检查b 上的条件,这些条件允许获得第二位的所有可能值。这一次, X{n+1} 的第二位同时取决于 abXn 的第一位和第二位。根据 ab. 的前两位,下表给出了 X{n+1} 的前两位值的顺序**

这里,前两位的序列也是重复的。但是只有以*结尾的 a 给出了循环前 X{n+1} 所有可能的四个**值。因此,这是一个关于的新条件,以获得前两位的所有可能值。***

  1. ab应该是奇数
  2. 一个 应该以 01 结尾。
    换句话说
    a mod 4 = 1
    换句话说 a-1 应该是 4 的倍数

我们在这里检索我们早先看到的关于最佳线性同余生成元的定理的条件之一(条件 n 3)。因为 M=24a-1 应该是 4 的倍数。

目前为止我们得到的信息是:

  • 1 第一位:长度为 2 的时间段
  • 2 第二位:长度为 4 的周期

如果你迭代下面的比特,你会得到类似的结果:

  • 3 第 3 位:最大长度为 8 的周期
  • 4 第 6 位:最长 16 的周期
  • ….
  • 31 第一位:周期长度最大为 2

此外,我们在上面对 ab 的前两位设定的两个条件都是足够的来获得所有剩余位的最大周期。这就是为什么最终定理中出现条件“ a-1 应为 4 的倍数,如果 M 是 4 的倍数”。

总之,因为它们的周期更长,高位比低位具有更好的随机性。

解决低位问题

从前面的章节中,我们明白了为什么It16 位有一段长度 2^i 。这是因为第 i 第位的 X{n+1} 只取决于第I 位的 Xn2^i 是我们可以用 i 位得到的最大组合数。

所以,我们需要一种方法,让第一位也依赖于其他位。加法和乘法只向左传播比特。是否有任何向右侧传播位的操作?一

例如:如果我们想使 1 的第一位、T53【X { n+1 }、依赖于的第三位、T59【Xn】、。我们把 Xn 除以 4,这相当于把 Xn 向右移动了两步。****

让我们用以下内容更新我们的线性同余发生器:

现在让我们看看这是否提高了第一位的随机性。

aX + b +的第 1 位位图(X >> 2)

对于 aX + b + (X >> 2),使用第 1 和第 2 位进行随机游走

这大大提高了第一位的随机性!位图中有一些图案(*黑点),但比黑白交替好得多。

让我们看看我们是否仍然擅长第 31 位的

aX + b + (X >> 2)的第 31 位位图

对 aX + b + (X >> 2)使用第 31 位和第 30 位的随机游走

嗯,不太好,现在我们得到了位图中的图案(*黑点),你可以看到一个形状在随机游走中无限重复。

我们可以尝试另一个金额来转换。为此,我编写了一个程序,返回不同班次金额的周期。结果如下:

没有任何金额给出 2 的最大期限。因此,这种形式的函数不能在不影响随机数发生器周期的情况下解决我们的问题。

研究线性同余发生器的变体并不容易,这些变体既能解决低位问题,又能实现最大周期长度。ab的调优对于 aX+b 来说已经被证明了,任何变体都要足够好的学*,以免陷入短周期。我尝试了不同版本的函数,如下所示。每次我的周期变短:

  • X { n+1 } =(aXn+b+X>>2)mod M
  • X { N+1 } =(aXn+b+sum I 从 1 到 N(X>>I))mod M
  • X { N+1 } =(aXn+b+xor I 从 1 到 N(X>>I))mod M
  • X { N+1 } =(aXn+b+N-1 个最高有效位之和** ) mod M**

如果你试一试,也许你会发现一个变种,可以解决周期和低位的问题!

结论

令我非常惊讶的是,我发现最著名的随机数发生器之一根本不是随机的。在本文中,我们已经看到了线性同余生成器如何无法为它生成的数字的低位获得看似随机的序列。我们还使用了两种可视化方法来帮助用肉眼评估随机数生成器。

今天,有更先进的随机发生器,不存在低位的问题,如梅森扭转器,它不像线性同余发生器那么简单,但绝对值得花时间来理解它是如何工作的。

双向联想记忆简明指南

原文:https://towardsdatascience.com/a-succinct-guide-to-bidirectional-associative-memory-bam-d2f1ac9b868

Arthur V. Ratz 的照片

读者需要了解的关于双向联想记忆(BAM)的一切,包括 Python 3.8 和 NumPy 中的示例

简介

B 双向联想记忆(BAM)是一种特殊类型的递归神经网络(RNN),最初由 Bart Kosko 在 20 世纪 80 年代初提出,试图克服自联想 Hopfield 网络和 ann 的几个已知缺点,后者从连续训练中学*数据的关联。

BAM 是异联想存储器,提供存储相关数据的能力,而不管其类型和结构,无需连续学*。在从 BAM 的存储器中调用数据关联之前,数据关联被同时存储,仅存储一次。通常,BAM 比现有的 ann 跑得快,在回忆关联时提供明显更好的性能。此外,与现有的人工神经网络相比,使用 BAM 完美地解决了已知的按位异或问题,这使得在其存储器中存储编码为二进制(双极性)形式的数据成为可能。

与单向 Hopfield 网络不同,BAM 能够双向调用分配给其输入或输出的数据关联。此外,它允许检索正确的关联,即使是不完整或失真的输入数据。

当作为基于人工智能的决策过程的一部分部署时,BAM 模型是相当有效的,它基于许多相关数据的各种关联来推断特定数据分析问题的解决方案。

一般来说,BAM 模型可用于多种应用,例如:

  • 分类和聚类数据
  • 不完整数据扩充
  • 恢复受损或损坏的数据

每当人工神经网络获取的各种知识不足以处理引入人工智能进行分析的数据时,BAM 模型就非常有用。

例如,用人工神经网络预测不完整文本中遗漏的单词,基本上需要将单词与句子的关联存储在人工神经网络的存储器中。然而,这将导致不正确的预测,因为相同的缺失单词可能出现在不止一个不完整的句子中。在这种情况下,使用 BAM 提供了存储和调用数据实体的所有可能关联的能力,例如单词到句子句子到单词单词到单词句子到句子,反之亦然。这反过来显著提高了预测的质量。为了扩充或聚集这些数据,还推荐多方向地关联各种数据实体。

最后,每个 ANN 的层的内存容量都绑定在最大浮点类型的大小: float64 。例如,shape (100x100)的单个 ANN 层的容量只有 1024 字节。显然,人工神经网络的层数以及每层中神经元的数量都必须增加,以具有存储联想和多方向回忆的能力。这反过来又会对基于人工神经网络的内存延迟产生负面影响,因为它的学*和预测工作量与人工神经网络的规模成比例地增长。

尽管如此,BAM 的学*和预测的高性能提供了根据需要分配大量存储空间的能力,超过了传统 ANN 的存储容量限制。同样,可以将多个 bam 聚合到内存中,具有分层结构。

存储在内存中的关联…

BAM 学*各种数据的关联,转换成双极模式。双极模式是二进制向量的特例,其元素分别是 1 的-1 的的值。多个模式(列)沿着矩阵的 y 轴排列成 2D 模式映射。x 模式映射是嵌入,其每一列对应于存储在 BAM 的存储器中的特定输入和输出数据项:

作者将数据编码成双极 2D 图形形状图(s×n)|图像

BAM 模型同时从模式映射中学*相关数据,分别分配给其相应的输入和输出:

作者分配给 BAM 模型|图像的输入(X)和输出(Y)模式映射

在上图中,BAM 模型学*数据的关联,分别编码到形状(𝙨 x 𝙣)和(𝙨 x 𝙢)的模式映射𝙓和𝒀中。在学*时,来自输入和输出模式的值被分配给 BAM 模型的相应输入𝙭ᵢ𝙓和输出𝙮ⱼ𝒀。反过来,输入和输出模式映射(列)必须具有相同数量的模式(𝙨)。由于 BAM 是一个异联想记忆模型,它有不同数量的输入(𝙣)和输出(𝙢),因此,相应地,在𝙓和𝒀这些模式映射中也有不同数量的行。

BAM 的拓扑和结构

通常,BAM 是一个原始的神经网络(NN ),仅由输入和输出层组成,通过突触权重相互连接:

BAM 模型的神经网络拓扑(4 x 3) |图片由作者提供

在上图中,输入层的神经元(𝒏)不执行输出计算,而是将输入𝑿前馈到 BAM 输出层的存储单元(𝒎)。它的大小基本上取决于 BAM 的输入和输出的数量(例如,输入和输出模式映射的维度)。上面显示的形状为(4 x 3)的 NN,在其输入和输出层分别由 4 个神经元和 3 个存储单元组成。

与传统的人工神经网络不同,BAM 的输出层由执行 BAM 输出计算的存储单元组成。每个存储单元基于由突触权重𝑾转发给该单元的多个输入𝑿来计算其输出𝒀,每个输出都具有特定的强度。

存储单元的输出对应于模式的特定值,被调用:

BAM 内存单元的输出(Y )|作者提供的图像

BAM 的输出计算为所有 BAM 输入𝑾ᵀ𝙓的加权和,作为双极性阈值函数的参数应用。每个输出𝒀的 (+)或 (-)值(例如 1-1) 总是与该单元的加权输入之和的大小成比例。

连接输入神经元和记忆细胞的所有突触权重存储由 BAM 基于下面讨论的 Hebbian 监督学*算法学*的基本记忆。

学*算法

从代数角度来看,BAMs 存储和回忆关联的能力完全依赖于矩阵的双向属性,T. Kohonen 和 J. Anderson 在 20 世纪 50 年代中期对此进行了研究:

两个矩阵𝑿和𝒀的内点积,给出一个相关矩阵𝑾据说是双向稳定的,是𝑿和𝒀回忆和反馈到𝑾的结果。

通常,这意味着矩阵𝑿和𝒀的相应行和列,以及它们的标量矢量积,同样对𝑾 的值有贡献,作为回忆:

因为,矩阵𝑿和𝒀的每一个向量都可以通过下面讨论的内点积𝑾𝑿ₖ或𝑾 𝒀ₖ很容易地回忆起来。

在这种情况下,𝑾是一个矩阵,它推断𝑿ₖ或𝒀ₖ向量的相关性。整个学*过程非常类似于 保持 (𝙬ᵢⱼ ≠ 0 )或 丢弃(𝙬ᵢⱼ= 0)特定权重,将 BAM 的输入神经元和记忆细胞相互连接。

突触权重𝙬ᵢⱼ 𝑾的值可以大于、小于或等于 0 。BAM 只保存那些突触权重,其值要么是正的,要么是负的。在初始化模型时,等于 0 的突触权重被简单地丢弃。

Donald Hebb 提出了双向矩阵性质,作为著名的监督学*规则,它是 Hopfield 网络和其他联想记忆模型的基础。

根据 Hebbian 算法,在初始化突触权重的矩阵𝑾ₙₓₘ时,所有相关模式被存储在 BAM 的存储空间中,仅一次(例如,存储空间)。通过分别取输入𝑿ₚₓₙ和输出𝒀ₚₓₘ模式图(即,矩阵)的内点积来获得矩阵𝑾ₙₓₘ:

或者,权重矩阵𝑾ₙₓₘ可以从𝑿ₚₓₙ、𝒀ₚₓₘ矩阵获得,作为相应模式𝙭ₖ和𝙮ₖ的外部克罗内克乘积的和。

与𝑿和𝒀的内点积不同,(𝙭ₖ,𝙮ₖ)𝑿,𝒀向量的外积产生矩阵𝙬ₖ𝑾(即基本记忆)。最后,通过逐点获得它们的和,所有的矩阵𝙬ₖ被组合成单个矩阵𝑾。

BAM 的突触权重初始化的整个过程如下图所示:

基于 Hebbian 算法学* BAM 模型|图片作者

然而,相关矩阵𝑾为作为正交向量的模式提供了最稳定和一致的记忆存储。𝑿,𝒀正交向量的乘积给出了对称相关矩阵𝑾,其中关联的基本记忆分别从模式图𝑿和𝒀学*。

因此,强烈建议在训练模型之前执行𝑿和𝒀模式图的正交化。由于𝑿和𝒀是两极的,𝒀的正交化可以很容易地做为:𝒀 = -𝑿.通过取负-𝑿,𝒀模式将具有与𝑿相同的值,其符号 (+/-) 变为相反。

BAM 的学*算法很简单,可以用 Python 3.8 和 NumPy 中的一行代码轻松实现:

从记忆中回忆模式

因为输入和输出模式映射已经存储在 BAM 的存储器中,所以通过在多次迭代中计算 BAM 的完整输出来调用特定模式的关联,直到检索到输入模式𝑿的正确关联。

为了计算完整的内存输出,在每次迭代中,𝞭-iterations,𝒌=𝟏..𝞭,𝙓模式的 BAM 的输入𝙭ᵢ乘以相应的突触权重𝙬ᵢⱼ 𝙒.在代数上,这是通过取权重矩阵𝙒-transpose 和输入模式𝙓.的内积来完成的然后,将 BAM 输入的加权和𝙒 ᵀ𝙓应用于双极阈值函数𝒀=𝙁(【𝙒ᵀ𝙓),以计算每个存储单元的输出,该输出对应于被调用的输出模式𝙮ⱼ 𝒀的特定值 1-1 。这种计算类似于通过传统人工神经网络的每一层前馈输入。

双极阈值函数𝙁与经典阈值函数完全相同,唯一的区别是其正(+)或 0 输入的值为 1、和负(-),除非另有说明。在这种情况下,𝙁的实际输入也包括零 :

双极性阈值函数 Y=F(X)

双极阈值函数的曲线图如下所示:

双极阈值激活功能|图片作者

下面列出了一个简单的代码片段,演示了 BAM 的内存单元激活:

与传统的人工神经网络不同,输出层中的存储单元还为下一次迭代𝙠+𝟏.计算新的输入𝙓ₖ₊₁然后,它检查当前𝙓和新输入𝙓ₖ₊₁是否不相等(𝙓≠𝙓ₖ₊₁).如果没有,它将新的输入分配给 BAM,在下一次迭代中继续计算输出𝒀。否则,如果是𝙓=𝙓ₖ₊₁,则意味着输出𝒀是输入𝙓的正确关联,并且算法已经收敛,从过程返回模式𝒀。此外,BAM 通过基于所讨论的相同算法双向计算存储器输出,提供了调用输入𝙓和输出𝒀的关联的能力。

图形调用过程如下图所示:

内存单元输出(Y)计算|作者图片

从 BAM 存储器中调出关联的算法如下:

设𝑾ₙₓₘ—为相关权重矩阵(即 BAM 存储器的存储空间),𝑿ₙ—为长度为𝒏的输入模式,𝒀ₘ—为长度为𝒎:的输出模式

回想一下先前存储在 BAM 内存中的输入模式𝑿的关联𝒀:

对于每个𝞭-iterations、𝟏𝞭*≤*𝒕,执行以下操作:

  1. 用输入向量𝑿₁←𝑿.初始化 BAM 的输入
  2. 计算 BAM 输出向量𝒀ₖ,作为权重矩阵𝑾 转置和输入向量𝑿ₖ的内点积,用于𝒌-th 迭代:

3.获得下一次𝒌+𝟏)-th 迭代的新输入向量𝑿ₖ₊₁,例如:

4.检查新的和现有的矢量𝑿ₖ₊₁≠𝑿ₖ是否相同:

如果不是,返回步骤 1,计算𝒌+𝟏)-th 迭代的输出𝒀ₖ₊₁,否则进行下一个步骤 5。

5.从过程中返回输出向量𝒀←𝒀ₖ,作为输入𝑿向量的正确关联。

6.继续步骤 2–4,直到收敛。

下面列出了 Python 3.8 和 NumPy 中实现模式预测算法的一段代码:

内存评估(测试)

下面列出的代码演示了 BAM 评估(测试)过程。它建立特定形状(模式×神经元×记忆 _ 细胞)的 BAM 模型,并生成 1D 数组,由 1-1 值组成。然后,它将数组重新整形为输入的二维图案图𝑿.为了获得𝒀的模式图,它执行𝑿的正交化,例如:𝒀=−𝑿.接下来,计算相关矩阵,将𝑿和𝒀模式的关联存储到 BAM 的内存中。

最后,它对每个输入模式𝙭ᵢ 𝙓执行模型评估,它从 BAM 的存储器中双向调用一个关联。当从存储器中调出输入模式 x⃗的关联 y⃗ₚ时,它会检查输出 y⃗ₚ目标 y⃗模式是否相同,显示每个输入模式𝙭ᵢ 𝙓:的结果

预测不完整的模式

BAM 模型的优点之一是能够通过 > 30 不完整或损坏的输入来预测正确的关联。下面的代码片段演示了不完整的模式预测。它从模式图𝑿中随机选择一个输入模式,并扭曲它,用任意的 1-1 替换它的多个值。它应用 poison(…)函数(在下面的代码中实现)来扭曲随机选择的模式 x⃗,正在回忆它的关联。最后,它预测一个关联模式,如果目标和预测的关联 y⃗和 y⃗ₚ是相同的,则执行一致性检查。如果是这样的话,x⃗被召回的正确联想模式是:

结论

尽管 BAM 模型无需持续学*就能灵活地存储和调用关联,但对于某些应用程序来说,它的效率可能会降低,因为它无法调用某些类型数据的正确关联。根据最新的研究,预测各种不完整或损坏的数据的关联基本上需要由大量存储单元组成的巨大尺寸的 bam。当回忆少量模式的正确关联时,也存在几个问题。显然,BAM 模型的现有变体必须经过改进才能用作大量应用的持久存储器。尽管如此,以下问题的解决方法仍在开发中。

源代码:

放弃

所有的图片都是由这个故事的作者使用 Draw.io 应用程序设计的,https://www.diagrams.net/

参考

  1. “双向联想记忆”——来自维基百科,免费百科。
  2. 自适应双向联想记忆,Bart Kosko,IEEE 系统汇刊,人与控制论,第 18 卷第 1 期,1988 年 1 月/2 月。
  3. 模式协会或联想网络,Jugal Kalita 科罗拉多大学科罗拉多泉分校。

过去一年我参加 Kaggle 比赛的经验总结

原文:https://towardsdatascience.com/a-summary-of-my-experience-with-kaggle-competitions-over-the-last-year-bac740974484

在高尔夫球比赛中取得好成绩的系统方法

格雷格·罗森克在 Unsplash 上的照片

作为一名数据科学爱好者,我尝试了许多不同的事情来提升我的知识和经验。读一年的每周机器学*论文,做 Coursera 的课程,看动手机器学*的书,参加 Kaggle 的比赛。在我看来,获得数据科学经验的最佳方式(除了在行业中工作)是参加 Kaggle 竞赛。当我开始写它们的时候,我确实面临着巨大的挫折,这也是我写这篇文章的原因。在做了 2-3 个以上的 Kaggle 比赛后,我开始注意到许多有用的模式,我希望我早就注意到了。如果你是第一次参加比赛,我强烈建议你注意这些事情,因为这会节省你很多时间。

1.探索数据,慢慢来(练*探索性数据分析(EDA))

我曾经非常兴奋地开始将数据输入机器学*模型,并尽快开始工作。然而,经过几次尝试后,我发现最初花时间研究这些数据是非常值得的。有大量的 EDA 教程,参加比赛的人通常会在最初发布大量的 EDA 笔记本。了解这些数据将为您节省大量时间,并帮助您做出明智的决策,决定尝试哪个模型,避免哪个模型。一般来说,我会说,如果比赛持续 3 个月左右,不要担心,如果你花前 2-3 周做 EDA。在第一阶段探索要比剥削好得多!

EDA 包括许多不同的工具,但我通常注意到这些工具是最有用的:

  1. 检查特征的分布。尝试查看要素是正态分布还是偏态分布。这可能会影响您预处理数据的方式。
  2. 检查要素的数据类型
  3. 检查要素的*均值、中值和标准差
  4. 检查要素的数量、数据集的大小
  5. 检查是否有任何可空/空字段
  6. 检查特征的相关性,高度相关的特征有时会被丢弃

你可以做更多的事情,但是如果你是一个初学者,也许就从这些开始吧。

2.开始阅读关于竞赛领域的论文

这可能不明显,有些人会不同意,但我强烈建议你阅读一些与竞争对手相同领域的初始机器学*论文。例如,如果你正在做一个关于在图像中检测皮肤癌的比赛,试着找到最近做最相似任务的论文(例如,可能是生物信息学中的计算机视觉)。

对你将要阅读的论文要务实和谨慎。很容易陷入无休止的循环阅读,甚至忘记比赛。浏览大约 10-20 篇论文,选择最好的 5 篇。我还强烈建议您与竞赛社区分享这些论文。获得人们的反馈,看看他们的想法,还可以获得几个 Kaggle 点!

3。开始试验模型

安德斯·吉尔登Unsplash 拍摄

这里一个很常*的错误是没有跟踪你的实验,迷失在混乱的笔记本中。你必须对你的实验系统化,记下你将要使用的模型和你将要测试的超参数范围。这是非常重要的建立一个坚实的基线,你可以在此基础上建立。

另外:

不要从神经网络开始

我总是看到这种错误,我为自己犯了几次这样的错误而感到内疚。从神经网络开始是非常诱人的(例如,从 NLP 竞赛中的变压器开始)。不要从最复杂的模型开始,你最终会非常沮丧。从最基本的模型开始,逐步构建更复杂的模型。使用梯度推进机器而不是深度神经网络赢得了很多比赛。此外,你必须学会如何使用梯度推进机,因为在这些 Kaggle 比赛中,它们绝对是性能方面的野兽。它们也很容易使用,其中几个作为轻量级 GBM 给你带来了非常有意义的结果,比如特性的重要性。

4.与社区合作

记住你是在一个公共的 Kaggle 社区上做一个竞赛。你总是会有问题,把它们贴在论坛上。如果可以的话,试着在团队中工作。向别人学*比自己学*要快得多。我保证,如果你在团队中工作,你正在犯的许多错误是可以避免的。

此外,与公共笔记本保持同步,尽可能多地从它们身上学*。

但是,不要简单地复制粘贴它们!

复制和粘贴它们只会让你一事无成,因为你实际上什么也学不到,而且大多数时候你会发现改进别人的代码非常困难。相反,试着理解他们的代码,也许复制一两个可以帮助你的程序块。

5.全体,全体,全体

老实说,集合是在 Kaggle 比赛中取得好成绩的秘密关键。我以前总是忘记做这件事。运行实验后,不要简单地提交最佳模型的预测。提交你最好的 3 个甚至 5 个模特的合奏。并且总是使用 3 或 5 K 倍来训练你的模型。

结论

老实说,我不觉得参加卡格尔比赛是一条容易的路。我通常觉得它们很有挑战性,现在依然如此。我从来没有赢过,但我总是发现自己在做了一次后学到了很多新概念。我也一直注意到,典型的卡格尔大师只有在参加了大量(100+)的卡格尔比赛后才能到达那里,这绝对是疯狂的。不确定我是否会走到那一步,因为在某个时候,你开始获得特定于 Kaggle 的经验,而不是可转移的数据科学经验。但是,我认为除非你参加 50 场以上的比赛,否则你不会达到那个水*。

如果您想定期收到关于人工智能和机器学*的最新论文的论文评论、高质量的 ML 教程等,请添加您的电子邮件此处 &订阅!

一种超快速的 Python 循环方式

原文:https://towardsdatascience.com/a-super-fast-way-to-loop-in-python-6e58ba377a00

你觉得 Python 慢吗?这里有一个在 Python 中快速循环的方法

图片来自 Shutterstock,授权给 Frank Andrade

众所周知,Python 是一种缓慢的编程语言。虽然 Python 比其他语言慢是事实,但是有一些方法可以加速我们的 Python 代码。

怎么会?简单,优化你的代码。

如果我们编写消耗很少内存和存储的代码,我们不仅可以完成工作,还可以让我们的 Python 代码运行得更快。

这里有一个快速也是超快速的 Python 循环方法,这是我在上的一门 Python 课程中学到的(我们从未停止学*!).

*均循环

假设我们想对从 1 到 100000000 的数字求和(我们可能永远不会这样做,但这个大数字将有助于我阐明我的观点)。

典型的方法是创建一个变量total_sum=0,在一个范围内循环,并在每次迭代中用i增加total_sum的值。

这就完成了工作,但是需要大约 6.58 秒。

虽然现在看起来没那么慢,但是当你在范围内的数字上加更多的 0 时,它会变得更慢。

让我们加速吧!

使用内置函数进行循环的更快方法

在 Python 中循环的更快方法是使用内置函数。

在我们的例子中,我们可以用sum函数替换 for 循环。此函数将对数字范围内的值求和。

上面的代码耗时 0.84 秒。这比我们之前使用的循环快多了!这就是为什么我们应该选择内置函数而不是循环。

但仍有改进的空间。

使用 Numpy 的超快速循环方式

几周前,在我参加的数据科学课程中,我了解到要成为一名更好的数据科学家,我应该遵循的软件工程实践之一就是优化我的代码。

我们可以通过向量化操作来优化循环。这比它们的纯 Python 对等物快一/两个数量级(特别是在数值计算中)。

矢量化是我们可以通过 NumPy 得到的东西。Numpy 是一个具有高效数据结构的库,用于保存矩阵数据。它主要是用 C 写的,所以速度是你可以信赖的。

让我们尝试使用 Numpy 方法.sum.arange来代替 Python 函数。

这可以在 0.22 秒内完成工作。这比以前的方法要快得多。

这就是为什么应该尽可能在循环中使用向量运算的原因。

用更多的计算来测试循环和数字

到目前为止,我们已经看到了 Numpy 的一个简单应用,但是如果我们不仅有一个 for 循环,还有一个 if 条件和更多的计算要做呢?

Numpy 的表现明显优于 loops。

假设我们有一组随机的考试分数(从 1 到 100),我们想要获得那些没有通过考试的人的*均分数(score <70).

Here’s how we’d do this with a for loop.

That takes approximately 15.7 seconds. Not bad, but we can get faster results with Numpy.

Here’s how we’d do this with Numpy.

The code above takes about 0.78 seconds. That’s way faster and the code is straightforward!

Learning Data Science with Python? )通过加入我的 10k+人的电子邮件列表来获得我的免费 Python for Data Science 备忘单。

如果你喜欢阅读这样的故事,并想支持我成为一名作家,可以考虑报名成为一名媒体成员。每月 5 美元,让您可以无限制地访问数以千计的 Python 指南和数据科学文章。如果你用我的链接注册,我会赚一小笔佣金,不需要你额外付费。

https://frank-andrade.medium.com/membership

三大 MLOps 工具概览

原文:https://towardsdatascience.com/a-survey-of-the-top-three-mlops-tools-1694688648c5

机器学*模型部署和管理的最新工具

像素上的像素生成的图像

部署和维护机器学*模型对于任何使用预测分析为客户提供价值的公司来说都是必不可少的。MLOps 是机器学*操作的缩写,指的是用于可靠地部署和维护机器学*模型的一组任务。随着数据科学和机器学*团队在各行各业的兴起,公司越来越多地使用预测分析来为客户提供价值。这就产生了对系统的需求,以确保机器学*管道对变化是健壮的,并且它们的结果是可重复的。

MLOps 位于软件开发运营(DevOps)、机器学*和数据工程的交叉点。MLOps 将一组特定的实践应用于机器学*生命周期中的所有步骤,包括数据收集和处理、标记和特征工程、模型训练和优化以及端点部署和监控。在高层次上,MLOps 寻求以有效和可靠的方式自动化这些相互关联的步骤,同时保持模型预测的质量并满足业务需求。

对于任何希望扩展其机器学*系统的公司来说,实施一些基本的 MLOps 实践是必不可少的。例如,关于数据收集和处理,在进入生命周期中的数据标记和特征工程步骤之前进行数据检查是很重要的。数据刷新可能会导致质量差的数据,这可能会成为数据标注和特征工程的瓶颈。这肯定会导致模型性能恶化,并降低 ML 系统对客户和最终用户的效用。

另一个例子是监控模型训练和模型预测的运行时间。如果数据刷新导致模型训练时间显著增加,应该有一个过程来使用更强大的机器或机器集群,以便部署不会显著延迟。此外,关于端点部署和建模,模型预测调用的延迟会对用户体验产生重大影响。例如,如果对工具返回预测的速度有所预期,则每当定型数据、模型特征或模型类型发生更改时,都应监控预测调用运行时。对数据摄取、模型验证和业务需求进行适当的检查可以防止质量差的模型和来自这些模型的无意义的*解被发送给客户。有各种各样的工具可用于监控数据、模型和业务规则。在这里,我们将调查三个最流行的 MLOps 工具。

库贝弗洛

Kubeflow 是谷歌开发的机器学*工具包,允许数据科学家和机器学*工程师监控机器学*生命周期。Kubeflow 基于 Kubernetes 构建,用于部署、扩展和管理复杂系统,如机器学*管道。Kubernetes 是一个开源的容器编排系统,主要用于软件工程领域。具体来说,它用于自动化软件部署、扩展和管理。

Kubeflow 本质上是机器学*管道 Kubernetes 的扩展。下图从概念上概述了 Kubeflow *台,以及它如何适应机器学*工作流程的不同组件。大致可以分为 ML 工具、模型服务工具和云计算*台。

作者图片

Kubeflow 通常对与数据科学家密切合作的 DevOp 工程师更有用。这可能是规模服务模型的最佳选择。

MLflow

另一个类似的工具包是由 Databricks 开发的 MLflow 。MLflow 有四个主要组件:跟踪、项目、模型和注册表:

作者图片

如图所示,每个 MLflow 组件分别用于模型实验、可再现运行、模型部署和模型存储。

跟踪

追踪对模型实验最有用。它包含一个 API,用于记录模型超参数、模型性能指标和工件,例如 pickeled 训练模型。

项目

项目组件对于以可重现的方式打包数据科学和机器学*代码非常有用。它还有一个 API 和命令行工具,允许多个项目链接在一起。

车型

模型组件用于服务模型。例如,它可以与 REST API 一起用于实时模型预测服务。

注册表

最后,registry 组件有几个工具用于管理 MLflow 模型的整个生命周期。这些包括集中式模型存储、API、ui,它们可用于跟踪模型沿袭、版本控制、模型分级和注释。

MLflow 对数据科学家和机器学*工程师更有用,因为它允许他们轻松地设计、运行和重现实验。

AWS SageMaker

AWS SageMaker 是另一个流行的 MLOps 工具。对于数据科学家和业务分析师来说,这是一个非常用户友好的选择,因为它为每个角色提供了 ide 和无代码 ui。它还拥有访问、标记和处理结构化和非结构化数据的工具。此外,与 Kubeflow 和 MLflow 类似,它可以直接部署和监控机器学*模型。

作者图片

总的来说,AWS SageMaker 可能是机器学*生命周期中数据工程和数据争论步骤的最佳选择。这是因为它有一个内置的 IDE,配备了完成这些任务的工具。

比较 Kubeflow、MLflow 和 AWS SageMaker

我们在这里讨论的三个*台之间有许多相似之处和不同之处。在高层次上,每个都可以用于部署、服务和维护机器学*模型。Kubeflow 和其他两个*台的一个很大的区别就是它依赖于 Kubernetes。此外,MLflow 是一个 python 库,使数据科学家可以非常容易地运行和保存实验以进行建模。MLflow 还可以与 AWS SageMaker 一起用于模型部署。Kubeflow 与 SageMaker 的不同之处还在于,它是免费和开源的,而 SageMaker 需要为 AWS 服务付费(即使是在免费层)。此外,与 Kubeflow 和 MLflow 相比,AWS SageMaker 是数据工程和数据争论任务的更好选择。鉴于每个*台都有利弊,DevOps 工程师、数据科学家和机器学*工程师最好对每个*台都有所了解。

结论

机器学*操作已经成为开发、监控和维护机器学*生命周期的重要部分。当谈到管理数据科学和机器学*管道时,对最佳实践和可用的最先进工具有一个总体的理解和认识是很重要的。Kubeflow 最适合用于大规模服务机器学*模型。MLflow 最适合模型实验和记录。AWS SageMaker 拥有许多与 Kubeflow 和 MLflow 相同的工具,同时还为数据工程任务提供了更多的工具。

用稳定扩散生成的合成图像数据集

原文:https://towardsdatascience.com/a-synthetic-image-dataset-generated-with-stable-diffusion-93e8b557051b

用 Wordnet 测试稳定扩散能力

由作者创建的稳定扩散的图像

用于从文本输入生成合成图像的当前模型不仅能够生成非常逼真的照片,而且能够处理大量不同的对象。在论文“评估使用稳定扩散生成的合成图像数据集”中,我们使用“稳定扩散”模型来研究哪些对象和类型被如此真实地表示,以至于后续的图像分类正确地分配它们。这给了我们在现实表现方面对模型的评估。

上面的照片用一个足球的例子来说明,不仅生成了非常逼真的照片,而且从精确的文本提示开始,创建了对象的非常不同的表示。

数据的生成

作为图像生成的基础,我们使用“稳定扩散”1.4 模型Huggingface 扩散器库的实现。该模型允许基于文本提示创建和修改图像。它是在 LION5B 文本到图像数据集的子集(LAION-美学)上训练的潜在扩散模型。

下图显示了从文本提示生成的图像示例

《站在水中的短腿哈夫林杰马》。

该示例表明,生成器模型可以表示具有不同属性的不同概念,还可以将它们组合在一个设置中。

由作者创建的稳定扩散的图像

我们创建了一个包含各种不同概念的图像的数据集。对于文本输入,我们使用“ Wordnet ”中包含的信息。Wordnet 将概念组织到所谓的“synsetss”中,synset 对应一个或多个具有相同含义的单词的含义。因此,一个意义不同的词可以属于几个同义词集。例如,“apple”这个词有水果和电脑品牌的意思,这两个词各有一个同义词集。

从 Wordnet synset‘object . n . 01’开始,通过递归调用“下位词”(比适用于它的一般或上位术语具有更具体含义的词),创建了 26,204 个名词 synset 的列表。对于这些名词中的每一个,我们使用 Wordnet 中的同义词集描述来生成图像。

这种提示的一个例子是:(狗的 synset)

“犬科动物属的一员(可能是普通狼的后代),从史前时代起就被人类驯养;出现在许多品种中”

对于每个 synset,生成了 10 个图像,并存储在 synset 的名称下,并附加了编号。这导致我们的数据集总共有 262,040 幅图像。

与每个 synset 的 10 个图像一起,保存一个文本文件,该文件包含所使用的提示、synset 的名称(例如“dog.n.01”)和 wordnet 编号(例如“n12345678”)。唱片可以从 Kaggle 下载。

https://www.kaggle.com/datasets/astoeckl/stable-diffusion-wordnet-dataset 引用:【https://arxiv.org/abs/2211.01777】T2

数据评估

为了对我们的数据集子集进行系统评估,我们使用了 ImageNet 大规模视觉识别挑战 (ILSVRC)数据集。
我们使用 vision transformer 模型的 Pytorch 实现,它在 ImageNet 数据上的前 1 名准确率为 88.55%,前 5 名准确率为 98.69%,以验证生成的图像可以正确分类。

对来自所考虑的子集的所有 8610 幅图像的审查产生每类 4.16 幅图像的*均正确分类(最多 10 幅),所有类的*均标准偏差为 3.74。下面的直方图显示了正确分类数量的巨大差异。NSFW 滤波器产生的黑色图像是统计数据的一部分。

作者图片

可以看出,虽然为大多数类别(73%)生成了至少一个正确识别的图像,但是所有 10 个图像仅在 14%的类别中被识别。这也反映了文章开始时的观察,即一个类生成的图像差别很大。这使得分类过程的任务变得复杂。

现在让我们考虑一些物体组的识别率。在 Wordnet 的层次结构下,总结了一些术语组的相关类别,并确定了每个类别的*均识别率。下表显示了结果。

不同物体类别的识别率

引人注目的是对建筑物的良好识别率。下图显示了“温室”的图像,所有 10 个图像都被正确识别。

“温室”——作者创造的稳定扩散的意象

“动物”类显示出低于*均水*的分类率。如果我们更仔细地观察这个组,我们会发现在 162 个动物类别中,没有一个图像是完全不被识别的。看看个体特定的例子,如下面的例子中的术语“黑脚雪貂”和“叶蝉”,“稳定扩散”显然揭示了动物科学中的重大缺陷。

“黑脚雪貂”——作者创造的稳定扩散的形象

“叶蝉”——作者塑造的稳定扩散的形象

创建术语“地图”,显示由
稳定扩散生成的哪些图像被视觉转换器模型正确识别,以及每种情况下的识别率有多高,我们根据语义在 2D 中放置术语,并根据子组对其进行着色。圆圈的大小表示正确分类的图像的数量。为了确定在这个地图上的位置,我们使用单词嵌入作为类名。

分类率“地图”——作者图片

这里,许多没有被正确识别的动物种类的小红点也很明显。

类似项目

一个提供对用稳定扩散生成的合成图像数据的访问的项目是“Lexica”。它是一个搜索引擎,从超过 1000 万张图片中返回一个术语的结果。但是,这里的整个数据库无法下载,也没有分类。

lexica——作者截图

中提供并描述了一个包含 200 万幅图像的大型数据库,该数据库也可以下载并作为开放源代码使用

https://poloclub.github.io/diffusiondb/

除了图像,“扩散数据库”数据集还包含用于生成每个图像的文本提示。作者通过抓取 Stable Diffusion 的 Discord 服务器并提取包括提示在内的图像来创建数据集合。

两个建筑的故事

原文:https://towardsdatascience.com/a-tale-of-two-architectures-48758462f5fd

将机器学*模型部署为微服务

开始是最容易的,从开始是最难的,可以这样解释狄更斯的杰作(其中之一)【双城记】的第一行。

我最近转到了另一个团队,那里正在开发一个非常有趣且具有挑战性的文档(pdf 和图像)分析解决方案。主要思想是提供内部自动化工具,以自动化和/或促进不同业务单元的流程接收文档。

例如,其中一个业务部门收到了大量的申请表。表格可能是手工填写的,由于扫描而歪斜,由于扫描而质量不好,等等。多年前创建的接收这些表单的原始流程是让某人手动提取感兴趣的字段,并将其输入到应用程序中。这个过程不仅容易出错,因为偶尔会出现图像质量不佳的情况,而且特别是因为处于循环中的人,他们唯一的(极其无聊的)功能是在最好的情况下复制粘贴数据,在最坏的情况下理解和键入像手写首字母缩写词这样的东西。

当我加入团队时,我的任务是帮助重新设计系统,通过不同的模型,在文档类型数量、请求数量,特别是整个系统提供的功能数量方面变得可扩展。这是通过将包含所有模型的整体应用程序分解为独立的微服务来实现的,这就是我将要谈到的旅程。

像往常一样各个击破

该团队从一开始就意识到单一模型是不够的,并试图理解概念验证需要什么。结论是,需要采取以下措施:

光学字符识别(OCR)模型

抗扭斜模型

一个分类模型

需要 OCR 模型来提取文档的内容。需要抗扭斜模型来确保文档正确对齐。需要分类模型来确保文档是模型所期望的类型。如果不是,那么 OCR 模型将被绕过。

一旦决定下来,每个数据科学家/ML 工程师(我从现在开始将他们都简称为工程师)都被分配了一个要解决的问题。因为这篇文章的重点是展示这些模型是如何首先集成到一个 monolith 应用程序中,然后再拆分成一个基于微服务的应用程序,所以我将把每个模型的细节放在另一个时间。

工程师们启动他们的 Jupyter 环境,收集数据并开始工作。不久之后,他们每个人都有了可以集成到更大的解决方案中的概念证明。正如古老的奥卡姆剃刀教导我们的那样,实体的增加不应该超出需要,所有的模型都被集成到一个单一的、基于 Python 的整体应用程序中。

该应用程序还公开了一个接收文档内容的 REST 端点。该解决方案被装箱,部署到 Rancher(一个 Kubernetes 企业管理解决方案)中,每个人都出去庆祝。

第一个,单块,版本(作者图片)

乐观的诅咒

最初的测试一如既往地有效,但真实数据打破了一切,也一如既往。允许通过 API 直接发送多个文档的内容会带来内存问题。此外,随着文档数量的增加,响应时间减少了,在某些情况下,一个请求甚至需要十几分钟。很明显,系统还没有准备好在客户端以同步方式工作。

基于第一次尝试的结果,提出了三个要求。首先,客户端不应该暴露给同步 API。第二,应该应用一些节流。第三,早就应该进行监测了。

要将系统调用转换成异步调用,一个显而易*的解决方案是在应用程序前面放置一个消息代理,例如 Kafka。消息可以被格式化为 Avro,模式将被存储在模式注册表中,这将有助于模式管理。然后,客户将能够把要分析的文档发送给 Kafka,应用程序将对其进行处理,并将结果发送回客户将会收听的另一个 Kafka 主题。因为在当前请求完成之前,应用程序不会收到另一个请求,所以内存问题将会消失。例如,节流可以通过 Kafka 主题分区的数量来实现。监控可以使用第三方库,一切正常。

但对于一个主要目的是使用机器学*模型来分析文档的应用程序来说,这是不是太多了?即系统在被很好地调用时很好地工作。此外,根据应用程序的吞吐量和文档的大小,让许多文档在 Kafka 主题中等待可能会成为一个内存问题。

基于此,并应用良好的旧职责分离,采用的路线是实现这三个新功能,异步调用、节流和监控,不是在应用程序内部,而是作为另一个应用程序(从现在称为 Orchestrator)的一部分,该应用程序将独立部署并调用文档分析器应用程序。此外,客户现在将发送可以下载文件的位置(例如 AWS S3 ),而不是它们的内容。这将缓解内存问题,并在需要时实现更快的文档检查,因为团队不需要接触客户来请求它们。

整个过程是这样的:

1.客户机将文档的位置和一个标识符(请求 id)发送给输入的 Kafka 主题,并监听输出的主题

2.Orchestrator 拾取消息,下载文档,提取其内容,调用文档分析器应用程序,等待响应,并在收到响应时将其发送给 Kafka

3.Orchestrator 使用最合适的工具收集和导出遥测数据

4.客户端根据请求 id 从响应 Kafka 主题中获取响应

语义听起来很棒,即一个指挥者指挥两个系统的操作,Kafka 和应用程序是两者的中心联系点,这使它处于一个独特的位置来监控周围的一切。

使系统在客户端异步(图片由作者提供)

自身成功的受害者

新方法很成功,更多的客户想使用它。然而,下一个用例带来了另一个复杂性。客户还想确定某些复选框是否被选中。

现在,应用程序必须以两种方式更新:

  1. 能够识别复选框
  2. 通过一个“if”语句来检查应该执行哪个管道,因为两个用例有不同的需求。

开发了复选框标识模型,并更新了 CI 管道,以将最新的模型文件包含到运行应用程序的容器中。Kafka 消息的 Avro 模式被更新,以作为有效载荷的一部分通知用例,然后一切又开始工作,直到下一个用例出现,带来了对另一个模型的需求,该模型应该能够识别签名是否存在。

重复上面提到的过程,即开发模型,将新的模型文件添加到 CI 管道,并插入另一个“if”语句以适应新的用例。

在那之后,情况是这样的:有五个工程师改变了相同的代码库,使用不同的模块,但使用相同的共享工具,例如图像处理方法,这开始违背 DRY(不要重复自己)原则。此外,对一个模型的每次更改都需要重新部署整个应用程序。随着模型被独立开发,它们版本的管理开始变得很糟糕。

重复的代码+来自不同空间的多个所有者=噩梦的秘诀(图片由作者提供)

各个击破,第二幕

正如开始提到的,我加入团队后的任务是帮助应用程序变得更具可伸缩性。一切都运行得很好,工具的选择已经很好了,所以这是一个重新考虑现有架构的问题。

我想到的第一个问题是:如果模型,尽管生活在相同的代码库中,是独立开发和维护的,是什么阻止了它们以相同的方式部署?答案不出所料:什么都没有。所以,我们进入正题。

第一步是将应用程序中的每个模型提取到它自己的存储库中。由于抗扭斜模型总是第一个被调用,所以它自然是第一个被提取的。它获得了自己的代码库、CI/CD 管道和 Rancher pod。现在,Orchestrator 在收到请求后,首先调用去歪斜模型,然后将得到的去歪斜文档传递给应用程序。接下来是要提取的文档分类模型,接下来是复选框和签名模型。剩下的代码库成为了 OCR 模型的基础。

但是,以前存在于 monolith 应用程序中的 ML 管道呢?嗯,因为他们的工作是通知哪个模型应该以哪个顺序被调用,自然的方向是将他们移动到指挥者那里。改变 Orchestrator 使其适合基于插件的架构,允许管道也可以独立开发,并简单地插入 Orchestrator。

将模型提取到微服务中,并将管道转换为可插拔组件(图片由作者提供)

让每个人都负起责任

这个新的架构似乎完全解决了这个问题。模型可以独立地发展,新的用例可以很快地添加进来(假设模型已经存在)。该应用程序已经成为一个完全分布式的应用程序,能够纵向扩展和横向扩展。但是对模型本身的监控呢?

到目前为止,Orchestrator 一直是遥测的单点,但现在应该为每个模型收集相同类型的指标。当然,自然的选择是应用 Sidecar 模式。sidecar 可以与模型一起部署,作为一个即插即用的解决方案,简单地添加到 pod 的部署描述符中,并成为模型 API 的代理,同时还收集指标。

最后,在考虑遥测的同时,我们还决定收集日志。仍然本着即插即用的精神,Fluentd 非常方便,也可以作为简单的部署人工制品添加到每个吊舱中。我们将 Elasticsearch 设置为这些日志的汇集点,瞧!现在,除了完全分布式和能够纵向扩展之外,应用程序是完全可观察的。

添加边车,使系统完全可*(图片由作者提供)

蛋糕上的樱桃

尽管一切都很顺利,但有一件事听起来还是不太对劲。Kafka 是一个很棒的工具,但是将它作为一个 API 向所有客户公开听起来并不合适。如前所述,为了促进模式的发展,我们使用了 Avro 和模式注册中心,虽然有很多库可以帮助集成,但这仍然不是很简单,尤其是在由 Kerberos 这样的解决方案保护的环境中。此外,通过 API 与外部系统交互的客户机更*惯于 REST 之类的东西,在某些情况下可能更喜欢它。

但是休息是第一选择,并没有像预期的那样起作用,就像开始解释的那样。此外,该系统具有异步性,一些客户已经在使用 Kafka。那么如何解决呢?很简单,通过添加 YAG,或者,另一个网关。

这个新的网关将与 Kafka 交互,并向客户端公开两个方法:发送(请求 Id,文档位置)接收(请求 Id,状态,结果)。前者将接收来自客户端的消息并将其发送给 Kafka,而后者将返回请求的当前状态(处理中、就绪、失败等)以及结果。

如果使用 Spring 之类的东西,将 REST API 连接到 Kafka 是非常容易的。不过,问题是要让多个客户端不断地访问数据库(我们在这个项目中使用了 MongoDB)。当然,请求是基于主键的,使用请求 id 作为索引集合的键,但是,根据请求的规模,这仍然可能导致问题。幸运的是,我们已经运行了一个 Redis 集群,我们可以将它用作缓存层。

允许客户在 REST 和 Kafka 之间选择

现在只是最好的时候。

整个建筑的典型代表(图片由作者提供)

参考文献

https://microservices.io/patterns/deployment/sidecar.html https://medium.com/nerd-for-tech/microservice-design-pattern-sidecar-sidekick-pattern-dbcea9bed783 https://thenewstack.io/ten-commandments-microservices https://en.wikipedia.org/wiki/Don't_repeat_yourself https://medium.com/omarelgabrys-blog/plug-in-architecture-dec207291800 https://piotrminkowski.com/2021/07/22/spring-cloud-stream-with-schema-registry-and-kafka/ https://www.fluentd.org/ https://epsagon.com/development/using-redis-to-optimize-mongodb-queries/

一张服务的网,只因为图像的美丽:)(图片由 Unsplash 提供)

非策略深度强化学*中的经验重放介绍

原文:https://towardsdatascience.com/a-technical-introduction-to-experience-replay-for-off-policy-deep-reinforcement-learning-9812bc920a96

探索提高深度强化学*代理样本效率的关键机制

机器人是一个定位于从深度强化学*中受益匪浅的领域。阿瑟尼·托古列夫在 Unsplash 上的照片

动机:深度强化学*代理的样本效率

训练深度强化学*代理需要大量的反复试验,以便代理学*健壮的策略来完成其环境中的一个或多个任务。对于这些应用,代理人通常只被告知其行为导致的奖励是大还是小。因此,代理必须间接地学*某些动作和状态的行为和值。可以想象,这通常需要代理对其行为和估计进行相当长时间的实验。

产生这些体验可能是困难的、耗时的和昂贵的,特别是对于像人形机器人这样的现实生活应用。因此,许多机器人学家和机器学*研究人员一直在考虑的一个问题是:“我们如何才能最大限度地减少我们需要生成的经验数量,以便成功地训练健壮和高性能的智能体?”

刚入门深度强化学*? 看看这个来自 OpenAI 的精彩介绍。

在类似人形机器人的应用中,为训练用于决策的深度强化学*代理生成经验可能是困难的、耗时的和资源昂贵的。幸好经验回放可以帮忙!图片由附身摄影Unsplash 上拍摄

进入:体验回放

正如你可能怀疑的,这就是经验回放的用武之地!这一关键技术背后的想法很简单——与其每次我们想训练代理人时都产生新的经验,为什么我们不继续从我们已经有的经验中学*呢?

经验重放是非策略深度强化学*算法的一个重要组成部分,它通过存储代理以前经历的环境交互来提高样本效率和训练的稳定性[1]。

体验回放缓冲区存储什么?

要回答这个问题,我们首先需要访问深度强化学*中“体验”的常*实现:

将培训体验表现为过渡和推广

在强化学*中,经验被表示为过渡和展开,后者是一组时间上连续的过渡。这些转换,以其最一般的形式,由作为训练样本提供给代理的五个特征/信号的五元组组成:

  1. 状态 ( s ):表示代理可用的信息,可用于动作选择。你可以把 s 看作是代理能够观察到的世界的表示。典型地,代理不能观察世界的真实状态,只是它的一个子集。
  2. 动作 ( a ):这些表示代理在与环境交互时可以做出的选择,无论是离散的还是连续的。代理人的行动选择通常会影响其下一状态s’奖励 r
  3. 奖励 ( r ):这些代表给予代理人的奖励,用于采取给定的动作给定的状态s*****或者,在某些情况下,仅仅用于观察/处于 a 对应的状态。*
  4. 下一个状态(s’):这表示代理处于状态 s 并采取动作后转换到的状态。****
  5. 完成信号 ( d ):这些是二进制信号,表示当前过渡是否代表给定展示/情节中的最终过渡。这些不一定用于所有环境,当不需要它们时(例如,没有终止条件的环境),它们可以简单地总是设置为 1 或 0。

象征性地写下,这些过渡五元组 T 给出如下:

过渡可以说是体验回放中最基本的体验单元。它从与其环境交互的代理中捕获一个样本数据点。

并且展示,也被称为情节或轨迹,并被表示为 R ,被给出为一组 N 过渡:

一个卷展栏对应一组 N (通常是连续的)过渡 T 。对于像机器人这样的应用程序,这些可能是机器人学*从 A 点到 b 点的相邻时间步。

这些过渡 T 和展开 R 是如何存储代理经验的主要表示。这些跃迁都位于跃迁空间内,我们用函数τ来表示。τ的定义域由主体状态动作空间 S x A 的笛卡尔乘积给出,共定义域由奖励状态空间( R x S )的笛卡尔乘积给出。在数学上,转移函数由下式定义(当它是确定性的时)😗***

转换函数/流形定义了状态和行动如何映射到奖励和未来状态。深度强化学*代理的目标是有效地学*这个转移函数,以及如何在其中进行规划和决策,以最大化回报。

我们如何实现体验回放?

Jason LeungUnsplash 上的照片。

体验回放通常实现为循环、先进先出(FIFO) 回放缓冲区 (可以把它想象成存储我们代理的体验的数据库)。我们使用以下定义对我们的经验重放缓冲区进行分类[1]:

  1. 重放容量:存储在重放缓冲器中的转换总数。
  2. 过渡年龄:定义为自过渡产生以来学*者所走的梯度步数。重放缓冲区的最早策略由缓冲区中最早转换的年龄表示。
  3. 重放比率:每个环境转换的梯度更新次数。假设代理可以通过重复训练相同的经验集来继续学*稳定的策略、行为和技能,较高的重放率有助于提高非策略强化学*代理的样本效率。

我们如何通过经验回放进行训练?

经验重放作为训练深度强化学*代理的训练程序的一部分。布鲁诺·纳西门托Unsplash 上拍照

我们已经讨论了如何描述重放缓冲区,但是它们是如何工作的呢?简而言之, replay buffers 为代理“重放”体验,允许他们重温记忆并进行培训。直观上,它允许代理“反思”和“学*”他们以前的错误。俗话说,我们从犯的错误中学*,对于经验回放来说也是如此。

经验重放缓冲区通常应用于非策略强化学*算法,通过捕获由与其环境交互的代理生成的所有样本,然后存储它们以备后用。重要的是,由于代理不符合策略(具有不同的训练与探索策略),从代理重放的样本不需要遵循连续的顺序。

我可以使用哪些库作为重放缓冲区?

在许多流行的 python 强化学*环境中都可以找到实现强化学*的功能,例如:

  1. TensorFlow 代理 (回放缓冲页面)
  2. 光线 RLLib (回放缓冲 API)
  3. 稳定基线 (使用带有软演员-评论家的重放缓冲)
  4. https://spinningup.openai.com/en/latest/(首页)********
  5. Keras-RL(首页)
  6. https://tensorforce.readthedocs.io/en/latest/modules/memories.html?highlight=replay buffer#memories(回放缓冲页)****

这些库中的许多都模块化地实现了重放缓冲器,允许选择不同的重放缓冲器不同的强化学*算法一起使用。

经验重放的最新进展

下面讨论的方法不仅提高了当今深度强化学*代理的采样效率和性能,而且这些技术及其相关方法有助于为许多新兴的新经验重放技术“播下种子”。杰里米·毕晓普在 Unsplash 上拍摄的照片

已经取得了重大进展,建立在经验重放的基础上,以进一步提高强化学*代理的样本效率和鲁棒性。这些进步可以大致分为两个主题:

(一)确定样本选择

㈡生成新的训练样本。

下面将讨论其中的每一个,以及文献中相应示例的样本。

确定样本选择(PER、LFIW、HER、ERO)

经验重放缓冲器显式管理强化学*代理的训练的一种方式是让它控制为代理重放哪些经验。一些文献示例包括:

  1. 优先化体验回放【PER】【4】:根据代理从该体验中学*会收到多少“惊喜”来分配数字“优先化”值。本质上,样本越“令人惊讶”(通常编码为 TD 误差),优先级权重就越大。********
  2. 似然自由重要性权重【LFIW】【5】:和 PER 一样,LFIW 使用 TD 误差来分配经验的优先顺序。LFIW 根据当前政策的可能性对经验进行重新加权。为了*衡偏差和方差,LFIW 还在政策内和政策外经验之间使用了一个无似然密度比估计器。这个比率又被用作优先级权重。********
  3. 后*之明体验回放 【她】【6】:通过不仅存储用于给定情节的原始目标的转换,还存储 RL 代理的其他目标的子集,来解决与稀疏回报环境相关联的问题。****
  4. 体验重放优化【ERO】【7】:学*一个单独的神经网络函数,用于确定从重放缓冲器中选择哪些样本。因此,除了底层代理的神经网络(通常是演员和评论家网络)之外,该架构还分配神经网络来为其他学*者确定样本选择。********

这些方法都控制如何为训练代理选择新样本,并且反过来允许改进深度强化学*代理的整体训练。新的经验重放不是仅仅向代理提供一组随机的经验进行训练(并随后使用梯度优化技术进行优化),而是启发式地或通过额外的梯度优化方法学*哪些样本提供给代理,以便最大化学*。重放缓冲器不仅提供和存储用于教导代理的隐喻书籍和课程,而且实际上负责决定在正确的时间给代理哪些书籍和课程。

生成新的训练样本(CT,S4RL,NMER)

另一类经验重放缓冲器集中于为代理生成新样本,以使用现有样本进行训练。一些文献示例包括:

  1. 连续转换(CT)【8】:通过使用 Mixup 9沿轨迹内插相邻转换,为连续控制环境中的强化学*代理执行数据扩充。********
  2. 出奇简单的自监督 RL(S4RL)【10】:提出、实现并评估七种不同的增强方案,以及它们在现有离线 RL 算法中的表现。这些增强机制有助于*滑深度强化学*代理的状态空间。********
  3. 邻域 Mixup 体验回放【NMER】(免责声明:我的研究)【11】:与 CT 类似,NMER 使用 Mixup 将附近样本重新组合生成新样本。然而,NMER 不是组合时间上相邻的样本,而是根据提供的距离度量组合(状态,动作)空间中最近的相邻样本。****

体验重放的未来(我的展望)

最初,重放缓冲区的任务只是存储代理的经验,对于代理如何使用样本来改进其策略和值函数几乎没有控制。然而,随着新的经验重放缓冲区的出现,重放缓冲区正在获得越来越重要的作用,不仅作为强化学*代理的经验存储机制,而且作为代理的训练器和样本生成器。从上面提到的技术以及更多的技术来看,我相信体验回放有几个发展方向。

  1. 插入的经历 ( 免责声明:这是我的硕士论文的主要研究领域。)—使用现有的经验,重放缓冲区将增加可用于训练的强化学*代理的经验集,从而导致更健壮的策略和决策制定。
  2. 低偏差、低方差样本选择 —重放缓冲区将进一步改进从重放缓冲区中选择样本的方式,以确保他们隐式教授给代理的经验分布有助于代理了解环境的真实表示及其相关的转换函数/流形。
  3. 神经经验重放 —如 ERO 等重放缓冲方法所*,经验重放中的一些机制可以自己学*,并且当作为神经网络实现时可以近似函数!随着经验重放方法的不断成熟和变得更加复杂,我相信我们将看到不同神经网络架构(MLPs、CNN、GNNs 和 Transformers)的持续集成和使用。

感谢您的阅读!要查看更多关于计算机视觉、强化学*和机器人技术的内容,请 关注我 。考虑加盟 Medium?请考虑通过这里 报名 。感谢您的阅读!

参考

[1]费杜斯,威廉,等,“重温经验重放的基本原理。”机器学*国际会议。PMLR,2020 年。**

[2]布洛克曼,格雷格,等,“开放的健身房。” arXiv 预印本 arXiv:1606.01540 (2016)。

[3]托多洛夫、伊曼纽尔、汤姆·埃雷兹和尤瓦尔·塔萨。“Mujoco:基于模型控制的物理引擎。” 2012 IEEE/RSJ 智能机器人及系统国际会议。IEEE,2012 年。

[4] Schaul,Tom 等,“优先化的经验重放” ICLR(海报)。2016.

[5] Sinha,Samarth 等人,“使用无似然重要性权重的经验重放”动态学与控制会议。PMLR,2022 年。**

[6] Andrychowicz,Marcin 等,“后*之明经验重放”神经信息处理系统进展 30 (2017)。**

[7]查,,等.“体验重放优化” IJCAI 。2019.

[8]林,,等.“连续过渡:通过混合提高连续控制问题的采样效率” 2021 年 IEEE 机器人与自动化国际会议(ICRA) 。IEEE,2021。

[9]张,,等.“混合:超越经验风险最小化”国际学*代表会议。2018.**

[10] Sinha、Samarth、Ajay Mandlekar 和 Animesh Garg。“S4RL:机器人离线强化学*的惊人简单的自我监督。”机器人学*会议。PMLR,2022 年。**

[11] Sander,Ryan 等人,“邻域混合经验重放:连续控制任务中提高样本效率的局部凸插值”动态学与控制会议。PMLR,2022 年。**

一个在 RNN 消失的渐变的真实故事

原文:https://towardsdatascience.com/a-true-story-of-a-gradient-that-vanished-in-an-rnn-56437c1eea45

你需要的只是一个简单明了的解释

递归神经网络试图推广前馈神经网络来处理序列数据。它们的存在彻底改变了深度学*,因为它们为从语言建模到翻译的众多迷人应用铺*了道路。然而,阻碍 RNNs 在许多这些应用中流行的一个问题是它们不能处理当输入序列很长时自然出现的长期依赖性。

正如我们在最后一个故事中所描述的,rnn 无法处理长期依赖性可以归因于它们的消失梯度问题,这是时间反向传播的副作用——用于训练这种网络的算法。

在这个故事中,我们将开始一个快速的旅程来了解时间的反向传播是如何工作的,以找出:

  1. 为什么渐变消失了?
  2. 为什么会引起短时记忆?
  3. 我们能做些什么来阻止它们消失?

照片由 Aron 视觉效果Unsplash 上拍摄

为什么渐变消失了?

在 RNN 中,任何示例(序列)造成的损失是序列中每个令牌造成的损失之和。这假定了常规设置,其中 RNN 为输入中的每个令牌生成一个输出。因此我们可以写

让我们试着找到∂l/∂w因为我们将需要它来进行梯度下降以更新w

接下来,wt23】ₓ是输入权重矩阵(用于循环层连接的输入),而 W ₕₕ是隐藏权重矩阵(用于从循环层到其先前输出的连接)。同时, W ₕ是输出权重矩阵(用于从递归层到输出的连接)。

现在很明显,一旦我们找到∂l/∂w,我们就找到了我们的目标∂l/∂w。我们利用链式法则把它写成

蓝色的两项很容易计算。对于第一项,损失是输出的直接函数,对于第二项,我们知道 yₜ=f(【wₒ】【ₕhₜ+bₕ】,所以在这两种情况下,只需要求导。

同时,对于第三个学期,我们需要记住

这意味着

所以通过使用链式法则,我们可以写出

蓝色的项很容易计算,因为每个 h【ᵢ】都是ₓ.w中的直接函数

请注意,如果我们想要使用完美符号,那么我们可能应该声明类似于 h=f(…) 的内容,然后在右侧使用 f 而不是 h ,但是我会这样保留它,因为除了其他原因之外,否则它看起来会更麻烦。

同时,对于另一个术语,我们似乎需要另一轮链式法则,因为

所以我们必须写

其中后插∂ht32】ₜt34】/∂wₕt37】ₓt39】产量

为什么会引起短时记忆?

现在,为了更仔细地观察消失梯度问题,让我们考虑一个 4 个单词的句子。这意味着 t=4 并且上面的表达式计算为

这我们可以认为是第四个词在w中更新权重的贡献。 注意考虑第一个词的唯一方法是通过第一个词,这个词(正如我们将要展示的)预计非常小。因此,就好像它不存在,尽管它与第四项有任何关联。

结果是参数将被偏向于仅捕获训练期间的短期依赖性。产生一个神经网络,它不能确定是否选择“今天早上我看到的猫非常饿”。

为了支持第一项预计会很小的事实,我们需要观察

由于网络的初始化方式(通常来自正态分布),权重自然很小,这同样适用于激活函数的导数,因为它通常是导数≤ 1 的双曲正切函数。用类似 ReLU 的东西替换 Tanh 可能只能解决部分问题。

我们能做些什么来阻止它们消失?

问题的根源显然是

我们能否重新设计循环层,使其不再必要?假设,我们宁愿让隐藏状态 h 被定义为

*是基于元素的产品

其中 G₁、g₂和 ĥ 中的每一个都是使用 h 作为先前隐藏状态的不同重现层的结果(它们都是它的函数)。

在这种情况下,我们有

我们不能再声称它总是≤ 1,即使这四项都成立。这个事实正是像 LSTM 和 GRU 这样的建筑用来克服梯度消失问题的。

杰奎琳·弗洛克在 Unsplash 上拍摄的照片

我们的故事到此结束。我们已经探索了 rnn 如何以及为什么会遭受短期记忆的困扰,以及可以做些什么来缓解这个问题。希望你觉得这个故事很容易读懂。下次*,再*。

使用 Python 和 Statsmodels 的 White 异方差一致性估计量教程

原文:https://towardsdatascience.com/a-tutorial-on-whites-heteroskedasticity-consistent-estimator-using-python-and-statsmodels-7d38789150d1

菲利普·D·T1 在 Unsplash 上的照片

如何通过 Python 和 statsmodels 使用 White 的异方差一致性估计量

在本文中,我们将学*如何使用 HC 估计量来执行对异方差稳健的统计推断。

本文是以下两部分系列的第 2 部分:

第 1 部分:介绍 White 的异方差一致性估计量
第 2 部分:使用 Python 和 Statsmodels 的 White 异方差一致性估计量教程

在第一部分中,我们深入研究了 White 的异方差一致性估计的理论。让我们快速回忆一下我们在第 1 部分中学到了什么。

考虑以下线性模型:

线性模型(图片由作者提供)

y 是响应变量。对于大小为 n 的数据集,它是大小为【n×1】的列向量。假设模型有 k 个回归变量,包括截距。 β 是回归系数【β_ 1,β_2,…β_ k】的列向量,其中 β_1 是截距。 X 是回归变量的矩阵,包括矩阵第 1 列截距的占位符。 X 大小为【n X k】

下面是等式(1)的矩阵形式:

线性模型(图片由作者提供)

等式(1)的最小二乘估计为产生以下估计量:

的 OLS 估计器(图片由作者提供)

由于估计系数 β_cap 是随机变量,因此它们具有方差-协方差结构,由以下协方差矩阵给出:

拟合回归系数的协方差矩阵(图片由作者提供)

该矩阵的对角元素是系数估计的标准误差,这些标准误差用于导出系数的 p 值和置信区间,换句话说,用于测试系数是否具有统计显著性并计算其精度。

β_cap 的协方差矩阵使用下面的矩阵方程来估计(其解释和推导在第一部分中涉及):

估计系数的协方差矩阵的公式(图片由作者提供)

上式中,T5【X’X(-1)算子的转置,对括号中的矩阵求逆。这个等式的核心是σω,它是模型误差的以下【n x n】矩阵:**

当模型误差为异方差和非自相关时,回归模型误差的协方差矩阵(图片由作者提供)

σ 只是一个普通的比例因子,使得 ω_i=σ _i/σ 。当模型的误差为同方差(常方差)和非自相关(在横截面数据集中相当常*)时, σ _i=σ 对于所有 iω_i=1 对于所有 iω=I,恒等式矩阵。在这种情况下,可以看出系数估计的协方差矩阵的公式简化为以下简单公式:

当模型误差为同方差非自相关时,拟合回归系数的协方差矩阵公式(图片由作者提供)

由于 σ 不可直接观测,我们使用以下公式来估计协方差矩阵。这里 s 是拟合模型的残差的方差:

当模型误差为同方差非自相关时,拟合回归系数的估计协方差矩阵的公式(图片由作者提供)

不幸的是,当模型的误差是同方误差时,我们不能使用等式(6)或(6a ),而必须回到等式(4)。在这个方程中,σω, 模型的误差的协方差矩阵本来就是不可观测的,所以必须进行估计。

为此,我们使用以下由 Halbert White 提出的估计量(也在第 1 部分中详细介绍),或其改进之一(也由 White 随后提出):

怀特的异方差一致性估计量(图片由作者提供)

式(7)中,e_i 为第 I 个预测值对应的拟合模型的残差:e _ I =(y _ I—X_ Iβ_ cap】其中X**_ I为第 I 行 X 。**

在本文的其余部分,我们将把这些结果付诸实践。我们将看到在模型误差异方差的情况下,如何使用 White 的 HC 估计量对模型系数进行统计推断。

以下模型试图从几个社会经济因素来解释美国某县的贫困状况,具体来说,就是该县居民的年龄中位数、该县待售房屋的空置率以及该县至少拥有一个大学学位的人口比例。

估算县级贫困的线性模型(图片由作者提供)

为了训练这个模型,我们将使用由美国人口普查局收集并在县一级汇总的几个社会经济指标的使用数据。该数据是美国人口普查局进行的 2015-2019 年美国社区调查(ACS) 5 年估计值的子集。下表包含我们将使用的数据(点击或单击图像进行缩放):

根据使用条款美国人口普查局提取的美国社区调查数据集的子集

本例中使用的数据集可以从这里 下载 。完整的 ACS 数据集可以使用公开可用的API从美国人口普查局的网站上获取,或者直接从人口普查局的 社区资源管理器 网站上获取。****

我们将使用 Python 和 Pandas 将 ACS 数据文件加载到内存中,并且我们将使用基于 Python 的 statsmodels 包来构建和拟合线性模型。

让我们从导入所需的包并将数据文件加载到 Pandas DataFrame开始:

****import** pandas **as** pd
**import** statsmodels.formula.api **as** smf
**from** patsy **import** dmatrices
**from** matplotlib **import** pyplot **as** plt***#Load the US Census Bureau data into a Dataframe*** df = pd.**read_csv**(**'us_census_bureau_acs_2015_2019_subset.csv'**, **header**=0)**

Patsy 语法构建模型的方程。Statsmodels 会自动将回归的截距添加到模型中,因此我们不必在模型的方程中明确指定它:

**reg_expr = **'Percent_Households_Below_Poverty_Level ~ Median_Age + Homeowner_Vacancy_Rate + Percent_Pop_25_And_Over_With_College_Or_Higher_Educ'****

建立和训练模型并打印训练摘要:

**olsr_model = **smf**.**ols**(**formula**=reg_expr, **data**=df)olsr_model_results = olsr_model.**fit**()**print**(olsr_model_results.**summary**())**

我们看到以下总结:

线性模型的训练总结(图片由作者提供)

我们将忽略 statsmodels 报告的 R *方值(或 0.191 的调整 R *方值,因为我们的兴趣在于估计</understanding-partial-effects-main-effects-and-interaction-effects-in-a-regression-model-54e8a127c62d'>【即系数估计值】,它们的标准误差和 95%置信区间,以及系数是否具有统计显著性。让我们放大输出的相关部分:

系数估计值、它们的标准误差、p 值和 95%置信区间(图片由作者提供)

我们看到所有的系数估计值在< .001. By default, Statsmodels has assumed homoskedastic errors and accordingly used Eq (6a) reproduced below to calculate the covariance matrix of coefficient estimates which is further used to calculate standard errors, p values and confidence intervals.

The formula for the estimated covariance matrix of the fitted regression coefficients when the model’s errors are 同态分布非自相关的 p 处都是显著的(图片由作者提供)****

我们已经看到,如果误差不是齐次的,那么上述公式将产生误导性的结果。因此,我们需要知道模型的误差是同方差的还是异方差的。

一个简单的异方差视觉测试包括绘制拟合模型的残差(模型误差的无偏估计)与响应变量的拟合值,如下所示:

*********#Carve out the y and X matrices***y_train, X_train = **dmatrices**(reg_expr, df, return_type=**'dataframe'**)***#Get the predicted values of y from the fitted model***y_cap = olsr_model_results.**predict**(X_train)***#Plot the model's residuals against the predicted values of y***plt.**xlabel**(**'Predicted value of Percent_Households_Below_Poverty_Level'**)plt.**ylabel**(**'Residual error'**)plt.**scatter**(y_cap, olsr_model_results.resid)plt.**show**()******

我们得到下面的散点图(画红线只是为了说明异方差):

拟合模型的残差与响应变量的估计值的关系图(图片由作者提供)

模型的误差明显是异方差的,这应该使我们怀疑 statsmodels 报告的标准误差、p 值和置信区间。

幸运的是,statsmodels 允许您在拟合模型时使用几种异方差一致性估计量中的一种。这些被表示为 HC0、HC1、HC2、HC3 等。

第一个,HC0 是我们之前看到的 White 的原始异方差一致性估计量(复制如下):

怀特的异方差一致性估计量(图片由作者提供)

HC1、HC2、HC3 对 HC0 进行了改进,使其对小规模数据集的偏向性更小。MacKinnon 和 White 在他们 1985 年的论文中描述了后三种估计量。

我们将依次尝试这四种方法。在每种情况下,我们将拟合模型并打印出如下培训摘要:

*********#Ask statsmodels to use the HC estimators***olsr_model_results = olsr_model.**fit**(cov_type=**'HC0'**)
**print**(olsr_model_results.**summary**())olsr_model_results = olsr_model.**fit**(cov_type=**'HC1'**)
**print**(olsr_model_results.**summary**())olsr_model_results = olsr_model.**fit**(cov_type=**'HC2'**)
**print**(olsr_model_results.**summary**())olsr_model_results = olsr_model.**fit**(cov_type=**'HC3'**)
**print**(olsr_model_results.**summary**())******

让我们将所有 4 次训练的系数估计值叠加起来,并与原始的估计值进行比较:

使用不同异方差一致性估计后的系数估计、标准误差和置信区间的比较(图片由作者提供)

第一组四行包含标准误差和置信区间,假设均方误差,即使用等式(6a)。下一组行包含使用不同 HC 估计值的估计值:HC0 到 HC3。我们看到,即使在使用 HC0 到 HC3 之后,所有系数在 p < .001. This is good news. However, as expected, the standard errors of the coefficient estimates become larger and the corresponding C.I.s become wider after accounting for heteroskedasticity.

Let’s zoom into a portion of the above figure to see what we mean:

Comparison of coefficient estimates, standard errors and C.I.s assuming homoskedastic errors and using White’s HC estimator (Image by Author)

Let’s look at the data for the coefficient estimate of 房主空置率下仍然具有统计显著性。在不考虑异方差误差的情况下,系数估计的标准误差为 0.088,但是当我们考虑异方差时,该系数的标准误差几乎翻倍,达到 0.158。

在不考虑异方差的情况下,房主 _ 空置率的系数估计的 95% C.I.s 为【0.748,1.091】。在考虑异方差后,它们变得更宽:【0.609,1.230】。******

我们还看到,HC1 至 HC3 的使用导致 White 的 HC 估算器估算的标准误差向上微移,尽管幅度非常小。例如,HC3 估计房主空置率系数的标准误差为 0.163,与 HC0 报告的估计值 0.158 相比,仅“提高”了 3%。**

无论如何,主要的收获如下:

面对异方差,回归模型的系数估计会失去精度。

因此,如果发现模型的误差是异方差的,这是横截面数据集中经常出现的情况,我们应该始终使用异方差一致性估计来对系数估计进行合理的统计推断。

下面是本文中使用的完整源代码:

参考文献、引文和版权

数据集

根据使用条款,从美国人口普查局提取的美国社区调查数据集。

报纸

怀特,哈尔波特。"异方差一致性协方差矩阵估计和异方差的直接检验."计量经济学,第 48 卷第 4 期,1980 年,第 817–38 页。JSTOR ,https://doi.org/10.2307/1912934.2022 年 9 月 25 日访问。 PDF 下载链接**

James G MacKinnon,Halbert White,具有改进的有限样本性质的一些异方差一致性协方差矩阵估计量,计量经济学杂志,第 29 卷,第 3 期,1985 年,第 305-325 页,ISSN 0304-4076,https://doi . org/10.1016/0304-4076(85)90158-7。(https://www . science direct . com/science/article/pii/0304407685901587)PDF 下载链接**

形象

本文中的所有图片版权归 Sachin Date 所有,版权归 CC-BY-NC-SA 所有,除非图片下方提到了不同的来源和版权。

如果你喜欢这篇文章,请关注我的Sachin Date获取关于回归、时间序列分析和预测主题的提示、操作方法和编程建议。**

给网球电视的(不浪漫的)情书

原文:https://towardsdatascience.com/a-unromantic-love-letter-to-tennis-tv-9daa4633ff81

约瑟芬·加塞在 Unsplash 上的照片

给网球电视的(不浪漫的)情书

用统计数据来证明满足我的 YouTube 瘾

今年的 ATP 巡回赛已经在澳大利亚网球公开赛之前开始了,拉法在墨尔本将冠军带回家——这使他打破了连续 19 个赛季获得冠军的纪录。鉴于这篇文章的标题,你可能会认为我是一个终生的网球超级粉丝,这是由令人印象深刻的青少年网球生涯或球场上的某种个人卓越所滋养的。现实是我:

  • 几乎完全是将我的第一次发球打在网上
  • 我对超过 10 次相当不稳定的地面击球的反弹感到兴奋

然而,自从去年网球电视(ATP 巡回赛的官方 YouTube 频道)进入我的生活,我现在几乎每天都看网球。这篇文章试图理解为什么我觉得“YouTube 集锦”这种媒体对一项我并不感兴趣的运动如此有吸引力。像往常一样,这个过程将是完全过度设计这个想法,并在这个过程中证明在我的手机上升级我的 YouTube“应用程序时间限制”是合理的。

亮点可以让你跟上这个季节的故事

背景很重要——这一点在我踢足球时变得非常明显。我对足球知之甚少,只够知道一支球队更有可能赢得英超联赛还是降级。但是语境是我和我的朋友在观看同一场足球比赛时产生以下两种观点的原因:

  • 两个低于标准杆的球队正在努力将 5 次传球串在一起,目前是一场零进球的*局
  • 两支以“坚韧风格”著称的球队之间的史诗般的赛季结束保级战

网球也是如此。正如每日比赛让足球迷能够了解赛季故事和相关比赛一样,跨越多场比赛的每日 YouTube 集锦也给了网球迷同样的机会。这很有帮助,因为关注网球开始需要更多的努力。

网球赛季的故事过去很容易理解

“三巨头”的出现和后来的统治地位意味着,以前关注网球并不需要太多——只需要关注 3 名球员(德约科维奇、费德勒和纳达尔),因此只需要 3 场面对面的比赛。这听起来可能有点夸张,但在过去的 18 年(2004 年至 2021 年)中,他们赢得了 71 个大满贯中的 59 个——这超过了每 5 场比赛中的 4 场,其中 8 年完全由他们主导。

鉴于这样的统治地位,以及由此而来的关于哪些球员将在“大赛”中扮演重要角色的决定论,真的没有必要去关注这个赛季剩下的比赛。这种情况正在改变。随着德约科维奇的统治地位开始受到新一批人(梅德韦捷夫、泽维雷夫等)的挑战,不再有同样的一小群球员宣称接近类似的统治地位。

有 3 名玩家,就有 3 名玩家紧随其后——这只是对二项式系数——“3 选 2”的陈述。8 个玩家会有 28 个,20 个玩家会迅速增加到 190 个。随着统治地位在比赛顶部的下滑,观看网球比赛以跟上赛季故事的数量增长非常快。你必须开始看大量的网球比赛,以防止最终看完一场大满贯半决赛,并努力说出两个“未知”的名字。亮点使这更容易跟随,在一个很酷很酷很酷的 10 分钟编辑中瞥*一场锦标赛的最后 8 场比赛。

然而,这就引出了一个真正的问题:即使你能看完所有的网球比赛,你还想看吗?尽管我喜欢在运动中安顿下来,但对我来说,答案是响亮的不。

大多数网球都不是网球

大多数网球比赛实际上并不是运动员在他们之间来回击球。现在,这不一定是网球特有的问题,也困扰着其他运动(最明显的是过度统计的美国运动),但值得记住。事实上,据估计一场网球比赛中只有 17.5%的比赛是用球进行的——这个 reddit 帖子证实了这一点(reddit 仅在可信度上被维基击败)。花费了大量的时间:

自从疫情开始以来,这种情况变得更加严重,球员们不得不在两局之间自己拿毛巾。

大多数网球都不是“激动人心的网球”

就像这篇文章中的大多数观点一样,网球中的大多数观点并不那么有趣。希望这不是那个有争议的声明,但即使如此,这也是我试图完全过度设计问题来证明这一点的地方。要做到这一点,需要定义在网球比赛中是什么让一分“激动人心”。对我来说,它是以下之一(或者最好是组合):

  • 它包含一个闪光弹(灼热的胜利者,tweener,一些其他 sikkkkk 技能或任何 Dimitrov 反手——跳到 1:02 分钟)
  • 它包含一个长时间的反弹,最好有一点动量摆动
  • 这很重要

现在前两者很难衡量,但是根据定义,在任何特定的网球比赛中都会很少。两者都是相对于*均值来定义的(“闪耀”和“长”),所以根据定义,它们会很少,所以如果这是你所追求的,那么无论如何高光是适合你的。

最后一点更容易量化——一分有多重要可以被认为是它对你赢得整场比赛(不仅仅是这场比赛或一盘比赛)的机会有多大的影响。为了量化“机会”,我们需要一个模型。

基于点的建模

我们对比赛中哪些分数最重要有一个直观的理解。赛点非常重要。设定点也是如此。此外,作为一个整体的*局打破和标准破发点。让这些观点有趣的(也确实存在的)是网球评分系统的离散化。可以说,评分系统是提升网球运动整体水*的关键。如果我们不在网球比赛中酌情计分,那么类似于大数定律(LLN)的东西就会出现,使它成为一件相当无聊的事情。这是因为如果我们简单地进行一场 100 分的比赛,那么稍微好一点的玩家总是会赢——这可以用“分数问题”从数学上证明。

为了给这种说法添加一点数学知识,让我们引入“基于点的建模”(太聪明了,不是我的原创想法)。简单来说,这个理论是这样的:

  • 两名球员打网球,ab
  • 每个人发球和回球
  • 给他们每个人一个概率,让他们在发球时赢得任何给定的分数{ p_ap_b },因此回球时获胜的概率是{ (1 - p_b)(1 - p_a) }
  • 现在为网球规则写一个算法,并根据谁在发球使用上述概率模拟每一分
  • 让算法在网球规则中运行,随机模拟每一点,直到规则规定比赛结束

作为一个例子,如果我给两名球员 100%的机会赢得他们自己的发球(即p_a = p_b = 1.0),那么我们将模拟a先发球:

  • a连得 4 分赢得第一局(1-0)
  • b连得 4 分赢得第二场比赛(1-1)
  • a连得 4 分赢得第三局(2-1)
  • 等等等等

一旦我们用0 < {p_a, p_b} < 1引入一点随机性,我们就会得到更有趣的结果,但过程是一样的——模拟每一点,算法会在整个比赛中发挥作用,直到我们以胜利者结束。

现在我们有了一个模型,我们能用它做什么呢?

像往常一样,对于“足够小”的问题,我们有两种方法来计算某件事情发生的概率:

  • 暴力破解:在网球比赛中,从给定的起点模拟一系列比赛,计算a获胜的次数,然后除以模拟的比赛总数,得到a获胜的概率
  • 封闭形式:从任何给定的起点推导出一个公式来表示获胜的概率

幸运的是,由于时间原因,我们可以使用后者。这里的理论很大程度上依赖于组合学,并且由于网球的来回性质(发球、接发球、发球等)。)随着抢七局的到来,比赛变得有点复杂。幸运的是,这里的和这里的和解释得非常简单,我已经将它们打包成一个简单的 python 包,名为 tennisim

考虑到这一点,我们可以进行以下操作:

  • 模拟一系列网球比赛(为了简单起*,我们可以用p_a = p_b来模拟)
  • 在比赛的每一点,根据我们的基于点数的模型,计算出玩家a赢得比赛的概率

太好了,但是这个概率和激动人心的网球得分有什么关系呢?

正如我们可以认为一分如果不改变我们赢得整场比赛的整体机会就完全无关紧要(就像足球比赛中输的球队在 10 比 0 落后时被罚点球),我们可以认为“激动人心的分”是大大改变我们赢得比赛的概率的分。如上所述,这些可能是:

  • 赛点
  • 设定点(当设置关闭时)
  • *局决胜(当集合根据定义已经接近时)
  • 断点

换句话说,所有的分数都是因为网球有一个离散的计分系统而存在的。因此,如果我们获胜的概率在某一点上变化很大,那么这可能是一个令人兴奋的观察点。

让我们模拟一些比赛

让我们从模拟每对概率的 1000 个匹配开始{p_a, p_b},为了简单起*,我们设置p_a = p_b

图片作者。输出数据帧,其中每行对应模拟比赛中的一点。

在尝试做任何花哨的事情之前,让我们先看看数据,看看事情是否有意义。让我们为每个“概率对”{p_a, p_b}选取 25 个匹配,并绘制概率序列在整个匹配中的表现。我们应该期望他们:

  • 以 50/50 开始(因为我们在开始时将我们的玩家设置为同样优秀,即p_a = p_b)
  • 玩家a要么最终获胜(1),要么输掉比赛(0),要么以 1 或 0 结束
  • 始终*稳地波动
  • 在任何一点上最大波动 0.5(这个 0.5 只发生在最后一盘抢七或最后一局*手)

让我们对分数进行分类,这样我们就可以根据一场比赛的百分比而不是绝对分数(因为每场比赛会略有不同)来绘制分数,然后绘制分数。

作者图片

我们在看什么?

  • 正如预期的那样,所有路径都以 50/50 开始,并朝着玩家a前进,要么赢(100%)要么输(0%)
  • 很明显,50%的路径比 80%的路径更像“随机漫步”,80%的路径看起来有点跳跃——80%的一些点在最后从 50%跳跃到 0%/100%
  • 60%和 70%的匹配介于两者之间,因为随着一些大的跳跃,路径变得更加确定

作为直接观察,我们可以假设如下:

“如果球员在发球方面相对更好,那么比赛的大部分时间似乎不是很重要(阅读:不有趣),相对较少的分数决定了比赛的整体结果”

在解释为什么之前,让我们试着通过以下方式让这听起来更有说服力一点:

  • 试图用统计学把上面的陈述变成数字
  • 试图使用听起来很花哨的词来听起来更有说服力

“概率变化”的分布是什么样的?

假设我们现在要看“元分布”,即潜在变量是概率本身的概率分布,让我们通过将“概率 chg”(上图中的波动)重命名为“兴趣”来简化事情。现在我们可以:

  • 对图上的上述线求一阶差分,得到每个点的“兴趣”
  • 根据概率对绘制它们{p_a, p_b}

作者图片

因此,当我们不把每场比赛看做一个时间序列时(而只是从每个{p_a, p_b}对的所有点的横截面来看),似乎在球员赢得更多自己的发球得分的比赛中,有更多的得分对比赛几乎没有影响——上面显示的是 0%左右越来越紧密的分布,其中 0%代表一个完全无关紧要的点。

但是,鉴于我们已经消除了时间序列元素,我们可能会在右下方的分布中屏蔽以下内容:

  • 大多数p_a = p_b = 80%比赛令人难以置信的无聊,没有有趣的分数
  • 一些p_a = p_b = 80%匹配是令人难以置信的史诗,包含了分布尾部所有有趣的点

为了验证这一点,我们可以看看:

  • 计算比赛特定统计数据(计算统计数据每个时间序列内)
  • 为了方便起*,将这些特定比赛的统计数据进行*均(或者只显示它们的分布以获得更完整的图片)

让我们来看看方差

鉴于上述分布看起来很钟形,虽然越来越厚尾,看看赢概率的方差可能是一个有用的措施。首先,让我们看看每场比赛获胜概率的总方差,它是给定服务概率对的所有比赛的*均值:

df_res[['p_a', 'p_b', 'match_id', 'prob_chg']].groupby(['p_a', 'p_b', 'match_id']).var().groupby(['p_a', 'p_b']).mean().rename(columns={'prob_chg':'Var(Prob Chg)'})

作者图片

有意思。这是一个相当无量纲的量,但趋势很明显。尽管我们上面说过,看起来以前看起来“无聊”的比赛实际上在获胜概率上产生了更多的变化。然而,我们忽略了一些事情:

  • 差异发生的地方:有可能所有的差异都发生在一场比赛的最后,所以你必须看完整场比赛才能得到好东西
  • 多少分构成了最大的差异:如上所述,看起来p_a = p_b = 80%游戏似乎在很大程度上被一些大的偏差所支配

为了深入了解这一点,我们可以做以下事情:

  • 在每场比赛中,根据分数的“兴趣”大小(获胜概率的变化)对分数进行排名
  • 计算每次匹配的方差
  • 计算顶部n点对方差的贡献(如果我们取所有能提供 100%方差的点)
  • 在给定概率对的所有匹配中*均这些百分比贡献

作者图片

上面的图表显示了什么?

  • 在最左边,我们可以看到对于p_a = p_b = 50%,“最有趣的点”占总兴趣的不到 10%,而对于p_a = p_b = 80%我们接近 25%
  • 在最右边,我们可以看到对于p_a = p_b = 80%,几乎 80%的变化都是由 10 个最大的点来解释的

换句话说,虽然这些比赛确实有更多的差异,但这种差异高度集中在选定的几个点上,对比赛的其余部分没有太大影响。

为什么?为什么会这样呢?

在极端的情况下,我们可以想到p_a = p_b = 100%——每个球员都有把握赢得自己发球的每一分。抛开游戏永远不会结束的事实(你会永远被锁定在第一盘抢七),它说明了上述的限制。每盘由 12 场完全没有意义的比赛组成,这 12 场比赛肯定会导致决胜局。随着p_a = p_b = 80%的出现,它不像现在这样极端,但它正在向那里发展。事实上,以 80%的概率赢得任何给定点数的给定发球游戏的概率是 98%。

即使你在你的发球比赛中落后 1 分(即 0-15 分),有 80%的机会在你的发球中赢得一分,你仍然有 93%的机会最终赢得比赛。这意味着大部分比赛都很无聊——用通俗的话来说,就是“发球机器人”连续 12 场比赛不停地发球得分,直到你达到 6-6,然后在抢七中决定整个比赛。或者,其中一个发球机器人出现了短暂的故障,被打破了(这种情况不太可能发生,但有可能发生),在这种情况下,这一局几乎肯定结束了,将以 6-4 结束,但仍然只有一个短暂的“感兴趣”的时刻。如上所述,这是忘记了技巧击球和史诗般的对打——然而,随着越来越多的点数开始变得越来越不均衡(更好的发球),这些也不太可能发生。

那么自动柜员机 ATP 在哪里?

鉴于以上所述,这感觉有点像一个引导性的问题。站出来说我们正处于p_a = p_b = 50%的场景中,这真的会打乱我过于费力的观点,即 YouTube 强调的是跟上游戏的前进方向。

****答案是大约 65–70 %,但这看起来会随着顶级球员的身高继续上升。让我们提供一些数据来支持这种说法,而不是未经证实就把它扔掉。我们可以利用杰夫·萨克曼(Jeff sack Mann)编制的数据库,这为他的数据密集型网球网站 tennisabstract 以及他运营的令人惊叹的博客“Heavy Topspin”here提供支持。原始数据文件可以在这里找到。让我们把数据拉进来,看看随着时间的推移,网球运动员的*均身高。

作者图片

因此,自 20 世纪 70 年代初数据库开始以来的过去 50 年中,这是一个非常明显的趋势。为什么?因为他们发球更好——发球是你的一次机会(一次机会),让你可以先发制人。这种身高趋势不会比现在的前 4 名更明显。抛开 6 英尺 2 英寸的德约科维奇不谈,以下三位都是新球员的一部分,他们分别是:

  • 梅德韦杰夫 6 英尺 6 英寸高
  • 泽维雷夫身高 6 英尺 6 英寸
  • 齐蒂帕斯 6 英尺 4 英寸

为了证明身高和服务能力之间的关系,我们可以使用一些数据——杰夫在 2017 年这里展示了一些数据。同样,使用 Jeff 的数据,我们可以看到一些常*的发球指标是如何与身高相关的。这些指标是:

  • 赢得服务游戏的百分比
  • SPW:赢得了%的服务点(这是我们在上述模型中的{p_a, p_b})
  • 第一次发球得分:第一次发球得分的百分比
  • 得分率:得分的发球的百分比

为了计算这些,而不是只查看数据库中的每一场 ATP 比赛,我们希望确保一些已经存在了一段时间的球员不会过多地扭曲我们的统计数据。换句话说,如果我们有一个异常出色的 5 英尺 9 英寸的发球手,他在 10 年里打了每一场 ATP 比赛,那么当我们对身高和这些数据之间的*均关系感兴趣时,这个球员将产生不成比例的影响。

为了解决这个问题,我们将利用棒球中广泛使用的一个概念,叫做‘季节年龄’。25 岁在棒球中被广泛使用,但是我们可以看看我们样本中网球运动员的*均年龄来决定什么年龄最合适。

作者图片

因此,即使排除“三巨头”,ATP 球员的*均年龄也在变老。看着上面的内容,让我们把 27 岁作为我们下面衡量标准的基础。在我们计算它们之前,让我们检查一下我们的身高分布是什么样的,以及我们是否需要对我们的身高进行分类。

作者图片

奇怪的是,对于一名 ATP 球员来说,看起来唯一比身高 175 厘米(5 英尺 9 英寸)更糟糕的事情就是身高 181 厘米或 186 厘米。事实上,这可能只是一个数据问题。让我们“修正”一下我们的身高数据,这样我们就能得到下面更*滑的分布。我们也将斗尾。

作者图片

最后,让我们选择我们的“27 岁赛季”数据,并计算我们的服务统计。

作者图片

以上 4 张图显示了身高和我们的指标之间的关系,每个指标都显示了身高对于发球优势的重要性。还计算了 r *方值,结果显示,*均而言,每个指标中 90–95%的变化都可以用身高来解释。引人注目。

请包起来

那么——我们展示了什么?

  • 就像其他运动一样,集锦提供了一个很好的方式来跟上一个赛季的故事——随着男子网球中目前出现的“统治稀释”,这一点变得越来越重要
  • 网球的大部分时间都没有花在打网球上
  • 打网球的大部分时间可能是无关紧要的网球,但这在多大程度上是真实的取决于球员的服务能力
  • 目前,ATP 巡回赛选手的*均发球能力并没有那么令人担忧,但是随着越来越高的顶级职业选手的趋势继续,更多的网球比赛将包含相当“无聊”的分数

因此,我觉得完全有理由继续我早上的例行公事,狼吞虎咽地吃掉网球电视放在我面前的任何东西。尤其是这个。而这个。还有这个也是。我是说,这些都是好东西,你应该去看看。

洛登不等式的一个用例

原文:https://towardsdatascience.com/a-use-case-for-lordens-inequality-d701dc7f1ccc

一个非常有用的概率不等式的典型假想用例。

照片由 papazachariasapixabay 上拍摄

爱丽丝是一个勤奋且非常有条理的人。她总是根据一个完全适合她的系统来运作,并让她保持一如既往的效率。随着时间的推移,她养成了一个特殊的*惯,那就是把项目分解成随机占用时间的子任务。在一天中,她可能有一个任务,也可能有十几个。

爱丽丝对自己的工作有自己的规定:她不完成最后一项任务就不回家,工作时间结束后也不开始新的任务。

作者图片

有一次,在完成一个她已经做了一年的长项目后,在回家的路上,她忍不住问自己以下问题:她能找到一种方法来估计她*均加班时间的上限吗?我们将帮助她完成她的使命:)

模型和实验:

爱丽丝提出的问题可以通过一个不为公众所熟知的概率属性来解决,这个属性是由Gary Lorden在他 1970 年的论文On Excess over the Boundary.中提出的

完成单个子任务所需的时间是一个随机变量。我们将把所有子任务的时间长度视为独立且同分布的随机变量:

作者图片

我们将指定另一个随机变量作为所有子任务的所有周期的总和。

作者图片

同样,我们将参考下一个量:

作者图片

作为工作时间后完成的最后一个子任务结束前的所有持续时间的总和,N(t)定义如下:

作者图片

超额的定义如下:

作者图片

这也被称为过冲

Lorden's inequality声明如下:

作者图片

也就是说,每当我们在超过某个正数的条件下有停止时间的累积和时,我们总是可以用子任务分布的不同矩来表示它。基本上,这个问题可以描述如下:

作者图片

让我们进行一个演示。首先,我们装入一些原料:

import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt

接下来,我们构建随机函数来帮助我们模拟解决方案:

我们将假设任务的持续时间是根据Gamma distribution分布的,T3 也被广泛用于建模等待时间。为了清楚起*,我们将下一个参数归属于该分布并将其可视化。

shape = 3
scale = 10
N_samples = 10000X = generate_gammas(shape, scale, N_samples)sns.displot(X)

作者图片

让我们写下一个函数,它采用分布参数和阈值来实现过冲。(在另一个用例中,您可以尝试插入不同的生成发行版) :

这里有一个全局函数来模拟几天内的超调量(几次实验) :

作为第一个例子,我们运行了一整年的模拟,也知道 Alice 一天工作从不超过 8 小时:

>>> N_worked_days = 365
>>> working_time_in_minute = 8 * 60 # 8 hours>>> run_experiments_for_one_excess(shape, scale, working_time_in_minute, N_worked_days)20.25803262081924

让我们计算二次分布的矩与一次分布的矩之比(期望值):

>>> X = generate_gammas(shape, scale, 100000)
>>> X_2 = np.power(X, 2)
>>> upper_bound = np.mean(X_2) / np.mean(X)
>>> upper_bound39.87780646001634

我们稍微调整了一下 Alice 的工作时间,看看这是否会影响她的加班时间:

更清晰的图像:

fig, ax = plt.subplots(figsize=(10,5))graph = sns.lineplot(range_fluctuation, experiments, label = "expected overshoot")
graph.axhline(upper_bound, color = "g", label = "upper bound")

ax.set_xlabel("minutes fluctuation")
ax.set_ylabel("Expected overshoot")
ax.legend(frameon=False)
plt.show()

作者图片

Lorden’s inequality肯定地告诉我们,即使过冲阈值波动,确定的上限仍然成立。这是因为上限只取决于任务持续时间的分布。

结束语:

我们在不等式的使用中没有提到一个重要的假设,因为分布的选择直接涉及到它。肯定是正面的。使用其他分布(如正态分布)会部分损害该属性,除非我们使用一个远离 0 且标准偏差非常低的*均值(类似狄拉克)。这样,我们可以确保——在我们的例子中——我们不会陷入负工期。
请随意将伽马分布替换为规范中注释的均匀/正态分布。

参考资料:

关于超限界

神经辐射场(NeRF)的基本概述

原文:https://towardsdatascience.com/a-very-basic-overview-of-neural-radiance-fields-nerf-db4a0d4c391b

它们有一天能取代照片吗?

图一。NeRF 管道。给定一大组图像,NeRF 学会隐式地表示 3D 形状,以便稍后可以合成新的视图。图片由米尔登霍尔等人从原始 NeRF 论文中检索而来。

深度学*时代始于它在传统 2D 图像识别任务(如分类、检测和实例分割)中带来的进步。随着技术的成熟,基于深度学*的计算机视觉的研究已经转向基本的 3D 计算机视觉问题——其中最值得注意的是合成物体的新视图,并从图像中重建其 3D 形状。许多方法将此作为传统的机器学*问题来解决,目标是在有限的一组训练迭代之后,学*系统从图像中“膨胀”出 3D 几何形状。然而,最近,一个全新的方向,即神经辐射场(NeRF),已被引入。这篇文章深入探讨了最初提出的 NeRF 的基本概念以及近年来它的几个扩展。

隐式表示几何图形

用于 3D 重建的 NeRF 模型和传统神经网络之间的最大区别在于 NeRF 是对象的特定于实例的隐式表示。

简而言之,给定从多个角度捕捉相同对象的一组图像以及它们相应的姿态,网络学*表示 3D 对象,使得新的视图可以以与训练视图集一致的方式合成。

从基本的 MLP 开始

图二。NeRF 培训概述。由米尔登霍尔等人从原始 NeRF 论文中检索的图像。

虽然这种隐式表示似乎很困难,但 Mildenhall 等人在他们的第一篇 NeRF 论文中表明,一个简单的多层感知器(MLP)拥有足够的能力来执行这样一个复杂的任务。

具体来说,这个全连接网络的输入是单个 5D 坐标(3 个用于位置,2 个用于观察方向),输出是给定位置的密度和颜色。实际上,密度只与位置有关,而与观察方向无关,因此仅使用位置来预测密度,而观察方向与位置特征相结合来预测所看到的颜色。

优化 NeRF

有两种实现技术可以更好地改进 NeRF,以更好地表示复杂场景——位置编码和分层体采样。

位置编码

以前的文献表明,将输入映射到更高维的空间有助于网络学*更复杂的功能。位置编码是一种特殊的编码功能,它通过使用高频函数来精确地执行该功能。在输入到 MLP 之前,位置坐标和视角方向都被输入到该编码函数中。

分层体积取样

当训练一个 NeRF 时,两个网络,一个粗略的,一个精细的,被联合优化。具体来说,我们首先使用标准采样训练一个粗网络。然后,给定粗略网络的输出,精细网络样本旨在对体积的更相关部分进行采样,以提高训练效率。

NeRF 的应用

图 3。NeRF 可能有一天会取代照片成为捕捉视觉记忆的新媒介。

当我们想要记住一个旅行过的地方,一个我们爱的人,或者一段我们珍惜的记忆时,照片一直是我们的首选媒介。NeRF 的兴起可能是一个更好的解决方案。

如果我们能够消除训练时间和图像数量的限制,NeRF 在多视图中存储视觉记忆的能力会大得多。它可能是一张“3D”照片,每个角度(甚至是你没有捕捉到的)都以高分辨率恰当地呈现在你面前。

超越标准 NeRFs

NeRF 的引入对 3D 重建领域来说是一股新鲜空气。将一个模型“过度拟合”到一个特定的 3D 实例是非正统的,但却产生了令人印象深刻的、新颖的视图合成品质。然而,首先提出的体系结构有一些主要的缺点。这些问题包括:

  1. 它需要同一物体的大量图像。
  2. 训练时间很长。
  3. 每个图像的相机姿态是必需的。

最近已经引入了许多作品来解决所有这些问题。下面我们列出了一些旨在解决这些问题的方法。

它需要同一物体的大量图像。

训练时间很长。

每个图像的相机姿态是必需的。

其他有趣的 NeRF 相关论文

结束注释

这就是你要的——对 NeRF 原始论文的一个非常简单的概述。这种表示视觉数据的新方式带来了无穷的潜力,并激发了大量不断改进的最新研究。也许有一天我们的记忆会以现实和想象的结合来储存。

“想象力比知识更重要。因为知识是有限的,而想象力包含整个世界,刺激进步,催生进化”——阿尔伯特·爱因斯坦

感谢你坚持到现在🙏 我定期写关于计算机视觉/深度学*的不同领域,所以 加入并订阅 如果你有兴趣了解更多!此外,这篇文章没有涉及任何数学或实现的细节,辐射场的扩展远远超出了我在这里提到的几个。详细解释请阅读原文。

谷歌云*台的(非常)简要概述

原文:https://towardsdatascience.com/a-very-brief-overview-of-google-cloud-platform-9dcce7bc1b1c

新用户开始深入了解 GCP 的介绍和术语

埃比尼·贝欣赏梵高的作品。来自维基共享资源

最近,我们的统计部门开始从本地服务器过渡到谷歌云*台(GCP)。可能你们中的许多人发现自己处于类似的情况。

我在使用 GCP 两年多的时间里发现,对于第一次学*云计算的新用户来说,网上提供的帮助少得惊人。我认为写一篇简短的文章来强调云的一些核心概念可能会有所帮助。

一个免责声明——我改编了为我们的暑期实*生写的文档,因为我认为它可能对更广泛的受众有用。我们使用由我们自己的 IT 部门构建的云环境,具有适合大型学术医疗机构的额外安全性。因此,该*台的一些功能被修改或禁用(例如,请求您自己的 DLVMs 的能力)。

如果你碰巧也为三盾工作,那么你就找对了文章。

什么是云?

云指的是另一家公司管理你的服务器,而不是你自己管理服务器的*台。之所以称之为云(在我看来,这是一个令人困惑的术语),是因为你正在访问一个由位于其他地方的成百上千个服务器组成的分布式网络,就像一个服务器“云”。

如果感兴趣,我真的很喜欢这个谷歌云中心的视频之旅,对我们来说,它位于南卡罗来纳州

值得一提的是,谷歌云*台是所有谷歌员工,包括数据科学家,在内部用于自己研究的相同工具。

云的优势是什么?

推动许多大型研究中心采用的最大优势是成本优势。但即使作为“最终用户”,我们也发现了谷歌云*台的几个优势。

无限的数据存储是最初吸引我们使用云的原因。我们一直在努力解决服务器存储问题。我现在有超过 30tb 的数据专门用于我的个人项目。

无需共享资源。另一个问题是太多的人(或者一个贪婪的人……)在运行大型计算任务,这会降低每个人的速度。对 GCP 来说,这不再是一个问题。

更新的工具。我们使用的许多工具,如 Tensorflow,都是由谷歌开发的(或者至少管理得更好)。访问最新的预构建软件包比自己尝试安装软件包要容易得多。

自我管理的环境。与共享服务器空间相比,单独的云 DLVM 通常更具可定制性,能够自由配置我们自己的单独环境是一个受欢迎的变化。

如果这些因素都不影响你的日常工作,我要补充一点,谷歌已经让我们获得了部署我们自己的模型所需的许多工具。因此,如果你正在编写希望其他人能够使用的代码,那么使用云将会有一个长期的优势。

简单说说安全问题

数据安全,尤其是在学术健康中心,理所当然是一个主要问题。谷歌云架构师与我们自己的 IT 部门一起开发了一个安全的*台,即使是谷歌员工也无法访问。

我要补充的是,谷歌在数据安全方面比我更有经验,我更愿意利用他们自己的*台,而不是试图自己建立一个。

云资源和术语

这是对您在使用云时会遇到的许多概念和术语的一个非常简单、非常基本的概述。我打算在以后的文章中更全面地讨论这些主题。

项目是一组共享存储和计算的用户,它是云中的基本组织级别,类似于共享服务器。我们的项目由我们研究实验室的 15 名成员组成。

每个项目都有一个唯一的项目 ID,显示在 web 界面的顶部。您需要知道这一点才能登录*台。

深度学*虚拟机,或 DLVMs ,是云的基本单元。对于使用过 Azure 或 AWS 的人来说,DLVM 和虚拟机完全一样。

DLVM 类似于您的个人计算机。DLVMs 不能共享;每个 DLVM 被分配给一个用户(尽管每个用户可以拥有任意多的 DLVM)。每个 DLVM 还有一个用于登录的唯一 ID。

就计算选项而言,DLVMs 几乎是无限可定制的。我发现拥有 16 个 CPU 内核和 60GB 内存的 n1-standard-16 配置非常适合我的大部分工作。我还添加了 2 个 T4 GPU 来训练基本的深度学*模型。这一成本约为 4 美元/小时

您只需在 DLVM 打开时付费。无论 DLVM 是被使用还是闲置,成本都是一样的,所以我们要求每个人都要注意,在一天结束时关闭他们的 DLVM。

Google 云*台的 JupyterLab 接口的一个例子。图片作者。

“计算引擎”菜单的一个示例,显示了分配给我们项目的 DLVM,以及启动/停止 DLVM 的选项。不幸的是,我不得不将 DLVMs 的名称灰化,一个典型的命名方案由 projectName-zone-userID 组成。图片作者。

存储桶是存储和共享文件的主要地方。与存储和计算不可分割的 Linux 服务器不同,存储桶与 DLVMs 位于不同的位置,这是该*台的一个方面,一开始可能会令人困惑。

这意味着,当您登录到 DLVM 时,存储桶中的文件不会立即对您可*。有一个简单的方法可以解决这个问题,通过将桶 fuse-mount到 DLVM,这使得所有的文件都可*。

一旦 bucket 被 fuse 挂载,它就无法与 DLVM 存储区分开来,并且可以使用相同的命令进行访问。我们希望在启动脚本中包含这个命令,这样当 DLVM 打开时它会自动运行。

该存储桶由项目的所有用户共享;被分配到项目的任何人都可以读写桶中的任何文件夹。这种情况正在改变,在过去几周内,我们的机构实施了“增强团队”功能,允许将多个存储桶附加到单个项目,每个存储桶具有不同的权限。但是,在这个存储桶中,所有成员仍然可以访问所有文件。

big query是 Google 版本的一个 SQL 数据库工具。作为一名专注于成像的数据科学家,我不经常使用 BigQuery,但我的同事告诉我,这是该*台最好的特性之一。它的速度快如闪电,并得益于谷歌作为关键词搜索领域世界领导者的专业知识。

Vertex AI 是向计算引擎提交代码的服务。向 Vertex AI 提交作业通常比在 DLVM 上运行要快得多,也便宜得多。对于那些熟悉 Slurm 或 Sun Grid 引擎的人来说,Vertex AI 是一个类比。

要使用 Vertex AI,您必须将代码包装在 Docker 容器中,并与 YAML 文件一起提交,该文件告诉引擎要应用什么计算资源。

作为 Docker 主题的一个简短说明,它已经迅速成为我们最喜欢的利用 GCP 的工具。对于我们的实*生,我的一个同事用 RStudio Pro 构建了一个定制的 Docker 容器,让我们可以提前完成设置他们的环境的艰苦工作。

这也使得使用 Vertex AI 变得更加容易,因为你已经在 docker 容器中调试了你的代码,这个容器很容易被推送到引擎中。

Google Cloud Software Developer Kit,或 Cloud SDK 是一个独立的可选命令行界面(CLI),用于从本地台式机或笔记本电脑运行云命令。我强烈推荐。

SDK 允许您从笔记本电脑管理 GCP,包括将文件复制到 bucket 从 bucket 复制文件,通过 SSH 访问您的 DLVM(包括交互式环境的端口转发),以及打开/关闭您的 DLVM。

在 Linux 和 Mac 上,SDK 命令可以从 shell 终端运行。在 Windows 上,Google 提供了单独的终端界面,它们也可以通过 PowerShell 获得。

一旦你熟悉了 SDK,就几乎不需要使用 web 界面,坦白地说,web 界面可能会很笨重。我将许多常用命令(如打开/关闭 DLVMs)打包成我的。bashrc 文件。

云 App。 最后,Google 还写了一个云主机智能手机 app。它的用途有限,但如果您忘记了,它可以用来打开/关闭您的 DLVM。

结论

感谢您的回顾,希望这些信息对您有所帮助!请留下评论,我很乐意回答任何问题。

我相信读者会很乐意听到您对该*台的体验,以及您可以提供的任何技巧或提示。

~噢

一个非常友好的终端和 Git 入门指南

原文:https://towardsdatascience.com/a-very-friendly-starting-guide-for-terminal-and-git-97c1757ecd4c

终端和 Git 是开发软件项目的基本工具,这里有一个简单、实用并且非常友好的入门指南

马库斯·斯皮斯克Unsplash 上拍摄的照片

介绍

在与软件新手相处了相当长的时间后,我看到许多人在终端和 Git 上苦苦挣扎。尽管这些工具使用起来几乎微不足道,但它们也是与计算机交互的一种不寻常的形式(更少的 UI,更多的文本),因此也是一种挣扎。因此,我写了这本简单、实用、非常友好(大量表情符号和迷因)的入门指南。不再挣扎!

注:本指南改编自我自己的二年级计算机工程课程入职指南

末端的

现在是时候感受一下黑客的感觉了!🐱‍💻你已经听说过一个叫做终端的东西,但从未体验过它是什么。终端是与计算机交互的程序员友好界面。使用终端,你可以做很多很酷的事情,例如,用一行代码删除电脑上的所有东西😱,以及基本的东西,例如显示目录的内容。🙄让我们从基础开始,首先就一些定义达成一致:

  • 命令:运行目录列表程序、文件删除程序等内置程序的一行。万一,你在问自己“这些是操作程序吗?”,答案是肯定的!这些也是程序!
  • 选项:稍微改变其功能的命令的开关/说明符,例如,列出目录中的隐藏的文件。你可以把选项想象成函数参数。

定义说够了!让我们看看一些实际的命令(和选项)!​

  • ls:LIsts 当前目录的内容。当用作 ls -l 时,它显示关于文件的更多细节,使用 ls -a 时,它也显示隐藏的文件。我们还可以将两个选项串联成 ls -al ,同时列出更多细节和隐藏文件!是不是很酷?🤓
  • mkdir:Makes adir具有给定名称的工厂。例如, mkdir fun 在当前目录下创建一个名为 fun 的文件夹。
  • 触摸 <文件名> :创建一个给定名称的空文件。
  • cd <路径> : C 将工作 d 目录切换到指定路径。例如,假设你目前在一个名为无聊 🥱的目录下(你的工作目录是无聊)CD 乐趣将工作目录改为乐趣!看,有了终端,享受乐趣就这么简单!🤩
  • pwd : p 打印终端的 w 工作 d 目录。
  • cat:将给定文件的提供内容打印到终端
  • less:将给定文件的初始内容以可滚动的格式打印到终端。对浏览大文件特别有用。点击 q 退出滚动。
  • mv:moves 将当前路径中的文件(或文件夹)移至其新路径。它也可以用于重命名。
  • CP:copies 文件。当与 -r 选项(recursion)一起使用时,它也可以复制文件夹。
  • rm <文件名>:Rem移动(或删除)给定的文件。当使用 -r 时,它也可以删除文件夹。运行这个命令的时间和地点要小心!它经常被用来恶作剧其他程序员…😛😛
  • sudo 它要求您输入管理员密码。这个命令是一个非常流行的迷因的动机!

这里有两个便于路径管理的附加说明。

  • ..指父目录。例如,如果当前目录是享受/博客光盘..将目录更改为享受
  • 指当前目录。例如, cp../fun.txt。将父目录中的 fun.txt 复制到当前目录中。

唷!🤯🤯我们讨论了很多事情,不是吗?你在很短的时间内学会了很多。你可能也很困惑,但这根本不是问题!继续,在你的计算机上打开一个终端并使用命令!感觉像个忍者!👨🏽‍💻👩🏽‍💻

PS: 这里的资料只是冰山一角,还有更多命令和选项需要学*。可以编辑文件( vinano )、安装/删除程序( apt-get )、连接其他电脑( ssh )等等。记住,谷歌是你的朋友!并不是说你需要它,但是这里有一个关于终端命令的很酷的教程。黑掉它!

饭桶

想想你开发的重要编码项目。你可能保存了代码的快照( important.pyvery_important.pyfinal _ very _ important . py,…,)以备后用,并以这样的文件夹结束📄📄📄。保存快照实际上被称为版本控制,有比存储一个文件的多个副本更酷的版本控制方式。 Git 是这样的工具之一(也是最受欢迎的一个)使得跟踪代码版本变得非常容易。把 Git 想象成一个程序员友好的 Google Drive 或 Dropbox(它们也保存了文档的版本,你可以返回到上面),可以在你的本地机器和云中运行!💻又是☁️,词汇第一:

  • 版本控制系统(VCS) :跟踪你的编码项目开发的软件。示例包括 git、mercurial 和 SVN。
  • Repository (Repo) :黑客对版本控制系统中编码项目的命名方式。🤓
  • 公共回购:每个人都可以访问的存储库。
  • 私有回购:只能由一部分人访问的仓库。
  • 远程:存储库的云(在线)副本。☁️
  • 本地:个人电脑上的项目副本。💻
  • Commit :在 git 历史中明确标记的检查点/版本/保存状态,以防您希望重新访问。
  • 推送:将本地提交转移到远程,上传。
  • :将远程内容转移到本地,下载。
  • GitHub :一个非常受欢迎的托管 git 软件的网站。它为查看、编辑和管理存储库提供了一个用户界面。大多数开发人员使用 GitHub 来托管他们的项目。

好吧!现在让我们看看如何使用 git。你可能已经猜到它不会有用户界面,对吗?反正谁需要 UI,我们懂终端!😉😉下面是 git 命令的一小部分。

  • git init :在当前工作目录下创建一个 git 存储库。调用此命令意味着您希望跟踪此文件夹下的更改。
  • git config-global user . email"your@email.com":通过配置您的邮箱地址向您介绍 git。这将用于私人回购的身份验证。🤝
  • git config-global user . Name【你的名字】 **:和上一个类似,介绍你的名字。🤝
  • git 克隆<https://url/to/repository . git>:在指定的 URL 中创建远程存储库的本地副本。通常每个项目只做一次。
  • git add:让 git 跟踪指定文件的变化。通常,您会跟踪所有的编码文件,但是如果您不需要某个文件的以前版本,您可以将其排除在版本控制之外。如果您推拉包含身份验证文件、敏感信息、非常大的数据集等的回购,这将特别有用。
  • git commit -m 包括提交消息是强制性的,该消息理想地解释了自前一次提交以来所做的更改。该消息将检查点与解释相关联。
  • git 推送:上传本地到远程。
  • git pull :下载远程到本地。
  • git status :显示有关(未)跟踪文件的当前状态、自上次提交以来的更改等信息。

Git 技能对于开发任何重要的软件项目都非常有用。然而,我很清楚,这是太多的内容,在短短几分钟内消化。这根本不是问题,因为 git 不是一个你应该熟记于心的工具。通常情况下,你只需了解基本知识,然后向你最好的朋友谷歌寻求更高级的需求。所以,继续吧,创建一个 GitHub 账户和你的第一个回购,然后开始玩吧!如果你想进一步阅读,这里有个链接

结论

在你走之前,如果你能在空闲时间练*一下 terminal 和 git 就好了。虽然它们真的是很酷的工具,但是如果你不练*,它们真的会令人沮丧。无论如何,编码快乐!👩🏽‍💻👨🏽‍💻

梯度下降和其他优化算法的可视化方法

原文:https://towardsdatascience.com/a-visual-approach-to-gradient-descent-and-other-optimization-algorithms-c82f45b7fc87

可视化梯度下降带动量梯度下降RMSpropAdam 之间的异同

克里斯汀·蒙克摄于 Pexels:https://www . Pexels . com/photo/photo-of-person-walking-on-unpaved-pathway-2599546/

介绍

如果你和我一样,方程不会自己说话。为了理解他们,我需要用一个具体的例子来看看他们是怎么做的。在这篇博文中,我将这一可视化原理应用于机器学*中常用的优化算法。

如今,亚当算法是一个非常受欢迎的选择。Adam 算法将动量学*速率的自调整添加到普通梯度下降算法中。但是动量和自调整到底是什么?

下面是这些概念所指内容的直观预览:

几种优化算法的行为。来源:作者的计算

线性回归

为了简单起*,我对二元线性回归模型使用了不同的优化算法:

y = a + bx

变量 y 代表我们试图用另一个变量 x 来预测/解释的一个量。未知参数有截距a斜率*b .*****

为了使模型符合数据,我们最小化模型和数据之间的差异的均方,其可以简洁地表达如下:

损失(a,b)=1/m||y-a-bx||

(假设我们有 m 个观察值,并使用欧几里德范数)

通过改变 ab 的值,我们有望提高模型对数据的拟合度。使用二元回归模型,一件好事是我们可以将损失函数值绘制成未知参数 ab 的函数。下面是损失函数的曲面图,黑点代表损失的最小值。

损失函数 OLS。来源:作者的计算

我们也可以使用等高线图来可视化损失函数,其中线是水*集(使得损失(a,b) = 恒定的点)。下面,白点代表损失函数的最小值。

等高线图损失函数 OLS。来源:作者的计算

梯度下降

普通梯度下降算法包括在最陡下降的方向上采取大小为 η 的步长,该步长由梯度的相反值给出。从数学上来说,更新规则如下:

在下一个图中,我展示了梯度下降算法隐含的一条轨迹。点代表迭代中 ab 的值,而箭头是损失函数的梯度,告诉我们在下一次迭代中向哪里移动。

一个关键特征是梯度下降算法可能会在水*集之间产生一些振荡。在一个完美的世界中,我们会像那样朝着最小值的方向*稳地移动。正如我们将看到的,增加动量是使轨迹向最小值*滑的一种方式。

梯度下降。来源:作者的计算

动量梯度下降

动量是指运动物体继续向同一方向运动的趋势。在实践中,我们可以通过考虑梯度的先前值来增加梯度下降的动量。这可以通过以下方式完成:

γ的值越高,当前更新中考虑的梯度的过去值越多。

在接下来的图中,我展示了梯度下降算法暗示的轨迹(蓝色 ) 和没有动量(白色)的

动量减小了沿坡度系数值的波动。一旦动量*均效应开始发挥作用,大幅上下波动往往会相互抵消。结果,随着动量的增加,我们朝着真实值的方向移动得更快。

有动量(蓝色)或无动量(白色)的梯度下降。来源:作者的计算

RMSprop

动量是梯度下降的一个很好的转折。另一条改进路线是引入一个针对每个参数定制的学*率(在我们的例子中:一个斜率学*率,一个截距学*率)。

但是如何选择这样一个系数特定的学*率呢?注意,前面的图显示梯度不一定指向最小值。至少在第一次迭代中没有。

直观地说,我们会给较小的权重给上下方向的移动,给较大的权重给左右方向的移动。RMSprop 更新规则嵌入了这个所需的属性:

第一行仅仅定义了 g 为损失函数的梯度。第二行表示我们计算梯度*方的移动*均值。在第三行中,我们在梯度给定的方向上迈出一步,但是通过过去梯度的移动*均值的*方根来重新调整。

在我们的例子中,因为斜率系数的梯度的*方往往很大,所以我们在那个方向采取小的步骤。截距系数则相反(小数值,大移动)。

RMSprop(蓝色)和渐变下降(白色)。来源:作者的计算

亚当斯

亚当优化算法具有动量,以及rms prop 的自适应学*速率。下面是几乎是亚当做的事情:

更新规则与 RMSprop 非常相似。关键区别是动量:变化的方向由过去梯度的移动*均值给出。

实际 Adam 更新规则使用 mv 的“偏差修正”值。第一步,Adam 将 mv 初始化为零。为了校正初始化偏差,作者建议使用重新加权版本的 mv:

下面,我们看到 Adam 诱导的轨迹有点类似于 RMSprop 给出的轨迹,但是开始更慢。

亚当(蓝色)和梯度下降(白色)。来源:作者的计算

主要情节

下一个图显示了由上述四种优化算法得出的轨迹。

主要结果如下:

  • 有动量的梯度下降比没有动量的梯度下降波动小。
  • Adam 和 RMSprop 采用不同的路线,在斜率维度上移动较慢,在截距维度上移动较快。
  • 正如预期的那样,Adam 显示了一些动量:当 RMSprop 开始向左转向最小值时,Adam 因为累积的动量而有更难的转弯时间。

几种优化算法的行为。来源:作者的计算

下图是同一张图表,但是是 3d 的:

几种优化算法的行为。来源:作者的计算

结论

在这篇博文中,我的目的是让读者对机器学*中使用的关键优化算法有一个直观的理解。

在下面,你可以找到用来制作本文所用图表的代码。毫不犹豫地修改学*率和/或损失函数,看看这会如何影响不同的轨迹。

代码(Python)

以下代码块加载依赖关系,定义损失函数并绘制损失函数(曲面和等高线图):

# A. Dependencies 
%matplotlib inline
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator

plot_scale = 1.25
plt.rcParams["figure.figsize"] = (plot_scale*16, plot_scale*9)

import numpy as np
import pandas as pd
import random
import scipy.stats
from itertools import product
import os
import time
from math import sqrt
import seaborn as sns; sns.set()
from tqdm import tqdm as tqdm       
import datetime
from typing import Tuple
class Vector: pass
from scipy.stats import norm
import torch
from torch import nn
from torch.utils.data import DataLoader
import copy
import matplotlib.ticker as mtick
from torchcontrib.optim import SWA
from numpy import linalg as LA
import imageio as io #create gif

# B. Create OLS problem
b0 = -2.0 #intercept
b1 = 2.0 #slope
beta_true = (b0 , b1)
nb_vals = 1000 #number draws

mu, sigma = 0, 0.001 # mean and standard deviation
shocks = np.random.normal(mu, sigma, nb_vals)

# covariate
x0 = np.ones(nb_vals) #cst
x1 = np.random.uniform(-5, 5, nb_vals)
X = np.column_stack((x0, x1))

# Data
y = b0*x0 + b1*x1 + shocks

A = np.linalg.inv(np.matmul(np.transpose(X), X))
B = np.matmul(np.transpose(X), y)
np.matmul(A, B)

X_torch = torch.from_numpy(X).float()
y_torch = torch.from_numpy(y).float()

# Loss function and gradient (for plotting)
def loss_function_OLS(beta_hat, X, y):
    loss = (1/len(y))*np.sum(np.square(y - np.matmul(X, beta_hat)))
    return loss

def grad_OLS(beta_hat, X, y):
    mse = loss_function_OLS(beta_hat, X, y)
    G = (2/len(y))*np.matmul(np.transpose(X), np.matmul(X, beta_hat) - y) 
    return G, mse

# C. Plots for the loss function
min_val=-10.0
max_val=10.0

delta_grid=0.05
x_grid = np.arange(min_val, max_val, delta_grid)
y_grid = np.arange(min_val, max_val, delta_grid)
X_grid, Y_grid = np.meshgrid(x_grid, y_grid)

Z = np.zeros((len(x_grid), len(y_grid)))

for (y_index, y_value) in enumerate(y_grid):
    for (x_index, x_value) in enumerate(x_grid):
        beta_local = np.array((x_value, y_value))
        Z[y_index, x_index] = loss_function_OLS(beta_local, X, y)

fig, ax = plt.subplots(subplot_kw={"projection": "3d"})

# Plot the surface.
surf = ax.plot_surface(X_grid, Y_grid, Z, cmap=cm.coolwarm, linewidth=0, antialiased=False, alpha=0.2)

ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter('{x:.02f}')

ax.scatter([b0], [b1], [true_value], s=100, c='black', linewidth=0.5)

x_min = -10
x_max = -x_min
y_min = x_min
y_max = -x_min

plt.xlim(x_min, x_max)
plt.ylim(y_min, y_max)

plt.ylabel('Slope')
plt.xlabel('Intercept')

fig.colorbar(surf, shrink=0.5, aspect=5)

filename = "IMGS/surface_loss.png"
plt.savefig(filename)
plt.show()

# Plot contour
cp = plt.contour(X_grid, Y_grid, np.sqrt(Z), colors='black', linestyles='dashed', linewidths=1, alpha=0.5)
plt.clabel(cp, inline=1, fontsize=10)
cp = plt.contourf(X_grid, Y_grid, np.sqrt(Z))
plt.scatter([b0], [b1], s=100, c='white', linewidth=0.5)
plt.ylabel('Slope')
plt.xlabel('Intercept')
plt.xlim(x_min, x_max)
plt.ylim(y_min, y_max)

filename = "IMGS/countour_loss.png"
plt.savefig(filename)
plt.show()

下一段代码定义了函数,这样我们就可以使用 Pytorch 解决 OLS 问题。在这里,使用 Pytroch 有点过了,但好处是我们可以使用预编码的最小化算法( torch.optim ):

def loss_OLS(model, y, X): 
    """
    Loss function for OLS
    """
    R_squared = torch.square(y.unsqueeze(1) - model(X[:,1].unsqueeze(1)))
    return torch.mean(R_squared)

def set_initial_values(model, w, b):
    """
    Function to set the weight and bias to certain values
    """
    with torch.no_grad():
        for name, param in model.named_parameters():
            if 'linear_relu_stack.0.weight' in name:
                param.copy_(torch.tensor([w]))
            elif 'linear_relu_stack.0.bias' in name:
                param.copy_(torch.tensor([b]))

def create_optimizer(model, optimizer_name, lr, momentum):
    """
    Function to define an optimizer
    """
    if optimizer_name == "Adam":
        optimizer = torch.optim.Adam(model.parameters(), lr) 
    elif optimizer_name == "SGD":
        optimizer = torch.optim.SGD(model.parameters(), lr)
    elif optimizer_name == "SGD-momentum":
        optimizer = torch.optim.SGD(model.parameters(), lr, momentum)
    elif optimizer_name == "Adadelta":
        optimizer = torch.optim.Adadelta(model.parameters(), lr)
    elif optimizer_name == "RMSprop":
        optimizer = torch.optim.RMSprop(model.parameters(), lr)
    else:
        raise("optimizer unknown")
    return optimizer

def train_model(optimizer_name, initial_guess, true_value, lr, momentum):
    """
    Function to train a model
    """
    # initialize a model
    model = NeuralNetwork().to(device)
    #print(model)

    set_initial_values(model, initial_guess[0], initial_guess[1])

    for name, param in model.named_parameters():
        print(name, param)

    model.train()

    nb_epochs = 100
    use_scheduler = False
    freq_scheduler = 100
    freq_gamma = 0.95
    true_b = torch.tensor([true_value[0], true_value[1]])

    print(optimizer_name)
    optimizer = create_optimizer(model, optimizer_name, lr, momentum)

    # A LOOP OVER EACH POINT OF THE CURRENT GRID
    # store mean loss by epoch
    scheduler = torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma=freq_gamma)
    loss_epochs = torch.zeros(nb_epochs)
    list_perc_abs_error = [] #store abs value percentage error
    list_perc_abs_error_i = [] #store index i
    list_perc_abs_error_loss = [] #store loss
    list_norm_gradient = [] #store norm of gradient
    list_gradient = [] #store the gradient itself
    list_beta = [] #store parameters

    calculate_variance_grad = False 

    freq_loss = 1
    freq_display = 10

    for i in tqdm(range(0, nb_epochs)):

        optimizer.zero_grad()

        # Calculate the loss
        loss = loss_OLS(model, y_torch, X_torch)
        loss_epochs[[i]] = float(loss.item())

        # Store the loss
        with torch.no_grad():
            # Extract weight and bias
            b_current = np.array([k.item() for k in model.parameters()])
            b_current_ordered = np.array((b_current[1], b_current[0])) #reorder (bias, weight)
        list_beta.append(b_current_ordered)
        perc_abs_error = np.sum(np.square(b_current_ordered - true_b.detach().numpy()))
        list_perc_abs_error.append(np.median(perc_abs_error))
        list_perc_abs_error_i.append(i)
        list_perc_abs_error_loss.append(float(loss.item()))

        # Calculate the gradient
        loss.backward()

        # Store the gradient
        with torch.no_grad():
            grad = np.zeros(2)
            for (index_p, p) in enumerate(model.parameters()):
                grad[index_p] = p.grad.detach().data
            #reorder (bias, weight)
            grad_ordered = np.array((grad[1], grad[0]))
            list_gradient.append(grad_ordered)

        # Take a gradient steps
        optimizer.step()

        if i % freq_display == 0: #Monitor the loss
            loss, current = float(loss.item()), i
            print(f"loss: {loss:>7f}, percentage abs. error {list_perc_abs_error[-1]:>7f}, [{current:>5d}/{nb_epochs:>5d}]")
        if (i % freq_scheduler == 0) & (i != 0) & (use_scheduler == True):
            scheduler.step()
            print("i : {}. Decreasing learning rate: {}".format(i, scheduler.get_last_lr()))

    return model, list_beta, list_gradient 

def create_gif(filenames, output_name):
    """
    Function to create a gif, using a list of images
    """
    with io.get_writer(output_name, mode='I') as writer:
        for filename in filenames:
            image = io.imread(filename)
            writer.append_data(image)

    # Remove files, except the final one
    for index_file, filename in enumerate(set(filenames)):
        if index_file < len(filenames) - 1:
            os.remove(filename)

# Define a neural network with a single node  
# Get cpu or gpu device for training.
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Using {device} device")

nb_nodes = 1
# Define model
class NeuralNetwork(nn.Module):
    def __init__(self):
        super(NeuralNetwork, self).__init__()
        self.flatten = nn.Flatten()
        self.linear_relu_stack = nn.Sequential(
            nn.Linear(1, nb_nodes)
        )

    def forward(self, x):
        out = self.linear_relu_stack(x)
        return out

使用梯度下降的最小化;

lr = 0.10 #learning rate
alpha = lr
init = (9.0, 2.0) #initial guess
true_value = [-2.0, 2.0] #true value for parameters

# I. Solve
optimizer_name = "SGD"
momentum = 0.0
model_SGD, list_beta_SGD, list_gradient_SGD = train_model(optimizer_name , init, true_value, lr, momentum)

# II. Create gif
filenames = []
zoom=1 #to increase/decrease the length of vectors on the plot
max_index_plot = 30 #when to stop plotting

# Plot contour
cp = plt.contour(X_grid, Y_grid, np.sqrt(Z), colors='black', linestyles='dashed', linewidths=1, alpha=0.5)
plt.clabel(cp, inline=1, fontsize=10)
cp = plt.contourf(X_grid, Y_grid, np.sqrt(Z))

# Add points and arrows
for (index, (bb, grad)) in enumerate(zip(list_beta_SGD, list_gradient_SGD)):
    if index>max_index_plot:
        break
    if index == 0:
        label_1 = "SGD"
    else:
        label_1 = ""
    # Point
    plt.scatter([bb[0]], [bb[1]], s=10, c='white', linewidth=5.0, label=label_1)
    # Arrows
    plt.arrow(bb[0], bb[1], - zoom * alpha* grad[0], - zoom * alpha * grad[1], color='white')
    # Add arrows for gradient:
    # create file name and append it to a list
    filename = "IMGS/path_SGD_{}.png".format(index)
    filenames.append(filename)
    plt.xlabel('cst')
    plt.ylabel('slope')
    plt.legend()
    plt.savefig(filename)

filename = "IMGS/path_SGD.png"
plt.savefig(filename)
create_gif(filenames, "SGD.gif")
plt.show()

利用动量梯度下降的最小化;

optimizer_name = "SGD-momentum"
momentum = 0.2

# I. Solve
model_momentum, list_beta_momentum, list_gradient_momentum = train_model(optimizer_name , init, true_value, lr, momentum)

# II. Create gif
filenames = []
zoom=1 #to increase/decrease the length of vectors on the plot
max_index_plot = 30 #when to stop plotting

# Plot contour
cp = plt.contour(X_grid, Y_grid, np.sqrt(Z), colors='black', linestyles='dashed', linewidths=1, alpha=0.5)
plt.clabel(cp, inline=1, fontsize=10)
cp = plt.contourf(X_grid, Y_grid, np.sqrt(Z))

# Add points and arrows
for (index, (bb, grad, bb_momentum, grad_momentum)) in enumerate(zip(list_beta_SGD, list_gradient_SGD, list_beta_momentum, list_gradient_momentum)):
    if index>max_index_plot:
        break
    if index == 0:
        label_1 = "SGD"
        label_2 = "SGD-momentum"
    else:
        label_1 = ""
        label_2 = ""
    # Point
    plt.scatter([bb[0]], [bb[1]], s=10, c='white', linewidth=5.0, label=label_1)
    plt.scatter([bb_momentum[0]], [bb_momentum[1]], s=10, c='blue', linewidth=5.0, alpha=0.5, label=label_2)
    # Arrows
    #plt.arrow(bb_momentum[0], bb_momentum[1], - zoom * alpha* grad[0], - zoom * alpha * grad[1], color='white')
    plt.arrow(bb_momentum[0], bb_momentum[1], - zoom * alpha* grad_momentum[0], - zoom * alpha * grad_momentum[1], color="blue")
    # create file name and append it to a list
    filename = "IMGS/path_SGD_momentum_{}.png".format(index)
    filenames.append(filename)
    plt.xlabel('cst')
    plt.ylabel('slope')
    plt.legend()
    plt.savefig(filename)

filename = "IMGS/path_SGD_momentum.png"
plt.savefig(filename)
create_gif(filenames, "SGD_momentum.gif")
plt.show()

使用 RMSprop 最小化:

optimizer_name = "RMSprop"
momentum = 0.0
# I. Solve
model_RMSprop, list_beta_RMSprop, list_gradient_RMSprop = train_model(optimizer_name , init, true_value, lr, momentum)

# II. Create gif
filenames = []
zoom=1 #to increase/decrease the length of vectors on the plot
max_index_plot = 30 #when to stop plotting

# Plot contour
cp = plt.contour(X_grid, Y_grid, np.sqrt(Z), colors='black', linestyles='dashed', linewidths=1, alpha=0.5)
plt.clabel(cp, inline=1, fontsize=10)
cp = plt.contourf(X_grid, Y_grid, np.sqrt(Z))

# Add points and arrows
for (index, (bb, grad, bb_RMSprop, grad_RMSprop)) in enumerate(zip(list_beta_SGD, list_gradient_SGD, list_beta_RMSprop, list_gradient_RMSprop)):
    if index>max_index_plot:
        break
    if index == 0:
        label_1 = "SGD"
        label_2 = "RMSprop"
    else:
        label_1 = ""
        label_2 = ""
    # Point
    plt.scatter([bb[0]], [bb[1]], s=10, c='white', linewidth=5.0, label=label_1)
    plt.scatter([bb_RMSprop[0]], [bb_RMSprop[1]], s=10, c='blue', linewidth=5.0, alpha=0.5, label=label_2)
    # Arrows
    plt.arrow(bb_RMSprop[0], bb_RMSprop[1], - zoom * alpha* grad_RMSprop[0], - zoom * alpha * grad_RMSprop[1], color="blue")
    # create file name and append it to a list
    filename = "IMGS/path_RMSprop_{}.png".format(index)
    filenames.append(filename)
    plt.xlabel('cst')
    plt.ylabel('slope')
    plt.legend()
    plt.savefig(filename)

filename = "IMGS/path_RMSprop.png"
plt.savefig(filename)
create_gif(filenames, "RMSprop.gif")
plt.show()

使用 Adam 的最小化:

optimizer_name = "Adam"
momentum = 0.0

# I. Solve
model_Adam, list_beta_Adam, list_gradient_Adam = train_model(optimizer_name , init, true_value, lr, momentum)

# II. Create gif
filenames = []
zoom=1 #to increase/decrease the length of vectors on the plot
max_index_plot = 30 #when to stop plotting

# Plot contour
cp = plt.contour(X_grid, Y_grid, np.sqrt(Z), colors='black', linestyles='dashed', linewidths=1, alpha=0.5)
plt.clabel(cp, inline=1, fontsize=10)
cp = plt.contourf(X_grid, Y_grid, np.sqrt(Z))

# Add points and arrows
for (index, (bb, grad, bb_Adam, grad_Adam)) in enumerate(zip(list_beta_SGD, list_gradient_SGD, list_beta_Adam, list_gradient_Adam)):
    if index>max_index_plot:
        break
    if index == 0:
        label_1 = "SGD"
        label_2 = "Adam"
    else:
        label_1 = ""
        label_2 = ""
    # Point
    plt.scatter([bb[0]], [bb[1]], s=10, c='white', linewidth=5.0, label=label_1)
    plt.scatter([bb_Adam[0]], [bb_Adam[1]], s=10, c='blue', linewidth=5.0, alpha=0.5, label=label_2)
    # Arrows
    plt.arrow(bb_Adam[0], bb_Adam[1], - zoom * alpha* grad_Adam[0], - zoom * alpha * grad_Adam[1], color="blue")
    # create file name and append it to a list
    filename = "IMGS/path_Adam_{}.png".format(index)
    filenames.append(filename)
    plt.xlabel('cst')
    plt.ylabel('slope')
    plt.legend()
    plt.savefig(filename)

filename = "IMGS/path_Adam.png"
plt.savefig(filename)
create_gif(filenames, "Adam.gif")
plt.show()

用四条轨迹创造“主情节”:

max_iter = 100
filenames = []
cp = plt.contour(X_grid, Y_grid, np.sqrt(Z), colors='black', linestyles='dashed', linewidths=1, alpha=0.5)
plt.clabel(cp, inline=1, fontsize=10)
cp = plt.contourf(X_grid, Y_grid, np.sqrt(Z))
colors = ["white", "blue", "green", "red"]

# Add points:
for (index, (bb_SGD, bb_momentum, bb_RMSprop, bb_Adam)) in enumerate(zip(list_beta_SGD, list_beta_momentum, list_beta_RMSprop, list_beta_Adam)):
    if index % freq_plot == 0:
        if index == 0:
            label_1 = "SGD"
            label_2 = "SGD-momentum"
            label_3 = "RMSprop"
            label_4 = "Adam"
        else:
            label_1, label_2, label_3, label_4 = "", "", "", ""
        plt.scatter([bb_SGD[0]], [bb_SGD[1]], s=10, linewidth=5.0, label=label_1, color=colors[0])
        plt.scatter([bb_momentum[0]], [bb_momentum[1]], s=10, linewidth=5.0, alpha=0.5, label=label_2, color=colors[1])
        plt.scatter([bb_RMSprop[0]], [bb_RMSprop[1]], s=10, linewidth=5.0, alpha=0.5, label=label_3, color=colors[2])
        plt.scatter([bb_Adam[0]], [bb_Adam[1]], s=10, linewidth=5.0, alpha=0.5, label=label_4, color=colors[3])
    if index > max_iter:
        break
    # create file name and append it to a list
    filename = "IMGS/img_{}.png".format(index)
    filenames.append(filename)
    # Add arrows for gradient:
    plt.xlabel('cst')
    plt.ylabel('slope')
    plt.legend()

    # save frame
    plt.savefig(filename)
    #plt.close()# build gif

create_gif(filenames, "compare_optim_algos.gif")

创建 3D“主图”:

max_iter = 100
fig, ax = plt.subplots(subplot_kw={"projection": "3d"})

# Plot the surface.
surf = ax.plot_surface(X_grid, Y_grid, Z, cmap=cm.coolwarm, linewidth=0, antialiased=False, alpha=0.1)
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter('{x:.02f}')
ax.view_init(60, 35)

colors = ["black", "blue", "green", "red"]
x_min = -10
x_max = -x_min
y_min = x_min
y_max = -x_min

# Add points:
for (index, (bb_SGD, bb_momentum, bb_RMSprop, bb_Adam)) in enumerate(zip(list_beta_SGD, list_beta_momentum, list_beta_RMSprop, list_beta_Adam)):
    if index == 0:
        label_1 = "SGD"
        label_2 = "SGD-momentum"
        label_3 = "RMSprop"
        label_4 = "Adam"
    else:
        label_1, label_2, label_3, label_4 = "", "", "", ""
    ax.scatter([bb_SGD[0]], [bb_SGD[1]], s=100, linewidth=5.0, label=label_1, color=colors[0])
    ax.scatter([bb_momentum[0]], [bb_momentum[1]], s=100, linewidth=5.0, alpha=0.5, label=label_2, color=colors[1])
    ax.scatter([bb_RMSprop[0]], [bb_RMSprop[1]], s=100, linewidth=5.0, alpha=0.5, label=label_3, color=colors[2])
    ax.scatter([bb_Adam[0]], [bb_Adam[1]], s=100, linewidth=5.0, alpha=0.5, label=label_4, color=colors[3])
    if index > max_iter:
        break
    # create file name and append it to a list
    filename = "IMGS/img_{}.png".format(index)
    filenames.append(filename)
    # Add arrows for gradient:
    plt.xlim(x_min, x_max)
    plt.ylim(y_min, y_max)
    plt.ylabel('Slope')
    plt.xlabel('Intercept')
    plt.legend()
    # save frame
    plt.savefig(filename)

filename = "IMGS/surface_loss.png"
plt.savefig(filename)
plt.show()

create_gif(filenames, "surface_compare_optim_algos.gif")

参考

  • 鲁德,塞巴斯蒂安。"梯度下降优化算法概述." arXiv 预印本 arXiv:1609.04747 (2016)
  • 《论深度学*中初始化和动量的重要性》机器学*国际会议。PMLR,2013 年。

关于这个话题的非常好的系列视频:

PyTorch 中学*速率调度程序的可视化指南

原文:https://towardsdatascience.com/a-visual-guide-to-learning-rate-schedulers-in-pytorch-24bbb262c863

Python 深度学*的 LR 衰减和退火策略

作者图片

深度学*中的学*率是多少?

神经网络有许多影响模型性能的超参数。基本超参数之一是学*率(LR),它决定了训练步骤之间模型权重的变化程度。在最简单的情况下,LR 值是 0 和 1 之间的固定值。

然而,选择正确的 LR 值可能具有挑战性。一方面,大的学*率可以帮助算法快速收敛。但它也可能导致算法在最小值附近反弹,而不会达到最小值,或者如果最小值太大,甚至会跳过它。另一方面,一个小的学*率可以更好地收敛到最小值。但是,如果太小,优化器可能需要太长时间才能收敛或者停滞不前。

什么是学*率计划程序?

帮助算法快速收敛到最优的一个解决方案是使用学*率调度器。学*率调度器在训练过程中根据预定义的时间表调整学*率。

帮助算法快速收敛到最优的一个解决方案是使用学*率调度器。

通常,学*率在训练开始时被设置为较高的值,以允许更快的收敛。随着训练的进行,学*率降低,以使收敛到最优,从而导致更好的性能。在训练过程中降低学*率也被称为退火或衰退

不同学*速率调度程序的数量可能会令人不知所措。因此,本文旨在向您概述 PyTorch 中不同的预定义学*率调度程序如何在训练期间调整学*率:

学*率调度程序

对于本文,我们使用 PyTorch 版本 1.13.0。您可以在 PyTorch 文档中阅读更多关于学*率调度器的详细信息。

import torch

您可以在本文末尾的附录中找到用于可视化 PyTorch 学*率调度程序的 Python 代码。

StepLR

在每经过预定数量的训练步骤后,[StepLR](https://pytorch.org/docs/stable/generated/torch.optim.lr_scheduler.StepLR.html#torch.optim.lr_scheduler.StepLR)将学*率降低一个倍数。

from torch.optim.lr_scheduler import StepLR

scheduler = StepLR(optimizer, 
                   step_size = 4, # Period of learning rate decay
                   gamma = 0.5) # Multiplicative factor of learning rate decay

PyTorch 学*率调度器StepLR (图片由作者提供)

多步骤

[MultiStepLR](https://pytorch.org/docs/stable/generated/torch.optim.lr_scheduler.MultiStepLR.html#torch.optim.lr_scheduler.MultiStepLR)——类似于[StepLR](https://pytorch.org/docs/stable/generated/torch.optim.lr_scheduler.StepLR.html#torch.optim.lr_scheduler.StepLR)——也以倍增因子降低学*率,但在每个预定义的里程碑之后。

from torch.optim.lr_scheduler import MultiStepLR

scheduler = MultiStepLR(optimizer, 
                        milestones=[8, 24, 28], # List of epoch indices
                        gamma =0.5) # Multiplicative factor of learning rate decay

PyTorch 学*率调度器MultiStepLR (图片由作者提供)

ConstantLR

[ConstantLR](https://pytorch.org/docs/stable/generated/torch.optim.lr_scheduler.ConstantLR.html#torch.optim.lr_scheduler.ConstantLR)以倍增系数降低学*率,直到训练步数达到预定义的里程碑。

from torch.optim.lr_scheduler import ConstantLR

scheduler = ConstantLR(optimizer, 
                       factor = 0.5, # The number we multiply learning rate until the milestone.
                       total_iters = 8) # The number of steps that the scheduler decays the learning rate

PyTorch 学*率调度器ConstantLR (图片由作者提供)

正如你可能已经注意到的,如果你的起始因子小于 1,这个学*率计划程序会在训练过程中增加学*率,而不是减少。

线性 LR

[ConstantLR](https://pytorch.org/docs/stable/generated/torch.optim.lr_scheduler.ConstantLR.html#torch.optim.lr_scheduler.ConstantLR)类似,[LinearLR](https://pytorch.org/docs/stable/generated/torch.optim.lr_scheduler.LinearLR.html#torch.optim.lr_scheduler.LinearLR)也在训练开始时以倍增系数降低学*率。但是它在限定数量的训练步骤上线性地增加学*速率,直到它达到它最初设置的学*速率。

from torch.optim.lr_scheduler import LinearLR

scheduler = LinearLR(optimizer, 
                     start_factor = 0.5, # The number we multiply learning rate in the first epoch
                     total_iters = 8) # The number of iterations that multiplicative factor reaches to 1

PyTorch 学*率调度器LinearLR (图片由作者提供)

如果你的起始因子小于 1,这个学*率计划程序还会在训练过程中提高学*率,而不是降低它。

指数 LR

在每个训练步骤中,[ExponentialLR](https://pytorch.org/docs/stable/generated/torch.optim.lr_scheduler.ExponentialLR.html#torch.optim.lr_scheduler.ExponentialLR)以倍增系数降低学*率。

from torch.optim.lr_scheduler import ExponentialLR

scheduler = ExponentialLR(optimizer, 
                          gamma = 0.5) # Multiplicative factor of learning rate decay.

PyTorch 学*率调度器ExponentialLR (图片由作者提供)

多项式 lLR

[PolynomialLR](https://pytorch.org/docs/stable/generated/torch.optim.lr_scheduler.PolynomialLR.html#torch.optim.lr_scheduler.PolynomialLR)通过使用一个多项式函数来定义步数,从而降低学*率。

from torch.optim.lr_scheduler import PolynomialLR

scheduler = PolynomialLR(optimizer, 
                         total_iters = 8, # The number of steps that the scheduler decays the learning rate.
                         power = 1) # The power of the polynomial.

下面你可以看到power = 1的学*率下降。

PyTorch 学*率调度器PolynomialLR with Power = 1 (图片由作者提供)

使用power = 2得到的学*率衰减将如下所示。

PyTorch 学*率调度器PolynomialLR with Power = 2 (图片由作者提供)

CosineAnnealingLR

[CosineAnnealingLR](https://pytorch.org/docs/stable/generated/torch.optim.lr_scheduler.CosineAnnealingLR.html#torch.optim.lr_scheduler.CosineAnnealingLR)通过余弦函数降低学*率。

虽然您可以从技术上安排学*率调整遵循多个周期,但想法是在最大迭代次数的半个周期内衰减学*率。

from torch.optim.lr_scheduler import CosineAnnealingLR

scheduler = CosineAnnealingLR(optimizer,
                              T_max = 32, # Maximum number of iterations.
                             eta_min = 1e-4) # Minimum learning rate.

PyTorch 学*率调度器CosineAnnealingLR (图片由作者提供)

两位 Kaggle 竞赛大师 Philipp Singer 和 Yauhen Babakhin 推荐使用余弦衰减作为深度迁移学*的学*速率调度器[2]。

CosineAnnealingWarmRestartsLR

[CosineAnnealingWarmRestarts](https://pytorch.org/docs/stable/generated/torch.optim.lr_scheduler.CosineAnnealingWarmRestarts.html#torch.optim.lr_scheduler.CosineAnnealingWarmRestarts)类似于余弦退火程序。但是,它允许您使用初始 LR 在每个时期重新启动 LR 计划。

from torch.optim.lr_scheduler import CosineAnnealingWarmRestarts
scheduler = CosineAnnealingWarmRestarts(optimizer, 
                                        T_0 = 8,# Number of iterations for the first restart
                                        T_mult = 1, # A factor increases TiTi​ after a restart
                                        eta_min = 1e-4) # Minimum learning rate

PyTorch 学*率调度器CosineAnnealingWarmRestarts (图片由作者提供)

这被称为热重启,于 2017 年推出[1]。增加 LR 会导致模型发散。然而,这种有意的发散使得模型能够避开局部极小值并找到更好的全局极小值。

CyclicLR

[CyclicLR](https://pytorch.org/docs/stable/generated/torch.optim.lr_scheduler.CyclicLR.html#torch.optim.lr_scheduler.CyclicLR)根据循环学*率策略调整学*率,该策略基于我们在上一节刚刚讨论过的热重启概念。PyTorch 中有三个内置策略。

from torch.optim.lr_scheduler import CyclicLR

scheduler = CyclicLR(optimizer, 
                     base_lr = 0.0001, # Initial learning rate which is the lower boundary in the cycle for each parameter group
                     max_lr = 1e-3, # Upper learning rate boundaries in the cycle for each parameter group
                     step_size_up = 4, # Number of training iterations in the increasing half of a cycle
                     mode = "triangular") 

使用mode = "triangular",得到的学*率衰减将遵循基本的三角周期,没有幅度缩放,如下所示。

PyTorch 学*率调度器CyclicLR with mode = 'triangular' (图片由作者提供)

使用mode = "triangular2",最终的学*率衰减将遵循一个基本的三角周期,在每个周期将初始振幅减半,如下所示。

PyTorch 学*率调度器CyclicLR with mode = 'triangular2' (图片由作者提供)

使用mode = "exp_range"得到的学*率衰减将如下所示。

PyTorch 学*率调度器CyclicLR with mode = 'exp_range' (图片由作者提供)

OneCycleLR

[OneCycleLR](https://pytorch.org/docs/stable/generated/torch.optim.lr_scheduler.OneCycleLR.html#torch.optim.lr_scheduler.OneCycleLR)根据 1cycle 学*率策略降低学*率,该策略在 2017 年的一篇论文中介绍过[3]。

与许多其他学*率调度器相比,学*率不仅在训练过程中降低。相反,学*率从初始学*率增加到某个最大学*率,然后再次降低。

from torch.optim.lr_scheduler import OneCycleLR

scheduler = OneCycleLR(optimizer, 
                       max_lr = 1e-3, # Upper learning rate boundaries in the cycle for each parameter group
                       steps_per_epoch = 8, # The number of steps per epoch to train for.
                       epochs = 4, # The number of epochs to train for.
                       anneal_strategy = 'cos') # Specifies the annealing strategy

使用anneal_strategy = "cos"得到的学*率衰减将如下所示。

PyTorch 学*率调度器OneCycleLR with anneal_strategy = 'cos '(图片由作者提供)

使用anneal_strategy = "linear"得到的学*率衰减将如下所示。

PyTorch 学*率调度器OneCycleLR with anneal_strategy = 'linear '(图片由作者提供)

reducelronplateaaulr

当指标停止改善时,[ReduceLROnPlateau](https://pytorch.org/docs/stable/generated/torch.optim.lr_scheduler.ReduceLROnPlateau.html#torch.optim.lr_scheduler.ReduceLROnPlateau)会降低学*率。正如您所猜测的,这很难可视化,因为学*率降低的时间取决于您的模型、数据和超参数。

带有 Lambda 函数的定制学*率调度程序

如果内置的学*率调度程序不能满足你的需要,你可以定义一个带有 lambda 函数的调度程序。lambda 函数是一个基于纪元值返回乘法因子的函数。

[LambdaLR](https://pytorch.org/docs/stable/generated/torch.optim.lr_scheduler.LambdaLR.html#torch.optim.lr_scheduler.LambdaLR)通过将来自λ函数的乘法因子应用于初始 LR 来调整学*率。

lr_epoch[t] = lr_initial * lambda(epoch)

另一方面,[MultiplicativeLR](https://pytorch.org/docs/stable/generated/torch.optim.lr_scheduler.MultiplicativeLR.html#torch.optim.lr_scheduler.MultiplicativeLR)通过将来自 lambda 函数的乘法因子应用于前一时期的 LR 来调整学*率。

lr_epoch[t] = lr_epoch[t-1] * lambda(epoch)

这些学*率调度器也有点难以可视化,因为它们高度依赖于定义的 lambda 函数。

结论和可视备忘单

现在你已经看到了各种不同的内置 PyTorch 学*速率调度器,你可能很好奇你应该为你的深度学*项目选择哪种学*速率调度器。

不幸的是,答案并不那么容易——在生活中经常如此。有一段时间,[ReduceLROnPlateau](https://pytorch.org/docs/stable/generated/torch.optim.lr_scheduler.ReduceLROnPlateau.html#torch.optim.lr_scheduler.ReduceLROnPlateau)是一个流行的学*率调度器。如今,像[CosineAnnealingLR](https://pytorch.org/docs/stable/generated/torch.optim.lr_scheduler.CosineAnnealingLR.html#torch.optim.lr_scheduler.CosineAnnealingLR)[OneCycleLR](https://pytorch.org/docs/stable/generated/torch.optim.lr_scheduler.OneCycleLR.html#torch.optim.lr_scheduler.OneCycleLR)这样的方法或者像[CosineAnnealingWarmRestarts](https://pytorch.org/docs/stable/generated/torch.optim.lr_scheduler.CosineAnnealingWarmRestarts.html#torch.optim.lr_scheduler.CosineAnnealingWarmRestarts)[CyclicLR](https://pytorch.org/docs/stable/generated/torch.optim.lr_scheduler.CyclicLR.html#torch.optim.lr_scheduler.CyclicLR)这样的热重启方法越来越受欢迎。

尽管如此,您可能需要运行一些实验来确定哪种学*速率调度程序最适合您的问题。但是,我们可以说的是,使用任何学*调度程序最有可能导致更好的模型性能。

下面是 PyTorch 中所讨论的学*率调度器的可视化总结。

PyTorch 中学*率调度器的备忘单(图片由作者提供)

喜欢这个故事吗?

如果你想把我的新故事直接发到你的收件箱, 订阅

成为媒介会员,阅读更多其他作家和我的故事。报名时可以用我的 推荐链接 支持我。我将收取佣金,不需要你额外付费。

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

TwitterLinkedInKaggle**

参考

[1] Loshchilov,I .,& Hutter,F. (2016)。Sgdr:带有热重启的随机梯度下降。arXiv 预印本 arXiv:1608.03983 。

[2] Singer,P. & Babakhin,Y. (2022) 深度迁移学*的实用技巧。2022 年巴黎卡格勒日。

[3]纽约州史密斯和托*(2019 年)。超收敛:使用大学*率非常快速地训练神经网络。在面向多领域运算应用的人工智能和机器学*(第 11006 卷,第 369–386 页)。SPIE。

附录

下面是我用来可视化学*率调度程序的代码:

**import torch
from torch.optim.lr_scheduler import StepLR # Import your choice of scheduler here

import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator

LEARNING_RATE = 1e-3
EPOCHS = 4
STEPS_IN_EPOCH = 8

# Set model and optimizer
model = torch.nn.Linear(2, 1)
optimizer = torch.optim.SGD(model.parameters(), lr=LEARNING_RATE)

# Define your scheduler here as described above
# ...

# Get learning rates as each training step
learning_rates = []

for i in range(EPOCHS*STEPS_IN_EPOCH):
    optimizer.step()
    learning_rates.append(optimizer.param_groups[0]["lr"])
    scheduler.step()

# Visualize learinig rate scheduler
fig, ax = plt.subplots(1,1, figsize=(10,5))
ax.plot(range(EPOCHS*STEPS_IN_EPOCH), 
        learning_rates,
        marker='o', 
        color='black')
ax.set_xlim([0, EPOCHS*STEPS_IN_EPOCH])
ax.set_ylim([0, LEARNING_RATE + 0.0001])
ax.set_xlabel('Steps')
ax.set_ylabel('Learning Rate')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.xaxis.set_major_locator(MultipleLocator(STEPS_IN_EPOCH))
ax.xaxis.set_minor_locator(MultipleLocator(1))
plt.show()**

SQL 日期/时间函数的可视化摘要

原文:https://towardsdatascience.com/a-visual-summary-of-sql-date-time-functions-8bb96ce4f1b4

准备 SQL 面试?

阿格巴洛斯Unsplash 上拍摄的照片

在时间戳、日期和时间数据类型之间,SQL 日期/时间函数可能很容易混淆。在这篇博客中,我将尝试使用 PostgreSQL 语法绘制出 SQL 访谈中常*的数据/时间命令。

在 SQL 代码之前

在我们开始编码之前,让我们先暂停一下,考虑一下日期/时间表示中的元素。我们知道时间是线性的,单向的,并且在数学上可以用向量来表示。

作者图片

时间向量 t 上的两个关键元素是时刻持续时间。这些术语可能不是最准确的,但是由于 SQL 使用了关键字时间戳间隔,现在让我们使用不同的词语来理解这个概念。

  • 瞬间指事件发生的瞬间。力矩是瞬时的,所以用向量 t 上的点来表示,t1 和 t2 是力矩。
  • 持续时间是指两个时刻之间的时间跨度。持续时间由无数个瞬间组成,有开始也有结束。

所以,我们真的只需要了解这两个元素,以及这两个元素之间的转换,就能掌握 SQL 中的日期/时间函数。

Moment & Moment 家庭

时间戳给了我们最多的信息。时间戳可以精确到毫秒,并且包含时区信息,但是大多数时候,YYYY-MM-DD HH:MM:SS 格式的时间就足够了。

作者图片

时间戳可以分成两部分,日期时间,通过将时间戳转换成日期时间对象(简写:😃。但是,将日期或时间转换回时间戳是不可取的,因为您将丢失时间戳中一半的信息或者 SQL 将抛出一个错误。

从一个时间戳中可以提取很多信息,比如年、月、日、时、分、秒等。然而,并不是所有的信息都可以单独从日期时间对象中提取。例如,您不能从时间 01:50:39 提取年份。

以下是 PostgreSQL 代码中的几个示例:

创造时刻

通常情况下,在 SQL 面试问题中会给你一点时间。例如,它可以是用户的登录时间、用户向另一个用户发送消息的时刻,或者客户下订单的时刻。但是,这并不能保证。有时候,你只需要创造属于你的时刻。

作者图片

现在 : 99%的时候,我们需要利用现在的时刻进行一些计算。CURRENT_TIMESTAMPNOW()给你当前时刻完全相同的时间戳。上图展示了更多的变化。请注意,没有所谓的LOCALDATE

定制时刻:很少会遇到需要定制特定时刻的情况,但如果你这样做了,MAKE_TIMESTAMP就会做到。上图展示了更多的变化。

从一瞬间到另一瞬间

DATE_TRUNC将一个时刻转换成另一个时刻。它的工作原理类似于一个下限函数,将时间戳重置为时间戳的年/月/周/日/小时/…的开始。

作者图片

您可以向函数DATE_TRUNC输入日期,而不是时间戳,它将通过用零填充未知时间来输出结果。但是,输入一个时间会抛出一个错误。

持续时间

现在,我们来谈谈持续时间。持续时间对应 PostgreSQL 中的区间,以' 20 年 11 个月 6 天'的格式表示。

作者图片

我们可以再次借用函数EXTRACTDATE_PART得到具体的年/月/日/小时/分钟/秒/…的间隔。AGE功能给了我们一个更全面的视角。请注意,如果只给AGE函数一个输入,它会自动将输入与当前时间戳进行比较,但输出的精度会与您的输入保持一致。

把瞬间和间隔放在一起

知道了timestamp2-timestamp1=interval,只要知道方程的两个元素,就可以计算第三个。因此,我们可以使用时间戳和间隔来获取其他时间戳。

作者图片

感谢您的阅读!希望这篇博客对你有所帮助。

对偏差和方差的直观理解

原文:https://towardsdatascience.com/a-visual-understanding-of-bias-and-variance-66179f16be32

为这两个概念开发更深层次直觉的指南

乔·马尔多纳多在 Unsplash 上的照片

B 当谈到统计建模时,ias 和方差是两个最基本的术语,机器学*也是如此。然而,在机器学*社区中对偏差和方差的理解有些模糊,部分是因为许多关于该主题的现有文章试图产生速记类比(“偏差”=“欠拟合”,“方差”=“过拟合”,牛眼图)。如果你想快速描述一个模型的性能(“模型具有高偏差和低方差”),这些类比是很好的,但我发现它们去除了偏差-方差权衡的潜在美感和具体性。我希望通过这篇文章,读者可以对统计建模中的偏差和方差有更深的理解。我也希望他们能把偏差和方差应用到其他情况。

统计建模

B ias 和方差来源于统计学*领域。统计学*是一个试图在收集的数据上建立模型的领域,以便(1)它们可以被预测或者(2)它们可以被理解。

举例 :非常流行的 波士顿房屋数据集 是美国人口普查局在 1996 年收集的数据集。它包含多个变量,如人均犯罪率、每个住宅的房间数量、非零售企业的比例和价格值。

如果你想建立一个房价模型,你可以设置其他变量作为模型的预测变量,而房价作为响应变量。如果有 p 个不同的预测因子 X1X 2、…、 Xp 和一个响应变量 Y ,那么我们可以假设一个 Y 使用 X 的模型为:

在这个等式中,注意除了固定的函数 f ( X )之外,等式中还有另一项 ϵ 。这是误差项。这一项是模拟值和实际值之间的差异,可以表示噪声或随机过程等。主要的要点是, ϵ 既独立于 X ,又具有为零的*均值。

在现实世界中,如果我们着手对这些数据进行建模,我们可能无法访问所有的数据点(所有数据点的集合被称为“总体”)。相反,我们只能访问选定数量的数据点(这称为“样本”)。这里,我们有一个 50 个数据点的样本。这将与我们对方差的讨论相关,因为同一总体的多次抽样将产生略有不同的估计模型。

为了使模型适合这个数据集,最好从尽可能简单的开始,然后逐渐变得复杂。这里,我将使用一个以 n^th 幂为最高幂的多项式模型,从 n =1(线性回归)开始,然后将 n 的值一直增加到 10。所有模型都被拟合以最小化均方误差值。

为了使模型适合这个数据集,最好从尽可能简单的开始,然后逐渐变得复杂。这里,我将使用 n 次多项式模型,从 n =1(线性回归)开始,然后将 n 的值一直增加到 10。所有模型都被拟合以最小化均方误差值。

什么是方差?

现在,让我们进入这篇文章的主要部分:发展对方差和偏差的理解。我们先讲方差,因为它更容易理解。简单来说,并不是所有的样本都一样。当两个样品不同时,我们生产的模型看起来略有不同。

从同一人群中抽取大小为 50 的不同样本。我们用三次多项式来拟合它们。

这里我们说我们改变了模型的参数。上图中,所有模型都是三阶多项式,以 X 为最高次幂。每个模型都是在略有不同的人口样本上训练的。

假设我们重复这个过程 100 次。这是它们的样子。

我们模型的目标是产生预测。使用模型来预测新的 XY 值会产生以下结果:

使用不同建模曲线(红线)对 Y 值(蓝点)的不同预测。灰色虚线是我们用作预测值的 X 值。

一些模型会产生变化很大的预测,但其他一些模型会产生非常一致的预测。我们用方差来量化一致性。从统计学角度来看,模型预测的方差是所有预测的方差的*均值(或期望值)。正如在的《统计学*导论中所说:

一般来说,更灵活的统计方法具有更高的方差。

什么是偏*?

答在我们做出各种各样的预测之后,我们还想考虑这些预测的*均值或期望值是多少。这个*均值被称为所有预测的期望值。偏差是指所有预测的期望值实际值相差多少。

偏差是真实数据(三角形)和预期值(蓝线)之间的“距离”。方差是不同预测的“宽度”(红色带)。

有了这个图,我希望你能理解如何测量偏差和方差,以及如何用它们来描述过度拟合或欠拟合的模型。

  • 在我们的线性回归模型中( n =1),预测值的*均值与实际的 Y 值相差很大。该模型也有广泛的范围。所以我们可以说线性回归模型有高偏差高方差
  • 在使用 n =7 的模型中,预测值的*均值非常接近实际的 Y 值。然而,该模型有非常广泛的范围。我们可以说 n =7 模型有低偏但是高方差
  • 在使用 n =2 和 n =3 的两个模型中,方差和偏差都非常小。统计建模的目标是产生和发现具有低方差和低偏差的模型。

偏差-方差权衡

我们如何知道我们的模型对现实有多“正确”?好吧,我在前面给过你提示。我们可以计算出预测值和实际值的误差,然后相加,取*均值。当然,这就是我们如何得出预测值的偏差。然而,这样做可能会适得其反,因为如果偏差为 0,这可能意味着预测器正确预测了一切(无方差),或者预测器错误地预测了一切,但它们甚至为零(高方差)。相反,我们对误差的绝对值或*方求和。在许多情况下,误差项的*方更为可取,因为在寻找解决方案方面,它更易于实现。我们称之为均方误差(MSE):

如果你以前学过统计学,你会知道这也被称为*方误差的期望值。期望值具有一些可以用来分解 MSE 的属性。你应该仔细阅读这篇博文中的维基百科的详细分解。最后,你应该得到

var ( ϵ ^2)项称为不可约误差。它决定了 MSE 的最小可实现值,进而决定了预测值。

作为练*,在已知误差来自均匀分布[-10,10]的情况下,能否计算出不可约误差值?

从这个分解中,很明显,MSE 是由预测值的和与偏差决定的。如果我们将模型的 MSE、方差和偏差项一起绘制成复杂性增加的曲线,我们将观察到 MSE 的 U 形值。选择一个正确的模型需要选择一个有适当的方差和偏差的模型。

这就是偏差——方差权衡。在这种情况下,MSE 在 n =3 时最低。我们可以说,三阶多项式最好地模拟了实际人口。

问题: 如果我增加训练数据的个数,一个预测器的偏差和方差会发生什么变化?

答案: 直觉地想,你会看到,通过采样更多的数据点,得到的预测模型会更稳定。因此,随着训练数据的增加,预测器将具有较低的方差。然而,偏*将保持不变。这是因为无论样本数量多少,偏差都会向*均值靠拢。实际上,如果用于训练的数据点太少,数据点的数量也会影响偏差,因为更多的数据点会使估计量更适合。

问题: 如果我给自己的模型加一个常数项,偏倚和方差会怎么样?

答案: 方差只是简单的衡量了预测的传播程度。如果我加入一个常数项,利差仍然保持不变,所以方差也保持不变。另一方面,偏差将向常数项的方向变化。

应用程序

到目前为止,我希望你能培养出对偏差和变化的直觉。更具体地说,为什么它们经常被用来描述模型。然而,您可能想知道它们是否只是描述模型的词语,没有实际的理论或实践重要性。在这里,我将指导您将偏差和方差应用于交叉验证。

交互效度分析

ross 验证是评估模型性能的最常用方法之一。通常,为了度量模型性能,您会将数据分为定型集和验证集,使用定型集更新模型参数,然后在验证集上生成评估。但是,如果原始数据集不够大,您可以在原始数据集的不同较小子集上重复训练模型。模型的最终评估将是使用不同验证集的所有评估的组合。通过查看采样过程,您可以立即看到这与预测值的方差方面有什么关系。我们的目标是找到在新的测试值上具有最低 MSE 的模型,那么交叉验证可以做到这一点吗?

首先,让我们考虑留一交叉验证(LOOCV)。在 LOOCV,测试集只有一个样本,而训练集有其余的样本。该模型被重复训练n1 次,其中 n 是数据集中数据点的数量。最终评估是所有培训的*均值。

很快,你就可以注意到 LOOCV 相对于简单的没有交叉验证的训练测试分割的优势。如果现有的数据样本足够好,那么训练集的重复采样与真实人群的重复采样是相似的。然而,有一个小小的警告。当执行 LOOCV 时,所有训练样本将具有非常大的重叠。这种大的重叠会产生模型的高方差。

为了减少差异,可以使用另一种交叉验证方法,称为 k-fold 交叉验证。在 k 重交叉验证中,样本被分成 k 等份。测试集是一部分,训练集是其余部分。该模型被重复训练 k 次,每次用不同的部分进行测试。与 LOOCV 相比,k-fold 验证可以产生具有较低方差的模型,但反过来具有较高的偏差。

对测试数据使用 LOOCV 和 K 倍交叉验证的 MSE 值。

交叉验证在选择最佳模型方面有多好?这里,我们将尝试使用 K 重交叉验证( K =10)来找到最佳多项式幂。LOOCV 产生最佳值 6,K 倍产生最佳值 3。如果我们不希望我们的模型过度拟合训练样本,我们可以使用更简单的模型,其中 n =3。

结论

我希望这篇文章能帮助你更好地理解偏差和方差分解背后的直觉。从现在起,当你考虑模型的偏差和方差时,你将不再需要考虑诸如飞镖靶之类的类比,而是可以直接从基本原理出发。

如果你想玩生成图形的游戏,这是源代码。玩得开心!

除非另有说明,所有图片均为作者所有。所有数据均由作者生成。

参考

詹姆斯·加雷思等人统计学*导论。第 112 卷。纽约:施普林格,2013 年。

数据可视化的工作流

原文:https://towardsdatascience.com/a-workflow-for-data-visualization-c887d57d7ef1

使用这个循序渐进的工作流程创建更有意义的可视化效果

作者图片

最近从编辑那里拿到了这本书 《生物技术和生命科学中的机器学*:使用 Python 构建机器学*模型并部署在云上 来评论并给出我的看法。

虽然这不是一个关于这本书本身的帖子,但我想指出的一点是,内容非常扎实。作者是 Saleh Alkhalifa ,他研究了除生物技术之外的许多概念,如关系数据库、Python、Data Viz、云

引起我注意的一件事是这个关于数据可视化的工作流程。我将在这篇文章中详细介绍每一个步骤,但是请注意每一步的代码和解释都是我的。我只是用 Alkhalifa 的工作流程向你展示一个数据可视化的好例子。有时,步骤中的任务会相互重叠。

获取:从数据源获取数据

了解:了解数据,了解类别和特性

过滤器:清理数据,去除缺失或错误的值

挖掘:识别模式,设计新功能

浓缩:分离出最有意义的特征

代表:选择这些特征的代表

获取数据

显然,好的可视化的第一步是有一些数据要查看,对吗?如果我没有事实,我就不能给你讲故事。

要获取数据,有许多可能,例如 SQL 查询、Excel 或 csv 格式的公司内部报告、来自互联网的数据集、来自政府、组织等。

在这个例子中,我将使用 Python 和 Pandas 来获取数据。数据集是这个关于 2018 年国家互联网用户的数据集来自 Kaggle 。原始资料来自维基百科,使用知识共享署名-相似分享许可 3.0。

# Reading the data from a csv
internet = pd.read_csv(file_path)
internet.head(10)

数据集的头。图片由作者提供。

了解您的数据

这一部分非常重要,因为在这里你将真正开始构思你想讲什么故事,你想向观众展示什么。

理解数据,实际上就是熟悉变量和变量中的内容,也许是绘制一些分布和统计描述。

# Check data types
internet.info() *>> Here we will have to clean some wrong data since the columns Percentage and Rank_pct have some wrong values. This will be shown in the Filter Section*-------
# Check the dataset shape
internet.shape
**[OUT]:** (215, 6)-------
# Check if there are duplicated countries
internet['Country or Area'].duplicated().sum()
**[OUT]:** 0-------
# Variables correlation
internet.corr().round(2).style.background_gradient(cmap='coolwarm')-------
# Statistical Description
internet.describe()

数据集中的相关性。图片由作者提供。

数据集的统计数据。图片由作者提供。

从上面的描述中,我们已经可以发现一些初步的*解:

  • 各国互联网用户的中位数为 250 万人。
  • 我们不会考虑*均数,因为数据中有很大的差异。只看最小值和最大值。同样,很容易看出标准偏差几乎是*均值的 4 倍。因此,差异相当大。
  • 人口遵循这一模式,因为用户和人口都具有 0.96 的强相关性。
  • 2018 年,连接到互联网的人口比例约为全球的 55%。

箱线图。图片由作者提供。

过滤器

过滤器部分是关于清理和切片数据来讲述你的故事。

由于数据集非常小,只有 215 个条目,我们不能根据我们试图创建的可视化删除太多的行。我们来看看这个数据在缺失值方面有多可靠。

# Missing data
internet.isnull().sum()
**[OUT]:** Country or Area    0 
Internet Users     0 
Population         0 
Rank               0 
Percentage         0 
Rank_pct           0 
dtype: int64

很好,没有遗漏信息。我们可以继续分析了。但是,如前所述,我们需要对列 PercentageRank_pct 进行一些清理。我们知道这些列可能有一个非数字的数字,因此它们被强制为字符串。所以让我们使用正则表达式来找到有问题的值。

# import re for regular expressions
import re# Check for non-numeric values
non_number = internet.Percentage.apply(lambda x: re.findall('^[1234567890]*', x) != ['0'])# slice on the problematic values
internet[non_number]

数据不是来自 2018 年的值有一个括号。图片由作者提供。

从这里,我们可以选择删除这些值,或者只删除(XXXX)并使用最新的值。我会选择放弃它们。

# Drop those values
internet.drop(internet[non_number].index, axis=0, inplace=True)# Assign correct value type
internet = internet.astype({'Percentage':float,'Rank_pct': int})

我的

在这一步中,我们将找到绘制数据的最佳模式。

嗯,我们可能在这个数据集中发现的最强模式是人口和互联网用户之间的正相关。因此,人口越多,互联网用户的数量就越多。让我们用图表来看看。

# Plot Internet vs Population size
px.scatter(internet, x= 'Population', y= 'Internet Users')

尽管中国和印度是例外,但这种相关性是强而正的。图片由作者提供。

然而,我们不能说人口越多的国家互联网用户就越多。

# Rank vs Pop Size
px.scatter(internet, x= 'Population', y= 'Percentage',
   size= 'Population', trendline="ols",
   title= "Population vs Percentage of it who are Internet Users", 
   color= 'Internet Users')

弱相关。图片由作者提供。

显然,我们可以做得更多,从其他数据集获取信息,如国家 GDP,并检查国家经济发展与互联网普及率之间的关系。但是为了简单起*,我们在这篇文章中没有这样做。

凝结

Condense now 意味着我们必须审视我们迄今为止所做的工作,并挑选出最佳*解,将它们整合在一起,以便能够在下一部分创建故事。

到目前为止,我们已经加载了数据,理解了数据,删除了丢失的值和错误的条目,然后检查了数据中的一些关系。

在这一步中,我将选择最佳特征以在下一步中创建可视化。

我知道我将使用地图来表示这些数据。由于我们处理的是国家数据,而观测数据不是时间序列,我认为最好的数据呈现方式是在地图上。因此,我将只省去两个排名栏。

代表

让我们绘制这些国家的地图,用互联网渗透率制作一个 choropleth 图层来显示它有多好,然后我们还将绘制气泡图来显示那个国家的人口规模。

下面是代码和结果:

# Import Folium for plot
import folium# Add population in millions column for better plotting
internet['pop_millions'] = internet.Population.div(1_000_000)# Bring lat long by country
lat_long = pd.read_html('[https://developers.google.com/public-data/docs/canonical/countries_csv')[0](https://developers.google.com/public-data/docs/canonical/countries_csv')[0)]
lat_long.reset_index(inplace=True)
# Correct Country names to match
lat_long.name.replace({'Myanmar [Burma]': 'Myanmar',
                       "Côte d'Ivoire": 'Ivory Coast',
                       "Congo [Republic]": 'Republic of the Congo',
                       "Palestinian Territories": 'Palestinian Authority',
                       "Macedonia [FYROM]": 'Macedonia',
                       "Timor-Leste": 'Timor Leste',
                       "Cape Verde": 'Cabo Verde'}, inplace=True)internet['Country or Area'].replace({'South Sudan': 'Sudan',
                                     'Democratic Republic of the Congo': 'Republic of the Congo',
                                      'The Gambia': 'Gambia',
                                     'The Bahamas' : 'Bahamas',
                                     'Micronesia, Federated States of': 'Micronesia'}, inplace=True)# json file for the world map
map_geo = '/content/globe.geo.json'
# Create the base map
m = folium.Map(location=[50, 0], zoom_start=3)# Create Choropleth layer
folium.Choropleth(
    geo_data=map_geo,
    name='choropleth',
    data=internet,
    columns=['Country or Area', 'Percentage'],
    key_on='feature.properties.name',
    fill_color='YlOrRd',
    fill_opacity=0.7,
    line_opacity=0.2,
    legend_name='Internet Users(%)').add_to(m)# Add Bubbles for the size of the country
for country in internet['Country or Area']:
  folium.CircleMarker(location= [ lat_long.query('name == [@country](http://twitter.com/country)')['latitude'].values[0], lat_long.query('name == [@country](http://twitter.com/country)')['longitude'].values[0] ],
                      radius=internet.query('`Country or Area` == [@country](http://twitter.com/country)')['Population'].values[0]/25000000,
                      color='blue',
                      fill=True, 
                      fill_color='red').add_to(m)folium.LayerControl().add_to(m)# View
m

彩色层是使用互联网的人口百分比,气泡是人口规模。图片由作者提供。

一些结论是,人口规模本身并不是互联网渗透率的良好指标。然而,我们看到绿色越深的国家(互联网用户越多)人口越少。我们还可以看到,美洲和欧洲的互联网普及率高于非洲国家和中美洲部分地区。考虑到一些国家人口众多,亚洲正在努力适应中绿色。

在你走之前

创建可视化并不是一件容易事情,但是我确信这个工作流程将帮助你从现在开始在你的头脑中构建这个任务。

请记住,我们必须加载,理解,清理,选择变量和最好的形式来代表你的故事。

如果您对数据有很好的理解,那么创建相关的可视化就会变得更容易。

如果这个内容你感兴趣,关注我。

https://gustavorsantos.medium.com/

参考

叶文档

Git Hub 中的代码和数据集。

零 ETL 的未来

原文:https://towardsdatascience.com/a-zero-etl-future-83c0d377ad95

AWS 和雪花能减少数据重复吗?

照片由seli̇m·阿尔达·埃里希马兹Unsplash 上拍摄

AWS 已经赶上了消除 ETL 需求的潮流。Snowflake 通过其混合表以及与 Salesforce 的合作伙伴关系宣布了这一点。

现在,我对“零 ETL”的命名有点异议。因为从表面上看,所描述的功能通常更接近于零集成的未来,这可能不够“令人兴奋”。这也可能只是 AWS 和雪花计划的第一阶段,以消除对 ETL 的需求。

总的来说,我同意减少存在的重复逻辑和数据的想法。作为一名专业的数据工程师,我确实觉得有时候数据管道会变得过于复杂,而且非常脆弱,这取决于它们对数据生产者的依赖程度。因此,如果有某种形式的途径通向零 ETL 世界,我们应该让它发生。

但是需要什么呢?

在本文中,我将经历一个零 ETL 的未来,以及我们如何实现它。

感知的问题

当我读到或听到这样的公告时,我认为其中有未讨论的细微差别。但我发现,当企业阅读这些类型的公告时,他们会从表面上看。

他们回来告诉他们的团队,我们希望走向无代码、零 ETL 和无服务器的未来。从商业角度来看,这一切听起来都不错:成本将会降低,人员数量可以大幅削减,数据的价值可以立即获得。

但是这将跳过所有其他不可避免的细微差别。

我读过的一篇文章甚至说:

ETL 是每个数据科学家和团队的祸根,因为他们试图让数据成型并投入工作。正如 AWS 首席执行官 Adam Selipsky 解释的那样,您可能在许多不同的地方有数据,如数据库中的应用程序使用数据和数据湖中的客户评论。迄今为止,将它们组合在一起一直是一个巨大的挑战。— 技术危机

这听起来好像通过 AWS 的解决方案,数据科学家的问题将不复存在。是的,如果我们可以创造一个零 ETL 的世界,数据科学家可以简单地从他们想要的任何地方提取数据,而不需要与数据工程师交谈。奇怪的是,他们跳过了数据工程师,只提到了对数据科学家的影响。

但是能做到吗?数据科学家能生活在一个只有数据存在的世界吗?

在深入零 ETL 的未来之前,让我们回顾一下 ETL 存在的一些原因。

我们为什么要 ETL

简单地将数据从 A 点复制到 B 点不是 ETL。如果这就是我们需要做的,我们可以创建复制数据库并报告这些。那么,为什么要创建复杂的系统并使用像气流或提督这样的工具呢?

为什么要聘请昂贵的数据工程师

为什么还要 ETL?

我个人在脸书开始问自己这个问题。我们有 Presto(现在是 Trino) ,它可以从技术上直接从 MySQL 源查询大量数据。我们需要 toETL 吗?

历史数据 —一般来说,大多数可操作的数据库不会跟踪历史数据。具体来说,它们不会跟踪历史上不断变化的实体数据,比如客户住在哪里。

因此,当数据被更新或删除时,如果您没有使用 CDC(变更数据捕获),您将会丢失信息。这就是为什么存在渐变维度的概念,以帮助跟踪信息,确保如果客户搬家或员工跳槽,我们可以随着时间的推移准确地反映出来。

别误会我的意思。除了传统的 SCD(s 低变化维度)之外,您可以做的只是创建一个日期分区,并将数据加载到一个不断扩展的表中。我们在脸书经常这样做,因为这是一个更简单的设计。

但这也让分析师和数据科学家更难查询数据。在很多情况下,我必须构建一个二级表,添加逻辑来跟踪每个日期分区的变化。

因此,最终,从数据模型中移除缓慢变化的维度的概念可能会非常棘手(但也许我们可以自动化它?)

整合数据 —在脸书工作的主要好处之一是数据在应用程序层面的整合程度。有一个实体层,任何人在构建他们的新特性的时候都可以从中提取出来,这意味着在应用程序端和分析端都可以很容易地将实体连接在一起。

当我在脸书工作结束时,我们已经将大部分核心管道缩减到 30-50 行代码,因为这主要只是配置。甚至 SQL 部分也可能被删除。这在很大程度上是由这样一个事实驱动的,即因为实体层得到了很好的开发,我们不需要编写复杂的查询来尝试连接数据。

情况并非总是如此。许多公司都有各种形状和大小的数据,因此几乎不可能跨来源集成数据,或者需要额外的几百行 SQL 才能跨实体连接。

易用性 —从 MongoDB 或 MySQL 等运营数据库中提取的数据通常以分析师难以处理的方式进行组织。你能想象把 MongoDB 的数据文件交给分析师吗?它嵌套很深,容易出错,很难做成任何可用的形状。

同样,来自传统 MySQL 数据库的高度规范化的数据模型也会带来问题。简单地将数据复制到 Redshift 或 Snowflake 将迫使分析师编写需要多个连接和可能的业务逻辑的查询。

同样,容易出错。

对数据所做的许多事情,无论是标准化命名约定还是重塑数据,都是为了让分析师更容易访问数据。不仅仅是把它放入另一个数据库,而是把它当作一个用户可以与之互动的产品。

尽管如此,我确实相信 ETL,至少是创建数据核心层的 ETL,在未来可能会被移除。

这个零 ETL 的未来需要什么?

实体层

如果更多的公司可以构建在应用层集成的系统,那么在集成数据方面就不会有任何问题。

这也会给应用团队和 SaaS 解决方案带来更多的责任。我确实相信这将带来一个重大的挑战,并且是为什么真正的零 ETL 未来会受到阻碍的主要原因。

命名和数据类型约定

标准化命名和类型约定将节省大量繁琐的工作。我认为有理由问…为什么数据工程师仍然必须编写小的“t”转换?

在一天结束的时候,我们最好都同意开始用标准化的约定命名所有的字段。

这将允许我们也标准化数据类型。当然,软件工程师也必须在日期格式上达成一致。

生产者所有权

数据仓库或任何独立的基础架构层都无法解决适用于 SaaS 应用的 ZeroETL。只有 SaaS 供应商负责将数据移动到他们客户的数据仓库,这一愿景才能实现。——阿伦·图拉斯达兰

除了负责移动数据,SaaS 供应商和数据生产者还必须确保他们管理所有的逻辑和数据变更。

移除 ETL 最困难的部分是 t,而不是一些基本的转换,比如标准化命名约定和数据类型(实际上,为什么这还没有自动化)。即使加上缓慢变化的维度,也可以说是广义的。

不,在那之后会有更多的变化。任何需要人工管理的业务逻辑或奇怪的枚举器都必须由数据的生产者来处理,无论是公司应用程序还是 Salesforce。

真相

有些人可能会认为,因为我一开始是一名数据工程师,所以我想捍卫 ETL,这是我们承担的一项常*任务。然而,世界在变,如果世界不再需要数据工程师来构建 ETL 呢?那就这样吧。

现在我认为这不会在未来两年内。尤其是在企业层面,对他们来说,从当前解决方案中迁移出来需要两年的时间(如果顺利的话)。所以即使他们今天就开始了,我们离零 ETL 还有很长的路要走。

你有什么想法,你能想象一个没有 ETL 的世界吗?需要什么?

AACL-IJCNLP 2022 亮点

原文:https://towardsdatascience.com/aacl-ijcnlp-2022-highlights-d605e71e618f

可调文本净化、惩罚过度*滑和用于看不*的语言的跨语言语言模型

蒂莫·沃尔茨在 Unsplash 上的照片

11 月 20 日至 23 日, AACL 2022 与 IJCNLP 联合举办。

这是计算语言学协会(ACL)亚洲分会 AACL 的第二版。它只在网上举行(原计划在台湾举行)。

由于 AACL 仍然是一个年轻的会议,它收到的提交比欧洲和北美同行少得多。在提交的 554 篇论文中,有 147 篇被接受。

这是一个 26.5%的接受率,与 ACL 组织的其他会议的接受率相差不远。换句话说,AACL 是一个非常挑剔的会议。

我查阅了会议记录,挑选了几篇我觉得特别有趣的论文。

如何选择高光?

我的集锦不一定是大会最好的论文。

我主要选择处理趋势话题的论文,如人工智能中的公*和跨语言 NLP。

我还试图选择那些得出适用于广泛的 NLP 应用的结论的论文,和/或我认为将对未来的工作产生重大影响的论文。

这种选择也受到我自己在自然语言生成和机器翻译方面的专业知识的影响,也就是说,我更关注在这些领域发表的论文。

具有隐私风险明确措施的神经文本净化

作者:安西·帕帕多普洛(奥斯陆大学)、·于(理工学院)、皮埃尔·利松(挪威计算中心)和莉莉娅·弗勒里德(奥斯陆大学)

NLP 模型越来越渴求数据。为了避免将私人信息传输到模型中,并防止在使用模型时侵犯隐私,应该应用文本净化。这是屏蔽文本中的任何私人信息的任务,例如姓名和地点,即可以帮助识别个人的信息。

文本净化是一项特别具有挑战性的任务,因为许多线索在单独使用时可能看起来毫无意义,但放在一起实际上可能会导致个人身份识别。标识符可以分类如下:

  • 直接:姓名、社交网络标识符、车牌号等。
  • 间接:出生日期、种族、国籍、地理定位数据点等。

在这项工作中,作者提出了一个不同于以往工作的方法。它引入了一个新的参数来控制隐私保护和数据有用性之间的权衡。事实上,以前的作品通常要么通过删除大量有用的信息(间接标识符)来保护隐私,要么不够积极,不足以保证隐私保护。

本文在权衡参数的需要上很有说服力。很容易想象需要或多或少主动清理的文档,例如,取决于领域(医疗记录、产品评论等。).

他们的方法分为 3 个步骤,如下图所示:

图由安西·帕帕多普洛(奥斯陆大学)、郝云·于(理工学院)、皮埃尔·利松(挪威计算中心)和利利亚·弗勒里德(奥斯陆大学)提供

他们首先应用实体识别器,该实体识别器特别适用于关注可能是直接或间接标识符的实体。然后,使用 3 种不同成分的组合,该方法识别哪些实体最有可能识别个体。这些组件的输出被组合以发布一个分数,该分数可用于调整净化的积极程度。

我认为这是一部令人印象深刻的作品。它保持简单和直观,同时为标准文本清理方法提供了一种可调的替代方法。

对于神经机器翻译来说,编码器-解码器是多余的吗?

作者:高英波、克里斯蒂安·赫罗德、杨子健和赫尔曼·内伊(亚琛工业大学)

标准神经机器翻译(NMT)使用编码器-解码器架构。相比之下,生成式预训练语言模型仅使用自回归解码器,而没有任何单独的编码器,但是仍然能够执行翻译。例如,GPT 3 号可以翻译。

高等人的这项工作旨在研究机器翻译中编码器和解码器是否冗余。换句话说,难道我们不能通过连接源句子和目标句子来简化 NMT 体系结构,然后用语言建模目标在结果序列上训练模型吗?

为了回答这个问题,他们对非常不同的语言对进行了广泛的实验:德语-英语,英语-罗马尼亚语,英语-汉语,以及在同一训练数据中混合了多种语言(法语,德语和西班牙语)的多语言设置。

他们的主要意*如下:

  • 翻译作为一种语言建模任务,其性能与标准的编码器-解码器架构相当。
  • 自动编码和交叉熵损失产生类似的结果
  • 对信号源来说,一个完整的注意力屏蔽是必要的
  • 伯特风格的噪声对更好地训练模型帮助不大
  • 语言模型应该具有与编码器-解码器版本一样多的参数,以实现类似的性能

它大大简化了 NMT 系统的当前架构。我们可以预期,在未来,翻译将更经常地作为语言建模任务来处理。

这项工作的一个局限在于评估。他们只用 BLEU 和 TER 这两个非常有限的指标来得出结论。鉴于这两个指标的评分之间的微小差异以及与人类判断的较差相关性,作者得出的结论在其他翻译任务中可能不成立。

对未知语言的跨语言少量学*

作者:尊达表·温纳塔(彭博)、吴世杰(彭博)、马扬克·库尔卡尼(亚马逊 Alexa AI)、塔玛·索洛里奥(彭博)和丹尼尔·普雷奥蒂乌克-皮埃特罗(彭博)

大型语言模型可以应用于训练数据中看不到的语言吗?

虽然语言模型的跨语言能力是一个趋势性的研究主题,但它们对未知语言的建模能力在很大程度上仍未得到充分研究。

这项工作使用 3 种不同的多语言模型:XLM-R、mT5 和 XGLM,应用于情感分类任务(NusaX ),研究了少镜头学*如何在预训练期间对未知语言进行学*。

他们发现,如果我们有至少 15 个少量学*的例子,微调预先训练的模型实际上是最佳策略。上下文学*和在推理时用例子提示模型似乎产生较低的结果。

他们尝试了 XLM-R、mT5 和 XGLM,但同时也改变了少量学*策略,例如,mT5 在实验中从不微调,而只是用几个例子来提示。XLM-R 进行了微调,但没有使用示例进行提示。作者的结论是,微调是最好的策略,但这可能只是由于 XLM-R 本身而不是微调。

尽管如此,事实上,一个语言模型可以模拟一种在预训练期间看不到的语言,只使用少量的学*,这确实是了不起的。

描述和解决神经自回归序列建模中的过度*滑问题

伊利亚·库利科夫、马克西姆·埃雷米夫和赵京贤(纽约大学)

自回归神经模型可以将非常高的概率分配给不合理的短序列。在极端情况下,序列甚至可能是空的。

有可能量化不合理的短序列产生的频率,即,当概率质量对短序列过度*滑时。

本文作者建议用“过度*滑率”进行量化。

他们首先表明,模型往往表现出罕*的过度光滑。它们生成的序列比它们应该生成的要短。

然后,他们提出了一种方法,使用负对数似然目标来减少模型训练期间的过度*滑率。

具体地说,他们以过度*滑损失的形式添加了正则化成分。这种损失有两项:第一项进一步最小化短序列的 EOS 令牌(即,生成时停止生成的令牌)的概率,而第二项防止短序列比完整序列更有可能。关于数学细节,我邀请你阅读这篇论文(第 3.1 节)。

注意,作者建议首先训练没有过度*滑损失的模型,因为它倾向于促进退化序列。然后,在模型的后续训练中,除了原始负对数似然训练目标之外,还可以引入过*滑损失。在第二次训练期间,过度*滑损失的贡献可以用权重α来调整。

在机器翻译中对所提出的方法进行了评估。正如我们在下图中看到的,该方法确实大大降低了过度*滑率。

图由伊利亚·库利科夫、马克西姆·埃尔梅耶夫和赵京贤(纽约大学)提供

在我看来,他们的结果中最引人注目的是对大波束解码的过*滑损失的好处。如下图所示,对于较高的α,BLEU 分数显著提高,特别是对于 100 的射束。

图由伊利亚·库利科夫、马克西姆·埃雷米夫和赵京贤(纽约大学)

它们表明句子的长度更接近参考句子的长度。

这项工作也是对深度学*中更好的波束搜索解码的重大进步。

预测公*性的系统评估

作者:(墨尔本大学)、艾力·申(亚马逊 Alexa AI)、特雷弗·科恩(墨尔本大学)、蒂莫西·鲍德温(墨尔本大学)和丽娅·弗雷曼(墨尔本大学 MBZUAI)

我发现这项工作特别有趣,因为它回答了许多关于应用于数据集的去偏置方法的有效性的问题。

简而言之,他们的主要结论是,不存在消除数据集中偏差的通用最佳方法。

消除偏差的有效性很大程度上取决于数据条件,而不是去偏差的方法。

在这项工作中,数据条件是一组属性,用于量化数据集中人口统计子群、刻板印象等表示的*衡程度。直觉上,如果这些条件没有被很好地量化,去偏置方法的评估可能导致错误的结论。

评估这些条件的影响的实验是广泛的,并且跨越多个任务:二元和多类分类,以及回归。

根据给出的结果,不可能在先前工作使用的标准基准上正确评估去偏置方法。标准基准提供了一个不完整的画面,它将根据数据条件支持特定的方法。

这意味着应该通过更好地考虑数据条件来再次评估先前的工作。

我认为这是 NLP 在公*性领域的一个非常重要的进步。本文的结论将鼓励更好的去偏置方法的评估实践和基准的新数据集的创建。

这项工作的限制之一是它主要集中在“群体公*性”上,即一个模型在独立于人口统计子群的情况下,其表现如何是公*的。没有研究其他类型的偏差。作者承认这一点,他们认为他们的结论应该适用于其他类型的偏*。

缺乏理论是痛苦的:在同行评议中模拟苛刻

作者:拉吉夫·维尔马、拉贾什·罗伊丘杜里(贾达夫普尔大学)和提尔森卡·戈萨尔(查理大学)

这是一项非常有趣的研究,它首先提醒了同行评议过程对科学论文作者来说是多么“痛苦”。

事实上,科学论文的审稿人经常是苛刻的,伤人的,并且可能忘记他们可能正在审阅一个年轻研究者的第一篇论文。

相信我,和大多数科学家一样,我也经历过。苛刻的评论对论文的改进毫无帮助,需要一些时间来找到再次提交的力量和动力。

尽管有问题的审查可能由元审查者或更高的计划委员会成员确定,但随着 AI/ML 会议变得越来越流行,由于要处理的审查量巨大,这变得越来越困难。

为了帮助完成这项任务,这项工作提出了一种自动的方法来评估评论的“苛刻度”。这里的最终目标是在评论发送给作者之前标记和编辑它们。

这项工作给出了下面这个苛刻评论的例子,来自 NeurIPS 2021:

“我确实有社会科学研究的经验,但这篇论文从那个角度来看缺乏洞察力或原创性,所以我建议拒绝,[……]”

“这篇论文最终会在某个地方发表,但不会有太大影响。”

这听起来很刺耳,也没有建设性,但我*过更糟糕的。

为了训练一个粗糙度预测模型,作者汇编并公开发布了一个评论数据集,并对其粗糙度进行了注释。

他们对数据集上的 BERT 模型进行了微调,以对评论进行严格分类。他们获得了高于 70%的准确率。

我的看法是,这种倡议是非常需要的。众所周知,同行评审过程存在许多问题。拥有像这样的自动化方法肯定有助于解决这个问题。我甚至可以想象直接在运行中计算苛刻度分数,以警告评论者该评论可能过于苛刻,应该进行编辑。

结论

当然,这只是 AACL-IJCNLP 2022 项目的一瞥。你可以在那里找到完整的程序:

我还没有看过发表在“发现”上的论文,但那里总是有很棒的论文发表,还有在同处一地的研讨会上。

如果你有兴趣发现其他杰出的作品,我在这里列出了我的亮点:

Benjamin Marie

本杰明·玛丽

NLP/AI 会议集锦

View list3 stories

如果你喜欢这篇文章,支持我工作的最好方式就是使用我的链接成为一名媒体会员:

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

如果你已经是会员,想要支持这项工作, 就在 Medium 上关注我吧。

使用分布式强化学*架构加速 RL 培训

原文:https://towardsdatascience.com/accelerate-training-in-rl-using-distributed-reinforcement-learning-architectures-b5a726b49826

附身摄影Unsplash 上拍照

最常*的有什么不同?

Re enforcement learning 是人工智能的一个领域,专注于教导智能体在复杂和动态的环境中自动进行顺序决策。一个智能体学*与一个真正的人类棋手对弈就是应用 RL 的一个例子。在 RL 环境中,代理通过探索和利用可以在环境上采取的动作来学*操作环境。代理人的目的是最大化长期累积回报,就像在一场国际象棋比赛中获得最高的胜利数。

来源:https://en.wikipedia.org/wiki/Reinforcement_learning

。RL 算法分为基于模型的算法和无模型算法。在基于模型的环境中,我们有环境的真实表示,这意味着我们知道在当前状态下采取行动时到达下一个状态的概率。这些环境很容易模拟。例如,如果你想教一个智能体解决一个迷宫游戏,把迷宫表示为一系列当前位置、动作(左、右、前、后)、下一个位置元组更容易。

无模型学*处理难以模拟的真实世界环境,没有真实的环境模型——例如,代理在真实世界中学*驾驶汽车。在这个例子中,将汽车周围的世界表示为当前位置、动作(左、右、前、后)、下一位置元组的元组是复杂的。在这种情况下,代理通过最初采取随机行动来收集经验,并在后期优化行动。因此,代理在无模型 RL 问题中花费的大部分时间是在生成数据。这不仅仅是环境的随机性;动态环境还包含大的状态空间和动作空间,这使得训练数据的收集更慢。

大多数 RL 应用在决策时需要高吞吐量,这不仅限于游戏。想象一下,一个工业机器人负责通过将压力保持在最佳水*来确保安全。这种工业应用中的推断时间应该在几毫秒/微秒内,以便防止灾难。因此,在训练、优化和推理时间有限且环境复杂的情况下,应用 RL 算法开发工业人工智能解决方案始终是一个挑战。

在这种情况下,分布式强化学*会很有帮助。在分布式强化学*中,作用于环境和从经验中学*的责任分别在参与者和学*者之间划分。代理收集的经验与学*者共享,学*者负责学*要采取的最佳行动。类似地,学*者学*的动作被发送给演员。这种去耦支持对各种分布式 RL 架构的研究。

这篇博文介绍了最常用的架构,以及它们之间的区别。这里给出的架构列表并不详尽。随着 RL 在研究和应用中的普及,提出了更多的变体。然而,其中的每一个都仅仅是先前架构的衍生物,并且在优化训练时间、通信开销、资源优化、运行成本等方面有所不同。解耦参与者和学*者的底层设计在许多领域都很常*。

注意:基于模型的 RL 算法,如值迭代或策略迭代,也可以并行化。然而,他们局限于环境模型可用的问题,这在现实世界中是非常罕*的。因此这篇博文只关注无模型 RL 算法。

哥里拉

Gorila 代表通用强化学*架构,是 2015 年提出的第一个大规模分布式强化学*架构。本文引入了使用负责创建经验轨迹的行动者和基于神经网络的表示价值函数或策略函数的学*者的思想。下图显示了哥里拉的建筑。

哥里拉建筑,来源:【https://arxiv.org/abs/1507.04296

GORILA 使用 DQN 学*价值函数。每个参与者从最新的 Q-网络参数中获得可以对环境采取的最佳行动。演员将体验轨迹发送到重放缓冲器。在一个环境中可以有多个参与者,这使得经验轨迹(训练数据)的收集更容易。每个学*者对训练数据进行采样,以使用深度 Q 学*来训练他们对应的 Q 网络。但是,梯度不会直接应用于目标网络。每个包含 Q 网络的学*器将梯度发送到参数服务器。参数服务器负责从学*者处收集梯度并合并梯度更新。参数服务器是使用 dist faith 构建的,dist faith 是一个用于并行训练大型网络的分布式系统。GORILA 使用模型并行性来收集和应用来自学*者模型的梯度,并将最新的 Q 网络参数发送到目标 Q 网络和演员。因此,用于生成最佳动作的模型参数落后于由学*者学*的最新参数,因为同步发生在每 N 个梯度更新之后。

黑斑羚

IMPALA 是重要性加权演员学*架构的标准,是 2018 年提出的另一种分布式 RL 方法,与 GORILA 截然不同。IMPALA 更适合多任务学*,你需要在不同领域的数百万个样本上进行训练。与 GORILA 学*价值函数不同,IMPALA 使用一种叫做 Actor-critic 的算法来学*政策函数和价值函数。在行动者-批评家方法中,有两个函数逼近器,一个负责学*策略,另一个负责学*价值函数。学*策略函数比纯值函数具有优势,因为策略函数本质上是随机的。在基于策略梯度的方法中,代理可以自由探索由策略函数生成的动作。相比之下,在传统的 Q-learning 中,只在学*阶段做出探索与利用的决策,但是由代理预测的动作是根据学*的策略采取的,这使得策略具有确定性。

(注意:可以使用 Q 学*来学*随机策略,这种策略称为准确定性策略)。

IMPALA 使用多个参与者和单个学*者策略来克服通信开销。学*者使用加速器(GPU)根据从各种参与者那里收集的经验来训练代理。学*者使用演员-评论家算法的变体来学*策略函数和基线值函数。然而,与 A3C 的分布式版本不同,参与者在本地存储并与集中式学*者共享经验,而不是梯度更新。IMPALA 采用各种优化技术来减少演员和学*者之间的滞后。使用 CNN + LSTM + FC 层来优化学*,其中对 CNN 和 FC 层的输入被并行处理。然而,该架构仍然遵循一个偏离策略的学*过程,因为参与者不使用最新的策略来派生动作。尽管如此,IMPALA 通过采用 V-trace 另一种不符合政策的演员-评论家强化学*算法来减少滞后的影响。正如算法的标题所提到的,“重要抽样”是一种应用于估计以减少方差的技术。IMPALA 通过对梯度应用权重来使用加权重要性采样。下图显示了 IMPALA 的架构示例。

英帕拉建筑(图片由作者提供)

SEED-RL

种子 RL 是最新的一个,由谷歌在 2020 年提出。SEED 代表可扩展且高效的深度 RL。SEED RL 解决了 IMPALA 使用的分布式参与者和集中式学*者方法中存在的许多不足。IMPALA 最重要的不足是使用 CPU 进行推理。SEED 通过将推理和轨迹集合移动到学*者来解决这个问题。有了这个变化,演员只负责操作环境。由于演员现在只有一项工作要做,所以它比 IMPALA 中使用的更轻便。此外,演员只分享经验。因此,与 IMPALA 相比,带宽需求是有限的,在 IMPALA 中,参与者共享模型参数、经验轨迹和 LSTM 状态。

由于参与者需要依赖学*者来完成每一步,这就引入了一个新的延迟问题。SEED 通过使用流式传输和始终开放的连接以及 GRPC 等低延迟通信协议来解决这一问题。此外,当参与者与学*者并置时,通过使用域套接字进一步减少了等待时间。下图显示了 SEED-RL 的架构。

SEED-RL 架构(图片由作者提供)

SEED 使用由 IMPALA 引入的 V-trace 来学*目标策略。SEED 不同于值函数的学*方式。SEED 使用 R2D2 (递归经验重放分布式强化学*),一种基于价值的分布式代理来学*价值函数。

下表总结了上述每种方法的优缺点。

分布式 RL 方法的利弊。(图片由作者提供)

总之,上述每种方法都以独特的方式解决了训练时间、成本、带宽需求和资源优化的问题。每种方法的应用都取决于问题的性质。尽管如此,人工智能在除游戏以外的工业应用中的应用已经获得了动力,基于按需定价模型的 RL 分布式架构,云提供商加速器的可用性将有助于该领域的进一步发展。

在谷歌 TPU 上使用 TensorFlow 加速分布式训练

原文:https://towardsdatascience.com/accelerated-distributed-training-with-tensorflow-on-googles-tpu-52f1fe21da33

了解您的硬件以优化您的软件

Cloud TPU v3 POD BYGoogle Cloud(CC BY 4.0)

在这篇文章中,我将从硬件的角度向您展示张量处理单元(TPU)的基本原理,并一步一步地向您展示如何使用 TensorFlow 在 TPU 上执行加速分布式训练来训练您自己的模型。

概述

  1. 简介
    1.1。张量处理单元1.2
    。[分销策略](#Distribution Strategies)
  2. 用 TensorFlow
    2.1 在 TPU 上实现分布式训练。硬件检测
    2.2。分布式数据集
    2.3。手动降损
    2.4。自定义训练循环
  3. 结论
  4. 更多资源

1.介绍

无论是谷歌的伯特,OpenAI 的 GPT-3 ,英伟达的威震天图灵 NLG 还是谷歌的开关变形金刚,这些模型都表明,通过大规模缩放你的模型和数据集,可以实现令人印象深刻的结果。虽然在这样的模型上运行推理已经是一个挑战,但训练模型更具挑战性。训练一个模型通常需要比推理多几个数量级的计算资源。需要大型硬件加速器集群在合理的时间内训练这些模型。除了 GPU 之外,张量处理单元(TPU)在训练模型中也起着重要的作用。为了利用 TPU 的高计算性能,理解底层硬件架构和理解必须如何准备代码是至关重要的。

让我们从一些解释开始,这些解释将帮助您了解 TPU 硬件的基本原理,并在实现代码时采取正确的措施。

在这篇文章的底部,你会找到一个笔记本的链接,在那里我用本文描述的技术改编了 TensorFLow 的 DCGAN 模型,并在 TPU 上训练该模型。

1.1.张量处理单元

张量处理单元是一种硬件加速器,用于加速矩阵的 MAC(乘法和累加)运算,这是机器学*中的主要运算之一。

底层硬件的性能依赖于许多方面,但有一个限制因素:内存接口。为了进行计算,处理器必须从内存中提取数据。有两个主要问题。第一个是内存访问延迟。访问存储器比对提取的数据执行计算花费更多的时钟周期,因为需要等待直到数据可用于计算。第二个是能耗。从 DRAM 读取数据比从芯片内部存储器读取数据需要更多的能量[3]。这种影响与时钟速度成线性比例关系,这意味着如果试图通过提高时钟速度来减少延迟,就必须考虑冷却策略。因此,性能瓶颈是内存接口。

如果可以以某种方式减少访问存储器的次数,就可以充分利用可用的计算资源,同时节省大量的电力。几十年前就已经提出了这个问题的解决方案:脉动阵列。想法很简单:对从内存中读取的单个数据项执行多个操作。它的灵感来自于通过我们身体泵送的血细胞。它们在心脏中开始循环,被泵送通过我们身体中的几个细胞,并循环回到心脏。心脏类似于记忆,每个细胞都是对血液进行操作的处理单元。图 1 中描绘了脉动阵列的抽象表示,其中 PE 是处理元件的一般形式。

图 1 心脏收缩系统的基本原理[4]

一般来说,PE 可以是任何东西,从单个逻辑门到整个处理器(链接回我们的 TPU 硬件)。过程如下:从内存中读取数据,由 PE 执行任意操作,将数据传递给下一个 PE,最后,在最后一个 PE 之后,将计算结果写回内存。

让我们更具体地看一个简单的例子。考虑一维卷积问题,这里我们有一个权重序列 W ,一个输入序列 X 。我们将计算输出序列 Y 及其元素 y_i

这个问题可以用图 2 所示的收缩期阵列来解决

图 2 收缩期卷积阵列(a)和单元(b ),其中 w_i 保持不变,x_i 和 y_j 在收缩期向相反方向移动[4]

在这种情况下,PE 有两个输入和两个输出。权重被预加载,同时数据 x 流经数组,计算各自的输出 y

上面的脉动阵列是一个简化的例子,有助于我们理解其背后的思想。在 TPU 中,脉动阵列以更复杂的方式使用,因为矩阵乘法单元伴随有向量和标量单元、高带宽互连和高带宽存储器接口。图 3 描绘了谷歌的 TPUv2 和 TPUv3。

图 3: Google 的张量处理单元,(左)Google Colab 中可用的 TPUv2,(中)Kaggle 中可用的 TPUv3,(右)由 Google Cloud(CC BY 4.0) 下制作的 TPU 的矩阵乘法单元动画

特别是 Google 的 TPUv2 实现了 8 核 180 万亿次浮点运算,每个都有一个 128x128 PEs 的二维脉动阵列。谷歌的 TPUv3 实现了高达 420 万亿次浮点运算。在其他改进中,TPUv3 将每个内核的脉动阵列数量增加了一倍,将每个内核的内存容量增加了一倍,引入了高带宽内存并改善了互连。上面提到的 FLOPS 是理论上限。在实践中,很难实现这些价值,因为不是所有的操作都受益于这种非常专业化的架构。此外,应该优化数据的输入管道,以保持 TPU 的计算资源繁忙。

脉动阵列和 TPU 一样,对于某些任务来说是高度专业化的。然而,训练机器学*模型需要更多的步骤,例如预处理数据或更新优化器状态。对于这样的任务,通用处理器(即 CPU)仍然是有益的。如果建立了到 Google 的一个云 TPU 的连接,那么实际上就建立了到一个主机 VM 的连接。该主机虚拟机管理与本地环境的通信,并通过高带宽 PCIe 接口控制 TPU(参*图 4)。

图 4Google Cloud(CC BY 4.0) 、【右】WARP 架构下(左)云 TPU 界面对比[5]

几十年前(也是在 80 年代),通过具有特殊编译器的通用主机来控制快速专用脉动阵列的想法再次被提出,即 WARP 架构。[5]这样的系统是可扩展的,最重要的是,对程序员隐藏了它们的复杂性。

如果你对谷歌 TPUs 的内部架构感兴趣,我推荐你观看谷歌来自 Hot Chip 2020 的演示。

1.2.分销策略

在研究 TensorFlow 中的实现之前,理解分布式培训的概念很重要。我们之前已经看到 TPU 有几个内核。多核的出现实现了真正的时间并行,这意味着代码可以并行执行,而不仅仅是以时间复用的方式执行。至少有两种范例可以实现并行以加快训练过程:模型并行和数据并行。模型并行性和数据并行性的图形表示如图 3 所示。

图 3:并行训练编程*惯用法,(左)模型并行训练,(右)数据并行训练[2]

在模型并行中,模型的不同部分在不同的设备上训练,但是在相同的训练批次上。

在数据并行训练中,单个模型被镜像并分布在由主机设备管理的多个设备(也称为工作者)中。主机设备充当模型的参数服务器。每个工人在训练批次的子集上训练其模型。对每个员工单独计算损失,并将其发送到外派国。各个损失值通过例如将它们相加来组合。最后,主机更新模型的权重,并重新分配更新后的模型。在这种情况下,客户端的单个线程可以控制训练循环,而大部分模型计算分布在几个设备上。由于所有模型总是具有相同的参数,并且同步更新,这种方法被称为同步数据并行。

2.用 TensorFlow 在 TPU 上实现分布式训练

在 TPU 上分配你的训练并不像听起来那么琐碎,但绝对值得努力。在 Github 上的这个笔记本里可以找到在 TPU 训练 DCGAN 的完整例子。

2.1.硬件检测

第一步是连接到 TPU。与 CPU 和 GPU 环境相比,在 TPU 环境中,您必须显式检测并连接到 TPU。由于 Google Colab 和 Kaggle 中的 TPU 资源有限,您可能希望在 CPU/GPU 上开发和调试,并在 TPU 上执行培训。因此,脚本自动检测可用的硬件并自动设置所需的策略是很有用的(参*代码 1)。

代码 1:自动检测硬件并设置相应的策略

提示:自动硬件检测的实现可以在我在 GithubPyPi 上的深度学*库 DeepSaki 中找到。

如果您正在运行一个 TPU 环境,例如 GoogleColab 或 Kaggle,您现在应该连接到您的 TPU。

2.2.分布式数据集

如前所述,当遵循同步数据并行范例时,您的训练数据将分布在所有工作人员中。TensorFlow 提供了一个从[tf.data.Dataset](https://www.tensorflow.org/api_docs/python/tf/data/Dataset)转换到[tf.distribute.DistributedDataset](https://www.tensorflow.org/api_docs/python/tf/distribute/DistributedDataset)的简单 API。这里举个例子:

train_distributed = strategy.experimental_distribute_dataset(train)
test_distributed = strategy.experimental_distribute_dataset(test)

在上面的例子中,traintest属于tf.data.Dataset类型。通常你会首先使用batch()cache()map()来定义你的输入管道,然后将你的数据集转换成分布式数据集。使用全局批处理大小而不是每个副本的批处理大小进行批处理非常重要。全局批次大小由所有副本中训练的批次数量决定。如果数据集除以可用于培训的员工人数,则为批量大小。

2.3.人工减少损失

您可能想知道为什么总是得到标量损失值,即使在计算多维损失时,比如两幅图像之间的像素损失。原因是:TensorFlow 执行自动损耗减少,在大多数情况下,损耗是通过对一个批次内的所有值求和并除以批次大小来减少的。实现自定义训练循环时,TensorFlow 要求您手动减少损失,因为不允许使用tf.keras.losses.Reduction.AUTO

我们要做的基本上是重新实现上述行为。以下代码显示了使用铰链损耗的程序:

import tf.keras.losses as losses
loss_fn = losses.Hinge(reduction=losses.Reduction.NONE)
loss = loss_fn(ground_truth, prediction)
loss = tf.reduce_sum(loss) * (1./GLOBAL_BATCH_SIZE)

首先,定义损失函数,并应用无减少策略。因此不执行任何缩减。接下来,计算ground_truth和模型的prediction之间的损失。然后,loss的所有值相加得到一个标量。最后,标量损失由全局批处理大小来缩放,而不是当前副本的批处理大小。使用全局批处理大小而不是每个副本的批处理大小进行缩放的原因是,在引言中描述的数据并行性范例中,所有工作线程的损失被加在一起。关于实现的细节将在定制训练循环一节中介绍。

2.4.自定义训练循环

到目前为止,我们已经连接到 TPU,准备了分布式数据集并执行了手动损失缩放。最后缺失的部分是分布式训练循环。

该示例侧重于培训的实现,但也可以以类似的方式应用于验证。

假设我们已经通过子类化tf.keras.Model实现了自己的定制模型(参*代码 2)。为了实现我们的定制训练循环,我们首先必须实现两个方法:train_step()distributed_train_step()

占位符(…)表示缺少代码,这是特定于给定示例的,但对于解释定制训练循环并不重要。

方法train_step()计算损失函数相对于模型权重的梯度。梯度计算在[tf.GradientTape](https://www.tensorflow.org/api_docs/python/tf/GradientTape)的上下文中完成。最后,优化器应用更新的权重。

方法distributed_train_step()train_step()的执行分配给所有工人,收集每个工人的最终损失,并对所有损失项求和。

装饰器@[tf.function](https://www.tensorflow.org/api_docs/python/tf/function)将装饰过的函数编译成图形,这加速了它的执行。

代码 2:分布式培训步骤的实现

定义好培训步骤后,我们现在可以继续最后一步:实现实际的培训循环。

代码 3:训练循环的实现

在这个函数中,我们使用 for 循环一次执行一个时期,直到所有时期都被执行。然后,我们在分布式数据集上逐批迭代,并在每一批上调用模型的distributed_train_step()方法。该方法返回所有工作线程的损失。我们对每一批的损失进行求和,并在迭代所有批后,根据训练的批数对结果进行缩放。

就是这样!祝贺你,你成功了!👏🎉

3.结论

我们已经从理解传统计算硬件的内存瓶颈走了很长一段路,引入了脉动阵列作为谷歌 TPU 的关键元素,讨论了分布式训练,最后研究了 TensorFlow 中的实现。TPU 具有惊人的性能指标,但因此是高度专业化的硬件,这意味着您可能无法充分利用它。

事实上,你可以免费访问 TPUs 是惊人的,因此,如果你知道如何使用它,这是一个很好的机会。

当然,TPU 并不是加速你训练的唯一方法。在其他技术中,你可以在 GPU/TPU 上使用混合精度进一步加速你的 TensorFlow 训练,通过它你可以利用专门的 float16 加速。

4.更多资源

  1. 在 TPU 上训练 DCGAN 的笔记本: Github
  2. 深度学* python 库 DeepSaki: Github 或者 PyPi
  3. 关于的指南在 GPU/TPU 上用混合精度加速你的 TensorFlow 训练

[1]谷歌。2021."云 TPU . "谷歌云。检索到 2021 年 5 月 2 日(https://cloud.google.com/tpu/docs/system-architecture?hl=de)。

[2]阿巴迪等人 2016。"张量流:异构分布式系统上的大规模机器学*."ArXiv:1603.04467【Cs】

[3] M. Horowitz,“计算的能源问题(以及我们可以做些什么)”,2014 年 IEEE 国际固态电路会议技术论文摘要(ISSCC),美国加利福尼亚州三藩市,2014 年 2 月,第 10-14 页。doi: 10.1109/ISSCC.2014

[4]孔汉东(1982 年)。为什么选择脉动架构?IEEE 计算机,15(1),37–46。https://doi.org/10.1109/MC.1982.1653825

[5] Annaratone,m .,Arnould,e .,Gross,t .,Kung,H. T .,Lam,m .,Menzilcioglu,o .,和 Webb,J. A. (1987 年)。翘曲计算机:结构、实现和性能。IEEE 计算机汇刊,36(12)。https://doi.org/10.1109/TC.1987.5009502

图核 IPU 上时态图网络的加速和缩放

原文:https://towardsdatascience.com/accelerating-and-scaling-temporal-graph-networks-on-the-graphcore-ipu-c15ac309b765

缩放 GNNs

图形神经网络(GNNs)标准硬件的适用性是图形 ML 社区中经常被忽视的问题。在这篇文章中,我们将探讨在 Graphcore 开发的新硬件架构上实现时态 GNNs,该架构是为图形结构的工作负载量身定制的。

Graphcore 弓 IPU 机。图片:图表核心

这篇文章与 伊曼纽·罗西 丹尼尔·贾斯特斯 合著,基于与英国半导体公司graph core的合作。

图结构的数据出现在许多处理交互实体的复杂系统的问题中。近年来,将机器学*方法应用于图结构数据的方法,特别是图神经网络(GNNs),已经*证了流行的巨大增长。

大多数 GNN 架构都假设图形是固定的。然而,这种假设往往过于简单:因为在许多应用程序中,底层系统是动态的,图表会随着时间而变化。这是例如社交网络或推荐系统中的情况,其中描述用户与内容的交互的图形可以实时改变。最近开发了几个能够处理动态图的 GNN 架构,包括我们自己的时态图网络 (TGNs) [1]。

通过在时间戳 t ₁ 和 t ₂.获得新的边,人与人之间的交互图是动态变化的

在这篇文章中,我们探索了 TGNs 在不同大小的动态图中的应用,并研究了这类模型的计算复杂性。我们使用 Graphcore 的 Bow 智能处理单元 (IPU)来训练 TGNs,并展示为什么 IPU 的架构非常适合解决这些复杂性,在将单个 IPU 处理器与 NVIDIA A100 GPU 进行比较时,速度提高了一个数量级。

TGN 架构在我们之前的帖子中有详细描述,由两个主要组件组成:首先,节点嵌入是通过经典的图形神经网络架构生成的,这里实现为单层图形注意力网络[2]。此外,TGN 还保留了一个总结每个节点过去所有交互的内存。这种存储通过稀疏读/写操作来访问,并使用门控循环网络(GRU) [3]通过新的交互来更新。

TGN 建筑。底部一行代表一个只有一个消息传递步骤的 GNN。顶行说明了图形中每个节点的额外内存。

我们关注通过获得新边而随时间变化的图。在这种情况下,给定节点的存储器包含关于以该节点为目标的所有边以及它们各自的目的节点的信息。通过间接贡献,给定节点的记忆也可以保存关于更远的节点的信息,从而使得图形注意力网络中的附加层可有可无。

对小图的应用

我们首先在 JODIE Wikipedia 数据集[4]上试验 TGN,这是一个 Wikipedia 文章和用户的二分图,其中用户和文章之间的每条边都代表用户对文章的编辑。该图由 9,227 个节点(8,227 个用户和 1,000 篇文章)和 157,474 条带时间戳的边组成,这些边用描述编辑的 172 维 LIWC 特征向量[5]进行了注释。

在训练期间,边被逐批插入到最初断开的节点集合中,同时使用真实边和随机采样的负边的对比损失来训练模型。验证结果被报告为在随机采样的负边缘上识别真实边缘的概率。

直观地说,大批量对训练和推理都有不利的后果:节点内存和图的连通性都只在处理完一整批后才更新。因此,一个批次中的后续事件可能依赖于过时的信息,因为它们不知道该批次中的早期事件。事实上,我们观察到大批量对任务性能的不利影响,如下图所示:

当使用不同的批量大小进行训练并使用固定的批量大小 10 进行验证时(左),以及当使用固定的批量大小 10 进行训练并使用不同的批量大小进行验证时(右),TGN 对 JODIE/Wikipedia 数据的准确性。

然而,小批量的使用强调了快速存储器访问对于在训练和推理期间实现高吞吐量的重要性。因此,与批量较小的 GPU 相比,具有较大处理器内存的 IPU 显示出了更大的吞吐量优势,如下图所示。特别地,当使用 10 TGN 的批量时,在 IPU 上的训练可以快大约 11 倍,并且即使使用 200 的大批量,在 IPU 上的训练仍然快大约 3 倍。

与 NVIDIA A100 GPU 相比,使用 Bow2000 IPU 系统中的单个 IPU 时,不同批量的吞吐量有所提高。

为了更好地了解 graph core IPU 上 TGN 培训吞吐量的提高,我们调查了不同硬件*台在 TGN 关键操作上花费的时间。我们发现,花费在 GPU 上的时间主要由注意力模块和 GRU 决定,这两种操作在 IPU 上执行效率更高。此外,在所有操作中,IPU 处理小批量产品的效率更高。

特别是,我们观察到 IPU 的优势随着更小和更分散的内存操作而增长。更一般地说,我们的结论是,当计算和内存访问非常异构时,IPU 架构比 GPU 显示出显著的优势。

TGN 在不同批量的 IPU 和 GPU 上关键操作的时间对比。

缩放至大图

虽然默认配置中的 TGN 模型相对较轻,只有大约 260,000 个参数,但是当将该模型应用于大型图形时,大多数 IPU 处理器内存都由节点内存使用。然而,由于它很少被访问,这个张量可以被移动到片外存储器,在这种情况下,处理器内存储器的利用率与图形的大小无关。

为了在大型图上测试 TGN 架构,我们将它应用于一个匿名图,该图包含 1550 万 Twitter 用户之间的 2.61 亿个关注[6]。这些边被分配 728 个不同的时间戳,这些时间戳尊重日期排序,但是不提供关于随后发生的实际日期的任何信息。由于该数据集中不存在节点或边要素,因此该模型完全依赖于图表拓扑和时间演变来预测新的链接。

由于大量数据使得与单个负样本相比识别正边缘的任务过于简单,我们使用 1000 个随机采样的负边缘中的真实边缘的*均倒数排名(MRR)作为验证度量。此外,我们发现当增加数据集大小时,模型性能受益于更大的隐藏大小。对于给定的数据,我们将潜在大小 256 确定为准确性和吞吐量之间的最佳点。

模型不同隐藏大小的 1000 个负样本的*均倒数排名。

U 使用片外存储器作为节点存储器会使吞吐量降低大约两倍。然而,使用不同大小的诱导子图以及具有 10 倍 Twitter 图节点数和随机连通性的合成数据集,我们证明了吞吐量几乎与图的大小无关(*下表)。在 IPU 上使用这种技术,TGN 可以应用于几乎任意大小的图,仅受可用主机内存量的限制,同时在训练和推理期间保持非常高的吞吐量。

在不同图尺寸上训练隐藏尺寸为 256 的 TGN 每批尺寸为 256 的时间。Twitter-tiny 与 JODIE/Wikipedia 数据集的大小相似。

正如我们之前已经反复提到过,选择实现图形 ML 模型的硬件是一个至关重要的问题,但也是一个经常被忽视的问题。特别是在研究社区中,抽象出底层硬件的云计算服务的可用性导致了这方面的某些“懒惰”。然而,当涉及到实现在具有实时延迟要求的大规模数据集上工作的系统时,就不能再简单地考虑硬件了。我们希望我们的研究能引起更多人对这一重要课题的关注,并为未来图形 ML 应用的更有效的算法和硬件架构铺*道路。

[1] E. Rossi 等,动态图上深度学*的时态图网络 (2020) arXiv:2006.10637 .参*随附的博文

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

[3] K. Cho 等,论神经机器翻译的性质:编码器-解码器方法 (2014),arXiv:1409.1259。

[4] S. Kumar 等,预测时态交互网络中的动态嵌入轨迹 (2019) KDD。

[5] J. W. Pennebaker 等人,《语言学调查和字数统计:LIWC 2001 年》(2001 年)。马威:劳伦斯·厄尔鲍姆联合公司 71。

[6] A. El-Kishky 等, kNN-Embed:多兴趣候选检索的局部*滑嵌入混合 (2022) arXiv:2205.06205。

我们感谢 Douglas Orr 和 Gianandrea Minneci 为实施 IPU TGNs 所做的贡献。关于图的深度学*的附加文章,请参*《走向数据科学》中我的 其他帖子 订阅我的帖子 ,获取 中等会员 ,或者关注我的Twitter

用于神经网络的硬件加速器

原文:https://towardsdatascience.com/accelerating-neural-networks-on-hardware-baa3c14cd5ba

脉动阵列如何工作

Vishnu Mohanan 在 Unsplash 上的照片

介绍

在一个神经网络被用来处理几乎任何类型的数据(从图像到音频或心脏活动)的世界,人们越来越有兴趣将这些模型的执行从云转移到边缘(嵌入式)系统。为什么这是一个有趣的趋势?这是这种范式转变的一些原因:

  • 能耗:与其在 GPU 这样昂贵且耗能的硬件上运行人工智能算法,为什么不构建一个专门定制的嵌入式设备来更有效地执行算法呢?
  • 隐私问题:与其将原始的传感器/摄像头数据发送到云端,从隐私的角度来看,将原始数据保留在设备中,只将已经处理过的结果共享到云端不是更好吗?

虽然有多种硬件架构和解决方案可以在嵌入式设备上加速这些算法,但最有吸引力的是基于脉动阵列的加速器。H. T. Kung 在其 1982 年论文中首次介绍了这些架构,这些架构基本上是通过以级联方式重复连接基本计算单元(称为处理单元,此后称为PE)来构建的。这些数组的一个重要方面是 PE 都等于。

Kung 提出的基本思想(实际例子*论文)。图片作者。

为什么这很重要?简单和常规的设计更容易也更便宜。此外,因为数据是在 PE 之间传播的,所以这种架构重用了大量数据,这在内存带宽和能耗方面是有吸引力的(数据只从内存中读取一次,可以多次重用)。

在本文中,您将:

  • 查看神经网络的基本数学运算是如何表示的
  • 了解脉动阵列如何能够执行矩阵乘法运算(配有漂亮且易于理解的动画!)
  • 查看如何围绕脉动阵列构建完整硬件加速器架构的示例
  • 获取关于该主题的实践项目、相关论文和教育视频的摘要

免责声明:要完全理解这篇文章,你应该对线性代数(知道什么是矩阵乘法)和数字电路(知道什么是寄存器和时钟)有一个基本的了解。如果你做到了,你就可以走了!如果没有,不要让这阻止你!我相信你会发现这篇文章很有趣。

将复杂的神经网络简化为基础

如今,神经网络正在成为极其复杂的算法,有数百层,数百万(有时数十亿)的参数。但是在这篇文章中,我们将关注当今流行的神经网络模型中使用较多的两层:卷积层和全连接层。

完全连接的层可以直接描述为矩阵乘法运算。卷积层稍微复杂一点,但是存在聪明的变换,以便将它们也变换成矩阵乘法运算(参*这篇文章这篇文章关于这些变换如何工作的例子)。这就是为什么我们将只关注如何设计一个脉动阵列来执行这个操作。

为了更新您的线性代数知识,让我们记住基本的通用矩阵乘法(GEMM)运算是如何计算的,我们将在整篇文章中继续使用这个小例子:

基本的 2x2 矩阵乘法。作者视频。

这里的基本操作是什么?再看一遍动画。你看到我们总是在两个元素之间做乘法,然后累加上一次乘法的结果了吗?这种操作被称为乘累加(MACC),在硬件中实现起来相当容易。

基础体育

因此,我们需要设计一些能够执行 MACC 操作的 PE。

我之前说过,这个运算是一个乘法后面跟着一个累加。现在,在神经网络中,A 矩阵通常是该层的输入,B 矩阵表示该层的参数(其权重)。因为这些参数是恒定的,并且在我们使用神经网络预测某些东西时不会(通常)改变,所以我们实际上可以将矩阵 B 的值预加载到 PE 中,并在多次乘法中重用它们!我向你保证,这以后会更有意义。这可以通过下图很容易地描述出来(寄存器 b 将预加载相应的 b 参数):

基础体育设计。图片作者。

但还记得我们讨论过这些脉动架构如何一个接一个地级联 PE 吗?为了做到这一点,我们只需添加几条线路,让我们能够从一个 PE 到另一个 PE 共享数据:

带有传播信号的基本 PE。图片作者。

这是我们的基本 PE!首先,注意我们如何从顶部插入 b 参数,并在每个时钟周期将其值传播到将连接到底部的 PE(这在用 B 矩阵预加载脉动数组时会很方便)。第二,注意在每个时钟周期,新的输入数据 a 来自左边的 PE,与存储的权重b相乘,然后与来自上面的 PE 的部分和累加。输出部分和然后被传播到下面的 PE,而原始输入数据 a 被传播到右边的 PE。最后,为了使图尽可能简单,我没有画出控制、复位和时钟信号。

接下来,我们将看到如何使用级联来执行整个矩阵乘法!

免责声明:请记住,这只是一种可能的处理元件配置,它使用权重固定方法(权重首先预加载到 PE 中,然后来自矩阵 A 的输入数据和部分和从 PE 流向 PE)。存在用于矩阵乘法的其他 PE 设计,例如,输出稳定方法。也可以使用脉动阵列加速的不同算法可以具有更简单或复杂的 PE 设计。有关所有这些其他方法和 PE 设计的示例,请查看“参考资料”部分和文章末尾。

构建脉动阵列

让我们建立一个 PE 的 2D 数组:一个脉动数组!如前一节所述,每个 PE 将从其左侧和顶部的 PE 接收数据,并将数据传播到其右侧和底部的 PE。

2D 脉动阵列。图片作者。

为了执行整个矩阵乘法,我们将首先将整个 B 矩阵预加载到脉动阵列中(记住,我们使用的是权重固定方法)。然后,我们将从左到右传播输入矩阵 A,并且从上到下传播部分和。C 结果矩阵将从底部 PEs 的输出中获得。请看下面的动画,它通过在 2x2 脉动阵列中执行[2,2]x[2,2]矩阵乘法来说明这一过程(请注意我们实际上是如何插入 A 矩阵的转置版本的):

在加权静态脉动阵列上执行 2×2 矩阵乘法。图片作者。

注意数据如何需要以这种“步进”或移位的方式进入脉动阵列,以及如何以相同的方式获得结果。如果数据在脉动阵列中一次移动一个时钟,那么计算特定配置获得完整结果需要多少个时钟是相当容易的。如果你感兴趣,可以看看阿斯加里等人的工作,其中对方程有更详细的解释。

如果不是执行 C=AB,我们还想添加一个矩阵(C=AB+D,有时被称为扩展 GEMM)会怎样?嗯,我们只是将 D 矩阵值插入到数组顶部的 PEs 的部分和输入中!

但是如果我们的输入矩阵大于脉动数组的大小,我们该怎么办呢?这就是我们使用*铺方法的时候。*铺意味着划分我们的 A 和 B 矩阵,以便我们得到可以在脉动阵列中执行的补丁。让我们来看一个 8×8 脉动阵列(Ax、Bx 和 Cx 都是 8×8 面片)上的[16,16]x[16,16]矩阵乘法的例子:

脉动阵列上的*铺示例。作者视频。

注意:如果*铺方法生成的分区小于脉动阵列的大小(例如,因为矩阵大小和脉动阵列大小之间的除法不是偶数),则 PE 将在计算期间保持空闲。当然,我们希望在一次计算中尽可能多地使用 PE。寻找跨不同工作负载最大化 PE 使用的操作符映射技术是一个活跃的研究领域!

将其集成到完整的硬件加速器架构中

仅举一个例子,为了了解所有这些在真实用例场景中是如何协同工作的,让我们向硬件加速器添加更多的模块。

首先,我们将添加内存来存储矩阵 A(称为输入特征映射)、矩阵 B(正如我们已经说过的,权重)和矩阵 C(称为输出特征映射)。然后,我们添加一个模块(例如,一个 DMA )来在加速器的内部存储器和外部 DRAM 之间移动数据(以防矩阵太大而不适合加速器的内部存储器,如果您试图运行一个当今流行的神经网络,如 YoloV7EfficientDet-D7 ,这几乎在所有情况下都会发生)。最后,我们添加了一个控制器模块来协调数据进出加速器,以及矩阵必须如何进入脉动阵列。

基本加速器图。图片作者。

动手!

您想尝试脉动阵列模拟器,尝试不同大小的暂存区和处理元件阵列尺寸,并分析整个神经网络架构的执行情况吗?查看 Scale-SIM [2】,这是一个用于脉动阵列的 Python 模拟器,您可以在其中探索卷积或全连接层等工作负载的内部内存大小和脉动阵列尺寸之间的权衡。

欢迎在推特LinkedIn 上关注我,让我知道你对这篇文章的看法,或者给我买杯咖啡如果你真的喜欢它!

感谢阅读!

参考

如果您对本文中使用的论文和工具感到好奇,或者您想了解更多关于脉动阵列的信息,我建议您看看这些论文和视频:

脉动阵列的设计(手动或自动):

实施:

视频:

在 IPU 加速 ResNet-50 训练:在我们的 MLPerf 基准之后

原文:https://towardsdatascience.com/accelerating-resnet-50-training-on-the-ipu-behind-our-mlperf-benchmark-2cefe43ab2b2

关于高效硬件扩展、内存优化策略和性能工具的技术指南

作者:Mario Michael Krell博士、刘振英、Emmanuel Menage 和 Bartosz Bogdanski

G raphcore 工程师在 2021 年 12 月发布的最新 MLPerf v1.1 培训结果中表现出色[9],我们的 IPU-POD16 在 ResNet-50 上的表现超过了英伟达的旗舰产品 DGX A100。

图片作者。

在这里,我们将解释我们的团队如何为这个流行的计算机视觉模型实现大规模加速。在本技术指南中,我们将揭示 Graphcore 工程师使用的各种技术和策略,涵盖高效硬件扩展、内存优化、实验跟踪、性能优化等。虽然本指南主要关注 IPU [9]的 MLPerf 中 ResNet-50 的性能指标评测优化,但它提供了性能指标评测优化的一般思路,该思路也适用于其他应用和硬件。

加速 ResNet-50

对于我们在 2021 年 12 月发布的 MLPerf v1.1 结果[9],我们在 ImageNet (RN50)上实现了 28.3 分钟的 ResNet-50 训练时间,每秒 30k 图像吞吐量,在 IPU-POD16 上以 75.9%的验证精度收敛之前有 38 个时期。在我们于 2020 年开始我们的第一个 MLPerf 项目之前,ResNet-50 训练的吞吐量约为每秒 16k 幅图像,大约需要 65 个历元才能达到收敛。将这些数字加在一起,我们获得了 3.2 倍的总体改善。然后,我们将应用从 IPU-POD16 扩展到 IPU-POD256,这使我们的培训时间又提高了 7.5 倍,吞吐量提高了 12 倍。那么,我们是如何实现这种加速的呢?

我们在此过程中开发的工具在我们的公共示例中提供,并不特定于 RN50 或 MLPerf 基准。我们认为其他 IPU 开发者可能会发现它们对他们的模型有用。关键成分是:

  • 优化的工作分配和沟通
  • 优化的主机 IO 和数据布局,分布在多个主机上
  • 对权重和偏差进行实验跟踪
  • 小有效批量
  • 从 SGD with Momentum 切换到 LARS optimizer
  • 带统计缓存的分布式批量定额
  • 重新计算检查点,而不是流水线处理
  • 随机舍入
  • 优化的编译和内存配置文件

IPU-POD:专为人工智能加速至超级计算规模而打造

将应用从 IPU-波德 16 扩展到我们的 IPU-波德 256。图片作者。

IPU 硬件如何扩展机器学*应用

为了扩展我们的应用程序,必须部署许多功能。缩放时的一个主要挑战是增加的批量大小和通信,这需要时间进行数据传输和存储代码。对于本地副本,我们希望保持微批量大小尽可能大,以获得批量范数的良好统计估计,这是 ResNet-50 模型的关键部分。需要聚集每个副本的梯度,并且优化器执行其更新。

这带来了计算和通信开销。减少这种情况的一个技巧是在单个复制品上进行梯度累积,并具有更大的有效批量。通过添加更多的副本,有效的批量大小将线性扩展。尽管这种方法将保证几乎线性的缩放,但是更高的有效批量增加了获得收敛所需的历元数。因此,对于较大的系统,需要减少梯度累积,并且梯度的有效通信是必不可少的。

在我们的实验中,IPU-POD128 和 IPU-POD256 的最佳折衷方案是梯度累积计数为 2,通信量略有减少,但保持有效批量尽可能小。考虑到较大的批量,“LARS 优化器和超参数优化”中提到的更改是必要的,因为 SGD 会比 LARS 增加更多的所需时期。此外,我们过度使用了负载分布工具 PopDist,如“扩展主机-IPU 通信”中所述。通过增加具有本地数据存储的主机数量,我们提高了数据加载带宽,并确保无论使用多少加速器,数据传输都不会变慢。

硬件扩展:连接 IPU-POD64 *台

Graphcore 的 IPU-PODs 从一开始就考虑到了可扩展性,正如我们最新提交的 MLPerf 中展示的难以置信的可扩展性所示。在一个机架内,IPU 通过高带宽 IPU 链路连接直接相互连接,形成两个环。使用这些直接连接,每个 IPU-POD64 提供 10.24TB/s 的巨大 IPU 链路带宽,具有超低延迟(250ns)。在这些垂直机架内连接的顶部,IPU 跨机架连接(直接或通过交换机)以形成水*环。这意味着机架数量增加一倍会使可用带宽增加一倍以上。

图片作者。

Graphcore 通信库(GCL)旨在充分利用这些硬件特性。

IPU-POD128 和 IPU-POD256 是由多架 IPU-pod 64 建造的。单个 IPU-POD64 由 16 个 IPU-M2000 垂直堆叠而成,用 IPU 链连接形成一个 2D 环。我们横向扩展解决方案的灵活性允许我们将 IPU-pod 64 横向连接在一起,形成更大的系统。连接此类系统有两种可能的方法:直接连接(一个 IPU-M 上的 GW-link 直接连接到其他 IPU-POD64 系统上的 IPU-M 2000)或通过交换结构连接,其中所有 IPU-M 2000 上的 GW-link 连接到交换机,然后交换机将流量转发到其他 IPU-pod 64 上的正确目的地 IPU-M 2000。在这两种情况下,多个 IPU-pod 64 之间的同步通过 GW 链路发送,而不需要物理同步线路来实现更简单的横向扩展。对于我们用于 MLPerf 工作的 IPU-POD128 和 IPU-POD256,我们使用交换解决方案,因为它允许我们更加灵活,并提供更好的故障转移。

Graphcore 针对 IPU-POD128 至 IPU-POD512 的横向扩展解决方案。图片作者。

查看 IPU-POD 横向扩展拓扑的各个方面,现在我们可以了解一下实际情况。这表明,即使在现有交换结构上部署带来了所有的灵活性和强大的选项,它实际上并不像最初想象的那样需要“额外的套件”。该系统有 8 个 IPU-POD64 机架,因此我们可以称之为 IPU-POD512。仅使用两台 128 端口 100GbE 交换机就可以实现 IPU-POD512 中每个 IPU-M2000 之间所有 GW 链路的互连。

使用 Graphcore 通信库(GCL)扩展通信

为了加快人工智能模型的训练,一个想法是在许多 IPU 上复制模型,每个 IPU 处理不同的批次。处理完一个批处理后,复本使用 all reduce 共享它们从该批处理中获得的信息(渐变)。在理想情况下,如果 All-Reduce 是瞬时的,我们将在吞吐量方面实现完美的扩展:副本数量翻倍将允许我们处理两倍的训练样本。

GCL 已经实施了多项优化,支持横向扩展到单个 IPU-POD64 之外。所有模型副本内部数据交换在编译时都是已知的,并且由 Poplar 详细描述,并且假设所有集体通信、ML 模型细节和网络拓扑在编译时也是已知的,则 GCL 执行是确定性的,并且可以相应地被调度和优化。GCL 还公开了一个公共 API,用于将通信组指定为总副本集的子集,从而为我们在大型系统上执行操作提供了灵活性。对于 IPU-POD256 的更大规模,我们使用分阶段的全部缩减,其中在多 POD 系统上的张量缩减作为三个不同的操作来执行。

首先,在作为 IPU-POD256 的构造块的每个 IPU-pod 64 内的 IPU 链路上进行减少散射。Reduce 分散的输出成为在 GW 链路上运行的 All-Reduce 的输入。这在多个 IPU pod 之间交换数据元素,确保同一级别的每个副本包含相同的数据。最后,对 All-Reduce 的输出执行 All-Gather 集合操作,它再次在每个单独的 IPU-POD64 中运行,以便最终每个复制副本都包含相同的数据拷贝。

我们的实现的一个重要特征是,在 All-Reduce 中花费的时间是要共享的数据总量除以可用总带宽的函数。因为 IPU 数量加倍意味着带宽量加倍,所以全缩减的时间保持不变。Graphcore 产品的主要特点是恒定时间完全减少:它使创新者能够通过使用更多硬件来更快地进行实验,有效地减少反馈回路,最终导致令人兴奋的发现。

鉴于我们对大型系统的梯度累积计数为 2,梯度通信的任何优化都会对我们的扩展性能产生重大影响。例如,我们将不同类型和形状的张量组合在一起,一次性完成通信。此外,为了充分利用带宽,我们优化了主机和 IPU 之间的网关,以立即转发数据,从而显著降低各种应用的延迟。每个 IPU-POD64 都有自己的网关。因此,这种变化主要受益于从 IPU-POD16 到 IPU-POD64 的扩展。

三相全还原的直观表示。图片作者。

针对扩展的内存优化

尽管数据所需的内存在缩放时保持不变,但交换代码需要额外的内存。因此,例如在“其他内存和速度优化”中提到的内存优化对我们的扩展成功至关重要,特别是因为 LARS 优化器甚至比 SGD 需要更多的内存。扩展到 IPU-POD128 和 IPU-POD256 的具体优化是减少 IPU-POD 之间交换的代码大小。

将验证扩展到 IPU-波德 256

对于验证,不需要向后传递,并且在批范数层中,应用同步移动*均值和方差。因此,计算布局是完全不同的。为了不浪费图形交换的时间,我们改为应用离线评估方案,即,我们在训练期间存储检查点,然后,我们使用验证数据来评估性能。我们还保持 IPUs 的相同配置,以避免重新配置的时间。这意味着对于 POD256 的情况,我们有 128 个主机进程,其中每个进程负责一个验证文件,然后汇总结果以计算整体性能。因为我们使用的是静态图,所以即使批量大小为 1,50000 个验证图像也不能完全分割,这将是低效的。但是,对于 MLPerf 设置,需要处理所有图像,并且不能遗漏样本。因此,我们将数据填充到下一个更大的批次,然后在后处理中移除填充结果。

在 IPU 硬件上大规模加速 ResNet-50

实验跟踪

在整个项目过程中,跟踪实验、查找详细的参数配置和深入研究日志非常重要。因此,我们充分利用了通过权重和偏差进行实验跟踪的优势,并定期创建报告来与同事交流结果,并比较运行情况以找出任何潜在的差异。使实验具有挑战性的是,在低历元计数的情况下,收敛对任何变化都过于敏感。例如,将累积计数减半可以很容易地将非收敛设置转换为收敛设置。此外,实验之间有很大的差异,需要这种方法来跟踪实验。我们跟踪了超过 2600 个实验。最近,我们在我们的 CNN 知识库中扩展了我们的追踪。使用*--wandb**--wandb-project*选项,结果会立即上传,而不是等待最终结果上传。

权重和偏差报告。图片作者。

减少纪元的数量

批量常模与群体常模

实际上,人们通常在大约 90 个纪元甚至更多的时候训练他们的网络。由于 MLPerf 基准只关心训练的时间,所以有很多调整来减少这个数字。我们的目标是将数量减少到 44 个时代,甚至更少。我们最初的实现使用了组范数而不是批范数,以便更快地处理和避免样本之间的依赖性。有关讨论,请参*[1]。

对于 65 个或更多的时期,这种标准化完美地工作。然而,在微调超参数时,我们了解到需要更积极和成本更高的归一化来在期望的小历元计数中获得收敛。这意味着我们开发的支持大批量范数的工具是特定于 MLPerf 基准的,因为必须减少历元的数量。如果没有这个要求,我们可能会坚持团体规范。

每个子图对应于一种特定的归一化技术,其特征在于其各组分量共享相同的归一化统计量。在每个子图中,中间激活的张量由批轴 B、通道轴 C 和空间轴(H,W)构成。图片由作者提供,改编自[7]。

增加批量

我们最初的设置是一个超过 4 个 IPUs(智能处理单元)的流水线,复制因子为 4,用于数据并行处理和分组调度。我们使用的批量为 16。将该设置更改为 batch-norm 是一个简单的配置更改,但收敛性仍略有改善。当我们通过使用内存高效通信、限制每个 IPU 的代码内存大小以及调整管道阶段的长度来微调内存和管道阶段以获得 24 的批处理大小时,情况变得更好。尽管如此,我们还是无法达到预期的 44 个纪元。因此,我们进行了一些模拟,发现 32 的批量应该足够了。通过模拟,我们可以在 44 个时期内达到收敛,但吞吐量低于可接受的水*,我们需要进行一些调整,如“增加吞吐量”一节中所述。

小有效批量

为了获得良好的硬件加速,通常要处理大量的数据。在单个加速器上使用更多数据通常会增加 ALU(算术逻辑单元)的使用率,并确保加速器获得足够的工作负载。请注意,IPU 有一种独特的分配工作负载的方式,也可以加速小批量的工作负载。此外,梯度和优化器更新的通信可能是昂贵的,因此可以通过降低这些更新的频率来增加吞吐量,例如通过使用梯度累积。请注意,梯度累积的回报随着每次增加而递减。在我们的实验中,我们意识到较大的批量需要更多的历元用于训练,这也可以在 MLPerf 参考收敛点中看到[8]。因此,更大批量的好处可能超过速度的提高。另一方面,每个“复制品”需要 32 的最小批量大小,以使批量标准工作。

对于最佳 IPU-POD16 配置,我们最终得到 3200 的有效批量大小(16 个副本,每个副本的微批量大小为 20,梯度累积计数为 10),其在 38 个时期内收敛。为了扩展到更大的系统,我们分别减少了梯度累积计数。由于较大机器上的通信效率和优化,保持梯度累积计数为 2 就足够了。对于 IPU-POD64 系统,我们使用类似的有效批量 3840 (64 个复制品,梯度累积计数为 3)也在 38 个时期内收敛。对于 IPU-波德 128 和 IPU-波德 256,我们使用的梯度累积计数为 2,有效批量为 5120 和 10240,相应的时期为 41 和 45,直到收敛。使用更大的尺寸会增加更多的历元计数,并且是不可行的。

LARS 优化器和超参数优化

尽管正常的 ML 设置在超参数的选择中表现出一定的鲁棒性,但是 MLPerf 中的低历元计数使得收敛对任何变化都敏感。这可以通过优化器的选择得到最好的体现。众所周知,LARS 是大批量的良好优化器。在我们的项目中,我们了解到它也是一个比动量随机梯度下降(SGD)更好的优化器,在收敛之前需要更少的时间。这种好处随着批量的增加而增加。请注意,LARS 需要更多的内存和计算,但次要成本超过了主要节省。我们的第一次和第二次 MLPerf 提交之间的一个主要变化是优化内存使用和启用 LARS,这导致了很大的加速。例如,对于我们的 IPU-POD16 设置,LARS 将所需的历元数从 44 个减少到 38 个。一个关键因素是热身时期的数量。SGD 需要 5 个历元,而 LARS 只需要 2 个历元。另一个敏感的超参数是 LARS 中的权重衰减参数,将其减少一倍并调整学*速率,可将收敛速度加快多达 2 个时期。

增加产量

管道*衡

与自然语言处理模型 BERT 相比,针对 RN50 优化流水线可能具有挑战性。有许多不同的组件需要不同的代码,并且各层之间的数据大小变化很大。因此,稍微修改一下分割策略就可能对内存配置文件产生重大影响,从剩余大量内存跳到需要过多内存。此外,正如我们在 PopVision 图形分析器中发现的那样,处理负载可能非常不*衡。第四个 IPU 的处理时间是第二个的两倍,并且由于数据的内存需求,没有*衡的空间。另一方面,IPU0 不能做太多的处理,因为它有最大的激活存储。类似地,IPU1 和 IPU2 也有一些空闲时间,甚至比绿条所示的同步时间更长。由于不*衡的计算和内存需求,很难进一步改善,我们选择了不同的途径,使用重新计算方法,可以在单个 IPU 上工作,并使用分布式批处理规范来实现足够大的批处理大小。

批量为 20 的 4 个 IPU 以上的分组调度管道的 PopVision 图形分析器摘录。第三行(IPU 2)对应于最后的第 4 级。与 IPU 2 相比,IPU 1 只需要不到 60%的处理周期。图片作者。

分布式批量定额

我们的批处理规范实现是在杨树级别上融合和优化的。通过之前用于流水线设置的所有内存微调,我们意识到现在可以在单个 IPU 上将新设置的批处理大小从 6 增加到 12,而无需任何流水线操作。现在,为了达到批量定额的批量大小 32,我们只需要一个分布式批量定额。对于其他一切,正常的数据并行处理就足够了。我们将这个特性添加到我们的框架中,只需要几行代码,我们在标准化实现中聚合了多个副本的统计数据。这种方法非常有效,并且不需要太多的内存,特别是因为统计数据的向量非常小。此外,向后传递只是 IPU 之间的梯度的集合,这有助于分布式批处理规范,因此只产生单行代码。

对于 TensorFlow 1.15 中的应用程序代码,界面保持了简约。只能设置一个配置号:

对于 12 的批量大小,我们需要在至少 3 个 IPU 之间合计数据,以达到至少 32 的批量标准批量大小。为了避免 IPU-M2000 机器之间的通信,它必须改为 4 个 IPU。

重新计算

为了从分布式批处理规范中获得更好的吞吐量和更少的通信开销,我们希望增加批处理大小并将分布式批处理规范限制为两个 IPU。因此,我们利用了重新计算。由于 TensorFlow 1.15 中没有对此的原生支持,我们使用了一个编程技巧。流水线的 IPU 实现附带了一个顺序调度,可用于在多个 IPU 上共享计算图。相反,我们没有将处理分布在多个 IPU 上,而是将它们都放在一个 IPU 上。请注意,片内存储器中的代码大小几乎没有增加,但是许多中间激活没有被存储,而是被重新计算。因此,我们释放了大量内存,可用于增加批处理大小。通过将我们的 splits 设置为b1/0/relu, b1/2/relu, b2/0/relu, b2/2/relu, b3/0/relu, and b3/3/relu,我们将批量增加到 20。我们可以通过将一些优化器状态卸载到主机来使用更少的重新计算点。我们避免了这种可能性,并将所有内容都保存在内存中,因为我们通过将更多数据传送到 IPU,更好地利用了通信带宽。因此,重新计算只需要三个要素:

*衡重新计算点需要了解计算图中不同阶段的内存占用情况。为了进行微调,我们使用了 PopVision 图形分析器中的内存配置文件,以确保我们最佳地利用了内存。因此,我们在初始层有一组更密集的重新计算检查点,并保留更长的最终阶段以减少计算开销,因为对于最后阶段,前向传递永远不会重新计算。

单个 IPU 的 1472 个图块的内存利用率。它达到了每个图块的内存限制。作者使用 PopVision 图形分析器制作的图片。

用 PopVision 图形分析器创建的活性报告。我们可以看到除了最后一段之外的前向传递,然后是前向传递(内存增加)和后向传递(内存减少)的每个重新计算段的 7 次颠簸。图片作者。

扩展主机-IPU 通信

对于 ResNet-50 基准数据加载来说,预处理是工作负载中至关重要的一部分。在我们的一个实验中,我们尝试了一个基于英特尔的主机,与使用 AMD 主机相比,它的 CPU 内核更少,大大降低了我们的处理速度。因此,我们的分解主机架构对于能够为手头的应用选择正确的主机尤为重要。

获得更多传输数据的一个简单方法是减小其大小。增强的图像数据以 Int8 格式传输,然后在 IPU 上而不是在主机上进行归一化。归一化是作为一个融合操作实现的,它将数据转换为 Float16,并添加第四个带零的通道,以减少后续卷积层的内存占用。

此外,为了传输更多的数据,数据加载需要使用 Graphcore 的 PopRun 框架进行并行化[6]。我们的分析表明,对于每组两个副本,一个主机进程是最好的。每台主机都以 8 个 numa 感知节点最佳运行,每个 CPU 4 个节点。因此,对于 IPU-POD 16、64、128 和 256,我们分别使用了 1、4、8 和 16 台主机。该命令类似于:

poprun --host $HOSTS $MPI_SETTINGS --num-instances “$INSTANCES” --num-replicas “$REPLICAS” python train.py args

使用$MPI_SETTINGS 中的“*--numa-aware 1”*激活 Numa 感知。尽管主机进程是独立的 MPI 进程,但是跨多个机架创建了所有副本的计算图的组合表示。每个主机进程读取一组大小相等的独立输入文件。因此,避免了文件读取中的任何冲突。即使对性能的影响可以忽略不计,分布式读取数据也会保存在缓存中。

其他内存和速度优化

除了重新计算,我们还使用了一些优化策略:

  • 我们存储批量定额统计数据以避免重新计算。
  • 我们在 FP16 中做了权重、激活和渐变的所有计算。我们还使用随机舍入来提高收敛速度,使用半偏卷积和矩阵乘法来提高速度。我们的硬件支持随机舍入。请注意,权重更新需要对每个副本进行相同的更新,以确保权重保持一致。这是通过使用 horovod 广播
    with tf.Graph().as_default(), tf.Session(): identical_seed = hvd.broadcast( identical_seed, root_rank=0, name=”broadcast_seed”).eval()
    同步起始种子并确保当应用权重更新时 IPU 被均等地播种来实现的。这是通过
    export POPLAR_ENGINE_OPTIONS=’{“target.deterministicWorkers”:”portable”}’实现的
  • 我们通过优化 IPUConfig [5]的“availableMemoryProportion”,微调了 IPU 上用于代码的内存和用于存储激活的内存之间的*衡,使其值约为 0.15。
    config.convolutions.poplar_options[‘availableMemoryProportion’] = …

有关内存和处理优化的更多想法,请查看我们的新指南[4]。

限制

这个博客中介绍的所有特性在最新版本中都可以使用。然而,我们想指出的是,尽管所有这些技术技巧可能对您的应用程序有所帮助,但它们并不是必须的。MLPerf 基准测试带有特殊的规则和限制,不适用于实际应用。

  • 基准要求的目标精度低于最大可达到的精度。
  • 对于基准测试,5 次运行中只有 4 次需要收敛。如果有一个失败,它就会被忽略。
  • 只有超参数的子集可以被改变,并且唯一可用的优化器是具有动量的 SGD 和 LARS。
  • 目标度量是训练/收敛时间,而不是吞吐量。这可能是因为随着批次大小和累积计数的增加,处理量可以增加,但收敛时间将需要更多的时间。
  • 我们仅每 4 个时期评估一次。更高的评估频率是违反规则的。
  • 培训仅在 ImageNet 上进行。
  • 学*率计划是二次多项式计划,而不是步进或余弦学*率计划。

实际上,没有人会在 ImageNet 上将 ResNet-50 训练到 75.9%的验证准确率。更容易下载精度更高的预训练网络。

在实践中,人们可以在不同的数据集上进行更高精度的训练。但是,当在不同的数据集上训练时,为该基准选择的参数可能不会转移。此外,可能需要更大的历元计数和不同的学*速率计划。随着时代数量的增加,如果训练是从零开始,而不是用预训练的模型,那么使用群体常模(或代理常模)可能会更好。

75.9%的最高准确率对于搜索等应用来说是不够的。想象一下,你有一个像 YFCC100M 数据集这样的 100.000.000 张图像的搜索引擎,你试图使用 ResNet-50 搜索某一类图像,例如折纸。丢失 24%的相关图片对你来说可能没问题。挑战在于,因为其他类别也会被错误分类,你会得到更多不是折纸而是来自其他图像的错误分类的图像。事实上,这些错误的分类将是大多数[2]。为了实现更高的精度,值得考虑更多像 EfficientNet 这样的先进模型,它们受益于本博客中提到的一些特性。你可能还想读一下,“我们如何让 EfficientNet 更有效率” [3]。

结论

将强大的 TensorFlow 1.15 框架与 Weights and Biases、Poplar 和 PopVision 工具以及强大的 MK2 IPU 结合起来,我们成功地充分利用了处理速度和内存,并实现了令人惊叹的性能。

谢谢

非常感谢 Brian Nguyen、Godfrey da Costa(和他的团队)以及 Mrinal Iyer 为完成这项工作所付出的努力。

我们还要感谢亚历克斯·库尼亚、菲尔·布朗、斯图尔特·科内尔、多米尼克·马斯特斯、、亚当·桑德斯、霍肯·桑德斯马克、乔治·帕韦尔扎克、西蒙·朗、卢克·哈德拉斯-格里、豪尔赫·贝隆·卡斯特罗、乔治·马修以及其他许多人的宝贵贡献。

参考

[1] A. Labatie,通过代理标准化激活消除 CNN 中的批次依赖性,走向数据科学 2021

[2] D. Ma,G. Friedland,M. M. Krell, OrigamiSet1.0:用于折纸分类和难度估计的两个新数据集,arxiv 2021

[3] D. Masters,我们如何让 EfficientNet 更加高效,迈向 2021 年的数据科学

[4] 内存和性能优化指南,Graphcore

[5] 在 IPU 、Graphcore 上优化卷积和 Matmuls 的临时内存使用

[6] PopDist 和 PopRun:用户指南,Graphcore

[7] N. Dimitriou 和 O. Arandjelovic,重影标准化的新观点,arXiv 2020

[8] MLPerf 参考收敛点,MLCommons

[9] MLPerf v1.1 培训结果。ml perf ID:1.1–2040,1.1–2042,1.1–2044,1.1–2045,1.1–2065。MLPerf 名称和徽标是商标。更多信息请* www.mlperf.org。

通过 Google 云*台访问 JupyterLab 界面

原文:https://towardsdatascience.com/accessing-jupyterlab-interface-through-google-cloud-platform-e4f6e4f4896f

简单的操作指南

一个修道士在工作。图片由维基共享提供。

本文是关于如何第一次在 Google 云*台上设置的简短教程系列的一部分。这篇文章是关于如何使用交互式 web 控制台。

关于 GCP 的概况,请看我之前的文章

一个免责声明——我改编了为我们的暑期实*生写的文档,因为我认为它可能对更广泛的受众有用。我们使用由我们自己的 IT 部门构建的云环境,具有适合大型学术医疗机构的额外安全性。因此,*台的几个特征可能被修改或禁用。

如果你也为三个盾牌工作,你来对文章了!

GCP 的 JupyterLab

GCP 上可用的基本计算资源是“深度学*虚拟机”,或“DLVM”。这类似于您的个人计算机,每个人都被分配了一个(或多个)DLVMs 来开发和调试代码。

有许多方法可以访问您的云 DLVM,但最简单的入门方法之一(似乎是“默认”选项)是交互式 JupyterLab 环境。

进入项目

首先,您需要登录到适当的云项目。如果您只使用一个项目,您应该自动登录。验证项目名称是否列在屏幕顶部或“项目信息”卡下。如果没有,有一个下拉菜单来选择适当的项目。

项目名称列在 GCP 菜单的顶部。图片作者。

如果您没有登录到正确的项目,从下拉菜单中搜索并选择它。图片作者。

访问 DLVM

其次,打开 DVLM。在 web 界面中,它们列在“计算引擎”选项卡下。如果你在一个有多个用户的项目中,每个人的 DLVMs 都会被列出。

如果 DLVM 正在运行,名称旁边会有一个绿色的勾号。您可以通过打开“选项”菜单并选择适当的命令来启动/停止 DLVMs。请注意,每当 DLVM 运行时,您都会被收费,所以请考虑在当天结束时停止它。

将显示所有用户的 DLVMs。绿色复选标记表示实例正在运行。要启动/停止,请单击右侧菜单中的相应选项。图片作者。

打开 JupyterLab

访问 JupyterLab 是通过 Vertex AI 菜单完成的(不要问我为什么不在前一个选项卡下)。从右上角菜单中选择顶点 AI,进入工作台

您的 DLVMs 将再次列在此菜单下。选择打开 JupyterLab 按钮。这将在您的浏览器中打开一个新标签。

VertexAI Workbench 菜单下,从适当的 DLVM 启动 JupyterLab 。图片作者。

Jupyter 接口

JupyterLab 将使用默认编辑器启动。关于 JupyterLab,网上有很多精彩的教程,所以我在这里就不赘述了。简而言之,主编辑窗口在右边,选项菜单在左边,默认打开文件浏览器。

在左侧菜单下,您还可以访问项目附带的 Google 云存储桶列表、BigQuery 菜单、活动内核实例管理器、GitHub 接口和扩展管理器。这些都是可定制的,并且会根据您的环境的配置而有所不同。

请注意,当您以这种方式启动 JupyterLab 时,您将作为用户" jupyter "登录,在下面的菜单中可以看到的默认主目录是" /home/jupyter "。这不是 DLVM 上的 root 用户(在我们的机器上,root 用户是"ext _ last name _ first name _ email _ extension",这是您 SSH 进入 DLVM 时的默认设置)。

JupyterLab 的主菜单。主目录/ home/jupyter 的文件存储显示在左侧浏览器中。图片作者。

JupyterLab 主要用于 Jupyter 笔记本,可以通过启动器选项卡中的 Python 3 卡启动,或者通过点击左上角菜单上的蓝色图标启动。你也可以访问发射器中的终端。我喜欢使用的另一个简单选项是在支持 Python markdown 的内置文本编辑器中编辑 Python 文件,并在终端中执行它。它并不复杂,但这是一个很好的方式,只需点击几下就可以开始,坦率地说,这与在 Sublime 中编辑没有太大的不同。

Google 云*台的 JupyterLab 中的 IPython 笔记本界面。图片作者。

在谷歌云*台的 JupyterLab 中,文本编辑 Python 脚本(左)并在终端中执行(右)。图片作者。

结论

开始使用谷歌云*台的方法有很多,但 JupyterLab 界面可能是最快、最简单的。希望这些说明对你有用。请留下评论,我很乐意回答任何问题。

我相信读者会很乐意听到您对该*台的体验,以及您可以提供的任何技巧或提示。

~噢

从 Garmin 可穿戴设备获取睡眠和活动数据(2022 年)

原文:https://towardsdatascience.com/accessing-sleep-activity-data-from-garmin-wearables-bffc64866a66

为匆忙的人提供一个友好的如何提取 Garmin Venu 2 数据的指南

大约 6 个月前,我在上写了如何转化。将 Garmin 的文件放入 CSV。

从那时起,我得到了一个新的 Venu 2 Garmin 手表,有了它就有更多的数据要处理了!!特别是在左右,从我的 Garmin 可穿戴设备中清除睡眠和活动数据

和以前一样,我希望这篇文章是我在浏览 Garmin 网站时发现的缺失/过时文档的一个很好的替代品。

剧透 :我写了一个脚本来 快速处理这里所有的 Garmin 数据 。尽情享受吧!🌴 🏄

新手表==新数据!!照片由 Gerardo RamirezUnsplash 上拍摄

睡眠、活动和更多数据

在我之前的帖子中,我假设所有可用的数据只在DI_CONNECT/DI-Connect-Fitness-Uploaded-Files中找到。活力

从那以后,我发现了更多的数据!

从 Garmin 获得数据转储后(正如我在上一篇文章中所解释的),这里是DI-CONNECT的文件结构:

我的文件,PII 省略了

至少对我来说,我会仔细检查每个文件和里面的日期。就像数据转储中包含的许多文件夹一样,许多文件都是空的——部分原因是我没有使用手表的所有功能,部分原因是我的手表没有所有功能。

在适当的 git repo 中编写的所有代码都遵循以下通用结构:

下面我们将介绍每个新的 Garmin json 文件以及预期的数据。

健康档案

DI-Connect-Wellness文件夹下,我们有两个文件,一个关注健康快照,另一个关注睡眠总数据。

这些是 DI-Connect-Fitness-Uploaded-Files 之外最有趣的分析文件。

…_wellnessActivities.json

这个 json 文件包含您的 Garmin 手表上的健康快照活动的数据。运行这项活动需要静坐 2 分钟,这样你的对手就可以获得准确的生物特征读数

您需要保持静止的原因是因为众所周知的移动会导致腕戴式显示器的精度问题。

在 Garmin watch 上运行健康快照活动如下所示。

数据包括:

  • 一天中的时间
  • 心率
  • 呼吸率
  • “压力”
  • 氧饱和
  • 心率变异性

“压力”用引号括起来,因为它是一个专有的、Garmin 特有的指标,在计算方式上是模糊的

已处理的…_wellnessActivities.json 文件的快照

此外,由于该活动需要手动触发,因此它可能为空。

…_sleepData.json

这个 json 文件包含关于睡眠的数据,汇总到每个会话级别。

该 json 中包含的数据实际上是 Garmin Connect 应用程序中该屏幕上使用的数据

数据包括:

  • 睡眠各阶段的秒数(清醒、浅睡、深睡、快速眼动)
  • 睡眠期间的呼吸频率
  • 关于睡眠质量、持续时间和恢复的“分数”
  • 你夜里醒来的次数
  • Garmin 根据您的睡眠情况生成的*解和反馈

“分数”在引号中,因为它是一个专有的、Garmin 特有的指标,在计算方式上是模糊的

已处理的…_sleepData.json 文件的快照

反馈和*解专栏出乎意料而且非常有趣,因为我不确定这些数据在 Garmin Connect 应用程序中是否容易获得:

反馈和*解列的快照

用户文件

DI-Connect-User文件夹下,我们有 14 个文件集中在您的 Garmin 个人资料上

虽然有一堆文件,但有些对分析并不感兴趣——3 个是各种大小的个人资料照片,一个(...-social-profile.json)包含您的 Garmin 个人资料上显示的信息,两个文件(user_profile.json & user_profile_suica.json)只包含您的姓名&电子邮件,另一个(user_contact.json)包含您的紧急联系人。

一些文件可能有潜在的有趣信息,但对我来说没有:

  • user_reminders.json是空的,可能是因为我不使用提醒
  • user_settings.json只有 1 行长,标记了每个区域之间的 HR。我使用的是默认值(*下文)
  • 可能包含生物特征数据,如身高和最大摄氧量,但对我来说一切都是空的

要快速检查一个 json 文件,比如user_settings.json,只需执行…

file_name = os.getcwd()+'/DI_CONNECT/DI-Connect-User/user_settings.json'
with open(file_name) as file:
        j = json.load(file)
json.dumps(j)

…这让我产生了:

这样我们就有 3 个文件需要分析:

FitnessAgeData.json

这个 json 文件包含关于你的健身年龄的数据。 Garmin 将健身年龄描述为:

健康年龄是相对于你的实际年龄而言,对你健康程度的估计。

它是通过将您当前的最大摄氧量健康水*与同性别不同年龄人群的正常值……[以及您的]活动强度、静息心率和体脂百分比或身体质量指数(身体质量指数)进行比较而计算出来的

您可以在应用程序的这个屏幕中查看您的 Garmin 健身年龄。数据转储中不包括的建议…

数据包括:

  • 你的年龄,身体质量指数,和静息心率
  • 充满活力的周数、天数和分钟数
  • 根据你目前的体重/身高/性别,你的健康身体质量指数、体脂%和最大摄氧量是多少
  • 你的最大摄氧量
  • 你的整体健康状况、体重指数和体脂百分比的“年龄”

“年龄”在引号中,因为它是一个专有的、特定于 Garmin 的指标,在计算方式上是模糊的

这些读数不一定像我希望的那样每天都有(从上面的截图中你可以看到日期上的巨大差距),但肯定是一个有趣的数据集,可以在更长的时间尺度上进行探索。

水合日志文件…json

所以我目前没有在我的手表上使用补水小工具,所以我的数据有点无聊/稀疏。每当你进行一项运动时,它都会做一个记录,因为它可以估计出汗量。

水合小部件数据包含在水合日志文件中

但是,如果您这样做了,下面是您可以期望数据包含的内容:

  • 阅读时间
  • 水合来源+活动 ID
  • 水合量,活动持续时间
  • 活动期间估计的排汗量

我的补水日志快照。数值全为 0,因为我没有记录锻炼期间的水摄入量

UDSFile_…json

UDS 文件,我假设它代表“用户每日总结”,包含每日的步数、楼梯、压力和身体状况

收集的车身电池数据的快照

该文件中的数据包括:

  • 每日时间和距离功能,如totalDistanceMeters
  • 心率特征
  • awakeAverageStressLevel这样的应力特征
  • 体感电池功能类似maxBodyBattery
  • 额外的日总呼吸和 SPO2 功能

我的 UDS 日志的快照。这里有超过 100 个功能!

健身档案

这些文件都与你和你的 Garmin 进行的谨慎的身体活动有关。

不幸的是,我不使用我的 Garmin 来设定目标或计划,所以大多数这些文件对我来说是空的。

这将只留下一个包含数据的文件:

…summaryed activities . JSON

顾名思义,这些表格包含了您佩戴 Garmin 时所进行的活动的摘要。像健康快照一样,这不是一种被动的数据收集形式,因为你需要手动告诉你的手表你正在锻炼。

然而,根据您参与的活动,您可以生成以下数据:

  • 活动名称和开始时间
  • 强度分钟
  • 仰角增益/损失、行进距离和位置
  • 呼吸率统计
  • 总套数和重复数

我的汇总活动表的快照

高尔夫文件

像大多数健身文件一样,我不打高尔夫,也不使用我的手表打高尔夫,所以这些文件是空的。也许将来我会从事这项运动,并开始收集一些这方面的数据。

健身上传的文件

最终的数据宝库以. zip 文件的形式出现,而不是我们过去看到的 json。

我在之前的中已经写过关于如何读取这个 zip 文件,但是这是一个有点手动的过程(或者需要制作一个宏)。从那时起,我已经建立了一个更加程序化的方法来解决这个转换需求:

我知道我应该使用 os.subprocess,但这是移植我之前的手动流程的最简单、最容易理解的方式

把所有的放在一起

如前所述,我将所需的处理步骤组合成了一个 git repo

  1. 克隆 Git Repo

我们将在下面使用的 github 命令的起源

只需打开终端并输入:

gh repo clone adam1brownell/garmin_data

会下载我写的代码。

通过导航到目录

cd adam1brownell/garmin_data

2.访问 Garmin Connect 数据

假设您已经在本地下载了 Garmin Connect 数据和 FitCSVJar 文件,正如我在之前的帖子中所详述的,您需要做的就是运行以下命令来处理您的文件:

python parse_garmin_connect.py [connect/data/folder/location] [FitCSV/file/location]

用适当的文件位置替换[连接/数据/文件夹/位置]和[fit CSV/文件/位置]。提示:在 Mac 上,您可以将&拖放文件拖到终端,以自动复制文件位置

它应该是这样的:

上述命令可能需要一段时间,因为它正在处理 fit 文件。

但是一旦完成,你应该有几个你的 Garmin 数据的 csv 文件,容易访问和准备分析!!

一旦你能分析你的 Garmin 数据,一切皆有可能!!照片由拉兹万·苏驰Unsplash 上拍摄

希望这有所帮助,如果有人遇到错误,我很乐意提供帮助🐛或者对❓有疑问

访问 2022 年纽约市的出租车数据

原文:https://towardsdatascience.com/accessing-the-nyc-taxi-data-in-2022-8363adfda76a

关于最近的变化你需要知道的一切

图片由 Benjamin Gremler 通过 Unsplash 提供

截至 2022 年 5 月 13 日,对纽约市出租车数据的访问已发生变化。拼花现在已经成为新的默认文件格式,而不是 CSV。实际上,这意味着您需要更改代码中的两件事:

  1. 将路径更改为 S3 桶
  2. 使用dd.read_parquet()方法,而不是你常用的dd.read_csv()pd.read_csv()

这篇文章提供了变化的背景,解释了拼花文件格式的好处,并展示了对纽约市 11 年出租车数据的运行计算。

图片来自www1.nyc.gov

你多年来一直在做的事情

NYC TLC 数据集是最知名的公共数据集之一。这是为数不多的既大(> 100GBs) 又相对干净的公共数据集之一。正因为如此,许多公司将其用于演示和内部测试。十多年来,数据集一直是大数据领域的一个可靠特征。

到了周末,这种情况突然发生了变化。如果你现在尝试拨打你熟悉的read_csv电话,你会遇到一个IndexError: list index out of range:

# read in 2012 CSV data 
ddf = dd.read_csv("s3://nyc-tlc/trip data/yellow_tripdata_2012-*.csv")

这将产生如下消息:

--------------------------------------------------------------------------- IndexError Traceback (most recent call last)
 Input In [21], in <cell line: 2>() ** 1** # read in 2012 CSV data ----> 2 ddf = dd.read_csv( **3** "s3://nyc-tlc/trip data/yellow_tripdata_2012-*.csv", **4** ) File ~/mambaforge/envs/dask-dataframes/lib/python3.9/site-packages/dask/dataframe/io/csv.py:741, in make_reader.<locals>.read(urlpath, blocksize, lineterminator, compression, sample, sample_rows, enforce, assume_missing, storage_options, include_path_column, **kwargs) **728** **def** read( **729** urlpath, **730** blocksize="default", (...) **739** **kwargs, **740** ): --> 741**return** read_pandas( **742** reader, **743** urlpath, **744** blocksize=blocksize, **745** lineterminator=lineterminator, **746** compression=compression, **747** sample=sample, **748** sample_rows=sample_rows, **749** enforce=enforce, **750** assume_missing=assume_missing, **751** storage_options=storage_options, **752** include_path_column=include_path_column, **753** **kwargs, **754** ) File ~/mambaforge/envs/dask-dataframes/lib/python3.9/site-packages/dask/dataframe/io/csv.py:520, in read_pandas(reader, urlpath, blocksize, lineterminator, compression, sample, sample_rows, enforce, assume_missing, storage_options, include_path_column, **kwargs) **515** paths = get_fs_token_paths(urlpath, mode="rb", storage_options=storage_options)[ **516** 2 **517** ] **519** # Infer compression from first path --> 520 compression = infer_compression(paths[0]) **522** **if** blocksize == "default": **523** blocksize = AUTO_BLOCKSIZEIndexError: list index out of range

换成拼花地板

拼花地板已经成为纽约市 TLC 数据的新默认值。要访问数据,您需要:

  1. 将 S3 存储桶的路径改为使用文件扩展名.parquet而不是.csv
  2. 使用dd.read_parquet()方法代替dd.read_csv()
# read in 2012 Parquet data 
ddf = dd.read_parquet("s3://nyc-tlc/trip data/yellow_tripdata_2012-*.parquet") ddf.head()

作者提供的图片(为便于阅读,已截断)

Dask 是按比例读取纽约市新出租车数据的最佳方式。Dask 使您能够最大限度地提高拼花文件格式的并行读/写能力。

你也可以通过pd.read_parquet()使用 pandas,但这意味着你只能使用一个 CPU 内核来处理数据。这将使你的工作流程变得更慢,可扩展性更差。

阅读这篇文章了解更多关于 Dask 如何帮助你加速数据分析的信息。

旧*难改

如果你真的,真的,真的想使用一个较慢的并行 I/O,较少的压缩选项,没有列修剪或谓词下推的劣质文件格式😉您仍然可以访问csv_backup目录中的 CSV 数据:

# read in 2012 CSV data 
ddf = dd.read_csv("s3://nyc-tlc/csv_backup/yellow_tripdata_2012-*.csv")

请注意,与新的 Parquet 文件相比,这些 CSV 文件的并行 I/O 速度较慢,压缩选项较少,并且没有列修剪或谓词下推。如果您正在大规模工作,除非您有非常充分的理由使用 CSV,否则您通常应该使用拼花地板而不是 CSV。阅读这个博客,了解更多关于如何用 Dask 编写拼花文件的信息。

还有更好的

NYC TLC 拼花文件的唯一缺点是下载这些拼花文件需要很长时间,因为每年有 12 个非常大的分区。为了并行 IO 和更快的计算,最好将数据集重新分区到更优化的大小。

ddf = ddf.repartition(partition_size="100MB")

下面的代码演示了对 2011 年到 2021 年的 NYC TLC 数据执行 groupby 计算。这是磁盘上超过 200GB 的未压缩数据。您的本地机器不太可能有运行该分析的内存。我们将在一个有 50 个工人和 16GB 内存的卷状集群上运行我们的计算。阅读文档开始使用 Coiled。

from coiled import Cluster 
from distributed import Client 
import dask.dataframe as dd # launch Coiled cluster 
cluster = Cluster( 
    name="dataframes", 
    n_workers=50, 
    worker_memory="16GiB", 
    software="coiled-examples/dask-dataframes",
) # connect Dask to Coiled 
client = Client(cluster)

现在我们可以加载我们的数据集:

# read in all data for 2011-2021 
ddf = dd.read_parquet("s3://nyc-tlc/trip data/yellow_tripdata_2011-*.parquet") for i in range(2012,2022): 
   ddf_temp = dd.read_parquet(f"s3://nyc-tlc/trip data/yellow_tripdata_{i}-*.parquet") 
    ddf = ddf.append(ddf_temp) # repartition dataset 
ddf = ddf.repartition(partition_size="100MB").persist()

现在通过计算来运行我们的组:

%%time 
# perform groupby aggregation ddf.groupby('passenger_count').trip_distance.mean().compute()CPU times: user 526 ms, sys: 55.1 ms, total: 582 ms 
Wall time: 10.3 s passenger_count
49.0      0.000000
208.0     0.241961
10.0      0.386429
19.0      0.690000
211.0     0.970000
192.0     1.010000
254.0     1.020000
223.0     1.160000
96.0      1.195000
177.0     1.340000
33.0      1.615000
249.0     1.690000
193.0     1.740000
112.0     1.800000
97.0      1.870000
129.0     2.050000
37.0      2.160000
0.0       2.522421
47.0      2.560000
15.0      2.590000
255.0     2.953333
6.0       2.975480
5.0       3.001735
70.0      3.060000
7.0       3.288784
247.0     3.310000
58.0      3.460000
225.0     4.830000
8.0       4.950078
250.0     5.010000
4.0       5.028690
9.0       5.675410
2.0       5.869093
3.0       5.931338
1.0       6.567514
61.0      8.780000
65.0     18.520000
36.0     20.160000
Name: trip_distance, dtype: float64

拼花地板是你的新朋友

是的,这种访问更改是痛苦的,并且意味着您可能必须更新一些遗留代码。但这种改变是有充分理由的:Parquet 是一种更有效的文件格式,尤其是在处理这种规模的数据集时,最好以并行方式读取。Parquet 使您能够执行节省时间的操作,比如并行 IO、列修剪和谓词下推。

阅读我们关于使用 Parquet 优于 CSV 或 JSON 的所有优势的帖子,了解更多信息并更详细地检查上述基准。

原载于 2022 年 5 月 17 日https://coiled . io

准确性、精确性和可回忆性——再也不会忘记!

原文:https://towardsdatascience.com/accuracy-precision-and-recall-never-forget-again-33e64635780

设计有效的分类模型需要预先选择合适的分类指标。这篇文章通过一个例子向你展示了三种可能的度量标准(准确度、精确度和召回率),同时教你如何容易地记住每一个标准的定义。

为了设计一个有效的监督机器学*模型,数据科学家必须首先选择合适的指标来判断他们的模型是否成功。但是选择一个有用的度量标准往往比预期的更具挑战性,特别是对于有大量不同度量标准选项的分类模型。

准确性仍然是最受欢迎的分类标准,因为它易于计算和理解。然而,准确度伴随着一些严重的缺点,特别是对于不*衡的分类问题,其中一个类别支配准确度计算。

在这篇文章中,让我们回顾一下准确性,同时定义另外两个分类指标:精确度和召回率。我将分享一种记忆精度和召回率的简单方法,并解释精度-召回率的权衡,这可以帮助您构建一个健壮的分类模型。

除特别注明外,所有图片均为作者所有。

模型和数据设置

为了使分类度量的研究更具相关性,可以考虑构建一个模型来对*面上的苹果和橙子进行分类,如下图中的表格所示。

大多数橙子出现在桌子的左边,而苹果大多出现在右边。因此,我们可以创建一个分类模型,将表从中间分开。桌子左侧的所有东西都会被模型认为是橙子,而右侧的所有东西都会被认为是苹果。

什么是准确性?

一旦我们建立了一个分类模型,我们如何确定它是否做得很好?准确性提供了一种判断分类模型的方法。要计算精确度,只需将所有正确分类的观察值加起来,然后除以观察值的总数。这个分类模型正确地将 4 个橙子和 3 个苹果分类,总共有 7 个正确的观察值,但是总共有 10 个水果。这个模型的准确率是 7/10,即 70%。

虽然准确性因其简单性而被证明是最受欢迎的分类标准之一,但它有几个主要缺陷。想象一下,我们有一个不*衡的数据集;也就是说,如果我们有 990 个橘子,只有 10 个苹果呢?一个达到非常高精度的分类模型预测所有的观察值都是橙子。准确率是 990/1000,或者 99%,但是这个模型完全忽略了苹果的所有观察。

此外,准确性*等地对待所有的观察。有时某些种类的错误应该比其他错误受到更重的惩罚;也就是说,某些类型的错误可能比其他类型的错误成本更高或风险更大。以预测欺诈为例。许多客户可能更希望他们的银行打电话给他们检查实际上合法的可疑收费(所谓的“假阳性”错误),而不是允许欺诈性购买通过(“假阴性”)。精确度和召回率是有助于区分错误类型的两个度量,并且对于类不*衡的问题仍然是有用的。

精确度和召回率

精确度和召回率都只被定义为一个类别,通常是正类或少数类。让我们回到苹果和橘子的分类上来。这里我们将专门针对 apple 类计算精度和召回率。

精度衡量一个特定类的模型预测质量,因此对于精度计算,只放大模型的苹果一侧。你可以暂时忘记橙色的一面。

精度等于正确的苹果观察值的数量除以模型的苹果侧的所有观察值。在下面的示例中,模型正确识别了 3 个苹果,但它将总共 5 个水果归类为苹果。苹果精度是 5 分之 3,或者 60%。为了记住精度的定义,请注意 preci SI on 只关注模型的 apple SI de。

另一方面,“回忆”( Recall)衡量的是模型对某一特定类别的实际观察的效果。现在来看看这个模型对所有真实的苹果做了什么。为此,你可以假装所有的橙子都不存在。这个模型正确地识别了 4 个实际苹果中的 3 个;召回率是 3/4,即 75%。记住这个简单的助记法:rec ALL 聚焦于 ALL 实际的苹果。

想看看实际情况吗?查看随附的 YouTube 视频,观看视觉演示!

精确-召回权衡

那么,衡量精度和召回率而不是坚持准确性有什么好处呢?这些度量当然允许您强调一个特定的类,因为它们是一次为一个类定义的。这意味着,即使您有不*衡的类,您也可以测量少数类的精度和召回率,并且这些计算不会受多数类观察的支配。但事实证明,在精确度和召回率之间也有一个很好的权衡。

一些分类模型,例如逻辑回归,不仅预测每个观察值属于哪一类,还预测属于特定类的概率。例如,模型可以确定特定水果有 80%的概率是苹果,20%的概率是橙子。像这样的模型带有一个决策阈值,我们可以调整它来划分类别。

假设您想要提高模型的精度,因为避免错误地声称一个实际的橙子是一个苹果(假阳性)非常重要。你可以提高决策阈值,精度会变得更好。对于我们的苹果橙模型,这意味着将模型线向右移动。在示例图像中,更新的模型边界产生 100%的完美精度,因为所有预测的苹果实际上都是苹果。然而,当我们这样做时,回忆可能会减少,因为提高阈值除了错误的橙子之外,还会漏掉真正的苹果。在这里,回忆下降到 50%。

好吧,如果我们想提高回忆呢?我们可以通过将模型线向左移动来降低决策阈值。我们现在在我们的模型的苹果侧捕获更多的实际苹果,但是当我们这样做时,我们的精度可能会降低,因为更多的橙子也会潜入苹果侧。这次更新后,召回率提高到了 100%,但准确率下降到了 50%。

当我们调整模型的决策阈值时,监控和选择适当的精度-召回权衡允许我们优先考虑某些类型的错误,无论是假阳性还是假阴性。

结论

与标准的精确度计算相反,精确度和召回提供了判断分类模型预测的新方法。凭借苹果的精准和召回,我们专注于苹果类。高精度确保了我们的模型所说的苹果实际上是一个苹果(preciSIon = appleSIde),但回忆优先正确识别所有实际的苹果(recALL=ALLapple)。

精确度和召回率允许我们区分不同类型的错误,精确度和召回率之间也有很大的权衡,因为我们不能盲目地改善一个而不经常牺牲另一个。精确度和召回率之间的*衡也可以帮助我们建立更健壮的分类模型。事实上,在建立分类模型时,从业者经常测量并试图提高一种叫做 F1-score 的东西,它是精确度和召回率之间的调和*均值。这确保了两个度量都保持健康,并且主导类不会像它通常在准确性方面那样压倒度量。

选择合适的分类指标是数据科学设计流程中至关重要的早期步骤。例如,如果你想确保不遗漏欺诈交易,你可能会优先召回欺诈案例。尽管在其他情况下,准确度、精确度或 F1 分数可能更合适。最终,您对度量标准的选择应该与您项目的目标紧密联系在一起,一旦它被确定,选择的度量标准应该驱动您的模型开发和选择过程。

原载于 2022 年 4 月 3 日【http://kimberlyfessel.com】

Ace 系统设计访谈—分布式 ID 生成器

原文:https://towardsdatascience.com/ace-the-system-design-interview-distributed-id-generator-c65c6b568027

1.介绍

当你上传一张图片到 Instagram 或在你最喜欢的经纪应用上进行交易时,后端系统会给新创建的对象分配一个唯一的 ID (UID)。这个 ID 通常在一些数据库表中用作主键,可以用来有效地检索对象。我想你知道我要去哪里——我们如何生成 uid?

你肯定知道 SQL 中的自动递增主键。依赖这个特性的问题是显而易*的——它只能在单机数据库上工作,因为它涉及到锁定,因此不可伸缩。如果我需要 Slack、AWS、Youtube 等应用每秒数百万 uid 怎么办?在这篇文章中,我想和你分享我设计的大型 UID 生成器。

1.1 要求

当谈到 UID 生成时,区分这两种类型的 UID 是至关重要的。首先,是没有明显语义的随机 UID。第二,是顺序 UID,它包含排序等固有信息。

图一。两种类型的 UID,按作者分类

随机 UID 过滤不出有意义的信息,因此把它交给人类更安全(客户和人类是不同的!客户端是代码,它会尝试猜测其他人的 URL)。给定一个随机的 UID,很难猜测其他对象的 ID,因此提供了一些隐私。Youtube 上的视频或 TinyUrl 上的链接就是这样编码的。例如,如果我创建了一个 tinyUrl 并得到tinyurl.com/2p8u9m2d,,我很难猜出其他新创建的 Url(事实上,【tinyurl.com/2p8u9m3d】或【tinyurl.com/2p8u9m2c】并不存在)。

顺序 UID 有它自己的优点。它的固有含义是帮助应用程序组织数据。例如,在 Instagram 的 Slack/images 中,为聊天消息提供连续的 uid 是有意义的,因为我们希望保留项目排序。此外,如果 uid 不暴露给人类,那么即使不使用固有的顺序,使用顺序 uid 也完全没问题。

在本文中,我将关注顺序 uid,因为大多数百万 WPS 级别的应用程序不会向人类发布 uid。下面是系统的核心功能需求:

  • 每秒能够生成一千万个顺序 uid
  • uid 必须保留一定程度的订购信息
  • 能够根据消耗量调整发电率

不用说,系统应该是可伸缩的和高度可用的。

2.高层设计

通常在系统设计面试中,我会从访问模式和数据库模式开始。然而,我们的系统不需要任何数据库支持,稍后我会向您展示这一点。整个系统几乎是无状态的;如果一个生成器崩溃,可以重启另一个并重新开始。

2.1 API 设计

我们的 UID 生成器只有一个目的——为任何需要的人提供新的 UID。因此,它只需要以下面向客户端的 RPC 接口:

get_uid_batch(batch_size: int) -> List[int64]

为了最小化通信开销,客户端每隔大约 100 毫秒获取一批 uid,并将 uid 缓存在内存中。如果客户端崩溃,本地 uid 就会丢失,这完全没问题,因为我们有很多东西可以浪费。

2.2 高层架构

  1. 由于应用程序的任务是每秒生成数百万个 uid,我们需要许多计算机并发工作来满足需求。
  2. 我们需要某种监视节点健康和工作负载的集群管理器。如果供不应求,经理会增加更多的工人。

图二。建筑,作者的形象

2.3 控制逻辑

  1. 启动 ZooKeeper 服务和集群管理器。在实践中,监管者可以被软件的内置功能所取代,例如自动缩放容器的 Kubernetes。
  2. 默认情况下,集群管理器创建 N 个工作线程。
  3. 当创建工作者时,它向 ZooKeeper 注册并获得唯一的工作者 ID(简单的整数,例如,从 0 到 256)。
  4. 每只工蚁都对应着动物园管理员的一个短命节点。当一个工人死了,它的 znode 会被删除,ZooKeeper 会通知主管。
  5. 所有工作线程定期将它们的 CPU 负载发送给集群管理器。经理删除/添加工人以最好地满足消耗率。

3.细节

3.1 流体分解

到目前为止,我们的讨论主要集中在高级特性上,比如 API 和架构。在这一部分,我们需要最终确定 UID 格式。应该是多长时间?它捕捉到了什么信息?

流体长度

UID 长度由应用程序及其存储需求决定。我们假设外部服务每秒消耗高达 1000 万个 uid。让我们来看看排出不同长度的 uid 需要多长时间:

图 3。UID 耗尽日期,按作者列出的数字

显然,我们至少需要 56 位,以便应用程序在其生命周期内不会用完新的 uid。

UID 时间戳

我们希望 UID 是可排序的,所以它的一部分必须是某种时间戳。对于我们的应用程序,将时间戳保持在毫秒粒度就足够了。UNIX 时间戳是一个很好的起点。但是,它有 64 位,对于我们的应用程序来说太长了。为了解决这个问题,我们可以建立一个自定义的纪元(而不是 UNIX 时间戳使用的纪元,1970/1/1 0:0:0 ),并计算经过的毫秒数。

图 4。作者如何使用纪元图

那么,应该用多少位来存储时间戳呢?图 5 显示了不同时间戳大小的溢出时间:

图 5。不同时间戳大小的溢出时间,按作者分类

假设项目寿命是 20 年,我们用 40 位是安全的。

UID 附加信息

很容易让人停下来完成我们的 UID 设计。然而,无论时间戳有多精确,都无法防止 UID 冲突。两台计算机可能会生成两个具有相同时间戳的 uid。为了区分同时生成的 uid,我们必须加入新的信息。以下是我的建议,基于实践中使用的流行设计( Twitter 雪花):

图 6。UID 分解,按作者分类

  1. 工人 ID:我们可以使用分配给每台计算机的唯一工人 ID 进行区分。位数由集群中的最大工作线程数决定。
  2. 线程 ID:为了最大化吞吐量,多线程被用来利用现代多核 CPU 机器提供的并行性。为什么不是进程 ID?进程间通信的开销更大,我们希望将所有生成的 ID 放入一个共享的内存缓冲区,RPC 线程可以访问这个缓冲区。
  3. 本地计数器:即使在 20 岁的计算机上,单线程也可以在一毫秒内生成两个时间戳。因此,我们需要一个本地计数器来进一步区分两个 uid。当计数器满时,线程会在当前毫秒内休眠。

我在我的笔记本电脑上做了一个简单的实验,一台 2019 款的六核 MacBook pro。这是我实现的吞吐量(这里是代码):

图 7。单机吞吐量,按作者列出的数字

在不运行 RPC 服务器和其他沉重的东西的情况下,我的笔记本电脑可以达到大约每百万秒 40K UIDs。理想沙箱中的吞吐量惊人地高,我假设在实践中性能只会下降。根据有根据的猜测,假设一台计算机可以生成 5K UIDs。要实现 1000 万 uid/s,我们需要大约两台计算机。当然,实际上,我们可能需要更多。

现在,将所有东西放在一起,峰值性能(对于我的笔记本电脑)是用 13 个线程(4 位)实现的,每个线程有 12 位本地计数器。不包括工人 ID,我们的 uid 中至少需要 56 位。因此,使用 64 位 uid 是个好主意。

图 8。UID 细分,按作者分类

3.2 为什么不排队

有些人可能想知道使用专用队列将外部服务从 ID 生成系统中分离出来是否是个好主意。一种可能的架构如下所示:

图 9。带有队列接口的替代架构,由作者绘制

像 Kafka 这样的中间件服务提供了很好的特性,比如解耦、缓冲、重试和简单的接口。然而,在这个应用程序中不需要这些特性。我们不需要缓冲多余的 uid,因为它们可以被丢弃。系统有我能想象到的最简单的 RPC 界面,这让卡夫卡的界面看起来像火箭科学。有了卡夫卡,消费者的数量受到分区数量的限制,不方便。

在所有反对队列的理由中,这是让我相信 RPC 更好的最重要的理由。一些队列没有披露缓冲的消息数量,这使得我们的服务无法在需求上升/下降时增加/减少容量。使用 RPC,集群管理器可以更容易地监控整体工作负载。如果没有人使用 uid,一些工人将被解雇以节省资金。

4.摘要

在这篇文章中,我们设计了一个具有惊人吞吐量的分布式顺序 UID 生成器。我们深入研究了各种方法之间的技术权衡。在面试中,没有最佳答案。所有的解决方案都有优点和缺点;我们的工作是评估他们中的每一个,并根据面试官给定的限制做出最合理的权衡。

另外,祝所有庆祝农历新年的人虎年快乐!

Ace 系统设计面试:作业调度系统

原文:https://towardsdatascience.com/ace-the-system-design-interview-job-scheduling-system-b25693817950

根据我自己的经验和与其他工程师的讨论,为大规模作业调度程序设计的。

1.介绍

当限价销售订单或一些代码计划在未来运行时,您需要一个像 Apache Airflow 这样的软件,它在满足某些条件时运行任务。由于它在行业中的广泛流行,作业调度器一直是系统设计面试的热门话题之一。在本文中,我想与您分享我根据自己的经验和与其他工程师的讨论而设计的大规模作业调度器。

1.1 要求

在面试中,具体地描述系统的期望特征是很重要的。没有人能在一个小时内设计出一个羽翼丰满的系统,所以尽量缩小题目!为了讨论的简单,我将集中讨论作业调度器的核心特性:

  • 创建/删除新作业及其计划
  • 查询用户拥有的所有作业
  • 查询作业的状态(运行、失败、完成等)
  • 查询作业的执行历史
  • 对失败任务的重试支持
  • 按时执行(当作业计划在下午 1 点运行时,应该在下午 1 点左右触发)

不用说,系统应该是水*可伸缩的和高度可用的。

1.2 交通量估计

命中作业调度程序的流量在不同的应用程序中有所不同。对于内部使用的调度程序,流量很小,因为用户数量受到团队规模的限制。另一方面,面向客户端的调度程序可能会受到大量流量的轰炸(比如 AWS 中的调度程序)。在本文中,为了更好地概括,我们假设流量很大:

  • 我们预计会有数百万活跃用户。
  • *均而言,每个活跃用户拥有几十个重复性作业。
  • *均而言,一个活跃用户每周会创造几个新工作。
  • 很大一部分工作每天重复几次。一些作业以更长的时间间隔执行。

基于上述估计,我们可以得出以下结论:

  • 后端数据库应该是水*可伸缩的,因为执行历史增长很快(每天创建大约 1 亿行数据)。
  • 该系统的读取量很大,因为调度程序创建一次作业并读取多次。执行历史也是如此,用户可以创建一个条目并多次查询。
  • 我们需要一组分散的工作人员以不同的能力同时运行作业。
  • 应该复制所有关键服务来处理大流量。

2.高层设计

2.1 数据库设计

在数据库设计中,应用程序的访问模式决定了使用什么模式。让我们研究一下命中数据库的请求:

读取操作

  • 给定一个用户 ID,检索属于它的所有作业(按客户端)
  • 给定一个作业 ID,检索属于它的所有/最新执行历史(按客户端)
  • 查找计划立即运行的所有作业(由内部服务器执行)

写操作

  • 用户可以(通过客户端)创建/删除新的作业计划。
  • 工作人员将向数据库添加执行历史(通过内部服务器)。
  • 运行作业后,系统会更新作业的下次执行时间戳(由内部服务器执行)。

在我们的用例中,不使用复杂的关系查询。大多数数据访问可以描述为主键查询(例如,给定一个作业 ID,获取所有执行)。此外,强一致性和事务的问题并不是最重要的。因此,只要针对读取进行了调优,分片 SQL 和 NoSQL 数据库都可以处理系统的所有需求。为了简单起*,我将在模式讨论中使用 NoSQL (Cassandra)语言,但请记住,您可以选择其他数据库,如 Postgres 或 HBase。

模式

作业表:我们需要一个记录作业元数据的表,比如所有者、执行间隔和重试策略。记住这个表的访问模式:给定一个用户 ID,获取一些作业记录。因此,我们可以使用 UserID 作为分区键,使用 JobID 作为排序键

图一。职务表,按作者列出的数字

历史表:该表用于存储作业的执行细节。给定一个作业,可能有多个执行与之相关联。记住访问模式:给定一个 JobID,检索所有执行历史。因此,我们使用 JobID 作为分区键,使用执行 ID 作为排序键(执行 ID 可以是一个简单的时间戳)

图二。历史表,按作者分类

调度表:当然,任何作业调度器的核心特性都是按时运行作业。因此,我们需要一个数据模型,它可以很容易地根据执行时间过滤作业。下面是一个适用于少量数据的简单设计:

图 4。附表设计 1,作者图

要获得待办事项列表,我们只需每分钟运行一次这样的查询:

SELECT * FROM ScheduleTable WHERE NextExecution == "1/5/2022:08:43"

当前设计的一个大问题是每个查询都会触发一次表扫描。如果数据很大,则需要额外的机制来确保系统的可伸缩性。详情请*详情部分。

如果你有处理大规模数据库的经验,单词表扫描应该会让你惊慌,更不用说每分钟都这样做了。有没有一种不用检查每一条记录就能筛选工作的方法?是啊!如果我们简单地颠倒图 4 中的数据模型,我们会得到:

图 5。附表设计 2,作者图

注意,执行时间被转换为 UNIX 时间戳,粒度为分钟级。这意味着计划在同一分钟运行的作业将共享相同的分区键。要获得计划立即运行的作业,只需找到带有当前 UNIX 时间戳的正确分区:

SELECT * FROM ScheduleTable WHERE NextExecution > "1641082500" AND NextExecution < "1641082580"

2.2 API 设计

我们的应用程序易于使用,它只需要以下 RPC 接口:

submit_job(user_id, schedule, code_location)retrieve_all_jobs(user_id)delete_job(user_id, job_id)get_exec_history(job_id)

2.3 架构

到目前为止,我们已经为应用程序打下了坚实的基础——数据库模式、RPC 调用。现在是做一些面向服务的设计的黄金时间!

  • Web 服务:调度系统的网关。来自客户端的所有 RPC 调用都由该服务中的一个 RPC 服务器处理。
  • 调度服务:它每分钟检查一次数据库中未完成的任务,并将它们推到队列中等待执行。一旦一个任务被调度,在执行历史表中创建一个状态=已调度的条目。有了这项服务,我们保证所有的作业都及时地被推到队列中。
  • 执行服务:在这项服务中,我们管理着一大群执行人员。每个工人都是消费者,执行从队列中获得的任何作业。需要额外的簿记,以确保在工人失败时重新执行。

图 6。高层建筑,作者图

3.细节

如果您仔细阅读图 6,您可能会想知道调度服务中的主服务器或执行服务中的健康检查器的用途。在这一节中,我们将讨论这些组件的必要性以及它们的工作原理。

3.1 按计划运行任务

让我们再次检查查询语句:

SELECT * FROM ScheduleTable WHERE NextExecution > "1641082500" AND NextExecution < "1641082580"

当并发运行的作业数量较少时,查询会产生合理数量的数据。然而,如果,比方说,10 万个作业被安排在这一分钟内运行,我们当然需要更多的工人来处理来自查询的入口数据以及将消息推送到队列。

当引入多个工人时,复杂性增加了——我们如何分配数据,使得每个工人只消耗 10 万个工作中的一小部分(10%)?事实证明,一个简单的复合分区键可以解决这个问题:

图 7。具有复合分区键的计划表,按作者分类

当一行被添加到明细表中时,它会被随机分配一个碎片号。有了新的模式,在工作人员之间分配负载变得非常容易:

Worker 1: SELECT * FROM ScheduleTable WHERE NextExecution > "1641082500" AND NextExecution < "1641082580" AND shard =1 Worker 2:SELECT * FROM ScheduleTable WHERE NextExecution > "1641082500" AND NextExecution < "1641082580" AND shard = 2...

尽管额外的分区键使数据分片变得容易,但还有另一个问题——工作人员总是来来去去。不能保证所有碎片都被覆盖。问题变成了我们如何将 N 个碎片*均分配给 M 个工人,其中 M 可以随时改变?

图 8。按作者列出的详细服务日程安排图

为了确保一个完整的工作分配,我们可以借鉴 MapReduce 的一些思想,在 MapReduce 中使用一个 master 来分配和监控工人。如果一个工作节点死亡,主节点会将其工作重新发送到其他节点。使用一个附加的本地数据库,这样就不会有作业被调度两次。当作业被推送到队列中时,会在本地数据库中创建一个条目,过期时间为 2 分钟。如果记录的原始处理程序死亡,碎片被移交给另一个工作者,新的工作者将跳过数据库中存在的任务。

3.2 排队交付

引入队列有两个原因。首先,我们需要一个缓冲区来容纳高峰时间的所有未决作业。其次,它将两个服务解耦。执行服务可以在不与调度服务协调的情况下增加/减少其容量。但是,有了额外的中间件,我们必须考虑什么类型的交付最适合系统(假设队列是在 Kafka 中实现的)。

至少一次交货

在这种交付模式中,消息在消费者提交索引之前被处理。如果使用者在提交前死亡,相同的消息将由不同的工作人员再次处理。

最多一次交货

在这种交付模式下,在消费者提交了消息的索引之后,消息将在第被处理。如果消费者在完成任务前死亡,作业将不会被重新处理。

在我们的应用程序中,至少一次交付具有更高的容错性,使得在 orchestrator 失败时重试失败的任务变得更加容易。只有当 orchestrator 在一个 workers 上成功启动容器时,才会提交消息(作业)。

3.3 处理故障和重试

尽管至少一次交付保证了每个作业都被分配给一个工人,但它不能防止工人失败时作业被丢弃。为了实现真正的重试功能,引入了异步运行状况检查器来运行以下逻辑:

  1. 分配作业时,会在本地数据库中创建一个具有最新更新时间的条目。
  2. 要求所有工人刷新更新时间~10s。
  3. 运行状况检查器将定期扫描该表,查找更新时间过时(例如,超过 30 秒)的作业。
  4. 满足上述标准的作业被送回队列重新执行。

图 9。故障处理,按作者分类

3.3 数据流

有了高级设计地址中的所有皱纹,我们终于可以得出系统的数据流:

创建/删除作业/检索历史

  • 客户端向 Web 服务发出 RPC 调用。
  • 其中一个 RPC 服务器使用提供的分区键查询数据库,并返回结果

安排作业

掌握

  • 每一分钟,主节点都会创建一个权威的 UNIX 时间戳,并为每个工作者分配一个碎片 ID(请参阅详细信息)和时间戳
  • 定期检查工人健康。如果它死了,把它的工作重新分配给其他人

工人

  • 工作者用时间戳和碎片 ID 查询数据库。
  • 对于每一行,如果它尚未被调度,则将其发送到队列中(请参阅详细信息)

执行作业

管弦乐演奏家

  • 一组编排者使用队列中的消息
  • 给定一条消息,找出一个工作量最小的工人。将工作分配给工人
  • 提交索引,重复步骤 1 到 3

工人

  • 工人定期用其时间戳更新本地数据库

健康检查器

  • 扫描本地数据库大约 10 秒
  • 如果任何行在大约 30 秒内没有更新,通过将作业 ID 推送到队列来重试

4.摘要

在本文中,我们设计了一个简单但可伸缩的作业调度器。除了高层次的设计,我们还深入研究了各种方法之间的技术权衡。在面试中,没有完美的答案。所有的解决方案都有缺陷,我们的工作是评估每一个,并向面试官解释我们的权衡。

系统设计面试高手—优步/Lyft

原文:https://towardsdatascience.com/ace-the-system-design-interview-uber-lyft-7e4c212734b3

1.介绍

当谈到在城市出行时,许多人选择优步或 Lyft 等拼车应用程序。事实上,这类应用通过提供有竞争力的价格、相当短的等待时间和高可用性,让短程通勤变得非常容易。从技术角度来看,像这样的系统非常有趣,因为最近邻搜索很难。在这篇文章中,我想分享我对优步/Lyft 这样的大型拼车应用的设计。

要求

现代拼车应用程序除了提供拼车服务外,还提供复杂的功能,如拼车、拼车、实时聊天。在这篇文章中,我想保持讨论的简短,只关注核心功能—预订乘车。以下是我们系统的功能需求:

  • 用户可以请求搭车,并应与附近的司机匹配
  • 用户可以看到所有附近的司机(虽然没有选择哪一个)
  • 司机可以回答/拒绝附近乘客的请求。
  • 创建旅行时,双方都能看到对方的实时位置。

不用说,系统应该是可伸缩的和高度可用的。

交通量估计

在讨论流量之前,我们先来看看优步的一个独特之处——它的数据使用是本地的。与 Slack 或 Instagram 等 app 不同,很少需要跨区域的数据通信。如果你身在纽约,你就不能在伦敦订车。因此,位置数据和行程不会在不同的地区之间复制(当然,访问频率较低的数据,如个人资料,会在全球范围内复制)。从这个意义上说,讨论全局流量不如区域流量有意义。

点击我们系统的乘车请求数量因应用程序的受欢迎程度而异。这里,我们假设大量的区域交通用于通用解决方案:

  • 将城市按邻近区域分组。我们可能需要十几个地区来覆盖整个美国
  • 我们预计在一个地区大约有 10 万活跃司机。
  • 我们预计一个地区会有大约 100 万活跃用户。
  • 全球用户总数为 1000 万。

假设司机和乘客都发出他们的位置信息,每条信息包括经度、纬度和额外的元数据。此外,骑手会定期检查附近的驾驶员(~5s),有时会提出骑行请求。我们可以预期的 QPS 和带宽数量是:

  • 我们预计每秒大约有 20 万次位置更新/写入
  • 我们预计每秒约 20 万次查询,峰值流量处理时加倍。
  • 每个位置消息由 ID (8 个字节)、经度和纬度(16 个字节)以及其他信息(64 个字节)组成。总上传带宽略低于 88MB/s

2.高层设计

数据库设计

我们的应用程序的访问模式决定了使用什么模式。让我们研究一下命中数据库的请求:

读取操作

  • 给定一个用户 ID,检索其配置文件
  • 给定一个用户 ID,检索用户完成的所有行程
  • 给定经度和纬度,查询附近的所有司机

写操作

  • 给定一个用户 ID,更新其位置
  • 给定一个行程 ID,司机可以接受/拒绝请求

数据库模式

给定访问模式,分片 SQL 是一个很好的选择,因为没有复杂的关系查询。注意,如果强一致性不是硬性要求,这里也可以使用像 Cassandra 这样的 NoSQL 数据库。

驾驶员资料表

图一。按作者分列的驾驶员概况表

骑手档案表

图二。骑手简介表,按作者分类

行程详细信息表

图 3。旅行详细信息表,按作者分类

除了这些数据库表,我们还需要另一个高性能存储来保存频繁更新的位置数据。由于实时位置数据本质上是短暂的,将它们保存在磁盘上没有意义。一个好的替代方法是使用内存缓存,比如 Redis 或 Memcache。

缓存模式

位置真实缓存

图 4。位置真相缓存,按作者分类

当涉及到用户位置时,这个缓存是事实的来源。手机应用程序会定期发送更新以保持准确性。如果用户断开连接,其记录将在 30 秒后过期。

驱动程序邻近缓存

图 5。驱动程序邻近缓存,按作者分类

邻近缓存对于附近的驾驶员搜索至关重要。给定一个位置,我们可以使用 G eoHash 来计算它的位置键,并检索网格中的所有驱动程序。我会在细节部分详细讨论这一点。

体系结构

随着对存储什么数据有了更清晰的理解,现在是时候进行面向服务的设计了!

  • 通知服务:每当后端需要向客户端发送信息时,通知服务用于传递消息。
  • 旅行管理服务:当旅行开始时,需要该服务来监控所有各方的位置以及计划路线
  • 乘车匹配服务:该服务处理乘车请求。它会根据司机的反应(接受或拒绝)找到附近的司机并进行匹配
  • 位置服务:所有用户必须通过该服务定期更新自己的位置。

图 6。高层架构,作者图

工作流程

  1. Bob 向搭车匹配服务发送搭车请求,并希望与司机配对。
  2. 骑手匹配服务联系位置服务并找到同一地区所有可用的驾驶员。
  3. 然后,搭车匹配服务进行排名/过滤,并通过通知服务将搭车请求推送给选定的司机。
  4. 司机可以接受/拒绝请求。收到后,乘车匹配服务将向行程管理服务发送行程详细信息。
  5. 行程管理服务监控行程进度,并向行程中涉及的各方广播司机和乘客的位置。

3.细节

高层架构设计相对简单。然而,如果你仔细检查,还是有一些皱纹。例如,我忽略了行程定价、拼车等功能。在这篇文章中,我想把重点放在与位置相关的问题上,因为它们是优步/Lyft 的基础。

3.1 如何高效查找附近的司机?

最近邻搜索是一个困难的问题,我们系统的规模使得有效的查找更加困难。我们可以使用一种称为 GeoHash 的技术,将用户的位置转换为对应于图 7 中一个单元的唯一键,并将搜索限制在几个相邻的单元,而不是计算数据库中骑手和每个司机之间的距离。

图 7。位置到 GeoHash,PC credit: [活字脚本](http://Movable Type Scripts)

图 7 展示了 GeoHash 的 key 属性——键和位置单元之间的一对一映射。因此,我们可以使用以下启发式方法来快速查找驱动程序:

  1. 给定一个用户位置,从经度和纬度计算其地理哈希。
  2. 有了 GeoHash 键,很容易计算附近 8 个像元的键。(*本帖)
  3. 用全部 9 个键查询位置服务;检索这些单元格中的驱动程序。

GeoHash 的精度由密钥长度决定。密钥越长,每个单元格就越小。

图 8。geohash 密钥长度和像元大小,按作者分类

使用什么样的钥匙尺寸比较合适?实际上,密钥大小是根据驾驶员和乘客的数量迭代确定的。在我看来,一个好的起点应该是 6 码,因为它覆盖了几个街区。

图 9。根据作者的数据,6 号 GeoHash 提供了大量的覆盖面

这些单元中可以容纳的驾驶员和乘客的最大数量是有物理限制的。回到图 5,每个单元格都是 Redis 中驱动程序邻近缓存中的一个条目。

您可能想知道 Redis 能否处理这种级别的流量。如果该地区有 100 万活跃骑手,命中集群的请求数约为 20 万次写入/秒(每个用户更新其位置约 5 秒)和 2M 读取/秒(每个用户读取 9 个 Redis 键约 5 秒)。

图 10。单个 Redis 节点容量,PC 由Redis.com

即使只有一个具有 32 个线程的 AWS c5.18xlarge 节点,系统也可以处理流量。在实践中,我们可以将工作负载分布到几十台计算机上,实现大约 100M 级别的 RPS 容量。

内存限制怎么办?如果我们使用大小为 6 的 geohash,缓存中可能有 32⁶~ = 100 亿个键,这太疯狂了。然而,如果移除了(图 5)的空键,我们将永远达不到这个数量的键。实际上,缓存条目的数量受到汽车数量的限制,因为每辆汽车只能在一个单元中!因此,内存不是瓶颈。

3.2 位置更新

希望我已经让你相信了在 Redis 上托管定位服务的可行性。现在让我们来看看用户是如何更新他们的位置的。

缓存中有两个表——位置真值表和驱动程序邻近度表。位置真值表的用法很简单。用户的移动应用程序每 5 秒钟向定位服务发送一次自己的位置和用户 ID。每当需要用户的精确位置时,系统可以通过用户 ID 查询该表。

邻近表本质上更有趣。司机开着车到处走,这意味着他们经常穿过一个牢房到另一个。当后端从驱动程序接收更新时,它不知道它们过去是什么单元。因此,很难将驾驶员从他们的旧单元中移除。言外之意很明显;由于数据陈旧,同一驱动程序可能会出现在多个单元中。

图 11。Redis 中的陈旧记录,按作者分列

为了解决这个问题,我们可以为每个记录引入一个时间戳。有了时间戳,很容易过滤掉陈旧的位置数据。实际上,Redis 中的有序集合数据结构是实现这一特性的有效方法。

除了司机的位置,我们还可以在缓存中保存车辆类型、行程状态(免费、正在行驶)等信息。有了这些附加信息,就可以快速进行乘车匹配,因为可以跳过到数据库的往返行程(查询车辆信息和行程状态)。

3.3 行程记录

我们系统的另一个重要特征是行程记录。对于一次完整的旅行,我们希望存储司机所走的路线,并让客户查看。

有许多方法可以实现这一功能;最简单的方法是依靠司机报告他们的位置和行程状态。位置服务将把所有带有 in-trip 状态的位置更新批量写入数据库进行永久存储。

依赖客户端 app 是有风险的。如果客户端应用程序在旅行中丢失了所有本地数据怎么办?在重新启动之前,它不知道驱动程序的状态。为了从失败中恢复,客户端应用程序应该检查数据库中是否有任何未完成的行程,并与司机确认它们的状态。

图 11。故障恢复,按作者分类

4.摘要

在本文中,我们设计了优步/Lyft 等拼车应用的基础。特别是,我们已经详细探讨了如何实现邻近搜索。记住,面试中没有完美的答案。所有的解决方案都有缺陷;我们的工作是在给定的假设和约束条件下提出一个足够好的设计。

赢得机器学*面试——第 1 部分

原文:https://towardsdatascience.com/ace-your-machine-learning-interview-part-1-e6a5897e6844

照片由 LinkedIn 销售解决方案Unsplash 上拍摄

深入线性回归、套索回归和岭回归及其假设

介绍

这些天我在机器学*领域有几个面试,因为我已经搬到国外,需要找一份新工作。

大公司和小创业公司总是想确保你知道机器学*的基础知识,所以我用一些时间来重温这些基础知识。因此,我决定分享一系列关于在机器学*中处理面试时你需要知道什么的文章,希望它也能帮助到你们中的一些人。

线性回归

线性回归(作者图片)

当我们谈论线性回归时,我们有一组点,为了方便起*,您可以认为这些点绘制在二维*面上(x:要素,y:标注),我们希望用直线拟合这些点。

也就是说,我们想要找到通过上图中的点之间的右的直线。

我们知道,用红色表示直线的方程是这样的类型: y = ax + b* 。所以找到正确的直线意味着估计我们需要绘制直线的参数 ab

但是我们如何找到这些我们可以称之为 的参数θ = (a,b)

直观地说,这种机制很简单,我们从任何一条直线开始,反复调整它,直到找到一条更好的直线。

按迭代调整(图片按作者)

但是我们如何在每次迭代中提高对 θ = (a,b) 的估计呢?要做到这一点,我们需要找到一种方法,能够告诉每一行有多少错误。在上图中,ITER 0 线比 ITER 1 线错得更多。现在我们需要找到一种形式主义来明确这一点,即使它在视觉上是微不足道的。

这就是所谓的损失函数帮助我们的地方。这个函数,给定一条线和我们的数据集点,将返回一个数字,这个数字相当于网络产生的误差,太棒了!所讨论的损失函数被称为均方误差(MSE)

MSE(作者图片)

在此函数中,对所有点的误差进行*均,即每个点到直线的距离。事实上,如果你仔细观察括号,我们会发现实际的 y 值和预测的 y 值之间存在差异。注意,预测的 y 将是 ax + b* 的结果(其中最初的 ab 是随机取的)。**

现在我们也有了一种方法来量化我们的直线的误差,我们需要一种方法来迭代地改进参数 θ = (a,b)

为此,我们使用梯度下降算法!算法告诉我们以下列方式更新参数。

更新规则(按作者排列的图像)

然后,我们只需要计算损失函数相对于两个参数(a 和 b) 的偏导数,并设置一个学*速率α ,它将是允许我们或多或少快速收敛(从而找到最优线)的超参数。如果我们选择太低的学*率,我们可能会收敛得太慢。相反,高学*率可能不会让我们收敛。****

我们可以重复这个迭代,直到损失函数的值,然后我们的网络的误差低,在这一点上,我们会找到一条线拟合我们的点!

我们可以直观地看到这种不断更新参数以最小化损失的过程,就像通过逐步下降来寻找函数的最小值一样。

梯度下降(图片由作者提供)

多元线性回归

显然,在我们有 n 维点的情况下,线性回归可以被推广,因此具有 n-1 个特征,而不是一个。在这种情况下,数据集中的每个点将由 n-1 个分量组成。

多元线性回归数据集(图片由作者提供)

在这种情况下,点 i、的预测将按以下方式计算。

多元线性回归预测(图片由作者提供)

在这里,我们将不得不估计所有** 参数 a1,a2,..安、乙、。**

多重共线性问题

当两个或多个要素高度相关时,会出现多重共线性问题。线性回归的最大优点之一是它的可解释性。在类型为 的模型中,y = a1x1 + a2x2 我知道每当 x1 增加一个单位 y 增加 a1 个单位。这是直接从公式推导出来的。但是在 x1x2 关联的情况下,当 x1 增加一个单位时, x2 也以某种方式增加,我无法再判断 y 会如何变化!当我有了 n 的特征时,想想真是一团糟!要进行多重共线性检测,可以使用相关矩阵,通常用热图绘制。当变量相关时,热图具有更强烈的值。**

热图示例(图片由作者提供)

里脊回归

岭回归是线性回归的一种变体,只是对损失函数做了一点小小的修改。

使用的损失函数如下。

岭损失函数(图片由作者提供)

与之前看到的 MSE 不同的是橙色部分,我们称之为。惩罚由模型(直线)参数的*方和构成。所以参数 a1 越大,…,an 网络的误差越大。这样,损失函数迫使梯度下降算法找到一条具有小参数的线,所以它是一个附加约束它用来限制模型的学*能力,使其不会陷入过拟合。λ是乘法因子,是网络的另一个超参数。

套索回归

套索回归和岭很像,只是罚分略有变化。

套索损失函数(作者图片)

在这种情况下,我们有参数的模而不是*方。套索经常导致某些系数 a1,…an 为零。所以这意味着一些功能将被取消。正因为如此,我们也可以用 lasso 回归作为特征选择,来搞清楚哪些特征最没用!****

基本假设

在应用线性回归之前,我们需要了解个假设,特别是 4 个假设。

  1. ****线性:显然,必须能够用直线(或多维超*面)拟合数据。
  2. ****同方差:即残差的方差对于 x 的任何值都保持不变,用例子更容易理解。

同质性(图片由作者提供)

3.独立性:观察是相互独立的。

4.误差的正态性:残差必须近似正态分布(您可以使用 QQ 图来检查)。

优势

  1. 线性回归对于可线性分离的数据表现特别好
  2. 易于实施和培训
  3. 它可以处理过度拟合使用正则化(套索,山脊)

劣势

  1. 有时需要大量的特征工程
  2. 如果这些特性是相关的,它可能会影响性能
  3. 它对噪音很敏感。

我们来编码吧!

我之前写的一篇关于实现线性回归的完整文章可以在这里找到:*仅使用 Numpy 的线性回归和梯度下降现在让我们看看如何使用 sklearn 用几行代码实现一个简单的线性回归。***

使用 skLearn 进行线性回归

最后的想法

我以前写过一篇关于如何只用 NumPy 实现线性回归的文章,你可以在这里找到文章!线性回归是开始学*最大似然的基本算法。如果你很好地理解了这一点,那么理解像神经网络这样更复杂的算法就容易多了。

线性回归的一个演变是多项式回归,这是一个更复杂的模型,也可以适合引入更复杂特征的非线性数据集,请查看这里:https://en.wikipedia.org/wiki/Polynomial_regression

结束了

马尔切洛·波利蒂

LinkedinTwitterCV

赢得机器学*面试——第二部分

原文:https://towardsdatascience.com/ace-your-machine-learning-interview-part-2-c58526b5faba

KOBU 机构Unsplash 上拍摄的照片

使用 Python 研究分类问题的逻辑回归

介绍

在以前的文章中,我们已经看到了线性回归算法的理论和实现:

  1. Ace your Machine Learning 面试—第一部分
  2. 仅使用 Numpy 的线性回归和梯度下降

现在让我们看看如何使用线性回归的变体来解决分类问题。

逻辑回归

我们要做的是建立一个模型,输出给定输入属于某个类的概率。

假设我们的输入数据由矢量 x 表示,我们直线的参数由矢量θ 表示。我们可以通过下面的方式简单地计算通常称为 logit 的第一个分数。

Logit(图片由作者提供)

一旦我们得到这个分数,我们仍然没有能力说我们的 x 是否属于一个概率为 p 的类。我们如何得到这个概率?

假设我们处于一个 二进制分类问题 ,那么一个数据项只能属于 0 类或者 1 类

你要做的是使用一个 sigmoid 函数 来估计概率。所以我们的 logit 将是这个函数的输入。

乙状结肠(图片由作者提供)

现在让我们想象一下 sigmoid 函数在图上的表现。

Sigmoid 函数(图片由作者提供)

你可以看到在 y 轴点 0.5 处,函数不知何故分成了两半。然后我们可以说如果我们得到的分数小于 0.5,我们将把我们的 x 归类为 0 否则归类为 1 。更正式地说:

决策阈值(图片由作者提供)

我们的目标是找到θ的最佳值,这样我们就能够(几乎)正确地对每个实例进行分类。因此,正如我在线性回归案例中展示的,我邀请你重读这里的,我们再次需要一个 成本函数为我们量化模型产生的误差。单个实例的成本函数如下。

单个实例的成本(图片由作者提供)

我邀请你思考一下为什么上面的成本函数是有意义的。如果将对数的图形可视化,就更容易理解为什么这个成本函数是有意义的。

-log(x)和 log(x)(图片由作者提供)

  • x 接近 0 时,log(x) 变得非常大,因此如果模型估计正实例(实例 1)的概率接近 0,则的成本会很高。**
  • 对称地,如果模型估计一个负实例(实例 0)的概率接近 1,那么成本将非常高。

我上面显示的成本是单个实例的成本,如果我们想要整个数据集的成本,我们只需*均所有单个实例的成本。

总成本函数(图片由作者提供)

请注意,所有的父母都有一个女儿,名叫萨拉·阿蒂瓦。一部分是左边的,另一部分是右边的。车安·阿瑟的第一首节奏很快,给人一种非常复杂的感觉。

多项式逻辑回归

逻辑回归可以推广到多个类别。当给定一个输入 x 时,该模型首先计算每个类别 k 的得分 s_k(x) (类似于 logit),然后使用 Softmax 函数(也称为归一化指数)估计该特定类别的概率。

所以首先让我们计算每门课的分数。

每堂课的分数(图片由 Auhtor 提供)

和以前一样,根据分数,我们可以使用 softmax 函数计算每个类的概率

Softmax 函数(图片由作者提供)

给定每个类的概率,我们选择哪个类?当然最有可能是,所以形式上 argmax 超过所有职业

Argmax over k(图片由作者提供)

但是在多项逻辑回归中应该使用哪个成本函数?嗯,交叉熵

交叉熵(作者图片)

我们来编码吧!

现在让我们看看如何使用 sklearn 实现一个简单的逻辑回归!我想指出的是,我们将简要地看一下 sklearn 在这个实现中的基本功能,而不涉及数据集分割、预处理等。我们将为这个脚本使用众所周知的虹膜数据集

首先,我们导入必要的库。

我们现在导入数据集,并用熊猫形象化它。数据集由 4 个数字特征组成,而目标是指示花的类型的多类数。

我们将特征值分配给变量 x ,将目标值分配给 y

现在我们可以使用 sklearn 函数来预测每个类的概率,或者直接使用 predict()(基于 argmax)函数来预测类本身。

最后的想法

当一个人开始研究分类问题的机器学*时,逻辑回归可能是最重要的算法。这是一个实现起来非常简单的算法,并且在线性可分经典上表现得非常好。我们已经看到,它既可以用于二元分类,也可以用于多元分类。

结束了

马赛洛·波利蒂

LinkedinTwitterCV

赢得机器学*面试——第三部分

原文:https://towardsdatascience.com/ace-your-machine-learning-interview-part-3-af432f922aa7

肯尼·埃利亚松在 Unsplash 上的照片

使用 Python 深入研究朴素贝叶斯分类器

这是我称为“Ace your Machine Learning 访谈”系列的第三篇文章,在这篇文章中,我回顾了机器学*的基础。如果你错过了前两篇文章,你可以在这里找到它们:

简介

朴素贝叶斯(Naive Bayes)是一种用于解决分类问题的机器学*算法,之所以这么说,是因为它基于贝叶斯定理。

称为分类器的算法为每个数据实例分配一个类别。例如,分类电子邮件是垃圾邮件还是非垃圾邮件。

贝叶斯定理

贝叶斯定理用于计算导致已验证事件的原因的概率。我们在概率课程中都学过的公式如下。

贝叶斯定理(作者图片)

所以这个定理回答了这个问题:‘给定事件 B 已经发生,事件 A 发生的概率是多少?有趣的是这个公式把问题反过来了。也就是说,我们可以通过查看每次事件 A 发生时 B 实际发生了多少次来计算这个概率。也就是我们可以通过去看过去(资料)来回答原问题。

朴素贝叶斯分类器

但是我们如何应用这个定理来创建一个机器学*分类器呢?假设我们有一个由个特征个目标组成的数据集。

数据集(作者提供的图片)

因此,我们现在的问题是‘给定这些特征发生的情况下,具有某个标签 y 的概率是多少?’

例如,如果 y =垃圾邮件/非垃圾邮件x1 = len(email)x2 = number _ of _ attachments,我们可能会问:

‘给定 x1 = 100 个字符和 x2 = 2 个附件,y 是垃圾邮件的概率是多少?’

要回答这个问题,我们只需要简单地应用贝叶斯定理,其中 A = {x1,x2,…,xn}和 B = {y}。

应用贝叶斯定理(图片由作者提供)

但这种分类器不叫贝叶斯分类器,而是叫朴素贝叶斯分类器。这是因为做了一个天真的假设来简化计算,即特征被假设为彼此独立。这使我们能够简化公式。

天真的假设(图片由作者提供)

这样,我们就可以计算出 y =垃圾邮件的概率。接下来我们就来计算一下 y = not_spam 的概率,看看哪个可能性更大。但是如果你想一想,在两个标签之间,具有较高概率的那个将是具有较大分子的那个,因为分母总是相同的: P(x1) * P(x2)…*

那么为了简单起*,我们也可以去掉分母,因为为了比较,我们不关心它。

简化公式(图片作者)

现在我们要选择最大化这个概率的类,我们只需要使用 argmax

Argmax 用于分类(图片由作者提供)

文本数据的朴素贝叶斯分类器

这种算法通常用于文本数据的 NLP 领域。这是因为我们可以将文本中出现的单个单词视为特征,并且天真地假设这些单词是独立的(这当然实际上不是真的)。

假设我们有一个数据集,其中每一行都有一个句子,每一列都告诉我们这个单词是否出现在句子中。我们删去了不必要的词,如冠词等。

现在我们可以用下面的方法来计算一个新句子好坏的概率。

文本示例(作者提供的图片)

我们来编码吧!

在 sklearn 中实现朴素贝叶斯算法非常简单,只有几行代码。我们将使用众所周知的虹膜数据集,它包含以下特征。

虹膜数据集(图片由作者提供)

sklearn 中的朴素贝叶斯(图片由作者提供)

优势

从好处的角度来看,朴素贝叶斯算法有其使用的简单性。虽然这是一个基本的过时的算法,但它仍然以相当的效率很好地解决了一些分类问题。然而,其应用仅限于少数特定情况。总结:

  • 适用于许多功能
  • 适用于大型训练数据集
  • 训练时收敛快
  • 它在分类特征上也表现得很好
  • 对异常值稳健

不足之处

从弊端来看,下面要特别提一下。算法需要问题中所有数据的知识。尤其是简单概率和条件概率。这种信息通常很难获得,而且成本很高。该算法提供了问题的“简单”近似,因为它没有考虑实例特征之间的相关性。

如果一个概率为零,因为它从未在数据中被观察到,你必须应用拉普拉斯*滑

处理缺失值

您可以简单地跳过缺少的值。假设我们扔了 3 次硬币,但是我们忘记了第二次的结果。我们可以试着总结第二次投掷的所有可能性。

跳过缺少的值(作者图片)

最后的想法

朴素贝叶斯是处理机器学*时需要了解的主要算法之一。它已经被大量使用,特别是在文本数据问题上,比如垃圾邮件识别。正如我们所看到的,它仍然有它的优点和缺点,但肯定的是,当你被问及基本的机器学*时,会有一个关于它的问题!

结束了

马赛洛·波利蒂

LinkedinTwitterCV

赢得机器学*面试——第四部分

原文:https://towardsdatascience.com/ace-your-machine-learning-interview-part-4-e30b695ce63

车头拍摄

使用 Python 深入研究支持向量机

这是我的第四篇文章,致力于我开始的关于机器学*基础知识的系列,以便接近你的面试。我把以前文章的链接留在这里。

  1. Ace your Machine Learning 面试—第一部分 :深入线性、套索和岭回归及其假设
  2. Ace your Machine Learning 访谈—第二部分 :使用 Python 深入研究分类问题的逻辑回归
  3. Ace your Machine Learning 面试—第三部分 :使用 Python 研究朴素贝叶斯分类器

简介

支持向量机(SVMs)的算法直观上非常简单,尽管对于没有很强数学背景的人来说,数学可能很复杂。

与逻辑回归一样,我们希望使用一条直线或一个 n 维的超*面来分离两类点。但与逻辑回归不同,我们试图找到使边际最大化的超*面。

裕度定义为分离超*面(决策边界)与最接近该超*面的训练样本之间的距离,即所谓的支持向量。让我们看一个例子。

逻辑回归 VS SVM(图片由作者提供)

通过最大化余量,我们将找到一条线,如上例所示,它将具有很大的泛化能力。因此,它不仅要考虑拟合(或过拟合)训练数据,还要能够对新数据做出良好的预测。

目标:找到使边际最大化的超*面。大的页边距比小的页边距能让我们更好地概括。

它是如何工作的?

假设我们的正点数取值 +1 ,负点数 -1 。因此,我们可以定义描述边缘和决策边界的函数。此外,我们通过 w 定义垂直于超*面的方向。让我们用下图总结一下。

SVM(作者图片)

现在假设你是一个正点 x ,它正好位于决策边界上,需要分类。在 w 的方向上你必须走多少 k 步才能被归类为正,让我们来计算一下。

SVM 数学(作者图片)

这将让你大致了解你是如何达到利润最大化的。但是为了最大化裕量,我们只需要最小化 ||w|| 因为它在分母中。显然,我们希望最小化 ||w|| 始终牢记想要正确分类点的约束。

约束 SVM(图片由作者提供)

最后,硬边界 SVM 优化问题可以定义如下。

硬边界优化问题(图片由作者提供)

软利润 SVM

正如你可能已经猜到的,如果有硬利润的 SVM,也会有软利润的 SVM。

在这个版本中,我们允许模型犯一些错误,也就是说,让一些点位于边缘线内。这样,通过允许存在一些错误,我们可以保持一个概括得很好的决策边界。在理论层面,我们引入了由 Vladimir Vapnik 于 1995 年首次引入的所谓的松弛变量。在 SVMs 的上下文中,我们将该变量称为 C ,它是要调整的网络的超参数。在这种情况下,我们的最小化问题变化如下。

软边 SVM(图片由作者提供)

软边距 SVM 中的错误(图片由作者提供)

我们来编码吧!

使用 sklearn 实现 SVM 非常简单,让我们来看看如何实现。这里我们还使用了众所周知的 Iris 数据集,它包含以下特征。

数据集由 sklearn 以开放许可的方式提供,你可以在这里找到它

出于可视化的目的,我们将仅使用 Iris 数据集的两个特征。因此,让我们加载并标准化我们的数据。

作者图片

现在,我们可以训练 SVM,并绘制决策边界。

作者图片

SVM 结果(作者图片)

最后的想法

朴素贝叶斯是处理机器学*时需要了解的主要算法之一。它已经被大量使用,特别是在文本数据问题上,比如垃圾邮件识别。正如我们所看到的,它仍然有它的优点和缺点,但肯定的是,当你被问及基本的机器学*时,会有一个关于它的问题!

支持向量机可以做的比我在本文中报道的多得多。特别地,SVM 核使得对不可从超*面分离的数据进行分类成为可能。使用核技巧,我们可以切换到具有更多维度的另一个维度空间,并在这个新空间中对数据集的点进行分类。在本系列的下一篇文章中,我们将详细介绍如何做到这一点!😁

结束了

马赛洛·波利蒂

LinkedinTwitterCV

赢得机器学*面试——第五部分

原文:https://towardsdatascience.com/ace-your-machine-learning-interview-part-5-3de48703cd65

Unsplash 上由 Austin Distel 拍摄的照片

使用 Python 深入研究内核支持向量机

正如我在本系列的前一篇文章中提到的,我现在将继续谈论支持向量机,以及如何使用核技巧将它们用于对非线性可分数据集进行分类。

如果你错过了这个 Ace your Machine Learning 面试系列的前几篇文章,我留下了下面的链接:

  1. Ace your Machine Learning 面试—第一部分 :深入线性、套索和岭回归及其假设
  2. Ace your Machine Learning 访谈—第二部分 :使用 Python 深入研究分类问题的逻辑回归
  3. Ace your Machine Learning 面试—第三部分 :使用 Python 深入研究朴素贝叶斯分类器
  4. Ace your Machine Learning 访谈—第四部分 :深入研究使用 Python 的支持向量机

介绍

在上一篇文章中,我们看到了如何通过最大化间隔来获得良好的概括,从而将支持向量机用于分类问题。

逻辑回归 VS SVM(图片由作者提供)

如果我们有一个不能用直线(或 n 维超*面)分类的数据集,我们该怎么办?

数据集不可线性分离(图片由作者提供)

请注意,在上图所示的数据集中,我们有两个类,red 和 blue。但是没有办法用一条直线把这两个类分开。唯一的方法是使用一种“循环”函数,绿色部分描述的函数。

这就是 SVM 核仁的神奇之处。它们允许我们将数据集投射到更高维度的空间。在这个新的空间中,很容易找到一个超*面来正确划分这两个类。

从 2D 到 3D 的转变(图片由作者提供)

因此,处理非线性可分数据的核方法的基本思想是创建原始特征的非线性组合,以便使用φ函数将数据集投影到新空间。让我们来看一个将我们从 2D 空间带入 3D 空间的φ函数的例子。

φ映射(图片由作者提供)

这种方法的问题是构建这些新功能在计算上非常昂贵。这就是所谓的内核技巧帮助我们的地方。首先,我们必须找出如何解决前一章中训练支持向量机的优化问题,但是数学是非常复杂的,并且会花费大量的时间。

总而言之,我们只需要明白我们需要计算每个向量对x _ I * x _ j的点积。那么在我们的例子中,我们应该首先使用函数φ将每个向量投影到新的空间中,然后计算φ(x _ I)φ(x _ j)*

所以有两件事要做:

  • 将每个向量投影到新的空间
  • 计算新空间中向量对之间的点积

内核技巧是一个函数,它允许我们直接获得新空间中向量之间的点积结果,而不必将每个单独的向量投影到新空间中。这将节省我们大量的时间和计算。更正式地说:

内核技巧(图片由作者提供)

但是这个内核技巧函数是什么样子的呢?不要担心,你不是必须找到这个函数的人,但它们是你可以在网上找到的众所周知的函数。让我们来看看最著名的高斯核或者也叫径向基函数

高斯核(图片由作者提供)

其中 y 为待优化的自由参数。

术语核可以被解释为一对例子之间的相似性函数。负号将距离度量转化为相似性得分,并且由于指数项,所得的相似性得分将落在 1(对于完全相似的示例)和 0(对于非常不相似的示例)之间的范围内。

我们来编码吧!

首先,让我们使用 xor 函数创建我们的线性不可分数据集。

线性不可分数据集(图片由作者提供)

现在我们可以使用参数kernel =‘rbf’训练一个 SVM,其中 RBF 代表径向基函数。我们可以看到分类器创建的决策边界。

决策界限(图片由作者提供)

您可以看到,SVM 能够使用 rbf 内核正确地分离这两个类!

如果我们增加 gamma 的值,我们将增加训练数据对决策边界的影响。因此过高的 gamma 将产生决策边界,这些边界将形成我们训练数据的一种轮廓,从而失去泛化能力

过度拟合(图片由作者提供)

最后的想法

在本文中,我们看到了内核支持向量机背后的理论以及如何使用 sklearn 实现它们。我们看到了输出如何随着 gamma 参数的变化而受到影响,这为训练集数据提供了更多的权重。

SVM 核长期以来一直是包括计算机视觉在内的许多领域中机器学*的艺术状态。它们今天仍然被广泛使用,所以了解它们是很重要的!我希望这篇文章对你有用。如果是的话,就跟着我一起看这个《王牌你机器学*面试》系列的下篇文章吧!😁

结束了

马赛洛·波利蒂

LinkedinTwitterCV

赢得机器学*面试——第六部分

原文:https://towardsdatascience.com/ace-your-machine-learning-interview-part-6-5f0d84e435a1

迪伦·吉利斯在 Unsplash 上的照片

使用 Python 深入决策树

今天我继续我的“Ace your Machine Learning Interview”系列的第六篇文章,讨论决策树!

如果您对本系列之前的文章感兴趣,我在这里留下了链接:

  1. Ace your Machine Learning 面试—第一部分 :深入线性、套索和岭回归及其假设
  2. Ace your Machine Learning 访谈—第二部分 :使用 Python 深入研究分类问题的逻辑回归
  3. Ace your Machine Learning 面试—第三部分 :使用 Python 研究朴素贝叶斯分类器
  4. Ace your Machine Learning 访谈—第四部分 :深入研究使用 Python 的支持向量机
  5. Ace your Machine Learning 访谈—第五部分 :深入研究使用 Python 的内核支持向量机

简介

我们现在已经到了引入决策树的时候了。让我们先说这个算法受到那些高度重视模型的可解释性的人的喜爱。也就是能够解释机器学*模型为什么会给出某个输出结果。想象一下你去银行申请抵押贷款。你的抵押贷款被拒绝了。然后你问为什么抵押贷款被拒绝给你。如果银行家回答你,“嗯……我不知道,电脑显示抵押贷款被拒绝了,所以我什么也做不了”,那就不太好了。这就是使用像神经网络这样的机器学*算法会发生的事情。相反,使用决策树,银行家将能够给你确切的原因。你的抵押贷款被拒绝有三个主要原因:(1)你的工资(2)你的年龄(3)你的历史。

我想马上告诉你,这个算法虽然用起来很简单,但并不是很'强大',它很容易导致数据过拟合。但是我们将在后面看到如何用一种组装方法来改进它。

决策图表

当我想到决策树时,我总是想象有一个数据集,为了简化可视化,只有两个特征,并像切馅饼一样切这个数据集。

只有您可以制作的切片必须*行于作为轴的特征。

用决策树剪切(图片由作者提供)

在上图中,我们有一个由几个点组成的二维数据集。这些点中的每一个都与一个类别相关联:三角形、圆形或十字形。决策树一次进行一次切割,目的是将每个特定类别的点隔离在一个空间中。这样,在我们必须对一个新点进行分类的推断时刻,我们只需要看到它将被放置在哪个空间中,我们就可以立即对它进行分类。

更详细

但是这些削减意味着什么呢?让我们考虑特征 1 的第一个切割,绿色切割。假设特征 1 是虹膜数据集的花瓣长度特征。然后在轴的 f1 点把空间分成两部分的绿切简单的问“ 你的花瓣长度值是大于还是小于 f1? “之后,我们将询问相同类型的问题,但针对特征轴 2 上的另一个值。同样的事情也发生在特征 1 上,蓝色切割等等…

最终,我们将会在每个点自己的子空间中对其进行正确的分类。

这就是模型的可解释性的来源!当我们对一个新的数据项进行分类时,我们所做的就是回答一系列这样的问题。当一个点被归类为某个标签 A 时,我们将完全能够说出原因!

为了便于可视化,这些问题以树的形式表示,为了对数据进行分类,我们必须从上到下遍历树。

决策树问题(图片由作者提供)

这些类型的树不一定是二进制的,它们也可以是 d 进制的,但是库的实现经常使用二进制的树,例如 sklearn。

如何找到最佳切工?

现在出现的问题是“但是我应该在哪个特征上进行第一次切割,我应该在那个特征上进行切割的值是多少?”

从树根开始,分割产生最大信息增益(IG) 的特征数据

基本上,我们从树中的一个节点开始,首先从根节点开始。每次我们进行分割(剪切)时,数据集中的一些数据将进入该节点的左侧子节点,一些数据将进入右侧子节点。如果这些子节点中的一个现在包含来自我们的数据集的数据,这些数据都具有相同的标签,我们将说该节点是纯的。否则,我们将继续使用其他拆分来拆分节点中的剩余数据集点。一个纯节点被称为树中的一片叶子。尽管一个节点不是纯的,它也可以变成一片叶子。在这种情况下,与这个节点相关联的标签是它包含在其中的多数类的值。

因此,如果一个叶子包含 10 个标签为 A 类的数据项,那么这个叶子的值将是 A。但是,如果一个叶子包含 8 个标签为 A 的数据和 2 个标签为 B 的数据,那么这个叶子的值仍然是 A。

决策树分类

所以现在在推理的时候,当我们被输入一个标签未知的数据项时,我们只需要遍历树,看看我们在哪个叶子上结束。我们将相应地对新数据项进行分类。

什么是纯洁?

我们直观地理解,我们做这些切割或分割是为了增加每个节点的纯度,也就是说,在每个节点上有一个单一类别的数据。但是纯度或者更确切地说杂质是如何被正式描述的呢?通常,有两种方法,我们可以使用熵或者基尼系数。

数学中的杂质(作者图片)

在每次拆分时,我们都希望减少每个节点的杂质。然而,我们也可以说,随着每一次分裂,我们希望增加信息增益。也就是说,在每次分割之后,我将拥有越来越多的关于节点的信息,并且我将越来越确信我对它进行了正确的分类。所以我们可以说,我们想要创建一个决策树,目标是最大化信息增益(IG)

DT 中的信息增益(图片由作者提供)

过度拟合

决策树没有被广泛使用,因为它们容易过拟合。事实上,考虑到您可以对任何类型的数据集进行分类,您只需进行连续的分割,直到您为输入数据的每一个点创建了一个节点叶。显然这样的 DT 会有很差的泛化能力。那该怎么办呢?我们可以设置正则化参数。例如,我们可以说树的深度不应该超过 5 分,这样我们可以避免过度拟合。最常*的参数如下。

  • 树的最大深度
  • 最小样本分割:一个节点在被分割之前必须拥有的最小样本数
  • 最小样本叶:一个叶节点必须拥有的最小样本数

另一种广泛使用的方法是 后剪枝 。一旦树被创建,我们去剪一些叶子或子树,所以我们将有一个模型,将有更大的泛化能力。

DT 中的后期剪枝(图片由作者提供)

我们来编码吧!

像往常一样,我们将使用虹膜数据集。数据集由 sklearn 在开放许可下提供,可以在这里找到。数据集如下。

虹膜数据集

出于可视化的目的,我们将仅使用 Iris 数据集的两个特征。因此,让我们加载并标准化我们的数据。虽然 DT 不需要特征缩放(酷!)

输入数据

现在,用 2 行简单的代码,我们将创建和适应 oud DT 模型。我们将绘制决策边界,以查看模型是否有效,是否能够对我们的数据进行分类。

一个非常酷的功能是让你绘制整个决策树,这样模型就不是一个黑盒,但你可以知道它背后发生了什么。

决策树(图片由作者提供)

最后的想法

我们来总结一下决策树的特点。

优点:

  1. 清晰的可视化:算法易于理解、解释和可视化。DT 的输出很容易被人理解。
  2. 决策树看起来像 if-else 语句,容易理解
  3. 用于回归和分类
  4. 可以处理分类变量和连续变量
  5. 自动处理缺失值
  6. 对异常值稳健
  7. 训练很快
  8. 不需要特征缩放。

缺点:

  1. 它通常会导致过度拟合。为了拟合数据(即使是有噪声的数据),它会不断生成新的节点。
  2. 它不稳定。添加新的数据点会导致整个树的重新生成。
  3. 不适合大型数据集。树可能长得太复杂,导致过度拟合。

😁

结束了

马赛洛·波利蒂

LinkedinTwitterCV

赢得机器学*面试——第七部分

原文:https://towardsdatascience.com/ace-your-machine-learning-interview-part-7-2688de34805f

Unsplash空中聚焦拍摄的照片

使用 Python 研究硬投票分类器的集成学*

我们来到了我的“Ace your Machine Learning Interview”系列的第七篇文章,在这篇文章中,我回顾了机器学*的一些基础知识,希望对你面对下一次面试有所帮助!😁

如果您对本系列之前的文章感兴趣,我在这里留下了链接:

  1. Ace your Machine Learning 面试—第一部分 :深入线性、套索和岭回归及其假设
  2. Ace your Machine Learning 访谈—第二部分 :使用 Python 深入研究分类问题的逻辑回归
  3. Ace your Machine Learning 面试—第三部分 :使用 Python 深入研究朴素贝叶斯分类器
  4. Ace your Machine Learning 访谈—第四部分 :深入研究使用 Python 的支持向量机
  5. Ace your Machine Learning 访谈—第五部分 :使用 Python 深入研究内核支持向量机
  6. Ace your Machine Learning 面试—第六部分 : 使用 Python 深入决策树

简介

集成学*是一种允许你一起使用多个预测器、分类器或回归器的方法。通过这种方式,您可以基于各种机器学*模型的知识创建一个更健壮的系统。

如果你仔细想想,当我们对某事犹豫不决时,这是我们人类通常会做的事情。我记得《生活大爆炸》系列中有一集,谢尔顿还没有决定是买 Xbox 还是 PlayStation。然后,他询问朋友的意*,希望得到大多数人的支持,并据此做出决定。我把视频留在这里给你!

Ensembling 方法做的是同样的事情。如果必须对一个点进行分类,它会征求几个分类者的意*,并采用大多数结果。(多数的使用并不总是如此,但却是最常*的)

通用集成学*

所以我们已经知道了如何构造一个集合方法。例如,我们训练几个分类器,然后采用多数投票来分类一个新实例。

下图很好地总结了这一点。

集成学*架构(图片由作者提供)

从技术上来说,当我们处理二元分类时,我们说我们在使用多数表决。另一方面,当我们做多类分类时,我们说多数投票。基本上你实际做的是使用模式函数,它在统计中从列表中取出最频繁的元素。

寻找多数的模式(作者图片)

但是这些 C1,C2,…,Cn 量词是什么样子的呢?他们可以是你喜欢的分类器,重要的是,你然后分组,并在一个函数中使用他们的预测,比如多数投票。例如,我们可以使用逻辑回归、SVM 和决策树。

整体方法示例(图片由作者提供)

但是,除了在集成方法中使用所有不同的算法,我们可以总是使用相同的算法吗?答案是肯定的!

装袋、粘贴和随机森林

到目前为止,我们总是使用我们的整个数据集,并用它来训练不同的算法,然后我们将这些算法组合成一个集成方法。

我们可以做的另一件事是始终使用相同的算法,例如我们可以使用三个支持向量机,但是每个 SVM 将在初始数据集的不同子集上绘制。 子集可以是数据集中所有记录的子集,也可以是特征(保留所有记录)的子集。最后,我们像往常一样对预测进行多数投票。

如果我们有 900 条记录的训练集。我们可以从 300 条记录中随机抽取一个子集用于每个 SVM。请注意,如果我们对这个子集进行重复,我们将使用一种叫做打包的方法。否则,不重复,称为粘贴

您曾经使用过或*过使用基于装袋或粘贴的组装方法吗?我打赌你有。随机森林

我们在上一篇文章中提到,通常在集成方法中使用决策树(DT)算法来提高其鲁棒性。而只由一棵决策树组成的ense bleng 被称为随机森林,因为它是一种广泛使用的算法,性能非常好。

我们已经提到,DT 总是试图在它找到的最佳特性上进行分割。另一方面,一个随机森林在众多 DT 中实例化一个时,只给它分配特征的一个子集。因此,DT 必须只在该特征子集内搜索最佳分割。

多余的树

有一个随机森林的实现,允许更快的训练,但增加了噪声。在这种情况下,DT 的每个特征除了从特征的随机子集中提取之外,还将在随机施加的阈值上进行分割。因此,它们非常快,我们可以同时实例化多个 DTs。额外的树以更大的偏差换取更低的方差,训练起来更快。

我们来编码吧!

让我们首先来看看 3 种不同算法在 Iris 数据集上的结果。数据集由 sklearn 在开放许可下提供,可以在这里找到。数据集如下。

我们将使用这三种算法:逻辑回归决策树分类器近邻分类器

此外,对于第一次和最后一次,我们将使用标准定标器进行一些数据处理。为了方便起*,我们将算法和定标器放在一个 sklearn 管道中。

输入数据

每个算法和管道将使用交叉折叠验证进行 10 次评估。

我在下面列出了我的算法:

  • Logistic 回归:ROC AUC:0.92-STD:0.15
  • 决策树:ROC AUC:0.87 STD:0.18
  • KNN:ROC AUC:0.85 STD:0.13

让我们看看我们能否在多数投票制下做得更好。我们首先用下面的方式定义一个名为 MajorityVotingClassifier 的类。我们只需要继承 BaseEstimator 和 ClassifierMixin 这两个类,就可以继承常*的估计器功能,比如 get/set_params 函数。

现在我们只需要实例化一个新的 MajorityVotingClassifier 类型的分类器,并将其添加到我们已经比较过的分类器列表中。

让我们看看取得的成果。你的可能会和我的略有不同。

  • Logistic 回归:ROC AUC:0.92 STD:0.15
  • 决策树:ROC AUC:0.87 STD:0.18
  • KNN:ROC AUC:0.85 STD:0.13
  • 多数投票:ROC AUC 0.98 STD:0.05

你可以看到,这一次多数投票成功地超过了单个分类器几个百分点。

因此,通过利用较弱的分类器,我们能够创建一个达到 98%分数的分类器!

最后的想法

合奏法通常用于像 Kaggle 或类似的比赛,有时可以让你赢得额外的几个百分点。另一方面,它在工业中并不总是有用的,因为通常不值得为了性能上的小改进而训练多分类器,所以人们必须有意识地使用这种方法。

我自己用它在名为evalita 2020的 NLP 竞赛中赢得了最佳系统奖,在该竞赛中,我基于集成技术创建了一个分类器。你可以在这里阅读更多关于我开发的做姿态检测的系统。😁

结束了

马赛洛·波利蒂

LinkedinTwitterCV

赢得机器学*面试——第八部分

原文:https://towardsdatascience.com/ace-your-machine-learning-interview-part-8-a9b94b8ed468

女同胞Unsplash 上拍照

使用 Python 从头开始使用 AdaBoost 进行集成学*

在我的系列文章“Ace your Machine Learning Interview”中,我继续谈论集成学*,特别是,我将重点关注 Boosting 算法,并特别提到 AdaBoost 。我希望我回顾机器学*基础知识的这一系列对你面对下一次面试有用!😁

如果您对本系列之前的文章感兴趣,我在这里留下了链接:

  1. Ace your Machine Learning 面试—第一部分 :深入线性、套索和岭回归及其假设
  2. Ace your Machine Learning 访谈—第二部分 2:使用 Python 深入研究分类问题的逻辑回归
  3. Ace your Machine Learning 面试—部分 3:使用 Python 深入研究朴素贝叶斯分类器
  4. Ace your Machine Learning 访谈—第四部分 :深入研究使用 Python 的支持向量机
  5. Ace your Machine Learning 访谈—第五部分 5:使用 Python 深入研究内核支持向量机
  6. Ace your Machine Learning 面试—第六部分 :使用 Python 深入决策树
  7. Ace your Machine Learning 面试—第七部分 :使用 Python 研究硬投票分类器的集成学*

介绍

我们在上一篇文章中讨论了什么是集成学*,我们已经看到并实现了基于多数投票的简单集成方法。

今天,我们通过特别参考自适应增强或 AdaBoost 来更详细地讨论一种称为 Boosting 的集成方法。你可能以前听说过这种算法,例如,它经常被用来赢得 Kaggle 比赛。

AdaBoost 的基本思想最早是在罗伯特·e·沙皮雷的论文http://rob.schapire.net/papers/strengthofweak.pdf中陈述的。

这个想法是以一种组合的方式使用各种 ML 算法,这些算法被称为弱学*器,因为它们本身不是很好,它们只能比随机猜测好一点。通过依次使用这些弱学*器,可以获得非常强的结果。

最初的 AdaBoost 想法

按照最初的设想,增强最初是基于我们已经看到的叫做粘贴的技术。

因此,实现了几个弱学*器,并且每个弱学*器在训练集数据的子集上被训练,而没有替换。我们将称为 wl_1、wl_2、…、wl_n 的弱学*器被顺序训练,并且每个 wl_i+1 在训练集的随机子集上被训练,来自 wl_i 的 50%的错误分类数据点被添加到该训练集中。通过这种方式,错误分类的数据点被赋予了更大的权重。

最后,他们会将所有落后的弱学*者合并成一个多数投票函数。

adaboost 算法

基本思想保持不变,但现在 AdaBoost 算法略有不同。首先,不再使用粘贴,而是在整个可用的训练集上训练每个弱学*者。此外,使用另一种机制来给予被先前的弱学*者错误分类的点更多的重要性。弱学*者 wl_i+1 将简单地给 wl_i 的错误分类的点更多的权重,给良好分类的点更少的权重。

加权误分类数据点(图片由作者提供)

在实现这个算法之前,让我们看一下伪代码来了解一下。

伪代码 Adaboost(图片由作者提供)

我们来编码吧!

所以首先我们初始化两个数组 yy_hat ,它们将是+1 和-1 的二进制向量。这些将代表真实的类和预测的类。之后,我们创建一个布尔列表,每个条目告诉我们预测是否正确。

现在让我们初始化权重。首先,每个数据点的权重是相同的,因为我们有 10 个数据点,每个数据点的权重是 0.1。

使用这些初始权重和预测,我们继续计算误差和系数α,我们将需要计算伪代码中所示的新更新的权重。

现在我们准备计算新的权重,然后对它们进行归一化。注意,根据预测是正确还是不正确,我们有两个不同的公式来更新权重。

现在我们在第二步中有了新的权重。你可以选择做 m 步,把所有的东西放在一个 for 循环中。

幸运的是,各种库已经有了更有效的实现。所以让我们看看如何使用 sklearn 来使用 AdaBoost!

以下虹膜数据集由 sklearn 在开放许可下提供,可以在这里找到。

首先,我们导入数据,并将其分为训练集和测试集。注意:为简单起*,我们将在该数据集中仅使用两个要素。

现在只需几行代码,我们就可以创建一个基于 500 个简单决策树的 AdaBoost,每个决策树都有 max_depth = 1 。我们看到我们得到了比仅仅使用决策树更好的结果。

就是这样!通过几个简单的步骤,您可以创建 AdaBoost 算法并获得您的预测。

最后的想法

所以在关于集成学*的第二篇论文中,我们看到了一种叫做 AdaBoost 的新算法。所谓的弱学*者是按顺序训练的,这被认为是不好的,因为这种顺序训练会浪费我们很多时间。然后,我们将能够通过关注未满足的情况,使每个预测器纠正其前任。所以新的预测器更关注疑难病例。对于新的预测因子,我们增加了疑难病例的权重。

关注我的“Ace you 机器学*面试”系列新文章!😁

结束了

马赛洛·波利蒂

LinkedinTwitterCV

赢得机器学*面试——第九部分

原文:https://towardsdatascience.com/ace-your-machine-learning-interview-part-9-2fd782b4bb8

使用 Python 深入研究混淆矩阵的性能评估指标和热图可视化

摄于 Unsplash 上的 Jopwell 系列

在这个“Ace your Machine Learning Interview”系列的这篇新文章中,我开始讨论一个不同的话题。我不会描述一种新的机器学*算法,而是向你展示如何评估一种算法是否工作良好。知道如何很好地评估一个 ML 系统和开发系统本身一样重要。

我希望你在处理下一次面试时会发现它很有用!😁

介绍

知道如何评估机器学*算法是非常重要的。如果我们不能判断算法的输出是好是坏,我们该如何改进我们的算法呢?有许多指标,有时很难浏览它们。你可能听说过类似于 ROCAUC 的缩写,或者你可能听说过 PrecisionRecall 以及其他指标。但是它们是什么,应该如何恰当地使用它们呢?

这些用于评估 ML 算法的各种度量可以从混淆矩阵中导出,混淆矩阵是算法预测我们的数据集中的标签有多好的一种“总结”。

在我参加的最后一次面试中,特别是在计算机视觉领域,我被要求解释什么是混淆矩阵,以及如何使用 Python 在实际练*中实现它。所以我决定写这篇文章来和你分享我的经历。

我也想给你一个建议,当你面临面试的时候,好好重温一下机器学*的基础知识。通常招聘的公司更感兴趣的是知道你能掌握机器学*的主要概念,而不是知道最新和最深奥的神经网络架构是什么。

所以我想谈谈如何阅读混淆矩阵,以及如何使用 Python 用几行代码实现它。

混淆矩阵

先说最简单的情况。假设你正在训练任何分类器:它可以是基于逻辑回归或朴素贝叶斯或任何其他你想要的算法的分类器。

给定输入的分类器只需说明该输入是肯定的还是否定的(狗或猫是同一个东西)。首先,你要做的是计算出这个分类器错误输出了多少次,它猜对了哪些点

然后我们可以开始计算他出错的次数。也就是说,它应该预测为正但预测为负的所有时间,以及它应该预测为负但预测为正的所有时间。然后我们也感兴趣的是算法给出了多少次正确的输出。也就是它正确预测了多少次正反。

为了避免混淆,简单地在一个被称为混淆矩阵 x. 的表格中总结所有这些值,行代表实际标签,列代表预测标签

困惑矩阵(图片由作者提供)

真阳性(TP) :分类器正确预测阳性。:分类器预测患者有肿瘤,是真的!

真阴性(TN): 分类器正确预测阴性。示例:分类器预测患者没有肿瘤,事实上患者是健康的。

假阳性(FP): 又称1 型错误。 分类器预测为阳性,但要预测的标签为阴性。:分类器预测患者患有癌症,但实际上是健康的。

假阴性(FN): 又称2 型错误。 分类器预测为阴性,但待预测的标签为阳性。示例:分类器预测患者没有肿瘤,而他有!

让我们来看一个如何在 Python 中使用 sklearn 计算混淆矩阵的例子。

以下虹膜数据集是 sklearn 在开放许可下提供的,在这里可以找到

首先,我们将下载数据并且像往常一样通过使用 sklearn 函数将分割成训练和测试集

from sklearn import datasets
import numpy as np
from sklearn.model_selection import train_test_split

iris = datasets.load_iris()

x = iris.data
y = iris.target

x_train, x_test, y_train, y_test = train_test_split(x,y, test_size = 0.3, stratify = y)

现在用你喜欢的分类器,在训练数据上训练它。在这种情况下,我将使用简单的逻辑回归

from sklearn.linear_model import LogisticRegression

lr = LogisticRegression()
lr.fit(x_train, y_train)

现在我们已经训练了我们的算法,剩下的就是对测试集进行预测。

predictions = lr.predict(x_test)

现在我们有了计算混淆矩阵所需的一切,从而对算法产生的错误有了更清楚的了解。为了计算混淆矩阵,我们只需要实现这两行代码。

from sklearn.metrics import confusion_matrix

cf = confusion_matrix(y_test, predictions)
print(cf)

困惑矩阵(图片由作者提供)

就这样:你现在拥有了你的混乱矩阵。如果我能再给你一个建议的话,在我看来,这样显示出来的混淆矩阵还是可读性不太好我经常喜欢把它显示成热图,这样当数字高的时候我就有明亮的颜色。这样,只要看一眼,我就能对我的算法的进展有个印象。为此,我使用了 Seaborn 库

import seaborn as sns

sns.heatmap(confusion_matrix(y_test, predictions))

混淆矩阵和热图(图片由作者提供)

我觉得好多了!因为大部分预测都是正确的,所以对角线上的颜色最浅。

最后的想法

知道如何评估你的机器学*算法是最重要的。为了做到这一点,知道如何计算和混淆矩阵代表什么肯定是第一步。在我经历的不同机器学*面试中,我经常不得不回答关于混淆矩阵和衍生指标的各种问题。因此,我希望这篇文章对您了解这个主题或刷新您的记忆有所帮助。😁

如果您对本系列之前的文章感兴趣,我在这里留下了链接:

  1. Ace your Machine Learning 面试—第一部分 :深入线性、套索和岭回归及其假设
  2. Ace your Machine Learning 访谈—第二部分 2:使用 Python 深入研究分类问题的逻辑回归
  3. Ace your Machine Learning 面试—部分 3:使用 Python 深入研究朴素贝叶斯分类器
  4. Ace your Machine Learning 面试—第四部分 :深入研究使用 Python 的支持向量机
  5. Ace your Machine Learning 访谈—第五部分 5:使用 Python 深入研究内核支持向量机
  6. Ace your Machine Learning 面试—第六部分 :使用 Python 深入决策树
  7. Ace your Machine Learning 面试—第七部分 :使用 Python 研究硬投票分类器的集成学*
  8. Ace your Machine Learning 面试—第八部分 :使用 Python 从头开始使用 AdaBoost 进行集成学*

结束了

马赛洛·波利蒂

LinkedinTwitterCV

赢得下一次数据科学面试

原文:https://towardsdatascience.com/ace-your-next-data-science-interview-2de74e26a96f

所有真实的东西都有非常详细的问题

在这篇文章中,我将谈谈数据科学面试过程以及根据我的经验提出的问题。许多人害怕面试,但是,请注意,这是一个候选人的市场,如果你知道期待什么和如何准备,这个过程会很有趣。重要的是要记住,根据不同的公司,流程会有所不同。即使在同一家公司,不同的面试官可能会有不同的方法。不是所有的受访者都会被问到同样的问题。但总的来说,在你申请的大多数数据科学工作中,你应该会看到一些相似之处。

Avel Chuklanov 在 Unsplash 上拍摄的照片

1.人力资源招聘人员的电话屏幕

这次介绍性面试的目的是更好地了解你的情况和一些你的学*和工作经验。在这一点上没有什么技术。这种对话相当简短,通常持续 15-30 分钟左右。

得到💬任何数据科学或编程问题的 GPT 式答案。为成千上万的人生成摘要和学*笔记📚只需一次点击即可获得学*资源。👉

https://aigents.co/learn

2.经理和人力资源部的面试

以我的经验来看,这一轮不是太讲究技术性,除非管理者有很重的量化/技术背景。他们将重点了解你的目标和期望,你申请这份工作的原因,以及你如何适应这个职位、团队和公司文化。偶尔,他们会问一些问题,对你的相关技能进行全面评估。我被问到的一些问题包括:

-你对公司了解多少?

这是一个古老的问题,但它确实不止一次发生在我身上。对你想为之工作的公司一无所知并不符合你的最佳利益。此外,了解这家公司及其代表的价值观也很有用。招聘人员会对你对公司使命的热情感到兴奋。对我来说,我将为之工作的公司遵循我欣赏的某些价值观也很重要。至少理论上是这样。

-你为什么申请?你对这个角色的期望是什么?

对于这类问题,想想你想如何为团队做贡献,这份工作对你的学*和职业道路有什么好处。要有说服力,你要对自己的职业想追求什么有一个清晰的想法。即使你不知道,也要假装知道!

一个有用的建议是想想公司的痛苦——他们雇佣你的原因。他们不会无缘无故地雇佣你,而是为了一个尚未被满足的目的和需求。这又需要提前做研究,做出有根据的猜测。这样,你会显得更合适,因为你知道他们需要什么,你能做什么!

-从职能方面解释你以前的相关经验。

简易柠檬榨汁机。预计他们会问一些关于你过去参与的项目的问题。总的来说,重点将放在功能方面。你不应该在这里谈技术。他们会感到厌烦。

-你如何与同事合作。

团队合作对任何项目都至关重要。很有可能你会和来自不同背景、文化、信仰的同事一起工作。想一想你在工作中面临困境的时候,无论是挑战最后期限还是工作中的冲突,以及你如何解决它。

女同胞Unsplash 上的照片。

3.采访高级/首席数据科学家

这个面试是一个技术、数学和概念的面试。我觉得这个没有固定的一套问题。对话的发展取决于你如何解释和回答事情,以及面试官对某个话题的经验/知识。

-从功能和技术上描述你参与的 DS 项目(他们会在你的简历中选择一个)

在一次面试中,我被要求解释我在简历中提到的图像识别项目。

  • 数据量
  • 由于您的数据很小,可以使用什么技术来增加数据量?
  • 任何潜在的数据质量问题。他们想知道你是否做了适当的探索性数据分析
  • 深入了解卷积神经网络背后的数学原理😐

在另一次面试中,面试官一头扎进了时间序列预测模型,这也是我简历中的一个项目。人们问了很多问题,你可能会想到如下一些问题:

  • 我使用了哪些指标来衡量模型性能(MAE、RMSE、AICc 等…)。为什么我选择了一个指标而不是其他指标?
  • 我是如何进行交叉验证的。因此,解释交叉验证背后的想法
  • 解释选择的特征选择技术
  • 我使用的一个模型是随机森林回归器。列出随机森林的 3 个超参数以及如何进行超参数调整(例如 Gridsearch Sklearn 或任何其他框架)
  • 我试验的另一个模特是 ARIMA。一位采访者说,这个模型基本上是自回归的。考虑上下文,你认为这是你的模型表现不好的原因吗?

丹·克里斯蒂安·pădureț在 Unsplash 上拍摄的照片

-数据科学中的伦理问题

面试官解释了一个真实的商业情况,并问公司处理这种情况的方式是否合乎道德。你在这里一定是明智的。你想对自己诚实,但你也不想冒犯你的潜在雇主。它需要理解上下文和数据科学中的一些道德和公*概念。尽量多听,多分析情况,不确定的时候多提问。

但是如果你似乎不能提供一个答案,不要担心。我可以救你。一个完美的答案可能是:道德问题和不道德问题之间的界限有时非常模糊,没有进一步的背景,很难做出决定😉

-我有数据,但没有商业案例。我能怎么做呢?

在真实的场景中,很多时候涉众会带着数据来找你,让你提出一些对他们有利的项目想法/倡议。因为他们来自企业,你不能指望他们总是知道他们可以对数据应用什么样的技术。您始终可以做的一件事是首先探索数据,将其可视化,并创建一个仪表板来提供*解。将它与利益相关者相关的主题联系起来。在我看来,这是我们作为数据科学家需要具备的技能。如果我们每天都与数据打交道,我们就有望提出关于我们可以用数据做什么的令人信服的商业案例想法。

4.编码任务

一旦你通过了技术面试,下一步可能是编码任务。你在有限的时间内进行编码练*。结果和代码将由负责人审查,他们将决定是否要与您继续合作。

不同公司的编码分配可能不同。从字面上看,这可能是一个编码练*,在这个练*中,你被要求解决一个现实世界的业务请求,即连接不同的数据集并报告不同客户的数量也可能是在做一个商业案例。给你一个数据集和一个要解决的业务问题。 对我来说,一直是后者。有了这个任务,招聘公司不仅想测试你的建模和编程技能,还想测试你在面对这样的问题时的整体方法。

这个练*的好处是它通常是一个带回家的作业。把自己锁在一个房间里,然后开始工作。你有你需要的所有资源,书,互联网。Google 和 Stack Overflow 都在。

我认为公司允许你在家里这样做的原因是,实际上,在我们的日常工作中,我们也谷歌。完全可以参考 StackOverflow 或其他资源并消化这些代码解决方案。这是一个正常的学*过程。只要你会谷歌(没错!),愿意学*,并且能够把点点滴滴联系起来,他们就满足了。同样,公司也不太担心你是否请其他人帮忙做这项练*。反正你讨论,得到同事的帮助。并且他们可以在代码审查/演示会议期间随时提问,以检查您对自己代码的理解以及您是如何处理问题的。

因为他们希望对您的方法有一个总体的了解,所以请确保您理解业务问题、数据,并且您使用的方法适合您想要解决的问题。我的一个朋友曾经告诉我,他有一次可怕的面试经历。采访者完全否定了他的方法。可怜的家伙。您将被要求发送您的笔记本(可能通过 GoogleColab 或任何类似的*台)和 ppt 演示文稿。如果可能,制作一个吸引人的幻灯片😊它有助于讲述一个故事,人们喜欢它。相信我,你可能在工作中经常这样做。

5.结果展示

厉害!你被选中展示你的成果。我们快到了。这样做的目的是探索你的方法的更多细节,所提供的解决方案是否合适,招聘公司是否想测试你与商业利益相关者交谈的能力。

你将有一些时间来展示你的作品,问题将会接踵而至。确保你理解你写在笔记本和幻灯片上的每一件小事。您应该会收到一些关于您的方法(即分类或回归)、您的特征工程和选择、您选择的模型、模型评估和任何潜在缺陷的问题。

通常,你向一组科学家和商业同事展示这个, 所以说后者的语言,并确保你的故事与他们相关 。如果数据科学家面试官认为有必要,他们可以从技术角度出发。在一次采访中,我认为我在演讲中过多地解释了精确性和回忆(🙈)你也可以试着提前和朋友一起练*以获得反馈。

关于我如何学*和准备面试的建议

  • 查看招聘信息,将你的相关经历与职位描述联系起来。如果可能的话,为工作描述中的每项任务准备一个你曾经参与过的类似项目。有了这个,你就有充分的准备了。
  • 了解所需的技术技能。他们通常在那里,因为他们将需要执行这项工作。自己学*准备。
  • 回顾你的简历——确保你非常详细地理解了简历中的所有内容。他们会被问到的!
  • 复*数学和概念面试题。我听到很多人说数据科学工作不需要数学或统计学。这是错误的,你确实需要它们。我被问了各种各样的问题,关于卷积神经网络、LSTM 的缩放输入特征以及算法背后的数学。老实说,你在不理解背后的直觉的情况下使用某样东西会感到舒服吗?
  • 尽你所能对将要面试你的人做更多的调查。了解他们做什么并找到共同点会让你在猜测他们可能会问什么样的问题时有优势。
  • 记住,你可以控制谈话向你想要的方向发展。
  • 在任何面试中,你都应该表现出正确的举止。假设有两个候选人:一个拥有所有合适的技术技能,但反社会,另一个在技术上不如第一个强,但他/她很有魅力,自信,并表现出学*的态度。我认为第二个很有可能会被选中。经理也在寻找一个团队可以每天一起工作 8 小时的人。
  • 什么让你与众不同:问关键问题。是的,对他们在面试中告诉你的每件事都持批评态度。我正在挑战他们告诉我的一个数据科学项目,经理很喜欢。你知道为什么吗?因为这也是他们对你日常工作的期望。
  • 材料和*台:

代码练*:leetcode.comlearnpython.org

数学和机器学*概念:https://www . Amazon . com/Hands-Machine-Learning-Scikit-Learn-tensor flow/DP/1492032646

时间序列预测:应用预测原理与实践:https://otexts.com/fpp3/

统计:https://www . Amazon . com/Elementary-Statistics-12 th-Mario-Triola/DP/0321836960

就是这样!我的实际面试经验,我希望它们能帮助你做好准备,让你在下一次数据科学面试中取得成功。

感谢您的阅读。如果你觉得我的帖子有用,并且你正在考虑成为一名中级会员,你可以考虑通过 推荐会员链接 ☺️ 来支持我,我会收取你一部分会员费,不需要你额外付费。如果你决定这样做,非常感谢你的支持。

使用变形金刚实现最先进的攻击性推文预测

原文:https://towardsdatascience.com/achieving-state-of-the-art-for-offensive-tweet-prediction-using-transformers-8245e571c769

利用蒸馏和微调进行文本分类

克劳迪奥·施瓦茨在 Unsplash 上拍摄的照片

虽然人们很容易理所当然地认为像拥抱脸这样的工具可以很容易地应用复杂的模型,并将学*转移到我们喜欢的任何问题上,但我认为展示这些工具可以在一个下午内实际实现最先进的(SOTA)结果是有益的。否则,努力又有什么意义呢?

我们的任务是预测一条推文是否无害。为此,我们将使用论文TweetEval:Tweet 分类的统一基准和比较评估 中的 Tweet eval 数据集。我们将只使用这个数据集的子集offensive,但是你可以查看其他子集,这些子集标记了诸如情绪和对气候变化的立场。我们正在执行一种文本分类,并将使用一个更小、更快的版本的 BERT transformer 模型,名为 DistilBERT

资料组

TweetEval 数据集的offensive配置在 Hugging Face 中有一个模型卡,它被描述为包含:

  • text:包含推文的string功能。
  • label:一个int分类标签,映射如下:0:非攻击性,1:攻击性

拥抱人脸数据集

让我们用load_dataset()函数加载适当的数据集:

offensive对象类似于 Python 字典,其键是数据集分割(训练、验证和测试)。

使用传统的 Python 字典语法允许我们访问这些单独的数据集。这些数据集将作为一个Dataset类返回,这是拥抱脸数据集中的一个关键结构。把一个Dataset看作一个特殊类型的数组,意味着我们可以索引它并得到它的长度。

这里需要理解的关键是,数据集中的单个项目(将此视为训练的一行)是一个字典,由关键字textlabel组成,这些关键字中的值是推文本身,以及攻击性状态。

从数据集到数据框架

虽然用 Python 管理字典是可行的,但使用 Pandas DataFrames 更容易,特别是因为大多数数据科学家都非常熟悉它。拥抱脸允许我们在标准的Datasets物体和熊猫DataFrame之间转换。我们可以使用set_format()来做到这一点:

图片作者。

万一我们忘记 0 或 1 是攻击性标签,我们可以在标签整数和名称之间转换。为此,我们访问数据集的特征,然后使用索引访问标签,最后使用int2str函数:

图片作者。

不*衡数据集-类的频率

有许多不同的策略来处理不*衡的数据,其中一些标签比其他标签出现得更频繁。通过简单的直方图,很容易看出我们的数据集是不*衡的:

我们的两个类在数据集中的出现频率(图片由作者提供)。

虽然我不一定要在这里深入探讨我们如何解决这个问题,但我要指出的是,这一点很重要。这里有一个处理分类问题中不*衡数据的好资源

推文长度和最大模型上下文

不同的模型采用不同数量的上下文,其中上下文是用作输入序列的标记的数量。最大输入序列长度称为最大上下文大小。虽然上下文取决于标记的长度和我们如何标记,但我们可以通过检查每条推文的字数来估计我们的大多数输入(即推文)是否会超过最大上下文大小:

我们将使用 DistilBERT 模型,它的最大上下文大小为 512 个令牌。每条推文的上限是 70 个词,这意味着我们应该没问题。

符号化

当我们使用一个拥抱脸模型,特别是一个预训练的模型时,我们需要确保我们使用的是模型训练时使用的同一个标记器。如果您不确定这是为什么,可以考虑在加密每个令牌时使用不同的令牌化器。因此,以前表示“球”的标记现在有了不同的标记,这给模型增加了解密这个附加层的额外工作。

DistilBERT(我们将要使用的模型)使用了WordPiece标记器。我们不需要做任何花哨的事情来实例化它— AutoTokenizer是一个 HF 类,它使用from_pretrained()方法为我们提供了一个预训练模型的相关标记器:

因为我们想要标记整个数据集(包括它的子集),所以我们使用内置的map()函数,它对数据集中的每一行应用一个处理函数。我们使用padding=True,所以示例都是批中最长项目的长度,其余的用 0 填充。truncation=True简单地确保每个示例小于最大上下文大小。

还要注意,除了返回编码后的 tweets 作为input_ids之外,tokeniser 还返回一个attention_mask数组列表。这是因为我们不希望模型被额外的填充标记弄糊涂:注意掩码允许模型忽略输入的填充部分。

我们最后使用map在所有数据集上应用记号化。batched=True意味着我们通过分批编码来加速这个过程,而batch_size=None意味着我们的分批将只是实际的数据集(例如,训练、验证)。这确保了输入具有相同的长度(即张量和注意力屏蔽)。

请注意,该映射向数据集中添加了新的列。

微调变压器

不幸的是,DistilBERT 只在预测序列中的屏蔽词方面受过训练。虽然大多数模型(身体对英语有深刻的理解,但最后几层(头部和头部)经过专门训练,可以预测这些被屏蔽的单词。这和我们的任务不一样。我们只想输出一个序列属于某一类的概率。因为只有两个类,所以我们只输出两个概率。

这意味着我们必须在最后一层训练隐藏状态,要求模型头是可微分的。与我们通常用 Pytorch 编写自己的训练循环不同,我们将遵循 fastai 方法,并使用 HF Transformers API 进行训练循环。

加载预训练的蒸馏模型

为了能够训练模型的最后几层,我们首先需要具有预训练权重的实际模型。拥抱脸通常会让我们使用方法.from_pretrained()抓取任何带有AutoModel类的模型。因为我们需要一个分类头,我们使用AutoModelForSequenceClassification,它只是在预训练权重的基础上,为分类选取合适的架构。唯一需要说明的是要预测的类的数量(在我们的例子中是两个):

定义绩效指标

训练器 API 需要的一个不太直观的东西是一个compute_metrics()函数,它接受一个EvalPrediction 对象(一个由predictionslabel_ids属性组成的命名元组)并返回一个度量:值对的字典。由于我们正在进行二元分类,我们将使用准确度和 F1 分数作为我们的衡量标准:

训练跑步

如果我们想上传我们的模型运行并保存我们的性能,我们需要登录到 HF Hub。这将允许我们与其他用户共享我们的模型。你需要一个write API 访问令牌,你可以在文档中读到。

图片作者。

训练器 API 还需要训练参数(包括我们的超参数)。我们使用来自高频变压器的TrainingArguments类来做到这一点。重要的是,我们在output_dir中指定了所有训练结果的存储位置。

在这里,我们还设置了批量大小、学*速率、时期数和其他重要参数。最后,我们使用训练器 API 实例化模型,并调用.train()进行微调。

图片作者。

我们可以再坚持训练几个纪元,看能不能挤出更多的汁液。为了检查这个结果是否合适,我们可以在 scikit-learn 中实现一个虚拟分类器,它只预测最常*的类,并看看它能获得什么样的精度。在这里,预测每条推文无害的准确率为 65%。要使用它,你需要定义X_train, y_train等等。

所以我们的模型肯定比基线要好。然而,为了更好地了解我们的性能,我们应该与该数据集上的可用基线进行比较。

请注意,我们可以通过在验证数据集上使用训练器的predict方法,然后调用该对象的metrics特性来获得一个指标字典:

结果比较

将模型上传到 HF Hub 的一个好处是,它们会在一个名为 Papers 的网站上自动评分,代码为。这些人将论文、数据集和社区模型汇集在一起,记录整个 ML 中数千个不同任务的所有评估指标。

我们要做的第一件事是在我们的浏览器中登录到拥抱脸,然后单击特定的模型(它将在您命名的任何名称下)。

图片作者。

这个页面列出了模型的性能,还提供了一个推理 API,这样您就可以自己尝试这个模型了。此外,它还会记录一段时间内的超参数和训练表现:

图片作者。

如果我们向下到右下角,我们可以转到带代码的论文,以查看该数据集和该任务的排行榜。

图片作者。

令人印象深刻的是,我们在微调预训练模型方面做得相当好。在这个特定的数据集上,我们现在是世界第一,无论是准确性还是 F1 分数。

F1 得分与之前的基线相比。注意,我们在这个数据集上实现了 SOTA(图片由作者提供)。

我们甚至在的论文中得到认可,将数据集的代码页作为最先进的基准:

我们的模型distil Bert-base-un cased-fine tuned-tweet _ eval-offensive现在以 Code 网站作为这个数据集的基准(图片由作者提供)列在论文上。

结论

这次排练真实地展示了杰瑞米·霍华德常说的一句话:不需要数学博士或昂贵的图形处理器就能在一个下午内完成一项任务。像拥抱脸和 fastai 这样的工具可以让我们快速训练模型,并在模型上迭代。使用越来越容易获得的预训练模型的迁移学*更多地利用了这些工具。

如果你对快速探索变形金刚拥抱脸的能力感兴趣,看看我在这里做的这个演示。

参考

[1] L. Tunstall、L. Werra 和 T. Wolf,用转换器进行自然语言处理 s (2022),奥赖利媒体

[2] 维克多·桑弗拉达利出道朱利安·肖蒙德托马斯·沃尔夫蒸馏版伯特:更小更快更便宜更轻 (2019)、arxiv

[3] F .巴比耶里,j .卡马乔-科拉多斯,L .内维斯,路易斯·埃斯皮诺萨-安克,Tweet eval:Tweet 分类的统一基准和比较评估 (2020),arxiv

[4] J. Howard 和 S. Ruder,面向文本分类的通用语言模型微调 (2018),arxiv

[5] 拥抱脸部数据集文档 (2022)

进行机器学*面试

原文:https://towardsdatascience.com/acing-machine-learning-interviews-aa73d6d7b07b

每个机器学*面试有四个关键部分——准备指南和资源

作者的形象。

我在攻读博士学位期间的许多同事现在都在寻找下一个搬来的地方。我知道要找到第一份工作有很多困难,所以我会积极帮助他们做好准备。随着时间的推移,我积累了大量的面试反馈语料库,在本文中,我总结了机器学*面试准备的相关来源。

在机器学*领域找工作的人有四个角色:研究科学家、应用科学家、研究工程师和(开发)工程师。尽管角色不同(看看这里的和这里的每个角色会有什么不同),所有这些角色在面试准备方面都有很多共同之处。一般来说,所有四个职位的面试都有四个部分,分别针对编码、机器学*理论、系统理解和软技能。

文章最后总结了文章中提到的有用资源列表!

编码

没有什么比编码更容易练*了——解决尽可能多的问题,你就安全了。一般来说,有两种类型的编码问题——实时编码和家庭任务。

实时编码

对于 ML 职位,询问繁重的算法问题不是一种普遍的做法。很难说您会被要求实现一个红黑树……但是,一般知识问题可能包含日常 ML 工作的某些方面。

编码部分不仅测试你解决问题的能力,还测试你的思维过程以及与面试官交流并写出清晰实用的代码的能力。因此,即使您知道解决方案并且可以直接编写,首先也要花一些时间解释您的推理,并努力思考代码的结构,使其干净且易于解析。

如果问题不简单,请提出澄清问题,并从强力解决方案开始。下一步是概述解决方案的伪代码——要么用函数声明和注释,要么只用注释。这将更容易看到更大的图景。然后,您可以查看填写解决方案的注释部分。

一般来说,最好的准备方式是在 leetcode 上解决 50-100 个问题。与其他*台相比,leetcode 的一大优势是详细的答案和问题统计——问题难度和哪些公司问过它。另一个有用的资源是破解编码面试书

家庭作业

得到一个家庭作业编码/工程任务是很常*的,这将直接测试你在一个实际问题上的领域知识和技能。通常会给你一个数据集和一组指令。你要么被要求分配 4-6 个小时(倒计时将从你收到任务的那一刻开始),要么给你几天到一周的更长时间来解决问题。

要准备这种问题,一个很好的资源就是 kaggle 。在这里,您既可以练*数据科学问题,也可以从其他人那里查找解决方案。同样的原则也适用于实时编码——清晰的、文档化的和可重用的代码,具有合理的算法决策。如果有你依赖的论文,确保也包括它们。

根据工作要求定制你的解决方案——如果该公司是一家高频交易基金,使用缓慢的深度学*算法将是不明智的——简单的感知机通常就足够了。另一方面,卫星成像公司会期待视觉深度模型的知识。

家庭作业通常会在下一个面试阶段讨论。你将有机会证明你的决定是正确的,并思考如何改进解决方案。

问题举例:

  1. 编写一个图像/文本分类器。
  2. 给定一个嘈杂的电力消耗时间序列,检测厨房中的灯何时被关闭。
  3. 给定数据,提取特征并建立聚类模型。

机器学*理论

通常会有关于基础知识的问题——线性代数、微积分、概率论和一般机器学*知识,以及专业领域的领域知识。对于研究职位,你可能会被要求展示你目前的研究或者阅读并讨论一篇论文。

基本原则

线性代数:最小二乘、特征向量、特征值、矩阵的秩、主成分分析、奇异值分解、正定矩阵、正交和标准正交矩阵;
概率:随机变量、方差、期望、似然、后验、贝叶斯推断、抽样、分布、概率密度函数;
微积分与最优化:凸性、正则化、积分、链式法则求微分;
机器学*:偏差-方差权衡,支持向量机,感知器。

在准备这篇文章的时候,我发现了这本机器学*职位的面试问答书,里面有一个坚实的问题列表,上面有这些问题的答案。另一本优秀的书,机器学*面试准备书,里面有很多很好的面试行为和薪资谈判部分以及技术问题。另外,我发现这个博客总结了来自 glassdoor 的关于机器学*面试的反馈。

问题举例:

  1. 什么是批量标准化?它的弊端是什么?描述纠正它们的标准化。
  2. 解释偏差-方差权衡。
  3. 列出常*的生成模型及其优缺点。
  4. 为什么香草甘斯很难训练?你如何能提高训练?
  5. 你如何防止神经网络过度拟合?
  6. 解释如何申请退学。训练和测试有区别吗?
  7. 给出神经网络优化器的例子,它们是如何工作的?什么是渐变爆炸?如何用激活功能来矫正?
  8. 为什么神经网络可能不适合给定的任务?(查看此文)
  9. 解释变形金刚中的注意力机制(这些现在是一个通用的框架,可以应用于广泛的问题)。
  10. 描述一种你选择的降维技术。

专业领域

大多数情况下,这份工作会假设你专攻某个领域。根据职位的不同,你可能需要知道一个月前发表的开创性论文或者开创性论文和最先进的模型。

我发现 paperswithcode 的方法部分对于准备面试时修改核心论文非常有帮助。该部分最有用的特点是论文摘要,附有图片和基本解释。

简历问题举例:

  1. 为什么 CNN 应用在图像上那么好?
  2. 如何应用反卷积?
  3. 为什么变形金刚应用于图像具有挑战性?
  4. 你如何将情绪从一张脸映射到另一张脸上?
  5. 什么是时态一致性,如何实现时态一致性?
  6. 对于创成式模型,可以使用哪些损失函数?
  7. 为什么 FID 评分可能不是最好的现实主义指标?
  8. 描述卷积类型及其背后的动机。
  9. 什么是实例规范化?
  10. 描述图像重建的损失函数及其优缺点。

NLP 问题示例:

  1. 为什么我们在变形金刚中需要位置编码?
  2. 描述几种注意机制,各有利弊?
  3. LSTMs 相对于普通 RNNs 的优势是什么?
  4. 我们对一个好的嵌入有什么期望?
  5. 如何评价翻译质量?为什么 BLEU 不是一个很好的指标?
  6. 什么是对比预测编码,为什么它有帮助?
  7. 你知道哪些 NLP 数据增强技术?
  8. 训练模型时如何学*生僻字?
  9. 解释语言是如何被视为图形的。这个图会有什么性质?

系统理解

系统理解问题将测试你解决公司遇到的典型问题的方法。例如,你可能被要求列出为一家广告管理公司设计推荐系统的步骤;对于成像公司,你可能会被问及创建新滤镜的步骤;对于一家计算机图形公司来说,你会被问到一种可以重建图像法线贴图的算法。

问题举例:

  1. 你如何判断两个模型中哪一个更好?
  2. 你会如何从零开始设计一个视频 in-painting/人脸转移/法线贴图重建(这是来自计算机图形学)/垃圾邮件检测器算法?
  3. 如何处理部署模型中的数据漂移?
  4. 如何设计一个算法,给定一幅受损栅栏的图像,就能估算出保险费用?

呈现

在研究职位的面试中,你会被要求准备一份关于你的研究的报告,或者谈论一篇最近在相关会议上发表的论文。

在每种情况下,都要根据你申请的职位来组织演讲。在每一种情况下,确保你知道更广泛的领域,知道最近的出版物和后续工作。我有一个关于如何在这里做一个强有力的陈述的指南。

软技能

软技能在面试过程的每个阶段都会受到测试——你如何与面试官交流,你如何谈论编码解决方案,以及你如何对笔记、批评和挑战做出反应。然而,几乎总是有一个单独的部分来测试行为部分。

亚马逊采访的每个人都喜欢清晰地了解他们期望员工具备的价值观。总的来说,我认为他们的面试准备指南在行为和软技能问题上是最诚实和最相关的。你可以在这里和这里找到测试每个潜在软技能值的问题示例。

几个框架可以用来回答基于原则/行为的问题。大部分都属于情境目标行动结果(STAR) 框架。手边总要有几个例子。

在我自己面试了几十个候选人之后,我意识到最好雇用一个技术能力稍差但有很强的沟通和团队能力的人。我在这篇文章中总结了一些技巧。你可能想在面试前检查一下。

多方面的

了解你的面试官

在面试之前,你通常会被告知面试官的名字。一定要查阅他们的资料,阅读他们的专业领域。了解一些他们领域的核心论文,以及他们看待机器学*的角度,将有助于你更好地找到答案。

态度

从我的经验来看,态度和知识技能一样重要。我是两本书的超级粉丝,这两本书分别是《思考的快与慢》和《T2 离群值》。第一个帮助你理解你的思维会引诱你进入的常*陷阱,第二个设置正确的心态。

尽管目前非常困难,尤其是如果你面临找工作的压力,把面试当作一次学*经历而不是一次考试——这将有助于你在这个过程中更加开放和接受。

大脑冷冻

我还没有*过一个人在面试中没有经历过大脑冻结——你的大脑变得麻木,手在发抖,甚至熟悉的问题也变得具有挑战性。

有一个简单的方法对我有效了很多次——不要试图隐藏冻结,承认它。大声对面试官说,你正准备陷入大脑冻结,担心即使是简单的事情也会无法解决。有了这个技巧,你就可以解除试图隐藏大脑冻结的压力,并向面试官发出信号寻求支持。毕竟,他们也希望你表现出色!

问题

面试是双向的;利用面试时间更多地了解角色和团队。你将有机会提问——不要只是问“我什么时候能得到回复?”。

摘要

不幸的是,面试是一种通过被拒绝的痛苦经历获得的技能(或者在模拟面试的更安全的环境中,我强烈建议你练*)。发出数百份申请,进行数十次面试才能被录用的情况并不少*。因此,最好在最后离开你最喜欢的公司,这样你才能为面试做好充分准备。下面我总结一下我在文中提到的链接:

软技能: 亚马逊面试备考指南亚马逊期望在员工身上体现的原则亚马逊原则解释情境任务行动结果技巧软技能来自一个机器学*博士
编码: 编码面试准备 leetcode破解编码面试本练*机器学*题
机器学*理论: 机器学* QA 书 1机器学* QA 书 2总结自 glassdoor不使用机器学*时的方法部分的论文代码

如果你喜欢这篇文章,请与朋友分享!要阅读更多关于机器学*和图像处理的主题,请点击订阅!

喜欢作者?保持联系!

我错过了什么吗?请不要犹豫,直接在 LinkedInTwitter 上给我留言、评论或发消息吧!

赢得麦肯锡数据科学面试的 ML 部分

原文:https://towardsdatascience.com/acing-the-ml-portion-of-mckinsey-data-science-interview-d816862733fc

Unsplash 上由 Austin Chan 拍摄的照片

咨询面试中 ML 部分的内容、原因和方式的详细指南

在我写了我加入麦肯锡的 决定以及我在那里学到的关于数据科学最有价值的经验之后,我还分享了我最终离开公司决定的原因,我从那些文章的读者那里收到了很多信息,询问如何准备咨询公司的数据科学面试。所以我想我会用几篇关于我的咨询面试过程和准备的文章来回答所有这些问题。

我在麦肯锡的面试是 3 年前的事了。随着实践的发展,一些面试过程可能会有一些变化。但是总体思路应该保持不变,准备过程也不应该有太大的不同。

所以让我们来谈谈咨询公司通常在候选人身上寻找什么,以及如何准备面试。面试有不同的部分——一般话题是 ML 知识、案例研究和文化契合度。我将在单独的文章中解决它们,以照顾每个人的注意力。你可能想知道为什么 SQL 和 Python(通常被其他公司用于 DS 面试)没有出现在列表中。我仍然强烈建议在面试前至少了解 SQL 和 Python 的基础知识,以防面试形式与我的有所不同。但 McK 普遍认为,只要你有一些编码经验,超级技术技能(像编码)是可以在工作中学*的。他们更愿意花时间测试你的“软技能”,比如学*能力、结构化问题解决能力和分析性思维方式。

为什么要测试

在技术领域,通常机器学*工程师(MLE)是建立模型的人,数据科学家主要从事分析和洞察生成。但作为 DS 顾问,你被视为“全栈”DS,这意味着你需要能够涵盖从数据管道到 ML 建模,一直到*解生成和用数据“讲故事”的事情。

因此,咨询公司希望确保你有足够的 ML 知识来从事甚至领导建模项目。

如何测试

就像我在我的采访系列中提到的关于 ML 的,通常有两种方法来测试我没有*过的 ML 知识——基于简历或基于理论。

大多数咨询面试都是基于我所听到的(和经历的)简历。这意味着两件事——你需要有一些建模经验,你需要知道如何谈论它。

如何准备

为了能够谈论建模经验,你需要,嗯,有一些建模经验。你可以通过你目前的工作获得建模经验,比如参与建模密集型项目;如果这不是一个选择,你可以利用像 Kaggle 这样的网站,通过兼职项目获得一些建模经验。

说到学*基础理论 ML 知识。在我看来,最好用的书是麻省理工运筹学教授 Dimitris Bertsimas 写的《分析边缘》。

它涵盖了从线性回归、CART 模型等基本概念到随机森林等更复杂的模型。它不包括超级先进的模型,如神经网络,强化学*等。但是根据我的经验,我在我的咨询生涯中很少使用这些模型,所以如果咨询面试对这些模型很重视,我会感到惊讶。

如果我要重新阅读这本书,为面试做准备,我会从第八章开始,在第八章中,每个模型都被详细剖析和解释,然后再看前面几章,这些章节展示了模型的案例研究。

如果你缺乏学术界和 Kaggle 环境之外的建模经验,你可能还需要了解一些关于 ML 的操作方面的知识。我个人认为 Educative.io 的探索 ML 面试课程在这方面非常有帮助。它进入了关于 ML 的操作方面的细节,比如如何选择指标和在线/离线模型评估。

如果你对机器学*基础比较熟悉,只是需要在面试前对其进行温*的话,我已经用了跳板的 51 个必备的机器学*面试问答作为快速温*

最后的建议

就像我在以前的文章中提到的,咨询公司真正关心的一件事是你的沟通能力,尤其是当涉及到复杂的分析概念时。咨询公司的数据科学家通常需要与没有分析背景的客户一起工作;所以你必须展示你的能力。在解释 ML 概念和模型时,尽量使用通俗易懂的英语,而不是晦涩难懂的术语,并确保你能真正解释它们,而不必进入计算的细节;因为你会遇到客户要求你“不用数学来解释聚类是如何工作的”。

想了解更多关于 DS 访谈的内容?以下是一些建议:

使用 BLS API、Python 和 Tableau 获取并可视化美国通货膨胀数据

原文:https://towardsdatascience.com/acquire-and-visualize-us-inflation-data-with-the-bls-api-python-and-tableau-409a2dca1537

经济学、通货膨胀、数据工程和数据分析

美国劳工统计局(BLS)收集和分析劳动经济学领域的数据。本文将向您展示如何使用 Python 和 BLS 公共数据 API 挖掘 BLS 数据。

通货膨胀削弱了货币的购买力。在 Unsplash 上由 Towfiqu barbhuiya 拍摄的照片。

“在没有金本位的情况下,没有办法保护储蓄不被通胀没收。没有安全的价值储存。”——艾伦·格林斯潘,美国美联储第 13 任主席

世界卫生组织(世卫组织)于 2020 年 3 月 11 日宣布新冠肺炎感染危机为全球疫情。到 2022 年 4 月,COVID 已经感染了超过 5 亿人,并导致 610 万人死亡。此外,与流行病相关的问题导致食品和燃料等消费品价格上涨。比如,在截至 2022 年 3 月的一年中,美国标准化“市场篮子”中所有商品的价格都上涨了 8.6%,这是四十年来最大的年度涨幅。

劳工统计局(BLS)是美国劳工部的一个单位。它是美国政府在劳工经济和统计领域的主要事实调查机构。它将收集和分析的大部分数据(如通胀数据)提供给美国公众、美国国会、其他联邦机构、州和地方政府、企业和劳工代表。

BLS 在其网站上以图表、图形、表格、Excel 文件、CSV 文件等形式提供了大量数据。但它也管理 BLS 公共数据 API,该 API 允许任何具有基本编程技能的人通过各种编程语言查询和获取数据。本教程将向您展示如何编写一个 Python 程序,使用 API 来获取几个与通货膨胀相关的数据序列。

BLS 数据概述

BLS 捕获、存储、分析并提供各种类型的数据。以下是它的一些数据主题:

  • 通货膨胀和价格
  • 薪酬和福利
  • 支出和时间使用
  • 失业
  • 雇用
  • 工作场所查询
  • 职业要求
  • 生产力
  • 国际技术合作
  • 国际进出口价格指数
  • 地理信息

例如,让我们看看消费者价格指数(CPI)数据。CPI 是家庭购买的一揽子消费品和服务的加权*均值。人们和实体使用 CPI 及其组成部分来跟踪一段时间内的价格变化。

下面的 BLS 数据浏览器截图显示了从 2003 年到 2022 年 3 月的 CPI 数据。请注意,数据可以下载到 XLSX (Excel)和逗号分隔值(CSV)文件。BLS 管理的大部分数据在这样的视图中对公众开放。

2003 年至 2022 年 3 月美国城市*均所有项目的消费者价格指数。Randy Runtsch 截图。

BLS 公共数据应用编程接口简介

BLS 的公共数据应用编程接口 (API)提供了对来自所有 BLS 程序的经济数据的公共访问。有了这个 API,程序员和数据工程师可以检索 JSON 或 XLSX (Excel 格式)的历史时间序列数据。

美国劳工统计局开发者主页。Randy Runtsch 截图。

BLS 公共数据 API 有两个版本:版本 1.0 和版本 2.0。虽然 1.0 版不要求用户注册,但它限制了用户可以做的事情。例如,它将每天的查询次数限制为 25 次,并且不返回值的百分比变化。相比之下,2.0 版本的用户每天最多可以进行 500 次查询,并在检索的数据集中包含随时间变化的百分比。

要对 BLS 公共数据 API 有一个基本的了解,请阅读以下页面:

运行程序以调用 BLS 公共数据 API 的先决条件

要运行下一节中显示的代码,您需要以下内容:

  1. BLS API 注册密钥。你可以在这里免费申请一个。
  2. 你电脑上最新版本的 Python。本教程我用的是 Python 3.10,这里有
  3. 代码编辑器或集成开发环境(IDE)。我使用免费的微软 Visual Studio Community 2022 for Windows。你可以在这里下载。如果您选择使用它,一定要安装它的 Python 应用程序项目工具。如果需要,可以稍后通过 Visual Studio 的内置安装程序添加特定于语言的工具。

在我编写并测试了通过 BLS 公共数据 API 检索 CPI 数据的程序之后,我使用 Tableau Public 构建了一个简单的仪表板来可视化数据。如果你想尝试 Tableau Public,它是免费的,在这里可以找到。请注意,您发布到 Tableau 公共服务器网站的任何内容,世界上的任何人都可以使用。

示例 Python 程序

本教程将向您展示如何使用 BLS 公共 API 2.0 版来检索从 2003 年到 2022 年 3 月的四个时间序列的 CPI 数据。在检索到 JSON 格式的数据后,程序将转换一些数据,并将数据记录写入一个简单的逗号分隔值(CSV)文件。

虽然可以修改程序来检索和保存 JSON 或 XLSX 格式的数据,但我选择 CSV 作为本教程的参考,原因如下:1) CSV 文件很简单,不需要特殊的电子表格软件来读取它们,2) CSV 文件可以很容易地导入 Tableau 和其他数据可视化工具。

BLS 数据系列 ID 值

对 BLS 公共数据 API 的每个调用都必须包含一个或多个数据序列 ID。id 指定了要检索的数据的具体类型。

在这个演示中,我选择通过 BLS 公共数据 API 检索这些 CPI 数据序列(ID 后跟标题):

  • CUSR0000SA0 —美国城市*均值中的所有项目,所有城市消费者,经季节性调整
  • CUSR0000SETB01 —美国城市*均汽油(所有类型),所有城市消费者,季节性调整
  • CUSR0000SAF1 —美国城市*均食品,所有城市消费者,季节性调整
  • CUSR0000SETA02 —美国城市*均二手车和卡车,所有城市消费者,季节性调整

您可以在 BLS 网站的多个位置找到数据系列 id。热门精选页面列出了热门剧集。在 BLS 数据查看器中也可以找到它们,如下图所示。

注意 BLS 数据查看器中的数据“系列标题”和“系列 ID”值。使用 BLS 公共数据 API 请求数据时需要“系列 ID”值。作者截图。

Python 代码

下面是调用 BLS 公共数据 API 来检索上述四个与通货膨胀相关的数据系列的 Python 代码。该程序由以下代码模块组成:

  • c_bls_data.py —该文件包含 c_bls_data 类,该类使用指定的参数调用 API,将返回的 JSON 数据结构转换为 CSV 记录,并将每个记录写入 CSV 文件。
  • run_get_bls_data.py —该文件是程序的入口点。它用指定要检索的数据的参数调用 c_bls_data 类。

下一节包括描述代码如何工作的伪代码。

程序伪代码

文件 cls_bls_data.py 中的 Python 类 c_bls_data 执行程序的工作。程序入口点在文件 run_get_bls_data.py 中,它只是创建一个 c_bls_data 的实例,并向它发送几个参数。这段伪代码描述了程序的工作原理:

  1. 使用以下参数创建 c_bls_data 的实例:API 注册键、输出文件夹和文件名、要检索数据的数据系列 id 列表、数据系列的起始年份以及数据系列的结束年份。
  2. 在 c_bls_data 的构造函数中,设置一些变量,构建调用 API 所需的参数。调用 get_data()函数来检索数据。
  3. get_data()函数将 API 请求发送到 BLS 服务器。然后,它将生成的 JSON 数据集返回给构造函数。
  4. 函数的作用是:打开一个输出 csv 文件。接下来,它写入一个头并设置 CSV 数据写入器。然后,它遍历 JSON 结构中的数据,将感兴趣的数据放入变量中。它连接期间名称(月)、“1”和年份,以“2022 年 1 月 1 日”的格式创建一个月值最后,它用所需的字段写入 CSV 记录。

若要在 Visual Studio 中运行代码,请按照下列步骤操作:

  1. 创建文件夹,程序将在其中写入其输出 CSV 文件。示例程序使用较旧的“c:/bls_data”
  2. 创建 Python 程序项目。
  3. 保存上面代码窗口中命名的两个文件。
  4. 将 run_get_bls_data.py 设置为启动文件。
  5. 运行程序。

如果一切顺利,程序将创建一个包含所需记录的 CSV 文件。下面的屏幕截图显示了文件中的一些示例数据。

Python c_bls_data 类编写的 CSV 文件中的示例数据。作者截图。

示例 Tableau 仪表板

我使用 Tableau Public 创建了一个简单的数据可视化仪表板来显示一段时间内的 CPI 数据。虽然创建仪表板的说明超出了本文的范围,但是您可以随意下载仪表板并将其加载到 Tableau Desktop(公共或商业版本)中,看看它是如何组装的,并根据您自己的需要进行更改。

通货膨胀仪表板在 Tableau 公共。由 Randy Runtsch 创建的仪表板。

如果你想学* Tableau,请看这里的21 个操作视频开始学* Tableau Public。

摘要

BLS 公共数据 API 使得程序员和数据工程师可以用 Python 和其他语言轻松获取美国经济数据。本文演示了一个 Python 程序,该程序调用 API 来检索四个与通货膨胀相关的数据系列,并将数据写入一个 CSV 文件。最后,它在一个 Tableau 公共仪表板中显示数据。

请随意使用和修改 c_bls_data 类,并根据您的需要进行调整。像这里显示的数据一样,通货膨胀数据是广大公众感兴趣的。但是您可以使用 BLS 公共数据 API 来访问和分析您、您的团队或您的公司感兴趣的其他数据。

第一幕:用动作变形金刚构建人工智能的未来有多熟练

原文:https://towardsdatascience.com/act-1-how-adept-is-building-the-future-of-ai-with-action-transformers-4ed6e2007aa5

人工智能的未来是数字和物理代理,它们可以在人类命令的指导下在世界上行动。

鸣谢:作者 via midway

人工智能最雄心勃勃的目标之一是建立能够做人类所能做的一切的系统。GPT-3 可以写,稳定扩散可以画,但都不能直接与世界互动。10 年来,人工智能公司一直试图以这种方式创造智能代理。现在这种情况似乎正在改变。

我最近的一篇文章报道了谷歌的 PaLM-say can(PSC),这是一个由 PaLM 驱动的机器人,是迄今为止最好的大型语言模型。PSC 的语言模块可以解释用自然语言表达的人类请求,并将其转换为高级任务,这些任务可以进一步分解为基本动作。然后,机器人模块可以在现实世界中执行这些动作,以满足用户的请求。虽然它有重要的局限性(我评论过),但谷歌的 PSC 是上一代人工智能与机器人集成的首批例子之一——数字连接到物理。

但是,物理机器人并不是唯一可以直接影响世界的人工智能代理。另一个有希望的研究方向是可以通过开放式动作与软件交互的数字代理。我这里说的不是 GPT-3 或 DALL E,它们只有极其有限的行动空间(它们缺乏任何类型的运动系统,无论是物理的还是数字的),因此只能间接影响世界(在人类阅读或看到它们的后代之后)。例如,我指的是 OpenAI 的视频预训练模型(VPT。我在这里介绍了,它通过观察人类演奏来学*演奏《我的世界》——在某种程度上模仿他们的行为。

到目前为止,像 VPT 这样的系统并不多,因为这是一项非常新的技术。训练和建造这些系统很难:GPT-3 只能修改世界的信息,而 VPT 也可以修改世界的状态——即使是在数字层面。VPT 享有更高程度的代理,并代表着一个更接近一般的智能。

但今天我不会谈论谷歌的 PSC 或 OpenAI 的 VPT。

Adept 制造了第一个动作变形金刚(ACT-1)

今天的文章介绍了一家新的人工智能初创公司, Adept ,它于今年早些时候推出,旨在构建“有用的通用智能”Adept 汇集了来自谷歌、DeepMind 和 OpenAI 的优秀人才——包括 2017 年发明变压器的家伙。像大多数其他人工智能公司一样,他们的主要目标是构建智能代理,但他们的愿景相当独特。

他们不是要建立一个可以做我们所能做的一切的 AGI——这将最终导致人类劳动力的大规模替代——而是要建立一个智能界面,可以充当人类和数字世界之间的自然翻译器——人工智能和人类合作而不是竞争。正如研究员大卫·栾(David Luan)所说(现在在 Adept 工作,之前在谷歌和 OpenAI 工作),“我们想建立一个自然语言界面……——一个你的计算机的自然语言前端。”

Adept 现在宣布它的第一个人工智能模型:动作变形金刚(ACT-1)。他们没有透露任何技术细节,只是说这是“一个经过训练使用数字工具的大规模变压器。”(他们很快会发表一篇论文。我会更新这篇文章以包含新的信息。Adept 的 ACT-1 是一个数字代理,旨在与其他程序和应用程序进行通信,并作为我们和数字世界之间的接口,一个自然的人机界面(HCI)。

Adept 发布了几个简短的演示视频,在视频中你可以看到第一幕的表演。它可以接受用自然语言表达的高级请求并执行它们——非常像谷歌的 PSC。这些任务可能需要跨软件工具和网站的几个步骤,复杂程度各不相同。ACT-1 可以在流程的不同点执行涉及各种工具的任务,并可以接受用户反馈以进行改进。

最重要的是,ACT-1 可以执行我们不知道如何做的动作。这就是 ACT-1 的用处变得明显的地方。ACT-1 可以充当多任务元学*者,能够处理各种软件应用。为了让它工作,我们只需要知道如何与第一幕沟通,以及我们想要的结果。如果 ACT-1 运行良好,我们就不必学*使用 Excel、Photoshop 或 Salesforce。我们会简单地将工作委派给第一幕,并专注于更具认知挑战性的问题。

如果你重读最后一段,你可以瞥* ACT-1(和一般的数字代理)的两个关键方面,我将在文章的其余部分讨论这两个方面。首先,我们有一个很大的“如果”在“如果第一幕完美运作。”如果没有,当我们面临一项我们缺乏能力或知识的任务时(例如,您必须组织一些数据,但不知道如何使用 Excel),我们如何知道何时应该信任它呢?第二,正确使用 ACT-1 要求我们知道如何与它沟通——这强调了提示在未来将有多重要(如果从 GPT-3 或稳定扩散中还不清楚的话)。

让我们从第一点开始。

艰巨挑战背后的大承诺

GPT-3 等基于变压器的模型的一个主要限制是,它们太不可靠,无法用于高风险环境(例如,心理健康治疗)。原因是这些模型(GPT-3 以及 VPT 或 ACT-1)是在互联网数据上训练的,并被优化以学*下一个令牌/动作,给定先前令牌/动作的历史。这意味着他们缺乏常识,表达意图的能力,或者对世界如何运作的深刻理解。这些人工智能系统在它们能做什么以及它们工作得有多好方面存在固有的局限性。一些限制可能是规模问题(更多的数据和更多的参数将解决它们),但其他限制似乎是它们如何设计和开发的内在问题。

尽管 ACT-1 的目的与 GPT-3 不同,尽管它有更大的行动空间,但它属于同一类模型,因此由于同样的原因而受到限制。它解释人类请求的能力不包括理解意图的能力。在其中一个演示示例中,用户要求 ACT-1 在休斯顿寻找一栋价格低于 60 万美元的房子。ACT-1 去寻找一个符合标准的房子,但是它不知道——不像任何人会立即推断出它——用户想要房子是为了别的事情。请求背后有一些意图,做出正确决策需要一些现实环境。第一幕无法获取这些信息。

现在,让我们来看看我上面提到的那个大“如果”。在房屋搜索的情况下,用户应该知道如何在没有 ACT-1 的情况下进行搜索。但是如果用户提出了一个他们不知道如何完成的请求呢?一个合理的可能性是,用户会盲目地相信人工智能系统正在做正确的动作(我们,愚蠢地,总是这样)。这是对我们无法信任的人工智能产生不健康依赖的完美配方。

你可能会说,我们已经依赖于许多许多抽象层,如果这些抽象层被打破,我们和其他人将完全失去防御能力。这是真的,但是我们倾向于用足够的可信度来构建这些层(例如,飞机似乎工作得很好,尽管你很可能不知道它们如何工作或者它们是否可靠。你相信社会有动力去建造它们,所以它们不会崩溃)。相比之下,基于深度学*的系统——即使是最先进的系统——也没有这种可靠性。

另一种可能性是,如果用户意识到人工智能的工作方式并了解其风险,决定不盲目信任系统。但是,即使在这种情况下,他们也没有办法评估 ACT-1 是否做对了。当我们问 GPT 3 号一些我们不知道答案的问题时,也会发生同样的情况。在某些情况下,我们可以简单地自己检查它(这破坏了系统的实用性),但在其他情况下,我们不能。

如果用户的不信任足够强烈,可能会导致他们不使用该系统。但另一个问题出现了:如果社会开始严重依赖这些类型的自然语言数字界面(就像它在社交媒体或智能手机上所做的那样),会怎么样?大麻烦。

在我们能够建立我们可以信任的人工智能之前(正如加里·马库斯教授所说),像 ACT-1 这样的系统的承诺只是承诺。如果它不能可靠地工作,ACT-1 只是一个非常昂贵的工具,只能完成我们也能完成的任务——我们经常不得不重新做它做错的事情。

ACT-1 的最终目标是雄心勃勃的,但在 Adept(或 OpenAI 或 DeepMind)这样的公司能够实现这一目标之前,前面还有重要的挑战。

提示是人机交互的未来

现在说第二点:提示的重要性(我之前在“软件 3.0——提示将如何改变游戏规则”中写过这个问题)。

你可能已经非常熟悉激励的概念(最先进的生成模型,如 GPT-3、LaMDA、DALL E、稳定扩散等。所有工作都有提示)。如果你不是,提示只是一种使用人类自然语言(例如英语)与人工智能系统(更一般地说,与计算机)交流的方式,让它们做一些特定的动作或任务。

提示是我们如何让生成式人工智能模型做我们想做的事情。如果你想让 GPT-3 写一篇文章,你可以说:“写一篇关于人工智能风险的 5 段文章。”那是一个提示。如果你想让 DALL E 创造一个美丽的形象,你可以说:“一只猫和一只狗在夏天玩球,充满活力和色彩的风格,高清。”那是另一个提示。谷歌的 PSC 和 Adept 的 ACT-1 工作方式相同。

提示与编程语言不同,它对我们来说非常直观。像 Python 或 C 这样的编程语言是当今最常*的 HCI。计算机天生就能理解这些语言,但我们学*它们会更加困难(它们可能需要多年的练*才能掌握)。因为提示不是别的,就是自然语言,我们马上就能学会。

有些人在提示工具和无代码工具之间做了类比,但是有一个重要的区别。尽管无代码软件消除了学*编码的需要,但它仍然需要用户单独学*每个特定的工具——无代码工具不是元工具。要让 ACT-1——一个元工具——做一些你只需要一项技能的事情;提示。诚然,这是一种无代码的形式,但它也是一种横向,自然技能——非技术通人士的终极梦想。

把提示放在历史的背景下,我们可以把它看作是 HCI(穿孔卡、机器码、汇编、低级编程语言和高级编程语言)漫长历史的最后一步。我们一直在爬楼梯,从用机器语言交谈到用人类语言交谈。我们在以前的基础上建立了越来越抽象的层,目的是隐藏人机交流背后的复杂性,使我们更容易。

提示是让计算机做某事的最新、最简单、最直观的方式。这是最强大的交流人机界面,因为它让我们在自己的领域感到舒适。它将数字用户的障碍降至最低。出于这些原因,我认为提示 HCI 在几年后会像今天的智能手机一样无处不在。这是一个我们每天都会使用的工具,可以处理任何与数字世界有关的事情。

提示是直观的,但也是一种技能

但是,即使提示是与计算机交流的最自然的方式,它也不是一种天生的能力。这是一项需要实践才能掌握的技能(即使它需要的数量比不上学*编程)。你可以把它想象成一种新的话语模式——相当于我们在和一个孩子说话时如何改变我们的语气、风格和词汇,或者政治家在和我们说话时如何使用修辞。提示是以特定形式针对特定目标的自然语言交流。从这个意义上来说,掌握它需要时间。

科技博客作者 Gwern 建议将框架提示作为一种新的编程范式。这个定义可能会疏远非编码人员,但它有助于他们理解这不是天生的。这是一项技能,虽然非常直观,但也需要实践(例如,让 GPT-3 输出你想要的东西可能需要几次尝试,才能得到像样的东西)。

正如 Gwern 解释的那样,如果我们把提示想象成一种编程语言,那么每个提示都可以理解为一个程序。当你用英语向 GPT-3 输入一个请求时,你就是在给它“编程”,让它去做一件其他版本不知道该怎么做的任务。你正在创造一个稍微不同的版本。因此,提示不仅仅是一种向计算机传达我们的需求的方式。这也是教他们用自然语言完成新任务的一种方式。

Gwern 以 GPT-3 为例强调提示是一种技能。他说,GPT-3 早期受到的主要批评之一是它无法正确执行一些基本的语言任务。他设法通过找到更好的提示来证明批评者是错误的。他证明了并不是所有的提示对于达到某种结果都是同样好或者同样有效的——就像与人类交谈可以被视为一种技能,可以表现得更好或者更差一样(如果我们将这一论点扩展到无限,我们会发现一切都是一种技能)。

即使像 GPT-3 或 ACT-1 这样的人工智能系统被证明非常有用,人们仍然需要学*创建良好的提示(类似于我们现在对 GPT-3 或稳定扩散所做的,这些工具并不是每个人都掌握到相同的程度)。

无论如何,虽然提示不是万灵药,但它绝对是人机交互的一大飞跃——将使人们能够利用计算机、程序、应用程序和其他工具的能力民主化,否则人们将无法这样做。

歧义和语境:提示的致命弱点

然而,尽管与以前的 HCI 相比,提示带来了巨大的优势和好处,但它并不完美。它有一个重要的缺点:人类语言固有的模糊性加上缺乏语境。

如果你考虑编程语言(甚至无代码工具),没有解释的余地。语法是严格而清晰的。如果你用 Python 键入一个句子,它只能表示一件事,计算机不需要“推理”或“理解”它的意思。它可以根据请求立即行动。因为提示存在于自然语言的领域中,所以它们失去了传统代码的刚性和明确性。如果我们想让 HCI 和提示一起工作,这是一个关键问题。

我们人类相互理解(尽管不一定总是如此),因为我们既可以访问我们认为是共同的共享知识库,也可以访问围绕任何给定交互的上下文信息。这是语言的实用主义的一面,它不能被整合到 GPT-3 或 ACT-1 的请求中。

一方面,这些系统缺乏常识,无法获取我们对世界的共享知识。另一方面,他们缺乏任何给定交互的特定上下文,因为该上下文通常通过显式方式(即,书面或口头语言)是不可传递的。这意味着,当有歧义时,第一幕要么猜一猜,要么就此打住,不完成任务。

以前写过关于大型语言模型的这个关键限制(现在也存在于这些数字代理中,甚至在 PSC 或即将到来的 Tesla bot 这样的物理机器人中),我不知道我们如何克服它。

我看到的唯一解决方案是设计和开发这些人工智能系统,就像我们教和教育孩子一样。他们需要在这个世界中成长,并与这个世界互动,以内化他们错过的所有知识。另一种选择是将它们的范围限制在任何不需要上下文的任务上,但这可能对它们来说太过严格而没有用。我们必须等待,看看我是否错了,还有另一种方法。

结论

Adept 已经开始雄心勃勃地寻求建立可以在世界上行动的人工智能代理。像 OpenAI、DeepMind 或谷歌一样,它面临着艰巨的挑战,要开发不仅非常强大,而且可靠的人工智能。

Adept 的愿景和目标强调了即时编程作为一种新的软件范式与人工智能系统和计算机进行通信的重要性。它们也揭示了传统人机界面的优势,如编程语言,以及看似不可逾越的限制。

总而言之,Adept 绝对是一家值得关注的公司。第一个动作转换器 ACT-1 开启了一条充满希望的研究路线,在未来的几个月/几年里会有很多值得谈论的内容。

订阅 算法桥 。弥合算法和人之间的鸿沟。关于与你生活相关的人工智能的时事通讯。

您也可以直接支持我在 Medium 上的工作,并通过使用我的推荐链接 这里 成为会员来获得无限制的访问权限! 😃

新型冠状病毒相关研究论文中的可操作知识抽取

原文:https://towardsdatascience.com/actionable-knowledge-extraction-from-research-articles-related-to-novel-coronavirus-6d27eadc6119

使用自然语言处理的分级相关知识提取:查询扩展和相似性网络

疾控中心Unsplash 拍摄的照片

概述

世界正在经历一场由称为严重急性呼吸综合征-冠状病毒 2(新型冠状病毒)的新型冠状病毒引起的肺炎爆发[1]。该流行病于 2020 年 1 月 30 日被宣布为国际关注的突发公共卫生事件,并于 2020 年 3 月 11 日被世界卫生组织确认为疫情[2]。作为对疫情的回应,白宫和一个领先研究团体的联盟已经准备了新冠肺炎开放研究数据集(CORD-19),其中包含超过 51,000 篇学术文章,包括超过 40,000 篇关于新冠肺炎、新型冠状病毒和相关冠状病毒的全文[3]。包括医生在内的医疗专业人员经常寻求特定问题的答案,以改进指导方针和决策。医学文献的巨大资源对于产生新的*解是重要的,新的*解可以帮助医学界提供相关知识和全面对抗传染病。医学研究社区可以通过从大量发表的文章中高效地分析和提取冠状病毒相关的特定知识来改进他们的政策。从大量文章中手动提取相关知识是劳动密集型的,不可扩展的,并且具有挑战性[4]。因此,已经进行了几次尝试来开发智能系统,以从许多非结构化文档中自动提取相关知识。在本文中,我提出了一个简单而有效的问答框架,它基于自动分析数千篇文章来生成长文本答案(部分/段落),以回答医疗社区提出的问题。在开发框架的过程中,我们广泛探索了自然语言处理技术,如查询扩展、数据预处理和向量空间模型。

简介

自 2019 年 12 月以来,中国湖北省最大的大都市武汉爆发了肺炎疾病[5]。这种呼吸道疾病由一种名为严重急性呼吸综合征-冠状病毒 2(新型冠状病毒)的新型冠状病毒引起,在人与人之间传播,已在大约四分之一年内导致疫情,影响了全球 230 个国家。截至 2020 年 4 月 11 日,该传染病已导致 1,779,842 例确诊病例和 108,779 例确诊死亡,从根本上影响了美国、意大利、西班牙和法国[6]。作为对疫情的回应,白宫和一个领先研究团体的联盟准备了新冠肺炎开放研究数据集(CORD-19),其中包含超过 51,000 篇学术文章,包括超过 40,000 篇全文,涉及新冠肺炎、新型冠状病毒和相关冠状病毒。我们开发了一个自动知识提取系统,该系统将从数千篇文章中生成有意义的信息,以帮助医疗保健专业人员和政府官员进行决策。

本文的目标是展示:

  1. 用于知识提取的问答框架能够从与特定问题或查询相关的文章中,按照章节/段落提取最相关的长文本答案。
  2. 在第二阶段,该框架将提供从给定文章生成的相关部分的相似性网络。该网络将提供关于特定查询的更广泛的观点。在这个过程中,医疗保健专业人员不仅会从一篇相关文章中获得信息,还会从讨论该主题的其他文章中获得信息。

为了在决策过程中帮助医疗专业人员,我们主要调查了该疾病在人类中的潜伏期,以进行演示[3]。

数据集

作为对疫情的回应,白宫和领先研究团体的联盟已经准备并提供了新冠肺炎开放研究数据集(CORD-19),其中包含超过 51,000 篇学术文章,包括超过 40,000 篇关于新冠肺炎、新型冠状病毒和相关冠状病毒【3,8】的全文论文。CORD-19 数据集整合了来自几个来源的论文:世界卫生组织、PubMed Central、bioRxiv 和 medRxiv,这些来源公开了论文元数据以及与每篇论文相关的文档 [8]。

在这个项目中,只有来自 biorxiv_medrxiv 文件夹的研究文章(由 803 篇全文论文组成)才会从这些广泛的语料库中进行分析。给出的论文是 JSON 格式的,需要转换成结构化格式以便进一步研究。图 1 显示了 JSON 格式的一篇样本论文的片段。每篇论文由 7 个部分组成:论文 id、元数据、摘要、正文、bib 条目、ref 条目和 back_matter。对于这项研究,我们只从每篇 JSON 格式的论文中提取了文章标题(来自 paper_id)、摘要和正文。图 2 示出了从 JSON 格式的论文中提取标题、摘要和正文。随后,提取的文本被连接以形成完整的纸质文本。

图 JSON 格式的文本(图片由作者提供)

图 2:标题、摘要和正文的提取(图片由作者提供)

方法:

我们开发了一个自动知识提取框架,从新冠肺炎相关研究文章的语料库中提取最相关的部分。该框架执行几个步骤来检索给定特定查询的最相关部分。检索信息时,执行了一些步骤:

1。 查询扩展:使用短查询进行信息检索会导致信息检索中的术语不匹配问题,因为查询术语可能缺少足够数量的单词。查询扩展技术通过向现有术语添加新的标记(单词)并生成扩展的查询来克服这一限制。局部分析是一种 QE 技术,其中通过利用给定查询的排名靠前的相关检索部分来扩展查询。相关性反馈是另一种利用用户提供的相关文档的 QE 方法[7]。

2。 数据预处理

a.大小写折叠:在这一步中,文档中的所有文本都被转换成小写字母,就像短语“数据挖掘”被转换成“数据挖掘”一样。

b.停用词去除:停用词是指 a、an、the、that 等词。在包含琐碎信息的文档中。在建立模型的过程中应该去掉停用词。

c.特殊字符删除:文档中有一些特殊字符,如“?”, "#", "!"等等。应该去掉。

d.词汇化:由于语法原因,文档中可能会使用不同形式的单词(如 studies、studying)。词汇化用于将单词的屈折形式简化为常*的基本形式(研究,研究à研究)。

e.N-grams: N-grams 考虑 N 个连续的单词,而不是一个单词。例如,2 个单词的短语:“病毒的传播动力学”à“传播动力学”、“的动力学”、“的动力学”和“病毒”。它可以用来捕获文档中文本的上下文。

3。 使用 TF-IDF 的变换-向量空间模型:首先通过将每个句子拆分成单词来将文档变换成单词包(BoW)。随后,通过术语频率-逆文档频率(TF-IDF)方法将 BoW 转换到向量空间。术语频率(TF)是通过取术语(词)的总出现次数与文档中的总字数之间的比率来定义的。另一方面,逆文档频率(IDF)测量术语对于语料库集合中的文档的重要性或权重[4]。等式 1、2 和 3 以数学形式给出了 TF、IDF 和 TF-IDF 的定义。

4。 相似度计算:余弦相似度是计算文档对之间相似度的方法之一。它测量两个向量之间角度的余弦,其中每个向量是通过使用向量空间模型导出的文档(句子/章节/段落)的数字表示。等式 3 示出了余弦相似性的数学定义,其中 A 和 B 是两个文档。

5。 信息提取:在该步骤中,框架通过利用查询对和所有文档之间的相似性得分来检索与查询相关的信息。

6。 相似性网络:加权相似性网络是在项目的第二阶段开发的,以从研究文章中获得更多可操作的*解。在这一步中,我们将利用阶段 1 的输出。

实验和结果

从文章中检索最相关的部分或段落的过程如图 3 所示。例如,用户输入查询术语“潜伏期”。然后将相关反馈查询扩展技术应用于该查询,并生成扩展的查询以供进一步研究。我们收集了冠状病毒潜伏期相关的信息,然后将其添加到查询词中[6]。图 4 显示了对术语“潜伏期”的扩展查询。随后,该框架首先搜索最相关的文章,然后分层调查每篇文章的最相关部分,最后向用户返回基于排序的相关部分。图 5 示出了从题为“冠状病毒疾病 2019 在潜伏期期间的传播可能导致隔离漏洞”的文章中检索到的与查询术语“潜伏期”最相关的部分。从图 5 中,该部分包含与新型冠状病毒的潜伏期相关的许多重要信息,这些信息对于医学专业人员做出决定可能是重要的。它可以帮助医疗保健专业人员对传染病的当前和未来规模进行建模,并评估疾病控制策略,如决定可能接触过病毒的人需要隔离多少天。

图 3:知识提取的过程(图片由作者提供)

从图 5 中,该部分包含与新型冠状病毒的潜伏期相关的许多重要信息,这些信息对于医学专业人员做出决定可能是重要的。它可以帮助医疗保健专业人员对传染病的当前和未来规模进行建模,并评估疾病控制策略,如决定可能接触过病毒的人需要隔离多少天。

(图片由作者提供)

在第二阶段,加权网络图将基于给定的查询词提供文章之间的相似性。图 5 展示了给定查询术语“潜伏期”的网络的例子。节点“潜伏期”和“id:23”之间的分数 0.23 表明它们之间的相似性是 0.23(这是该网络的最大值),而“id:23”是给定研究文章之一的 id。医疗专业人员可以通过这个网络研究所有的文章以获得潜伏期相关的知识。

(图片由作者提供)

结论

世界正在经历由一种新型冠状病毒引起的肺炎爆发。与冠状病毒相关的大量医学文献资源包含有价值的信息,可以为医学研究团体提出的特定问题提供答案。卫生保健专业人员可以通过从许多已发表的文章中高效地分析和提取冠状病毒相关的特定知识来改进他们的政策,并全面抗击传染病。我们开发了一个可操作的知识抽取框架,它可以根据与特定查询相关的部分/段落自动抽取相关信息。该框架在模型构建过程中利用了最先进的自然语言处理技术。该框架还提供了从给定文章生成的相似性网络,这些文章提供了关于特定查询的更广泛的观点。因此,医疗保健专业人员不仅会从一篇相关文章中获得信息,还会从讨论该主题的其他文章中获得信息。

代码:

import os
import json
import numpy as np
import pandas as pd
import nltk
# nltk.download()
from nltk.corpus import stopwords 
stopwords = stopwords.words('english')
from nltk.tokenize import word_tokenize 
import re
from nltk.stem import WordNetLemmatizer, PorterStemmer
lemmatizer = WordNetLemmatizer()
stemmer = PorterStemmer()f = path-directory-of-the-datafiles_in_bioarve = os.listdir(f)# Reading the parts of given papers from the local computer one by one: p1--> read all papers in dictionary format, title--> title of the paper, abstract_text --> abstract of the paper, body_text --> body texts are spread all over the article, adding all those text bodies togetherpaper_id = []
title_text = []
abstract_text = []
body_text = [] 
for j in range(len(files_in_bioarve)):
    a_text = ''
    b_text = ''
    t_text = ''
    p1 = json.load(open(f + files_in_bioarve[j], 'rt'))for i in range(len(p1['metadata'])):
        t_text += p1['metadata']['title']
    title_text.append(t_text)

    for i in range(len(p1['abstract'])):
        a_text += p1['abstract'][i]['text']
    abstract_text.append(a_text)

    for i in range(len(p1['body_text'])):
        b_text += p1['body_text'][i]['text']
    body_text.append(b_text)# aggregating all the parts of each of the papersdocs = [title_text[i] + abstract_text[i] + body_text[i]  for i in range(len(body_text))]## input: a sprecific queryquery = """case days period incubation incubation period covid-19 quarantine infect epidemic time individuals disease isolation median range transmission infection onset mean quarantine period report study hospitalize result periods data estimate fatality rate number expose period days coronavirus include adults longer model wuhan history symptom day use casualties symptom onset fatality rate outbreak base therefore population 7-day"""docs.insert(0, query)def text_preprocessing_0(text):
    """
    1\. case folding: all letters folded to lower case
    2\. removing non-alphanumeric characters
    3\. tokeinizing the sentences into words
    4\. removing stopwords
    5\. lemmatization
    6\. steming
    """
    lower_case = text.lower()  
    token =  word_tokenize(lower_case)
    filter_tokens = [w for w in token if w not in stopwords]
    lemmatized_words = [lemmatizer.lemmatize(filter_tokens[i], pos = 'v') for i in range(len(filter_tokens))] 
    return lemmatized_wordsclean_docs = [' '.join(text_preprocessing_0(docs[i])) for i in range(len(docs))]

我扩展了这个工作,并在去年的 IEEE 大数据 2020 大会上发表。如果你想引用这个作品—

马苏姆,m .,沙赫里亚尔,h .,哈达德,H. M .,阿哈迈德,s .,斯内哈,s .,拉赫曼,m .,Cuzzocrea,A. (2020,12 月)。新冠肺炎的可操作知识提取框架。在 2020 年 IEEE 大数据国际会议(大数据)(第 4036–4041 页)。IEEE。

阅读默罕默德·马苏姆博士(以及媒体上成千上万的其他作家)的每一个故事。

你的会员费将直接支持和激励穆罕默德·马苏曼德和你所阅读的成千上万的其他作家。你还可以在媒体上看到所有的故事—https://masum-math8065.medium.com/membership

快乐阅读!

参考

[1]埃斯特拉达,E. (2020)。SARS 冠状病毒 2 型主要蛋白酶的拓扑分析。bioRxiv。

【2】奥尔蒂亚,I .&博克,J. O. (2020)。通过影响途径分析和网络分析重新分析新型冠状病毒感染宿主细胞蛋白质组学时程数据。与炎症反应的潜在联系。BioRxiv。

【3】https://www . ka ggle . com/Allen-institute-for-ai/CORD-19-research-challenge

【4】穆罕默德,m .,科萨拉朱,s .,t .,莫德吉尔,g .&康,M. (2018 年 10 月)。使用层次文档分析从 OCR 文档中自动提取知识。《2018 年适应性和融合系统研究会议论文集》(第 189–194 页)。

[5]黄,杨,涂,米,王,陈,周,周,陈,陈…&黄,秦(2020)。中国武汉地区新型冠状病毒感染实验室确诊阳性病例的临床特征:回顾性单中心分析。旅行医学和传染病。

https://www.worldometers.info/coronavirus/】https://www.worldometers.info/coronavirus/

【7】崔,h,文,林君如,聂,林君宜,&马文友(2002 年 5 月)。使用查询日志的概率查询扩展。《第 11 届万维网国际会议论文集》(第 325-332 页)。

【8】王,L. L .,Lo,k .,Chandrasekhar,y .,Reas,r .,Yang,j .,Eide,d .,… & Kohlmeier,S. (2020)。新冠肺炎开放研究数据集。ArXiv。

神经网络中的激活功能:你可能不知道的

原文:https://towardsdatascience.com/activation-functions-in-neural-networks-what-you-may-not-know-2d99ad093246

如何识别最佳(和最差)激活函数

照片由 JJ 英Unsplash 上拍摄

当我第一次开始学* ML 时,我被告知激活是用来模仿大脑中的“神经元激活”,因此得名神经网络。直到很久以后,我才了解到这个积木的更精细的复杂性。

在这篇文章中,我将解释深层神经网络中激活函数背后的两个关键概念和直觉:

  • 为什么我们需要它们,
  • 为什么我们不能选择任何非线性函数作为激活函数。

本文中的所有数字和结果都是作者创作的:等式是使用 TeXstudio 编写的;使用 Keras 创建模型,使用 Netron 可视化;使用 matplotlib 绘制图形。

Keras 支持的一些激活

为什么我们需要激活函数?

术语:激活是一个非线性函数。简单地说,它是不属于形式y = mx + b的任何函数。

在神经网络中,这些函数通常放在每个卷积或全连接(又称密集)层的输出之后。他们的主要工作是“激活神经元”,即捕捉模型的非线性

但是什么是非线性,为什么它很重要?

考虑以下具有两个密集图层的简单网络(如果您使用过 MNIST 数据集,可能会觉得很熟悉):

简单的双层网络

设输入为x,第一层的权重和偏差为W_1, b_1,第二层的权重和偏差为W_2, b_2。用激活功能σ_1, σ_2,第一层的输出是:

整个模型的输出是:

但是如果我们不使用任何激活功能呢?如果没有σ_1σ_2,新的输出将是:

注意,这个等式可以简化为:

这相当于具有一个密集层的浅网络。简单来说,第二层根本没有添加任何有用的信息。我们的模型现在相当于:

浅层单层网络

我们可以将这种分析推广到任意层数,结果仍然成立。(微积分类似的结果:线性函数合成还是线性函数。)

因此,为了让深层网络有意义,我们必须对每个隐藏的输出进行激活。

否则,我们的网络将会很浅,学*能力将会受到严重限制。

这里有一个关于 MNIST 的快速实验来进一步说明这个结果:

MNIST 的一些快速结果

一些流行的激活功能

对于大多数实际系统/模型,激活是以下三种之一:ReLU、Sigmoid 或 Tanh(双曲正切)。

热卢

最简单的(也可以说是最好的)激活。如果隐藏层的输出为负,我们只需将其设置为零:

ReLU 的图形是:

ReLU 激活功能

优点:

缺点:

  • Dead ReLU:如果所有输出都是负的,梯度将被削波为零。这可以通过更好的权重初始化来避免。

乙状结肠和 Tanh

这些函数具有以下形式:

(你能推导出这些函数的导数吗?不要担心,PyTorch 和 TensorFlow 等现代 ML 框架免费提供这些激活,反向传播已经内置并优化。)

他们的图表是:

Sigmoid 和 Tanh 激活函数

它们的行为非常相似,只是 Sigmoid 的输出上限在[0,1]之间,Tanh 的输出上限在[-1,1]之间。

优点:

  • 不会破坏激活。
  • Sigmoid 适合捕捉“概率”,因为输出上限在 0 和 1 之间。(这些概率的总和不是 1,为此我们需要 Softmax 激活。)

缺点:

  • 较慢的反向传播计算。
  • 很多情况下收敛较慢。
  • 消失梯度:当输入远离零时,图形是*坦的。这可以通过使用正则化来避免。

为什么不是其他非线性函数?

说到非线性,我会想到其他一些函数:二次函数、*方根函数、对数函数…

为什么我们在实践中不使用这些函数?

根据经验,良好的激活:

  • 应该为所有实数定义,
  • 是可微分的,并且可以有效地实现反向传播,
  • 可以“启发式”解释。

上述三个函数的一些问题是:

  • 二次:没有给出有意义的信号。输出-2 或 2 将给出相同的结果。
  • *方根:没有为x < 0定义。
  • 对数:没有为x <= 0定义,这个函数在零附近也是无界的。

作为练*,可以考虑微积分/线性代数中遇到的其他非线性函数。想想我们为什么不使用它们。这是一个很好的练*,可以提高你对深度学*的直觉。

比如:我能不能把*方根函数扩展到负值(通过对称绘制),并以此作为激活函数?

扩展*方根函数

(提示:这个激活功能很有问题!)

结论

在建立深度学*模型时,激活功能通常是事后想起的。然而,在它的机制中有一些微妙之处,你应该知道。希望这篇文章能让你更好地理解激活的基本概念,以及为什么我们会选择一些功能而不是其他。

快乐学*!

如果你愿意支持 Thu,你可以考虑注册成为一名中等会员。每月支付 5 美元,你就可以无限制地阅读媒体上的故事。如果你使用他的推荐链接,Thu 也会得到一小笔佣金。

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

主动学*:改善数据标注体验的实用方法

原文:https://towardsdatascience.com/active-learning-a-practical-approach-to-improve-your-data-labeling-experience-26da83983393

实践教程

使用 doccano 和 modAL 的更智能的人类标记方式

米歇尔·图尔凯维奇Unsplash 拍摄的照片

**Table of Contents**· [Human Labeling](#19f8)
· [Active Learning](#7fa3)
  ∘ [Performance with all observations](#af68)
  ∘ [Performance with active learning](#b947)
· [Wrapping Up](#a7fb)

好了,让我们来讨论一件在数据科学领域没有得到太多关注的事情:标记你的数据。这是一个痛苦的过程,这可能会导致你在互联网上找到的教程或你参加的训练营中忽视它。然而,它是数据管道中最重要的组件之一,你知道,垃圾进垃圾出。一个不好的标签导致一个不好的模型和一个不好的生产实践。

最近,一种以数据为中心的机器学*方法将这一想法引入了一个全新的研究领域。

这个故事是一个关于如何执行人类标签的教程。我们将会看到这是一种费力的活动,因此,以后我们会寻求一种替代方法,如主动学*。主动学*的理念是智能地查询最有信息的观察,为你贴上标签。

作为主动学*的一个例子,请看下图。有 100 个二维观测值,分为红色和蓝色两类。主动学*只查询了 13 个观察值,已经达到了 91%的准确率(*右图右下角)。在这种情况下,主动学*的最终决策边界也相当不错。

行动中的主动学*。插图由作者提供,只要作者引用了这个故事的链接,就可以分发。

在这个故事中,为了让我们在主动学*中脱颖而出,我们将使用一个名为problems.json的数据集,它有两个键:problem键包含 LaTeX 格式的数学问题,而tags键很快将填充一到两个代数、组合学、几何或数论类。

请注意,一个问题可以分为多个类别。例如,下面这个问题被归类为代数和组合学。

总共有 181 个不同的问题。目前来看,这些问题没有任何标签。在这个故事中,我们的主要目标是给他们合适的标签。

人类标记

社区已经为数据标注开发了多种工具。对于一般用途和数据类型,我们有 ProdigyLabelboxLabel Studio 等等。然而,我们将使用 doccano ,一个用于文本分类、序列标记和序列到序列任务的开源文本注释工具。原因是 doccano 是专门为文本数据构建的,所以我们不需要安装通用标记工具有时需要的附加库。我们不需要手动将数据连接到数据库,也不需要担心数据安全性。此外,doccano 是免费的,并具有黑暗模式功能😄

如果您没有安装 doccano,请在终端中使用 pip 命令立即安装。

$ pip install doccano

然后,如果您是第一次运行 doccano,请执行以下命令。他们将初始化一个数据库,并创建一个用户名为“admin”和密码为“pass”的超级用户。您可以随意更改用户名和密码。如果你以前做过,你可以跳过这一步。

$ doccano init$ doccano createuser --username admin --password pass

之后,在本地机器上启动一个 web 服务器。

$ doccano webserver --port 8000

现在,在不同的终端中,启动任务队列来处理文件上传/下载。

$ doccano task

打开http://127 . 0 . 0 . 1:8000/,你将被定向到 doccano 主页。使用您的用户名和密码登录,导入problems.json文件,然后开始标记!

设置 doccano |插图作者作者

您可以从 doccano 服务器导出带标签的数据,并从那里开始工作。我们把它命名为problems_labeled.json吧,以后把它读成熊猫数据帧。

你可能已经猜到了,人类标记需要很长时间。我们需要另一种方法。

主动学*

我们了解到的一点是,人类标记是昂贵的,即使使用最复杂的标记工具。一个原因是太多的观察结果无法标注。那么,如果我们只标记值得的观察值,那些我们的模型最困惑的观察值,并假设其他观察值很容易预测,因此没有太多新的信息可以学*,会怎么样呢?因此,新的工作流程将不是标记所有观察值,而是:

  1. 标记一小组初始观察值来训练模型
  2. 请训练好的模型预测未标记的数据
  3. 根据预测置信度最低的样本(不确定性采样),从未标记的数据中确定要标记的新观察值
  4. 重复操作,直到达到所需的性能

这个工作流程叫做主动学*。幸运的是,对于第一步,我们已经有了一些来自 doccano 的标记数据,并可以从中初始化。

这种技术的一个缺点是需要一个模型,因此需要首先对数据进行预处理。然而,您不必实现花哨的预处理或最先进的模型,因为它们仅用于选择哪些最佳观测值需要标记,仅此而已。

为了比较主动学*和纯人类标记,我们将对两者采用相同的模型。主动学*将从 doccano 的 50 个标记观察开始进行。您将看到,主动学*的性能将接近使用较少数据的人类标记。

探索性数据分析提出了一些清理策略:

  1. 小写所有文本
  2. 删除 URL
  3. 删除所有 LaTeX 数学表达式和渐近线代码块。它们可能会传达有用的信息,但就目前而言,我们不想太超前。
  4. 删除错误的 LaTeX 语法和停用词
  5. 处理过滤器和非字母数字字符
  6. 堵塞物

上述清洁步骤中的第 3 步是最具挑战性的一步。为此,我们形式化了 4 种类型的数学表达式:

  1. 单或双美元符号,\$...\$\$\$...\$\$
  2. 一对括号(...)
  3. 一对支架[...]
  4. \begin...\end命令

为了使用正则表达式匹配 LaTeX 语法,我们使用递归,因为四种类型中的每一种都可以包含在其他类型中。模式相当复杂,如下所示。

这同样适用于渐近线模式。

现在,该打扫卫生了!

我们可以查询一些标签和标记,看看从给定的标记中猜测标签是否有意义。

['number theory']
let let let product element prove nanang susyanto jogjakarta['combinatorics', 'number theory']
determin proof number permut valu fix valu integ multipl['algebra']
let real number ration number prove integ['combinatorics', 'geometry']
hall castl regular hexagon side length 6 meter floor hall tile equilater triangular tile side length 50 centimet tile divid three congruent triangl altitud orthocent see below small triangl color tile differ color two tile ident color mani color least requir tile s pattern is['geometry']
given triangl right angl show diamet incent

正如我们在上面看到的,从标记中猜测标签是合理的。例如,如果一个标记包含“triangl”或“incircl”,其中一个标签很可能是“geometry”。

主动学*的策略类似于通常的机器学*建模:将数据集分为训练和测试,在训练数据集上训练模型,并在测试数据集上寻找性能。训练和测试数据集是从标记的观察值构建的。如果你目前没有这些,先标记一小部分观察结果。未标记的观察值将由人类标记(不是所有人,只是一些你的模型最容易混淆的观察值),并包含在我们所谓的数据集中。

将标签转换成 4 个二进制列,依次代表algebracombinatoricsgeometrynumber theory

Classes: ['algebra' 'combinatorics' 'geometry' 'number theory']

对于模型管道,我们将首先将文本特征提取到 TF-IDF 的矩阵中,然后采用具有*衡类别权重的逻辑回归(以解决类别不*衡)。该模型将在一个多类设置中作为一个对其余的训练。

然后,创建下面的calc_score函数,计算模型在加权精度、召回率和 f1 分数方面的性能。

所有观察的性能

首先,让我们使用来自 doccano 标记过程输出的所有观察结果来查看模型的性能。请记住,我们希望主动学*者的表现以后会使用更少的数据接近这种表现。

{'precision': '0.87', 'recall': '0.83', 'f1': '0.84'}

主动学*的表现

对于这一个,将分类器包装在一个带有min_confidenceActiveLearner模型中,用于多标签查询策略。

让我们训练模型,看看它在精确度、召回率和 f1 分数方面的表现。

{'precision': '0.29', 'recall': '0.19', 'f1': '0.19'}

正如所料,该模型最初的表现非常糟糕。主动学*从池数据集中一次查询一个观察值,人工标记观察值(使用 python 中的input()函数),然后主动学*用新观察值的附加知识教导模型。

完成查询,使得所查询的观察是模型最不确定它属于哪个标签的观察。如果模型性能已经足够好,则可以停止该过程。具体来说,让我们逐一查询 90 个观测值。

每次查询的主动学*性能|图片作者作者

Scores after active learning
============================
precision: 0.81
recall: 0.81
f1: 0.80

我们看到,通过仅使用 70%的所有观察值,所有得分都有显著提高,从 0.2–0.3 提高到 0.8。这接近使用所有观察值的同一模型的 0.83–0.87 分。来自X_pool的标记观察值被附加到X_init,未标记的观察值留在X_pool。让我们把它们都存起来以备将来使用。

包扎

主动学*是一种数据标记方法,其中将模型应用于小型手动标记数据集,以查询模型最不可信的未标记数据点。因此,主动学*为标注者提供了一种选择值得标注的数据点的方法,从而节省了大量时间。在这个故事中,我们看到了主动学*在多标签分类任务中的应用。我们只使用了所有数据点的 70%,就有了高质量的标签。

🔥你好!如果你喜欢这个故事,想支持我这个作家,可以考虑 成为会员 。每月只需 5 美元,你就可以无限制地阅读媒体上的所有报道。如果你注册使用我的链接,我会赚一小笔佣金。

🔖想了解更多关于经典机器学*模型如何工作以及如何优化其参数的信息?或者 MLOps 大型项目的例子?有史以来最优秀的文章呢?继续阅读:

Albers Uzila

艾伯斯·乌兹拉

从零开始的机器学*

View list8 storiesAlbers Uzila

艾伯斯·乌兹拉

高级优化方法

View list7 storiesAlbers Uzila

艾伯斯·乌兹拉

MLOps 大型项目

View list6 storiesAlbers Uzila

艾伯斯·乌兹拉

我最好的故事

View list24 storiesAlbers Uzila

艾伯斯·乌兹拉

R 中的数据科学

View list7 stories

幕后的主动学*

原文:https://towardsdatascience.com/active-learning-behind-the-scenes-7e82f024a5db

我如何评估我的主动学*结果?

照片由格温·金Unsplash

在我以前的帖子中,我描述了什么是主动学*(主动学*介绍和主要方法)以及如何以简单通用的方式实现这样的管道(主动学*管道的架构)。

这篇文章基于我在 2021 年 Reversim 峰会上的演讲。我想向前跳几步,谈谈我如何评估我的主动学*模型的结果,以及它如何帮助我抓住一个巨大的错误。

图片由 Gilad Artzi 提供,来自 2021 年 Reversim 峰会(经组织者许可)

主动学*=数据选择器

一般来说,当我们谈论主动学*时,我们谈论的是创建一个数据选择器。一种自动算法,它将能够从我们的未标记数据中选择一个子集,并将为我们的模型提供最大的性能增益,因此它将能够学*并提高其准确性。

数据选择器。图片由作者提供。

数据选择器演变

假设我们有 100 万个新的未标记图像。我们只能将其中的 1000 个发送给标注器,并将它们添加到训练集中。我们将如何选择这 1000 张图片?

随机抽样

选择未标记数据进行标记的最流行的方法是随机抽样。只需随机选择你需要的样品数量。在这种情况下,假设数据越多,我们的算法就越精确。使用随机抽样,我们不考虑我们目前的模型,如果我们有一个。我们选择数据时不考虑模型的优缺点。

这让我们想到了第二个选择。

人类智能选择器

在这个选项中,我们利用我们作为数据科学家所拥有的关于数据和模型的知识。我们可以明智地选择我们想要使用的数据。我们知道什么类型的数据对我们的模型更具挑战性,在什么样的样本上它会失败,我们可以使用这些知识来选择那些确切的样本,并对它们进行努力。

但这不会持续太久。它不可扩展。单个数据科学家无法检查庞大的未标记数据集。我们真正想要的是我们自己的自动化版本。

自动智能选择器

我们实际上想要的是创建一个自动算法,封装我们关于模型和数据的知识,当然还有更多我们目前没有的知识。这样,从我们的未标记数据中明智地选择一个子集将会更容易和更快。

数据选择进化。图片由作者提供。左乐高图片:照片由哈维·卡夫雷拉Unsplash 上拍摄

创建这样一个自动数据选择器有几种方法。你可以在我之前的帖子中读到更多。

在本帖中,我们将重点评估不确定性方法的结果。提醒一下,在不确定性方法中,我们的目标是识别硬样本,即我们的模型对其输出不确定的样本。

主动学*迭代—概述

在我们继续评估之前,让我们简单回顾一下单个的主动学*迭代。主动学*是一个连续的过程,在每次迭代中,我们将数据选择器应用于当前未标记的数据集。单次迭代包括两个主要步骤——从未标记数据中选择和注释子集,并使用新选择的数据以及现有的训练数据再次训练模型。

单一主动学*迭代。作者图片

主动学*评价

一旦我们开发了我们的数据选择器,我们想评估我们的整个学*管道。

在 POC 阶段,我们有一个用于研究的大型带注释的数据集。我们将在这里使用它进行评估。

验证集在所有实验中都是固定的。只是训练在变。

智能选择与随机选择

第一个也是最重要的评估是检查我们的模型在有和没有数据选择器的情况下的性能。我们的基线是使用数据的随机抽样开发的模型(没有数据选择器)。我们希望我们的新模型,即使用明智选择的数据(带有数据选择器)开发的模型,在使用相同数量的数据时,能够获得比基线更好的性能。

模特表演。图片由作者提供。

太好了!我们获得了比基线更高的性能!

够不够?

这个图表告诉我们关于数据选择器的什么信息?我们怎么知道它选择了硬的和不确定的样本?答案是我们没有。我们需要看到这张图表背后的场景,更好地理解数据选择和已经完成的学*。

我告诉你是因为我有过不好的经历。我的第一个性能图是完美的,好得令人难以置信。事实也的确如此。有一个巨大的错误,不知何故导致图形是伟大的。而我掉进了陷阱,以为自己钉死了,完成了任务。但是当我调查我的数据选择器时,我得到了奇怪的结果。我就是在那里找到我的虫子的。如果我不去看幕后,我永远也不会发现它。

对数据样本进行排序既困难又容易

为了更好地理解我们的数据选择器,我们需要将我们的样本(在我的例子中是图像)分为简单样本和困难样本,以便我们能够研究数据选择器的选择。

在我的例子中,每张图片都由三个不同的标注者标记。我可以使用所有的注释来计算注释者之间的共识。一致性低的图像可以看作硬样本,一致性高的图像可以看作易样本。

作者创造的形象。

数据选择器评估

在这一节中,我将描述如何调查我的数据选择器结果。使用上一节中的排名图,我创建了下图:

作者创作的图表。

让我看一下图表。

  • y 轴——注释者的*均共识,如上一节所述。高共识→易样本。
  • x 轴——我们的数据选择器在每次学*迭代中选择的子集。
  • 红线——随机抽样。正如预期的那样,当我们随机抽样时,所有迭代的一致性保持不变。
  • 青色线-智能选择。在这种情况下,我们期望图形单调增加。每次数据选择器选择一个新的子集,它应该选择最难的例子。因此,它将选择的下一个子集将是更容易的子集。这是因为我们在研究阶段有一个有限的数据集。

如果我们没有得到一条单调递增的线,我们需要问自己为什么,它是否有意义。这可能是一个 bug,也可能是因为您使用的方法的特性而发生的。无论如何,我们需要这个图表来查看我们的数据选择器的行为方式。

学*评价

好的,很好,我们的数据选择器工作了。现在我们想向前迈一步,看看我们学*过程的幕后。我们想知道在简单的样本上,更好的性能是来自更好的精度,还是在困难的样本上,我们也能获得更好的性能。

为此,我创建了如下图表:

作者创作的图表。

那么我们在这里看到了什么?

  • y 轴-模型的精确度
  • x 轴——注释者一致同意从难到易的样本。(例如,最左边的条柱表示注释者在 0%到 10%之间的共识,而最右边的条柱表示在 90%到 100%之间的共识)
  • 红色和青色直方图-分别使用随机采样和智能选择的结果。
  • 红色和青色线—直方图的趋势线(根据颜色,每个直方图对应一条线)。

现在让我们看看从这个图表中我们能学到什么,以及为什么它是一个重要的图表。首先,我们看到青色趋势线(智能选择)总是高于红色趋势线(随机选择)。意思是,当我们明智地选择数据时,无论是简单样本还是困难样本,我们都能获得更高的准确性。

但是还有更多。如果我们看黄色多边形,趋势线之间的区域,我们可以看到该区域在硬样本区更大。意思是,相对于随机抽样,我们获得的准确性增益来自于对硬样本的改进,而不是对简单样本的改进。

这正是我们想要的!!

外卖食品

图片由作者提供。

最终,我知道并不是我在这里描述的所有东西都能应用到你的数据上。但这不是重点。

主要的收获是,我们需要看一看幕后,每个人都有自己合适的方式。在这种情况下,仅有性能图是不够的。性能图并没有告诉你整个故事(在我的例子中是一个 bug)。我们需要更深入地挖掘并理解我们的数据选择器行为,我们需要检查我们是否确实在数据中的硬样本上获得了改进,因为这是我们想要努力的地方。

那么让我们一起来看看幕后,让我们来改进我们的模型吧!

想听更多我的作品吗?在 Linkedin 上关注我,并访问我的网站

细胞成像的主动学*

原文:https://towardsdatascience.com/active-learning-for-cell-imaging-99fc7dcdbc82

根据标记对模型性能的预期影响,优先标记细胞成像样本。

作者(同等贡献)

阿迪·尼西姆诺姆·西格尔尼姆罗德·伯曼

介绍

许多机器学*任务面临的主要障碍之一是缺乏标记数据。标注数据可能既费钱又费钱。因此,由于缺乏标签,很多时候甚至尝试使用机器学*方法来解决问题都是不合理的。

为了缓解这个问题,机器学*中出现了一个领域,叫做主动学*。主动学*是机器学*中的一种方法,它提供了一个框架,用于根据模型已经看到的已标记数据对未标记数据样本进行优先排序。我们不会对此进行详细介绍,您可以阅读机器学*中的主动学*文章,该文章深入解释了该框架。

细胞成像中的数据科学是一个快速发展的研究领域。然而,正如在其他机器学*领域一样,标签是昂贵的。为了解决这个问题,我们在这篇文章中展示了一个对红细胞和白细胞的图像细胞主动学*分类任务的端到端工作。

我们的目标是介绍生物学和主动学*的结合,并帮助其他人使用主动学*方法解决生物学领域中类似的和更复杂的任务。

文章由三个主要部分构成:

  • 细胞图像预处理——我们展示了如何预处理未分割的血细胞图像。
  • 使用 Cell Profiler 提取细胞特征——我们展示了如何从生物细胞照片中提取形态特征,以用作机器学*模型的特征。
  • 使用主动学*——我们展示了一个模拟使用主动学*的实验,以及与不使用主动学*的对比。

项目资料馆位于:
https://github.com/noamsgl/active_learning_cell_imaging

细胞图像预处理

数据集

我们将使用一个血细胞图像的数据集,该数据集在麻省理工学院的许可下被上传到 GitHub 和 T2 Kaggle。每张图片都根据红细胞(RBC)和白细胞(WBC)分类进行标记。4 种白细胞(嗜酸性粒细胞、淋巴细胞、单核细胞和嗜中性粒细胞)还有其他标记,但我们在研究中没有使用这些标记。

以下是来自数据集的全尺寸原始图像示例:

一个被 16 个红血球包围的白血球。来源: BloodImage_00023.jpg

创建示例数据框架

我们发现原始数据集包含一个 export.py 脚本,该脚本将 XML 注释解析为一个 CSV 表,其中包含每个单元格的文件名、单元格类型标签和边界框。

不幸的是,原始脚本没有包含一个 cell_id 列,这是必要的,因为我们正在对单个单元格进行分类。因此,我们稍微修改了代码以包含该列,并选择了包含 image_idcell_id 的新文件名:

预处理数据集以包含整齐的数据集

种植

为了能够处理数据,第一步是基于边界框坐标裁剪全尺寸图像。这导致了怪异的细胞图像:

细胞图像示例。裁剪原始图像后,每个单独的单元格都被单独保存到文件中。

这里是代码:

裁剪图像到单元格并更新文件名。

为了您的方便,我们将原始存储库分叉,并将裁剪后的图像上传到 GitHub!可以在以下位置找到它们:

https://github . com/noamsgl/BCCD _ 数据集/树/主人/BCCD/裁剪

这就是预处理!现在,继续用 CellProfiler 提取特征。

基于细胞轮廓仪的细胞特征提取

CellProfiler 是一款免费的开源图像分析软件,旨在从大规模细胞图像中自动定量测量表型。CellProfiler 有一个用户友好的图形用户界面(GUI ),允许您使用内置管道以及使用各种测量和功能根据您的特定需求构建自己的管道。

开始使用:

首先,下载 Cellprofiler 。如果 CellProfiler 无法打开,您可能需要安装 Visual C++可再发行版

一旦 GUI 弹出,加载图像并将组织好的元数据写入 CellProfiler。如果您选择构建自己的管道在这里您可以找到 CellProfiler 中可用的模块列表。大多数模块分为三个主要组:图像处理、对象处理和测量。您可以保存您的管道配置并重复使用或与世界共享。

现在我们将演示特征提取过程:

  • 图像处理例如,将图像从彩色转换为灰度:

这里显示的是原始细胞图像(左),以及相同的图像转换为灰度(右)。灰度转换是对象处理步骤所必需的。

  • 对象处理- 这些模块检测和识别,或者允许你操纵图像中的对象。

CellProfiler GUI 中对象识别步骤的结果。该算法检测和定位用于测量的主要感兴趣生物对象。

  • 测量- 现在,在我们已经激活图像处理模块,并且我们已经在其中识别了主要对象之后,已知有助于细胞剖析的测量可以针对每个对象进行计算并且针对每个图像进行总结。

使用测量模块从灰度图像中提取的特征示例。每行代表一种特征类型。*均值、中值和标准值中的每一个都被输入到分类器。

使用 CellProfiler,您可以将输出数据保存到 spreedsheets 或其他类型的数据库中。我们将输出保存为. CSV 文件,并将其作为机器学*模型的特征加载到 Python 中。

使用主动学*

好了,现在我们终于有了表格数据,我们可以尝试用它来做实验。我们想要试验使用主动学*策略是否可以通过标记更少的数据和获得更高的准确性来节省时间。我们的假设是,使用主动学*,我们可以通过显著减少在细胞分类任务中训练机器学*模型所需的标记数据量,来潜在地节省宝贵的时间和精力。

主动学*框架

在我们开始实验之前,我们想快速介绍一下模态。ModAL 是 python 的一个主动学*框架。它共享 Sklearn API,所以如果你使用 Sklearn 的话,很容易将它集成到你的代码中。这个框架允许你轻松地使用不同的先进的主动学*策略。他们的文档很容易理解,我们强烈建议在您的主动学*管道中使用。

主动学* VS 随意学*

实验

为了验证我们的假设,我们将进行一项实验,比较添加新标记数据的随机子采样策略和主动学*策略。我们将开始用几个相同的标记样本训练 2 个逻辑回归估计量。然后,我们将对一个模型使用随机策略,对第二个模型使用主动学*策略。我们将在后面解释这到底是如何工作的。

为实验准备数据

我们首先加载由 Cell Profiler 创建的特性。为了使事情更容易,我们过滤无色血细胞血小板。我们只保存红细胞和白细胞。因此,我们试图解决一个二元分类问题-红细胞与白细胞。然后我们使用 sklearn 标签编码器设置标签,从数据中提取学*特征到 X,最后拆分数据进行训练和测试。

为实验拆分训练集/测试集

为实验准备数据

现在我们将设置模型

初始化基线和主动学*者

虚拟学*者将是使用随机策略的模型,而主动学*者将使用主动学*策略。为了实例化一个主动学*者模型,我们使用模态包中的 active learner 对象。在' estimator '字段中,您可以插入任何适合数据的 sklearn 模型。在' query_strategy '字段中,您可以选择特定的主动学*策略。我们使用了'不确定性 _ 采样()'。更多信息请查看模态文档

分割训练数据

为了创建我们的虚拟策略实验,我们将训练数据分成两组。第一个是训练数据,我们知道它的标签,我们将使用它来训练我们的模型。第二个是训练数据,我们表现得好像不知道它的标签。我们将已知的训练规模设置为 5 个样本。

拆分每个模型的数据集

模拟活动与虚拟

现在,我们将运行 298 个时期,在每个时期中,我们将训练每个模型,选择下一个样本,我们将根据每个模型的策略插入' base '数据,并测量其在每个时期的准确性。我们将使用*均精度得分来衡量模型的性能。我们选择这一指标是因为数据集的不*衡性质。

为了在随机策略中选取下一个样本,我们将把下一个样本添加到虚拟数据集的“”组中。这个数据集是混洗的,所以不需要重新混洗。为了使用主动学*框架挑选下一个样本,我们将使用名为' query 的 ActiveLearner 方法,该方法获取' new '组的未标记数据,并返回他建议添加到训练' base '组的样本的索引。我们挑选的每个样本都将从' new '组中删除,这样就不会有样本被选择两次或更多次。

运行主动学*实验

在这个例子中,我们在每次迭代中增加了 1 个样本。在现实世界中,一次采样一批 k 个样本可能更实际。

结果

虚拟学*与主动学*的*均精确度分数

这些策略之间的差异是惊人的!

我们可以看到,使用主动学*,我们能够在只有 25 个样本的情况下达到*均精度 0.9 分!而虚拟策略需要 175 个样本才能达到相同的精度!多么大的差距!

此外,活动模型达到几乎 0.99 的高分,而虚拟模型停止在 0.95 左右!如果我们使用所有的数据,那么它们最终会达到相同的分数,但是出于我们的目的,我们限制了来自数据集的 300 个随机样本。

该图的代码:

绘制上述结果的代码

结论/讨论

用于细胞图像分类的监督机器学*技术需要有标签的数据集。随着数据的增长,这些技术的成功将受到预算外标签的限制。为了克服这一挑战,我们展示了如何轻松地使用主动学*来选择最少数量的图像进行标记,同时仍然获得最高的分类分数。我们的实验表明,主动学*策略在只有 25 个标签的情况下获得了 0.9 的*均精度(适用于不*衡数据集的指标),而随机选择虚拟策略的*均精度为 0.4。

细胞成像对生物学、医学和药理学领域做出了巨大贡献。它用于识别细胞的类型、毒性、完整性和阶段,这些信息对于医疗保健提供者和科学家识别疾病和扩展我们对细胞生物学的理解至关重要。以前,分析细胞图像需要宝贵的专业人力资本。显微镜方法的质量和可用性的现代改进以及先进的机器学*算法,使数据科学领域能够彻底改变细胞成像。这些新技术导致了动态和多维质量数据库,并且处理这种现代细胞成像数据的能力在细胞生物学领域的进步中具有至关重要的作用。

希望细胞生物学家和其他人会发现这篇文章有助于理解主动学*策略,如何在定制的机器学*解决方案中实现它们,并发现在他们的研究中使用数据科学方法更容易。

最后,欢迎您在项目中使用主动学*后,在评论区分享您的想法和建议!

参考

[1] 机器学*中的主动学*|作者 Ana Solaguren-Beascoa 博士|致力于数据科学

[2] GitHub —圣干/BCCD_Dataset: BCCD(血细胞计数与检测)数据集是一个小规模的血细胞检测数据集。

[3] 血细胞图像| Kaggle

[4] 卡彭特,A. E .、琼斯,T. R .、兰普莱希特,M. R .、克拉克,c .、康,I. H .、弗里曼,o .……&萨巴蒂尼,D. M. (2006)。CellProfiler:用于识别和量化细胞表型的图像分析软件。基因组生物学7 (10),1–11

[5] 斯特灵,D. R .、斯温-鲍登,M. J .、卢卡斯,A. M .、卡彭特,A. E .、西米尼,b . a .&古德曼,A. (2021)。CellProfiler 4:速度、效用和可用性方面的改进。 BMC 生物信息学22 (1),1–11。

机器学*中的主动学*解释

原文:https://towardsdatascience.com/active-learning-in-machine-learning-explained-777c42bd52fa

Python 中主动学*管道的直觉和实现

fynnUnsplash 拍摄的图像

本文的重点将是解释主动学*管道的概念、直觉和简单实现。管道将在 Python 中构建,当标记数据量有限时,我们将使用主动学*来提高二进制分类模型的性能。

目录

  • 什么是主动学*?
  • 主动学*的应用
  • 问题陈述
    -要求
  • 主动学*解决方案架构
  • 生成数据
    -标注数据
  • 建模
    -训练模型
    -模型性能
    -预测
    -预测-标签分解
    -再训练模型
    -再训练模型性能
  • 结束语
  • 资源

什么是主动学*?

主动学*是机器学*的一个分支,其中模型可以访问新标记的数据点。当有大量未标记的数据并且手动注释过程非常昂贵时,这是一种常用的策略[1]。主动学*可以描述为一个迭代的监督学*过程。

与主动学*相关的体系结构可以概括如下。假设您有数百万行数据,而这些行中只有 1%被标记。你可以在这 1%的数据上训练一个模型,并让它在另外 99%的未标记的数据上进行预测。预测必须具有某种与之相关的置信度,该置信度将指示这是正确预测的可能性。然后,您需要确定所有非常可能正确的预测(比如预测概率大于 95%的预测)和不太可能正确的预测(比如预测概率小于 60%的预测)。现在,您仔细检查并手动注释模型不信任的所有数据点,将其与之前标记的数据点以及模型信任的数据点合并。现在,您有了一组标记数据,比您训练的初始模型大得多。您现在可以重新训练模型,希望新重新训练的模型在更多的数据点上产生更好的性能。这个过程可以反复进行,直到你对你试图解决的问题的结果感到满意为止。

主动学*的应用

主动学*常用于各种行业和问题。通常,可以实现主动学*来解决自然语言处理、计算机视觉和推荐系统中的问题。例如,在推荐系统的环境中,冷启动问题是一个常*的问题,但在将推荐系统推向生产时会反复出现。如果没有任何与新用户或产品相关联的标记数据,模型很难做出有价值的推荐。主动学*可以通过将人保持在循环中来解决这个问题,人会做一些手动注释,以尝试在新引入的产品和*台上的其他产品/用户之间形成连接。然后,这可以反馈到模型中,以提供有价值的建议。

问题陈述

我们要解决的商业问题与人口统计学建模有关。给定一些与我们*台上的用户相关联的重要统计数据,我们希望确定与该用户相关联的性别。我们有大量的生命统计数据,但很少或没有标记的数据点。目标是建立一个主动学*管道来训练一个模型,以识别给定用户的性别。

要求

Python=3.8.8
pandas=1.2.4
numpy=1.20.1
sklearn=0.24.1

还有一些其他的需求,比如uuidrandom模块,但是这些都是 Python 预装的。

主动学*解决方案架构

给定大的未标记数据集,以下是与构建用于预测与用户相关联的性别的分类器相关联的架构。

  1. 标记一些数据点——这个过程可以随机进行,也可以有选择地进行。
  2. 在这些标记的数据点上训练一个标为m1的模型。
  3. 使用模型m1对所有未标记的数据点进行预测。确定与这些预测相关的模型的可信度。
  4. 对于模型非常有信心的所有点,将它们视为新的附加标记数据
  5. 对于模型不确定的所有点,注释这些结果
  6. 将来自步骤 1 的标记点、来自步骤 4 的置信结果和来自步骤 5 的带注释的非置信结果合并在一起,成为更大的标记数据数据集。
  7. 在这个更大的标记数据上训练一个新的模型m2,并评估它与m1相比的性能
  8. 重复过程 1 到 7,直到你对结果满意为止。

主动学*框架。图片由作者提供

生成数据

如果需要说明这一点,如果您使用这种方法来解决一个突出的问题,不要麻烦生成数据集,使用您正在处理的数据集。我只是为了简单性和可再现性而生成一个数据集,并概述如何使用主动学*来解决这样一个问题的用例。

我们将生成与人类相关的虚假生命统计数据。我们正在构建的函数将随机生成虚假的身高、体重和年龄数据。下面列出的函数产生的数据帧将产生一个 CSV,其中包含:

- uuid (UUID4) : A unique identifier to the user 
- height (Integer) : The height of the user in cm 
- weight (Integer) : The weight of the user in pounds (lbs) 
- age (Integer) : The age of the user 
- gender (String) : The gender associated with the user if known

生成数据的前 5 行。图片由作者提供。

当然,由于我们随机生成数据,我们会有奇怪的标签值,比如一个 11 岁的女孩,体重 153 磅,身高 81 厘米。

与生成的数据集相关联的统计数据。图片由作者提供。

请记住,由于这是随机生成的,如果您试图复制该流程,您将会生成不同的值。

注释数据

在这里,人们通常会标注与标签相关的数据集,为了快速和简单起*,我将选择随机分配的性别数据。您可以研究各种各样的采样策略(如有目的的采样和方便的采样)来最好地选择要注释的数据点。有目的的抽样指的是能够为模型提供信息的选择性抽样。方便抽样是指太容易给信息贴标签。请注意,与随机采样相比,这两种方法都会在标注过程中引入偏差,并可能对模型性能产生积极/消极影响(很难说,这在很大程度上取决于您要解决的问题)。

带注释的数据行。图片由作者提供。

最后,我们有 232 行标记数据和 768 行未标记数据。

系统模型化

我将使用梯度推进模型来训练二元分类器,在现实世界中,你应该尝试许多不同的分类器(如 SVC,逻辑回归,KNN,XG Boost 等。)并评估每个的性能。您还应该对这些模型进行超参数调整,以优化性能。

火车模型

模型性能

模型的性能。图片由作者提供。

尽管考虑到我们是如何生成数据的,这些数字是非常没有意义的,但我们可以看到该模型几乎有 50%的准确性,这是有意义的,因为这是随机机会。

预测

我们希望确定与每个类别相关的预测和预测概率。当考虑预测概率时,我们可以将它们存储在一个字典中,其中键是类,值是与该类相关联的预测概率。

预测-标签分解

具有低预测概率的预测将由用户手动注释,而具有高预测概率的预测将被假定为由模型生成的良好预测。这将允许我们增加我们的标记数据,并根据以前模型的最佳表现结果重新训练新模型。出于本教程的目的,我将low prediction阈值设置为小于或等于 0.6,将high prediction阈值设置为大于或等于 0.9。这两个范围之间的任何值都不会被标记。

我们标记为注释/注释/都不是的预测数量。图片由作者提供。

同样,出于简单起*,我将随机指定一个性别(因为这是随机生成的数据),但实际上您应该手动标记它。

现在完成这个过程后,我们有了401标记的数据点。这远远大于我们之前在训练模型时拥有的标记数据点的数量(232)。

再训练模型

现在,我们可以在新标记的 401 个数据点上重新训练模型,并重新评估模型的性能。

重新训练的模型性能

与重新训练的模型相关联的模型性能。图片由作者提供。

现在我们可以看到模型有了实质性的改进,给出的数据是如何产生的,结果是没有意义的。希望这给了你一些关于主动学*如何改进数据驱动管道的标签和建模组件的想象。

结束语

主动学*是一种迭代的监督学*过程,可用于解决推荐系统、自然语言处理、计算机视觉或其他具有大量未标记数据的问题。

该过程开始于在一组标记数据上训练模型,生成预测,并在由人/模型标记的附加数据上重新训练模型。这个过程反复进行,直到用户对模型性能感到满意。

请注意,上述教程中的示例与随机生成的数据相关,该示例旨在展示主动学*的强大功能,以及如何在标记数据数量有限的情况下使用它来解决问题。尽管模型的性能有所提高,但该模型本质上是在学*随机性,所以对这些结果不能全信。

您可以在 Jupyter 笔记本上遵循本文中使用的代码。完整的文件可以在我的 GitHub 这里找到。

资源

如果你喜欢这篇文章,这里有一些我写的其他文章,你可能也会感兴趣。

[## 贝叶斯 A/B 测试解释

towardsdatascience.com](/bayesian-a-b-testing-explained-344a6df88c1a)

主动学*概述:策略和不确定性测量

原文:https://towardsdatascience.com/active-learning-overview-strategies-and-uncertainty-measures-521565e0b0b

作者图片

直觉和主动学*术语概述,并动手进行不确定性抽样计算。

1.主动学*

主动学*是对需要标记的数据进行优先排序的过程的名称,以便对训练监督模型产生最大影响。

主动学*是一种策略,在这种策略中,学*算法可以交互式地询问用户(教师或 oracle ),以便用真正的标签标记新的数据点。主动学*的过程也称为最优实验设计。

主动学*的动机是理解到并非所有标记的例子都同样重要。

主动学*是一种方法,有时可以大大减少训练模型所需的标记数据量。它通过为专家区分标签工作的优先级来做到这一点。

  • 主动学*可以在提高准确性的同时降低成本。
  • 是对现有模型的增强。
  • 是策略/算法,不是模型。
  • 但是可能很难。“主动学*容易理解,不容易执行上”

主动学*背后的关键思想是,如果允许机器学*算法选择它学*的数据,它可以用更少的训练标签获得更高的准确性。— 主动学*文献调查,毛刺落定

主动学*不是一次收集所有数据的所有标签,而是优先考虑模型最容易混淆的数据,并只请求这些数据的标签。然后,该模型对这少量的标记数据进行一些训练,然后再次为最容易混淆的数据要求更多的标签。

通过对最容易混淆的例子进行优先排序,该模型可以使专家专注于提供最有用的信息。这有助于模型更快地学*,并让专家跳过对模型没有太大帮助的标记数据。结果是,在某些情况下,我们可以大大减少我们需要从专家那里收集的标签数量,同时仍然可以获得一个很好的模型。这意味着为机器学*项目节省时间和金钱!

2。主动学*策略

主动学*的步骤

文献中研究了多种方法,涉及如何在标记时区分数据点的优先级以及如何迭代该方法。然而,我们将只介绍最常*和最简单的方法。

在未标记数据集上使用主动学*的步骤是:

  1. 首先需要做的是,需要手工标记该数据的一个非常小的子样本。
  2. 一旦有了少量的标记数据,就需要对模型进行训练。该模型当然不会很好,但会帮助我们了解参数空间的哪些区域需要首先标记以改进它。
  3. 在训练该模型之后,该模型用于预测每个剩余的未标记数据点的类别。
  4. 基于模型的预测,在每个未标记的数据点上选择分数。在下一小节中,我们将介绍一些最常用的可能得分。
  5. 一旦选择了对标记进行优先排序的最佳方法,就可以迭代地重复该过程:可以在新的标记数据集上训练新的模型,该数据集已经基于优先级分数进行了标记。一旦在数据子集上训练了新的模型,未标记的数据点可以通过模型运行,以更新优先化分数,从而继续标记。这样,随着模型变得越来越好,人们可以不断优化标记策略。

作者的 AL / Image 的一般策略

2.1 主动学*方法#1:流

在基于流的主动学*中,所有训练样本的集合作为流呈现给算法。每个示例都被单独发送给算法进行考虑。该算法必须立即决定是否标记该示例。从该池中选择的训练样本被 oracle 标记,并且在显示下一个样本以供考虑之前,该标签被算法立即接收。

作者图片

2.2.主动学*方法#2:集中

在基于池的采样中,训练样本是从大量未标记的数据中选择的。从该库中选择的训练样本由 oracle 标记。

作者图片

2.3 主动学*方法#3:委员会提问

用词委员会的质疑是使用多个模型而不是一个。

另一种方法,称为委员会查询,维护模型(委员会)的集合,并选择最“有争议”的数据点来标记下一个数据点,即模型不同意的数据点。使用这样的委员会可以让我们克服单一模型所能表达的限制性假设,尽管在任务开始时,我们仍然无法知道我们应该使用什么样的假设。

3。不确定性测量

识别接下来要标记的最有价值的例子的过程被称为“采样策略”或“查询策略”。抽样过程中的评分函数称为“采集函数”。如果被标记,则具有较高分数的数据点被期望为模型训练产生较高的值。有不同的抽样策略,如不确定性抽样、多样性抽样、预期模型变化等,在本文中,我们将只关注最常用的不确定性测量策略。

不确定性采样是一套技术,用于识别当前机器学*模型中接近决策边界的未标记项目。虽然很容易确定模型何时有信心(有一个结果有很高的信心),但您有许多方法来计算不确定性,您的选择将取决于您的用例以及对您的特定数据最有效的方法。

最具信息性的例子是分类器最不确定的例子。

这里的直觉是,模型最不确定的例子可能是最困难的例子——特别是位于类边界附近的例子。学*算法将通过观察困难的例子获得关于类边界的最多信息。

让我们举一个具体的例子,假设你试图建立一个多类分类来区分 3 类猫,狗,马。该模型可能会给出如下预测:

此输出很可能来自 softmax,它使用指数将对数转换为 0–1 范围的分数。

作者图片

3.1。最不自信:

最低置信度取 1 (100%置信度)和每个项目最有把握预测的标签之间的差。

虽然您可以仅根据置信度对顺序进行排序,但是将不确定性分数转换为 0-1 范围会很有用,其中 1 是最不确定的分数。在这种情况下,我们必须将分数正常化。我们从 1 中减去该值,将结果乘以 n/(1-n),其中 n 是标签的数量。我们这样做是因为最小置信度绝不会小于 1 除以标签数,这是所有标签具有相同预测置信度的时候。

让我们把这个应用到我们的例子中,不确定性分数将是:
(1–0.9352)*(3/2)= 0.0972。

最小置信度是最简单和最常用的方法,它给出了预测的等级顺序,其中您将对预测标签具有最低置信度的项目进行采样。

3.2。置信区间抽样

不确定性抽样最直观的形式是两个最有把握的预测之间的差异。也就是说,对于模型预测的标签,它比下一个最有信心的标签有多少信心?这被定义为:

同样,我们可以将其转换为 0–1 的范围。我们又要从 1.0 中减去,但是最大可能的分数已经是 1 了,所以不需要乘以任何因子。

让我们将置信区间抽样应用于我们的示例数据。“猫”和“马”是最有信心和第二有信心的预测。在我们的例子中,这个不确定性分数是 1.0-(0.9352–0.0540)= 0.1188。

3.3。比率采样

信心比率是信心边际的一个微小变化,着眼于最高两个分数之间的比率,而不是差异。

现在让我们再次插入我们的数字:0.9352 / 0.0540 = 17.3185。

3.4。熵采样

应用于概率分布的熵包括将每个概率乘以其自身的对数,然后取负和:

让我们计算示例数据的熵:

按作者分类的表格

对这些数字求和并求反得出 0-SUM(–0.0705,-0.0903,-0.2273)= 0.3881

除以标签数量的对数得出 0.3881/ log2(3) = 0.6151

关闭

机器学*社区的大部分焦点是创建更好的算法来从数据中学*。但是获得有用的带注释的数据集是困难的。真的很难。这可能会很昂贵、耗时,并且最终仍然会出现一些问题,比如某些类别中缺少注释。主动学*是这方面的一个重要组成部分,在我看来并没有得到充分利用。

参考

[1]https://www . manning . com/books/human-in-the-loop-machine-learning

[2]https://towards data science . com/introduction-to-active-learning-117 e 0740 D7 cc

[3]https://www . cs . CMU . edu/~ Tom/10701 _ sp11/renditions/returnation _ 13 . pdf

[4]https://www.youtube.com/watch?v=l6HFdqk480o&feature = youtu . be

AdaBoost,循序渐进

原文:https://towardsdatascience.com/adaboost-in-7-simple-steps-a89dc41ec4

升压和 AdaBoost 简介

AdaBoost—作者图片

AdaBoost 属于集成学*方法,并模仿“群体智慧”的原则:单独表现不佳的模型在组合时可以形成强大的模型。

2021 年发表的一项麻省理工学院的研究描述了人群如何识别假新闻。没有背景知识或事实核查,个人往往很难可靠地识别假新闻。然而,根据我们的经验,我们通常至少能够给出一个趋势,这通常比随机猜测要好。如果我们想知道一个给定的标题描述的是事实还是包含假新闻,我们可以简单地随机问 100 个人。如果超过 50 个说头条含有假新闻,我们就归类为假新闻。

几个单个弱学*器的预测组合起来可以产生一个强学*器,该强学*器能够以很高的准确度区分真伪。

用集成学*,我们模仿这个概念

Boosting 是最流行的集成学*技术之一。建立一组所谓的弱学*器,即性能略好于随机猜测的模型。单个弱学*器的输出被组合为加权和,并代表增强分类器的最终输出。AdaBoost 代表“自适应增压”。适应性,因为模型是一个接一个地建立的,并且前面模型的性能影响后面模型的模型建立过程。

在学*过程中,AdaBoost 算法还会为每个弱学*者分配一个权重。因此,不是每个弱学*者对集成模型的预测都有相同的影响。这个计算整体模型预测的过程称为 软表决 。另一方面,如果每个弱学*者的结果被同等地加权,我们会说 硬投票 。[Kum21]

仅次于 装袋助推 是最广为人知的合奏方法。

  • 装袋中, 我们训练一组相互独立的个体模型。各个模型彼此不同,因为它们是用训练数据集的不同随机子集训练的。随机森林就是基于这个原理。一组单独的决策树形成集合模型的预测。
  • 另一方面,在 增强 中的训练是连续的。各个模型的建模过程一个接一个地进行,由此模型预测的准确性影响后续模型的训练过程。AdaBoost 算法是如何做到这一点的,将在本文中逐步解释。模型由弱学*器、深度为 1 的简单决策树,即所谓的“决策树桩”来表示。

本文旨在逐步解释 AdaBoost 算法背后的概念。为此,我搜索了一个简单的分类数据集,找到了“成人”数据集。【KOH 96】

使用的数据集

“成人”数据集(也称为“人口普查收入”数据集)用于二元分类任务。该数据集包含描述生活在美国的人的数据,如性别、年龄、婚姻状况和教育程度等属性。目标变量区分年收入低于和高于 50,000 美元。

为了说明 AdaBoost 算法是如何工作的,我简化了数据集,只使用了其中的一小部分。我已经将代码片段打包到 Jupyter 笔记本中描述的步骤中。如果您想自己遵循这些步骤,可以随意克隆 repo 或使用文本中的代码片段。

https://github.com/polzerdo55862/Ada-Boost-Tutorial

加载数据集

准备数据集

我直接从 UCI 加载数据集,并准备 3 个简单的二进制特征:

  • 男性(是或否)
  • 每周超过 40 小时(是或否)
  • 50 岁以上(是或否)

在下文中,我将使用这个简单的数据集来解释 AdaBoost 算法的工作原理。

1.建造第一个 WeakLearner:找到性能最好的树桩

第一步,找一个 WeakLearner,可以对目标变量做一个陈述(> 50k 收入),至少比随机猜测略胜一筹。

AdaBoost 可以与几种机器学*算法结合使用。在这种情况下,我们选择决策树作为弱学*器,这是 AdaBoost 算法最流行的应用。

只是作为一个简短的复*:

决策树在所谓的 节点 逐步分割整个数据集。树中的第一个节点叫做 根节点 ,所有跟随 决策的节点 。不再发生数据集分割的节点被称为 终端节点叶节点

决策树—作者图片

我在这里描述了用于回归任务的决策树和随机森林的工作原理:

</7-of-the-most-commonly-used-regression-algorithms-and-how-to-choose-the-right-one-fc3c8890f9e3>

如果您对如何使用决策树执行异常检测任务感兴趣,您可以在此处找到对 隔离林 的介绍:

现在,我们试图找到在预测输出变量方面表现最佳的第一个决策树桩。为此,我们遵循与学*决策树相同的过程。第一步,我们确定数据集中最有可能区分高于和低于 50k 收入的特征。

为了有某种度量来评估不同的特征,我们使用了基尼系数。我们想找到叶子杂质最低的节点。

我们从随机选择的特征开始;这里的特征是“男性”。属性只区分这个人是不是男人。根节点将整个数据集分割成一个子集,其中仅包含男性和所有其他人的实例。

如果一个子集(例如 D1)包含 k 个不同的类,那么一条记录属于 I 类的概率可以描述为 p_i. [Kar22]下图中,我描述了如何计算左边终端节点的 基尼杂质

我们在下面使用的简单数据集只包含 10 个实例,6 个实例描述男性,4 个描述女性。如果我们查看包含 6 个“男性”数据样本的子集 D1,我们会看到 6 个人中有 4 个人的收入在 5 万英镑或以下。只有 2 张唱片的收入超过 50k。

因此,子集 D_1 的随机样本显示收入高于 50k 的概率是 2/6 或 1/3 ,样本显示收入低于 50k 的概率是 4/6 或 2/3 。因此,叶 1(子集 D_1)基尼系数为 0.444

如果我们对叶子 2 做同样的事情,我们得到的杂质为 0.375

由于我们想要比较根节点“雄树”、“40 小时以上”和“50 年以上”的树桩的性能/基尼指数,我们首先计算根节点“雄树”的加权基尼系数,作为单个树叶的加权和。

计算基尼指数-作者图片

我在下面的 Python 片段中绘制了基尼指数的计算,它只是简单地迭代数据框的所有列,并执行上述基尼指数计算:

目标是最小化叶子的基尼杂质,从而最大化基尼增益,基尼增益被计算为两个分裂子集的加权杂质和整个数据集的杂质之间的差。

工作时间特征为" > 40 小时"的树桩显示出最高的基尼系数,因此被用于构建第一个树桩。

作者计算残肢图像的误差

AdaBoost 现在正在继续按顺序建造树桩。AdaBoost 的特别之处在于,第一个树桩产生的误差会影响下一个树桩的建模过程。第一个树桩错误分类的实例将在下一个树中被赋予更大的权重。单个残肢的结果在集合模型中的权重取决于残肢的误差有多高。

2.计算残肢的误差

在上图中,我已经画出了正确和错误分类的实例数量。据此,在为训练数据集的记录预测目标变量时,stump 仅产生一个错误。数据集中只有一个例子,每周工作时间超过 40 小时,但每年收入不到 5 万英镑。数据集中的所有其他实例都已经用这个简单的决策树桩正确分类了。

对于误差值的计算,我们为数据集的每个记录引入权重。在第一个树桩形成之前,每个实例的权重 ww=1/n ,其中 n 对应数据集的大小。因此,所有权重的总和为 1。

然后,决策残肢产生的误差被简单地计算为残肢错误分类目标变量的所有样本权重的总和。由于所选的决策树桩仅错误分类了一个实例,第一次运行的错误是 1/10。

计算加权误差-作者图片

函数“calculate _ error _ for _ choosed _ stump”计算我选择的特征作为根节点的树桩的加权误差(selected _ root _ node _ attribute)。

3.计算树桩的权重,即“话语权”

正如已经提到的,集合模型的结果是所有树桩预测的加权和。因此,在下文中,我们感兴趣的是刚刚构建的树的预测对于最终的集合模型有多重要。或者换句话说,say (alpha) 的 量有多高。

我们计算出α的金额如下:

计算作者的 say-Image 数量

上图左边部分显示了say(alpha)量与残肢加权误差的关系。对于小误差 量大的说 。对于较大的误差,α甚至可以取负值。对于 0.1 的第一个残端的误差,alpha/量说 大约是 1.1

4.样品重量的调整

由于我们希望在对第二个树桩建模时考虑第一个树桩的结果,所以我们根据第一个树桩的误差来调整样本权重。第一个树桩预测错误的数据集记录应该在下一个树桩的构建过程中发挥更大的作用。为此,我们首先调整单个样本的权重。

使用 alpha 计算样品的新重量,如下所示:

  1. 左图显示了正确分类样本的缩放比例。
  2. 右图显示了错误分类样本的缩放比例
  3. 然后,新的样本权重被归一化

计算样品重量—图片由作者提供

计算并绘制新的重量标度:

使用刚刚定义的函数更新样品重量:

5.第二次运行:形成新的引导数据集

对于第二次运行,我可以简单地为每个属性构建一个树桩,并选择加权误差最小的树桩。

或者,我们可以使用样本权重来生成一个新的数据集,其中权重较大的样本在统计上更常*。为此,我使用样本权重将范围 0–1 划分为多个区间。

您可以在图像中看到描述为“累计 _ 总和 _ 下限”和“累计 _ 总和 _ 上限”的箱范围。

定义范围-作者提供的图像

然后,我在 0 和 1 之间选择一个随机数,并寻找该数所在的范围/bin。我复制已识别的记录,并将其添加到新的数据集中。

我重复这个过程 N 次,直到我得到一个新的数据集,它是我的原始数据集的两倍长。

由于权重较大的样本在权重范围(从 0 到 1)中占据较大的范围,因此权重较大的样本通常会在新数据集中出现多次。这正是您在下图的数据集中看到的内容。被第一个树桩错误分类的样本权重更大(这里权重为 0.5),最终更频繁地出现在新数据集中。

生成新数据集-作者提供的图像

对于新数据集,我们重复第一步:

  1. 计算所有特征的基尼系数,并选择该特征作为显示最大基尼系数的第二个树桩的根节点
  2. 建造第二个树桩
  3. 将加权误差计算为错误分类样本的样本权重之和

找到第二个树桩的根节点:

6.重复该过程,直到达到终止条件

该算法现在重复刚刚描述的步骤,直到达到某个终止条件,例如直到所有特征已经被用作根节点一次。

总结

对于 1 中的 t…t:

  1. 找到最大化基尼增益(或者最小化错误分类实例的误差)的弱学*器 h_t(x)
  2. 将弱学*器的加权误差计算为误分类样本的样本权重之和。
  3. 将分类器添加到集成模型中。模型的结果是个别弱学*者的结果的总结。使用上面确定的“说的量”/加权错误率α对弱学*者进行加权。
  4. 更新权重:在加权和误差的帮助下,我们将α计算为刚形成的弱学*者的“发言权数量”。
  5. 我们使用这个 alpha 来重新调整样本权重。
  6. 新的样本权重被归一化,使得权重之和再次为 1
  7. 使用新的权重,我们通过在 0 和 1 之间选择 N 次随机数来生成新的数据集,然后将数据样本添加到代表该数据集的新数据集。

7.将弱学*者组合成一个集成模型

集合模型计算预测如下:

  • 对每个树桩做预测

举个简单的例子,一个 30 岁的人每周工作 42 小时,第一个树桩的结果是收入高于 50k,第二个树桩的结果是收入低于 50k。

  • 的量累加到的每一个输出值

到目前为止,我们的简单集合模型只包含两个树桩。我们将收入分类在 50k 以上的树桩和收入分类在 50k 以下的树桩的权重相加。

建立集合模型——作者的图像

然后我们简单的比较一下权重之和。因为在我们的例子中,第一个树桩的重量占优势,所以集合模型的预测是收入 50k。

摘要

近年来,Boosting 方法在许多数据竞赛中表现出了优异的结果,然而它们背后的概念却非常简单。简单易懂的步骤构建简单可解释的模型。只有简单模型的组合才能产生强大的学*者。

如果您还不是中级高级会员,并且想要成为会员,您可以通过使用此推荐链接注册来支持我。

感谢您的阅读!

参考

彼得·迪兹克斯:麻省理工学院新闻,2021 年。https://news.mit.edu/2021/crowd-source-fact-checking-0901

[Kar22] Fatih Karabiber :基尼杂质,2022。https://www.learndatasci.com/glossary/gini-impurity/

[Kum21] Ajitesh Kumar:硬投票与软投票分类器 Python 示例,2021。https://vital flux . com/hard-vs-soft-voting-classifier-python-example/

[Koh96] Kohavi,Ronny 和 Becker,Barry:成人数据集,1996 年。https://archive.ics.uci.edu/ml/datasets/adult(CC 乘 4.0)

[Wiq20] Wiqaas:推进决策树桩,2020 年。https://github . com/wiq AAS/YouTube/blob/master/Machine _ Learning _ from _ Scratch/ada boosting/ada boosting _ Decision _ tree . ipynb

使情感分析模型适应定制领域

原文:https://towardsdatascience.com/adapting-a-sentiment-analysis-model-to-a-custom-domain-62ec386516bc

我们的实验发现和您尝试模型的机会

作者图片

简介

你能把一个通用的 ML 模型用于情感分析,使它适应一个特定的领域,并得出可接受的结果吗?这是多大的挑战?

事实证明,只要付出合理的努力,这是可行的。Toloka 的 ML 团队最近在金融领域调整了一个一般情绪模型,我很高兴分享我们的实验结果。

你可以在这里尝试微调后的情绪分析模型或者继续阅读了解更多细节。

基线模型

我们使用的基线模型是本文中描述的基于 RoBERTa 的分类器。

它是一个通用的自然语言处理模型,执行简单的情感分析任务。它将英语文本分为三类:

  • 积极情绪😀
  • 中性情绪😐
  • 消极情绪🙁

这种深度学*模型相对擅长于识别与它接受训练的内容相似的简短、类似推特的文本的情绪,但当我们检查它在金融领域的表现时,这种能力下降了。这是 ML 团队将模型应用于特定领域的绝佳机会。

微调模型

我们使用了financialphasebank 数据集。它由来自金融新闻的 4840 个英语句子组成,按情感分类。同样,我们有三节课:

  • 积极情绪😀
  • 中性情绪😐
  • 消极情绪🙁

在我们的实验中,我们仅使用 1e-2 的学*速率来调整分类头,运行它五个时期,并且仅使用一半的数据。仅调整头部(冻结其余权重)是一种不同寻常的训练深度学*模型的方法。这种方法通常应用在 CV 中,并且显著降低了训练的复杂性。它可以在较小的 GPU 上完成,但该过程并不总是有效——对于某些任务来说,它可能是不够的。幸运的是,在我们的案例中,以这种方式训练的模型在测试集上给了我们令人印象深刻的结果,我们决定使用一组不同的财务数据来评估它。

评估数据集

我们用来评估这两个情感分析模型的数据集来自 Kaggle,可以从这里下载。这是一个长长的金融标题列表,上面标注了与其中的金融实体相关的情感。你可以看到下面的前几行。

作者图片

因为我们的情感分析模型不是基于方面的,所以我们必须在评估数据集之前对其进行预处理。我们决定给每个标题贴上这样的情感标签:

  • 如果标题中提到的所有实体都有相同的情感,我们可以假设这是整个标题的情感
  • 如果实体有混合的情感,我们从数据集中删除它们

这导致了每个标题独特的整体情绪,如下图所示。

作者图片

我们只使用了 1000 个条目,假设这足以进行可靠的评估。你可以查看这本 colab 笔记本,找到我们在实验中使用的代码,以及我们如何对每个模型进行情感分析的更多细节。

情绪分析结果

在我们为两个机器学*模型收集了情感分析预测之后,我们可以通过查看准确度、精确度、召回率和 f 分数来建立它们之间的公*比较。我们使用 scikit-learn 库打印了两种模型的分类报告。

基线模型—作者提供的图片

微调模型,图片由作者提供

从上面的图片中,您可以看到微调版本在所有*均指标上都优于基线:

  • 精确度从 0.73 到 0.77
  • 回忆从 0.41 到 0.76
  • f 值从 0.27 降到了 0.77

单独的结果表明,基线模型的正类和负类的召回率非常低:分别为 0.01 和 0.12。对新模型的微调使得积极类的召回率为 0.71,消极类的召回率为 0.78。

在这种情况下,这种高召回率是域调整的结果。基线模型在其训练中没有遇到评估数据集中存在的金融术语,这就是它在这种情况下努力寻找积极和消极词汇的原因。在模型被修改并暴露于领域内的训练数据后,它发生了决定性的变化,并导致积极和消极类别的回忆的增加。

然而,中性类的回忆从 0.99 下降到 0.8。阴性和阳性的精确度也略有下降。这些是我们需要记住的指标,尽管高基线分数是由模型过度预测中性类引起的。

混乱矩阵说明了这种情况。

情感模型:混淆矩阵,作者图片

仔细观察就会发现基线模型在标记积极情绪和消极情绪时存在的问题。它 331 次将正面标题误标为中性。同样,负面类被误标为中性的有 258 次。这对于在这种情感分类任务中应该被可靠地检测到的类别来说是非常差的性能。

微调后的模型解决了这个问题,给了我们更正确的预测。正面类只有 85 次被误标为中性,负面类有 56 次被误标为中性。这再次归功于对模型的调整,以及在 find tuning 过程中,它学*了金融文本中的积极和消极指标。

总结

Toloka ML 团队已经证明,在不同领域训练的情感模型可以被微调到一个新的领域,从而相对容易地创建一个定制的情感分析模型,而无需太多数据。

我们的基线模型被训练来检测社交媒体帖子的情绪,使其容易在金融领域出错。但是在金融领域对模型进行微调,即使使用完全不同的金融数据集,也能显著改善结果。

你可以在这个 colab 笔记本里通读实验的代码。

也欢迎你使用微调过的型号,并在下面的评论中告诉我们你的想法。

PS:我正在 Medium 和aboutdatablog.com上写文章,深入浅出地解释基本的数据科学概念。你可以订阅我的 邮件列表 在我每次写新文章的时候得到通知。如果你还不是中等会员,你可以在这里加入https://medium.com/@konkiewicz.m/membership

下面还有一些你可能喜欢的帖子

*https://medium.com/geekculture/scraping-and-evaluating-elons-musk-tweets-e2c7bb94b75e *

机器学*的自适应参数方法

原文:https://towardsdatascience.com/adaptive-parameters-methods-for-machine-learning-6f7101a9a71

让我们探索一些方法来适应您的参数随着时间的推移。

罗斯·芬登在 Unsplash 上的照片

在这篇文章中,我将讨论机器学*的自适应参数方法背后的思想,以及为什么和什么时候使用 python 作为一些实际例子来实现它们。

1。简介

自适应方法(也称为参数调度)是指使用调度在训练时更新一些模型参数的策略。

这种变化将取决于模型在时间 t 的状态;例如,您可以根据损失值、迭代次数/时期数、经过的训练时间等来更新它们。

例如,一般来说,对于神经网络,学*速率的选择有几个结果;如果学*率过大,可能会超调最小值;如果它太小,可能需要很长时间才能收敛,或者可能陷入局部最小值。

适应性学*率。图片由作者提供。

在这种情况下,我们选择改变学*率作为历元的函数;这样,你可以在训练开始时设定一个较大的速率,并顺应时代的增长;您可以减小该值,直到达到较低的阈值。

你也可以把它看作是一种探索的方式与剥削的策略,所以在开始的时候,你允许更多的探索,在结束的时候,你选择剥削。

2.适配器

有几种方法可以选择来控制参数从初始值到最终阈值的形式和速度;在本文中,我将它们称为“适配器”,并且我将把重点放在将参数值改变为迭代次数的函数的方法上(在神经网络的情况下,是迭代次数)。

我将介绍一些定义和符号:

初始值表示参数的起点,结束值是经过多次迭代后得到的值,自适应速率控制从初始值到结束值的速度。

在这种情况下,每个适配器应该具有以下属性:

在本文中,我将解释三种类型的适配器:

  • 指数的
  • 相反的
  • 潜在的

2.1 指数适配器

指数适配器使用以下形式来更改初始值:

根据这个公式,alpha 应该是一个正值,以获得所需的属性。

如果我们为不同的 alpha 值绘制这个适配器,我们可以看到参数值如何随着不同的形状而减少,但是它们都遵循指数衰减;这显示了 alpha 的选择如何影响衰减速度。

在本例中,initial_value 为 0.8,end 值为 0.2。可以看到,alpha 值越大,收敛到接近 0.2 的值所需的步数/迭代次数就越少。

指数衰减。图片由作者提供。

如果您选择的初始值小于结束值,您将执行指数上升,这在某些情况下很有帮助;例如,在遗传算法中,你可能在第一代开始时有一个低的交叉概率,并随着代的发展而增加。

如果起点是 0.2,一直到 0.8,上面的图看起来是这样的:你可以看到衰变的对称性。

指数上升。图片由作者提供。

2.2 反向适配器

反向适配器使用以下形式来更改初始值:

根据这个公式,alpha 应该是一个正值,以获得所需的属性。这是适配器的外观:

逆衰变。图片由作者提供。

2.3 潜在适配器

反向适配器使用以下形式来更改初始值:

该公式要求 alpha 在(0,1)范围内,以获得所需的属性。这是适配器的外观:

潜在衰变。图片由作者提供。

2.4 比较适配器

正如我们所看到的,所有的适配器以不同的速率改变初始参数(这取决于 alpha),所以比较一下它们的行为是有帮助的;这是固定 alpha 值为 0.15 时的结果。

适配器比较。图片由作者提供。

你可以看到,潜在的适配器是一个下降更快,紧随其后的是指数;反向适配器可能需要更长次数的迭代才能收敛。

这是用于这种比较的代码,以防您想使用参数来查看其效果;首先,确保安装软件包[2]:

pip install sklearn-genetic-opt

3.Python 示例

在本节中,我们希望使用一种算法来自动调整超参数;这种算法通常带有控制优化过程的选项;例如,我将使用遗传算法,通过指数适配器来控制变异和交叉概率;这些与算法的探索与探索策略相关。

你可以查看我写的另一篇文章来了解更多关于超参数调整的遗传算法。

首先,让我们导入我们需要的包。我将使用 digits 数据集[1]并微调一个随机森林模型。

注意:我是示例中使用的包的作者;如果你想进一步了解,投稿或者提出一些建议,可以查看本文末尾的文档和 GitHub 资源库。

para_grid 参数界定了模型的超参数搜索空间,并定义了数据类型;我们将使用交叉验证准确性来评估模型的超参数。

我们定义了优化算法,并创建了自适应交叉和变异概率。我们将从高变异概率和低交叉概率开始;随着代数的增加,交叉和变异概率将分别增加和减少。

我们还将打印和绘制一些统计数据来理解结果。

在这个特定的例子中,我得到了 0.941 的准确度分数(在测试数据上),并找到了这些参数:

{‘min_weight_fraction_leaf’: 0.01079845233781555, ‘bootstrap’: True, ‘max_depth’: 10, ‘max_leaf_nodes’: 27, ‘n_estimators’: 108}

您可以检查搜索空间,它显示了该算法研究了哪些超参数。

带适配器的示例空间。图片由作者提供。

作为参考,这是没有自适应学*的采样空间的样子;该算法探索了具有固定低变异概率(0.2)和高交叉概率(0.8)的较少区域。

没有适配器的采样空间。图片由作者提供。

结论

当训练机器学*算法时,调整或调度参数可能非常有用;它可以让你更快地收敛算法,或者用动态策略探索复杂的空间区域,即使文献主要将它们用于深度学*,正如我们已经展示的那样,你也可以将它用于传统的机器学*,并调整其思想,将其扩展到任何其他可能适合变化参数策略的问题集。

如果你想了解更多关于 sklearn-genetic-opt 的信息,你可以查看这里的文档:

https://sklearn-genetic-opt.readthedocs.io/en/stable/index.html [## sklearn genetic opt 文档

Sklearn-genetic-opt 使用 deap 包中的进化算法来选择一组超参数…](https://sklearn-genetic-opt.readthedocs.io/en/stable/index.html)

参考

知识共享署名 4.0 国际 (CC BY 4.0)许可下的[1]数字数据集:https://archive-beta . ics . UCI . edu/ml/datasets/optical+recognition+of+手写+数字

[2] sklearn-genetic-opt 回购:【https://github.com/rodrigo-arenas/Sklearn-genetic-opt

如何使用 Pi 增强汽车上的 ADAS?

原文:https://towardsdatascience.com/adas-collision-avoidance-system-on-indian-cars-bac64cc8a863

启用防撞系统(CAS) &使用 Pi 在您的汽车上实现智能环绕视野。这种低成本的解决方案,即 T2 使用的技术,如激光雷达-相机低空传感器融合技术,非常适合发展中国家。

虽然印度只占 1%的车辆,世界银行的调查报告全球道路死亡的 11%发生在印度!在发展中国家,加强道路安全势在必行,在这些国家,大多数车辆没有先进的驾驶辅助功能,他们也负担不起为提高安全性而升级汽车的费用。此外,这些国家提出了一系列独特的挑战。这些包括过时的车辆,缺乏人行车道,混乱的交通,动物过马路,等等。

在这种背景下,该解决方案旨在为印度最便宜的汽车配备** 超便宜的 ADAS 级,即防撞和智能全景。配有前方碰撞预警系统(FCW)或自主紧急制动系统(AEB)的现代汽车价格昂贵,但**我们可以以较低的成本在旧车上增加这些功能。****

项目演示

ADAS-CAS 小工具通过声光指示器警告驾驶员

此解决方案的完整源代码可在 此处 获得

这个想法是使用电池供电的 Pi 连接到安装在汽车引擎盖上的激光雷达、Pi Cam、LED SHIM 和 NCS 2,以感知前方物体的深度和方向。这个不仅启用了** 前向碰撞预警系统,还启用了 智能驾驶辅助,对交通标志 或行人、沿路边行走或过马路发出警报。**

激光雷达使用激光束根据反射时间计算距离。

激光测距[5]。c =光速

相机的分辨率通常比激光雷达高,但相机的 FOV 有限,无法估计距离。旋转激光雷达360 视场, Pi Cam 只有 62x48 度 水* x 垂直视场。当我们在这里处理多个传感器时,我们需要使用视觉融合技术来整合传感器输出,即获得车辆前方障碍物的距离和角度。在动手实施之前,我们先讨论一下传感器融合的理论基础。

传感器融合的思想

每种传感器都有自己的优缺点。以雷达为例,它的分辨率很低,但却擅长在没有视线的情况下进行测量。在自动驾驶汽车中,通常使用激光雷达、雷达和摄像头的组合来感知环境。这样,我们可以通过结合所有传感器的优点来弥补缺点。

  • 相机:非常适合理解场景或对物体进行分类
  • 激光雷达:优于利用脉冲激光波估计距离
  • 雷达:可以利用多普勒效应测量障碍物的速度

该相机是一个 2D 传感器,通过它可以识别边界框、交通灯、车道划分等特征。激光雷达是一种输出一组点云的 3D 传感器。融合技术找到激光雷达探测到的点和摄像机探测到的点之间的对应关系。为了统一使用激光雷达和相机来构建 ADAS,需要通过以下步骤将 3D 传感器输出与 2D 传感器输出融合。

1.将激光雷达点云** (3D)投影到 2D 图像上。**

2.使用 YOLOv4 等算法进行物体检测

3.匹配 ROI** 找到感兴趣的激光雷达投影点。**

激光雷达-相机传感器融合[2]

通过以上 3 个步骤,周围的** 物体将使用激光雷达-相机融合进行测量和分类。**

激光雷达-相机传感器融合考虑

当来自 cam 的原始图像与来自雷达或激光雷达的原始数据融合时,这被称为低级融合或早期融合。在后期融合中,检测在融合之前完成。请注意,在 2D 影像上投影 3D 激光雷达点云存在许多挑战。在执行融合时,必须考虑两个传感器之间的相对方位和*移

  • 旋转:激光雷达和相机的坐标系可以不同。激光雷达上的距离可能在 z 轴上,而相机上的距离在 x 轴上。我们需要在激光雷达点云上应用旋转以使坐标系相同,即将每个激光雷达点乘以 旋转矩阵。****

我们需要旋转,使激光雷达和相机坐标系相同

  • 翻译:在自动驾驶汽车中,激光雷达可以位于中央顶部,摄像头位于两侧。每个装置中激光雷达和摄像机的位置可以不同。基于相对传感器位置,通过乘以*移矩阵*移激光雷达点。****
  • 立体校正:对于立体摄像机设置,我们需要 做立体校正 使左右图像共面。因此,我们需要乘以矩阵 R0 来沿着水*核线对齐所有东西。****
  • 内在校准:校准是告诉你的相机如何将 3D 世界中的点转换成像素的步骤。为此,我们需要乘以包含工厂校准值的固有校准矩阵。

内在校准矩阵。f =焦距。c =光学中心

综上所述,我们需要将激光雷达点乘以所有的 4 个矩阵才能投影到相机图像上。

将 3D 中的点 X 投影到 2D 的点 Y 上,

激光雷达-相机投影公式

  • P =摄像机内部校准矩阵
  • R0 =立体校正矩阵
  • R|t =旋转&从激光雷达到摄像机的*移
  • X =三维空间中的点
  • Y = 2D 图像中的点

请注意,我们将刚体变换、旋转和*移组合在一个矩阵 R|t 中。将这三个矩阵 P、R0 和 R|t 放在一起,说明外部和内部校准将激光雷达点投影到相机图像上。然而,矩阵值高度依赖于我们定制的传感器安装。

这只是拼图的一部分。我们的目标是为任何廉价汽车增加一个端到端防撞系统 和智能全景。这将包括我们选择的传感器、传感器位置、数据采集、自定义视觉融合和物体检测,以及一个数据分析节点,以实现传感器间的同步,从而触发驾驶员辅助警告以避免危险。

RPi 和 RPLIDAR A1 的实际实施

首先,我们需要用 RPLIDAR A1、Pi Cam、LED 垫片和 NCS 2 组装 Pi。 2D 激光雷达被用来代替 3D 激光雷达,因为我们的目标是使这个小玩意最便宜成为可能。该装置由 5V 3A 10K 毫安电池供电。为了便于组装,激光雷达支架是 3D 打印的并附在 RPi 上。挂载设计的一部分取自从这里获得的 STL 文件

STL 可视化:Raspberry Pi 的激光雷达挂载

使用微型 USB 电缆将 RPLIDAR A1 与连接到 Pi USB 的 USB 适配器连接。激光雷达的适配器提供电源,并将激光雷达的内部 UART 串行接口转换为 USB 接口。使用 Aux-to-Aux 电缆将 RPi 连接到扬声器。由于物理限制,使用 LED 垫片代替 Blinkt 来发出警告信息。虽然ADAS 小工具的总成本约为 150-200 美元,人们可能需要至少再支付10-20000 美元, 才能获得具有如此先进功能的汽车模型。

让我们想象一下,3D 激光雷达的连接方式与上述相同。首先,我们将尝试在上面的小工具上解决 3D 激光雷达-相机传感器融合。然后我们将看到 2D 激光雷达-相机融合的变化,以便使其在 RPLIDAR A1 上工作。

安装在汽车引擎盖上的 ADAS 设备

3D 激光雷达-相机传感器融合

从上面的讨论中可以清楚地看到,我们需要进行旋转、*移、立体校正和内部校准来将激光雷达点投影到图像上。我们将基于我们构建的自定义小工具尝试应用上述公式。

从上面的图像中,您可以估计 Pi Cam 位于激光雷达扫描*面下方 10 mm 处。即沿着 3D 轴的[0,-10,0] 的*移。考虑将威力登 HDL-64E 作为我们的 3D 激光雷达,其需要 180°旋转以将坐标系与 Pi Cam 对齐。我们现在可以计算 R|t 矩阵了。****

当我们在这里使用一个单目摄像机时,立体校正矩阵将是一个单位矩阵。我们可以根据 V2 Pi Cam 的硬件规格制作内部校准矩阵。****

我们可以输入“n”个点,而不是 1 个点

树莓派 V2 相机,****

  • 焦距(FL) = 3.04 毫米
  • FL 像素=焦距 sx,其中 sx =真实世界与像素的比率*
  • 焦距 sx = 3.04mm 毫米 (1/ 0.00112 毫米每像素)= 2714.3 像素**

由于形状不匹配,矩阵无法相乘。为了使它工作,我们需要通过添加 0 和 1 作为最后一行或一列来从欧几里得坐标转换到齐次坐标。完成乘法运算后,我们需要将转换回齐次坐标。

欧几里德到齐次的相互转换

在 3D 点云上应用投影公式后,可以看到 3D LIDAR-CAM 传感器融合投影输出。从 360 威力登 HDL-64E 和摄像机下载输入传感器数据并输入。

然而, 3D 激光雷达的成本是构建廉价解决方案的一个障碍。我们可以使用便宜的 2D 激光雷达,并做必要的调整,因为它只能扫描一条水*线。

2D 激光雷达-相机传感器融合

我们的小工具配备了 2D 反相激光雷达 A1,以最大限度地降低成本。这台激光雷达在 2D *面上扫描环境,与相机*面正交。旋转扫描将对从 0°到 360°的每个角度估计到障碍物的距离。由于激光雷达 w.r.t. Pi Cam 在小工具中的位置,相机在激光雷达几何图形上处于+90°。但是请注意 Pi 凸轮 V2 的视野在水* x 垂直方向分别为62 x48****

设备的集成前视图如下所示。

激光雷达-照相机几何学

由于激光雷达和相机传感器数据都可以在正面 62 弧中获得,我们需要融合这些数据。在激光雷达扫描*面中,相机数据从+59 到+59+62=121。我们可以在图像上运行对象检测来获得感兴趣对象的边界框。例如:人、汽车、自行车、红绿灯等。由于 2D 激光雷达只有宽度信息,因此只考虑每个边界框的 x_min 和 x_max。****

我们需要计算对应于图像像素的激光雷达角度,以便估计到像素的距离。为了找到到边界框内物体的距离,使用下面的公式计算对应于 x_min & x_max 的θ_min 和θ_max基于上图,

w =图像宽度。对θ_max 也应用相同的公式

现在,您可以根据最新的激光雷达扫描数据找到θ_min 和θ_max 之间每个角度的距离。然后计算对着物体边界框的所有激光雷达点的中间距离 以估计物体深度。如果距离低于阈值,则基于角度触发警告。如果在后续帧中长方体中心移动了很大距离,则重复警告。

为了构建无阻塞的系统流程,采用了模块化架构,其中,每个独立节点依赖于不同的硬件组件。“物体检测”节点使用 Movidius** 进行推断,而“距离估计”节点将 LIDAR 数据作为输入,而“警报”模块向 Pimoroni Blinkt 和 扬声器发送信号。模块通过 MQTT 消息就各自的主题进行**交流。****

架构图

3 个独立的 MQTT 节点,每个都链接到不同的硬件,运行在 Pi 上

时间同步模块负责传感器融合的“数据相关性因子”。对于 ADAS,“节点 1”检测到的物体的位置可能会随着物体的移动而改变。因此,边界框的距离估计可能会在 2-3 秒后出错(而消息可能会保留在 MQTT 队列中)。为了同步,当前时间= 60 *分钟+秒被附加到消息中(忽略滞后的消息)。****

模型输出从节点 1 发送到节点 2,在此发生 LiDAR-Cam 传感器融合,进一步将消息推送到节点 3。为了使系统正常运行,3 个 MQTT 节点应该协同工作,由 MQTT 消息进行编排,发布和订阅各自的主题。

在这篇文章的顶部,你可以看到这个小工具行驶在印度的道路上,在感知到周围的物体以及它们的深度和方向后,给出驾驶员辅助警报。扬声器内部连线或集成蓝牙扬声器,使驾驶员更容易听到通知。

这个 ADAS 设备可以连接到 can 总线上,让它加速、转向或刹车。RPi 没有内置的 CAN 总线,但它的 GPIO 包括 SPI 总线,它受到许多 CAN 控制器如 MCP2515 的支持。因此,通过将该设备连接到 can 总线,可以实现自动紧急制动(AEB)和防撞系统(CAS)。****

适应印度的条件

印度的交通难题如此独特,以至于需要定制的解决方案。首先,我们需要用印度的交通工具训练物体检测模型,比如卡车、tempos、货车、汽车、人力车等等。

此外,为了增强智能环绕视图,我们需要用印度交通标志和标牌训练 型号 ,以便在印度道路上给出更有意义的驾驶员辅助警告。这在印度是常*的景象,像牛、猪、水牛、山羊、狗等动物。,穿越道路和高速公路。因此,检测它们也是有益的。

YOLO 能够对行走在印度道路上的奶牛进行分类

对于概念验证,请参* SSD-Mobilenet 模型的输出,该模型被训练用于根据印度招牌对印度交通标志进行分类。你可以进一步对交通标志进行分类,以破译标志的确切含义。

SSD-MobileNet 模型能够对印度交通标志(黄色 Bbox)和标志牌(绿色 Bbox)进行分类

*带注释的印度交通标志数据集由印度 Datacluster 实验室提供。他们还没有完成印度车辆”数据库的注释。*只是训练时间问题 制造这个小玩意,为印度量身定做。

为了从图像中找出 ROI,我们使用了 SSD MobileNet 对 COCO 进行了训练,过滤了潜在的对象。为了只检测人和车辆,你可以使用这种模式来获得更好的速度和准确性。

更重要的是,可以用你定制的带注释的数据训练一个对象检测模型,用 OpenVINO 做硬件优化,部署在 Pi 上,只要这些层受 OpenVINO 支持。通过这样做,我们可以在 RPi 上部署一个对象检测模型来定位定制对象。

1.首先,选择针对低功耗硬件的高效对象检测模型,如 Efficientdet、SSD-Mobilenet、Tiny-YOLO、YOLOX 等。我在 RPi 4B 和 SSD-Mobilenet 上对所有提到的模型进行了实验 获得了最高的 FPS。

2.使用您的自定义数据进行对象检测模型的迁移学*

3.转换经过培训的*。pb 文件到中间表示** — 。xml 和。使用**模型优化器的 bin。****

export PATH = "<omz_dir>/deployment _ tools/inference _ engine/demos/common/python/😒 PATH "</omz_dir>

python 3<OMZ _ 目录>/部署 _ 工具/模型 _ 优化器/mo_tf.py** —输入 _ 模型<冻结 _ 图形. pb > —反向 _ 输入 _ 通道—输出 _ 目录<输出 _ 目录>—tensor flow _ object _ detection _ API _ pipeline _ config<到 SSD _ mobilenet _ v2 _ coco . config>的位置—tensor flow _ use _ custom _ operations _ config【T61**

python 3 object _ detection _ demo . py-d CPU-I<input_video>—labels labels . txt-m—在 ssd</input_video>

4.最后,在 Pi 上部署硬件优化模型

此解决方案的完整源代码可在 此处 获得

如有任何疑问或建议,可在此 联系我https://www.linkedin.com/in/ananduthaman/

参考

1.激光雷达-相机传感器融合高水*:【https://www.thinkautonomous.ai/blog/?】T43p =自动驾驶汽车中的激光雷达和摄像头传感器融合**

2.Adafruit 的激光雷达数据扫描码存根:https://learn . Adafruit . com/remote-IOT-environmental-sensor/code**

3.摄像机标定和内禀矩阵估计:https://www . cc . gatech . edu/classes/ay 2016/cs 4476 _ fall/results/proj 3/html/agartia 3/index . html**

4.自动驾驶汽车的视觉融合*PyImageSearch 大学的课程:【https://www.pyimagesearch.com/pyimagesearch-university/ ***

5.【https://en.wikipedia.org/wiki/Lidar】激光雷达距离估计:

6. RPLIDAR A1 M8 硬件规格:https://www . generation robots . com/media/RP lidar-A1 M8-360 度激光扫描仪-开发-套件-数据表-1.pdf

7.模型训练,数据清洗&增强:www.roboflow.com**

8。印度交通标志模型已经使用由印度数据集群实验室提供的交通数据集进行了训练。****

如何在熊猫中添加新的空列

原文:https://towardsdatascience.com/add-empty-col-pandas-23d323f0fcc7

使用 Python 向现有 pandas 数据框架添加空列

凯利·西克玛Unsplash 上拍摄

在我最近关于 Medium 的一些文章中,我们讨论了如何基于其他列的值在 Pandas 数据帧中添加新列。

另一个通常用户需要在数据帧上应用的类似操作是在现有的帧中添加一个新的空列。当我们希望以后填充该列,而不是仅仅用一些特定的值初始化它时,这通常是有用的,无论是硬编码的还是基于一些其他的计算。

在今天的简短教程中,我们将演示如何在现有的 pandas 数据框架中添加这样的空列。

首先,让我们创建一个示例数据框架,我们将在本文中引用它来演示一些概念。

import pandas as pddf = pd.DataFrame(
    [
        (1, 121, True), 
        (2, 425, False),
        (3, 176, False),
        (4, 509, False),
        (5, 120, True), 
        (6, 459, False),
        (7, 981, True),
        (8, 292, True),
    ], 
    columns=['colA', 'colB', 'colC']
)print(df)
 ***colA  colB   colC*** *0     1   121   True
1     2   425  False
2     3   176  False
3     4   509  False
4     5   120   True
5     6   459  False
6     7   981   True
7     8   292   True*

在 Pandas 中创建新的空列

因为我们希望新列为空,所以我们实际上可以为每条记录分配numpy.nan值。插入一个没有值的新列非常简单

import numpy as npdf['colD'] = np.nanprint(df)
 ***colA  colB   colC  colD*** *0     1   121   True   NaN
1     2   425  False   NaN
2     3   176  False   NaN
3     4   509  False   NaN
4     5   120   True   NaN
5     6   459  False   NaN
6     7   981   True   NaN
7     8   292   True   NaN*

指定空列的数据类型

现在,尽管 DataFrame 中新创建的列是空的,但我们可能希望指定特定的 dtype。期望是在某个时候这个空列将被填充一些值(否则一开始创建它有什么意义!).

我们可以通过调用dtypes属性来打印出 DataFrame 中每一列的数据类型:

>>> df.dtypes
>>> df.dtypes
*colA      int64
colB      int64
colC       bool
colD    float64
dtype: object*

Pandas 自动创建了一个类型为float64的空列——这是因为默认情况下np.nan的类型是 float。

>>> type(np.nan)
*<class 'float'>*

相反,我们可能打算在新创建的空列中存储布尔值。在这种情况下,我们可以在创建列后直接转换它,如下所示:

import numpy as npdf['colD'] = np.nan
df['colD'] = df['colD'].astype('boolean')print(df.dtypes)
*colA      int64
colB      int64
colC       bool* ***colD    boolean*** *dtype: object*

最后的想法

有时,我们可能需要在现有的 pandas 数据帧中添加一个空列,以便以后填充。在今天的简短教程中,我们演示了如何创建这样的列,以及如何将其数据类型更改为所需的类型。

成为会员 阅读介质上的每一个故事。你的会员费直接支持我和你看的其他作家。你也可以在媒体上看到所有的故事。

https://gmyrianthous.medium.com/membership

相关文章你可能也喜欢

在 Data Studio 中添加多个比较期间

原文:https://towardsdatascience.com/add-multiple-comparison-periods-in-data-studio-533b41e71a5a

一目了然地发现您的表现,比较不同的时间段

艾萨克·史密斯在 Unsplash 上拍摄的照片

介绍

您是否遇到过这样的情况:在分析数据时,您需要同时了解“以前”和“同比”的变化?你知道这不是科幻小说中的场景,当你想要执行一个完整而有洞察力的数据分析时,这种情况经常发生。🤓

Data Studio 是一个功能强大的工具,它为您提供了大量漂亮的图表来可视化您的数据并高效地讲述您的故事。但是,当您想要比较两个不同日期期间的数据性能时,会发生什么情况呢?

让我们考虑一下使用 Data Studio 时的直接选项:

  1. 你可以决定你最想要什么,因为没有办法把两个比较日期加到一个图中。
  2. 您创建了一个全新的页面(第一个页面的副本)来添加第二个比较期间。

好吧,不要失望,因为我有一个解决方案给你,这将引导你到一个美丽而有洞察力的视觉化。

该过程

出于本文的目的,我将使用来自谷歌商品商店的模拟账户的谷歌分析数据。当然,您可以使用任何来源的数据,包括历史信息。

过程背后的想法:我需要什么?

让我们再次运用我们的创新思维…

我将要描述的解决方案仅适用于记分卡,包括:

  • 两个相同指标的记分卡。
  • 每个记分卡的不同比较日期。
  • 一点点定制看起来花里胡哨。

让我们这样做吧…

我将尽可能描述得更详细,以方便您的生活,并能够专注于您的数据,而不是可视化的机制。

第一步:连接你的数据源

在开始为报表创建记分卡之前,您需要首先连接数据。

在 Data Studio 的众多连接器中进行选择…

作者照片

…选择包含您要分析的数据的数据库…

作者照片

…并将它们添加到您的报告中。

作者照片

第二步:创建你的第一张记分卡

点击“添加图表”选项,选择“记分卡”选项…

作者照片

…并为您的记分卡选择所需的指标。

作者照片

第三步:选择您的主要比较日期

转到“数据”窗格,向下滚动到“默认日期范围”部分,然后单击“比较日期范围”下拉菜单…

作者照片

…选择“前期”选项,然后单击“应用”。

作者照片

步骤 4:复制您的记分卡

使用完全相同的指标复制您的记分卡,以便创建二级比较计算。

作者照片

第五步:选择你的第二比较日期

对于第二个记分卡,选择“上一年”选项,遵循与之前相同的步骤。

作者照片

第六步:让你的视觉富有洞察力

更改第二个记分卡的标签颜色—我选择白色,因为我的背景颜色,但您应该选择与仪表板背景相匹配的颜色。

作者照片

正确安排图表——将第二张记分卡放在后面,或者将第一张放在前面。

作者照片

转到“填充”部分,从“行高”下拉列表中为您的主要记分卡留出一些空间,我通常选择 48,但这取决于您。

作者照片

为比较添加标签,并为文本选择更中性的颜色,以使视觉效果易于阅读。

作者照片

第七步:向仪表盘添加更多数据

你不必就此打住!将更多信息添加到您的仪表板,以讲述您的完整故事…

作者照片

这就对了!!!✨

最后的想法

我已经说过很多次我对 Data Studio 的钦佩。这是一个强大的工具,在可视化方面有很多选项。其中一些是直截了当的,而另一些则需要更多的挖掘。但是没有一次我不能得到我想要的任何东西。所以,每当你在使用 Data Studio 得到你想要的东西时遇到困难,后退一步,想得更简单,尝试不同的解决方案,直到你得到你想要的结果…我告诉你,你永远不会输。

我叫 Alexandra Poulopoulou,是希腊 Reprise Digital 的一名数据和分析架构师。在我的职业生涯中,我参与了几个分析项目,以推动成功的商业决策。

如果你喜欢刚刚阅读的内容,请在 MediumLinkedInTwitter 上关注我,了解更多信息。

如果你愿意支持我们的努力,你可以点击并订阅这里

向 Python 组合图添加第三个 Y 轴

原文:https://towardsdatascience.com/adding-a-third-y-axis-to-python-combo-chart-39f60fb66708

使用 Matplotlib、Seaborn 和 Pandas plot()创建多 Y 轴组合图的实践教程

艾萨克·史密斯Unsplash 上拍摄的照片

可视化数据对于分析数据至关重要。如果你看不到你的数据——从多方面看,你将很难分析这些数据。

来源于 Python 数据【1】

Python 中有许多不同的图形来可视化数据,幸好有 Matplotlib、Seaborn、Pandas、Plotly 等。在数据分析过程中,你可以做一些非常强大的可视化。其中组合图是在同一个图形上两种图表类型(如条形图和折线图)的组合。这是 Excel 最受欢迎的内置图表之一,广泛用于显示不同类型的信息。

在之前的文章中,我们已经讨论了如何创建双轴组合图。在某些情况下,添加第三个或更多的 y 轴非常有用,可以直观地突出不同数据集之间的差异。在本文中,我们将探索如何用 Matplotlib、Seaborn 和 Pandas plot()添加第三个 y 轴。这篇文章的结构如下:

  1. Matplotlib
  2. 海生的
  3. 熊猫plot()

请查看笔记本获取源代码。更多教程可从 Github Repo 获得。

为了演示,我们将使用来自维基百科的伦敦气候数据:

**x** = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
**average_temp** = [5.2, 5.3,7.6,9.9,13.3,16.5,18.7, 18.5, 15.7, 12.0, 8.0, 5.5]
**average_percipitation_mm** = [55.2, 40.9, 41.6, 43.7, 49.4, 45.1, 44.5, 49.5, 49.1, 68.5, 59.0, 55.2]
**average_uv_index** = [1,1,2,4,5,6,6,5,4,2,1,0]london_climate = pd.DataFrame(
  {
    'average_temp': average_temp,
    'average_percipitation_mm': average_percipitation_mm,
    'average_uv_index': average_uv_index
  }, 
  index=x
)

在同一个图表上绘制多个图表非常容易。例如,使用 Matplotlib,我们可以简单地一个接一个地调用图表函数。

plt.**plot**(x, average_temp, "-r", label="average temp")
plt.**plot**(x, average_percipitation_mm, "-b", label="average percipitation mm", )
plt.**plot**(x, average_uv_index, "-g", label="average temp")plt.legend(loc="upper left")
plt.show()

单轴组合图(图片由作者提供)

这当然会创建一个组合图,但是所有的线条都使用相同的 Y 轴。查看和解释可能非常困难,尤其是当数据在不同的范围内时。我们可以使用多个 Y 轴来改进它。但是一开始使用多个 Y 轴可能会有点混乱。让我们继续探索如何向 Python 组合图添加第三个 Y 轴。

1.Matplotlib 添加第三个 Y 轴

在上一篇文章中,我们已经学*了通过调用twin()生成共享同一 X 轴的两个独立的 Y 轴来制作双轴组合图的技巧。通过创建另一个twinx()轴并使用set_postion()偏移第三个轴的右脊椎位置,可以类似地创建第三个 y 轴:

# Create figure and axis #1
fig, ax1 = plt.subplots()# plot line chart on axis #1
p1, = ax1.plot(x, average_temp) 
ax1.set_ylabel('average temp')
ax1.set_ylim(0, 25)
ax1.legend(['average_temp'], loc="upper left")
ax1.yaxis.label.set_color(p1.get_color())
ax1.yaxis.label.set_fontsize(14)
ax1.tick_params(axis='y', colors=p1.get_color(), labelsize=14)# set up the 2nd axis
**ax2 = ax1.twinx()** 
# plot bar chart on axis #2
p2, = ax2.plot(x, average_percipitation_mm, color='orange')
ax2.grid(False) # turn off grid #2
ax2.set_ylabel('average percipitation mm')
ax2.set_ylim(0, 90)
ax2.legend(['average_percipitation_mm'], loc="upper center")
ax2.yaxis.label.set_color(p2.get_color())
ax2.yaxis.label.set_fontsize(14)
ax2.tick_params(axis='y', colors=p2.get_color(), labelsize=14)# set up the 3rd axis
**ax3 = ax1.twinx()**
# Offset the right spine of ax3\.  The ticks and label have already been placed on the right by twinx above.
**ax3.spines.right.set_position(("axes", 1.15))**
# Plot line chart on axis #3
p3, = ax3.plot(x, average_uv_index, color='red')
ax3.grid(False) # turn off grid #3
ax3.set_ylabel('average UV index')
ax3.set_ylim(0, 8)
ax3.legend(['average_uv_index'], loc="upper right")
ax3.yaxis.label.set_color(p3.get_color())
ax3.yaxis.label.set_fontsize(14)
ax3.tick_params(axis='y', colors=p3.get_color(), labelsize=14)plt.show()

像我们通常做的那样,在ax1上绘制第一条线图。我们调用ax2 = ax1.twinx()来设置第二轴并绘制第二线图。之后,我们再次调用ax3 = ax1.twinx()来设置第三轴并绘制第三线图。窍门是调用ax3.spines.right.set_position(("axes", 1.15))偏移ax3的右脊线。请注意,调用ax2.grid(False)ax3.grid(False)是为了避免网格显示问题。通过执行代码,您应该得到以下输出:

使用 Matplotlib 的第三个 y 轴组合图(图片由作者提供)

3.Seaborn 添加第三个 Y 轴

Seaborn 是一个构建在 Matplotlib 之上的高级数据可视化库。在幕后,它使用 Matplotlib 来绘制它的情节。对于底层配置和设置,我们总是可以调用 Matplotlib 的 API,这就是在 Seaborn 中制作多 Y 轴组合图的诀窍:

# plot line chart on axis #1
ax1 = sns.lineplot(
    x=london_climate.index, 
    y='average_temp', 
    data=london_climate, 
    sort=False, 
    color='blue'
)
ax1.set_ylabel('average temp')
ax1.set_ylim(0, 25)
ax1.legend(['average_temp'], loc="upper left")
ax1.yaxis.label.set_color('blue')
ax1.yaxis.label.set_fontsize(14)
ax1.tick_params(axis='y', colors='blue', labelsize=14)# set up the 2nd axis
**ax2 = ax1.twinx()**
# plot bar chart on axis #2
sns.lineplot(
    x=london_climate.index, 
    y='average_percipitation_mm', 
    data=london_climate, 
    sort=False, 
    color='orange', 
    **ax = ax2**       # Pre-existing axes for the plot
)
ax2.grid(False) # turn off grid #2
ax2.set_ylabel('average percipitation mm')
ax2.set_ylim(0, 90)
ax2.legend(['average_percipitation_mm'], loc="upper center")
ax2.yaxis.label.set_color('orange')
ax2.yaxis.label.set_fontsize(14)
ax2.tick_params(axis='y', colors='orange', labelsize=14)# set up the 3rd axis
**ax3 = ax1.twinx()**
# Offset the right spine of ax3\. The ticks and label have already been placed on the right by twinx above.
**ax3.spines.right.set_position(("axes", 1.15))**
# Plot line chart on axis #3
p3 = sns.lineplot(
    x=london_climate.index, 
    y='average_uv_index', 
    data=london_climate, 
    sort=False, 
    color='red', 
    **ax = ax3**       # Pre-existing axes for the plot
)
ax3.grid(False) # turn off grid #3
ax3.set_ylabel('average UV index')
ax3.set_ylim(0, 8)
ax3.legend(['average_uv_index'], loc="upper right")
ax3.yaxis.label.set_color('red')
ax3.yaxis.label.set_fontsize(14)
ax3.tick_params(axis='y', colors='red', labelsize=14)plt.show()

sns.lineplot()返回一个 Matplotlib 轴对象ax1。然后,类似于 Matplotlib 解决方案,我们调用ax2 = ax1.twinx()来设置第二个轴。之后,使用参数ax = ax2调用sns.lineplot()在现有轴ax2上绘图。对于第 3 行,我们再次调用ax3 = ax1.twinx()来设置第 3 轴,并使用参数ax=ax3调用sns.lineplot()在现有轴ax3上绘图。我们应用同样的技巧ax3.spines.right.set_position(("axes", 1.15))来偏移ax3的右脊椎。通过执行代码,您应该得到以下输出:

使用 Seaborn 的第三个 y 轴组合图(图片由作者提供)

4.熊猫图()-添加第三个 Y 轴

熊猫用plot()法制作图表。默认情况下,它调用 Matplotlib 的 API。我们可以将参数secondary_y设置为True,以允许在辅助 Y 轴上绘制第二个图表。要添加带有第三个 Y 轴的第三个图表,我们可以应用与之前相同的技巧。

# Create the figure and axes object
fig, ax = plt.subplots()# Plot the first x and y axes:
london_climate.plot(
    use_index=True, 
    y='average_percipitation_mm', 
    **ax=ax,** 
    color='orange'
)
ax.set_ylabel('average_percipitation_mm')# Plot the second x and y axes. 
# By secondary_y = True a second y-axis is requested
ax2 = london_climate.plot(
    use_index=True, 
    y='average_temp', 
    **ax=ax,** 
    **secondary_y=True,** 
    color='blue'
)
ax.legend().set_visible(False)
ax2.set_ylabel('average_temp')# Plot the third x and y axes
**ax3 = ax.twinx()
ax3.spines.right.set_position(("axes", 1.15))**
london_climate.plot(
    use_index=True, 
    y='average_uv_index', 
    **ax=ax3,** 
    color='red'
)
ax3.grid(False)
ax3.set_ylabel('average_uv_index')# Set up legends
ax3.legend(
    [ax.get_lines()[0], ax2.get_lines()[0], ax3.get_lines()[0]], 
    ['average_percipitation_mm','average_temp','average_uv_index'], 
    loc="upper left"
)plt.show()

注意,我们设置use_index=True使用索引作为 x 轴的刻度。通过执行代码,您应该得到以下输出:

使用熊猫图()的第三个 y 轴组合图(图片由作者提供)

结论

在本文中,我们学*了如何用SeabornPandas plot()创建一个多 Y 轴组合图。组合图是数据可视化中最流行的图表之一,知道如何创建多 Y 轴组合图对分析数据非常有帮助。

感谢阅读。请查看笔记本获取源代码,如果您对机器学*的实用方面感兴趣,请继续关注。更多教程可从 Github Repo 获得。

参考

在拥抱脸模型上添加自定义层

原文:https://towardsdatascience.com/adding-custom-layers-on-top-of-a-hugging-face-model-f1ccdfc257bd

了解如何从拥抱脸模型体中提取隐藏状态,在其上修改/添加特定于任务的层,并使用 PyTorch 端到端地训练整个自定义设置

在开始之前,这篇文章假设对拥抱脸有基本的了解(使用开箱即用的模型)。此外,在 拥抱脸 的人们大声喊出来,建立一个对初学者友好的学*环境!

你会从这个博客中学到什么?

  1. 从拥抱面部中枢使用特定于任务的模型,并使它们适应你手头的任务。
  2. 将模型的头部与身体分离,并使用身体来利用特定领域的知识。
  3. 在 PyTorch 中构建一个定制的头部并将其连接到 HF 模型的主体上,并对系统进行端到端的训练。

拥抱脸模型的剖析

这是一个典型的高频模型的样子

作者图片

为什么我需要分别使用头部和身体?

拥抱脸的一些模型在问答或文本分类等下游任务中接受训练,并包含关于它们在权重中接受训练的数据的知识。

有时,特别是当我们手头的任务包含非常少的数据或者是特定领域的任务(如医疗或体育特定任务)时,我们可以利用 中枢 上接受过任务(不一定与我们手头的任务相同,但属于同一领域,如体育或医疗)训练的其他模型,并利用这些模型的一些预先训练的知识来提高我们自己任务的性能。

  1. 一个非常简单的例子是,假设我们有一个小数据集来分类一些财务报表在情绪方面是积极的还是消极的。然而,我们去了中心,发现很多模型已经被训练用于与金融相关的 QA。我们可以从这些模型中使用T21s来改进我们自己的任务。
  2. 另一个简单的例子是,当某个特定于领域的模型已经学会从一个巨大的数据集中将文本分类成 5 个类别时,它是在上被训练的。假设我们有一个相似的分类任务,一个完全不同的数据集在同一个域中,我们只想将数据分为 2 类而不是 5 类。我们可以再次使用模特的身体,并添加我们自己的头部,试图在我们自己的任务中增加特定领域的知识。

概略地说,这就是我们正在努力做的

作者图片

作者图片

跳入代码!

我们的任务很简单,讥讽检测来自 Kaggle 的https://www.kaggle.com/rmisra/news-headlines-dataset-for-sarcasm-detection数据集。

你可以在这里 查看完整代码 。出于时间的考虑,我没有包括下面的预处理和一些训练细节,所以请确保查看笔记本以获得完整的代码。

我将使用一个在巨大的推特语料库上训练的具有 5 个分类输出的模型来分类 5 种不同的情绪,提取身体并在 PyTorch 中为我们的任务添加自定义层(2 个标签,讽刺和非讽刺),并端到端地训练新模型。

注意:您可以使用本例中的任何模型(不一定是为分类而训练的模型),因为我们将只使用该模型的身体,而不使用头部。

这就是我们的工作流程

作者图片

我将跳过数据预处理步骤,直接跳到主类,但是您可以在本节开头的链接中查看完整的代码。

标记化和动态填充

提取身体并添加我们自己的层

如你所*,我们首先从 PyTorch 中派生出 nn 模块的子类,使用 AutoModel(从 transformers 中)提取模型主体,并向我们想要使用其主体的模型提供检查点。

注意,返回一个token classifier output(来自变形金刚库)** ,这确保我们的输出与中枢上的拥抱人脸模型的输出格式相似。**

端到端培训新模型

如您所*,我们使用这种方法获得了不错的性能。请记住,这篇博客的目的不是分析这个特定数据集的性能,而是学*如何使用预先训练好的身体并添加自定义头部。****

结论

我们看到了如何使用 Hugging Face Hub 向预训练模型的身体添加自定义层。

一些要点:

  1. 这种技术在以下情况下特别有用:我们有特定于领域的小型数据集,并且希望利用在同一领域(任务不可知)的大型数据集上训练的模型来提高小型数据集的性能。
  2. 我们可以选择已经在不同于我们自己的任务的下游任务上训练过的模型,并且仍然使用来自该模型主体的知识。
  3. 如果您的数据集足够大且通用,这可能完全没有必要,在这种情况下,您可以使用 AutoModelForSequenceClassification 或任何其他您必须使用类似 BERT 的检查点来解决的任务。事实上,如果是这样的话,我会强烈建议不要构建自己的头部。

查看我的 GitHub 其他一些项目。可以联系我 这里 感谢您的配合!

如果你喜欢这个,这里还有一些!

**

参考

  1. 令人惊叹的拥抱脸示例部分!
  2. 数据集的引用和数据集的引用
@article{misra2019sarcasm,
  title={Sarcasm Detection using Hybrid Neural Network},
  author={Misra, Rishabh and Arora, Prahal},
  journal={arXiv preprint arXiv:1908.07414},
  year={2019}
}

使用 Hasura 向 shell 脚本管道添加事件通知和结果持久性

原文:https://towardsdatascience.com/adding-event-notifications-and-result-persistence-to-shell-scripted-pipelines-with-hasura-91b31e12e64a

原始图像从 iStockphoto 获得许可,Hasura 徽标经许可使用

在生物信息学中,作为一堆外壳脚本开发的计算管道无处不在。尽管像 Apache Airflow 这样的现代应用和像 Prefect 这样的云服务提供了更优雅、功能更丰富的解决方案,但现实是,在一个全新的*台上重新实现整个 shell 脚本管道对许多人来说往往是一个太大的步骤。当管道是从很久以前的博士后传下来的,或者当开发人员更多地来自科学背景(例如计算生物学)而不是软件工程背景时,情况就更是如此。

Nextflow 这样的工具通过提供一个 DSL 来运行 shell 脚本,从而允许一个更加渐进的方法,这样命令就可以逐渐从 shell 脚本中移出并迁移到 DSL 上。问题是这些工具正在老化,并且缺少许多对今天的工作流来说必不可少的功能。以事件通知为例,Nextflow 只为电子邮件和电子邮件提供配置。计算管道本质上是事件驱动的,因此在处理完成时,我可能想要一封电子邮件,但我也想通知一个松弛的通道,我想启动一两个 webhook,我想广播到多个上游应用程序,如 LIMS 和文件服务器。

shell 脚本管道的另一个痛处是保存结果。写出数据文件很容易,但是捕获和持久化管道运行的关键结果和度量又如何呢?这些数据当然也可以被写入某种机器可读的中间文件,但是这个文件需要在下游的某个地方被解析,这是低效的,并且会产生打字和后续逻辑的问题(例如舍入精度差异)。

或者,可以调用最终的 shell 脚本来运行一组直接的 SQL UPDATE/INSERT语句,这些语句用结果数据填充数据库。假设您可以获得一个配置了适当身份验证和受限角色的数据库用户帐户(防止小鲍比表),那么这是一个可行的解决方案,前提是您只需要记录一些值。一旦你有了更多不同格式的不同类型的值(例如csv vs json,那么试图在一个 shell 脚本中将数据转换成 SQL 语句不仅是糟糕的做法,而且很快变成了转义符的噩梦。例如,双引号()在 JSON 和 Bash 中用于分隔字符串,但在 Postgresql 中用于分隔标识符(例如列名),因此值必须始终用单引号()替换,同时在 shell 中进行双转义。

最后一种选择是开发某种定制 API,通常通过 HTTP,并从 cURL 或 wget 发送一个请求,将数据打包到一个不可读的 URL 编码的查询字符串或一个又大又长又丑的 JSON 参数中。这是可行的,就像在 90 年代一样,但是有更快、更容易和更健壮的选择,不会招致同样的技术债务和维护开销。

带有 Hasura 的即时自动 GraphQL

如果您是 GraphQL 的新手,在被仅仅为了改进管道而不得不学*一种全新的查询语言的前景吓退之前,您必须知道关于 Hasura 的两件最重要的事情:

  1. 你不需要了解任何 GraphQL 来开始使用 Hasura——它为你编写了 GraphQL,所以你可以一步一步地学*。
  2. 你不需要用 Hasura 替换任何东西 — 它和你正在运行的任何东西一起安静地工作,你可以慢慢地开始在有意义的地方和时间使用功能。

图片由作者提供,Hasura & GraphQL 徽标经许可使用

Hasura 封装了一个现有的数据库(PostgreSQL,MySQL,MSSQL ),但是除非你要求,否则不会接触你的数据。对于这个例子,让我们使用一个非常简单的演示数据库(让 SQL 创建它)。

作者图片

现在有了您的 DB 凭证,我们可以用下面的命令在 Docker 上下载并运行 Hasura。

docker run -d -p 8080:8080 \
  -e HASURA_GRAPHQL_DATABASE_URL=
postgres://hasurauser:hasurapwd@host.docker.internal:5432/pipelinedemo \
  -e HASURA_GRAPHQL_ENABLE_CONSOLE=true \
  -e HASURA_GRAPHQL_ADMIN_SECRET=MyHasuraSecret \
  hasura/graphql-engine:v2.1.1# replace HASURA_GRAPHQL_DATABASE_URL and MyHasuraSecret as required

接下来转到 http://localhost:8080/ ,在密码提示中输入上面HASURA_GRAPHQL_ADMIN_SECRET的值,然后点击顶部的“数据”导航菜单选项卡。首先要注意的是,Hasura 免费为您提供了一个整洁的 GUI 数据库浏览器。您可以插入行、配置新的表和列,甚至直接从控制台运行任意 SQL。连接好数据库后,我们现在希望跟踪我们的表和关系,这样 Hasura 就可以分析模式并创建 API。只需点击“public”模式,然后点击未跟踪的表或视图旁边的“Track All”即可看到下面的屏幕。

作者图片

我们还想告诉 Hasura 有关关系的信息,所以我们单击未跟踪的外键关系旁边的“Track All”。最后,通过从左侧选择运行样品表,点击插入行选项卡并输入以下值,将一些测试值添加到这些表中。

作者图片

现在 Hasura 知道了我们的 DB,我们可以通过点击顶部的“API”导航菜单标签来尝试一些 GraphQL。当我们的管道完成时,我们希望在数据库中添加或更新一条新记录 GraphQL 中的任何写操作都被称为突变。让我们创建一个变异,将一个示例记录添加到我们的sample_runs表中。

  1. 向右滚动到左边的浏览器框的底部,在那里显示添加新的选择“突变”并点击“+”按钮。
  2. 从左侧的浏览器框中展开 insert_sample_runs ,点击所有复选框(sample_idrun_idqc_scoreduplication_rate,为每个字段添加一个示例值。
  3. insert_sample_runs 下方展开返回,点击sample_idrun_id复选框
  4. 点击播放按钮,run_idsample_id值应返回如下。您可以通过返回到数据导航菜单选项卡并查看样本 _ 运行表来检查嵌件是否工作。

作者图片

不把这篇文章作为关于 GraphQL 的文章,另一个值得注意的关键特性是,与相关的表也可以在同一个请求中被查询和变异——上面的那些> run:> sample:节点可以被扩展以插入/返回相应表中的列。这大大优于众所周知的因提取不足/提取过多而导致效率低下的 REST。

graphqurl 是 GraphQL 的命令行 cURL

从 web GUI 中改变数据对于学*和测试来说非常好,但是对于我们的管道来说,我们需要从我们的 shell 脚本中调用更新,这就是 graphqurl 的用武之地——这是一个强大的 CLI,也是由 Hasura 开发的。

npm install -g graphqurl

现在我们可以调用相同的 GraphQL 变体,方法是将上面的代码复制并粘贴到一个纯文本文件中,我们称之为mutation.graphql,并至少更改sample_idrun_id值,因为它们用于主键。现在,当我们的 shell 脚本管道想要在mutation.graphql中报告数据时,它只需运行下面的命令。

gq http://localhost:8080/v1/graphql \
  -H 'X-Hasura-Admin-Secret: MyHasuraSecret' \
  -q "$(cat mutation.graphql)"

最后一步是将我们的静态值换成变量并绑定它们(*下文)。与发送 SQL 插入或 HTTP/REST 请求相比,GraphQL 真正的优点在于,GraphQL 是强类型的,因此类型检查和验证是该语言的一部分。这对于精确度至关重要的科学领域尤其有价值。例如, n 小数点的值应完全按照该值进行通信,而不是作为字符串发送,因为存在根据目的地类型解析为较低精度的风险。类型检查还使得 shell 脚本开发变得更加高效和轻松,因为客户端可以在发送请求之前对其进行验证。

# mutation.graphqlmutation ($sample_id: Int!, $run_id: Int!, $qc_score: Int!, $duplication_rate: Float!){
  insert_sample_runs(objects: {
    sample_id: $sample_id,
    run_id: $run_id,
    qc_score: $qc_score,
    duplication_rate: $duplication_rate}) {
      returning {
        run_id
        sample_id
      }
  }
}

我们现在可以使用-v参数运行 graphqurl 来处理单个管道结果,或者使用-variablesJSON来处理一组已经格式化的结果,如下例所示。

gq http://localhost:8080/v1/graphql \
  -H 'X-Hasura-Admin-Secret: MyHasuraSecret' \
  -q "$(cat mutation.graphql)" \
  --variablesJSON '{"sample_id": 1003, "run_id": 502, "qc_score": 88, "duplication_rate": 0.5678}'# or -v for individual key-value pairs (to avoid JSON formatting)

通过这一条命令,我们的管道现在可以直接从 shell 脚本中保存结果,并免费进行类型检查和验证——这多好啊!添加新的数据点非常简单,只需在mutation.graphql中添加一行来定义要保存到哪个表和列,然后将新值作为参数传递。调试轻而易举,因为您可以从 GraphQL 获得有用的错误,其他任何人都可以过来打开mutation.graphql来准确理解正在发生的事情,而无需关注一个转义字符——天堂!

灵活的无代码事件触发器

既然我们已经保存了数据,那么触发一些事件就好了,而不仅仅是一封来自 Sendmail 旧版本的电子邮件,你知道它随时都会关闭。同样,您可以创建自己的 webhook 微服务,测试、部署、监控和维护它,但当 Hasura 包含一个易于配置并可以从友好的 Web UI 监控的可靠解决方案时,为什么要这么麻烦呢?

对于本例,让我们向 Slack 发送一条消息,提醒我们管道结果。首先,你需要按照 Slack 的这些步骤来获得你唯一的秘密 webhook URL。现在转到顶部的“事件”导航菜单选项卡,点击左侧事件触发器旁边的“创建”,给它命名,然后将你的 Slack URL 粘贴到 Webhook 处理程序框中。然后,我们希望选择 sample_runs 表,并选中 Insert 旁边的框,以便在我们从管道添加新记录时触发它。

作者图片

规格中,我们还可以看到 Slack 解释消息所需的请求格式,因此我们需要相应地讨论我们的管道结果,这就是 Hasura(再次)为我们提供帮助的地方。只需创建一个新的有效负载转换,然后我们就可以配置请求体来匹配 Slack 规范。我们甚至得到了自动完成,请求的预览和我们输入时的错误检查——你还能要求什么呢!

作者图片

保存触发器后,向 sample_runs 添加新记录,然后返回 Hasura 控制台的 Events 选项卡。单击左侧的事件( slack_notification ),您应该会在 Processed Events 选项卡下看到最近的调用,以及在 Invocation Logs 选项卡下的完整请求和响应,这对调试很有用。

如果您有一个支持 webhook 的接收器/处理器,那么 web hook 就很棒,但是如果您有一个客户端,比如说一个独立的实验室仪器,它需要从一个事件中触发,但是不能运行一个专用的服务器来持续监听 web hook 调用,那该怎么办呢?Hasura 为您提供了订阅— 另一个宝贵的 GraphQL 特性,它允许客户端通过 websocket 监听实时变化,而无需轮询。客户端可能是一个简单的 web 应用程序,或者在这种情况下是 graphqurl,它可以订阅一个查询,然后在数据库值发生变化时触发仪器上的一个功能——查看 graphqurl 文档以获取示例。

希望这篇文章已经证明了,使用像 Hasura 这样的现代工具可以让你在为 shell 脚本管道添加新特性方面立竿*影。请记住,我们只是触及了 Hasura 的皮毛——使用 JWTs 进行认证、使用 DB 查询进行授权、模式拼接、数据库触发器、可定制的外部操作——对于您现有的数据库来说,它真的是一把无代码的瑞士军刀,值得一试。

Whitebrick 我们是 Hasura 的忠实粉丝,我们总是有兴趣了解您如何使用它,我们还提供咨询服务,所以不要犹豫联系

熊猫和 SciPy 的回归图

原文:https://towardsdatascience.com/adding-regression-lines-to-pandas-plots-with-scipy-2e23fd524adb

回归可用于预测未来或识别数据中的趋势和关系

作者图片

回归模型可用于两个不同的目的,发现数据趋势和进行预测。

Plain old Pandas plots 没有内置回归功能,但可以使用 SciPy 轻松生成,用他们自己的话说,SciPy 库提供了“Python 中科学计算的基本算法”。我们将使用的 SciPy API 部分是包含回归功能的 scipy.stats

在本文中,我们将首先了解如何构建一个简单的回归模型来揭示数据的趋势,然后我们将继续了解如何将回归模型用作预测器。

寻找趋势

我在伦敦及其周边生活了很多年,感觉那里的夏天越来越暖和了。它们是真的还是我想象出来的?如果是 15 或 25 岁,所有那些在夏日阳光的第一个迹象出现在摄政公园的赤裸上身的比基尼男女都会在那里,所以这种间接证据没有多大帮助。我们需要数字,幸运的是我们有一些。

在本文的第一部分,我们将看看伦敦过去几十年的夏季*均气温,看看我们能否得出任何关于首都变暖的结论。

我们将使用一些来自英国气象局公开数据的数字。你可以在这里下载—另存为londonweather.csv

这里的所有代码都是作为 Jupyter 笔记本用 Python 开发的,下面的每个代码块代表笔记本中的单个单元。

让我们导入库。

import pandas as pd
from scipy import stats

只有两个库:Pandas,因为我们将使用数据帧,并用 Pandas 绘图函数绘制结果;我们从 SciPy 导入了 stats 模块。

首先,我们将数据加载到名为weather的数据帧中。您下载的数据不仅仅包含全年的温度数据,因此我们将对其进行过滤,去掉我们不会用到的数据。基本上,我们只想要七月的最高温度(那通常是最热的夏季)。每个月的最高温度在Tmax栏中给出。

因此,我们通过只选择七月('Month == 7')来从weather创建数据帧july,然后我们只复制列YearTmax.

我们现在有一个包含伦敦 1957 年至 2018 年 7 月最高温度的数据框架。

在这里,我们使用 Pandas 的scatter函数绘制了一个散点图。

weather = pd.read_csv('londonweather.csv')

july = weather.query('Month == 7')[['Year','Tmax']]
july.plot.scatter(y='Tmax',x='Year', figsize = (16,8))

作者图片

这些点几乎无处不在,很难看出一个清晰的趋势。尽管在以后的几年里气温可能会更高——看起来图表的左上角和右下角有相对较空的区域,这表明在最初的几年里高温较少,而在以后的几年里低温较少。

为了验证这一点,我们将使用 SciPy 的stats.linregress函数构建一个简单的线性回归模型。该函数有两个参数,都是列表。列表是构建模型的 xy 值,在我们的例子中 x 是年份, y 是七月的最高温度。

从包含模型参数的函数返回一个对象。这里我们使用截距和斜率的值来计算代表回归线的值列表,并将它们添加到名为trend的新 dataframe 列中。

完成这些后,我们现在绘制原始散点图和趋势线图。

x = july['Year']
y = july['Tmax']m = stats.linregress(x, y)t = [m.slope * i + m.intercept for i in x]july.insert(len(july.columns),'trend',t)ax = july.plot.scatter(x='Year',
                       y='Tmax')
july.plot.line(x='Year',
               y='trend', 
               color='red', 
               ax=ax, 
               figsize = (16,8))

作者图片

现在可以清楚地看到有上升的趋势。如果我们看一下数据图,我们可以看到,我们的趋势线显示,从 1957 年到 2018 年,气温上升了近 3 摄氏度。

作者图片

通过肉眼观察数据,我们可能会发现温度的上升,但是添加一条回归线会使观察变得容易得多。

因此,我们可以看到回归线如何有助于发现模式。接下来我们将看看它的预测能力。

预测值

我们将使用的下一个数据集是经济合作与发展组织 ( OECD)公开提供的 G7 国家集团的国内生产总值(GDP)。

GDP 本质上是对一个国家财富的衡量,但我们的数据并没有显示绝对值,而是代表了 GDP 随时间的变化。因此,它们是衡量经济增长的指标。从 2007 年到 2021 年,记录了一年中每个季度的数据,每个值都与 2015 年的 GDP 相关。2015 年的国内生产总值被认为是 100,所以如果加拿大的国内生产总值在 2007 年第一季度是 88.1,这意味着实际的国内生产总值是 2015 年加拿大国内生产总值的 88.1%。

由于国内生产总值通常会随着时间的推移而逐渐增加,数据往往显示 2015 年之前的数值略低于 100,而在以后几年略高。然而,经济冲击,如 2008 年的金融危机和当前的乔维德疫情可能会导致所有国家的国内生产总值迅速下降。

你可以在这里下载我的数据副本。将其保存为QNA_26022022111050612.csv (这是它的正式名称——如果你愿意,可以称之为更简单的名称,但要记得相应地修改下面的代码)。

下面的代码将数据加载到 dataframe 中并对其进行过滤:首先,我们只需要数据 VIXOBSA(如上所述),并且我们只对 G7 国家感兴趣。代码

(gdpdata['MEASURE']=='VIXOBSA') & (gdpdata['Country']=='G7')

为我们做过滤。

然后我们进一步减少数据,只复制列Period(例如,Q1 2007)和Value(GDP 数字)。

gdpdata = pd.read_csv('QNA_26022022111050612.csv')

G7data = gdpdata[(gdpdata['MEASURE']=='VIXOBSA') 
               & (gdpdata['Country']=='G7')]

G7data = G7data[['Period','Value']]

产生的数据框架来自 Q1–2007 年第四季度–2021 年,如下所示:

作者图片

Period 列不是一个非常有用的格式,所以我将在数据帧中添加一个新列yr,如下所示:

def formyr(x,data):
   d = data['Period'].values[x]
   y= int(d[-4:])+int(d[1:2])*0.25 - 2007
   return y yr=[formyr(x,G7data) for x in range(len(G7data)) ]
G7data['yr'] = yr

现在看起来是这样的:

作者图片

新列表示特定条目的年份,并从零开始编号。季度由季度表示,所以 Q1 2007 年是 0.25,而 2009 年第三季度是 2.75。这个数字列使得创建模型更加容易。

现在,我们以与之前相同的方式制作模型,绘制原始数据的散点图,并在其上覆盖回归图。

x = G7data['yr']
y = G7data['Value']m = stats.linregress(x, y)t = [m.slope * i + m.intercept for i in x]
G7data.insert(len(G7data.columns),'r',t)ax = G7data.plot.scatter(x='Period',
                         y='Value')
G7data.plot.line(x='Period',
                 y='r', 
                 color='red', 
                 ax=ax, 
                 figsize = (16,8), 
                 rot=90)

作者图片

我们可以看到,在整个时期内创建一个模型会产生一条趋势线,但这并不是一个特别好的预测指标。这是因为 2008 年和 2020 年的重大事件导致了如此大的增长波动。

然而,我们可以看到,在两次重大中断之间,增长相当一致。所以我们可以在这中间的几年里尝试一个模型。让我们创建一个模型,从第 2 年到第 8 年(即 2009 年到 2014 年)的数据开始,看看这是否更有意义。

下面的代码就是这么做的。该模型是在中间年份创建的,然后应用于整个范围。

G7data2009 = G7data[(G7data['yr']>2) & (G7data['yr']<=8)]x = G7data2009['yr']
y = G7data2009['Value']m = stats.linregress(x, y)t = [m.slope * i + m.intercept for i in G7data['yr']]G7data.insert(len(G7data.columns),'r2',t)ax = G7data.plot.scatter(x='Period',
                         y='Value')
ax = G7data.plot.line(x='Period',
                      y='r2', 
                      color='red', 
                      ax=ax, 
                      figsize = (16,8), 
                      rot=90)

看下面的图,我们可以看到模型在预测 2009 年到 2019 年底之间相对稳定的时间方面做得相当好。

作者图片

那么,这告诉我们什么呢?

我认为有两件事:

  1. 在“正常”情况下,一个简单的回归模型可以用来进行预测
  2. 现实生活中发生的随机事件是无法预测的

模型总是对现实的简化,有时它们在预测未来趋势时很有用,但有时随机事件会介入并使它们出错。

我希望你已经通过回归图的使用以及如何用 SciPy 将它们轻松地添加到熊猫图中享受了这次漫游。你可以欣赏它们被用来识别模式或进行预测的方式。但是你也要意识到,随机事件会打乱任何预测模型,不管它有多复杂(或者在这种情况下很简单)。

一如既往地感谢您的阅读,如果您想知道我何时发表新文章,请考虑注册下面的电子邮件提醒,或者订阅我在 Substack 上偶尔发布的免费简讯。

如果你还不是一个媒体订阅者,那就注册吧,这样你就可以每月花 5 美元阅读尽可能多的文章。在这里注册,我将赚取一小笔佣金。

密码

你可以下载一个 Jupyter 笔记本,里面有我的 Github 资源库中的所有代码,这里是。

脚注

  1. 英国气象局的数据来源于 https://www . metofice . gov . uk/research/climate/maps-and-data/historic-station-data 的记录,并由我根据开放政府许可的条款进行了修改
  2. 经合组织(2022 年),季度国民账户:七国集团国民生产总值 EI 副本,网址:https://stats.oecd.org/Index.aspx?QueryId=77241(2022 年 2 月 26 日访问)

解决过度拟合 2023 指南— 13 种方法

原文:https://towardsdatascience.com/addressing-overfitting-2023-guide-13-methods-8fd4e04fc8

您的一站式学*场所,了解防止机器学*和深度学*模型过度拟合的 13 种有效方法

埃里克·范·迪克在 Unsplash 上的照片

谁不喜欢为大多数数据科学家面临的最糟糕的问题寻找解决方案呢?【过拟合问题】

本文可能是学*机器学*和深度学*模型中防止过拟合的许多有效方法的一站式地方。

过度拟合会发生什么?

过度拟合通常发生在模型过于复杂的时候。当模型过度拟合训练数据时,会发生以下情况:

  • 模型试图记忆训练数据,而不是从数据中学*基本模式。机器学*涉及从数据中学*模式和规则,而不是记忆数据。
  • 该模型仅在训练数据上表现良好,而在新的未知数据上表现不佳。一个好的模型应该能够在训练数据上表现良好,并且能够在新的未知数据上进行很好的概括。

如何检测过度拟合

下一个问题是:

我们如何识别机器学*和深度学*模型中的过拟合?

使用学*曲线

过度拟合是我们肉眼看不到的东西!一个简单而有效的机器学*可视化称为学*曲线可以用来检测机器学*和深度学*模式中的过度拟合。

学*曲线绘制了训练和验证分数与时期数的关系。

学*曲线表明模型过度拟合:

  • 如果训练分数和验证分数之间有明显的差距。
  • 当验证误差(损失)在某个点开始增加,而训练误差(损失)仍然减少时。在准确度的情况下,验证准确度在某个点开始降低,而训练准确度仍然增加。

用学*曲线检测过度拟合(图片由作者提供)

使用验证曲线

学*曲线在深度学*模型中非常常*。以检测诸如决策树、随机森林、k-最近邻等一般机器学*模型中的过拟合。,我们可以使用另一个机器学*可视化称为验证曲线

验证曲线描绘了单个超参数对训练和验证集的影响。

x 轴代表给定的超参数值,而 y 轴代表训练和验证分数。

对于单个超参数的给定值,我们可以使用验证曲线来检测机器学*模型中的过度拟合。

为此,我们需要确定最重要的模型超参数,并使用验证曲线绘制其值的影响。

这方面的一些例子包括:

  • 我们可以使用验证曲线来绘制决策树或随机森林模型的 max_depth (树深度)超参数的影响。
  • 我们可以使用验证曲线来绘制 KNN 模型的 n_neighbors (邻居数量)超参数的影响。

下图显示了为随机森林分类器创建的验证曲线,用于测量 max_depth (树深度)超参数对训练和验证分数(精确度)的影响。

验证曲线(图片由作者提供)

max_depth 值为 6 之后,模型开始过度拟合训练数据。换句话说,验证精度在 max_depth=6 处开始下降,而训练精度仍在增加。

使用多个评估指标

根据我们使用的机器学*算法的类型,Scikit-learn 和 TensorFlow 提供了不同类型的模型评估指标。我们可以使用(甚至组合)这些评估指标来监控模型在训练期间的性能,然后通过分析评估指标的值来确定模型是否过度拟合。

下图显示了完全成熟的决策树分类器的训练和测试精度,以及测试数据的混淆矩阵。

评估决策树分类器(图片由作者提供)

在完全成熟的决策树中,过度拟合是有保证的!100%的训练准确率意味着决策树分类器模型在训练集上表现良好。71%的测试准确度清楚地表明,该模型在新的看不*的数据上表现不好。测试精度远低于训练精度。换句话说,训练和测试的准确性之间有明显的差距。这些事情表明模型明显过度拟合。

在这种情况下,假阳性和假阴性的数量也很高。这是该模型在测试数据上表现不佳的另一个迹象。

在应用适当的正则化技术(限制树的增长和创建系综)之后,我们得到以下评估值。

(图片由作者提供)

训练和测试准确度分数都很高,它们之间没有明显的差距。除此之外,假阳性和假阴性的数量也减少了。现在很明显,正则化决策树模型现在并没有过拟合。

解决过度拟合的 13 种有效方法

这里总结了机器学*和深度学*模型中用于防止过拟合的方法。我们将详细讨论每种方法。

**Addressing Overfitting - 13 Methods**
-----------------------------------
01\. [Dimensionality Reduction](#76e6)
02\. [Feature Selection](#2943)
03\. [Early Stopping](#c513)
04\. [K-Fold Cross-Validation](#ae2a)
05\. [Creating Ensembles](#832f)
06\. [Pre‐Pruning](#5b1b)
07\. [Post‐Pruning](#235d)
08\. [Noise Regularization](#bbc5)
09\. [Dropout Regularization](#8cde)
10\. [L1 and L2 Regularization](#27c3)
11\. [Data (Image) Augmentation](#4d98)
12\. [Adding More Training Data](#e080)
13\. [Reducing Network Width & Depth](#3dc4)

注意: 如果你想获得下面讨论的每种方法的实践经验,我已经为此创建了一个单独的文章集!访问此链接获取所有文章。在那里,您将通过编写代码来学*如何应用每种方法!

我们开始吧!

1️⃣通过降维解决过拟合问题

当模型太复杂时,过度拟合经常发生。模型复杂的主要原因是数据中存在许多特征(变量)。数据中特征的数量称为其维数。

当训练数据的维数较高时,模型往往会过度拟合训练数据。

减少数据中的特征数量称为降维。我们应该尽可能多地保留原始数据中的差异。否则,我们会丢失数据中的有用信息。

降维处理过拟合,如下所示。

  1. 降维减少了数据中的特征数量。应用降维后,模型的复杂度也将降低。因此,模型不会再过度拟合训练数据!
  2. 降维还可以去除数据中不必要的噪声。噪声数据会导致过度拟合。该模型将防止在去除数据中的噪声之后过度拟合训练数据。

最常*的降维方法是主成分分析。它为低维形式的数据找到一组新的不相关特征。

PCA 可以有效地消除过拟合问题。

2️⃣通过特征选择解决过拟合问题

特征选择可以被认为是一种降维方法,因为它从数据集中移除了冗余(不必要)的特征。这减少了数据中的特征(维度)数量。

特征部分方法不是寻找一组新的特征,而是通过移除数据中不需要的特征来仅保留最重要的特征。原始值保持不变。这就是特征选择与 PCA 的不同之处,在 PCA 中我们得到新的变换值。

一个简单的机器学*可视化叫做特征重要性图可以用来选择最重要的特征。该图是基于每个特征的相对重要性而创建的。下图显示了使用包含 30 个特征的乳腺癌数据集创建的图。

用于乳腺癌数据集的特征重要性图(图片由作者提供)

您可以看到一些特征对模型没有太大的贡献。他们的贡献微不足道。因此,我们可以删除这些特征,只使用最重要的特征来构建模型。

从数据中移除最不重要的特征将降低模型的复杂性,并消除数据中的噪声(如果有的话)。这就是特征选择如何防止模型过度拟合。

3️⃣通过提前停止解决过度拟合问题

早期停止是防止机器学*和深度学*模型中过拟合的另一种有效方法。

在早期停止中,我们通过查看学*曲线或验证曲线,在模型开始过度拟合之前,有意地提前停止模型训练过程。

使用学*曲线执行提前停止(图片由作者提供)

在第 5 个时期之后,模型开始过度拟合训练数据。如果我们在那个时期之后继续训练,尽管训练误差进一步减小,但是验证误差增加。训练分数和验证分数之间的差距也会增大。这些都是过度拟合的迹象。

4️⃣通过 k 倍交叉验证解决过度拟合问题

k 倍交叉验证是一种数据分裂策略。在构建 ML 和 DL 模型时,我们通常将整个数据集分成训练集和测试集。这里的问题是,模型在训练过程中只看到一组特定的实例(数据点)。

在 k-fold 交叉验证中,根据 k 的值(通常为 5 或 10),将整个数据集拆分成不同的折叠。每个文件夹包含不同类型的实例(数据点)。该模型在每次迭代中对 k-1 倍的数据进行训练。在每次迭代中使用剩余的数据折叠进行评估。如下图所示,训练和评估折叠在每次迭代时都会发生变化。在每次迭代中计算评估分数,并取*均值。

K 倍交叉验证程序:k=5 (图片由作者提供)

在 k-fold 交叉验证中,模型在训练期间看到不同的实例集(数据点),因为在每次迭代中训练和评估折叠都发生了变化。该模型将学*所有需要的模式,并将对新的看不*的数据进行很好的归纳。换句话说,k 重交叉验证可以防止模型过度拟合。

5️⃣通过创建合奏解决过度配合问题

这种方法仅限于基于树的模型。决策树模型总是过度拟合训练数据,除非我们通过为 max_depth (树深度)超参数设置一个较低值来限制树的增长。

即使我们在训练期间限制了树的增长,决策树模型仍然可能过度拟合训练数据。减少决策树过度拟合的一个有用方法是创建集成。集成(组)是从训练数据和特征的子集创建的多个决策树的集合。

例如,随机森林是包含一组不相关的决策树的集合。

与决策树模型相比,随机森林由于其额外的随机性,不太可能过度拟合训练数据。

由于不相关树,额外的随机性出现在随机森林中。当创建随机森林时,数据混合得很好。除此之外,通过*均每个不相关树的结果来计算最终结果。因此,随机森林比单一决策树能产生更准确和稳定的结果。

6️⃣通过预修剪解决过度拟合问题

修剪方法用于防止决策树中的过度拟合。有两种主要的修剪方法,称为预修剪和后修剪。

默认情况下,决策树会增长到其最大深度。完全长大的树总是超过训练数据。

在决策树中,修剪是控制树的生长的过程。

预修剪应用提前停止规则,该规则过早地停止决策树的生长。预剪枝后,决策树的分支更少。我们可以通过限制以下超参数的值来在决策树中应用预修剪。

  • max_depth: 树的最大深度。减小该值可以防止过度拟合。
  • min_samples_leaf: 一个叶节点所需的最小样本数。增加该值可以防止过度拟合。
  • min_samples_split: 分割内部节点所需的最小样本数。增加该值可以防止过度拟合。

有两种常用的方法来调整这些超参数。

  • 一次测量一个超参数的影响,同时保持其他超参数的默认值。为此,我们可以使用验证曲线来检测过度拟合。
  • 一次调整多个超参数。此处不能使用验证曲线来测量多个超参数的影响。这里,应使用网格搜索或随机搜索一次调整多个超参数。

7️⃣通过后期修剪解决过度拟合问题

后期修剪是指在树完全长成后,除去树的某些部分的过程。

成本复杂性剪枝(ccp)是一种后剪枝方法。它包括为 Scikit-learn 决策树类中的CCP _ 阿尔法 超参数找到正确的值。

ccp 阿尔法的默认值是零,这意味着默认情况下不执行修剪。较大的值会增加要修剪的节点数,并降低树的深度。因此,CCP _ 阿尔法的较大值可以防止过度拟合。

要找到CCP _ 阿尔法 超参数的最佳值:

  • 我们可以尝试 0.01、0.02、0.05、0.1 等不同的值。,并监控培训和验证分数。
  • 我们可以将所有有效的阿尔法值一次一个地传递给 ccp 阿尔法超参数,然后计算训练和验证分数。阿尔法的所有有效值都可以通过CCP _ 阿尔法属性访问。

调整 ccp 阿尔法超参数(图片由作者提供)

alpha=0.06 时,验证精度开始增加,而训练精度几乎保持不变。alpha 的下一个可用值是 0.12,它的性能分数非常低。根据该图,α的最佳值是 0.06。

用噪声正则化解决过拟合的 8️⃣

向现有数据添加噪声是防止神经网络中过拟合的有效正则化方法。我们通常将噪声添加到神经网络的输入层,因为输入层保存训练数据,尽管也可以将噪声添加到隐藏层和输出层。

当向训练数据添加噪声时,将向每个训练实例添加少量噪声,并生成同一实例的不同版本。这将扩展原始数据集!这将隐式地向原始数据集中添加更多的训练数据。添加更多的训练数据将有助于防止过度拟合。

除此之外,在将噪声添加到数据之后,模型将 而不是 单独捕获训练数据中的噪声。这也将有助于减少过度拟合。

9️⃣通过调整辍学来解决过度适应问题

放弃正则化是一种特定于神经网络的正则化方法,用于防止神经网络中的过拟合。

在丢弃正则化中,该算法根据我们在每层中定义的概率值,在训练期间从网络中随机删除一些节点。被移除的节点不参与参数更新过程。基于每一层应用丢失正则化。这意味着我们可以在每一层分别设置不同的退出概率。

辍学正规化流程(图片由作者提供)

在应用退出正则化之后,原始网络变得更小。较小的网络灵活性较差,因此不会出现过度拟合。

在丢失正则化中,一些权重值为零,因为它们的节点是不活动的。因此,所有其他权重都需要参与权重更新过程。网络的输出不依赖于某些大的权重。这可以减少神经网络中的过拟合。

丢失正则化是防止神经网络过拟合的最有效方法。

用 L1 和 L2 正则化解决过拟合的 1️⃣0️⃣

L1 和 L2 正则化通常应用于神经网络模型,以防止过拟合。L1 和 L2 正则化的选择取决于我们在训练期间添加到损失函数中的正则化项。

当正则项为 L1 范数 [ *λ (权重绝对值之和) ]时,称为 L1 正则化。当正则项为 L2 范数 [ *λ (权值的*方值之和) ]时,称为 L2 正则化

神经网络的 L1 和 L2 正则化定义如下。

L1 和 L2 正规化(图片由作者提供)

λ控制正则化的级别。因此称为正则化参数(因子)。

  • lambda=0:最小值。没有应用正则化。
  • lambda=1:最大值。应用完全正则化。

λ值越大,意味着正则化越强,从而减少了神经网络中的过拟合。

通常,L1 和 L2 正则化保持神经网络的权重较小。不会有任何大的权重过分强调某些输入。小权重值对输入数据中存在的噪声不太敏感。因此,在 L1 和 L2 正则化神经网络中不会发生过拟合。

L1 和 L2 正则化方法也可以应用于一般的机器学*算法,如逻辑回归、线性回归等。

在 logistic 回归中,有一个超参数叫做(取值:‘L1’‘L2’‘elastic net’*)来选择正则化的类型。注意' elasticnet' 同时将 L1 和 L2 正则化应用于模型。***

对于线性回归,Scikit-learn 为每种正则化类型提供了三个单独的类,称为Ridge()(应用 L2 正则化)、Lasso()(应用 L1 正则化)和ElasticNet()(应用 L1 和 L2 正则化)。

1️⃣1️⃣用数据(图像)寻址过拟合 a 增强

数据扩充通常在图像数据上执行。因此,数据增强在某些上下文中也被称为图像增强**

图像增强是通过对同一幅图像进行某种变换,产生新的变体,从而增加图像数量的过程,这种变换包括缩放翻转旋转移动缩放光照压缩裁剪等。**

图像增强最重要的是保留图像的上下文。换句话说,当扩充图像时,图像上下文不应该被改变。

图像增强更适合经常需要更多训练数据的深度学*模型。这是一种为模型提供更多训练数据的廉价方法!

图像增强如下减少了神经网络中的过拟合。

  1. 图像增强通过添加更多的训练实例来扩展数据集。添加更多的训练数据将防止过度拟合。
  2. 图像增强允许神经网络在训练期间看到相同图像的许多变体。这减少了在学*重要特征时对图像原始形式的依赖。当在新的看不*的数据上测试时,网络将变得更加健壮和稳定。

1️⃣2️⃣通过添加更多训练数据解决过度拟合问题

向模型中添加更多的训练数据将防止过度拟合。有许多方法可以将更多的训练数据添加到模型中。

  • 收集新的相关数据(昂贵)
  • 通过向数据添加噪声来扩展原始数据集(成本低廉)
  • 数据扩充(廉价)

1️⃣3️⃣通过减小网络宽度和深度解决过拟合问题

神经网络的结构由其宽度和深度定义。深度定义了神经网络中隐藏层的数量。宽度定义了神经网络每层的节点(神经元/单元)数量。**

减少隐藏层的数量和隐藏单元的数量会降低网络的灵活性。灵活性较低的网络无法捕获数据中的噪声,也不会过度拟合训练数据。

今天的帖子到此结束。

如果您有任何问题或反馈,请告诉我。

阅读下一篇(强烈推荐)

  • 获得“解决过度装配 2023 指南”的实践操作

***

(作者截图)***

支持我当作家

我希望你喜欢阅读这篇文章。如果你愿意支持我成为一名作家,请考虑注册成为会员,不受限制地使用媒体。它只需要每月 5 美元,我会收到你的会员费的一部分。

***https://rukshanpramoditha.medium.com/membership

非常感谢你一直以来的支持!下一篇文章再*。祝大家学*愉快!

鲁克山·普拉莫蒂塔
2022–11–22***

注释和文档字符串之外的高级代码文档

原文:https://towardsdatascience.com/advanced-code-documentation-beyond-comments-and-docstrings-2cc5b2ace28a

使用 Sphinx 并阅读文档以获得用户友好的界面来理解代码库——即使对于非技术用户也是如此

更新 :本文是系列文章的一部分。退房 第二部分*第三部分 *

使用 Sphinx 的文档托管在 Read Docs 上—图片由作者提供

文档向用户展示如何使用或理解项目,根据项目类型有不同类型的文档。如果您正在从事 Python 项目——无论是编写 Python 包还是仅仅是个人项目,并且您希望您的读者理解代码正在做什么的高层次细节,而不是代码是如何完成的。

对于任何项目来说,可理解性都是很重要的,一个项目的好坏取决于它的文档。如果除了开发者之外的人不理解它是如何工作的,那么它是没有用的。文档使不同的开发人员能够更有效地协作,当一个项目从一个人移交给另一个人时,文档尤其重要。

适当的文档不仅节省了理解代码的大量时间,还减少了出错时的挫折感。

为 Python 项目编写文档的一种方法是为您的类和函数编写文档字符串。如果您对 docstring 完全陌生,或者您的代码中已经有了 docstring,并且正在寻找一种以用户友好的方式显示它的方法,请继续阅读!

本文将详细介绍您可以采用的 3 种流行的 docstring 格式,使用 Sphinx 以用户友好的方式显示文档,Sphinx 的一些基本定制,最后在 Read Docs 上托管它!

目录

Google、Numpy 和 reStructuredText 文档字符串格式

我将快速阐述三种更流行的 docstring 格式。没有可以使用的最佳格式,但是为了一致性,在整个代码库中坚持一种格式是很重要的。就我个人而言,我更喜欢 Google docstring 格式,因为它用更少的代码行产生更宽的文档字符串。Numpy docstring 格式倾向于导致更窄的 docstring 和更多的代码行。下面是不同格式的演示,示例函数接受参数ab

Google 文档字符串格式

*def sample_function_google(a, b):
    """Google style

    Args:
        a:
        b:

    Returns:

    """*

Numpy 文档字符串格式

*def sample_function_numpy(a, b):
    """Numpy style

    Parameters
    ----------
    a
    b

    Returns
    -------

    """
    pass*

重构文本格式

*def test_function_restructured_text(a, b):
    """reStructuredText style

    :param a:
    :param b:
    :return:
    """
    pass*

一旦为类和函数编写了 docstrings,就可以进入下一部分了!

Sphinx 设置

斯芬克斯标志—图片由如何不编码

Sphinx 是一个将代码中的文档字符串转换成美观、可读的 HTML 文件的工具。它需要一次性的努力来建立和只有一行命令来刷新文件(阅读到最后,以了解如何自动刷新文件!)

首先,将下面列出的包添加到您的requirements.txt中,并执行pip install。这将安装软件包及其依赖项。

要初始化 Sphinx,在同一个命令提示符下运行下面几行代码。请注意,安装时只需运行一次。该程序将提示您输入项目名称、作者姓名、项目版本和项目语言,您可以相应地填写。在这一步之后,额外的文件夹和文件将出现在您的项目中,我将在下一节中详细介绍。

*$ mkdir docs
$ cd docs
$ sphinx-quickstart*

最后,可以调用下面几行代码来分别呈现和删除文件。当你想刷新你的文件时,可以使用它们。现在你准备好了!

*$ make html
$ make clean*

解释了 Sphinx 文件夹结构

如前所述,有几个文件夹和文件被添加到项目中,但是不要担心,你只需要编辑source文件夹中的内容。

build文件夹包含渲染的 HTML 文件,您可以在运行make html命令后查看。source文件夹包含两个重要组件

  • conf.py处理文档的配置
  • 各种.rst文件,控制你想添加到文档中的内容

现在,你应该只有一个可用的index.rst文件,你的 HTML 文件应该看起来非常简单。下一节将讨论如何定制和美化你的文档。

最初的狮身人面像文档——作者图片

自定义主题、图像和样式

最恰当的改进是选择一个狮身人面像主题。你可以在斯芬克斯主题文档上查看主题的完整列表。出于演示目的,我将选择经典主题,并在conf.py文件中相应地修改主题和主题选项。

*html_theme = "classic"
html_theme_options = {
    "rightsidebar": "true",
    "relbarbgcolor": "black"
}*

刷新文档现在看起来像这样—稍微好一点。

斯芬克斯文档经典主题—作者图片

下一个改进是在你的文档中添加图像,用于标识和 HTML 标签。这可以在两行代码中完成,注意图像文件路径应该是相对于conf.py文件所在路径的。

*html_favicon = '../../assets/documentation-icon.svg'
html_logo = '../../assets/favicon.ico'*

最后,我想提到的改进是使用 CSS 样式定制文档。CSS 是一个非常强大的工具,可以控制 HTML 页面上任何元素的样式。这可以通过添加一个 CSS 文件到source/_static文件夹来完成。假设我创建了一个名为custom.css的 CSS 文件,我可以将它链接到conf.py文件,

*def setup(app):
    app.add_css_file('custom.css')*

用添加的图像和 CSS 样式刷新文档以控制我的图像的大小,现在看起来像这样—

狮身人面像文档,带有图片和样式——作者图片

添加文档内容

当然,如果文档只有漂亮的风格而没有内容,那它有什么用呢?使用.rst文件可以添加内容,但首先我们必须将 codebase 的根目录添加到文件路径中,并指出这个项目使用的是哪种类型的 docstring 格式。

要将代码库的根添加到文件路径中,请将以下代码行添加到您的conf.py中,如果您有不同的文件夹结构,您可以更改它。

*import os
import sys
sys.path.insert(0, os.path.abspath('.'))
sys.path.insert(0, os.path.abspath('../..'))*

默认情况下,Sphinx 接受 reStructuredText docstring 格式。如果您正在使用 Google 或 Numpy docstring 格式,请将以下代码添加到您的conf.py文件中。

*extensions = ['sphinx.ext.napoleon', 'numpydoc']*

这就结束了对conf.py文件所做的所有修改,最终的文件应该是这样的,

继续讨论.rst文件,我建议创建一个类似于你的代码库文件结构的rst文件结构,并使用index.rst链接到其他rst文件。下面是一些例子,你可以在这里查看我的 Github 库。

index.rst内,

*:doc:`sample_function`
    Documentation for sample-function*

sample_function.rst内(由上述index.rst调用)

*Sample Function
--------------------------

.. automodule:: sample_function.sample_function_google
    :members:
    :undoc-members:
    :show-inheritance:*

现在,我的示例函数的文档看起来像这样—

我的示例函数的 Sphinx 文档—作者图片

在阅读文档时托管文档

恭喜你,你已经成功地建立了一个可读的 HTML 格式的文档!然而,这些文件只存在于你的电脑上,任何人都不能共享。要在 Read Docs 上托管它,您的存储库必须首先位于一个公共的 GitHub 存储库中。申请一个Read Docs账号,分别链接到你的 GitHub 和选择你的库。这将在线构建和托管您的文档。现在,一旦您将任何更改推送到您的 GitHub 库,文档将自动刷新!

或者,可以选择手动上传文件,但这不会利用自动刷新。

希望您已经学*了设置、定制和托管 Sphinx 文档的基础知识。通过样式化、定制函数和类的格式、添加徽章、使用扩展来查看 Jupyter notebook 和 Markdown 文本,甚至在 Confluence 等其他*台上托管它,有更多的方法来增强文档。有需求的话可以出续集;)

*

这些是 GitHub 库阅读演示中使用的文档文档的链接。

感谢您的阅读!如果你喜欢这篇文章,请随意分享。*

相关链接

阅读我个人项目的文档:https://kayjan.readthedocs.io/

狮身人面像文献:https://www.sphinx-doc.org/en/master/

包含覆盖率和单元测试的高级代码文档—第 3 部分

原文:https://towardsdatascience.com/advanced-code-documentation-with-coverage-and-unit-tests-part-3-3f7b698497fb

评估文档的完整性并对文档字符串执行单元测试——使用和不使用 Sphinx

更新 :本文是系列文章的一部分。查看 第一部分第二部分

尼克·莫里森在 Unsplash 上拍摄的照片

第一篇文章展示了如何设置、定制和部署 Sphinx 文档,第二篇文章提到了使用 Sphinx 扩展来处理更复杂的项目结构、合并多种文件类型和添加徽章。只要您的代码库中有某种形式的文档字符串,这一切都可以工作,但是您如何真正知道您的文档字符串是否足够好呢?本文将介绍对文档字符串执行单元测试的方法,并检查文档字符串的覆盖率——使用和不使用 Sphinx 都可以。

目录

使用 Sphinx 对文档字符串进行覆盖率测试

覆盖率是指包含文档的范围(类、函数、模块)的比例。良好的覆盖率意味着代码库得到了很好的解释。

可以使用我在第二篇文章中提到的 Sphinx 扩展来检查文档字符串的覆盖率。简单回顾一下,扩展允许您添加特性或修改 Sphinx 布局。用于检查覆盖率的 Sphinx 扩展不需要安装额外的 Python 包,只需将sphinx.ext.coverage添加到conf.py文件的扩展列表中,并在命令提示符下运行下面一行,

$ sphinx-build -v -b coverage docs/source docs/build/coverage

为了分解上面的命令,-v增加了详细度,将额外的日志打印到控制台,-b coverageconf.py所在的源目录docs/source中运行覆盖构建器,覆盖结果将保存到输出目录docs/build/coverage

我特意留下了一个没有 docstrings 的函数,覆盖结果可以在/docs/build/coverage/python.txt中找到,如下所示,

Undocumented Python objects
===========================
sample_function
---------------
Functions:
 * sample_function_no_docstring

注意:如果覆盖率测试没有成功标记没有文档字符串的函数,检查您的.rst文件中是否有:undoc-members:并删除这一行。

注意:如果您收到No module named ..; .. is not a package警告等警告,请检查您的.rst文件。确保您指向的是 Python 文件,而不是 Python 文件中的函数。

不使用 Sphinx 的文档字符串覆盖测试

如果您的 Python 包不支持 Sphinx,您仍然可以使用docstr-coverage Python 包检查您的代码库的覆盖率,安装该包并在命令提示符下运行下面一行,

docstr-coverage . --skip-file-doc --exclude ".*/docs"

为了分解上面的命令,.表示当前目录,这是代码库的位置,--skip-file-doc忽略检查每个文件顶部的文档字符串,--exclude ".*/docs"添加排除路径以避免运行覆盖测试。

和以前一样,我特意留下了一个没有文档字符串的函数,覆盖率结果如下所示

覆盖率测试结果-作者图片

也就是说,文档字符串覆盖只是覆盖测试的一个方面,还有其他的代码覆盖测试,它们关注函数覆盖(检查冗余函数)、语句覆盖(检查冗余语句)、条件覆盖(检查冗余 if-else 语句),等等。

文档字符串的单元测试

代码覆盖率度量可能与项目的整体代码质量相关,但不能正确测试代码库,而代码库是通过单元测试来实现的。

单元测试是测试一个单元或代码库中可以逻辑隔离的最小代码段,这在测试驱动开发(TDD)中至关重要。它允许在开发周期的早期发现实现中的错误。

正如我们正在讨论的文档主题,简单的测试可以用函数 docstring 编写,并使用内置 Python 库的doctest Python 包进行测试。

用函数 docstring 编写的测试信息丰富,因为它向用户展示了如何使用样本输入和预期输出与函数进行交互。然后用doctest完成,它能够测试预期的返回值和预期的错误。

为了举例说明,我编写了一个简单的函数,将两个数相加。为了简单起*,我删除了 docstring 中定义函数描述、参数和返回值的部分。您也可以通过复制代码并使用python sample_doctest.py -v在命令提示符下运行 Python 文件来尝试,其中-v增加了冗长性。

单元测试结果-作者图片

警告:使用doctest作为单元测试的手段不如流行的 Python 框架如unittestpytest强大。

访问编写函数的文档字符串

由于我们总是可以调用打印出文档字符串信息的help(*function_name*),所以很少使用访问编写函数的文档字符串。但是,如果我们需要将编写的函数的文档字符串检索到一个字符串变量中,有两种方法可以做到这一点,即使用inspect内置 Python 库或访问函数的__doc__属性。

import inspect
*function_name*.__doc__  # will have indent
inspect.getdoc(*function_name*)  # will not have indent

希望你已经学会了一些有用的方法来检查、测试你的文档字符串并与之交互。我希望这一系列文章已经充分介绍了关于 docstring 和文档的主题。如果有其他有趣的方面,请留下您的评论。

感谢您的阅读!如果你喜欢这篇文章,请随意分享。

相关链接

sphinx.ext.coverage文档:https://www . sphinx-doc . org/en/master/usage/extensions/coverage . html

docstr-coverage文档:https://pypi.org/project/docstr-coverage/

doctest文件:【https://docs.python.org/3/library/doctest.html

inspect文件:https://docs.python.org/3/library/inspect.html

Sphinx 高级代码文档—第 2 部分

原文:https://towardsdatascience.com/advanced-code-documentation-with-sphinx-part-2-32c82860a535

Sphinx 的扩展提供了一个用户友好的界面来理解代码库——即使对于非技术用户也是如此

更新 :本文是系列文章的一部分。查看 第 1 部分 第 3 部分

格伦·卡斯滕斯-彼得斯在 Unsplash 上拍摄的照片

上周,我在 Read Docs 上发表了一篇关于如何设置、定制和部署 Sphinx 文档的文章,这应该足以让你的第一稿启动并运行。但实际上,您的代码库可能是一个复杂的函数和类结构,或者您可能希望向观众展示如何使用 Jupyter 笔记本与您的代码库进行交互的示例。这篇文章将涉及到增强你的(不那么)初始文档的方法。

目录

函数和类的更多格式

Python 类允许对函数和数据进行分组,并提供面向对象编程(OOP)的特性,这是一种构建灵活、可重复代码的方式。类中的函数被称为类方法。

在第一篇文章中,我们使用automodule将文档字符串转换成函数的文档。当使用类时,我们可以使用autoclass执行同样的操作。

使用自动模块(左)和自动类(右)的文档–作者图片

Sphinx 很灵活,有其他方法可以达到相同的效果,甚至可以更改显示以包含或排除项目。修改 Sphinx 布局是通过使用扩展实现的,这可能需要安装额外的 Python 包,修改conf.py文件,或者更改.rst文件。

在后面的章节中,扩展的使用也是相关的。完整的扩展列表的一部分可以在 Sphinx 文档中找到。

使用 autodocsumm 的文档–作者图片

要以表格格式显示所有类方法的列表,安装 Python 包autodocsumm并将其包含在conf.py中,如下所示:

extensions = ["autodocsumm"]
autodoc_default_options = {"autosummary": True}

我发现autodocsumm扩展非常有用,因为我可以用表格的形式查看所有的类方法。还有其他流行的扩展如autodocautosummary。个人觉得autodocsumm是两者的结合,比较好用。

使用扩展查看 Jupyter 笔记本和减价文本

Jupyter 笔记本是自包含的文档,可以向用户展示如何与你的代码库交互,展示一个示例案例研究,或者它只是一种漂亮的、有组织的方式来显示代码。本着持续集成持续交付(CI/CD)的精神,最好让 Sphinx 文档显示 Jupyter 笔记本,而不是通过文本、代码和图像在.rst文件中复制笔记本。

要展示 Jupyter 笔记本,安装 Python 包nbsphinx并将其添加到conf.py文件的扩展列表中,类似于上一节。您还需要运行conda install pandoc。这就完成了安装,Jupyter 笔记本路径可以添加到index.rst中,就像index.rst指向其他.rst文件一样。

狮身人面像上展示的朱庇特笔记本——作者图片

降价文本是常用于README的文本文件。为了展示 Markdown 文件,所需的 Python 包应该是myst_parser,类似地,将其添加到conf.py中的扩展列表。现在,您可以通过以下方式指向index.rst中的降价文本,

.. include:: ../../README.md
   :parser: myst_parser.sphinx_

还有其他扩展如m2rm2r2recommonmark也可以显示降价文本,但是myst_parserSphinx 文档中推荐的处理降价文本的方式。

在 Sphinx 上整合 README Markdown–作者图片

您还可以在 Sphinx 上包含其他格式的文件,请访问我的 GitHub 库以保持更新!

添加徽章以展示代码质量

狮身人面像上的徽章——作者图片

徽章显示文档的状态——构建状态、单元测试结果、维护质量、python 包版本、发布版本、python 版本兼容性、许可证、下载次数等。

徽章通常由图像 URL、路径 URL 和替代文本组成。它在.rst文件中有这样的格式

.. image:: image-URL
   :target: path-URL
   :alt: Alt-Text

下面是.md文件中徽章的格式

[![Alt-Text](image-URL)](path-URL)

徽章可以是静态的也可以是动态的。对于静态徽章,我推荐使用 shields.iobadgen.net来生成图片 URL。动态徽章会被刷新,并且通常会由持续集成持续交付(CI/CD)流程自动刷新。动态徽章的一些示例包括阅读文档圈子 CITravis CI 徽章等等。

托管关于 Confluence 的文档

Confluence 是一个团队知识共享工作区,团队成员可以在这里协作处理工作和文档信息。将 Sphinx 与 Confluence 集成在一起,可以将项目文档和代码文档保存在一个一站式门户中。

要进行设置,这需要 Python 包sphinxcontrib-confluencebuilder,同样将其添加到conf.py中的扩展列表。在 Confluence 中,从Space Settings > Manage space > Space details获取空格键,并在这里创建一个 API 令牌。现在您已经有了在 Confluence 上发布 Sphinx 文档的所有细节!

要执行链接 Sphinx 和 Confluence 的最后一步,在conf.py中添加以下信息,最后运行make confluence来构建您的 Confluence 文档。

confluence_publish = True
confluence_space_key = CONFLUENCE_SPACE_KEY
confluence_server_url = 'https://<your-page>.atlassian.net/wiki/'
confluence_server_user = '<your-email>@gmail.com>
confluence_server_pass = CONFLUENCE_API_KEY

Confluence 页面上的 Sphinx 文档–图片由作者提供

希望你已经学会了一些先进实用的使用斯芬克斯的方法。Sphinx 绝对是一个让代码库脱颖而出的工具,为用户提供可读性和可理解性。

这些是演示中使用的 GitHub 库阅读文档文档汇合页面的链接。

感谢您的阅读!如果你喜欢这篇文章,请随意分享。

相关链接

阅读我个人项目的文档:https://kayjan.readthedocs.io/

狮身人面像文献:https://www.sphinx-doc.org/en/master/

带有 Confluence 的 Sphinx 文档:https://sphinxcontrib-Confluence builder . readthedocs . io/en/stable/

Sklearn 高级缺失数据插补方法的深入教程

原文:https://towardsdatascience.com/advanced-missing-data-imputation-methods-with-sklearn-d9875cbcc6eb

学会利用强大的基于模型的插补技术。

安妮·伦凯拍摄

介绍

尽管有大量的 MOOCs 和其他在线资源,但在处理某些数据问题方面仍然存在技能差距。一个例子是正确处理现实世界数据集中的缺失数据。新手往往对这个问题掉以轻心,也不怪他们。尽管这是一个如此紧迫的问题,但丢失数据问题的复杂性被大大低估了,因为存在小的、易于使用的玩具数据集。

因此,许多初学数据的科学家不会超越简单的均值、中值或众数插补。虽然这些方法对于简单的数据集来说可能足够了,但是对于处理大型数据集中的缺失数据来说,它们并不是一个合适的解决方案。

像数据科学工作流程的任何其他阶段一样,缺失数据插补是一个迭代过程。你应该能够使用多种方法并有效地比较它们的结果。虽然基本技术可能表现良好,但这种情况很少发生,因此您需要一些备份策略。

本教程将介绍 Sklearn 中两个更健壮的基于模型的插补算法— KNNImputerIterativeImputer。您将学*它们的基本用法,调整它们的参数,最后,看看如何直观地测量它们的效果。

https://ibexorigin.medium.com/membership

获得由强大的 AI-Alpha 信号选择和总结的最佳和最新的 ML 和 AI 论文:

https://alphasignal.ai/?referrer=Bex

识别缺失的类型

实施有效插补策略的第一步是确定值缺失的原因。尽管每个案例都是独一无二的,但失踪可以分为三大类:

  • 完全随机缺失(MCAR) :这是一个真实的数据随机缺失案例。例如数据输入中的突然错误、暂时的传感器故障或与任何外部因素无关的一般丢失数据。丢失的数量很少。
  • 随机失踪(MAR) :这是一个更广泛的 MCAR 案例。尽管乍一看,丢失的数据似乎是随机的,但它将与其他观察到的特征有一些系统的关系——例如——在计划的维护中断期间,观察设备中丢失的数据。空值的数量可能会有所不同。
  • 非随机缺失(MNAR) :缺失值可能大量存在,缺失的原因与我们无法控制或了解的因素有关。

确定你的问题属于哪一类可以帮助你缩小解决方案的范围。

让我们使用糖尿病数据集进一步探究这些缺失类型:

作者图片

有五个要素具有不同比例的缺失值。识别缺失类型的第一步是绘制缺失矩阵。这个特殊的情节可以通过missingno包获得,我们可以将它作为msno导入:

作者图片

该矩阵显示了空值是如何分散在数据集中的。白色的线段或线条表示缺失值所在的位置。葡萄糖、身体质量指数和血压列可被视为 MCAR,原因有二:

  • 缺失值的比例很小。
  • 缺失值完全随机分布在数据集中。

但是,胰岛素和 SkinFoldThickness 列有异常多的缺失数据点。那么,他们的失踪有什么关系吗?

为了回答这个问题,MSNO 提供了一个缺失率热图,显示了缺失率之间的相互关系:

>>> msno.heatmap(diabetes);

作者图片

从图中我们可以看到皮肤厚度和胰岛素之间有很强的相关性。我们可以通过对任一列进行排序来确认这一点:

>>> msno.matrix(diabetes.sort_values("Insulin"));

作者图片

该图显示,如果 SkinThickness 中的数据点缺失,我们可以猜测它也从胰岛素列中缺失,反之亦然。由于这种联系,我们可以有把握地说两列中缺失的数据不是随机缺失的(MNAR)。

我们还可以看到血压和皮肤厚度之间的弱相关性,这表明血压并非完全随机缺失(MCAR),而是与皮肤厚度的缺失值有一定关系。换句话说,就是随机缺失(MAR)。

你可能需要一段时间来理解这些思念的类型。要更深入地了解,你可以参考我写的另一篇文章,专门讨论想念类型和 MSNO 套餐:

https://towardsdev.com/how-to-identify-missingness-types-with-missingno-61cfe0449ad9

用 KNNImputer 输入

现在,让我们来介绍一些插补方法。

除了基本的SimpleImputer,Sklearn 还提供了KNNImputer类,它使用 K-Nearest-Neighbors 算法来估算数值。如果您不熟悉它,我推荐您阅读我关于它的另一篇文章:

作为参考,下面是一篇文章的节选,简要介绍了 KNN 算法的工作原理:

“假设您有一个包含两个类别的变量,此处显示了这两个类别:

图片由维基百科

给定一个新的未知样本,如何判断它属于哪一组?当然,你会看周围的点。但是结果真的取决于你看得多远。如果您查看最近的三个数据点(实心圆内),绿点将属于红色三角形。如果你看得更远,(虚线圆圈内)点将被归类为蓝色方块。

KNN 也是如此。根据 k 的值,该算法通过分类中最近的 k 个邻居的多数投票对新样本进行分类。对于预测新样本的实际数值的回归,该算法取最近的 k 个邻居的*均值。"

KNNImputer 是 KNN 算法的一个略微修改的版本,它试图通过*均其 k 最近邻居之间的距离来预测数值的无效值。对于已经使用 Sklearn 一段时间的人来说,它的 Sklearn 实现应该不成问题:

有了这个估算器,问题就是为 k 选择正确的值。由于您无法使用 GridSearch 对其进行调优,因此我们可以采用可视化方法进行比较:

作者图片

在第 5 行中,我们绘制了缺失值的原始皮肤厚度分布。然后,在第 6–9 行,我们用不同的 k 值估算相同的分布,并在原始分布的顶部绘制。估算分布越接近原始分布,估算就越好。在这里,似乎 k=2 是最佳选择。

用迭代估算器估算

另一种更健壮但计算成本更高的技术是使用IterativeImputer。它采用任意的 Sklearn 估计量,并尝试通过将其他要素建模为具有缺失值的要素的函数来估算缺失值。以下是对其功能的更详细的逐步说明:

  1. 回归量被传递给转换器。
  2. 选择具有缺失值的第一个特征( feature_1 )。
  3. 数据被分成训练集/测试集,其中训练集包含 feature_1,的所有已知值,测试集包含缺失样本。
  4. 回归变量适合所有其他变量作为输入,而 feature_1 作为输出。
  5. 回归预测器预测缺失值。
  6. 转换器继续这个过程,直到所有的特征都被输入。
  7. 步骤 1-6 被称为一轮迭代,这些步骤按照max_iter transformer 参数的规定执行多次。

这意味着IterativeImputer (II)预测单个缺失样本的可能值不是一个而是 max_iter 个。这样做的好处是将每个缺失数据点视为一个随机变量,并将缺失值带来的固有不确定性联系起来。这也被称为多重插补,,它是大多数其他插补技术的基础(是的,还有很多其他技术)。

当所有迭代完成后,II 只返回预测的最后结果,因为通过每次迭代,预测都会得到改善。该算法还有一个早期停止功能,如果两轮之间没有明显的差异,它可以终止迭代。

根据 Sklearn 的说法,IterativeImputer 的这种实现受到了更流行的 R MICE 包(通过链式方程进行多元插补)的启发。让我们来看看它的实际应用:

*IterativeImputer*仍然是一个实验性的特性,所以不要忘记包含上面代码片段的第二行。

estimator设置为无时,算法会自行选择。但是,在阅读了 Sklearn 关于IterativeImputer的官方指南之后,我了解到BayesianRidgeExtraTreeRegressor产生了最好的结果。

不同技术的性能比较

现在是检验估算效果的时候了。为了实现这一点,我们将预测患者是否患有糖尿病(结果),因此这是一项二元分类任务。让我们构建功能/目标阵列:

我们将使用交叉验证来测试KNNImputerIterativeImputer。对于估算器,我们将使用推荐的BayesianRidgeExtraTreesRegressor:

作者图片

我们可以从最终的结果中看到,在 RandomForests 上训练时,具有七个邻居的 KNNImputer 是数据集的最佳选择。尽管我提到过IterativeImputer会更健壮,但你永远无法确定。也许,我们可以通过调整它的参数来获得更好的性能。

摘要

数据缺失是一个应该重视的问题。如果你连先决数据问题都解决不了,那么花几个小时学*复杂的 ML 算法是没有意义的。请记住,模型的好坏取决于对其进行训练的数据。这意味着您必须尽最大努力处理缺失的数据点,因为它们在现实世界的数据集中无处不在。

在本文中,您学*了如何使用两种基于模型的技术来处理缺失:KNNImputerIterativeImputer。以下是它们的文档链接、官方的 Sklearn 使用指南以及有助于您理解的相关资源:

感谢阅读!

https://ibexorigin.medium.com/membership https://ibexorigin.medium.com/subscribe

我的更多故事:

</10-minute-effortless-sql-tutorial-for-die-hard-pandas-lovers-a64c36733fd0> https://ibexorigin.medium.com/yes-these-unbelievable-masterpieces-are-created-with-matplotlib-b62e0ff2d1a8

拥有 GPT-3 和 GPT-J 的先进 NER

原文:https://towardsdatascience.com/advanced-ner-with-gpt-3-and-gpt-j-ce43dc6cdb9c

几年前出现了基于变形金刚的生成式深度学*模型。GPT-3 和 GPT-J 是当今最先进的文本生成模型,它们非常强大,几乎彻底改变了许多传统的 NLP 用例。实体抽取(NER)就是其中之一。

在本文中,我们将看到如何使用 GPT 模型来执行高级实体提取,而无需注释任何数据。注释和训练自己的 NER 模型一直是一个挑战,但幸运的是,这不再是必要的了!

由于 GPT-3 可能相当昂贵,我们所有的例子都将基于 GPT-J 通过 NLP 云 API 进行快速原型制作。

法国阿尔卑斯山(图片由作者提供)

用老方法做 NER

实体提取是最古老的 NLP 用例之一,也可能是当今生产中最常*的 NLP 用例之一。传统上,像 spaCyNLTK 这样的框架曾经是最好的选择。

SpaCy 非常适合生产,因为它易于使用,并且在生产中运行速度极快。SpaCy 提供了许多预先训练的模型,人们可以很容易地下载并在生产中立即开始使用。空间模型支持一些现成的本地实体,如地址、日期、货币…

NLTK 不适合生产,但它是研究项目和 NLP 升级的一个很好的工具。NLTK 也提出了一些预训练的模型,但是比 spaCy 少了一些本地实体。

这些预训练模型的主要问题是,它们只支持它们被训练的原生实体…而这些实体在现实生活项目中很少有用。大多数公司希望使用 NER 提取自定义实体,如职位、产品名称、电影名称、餐馆等。唯一的解决方案是通过漫长而乏味的注释过程为这些新实体创建一个庞大的数据集,然后训练一个新的模型。每当人们想要支持一个新的实体时,唯一的解决方案就是重新注释和训练。像 Prodigy 这样伟大的注释工具确实有所帮助,但它仍然需要一个或几个人力资源在潜在的长时间内做大量的工作。

希望 GPT 大型语言模型现在能解决这个问题。

什么是 GPT-3 和 GPT-J?

2020 年 5 月,OpenAI 发布了一个巨大的 NLP 模型:GPT-3。

GPT-3 是一个基于变形金刚的大型语言模型,它开始革新自然语言处理领域。该模型在 175B 参数上进行训练。它是如此之大,以至于它可以理解许多人类的查询,而不必为此进行明确的训练。它几乎可以做传统 NLP 模型所做的一切:NER、摘要、翻译、分类…等等。

GPT 3 号有几个弱点:

  • 它非常昂贵,只能通过 OpenAI API 使用
  • 它非常慢(与 spaCy 这样的框架相比)
  • 它不一定容易使用

好消息是,EleutherAI(一个人工智能研究人员的集体)在 2021 年发布了开源替代品:GPT-J 和 GPT-NeoX 20B。任何人都可以在任何服务器上部署这些 NLP 模型,但在实践中,这需要一些 MLOps 知识,而且成本可能相当高,这就是为什么我们要使用既经济又易于使用的 NLP 云 API。

设置 NLP 云

首先,在 NLP 云上注册。

然后切换到现收现付计划,因为该计划允许您尽可能多地使用 GPT-J,并且前 100k 令牌是免费的,这对于测试本文中的代码来说绰绰有余。

检索您的 API 令牌。

最后,下载他们的 Python 客户端,因为我们将在以下示例中使用它:

pip install nlpcloud

快速工程

假设我们想从一段文本中提取职位名称。

让我们向 GPT·J 提出第一个天真的请求:

import nlpcloudclient = nlpcloud.Client("gpt-j", "<your_token>", gpu=True)
generation = client.generation("""Extract job titles from the following sentence: Maxime is a data scientist at Auto Dataset, and he's been working there for 1 year.""")print(generation["generated_text"])

输出:

Extract job titles from the following sentence: Maxime is a data scientist at Auto Dataset, and he's been working there for 1 year.1\. Maxime works in the data science team at Auto Dataset.

如你所*,我们悲惨地失败了!原因是,像 GPT-3 和 GPT-J 这样的生成模型需要在提示中提供几个例子,以便理解你想要什么(也称为“少量学*”)。提示基本上是一段文本,您将在实际请求之前添加它。

让我们用提示中的 3 个例子再试一次:

import nlpcloudclient = nlpcloud.Client("gpt-j", "<your_token>", gpu=True)generation = client.generation("""[Text]: Helena Smith founded Core.ai 2 years ago. She is now the CEO and CTO of the company and is building a team of highly skilled developers in machine learning and natural language processing.
        [Position]: CEO and CTO
        ###
        [Text]: Tech Robotics is a robot automation company specialized in AI driven robotization. Its Chief Technology Officer, Max Smith, says a new wave of improvements should be expected for next year.
        [Position]: Chief Technology Officer
        ###
        [Text]: François is a Go developer. He mostly works as a freelancer but is open to any kind of job offering!
        [Position]: Go developer
        ###
        [Text]: Maxime is a data scientist at Auto Dataset, and he's been working there for 1 year.
        [Position]:""",
    max_length=500,
    end_sequence="\n###",
    remove_end_sequence=True,
    remove_input=True)print(generation["generated_text"])

输出:

Data scientist

成功了!这里发生了什么?

首先,在传递我们的实际句子之前,我们在提示中给出了 3 个问题和 3 个回答。3 个例子通常足以教会这些模型你想要达到的目标。

我们还使用了几个参数:

  • max_length告诉 API 最多生成 500 个令牌
  • end_sequence="\n###"告诉模型一旦到达\n###就停止生成文本。这使得文本生成速度更快,因为我们不必等到生成 500 个令牌(也更便宜)。我们知道模型会在结果后面加上\n### token 是因为我们在提示里每个结果后面都加了,而 GPT-J 非常擅长学*格式化。
  • remove_end_sequence简单地删除响应末尾的\n###
  • remove_input从响应中删除输入

用 spaCy 做同样的事情需要一个专门的数据集+大量例子的训练…换句话说,我们只是节省了几周,甚至几个月的人工工作!

丰富

我们刚刚用 GPT J 做了第一个实体抽取的概念证明,但是我们当然可以改进它。

我们应该做的第一件事是降低顶部 P 值。Top P 和温度是 GPT 模型的两个常用参数。高值往往会产生更多的原始结果,这不是我们在这里想要的,因为我们希望模型以确定的方式一致地提取相同的实体,而不需要发明任何东西。最好的方法是将 Top P 降低到 0.1。

我们应该关心的第二件事是处理空响应的能力。您的文本不包含任何职位,这种情况确实可能发生,在这种情况下,您希望模型返回类似“none”的内容(例如)。所以你需要明确地告诉模型。

让我们实施这两项改进:

import nlpcloudclient = nlpcloud.Client("gpt-j", "<your_token>", gpu=True)
generation = client.generation("""[Text]: Helena Smith founded Core.ai 2 years ago. She is now the CEO and CTO of the company and is building a team of highly skilled developers in machine learning and natural language processing.
        [Position]: CEO and CTO
        ###
        [Text]: Tech Robotics is a robot automation company specialized in AI driven robotization. Its Chief Technology Officer, Max Smith, says a new wave of improvements should be expected for next year.
        [Position]: Chief Technology Officer
        ###
        [Text]: François is a Go developer. He mostly works as a freelancer but is open to any kind of job offering!
        [Position]: Go developer
        ###
        [Text]: The second thing we should care about is the ability to handle empty responses.
        [Position]: none
        ###
        [Text]: Maxime is a data scientist at Auto Dataset, and he's been working there for 1 year.
        [Position]:""",
    max_length=500,
    top_p=0.1,    
    end_sequence="\n###",
    remove_end_sequence=True,
    remove_input=True)print(generation["generated_text"])

例如,你可以通过处理多个结果来进一步改进你的提示(例如,从同一段文本中提取几个职位名称)。

生产部署

这些 GPT 模型的主要缺点是它们在生产中高效运行的成本很高,并且需要一些高级 DevOps 知识。

例如,你应该忘记在你自己的本地机器上或者甚至在 CPU 服务器上运行 GPT-J。如果你想让它在一个体面的时间(1 秒以下)提取你的实体,你需要使用一个好的 GPU,如英伟达 RTX A6000 或英伟达 A40。

结论

一旦你理解了如何处理提示,用 GPT-3 和 GPT-J 进行实体抽取会给出令人印象深刻的结果。

由于不需要更多的注释和培训,我认为这将极大地改变 NER 项目的组织方式。

虽然仍然存在一些基础设施的挑战,但我认为与数据标签的人力成本相比,这些挑战可以忽略不计。

我希望这篇文章有用,它会给你的下一个 NER 项目带来新的想法!

在一行代码中创建令人惊叹的可视化熊猫数据框架

原文:https://towardsdatascience.com/advanced-pandas-plots-e2347a33d576

一个简单的技巧,使您的图表具有交互性和视觉吸引力

来自佩克斯莎伦·麦卡琴的照片

伟大的视觉化带来卓越的洞察力。

几乎每个使用 Python 的数据科学家也用熊猫。这是事实上的用于数据争论的 Python 库。开箱即用的熊猫为常*的图表类型提供了一些很好的可视化效果。

但是默认并不是最好的。

我们可以用一个像 Plotly 这样的配套框架做得更好。我们可以将绘图后端设置为 Plotly,并在我们的项目中使用其时尚的图表。

但是单独设置后端并不能给我们的数据帧带来的全部好处。例如,Pandas 没有表面绘图选项。此外,Plotly 创建图表的方式与熊猫略有不同。

袖扣是另一个弥合这一鸿沟的图书馆。我们可以用同样的熊猫叫声来制作更令人惊叹的图表。此外,我们可以开发高级图表,如曲面图。

如何从数据帧创建情节-纯熊猫的方式。

在 Pandas 中,如果要创建条形图、箱线图等图表,只需调用 plot 方法即可。我们可以指定我们需要的图表类型和其他几种配置。

在下面的例子中,我们使用 panda 的内置绘图功能创建了一个条形图。

df.plot(kind='bar', x="month", y="passengers")

Pandas 使用 Matplotlib 后端创建的条形图—作者截图。

以上很直白。然而,它的外观并没有那么好。

Pandas 默认的绘图后端是 Matplotlib 。它在许多情况下都工作得很好。但是如果有不同的后端,图表会更好。

通过将绘图后端改为 Plotly,我们可以快速将这个普通的图表变成一个漂亮的图表。

pip install plotly==5.5
# conda install -C plotly plotly==5.5.0

如果您的计算机上还没有安装 Plotly,请使用上面的代码。

我们可以用下面一行代码将后端设置为 Plotly。我建议您在将熊猫导入笔记本(或项目)后立即添加这一行。)

 import pandas as pd
pd.options.plotting.backend = “plotly”

生成的图表更具美感,而且总结得很好。

条形图由熊猫的 Plotly 后端创建-作者截图。

但是,正如我前面提到的,它仍然缺少一些关键图表。我们换个方式来挖掘 Plotly 的最大潜力。

</9-easy-steps-to-make-great-charts-33e2c4612e39>

如何使用袖扣从数据框中创建图

Cufflinks 是一个 Python 库,它帮助我们以一种类似熊猫的自然语法来使用熊猫。它还增加了比我们通常在熊猫数据框中看到的更令人印象深刻的图表类型。

我们可以导入它,配置一次全局主题和其他选项,并使用添加到每个数据帧的iplot API,而不是默认的绘图方法。

让我们用下面的命令从 PyPI 安装它。

pip install cufflinks

安装完成后,我们可以在笔记本中导入并配置它。

import pandas as pd
import cufflinks as cf
import numpy as npcf.set_config_file(theme='pearl')

我们现在可以使用iplot方法创建许多不同的图表。这里有一个例子。

cf.datagen.lines(4,1000).iplot()

我们使用了袖扣包装的datagen模块。它允许我们为各种情况生成随机数据。我们将用它来为这篇文章的其余部分创建数据。

使用袖扣、熊猫和 Plotly 生成的折线图--作者截图。

这个小小的调整极大地提高了图表的可展示性,而没有显著改变我们的代码。

我们可以在数据帧上创建的图形数据可视化类型。

Plotly 有几种不同的图表类型。其中一些可以通过袖扣买到,我们可以直接从数据框中调用。

以下是一些熊猫身上没有的图表,但通过袖扣却成为可能。

3D 曲面图。

曲面图是三维数据的可视化表示。它在很多应用中都很有用。例如,我们在机器学*中使用曲面图来研究成本函数和梯度下降优化。

以下代码从 dataframe 创建表面图。袖扣选择列和行索引作为 x 轴和 y 轴。数据帧的值在 z 轴上。

表面图的数据集。作者截图。

cf.datagen.sinwave(10,.25).iplot(kind='surface')

用袖扣、Plotly 和熊猫创建的表面图。—作者 GIF。

如果数据集的所有值都在不同的列中,请在绘制之前使用如下所示的透视函数将其转换为兼容的格式。

在曲面图中使用的数据透视表。—作者截图。

气泡图

气泡图是以有意义的方式可视化多维度的另一个好方法。我们可以在一张图中描绘出四个特征,包括一个分类变量。

下面的图表显示了行星大小如何随着它与太阳的距离以及每个行星的质量而变化(当然是假数据。)

cf.datagen.bubble(prefix="planet").iplot(kind='bubble',x='x',y='y',size='size',categories='categories',text='text', xTitle='Relative Mass',yTitle='Distance from the Sun',title='Plannet Size, Mass and Distance')

用袖扣、熊猫和 Plotly 创建的气泡图——作者的屏幕记录。

另外,请注意,您使用袖扣扩展创建的图表是交互式的。将鼠标悬停在任何气泡上以查看其详细信息。你可以点击任何类别来打开或关闭它。

热图图表

热图通常是在数据集中找出热点的一种更简单的方法。它们就像表面图,允许我们同时可视化三个数据维度。但是在这里,我们用的不是 z 轴,而是色谱。

像其他图表类型一样,创建热图也很容易。

cf.datagen.heatmap(20,20).iplot(kind='heatmap',colorscale='spectral')

用袖扣创建的热图,绘在熊猫数据帧上——作者截图。

传播图表

假设你在一段时间内跟踪两个类别的变量;你可能还想看看它们的差异是如何随着时间而变化的。你可能要看看差距是否正在缩小,甚至翻转。或者可能是差异本身的趋势。

分布图是一种很好的方式来显示两个变量随时间的分布。

cf.datagen.lines(2).iplot(kind='spread',xTitle='Dates',yTitle='Return')

电子表格的工作原理就像折线图一样。但是除了绘制各条线之外,它还会在折线图下方生成一个面积图。它们共享同一个时间轴,因此很容易理解。

用袖扣和熊猫数据框绘制的电子表格。—作者截图。

这些只是你可以用袖扣扩展创建的许多图表中的一部分。当然,您也可以从 pandas 默认 API 中获得更常*的图表。

改变图表的主题。

通过袖扣配置,你可以轻松地在几种颜色主题之间切换。我们有以下选项来选择一个。

ggplot, pearl, solar, space, white, polar, henanigans

在本文的顶部,我们第一次配置袖扣时使用了珍珠主题。下面是我们如何把它改成不同的主题。

cf.set_config_file(theme='henanigans')

下面是我们使用的最后一个例子如何出现在其他颜色主题中。

袖扣中不同主题生成的电子表格-作者截图。

最终想法

可视化使得我们可以用手头的数据做的事情完全不同。

当使用 Pandas dataframes 时,我们主要使用其默认的绘图方法来创建图形。但是这些图表的风格不足以很好地呈现它。一个快速的技巧是将绘图后端改为 Plotly 并拥有漂亮的图表。

然而,熊猫数据框的另一个巧妙绑定,称为袖扣,为默认的熊猫绘图选项增加了额外的可能性。有了它,我们可以在几个预配置的主题之间快速切换,并解锁 Pandas 中没有的图表。

这篇文章讨论了如何开始使用熊猫、Plotly 和袖扣。我们还在一行代码中创建了一些奇妙的数据帧视觉效果。

</5-python-gui-frameworks-to-create-desktop-web-and-even-mobile-apps-c25f1bcfb561>

朋友,感谢你的阅读!在LinkedInTwitter,以及Medium上跟我打招呼。**

还不是中等会员?请使用此链接 成为会员 因为,在不为你额外付费的情况下,我为你引荐赚取一小笔佣金。

使用 scikit 的高级管道-了解

原文:https://towardsdatascience.com/advanced-pipelines-with-scikit-learn-4204bb71019b

整合来自 imblearn 的模块、管道中的功能引擎,并提取功能重要性图

照片由 Pexels 拍摄。

在您的机器学*项目中使用管道有助于为您的工作流带来更多的结构。它们使您的不同过程步骤更容易理解、重现,并防止数据泄漏。

Scikit-learn pipeline 与其变压器、模型和其他模块配合得非常好。然而,当一个人试图 scikit-learn 的管道与来自 imblearn 等其他包的管道解决方案或模块进行合并或集成时(即使它是建立在 scikit-learn 之上的),这可能(非常)具有挑战性。

可能会出现这样的问题:

**TypeError**: All intermediate steps should be transformers and implement fit and transform or be the string ‘passthrough’ ‘SMOTE()’ (type <class ‘imblearn.over_sampling._smote.base.SMOTE’>) doesn’t

即使完全坚持 scikit-learn 功能,从管道中提取最终使用的特性来创建特性重要性图也常常是具有挑战性的。

本文通过构建一个用于客户流失预测的集成或投票分类器的例子向您展示如何

  • scikit-learnimblearnfeature-engine 包中构建一个包含模块的管道
  • 在编码步骤之后,从你的管道中提取特征(例如,一键编码)。
  • 创建一个特征重要性图。

重要提示:我建议安装最新版本的 scikit-learn(在撰写本文时是 1.1.1)以便能够从管道中提取特性。由于这个要求,代码将不能在 Google Colab (1.0.2)上运行。

Outlook 最终解决方案:在一个管道中组合来自不同包的几个模块

图一。最终管道(图片由作者提供)。

图 1 显示了我们希望在本文末尾看到的内容。下面,我们将实现这些步骤中的每一个。从丢弃不相关的特征(步骤 1)到应用估算器和缩放器(步骤 2)和处理类别不*衡(步骤 3)到我们的集成模型(步骤 4)。在第 5 步中,我们应用超参数优化并创建一个特征重要性图。

EDA、特征构建、最大化模型性能、分析和解释结果不在本文的范围之内。目标是向您展示如何使用集成了来自不同包的模块的管道

步骤 0:准备和数据加载

在设置我们的管道之前,我们必须加载我们需要的包和示例数据。

下面的代码向您展示了本文中所需的包和模块。

上面的代码导入了常*的嫌疑人(熊猫、numpy 等。),提到的软件包 scikit-learn(或 sklearn),imblearn 和 feature-engine。它还导入了 xgboost,这是我们的集成分类器的一部分,以及用于超参数调整的 scipy 包中的 loguniform 模块。

如果你以前没有听说过 imblearn 和特性引擎包,这里有一个简短的解释。 Imblearn 通过提供不同的采样策略,帮助你处理类不*衡特征引擎 提供模块管理数据集中的列或特征(例如,删除不相关的)。

数据集:报纸流失

所使用的数据集来自以前的 Kaggle 竞赛并获得 CC0:公共领域许可。它包含 15.855 条记录和 19 列,包括目标变量订户(是/否)。大多数特征都是典型的。

下面的代码加载数据并应用一些预备步骤,比如将所有列名转换成小写并将目标变量转换成布尔值。

在应用这些次要的预清理步骤后,数据应该如下所示:

图二。摘录报纸资料(图片由作者提供)。

步骤 1:排除特征

管道中的第一步是排除或删除对我们的预测没有帮助的列。例如,列 subscriptionid,每行有不同的值,这是有意义的,但是这个特性对我们的建模步骤没有好处。我们还可以排除重复的特征(例如,具有相同值的相同列两次或更多次)和包含常数值的特征。

上面的代码创建了一个管道对象(line 1),并添加了三个步骤(lines 3–5)。步骤被定义为元组,第一个元素定义步骤的名称(例如,‘drop _ columns’),第二个元素定义转换器(例如, DropFeatures() )。

这些都是非常简单的步骤,也可以应用到管道之外(例如,熊猫)。然而,本文的想法是在管道中集成尽可能多的功能。更多关于特性引擎包的信息可以在这里找到📗

蓝色圆圈中的“步骤”(图 1)和标题是指导您阅读本文的步骤。上面代码中的步骤是“真正的”管道步骤。

步骤 2:估算和转换值

在我们删除了不相关的列之后,我们现在关注于处理缺失值和特性缩放。我们的数据集包含不同类型的列( integercategorial )。这就是为什么我们必须定义两个独立的工作流。

我们添加了一个名为清理的新步骤,并创建了一个 ColumnTransformer 对象(line 8)。在 ColumnTransformer 中,我们设置了两条新管道。一个用于处理数值(line 10),一个用于处理类别值(line 16)。为了确保为每个步骤选择正确的列,我们使用了 make_column_selector 方法(lines 13,19)。

我们通过使用 dtype_include 参数来选择相关的列。当然,我们也可以提供列名列表或 regex 语句。

第三步:取样

流失或欺诈分类的一大挑战是处理类别不*衡。Imblearn 提供了一系列可供您应用的采样方法。在这个例子中,我们将使用 SMOTE 采样方法(line 23)。

从管线中提取变换和缩放的特征

在第 4 步建立我们的集成分类器之前,我们要检查哪些特征通过了管道,它们看起来像什么。

图 3 显示了我们管道的当前状态。

图 3。步骤 3 后的管道(图片由作者提供)。

pipeline 对象提供了一个名为get _ feature _ names _ out()的方法。但是在使用它之前,我们必须在数据集上安装管道。由于步骤 3 (SMOTE)只关注我们的 y 数据,我们可以忽略它,只关注步骤 1–2。

上面的代码(line 1)提取了从 DropFeatures ( [0:)到cleaning:column transformer(:4])步骤的流水线步骤,并拟合训练数据(line 2)。管道拟合好后,我们可以调用get _ feature _ names _ out()方法。结果看起来像这样:

0                    num__year_of_residence
1                             num__zip_code
2                       num__reward_program
3        cat__hh_income_$  20,000 - $29,999
4        cat__hh_income_$  30,000 - $39,999
                        ...                
12122               cat__source_channel_TMC
12123            cat__source_channel_TeleIn
12124           cat__source_channel_TeleOut
12125               cat__source_channel_VRU
12126          cat__source_channel_iSrvices
Length: 12127, dtype: object

由于一次热编码,产生了许多新功能( cat__XX_XX )。命名约定向您显示该特征是数字特征还是类别特征(如 cat__ )、其名称(如 source_channel_ )以及相关值( TMC )。

为了像我一样显示您的管道(例如,图 3),只需在调用您的管道对象(例如,ppl)之前将set_config(display="diagram")放在您的代码中。参*步骤 0“准备和数据加载”代码行 33。

步骤 4:构建集成分类器

现在是时候建立我们的集成或投票分类器。在本例中,我们想使用下面三个模型的均值预测(lines 2–6)。这就是为什么我们将投票参数设置为 ( line 8)。

在定义集合模型之后,我们准备将它集成到我们的管道中。

如果你已经注意到了,那么你已经看到了line 1的变化。我们现在用的不是 sklearn 的 Pipeline 对象,而是 imblearn 的im Pipeline

如果我们不这样做,那么在拟合(ppl.fit(X_train, y_train))数据时,我们会得到以下错误:

**TypeError**: All intermediate steps should be transformers and implement fit and transform or be the string 'passthrough' 'SMOTE()' (type <class 'imblearn.over_sampling._smote.base.SMOTE'>) doesn't

太好了!我们终于组装好了管道。结果可以在图 4 中看到。

图 4。最终管道(图片由作者提供)。

步骤 5:超参数调整和特性重要性

超参数调谐

下面的代码显示了如何通过使用 RandomizedSearchCV 来应用超参数调整。

定义的参数(lines 3-17)遵循特定的命名惯例:

  • 第一个参数( ensemble__ ):投票分类器的名称
  • 第二个参数( lr__ ):我们集合中使用的模型的名称
  • 第三个参数(解算器):模型相关超参数的名称

因为我们必须处理类不*衡,我们将在这个例子中使用重复分层 k-fold ( line 20)。更多关于其优势的信息可以在这里找到。

如果您不想使用超参数调整而想使用您自己的超参数值,您可以在模型初始化(步骤 4)时设置它们,或者在之前添加一个新行*ppl.set_params(**dict_with_best_params)* 拟合语句(*ppl.fit()*)。

特征重要性图

为了使用我们的管道创建一个特征重要性图,我们使用了 排列重要性

Lines 3 to 13显示一个函数,该函数稍后将绘制我们的特征重要性。lines 16 to 18中的代码提取了我们管道中使用的特性名称(作为一个例子,我们在第 3 步结束时做了同样的事情)。在最后两行(lines 20 to 21)中,我们在训练数据上使用拟合的模型/管道来计算排列重要性。

查看特征或排列重要性图(图 5),我们可以看到特征 hh_income 主导了预测。由于该特性包含可排序的值(30–40k 小于 150–175k),我们可以使用不同的编码方式(例如,使用 LabelEncoding)。

图 5。排列重要性图(图片由作者提供)。

结论

使用管道可能会让人神经紧张。特别是如果你想提取特性,组合和使用不同包中的模块,并创建一个特性重要性图。本文通过一个带有不*衡类的分类问题的例子展示了如何创建一个高级管道并应用上面提到的所有步骤。

来源

数据集:https://www . ka ggle . com/datasets/andieminogue/newspaper-churn(CC0:公共领域)

Scikit-learn:https://Scikit-learn . org/stable/modules/generated/sk learn . pipeline . pipeline . html

不*衡学*:https://不*衡学*. org/stable/references/generated/imb learn . pipeline . pipeline . html

特征-引擎:【https://feature-engine.readthedocs.io/en/latest/

创建特征重要性图:https://inria . github . io/scikit-learn-mooc/python _ scripts/dev _ features _ importance . html

高级 SQL:超越基础

原文:https://towardsdatascience.com/advanced-sql-going-beyond-the-basics-bbcae047fe7e

卡斯帕·卡米尔·鲁宾在 Unsplash 上的照片

结构化查询语言(SQL)为您的工具箱增添了一大亮点。它可能不像 Python 或 JavaScript 那样受欢迎,但了解 SQL,尤其是高级 SQL,会带来很多好处。

一方面,了解高级 SQL 技术可以帮助您从数据中获得更好的洞察力,从而可以更有效地交流您的想法。由于 SQL 和其他语言一样存在性能瓶颈和性能问题,因此更深入的了解将有助于您优化查询。

最后,额外的知识将帮助您从其他开发人员中脱颖而出,这些开发人员可能知道 CRUD 操作,但不知道高级 SQL 概念。这给了你一个职业优势。

本文将向您介绍一些高级 SQL 概念,包括子查询、运行总计和公共表表达式(cte)。接下来,您可以使用任何支持 SQL 的数据库和您选择的编辑器。你也可以使用一个在线 SQL 编辑器。

以下示例使用在线 SQL 编辑器和 SQLite 数据库。如果您正在使用 PostgreSQL 之类的数据库,您可能需要更改语法;然而,基本概念是相同的。

并集、交集和例外运算符

您可以使用本资源中的样本数据。在这个例子中,所有的命令都被合并到这个库中的一个脚本中。运行该脚本,它将创建三个包含示例数据的表。以下是表格的模式:

图片由 w3 resource(CC BY 4.0)

每个表格的前五行如下所示:

作者截图

UNIONINTERSECTEXCEPT运算符帮助您组合两个查询的结果。在处理集合时,SQL 中的运算符类似于数学运算符。你必须记住以下规则:

第一个查询返回的表中的列数和列顺序必须等于第二个查询返回的表中的列数和列顺序。此外,相应列的数据类型必须兼容。

下面是在 SQL 中使用运算符的一般语法:

SELECT * FROM TABLE1
OPERATOR
SELECT * FROM TABLE2

联合运算符

UNION操作符返回来自两个查询的表的组合。默认情况下,结果不会有重复值。但是,如果您想保留副本,可以使用UNION ALL操作符。

以下命令将返回所有不同城市的列表:

SELECT working_area FROM AGENTS
UNION
SELECT cust_city FROM CUSTOMER

以下命令将返回所有城市的列表,包括重复的城市:

SELECT 
  working_area 
FROM 
  AGENTS 
UNION ALL
SELECT 
  cust_city 
FROM 
  CUSTOMER

下图比较了UNIONUNION ALL的输出:

作者截图

如你所*,在右边的表格中,伦敦和班加罗尔被重复。

交集运算符

INTERSECT操作符返回第一个和第二个查询返回的表中的公共元素。

-- Returns a list of common cities in both columns
SELECT 
  working_area 
FROM 
  AGENTS 
INTERSECT 
SELECT 
  cust_city 
FROM 
  CUSTOMER

结果如下所示:

作者截图

操作员除外

EXCEPT操作符返回第一个查询返回的表中所有不在第二个查询返回的表中的元素。

SELECT 
  working_area 
FROM 
  AGENTS 
EXCEPT 
SELECT 
  cust_city 
FROM 
  CUSTOMER

上面的命令将返回一个包含温哥华的单行表。你会注意到温哥华是唯一一个在CUSTOMER.cust_city而不在AGENTS.working_area的城市。

子查询

在 SQL 中,可以在查询中包含一个查询,也称为子查询。子查询中也可以包含查询。子查询有三种主要形式:

  • 作为SELECT语句的一部分
  • FROM之后
  • WHERE之后

子查询帮助您将复杂的连接和联合分解成更小的部分,使您的查询更具可读性和可维护性,特别是因为您可以使用现有查询的结果。子查询还使调试更容易,因为您可以独立地调试每个查询。理解子查询也有助于您编写递归 SQL。

带 SELECT 的子查询

查看名为AGENTSORDERS的表格。您的任务是返回一个包含两列的表。第一列应该包含来自AGENTS表的agent_code,第二列应该包含ORDERS.ord_amount列的总和。第二列应该有相同的值,或者重复多次的总和。

首先,返回所有订单金额的总和:

SELECT 
  SUM(ord_amount) 
FROM 
  ORDERS

上面的命令将是您的子查询。您可以如下所示使用它来获得所需的结果:

SELECT 
  agent_code, 
  (
    SELECT 
      SUM(ord_amount) 
    FROM 
      ORDERS
  ) total 
FROM 
  AGENTS

第二行中的命令是子查询。它返回ORDERS.ord_amount列的总和。您还可以命名第二列,方法是使用AS或在子查询后包含您喜欢的名称。下面是部分结果的截图:

作者截图

带有 FROM 的子查询

以下 SQL 命令返回一个表,其中包含订单总额、*均订单额以及代理销售给客户的订单数:

SELECT 
  agent_code, 
  cust_code, 
  sum(ord_amount) total_amnt, 
  avg(ord_amount) avg_amount, 
  count(*) AS num 
FROM 
  ORDERS 
GROUP BY 
  agent_code, 
  cust_code

您必须使用结果来查找每个代理销售的订单总数。您可以将上面的命令和FROM一起用作子查询:

SELECT 
  agent_code, 
  count(agent_code) AS count 
FROM 
  (
    SELECT 
      agent_code, 
      cust_code, 
      sum(ord_amount) total_amnt, 
      avg(ord_amount) avg_amount, 
      count(*) AS num 
    FROM 
      ORDERS 
    GROUP BY 
      agent_code, 
      cust_code
  ) 
GROUP BY 
  agent_code

上面的命令返回每个代理销售给的客户总数。您可以从子查询返回的表中进行选择,而不是从现有表中进行选择。以下是部分结果:

作者截图

带有 WHEN 的子查询

现在使用AGENTSCUSTOMER表返回一个只包含代理和客户共享的通用名称的表。

首先,使用以下命令返回一个包含每个客户姓名的表:

SELECT 
  cust_name 
FROM 
  CUSTOMER

现在使用IN操作符和上面查询返回的表来查找常用名称。下面是命令,使用前面的命令作为子查询:

SELECT 
  agent_name 
FROM 
  AGENTS 
WHERE 
  agent_name IN (
    SELECT 
      cust_name 
    FROM 
      CUSTOMER
  )

WHERE子句检查子查询返回的表中是否存在AGENTS.agent_name。它将返回一个有两行的表:Benjamin 和 Charles。

公共表表达式(cte)

在 SQL 中,创建临时变量来存储子查询的结果。这些变量只能在外部查询中访问。在前面的示例中,您返回了一个包含每个代理销售的订单数量的表,您可以将该结果存储为 CTE,以使您的查询更具可读性。

WITH CTE_AGENT_CUSTOMER AS (
  SELECT 
    agent_code, 
    cust_code, 
    sum(ord_amount) total_amnt, 
    avg(ord_amount) avg_amount, 
    count(*) AS num 
  FROM 
    ORDERS 
  GROUP BY 
    agent_code, 
    cust_code
) 
SELECT 
  agent_code, 
  count(agent_code) AS count, 
  AVG(total_amnt) AS AVG, 
  SUM(total_amnt) AS SUM 
FROM 
  CTE_AGENT_CUSTOMER 
GROUP BY 
  agent_code

使用递归 SQL 时需要 cte。

SQL 中的递归 cte

SQL 中的递归类似于任何其他语言中的递归。你把一个更大的问题分成一个更小的问题,继续解决这个更小的问题,直到你达到终止条件。如果您不提供终止条件,它会将您的 SQL 命令发送到一个无限循环中。

下面是两个可以用递归解决的常*问题。

前 N 个数字

你的任务是使用递归打印一个从 1 到 20 的表格。下面是递归代码:

WITH NUMBER_CTE AS (
  SELECT 
    1 AS num -- Starting Table
  UNION 
    -- Combine Starting Table with Table from Below Query
  SELECT 
    num + 1 as num -- Update Rule
  FROM 
    NUMBER_CTE -- CTE calling itself, ie recursion
  WHERE 
    num < 20 -- Terminating Condition
    ) 
SELECT 
  * 
from 
  NUMBER_CTE -- Displaying the recursive CTE

分别考虑UNION操作符的第一个和第二个查询。

SELECT 
  1 AS num -- Starting Table

上面是一个简单的查询,返回一个名为num的列,其中包含值1

SELECT 
  num + 1 as num -- Update Rule
FROM 
  NUMBER_CTE -- CTE calling itself, ie recursion
WHERE 
  num < 20 -- Terminating Condition

只要原始值小于20,上面的查询就会将列num的值递增 1。

在第一次运行中,第一个子查询的结果将是:

num
------
1
------

第二次查询的结果将是:

num
------
2
------

UNION操作符将合并两个表,并将您的 CTE 更新到下表:

num
------
1
------
2
------

在第二个查询中,由于您从您的 CTE 中进行选择,这两个查询以及UNION操作符将被再次执行。第一个查询将再次返回:

num
------
1
------

第二个查询将使用上一次运行的 CTE,并将每行递增 1,返回以下内容:

num
------
2
------
3
------

UNION操作符再次组合来自两个查询的表。更新后的 CTE 将是:

num
------
1
------
2
------
3
------

这个过程将一直进行,直到该列包含一个值为20的行。在这种情况下,不会满足WHEN条件,您将停止递归过程。

阶乘

现在尝试一个 SQL 命令,创建一个包含阶乘值的表。试求5的阶乘。

WITH FACTORIAL AS (
  SELECT 
    5 AS NUM, 
    1 AS PRODUCT -- Starting Table
  UNION 
    -- Combine Starting Table with Table from Below Query
  SELECT 
    NUM - 1 AS NUM, 
    PRODUCT * NUM AS PRODUCT -- Update Rule
  FROM 
    FACTORIAL -- CTE calling itself, i.e recursion
  WHERE 
    NUM > 1 -- Terminating Condition
    ) 
SELECT 
  * 
FROM 
  FACTORIAL

初始表应该有两列——一列存储当前乘数,一列存储当前乘积。乘积将是1,而第一个乘数将是5

第一个查询的结果将是:

num    product------ ---------
5        1
------ ---------

第二个查询的结果将是:

num        product
--------   --------------
5-1 = 4     5*1 = 5
--------   --------------

新的 CTE 将是:

num    product
------ ---------
5         1
------ ---------
4         5
------ ---------

在下一次运行中,第一次查询的结果将是相同的:

num    product
------ ---------
5        1
------ ---------

第二次查询的结果将根据上次运行的 CTE 进行计算:

num         product
---------   ---------
5 - 1 = 4   1 * 5 = 5
---------   ---------
4 - 1 = 3   5 * 4 = 20
---------   ---------

UNION操作符将合并两个表。更新后的 CTE 将是:

num     product
------  ---------
5         1
------  ---------
4         5
------  ---------
3        20
------  ---------

这个过程将继续下去,直到你达到终止条件。

递归 cte 的一般语法

基于上述问题,您可以看到 SQL 中递归 cte 的一般语法:

WITH CTE AS
(
    -- Starting Table
    UNION -- Combine Starting Table with Table from Below Query
    -- Updated Table with Update conditions if any
    FROM CTE-- CTE calling itself, i.e recursion
    -- Terminating Condition
)SELECT * FROM CTE

终止条件不一定必须是WHERE条件;也可以是JOIN条件。您将在以下情况下查看使用JOIN的终止条件。

添加示例数据

递归通常用于寻找公司中的层次结构,或者在处理家谱时使用。您需要在数据库中创建一个新表。第一列是代理的代码,第二列是他们经理的代理代码。如果代理没有经理,第二列中的值将是NULL。下面是您将添加到数据库中的层次结构:

作者截图

你可以找到在这个报告中添加数据的脚本。

任务一

假设您获得了一个代理的 ID,并被要求返回一个包含代理的经理、跳过经理、跳过经理等的表。,一路到顶。下面是完成此任务的命令:

with HIERARCHY_CTE AS (
  SELECT 
    h1.agent_code, 
    h1.manager_code 
  from 
    HIERARCHY h1 
  WHERE 
    h1.agent_code == 'A006' 
  UNION 
  SELECT 
    h2.agent_code, 
    h2.manager_code 
  FROM 
    HIERARCHY h2 
    JOIN HIERARCHY_CTE ON h2.AGENT_CODE = HIERARCHY_CTE.manager_code
) 
SELECT 
  * 
FROM 
  HIERARCHY_CTE

同样,单独考虑每个查询。

SELECT 
  h1.agent_code, 
  h1.manager_code 
FROM 
  HIERARCHY h1 
WHERE 
  h1.agent_code == 'A006'

上面的查询返回代理的代码和他们经理的代理代码。以下是输出:

agent_code   manager_code
---------   ------------
A006         A005

现在看看第二个查询:

SELECT 
  h2.agent_code, 
  h2.manager_code 
FROM 
  HIERARCHY h2 
  JOIN HIERARCHY_CTE ON h2.AGENT_CODE = HIERARCHY_CTE.manager_code

这将在HIERARCHY表和您创建的 CTE 之间执行一个JOIN。它试图找到来自HIERARCHYagent_code与 CTE 的manager_code相匹配的行。然后它返回代理的代码和他们经理的代码,或者是A006的经理和A006的跳过经理。

以下是输出:

agent_code  manager_code
---------   ------------
A005        A003

该联合返回下表:

agent_code  manager_code
---------   ------------
A006        A005
---------   ------------
A005        A003

在第二次运行时,第一个查询将再次返回:

agent_code   manager_code
---------    ------------
A006           A005

然而,第二个查询也将包括A003的经理。以下是输出:

agent_code manager_code
--------- ------------
A005        A003
--------- ------------
A003        A001

UNION运算符组合这些表。您更新后的 CTE 将是:

agent_code    manager_code
---------    ------------
A006           A005
---------    ------------
A005           A003
---------    ------------
A003           A001

A001没有经理。在下一次运行中,您将遇到终止条件。

任务二

在此任务中,您将为每个代理分配一个级别。没有老板的代理是一级,向他们汇报的代理是二级,以此类推。下面是返回该表的命令:

with HIERARCHY_CTE AS (
  SELECT 
    h1.agent_code, 
    h1.manager_code, 
    1 AS level 
  from 
    HIERARCHY h1 
  WHERE 
    h1.manager_code IS NULL 
  UNION 
  SELECT 
    h2.agent_code, 
    h2.manager_code, 
    level + 1 AS level 
  from 
    HIERARCHY h2 
    JOIN HIERARCHY_CTE on h2.manager_code == HIERARCHY_CTE.agent_code
) 
SELECT 
  * 
FROM 
  HIERARCHY_CTE

这类似于上一个任务中的命令。最主要的区别是,你是从顶层代理开始,而不是底层。

累计总数

累计也称为累积和。考虑数据库中的ORDERS表。它有称为ord_amountord_date的列。尝试计算ord_date列中每个日期记录的累计和。下面是命令:

SELECT 
  ord_date, 
  SUM(ord_amount) OVER (
    ORDER BY 
      ord_date
  ) AS Running_Total 
FROM 
  ORDERS

OVER命令告诉 SQL,您想要查找整个数据集上ord_amount列的累积和。ORDER BY子句中的列用于按日期对结果进行排序。

CASE WHEN 语句

CASE WHENSQL 中的语句类似于其他语言中的 if-else 或 switch-case 语句。以下是CASE WHEN语句的一般语法:

CASE
WHEN CONDITION THEN RESULT
WHEN CONDITION THEN RESULT
WHEN CONDITION THEN RESULT
ELSE RESULT
END Column_Name

如果没有一个条件返回 true,则返回ELSE中的结果。

CUSTOMER表有一个名为grade的列,包含来自0-4的值。您的任务是创建一个名为grade_letter的新列,它将1映射到A,将2映射到B,并将所有其他内容映射到F。您可以使用CASE WHEN语句来完成这项任务。下面是命令:

SELECT 
  *, 
  CASE WHEN grade == 1 THEN 'A' WHEN grade == 2 THEN 'B' ELSE 'F' END grade_letter 
FROM 
  CUSTOMER

结论

本指南为您提供了一些使用更高级 SQL 主题的实践经验。实现这些工具将帮助您从数据中获得更多的洞察力,以便您可以用 SQL 编写更好的查询。

如果您正在使用 SQL,您可能会对 CloudQuery 感兴趣。基于 SQL 的开源云资产清单集成了主要的云提供商,包括 Azure、AWS 和 GCP。您可以使用它从当前和历史的角度审计和评估您的云资产。

关于 CloudQuery 能为你做什么的更多信息,查看它的文档

This article was originally posted on 
https://www.realpythonproject.com/advanced-sql-going-beyond-the-basics/Connect with me on LinkedIn: 
https://www.linkedin.com/in/rahulbanerj

面向初学者的高级 SQL 技术

原文:https://towardsdatascience.com/advanced-sql-techniques-for-beginners-211851a28488

从 1 到 10,你的数据仓库技能有多好?

Github

杰斯·贝利在 Unsplash 上拍摄的照片

从 1 到 10,你的数据仓库技能有多好?想上 7/10 以上?这篇文章是给你的。

想尽快准备好数据分析师的工作面试吗?这篇博文详细解释了一些复杂的数据仓库 SQL 技术。我将使用 BigQuery 标准 SQL 方言来写下关于这个主题的一些想法。

1.增量表和合并

以正确的方式有效地更新表是很重要的。这的确很重要。理想的情况是当你有主键、唯一整数和自动增量的事务时。这种情况下的表更新很简单:

在现代数据仓库中处理非规范化的星型模式数据集时,情况并非总是如此。您可能需要用 SQL 创建会话和/或用一部分数据增量更新数据集。transaction_id可能不存在,但你将不得不处理数据模型,其中唯一键依赖于已知的最新transaction_id(或时间戳)。例如,last_online数据集中的user_id依赖于最近已知的连接时间戳。在这种情况下,您可能希望update现有用户和insert新用户。

合并和增量更新

您可以使用合并或者将操作分成两个动作。一个用新记录更新现有记录,另一个插入不存在的全新记录(左连接情况)。

MERGE 是关系数据库中普遍使用的语句。Google BigQuery MERGE 命令是数据操作语言(DML)语句之一。它通常用于在一条语句中自动执行三个主要功能。这些功能是更新、插入和删除。

  • 当两个或多个数据匹配时,可以使用 UPDATE 或 DELETE 子句。
  • 当两个或多个数据不同且不匹配时,可以使用 INSERT 子句。
  • 当给定的数据与源数据不匹配时,也可以使用 UPDATE 或 DELETE 子句。

这意味着 Google BigQuery MERGE 命令允许您通过更新、插入和删除 Google BigQuery 表中的数据来合并 Google BigQuery 数据。

考虑这个 SQL:

在这里,我们只用一个操作就完成了更新和插入。

2.计数单词

执行 UNNEST()并检查您需要的单词是否在您需要的列表中,这在许多情况下可能是有用的,例如数据仓库情感分析:

3.在 SELECT 语句外使用 IF()语句

这给了我们一个机会来节省一些代码行,并且在代码方面更有说服力。通常情况下,您会希望将它放入一个子查询中,并在 where 子句中添加一个过滤器,但是您可以改为执行 this :

另一个例子是而不是如何与分区的表一起使用。不要这样。这是一个不好的例子,因为由于匹配的表后缀可能是动态确定的(基于你的表中的某些东西),你将被收取全表扫描的费用。

也可以在HAVING子句和AGGREGATE函数中使用。

4.使用分组依据汇总

ROLLUP 函数用于在多个级别执行聚合。当您必须处理尺寸图时,这很有用。

作者图片

以下查询根据在 where 子句中指定的交易类型(is_gift)返回每天的信用消费总额,并且还显示每天的消费总额以及所有可用日期的消费总额。

5.将表格转换成 JSON

假设您需要将表转换成 JSON 对象,其中每条记录都是嵌套数组的一个元素。这就是to_json_string()功能变得有用的地方:

然后你可以在任何地方使用它:日期、营销漏斗、指数、直方图等。

6.使用分区依据

给定user_iddatetotal_cost列。对于每个日期,如何在保留所有行的同时显示每个客户的总收入值?您可以这样实现:

7.移动*均数

通常,BI 开发人员的任务是将移动*均值添加到报告和他们奇妙的仪表板中。这可能是 7 日、14 日、30 日/月甚至是年的 MA 线图。那么我们该怎么做呢?

8.日期数组

当你使用用户保持或者想要检查一些数据集是否缺少值,例如日期时,变得非常方便。BigQuery 有一个函数叫做GENERATE_DATE_ARRAY:

我之前在这里写过:

9.Row_number()

这有助于从数据中获取最新信息,如最新更新的记录等。或者甚至删除重复项:

10.NTILE()

另一个编号功能。如果你有一个手机应用程序,监控Login duration in seconds这样的事情真的很有用。例如,我将我的应用程序连接到 Firebase,当用户使用login时,我可以看到他们用了多长时间。

作者图片

该函数根据行排序将行划分到constant_integer_expression桶中,并返回分配给每一行的从 1 开始的桶号。存储桶中的行数最多相差 1。余数值(行数除以时段的余数)从时段 1 开始为每个时段分配一个。如果constant_integer_expression评估为空、0 或负,则提供错误。

在本文中,您可以找到如何使用 Firebase 和 Google Analytics 4 数据创建自定义用户活动和绩效仪表板的教程:

11.等级/密集 _ 等级

它们也被称为编号功能。我倾向于使用DENSE_RANK 作为默认排名函数,因为它不会跳过下一个可用的排名,而RANK会。它返回连续的等级值。您可以将它与一个将结果划分到不同存储桶的分区一起使用。如果每个分区中的行具有相同的值,它们将获得相同的等级。示例:

另一个关于产品价格的例子:

12.透视/取消透视

透视将行更改为列。这就是它的全部功能。Unpivot 做与相反的。最后,它在 BigQuery 中可用:

13.名值/姓值

这是另一个有用的函数,它有助于获得特定分区中每一行相对于第一个/最后一个值的增量。

14.将一个表转换成结构数组,并将它们传递给 UDF

当您需要将带有复杂逻辑的用户定义函数(UDF)应用于每一行或每一个表时,这非常有用。你总是可以把你的表看作一个 STRUCT 类型对象的数组,然后把它们传递给 UDF。看你的逻辑了。例如,我用它来计算购买过期时间:

以类似的方式,您可以创建不需要使用 UNION ALL 的表。例如,我用它来模拟单元测试的一些测试数据。这样你可以在你的编辑器中使用Alt + Shift + Down来快速完成。

15.使用跟随和无限跟随创建事件漏斗

营销渠道就是一个很好的例子。您的数据集可能包含连续重复的相同类型的事件,但理想情况下,您会希望将每个事件与下一个不同类型的事件链接起来。当你需要得到某个东西的列表时,例如事件、购买等,这可能是有用的。为了建立一个漏斗数据集。使用 PARTITION BY it 使您有机会将以下所有事件分组,而不管每个分区中有多少个事件。

16.正则表达式

如果您需要从非结构化数据中提取某些信息,例如汇率、自定义分组等,您可以使用它。

使用 regexp 处理货币汇率

考虑汇率数据的这个例子:

使用 regexp 处理应用程序版本

有时,您可能想使用regexp为您的应用获取主要发布修改版本,并创建自定义报告:

结论

SQL 是帮助操作数据的强大工具。希望这些来自数字营销的 SQL 用例对你有用。这确实是一项方便的技能,可以帮助你完成许多项目。这些 SQL 片段让我的生活变得更加轻松,我几乎每天都在工作中使用它们。此外,SQL 和现代数据仓库是数据科学的必备工具。其强大的方言功能允许轻松地建模和可视化数据。因为 SQL 是数据仓库和商业智能专业人员使用的语言,如果您想与他们共享数据,它是一个很好的选择。这是与市场上几乎所有数据仓库/湖解决方案进行通信的最常*方式。

推荐阅读:

[1]https://cloud . Google . com/big query/docs/reference/standard-SQL/DML-syntax # merge _ statement

[6]https://towards data science . com/how-to-compute-a-moving-average-in-big query-using-SQL-15 F3 fedd 7489

[11]https://cloud . Google . com/big query/docs/reference/standard-SQL/window-function-calls

[12]https://cloud . Google . com/big query/docs/reference/standard-SQL/query-syntax # unpivot _ operator

[14]https://cloud . Google . com/big query/docs/reference/standard-SQL/functions-and-operators # first _ value

最初发表于T5【https://mydataschool.com】

关于如何将 CSV 文件读入熊猫的高级技巧

原文:https://towardsdatascience.com/advanced-tips-on-how-to-read-csv-files-into-pandas-84ebb170f6e5

学* 5 个小技巧,让你远离痛苦。

Sam Dan TruongUnsplash 上拍摄的照片

您的旅程概述

  1. 设置舞台
  2. 以普通的方式导入 CSV 文件
  3. 第一个提示:仅导入选定的列
  4. 第二个提示:处理真值和假值
  5. 第三个技巧:偷看数据
  6. 第四个提示:设置索引列
  7. 第五个技巧:像专家一样处理缺失值
  8. 收尾

1 —搭建舞台

在从事数据科学和数据分析工作时,将数据加载到熊猫中是令人难以置信的常*。有许多不同的格式需要考虑,如 CSV 文件Excel 文件JSON 文件原始文本文件拼花文件等。

说到 CSV 文件,你很快就知道熊猫可以用方法pd.read_csv()轻松导入 CSV 文件。然而,鲜为人知的是可以传递给方法pd.read_csv()的可选参数数量惊人。这给了你很大的定制!如果你认为我夸张了,看看下面熊猫文档的截图:

截图来自https://pandas . pydata . org/docs/reference/API/pandas . read _ CSV . html

这是相当压倒性的,对不对?😧别担心,我会教你知道的最重要的 5 个

如果没有这些有用的可选参数,您将不得不做额外的预处理。这通常较慢,并且需要较高的计算成本。简而言之,这些可选参数中的一些可以节省大量时间,让你从枯燥的工作中解脱出来。

告别不必要的预处理,向导入 CSV 文件的高效、干净的代码问好。

先决条件:你应该已经安装了 Pandas,并且知道什么是 CSV 文件。除此之外,没有任何先决条件。我们走吧!

2-以普通的方式导入 CSV 文件

在您学*这些很酷的技巧之前,让我们确保您知道在 Pandas 中导入 CSV 文件的基本方法。假设您有一个名为employees.csv的 CSV 文件,其中包含以下信息:

Name,Age,Wage
Eirik,27,75000
John,33,85000
Janet,25,78000
Phil,23,66000

然后您可以用下面的代码片段将整个文件employees.csv导入到 Pandas 中:

import pandas as pdemployees = pd.read_csv("filepath_to_employees.csv")

你得到的数据帧employees包含以下信息:

熊猫数据帧从简单的 CSV 文件。

上面的代码是在 Pandas 库中使用函数read_csv()的最基本方法。导入整个 CSV 文件

如果 CSV 文件格式完美,没有丢失的值,并且您需要所有的列和行,这将非常有用。然而,实际上,对许多人来说,这些要求更像是白日梦,而不是现实。让我们看看如何使用可选参数来处理更复杂的情况🔥

3 —第一个提示:仅导入选定的列

通常,您只需要 CSV 文件中的一些列,而不是所有列。对此的一个解决方案是导入整个 CSV 文件,然后按如下方式过滤掉列:

employees = pd.read_csv("filepath_to_employees.csv")
employees = employees[["Name", "Wage"]]

数据框employees现在包含以下信息:

包含选定列的熊猫数据框架。

虽然这种方法确实有效,但在代码长度和性能方面效率都很低。您导入了整个Age列,但从未使用过它!

最好告诉函数read_csv()只导入您需要的列。您可以使用可选参数usecols来完成此操作,如下所示:

employees = pd.read_csv(
  "filepath_to_employees.csv", 
  usecols=["Name", "Wage"]
)

这产生了完全相同的结果。避免导入大量不需要的数据,避免编写 Pandas 代码来过滤掉无用的列。那是一石二鸟😄

参数usecols通常期望您要导入的列名列表。但是,您也可以传递一个(通常是匿名的)函数来确定一个列是否被选中。有关这方面的更多信息,请查看 Pandas 文档中的usecols可选参数。

第二个技巧:处理真值和假值

CSV 文件通常包含指示某事物是真还是假的值。问题是,这种迹象可以有各种各样的味道。要查看示例,请考虑具有以下额外列的 CSV 文件employees.csv:

Name,Age,Wage,Insurance
Eirik,27,75000,Yes
John,33,85000,No
Janet,25,78000,yes
Phil,23,66000,no

这个 CSV 文件中的真值有两个直接问题:

  • CSV 文件使用单词YesNo,而不是 Python 识别的关键字TrueFalse
  • Yes/yesNo/no既有小写也有大写。可能是 HR 员工手动输入的数据?无论如何,你都要考虑到这一点。

通过做一个简单的导入语句,熊猫不知道单词YesNo是什么意思:下面的代码

employees = pd.read_csv("filepath_to_employees.csv")

简单给出数据框架:

带有保险栏的数据框很难处理。

现在,根据Insurance列中的值过滤列非常麻烦。

您可以使用map()功能手动重命名Insurance列中的值。然而,如果你已经在博文中走到这一步,你就知道这不是办法。

最好的处理方式是在函数read_csv()中使用可选参数true_valuesfalse_values。两个参数都只需要一个单词列表,这些单词应该被翻译成 Python 关键字TrueFalse:

employees = pd.read_csv(
    "filepath_to_employees.csv", 
    true_values=["Yes", "yes"], 
    false_values=["No", "no"]
)

数据帧现在看起来如下:

带有保险栏的数据框易于操作。

5 —第三个技巧:查看数据

Unsplash 上由 Dmitry Ratushny 拍摄的照片

这是一个短的。如果您有一个巨大的 CSV 文件,但只想看一眼数据,那么加载整个文件是一个巨大的时间浪费。相反,您可以使用可选参数nrows来指定应该读入多少行 CSV 文件。

让我们考虑下面这个简单的 CSV 文件numbers.csv:

Numbers,Squares
1,1
2,4
3,9
4,16
5,25
6,36
7,49
8,64
9,81
10,100
.
.
.
1000000,1000000000000

这是一个包含 1.000.000 个数字的文件。我知道这很做作,但它是一个很好的例子。下面的代码将只导入 1.000 行:

numbers = pd.read_csv(
  "filepath_to_numbers.csv",
  nrows=1000
)

此代码仅挑选出前 1000 行,您将获得数据帧:

前 1000 行。

通常,选择这样的样本就足以探索数据。

注意:如果您正在导入的数据是以某种方式排序的(如时间序列),那么导入前 1000 行可能会使数据呈现出非常扭曲的画面。

在上面的例子中,您可能还想将索引列设置为 CSV 文件中的Numbers列。现在的数据框架有很多冗余信息。这是下一个提示!

6 —第四个技巧:设置索引列

考虑numbers数据帧

索引列和数字列本质上是相同的。

有时您希望将一个列(在本例中是Numbers列)设置为索引列。这在时间序列数据中经常发生,其中事件的时间是索引数据的一个很好的列。Pandas 将默认创建自己的索引列。但是,您可以通过使用可选参数index_col来决定自己的索引列,如下所示:

numbers = pd.read_csv(
  "filepath_to_numbers.csv",
  nrows=1000,
  index_col="Numbers"
)

使用此代码,您将获得以下数据帧:

Numbers 列现在是索引。

可选参数index_col通常需要一个与 CSV 文件中的列名相对应的字符串。然而,如果你传入一个字符串列表,那么你会得到一个 Pandas MultiIndex 👍

第五个技巧:像专家一样处理缺失值

熊猫功能read_csv()不傻。每当 CSV 文件中的条目具有值 NULLNaNn/a ,则read_csv()会将该值解释为缺失。在 read csv 文档中有一个 Pandas 将识别为缺失的值的完整列表。很聪明,对吧?

然而,有时 CSV 文件包含微妙格式的缺失值。让我们回头看看你在博文中提到的employees.csv文件:

Name,Age,Wage
Eirik,27,75000
John,33,85000
Janet,25,78000
Phil,23,66000

现在让我们假设一个叫“Sarah”的新员工即将开始工作。但是,她的新工资尚未被 HR 登记,因此在输入正确的金额之前,该工资将被设置为零:

Name,Age,Wage
Eirik,27,75000
John,33,85000
Janet,25,78000
Phil,23,66000
Sarah,25,0

显然,Sarah 的工资应该被认为是一个缺失值,因为它还没有被写入系统。然而,熊猫不会理解这一点,只会简单地把它当作莎拉是一个拿“经验”报酬的实*生😡

对此的一个解决方案是在数据导入后过滤掉工资为零的员工。但是,正如您现在所期望的,您可以在read_csv()函数中使用一个可选参数。如下使用可选参数na_values:

employees = pd.read_csv(
    "path_to_employees.csv",
    na_values=["0"]
)

现在,数据框架已经正确地将 Sarah 的工资识别为丢失:

莎拉的工资被正确地认定为失踪。

如果您想将更多的值标记为缺失,那么只需将它们提供给传递给na_values参数的列表。

警告:如果您的其他列中有一列的有效值为零,那么这种方法也会将它们标记为缺失。不太好。为了避免这种情况,你也可以传递一个字典给na_values。字典的键是有问题的列名(在您的例子中是“工资”),值是缺少的值(在您的例子中是“0”)。运行 Pandas 的info()方法来检查您没有引入错误的缺失值总是一个很好的明智检查。

8 —总结

Joshua Hoehne 在 Unsplash 上拍摄的照片

我已经向您展示了在 Pandas 中导入 CSV 文件的 5 个技巧。我希望你学到了一些新东西,并且能够在未来的项目中使用。如果你需要知道更多,那么看看熊猫文档。

喜欢我写的?查看我的其他帖子,了解更多 Python 内容:

如果你对数据科学、编程或任何介于两者之间的东西感兴趣,那么请随意在 LinkedIn 上加我,并向✋问好

使用 BERTopic 进行高级主题建模

原文:https://towardsdatascience.com/advanced-topic-modeling-with-bertopic-85fb8a90369e

我们如何组织世界上最难组织的数据?

阿什·埃德蒙兹在 Unsplash 上拍摄的照片。原文章发表在 pinecone.io

组织大量的非结构化文本数据是复杂的。它不是为机器理解而设计的,让人类处理如此大量的数据非常昂贵,而且非常慢。

幸运的是,隧道的尽头有光明。越来越多的这种非结构化文本变得可以被机器访问和理解。我们现在可以根据的含义 搜索文本,识别文本情感,提取实体,等等。

变形金刚是这一切的幕后推手。这些变压器(不幸的是)不是迈克尔·贝的汽车人和霸天虎,也(幸运的是)不是嗡嗡作响的电箱。我们的 NLP 变形金刚介于两者之间,它们还不是有意识的汽车人,但它们能够理解语言,这种理解方式直到几年前还只存在于科幻小说中。

具有类似人类语言理解能力的机器对于组织大量非结构化文本数据非常有帮助。在机器学*中,我们将这项任务称为主题建模,即将数据自动聚类到特定主题中。

BERTopic 利用这些(尚未感知的)transformer 模型的高级语言能力,并使用其他一些 ML magic,如 UMAP 和 HDBSCAN(稍后将详细介绍)来产生当今语言主题建模中最先进的技术之一。

文章视频版看这里

我们将深入 BERTopic [1]背后的细节,但在此之前,让我们看看如何使用它,并先看一眼它的组件。

首先,我们需要一个数据集。我们可以通过以下方式从 HuggingFace datasets 下载数据集:

数据集包含使用 Reddit API 从 /r/python 子编辑中提取的数据。用于这个(和所有其他例子)的代码可以在找到。

Reddit 线程内容可以在selftext特性中找到。有些是空的或短的,所以我们用:

我们使用BERTopic库执行主题建模。“基本”方法只需要几行代码。

model.fit_transform我们返回两个列表:

  • topics包含输入到其建模的主题(或集群)的一对一映射。
  • probs包含一个输入属于他们指定主题的概率列表。

然后,我们可以使用get_topic_info查看主题。

顶部的-1主题通常被认为是不相关的,它通常包含停用词,如。然而,我们通过vectorizer_model参数删除了停用词,因此它向我们显示了主题的【最一般】,如【Python】【code】【data】

该库有几个内置的可视化方法,如visualize_topicsvisualize_hierarchyvisualize_barchart

BERTopic 的visualize_hierarchy可视化让我们可以查看主题的“层次”。

这些代表了 BERTopic 库的表层,它有很好的文档,所以我们在这里不再赘述。相反,让我们试着理解一下BERTopic是如何工作的。

概观

BERTopic [2]中使用的有四个关键部件,它们是:

  • 变压器嵌入模型
  • UMAP 降维
  • HDBSCAN 聚类
  • 使用 c-TF-IDF 的聚类标记

我们已经在这几行 BERTopic 代码中完成了所有这些工作;一切都被抽象化了。但是,我们可以通过了解每个组件的要点来优化流程。本节将在没有 BERTopic 的情况下完成每个组件,并在最后返回 BERTopic 之前了解它们是如何工作的。

变压器嵌入

BERTopic 支持几个库,用于将我们的文本编码成密集的矢量嵌入。如果我们构建低质量的嵌入,我们在其他步骤中所做的任何事情都无法帮助我们,所以从一个支持的库中选择一个合适的嵌入模型非常重要,这包括:

  • 句子变形金刚
  • 天资
  • 空间
  • 根西姆
  • 使用(从 TF Hub)

其中,语句转换器库提供了最广泛的高性能语句嵌入模型库。在 HuggingFace Hub 上搜索“句子变形金刚”就能找到。

在 HuggingFace Hub 上搜索“句子变形金刚”,可以找到官方句子变形金刚模型。

这个搜索的第一个结果是sentence-transformers/all-MiniLM-L6-v2,这是一个流行的高性能模型,它创建了 384 维句子嵌入。

为了初始化模型并编码我们的 Reddit 主题数据,我们首先pip install sentence-transformers然后编写:

在这里,我们对文本进行了成批的16编码。每个批次都被添加到embeds数组中。一旦我们拥有了embeds中所有的句子嵌入,我们就准备好进入下一步了。

降维

在构建我们的嵌入之后,BERTopic 将它们压缩到一个低维空间中。这意味着我们的 384 维向量转化为二维/三维向量。

我们可以这样做,因为 384 维是很多的 T21,我们不太可能真的需要那么多维来表示我们的文本。相反,我们试图将这些信息压缩成二维或三维。

我们这样做是为了更有效地执行下面的 HDBSCAN 集群步骤。用 384 个维度执行聚类步骤会非常慢[5]。

另一个好处是我们可以可视化我们的数据;这在评估我们的数据是否可以聚集时非常有用。可视化也有助于调整降维参数。

为了帮助我们理解降维,我们将从世界的 3D 表示开始。你可以在这里找到这部分的代码。

来自[jamescalam/world-cities-geo](https://huggingface.co/datasets/jamescalam/world-cities-geo)数据集的点的 3D 散点图。互动视觉可以在这里找到

我们可以对这些数据应用许多降维技术;两个最受欢迎的选择是 PCA 和 t-SNE。

我们的 2D 世界减少了使用五氯苯甲醚。

PCA 通过保持更大的距离(使用均方误差)来工作。结果是数据的全局结构通常被保留[6]。我们可以看到上面的行为,因为每个大陆都与其相邻的大陆组合在一起。当我们在数据集中有容易区分的聚类时,这可能是好的,但对于更细微的数据,这种方法表现不佳,因为局部结构很重要。

2D 地球减少使用 t-SNE。

t-SNE 则相反;它保留了局部结构而不是全局结构。这种局部的焦点来自于 t-SNE 建立一个图表,连接所有最近的点。这些局部结构可以间接地暗示整体结构,但它们没有被强烈地捕捉到。

PCA 侧重于保持 相异 而 t-SNE 侧重于保持 相似

幸运的是,我们可以使用一种不太为人所知的技术来捕捉这两者的最佳之处,这种技术叫做Un formManifoldAapproximation 和Pproduction(UMAP)。

我们可以使用使用pip install umap-learn安装的 UMAP 库在 Python 中应用 UMAP。要使用默认的 UMAP 参数映射到 3D 或 2D 空间,我们只需编写:

UMAP 算法可以使用几个参数进行微调。尽管如此,仅用n_neighbors参数就可以实现最简单和最有效的调优。

对于每个数据点,UMAP 搜索其他点并识别第 k 个最近的邻居[3]。它是由n_neighbors参数控制的 k

kn_neighbors在这里是同义词。当我们增加n_neighbors时,UMAP 构建的图表可以考虑更远的点,更好地代表全球结构。

在我们有许多点(高密度区域)的地方,我们的点和它的第 k 个最近邻点之间的距离通常较小。在点数较少的低密度区域,距离会大得多。

使用不同区域中第 k 个最近邻居之间的距离间接测量密度。

UMAP 将试图保持到第 k 个最近点的距离,这就是 UMAP 在转移到一个更低维度时试图保持的距离。

通过增加n_neighbors,我们可以保留更多的全局结构,而更低的n_neighbors可以更好地保留局部结构。

更高的n_neighbors ( k )意味着我们保留了更大的距离,从而保留了更多的全局结构。

与 PCA 或 t-SNE 等其他降维技术相比,找到一个好的n_neighbours值可以让我们相对较好地保留局部和全局结构。

将其应用到我们的 3D 地球,我们可以看到邻国仍然是邻居。同时大陆摆放正确(南北倒置),岛屿与大陆分离。我们甚至还有“西欧”的伊比利亚半岛。

UMAP 还原的地球。

UMAP 保留了 PCA 没有保留的可识别特征和比 SNE 霸王龙更好的全局结构。这是 UMAP 利益所在的一个很好的例子。

如果我们已经标记了数据,通过将标签传递给target参数,UMAP 也可以用作监督降维方法。使用这种有监督的方法有可能产生更有意义的结构。

记住所有这些,让我们将 UMAP 应用于我们的 Reddit 主题数据。使用3 - 5中的n_neighbors似乎效果最好。我们可以添加min_dist=0.05来允许 UMAP 将点放得更近(默认值是1.0);这帮助我们将三个相似的主题从 r/Pythonr/LanguageTechnologyr/pytorch 中分离出来。

Reddit 主题使用 UMAP 将数据简化到 3D 空间。

随着我们的数据减少到一个低维空间,主题很容易视觉识别,我们在一个很好的位置上移动到集群。

HDBSCAN 聚类

我们已经使用现有的特征为我们的聚类着色,可视化了 UMAP 缩减的数据。它看起来很漂亮,但是我们通常不执行主题建模来标记已经标记的数据。如果我们假设我们没有现有的标签,我们的 UMAP 视觉将如下所示:

UMAP 减少了城市数据,我们可以区分许多集群/大洲,但没有标签着色就困难得多。

现在让我们看看如何使用 HDBSCAN 对(现在的)低维向量进行聚类。

聚类方法可以分为*面或分层的质心或基于密度的技术【5】。每一种都有自己的优点和缺点。

扁*化或层次化仅仅关注聚类方法中是否存在层次。例如,我们可以(理想地)将我们的图层次结构视为从大陆到国家再到城市。这些方法允许我们查看一个给定的层次结构,并尝试沿着树识别一个逻辑“切割”。

分层技术从一个大的集群开始,将这个集群分成越来越小的部分,并试图在层次结构中找到理想的集群数量。

另一种分裂是基于质心或基于密度的聚类。即基于接近质心的聚类或基于点密度的聚类。基于质心的聚类非常适合于【球形】聚类,而基于密度的聚类可以处理更不规则的形状识别异常值。

基于质心的聚类(左)与基于密度的聚类(右)。

HDBSCAN 是一种基于密度的分层方法。这意味着我们可以受益于分层数据更容易的调整和可视化,处理不规则的聚类形状,识别异常值。

当我们第一次将 HDBSCAN 聚类应用于我们的数据时,我们将返回由下面的浓缩树图中的红色圆圈标识的多个微小聚类。

随着算法通过增加λ值进行扫描,浓缩树图显示了离群点的减少和聚类的分裂。

HDBSCAN 根据不同 lambda 值下的大小和持久性选择最终聚类。树中最粗、最持久的“分支”被认为是最稳定的,因此是聚类的最佳候选。

这些聚类不是很有用,因为默认创建一个聚类所需的最小点数仅仅是5。给定我们的~3K 点数据集,我们的目标是产生~4 个子旋涡星团,这是很小的。幸运的是,我们可以使用min_cluster_size参数增加这个阈值。

好些了,但还不够。我们可以尝试将min_cluster_size减少到60,以将三个集群拉到绿色区块下方。

不幸的是,这仍然拉进绿色块,甚至允许太小的簇(如左边)。另一个选择是保留min_cluster_size=80,但增加min_samples=40,以允许更多稀疏的核心点。

现在我们有四个集群,我们可以使用clusterer.labels_中的数据来可视化它们。

HDBSCAN 对 reddit 主题进行聚类,准确识别不同的子 Reddit 聚类。稀疏的蓝点是异常值,并且不被识别为属于任何聚类。

一些异常值用蓝色标记,其中一些有意义(固定的每日讨论线程),其他没有意义。然而,总的来说,这些集群是非常准确的。有了这些,我们就可以试着识别这些集群的意义。

基于 c-TF-IDF 的主题抽取

BERTopic 的最后一步是为每个集群提取主题。为此,BERTopic 使用了 TF-IDF 的修改版本,称为 c-TF-IDF。

TF-IDF 是一种流行的技术,用于识别给定一个术语或一组术语的最相关的【文档】。c-TF-IDF 通过在一个集群中找到所有“文档”中最相关的术语来扭转这一局面。

c-TF-IDF 从每个类(集群)中寻找最相关的术语来创建主题。

在我们的 Reddit 主题数据集中,我们已经能够识别非常独特的集群。然而,我们仍然需要确定这些集群谈论什么。我们首先预处理selftext来创建令牌。

c-TF-IDF 的一部分要求计算类别 c 中术语 t 的频率。为此,我们需要查看哪些令牌属于每个类。我们首先将集群/类标签添加到data

现在创建特定于类的令牌列表。

我们可以计算每个类的频率(TF)。

请注意,这可能需要一些时间;我们的 TF 过程将可读性放在任何效率概念之上。一旦完成,我们就可以计算Iv 反转 D 文档 F 频率(IDF ),它告诉我们一个术语有多常*。罕*术语比常*术语具有更高的相关性(并将输出更高的 IDF 分数)。

tf_idf,我们有一个vocab大小的每个职业的 TF-IDF 分数列表。我们可以使用 Numpy 的argpartition函数来检索包含每个类的最大 TF-IDF 分数的索引位置。

现在我们将这些索引位置映射回vocab中的原始单词。

回到 BERTopic

我们已经讨论了相当多的内容,但是我们能把我们所学的应用到 BERTopic 库吗?

幸运的是,我们只需要几行代码。和以前一样,我们初始化我们的自定义嵌入、UMAP 和 HDBSCAN 组件。

您可能会注意到,我们已经将prediction_data=True作为一个新参数添加到了HDBSCAN中。我们需要这样做,以避免在将我们的自定义 HDBSCAN 步骤与 BERTopic 集成时出现 AttributeError 。添加gen_min_span_tree为 HDBSCAN 增加了另一个步骤,可以改善生成的集群。

我们还必须初始化一个vectorizer_model来处理 c-TF-IDF 步骤中的停用词移除。我们将使用 NLTK 中的停用词列表,但是添加了一些看起来会影响结果的标记。

我们现在准备将所有这些传递给一个BERTopic实例,并处理我们的 Reddit 主题数据。

我们可以用model.visualize_barchart()来想象新的主题

我们的最终主题是使用 BERTopic 库和经过调整的 UMAP 和 HDBSCAN 参数生成的。

我们可以看到主题与r/投资r/pytorchr/LanguageTechnologyr/Python 完美契合。

Transformers、UMAP、HDBSCAN 和 c-TF-IDF 显然是功能强大的组件,在处理非结构化文本数据时有着巨大的应用。BERTopic 已经抽象了这个堆栈的大部分复杂性,允许我们只用几行代码就可以应用这些技术。

虽然 BERTopic 可能很简单,但您已经看到它可以深入到各个组件中。通过对这些组件的高度理解,我们可以极大地提高我们的主题建模性能。

我们已经在这里介绍了一些要点,但是在本文中,我们实际上只是触及了主题建模的皮毛。BERTopic 和每个组件的内容比我们希望在一篇文章中涵盖的要多得多。

所以,去应用你在这里学到的东西吧,记住,尽管这里展示了 BERTopic 令人难以置信的性能,它还可以做更多的事情。

资源

🔗所有笔记本脚本

[1] M. Grootendorst, BERTopic Repo ,GitHub

[2] M. Grootendorst, BERTopic:基于类的 TF-IDF 过程的神经主题建模 (2022)

[3] L .麦金尼斯,j .希利,j .梅尔维尔, UMAP:一致流形逼近与降维投影 (2018)

[4] L .麦金尼斯,谈 UMAP 降维 (2018),SciPy 2018

[5] J. Healy, HDBSCAN,基于快速密度的聚类,如何和为什么 (2018),PyData NYC 2018

[6] L .麦金尼斯,《一个骗子的降维指南》 (2018),PyData NYC 2018

UMAP 解说,AI 与 Letitia 的茶歇,YouTube

*除另有说明外,所有图片均出自作者之手

进阶教程:如何像绝对 Boss 一样掌握 Matplotlib

原文:https://towardsdatascience.com/advanced-tutorial-how-to-master-matplotlib-like-an-absolute-boss-aae2d4936734

前所未有地使用 Matplotlib

露丝·齐默曼在 Unsplash 上拍摄的照片

我曾经有一个原则…

当我还是一个初学数据可视化的人时,我曾经有一个原则——永远不要访问 Matplotlib 文档。

从没有好东西从那里出来。当我在它的页面上时,我的眼睛会处理英语单词,但是,不知何故,它们被解释进我的大脑,就像我在破译一门外语一样。然后我会偶然发现一些像这些的杰作,我会想,我甚至会使用同一个库吗?

即使您是一名经验丰富的程序员,我相信您在学* Maplotlib 时也面临过类似的挑战。这不是一个容易的图书馆。有如此多的类和如此多的方法来完成最简单的任务——完全混乱。

如果你在那个位置,或者想加强你的 Matplotlib 游戏,我有你需要的指南。我会告诉你如何深入 Matplotlib 丛林的根部,放一把火,然后乘着喷气背包飞出去了。你准备好了吗?开始吧!

https://ibexorigin.medium.com/membership

获得由强大的 AI-Alpha 信号选择和总结的最佳和最新的 ML 和 AI 论文:

https://alphasignal.ai/?referrer=Bex

艺术家创造了 Matplotlib

虽然优秀的程序员编写了 Matplotlib,但它由称为 Artists 的基类组成。

情节中每一个带圆圈注释的组件都被实现为一个单独的类,这个类从基础艺术家那里继承了。但是这种将所有事物表示为一个类的能力有它的优点和缺点。

一方面,它赋予了 Matplotlib 前所未有的灵活性。使用它们各自的类,您可以调整几乎任何绘图组件,直到您满意为止。通常,您有多个选项来完成相同的任务,使您能够在不同的界面之间切换。

也许,这是 Pythonistas 对 MPL 最不满意的地方。根据 Python 的禅,应该有一种,最好只有一种显而易*的方法来做某事。而 Matplotlib API 在任何你能想到的方面都违反了这个规则。

结果是新手很迷茫。他们不知道使用哪个类或函数来完成一个简单的任务。他们不理解文档,因为,坦白地说,它太难理解了。即使是有经验的开发人员也可能不知道这样的错误意味着什么:

很自然,您会感到沮丧,因为您不知道在哪里使用了 Lined2D 对象,也不知道它是从哪里来的。

如果你是这些人中的一员,我将向你展示我学到的一些技巧,这将使你成为一个专业的 Matplotlib 用户,并像阅读儿童睡前故事一样阅读文档。

创建您自己的统一工作流程

我们将从选择一种统一的方法来完成任务开始。做单个的方法有很多种,坚持只做一种风格并掌握它是必不可少的。

我用来创建和自定义图的工作流程如下:

  1. 用基本元素和低定制来创建剧情本身。
  2. 找出情节的弱点,记下你想改进的部分。
  3. 用相关的 Matplotlib 函数隔离那些弱组件。
  4. 使用 Matplotlib 的瑞士军刀对它们进行微调,直到您满意为止(稍后将详细介绍)。
  5. 保存或显示绘图。

我们将详细学*如何做每一步。我向你保证,这个框架几乎适用于你创建的任何类型的情节和你想要的定制。

形象地说…

让我们从学*如何使用图形创建情节开始。MPL 中的一个人物对象就是最高级别的艺术家,可以认为是你画一切的画布。

您可以使用figure功能创建一个没有绘制任何内容的图形。就其本身而言,图形什么也不做——记住,它是你用来绘图的空白白纸。

我们稍后将回到数字上来。

让我们扔斧子吧!

Photo byMathias p . r . RedingonPexels

当我们给图形添加轴时,乐趣就开始了。Axes类是一个在绘图中表示一组 x,y 坐标系的 artist:

向图形添加空白轴的功能是add_axes,但实际上,您从未使用过它。相反,通常使用subplots功能同时创建一个图形和一个或多个轴:

>>> fig, ax = plt.subplots()

作者图片

这将立即创建一个图形并附加一个轴(坐标系)。接下来,我们开始使用绘图方法在轴上绘制数据。

这些地块有barhistscatterboxplot等名称。让我们创建一个简单的散点图,并画几条线:

作者图片

我们已经可以看到这个情节需要几个文本标签。此外,我们不喜欢点和线的默认颜色。还有,数字本身有点小。

看到我们在这里做的了吗?我们首先创建了一个基础图,并确定了我们想要改进的组件。现在,我们需要弄清楚如何提取这些组件并定制它们。

分解图组件及其组件及其组件

由于我们一开始就创建了轴和图形,它们已经被隔离为对象(figax)。

现在,让我们暂时假设我们有图形,但没有坐标轴。我们如何从图中提取它?

每个 matplotlib 艺术家都有几个以get_*前缀开头的方法。如果我们调用fig上的dir函数,我们可以看到几个例子:

在列表中,我们看到一个名为get_axes的小函数,所以我们将使用它。

axes 的官方类名称是AxesSubplot,正如我们所*,列表上只有一个:

ax = axes_list[0]

我知道这些是基本概念,但是你应该从这里吸取的教训是,MPL 中的每个类都有这样的get_*函数,允许你检索组件类的不同部分。

Matplotlib 的瑞士军刀

照片由 卜锦昭 在 Pixabay 上

现在我们有了几个对象,是时候使用它们的参数来定制它们了。但是首先,我们要问——我的对象接受什么参数,它们取什么值?

这就是 Matplotlib 的瑞士军刀发挥作用的地方。这是函数plt.setp ( 设置参数),可通过 PyPlot API 访问。

因此,让我们看看 figure 对象接受哪些参数:

在没有参数的对象上调用函数会打印所有对象参数的文档。在参数列表中,我们看到了我们想要更改的参数,即图形大小。就是那个叫size_inches的:

将对象及其参数名作为字符串传递是打印出参数可能值的一种简化方式。现在,让我们最后改变图形大小:

该函数返回 None,表示操作成功。现在,我们再来看看这个情节:

>>> fig.get_figure()

作者图片

现在,该用斧子了:

我们希望更改轴标签、限制、标题和轴脊线颜色。如果我们不知道这些参数的当前值,我们就打电话给plt.getpsetp的朋友:

>>> plt.getp(ax, "xlim")(0.35, 3.65)

setp类似,getp返回参数的默认值或当前值。在对象上不带任何参数调用它将返回所有默认值。让我们改变我们想要的:

作者图片

但是线条和标记的颜色呢?我们也说过我们会调整轴线?它们是独立的类,所以我们需要把它们从坐标轴中提取出来。但在此之前,我们需要了解几个至关重要的概念。本节仅作为setpgetp功能的介绍。

容器和原语

为了从基础艺术家到丰富多彩的情节,组件需要通过许多 MPL 类的继承链。沿着这条链,两组类对于如何使用 Matplotlib 至关重要。这些组被称为容器原语

我们已经看到了容器的两个实例——图形和轴。这个图形包含了轴,而轴包含了几乎所有的东西。

图元是所有进入容器的图形或几何对象。你很少直接使用这些原语。它们是在您调用绘图函数时动态创建的。您可以在 Matplotlib 的patches模块下访问它们的所有名称:

如您所*,我们已经获得了创建直方图、散点图、箱线图和线图所需的一切。它们都可以使用补丁制作,如圆形、矩形、多边形和直线。

你可以从 docs 这里找到 的全貌。

从上面 Matplotlib 类的映射中,我们看到了我之前提到的小 Lind2D 。当我们使用plotscatter函数绘制散点图和线条时,它是一个绘制线条和标记的类。

现在,回到我们的情节——这里是我们到目前为止所做的步骤:

作者图片

让我们看看ax内的所有艺术家:

我们看到了我们的线条。我们还可以看到四个棘,它们是独立的类。X 轴和 Y 轴对象与第一个元素一起可*,这是我们以前没有*过的。

PathCollection代表一组点。因此,让我们提取它,并给点一些定制:

作者图片

我们增加了一点尺寸,给这些点加上红色的黑边,

类似地,我们可以调整脊柱:

作者图片

我推荐的最后一个技巧是将所有创建的图存储到一个变量中,以便您可以单独处理它们,而不必通过轴访问它们:

把所有东西放在一起

让我们把今天学到的所有杂乱的信息组织起来:

  1. 创建情节并标记要改进的部分。
  2. 提取单一成分。如果你不知道你在找什么,就在坐标轴或图形对象上调用dir。同样,get_*前缀函数在这种情况下也很有用。
  3. 拥有一个组件后,通过调用plt.getp查看其参数的默认值。
  4. 标记您需要的参数,并在每个参数上调用plt.setp来查看它们可能接受的值。
  5. 使用相同的函数设置您的自定义值。
  6. 重复 2–5,直到你得到你需要的完美的情节。

一旦你经历了这个工作流程几次,你就会对更高层次的功能更加适应。您将开始直接向函数调用传递参数,或者在创建轴时传递参数,而不是从轴和原语中提取每个组件。

但是setpgetpdir函数是您遇到未知 Matplotlib 类或函数时所需的一切。

此外,学*艺术家、补丁和容器/原语的概念可以帮助您最大程度地理解文档。这些是在文档中出现最多的术语。我强烈建议用你新获得的知识去浏览它们,以便学到更多。

摘要

数据可视化不是学*绘图库。它是创造力、理解观众以及以专业和信息丰富的方式提供*解的结合。

我希望这三种技能都来自你。我的部分是展示如何使用 Python 生态系统中最强大的绘图库之一来补充这些技能。我已经教了你一个强大的迭代过程,使你能够以智能和结构化的方式改进 Matplotlib 图。

https://ibexorigin.medium.com/membership https://ibexorigin.medium.com/subscribe

您可能会对这些热门话题感兴趣…

</10-sklearn-gems-buried-in-the-docs-waiting-to-be-found-ad95a8fabdfd> https://ibexorigin.medium.com/python-became-the-language-of-the-year-3-times-in-4-years-it-wont-be-this-year-e5c724758ef https://ibexorigin.medium.com/how-to-use-matplotlib-annotations-like-you-know-what-you-are-doing-da61e397cce3

用于文本数据分析的高级可视化

原文:https://towardsdatascience.com/advanced-visualisations-for-text-data-analysis-fc8add8796e2

探索 n-gram 单词云、和弦图和气泡图,以及它们在 Python 中的实现

图一。打包气泡图,作者图片

本文将介绍几个稍微高级一点的图形,用于 Python 中的文本数据可视化。更准确地说:

  • N 元词云:显示高阶 N 元词出现的频率
  • 弦图:显示几个实体之间的联系及其强度
  • 包装气泡图:词频视觉化展示

为了说明它们的应用和 python 编码,我使用了经典的 IMDb 50K 电影评论(数据许可在这里是)。数据的子集已经进行了预处理,清除了数字、停用词和特殊字符。

#1: N 元单词云

Python 的 wordcloud 库中的标准单词云显示 unigrams(单个单词,如“猫”、“桌子”或“花”)。我们将探索一个稍微高级一点的图表版本,它描绘了二元模型和三元模型(即两个和三个连续单词)的频率。

图二。Bigram 词云,图片作者

图 3。三元词云,作者图片

二元词云

首先,我们导入正面和负面电影评论的数据:

Collocation _ threshold = 2collocations =True 参数告诉 Python 在生成的 wordcloud 对象中显示二元模型:

我们使用 matplotlib 来显示图像。

照片由 Geri MisUnsplash 上拍摄

三元词云

使用generate _ from _ frequency(trigrams _ dict)生成三元模型和高阶 n 元模型(例如,4 元模型),其中三元模型 _dict 是 n 元模型及其频率的字典。

在我们的案例中:

图 4。含有三元模型及其频率的字典

下面是从三元模型及其消极和积极情绪样本的频率生成 wordcloud 对象的代码。

图 3 中的词云的生成类似于二元模型的图表。

#2:和弦图

弦图是一种显示实体间相互关系(流程或连接)的方法。创建图表需要一些网络理论的基础知识,这在 Erik Ma 的电子书 网络分析变得简单 中有很好的解释。

在图表中,数据围绕一个圆呈放射状排列。实体之间的关系通常绘制为,它们的大小与连接的重要性成正比(数据可视化目录,2022 )。

图 5。和弦图,图片由作者提供

在我们的数据中,我们感兴趣的是电影的质量,如“特效”或“最佳男配角”,是如何与 7 部受欢迎的电影及其评级(如“好电影”、“坏电影”、“浪费时间”)进行讨论的。弦图通过分析语料库中二元模型(三元模型)之间的关系,帮助我们更好地解释和呈现评论者的观点。

  • 节点 【所有 str】:质量、电影名称和口头评级
  • 边缘【int】:影评中的同现

我们将继续以下步骤:

  • 为图形网络准备数据
  • 创建网络图对象
  • 在弦图中可视化网络

1.数据准备

预处理的 IMDb 数据具有节点和边结构。我们看到,比如“烂片”bigram 在同一个评论中被提到了 40 倍的“特效”。

图 6。数据为文字网络,图片由作者提供

2。创建网络结构

NetworkX 是一个用于创建和研究复杂网络的 Python 包。此代码读取数据,创建网络结构,并绘制网络图:

3.准备一张和弦图

Nxviz 是一个 Python 库,用于构建 NetworkX 图形对象的 rational 网络可视化。这个例子使用nxviz==0.6.3.首先,我们计算每个节点的度(参考 Nxviz 文档)。接下来,我们将数据中的边形式化。

CircosPlot 是NX viz 中的一个和弦图实现。下面是创建图表的代码(图 5)。

电影评论的弦图可能表明,许多评论家对詹姆斯·邦德电影的评价很差,因为糟糕的表演,他们可能会将它与《星际穿越》相比较。《拯救大兵瑞恩》因为摄影排得好,《霍比特人》因为特效排得好。

#3:包装气泡图

一个包装的气泡图以一串圆圈显示数据。它的基本积木是( Tableau,2022 ):

  • 尺寸定义单个气泡
  • 尺寸代表单个圆圈的大小和颜色。

气泡的位置通常针对紧凑性进行了优化,使图形更好地呈现。在 IMDb 数据中,最常*的二元模型代表一个维度,它们的频率是图 7 中气泡图大小的度量。颜色是随机设置的。

图 7。二元模型及其频率的打包气泡图,图片由作者提供

用 Python 制作打包气泡图最简单的方法可能是使用 matplotlib 文档中指定的BubbleChart类中的函数。我们将使用这个类,不做任何修改。

数据被格式化了一点,这样我们可以更好地说明圆圈的大小。从 matplotlib 的调色板中选择颜色。下面是示例的样子:

接下来,我们调用带有 bubble_spacing 参数的BubbleChart类,该参数指定气泡之间的最小间距。

最后,图 7 中的气泡图显示了数据。

Pixabay 在像素上拍摄的照片

结论

本文建议使用三种更复杂的图表来绘制文本数据。以下是一些可能的应用:

N-gram 词云:

公告摘要

  • 美国总统对闯入国会大厦说了什么?
  • 随着时间的推移,中国国丨家丨主丨席的公开声明是如何发展的?

文章标题和摘要概要

  • 发表在特定主题文章中的关键词是什么(例如,区块链在经济学中的应用)?

弦图:

文字网络分析

  • 可视化多对多关系及其优势
  • 发现数据中的复杂结构(例如客户使用相同的电子邮件地址来获得特定的折扣)

包装气泡图:

数据讲故事

  • 有助于说明问题,介绍程式化的事实,并准备引人入胜的演示

我的 GitHub 上有 Jupyter 笔记本的完整代码。请随意在您的数据上使用它。

PS:你可以订阅我的 邮件列表 在我每次写新文章的时候得到通知。而如果你还不是中等会员,可以在这里 加入

参考

[1] Tableau 桌面和 Web 创作帮助。构建一个打包的气泡图。从https://help . tableau . com/current/pro/desktop/en-us/build examples _ bubbles . htm检索到 2022-5-7。

[2]数据可视化目录。和弦图。从https://datavizcatalogue.com/methods/chord_diagram.html取回 2022–5–7。

具有机器学*功能的高级垃圾分类

原文:https://towardsdatascience.com/advanced-waste-classification-with-machine-learning-6445bff1304f

变更数据

具有机器学*功能的高级垃圾分类

改进废物分类技术

照片由 Alfonso Navarro 在 Unsplash 上拍摄

介绍

如果我们作为一个社会不采取行动来防止这种情况发生,不可回收废物在世界各地垃圾填埋场的积累以及大多数材料生物降解所需的大量时间会在不久的将来以显著的方式影响我们的生活方式。此外,在人类面临的最臭名昭著的风险中,废物积累可以通过苍蝇、蚊子和更多昆虫等媒介加速疾病传播。此外,除了破坏自然栖息地的美丽、砍伐森林和为垃圾填埋场提供足够空间的地形占用之外,土壤和水也容易受到污染,因为有毒化学物质存在于处理不当的材料中。与此同时,污染会改变食物链,从而不可避免地给人类和全球自然生态系统带来更多疾病和健康问题。

在过去的 50 年里,废物堆积成为一个日益严重的问题,主要有三个原因。第一个是市场上缺乏可回收物品,尽管公司很长时间以来一直在开发更可持续和生态的产品。第二个原因是当今另一个最普遍的问题,称为人口过剩。必须为大量人口提供各种资源这一事实意味着在处理垃圾产生时会面临非常复杂的物流挑战,因此可回收产品的比例有所增加,但相比之下,这些产品最终会进入垃圾填埋场甚至海洋,影响成千上万海洋物种的生活。最后,第三个原因是我们的社会缺乏对气候变化等问题的参与。

为了以数据的形式显示废物堆积问题,有必要知道世界人口每年产生 70 至 90 亿吨废物,其中 70%被不当处理,最终被填埋,有污染自然环境的风险,并对人类健康造成新的威胁,如 海洋微塑料 。该数据指的是人类创造的用过的、不想要的和丢弃的物品的总量。但是,产生的废物总量与所谓的 【城市固体废物】是有区别的,后者仅包括城市中心或其影响区域产生的垃圾。关于剩余垃圾的数量,每年大约产生 20 亿吨的城市垃圾,其中大约 33%没有得到充分的管理。是指每人每天产生从 0.14.5 公斤的垃圾,*均0.7 公斤 。此外,预计到 2050 年,由于全球人口的快速增长以及工业发展和人类文明持续发展对自然资源的密集使用的需求,城市垃圾将增加到 3.4 亿吨。**

理想情况下,一个全面实施的 循环经济 模式本质上是一个解决积累问题的绝佳方案,除了气候变化,甚至是我们世界某些地方的供应危机。这是因为它的三个原则(消除浪费和污染,循环产品和材料,再生自然)导致了一种有效的管理自然资源的方式,而我们有时并没有正确地重视这些资源。然而,主要由于技术、工程和后勤方面的限制,以完整的方式执行这样一个复杂的计划并不容易。

环境保护中的机器学*

尽管有这些限制,一些新兴的最新技术正开始改变我们看待和面对这些问题的方式。如今最臭名昭著的一个是机器学*,它是人工智能的一个分支,使机器有可能学*特定而复杂的任务,如分类、预测、决策、内容生成等。,通过使用大量数据并结合受人类学*方式启发的高级学*算法。由于机器学*的可扩展性和性能,使用机器学*来自动化这些任务有时对人类非常有用。

就其与可持续性和循环经济实施的关系而言,机器学*具有自动化各种任务的潜力。从改善我们呼吸的空气质量的数据趋势预测,以及从收集的数据中寻找模式来测量全球变暖,识别自然环境中的废物,甚至对几种类型的垃圾材料进行分类,以提高垃圾处理厂的性能。因此,正确识别和区分垃圾中的可回收物品也是迈向可持续循环经济模式的重要一步。然而,机器学*现在出现在比我们想象的更多的与环境保护相关的过程中。例如,模型做出的正确的能源或产品需求预测可以避免自然资源的浪费。此外,足够先进的模型甚至可以通过化学结构发现新材料,提高日常产品的效率和可回收性。

目标

本文的目标是促进机器学*技术的发展和改进,专注于解决上述(废物堆积、全球变暖、污染等)等环境问题。)通过创建一个能够根据制造材料在九种不同类型的废物之间进行分类的模型,从而实现其 的可回收性。 此外,自其开源以来,它将接受专业人士和主题专家的实验。当改善机器学*领域中的模型的性能时,该实验是关键,以及在该过程中使用的数据收集和处理技术。

此外,直观地解释机器学*算法的内部功能以及它们在未来可能给人类带来的好处,可以提高社会对这些新指数技术的理解和信任。此外,专注于使用新的破坏性方法来尝试解决环境问题,可以提高我们所有人保护地球的意识,让位于在日常生活中可能实施的新的可持续*惯。

它是如何工作的?

因此,为了建立一个正确分类不同类型废物的分类器,我们需要一个名为 卷积神经网络 的模型架构,因为我们的数据集将主要由 标记为 的图像组成,这意味着每个图像都有一个相应的标签,指示模型必须提供的正确预测(废物类型)。同时,该模型在卷积模块之后还需要一个 全连接网络 来将其给出的任意响应转换为一组具有特定结构的值,这将允许我们确定该模型预测的类别。

使用 卷积网络 处理图像的目的在于其从具有位置、旋转和比例不变性的图像中提取某些模式或特征的能力。为了理解在检测图像中的特征时这些属性的力量,让我们考虑一个例子。

(图片作者)

例如,如果我们想检测手写数字 3 作为特征,我们可以使用一个完全连接的网络。尽管如此,它只会‘see’特定图像区域中的数字和旋转,当元素被放置在随机位置或旋转时会给出错误的预测。相反,具有卷积部分的模型可以独立于其属性有效地检测特征。

作者 GIF

如果你想知道这是如何做到的,这种架构的基本操作是 卷积 ,因此得名 卷积网络。在上面的动画中可以看到,一个深灰色的矩阵称为 内核 遍历所有输入图像像素(蓝色矩阵)将内核的每个像素值乘以输入图像的相应像素值。之后,它将所有结果值的总和按顺序放入特征映射矩阵中。为了保持特征图相对于输入图像的维度,您可以添加 填充、 ,这是图像周围的一行空值。此外,您可以更改 stride 等参数,它决定了内核在遍历图像时向左移动的 【步长】**

(图片作者)

机器学*模型可以修改内核的值来检测复杂的特征,如人脸、车轮等。例如,正如您在上面看到的,您可以使用卷积将眼睛检测器内核传递给图像,并通过查看输出特征图来了解眼睛的位置。要更详细地了解它是如何工作的,可以访问 这个资源。

(图片作者)

在进入完整的网络之前,我们先来看看神经网络的基础知识。这个数学模型通过模仿我们人类大脑的工作方式来学*一组数据中的模式和关系。神经网络最基本的组件是神经元,它获取 n 个 输入值,并计算其 加权和 (所有输入的和乘以相应的权重参数)。然后,它通过激活函数传递该值,以引入非线性,并输出该函数的结果。因此,组织在不同层的多个神经元的组合使网络能够获得“知识”为了理解所有的底层细节,你可以在下面的资源中了解更多关于神经网络的知识。

(图片由作者提供,灵感来自 Erik McleanUnsplash 上)

最后,让我们看看前面的所有元素是如何共同组成一个完整的 卷积模型 就像上面所表示的那样。首先,输入图像通过一系列卷积层,随后使用每层中具有不同值的多个核来提取复杂性不断增加的特征。然后,结合卷积图层并为了降低影像的维数,一些池图层使用特定变量(如*均值、最大值或最小元素)执行卷积,而不是传统的加权和。这些操作也有助于保存网络中的信息。

提取特征后, 展*全局池 层转换最后一个卷积层的输出,并馈送给一个 全连接 【密集】网络,该网络根据学*到的模式执行分类。整个网络的最后一层包含的神经元和我们要预测的类别一样多。利用soft max激活函数,该层可以为每个神经元分配一个概率,该概率表示特征类在输入图像中存在的程度。

履行

为了以编程方式构建卷积神经网络,我们将使用运行在 web *台Google Colab上的 Python 代码,它为训练这样的大型模型提供了一个快速、舒适和健壮的云环境。此外, Python 编程语言有各种各样的库,用于构建机器学*算法,使训练和评估变得更加容易。这样的库有 Tensorflow,Keras,Numpy,Matplotlib 等。

数据收集和处理

在构建、训练和评估我们的模型之前,我们必须收集一个带有标签的垃圾图像数据集。互联网上有许多资源,您可以下载数据集用于机器学*项目,不仅有图像数据集,还有基于数字的数据集,如交通、销售等。

在这个项目中,我们将通过以下来源从Github收集数据:

准备好数据后,让我们开始用所有的 Python 代码构建 Colab 笔记本 。但是,首先,我们需要导入我们将需要的库:

****import** tensorflow **as** tf
**import** numpy **as** np
**import** matplotlib.pyplot **as** plt
**import** random
**import** math
**import** os
**import** cv2 **as** cv
**from** sklearn.linear_model **import** LinearRegression
**from** sklearn.preprocessing **import** PolynomialFeatures, StandardScaler, LabelEncoder
**from** sklearn.model_selection **import** train_test_split**

之后,我们必须将数据分成两个数据集(训练和测试)。每一个都只在项目的相应阶段使用(模型的训练和评估)。该操作对于使模型能够从提供的数据归纳到用户将在生产中使用的任何输入非常关键。对于培训和测试,通常的拆分率分别为 70/30、80/20 和 90/10。

以下代码使用tensor flow库的KerasAPI,通过将所有图像调整为 256x256 的标准尺寸并将批处理大小设置为 128 来预处理位于文件夹中的数据集,这意味着在训练过程中,数据将以 128 个图像的块通过网络。

***DIR **=** "/content/WasteClassificationNeuralNetwork/WasteImagesDataset"train_dataset **=** tf**.**keras**.**preprocessing**.**image_dataset_from_directory(DIR, validation_split**=**0.1, subset**=**"training", seed**=**42, batch_size**=**128, smart_resize**=True**, image_size**=**(256, 256))test_dataset **=** tf**.**keras**.**preprocessing**.**image_dataset_from_directory(DIR, validation_split**=**0.1, subset**=**"validation", seed**=**42, batch_size**=**128, smart_resize**=True**, image_size**=**(256, 256))***

此外,我们可以将从训练数据集对象(本例中为 9 个类)中提取的类的数量存储在一个变量中,并使用TF . data . auto tune来优化训练和测试数据集对象的性能。**

**classes **=** train_dataset**.**class_names
numClasses **=** len(train_dataset**.**class_names)
print(classes)AUTOTUNE **=** tf**.**data**.**AUTOTUNE

train_dataset **=** train_dataset**.**prefetch(buffer_size**=**AUTOTUNE)
test_dataset **=** test_dataset**.**prefetch(buffer_size**=**AUTOTUNE)**

模型构建和培训

由于我们正在处理一个相对较大的数据集 (+5000 张图像),当在如此大量的数据上训练一个模型时,使用一种通用的技术是很方便的,这种技术被称为 【转移学*】 这是指用一个已经训练好的模型替换你的模型的卷积部分。因此,在训练之前,由于经过训练的卷积部分,您的模型将能够从输入图像中提取有用的特征。此外,它将只需要训练最后几个密集层,从而减少计算能力和时间。有很多经过训练的卷积模型可用,但最常*的包括在我们目前用于该项目的 Keras API 中。

**baseModel **=** tf**.**keras**.**applications**.**MobileNetV3Large(input_shape**=**(256, 256,3), weights**=**'imagenet', include_top**=False**, classes**=**numClasses)
**for** layers **in** baseModel**.**layers[:**-**6]:
  layers**.**trainable**=False**

last_output **=** baseModel**.**layers[**-**1]**.**output
x **=** tf**.**keras**.**layers**.**Dropout(0.45) (last_output)
x **=** tf**.**keras**.**layers**.**GlobalAveragePooling2D()(x)
x **=** tf**.**keras**.**layers**.**BatchNormalization() (x)
x **=** tf**.**keras**.**layers**.**Dense(256, activation **=** tf**.**keras**.**activations**.**elu, kernel_regularizer**=**tf**.**keras**.**regularizers**.**l1(0.045), activity_regularizer**=**tf**.**keras**.**regularizers**.**l1(0.045),  kernel_initializer**=**'he_normal')(x)
x **=** tf**.**keras**.**layers**.**Dropout(0.45) (x)
x **=** tf**.**keras**.**layers**.**Dense(numClasses, activation**=**'softmax')(x)

model **=** tf**.**keras**.**Model(inputs**=**baseModel**.**input,outputs**=**x)**

正如您在代码中看到的,该模型建立在mobilenetv 3 large预训练模型的基础上,没有其原始的最终密集层,而是由一个从全局*均池操作接收数据的 256 个神经元的隐藏层、一个用于固定内部的 批处理规范化 层所取代之后,最后一层包含由【num classes】变量确定的输出类一样多的神经元。注意,我们需要添加正则化 来防止过度拟合,导致缺乏泛化能力。**

除了迁移学*,有时解冻预训练卷积模型的最后几个卷积层也是合适的。这种做法被称为https://youtu.be/5T-iXNNiwIs微调,提高了模型的整体性能。这里只解冻最后六层*(可以训练)。*****

**model**.**compile(optimizer**=**tf**.**keras**.**optimizers**.**Adam(learning_rate**=**0.00125), loss**=**tf**.**keras**.**losses**.**SparseCategoricalCrossentropy(from_logits**=True**), metrics**=**['accuracy'])

epochs **=** 50
history **=** model**.**fit(train_dataset, validation_data**=**test_dataset, epochs**=**epochs)**

一旦建立了模型,我们通过分配用于优化所有网络参数的SparseCategoricalCrossentropy损失函数、 亚当 算法和精度度量来编译它。最后,使用fit()函数在 50 个时期(整个数据集通过网络的时间)内训练模型。

模型评估

所需的训练时间取决于硬件、模型复杂性和数据集大小。但在这种情况下,使用配备有GPU、Google Colab 环境,一个大约 5000 张图像大小的数据集和一个具有大约 4500000 个参数的模型,其中只有大约 150 万个是可训练的,完成训练过程需要大约 7 分钟。****

************

(图片由作者提供)****

完成训练后,我们可以使用Matplotlib库在图表中绘制各时期的损失和精度值,以检查模型在该过程中的表现。如左图所示,训练值和测试值(每个数据集一个)的精度在第一个时期以类似的方式增加,直到达到测试精度低于训练精度(蓝线)的点。这是过度拟合的指标;训练值和测试值之间的差异越大,模型的过度拟合程度就越高,可推广性就越差。尽管失去了泛化能力,但在这种情况下,从训练的 98.75%的准确度到测试的 96.45%,差异不超过 2%,这不会以显著的方式影响模型的结果。****

(作者图片)**

我们可以通过构建 混淆矩阵 并使用来自两个数据集的数据评估模型来观察最终结果。获得的精度达到 98%,但是之前提出的过拟合问题可以将这个值降低到 97% 甚至 96%。 然而,测试模型性能的最佳方式是将其部署到生产中,并使用大量的 【未知】 数据对其进行评估。

要对单个图像进行预测,这是该模型的主要用途,我们可以通过 Keras API 对输入图像进行预处理,将其转换为一组值,并使用predict()函数从模型中获取预测。

****path **=** "/content/img.jpg"

img **=** tf**.**keras**.**preprocessing**.**image**.**load_img(path, target_size**=**(256, 256))
img_array **=** tf**.**keras**.**preprocessing**.**image**.**img_to_array(img)
img_array **=** tf**.**expand_dims(img_array, 0) 

predictions **=** model**.**predict(img_array)****

照片由 Dstudio BcnUnsplash 拍摄

例如,这个塑料勺子的图像会得到以下结果:

****[1.1614963e-01 1.0170896e+00 3.3458400e-01 3.6209685e-01 9.5969460e+01
 5.7956848e-02 1.9298062e+00 8.9533217e-02 1.2331158e-01] 
 ['Aluminium', 'Carton', 'Glass', 'Organic Waste', 'Other Plastics', 'Paper and Cardboard', 'Plastic', 'Textiles', 'Wood']
Prediction:  Other Plastics 95.96946239471436%****

应用程序

看到了像tensor flow这样的现代图书馆为构建这样复杂的机器学*算法提供的设施,分析这种模型在处理环境威胁时的真正好处就很方便了。第一个是它的重量,仅占用 30MB 的磁盘空间,这要归功于我们在执行 迁移学***(MobileNetV3)时使用的移动优化卷积模型,这使得模型易于部署,从而鼓励用户利用它。此外,尽管在损失和精度曲线中观察到小的过拟合,但其在评估阶段的结果和泛化能力使其足够健壮,可以扩展到更大的数据集。**

但是,要构建一个庞大的数据集并随着时间的推移进行扩展,需要一个强大的基础设施来存储数据。此外,许多人的合作对于收集和人工解释数据更为必要。这就是为什么像joinus 4 the planet(一个连接并为人们提供解决环境问题机会的*台)这样的倡议如此关注合作,使社会能够改造世界并保护环境。此外,协作是提高机器学*和整体技术的基本要求之一。因此,如果我们想要一个*衡的大自然和一个没有污染或任何危险的世界,我们必须共同努力。**

资源

github repo:https://github . com/cardstani/waste classificationneuralnetwork

您可以在 本网站:【https://wasteclassificationwebsite.cardstdani.repl.co/】上测试部署的模型**

推进机器智能:为什么环境决定一切

原文:https://towardsdatascience.com/advancing-machine-intelligence-why-context-is-everything-4bde90fb2d79

图片来源:red pixelviaAdobe Stock

我们大多数人都听说过这样一句话,“形象就是一切。”但是当谈到把人工智能带到一个新的水*时,语境才是最重要的。

情境意识体现了人类学*中所有微妙的细微差别。正是“谁”、“哪里”、“何时”和“为什么”决定了人类的决策和行为。如果没有上下文,当前的基础模型注定会旋转它们的轮子,并最终打断对人工智能改善我们生活的期望的轨迹。

这篇博客将讨论上下文在 ML 中的重要性,以及后期绑定上下文如何提高机器启蒙的标准。

为什么背景很重要

背景深深植根于人类的学*中,以至于我们很容易忽视它在我们如何应对特定情况时所扮演的关键角色。为了说明这一点,考虑两个人之间的对话,对话以一个简单的问题开始:奶奶好吗?

在真实世界的对话中,这个简单的查询可以根据上下文因素(包括时间、环境、关系等)引发任意数量的潜在响应。:

图一。一个恰当的回答“奶奶好吗?”高度依赖于上下文。图片来源:英特尔实验室。

这个问题说明了人类的大脑如何跟踪和考虑大量的上下文信息,甚至是微妙的幽默,以返回相关的响应。这种流畅地适应各种微妙环境的能力远远超出了现代人工智能系统的能力。

为了理解机器学*中这种缺陷的意义,考虑基于强化学*(RL)的自主代理和机器人的发展。尽管基于 RL 的架构在模拟游戏环境中取得了宣传和成功,如 Dota 2星际争霸 2,但即使是纯粹的游戏环境,如 NetHack 也对当前的 RL 系统构成了巨大的障碍,因为赢得游戏所需的政策具有高度的条件性和复杂性。类似地,正如最近的许多作品中指出的,自主机器人在能够与以前看不*的物理环境互动之前还有很长的路要走,而不需要在部署之前模拟正确的环境类型,或者强化已学*的策略。

当前 ML 和上下文查询的处理

除了一些显著的例外,大多数 ML 模型包含非常有限的特定查询的上下文,主要依赖于模型被训练或微调的数据集所提供的通用上下文。这种模型也引起了对偏差的极大关注,这使得它们不太适合在许多商业、医疗保健和其他关键应用中使用。即使是在语音助手 AI 应用程序中使用的最先进的模型,如 D3ST ,也需要手动创建模式或本体的描述,其中可能包含模型识别上下文所需的意图和动作。虽然这涉及相对最低水*的手工制作,但这意味着每次更新任务的上下文时都需要明确的人工输入。

这并不是说机器学*模型的上下文感知没有重大发展。OpenAI 团队的著名大型语言模型 GPT-3 已经被用来生成与人类文章相媲美的完整文章 T2,这是一项至少需要跟踪本地上下文的任务。谷歌在 2022 年 4 月推出的路径语言模型 (PaLM)展示了更强大的能力,包括在适当的上下文中理解概念组合的能力,以回答复杂的查询。

图二。PaLM 能够成功地处理需要在同一概念的不同上下文之间跳转的查询。图片鸣谢:Google Research【13】CC BY 4.0 license

最近的许多进步都集中在基于检索的查询增强,其中对模型(查询)的输入通过从辅助数据库中自动检索相关数据来补充。这使得在问答和知识图推理等应用上取得了重大进展

即使在一些背景约束下,可实现的输出质量也有了如此大幅度的提高,这可能很容易让人认为这表明了现代人工智能系统中更普遍的背景意识。然而,这些模型仍然不能提供更复杂的应用所需要的环境,如制造业、医疗实践等。这样的应用程序通常需要一定的上下文灵活性——正如在之前的一篇博客中的适应性部分所讨论的。例如,相关上下文可能必须以时间信息为条件,如用户请求的紧急程度,或者交互的目标和敏感性。这种适应性将允许给定查询的适当上下文基于与人的通信的进展而发展。简单地说,模型必须避免妄下结论,直到获得所有相关的上下文信息。这种对原始查询的最终响应的谨慎定时的暂停可以被称为后期绑定上下文

值得一提的是,最近的神经网络模型确实具有实现某些后期绑定上下文的能力。例如,如果模型附加了像维基百科这样的辅助数据库,它可以用最新版本的维基数据来调整其响应,从而在对特定查询提供响应之前考虑某种程度的时间相关上下文。

高度重视上下文的一个领域是对话式人工智能,特别是多回合对话建模。然而,承认在提供话题意识、考虑隐含时间、先验知识和意向性方面存在关键挑战

大多数当前部署的人工智能技术的问题是,即使它们可以在特定情况下执行条件反射过程,随着时间的推移条件反射对许多应用程序来说仍然是一个挑战,因为它需要结合对手头任务的理解以及对之前发生的事件序列的记忆,这充当了条件反射先验。为了考虑一个更轻松、更隐喻的例子,人们可以回忆起加拿大侦探剧“默多克之谜”,它以其副歌“你有什么,乔治?”。这是侦探默多克不断用来询问治安官克雷布特里最新进展的短语,答案总是不同的,并且高度依赖于故事中先前发生的事件。

将上下文构建到机器学*中

那么,如何在机器学*中大规模地整合和利用后期绑定上下文呢?

一种方法是创建元知识的“选择掩码”或“覆盖层”,提供相关上下文信息的重叠层,基于特定用例有效地缩小搜索参数。例如,在对正确处方进行医学搜索的情况下,医生会考虑患者的诊断状况、其他共病、年龄、以前的不良反应和过敏史等,以将搜索空间限制在特定药物上。为了处理上下文的后期绑定方面,这种覆盖必须是动态的,以捕捉最近的信息、基于特定于案例的知识对范围的细化、对正在进行的交互的目标的理解等等。

图 3:正确的医疗决策需要大量针对患者的及时背景考虑。图片来源:英特尔实验室。

源属性是另一个关键的元知识维度,它作为一个选择掩码特别有用,可用于启用后期绑定上下文。这就是为什么一个模型会更相信一个特定的来源——比如《新英格兰医学杂志》对一个匿名的 Reddit 帖子。来源归属的另一个应用是选择一组正确的决策规则和约束条件,这些规则和约束条件应在给定的情况下应用,例如,当地司法管辖区的法律或特定州的交通规则。来源归属也是减少偏差的关键,因为它是在创建信息的来源的背景下考虑信息,而不是通过出现次数的统计来假设信息的正确性。

这篇博客没有触及一个非常重要的方面——人类或未来的人工智能系统如何选择相关的信息片段作为特定查询的上下文?为了找到上下文相关的数据片段,必须搜索的数据结构是什么?这种结构是如何学*的?在以后的文章中会有更多关于这些问题的内容。

避免断章取义

人工智能领域在整合条件作用、组合性和上下文方面取得了长足的进步。然而,机器智能的下一个级别将需要在合并动态理解和应用后期绑定上下文的多个方面的能力方面取得重大进展。当在高度感知、即时互动的人工智能范围内考虑时,上下文就是一切。

参考文献

  1. Bommasani,r .,Hudson,D. A .,Adeli,e .,Altman,r .,Arora,s .,von Arx,s .,… & Liang,P. (2021)。论基金会模式的机遇与风险arXiv 预印本 arXiv:2108.07258
  2. Berner,c .、Brockman,g .、Chan,b .、Cheung,v .、Dę biak,p .、Dennison,c .……、张,S. (2019)。大规模深度强化学*的 Dota 2。 arXiv 预印本 arXiv:1912.06680
  3. Vinyals,o .,Babuschkin,I .,Czarnecki,W. M .,Mathieu,m .,Dudzik,a .,Chung,j .,…,Silver,D. (2019)。星际争霸 2 中的特级大师级使用多智能体强化学*。 性质575 (7782),350–354。
  4. h . küttler,n . nard elli,a . Miller,r . raile anu,r . selva tici,m . Grefenstette,e .,& rocktschel,T. (2020 年)。net hack 学*环境。 神经信息处理系统的进展33 ,7671–7684。
  5. Kostrikov,I .,Nair,a .,& Levine,S. (2021 年)。采用隐式 q 学*的离线强化学*。arXiv 预印本 arXiv:2110.06169 。
  6. Ibarz,j .,Tan,j .,Finn,c .,Kalakrishnan,m .,Pastor,p .,和 Levine,S. (2021)。如何用深度强化学*训练你的机器人:我们已经学到的教训。 《国际机器人研究杂志》40(4–5),698–721。
  7. Loquercio,a .,Kaufmann,e .,Ranftl,r .,Müller,m .,Koltun,v .,和 Scaramuzza,D. (2021 年)。在野外学*高速飞行。 科学机器人6 (59),eabg5810。
  8. Yasunaga,m .,Ren,h .,Bosselut,a .,Liang,p .,,Leskovec,J. (2021)。Qa-gnn:使用语言模型和知识图进行推理,用于问题回答。 arXiv 预印本 arXiv:2104.06378
  9. Mehrabi、f . mor statter、n . sa xena、Lerman、k .和 a . Galstyan(2021 年)。关于机器学*中偏*和公*的调查。 ACM 计算调查(CSUR)54 (6),1–35。
  10. 赵,顾磊杰,曹,于,王,李,吴,(2022)。描述驱动的面向任务的对话建模。 arXiv 预印本 arXiv:2201.08904
  11. t .布朗、b .曼恩、n .赖德、Subbiah、m .卡普兰、J. D .、Dhariwal、p .…& amo dei,D. (2020 年)。语言模型是一次性学*者。 神经信息处理系统的进展33 ,1877–1901。
  12. 记者 G. S. (2020 年 9 月 11 日)。一个机器人写了整篇文章。你害怕了吗,人类?守护者。
  13. Chowdhery,a .、Narang,s .、Devlin,j .、Bosma,m .、Mishra,g .、Roberts,a .…& Fiedel,N. (2022)。Palm:用通路来扩展语言建模。 arXiv 预印本 arXiv:2204.02311
  14. Lewis,p .,Perez,e .,Piktus,a .,Petroni,f .,Karpukhin,v .,Goyal,n .,… & Kiela,D. (2020)。知识密集型自然语言处理任务的检索增强生成。 神经信息处理系统进展33 ,9459–9474。
  15. Borgeaud,s .,Mensch,a .,Hoffmann,j .,Cai,t .,Rutherford,e .,Millican,k .,… & Sifre,L. (2021)。通过从数万亿个标记中检索来改进语言模型。 arXiv 预印本 arXiv:2112.04426
  16. 歌手 g(2022 年 1 月 15 日)。 LM!=KM:语言模型无法满足下一代人工智能知识模型需求的五大原因。中等。
  17. 摩尔,A. W. (2022,4 月 14 日)。 对话 AI 的时刻现在是福布斯。
  18. 徐,杨,赵,洪,张,(2021 年 5 月)。话题感知的多回合对话建模。第三十五届 AAAI 人工智能大会(AAAI-21)
  19. 李玉英,李伟文,聂,等(2022)。对话式开放领域问答的动态图推理。 美国计算机学会信息系统汇刊(TOIS)40 (4),1–24。
  20. 高,陈,雷,魏,何,德,李,蔡,等(2021)。会话式推荐系统的进展与挑战:综述。 艾开2 ,100–126。
  21. 歌手 g(2022 b,5 月 9 日)。 对知识的理解和深入 —走向数据科学。中等。

使用 Dash 通过 Python 升级到专业仪表板

原文:https://towardsdatascience.com/advancing-to-professional-dashboard-with-python-using-dash-and-plotly-1e8e5aa4c668

增强初始框架代码的高级方法

我的 Dash web 应用程序的登录页面—作者图片

那么您已经遵循了推荐的文件夹结构,构建了一个简单的框架 dash 应用程序,或者甚至可能将它部署到了某个服务器上,那么现在呢?您添加了更多的组件,但是面临需要调试的错误,或者 web 应用程序不够“专业”。这篇文章包含了让 Dash 应用程序运行得更快,提高 web 应用程序的美观性,减少调试的痛苦,SEO,跟踪和一些额外的高级东西的技巧。本文的结构是这样的,随着我们的进展,它的复杂性增加了,但是不要担心,演示代码可以用来说明每一点。

目录

先决条件

了解 Dash 应用的基本知识。如果没有,Dash 官方文档中的 Dash 教程可以让你快速上手。

管理回拨效率

有没有注意到 web 应用程序在页面加载或切换选项卡时需要一些时间来渲染?Dash 的工作方式是,当一个组件出现在屏幕上时,该组件的所有相关回调都将被触发——即使输入没有被触发。如果屏幕上没有太多组件,这可能不是问题,但是当在没有正确初始化的变量上触发回调时,您将遇到可伸缩性问题甚至错误。

官方 Dash 文档建议引发PreventUpdate异常以防止更新输出,然而,这涉及到检查输入是否为None,这可能是也可能不是不同组件的情况。我采用的一个解决方案是初始化返回变量,只有当回调通过输入触发时才更新返回变量。下面显示了一个例子,

@app.callback(...)
def sample_function(trigger)
    reply = ""
    if dash.callback_context.triggered:
        reply = "Callback is triggered"
    return reply

这样,如果无意中触发了回调,它将跳过所有中间处理,从而节省页面加载或 tab 切换的时间。

更新 :您可以在@app.callback()装饰器中设置prevent_initial_call=True来防止回调级别的初始回调。这可以在高级回调仪表板文档中找到。

专业外观的 CSS 样式

在屏幕上添加更多组件时,您可能会注意到默认颜色使 web 应用程序看起来非常单调或空洞。一个建议是为你的网络应用选择一个颜色方案。我使用的一些网站是 colour-hexAdobe ,它们为获取预设调色板提供了一个很好的起点。

使用 CSS 样式可以帮助同时改变多个组件的样式,而不是手动改变颜色方案的字体和背景,只要它们属于同一个“组”。这可以通过使用 Dash 组件的className属性来完成。

app.layout = html.Div([
    html.Div(className="custom-div"),
    html.Div(className="custom-div"),
])

/assets文件夹的 CSS 文件中,为该类添加自定义样式

.custom-div {
    color: steelblue;
}

用 decorators 调试

编码时,错误是不可避免的,使用app.run_server(debug=True)可以帮助热重装,并在错误发生时显示回溯消息。但是,当您不知道触发了哪些回调,或者触发回调的顺序时,可能很难进行调试。

装饰器允许对现有函数进行扩展,而无需修改原始函数源代码

将 decorators 堆叠到回调函数中可以用来在回调被触发时添加打印语句。它实现起来很简单(每个回调只有一行代码),如果您想进入或退出调试模式,您可以很容易地打开和关闭它!

# Toggle this to enter or exit debug mode
debug_mode = True

def print_callback(debug_mode):
    def decorator(func):
        def wrapper(*args, **kwargs):
            if debug_mode:
                print(f"==== Function called: {func.__name__}")
                print(f"Triggered by {dash.callback_context.triggered[0]['prop_id']}")
            result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

# Using the decorator
@app.callback(...)
@print_callback(debug_mode)
def sample_function(trigger):
    pass

装饰函数添加的打印语句示例

具有客户端回调的多标签应用程序

客户端回调是直接在浏览器中运行的回调,而不是向 Dash 发出请求,当回调由于数据传输或回调链而导致大量开销时,客户端回调非常有用。一般来说,我不使用很多客户端回调,除了选项卡(来自 dash 核心组件),我希望不同的选项卡可以改变 web 应用程序的标题。这是一个非常小的改进,但是我发现与在不同的标签上只显示一个标题相比,它使 web 应用程序更加定制化和交互式。

app.layout = html.Div(
    html.Div(id="dummy-component"),
    dcc.Tabs(
        id="tabs-parent",
        value=None,
        children=[
            dcc.Tab(label="Tab 1", value="tab1"),
            dcc.Tab(label="Tab 2", value="tab2"),
        ],
    )
)

app.clientside_callback(
    """
    function(tab_value) {
        if (tab_value === 'tab1') {
            document.title = 'Tab One'
        } else if (tab_value === 'tab2') {
            document.title = 'Tab Two'
        }
    }
    """,
    Output("dummy-component", "children"),
    [Input("tabs-parent", "value")],
)

多页应用程序

使用多个选项卡的另一种方法是使用扩展,如www.example.com/extension,在多个页面上呈现 web 应用程序。为此,您需要为不同的页面准备好多个html.Div容器,并利用dcc.Location获取当前的 web 应用程序 URL。

app.layout = html.Div(
    [
        dcc.Location(id="url", refresh=False),
        html.Div(id="page-content"),
    ]
)

@app.callback(Output("page-content", "children"), Input("url", "pathname"))
@print_callback(print_function)
def display_page(pathname):
    if pathname == "/":
        return html.Div("Main application")
    elif pathname == "/extension":
        return html.Div("Extension application")

搜索引擎优化

你可以使用元标签来执行 SEO,一些重要的标签包括标题标签、元描述标签和社交媒体元标签。这些标签不仅能与搜索引擎交流,还能让你的网络应用程序的 URL 更易于共享!我的 web 应用程序就是一个例子,如下所示

https://kayjan.fly.dev

下面的代码示例展示了如何将 meta 标签添加到 Dash 应用程序中。请注意,必须为谷歌(以og:开头的标签)和 Twitter(以twitter:开头的标签)分别添加重复的标签。

meta_tags = [
    {
        "name": "author",
        "content": "Kay Jan WONG"
    },
    {
        "name": "description",
        "content": "Kay Jan's Side Project - Automate repetitive data analysis tasks and perform predictions and optimizations",
    },
    {
        "name": "viewport",
        "content": "width=device-width, initial-scale=1"
    },
    {
        "property": "og:type",
        "content": "website"
    },
    {
        "property": "og:title",
        "content": "Tools to make life easier"
    },
    {
        "property": "og:description",
        "content": "Automate repetitive data analysis tasks and perform predictions and optimizations",
    },
    {
        "property": "og:image",
        "content": "link-to-image.png"
    },
    {
        "property": "twitter:title",
        "content": "Tools to make life easier"
    },
    {
        "property": "twitter:description",
        "content": "Automate repetitive data analysis tasks and perform predictions and optimizations",
    },
    {
        "property": "twitter:image",
        "content": "link-to-image.png",
    },
]
app = dash.Dash(__name__, meta_tags=meta_tags)

使用谷歌分析进行跟踪

部署后,很自然地想要执行跟踪和查看网站流量。一种方法是将 Google Analytics 整合到 Dash 应用程序中。有一系列的安装步骤我不会在这里介绍,但是你可以按照谷歌文档中的开始使用分析的说明。之后,你应该会得到一个类似于<script async src="https://www.googletagmanager.com/gtag/js?id=XXX"></script>的谷歌标签脚本。

Dash 中使用的 HTML 组件是 pythonic 代码。为了合并原始的 HTML 脚本,我们可以改变应用程序的index_string组件。您可以直接复制下面的代码,并相应地填写您的 Google 标记脚本。

app.index_string = """
<!DOCTYPE html>
<html>
    <head>
    <!-- Global site tag (gtag.js) - Google Analytics -->
    <script async src="https://www.googletagmanager.com/gtag/js?id=XXX"></script>
    <script>
        window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}
        gtag('js', new Date());
        gtag('config', 'XXX');
    </script>
        {%metas%}
        <title>{%title%}</title>
        {%favicon%}
        {%css%}
    </head>
    <body>
        {%app_entry%}
        <footer>
            {%config%}
            {%scripts%}
            {%renderer%}
        </footer>
    </body>
</html>
"""

结论

诚然,我不是 Dash 方面的专家,也没有受过前端开发的专业训练;我只为我的工作和个人项目构建了一个 web 应用程序。分享的代码是我很好奇的东西,为了让它们工作,我经历了很多困难。希望这也能让你受益。

感谢您的阅读!如果你喜欢这篇文章,请随意分享。

相关链接

我的个人 Dash 应用:https://Kay Jan . fly . dev

Plotly Dash-你需要知道的一切:https://medium . datadriveninvestor . com/Plotly-Dash-你需要知道的一切-bc09a5e45395

嵌入式视觉系统的对抗鲁棒性

原文:https://towardsdatascience.com/adversarial-robustness-for-embedded-vision-systems-773ee518fbf0

什么是恶意攻击,如何保护您的嵌入式设备免受这些攻击

作者图片

快速介绍

由于嵌入式系统的相对健壮的深度神经网络(DNN)的选项非常有限,本文试图提供该领域的入门知识,并探索一些现成的框架。

什么是对抗强大的 DNN?

深度神经网络已经使机器学*和推理大众化。这有两个主要原因。首先,我们不需要从目标数据集中查找和设计要素,DNN 会自动完成这项工作。其次,预训练模型的可用性有助于我们快速创建特定于任务的、经过微调/转移的学*模型。

尽管 dnn 广受欢迎,但它有一个严重的弱点,这使得这些网络无法用于现实生活中的安全关键系统。尽管 DNN 模型被证明对随机噪声相当稳健,但它无法抵抗精心设计的对输入的对抗性扰动

在计算机视觉中,对抗性攻击通过像素的微小变化来改变输入图像,使得这些变化对于人类来说仍然是视觉上不可察觉的,但是 DNN 不能正确地推断图像。后果可能非常严重。自动驾驶车辆的交通标志识别模块可能会将左转解释为右转路标,并掉入沟渠中!光学字符识别器(OCR)可能会错误地读取数字,从而导致财务欺诈。

幸运的是,许多专心致志的研究人员正在努力创造出对抗稳健的 DNN 模型,这种模型不会轻易被对抗扰动所愚弄。

对抗鲁棒性对嵌入式视觉重要吗?

绝对。思科预测,到 2023 年,机器对机器(M2M)连接数量将达到 147 亿[8];来自 Linux 基金会的这份报告[9]预计到 2028 年边缘计算的功率足迹将达到 102 千兆瓦(MW),Statista 预测到 2030 年将有 77.02 亿个边缘支持的物联网设备[10]。许多边缘计算应用都是嵌入式视觉相关应用,通常部署在安全关键系统中。然而,对于嵌入式系统来说,对抗鲁棒性的选择并不多。我们正在积极研究这一领域,我将在这里提到我们最近的一项研究。

但是在深入研究嵌入式系统的对抗性健壮性之前,我将在下一节给出这个主题的简单背景。已经熟悉这个题目的读者可以跳到下一部分。

对抗性鲁棒性引物

对抗性鲁棒性是一个非常流行和快速发展的研究领域。在这个博客[1]中,你可以看到致力于这一领域的大量研究文章。

对敌对图像最大的担忧是几乎不可能发现图像被篡改。

列 1:原始图像,标准 CNN 推理,列 3:被攻击的图像,标准 CNN 推理列 2:原始图像,鲁棒 CNN 推理,列 4:被攻击的图像,鲁棒 CNN 推理(Sym)手写数字 8 取自MNIST【15】在知识共享署名-共享 3.0 许可下,由作者使用类可视化的图像集合

例如,上图中来自 MNIST 数据集【15】的 a 手写数字 8 被标准的卷积神经网络(CNN)推理误归类为数字 2 。你能看出第一栏和第三栏中的图像有什么显著的不同吗?我不能。

CNN 做了。对手做了一些微小的改变,这些改变对人眼来说并不重要,但它对 CNN 的决策过程造成了严重破坏。然而,当我们使用健壮的推理机制(由 Sym 表示)时,我们看到被攻击的图像也被正确分类(列 4)。

让我们从另一个角度想一想。第 3 栏的图片从任何角度看都是数字 2 吗?不幸的是,CNN 是这么认为的。这是一个更大的问题。对手可以调整任何图像,哄出一个有利于它的决定,以实现其恶意的目标。

事实上,这些对立的例子就是这样被发明出来的。正如 Ian Goodfellow 在本次演讲中所述(大约 7 分钟),他们在探索 CNN 运作如此之好的原因。在这个过程中,他们想对不同类别的图像进行小的改变,这样这些图像就变成了飞机类别的图像。虽然他们期望某种飞机特有的特征(比如说,机翼)能够在飞船图像中显现出来,但这种事情并没有发生。在对图像做了一些改变后,他们的 CNN 开始自信地推断出一张完全看起来像一艘的图像,作为一架飞机。

现在,有了基本的概述,让我快速总结一下开始对抗鲁棒性需要知道的要点:

  1. 对抗性攻击优化算法,用于找到 DNN 做出错误决策的示例输入。有趣的是,这样的例子一点也不难找到,相反,它们几乎存在于输入流形的任何地方。尽管标准的、基于经验风险最小化的训练方法在训练 DNN 模型时可能不包括这样的例子。
  2. 一个好的 对抗性攻击 快速找出最有效的对抗性例子。有效对抗图像在视觉上与原始图像相似(就距离度量而言),但迫使模型将其映射到不同于原始图像的决策边界。距离度量是曼哈顿距离(L1 范数)、欧几里德距离(L2 范数)或切比雪夫距离(L∞范数)。
  3. 如果对手的目标是迫使 DNN 将决策映射到任何错误的类,则称为 无目标 攻击。相反,在 有针对性的 攻击中,对手迫使 DNN 映射到对手期望的特定类别
  4. 扰动 以每像素的变化来度量,通常用ϵ.来表示例如,0.3 的ϵ将意味着干净示例(原始图像)的每个像素在相应的相反示例中经历 0.3 的最大变化
  5. 清晰图像和对抗图像测量的 DNN 的精度通常分别称为 清晰精度稳健精度
  6. 对手可以攻击 DNN 推论,而不需要访问模型、训练细节和对测试数据分布的有限估计。这个 威胁模型 叫做一个完整的 黑盒 设置【2】。这可以像在一个真实的物体上贴一个小的物理标签一样简单,DNN 正试图推断出这一点。在另一个极端,完整的 白盒 设置指的是一种攻击模型,其中的模型、训练细节,甚至防御机制都是对手已知的。这被认为是对抗性辩护的考验。在上述两种设定的中级下评估不同的攻击和防御。
  7. 对抗性防御 旨在挫败对抗性攻击。对抗鲁棒性可以通过经验防御(例如,使用对抗示例的对抗训练)或启发式防御(例如,预处理被攻击的图像以消除干扰)来实现。然而,这些方法经常通过实验结果得到验证,使用然后是攻击。没有理由为什么一个新的更强的对手不能在以后打破这些防御。这正是对抗性鲁棒性研究中正在发生的事情,通常被称为猫捉老鼠游戏

对抗性研究社区旨在解决最后一点中强调的这种追赶游戏。该领域目前的研究重点是开发 认证和可证明的防御 。这些防护修改模型操作,使得这些操作对于输入值的范围是可证明正确的,或者使用高斯噪声执行分类器的随机*滑,等等。

嵌入式视觉系统的对抗性鲁棒性?

到目前为止,对抗性研究团体并没有关注嵌入式系统的对抗性健壮性。这是完全正常的,因为这个领域本身仍在形成之中。

我们在卷积神经网络中看到了同样的趋势。AlexNet [12]在 2012 年赢得 ILSVRC 挑战赛[14]后,DeepCompression [11]花了四年时间才率先生成小型修剪模型。然而,在那个时期,没有办法完全利用这些修剪过的模型,因为没有既定的硬件支持来在 CNN 推断期间利用稀疏性。最近,这种支持正在发展,研究人员甚至在微控制器上运行 CNN。

嵌入式系统的对抗性防御必须在大小、运行时间内存CPU 周期能量消耗方面非常低的开销。这立即取消了最佳可用选项,即对抗性训练模型。这些型号巨大CIFAR-10 约 500 MB(此处*)。正如本文[3]中恰当解释的那样,与标准模型相比,对抗性训练的模型倾向于学*更复杂的决策区域。这种可证明的强大防御还没有扩展到现实生活中的网络。使用生成式对抗网络(GAN)或自动编码器来净化受攻击图像的启发式防御对于嵌入式设备来说太耗费资源了。

这使得基于简单启发式输入转换的防御成为资源有限设备的唯一选择。然而,正如开创性的著作[4–5]所示,所有这些防御都依赖于某种形式的梯度混淆,并且最终可以被强大的适应性攻击打破。这种防御可以带来一些好处的方式是使转变变得非常强大。这不能抵御强大的适应性攻击,但是破坏转换的时间将取决于对手可获得的计算资源。

其中一个成功的作品[6]使用了一系列简单的变换,例如降低颜色的位分辨率、JPEG 压缩、噪声注入等。它们一起防御[4]中介绍的反向传递可微逼近* (BPDA)攻击。遗憾的是,本文没有公开的实现可供尝试。*

另一个最近的工作[7]使用输入离散化在 DNN 推理之前净化对立的图像。在净化过程中,位于不受限制的实数域中的图像像素值被转换成一组受限的离散值。由于这些离散值是从大型干净的图像数据集中学*的,因此转换难以打破,并且替换移除了一些不利的扰动。

有人动手…

首先,让我们看一些示例攻击,以创建一些敌对的图像。

我们可以使用任何现有的库,例如 Foolbox对抗性攻击 pytorchART …,等等。

下面是一个用对抗性攻击-pytorch 使用 AutoAttack 的实现来攻击和创建对抗性例子的例子[13]:

*from torchattacks import *attack = AutoAttack(your_dnn_model, eps=8/255, n_classes=10, version='standard')for images, labels in your_testloader:
    attacked_images = attack(images, labels)*

这里是另一个用 Foolbox 使用投射梯度下降攻击[3]攻击和创造对抗性例子的例子:

*import foolboxattack = foolbox.attacks.PGD(your_dnn_model)for images, labels in your_testloader:
    attacked_images = attack(images, labels)*

这些被攻击的图像可用于通过 DNN 进行推断。

接下来,让我们尝试用 SymDNN 来防御攻击。使用这个库的第一步是从这个链接克隆或下载这个库。

下一步是安装 SymDNN 的依赖项。存储库的自述文件中描述了这一步骤和 python 可选虚拟环境设置。

接下来,我们需要为离散化设置一些默认参数。所提供的缺省值对于一些数据集和攻击来说工作良好。我们可以稍后调整这些,以进行推断健壮性-延迟-内存的权衡。

*# For similarity search
import faiss
import sys
sys.path.insert(1, './core')# function for purification of adversarial perturbation
from patchutils import symdnn_purify# Setup robustness-latency-memory tradeoff parameters, defaults are good enough, then call the purification function on attacked imagepurified_image = symdnn_purify(attacked_image, n_clusters, index, centroid_lut, patch_size, stride, channel_count)*

这些净化后的图像可用于使用 DNN 的进一步推断。这个净化功能在处理内存方面极其低开销,适合嵌入式系统。

SymDNN 存储库包含在几种攻击和不同威胁模型下对 CIFAR-10、ImageNet 和 MNIST 的许多攻击示例。

这是一个在 SymDNN 中使用 BPDA 攻击【4】实现攻击和创建对抗示例的示例,摘自此处:

*bpda_adversary16 = BPDAattack(your_dnn_model, None, None, epsilon=16/255, learning_rate=0.5, max_iterations=100)for images, labels in your_testloader:
    attacked_images = bpda_adversary16.generate(images, labels)*

**攻击强度迭代等。超参数在原始论文【4】中有解释,通常取决于应用场景。

结论

尽管对抗性鲁棒性是一个经过充分研究的领域,但我们认为,在它能够成功部署到现场之前,有几个点需要连接,特别是在边缘计算场景中。我们提出的 SymDNN 防御,不能够撤销所有攻击。然而,它可以很容易地用于使嵌入式视觉系统对一些敌对攻击具有鲁棒性。随着嵌入式人工智能(AI)在未来迅速发展,手头有东西来保护它们总比什么都没有好。

参考

[1] Nicholas Carlini,所有(arXiv)对抗性示例论文完整列表* (2019),https://Nicholas . Carlini . com/writing/2019/All-Adversarial-Example-Papers . html*

[2] Nicolas Papernot,Patrick McDaniel,Ian Goodfellow,Somesh Jha,Z. Berkay 切利克和 Ananthram Swami,针对机器学*的实际黑盒攻击* (2017),在 2017 年亚洲计算机与通信安全会议上*

[3] Aleksander Madry,Aleksandar Makelov,Ludwig Schmidt,Dimitris Tsipras,和 Adrian Vladu,T owards 深度学*模型抵抗对抗性攻击 (2018),在 2018 年 ICLR

[4] Anish Athalye,Nicholas Carlini 和 David A. Wagner,模糊的梯度给人一种错误的安全感:绕过对抗例子的防御* (2018)。在 2018 年的 ICML*

[5] Florian Tramèr,Nicholas Carlini,维兰德·布伦德尔和亚历山大·马德瑞,关于对抗性示例防御的适应性攻击* (2020)。在 NeurIPS 2020 中*

[6] Edward Raff,Jared Sylvester,Steven Forsyth 和 Mark McLean,随机变换的弹幕,用于对抗性的稳健防御* (2019),2019 年在 CVPR 举行*

[7] Swarnava Dey、Pallab Dasgupta 和 Partha P Chakrabarti, SymDNN:简单&嵌入式系统的有效对抗鲁棒性 (2022),CVPR 嵌入式视觉研讨会 2022

[8]思科、思科年度互联网报告(2018–2023)https://www.cisco.com/c/en/us/solutions/collateral/高管视角/年度互联网报告/白皮书-c11–741490 . html

Linux 基金会,State of The edge 2021(2021)https://stateofthedge . com/reports/State-of-The-edge-report-2021/

[10] Statista,2020 年至 2030 年全球物联网(iot)设备的数量,按市场划分* (2022 年),https://www . Statista . com/statistics/1259878/edge-enabled-IOT-device-market-world wide/, 2022 年*

[11]宋涵,,毛,威廉·戴利,深度压缩:通过剪枝、训练量化和霍夫曼编码压缩深度神经网络* (2016),2016*

[12] A. Krizhevsky、I. Sutskever 和 G. E. Hinton,使用深度卷积神经网络的 Imagenet 分类* (2012 年),载于 NeurIPS 2012 年*

[13] Francesco Croce 和 Matthias Hein,对各种无参数攻击集合的对抗性鲁棒性的可靠评估* (2020),ICML 2020*

[14] Olga Russakovsky、Jia Deng、苏浩、Jonathan Krause、Sanjeev Satheesh、Sean Ma、、Andrej Karpathy、Aditya Khosla、Michael Bernstein、Alexander C. Berg 和李菲菲。( =同等贡献) ImageNet 大规模视觉识别挑战赛。 IJCV, 2015*

[15] Y. LeCun、L. Bottou、Y. Bengio 和 P. Haffner。基于梯度的学*应用于文档识别。美国电气和电子工程师学会会议录,86(11):2278–2324,1998 年 11 月**

通过 AWS 机器学*专业的建议和提示

原文:https://towardsdatascience.com/advice-tips-for-passing-aws-machine-learning-specialty-102f7f5f99a0

关于 2021 年底通过 CLF-C01 和 MLS-C01 考试的思考和建议

绿色变色龙Unsplash 上的照片

2021 年下半年(又名。2020 年第 673 天),我参加并通过了 AWS 认证机器学*专业考试。我读了一堆关于这个主题的其他文章,所有这些都在我通过考试的道路上帮助和支持了我。完成后,我想为这个知识库做出贡献,所以,在真正的数据科学时尚中,我想我应该继续下去,开源我的经验和准备材料。

背景

每个人对待这些考试的方式都不一样,所以在我进入这篇文章之前,详细介绍一下我的背景和我从哪里开始准备考试可能会有所帮助。在我开始学*的时候,我已经从事数据科学大约 7 年了。我拥有应用统计学硕士学位,并在大学期间辅修了数学。在参加考试的时候,我在云计算方面的经验包括在 SageMaker 上培训和部署 XGBoost。尽管比我训练的基于树的算法更环保,我还是把目光放在了轻盈蓬松的云朵上,并开始行动。

考试时间表和准备时间长度

现在我们已经了解了初步的信息,让我们来看看我的考试之路是怎样的。

正如之前很多人建议的那样,我选择先从云从业者开始(亚当·德扬斯做了很好的工作,解释了为什么你会想这么做(从准备的角度和财务的角度)。9 月底报名了执业医师考试,劳动节周末后开始认真学*。一旦我开始钻研,我发现云从业者考试虽然范围很广,但并不是一个很难的考试——大约三周的时间足以掌握材料。

通过云从业者考试后,我休息了一个周末,才开始准备 11 月中旬的机器学*专业考试。这次考试需要我更多的注意力,我在十月初开始学*,给自己整整 6 周的时间准备。我全职工作,所以为了保持理智,偶尔看看外面的世界,我选择安排每周大约 2-3 个晚上的 2 小时学*时间,周末的学*时间更长。总而言之,我给了自己 3 周的时间参加云从业者考试,6 周的时间参加机器学*专业考试,我发现在全职工作的同时,这些时间足够彻底地覆盖材料。

我在学*期间采用的主要策略是浏览 Udemy 课程,然后用剩下的时间参加模拟考试,并复*原始资料寻找我错过的答案。实践考试有助于发现我的知识缺口,并帮助我为考试中的知识测试做准备(例如,区分类似的服务(如 Lex/transcriptor/Polly/understand)非常重要)。最后一点:我没有浏览白皮书(我个人更喜欢角落里有小涂鸦的粉红色纸张)或使用正式的 AWS 培训,尽管我看了一些 Emily Webber 和以前的 re:Invent 会议视频。

由于 MLS 考试更难,很少有人分享他们的考试经历,我将在这篇文章的剩余部分更具体地关注 MLS 考试(尽管我也会参考下面一些有助于通过 CPP 的文章和资源)。

考试经历

由于我是在疫情报名参加这两项考试的,所以我选择在家里参加 Pearson OnVue 考试,而不是去考试中心(我可能会因为 In-N-Out 的动物薯条而被 COVID,但不是 CPP)。很明显,如果没有 AWS 的突击队从我的窗口闯入,我不能透露考试的内容,但我会分享一些关于我考试经历的想法。

像许多其他有类似数学/统计背景的人一样,对我来说,考试最容易的部分是数据分析和建模部分。例子包括破译图表,解释混乱矩阵(名称完全检查出来),调整特定的算法,如随机森林,等等。就我个人而言,考试中涉及 AWS 服务的特定用例及配置的部分(确定特定 AWS 服务的适当参数、文件夹结构的特定顺序等)更难。由于 CPP,我能够很容易地识别 AWS 服务,但因为 MLS-C01 是一个专业水*的考试,它比我准备的更深入这些服务的实现。我最后花了整整 3 个小时,因为我已经标记了我不确定的问题,并在最后花时间回溯这些问题。在考试结束时,我没有被留在悬念中——测试*台带我完成了一项简短的调查,然后给出了我是否通过的即时反馈。我一定还在肾上腺素的刺激下,因为我在 10 个问题的调查中一路汗流浃背。

学*资料&资源

其他博客帖子和文章中有用的是每个作者认为最有用的材料和资源列表。我整理了自己的清单,以下是在整个过程中对我帮助最大的材料:

  • 首先,我真的很欣赏这个 Reddit 帖子。作者在考试前分享了一些关于他的实践考试结果的精彩分析,并详细介绍了他使用的资源。
  • 这些是我在 Udemy 上的课程—

强烈推荐 AWS 认证机器学*专业 2022 —动手!| Udemy

好,但不如上面的 AWS 机器学*认证考试|全指南| Udemy
亚马逊 AWS SageMaker,AI 与机器学*用 Python 课程| Udemy

Quizlet 。2021 年 8 月至 11 月间,Quizlet 取代 Instagram,成为我最好的朋友。在我的 Udemy 课程中,我一直使用 Quizlet 作为不熟悉的术语和信息的存储库,以及我犯了错误并想重新讨论的问题的存储库。以下是我的 Quizlet 牌和其他我认为有用的牌:

最后几条建议

回顾我的个人历程,这里有一些我会给过去的自己的建议:

  • 拥有更多 SageMaker 经验会使考试体验更容易
    考试创建者建议拥有至少两年使用 AWS ML/AI 服务和*台的经验。如果我等到考试的时候,多和 SageMaker 合作,我可能就不会这么纠结了
  • 考试不是关于准确性,而是关于知道的比曲线更多。你将会被那些过去答对的人评判,而不是整体的准确性。 本文解释评分标准 揭秘您的 AWS 认证考试成绩| AWS 培训与认证博客
    考试前的周末,我正在重考,*均准确率约为 70%,这让我感到不安,因为实践考试估计 75%的准确率是通过考试的基准
  • 将考试安排在一天中你最警觉的时候 我最初在下午 3 点到 5 点参加 CPP,我可以感觉到我的大脑在变慢,所以对于机器学*专业考试,我将考试安排在一天的早些时候(上午 11:30 到下午 2:30),感觉更加警觉
  • 考试前充分补充燃料有很多研究和营养专家都在谈论食物和我们大脑的表现之间的相关性。我从自己的亲身经历中知道,当我的身体处于禁食状态时,我的头脑往往会更清晰。所以我在考试前一周和考试当天限制卡路里。对我来说,我的大脑处于最佳状态,我在考试中经历了更少的精神迷雾。
  • 仔细阅读问题并练*放慢速度 有时我会快速阅读问题并错过关键细节,所以我使用了 Pearson *台上的笔记功能,并从问题中键入关键单词和短语,以放慢速度,专注于问题的重要细节
  • 使用问题标记功能 我在模拟考试和实际考试中使用了标记功能来区分难的和容易的问题,这样当我回去查看我的回答时,我可以跳过容易的问题
  • 在准备参加模拟考试之前兑换免费模拟考试券 在通过任何认证后,您可以兑换免费模拟考试券,但我没有意识到的是,模拟考试在您兑换后一个月到期,因此我的建议是在接近您计划参加的时间兑换,我错误地认为我可以无限制地参加计时考试
  • 家里的考试桌上可以有水 最后,皮尔森说,你可以在考试桌上喝一杯水,但不建议使用洗手间,所以我不得不坐了整整 3 个小时。另外,不要忘记把你的笔记本电脑插上电源,把你的手机放在旁边(但不要放在桌子上)

我尽了最大努力来记录我学*、准备和参加考试的经历——希望这对你的旅程有所帮助!我很乐意在 Twitter 上回答任何进一步的问题(或者在 LinkedIn 上找到我),并在考试的另一边与你联系!感谢您的阅读——祝您好运,希望在未来的 AWS 活动中*到您!

云从业者资源

AWS 认证云从业者考试培训【新】2022 | Udemy
【Quizlet 套牌】AWS 云从业者服务
【Quizlet 套牌】AWS CPP 竞猜题

在模拟原子和分子方面击败物理学之后,机器学*现在正在与之合作

原文:https://towardsdatascience.com/after-beating-physics-at-modeling-atoms-and-molecules-machine-learning-is-now-collaborating-with-6e4dab20ae5c

将两个世界的精华结合在一起

Unsplash 上由 Toa Heftiba 拍摄的照片

预测原子、分子和材料的结构、运动和反应性在现代科学中至关重要,因为它们与它们的性质和行为直接相关,因此与应用直接相关。传统上,在原子水*上研究物质一直使用基于物理学的方法,这些方法依赖于经典或量子力学的原理——取决于预期的细节水*和所提的问题。无论模拟的确切类型是什么,在这些方法中,目标总是试图尽可能准确地描述现实,并按照回答感兴趣的问题的要求,通过以模拟所研究系统的物理特性(包括其随时间和空间的演变)的方式来参数化这种现实。

例如,如果想要研究分子的 3D 结构如何随时间变化而不断裂或形成任何键,即简单地通过其连接性不变的原子的温度诱导振动,选择的技术是某种形式的原子分子动力学模拟。经过足够长的时间,原子的快速振动耦合成键长和键角变形,然后二面角旋转,最终更大的构象变化。在生物学中,这种模拟有大量的应用,但在实践中非常缺乏,因为对这种系统中所有可能的原子、键和相互作用进行完美的参数化非常困难,甚至是不可能的,还因为与用于积分运动方程的飞秒时间尺度相比,感兴趣的事件发生在非常长的时间尺度中,因此这些模拟今天几乎不能探索最快的事件。

在另一个更大的层面上,如果感兴趣的问题涉及例如蛋白质如何在膜旁边扩散,假设其形状不会随着时间的推移而发生很大变化,那么可以进行模拟,将多个原子一起建模为粗粒,即所谓的粗粒模型。粒度水*从每个珠子几个原子到每个珠子整个蛋白质;同样取决于所提的问题。但是,物理必须以某种方式描述,运动方程需要传播,因此许多问题是简单棘手的。

在尺寸谱的另一端,人们可能希望模拟一个分子或一片材料中所有电子或一组电子的分布和能量。这需要某种量子力学计算,它可以回答涉及键形成和断裂的问题,或者电子在特定情况下经历的跃迁。这些模拟甚至比原子模拟更难建立、参数化和运行,今天它们可以达到比经典模拟更小的规模和时间尺度。

正如你可能已经从前面的段落中建立了想法,基于物理学的模拟试图准确地描述现实是非常强大的,但也是非常有限的。因此,虽然原则上这些方法应该允许我们准确地预测任何分子或分子组的任何性质,但在实践中它们常常达不到要求。作为上述解释的总结,这主要是因为两个原因:(I)这些模拟依赖于我们需要知道的许多假设和近似,因为我们不能精确地模拟现实,以及(ii)它们通常受到可用计算能力的限制,使得即使现实可以被模拟到精确的细节,计算能力仍然是这样的限制,以至于在实践中相对于今天的模拟所能提供的几乎没有变化。

因此,在实践中,这些基于物理学的方法只对某些领域的某些问题非常有用,而它们完全难以准确捕捉其他领域的复杂性和微妙性。仅举一个与我的研究密切相关的例子,人们会期望模拟应该能够将延伸的蛋白质折叠成正确的 3D 结构。实际上,除了小蛋白质和使用非常复杂的机器来运行分子模拟,我们还远远没有做到这一点,正如我在这里描述的:

人工智能时代

近年来,越来越倾向于使用基于人工智能(AI)的方法来预测不同分辨率水*的分子属性,从原子中的电子到生物分子和散装材料。这些方法涉及使用机器学*算法,这些算法利用大量已知分子结构和属性的数据进行训练,然后使用他们从这种训练中所学到的知识来预测新分子和材料的结构和属性,甚至设计一些新的分子和材料。

与基于物理的方法不同,这些基于人工智能的方法不依赖于任何特定的假设或近似,例如原子及其相互作用的参数化来描述现实。相反,他们依靠大数据和现代机器学*算法的力量来进行准确的预测。

回到早期的例子,通过使用纯物理方法折叠蛋白质来预测蛋白质的结构,这是人工智能方法击败基于物理的方法的一个完美的例子。甚至在 AlphaFold 在 CASP14 中出现之前,最好的蛋白质结构预测程序就已经在使用 ML 方法来辅助它们的计算了。我特别讨论了如何在 CASP12 和 CASP13 中预测蛋白质氨基酸之间的接触,然后通过混合 ML 预测的接触和蛋白质的部分基于物理学的描述来折叠蛋白质。在这个时候,甚至更早,纯粹基于物理的方法在 CASP 排名中排名相当低。(要了解关于 CASP 和这些技术的更多信息,在这里查看我的文章)。

当然,基于人工智能的方法在分子结构预测中取得成功的一个显著例子是由 DeepMind 开发的 AlphaFold 系统,该系统专门用于预测(静态)蛋白质结构(我强调静态是因为这是人工智能现在开始协助物理学的另一个重要方面,我将在稍后讨论)。AlphaFold 2 的预测非常出色,推动了现代生物学的一场革命,并进一步发展了新的纯人工智能方法来预测其他蛋白质属性,现在还推出了基于人工智能/物理的混合方法,我将在下面介绍。

总体而言,基于人工智能的方法在分子结构预测中战胜基于物理的方法,凸显了机器学*和人工智能在化学、生物和材料科学领域的潜力。通过利用大量可用的数据,这些方法已经能够做出高度准确的预测,而这些预测在以前被认为是几十年内无法实现的,如果只采用传统的基于物理的方法。因此,基于人工智能的方法可能会在分子结构预测领域继续增长,并可能导致我们对化学和生物过程的理解取得重大进展。

基于物理的模型仍然需要,原因有很多

但是,尽管基于人工智能的分子研究方法及其引发的革命如此神奇,科学家仍然倾向于基于物理的模型还有许多原因。首先,人工智能方法很难解释,这意味着它们可以完美地工作,但仍然是黑箱,阻止任何对它们为什么表现如此好的真正理解。这不仅意味着缺乏基本的理解(比如,黑匣子知道哪些我们不知道的物理知识?)也是对系统的盲目信任,该系统可能会在用户没有注意到的情况下意外发生故障。

第二,对现实的真实再现,即使不完整,也意味着理解自然的相关力量和时空的属性实际上是如何共同作用,使我们的现实成为现实的。有了这样一个植根于物理学核心的基本理解,应该更容易将描述研究系统的数学模型转化为不同时间或略有不同的属性,有效地在人工智能方法所用的训练数据之外进行外推,并且仍然有一些合理的信心,即模拟将做出可靠的预测。例如,如果我们在另一个星球上发现了生命,它可能会在不同的条件下进化,因此它们的生物分子可能会完全不同……AlphaFold 对研究这些分子毫无用处,但一种据称基于物理学的原子模拟方法足够先进和快速,就像我们当前的 alpha fold 对地球生物学一样可靠和有用,将对研究另一个星球的生物学非常有用。

第三,即使在今天,也有很多物理、化学、生物、工程等问题。(很大程度上,他们的大多数问题,我会说)人工智能方法根本无法处理,因为没有足够的数据来训练他们!当相对于问题的复杂性而言,只有小数据集可用时,适当的、明确的物理模型可以比人工智能方法做得更多。

基于物理和基于人工智能的方法的结合

也许,有一天基于纯物理的方法将会破解这一切,并允许我们以完美的精度模拟一切(注意范围外:关于这一点,我推荐 J. L .博尔赫斯的 关于科学中的精确 )。但是现在,我们显然离解决主方程、基本定律、常数和简单的参数化还很远。

然而,随着基于人工智能的方法与更经典的模拟方法相结合,特别是通过帮助和促进最困难的计算,在不久的将来还是有希望的。通过结合两个世界的优点,科学现在开始快速发展,ML 工具填补了留下的空白,但分析模型和常规的数值方法和算法却有助于它们自己的发展。例如,我之前描述了人工智能预测如何帮助产生大量高质量的人工数据集,然后人类科学家可以通过一个最终导出分析模型和算法的过程将这些数据集放在一起——这是计算机如何帮助人类智力的一种令人惊讶的方式:

与物理学更相关的是,我还介绍了考虑物理约束的符号回归如何能够重新发现已知的物理学,并发现在物理学和工程学中使用的新方程:

在接下来的内容中,我将围绕 3 个主题/案例,展示几个结合了基于人工智能和基于物理的方法的研究和工具开发的具体例子。

案例 1:加速量子力学计算

马等人,2022 和柯克帕特里克等人科学 2021 正如我在一篇专门的博客文章中所讨论的那样,谷歌研究人员最近采用了人工智能方法和符号回归来大幅加快量子力学计算中涉及的一个特定计算步骤:

Deepmind 对量子计算中的类似问题提出了不同的解决方案,也是基于 ML 方法

Smith et al Chemical Science 2017 及后续作品 ML 被用来辅助基于物理的计算的另一种方式是替代或补充描述粒子之间相互作用的力场,主要是在经典模拟中。这种模拟通过将其他原子视为由数学描述连接的软球来描述分子,类似于模拟键的弹簧、沿二面角的扭曲、静电相互作用的电荷以及其他类似术语。这些方程加上它们需要的所有参数化构成了所谓的力场。给定空间中原子的配置及其连接性,并根据给定力场的方程和参数,计算机程序可以计算出所有原子上的合力,然后从中一遍又一遍地传播牛顿运动方程,产生一种原子位置如何随时间演变的电影-称为分子动力学轨迹。

但是如果可以用其他方法计算这些力呢?一种可能性是通过量子计算来计算它们,这种技术确实存在,并允许检查诸如键形成和断裂等事件,但对于传播更大规模的运动来说太慢了。

一些现代神经网络提供了量子计算方法的准确性和一些能力,在某种程度上适用于经典的分子动力学模拟。也许最先进的这类系统是 ANI,是阿纳金-我的缩写,源自美国佛罗里达大学和卡耐基梅隆大学的罗伊特伯格和伊萨耶夫小组开发的分子能量精确神经网络引擎;

https://pubs.rsc.org/en/content/articlelanding/2017/sc/c6sc05720a#:~:text=ANI is a new method,AEV) as a molecular representation

ANI 读入原子坐标和符号,并返回能量,从其沿三维空间的梯度,还可以获得作用在原子上的力。正如作者所展示的,一旦获得了力,这些力就有可能被用来优化分子的几何形状和进行其他类型的计算。潜在地,通过一些仍在研究和开发中的调整,这些力可以用来驱动分子动力学模拟,取代传统的力场。

ANI 作为一个深度神经网络,通过使用 DFT 类型的非常详细的量子力学计算,对成千上万个小有机分子产生的数据进行训练,每个小分子具有多种不同的构象和不同的变形。与使用变压器、注意力、扩散和其他最新元素的现代架构相比,神经网络本身相对简单。但它显然是高效和快速的:它可以以接近 DFT 的精度传递能量和力,但比实际的 DFT 计算快大约一百万倍。

为了读取原子,ANI 使用原子环境向量的修改版本,该版本是根据分子系统中原子的空间排列计算的。最初,ANI 在只包含 H、C、O 和 N 原子的分子上进行训练,然后扩展到包括 S、F 和 P ,它们与有机化学和生物学非常相关(特别是,覆盖了大约 90%的类药物分子)。

通过一系列案例研究,ANI 的开发人员表明,在比训练数据集中包含的分子系统大得多的分子系统上,与参考 DFT 计算相比,它在化学上是准确的,训练数据集中包含的分子系统相当小,代价是运行了数百万次 DFT 计算来产生所有训练数据。ANI 提供了 DFT 质量的作用于原子的能量和力,但速度快了大约一百万倍,允许一系列以前无法想象的应用。对于一些围绕分子结构的计算任务,ANI 有可能取代量子计算和经典力场。对于分子模拟,ANI 可以填补空白,例如模拟没有参数化的分子。

显然,ANI 的路线图是作为一个可转移的(即一般)力场,可用于以 DFT 精度模拟分子力学,但速度是简单的神经网络传播。一些 ANI 开发者也参与了分子动力学模拟的 AMBER 程序的发展,所以我们可以看到 ANI 在未来被整合到其中。

作为另一个具体的示例应用,我们使用 ANI 作为分子结构操纵 VR 工具的一个组件,以在交互式分子模拟中提供真实的物理特性,接近 DFT 水*,但足够快速地实时运行。你可以在这个短片中看到它的作用:

https://www.youtube.com/shorts/BKRmyvMXBRo

基于材料的高质量电子结构计算的大数据集训练的基于 ML 的力场是有吸引力的,因为它们结合了效率和准确性。作者强调了设计高质量训练数据集的重要性,并讨论了主动学*和迁移学*等策略以提高模型的准确性。他们也提供这些进展到分子和材料的应用的例子。

案例 2:用人工智能挖掘蛋白质构象

Degiacomi Structure 2019 和 Ramaswamy 等 Physical Review X 2021 如果说分子模拟一般比较难,那么蛋白质的分子模拟就特别具有挑战性。蛋白质是相当大的分子,具有相当大的灵活性和动态性,具有相当疏水的内部接触(类似于油滴中油分子之间的接触),但也在其表面与水相互作用。此外,它们的稳定性和结构还受到静电相互作用、芳香堆积、蛋白质原子之间以及与溶剂之间的氢键等的调节。也就是说,它们在化学和物理上非常复杂,尽管它们的成分表面上很简单。因此,模拟蛋白质如何折叠、扩散、相互作用、改变结构或反应是极其困难的。更重要的是,即使我们有一个完美的力场,实际感兴趣的事件通常在几十微秒到几毫秒甚至更长的时间尺度内,而当前原子级的详细模拟用传统的硬件和软件无法达到几微秒以上。

正如我们在上面看到的,基于 ML 的方法可能有助于显著加快这些模拟。在探索这一点的第一批作品中,有两篇由英国杜伦大学的 Degiacomi 小组撰写的论文。

首先,研究人员证明了在 MD 模拟产生的蛋白质结构上训练的神经网络可以用来生成新的,似乎合理的蛋白质构象。他们表明,这种方法可以用于蛋白质-蛋白质对接场景,其中考虑灵活性的能力有助于蛋白质结合时发生的广泛铰链运动-这在常规原子模拟中需要很长的计算时间。

**https://www.sciencedirect.com/science/article/pii/S0969212619301145

该网络在通过常规原子模拟产生的可选蛋白质构象的集合上进行训练,并在不用于训练的一组独立构象上进行测试。该网络由一个编码器组成,该编码器接收原子坐标,并将它们通过一系列神经元数量逐渐减少的隐藏层,以产生输入构象的低维表示。然后,该信号进入解码器,这是另一系列隐藏层,但这一次神经元的数量增加了,解码器将其扩展回输出,该输出应该类似于通过编码器的初始蛋白质结构。整个自动编码器最初被训练成编码-解码结构,使得输入和输出构象之间的差异最小化。但经过训练后,解码器可以用来从潜在空间内的任何坐标生成新的蛋白质结构。

在随后的工作中,同一个小组开发了一个卷积神经网络,它不仅学*蛋白质构象,还学*它们如何相互交换,这被称为构象空间。此外,这个网络使用损失函数来确保构象之间的中间产物在物理上是合理的。这样,在对常规原子模拟的快照进行训练后,网络可以预测给定的蛋白质构象如何转变为另一种构象,即它如何以物理上合理的方式移动。

https://journals.aps.org/prx/abstract/10.1103/PhysRevX.11.011052

在核心,这个网络还包括一个编码器和解码器,就像在以前的工作中一样,压缩和解压缩信息,沿途产生结构性波动。但是在编码器和解码器之间,这个网络增加了一个模块,其损失函数包含基于物理的项,确保任何一对构象之间的潜在空间插值产生低能的蛋白质结构。基于物理学的损失函数是基于经典原子模拟的一个琥珀力场(更具体地说是琥珀 ff14SB)构建的,分别采用其成键和非成键项。通过使用这种损失,网络的内部模块在连接输入和输出蛋白质构象的测地线的所有点上强制遵守物理学,并约束中间体遵循局部最小能量路径。

重要的一点是,由于网络可以将从一种蛋白质学到的特征转移到其他蛋白质,这种架构最终可以发展成为一种可转移的基于 ML 的力场,用于模拟蛋白质动力学。实现这一目标将为结构生物学和蛋白质建模带来大量机会。

Majewski 等人 arXiv 2022 仍然与蛋白质有关,但分辨率较低,Majewski 等人刚刚发布了一份预印本,描述了基于人工神经网络和基于统计力学的粗粒度分子势。他们用 9 ms 的累积原子模拟(大部分是由这种专用计算机产生的)来训练这个神经网络,用于各种不同结构的 12 种不同蛋白质。所得到的粗粒度模型将构象动力学的采样加速了三个数量级以上,同时保留了用于训练的详细原子模拟所提供的系统热力学。

https://arxiv.org/abs/2212.07492

致力于可转移的基于 ML 的力场,作者进一步表明,可以计算单个粗粒度势,它可以正确地模拟所有 12 种蛋白质的动力学,甚至捕获这些蛋白质突变版本的某些特殊特征。

案例 3:寻找自由能计算和增强取样的反应坐标的 ML 方法

取代力场或辅助物理计算并不是 ML 辅助物理的唯一方式。正在探索的整个领域是 ML 方法如何绘制构象景观并为模拟构建有效导航的路线。最早的方法涉及数学,如主成分分析,这是一种强大而快速的方法,但受到其线性特性的限制。由于更加通用,现代 ML 工具会更有帮助。

该领域的几个大团体利用最近的一篇综述探索了 ML 在物理学中的这种应用,以及我前面提到的一些促进力学计算的应用。该综述讨论了机器学*技术在分子动力学模拟中的应用,用于构建经验力场和确定自由能计算和增强采样的反应坐标。这些技术有可能从复杂系统模拟产生的大量数据中提取有价值的信息,但也有应该考虑的局限性。综述的重点是这些技术在材料和生物系统中的应用。

案例 4: ML 适应更好地模拟远程物理

大多数处理分子和材料的 ML 方法的一个重要限制是,它们的预测通常建立在相当局部的效应上,比如在一个原子的半径 X 埃内,或者直到 n 键之外,这两者与所研究系统的总尺寸相比通常都很小。为了得到完整的预测,局部计算的效应经常被汇集在一起。在这个过程中,长期信息可能会丢失。

格里萨菲和塞里奥蒂在《化学物理杂志》2019 中的一项工作提出了一种规避这种限制的可能方式,通过一种将物理术语与 ML 模型融合在一起的手段。

如上所述,大分子或大块材料的性质可能涉及所有以原子为中心的环境贡献的总和计算。这带来了解释的缺点,它不能捕捉非局部的,非加性的影响,如。例如,长程静电产生的效应所涉及的距离,可能比通常计算贡献的局部球体的距离大得多。这项工作的作者用一个框架解决了这个问题,该框架引入了系统的非局部表示,这些表示被重新映射为局部定义的特征向量,并在空间中等变,因此可以“连接”分子或材料的远点。这个框架原则上可以适用于任何种类的长期效应,正如他们用各种例子证明的那样。

在全球范围内,这项工作表明,将对长程相关性敏感的表示与以原子为中心的加性 ML 模型的可转移性相结合,可以更好地预测化学和物理现象。这正是这篇文章想要表达的观点:纯物理和基于 ML 的模型如何比以往更好地推进科学和工程。

关于 ML 和其他科学与工程计算方法的进一步阅读

除了我在整篇文章中提到的文章和博客条目…

https://medium.com/advances-in-biological-science/how-computer-modeling-simulations-and-artificial-intelligence-impact-protein-engineering-in-4d8473bd59ff

www.lucianoabriata.com我写作并拍摄我广泛兴趣范围内的一切事物:自然、科学、技术、编程等等。 成为媒介会员 访问其所有故事(我免费获得小额收入的*台的附属链接)和 订阅获取我的新故事 通过电子邮件 。到 咨询关于小职位 查看我的 服务页面这里 。你可以 这里联系我 **

做了调查之后,是时候相信你的直觉了

原文:https://towardsdatascience.com/after-doing-your-research-its-time-to-trust-your-instinct-252412610fc9

作者聚焦

关于数据科学教育的挑战,以及让复杂的主题变得容易理解。

在 Author Spotlight 系列中,TDS 编辑与我们社区的成员谈论他们在数据科学领域的职业道路、他们的写作以及他们的灵感来源。今天,我们很高兴与 穆尔塔扎·阿里 分享我们的对话。

照片由穆尔塔扎·阿里提供

Murtaza 是华盛顿大学的博士生,研究以人为中心的设计和工程,专注于数据科学。他的研究重点是数据可视化、以人为中心的数据科学和计算教育,他的一些其他(偶尔相关)兴趣包括写作和教学。

是什么激发了你最初对数据相关话题的兴趣?

我在加州大学伯克利分校读本科时是应用数学专业的学生,在我大三的时候,我选修了一门很受欢迎的课程——“数据 100:数据科学的原理和技术。”我对这门课没有太多期望;我接受它主要是因为其他人推荐它,而且它涵盖了我的一个主要需求。

那门课对我未来的学术轨迹产生了巨大的影响。它有一个独特的结构:由两位教授共同授课,一位是统计专家,另一位是著名的计算机科学家。这样做是为了强调数据科学本质上是跨学科的,这是我在写作和工作中经常强调的。在每周的讲座中,他们讨论高层次的话题以及社会影响,并分配实验室和项目,让学生动手实践数据争论、处理和分析任务。

然而,那个学期特别独特的是,它是在 2020 年春天——由于新冠肺炎,我们上线时被打断了。那个学期,我花了很多时间使用课堂上的技能来探索和分析各种在线数据集,甚至参加了我的第一次 Kaggle 比赛。我参加了每周的 Zoom 办公时间,与教授讨论我初露头角的兴趣,教授鼓励我,甚至指导我加入了一个以数据为中心的研究小组。从那以后大约两年了,我对数据的迷恋没有任何停止的迹象。

作为一个正在攻读博士学位的人,你最感兴趣的问题是什么?

早在我参加“数据 100”课程并对数据科学感兴趣之前,我是一名计算机科学入门助教,我知道我喜欢教学——这是我最初获得博士学位的动力。经过多次培训,在许多学生面前挣扎,并审查各种教学评估的结果,我意识到学生(我不严格地使用这个词,因为它不仅仅指大学本科生)最希望他们的老师有一点:以简单易懂的方式简化复杂概念的能力。那是黄金标准,我努力去实现它。

在许多方面,我认为这是吸引我进入数据科学的原因——在数据科学中,是数据可视化的原因。我看到了可视化和教育之间的许多联系,其中最主要的一点是,它们都旨在为一些目标受众获取复杂的想法并简化它们。这就是我在博士申请中所写的内容,也是我主要致力于数据可视化和计算教育相关问题的原因。

你已经知道未来几年你的作品会是什么样了吗?

由于我还在读博士,我还没有一个占据我大部分时间的具体项目,但我正在探索各种途径,试图找到我的定位。也就是说,有几个问题我目前有兴趣回答:

  • 文本数据本质上是非结构化和无序的,这使得它很难可视化。如果我们简化它,把重点放在具有人类定义的顺序的文本和文档上会怎么样?这种文本的一个例子是学术研究论文,其按节组织,并且在节内按段落组织。有没有有效的方法来设计和实现这些和相关文档的可视化?
  • 人们喜欢漂亮的东西。在使可视化吸引人的眼球,同时又能有效地呈现数据之间,什么是正确的*衡?我们希望人们学*,但我们也希望他们享受其中。
  • 在当今以技术为中心的世界中,计算教育变得越来越重要,然而美国的教育体系也存在令人难以置信的缺陷、偏*和漏洞。这是一个极其宽泛的问题,但也是一个同样重要的问题:我们如何让它变得更好?“更好”到底是什么意思?
  • 一个稍微相关的问题:所有这些关于连接可视化和教育的东西只是我头脑中的一个幻想吗,或者我们实际上可以混合这两个领域的技术以便各自受益?

这些听起来像是需要探索的非常重要的问题!你认为为了接近这些大课题,高级学位是必要的吗?

大约在我完成本科学业的时候,许多人坚定地认为,至少硕士学位是在数据科学职位上有竞争机会的必要条件。虽然我认为这种说法肯定还是有一些价值的,但我也认为随着大学数据科学课程变得越来越先进和广泛,一个高级学位可能不是严格必要的。

你会建议人们如何做这个决定?

有几个重要的问题需要自己考虑。

我目前的技能如何适应我想要的工作?获得硕士学位的额外一年或两年时间是否会让我获得更多统计、概率和数据科学方面的基础知识,或者使我能够专攻我感兴趣的领域,如人工智能?我真的需要上学,还是可以自学?

许多人盲目地归因于对自我学*的崇拜,但我个人认为这因人而异。有些人,比如我自己,从一个有组织的班级中受益匪浅,这个班级有结构化的作业和外部责任。

有了博士,问题就不一样了。在获得博士学位之前,你需要绝对确定你喜欢研究或教学。虽然获得博士学位后回到工业界而不是留在学术界肯定是可能的,但博士学位期间将涉及大量的研究和一些教学。大多数博士项目都是有报酬的,学生可以获得生活津贴,但数额非常低(通常每月 2000 至 3000 美元,一年 9 个月,取决于学校所在的地区和项目),因此这也值得思考。

当然,回报也可能是巨大的:你将学到大量的东西,你将成为你论文特定领域的领先专家,你将成为就业市场上的抢手货。然而,你必须问自己两个问题:1)我真的需要这个吗,2)我真的想要这个吗?

还有一件事:在你做了做决定所需的所有研究之后,相信你的直觉。它通常知道什么是对的。

你的公开写作是否影响或借鉴了你目前的学术工作?这两个领域是如何相互作用的?

目前,因为我还在博士的早期阶段,我还没有写我的研究项目。这在很大程度上是因为它们仍未公开,在接受同行评审时需要保持私密性。

然而,我获得博士学位的主要原因之一是因为我热爱教学,这与我的写作有着巨大的互动。我的目标之一是为计算机科学和数据科学教育设计更好的技术,尤其是为那些没有经验的人。结果我写的很多文章都是针对新手的。正如我上面提到的,我试图把复杂的想法用简单的方式表达出来。

这是我们在你最近的许多关于 TDS 的文章中看到的。是什么激励你开始为更广泛的读者写作?

这部分与我上面提到的有关:我的一个爱好是教学,所以写教学文章是这一爱好的自然延伸。想分享我对媒介的*解和想法,在某种程度上是我对“学术把关”这一概念感到沮丧的一种表达,作为博士学位的一部分,我对这个概念太熟悉了。

在学术界,所有的东西都是用复杂华丽的语言写成的,从来没有针对普通大众。我发现这是一个重大问题,特别是因为研究的全部目的是让世界总体上变得更美好(广义上讲)。Medium 给了我一个出口,让我可以简单通俗地写作,让每个人都能理解概念。作为一个在大学早期努力奋斗的人,这对我来说非常重要,我很感激有机会这样做。

要了解更多关于穆尔塔扎的工作和探索他的最新文章,请在媒体推特上关注他。为了体验一些 Murtaza 的可访问且有用的数据科学指南,以下是 TDS 档案中的一些亮点:

想和广大观众分享一些你自己的作品吗?我们很乐意收到你的来信。

这个 Q & A 是为了长度和清晰而稍加编辑的。

人工智能加速器和机器学*算法:协同设计和进化

原文:https://towardsdatascience.com/ai-accelerators-machine-learning-algorithms-and-their-co-design-and-evolution-2676efd47179

人工智能加速器机器学*中的高效算法和方法—英伟达 GPU、英特尔 Habana Gaudi 和 AWS Trainium 和推理

作者插图

很有可能你正在一台现代电脑上阅读这篇博文,这台电脑要么放在你的膝盖上,要么放在你的手掌上。这种现代计算机具有中央处理器(CPU)和其他专用芯片,用于专门的任务,如图形、音频处理、网络和传感器融合等。这些专用处理器可以比通用 CPU 更快、更有效地执行专门的任务。

从计算的早期开始,我们就将 CPU 与专用处理器配对。70 年代早期的 8 位和 16 位 CPU 在执行浮点计算时速度很慢,因为它们依赖软件来模拟浮点指令。由于计算机辅助设计(CAD)、工程模拟等应用需要快速浮点运算,CPU 与一个数学协处理器配对,它可以将所有浮点计算卸载到这个专用协处理器。数学协处理器是专用处理器的一个例子,它被设计用来比 CPU 更快更有效地完成特定任务(浮点运算)。

作者插图

如果你一直在关注人工智能或半导体行业的最新进展,你可能听说过专用机器学*处理器(人工智能加速器)。虽然最受欢迎的加速器是 NVIDIA GPUs,但还有其他加速器,包括英特尔 Habana Gaudi、Graphcore Bow、谷歌 TPUs、AWS Trainium 和 Inferentia。为什么今天有这么多 AI 加速器选项?它们和 CPU 有什么不同?算法如何改变以支持这些硬件?硬件如何发展以支持最新的算法?让我们找出答案。在这篇博文中,我将介绍:

  • 为什么我们需要专门的 AI 加速器?
  • 对机器学*硬件进行分类——CPU、GPU、AI 加速器、FPGAs 和 ASICs
  • “硬件感知”算法和“算法感知”硬件
  • 人工智能加速器和高效机器学*算法的共同进化
  • 人工智能加速器和有效的推理算法
  • 人工智能加速器和用于训练的高效算法
  • 人工智能加速器的未来

为什么我们需要专门的 AI 加速器?

构建机器学*专用处理器的三个最重要的原因是 (1)能效(2) 更快的性能和(3)模型大小和复杂性。提高模型准确性的最新趋势是引入具有更多参数的更大模型,并在更大的数据集上训练它们。我们在包括计算机视觉、自然语言和推荐系统在内的所有应用中都看到了这种趋势。

像 GPT 3 这样的语言模型有 1750 亿个参数,这在几年前还被认为是极端的。从那时起,我们已经看到了像 GLaM 的模型有 1.2 万亿个参数,NVIDIA 的 MT-NLG 有 5300 亿个参数。如果历史有任何指示,模型大小将继续变大,当前的处理器将无法在严格的训练时间和推理延迟要求下提供训练或运行这些模型的推理所需的处理能力。

然而,我们需要专门的人工智能加速器并使开发定制芯片的经济性发挥作用的一个最重要的原因是对能源效率的需求。

为什么我们需要节能处理器?

机器学*模型越大,需要执行的内存访问操作就越多。像矩阵-矩阵和矩阵-向量计算这样的计算操作是比存储器访问更节能的操作。如果你看看从存储器读取访问所消耗的能量与加法和乘法运算所消耗的能量相比,存储器访问操作比计算操作多消耗几个数量级的能量。由于大型网络不适合片上存储,因此需要更多消耗能源的 DRAM 访问。

来源:https://arxiv.org/pdf/1506.02626v3.pdf

当像深度神经网络这样的应用程序在通用处理器上运行时,即使通过扩展来实现很小的性能改善,也会带来巨大的能耗和设备成本。

G 通用处理器(如 CPU)以能效换取多功能性,专用处理器(人工智能加速器)以能效换取多功能性。

另一方面,人工智能加速器可以设计为具有最大限度地减少内存访问的功能,提供更大的片上缓存,并包括专用硬件功能来加速矩阵-矩阵计算。由于人工智能加速器是专门建造的设备,它“知道”它运行的算法,其专用功能将比通用处理器更有效地运行它。

对机器学*硬件进行分类——CPU、GPU、AI 加速器、FPGAs 和 ASICs

现在让我们来看看不同类型的处理器,以及它们在通用处理器和专用处理器中的位置。

作者插图

在谱的左端是 CPU,这些是真正通用的,因为你可以在它们上面运行任意代码。您可以使用它们来执行专用芯片执行的任何任务,包括图形、音频处理、机器学*等。如前所述,您将放弃性能和能效。

另一端是专用集成电路(ASICs)。这些也被称为固定功能芯片,因为它们的存在只是为了做一件或几件事情,通常是不可编程的,并且不公开开发人员关注的 API。这方面的一个例子是耳机中的噪声消除处理器。它需要高能效以延长耳机的电池寿命,并且功能足够强大以达到目标延迟,这样当您使用它们观看您最喜欢的电视节目时,就不会遇到延迟或令人沮丧的不同步问题。

谱的左端是关于通用和可编程性,谱的右端是关于专用和效率。

像 GPU、FPGAs 和 AI 加速器这样的处理器属于这个范围的什么位置?

回答:介于这两个极端之间。

作者插图

更接近 ASIC 一端的是现场可编程门阵列(FPGAs)。顾名思义,它是可编程的,但你需要硬件设计技能和硬件描述语言(HDL)的知识,如 verilog 或 VHDL。换句话说,它太低级了,离芯片太近,软件开发人员没有技能和工具来编程。

在 CPU 一端的右边是 GPU。与 CPU 不同,GPU 是专用处理器,擅长并行工作负载,如图形着色器计算和矩阵乘法。CPU 更适合延迟敏感型应用,而 GPU 更适合需要高吞吐量的应用。GPU 在某种意义上类似于 CPU,它们是可编程的,并使用 NVIDIA CUDA 和 OpenCL 等语言。与 CPU 相比,这些并行处理器可以运行更少的任意功能,但真正擅长利用并行性的代码。

人工智能加速器,如英特尔 Habana Gaudi、AWS Trainium 和 AWS 推理,位于 GPU 的右侧。Habana Gaudi 提供可编程性,但不如 GPU 通用,所以我们可以让它更接近 GPU。AWS 推理是不可编程的,但它提供了一系列支持的操作,如果您的机器学*模型不支持这些操作,那么 AWS 推理会为这些操作实现 CPU 后退模式。因此,我们可以将 AWS 推理进一步放在光谱的右边。

“硬件感知”算法和“算法感知”硬件

既然我们已经有了一个思考不同类型处理器的心智模型,让我们来讨论这些处理器如何与运行在其上的软件进行交互。

作者插图

通用计算模型有两个组件(1)软件和算法,以及(2)运行软件的硬件处理器。在大多数情况下,这两者是相当独立的,因为当你写软件时,你很少考虑它在哪里运行。设计硬件功能时,它们旨在支持最广泛的软件。

作者插图

该模型开始为深度学*等需要更高性能和能效的应用而发展,弥合了算法设计和硬件设计之间的差距。现代机器学*计算模型还包括两个组件(1)机器学*算法和软件框架(2)与 AI 加速器配对的通用处理器。

与通用计算模型不同,研究人员开发了“硬件感知”的机器学*算法,即他们编写的代码利用了硬件特定的功能,如多精度类型(INT8、FP16、BF16、FP32),并针对特定的芯片功能(混合精度、结构化稀疏)。作为用户,你可以通过流行的机器学*软件框架来利用这些特性。类似地,硬件设计师构建“算法感知”的人工智能加速器,即他们设计专用的硅功能,可以加速机器学*矩阵计算(例如张量核)。

这种“硬件-算法意识”是可能的,因为人工智能加速器硬件和机器学*算法正在共同进化。硬件设计师正在向人工智能加速器添加由机器学*算法利用的功能,机器学*研究人员正在创建新的算法和方法,可以利用人工智能加速器上的特定功能。

硬件和软件作为一个整体更加紧密地工作,从而带来更高的性能和能效

人工智能加速器和高效机器学*算法的共同进化

人工智能加速器分为两类——(1)用于训练的人工智能加速器(2)用于推理的人工智能加速器。由于训练和推理的目标是不同的,并且 AI 加速器是用于专门工作负载的专用处理器,因此为每种类型的工作负载设计单独的处理器是有意义的。

训练加速器的目标是减少训练时间,并且训练加速器被设计成具有训练算法可以利用的硬件特征。这通常意味着训练加速器是更高性能的处理器,更多的内存支持更高的吞吐量(每秒处理的数据)。由于训练加速器是吞吐量集中的设备,如果您最大化吞吐量或利用率,它的能量成本/吞吐量将会更低。训练加速器还支持混合精度训练,使用专用硬件功能,在低精度下执行计算速度更快,在高精度下累积结果,与通用处理器相比,更加节能。我们将在人工智能训练加速器一节中更详细地讨论混合精度训练。

另一方面,推理加速器的目标是减少大量独立数据批次的预测延迟。因此,推理加速器需要是能量有效的,并且具有低能量成本/预测。您可以使用训练加速器进行推理(训练的正向传递本质上是一个推理任务),但是训练加速器上的能量成本/推理会高得多,因为它在小批量推理请求中没有得到充分利用。

作者插图

一个训练加速器就像一辆公共交通巴士,只有当巴士一直爆满,燃料成本/乘客成本较低时,它才是节能的。如果你使用公共汽车每次只运送一个人,那么每位乘客的燃料成本就会更高。另一方面,推理加速器就像一辆跑车,比公共汽车更快,比一个乘客的公共汽车更节能(因为每名乘客的燃料成本更低)。但是,如果你想用一辆跑车运送 50 个人,效率会很低,速度也会很慢(更不用说违法了)。

在下一节中,我们将分别仔细研究训练和推理工作流。对于每一个,我们将看看为其任务提供最佳性能和能效的人工智能加速器和软件功能。

人工智能加速器和有效的推理算法

我们知道,机器学*推理包括将训练好的模型应用于新数据,以获得模型预测结果。在这一节中,我们将讨论在人工智能加速器上运行的高效算法,以使推理更加高效和节能。

作者插图

能让机器学*推理更高效的最重要的软硬件绝招就是量化。为了充分理解量子化,我们必须理解计算机硬件中的数字表示。数字计算机中的浮点数是连续实数值的离散表示。机器学*算法通常存储和处理基于 IEEE 754 标准的单精度(FP32)数字。IEEE 754 指定了额外的浮点类型,如 AI 加速器通常支持的半精度(FP16)和双精度(FP64)。现代 AI 加速器还支持其他非 IEEE 754 标准表示,如 bfloat16(由 Google Brain 推出,由 NVIDIA Ampere GPUs、AWS Inferentia、AWS Trainium、Intel Habana Gaudi、Google TPUs 支持)和 TF32(在 NVIDIA Ampere 架构和 AWS Trainium 加速器中)。推理加速器通常也支持整数精度,如 INT8 和 INT4。

推理量化的好处

对于推理任务,模型权重和激活可以被量化,即从 FP32(典型的训练精度)转换为较低精度的表示,例如 FP16、bfloat16 或 INT8。较低精度的型号意味着更好的性能和能效。当您从 FP32 位转到 FP16 操作时,数据大小减少了 2 倍,能耗减少了大约4 倍,FP16 操作的芯片面积减少了大约 4 倍。

从仅推理硬件设计的角度来看,构建更小的仅推理加速器是有意义的,这些加速器仅支持较低的精度,因此更节能。从 FP32 迁移到 INT8 结果将导致更低的能源利用率,因为数据大小减少了 4 倍。

这种巨大的性能效率提升通常是以模型预测准确性为代价的。移动到较低精度的表示是一种压缩,这意味着量化时会丢失一些数据。与 FP16 和 INT8 相比,FP32 具有较大的动态范围,如下所示。因此,推理量化的目标是在量化到较低精度时只保留“信号”,并去掉“噪声”,有几种方法可以做到这一点。

用 NVIDIA GPUs 量化

基于 NVIDIA Ampere 和 NVIDIA Turing 架构的新一代 NVIDIA GPUs 支持一系列仅用于推断的精度类型。虽然 FP16 precision type 早在 2016 年就在 NVIDIA Pascal 架构中首次推出,但最新的 NVIDIA Ampere 和基于图灵的 GPU 是真正“硬件-算法协同进化”的例子。我已经在我的博客文章中讨论了 GPU、GPU 架构及其特性的完整历史:

在这一节中,我将重点介绍 GPU 上量化的硬件和软件支持。

我们以 NVIDIA Ampere GPU 架构为例。在 AWS 上,您可以通过启动 p4d Amazon EC2 实例来访问基于 Ampere 的 NVIDIA A100,通过从 G5 实例类型启动 GPU 来访问 NVIDIA A10G。这两款基于 NVIDIA Ampere 的 GPU 都支持 FP64、FP32、FP16、INT8、BF16、TF32 精度类型,并且还包括专用于混合精度算法的芯片,NVIDIA 称之为张量内核。为了便于推断,我们只关心的精度类型是 FP16 和 INT8,在下一节讨论训练时,我们将再次讨论其他精度类型。

由于大多数深度学*框架在 NVIDIA GPUs 上以 FP32 训练模型,因此为了更有效地运行推理,NVIDIA 提供了 TensorRT,这是一种可以将模型权重和激活量化为 FP16 或 INT8 的编译器。为了执行量化,TensorRT 将确定一个比例因子,以将 FP32 张量的动态范围映射到 FP16 或 INT8 的动态范围。这对 INT8 来说尤其具有挑战性,因为它的动态范围远远小于 FP32 的动态范围。INT8 只能表示 256 个不同的值,而 FP32 可以表示大约 4.2 倍的 10⁹值!

ML 研究和硬件社区提出了两种方法来利用量化而不损失准确性:

  1. 训练后量化(PTQ):从 FP32 中的训练模型开始,导出比例因子以映射 FP32 -> INT8。TensorRT 通过测量每一层的激活分布并找到最小化参考分布和量化分布之间的信息损失(KL 散度)的比例因子来做到这一点。
  2. 量化感知训练(QAT):在训练过程中计算比例因子,允许模型适应并最小化信息损失。

让我们花点时间来欣赏一下硬件和算法之间的这种动态关系。我们可以看到,硬件已经发展到提供更高效的芯片功能,如降低精度,现在算法必须发展到利用芯片功能!

有关量化如何在 GPU 上与 NVIDIA TensorRT 一起工作的代码示例,请阅读我的博客文章:

用 AWS 推理进行量化

虽然 NVIDIA GPUs 最初是为了加速图形而创建的,并正在发展成为强大的人工智能加速器,但 AWS Inferentia 的创建只有一个目的,即加速机器学*推理。每个 AWS 推理芯片有 4 个神经内核,每个神经内核是一个脉动阵列矩阵乘法引擎,具有两级存储器层次和一个非常大的片上缓存。它支持 FP16、BF16 和 INT8 数据类型,不支持更高精度的格式,因为您不需要它来进行推断——它毕竟是一个专用处理器。就像英伟达针对 GPU 的 TensorRT 编译器,AWS Neuron SDK 以及支持量化和优化高效推理的编译器。

在撰写本文时,尽管 AWS 推理硬件支持 INT8,但 AWS 神经元编译器仅支持 FP16 和 bfloat16 作为量化目标。在编译过程中,用 FP32 训练的模型会自动转换成 bfloat16。如果您在使用 AWS Neuron 编译器之前手动将权重从 FP32 量化到 FP16,那么它将保留 FP16 精度进行推理。

与 GPU 相比,AWS 推理加速器不可编程,因此在我们之前讨论的硬件频谱中,它属于 GPU 的右侧,更接近 ASICs。如果模型具有 AWS 推理完全支持的操作,那么对于特定模型和批量大小的组合,它可能比 GPU 更节能。但是,如果模型有不支持的操作,AWS Neuron 编译器会自动将这些操作放到主机 CPU 上。不幸的是,这会导致 CPU 和加速器之间的额外数据移动,从而降低其性能和效率。

训练人工智能加速器和高效算法

机器学*训练包括使用训练数据优化模型的参数,以提高模型的预测准确性。在这一节中,我们将讨论在人工智能加速器上运行的高效算法,以使推理更加高效和节能。

让我们重新审视一下 precision,但这次是为了培训工作流。正如我们之前在训练期间讨论的,权重和激活存储在 FP32 表示中,FP32 表示是先于深度学*的 IEEE 754 浮点标准。ML 的研究人员选择这个作为默认的浮点表示,因为在训练期间,FP16 不能容纳足够的信息,而 FP64 太大了,我们实际上不需要那么大的数量和精度。他们需要的是介于两者之间的东西,但当时硬件中没有这种东西。

换句话说,现有的硬件不知道算法需求,或者说不知道我们前面讨论过的“算法感知”。

如果 ML 研究人员有能力选择任何对机器学*非常有用的浮点表示,那么他们会选择一种看起来不同于 FP32 的表示,或者使用精度的组合来提高性能和效率。这正是人工智能加速器在混合精度训练中采取的方向,它需要硬件和算法的共同设计才能工作。

作者插图

混合精度训练以提高性能和效率

矩阵乘法运算是神经网络训练和推理的面包和黄油,人工智能加速器的大部分时间都花在乘以各层输入数据和权重的大型矩阵上。混合精度训练背后的想法是,训练期间的矩阵乘法发生在较低精度的表示(FP16、bfloat16、TF32)中,因此它们更快、更节能,结果在 FP32 中累积,以最大限度地减少信息损失,使训练更有效、更快。

使用 NVIDIA GPUs 进行混合精度训练

2017 年,英伟达宣布了 Volta 架构,该架构在其芯片中采用了专门的机器学*功能,称为英伟达张量核心。张量核心支持使用 FP16 数学和 FP32 累加的混合精度训练。新一代 NVIDIA GPU 架构将支持从 FP16 扩展到其他精度降低的格式(bfloat16、TF32)。在芯片级,Tensor Core 通过 FP32 累加执行精度降低的融合乘加(FMA)。

每一代 NVIDIA 架构的改进都是硬件算法协同设计和协同进化的一个很好的例子。

  • NVIDIA Volta architecture (2017)推出了第一代张量内核,仅支持 FP16 数学和 FP32 混合精度累加
  • NVIDIA Turing (2018)扩展了张量核以支持 INT8 和 INT4 简化精度(这主要有利于推理,而不是训练)
  • NVIDIA Ampere (2020)扩展了张量内核以支持 bfloat16、TF32,这意味着它可以执行 FP16、bfloat16 或 TF32 数学运算,并在 FP32 中累加以实现混合精度

混合精度训练的一个挑战是,从软件的角度来看,它不“只是工作”。用户必须在训练过程中执行额外的步骤,例如在可能的情况下将权重转换为 FP16 数据类型,同时保留 FP32 权重和损失比例的副本。虽然 NVIDIA 支持深度学*框架在最少代码更改的情况下完成这些步骤,但它对最终用户的概念要求很高,不像 FP32 中的培训那样简单。

通过 NVIDIA Ampere,硬件已经发展到支持新的 TF32 格式,显著解决了这一用户体验缺陷。TF32 令人兴奋的是,它具有 FP32 的范围和 FP16 的精度,这意味着深度学*框架可以支持它开箱即用,而不需要执行像转换和簿记这样的额外步骤。虽然 TF32 在没有开发人员开销的情况下提供了比 FP32 更好的性能,但 NVIDIA 仍然建议使用基于 FP16 或 bfloat16 的混合精度训练来获得最快的训练性能。

用其他 AI 加速器进行混合精度训练

英特尔哈瓦那高迪

Habana Gaudi 加速器支持混合精度的方式与 NVIDIA 支持它的方式类似——借助一个附加工具,你可以与深度学*框架一起使用,该框架可以为你执行造型和记账。在 AWS 上,您可以通过启动亚马逊 EC2 DL1 实例来访问英特尔 Habana Gaudi AI 加速器,这将为您提供 8 个 Gaudi 加速器。

AWS Trainium

AWS 在 re:invent 2021 上宣布了 AWS Trainium,这是一个由 AWS 的 Annapurna 实验室建造的人工智能加速器。在撰写本文时,AWS Trainium 尚未全面上市。在这次发布会上,AWS 分享了 AWS Trainium 在发布时将支持 FP16、TF32、bfloat16、INT8 以及一种令人兴奋的新格式 cFP8,它代表可以定制的 8 位浮点。

人工智能加速器的未来

对于机器学*算法研究和机器学*硬件设计来说,我们都生活在一个激动人心的时代。人工智能加速器将继续发展,以提供更高的性能,更好的能效,并变得像通用处理器一样无缝使用。

现代人工智能加速器已经包括预期的硬件功能,例如支持 INT1 和 INT4 精度类型,这种类型目前不用于训练或推理任务,但有一天可能会实现新的机器学*算法。人工智能加速器的网络是另一个正在经历变革的重要领域。随着模型规模的不断增长,我们将需要更大的计算集群,其中许多人工智能加速器相互连接,以支持更大的工作负载。英伟达通过 NVLink 和 NVSwitch 提供高带宽 GPU 间互连,英特尔 Habana Gaudi 集成了片上和基于以太网的 RoCE RDMA。随着越来越多的应用程序集成基于人工智能的解决方案,人工智能加速器将继续存在,并将成为现代计算环境中的一个主要部分。

我期望看到更多进步的领域是用户/开发者体验。今天的异构计算模型涉及到使用多个 CPU、人工智能加速器及其网络和存储设置,这对大多数数据科学家和开发人员来说都是非常具有挑战性的。虽然像 Amazon SageMaker 这样的云中托管服务消除了管理基础设施的所有需求,使扩展机器学*变得容易,但开源框架仍然希望用户了解底层硬件、精度类型、编译器选项和网络原语等。

在未来,开发人员将登录远程 IDE 并使用开源机器学*框架运行代码,而不会再考虑它在哪里以及如何运行。他们只会指定成本与速度的权衡——更快的结果花费更多,更慢的结果节省成本——这将是他们唯一的认知负担。我是一个乐观的人,我认为我们很接近了。

你好。谢谢朋友,看完!

如果你觉得这篇文章很有趣,可以考虑给它一点掌声,然后在 medium 上跟我学。也请查看我在 medium 上的其他博客帖子,或者在 twitter ( @shshnkp )、 LinkedIn 上关注我,或者在下面留下评论。想让我写一个特定的机器学*主题吗?我很想收到你的来信!

人工智能联盟和极权主义

原文:https://towardsdatascience.com/ai-alignment-and-totalitarianism-62be89fa1bdf

意*

汉娜·阿伦特会对人工智能对齐说些什么?

图片来源: Unsplash

介绍

这篇文章通过极权主义的框架来看待人工智能的错位,如汉娜·阿伦特的极权主义的起源中所述。我不想在 20 世纪非常真实的、单一的极权主义恐怖和仍然是假设的人工智能错位问题之间做任何油嘴滑舌的道德比较;但我认为这种相似之处仍然值得探究。

在她的巨著中,阿伦特描述了一个历史和政治背景,它孕育了一场与人类繁荣根本不一致的政治运动,这是一场与以往政府形式的反常决裂,构成了一台毁灭人类的机器。尼克·博斯特罗姆著名的纸张思维实验想象了一个 AGI,他被授权制造尽可能多的回形针;由一个全能的代理人来执行,这个*庸但不受约束(读极权主义)的奖励函数导致了天启。两者都是强大的机器,在没有自然的人类直觉的指导下,朝着与人类繁荣根本不一致的目标逻辑地、无情地前进。

是什么让政府成为极权政府?

极权政府区别于其他形式的独裁政府(甚至像墨索里尼的意大利这样的法西斯独裁政府),在于它不断地走向统治生活的每一个方面。它的终极目标是让人类机器人,可以预测地、顺从地对政权的命令做出反应,消灭自由意志的所有残余。任何形式的人类自发性都是对秩序的威胁:极权主义可以被认为是一个试图进一步消灭它的系统。

在阿伦特的思想中,当一个运动达到一个逃逸速度并退出“正常”政府的领域时,它就变成了极权主义,而“正常”政府,无论是哪种类型,都在某种程度上受到功利主义的约束:这是为其人民的福利服务的某种需要。(允许这种逃避的历史和政治条件超出了我的能力范围,也是本书大部分的主题。)

但是一旦它逃脱了,它就变成了一台毁灭人类的机器。它原子化、恐吓和谋杀自己的人民。它用运动的逻辑代替了常识,运动需要无限的扩张和与外部正常世界的战争。合乎逻辑的结论是,这场运动要么在外部被击败,要么耗尽人的生命来摧毁:没有可能的*衡。

生成人工智能和创造性破坏

博斯特罗姆的毁灭人类的回形针似乎是一个不可信的例子,但它强调了在一个只关心逻辑目标实现的无限过程中规模的危险。

生成式人工智能模型(如 OpenAI 的 GTP-3 和 DALLE-2)在创造能力方面取得了令人难以置信的加速飞跃,颠覆了关于人工智能有能力破坏何种工作的传统预期。它们通过拜占庭神经网络架构输入大量数据(基本上是整个互联网)来产生捕捉令人震惊的细微差别的信息模型。而且,由于他们所训练的群体的普遍性(出色地展示了一篇这种规模的博客文章),他们在执行任务时表现出惊人的灵活性。允许这种进步的基本创新是网络和训练集的规模;事实证明,蛮力,而不是更聪明的信息结构,可能是广义智能的关键。

从某种意义上说,人工智能在这里的错位与政治经济有关:它以零边际成本即时完成智力工作(如新闻、医疗诊断、标志设计)的能力,可能会把人们完全挤出特定领域,留下不满的大众。

但从另一个角度来看,威胁在于扼杀以人为中心的创造力。如果你不相信这个人工智能具有真正的自发性(我不相信),即使你相信,如果你相信它的自发性与人类的自发性有根本的不同(如果我不相信,我会相信),那么人工智能已经消灭了人类在其领域的自发性。不是字面上的机器学*奖励功能摧毁了人类,就像博斯特罗姆的回形针算法一样,人工智能的运行颠覆了人类以特定方式创造的动机。机器的规模和效率,加上资本主义的基本原理,扼杀了人性的核心原则。

我个人不相信一个 LLM 会粉碎一个领域中所有人类的创造力,LLM 可能会成为在新的方向上投射创造力的强大工具。但是,随着人工智能生成能力的相互复合(值得强调的是,人工智能已经开始编写代码),人类适应的速度有多快?

风险和回报

20 世纪的极权主义罪行是由带有不人道目的的人类领导的运动延续下来的。人工智能安全研究人员的担忧集中在算法奖励函数的非人性本质上,这些函数寻求最小化数学定义的误差。

我相信机器学*承诺的物质丰富和知识是追求它的足够好的理由。但任何不受人类需求约束的权力系统(如大公司手中的人工智能)——甚至或特别是创造和智力满足的需求——都会打开一扇门,无论多么小,通向生活和意义的空虚。

AI 和 ML 能保存干净的转换加速吗,或者只是在风暴中保持亮着?

原文:https://towardsdatascience.com/ai-and-ml-to-save-the-clean-transition-acceleration-or-just-to-keep-the-light-on-during-the-storms-9219b52a8fba

在一个充满多重挑战和风暴的世界里,整合可再生能源,如果没有人工智能和机器学*,说起来容易做起来难

马克斯·拉罗彻尔在 Unsplash 上拍摄的照片

随着疫情仍处于幕后,许多国家的政治危机加剧,再加上气候变化对全球的影响越来越大,可再生能源行业(如全球许多行业)迫切需要高效的工具和方法来恢复我们的“技术”元气。

但在风暴期间保持照明是一种选择还是行业生存的必要条件?

人工智能先驱之一, Rana el Kaliouby (一位 AI 思想领袖。机器学*科学家。Smart Eye 的副首席执行官、 Affectiva 的前联合创始人兼首席执行官)正确地表示,“人工智能正在社会中扮演许多新角色——成为我们的同事,在我们的家中充当虚拟助理,操作我们的汽车,等等”。

https://blog.re-work.co/interview-with-rana-el-kaliouby-ceo-affectiva/

虽然电网是地球上最复杂的机器之一,但它在不断变化的世界中发展迅速,而各种可再生能源的增加使其更加复杂。值得注意的是,由于众所周知的风能和太阳能固有的可变性,目前的电网在适应可再生能源的多样性方面面临许多挑战。

公用事业行业需要智能系统来帮助改善可再生能源与现有电网的整合,并使可再生能源成为能源供应中的*等参与者。

以下是人工智能技术如何有助于提高可再生能源的可靠性,以及在当地和全球范围内实现电网现代化。

不断增长的挑战

它始于理解和认识到每个人以及每项技术都是独一无二的,都有不同的优势、能力和经验。整合不同的能源是第一步,认识到这一点,然后创造环境,在那里你可以发挥每一个最好的方面,这样当他们一起工作时,总和远远大于部分。

在这篇文章中,我想重点关注机器学*和数据源中的技术集成,这些技术可以作为能源转型的催化剂,而技术的限制和简单的“竞争”将打破整个过程。

为了想出前沿的解决方案,你真的需要有不同的视角和技能。我们都知道,在一个团队中,如果你有相同类型的人在做某件事(都是男性,都是老人,都来自城市,等等)。),您只能创建自己的解决方案类型。整合差异,实际上可以让你扩大视野,突破界限。人工智能有助于整合不同的解决方案,拓宽可能性的范围。

西蒙朱Unsplash 上拍照

书籍和电影中的人工智能已经以不同的形式存在了很长时间。他们被描绘成有时友好,有时险恶。但在现实生活中,我们喜欢将 AI 视为增强智能。多年来,人工智能已经在许多不同的领域证明了自己的用处。在人工智能出现之前,计算机仅根据例子识别照片中的人的想法是闻所未闻的。今天,我们甚至使用人工智能来检查医学图像,以快速识别异常,挽救患者的生命。

Coursera 联合创始人、百度人工智能事业部前负责人 / 谷歌大脑将人工智能的变革性影响比作 100 年前电力的变革性影响,我当然同意他的观点。

事实上,AI 对不同的人意味着不同的东西。对于视频游戏设计师来说,人工智能意味着编写影响机器人如何游戏或环境如何对玩家做出反应的代码。对于我们大多数人来说,我们看到的人工智能更有可能是你手机上的一个应用程序,而不是智能机器人(或 Android!).它被用于幕后管理财务,建议你的下一部网飞电影,识别信用卡欺诈,阅读医学成像,并为病人找到合适的临床试验。人工智能参与了我们每天的决策。

到 2025 年,美国人工智能支出将增长到 1200 亿美元,在 2021-2025 预测期内,复合年增长率(CAGR)为 26.0%。此外,国际数据公司( IDC )的最新全球人工智能支出指南中描述的所有 19 个美国行业预计将实现 20%或更高的人工智能支出增长。美国也占全球人工智能支出的一半以上。

https://www . enterprise ai . news/2022/03/17/spending-on-ai-solutions-will-double-in-the-us-2025-says-IDC/

图片来源:Smart Phases Inc .(nova cab . us)

“使用人工智能的最大潜在好处仍然是它在开发新业务和建立新商业模式方面的用途,”IDC 客户洞察分析团队的高级研究经理 Mike Glennon 说。“然而,现有企业不愿接受这一潜力,将最大的机会留给了新的市场进入者,他们不惧怕变化,能够轻松适应新的经营方式。商业的未来是人工智能,那些能够抓住这个机会的公司很容易成为新的巨头。”

但在能源领域,它仍有很长的路要走。与许多其他行业相比,在电力行业,我们可以利用增强智能来扩展人类的能力,并完成人类或机器无法独自完成的事情。我们今天面临的一些挑战来自于过量的信息。更快的通信、分布式计算和物联网(IoT)导致了(指数级增长的)海量数据的产生,而物联网本身和社交网络鼓励了大部分数据的非结构化。数据太多,人类专家无法跟上所有的变化和进步。

增强智能

随着机器学*带来的增强智能,我们可以从数据中提取更多的实质和相互关系,同时将所需的信息放在我们的指尖,并用证据支持这些信息,以便利益相关者可以做出更明智的决策。这将允许专家和决策者扩展他们的能力,以便他们能够更好地服务他们的客户。机器做耗时的工作,这样我们才能做重要的事情。

在传统编程中,一切都是确定的,if-then-else 循环决定了软件如何响应变化的条件。当您比较已知值,如温度、文本字符串或电子表格中的数字时,这很有用。但是当你想要将对象-决策-变化分类时,简单的“如果-那么”语句是行不通的。这个世界太复杂了,有灰色阴影和多个正确答案,概率答案成为一种要求。在电力领域,几乎一切都是概率性的(天气、消费者行为、高峰管理、风力涡轮机或太阳能光伏输出等)。).确定性系统可以告诉你,“答案是 X,因为比较成功”,例如恒温器上的温度,而在负载均衡或可再生发电中则需要概率性系统,因为你需要一个系统告诉你,“我非常有信心这是正确的答案,但我也有证据支持这些替代方案”(例如,储存能量以备后用,减慢风力涡轮机,因为风力可能超过限制,等等)。).

机器学*在电力领域的应用

AI 擅长什么,不擅长什么?答案往往归结于数据。人工智能技术就像任何技术一样会改进,所以今天的限制可能是明天的突破,但当前的人工智能技术非常擅长分类和翻译(解释)。

不管你说的是自然智能还是人工智能,没有什么是不能学*的智能。人类生来就有某种程度的先天智能,我们可以通过学*来建立这种智能。先天智能机器唯一拥有的是我们给予它们的东西,而常识目前不在那张很短的清单上。不过,我们提供的是检查示例的能力,以及基于输入和期望输出创建机器学*(ML)模型的能力。对于监督学*,我们为 AI 提供了例子。无监督学*是你提供输入,而不是标签,让机器推断质量。这种类型的学*对于聚类数据很有用,其中数据根据其与邻居的相似程度以及与其他事物的不相似程度进行分组。

一旦数据被聚类,您就可以使用不同的技术来研究这些数据并寻找模式。强化学*是机器做出决定,并根据决定是否正确给予奖励或回报。你可以使用强化学*来教机器下棋或导航障碍课程,如需求侧管理或发电计划。深度学*是应用于神经网络的机器学*的子集。深度学*网络指的是节点的排列,这肯定会是下一代与能源相关的人工智能应用

当选择用于训练机器模型的数据源时,重要的是对在生产中会遇到的数据的代表性数据进行采样。可能出现的一个挑战是训练数据无法预测未来的输入数据。这个问题必须在这个过程中尽快解决。不一定你需要所有的答案,而是你确定了一个处理这种情况的过程。因为垃圾输入等于垃圾输出,没有任何人工智能解决方案可以从坏数据中给出好的结果。然而,如果您的一些数据是坏的,您可以做的是识别并保留您的可用数据,并收集(或构建)可以在您的解决方案中使用的新数据。您应该考虑您必须处理的数据的数量、质量和敏感性。

斯蒂芬·道森在 Unsplash 上拍摄的照片

更高效地整合不同来源

能源网格可以与设备和传感器互连,以收集大量数据。

当与人工智能结合时,这些数据可以为电网运营商提供新的*解,以更好地控制运营。它为能源供应商提供了灵活性,可以根据需求灵活地调整供应。

先进的负载控制系统可以安装在设备上,如工业炉或大型交流设备,当电源不足时,这些设备可以自动关闭。智能储物单元还可以根据供应流量进行调节。

此外,智能机器和先进的传感器可以预测天气和负载,从而全面提高可再生能源的整合和效率。

这对于电网运营商来说变得越来越复杂,对于较小的设施或社区来说也是如此。它现在涉及将可再生能源生产资产纳入自我消费(太阳热能和/或光电、从生物量或沼气生产热能、地热能……),以使运营商能够减少碳足迹,实现能源组合多样化,并减少对传统燃料的依赖,这将有助于更好地控制与能源相关的长期预算。

在任何情况下,它都是优先激活的杠杆:“未用完的能源没有成本,也不会造成污染”。另一方面,即使有一些很好的成功或更有吸引力的行业,可再生能源和回收技术的部署在行业中仍然太落后。有许多障碍需要克服:巨大的投资成本、当前与化石燃料和廉价电力的竞争、对与这些创新技术相关的运营风险的恐惧、缺乏技术知识或运营能力等。这就是人工智能和数据科学可以提供很大帮助的地方。

可以分析许多积极的经验,并将其作为“学*”阶段的范例。这将旨在通过回收技术和可再生能源向该行业提供短期内的可能性,重点是主要部门和一套技术。

可再生能源的强劲基本面

自 2019 年可再生能源行业展望以来,“三个有利趋势支撑了强劲的基本面”。这些趋势包括支持可再生能源增长的新兴政策、扩大投资者对该领域的兴趣,以及提高风能和太阳能对电网、资产所有者和客户价值的技术进步。或许最重要的是,大多数细分市场的强劲需求。自 2017 年以来,公用事业表现出强劲的“自愿需求”(52%的公用事业规模的太阳能项目在开发中,73%的项目在 2018 年上半年宣布,而不是我们过去看到的由政策命令驱动的需求)。自 2017 年以来,仅新的太阳能项目就占超过煤炭、天然气和核能的两倍。企业对可再生能源的需求迅速增长,这在一定程度上推动了自愿需求。

在联合国气候变化会议(COP26)上,落基山研究所(RMI)、气候智能风险投资公司(Climate Smart Ventures)、碳信托公司(Carbon Trust)和能源转型智库国际网络(INETT)宣布成立煤炭资产转型加速器(CATA),这是一个首创的*台,将利用金融来加速全球煤炭转型。CATA 由 IKEA Foundation 和 Growald Climate Fund 资助,旨在为地方政府、公用事业公司、金融家和民间社会组织提供前沿分析、领先的专业知识和一系列工具和资源,以实现从煤炭到清洁能源的转型。

欧洲气候基金会(ECF)总裁兼首席执行官 Laurence Tubiana 在第 26 次缔约方会议上向代表们介绍了 CATA,他说:“显而易*的是,单靠经济和气候政策不会像气候科学所敦促的那样迅速将煤炭从系统中清除,尊重区域和当地背景并考虑到公正过渡的金融机制是关键。”。

推出新举措,加速全球煤电厂转型……

RMI 及其合作伙伴表示,设计良好的金融机制可以支持从煤炭到清洁能源的公*过渡。

https://zephyrnet.com/new-initiative-unveiled-to-expedite-transition-of-coal-plants-globally/

2019 年,马绍尔群岛已经在展示他们通过各种采购途径购买了近 6.5 千兆瓦(GW)的可再生能源。

https://rmi.org/press-release/new-facebook-google-gm-and-walmart-led-renewables-group-launched/

拯救地球从未如此有利可图;这是该行业成熟的又一标志。因此,对话现在转向人工智能将如何帮助传统能源、可再生能源和储能改善电网,以满足(目前)未来的需求。

让我们把重点放在建设性的东西上,放在如何利用人工智能和能量存储的技术组合上。因此,对已经超过传统能源的可再生能源的投资将变得更加经济合理,而且还因为这可能成为应对气候变化和建立更有弹性的电网的主要倡导者之一。

人工智能可以帮助整合微电网和管理分布式能源。当社区一级的可再生能源发电机组加入初级电网后,电网内的能量流动就变得很难*衡。

人工智能驱动的控制系统可以在解决质量和拥堵问题方面发挥至关重要的作用。

提高安全性和可靠性

虽然人工智能在可再生能源领域的最大目标是管理间歇性,但它也可以提高安全性、效率和可靠性。

它可以帮助您了解能源消耗模式,并识别设备的能源泄漏和健康状况。

例如,人工智能驱动的预测分析可以从风力涡轮机传感器收集数据,以监控磨损。该系统将监控设备的整体健康状况,并在需要维护时提醒操作员。

人工智能的集成可以通过引入新的服务模式和鼓励更高的参与度来帮助可再生能源供应商扩大市场。人工智能驱动的系统将能够分析与能源收集相关的数据,并提供对能源消耗的*解。

这些数据将帮助供应商优化现有服务并推出新的服务模式。它还可以帮助零售供应商瞄准新的消费市场。

具有智能存储的智能电网

最后,人工智能与智能储能(IES)的集成可以为可再生能源行业提供可持续和可靠的解决方案。

这个智能电网将能够分析从几个传感器收集的大量数据,并及时做出能源分配的决定。

这也将有助于微电网有效地管理当地的能源需求,同时继续与主电网进行电力交换。

未来必要的改变。当多重危机一个接一个出现,或者同时以一种完美风暴的方式出现时,我们只需要把它们放在适当的位置。但是解决方案就在眼前。

简而言之,AI 和 ML 都可以节省干净的过渡加速度,并在前方的风暴中保持光明。让我们立即采取行动吧。

Josep Castells 在 Unsplash 上拍摄的照片

这篇文章是荷兰国际集团的夏羽·比洛多关于人工智能和能量储存的系列文章的一部分。工程师,博士,智能阶段首席技术官( Novacab ),加拿大工程师协会会员,麦吉尔大学工程学院讲师,能源中心专家撰稿人

您可以在此找到其他文章:

人工智能应用于掩模检测:迁移学*应用

原文:https://towardsdatascience.com/ai-applied-to-mask-detection-a-transfer-learning-application-2105956c8720

应用机器学*

将预训练模型应用于分类问题

图片改编自面罩检测| Kaggle

T 转移学*是在几分钟内适应极其复杂的模型以获得极好结果的最佳方式。在这篇文章中,我将迁移学*应用于面具检测。

介绍

掩模检测是当今世界的一个相关问题。在写这篇文章的时候,欧洲的许多国家仍然强迫你在室内和公共交通工具上穿着它们。训练一个模型来检测是否戴了面具是一个有趣的问题,在这里我可以展示迁移学*的潜力。

从图片预测口罩佩戴是否正确涉及多个步骤。每个图像可以包含多个人,我们希望对每个人进行预测。问题的第一部分包括找到每张图像中的人脸,裁剪人脸,并准备将它们用作机器学*模型的输入。问题的第二部分是分类问题。被裁剪的面部被分为 3 类:“面具”、“无面具”、“面具佩戴不正确”。

数据

在整篇文章中,我使用了面具检测| Kaggle 数据集,这是一个公共数据集,包含 800 多张带面具的人的标签图像。

每个类别图像数量的条形图。作者图片

数据集被标记。每张图片都包含了每张脸的位置信息,以及这个人戴面具的方式是正确的、错误的还是根本没戴。绝大多数被贴标签的脸都戴着口罩。

检测人脸

问题的第一部分是检测图像中的人脸,对它们进行裁剪,并准备好用作分类器的输入。

为了检测人脸,我使用了 CV2 的预训练模型,该模型接收图像并返回图像中人脸的坐标。我尝试了他们的许多模型,但我发现“Haar cascode _ frontal face _ alt 2 . XML”最适合戴面具的人。

上面的代码加载 CV2 人脸模型,然后遍历每张图像,找到每张人脸,并将鲮鱼的位置添加到熊猫数据帧中。生成的数据框如下所示:

经过处理的图像和人脸的数据帧。作者图片

CV2 模型经过训练,可以在没有面具的情况下检测人脸,因此它们无法找到每张照片中的每张脸是正常的。众所周知,这些型号还会与不直接面对摄像机的人发生冲突。

在随机图像中寻找人脸。图像改编自面罩检测| Kaggle 数据集

在上图中,绿色方块表示数据集中提供的每个面的位置标签。蓝色的是模型的预测。对于这张特定的图像,模型表现良好,检测到了所有三张脸。

为了验证面部的检测,我查看预测的中心,如果它在数据集中标记的正方形内,我认为预测是正确的。

该模型并不完美,它错过了大约 80%的标记人脸。

在样本图像中查找人脸。从面罩检测| Kaggle 数据集调整的图像

该模型被训练成仅检测正面人脸。在上图中,该模型仅检测到 16 张人脸中的 4 张。尽管性能很好,但我仍然会使用这个模型来检测人脸,我自己的训练超出了范围。

为分类器准备数据

一旦我们确定了每张图像中的人脸位置,我就可以裁剪图像并单独保存每张人脸。然后,在训练分类器之前,我可以重新缩放和整形图像,使它们都一致。

为了裁剪和保存每张脸,我使用了上面的代码。整形和归一化可以使用数据发生器来完成,该数据发生器在训练期间被馈送给神经网络。

人脸面具检测的图像预处理流程。图片改编自面具检测| Kaggle

上面是预处理的图表。我首先使用 CV2 模型来定位面部并裁剪它们。然后我把它们调整到普通大小。在这之后,我还将数据标准化,以便神经网络更容易学*。

预处理图像的 9 个样本。图片改编自面具检测| Kaggle

上述 9 幅图像是分类器的示例输入。该模型将尝试将这些图像中的每一个分类为“面具”、“无面具”或“不正确佩戴”。

面部分类

一旦图像得到处理,我们就可以训练一个分类器来预测每张图像显示的是一个人正确戴着面具、不正确戴着面具还是根本没戴面具。

在图像上训练分类器可能非常昂贵,尤其是为了获得良好的性能。这就是我使用迁移学*的原因:

迁移学*

迁移学*包括采用预先训练好的模型,并根据我们自己的应用进行调整。迁移学*对图像数据模型特别有效。

在用于图像分类的迁移学*中使用的最流行的模型是为 ImageNet 竞赛训练的模型。ImageNet 是一项竞赛,由大公司训练极其庞大的模型,将数百万张图像中的对象分类到 1000 个类别中。

不同架构的性能。下图 CC BY 4.0 来自深度学*讲座【1】

上图显示了模型的性能与其训练成本的关系。我希望在没有 GPU 的本地机器上训练这些,因此我选择了 ResNet-50(图片左上角的粉红色)。该模型取得了很好的性能,训练效率很高。

ResNet-50 是一个真正的巨型模型。它包含超过 2300 万个参数。当它在 ImageNet 比赛时,它被训练将图像分类成 1000 个类别,然而,我的分类问题只包含 3 个类别(面具,没有面具,面具佩戴不当)。因此,我们必须调整模型,以便能够在这个问题中使用它。

所以为了让这个模型适应我的应用,我去掉了神经网络的最后一层,然后加上我自己的;这次输出大小为 3 而不是 1000(因为我想要 3 个类别)。然后,我可以训练这最后一层,而不接触其他层的任何重量。用 2300 万个参数训练整个模型会很昂贵,但因为我只训练最后一层,所以这样做很便宜。

模型总结。作者图片

在上面的模型摘要中,您可以看到该模型有超过 2300 万个不可训练的参数(为 ImageNet 训练的参数)。我正在训练的唯一一层是包含 6147 个参数的最终层。

在这些深度神经网络中,大多数模型试图在输入图像中找到重要的特征,如形状、纹理等。通过改变最后一层,我们使用所有的信息,但只改变最后一部分,使其对我们的应用有用。

在上面的代码中,我使用 Keras 加载了预训练的 ResNet50。模型中唯一可训练的层是最后一层。然后,我可以像训练任何其他神经网络一样训练该模型。

培训和结果

我对最后一层进行了 30 次训练,在没有 GPU 的情况下花了大约 10 分钟。该模型达到了 90%以上的准确率。

训练和验证在训练期间每个时期的损失和准确性。作者图片

正如你在上面看到的,仅仅过了 30 个时期,这个模型似乎就收敛到了一个好的性能。如果没有迁移学*,这将需要相当长的时间。

训练模型在训练数据集和验证数据集上的性能。作者图片

以上是用于训练和验证的混淆矩阵。混乱矩阵可以让你看到模型哪里出错了。验证数据集由前面部分提到的 CV2 模型提取的人脸组成。该模型很好地标记了戴面具和不戴面具的人,在这些方面达到了 90%以上的准确率和召回率。这个模型很难正确地给戴错面具的人贴上标签。

ResNet-50 对口罩分类的预测。图片改编自面罩检测| Kaggle

结合两种模式

我们现在可以从图像中提取人脸,并对其进行预测。让我们来看看模型的表现:

迁移学*模型预测。图片改编自面具检测| Kaggle

面向前方的预测

当图像的主体面对摄像机时,该模型表现得非常好。然而,当对象很远并且没有看着相机时,模型无法检测到任何人脸。

模特在正面人物身上表现很好。图片改编自面具检测| Kaggle

模特在正面人物身上表现很好。图片改编自面具检测| Kaggle

该模型在上面的图像中表现很好,因为图像中的人大致面对摄像机。在左边你可以看到数据的真实标签,在右边你可以看到分类器的预测。

当人们不面对镜头时,模型表现不佳。图片改编自面具检测| Kaggle

然而,当人们不面对相机或离得太远时,该模型无法识别一张脸。

面具佩戴不当

该模型特别擅长检测戴面具和不戴面具的情况,但很难检测戴错面具的情况。

模特努力发现戴错的面具。图像改编自面罩检测| Kaggle

在上面的图片中,左边的女人把她的面具放在鼻子下面,但是模型仍然把它归类为面具。

模特努力发现戴错的面具。图像改编自面罩检测| Kaggle

在上面的图像中,模型正确地识别出戴着错误面具的女人,但是没有看到左边的男人,因为他没有面对镜头。

结论

迁移学*可以让您立即训练出复杂且性能良好的模型。在这篇文章中,我展示了我用来解决面具检测问题的管道。这个问题包括两个关键部分,在第一部分中,我希望检测人们的面部并对它们进行预处理,以便它们可以用作分类器的输入。在第二阶段,我使用迁移学*训练一个分类器来预测这个人是否戴着面具。

模型训练结果令人满意。该分类器运行良好,并且可以检测面具是否被正确佩戴。人脸检测可以改进,它检测到的人脸大部分是正确的,但它很难找到每张图像中的所有人脸。

潜在风险和道德问题

在处理面部识别和其他个人身份信息时,会涉及风险和道德问题。在这些项目中,尊重人们的隐私权是很重要的。我可能会在未来的文章中探讨这个问题的一个解决方案,就是在机器学*模型中使用差分隐私。

在为屏蔽检测模型选择合适的应用时,应该考虑伦理问题。一个潜在的用例可能是计算在健身房正确佩戴口罩的人的百分比,而不是对佩戴不当的人进行罚款。对某人罚款将涉及从图像中确定此人的身份,这引起了伦理问题,因为这些数据可能被恶意使用。正确选择用例是使这些模型安全和合乎道德的关键。

支持我

希望这对你有所帮助,如果你喜欢,你可以 关注我!

你也可以成为 中级会员 使用我的推荐链接,获得我所有的文章和更多:https://diegounzuetaruedas.medium.com/membership

你可能喜欢的其他文章

无监督学*:K 均值聚类

数据可视化理论

参考

[1]https://www . semantic scholar . org/paper/An-Analysis-of-Deep-Neural-Network-Models-for-Canziani-Paszke/9a 786 D1 ECF 77 dfba 3459 a 83 CD 3 fa 0 f 1781 BBC ba 4

基于多模态神经网络的人工智能辅助标注

原文:https://towardsdatascience.com/ai-assisted-annotation-with-multimodal-neural-networks-1c69f5a4017c

反垃圾邮件人脸检测项目的真实数据验证示例

图片由 T umisu 来自 Pixabay

简介

近年来,人们对人脸识别系统进行了大量的研究。因此,这一领域最先进的算法已经达到了相当高的精度。足够体面,可以跨不同行业实施解决方案。

人脸识别系统现在已经成为我们日常生活的一部分,帮助我们完成解锁手机等基本任务。然而,这项技术激起了人们对隐私的担忧,以及政府和大型组织对其使用的争议。

关于人脸识别系统的挑战之一是它们容易受到欺诈攻击。在本文中,您将看到如何为一个人脸反垃圾邮件项目收集和验证数据。

欺骗攻击

有不同类型的欺骗攻击可以用来欺骗人脸识别系统。最常*的包括打印的照片,重播的视频,或者一个戴面具的人。

作者照片

那么,我们如何收集数据来训练反垃圾邮件模型呢?一种快速而经济的收集数据的方式是使用众包*台,如 Toloka

为了这个反垃圾项目的目的,Toloka 被用来收集 3-5 秒钟的人脸视频。来自 50 多个国家的 60,000 多名表演者提交了视频。

作者照片

在数据收集阶段之后,视频被分解成单独的照片,然后发送进行数据验证。

用简单的人工神经网络验证收集的数据

作者照片

最简单的验证形式包括基本检查,如寻找重复、模糊、照明或目标是否确实出现在图片中。然而,一些照片需要更先进的技术来评估照片的质量是否可以接受。

使用多模态神经网络进行高级验证

作者照片

更高级的验证检查点包括检查图像中是否有 Tik Tok 标记,或者该人是否戴着面具或眼镜。也许图片上有水印图像。这种情况需要专门的算法,通常需要特定的训练来发现这些特征。一种替代方法是使用多模态神经网络,如 CLIP,这正是在这个项目中使用的方法。

什么是 CLIP,我们如何使用它来验证图像?

CLIP (对比语言——图像预训练)是一种从自然语言监督中学*视觉概念的模型。然后,它可以应用于任何标准的视觉分类任务,如 ImageNet 分类。它在 ImageNet 数据上实现了与 ResNet100 相同的准确性,尽管它没有看到来自它的任何示例。该模型根据图像及其描述进行训练,如下图所示。

剪辑模型表示,作者照片。

因为模型能够预测看不*的类,我们可以问这样的问题“图像中有来自抖音的文本吗?”或者“图像里有面具吗?”剪辑结果帮助我们识别图像中的某些元素,而无需为我们想要检查的每个特征明确训练模型。

这就是在反垃圾邮件项目的图像集合中实现的内容。但是没有使用一个剪辑模型,而是使用了它的几个变体,然后将结果汇总。

作者照片

上图显示了提示“图像中有来自抖音的文本吗?”的剪辑聚合的可视化效果基于综合决策,图像被接受或拒绝用于项目,并继续进行下一个检查,例如“图像中有掩模吗?“一旦通过所有检查,该项目将被接受。

总结

在本文中,我们研究了如何使用简单的人工神经网络和更复杂的多模态神经网络(如 CLIP)来收集和验证人脸识别项目的数据。更多细节,请看扎哈尔·帕什金的演讲,他是 CFT的计算机视觉工程师。此外,如果您想了解更多关于数据收集和数据验证流程的信息,请加入这个数据赋能社区

PS:我正在 Medium 和aboutdatablog.com上撰写深入浅出地解释基本数据科学概念的文章。你可以订阅我的 邮件列表 每次我写新文章都会收到通知。如果你还不是中等会员,你可以在这里加入https://medium.com/@konkiewicz.m/membership

下面还有一些你可能喜欢的帖子:

* *

人工智能现在可以玩《我的世界》了——离环游世界又近了一步

原文:https://towardsdatascience.com/ai-can-now-play-minecraft-and-is-a-step-closer-to-navigate-the-world-1f19cfe37ef

开放式人工智能的开始

照片由摄影师 Gersamina Donnichi 拍摄

在语言处理(【GPT-3】)和文本到图像生成( DALL E 2 )方面建立了令人印象深刻的模型之后,OpenAI 现在面临着一个可以说是更大的挑战:开放式行动。在解决所谓的人工通用智能(AGI)的伟大任务中,他们意识到语言和视觉不是人工智能应该擅长的唯一领域。GPT-3 和 DALL E 2 在他们所做的事情上非常出色,但是尽管他们很强大,他们仍然被限制在他们虚拟世界的有限范围内。

Sharif Shameem 是 GPT 3 的早期测试者之一。他意识到 GPT-3 可以被提示解决编码任务——这导致 OpenAI 最终开发了 Codex,现在嵌入到 GitHub Copilot 中。他尝试了其他方法让 GPT 3 号站到了边上。其中一项任务是让 GPT 3 号在沃尔玛买一对苹果*板电脑。尽管 GPT 3 号走得相当远,但它无法成功完成指定的任务。语言是一个强大的工具,但它不是绝对的。

GPT 3 号失败了,因为它试图做的事情与一种特殊的能力有关。就像操作计算机和——保持距离——在现实世界中导航一样,在互联网上搜索是一种内在的开放式活动,需要一种当前人工智能所缺乏的智能形式。这就是 OpenAI 现在试图解决的问题,他们已经开始通过模仿人类来教一个 AI 扮演《我的世界》

VPT:开放式学*的开端

《我的世界》是一个开放世界的游戏。这意味着玩家可以做许多不同的事情,执行许多不同的动作,而不必遵循预先定义的路径。它也特别容易玩和理解,这当然有助于使它成为目前世界上最受欢迎的游戏。

这些特点使它成为完美的候选人。YouTube 和其他*台上记录了成千上万的游戏时间。这是一个等待开发的大量训练数据。然而,这些数据集并没有被贴上人类玩家懒得解释如何的标签。他们只展示了什么。如果一个玩家在《我的世界》建了一座房子,你会看到他在做什么——动作——而不是他怎么做的——命令。

OpenAI 几天前在它的博客(和论文)中展示了它的解决方案。视频预训练(VPT),如其名,是一种“半监督模仿学*方法”为了充分利用现有数据,研究人员将学*过程分为两步(他们证明这种方法比单一过程产生更好的结果)。首先,他们在一个小型数据集(2K 小时的《我的世界》视频)中训练了一个名为逆动力学模型(IDM)的神经网络,该数据集带有动作命令标签。这个模型学*从“过去和未来的信息”中预测行动。

打个比方,这就像试图猜测视频中的一个动作,只看到开头和结尾,却看不到中间。了解行动的结果给 IDM 带来了现实世界中不存在的明显优势(即我们知道发生了什么,但不知道将会发生什么)。

第二,IDM 用于标记剩余的 70K 视频小时,并训练一个 VPT 基金会模型(注意:基金会模型这个术语在 AI 社区中仍然存在广泛的争论,并且没有被普遍接受为大型神经网络的默认命名)。完整的 VPT 神经网络然后可以学*使用较大的标记数据集作为训练数据来预测给定的过去帧的未来帧。这为 VPT 提供了一种能力,OpenAI 称之为“行为克隆”——通过看到动作来学*复制动作。

VPT 概述。信用: OpenAI

使用这种新颖的方法,VPT 已经学会了在《我的世界》做一些人类玩家做的基本任务(例如,游泳、吃食物或狩猎),这些任务在以前的解决方案如强化学*(RL)中是不可能的。开放式设置不提供 RL 模型所需的必要约束。例如,国际象棋或围棋已经被 RL 和搜索算法(例如 AlphaZero)的组合所掌握。这是可能的,只是因为设置和规则受到极大的限制。在国际象棋中奖励行动很容易,但在《我的世界》,或者就此而言,在现实世界中就不那么容易了。

VPT 可以通过特定任务的视频进行进一步微调,以指导模型学*复杂的动作,如建造房子所需的动作(这需要制作工具等)。OpenAI 还证明了 VPT 可以成功地用作 RL 方法的先验。VPT 像人类玩家一样“行动”,这使得它“对 RL 来说是一个更好的先验”(即,跟随人类的行动比使用随机行动作为先验更好,就像在 RL 中常*的那样)。

随着大型神经网络的出现,开源倡议在人工智能中的重要性日益增加,作为对开源倡议的认可,OpenAI 决定开放标记的数据、代码和权重,以帮助对这种方法的进一步研究。

VPT 与人类智慧

VPT 是开放式人工智能代理向前迈出的重要一步。它可以超越强化学*,在过于复杂的环境中定义合理的先验,建立具体的奖励,并建立足够好的模拟器来进行 RL 模型所需的无数模拟。

然而,澄清这一新范式仍然远远没有为人工智能提供类似人类的智能是很重要的。VPT 和我们之间的这三个重要差异可以凸显出我们距离 OpenAI 的 AGI 之梦有多远。

模仿 vs 原始动作

众所周知,在认知科学中,婴儿不仅通过观察来学*,还通过模仿来体现他们对他人行为的感知。作为群居动物,我们从很小的时候就在与他人的互动中成长。VPT 在这方面向前迈出了一步。行为克隆恰恰在于复制一个基于动作的过程,并不断重复,直到学会为止。尽管如此,这与 GPT-3 预测下一个令牌的能力没有太大区别,因为它给出了前一个令牌的历史。

虽然模仿是人类早期认知发展的关键,但我们很快就开始自己尝试。我们以独特的方式行动,因为与 VPT 相反,我们有一个游乐场,可以让我们边行动边学*。支配大脑的反馈过程总是接受新信息来更新我们的世界模型。如果一个蹒跚学步的孩子建造了一座砖砌的塔,并推着它直到砖块落下,她将会学到一些关于这个世界的新东西。VPT 在任何意义上都做不到这一点。

虚拟世界 vs 现实世界

VPT 解决开放式虚拟行动问题的方法和自动驾驶汽车解决受约束的现实世界行动问题的方法有一些相似之处。两者都在处理超越感知或语言的行动领域。而且两者都极其有限。自动驾驶汽车——除了没有准备好——旨在以非常具体的目标作为动力来导航世界:从 A 到 B,不接触任何东西,遵守交通规则。虽然如果可能的话非常有用,但它远不及人类驾驭世界的能力。

VPT 驾驭《我的世界》世界的能力同样无法模仿人类的行为。即使视频游戏比国际象棋和围棋复杂得多,但与现实世界相比,它仍然有很大的局限性。VPT 已经学会了一些命令,以及这些命令的有序组合如何导致连贯的行动(尽管连贯是由我们而不是系统本身赋予的)。但是现实世界不是简单的命令就能解决的。我们的大脑使用一套复杂的——也不是完全理解的——过程来处理世界发送的多模态感知,并通过规划和决策将它们转化为行动。这可能不仅仅是规模的问题。我们可能需要一个质量上截然不同的范式来实现我们现在所处的 AGI。

预测 vs 理解

人类对世界的理解很大一部分来自于行动和探索。虽然 VPT 在一个开放的环境中行动,这使它与 GPT-3 或达尔-2 处于不同的类别,但它仍然是一台预测机器。VPT 可以在《我的世界》建房子或者钻石斧子,但是它仍然不知道为什么要这么做。它已经“看到”人类在做这件事,但还不知道这个动作的意义。考虑到人类在游戏中的目标和目的,这有什么关系呢?

视频数据集中人类动作背后的目的和意图隐藏在命令之外。当人类玩游戏或者在世界上导航时,总会有一个更大的计划,这是无法通过观察单独的甚至后续的行动来了解的。VPT 不能进入那个计划。玩家在《我的世界》建造房子,不仅仅是因为他们可以,而是为了有一个避难所度过夜晚,也许以后可以升级成更大的东西。他们用金刚石材料改进工具,以防止它们破裂。如果 VPT 直接去制造一把钻石斧子,那并不是因为它知道其他类型的低质量工具最终会失败。动机和意图对于人类的计划和行动至关重要。我们所做的一切都不是从这些中抽象出来的,而 VPT 缺乏这些。

OpenAI 一直在建设通往它热爱的 AGI 的道路。每一步都值得分析和审视,但我们离那个目标还很远。

订阅 算法桥 。弥合算法和人之间的鸿沟。关于与你生活相关的人工智能的时事通讯。

您也可以直接支持我在 Medium 上的工作,并通过使用我的推荐链接 这里 成为会员来获得无限制的访问权限! 😃

人工智能可以创作出获奖的艺术作品,但它仍然无法与人类的创造力相抗衡

原文:https://towardsdatascience.com/ai-can-produce-prize-winning-art-but-it-still-cant-compete-with-human-creativity-4adbd54cc328

机器人的各种艺术品,由 AI 绘制。作者创建的图像(使用稳定扩散)。

人们认为创造力是人类与生俱来的。然而,人工智能(AI)已经达到了同样具有创造力的阶段。

最近的一场比赛引起了艺术家的愤怒,因为它向一个被称为 Midjourney 的人工智能模型创作的艺术品颁奖。这种软件现在可以免费获得,这要归功于一种叫做稳定扩散的类似模型的发布,这是迄今为止同类软件中最有效的。

创意从业者联盟,如阻止人工智能抢尽风头一段时间以来一直在提高对人工智能在创意领域使用的关注。但是人工智能真的能取代人类艺术家吗?

AI 艺人。阿斯坎尼奥/阿拉米股票照片。

这些新的人工智能模型可以产生无限的可能性。上面显示的每个机器人的图像都是独一无二的,但是都是由相似用户请求的稳定扩散产生的。

有两种方法可以使用这些人工智能艺术家:写一个简短的文本提示,或者在提示旁边提供一个图像,以提供更多的指导。从一个 14 个字的提示中,我能够为一家提供水果的虚构公司产生几个标志创意。不到 20 分钟。在我的中档笔记本电脑上。

一家新鲜水果公司的设计,快速交付,徽标,高对比度,聚乙烯——我用来获得稳定扩散的提示,以制作这些图像。

从上面的结果可以看出,稳定扩散很难创造出包含文字的艺术。有些水果有点臭。

然而,如果不使用人工智能或借助图形设计师的帮助,我根本不可能制作出任何类似的东西。我也不可能自己创造机器人图片。

这项技术的潜力并没有被忽视——负责稳定扩散的初创公司 Stability AI 的目标是 10 亿美元(9 亿美元)的投资评估。但是这些人工智能模型开始对现实世界产生影响,正如获奖的 midway 图片所示。事实上,艾真正擅长的是创作结合不同元素和风格的艺术作品。

然而,虽然人工智能可以为你做大部分的跑腿工作,使用这些模型仍然需要技能。有时提示并不能生成您想要的图像。或者人工智能可以与其他工具一起使用,只是组成更大管道的一小部分。

制作艺术作品不同于制作数字设计。稳定扩散更擅长绘制风景而非徽标

为什么稳定扩散会改变游戏规则

人工智能模型通常被训练使用包含惊人的 58.5 亿张图像的数据集来创建艺术。需要这些大量的数据,这样人工智能才能学*图像内容和艺术概念。这需要很长时间来处理。

对于稳定的扩散,花费了 150,000 小时(刚刚超过 17 年)的处理器时间。然而,通过在大型计算集群(充当单个设备的强大计算机的集合)上进行并行训练,这可以减少到不到一个月的实时时间。

Stability AI 还提供了一个名为 DreamStudio 的在线工具,可以让你以每张图片 0.01 美元的价格使用它的 AI 模型。相比较而言,要用竞争对手 OpenAI 的美术模型, DALL E 2 ,成本是的十几倍

这两种方法使用相同的基本方法,称为扩散模型计算机程序,它通过查看大量现有图像来学*创建新图像。然而,稳定扩散具有较低的计算成本,这意味着它需要较少的训练时间,并且使用较少的能量。

另外,你实际上不能自己下载和运行 OpenAI 的模型,只能通过一个网站与之交互。同时,稳定扩散是一个开源项目,任何人都可以玩。因此,它享受着在线编码社区快速开发的好处,例如模型的改进、用户指南、与其他工具的集成。这已经在 2022 年 8 月《稳定扩散》发布后的几周内发生了。

艺术的未来?

人工智能艺术模型仍然很难正确地绘制手。作者使用稳定扩散创建的图像。

虽然在过去的五年里已经取得了巨大的进步,但人工智能艺术模型仍然有一些问题需要解决。他们作品中的文字是可以辨认的,但经常是胡言乱语。同样,AI 也在努力渲染人手。

还有一个明显的限制,即这些模型只能制作数字艺术。它们不能像人们一样使用油画或蜡笔。就像黑胶唱片已经卷土重来一样,技术最初可能会创造一种新形式,但随着时间的推移,人们似乎总是会回到最初的形式,即最高质量的

最终,正如之前的研究发现的那样,人工智能模型在目前的形式下更有可能成为艺术家的新工具,而不是创造性人类的数字替代品。例如,人工智能可以生成一系列图像作为起点,然后可以从人类艺术家中选择并改进这些图像。

这结合了人工智能艺术模型的优势(快速迭代和创建图像)和人类艺术家的优势(对艺术作品的愿景和克服人工智能模型的问题)。当需要特定的输出时,在委托艺术的情况下尤其如此。人工智能本身不太可能产生你所需要的东西。

然而,创意人员仍然面临着危险。选择不使用 AI 的数字艺术家可能会落后,无法跟上 AI 增强艺术家的快速迭代和更低成本。

原载于 2022 年 9 月 30 日【https://theconversation.com】

人工智能可以向我们展示有意识意味着什么

原文:https://towardsdatascience.com/ai-can-show-us-what-it-means-to-be-conscious-8abe5fff49b0

随着人工智能的发展,我们对意识的理解以及它对人类的意义也将随之发展

拉蒙·萨利内罗在 Unsplash 上的照片

6 月 11 日,谷歌工程师布雷克·莱莫因发布了一份他与 LaMDA 的对话记录。LaMDA 是谷歌的机器学*模型,模仿人类的语言和思维,莱莫因认为它是有知觉的。

虽然一致认为 LaMDA 在获得知觉之前还有一段路要走,但我们可以从中学*很多东西。

探索人工智能模型如何思考可能是意识秘密的关键,使我们能够解释为什么它存在于我们的大脑中。

在其历史的大部分时间里,意识被认为是一个最好留给哲学领域去研究的领域。鉴于其精神本质,神经科学和技术似乎不可能解决这样一个话题。但是,近几十年来,我们已经看到了这一点。

研究人员现在认识到意识是与物质大脑本身纠缠在一起的东西,从它的形而上学起源转变而来。我们已经转向以科学方法研究意识,现在我们甚至有办法在实验室里测量意识。

神经科学旨在解决的问题被称为意识的简单问题。它询问大脑的哪些部分引起意识,以及这些部分的哪些变化会影响意识。

但是还有另一个被称为意识难题的问题。哲学家 Ned Block 提出了这个问题,并质疑为什么意识与我们的大脑有联系?为什么我们将意识作为人类经验的一部分?我们大脑的结构和过程是什么导致了对世界的复杂体验?

这些问题需要一个非人类来回答。

用人工智能理解意识

在构建人工智能模型时,研究人员一直致力于让它们具有自我意识。他们多年来一直致力于创造能够像人类一样处理信息和思考的系统。但是,无论我们如何像人类一样建立一个系统,意识似乎总是我们尚未克服的障碍。

要回答意识这个难题,我们不能再从人类开始了。有太多的变量来总结自我意识和意识。

人工智能允许我们从头开始。我们观察不同种类的机器人,分析它们的行为,观察我们称之为类意识的行为。这带来了一种以研究为基础的哲学趋势,这种趋势依靠证据来为哲学问题提供答案。

但不仅仅是理解意识是什么,人工智能还在帮助我们理解意识不是什么。

人工智能中的反证意识

听到莱莫因声称 LaMDA 是有知觉的,许多研究员同事正确地指出 LaMDA 的整个目标是含蓄地表现出有意识。

谷歌的工程师创造了 LaMDA 来模拟人类的对话,其中很多都是关于感觉的话题。从关于天气的谈话到关于关系和故事的细节,人类的交流是建立在意识和感受感觉和情绪的能力上的。所以毫不奇怪,这是 LaMDA 优先考虑并擅长的品质。

围绕 LaMDA 的论述向我们表明,意识不仅仅是交流。这被更早的神经科学实验进一步证实,如裂脑程序。

在经历大脑分裂的人中,大脑左右半球之间的连接被切断,导致个体身体的左右部分独立行动。大多数时候,这些个体的行为都很正常,但在某些实验条件下,很明显,只有大脑的左半部分可以通过语音进行交流,而右半部分则保持沉默,并努力进行交流。

这是否意味着那个人的大脑只有一半是有意识的?显然不是,所以意识不仅仅是交流。

随着我们迭代人工智能模型,并使它们越来越好,我认为我们将到达一个必须做出艰难决定的时刻。我们有两个选择:

承认 AI 变得有意识有自我意识。

如果我们承认这一点,我们将需要面对这样一个事实,即意识不再是人类独有的东西。现在有一种无机生命形式与我们共享这个星球,并拥有我们所有的认知和意识。

一旦我们接受了这一点,我们就能更好地了解自己。能够复制某些东西是理解它的第一步,理解是什么导致人工智能模型中的意识产生,将比单独的测试和研究更能教会我们更多关于我们自己的心理。这对神经科学、哲学、心理学、计算机科学,以及任何其他处理现代意识问题的领域都是一个福音。

否认人工智能已经变得有意识和自我意识

但是如果我们否认人工智能是有意识的,我们可能需要否认人类也是有意识的。在某一点上,人工智能可以做人类大脑能够做的许多事情,如果我们否认机器人表现出的特征是意识的证据,我们也将不得不否认同样的特征是人类意识的证据。

如果一个人工智能模型发展了反思自己思想的能力,并拥有自我认知,我们说这不是意识的证明,那么我们就不能再说自我反思是我们意识的证明。

最终,机器人将达到这样一个地步,它们拥有我们如此多的能力,我认为任何人都很难在不损害我们认为使我们成为人类的因素的情况下争辩人工智能模型没有意识。

人工智能及其发展带来的哲学问题比预期的要早得多。这些都是我们需要回答的问题。在那之前,我们从这些不可思议的发明和发展中学*。

如果你喜欢我的作品并想阅读更多,可以考虑通过我的推荐链接加入 Medium。你每个月可以阅读无限量的故事,一小部分会员(无需额外费用)支持我。

人工智能聊天机器人让一切变得简单,礼貌

原文:https://towardsdatascience.com/ai-chatbots-made-easy-courtesy-rasa-8ecdc2853e66

使用 RASA & Python 构建板球聊天机器人的分步指南

在本文中,我们将使用 RASA 框架构建一个简单的板球聊天机器人。本文的重点是理解 RASA 的基础知识,并展示一个人可以多快地开始使用一个工作机器人。

图片:来自 Pixabay

RASA 是什么&为什么

什么是 RASA?

RASA 是一个开源工具,它使用自然语言理解来开发基于人工智能的聊天机器人。它提供了一个框架,可以用最少的编码技巧创建聊天机器人。RASA 允许用户通过各种配置来训练和调整模型。它的易用性使其成为全球开发者创建行业级聊天机器人的热门选择。

为什么是拉莎?

  • 这是一个开源的免费框架
  • 开始很容易
  • 构建一个基本的机器人不需要预先的编码知识

RASA 框架

任何聊天机器人都必须执行两个主要活动,首先必须理解用户想要说什么,然后为用户提供有意义的响应。RASA 使用 RASA NLU 和 RASA 核心来实现这一目标。

拉萨 NLU &拉萨核心(图片由作者提供)

理解术语

常用术语(图片由作者提供)

目的

  • 意图是从消息中识别用户的意图
  • 意图分类为用户消息分配一个标签

实体

  • 实体抽取从用户消息中提取有用的信息
  • 在训练数据中处理常*的拼写错误和同义词

样本意图识别&实体分类(图片由作者提供)

反应

  • 响应或模板是机器人响应的消息
  • 可以为单个响应类型定义不同的文本消息,这样机器人就不会向用户发送重复的消息

行为

  • 动作定义了机器人如何响应用户。它可能是一个简单的文本响应,也可能是向用户提出一个问题
  • 自定义操作也可以用一段代码来定义。它通常用于文件查找或进行外部 API 调用

狭槽

  • 插槽就像机器人中的内存位置
  • 它用于存储对话期间需要的字段

形式

  • 表单用于从用户处收集多个数据点
  • 它使用插槽来存储用户输入

使用 RASA 构建聊天机器人的步骤

  1. 安装和初始化
  2. 创建用户流
  3. 从外部 API 读取
  4. 构建用户旅程
  5. 使用 CLI 进行培训和测试
  6. UI 集成

在这个例子中,我们将构建一个基本的 cricket chatbot,它连接到一个外部 URL 来获取实时 cricket 数据。

蟋蟀聊天机器人(图片由作者提供)

步骤 1:安装和初始化

建议在单独的虚拟环境中安装 rasa,因为它有许多依赖项。使用 pip 命令安装 rasa。

pip install rasa# Check the rasa version
rasa --version

本教程中使用了 rasa 3.1.0。现在 rasa 已经安装好了,我们可以开始了。Rasa 提供了一个基本的样例项目。在新的项目文件夹中,运行下面的命令来设置项目。

rasa init

这将创建一个样例项目,其中包含运行一个基本聊天机器人所需的所有文件。初始化后的目录结构如下所示。

默认 RASA 目录结构(图片由作者提供)

步骤 2:创建用户流

对于用户流,有两个主要文件需要更新——nlu . yml 和 domain.yml

nlu.yml 文件包含用户可能输入的所有可能的消息。用户可以为该文件中捕获的相同意图提供不同形式的输入。

板球聊天机器人nlu . yml 的样本内容(图片由作者提供)

domain.yml 文件类似于主文件,包含有关用户意图、机器人响应、插槽、表单、动作等信息。

板球聊天机器人的示例 domain.yml

步骤 3:从外部 API 读取

如果需要任何外部 API 调用来获取数据,这是一个可选步骤。

在示例 cricket chatbot 中,使用 API 从外部源获取 cricket 数据。

actions.py 文件用于与外部 API 进行交互。在板球聊天机器人中,我们将使用 cricketdata api 服务。这项服务每天提供 100 个免费请求,足以构建聊天机器人的演示版。

cricketdata.org注册获取 api 密钥。使用 actions.py 文件中的 api 键连接到 url 并获取数据。

这个板球聊天机器人定义了两个动作。一个动作是获取所有最近举行的比赛的结果。另一个动作是获取即将到来的比赛的列表,要么是为插槽中设置的特定球队,要么是为所有球队。

定义了使用外部 api 获取最近匹配结果的操作

定义了使用外部 api 获取即将到来的匹配的动作

获取数据的代码更新后,需要启动 actions 服务器,这样 chatbot 就可以调用获取外部数据所需的端点。默认情况下,操作服务器在端口 5055 上启动。

注意:应该在 endpoints.yml 文件中设置操作服务器 url

action_endpoint:
  url: "[http://localhost:5055/webhook](http://localhost:5055/webhook)"

现在用下面的命令在其中一个 shells 上启动操作服务器。

rasa run actions

为板球聊天机器人定义的动作(图片由作者提供)

步骤 4:构建用户旅程

stories.yml 文件中更新了各种可能的用户旅程。开心和不开心的经历都可以更新。添加更多的故事将增强聊天机器人处理不同用户流的能力。

板球聊天机器人的示例故事(图片由作者提供)

步骤 5:使用 CLI 进行培训和测试

模型使用的组件和策略在 config.yml 文件中定义。如果该文件中未设置“管道”和“策略”, rasa 将使用默认模型来训练 NLU 和核心。

rasa train

使用默认组件的 rasa 训练(图片由作者提供)

训练完成后,模型将存储在 models/文件夹中。既然模型已经训练好了,我们就可以测试聊天机器人了。要在命令行上运行 chatbot,请使用以下命令。

rasa shell

shell 提示符下与机器人交互的示例(图片由作者提供)

在任何时候使用/stop 退出机器人

在 shell 提示符下停止 bot(图片由作者提供)

步骤 6:用户界面集成

聊天机器人可以作为聊天工具集成到任何现有的网站上,或者可以与脸书、Slack、Twilio、Webex、Mattermost 等应用程序连接

对于这个例子中的板球聊天机器人,我们将使用 slack 与聊天机器人进行交互。如何配置 slack 的详细信息可在此处获得: rasa — slack integration

由于 slack 将无法访问本地主机 url,因此使用 ngrok 来获取聊天机器人的公共 URL。设置 ngrok 的详细信息可在此处获得: ngrok-setup

一旦 slack 和 cricket 聊天机器人之间建立了连接,就可以使用 slack 通道开始与机器人聊天。

聊天机器人集成到 slack 的样本(图片由作者提供)

RASA —附加组件

除了到目前为止解释的基本概念之外,RASA 中还有其他几个可用的特性。本节将介绍几个有趣的可用附件。

创作互动故事

创建故事的另一个选项是使用 rasa 交互模式。此选项可用于调试项目或添加新故事。

rasa interactive

与 rasa 互动构建故事的示例(图片由作者提供)

一旦构建了用户场景,现有的配置文件就会用新的条目进行更新。

使用 rasa interactive 更新配置文件(图片由作者提供)

聊天可视化

默认情况下,当模型在交互模式下学*时,可以使用以下 URL 来可视化这些故事。

http://localhost:5006/visualization . html

以互动模式训练的故事样本(图片由作者提供)

源代码

样本 cricket 聊天机器人的完整源代码可以通过以下链接获得: cricket_rasa_chatbot

结论

RASA 非常容易设置,您可以快速开始使用自己的个性化聊天机器人。一旦开始,就不应该停止。这篇简短的教程仅仅触及了冰山一角。RASA 文档非常全面,非常方便用户使用。

点击这里探索&利用其他令人兴奋的可用功能。
聊天愉快!!😃

AI 可以从这三个领域学到一两件事

原文:https://towardsdatascience.com/ai-could-learn-a-thing-or-two-from-these-three-fields-9aaf90f21f4c

随着人工智能系统不断从周围世界产生的数据中学*,它们的创造者也必须如此。照片由 Unsplash 的 Aideal Hwa 拍摄。

众所周知,人工智能(AI)领域充满了丑闻、偏*和限制。也不乏解决这些问题的尝试,无论是来自技术、数学、伦理,甚至是设计。越来越清楚的是,这些问题永远不会有一个放之四海而皆准的解决方案,与其试图重新发明轮子,该领域可以从利用现有的走向以人为本和包容性的运动和趋势中受益匪浅。

数据女权主义——参与

从广义上说,参与意味着参加某事。利益主体参与人工智能领域的一个重要好处是更均匀地分配决策权,并在受技术或干预影响的各方中拥有有影响力的声音,特别是那些经历“结构性压迫”或“系统性劣势”的各方。“参与”是指任何人在任何时候出于任何目的参与某项活动;作为一个术语,它是非特定的。虽然该术语经常用于人机交互和设计领域,但它用于描述广泛变化的参与度,对于利益相关者和设计/开发团队来说,甚至在不同的用户组之间,这种参与度通常是不*等或不对称的,形成了不对称的协作模型

数据女权主义超越了性别不*等,专注于公*和有意义地参与整个技术生命周期。照片由拍摄,那是她的事来自 Unsplash

在记录和分析参与性活动发生时研究人员和参与者之间互动的实际效果方面也做得很少。另一方面,通过使用包容性和多样性的框架,目标变得面向建设一个环境,在这个环境中,具有不同背景和经历的人感到舒适,并被赋予足够的权能,能够有意义和有效地参与。参与还可以实现价值敏感性,因为让利益相关者参与进来是理解他们的价值并允许他们做出反映这些价值的决策的唯一途径。它避免了同质的创作者群体做出假设和决定,他们可能会成为特权风险和隧道视野的牺牲品。

跨学科研究——跨学科合作

尽管在全球范围内有许多跨学科的呼吁,但让跨学科工作成为热门话题已经有很长时间了。虽然“跨学科研究”一词最早出现在 20 世纪,但有证据表明,与古埃及和古希腊一样古老的文明参与了跨学科的工作和研究。任何活动都可以被描述为跨学科的,只要它使用的工具、知识或框架跨越了两个或更多的学科;其中,一个学科是一个学术领域,它有自己生成知识、提出问题和寻求答案的既定方式(即,它自己的工具、框架、模型、术语等等)。通过利用不同且通常不相似的学科的知识、技能、工具和框架,跨学科团队能够更好地解决和回答跨学科的问题,而单科专家不具备独自解决问题所需的知识。创建基于人工智能的系统是一个高度跨学科的过程,涉及几个科学领域,如数据科学,数学,计算机科学,物理学。然而,不可忽视的是,需要与社会科学家、领域专家、用户和设计专家进行跨学科合作,以获得这些系统的维度和影响的真正整体视图。

跨学科合作是一个强大的工具,可以帮助弥合学科工具和理解之间的差距,并建立一个更强大、更团结的整体。来自 UnsplashVardan Papikyan 摄影。

无数人呼吁为基于人工智能的系统引入跨学科、参与式的设计过程,特别是在帮助解释和透明将价值观嵌入这些系统、提供问责制以及减轻由几个级联偏差和限制引起的下游伤害方面。也有人呼吁在整个人工智能管道中进行协作,包括数据创建和选择,而不是让设计师在前端或过程的开始,工程师在后端。事实上,有人说,打击现有的结构和数据偏*蔓延到人工智能系统的唯一方法是远离定制的、纯技术的解决方案,并使用开放的建设性对话、合作和集体反思来弥合利益相关者愿景和实际实施之间的鸿沟,并检查人工智能系统正在使用的更广泛的社会文化背景的更广泛框架,并让所需的声音以有意义、有影响的方式提供他们的输入。

这些呼吁和建议强调了以人为中心、对价值敏感的人工智能系统是通过多元化参与和跨学科合作构建的。

软件工程——非功能需求和文档

展望软件工程领域,出现了几个重要的教训。

利用非功能需求

需求规格说明是抽象的、更高层次的概念(在软件工程中以非功能性需求的形式出现)和工程师可以实际实现的具体需求之间的重要桥梁。这些非功能性需求可以被认为是用户价值和优先级以及其他社会技术元素和约束的同义词;技术领域中通常被忽视的因素。

将非功能性和基于价值的需求与功能性需求一起操作的实用方法,对于创建更加以人为中心的人工智能系统大有帮助。照片由来自 UnsplashJoan Gamell 拍摄。

从利益相关者收集的高级非功能性需求开始,这些需求通常被重新组织为“质量目标”,然后以“质量因素”的形式提取潜在的价值,这些价值被量化为“质量标准”,最终使用“质量度量”进行测量。例如,用户可能表示他们希望系统在任何需要的时候都保持在线。这种非功能性需求将转化为质量目标,即系统应该对用户始终在线。潜在的质量因素将是“可靠性”,质量标准可能是让系统在 99%的时间内在线,所使用的指标可能是服务器在一年内离线的时间(这应该是<1%). By following this series of translations and conversions, ambiguous stakeholder statements can be transformed into quantifiable metrics and well-defined desired outcomes across managerial, design, and implementation levels.

This specification process can help address calls for operationalizing abstract chosen qualities and values into measurable, actionable steps and metrics, and “从原则到实践)当涉及到基于人工智能的系统时,以及该领域内发布的道德准则和建议因过于理论化和难以实施而受到的批评。关键是将度量标准转化为具体的目标和结果,否则这些度量标准就是理论上的构造,无法量化,甚至无法观察到。

气密文件

人工智能系统构建方式的巨大局限性之一是缺乏透明度。这部分是由于对所产生的学*和知识以及贯穿其中的设计决策的过度技术性和/或有限的文档化和反思。文档的缺乏会导致数据丢失,以及对团队角色、预期结果和正在发生的过程的混淆——尤其是在跨学科的环境中。另一方面,文档提供了团队理解的共享表示,以及一个参考点,并且可以增量地和协作地创建,这使它成为一个非常有用的工具。因此,关注文档阶段,或者在整个过程中作为文档本身的工件的生产,是非常重要的。在基于人工智能的系统的背景下,文档被发现增加了透明度和可解释性,帮助创作者理解所涉及的各种利益相关者的不同需求,反映和证明所做的不同决定,弥合人工智能伦理和实践之间的差距,并将整个人工智能生命周期包含和统一在一个工件中——将文档变成有形的工件和过程本身。

让人工智能系统更加以人为本和对价值更加敏感是一项具有挑战性但至关重要的工作。来自 UnsplashAlexander Sinns 摄影。

将这一切结合在一起

人工智能领域及其设计过程可以从其他领域和当前趋势中学到一两件事。通过关注:

  1. 有意义和公*的参与(数据女权主义),
  2. 支持并优先考虑跨学科合作(跨学科研究),
  3. 捕捉和操作人们的价值观和优先事项(软件工程),以及
  4. 维护文档透明度(软件工程)

该领域可以通过使用来自隔壁的屡试不爽的方法来解决其当前的几个缺点。

我适合的地方

当前的现实是,人工智能系统悬而未决,有可能变得更加孤立、排外和复杂;或者开放,变得更容易接近和包容,这是我博士项目的灵感来源。我正致力于创建一个参与性的过程,以及一个支持它的工具包,在人工智能的整个生命周期中系统地让人们参与进来——重点是价值敏感性。

你可以在伦敦帝国理工学院网站上查看我的项目的官方页面。你也可以看看我写的另一篇解释我博士项目的细节的文章。

我建立了这个媒体账户来发布我在博士项目中的有趣发现,希望以一种任何人都可以理解的方式传播关于人工智能系统的新闻和信息。如果你喜欢这篇文章,那么请考虑跟随我发布新的东西,并请喜欢和分享!

人工智能新兴技术值得关注

原文:https://towardsdatascience.com/ai-emerging-technologies-to-watch-c91b8834ddd9

通过新颖的软件和硬件技术改变人工智能的使用

佛罗里达州威尼斯海滩图片由作者提供

介绍

我有幸在英特尔参与的最激动人心的项目之一是领导工程团队设计、实施和部署软件*台,该*台支持基于哈瓦那高迪处理器的 MLPerf 大规模培训。我学到了很多关于如何在大型硬件集群中扩展人工智能培训的知识,以及构建数据中心的挑战。最突出的一点是,驱动这样一项计算密集型工作需要大量的硬件、人力和电力。

现代 AI/ML 解决方案已经表明,给定大量的计算资源,我们可以为复杂的问题创建惊人的解决方案。利用像 DALL EGPT-3 这样的解决方案来生成图像或创建类似人类的研究论文的应用程序确实令人兴奋。

当我在度假时(*上图),我花了一些时间思考过去几年中模型参数大小的爆炸,以及计算加速器如何快速跟上。我发现了这个帖子,大型语言模型:新摩尔定律?,来自 HuggingFace 的人们,我觉得他们很有趣,特别是因为他们比我更了解深度学*模型。

我发现他们与摩尔定律的比较特别恰当,摩尔定律假设晶体管数量和计算能力每两年翻一番。我想到的另一个类似的类比是,在 20 世纪 90 年代末和 21 世纪初,CPU 频率升级竞赛是如何进行的。在这两种情况下,计算硬件增长迅速(甚至呈指数增长),但最终开始遇到众所周知的瓶颈。

HuggingFace 的文章描述了如何减少将模型投入生产所需的计算量。这些是非常重要的技术,但我认为同样重要的是找到更有效地解决相同问题的替代方法。就像当 CPU 频率达到极限时,计算机行业转向关注并行性/每周期指令数(IPC)/等。过去十年的 AI/ML 工作已经向我们展示了一些可能的例子,现在的问题是我们能否使用不同的、更优化的技术提供相同的解决方案。

一些有趣的竞争者

显然,我并不了解这个领域正在进行的所有研究,我也不会自称了解,所以这里列出了一些有趣的技术,它们至少在各个领域提供了一些希望。与其深入研究并试图重现人们已经完成的一些伟大的工作,我主要是试图涵盖我们何时可以使用这些技术来解决可能也映射到 AI/ML 领域的问题。

相似性搜索

相似性搜索是一种近似的最近邻(ANN)算法,可用于识别将大向量作为输入的数据组。它采用这个向量和相似向量的现有数据库,并试图识别数据库中的哪些向量最像输入向量。最酷的是向量可以是任何东西,所以相似性搜索的应用可以很广泛。例如,它可用于确定某些数字化资产(图像/声音等)是否与其他资产相似。

为了更好地描述如何利用相似性搜索以及新技术如何提供良好的准确性和良好的功耗,请查看这篇文章:

https://www.linkedin.com/pulse/power-intel-hardware-billion-scale-similarity-search-mariano-tepper/

多模态认知人工智能

顾名思义,多模态认知人工智能是一个试图采用存在于各种空间中的解决方案,并将它们相互逻辑组合以提供上下文的领域。这使得将大量训练有素的模型结合起来提供更好的解决方案成为可能。我也一直在考虑这个问题,想知道这是否为一些更小、更不准确、计算密集度更低的模型打开了大门,这些模型可以在解决方案中得到利用,而以前如果没有上下文,它们可能不够准确。老实说,我不确定,我很想听听更多领域专家对这个想法是否有意义的看法…

有趣的是,就在我准备发表这篇文章的时候,英特尔的 VL 解释器在 IEEE/CVF 计算机视觉和模式识别国际会议(CVPR) 2022 活动上获得了最佳演示奖!这个工具帮助我们理解视觉语言转换器的行为。

https://github.com/IntelLabs/VL-InterpreT

神经形态计算

神经形态计算可能是这三种方法中我最喜欢的,可能是因为它有硬件组件,也可能是因为在我看来它是 AI/ML 建模的另一个阶段。

20 多年前,当我在大学时,我第一次了解了神经网络,这是深度学*算法的主要构建模块之一。这个概念在当时是有意义的,离散层通过节点/层内的连接和数学运算相互传递信息。当在教科书中被描述为类似于大脑如何工作时,我接受了它的表面价值。

神经形态计算的酷之处在于,它使用硬件来更准确地模拟神经系统中神经元的工作方式。神经形态芯片没有集中的共享存储和内存,而是有几个独立的内核,它们有自己的存储和本地内存。内核完全相互连接,这允许内核之间的无数通信流。此外,用于神经形态计算系统的算法可以考虑各种输入因素,包括例如输入随时间的速率或尖峰间隔。

鉴于这是一种相对较新的解决问题的方法,它需要一些新的编程范例。作为硬件研究领域的领导者之一,英特尔已经开源了一个名为 Lava 的软件框架,以帮助程序员利用硬件功能。Lava 支持类似深度学*的算法,以及其他类型的算法。

神经形态计算的一个潜在的巨大好处是,这种硬件通常可以以极小的功耗为人工智能领域的一些问题提供解决方案。有很多工作要做,但这一领域的初步工作非常有趣,非常有前途。此外,神经形态计算可以为通过传统计算方法不容易解决的问题提供解决方案。这不仅仅是一种人工智能硬件优化,而是一种全新的思考计算的方式。

这里的第一个链接是一个非常棒的资源,他们有一个非常好的概述,还有一些研讨会,有一些非常容易理解的概述和深入的视频。

https://intel-ncl.atlassian.net/wiki/spaces/INRC/overview?homepageId=196610

结论

在 AI/ML 领域有许多令人兴奋的研究领域,它们似乎有助于创建需要更少计算能力的更有效的解决方案。计算密集型人工智能/人工智能将永远有一个空间,大量的工作表明了这个空间可以提供的结果的可能性。

然而,随着模型变得越来越大,我们在准确性和可训练性方面达到收益递减点,解决类似问题的新替代方法变得越来越成熟,这些方法需要更少的大规模计算。

相似性搜索、多模态认知人工智能和神经形态计算都是这种方法的例子,我很乐意听到我应该检查的其他新方法,请在评论或 Twitter 上告诉我!

**Want to Connect?**If you want to see what random tech news I’m reading, you can [follow me](https://twitter.com/tonymongkolsmai) on Twitter.Tony is a Software Architect and Technical Evangelist at Intel. He has worked on several software developer tools and most recently led the software engineering team that built the data center platform which enabled Habana’s scalable MLPerf solution.Intel, the Intel logo and other Intel marks are trademarks of Intel Corporation or its subsidiaries. Other names and brands may be claimed as the property of others.

人工智能、ESG 和炼油:3 如何成为 1 的一部分

原文:https://towardsdatascience.com/ai-esg-and-oil-refining-how-3-can-become-part-of-1-ac5577583168

思考三个有趣世界的交集和对未来的展望

迈克·什切潘斯基在 Unsplash 上的照片

TL/DR:随着炼油厂追踪他们的环境足迹,碳排放将成为运营计算的一部分,目前经济和物流因素在很大程度上扮演着唯一的角色。人工智能也将有助于减少碳足迹,但这里的情况更加微妙。

在我职业生涯的第一个十年,我使用从基于 Excel 的计算到更复杂的机器学*等数据和工具来优化炼油和石化流程,现在我的工作重点是增加环境、社会和治理(ESG)要求对公司的影响。当考虑数据和分析在帮助公司满足这些要求方面所扮演的角色时,我想思考一下对环境绩效和数据的关注如何重塑炼油业。

我们将首先回顾炼油厂目前用于优化生产的方法,然后评估增加对“E”的审查会如何影响这种方法,最后开始探索数据和机器学*所起的作用。我要强调的是,这些主题非常复杂,值得单独撰写文章,而我主要选择突出前两个主题中的关键点。第三个——数据和机器学*扮演的角色——将是另一篇文章的主题。这篇文章包含了我的想法,而不是现在或以前的雇主的想法。

在开始之前,为什么要在这个考虑上投入这个时间和空间?因为 ESG 的日益突出意味着它正在理所当然地侵入运营考虑,因为公司意识到投资者对 ESG 表现的关注意味着他们需要修改传统方法以实现利润最大化。这不仅是维持它们声誉的关键,也是维持它们经济状况的关键,例如,通过降低借贷成本正如 MSCI 链接文章中概述的那样。

H 炼油厂目前如何实现优化?

照片由 Tasos MansourUnsplash 上拍摄

一个炼油厂寻求在约束条件下最大化输出产品和输入原料之间的利润。这是一个优化问题,目前由精炼厂使用一些精炼厂称为“LP”的商用软件来解决,因为这些优化问题过去很大程度上可以通过传统的线性规划来解决。本文将使用术语“LP will 将有以下具体输入:

  • 输入原料通常包括炼油厂可能从世界任何地方购买的各种原油。这些原油具有不同的质量,影响炼油厂的限制、产品规格,其定价水*既反映了其独特的属性,也反映了更大的宏观经济因素
  • 产品包括炼油厂出售的任何东西;这不仅包括汽油/柴油/喷气燃料等汽车燃料,还包括沥青等产品的组成部分。LP 将像对每种原油一样对每种产品定价
  • 限制解空间的约束。这些包括原油的可获得性,例如,是否只有这么多原油可以通过炼油厂购买或加工?、需求限制以及精炼厂内的限制。这最后一类的例子很多,可应用于单个装置的生产能力、管道冶金、用于将原油转化为最终产品的化学催化剂的健康状况等。

炼油厂将根据上述限制优化产品、原油和其他运营成本之间的利润。这种数学优化之所以可能,是因为炼油厂的线性规划具有数千个方程和变量,这些方程和变量将约束条件和产品与原油质量联系起来,因此线性规划可以准确预测原油选择和/或产品布局对炼油厂运营的影响。或者,如果设置了炼油厂约束条件,那么 LP 将在这些约束条件内找到原油选择和/或产品布局的最佳组合。

这些都是复杂的话题,网上有大量的参考资料——这里有一个的例子。就本文而言,可以说 LP 将根据供应链和经济变量的组合来选择原油和销售产品。下面是总结刚才讨论的概念的示意图:

图 1——传统炼油厂低压系统示意图

H

当使用其 LPs 分析原油选择和产品布局时,炼油厂将在所有 3 个范围内纳入其碳排放。

这里有一些背景:当我说碳排放时,我指的是二氧化碳(CO2)和甲烷(CH4),当我谈到范围时,我指的是温室气体议定书(GHGP)将排放分配到范围 1、范围 2 和范围 3。关于这个话题,网上有太多的信息——这里有一个例子——现在可以说,范围 1 的排放是记者拥有的资产的排放,范围 2 的排放是由购买的公用事业间接造成的,范围 3 的排放是由记者供应链中的其他实体间接造成的。

炼油厂如何将排放评估纳入 LP?有几种方法可以做到这一点,下面列出了其中的两种:

  1. 为排放的 CO2 和 CH4 创造产品并指定负价格,因此 LP 将这些排放视为成本。通过这种方式,LP 将为那些导致高 CO2 排放和/或 CH4 排放的炼油厂操作、原油选择和/或产品布局分配成本。
  2. 为炼油厂产生的排放设定一个上限作为约束

我应该强调,这些都是了不起的成就。正如这篇工作帖子中所述,推导出支持 LP 的正确方程是一项复杂的工作,需要正确的过程数据和对精炼操作的透彻了解。通过方程式将排放量与上述各种炼油厂输入量联系起来是非常困难的,必须小心谨慎地进行,以实现最佳的相关性,从而最大限度地提高预测的准确性。

也就是说,在炼油厂的 LP 中建立碳成本代表着成功地包含了链接中列出的外部性这是一个重大的转变,因为 LP——以及炼油厂的运营——现在将为原油选择、产品布局和炼油厂运营提供信息,从而最大限度地减少二氧化碳排放。

这对炼油厂意味着什么?

  • 这意味着原油选择不再纯粹是价格和炼油厂限制的函数——原油的“肮脏度”或其每桶排放量现在将成为炼油厂选择原油的一个因素,其确切影响程度与选择的价格相关。
  • 落基山研究所的这篇文章包括一张图表,展示了各种类型原油的肮脏程度——虽然历史上更脏、更重的原油更便宜,运行更多这些原油一直是炼油厂投资的动机,但二氧化碳排放现在将影响这些类型的决策。正确的原油选择有助于减少范围 1 排放和范围 3 类别 1(购买的货物和服务)排放。
  • 炼油厂以前将减排项目视为“必须做的事情”,预计不会产生任何经济价值,现在,测量实现的 CO2 减排并使用 LP 中相应的 CO2 价格可以为这些项目创造收入。炼油厂现在将清楚地看到的经济价值,这是通过减少他们的范围 1 排放而认识到的。

以下是炼油厂 LP 的新视图:

图 2 —包含 ESG 的炼油厂 LP

最后,机器学*如何融入到这个讨论中?

照片由 h heyerleinUnsplash 上拍摄

通过建立机器学*模型,利用资产和生产数据预测排放,并帮助避免炼油厂危险带来的安全风险,我相信人工智能是炼油厂了解和管理排放因素的工具包中的一个重要组成部分。

有许多资源涵盖了这一主题,以下来自碳氢化合物处理创新的文章仅提供了一些例子;这保证了我目前正在撰写的一篇文章,这篇文章回顾了一些令人兴奋的使用人工智能的机会,但是有一些警告集成了早期围绕 LP 和 ESG 的讨论。下面是一个概要,稍后将提供更多详细信息:

  • 由于炼油厂传统上使用 LP 来优化运营,当要求利益相关者采用新的工具和技术时,例如由机器学*支持的基于网络的应用程序,将会遇到阻力。这将需要炼油厂 LP 用户和其他利益相关方的开放性和灵活性,以及教育和培训人员的变革管理计划,从而让他们有信心使用这些新工具。
  • 虽然人工智能有可能改善炼油厂的成本和排放状况,但其高计算需求会在内部或云中造成大量电力使用——这篇谷歌人工智能博客文章谈到了正在进行的努力,以最大限度地减少对范围 3 排放(范围 2,如果是内部存储)的影响。人工智能模型也占用存储空间,伴随着能源需求和排放。
  • 炼油厂 LPs 还需要计算来运行用于求解 1000 个方程的算法,以达到最佳结果;这些计算资源需要电力。LP 型号可能高达数千兆字节(GB ),因此会产生自己的电力消耗和范围 3 排放足迹(范围 2,如果是内部存储)。

数据和分析在以 ESG 为中心的炼油厂中扮演的角色将是我下一篇文章的重点。

人工智能伦理:算法个性化的冲突视角

原文:https://towardsdatascience.com/ai-ethics-conflicting-visions-of-algorithmic-personalization-d04a2e06c0f9

意*

人工智能伦理:算法个性化的冲突视角

个性化作为最佳控制或人类解放的工具?

Unsplash 上由 Kalea Jerielle 拍摄的照片

在具有讽刺意味的转变中,适应性网络Web 2.0 技术所承诺的自我表达、自由和互利合作已经被企业一边倒地吸收了。在这个过程中,经济理论中有争议的假设被引入到个性化研究中,很少受到批评性的反对。

从表面上看,个性化是一套技术,旨在过滤无关信息,并提供适合个人品味和需求的建议。但是,脸书、谷歌和亚马逊等商业*台上的个性化越来越多地通过工程优化和控制的镜头来想象(我在这里讨论基于强化学*的个性化的控制含义)。此外,在创新和创造性破坏的技术要求的催化下,大型企业*台通过自私自利的竞争新自由主义经济逻辑来实现个性化。

将工程形式主义和经济理论应用于全球范围内数十亿人类用户引发了围绕个人自主和人类自决的伦理问题,其中一些现在正在被转化为正式立法,如欧盟的 GDPR ,以及最近提出的人工智能法案数字服务和市场法案

个性化的经济合理性

在经济理论中,*台被视为多边市场,旨在实现用户活动和内容的商品化。感兴趣的第三方,尤其是广告商,受益于该*台的算法标准化和治理结构提供的人类注意力“密集市场”。专业化通过贸易服务于互惠互利。广告商可以将机器学*驱动的市场细分的复杂工作外包给该*台,利用其对顶级数据科学家、计算能力和大量隐性行为数据的访问,让他们更好地将稀缺资源投资于开发个性化信息和通过*台的推荐基础设施提供的服务。

新古典经济学颂扬市场自然产生商品和服务最优配置的能力,因为所有交易都被认为是自愿和互利的。否则,理性行为者就不会进行交易。因此,个性化通过允许理性消费者访问更大的选择集(即市场),促进同行、服务和产品提供商之间的信息交换,并降低搜索、交易和决策成本,从而增强了理性消费者(以及广告客户)的能力。

从这个角度来看,个性化是市场驱动的经济自由观的技术实现,在这种经济自由观中,人们可以得到他们个人喜欢的东西——无论这些偏好的谱系或合法性如何。从这个角度来看,个性化促进了自由,因为它是基于自愿的,因此也是公*的交换:理性的用户被认为是自愿地与*台互动,并留下行为跟踪数据,这些数据随后可以根据用户透露的需求和需要进行处理并与感兴趣的外部方交换。正如诺贝尔奖获得者米尔顿·弗里德曼在他 1980 年的著作自由选择中所言,这种基于市场的自愿交易过程促进了经济交换、繁荣,并最终促进了人类自由。

但是,几十年来获得诺贝尔奖的经济理论所支持的乐观故事忽略了许多重要的细节。正如脸书举报者 Francis Haugen 所描述的,经济激励可以促使企业*台掩盖可能对其底线产生负面影响的个性化研究。这包括发现个性化技术的应用可能对个人产生破坏性的心理影响,并对社会产生不稳定的影响。

个性化科学的目标:控制还是自由?

在现代,我们倾向于狭隘地将知识等同于科学。这可能是由强大的技术官僚、经济专家和今天的数据科学家推动的更大的意识形态 科学主义 利己主义的症状,以证明他们提升的社会地位和决策权?

按照德国哲学家尤尔根·哈贝马斯的说法,答案可以说是肯定的。在他 1971 年的著作《知识和人类兴趣》中,他声称人类知识分为三大类,每一类都表达了人类的基本兴趣。他进一步主张,特别是在他后来的交流行为理论中,忽视除了预测、操纵和控制对象之外的其他兴趣会导致文化、社会和个人发展的病态。除非我们意识到科学与控制和预测并不共延,否则我们仍然无法自由决定自己的未来——在道德上受到我们自己技术的阻碍。

哈贝马斯坚持认为经验分析知识服务于我们对预测、操纵和控制自然的工具性兴趣。我们人类同胞的实践知识和相互理解服务于我们的诠释学兴趣。最后,通过批判性的、自我反思的和深思熟虑的思想解放符合我们的关键利益。对哈贝马斯来说,批判科学通过反思自身及其方法来发现自身的局限性,并在此过程中发展和扩大其认识论范围。批判性科学是人类物种层面的元认知:它不仅告诉我们哪里的科学知识可能是强大的,还告诉我们哪里的科学知识可能是脆弱的,并在不久的将来需要修订。这里我想起了统计推断中置信区间的作用。

借鉴弗洛伊德心理疗法的模式和皮亚杰(T2)和科尔伯格(T4)提出的逻辑和道德发展阶段,解放科学旨在将我们从更低级且经常被压抑的强迫、本能和神经症中解放出来——这是我们早期丑陋的动物本性的一部分,当时身体力量仍然控制着社会关系,T6 可能是正确的。今天,我们已经超越了霍布斯的自然状态,部分原因是我们有能力控制和操纵自然来满足我们的基本物质需求。经验分析知识拯救世界!

但是我们现在还不清楚。哈贝马斯认为,在由自由市场竞争的新自由主义意识形态主导的日益全球化的世界中,金钱越来越多地协调我们的社会互动,并将社会协调降低到以自我为中心的效用计算的博弈论和后果主义逻辑。

个性化的人:你在哪里?

个性化,正如这个词本身所暗示的,建立在一个隐含的人的概念上。根据不同的哲学家,这个人可能是下列的一个或全部:

  • 政治动物
  • 道德代理人
  • 理性、自觉的主体
  • 特定权利的拥有者
  • 具有明确的个性或者特点
  • 一种叙事驱动和独特自我诠释的动物
  • 一种自我组织的信息系统,能够随着时间的推移以独特的自我决定的方式发展和变化

康德:遵守普遍道德法则的自由

启蒙哲学家伊曼纽尔·康德认为人类的状况是内在矛盾的,在某种程度上早于现代双过程心理学。康德的墓碑上写着一句名言:

有两样东西,我们越是经常、越是坚定地思考它们,它们就会让我们心中充满新的、越来越多的钦佩和敬畏:我头上的星空和我心中的道德法则。

一方面,我们是物理生物,是受牛顿宇宙运动定律支配的物体。在这方面,我们与构成漂浮在太空中的岩石的一簇簇无意识的原子没有什么不同。然而,我们也拥有理性的能力,一种几乎无限的能力,能够意识到并清楚地表达出支配我们行为的规则。人类存在的这种规范性、自我参照性和“更高”的方面是人类价值和独特道德地位的基础。它赋予我们独特的个性,也是我们通常所说的“自我”的焦点大多数上瘾者都会同意,尽管我们可能会在意志力上有短暂的失误,但我们通常会将“真实的自我”与有意识、理性的自我反思的结果联系起来,而不是与我们的本能、欲望和即时需求联系起来。

康德认为,从严格意义上讲,出于本能和利己动机的行为没有道德价值。作为理性主义者,康德相信道德原则必须先于我们可能有的任何经验、兴趣或欲望而产生。的确,善意——为了职责而履行职责的————是唯一的无条件内在善意,但它需要自主性(即自我立法能力)才能有牙齿。意志必须同时创造它自己的法则,并把自己与这些法则捆绑在一起,这样它才是好的。客观上对所有理性存在有效,康德称这样的普遍法则为绝对命令。成为理性意味着有效地使一个人的意志和绝对命令一致。

因此,矛盾的是,自由来自于将一个人的意志与内在的普遍道德法则捆绑在一起,这是一条所有理性生物天生就能遵循的法则。

康德声称,这种绝对命令是所有道德义务的基础,并作为我们行动动机的决定程序。类似于逻辑一致性的概念,绝对命令认可那些行动规则,当被所有理性主体普遍化时,不会导致矛盾。换句话说,只有可以转化为绝对命令的责任——而不会弄巧成拙或导致矛盾——才算道德责任。例如,我们有义务做出虚假的承诺吗?不,因为如果没有人信守承诺,承诺本身的概念就会瓦解。

与康德对道德的抽象和逻辑方法相反,越来越多地推动算法个性化的正统经济思想遵循哲学家大卫·休谟的经验主义,他的著名观点是理性是并且应该是激情的奴隶。关于算法个性化的基础,这种划分被我称为 视觉冲突

照片由 GR StocksUnsplash 上拍摄

个性化的冲突愿景

为了更好地理解与个性化相关的人文主义和经济观点之间的紧张关系,我想改编一下托马斯·索威尔在他富有洞察力的书《愿景的冲突》中所做的区分。

索威尔是一名训练有素的经济学家,他区分了西方思想中两种相互冲突的政治和道德观点。这些愿景是无所不包的世界观,不仅偏向一个人的伦理和政治理论,也偏向一个人对科学知识的性质和范围的理解。然而这两种观点是互不相容的。实际上,一个人看到一只鸭子,另一个人看到一只兔子。例如,消费者主权概念背后的标准经济思维暗示,因为我们渴望某样东西,它一定是好的。然而康德主张相反的观点:某物是好的,因此我们必须渴望它(就我们是理性的存在而言)。

我推测人工智能伦理学领域的出现在某种程度上是这种观点冲突的表现。因此,对人工智能伦理的工作和兴趣的快速增长应该被解释为表达对个性化技术迄今为止忽略了无约束愿景的基本元素的不满。我们可以粗略地将这些不受约束的因素与哈贝马斯所说的我们的解释学和解放兴趣联系起来,以实现相互理解和从我们基础的动物性本质中获得自由。

受限的视觉

到目前为止,个性化技术在很大程度上是在追求受限视觉的过程中发展起来的。这种受约束的观点遵循了一条最早由苏格兰启蒙运动(T2)的思想家提出的思想路线,比如 T4 的亚当·斯密(T5)和大卫·休谟(T6)。它将相关性置于因果关系之上,将*惯和传统中隐含的直觉和经验知识置于显而易*的原因之上,将可观察到的结果置于不可观察到的意图之上,并将理想与实现理想所需的成本进行权衡。完美不应该是好的敌人。稀缺性和有限性被视为人类生存的基本方面,因此关于分配这种稀缺资源的各种方式的相对效率问题被列为优先事项。受限视野接受权衡是生活中不可避免的事实。

从伦理的角度来看,受约束的观点严重依赖于对正确行为和价值的结果主义、工具主义推理,并采取一种“系统级”的功利主义观点,主张集合体的属性优于个体。受限视觉分享了一种类似于行为主义和(逻辑)实证主义的科学哲学,因为它通过参考环境的可观察、可验证的经验特征来寻找对人类行为的普遍不变的类似法律的解释,避免不可验证、不可观察的内在原因的可疑的形而上学主张。与新古典经济学一样,受约束的视野似乎遭遇了一个明显的物理学嫉妒案例,即物理学的唯物主义科学体现了人类调查研究的方法论和认识论理想。

不受约束的视野

我认为,无论是出于实践还是意识形态的原因,个性化技术的发展在很大程度上独立于不受约束的视野。但随着人工智能伦理领域的发展,这种情况可能会慢慢改变。

不受约束的愿景源自法国和德国启蒙时代的思想,由孔多塞和 T2 的伊曼纽尔·康德发展而来,将理性和有意识的深思熟虑提升到直觉、*惯和传统之上,强调抽象的理想而不是实现这些理想所需的实际牺牲,并惊叹于有教养的人类思维达到自我认识和普遍真理的能力。

不受约束的观点认为某些行为和事态本质上是好的,这是因为在理想的公正观察者看来,它们具有客观属性,或者是审议或普遍化的理想化程序的结果。受限视觉的工具主义或结果主义推理通常被认为是低劣的,因为它倾向于不加批判地把结果视为既定的(但是是谁给的呢?并且可以证明把人当作物品,仅仅是达到他人目的的手段是正当的。

在其政治、伦理和法律形式中,这种不受约束的观点经常赞同对追求公共利益的个人可以做什么制定严格的规则,经常使用权利作为“王牌”的概念来描绘无论效用或后果如何都不能跨越的个人神圣性领域。

就科学哲学而言,不受约束的观点的理性主义超越了可观察的相关性,并通过提及行动的内部原因来解释人类行为,这涉及不可观察的意图,其内容可能只有那些参与共享生活或文化形式的人才能完全理解和理解。不受约束的视野认可了现实主义者,甚至是超验现实主义者的形而上学。

人工智能伦理学:一种矛盾修饰法?

一些哲学家称经济伦理的概念为矛盾修饰法。这也适用于人工智能伦理的思想吗?人工智能体现了统计学、计算机科学、数学和工程领域的前沿知识。然而伦理本质上是保守的。哲学学生仍然阅读 2000 年前的文本,而工程师却不读,这是有原因的。

但个性化核心的视觉冲突并不是放弃对个性化未来希望的理由。不受约束的理想主义宣称技术和道德进步不是也不应该是相互排斥的。扩大对数据科学家和工程师的教育,让他们接触哲学和社会科学的关键思想,是重要的第一步。包括来自各种文化和跨学科视角的人工智能研究人员也是如此。如果个性化被(重新)想象为一种解放技术,而不仅仅是一种工具控制和优化人类对象的工程工具,这些变化将是必要的。

我们必须确保,在开发和部署个性化技术的过程中,我们不会为了效率、便利或利润这种纯粹的工具性商品而牺牲我们内在良好的认知“内在道德法则”的能力。批判性科学和人工智能伦理在指导我们应用技术方面发挥了作用,这些技术促进了我们的诠释学和批判性兴趣,并进一步——而不是阻碍——人类道德发展。

绘画的人工智能:揭示神经风格的转移

原文:https://towardsdatascience.com/ai-for-painting-unraveling-neural-style-transfer-5ac08a20a580

背景

在一个 NFT 数百万美元出售的世界,下一个有利可图的业务可能是创建独特的虚拟实体,以及谁比人工智能更适合这项工作。事实上,早在 NFT 大肆宣传之前,2018 年 10 月,第一幅人工智能生成的画像以 432,500 美元的价格售出。从那以后,人们利用他们对先进算法的深刻了解来制作令人惊叹的艺术品。例如,Refik Anadol 是一位使用人工智能创作迷人画作的艺术家。(在此环节恳请大家查看他的一些作品)。另一位数字艺术家 Petros Vrellis 在 2012 年制作了梵高著名作品《星夜》的互动动画,三个月内点击量超过 150 万次。然而,人工智能的创作能力并不仅限于艺术作品。人们正在建造智能系统,可以写诗、歌曲、故事情节,也可能做其他创造性的工作。我们是否正在走向一个所有艺术家都将与人工智能竞争的世界?然而,也许这不是我想要讨论的。我这篇文章的目的是深入研究一种优雅的算法, 神经风格转移 ,这可能有助于像我这样糟糕的画家成为艺术大师。

1.神经类型转移——想法

任何图像都可以分为两个组成部分,内容和风格。内容是指不同对象的错综复杂,而风格是总的主题。您也可以将这两者解释为图像的局部和全局实体。例如,在下图中,埃菲尔铁塔的详细设计是内容,而背景色调——蓝天和绿色的环境——构成了风格(主题)。

照片由 Kirsten 在 Unsplash 上绘制

神经风格转移(NST)的思想是获取一幅图像,并将其内容重组为其他图像的风格。与上面的情况不同,从更吸引人的图片(如梵高著名的《星夜》画)中转移主题(风格)可以导致令人着迷的重组。

下面详细讨论一下上面的改造。

2.风格转移的 CNN

既然我们处理的是图像,那么卷积神经网络是风格转换的关键就不足为奇了。还有,因为大量的 CNN 已经在图像处理任务中取得了令人难以置信的成绩,所以我们不需要为 NST 单独训练一个。我会使用 vgg-19 网络(风格转移的转移学*),但你可以使用任何其他预训练的网络或训练自己的网络。

Vgg-19 网络具有以下架构:

首先,我们来看看上面的一些层李尔都认识什么。每层至少有 64 个过滤器来学*图像特征。为简单起*,我们将使用前十个过滤器的输出来查看这些层学到了什么。如果您想要代码,您可以使用以下链接之一。

https://www.kaggle.com/shashank069/neuralstyletransfer-experiments

https://github . com/shashank 14k/my work/blob/main/neuralstyletransfer-experiments . ipynb

conv 第一街区

conv 第二街区 1 号

conv 第三街区 1 号

conv 第四街区 1 号

conv 第五街区 1 号

conv 第五街区 2 号

你从上面的情节中得到什么?初始层似乎确定了图像的整体背景(全局属性)。这些图层似乎可以识别全局的边缘和颜色,因此它们的输出与原始图像非常接近。这类似于用黄油纸描摹照片。您可能无法再现照片中不同物体的错综复杂,但是,您可以获得准确的整体表现。

然后,随着图像在网络中传输,输出会失真。这些层中的滤波器输出,尤其是 block_5_conv_2,集中于特定位置,并提取关于不同对象的形状的信息。例如,下面的两个过滤器对埃菲尔铁塔的细节感兴趣。在分类问题上,也许这些局部特征会帮助 CNN 将埃菲尔铁塔与其他轮廓相似的建筑(如电塔)区分开来。

块 _5_conv_2 的输出(滤波器 4)

块 _5_conv_2 的输出(滤波器 13)

使用 CNN 的图像的全局和局部成分的这种可分性是驱动风格转移的原因。艺术风格的神经算法的作者,关于神经风格转移的原始论文(Gatys 等人)报告说,由于较深的层在识别细节特征方面表现良好,因此它们被用于捕捉图像内容。类似地,初始层,能够伪造一个好的图像轮廓,被用来捕捉图像风格(主题/全局属性)。

3.图像重组

我们的目标是创建一个新的图像,从一个图像中捕捉内容,从另一个图像中捕捉风格。首先,让我们解决内容部分。

3.1 内容信息

我们在上一节中已经确定,更深层的输出有助于识别图像内容。我们现在需要一种机制来捕获内容。为此,我们使用一些熟悉的数学——损失函数和反向传播。

噪声图像(在 Python 中生成)

考虑上面的噪声图像(X)。此外,为了简单起*,假设我们选择的用于风格转换的 CNN 仅包括两层,A1 和 A2。通过网络传递目标图像(Y)并使用 A2 的输出 A2(A1(Y)),我们获得关于其内容的信息。为了学*/捕捉这些信息,我们让 X 通过同一个网络。由于 X 由随机排列的像素值组成,A2(A1(X))也是随机的。然后,我们将内容损失函数定义为:

这里,(I,j)是图像数组中位置的索引符号。(目标内容图像和噪声图像的大小必须相等)。本质上,如果得到的数组 A2(A1(X))和 A2(A1(Y))的形状是(m,n),损失函数计算它们在每个位置的差,对它们求*方,然后对它们求和。这样,我们强制 X 成为一个图像,当它通过网络时,产生与 y 相同的内容信息。然后,我们可以像在任何神经网络中通常做的那样,使用反向传播来最小化内容损失。然而,有一个微小的区别。在这种情况下,变量是图像数组 X 的值,而不是网络权重。因此,最后的等式是:

我们可以将这个想法扩展到任何规模的网络,并选择任何合适的层来收集内容信息。

3.2 风格信息

捕捉风格比捕捉内容更复杂。它需要理解 gram 矩阵。

3.2.1 克矩阵

如果你参考 vgg-19 的架构(第 2 节),你会看到 block_1_conv_1 的输出是(m,n,64)的形状。为了简单起*,假设 m,n = 3,2,并且滤波器的数量也是 2 而不是 64。

两个滤波器的输出

如你所知,CNN 过滤器学*识别不同的属性——像边缘/线条、颜色强度等空间特征。假设上面的滤镜可以识别不同位置的红色和蓝色阴影。因此,滤波器 1 输出中每个索引的像素值(范围 0-1)代表该位置红色的强度。滤光器 2 给出了关于蓝色的相同信息。现在,堆叠两个输出数组,并取结果数组与其转置的点积。我们得到了什么?

最终结果是由两个过滤器识别的属性的相关矩阵。如果您检查两个过滤器的输出,您会注意到红色强度高的位置蓝色味道较少。因此,点积矩阵的非对角线值(红色和蓝色之间的相关性)较小。如果我们现在改变像素值,使红色和蓝色一起出现,非对角线值将增加。

因此,在 CNN 的上下文中,gram 矩阵是由层的所有过滤器识别的所有特征的相关矩阵。让我们看看他们如何帮助风格转移。

3.2.2 风格和综合损失

斯蒂夫·约翰森Unsplash 上拍照

假设我们希望从上面的图像中转移样式。注意浅蓝色(倾向于白色)的多条条纹(垂直和水*线条)的存在。识别线条和浅蓝色的两个过滤器的 Gram 矩阵将返回这些特征之间的高度相关性。因此,该算法将确保这些特征一起出现在重组的图像中,并很好地完成风格的转换。实际上,每个 CNN 层都有许多过滤器,这导致了庞大的 gram 矩阵,但这个想法仍然有效。例如,vgg-19 中的 block_1_conv_1 的输出的 Gram 矩阵将是 64 个特征的相关矩阵。

接下来,我们需要建立风格损失的函数。假设,在通过块 _1_conv_1 传递目标风格图像时,我们得到一个 gram 矩阵 g。我们通过同一层输入我们的噪声图像 X,并计算它的 gram 矩阵(P)。风格损失的计算公式如下:

这里,(I,j)是 gram 矩阵中位置的索引符号。通过最小化该函数,我们确保 X 与我们的目标风格图像具有相同的特征相关性。

另一件要注意的事情是,不同于从单个层计算的内容损失,样式损失是从多个层计算的。 Gatys et al 为此使用了五层。因此,最终的风格损失是:

w 是分配给每层损失的重量。这是一个超参数,可以调整来观察重组是如何变化的。我们将在最后一节讨论改变这些权重和使用单一图层进行样式转换的结果。

组合损失函数是样式和内容损失的总和。同样,每个单独的功能都有一个权重。样式的权重越大,将确保重组后的图像捕捉到更多的样式,反之亦然。

4.改变超参数

最后,在讨论了理论之后,让我们用不同的超参数来实验神经类型转移。代码可以参考上面提供的笔记本链接。作为参考,使用参数调用样式传递函数:

  1. 内容图像的路径
  2. 样式图像的路径列表
  3. 含量损失重量
  4. 风格损失重量
  5. 迭代次数(反向传播)
  6. 样式图像的权重列表—如果您想要从多个图像中传递样式,您需要为每个目标样式图像提供权重
  7. 样式图层的权重列表-分配给样式损失函数中涉及的每个图层的权重

我们将使用以下图像进行实验:

4.1 5 个损失权重相等的风格层,1 个内容层

我们将使用这个图像来比较改变超参数的结果。

4.2 将风格损失函数的权重从 0.005 增加到 0.1

正如所料,增加权重会促使算法捕捉更多的风格。因此,重组具有更好的蓝色和黄色的组合。

4.3 对样式使用单层

仅使用 block_1_conv_1 进行样式丢失不会导致令人着迷的重组。也许,由于 syle 由各种阴影和空间属性组成,所以来自多个层的过滤器是必要的。

4.4 对内容损失使用不同的图层

将 block1_conv1 用于内容信息会强制网络从目标内容图像中捕获全局特征。这可能会干扰样式图像的全局特征,我们最终会得到一个令人震惊的样式转换。我认为,结果证明了为什么鼓励在 NST 中使用更深的层。它们只关注内容图像中突出对象的局部细节,能够*滑地复制样式图像的主题。

4.5 手动为样式层分配权重[0.4,0.3,0.2,0.05,0.05]

虽然 4.1 和目前的重组没有明显的区别,但在我看来,后者有一个整体的浅色阴影。这可能是由于分配给 block1_conv_1 的权重较高,根据 4.3,block 1 _ _ 1 从《星夜图》生成白色调。

4.6 手动给样式层分配权重【0.05,0.05,0.2,0.3,0.4】

与 4.5 相比,它具有更引人注目的颜色组合。将较高的权重分配给较深的层会提供更吸引人的结果。来自这些层的 Gram 矩阵可能正在计算《星夜》中更主要的全球特征之间的相关性。

4.7 使用多幅图像进行风格转换

最后,让我们从多幅图像中捕捉风格,进行更艺术化的重组。它需要在风格损失上稍作修改。每幅图像的风格损失与前面 3.2.2 中讨论的一样

然而,总的风格损失是:

本质上,正如我们到目前为止所做的那样,我们为每幅图像的风格损失分配权重,并将它们相加。

5.评论

就这样,我结束了这篇文章。我敦促您用提供的代码进行更多的实验。另外,我已经从头开始实现了这个算法,应该有一个更有效的过程。更好的优化器肯定会提高性能。我希望用神经网络创作艺术很有趣。将神经风格迁移与生成性对抗网络结合起来是一个诱人的命题,我希望将来能涉及到它。

参考资料:

艺术风格的神经算法

https://arxiv.org/abs/1508.06576

笔记本链接:

1.卡格尔:

https://www.kaggle.com/shashank069/neuralstyletransfer-experiments/data

2.开源代码库

https://github . com/shashank 14k/my work/blob/main/neuralstyletransfer-experiments . ipynb

人工智能生成的艺术:如何开始生成你自己的图像

原文:https://towardsdatascience.com/ai-generated-art-how-to-get-started-with-generating-your-own-images-821bc130fef4

DALL E2、中途和稳定扩散的非技术性比较

作者图片

如果你没有生活在岩石下,你可能已经看到人工智能(AI)生成的图像到处出现。这些图像通常是用“文本到图像”生成模型生成的。也就是说,你输入一个文本描述(“提示”),几分钟后模型就会生成一个或多个描述你的提示的图像(“生成”)。

也就是说,你输入一个文本描述(“提示”),几分钟后模型就会生成一个或多个描述你的提示的图像(“生成”)。

在撰写本文时,三个最受欢迎的模型是稳定扩散中途达尔 E2

在本文中,我们将从以下方面比较这三种模型:

  • 如何创建人工智能生成的图像
  • 创造人工智能生成的艺术需要多少钱?
  • 可以商业化使用 AI 生成的图像吗?

我们不会解释这些人工智能模型是如何在引擎盖下工作的。此外,我们不会对这三种型号进行并排比较。例如,在这个伟大的 Twitter 线程中已经完成了:

Twitter 帖子,并排比较了由 Fabian Stelzer 在稳定扩散 vs midway vs DALL E2 中使用相同提示生成的图像

让我们按字母顺序来看看这三种型号。

出于本文的目的,我们将通过提示“一个可爱的机器人站在森林中的静止动画”来探索这三个模型。

注意撰写时间(2022 年 9 月)三款车型都是 在积极开发 (beta 阶段)。因此,如果您稍后阅读这篇文章,它可能不代表当前的状态。

DALL E2

DALL E2OpenAI 开发,目前处于 beta 阶段。

如何用 DALL E2 生成图像?

为了用 DALL E2 生成图像,OpenAI 为你提供了一个极简的 web 应用。然而,在你用 DALL E2 生成你的第一张图片之前,你必须首先被邀请去试用它。你可以通过候补名单【5】申请。

2022 年 9 月 4 日 DALL E 截图(图片由作者提供)。

先决条件

通过等候名单申请后的邀请。

然而,并不能保证你会被录取,可能需要几个月才能被录取【7】。

功能

在 DALL E2 中,您可以使用“文本到图像”和“文本引导图像到图像”生成算法生成图像。使用“文本引导图像到图像”生成算法,您可以上传图像并删除上传图像中您希望 DALL E2 重新生成的部分。

2022 年 9 月 4 日 DALL E 代对提示“一个可爱的机器人站在森林里的定格动画剧照”(图片由作者提供)。

您也可以创建已生成图像的变体。

2022 年 9 月 4 日 DALL E 变奏到提示“一个可爱的机器人站在森林里的定格动画剧照”(图片由作者提供)。

此外,或使用“文本引导图像到图像”生成算法编辑生成的图像。您甚至可以使用“Generation frame”选项在已经生成的图像上生成另一个图像,从而扩展您生成的图像。

2022 年 9 月 4 日 DALL E 编辑应用截图(图片由作者提供)。

2022 年 9 月 4 日 DALL E 生成的文字引导图像到图像生成的截图(图片由作者提供)。

分辨率和格式

在 DALL E2 中,所有生成的图像都具有 1024 乘 1024 的固定图像尺寸

使用 DALL E2 要花多少钱?

当你进入 DALL E 的时候,你会得到 50 个免费积分,你必须在第一个月内用完。在接下来的每个月里,15 个免费的信用点数将会重新填满。请注意,这意味着免费积分不会在几个月内累计。

每个提示将创建四个图像,它将消耗大约一个信用点[8]。

如果这还不够,你可以花 15 美元购买 115 代的额外信用。一旦你的免费信用额度用完,大约是每一代 13 美分(T2)。

你能在商业上使用 DALL E2 生成的图像吗?

是的,根据他们的条款[4],您可以在商业上使用 DALL E2 生成的图像:

在遵守这些条款和我们的内容政策的前提下,您可以出于任何合法目的使用 Generations,包括商业用途。这意味着你可以将你的权利出售给你所创造的一代人,将它们整合到书籍、网站和演示文稿等作品中,或者以其他方式将它们商业化。— [4]

中途

Midjourney 由同名研究实验室开发,目前处于公测阶段。

你如何在中途生成一个图像?

要使用中途生成图像,您可以使用中途不和谐服务器

2022 年 9 月 4 日中途不和服务器截图(图片由作者提供)。

先决条件

Discord 帐户访问中途 Discord 服务器

特性

Midjourney 主要在他们的 discord 服务器上提供【文本到图像】代。您只需向 Discord bot 发送一条消息,以命令/imagine开始,后跟您的提示。

中途不和服务器截图 2022 年 9 月 4 日世代到提示“一个可爱的机器人站在森林里的定格动画剧照”(图片由作者提供)。

此外,您可以创建生成的图像的其他变体,或者将生成的图像放大到更高的分辨率。

2022 年 9 月 4 日中途不和服务器变奏曲精选一代对提示“一个可爱的机器人站在森林里的定格动画剧照”(图片由作者提供)。

但是,您也可以将文本导向图像的一个或多个图像的 URL 输入到图像生成中。

此外,你可以在midjourney.com/app上找到你生成的所有图像,并在那里进行过滤和组织。

2022 年 9 月 6 日 midjourney.com/app 截图(图片由作者提供)

分辨率和格式

在中途,您可以创建 v 各种格式的图像,图像分辨率高达 2048×2048

使用 mid travel 要花多少钱?

当你第一次加入 midway Discord 服务器时,你可以获得 25 分钟的免费 GPU 时间,你可以用自己的时间[3]。这大约相当于 25 代免费的,因为一代大约需要一个 GPU 分钟[3]。一个请求将根据您的提示生成四个选项。

之后,您可以从两个计划中进行选择[3]:

  • 基本计划的费用是每月 10 美元,200 分钟的 GPU 时间(大约每代 5 美分)
  • 标准计划每月花费 30 美元,使用 15 个小时的 GPU 时间(大约每代 3 美分)

如果你想为一家年收入超过 100 万美元的公司商业使用这些图片,你需要以每年 600 美元的价格获得公司计划。

你能在商业上使用 Midjourney 生成的图像吗?

是的,如果你是付费会员,你可以根据他们的条款商业使用 Midjourney 生成的图片。

根据上述许可,您拥有使用服务创建的所有资产。如果您属于以下例外情况,则这不适用。 […]

如果您不是付费会员,Midjourney 授予您知识共享非商业性使用 4.0 归属国际许可下的资产许可(“资产许可”)。— [3]

这也意味着,如果你不是付费会员,你可以将这些图片用于非商业目的,还可以修改它们。

稳定扩散

稳定扩散是由来自 CompVisStability AILAION 的研究人员和工程师创造的。它是开源的,于 2022 年 8 月向公众发布。

如何生成扩散稳定的图像?

您有两种选择来生成具有稳定扩散的图像:

  • 在您的计算机或云服务上运行稳定的本地扩散
  • 使用像 Dream Studio 这样的网络应用

先决条件

如果你想自己运行稳定扩散模型,你需要一个至少有 10GB VRAM 的 GPU。Huggingface 提供了关于如何使用稳定扩散模型的教程【2】。

如果你想了解更多,这里有一个由吉姆·克莱德·蒙赫提供的很棒的分步指南:

https://medium.com/geekculture/run-stable-diffusion-in-your-local-computer-heres-a-step-by-step-guide-af128397d424

如果不想处理任何代码,也可以使用 Dream Studio web 应用。为此,你只需要注册一个帐户。

2022 年 9 月 4 日梦想工作室截图(图片由作者提供)。

特性

梦想工作室主要提供“文字到图像”基于稳定扩散的世代。然而,它有各种选项,如设置生成图像的步骤数或设置随机种子。

您还可以将每代图像的数量设置在 1 到 9 之间。

梦工厂截图生成到提示“一个可爱的机器人站在森林里的定格动画剧照”2022 年 9 月 4 日(图片由作者提供)。

此外,稳定扩散能够使用文本引导的图像到图像生成算法来生成图像。你可以在上摆弄它,通过拥抱脸来扩散其余的。

2022 年 9 月 6 日拍摄的扩散其余截图(图片由作者提供)

分辨率和格式

通过稳定的扩散,您可以创建各种格式的图像,图像分辨率高达 1024 x 1024。

使用稳定扩散要花多少钱?

当你第一次在dream studio beta上注册时,你会得到价值 2 英镑的积分[1]。这大致相当于每张图片免费生成 200 次。一个图像生成的价格在每个图像 1 到 28 个信用点之间变化,取决于图像的大小和您希望模型花费多少步骤来生成您的图像。

免费试用后,您可以购买 10 个增量的额外点数[1]。

你能在商业上使用稳定扩散生成的图像吗?

是的,根据他们的条款[9],你可以在商业上使用稳定扩散生成的图像。

请注意,虽然用户已经丧失了这些图像的版权(以及任何/所有知识产权要求),但它们仍然是公共领域,任何人都可以出于任何目的使用,包括用户。请随意使用来自 DreamStudio Beta 和 Stable Diffusion Beta Discord service 的图像用于任何目的,包括商业目的。— [9]

结论

在本文中,我们比较了目前最流行的三种图像生成模型:稳定扩散、和 DALL E2。在这次比较中,我们采用了一种非技术性的方法:

  • 如何开始使用每个模型,以及从开始使用到生成第一张图像需要多长时间
  • 使用每种型号的成本是多少
  • 你是否可以在商业上使用这些图片

下面,你可以找到一个表格,总结了三个模型在写作时的比较。请记住,下表可能会发生变化,因为三款车型正在积极开发中,该表可能很快就会过时。

DALLE、Midjourney 和 Stable Diffusion 的非技术比较:截至 2022 年 9 月的特征、格式、分辨率、商业用途、先决条件、成本和试验。(图片由作者提供)请注意,随着模型的积极开发,内容可能会发生变化。

喜欢这个故事吗?

以下是我收集的其他生成性人工智能文章:

**Leonie Monigatti

莉奥妮·莫尼加蒂**

生成人工智能

View list3 storiesA non-technical comparison of DALL·E2, Midjourney, and Stable DiffusionSugar cookies for Christmas

如果你想把我的新故事直接发到你的收件箱, 订阅

成为一名媒体会员,阅读更多来自我和其他作家的故事。报名时可以使用我的 推荐链接 支持我。我将收取佣金,不需要你额外付费。

**https://medium.com/@iamleonie/membership

TwitterLinkedInKaggle**

参考

[1]梦工作室,https://beta.dreamstudio.ai/faq(2022 年 9 月 5 日访问)

[2]拥抱脸,“🧨扩散器的稳定扩散”,google.com。https://colab . research . Google . com/github/hugging face/notebooks/blob/main/diffusers/stable _ diffusion . ipynb # scroll to = GD-vx3 CAV oct

[3]中途,“中途文档”。git book . io .https://midjourney.gitbook.io/docs/(2022 年 9 月 4 日访问)

[4] OpenAI,“使用条款”。openai.com。https://labs.openai.com/policies/terms(2022 年 9 月 4 日访问)

[5] OpenAI,“DALL E Now
有 Beta 版”openai.com。https://openai.com/blog/dall-e-now-available-in-beta/(2022 年 9 月 4 日访问)

[6] J. Jang,“信贷是如何运作的”。openai.com。https://help . open ai . com/en/articles/6399305-how-Dall-e-credits-work(2022 年 9 月 4 日访问)

[7] Reddit,“DALL-E 2 等候名单需要多长时间?如果你申请的话,有百分之百的把握会被录取吗?”。reddit.com。https://www . Reddit . com/r/open ai/comments/vahnqg/how _ much _ time _ does _ the _ dalle _ 2 _ wait list _ take _ and/(2022 年 9 月 4 日访问)

[8] D. Schnurr,“DALL E 编辑指南”,openai.com。https://help . open ai . com/en/articles/6516417-Dall-e-editor-guide(2022 年 9 月 6 日访问)

[9]稳定 AI,《稳定扩散梦想工作室 beta 服务条款》。稳定. ai .https://stability.ai/stablediffusion-terms-of-service(2022 年 9 月 5 日访问)**

人工智能地理空间野火风险预测

原文:https://towardsdatascience.com/ai-geospatial-wildfire-risk-prediction-8c6b1d415eb4

使用地理空间栅格数据评估美国邻近地区野火危害的预测模型

迈克·纽伯瑞在 Unsplash 上的照片

野火是意外的火灾事件,既有自然发生的,也有人类活动造成的。在美国,它们每年造成数十亿美元的损失[1],2020 年,仅在美国,它们就烧毁了超过 1000 万英亩的土地[2]。大部分费用来自预防工作。例如,加利福尼亚州最近批准了超过 15 亿美元的野火预防预算[3]。决定将这笔支出分配到哪里需要了解哪些区域处于高风险,因此在本文中,我提出了一个使用深度学*图像处理和地理空间数据集提供最新火灾风险地图的框架。

本文的第一部分介绍了遥感领域的一些背景知识,以及在这个项目中广泛用于创建数据集的工具 Google Earth Engine 。如果你已经熟悉这些主题,或者只是想跳到该项目,请随意向下滚动到人工智能地理空间野火风险预测,其中涵盖了准备数据集和训练深度学*模型

该项目是作为库珀联盟研究生水*课程 ECE-471:遥感和地球观测中的机器学*主题的一部分进行的。

遥感和地球观测

对于门外汉来说,遥感是一门从远处获取信息的科学,通常使用飞机或卫星。通常,它被认为是在卫星观测地球的背景下;一个常*的例子是谷歌地球上的卫星视图。

传感器本身的范围从被动传感器到主动传感器,被动传感器像照相机一样检测自然光,无论是发射的还是反射的,主动传感器发射自己的能量并观察反射,如雷达或激光雷达。光的不同成像频率被称为光谱带。卫星环绕地球运行,拍摄沿途的大片土地,如下图所示。由于这种模式,需要一定的时间来对整个地球进行成像。

美国宇航局的地球资源卫星极地轨道成像条带每 16 天重访一次每个点。从美国宇航局在 https://www.youtube.com/watch?v=yPF2jpjB3Qw取回

地球上同一点的连续图像之间经过的时间被称为重访率。通常,在重访率(时间分辨率)和空间分辨率之间有一个权衡,空间分辨率是指地面上像素的大小。例如,受欢迎的 MODIS 卫星大约有 2 天的重访率,分辨率为 250 到 1000 米,具体取决于光谱带[4]。相比之下,Landsat-8 在可*光波段的分辨率为 30 米,但重访率约为 16 天[5]。

谷歌地球引擎

Google Earth Engine (GEE)是一个强大的界面,可以让你从地球上的任何地方访问超过三十年的卫星图像和其他地理空间数据。我强烈推荐你探索他们的数据集

在下面的代码中,我展示了获取一些数据并将其绘制在交互式地图上是多么容易。首先,你必须用 GEE 注册一个开发者账户。确保你已经安装了 geemapee(Google Colab 预装了 ee ,但 geemap 没有),并验证你的帐户。找到你感兴趣的数据集的代码,GEE 调用这些图像集合。对于这个演示,我使用“MODIS/006/MCD43A4”选择了 MODIS。该集合包含公共目录中的每一幅图像-覆盖整个地球的多年数据-因此在检索任何图像之前,您需要应用一些过滤器。

在遥感和地球观测中,使用合成图像是很常*的,也就是说,当你将多幅图像组合起来创建一幅新的图像。例如,如果在某一天,一朵云碰巧遮住了你的图像的一部分,那么在多天的时间跨度内取一个中间值合成将会给你一个干净无云的图像。均值和中值合成是其他常*的例子,但你可以发挥创造力。例如,如果你正在制作一个洪水地图,你可以尝试一个“最湿像素”合成,使用一个巧妙的波段组合来指示水的存在。

在像 Colab 这样的 Jupyter 环境中运行上面的代码,将会弹出一个交互式地图,如下图所示。只需几行代码,我们就可以获得整个地球的卫星图像!这是 2020 年 6 月美国本土(CONUS)的中值合成图。请注意,这个特定的图像集合没有显示开阔的海洋,边缘的浅蓝色只是背景中的默认地图。

美国毗邻地区的 MODIS 影像,2020 年 6 月[4]。作者可视化。

GEE 还允许您以通用格式(包括 geotiff)导出这些图像。您可以指定分辨率、投影和感兴趣区域,感兴趣区域可以使用 geojson 等格式进行定义。这对于创建为机器学*(ML)而格式化的数据集来说很方便。

最后,不提到 GDAL [6]就很难谈论地理空间数据集的处理,但是这个工具非常强大,可以非常快速地变得非常复杂!与其在这里深入探讨,我会把你链接到罗伯特·西蒙【7】的一篇优秀的 3 部分教程。

人工智能地理空间野火风险预测

该项目的目标是使用 GEE 上可用的大量地理空间数据集来创建一个地图,对美国各地的野火风险和危险级别进行评级。将此视为像素分类问题,有两大步骤需要讨论。首先是数据集的准备,包括:输入地理空间数据的选择,训练标签的注释,以及使用 GIS 软件为 ML 准备数据。其次是训练一个深度神经网络来执行逐像素分类,也称为语义分割。最后,我们可以可视化结果并讨论模型的性能。

I)准备数据集

输入:GEE 数据集

输入数据集由来自 GEE 目录的各种地理空间数据组成。这项任务的第一个也可能是最直接的图像收集是 MODIS (如上所示)【4】,它的七个光学波段以 500 米的分辨率提供了美国的每日覆盖范围。之所以选择它,是因为它的重访率高,允许每周重新生成野火灾害预测工具。

第二个目录是从爱达荷大学的网格地面气象数据集[9]中得到的气象数据的集合。这些数据每天都有,分辨率为 4000 米,包含最高地表温度、最低湿度、标准化降水指数(SPI)和蒸发需求干旱指数(EDDI)等信息。

美国邻近地区的 GRIDMET 最高地表温度[9]。作者可视化。

我们考虑的第三个目录是着陆火灾*均火灾重现间隔(MFRI) [10]。该地图由美国农业部森林服务局和美国内政部地质调查局汇编而成,使用历史趋势根据野火之间的*均年数对每 30 米像素进行分类。这些值以分类数据的形式呈现,以 5 年为间隔进行分类。虽然这张地图只出版过一次,但数据的性质使它在几年后仍然具有相关性。这里的问题当然是这一层的输入数据不会随着时间的推移而改变,但它仍然可以帮助模型了解地区趋势。换句话说,它对于提高空间精度非常有用,但对于时间精度却没有用。这种权衡将在第三部分详细讨论。

美国邻近地区的*均火灾重现间隔[10]。如这张地图所示,越暗的地方火灾越频繁。这张地图没有提到火灾的严重程度。作者可视化。

输入数据集考虑的第四个也是最后一个集合是美国农业部国家农业统计服务农田数据图层[11]。这是一个 30 米分辨率的土地覆盖分类图,将每个像素分为一百多个类别,对应于不同的作物和各种非耕地类型。由于我们测量野火风险的方式,该数据集将被证明是有用的,这种方式将农田视为“不可燃”,与常年积雪/冰和裸露地面属于同一类别。这可能导致一些土地难以分类,因为它可能看起来可燃,但我们的数据集不会这样认为。为了抵消这一点,我们手动创建了一个二进制掩码,将每个像素分类为培养或非培养。(最后我们注意到,如果没有这个附加层,模型实际上表现得一样好,如果不是更好的话)

全国农业统计服务耕地数据图层[11]。尽管我们对耕地和非耕地实施了二进制图层,但此地图显示了所有可用的类别。作者可视化。

输出:野火潜在危险

有一堆数据来预测火灾是很好的,但是我们如何去了解什么实际上与火灾风险相关?我们需要一些量化火灾危险的参考地图。显然,我们不能使用燃烧过的地方的图像,因为那不能告诉我们很多关于火灾前的情况。我们考虑找到燃烧的区域,绘制出它们的边界,并考虑火灾前几周是高火灾危险的例子。虽然这种方法可能会有很好的结果,但手动搜索火灾并编写一种方法来恢复火灾前的图像将是乏味的,并且可能会将我们限制在像加利福尼亚这样的热点地区。此外,火灾的严重程度没有细微差别。

在搜索另一个火灾危险数据集时,我们发现了这个,美国农业部森林服务局的野火潜在危险 (WHP) 地图[12]。

2020 年野火潜在危险图“描述了抑制资源难以控制的野火的相对潜在危险”[12]。美国农业部森林服务局提供的图片

WHP 地图是一个栅格地理空间数据集,旨在“帮助评估野火危害或确定大型景观中燃料管理需求的优先级”目标不仅仅是量化野火发生的可能性,还要考虑到野火的强度、破坏性和难以控制的程度。

“用较高的 WHP 值绘制的区域表示在有利的天气条件下,燃料有较高的概率经历燃烧、隆起和其他形式的极端火灾行为。”[12]

该地图作为地理空间数据集发布了三年:2014 年、2018 年和 2020 年。它可以是分类值,有 5 个火灾危险级别(非常低、低、中、高和非常高)和 3 个其他类别(不可燃、水和已开发),也可以是连续的整数值。虽然该数据集不作为 GEE 目录的一部分,但它是公共领域的,我们可以从美国农业部研究数据档案馆下载。

处理:为 ML 准备数据

我们现在有几个输入数据集,可以很容易地结合起来用于训练和运行模型,以及一个输出数据集,可以作为监督学*算法的标签。太好了!但是仍然缺少一个关键的步骤,数据根本不是 ML 格式的。尤其是对于为图像处理设计的算法。

我们要做的第一件事是按月份过滤所有栅格数据集,并确保它们在相同的坐标参考系统(CRS)中以相同的分辨率正确排列。使用 GDAL 和 gdalwarp 命令,这变得相当简单。我们选择了常*的 EPSG:4326 作为我们的 CRS(用于 GPS),500 米作为我们的分辨率。(技术说明:对分类栅格数据集进行重采样时,请确保使用“近似”、“模式”或类似的重采样算法来保留输入值,而不是“双线性”、“立方”等… )

第二步是将整个圆锥切割成可以由深度学*模型处理的更小的图像,并将特征图像与其标签配对。为了使模型工作,所有输入图像必须具有完全相同的大小,当在投影系统的怪圈中工作时,这比听起来更难——有数百万种方法可以展*球体,但没有一种真的那么好!我们使用在线工具 G eoJSON Grid Creator 生成一个完美*铺美国的网格,然后手动删除美国边界以外的任何方块。我们的目标是每个区块大约 256 公里宽,或者 512 个像素,每个像素 500 米。下图中的最终网格包含 177 个图块。

全网格覆盖整个美国。瓷砖约为 256x256km 公里。图片作者。

准备好格网后,我们现在可以遍历数据集中的每个切片,并将该区域导出为堆叠了每个要素图层的 geotiff,以及带有 WHP 地图标注的配对 geotiff。我们使用三个夏季月份(美国大部分地区火灾季节的高峰期)、六月、七月和八月的中值合成数据进行了这项研究,这三年是 WHP 地图可用的三年中的每一年,即 2014 年、2018 年和 2020 年。最终数据集包含整个美国 9 倍以上的 13 层地理空间数据的图像。

ii)深度学*模型

目标是什么?

在我们进入模型之前,我想快速谈谈我们的目标。我们最初的目标是拥有一种算法,可以每周生成美国本土的野火风险地图。我们很早就知道,为“风险区域”标记数据的发现会很困难。不仅在美国以任何分辨率标注每个像素的过程都很困难,而且构成火灾的因素也是微妙而复杂的,我们对这一主题的了解还不足以自己做出判断。找到 WHP 地图为我们解决了这个问题,但是从人工智能的角度来看,它有自己的问题。其中最大的问题是它每隔几年产生一次,并且不对应于任何特定的时间点。如果我们每周甚至每月都生成一张新地图,我们实际上是在拓展 WHP 地图的预期用途。

本质上,我们通过假设 WHP 地图最符合美国夏季火灾高峰期的观察结果来执行时间插值,并希望模型能够了解足够多的地理上不同的位置以将这些细微差别应用于不同的时间。换句话说,我们希望它从空间差异中学*时间差异。如果我们试图预测不同季节的火灾危险,这将导致推断时的领域差距。ML 中的域差距是指用于训练的数据与用于推断的数据不相似。虽然我们知道这将使模型变得不完美,但我们仍然希望看到它的表现,也许可以为未来的尝试学*一些东西。

一种用于语义分割的神经网络

根据 2 个以上的类别标记图像中的每个像素的任务被称为多类别语义分割o . ronne Berger,P. Fischer,T. Brox 在 2015 年推出的 U-Net 是完成这项任务的优秀神经网络模型【13】。虽然最初用于显微镜图像中细胞的二进制分割,但是已经表明其可以很好地推广到其他分割任务,包括遥感数据的多类分割。架构如下图所示。

原始论文中提出的 U-Net 架构。Ronneberger 等人的图表。

在此示例中,输入图像为 572x572。它们穿过卷积层,增加了信道的数量。然后,使用最大池操作将它们缩小 2 倍,通过另一组卷积层。这又进行了 3 次,之后“图像”或特征图被向上传递,使用向上卷积来反转最大池操作。来自收缩路径的图像被附加到扩展路径中的相应图像,以帮助保留原始输入的形状和内容。

我们使用 Tensorflow 和 Keras 的模型实现略有不同,以支持多个输入通道、不同的图像尺寸和输出端的多个类。完整的模型可以使用函数初始化,如下所示。

我们的调整

为了支持我们图像的尺寸,我们必须做另一组重要的改变。因为图像必须相互附加,收缩和扩展路径的尺寸必须完全匹配。要做到这一点,图像尺寸必须在每次收缩前被 2 整除。我们的图像是 513x565,显然不能被 2 整除,更不用说 16 了。使用 GDAL 将 geotiffs 读入 numpy 数组,然后我们将图像填充到 576x528 的维度,这是下一个可用的 16 的倍数。

我们还实现了一个加权损失函数,以防止模型完全忽略不太常*的类别,如非常高的风险或水。这是通过增加错误分类的代价来实现的,而错误分类的代价与一个类的流行度成反比。类别分布如下图所示,注意填充是如何添加空白像素的,覆盖了图像的 12.6%。

填充和标记图像中类的像素分布。图片作者。

通过这些重要的调整,我们能够使用 80%的数据集来训练我们的模型,将剩余的 20%用于验证和测试。我们选择的批量大小为 16,因为我们的 GPU 没有足够的内存容纳 32。我们的模型在 20 个时期后收敛,训练和验证数据的准确率为 65%。

可视化输出

为了观察我们模型的输出,我们必须将它们转换回具有适当坐标的地理 IFF。为此,我们保存每个图块的目标图像的元数据,并使用它在神经网络的输出端导出数组。然后,我们可以使用 GQIS 来重新组合图块,并在地图上显示它们以及一些附加元素,如国家和州边界,以及图例[14]。使用这种方法和我们的模型,我们现在终于可以重现多年来没有的 WHP 地图了!

2019 年 7 月预测的野火潜在危险地图。图片作者。

通过观察夏季几个月的一些输出,我们注意到我们的模型在预测最高风险水*时非常害羞。将这张地图与 WHP 的原始地图相比,我们注意到少了很多红色,尤其是美国最西部的部分。然而,该模型乐观地认为这些地区中的大多数都具有高风险。同样,该模型经常忽略低风险类别,而是选择非常低风险。这些问题可以通过调整损失函数来解决,以进一步惩罚这些代表性不足的类别的错误分类。

该模型在识别水和不可燃区域方面几乎没有困难,包括中西部和密西西比河沿岸的耕地。

因此,该模型在呈现未经训练的夏季图像时表现相当好,但如果我们试图预测冬季的野火危险,会发生什么呢?为了测试这一点,我们运行了 2020 年 1 月的预测。这是结果。

2019 年 1 月预测的野火潜在危险地图。图片作者。

太棒了。这表明该模型不仅仅是记忆和再现 WHP 地图。有证据表明,该模型学会了概括其训练域之外的月份。例如,该国被雪覆盖的部分现在显示为不可燃,这是有道理的,因为常年冰雪(在训练数据中非常罕*)在原始 WHP 地图中被认为是不可燃的。另一个好的结果是,西部的许多高风险和非常高风险地区被降级为中度风险甚至更低。

虽然该模型确实显示了学*从地理差异中归纳时间差异的证据,但仍然存在一些明显的问题。例如,南方大部分地区现在被认为比夏天时风险更高。一些研究确实表明,像佐治亚州和卡罗莱纳州这样的州比像加利福尼亚这样的州更有可能在冬末或春天遭遇火灾,但这个模型似乎仍然高估了风险。由于南方没有经历太多的降雪,光秃秃的树木和干燥的冬季条件(在训练中看不到)可能是造成这种情况的原因。

另一对只在冬季预测中明显的问题是更嘈杂的输出和网格状伪像。在整个国家最北部的不可燃烧区域,似乎有一些非自然高预测的斑点,包括许多非常高风险的单像素。网格状伪像,在俄克拉荷马州、密苏里州和阿肯色州周围最明显,似乎是由*铺造成的,尽管它们不会在夏季预测中出现,因此可能有一种方法来纠正它们。

iii)我们学到了什么?

鉴于这个项目令人生畏的性质,我们只有短短的几周时间来完成它,我们对结果感到兴奋。学*使用地理空间数据是令人大开眼界的,使用它来准备一个带标签的机器学*数据集绝非易事。在这个项目中,我们学到了大量关于使用地理空间栅格数据和为 ML 预处理数据的知识。

当我们开始这个项目时,据我们所知,还没有人发表过自动预测全国范围内野火风险的模型。虽然这个模型远非完美,但它可以作为概念的证明。它展示了在深度神经网络中通过像 GEE 这样的 API 使用地理空间数据来执行像美国这样大规模任务的可能性。

地理空间数据丰富,易于访问,为数据饥渴的深度学*模型提供了完美的框架。我强烈鼓励每个人去探索可能性!然而,获得好的标签可能相当困难。量化火灾风险或危险仍然是这项特殊任务的最大问题。WHP 地图是这个项目的一个很好的起点,但是在一些专家的帮助下,甚至一些人工标注,结果会有很大的改善。我期待着在时间允许的情况下再次访问这个项目。

我希望你喜欢这本书!如果你对这个项目和我忽略的许多实施细节有任何问题,请留下评论或直接通过thjaquenoud@gmail.com 联系我。我要感谢我在这个项目上的合作者 Kevin Kerliu 和 Brandon Bunt,以及我们的 Krishna Karra 教授,他向我们展示了栅格数据、地理信息系统以及 GDAL、GQIS 和 GEE 等工具的诀窍。

来源:

[1] 国家统计局 (2021),国家机构间消防中心
【2】t . Feo 和 S. Evans,加州野火的成本 (2020),加州科学委员会&技术
【3】a . Beam,加州批准干旱、野火预防的新支出 (2021),美联社新闻
【4】ORNL·DAAC, MODIS 和 VIIRS 土地产品全球子集化和可视化工具【1】 分析 LANDSAT 软件包 (2011 年)中的遥感数据,统计软件杂志
【6】n . gore lick、M. Hancher、M. Dixon、S. Ilyushchenko、D. Thau 和 R. Moore, Google Earth Engine:行星尺度的地球空间分析,面向所有人,环境遥感
【7】GDAL/OGR 贡献者, GDAL/OGR 地理空间数据抽象软件库(2020 年) 为生态应用和建模开发网格地面气象数据 (2013),《国际气候学杂志》
【10】LANDFIRE, LANDFIRE:现有植被类型 (2020),美国农业部和美国内政部
【11】美国农业部国家农业统计局,农田数据层(2020)
【12】g . k . Dillon 林务局
【13】o . Ronneberger、P. Fischer 和 T. Brox, U-Net:生物医学图像分割的卷积网络 (2015),计算研究储存库
【14】GQIS.org, QGIS 地理信息系统 (2022),QGIS 协会

人工智能让你的背部分段(PyTorch)

原文:https://towardsdatascience.com/ai-got-your-back-segmented-pytorch-72ef14856db6

用于脊柱的 UNet 分割

图片部分由本来源部分由作者提供

随着我们每天收集更多的数据,人工智能(AI)将越来越多地用于医疗保健领域。医疗保健中人工智能应用的一个关键类别是诊断。医疗诊断中的人工智能有助于决策、管理、自动化等。

脊柱是肌肉骨骼系统的重要组成部分,支撑着身体及其器官结构,同时在我们的流动性和负荷转移方面发挥着重要作用。它还能保护脊髓免受冲击造成的损伤和机械冲击。

在自动脊椎处理流水线中,脊椎标记和分割是两个基本任务。脊柱图像的可靠和精确处理有望有益于临床决策支持系统,用于脊柱和骨骼健康的诊断、手术计划和基于群体的分析。设计用于脊柱处理的自动算法是具有挑战性的,这主要是由于解剖和采集协议中的相当大的变化以及公开可用数据的严重缺乏。

在这篇博客中,我将只关注给定 CT 扫描数据集中的脊柱分割。标记每个椎骨和进一步诊断的任务没有包括在这个博客中,可以作为这个任务的继续。

脊柱或椎骨分割在所有关于脊柱形态学和病理学的自动量化的应用中是至关重要的步骤。随着深度学*的出现,对于计算机断层扫描(CT)扫描这样的任务,大量不同的数据是主要的受欢迎资源。但是,目前还没有大规模的公共数据集。VerSe I是一个大规模、多探测器、多站点的 CT 脊柱数据集,由来自 355 名患者的 374 次扫描组成。2019 年和 2020 年的数据集都有。在这篇博客中,我将两个数据集合并成一个数据集,以便从更多的数据中获益。

https://github.com/anjany/verse#download

*The data is provided under the CC BY-SA 4.0 License, making it fully open-sourced.*

NIfTI(神经成像信息学技术倡议)是一种用于神经成像的文件格式。NIfTI 文件在神经科学甚至神经放射学研究的成像信息学中非常常用。每个 NIfTI 文件包含多达 7 维的元数据和体素,并支持各种数据类型。前三个维度被保留来定义三个空间维度 xy、z ,而第四维被保留来定义时间点 t 。剩下的维度,从第五到第七,则是其他用途。然而,第五维度仍然可以有一些预定义的用途,例如存储体素特定的分布参数或保存基于向量的数据。VerSe 数据集包含 NIfTI 文件的 zip 文件。

ITK 快照 是一款用于分割 3D 医学图像中结构的软件应用。它是可以安装在不同*台上的开源软件。我已经使用它能够在 3D 视图中可视化 NifTi 文件,并在原始图像上加载和覆盖 3D 蒙版。我强烈推荐在这个任务中使用它。

CT 扫描机— 图像来源

计算机断层扫描 (CT)是一种 x 射线成像程序,在该程序中,一束狭窄的 x 射线在围绕身体快速旋转的同时瞄准患者。机器收集的信号将被存储在计算机中,以生成身体的横截面图像,也称为“切片”。这些切片被称为断层图像,包含比传统 x 射线更详细的信息。一系列切片可以数字地“堆叠”在一起,以形成患者的 3D 图像,该图像允许更容易地识别和定位基本结构以及可能的肿瘤或异常。

动作步骤如下。我开始下载 2019 年和 2020 年的数据集。然后,我将两个数据集合并到它们的训练、验证和测试文件夹中。下一步是读取 CT 扫描图像,并将 CT 扫描图像的每个切片转换为一系列 PNG 原始图像和蒙版。后来我使用了这个 Github repo 中的 UNet 模型,并训练了一个细分模型。

数据理解:在开始数据处理和训练之前,我想加载几个 NIfTI 文件,以便更熟悉它们的 3D 数据结构,并能够可视化它们和从图像中提取元数据。

下载完 VerSe 数据集后,我能够使用 NiBabel 库打开一个 .nii.gz 文件(解释如下)。通过读取一个文件并查看 CT 扫描图像的一个特定切片,我能够运行 Numpy transpose 函数来查看轴向、矢状和冠状三个不同视图中的一个切片。

三个不同角度的 CT 扫描切片——图片由作者提供

在我更加熟悉原始图像并且能够从原始 3D 图像中取出一个切片后,现在是时候查看同一切片的蒙版文件了。正如你在下图中看到的,我能够在原始图像切片上叠加蒙版切片。我们在这里看到渐变颜色的原因是,遮罩文件不仅定义了存在的每个椎骨的区域,而且它们还具有不同的标签(用不同的颜色显示),即每个椎骨的编号或标签。为了更好地理解脊柱标签,你可以参考这一页

将蒙版数据叠加在原始图像的一个切片上—按作者分类的图像

数据准备:数据准备的任务是从原始图像和掩模文件中生成每个 3D CT 扫描文件的图像切片。它从在中读取原始和掩模图像开始。zip" 格式,并将它们转换成 Numpy 数组。然后浏览每幅 3D 图像,检查每幅图像的视角,并尝试将大多数图像转换为矢状视图。接下来,我从每个切片生成了 PNG 文件,并将它们存储为灰度值“L”格式。在这种情况下,我们不需要生成 RGB 图像,因为每个 CT 扫描切片都只有 1D 值。

在这项任务中,我使用了 UNet 架构来对数据集应用语义分段。为了更好地了解 UNet 和语义分割,我推荐查看这个博客。

我还使用了 PytorchPytorchvision 来完成这个任务。正如我提到的这个回购使用 PyTorch 很好地实现了 UNet,我一直在使用其中的一些代码。

由于我正在处理 NIfTI 文件,并且能够用 python 阅读这些文件,我将使用ni Abel库。NiBabel 是一个 python 库,用于读写一些常*的医学和神经成像文件格式,如 NIfTI 文件。

*Dice Score: 为了评估我们的模型在语义分割任务中的表现,我们可以使用 Dice Score。Dice 系数是 2 重叠面积(在预测遮蔽面积和真实遮蔽面积之间)除以两幅图像中的像素总数。

骰子点数— 图片来源

****训练:首先我定义了 UNet 类,然后定义了 PyTorch 数据集类,它包括读取和预处理图像。预处理任务包括加载 PNG 文件,将它们的大小调整为一个大小(在本例中为 250x250),然后将它们全部转换为 NumPy 数组和 PyTorch 张量。通过调用 dataset 类(VerSeDataset ),我们可以在我定义的批处理中准备我们的数据。为了确保 raw 图像和 mask 图像之间的映射是正确的,我曾经调用过next(iter(valid_dataloader))来获取一批中的下一个项目并将其可视化。

后来我把模型定义为model = UNet(n_channels=1, n_classes=1)。通道数是 1,因为我有一个灰度图像,而不是 RGB,如果你的图像是 RGB 图像,你可以将通道数改为 3。类的数量是 1,因为我只有一个类来判断一个像素是不是椎骨的一部分。如果你的问题是多类分割,你可以设置你有多少个类就有多少个类。后来我训练了一些时期的模型。对于每一批,我首先计算损失值,通过反向传播更新参数。后来,我再次检查了所有批次,只计算了验证数据集的损失,并存储了损失值。接下来,我直观地查看了训练和验证的损失值,并跟踪了我们模型的性能。

在我保存了模型之后,我能够抓取其中一个图像,并将其传递给训练好的模型,并接收到一个预测的掩模图像。通过绘制原始、真实遮罩和预测遮罩的所有三幅图像,我能够直观地评估结果。

原始图像(左)、真实蒙版(中)和预测蒙版(右)-按作者分类的图像

正如你从上面的图像中看到的,这个模型在矢状面和轴向上都做得很好,因为预测的遮罩与真实的遮罩区域非常相似。

您可以在这里找到完整的代码:

****未来工作:这项任务也可以用 3D UNet 来完成,这可能是学*脊椎结构的更好方法。因为我们有每个椎骨的每个掩模区域的标签,那么我们可以进一步做多类掩模分割。此外,当图像视图为矢状时,模型性能最佳,因此可能将所有切片转换为矢状会具有最佳模型。

感谢阅读!

AI 诚信:其他行业的领导力课程

原文:https://towardsdatascience.com/ai-integrity-leadership-lessons-from-other-industries-82e3d6af2e95

日常诚信

其他领域犯错更好吗?

Riccardo AnnandaleUnsplash 上拍摄的照片

欢迎回到本系列,关注数据科学中的日常伦理挑战!我之前的帖子关注的是应对错误的个人准备。在缺乏行业规范或强有力的领导的情况下,诚实行事的重担落在了员工个人身上,包括初级员工。一定要这样吗?管理者和行业领导者应该扮演什么角色?还有其他领域的做法不一样吗?

在这篇文章中,我讨论了来自其他行业的想法和实践,我相信这些想法和实践将有助于数据科学领导者促进诚实和透明。这些都与人工智能完整性中对积极领导力的普遍需求有关。

行业规范

我选择强调三个可能作为数据科学模型的领域:精算科学、软件工程和学术界。我有在其中两个领域(软件工程和学术界)工作的直接经验,但是依赖于发表的报告和对精算科学的总体印象。这不是一项定量研究;即使我在一个领域工作过,这些 1 或 2 次的遭遇也不一定有代表性。然而,即使是我有限的经验也显示了一系列正直的方法,其中一些比另一些更有效。

如果其他行业的一些工作不能让我成为这些领域的专家,我就不能声称了解数据科学组织中实现完整性的所有方法。但是,我去过一些地方,观察过许多客户、供应商等。,即使这种适度的经验也足以让我看到由于忽视诚信而导致的麻烦。这些问题从不必要的混乱到完全丧失信誉。

除了我自己的经验之外,我还寻找了关于数据科学完整性的外部信息。在我之前的文章中,我讨论了在人工智能伦理研讨会上询问如何处理错误[1]。我的问题似乎让这个主要关注算法偏差和隐私的小组大吃一惊。反过来,我感到惊讶的是,诚信问题不被认为是这样一个群体的主题。正在讨论的问题确实非常重要,也许把重点放在这些问题上是有意义的。但是,在诚实和正直的日常问题上,一个人去哪里寻求指导呢?

两个主要的数据科学伦理会议是 ACM 的 FAccT 和 AAAI/ACM 的人工智能伦理和社会[2,3]。我在他们的 2019-2021 议程中搜索了“诚实”、“诚信”和“披露”等词。我只找到了两个匹配,都没有讨论错误或撒谎,而是用户体验混乱和学术界的利益冲突。同样,搜索“错误”会导致关于统计错误的文章,而不是人为错误。

相比之下,在精算网站上进行这样的搜索会得到大量相关的结果。事实上,美国精算学会采用的职业行为准则将“职业诚信”列为第一准则[4]。为什么数据科学和精算科学的伦理焦点不同?毕竟领域有很多重叠。我的感觉是,执业了几个世纪的精算师们已经从错误中吸取了教训。一个更新的领域,数据科学似乎是从零开始,而不是利用其他专业的智慧。

精算模型

精算师是有执照的。执照委员会制定政策,当违反道德时可以吊销执照。没有执业“数据科学”的执照。我在美国工作,我认为这里不太可能获得许可(参*[5])。然而,在英国已经有了形式化数据科学的努力[6];我不知道这些努力进展如何。

不管怎样,我认为我们可以从精算师那里学到很多东西。首先,他们公开讨论诚信问题,设定期望,并为成员提供实际指导[7-10]。他们甚至调查其成员对诚信的关注和实践,并公布结果[7]。

精算方法是明确的。如果你犯了错误,无论如何你都要揭露它。如果其他人犯了错误或违规,你也要披露。如果你不这样做,你可能会失去你的执照和职业生涯。我认识的一些人会认为这种方法“幼稚”、“简单”等等。然而,精算科学已有 300 多年的历史,专业许可已有大约 130 年[11];他们的方法肯定有优势。

我认为这种明确的政策是最好的。披露是将客户和公众的福祉置于数据科学家的舒适之上的唯一选择。

学术模式

在学术界,工作是由许多独立的研究小组完成的,其实践高度依赖于主要教授的个性。数据科学也差不多;道德标准主要是由公司文化和经理个人决定的,在不同的组织中有很大的差异。

在某些学术领域,审查委员会可能以主动(人类受试者委员会)或被动(不当行为委员会)的方式监管伦理问题。类似的委员会被认为是数据科学中伦理问题的解决方案[12]。作为一个在非常小的企业工作过的人,我警告说,这个解决方案可能会遗漏一大批数据科学家。也许有一天咨询公司,甚至评级机构会出现。例如,算法正义联盟/ORCAA 提供评论服务[13,14];然而,据我所知,这个过程解决的是算法偏差,而不是诚实。

即使这种板可以广泛使用,我觉得它们也适用于可以主动解决的问题,如隐私和算法偏*,但可能在确保完整性方面效果不佳。任何委员会的成功也将取决于成员的选择、成员在评估中的安全感以及领导者对建议的开放程度。我认为,在学术界,真正独立的委员会更有可能,因为成员有任期和某种程度的文化保护。

在这里讨论的所有领域中,数据科学最像学术界,无论是在当前实践中还是在建议的改革中。但是,我认为这种模式对我们来说有一些缺点。除了一些研究环境,数据科学不是科学。我们不会开发出不断挑战和改进的通用理论。我们的结果可能只适用于一家公司,在任何其他环境下都不可复制。此外,我们的结论可能是商业机密,因此不接受审查。我们可以跟随商业周期快速行动,产生大量很快就会过时的信息。错误的自然修正可能永远不会发生;我们对自己产生的信息负责。

软件工程模型

许多年前,我从事软件质量控制工作,编写自动化测试。在那里,他们为错误做准备——质量保证(QA)被纳入开发周期。软件工程也经常使用标准渠道来披露缺陷,例如软件更新和补丁。

相比之下,在数据科学和分析中,做数学或建立模型的人通常单独负责质量;正规的 QA 很少。不是所有的项目都适合自动化测试,但是我个人相信有很多方法可以改进我们的过程。例如,对用于模型构建(或部署)的最终的、干净的数据集进行基于断言的测试是非常有帮助的。同行评审和与客户或主题专家的仔细(甚至结构化)咨询也是有益的。

不管质量保证过程的细节如何,我觉得质量保证的心态是无价的。错误被视为过程的问题,而不是个人的缺点。即使当我与被认为是精英的开发团队一起工作时,人们也认为会出现错误。如果我没有发现错误,没有人会祝贺开发人员的完美(相反,他们会认为我一定错过了什么)。在我看来,共同承担质量责任,承认即使是最好的人也会犯错误,有助于人们减少恐惧,提高创造力。

在软件中,错误被重新命名为“bug”,责备被过程所取代。此外,他们使用成熟的工具,如测试工具,并建立了揭露错误的渠道。“数据科学”涵盖了广泛的项目和技能,其中许多不能直接映射到软件工程实践中。然而,我认为我们应该尽可能多地借用他们的工具。

混合模型

作为一个新的领域,数据科学的优势在于能够借鉴具有数百年经验的各种行业的最佳实践!我们可以挑选对我们有用的。

如果让我设计一个人工智能完整性的模型,我会使用这里讨论的所有领域的一部分。像精算师一样,我们可以设定很高的道德标准。我们可以公开讨论诚信面临的挑战,监督自己,从错误中学*。我们可以明确期望,同时为员工提供实际指导。

模仿软件工程,我们可以提高质量保证,在令人尴尬的事情发生之前发现错误。我们可以有适当的纠正渠道,这样我们(和我们的客户)就知道当错误发生时该怎么做。

此外,我们可以让错误变得令人厌烦——一些需要通过过程而不是个人的完美来解决的事情。我们需要承认错误会发生,并建立沟通这些错误的渠道。此外,我们需要能够从中学*,而不是仅仅对个人的不完美感到愤怒。

和学术界一样,机构文化和管理风格至关重要。诚信不会发生在真空中;我们的个人价值观和弱点与我们的环境相互影响。为了成功地应用任何领域的任何想法,我们需要积极的领导。

引领诚信

在诚信领域,领导者的角色是什么?在我看来,这与其他领导领域非常相似。领导者设定期望,并提醒人们政策和规范。他们通过减少模糊性、提供培训和指导来消除实现目标的障碍。他们设定了一个情感基调,可以提供一个很好的例子。他们检查、创建和更改流程以实现他们的目的。

有很多数据科学团队拥有优秀的领导力、积极的公司文化和想要做正确事情的员工。这些组织可能不会直接讨论诚信问题,但总体氛围有利于良好的道德规范。这些群体现在很好,未来大部分也会很好。这些有效的团队“足够好吗?”或者说,有必要对诚信更有目的性吗?

在我看来,拥有令人愉快的文化和优秀人员,但未能直接解决完整性问题的数据科学团队正在冒险。缺乏对完整性的特别关注会导致模棱两可的情况,这对于自我辩护或最小化来说是更高的风险。此外,团体不是在真空中运作的。员工可能会从一家公司跳槽到另一家公司,有过不愉快经历的客户需要从新的供应商那里得到保证。

我*过如何而不是领导正直的例子,这些也有助于理解有目的行动的重要性。我看到质量控制被完全忽视,当问题出现时,随之而来的是困惑。诚信的最佳实践通常不会被讨论,管理者也不会对新员工设定期望。当员工犯错时,一些经理会变得愤怒或具有惩罚性(我将在未来的文章中讨论心理安全和相关问题)。最糟糕的是,我*过一些领导者决定不披露影响外部客户的错误——然而,同样是这些领导者却希望员工完全透明。

善意的忽视和有害的领导都会危及这一领域的可信度,还会让客户和公众面临风险。在我看来,缺乏对诚信的关注也会反过来伤害领导者,导致项目失败、客户流失和员工不满。我相信领导人工智能的完整性包括明确的最佳实践。我们必须明确诚实的价值和披露的必要性。

数据科学完整性中最关键的模糊点之一是如何以及何时披露错误。每个从事数据科学工作的人都应该明白,如果他们发现或犯了错误,应该怎么做,领导者需要与其他利益相关者一起设定预期。

当客户与分析公司合作时,他们通常不会问错误是如何沟通的。反过来,数据科学组织不会提出这个问题,所以当错误发生时,我们不确定是否或如何通知客户。这几乎就好像错误是黑社会恶魔,不得提及,以免被召唤。但是这种对话的缺乏为推诿留下了很大的空间。也许客户不再使用它了,也许他们不想被一个我已经确信不可能那么重要的问题所困扰,也许损害已经造成了。

类似地,仪表板用户界面经常被设计成无法通知用户过去的错误,甚至是现在的错误;我*过几次仪表板错误让团队完全措手不及的情况。在没有计划的情况下,他们争先恐后地关闭一个网站“进行维护”,或者只是在修复之前假设没有人会注意到它。

其他职业似乎也有披露错误的标准渠道。在新闻业,报纸可能会刊登勘误表。在软件工程中,他们使用补丁、更新,甚至新闻稿。在数据科学中,错误披露的渠道可能因项目而异,也可能是正式或非正式的,但应该存在并成为项目规划的一部分。

最后的想法

当领导者未能解决诚信问题时,负担就会落到员工个人身上。人们期望他们知道应该向谁披露错误,并且要迅速而得体地这样做。通常一个组织提供很少甚至没有 QA 支持、代码评审等。,这也留给个体从业者。

这些工人是谁?对于一个较新的领域来说,许多数据科学家相对缺乏经验,这并不奇怪。堆栈溢出调查列出了数据科学和机器学*工程师的工作年限比任何其他类型的开发人员都少,除了学生[15]。Kaggle 的调查发现,超过一半的数据科学家年龄在 35 岁以下[16]。据 Business Insider 报道,美国数据科学项目的数量在六年内增长了近四倍[17],并且已经有很多关于这些众多新毕业生就业市场困难的报道。

将诚信的主要责任放在如此脆弱、缺乏经验的员工身上是不正确的。我们所有上了几年的人都必须至少承担一些责任;此外,我们必须对各级领导提出更高的要求。幸运的是,其他领域为开发该领域的最佳实践提供了丰富的想法和多种选择。

参考

[1] V. Carey, AI Integrity:提前计划做正确的事情 (2021),走向数据科学

[2]美国计算机学会公*、问责和透明会议(ACM FAccT) (2021),网站

[3]AAAI/美国计算机学会人工智能、伦理和社会会议(2001 年),网站

[4]美国精算师学会,职业行为准则 (2001 年)

[5] A. Lyskov,数据科学家是否应该获得许可? (2019),走向数据科学

[6] B. McKenna,BCS,皇家统计学会,Alan Turing Institute 联合起来巩固数据科学专业精神(2021)ComputerWeekly.com,7 月 23 日

[7]美国精算师学会,《精算职业面临的关键伦理问题:美国精算师学会成员的看法》(2015 年)

[8] A. Lacroix,精算师的道德和专业精神 (2017),超越风险,加拿大精算师协会文件 217062

[9] R. Kutikoff,道德精算师 (2014),计划顾问,夏季

[10] L. Bloom,错误和遗漏:当你犯了一个错误时该怎么做 (2012),计划顾问,Summer

[11]精算师协会,历史背景 (2021)

[12] R. Blackman,如果你的公司使用人工智能,它需要一个机构审查委员会 (2021),《哈佛商业评论》,4 月 1 日

[13]算法正义联盟,请求算法审计,网站 (2021)

[14] ORCAA,网站 (2021)

[15]栈溢出, 2021 年开发者调查 (2021)

[16] Kaggle,机器学*与数据科学状态 2021 (2021)

[17] J. C. Oliver 和 T. McNeil,数据科学的工作正在增加,但并不是所有的学生在开始职业生涯之前都接受了道德培训 (2021),商业内幕

人工智能的可观察性和数据是网络安全的弱点

原文:https://towardsdatascience.com/ai-observability-and-data-as-a-cybersecurity-weakness-6523131ed7b9

播客

戴夫·希尔科谈监控和理解你的数据的重要性

苹果 | 谷歌 | SPOTIFY | 其他

编者按:TDS 播客由 Jeremie Harris 主持,他是 Gladstone AI 的联合创始人。每周,Jeremie 都会与该领域前沿的研究人员和商业领袖聊天,以解开围绕数据科学、机器学*和人工智能的最紧迫问题。

假设你是一家大型对冲基金,你想出去给自己买一些数据。数据对你来说非常有价值——它会影响你的投资决策,决定你的结果。

但是当你收到数据的时候,一股寒气顺着你的脊梁袭来:你怎么知道你的数据供应商给了你他们承诺的数据?从您的角度来看,您正盯着电子表格中的 100,000 行,无法判断其中一半是不是虚构的,或者更多。

事后看来,这似乎是一个显而易*的问题,但这是我们大多数人都没有想到的问题。我们倾向于假设数据就是数据,电子表格中的 100,000 行就是 100,000 个合法样本。

确保您正在处理高质量的数据,或者至少您拥有您认为您拥有的数据,这一挑战被称为数据可观察性,它在大规模上解决起来令人惊讶地困难。事实上,现在有很多公司专门从事这方面的工作——其中一家是 Zectonal,它的联合创始人戴夫·希尔科将加入我们今天的播客。

Dave 的职业生涯一直致力于了解如何评估和监控大规模数据。在云计算的早期,他首先在 AWS 这样做,现在通过 Zectonal,他正在研究允许公司检测数据问题的策略——无论这些问题是由故意的数据中毒还是无意的数据质量问题引起的。在这一集的 TDS 播客中,Dave 和我一起讨论了数据可观测性、数据作为网络攻击的新载体以及企业数据管理的未来。

以下是我在对话中最喜欢的一些观点:

  • 不能总是相信数据供应商会在他们承诺的时候交付他们承诺的数据。戴夫发现,在某些情况下,数据供应商会复制,甚至直接捏造样本添加到合法数据中,以欺骗他们的客户,让他们认为他们收到了承诺的全部数据。总的来说,公司缺乏一个系统的方法来评估这种情况何时发生以及是否会发生。
  • 与数据数量和质量同样重要的是数据到达的时间。旧数据可能会过时,如果供应商数据的预期年龄与其实际年龄之间存在重大延迟,您可能会遇到超出分布的采样问题,这会使模型表现不佳。从这个角度来看,数据可观测性可能会成为一个人工智能安全问题。
  • 合成数据是我们之前讨论过的一个话题。它允许我们通过利用嵌入了大量世界知识的大型模型(想想:GPT-3),生成实际上可能比“常规”数据信息更丰富的新样本,这些模型可以用来生成解释原始数据没有捕捉到的上下文的样本。但是,数据供应商也可以利用合成数据来夸大一个小得多的真实数据集,以欺骗客户,让他们相信他们获得了比实际更多的原始数据。Dave 认为,随着合成数据生成的不断改进,这将成为未来的一个主要问题。
  • Dave 讨论了 Zectonal 最近进行的一项实验,该实验显示了如何将数据用作实施新型网络攻击的载体。许多网络攻击涉及向易受攻击的 API 发送命令,这导致这些 API 以某种方式失败,从而产生可被黑客利用的漏洞。因此,一整套网络防御生态系统已经发展到可以防止这种正面攻击得逞,或者至少可以减轻它们的影响。但 Zectonal 的研究显示了恶意有效载荷是如何被插入数据中的,这几乎没有受到太多的网络安全审查。Dave 假设数据在未来将成为网络攻击者的一个重要渠道,特别是考虑到历史上很少注意保护数据。

章节:

  • 0:00 介绍
  • 3:00 什么是数据可观测性?
  • 10:45 与数据提供商的“有趣交易”
  • 12:50 数据供应链
  • 16:50 各种网络安全影响
  • 20:30 深度数据检查
  • 27:20 观察到的变化方向
  • 普通人能走的 34 步
  • 41:15 GDPR 过渡的挑战
  • 48:45 总结

人工智能在区块链(它实际上可能只是有意义)

原文:https://towardsdatascience.com/ai-on-the-blockchain-it-actually-might-just-make-sense-6763389453cc

播客

Ala Shaabana 和 Jacob Steeves 谈去中心化人工智能的好处

苹果 | 谷歌 | SPOTIFY | 其他

编者按:TDS 播客由杰雷米·哈里斯主持,他是人工智能安全初创公司墨丘利的联合创始人。每周,Jeremie 都会与该领域前沿的研究人员和商业领袖聊天,以解开围绕数据科学、机器学*和人工智能的最紧迫问题。

两位拥有世界级血统的人工智能研究人员决定建立一家公司,将人工智能应用于区块链。现在对大多数人来说,包括我自己在内,“区块链上的人工智能”听起来像是某种创业时髦词 bingo 中的获奖词。但我在与雅各布和阿拉的交谈中发现,他们实际上有很好的理由将这两种成分结合在一起。

在高水*上,在区块链上进行人工智能允许你分散人工智能研究,并奖励实验室建立更好的模型,而不是在华而不实的期刊上发表论文,这些期刊往往有偏*的评论者。

这还不是全部——正如我们将看到的,Ala 和 Jacob 正在用他们的分散式机器学*方法解决人工智能中一些最棘手的问题。从设计强大的基准到奖励优秀的人工智能研究的问题,甚至是将权力集中在少数几家建立强大人工智能系统的大公司手中的问题——这些问题都在他们建立区块链初创公司 Bittensor 的时候出现了。

Ala 和 Jacob 和我一起在这一集的 TDS 播客中谈论所有这些事情。以下是这一集里我最喜欢的带回家的东西。

  • 从某种意义上说,比特币是世界上最大的超级计算机。它由无数的矿工组成,每个人都在狂热地生成随机的字符串,希望他们能找到正确的序列,从而获得向区块链添加区块的权利——以及随之而来的经济奖励。当你缩小时,这看起来像是浪费了大量的计算能力。随机数生成并不完全是一项有价值的经济活动,然而成千上万的 GPU 正在疯狂地进行这项工作,保持比特币生态系统的运行。Ala 和 Jacob 开始思考:我们能不能设计一种新的区块链,把所有的计算导向更有建设性的东西?
  • 这就是位张量的用武之地。Bittensor 上的矿工不是猜测随机字符串,而是解决机器学*问题。他们竞相生成图像、句子或其他有用输入的潜在表征,当他们开始在相似的表征上趋同时,就形成了共识。当矿工们的表现和其他人相似时,他们就会得到奖励。
  • Bittensor 的网络一直在快速扩张,很快接近 Open AI 的 GPT-3 模型的规模。这是一个非常保守的估计,很大程度上是因为 Jacob 和 Ala 无法知道位张量挖掘者正在使用的模型的架构:实际上他们只能看到模型的输出,这使得他们的网络本质上是精英化的。

你可以在推特上点击这里,或者我这里

章节:

  • 0:00 介绍
  • 2:40 阿拉和雅各布的背景
  • 4:00 区块链的人工智能基础知识
  • 11:30 创造人类价值
  • 17:00 谁看到了好处?22:00 使用 GPU
  • 28:00 模特们互相学*
  • 37:30 网络规模
  • 45:30 这些系统的校准
  • 51:00 购买系统
  • 54:00 总结

2022 年要读的 AI 论文

原文:https://towardsdatascience.com/ai-papers-to-read-in-2022-c6edd4302247

阅读建议让你了解人工智能和数据科学的最新和经典突破。

照片由阿尔方斯·莫拉莱斯Unsplash 拍摄

今天我回到我的人工智能论文推荐系列,带给你十个新的人工智能论文建议(和更多链接)。我的老读者应该记得第一个、、第二个和第三个列表。现在,近两年后,第四部分来了。对于本系列的新手来说,这是一个非常固执己*的列表,你可能不同意所有的观点。有鉴于此,我尽力概述为什么你应该关心每一篇论文,以及它们在大计划中的位置。

在论文之前,我需要为所有阅读这篇文章的研究人员做出一个关于 AI 的声明:我们不需要更大的模型;我们需要解决方案。虽然公司已经达到万亿参数大关,但在医疗人工智能或缓解解决新问题所需的数据要求等实际问题上,几乎没有任何进展。出于这个原因,不要指望我在这里建议 GPT 废话。

最后但并非最不重要的是,作为一个小小的免责声明,我的大部分工作都围绕着计算机视觉,所以可能有很多关于强化学*、图形和音频等主题的优秀论文,而我并不知道。如果有任何你认为我应该知道的论文,请在评论中告诉我,❤.

我们走吧:

#1 深度学*不是你需要的全部(2021)

施瓦兹-齐夫、拉维德和阿米泰·艾蒙。“表格数据:深度学*不是你需要的全部。” 信息融合81(2022):84–90。

今年是 AlexNet 十周年。从那以后,深度学*变得比人工智能本身更加突出,机器学*现在听起来很过时,对 A*搜索没有概念的数据专业人士的数量不断增长。尽管如此,老式的机器学*技术仍然和以往一样与许多任务相关。

在这篇论文中,作者展示了 XGBoost 如何在各种表格数据集上匹配或超越深度学*解决方案,无论有无调整。另外,它显示了自动调优的 XGBoost 分类器比未经调优的分类器好得多。

理由一: AI 不是深度学*。远不止如此。特别是如果你是一个初学数据的科学家,要对经典技术给予应有的尊重,比如线性和逻辑回归、决策树、支持向量机和助推器。

原因 2: 在现实生活中,人们很容易忽略自动化调优方法如何在高效模型上创造奇迹,比如 XGBoost。在本文中,作者使用了 HyperOpt 的贝叶斯优化,在基线的基础上提高了约 30%。也许你也该学点远视了:)

花絮:你知道 XGBoost 是 2014 年发布的吗?它几乎和 TensorFlow 一样古老,但比神经网络要新得多。

延伸阅读:关于助推器,一个很好的读物是最初的 AdaBoost 论文(1997),它为后来的大多数集成方法奠定了基础。是我第二张单子的第二次建议阅读。关于简单模型击败复杂模型,另一个令人兴奋的阅读是快速文本线性文本分类器的分析和优化

#2 面向 21 世纪 20 年代(2022 年)的 ConvNet

刘、庄等“面向 21 世纪 20 年代的网络” arXiv 预印本 arXiv:2201.03545 (2022)。

虽然卷积神经网络(CNN)超越了以前的许多计算机视觉文献,但视觉变形金刚(vit)正在努力超越由 CNN 征服的空间。在这方面,ViTs 还没有这样做的普遍同意的原因是它们的计算成本,这仍然是一个公开的问题。

本文表明,经过仔细调整和训练的 ResNet 模型可以在 ImageNet、COCO 和 ADE20k 上匹配或超越 Transformers。换句话说,CNN 可能会存在更长时间。作者将其现代化的 ResNet 命名为“ConvNeXt”。

理由 1: 这是一篇非常实用的论文。几乎所有对 ResNet 的更改都可以扩展到其他模型。尤其是第 2.6 节,非常具有可操作性,今天就能给你结果。

原因二:对变形金刚颇有炒作。然而,这些论文不仅仅是关注。本文展示了如何将这些元素移植到乏味的旧模型中。

原因 3: 跟#1 一样,时髦的模型可能不是你任务的最佳模型。事实上,关于计算机视觉,ResNet 可能仍然是最安全的赌注。

花絮:如果你曾经想知道在 CNN 之前哪些算法是流行的,那么 ILSVRC 2012 第二名使用了 SIFT 等等。

延伸阅读:尽管 ConvNeXt 可以说更好,但关于 VisionSwin Transformers 还是值得一读的。其他有趣的阅读肯定会出现在未来的列表中的是 MLP康米克斯。顺便说一句,这并不是第一家尝试翻拍 ResNet 的报纸。这里是另一个例子

#3 变压器调查(2021 年)

林,天阳,等《变形金刚概览》 arXiv 预印本 arXiv:2106.04554 (2021)。

从 2020 年到 2022 年,比以往任何时候都有更多的地球资源被塑造成人工智能突破。如今,说“全球变暖需要关注”是一种奇怪的讽刺。尽管如此,在这个不断变化的领域,通过及物性,对最热门话题的调查是最热门的论文。

理由 1: 尽管有 N 个复杂性,变形金刚还是在这里呆着。对于任何数据专业人员来说,了解自然语言处理(NLP)的最新进展都是非常重要的。

原因 2: 截至发稿时,还没有 X-former 被广泛采用作为原始 Transformer 的继任者,尽管有人声称线性复杂度。今天,任何设计神经网络的人都有兴趣看看作者迄今为止是如何试图提高注意力的。

花絮: 为什么这么多 AI 系统都以布偶命名?

延伸阅读:这篇论文之后,一个自然的后续就是 2022 ICLR 的视觉变形金刚是如何工作的?然而,如果你想处于新闻的边缘,我强烈推荐阅读带有代码简讯的论文。感谢大卫·佐丹奴在一年多前的评论中向我推荐这份时事通讯。从那以后,它成了我最喜欢的新闻来源之一。

第四名 SimCLR (2020 年)

陈,丁等.“视觉表征对比学*的一个简单框架” 机器学*国际会议。PMLR,2020 年。

到目前为止,所有提到的论文都解决了监督学*:学*将 X 映射到 y。然而,整个世界都致力于一个“无 y”的世界:无监督学*。更详细地说,这个领域处理没有明确答案的问题,但是可以获得有用的答案。例如,我们可以通过几种方式对一组客户进行聚类:性别、年龄、购买*惯等。,我们可以根据这些集群制定有利可图的营销策略。

在这篇论文中,作者简化了现有的关于对比学*的文献来创建 SimCLR。该方法显示出产生更好的下游结果,同时比竞争方法简单得多。从某种意义上来说,你可以把这项工作理解为相当于 Word2Vec 的视觉——一种从大型图像语料库中提取有用特征的系统化方法。

理由 1: 如果你仔细想想,大部分人类学*都是无人监督的。我们不断地观察这个世界,并根据我们所看到的画出图案。我坚信任何对普通智力的突破都将带有相当大的无人监管的成分。因此,关注这一领域与人工智能领域的几乎所有人都有关系。

原因二:过去十几年 NLP 的突破都来自于无监督的预训练。到目前为止,类似的革命还没有出现在图像中。关注这个话题的另一个原因。

琐事:尽管非监督算法没有“y”,但大多数技术都像监督方法一样优化成本函数。例如,超分辨率模型最小化了原始图像和它们的缩减采样重建之间的重建误差。

延伸阅读:有许多有趣的无人监管的问题。下面是一个不详尽的列表: GANs风格转移图像超分辨率聚类异常检测关联规则挖掘等。继续对比学*主题, SimCLRv2 是一个自然的后续。

第五名效率网(2019)

谭,明星和郭乐。“效率网络:反思卷积神经网络的模型缩放” 机器学*国际会议。PMLR,2019。

手动调整神经网络经常感觉像玩乐高。你可以添加/删除层和神经元,玩激活功能,调整训练计划等。大多数情况下,我们的行为是任意的,比如将事物翻倍或减半,或者坚持 2 和 10 的幂。

在这项工作中,Tan 和 Quoc 研究了一种更具原则性的方法,即使用神经结构搜索(NAS)来放大和缩小网络。他们的研究发现,当深度、宽度和分辨率一起缩放时,可以获得最佳结果。此外,他们发布了一组预训练模型,从微型到超大,实现了最先进的结果。

理由 1: 本文是一个很好的例子,说明自动化调优策略(如 NAS 和贝叶斯优化)如何比手动调优模型更具成本效益。此外,您可以轻松控制您的调优预算。

理由二:谨防只有“畸形”设定的机型。稳健模型总是可以从小到大扩展,同时保持最先进的重要性。EfficientNet 就是一个很好的例子。

原因 3: 最近,无论是在视觉还是 NLP 任务上,主干架构的重要性都在持续增长。虽然我们仍然看到头部网络[ 123 ]的进步,但很难说真正的收益来自哪里。

花絮:供参考,根据代码为的论文,ImageNet 上当前 Top-1 最先进的在约 24 亿个参数下的准确率为 90.88%。至于 Top-5,目前为止最好的模型排名 99.02%。

延伸阅读:虽然对最大的语言模型 IMHO 存在激烈的竞争,但对高效但强大的模型的讨论要有趣得多(也更具包容性)。早期的名字包括 MobileNetShuffleNetSqueezeDet ,而最近的冠军是 Conv 混合器

#6 推动窄精度的极限(2020 年)

Darvish Rouhani,Bita,et al. “用微软浮点运算推动云级窄精度推理的极限” 神经信息处理系统进展33(2020):10271–10281。

继续速度的话题,在本文中,微软的研究人员展示了微软浮点格式(MSFP)的有效性,这是一种用于高效大规模浮点数学的共享指数方法。虽然仅限于推理工作负载,但所呈现的架构清楚地显示了专用单元如何能够显著扩展我们当前的容量。

然而,我并不是因为这篇论文的优点才把它加入列表的。相反,我的意思是提高对正在进行的窄精度革命的认识。市场上有谷歌 TPUAWS 推理Nvidea TensorCores ,还有无数创业公司在定制 AI 芯片上工作。虽然科学进步很大,但我预计未来五年的成果将完全由硬件驱动。

原因 1: MLOPs 是当今商业 AI 最关键的方面之一。实现高精度固然不错,但是在保持低成本的同时无缝部署模型却是另一个挑战。

理由二:今天的研究就是明天的现实。我们现在都使用混合精度训练。我不知道接下来我们会使用哪种 floats,但是我建议留意所有的候选人。

花絮:与此同时,Meta 正在搭建六千 GPU 集群。

延伸阅读:本次讨论感兴趣的是模型量化和修剪的主题。总的来说,这些技术旨在减少模型的大小和开销,以提高效率和降低成本。边缘设备(例如,移动电话)对这些技术特别感兴趣。

#7 我们真的需要乘法吗?(2020)

陈、韩婷等“AdderNet:深度学*真的需要乘法吗?."IEEE/CVF 计算机视觉和模式识别会议论文集。2020.

在这篇论文中,Chen 等人表明,标准卷积层可以由更简单的基于加法的方法来代替,只有边际精度损失(< 2%)。当卷积将特征与滤波器相乘时,所提出的方法计算绝对差。实际上,这相当于激活是特征和过滤器之间的 L1 距离。

直观上,卷积计算特征与过滤器的相关程度(即,它们是否共享相同的符号)。当我们改变绝对差的乘法时,我们有效地计算特征和过滤器之间的相似性。如 3.1 节末尾所述,这可以理解为执行模板匹配。

理由 1: 如果无乘法网络不能激发你的兴趣,我不知道还有什么能激发你的兴趣。像这样激进的想法总是值得一读。

原因 2: 也许所有投入到更快的浮点数学和硬件矩阵乘法上的努力可能都是徒劳的。

花絮:CNN 背后的原始灵感可以追溯到 1979 年,并被命名为 NeoCognitron 。然而,CNN 直到 2012 年才在它的许多理论实践问题得到解决之后才开始崭露头角。

延伸阅读:虽然有大量工作在寻找卷积替代方案,但也有大量人致力于用替代反向传播。简而言之,反向传播本质上是顺序的——我们一次训练一层。如果我们有一种算法可以并行训练所有层,我们会更好地使用当前的计算集群。

第八名 StyleGAN 3 (2021)

Karras,Tero,et al. 《无别名生成对抗网络》 神经信息处理系统进展 34 (2021)。

贯穿本文的一个不变主题是深度学*中的任何事情都可能改变或可能是错误的——甚至乘法也不安全。最初的 StyleGAN 论文从根本上改变了我们在 GAN 上使用噪声的方式。在第三次迭代中,作者邀请我们重新解释数据如何通过网络流动,而不是作为一个离散的实体,而是作为一个连续的信号。

简而言之,他们认为边界填充、上采样和 ReLU 等操作要么会泄漏位置数据,要么会给信号带来不必要的高频。实际上,这使得生成器学*不必要的偏差,例如始终将眼睛和鼻子放在相同的坐标上。通过改造这些元素,作者改进了*移和旋转的网络均衡性。

原因 1: 我们知道 CNN 是空间不变的,因为*面卷积是空间不变的。有时候事情比我们意识到的要复杂。这提醒我们应该如何灵活地对待我们所有的信仰。

理由 2: 所有这三篇 StyleGAN 论文都是关于数据可视化和表示的生动的一课。单从视觉效果来看,它们是值得打开的。

原因 3: 最近的生成模型,如 StyleGAN,显示了人工智能对于新颖的图形应用程序是多么成熟。也许这篇论文能启发你想出一些创业点子。

琐事:你可以使用外伏发生器来体验甘斯的强大力量(或者浏览此人不存在)

延伸阅读:几年前,只有 GANs 能做出好看的作品。如今,变分自动编码器(VAEs)赶上来了,但其他方法也出现了。下面是对深度生成模型(2021) 的最新综述。

#9 人工智能中的透明度和再现性(2020 年)

本杰明·海贝-卡恩斯等人《人工智能中的透明性和再现性》 性质 586.7829 (2020): E14-E16。

这篇文章不是一般的研究论文。相反,这是一封公开信,谴责谷歌的乳腺癌人工智能团队,比如说,不完整的论文。总之,谷歌声称它开发了一种用于乳腺癌筛查的人工智能,明显优于最先进的和人类放射科医生。然而,无论是代码还是数据集都没有发布,这让国际社会对这项工作产生了怀疑。此外,乳腺癌是女性死亡的主要原因之一,因此这篇论文引起了媒体的广泛关注。

由于这篇论文,原作者最终发布了文章的附录。他们进一步描述了技术方面和 OPTIMAM 数据集,该数据集包括研究中使用的英国数据集。然而,他们的答复证明大部分代码严重依赖内部基础设施,不能公开。

原因 1: 光有名气和大成绩是不够的。透明度和再现性很重要。确保你比谷歌做得更好。

原因 2: 得知谷歌同意发表原始论文,让人们对导致 Timnit Gebru 被谷歌解雇的所谓内部审查过程有了一些了解。

理由三:这篇论文是关于礼貌地批评别人工作的一课。引用摘要,“方法细节和算法代码的缺乏破坏了它的科学价值。"

延伸阅读:关于这个讨论,阅读原论文和作者随后的回复可以感兴趣。快进到 2022 年,虽然作者纠正了大多数问题,但最初的考虑不应被忘记:透明度和再现性是最重要的。

智力指标排名第十(2019)

弗朗索瓦,Chollet。 “论智力的衡量” arXiv 预印本 arXiv:1911.01547 (2019)。

虽然我之前列表中的大多数建议仍然适用,但这篇论文尤其值得重复,不是因为它具体的名气或结果,而是因为它带来的问题。在我们努力获得更精确的模型的同时,整个 AI 场景从更广泛的追求开始:什么是智能,我们如何人工创造它?

我相信我们还没有触及这个问题的表面。我们连智力是什么、如何测量都无法达成一致,更不用说意识等更深刻的概念了。在这篇论文中,弗朗索瓦·乔莱(Franç ois Chollet)尽力开发出可操作的定义,并为我们提供了 ARC ,一种学*算法的智商测试。

引用论文中的话,“为了朝着更智能、更像人类的人工系统稳步前进,我们需要遵循适当的反馈信号。”

理由#1: 虽然数据科学很酷也很时髦,但人工智能才是真正的东西。如果没有人工智能,就不会有数据科学。而它的终极目标并不是去发现对数据的洞察。取而代之的是制造能有自己想法的机器。所以,花点时间思考一些基本问题:什么是智力,我们如何衡量它?这篇论文是一个良好的开端。

原因#2: 在过去的几十年里,IA 社区被来自数理逻辑和演绎推理的思想所主导。然而,在没有任何形式的显式推理的情况下,支持向量机和神经网络在该领域的发展远远超过了基于逻辑的方法。ARC 会引发经典技术的复兴吗?

原因 3: 如果 Chollet 是正确的,我们仍然需要几年的时间来创建算法来解决 ARC 数据集。如果你正在寻找一个可以在业余时间玩的数据集,这里有一个可以让你忙起来:)

花絮:以防你不知道,Fran ois Chollet是 Keras 和神奇的深度学*用 Python 书背后的人。

延伸阅读:2018 年,Geoffrey Hinton、Yosha Bengio 和 Yan LeCun 因其在深度学*基础方面的开创性工作获得了图灵奖。2020 年,他们在 AAAI 会议上分享了他们对人工智能未来的看法。你可以在这里看。从深度学*的角度来看,它已经有将近两年的历史了,就像十年前一样。然而,看到他们当时的想法并将其与今天已经做的事情联系起来是很有趣的。

T21:他的一切都是为了现在。如果你对这篇文章或报纸有任何问题,请随时评论或与我联系。你也可以订阅我在这里发布的时候通知你

写这样的清单是一项很大的工作,所以,如果这是一篇值得阅读的文章,请与你的同龄人分享,或者在评论中给我一个阅读建议。谢谢大家!

如果你是中新,我强烈推荐订阅。对于数据和 IT 专业人士来说,中型文章是 StackOverflow 的完美搭档,对于新手来说更是如此。注册时请考虑使用我的会员链接。你也可以通过请我喝杯咖啡:)来直接支持我

感谢阅读:)

人工智能驱动的虚假信息,现在和未来

原文:https://towardsdatascience.com/ai-powered-disinformation-present-and-future-555cc56144e9

播客

卡佳·塞多娃论语言模型的恶意应用

苹果 | 谷歌 | SPOTIFY | 其他

编者按:TDS 播客由杰雷米·哈里斯主持,他是人工智能安全初创公司墨丘利的联合创始人。每周,Jeremie 都会与该领域前沿的研究人员和商业领袖聊天,以解开围绕数据科学、机器学*和人工智能的最紧迫问题。

直到最近,很少有人关注人工智能的潜在恶意应用。这有一定的道理:在一个人工智能范围狭窄、必须为每个应用程序专门构建的时代,你需要一个完整的研究团队来开发针对恶意应用程序的人工智能工具。由于这种人才在合法经济中工作更有利可图(也更安全),艾没有给恶意演员提供多少唾手可得的果实。

但是今天,这一切都改变了。随着人工智能变得更加灵活和通用,人工智能的建造目的与其潜在的下游应用之间的联系几乎消失了。大型语言模型可以被训练来执行有价值的任务,比如支持作者、在语言之间进行翻译或者编写更好的代码。但是,一个可以写文章的系统也可以写假新闻,或者为一大批类似人类的文本生成机器人提供动力。

与人工智能历史上的任何其他时刻相比,向规模化、通用基础模型的转移已经表明人工智能如何成为一把双刃剑。现在,这些模型已经存在,我们必须与它们达成协议,并找出如何建立社会,在面对引人注目的人工智能生成的内容和越来越容易获得的具有恶意使用潜力的人工智能工具时保持稳定。

这就是为什么我想与前国会议员和微软校友 Katya Sedova 交谈,她现在在乔治敦大学安全和新兴技术中心工作,她最近与人合著了一些有趣的作品,探索人工智能目前和未来可能的恶意使用。如果你喜欢这个对话,我真的建议看看她的团队的最新报告——它被称为“ AI 和虚假信息运动的未来”。

在这一集的 TDS 播客中,Katya 和我一起谈论了恶意的人工智能聊天机器人、假新闻的产生以及人工智能增强影响力活动的未来。

以下是我在对话中最喜欢的一些观点:

  • 当谈到人工智能增强的信息操作时,许多人正确地认为自动内容生成是一个主要的风险来源。但 Katya 指出,人工智能工具在虚假信息运动的早期阶段也很有用,当时一个恶意的演员试图了解其目标观众,以期找到可能获得牵引力的叙事或策略。情感分析、概念图和该分析阶段可能需要的其他任务——这些任务可以通过现有工具进行增强或自动化。
  • 许多虚假信息活动都有一个共同阶段,那就是建立基础设施,恶意参与者可以利用这些基础设施来推广他们的信息。例如,这种基础设施可以包括 Twitter 上的虚拟机器人账户,或者虚假的智库网站。人工智能可以以改变游戏规则的方式增强或自动化这一过程。例如,通过大幅降低类似人类的文本生成成本,语言模型可以允许社交媒体机器人定期发布与它们最初被创建来推动的叙事没有直接联系的主题。这将产生更多有机的、看起来合法的机器人,它们可以被用来积累追随者,并且更难被识别为不真实的。
  • 人工智能驱动的虚假信息战役变得非常复杂,并对人工智能的新发展做出快速反应。例如,在 thispersondoesnotexist.com(基于 StyleGAN2)公开发布的几周内,Katya 知道至少有一个国家支持的操作开始使用该工具为虚假的社交媒体机器人生成头像。她预计,一个复杂的恶意人工智能工具生态系统将越来越多地由专门的灰色市场“影响力即服务”公司开发和集成。
  • 类人文本生成的自动化(以及其他)引发了关于允许在线匿名的风险回报情况的问题。虽然匿名对于确保压制言论的国家的活动分子的安全至关重要,但它也使国内外的影响行动有可能大规模展开。
  • Katya 认为,人工智能行业和学术界应该投资于关于制定出版规范的热烈讨论,这些规范反映了开源算法可能产生的潜在影响,特别是当它们被用于虚假信息活动时。这些对话正在开始,但正如许多与人工智能相关的问题一样,这是一个必须在最后期限内完成的哲学问题。

你可以在推特上关注卡佳,或者我在这里

章节:

  • 0:00 介绍
  • 2:40 恶意使用人工智能
  • 4:30 过去十年在这个领域
  • 7:50 自动化的低手水果
  • 14:30 其他分析功能
  • 25:30 真实的机器人
  • 30:00 服务业的影响
  • 36:00 比赛到底
  • 42:30 系统自动化
  • 50:00 制造规范
  • 52:30 跨学科对话
  • 54:00 总结

人工智能寄存器 101

原文:https://towardsdatascience.com/ai-registers-101-7e2f58719781

责任人工智能系列

设计和部署支持有意义的透明性的 ADS 寄存器的简短指南

来源:图片由作者提供

术语重要提示:虽然经常被称为“AI”寄存器,但更合适的术语应该是“算法决策系统”(ADS)寄存器。

什么是语域?它如何实现透明性?

登记册是信息的正式记录。在其最简单的形式中,它可以提供对正在使用的算法系统的可*性,这是最基本的透明形式。它还可以被设计成实现有意义的透明度以满足利益相关者的信息需求。我在本文中探索的是后一种用例。

有意义的透明是人工智能伦理学中的一个重要概念。这意味着以最适合他们理解的方式交付与每个利益相关者群体相关的信息。在“高风险”系统中,这一点尤其重要,这些系统可能直接或间接影响个人可能获得的利益、惩罚或机会,在这种情况下,有意义的透明度是实现代理和问责的关键。

正如我在上一篇文章中所讨论的,算法政策和监管在很大程度上是滞后的。目前没有要求组织披露正在使用的算法系统。挑战这一现状的第一个重大进展是欧盟人工智能法案(2021) 草案,该草案将授权组织创建和维护人工智能系统和风险缓解措施的清单。如果实施,这些强制披露可能不会为受影响的群体实现有意义的透明度,因为它们的范围有限,但它们标志着向提供基本可*性迈出了有益的一步。

尽管缺乏监管,许多地方政府,如阿姆斯特丹、T2、昂蒂布、T4、赫尔辛基、南特、纽约,已经采取措施创建他们自己的算法注册。这些第一代登记册在复杂程度和完整性方面各不相同。它们通常也达不到实现有意义的透明度的“理想”,但仍然代表了向广告透明度迈出的良好一步。

从第一代算法寄存器中我们可以学到很多东西。基于从业者访谈的一个有趣的发现是,注册可以帮助激励广告所有者改善他们的内部治理和控制。它还可以促成公民驱动的问责机制,鉴于当前的监管环境,这一点至关重要。

算法寄存器在使负责任地使用算法决策系统中的潜在作用。来源:图片由作者提供。

如何设计和部署算法寄存器以实现有意义的透明性?

来源:作者图片

虽然登记册本身似乎是一个简单的工具,但启动登记册的大部分繁重工作都与维护和共享 ADS 披露所需的治理和流程有关。

本指南介绍了建立 ADS 注册的关键步骤,希望这一透明工具能够得到更广泛的应用。

第一步:就注册目标达成一致

从组织层面对成功的共同理解开始。这将是你衡量性能的标准,并在每次迭代中改进你的寄存器。

一些激励目标包括:

  • 在标准报告框架下跟踪计划、部署和停用的广告;
  • 满足公民信息需求,为受影响的群体提供代理;
  • 围绕 ADS 实施创建强有力的治理;
  • 能够符合现有的(或未来的)法规。

步骤 2:识别和理解利益相关者的需求

下一步是确定所有相关的内部和外部利益相关者,并了解他们与您的组织拥有的算法决策系统集相关的信息需求。

内部利益相关者包括负责算法决策系统的调试、开发、部署、使用和维护的团队。他们也可以包括高层领导和其他广告团队。

外部利益相关者可以包括监管和监督机构(如果授权)、公共利益团体(倡导者、记者、研究人员),以及直接或间接受算法决策系统影响的个人。

进行用户调查研究是发现复杂信息需求和测试与利益相关者沟通方式的一种有价值的方式。

例如,受算法决策系统影响的个人可能对算法和计算过程有不同程度的理解。有些人可能对这些主题一点都不精通,有些人可能有一些介绍性的概念,还有一些人可能很好奇,想亲自查看一下代码。作为受影响的个人,他们可能主要关心的是了解自己的结果并有机会进行补救。

来源:作者图片

另一方面,公共利益团体由通常在评估算法系统及其影响方面拥有技术专长的个人组成。他们注册的主要目的是获得验证负责任地使用算法系统所需的信息。

这项关于英国公民信息需求的研究为开展类似的用户研究提供了有益的参考。这项研究的一个有趣发现是,公民通常不关心算法透明度信息,除非他们个人碰巧对某个算法系统有问题。他们还希望透明度信息能够公之于众,不管他们个人对此有何兴趣,以此作为一种手段,使公共利益团体能够代表他们审查信息,并提出任何潜在的关切。

步骤 3:定义合适的参与模型

一旦确定了所有相关的利益相关者,您就必须定义适当的模型,以便在您的组织所使用的算法决策系统上与每个利益相关者合作。

在内部,应该有明确的角色和责任分配,以及正式的交接,并审查委托、设计、开发、维护和使用系统的不同团队之间的接触点。

在外部,根据法规,可能需要获得政府机构的批准或咨询。受影响的个人和公共利益团体也应该定期参与。在本文中,我将深入探讨这些公民参与模式。

在设计这种参与模型时,采用基于生命周期的方法非常重要,因为算法系统可以在部署后定期更新。对欧盟人工智能法案的主要批评之一是,它将广告提供商视为推出一次性产品的制造商,这些产品可以在发布时进行一次评估,这严重忽视了算法系统在部署后的发展程度。

关于算法系统最重要的决定通常是在系统开发前做出的。在这个阶段进行的参与接触点和评估对于保证算法系统的负责任的开发和使用是至关重要的。

下面是一个高风险算法系统参与模式的示例,该系统需要监管机构的批准,并与民间社会充分合作,以最大限度地降低伤害风险。

高风险算法决策系统的内部和外部利益相关者之间基于生命周期的参与模型(说明性的)。来源:作者图片

步骤 4:创建并采用 ADS 披露框架

在算法系统生命周期的每一步,都有关于适当的过程和系统正在实现的结果的重要信息需要捕捉。

广告生命周期的过程和结果相关披露的高级框架。来源:作者图片

每个披露都应该有一个指定的所有者,并应由其他利益相关者审查,以验证共享的信息。

以下是系统生命周期中建议披露的详细视图,包括披露所有人和建议接触点。

广告生命周期披露。来源:作者创作。

在利益相关者访谈和用户研究(步骤 2)中发现的*解应该有助于为每次披露提供沟通指南。

每个披露都应该以最能让关键利益相关者理解和代理的方式来编写和说明。

多层次算法披露。来源:作者图片

最完整的披露应记录在内部登记簿中。这些信息的子集可以公开共享,以最好地满足公民的信息需求。监管者、审计师和潜在公共利益团体应该通过数据共享协议获得相关私人信息的特权。

这就是我们所说的多层次披露。

系统所有者可能不愿意将他们视为“商业秘密”的源代码和其他元素公开。还有人担心,分享一个系统如何工作的微小细节可能会导致系统游戏。多级披露允许系统所有者与通过特权访问渠道提供的关键信息(如源代码)共享与每个利益相关者需求最相关的信息,利益相关者可在该渠道评估该信息并共享其评估结果(但不包括源代码)。

**

左图:阿姆斯特丹市政当局推出的自动停车控制系统的 ADS 流程图(面向非技术用户),来源;右图:Youtube 推荐引擎的广告架构模式(面向技术用户),来源

让我们考虑与算法决策系统的架构相关的披露——这可以帮助相关的利益相关者了解系统如何工作。例如,受到因不当行为而被罚款的自动停车系统影响的个人想知道该系统如何工作,而不必了解驱动广告的技术栈。他们感兴趣的是了解 ADS 是如何做出罚款决定的,该过程的哪些部分是由人审查的,以及质疑潜在错误决定的过程是什么。其他利益相关者可能希望从技术角度了解系统如何工作。这意味着理解所使用的处理步骤和方法,并且有可能访问代码和测试数据。

需要不同的信息集合,以使每个相关的利益攸关方获得有意义的透明度。登记册应该能够收集所有这些信息,并向每个利益攸关方披露适当的信息子集。

回到我们的自动停车系统的例子。公共登记簿应包括一个易于理解的流程图,解释系统如何做出罚款(或不罚款)的决定,并清楚地概述该过程的哪些部分由人类执行或监控。审计员和公共利益团体可以请求访问代码和详细的技术架构文档来执行评估。这就是多层次披露在实践中的样子。

步骤 5:设置采购服务的透明度要求

当您没有子系统的完全所有权时,交付透明性会变得复杂。事实上,算法系统的所有者采购第三方服务(如内置模型、开箱即用模型或专用企业解决方案的数据和 AI *台)是非常常*的。

大多数公共部门实体都有具体的采购指南,一些国家甚至在采购数据和人工智能相关服务时制定了具体的指南(例如英国)。我们开始看到公共部门从他们的第三方提供商那里制定具体的算法透明度要求。例如,市要求其供应商遵守“程序透明”(即建立适当的安全流程所需的信息),并在需要时向审计员提供“技术透明”(即源代码)。

私人组织应该利用他们的购买力来选择能够遵守透明度要求的供应商,并共同努力实现这些要求。在设计支持您注册的合作模式时,还应考虑第三方提供商。

第六步:设计注册用户界面/UX

设计在实现有意义的透明以满足不同利益相关者的需求方面起着至关重要的作用。

各种各样的利益攸关方应该能够以最有利于他们理解和代理的方式方便地访问登记册并找到他们需要的信息。

登记册的设计应遵循以人为中心的迭代方法,与核心利益攸关方接触,并将他们的反馈纳入设计流程。

这里的一些关键交付成果包括:

  • 为每个利益相关者角色定义用户旅程;
  • 定义关键用户交互;
  • 设计寄存器接口,说明披露架构、用户旅程和关键交互。

这里考虑边缘情况很重要。例如,低风险广告和高风险广告的用户体验有何不同?这将如何影响登记册的设计?

摘自阿姆斯特丹人工智能注册的市政当局的登录页面。

步骤 7:逐步推出和测试登记册上的算法系统

选择几个候选广告用于注册的测试版。理想情况下,这些广告应该处于生命周期的早期阶段(试运行阶段),以确保支持过程和治理能够捕获正确的信息。

像对待产品一样对待你的收银机。从 MVP 开始,测试,根据设定的目标测量性能,并迭代。

在第一个系统上线后,收集相关内部和外部利益相关方的反馈,并根据注册目标跟踪进度。通常,需要几个迭代周期来获得正确的寄存器和支持它的过程。

一旦你有了一个稳定的广告加入机制,是时候向组织的其他成员宣传了,并把所有的广告都加入到注册中。

走向更广泛的寄存器实现

大多数组织都有一些正在使用的内部广告日志,这些日志可能集中在一个地方,也可能不集中在一个地方。然而,组织很少公开共享这些信息(即使是其中的一部分)。

在本指南中,我试图阐述传播算法寄存器背后的动机,并提供实现它的指南。需要建立强有力的激励机制,以促进更广泛地采用登记册(可能通过监管)。我真的希望未来监管变化的前景和来自公民社会和公共利益团体的越来越大的压力将成为一个激励因素,促使组织在实现算法透明度时采取积极的方法。

在这方面,登记册是一个有用的工具;他们鼓励设置内部和外部治理,以确保负责任地使用和部署算法决策系统。

更深入:实现算法透明的参与式方法

在下一篇文章中,我将探讨如何让公民参与负责任地使用算法决策。

*https://medium.com/@mayamurad/participatory-approaches-to-algorithmic-responsibility-c349d0e96200

基于我的研究生论文“ 超越黑盒*”(MIT 2021)的一系列关于负责任的 AI 的一部分。提出的想法是基于几个在管理、部署和评估人工智能系统方面有直接经验的从业者的反馈和支持而发展起来的。我正在分享和开源我的发现,以使其他人能够轻松地研究并为这个领域做出贡献。**

人工智能升级:不容忽视的趋势

原文:https://towardsdatascience.com/ai-scaling-why-keeping-up-is-essential-and-how-to-do-it-56be3c2e1e5

Gladstone AI 播客第一集🎧

新一代人工智能系统如何改变商业战略、安全和公共安全的世界。

使用 DreamStudio 创建的人工智能生成的图像。

GPT-3 于 2020 年初问世,震惊了世界。

第一次,我们有了一个人工智能系统,它可以像人类一样书写文本,以至于读者始终无法分辨它是由人工智能生成的。不仅如此,GPT-3 还可以在不同语言之间进行翻译,编写代码,回答问题,等等。

这一切都归功于它的规模。GPT-3 是一个更大的模型,比以前开发的任何变压器具有更多的参数。它是用相当大的处理能力和相当大的数据集来训练的,这个数据集相当于当时互联网上所有的文本。

简单地扩展一个简单的变压器架构——一个已经存在了三年的架构!—我们可以达到相当高的一般智能水*,类似人类的文本生成能力让几乎所有人都感到震惊。但它产生了巨大的后果:通过建造 GPT-3 并以如此公开的方式向世界宣布,OpenAI 吸引了世界对人工智能扩展现象的关注。

从那以后,数十家其他公司推出了自己的超级人工智能模型,拥有越来越惊人的能力。谷歌人工智能,DeepMind,微软,英伟达,Cohere,AI21Labs,以及更多的西方集团已经加入了这场竞争。华为、浪潮、北京人工智能研究院和清华大学的中国实验室也接近人工智能扩展的前沿——尽管出口管制使他们更难获得对扩展人工智能至关重要的处理能力。

OpenAI 在 2020 年首次翻倍的 one-fringe AI 扩展策略现在正成为世界领先实验室事实上的共识。尽管 OpenAI 用 GPT-3 提出的具体配方后来被证明是次优的(正如 DeepMind 的 Chinchilla 所显示的),但事实仍然是:我们现在有一种可靠的方式来增加更多规模——更多数据、更多处理能力和更大的模型——并从我们的人工智能系统中获得更多智能和更多能力。

而且看不到尽头:正如过去几个月人工智能发展的惊人速度所显示的那样,规模似乎一直在产生回报。谷歌的 Minerva 模型可以解决本科水*的数学问题。DeepMind 的 Flamingo——以及此后的许多其他缩放多模态模型——表明缩放使人工智能能够处理和输出文本、图像、视频和其他数据,效果令人震惊。曾经科幻小说幻想的东西,文本到图像,文本到视频,实际上,文本到任何东西的模型现在都是*凡的日常现实。

错过这些发展中的任何一个都会导致严重的盲点。以下是我们在 Gladstone AI 播客的第一集中讨论的一些内容:

  • 如果你不知道文本到图像现在是可能的,你会更有可能购买社交媒体影响力运营,其中一些已经依赖于人工智能生成的图像来支持错误的叙述。(举一个简单且早已过时的例子,众所周知,俄罗斯特工曾利用 thispersondoesnotexist.com 的为他们的干涉活动生成虚假的推特个人资料图片。)
  • 如果你没有意识到语言建模的现状,你可能会错过部署可靠有效的全自动客户服务聊天机器人的机会。
  • 如果你没有跟踪人工智能驱动的代码生成,你可能不会意识到我们即将进入一个人工智能增强的恶意软件的新时代。
  • 如果你没有跟踪通用人工智能的突破,你可能不会意识到我们正在接近一个广泛人类智能的时代,在这个时代,人工智能事故成为全球灾难性风险的来源

跟上人工智能的当前发展水*正成为一种必须——不仅对数据科学家、数据分析师、MLEs 等来说如此,对完全非技术人员来说也是如此,他们和我们一样,以我们从未有过的方式直接受到前沿人工智能的影响。

这直接意味着,即将到来的人工智能时代最有价值的技能之一将是把新的技术发展转化为非技术语言的能力。随着人工智能的进步加速,实际人工智能和感知人工智能能力之间的差距将变得更大,一个组织的竞争能力将因其识别和利用最新人工智能工具的速度而成为瓶颈。生活在人工智能扩展的技术世界和商业战略的非技术世界之间的人将成为每个组织中最有价值的资产。

在未来的剧集中,我们将在人工智能最新进展的背景下,更详细地研究这些大的“现在是什么”问题。

🎧

Spotify

章节:

  • 零点介绍
  • 1:38 GPT-3 和人工智能缩放
  • 7:06 新应用的爆发
  • 9:40 为什么自动完成导致了人工智能革命
  • 13:03 人工智能扩展的战略意义
  • 17:27 风险:人工智能驱动的选举干扰、网络钓鱼和机器人
  • 27:40 风险:GPT 的禽流感事故-3
  • 31:30 风险:来自人工智能事故的全球灾难性风险
  • 35:50 总结

混合专家模型的人工智能缩放

原文:https://towardsdatascience.com/ai-scaling-with-mixture-of-expert-models-1aef477c4516

播客

Liam Fedus 和 Barret Zoph 关于计算高效、稀疏和缩放模型

苹果 | 谷歌 | SPOTIFY | 其他

编者按:TDS 播客由杰雷米·哈里斯主持,他是人工智能安全初创公司墨丘利的联合创始人。每周,Jeremie 都会与该领域前沿的研究人员和商业领袖聊天,以解开围绕数据科学、机器学*和人工智能的最紧迫问题。

人工智能的发展真的很快。自从 GPT-3 问世以来,很明显,我们需要做的事情之一是超越狭隘的人工智能,走向更普遍的智能系统,这将是大规模扩大我们模型的规模,它们消耗的处理能力和它们接受训练的数据量,同时进行。

这导致了一波大规模模型的浪潮,训练这些模型非常昂贵,很大程度上是因为它们庞大的计算预算。但是,如果有一种更灵活的方式来扩展人工智能——一种允许我们从计算预算中分离模型大小的方式,以便我们可以跟踪更有效的计算过程来扩展,会怎么样?

这就是所谓的混合专家模型(MoEs)的前景。与更传统的变形金刚不同,moe 不会在每次训练时更新所有的参数。相反,他们将输入智能地路由到称为专家的子模型,每个子模型可以专门从事不同的任务。在给定的训练过程中,只有那些专家的参数被更新。结果是一个稀疏的模型,一个计算效率更高的训练过程,以及一个新的潜在的扩展途径。

谷歌一直在推进 MoEs 研究的前沿,特别是我今天的两位客人,他们参与了这一战略的开拓性工作(还有许多其他工作!).Liam Fedus 和 Barret Zoph 是谷歌大脑的研究科学家,在这一集的 TDS 播客中,他们和我一起谈论了人工智能缩放、稀疏性以及 MoE 模型的现在和未来。

以下是我在对话中最喜欢的一些观点:

  • 专家模型混合通常包含一个路由模型或开关,它决定特定输入将被发送给哪个专家。Liam 和 Barret 仍然不确定对于一个给定的问题有多少专家是最佳的,他们已经测试了有 2 到 1000 个专家的系统。
  • 人们常说,人工智能的历史涉及研究人员逐渐了解到,他们应该将越来越少的假设硬编码到他们的模型中(这些假设被称为“归纳先验”)。例如,在从 2010 年之前的时代到深度学*时代的飞跃中,我们了解到决策树和支持向量机等固执己*的结构不如神经网络那样可扩展,神经网络似乎对数据“应该”如何处理做出更少的假设。同样,卷积网络和递归网络对图像中的*移不变性和文本中的标记排序做出了假设,现在这些假设看起来越来越没有必要,因为变压器在各自的专业领域优于这两种模型类型。因此,一个问题出现了:MoEs 是放松关于模型架构的假设的另一个步骤吗?如果是,它们到底放松了什么假设?
  • 在某种意义上,MoEs 可以被认为是密集变压器的更一般的版本。毕竟,密集变压器实际上只是一个专家的 MoE。出于这个原因,Barret 和 Liam 倾向于认为 MoEs 是从机器学*中去除归纳先验的进一步发展。
  • 历史上,MoEs 比密集模型遭受更多的训练不稳定性。其中一个原因与路由机制有关,该机制决定了哪个专家将看到给定的输入。因为该决定是离散的(必须选择专家的特定子集,并且您不能半选一个专家),所以样本通过 MoE 的路径可能会有很大的不同,根据路由器的输出,将它暴露给完全不同的专家。因此,反向传播变得更具挑战性。从工程的角度来看,由于与密集模型相比,moe 的参数数量较多,因此更难训练和部署。Barret 指出,一个常*的策略是按照专家的方式划分模型,在每个可用的 GPU 上训练一个专家。因此,当决定在您的模型中包含多少专家时,硬件的可用性成为一个关键的考虑因素。
  • moe 仍然在一般化上挣扎,当在新任务上进行微调时,表现往往比密集模型差一些。Liam 和 Barret 认为这是因为过度拟合,由于 MoE 模型的高参数计数,这成为一个特别重要的问题。但他们对可能克服这个问题的潜在正规化策略保持乐观,并认为 MoEs 可以在通用人工智能的未来发挥重要作用。

你可以在这里在 Twitter 上关注利亚姆,在这里在 Twitter 上关注巴雷特,或者在这里关注我

章节:

  • 0:00 介绍
  • 2:15 嘉宾背景
  • 8:00 了解专业化
  • 13:45 对未来的推测
  • 21:45 开关变压器与密集网络
  • 27:30 更多可解释的模型
  • 33:30 假设和生物学
  • 39:15 总结

人工智能、单细胞基因组学和计算生物学的新时代

原文:https://towardsdatascience.com/ai-single-cell-genomics-and-the-new-era-of-computational-biology-da12563c7707

播客

程昕婷·拉韦谈人工智能驱动的单细胞免疫学的前景

苹果 | 谷歌 | SPOTIFY | 其他

编者按:TDS 播客由杰雷米·哈里斯主持,他是人工智能安全初创公司墨丘利的联合创始人。每周,Jeremie 都会与该领域前沿的研究人员和商业领袖聊天,以解开围绕数据科学、机器学*和人工智能的最紧迫问题。

直到最近,对人类疾病的研究还包括观察大的东西——如器官或宏观系统——并弄清楚它们何时以及如何停止正常工作。但这一切都开始发生变化:近几十年来,新技术让我们能够通过检查单细胞的行为和特征,以更细致的方式来看待疾病。

其中一类技术现在被称为单细胞基因组学——在单细胞水*上研究基因表达和功能。单细胞基因组学正在创建由数千万个细胞组成的新的高维数据集,这些细胞的基因表达谱和其他特征已经过精心测量。这些数据集为人工智能驱动的药物发现开辟了令人兴奋的新机遇——初创公司现在开始正面应对这些机遇。

今天和我一起的是程昕婷·拉韦,Immunai 的计算生物学高级主管,Immunai 是一家利用单细胞水*的数据在工业规模上对免疫系统进行高分辨率分析的初创公司。在这一集的 TDS 播客中,程昕婷和我一起谈论了是什么让免疫系统成为现代医学如此令人兴奋的前沿,以及单细胞数据和人工智能可能如何为疾病治疗带来前所未有的突破。

以下是我在对话中最喜欢的一些观点:

  • 虽然器官和其他宏观结构很重要,但免疫系统的故事在很大程度上是 50 多种不同细胞类型的故事,这些细胞以复杂的方式与身体其他部分相互作用。许多表现出相似症状的疾病,如果源于不同免疫细胞类型的问题,可能会对不同的治疗产生反应。因此,对某些疾病的有效治疗需要在细胞水*上了解其潜在原因。
  • 不同进步的融合使得单细胞数据成为可能,这些数据来自微流体、光学和人工智能等不同领域。结果是,我们现在可以测量超过 20,000 个基因的表达水*,膜蛋白的组成,以及单个细胞的各种其他特征。这导致稀疏的高维数据集非常适合 ML 分析。(稀疏性的出现是因为基因组中的 20,000 个基因中的大多数实际上并不是由大多数细胞表达的。)
  • 这些数据集的一个特别有前途的用例是药物相互作用的研究。我们今天拥有的关于药物相互作用的大部分数据都是可疑的:有如此多的常用处方药,以至于同时研究两种以上药物之间的相互作用很快就会导致组合爆炸的可能性。药物相互作用的空间是巨大的,这使得它特别适合于利用压缩的潜在表示来进行预测的 ML 技术。
  • Immunai 还致力于预测不同细胞类型对治疗或药物的反应。为此,他们将单个细胞暴露于他们感兴趣的药物或扰动中,并测量其反应。但是这个过程很昂贵,所以实际上他们拥有的绝大多数数据并没有以这种方式标注。出于这个原因,他们大量使用半监督学*技术,这种技术可以从标记和未标记的数据中学*。
  • 程昕婷引用变压器网络作为一个与人工智能相关的突破,它被证明是单细胞数据分析的游戏规则改变者。更一般地说,标签的稀疏性和数据量的结合使得自回归技术在该领域特别有趣。在未来 3 年,程昕婷乐观地认为,像变形金刚这样的技术将在理解免疫行为和发现新的、更有效的药物方面带来重大突破。

章节:

  • 0:00 介绍
  • 2 点程昕婷的背景
  • 4:00 免疫系统和现代医学
  • 14:40 数据收集技术
  • 19:00 将细胞暴露于不同的药物
  • 24:00 标记和未标记的数据
  • 27:30 数据集状态
  • 31:30 最新算法进展
  • 36:00 癌症和免疫学
  • 接下来几年的 40:00
  • 41:30 总结

人工智能策略现在是一个国家定义的能力

原文:https://towardsdatascience.com/ai-strategy-is-now-a-nation-defining-capability-35f64bda1054

社区聚焦

人工智能策略现在是一个国家定义的能力

为菲律宾设计国家人工智能路线图,通过人工智能生态系统“良心”*衡创新和责任

在 Community Spotlight 系列中,TDS 编辑与数据科学社区成员畅谈有助于推动该领域发展的激动人心的计划。今天,我们很高兴与您分享埃利奥特·冈恩https://medium.com/u/aad1101621dd?source=post_page-----35f64bda1054--------------------------------与埃里卡·莱加拉【的对话,埃里卡·莱加拉是菲律宾亚洲管理学院的数据科学教授,也是菲律宾和新加坡政府机构的人工智能项目顾问。****

图片由 Erika Legara 提供

Erika 参与了新加坡和菲律宾的中小型企业(SME)、跨国公司(MNC)和政府机构的数百万美元的研发项目。2019 年,菲律宾政府聘请 Erika 和她的同事起草了国家人工智能路线图。

作为人工智能、基础设施、教育和智能治理方面的政府政策顾问,我很想更多地了解你的工作。你能分享一下你在菲律宾贸易和工业部起草国家人工智能路线图的角色吗?这个项目在哪些方面对菲律宾具有重要的战略意义?

许多企业和组织已经将数据科学和人工智能(DSAI)视为战略能力。它们不再是可选的,“最好拥有”的能力,而是必要的,“必须拥有”——关系到组织的生存。世界各地的领导者已经意识到,如果他们希望他们的组织保持相关性,甚至生存下去,他们必须具有竞争力和创新能力。因此,拥抱技术已经成为一种必然,尤其是分析,因为它的预测能力。

近年来,各国政府也开始认识到同样的事情,菲律宾也不例外。像军事能力一样,人工智能现在被广泛认为是一种定义国家的能力,特别是因为人工智能跨越了各个行业和部门。

最终,菲律宾政府的目标是通过创新和企业家精神来利用我们人民和资源的潜力。例如,当地贸易部贸易和工业部(DTI)正在实施包容性创新产业战略(i3S ),旨在发展制造业、农业和服务业中具有全球竞争力的创新产业。除其他技术外,DSAI 在实现这一目标、推动创新、数字化转型和提高行业竞争力方面处于前沿和中心位置。

DTI 与我和我的同事 Chris Monetrola 博士签订了合同,共同设计和制作菲律宾的人工智能路线图。它的制定是我们开发和实施人工智能战略、计划和项目的第一步,特别是帮助当地企业变得更有生产力和竞争力。在制定路线图的过程中,我带来了我在数据驱动科学方面的专业知识,以及与各种利益相关者合作的丰富经验,特别是在三螺旋项目上。我的另一部分职责是审查其他国家发布的现有人工智能政策和战略,确定菲律宾可以采用的最佳政策和实践,并根据我们的文化定制和调整这些原则和实践。最后,DTI 还要求我们分析该国的人工智能政策景观和生态系统。考虑到我们过去的 R&D 项目,我们还确定了具有有形社会经济效益的 DSAI 应用程序,包括短期和长期的。

你最喜欢或特别引以为豪的项目是什么?

除了设计国家人工智能路线图,我特别自豪的是最近与一家跨国公司(Aboitiz Group)、我们的学术机构(亚洲管理学院)、由国家经济发展局领导的各种政府机构以及一些地方政府单位合作的接触追踪项目。该项目是一个以数据换利益的志愿项目,旨在提高我国追踪接触者的能力,这一能力此前被确定为我国政府应对新冠肺炎疫情的“最薄弱环节”。

图片由 Erika Legara 提供

该项目由两个主要部分组成——第一部分涉及各种数据源的整合和协调,特别是来自新冠肺炎测试结果的案例数据库和接触者追踪应用程序数据库。第二,我们设计了算法来有效地建立联系追踪网络,并随后识别社区中的“脆弱”个体。

这个项目的一个很好的竞争者是智慧城市项目,在菲律宾的一个发展中的小城市 Cauayan 市,我参与了这个项目。这是第一个由我们的科学部——科技部(DOST)资助的智能城市项目。在学术上,城市科学当然令人兴奋;但与科学相比,与各种个人,尤其是领域专家(例如政策和工程)一起工作的经历同样令人兴奋。

我研究城市复杂性已经有一段时间了,我接触到的大部分作品只涉及对拥有丰富数据源和已经成熟的数据驱动文化的先进城市和经济体的研究。然而,当研究菲律宾等发展中经济体的城镇动态时,数据驱动的城市研究人员面临不同的挑战。

您对政府如何降低部署人工智能解决方案和干预与边缘化社区相关的脆弱性的风险有什么*解吗?

我是道德和负责任的人工智能的大力倡导者。因此,菲律宾国家人工智能路线图设计也强调了建立人工智能生态系统“良心”的重要性,它在计划中有自己的战略维度。该维度涵盖 DSAI 的数据隐私和更具争议的道德问题,推动建立可靠、安全、可靠、包容、负责和透明的预测*台。因此,我们对贸易和工业部的建议是建立一个专注于负责任的数据和人工智能技术的委员会或咨询委员会。理想情况下,该委员会将由决策者、法律专家、伦理学家、学者和 DSAI 实践者组成。此外,这方面的努力将与其他国家为数据和人工智能制定的其他负责任的道德准则相融合。

在人工智能和 DS 领域,你认为哪些项目最好由政府机构处理,而不是以营利为目的?

正如我们在这一领域的大多数人所知,DSAI 跨越部门和行业。事实上,确定一个 DSAI 无法产生影响的部门或行业,或者至少是技术无法应用的部门或行业,是一个相当大的挑战。

现在,在政府推动的 DSAI 项目中,这些项目将对人们的生活和生计产生直接影响;即改善人民福利的倡议。

政府机构也应该支持专门改善公共服务和其他政府程序的 DSAI 项目。在我看来,示例项目包括土地使用设计和开发、交通管理、减少灾害风险、改善公共卫生服务管理以及能源和水资源管理。

最后,这些机构在宪法上有义务确保菲律宾人得到公*和适当的待遇,并在没有恐惧或偏袒的情况下提供后者的服务,可能会刺激公*人工智能的倡议,特别是为当地人工智能公*奠定基础所需的法律、政策和判例框架。

你认为政府(在菲律宾或新加坡)在数据科学造福社会方面扮演着什么样的领导角色?

我认为政府是各种社会公益项目数据科学的主要推动者。首先,我希望他们能为 DSAI 提供战略方向,以最大限度地提高社会经济效益。其次,我也相信政策制定者能够为数据科学家和 DSAI 团队提供实际的使用案例,确定必须优先解决的关键社会经济问题,并用数据驱动的方法加以解决。比如某政府机构力推我参与的接触者追踪项目。事实上,当我在新加坡的时候,我参与的大多数 R&D 项目都是由政府机构支持的——从交通管理到土地使用设计,再到改善人类流动性。

除了用例,我还看到政府支持数据管理和推动开放数据计划,主要是因为政府收集了大量关于公民和环境的信息。

我已经提到过,政府机构可以刺激法律、政策和法理框架的发展,为当地的公*人工智能打下坚实的基础。但是,更普遍的是,政府有责任提供必要的法律和政策框架,为人工智能倡议创造一个健康的当地生态系统,同时防止或尽量减少这些倡议对菲律宾人造成的不同待遇或影响。

最后,我认为政府是企业、社会和其他部门在数字化转型和 DSAI 计划中的主要合作伙伴。我还认为,政府的角色是提供合适的环境、基础设施和服务,让其他组织从大数据、人工智能和第四次工业革命中的其他新兴技术中获得最大收益。

你喜欢什么样的 DS/ML 写作,你更希望看到什么?

我通常会去《走向数据科学》获取更多技术文章,然后去其他来源,如《哈佛商业评论》和《麻省理工学院斯隆管理评论》,获取关于数据和人工智能战略、数据科学领导力、建立和管理数据科学团队以及技术创新的主题。我希望从 DSAI 团队和他们的非 DSAI 合作者的角度,在 TDS 中阅读更多的 DSAI 用例及项目实现。从经验来看,许多中小企业和传统的大公司在他们的数字化转型和 DSAI 之旅中苦苦挣扎。因此,如果能更多地了解世界各地的利益相关者在拥抱 DSAI 时面临的挑战,以及(如果可能的话)为克服这些困难而实施的战略,那将是一件非常棒的事情。

在接下来的几个月/几年里,你对 DS/ML 社区有什么希望?

事实上,我对 DSAI 社会寄予厚望。一是我们继续参与数据驱动的项目,为社会造福;除了实际帮助社会,这也是该领域被那些不像我们一样接触数据驱动方法的人认可的一种方式。

我也希望我们,特别是那些在交叉领域工作的人,学*一下我们 DSAI 会议厅外的人是如何说话的。就背景而言,高管(非 DSAI)往往会对 DSAI 能为他们的组织做什么感到失望,因为他们的技术团队,即数据科学家,根本无法将人工智能的结果转化为他们可以理解的东西——转化为对业务有价值的*解。因此,企业和其他更传统的组织经常会问 DSAI 从业者,“那又怎么样?”我害怕自己陷入这种境地。我真诚地希望,在不久的将来,在 DSAI 从业者的帮助下,越来越多的组织接受更加数据驱动的文化。

最后,我希望我们作为 DSAI 的实践者对我们在算法创新方面的建设变得更加尽责——我们都将成为负责任和有道德的人工智能冠军。

好奇想了解更多关于莱加拉博士的工作吗?在推特LinkedIn 上关注她,查看她的网站。这是采访中提到的两个项目,展示了机器学*如何用于社会公益。

  • " ACCeSs@AIM-Cauayan City 智慧城市项目":le gara 博士是一个智慧城市项目的共同负责人,该项目旨在制定一个智能指数,能够可靠而准确地捕捉一个城市的“健康状况”。
  • 菲律宾人工智能路线图:Legara 博士和她的同事领导了菲律宾国家人工智能战略的发展。

Airbnb 数据科学家面试问题

原文:https://towardsdatascience.com/airbnb-data-scientist-interview-questions-9e2dfa7d9df2

本文将教你如何解决 Airbnb 数据科学家面试中的一个难题

作者在 Canva 上创建的图片

Airbnb 是最受数据科学家欢迎的公司之一。这是在住宿和酒店行业。虽然传统上,你不会想到这是一个数据科学家高度感兴趣的行业,但 Airbnb 不同。当然,这种差异反映在他们是一个在线住宿市场,连接着主人和客人。要做到这一点,他们依赖于数据和数据科学家。

你依赖于在工作面试中给人留下深刻印象。如果你有兴趣在 Airbnb 工作,那就是。让你更容易在面试中表现出色的事情之一是知道他们在 Airbnb 会问什么类型的问题。

另一件事是回答具体的问题,就像我们现在要讨论的问题。

Airbnb 数据科学家面试问题

主机人气租赁价格

Airbnb 面试中的一个难题是:

截图来自 StrataScratch

问题链接:https://platform . stratascratch . com/coding/9632-host-popularity-rental-prices

注意,*台上的问题略有修改。与视频相比,主要的区别是受欢迎程度分级类别和表格的名称。因此,这里的解决方案会略有不同,但方法是相同的。

数据

您可以使用 airbnb_host_searches 表来解决这个问题。

运行小部件中的代码来查看数据。

SELECT * 
FROM airbnb_host_searches;

应该是这样的。我们将只显示前三行。显示整个表格会占用太多空间。

截图来自 StrataScratch

解决方法

编写解决方案代码的方法可以分为以下几个步骤:

  • 找到不同的主机
  • 使用 CASE WHEN 语句创建流行度分级类别
  • 使用聚合函数查找每个类别的最低、*均和最高租赁价格
  • 按类别分组

解决方案假设

作者在 Canva 上创建的图片

当你参加数据科学面试时,陈述你的假设总是明智的。这样,面试官就能理解你的观点,并据此评估你的解决方案。如果你这样做了,你就可以避免你的解决方案因为没有解释解决方案中的假设而被扣分的可能性。

此外,通过陈述假设,你会对如何解决面试问题有一个更清晰的想法。对于这个 Airbnb 数据科学家面试问题,我们唯一的假设是:

  • “评论数量”列中的所有值都是整数,不会有空值

Airbnb 面试问题解决方案

我们应该遵循上面概述的步骤。

这里要做的第一件事是找到独特的宿主。问题的提示建议我们通过连接几个列来创建自己的 host_id。

SELECT DISTINCT CONCAT(price, room_type, host_since, zipcode, number_of_reviews) AS host_id,
          number_of_reviews,
          price
   FROM airbnb_host_searches

我们使用 CONCAT()函数创建主机 ID,并将查询写成 CTE。我们还需要关于每个主机的评论数量和价格的信息。

这个查询被写成一个名为 hosts 的 CTE。它将输出包含以下前几行的结果:

截图来自 StrataScratch

下一步是创建评级类别。为此,您需要使用 CASE WHEN 语句。最实用的方法是将查询的这一部分写成 CTE。

SELECT CASE
              WHEN number_of_reviews = 0 THEN 'New'
              WHEN number_of_reviews BETWEEN 1 AND 5 THEN 'Rising'
              WHEN number_of_reviews BETWEEN 6 AND 15 THEN 'Trending Up'
              WHEN number_of_reviews BETWEEN 16 AND 40 THEN 'Popular'
              WHEN number_of_reviews > 40 THEN 'Hot'
          END AS host_popularity,
          price
   FROM hosts;

如果同时运行第一步和第二步,代码将返回以下结果(仅显示前几行):

截图来自 StrataScratch

现在,我们必须计算最低、*均和最高价格,并根据主持人的受欢迎程度进行分组。为此,我们将编写带有聚合函数的 SELECT 语句,并使用代码的前一部分作为子查询,如下所示:

SELECT host_popularity AS host_pop_rating,
       MIN(price) AS min_price,
       AVG(price) AS avg_price,
       MAX(price) AS max_price
FROM
  (SELECT CASE
              WHEN number_of_reviews = 0 THEN 'New'
              WHEN number_of_reviews BETWEEN 1 AND 5 THEN 'Rising'
              WHEN number_of_reviews BETWEEN 6 AND 15 THEN 'Trending Up'
              WHEN number_of_reviews BETWEEN 16 AND 40 THEN 'Popular'
              WHEN number_of_reviews > 40 THEN 'Hot'
          END AS host_popularity,
          price
   FROM hosts) a
GROUP BY host_pop_rating;

所有三个 SQL 聚合函数都应用于 price 列,数据取自子查询。另一方面,子查询从 CTE 中获取数据。

如果将所有这些放在一起,最终的解决方案将是:

WITH hosts AS
  (SELECT DISTINCT CONCAT(price, room_type, host_since, zipcode, number_of_reviews) AS host_id,
          number_of_reviews,
          price
   FROM airbnb_host_searches)SELECT host_popularity AS host_pop_rating,
       MIN(price) AS min_price,
       AVG(price) AS avg_price,
       MAX(price) AS max_price
FROM
  (SELECT CASE
              WHEN number_of_reviews = 0 THEN 'New'
              WHEN number_of_reviews BETWEEN 1 AND 5 THEN 'Rising'
              WHEN number_of_reviews BETWEEN 6 AND 15 THEN 'Trending Up'
              WHEN number_of_reviews BETWEEN 16 AND 40 THEN 'Popular'
              WHEN number_of_reviews > 40 THEN 'Hot'
          END AS host_popularity,
          price
   FROM hosts) a
GROUP BY host_pop_rating; 

这个查询返回正确的答案。

截图来自 StrataScratch

结论

通过在数据科学工作面试中问这个问题,Airbnb 测试了几个重要的 SQL 概念。例如,使用 CONCAT()函数查找不同的值和操作数据。

第二个重要的概念是 SQL 聚合函数。此外,这个 Airbnb 数据科学家面试问题测试了您在陈述和分组数据时使用 CASE 的技能。

此外,为了让所有这些概念在一个非常简洁的查询中工作,您必须熟练地编写 cte 和子查询。除了你的技术知识之外,你对问题的理解程度和解决方法也是写出正确答案的重要因素。遵循结构化和编写 SQL 代码的最佳实践总是一个好主意!

使用气流装饰器创作 Dag

原文:https://towardsdatascience.com/airflow-dags-decorators-b5dc03c76f07

用 Python decorators 创作 Apache Airflow DAGs 和任务

柴坦尼亚电视台Unsplash 拍摄的照片

介绍

在气流中编写管道的最常*方式是使用 DAG 上下文管理器自动为该 DAG 分配新的运算符。从 Airflow 2 开始,您现在可以使用 decorators 来创作 Airflow DAGs 和任务。

在今天的教程中,我们将介绍这些装饰器,并展示如何使用它们来编写更简洁的代码。此外,我们还将演示如何使用更传统的方法编写相同的 DAG。

传统的方式

在 Airflow 中创作数据管道最常用的方法是使用 DAG 作为上下文管理器,自动为该 DAG 分配新的操作符。

例如,假设我们想要构建一个 ETL 管道,在这个管道中,我们将从外部 API 获取一些数据,对其进行转换,并最终将结果报告为标准输出。

为此,我们将创建三个简单的任务,如下所示。

import logging
import requests
from datetime import timedeltafrom airflow import DAG
from airflow.utils.dates import days_ago
from airflow.operators.python_operator import PythonOperator ENDPOINT = 'https://some-api.com/data'default_args = {
    'owner': 'airflow',
    'retries': 1,
    'retry_delay': timedelta(minutes=5),
}def _extract_data():
    return requests.get(ENDPOINT).json()['data']def _transform_data(data):
    return {'no_records': len(data)}def _load_results(no_records):
    logging.info(
        f'No. of records fetched by {ENDPOINT}: {no_records}'
    )with DAG(
    default_args=default_args,
    schedule_interval='@hourly', 
    start_date=days_ago(1),
):
    extract = PythonOperator(
        task_id='extract_from_api',
        python_callable=_extract_data,
    ) transform = PythonOperator(
        task_id='transform_data',
        python_callable=_transform_data,
        op_kwargs=[extract]
    ) load = PythonOperator(
        task_id='load_data',
        python_callable=_load_results,
        op_kwargs=[transform['no_records']]
    ) extract >> transform >> load

使用气流装饰器创作 Dag

从 Airflow 2.0 开始,你也可以使用 decorators 从一个函数创建 Dag。Python 中的 decorator 是一个函数,它接受另一个函数作为参数,修饰它(即丰富它的功能)并最终返回它。

DAG 装饰器创建一个 DAG 生成器函数,每个用@dag装饰器装饰的函数都将返回一个 DAG 对象。但是请注意,到目前为止,您只能对 Python 函数使用 Airflow 装饰器,通常您必须通过PythonOperator调用这些函数。

from datetime import timedeltafrom airflow.decorators import dag, task
from airflow.utils.dates import days_ago ENDPOINT = 'https://some-api.com/data'default_args = {
    'owner': 'airflow',
    'retries': 1,
    'retry_delay': timedelta(minutes=5),
}@dag(
    default_args=default_args,
    schedule_interval='@hourly', 
    start_date=days_ago(1),
)
def example_dag(): @task
    def extract():
        return requests.get(ENDPOINT).json()['data'] @task
    def transform(data):
        return {'no_records': len(data)} @task
    def load(no_records):
        logging.info(
            f'No. of records fetched by {ENDPOINT}: {no_records}'
        ) load(transform(extract()['no_records'])) dag = example_data()

正如你所看到的,decorators 帮助我们写了一个更干净、更简洁的代码。无需为每个单独的任务显式指定 PythonOperators,我们通过利用新的气流装饰器,仅用几行代码就创建了一个相当简单的 DAG。

最后的想法

在今天的文章中,我们展示了如何使用新的气流装饰器来创作任务和 Dag。这无疑是一个非常有前途的特性,但还不完全,因为它只能用于非常小的可用操作符子集。

此外,我对我们需要使用新符号来指定任务依赖关系的方式有点怀疑。对于复杂的依赖关系,语法会变得非常混乱,可读性也不好。总的来说,我认为这是一个很好的补充,至少可以用于一些基本的 Dag。

请注意,您甚至可以创建定制的装饰器,以满足您特定项目的需求。您可以在官方文档的相关章节中找到更多关于如何操作的信息。

成为会员 阅读介质上的每一个故事。你的会员费直接支持我和你看的其他作家。你也可以在媒体上看到所有的故事。

https://gmyrianthous.medium.com/membership

相关文章你可能也喜欢

气流,级长,和 Dagster:一个内部看看

原文:https://towardsdatascience.com/airflow-prefect-and-dagster-an-inside-look-6074781c9b77

约书亚·索蒂诺在 Unsplash 上拍摄的照片

现代数据堆栈的一大优点是与组成堆栈的所有不同组件的互操作性,但不幸的是,编排仍然是一个棘手的问题。数据管道仍然涉及定制脚本和逻辑,它们并不完全适合 ETL 工作流。无论是定制的内部服务,还是像下载文件、解压文件和读取内容这样简单的事情,仍然需要编排工具。

虽然现代数据堆栈确实提供了很大的灵活性,各种组件可以很好地相互配合,但能够协调整个堆栈的工作流仍然不是一个已解决的问题。

进入流程编排工具,如 Apache Airflow、Prefect 和 Dagster。这些工具是数据工程团队的面包和黄油。阿帕奇气流(Apache Airflow)是三者中最古老的一个,是一个经过战斗考验的可靠解决方案,它脱胎于 Airbnb,由 Maxime Beauchemin 创建。当时,数据工程是一个不同的世界,主要关注定期调度的批处理作业,这些作业通常涉及带有 Hive 和 Druid 等词的丑陋系统。今天你仍然可以在气流中看到很多这种传统。

Prefect 和 Dagster 是较新的产品,都受其云产品 Prefect Cloud 和 Dagster Cloud 的支持。Prefect Cloud 可以自由启动并托管一个调度程序,而混合架构允许您在本地或基础架构上运行任务。Dagster Cloud 刚刚发布,正在提前访问中!

什么是气流,它的顶级替代品是什么?

Airflow 是一个工作流编排工具,用于编排分布式应用程序。它通过使用 DAGs(有向无环图)在不同的服务器或节点上调度作业来工作。Apache Airflow 提供了一个丰富的用户界面,可以轻松地可视化管道中的数据流。您还可以监控每个任务的进度并查看日志。

如果你曾经对日期如何在气流中工作感到困惑,你会看到一些遗产。很少有人不被什么是执行日期以及为什么他们的 DAG 没有在他们期望的时候运行所迷惑。所有这些都是从午夜后一段时间运行日常工作的日子里滋生出来的。

来看看多年前的气流 1.4,来源:Github 上的气流

Airflow 现在是 Apache 的一个项目,Apache 基金会对它的采用巩固了该项目作为现状开源编排和调度工具的地位。今天,成千上万的公司使用气流来管理他们的数据管道,你很难找到一家大公司在他们的堆栈中没有一点气流。像天文学家和 AWS 这样的公司甚至提供托管气流作为服务,这样围绕部署和维护实例的基础设施就不再是工程团队关心的问题。

也就是说,随着数据环境的变化,在测试、非预定工作流、参数化、数据传输和存储抽象方面,Airflow 经常会遇到一些障碍。

气流的好处

在我们深入其中一些陷阱之前,有必要提一下气流的一些好处:毫无疑问,一个已经存在了十多年、得到 Apache 基金会支持、完全开源并被数千家公司使用的项目是一个值得考虑的项目。从很多方面来说,选择气流是最安全的选择,社区支持和被证明的有用性使它成为一个如此安全的选择,你甚至可能会说没有人因为选择气流而被解雇(可能)。

例如,与任何其他竞争对手相比,气流的堆栈溢出问题要多 2 个数量级。如果你有问题,你不是一个人,其他人有希望找到解决方案。几乎所有你能想到的工具都有气流提供器,使得用你现有的数据工具创建管道变得容易。

气流的问题

随着数据环境的不断发展,数据团队使用工具做的事情越来越多。他们正在构建复杂的管道来支持数据科学和机器学*用例,从各种系统和终端接收数据以将其收集到仓库和数据湖中,并为跨多个数据系统的终端用户工具编排工作流。有一段时间,气流是唯一真正可用的编排工具,因此许多团队试图将他们日益复杂的需求挤进气流,经常碰壁。

我们看到的气流部署的主要问题分为以下几类:

  • 本地开发、测试和存储抽象
  • 一次性和不定期计划的任务
  • 任务之间的数据移动
  • 动态和参数化的工作流

我们将通过探索两个替代工具 Dagster 和 Prefect 如何解决这些问题来深入研究每一个问题。

看看达格斯特和长官

Dagster 是一个相对年轻的项目,由尼克·施勒克于 2018 年 4 月启动,他之前是脸书 GraphQL 的联合创始人。同样,2018 年,耶利米·劳因(Jeremiah Lowin)成立了 Prefect,他在设计 Prefect 时吸取了作为阿帕奇气流(Apache air flow)PMC 成员的经验。

这两个项目都在解决一个共同的问题,但却有着不同的驱动理念。Dagster 采用第一性原理方法进行数据工程。它构建时考虑了整个开发生命周期,从开发到部署,再到监控和可观察性。另一方面,Prefect 坚持负面工程的哲学,建立在用户知道如何编码的假设上,并且尽可能简单地获取代码,并将其构建到分布式管道中,由其调度和编排引擎支持。

这两个项目都获得了很大的牵引力,并迅速改善。让我们来看看这两个项目是如何应对气流所面临的一些挑战的。

本地开发和测试

有了气流,本地开发和测试可能是一场噩梦。如果您的 production Airflow 实例使用 Kubernetes 作为执行引擎,那么您的本地开发也需要 Kubernetes,因为使用 S3Operator 编写的任务需要连接到 AWS S3 才能运行:这对于本地开发来说并不理想。

# In Airflow, the task writes to S3, using the S3 hook, and the function doesn't take any arguments.
def to_s3():
    path_file = 'test.csv'
    df = pd.read_csv(path_file)
    csv_buffer = StringIO()
    df.to_csv(csv_buffer)
    s3 = S3Hook(aws_conn_id='my_s3')
    s3.get_conn()
    s3.put_object(Body=csv_buffer.getvalue(),
                  Bucket=BUCKET_NAME,
                  Key='test.csv')task_to_s3_op = PythonOperator(
    task_id='UploadToS3',
    provide_context=True,
    python_callable=to_s3,
    dag=dag
)

对于 Dagster,计算和存储是两个不同的问题,可以抽象出来。您的函数接受输入和输出,而不是显式地向 DAG 提供特定的 Kubernetes 实例,这取决于在运行时配置的持久化数据的资源,无论是用于开发的本地临时文件,还是生产云中的加密对象存储。

# In Dagster, a function is explicit about  data frames as inputs and outputs. How these are persisted is defined at run-time, not in the code itself. 
@solid
def filter_over_50(people: DataFrame) -> DataFrame:
  return people.filter(people['age'] > 50)# Resource definitions can be swapped out depending on the environment through code
calories_test_job = calories.to_job(
    resource_defs={"warehouse": local_sqlite_warehouse_resource}
)
calories_dev_job = calories.to_job(
    resource_defs={"warehouse": sqlalchemy_postgres_warehouse_resource}
)

尽管通过 RunConfigs,Prefect 也支持存储上的抽象级别。

from prefect import Flow
from prefect.run_configs import KubernetesRun# Set run_config as part of the constructor
with Flow("example", run_config=KubernetesRun()) as flow:
    ...

然而,这并没有提供与 Dagster 相同的抽象级别,这使得本地开发更加棘手。对于 Prefect 来说,参数化是局部开发的重点。通过能够参数化您的流,您可以为本地开发提供较小的数据集,为生产使用提供较大的数据集。

计划任务

在 Airflow 中,计划外任务会导致许多意外问题,所有 DAG 都需要某种类型的计划,并且不可能在相同的执行时间内多次运行 DAG。

使用 Prefect,流程可以随时运行,因为工作流是独立的对象。由于其调度程序的工作方式,我们通常需要等待 5-10 秒才能让 Airflow DAG 从预定时间运行,而 Prefect 通过利用 Dask 等工具,实现了 DAG 和任务的快速调度。

同样,Dagster 为手动运行和计划 Dag 提供了很大的灵活性。您甚至可以根据时间表本身修改特定作业的行为,这是非常强大的。例如,如果您希望在周末和工作日提供不同的运行时配置。

@schedule(job=configurable_job, cron_schedule="0 0 * * *")
def configurable_job_schedule(context: ScheduleEvaluationContext):
    scheduled_date = context.scheduled_execution_time.strftime("%Y-%m-%d")
    return RunRequest(
        run_key=None,
        run_config={"ops": {"configurable_op": {"config": {"scheduled_date": scheduled_date}}}},
        tags={"date": scheduled_date},
    )

在 Dagster 中运行作业非常简单:

dagster job execute -f hello_world.py

气流中的数据流,提督和达格斯特

气流最大的难点之一是相关任务之间的数据移动。传统上,每个任务都必须将数据存储在某个外部存储设备中,使用 XComs 传递关于数据存储位置的信息(先不说 XComs 出现之前的情况),接下来的任务必须解析这些信息以检索数据并处理数据。

在 Dagster 中,作业的输入和输出可以更加明确。

import csvimport requests
from dagster import get_dagster_logger, job, op@op
def download_cereals():
    response = requests.get("<https://docs.dagster.io/assets/cereal.csv>")
    lines = response.text.split("\\n")
    return [row for row in csv.DictReader(lines)]@op
def find_sugariest(cereals):
    sorted_by_sugar = sorted(cereals, key=lambda cereal: cereal["sugars"])
    get_dagster_logger().info(
        f'{sorted_by_sugar[-1]["name"]} is the sugariest cereal'
    )@job
def serial():
    find_sugariest(download_cereals())

在上面的例子中可以清楚地看到,download _ 谷类操作返回一个输出,find_sugariest 操作接受一个输入。Dagster 还提供了一个可选的类型提示系统,以提供良好的测试体验,这在气流任务和 Dag 中是不可能的。

@op(out=Out(SimpleDataFrame))
def download_csv():
    response = requests.get("<https://docs.dagster.io/assets/cereal.csv>")
    lines = response.text.split("\\n")
    get_dagster_logger().info(f"Read {len(lines)} lines")
    return [row for row in csv.DictReader(lines)]@op(ins={"cereals": In(SimpleDataFrame)})
def sort_by_calories(cereals):
    sorted_cereals = sorted(cereals, key=lambda cereal: cereal["calories"])
    get_dagster_logger().info(
        f'Most caloric cereal: {sorted_cereals[-1]["name"]}'
    )

在 Prefect 中,输入和输出也很清楚,很容易连接在一起。

with Flow("Aircraft-ETL") as flow:
    reference_data = extract_reference_data()
    live_data = extract_live_data() transformed_live_data = transform(live_data, reference_data) load_reference_data(reference_data)
    load_live_data(transformed_live_data)

转换函数接受来自 reference_data 和 live_data 的输出。对于大文件和昂贵的操作,Prefect 甚至提供了缓存和持久化输入和输出的能力,从而在调试时缩短开发时间。

动态工作流

Dagster 和 Prefect 的另一个很棒的功能是创建动态工作流的简单界面,这是 Airflow 所缺少的。

在 Prefect 中,参数可以在云接口中指定,或者显式地提供给 Flow runner。这使得扩展到大型复杂计算变得容易,同时允许在管道上工作时进行合理的初始开发。

在 Dagster 中,您可以定义一个图,然后对该图进行参数化,以允许动态配置,这是完全定制资源、配置、挂钩和执行器的能力。

from dagster import graph, op
from dagster import ResourceDefinition@op(required_resource_keys={"server"})
def interact_with_server(context):
    context.resources.server.ping_server()@graph
def do_stuff():
    interact_with_server()prod_server = ResourceDefinition.mock_resource()
local_server = ResourceDefinition.mock_resource()prod_job = do_stuff.to_job(resource_defs={"server": prod_server})
local_job = do_stuff.to_job(resource_defs={"local": local_server})

包扎

我希望这是对一些新的编排工具的有益探索,这些工具已经开始在数据领域获得牵引力。尽管 Airflow 有缺点,但它仍然是一个可靠的、架构良好的*台,可以很好地为许多人服务。然而,这一领域的竞争只会有助于改进所有的工具,因为它们可以相互学*和改进。我很期待看到这个领域的发展,也很想知道你的想法。

您使用的是哪个调度程序?您是否有迁移气流的计划?请在下面评论或者在 Twitter 或者通过电子邮件告诉我!

喜欢这个关于 ETL 编排的内容吗?阅读更多关于下一代 ETL: 反向 ETL ,或联系 Hightouch 的Pedram 团队。

深度学*中的任意和认知不确定性

原文:https://towardsdatascience.com/aleatoric-and-epistemic-uncertainty-in-deep-learning-77e5c51f9423

它们之间的区别以及如何用张量流概率处理它们

来源:像素

包括深度学*在内的机器学*与各个方面出现的不确定性密不可分。在这篇文章中,我们将讨论任意不确定性和认知不确定性之间的区别,这两种不确定性,特别是在深度学*的背景下。我们还将给出一个张量流概率的例子来形象化这两种类型的不确定性。请查看笔记本了解更多代码详情。

任意与认知的不确定性

区分认知不确定性和随机不确定性的一种方法是检查是否可以通过更多的知识来减少不确定性。事实上,“认知的”一词来自希腊语“επιστήμη”,可以粗略地翻译为知识。

这两种不确定性来源的一个例子是判断一个人是否为 covid 阳性。更多的临床试验和医学实验将减少认知上的不确定性,导致对病毒更好的理解和更有说服力的诊断,而我们永远无法对我们的结论 100%确定,因为随机性质导致的随机不确定性。

在深度学*的背景下,我们更愿意将经典的神经网络视为一个概率模型:给定一个输入 x,网络的最后一层给出一个概率分布,要么是分类情况下的类集,要么是回归情况下的预测点。在这种情况下,认知不确定性通常被解释为神经网络参数的不确定性,如果我们有一个包含更多所需信息的数据集,这种不确定性可以减少。另一方面,随机不确定性出现在通过最大似然推断实现的概率预测本身中。

许多研究人员一直专注于量化机器学*环境中的两种不确定性。一种想法是测量总不确定性和随机不确定性,并将认知不确定性视为两者之间的差异[1]。

TFP 模型化不确定性

在本节中,我们将使用TensorFlow Probability(TFP),这是一个基于 tensor flow 构建的 Python 库,它可以轻松地在现代硬件上结合概率模型和深度学*,以在简单的合成数据集上建模不确定性。我们将在这个例子中看到,我们可以减少认知的不确定性,但不能减少随机的不确定性。

下图显示了代码中使用的数据集。这里,橙色点仅代表全部数据的 10%。在下文中,我们将在“完整数据集”和“部分数据集”上训练相同的模型,以查看添加更多数据是否有助于减少不同类型的不确定性。

作者图片:TFP 模型中使用的数据

任意不确定性

我们用下面的代码来考虑任意的不确定性:

该模型仅包含两个层:一个传统的密集层,具有两个输出神经元,用作下面的分布λ层的*均值和标准偏差值。

我们在整个数据集和具有较少点的数据集(上图中的橙色点)上训练模型,并获得以下结果。我们可以立即注意到,在不同数据集上训练的模型产生了相似的结果,添加更多的数据不会减少任意的不确定性。

作者图片:任意的不确定性

认知不确定性

认知不确定性会发生什么?现在让我们看看下面的代码:

与我们之前所做的不同,这里的模型包含了一个稠密的变化层。这一层使用变分推理来拟合核矩阵和偏置项上的分布的后验概率,否则偏置项就像密集层一样使用。在机器学*中,变分推理是马尔可夫链蒙特卡罗(mcmc)的一种替代方法来逼近后验分布。

像以前一样,我们在整个数据集和具有较少点的数据集上训练模型。我们注意到,在下图中,当我们在更大的数据集上训练模型时,标准偏差更小。换句话说,这个例子表明更多的数据可以减少认知的不确定性。

作者图片:认知的不确定性

任意和认知的不确定性

对于那些感兴趣的人,我们可以把这两种不确定性放在一个单一的模型中,用下面的模型:

结论

在这篇文章中,我们讨论了任意不确定性和认知不确定性的区别,并用一个简单的例子说明了 TFP 的区别。然而,在结束这篇文章之前,我想说的最后一句话是,任意的和认知的不确定性不应该被视为绝对的概念。改变环境会改变不确定性的来源,有时我们很难区分。

参考

[1]t .德弗里斯和 g .泰勒(2018 年)。神经网络中非分布检测的学*置信度。

你的模型做出不公*预测的 5 个原因

原文:https://towardsdatascience.com/algorithm-fairness-sources-of-bias-7082e5b78a2c

常*偏差来源— 历史偏差代理变量不*衡数据集算法选择用户交互

(来源: flaticon )

从表面上看,机器学*看起来不偏不倚。算法没有种族、民族、性别或宗教等敏感特征的概念。所以他们不应该对某些群体做出有偏*的决定。然而,如果任其发展,他们就会这样做。为了纠正有偏*的决策,我们首先需要了解偏*来自哪里。

我们将讨论不公*决策的 5 个原因。其中三个原因涉及用于训练模型的数据。即历史偏差代理变量不*衡数据集。最后两个原因涉及算法选择用户如何与模型互动。一路上,我们还讨论了这些如何与机器学*中更一般形式的偏差相关联。即测量偏差、表征偏差和聚合偏差。

偏*与公*

在我们深入研究之前,让我们澄清一些事情。偏*可能是一个令人困惑的术语。它在许多领域被用来指代一系列问题。在 ML 中,偏差是在模型开发过程中产生的任何系统误差。这些错误可能是不正确的假设或代码错误造成的。它们可以在数据收集、特征工程或培训过程中引入。甚至你部署模型的方式也会引入偏*。

例如,假设我们想要选择一个最终模型。为此,我们选择具有最高训练精度的模型。我们假设训练精度是未来模型性能的良好反映。不幸的是,这是一个不正确的假设。该模型可能过度适合于训练集。这种偏*可能会导致一些不正确的预测。

(来源: flaticon )

“公*”是指不因个人或群体的特点而对他们有任何偏*。对于“偏*”有一个类似的通俗定义。偏*是对一个人或一群人的偏*。更糟糕的是,在算法公*领域,还有第三种偏*的定义。我们可以把【偏差】称为任何导致模型变得不公*的错误。在本文中,我们将在定义之间跳转。上下文应该清楚地表明使用的是哪一个。

偏*的来源

基于以上,似乎所有的模型都是不公*的。机器学*的要点是根据群体的特征来区分群体。所以,定义我们所说的“特征”是很重要的。当分析公*时,我们指的是敏感的特征。这些因素包括种族、民族、原籍国、性别或宗教。在一个数据集中,这些特征被称为 保护变量

有许多原因可以解释为什么一个模型对这些群体中的一个不公*。在模型开发的任何时候都可能出错。然而,并不是所有的错误都会导致不公*的模式。某些错误/偏*更有可能导致不公*的模型。我们将在下一章讨论这些。

图 1:偏*来源概述(图片由作者提供)

原因一:历史不公

过去,某些群体受到歧视。这可以通过法律有意地发生,也可以通过无意识的偏*无意地发生。无论什么原因,这种历史偏*都可以反映在我们的数据中。模型的设计是为了适应数据。这意味着数据中的任何历史偏差都可以反映在模型本身中。

历史偏*可以以不同的方式表现出来。少数群体的数据更有可能丢失或记录不正确。目标变量可能反映不公*的决策。当目标变量基于人的主观决定时,这种情况更有可能发生。最近的一个例子来自亚马逊开发的用于帮助自动化招聘的模型。

来源: flaticon

亚马逊使用历史申请者的简历来训练他们的模型。目标变量基于接受或拒绝工作申请的决定。问题是,由于招聘人员的偏*,大多数成功的申请者都是男性。妇女被拒绝是因为她们的性别,而不是她们的资格。这种偏差最终会反映在目标变量中。该模型学会了将女性简历的特征与落选候选人联系起来。实际上,它甚至惩罚了“女人”这个词(例如女子足球队队长)。

测量偏差

数据中的历史偏倚与 测量偏倚 的概念有关。在机器学*中,我们需要定义特征或标签。这些作为其他更复杂或不可测量的结构的代理。首先,当一个代理是一个坏的结构替代品时,测量偏差就发生了。如果代理不是跨不同组统一创建的,也会发生这种情况。

对于招聘模式来说,历史决定就是标签。它是候选人能力的代表。问题是这些决定并不是一致做出的。男性和女性候选人受到不同的待遇。换句话说,代理在不同的组中是不一致的。在这种情况下,历史偏差导致了测量偏差。

原因 2:代理变量

我们上面提到过 被保护变量 。这些是代表种族或性别等敏感特征的模型特征。使用这些特征会导致不公*的模型。通常,正常特征可以与受保护特征相关或关联。我们称之为代理变量。使用代理变量的模型可以有效地使用受保护的变量来做出决策。

例如,在你生活的南非,你的种族是很有预*性的。这是由于该国的种族隔离历史。您可以在图 2 中看到我们的意思。开普敦市仍然因种族而分裂。这意味着在模型中使用某人的邮政编码可能会导致种族歧视。

图 2:按居民种族划分的开普敦地图(来源: stats SA

理解代理变量时,关联和因果关系之间的区别很重要。假设我们正在构建一个模型来预测客户是否会拖欠贷款。一个理性的人会同意某人的种族不会导致他们的风险改变。事实上,甚至不是他们的位置改变了他们的风险。这是他们的经济地位。然而,模型只关心联想。不幸的是,在南非,种族、地理位置和经济地位都是相关联的。

原因 3:不*衡的样本

假设我们计算人口的*均结婚年龄。我们得到的值是 33。看一下图 3,我们可以看到这个值并不代表所有的子群体。宗教团体的*均年龄为 28 岁,要低得多。由于非宗教团体的规模,*均值有所偏差。换句话说,人口*均水*更接近非宗教群体。

图 3:人口*均值如何被扭曲的例子(图片由作者提供)

模型参数也会以类似的方式倾斜。模型试图捕捉整个训练群体的趋势。但是,在不同的子组中,模型特征可以有不同的趋势。所谓趋势,我们指的是特征和目标变量之间的关系。如果一个群体占人口的大多数,模型可以偏向于该群体内的趋势。因此,少数群体的模型性能可能会更差。

我们可以在图 4 中看到一个倾斜数据集的例子。ImageNet 是用于训练图像识别模型的大型数据集。在这里,我们可以将不同的国家视为亚组。像出租车、餐馆和婚礼这样的概念出现在数据集中。这些在不同的国家可能看起来非常不同。问题是大多数图片来自北美和欧洲。这导致来自中国(1%)和印度(2.1%)等国家的图像表现不佳。

图 ImageNet 数据集的地理多样性。al

表征偏差

这种偏差来源与代表性偏差有关。代表性偏差是指发展人群未能很好地推广到所有亚组。与 ImageNet 一样,如果对某些子群体关注不够,这种情况也会发生。一些数据集甚至可以反映出有意排斥少数民族的决定。在这种情况下,开发人群并不能很好地代表目标人群。

即使开发人群完美地代表了目标人群,代表性偏差仍然可能发生。根据定义,少数群体将占人口的较小比例。这意味着他们在发展人口中所占的比例也将减少。这可能会导致我们上面讨论的模型倾斜的问题。

原因四:算法选择

前三个偏差来源都与数据有关。我们对所用算法的选择也会导致公*性问题。首先,一些算法比其他算法更难解释。这使得识别偏差来源和纠正偏差变得更加困难。另一个主要因素是模型的目标。这就是模型被训练的目的。

(来源: flaticon )

实际上,使用成本函数来训练模型。典型地,成本函数被设计成最大化某种精确度。这就是模型预测目标变量的精确程度。最大化准确性不一定会导致不公*的决定。然而,由于我们没有优先考虑公*,我们将更有可能以不公*的决定而告终。除非我们调整成本函数来考虑公*性,否则我们无法保证决策的公*性。

聚集偏差

成本函数还有另一个问题。也就是说,他们通常旨在最大化整个开发群体的准确性。如果群体由不同的子群体组成,这可能会导致问题。该模型在总体上表现良好,但对其中一个分组表现不佳。这类似于我们上面讨论的代表性偏差。只不过现在我们讨论的是模型而不是数据。

我们可以看到数据和算法选择中的偏差是如何结合起来产生不公*的决策的。数据集内的表示偏差会导致模型内的聚集偏差。类似地,算法可以使用一个代理变量来最大化准确性。它不在乎使用这些变量是否会导致不公*的决策。

原因 5:用户反馈循环

偏*的最后一个来源与我们如何与模型互动有关。一旦训练完成,模型将被部署。随着用户与模型的互动,我们将收集更多的数据来训练模型的未来版本。用户与模型交互的方式可能会引入偏差。模型中的现有偏差会导致新数据中的进一步偏差。

(来源: flaticon )

例如,假设我们开发了一个用于预测某人是否患有皮肤癌的模型。由于表征偏差,当人具有浅色皮肤时,模型表现得更好。可以理解,有色人种可能会避免使用我们的模型。因此,我们只会从针对浅色皮肤的诊断中收集数据。这将放大代表性偏差,并在未来导致更有偏差的模型。

因此,在部署模型之前,我们需要测量偏差,确定其来源并加以纠正。在这篇文章中,我们关注了偏*的来源。知道来源是关键。它将帮助您决定纠正它的最佳解决方案。未来的一篇文章将关注测量偏差,另一篇文章将关注校正偏差。

我希望这篇文章对你有帮助!你可以成为我的 推荐会员 来支持我。你可以访问 Medium 上的所有文章,我可以得到你的部分费用。

https://conorosullyds.medium.com/membership

你可以在|Twitter|YouTube|时事通讯上找到我——注册免费参加 Python SHAP 课程

图像来源

所有图片都是我自己的或从www.flaticon.com获得。在后者的情况下,我拥有他们的保费计划中定义的“完全许可”。

参考

Pessach,d .和 Shmueli,e .(2020),算法公*性https://arxiv.org/abs/2001.09784

Mehrabi,n .、Morstatter,f .、Saxena,n .、Lerman,k .和 Galstyan,A .,(2021),关于机器学*中的偏*和公*的调查https://arxiv.org/abs/1908.09635

Chouldechova,a .和 Roth,a .,(2018),机器学*中的公*前沿https://arxiv.org/abs/1810.08810

Wickramasinghe,S. (2021),机器学*中的偏差&https://www.bmc.com/blogs/bias-variance-machine-learning

Suresh,h .和 Guttag,j .(2021),一个理解机器学*生命周期中伤害来源的框架https://arxiv.org/abs/1901.10002

《卫报》,亚马逊抛弃了偏爱男性从事技术工作的人工智能招聘工具 (2018),https://www . the Guardian . com/technology/2018/oct/10/Amazon-hiring-AI-gender-bias-recruiting-engine

大科技的算法行为修正正在削弱学术数据科学研究

原文:https://towardsdatascience.com/algorithmic-behavior-modification-by-big-tech-is-crippling-academic-data-science-research-c600d4fe696b

意*

主要*台如何使用有说服力的技术来操纵我们的行为,并日益扼杀有社会意义的学术数据科学研究

我们社会的健康可能取决于让学术数据科学家更好地访问企业*台。马特·西摩在 Unsplash 上的照片

这篇文章总结了我们最近发表的论文 自然机器智能中通过数字*台 进行算法行为修改的新领域中学术数据科学研究的障碍。

一个由数据科学学者组成的多元化社区使用 行为大数据 (BBD)进行应用和方法研究。BBD 是由我们日常使用互联网和社交媒体*台、移动应用程序、物联网(IoT)小工具等产生的关于人类和社会行为、行动和互动的大型和丰富的数据集。

虽然缺乏对人类行为数据的访问是一个严重的问题,但缺乏关于 机器行为 的数据也日益成为数据科学研究进展的障碍。有意义且可推广的研究需要访问人类和机器行为数据,并访问算法机制对人类行为产生因果影响的或相关信息。然而,这样的机会对大多数学者来说仍然遥不可及,甚至对那些在名牌大学的人来说也是如此。**

这些访问障碍提出了新的方法、法律、道德和实践挑战,并有可能扼杀对数据科学研究、公共政策和监管的宝贵贡献,而此时迫切需要对全球集体行为的循证、非营利管理

*台越来越多地使用 说服技术 来自适应地、自动地定制行为干预,以利用我们的心理特征和动机。照片由班农·莫里西Unsplash 上拍摄

下一代顺序适应性说服技术

脸书InstagramYouTube抖音这样的*台是庞大的数字架构,面向用户数据的系统收集、算法处理、流通和货币化。*台现在实施数据驱动、自主、交互和顺序自适应的算法来大规模影响人类行为,我们称之为算法*台行为修正 ( BMOD )。

我们将算法 BMOD 定义为数字*台上旨在影响用户行为的任何算法动作、操纵或干预。两个例子是用于预测文本的自然语言处理 (NLP)算法和强化学*。两者都是用来个性化服务和推荐(想想脸书的 News Feed ),增加用户参与度,产生更多的行为反馈数据,甚至通过长期*惯形成“钩住”用户。

在医疗、治疗和公共卫生领域, BMOD 是一种可观察和可复制的干预措施,旨在在参与者明确同意的情况下改变人类行为。然而,*台 BMOD 技术越来越不可观察不可复制,并且没有明确的用户同意。

至关重要的是,即使*台 BMOD 对用户可*,例如,作为显示的推荐、广告或自动完成的文本,外部研究人员通常也无法观察到。只能访问人类 BBD 甚至机器 BBD(但不能访问*台 BMOD 机制)的学者被有效地限制在基于观察数据研究干预行为。这对(数据)科学不利。

*台已经成为外部研究人员的算法黑匣子,阻碍了非营利数据科学研究的进展。来源:维基百科

算法 BMOD 时代推广研究的障碍

除了增加错误和遗漏发现的风险,由于算法混淆,回答因果问题变得几乎不可能。在*台上进行实验的学者必须尝试对*台的“黑盒”进行逆向工程,以便从他们自己的影响中理清*台的自动干预(即 A/B 测试、多臂强盗和强化学*)的因果影响。这个经常不可行的任务意味着使用*台在其内部实验系统上公开发布的任何少量信息来“猜测”*台 BMOD 对观察到的治疗效果的影响。

学术研究人员现在也越来越依赖涉及机器人和虚拟用户账户的“游击战术”来探索*台算法的内部工作,这可能会使他们陷入法律危险。但是,即使知道*台的算法,也不能保证理解它在拥有数百万用户和内容项的*台上部署时的最终行为。

图 1: 用于 BMOD 和预测的人类用户的行为数据和相关机器数据。行代表用户。学术界不知道或无法获得重要和有用的数据来源。来源:作者。

图 1 说明了学术数据科学家面临的壁垒。学术研究者通常只能访问 公共用户 BBD (例如,分享、点赞、帖子),而 隐藏用户 BBD (例如,网页访问、鼠标点击、支付、位置访问、好友请求) 机器 BBD (例如,显示的通知、提醒、新闻、广告)和 兴趣行为 (例如,点击、停留时间)

学术数据科学研究人员面临的新挑战

企业*台和学术数据科学家之间的鸿沟越来越大,这可能会扼杀关于长期*台 BMOD 对个人和社会的影响的科学研究。我们迫切需要更好地理解 BMOD *台在促成心理操纵成瘾政治极化中的作用。除此之外,学术界现在还面临着其他几个挑战:

  • 更复杂的伦理审查 大学机构审查委员会 (IRB)成员可能不了解*台使用的自主实验系统的复杂性。
  • 新的出版标准 越来越多的期刊和会议要求证明部署的影响,以及对用户和社会的潜在影响的道德声明。
  • 可复制性较低的研究 *台研究人员或与学术合作者使用 BMOD 数据的研究不能被科学界复制。
  • 公司对研究结果的审查 *台研究委员会可能会阻止发表批评*台和股东利益的研究。

学术隔离+算法 BMOD =碎片化社会?

学术孤立的社会影响不应该被低估。算法 BMOD 在无形中工作,可以在没有外部监督的情况下部署,放大公民和外部数据科学家的 认知碎片 。不知道其他*台用户看到什么和做什么,减少了围绕数字*台在社会中的目的和功能进行富有成效的公开讨论的机会。

如果我们想要有效的公共政策,我们需要公正可靠的科学知识,了解个人在*台上看到什么和做什么,以及他们如何受到算法 BMOD 的影响。

脸书告密者弗朗西丝·豪根向国会作证。来源:维基百科

我们的共同利益需要*台透明和可访问性

前脸书数据科学家和告密者 Frances Haugen 强调透明和独立研究者访问*台的重要性。在她最近的美国参议院证词中,她写道:

….没有人比脸书更能理解脸书的破坏性选择,因为只有脸书有机会一探究竟。有效监管的一个关键起点是透明度:完全获取非脸书指导的研究数据。只要脸书在暗中运作,不让公众看到它的研究,它就是不负责任的。如果放任不管,脸书将继续做出违背我们共同利益的选择。

我们支持 Haugen 对更大的*台透明度和访问的呼吁。

学术孤立对科学研究的潜在影响

更多详情请参*我们的论文

  1. 进行了不道德的研究,但没有发表
  2. 更多未经同行审评的出版物,例如关于第十四次评估报告的出版物
  3. 错位的研究主题和数据科学方法
  4. 对科学知识和研究的寒蝉效应
  5. 支持研究主张的困难
  6. 培训新数据科学研究人员的挑战
  7. 浪费的公共研究基金
  8. 错误的研究努力和无足轻重的出版物
  9. 更多基于观察的研究和研究倾向于更容易访问数据的*台
  10. 对数据科学领域的声誉损害

学术数据科学何去何从?

学术数据科学家在这一新领域的角色仍不清楚。我们看到学术界出现了新的职位和职责,包括参与独立审计,与监管机构合作监督 BMOD *台,开发评估 BMOD 影响的新方法,以及在流行媒体和学术机构中引导公众讨论。

打破当前的障碍可能需要超越传统的学术数据科学实践,但在算法 BMOD 时代,学术隔离的集体科学和社会成本太大,不容忽视。

医疗保健中的算法偏差及其缓解策略

原文:https://towardsdatascience.com/algorithmic-bias-in-healthcare-and-some-strategies-for-mitigating-it-835abe28df7

当心你的人工智能系统中的偏*:有时这是生死攸关的事情

图片由国立癌症研究所Unsplash 上拍摄

介绍

不知道你怎么样,我第一次接触 AI 是在全是智能机器人的电影里。他们的行为让我相信,整个世界都会被那些愤怒的机器征服。

但是我的信念已经改变了,因为现在,我相信人工智能可以做得比试图毁灭世界更好。

人工智能可以改善医疗保健,拯救世界各地数百万人的生命。

但是什么是人工智能🤖?

人工智能有多种定义,大多数都集中在同一个意思上。以下是我对人工智能的三点定义。

  • 这是教育算法使用大型复杂数据集像人类一样行动的过程。
  • 它在训练过程中从数据中学*,以保持稳定,从而做出更好的决策。
  • 这些模型一旦在非常大的患者数据上进行训练,就可以做出比真正的人类专家更准确的预测。

例如,在医疗保健领域,人工智能正被用于提供正确的诊断和治疗建议,所有这些都需要对结果进行清晰的解释。

人工智能在医疗保健中的图示(图片由作者提供)

被称为深度学*教父的杰弗里·辛顿在 2016 年发表的声明引起了放射科医生的注意:

人们现在应该停止培训放射科医生。很明显,在 5 年内,深度学*将会比放射科医生做得更好

然后,一年后, CheXNet 和来自斯坦福大学的 6 名放射科医生在接受了数千张图像(肺炎和非肺炎)的训练后,在最近的一次测试中进行了 50 次肺炎胸部 x 光检查。你猜怎么着:ChexNet赢了81% accuracy79% accuracy of the 6 Radiologists

ChexNet Vs. 6 放射科医生在胸部 x 线诊断(图片由作者提供)

出于训练目的,该模型被给予了数万张图像(肺炎和非肺炎)。

这是许多突出人工智能如何执行通常由医生执行的任务的项目之一。性能表明这些算法在诊断疾病方面变得更好了多少,甚至有时具有如上所示的更好的性能。

等等,你是在告诉我们人工智能是医疗保健中所有完美的顶峰吗?

不,人工智能不仅仅是医疗领域的荣耀

尽管有这些承诺,人工智能的使用并非没有法律风险。我们可以从这两个案例中说明人工智能是如何导致医疗保健领域对个人的歧视 你可以从如何减轻医疗中的算法偏差的新闻中了解这两个案例的更多细节。

你可能知道,种族偏*仍然是一个问题,但当它被传播到医疗保健领域时,情况会变得更糟,因为在这里,这是一个生死攸关的问题。

第一例→联合健康集团

Optum (UnitedHealth group)开发了一种商业算法,以确定哪些患者需要额外的医疗护理(医疗需求最大的患者)。

算法中的偏差使得需要额外护理的黑人患者数量减少了一半以上,并错误地得出结论,黑人患者比同样患病的白人患者更健康。

为什么会这样?

任何明显的种族信息(如肤色、邮政编码等。)实际上是在算法训练过程中使用的。但种族与其他因素相关,如历史医疗支出,以评估未来的医疗需求,这使得它反映了经济不*等,而不是病人的真正医疗需求。

根据凯泽家族基金会 (KFF)…

  • 家庭更有可能将年度预算的 1%用于医疗保健。
  • 低收入住房的*均医疗支出是 235 美元,而私人保险是 2401 美元。

我们知道 Optum 正在通过连接和服务 150 个国家的整个卫生系统来推动卫生保健,我们已经可以想象这种偏*对人们生活的影响。

第二个案例→新冠肺炎的药物发现

在新冠肺炎期间,开发了一个人工智能系统来对病人进行分类,并加快新疫苗的发现。

人工智能系统能够以 70%至 80%的准确率预测哪些患者可能会患严重的肺部疾病。

这个人工智能系统的问题是,分诊过程仅仅基于患者的症状和先前存在的状况,这可能是有偏*的,因为基于种族和社会经济地位的差异。

减轻算法偏差的 5 种策略

这些年来,人工智能模型发展迅速。与此同时,我们也看到了许多失误。人工智能系统中的偏*最终导致了一个不公*的社会。

以下五个策略(不是一个详尽的列表)可以用来减轻这些偏*。

  1. 收集和使用多样化的训练数据 :算法中偏差的一个主要原因是使用了不代表真实世界人群的训练数据。为了缓解这种情况,收集和使用不同的训练数据是很重要的,这些数据准确地反映了将对其使用该算法的人群的人口统计、背景和特征。
  2. 测试算法的偏差 :在一个算法被训练之后,测试它的偏差是很重要的,以确保它做出公*和无偏*的决策。这可以通过多种方法来实现,包括进行偏*审计和使用公*指标来衡量算法的性能。
  3. 使用算法公*技术 :有几种算法公*技术可以用来减轻算法中的偏差,包括调整数据以减少偏差的预处理算法,在训练过程中进行调整的处理中算法,以及调整算法输出以使其更加公*的后处理算法。
  4. 确保透明度和问责制 :减少算法偏差的另一个重要步骤是确保算法透明和问责。这意味着对算法如何工作提供清晰的解释,定期审查和更新算法以消除任何可能引入的偏*,并为个人提供质疑算法所做决定的机制。
  5. :最后,与多元化的利益相关者(包括可能受算法影响的个人和社区)进行互动非常重要,以便了解他们的观点,并将他们的反馈纳入算法的设计和实施中。这有助于确保算法是公*和公正的,并且它准确地反映了将要使用它的人群的需求和关注。

这些最佳实践的局限性。

偏*以不同的形式存在,处理起来很有挑战性,并且可能发生在开发生命周期的不同阶段。

  • 历史偏*:当收集来训练人工智能系统的数据不再反映当前现实时,就会出现这种情况。例如,尽管性别薪酬差距仍然是一个问题,但在过去这一问题更为严重。
  • 代表性偏差:这种偏差的结果取决于如何定义训练数据以及如何从人群中取样。这种场景的一个例子是用于训练第一个面部识别系统的数据,这些数据主要依赖于白人面孔,这导致模型很难识别黑人面孔和其他深色皮肤的面孔。
  • 测量偏差:当训练数据特征或测量与真实数据不同时出现。这是图像识别系统的常*问题,其中数据主要从一种类型的摄像机收集,而现实世界的数据来自多种类型的摄像机。
  • 编码/人类偏*:这通常发生在科学家带着他们对研究的主观想法深入一个项目的时候。例如:“非白人患者接受的心血管干预和肾脏移植较少”,以及“黑人妇女在被诊断患有乳腺癌后更有可能死亡”。* 来源*

结论

对于任何数据项目,尤其是医疗保健项目,不要忘记人工智能中的潜在偏*,这一点很重要。

早期采用正确的系统,并在整个项目生命周期中保持它们,可以帮助快速识别主要问题,并以有效的方式对它们做出响应。

请记住,让我们非常小心,非常有意识地设计那些人工智能系统。

如果你喜欢阅读我的故事,并希望支持我的写作,考虑成为一个媒体成员。每月支付 5 美元,你就可以无限制地阅读媒体上的故事。

欢迎在媒体推特YouTube 上关注我,或者在 LinkedIn 上打招呼。讨论人工智能、人工智能、数据科学、自然语言处理和人工智能是一种乐趣!

额外资源

健康算法中的种族偏*

新冠肺炎和种族/民族差异

算法解释#1:递归

原文:https://towardsdatascience.com/algorithms-explained-1-recursion-f101500f9316

通过 Python 中的示例了解何时以及如何使用递归解决方案

这是用 Python 示例解释算法系列的第一篇文章。这是为有抱负的数据科学家和软件工程师或那些希望在准备编码面试中复*算法的人准备的。

图片由 Gerd AltmannPixabay 拍摄

在学*数据结构和算法时,递归是编程中的一个基本概念。在本文中,我将解释什么是递归,何时使用递归,并浏览一些用 Python 3 编写的例子。

什么是递归?

递归是指函数或方法调用自身,它对于分治范式是必不可少的,其思想是将较大的问题分成较小的子问题,子问题是原始问题的某个常数部分。递归的工作方式是通过单独解决较小的子问题,然后将结果聚集起来返回最终的解决方案。

什么时候使用递归?

递归经常用于本质上是递归的问题。这包括具有父子关系的图、树和数据结构。递归问题的一些典型例子是计算第 n 个斐波那契数,计算一个数的阶乘,以及将十进制数转换成二进制数。

为什么我应该使用递归?

正确使用时,递归解决方案通常会产生更清晰、更易读的代码。当求解本质上是递归的解时,它更直观,我们将在后面的例子中看到。但是,请记住,递归解决方案的内存效率可能较低,如果您的计算机内存耗尽,或者您的函数在到达基本情况之前堆栈过深,将会导致堆栈溢出错误。

我如何构造一个递归算法?

要编写递归算法,首先需要将问题分成两部分,第一部分是基本情况,第二部分是递归步骤:

  1. 基本情况:基本情况是指停止调用递归函数需要满足的条件。这是终止递归函数并返回结果之前的结束状态或最后一个待评估的事例。如果没有基本情况,你的递归函数将会无限循环下去,永远不会终止!
  2. 递归步骤:这是递归调用同一个函数的代码部分,使用每次递归调用都更新的输入来计算结果。每一次迭代都应该让你更接近基本情况。

示例 1:使用递归确定第 n 个斐波那契数列

在斐波纳契数列中,数列的第一项和第二项分别是 0 和 1。要计算位置 n 的数字,可以取前面两项的和,即位置(n-1)的数字+位置(n-2)的数字。斐波纳契数列 F 可以用数学方法表示如下:

  • F(1) = 0
  • F(2) = 1
  • F(n) = F(n-1) + F(n-2)

我们将定义一个函数fibonacci(),它将一个数字 n 作为参数,并返回斐波那契数列中位置 n 处的数字。这个问题可以用多种方法解决,但在递归解决方案中,我们可以将问题分解为以下两个部分:

  1. 基本情况:如果 n 为 1,则返回 0,因为斐波那契数列的第一项为 0。如果 n 是 2,则返回 1,因为数列的第二项是 1。
  2. 递归步骤:对于 n 的所有其他值,我们可以通过将前面两项相加来计算位置 n 处的数字:fibonacci(n-1) + fibonacci(n-2)。

以下是计算斐波纳契数列中第 n 个数字的递归解决方案的 Python 实现:

def fibonacci(n):
   if n == 1:
      return 0
   if n == 2:
      return 1
   return fibonacci(n-1) + fibonacci(n-2)

例 2:计算第 n 个阶乘

第 n 个数的阶乘是从 1 到 n 的所有整数的乘积,比如 5 的阶乘就是5! = 1 * 2 * 3 * 4 * 5 = 120。注意 0 的阶乘是 1,负数的阶乘是未定义的。

我们将定义一个函数factorial(),它将一个数字 n 作为参数,并返回 n 的阶乘。为了用递归解决这个问题,我们必须把它分解成以下两种情况:

  1. 基本情况:如果 n = 0 或 1,返回 1。如果 n < 0,返回错误,因为负数的阶乘未定义。
  2. 递归步骤:用前一项的结果乘以 n,即n * factorial(n-1)

以下是计算第 n 个阶乘的递归解决方案的 Python 实现:

def factorial(n):
   if (n == 0 or n == 1):
      return 1
   if n < 0:
      raise Exception("n must be positive. The factorial of a negative number is undefined.")
   return n * factorial(n - 1)

示例 3:将十进制整数显示为二进制

在日常生活中,最常用的数字系统是十进制数,它的基数是 10。对于数字系统,通常使用二进制数字系统,其基数为 2。

将十进制数转换为二进制数的一种方法是将该数除以 2,并记录下每一步的余数,然后以相反的顺序(从下到上)写出余数,这就是整数的二进制等效值。例如,二进制的十进制数 36 是:

36/2 = 18r0→18/2 = 9r0→9/2 = 4R1→4/2 = 2r0→2/2 = 1r0→1/2 = 0R1

以相反的顺序收集余数,我们得到 100100 作为十进制数 36 的二进制数。

我们将定义一个函数convert_to_binary(),它接受十进制数 n ,并以整数列表的形式返回二进制数。为了递归地解决这个问题,我们可以把它分成两部分:

  1. 基础案例:如果 n 等于 0,返回一个整数为 0 的列表。如果 n 等于 1,则返回一个整数为 1 的列表。
  2. 递归步骤:对商(数字 n 除以 2)调用函数convert_to_binary(),并跟踪该操作的余数。

以下是将十进制数转换为二进制数的递归函数的 Python 实现:

def convert_to_binary(n):
   if n == 0:
      return [0]
   elif n == 1: 
      return [1] 
   remainders = convert_to_binary(n // 2)
   remainders.extend([n % 2])
   return remainders

结论

递归是一个基本的编程概念,在编码面试中很流行。递归的一些常*用例是具有父子关系的数据结构。编写递归解决方案的关键是首先定义基本情况,然后考虑递归步骤。递归通常会产生更简洁的代码,但它可能没有内存效率高。

更多请看本算法讲解系列: #1:递归(本期文章) #2:排序#3:搜索#4:贪婪算法#5:动态规划#6:树遍历

算法解释#2:排序

原文:https://towardsdatascience.com/algorithms-explained-2-sorting-18d0875528fb

三种排序算法的解释及其在 Python 中的实现

图片由 200 度来自 Pixabay

在前一篇文章中,我介绍了递归,我们将在这篇文章的基础上构建排序算法。排序算法用于重新排列数组中的元素,使每个元素都大于或等于其前一个元素。有许多不同类型的排序算法,我将介绍三种最常*的值得熟悉的算法:选择排序、插入排序、合并排序。

作为演示如何应用每种排序算法的例子,假设您正试图按作者的姓氏对书架上的 n 本书进行排序。

选择排序

在选择排序中,首先在整个书架中查找作者姓氏出现在字母表中最早的那本书,并将该书放在书架的开头,从左数第 1 个位置。接下来,我们将从位置 2 的书开始,向右移动,在剩余的子数组中查找其作者的姓氏出现在字母表中最早的书,然后将该书放在位置 2。重复这个过程,直到槽 n — 1 ,我们将使用选择排序完成整个书架的排序。

为了在 Python 中实现选择排序算法,我们需要跟踪两个子数组:已排序的子数组(当前索引 i 右侧原始数组中的元素)和剩余的未排序子数组(当前索引 i 左侧原始数组中的元素)。对于原始数组中的每个元素,我们需要遍历剩余的未排序子数组中的元素,以找到最小的元素,并将其与当前索引 i 中的元素交换。

选择排序算法的时间复杂度是 O(n ),因为该算法中有两个 for 循环。

def selection_sort(arr):
   n = len(arr)
   for i in range(n):
      # Find smallest element in the remaining indices of the array
      min_idx = i
      for j in range(i + 1, n):
         if arr[j] < arr[min_idx]:
            min_idx = j # Swap smallest minimum element with the element in position i
      arr[i], arr[min_idx] = arr[min_idx], arr[i]

   return arr

插入排序

在插入排序中,第一个 I 索引中的元素与最初在第一个 I 索引中的元素相同。类似于选择排序,我们从左到右遍历原始数组的每个元素。但是,这一次我们将比较当前索引 i (key)处的元素与当前索引右侧的已排序子数组中的每个元素,直到我们找到一个不超过当前元素的元素,并将它放在这个新位置。

插入排序算法的时间复杂度的上限是 O(n ),当数组中的元素顺序相反时会出现这种情况,因为内部 while 循环必须遍历已排序子数组中的每个元素。如果所有元素都已排序,并且内部 while 循环不必进行任何迭代,则插入排序算法的时间复杂度的下限是 O(n)。

def insertion_sort(arr):
   n = len(arr)
   for i in range(1, n):
      key = arr[i]
      j = i - 1 # Compare key to every element in the 
      # sorted subarray until the key is smaller 
      # than the current element 
      while j >= 0 and key < arr[j]:
         arr[j + 1] = arr[j]
         j -= 1 # Insert key in identified position
      arr[j + 1] = key return arr 

合并排序

合并排序是一种分治算法,我们将问题分解成子问题,递归地解决子问题,然后将子问题的解决方案组合起来解决原始问题。在我们的图书分类示例中,我们将如何应用分而治之:

  1. Divide :将数组分成两半;
  2. 征服:递归排序上一步得到的两半书中的书籍。基本情况发生在子阵列中只剩下一本书的时候;
  3. 合并:将排序后的两半合并在一起。

合并排序的运行时复杂度为 O(n log n ),因为将数组分成块需要 O(log n)时间,对每个块进行排序需要线性时间来合并两半。

def merge_sort(arr):
   # Terminating base case
   if len(arr) < 2:
      return arr
   else:
      # Divide array into two subarrays
      midpoint = len(arr) // 2
      left = arr[:midpoint]
      right = arr[midpoint:] # Sort subarrays
      sorted_left = merge_sort(left)
      sorted_right = merge_sort(right) # Merge sorted subarrays
      sorted_arr = []
      while len(sorted_left) > 0 and len(sorted_right) > 0:
         # Compare first elements of subarrays
         if sorted_left[0] < sorted_right[0]:
            sorted_arr.append(sorted_left[0])
            sorted_left.pop(0)
         else:
            sorted_arr.append(sorted_right[0])
            sorted_right.pop(0) # Insert remaining items in sorted subarrays
      sorted_arr.extend(sorted_left)
      sorted_arr.extend(sorted_right) return sorted_arr

结论

选择排序、插入排序和合并排序是需要了解的典型排序算法。Python 示例旨在帮助演示这些算法在实践中如何工作。在算法解释系列的下一部分,我将介绍搜索算法。

更多请看本算法讲解系列: #1:递归#2:排序(本期文章)、 #3:搜索#4:贪婪算法#5:动态规划#6:树遍历

算法解释#3:搜索

原文:https://towardsdatascience.com/algorithms-explained-3-searching-84604e465838

通过 Python 中的线性和二分搜索法示例了解搜索

图片来自 PixabayClker-Free-Vector-Images

搜索算法对于检索存储在数据结构中的一个或多个元素是有用的。搜索算法适用的一些问题示例包括检索数据库中的特定记录或搜索文章中的关键字。

搜索算法通常分为两种类型:

  1. 顺序搜索:顺序搜索算法可以在有序或无序的数据结构上执行。该算法遍历数据结构并按顺序检查每个元素,直到找到所需的元素。线性搜索就是一个例子。
  2. 区间搜索:要执行这种类型的搜索,底层数据结构必须已经排序。因此,给定一个排序的数据结构,区间搜索算法递归地在中点将搜索空间分成两半,直到找到想要的元素,因此它比顺序搜索算法更快更有效。二分搜索法就是一个例子。

线性搜索

给定一个已排序或未排序的数组,线性搜索从索引 0 开始,遍历数组中的每个元素,直到找到目标项并返回其索引。如果没有找到目标元素,返回-1。

该算法的时间复杂度为 O(n)。这是因为在最坏的情况下,目标项是数组中的最后一个元素,我们将不得不遍历整个数组中的每一项,导致 n 次比较。

def linear_search(arr, target):
   for idx, num in enumerate(arr):
      if num == target:
         return idx
   return -1

二进位检索

给定一个已排序的数组,二分搜索法的工作方式是在数组的中点将数组一分为二,并将目标元素与数组中的中间元素进行比较。如果目标元素小于中间的元素,则继续搜索数组的左半部分。否则,如果元素大于中间的元素,则继续搜索数组的右半部分。重复这个过程,直到目标元素等于中间元素,并返回它的索引。如果没有找到目标元素,返回-1。

二分搜索法算法的时间复杂度是 O(log n ),因为我们每次迭代都将搜索空间分成两半。

def binary_search(arr, start, end, target):
   while start <= end:
      midpoint = start + (end - start) // 2
      mid_elem = arr[midpoint] # if target is greater, ignore the left half
      if target > mid_elem:
         binary_search(arr=arr, start=midpoint+1, end=end, target=target) # if target is smaller, ignore the right half
      elif target < mid_elem:
         binary_search(arr=arr, start=start, end=midpoint-1, target=target) # otherwise target is equal to midpoint
      else:
         return midpoint return -1

结论

在本文中,我们讨论了两种重要的搜索算法——顺序搜索和区间搜索。线性搜索是时间复杂度为 O(n)的顺序搜索的经典示例,而二分搜索法是时间复杂度为 O(log N)的更高效的区间搜索的常用示例。

更多请看本算法讲解系列: #1:递归#2:排序#3:搜索(本期文章)、 #4:贪婪算法#5:动态规划#6:树遍历

算法解释#4:贪婪算法

原文:https://towardsdatascience.com/algorithms-explained-4-greedy-algorithms-f60792046d40

对贪婪算法的解释以及用 Python 实现的分数背包和硬币兑换问题的解决方案

图片来自 PixabayClker-Free-Vector-Images

贪婪算法通常是一种实用的方式来找到一个体面和优雅的,虽然不总是最优的,优化问题的解决方案。它的工作原理是做出一系列选择,并在每个决策点总是选择下一个最佳选择。一类这样的问题是活动选择问题,我们试图在各种竞争活动中安排资源。

贪婪算法通常具有以下两个属性:

  1. 贪婪选择性质:选择局部最优(贪婪)选择导致全局最优解,意味着每一步的贪婪选择都会产生全局最优解。
  2. 最优子结构:整个问题的最优解也包括子问题的最优解。换句话说,最优解与第一步是一致的,这种解决子问题的一般策略也可以用来解决整个问题。

在接下来的几节中,我们将介绍两个可以用贪婪算法解决的经典例子。

背包问题

背包问题是优化问题的一个典型例子,其中的前提是一个窃贼正在抢劫一家有 n 件物品的商店,每件物品的价值为美元,重量为磅。窃贼想要最大化被盗物品的价值,但是他们的背包只能装最大重量的物品,他们应该拿什么物品呢?

这个问题有两个版本:

  • 0–1 背包问题:这也叫做离散背包问题,因为物品要么被拿走,要么不被拿走。对于这个问题,贪婪解产生局部最优解,但不总是全局最优解,因为项目是不可分的。因此,我们将在下一篇文章中研究如何使用动态编程找到这个问题的最优解。
  • 分数背包问题:这也叫连续背包问题,因为窃贼可以拿走一个物品的分数。对于背包问题的这种变体,贪婪算法将总是产生最优解。

要解决分数背包问题,首先计算每件物品的每磅价值( v_i/ w_i )。然后,在每个决策点,做出贪婪的选择,小偷尽可能多地拿走每磅价值最高的物品,直到他们达到最大重量 W ,背包满了。

分数背包问题的时间复杂度是 O(n log n),因为我们必须根据每磅的价值对物品进行排序。下面是一个贪婪算法在 Python 中对此问题的实现:

def fill_knapsack_fractional(W, values, weights):
   """Function to find maximum value to fill knapsack.

   Parameters:
   W (int): maximum weight of knapsack .
   values (dict): dictionary with item name as key 
      and value of item as value.
   weights (dict): dictionary with item name as key 
      and weight of item as value.

   Returns: 
   int: value of filled knapsack.
   """
   knapsack_value = 0
   W_remaining = W
   items_taken = {}
   value_per_pound = {} # Calculate value per pound for each item
   for item, v_i in values.items():
     w_i = weights.get(item)
     value_per_pound[item] = v_i / w_i # Sort items by value per pound
   items_sorted = dict(sorted(value_per_pound.items(), key=lambda x: x[1],  reverse=True))

   # Add items to knapsack
   for item, value_per_pound in items_sorted.items():
     v_i = values.get(item)
     w_i = weights.get(item)
     if W_remaining - w_i >= 0:
        knapsack_value += v_i
        W_remaining -= w_i
     else:
        fraction = W_remaining / w_i
        knapsack_value += v_i * fraction
        W_remaining -= int(w_i * fraction) return knapsack_value

硬币兑换问题

硬币兑换问题的目标是在给定一组具有不同支配的有限硬币的情况下,找到总数达到期望数量的最少硬币。

为了使用贪婪算法解决这个问题,我们首先按降序排列硬币。然后,我们总是会找到最大的硬币支配,小于或等于我们剩余的数量,并重复这个过程,直到我们达到我们想要的数量。如果用给定的一组硬币无法达到期望的数量,则返回-1。

请注意,虽然您可以用贪婪算法解决硬币兑换问题,但您可能并不总能找到最佳解决方案。为此,建议使用动态编程——在的下一篇文章中有所涉及。(感谢查德张指出这一点!)

这个算法的时间复杂度是 O(n log n),因为硬币列表是按支配从大到小排序的。下面是 Python 的实现:

def get_change(amount, coins):
   """Function to find the desired amount with the 
   smallest number of coins given a finite set of coins. Parameters:
   amount (int): desired amount to reach.
   coins (list): list of coin dominations. Returns:
   list: list of coins chosen
   """
   # Sort coins from largest to smallest domination
   coins_sorted = sorted(coins, reverse=True)
   change = [] for coin in coins_sorted:
       if coin <= amount: 
          change.append(coin)
          amount -= coin
          if amount == 0:
             return change

   return -1

结论

贪婪算法有许多应用,本文中我们介绍了两个例子——分数背包问题和硬币兑换问题。在贪婪算法失败的情况下,即局部最优解不会导致全局最优解,更好的方法可能是动态规划(接下来)。

更多请看本算法讲解系列: #1:递归#2:排序#3:搜索#4:贪婪算法(本期文章)、 #5:动态编程#6:树遍历

算法解释#5:动态编程

原文:https://towardsdatascience.com/algorithms-explained-5-dynamic-programming-e5472a4ce464

用 Python 中离散背包和最长公共子序列问题的示例解决方案解释动态编程

图片由穆罕默德·哈桑来自 Pixabay

动态规划对于解决具有重叠子问题和最优子结构的问题是有用的。在上一篇关于贪婪算法的文章中,我们谈到了贪婪的选择或者在每个决策点选择最佳的下一个选择有时会产生局部最优的选择。在这些情况下,我们可以使用动态规划来克服这个问题,更有效地解决这些优化问题。

动态规划对于表现出以下两个特征的问题是有效的:

  1. 最优子结构:组合子问题的最优解,产生全局最优解。
  2. 重叠问题:多次求解同一个子问题可以找到最优解。

换句话说,动态规划是一种适用于问题的优化方法,通过将其分解为更小的子问题,找到这些子问题的最优解,并将最优解组合以产生全局最优解,可以最优地解决这些问题。为了提高算法的效率,通常使用记忆来重用和跟踪已经在一些数据结构中评估过的先前项目。

使用动态规划解决问题的步骤包括:I)定义子问题,ii)寻找递归,iii)求解基本案例。在接下来的几节中,我们将介绍一些可以用动态编程解决的例子。

在本文中,我们将介绍两个优化问题,以及如何使用 Python 中的动态编程来解决它们。

离散背包问题

在上一篇关于贪婪算法的文章中,我们使用贪婪算法实现了分数背包问题的解决方案。然而,对于离散背包问题,贪婪算法并不总是导致使用贪婪算法的全局最优解,因为项目是不可分的。相反,我们将探索如何使用动态规划来解决离散背包问题。

提醒一下,背包问题的前提是一个窃贼正在抢劫一家有 n 件物品的商店,每件物品的价值是美元,重量是磅。窃贼想最大化被盗物品的价值,但他/她的背包只能装最大重量的物品,他/她应该带什么物品?

我们可以把这个问题分解成:

  1. 子问题:构造一个矩阵 M 来跟踪结果,并通过用重量限制为 j 的物品 i[0…i] 填充背包来定义 M[i,j]为最大值
  2. 递归:递归可以分为以下两种情况之一:I)如果第 I 个项目的权重 w[i] 在第 j 个单元格小于或等于我们背包的剩余容量,那么我们可以选择添加第 I 个项目;ii)如果在第 j 个单元格中 w[i] 的重量超过了背包的剩余容量,那么我们不添加它,重量保持不变。
  3. 基本情况:初始化 M[i,0]M[0,j] 为 0,因为背包将从权重 0 开始。

离散背包问题的动态规划解的时间复杂度是 O(nW),其中 n 是物品的数量,而 W 是背包的容量或重量限制。这是因为我们首先遍历物品的数量,然后遍历背包中允许的总重量,以找到这个问题的最优解。以下是离散背包问题的动态编程解决方案的 Python 实现:

def fill_knapsack_discrete(W, values, weights):
   """Function to find maximum value to fill knapsack 
      whereby items are not divisible.

   Parameters:
      W (int): maximum weight of knapsack.
      values (list): list of item values.
      weights (list): list of item weights.

   Returns: 
   int: value of filled knapsack.
   """
   # Initialize matrix
   num_items = len(values)
   M = [[None] * (W + 1) for i in range(num_items + 1)] for i in range(num_items + 1):
     for j in range(W + 1):
        # Base case
        if i == 0 or j == 0:
           M[i][j] = 0
        # Recurrence if weight of item is less than or 
        # equal to the remaining capacity of knapsack
        elif weights[i - 1] <= j:
           M[i][j] = max(
              values[i - 1] + M[i - 1][j - weights[i - 1]], 
              M[i - 1][j]
           )
        # Recurrence if weight of item is more than 
        # remaining capacity of knapsack
        else:
           M[i][j] = M[i - 1][j] return M[num_items][W]

最长公共子序列(LCS)问题

这个问题如下:给定两个字符串 ab ,求两个字符串中存在的最长公共子序列(LCS)的长度。请注意,子序列是以相同的相对顺序出现的序列,但它可能不连续。

在这种情况下,我们可以将问题分解为:

  1. 子问题:构造一个矩阵 L 来跟踪结果,并将 L[i,j] 定义为 a[0…i]b[0…j]的最长公共子序列的长度。
  2. 递归:我们可以把递归分成以下两种情况之一:I)如果 a[i] 等于 b[j] ,那么它们都对 LCS 有贡献,我们可以把结果加 1,所以 L[i,j] = L[i-1,j-1]+1; ii)如果 a[i] 不等于 b[j] ,那么没有匹配,可以丢弃一个所以 L[i,j] = max(L[i-1,j],L[i,j-1])。
  3. 基本情况:初始化 L[i,0]L[0 j] 为 0。

这个问题的动态编程解决方案的时间复杂度是 O(nm),因为我们首先遍历长度为 n 的第一个字符串 a ,然后遍历长度为 m 的第二个字符串 b 。下面是 Python 中的实现:

def find_lcs(a, b):
   # Find length of strings
   len_a = len(a)
   len_b = len(b) # Initialize matrix
   L = [[None] * (len_b + 1) for i in range(len_a + 1)] # Loop through strings and record the length of LCS at
   # each a[0...i] and b[0...j]
   for i in range(len_a + 1):
      for j in range(len_b + 1):
         # Base case
         if i == 0 or j == 0:
            L[i][j] = 0
         # Recurrence if characters match
         elif a[i - 1] == b[j - 1]:
            L[i][j] = L[i - 1][j - 1] + 1
         # Recurrence if characters do not match
         else:
            L[i][j] = max(L[i - 1][j], L[i][j - 1]) return L[len_a][len_b]

结论

动态规划是解决最优化问题的一个非常有用的工具。实现动态规划算法的步骤包括将问题分解成子问题,识别其重现和基本情况以及如何解决它们。

更多请看本算法讲解系列: #1:递归#2:排序#3:搜索#4:贪婪算法#5:动态规划(本期文章) #6:树遍历

算法解释#6:树遍历

原文:https://towardsdatascience.com/algorithms-explained-6-tree-traversal-1a006ba00672

用 Python 中的例子解释树遍历算法

图片由 Clker-Free-Vector-Images 来自 Pixabay

树由一组由边连接的节点表示。它们被认为是分层的非线性数据结构,因为树中的数据存储在多个层次上。树具有以下属性:

  • 根节点:每棵树都有一个节点被指定为根节点,它是树的最顶端的节点,并且是没有任何父节点的节点。
  • 父节点:父节点是它之前的节点,除了根节点之外的每个节点都有一个父节点。
  • 子节点:子节点是其后的节点。根据树的类型,每个节点可以有不同数量的子节点。

树形数据结构的类型

有一些通用树具有上面列出的属性,并且对节点数量没有其他限制。还有各种类型的树数据结构,对于不同的用例有更多的限制,下面是一些常*的:

  1. 二叉树:二叉树是一种节点最多可以有两个子节点的树,正如“二进制”标签所暗示的。
  2. 二叉查找树(BST):BST 是二叉树的一个特例,其中的节点是按照它们的值排序的。对于每个父节点,左边的子节点是一个较小的值,而右边的子节点是一个较大的值。这种结构使得查找很快,因此对于搜索和排序算法很有用。
  3. 堆:堆是一种特殊的树数据结构,有两种类型的堆:I)最小堆是一种树结构,其中每个父节点小于或等于其子节点;ii)最大堆是一种树形结构,其中每个父节点大于或等于其子节点。这种类型的数据结构对于实现优先级队列很有用,在优先级队列中,项目按权重排列优先级。请注意,Python 有一个名为heapq的内置库,其中包含对堆数据结构执行不同操作的函数。

树遍历算法

在回顾了树数据结构的常*类型之后,下面是一些常*的树遍历算法及其在 Python 中的实现的例子。

广度优先搜索(BFS)

面包优先搜索(BFS)是一种常用算法,用于按系统顺序遍历二叉查找树(BST)或图。它从第 0 层的根节点开始,一次访问一个节点,从一侧横向移动到另一侧,直到找到所需的节点或访问完所有节点。该算法在深入搜索之前先进行大范围搜索,因此被称为面包优先搜索。

BFS 的时间复杂度是 O(n ),因为树的大小由项目搜索长度决定,并且每个节点被访问一次。下面是 Python 中的实现:

def bfs(graph, source):
   """Function to traverse graph/ tree using breadth-first search Parameters:
   graph (dict): dictionary with node as key and 
                 list of connected nodes as values.
   source (str): source node to start from, usually 
                 the root node of the tree. Returns:
   bfs_result (list): list of visited nodes in order.
   """
   # Define variables
   bfs_result = []
   queue = [] # Add source node to queue
   queue.append(source) while queue:
     # Visit node at front of queue
     node = queue.pop(0) # Check if we have visited this node before
     if node not in bfs_result:
        # Mark node as visited
        bfs_result.append(node)
        # Add all neighbor nodes to queue
        for neighbor in graph.get(node, []):
           queue.append(neighbor) return bfs_result

深度优先搜索

深度优先搜索(DFS)是树遍历算法的另一种变体,它也从根节点开始,但沿着一个分支向下移动,并尽可能沿着一个分支向下移动。如果所需的节点不在该分支中,它会返回并选择另一个分支。该算法一直这样做,直到找到期望的节点或者所有节点都被访问过。该算法在进入另一个分支之前首先向下探索一个分支(深度),因此被称为深度优先搜索。

基于与 BFS 相同的原因,DFS 的时间复杂度也是 O(n)。下面是 Python 中的实现:

def dfs(graph, source):
   """Function to traverse graph/ tree using depth-first search Parameters:
   graph (dict): dictionary with node as key and 
                 list of child nodes as values.
   source (str): source node to start from, usually 
                 the root node of the tree. Returns:
   dfs_result (list): list of visited nodes in order.
   """
   # Define variables
   dfs_result = []
   queue = [] # Add source node to queue
   queue.append(source) while queue:
      # Get last item in queue
      node = queue.pop() # Check if we have visited node before
      if node not in dfs_result:
         dfs_result.append(node)
         # Add neighbors to queue
         for neighbor in graph.get(node, []):
            queue.append(neighbor) return dfs_result

结论

树是表示分层和非线性数据的有用数据结构。最常用的树数据结构类型是二叉树(树中的每个节点最多有两个子节点)、二叉查找树(二叉树,其中节点按值排序)和堆(树,其中父节点少于或多于它们的子节点,取决于它是最小堆还是最大堆)。

在算法方面,面包优先搜索和深度优先搜索是重要的树遍历算法,具有许多实际应用,从 GPS 导航系统中的路径寻找和路线规划到调度到网络拓扑。在下一篇文章中,我们将介绍一个用于信息编码的树遍历的特殊例子,称为霍夫曼码。

更多请看本算法讲解系列: #1:递归#2:排序#3:搜索#4:贪婪算法#5:动态规划#6:树遍历(本期文章)。

算法解释#7:霍夫曼编码

原文:https://towardsdatascience.com/algorithms-explained-7-huffman-coding-1be107beb546

一种文本压缩算法的解释及其在 Python 中的实现

在本算法讲解系列的前几篇文章中,我们经历了六种不同类型的算法( #1:递归#2:排序#3:搜索#4:贪婪算法#5:动态规划#6:树遍历)。在本文中,我们将深入研究一个用于文本压缩的贪婪算法的实际用例——霍夫曼编码。

什么是霍夫曼编码?

霍夫曼编码是一种经常使用的技术,用于在不丢失信息的情况下将文本压缩到较小的大小。信息被编码为二进制字符串(1 和 0 的比特),目标是用尽可能少的比特明确地传输信息。

这种贪婪算法通过评估字符的频率并使用按频率排序的二叉树,找到了将每个字符编码为二进制字符串的最佳方式。出现频率较高的字符被编码为较短位的字符串,而出现频率较低的字符被编码为较长位的字符串。

霍夫曼编码是如何工作的?

该算法通过使用优先级队列 Q 以自下而上的方式构建树 T 来工作,该优先级队列选择两个最不频繁的对象并将它们合并在一起,进而创建一个新对象,其频率是两个合并对象的频率之和。重复这个过程,直到输入文本中的所有单词都被编码。

用 Python 实现霍夫曼编码

考虑下面这个词——“最小”。

I .创建一个树数据类

第一步包括编写一个数据类来存储树的数据。我选择使用数据类而不是常规类,因为在 Python 3 中,默认情况下数据类有各种“dunder”方法。例如,生成的repr(打印表示)字符串将包含类名,以及每个字段的名称和值,使用户更容易理解打印的树实例。

数据类本身相对简单。它包含两个参数,left表示左节点(str),而right表示右节点(str)。当构建树时,我们需要访问子节点,所以在这个数据类中,有一个函数children()简单地返回leftright节点。

from dataclasses import dataclass[@dataclass](http://twitter.com/dataclass)
class Tree:
   left: str
   right: str def children(self):
      return self.left, self.right

二。构建树

接下来,我们将构建一个包含输入文本中按频率排序的所有字符的树。为此,我们将查看字符频率,并将这些字符存储在按频率排序的优先级队列 Q 中。

接下来,我们开始构建一棵树,由此我们将来自 Q 的具有最小频率的字符指定为根节点的左子节点,并将来自 Q 的具有第二最小频率的字符指定为根节点的右子节点。然后,我们将根节点的值指定为两个子节点的频率之和。

回到我们的词(“最小”),按频率排序的唯一字符数是:{'m': 3, 'i': 2, 'n': 1, 'u': 1}。因此,第一次迭代将构建一个深度为 1 的树,由计数为 1 的“u”作为左子节点,计数为 1 的“n”作为右子节点,sum (2)作为根节点。

从第一次迭代构建的树

我们重复同样的过程,直到所有的字符都被编码,我们最终得到一个最大深度为 3 的树,如下图所示。

由单词“最小值”构造的树

下面是用 Python 编写的HuffmanCodingTree类中的_build_tree()函数的代码片段,它从输入文本构建了一棵树。与上述过程类似,该函数执行以下操作:

  1. 统计输入文本中独特字符的频率,并将其存储为名为char_counts的字典。
  2. 按频率降序排列char_counts,并将其存储为优先级队列 Q
  3. 循环通过 Q 弹出频率最低的两个字符,并将其指定为左右节点,然后将两个子节点的频率相加,并将该值指定为父节点。
  4. 将父节点作为包含树和父节点值的元组附加到 Q.

该函数返回构建树的。对于我们输入的文本“最小值”,返回的结果将是:Tree(left=Tree(left='m', right=Tree(left=Tree(left='u', right='n'), right='i'))

def _build_tree(self):
   # Get count of unique characters in chars
   char_counts = dict(Counter(self.chars))
   # Initiate priority queue Q of unique characters
   # and sort by descending order of frequencies
   Q = sorted(char_counts.items(), key=lambda x: x[1], reverse=True)

   while len(Q) > 1:
      # Get minimum value of Q to be assigned as left node
      node_l, freq_l = Q.pop()
      # Get next minimum value of Q to be assigned as right node
      node_r, freq_r = Q.pop()
      # Build tree with left and right nodes
      parent_node = Tree(left=node_l, right=node_r)
      # Sum frequencies of both returned values and assign to tree
      parent_node_freq = freq_l + freq_r
      # Add parent node to tree
      Q.append((parent_node, parent_node_freq))
      Q = sorted(Q, key=lambda x: x[1], reverse=True) return Q[0][0]

三。将霍夫曼编码分配给树

构建树之后,最后一步是分配编码。该算法将 0 赋给左边缘,1 赋给右边缘,因此我们将编写一个名为_assign_huffman_coding()的函数来完成这个任务,该函数有两个参数:nodeencoding

该函数将递归调用自身,直到树中的所有节点都被编码。因此,第一步是定义基本情况,其中输入是单个节点。然后,我们将递归调用该函数来构建左右分支,直到它到达基本情况(只剩下一个节点)。该函数返回一个字典,将节点作为键,将编码作为值。

def _assign_huffman_coding(self, node, encoding=''):
   # Case when node is a single node
   if type(node) == str:
      return {node: encoding}
   huffman_dict = {}
   (node_l, node_r) = node.children()
   # Recursively build left branch 
   huffman_dict.update(self._assign_huffman_coding(node=node_l, encoding=encoding + '0'))
   # Recursively build right branch 
   huffman_dict.update(self._assign_huffman_coding(node=node_r, encoding=encoding + '1'))

   return huffman_dict

结果

对于单词“minimum ”,产生的编码树如下所示。编码由边缘的红色文本表示。

单词“最小值”的霍夫曼树

要提取每个唯一字符的压缩代码,只需沿着从根节点到叶节点的边。例如,“m”的编码是0,“u”的编码是100。下表显示了单词“minimum”中每个独特字符的频率、编码和大小:

--------------------------------------------------
|  Character | Frequency |  Encoding |    Size   |
--------------------------------------------------
|      m     |     3     |     0     | 3 x 1 = 3 |
--------------------------------------------------
|      i     |     2     |    11     | 2 x 2 = 4 |
--------------------------------------------------
|      u     |     1     |    100    | 1 x 3 = 3 |
--------------------------------------------------
|      n     |     1     |    101    | 1 x 3 = 3 |
--------------------------------------------------
| 4x8=32bits |   7 bits  |           |  13 bits  |
--------------------------------------------------

每个字符的大小是 8 位,所以在没有压缩的情况下,单词“minimum”的大小将是 7 个字符 x 8 位= 56 位。利用霍夫曼编码算法,我们能够将字的大小减少到 32 位(4 个字符×每个字符 8 位)+ 7 位(频率之和)+ 13 位(频率之和×每个字符的深度)= 52 位。我们设法将单词“minimum”的大小减少了 4 位——想象一下这对于一个段落或一个文档会是什么样子!

结论

Huffman 编码算法用于文本压缩,它是一个有趣而实用的例子,用来说明以前在这个算法解释系列中涉及的概念,从贪婪算法到树遍历。实现霍夫曼编码算法有三个步骤:I)创建一个数据类,II)从输入文本构建一个树,III)给树分配霍夫曼编码。

要查看完整代码,请点击此处。更多文章参*本算法讲解系列: #1:递归#2:排序#3:搜索#4:贪婪算法#5:动态规划#6:树遍历

对齐其他 Ode 上的*毛刺

原文:https://towardsdatascience.com/aligning-flat-burrs-on-fellow-ode-2ab39a5264ea

咖啡数据科学

咖啡研磨机带来更多乐趣

我借用了一个带有 SSP 多用途毛刺的同胞颂歌,它似乎没有表现出与我的利基不同。但是有人指出可能是对齐的原因,于是我对齐了毛刺(得到允许)。

我从来没有对齐毛刺,但过程是直截了当的。

作为参考,Ode 刻度盘上的每个数字设置之间有两个设置,所以我将这些设置称为 0.3 和 0.6。所以在设置 1 和 2 之间,还有设置 1.3 和 1.6。

首先,把它拆开:

所有图片由作者提供

确保你的工作空间乱七八糟,因为这意味着你在做正确的事情。

接下来,检查毛刺。我注意到一个尺寸上的标记比另一个更强,这表明我可以在哪里添加垫片来改善对齐。

然后将垫片添加到对面标记的中间。通常情况下,您会用类似干擦市场的东西标记毛刺,运行毛刺,并查看哪里的标记被删除。因为那些标记,我不认为我必须一开始就这么做。

所以我找到了标记对面的中间,我加了铝箔。

然后我用记号笔在刀片上做了标记。

我在很低的研磨设置下运行了一段时间,一切似乎都很*稳。

我看了毛刺集的两个部分,它似乎是均匀的。

然而,我想听听别人的意*,所以我又做了一次测试。

后来,我发现在同样的设置下,我的研磨效果更好。校准前拨入设置为 2.6,但校准后设置为 3.6。

我看了前后的粒子分布。我用了不同的豆子,因为我一时冲动把毛刺对齐了。我没有收集前后的样本,但我使用的其他豆子具有相似的密度:

校准前的咖啡密度= 0.402 克/毫升

校准后的咖啡密度= 0.403 克/毫升

研磨后设置值 2.6 似乎介于设置值 1 和 2 之间。

这意味着研磨机可以更精细,因为毛刺是对齐的。未对齐的毛刺会导致毛刺接触得更快。因此,如果你正在调整你的毛刺,一个很好的方法来知道你这样做是正确的,是注意到一个更好的研磨设置。

设备/技术

意式咖啡机 : 像样的意式咖啡机

咖啡研磨机 : Fellow Ode+SSP 多用途毛刺

咖啡:家庭烘焙咖啡,中杯(第一口+ 1 分钟)

镜头准备:断奏夯实

预输注:长,约 25 秒

输液:压力脉动

过滤篮 : 20g VST

其他设备: Atago TDS 计Acaia Pyxis 秤

绩效指标

我使用两个指标来评估技术之间的差异:最终得分和咖啡萃取。

最终得分 是评分卡上 7 个指标(辛辣、浓郁、糖浆、甜味、酸味、苦味和余味)的*均值。当然,这些分数是主观的,但它们符合我的口味,帮助我提高了我的拍摄水*。分数有一些变化。我的目标是保持每个指标的一致性,但有时粒度很难确定。

强度半径(IR) 定义为 TDS 对 EY 控制图上原点的半径,所以 IR = sqrt( TDS + EY)。这一指标有助于标准化产量或酿造比的击球性能。

我在 4 次烘烤中观察了 4 个镜头对。味道没有明显的趋势,但提取率略有下降。这可能是由于对齐毛刺的研磨设置太细,因为研磨设置从未对齐毛刺的设置 2.3 变为对齐毛刺的设置 3.6。我有点懒于拨入恰到好处。

我原以为对齐后会有更紧密的分布。这看起来像是有一个转变,但看起来不像是有一些紧密的粒子分布。我仍然更喜欢有对齐的毛刺,但我没有在前后的粒子分布中看到什么特别的东西来说*的毛刺似乎与圆锥形毛刺有根本的不同。更多的将被揭露。

如果你愿意,可以在推特、 YouTubeInstagram 上关注我,我会在那里发布不同机器上的浓缩咖啡照片和浓缩咖啡相关的视频。你也可以在 LinkedIn 上找到我。也可以关注我在订阅

我的进一步阅读:

我未来的书

我的链接

浓缩咖啡系列文章

工作和学校故事集

关于谷歌开发者学生俱乐部的一切——从申请到毕业

原文:https://towardsdatascience.com/all-about-google-developer-students-club-from-application-to-graduation-bee35f411b05

图片来自作者:GDSC——申请、选择、规划、毕业

从 DSC 领导的角度看开发者学生俱乐部

Google 每年都会从全球的大学中挑选学生来领导他们校园里的开发者社区,帮助学生弥合理论和实践之间的差距。这些学生是领导者,致力于帮助他们的同伴在对等的环境中学*、成长和联系。

作为该计划的一部分,这些被称为领导者的学生与他们的大学合作,在他们的校园里建立一个学生俱乐部,并与当地的合作伙伴合作,在谷歌的帮助下,为下一个 10 亿用户建立解决方案。我是在特里凡得琅的 DevFest'19 期间知道这个项目的。

这篇文章重点介绍了我在大学建立并领导一个开发者学生俱乐部的个人经历。如果你觉得这很有帮助,那就考虑鼓掌,这样灵媒就知道你在享受你所读的东西。此外,请随时通过 LinkedIn、脸书或 Instagram 与我联系。

打造完美应用程序

谷歌通过 Advocu *台接受研究生和本科生的申请。印度地区的申请通常在三月的最后一周开放,通常会持续两到三周。

申请是在滚动的基础上进行评估的,所以建议尽快申请。这可以大大提高你被面试选中的几率。就我而言,我是在申请开始的前三天内申请的。你也可以通过填写这张表格来表达你的兴趣。

通常,作为申请的一部分,你会被要求提交你的个人资料,一些论文问题的答案,以及一段 90 秒的视频。在申请的时候,确保你严格遵循关于你的答案的性质和长度的指导方针。申请 GDSC 大学不需要你的简历。

瞄准月球发射。想想 10 倍。不是 10% ~ 肯·诺顿

将近两周后,我收到一封电子邮件,邀请我去采访一位谷歌开发专家。谷歌为你提供了从可用的时间段中选择面试的首选日期和时间的灵活性。尽早预订您喜欢的时间段,因为时间段预订是实时发生的。

一旦你预定了一个时段,你就会收到一个 30 分钟面试的日历邀请。我与 Summit Kakkar 先生的面谈安排在 4 月 30 日。

采访谷歌代表

面试,尤其是在线面试,可能会有压力。我面试的那天早上充满了焦虑,因为我事先不知道会发生什么。我的大学从来没有 GDSC 俱乐部,这是我第一次面试

为了镇定我的神经,我在面试开始前 10 分钟登录了会议。中午 12 点整,我的面试官加入了电话会议,但由于他的笔记本电脑需要充电,不得不推迟半个小时。我们在中午 12:20 左右联系上了,采访以友好的介绍开始。

图片来自作者:GDSC 采访前几分钟

气氛感觉很轻松,面试很顺利。面试官很想了解我的领导能力,以及我帮助同事成长的计划。只有几个技术性问题,这让面试更像是一场对话。我觉得面试总体来说很顺利。

选拔和入职

在接下来的三个月里,我在 GDSC 的申请没有任何进展(延迟是因为新冠肺炎疫情病毒的爆发),但是我确保和团队保持联系,因为我有很高的期望。

到了 8 月的第二周,谷歌终于开始发送选拔邮件,8 月 12 日,我收到了一封电子邮件,通知我已被我所在的学院选为领袖,并将加入一批来自世界各地 1000 多所大学和学院的出色学生领袖。

图片来自作者:GDSC 精选邮件

所有销售线索必须在收到选择电子邮件的 7 天内提交一份接受表,以确认他们参与该计划。一旦他们接受,他们将获得各种专属*台和资源,包括社区领导*台、活动*台、官方全球 Slack 和全球 GDSC 邮件列表等。

由于全球疫情,DSC 峰会被取消,线索收到了一箱谷歌商品,如 t 恤,咖啡杯,耳机,营销材料和许多其他谷歌品牌的物品。

两周后,谷歌为所有新选择的潜在客户举办了一个三小时的专门入职会议。在这次会议中,我们被介绍给 GDSC 的社区项目经理,并简要介绍了我们的职责。

本次会议由来自世界各地的多位嘉宾主讲,我们还听取了即将毕业的领导讲述他们的经历。在我们的任期内,我们总共与四位 CPM 合作。就这样,简单的部分结束了,真正的工作才刚刚开始。终于到了我系好安全带的时候了。

核心团队选择和活动策划

任何成功的俱乐部都需要志趣相投的个人的协调、合作和协作,而这正是你的核心团队发挥关键作用的地方。这些人是您的同事,他们将在您作为领队的整个旅程中协助您组织和规划活动和其他活动。

图片来自作者:GDSC 每周同步-圣诞庆典

谷歌建议拥有一个由 5 名成员组成的核心团队,但是你可以招募你认为需要的人数。一个理想的核心团队由来自不同院系和学术水*的学生组成。我从 8 名成员开始,最终团队发展到 11 人。领导制定成员资格标准。

当我开始从零开始创建俱乐部时,我的重点是让那些擅长影响校园中被动人群的人开始参与技术活动。如果你已经在你的大学里有一个专门的俱乐部,你可以选择具有良好技术技能和知识的人。

每位领导还必须从他们的学院中选择一名指导教师,理想情况下,应该是你的系主任或你的工作人员指导教师。这些教师顾问将帮助和指导你在你的大学顺利举办活动,并将接受一些培训。

谷歌不承认任何俱乐部的联合领导,尽管你仍然可以在团队中包括一个(领导特权将只提供给官方选择的领导)。此外,你可以自由邀请高年级学生加入你的核心团队。然而,需要注意的是,俱乐部的所有核心团队成员必须在同一所大学学*。

领导每周与 CPM 进行一次同步电话会议,有时每两周一次,讨论项目的未来。在这些通话中,销售线索可以与项目经理互动,消除他们的疑虑。就我们而言,过去我们每周二从晚上 8 点开始开一个小时的会。

为了成功完成该计划,谷歌要求领导每 90 天至少安排一次活动。这些活动提供了一个讨论谷歌以外的技术的机会,目的是在不贬低包括谷歌在内的任何公司的情况下促进跨技术学*。

在我任职期间,在一个专门团队的支持下,我成功地组织了超过 18 次在线活动,指导了近 2,000 名学生(尽管我来自一所学生不足 300 人的大学。)在各种技术领域,如云计算、应用程序开发和机器学*。

要成功组织一次活动,让相关领域的专业人士参与进来至关重要。我们的活动主要由亚马逊和 GitHub 等大型跨国公司的嘉宾主讲。语言限制不是问题,用当地语言举办活动完全可以接受。

图片来自作者:GDSC 活动*台

谷歌开发人员为每个俱乐部提供了一个专属的活动*台,用于注册活动和收集学生的反馈。虽然领导者可以选择为他们的俱乐部创建一个个性化的网站,但只有在 DSC events *台中记录的活动才会被计入由 Google Developers 团队评估的领导者毕业要求的实现情况。

除了活动*台,销售线索还可以利用社区销售线索*台,这是一个只有通过邀请才能访问的专属*台。它使销售线索能够在计划活动时交换和使用资源,包括资料、时间表和其他活动工具。

为了支持他们的营销工作,销售线索会收到一个虚拟计划套件,其中包含大量针对不同社交媒体*台优化的数字模板和视觉资产。组织者被允许使用品牌标志和设计,只要他们遵守品牌指南。

活动协作和解决方案挑战

与其他团体、俱乐部和组织合作是为 DSC 活动争取更多演讲者、场地和赞助的好方法。在选择合作伙伴时,谷歌非常通融。但是,领导应避免利用 GDSC 谋利。组织者只应向参与者收取活动运营成本的费用。

我第一次作为领导者与特里凡得琅工程学院合作,组织了为期 4 天的 Android 学* Jams 活动。我们的合作伙伴关系使我们两个俱乐部能够将他们的影响扩大到更广泛的受众,不仅是在四次学*堵塞期间,而且在随后的许多项目中。

在我任职期间,我们与 125 个以上的 GDSCs 合作组织了为期一周的系列研讨会、活动等。仅在头几天,旗舰活动就吸引了超过 13,000+的注册和超过 50,000+的浏览量。这种合作帮助我们获得了大型赞助商和参与者。

在 DSC WoW 之后,我们与该国的 30 个其他俱乐部合作组织了为期一个月的网络学*集会,名为 30 天的网络开发。

在任期的最后一个季度,GDSC 领导有机会参加技能提升培训计划,该计划为领导及其核心团队成员提供专门的软硬技能培训。培训每周进行一次,通常是在引导期的最后一个季度。

GDSC 还通过解决方案挑战为学生提供了另一个绝佳的机会,这是一个由谷歌开发团队主办的为下一个 10 亿用户打造的竞赛。这个机会只提供给谷歌开发者学生俱乐部的会员。最近,DSC 解决方案挑战赛的目标是利用谷歌技术解决 17 个联合国可持续发展目标(SDG)中的一个或多个。

比赛的获胜者将获得各种奖励,如现金奖励、证书等。此外,谷歌工程师为他们提供指导机会,帮助他们开发解决方案。

推荐、毕业和 GDSC 会议后的机会

在选择新线索的申请打开之前,当前线索被给予推荐代码,该代码可以与希望在其大学申请领导 GDSC 的有抱负的学生共享。这些代码在公开申请发布前一周提供给当前负责人,并且可以与任何机构的学生共享,无论他们的资格如何。

请记住,有推荐人并不能确保你会被选中或进入面试名单,但它确实会在每年提交的大量申请中为你的申请提供一些额外的考虑。

图片来自作者:GDSC 结业证书

经过几个月的努力工作,当我从这个项目毕业时,终于到了我们将衣钵传递给下一批领导的时候了。就我而言,我们的任期于 6 月 1 日结束,也就是我加入后的近 10 个月。我们用一个虚拟毕业日计划来庆祝,在这个计划中,所有符合毕业标准的领导都会收到他们的证书和相应的权利。

由于该项目是在网上进行的,谷歌提出为所有线索支付零食的费用。毕业日包括一个网络会议,一个令人惊叹的魔术表演,接着是聊天室的*面和问候。

几周后,谷歌向所有符合条件的领导及其核心团队成员分发了毕业 schwag 工具包。GDSCs 为学生提供了无限的机会,我坚信我们作为学生获得的经验是令人难以置信的充实。作为社区的一部分,我们的活动不仅帮助了我们,也帮助了我们大学内外的本地开发者社区。

图片来自作者:GDSC 毕业日 2021

在我的领导任期结束后,我成为了微软学*项目的学生大使和 IEDC 的首席执行官,并在雀巢和小米完成了实*。我相信我在谷歌开发者学生俱乐部的经历为我提供了一个坚实的基础,帮助我在这些高要求的角色中脱颖而出。

就这样,我以为我和 GDSC 的旅程结束了。但是没有?在我任期结束后的 2021 年,我有机会在德国亚琛工业大学指导 GDSC。目前,在 2022 年,我在我自己的学院指导俱乐部,由我的一名 GDSC 大学新生领导。

话虽如此,是时候总结一下了。我希望这篇文章能帮助你在加入一个最受欢迎的社区时有一个良好的开端。如果你有任何问题,或者如果你认为我犯了一个错误,请随时通过 LinkedInInstagrammail 与我联系。下次*,快乐学*。

所有关于 N-HiTS:时间序列预测的最新突破

原文:https://towardsdatascience.com/all-about-n-hits-the-latest-breakthrough-in-time-series-forecasting-a8ddcb27b0d5

从理论到实践,了解时间序列预测的最新技术 N-HiTS,并使用 Python 将其应用到实际项目中

毛罗·吉利在 Unsplash 上拍摄的照片

之前的一篇文章中,我们探索了 N-BEATS:一种依靠基础扩展概念来预测时间序列的深度学*模型。

在发布时,即 2020 年,N-BEATS 使用不依赖于时间序列特定组件的纯深度学*架构实现了最先进的结果。

截至 2022 年 1 月,已经提出了增强 N-BEATS 的新模型: N-HiTS 。这个由 Challu 和 Olivares 等人提出的新模型改进了输入的处理和输出的构造,导致更好的精度和更低的计算成本。

在本文中,我们首先详细探索 N-HiTS 的内部工作原理,以了解这种新方法如何改进 N-BEATS。然后,我们使用 Python 在预测项目中实际应用 N-HiTS。

我强烈建议您在处理这个问题之前阅读我关于 N-BEATS 的文章,因为 N-HiTS 是 N-BEATS 的一个发展,并且两个模型之间有许多相同的概念。

同样,我将使用更多的直觉和更少的等式来解释 N-HiTS 的架构。当然,更多的细节,我建议你看一下原文

用 Python 中我的 免费时间序列小抄 学*最新的时间序列分析技术!获得统计和深度学*技术的实现,全部在 Python 和 TensorFlow 中!

我们开始吧!

探索 N 次点击

N-HiTS 代表NT21欧洲 i 国际时间S系列预测。

简而言之,N-HiTS 是 N-BEATS 模型的扩展,提高了预测的准确性,降低了计算成本。这是通过模型以不同的速率对时间序列进行采样来实现的。这样,模型可以学*系列中的短期和长期效果。然后,在生成预测时,它将结合不同时间尺度的预测,同时考虑长期和短期影响。这叫做分层插值

让我们更深入地研究这个架构,详细了解这个模型是如何工作的。

N-HiTS 的体系结构

下面是 N-HiTS 的架构。

N-HiTS 的架构。还是那句话,模型是由栈和块组成的,就像 N 拍一样。图片由 C. Challu、K. Olivares、B. Oreshkin、F. Garza、M. Mergenthaler-Canseco 和 A. Dubrawski 拍摄,来自 N-HiTS:用于时间序列预测的神经分层插值

从上图中,我们注意到该模型与 N-BEATS 非常相似:该模型同时进行预测和反预测,它由堆栈和块组成,最终预测是每个堆栈的部分预测之和,一个堆栈中的每个块之间存在残差连接。

然而,有一些关键的修改允许 N-HiTS 持续优于 N-BEATS。

多速率信号采样

在数据块级别,我们注意到增加了一个 MaxPool 层。这就是模型实现多速率采样的方式。

回想一下 maxpooling 只是取给定的一组值中的最大值。每个堆栈都有自己的内核大小,内核大小的长度决定了采样速率。

较大的内核大小意味着堆栈关注时间序列中的长期影响。或者,小的内核尺寸强调系列中的短期效应。下图显示了这一点。

说明了 MaxPool 层内核大小的影响。请注意,较大的内核大小如何通过更积极的子采样来强调系列中的长期特征。图片由作者提供。

看上面的图片,我们可以看到改变内核大小是如何影响堆栈的输入信号的。由于内核较小,该系列几乎没有变化,并且包含短期变化。然而,随着内核大小的增加,我们可以看到该系列变得更加*滑,并且强调了长期变化。

因此,最大池层允许每个堆栈专注于特定的信号规模,无论是短期还是长期。这也是 N-HiTS 在长期预测方面表现更好的原因,因为在系列中有一个专门学*和预测长期影响的堆栈。

此外,由于大的核大小更积极地对序列进行重新采样,它减少了可学*参数的数量,从而使模型更轻便,训练更快。

回归

一旦输入信号通过最大池层,该模块使用全连接网络来执行回归,并输出预测和反向预测。

backcast 表示块捕获的信息。因此,我们从输入信号中移除反向传播,并通过剩余连接将结果信号传递给下一个模块。这样,任何未被某个块捕获的信息都可以被下一个块建模。

分级插值

顾名思义,N-HiTS 使用分层插值来产生其预测。这用于降低预测的基数。让我们把这个翻译成日常用语。

请记住,基数只是一组给定数字中元素的数量。例如,[6,7,8,9]的基数是 4,因为集合中有四个元素。

因此,在大多数预测模型中,预测的基数等于预测范围的长度。换句话说,预测的数量等于我们希望预测的未来时间步长的数量。例如,如果我们想要未来 24 小时的每小时预测,那么模型必须输出 24 个预测。

当然,所有这些都是有意义的,但当视野变得很长时,就会出现问题。如果我们想要的不是未来 24 小时的每小时预测,而是未来 7 天的每小时预测,那该怎么办?在这种情况下,模型的输出基数为 168 (24 * 7)。

如果您回忆一下 N-BEATS 模型,最终预测是每个堆栈的所有部分预测的组合。因此,每个堆栈生成 168 个预测,这在计算上是昂贵的。

为了解决这个问题,N-HiTS 使用分层插值,其中每个堆栈都有一个他们称之为的表现力比率。这就是单位时间内预测的次数。反过来,这与每个堆栈专门以不同的速率处理序列的事实有关,因为 MaxPool 层对序列进行子采样。

例如,一个堆栈每小时学*一次短期效应,但下一个堆栈每 12 小时对序列进行二次采样,下一个堆栈每 24 小时进行一次。因此,由于每个堆栈都有自己的规模,因此每个堆栈的基数都不同。下图对此进行了说明。

假设对下周的每小时预测。我们可以看到 N-HiTS 具有较低的基数,因为每个堆栈都有自己的规模。堆栈 1 查看每小时的数据,堆栈 2 查看每 12 小时的数据,堆栈 3 查看每 24 小时的数据。图片由作者提供。

在上图中,我们假设一个场景,其中我们有每小时的数据,我们希望对下周进行每小时的预测(未来 168 次预测)。在 N 拍的情况下,每个堆栈进行 168 次部分预测,并且必须对每个进行求和以生成最终预测。

但是,在 N 次命中的情况下,由于 MaxPool 层的原因,每个堆栈以不同的比例查看数据。因此,堆栈 1 查看每小时的数据,因此必须进行 168 次预测。例如,Stack 2 每隔 12 小时查看一次数据,因此只需进行 14 次预测(因为 12 适合 168 的 14 倍)。然后,Stack 3 每隔 24 小时查看一次数据,因此它只需进行 7 次预测(因为 24 适合 168 中的 7 次)。

因此,我们看到堆栈 1 比堆栈 2 具有更高的表现率,堆栈 2 比堆栈 3 具有更高的表现率。

我们可以在下图中看到这种行为。

N-BEATS 和 N-HiTS 如何预测?在顶部,我们看到每个 N 拍堆栈在每个时间步长输出一个预测,必须对其求和才能生成最终预测。在底部,N-HiTS 输出的预测要少得多,因为每个堆栈都以自己的频率工作。图片由作者提供。

从上面的图片中,我们清楚地看到 N-BEATS 的每个堆栈在每个时间步都输出一个预测,并且每个堆栈都必须求和才能生成最终预测。

另一方面,N-HiTS 具有工作在不同频率的堆栈。因此,堆栈 1 在每个时间步长进行预测,但是堆栈 2 仅每 12 小时进行一次预测,而堆栈 3 每 24 小时进行一次预测,因此降低了计算成本。

将不同时间尺度的预测相结合的事实定义了分级插值。

如果不清楚的话,这里有一个取自原始文章的图,它也说明了分层插值。

N-HiTS 中的层次插值。我们可以看到每个堆栈输出不同数量的预测,因为它们每个都在自己的规模(或频率)上专门化。C. Challu、K. Olivares、B. Oreshkin、F. Garza、M. Mergenthaler-Canseco 和 A. Dubrawski 的图像来自 N-HiTS:用于时间序列预测的神经分层插值

同样,在上图中,我们看到 N-HiTS 中的每个堆栈输出不同数量的预测,因为每个堆栈工作在不同的频率。Stack 1 着眼于长期效应,因此它的预测在时间上更有间隔。另一方面,Stack 4 关注短期影响,并输出时间上更接近的更精细的预测。

摘要中的 n 次点击

简而言之,N-HiTS 通过一个 MaxPool 层扩展了 N-BEATS 架构,允许每个堆栈以不同的比例查看系列。一个堆栈可以专注于长期效果,另一个专注于短期效果。通过在称为分层插值的过程中组合每个叠加的预测来获得最终预测。这使得模型更轻便,对于预测长时间范围更准确。

既然我们已经详细探讨了 N-HiTS 的内部工作原理,那么让我们将它应用到一个预测项目中。

N 次命中预测

我们现在准备在预测项目中应用 N-HiTS 模型。在这里,我们将预测每小时 94 号州际公路西行交通量。注意,我们只使用了 UCI 机器学*知识库上的完整数据集的一个样本,该样本由明尼苏达州交通部好心提供。

这与我们在 N-BEATS 的文章中使用的数据集相同。我们将使用相同的基线和相同的训练/测试分割,来评估 N-HiTS 相对于 N-BEATS 和基线模型的性能。

为了完整起*,我们在这里包括了所有的步骤,但是如果你最近读了我的关于 N-BEATS 的文章,可以直接跳到应用 N-HiTS。

同样,我们使用 Darts,所有代码都在 Python 中,你可以在 GitHub 上获取完整的源代码以及数据集。

我们走吧!

读取数据

当然,每个项目都从导入必要的库开始。

import pandas as pd
import numpy as np
import datetime
import matplotlib.pyplot as plt

from darts import TimeSeries

import warnings
warnings.filterwarnings('ignore')

然后,我们实际上读取我们的数据,并将其存储在数据帧中。

df = pd.read_csv('data/daily_traffic.csv')

由于我们使用的是 dart,我们将从 DataFrame 转到 TimeSeries 对象,这是 dart 中的基本对象。Darts 中的每个模型都必须有一个 TimeSeries 对象作为输入,它还输出一个 TimeSeries 对象。

series = TimeSeries.from_dataframe(df, time_col='date_time')

现在,我们可以使用plot方法轻松地可视化我们的数据。

series.plot()

每小时 94 号州际公路西行交通量。我们已经可以看到每日的季节性和每周的季节性。图片由作者提供。

看上面的图,我们已经发现我们有两个季节周期:每周和每天。很明显,白天路上的车比晚上多,工作日的车比周末多。

这实际上可以用飞镖来验证。它带有一个check_seasonality函数,可以告诉我们一个季节周期是否具有统计意义。

在这种情况下,因为我们有每小时的数据,所以每日季节性的周期为 24(一天中的 24 小时),每周季节性的周期为 168(一周中的 24*7 小时)。

所以,让我们确保这两个季节都很重要。

from darts.utils.statistics import check_seasonality

is_daily_seasonal, daily_period = check_seasonality(series, m=24, max_lag=400, alpha=0.05)
is_weekly_seasonal, weekly_period = check_seasonality(series, m=168, max_lag=400, alpha=0.05)

print(f'Daily seasonality: {is_daily_seasonal} - period = {daily_period}')
print(f'Weekly seasonality: {is_weekly_seasonal} - period = {weekly_period}')

上面的代码块将打印出两个季节周期都是重要的,稍后我们将如何对该信息进行编码以将其输入到我们的模型中。

拆分数据

预测项目中的一个自然步骤,将我们的数据分成训练集和测试集。在这种情况下,我们为测试集保留最近五天的数据,并将其余数据用于训练。

train, test = series[:-120], series[-120:]

train.plot(label='train')
test.plot(label='test')

训练/测试分割了我们的数据。最后五天用于测试集。图片由作者提供。

基线模型

在使用 N-BEATS 之前,最好先有一个基线模型。这是一个简单的模型,作为确定更复杂的模型是否更好的基准。

基线模型通常依赖于简单的统计或简单的启发式。在这种情况下,一种简单的预测方法是简单地重复上一个季节。在这里,由于我们有两个季节性周期,我们将使用每周季节性,以考虑周末的交通量较低。

from darts.models.forecasting.baselines import NaiveSeasonal

naive_seasonal = NaiveSeasonal(K=168)
naive_seasonal.fit(train)

pred_naive = naive_seasonal.predict(120)

在上面的代码块中,我们简单地获取了训练集中最后一周的数据,并在将来重复它。当然,由于我们的预测范围只有五天而不是七天,我们在第五天截断了预测。

下面,我们可以看到来自基线模型的预测。

test.plot(label='test')
pred_naive.plot(label='Baseline')

来自基线模型的预测。图片由作者提供。

然后,我们使用*均绝对误差(MAE)来评估基线的性能。

from darts.metrics import mae

naive_mae = mae(test, pred_naive)

print(naive_mae)

这给了我们 249 的 MAE,因此这是我们试图使用 N-HiTS 来打破的分数。

应用 N 次点击

我们现在准备将 N-HiTS 应用到我们的项目中。

Darts 使我们能够非常轻松地使用 N-BEATS 和 N-Hits 等最先进的模型,因此我们从导入模型和数据缩放器开始。当使用深度学*时,在 0 和 1 之间缩放数据总是一个好主意,因为它使训练更快。

from darts.models import NHiTSModel
from darts.dataprocessing.transformers import Scaler

然后,我们在 0 和 1 之间调整我们的数据。请注意,我们只在训练集上安装了缩放器,以避免将测试集的信息提供给模型。

train_scaler = Scaler()
scaled_train = train_scaler.fit_transform(train)

现在,我们准备初始化 N-HiTS 模型。这里,我们提供了整整一周的数据(168 个时间步长),并训练模型预测未来五天(120 个时间步长),因为这是我们测试集的长度。

nhits = NHiTSModel(
    input_chunk_length=168, 
    output_chunk_length=120,
    random_state=42)

然后,我们简单地在缩放的训练集上拟合模型。

nhits.fit(
    scaled_train,
    epochs=50)

在这里,我们真的可以看到 N-HiTS 的训练速度比 N-BEATS 快得多。另外,飞镖给我们展示了模型的尺寸。在 N-HiTS 的情况下,我们的模型重 8.5 MB,而 N-BEATS 重 58.6 MB。几乎轻了 7 倍!

我们清楚地看到了更低的计算成本,但是该模型在预测方面的表现如何呢?

然后,我们使用predict方法生成预测。请注意,预测将在 0 和 1 之间,因为我们适合缩放的训练集,所以我们需要反转转换。

scaled_pred_nhits = nhits.predict(n=120)
pred_nhits = train_scaler.inverse_transform(scaled_pred_nhits)

我们可以在下图中看到 N-HiTS 的预测。

test.plot(label='Actual')
pred_nhits.plot(label='N-HiTS')

来自 N 次点击的预测。图片由作者提供。

然后,我们简单地打印出 MAE。

mae_nhits = mae(test, pred_nhits)

print(mae_nhits)

这打印了 266 的 MAE。同样,我们没有超过基线,但这是对 N-BEATS 的一个显著改进,如下所示。

每个预测模型的性能。我们看到 N-HiTS 优于 N-BEATS,但它的表现却不如基线。图片由作者提供。

同样,结果令人失望,因为基线仍然优于 N-HiTS。但是,请记住,我们正在处理一个小而简单的数据集。我只取了一个完整数据集的样本,这个样本可能特别具有重复性,这解释了为什么基线如此之好。

尽管如此,您现在知道 N-HiTS 如何工作,以及如何在预测项目中应用它!

结论

N-HiTS 是时间序列预测模型的最新发展,它的表现一直优于 N-BEATS。

N-HiTS 在 N-BEATS 的基础上构建,在每个块上添加一个 MaxPool 层。这将对系列进行子采样,并允许每个堆栈根据内核大小关注短期或长期效果。然后,使用分层插值来组合每个堆栈的部分预测。

这导致 N-HiTS 是一个更轻的模型,在长时间范围内具有更准确的预测。

我希望你喜欢这本书,并且你学到了新的东西!

干杯🍺

posted @ 2024-10-18 09:30  绝不原创的飞龙  阅读(675)  评论(0)    收藏  举报