TowardsDataScience-博客中文翻译-2019-四十八-

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

TowardsDataScience 博客中文翻译 2019(四十八)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

神经量子态

原文:https://towardsdatascience.com/neural-quantum-states-4793fdf67b13?source=collection_archive---------3-----------------------

神经网络如何解决量子力学中高度复杂的问题

Image par Colin Behrens de Pixabay

现代理论物理中最具挑战性的问题之一是所谓的多体问题。典型的多体系统由大量强相互作用的粒子组成。很少有这样的系统可以进行精确的数学处理,并且需要数值技术来取得进展。然而,由于指定一个通用多体量子态所需的资源以指数方式取决于系统中的粒子数量(更准确地说,取决于自由度的数量),即使是今天最好的超级计算机也缺乏足够的能力来精确地编码这样的状态(它们只能处理相对较小的系统,少于 45 个粒子)。

正如我们将看到的,机器学习技术(特别是人工神经网络)的最新应用已经被证明能够提供这种复杂状态的高效表示,使其压倒性的复杂性在计算上易于处理。

在这篇文章中,我将讨论如何应用(一种)人工神经网络来表示许多粒子的量子态。本文将分为三个部分:

  • 基本量子力学概念的鸟瞰图。
  • 机器学习概念的简要描述,特别关注一种称为受限玻尔兹曼机器(RBM)的人工神经网络
  • 解释如何使用 RBM 来表示多粒子量子态。

序言

阿尔伯特·爱因斯坦的科学合作者之一,波兰物理学家利奥波德·英费尔德在他的自传中讲述了一个有趣的故事。

Einstein and Infeld in Einstein’s home (source).

根据因菲尔德的说法,在两位物理学家花了几个月时间进行漫长而艰苦的计算后,爱因斯坦会做出如下评论:

“上帝[自然]不关心我们的数学困难。他根据经验进行整合。”

—爱因斯坦(1942 年)。

爱因斯坦的意思是,虽然人类必须借助复杂的计算和符号推理来解决复杂的物理问题,但自然不需要这样做。

快速提示:爱因斯坦在这里使用了“积分”这个术语,因为许多物理理论都是用被称为“微分方程”的方程来表述的,为了找到这些方程的解,人们必须应用“积分”的过程。

多体问题

正如引言中提到的,理论物理中一个众所周知的难题是多体问题。这个问题已经在经典系统(基于牛顿三大运动定律及其改进的物理系统)和量子系统(基于遵守量子力学定律的系统)中研究了很长时间。

第一个被广泛研究的(经典的)多体问题是涉及地球、月球和太阳的三体问题。

A simple orbit of a 3-body system with equal masses (source).

第一个研究这个多体问题的科学家不是别人,正是艾萨克·牛顿在他的杰作《数学原理》中提到的:

“行星每旋转一周,它就跟踪一个新的轨道[……],而每个轨道都取决于所有行星的综合运动,更不用说它们之间的相互作用[……]。除非我大错特错,否则同时考虑如此多的运动原因,并通过精确的定律来定义运动,这将超出人类的智慧。”

艾萨克·牛顿(1687 年)

Newton’s Principia Mathematica, arguably the most important scientific book in history.

因为本质上所有相关的物理系统都是由一组相互作用的粒子组成的,所以多体问题非常重要。

穷人的定义

人们可以把这个问题定义为“研究物体之间的相互作用对多物体系统行为的影响”。

Collisions of gold ions generate a quark-gluon plasma, a typical many-body system (source).

“许多”在这个上下文中的含义可以是从 3 到无穷大的任何值。在最近的一篇论文中,我和我的同事表明,对于 N = 5 个自旋激发,已经可以找到量子多体行为的特征(下图)。

The density of states of a type of spin system (XX model). As the number of spin excitations increases from 2 to 5, a Gaussian distribution (typical of many-body systems with 2-body couplings) is approached (source).

在这篇文章中,我将重点关注 量子多体问题,这是2013 年以来我的主要研究课题。

量子多体系统

早在 20 世纪 30 年代,物理学家就发现了量子多体系统的复杂性。大约在那个时候,伟大的物理学家保罗·狄拉克 预见了量子力学中的两大问题。

The English physicist Paul Dirac (source).

根据他的说法,第一个是“与相对论思想的理论的精确拟合有关”。第二是“这些(量子)定律的精确应用导致方程过于复杂而无法求解”。第二个问题正是量子多体问题。

幸运的是,许多物理系统的量子态可以用比希尔伯特空间最大容量少得多的信息来描述。这一事实被一些数字技术所利用,包括著名的量子蒙特卡罗 (QMC)方法。

量子波函数

简单来说,一个量子波函数在数学上描述了一个量子系统的状态。第一个接受精确数学处理的量子系统是氢原子。

The probability of finding the electron in a hydrogen atom (represented by the brightness) (source).

一般来说,量子态由复概率振幅ψ(S表示,其中自变量 S 包含了关于系统状态的所有信息。例如,在旋转 1/2 的链中:

A 1D spin chain: each particle has a value for σ in the z-axis (source).

从ψ(S)可以推导出与系统测量相关的概率。例如,正实数ψ(S)的平方模给出了与ψ(S)相关的概率分布:

哈密顿算符

量子系统的性质被系统的哈密顿算符 H 封装。后者是两项的总和:

  • 系统中所有粒子的动能,它与它们的运动有关
  • 系统中所有粒子的势能,与这些粒子相对于其他粒子的位置有关。

量子系统的允许能级(其能谱)可以通过求解所谓的薛定谔方程得到,薛定谔方程是描述量子力学系统行为的偏微分方程。

The Austrian physicist Erwin Schrodinger, one of the fathers of quantum mechanics (source).

薛定谔方程的时间无关版本由以下特征值系统给出:

本征值和相应的本征态是

最低能量对应于系统的所谓“基态”。

简单的例子

具体来说,让我们考虑下面的例子:量子谐振子。QHO 是经典谐振子的量子力学对应物(见下图),这是一个系统,当它从初始位置位移时,会经历一个力,使其恢复到平衡位置。

A mass-spring harmonic oscillator (source)

下面的动画比较了简谐振子的经典概念和量子概念。

Wave function describing a quantum harmonic oscillator (Wiki).

虽然在明确定义的轨迹中的简单振荡质量代表经典系统(上图中的块 A 和 B),但相应的量子系统由复杂的波函数代表。在每个块中(从 C 开始)有两条曲线:蓝色的是ψ的实部,红色的是虚部。

量子自旋系统的鸟瞰图

在量子力学中,自旋可以粗略地理解为粒子和原子核所携带的“角动量的内禀形式”。虽然直观地认为自旋是一个粒子绕其自身轴的旋转,但这一图像并不完全正确,因为这样粒子会以超过光速的速度旋转,这违反了基本的物理原理。如果事实自旋是没有经典对应的量子力学物体。

Example of a many-body system: a spin impurity propagating through a chain of atoms (source)

量子自旋系统与磁性现象密切相关。磁铁是由原子构成的,原子往往是小磁铁。当这些原子磁铁变成平行取向时,就产生了我们所熟悉的宏观效应。

Magnetic materials often display spin waves, propagating disturbances in the magnetic order (source).

我现在将提供机器学习算法的基本组件的快速总结,这将有助于读者理解它们与量子系统的联系。

机器学习=机器+学习

机器学习方法有两个基本组成部分( Carleo,2017 ):

  • 机器,其可以是例如具有参数的人工神经网络ψ

  • 使用例如随机优化算法执行的参数W 、的学习。

The two components of machine learning (NN cartoon from here).

神经网络

人工神经网络通常是非线性多维嵌套函数。对它们的内部工作方式的理解仅仅是探索性的,对它们的结构的研究并不能产生关于它所近似的功能的见解。

Simple artificial neural network with two hidden layers (source).

由于网络参数和正在逼近的数学函数之间缺乏明确的联系,人工神经网络通常被称为“黑箱”。

[## 神经网络的逼近能力(使用 Python 代码)

为什么神经网络可以预测(几乎)任何过程的结果

towardsdatascience.com](/the-approximation-power-of-neural-networks-with-python-codes-ddfc250bdb58) [## 神经网络和纯数学之间的联系

一个深奥的定理如何给出关于人工神经网络能力的重要线索

medium.freecodecamp.org](https://medium.freecodecamp.org/connections-between-deep-learning-physics-and-pure-mathematics-part-i-947abeb3a5dd)

有几种类型的人工神经网络,但对于我们目前的目的,我将集中于限制玻尔兹曼机器(RBM)的具体情况。

什么是受限玻尔兹曼机?

受限玻尔兹曼机器是生成型随机神经网络。它们有许多应用,包括:

  • 协同过滤
  • 降维
  • 分类
  • 回归
  • 特征学习
  • 主题建模

RBM 属于一类被称为基于能源的模型的模型。它们不同于其他(更流行的)神经网络,后者基于输入估计一个,而 RBM 估计输入的概率密度(它们估计许多点而不是单个值)。

RBM 具有以下属性:

  • 它们是浅网络,只有两层(输入/可见层和隐藏层)
  • 它们的隐藏单元 h 和可见(输入)单元 v 通常是二进制值
  • 有一个权重矩阵 W 与隐藏和可见单元之间的连接相关联
  • 有两个偏差项,一个用于由 a 表示的输入单元,一个用于由 b 表示的隐藏单元
  • 每个配置都有一个相关的能量泛函E(vh ),它在训练期间被最小化
  • 它们没有输出层
  • 没有层内连接(这是“限制”)。对于一组给定的可见单元激活,隐藏单元激活是相互独立的(反之亦然)。这个特性极大地方便了分析。

要最小化的能量泛函由下式给出:

Eq.1: Energy functional minimized by RBMs.

可见和隐藏单元的联合概率分布为:

Eq.2: Total probability distribution.

其中归一化常数 Z 称为配分函数。追踪隐藏单元,我们获得可见(输入)向量的边际概率:

Eq.3: Input units marginal probability distribution,

因为,如前所述,给定可见(隐藏)单元激活,隐藏(可见)单元激活是相互独立的,所以可以写:

Eq.4: Conditional probabilities becomes products due to mutual independence.

此外:

Eq. 5: Same as Eq.4.

最后,激活概率为:

Eq.6: Activation probabilities.

其中 σ 是 sigmoid 函数。

训练步骤是之后的:

  • 我们首先将可视单元状态设置为一个训练向量。
  • 然后使用等式 6 左边的表达式计算隐藏单元的状态。
  • 在为隐藏单元选择了状态之后,执行所谓的“重建”,根据等式 6 右边的表达式将每个可见单元设置为 1。
  • 重量变化如下(主要变量是重建值):

RBMs 如何处理输入,一个简单的例子

以下分析大量基于此优秀教程。下面的三幅图显示了 RBM 是如何处理输入的。

A simple RBM processing inputs (source).

  • 在隐藏层的节点 1 处,输入 x 乘以权重 w ,添加偏差 b ,并将结果馈入激活,使输出成为原点(见最左边的图)。
  • 在中间的图中,所有输入在隐藏节点 1 处组合,并且每个输入 x 乘以其对应的 w 。然后对乘积求和,加上 bias b ,并将最终结果传递给激活函数,产生来自隐藏节点 1 的完整输出 a
  • 在第三张图中,输入 x 被传递给隐藏层中的所有节点。在每个隐藏节点, x 乘以其对应的权重 w 。各个隐藏节点接收所有输入 x 的乘积以及它们各自的权重 w 。然后将偏差 b 加到每个和上,结果通过激活函数,为所有隐藏节点产生输出。

RBM 如何学习重构数据

RBMs 执行一种称为“重建”的无人监督的过程。他们学习在数据的两层之间执行一长串的传递(向前和向后传递)来重构数据。在反向传递中,如下图所示,隐藏层中节点的激活函数成为新的输入。

这些输入和各自权重的乘积被求和,并且来自可视层的新偏差 b 被添加到每个输入节点。这种操作的新输出被称为“重建”,因为它是原始输入的近似。

自然地,重建和最初的输入非常不同(因为 w 的值是随机初始化的)。然而,随着误差相对于 w s 反复反向传播,它逐渐最小化。

因此,我们认为:

  • 在前向传递中,RBM 使用输入来对节点的激活进行预测,并根据加权输入 x 来估计输出 a 的概率分布
  • 在向后传递中,RBM 试图根据激活来估计输入 x 的概率分布**

结合两个条件分布,获得了联合概率分布 xa ,即 RBM 学习如何近似原始数据(输入的结构)。

如何连接机器学习和量子系统?

在最近发表在《科学》杂志上的一篇文章中,有人提出可以将量子多体系统的量子波函数ψ(S)视为一个黑箱,然后使用 RBM 对其进行近似。RBM 被训练成通过优化其参数来表示ψ(S)。

RBM used by Carleo and Troyer (2017) that encodes a spin many-body quantum state.

问题是如何把(与时间无关的)薛定谔方程这个特征值问题重新表述为机器学习问题。

变分法

事实证明,答案已经为人所知相当一段时间了,它基于所谓的变分法,这是波动方程的一种替代形式,可用于获得量子系统的能量。使用这种方法,我们可以将优化问题写成如下形式:

其中E【ψ】是依赖于本征态和哈密顿量的泛函。解决这个优化问题,我们得到基态能量和相应的基态。

量子态和受限玻尔兹曼机

在 Carleo 和 Troyer (2017) 中,RBM 被用来表示一个量子态ψ(S)。他们将 RBM 一般化,以允许复杂的网络参数。

很容易证明能量泛函可以写成

其中最后一个等号后面的期望值的自变量是局部能量。然后使用随机重构 (SR)的方法训练神经网络。相应的优化迭代如下:

The gradient descent update protocol.

其中 η 是学习率S是依赖于本征态及其对数导数的随机重构矩阵。更多详情请查看本文。

Carleo 和 Troyer (2017) 对自旋为 1/2 的量子系统特别感兴趣,他们将量子态写为:

在这个表达式中,ψ的 W 自变量是一组参数:

其中 ab 上的组件是真实的但是 W 可以是复杂的。层内交互的缺失(RBMs 架构的典型特征)允许隐藏变量被求和(或追踪),从而将上述表达式大大简化为:

为了训练量子波函数,遵循与上述 RBMs 类似的过程(更多细节在此)。

令人印象深刻的准确性

下图显示了 NQS 基态能量估计的可忽略的相对误差。每个图对应于一个测试用例,它是一个具有已知精确解的系统。横轴是隐藏单元密度,即隐藏单元和可见单元的数量之比。请注意,即使使用相对较少的隐藏单元,模型的精度也已经非常令人印象深刻(百万分之一的误差!)

The error of the model ground-state energy relative to the exact value in three tests cases (source).

结论

在这篇简短的文章中,我们看到了受限玻尔兹曼机器(RBMs),一种简单的人工神经网络,可以用来以极高的精度计算许多粒子的量子系统的基态能量。更多细节,我建议去查一下最早提出这种方法的优秀论文。

感谢阅读!

我的 Github 和我的个人网站 www.marcotavora.me (希望)有一些关于数据科学和物理学的其他有趣的东西。

一如既往,欢迎建设性的批评和反馈!

使用 Tensorflow 2.0 进行神经风格转换

原文:https://towardsdatascience.com/neural-style-transfer-23a3fb4c6a9e?source=collection_archive---------18-----------------------

作为将预制的 Tensorflow 代码和算法串在一起的过渡,我通过尝试我在一篇论文中描述的算法的第一个实现,开始了成为一名熟练的 Tensorflow 编码器的旅程。

这个项目是我将深度学习融入学校工作的一种方式。最初的项目是我计算机科学选修课上的一个图像处理项目。该项目的约束包括为图像处理应用程序创建一个功能,该功能将增加应用程序的价值并增加功能。

在了解了这些要求后,我想到了神经类型转移,在 coursera 的 deep learning . ai DL specialization 中为我介绍了这一点。主意已定,我开始研究神经类型转移的数学。知道 Tensorflow 2.0 将会被急切地执行,我决定用它来编程算法,以便于扩大项目规模。

我的第一步是阅读向研究界介绍 NST 的论文。

论文摘要

[## 艺术风格的神经算法

在美术中,尤其是绘画,人类已经掌握了通过构图创造独特视觉体验的技巧

arxiv.org](https://arxiv.org/abs/1508.06576)

该论文的作者提出了一种算法,通过神经网络将一幅图像的风格转移到另一幅图像的内容上来创建艺术品。

总的来说,人类非常擅长识别图像的整体风格,那些精通艺术的人甚至可以按照其他更著名的艺术作品的风格来复制艺术作品。本文中介绍的算法试图对人类创作新艺术作品的能力进行建模。

使用 VGG19 预训练权重中中间层的激活从内容和风格图像中提取信息,输出图像被优化以最小化 3 种类型的损失:

Source

内容丢失

损失函数的这一部分负责控制最终出现在优化输出图像中的内容图像的数量。内容丢失的主要挑战是找出一种方法,只提取图像的内容特征,而不是样式图像。如果内容丢失只是检查输出图像和内容图像之间的距离,那么内容和样式特征都将被转换到输出图像上。这是一个问题,因为我们不想要内容图像的样式,但想要样式图像的样式。

对此的解决方案是使用卷积神经网络的特征图。受过训练的神经网络学会表现图像的不同部分。作者发现,ConvNet 的初始层代表图像的粗略、基本模式,而后面的层代表更明显的特征。如下所示,ConvNet 的中间层可以在没有样式信息的情况下捕获图像的空间信息,这正是这里所需要的。

这是这篇论文的主要发现,意味着 ConvNets 能够分离图像的风格和内容特征,并且这些特征可以用于创建图像的复杂组合。

L. Gatys et Al

定义为输出和内容特征映射之间的简单 L2 距离,它迫使优化器合并内容图像的基本内容。

风格丧失

风格损失负责将风格图像合并到最终输出中。虽然人类对风格的理解通常基于图像的经验和模糊特征,但本文提出使用 gram 矩阵来表示图像的风格。

gram 矩阵是通过计算展平样式特征和它们自身的点积而得到的。

使用 gram 矩阵是因为图像的风格不依赖于像素值,而是依赖于像素值之间的关系;gram matrix 将关于样式图像的所有信息去本地化,例如纹理、形状和重量:到底什么是样式。

为了简化和理解格拉姆矩阵所代表的内容,让我们以两个向量的点积为例。

Source

点积也可以定义为 a 在 b 轴上的长度乘以 b 的长度。这意味着向量 a 和 b 之间的角度越小,它们之间的点积就越大。因此,两个向量的点积表示它们彼此有多相似。

现在,让我们来看看扁平化风格特征中的 2 个特征。它们之间的点积越大,特征之间的相关性越强,点积越小,特征之间的差异越大。也就是说,乘积越小,这两个特征同时出现的次数越少,乘积越大,它们同时出现的次数越多。直观地说,这给出了关于图像的纹理和风格的信息,并丢弃了关于图像的所有空间信息。

一旦计算了 gram 矩阵,就使用相同的 L2 距离来计算输出图像的 gram 矩阵和样式图像的 gram 矩阵之间的差异。

优化

这些损失在随机噪声图像上进行优化,该图像基于总损失的梯度而改变。

我的实现

我使用了论文中的上述细节来实现我自己的 NST 算法。我对基本算法做了一些修改,以便更容易在 Tensorflow 中实现,并提高输出图像质量。

总变差损失

在评估我实现的算法时,我做的第一个改变是减少图像的“颗粒感”。这是因为图像中存在相当多的噪声,并且沿着角落经常有颜色和色调的突然变化。

在考虑这个问题的解决方案时,我想到总变差是图像中噪声的一个很好的度量,并且它可以很容易地在 tensorflow 中实现。

事实证明,全变分是张量流中的内置函数。该函数对相邻像素值的绝对差值求和。

亚当优化器

我在实现算法时做的另一个改变是使用亚当优化器代替 L-BFGS。让我们先来看看它们之间的区别。

L-BFGS 算法是估计参数空间曲率的真正的准牛顿方法。如果参数空间有大量的鞍点,这使得它优于 Adam。Adam 优化器是一种一阶方法,试图弥补它不能估计曲率的事实。L-BFGS 算法的缺点是计算量大,而亚当运行速度很快。

我选择使用 Adam 的主要原因是因为这种计算上的差异。另一个几乎同样重要的原因是,Tensorflow 没有 L-BFGS 实现,只有一种方法来合并 scipy 的优化器。不幸的是,我发现 scipy 的优化器非常慢,所以决定用 Adam 代替。

密码

我用的是 Tensorflow 2.0,它内置了急切执行功能…

个人损失

组合损失

我对每张图片的每组特征图的损失进行了平均。这使我能够在不改变损失权重的情况下,更改用于获取要素地图的 conv 图层数量。

计算梯度

随着急切执行的增加,tensorflow 增加了一种创建计算图形的方法,通过该图形可以计算梯度。要做到这一点,您可以用 tf 将所有要做的计算包装在一个中。GradientTape()作为磁带结构,然后一旦在“with”之外,你就计算梯度。

整体优化功能

整个优化过程从将输出图像初始化为内容图像开始。这是对原始论文的第三次也是最后一次修改。我发现当输出图像作为内容图像开始时,模型会收敛得更快。这是因为该模型不必从随机初始化的图像中从头开始,只需改变内容图像的样式。

结果

在对许多不同的图像和样式运行 NST 后,我发现具有统一和清晰样式的样式图像很容易被转换到内容图像上,并且具有清晰和明确的边缘和线条的内容图像也很容易被转换。

正如你所看到的,大部分的风格都转换得干净而准确。不太吸引人的图像的重复出现的模式是样式图像的样式不是很明确。

此外,出于时间考虑,所有图像的尺寸都调整为 512x512 像素。这也是为什么由于图像上的插值伪影,一些样式没有被完美地翻译。

产生的最佳图像是在没有对原始图像进行任何尺寸调整和任何更改的情况下创建的。

如上图所示,神奈川外巨浪的风格与图宾根内卡锋面的图片完美融合,产生了高分辨率和美丽的边缘和边界的图像。图像的内容保持清晰,而风格却完全和根本不同。

结论/想法

这是一个很好的例子,说明了神经网络的代表性力量,以及看似神秘的层和算法是如何产生这种美感的。nst 算法证明了神经网络与我们自己对这个世界的理解是多么相似。

我的信念是,如果对其他神经网络,如 RNNs 和 GANs,有了这样一个完整的理解,一些更不可思议的事情将成为可能。我觉得在课程和教程中,对神经网络的理解和获得直觉是不够强调的,这导致了在神经网络层周围形成了一个看似“黑箱”的东西。

由于这个项目,我对神经网络和卷积层的理解有了很大的增长,我学到并获得了许多我在其他项目中缺乏的直觉。我希望这种对 ConvNets 的经验主义理解能够帮助我从根本上理解深度学习中的条件 GANs 和其他更复杂的技术。

这个项目帮助我的另一件事是,它打破了我阅读论文的僵局。在这个项目之前,由于我对科学论文的复杂性和“声望”的误解,这是我不愿意甚至害怕的事情。通过这个项目,我学会了阅读和理解论文的核心技术,现在将它们应用到未来越来越多的研究中。

感谢阅读!该项目的完整代码和结果在https://github.com/tekotan/csp-neural-style-transfer。

神经类型转移

原文:https://towardsdatascience.com/neural-style-transfer-4d7c8138e7f6?source=collection_archive---------26-----------------------

风格转移是计算机视觉中一个令人兴奋的子领域。它旨在将一个图像的风格转移到另一个图像上,称为内容图像。这种技术允许我们结合不同图像的内容和风格来合成新的图像。在这个子领域已经取得了一些进展,但最值得注意的初步工作(神经类型转移)是由 Gatys 等人在 2015 年完成的。我应用这种技术得到的一些结果可以在下面看到。

Left to right: Content image, Style image, Generated image

这种方法相当直观,本文是在 Pytorch 和 Python 中实现神经类型转换的简单指南,前面还有对该方法的解释。这篇文章的完整代码可以在我的 github 上找到。

理解风格和内容

神经风格转移包括将一幅图像的风格转移到另一幅图像的内容上。这些东西是什么?

内容 字面意思是图像由什么组成。它可能是一个风景,一个海滩环境,一只花园里的猫,一只动物园里的长颈鹿…..等等。在你典型的图像分类网络中,这基本上就是你的图像的标签。内容是图像组成的高级表示。卷积神经

风格 一幅图像涉及更复杂的细节:笔触、颜色对比、整体纹理..等等。假设图像的内容是一只狗,那么你和我绘制“内容”即狗的方式将会不同。这种差异就是图像的风格。你的笔触可能会更粗、更有活力,而我的会更细、更暗淡。

这些定义有助于理解,但实际实现算法需要更精确的定义。这些定量定义可以使用下面概述的标准图像分类网络来获得。

卷积神经网络(CNN)常用于图像分类任务。对于分类,他们将图像作为输入,并应用一系列卷积滤波器、最大池和非线性激活,以给出输入图像的更密集表示。我假设读者熟悉 CNN:这里提供了更全面的 CNN 指南。

这些卷积网络丢失了大量的输入图像信息(尤其是汇集层)。这种丢失的信息主要与图像的风格有关,因为当处理图像分类任务时,风格是无用的信息。默认情况下,这些分类管道(CNN)非常擅长表示图像的内容。密集输出表示是要素地图的术语,从这些 CNN 获得的完全连接的图层保留了输入图像的大部分内容,但丢失了许多样式。这是因为 CNN 的任务是对图像进行分类,这自然与图像的内容有关,而不是真正的风格。因此,图像的内容可以直接定义为从任何预训练图像分类网络获得的最后卷积特征图的输出。

对于本文,我们将使用作者最初使用的原始预训练 VGG19 网络。因此,图像的内容表示将是 VGG19 网络中最后一个卷积层(块 5,层 4)的输出。目标图像,即我们希望最终实现的图像,将从内容图像开始,我们将迭代地修改它,以将我们的样式图像的样式合并到这个目标图像上。然而,当我们进行修改时,我们希望保留图像的内容表示。我们将最小化表示两个图像(内容图像和目标图像)的内容损失的损失函数。这种内容损失可以简单地视为两个图像的内容表示的均方误差(MSE)损失(上面提到的 VGG19 特征图输出)。

The content loss, the term T_subC is the target image content feature map, and the term C_subC is the content image content feature map, L_sub(Content) represents the MSE of the two. The term is divided by 2 only for obtaining lower numerical value.

图像上的风格在数量上表示起来有点复杂,因为网络本身并不保存这种风格信息。但是,正如我们对内容图像所做的那样,我们会提出一种样式表示,并在迭代转换期间最小化样式图像和目标图像之间的样式损失。

使用作为卷积特征图的一部分的不同矢量的输出的相关性来获得风格表示。这里的想法是,对于不同的风格,不同层的不同特征地图中的特征向量将以不同的方式相关。这种相关性将代表图像的风格,即不同的笔触、调色板和纹理。在数学上,特定特征映射的这种相关性是通过将特征映射与其自身的转置相乘来获得的。这很容易理解,因为这种乘法将给出原始特征图输出中每组向量之间的相关值。得到的合成矩阵称为 gram 矩阵。图像的整体风格是通过考虑 VGG19 中 5 个卷积层的所有 gram 矩阵而获得的。类似于内容损失,风格损失被定义为目标图像的 gram 矩阵和风格图像的相应 gram 矩阵的 MSE。然而,这一次,有 5 个特征图,即 5 个 gram 矩阵,即风格的 5 个损失,而不是仅仅 1 个(内容的)。因此,整体风格损失被视为内容损失的线性组合。

生成这些用于风格比较的 gram 矩阵背后的主要直觉是比较具有不同内容的不同特征图之间的关系,以查看特征图的风格是否相似。

The style loss, w_subi correspond to the weights given to each of the 5 gram matrix losses, T_sub(s, i) represents the target image style feature map, S_sub(s, i) represents the style image style feature map, a is the weight hyperparameter to assign relative importance of style and content losses, L_sub(style) is the overall weighted MSE.

我们现在的总体损失等于风格损失加上内容损失。使用这个损失作为我们的目标函数,我们可以开始使用标准的反向传播和梯度下降来优化我们的目标图像(初始化为内容图像)。这就是神经风格转移所需要的全部!

实施

第一个:包括所有必要的库

第二个:在 Pytorch 中初始化预训练的 VGG19 模型,并冻结所有模型参数,因为我们将不训练网络。如果 NVIDIA GPUs 可用,将模型移至 cuda。

第三个:定义一个函数,从 VGG19 网络中提取特征。字典中的层名称是 Pytorch 预训练 VGG19 模型中预定义的名称。

第四个:定义一个函数,在给定特征图为张量的情况下,计算 gram 矩阵。

第五个:获取样式和内容图像的特征,获取样式损失的 gram 矩阵,将目标图像初始化为样式图像,为来自 5 个 gram 矩阵的损失的线性组合设置样式权重,为两个损失的相对重要性设置内容权重和样式权重(在上面的样式损失图像中为a’),为反向传播选择优化器,并设置迭代和修改目标图像的步骤数。

第六:迭代修改目标图像,同时保持损失最小。修改为'步数'步数。

差不多就是这样!神经类型转移的完整实现和解释。你可以在我的 github 上查看结果和全部代码。

感谢您的阅读!

卷积网络的神经类型转移和可视化

原文:https://towardsdatascience.com/neural-style-transfer-and-visualization-of-convolutional-networks-7362f6cf4b9b?source=collection_archive---------7-----------------------

使用迁移学习在 10 分钟内创建专业外观的艺术品。

同样,我们钦佩音乐家、艺术家、作家和每一个有创造力的人的故事,因为他们的个人奋斗,他们如何克服生活的挑战,并从他们经历的一切中找到灵感。这是人类艺术的真正本质。这是无法自动化的事情,即使我们实现了始终难以捉摸的通用人工智能。— 雷·迪克森,BD tech talks

Neural style transfer using the style of famous “Great Wave off Kanagawa” and transferring to the skyline of Chicago.

这篇文章将是一个关于使用神经风格转移(NST)学习来生成像上面这样的专业外观的艺术品的教程。NST 已经存在有一段时间了,在你之前有一些网站执行所有的功能,但是,玩一玩和创建你自己的图像是非常有趣的。NST 是计算密集型的,所以在这种情况下,你不是被你的想象力所限制,而是主要被你的计算资源所限制。

本文中使用的所有代码都可以在我的神经网络 GitHub 页面上提供的 Jupyter 笔记本上找到。到本文结束时,您将拥有使用任何图像生成作品所需的所有资源。

[## GitHub-mpstewart 1/神经网络

这个存储库包含与我的全连接神经网络系列相关的 Jupyter 笔记本内容。

github.com](https://github.com/mpstewart1/Neural-Networks)

介绍

神经类型转移 (NST)可以总结如下:

高感知质量图像的艺术生成,将某些输入图像的风格或纹理与不同图像的元素或内容相结合。

从上面的定义可以清楚地看出,要使用 NST 生成一幅图像,我们需要两幅独立的图像。第一幅图像是我们希望转换风格的图像——这可能是一幅名画,例如我们看到的第一幅图像中使用的“神奈川外的巨浪”。然后,我们拍摄第二张图像,并使用第一张图像的样式来转换这张图像,以便变形这两张图像。下图说明了这一点,其中图像 A 是一个河边城镇的原始图像,第二个图像(B)是图像转换后的图像(样式转换图像显示在左下角)。

Leon A. Gatys, Alexander S. Ecker, and Matthias Bethge, “A neural algorithm of artistic style,” Aug. 2015. [1]

本教程将充分详细地解释这个过程,以理解在引擎盖下发生了什么。为了理解这一点,我们首先要看看卷积神经网络的其他一些方面。将讨论以下主题:

  • 可视化卷积网络
  • 图像重建
  • 纹理合成
  • 神经风格转移
  • 深梦

是时候开始了。

可视化卷积网络

为什么我们想要可视化卷积神经网络?主要原因是,有了神经网络,我们对学习和内部运作了解甚少

通过可视化,我们可以:

  • 观察输入刺激如何激发个体特征图,
  • 观察特征的演变
  • 做出更有根据的设计。

在本文中,我们将使用类似于 AlexNet [2]的架构来解释 NST。

The architecture used for NST. [3]

详情见“可视化和理解卷积网络” [3]。该网络在 ImageNet 2012 培训数据库上接受 1000 个班级的培训。输入是大小为 256 x 256 x 3 的图像,网络使用卷积层和最大池层,最后是完全连接的层。

为了可视化,作者使用了一个去进化网络【4】。这样做的目的是将隐藏的特征映射投影到原始输入空间中。这使我们能够可视化特定过滤器的激活功能。“去卷积”网络的名称可能是不合适的,因为该网络不执行任何去卷积。

Deconvolutional network [4].

解卷积网络描述

这个反进化网络有几个方面:去极化、整流和过滤。

取消 pooling

  • 最大池操作是不可逆的。
  • 开关变量—记录最大值的位置。
  • 它将重构的特征放入记录的位置。

Unpooling layer.

整流— 信号经过 ReLu 操作。

滤波 —使用转置卷积。

  • 过滤器水平和垂直翻转。
  • 转置卷积将要素映射回输入空间。
  • 转置卷积对应于梯度的反向传播(类似于 MLPs)。

我们如何进行特征可视化?

(1)在训练好的网络上评估验证数据库。

(2)记录每个过滤器输出的九个最高激活值。

(3)将记录的九个输出投影到每个神经元的输入空间。

  • 投影时,给定层中的所有其他激活单元都被设置为零。
  • 该操作确保我们仅观察到单个通道的梯度。
  • 开关变量用于非 pooling 层

我们现在可以使用这种技术来查看 AlexNet 各层的输出。

AlexNet first layer.

AlexNet second layer.

AlexNet fourth layer.

AlexNet fifth layer.

我们可以从上面的图像中看到,早期的层学习更多的基本特征,如线条和形状,而后面的层学习更复杂的特征。

我们如何在训练中测试特征进化?

我们可以查看五层中每一层在 1、2、5、10、20、30、40 和 64 个时期后的特征演变。

Example output of five layers at a specified number of epochs.

关于网络,我们可以注意到以下几点:

  • 在几次单次通过后,低层很快会聚。
  • 第五层直到非常大量的时期才收敛。
  • 收敛后,下层可能会改变其特征对应关系。

我们如何知道这是最好的架构?

我们可以进行架构比较,我们实际上尝试两种架构,看看哪一种做得最好。我们可以通过检查不同架构对相同输入的响应是否相似或更强烈来做到这一点。

Left picture used filters 7 × 7 instead of 11 × 11, and reduced the stride from 4 to 2.

我们在上面的图像中看到,有证据表明,修改后的(左侧)网络上有更少的死单元,以及更多定义的功能,而 Alexnet 有更多的混叠效果。

图像重建

这就是数学上有点复杂的地方。如果您想了解 NST 的内部工作原理,这是很有必要的,如果不是,请随意跳过这一部分。本节将遵循“通过反转理解深层图像表征”【5】中给出的解释。

我们能够从潜在特征中重建图像。我们可以训练网络中的层来保留图像的精确照片表示,保留几何和光度不变性。为了清楚起见,下面等式中的符号a【l】对应于层 l 的潜在表示。我们的工作是解决最优化问题:

我们还可以使用α-范数正则化子来正则化这个优化过程:

以及总变分正则化子:

这将在后面的代码实现中变得更加清晰。

图像重建的步骤是:

  • 用随机噪声初始化 y
  • 前馈传递图像。
  • 计算损失函数。
  • 计算成本的梯度并反向传播到输入空间。
  • 用梯度步长更新生成的图像 G

此过程用于生成下面的示例图像。

Example of image reconstruction.

Example of image reconstruction.

纹理合成

纹理合成的目的是生成模仿给定纹理的高感知质量图像。这是使用用于对象分类的经过训练的卷积神经网络来完成的。我们将各层之间的特征关联作为一个生成过程。下面是一个纹理合成的例子:

Example of texture synthesis.

给定图层的输出将如下所示:

为了计算特征图的互相关,我们首先使用带有下标 ijk 和上标 la 来表示给定滤波器 k 在层 l 的输出。该输出与不同通道k’之间的互相关为:

格拉姆矩阵定义为:

在哪里

生成新的纹理

为了创建一个新的纹理,我们可以合成一个与我们想要再现的图像具有相似相关性的图像。 G 上标【l】**【S】是指样式图像的克矩阵, G 上标【l】**【G】是指新生成的图像。

在哪里

指的是 Frobenius 规范。我们将所有层损失合并到一个全局成本函数中:

对于给定的权重λ1,.。。,λL。

流程描述

现在我们知道了所有的细节,我们可以完整地说明这个过程:

要了解更多细节,我建议你参考论文“使用卷积神经网络的纹理合成”【6】。

神经类型转移

NST 最早发表于 Gatys 等人的论文《艺术风格的一种神经算法》,最初发布于ArXiv2015【7】。

几个移动应用程序使用 NST 技术,包括 DeepArt 和 Prisma 。

这里有更多的样式化的例子,用来转换我们之前使用的河岸城镇的相同图像。

神经风格转移结合了内容和风格重建。要让 NST 发挥作用,我们需要做几件事:

  • 选择一个层(或一组层)来表示内容-为了获得最佳效果,建议使用中间层(不要太应该,也不要太深)。
  • 通过使用反向传播来最小化总成本。

  • 用随机噪声初始化输入(产生梯度所必需的)。
  • 用平均池替换最大池层,以改善渐变流并生成更具吸引力的图片。

代码实现

现在到了你们期待已久的时刻,代码能够让你们自己制作这些图像。要更清楚地了解代码和数学符号之间的关系,请参阅 GitHub 资源库中的 Jupyter 笔记本。

第 1 部分:导入必要功能

第二部分:内容丢失

我们可以生成一个图像,它结合了一对的内容和风格以及包含这些信息的损失函数。这是通过两个术语实现的,一个术语模拟内容图像的特定层的特定激活,另一个术语模拟样式。损失函数中要优化的变量将是生成的图像,其目的是最小化建议的成本。注意,为了优化该函数,我们将对像素值而不是神经网络权重执行梯度下降

我们将加载一个名为 VGG-16 的经过训练的神经网络,该网络在 1 中提出,他们分别在 2014 年 ImageNet Challenge 的本地化和分类赛道上获得了第一名和第二名。这个网络已经被训练成可以从超过一百万张图片中识别超过 1000 个类别。我们将使用为感兴趣的图像获得的激活值来表示内容和样式。为了做到这一点,我们将前馈感兴趣的图像,并观察它在指示层的激活值。

内容损失函数测量生成图像的特征图与源图像的特征图有多大不同。我们将只考虑用一个单独的层来表示图像的内容。

第 3 部分:风格损失

该样式测量一组图层中过滤器之间的相似性。为了计算相似性,我们将计算样式层的激活值的 Gram 矩阵。Gram 矩阵与经验协方差矩阵相关,因此反映了激活值的统计。

输出是一个二维矩阵,它近似地测量给定层的不同滤波器之间的互相关。这在本质上构成了一层的风格。

第 4 部分:风格损失—图层损失

在实践中,我们计算一组层的风格损失,而不仅仅是一个层;则总风格损失是每层风格损失的总和:

第 5 部分:全变差正则化子

我们还将使用全变分正则化来提高图像的平滑度。这个惩罚项将减少相邻像素值之间的变化。

第 6 部分:风格转移

我们现在把它们放在一起,生成一些图像!下面的style_transfer函数结合了你在上面编码的所有损失,并对图像进行优化,使总损失最小化。阅读代码和注释以理解该过程。

第六部分:生成图片

现在我们准备制作一些图像,运行你自己的构图,测试超参数的变化,看看你能想出什么,下面我给你一个例子。要改变的超参数列表如下:

  • base_img_path是内容图像的文件名。
  • style_img_path是样式图像的文件名。
  • output_img_path是生成图像的文件名。
  • convnet是神经网络的权重,VGG-16 或 VGG-19。
  • content_layer指定哪个层用于内容丢失。
  • content_weight在整体复合损失函数中对内容损失进行加权。增加此参数的值将使最终图像看起来更真实(更接近原始内容)。
  • style_layers指定用于样式丢失的图层列表。
  • style_weights为 style_layers 中的每一层指定一个权重列表(每一层都将对整体样式损失产生影响)。我们通常为早期风格层使用较高的权重,因为它们描述了更多的局部/较小尺度的特征,这对于纹理来说比较大感受野上的特征更重要。一般来说,增加这些权重会使生成的图像看起来不太像原始内容,并且更偏向于样式图像的外观。
  • tv_weight指定总损失函数中总变差正则化的权重。增加该值会使生成的图像看起来更平滑,锯齿更少,但会降低样式和内容的保真度。

如果运行 50 次迭代,下面的代码将生成本文的正面图像。

下面是我自己在 50 次迭代后实现的几个粗略的例子:

Style of ‘Escher Sphere’ used to transform an image of the Goldengate Bridge.

Style of ‘Seated Nude’ used to transform an image of the riverbank town image.

我建议在 GitHub 资源库(或您自己的资源库)中获取一些图像,并使用超参数,看看您能制作出什么样的图像。然而,警告你,训练时间相当长,除非你有一个 GPU,可能需要几个小时的一个图像。

深梦

DeepDream 是一个计算机视觉程序,由 Google 工程师 Alexander Mordvintsev 创建,它使用卷积神经网络通过算法 pareidolia 寻找并增强图像中的模式,从而在故意过度处理的图像中创建一个梦幻般的迷幻外观。

谷歌的项目推广了术语(深度)“做梦”,指的是在经过训练的深度网络中产生预期激活的图像的生成,该术语现在指的是相关方法的集合。

这是一个由 DeepDream 转换的图像的例子。

概念主义:深入神经网络

对于神经网络中的每一层封装了什么类型的特征,我们已经有了合理的直觉:

  • 第一层可能寻找边缘或角落。
  • 中间层解释基本特征,以寻找整体形状或组件,如门或树叶。
  • 最后一层将它们组合成完整的解释:树、建筑等。

这对于判别模型来说很好,但是如果我们想要构建一个生成模型呢?比方说,你想知道哪种图像会产生一个香蕉。一种方法是将神经网络颠倒过来,从充满随机噪声的图像开始,然后逐渐将图像调整到神经网络认为是香蕉的方向。

就其本身而言,这并不能很好地工作,但是如果我们施加一个先验约束,即图像应该具有与自然图像相似的特征,例如相邻像素之间的相关性,这就变得更加可行了。

或许不足为奇的是,经过训练能够区分不同图像类别的神经网络也拥有生成图像所需的大量信息。

这可以用于类生成的目的,本质上是将判别模型转换成生成模型。但是我们为什么要这么做呢?

好吧,假设你训练一个神经网络来分类叉子。你拍摄了数千张叉子的图像,并用它们来训练网络,网络在数据上表现得相当好——但网络在做什么呢?网络用什么来表示分叉?这对于确保网络学习正确的特征而不是欺骗是有用的。

可视化错误

这种欺骗的一个很好的例子是哑铃。在一组哑铃图片上训练网络后,我们使用一些带有先验约束的随机噪声来“想象”一些哑铃,看看会弹出什么,结果如下:

正如我们所看到的,网络总是生成带手臂的哑铃。然而,该网络未能完全提取哑铃的本质——例如,没有一张照片中有举重运动员。视觉化可以帮助我们纠正这种训练失误。

增强特征地图

我们也可以让网络做出决定,而不是规定我们希望网络放大哪个特征。

这可以通过向网络提供图像,然后选择一个层,并要求网络增强它检测到的任何内容来实现。较低的层倾向于产生笔画或简单的装饰性图案,例如:

随着更高级别的层,复杂的特征甚至整个对象往往会出现。—这些识别更复杂的特征。这个过程创造了一个反馈循环:如果一朵云看起来有点像一只鸟,网络会让它看起来更像一只鸟。

如果我们用动物的图片进行训练,网络会让它看起来更像动物:

由于输入的特征会使网络偏向某些解释,因此结果会因图像类型的不同而有很大差异。例如,地平线上往往布满了塔和宝塔。岩石和树木变成了建筑。鸟和昆虫以树叶的形象出现。

如果我们对它自己的输出迭代地应用算法,并在每次迭代后应用一些缩放,我们会获得源源不断的新印象,探索网络所知道的一系列事情。

DeepDream 是一个迷人的项目,我鼓励读者如果感兴趣的话,可以更深入地了解它。

最终意见

我希望你喜欢这篇神经风格转移的文章,并学习了一些关于风格转移、卷积神经网络的新知识,或者可能只是喜欢看 DeepDream 的深度神经网络生成的迷人图片。

参考

[1] Leon A. Gatys,Alexander S. Ecker,和 Matthias Bethge,“艺术风格的神经算法”,2015 年 8 月。

[2] Alex Krizhevsky、Ilya Sutskever 和 Geoffrey E Hinton,“使用深度卷积神经网络的 Imagenet 分类”,载于《神经信息处理系统进展》,2012 年,第 1097–1105 页。

[3]马修·d·泽勒和罗布·弗格斯,《计算机视觉中的可视化和理解卷积网络》。2014,第 818–833 页,施普林格出版社。

[4]马修·D·泽勒、格雷厄姆·W·泰勒和罗布·弗格斯,“用于中高级特征学习的自适应去进化网络”,载于 IEEE 计算机视觉国际会议(ICCV),2011 年,第 2018–2025 页。

[5] Aravindh Mahendran 和 Andrea Vedaldi,“通过反转理解深层图像表示”,2014 年 11 月。

[6] Leon A. Gatys、Alexander S. Ecker 和 Matthias Bethge,“使用卷积神经网络的纹理合成”。

[7]莱昂·加蒂斯;亚历山大·埃克;马蒂亚斯·贝斯吉(2015 年 8 月 26 日)。《艺术风格的神经算法》。

实时视频上的神经类型转换(带有完整的可实现代码)

原文:https://towardsdatascience.com/neural-style-transfer-on-real-time-video-with-full-implementable-code-ac2dbc0e9822?source=collection_archive---------14-----------------------

Neural Style Transfer

执笔:2019 年 5 月 29 日作者:Sourish Dey

最近几年,我们几乎在生活的每个角落都体验到了计算机视觉的应用——这要归功于海量数据和超强 GPU 的可用性,这使得卷积神经网络(CNN)的训练和部署变得超级容易。在我的上一篇文章中,我讨论了一个这样的商业增值应用。今天围绕机器学习的最有趣的讨论之一是它可能如何影响和塑造我们未来几十年的文化和艺术作品。神经类型转移是卷积神经网络最具创造性的应用之一。

通过拍摄内容图像和风格图像,神经网络可以将内容和风格图像重新组合,以有效地创建艺术(重组 ) 图像。虽然有许多像 Prisma 这样的应用程序可以为手机拍摄的图片生成艺术风格,但本文的目的是要立刻理解这个看似困难的概念背后的科学和艺术。这里分享实时可实现的代码。

背景-神经类型转移

神经风格转移(Neural Style Transfer)的概念最初是由 Gatys、Ecker 和 Bethge ( 艺术风格的神经算法于 2015 年)在开创性的论文中提出的,演示了一种将一幅图像的艺术风格与另一幅图像的内容相结合的方法。基本思想是采用像 VGG 16(通常为图像分类或对象检测而训练)这样的预训练深度卷积神经网络学习的特征表示,以获得图像风格和内容的单独表示。一旦找到这些表示,我们就试图优化生成的图像,以重新组合不同目标图像的内容和风格。因此,这个概念随机化了纹理、对比度和颜色,同时保留了内容图像的形状和语义特征(中心方面)。虽然它有点类似于颜色转换,但它能够传递纹理(样式)和其他各种扭曲,这是经典颜色滤镜所无法实现的。

问题陈述——不是优化问题吗?

所以这里的问题陈述给定了一张内容照片 X 和风格照片 Y 我们如何将 Y 的风格转移到内容 X 上生成新的照片 Z 我们如何训练 CNN 处理和优化差异(X 和 Y 之间的差异)以达到一个最优的全局(Z)?

基本概述-神经风格转移(来源)

基本概述-神经类型转移(来源)

优化问题概述

Gatys 在原论文(一种艺术风格的神经算法2015)中显示“将一幅图像的风格(纹理)转移到另一幅内容图像上,被提出为一个优化问题,可以通过训练一个深度神经网络来解决”。以下是这个拼图的组成部分:

  • 内容损失:它表示样式转移网络的输出图像(样式化图像)的内容与输入图像或“内容目标”的内容的相似程度,如果输入图像(X)和样式化图像(Z)在内容方面彼此相似,则它趋于零,如果它们不同,则它增大。为了恰当地捕捉图像的内容,我们需要保留空间(形状/边界等。)/内容图像的高级特征。由于像 VGG16 这样的图像分类卷积神经网络被迫学习更深层的高级特征/抽象表示或图像的“内容”,因此对于内容比较,我们在输出(softmax)层之前的某个更深层(L)1 或 2 层使用激活/特征映射。可以根据需要选择 L(从哪个层提取内容特征),选择的层越深,输出图像看起来就越抽象。所以 L 是网络的超参数。

  • Gram 矩阵和样式损失:虽然稍微复杂一些,但是原始样式图像(Y)和网络输出图像(Z)之间的样式损失也是作为从 VGG-16 的图层输出中提取的要素(激活图)之间的距离来计算的。这里的主要区别在于,不是直接比较来自 VGG-16 的层激活矩阵的特征表示,而是将那些特征表示转换成空间相关矩阵(在激活图内),这是通过计算 Gram 矩阵来完成的。gram 矩阵包含风格图像层上每对特征图之间的相关性。因此,本质上,Gram matrix 捕获了在图像的不同部分同时出现的特征的趋势。它表示一组向量的内点积,这捕获了两个向量之间的相似性,因为如果两个向量彼此相似,那么它们的点积将会很大,因此 Gram 矩阵也会很大。

来源

  • 在最初的论文中,Gatys 建议结合浅层和深层 conv 层来计算风格表现的风格损失。因此,风格损失是每个 conv 层激活矩阵的原始风格图像(Y)和生成的图像(Z)之间的风格特征的均方差(欧几里德距离)的总和。

  • 总体损失:总体损失是内容损失和风格损失的加权和,如下所示。

  • 网络被训练成同时最小化内容损失和风格损失。α和β分别是内容损失和风格损失的权重,也是整个 CNN 的超参数。这些值的选择完全取决于生成的图像(Z)中需要保留多少内容或样式。这里,我们从随机(白噪声)图像矩阵开始,并在每次迭代中计算内容图像(内容损失)和样式图像(样式损失)之间的特征映射距离(总体损失),以计算总体损失。因此,这种损失通过网络反向传播,我们需要通过适当的优化技术(相当于梯度下降)在迭代(几千次)中最小化总损失,以更新与内容和风格图像一样接近的随机图像矩阵。我们继续这个过程,直到我们得到最小的阈值损失值,以生成优化的混合图像(Z),它看起来类似于内容(X)和样式图像(Y)。

因此,根据上述典型的 NST 网络,在更深的层计算内容损失,以捕获高级特征(空间),而对于样式图像,则捕获详细的样式特征(纹理、颜色等)。)风格损失通过提取每个 conv 区块的浅层(conv-1)的网络输出(激活图)来计算。典型的预训练分类 CNN 如 VGG16 由几个 conv 块组成,其具有 2 或 3 个卷积(Conv2D)层(conv1、conv2 等。)接着是 pooling(最大/平均)层。所以风格图像网络是一个多输出模型。在下一节中,我们将简要讨论这个概念在实时视频数据上的实现。详细代码以及所有输入(内容视频和风格图像)和输出(生成的图像帧)可在这里找到。

实时视频上的神经类型转移;

我将解释图像的步骤,因为视频只不过是一组图像的集合。这些图像被称为帧,可以组合起来获得原始视频。因此,我们可以循环所有单个帧的步骤,重新组合并生成风格化的视频。

第一步:装载预先训练好的 VGG-16 CNN 模型

为 NST 应用从零开始构建(训练)CNN 需要大量时间和强大的计算基础设施,这对于个人来说是不容易获得的。

因此,我们将加载权重(从著名的' ImageNet 的图像中训练)挑战)一个预先训练好的 CNN- VGG-16 实现神经风格转移。我们将使用 Keras 应用程序为 VGG-16 加载预先训练好的重量。VGG-16 可能不是 NST 的最佳 CNN 架构。对于这种应用,有更复杂(具有高级架构的更深层次)的网络,如 InceptionV4、VGG-19、Resnet-101 等,这将花费更多的时间来加载和运行。然而,作为实验,我们选择了 VGG-16(具有高分类准确度和对特征的良好内在理解)。

*from keras.applications.vgg16 import VGG16
shape = (224,224)
vgg = VGG16(input_shape=shape,weights='imagenet',include_top=False)*

形状在这里很重要,因为 VGG-16 网络采用形状为 224 x 224 x 3 的输入图像。

*vgg.summary()
**_________________________________________________________________**
Layer (type)                 Output Shape              Param #   
=================================================================
input_21 (InputLayer)        (None, 224, 224, 3)       0         
**_________________________________________________________________**
block1_conv1 (Conv2D)        (None, 224, 224, 64)      1792      
**_________________________________________________________________**
block1_conv2 (Conv2D)        (None, 224, 224, 64)      36928     
**_________________________________________________________________**
average*_pooling2d_*101 (Avera (None, 112, 112, 64)      0         
**_________________________________________________________________**
block2_conv1 (Conv2D)        (None, 112, 112, 128)     73856     
**_________________________________________________________________**
block2_conv2 (Conv2D)        (None, 112, 112, 128)     147584    
**_________________________________________________________________**
average*_pooling2d_*102 (Avera (None, 56, 56, 128)       0         
**_________________________________________________________________**
block3_conv1 (Conv2D)        (None, 56, 56, 256)       295168    
**_________________________________________________________________**
block3_conv2 (Conv2D)        (None, 56, 56, 256)       590080    
**_________________________________________________________________**
block3_conv3 (Conv2D)        (None, 56, 56, 256)       590080    
**_________________________________________________________________**
average*_pooling2d_*103 (Avera (None, 28, 28, 256)       0         
**_________________________________________________________________**
block4_conv1 (Conv2D)        (None, 28, 28, 512)       1180160   
**_________________________________________________________________**
block4_conv2 (Conv2D)        (None, 28, 28, 512)       2359808   
**_________________________________________________________________**
block4_conv3 (Conv2D)        (None, 28, 28, 512)       2359808   
**_________________________________________________________________**
average*_pooling2d_*104 (Avera (None, 14, 14, 512)       0         
**_________________________________________________________________**
block5_conv1 (Conv2D)        (None, 14, 14, 512)       2359808   
**_________________________________________________________________**
block5_conv2 (Conv2D)        (None, 14, 14, 512)       2359808   
**_________________________________________________________________**
block5_conv3 (Conv2D)        (None, 14, 14, 512)       2359808   
**_________________________________________________________________**
average_pooling2d_105 (Avera (None, 7, 7, 512)         0         
=================================================================
Total params: 14,714,688
Trainable params: 14,714,688
Non-trainable params: 0*

VGG-16 建筑

第二步:定义内容模型和成本函数

对于高级内容特征,我们希望考虑整个图像的特征。所以我们将把 max-pool(可能会丢掉一些信息)换成 average pool。然后,我们将从总共 13 个卷积中选择任何更深的层作为“输出”,并定义该层的模型。然后,我们将在 n/w 中馈送我们的预处理内容图像(X ),以在输出层 wrt 计算(预测的)特征/激活图。该模型和模型输出 wrt 为定义形状(224 x 224 x 3)的任意随机(白噪声)矩阵。我们计算内容图像网络的 MSE 损失和梯度。这将有助于将输入图像(随机图像)更新到梯度的相反方向,并允许内容损失值降低,从而生成的图像将与输入图像的图像相匹配。详细的实现代码保存在我的 GitHub 库中。

*content_model = vgg_cutoff(shape, 13) *#Can be experimented with other deep layers*
*# make the target*
target = K.variable(content_model.predict(x))
*# try to match the input image*
*# define loss in keras*
loss = K.mean(K.square(target - content_model.output))
*# gradients which are needed by the optimizer*
grads = K.gradients(loss, content_model.input)*

第三步:定义风格模型和风格损失函数

两个图像的特征映射在给定层产生相同的 Gram 矩阵,我们期望两个图像具有相同的风格(但不一定是相同的内容)。因此,网络中早期层的激活图将捕获一些更精细的纹理(低级特征),而更深层的激活图将捕获图像风格的更多高级元素。因此,为了获得最佳结果,我们将浅层和深层的组合作为输出,以比较图像的样式表示,并相应地定义多输出模型。

这里,我们首先计算每一层的 Gram 矩阵,并计算风格网络的总风格损失。我们对不同的层采用不同的权重来计算加权损失。然后,基于样式损失(样式分量的差异)和梯度,我们更新输入图像(随机图像)并减少样式损失值,使得生成的图像(Z)纹理看起来类似于样式图像(Y)的纹理。

**#Define multi-output model*
symb_conv_outputs = [layer.get_output_at(1) for layer in vgg.layers\
if layer.name.endswith('conv1')]
multi_output_model = Model(vgg.input, symb_conv_outputs)
*#Style feature map(outputs) of style image*
symb_layer_out = [K.variable(y) for y in multi_output_model.predect(x)] *#Defining Style loss*
def gram_matrix(img):
    X = K.batch_flatten(K.permute_dimensions(img,(2,0,1)))
    gram_mat = K.dot(X,K.transpose(X))/img.get_shape().num_elements()
    return gram_mat def style_loss(y,t):
    return K.mean(K.square(gram_matrix(y)-gram_matrix(t))) *#Style loss calculation through out the network*
*#Defining layer weights for layers* 
weights = [0.2,0.4,0.3,0.5,0.2]
loss=0
for symb,actual,w in zip(symb_conv_outputs,symb_layer_out,weights):
    loss += w * style_loss(symb[0],actual[0])
grad = K.gradients(loss,multi_output_model.input)
get_loss_grad = K.Function(inputs=[multi_output_model.input], outputs=[loss] + grad)*

第四步:定义总成本(总损失):

现在我们可以结合内容和风格损失来获得网络的整体损失。我们需要使用合适的优化算法在迭代过程中最小化这个数量。

*#Content Loss
loss=K.mean(K.square(content_model.output-content_target)) * Wc #Wc is content loss weight(hyperparameter)#Defining layer weights of layers for style loss 
weights = [0.2,0.4,0.3,0.5,0.2]#Total loss and gradient
for symb,actual,w in zip(symb_conv_outputs,symb_layer_out,weights):
    loss += Ws * w * style_loss(symb[0],actual[0]) #Wc is content loss weight(hyperparameter)

grad = K.gradients(loss,vgg.input)
get_loss_grad = K.Function(inputs=[vgg.input], outputs=[loss] + grad)*

第五步:求解优化问题和损失最小化函数

在定义了整个符号计算之后,图的优化算法是主要的组成部分,它将能够迭代地最小化整个网络的成本。这里不用使用 keras 标准的优化器函数(如 optimizer。Adam、optimizers.sgd 等。),这可能需要更多时间,我们将使用有限内存 BFGS(Broyden–Fletcher–gold farb–Shanno),这是一种使用有限计算机内存的近似数值优化算法。由于它的线性内存需求,这种方法非常适合于涉及大量变量(参数)的优化问题。像正常的 BFGS 它是一个标准的拟牛顿法,通过最大化正则化对数似然优化平滑函数。

Scipy 的最小化函数(fmin_l_bfgs_b)允许我们传回函数值 f(x)及其梯度 f'(x),这是我们在前面的步骤中计算的。但是,我们需要以一维数组格式展开最小化函数的输入,并且损耗和梯度都必须是 np.float64。

**#Wrapper Function to feed loss and gradient with proper format to L-BFGS* 
def get_loss_grad_wrapper(x_vec):
        l,g = get_loss_grad([x_vec.reshape(*batch_shape)])
        return l.astype(np.float64), g.flatten().astype(np.float64)
*#Function to minimize loss and iteratively generate the image*
def min_loss(fn,epochs,batch_shape):
    t0 = datetime.now()
    losses = []
    x = np.random.randn(np.prod(batch_shape))
    for i in range(epochs):
        x, l, _ = scipy.optimize.fmin_l_bfgs_b(func=fn,x0=x,maxfun=20)
    *# bounds=[[-127, 127]]*len(x.flatten())*
    *#x = np.clip(x, -127, 127)*
    *# print("min:", x.min(), "max:", x.max())*
        print("iter=%s, loss=%s" % (i, l))
        losses.append(l)
    print("duration:", datetime.now() - t0)
    plt.plot(losses)
    plt.show()
    newimg = x.reshape(*batch_shape)
    final_img = unpreprocess(newimg)
    return final_img[0]*

步骤 6:对输入内容和样式图像运行优化器功能:

在输入内容帧和样式图像上运行优化器,并且按照定义的符号计算图,网络执行其预期的最小化总体损失的工作,并且生成看起来尽可能接近内容和样式图像的图像。

输出图像仍然有噪声,因为我们仅运行网络 30 次迭代。理想的 NST 网络应该经过数千次迭代优化,以达到最小损耗阈值,从而产生清晰的混合输出。

步骤 7:对所有图像帧重复上述步骤:

从短视频中提取帧后,对每一帧进行网络推理,为每一帧生成风格化图像,并对风格化图像帧进行重组/拼接。

**#Vedio Reading and extracting frames*cap = cv2.VideoCapture(path)
while(True):
    ret, frame = cap.read()
    frame = cv2.resize(frame,(224,224))
    X = preprocess_img(frame) *#Running the above optimization as per defined comutation graph and generate styled image frame#* 
    final_img = min_loss(fn=get_loss_grad_wrapper,epochs=30,batch_shape=batch_shape)    
    plt.imshow(scale(final_img))
    plt.show()
    cv2.imwrite(filename, final_img)*#Recombine styled image frames to form the video*
video = cv2.VideoWriter(video_name, 0, 1, (width,height))
for image in images:
    video.write(cv2.imread(os.path.join(image_folder, image)))
cv2.destroyAllWindows()
video.release()*

我们也可以使用设备相机胶卷来尝试视频,并尝试在线模式下的风格转换(实时视频),只需调整视频捕捉模式。

*cap = cv2.VideoCapture(0)
cap.release()*

商业应用

除了这种看似奇特的技术的个人和艺术用途,神经风格转移有可能改变人类创造力传统上占主导地位的任何行业,如美术、时装、建筑或新时尚汽车纹理设计等。以时装业为例,该行业需要对时尚的机制有深刻的理解:趋势的成因和传播,循环重复的原则和进化模式,以发展未来的时尚。

图片提供

然而,神经网络或 NST 可以通过自动为不同类型的服装分配形状、元素和创意纹理(风格)来帮助设计新的设计,并进一步将它们结合起来,以生产出未来的流行时尚。通过自动化 NST 的重要部分,有可能大大减少服装设计过程。为了进一步了解,我鼓励你阅读这篇文章。

进一步的改进和实验:

以下是一些提高生成图像质量的策略:

1)更多次迭代:显然,运行网络更多次迭代(大约 1000 次)将减少总体损失,并将创建更清晰的混合图像。

2)高级 CNN 架构:对于 NST 应用,通常具有非常高级连接的更深的神经网络可以更准确地捕捉高级(空间)和详细的纹理特征。因此,值得尝试其他优秀的预训练网络,如 InceptionV4、GoogLeNet、Resnet-101 等。然而,对于具有数千次迭代 NST 应用,这些网络的运行时间非常高,且需要昂贵的计算基础设施,如强大的 GPU 栈。

3)调整内容和风格损失权重:作为一项实验,我尝试分别使用 4 和 0.03 作为内容和风格损失权重,主要是为了尽可能多地捕捉内容(因为我只运行了几次网络迭代)。但是,这可能不合适,找到最佳权重的理想方法是通过网格搜索

4)针对样式损失调整层权重:为了最大化样式特征捕获,我们需要调整各个 conv 层中的权重以控制样式损失计算,从而优化纹理的提取(早期层的较精细纹理和较深层的较高级特征)。同样,这些是超参数,网格搜索是理想的选择。

此外,我们可以使用层(L)来提取内容特征。l 也是网络的超参数。

神经风格转移系列:第二部分

原文:https://towardsdatascience.com/neural-style-transfer-series-part-2-91baad306b24?source=collection_archive---------18-----------------------

神经类型转换的 TensorFlow 和 pyTorch 实现

他的文章来自我们在第一篇文章中讨论的内容。虽然我们谈到了直觉和神经类型转移如何工作的理论,但我们现在将继续实现最初的论文。如果这是你阅读这个系列的第一篇文章,我恳求你阅读下面给出的前一篇文章。我们已经深入解释了 neural style 是如何工作的,这篇文章主要是关于如何实现它。理解理论上的细微差别也有助于理解实现。

神经风格迁移教程—第一部分:神经风格迁移理论

在解释整个代码之前,我将先浏览一下实现它们的框架。然后进入实现阶段。

实现的代码可以在这里找到。[ Pytorch , Tensorflow

注意:你一定注意到了,不是将代码模块化成一组损失,网络创建和培训文件。我们刚刚创建了两个名为 train_Pytorch.py 和 train_TensorFlow.py 的文件,我们可能会在未来的代码中更改此工作流。

在我们深入研究代码实现之前,现在让我们试着对深度学习框架有一个整体的看法。由于我们将使用 Python,我将坚持使用 Pytorch 和 Tensorflow 等主流框架。这将是一个非常全面的库视图,我们可以写另一篇文章,专门讨论不同的可用框架及其优缺点。您可能想看看其他几个框架,包括但不限于 Dynet、Chainer 和 Julia language 最近发布的框架 flux。另一件要注意的事情是,尽管这些是用于构建模型的框架,但还有更高级别的抽象,如 fastai、spacy 和 keras。

A computational graph

Pytorch 是由脸书借鉴 Lua 中的 torch 并在 caffe2 上构建而成的,而 Tensorflow 是由 google 创建的。Tensorflow 仍然是大多数人当前选择的框架,但 Pytorch 正在迅速加快速度,据说在某些方面更好。Pytorch 和 Tensorflow 都创建了被称为计算图的东西,两者的主要区别在于它们如何创建这些计算图。Pytorch 创建动态图,Tensorflow 创建静态图。这意味着,在 Pytorch 中,您可以随时操作您的图形,而在 Tensorflow 中,您必须事先完全定义它。Tensorflow2.0 正在尝试将动态图以急切执行的形式融入到语言中。Pytorch 更 pythonic 化,因此学习起来更直观,而 Tensorflow 有许多好的特性,如 Tensorboard(模型的可视化平台),也更容易投入生产。

现在回到我们的文章,在这个代码解释中,我希望给出一些关于计算图的概述,并看到框架中的一些差异和相似之处。我想恳求你先理解代码,运行它,然后执行它,而不要看代码,如果有任何错误。我不会讨论为该程序编写的实用程序,因为它们只是数据加载函数,本质上大多是琐碎的。

首先要注意的是“内容层”和“风格层”,你可以用任何你想要的方式来尝试不同的表现。正如在原始文章中所解释的,这两个数组用于表示您将从中获取要素制图表达的图层。

在 pyTorch 中,创建网络的方法是重载 nn.Module。它通常有两个部分,首先是初始化所有层的 init 方法,然后是 forward 方法,forward 方法用于通过网络实际传递数据并获得输出。在这段代码中,我选择编写我自己的 VGG19 网络,但是也有一些方法可以导入内置的模型并加载权重。我选择以一种特殊的方式做的一些事情是保持平均池层,你也可以使用最大池层。

如果你想知道变换变量的用途是什么,它基本上是为了变换你的输入图像而存在的,无论原始分辨率是多少,都可以将其转换成可以馈入 VGG 网络的东西。我们对图像进行归一化处理,以便更详细地描述图像网络的含义。

在复制论文或制作模型时,框架内需要注意的一件事是,通常我们在 cpu 上有数据,但神经网络模型的效率训练是在 GPU 上进行的,因此正如你所见,我们使用了。cuda() 函数将我们的样式和内容图像等对象传输到 gpu 上。我们将预训练的 VGG 权重加载到模型上,这些预训练的权重来自在 Imagenet 上训练的 VGG。保存的重量文件的扩展名为。pth 需要注意的一件事是,当你编写你的网络并保存权重并尝试在我的网络上运行时,它可能不会工作虽然我们都在训练 vgg 网络,但不同的层名称等细节可能会或选择 max 而不是 average pooling 等层可能会在加载权重时引发错误。

谈到损失函数,首先我们有 gram 矩阵类。如前一篇文章所述,我们使用 Gram 矩阵提取特征层,即。bmm() 代表批量矩阵乘法。在批量矩阵乘法中,最后 2 个维度用于矩阵乘法,而其余维度被视为批量。我在变量后面的注释中写了一个例子来给出矩阵维数的概念。样式损失的计算方法是,首先传递图层以获取其 gram 矩阵表示,然后获取表示和目标之间的均方误差。一步一步地检查其余部分,我们从 VGG 网络中分离层,并将它们添加到各自的目标层。然后,我们开始定义损失、目标和损失层。最后,我们有风格权重和内容权重,你可以用任何你想要的方式进行实验,该文件建议 1000 和 5 是一个很好的开始方式,你的内容权重越高,你就越保留你的原始图像,你的风格权重越高,你会发现风格变得越来越突出,而内容退居其次。

最后是训练循环,训练循环是各种深度学习模型建立的关键部分。为了勾勒出一个通用的框架,我们在任何训练循环中做三件事,我们决定优化器,计算损失,然后反向推进。在上面的例子中,我们使用了 LBFGS 优化器。我们可以看到我们称之为。zero_grad() 函数这是因为,pytorch 默认情况下会累积梯度,所以我们需要每次在计算梯度之前将梯度设置为零。然后通过遍历所有的样式和内容层来累积总损失,之后是。backward() 函数用于计算梯度和。步骤()用于更新权重。我们将损失函数传递给步骤()的原因是,在 LBFGS 的情况下,需要多次计算损失。

现在,我将尝试指出主要的区别,而不是完整地浏览 Tensorflow 代码,因为代码的其余部分与 pyTorch 非常相似。其中一个基本区别是在 run_style_transfer() 中,我们可以观察到一个会话变量正在被创建,这就引出了一个事实,即由于 tensorflow 创建静态图,我们需要首先定义一个会话,然后在这个会话中训练模型。Adam 优化器用于训练模型,而不是 LBGFS。在训练循环中,会话是通过将优化器传递给相同的。并且只有在当前损失好于(即小于)先前损失的情况下,才更新损失。预加载重量的 VGG 模型是从 keras 导入的,而不是从头开始编写的。训练模型时,可能需要一段时间,因为如果本地没有权重,tensorflow 将下载权重。

好了,你已经成功地看到了神经类型转换的代码。接下来要做的是,运行代码并亲自查看输出。我们将继续快速神经风格转移系列,简单介绍一下,当你训练网络时,你可能会观察到,对于每种风格,你都需要重复训练整个网络。解决这个问题的一个更好的方法可能是学习样式权重,保存它们,然后随时加载您想要的任何内容图像。这可能听起来令人困惑,所以期待深入的文章。

非常感谢等待这篇文章。

感谢瓦姆西克·谢蒂与我共同创作了这个系列。

您可以在这个资源库中找到代码,在这里我们也将有本系列未来文章的代码。

神经象征 VQN——非纠缠的推理——或者——答案是:非纠缠

原文:https://towardsdatascience.com/neural-symbolic-vqn-disentagled-reasoning-or-the-answer-disentanglement-49f0fa0eb9c7?source=collection_archive---------12-----------------------

一个可解释的深度学习系统的解释。

Kreg Steppe [CC BY-SA 2.0 (https://creativecommons.org/licenses/by-sa/2.0)]

几乎每一项技术进步都始于科幻小说中的一个例子。因此,在我解释这些科学家的研究成果之前,我想让你们看一下经典电视剧《星际迷航——下一代,身份危机》中的一集。
播放时间索引 25:53 到时间索引 31:47 的嵌入视频,猜猜论文讲的是什么…
(当然你也可以看完整集;我会等你;)
(对于那些被 daily motion-video-player 弄糊涂的人:点击开始,然后【视频上的任何地方】点击并向右/向左拖动以调整时间索引。—知道这一点会节省我宝贵的两分钟……)

Star Trek TNG S04E18 Identity Crisis; ~ Stardate 40164.7

我希望你喜欢它;但是让我们来揭开我想要达到的目标的神秘面纱:

这一集提到的部分展示了计算机的视觉分析能力,以及如何使用这种能力:
当 Geordi La Forge 在视频中检测到阴影时,他想知道它的来源。计算机自然不知道他说的是什么影子,于是 Geordi 让计算机合成了一个全息程序,用于进一步分析。
在这个节目中,Geordi 告诉计算机从场景中移除一些物体,然后问了一个至关重要的问题:
“计算机,使用矢量分析,识别这个阴影的来源”受访者回答“程序中没有可以产生阴影的物体”

这是一个真正了不起的例子,计算机根据某个场景响应查询。
由于我们生活在一个数据时代,已经有至少一个数据集适合训练算法来执行这样的任务:CLEVR(组合语言和初级视觉推理)数据集。

数据集由场景图像、针对该场景的问题以及用于寻找每个问题答案的功能程序组成。
下面是一个例子:

对左边图片的一个问题可以是:
大金属立方体左边的大圆柱体是什么颜色?

答案当然是:红色。

该程序可以这样工作:

Filter the scene by metallic cubes -> 
filter by size -> 
take one of them if one exists -> 
filter the scene by objects left to its position -> 
filter by size -> 
filter by cylinders -> 
take one of them if one exists -> 
output its color

正如 DeepMind 的论文所指出的,已经有几种方法可以解决这个有趣的问题,但是,其中大多数都是端到端的方法,并且/或者它们的性能不如它们在企业的计算机核心中实现时应该表现的那样好。

因此,这里有一个解释,如何被称为神经符号 VQN 的新框架在这个数据集上达到 99.8%的准确率:

DeepMinds 系统由三个子系统精心组成:

  • 场景解析器或去渲染引擎
  • 问题解析器/程序生成器
  • 程序执行环境

screenshot of the mechanics of NS-VQN; source: DeepMind paper

让我们逐一查看不同的组件,然后讨论它们的总体方法。

场景解析器本身由两个子系统组成(如上图所示)。第一部分检测场景中的对象。它在带标签的数据集上进行了预训练。“Mask R-CNN”获得图像的压缩版本,并被训练为用可见的框/覆盖物覆盖场景中的对象。

现在“标记的”(和压缩的)图像与原始(未压缩的)图像一起被送入 CNN,以提取物体的相应坐标。

第二步生成原始图像的表示,可以对其进行查询。然而,要真正查询它,我们需要一个程序。

这个(纯函数式)程序[ 这篇文章解释了函数式编程的基础知识 ]是通过将问题输入双向 LSTM 编码器生成的。编码器输出被输入到 LSTM 解码器列表中。每个解码器的输出是一个函数。将这些函数与我们图像的表格表示一起使用,会产生(潜在的)正确结果。

好吧,最后一部分一开始可能不容易理解;让我再试一次:
你可以把 LSTM-编码器-解码器模式想象成类似于笔记本中的交叉引用系统。编码器为输入的问题生成一个抽象的表示,解码器提取这个“参考”并吐出它指向的东西;在这种情况下是一个函数。
系统作为一个整体被训练(如黑框所示),因此编码器学习将查询翻译成抽象序列,每个解码器解释其部分(最终程序序列)以输出属于最终半功能程序的正确功能。[半功能性,因为它被解释为命令性的;然而,人们可以把 executor 看作是一个 monad 实现,支持函数式程序的命令式符号。

在程序生成之后,我们将程序以及表格图像表示交给程序执行者。
(这部分相当简单,因为它只是用正确的数据执行函数,这意味着将一个函数的输出作为参数传递给下一个函数,直到程序终止。)

如果您想了解性能和结果的详细信息,请查看论文中的其他图表。(他们的描述相当直接。)

上面描述的架构有很多有趣的特性。我们已经讨论了它的编译部分,但是对设计来说还有更有趣的东西:可解释性。

设计的深度学习算法无法解释它是如何得出特定结果的。这个解释隐藏在一层层相连的神经元中,对于人类用户来说是不可读的,也是不可理解的。由于上述架构使用了多种深度学习算法,我们可以假设它是通过设计一个黑盒来实现的。然而,我们大错特错了。

研究人员使用深度学习黑盒来生成输入数据的表示(例如,视觉标记图片中的对象,编辑带有图片中位置的对象列表,…)。所有这些表示都是人类可读的,因此是可以解释的。
用户可以(从算法中得到结果后)看一看程序和生成的表格,推断程序可能在哪里出错;或者(更重要的是)为什么输出是“小”而不是“大”,因为网络将一个立方体误认为一个球体(这可以在查看标记的图片、表格和输入图片时看到)。

我们可以把这种方法称为面向表示的学习:不是制作一个只使用一个巨大的主函数(比如一个巨大的神经网络)的程序,而是制作一个被很好地划分成更小部分的程序,可以更容易地解释和修复。

设计面向表征的学习系统的主要好处可能一开始并不太明显,但请保持关注:
可能永远不会有一个系统可以解决所有问题(除了,显然是巨型计算机“地球”,生命本身是其中的一部分,由 Magrathea 上的 Deep Thought 设计)。然而,已经有很多好的机器学习架构来解决特定的问题(例如,自然语言处理、图像识别、匹配音乐等)。).
使用面向表示的学习方法使我们能够将这些解决方案连接在一起,不是一个单一的系统,而是一个可以解释(不一定用自然语言)为什么以及如何得到答案(当然是 42)的系统。

另一个好处是子系统可以彼此独立地训练。如果系统作为一个整体缺乏一些性能,我们可以看到,例如,程序生成器需要更多的调整,我们不必再次训练整个系统。我们可以训练或替换程序生成器。

总之,DeepMind 提出的架构(当然还有 DeepThought[1]提出的架构)是可执行的、可解释的和高度模块化的。它也是独立于领域/技术的(这意味着我们可以想象这个系统也适用于声音,并与一些随机森林相结合)。

现在你也知道题目中问题的答案了。(对于现在迷茫的大家,管好自己的毛巾,是“可解释深度学习的关键是什么?”。)

[1]:deep thinks 提出的架构(地球)当然也主要是可解释的(你可以自己构建推理链)和模块化的(你是可替换的),然而,由于我们的祖先长期以来一直决定在树上跳来跳去,所以性能不是很好。)

NeurIPS 2019

原文:https://towardsdatascience.com/neurips-2019-225fd7636ce5?source=collection_archive---------19-----------------------

Vancouver Skyline

势不可挡。

是的,我再说一遍。势不可挡。如果我要用一个词来总结我在 2019 年第 33 届年度神经信息处理系统大会上的经历,“压倒性”几乎可以概括大部分。

接受 6743 篇提交的论文中的 1428 篇可能会让神经信息处理系统会议应接不暇。但在温哥华会议中心,13000 名人工智能研究人员的出席令人麻木。

Vancouver Convention Center

我要感谢亚马逊给我这个机会来参加会议,尽管只是作为一个与会者。尽管如此,这是一个很好的机会,让世界上最优秀和最伟大的研究人员聚集在一个巨大的建筑下。如果我不感谢组织者和主持人所做的大量工作,我肯定是失职的。在 7 天的时间里,我学到了很多东西,以下是我个人的亮点。

呼唤:再现性、公平性(伦理人工智能)和可解释性(可解释的人工智能)。

可解释性

AllenNLP 解读 :基于 Allen NLP 之上的工具包。这是一个解释 NLP 模型预测的框架。到目前为止,本演示已经涵盖了 16 种不同的自然语言任务。这是一个介于可解释性和 NLP 之间的有趣的工作。我特别喜欢这两种可视化方式&解释:使用显著图的简单梯度和基于热翻转的对抗性攻击。

这个看起来是这样的:可解释图像识别的深度学习 :本文介绍了一种新的架构 ProtoPNet,它有一个原型层。它充当可解释层,同时仍然实现与 SOTA 深度学习模型相当的性能结果。[ 论文 ] [ 3min 视频 ] [ 幻灯片

再现性

如果这项研究不可重复,那它还有什么意义呢?是的,我们经常听到人们谈论这一点。显而易见,研究团体和 NeurIPS 对这些主张做出了回应。可再生性正受到重视,至少已经开始受到重视。NeurIPS 首次组织了再现性挑战,鼓励机构通过 OpenReview 使用被认可的论文。浏览“再现性清单”很有意思。

公平

众所周知,ML 模型是不公平的(到目前为止)。可能会有种族偏见、性别偏见和其他此类偏见渗透到模型中,导致灾难性的后果

首先,你会惊讶地发现:

  • 面部分析 AI 对深色皮肤表现较差
  • 白人男性给出最低的错误匹配率(FMR ),而黑人女性给出最高的 FMR

NeurIPS 2019 见证了该领域的大量研究。几个有趣的例子:

  • 不要问 AI 能做什么,要问 AI 应该做什么:走向一个任务可委派性的框架[delegability . github . io][论文 ] [ 海报 ] [ 3 分钟视频 ]
  • 公平近邻[ 论文][幻灯片]
  • 医疗保健公平 ML[已接受论文

特邀演讲人

Celeste Kidd,谈到 开幕当天如何认识 。它受到了观众的热烈欢迎。在强调#metoo 运动后的性骚扰问题时,她的主题演讲引起了与会者的共鸣。

Yoshua Bengio ,做了题为 从系统 1 深度学习到系统 2 深度学习 的远见演讲。虽然很高兴看到 ML 和 DL 快速发展,但强调它的缺陷、缺点以及未来需要的改进和适应也很重要。

很酷的演示

这张纸怎么进得去?“——为顶级 AI 会议写作时给研究人员提建议的游戏。该项目的目的是建立一个自然语言分类+可解释的人工智能工具,用于分析论文并提出修改建议,以使其被顶级会议接受。出于演示的目的,他们将论文标题而不是整篇论文作为输入。

将 AI 引入命令行 [ 演示——这是我在 NeurIPS 2019 上发现的最酷的演示和想法之一。这可能会让软件开发人员、工程师和一般的计算机科学人员彻夜难眠。但是,CLAI(命令行人工智能)仍然是一个强大的想法。这个由 IBM Research AI 开发的工具利用了 NLP 和强化学习。自然语言支持、现场支持&故障排除、智能自动化是该工具的强大功能。看看它如何演变会很有趣。

来自松下测试研究实验室的人们展示了智能家电:与你的冰箱聊天。用户可以通过 Facebook Messenger 界面询问冰箱内的内容、物品数量、物品新鲜度等问题。尽管只是一个演示,我还是期待真实世界的数据和更丰富的体验。但是 DNN 模型是在一组特定的图像上训练的,并且数据集是限制性的。尽管如此,这是一个展示 CV+NLP 强大功能的好主意,有很大的潜力和适用性。

与人工智能化身进行一对一的健身训练:数字健身教练米莉(Millie)实时互动,观察用户的动作,并对其速度、准确性和形式进行评分。

机器人辅助梳头 :南加州大学的研究人员开发了一种机器人,它使用摄像头来绘制人的头部和头发的 3D 地图。它可以被想象成一个点云。它随后创建计划好的路径并执行它们。[ 演示

学习机可以卷曲——自适应深度强化学习使机器人 Curly 能够在冰冷的世界中战胜人类玩家。由来自韩国大学和柏林理工学院的团队设计的名为卷毛的机器人。深度学习不仅在围棋、国际象棋等游戏中击败冠军,现在它还进军奥运项目。体育界暂停了一场革命。

车间

星期五和星期六是一个高度平行的问题。不幸的是,我的单线程引擎被证明是一个瓶颈。尽管如此,我还是鼓励每个人尝试用 ML 应对气候变化。12 个小时的工作坊,但有很多有趣的事情发生。季节性、雪崩和电动汽车(EV)的研究可以说“只是冰山一角”。

获奖论文

最佳论文奖

具有 Massart 噪声的半空间的分布无关 PAC 学习

荣誉奖:

  1. 非参数密度估计&在 Besov IPM 损失下 GANs 的收敛速度
  2. 快速准确的最小均方解算器

杰出的新方向文件

一致收敛可能无法解释深度学习中的泛化

荣誉奖:

  1. 端到端的终结:表征的梯度隔离学习
  2. 场景表示网络:连续 3D 结构感知神经场景表示

时间考验奖

正则化随机学习和在线优化的双重平均方法

为了理解获奖论文,我发现这篇文章很有帮助。

总而言之,这是在温哥华度过的精彩刺激的 7 天。没有进入炒作周期,我真的觉得,这只是旅程的开始。还有很多有待研究、发明和应用到工业中。活着是多么令人兴奋的时刻啊!

NeurIPS 2019。第一天

原文:https://towardsdatascience.com/neurips-2019-day-1-60393c6bc30d?source=collection_archive---------35-----------------------

辅导日

NeurIPS 被证明是机器学习社区中最重要的会议。今年是在美丽的加拿大城市温哥华,有超过 10,000 人参加。共提交了 6734 篇论文,其中 1428 篇被接受。你可以看到,人们不仅很容易被参加的人数淹没,也很容易被信息流淹没。

关于会议其他日期的信息可以在这里找到:

  • 第二天
  • 第三天
  • 第四天
  • 第五天
  • 第六天

第一天(星期一)是辅导课。有三个辅导轨道,每个辅导会议持续约两个小时。我决定参加三个教程:贝叶斯原则的深度学习,分布和模型的可解释比较以及综合控制。

第一个教程的幻灯片可以在这里找到。我注意到了两件事。首先,作者的注意力放在了优化算法上,而不是在神经网络上进行全面的贝叶斯推理(我们知道这是难以处理的)。事实上,他表明,许多优化算法可以从贝叶斯原理中推导出来。例如,梯度下降可以从具有同位素协方差的高斯模型中导出。RMSProp 对应于具有对角协方差矩阵的多元高斯。其他优化算法,如亚当,也可以追溯到贝叶斯原则。事实上,按照这种方法,可以推导出其他优化算法,如演示中所示。这些优化为某些任务提供了更好的结果。

作者提出的第二个有趣的观点是,使用贝叶斯原理,我们不仅可以探索参数空间,还可以通过分配每个例子的重要性来探索输入空间。每个例子的重要性不同的想法是非常古老的,并且是支持向量机(SVM)算法的基础。事实上,在建立决策边界时,边界示例比远离决策边界的示例更重要。有可能使用贝叶斯学习重新提出这个问题,其中在每一步都选择重要的例子。这类似于贝叶斯优化算法,但远远超出了简单的高斯过程假设。事实上,根据作者的说法,在每个学习步骤中选择最重要的例子是人类如何学习的。

让我跳到 Celeste Kidd 的第一天主题演讲,准确地说是关于人们如何学习的。她是加州大学伯克利分校基德实验室的创始人,在那里她研究婴儿的认知过程。他们的学习方式实际上是积极的,选择有助于他们形成更复杂信念的活动。该实验室使用眼球追踪和其他线索来判断婴儿的注意力。婴儿很少注意可预测的观察,因为他们从中学不到什么。他们也不太注意非常新奇的观察,从这些观察中他们不能学到很多东西。中间有一个最大化学习的金发区。同样,当面对歧义时,他们会采取行动解决或消除歧义。

回到教程,第二个是由三人小组提出的,范围很窄:发行版之间的比较。我没有找到这个的幻灯片,但是你可以稍后查看教程的第页。它对散度的类型进行了非常深入的理论回顾:积分概率度量是基于分布之间的差异,φ-散度是基于分布的比率。第一类的例子是 MMD 和瓦瑟斯坦距离。后者的一个例子是 KL-divergence。让我惊讶的是内核又回来了!在第一个教程中也使用了内核。在这里,它们被用来模拟 MMD 和同一家族的其他分歧。碰巧的是,内核的选择在这里非常重要,并且在社区中有许多想法,它们中的哪一个对于特定的任务工作得更好。显然,分布之间的差异必须根据数据样本进行估计,这就把我们带回了统计假设检验。这里的零假设是两个分布相同,但是 MMD 分布本身非常复杂,所以假设检验非常困难,社区里有很多想法如何克服困难。也可以使用相同的方法进行拟合优度测试,在这种情况下,可以使用 Stein 算子和核 Stein 差异来更容易地进行测试。

第三个教程也是由阿尔贝托·阿巴迪(Alberto Abadie)等三人组领导的,他开创了这个方法。幻灯片可以在这里找到。合成对照的主题非常重要,因为随机对照研究并不总是可行的。这是一个反现实的技术,只有一个问题:如果不进行干预会发生什么?例子,如果没有英国退出欧盟,英国经济将如何发展。这些方法出奇的简单,而且不需要微积分,因为它们是基于时间序列预测技术。这些模型的一些稳定性问题可以通过仔细选择未处理的例子和加强模型参数的稀疏特性来解决。

最后,在晚上举行了第一次海报发布会,不幸的是,它与招待会同时举行。组织者注意:这不是一个好主意。这里有一些引起我注意的海报。

我将在会议的剩余时间里发布更多信息——敬请关注!

NeurIPS 2019 论文浏览器—带 Streamlit

原文:https://towardsdatascience.com/neurips-2019-exploration-app-with-streamlit-923efdd8ce01?source=collection_archive---------25-----------------------

screenshot of the app

NeurIPS 2019 explorer 帮助您找到需要阅读的论文。

https://neurips2019exploration.herokuapp.com

NeurIPS 2019 探索者应用

[## 细流

NeurIPS 2019 探索 App

neurips2019exploration.herokuapp.com](https://neurips2019exploration.herokuapp.com/)

(点击上面的应用程序)

自从我知道了 streamlit,我总是想尝试用它来构建一些东西。所以我最终建立了一个小应用程序来探索 NeurIPS 2019 的论文,今年接受的论文数量惊人——1428 篇论文。

你可以在这里找到代码:【https://github.com/noklam/NeurIPS2019Exploration】T2

介绍

应用程序的创建并不复杂,我花了大部分时间解析数据(特别是在应用程序的创建过程中,他们更新了网站,所以我不得不重新编写一些脚本来解析数据。🙄).另一大部分时间花在了弄清 streamlit 的动态并使其工作上。

Streamlit 太棒了,它不需要太多思考就能完成大部分工作。但是他们也得到改进的空间,比如表格和文字的渲染不一致。它们有多种显示文本的方式,如果你把它们混合在一起,最终会有一些不太好的格式,你也没有一个简单的方法来配置。

另一个缺陷是您没有选项来配置 dataframe 的列宽,所以我最终不得不使用静态表(看起来有点奇怪)而不是动态表(这会截断文本并导致笨拙的水平滚动)。

最后,它仍然是一个伟大的图书馆,我相信他们会很快改进。建造这个很有趣。如果你发现了错误或者有什么建议,请告诉我。

附:当我建立这个应用程序时,他们不断地改变他们的网站,所以它只包括海报,但不包括教程和研讨会,我会很快将它们添加回来。

资源:

[## NeurIPS 2019 日期和细节已公布

NeurIPS(神经信息处理系统会议)的组织者今天宣布了日期和其他…

medium.com](https://medium.com/syncedreview/neurips-2019-dates-and-details-announced-a4958d938769)

https://towards data science . com/how-to-build-your-machine-learning-app-in-3-simple-steps-d56ed 910355 c

神经形态硬件:试图将大脑植入芯片

原文:https://towardsdatascience.com/neuromorphic-hardware-trying-to-put-brain-into-chips-222132f7e4de?source=collection_archive---------9-----------------------

到目前为止,芯片制造商一直依靠著名的摩尔定律来生产下一代计算能力更强、功耗更低的芯片。现在,这些进步正慢慢停止。世界各地的研究人员正在提出替代架构,以继续生产更快、更节能的系统。本文讨论了这些备选方案,以及为什么其中一个方案在避免芯片设计行业陷入困境方面可能比其他方案更有优势。

什么是摩尔定律及其黄昏

摩尔定律,或者换句话说,全球芯片制造商的救星,是由英特尔公司的创始人戈登·摩尔博士在 1965 年提出的。法律规定芯片上的晶体管数量每两年翻一番。但是为什么是芯片制造商的救世主呢?前英特尔工程师 Robert P. Colwell 说,这个定律在半导体繁荣时期非常强大,以至于“人们会自动购买下一个最新最棒的计算机芯片,并完全相信它会比他们现有的更好。过去,写一个性能很差的程序不是问题,因为程序员知道摩尔定律最终会拯救他。

我们今天面临的问题是,法律几乎已经死亡!或者是为了避免冒犯摩尔的粉丝——正如博通首席技术官亨利·萨缪尔里所说——

它在变老,在老化,它没有死,但你必须为美国退休人员协会签署摩尔定律。"

随着我们接近原子尺度,芯片制造商要进一步缩小晶体管的尺寸变得越来越困难。该行业已经开始感受到压力。英特尔在 2015 年宣布,其新一代芯片将每 2.5 年发布一次。这也表明晶体管可能只在未来 5 年内继续缩小。

Source: Finding a roadmap to achieve large neuromorphic hardware systems. Over the last several years, the computational efficiency has not scaled along the lines expected by traditional Moore’s law type scaling. A closer look suggests an asymptote is being reached in MAC computational efficiency using classical digital techniques.

那么,是什么导致这项长期存在的法律失效呢?是量子力学,傻!让我们更深入地了解处理器的工作原理。我们都知道处理器只理解机器代码。因此,无论它存储或处理的是 1 和 0 的形式。这些 1 或 0 的状态由逻辑门保存,而逻辑门又由晶体管组成。晶体管的工作是调节电子的流动(通过建立一个势垒),从而在逻辑门中保持一个特定的状态。现在,当我们降低到 1 纳米= 10 个原子的尺度时,就很难调节电子流了。即使存在势垒,由于一种叫做量子隧道的现象,电子流仍会继续。因此,漏电流显著增加,导致架构效率低下。

替代途径

IBM’s carbon nanotubes could serve as a replacement to silicon. Source: IBM Research

研究人员和公司正试图提出替代方案,以避免在计算机架构领域陷入谷底。英特尔制造集团的前负责人暗示,该公司将采用新材料并改变晶体管的结构,以增加对电流的控制。随着深度学习的进展和新的复杂算法的开发,对能够高效执行繁重矩阵计算的芯片的需求越来越多。

全球研究人员正在探索以下新领域:

  • 量子计算:它利用了一个亚原子粒子在任何给定时间以多于一种状态存在的能力。不像传统的比特可以存储 0 或 1,量子比特 可以存储更多的信息。这意味着量子计算机可以用更少的能量存储比传统计算机多得多的信息。
  • 碳纳米管:这是卷成圆柱形的微小碳片,IBM 正在积极探索。在《科学》杂志上发表的一篇论文中,他们描述了一种使用碳纳米管制造晶体管的新方法,这种晶体管可能比我们今天使用的硅晶体管小得多。
  • 并行架构:这种方法在过去的十年中被广泛用于规避性能障碍。正在开发高度并行的架构(GPU)来执行同时操作。与冯·诺依曼 架构在单核上串行执行指令不同, GPU 拥有在多核上运行的并发线程,从而大大加快了处理速度。焦点也转向高能效的 FPGA,以取代 GPU。
  • 神经形态硬件:它包括任何模拟我们神经系统自然生物结构的电子设备。目标是通过在硅中实现神经元来赋予机器认知能力。由于其更好的能效和并行性,它被认为是传统架构和高能耗 GPU 的替代方案。

在上述领域中,量子计算和碳纳米管仍处于初级发展阶段。它们仍然不能完全替代硅,更不用说它们的商业生产了。GPU 已经使用了很长时间,但它们消耗大量的能量。神经形态硬件也相对处于发展的中间阶段,但为即将到来的性能危机提供了一个非常可能的解决方案。

神经形态硬件

人类大脑是地球上现存的能量效率最高、延迟最低的系统。它处理复杂信息的速度比任何计算机都快,处理方式也比任何计算机都好。这很大程度上是由于它的结构由密集的神经元组成,通过它们的突触有效地传输信号。神经形态工程的目标是在硅片上实现这种架构和性能。该术语是由卡弗·米德在 20 世纪 80 年代末创造的,描述了包含模拟/数字电路的系统,以模拟神经系统中存在的神经生物元素。许多研究机构一直在投资开发能做同样事情的芯片。

DARPA’s Systems of Neuromorphic Adaptive Plastic Scalable Electronics (SyNAPSE) board rocking 16 TrueNorth chips. Each chip has one million silicon “neurons” and 256 million silicon synapses between neurons. Source: IBM Corp

IBM 的神经形态芯片— TrueNorth 有 4096 个核心,每个核心有 256 个神经元,每个神经元有 256 个突触与其他神经元进行通信。这种结构非常接近大脑,在能量上非常有效。同样,英特尔的Loihi 拥有 128 个内核,每个内核有 1024 个神经元。曼彻斯特大学的 APT 小组最近披露了世界上最快的超级计算机— SpiNNaker 仅由神经形态核心组成。 Brainchip 是另一家为数据中心、网络安全和金融技术开发类似芯片的公司。人类大脑项目是一项由 EU-资助的大型项目,旨在研究如何构建模仿大脑工作方式的新算法和计算机

所有这些系统都有一个共同点——都非常节能。

TrueNorth 的功率密度是传统冯诺依曼处理器的万分之一。

这种巨大的差异是因为片上处理的异步本质,就像人脑一样。不需要在每个时间步更新每个神经元。只有在行动中的人才需要力量。这被称为事件驱动处理,是使神经形态系统作为传统架构的合适替代方案变得可行的最重要的方面。

脉冲神经网络

神经形态芯片上由突触互连的密集**神经元网络被称为脉冲神经网络。神经元通过突触传递脉冲来相互交流。上述芯片在硬件中实现了这个网络,但也非常强调在软件中模拟它,以评估性能或解决模式识别和深度学习的其他应用的问题。****

A full mesh Spiking Neural Network with input and output spike trains. The weights are updated using STDP rule.

脉冲神经网络以脉冲序列的形式在时域中对信息进行编码,即两个连续脉冲之间的时间差决定了网络的特性。网络最基本的元素——神经元——的功能由一个微分方程控制。神经元的输入是时域中离散尖峰的形式,而不是连续值。由于 SNN 的这些特性,用于训练它的方法也不同于现有的人工神经网络。代替梯度下降,一个更符合生物学原理的赫比学习被使用。它也被称为尖峰时间依赖可塑性(STDP)

Hebbian Learning in action in biological neurons. Neurons communicate by transmitting impulses over a network of synapses. Source: Unknown

这一切起初看起来似乎很深奥,需要时间来掌握 SNN 的网络动态。由于这个领域仍处于初级阶段,可用的文档也不全面。

这一系列博客旨在从零开始发展对 SNN 的理解,深入解释网络的每个元素,并用 Python 实现。还将讨论 Python 中用于 SNN 的现有库。

跟随计算神经科学在这个有趣的领域获得更多见解。此外,作为我的客人,为这一出版物作出贡献。欢迎合作。

中子:一个 4000 美元的 RTX 2080Ti (MSI)深度学习盒(8700k/64GB/2080Ti)

原文:https://towardsdatascience.com/neutron-a-4000-rtx-2080ti-msi-deep-learning-box-8700k-64gb-2080ti-82db257f0247?source=collection_archive---------13-----------------------

获得我们的第一个深度学习构建的第 1 部分(共 2 部分)

免责声明:虽然我选择了来自不同制造商的组件,但没有一个是受赞助的。

还要注意价格是基于印度的。根据您所在的国家,这里的组件可能会相对昂贵得多。

但是如果微星-你在读这个。我有更多的插槽来填充更多的 RTX 卡;)

自从几个月前我和 Rishi Bhalodia 共同创立的小公司 Neuroascent 成立以来,我们已经到了一个阶段,现在我们准备投资一个“深度学习平台”。

我们是 fast.ai 的研究员和粉丝,杰瑞米·霍华德建议在进行 MOOC 的第二部分时建立一个“深度学习盒子”。

我们已经决定将我们的时间完全奉献给 fastai ,然后转向其他途径。

在这次完成第 1 部分(v3,2019 版)后,在了解并分享了如何不做 fast.ai 后,这是我们为 fast.ai 第 2 部分做准备的努力,同时在 Kaggle 上进行更多练习。

这篇博客文章介绍了我们对电脑组件所做的选择,为什么我们选择让第三方零售商来组装它: Ant-PC 而不是自己组装,以及一些建议,告诉你在哪些地方可以节省一些钱或获得更好的性价比。

为什么是深度学习盒子?

在投资“DL Box”之前,我已经使用了 AWS 一段时间,这实际上是我的第二次投资,第一次是“游戏笔记本电脑”-基于 1070。

为什么拥有一个 DL 盒子是个好主意?

  • AWS 长期账单> > DL 设备的成本。
  • 除此之外,您还可以安心地不必确保您的“实例已关闭”。
  • 与“标准 AWS 实例”相比,您可以争取更快的构建(基于 2080Ti 的构建)

此外,我的理由与他在此提到的弗朗西斯科·英厄姆有很大的共鸣

粘贴用于阅读的副本:

原因:

游戏中的皮肤
在你的新建筑上投资一大笔钱向你自己证明你对 DL 的东西是认真的。

动机
完成构建,伴随着选择部件、采购部件和让一切顺利工作(包括硬件和软件)的麻烦,是非常令人满意的。

灵活性
事实上,您自己从头开始制定了这个计划,这意味着您知道您采取的每一个步骤,并且可以在必要时轻松地进行更改(例如,将计算机部件换成新的或者修改您的开发设置)。

工作轻松
如果你买得起好的硬件,一切都比依赖外部计算容易。运行笔记本电脑流畅而快速,没有延迟。这极大地方便了实验。

好吧,但是为什么要组装呢?

鉴于我们对硬件缺乏经验,又害怕弄坏任何东西,我们决定多花一点钱把它组装起来。

事实证明,印度的一家网上商店并没有为此向我们开出高额账单。

几个优点:

  • Ant-PC 的人已经向我承诺,在将 PC 发送给我之前,我会进行两天的压力测试,这意味着我不会收到任何有问题的组件。
  • 他们提供 1 年的现场保修:而不仅仅是个别部件的保修,我将得到一年的“中子”保修-这是一个加号。
  • 此外, Ant-PC 的人是印度少数几个与“DL 版本”合作过的零售商之一,所以他们在决定我们的组件时帮了大忙。
  • 最后,他们给了我免费的 RGB 灯(重要的细节)

成分

背景故事讲完了,让我们开始吧。

免责声明:我既不是硬件专家,也不强烈推荐我的选择。一定要做好调查。我的想法很大程度上来源于 Kaggle Noobs 社区和 fast.ai 论坛,那里有更多经验的人对我有很大帮助。

影响我观点的来源:

  • 从 fast.ai 构建自己的深度学习盒子线程
  • Kaggle Noobs 中的硬件通道

我尝试处理的几件事:

  • 升级空间
  • 争取最好的 GPU(根据预算)
  • 获得一个多汁的 NVMe M.2 驱动器(建议从杰里米在 fastai 论坛)

中央处理器

英特尔 i7–8700k

引用 Tim Dettmer 的博客“深度学习的完整硬件指南

中央处理器

人们犯的主要错误是人们过于关注 CPU 的 PCIe 通道。你不应该太关心 PCIe 巷。相反,只需查看您的 CPU 和主板组合是否支持您想要运行的 GPU 数量。第二个最常见的错误是得到一个太强大的 CPU。

6 核 CPU 是我们需求的最佳选择。

几次打嗝:

  • 它支持高达 64GB 的内存:修复-分配更多的交换空间。老实说,现在我看不到我使用> 64GB 内存的可能性,但为了未来的需要——这可能是你想要研究的东西。
  • 不是第九代:
    在组装的时候,世界已经见证了第九代处理器的崛起。

第九代处理器的发布是使第八代处理器更实惠的一个好因素,第九代处理器的性能/价格差异对我们来说似乎并不突出。

随机存取存储

RAM 来源:Tim Dettmer 的博客

RAM 的主要错误是购买时钟频率过高的 RAM。第二个错误是没有购买足够的 RAM 来获得流畅的原型开发体验。

我们争取 64GB

16 * 4:G . Skill rip jaws V DDR 4 3200 MHz

一些建议:

  • 正如 Tim Dettmer 指出的,你可以选择时钟频率较低的 RAM,但是价格差异很小,所以我们选择了这些 RAM。
  • 如果出于同样的逻辑,你想用 RGB RAM:你可以用便宜得多的 LED 灯条,这会让你的外壳看起来更好;)

另外,请注意,我们的主板支持高达 64GB 的内存。

国家政治保卫局。参见 OGPU

对于 GPU,RTX 2080 Ti 是我们的选择。

2070 和 2080Ti 之间的价格差异大约为 900 美元,对于 2080Ti 的价格来说,你可以选择 2x2070,这将使你的内存大小得到提升。

但是由于缺乏跨多个 GPU 的训练模型的经验,我们坚持使用 2080Ti。

我还想指出,我决定选择微星游戏 X 三重奏——这是我个人对微星的偏爱。

嘿微星,我知道你没有赞助这个。我没有生气,我的主板上有更多的插槽,你可以帮我处理:D

注:游戏 X 三重奏是一个庞大的卡。我们在 Ant-PC 的朋友警告我们,要插入更多的 GPU,我们必须考虑垂直安装或移除 GPU 的支撑杆。

支撑杆:GPU 重约 3 千克,因此需要一个支撑杆来防止它下垂。

母板

快速检查清单:

  • 符合你的情况。
  • CPU 兼容。
  • 支持您喜欢的内存大小。
  • 支持多个 GPU。
  • 支持多个 NVMe M.2 驱动器。
  • 支持多硬盘(大多数现代主板都有)

出于上述原因和对微星的偏见,我们决定获得微星 Z370 PC PRO

  • 支持第八代处理器。
  • 支持高达 64GB 的内存。
  • 将允许多达 3 个 GPU。
  • 支持 2 个 M.2 驱动器。

情况

我们的零售商建议购买 CoolerMaster H500 版本,原因如下:

  • 该案件有一个体面的大小,允许方便的升级。
  • 透明面板,以显示一些 RGB 的爱。

程序存储单元(Program Storage Unit)

另一个检查表:

  • 支持当前组件。
  • 将支持未来的组件需求。

出于这些原因,我们选择了酷派先锋 1000W PSU

CPU 冷却器

这是我想快速重复的另一件事,

根据我以前的(不正确的)知识,我认为液体 CPU 冷却器是最好的,因为我将添加多个 GPU,同时,我想保持冷却。

但是值得庆幸的是,正如弗朗西斯科·英厄姆在 Fastai 论坛上指出的那样,液体冷却器只有在你需要超频 CPU 时才有很大帮助——这不是我们的要求。

另外,有很小的可能会有泄漏——不会发生——但这是可能的。

出于这些原因,我们决定用 Hyper 212 LED Turbo 替换 ML240L 液体冷却器。

我们的零售商-Ant PC 也证实了这是一个很好的选择,而且如果需要的话,更换冷却器总是很容易。

存储

我决定在这上面摇摆 2 个不同的驱动器

  • 512GB 970 Pro 三星 M.2 固态硬盘

用法:Ubuntu+Swap+活动数据集

  • 2TB 硬盘

用途:1.5TB 用于存档

512GB 用于 Windows 安装。当然是为了光线追踪的目的。

最后,这里是中子的一些初步看法。

在这篇博客的第 2 部分,我将分享设置 DL 环境的步骤,随后是一些基准测试。

如果你觉得这很有趣,想成为我的学习之路*的一部分,你可以在 Twitter* 这里 找到我。

如果你有兴趣阅读关于深度学习和计算机视觉的新闻,可以在这里查看我的 快讯

永远不要跨过“平均”4 英尺深的河

原文:https://towardsdatascience.com/never-cross-a-river-4-feet-deep-on-average-d1a8d1ec345c?source=collection_archive---------17-----------------------

数据假象

总结战争与和平——避免常见的数据陷阱

一——概述战争与和平

《战争与和平》有 361 章 587287 字 559 字!一个普通人大概需要 33 个小时来读完整本书,一些学者花了一生的时间来剖析这部杰作。你会如何向从未读过这本书的人简要解释这本书?

最简短的“总结”可以是这样的:“战争与和平大体聚焦于拿破仑 1812 年入侵俄罗斯”

一个稍微复杂一点的“让你觉得这本书也有一些浪漫色彩的总结可能是”这本书讲述了文学中三个最知名的人物:皮埃尔·别祖霍夫,一个伯爵的私生子,他正在为自己的遗产而斗争,渴望精神上的满足;安德烈·博尔孔斯基王子,他离开了他的家庭去参加反对拿破仑的战争;娜塔莎·罗斯托夫(Natasha Rostov),一个贵族的年轻漂亮的女儿,在拿破仑的军队入侵时引起了两个人的兴趣,托尔斯泰出色地跟踪了来自不同背景的人物——农民和贵族,平民和士兵——他们与他们的时代、历史和文化特有的问题进行斗争。随着小说的进展,这些人物超越了他们的特殊性,成为世界文学中最感人的人物。 1

Could you read a book the size of war and peace but full with raw data?

这些总结充其量是“聊胜于无”,但没有一个能恰如其分地描述托尔斯泰的杰作。事实上,给你朋友的唯一真正的建议是慢慢地、一丝不苟地阅读整本书,在笔记本上记下每一个字符,这样他们就不会被错综复杂的情节弄糊涂了。

然而,许多商业决策都是在类似的非常不完善的数据汇总的基础上做出的:商店因为季度业绩低于预期而关闭,销售人员因为年度业绩令人鼓舞或令人失望而被提升或解雇,产品线因为整体利润不如其他产品线而停产…

一个简短的例子

让我用一个简单的例子来说明总结是如何误导人的……几年前,我与人合伙创办了一家餐饮企业,我们雇佣了几十名难民和移民厨师,为团队午餐或公司活动提供他们的美味佳肴。

由我们自己的员工将食品交付给最终客户。准时交货是衡量客户满意度的一个关键指标,因此,我想给准时交货率最高的员工颁发一份特别奖。为了简单起见,让我们假设我们只有两个交付人员:Farid 和 Fatima

  1. 一月份,法里德的平均准时分娩率高于法蒂玛:分别为 90%和 88%
  2. 2 月份,Farid 的平均准时交付率再次高于 Fatima,分别为 80%和 78%

谁应该得奖?法里德显然是对的…?

如果我告诉你,一月和二月 合计,是法蒂玛,而不是法里德的准时交付率最高,会怎么样?

你可能会想不可能——法里德在一月和二月会更好,而法蒂玛总体上会更好?很简单。事实上,如果你看看下表:

从数学的角度来看,推理很简单:如果 A1/C1 > B1/D1,A2/C2 > B2/D2,我们不能必然地假设(A1+B1)/(C1+D1) > (A2+B2) / (C2+D2)!这是一个基本的比率规则。换句话说,两个月的算术平均值(Farid 为 85%,Fatima 为 83%)与上述的加权平均值之间存在明显差异。

然而,从逻辑的角度来看,结论仍然可能非常违背直觉和令人不安!对我来说,问题仍然存在:谁应该获得这个奖?当然,答案取决于我们如何提问(奖金应该按月发放还是按周期发放)?你可以很容易地看到同样的推理如何应用到其他领域(例如,产品 A 在一个月的每个星期都比产品 B 有更高的利润率,但是产品 B 在这个月有更高的利润率……)

另一方面,言外之意很清楚:仅仅依靠“总结”是不够的…

那我们该怎么办?“读取”所有数据?

实际上,想象一下,您想要理解一个大约和《战争与和平》一样大的数据集(比如大约 500,000 个数据点)。理解它、描述它、获得洞见并付诸行动的最佳方式是什么?考虑到战争与和平小说的相似性,你可能需要花几个月的时间来观察整个数据集,观察并理解每一个小数据点,以及它与其他数据点的联系。当然,这是不切实际的:不仅要花很长时间来观察所有的数据,更重要的是,我们的大脑没有能力吸收或理解成千上万个不同的数据点。例如,当阅读一本小说时,我们的大脑有一种与生俱来的能力,并且从小就被训练来建立一个连贯的叙述,将概念联系在一起,即使你在阅读这些概念时相隔几周或几个月。然而,我们的大脑从不同的数据中构建连贯图像的能力却非常有限。在某种程度上,用我们理解 50 万字的《战争与和平》的方式来理解这 50 万个数据点,目前仍将是一个遥远的梦想。

作为一种变通方法,我们使用统计描述符(如平均值、中值、标准差)分析和总结数据,并使用相关、聚类和模式分析等工具…我们使用技术工具,并越来越多地使用人工智能来大幅提高我们分析和总结数据的速度。这些方法旨在通过简化信息,在数据的复杂性和我们人类思维的有限理解之间建立一座“桥梁”,但如果使用不当,它们也会产生不完整甚至错误的图像。

假设,如果有一个超人的大脑可以理解数百万数据行形式的原始数据,这将是一种真正实现对每个数据点的完美理解的方法。(你可能会认为人工智能是这种理解的某种版本——我认为人工智能确实有机会增强这种理解,但这应该是另一篇文章的主题)这种超人的思维当然会将任何“总结”数据的尝试视为对他们完美理解的降级。这就是我们应该如何看待数据的统计描述符——特别是平均值和方差——作为看待数据的方便但不完美的方式。它们经常带有固有的偏见,会直接导致错误的结论。它们是完美的例子,说明“半理解”实际上可能比“完全不理解”更糟糕。

在接下来的系列文章中,我将通过几个实际例子来说明我们在使用这些总结“妄下结论”时所犯的一些判断错误和偏见,并解释为什么“显而易见的答案”并不像看起来那么显而易见。

这是给谁的?

本系列对数据作者(准备和展示数据的人,如顾问)和数据读者(数据的接收者,或被顾问讲课的人)都有帮助。

对于数据作者来说,目标不是提供先进的数据分析技术。这些在今天的大量书籍中都有涉及。事实上,数据作者今天面临的主要挑战是我所谓的“法拉利错觉”:这是一种错觉,因为你开着法拉利,所以你是一个更好的飞行员,而事实上,如果你想开法拉利,你必须学会成为一个更好的飞行员。否则,当你踩下油门时,你所做的只是增加撞车的几率。在 excel 中创建一个包含类别平均值的数据透视表只需不到一分钟的时间,我仍然惊讶于 Tableau 这样快速简单的工具可以通过简单的拖放来总结和创建数十万个数据点的美丽视觉效果。向左拖动,向右拖动,神奇的是,你就有了你需要的漂亮的平均图表。这些工具正变得越来越强大、快速和花哨,但对于数据作者来说,很容易将花哨和强大与准确混淆起来。我的目标是这一背景实际上是提醒一些基本原则,即使是高级数据科学家有时也似乎忘记了,就像有经验的登山者经常在最容易的路径上绊倒,当他们不注意的时候。当然,如果考虑到正确的焦点,这些工具会变得非常方便。

对于“数据读者”/ 来说,向人们展示数据的目的是帮助他们提出正确的问题,而不是落入数据作者通常有意为他们设置的陷阱。这些“技巧”可以被故意使用,特别是由昂贵的顾问使用,以证实他们的高级合伙人在他们对数据将说什么有一点线索之前就已经给了客户错误的结论。他们晚上仍然睡得很好,因为有时“目的可以证明手段的正当性”

下面的例子将有助于说明我们需要持怀疑态度并提出正确的问题,尤其是在被放映完美幻灯片的顾问讲课时。我的一般经验是:格式越完美,演示者越优雅,幻灯片越有光泽,你就越应该怀疑,问更多的问题。

在下一章中,我将为最流行的“汇总”统计说明上面的概念:平均值。我将用具体的例子来说明平均值可能产生误导的几种情况:

  1. 被平均的数据比被平均的层具有更多的底层
  2. 基于不足数据点的平均值
  3. 当数据层具有不同的分散程度时,平均值会传达误导信息

II——为什么平均值会误导人

让我们回到我的餐饮公司。公司厨师开发了几十种来自他们烹饪传统的菜肴——虽然在我看来都很特别,但他们的菜肴对典型的美国人来说或多或少是成功的。在我们不断努力为顾客提供最佳服务的过程中,我们希望了解谁是我们最好的厨师,我们发起了一项调查,顾客可以对每位厨师的烹饪进行评分。在我们承办的每个活动中,每个厨师通常都会准备一道菜。

每位厨师的平均结果如下所示

直接结论是显而易见的:

  1. Faven 的评分比她的厨师同事低得多。我们或许应该解雇她,或者至少让她在厨房帮忙,而不是用不为人知、显然不受欢迎的味道折磨我们的顾客?
  2. 法蒂玛是我们最好的厨师!让我们宣传她,为她的美食多做些广告吧!
  3. 法里德、巴特萨和阿扎尔都是同样伟大的厨师,评分也差不多。Nidal 稍微低一点但是还是可以的。科萨拉只有 70%——还可以,但是我们应该少用她。

a)数据有多少层?

简单吧?没那么快。事实证明,所有这些结论都是错误的,或者至少是误导性的:我们的调查确实要求每个顾客对厨师进行评价,我们知道每个厨师为每个活动准备了不同的菜肴。如果我们不只是平均厨师的结果,而是平均相应菜肴的结果,会怎么样?结果如下:

我们可以清楚地看到,最受欢迎的菜肴是埃及穆萨卡,它是……厨师法文的创造!仅仅依靠平均每位厨师,我们就要解雇负责我们最受欢迎菜肴的人了!Faven 主厨有另外两种菜降低了她的平均水平,这些菜显然不受纽约人的欢迎,应该被淘汰。但她显然有一些天赋,我们应该鼓励她创造一些新的菜肴。

这是同一概念的另一个例子。我们的客户服务代表 Alex 很有远见地询问了每一个调查对象他们是否是素食者。当我们对引入该维度的回答进行平均时,结果如下:

这里第二个错误的结论是科萨拉的美食其实是最受素食者欢迎的!所以,再一次,平均每个厨师只把 Kosala 列为相当一般,并且忽略了这个关键的洞察力(特别是我们的许多顾客是素食主义者)

这是什么意思?

在我们上面的例子中,考虑评价菜肴而不是厨师,或者介绍顾客的类型似乎是显而易见的——这从本质上说明了这一点。但是您可以在下面的类似示例中看到这是如何产生误导的:

“一家公司想要关闭表现不佳的店铺,它关注的是每家店铺的平均收入”。但是想象一下,平均收入最低的商店恰好是销售最多产品、利润最高的商店,或者是最有增长潜力的商店?这是一个与厨师的例子非常相似的例子,我相信你们中的很多人都以这样或那样的形式遇到过很多次。

b)我是否有足够的独立数据点?

现在让我们来看看每个厨师/菜肴收到的评论数量。

上表中一个值得注意的事实是,Fatima 得到的评论比她的同龄人少得多,实际上少了 100 倍!原来 Fatima 是我们最新的厨师:其他厨师通常每人承办 40 多场活动,而她在 2018 年 9 月 12 日只承办了一场活动!

现在让我们放大一下 Fatima 承办的活动,看看具体的评分:

嗯,那个活动的人对他们的评价特别慷慨,不仅仅是对 Fatima,而是对所有人!那么我们现在说什么?尽管如此,肯定法蒂玛是有史以来最好的厨师?不太确定是吧。如果你已经提升了法蒂玛,为什么不打电话给她说:“嘿,我真的很抱歉,这次提升有点仓促!你的厨艺很有前途,但是我们真的还不知道你是不是一个好厨师,在我们可以肯定地说任何事情之前,你还有许多困难要克服。现在继续好好工作,让我们几个月后再聚”

不仅仅是观察次数…

你可以称之为“统计显著性”,但它不仅仅是观察的数量。在这个特定的例子中,数据(事件)还有另一个维度,这使得数据点不是独立的(即,不仅 Fatima 有非常少的数据点,而且它们也不是独立的,因为它们都与单个事件相关)

c)数据的分散程度如何?

好吧——但是法里德、巴特萨和阿扎尔呢?它们看起来非常相似:总体平均评分相似,每道菜的平均评分相似,并且都有大量的数据点。在这种情况下,平均数一定有公平的代表性,对吗?让我们看看个人评分,看看我们是否错过了什么。下图显示了每道菜在特定容器中的评级数量(例如,70 至 80 将被归入 80 桶)。

Batsa 的收视率看起来不一样吧?他们都在 70 年代和 80 年代,而法里德,阿扎尔和科萨拉都有更多的极端(或低或高)。换句话说,几乎每个人都认为 Batsa 的菜肴非常好——没有人认为它们一般或特别,而对于其他厨师,我们有一些顾客认为他们的菜肴特别或一般!这是另一个机会,可以再次对数据的所有维度(每个事件、每个客户类型……)进行切片,以了解更多信息。我不会告诉你细节,但事实证明,法里德和阿扎尔的菜在那些自称为“爱冒险的食客”并喜欢尝试不同且颇具异国情调的东西的人那里会获得极高的评分,而那些喜欢安全行事的人有时会获得较低的评分——你知道我在说谁:那些只会在泰国餐馆点泰式炒面而不会尝试其他东西的人……相比之下,Batsa 的菜是冰淇淋的“香草”风味:每个人都喜欢它,但没有人对它着迷!这被证明是非常有价值的信息,因为它将帮助我们标记我们的菜肴:“冒险”或“取悦大众”。

从技术上来说,这是通过每个维度上的方差或标准差来衡量的(较小的标准差表示较小的方差),但是,我发现像上图这样的可视化表示比仅使用标准差度量更有说服力。

“永远不要穿过平均深度为 4 英尺的河流”…我们何时以及如何使用平均值

我最喜欢的作家之一尼古拉斯·塔勒布说得好,“永远不要跨过平均 4 英尺深的河”。从本质上说,他是在说,数据的可变性会使平均值变得无用,并经常导致错误,正如我们上面所说明的那样。

但这是否意味着我们应该永远抛弃平均数给我们的结论?我们不要那么激进好吗?当一个人意识到上下文时,平均值会很有帮助。例如,如果我告诉你,本田奥德赛 2018 EX 在纽约的平均售价为 29,978 美元,而本田 Pilot 2018 EX 的平均售价为 39,760 美元,这实际上是一个有用的信息,可以得出购买奥德赛会更便宜的结论,并让你知道你会花多少钱。这些数据的背景是:

  1. 它是基于美国各销售点成千上万的独立观察
  2. 这是相当具体的(我们有型号和地理和其他方面(如颜色)不太可能影响价格明显)
  3. 数据并没有那么分散:当然,有一个非常有才华的推销员能够以高出 5%的价格卖出,或者你的伊拉克朋友曾经在巴格达市场交易地毯,他会以低于你 7%的价格卖出。但总的来说,这些数据看起来像一条清晰且相当窄的钟形曲线

但是让我们再举一个平均价格没有帮助的例子。假设你要建议你那疯狂富有的亚洲朋友,在苏富比拍卖一幅毕加索的画和一幅梵高的画,出价多少。你拿出平均数据,说毕加索在拍卖会上的平均售价为 700 万美元,梵高的平均售价为 1300 万美元。正如你已经猜到的,这对你的朋友来说几乎是无用的信息,因为:

  1. 对梵高或毕加索作品销售的观察并不多,而且随着时间的推移,这些观察往往会发生变化
  2. 这幅画的作者并不是它价格的唯一预测者(有点像上面的厨师和菜肴)。还有其他维度(比如绘画的状态)
  3. 最重要的是,数据中存在显著的差异,存在显著的极端情况(毕加索为 1 亿美元,梵高为 8000 万美元以上)。它远不是一条清晰的窄形钟形曲线

另一个我个人觉得非常有趣的日常例子是 Yelp 或 Google 上的餐厅五星评级系统。有了这个系统,每家餐厅基本上都被划分为一个等级(即在 5 星级标准中为 2.5、3 或 4.5)。这是一个完美的例子,平均过度简化了信息,抹去了每个餐厅的特质。有了这个评分,“受欢迎的人”自然会上升到首位,有点像“香草”冰淇淋比绿茶冰淇淋更受欢迎。但如果你像我妻子一样是绿茶冰淇淋的忠实粉丝,那么你可能会因为仅仅依赖明星系统而错失良机。“群众的智慧”有时是“群众的暴政”,在许多方面,老式的餐馆评论(当由不带偏见的专业人士撰写时)可以对餐馆进行更有色彩和味道的评论。

这并不是说星级评定和群体智慧应该被忽略,但它更适合于本质上同质的事物:例如,对评级至关重要的卫生和舒适度评级在商务酒店中非常普遍,不像餐厅食物那样太依赖于“味道”。

作为补充说明,我应该强调,我遇到过一个显著的例外,在这个例外中,平均值实际上比数据点的集合更能提供信息:“群体的智慧”。如果你让人们猜罐子里有多少颗软糖,你会注意到他们答案的平均值是最佳近似值(会有比平均值做得更好的“专家”,但他们不会像平均值那样“一致”——也就是说,如果你重复实验多次,平均值将是所有专家中的赢家。这就是“群体智慧”效应,这是一个引人入胜的现象,值得单独辟出一章。

这对数据作者和数据读者意味着什么

总的来说,你需要采取怀疑的态度,了解正确的背景。数据是棘手的,所以记住任何合成都是不完美的。当然,这是可以的,也是必要的,但是,意识到这一点会有很大帮助:

  • 问自己(或作者)正确的问题:
  • 我还可以在哪些维度上分割数据?是否有我看不到的隐藏的可变性?
  • 每个平均值下面有多少个观察值,它们是独立的吗?
  • 数据有多分散?
  • 花时间观察数据——在计算任何平均值之前,使用工具对多个维度进行分割
  • 获取一些基本指标:维度数量、每个维度的观察数量、每个维度的差异
  • 问问自己,发言人是否有意操纵信息
  1. 企鹅随机屋的描述
  2. 数据分析工具、机器学习和人工智能当然可以大大提高我们分析和总结数据的速度,但问题是它们在多大程度上传达了一幅增加我们对数据理解的画面

使用深度学习预测下一个搜索关键词

原文:https://towardsdatascience.com/never-leave-the-search-result-page-19b654791c27?source=collection_archive---------17-----------------------

第一部分:盗梦空间

下一个单词预测或语言建模的任务是预测下一个单词是什么。当你写短信或电子邮件时,你可能每天都在使用它而没有意识到这一点。电子商务,尤其是基于杂货的电子商务,可以广泛受益于这些功能。

Examples of next word prediction

搜索在电子商务购物中起着举足轻重的作用。特别是对于杂货购物,大多数电子商务网站报告 40-50%的转化率来自搜索结果页面。因此,对于任何杂货电子商务网站来说,在搜索功能方面保持领先是至关重要的。

在寻找食品杂货时,我们发现自己每次都在寻找或多或少相同的东西。任何一般的家庭购物清单都会有一套日常用品,也会有一个购物模式。此外,搜索特定食谱的项目,我们会发现一个购物模式。

因此,对于客户搜索的每个会话,将形成一种以搜索词为节点的 DAG ,从一个搜索词到另一个搜索词的过渡是边。举个例子,

milk → bread → butter → cheese → eggs → chicken

所有这些使我们能够根据会话中之前的搜索来预测客户接下来会搜索什么,就像电子邮件或手机键盘的情况一样。

赞成的意见

  1. 我们的搜索将变得客户友好互动,因为客户不可能键入下一个搜索词。
  2. 我们可以“引导”我们的客户选择高性能的搜索词,而不是长尾搜索词、不正确的拼写等等。
  3. 我们的百分比转换从搜索结果页面相比,总转换可能会增加。
  4. 客户可能会添加比他们预期更多的产品来代替建议。

面向连接的网络服务(Connection Oriented Network Service)

  1. 我们的下一个搜索词预测可能会限制客户可能搜索的产品范围。例如,一个全新的项目出现在我们的网站上,但在搜索时不会出现在现有的搜索列表中。由于我们的领域是杂货,产品的数量及其各自的上下文是有限的,我们可以忽略这个问题(根据您的目录可能不存在)。此外,如果该项目和搜索词变得足够流行,它会在下一次迭代中被添加到我们的集合中。
  2. 预测不受欢迎的或/和重复的术语可能会妨碍客户体验。就像我们在键盘和电子邮件中看到的这个特性一样,我们通过一个非侵入式的 UI 来解决这个问题,这是一个更好的辅助特性。

对自然语言处理的需求

由于我们有一个可接受术语的大字典,运行日常分析是不可能的,因为所有数据组合都不可用,并且所有组合都会产生一个相当大的数字(对于 1000 个术语和预测第 5 个术语,我们需要计算 10 个 Dag)。我们需要根据前一个序列的上下文来预测下一个搜索词,这是我们在运行纯分析时无法捕捉到的。因此,为了预测下一个关键字,我们需要探索 NLP 技术。

第 2 部分:设计和实现

客户行动流程和高级设计

Customer action flow diagram

所以我们的预测有两个动作。

一个是客户没有为搜索词添加任何项目,我们预测一些与他/她可能正在寻找的东西相关的搜索词。例如,假设客户搜索牛奶,但他可能正在寻找蓝色牛奶,这可能不会出现在我们的 SRP(搜索结果页面)的顶部。因此,我们给我们的客户更具体的搜索条件。

第二个例子是顾客在他的购物车中添加了一些牛奶商品,并寻找更多的东西,如面包、奶酪、鸡蛋等。这里,我们根据会话中之前的搜索给出下一个搜索词的预测。

为了预测下一个可能的搜索关键字:

  1. 前端服务传递最后 N 个搜索关键字。
  2. 后端服务验证所有 N 个关键字都存在于模型的关键字字典中。
  3. 对于字典中不存在的关键词,后端调用相似词模型,得到与前端传递的词相似且存在于字典中的词。
  4. 后端将修改后的最后 N 个术语传递给下一个术语模型,得到结果并将其提供给前端。

下一期模型的详细设计

为了找到和设计下一个术语模型,我们称之为 NLSRP 模型,(模型名称工作进行中,欢迎任何建议:) )我们遵循:

收集原始数据和预处理

为了建模,我们需要数据。在我们的例子中,它应该是具有连续术语的会话的形式,导致添加到 cart,dag 的列表,类似于:

milk → bread → eggs → ...

这里,

  1. 我们需要过滤掉不在我们的首选列表中的术语。
  2. 我们需要短时间内的连续术语(我们花了 20 分钟)。

如果您有一个包含会话 id、时间、添加到 SRP 上的购物车的术语的表,我们可以运行一个 spark 作业来获取所需的数据。

mainDataset = mainDataset.groupBy(
*col*(**"session_id"**),
*window*(*col*(**"datetime"**), **"20 minutes"**))
.agg(*collect_set*(
*col*(**"term"**))
.as(**"termlist"**));

数据建模

我们的第一个挑战来了,如何对我们的搜索词进行建模,以将它们提供给学习模型。

为我们的搜索词生成 word2vec 嵌入,用于 CBOW 模型(给定相邻词给出当前词),以及 skip-gram 模型(给定前一个词预测下一个词)。word2vec 的超参数:

大小: 每个搜索项嵌入的大小。100–300 是推荐的大小。由于我们的 vocab 大小限制在 100 个或最多 1000-2000 个搜索词,我们可以放心地认为是 100 个。

窗口:在我们的用例中,7 似乎是一个理想的值,因为我们序列的最大长度是 15。

hs: 不需要分层 softmax,因为我们的 vocab 大小很小。(它是 softmax 的近似值)

iter: 经过 25+1 次迭代后我们在模型中看不到任何变化。我们可以使用 5 为耐心的 EarlyStopping 回调来获得迭代次数。

我们使用 gensim 的 cython 优化实现来获得我们的定制嵌入。

我们得到这样的结果:

[('semi skimmed milk', 0.652964174747467),
 ('cravendale', 0.4939464330673218),
 ('skimmed milk', 0.35889583826065063),
 ('long life milk', 0.3340461850166321),
 ('sandwich fillers', 0.321510910987854),
 ('sandwich meat', 0.3212273120880127),
 ('flavoured water', 0.30973631143569946),
 ('cheese spread', 0.3049270212650299),
 ('crisp', 0.3014737665653229),
 ('cereal bars', 0.3007051646709442)]

我们可以看到类似的术语出现,只是通过学习(应用 word 2 vec)Dag。这也证实了我们关于顾客购物模式的假设。

从我们的 Dag 列表中,我们创建输入,输出对应于固定的大小。我们将固定窗口 N 取为 5。因此,我们传递 4 个搜索项作为输入,得到序列中的第 5 个项作为输出。

基线我们的期望

Word2Vec 在输出层训练的是下一个单词的概率。因此,线性神经网络的输出层用于获得单词嵌入,从而为我们提供未来的单词预测。

Gensim 提供了一个 API 来实现这一点

我们得到的输出如下:

[('fruits', 0.0055794665),
 ('pork', 0.0042083673),
 ('potato', 0.0032076887),
 ('choc waffle', 0.0028934616),
 ('drink', 0.0026189752),
 ('chocolate pudding', 0.0023179431),
 ('rice', 0.002288311),
 ('yogurt', 0.0022665549),
 ('breakfast. bars', 0.0021832779),
 ('freddio', 0.0021441795),
 ('flavour water', 0.0021338842),
 ('beef', 0.0021277776),
 ('dog', 0.0021113018),
 ('angel cajes', 0.002109515),
 ('yogurts', 0.0021087618),
 ('apple', 0.0020760428),
 ('figita', 0.002075238),
 ('schwepp', 0.00204034),
 ('breakfast', 0.0020321317)]

我们以此为基础对 CBOW 和 skip gram 进行了基线预测,得到了一个相当好的模型。

更加努力

我们的任务是通过查看之前的关键字来预测每个搜索关键字,而 RNNs 可以保持一个隐藏状态,可以将信息从一个时间步转移到下一个时间步。

Sample RNN example

我们尝试用 RNNs 实现 seq2seq 模型。我们在 keras 和 tensorflow 后端的帮助下做到了这一点。

我们在 Keras 设置了一个多层 LSTM/GRU,每层有 N 个隐藏单元,共 2 层。RNN 的输入是最后 4 个搜索项,目标是下一个搜索项。

该模型可以根据复杂程度在 LSTM 或 GRU 进行训练。它可以有隐藏的细胞。这里你需要使用 RNN 类、批量、隐藏层输入、嵌入矩阵类型(cbow 或 skip gram)、退出、层(深度模型为 2)来获得最佳模型。

回调将在每个时代和我们引入的自定义记录器之后保存每个模型。

这个模型将产生比 word2vec 的输出层更好的模型。

在生产中部署

我们可以把 keras 模型转换成 tensorflow,用 tensorflow-serving 的 docker 来服务它。这将把. hd5 模型保存到. pb 文件中,该文件通过 tensorflow serving 和 docker 部署。

相似性搜索

每个电子商务网站都有一个基本的东西,叫做目录。该目录分为类别、子类别和进一步的子类。对于 SRP 上点击的每个项目,我们将获得每个搜索项的类别级别、子类别级别和其他子类级别的贡献。

该贡献作为一个整体将成为搜索项意图树。意图树将是类和它们各自的值(贡献)的向量。我们可以通过许多技术找到给定向量和向量列表之间的 L2 距离相似性,即给定的搜索项和可接受的搜索项列表。如果你的列表很小,你可以穷举迭代。另外,我们可以使用脸书的 FAISS 来寻找 Voronoi 单元中的相似向量。

我以此结束这篇文章,如果你呆了这么久,请评论你的疑问和建议:)。

AirBnB 新用户预订预测——使用机器学习

原文:https://towardsdatascience.com/new-airbnb-user-booking-prediction-using-machine-learning-874836bff403?source=collection_archive---------23-----------------------

Photo credits to Prexels

对任何公司来说,最有价值的信息之一就是了解用户的行为。一个好的战略决策通常基于对客户购买模式和趋势的了解。此外,互联网已经连接了世界,我们的数据被共享,并用于网络上的每一个营销活动。数据已经成为 21 世纪最有价值的商品。

在这篇摘录中,我想使用机器学习来预测 AirBnb 新用户的行为,以分类用户是否会在注册账户的 5 天内进行预订。这个博客解释了这个项目的工作流程和一些决策。尽情享受吧!

你可以在这里找到这个项目报告。

我还在 Heroku 上托管了一个 flask 应用程序,请随意查看这里的。

问题陈述:

我们能使用机器学习来发现 AirBnB 新用户的洞察力吗?

我们如何利用用户行为预测来最大化假想营销活动的收益?

TL;速度三角形定位法(dead reckoning)

我们从在 Kaggle 上发现的不平衡数据集开始。我们使用 ADASYN 对我们的训练集进行过采样,以输入到基本的逻辑回归模型中。我们决定使用 AUC 分数作为我们的评估指标,因为我们希望根据假设的业务约束优化概率阈值。总之,使用我们的最佳表现模型(CatBoost),我们应该向至少有 16%的预订概率的用户做广告,以最大化净收入。在这个过程中,我们发现用户通过 web 应用程序和特定的注册流程进行注册会产生更高的整体转化率。

这是我的方法:

  1. 数据预处理
  2. 型号选择
  3. 模型评估和度量
  4. 要点和建议
  5. 烧瓶应用程序

数据预处理

为了这个项目,我使用了 Kaggle 上的一个旧数据集。你可以在这里找到数据集。Kaggle 最初的问题陈述是预测新用户的首次旅行目的地。我更感兴趣的是第一次使用 AirBnb 的用户是否会预订。

以下是我使用的一些功能:

  • date_account_created:帐户创建日期
  • timestamp_first_active:第一个活动的时间戳,注意它可以早于 date_account_created 或 date_first_booking,因为用户可以在注册之前进行搜索
  • date_first_booking:首次预订的日期
  • 性别
  • 年龄
  • 注册方法
  • 注册流:用户注册的页面
  • 语言:国际语言偏好
  • affiliate_channel:什么样的付费营销
  • affiliate_provider:营销的地方,如谷歌,craigslist,其他
  • first_affiliate_tracked:用户在注册之前互动的第一个营销是什么
  • 注册应用程序
  • 第一设备类型
  • 第一个浏览器

由于我们偏离了最初的 Kaggle 问题陈述,我们必须制作自己的输出标签。我决定,我们的积极阶层将是那些在注册 AirBnB 账户后 5 天内进行预订的人,否则他们将被视为处于消极阶层。在 5 天之后,既记账又预订的用户数量显著减少,因此,我使用 5 天作为分类阈值。

在注册后 5 天内预订的用户被标记为 1。

在注册后 5 天内没有预订的用户被标记为 0。

使用这个定义,我们有大约 40,000 个正类(1)和 111,500 个负类(0)。在实践中,我们的积极阶层代表性不足是相当普遍的。这被称为不平衡数据集。这是一个专门针对欺诈或其他异常检测等问题的问题。克服不平衡数据的常用技术是对训练数据集进行过采样。我们从来不想在我们的验证或测试集上进行过采样。在这个项目中,我使用了 ADASYN,它是自适应合成采样方法的缩写。在将数据分成训练集、验证集和测试集之后,我将 ADASYN 应用于训练集。我们现在正在处理 66,880 个阳性和 69,685 个阴性标签。最后,让我们开始建模…

模特培训

在应用任何高级机器算法之前,最好总是构建一个普通的基础模型。我使用 SciKit-Learn 的逻辑回归软件包来训练一个基本模型。结果如下:

如您所见,由于分布不平衡,我们的模型在预测负类(0)方面比正类(1)做得更好。对于这个项目,我们希望最大化我们的阳性类(1)的 AUC 分数。我将在下面的评估部分更详细地解释我们为什么选择这个指标。

我继续使用其他分类算法,如朴素贝叶斯、KNN、决策树、RandomForest、XGBoost 和 CatBoost。我根据 AUC 分数挑选了表现最好的 3 个模型,并对所有这些模型进行了参数调整。我将在另一篇文章中详细介绍如何有效地使用 GridSearchCV 来调整不平衡数据集上的参数。以下是参数调整后 AUC 得分最高的前 3 个模型的结果。

在选择具有相似性能的型号时,需要考虑一些事情。我将在下一节“模型评估”中讨论更多细节。

模型评估和度量

如上所述,我们主要关注最大化 AUC 分数。AUC 代表曲线下面积。它是在各种概率阈值下模型性能的度量。分类算法的默认概率阈值设置为 0.50。这意味着如果模型输出 0.50 或更大的概率,它将预测正类(1)。相反,如果模型输出 0.50 或更小的概率,它将预测负类(0)。我们在哪里设置阈值是特定于业务案例的约束。在我们定义假设的业务案例之前,让我们看看在模型选择过程中我们可能要考虑的其他事情。

模型的可解释性是选择模型时要考虑的最重要的事情之一。最终,我们希望能够解释我们模型的结果,并对问题提出有见地的建议。在三个模型(logistics、XGBoost、CatBoost)中,Logistics 回归是迄今为止最容易解释的。

模型训练速度可能是另一个需要考虑的因素。如果经常重新训练模型是令人感兴趣的事情,人们可能希望训练速度尽可能快。其他人可能也希望预测速度尽可能快,因为预测速度直接影响客户在 web 上的信息流。在我们的例子中,我们对训练时间更感兴趣,因为我们希望能够随着更多数据的可用而定期更新我们的模型。以下是顶级模特的训练时间:

同样,逻辑回归在速度上胜出,但 CatBoost 也不算太慢。

最后,但也是最重要的,让我们将这些点与我们假设的 AirBnB 业务问题联系起来。

我们如何利用用户行为预测来最大化假想营销活动的收入?

我们的目标是最大限度地提高假想营销活动的收入。让我们来解释一下这个问题的背景。经过一番研究,我得出了一些估计(它们绝不是 100%准确的):

预计 2020 年将有大约 220 万新用户使用 AirBnB。所有首次用户中有 23%预计会进行预订—这是我们样本数据集中的正类样本。当平均预订价格为每晚 160 美元(17%的费用来自预订者,3%来自房东)时,AirBnB 的每次预订收入约为 32 美元。我还估算了每个用户的平均广告成本为 5 美元。不要太在意这些数字是从哪里来的,但要得出合理的结论,有这些业务约束是很重要的。利用这些信息,我们可以预测每个用户的成本和收益。

通过了解我们预测的成本和收益,我们可以改变概率阈值来最大化任何广告活动的利润。每个概率阈值将为真阳性、真阴性、假阳性和假阴性的数量产生一组不同的计数。我们要绘制概率阈值与净收入的关系图。

很明显,CatBoost 模型为我们假设的营销活动带来了最高的收入。这与我们的假设一致,即最大的 AUC 分数将产生最好的结果。尽管就训练时间而言,CatBoost 是一种比 logistics regression 慢的算法,但就总收入而言,它比 logistics regression 多 150,000 美元。在下一节中,我将讨论将我们的概率阈值设置为 0.16 的重要性及其意义。

要点和建议

如上所述,我们需要将概率阈值设置为 0.16,以达到我们假设的活动的最大收入。这意味着,如果我们的模型预测一个新用户有 16%或更高的机会预订,那么在我们的活动中瞄准这个用户是值得的。

让我们看看我们选择的 CatBoost 模型的特性重要性。

使用基于树的模型的缺点是我们失去了可解释性。根据你所处的行业,有时候了解你的模型的解释比模型的表现更重要。从功能重要性来看,我们只知道 signup_flow、signup_method 和 signup_app 是预测预订行为的重要因素。

为了更深入,让我们来看看物流回归模型的系数,它具有很高的可解释性。它似乎与 CatBoost 模型的功能重要性保持一致。这样,我们就可以对每个功能如何影响用户行为有一些信心

These coefficients are transformed from log odds

就拿‘sign up _ app _ Web’来说吧。在其他功能保持不变的情况下,通过网络注册的新用户在注册账户 5 天后进行预订的几率是不通过网络注册的用户的 6 倍。AirBnB 的网络体验一定有什么能产生更高的转化率。类似地,同样的分析也适用于注册流程。注册流本质上是用户从最初接触产品到注册页面所看到的页面流。注册流 24、3 和 12 往往表现良好。

烧瓶应用程序

如果你能走到这一步,我为你骄傲!下面是 Flask 应用程序的一个片段。如果你有兴趣的话,可以自己去看看!我将把如何创建烧瓶应用程序的细节留待以后讨论。我通过 Heroku 在一个免费的托管平台上部署了应用!

关于 CatBoost,我应该说的另一点是,与其他算法不同,CatBoost 将以文字形式接受特性。我们不需要一次性编码分类特征,这有助于简化 Flask 应用程序的后端 python 脚本。

感谢您的阅读!

你可以在这里找到这个项目库。

你也可以在我的 LinkedIn 上找到这个帖子。

人工智能和机器学习时代数学/统计科学学生的新途径

原文:https://towardsdatascience.com/new-avenues-for-statistical-science-students-in-the-era-of-artificial-intelligence-machine-291d630437c2?source=collection_archive---------31-----------------------

在这个从手机、家电和电子产品、城市、电子商务、医疗保健、连接到工业 4.0 标准的一切都变得“智能”的时代,我们关注统计科学的范围。人工智能和机器学习是技术的新流行语;让人想起电的发现或计算机的发明。工资最高的工作是在人工智能、人工智能和数据科学领域。没有统计科学的核心,这些途径是不可能的。我们探索统计科学毕业生在新技术领域可以利用哪些技能,以及在“智能”世界中可以弥合哪些差距。

1.传统统计科学

Figure 1. Traditional Statistics mostly into reporting and Data Analysis

很久以前,统计学通常被认为是银行和金融部门最常用的学科。大多数毕业生无法超越银行和金融工作的范畴。从工资水平、技术挑战和影响因子来看,这个数学领域不像工程和计算机科学那么酷。然而,统计科学一直是破解最复杂问题的最有力武器,这些问题来自核物理、通信系统、机器人、空间科学和其他许多领域。

1.今日统计科学

随着计算机计算能力的巨大飞跃和更有效的统计算法的发明;人工智能和机器学习已经进入了一个新的领域。它的影响又远又广,几乎触及每一个生命。

A 人工智能和机器学习是计算机科学的一个分支,它使用核心统计算法来训练计算机进行学习;通过预测、诊断或预后采取行动。AI 在学术界被广泛接受为使用(深度)神经网络的算法家族,而机器学习则是没有神经网络的统计算法家族。

学习大致分为三类

2.1 监督学习

Figure 2.1.1 Supervised learning Logical Architecture [1]

Ssupervised Learning 是一种统计学习算法,它使用一个已知的数据集——称为由输入值和响应值形成的训练数据集——来学习过去,通过损失函数优化来最小化误差,并建立一个模型来对新数据集进行预测。

监督学习分为两部分-

分类:分类响应值,其中数据可以被分成特定的“类”

回归:连续响应值。

Figure 2.1.2 (a) Classification example showing decision boundary separating two classes (b) Linear Regression of data points. [2]

2.2 无监督学习

U 监督学习是一种机器学习算法,用于从由没有标记响应的输入数据组成的数据集进行推断。

最常见的无监督学习方法是聚类分析,用于探索性数据分析,以发现数据中隐藏的模式或分组。使用基于诸如欧几里德距离或概率距离的度量定义的相似性度量来对聚类进行建模。

Figure 2.2. (a). Clustering of Data Samples using Gaussian Mixture Models and Expectation Maximization.(GMM-EM) (b) Clustering using K-means.[7]

2.3 强化学习

这是另一类算法,通过基于动作最大化奖励和最小化惩罚来学习。它不同于监督学习算法,因为监督学习具有目标数据形式的答案,所以模型是在正确答案上训练的。在强化学习中,主体决定做什么来执行特定的任务。

Figure 2.3.1. Typical framing of a Reinforcement Learning (RL) scenario: an agent takes actions in an environment, which is interpreted into a reward and a representation of the state, which are fed back into the agent. [4]

3.当今机器学习/数据科学中使用的算法

Table 3.1 Most useful algorithms used in Machine Learning / AI

虽然大多数数学/统计科学毕业生在毕业期间会遇到各种各样的算法,但表 3.1 强调了机器学习和人工智能的当代艺术中最重要的要求。在工业和研究领域,这些算法被广泛使用,并且对它们的熟悉是最受欢迎的。

我们特别强调基于神经网络的人工智能相关算法是未来技术进步的驱动力。接触人工智能现在是毕业生的必修课。

Figure 3.1 Applications of AI. (a) Objects detection from the image [6] (b) Time Series prediction on some data

A I 用于基于视觉的应用,如 o 对象检测、对象分类、对象语义字幕。自动驾驶汽车、面部识别、入侵检测是流行的用例。

Figure 3.2 (a) Self Driving car identifying objects on front. [3]

b) Speech to text used in modern day applications like Voice search, Google Maps, Voice assisted infotainment in vehicles etc.[4]

A I 用于序列建模,带时间语义数据。时间序列预测、来自文本数据的情感分析、语言翻译、语音识别、语音到文本和文本到语音是一些最广泛使用的应用。

统计学毕业生需要熟悉线性代数中的关键数学概念、微分学、优化技术,如梯度下降、最大似然和最大后验估计、贝叶斯统计、线性模型

Table 3.2. Key mathematical concepts required to be familiar with

4.程序设计语言

统计科学毕业生不需要熟悉计算机科学工程,但是,至少一门编程语言的知识和将数学模型编码成软件的能力是必须的。事实上,上面提到的大多数工具和算法都是在编程练习中学会的。

ython 是数据科学家和计算机科学专业人士用来构建 ML 和 AI 应用程序的最流行的语言。Python 已经走在了传统语言的前面,如 Java、C++、PHP 。它很容易学习,非常强大,涵盖几乎所有应用程序的库,强大的用户基础 Github 和堆栈溢出。根据大多数跨行业的调查[8–12],Python 作为最通用、最流行的编程语言占据主导地位。

通过 python 学习数据科学及其应用既简单又有趣。Python 拥有数百个数据科学库来构建强大的应用程序。

强烈建议数据科学专业的学生在学习这门课程时熟悉 Python。能够将数学模型转化为工作程序对学生来说是最大的优势。

M ATLAB 是最强大的商用数值计算平台。学生熟悉它是一个加分项。

R 专为统计应用而设计,但是不同平台上丰富的库使得 Python 成为更好的选择,因为解决方案需要跨各种技术栈的集成。

5.ML/DS 的职业前景和道路

数据科学家是过去 4 年来最好的工作[13,14]。数学/统计科学毕业生的范围是巨大的。麦肯锡全球研究所警告说,数据和分析人才严重短缺。仅美国就缺少 20 万名数据科学家和 120 万名具有数据科学知识的管理人员。其他国家的短缺并没有太大的不同。在过去的 4 年中,对 ML 和数据科学专业人员的需求增长了 10 倍[14]。

Figure 5. Rate of Growth of Jobs in Specific Domains [14]

LinkedIn[14]也分析了这些工作的职业道路,以下是 5 个最常见的前角色

Table 5. Career Path for the Machine Learning Engineer and Data Scientist

6.结论

我们强调了数据科学在各个行业领域的范围,研究了成为数据科学家/机器学习/人工智能专家所需的数据科学方面的特定技能。我们还展示了该领域毕业生的职业前景、需求和道路。培养具有上述技能的统计毕业生至关重要,以使他们符合当前的技术需求。如果以上任何一项缺失,大学最好纳入数学/统计科学毕业生的完整技能发展。

7.参考

1.NPTEL —机器学习简介

2.https://kindsonthegenius . com/blog/2018/01/what-is-the-difference-that-classification-and-regression . html

3.https://blog . statsbot . co/neural-networks-for-初学者-d99f2235efca

4.https://9 to 5 Google . com/2017/04/18/Google-cloud-speech-API-recognition/

5.https://en.wikipedia.org/wiki/Reinforcement_learning

6.https://en.wikipedia.org/wiki/Object_detection

7.斯坦福大学机器学习 CS229

8.https://coding infinite . com/best-programming-languages-to-learn-2019/

9.https://www . techrepublic . com/article/forget-the-most-popular-programming-languages-heres-what-developers-actual-use/

10.https://www . geeks forgeeks . org/top-10-programming-languages-of-the-world-2019-to-begin-with/

11.https://www . fullstackacademy . com/blog/nine-best-programming-languages-to-learn-2018

12.https://technostacks.com/blog/top-programming-languages

13.https://www . Forbes . com/sites/louiscumbus/2018/01/29/data-scientist-is-the best-job-in-America-dues-2018-rankings/# 182 f4b 955535

14.https://economic graph . LinkedIn . com/research/LinkedIns-2017-US-Emerging-Jobs-Report

15.https://www . Forbes . com/sites/louiscolumbus/2016/12/18/mckinseys-2016-analytics-study-defines-the-future-machine-learning/# 3aa 65 f 9514 EB

16.麦肯锡全球研究院——分析时代:在数据驱动的世界中竞争,2016

在 2019 年 Geo for Good 峰会上宣布了新的地球引擎功能

原文:https://towardsdatascience.com/new-earth-engine-features-announced-at-geoforgood-summit-2019-57c33ef48bb8?source=collection_archive---------24-----------------------

改进的文档|与 Google AI 平台的集成|更酷的可视化

The Geo for Good Summit 2019 was held on 16–19 Sep 2019 at Google Event Center, Sunnyvale, California. Image by Google Earth Outreach.

随着 2020 年 9 月 14 日 Geo for Good Summit 2020 的临近,看看去年宣布的所有新功能可能会有所帮助。这不仅能帮助你学习新的技巧和诀窍,还能帮助你决定参加网上活动(如果你还犹豫不决的话)。

Geo for Good Summit 2019 于 2019 年 9 月 19 日落下帷幕,作为第一次与会者,我惊讶地看到峰会上宣布的新进展数量。此次峰会是同类峰会中的第一次,它将用户峰会和开发者峰会合二为一,让用户受益于新工具的知识,让开发者了解用户的需求。因为我的主要关注点是大规模地理空间建模,所以我只参加了与谷歌地球引擎相关的研讨会和分组会议。至此,让我们来看看三个新的令人兴奋的发展,以打击地球引擎

1.关于机器学习的更新文档

The documentation for Machine Learning and Deep Learning has been updated. Screenshot by author from this website.

文档真的吗?是啊!作为一名业余地球引擎用户,我对这个工具的头号抱怨是它在应用开发者网站、谷歌地球博客和它们的堆栈交换答案之间传播的糟糕的文档质量。因此,欢迎对文档进行任何更新。我很高兴文档已经更新,以帮助对实现机器学习和深度学习模型感兴趣的地理空间数据科学家的不断增长的用户群。

文档附带了自己的示例 Colab 笔记本。示例笔记本有监督分类、非监督分类、密集神经网络、卷积神经网络、Google Cloud 上的深度学习。我发现这些笔记本对我的起步非常有用,因为在流程中有相当多的非平凡数据类型转换(intfloat32等等)。

2.地球引擎和人工智能平台集成

The Google Colab Environment is now integrated with Google AI Platform using the ee.Model API. Image by author.

尼克·柯林顿和克瑞丝·布朗共同宣布了期待已久的地球引擎+谷歌人工智能平台整合。到目前为止,用户基本上限于在 Google Colab 的虚拟机(VM)上运行小型作业,并希望与 VM 的连接不会超时(通常持续约 4 小时)。其他限制包括缺少任何任务监控或排队功能。

不再是了!新的ee.Model()软件包让用户可以与谷歌云服务器通信,他们可以根据自己的需要来设置服务器。不用说,这是对 VM 上以前提供的原始深度学习支持的巨大改进。尽管它是免费的,但人们不能简单地训练、验证、预测和部署任何大于几层的模型。一旦在 Google bucket 中创建了.TFRecord对象,就必须在 Google AI 平台上单独完成。通过这种云集成,用户可以直接在 Colab 环境中运行和测试他们的模型,从而极大地简化了这项任务。ee.Model()类附带了一些有用的功能,比如ee.Model.fromAIPlatformPredictor()可以直接从你在谷歌云上的模型预测地球引擎数据。

最后,由于你的模型现在位于人工智能平台上,你可以作弊并使用你自己离线训练的模型来预测地球上的发动机数据并绘制其输出图。注意,如果你想这样做,你的模型必须用tf.contrib.saved_model格式保存。流行的 Keras 功能model.save_model('model.h5')ee.Model()不兼容。

展望未来,似乎该团队计划坚持将 Colab Python IDE 用于所有深度学习应用程序。然而,对于深受喜爱的 javascript 代码编辑器来说,这并不是致命的打击。在峰会上,我看到与会者仍然更喜欢 javascript 代码编辑器来完成他们的非基于神经的机器学习工作(如支持向量机、随机森林等)。).作为一个 python 爱好者,我也去代码编辑器快速可视化和地球引擎应用!

我没有在峰会上试用新的ee.Model()包,但尼克·克林顿展示了一个笔记本,上面有一个简单的工作示例来帮助我们学习函数调用。开发过程中仍然存在一些问题,比如由于“地球引擎与云平台的通信方式”,在预测期间将卷积内核限制为仅 144 像素宽,但他向我们保证,这将很快得到解决。总的来说,我对这种集成感到兴奋,因为 Earth Engine 现在是我地理空间计算工作的真正替代选择。随着地球引擎团队承诺在ee.Model()类中提供更多新功能,我想知道世界各地的公司和实验室是否会开始将他们的建模工作迁移到地球引擎。

3.更酷的可视化!

Global 24-hour temperature animated gif produced on Earth Engine using the ‘NOAA/GFS0P25’ dataset. Link to code. Image by author.

Matt Hancher 和 Tyler Erickson 展示了一些与可视化相关的新功能,我发现这大大简化了开发动画视觉效果的工作。使用ee.ImageCollection.getVideoThumbURL()功能,您可以在几秒钟内创建自己的动画 gif!我在一组数据集上试了一下,创建 gif 的速度确实令人印象深刻。

对将视频的每一次迭代导出到你的硬盘说再见吧,因为使用print()命令这些 gif 就出现在控制台上!上面显示的是来自“NOAA/GFS0P25”数据集的全球温度预测示例。波浪状图案是由于地球自转导致太阳在不同时间撞击我们星球的表面造成的。制作 gif 的代码可以在这里找到。这个动画是基于迈克尔·德威特的原创博文中的例子,我参考了开发者页面上的这个 gif 制作教程来制作的。

我没有涵盖峰会上介绍的所有新特性和功能。为此,请阅读峰会重点介绍工具,如 Google Earth Pro,BigQuery GIS,Plus Codes 等。您还可以查看峰会的会议资源,获取您感兴趣主题的演示文稿和笔记本。

GeoforGood19

Hadoop 中的新特性:你应该知道 Hadoop 中的各种文件格式。

原文:https://towardsdatascience.com/new-in-hadoop-you-should-know-the-various-file-format-in-hadoop-4fcdfa25d42b?source=collection_archive---------5-----------------------

Hadoop 文件格式初学者指南

答几周前,我写了一篇关于 Hadoop 的文章,并谈到了它的不同部分。以及它如何在数据工程中发挥重要作用。在这篇文章中,我将总结 Hadoop 中不同的文件格式。这个话题将会很简短。如果你想了解 Hadoop 是如何工作的,以及它在数据工程中的重要作用,请访问我关于 Hadoop 的文章,或者跳过它。

[## Apache Hadoop 小结:大数据问题的解决方案和来自 Google 的提示

欢迎学习大数据和 Hadoop 简介,我们将在这里讨论 Apache Hadoop 以及如此大的问题…

towardsdatascience.com](/a-brief-summary-of-apache-hadoop-a-solution-of-big-data-problem-and-hint-comes-from-google-95fd63b83623)

Hadoop 中的文件格式大致分为两类:面向行和面向列:

面向行:
存储在一起的同一行数据即连续存储:SequenceFile、MapFile、Avro Datafile。这样,如果只需要访问该行的少量数据,则需要将整行数据读入内存。延迟序列化可以在一定程度上减轻问题,但是从磁盘读取整行数据的开销是无法收回的。面向行的存储适用于需要同时处理整行数据的情况。

面向列:
将整个文件切割成几列数据,并将每列数据存储在一起:Parquet、RCFile、ORCFile。面向列的格式可以在读取数据时跳过不需要的列,适用于只有一小部分行在字段中的情况。但是这种读写格式需要更多的内存空间,因为缓存行需要在内存中(在多行中获取一列)。同时也不适合流式写入,因为一旦写入失败,当前文件无法恢复,而面向行的数据可以在写入失败时重新同步到上一个同步点,所以 Flume 使用面向行的存储格式。

Picture 1.(Left Side )Show the Logical Table and Picture 2. ( Right Side) Row-Oriented Layout(Sequence File)

Picture 3. Column-oriented Layout (RC File)

如果仍然不清楚什么是面向行和面向列,不要担心,你可以访问这个链接并知道它们之间的区别。

以下是一些在 Hadoop 系统上广泛使用的相关文件格式:

序列文件

存储格式因是否压缩以及是使用记录压缩还是块压缩而异:

The Internal structure of a sequence file with no compression and with record compression.

不压缩:
按照记录长度、键值长度、值度、键值、值值顺序存储。该范围是字节数。使用指定的序列化执行序列化。

记录压缩:
只对值进行压缩,并将压缩后的编解码器存储在头中。

分块压缩:
多条记录一起压缩,利用记录间的相似性,节省空间。在块的前后添加同步标志。块的最小值是由属性设置的 io . seqfile . compress . block size。

The internal structure of a sequence file with block compression

地图文件

MapFile 是 SequenceFile 的变体。在向 SequenceFile 添加索引并对其排序后,它是一个映射文件。索引存储为一个单独的文件,通常每 128 条记录存储一个索引。可以将索引加载到内存中进行快速查找——这些文件按照键定义的顺序存储数据。
映射文件记录必须按顺序写入。否则,将引发 IOException。

映射文件的派生类型:

  1. SetFile : 一个特殊的映射文件,用于存储一系列可写类型的键。钥匙是按顺序写的。
  2. ArrayFile: Key 是表示在数组中位置的整数,值可写。
  3. BloomMapFile: 使用动态布隆过滤器针对 MapFile get()方法进行了优化。过滤器存储在内存中,只有当键值存在时,才调用常规的 get()方法来执行读取操作。

Hadoop 系统下面列出的文件包括 RCFile、ORCFile 和 Parquet。Avro 的面向列版本是 Trevni。

RC 文件

Hive 的记录列式文件,这种类型的文件首先将数据逐行划分为行组,在行组内部,数据以列的形式存储。其结构如下:

Data Layout of RC File in an HDFS block

与纯粹的面向行和面向列相比:

Row-Store in an HDFS Block

Column Group in HDFS Block

兽人档案

ORCFile(优化记录列文件)提供了比 RCFile 更有效的文件格式。它在内部将数据划分为默认大小为 250M 的条带。每个条带包括一个索引、数据和页脚。索引存储每列的最大值和最小值,以及每一行在列中的位置。

ORC File Layout

在 Hive 中,以下命令用于使用 ORCFile:

CREATE TABLE ...STORED AAS ORC 
ALTER TABLE ... SET FILEFORMAT ORC 
SET hive.default.fileformat=ORC

镶木地板

基于 Google Dremel 的面向列的通用存储格式。尤其擅长处理深度嵌套的数据。

The internal Structure of Parquet File

对于嵌套结构,Parquet 将其转换为平面列存储,用重复级别和定义级别(R 和 D)表示,并在读取数据以重建整个文件时使用元数据来重建记录。结构。以下是研发的一个例子:

AddressBook {   
     contacts: {     
        phoneNumber: "555 987 6543"  
}   
 contacts: {   
} 
} 
AddressBook { 
}

现在,你知道 Hadoop 中不同的文件格式。如果您发现任何错误和建议,请随时与我联系。你可以通过我的 LinkedIn 联系我。

[## 忘记 API 用漂亮的汤做 Python 抓取,从 web 导入数据文件:第 2 部分

API 并不都是为你准备的,但是美丽的汤会永远伴随着你。

towardsdatascience.com](/forget-apis-do-python-scraping-using-beautiful-soup-import-data-file-from-the-web-part-2-27af5d666246)

新程序员的 7 大罪

原文:https://towardsdatascience.com/new-programmers-7-cardinal-sins-310615988944?source=collection_archive---------7-----------------------

面向非程序员的编程

提高编程技能的学习

Image from David Rangel available at Unsplash

当我发表文章 时,为什么每个工程师都应该开始考虑发展分析和编程技能? 我怎么也想不到它会对读者产生如此积极的影响。希望开始探索编程和数据科学领域的人向我寻求建议,以充分利用这一惊人的旅程;还有人问我下一篇文章的发布日期;还有许多人询问如何顺利过渡到这个职业。我非常希望在这段旅程中继续分享我的经历、学习、成功和失败,以帮助尽可能多的人过渡到充满无数好处和机会的职业生涯。给你,亲爱的读者:谢谢

-罗伯特

每一次向新职业的过渡都涉及到一个学习曲线;在完全适应新的工作环境之前,我们都必须经历一个过程。具有很强的适应能力和对变化的灵活性的人可能会发现它平滑而简单;其他的可能需要更多的时间和努力。不管你处于学术还是专业阶段,毫无疑问,向数据科学职业过渡将是一个挑战,在某种程度上,这是一个充满持续学习的无尽旅程。然而,迈出第一步是最重要的,但也是最困难的。基于我在数据科学领域的短暂职业生涯,我提出了以下新程序员的 7 " 基数 原罪";我从错误和失败中学到的教训,我希望有人能提前想到;帮助我成长并帮助我在实现目标的道路上更进一步的课程。希望你觉得它们有用…

1.一开始就没有一个初始策略

大多数没有计算机科学或数据分析背景的工程师想要在数据科学领域开始新的职业生涯,他们没有明确的战略,没有成为数据科学家、分析师或工程师的步骤。他们试图在没有真正深入具体话题的情况下,尽可能快地用信息填满自己的脑袋;他们倾向于一次注册多个在线课程,从不同的网站下载一些小抄,阅读许多作者的文章,但没有一个结构化的计划。在开始这段旅程之前,我会 高度 建议制定一个学习计划和一个日常习惯清单,努力实现你的目标,建立/加强你的分析和编程技能。自己研究你想从事的行业中最流行的编程语言和软件,搜索最广泛使用的库和软件包,并根据你的目标确定哪种编程语言和软件最适合你。坚持和练习会让你成为大师。

2.试图同时学习几种编程语言和软件

新程序员经常会受到诱惑,想同时学习几种编程语言和软件,并把它们作为技能写进简历。虽然你可能认为这是推销自己的一种策略,但往往会适得其反。拥有数据科学、数据分析师和数据工程职位的公司和组织更有可能要求候选人在一种或两种(最多三种)编程语言和软件方面具有强大而扎实的背景。很少有职位要求你同时精通 Python、R、SQL、C、C++、C#、Matlab、Java、Ruby 和 Go。取而代之的是,研究你在特定行业或公司更可能使用的编程语言和软件;掌握你的编程和分析技能,成为真正的专家。你会意识到所有的编程语言都有一个共同的逻辑和相似的功能,在此之后,从一种语言到另一种语言的转换只需要你学习不同的语法,而不是它背后的整个逻辑。

3.不要在代码上写注释行

尽管这听起来很明显,是一个无关紧要的任务,但它代表了一个很好的策略,可以跟踪每一行或者每一块代码在返回暂停的项目时所执行的操作。在最初的代码编写过程中,程序员对项目的目的和目标有清晰的认识;他们知道他们想要编码的程序背后的逻辑步骤和他们追求的结果。然而,由于多种原因(经济限制、信息缺失、优先级变化),所有项目都容易暂停,这将迫使程序员切换到不同的任务,使前一个任务暂停。恢复一个被中断的项目花费的时间越长,记住它被留在哪里以及它遗漏的点的机会就越小。这就是注释行发挥作用的地方。试着在你认为有必要的地方包含它们;记住要足够清楚,并牢记它们应该让代码程序员和执行者理解代码背后的逻辑步骤。

4.在编写代码的过程中不要求反馈

你的经理要求你做什么,她/他期望你做什么,客户要求什么,而你实际做了什么,这之间总是有巨大的差距。每当你开发一个程序或新代码时,试着把它分成几个阶段,并在进入下一个阶段之前寻求反馈。在每个阶段结束后获得反馈会让你知道你是否仍然在正确的轨道上,或者是否根据客户的要求需要做出改变。嘿,这并不意味着你不能理解你被要求做的事情,而是把它看作是利益相关者之间想法和期望的一致。你收到的反馈越多,如果偏离了方向,你需要修改的东西就越少。记住,持续的沟通对于每个项目的成功实施都是至关重要的。

5.不测试你目前的知识

你可能已经看过很多如何做和一步一步的编程教程。您可能也读过多本数据科学书籍和编程指南。你可能已经完成了很多来自 Udemy、Coursera 和 DataCamp 的编程训练营。猜猜接下来是什么?测试你目前的知识。这种训练营和课程的真正价值不是结业证书本身,而是你获得的知识和能够 成功应用 解决给定问题。说实话,每个人都可以通过跳过大部分讲座而不真正经历它们来注册在线课程,从而获得证书;公司和组织都意识到了这一点。尝试将自己推向新的极限,在网上寻找编程挑战,尝试头脑风暴的想法,并在没有太多帮助资源的情况下编写代码。这并不意味着你在实际工作中没有它们,但是它会让你感觉更舒服,更安全,更少依赖它们。

6.变得一致

在某些时候,你可能会觉得使用一种特定的编程语言和软件很舒服,但你可能会发现学习一种新的编程语言和软件毫无用处。我多次听到数据分析师争论哪种编程语言在能力、可用的库和包、在线资源和受欢迎程度方面是最好的。然而,你必须足够谦虚,认识到从另一种语言、库、包或软件中学习新东西的空间总是存在的。每种编程语言和软件都有其优点和缺点,但是我们的目标是充分利用它们的优点,并且足够灵活地确定哪种语言和软件最适合用于解决特定问题的特定任务。

7.假设你什么都知道

相信我,你不知道。没人知道。数据科学领域如此广泛,以至于每天都有学习新东西的空间。你能探索、使用和掌握的库、包、函数、方法和算法的总数真的很高。永远保持好奇,记得保持谦虚,因为你认为你知道的越多,实际上你知道的就越少。

— —

如果你觉得这篇文章有用,欢迎在 GitHub 上下载我的个人代码。你也可以直接在 rsalaza4@binghamton.edu 给我发邮件,在LinkedIn上找到我。有兴趣了解工程领域的数据分析、数据科学和机器学习应用的更多信息吗?通过访问我的媒体 个人资料 来探索我以前的文章。感谢阅读。

罗伯特

保护您的隐私,创建您自己的虚拟专用网络

原文:https://towardsdatascience.com/new-story-a6420a1f097?source=collection_archive---------13-----------------------

Hacking Scence.

当您的智能手机或笔记本电脑连接到不可信的网络(如酒店、咖啡店或图书馆的 WiFi)时,您是否希望安全可靠地访问互联网?一个虚拟专用网 (VPN)可以让你像在一个专用网上一样,安全地穿越不可信的网络。流量从 VPN 服务器流出,继续其到达目的地的旅程。

OpenVPN 是一款功能全面、开源的安全套接字层(SSL) VPN 解决方案,支持多种配置。在这个由两部分组成的教程中,我们将使用 digital ocean 在 Ubuntu 服务器上设置一个 OpenVPN 服务器,然后配置从 Android 对它的访问。本教程将使每个设置的安装和配置步骤尽可能简单。让我们从第一部分开始,它包括安装和配置的前五个步骤。

第一步:安装 OpenVPN 和 EasyRSA

这一步适用于 VPN 服务器和 CA 机器。我们开始更新我们的包索引并安装 OpenVPN。OpenVPN 在 Ubuntu 的默认存储库中可用,所以我们可以使用apt进行安装

$ sudo apt update 
$ sudo apt install openvpn

OpenVPN 是一种 TLS/SSL VPN。这意味着它使用证书来加密服务器和客户端之间的流量。为了发布可信证书,我们将设置简单的证书颁发机构(CA)。为此,我们将从项目的官方 GitHub 资源库下载最新版本的 EasyRSA,我们将部署它来构建我们的 CA 公钥基础设施(PKI)。

我们将在独立的服务器上构建 CA。这种方法的原因是,如果攻击者能够渗透到我们的服务器,他们将能够访问我们的 CA 私钥,并使用它来签署新的证书,使他们能够访问我们的 VPN。因此,从独立机器管理 CA 有助于防止未经授权的用户访问我们的 VPN。还要注意,作为进一步的预防措施,建议我们在不使用 CA 服务器来签署密钥时将其关闭。

为了开始构建 CA 和 PKI 基础设施,我们使用 wget 在我们的 CA 机器和 OpenVPN 服务器上下载最新版本的 EasyRSA。要获得最新版本,请进入官方 EasyRSA GitHub 项目的 发布页面,复制以.tgz结尾的文件的下载链接,然后将其粘贴到以下命令中:

$ wget -P ~/ [https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.4/EasyRSA-3.0.4.tgz](https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.4/EasyRSA-3.0.4.tgz)

然后提取 tarball:

$ cd ~ 
$ tar xvf EasyRSA-3.0.4.tgz

我们已经成功地在服务器和 CA 机器上安装了所有需要的软件。继续配置 EasyRSA 使用的变量,并设置一个 CA 目录,从中我们将生成我们的服务器和客户机访问 VPN 所需的密钥和证书。

第二步:配置 EasyRSA 变量并构建 CA 证书

我们将仅在 CA 机器上遵循这些说明。EasyRSA 安装了一个配置文件,我们可以编辑它来为我们的 CA 定义一些变量。在我们的 CA 机器上,导航到 EasyRSA 目录:

$ cd ~/Documents/EasyRSA-3.0.4/

这个目录中有一个名为vars.example的文件。我们制作了这个文件的副本,并将副本命名为vars,没有文件扩展名:

$ cp vars.example vars

我们使用我们首选的文本编辑器打开这个新文件,我们可以使用另一个编辑器,例如 nano 编辑器:

$ vim vars

查找为新证书设置字段默认值的设置。它看起来会像这样:~/Documents/EasyRSA-3.0.4/vars

. . .#set_var EASYRSA_REQ_COUNTRY    "US"
#set_var EASYRSA_REQ_PROVINCE   "California"
#set_var EASYRSA_REQ_CITY       "San Francisco"
#set_var EASYRSA_REQ_ORG        "Copyleft Certificate Co"
#set_var EASYRSA_REQ_EMAIL      "me@example.net"
#set_var EASYRSA_REQ_OU         "My Organizational Unit". . .

取消对这些行的注释,并将突出显示的值更新为我们喜欢的值,但我们不会将它们留空:~/Documents/EasyRSA-3.0.4/vars

. . .set_var EASYRSA_REQ_COUNTRY    "US"
set_var EASYRSA_REQ_PROVINCE   "NewYork"
set_var EASYRSA_REQ_CITY       "New York City"
set_var EASYRSA_REQ_ORG        "DigitalOcean"
set_var EASYRSA_REQ_EMAIL      "admin@example.com"
set_var EASYRSA_REQ_OU         "Community". . .

完成后,保存并关闭文件。在 EasyRSA 目录中有一个名为easyrsa的脚本,调用它来执行与构建和管理 CA 相关的各种任务。我们使用init-pki选项运行这个脚本,在 CA 服务器上启动公钥基础设施:

$ ./easyrsa init-pki

在这一点上,我们再次调用easyrsa脚本,在它后面加上build-ca选项。这将构建 CA 并创建两个重要的文件ca.crtca.key,它们构成了 SSL 证书的公共端和私有端。

  • ca.crt是 CA 的公共证书文件,在 OpenVPN 的上下文中,服务器和客户端使用该文件相互通知他们是同一个信任网络的一部分,而不是某人执行的中间人攻击。因此,我们的服务器和所有客户端都需要一份ca.crt文件的副本。
  • ca.key是 CA 机器用来为服务器和客户端签署密钥和证书的私钥。如果攻击者能够访问我们的 CA,进而访问我们的文件,他们将能够签署证书请求并访问我们的 VPN,从而影响其安全性。这就是为什么我们的文件应该只有在我们的 CA 机器上,并且理想情况下,我们的 CA 机器应该在不签署证书请求时保持离线,作为额外的安全措施。

如果我们不想每次与 CA 交互时都被提示输入密码,我们可以运行带有nopass选项的build-ca命令,如下所示:

$ ./easyrsa build-ca nopass

在输出中,我们将被要求确认我们的 CA 的通用名称:

通用名称是在证书颁发机构的上下文中用来指代该机器的名称。我们可以输入任何字符串作为 CA 的通用名称,但是为了简单起见,按下ENTER接受默认名称。这样,我们的 CA 就就位了,并准备好开始签署证书请求。

第三步:创建服务器证书、密钥和加密文件

我们将仅在服务器上遵循这些说明。现在我们已经有了一个准备好的 CA,我们可以从我们的服务器生成一个私钥和证书请求,然后将请求传送给我们的 CA 进行签名,创建所需的证书。我们也可以自由创建一些加密过程中使用的附加文件。首先导航到我们的 OpenVPN 服务器上的 EasyRSA 目录:

$ cd ~/Documents/EasyRSA-3.0.4/

从那里,用init-pki选项运行easyrsa脚本。虽然我们已经在 CA 机器上运行了这个命令,但是有必要在这里运行它,因为我们的服务器和 CA 将有单独的 PKI 目录:

$ ./easyrsa init-pki

然后再次调用easyrsa脚本,这次使用gen-req选项,后跟机器的通用名称。同样,这可以是我们喜欢的任何东西,但最好是描述性的。在本教程中,OpenVPN 服务器的通用名称将简单地称为服务器。一定要包括nopass选项。如果不这样做,将对请求文件进行密码保护,这可能会导致以后的权限问题:

$ ./easyrsa gen-req server nopass

这将为服务器创建一个私钥和一个名为server.req的证书请求文件。将服务器密钥复制到/etc/openvpn/目录:

$ sudo cp ~/Documents/EasyRSA-3.0.4/pki/private/server.key /etc/openvpn/

我们将仅在 CA 机器上遵循这些说明。使用一种安全的方法(比如下面例子中的 SCP ),将server.req文件传输到我们的 CA 机器:

$ scp -i ~/.ssh/id_rsa_do zaid@my_server_ip:~/Documents/EasyRSA-3.0.4/pki/reqs/server.req .

接下来,在我们的 CA 机器上,导航到 EasyRSA 目录:

$ cd ~/Documents/EasyRSA-3.0.4/

再次使用easyrsa脚本,导入server.req文件,遵循具有其通用名称的文件路径:

$ ./easyrsa import-req /tmp/server.req server

然后,我们通过运行带有sign-req选项的easyrsa脚本,后跟请求类型和通用名称,对请求进行签名。请求类型可以是clientserver,因此对于 OpenVPN 服务器的证书请求,请确保使用server请求类型:

$ ./easyrsa sign-req server server

在输出中,我们将被要求验证请求是否来自可信的来源。键入yes,然后按ENTER确认:

如果我们加密了 CA 密钥,此时会提示我们输入密码。接下来,使用一种安全的方法将签名的证书传输回我们的 VPN 服务器:

$ scp -i ~/.ssh/id_rsa_do pki/issued/server.crt zaid@my_server_ip:/tmp

在退出我们的 CA 机器之前,我们也将ca.crt文件传输到我们的服务器:

$ scp -i ~/.ssh/id_rsa_do pki/ca.crt zaid@my_server_ip:/tmp

我们将只在服务器上遵循这些说明。接下来,重新登录到我们的 OpenVPN 服务器,并将server.crtca.crt文件复制到我们的/etc/openvpn/目录中:

$ sudo cp /tmp/{server.crt,ca.crt} /etc/openvpn/

然后导航到我们的 EasyRSA 目录:

$ cd ~/Documents/EasyRSA-3.0.4/

在这里,通过键入以下命令创建一个强 Diffie-Hellman 密钥,以便在密钥交换期间使用:

$ ./easyrsa gen-dh

这可能需要几分钟才能完成,所以如果你在这里,我亲爱的读者,你可以喝杯茶,尽情享受。一旦完成,生成一个 HMAC 签名以增强服务器的 TLS 完整性验证能力:

$ openvpn --genkey --secret ta.key

当命令完成时,我们将两个新文件复制到我们的/etc/openvpn/目录中:

$ sudo cp ~/Documents/EasyRSA-3.0.4/ta.key /etc/openvpn/
$ sudo cp ~/Documents/EasyRSA-3.0.4/pki/dh.pem /etc/openvpn/

至此,我们的服务器所需的所有证书和密钥文件都已生成。我们已经准备好创建相应的证书和密钥,我们的客户机将使用它们来访问我们的 OpenVPN 服务器。

第四步:生成客户端证书和密钥文件

我们将只在服务器上遵循这些说明。虽然我们可以在客户机上生成私钥和证书请求,然后将其发送给 CA 进行签名,但本指南概述了在服务器上生成证书请求的过程。

这样做的好处是,我们可以创建一个脚本来自动生成包含所有必需的密钥和证书的客户端配置文件。这让我们不必向客户端传输密钥、证书和配置文件,并简化了加入 VPN 的过程。

最佳实践

我们将为本指南生成一个客户端密钥和证书对。如果我们有多个客户,我们可以对每个客户重复这个过程。但是请注意,我们需要为每个客户端的脚本传递一个唯一的名称值。在本教程中,第一个证书/密钥对被称为client1

首先,在我们的主目录中创建一个目录结构来存储客户端证书和密钥文件:

$ mkdir -p ~/client-configs/keys

由于我们将在此目录中存储客户端的证书/密钥对和配置文件,因此作为一项安全措施,我们现在应该锁定其权限:

$ chmod -R 700 ~/client-configs

接下来,导航回我们的 EasyRSA 目录,运行带有gen-reqnopass选项的easyrsa脚本,以及客户端的通用名称:

$ cd ~/Documents/EasyRSA-3.0.4/
$ ./easyrsa gen-req client1 nopass

ENTER确认常用名。然后,将client1.key文件复制到我们之前创建的/client-configs/keys/目录中:

$ cp pki/private/client1.key ~/client-configs/keys/

接下来,使用安全方法client1.req文件传输到我们的 CA 机器。我们将仅在 CA 机器上遵循这些说明。

$ sudo scp -i ~/.ssh/id_rsa_do zaid@my_server_ip:~/Documents/EasyRSA-3.0.4/pki/reqs/client1.req .

我们导航到 EasyRSA 目录,并导入证书请求:

$ cd ~/Documents/EasyRSA-3.0.4/
$ sudo ./easyrsa import-req /tmp/client1.req client1

然后像我们在上一步中对服务器所做的那样对请求进行签名。不过,这次一定要指定client请求类型:

$ cd pki/reqs
$ sudo chown zeyd:zeyd client1.req
$ ./easyrsa sign-req client client1

在提示符下,输入yes以确认我们打算对证书请求进行签名,并且它来自受信任的来源。同样,如果我们加密了 CA 密钥,这里会提示我们输入密码。这将创建一个名为client1.crt的客户端证书文件。将此文件传输回服务器:

$ scp -i ~/.ssh/id_rsa_do pki/issued/client1.crt zaid@my_server_ip:~/client-configs/keys/

我们将只在服务器上遵循这些指示。接下来,我们也将ca.crtta.key文件复制到/client-configs/keys/目录:

$ cp ~/Documents/EasyRSA-3.0.4/ta.key ~/client-configs/keys/
$ sudo cp /etc/openvpn/ca.crt ~/client-configs/keys/

这样,我们的服务器和客户机的证书和密钥都已生成,并存储在服务器上的适当目录中。仍然需要对这些文件执行一些操作,但是这些将在后面的步骤中进行。现在,我们可以继续在我们的服务器上配置 OpenVPN。

第五步:配置 OpenVPN 服务

我们将仅在服务器上遵循这些说明。现在,我们的客户机和服务器的证书和密钥都已经生成,我们可以开始配置 OpenVPN 服务来使用这些凭证。首先将一个示例 OpenVPN 配置文件复制到配置目录中,然后提取它,以便将其用作我们设置的基础:

$ sudo cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn/
$ sudo gzip -d /etc/openvpn/server.conf.gz

在我们首选的文本编辑器中打开服务器配置文件:

$ sudo vim /etc/openvpn/server.conf

通过查找tls-auth指令找到 HMAC 部分。这一行应该已经被取消了注释,但是如果没有,那么删除"“取消注释。在这一行下面,添加key-direction参数,设置为" 0":/etc/openvpn/server.conf

tls-auth ta.key 0 # This file is secret
key-direction 0

接下来,通过查找注释掉的cipher行,找到关于加密算法的部分。AES-256-CBC密码提供了很好的加密级别,并得到了很好的支持。同样,这一行应该已经被取消了注释,但是如果没有,那么就删除""前置:/etc/openvpn/server.conf

cipher AES-256-CBC

在此之下,添加一个auth指令来选择 HMAC 消息摘要算法。为此,SHA256是个不错的选择:/etc/openvpn/server.conf

auth SHA256

接下来,找到包含定义 Diffie-Hellman 参数的dh指令的行。由于最近对 EasyRSA 进行了一些更改,Diffie-Hellman 密钥的文件名可能与示例服务器配置文件中列出的不同。如有必要,通过删除2048来更改此处列出的文件名,使其与我们在上一步中生成的密钥一致:/etc/openvpn/server.conf

dh dh.pem

最后,找到usergroup设置,去掉"在每一行的开头取消对这些行的注释:/etc/openvpn/server.conf

user nobody
group nogroup

到目前为止,我们对样本server.conf文件所做的更改对于 OpenVPN 的运行是必要的。下面列出的更改是可选的,尽管它们对于许多常见用例来说也是必需的。

在 Udemy 上查看我们的免费课程。

感谢阅读。如果你喜欢这篇文章,请点击下面的按钮,这样我们就可以保持联系。

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

图像处理新手?

原文:https://towardsdatascience.com/new-to-image-processing-5aa5200aa895?source=collection_archive---------36-----------------------

本文将总结最基本和最简单的图像处理技术,如 RGB 提取、对象标记,并展示对图像应用不同类型的滤镜后会发生什么。

下面例子的环境是用 Octave interpreter for Linux 在 Octave 中完成的。

RGB 与 HSV 提取

Figure 1. The Comparison Extracting the original image with RGB vs HSV

图像提取可以通过两种方法完成,直接从 RGB 颜色模型或通过转换到 HSV 模型。

为了在 RGB 颜色模型中只提取花的黄色像素,我们将不得不考虑红色、绿色和蓝色的近似值。然后对这 3 个值应用阈值。

然而,在 HSV 模型中,我们只需要对强度值应用阈值来提取花部分。色调和饱和度可以忽略不计。

标注对象

此图像中有 3 个以上的对象,我们希望用大于 200 像素的连接像素来标记每个对象。

Figure 2. Trying to label different objects in the original image.

1)我们需要创建一个 3×3 大小的结构元素,以便稍后进行侵蚀和扩张。

2)创建一组与输入图像大小相同的空白矩阵。[在这种情况下,我创建了 5 个空白矩阵,称为标签。]

3)从输入图像中,我们需要找到值为“1”的第一个像素位置,并从该点开始膨胀。这将提取第一个对象。

4)检查对象是否包含至少 200 个像素。然后将值从“1”替换为“2 ”,如标记我们的对象编号,并将该数据存储在第一个空白矩阵中。

5)在原始图像中,将所有已标记的值设置为“0”。然后为我们的下一个对象找到下一个起点。

6)重复迭代,直到原始图像被替换为“0”值,或者直到它为空。

过滤器

噪声是处理图像时的主要问题之一。使用正确的过滤方法消除噪声有助于获得更清晰的图像输出。

过滤可以分为两个领域:

1)空间域

2)频域

Figure 3. A process chart to compare spatial filters and frequency filters.

在空间域中,通常为 3×3 或 5×5 的遮罩被创建并应用于原始图像中的第一个像素,直到最后一个像素。因为在空间域中,遮罩的中心值至关重要,所以我们需要在输入图像的边界周围实现填充算法。

Figure 4. Explains the equation for spatial filtering.

空间域中的滤波

使用均值和平均滤波器的空间滤波示例

Figure 5. The result of applying a Mean filter VS using the existing function in Octave.

下面的代码比较了两种过滤方法的编译时间,一种是自己编写函数,另一种是使用 Octave 库中现有的函数。

在 DIY 滤镜输出中,我使用了

1 0 1
1 -4 1
0 1 0

(均值滤波器)作为过滤遮罩。

频域滤波

定义

  • 这些技术基于修改图像的光谱变换
  • 将图像转换为其频率表示
  • 执行图像处理
  • 计算回到空间域的逆变换
  • 高频对应于图像中快速变化的像素值(如文本、纹理、树叶等)。)
  • 强低频分量对应于图像中的大尺度特征(例如,主导图像的单个同质对象)

技术

  • 傅里叶变换
  • 非周期但曲线下面积有限的函数可以表示为正弦和/或正弦乘以权函数的积分

Figure 6. Shows the equation of Fourier Transform and Inverse Fourier Transform for filtering the image in a Frequency Domain

使用高斯和理想滤波器的低通滤波输出示例

Figure 7. The image on the left is the original image and the image on the right shows the result after applying the Lowpass filter.

Figure 8. Shows the output of the image after applying the Ideal Lowpass filter to the original image.

频域高斯滤波:

[使用 fspecial()和截止频率= 100]

频域中的理想低通滤波

[使用 meshgrid(),截止频率=最大距离的 67%]

机器学习新手?尽量避免这些错误

原文:https://towardsdatascience.com/new-to-machine-learning-try-to-avoid-these-mistakes-d54a164e2316?source=collection_archive---------23-----------------------

作为一名数据科学家,我艰难地学到了一些东西

机器学习是计算机科学中最热门的领域之一。如此多的人抱着这样一种错误的想法,即仅仅运行 10 行 python 代码,并期望事情在任何情况下都能神奇地工作。这篇博客是关于我艰难地学到的所有东西。希望它能为你节省一些犯同样错误的时间。

1.你不应该相信这是魔法

机器学习就像任何科学领域一样:它有自己的规则、逻辑和局限性。相信这是某种黑魔法无助于提高你的人工智能技能。这种信念将与你理解每个模型/层类型如何工作所需的科学好奇心相抵触。相信这是魔法是一种懒惰的方式来说服自己为什么不需要理解背后运行的机制。

ML 唯一神奇的地方就是背后没有魔法。它基于纯粹的逻辑、数学,当然还有一些随机性和运气…

Machine learning is magical but NOT magic

2.不要从真实的数据集开始

从真实世界的数据集开始,充满了问题和噪音不会帮助你寻求理解。取而代之的是,生成一些理想的伪数据集。例如,首先创建一个随机 x 列表和一个 y=3x+2 列表,然后测试密集层将如何学习权重 3 和偏差+2。

这允许你逆向工程反向传播背后的机制,不同的优化器,不同的初始化方法,看看模型是否收敛得足够快。逆向工程是一种有趣的方式来理解事物是如何工作的,而不需要进入复杂的数学细节。(但如果可以,何乐而不为!)

每当试图解决一种新类型的问题时,首先尝试思考是否有办法首先生成一个理想的、无噪声的、假的数据集,以便检查哪种类型的层或 ML 模型将更容易解决这一挑战。如果一个模型不能解决这个假的/简单的挑战,那么在一个更难的嘈杂的数据集上尝试它甚至没有意义。

3.不要从庞大的数据集开始

立即将整个数据集投入到模型中,然后等待几个小时才能得到第一个结果,这是适得其反的。相反,最好从一小部分数据开始,先用不同的模型进行实验。一旦你得到了最初的第一个结果,你就可以去大数据。

Go step by step

4.首先可视化/清理数据

理解你的数据集是成功的关键点和主要因素,清理数据是 ML 中最重要的步骤之一。找出数据收集、存储、频率等方面的问题非常重要。可视化数据集有助于识别许多问题。数据是否包含大量缺失值?如何替换它们?数据采样速率相同吗?特征需要规范化吗?特征是否独立?我们需要先运行 PCA 吗?或许数据科学中最重要的原则如下:

Shit IN -> Shit OUT principle

5.特征的数量并不重要,重要的是维度的数量。

具有 100 个特征的数据集(其中所有特征都是线性相关的)可以有效地减少到只有 1 个特征,而不会丢失数据。了解特征和维度的区别对降低数据集的复杂性有很大帮助。

6.小心数据泄漏或扭曲的数据

神经网络以其欺骗和懒惰地学习我们不想让它们学习的东西的能力而闻名。例如,如果类别之间存在很大差异,假设 99.99%的邮件不是垃圾邮件,0.01%是垃圾邮件,那么神经网络很有可能会一直懒洋洋地学习对非垃圾邮件进行分类。另一个问题是数据泄露:

当您希望使用模型进行预测时,任何其值实际上不可用的特征,都是会给模型带来泄漏的特征。

当你用来训练机器学习算法的输入数据恰好拥有你试图预测的信息 —丹尼尔·古铁雷斯问数据科学家:数据泄露

因此,请确保没有简单的方法来作弊,并在输入和输出之间找到简单但无意义的相关性。

Take care of leakage

7.快速迭代,更快失败

在看了这个关于棉花糖挑战的视频后,我得到了这个观点的灵感:

Marshmallow challenge

教训是不要假设你最初的模型想法会起作用,你可能会错误地认为,你越快发现这一点,你就越快尝试其他东西,而不会浪费太多时间,达到最后期限或在发现真相之前支付巨额云计算账单。

拥有一个足够快的地面模型是一个关键点,剩下的时间可以用来改进结果和更新“到目前为止”最好模型的记录。但关键是不要等到最后一刻才验证结果。

8.小心不要过度装配

为一个训练阶段 0 亏的模特感到骄傲是很有诱惑力的。然而,它可能不是真实世界的最佳模型。这是一个众所周知的过拟合问题

Over-fitting illustrated

9.不要从复杂的 ML 模型开始

不要直接使用一个 双向 LSTM 变分自动编码器与 注意机制模型 ,如果你的问题已经可以简单地使用一个线性密集层解决。

Tensorflow 很强大,但你可能不是

最好是先从简单的模型开始,你可以理解和控制,然后逐渐增加复杂性,以检查复杂性是否带来任何附加值。请记住,最后,模型越复杂,就需要越多的数据来真正验证模型没有过度拟合。

一个好的经验法则是跟踪模型中参数的数量与数据集大小的关系。如果您的模型参数数量大于您的数据集大小,这将触发一个自动警告!

Don’t go full complexity

10.不要犹豫,创建一个定制的损失函数

机器学习的目标是减少损失函数。在许多情况下,缺省值(RMSE,对数损失)就足够了。但是很多人害怕为一些具体问题定义自己的损失函数。

损失函数可以被看作是你希望 ML 模型实现的惩罚或奖励。因此,如果您希望 ML 模型收敛到特定行为,可以通过创建一个损失函数来实现,该函数奖励这种行为,同时惩罚针对您的特定问题和特定数据集的不当行为。

Machine learning is like a child — It needs guidance, through loss functions

结束点——投资

机器学习的最佳投资是在知识上,你越了解每一层的抽象角色、每一个功能背后的机制、局限性,就越容易更快地创建模型。

第二个最好的投资,是在一个专用的 硬件上进行机器学习。一个 300 美元的 GPU 可以加速高达 20 倍的培训工作量,这意味着一天的工作可以减少到一个小时,同样的数据科学家工程师可以在相同的时间内尝试 20 倍以上的模型。

最后一点:

永远不要低估娱乐的重要性。

如果你喜欢阅读,请关注我们: 【脸书】 推特 LinkedIn

原载于 2019 年 7 月 19 日 https://medium.com**的

人工智能经济的世界新秩序

原文:https://towardsdatascience.com/new-world-order-of-the-ai-economy-a9fa40375ba8?source=collection_archive---------20-----------------------

结合其他全球趋势,人工智能正在迅速拆除建立新世界秩序的旧壁垒。因此,下一个世纪将由迅速适应新人工智能经济的国家主导。如果中国不能适应人工智能经济,下一个世纪将是“中国世纪”的假设可能被证明是错误的。

人工智能经济建立在三大支柱之上:

  1. 人工智能劳动力:拥有广泛技能的劳动力资源,包括人工智能研究人员、人工智能实施者和精通机器人和自动化的人工智能工作者
  2. 人工智能基础设施:需要数据共享、算法交换、劳动力流动和低成本能源来支持持续的人工智能创新
  3. 人工智能社会契约:工人失业将产生巨大的阻力。再培训、保证收入计划和其他转型成本将被采用人工智能经济的领先国家吸收

Pax Britannica (1815- 1914) — Map reproduction courtesy of the Norman B. Leventhal Map & Education Center

旧世界订单:

自 19 世纪初以来,英国统治下的和平(1815-1914)、美国世纪(1917-2017)和中国世纪(2017 年至今)的出现(或可能再次出现)都是由类似的经济和政治规则推动的。

1.容易获得的低成本劳动力、能源和原材料

2.机构和政府对工业的支持,提供了获得资本、政治稳定和国际贸易的机会

3.持续创新推动边际生产成本下降,工人生产率提高,支持生活水平的提高

自 1800 年以来,包括电报、蒸汽动力、电力、装配线、自动化和最近的机器人技术在内的新技术的迅速采用为早期采用者带来了持久的优势和在世界舞台上的优势。

随着中国准备承担下个世纪的经济霸权,或许规则已经改变。重要的是,根据杰里米·里夫金(2015 年)的说法,能源成本正迅速走向“零边际成本”,正如 T2·法里德·扎卡利亚(2009 年)在其著作《后美国世界》(The Post American World)中首次概述的那样,军事和政治权力的不断扩散正在降低超级大国游戏的新参与者的壁垒。

最根本的规则变化是人工智能(AI)的主流采用,以及在自动化、效率和准确性方面实现人工智能驱动的巨大生产力增益。AI 和自动化从根本上改变了以前世界秩序的经济基础。

  1. 数字工作者是在云中或桌面计算机上作为程序运行的重复任务的机器人,这与 1999 年科幻电影《黑客帝国》中的角色并非完全不同。这通常被称为机器人流程自动化,但新一代数字工人正在使用计算机视觉和先进的机器学习来执行工作,速度是传统人类工人的 100 倍
  2. 体力工作越来越多地使用工业机器人来代替人类工人。计算机视觉和机器人技术的进步正在迅速缩小只能由人类完成的事情的范围。机器人的应用正在飞速发展,即使是在低成本劳动力仍然充足的市场
  3. 用模糊事实做出的复杂决策长期以来一直是人类主题专家的领域,他们的有机神经网络大脑可以考虑所有数据,并在瞬间做出最佳决策。如今,这一优势正在缩小,深度学习系统在认知、视觉、翻译、信号处理、复杂系统分析和无数其他任务方面一直优于人类

构建人工智能经济:

第一优先:人工智能劳动力

对人工智能和机器人技术工人的需求已经远远超过了目前的供应。随着人工智能经济的发展,这种阻抗不匹配将成为创新的一个门控因素。为了避免这种情况,我们需要立即投资调整我们的劳动力。正如李开复在他的书《人工智能超级大国:中国、硅谷和世界新秩序》中概述的那样,中国已经在创造“人工智能城市”,并在中国政府的全力支持下建设这种人工智能能力。未来的领导者需要通过以下方式打造这种力量:

  • 招募并留住(国内)最优秀的人工智能人才到大学从事研究并支持本科人工智能教育。资助人工智能领域的研究生研究,包括拨款、挑战和以行业为重点的联合创新项目
  • 拓宽科学、工程和数学本科学位要求,以包括核心人工智能教育和实践经验
  • 资助机器人和机电培训项目技术和两年制学院,并与工业机器人供应商紧密合作

根据“新美国安全中心”的论文了解中国的人工智能战略,中国目前正在这一领域进行大量投资,在人工智能研究方面排名第一,在人工智能专利方面排名第一,在人工智能风险投资方面排名第一,在人工智能公司数量方面排名第二,在最大的人工智能人才库方面排名第二

第二优先:人工智能基础设施

最近关于人工智能的新闻一直集中在与数据收集和使用相关的隐私问题和偏见上。从为训练虚拟助理而收集的个人数据,到人工智能评估购物者的犯罪意图,显然任何问题都有待解决。中国已经采取了一种权宜的数据收集方法,并可以利用这种方法超越其他全球人工智能竞争对手。

  1. 国家数据共享计划对于建立下一代人工智能所需的训练集至关重要——西方需要迅速解决隐私和伦理问题
  2. 开放算法交换以及商业算法交换将是一个关键的成功因素。知识产权法将需要适应,以促进思想和 ML 模型的流动
  3. 劳动力的流动性和低成本的能源将需要支持持续的人工智能创新

正如这篇 IEEE 文章中所详述的,我们已经看到商业形式只是为了弥补这些数据差距:IEEE Spectrum 文章但是这些模型存在很多商业摩擦

第三优先:AI 社会契约:

最近的全球政治和经济状况加剧了世界各地的民族主义和移民问题。这在一定程度上是因为工作场所的自动化开始取代工人。领先的人工智能经济学将通过人工智能优化的社会结构或安全网来解决这些社会问题,以避免政治摩擦

  1. 中年工人的再培训和技能提升,加上从衰退行业分流年轻工人,将是继续成功的关键
  2. 为无法重新获得技能的工人提供有保障的收入计划,将缓解变革阻力,维护社会秩序

数据科学家的新年决心

原文:https://towardsdatascience.com/new-years-resolutions-for-data-scientists-43a0d3d8b4ff?source=collection_archive---------17-----------------------

更好的项目和更干净的代码的新十年指南

今天是反思过去 364 年并宣布自我完善的传统日子。

这是多事之秋。像伯特这样的模特震撼了传统领域;Kubernetes 和 Docker 联手了;公司因使用有偏见的算法进行商业决策而受到抨击;争议搅乱了数据科学训练营;职位描述需要不断扩展的不相关技能。比以往任何时候都清楚的是,我们的行业是一个多面性的行业,在这个行业中,保持稳定和相关性是一项挑战。

这里有 10 条建议,每条都有助于你成为一名数据科学家和程序员,并提供有用的资源,还有 6 条可以帮助你在这个过程中保持理智:

通用编程

Photo by Denis Pavlovic on Unsplash

  1. 我将让(我的 python 路径)成形。
  2. 我将清理环境(而不是pip install每个包都要同一个)。
  3. 我会学一门新的语言。
  4. 为了更好的数据序列化,我将放弃 pickle T8。
  5. 我将设定健康的界限(与容器化)。
  6. 我会写干净,优雅的代码。
  7. 我将学习足够的 C 语言在 Python 崩溃时修复它(或者至少理解它为什么会崩溃)。
  8. 我将实际上 学会如何负责任地获得。
  9. 我将学习 bash 成为命令行向导。
  10. 我将扩展我的研究工具箱以便更好地调试。

数据科学、机器学习和人工智能

Photo by h heyerlein on Unsplash

  1. 我会关注机器学习中的偏差,争取从我的数据中消除。
  2. 我会问为什么事情会起作用,而不仅仅是它们会起作用。我会批判性地评估预先训练好的模型,而不是天真地使用它们。
  3. 如果我更倾向于实践,我会学习一些理论上的东西——比如我的模型背后的数学。
  4. 如果我更学术一点,我会动手做一些的东西,不会让完美主义阻止我推出产品。
  5. 我会加入一个以数据科学为导向的 Slack ,Discord,或者 IRC 频道去认识新同事。
  6. 我会参加聚会或会议(或者至少在线观看视频)来增长我的技能。
  7. 我会将我的模型可视化,或者将它们部署到 web 应用中,这样更多的人可以使用和理解它们。
  8. 我会交叉训练我的大脑,提高我的领域知识。(对于 NLP 工程师,我推荐学习语言学。)
  9. 我将在我不擅长的领域做一个项目——如果我经常与数字打交道,就使用非结构化数据;如果我经常与文字打交道,就尝试计算机视觉。(甚至可能制作一些艺术!)
  10. 我会在社交媒体上关注一些令人敬畏的人工智能从业者。

普遍建议

Photo by Lindsay Henwood on Unsplash

无论你想在今年做得更好,这里有一些基本的决心,为你的成功打下基础:

  1. 我会优先考虑每晚至少睡 8 个小时,因为睡眠对学习来说是必不可少的。
  2. 我会每天花时间运动身体,吃有营养的食物,因为健康对成功至关重要。
  3. 我会找到适合我的压力管理技巧,因为我的心理健康和我的身体健康以及职业道德一样重要。
  4. 除了工作和学习,我会花时间做自己喜欢的事情,因为成为一个快乐、全面发展的人不仅有利于提高生产力,也是生活的意义所在。
  5. 我会记住,我作为一个人的价值与我的求职、我的 Kaggle 分数或任何其他成功的外部衡量标准无关。在这个行业里很容易精疲力竭,灰心丧气。我会尊重我的步伐和进步。
  6. 如果我感到沮丧、焦虑或孤独,我会向我的朋友和同事求助。我们都在这个一起。

后知后觉是 2020 年。从你的错误中吸取教训,确定你需要强化的地方,并制定一个计划,在这一年中改进。

但是试着享受这个过程。

纽约出租车数据集分析

原文:https://towardsdatascience.com/new-york-taxi-data-set-analysis-7f3a9ad84850?source=collection_archive---------14-----------------------

用回归模型预测出租车费用

Photo by Anders Jildén on Unsplash

最近我有机会玩了一下谷歌云的大查询平台托管的纽约出租车公共数据集。我决定对数据集应用机器学习技术,尝试使用 Python 建立一些预测模型。在这篇文章中,我将尝试预测出租车费用。让我们直接开始吧!本文的所有代码都可以在 Github 的链接中找到

Google Big Query Tables

首先,在检查 Google 大查询表时,我们注意到每年有一个表。这给了我一个想法。我可以使用 2015 年的数据来训练我的机器学习模型,然后使用 2016 年的数据来测试模型的预测能力。

接下来,让我们使用 Google 的 data lab 平台查询 2015 年的随机 100K 行和 2016 年的随机 100K 行。

现在,让我们开始预测出租车费用的过程。首先,让我们导入必要的包并将数据加载到 pandas 数据框中。我使用%matplotlib 内联,因为我使用 jupyter 笔记本进行分析。

从数据框中,我们看到每一行都是一次旅行,而每一列都是与旅行相关的属性。

直觉:

我喜欢首先纯粹凭直觉建立一个预测模型来开始我的项目。这个简单直观的模型将给出我们的基线精度,我们将尝试使用更先进的技术来打破这个基线精度。

对于任何预测模型,我们需要考虑我们试图预测的响应变量是什么,以及可能对所述响应产生影响的特征变量是什么。在本练习中,我们想要预测的响应是 fare_amount 。纯粹从直觉的角度来看,我们知道出租车一般按固定的初始费用+每公里 a(总距离)+每分钟 a(总时长)收费。回头看看我们的数据框列,我们已经有了一个 trip_distance 列,但是我们缺少一个 trip_duration 列。但是,我们提供了接送日期时间,因此我们可以使用下面的这些列轻松计算出 trip_duration

现在,让我们为简单直观的模型( fare_amounttrip_distance、trip_duration )可视化感兴趣的列。

Visualizing the columns of interest for simple intuitive model

从图表中可以看出,所有三列都有显著的异常值。让我们执行一个离群点删除,并再次绘图。

Visualizing the columns of interest after outlier removal for simple intuitive model

好多了!此外,我们可以清楚地看到票价 _ 金额行程 _ 距离行程 _ 持续时间之间有很强的相关性,因此我们是在正确的轨道上。

在我们继续之前,让我们创建一些助手函数。第一个功能是拆分数据,以便训练数据集只包含 2015 年的数据,测试数据集只包含 2016 年的数据,如前所述。第二个功能是计算一些可用于评估模型预测能力的统计数据。在本练习中,我选择的统计数据是均方根误差(RMSE),它给出了实际费用 _ 金额和预测费用 _ 金额之间的差异的标准偏差,单位为美元,可以计算为 sklearn 的均方误差()的平方根。R-square 给出了模型预测的实际 fare_amount 的变化量的百分比,可以直接从 sklearn 的 r2_score() 中获得。

太好了!现在,我们已经准备好完全凭直觉构建我们的第一个模型。让我们首先将数据分为响应(y)和特征(X),然后使用上述帮助函数创建训练集和测试集,然后在训练数据集上拟合简单的线性回归模型,最后使用上述帮助函数检查模型结果。

----Training Data results (2015 data set)----
RMSE: $5.6
R2: 0.79

----Test Data results (2016 data set)----
RMSE: $5.5
R2: 0.81

对我们的第一次尝试来说还不错!测试数据集的 RMSE 为 5.5 美元,我们将使用它作为基线得分。现在,让我们努力提高这个分数。

特征工程:

我在这里采用的方法是通过特征工程的过程给模型增加更多的特征。对问题进行更深入的思考。

  • 一周中的取件日和一天中的时间可能在需求和交通状况中发挥重要作用,从而对票价产生影响
  • 纬度差和经度差可以是增加行程距离对费用影响的附加数据
  • 由于特定位置的额外费用,上下客社区可能会对票价产生影响?

所以,让我们添加一些额外的功能如下。Geohashing 是一种基于绝对纬度和经度创建离散地理位置的方法。您可以将它视为为属于同一邻域的位置创建一个通用名称。我使用 pygeohash python 包,可以使用pip install pygeohash安装。由于纬度和经度列中有许多缺失的数据,让我们也删除它们。新增功能包括:

  1. 提货月份
  2. 一周中的提货日
  3. 一天中的取件时间
  4. 纬度差
  5. 经度差
  6. 地理哈希拾取位置
  7. 地理哈希删除位置

看起来在 lat_diflon_dif 中有一些异常值,我们把它们去掉吧。此外,由于像 month、day_of_week、hour_of_day、pickup_geohash 和 dropoff_geohash 这样的列是分类的,所以让我们使用 pandas get_dummies 方法对它们进行编码。

Visualizing the features

现在,让我们拆分训练和测试数据集,并拟合一个简单的线性回归模型

----Training Data results (2015 data set)----
RMSE: $3.5
R2: 0.92

----Test Data results (2016 data set)----
RMSE: $7139352.0
R2: -338832003532.88

呀!该模型在训练数据集上具有更好的 RMSE,但在测试数据集上具有更差的 RMSE,这表明该模型过度拟合。这就需要使用正则化技术。我们可以用 sklearn 的 Lasso 回归进行正则化。

----Training Data results (2015 data set)----
RMSE: $5.6
R2: 0.79

----Test Data results (2016 data set)----
RMSE: $5.3
R2: 0.82

好吧,从过度拟合的角度来看,这更好,但 RMSE 模型并没有改善太多。让我们现在尝试超参数调整,以改善模型 RMSE。我们可以为 Lasso 回归调整的参数称为 alpha,它是一个乘以 L1 罚项的常数。alpha 的默认值是 1。较小的 alpha 将通过减少惩罚项使 Lasso 回归类似于线性回归。

因为我们使用套索回归,有两种方法来执行阿尔法超参数调整。第一种方法是使用 sklearn 的通用 GridSearchCV,它可以用于调整任何机器学习模型。第二种方法是使用 sklearn 自己的 LassoCV,它专门用于 Lasso 回归。让我们两个都试试,比较他们的运行时间,以及每个人能找到的最好的阿尔法。

首先,让我们运行 GridSearchCV 方法:

GridSearchCV execution time: 3124.58699989Lasso best params: {'alpha': 0.0004012807031942776}

----Training Data results (2015 data set)----
RMSE: $3.7
R2: 0.91

----Test Data results (2016 data set)----
RMSE: $3.8
R2: 0.90

哇!当 alpha 值为 0.0004 时,我们能够获得仅 3.8 美元的测试 RMSE!然而,GridSearchCV 方法的运行时间长达 3124 秒。差不多一个小时了!让我们看看 LassoCV 是否能跑得更快,但为我们提供可比较的结果。请注意,我们将对 LassoCV 使用相同的 alpha 搜索空间,以实现真正的面对面比较。

LassoCV execution time: 42.0979998112LassoCV best params: 0.000401280703194

----Training Data results (2015 data set)----
RMSE: $3.7
R2: 0.91

----Test Data results (2016 data set)----
RMSE: $3.8
R2: 0.90

太棒了。LassoCV 不仅为我们提供了相同的最佳 alpha 值 0.0004,以获得仅 3.8 美元的测试 RMSE,而且它的运行速度更快,可以在 42 秒内完成!我必须承认,我自己也对结果感到惊讶,并且必须深入研究才能理解为什么 LassoCV 比 GridSearchCV 跑得快得多。目前,看起来我们使用线性模型可以达到的 RMSE 的最佳测试分数是 3.8 美元。这比我们简单直观模型的 RMSE 低 1.7 美元!最后,让我们绘制实际票价与 LassoCV 模型预测票价的对比图,以直观地检查相关性

Actual vs Predicted Fare using LassoCV tuned model

太好了!那表情很有希望。

我们可以通过尝试更复杂的模型,如梯度增强,甚至是神经网络,来进一步改善模型的 RMSE。我们还可以通过查询 100 万行而不是 10 万行来将更多的数据添加到训练集中。你怎么想呢?请就我们如何进一步改进该模型发表评论。

感谢您的阅读!希望你觉得有趣。干杯!

使用机器学习的新闻和媒体偏见检测

原文:https://towardsdatascience.com/news-and-media-bias-detection-using-machine-learning-a-potential-way-to-find-fake-news-13c766aa3988?source=collection_archive---------27-----------------------

媒体。在美国,这一直是一个有分歧的问题,由于新闻业内隐含的偏见,媒体和报纸对关键话题的报道有所不同。我听说过隐性偏见,但它们是什么?从本质上讲,大型报纸机构撰写的文章往往反映了作者的继承观点,尤其是因为新闻机构往往更喜欢来自政治光谱某一领域的作者。现任美国总统唐纳德·j·特朗普(Donald J. Trump)一贯创造不同的观点:保守派人士更有可能以有利的方式报道特朗普的行动,而自由派媒体则倾向于以负面的方式描绘特朗普的行动。因此,很明显,媒体渠道在关键问题上存在很大的分歧和偏见——但如果我们能够直接识别任何新闻文章中的偏见,会怎么样呢?

Simplified representation of the American political spectrum: liberal sources tend to report more negatively about Donald Trump, while conservative sources tend to report more positively

数据。有大量数据代表了媒体的偏见——我发现 ProQuest 报纸数据库中有来自许多新闻来源的数千篇关于唐纳德·特朗普的文章。我还意识到,我可以使用媒体偏见/事实核查这个识别主要新闻来源的政治偏见的最大网站,合理地确定一个足够大的新闻机构的总体政治倾向。有了如此大量的数据,有一个很好的方法来看看我是否可以分析这些偏见的文章——机器学习。

机器学习。通过利用神经网络并充当人工大脑,机器能够在最少人工参与的情况下在大数据集中找到模式(当有数百万个数据点时,这真是太棒了!).由于可用数据和计算能力的增长,机器学习最近出现了巨大的增长。研究人员还一直在努力制造越来越多层的更复杂的神经网络(深度学习),这使他们能够解决更困难的问题。机器学习本身在几乎所有可以想象的领域都有一堆应用;机器学习的最新进展包括自动驾驶汽车、语言翻译和面部识别。我之前使用机器学习来预测加密货币价格(链接,并生成鞋子设计(链接)。这一次,我将使用它来识别文章的新闻来源,并预测文章中的偏见。现在来研究一个更具体的神经网络架构…

A simple feedforward neural network

LSTM 细胞。一个特别的神经网络是寻找模式的真正革命性的方法,它是来自本文的长短期记忆(LSTM)递归神经网络(RNN),它由多个单独的 LSTM 细胞组成。但它是如何工作的呢?它基本上是通过使用特殊的门来允许每个 LSTM 层从先前层和当前层获取信息。数据通过多个门(例如,遗忘门、输入门等)。)和各种激活功能(例如 tanh 功能),并通过 LSTM 细胞。这样做的主要优点是,它允许每个 LSTM 细胞在一定时间内记住模式;他们本质上可以“记住”重要的信息,而“忘记”不相关的信息。这在分析文本时非常有用(例如,单词“和”不像“自由”这样的加载单词那样与政治偏见相关)。现在我已经有了数据和模型的计划,我终于可以开始了。

An LSTM cell and its internal components — cell state c. input gate i, forget gate g, output gate o, and external input gate g

数据收集。随着我的计划准备就绪,我开始了真正的工作。我回到 ProQuest 报纸数据库,为四个新闻源下载了每个新闻源 5000 篇文章,总共 20000 篇文章。这些新闻来源是纽约时报、CNN、华尔街日报和纽约邮报(根据媒体偏见/事实核查确定,从最自由到最保守排列)。幸运的是,这些文章下载到每个来源的一个文件中,所以我简单地根据它们的新闻来源(0 到 3)标记了四个集合。没那么简单,对吧?完全正确!这里的问题是我的神经网络接受数字,而不是单词…

单词嵌入。为了将单词输入到我的模型中,我必须使用单词嵌入方法将每篇文章中的每个单词转换成向量表示。对于这个项目,我使用了这篇论文中的 GloVe 方法,它将单词转换成一个 300 维的向量,使得相似的单词在这个 300 维的空间中彼此靠近。但是你怎么可能用数字来表示一个单词呢?嗯,GloVe 代表一个词,有 300 个确定的特征。把它想象成这个词的特征(例如,当使用 GloVe 时,(男人减去女人)的向量表示等于(国王减去王后),因为在这两种情况下,除了性别之外,两者的几乎所有特征都是相同的)。既然单词已经用数字表示了,我可以对我的数据进行一些最终的调整。

Words are embedded with “features” where similar words are close to each other

数据预处理。文章根据原文中的分段符分成几节。你为什么那样做?对于一个模型来说,很难一次分析整篇文章(RAM issues ouch),所以更好的方法是浏览每一句话,并对每一句话的结果进行平均,以获得对文章的预测。我从每个来源选取了 1,000 篇文章作为我的测试集(20%拆分),剩余的数据被放入训练集,其中 5%的训练集被用作验证集。终于可以准备开始编码我的深度学习模型了!

深度学习模型。我专注于使用长短期记忆递归神经网络,以允许神经网络识别数据中的重要信息,并根据它找到的属性预测文章的来源。我还决定从这篇论文中添加一些脱落层,以确保我的模型不太符合训练数据(尽管这听起来像是任务完成了,但实际上使模型总体上不太准确)。我使用 Keras 和 Python 3.6 中的 Tensorflow 后端来创建我的模型。这些图层是输入图层、LSTM 图层、下降图层、LSTM 图层、下降图层、密集图层和 softmax 输出图层。

Deep recurrent neural network architecture for textual origin classification

训练。我训练了我的模型 10 个纪元。为什么是 10 个纪元?这是由早期停止决定的,当验证精度停止增加时,模型自动停止训练——它只是碰巧在数字附近。我使用了一些非常标准的超参数:1024 的批量大小、分类交叉熵损失函数、AdamOptimizer 和 ReLu/softmax 激活函数。

Progress of the model’s accuracy throughout training

结果。现在是有趣的部分!我发现有两件事我想测试我的模型的能力:预测文章的来源和预测文章的政治偏见。我通过 F1 分和二元准确率来衡量新闻源预测的能力;我通过 n-grams 和 t-SNE 可视化分析了政治偏见检测的能力。以下段落详细介绍了模型的每个分析。

F1 得分(准确度)。该模型获得了 77.20%的 F1 分数(即,此类问题的准确率)。我怎么知道模特不只是运气好?我对这个数字做了统计显著性检验,得到 p 值为 0。实际上,我的模型碰巧准确预测到这一点的概率是 0%。接受模型是好的。

二进制精度。我还使用受试者工作特征(ROC)曲线下的面积测试了每个类别的模型的二进制准确性;这给了我 94%以上的所有类的二进制准确率。这是什么意思?这基本上意味着该模型非常擅长区分文章的来源。

Area under the ROC curve for each class

N-Grams。首先,我进行了一个 n-gram 测试——基本上,我从测试集中提取了 7 个单词的所有可能序列,其中一个单词必须是“Trump”(这给了我一个可能有偏见的句子),并将这些短语反馈到模型中。我选择了可信度最高的短语,这可以被认为是一种让我看到模型与每个新闻源相关联的短语的方式。该模型能够将自由派消息来源与关于唐纳德·特朗普的负面措辞相关联(这通常是自由派消息来源对特朗普的预期报道),并将保守派消息来源与关于唐纳德·特朗普的正面措辞相关联(这通常是保守派消息来源对特朗普的预期报道)。

Phrases of length 7 (one of the words must be “Trump”) that the model associates with each class

t-SNE 可视化。 这个东西听起来很复杂,是什么?让我们后退一点——我的模型的输出是四维的,因为有四个类。我不能绘制它,所以我从 4 维输出层收集置信度,并使用 t 分布随机邻居嵌入(t-SNE)可视化方法调整它的大小。这意味着四维预测被转换成二维点。我绘制了这些点,并根据它们真正的新闻来源给它们着色(蓝色代表自由派来源,红色代表保守派来源)。一般来说,这个方法让我画出模型的预测,看看它们是如何分布的。我发现这个模型能够把自由派的资料和保守派的资料组合在一起。这种分组非常重要,你实际上可以在自由派和保守派之间划出一条非常清晰的分界线。哇!这有点像模型有自己的文章政治光谱!有趣的是你提到了这一点,我也正打算这么说——能够看到模型如何基于偏见分析这些文章,这非常酷!但真正的问题是:我们如何应用这一发现?

t-SNE visualization of the model’s predictions, showing its ability to distinguish between origins and also between political bias

应用。这种技术的一个直接应用是将模型嵌入到像苹果新闻这样的新闻应用中。这将为用户提供新闻提要中每篇文章的实时分析,并在他们点击任何内容之前通知他们任何潜在的偏见(例如,“这篇文章有 43%的机会具有适度的自由偏见”)。该项目的一个更间接的扩展是将模型作为扩展嵌入到 web 浏览器中。经过一些修改,这意味着该模型可以分析网站的不同形式的偏见(例如,识别可能为产品做广告的网站)以及政治偏见。这将给用户提供前所未有的控制,让他们能够控制自己想获取的信息,并避免有偏见的信息。但是这个项目的长期期限是什么?为了最大限度地利用这个项目,我将使用这个模型来生成一个巨大的数据库,其中包含来自不同政治领域的句子。然后,我会训练一个 CycleGAN 或其他生成神经网络,使其能够将有偏见的句子转换为具有相同意思的同一句子的完全无偏见的版本。完成后,主要用途是应用检测模型找到有偏见的句子,然后应用生成模型将每个有偏见的句子转换成目标句子。什么?这将是一个浏览器扩展,它不仅会告诉你是否有偏见,还会给你一个选项,让你在消除偏见的情况下阅读同一个网站!疯狂 yyyyy。**

总结。我创建了一个机器学习模型,它不仅能够高精度地预测一篇文章的新闻来源,还能检测新闻文章的政治偏见。这表明机器学习是多么强大,以及它有多么广泛的应用。该项目的主要应用在于浏览器扩展和嵌入新闻应用程序。在这两种情况下,用户将获得对他们阅读的信息的控制,这两种应用程序都促进了公众对拥有公正观点的重要性的认识。然而,将这个项目的模型进一步应用于创建将有偏见的句子转换成无偏见的句子的神经网络具有很大的潜力,因为它能够生成有偏见的句子的无偏见版本。

也许有一天我们能够完全控制我们接收的信息。

常见问题。我去了英特尔国际科学与工程展览会展示这个项目——这里是评委问我的一些问题,您可能也想知道。

  • 当我可以在你提到的媒体偏见/事实核查网站上找到偏见时,你的项目有什么意义?该网站的局限性在于它是手动的,只有大型媒体公司的概况。我的模型能够单独查看文章。例如,网站可能会说 CNN 的文章实际上是保守的,因为它是一般化的,所以有点自由,但我的模型能够分析文章,并确定它是保守的,即使它来自 CNN。这种模式在小型新闻机构中也有优势,比如在脸书看到的那些可能在为某个议程做广告的新闻机构。这些组织不能在网站上检查,因为他们很小,但是模型仍然能够分析他们的帖子以找出偏见。
  • 你试过其他型号吗?我最近看到卷积神经网络在语言任务上也表现良好,但决定坚持使用递归神经网络的标准。我将来肯定会像伯特一样尝试更多的模型。
  • 你的下一步是什么?我可能会添加一个中立的来源,收集更大范围的政治偏见,这样我的模型就更广泛了。更多应用!
  • 你怎么知道这个模型是通过政治偏见而不是文章主题之类的东西来识别来源的?n-grams 没有显示一个明确的主题,并且它们几乎只具有政治偏见作为唯一可识别的信息。这意味着该模型似乎将政治偏见视为来源的主要指标,并且该模型必须擅长于这样做才能准确。

新闻公司与伯特联系

原文:https://towardsdatascience.com/news-to-company-linking-with-bert-48a1ac9805f1?source=collection_archive---------12-----------------------

So much noise, so little signal (source)

我们都听说过 Bert 以及这个模型家族如何成为许多 NLP 任务的当前艺术状态。我想分享一下我们在 Company.info 只用基于 Bert 的模型创建完整的新闻到公司链接渠道的经验。

我们的业务是收集和出售在荷兰注册的公司的准确信息。这对我们的客户在销售、营销和合规方面非常有帮助,可以节省大量时间。关于公司的数据不断变化,从他们的办公地点到活动和产品,要跟上这些变化是相当费力的。我们提供一体化解决方案,让我们的用户可以专注于重要的事情。

新闻是一个特别重要的信息来源。如果我们在文章发表时就收录它们,并正确地分析它们的内容,我们就能够在它们发生时提供关于公司及其活动的细节。为了实现这一点,我们建立了一个从新闻文章中摄取、链接和提取信息的渠道。

为了让您有所了解,以下是我们门户网站的新闻部分显示的关联公司(荷兰语):

A News article linked to Microsoft and Ingram Micro

对于一个合适的新闻公司链接,有几件事要做好:

  • 过滤无关的新闻
  • 摘录提及的相关公司
  • 为每个提及生成候选人
  • 挑选合适的候选人

这里是管道的概述,接下来我们将介绍每个阶段:

News to company linking pipeline

我不会讨论摄取部分,因为这是一个值得单独发布的数据工程壮举。因此,在我们的管道中,我们从一个经过清理和去重的文章数据库开始,为链接做好准备。

相关新闻过滤

一篇新闻文章是否相关实际上取决于出版商的业务和受众。如果你是 TechCrunch,你就不会发布关于政党丑闻的新闻。Company.info 也不例外,随着时间的推移,会创建一套标准来确定相关性。举个例子,

  • 这篇文章应该是关于在荷兰有注册办事处的公司
  • 股票市场的新闻是不相关的,除非他们报告一个大的损失或利润
  • 关于服务中断的新闻是不相关的

虽然有很多这样的规则,但它们并不是黄金法则:您通常需要考虑不止一个,有些可能在特定时期适用,甚至不同的编写者可能会对同一篇文章做出不同的决定。

随着时间的推移,我们已经捕获了编写者的决定,这给了我们一个训练二进制分类模型的开端。深度学习模型是利用大量数据并学习自然语言中所有细微差别的首选。目前,预训练的 Transformer 语言模型提供了最好的结果,我们在多语言 Bert 的基础上创建了我们的分类器。

我们所有的实现都是基于奇妙的变形金刚库,这个库是透明的,最新的,用 fp16 和分布式训练可以快速训练。对于这一部分,我们调整了一个BertForSequenceClassification模型。

我们的银牌测试集的 F1 分数对于我们的目的来说已经足够高了(抱歉,我们的法律团队不愿意分享数字)。经过误差分析,我们意识到,对于错误的预测,通常模型预测是正确的,这可以用我们的噪声数据集来解释。对于许多错误,你还需要努力思考来证明一个不同的预测,而且不可能有实际的共识。

我们正在将模型推向生产,但我们还没有将编写者排除在循环之外:当模型不自信时,我们要求他们为下一轮训练决定和收集用户行为。

相关实体确认(RER)

这非常类似于传统的命名实体识别(NER)问题,除了我们对所有的ORG类的实例不感兴趣,只对重要的实例感兴趣。一篇新闻文章可以提到几十家公司,但并不是所有的公司都有新闻价值。以下面的片段为例:

FD Mediagroep 从 Heerhugowaard 手中接管信息和数据分析公司 Sizo。随着这项收购于周三宣布,Het Financieele Dagblad 和 BNR·尼乌斯 radio 背后的公司加强了其在公司数据领域的地位,自 2012 年收购 Company.info 以来,它一直活跃在这个市场。

这里,**FD Mediagroup****Sizo**是相关的公司提及,其余的应该忽略:

  • Heerhugowaard 是一个位置
  • 《金融日报》是一份报纸
  • BNR 新闻电台是一家广播电台
  • Company.info 是一家公司,但这不是本文的重点

所以首先,你有古典 NER 的所有挑战;也就是说,您不希望将产品、专有名称或非公司缩写与公司混淆。最重要的是,如果是一家公司,你需要决定它与整篇文章的相关性。

解决这个问题的一个方法是有两个阶段:一个是传统的句子级 NER,然后是显著性模型,该模型决定哪些提取的提及值得链接。这是我们开始之前的设置,这意味着要调整两个模型;但是,如果我们将两者结合起来,端到端地解决问题,会怎么样呢?

这就是我们所做的,我们称之为相关实体识别(RER)。这基本上是一个序列到序列模型,令牌作为输入, IOB 标签作为输出。非常类似于 NER 的解决方案,除了我们将整篇文章作为输入,并且只为相关的提及指定 B-ORG 和 I-ORG 标签。

对于这一部分,我们还使用了基于 Bert 的实现;特别是这个建立在BertForTokenClassification之上的变形金刚的延伸。不过,它被并入主回购协议只是时间问题。同样,训练过程非常顺利,我们很快就取得了成果。新模型几乎总是报告公司名称,不会将缩写、人名或地名与公司混淆。

该模型在检索相关提及方面获得了显著的 F1 分数,其预测给我们的人类评估者留下了深刻的印象。它能够区分真正细微的差别,并有效地利用上下文来区分相关性。我们认为这是变形金刚模型中自我关注闪耀的领域;不仅因为我们能够看到一篇文章的整个上下文,而且还可以看到每一个单词是如何与另一个单词相关联的,以及如何有效地利用这些信息来学习决定相关性的关系。

候选生成

对于每个提取的提及,目标是从我们的 Elasticsearch 数据库中注册的 300 多万家公司中找到合适的公司。然而,对所有这些记录运行机器学习模型是不可行的,所以通常首先提取一个小得多的候选人列表,然后只对这些候选人运行链接模型。

为此,我们简单地做一个简单的 Elasticsearch 查询,使用从上一步中提取的提及信息,对照一些有意义的字段,如注册公司名称和 url。然后,我们将 top- n搜索结果输入链接模型进行训练或预测。因为基本事实表明了给定提及的正确公司 ID,所以我们可以为每个提取的候选人分配一个二进制标签。训练时,阳性样本将有label = 1,所有其他阴性样本将有0。上菜时,我们把所有的候选人喂给链接模型,让它挑选正确的一个。

虽然候选生成可能看起来简单,但它实际上起着重要的作用;因为如果合适的公司没有出现在候选名单中,它将没有机会被下游链接模型评分。为了衡量某种候选生成方法或搜索策略的效果,我们考察了检索召回率。也就是说,如果我们取顶部的50结果,那么被提及的目标公司出现在这些50中的频率是多少。你可以花时间优化搜索策略,或者以训练/推理时间为代价,简单地强制更多的候选人。

实体链接

好了,我们已经走了很远了!现在我们只需要决定一个候选(实体)成为我们目标的可能性。例如,假设提到了Sizo(文章中的公司名称),我们从 Elasticsearch 中抽取了 20 名候选人,他们的名字、URL 或公司描述中都以某种方式包含了单词Sizo。他们没有必然的联系。例如,其中一个是咨询公司,而另一个是当地的理发店。但是如何才能选择合适的搭配呢?

你我正常做的是,先看文章,了解上下文;是科技新闻还是与银行业或本地业务相关的新闻?文章用了哪些词(想话题建模)?有没有提到地点或关键人物可以帮助做出正确的猜测?

另一方面,我们查看每个候选公司及其所有属性来猜测可能性:该公司的活动代码是什么?如果它有一个网站,他们在描述他们的产品或服务时使用的关键术语是什么?注册地点在哪里,谁是关键人员?财务信息(如年利润/资产)能给我们提供有关其经营规模的线索吗?

有了双方的这些信息,我们通常可以相当成功地挑选出正确的候选人。

实体链接是一个经典的 NLP 问题,你可以在这里查看最近的一些方法。在疯狂地混合和匹配想法之前,我们问自己:我们能想到的最简单体面的深度模型是什么?我们能单独依靠伯特来完成这项工作吗?

Bert 和许多最近的预训练模型具有将多个序列作为输入的能力。例如,在一个多任务训练设置中,Bert 本身被训练来预测两个句子是否相互跟随。在 Bert 的术语中,text_a是第一个,text_b是第二个输入序列。text_b是可选的,你只有在处理“序列对”问题时才使用它。

让我们花点时间想想这个双输入设置有多强大。你基本上被赋予了权力来模拟两个“任何东西”之间的关系,无论你需要什么,只要你能用有意义的文本形式来表示它们。

这种双输入设置,非常符合我们之前建立的思维过程;也就是一边看文章和上下文,另一边看每个候选人的属性。具体来说,我们将(提及,文章)对表示为text_a(第一个序列),将候选公司的文本表示为text_b(第二个序列)。然后,我们定义一个二进制分类任务,并教导该模型对阳性样本预测 1,对阴性样本预测 0。

举个例子,考虑一下我们之前看到的同一个新闻片段:

FD Mediagroep 从 Heerhugowaard 手中接管信息和数据分析公司 Sizo。随着这项收购于周三宣布,Het Financieele Dagblad 和 BNR·尼乌斯 radio 背后的公司加强了其在公司数据领域的地位,自 2012 年收购 Company.info 以来,它一直活跃在这个市场。

在这里,我们希望将提及**FD Mediagroep** 联系起来,因此我们将提及和文章(第一个序列)表示如下:

  • text_a : **FD Mediagroep** | FD Mediagroep takes over information and data analysis company Sizo from Heerhugowaard. With this acquisition announced on Wednesday, the company behind Het Financieele Dagblad and BNR Nieuwsradio strengthens its position in the field of company data, a market in which it has been active since the acquisition of Company.info in 2012.

虽然我们主要关注的是提及,但文章是决定公司的行业和活动的重要背景。在提及和文章文本之间使用|分隔符有点武断,我们期望我们的模型在看到足够多的样本后学习这种key | context语义。

现在我们必须考虑第二个序列,以及如何在单个字符串中表示一个公司及其所有属性。假设 Elasticsearch 返回的候选人具有以下属性:

  • id : 235582
  • 名称:FD Mediagroep B.V.
  • 别名:[FDMG, FD, Financieele Dagblad, Het Financieele Dagblad]
  • 网址:[[www.fdmediagroep.nl,](http://www.fdmediagroep.nl,) [www.fdmg.nl](http://www.fdmg.nl)]
  • 描述:The FD Mediagroep is a Dutch media group. The group originated from Het Financieele Dagblad, but also includes BNR Nieuwsradio, Energeia and ESB.

我们将所有这些信息压缩成:

  • text_b : **name**: FD Mediagroep B.V., FDMG, FD, Financieele Dagblad, Het Financieele Dagblad | **url**: [www.fdmediagroep.nl,](http://www.fdmediagroep.nl,/) [www.fdmg.nl/](http://www.fdmg.nl/) | **description**: The FD Mediagroep is a Dutch media group. The group originated from Het Financieele Dagblad, but also includes BNR Nieuwsradio, Energeia and ESB.

我们遵循与text_a相同的|分离结构。最重要的是:

  • 实体属性被简单地映射到key: value表示。
  • 多值属性的值用逗号连接。
  • 所有语义相似的属性如namealternate_names都被折叠在同一个键下。
  • 缺失值将简单地写成nil

如上所述,Bert 模型应该很容易决定text_b中代表的公司是否是text_a中提及的正确目标。

对于这一部分,我们还调整了一个单一的BertForSequenceClassification模型,并将问题定义为一个二元分类任务。在训练期间,所有阳性样本(text_atext_b对)得到标签 1;和阴性样品 0。服务时,我们预测所有候选人的可能性,并报告得分最高的候选人。

将问题公式化为二进制分类主要是出于性能原因,并且与负采样方法非常一致。将所有东西都塞进 Bert 有它的好处,包括简单性和极大地受益于考虑到text_atext_b记号之间的良好关系的自我关注。但是有几个问题:

  • 我们实际上是在寻找一个多类分类器,并且在决定最可能的匹配之前,理想的情况是同时查看所有的候选项。这不是 Bert 的设计工作方式,所以我们必须求助于二进制分类。
  • 整个训练过程有点低效:对于每一个给定的提及和x阳性和阴性样本,我们重复text_a对应于提及的x次。理想情况下,我们应该只编码text_a一次。
  • 与上述相关的是我们如何处理负样本数量和训练时间之间的权衡。
  • Bert 对输入长度(最大 512 个子字)有一个硬约束,这对于适应所有新闻文章和实体属性是非常严格的。

因此,虽然这个解决方案对我们的目的来说是好的,但我们可以想办法改进它。最近许多关于实体链接的工作试图将提及和实体映射到一个嵌入空间,其中匹配的提及和实体彼此更接近。例如,请参见此处的、此处的或此处的。这种方法的优点是:

  1. 没有输入限制:包括候选人的所有文本、数字和分类数据。
  2. 整体嵌入一个候选公司。这种 company-to-vec 对于聚类或相似建模等其他任务非常有用。

但这并不意味着我们必须抛弃 Bert,我们仍然可以使用一个经过调整的 Bert 作为文本特性的强大编码器。这就是我们现在正在做的,我将在以后的文章中省略细节。

对于没有任何调整或巧妙技巧的纯 Bert 模型来说,结果相当令人印象深刻。让您了解一下,与我们基于 xgboost 和手工制作功能的传统系统相比,它实现了17%绝对 F1 增益。最终用户测试也很有结论性,我们正在将这种模式推向生产。

最终注释

这就是你要的,一个功能齐全的新闻链接管道。我们在所有阶段都使用了相同的底层 Bert 模型,这不仅给出了令人印象深刻的结果,还极大地简化了代码重用和维护。

在我们的 Kubernetes 集群中,每个单独的模型都作为一个微服务提供,并在管道的正确步骤由一个编排服务调用(想想 AWS 步骤函数)。每个型号都可以自行扩展,我们可以为不同的服务提供不同的硬件配置。例如,过滤服务(流水线的第一步)是相当轻量级的,可以在一个小型的纯 cpu 机器上提供。尽管实体链接模型需要更多的资源,但是我们使用 gpu 机器来跟上输入负载。

我想借此机会感谢我在 Company.info 的所有同事。这是少有的拥有支持性文化、大量数据和值得解决的问题的地方之一。

如果您有问题或建议,请留下评论。谢谢,直到下一个帖子:)

使用文本和元数据的下一个最佳动作预测:构建代理助手

原文:https://towardsdatascience.com/next-best-action-prediction-with-text-and-metadata-building-an-agent-assistant-81117730be6b?source=collection_archive---------12-----------------------

利用深度学习提高客服团队的效率

简介和动机

我们在 Reply.ai 的使命是在与企业互动时消除挫折感,节省人们的时间。我们可以影响客户体验的方法之一是让客户支持代理更开心、更高效。我们很乐意与 ML 社区分享我们如何使用深度学习来制作实时助手,以提高客户服务团队的效率。

在 Zendesk、Kustomer、Khoros 这样的客服平台里,客服人员在回答罚单、聊天的时候,会做很多重复性的工作。除了其他职责之外,他们还必须对票证进行分类、添加特定标签、将票证发送给其他团队、选择模板,而不是编写独特的个性化响应。我们这个项目的目标在概念上很简单:为支持代理提供关于他们下一步最佳行动的建议。通过帮助代理完成枯燥的任务,用户将获得更快的响应,代理可以将宝贵的时间花在更复杂的查询上。还记得微软的 Clippy 吗?这是正确的做法,对于客户服务团队也是如此。

问题定式化

首先,我们把这个问题公式化为一个纯文本多类分类任务。我们所需要的只是被标记的数据,来把它作为一个有监督的机器学习问题来处理。

因此,我们分析了支持团队的历史记录,并重新创建了每个票据的整个生命周期,从其创建到被标记为由支持代理解决的那一刻。我们关注客户端和代理之间交换的消息的文本内容以及在票据上执行的任何其他操作。

产生的数据集由 23k 个票证快照样本组成,包含客户端和代理之间的对话,以及它们相关的元数据和执行的操作。我们的分类器旨在学习这些动作并建议最可能的动作。

扩展问题表述,将对话背景考虑在内

经过一些初步的实验,我们得出的结论是,我们必须扩展问题公式,因为我们需要做的不仅仅是纯文本分类。在许多情况下,仅通过查看客户的文本请求,无法建议适当的支持措施。我们需要这个模型来考虑当时的环境。否则,纯文本和指定标签之间的关系就太随意了。因此,我们摆脱了纯文本模型模式,为模型提供了上下文元数据作为额外的输入。

让我们看一个具体的例子来说明这一点。我们正在与一个电子商务平台合作,客户会经常询问他们订单的状态或抱怨延迟的项目。为了选择最佳的可能回应,我们需要知道订单的实际状态。物品已经离开仓库了吗?有交通事故吗?

这就是元数据发挥作用的地方。我们添加了一个分类变量,其中包含关于订单状态的重要信息,作为附加输入。现在,我们需要一个能够处理新输入特征的模型。

寻找解决方案

现有的关于结合文本和元数据的模型的研究非常缺乏。这真的让我们很惊讶,因为我们相信这样的模型在许多现实生活中的人工智能应用中会非常有用,而不仅仅是在我们的特殊用例中。所以我们想填补这个空白,建立我们自己的!

我们决定从 fast.ai 开始,这是我们进行深度学习的首选库。我们必须承认:我们在这里确实有偏见,因为团队中的一部分人将他们的深度学习知识归功于雷切尔·托马斯和杰瑞米·霍华德非凡的教学风格,而且我们参加了当前课程的伙伴计划。在仔细查看了 fast.ai 论坛之后,我们终于找到了其他有着完全相同问题的分区器,更重要的是,还有一些有用的代码。幸运的是,另外两名学生 Quan Tran 和 José M. Fernández Portal 已经做了大量工作,我们能够进行合作。结果是在 fast.ai 库的基础上构建了一个模型,我们可以用它来处理对客户支持票据进行分类的任务,并考虑上下文元数据。

Concat 模型架构

下面是我们提出的模型架构的一个非常高层次的解释。(欢迎在评论中点击了解详情,或者让我们在 fast.ai 论坛的这个帖子中进行更技术性的对话。)

神经网络(NN)可以由其他更小的 NN 组成。这种类型的模块化架构由多个不同的网络组成,这些网络用于执行子任务。他们可以相互作用或独立工作,以实现输出。建议的实现利用该属性分三个阶段创建端到端解决方案:

  1. 特征提取:输入层由两个子模块组成。文本数据被传递到用于文本分类的尖端 NN 解决方案,称为 【乌尔姆菲特】 ,并且表格元数据由 fast.ai 表格 NN 标准实现来处理。这两个模块互不连接,独立工作,从各自的输入数据中提取特征。它们中的每一个都输出一个向量来表示这些特征。
  2. 特征组合:在第二步中,我们通过简单地连接两个向量,将前面模块的输出组合成一个。
  3. 分类:最后,我们将连接的向量送入第三个模块,对表示的特征进行解码和分类。对于这个任务,使用多层感知器,这是标准的方法。

Model Architecture

结果

我们的最佳车型 F1 得分为 0.57 。结果是在一个非常嘈杂的数据集上实现的,该数据集具有分布在 20 个目标类上的巨大的类不平衡。我们将其与优步·艾的路德维希进行了比较,后者提出了一种不同的方法来组合文本和元数据特征。我们用 Ludwig 训练的最好模型是一个使用预训练手套向量的 WordCNN。优步·路德维希·艾的 F1 成绩要低得多,为 0.41 分

自己试试这个!

我们对这个结果不满意,因为我们客户的数据中的噪音和类别不平衡使得我们不可能获得一个清晰的概念证明。这就是为什么我们创建了一个简短的实验,这样你就可以说服自己我们的 Concat 模型实际上是有效的,并自己运行一些代码。检查一下 Kaggle 内核。为了简单起见,我们基于 IMDB 电影评论数据集生成了合成数据。但是请随意插入您自己的数据集,并告诉我们它是如何进行的。

关于回复

Reply.ai 开发 ai 技术,为快速发展的公司提供更快、更智能的客户服务。在 Forrester 的企业客户服务排名中,我们与三星、可口可乐、霍尼韦尔和拉斯维加斯的 Cosmopolitan 等客户合作,让他们的客户更开心,让他们的客户服务团队更高效。

感谢

  • 维克多·佩纳多在这个项目和这篇文章上的合作。
  • Quan Tran 和 José M. Fernández Porta l 做了很多艰苦的工作

☞仍有疑问或想使用 AI 为您的客户提供更好的自助服务,DM us on Twitter

下一个更好的玩家?用于二元分类的 GBDT + LR

原文:https://towardsdatascience.com/next-better-player-gbdt-lr-for-binary-classification-f8dc6f32628e?source=collection_archive---------18-----------------------

另一种有效的叠加预测算法

Clarke Quay @ Singapore

例如,具有逻辑回归的堆积梯度推进决策树(GBDT)在解决二元分类问题时可以是非常有效的算法。CTR 预测。

从 2014 年发布的论文脸书预测广告点击的实践经验中,脸书通过结合决策树和逻辑回归为他们的点击预测系统引入了这种算法。该算法将系统性能提高了 3%,对在线业务产生了重大影响。

在本文中,我将介绍以下议程:

  • 算法解释
  • 使用信用审批数据集的 Python 实现
  • RAM 问题和潜在解决方案

我们开始吧!

算法解释

GBDT 和逻辑回归都是众所周知的分类模型。GBDT-LR 算法通过将每棵树的预测叶节点的索引作为线性分类器逻辑回归的稀疏输入来组合这两个模型。

让我们假设我们已经训练和调整了一个有 300 棵树的 GBDT 模型,每棵树有 3 个叶节点。第二步是使用该模型再次对训练数据集进行预测。然而,不是输出标签,而是为 300 棵树中的每一棵树返回预测叶节点的索引。

GBDT output prediction leaf node index

在上面的示例中,第一棵树返回 3,因为预测是在第三个叶节点上。同样,第二棵树返回 2,最后一棵树返回 1。GBDT 模型的输出将看起来像[3,2,…]。,1].由于模型包含 300 棵树,这个列表应该有 300 个元素。

One-hot encode GBDT output

接下来,列表中的每个数字都被一键编码。比如 3 变成[0,0,1],2 变成[0,1,0],1 变成[1,0,0]。这些一键列表被附加在一起以形成逻辑回归模型的输入。因为每棵树包含 3 个叶节点,所以最终的列表应该有 300 * 3 个元素。

Overall Structure

现在,我们已经成功地为逻辑回归构建了训练数据集。很明显,输入数据非常稀疏。因此,L1 正则化用于解决这个问题,并避免过度拟合。

Python 实现

让我们用 UCI 信用审批数据集来看一下 Python 的实现。源代码可用。数据集包含 15 个不同的标称和序数特征(A1 至 A15)以及一个二元目标标签(A16)。

Data Glance

为了快速处理数据,丢失值的记录将被删除。分类特征是一次性编码的。

Quick Data Processing

首先,让我们训练一个 GBDT 和一个逻辑回归模型用于基准测试。对于 GBDT,网格搜索用于寻找最优参数。选择 ROCAUC 分数作为评估标准。

Benchmark Models

从上面的脚本可以看出,我使用 lightgbm 来训练 GBDT 模型。Lightgbm 分类器适用于该算法,因为我们可以通过调整“num_leaves”参数来指定每棵树中的叶节点数。树的数量由“n_estimators”控制。

接下来,我们将使用经过训练的 GBDT 模型对训练和测试数据进行预测。将“pred”函数中的“pred_leaf”设置为 True,以输出每棵树的预测叶节点的索引。

Output Prediction Leaf Node Index

最后,我们需要将 GBDT 输出转换为独热格式,并使用稀疏数据来训练具有 L1 正则化的逻辑回归。

GBDT-LR Performance

嘣!GBDT-LR 算法实现了 0.86 的 ROCAUC 分数,这优于基线 GBDT (0.83)和 LR (0.82)模型。

RAM 问题

到目前为止,一切看起来都很好,对吗?然而,这个数据集非常小。处理后只包含 653 条记录。因此,我们正在训练只有 20 个叶节点的小树。想象一下,在 GBDT 模型中,我们有一个更大的数据集,包含更多的要素,需要更多的叶节点和更多的树,这种一次性编码的输出可能非常巨大。

矩阵的大小可以通过记录数叶节点数树数来计算。在解决复杂问题时,我们需要小心处理这个矩阵。一个潜在的解决方案是将该矩阵转换成稀疏矩阵对象。

Use of Sparse Matrix

注意,通过将独热矩阵转换成稀疏矩阵,RAM 使用从 4,272 字节减少到 56 字节。然而,随着处理时间从 419 毫秒增加到 898 毫秒,这个技巧给 CPU 计算带来了更多的负担。

结束注释

同样,上面用作示例代码在@ 这里可用。

感谢阅读!

下一代自适应神经系统

原文:https://towardsdatascience.com/next-gen-adaptive-neural-systems-c71615eae2a?source=collection_archive---------16-----------------------

Photo by Joshua Sortino on Unsplash

自从深度学习革命开始以来,神经网络中就存在一种趋势,这种趋势可以简单地用一个词来概括:规模。

缩放这些模型的自然维度是计算和数据。十多年来,从硬件加速器到高级软件工具,计算扩展在堆栈的每个级别都是一项艰巨的任务。大型数据集已成为新数字经济中的一个关键优势,它一直是能够吸收和理解此类数据集的模型背后的驱动因素。

在大多数情况下,最好的模型处于我们扩展这些资源的能力的最前沿。这成为一个实际问题,因为预测有时需要在低延迟的情况下大量计算,但通常学习最好的模型不是最快的。与解决这个问题相关的研究领域叫做模型压缩。有许多技术,有些感觉有点粗糙,比如将小权重设置为零,并引入稀疏数据表示。其他方法似乎更有原则,如知识提炼,其中一个训练有素的重量级模型用于“教授”一个小得多的网络,或者另一种称为条件计算的技术,其中控制器决定为给定的输入样本激活网络的哪些部分。

模型适应和解压缩

相对于最初训练的网络,压缩模型在泛化能力方面损失了多少,这是一个公开的问题。如果你读了论文,你当然会发现在实验中,压缩模型的表现和原始模型一样好,甚至比原始模型的评价集还要好。但我在现实世界中部署模型时学到的一件事是,故事永远不会结束。环境总是可以在你的带领下改变,有时很慢,有时相当快。

通往真正智能和适应性系统的道路可能依赖于我从旧的创造力和天才之神那里得到的灵感,我称之为模型解压。原理很简单:当你发现你的模型在性能上有偏差时,在压缩模型中添加一些容量,然后动态学习。

从技术角度来看,这听起来像是一个愚蠢的想法,因为我们今天处理模型漂移的方式要有效得多。我们只是重新训练或不断训练大网络,并在我们想要推出新型号时重复压缩过程。理解为什么认为是次优的,需要一点关于边缘计算的想象力。

边缘

模型压缩得到真正关注的原因是因为我们希望部署这些令人惊叹的技术,而不会受到网络的瓶颈限制。网络通信通常是最慢和最糟糕的资源,因此,如果你需要一个大型云服务器来完成所有的 ML 并将其发送回手机或远程设备,你将面临可靠性和延迟的问题。模型压缩使我们能够运输这些模型,并以低延迟和低功耗在设备上运行它们。

我会回头说我们当前的方法有点傻,因为当环境彻底改变时,你不能指望一个超专门化的模型简单地完全适应自己。如果这是真的,我们将永远不需要一个重量级的模型。最近有一些关于使用被称为“教学助手”的中间模型的工作,来帮助建立一个蒸馏的层次结构,以帮助学生网络更好地学习。从解决边缘模型漂移的逻辑角度来看,似乎中间网络可以满足教师和学生之间的一系列资源需求。

当然,对于较小的漂移来说,这更有意义,甚至可能不需要任何新的资源(除了计算能力)。这都是相对的,当人类以人工智能工程师的形式被警告模型突然倒退时,他们不应该调整自己。更有意义的是,我们向这个系统引入新的组件来帮助自动化这个过程。

对于我们在训练和推理阶段之间的区别,有很多批评。这个想法是,训练应该像在大脑中一样一直进行,而不仅仅是一次性的。这和持续学习者的学习有些关系。

不幸的是,这并不容易符合硬件的故事。培训被认为是非常计算密集型的,如果没有硬件加速,这种情况是相当没有希望的。但现实并非总是如此:从头开始训练众所周知是计算密集型的,但我们可能不需要对训练数据进行几十次或几百次检查来适应新的情况。也许有必要重新审视一下利用当前硬件进行边缘培训的想法。

下一代神经系统

由于对资源的严格限制,这些问题在今天对 edge 来说是很难解决的。它们在云中的负担要小得多,所以我们为什么没有能够自动调整自己并不断从各种流中摄取数据的系统,这是一个奇怪的问题。嗯,我们有他们,但在我所知道的这样做的组织中,他们的 ML 团队的规模在几十到几百人之间。一个很大的原因是,构建可伸缩的数据处理系统仍然很重要。但更大的原因是,由于各种原因,我们的模型仍然很难训练,这涉及到许多人尝试不同的想法来提高性能。

这在手工生成特征的 ML 时代是有意义的。但是深度学习已经改变了这一点,或者至少它承诺会改变。在过去的几十年里,特别是最近的几十年里,我们已经证明了这是可行的。但大多数现实世界的场景都没有受益于一些非常聪明的科学家和多年来对归纳偏差和数据准备策略的研究思考。他们努力的结果是神经结构搜索、超参数优化和迁移学习。这些也在谷歌内部得到了证明,以至于它现在可以作为云服务使用。随着不同数据领域中新形式的无监督预训练方法的出现,深度学习的典型成功可能最终会在跨领域和行业的许多现实世界问题中实现。

这些是我们下一代系统的基本要素。

障碍

到目前为止,这些元素还没有集成到一个系统中。我们没有实现目标有几个原因,我将简要介绍一下。

有些部分似乎不兼容。例如,在通过神经架构搜索找到最佳架构后,如何从预训练的模型中进行迁移学习?有没有软件可以存储模型,当你想建立一个新的模型时可以查询它们,检索最好的模型作为预训练的起点?在将原始数据转换成当前网络可以有效学习的最佳形式方面,是否存在类似的事情?当然,这些算法存在超参数等价物,应该结合模型进行调整吗?我预计我们将及时解决其中的一些问题,这必须由一个在系统工程和深度学习科学方面都具有专业知识的行业研究实验室来推动。

运行这样一个系统也有很大的成本,忽略了建设它所必需的前期资本。但是如果我们把视野扩展到时间维度,成本就没那么有趣了。因为每个人都知道,计算成本总是会大幅下降,半个世纪以来一直如此,尽管摩尔定律已经终结,但它仍将继续,而且现在整个全球经济都在推动这一进步。

成本也不那么令人感兴趣,因为迁移学习承诺消除大量必要的计算能力。人们只需要训练一个好的基础模型一次,并根据需要多次微调它,成本要小几个数量级。这引发了该领域另一项高级技术的应用:联邦学习。

通常情况下,公司拥有不想共享的专有数据。然而,由于对其应用深度学习存在严重成本限制,他们也可能不愿意利用这些数据。但是,如果我们拥有下一代自适应深度学习系统,并具备联合学习的能力,也就是说,在本地进行培训(就像在公司网络内部一样),并且只向外部世界报告梯度,他们可能会更愿意。具体来说,这可以使多个医疗记录公司或律师事务所联合创建针对他们的问题的最佳模型,将其真正的应用留在下游,以针对他们的具体问题进行微调,而他们不必分享关于该模型的任何信息(其他各方可能也不太关心它,因为它对他们来说只有很小的价值)。联合学习甚至可以进一步降低初始预训练模型的成本。

也许我们根本不需要等待更好的计算机硬件。

下一级艺术与工作和休闲的未来

原文:https://towardsdatascience.com/next-level-art-and-the-future-of-work-and-leisure-f66049112e44?source=collection_archive---------19-----------------------

用人工智能变得更有创造力(和人性)

Photo by Amaury Salas on Unsplash

人工智能和深度学习对大量领域产生了巨大影响,并在过去几年中引发了许多颠覆和进步,这一事实对许多阅读本文的人来说不会感到惊讶。

然而,有些人可能会感到惊讶的是,即使是艺术和创意领域,这些一直被视为独特的人类领域,也没有受到这些最新进展的影响。

对人工智能取代工作的恐惧是围绕这些技术最常见的担忧之一。现在它甚至侵占了我们的创造性追求。这是否意味着我们不仅要担心我们的工作被人工智能抢走,还要担心我们的人性?

虽然许多人担心人工智能会取代或替代人类,或者认为人工智能永远不会有创造力,人工智能产生的任何东西根据定义都不是艺术,但我想提出一种替代观点。我相信,先进的 AI 将让我们专注于我们独特的天赋和优势,为我们提供创造性探索和表达的新工具,让我们享受更多高质量的休闲时间。

最终,它将使我们变得更有人情味。

在这篇文章中,我首先想给你一个非常简短(并且非常不完整)的关于深度学习和艺术交叉的介绍,并向你介绍一小群选择了神经网络作为他们首选媒介的艺术家。

然后,我想向您介绍我目前的公司 Qosmo 在过去几年中一直在从事的一些项目,以及我自己的一些个人项目。

最后,我想和你们分享一个不仅是人工智能和创造力,更广泛的工作和人类的未来愿景。

我希望在这篇文章结束时,我会让你相信,我们既不应该害怕人工智能削弱或贬低我们的人性,也不应该认为它只会影响日常工作,但不会对我们的创造力产生任何影响。相反,我希望到最后你会对人工智能的未来感到兴奋,并准备好接受它,不是作为一个竞争对手,而是作为一个强有力的工具来重获和加强我们的人性。

边注:本文基于我在 2019 年 SciPy Japan 上的一系列演讲,以及 2019 年日经 AI 峰会上的扩展版本。如果你更喜欢看视频,你可以在 YouTube 上找到 SciPy talk。但是这篇文章不仅是最近的,而且更有深度,特别是关于知识工作和创造力的未来的最后一部分,在 SciPy 的演讲中我根本没有时间去触及它。

人工智能艺术简史

人工智能和创造力之间的联系第一次从相当深奥的圈子渗透到主流意识,可能是在 2015 年谷歌宣布 DeepDream 的时候。

Image credit: https://www.reddit.com/r/deepdream/comments/3cc2a2/very_wow_such_puppyslug/

想象一下盯着一朵云。过了一会儿,你会感觉到你可以在那里看到一个模式。也许是一张脸。你盯着云看的时间越长,越想那张脸,你实际上就越说服自己,云中真的有一张脸在盯着你。

DeepDream 本质上就是这种现象的神经网络等价物。

通过反复强化神经网络在图像中拾取的模式,最初非常微妙的模式(或其想象的暗示)逐渐变成这些模式的完整表现。这样,狗的眼睛开始长出来,蜗牛从建筑物中冒出来,风景变成了有着童话般高塔的奇异城市景观。

从高中开始,一直到我获得博士学位,我偶尔会为乐队制作音乐视频来赚点小钱。我第一个使用深度学习的项目是在 2016 年我的博士学位即将结束时,当时我使用 DeepDream 网络在我为字母和树制作的《虚空》的视频中实现了一种有点新奇的视觉效果。

虽然今天没有人会对此感到兴奋,但你必须记住,就深度学习而言,2016 年是史前时代。当时这是一个非常酷的效果(至少我是这么认为的),这是我熟悉 TensorFlow(当时仍处于起步阶段)和深度学习的一个好方法。

最近,我们已经超越了对现有图像的简单处理。特别是,我们已经看到了神经网络在生成图像方面的惊人突破。很大程度上,这要归功于一种叫做 GANs生成对抗网络的网络。

GANs 基本上是通过让两个网络相互对抗来工作的,一个是生成假数据的生成器,另一个是必须判断数据是真实的还是由生成器网络创建的伪造品的鉴别者或评论家,他们已经在他们可以生成的图像类型中实现了令人震惊的准确性和可信度。

特别受欢迎(也很奇怪)的是(半)真实的脸相互变形的幻觉图像,这导致了令人着迷的视频。

由于这类甘赝品最近达到的真实程度,一个像这样的网站山寨产业已经兴起。每当这个特定的网站被刷新,一个新的由神经网络想象出来的照片般真实的肖像就产生了。虽然这很有趣,但它也让人们关注围绕深度造假和在近乎完美的人工智能造假时代真实数据的可信度日益增长的问题。

这一点我将在下面再次谈到。虽然人工智能艺术本身是有趣和令人愉快的,但它也像其他艺术形式一样,允许我们突出问题,表达我们的关切。通过使用这些问题或失败点作为我们工作的基础,并把它们发挥到极致,我们作为艺术家可以传播意识和教育。

最好的艺术不仅仅是审美上的愉悦,还能引发人们的思考。

2018 年 10 月,当法国集体 【明显】 能够在知名拍卖行佳士得以 432,500 美元的价格拍卖他们的甘创作的艺术品【Edmond de Belamy】时,人工智能艺术第一次真正成为主流。

Image credit: https://en.wikipedia.org/wiki/Edmond_de_Belamy#/media/File:Edmond_de_Belamy.png

这在艺术和 AI 社区都引起了轩然大波,并提出了 AI 是否能真正产生艺术的问题。

然而,这远不是它提出的唯一问题,拍卖后的大部分注意力都集中在显而易见公司处理和实施这个项目的方式上。他们面临着严厉的批评,因为他们采用了别人的代码,在一个结果可疑的简单数据集上进行训练,并出售打印在画布上的生成输出。

我不想太深入整个关于明显是否值得金钱和关注的争论(如果你感兴趣,网上有很多这样的讨论,例如伟大出版物 Artnome 中的这篇文章)。然而,我想说的是,在我看来,不管我们是否认为最终的作品是艺术,在我看来,显然不是真正的艺术家。

很能说明问题的是,他们甚至没有用自己的名字,而是用 GAN 算法背后的一个关键方程来签名。就好像他们想说“不是我们做的,是人工智能做的。”

这与真正的人工智能艺术家所做的完全相反。

就像一个画家研究他的画笔和画布并完善他的笔触一样,就像一个钢琴家研究她复杂的乐器并练习她的技巧一样,一个真正的人工智能艺术家深入研究他正在工作的网络,以及他需要操纵它们的方式,以精确地实现他心目中的创造性结果。

从这个意义上说,AI 和神经网络不是创造者!它们是钢笔、刷子、照相机、小提琴、凿子等。他们是工具。

由于它们的高度复杂性和新颖性,它们可能看起来像魔法,像自主的创造者,但最终它们仅仅是(希望)熟练的创造者手中的工具。

对我来说,显而易见的是非常聪明地利用这种新颖性和高度复杂性来做好销售。无论你如何看待他们的艺术才华,他们肯定是聪明的企业家。

这有点像有人在 1985 年 MS Paint 发布前夕用它画了一个简单的草图,印在一张大画布上,然后拍卖掉。创造它的过程的纯粹的新颖性和(当时)看似很高的复杂性可能已经获得了很高的价格并给人们留下了深刻的印象。但它可能不会是“好艺术”。Paint 女士肯定不会是创造者。

就像数码相机不比模拟相机更具创造力,或者 Photoshop 不比前数字平面设计师的笔和纸更具创造力一样,人工智能和深度学习也是如此——至少在可预见的未来,我们可以现实地想象它们——不是创造者,而是创造者使用的工具。

对于那些对真正的自主创造力感到兴奋的人来说,这可能会有点失望。但我对此感到高兴,并认为这丝毫不会降低人们对这些技术的热情。它们让我们创作者真正有了新的创造性表达方式。不仅仅是作为固定的工具,它们几乎是一个元工具,允许我们不断地梦想新的工具和过程来实现我们的创造性愿景。

关于我认为什么/谁是真正的人工智能艺术家,让我简单地给你介绍几个我认为属于这一类的人。

这个列表绝不是详尽的,人工智能艺术家的社区正在不断增长。开始研究更广泛的人工智能艺术的一个好地方是由巴鲁·埃利奥特组织的 NeurIPS 工作室的画廊,该工作室是关于创造性和设计的机器学习的

为了简洁起见,我也不会太深入任何一位艺术家的细节,而是鼓励你自己去看看他们的艺术(和思想)。

认识人工智能艺术家

可能最著名的人工智能艺术家是马里奥·克林格曼。

克林格曼,就像显而易见的一样,将他的大部分注意力集中在与甘相关的艺术上,尤其是肖像画。然而,与显而易见的相反,他真正成为了它们错综复杂的大师,确切地知道如何设计、训练和操纵它们,以达到他所渴望和设想的精确的艺术效果。

他的许多作品都有一种令人难以置信的微妙之处,让人想起更传统的艺术形式,常常怪异地将美术美学与更抽象的艺术形式混合在一起。

“Neural Glitch”; Image credit: http://www.aiartonline.com/art/mario-klingemann/

驱动他追求人工智能艺术的是对“趣味性”的追求,正如他在接受艺术市场大师 采访时概述的那样。

“我试图找到有趣的东西,这是一种永无止境的探索,因为一旦你抓住它,它就会像雪花一样在你手中融化。有趣隐藏在不熟悉、不寻常和不可思议之中,但是一旦你发现了它,并把它拖到聚光灯下,你看它的时间越长,它就变得越熟悉或正常,最终失去它的有趣性。

我使用机器作为检测器,帮助我在不断增长的信息堆中进行搜索,这些信息正以越来越快的速度进入我们的世界。与此同时,我自己也在不断增加,用机器生成有序的信息模式,速度比我自己的设备更快。在这个过程中,有时是我决定,有时是我让机器决定。"

这个搜索方面是人工智能艺术中反复出现的主题。

我们可以想象所有可能的艺术品的抽象空间。这个空间是难以置信的高维度和巨大的(潜在的无限取决于我们所考虑的媒体)。传统上,艺术家只能非常缓慢地探索这个空间中的无限小的区域。

神经网络本质上提供了工具,允许我们以更快的速度和更广阔的视野探索这个空间。人工智能艺术家的技能往往在于知道如何将这种网络化的探索引向“高度有趣”的区域。

克林格曼最近还在苏富比拍卖行拍卖了他的一件作品路人的回忆。这件作品不仅仅是一件静态的艺术品,它实际上包括了生成机制本身,导致了一个完全生成的、无限进化的装置。

最后,这件作品“仅仅”卖了 3.2 万英镑,这导致了一场广泛的媒体风暴,文章题为“人工智能艺术品在拍卖中失败,机器人启示录尚未到来”,宣称短命的人工智能艺术场景只不过是一种好奇,基本上已经走到尽头。

然而,我个人认为这对人工智能艺术社区来说是一个好迹象(我认为马里奥·克林格曼也同意这一点)。32,000 英镑是一个合理且非常值得尊敬的价格,它并没有标志着人工智能艺术的终结,而是标志着人工智能艺术炒作和利用注意力/新奇经济的终结。

这标志着人工智能艺术已经成为一种严肃而受人尊敬的艺术形式,而不是一种被夸大的好奇心。

与马里奥·克林格曼的作品非常不同,但同样有趣的是土耳其媒体艺术家 Memo Akten 的作品。

克林格曼的作品非常“专注”(因为没有更好的词),接近艺术,而阿克滕的作品则更具概念性和多样性。虽然他的最终结果可能看起来不那么“精致”,但它们都是基于通常非常简单但巧妙而具有煽动性的想法。

我强烈建议你去看看的作品目录,因为它种类繁多,但是我想在这里和你分享我最喜欢的他的作品,他称之为 学着去看

这个想法非常简单,但结果却令人震惊和深思。

在训练过程的开始,神经网络通常是随机初始化的,这意味着它们绝对没有“真实世界”的概念。在训练过程中,通过反复接触数据,他们形成了世界的图像(或者至少是数据集中所代表的世界)。如果这个数据集有偏见,那么经过训练的网络的世界观也会有偏见。

在《学会看》中,Akten 将这一想法发挥到了极致,并在非常独特的图像数据集上训练了各种神经网络。

一个网络只看到海洋和海岸线的图像,另一个网络只看到火的图像,还有一个网络只看到花的图像。

结果是,一旦网络完成了他们的训练过程,并被释放到“真实世界”,看到更多的普通图像,他们只能根据他们所学到的来解释这些图像。

例如,“花卉网络”不知道如何更好地解释它所看到的关于花卉的一切,它看到的任何地方都有花卉。

这就好像一个孩子从出生就在一个除了鲜花什么都没有的孤立环境中长大,然后突然被释放到现实世界中。它的视觉皮层和模式识别系统可能会努力解释新的模式,也可能会看到到处都是花。

虽然这是一个思想实验和纯粹的猜测,但众所周知,我们人类对我们视觉感知中的某些模式也有自然的(非常有用的)偏好,例如偏好看脸。

学会观察提出了一个有趣的问题:由于我们独特的成长和文化背景,我们每个人可能会有多少偏见。

我们看待和感知世界的方式到底有多不同?

虽然它不太可能像 Akten 网络的偏见或思想实验中的孩子那样强烈,但几乎可以肯定的是,人与人之间存在微妙的差异。

算法的偏差在过去已经引起了普遍关注。种族主义聊天机器人或性别歧视图像识别/分类模型只是一些例子。它们确实是数据驱动科学,特别是深度学习的最基本问题之一。

在某些情况下,偏见非常明显。虽然这些案例确实令人震惊和担忧,但它们不太可能是最有问题的,因为它们太明显了。随着数据驱动技术变得越来越普遍,特别是细微但无处不在的小偏差将变得至关重要,但也很难检测和消除。

虽然我们可能没有直接的解决方案,但作为艺术家,我们有能力让这个问题引起关注,并通过将它发挥到极致,让外行(以及经验丰富的从业者)更容易理解它。

这是我认为许多有趣的人工智能艺术生活的地方,特别是 Memo Akten 也参与的更具概念性的那种:采用成熟的神经网络,并将它们推向(或超越)它们的临界点或应用领域。这不仅经常导致有趣和意想不到的结果,还让我们更深入地了解如果在现实世界中盲目放任这种模型可能产生的问题。

这里我要介绍的最后一位艺术家是计算设计讲师汤姆·怀特。

顾名思义,他的项目感知引擎专注于感知在创造力中的作用。用他的话说,

“人类的感知是创造过程中经常被低估的组成部分,因此设计一个将感知放在前面和中心的计算创造过程是一个有趣的练习。”

同样,它本质上是一种通过巧妙地改变应用领域来欺骗神经网络做它们最初不想做的事情的练习。

它使用了对立的例子的想法,并把一个有趣的艺术扭曲。特别是,怀特建立了一个反馈回路,在这个回路中,对网络的感知引导着创作过程,而创作过程又反过来影响感知。

简单地说(有点简化),White 使用了一个经过训练的神经网络来识别图像中的对象,然后使用了第二个系统,该系统可以生成抽象形状并搜索一个结果,该结果可以“欺骗”网络对特定对象类进行高确定性预测。结果是看似抽象的形状(怀特后来把它变成了真实的丝网印刷),仍然使网络确信是某些物体的照片般逼真的表现。

Image credit: https://medium.com/artists-and-machine-intelligence/perception-engines-8a46bc598d57

有趣的是,一旦我们知道网络认为它看到了什么,我们在大多数情况下也可以突然看到大多数图像中的对象(尽管我怀疑有人被骗将其与真实的东西混淆)。

White 使用的真实过程实际上比我在这里给出的项目的简略大纲更加巧妙和深刻。如果你对细节感兴趣,我强烈推荐你看看他的文章。

[## 感知引擎

一个视觉概述检查神经网络的能力,创造从真实的收集抽象的表现…

medium.com](https://medium.com/artists-and-machine-intelligence/perception-engines-8a46bc598d57)

Qosmo:计算创造力和超越

现在你已经对人工智能艺术有了一点概念,并且认识了一些在这个新兴领域工作的人,让我简单地给你讲讲我自己是如何参与进来的。

实际上,我的学术生涯始于一名物理学家,攻读量子信息理论博士学位。但是在做这个的时候,我意识到我想做一些更实用的东西。通过我共同创立的一家初创公司,我也有了一些创业经验,我认为人工智能不仅从纯粹的学术角度来看很有趣,而且也是解决一些非常酷的现实世界问题(并赚些钱)的非常有前途的工具。

因此,在获得博士学位后,我在一家初创公司工作了几年,该公司将人工智能应用于广泛领域的商业问题,例如金融和医疗保健。虽然在这些领域肯定有有趣的问题需要解决,但我个人对人工智能的创造性越来越感兴趣。

最终,在 2019 年 2 月,我终于决定辞去之前的工作,加入我的朋友 Nao Tokui 在他的公司 Qosmo 。如果你对这一切是如何展开的完整故事感兴趣(以及我是如何同时成为一名作家和音乐家的),我最近详细写了这一切:

[## 在不到两年的时间里,从上班族变成了作家、音乐家和艺术家

分享你的创意项目如何改变你的生活。

medium.com](https://medium.com/swlh/from-office-worker-to-author-musician-and-artist-in-less-than-two-years-e69fbbc6f520)

Qosmo 是一个位于东京的小型创意团队。该公司的核心理念是“计算创造力”,重点关注 AI 和音乐(但肯定不限于这些领域)。

这里我想简单介绍一下我们过去的三个项目。

AI DJ

大概到目前为止 Qosmo 最著名的项目就是我们的 AI DJ 项目了。

最初开始于 2016 年的 AI DJ 是一场人类与 AI 的音乐对话。

在 DJing 中,播放“背靠背”意味着两名 DJ 轮流选择和混合曲目。在我们的例子中,我们有一个人和一个人工智能背靠背地玩。

具体来说,一个人(通常是 Nao)选择一首曲目并进行混音,然后 AI 接管并选择一首曲目并进行混音,以此类推,创造出一种自然、连续的合作表现。

这种增强人类创造力和处理人类与机器创造力之间关系的想法是我们在 Qosmo 所做工作的核心。我们对自主创新的机器并不特别感兴趣(我们也不真的相信它们在不久的将来是可能的),而是对人类如何为了创新的目的与人工智能和机器进行交互感兴趣。

AI DJ 由几个独立的神经网络组成。核心是一个可以根据以前播放过的曲目选择曲目的系统,以及一个可以进行节拍匹配和混音的系统。

至关重要的是,我们使用的不是数字音频,而是真正的黑胶唱片。人工智能必须学会如何物理地操纵光盘(通过使用强化学习训练的微型机器人手臂),以便对齐节拍,并使节奏匹配。

虽然这个项目已经有几年的历史了,但是我们仍然在不断地开发这个系统。例如,使用摄像机来分析人群行为,并通过根据这些信息调整曲目选择来鼓励人们多跳舞。

过去,我们在许多地方,包括本地和全球,都进行过这种表演。到目前为止,我们最大的表现是在谷歌 I/O 2019 上,在首席执行官桑德尔·皮帅的主题演讲之前,我们在主舞台上做了一个小时的表演,让观众热身。

你可以在我们的网站上了解更多关于 AI DJ 的详细信息。

[## 人工智能 DJ 项目-人工智能和人类之间的对话

“人工智能 DJ 项目”是一场现场表演,由人工智能(AI) DJ 和人类 DJ 一起演奏…

qosmo.jp](http://qosmo.jp/en/projects/ai-dj-human-dj-b2b-2/)

想象的声音场景

作为人类,我们的视觉和听觉体验有着很深的联系。看看海滩的图片,你很容易想象海浪和海鸥的声音。看着繁忙的十字路口,脑海中可能会浮现出汽车喇叭声和建筑噪音。

想象的声音场景是一项实验,让 AI 对想象的声音和图像有类似的感觉。这是一个基于网络的声音装置,让用户探索谷歌街景,同时沉浸在人工智能想象的声音场景中。

在技术上,它是基于跨模态信息检索技术的思想,如图像到音频或文本到图像。

用关于视频(即,视觉和音频)输入的两个模型来训练该系统:一个良好建立的、预先训练的图像识别模型处理帧,而另一个卷积神经网络将相关联的音频读取为频谱图图像,其损失迫使其输出的分布尽可能接近第一个模型的分布。

一旦经过训练,这两个网络就可以让我们从庞大的环境声音数据集中检索出与特定场景最匹配的声音文件。

生成的声音场景有时有趣,有时有趣,有时发人深省。其中许多符合人类的预期,而另一些则让我们感到惊讶。我们鼓励你迷失在想象的声音场景中。

神经节拍盒

我们最近的艺术项目是 Neural Beatbox,这是一个视听装置,目前作为展览“人工智能:超越人类”的一部分在伦敦巴比肯展出(还展出了 Mario Klingemann 和 Memo Akten 的作品)。

就像 AI DJ 一样,这个作品围绕着一个音乐对话。然而,除了在人工智能 DJ 中,人工智能不是参与者,而只是推动者,对话发生在装置的不同观众之间。

节奏和节拍是人类最基本和最古老的交流方式。Neural Beatbox 使任何人,无论他们的音乐背景和能力如何,都能用自己的声音创造复杂的节拍和节奏。

当观众走近这个装置时,他们被鼓励录制自己的短片,发出声音,做鬼脸。使用该视频,一个神经网络将观众的声音分割、分析并分类为各种类别的鼓声,然后将其中一些整合到当前播放的节拍中。

同时,另一个网络不断产生新的节奏。

通过以这种方式结合后续观众的贡献,人们之间直观的音乐对话得以展开,从而产生不断发展的作品。

人工智能的轻微缺陷,如偶尔的错误分类或不寻常的节奏,实际上增强了创作体验,并导致有趣和独特的音乐体验。作为观众,试图通过制造“非鼓声音”来推动系统超越其预期领域,可以导致真正有趣的结果,其中一些结果实际上令人惊讶地充满音乐和灵感。

目前,Neural Beatbox 仅限于在巴比肯展览等公共场所展示,但我们也在考虑将它作为一个基于网络的互动作品开放。我们只是有点担心互联网上的人们可能会为这个装置贡献什么样的声音和视频…虽然结果可能会很搞笑和有趣,但它们可能也会很快包含一些 NSFW 的内容。;)

生成模型和价值

除了我最近在 Qosmo 的工作之外,我还和 AI 一起完成了一些我自己的艺术作品和一些与创造力相关的项目。在向您展示其中一些之前,我想简单快速地进行一次技术考察。

创意场景中使用的许多模型都属于“生成模型”这一大类。上面介绍的 GANs 就是其中的一个变种。

生成模型本质上是这样的模型,顾名思义,学习如何生成或多或少真实的数据。物理学家理查德·费曼的一句话很好地概括了这背后的一般思想。

"我不能创造的东西,我不明白。"—理查德·费曼

作为与人工智能合作的研究人员和工程师,我们希望如果我们能够教会我们的模型创建至少是模糊现实的数据,这些模型一定已经对真实世界的样子或行为方式有了某种“理解”。

换句话说,我们用创造和产生有意义的输出的能力作为智能的标志。

不幸的是,这种“理解”或“智能”仍然经常看起来像下面的图像。

Image credit: https://sufanon.fandom.com/wiki/File:Pix2pix.png

虽然我们的模型确实在学习真实世界的一些东西,但它们的知识领域通常非常有限,正如我们在上面的偏见例子中已经看到的那样。

在我之前从事实际商业应用的工作中,这是个坏消息。你不希望你的财务或医疗预测看起来像上面的图片!

然而现在作为一名艺术家,我发现这令人兴奋和鼓舞。事实上,正如已经指出的,许多艺术家故意寻找这些生成模型的断点或边缘案例。

我个人最喜欢的生成模型类型是所谓的变分自动编码器,或者简称为 VAEs 。我发现它们都非常通用,而且从信息论的角度来看,它们既漂亮又优雅。

简而言之,vae 将原始数据作为输入,然后通过信息瓶颈压缩和传输这些数据,最后尽可能精确地重建这些数据。

由于信息瓶颈(更专业地说:一个比数据空间维度低得多的潜在空间),模型不能只是直接传递数据,而必须学习高效的抽象和概念。

例如,如果我们想将它应用于狗和猫的图像,而不是简单地传输每一个像素值,则模型被迫学习抽象概念,如“狗”和“猫”的概念、腿和耳朵的概念、皮毛颜色等,这允许数据的更紧凑(尽管通常不是完全无损)的表示。

作为这个过程的一个整洁的副产品,我们得到了我们的数据的一个紧凑的数学描述,一个所谓的潜在向量或嵌入。这使得我们可以做各种有趣的事情,如有意义的数据比较以及数据点之间的真实插值,如上面 GAN 人脸的例子。

如果您想更详细地了解所有这些,我从两个玩家之间合作博弈的角度写了一篇关于 VAEs 的深入讨论。

* [## 作为双人游戏的可变自动编码器(上)

爱丽丝和鲍勃在自动编码奥运会上

towardsdatascience.com](/the-variational-autoencoder-as-a-two-player-game-part-i-4c3737f0987b)

个人项目

我想在下面展示的项目都以这样或那样的方式使用了 VAEs。

潜在脉动

当 VAE 被初始化时,它的数据表示是完全随机的,因为它还没有学习任何关于训练数据的东西。然后,随着训练的展开,网络逐渐学习不同的概念和抽象,相似数据的聚类开始在潜在空间中形成,随着模型收敛,这些聚类越来越清晰。

潜在脉动显示了一个这样的训练过程,从最初的随机混沌,到模型经历不同阶段,尝试不同的表示,最后确定在一个表现出相当明显的聚类。

此处潜在空间中的每个点代表大约 30 万条消费者投诉文本中的一条,这些文本涉及大约 12 种不同的金融产品(如“信用卡”、“学生贷款”等),用不同的颜色表示。

除了自然的学习过程,我还在嵌入中添加了一些周期性的随机噪声,以创建与轨道【2 Minds】【inside info】同步的节拍模式,时间从最初的 172bpm 延长到 160bpm,以更好地匹配视频帧速率。我选择了“两个头脑”这首歌,因为这个标题让我想起了 VAE 的编码器和解码器的关系。

通常,当用生成模型创作艺术时,我们会想到模型创作的实际输出。然而,潜在脉动颠覆了这一概念,表明潜在空间本身可以具有内在的美感和艺术品质,即使模型训练的数据显然是枯燥的,如本案例中使用的消费者投诉文本。

潜在景观

另一个相关的作品是潜在景观,它在视觉化潜在空间中根深蒂固的优雅和美丽方面走得更远。

我喜欢把这些看作是神经网络的“大脑扫描”。

从技术上来说,这些图像是通过分析潜在空间的潜在度量生成的(这件作品实际上是我们正在进行的研究论文的副产品)。粗略地说,潜在的空间不是“平的”,空间内的距离也不一致。潜在景观显示了在潜在空间的不同位置有多少弯曲,多少距离扭曲。

上面的结果也是基于在相同的金融投诉数据集上训练的 VAE,显示了令人想起外星景观或宇宙气体云的抽象形成。

就像在《潜在的脉动》中一样,网络本身,而不是生成模型的输出,成为了艺术品。

神经机能障碍

我要提到的最后一个项目是我迄今为止最大的个人项目。因为我之前已经在媒体上广泛地写了这个项目,我只想给你一个非常简短的概述。

NeuralFunk 是一个利用深度学习进行声音设计的实验。这是一个完全由神经网络合成的样本制成的实验轨道。

再说一次,神经网络不是音轨的创造者,但它们是用来创作音轨的唯一工具。因此,结果不是人工智能创作的音乐,而是用人工智能作为探索创造性表达新方式的工具创作的音乐。

在创建样本的过程中,我使用了两种不同类型的神经网络,一种是根据光谱图训练的 VAE 神经网络,另一种是 WaveNet 神经网络(还可以根据来自 VAE 的光谱图嵌入进行调节)。这些网络一起提供了许多工具来产生新的声音,从重新想象现有的样本或将多个样本组合成独特的声音,到完全无条件地创造全新的声音。

由此产生的样本然后被用来制作最终的轨道。

标题 NeuralFunk 的灵感来自鼓和低音子流派 Neurofunk 这是我最初的想法。但是在项目的过程中,它变成了更具实验性的东西,与声音设计过程本身的实验性质相匹配。

如果你想了解这个项目的全部细节(包括代码),可以看看我写的文章。

[## NeuralFunk -将深度学习与声音设计相结合

完全用神经网络产生的样本制作轨迹

towardsdatascience.com](/neuralfunk-combining-deep-learning-with-sound-design-91935759d628)

那么我的下一步是什么?

我有一个使用人工智能的扩展现场表演的大愿景,它将结合上面介绍的许多概念(和项目),并将它们带到一个新的水平,同时给我一种全新的音乐表演方式。

到目前为止,这不过是一个愿景,鉴于项目的规模,我甚至有点害怕开始。

然而,我目前正在非常积极热情地写一本关于休息时间的重要性的书。

虽然这看起来有点不着边际,但它实际上在几个方面完全融入了人工智能和创造力的关系。

为了让你相信这一点,让我们来做一个小小的旅行。起初,这看起来可能是随机的和不相关的,但是请耐心听我说,希望到最后你会同意我的观点,并对这个未来的愿景感到兴奋。

工作、休闲和创造力的未来

在人类历史的大部分时间里,工作的概念本质上等同于体力劳动。先是在田地和农场,后来在工厂。

在 20 世纪初,工厂工人平均每天工作 10 个小时以上,每周工作 6 天。

这一切都在 1926 年发生了变化,亨利·福特引入了八小时工作制和五天工作制(同时将工资大幅提高到行业标准以上)。

福特为什么要这么做?这不是因为他只是一个好人。他可能是,我不确定,但他这样做的原因更实际,更受商业驱动。

首先,他认识到,如果他提供比别人更好的工作条件,他就能轻易地吸引到最优秀的人才。这正是所发生的事情。最熟练的工人离开了他的竞争对手,排队到他的工厂工作。如果有人不表演,他就被解雇了。有足够多的人愿意接管这个职位。

第二,他认为如果人们没有空闲时间或者太累而不能利用空闲时间,他们就不会在休闲活动上花钱。

“有更多闲暇的人必须有更多的衣服。他们吃更多种类的食物。他们需要更多的交通工具。[……]休闲是不断增长的消费市场中不可或缺的成分,因为劳动人民需要有足够的空闲时间来寻找消费品的用途,包括汽车。”

这纯粹是经济上的。

通过给他的工人更多的休闲时间(和更多的钱花在休闲上),同样的工人最终能够并被激励去购买他们正在生产的产品。更多的空闲时间不会有害,反而会促进经济发展!

最后,也是我们讨论中最有趣的一点,他意识到他的员工可以在更短的时间内完成更好的工作,原因有两个。

对时间的限制会带来更多的创新和更好的方法。人们会真正考虑如何工作,而不仅仅是埋头苦干。

“我们可以在五天内获得至少和六天一样多的产量,我们可能会获得更大的产量,因为压力会带来更好的方法。”—亨利·福特

此外,休息得更好的员工通常更有效率,更有动力,也更少犯代价高昂的错误。

本质上,福特认为即使对于体力劳动来说,将忙碌等同于生产力也只是在一定程度上起作用。

大约在福特缩短其工厂工作时间的同时,哲学家伯特兰·罗素于 1936 年发表了他的精彩论文【歌颂懒惰】。

在这篇文章中,罗素指出,从历史上看,不是工作,而是对闲暇的庆祝让我们完成了许多我们现在认为是文明最大成就的事情。

“过去有一个小的休闲阶层和一个大的工人阶层。有闲阶级享有的优势在社会正义中是没有基础的[……]它几乎贡献了我们所称的文明的全部。它培育了艺术,发现了科学;它写了书,发明了哲学,改善了社会关系。甚至被压迫者的解放通常也是从上面开始的。没有有闲阶级,人类永远不会摆脱野蛮。”

他继续认为,前进的道路是重新发现我们对休闲和休假的欣赏(至少是高质量的休闲,如反思和沉思,而不是无休止地滚动我们的脸书饲料)。

让每个人都加入休闲阶层,而不仅仅是少数人。

我想严肃地说,在现代社会中,对工作美德的信仰正在造成巨大危害,而通往幸福和繁荣的道路在于有组织地减少工作。—伯特兰·罗素

鉴于 20 世纪初的这种趋势,我们现在应该生活在一种文化中,这种文化类似于古希腊和古罗马,高度重视休闲,并认为忙碌实际上是一种懒惰,缺乏时间管理和深刻的反思。

然而,事实似乎恰恰相反。我们发现自己身处一种文化中,这种文化常常把忙碌、压力和过度工作作为荣誉的象征、成就和骄傲的标志。一个按时下班并在白天充分休息的人不可能像一个日复一日长时间加班并且几乎不离开办公桌的人那样高效,对吗?

问题是,即使我们已经在很大程度上从体力劳动转向了知识工作,工人们仍然遭受着相当于工厂工作心态的智力折磨!

在某种程度上,这可能是合理的,目前仍然存在相当于工厂工作的大量智力残余。在这种工作中,投入的时间越多,产出越多(至少在一定程度上,就像亨利·福特意识到的那样)。

这是一种真正证明长时间工作和牺牲休息时间是合理的工作。但这也是最没有价值的一种工作。而且这个值一直在进一步递减。迅速地。这些正是被人工智能和其他生产力和自动化工具颠覆并最终取代的成熟任务。他们的日子已经屈指可数了。

在我之前的工作中,我领导了一个人工智能工具的开发,该工具帮助金融分析师搜索大量新闻数据,并从这些文本中产生见解。有了这个工具,分析师可以将搜索相关信息和为经理生成特定报告的时间减少 90%!在常规任务上浪费的时间减少了 90%,现在可以将这些时间重新投入到真正重要的工作中,真正利用他们的技能和创造力。

或者,它可以投资到休假中。这是一项值得的投资。

人工智能不会夺走我们的工作,也不会威胁或削弱我们的人类价值观。我的朋友和合著者约翰·菲奇和我认为事实正好相反。是的,人工智能将扰乱就业格局,但将会保留的工作以及新创造的工作将围绕创造力和同理心等人类技能。

这些技能相对于时间是高度非线性的。投入更多的时间绝对不等于产出更好或更高。事实上,很容易投入太多时间,忽略休息的平衡和滋养作用,结果减少一个人的产出。

在未来的工作中,休假将不会被认为是一件“值得拥有”的事情,或者是慷慨的雇主为吸引和留住人才而提供的诱人福利。

相反,有意识地休假将是关键技能和竞争优势之一。除了我们的工作伦理,我们应该认真开始思考我们的“休息伦理”。

约翰和我对这个未来非常兴奋,我们目前正在写一本关于休假的书。

* [## 休假-重新发现人类最伟大的实践之一

重新学习在不精疲力竭的情况下实现目标的失传艺术。

www.timeoffbook.com](https://www.timeoffbook.com)

我们希望鼓励更多的人重新发现这种似乎已经被遗忘的古老艺术,并就如何培养和利用高质量的休闲提供非常实用的技巧,以及分享历史和当代关于利用时间力量的惊人人物的不可思议的故事。

我们相信,专注于将同理心和创造力以及支持它们的休闲实践和习惯置于其企业或个人哲学核心的公司和个人将会蓬勃发展。

很快,这可能是唯一可行的选择。

忙碌工作很容易自动化,没有人,不管他们投入多少时间,牺牲多少生命,会在这些任务上胜过人工智能。

另一方面,创造力和同理心在未来很长一段时间内仍将是人类特有的。

那些理解这些技能以及新工具的人将不会把人工智能视为障碍或对手,而是作为一种使人类更上一层楼的技术。

能够让他们这样做的将是一种健康的工作和休闲节奏,以及有意识的休假实践。

所以我们不妨现在就开始练习!*

我希望这篇长文让你对人工智能艺术本身感到兴奋,以及人工智能将允许我们在未来更多地关注创造力的更广泛的影响。

我也希望我激励你自己采取行动。

如果你是一名人工智能从业者,希望你能玩玩你自己的人工智能艺术,也许从推动你的模型接近和超越它们的极限开始,看看它们如何表现。

但是不管你是否直接与人工智能一起工作,我真的希望你能考虑用更多更好的时间来练习。

不是偷懒,也不是偷懒。这是你对自己最好的投资之一!

让我们把无用功留给 AI,变得更有人情味!*

熊猫和模特的下一步

原文:https://towardsdatascience.com/next-steps-with-pandas-and-modeling-5e6e36672e39?source=collection_archive---------12-----------------------

Not for wildlife enthusiasts, but data scientists. Copyright Chi King under the Creative Commons Attribution 2 Generic License. No changes were made to this image.

到目前为止,您已经学习了机器学习的基础知识,以及一点 Python 3 和 Pandas。下面是一些后续步骤和免费资源,让你开始行动。我会继续在这里添加我想到的信息,或者评论中的建议。

  • 阅读熊猫文档

此时,您不应该像阅读一本书一样阅读文档(尽管如果这对您有用,您可以这样做)。自上而下浏览文档,熟悉各种可用的主题。

在查看堆栈溢出之前,特别是如果您想提出问题,请查看文档。我更喜欢查找我当前的疑问或问题,并通读相关部分。

例如,我经常不得不编写自己的日期时间解析器,并将其传递给 read_csv 。我还传递了自己的数据类型列表,以获得正确的数据框。文档中有这两种情况的示例。

文档还包括食谱,非常值得浏览。

  • 将 Pandas 用于大型数据集

在创建了我的 Pandas 数据框之后,我使用 Pandas 创建了大约 30 GB 的数据集。这个过程包括导入、清理、合并 Pandas 数据帧和旋转(如果需要的话)。在 Pandas 中使用大型数据集有多种策略。查看文档和这个关于栈溢出的问题。小心栈溢出的老问题,因为它们可能涉及过时的特性或熊猫编码风格。

用于 Tensorflow 的 Dask和 Dask-ml 可能是你的下一步,还有分布式 Tensorflow 。在走这条路之前,确保你能彻底证明资源的花费是合理的。制定一份书面计划,并在做出最终决定前征求反馈。

  • 用 tsfresh 提取日期/时间特征

不要试图自己构建依赖于时间的特征(星期几等)。

  • 通过指定 dtypes 减少内存使用

不要只接受熊猫的推断。检查数据类型,并仔细查看没有按预期显示的列。如果已知一个列只包含浮点数或整数,并且它显示为对象,那么请仔细检查它。

如果您知道某个特定的列是一个范围有限的整数,比如 1–3,请指定数据类型。例如

并且要小心具有混合数据类型的列。 Pandas 使用数据块而不是整列来推断数据类型。所以仔细检查导入数据的数据类型是必要的。

  • 汤姆·奥格斯佩格的《现代熊猫》

我从阅读汤姆的书中受益匪浅,这本书是免费的。不过,我劝你还是付他点什么吧,要看你自己的情况。

  • 克里斯·阿尔邦和技术笔记

另一个优秀的免费资源。当你遇到问题或疑问时,请在这里查阅。

  • 学习贝叶斯方法

正如 Cal Davidson Pilon 在他的书 概率编程和针对黑客的贝叶斯方法 中指出的,贝叶斯方法在统计学书籍中经常受到冷遇。贝叶斯方法优雅、有用,是思考某些问题的一种非常自然的方式。我们现在都有计算资源,如数字海洋、自动气象站等。所以贝叶斯方法现在已经可以实际学习和使用了。

Pilon 首先通过编码,然后是理论来介绍贝叶斯方法,这不仅是开发 Python 技能的极好方法,也是获得工作模型的极好方法。

艾伦·唐尼的《思维贝叶斯》和《思维统计》都是免费的,也值得一读。

  • 最好的计算和学习资源

最佳永远是一个相对名词。这就是为什么 Stack 的人会问很多封闭的问题,询问使用哪种技术或者哪种技术是 T2 最好的。 Tim Dettmers 发表了一篇评估各种 NVIDIA 卡的性价比的优秀博文。挑选一台符合你预算的二手电脑,但在购买之前,确保你了解你需要的计算能力。

最新的驱动程序更新可能不支持旧的 AMD 卡。

如果你正在寻找便宜的培训或教程资源,不要忽视甲骨文、英伟达、英特尔或 AMD 的开发者网站。例如,英伟达提供相关技术的在线课程,如 OpenACC。

  • 参与挑战

例如, Kaggle 数据清理挑战可以锻炼你的技能。创建几个笔记本在 GitHub 上展示总是一件好事,可以传递给潜在的雇主,或者作为在当地 PyData meetup 上准备演讲的提纲。

  • 参加您当地的 PyData 聚会

请在评论中留下优质资源。我一直在寻找对这份文件的补充。

熊猫形象版权所有 驰王知识共享署名 2通用许可。没有对此图像进行任何更改。**

NFL 教练是如此,如此可预测

原文:https://towardsdatascience.com/nfl-coaches-are-so-so-predictable-3e15fa69bd32?source=collection_archive---------12-----------------------

深入分析

Source: Pixable

周日,深秋。我在看匹兹堡钢人队,我开始生气了。这是托德·哈利时代,你可以肯定,在比赛的某个时刻,钢人队将会遵循以下比赛顺序:跑-跑-传球-踢。钢人队有可能赢得这场比赛吗?他们在场上的什么位置?他们目前赢了吗?没关系——和现代 NFL 中的许多其他进攻协调人一样,Haley 也有自己的风格。某种…可预测性。他可能会改变路线和阵型,但是类型的比赛——第一次进攻,在只剩两码的时候第三次传球——似乎太容易预测了,即使是对普通球迷来说。

不久前,如果不为数据付费或从各种来源获取大量数据,很难量化 Haley 和其他 OCs 在他们的游戏呼叫中的可预测性。但是多亏了马克西姆·霍洛维茨和罗恩·尤尔科的NFL scraper软件包,获得每场比赛的详细数据从未如此简单。所以我决定进行调查:NFL 的比赛召唤有多可预测?

为此,我使用 NFL scraper(所有用于分析的代码都可以在这里找到)收集了 2009 年至 2018 年的详细数据。我想了解的第一件事是跟注的游戏条件。我最喜欢的一个包含大量游戏场景信息的指标是获胜概率,或者基于当前的游戏条件,如分数、剩余时间、场地位置等,X 队最终赢得游戏的可能性有多大。具体来说,我想了解基于球队控球时的预扣胜率的打法会被称为什么打法。让我们从这里开始,第一步,看看快照前成功概率的一般分布。

好吧,不完全是正态分布,但在被称为胜率极高或极低的比赛中,也没有太多的模式。好了,检查完毕后,让我们来看看这是如何按玩法来划分的。在我的数据集中,有 398,645 次播放。这是按游戏类型的分类:

下面,您将看到两个独立的可视化效果——在左边,方框图显示了调用的时间汇总,在右边,我绘制了所有数据,以便更好地了解真实的分布情况:

**

哇哦。教练都是疯狂保守的!当一个球队获胜的机会少于 50%时,通常会判平底球、第四次传球和越位球…而且通常在击球前的概率要低得多。你可以说我疯了,但是当球队更有可能输球而不是赢球时,他们应该尽一切努力保住控球权,然而,当拥有控球权的球队有将近 55%的概率输掉比赛时,平均的控球率就会出现。

因此,数据告诉我们,当涉及到比赛叫牌时,教练有一些奇怪的倾向,至少在赛前获胜概率的背景下是如此。但也许还有其他的情境因素影响着他们所谓的戏剧类型,而这些戏剧在当时是最有意义的。

为了分析这是否是真的,我建立了一个分类模型,该模型只包含一些变量,以了解 NFL 中“可预测”的比赛召唤实际上是多少。从那里,我研究了多少可预测性如何影响胜利的可能性,以及不可预测性对每场比赛的平均和整体影响。

我不打算进入我如何建立分类模型的细节(或其他技术的许多细节——你可以随时查看代码或在 Twitter 上联系我),但我想让模型尽可能“天真”——这意味着我没有让模型暴露尽可能多的信息。也就是说,我没有让模特知道谁在和谁比赛,也没有让模特知道赛季的星期。这些都是可以提高准确性的变量,但是我不希望个别球队和/或赛季动态压倒比赛召唤的情境方面。

也就是说,我在 2009 年至 2018 年的逐场比赛数据样本上训练了我的模型,并在同一时期随机抽取的样本上进行了测试。模型中包括的特征描述了比赛的预扣分情况— 击倒、距离、场上位置、剩余时间、比分差距、预扣分获胜概率和各种预期得分结果(即下一次得分比赛的可能性)。我也控制了季节。

该模型表明,NFL 中的比赛呼叫是令人惊讶地可预测的——该模型在训练和测试集中正确地“呼叫”了大约 77%的比赛(参见代码以了解其他度量,如精度、kappa 等)。正如你在下面的混淆矩阵中看到的,这个模型在预测什么样的打法会被叫牌上没有太大的困难,只是在跑动和传球上有点混淆。如果我给出了有关团队参与的模型信息或其他更广泛的战术风格的历史特征,这可能会得到澄清。

现在我们有了广义的“可预测性”,我们可以检查哪些团队比“平均水平”更可预测或更不可预测在分析的时间段内,新英格兰队是最难预测的球队之一,这并不令人惊讶:

这张图表显示,该模型正确地预测了充电器在 2009 年至 2018 年期间播放的所有戏剧中的近 80%,这还没有提到克拉伦斯·谢尔蒙、哈尔·亨特、肯·惠森杭特、弗兰克·赖克。虽然这并不完全相关,但在这个时间段内普遍成功的团队聚集在图表中不太可预测的一侧。

这种相关性很有趣,部分原因是很难在 NFL 保持几年以上的好成绩,还因为该模型考虑了每一场比赛——这张图表只是从总体上考察了“可预测性”。那么每场比赛的可预测性是如何影响输赢的呢?

第一步只是看看每场比赛的可预测性有多分散。在左边,我按游戏绘制了广义分类模型的准确性,区分了输和赢(灰色= 0 =输,蓝色= 1 =赢)。该模型是全面可靠的,几乎在每场比赛中都预测了超过 60%的吹罚,并且在一些比赛中接近 95%是正确的。但是正如你从上面直方图相似的形状和高度可以看到的,仅仅是可预测性并不能很好的区分成功和失败。这表明,有一些潜在的变量可以更好地区分成败,团队质量是最明显的一个。

考虑到这一点,我想在控制团队实力的同时,模拟出每场比赛的可预测性对输赢的影响。通过使用可预测性和团队来拟合每场比赛结果的 logit 模型,我们可以做到这一点。而且结果很有意思!

首先要注意的是,仅仅使用团队、可预测性和一个简单的模型,我们就可以相当准确地从输家中挑选赢家。左侧的图表是一个混淆表,显示了模型的校准统计数据(基本上,如果我们分配 10 个团队有 70%的获胜机会,那么从长远来看,7 个团队应该会获胜——这与您应该如何测量天气预报的准确性类似)。在右边,我们可以看到一旦我们控制了整个团队的力量,可预测性是如何影响胜利的可能性的。基本上,你的叫牌越不可预测,你赢得比赛的可能性就越大(某人,请将这篇文章发给 Randy Fichtner )。

**

所以结论是…在你的叫牌中少一些可预测性,你就能赢得比赛。对吗?

不完全是。这项分析之前的一切主要集中在 NFL 的比赛召唤是否是普遍可预测的。它没有检查正在被调用的戏剧是好是坏。毕竟,如果教练已经在优化他们的战术选择,那么可预测性可能是好的。这种分析并没有深入到的比赛实际上叫什么,场上有什么人员,以及一个团队执行得有多好。但我们可以大致估计,当其他教练转向时,转向是否有价值。

为了做到这一点,我使用了另一个我喜欢的叫做胜利概率的指标。基本上,你在比赛开始前测量一个队获胜的可能性,然后在比赛结束后再次测量这个可能性。这两个概率的差异是该游戏在促成胜利方面的成功或不成功程度(增加的胜利概率可以是负的,只是你在你的起始位置“增加”了一个负值)。

我们可以使用观察到的 WPA 来创建一个 eWPA 模型,或按游戏类型创建预期的 WPA。然后,我们针对模型“称之为”错误的打法,将实际的 WPA 与 eWPA 进行比较,因为这些打法是教练偏离他们的平均水平的打法。然后,我们可以看到当他们偏离时团队的效率如何,以及这在整个赛季中对他们团队的帮助有多大。

**

正如你从上面的图表中看到的,有一些证据表明,偏离预期的行动号召会增加一个团队获胜的几率。在每场比赛的基础上,一场意想不到的比赛价值约 0.07%的额外 WPA 跨越团队赛季。这听起来可能不多,但是整个赛季加起来,平均每个队加起来有 21%的获胜概率**。只有 5 支队伍在曲折前进而不是曲折前进时产生的 WPA 比预期的少。这就是大多数球队都在跑的时候球队应该投球的决定性证据吗?不一定。但是有一些统计证据表明 NFL 的比赛召唤是次优的。我不是第一个得出这个结论的分析师(或粉丝)。**

无论是哪种情况,我希望你喜欢这次对 NFL 比赛召唤倾向的深入研究,以及如何将高级分析技术应用于比赛数据可以产生一些有趣的见解。现在,我们需要做的就是让教练在他们预计会输的时候停止踢皮球…

NGBoost 解释道

原文:https://towardsdatascience.com/ngboost-explained-comparison-to-lightgbm-and-xgboost-fda510903e53?source=collection_archive---------4-----------------------

现实世界中的数据科学

与 LightGBM 和 XGBoost 的比较

Photo by James Pond on Unsplash

Stanford ML Group 最近在他们的论文,【1】Duan et al .,2019 及其实现中公布了一种新算法,名为 NGBoost。该算法通过使用自然梯度将不确定性估计包括到梯度增强中。本文试图理解这种新算法,并与其他流行的 boosting 算法 LightGBM 和 XGboost 进行比较,看看它在实践中是如何工作的。

内容

  1. 什么是自然渐变增强?

  2. 经验验证—与 LightGBM 和 XGBoost 的比较

  3. 结论

  4. 什么是自然渐变增强?

正如我在简介中所写的,NGBoost 是一种新的提升算法,它使用自然梯度提升,这是一种用于概率预测的模块化提升算法。该算法由基本学习器参数概率分布评分规则组成。我将简要解释这些术语是什么。

From the paper, Duan, et at., 2019

  • 基础学习者

该算法使用基础(弱)学习器。它采用输入 x ,输出用于形成条件概率。那些基础学习者对树学习者使用 scikit-learn 的决策树,对线性学习者使用岭回归。

  • 参数概率分布

参数概率分布是一种条件分布。这由基础学习者输出的附加组合形成。

  • 评分规则

评分规则采用预测的概率分布和对目标特征的一次观察来为预测评分,其中结果的真实分布在预期中获得最佳评分。该算法使用最大似然估计或 CRPS。

我们刚刚学习了 NGBoost 的基本概念。我绝对推荐你阅读原文进一步理解(有数学符号的算法更容易理解)。

2。经验验证—与 LightGBM 和 XGBoost 的比较

Photo by billy lee on Unsplash

让我们实现 NGBoost,看看它的性能如何。原论文也在各种数据集上做了一些实验。他们比较了 MC dropout、Deep Ensembles 和 NGBoost 在回归问题中的表现,NGBoost 显示了其极具竞争力的性能。在这篇博文中,我想展示一下模型在 Kaggle 上著名的房价预测数据集上的表现。该数据集由 81 个要素、1460 行组成,目标要素是销售价格。让我们看看 NGBoost 可以处理这些情况。

Distribution of the target feature

由于测试算法的性能是这篇文章的目的,我们将跳过整个特征工程部分,将使用那那西的解决方案。

导入包;

# import packages
import pandas as pdfrom ngboost.ngboost import NGBoost
from ngboost.learners import default_tree_learner
from ngboost.distns import Normal
from ngboost.scores import MLEimport lightgbm as lgbimport xgboost as xgbfrom sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
from math import sqrt

这里我将使用上面的默认学习者、分布和评分规则。用这些东西来玩会很有趣,看看结果会有什么变化。

# read the dataset
df = pd.read_csv('~/train.csv')# feature engineering
tr, te = Nanashi_solution(df)

现在用 NGBoost 算法预测。

# NGBoost
ngb = NGBoost(Base=default_tree_learner, Dist=Normal, Score=MLE(), natural_gradient=True,verbose=False)ngboost = ngb.fit(np.asarray(tr.drop(['SalePrice'],1)), np.asarray(tr.SalePrice))y_pred_ngb = pd.DataFrame(ngb.predict(te.drop(['SalePrice'],1)))

对 LightGBM 和 XGBoost 进行同样的操作。

# LightGBM
ltr = lgb.Dataset(tr.drop(['SalePrice'],1),label=tr['SalePrice'])param = {
'bagging_freq': 5,
'bagging_fraction': 0.6,
'bagging_seed': 123,
'boost_from_average':'false',
'boost': 'gbdt',
'feature_fraction': 0.3,
'learning_rate': .01,
'max_depth': 3,
'metric':'rmse',
'min_data_in_leaf': 128,
'min_sum_hessian_in_leaf': 8,
'num_leaves': 128,
'num_threads': 8,
'tree_learner': 'serial',
'objective': 'regression',
'verbosity': -1,
'random_state':123,
'max_bin': 8,
'early_stopping_round':100
}lgbm = lgb.train(param,ltr,num_boost_round=10000,valid_sets=[(ltr)],verbose_eval=1000)y_pred_lgb = lgbm.predict(te.drop(['SalePrice'],1))
y_pred_lgb = np.where(y_pred>=.25,1,0)# XGBoost
params = {'max_depth': 4, 'eta': 0.01, 'objective':'reg:squarederror', 'eval_metric':['rmse'],'booster':'gbtree', 'verbosity':0,'sample_type':'weighted','max_delta_step':4, 'subsample':.5, 'min_child_weight':100,'early_stopping_round':50}dtr, dte = xgb.DMatrix(tr.drop(['SalePrice'],1),label=tr.SalePrice), xgb.DMatrix(te.drop(['SalePrice'],1),label=te.SalePrice)num_round = 5000
xgbst = xgb.train(params,dtr,num_round,verbose_eval=500)y_pred_xgb = xgbst.predict(dte)

现在我们有了所有算法的预测。让我们检查一下准确性。我们将使用与这次卡格尔比赛相同的标准,RMSE。

# Check the results
print('RMSE: NGBoost', round(sqrt(mean_squared_error(X_val.SalePrice,y_pred_ngb)),4))
print('RMSE: LGBM', round(sqrt(mean_squared_error(X_val.SalePrice,y_pred_lgbm)),4))
print('RMSE: XGBoost', round(sqrt(mean_squared_error(X_val.SalePrice,y_pred_xgb)),4))

以下是预测结果汇总。

Summary of the results

看起来 NGBoost 胜过了其他著名的 boosting 算法。平心而论,我感觉如果调一下 BGBoost 的参数,会更好。

NGBoost 与其他 boosting 算法的最大区别之一是可以返回每个预测的概率分布。这可以通过使用 pred_dist 函数来可视化。该功能能够显示概率预测的结果。

# see the probability distributions by visualising
Y_dists = ngb.pred_dist(X_val.drop(['SalePrice'],1))
y_range = np.linspace(min(X_val.SalePrice), max(X_val.SalePrice), 200)
dist_values = Y_dists.pdf(y_range).transpose()# plot index 0 and 114
idx = 114
plt.plot(y_range,dist_values[idx])
plt.title(f"idx: {idx}")
plt.tight_layout()
plt.show()

Probability distribution examples

上面的图是每个预测的概率分布。x 轴显示销售价格的对数值(目标特征)。我们可以观察到,索引 0 的概率分布比索引 114 更宽。

4。结论和想法

从实验结果来看,NGBoost 和其他著名的 boosting 算法一样好。然而,计算时间比其他两种算法要长得多。这可以通过使用二次抽样方法来改善。此外,我有一个印象,NGBoost 包仍在进行中,例如没有提前停止选项,没有显示中间结果的选项,选择基础学习者的灵活性(到目前为止,我们只能在决策树和岭回归之间选择),设置随机状态种子,等等。我相信这几点很快就会落实。或者你可以为项目做贡献:)

你也可以在我的 GitHub 页面上找到我在这篇文章中使用的代码。

包裹

  • NGBoost 是一种新的 boosting 算法,它返回概率分布。
  • 自然梯度推进,一种用于概率预测的模块化推进算法。这由基本学习器参数概率分布和 S 取芯规则组成。
  • NGBoost 预测与其他流行的 boosting 算法相比具有很强的竞争力。

如果你觉得这个故事有帮助,有趣或什么的,或者如果你有任何问题,反馈或字面上的任何东西,请随时在下面留下评论:)我真的很感激。还有,你可以在 LinkedIn 上找到我。

参考:

[1] T. Duan 等, NGBoost:概率预测的自然梯度推进 (2019),ArXiv 1910.03225

使用标准和高级曲棍球统计数据的 NHL 球员评级

原文:https://towardsdatascience.com/nhl-player-rating-using-standard-and-advanced-hockey-stats-af2a9537909e?source=collection_archive---------9-----------------------

玩 EA sports (EAS) NHL(或众所周知的 Chel)这些年来,我经常想知道他们是如何得出他们的玩家评级的。根据每个球员的简历和个人资料,总得分(通常在 70 到 100 之间)是由每个球员的各种参数组合而成的。例如,速度、加速度、击球力量和击球准确度(或类似)、球棍处理能力、耐力、攻击性、强度等等。然而,在现实中,你如何衡量强度或侵略性,甚至坚持处理能力,以至于你可以在与其他人的比较中得分?EAS 分级系统的整个概念(对于他们所有的体育比赛)是一个鲜为人知的秘密。但它确实让我想知道是否有可能建立我自己的玩家评级系统(让我们称之为 Sigmoid 玩家评级;SPR)只使用优秀的老玩家指标。在之前的一篇文章中,我制作了一个模型,使用各种表现指标来预测球员工资。这里,我将使用相同的性能数据集来生成玩家评级。

数据集

使用的最终数据集是传统和高级玩家指标的组合。传统的统计数据涉及进球和助攻(总得分)、加减分、点球时间和冰上时间等指标,而高级球员指标则更多地涉及球员行为和控球。利用 Python 的 beautifulsoup 库,我刮到了更多传统的统计数据(比如进球、助攻、积分等。)来自 www.Hockey-reference.com 的,,而高级指标则由 www.corsica.hockey 提供。科西嘉曲棍球的高级曲棍球统计从 2008 年开始,因此,我有近 2000 名球员的数据,跨越 2008 年至 2018 年。需要注意的是,我只考虑了游戏处于平均水平时的高级统计数据。数据被清除掉丢失的值,并被传入 Pandas 进行分析。虽然,我计划最终达到它,这个评级系统只适用于运动员,而不是守门员。守门员的统计和溜冰者的统计非常不同。

模型概念

我熟悉其他一些玩家的评级方法,我的想法建立在那些聪明的评级系统之上。基本上,我们获取单个参数,对每个参数应用一个权重,然后对它们求和。本质上,该模型是单个加权参数的总和。最难的部分是确定哪些是最重要的参数,以及应该给每个参数什么权重。从我之前的帖子可以看出,使用随机森林分类器可以确定一些更重要的特征。因此,我将使用其中的一些功能。每个参数权重的选择有些随意。我可以使用 EAS 评级作为事实,并尝试使用一些机器学习方法来预测权重。虽然这似乎不是一个坏主意,但这些评级有太多的未知。它们真的是基于玩家的衡量标准,还是通过某种人为因素测量设备神奇地计算出来的?他们的收视率是基于上一季的,还是几季的平均值?他们的算法每年都会改变吗?对我来说,探索这条路线有太多的不确定性。因此,我提出了我自己的权重,在我看来,这似乎很好。

将所有选定的参数加在一起是一个好的开始,但这并不意味着结果在空间上是连续的。什么时候我们达到了最大值 100?也许下个赛季,有人超过了 100 分,这意味着前一年的收视率已经过时了。为了克服这个连续性问题,我们可以利用 Sigmoid 函数,它在下面的公式中描述,

概率 P 被描述为输入变量 x,的函数,其中 z 是由常数β0 描述的多项式表达式,权重 w,其中输入参数 x 用于从 i=1 到 n 的所有包含参数。用图形表示,这可以如图 1 所示。

Fig1: A standard Sigmoid function where the sum of weighted parameters can be represented as a probability value

可以看出,S 曲线充当概率曲线,并且渐近地接近 0 和 100,并且在 50 处穿过 y 轴。Sigmoid 函数主要用于机器学习逻辑回归问题,在给定一组独立输入参数的情况下,通过将其从优势空间的对数转换到概率空间来识别因变量的二分法分类。

同时,我们已经有了预先确定的权重,我们不打算在这里对任何东西进行分类,我们仍然可以利用通过标准 Sigmoid 函数传递参数的多项式组合。从图 1 可以看出,随着值接近+∞和-∞,对 y 轴的灵敏度降低。本质上,玩家将具有介于 50 和 99.9(递归地)之间的评级,因为每个玩家的权重之和应该大于零。

高级曲棍球统计术语词汇

我假设读者理解基本曲棍球统计数据的概念,如得分(进球+助攻)、平均上场时间(每场)、盖帽、放弃、带走、命中、罚分、罚分、赢分、输分。但是,也许有一些更高级的指标是外来的,所以我将简要解释它们的含义。

CF%: CF 代表“Corsi For”,这是当一名球员在冰上时该球员的球队产生的射门次数,与“Corsi Against”(CA)相对,这是当该球员在冰上时对方球队产生的射门次数。CF%简单来说就是 CF / (CF + CA)。

CFQoC:比赛平均 CF%的质量。数字越高,竞争程度越高。关于它的解释,这是一个有些争议的统计数据,但我喜欢它被用在 OZS 的上下文中(见下文)。

CFQoT:这是玩家的队友的 CF%。它表明了一个球员相对于他的队友对整体比赛的贡献。通常这是一个很好的指标,可以看出某个球员是否让他周围的球员变得更好。

OZS:进攻区开始。给定球员在进攻区域开始移动的次数百分比。

PDO:这不是一个首字母缩写词,是由曲棍球博客作家维克·法拉利起的名。这只是运气的代表。它是球员在冰上时的射门百分比加上他所在球队的扑救百分比。更多精彩文章点击此处。

xGF%:的预期目标与的预期目标的比率。预期目标仅仅是给定射门得分的可能性。它提供了对拍摄质量的判断。因此,xG 值为 0.2,意味着射门的概率为 20%。从本质上讲,这里的高得分球员都有高质量的机会。

DPS:防守点股。由 Hockeyreference.com 设计的三个标准之一(其他标准是进攻得分份额和守门员得分份额),使用边际进球得分和边际进球得分的概念为球员的每一分分配一个分数。获得 DPS 比 OPS 更难,因此防守型前锋和 D-men 比大多数进攻型前锋有更高的 DPS。更多信息见链接

该算法

这里的 python 代码片段(图 2)显示了在堆叠单个参数(GSS_adj)并通过 Sigmoid 函数传递它们之前,我所使用的算法和权重。

该算法背后的思想相当复杂,在这篇文章中,我们将尽可能详尽地解释这一切。相反,你可以在我的 Github 库上找到更多。我会说一些事情;

1)我用分数来衡量成功。我不区分进球,第一次和第二次助攻。对我来说,不管你在哪里,做了什么,如果你为目标做出了贡献,那么你就是富有成效的。一个进球是如何得分的完全取决于具体情况,并且因进球而异。

2)计算权重,使得平均而言,堆叠的“GSS_adj”中的大部分权重(50%)来自点数(生产率),“defn”约占35%(责任),“toi”约占~8%(耐力),其他参数构成其余部分(杂项)。

3)只考虑给定赛季 10 场以上的球员。

4)玩家的评级基于通过 82 场游戏预测的统计数据。

等级

以下总体评级(SPR)是过去三年(2016 年、2017 年、2018 年)个人年度评级的加权平均值,因此,玩了所有三年的玩家的个人年度评级在前一年、两年前、三年前分别加权分布为 50%、30%和 20%。

对于在过去三年中只打了两个赛季的球员,最近一年的总体评分权重为 60%,最老的一年为 40%。最近三年只有一个赛季的球员,没有加权。考虑到表 1,这里出现的一些名字并不令人惊讶。一些名字不见了,包括 Auston Matthews,Mitch Marner,Nathan MacKinnon,Mikko Rantanen,Gabe Landeskog 和 Johnny Gaudreau。尽管他们去年都表现强劲,但这是一个加权平均值,因此前几年对总体评分略有限制,但他们的得分在 87 至 90 分之间,相当可观。鉴于它们今年的表现,它们 2019 年的 SPR 值将会更高。需要注意的是,马特-巴尔扎尔和叶夫根尼-达多诺夫只踢了一个赛季。

与 EA Sports 相比

所以,让我们来验证一下。虽然 EAS 的评级不一定是真理,但这是促使我首先制作自己的评级系统的原因,因此将这里的总体评级与 EAS 的评级进行比较似乎是正确的。应该重申的是,我不是要复制 EAS,但是我们需要一些基准来比较。图 4。显示 EAS 玩家评级(2018-2019 版,但评级基于 2017-2018 赛季)作为每个 EAS 评级大于 73 (99%的数据)的玩家的 SPR 的函数。R2 值为 0.76,具有很强的统计学显著相关性(r = 0.87,P 值= 0),这意味着 76%的 EAS 评级可变性可以用 SPR 来解释。RMSE 为 2.6,最佳拟合线幅度为 0.60,截距为 32.5。从小到大有少量的同方差。本质上,SPR 倾向于高估约 82 以上的 EAS(即最佳拟合线穿过 1–1 线的位置),低估以下的 EAS,但总体而言,存在良好的相关性。

Fig 4. EAS ratings as a function of SPR with best fit line, and 1–1 line plotted for comparison

考虑比较的另一种方法是检查每个评级人群的分布关系。图五。显示了 SPR 和 EAS 的分布图以及 KDE 曲线。可以看出,除了 SPR 更宽之外,两种分布在形状上相似,具有双峰结构。我们可以测试这两个平均值之间的差异是否具有统计学意义。通过这样做,我们可以研究 SPR-EAS 分布是否代表相同的分布。这里,我们将 P 值显著性阈值设置为 0.05(或 5%)。

Fig 5. Distributions and KDE’s for SPR and EA Sports values

P 值越低,获得与零假设为真时观察到的结果相似的结果的概率越低(因此,它不是偶然发生的)。这两种分布都不属于正态分布。

然而,我们可以利用中心极限定理(CLT ),从每个分布中随机抽取样本。CLT 指出,对于抽取的足够大量的样本,假设样本过程是随机的,并且每个抽取的样本都是独立的(即一个玩家的评级不会影响另一个),那么最终的分布将是平均值附近的正态分布,我们可以对其进行假设检验。下面是这样一个例子,从每个分布中随机抽取 500 个样本(替换),计算平均值。这个过程重复约 527 次(SPR 和 EAS 数据集的长度),以确保正常(图 6。).

Fig 6. Sampling distributions of SPR and EA Sports values

因为我们有两个正态分布,我们现在可以进行假设检验。由于两个分布之间的方差不同,我们进行了韦尔奇 T 检验。无效假设是 SPR 和 EAS 评级之间的平均评级之间没有关系。在进行假设检验时,P 值= 0(即<0.05) and Cohen’s D value > 2 ),这意味着我们应该拒绝零假设,并且在抽样 SPR 和 EAS 评级均值之间存在很大的统计显著差异。此外,还进行了 Kolmogorov-Smirnov 检验,以确定是否可以从同一分布中抽取 2 个随机样本。这也证明了 P 值=0,也得出两个分布不同的结论。

总的来说这意味着什么?尽管我们发现 SPR 和 EAS 值之间有很强的相关性,但分布被认为是彼此非常不同的。这很好,如果他们来自同一个发行版,那么我也可以只使用 EAS 评级,这不是这里的重点!

模型问题

这个模型有几个地方出了问题,可以改进。与 EAS 相比,这个模型低估了防守型的防守队员。我需要想办法给这些球员更多的信任。他们往往有良好的“责任”价值观,但由于他们没有贡献分数,因此很可能会错过机会,尽管他们对团队的整体贡献很重要。另一个问题是 82 场比赛的预测。很难证明如果一个球员只打了 48 场比赛,然后受伤错过了剩下的赛季,他会取得什么成就。选择投射到 82 场比赛是为了让每个人都在相同的出场频率上被比较。它的工作方式与计算每场游戏费率的“选择指标”值相同。然而,谁能说一个特定的球员会继续得分,击球,得分等等。考虑到赛季的长度和球员的疲劳,或者随着时间的推移,速度会减慢。通过考虑一个球员的统计数据是如何随时间变化的,可以得到某种基线。这是我在未来版本中可能会考虑的事情。

结论

虽然这很好地预测了每个玩家的评分,但我们必须记住这只是一个模型。它没有对错之分,只是提供了一个真相的“暗示”。这里有一些东西,我认为是构成一个曲棍球运动员的重要特征,如果有的话,但是这些选择可能不适合其他人。然而,我们已经看到,使用 Sigmoid 函数可以很好地构建这样的模型,如果 EAS 使用类似的方法,我不会感到惊讶。如果你对 2017-2018 赛季结束时的完整评级感兴趣,你可以在我的 Github 资源库上找到它们作为 2018.csv。感谢阅读!

尼古拉斯·凯奇——虚假的泳池救星?

原文:https://towardsdatascience.com/nicholas-cage-pool-saviour-9c13feafff6f?source=collection_archive---------17-----------------------

Photo by Brooklyn Morgan on Unsplash

测试虚假的相关性

好吧,我坦率地告诉你,我不完全确定我在这里发现了什么。不知何故,我觉得在我周末做的这个有点仓促的分析背后有一个秘密的意义。不知何故,在某个地方,电影中尼古拉斯·凯奇的魔力并不局限于我的内心深处,但事实上,就像标题图片中尼古拉斯·凯奇在 Con Air 的华丽鬃毛一样,他涵盖了整个世界。让我们来看看我可能不应该做的事情。如果你想跳到精彩的部分,你要找的图表就在页面的一半,非常有趣。

好吧,我们从头开始…

在你漫游互联网的时候,你可能会碰到这个有趣的图表。

from: http://tylervigen.com

这个图表和其他类似的 tylervigen.com 图表的目的是教育人们相信相关性等于因果关系的谬论。现在,虽然尼古拉斯·凯奇出演的电影数量和掉进游泳池淹死的人数之间看起来确实有关系,但我们知道事实并非如此。

然而,作为尼古拉斯·凯奇的超级粉丝,我相信除了这种简单的关联,也许还有更多证据。如果我们尝试针对我们的池数据设置一组不同的 Nicholas Cage 相关数据会怎么样?我们能找到相关性吗?更好的是,我们会发现负相关吗?我们会发现尼古拉斯·凯奇和他辉煌的电影生涯减少了溺死在泳池中的人数吗?我必须弄清楚。

传奇开始了…

最明显的地方开始检查尼古拉斯凯奇效应对我们的泳池溺水数据将是看他的电影质量。也就是好的尼古拉斯凯奇电影有助于减少泳池死亡吗?为此,我前往烂番茄,去看看老好人尼克的职业生涯。匆匆一瞥,他的职业生涯跨越了令人印象深刻的 38 年,有 100 多部电影值得称赞。它们各不相同,从热门的《T2 离开拉斯韦加斯》到票房炸弹的《T4》《幽灵骑士》……以及它的续集()说真的,我喜欢这个家伙,但是谁会为此买单呢?! )

A sample of the data we will be using.

因此,在使用美丽的汤进行了一些轻微的网络搜索之后(对不起,烂番茄,这是为了更大的利益!我现在自豪地拥有尼古拉斯·凯奇的分级电影记录。下一步是清理数据。我想特别针对尼古拉斯·凯奇不仅仅是制片人、导演或任何其他职位的电影。我觉得最好的成功指标是尼古拉斯·凯奇出现在屏幕上的电影,或贡献出他独特的声音和措辞,历史上曾让观众高兴。所以再见了大卫·盖尔的一生* ( 不知道他是制片人),再见了吸血鬼的影子 ( 真的?太酷了!我需要尼古拉斯凯奇这个传奇人物!*

接下来,我想清除没有分数的电影。这些电影要么是凯奇参演但从未公映的,要么是公映后从未评论的。前者的优势更大。我确实遇到了一个异常情况,由艾迪·墨菲主演的《一千个字》,它在评论家中的评分为 0%,但幸运的是,凯奇只被认为是这部电影的制片人,所以我们可以安全地删除它。

Admit it, you’re going to watch it for its 0% rating. So bad its good?

最后,为了对我们的数据进行排序,我们使用一个 Pandas groupby 命令来计算每年的平均分数。这将有助于把我们的分数和溺水数据联系起来。最后的结果?非常令人满意。

你们期待已久的时刻

这不是很神奇吗??现在,我坦率地承认,我在这里做了另一个虚假的相关图,但很难抗拒真正看看这个,并得出一些有趣的结论,当然都是虚假的。

例如,2003-2005 年是尼古拉斯·凯奇最好的几年。2003 年火柴人问世,2004 年国宝、战争之王、天气预报员紧随其后。这些是尼古拉斯·凯奇最具代表性的电影,非常成功,我们看到这些年溺水死亡人数呈稳步下降趋势。从 2006 年开始,事情开始变得有点疯狂,一开始是评价很高的《世界贸易中心》,T19 但以无限记忆的《柳条人》,结束,我们看到尼古拉斯·凯奇穿着熊装,打了一个穿得像 18 世纪定居者的女人。

随着 2007 年《幽灵骑士》(T0)、Next、和国宝 2 的上映,事情开始失去控制,只有他在罗伯特·罗德里格兹 GrindHouse 的短暂露面才挽救了局面。2008 年,集体“不良”终于达到顶点,凯奇最差的电影(在这个例子中为),曼谷危险,泳池死亡人数上升到 123 人。最后,还有一个有趣的负相关性-0.577172。这不是最好的,但比我预期的要高很多,虽然真的比我希望的要低。

最后,出于好玩,我使用 statsmodel 的 OLS 对模型进行了简单的线性回归,得出了以下结果:

我们的 R 值很低,我更喜欢 0.6 到 0.7 的值,这有助于证明尼古拉斯·凯奇是我们的精神生命卫士。这个数据中一个有趣的数字是位于 OLS 汇总中间的系数。它基本上表明,在一定程度的误差下,尼古拉斯·凯奇的电影每得一分,泳池溺水人数每年下降 0.0119 人,这多少有助于我们的案例。

最终结论

好了,完成了,但是即使我没有得到我想要的相关性或因果关系,结果仍然很有趣。我不禁认为,尼古拉斯·凯奇的两组数据显示了溺水死亡与泳池死亡之间的关系,这两者之间没有什么关联。阻碍我的一件事是缺乏更多关于泳池溺水死亡的数据。疾病预防控制中心对溺水死亡有非常广泛的分类,我无法确定哪些是在游泳池中,哪些是在其他类型的水体中。数据的原始来源是涵盖 1999 年至 2009 年的一次完成周报。也许另一个将于 2009-2019 年发布。有了更多的数据,也许我能找到更强的关系。毕竟,我们知道尼古拉斯·凯奇的职业生涯出现了戏剧性的下滑,我不禁想知道泳池死亡人数的上升是否与他的职业生涯相关。也许我的下一个笼子分析将围绕票房回报和池死亡。原因可能在于尼古拉斯·凯奇的票房吸引力,即人们正在观看他的电影并远离游泳池吗?只有进一步的分析才能告诉我们!最后,我想我只能说,银幕传奇尼古拉斯·凯奇与泳池安全有关!还有,松露猪的新电影?绝对看那个!

此分析的所有代码可在我的 Github 上获得

来源:

[## 尼古拉斯·凯奇

尼古拉斯凯奇名人简介-查看最新的尼古拉斯凯奇照片库,传记,照片,图片…

www.rottentomatoes.com](https://www.rottentomatoes.com/celebrity/nicolas_cage) [## 15 件相互关联的疯狂事情

为什么这些事情相互关联?这 15 个相关性会让你大吃一惊。(这个标题够煽情吗……

tylervigen.com](http://tylervigen.com/spurious-correlations)

在 LinkedIn 上与我联系!

[## 汉密尔顿·张,CRPC·CSPO-熨斗学校-纽约,纽约| LinkedIn

具有财务规划背景的数据科学家和机器学习工程师。我有专家级的知识…

www.linkedin.com](https://www.linkedin.com/in/hamilton-chang-crpc®/)

简化你生活的九个 Postgres 概念🐘

原文:https://towardsdatascience.com/nine-postgres-concepts-to-simplify-your-life-a0aa8c9bd87d?source=collection_archive---------15-----------------------

我不喜欢无意义的介绍,所以我们直接开始吧。

“If we have data, let’s look at data. If all we have are opinions, let’s go with mine.”

1.从文本语料库中生成 n 元语法

与使用另一种脚本语言相比,查询文本语料库并立即获得 n 元语法要简单得多。结果数据可以被存储用于多种目的,包括但不限于:关键短语识别、自动完成提示、自动纠正提示。这个集合还可以使用上下文 word2vec 模型创建单词和短语向量。

A way of generating n-grams in Postgres

这里,是按单词出现的顺序排列的单词记录集(直接获得或通过一些操作获得)。看起来是这样的:

Example Record Set of ordered words

2.高效地从表中删除重复项

I know not why I use so many GIFs

考虑到多个约束,下面的查询非常适合从表中删除重复项。这里,考虑列 var1 和列 var2 相同的所有行,保留一个副本,其余的被删除。

Efficiently delete duplicates rows from a table with a set of specific constraints.

3.忽略冲突的快速更新

You think throwing an error in my face will stop me from updating you, you scum of a table?

通常,更新表中的行值会导致与现有行的冲突。一些流氓条目阻止简单直接的更新查询运行到最后。为了解决这个问题,一个简单的程序可以逐行更新表格,忽略与约束冲突的条目,这很有意思。您可以选择记录这些行,以便在异常处理中进一步处理。

Handle update conflicts smarter.

另一种处理方法是移除冲突约束,正常更新表,处理冲突行(例如移除重复项)并重新添加约束。这不是推荐的方法。

4.复制带有现有约束的表

复制表时,约束有时是必不可少的,可以包括如下内容:

CREATE TABLE *table_copy* (LIKE *_table* INCLUDING ALL);INSERT INTO *table_copy* SELECT * from *_table*;

5.处理行锁

很容易出现这样的情况:多个进程持有对公共关系的锁,从而导致死锁情况。过时的查询或断开的连接是过时的,可以这样查询:

Get a list of queries and their details that hold locks over relations in a dB.

可以使用以下查询终止阻塞和/或被阻塞的语句:

SELECT pg_terminate_backend(*pid*)

6.查询 JSON 和 JSONB 列

很容易忘记 JSON(/B)及其数组可以像在脚本语言中一样被查询。将下面的 jsonb 结构视为关系中的一个单元格:

以下所有查询都是可能的:

7.高效的文本搜索和构建自动完成/自动更正模块!

Correct those typos and complete those sentences by using the power of tri-gram search.

我建议你在开始搜索任务之前阅读这篇博客文章:

  • 发现 Postgres 指数背后的计算机科学

在另一篇文章中,我描述了提取名词块的基本步骤,将它们存储在数据库中,查询它们并对结果进行排序。本文根据包含的名词块短语搜索数据点。这个可以扩展到全文搜索!

8.分组依据,每组多行

像 grouping 这样的聚合运算符为每个分组元素返回一个分组行。为了获得每个组的多行,下面的查询创造了奇迹。

9.有价值的信息

我发现以下三个概念在日常查询中有巨大的价值。

A.无效的

SELECT null **IS** null; 
--trueSELECT null **IS DISTINCT FROM** null;
--falseSELECT null **=** null; 
--nullSELECT null and null; 
--nullSELECT null **isnull**; 
--trueSELECT null notnull; 
--falseSELECT true or null; 
--trueSELECT true and null; 
--nullSELECT null is **unknown**; 
--true

B.对称的

SELECT 2 BETWEEN 1 and 5; 
--trueSELECT 2 BETWEEN 5 and 1; 
--falseSELECT 2 BETWEEN SYMMETRIC 5 and 1; 
--true

C.PgAdmin 具有查询的自动补全功能

鲜为人知的功能。从文档中:

要使用自动完成功能,请键入您的查询;当您希望查询编辑器建议查询中可能出现的下一个对象名称或命令时,请按下Control+空格键 组合键。例如,键入“SELECT * FROM”(不带引号,但有一个尾随空格),然后按 Control+Space 组合键从自动完成选项的弹出菜单中进行选择。

D.睡眠

SELECT pg_sleep(5);
--sleeps for 5 seconds indeed!

See you in the next one!

注意事项:

我喜欢阅读的一个很棒的博客可以在这里找到。

成为数据科学家所需的技能

原文:https://towardsdatascience.com/ninja-skills-of-modern-data-scientist-621622e59614?source=collection_archive---------13-----------------------

内部人工智能

成为数据科学家的详细信息,从数学到编程到商业到沟通!!!一切都在这里!!!

https://giphy.com

人工智能爱好者你好!!!如果你认为你想成为一名数据科学家,那么你在一个完美的地方获得了真正的数据科学家所拥有的所有技能。

通俗地说,火箭科学家是一个拥有火箭科学知识(和惊人经验)的人。成为一名数据科学家并没有那么难。(我说不难,并不是说每个小 kid 都适合这个角色。成为一名喷气式飞机驾驶员并不是火箭科学,但是要成为一名喷气式飞机驾驶员仍然需要很多努力。)

https://giphy.com

在 LinkedIn 上与许多数据科学家交谈后,我写这篇博客是为了收集别人 30 多年的生活经验。你会在这里找到很多奇妙的经历。

抓紧时间,继续阅读成为数据科学家所需的技能。

1.数学和统计学

1.机器学习

各种机器学习技术的知识就像任何数据科学家的心脏。没有机器学习知识,很难想象数据科学家的存在。大多数公司要求作为机器学习工程师至少有 3-5 年的基层经验,之后,你将有资格成为任何组织的数据科学家。

机器学习工程师是人工智能项目中的万金油。百事通意味着对问题定义、数据分析、结果展示和测试的透彻理解。它包含了从预处理和选择合适的算法来解决问题到用可视化的方式展示结果的所有内容。你必须全靠自己!!!您是开发人员、分析师,也是测试人员。

所以基本上,你需要机器学习的超能力。

你不必编码每一行,但是理解机器学习是很重要的。

https://giphy.com

2.统计建模

统计在数据科学家的生活中扮演着非常重要的角色。只是做一个机器学习算法的代码,你要更多的分析数据。最后,预处理良好的数据意味着项目已经完成了 50%。

您需要对什么是评估矩阵以及准确性、错误率、精确度、召回率、F1 分数和其他术语有一个基本的了解,才能完成您的任务。在概率和统计方面有超级理解力的人可以像国王一样统治数据科学的世界。

3.贝叶斯推理

贝叶斯理论是数据分析师世界中最重要的理论。数据革命始于贝叶斯理论。贝叶斯理论的具体基础将始终帮助您在数据科学竞赛中领先。掌握这一理论很容易让你从其他竞争者中脱颖而出。

4.监督学习和非监督学习

一个没有监督算法知识的数据科学家就像一个没有球的足球运动员。如果 11-11 名球员无球踢球会是什么样子?愚蠢。没有监督和非监督算法的知识也是一样的。

https://giphy.com

监督算法包括线性回归、逻辑回归、朴素贝叶斯线性判别分析、决策树、K-最近邻算法、支持向量机、神经网络(多层感知器)等等。

无监督算法包括层次聚类、K-均值、混合模型、DBSCAN、光学算法、主成分分析等等。

5.最佳化

优化是很少有人能掌握的技能。这是你区别于其他开发者的关键因素。训练模型不是非常重要,但是创建模型的优化版本需要大量的工作。超参数每天都会让你头疼,对优化的完美理解就像一场没有任何障碍的比赛。所以,优化你的优化技巧,做一个英雄。

2.编程和数据库

1.计算机科学基础

计算机科学技能是很少有人能掌握的。但是我有很多专业的机械工程师。他们开始学习 Python,然后转向数据科学领域。你会惊讶地发现他们表现得像冠军一样!!!

但是计算机科学概念对于数据科学家角色来说是非常重要的要求。掌握算法,操作系统,非常基础的网络开发和设计,计算机网络将会有很大的不同。这些概念会让你的速度提高 10 倍。

2.脚本和编程语言

如果没有像 Python ♥、r 或 MatLab 这样的脚本和编程语言,就不可能想象数据科学家的生活。如果你没有其中任何一个,那么就把自己踢出这场比赛。你永远不会有一个没有草的花园。你能想象没有草的花园是什么样子吗???想象一下。那不是花园,是沙漠。你必须在沙漠中耕作。这怎么可能呢?[1]您不仅需要了解 Python,还需要了解一些更高级的库,如 TensorFlow、PyTorch、Keras with MatplotLib、Numpy 和 Pandas。

所以在脚本和编程语言知识上没有妥协。就像不不不不。就是这样!!!

https://giphy.com

3.数据库 SQL 和 NoSQL

每个项目都有自己的数据和存储格式。对各种数据库的透彻理解可以帮助您理解和定义项目的具体问题。

数据可以是任何形式。你只需要接受这些数据。你不能对你的客户说,“不,我想要不同格式的数据。”您有责任将数据转换为算法所需的输入,并对其进行预处理。数据科学世界指出,粗糙的数据会降低你的准确性,但大量的非结构化数据会给你意想不到的东西。这需要创新的想法来解决。在这里,不同数据库的知识将帮助你。它可以是结构化的、非结构化的、图像、文本、音频或其他内容。

4.将数据转化为可视化

可视化是你可以用数据做的一件神奇的事情。当你尝到可视化的重要性,你会从内心感受到数据。可视化是展示结果的最佳方式。演示时不用说一个字,你的老板就会明白一切。所以这是数据科学学科成功的关键。

5.数据科学工具知识

不同工具上的命令就像是用特斯拉赛博卡车赛车在比赛中表演。你也可以用塔塔 Nano(印度最便宜的车)完成一场比赛但是值得完成一场比赛吗?明智地使用任何工具也是一种技能。互联网上什么都有,但你必须正确使用它。

像 Tableau,SAS,Apache Spark 这样的工具。Excel、RapidMiner、KNIME、QlikView 可以提高您的项目绩效和期限。

https://giphy.com

6.云

云知识不是强制性的,而是一种资产。一些内置的库和服务可能会很好用,例如 Google MLKit、Google Colaboratory、Kaggle 服务器、IBM Watson 和其他 API、微软 Azure AI toolkit 和 AWS storages。

至此,技术细节已经完成。

但是你仍然不知道如何成为一名数据科学家,琼恩·雪诺!!!

3.领域知识和软技能

1.对商业充满热情

数据科学家也经常从业务角度思考问题,因为归根结底,什么才是最重要的???钱。是的,再说一遍!!!钱!!!

你必须有强大的商业策略。这将提升你在组织中的价值,最重要的是你的职位。作为一名数据科学家,对业务视角有所了解是件好事。

2.对数据好奇

一名优秀的数据科学家有能力根据自己的经验以不同的方式看待数据。初级工程师看不到数据科学家能看到的东西,因为他们有经验和惊人的天赋。所以数据很说明问题!!!作为一名数据科学家,你只需仔细聆听!!!

3.问题求解程序

人工智能是没有人是完美的领域。你可以面对许多挑战,你只需要跳出框框思考。从字面上跳出框框思考解决问题。你身边就有一个解决方案,但是你只需要把它邀请到你的脑海中,它就会解决你的问题。

4.战略决策者

在作为数据科学家的某些阶段,你必须走得更远,因为在完成一些任务后,你会意识到用另一种技术可以更容易地做到这一点。所以运用一些脑力和技巧来做决定吧。继续使用基本解决方案,然后回来应用一些高级版本。

4.沟通

1.与高级管理层的接触

这都是关于网络、人际交往技巧和人际交往技巧的。播种什么就收获什么。这就像是你在数据科学职业竞赛中的兴奋剂。与权威打交道,当一个组织需要时,他们会提升你。与前辈的良好沟通会让你了解即将到来的项目。提前做好准备是最好的表演方式。

2.讲故事的技巧

作为一名数据科学家,你必须参加很多会议,包括董事会、客户、首席技术官和许多其他人。因此,在不给他们看代码的情况下,你必须向他们解释一个场景。所以只要展示魔法,人们就会认为你是天使。讲好故事,你就能睡个好觉。

3.人工智能不同最新趋势的知识

让自己跟上市场的最新趋势和技术。这会让你成为一个积极的领导者。而在这个科技时代(21 世纪),只有积极的领导者才能统治。

如果你掌握了这些技能,那么你就是这个游戏的冠军。神级!!!

https://giphy.com

参考资料:

[1]https://en.wikipedia.org/wiki/Desert_farming

NIPS 2018 年关于“金融风险稳健分类”的论文——摘要

原文:https://towardsdatascience.com/nips-2018-paper-on-robust-classification-of-financial-risk-summary-93445019d4f0?source=collection_archive---------18-----------------------

在这篇短文中,我将概述一篇名为“金融风险稳健分类”的研究论文。该论文被 NIPS 2018 关于“人工智能在金融服务中的挑战和机遇”的研讨会接受,旨在解决使用深度学习模型进行信贷借贷时出现的非常有趣和独特的问题。

概观

作者

这篇论文是由哈佛大学的 4 名计算机科学家撰写的。

出版

论文于 2018 年 11 月 27 日发布,是 NIPS 2018 年关于“人工智能在金融服务中的挑战和机遇”研讨会的一部分。

问题

已经观察到,输入数据的微小变化可以显著改变机器学习模型的结果。当试图在现实世界的系统中部署这种模型时,这带来了挑战,特别是在金融服务中,因为它允许精心构造的输入“愚弄”模型做出错误的决策。

解决办法

作者旨在使用“鲁棒优化算法”解决该问题,该算法增强了神经网络模型,以关注产生更高分类损失的变化(扰动)。

结果

通过比较两个神经网络之间的准确性和损失来进行评估。两个模型使用相同的底层结构(4 层,每层具有相同数量的单元和激活),但其中一个还使用了“鲁棒优化算法】。结果直接取自论文:

Credits to the authors of “Robust Classification of Financial Risk”

如您所见,损耗从 1.0 下降到 0.6,准确度从 50%提高到 70%。

书面演练

这项研究旨在回答这两个问题:

  1. 输入数据的微小扰动会导致错误分类吗?
  2. 稳健分类能否帮助金融服务中使用的机器学习模型在扰动的例子上表现更好?

该分析是在一个数据集上进行的,该数据集包括从 LendingClub (一个点对点借贷平台)获得的 421,095 份申请的借贷数据。作者使用了 4 种类型的扰动(输入数据的变化),包括:

  • 快速梯度符号法(FGSM) —在损失函数相对于输入的梯度方向上扰动输入。换句话说,该方法将 符号 函数应用于梯度,以确定输入应该朝哪个方向(正、负或零)变化。每次变化的大小由常数 e 决定。更多细节,参见论文中的第 2.2 节并浏览这篇伟大的张量流教程。
  • 预计梯度下降——与 FGSM 相同,但使用与其符号值相反的实际梯度。
  • 基于雅可比矩阵的显著性映射攻击 —扰动对损失函数影响最大的输入。
  • 最大显著性攻击 —以设定的百分比增加或减少来单独扰动每个特征,并找出这些特征中哪一个产生最高的成功误分类率。之后,作者选取其中一两个受影响最大的特征,用一个固定的百分比变化来干扰它们。

注意:“扰动”是输入中的一种变化,这种变化对人类来说可能是微小的或不明显的,但实际上却使网络误分类,产生巨大的误差。

回到问题 1,作者指出:

我们首先表明,在我们高精度贷款等级预测模型上的小扰动是成功的,每个特征 1.3%的平均扰动导致 95%输入的错误分类。

该模型是一个神经网络,具有大小为 100 和 60 的两个密集的 ReLU 层,使用 0.2 的漏失和具有 7 种可能结果的最终 softmax 层。结果的数量是根据数据确定的——lending club 使用一种信用系统,给任何候选人分配 A-G 的分数。

对于第二个问题,作者使用鲁棒优化算法,该算法通过识别哪些扰动具有高分类损失来增强网络,并且在训练期间更加关注那些扰动类型。

您在上面看到的结果是在训练神经网络和使用“鲁棒优化算法”的网络之后获得的,训练集在每次迭代中对扰动类型具有固定的均匀分布。

换句话说,在每个训练步骤中,作者均匀地随机挑选一个数据集,其中应用了四种扰动类型中的一种。

正如您所看到的,所提出的优化算法具有显著的效果。有关该算法如何工作的更多细节,请阅读论文中的第 2.3 节。

关键要点

下面列出了论文中发现的一些有用的观点:

  • 深度学习模型容易受到使用敌对输入的攻击。一个这样的例子是信用风险评估,其中抵御这种攻击的鲁棒性是必不可少的。
  • 类似于本文中应用的算法可以增强现有的模型,以识别这种错误分类。
  • 有用的资源是 LendingClub 数据集,其中包括数千名候选人的贷款数据。

谢谢你的阅读。希望你喜欢这篇文章🤩我祝你今天过得愉快!

NLP 102:阴性取样和手套

原文:https://towardsdatascience.com/nlp-101-negative-sampling-and-glove-936c88f3bc68?source=collection_archive---------3-----------------------

让 Word2Vec 变得越来越好。

Photo by Joshua Sortino on Unsplash

从语料库中生成高质量单词嵌入的一种方法是使用 Word2Vec — CBOW 或 Skip-gram 模型。这两种模式有一些共同点:

  • 训练样本由一对基于出现的接近度选择的单词组成。
  • 网络的最后一层是 softmax 函数。

CBoW/Skip-gram 的问题

首先,对于每个训练样本,只有对应于目标词的权重可能得到显著更新。在训练神经网络模型时,在每次反向传播过程中,我们都尝试更新隐藏层中的所有权重。对应于非目标单词的权重将接收到微小的变化或根本没有变化,即在每一遍中,我们仅进行非常稀疏的更新。

其次,对于每一个训练样本,使用 softmax 计算最终概率是一个非常昂贵的操作,因为它涉及对我们词汇表中所有单词的分数求和以进行标准化。

The softmax function.

因此,对于每个训练样本,我们执行一个昂贵的操作来计算单词的概率,这些单词的权重甚至可能不会更新,或者更新得如此之少,以至于不值得额外的开销。

为了克服这两个问题,我们尝试减少为每个训练样本更新的权重数量,而不是强行创建训练样本。

负采样

负采样允许我们只修改一小部分权重,而不是每个训练样本的所有权重。我们通过稍微修改我们的问题来做到这一点。我们不是试图预测词汇表中所有单词的邻近单词的概率,而是试图预测我们的训练样本单词是否是邻近单词的概率。参考我们之前的例子(桔子果汁),我们并不试图预测果汁成为邻近词的概率,即 P( 果汁 | 桔子),我们试图通过计算 P(1| < 桔子果汁)来预测(桔子果汁)是否是邻近词

因此,我们现在已经把它变成了 10,000 个二进制分类问题,而不是一个巨大的 soft max——在 10,000 个类别中分类。

我们通过随机选择少量“负面”词(一个超参数,假设为 5)来更新权重,从而进一步简化问题。(在这种情况下,“否定”单词是我们希望网络输出 0 的单词)。

对于我们的训练样本(橘子果汁,我们将取五个词,说苹果晚餐椅子,房子作为负样本。对于这个特定的迭代,我们将只计算果汁、苹果、晚餐、狗、椅子、房子的概率。因此,损失将只为它们传播回来,因此只有对应于它们的权重将被更新。

目标函数

Overall Objective function in Skip-gram and Negative Sampling. Here sigmoid = 1/(1+exp(x)), t is the time step and theta are the various variables at that time step, all the U and V vectors.

第一项试图最大化位于上下文窗口中的实际单词的出现概率,即它们共现。而第二项,试图迭代一些不在窗口中的随机单词 j ,并最小化它们同现的概率*。*

我们根据随机单词出现的频率对它们进行采样。P(w) = U(w)的 3/4 次方,其中 U(w)是一个单图分布。3/4 次幂使得不太频繁的单词被更频繁地采样,如果没有它,采样诸如“The”、“is”等频繁单词的概率将比诸如“斑马”、“大象”等单词高得多。

在我们上面提到的例子中,我们试图最大化概率 P(1| <桔子果汁* >)和最大化(因为在我们的目标函数中它前面有一个负号,所以当我们将选择最大值时,我们将鼓励它们不要发生)我们的负样本的概率 P(1| < 桔子,苹果 >),P(1| < 桔子,晚餐 >),P(1*

对于大型数据集,选择一个小的值 k ,大约在 2 到 5 之间。而对于较小的数据集,相对较大的值是优选的,大约 5 到 20。

子采样

语料库中单词的分布是不均匀的。有些词比另一些词出现得更频繁。诸如“the”“is”“are”等词出现得如此频繁,以至于在训练模型时省略一些实例不会影响其最终嵌入。此外,它们的大多数出现并没有告诉我们它的上下文含义。

在二次抽样中,我们通过限制样本出现的频率来限制一个词的样本数量。对于频繁出现的单词,我们会删除一些作为相邻单词和输入单词的实例。

性能考虑因素

在多 CPU 机器上使用并行训练可以显著减少 word2Vec 的训练时间。超参数的选择对性能(速度和精度)至关重要,但不同的应用会有所不同。要做出的主要选择是:

  • 架构 : skip-gram(较慢,对不常用词更好)vs CBOW(快)。
  • 训练算法 :分级 softmax(对不常用词更好)vs 负采样(对常用词更好,对低维向量更好)。
  • 常用词的子采样:可以提高大型数据集的精度和速度(有用值在 1e-3 到 1e-5 范围内)。
  • 词向量的维度 :通常越多越好,但也不尽然。
  • 上下文(窗口)大小 :对于 skip-gram 通常在 10 左右,对于 CBOW 在 5 左右。

几乎所有使用的目标函数都是凸的,所以初始化很重要。在实践中,使用小随机数来初始化单词嵌入会产生好的结果。

基于计数的方法

在 word2vec 中,我们本质上要做的是捕获单词的共现,但是一次一个滑动窗口。如果我们在一个矩阵中一次性捕捉到 co 出现的频率,会怎么样?这将在计算上比训练神经网络更简单和容易。使用这种方法,问题有点类似于我们面对的一次性表示(在以前的帖子中讨论过)。虽然我们在一定程度上解决了捕获单词间相似性的问题,但其他维度问题仍然存在。

总而言之,通过使用基于窗口的方法来学习我们的嵌入,我们能够捕获复杂的模式而不仅仅是单词相似度,但是我们对统计数据的使用效率很低。通过使用纯粹基于计数的方法,我们使统计数据得到了有效的利用,但是当我们将这些嵌入应用到外部任务时,这些复杂的潜在模式非常有用。

手套

它是基于计数和基于窗口的模型的混合。GloVe 的优势在于,与 Word2vec 不同,GloVe 不仅仅依赖于局部统计(单词的局部上下文信息,基于窗口的模型),而是融入了全局统计(单词共现,基于计数的模型)来获取单词向量。****

目标函数

Objective function for the GloVe model.

对于每一对可能同时出现的单词 ij ,我们试图最小化它们单词嵌入的内积与 ij 的对数之差。术语**f(Pij)允许我们降低一些非常频繁的共现的权重,并限制非常频繁的单词的重要性。

这里的 uv 向量是可以互换的。我们在这里使用两组不同的向量,因为它在优化时提供了更多的稳定性。如果我们只使用一组向量,我们将执行一个与它本身的内积,我们将有一个表现不太好的目标函数。在我们的最终评估中,我们将通过执行元素相加来简单地将两者结合起来。

优势

  • 快速训练:与基于窗口的方法不同,在基于窗口的方法中,我们过去常常一次优化一个窗口(可能多次对相同的同现进行训练),在 GloVe 中,我们一次只优化一个计数。
  • 可扩展:在庞大的语料库中,罕见的单词不会经常出现,但 GloVe 允许我们捕捉语义,而不管单词出现的次数。
  • 有效使用统计数据:这有助于模型在小语料库和小向量上表现良好。

突出

最近的邻居

两个单词向量之间的欧几里德距离(或余弦相似度)提供了一种测量相应单词的语言或语义相似度的有效方法。

线性子结构

这种计算两个词之间相似性的简单性可能是有问题的,因为两个给定的词几乎总是表现出比单个数字更复杂的关系。比如可能被认为和相似,两个词都是描述人类的;另一方面,在现实世界中,我们知道不应该认为男人=女人。这种差异不仅是生物学上的,也是社会学上的。{性别平等仍然是许多人渴望的理想,却没有人去实现}。为了以定量的方式捕捉区分男人女人的细微差别,模型有必要将一个以上的数字与单词对相关联。

参考

  • 单词和短语的分布式表示及其组合性
  • Chris McCormick Word2Vec 教程第 2 部分—负采样
  • 斯坦福手套博客
  • 谷歌:Word2Vec

我认为你会喜欢:D 的其他文章

  • 是的,你应该听听安德烈·卡帕西的话,了解一下反向传播
  • NLP 模型评估—最新基准
  • 在深度学习中获得注意力

我很高兴你坚持到了这篇文章的结尾。🎉我希望你的阅读体验和我写这篇文章时一样丰富。💖**

请在这里查看我的其他文章。

如果你想联系我,我会选择推特。

NLP 101: Word2Vec — Skip-gram 和 CBOW

原文:https://towardsdatascience.com/nlp-101-word2vec-skip-gram-and-cbow-93512ee24314?source=collection_archive---------0-----------------------

单词嵌入速成班。

Photo by Sincerely Media on Unsplash

单词嵌入是什么意思?

单词嵌入只是单词数字表示的一种花哨说法。一个很好的类比是我们如何使用颜色的 RGB 表示。

为什么我们需要单词嵌入?

作为一个人,从直觉上来说,想要用数字来表示单词或宇宙中的任何其他对象没有多大意义,因为数字是用来量化的,为什么需要量化单词呢?

在科学课上,我们说我的车的速度是 45 公里/小时,我们得到了我们开得有多快/多慢的感觉。如果我们说我的朋友以 60 公里/小时的速度开车,我们可以比较一下我们谁开得更快。此外,我们可以计算在某个时间点我们将在哪里,当我们知道我们旅程的距离时,我们将到达我们的目的地等等。类似地,在科学之外,我们用数字来量化质量,当我们报出一件物品的价格时,我们试图量化它的价值,一件衣服的尺寸,我们试图量化它最适合的身体比例。

所有这些表述都是有意义的,因为通过使用数字,我们可以更容易地根据这些品质进行分析和比较。鞋子和钱包哪个更值钱?尽管这两种物品不同,但有一种方法可以回答这个问题,那就是比较它们的价格。除了量化方面之外,这种表示没有任何其他可获得的东西。

既然我们知道对象的数字表示通过量化某种质量来帮助分析,问题是我们想要量化什么质量的词?

答案是,我们要量化 语义 。我们希望用一种人类能够理解的方式来表达单词。不是这个词的确切意思,而是上下文的意思。例如,当我说单词 see,时,我们确切地知道我在说什么动作——上下文——即使我们可能无法引用它的意思,那种我们可以在字典中找到的,我们头顶的意思。

什么是好质量的单词嵌入,如何生成?

最简单的单词嵌入是使用一键向量。如果你的词汇表中有 10,000 个单词,那么你可以将每个单词表示为一个 1x10,000 的向量。

举个简单的例子,如果我们的词汇表中有 4 个单词— 芒果、草莓、城市、德里— ,那么我们可以将它们表示如下:

  • 芒果[1,0,0,0]
  • 草莓[0,1,0,0]
  • 城市[0,0,1,0]
  • 德里[0,0,0,1]

上面的方法有一些问题,首先,我们的向量的大小取决于我们的词汇的大小(这可能是巨大的)。这是一种空间浪费,并且以指数方式增加了算法的复杂性,导致了维度的诅咒。

其次,这些嵌入将与它们的应用紧密耦合,使得迁移学习到使用相同大小的不同词汇的模型,从词汇中添加/删除单词几乎是不可能的,因为这将需要再次重新训练整个模型。

最后,创建嵌入的全部目的是捕捉单词的上下文含义,这是这种表示法所不能做到的。意思或用法相似的词之间没有关联。

**## Current situation** 
Similarity(Mango, Strawberry) == Similarity(Mango, City) == 0**## Ideal situation**
Similarity(Mango, Strawberry) >> Similarity(Mango, City)** Note: Similarity(a,b) = *a.b/(||a||*||b||*) Cosine similarity

连续词袋模型(CBOW)和跳格

两者都是通过使用神经网络来学习每个单词的底层单词表示的架构。

Source: Exploiting Similarities among Languages for Machine Translation paper.

CBOW 模型中,上下文(或周围单词)的分布式表示被组合起来预测中间的单词。而在跳格模型中,输入单词的分布式表示用于预测上下文

任何神经网络或任何监督训练技术的先决条件是具有标记的训练数据。你如何训练一个神经网络来预测单词嵌入,当你没有任何标记数据,即单词和它们相应的单词嵌入?

跳格模型

我们将通过为神经网络创建一个“假”任务来进行训练。我们不会对这个网络的输入和输出感兴趣,相反,我们的目标实际上只是学习隐藏层的权重,这实际上是我们试图学习的“单词向量”。

Skip-gram 模型的假任务是,给定一个单词,我们将尝试预测它的相邻单词。我们将通过窗口大小——一个超参数——来定义一个相邻单词。

The word highlighted in yellow is the source word and the words highlighted in green are its neighboring words.

给定句子:
“我早餐吃橘子 果汁 和鸡蛋。”
且窗口大小为 2,如果目标词是果汁,其邻词将是(有、橙、和、蛋)。我们的输入和目标词对将是(果汁,有),(果汁,橙),(果汁,和),(果汁,鸡蛋)。
还要注意,在样本窗口中,单词与源单词的接近度不起作用。所以有,橙,和,在训练时会被同等对待。

Architecture for skip-gram model. Source: McCormickml tutorial

输入向量的维数将是 1xV——其中 V 是词汇表中的个单词— ,即单词的一键表示。单个隐藏层将具有维度 VxE,其中 E 是单词嵌入的大小,并且是超参数。隐藏层的输出将是 1xE 的尺寸,我们将把它输入到一个 softmax 层。输出层的维度将是 1xV,其中向量中的每个值将是目标单词在该位置的概率得分。
根据我们之前的例子,如果我们有一个向量[0.2,0.1,0.3,0.4],这个词成为芒果的概率是 0.2,草莓是 0.1,城市是 0.3,德里是 0.4。

对应于源单词的训练样本的反向传播在一次反向传递中完成。所以对于果汁,我们将完成所有 4 个目标词 ( have,orange,and,eggs)的正向传递。然后我们将计算对应于每个目标单词的误差向量【1xV dimension】。我们现在将有 4 个 1xV 误差向量,并将执行逐元素求和以获得 1xV 向量。隐藏层的权重将基于这个累积的 1xV 误差向量进行更新。

CBOW

CBOW 中的假任务有点类似于 Skip-gram,在某种意义上,我们仍然采用一对单词,并教导模型它们共同出现,但我们不是添加错误,而是添加相同目标单词的输入单词。

我们的隐藏层和输出层的尺寸将保持不变。只有我们的输入层的维度和隐藏层激活的计算将改变,如果我们对于单个目标单词有 4 个上下文单词,我们将有 4 个 1xV 输入向量。每个都将乘以 VxE 隐藏层,返回 1xE 向量。将对所有 4 个 1xE 向量进行元素平均,以获得最终的激活,然后将该激活馈入 softmax 层。

Skip-gram :适用于少量的训练数据,甚至可以很好地表示罕见的单词或短语。
CBOW :训练速度比 skip-gram 快几倍,对常用词的准确率略高。

在本帖第二部分NLP 101:阴性采样和手套中,我们讨论了:

  • 负采样 —一种在不影响嵌入质量的情况下改善学习的技术
  • 另一个单词嵌入叫做 GloVe ,它是基于计数和基于窗口的混合模型。

参考

  • 讲稿 cs 224d:NLP 第一部分的深度学习
  • 讲稿 cs 224d:NLP 第二部分的深度学习
  • 麦考密克,C. (2016 年 4 月 19 日)。 Word2Vec 教程——跳格模型

我认为你会喜欢:D 的其他文章

  • 是的,你应该听听 Andrej Karpathy,并了解反向传播
  • NLP 模型评估—最新基准
  • 理解深度学习中的注意力
  • 变形金刚——谷歌的伯特和 OpenAI 的 GPT 等模型的基本模块。

我很高兴你坚持到了这篇文章的结尾。🎉我希望你的阅读体验和我写这篇文章时一样丰富。💖**

请点击这里查看我的其他文章。

如果你想联系我,我会选择推特。

NLP(人工智能)现实…混乱

原文:https://towardsdatascience.com/nlp-ai-reality-decluttered-3dd34f6daba0?source=collection_archive---------29-----------------------

诗歌生成器、推文生成器、新闻生成器、聊天机器人、破解考试的机器……唷……自然语言处理(NLP)已经离我们很远很远了。还是我们在媒体炒作的回音室里?现实是怎样的?

现实是开发人员在哪里…他们在编码什么,出现了什么问题,发生了什么对话?像 Stack Overflow 这样的顶级开发者网站对此有很好的描述。这也是一个很好的预示未来的指标(今天正在开发明天的解决方案)。让我们解混得到 NLP 现实。

这是开发者提出的问题的摘要、基本标签和标题。截至 2019 年 6 月,在 1867 个标签上分析了 11000 个查询。

属性:标签数据来自堆栈溢出

注:2019 年的数据是今年迄今为止的数字,因此会出现下降。按比例计算,2019 年在 6 个月内约为 2018 年的 70%,并有望大幅超过 2018 年。

Top 15 tags

  • NLP 正在兴起,尤其是在 2016 年之后
  • 机器学习比深度学习用得更多……深度学习正在逐级提升
  • 早些年出现了 Java、PHP 等…现在主要是 python
  • NLP 仍然是一流的 NLTK(自然语言工具包)库,它已经强大了十年
  • 嵌入/矢量技术在最近几年有所发展…先驱 word2vec 仍然占据主导地位
  • 文本分析是文本分类的主要用例

注:参见插图“矢量化标签网络”来理解这些技术术语是如何获得的。

快速进入这些领域…向量、库和用例。

矢量:下面的图表显示了一部分关于矢量生成技术的见解。Word2Vec 占主导地位,但像 elmo、bert 等新架构的快速发展正在蚕食它的份额。

Vector Generation

库:NLTK 最简单免费的库,Scikit-learn 独霸。斯坦福大学在 70 年代以基于规则的文本处理开创了自然语言处理,并继续赢得人们的忠诚。

鉴于 Word2Vec 的受欢迎程度,在那里看到 Gensim 并不奇怪。Spacy 是在 NLP 中取得巨大进展的软件包。有趣的是,bigtech 驱动的 NLP APIs 还没有引发很多讨论。

用例:用例主要是在文本分析/挖掘中。近年来,文本分类和情感分析的份额越来越大。情感分析是文本分类的一种形式,很明显,文本分类是开发人员正在讨论的用例。

快速浏览每个用例可以发现,文本分析和信息提取主要利用了 regex、tf-idf、nltk 等。文本分类/情感分析是深度学习出现的地方。

使用主题建模技术理解文档继续沿用旧的 LDA 和 Gensim 方法。利用嵌入和深度学习让机器理解语言还没有出现。

总之,自然语言处理越来越受到重视,尽管是现有技术的更高组合。向量和深度学习概念的探索获得更多份额。

NLP 现实…通过“AI+代码”去杂乱。

基于自然语言处理的提高预测模型精度的数据预处理方法

原文:https://towardsdatascience.com/nlp-based-data-preprocessing-method-to-improve-prediction-model-accuracy-30b408a1865f?source=collection_archive---------12-----------------------

自然语言处理如何帮助均匀化异构数据集以优化机器学习回归任务的预测模型。

Photo by Milad Fakurian on Unsplash

任务概述

如今,将机器学习用于点对点市场非常流行,因为它可以提高 UX,增加客户忠诚度。在第一部分的中,我描述了众包平台【Arcbazar.com】基于 ML 的奖项推荐系统的主要阶段,客户发起设计师竞赛并设立奖金。ML 系统在已完成的带有付费奖项的竞赛的数据集上进行训练,以帮助客户为某个建筑项目设置最佳奖项。经过数据分析,选择了最佳回归算法。

问题

正如在上一篇文章中提到的,我对数据集做了一些简化。我将训练数据集的三个文本描述字段替换为一个有数值的字段——字符总数。因此,我得到了 5 个字段的数据集,而不是 7 个字段。

然而,测试表明,模型的准确性可以提高。

在这篇文章中,我将告诉您如何使用自然语言处理来升级数据集预处理的预测模型。

假设

古希腊哲学家苏格拉底说:“说话,让我能看见你”。这句格言的意思是,我们的言语比我们想说的更多地揭示了我们的个性。此外,它还提示了一个假设,即项目的文本描述可能与奖励金额相关联,并且这些关系比大量字符更强。

我决定使用自然语言处理方法将文本描述的字符串类型数据转换为数值,目的是丰富和均匀化数据集。

ML 系统升级分为三个主要步骤:

  1. 文本清理。
  2. 文本到数字的转换。
  3. 选择最佳回归方法。

文本清理

对于数据库的每个文本描述字段,我使用 Python 语言的自然语言工具包和 gensim 库应用了文本清理算法。但是,您可以使用您喜欢的任何 NLP 库。我将文本转换成小写,去掉标点符号和英语停用词。

#Transform to lower case
import stringfeatures['description'] = features['description'].str.lower()#Remove punctuation
table = str.maketrans('', '', string.punctuation)
features['description'] = [features['description'][row].translate(table) for row in range(len(features['description']))]#Remove stopwords
import nltk
nltk.download('stopwords')
from nltk.corpus import stopwords
stop = stopwords.words('english')features['description'] = features['description'].apply(lambda x: " ".join(x for x in x.split() if x not in stop))

文本到数字的转换

然后,每个字段中最常用和最不常用的单词都被删除。语义分析中常用(最频繁)词的含义非常接近停用词。他们给文本添加了一种类似噪音的模式。此外,最不常用的词的意义可以忽略不计,它们可以被过滤掉。这一步的目的是筛选出最有价值的单词。我使用了图形分析,绘制单词和它们的频率。

#Find words spreading (each word frequency)
freq_d = pd.Series(‘ ‘.join(features[‘description’]).split()).value_counts()#Plot the words distributionfreq_d.plot(kind=’line’, ax=None, figsize=None, use_index=True,
            title=None, grid=None, legend=False, style=None,
            logx=False, logy=False, loglog=False, xticks=None,
            yticks=None, xlim=None, ylim=None, rot=None,
            fontsize=None, colormap=None, table=False, yerr=None,
            xerr=None, label=None, secondary_y=False)

词频可视化帮助我筛选出频率大约在 5 到 200 之间的词。

#Remove the least frequent words
rare_d = pd.Series(' '.join(features['description']).split()).value_counts()[-17528:]rare_d = list(rare_d.index)features['description'] = features['description'].apply(lambda x: " ".join(x for x in x.split() if x not in rare_d))#Remove the most frequent words
freq_d = pd.Series(' '.join(features['description']).split()).value_counts()[:30]freq_d = list(freq_d.index)features['description'] = features['description'].apply(lambda x: " ".join(x for x in x.split() if x not in freq_d))

然后每个文本记录被标记化——一个文本被分割成一个单词数组。

features['description'] = [text.split() for text in features['description']]

单词及其频率的组合给出了一个文本向量,其中每个单词都用它的索引代替。相似的向量表示相似的文本。这就是语义搜索引擎的工作方式。与现代搜索引擎不同,这里我只关注可能的相似性的一个方面——它们的文本(单词)的明显语义相关性。没有超链接,没有随机游走的静态排名,只是对布尔关键字匹配的语义扩展。

#Create a set of text records for each field
from gensim import corporadict_d = corpora.Dictionary(features['description'])

将文本转换成单词包(BoW)格式,即(token_id,token_count)元组的列表,是由类gensim.corpora.dictionary.Dictionary().doc2bow()的属性完成的。

#Convert tokenized text (corpora) to vectorscorpus_d = [dict_d.doc2bow(line) for line in features['description']]

为了得到一个实数而不是一个向量,我使用了一个范数,它是一个函数,为向量空间中的每个向量指定一个严格为正的长度或大小。

#Transform vectors of texts to scalar values (calculating norms of vectors)
from numpy import linalg as LAcorpus_d_vec_norm = [LA.norm(vec) for vec in corpus_d]
#Replace text descriptions in the database with norms of vectors
features[‘description’] = corpus_d_vec_norm

最后,我得到了一个同质的 7 场数据集。

选择最佳回归方法

我使用了之前测试中评级最高的机器学习方法——随机森林回归器——来计算模型如何适应我们的新数据集。决定系数 R 的平方是 5 字段数据集(0.37)的两倍(约 0.75)。

Random Forest Regressor results distribution on 7-field data

最初,我有混合数据集:前三个字段(下拉菜单)显然是相互依赖的,接下来的三个字段(描述)更具波动性。

由于我的假设,描述域在哲学上(甚至心理学上)更接近于奖励值。所以,我把 ML 方法改成了人工神经网络。顺便说一下,该算法在之前的 5 字段数据集测试中被拒绝,因为它的 R 平方非常低,为 0.05。

Image source: scikit-learn.org

然而,多层感知器只有三个隐藏层的回归器给出了 R 平方为 0.999962 的惊人结果。

Multi-layer Perceptron Regression on 7-fields dataset.

import sklearn
from sklearn.neural_network import MLPRegressormlpreg = MLPRegressor(hidden_layer_sizes=(3,), activation=’relu’,
         solver=’adam’, alpha=0.001, batch_size=’auto’,
         learning_rate=’adaptive’, learning_rate_init=0.01,
         power_t=0.5, max_iter=1000, shuffle=True, random_state=9,
         tol=0.0001, verbose=False, warm_start=False, momentum=0.9,
         nesterovs_momentum=True, early_stopping=False,
         validation_fraction=0.1, beta_1=0.9, beta_2=0.999,
         epsilon=1e-08)

结论

1.所获得的结果显示了向量的范数对于替换文本向量的适用性,而没有显著的数据丢失。

2.客户对他/她的需求的口头描述比下拉菜单更接近于奖金数额,因为这些文字可能表达了人类的本质或共同的动机。

3.基于人工神经网络的算法在“理解”人性方面比随机森林更好,首先是因为它在结构上与人脑相似。

基于自然语言处理的无用户偏好推荐系统

原文:https://towardsdatascience.com/nlp-based-recommender-system-without-user-preferences-7077f4474107?source=collection_archive---------5-----------------------

推荐系统 (RS)已经发展成为帮助用户做出明智决策和选择的基本工具,尤其是在大数据时代,客户必须从大量产品和服务中做出选择。人们提出了许多遥感模型和技术,其中大多数都取得了巨大的成功。其中,基于内容的粗糙集和协同过滤粗糙集是两个有代表性的。研究界和工业界都证明了它们的有效性。

我们将在自然语言处理方法的基础上建立一个基于内容的推荐系统,当我们处理以描述或标题(一般是文本数据)为特征的产品,如新闻、工作、书籍等时,这种方法非常有用..

开始吧!

数据

我们将使用来自一些自由职业者网站的项目数据集,这些项目是出于教育目的从 RSS 源解析而来的。

我们将根据自由职业者以前做过的项目,尝试向他们推荐感兴趣的项目。

import pandas as pd
projects = pd.read_csv("projects.csv")
projects_done= pd.read_csv("projects_done_by_users_history.csv")
projects.head()

Dateframe of projects

项目完成历史表包括 2 行,用户标识和项目标识。

现在让我们准备数据并清理它。

projects = projects.drop_duplicates(subset="Title", keep='first', inplace=False)
projects["Category"] = projects["Category"].fillna('')
projects["Description"] = projects["Description"].fillna('')
projects["SubCategory"] = projects["SubCategory"].fillna('')
projects['Title']= projects['Title'].fillna('')

让我们将每个文档的所有行合并为一行

projects["text"] = projects["Category"] + projects["Description"] + projects["SubCategory"] + projects["Title"]

现在我们将计算 TF-IDF “项频率—逆数据频率”

from sklearn.feature_extraction.text import TfidfVectorizertf = TfidfVectorizer(analyzer='word',ngram_range=(1, 2),min_df=0, stop_words='english')
tfidf_matrix = tf.fit_transform(projects['text'])

是时候生成余弦 sim 矩阵了

from sklearn.metrics.pairwise import linear_kernel, cosine_similaritycosine_sim = linear_kernel(tfidf_matrix, tfidf_matrix)

现在我们完成了,我们的自由职业者是免费的开放项目..给他们推荐几个有意思的项目吧:))

getUserDone 函数将返回一个列表,其中包含用户已完成项目的所有 id。

get_recommendations 将返回一个列表,其中包含与特定用户完成的项目最相似的项目,该列表将按升序排序。

titles = projects['Title']
indices = pd.Series(projects.index, index=projects['Title'])

让我们推荐 id 为 20 的用户可能感兴趣的前 25 个项目。

get_recommendations(20).head(25)

Top 25 Recommendations

结论

在本文中,我们使用 NLP 方法构建了一个基于内容的推荐器,它对于包含文本数据的产品非常有用。

不需要用户的偏好,我们可以从他们完成的项目中为他们推荐高质量的推荐。

这种方法也有优点,这就是为什么总是建议使用多种方法,并结合它们以获得准确的结果。

NLP 基础,动手操作:一个语言分类器,分 3 步在线部署

原文:https://towardsdatascience.com/nlp-basics-hands-on-a-portuguese-dialect-classifier-deployed-online-in-3-steps-53a8b3b88ea9?source=collection_archive---------28-----------------------

São Paulo or Lisbon? (Photos by Gabriel Santos and Lisa Fotios)

TL;dr:我用 scikit-learn 创建了一个葡萄牙方言分类器,用了 5000 篇 TED 演讲。然后我修补了 Flask 和 Vue.js 来与你分享。

小团体

是的,我是最近决定加入数据科学潮流的一群人中的一员。人们说,边走边学。他们说,想出一个问题并找到它的解决方案。他们说,不要害怕在路上打碎东西。我也在努力。作为一名波兰-葡萄牙语翻译,我立刻想到了一个现实世界的问题:

你知道,葡萄牙语是横跨大西洋的一种语言。巴西和旧世界(葡萄牙+讲葡萄牙语的非洲和亚洲国家)的变体在词汇、语法和发音方面有所不同。

与此同时,波兰的自由葡萄牙语翻译市场相当狭窄。我没有足够的时间专门研究和坚持其中一个品种。我头上戴着两顶帽子,有时在同一个工作周,我必须加倍小心地保持给定翻译的一致性。这就是为什么我对 NLP 项目的第一个想法是葡萄牙语方言分类器。

无论是在自然语言处理还是人工智能领域,这都不是开拓性的研究。我在这里的动机与我之前关于 tweet bot 的 Medium 文章类似——展示在 Python 中进行自然语言处理的第一步是多么简单。作为一个没什么技术背景的人,我尽量用通俗易懂的英语来呈现。

这篇文章分为三个主要部分:

  • 准备源数据(Scrapy);
  • 训练模型(sci kit-learn);
  • 使用模型(Flask+Vue.js)部署 API。

准备源数据

A lecture. Could be a TED one. Photo by Samuel Pereira on Unsplash

我需要什么数据,从哪里收集,如何收集?在这种情况下,我选择 TED.com 作为我的来源。这是一个相当大的数据库,方便转录讲座。在这种情况下,特别重要的是,TED 的翻译团队严格区分两种葡萄牙语方言(例如,维基百科就不是这种情况)。

TED 曾经维护了一个官方 API,但他们在 2016 年停止了它,所以我建立了一个 Scrapy spider 来收集数据。大部分是基于刺儿头教程的样板。蜘蛛在指定语言的 TED 演讲目录中循环,并跟踪各个演讲的链接:

def parse_front(self, response):

   talk_links = response.css(“a.ga-link::attr(href)”) 
   links_to_follow = talk_links.extract()    for url in links_to_follow: 
      url = url.replace(‘?language’, ‘/transcript?language’) 
      yield response.follow(url=url, callback=self.parse_pages)

然后,第二种解析方法抓取各个讲座的标题和文本,并将它们添加到字典中:

def parse_pages(self, response): 
   title = response.xpath(‘//head/title/text()’).extract_first()    
   title = title.strip() 
   title = title.split(‘:’)[0] 
   talk = response.xpath( ‘//div[@class=”Grid__cell flx-s:1 p-r:4"]/p/text()’).extract() 
   for i in range(len(talk)): 
      line = talk[i].strip() 
      line = line.replace(‘\n’,’ ‘) 
      talk[i] = line.replace(‘\t’,’ ‘) 
   talk = ‘ ‘.join(talk) 
   talk = talk.replace(‘\n’,’ ‘) 
   ted_dict[title] = talk

完成后,字典被转储到一个 CSV 文件中。我需要做的就是确定合适的 xpaths。我还设置了每次下载之间的半分钟延迟(如果没有它,我会过于频繁地访问服务器,这会阻塞我的查询):

class TedSpiderPt(scrapy.Spider): 
   name = “ted_spider_pt” 
   download_delay = 0.5

剩下的资料准备和训练过程都可以在 Jupyter 笔记本这里伴随。下面,我浏览了一下,并强调了关键时刻。

我为葡萄牙语的每个版本搜集了大约 2500 个 TED 演讲,每个演讲大约有 12000 到 18000 个字符。清理完格式后,我将 PT-PT(欧洲葡萄牙语)的转录标记为“0 ”, PT-BR 的转录标记为“1 ”,然后用 scikit-learn 的 CountVectorizer 拟合并转换它们。

An example of data prepared for CountVectorizing.

如果这篇文章是对自然语言处理的介绍:CountVectorizer 将一组文本文档转换成字数。这种数字形式的文本数据极大地提高了处理它的能力。

首先,我按照 2:1 的比例将讲座分成训练集和测试集。该模型将仅在训练数据上学习。测试部分用于在向世界发布之前检查其性能。

然后,我将向量机与训练数据相匹配——简单地说,它会为在那里找到的每个单词分配一个唯一的数字,从而创建一个词汇表。为了消除极端的异常值,我将参数 min_df 设置为 2——只出现一次的单词不考虑在内。然后,我转换训练集——即统计词汇表中每个单词的出现次数。在计数矢量化之后,在组成训练集的 3555 个谈话的每一个中计数 59061 个单词中的每一个。

请参见下面的图示:

Tracking down a particular word.

单词“eu”(葡萄牙语中的“me”)在词汇表中被索引为“23892”。在这个指数的字数统计中,我们看到一个演讲中“eu”的数量明显较高。我们可以追溯到演讲的转录……事实上,个人经历在 Chiki Sarkar 的 TED 演讲中发挥了重要作用。

除了向量化和计数,我避免任何其他预处理。我不做词干分析,因为我想保留两种语言版本之间的语法差异(如动词变化差异)。举个例子:把“[a] fazer”和“fazendo”减少到它们的词干会模糊我想要抓住的 PT/BR 区别。

训练模型

Photo by Jelmer Assink on Unsplash

然后,我在训练集上训练一个多项式朴素贝叶斯分类器。尽管这种方法相当基础,但在 NLP 应用程序中,比如这个,它的效果非常好。

再次,一些简单的英语解释:NaiveBayes 分类器基本上比较给定单词在 BR 和 PT 集中的频率,从而确定该单词是否建议更“巴西”或“葡萄牙”的文本。在预测时,对文本中的所有单词进行加权,我们获得最终的概率。

在训练分类器之后,我使用与之前相同的矢量器来转换测试集。它已经填充了训练集词汇,并且它将只计算出现在其中的单词。

然后使用多项式贝叶斯对矢量化的测试集进行分类。在这个特殊的例子中,我对测试集做了一点调整——我想测试它对短文本进行分类的能力。因此,我将测试集的讲座分成 200-760 个字符的小块。相比之下,你现在正在阅读的段落包含 370 个字符。结果呢?

How’s that for a score?

我在短文本上实现了 86.55%的准确率,错误分类的 PT-PT 和 PT-BR 示例的比例几乎相同。这是一个足够好的分数吗?我不是这里最客观的法官,但我会说这很体面。让我们看一些错误分类短语的例子来帮助我们评估模型。

Three examples of PT-BR texts classified as PT-PT

即使你不熟悉这两种葡萄牙语变体,也可以想象一下,有些句子听起来既不像典型的美式英语,也不像典型的英式英语。这就是这里许多分类错误的短语的问题。无论如何,我将在本文的后续部分更深入地研究改进模型的方法。现在,让我们与世界分享吧!

使用模型部署 API

Image source and all the rest of Flask goodness: https://palletsprojects.com/p/flask/

如果我想在 Jupyter 笔记本之外使用我的模型,我需要一种导出它的方法。对于这个任务,我使用了 joblib 序列化库,它提供了这个问题的轻量级解决方案。

扔给模型的每个新文本都需要由矢量器进行转换,然后进行分类。因此,我将矢量器和分类器打包成一个 scikit-learn 管道。然后只需将它转储到 joblib 文件中:

pipeline = Pipeline([('vectorizer',vectorizer), 'classifier',nb_classifier)])dump(pipeline, 'ptclassifier.joblib', protocol = 2)

“轻量级”这个术语也适用于 Flask ,一个我用来部署 API 的精益 web 应用框架。我的 Flask 应用程序的完整代码是 GitHub repo 中的。它基本上加载 joblibbed 模型并监听带有一个参数的 GET 请求:一个文本数据字符串。一旦接收到,它通过管道传递字符串,并返回预测的标签和该预测的置信度值。

我还应用了 flask-cors 包来允许来自不同来源的请求。在我们的例子中,我稍后将介绍的托管在其他地方的前端应用程序需要访问这个 Flask API。你可以在这里阅读更多关于 CORS 的信息。

我在 PythonAnywhere 上托管了我的 Flask 应用,我在 tweetbot 文章中详细描述了这项服务。如果你从在线托管的 Python 脚本开始,我全心全意地推荐 PyA 支持团队总是对我的初学者问题很有帮助。

我通向 ML 前端的痛苦之路

You always need a frontend, as scrappy as it may be. Photo by Eric Muhr on Unsplash

啊,前台。我巨大挫败感的根源和原因。我确信,在最后一英里,建立一个带有文本框和“发送”按钮的最简单的页面是相当容易的。我深信不疑,结果陷入了恶性循环。

首先,我得到一个建议,我应该使用 Vue.js ,但是从一本关于 JavaScript 本身的书开始,比如 EloquentJS 。啊啊。不要误会我,我喜欢 EJS,它的在线版本,有练习用的沙盒,非常容易上手。但在一周的课程后,我意识到我此刻的目标是缝合一个基本的前端,然后回去构建模型。我仍然觉得 Python 不够流利,无法开始一门新的语言。

然后我谷歌了“简单机器学习前端模板”和类似的关键词,结果喜忧参半。我掉进的陷阱?我对最小可行解决方案的耐心持续的时间比我理解和部署模板所需的时间要少。

最后,我找到了一个对我的急性子足够有效的方法——由 James Salvatore 在 Uptake Tech 博客中提出。我拿了他的模板,并根据我的需要做了一些调整。为了简单起见,我去掉了工具栏,添加了一个图片作为标题,并且只保留了一个文本框。我在 AlwaysData 上托管了该应用的生产版本,这是我可以推荐的另一项服务。

如果你还没有看到最终的结果在这里。

The Brazilian anthem is classified as 97.5% Brazilian. What’s the result for its Portuguese counterpart? Check for yourself here.

随便玩玩,就算不懂葡萄牙语。如果你在上面打碎了什么东西并告诉我,我会非常高兴的!此外,对库中代码的任何建设性的批评都会赢得我永远的感激。

下一步是什么?

本文将有第二部分。在不久的将来,我想:

  • 添加一个功能,向我的前端应用程序的用户显示单个单词如何影响预测;
  • 刮一些其他文字来源(新闻、博客、电影字幕),在上面检查模特的表现;
  • 探索分类器的错误并尝试发现模式;
  • 尝试用 LSTM 方法解决问题,并比较结果;
  • 最后但同样重要的是,希望我能从读者那里得到一些值得分享的反馈!

奖金(葡萄牙语者)!

我偶然发现了两个人们用葡萄牙方言解决类似问题的例子:

  • 巴西区域自动识别研究,作者 Nathalia Alves Rocha (pdf)
  • Rodrigo card oso 的《PHP 中的机器学习》

感谢Piotr migda对本项目和其他项目的指导,感谢 Kamil Herba 和Piotr Kaznowski对本文和 webapp 的见解。

[NLP]基础:理解正则表达式

原文:https://towardsdatascience.com/nlp-basics-understanding-regular-expressions-fc7c7746bc70?source=collection_archive---------8-----------------------

你唯一需要的向导

Photo by travelnow.or.crylater on Unsplash

当我开始学习自然语言处理时,正则表达式真的感觉像一门外语。我努力理解语法,花了几个小时写一个正则表达式来返回我正在寻找的输入。很自然的,我尽可能的远离他们。

但事实是,作为一名数据科学家,总有一天你会接触到正则表达式。它们构成了自然语言处理中基本技术的一部分,学习它们将使你成为一个更高效的程序员。

所以是时候坐下来开始了。把学习正则表达式想象成一堂语法课:它们很痛苦,起初看起来不可理解,但一旦你理解并学会了,你会感到如释重负。我向你保证,到头来也没那么难。

注意,我将在本文中使用的编程软件是 R.

展开正则表达式

简而言之,正则表达式是给函数的“指令”,告诉它如何匹配或替换一组字符串。

让我们从正则表达式的一些基础开始,这是一些你应该知道的基本语法。

括号 []用于指定字符的析取。例如,使用括号放 W 或 W 允许我返回大写的 W 或小写的 W。

/[wW]oodchuck/ --> Woodchuck or woodchuck 
/[abc]/ --> ‘a’, ‘b’, or ‘c’
/[1234567890]/ --> any digit

如果你添加一个破折号,你就指定了一个范围。例如,将 A-Z 放在括号中允许 R 返回一个大写字母的所有匹配。

/[A-Z]/ → machtes an upper case letter
/[a-z]/ → matches a lower case letter
/[0–9]/ → matches a single digit

可以用于否定,或者仅仅表示.

/[ˆA-Z]/ --> not an upper case letter
/[ˆSs]/ --> neither ‘S’ nor ‘s’
/[ˆ\.]/ --> not a period
/[eˆ]/ --> either ‘e’ or ‘ˆ’
/aˆb/ --> the pattern ‘aˆb’

问号?标记上一个表达式的可选性。例如,将一个。在土拨鼠结束时,返回土拨鼠(不带 s)和土拨鼠(带 s)的结果。

/woodchucks?/ --> woodchuck or woodchucks
/colou?r/ --> color or colour

可以用。指定两个表达式之间的任意字符。例如,输入 beg.n 将返回 begin 或 begin 这样的单词。

/beg.n/ --> Match any character between beg and n (e.g. begin, begun)

*或+ 用户允许您添加 1 个或多个先前字符。

 oo*h! → 0 or more of a previous character (e.g. ooh!, ooooh!)
o+h! → 1 or more of a previous character (e.g. ooh!, ooooooh!)
baa+ → baa, baaaa, baaaaaa, baaaaaaa

用于断言关于字符串或匹配过程的一些东西。因此,它们不是用于特定的单词或字符,而是帮助进行更一般的查询,正如您在下面的示例中所看到的。

 . → any character except a new line
\\w → any word character
\\W → anything but a word character
\\d → any digit character
\\D → anything but a digit character
\\b → a word boundary
\\B → anything but a word boundary
\\s → any space character
\\S → anything but a space character

POSIX 字符类别有助于匹配特定的字符类别,如数字。换句话说,它使一个小的字符序列匹配一个更大的字符集。

 [[:alpha:]] → alphabetic characters
[[:digit:]] → digits
[[:punct:]] → punctuation
[[:space:]] → space, tab, newline etc.
[[:lower:]] → lowercase alphatic characters
[[:upper:]] → upper case alphabetic characters

strsplit()、grep()和 gsub()

这是行动开始的地方。在处理字符串时,很可能必须使用命令 strsplit()、grep()和 gsub()来激活您希望 R 返回给您的输入。

strsplit(x,split)

下面的例子展示了一种使用 strsplit 来拆分句子中的单词的方法,在这个例子中是破折号“…”内的所有单词。

richard3 <- “now is the winter of our discontent”
strsplit(richard3, “ “) # the second argument specifies the space

grep(pattern,x,ignore.case = FALSE,value = FALSE)

grep 允许你“抓取”你想要的单词或单词集,这取决于你设置的匹配模式。例如,在下面的代码中,我让 R 返回包含单词“both”的字符串。

grep.ex <- c(“some like Python”, “some prefer R”, “some like both”)grep(“both”, grep.ex) # in numerical form
grep(“both”, grep.ex, value=TRUE) #prints the character string itself

gsub(pattern,replacement,x,ignore.case= FALSE)

例如,gsub 允许你用一个词替换另一个词。在这种情况下,我选择在下面的字符串中用超人代替罗密欧。

r_and_j <- “O Romeo, Romeo, wherefore art thou Romeo?”
gsub(“Romeo”, “Superman”, r_and_j, ignore.case = FALSE)

应用了正则表达式

让我们开始将这些命令应用于正则表达式。下面我给你看几个例子。

1.grep(模式,x,ignore.case =假,值=假)

dollar <- c(“I paid $15 for this book.”, “they received $50,000 in grant money”, “two dollars”)

注意,在上面的例子中,你有三个不同的句子,其中两个使用了\(符号,一个使用了单词“美元”。仅使用\)来匹配您的模式将会返回所有三个句子。然而,如果你在\(前加上\\你可以指定你只需要使用\)符号的句子。

grep(“$”, dollar) 
grep(“\\$”, dollar)

下面还有几个例子,说明如何使用 grep 来匹配单词“ashes”、“shark”、“bash”的正则表达式:

# matches all three vector elements
grep(“sh”, c(“ashes”, “shark”, “bash”), value=TRUE) # matches only “shark”
grep(“^sh”, c(“ashes”, “shark”, “bash”), value=TRUE) # matches only “bash”
grep(“sh$”, c(“ashes”, “shark”, “bash”), value=TRUE) 

关于“失态”、“擦破”、“粉笔”三个词:

quant.ex <- c(“gaffe”, “chafe”, “chalk”, “encyclopaedia”, “encyclopedia”)# Searching for one or more occurences of f and we want to see the value not only the index (that’s why we put value = TRUE)
grep(“f+”, quant.ex, value=TRUE) # one or two “f”
grep(“f{1,2}”, quant.ex, value=TRUE) # at least one “f”
grep(“f{1,}”, quant.ex, value=TRUE)

2.gsub(pattern,replacement,x,ignore.case= FALSE)

在下面的例子中,你可以用 gsub 替换句子中的单词。

ex.sentence <- “Act 3, scene 1\. To be, or not to be, that is the Question:”

如果您还记得在本文第一部分中学习的正则表达式,您应该能够猜出 R 将返回哪种输入。否则,我会将它添加到下面的代码中,以便您更好地理解使用正则表达式返回所需结果的所有不同方式。

gsub(“.”, “*”, ex.sentence, ignore.case=TRUE, perl=TRUE)
[1] "**********************************************************"gsub(“\\w”, “*”, ex.sentence, ignore.case=TRUE, perl=TRUE)
[1] "*** *, ***** *. ** **, ** *** ** **, **** ** *** ********:"gsub(“\\W”, “*”, ex.sentence, ignore.case=TRUE, perl=TRUE)
[1] "Act*3**scene*1**To*be**or*not*to*be**that*is*the*Question*"gsub(“\\d”, “*”, ex.sentence, ignore.case=TRUE, perl=TRUE)
[1] "Act *, scene *. To be, or not to be, that is the Question:"gsub(“\\D”, “*”, ex.sentence, ignore.case=TRUE, perl=TRUE)
[1] "****3********1********************************************"gsub(“\\b”, “*”, ex.sentence, ignore.case=TRUE, perl=TRUE)
[1] "*Act* *3*, *scene* *1*. *To* *be*, *or* *not* *to* *be*, *that* *is* *the* *Question*:"gsub(“\\B”, “*”, ex.sentence, ignore.case=TRUE, perl=TRUE)
[1] "A*c*t 3,* s*c*e*n*e 1.* T*o b*e,* o*r n*o*t t*o b*e,* t*h*a*t i*s t*h*e Q*u*e*s*t*i*o*n:*"gsub(“\\s”, “*”, ex.sentence, ignore.case=TRUE, perl=TRUE)
[1] "Act*3,*scene*1.*To*be,*or*not*to*be,*that*is*the*Question:"gsub(“\\S”, “*”, ex.sentence, ignore.case=TRUE, perl=TRUE)
[1] "*** ** ***** ** ** *** ** *** ** *** **** ** *** *********"

否则,试着猜测最后一个问题的答案:

letters.digits <- “a1 b2 c3 d4 e5 f6 g7 h8 i9”
gsub(“(\\w)(\\d)”, “\\2\\1”, letters.digits)

就是这样!我希望你喜欢这篇文章,并且我已经设法使正则表达式对你来说更容易理解。

我经常写关于数据科学和自然语言处理的文章。在 Twitter Medium上关注我,查看更多类似的文章或简单地更新下一篇文章。 感谢阅读!

PS:最后一个的答案是“1a 2b 3c 4d 5e 6f 7g 8h 9i”。换句话说,您已经使用正则表达式重写了所有的字母和数字。很酷不是吗?

过去 25 年中的 NLP 商业化

原文:https://towardsdatascience.com/nlp-commercialization-in-the-last-25-years-6468d8119fcd?source=collection_archive---------22-----------------------

Photo by Thomas Kelley on Unsplash

自然语言工程期刊 现在已经是第 25 个年头了。早在 1995 年第一期的编辑序言中就强调,该杂志的重点是自然语言处理(NLP)技术的实际应用:这是一个严肃的出版物,有助于鼓励研究想法进入实际产品的时机已经成熟。那时 NLP 技术的商业化已经开始,但是在过去的四分之一世纪里,事情已经有了巨大的进展。因此,为了庆祝杂志的周年纪念,我们来看看商业 NLP 产品在过去 25 年中是如何发展的。

这篇文章的一个版本也出现在 2019 年 5 月的《自然语言工程》杂志上。

一些背景

对许多研究人员来说,自然语言处理工作有双重吸引力。一方面,语言理解或语言产生的计算模型经常被视为探索语言学和心理语言学理论问题的手段,一般的论点是,如果你能建立某种现象的计算模型,那么你很可能朝着理解这种现象的方向前进了一些。另一方面,自然语言处理技术的实际应用范围一直很诱人:我们可以构建真正有用的与人类语言一起工作的计算工件的想法可以追溯到 20 世纪 50 年代早期机器翻译实验领域的起源。

然而,直到 20 世纪 90 年代早期,NLP 的商业应用才真正开始蓬勃发展,特别是在美国的定向研究的推动下,其中大部分是由 DARPA 通过消息理解会议(MUC)等项目资助的,而在欧洲,则是通过许多大规模前瞻性的 EU-资助的研究项目。正是在这种活动的背景下,自然语言工程杂志应运而生,其明确的目标是主要关注实践贡献而非理论贡献。

《华尔街日报》现在已经是第 25 个年头了,我们有一个很好的借口来看看 NLP 商业化的历史,并反思我们在这 25 年里走了多远。

起点

除了是该杂志创刊的一年,1995 年还发生了大量与计算机相关的事件。这是视窗 95 和网景问世的一年;Java 1.0 出现,JavaScript 被开发出来;DVD 问世了,索尼在北美发布了 PlayStation。也是在这一年,NSFNet 退役,消除了互联网商业化的最后限制。Yahoo.com、eBay.com 和 Amazon.com 都是在 1995 年启动的。IBM 推出了“深蓝”,这一计算机系统后来打败了国际象棋世界冠军加里·卡斯帕罗夫。啊,那是令人兴奋的日子!

为了我们现在的目的,1995 年也是肯·丘奇和丽莎·劳发表了一篇关于自然语言处理程序商业化的文章的一年。值得回顾一下当时该领域是如何出现的。丘奇和劳着眼于四个领域的发展:一般的自然语言处理,文字处理,信息检索和机器翻译。在每一个案例中,他们都试图描述什么是广为人知的技术,什么是最先进的,什么是更具前瞻性的。表 1 重述了该论文中相关汇总数字的内容。

在某些方面,看起来似乎没有什么变化:尽管丘奇和饶认为前瞻性的每个主题都取得了进展,但它们不是你所说的完全解决的问题,所以我认为它们在某些方面仍然是前瞻性的,也许沿着真正的人工智能是我们尚未建立的东西的路线。但是在下面我们将探讨的各种方式中,该领域已经在许多方面向前发展,并且今天日常使用的基于 NLP 的产品在 25 年前我们不会认为是合理的。

当然,最值得注意的是,由于广泛采用机器学习和统计技术,解决许多问题的方法发生了变化;在 20 世纪 90 年代中期,人们对统计方法进行了研究,但任何已经达到产品状态的东西,就其技术基础而言,都可能主要是基于规则的。新技术不仅为老问题提供了新的解决方案,还将新问题带到了舞台上,产生了我们以前想不到的产品创意。

商业景观

出于这里提供的分析的目的,我将采用 NLP 应用程序和技术的空间分解,它与 Church 和 Rau 使用的略有不同,并且对应于我在以前的专栏中使用的空间分解。这种世界观将商业 NLP 领域分为六个关键领域:

机器翻译:将源自然语言中的语言内容翻译成目标自然语言的保义翻译。

语音技术:将对应于语言话语的波形转换成该话语的文本呈现(语音识别);或者相反,将语言表达的文本表示转换成相应的音频形式(语音合成或 TTS)。

对话界面:交互式界面,允许用户提出自然语言问题(通过语音或文本)并获得答案,可能在较长的多回合对话中。

文本分析:检测文本来源中有用的内容或信息,通常通过分类或提取。

自然语言生成:从一些潜在的非语言信息表示中生成语言输出。

写作辅助:体现一些语言知识的技术,目的是提高人类创作的语言内容的质量。

当然,还有其他方法可以分解能量场。我发现这种看待事物的方式很有用,因为它相当好地对应了该领域供应商倾向于使用的一组自我分配的类别。有争议的是,语音技术不再代表一个独立的类别,已经在某种程度上被吸收到更广泛的对话界面领域。然而,至少早在 20 世纪 90 年代,用于将语音转换为文本的技术与用于处理文本的技术之间就有着明显的区别。

在本文的剩余部分,我们将依次研究这六个类别中的每一个。

机器翻译

如前所述,机器翻译的第一次实验开始于 20 世纪 50 年代,随着现在著名的 1954 年乔治敦-IBM 俄语到英语的翻译演示获得了广泛的关注。商业提供商在 20 世纪 60 年代末和 70 年代初出现,事实上,该领域最早的公司之一, Systran (成立于 50 多年前的 1968 年)
仍然是领先的翻译工具和服务提供商。

早期的机器翻译系统纯粹是象征性的,基于大量手写规则,将一种语言的语言内容转换成另一种语言。商业机器翻译软件的 PC 版本在 20 世纪 90 年代初开始出现。直到 20 世纪 90 年代后期,基于网络的翻译才出现(回想一下,网络在 1991 年才公开),1997 年 AltaVista 的 Babel Fish translator 使用了 Systran 的技术。因此,25 年前,商业机器翻译是一种基于规则的努力,商业重点是体现功能的工作台,如翻译记忆,这可以提高生产率。虽然 IBM 在 20 世纪 80 年代末发表了关于统计机器翻译(SMT)的研究,但直到 2007 年,随着谷歌翻译
的推出,基于网络的翻译才成为统计翻译。

今天,翻译行业处于不断变化的状态。有时粗糙的 SMT 被
认为对于某些目的来说已经足够好了,毫无疑问,深度学习技术的使用已经改善了结果。但是机器翻译在质量和准确性方面仍有一些不足,因此有越来越多的混合解决方案试图将机器翻译的可扩展性与人工翻译的精确性和准确性结合起来;例如,参见 Lilt 。机器翻译的广泛可用性和低成本在更广泛的翻译行业引发了大量的反思:每当机器翻译的质量提高时,[人工翻译不得不重新考虑他们给这个团体带来了什么](https://slator.com/sponsored-content/how-augmented- translation-will-redefine-the-value-of-translators/)。这种
是一种存在主义焦虑,我们可以期待在未来几年里看到它继续上演。

但是回到 1995 年,谁会想到你可以将手机摄像头对准日文菜单,然后在屏幕上看到英文翻译?那是科幻小说里的东西。

语音技术

语音社区早在 NLP 世界的其余部分之前就接受了统计技术;特别是,hmm 在 20 世纪 70 年代的采用是一个重大突破,导致了识别性能的显著提高。但是语音识别的进步仍然受到当时内存和计算能力的限制。在 20 世纪 70 年代末,IBM 拥有可以识别 1000 个单词的词汇的技术——前提是每个单词作为一个独立的单元说出,并且在下一个单词之前有一个停顿。到了 20 世纪 90 年代,技术得到了改进,计算能力也提高到了在 PC 桌面上进行语音识别的程度。1990 年为基于 DOS 的计算机发布的 Dragon Dictate 售价 9000 美元,但仍只能识别孤立的单词。Dragon Naturally
Speaking 于 1997 年 7 月问世,它可以每分钟识别多达 100 个单词的连续语音(一旦你对它进行 45 分钟的训练,使它适应你的声音),同年晚些时候,IBM 发布了一款名为 ViaVoice 的竞争产品与之匹敌。

20 世纪 90 年代中期,是语音识别商业应用的早期。与其他任何领域相比,过去 25 年取得的惊人进步在这里最为明显:将 20 世纪 90 年代初的孤立单词识别与我们现在对 Alexa、Siri 和谷歌助手的识别准确性的期望进行对比。

在过去的 25 年里,商用语音合成技术也经历了巨大的改进。自 20 世纪 90 年代初以来,许多计算机操作系统都包括了语音合成器。机器人 DECtalk——以斯蒂芬·霍金的声音而闻名——于 20 世纪 80 年代中期推出,但语音合成技术到 1995 年并没有太大变化。在 20 世纪 90 年代采用串联合成产生了听起来更自然的合成输出,但仍然有听觉故障,并且感觉输出不太令人信服。然而,由于深度学习技术的应用,过去几年已经取得了重大发展。今天部署的语音合成的高质量是最明显的,如果你听听[谷歌双工的对话贡献](https://ai.googleblog.com/2018/05/duplex-ai-system-for-natural- conversation.html),完成
犹豫和填充,或者 Alexa 最近引入的[新闻播音员的声音](https://techcrunch.com/2019/01/16/alexa-gets-a-professional- newscaster-voice-for-reading-the-days-news)。

对话界面

我使用术语“对话界面”来涵盖许多不同的技术:

  • 20 世纪 60 年代和 70 年代早期基于文本的对话互动实验,例如约瑟夫·韦森鲍姆的《伊莉莎》。
  • 基于文本的自然语言数据库界面在 20 世纪 70 年代和 80 年代是人们关注的焦点,它允许用户输入诸如“有多少销售人员比我挣得多?”而不是必须制定一个意思相同的 SQL 查询。
  • 20 世纪 90 年代的语音对话系统,在基于电话的应用中,有限状态对话模型
    与基于语法的语音识别相结合。
  • 现在的虚拟助手,比如 Siri,Alexa,Google Assistant。
  • 今天的基于文本的聊天机器人,在许多网站和消息应用程序上都可以找到,
    显示了广泛的功能(或者,通常是缺乏功能)。

这些看起来似乎都是非常不同种类的应用程序,但是它们都有一个共同点,那就是它们都试图支持某种形式的自然语言对话。如今,这项技术已经出现在大多数日常用户面前,这种对话通常仅限于一次性的问答环节(“嘿,Alexa,几点了?”).然而,在过去的几年中,许多供应商已经提出了变得更加会话化的需求,在多个回合中保持对话,因此必须处理诸如会话上下文和回指之类的对话现象。因此,交互式语音识别开发人员在 20 世纪 90 年代和 21 世纪初学到的许多经验正在被今天的聊天机器人开发人员重新学习。布鲁斯·巴伦廷在这个
话题上的重要贡献在今天和 10-20 年前一样重要。

马克·吐温被指责几乎引用了每一句名言,据说他说过“历史不会重演,但它常常会重复”。因此,当新的对话设计者正在重复他们 20 年前的前辈的错误时,今天的区别是语音识别实际上工作得足够好,以至于基于文本的界面和基于语音的界面之间几乎没有区别。在 20 世纪 80 年代和 90 年代,NLP 在对话方面的工作通常只是假设存在完美的语音识别,这个问题需要由大楼中的其他团队来解决;但当时的高识别错误率意味着,如果在真实的口语中放任自流,这些系统从根本上说是不可行的。

但是,自那时以来,我们已经走过了漫长的道路。1992 年,美国电话电报公司推出了用于呼叫路由的语音
识别服务,证明了即使使用极其有限的五个术语词汇也可以开发出有用的应用程序:该应用程序用于对方付费和向第三方付费的长途呼叫,并识别对录音语音提示的五种不同响应:“电话卡”、“对方付费”、“第三方”、“个人对个人”和“接线员”。20 世纪 90 年代早期的 DARPA 口语系统计划,特别是 ATIS(航空旅行信息系统)共享任务,展示了在实验室中可以实现的令人印象深刻的结果,并鼓励了交互式语音识别行业的开始。即将成为基于电话的 IVR 的重量级公司 Nuance 和 SpeechWorks 都是在 20 世纪 90 年代中期在 DARPA ATIS 任务取得进展的背景下成立的;到 20 世纪 90 年代后期,越来越多的商业上有用的应用被开发出来,如上所述,结合了有限状态对话建模和基于语法的语音识别来管理语音识别错误。

今天,我们仍然没有解决长期的自然主义对话所带来的问题。但是,即使它的应用领域很窄,也很难不对谷歌双工展示的对话能力印象深刻。

文本分析

我使用术语“文本分析”来涵盖通常应用于文档的各种分类和提取过程。DARPA 资助的 MUC 会议是定义和发展这一技术领域的关键,早期的最初重点是命名实体识别。到 20 世纪 90 年代中期,开始出现旨在将这些方法商业化的商业实体。其中只有一小部分仍然作为独立的公司存在;据我所知,只有两家是成立于 1995 年的 Basis 和成立于 1996 年的 NetOwl 。然而,许多其他早期参与者已经被收购,并仍然以其他形式活跃:特别是,1998 年成立的 ClearForest,现在成为汤森路透文本分析解决方案的一部分,品牌为[路孚特](http://www. opencalais.com)。

如果您将这些老供应商与该领域的许多新进入者进行比较,产品的成熟度,尤其是在功能广度方面,是显而易见的。但老玩家没有满足于他们的荣誉:Basis 和路孚特似乎都在跟上时代,引入深度学习技术,就像新的竞争对手将这些技术作为起点一样。

也许在过去的 25 年中最显著的发展是情感分析作为一项关键技术的出现;以至于一些文本分析公司,如 Clara bridge T1,已经重生为专注于客户体验分析的 T2 技术提供商。

与其他所有事情一样,深度学习已经进入了文本分析领域,相当多的新进入者自豪地谈论他们使用这些新技术作为区分自己和保守派的一种方式。尚不清楚这些方法是否真的比那些更成熟的参与者提供了更好的结果,这些参与者当然受益于在其间的几十年中调整了他们的技术。有趣的是,早在 1995 年,Church 和 Rao 就将事件提取视为该领域的前瞻性主题:对于少数选择接受它的商业文本分析提供商来说,它仍然是一个挑战。在另一个历史押韵的例子中,地名词典——最早的命名实体识别方法的支柱——又回来了,但是是从 DBpedia 等来源构建的更丰富形式的知识图。事实证明,字符串匹配在 1995 年是一个好主意,今天仍然是一个好主意。

自然语言生成

1995 年,NLG 几乎没有任何商业活动。据我所知,当时活跃在该领域的唯一一家公司 CoGenTex 成立于 1990 年,主要依靠政府合同生存。但是
今天的情况很不一样;在过去的 5-10 年里,越来越多的公司宣称自己是 NLG 的供应商。叙事科学和[自动洞察](/ automatedinsights.com)是这里最引人注目的玩家,但还有阿里亚·NLG、 Ax 语义学和 Yseop 等等。据我所知,这些公司中的大多数似乎都在使用某种“智能模板”来生成常规文本,如财务报告或数据驱动的新闻报道。这些供应商中的许多还在为 Tableau 和 Qlik 等商业智能工具制作[插件,为这些工具已经制作的高质量可视化内容添加叙事内容。几乎没有证据表明,商业 NLG 产品利用了更丰富的语言概念,如聚合和引用表达式生成,这些概念是在研究社区中开发的;我的感觉是,到目前为止正在探索的用例并不保证使用这些想法。随着越来越复杂的应用程序的尝试,这种情况当然会改变。](https://www.tableau.com/about/blog/2016/8/bringing-power- natural-language-tableau-58325)

更非传统形式的 NLG 的商业应用——至少从传统 NLG 研究议程的角度来看——也已经出现。仅举两个例子: Phrasee 为电子邮件生成优化的推送
消息和主题行;此外,利用图像字幕方面的最新进展,微软的视觉人工智能通过为图像制作描述来帮助那些视力受损的人。尤其是后者,在 1995 年还没有出现。

写作辅助

1995 年,自动化写作辅助包括拼写检查器、风格检查器和基于模式匹配的非常简单的语法检查器。Word Perfect 是 20 世纪 90 年代初微软 Word 的主要竞争对手,它授权并随后收购了一款名为 Grammatik 的产品;MS Word 许可了一个名为 CorrecText 的竞争工具。像当时所有可用的语法检查器一样,这些工具的灵感来自 Unix Writer's Workbench 中使用的简单字符串匹配方法。我们不得不等到 1997 年,微软才发布了自己的基于语法的语法检查器,作为微软 Word 的一部分,使用的是由 Karen Jensen 和 George Heidorn 开发的技术,他们之前负责 IBM 的 Epistle
语法检查系统:论文发表在 20 世纪 80 年代初的 Epistle 上,但正是 Word 中基于语法的语法检查在 14 年后将 NLP 技术应用于数百万台桌面上。

到了 20 世纪 90 年代中期,Word Perfect 开始走下坡路(尽管它直到-
日仍可使用),微软似乎赢得了桌面战争。Word 的垄断意味着进一步开发语法检查功能的动力很少,而且对新玩家来说门槛很高。因此,在 2009 年 Grammarly grammar 和 style checker 出现之前,这方面的商业活动并不多。到 2017 年,Grammarly 声称拥有[690 万日活跃用户](https://producthabits.com/how-grammarly-quietly-grew-its-way-to-7- million-daily-users),其中大部分用户免费使用该服务。这与微软 2016 年[的 12 亿 Office 用户](https://www.windowscentral.com/there-are-now-12-billion-office-users-60- million-office-365-commercial-customers)相比是一个微小的用户群,但当然不是每个使用 Word 的人也使用 Word 的语法检查器;没有真正可比的数字。碰巧的是,2017 年微软[开始推出对其语法检查器](https://redmondmag.com/articles/2017/06/21/making-word-grammar-checker- better.aspx)的改进,最近在 Build 2019 大会上发布了一些重要公告。因此,经过多年的停滞,我们可能希望 Grammarly 作为一个严重的竞争对手的到来将为这一领域的发展注入新的活力。我自己的观点是,我们将在未来几年看到一些重大的产品改进,将 NLG 的想法与提供写作帮助结合起来。

总结

这就是你要去的地方:在《自然语言工程杂志》的生命周期中,商业 NLP 是如何发展的旋风之旅。很明显,NLP 行业在这段时间里已经走过了很长的路。早在 1995 年,该领域之外相对较少的人知道如何扩展缩写词“NLP ”,任何随机的个人都可能认为它指的是神经语言学编程。今天,几乎每个拥有智能手机的人都有过通过 Siri 或谷歌助手直接使用 NLP 技术的经历,这个术语被广泛理解。

在某种程度上,我们的期望已经无限增长。我们越来越习惯于向我们的智能扬声器抛出随机问题。通过基于网络的化身,我们将机器翻译视为随时可用的商品。但与此同时——我发现这是一个令人着迷的发展——我们的期望在某种程度上也更加现实。如果 Alexa 误解了我们的问题,或者 Google Assistant 给出了一个看似虚假的答案,我们不会特别不安;我们承认这些技术偶尔出错是正常的。同样,我们知道我们应该谨慎对待机器翻译的结果,怪异的翻译不再保证它们曾经产生的幽默关注。我们似乎已经到达了这样一个点,尽管不完美,但技术已经足够好,可以在日常生活中使用。通过无处不在的曝光和足够好的组合,NLP 已经成为我们日常体验中被接受的一部分。从 25 年前的角度来看,这的确令人印象深刻,而《自然语言工程》杂志在这一过程中发挥了自己的作用。

如果你想要一种简单的方法来跟上商业 NLP 世界的关键发展,可以考虑注册本周 NLP ,这是一份每周周五出版的简短时事通讯。

NLP:来自 BERT 的语境化单词嵌入

原文:https://towardsdatascience.com/nlp-extract-contextualized-word-embeddings-from-bert-keras-tf-67ef29f60a7b?source=collection_archive---------1-----------------------

使用 Keras 和 TF 从 BERT 中提取上下文化的单词嵌入

Photo by Eugenio Mazzone on Unsplash

毫无疑问,自然语言处理(NLP)研究在相对静止了几年之后已经有了巨大的飞跃。首先,谷歌来自 Transformer (BERT) [1]的双向编码器表示在 2018 年底成为亮点,在许多自然语言处理任务中实现了最先进的性能,不久之后,OpenAI 的 GPT-2 通过承诺更惊人的结果抢了风头,据报道,这些结果太危险了,无法发布!考虑到这些出版物背后的时间框架和参与者,不难意识到目前该领域有很多活动。

也就是说,我们将在这篇文章中关注 BERT,并试图通过提取像 ELMo [3]一样的预训练上下文化的单词嵌入来获得一小块蛋糕。

为了给你一个简要的概述,我将首先给出一点背景知识,然后对 BERT 的体系结构做一个高层次的概述,最后在解释一些棘手的部分的同时跳到代码中。

为了更加方便,我将使用 Google 的 Colab 进行编码,但是相同的代码也可以在您的本地环境中运行,无需做太多修改。

如果您只是为了编码部分而来,请跳到“ BERT 单词嵌入提取”部分。在这里找到完成的笔记本代码。

单词嵌入

首先,嵌入只是高维向量空间中一个点的(适度)低维表示。同样,单词嵌入是单词在低维空间中的密集向量表示。第一个,利用神经网络的单词嵌入模型由谷歌的研究于 2013 年发表[4]。从那以后,在今天实践中使用的几乎每个 NLP 模型中都遇到了单词嵌入。当然,坦率地说,如此大规模采用的原因是它们的有效性。通过将一个单词翻译成一个嵌入,就有可能以数字形式模拟一个单词的语义重要性,从而对其执行数学运算。为了更清楚地说明这一点,我会给你一个最常见的例子,你可以在单词嵌入的上下文中找到它

当 word2vec 模型首次实现这一点时,这是一个惊人的突破。从那里,许多更高级的模型浮出水面,它们不仅捕捉静态语义,还捕捉语境化的含义。例如,考虑下面的两个句子:

我喜欢苹果。

我喜欢苹果 macbooks

注意,apple 这个词在每个句子中有不同的语义。现在有了语境化的语言模型,单词 apple 的嵌入将有一个不同的向量表示,这使得它对于 NLP 任务来说更加强大。

然而,我将把如何工作的细节留在这篇文章的范围之外,只是为了保持简短和中肯。

变形金刚

坦率地说,NLP 领域的许多进展都可以归功于一般深度学习研究的进步。更特别的是,谷歌(又来了!)在一篇开创性的论文[5]中提出了一种新的神经网络架构,称为转换器,它比传统的顺序模型(LSTM、RNN、GRU 等)有许多好处。优点包括但不限于,对时间序列中的记号之间的长期依赖性进行更有效的建模,以及通过消除对先前记号的顺序依赖性来更有效地训练模型。

简而言之,转换器是一种编码器-解码器架构模型,它使用注意机制将整个序列的更完整图像一次转发给解码器,而不是按顺序转发,如下图所示。

Source: http://mlexplained.com/2017/12/29/attention-is-all-you-need-explained/

同样,我不会描述注意力如何工作的细节,因为这将使这个话题更加混乱,更难消化。请随意阅读参考资料中的相关论文。

OpenAI 的 GPT 是第一个创建带有微调的基于转换器的语言模型的人,但更准确地说,他只是使用了转换器的解码器。因此,使语言建模单向。放弃编码器的技术原因是,语言建模将成为一项琐碎的任务,因为要预测的单词最终会看到自己。

来自变压器的双向编码器表示(BERT)

到目前为止,模型的名称应该更有意义,并给你一个大概的概念。BERT 将所有东西结合在一起,使用编码器而不是解码器来构建一个基于双向转换器的语言模型!为了克服“看到自己”的问题,谷歌的人有了一个巧妙的想法。他们雇佣了蒙面语言建模。换句话说,他们隐藏了 15%的单词,并利用它们的位置信息进行推断。最后,他们还稍微混合了一下,让学习过程更有效。

尽管这种方法对收敛时间有负面影响,它甚至在收敛之前就超过了最先进的模型,从而确保了模型的成功。

通常,BERT 代表一种支持迁移学习和特定任务微调的通用语言建模,然而,在这篇文章中,我们将仅通过使用 Keras 和 TensorFlow 从 BERT 中获取 ELMo 类单词嵌入来触及其特征提取方面。

但是不要着急!在我们进入代码之前,让我们快速探索一下 BERT 的架构,以便我们在实现时有一些背景知识。相信我,这会让事情更容易理解。

事实上,BERT 开发人员创建了两个主要模型:

  1. 基: 变压器块数(L): 12,隐层尺寸(H): 768,注意头(A): 12
  2. 大: 变压器块数(L): 24,隐藏层大小(H): 1024,注意头(A): 16

在这篇文章中,我将使用基本模型,因为它足够了(而且更小!).

从一个非常高的角度来看,BERT 的架构是这样的:

这看起来很简单,但请记住,每个编码器模块都封装了一个更复杂的模型架构。

在这一点上,为了使事情更清楚,理解 BERT 作者用于微调和特定任务训练的特殊记号是很重要的。这些是:

  1. 【CLS】:每个序列的第一个令牌。一种分类令牌,通常与 softmax 层一起用于分类任务。对于其他任何事情,可以放心地忽略它。
  2. 【SEP】:序列定界符 token,用于序列对任务的预训练(即下一句预测)。需要序列对任务时必须使用。当使用单个序列时,它只是附加在末尾。
  3. 【掩码】:用于掩码字的令牌。仅用于培训前。

接下来,BERT 期望的输入格式如下所示:

Source: https://arxiv.org/pdf/1810.04805.pdf

因此,与 BERT 一起使用的任何输入都必须进行格式化以匹配上述内容。

输入层只是序列记号和特殊记号的向量。上例中的“# #ing”记号可能会引起一些人的惊讶,所以为了澄清,BERT 利用了 WordPiece [6]进行记号化,这实际上是将类似“playing”的记号拆分为“play”和“# ing”。这主要是为了涵盖更广泛的非词汇(OOV)* 词汇。*

记号嵌入是每个记号的词汇 id。

句子嵌入只是一个数字类,用来区分句子 A 和 b。

最后,变换器位置嵌入表示每个单词在序列中的位置。关于这个的更多细节可以在[5]中找到。

最后,还有最后一件事。到目前为止,一切都很好,但是我如何从中获得单词嵌入呢?!?如前所述,BERT 基本模型使用了 12 层变换器编码器,每一层的每一个输出都可以作为一个单词嵌入!你可能想知道,哪一个是最好的呢?嗯,我想这取决于任务,但根据经验,作者认为最好的选择之一是对最后 4 层求和,这就是我们将要做的

Source: http://jalammar.github.io/illustrated-bert/

如图所示,最好的执行选项是连接最后 4 层,但在本文中,为了方便起见,使用了求和方法。更具体地说,性能差异不是很大,而且更灵活地进一步截断维度,不会丢失太多信息。

伯特单词嵌入提取

理论说够了。让我们继续练习。

首先,创建一个新的 Google Colab 笔记本。进入编辑- >笔记本设置,确保硬件加速器设置为 TPU。

现在,第一个任务是克隆官方的 BERT 存储库,将它的目录添加到 path 中,并从那里导入适当的模块。

*!rm -rf bert
!git clone [https://github.com/google-research/bert](https://github.com/google-research/bert)import syssys.path.append('bert/')from __future__ import absolute_import
from __future__ import division
from __future__ import print_functionimport codecs
import collections
import json
import re
import os
import pprint
import numpy as np
import tensorflow as tfimport modeling
import tokenization*

从 BERT 导入的两个模块是建模标记化。建模包括 BERT 模型实现,而标记化显然是为了标记化序列。

除此之外,我们从 colab 获取我们的 TPU 地址,并初始化一个新的 tensorflow 会话。(注意这只适用于 Colab。本地运行时,不需要)。如果您在运行下面的块时看到任何错误,请确保您使用 TPU 作为硬件加速器(见上文)

接下来,我们选择想要使用的 BERT 模型。

正如你所看到的,有三种模型可供我们选择,但实际上,在官方的 BERT GitHub 资源库中甚至有更多预先训练好的模型可供下载。这些只是已经被谷歌下载并存放在一个开放的桶中的模型,因此可以从合作实验室访问。(对于本地使用,您需要下载并提取一个预先训练好的模型)。

回想一下之前的参数:12 L(变形块)768 H(隐藏层大小)12 A(注意头像)。“不区分大小写”只适用于小写序列。在本例中,我们将使用无案例的 BERT 基本模型。

此外,我们为模型定义了一些全局参数:

上面的大多数参数都是不言自明的。在我看来,唯一有点棘手的是层数组。回想一下,我们使用的是 12 个隐藏编码器的最后 4 层。因此,层保持它们的索引。

下一部分将专门为处理前和处理后的输入定义包装类(特性)。

InputExample 类中,我们已经将 text_b 默认设置为 None ,因为我们的目标是使用单个序列而不是序列对。

而且 InputFeatures 类封装了 BERT 输入需要的特性(见上面的输入图)。 tokens 属性显然是输入记号的向量, input_ids 是与词汇表中的记号相对应的 id, input_mask 从填充中注释真实的记号序列,最后, input_type_ids 将段 A 与段 B 分开,因此它在这里实际上并不相关。

现在,添加以下代码:

这是为了设置我们的估计器。估计器只是 tensorflow 提供的模型的抽象,以及用于训练、评估和预测的 API。因此,我们的定制估算器是 BertModel 的包装器。诚然,有部分代码可以从上面删除,但我坚持谷歌提供的例子只是为了保持一致。重要的部分是第 60 行——在这里定义了 bert 模型——和第 100 行,在这里提取了前 4 层的预测。

继续添加以下内容:

这是负责输入处理的函数。换句话说,它将输入样本转换为输入特征

除此之外,我们还创建了一个函数,用于将一个普通的字符串序列转换成 InputExample :

现在,对于代码的最后一位,我们定义了一个函数,该函数接受一个字符串数组作为参数,接受嵌入输出的所需维度(max 768 ),并返回一个字典,将令牌作为键,将嵌入向量作为值。

上面的代码片段简单地构建了估计器,并基于给定的输入调用预测。

让我们通过运行以下命令来测试我们的模型:

*embeddings = get_features([“This is a test sentence”], dim=50)
print(embeddings)*

如果一切顺利,您将拥有一个包含每个令牌大小为 50 的嵌入的字典。请记住,这些是上下文化的嵌入,所以如果您在不同的序列上有重复的标记,那么只有最后一个标记的嵌入会保留在字典中。要保留两者,请用不同的数据结构替换字典。

你可以在这里找到完整的笔记本。

未来的工作

现在,这些嵌入可以用作为定制任务构建的其他模型的输入特性。然而,我将把它留到另一篇文章中。或者甚至可以实现一个 BERT Keras 层来实现无缝嵌入集成。

结论

这都是我给你们的。我希望你喜欢这篇文章,并希望对伯特有一个更清晰的了解。欢迎在评论区发表您的反馈或问题。

参考资料:

[1] J.Devlin,M. Chang,K. Lee 和 K. Toutanova, BERT:用于语言理解的深度双向转换器的预训练 (2018)

[2],Alec,Wu,Jeff,Child,Rewon,Luan,David,Amodei,Dario,Sutskever,Ilya,语言模型是无监督多任务学习器 (2019)

[3] M. Peters,M. Neumann,M. Iyyer,M. Gardner,C. Clark,K.Lee 和 L.Zettlemoyer,深度语境化的词语表征 (2018),计算语言学协会北美分会

[4] T.Mikolov,I. Sutskever,K. Chen,G. Corrado 和 J. Dean,单词和短语的分布式表示及其组合性 (2013)

[5]A .瓦斯瓦尼、n .沙泽尔、n .帕尔马、j .乌兹科雷特、l .琼斯、A .戈麦斯、l .凯泽和 I .波洛苏欣,注意力是你所需要的全部 (2017)

[6]吴、舒斯特、陈、乐、、马切里、克里昆、曹、高、马切里、克林纳、沙阿、约翰逊、刘、Kaiser、S. Gouws、Y. Kato、T. Kudo、H. Kazawa、K. Stevens、G. Kurian、N. Patil、W. Wang、C. Young、J. Smith、J. Riesa、A. Rudnick、O. Vinyals、G. Corrado、M. Hughes 和 J. Dean 谷歌的神经机器翻译系统:弥合人类和机器翻译之间的鸿沟 (2016)

面向初学者的 NLP:清理和预处理文本数据

原文:https://towardsdatascience.com/nlp-for-beginners-cleaning-preprocessing-text-data-ae8e306bef0f?source=collection_archive---------2-----------------------

NLP 是自然语言处理的缩写。你可能知道,计算机不像理解数字那样擅长理解单词。这一切都在改变,尽管 NLP 的进步每天都在发生。事实上,苹果的 Siri 和亚马逊的 Alexa 等设备可以(通常)理解我们询问天气、方向或播放某种类型的音乐,这些都是自然语言处理的例子。你的电子邮件中的垃圾邮件过滤器和你在小学学会打字后使用的拼写检查是你的计算机理解语言的一些其他基本例子。

作为一名数据科学家,我们可能会使用 NLP 进行情感分析(将单词分类为具有正面或负面含义),或者在分类模型中进行预测,等等。通常情况下,无论我们是得到数据还是不得不搜集数据,文本都是自然的人类格式的句子、段落、推文等。在我们开始分析之前,我们必须做一些清理工作,将文本分解成计算机容易理解的格式。

对于这个例子,我们正在检查亚马逊产品/评论的数据集,可以在 data.world 上找到并免费下载。我将在 Jupyter 笔记本中使用 Python。

以下是使用的导入:

(如果您以前从未使用过,您可能需要在单元格中运行nltk.download()。)

读入 csv 文件,创建数据框并检查形状。我们从 10,000 行和 17 列开始。每一行都是亚马逊上不同的产品。

我进行了一些基本的数据清理,现在我不会详细介绍,但如果你想要一些提示,你可以在这里阅读我关于 EDA 的帖子。

为了使本例的数据集更易于管理,我首先删除了空值过多的列,然后删除了所有剩余的空值行。我将number_of_reviews列的类型从 object 改为 integer,然后创建了一个新的 DataFrame,只使用不超过 1 个 review 的行。我的新形状是 3705 行 10 列,我把它重新命名为reviews_df

注意:如果我们真的要使用这个数据集进行分析或建模,或者除了文本预处理演示之外的任何事情,我会建议 而不是 删除这么大比例的行。

下面的工作流程是我被教导使用和喜欢使用的,但是步骤只是让你开始的一般建议。通常我必须根据文本格式进行修改和/或扩展。

  1. 删除 HTML
  2. 标记化+去除标点符号
  3. 删除停用词
  4. 词汇化或词干化

在清理这些数据时,我遇到了一个以前从未遇到过的问题,并从geeksforgeeks.org那里学到了一个很酷的新技巧,将一列中的字符串按照空格或指定字符拆分成多列。

我最感兴趣的列是customer_reviews,但是,仔细一看,它目前在由//分隔的一个单元格中包含评论标题、评级、评论日期、客户名称和评论。

熊猫.str.split的方法可以适用于一个系列。第一个参数是你想要分割的字符串的重复部分,n=最大分割数,expand=True将分割成新的列。我将 4 个新列设置为一个名为reviews的新变量。

然后可以在原来的reviews_df中重命名新的 0,1,2,3,4 列,去掉原来乱七八糟的列。

我对新的customer_name列运行相同的方法,在\n \n上进行拆分,然后删除第一列和最后一列,只留下实际的客户名称。如果这是一篇更长的文章,我们还可以做更多的事情!马上,我可以看到名字和日期仍然可以使用一些清洗,把他们放在一个统一的格式。

删除 HTML 是我这次没有做的一个步骤,但是,如果数据来自网络抓取,从这个步骤开始是个好主意。这是我会使用的函数。

几乎每一步都包括创建一个函数,然后将其应用于一个系列。做好准备,lambda 函数将很快成为你的新朋友!您也可以构建一个函数来一次性完成所有这些工作,但是我想展示分解并使它们更容易定制。

去掉标点符号:

一种方法是通过 list comprehension 循环遍历整个系列,并保留不在string.punctuation中的所有内容,这是我们在开始时用import string导入的所有标点符号的列表。

“ “.join will join the list of letters back together as words where there are no spaces.

If you scroll up you can see where this text previously had commas, periods, etc.

然而,正如您在上面的第二行输出中看到的,这个方法没有考虑用户输入错误。客户输入了“孙子,am,一旦去掉逗号,这个单词就变成了一个单词“grandsonam。我仍然认为如果你需要的话,知道这些是很方便的。

符号化:

这使用正则表达式(也称为 RegEx)根据指定的模式将字符串分解成单词或片段的列表。我这次选择使用的模式(r'\w')也去掉了标点符号,尤其是对于这些数据来说,这是一个更好的选择。我们还可以在 lambda 函数中添加.lower(),让所有内容都变成小写。

see in line 2: “grandson” and “am” are now separate.

正则表达式的其他一些例子有:

‘\w+|\$[\d\.]+|\S+’ =按空格或不与数字相连的句点分割

‘\s+’, gaps=True =获取除空格以外的所有内容作为令牌

‘[A-Z]\w+’ =只有以大写字母开头的单词。

删除停止字:

我们在开头用from nltk.corpus import stopwords从 NL 工具包中导入了一个最常用单词的列表。您可以运行stopwords.word(insert language)来获得每种语言的完整列表。有 179 个英语单词,包括'我','我','我自己','我们','你','他','他的',例如。我们通常希望删除这些,因为它们的预测能力较低。有些时候你可能想保留它们。例如,如果您的语料库非常小,删除停用词会使单词总数减少很大一部分。

词干化&词汇化:

这两种工具都将单词缩短回其词根形式。词干有点激进。它会根据常见的前缀和/或词尾进行删减。它有时会有所帮助,但并不总是如此,因为很多时候新单词是如此的根以至于失去了它的实际意义。另一方面,词汇化将常见单词映射到一个库。与词干提取不同,它总是返回一个可以在字典中找到的合适的单词。我喜欢比较两者,看哪一个更适合我的需要。我通常更喜欢 Lemmatizer,但令人惊讶的是,这一次,词干似乎有更多的影响。

Lemmatizer: can barely even see a difference

你在斯特梅尔身上看到了更多的不同,所以我会保留这一点。因为这是最后一步,所以我在函数中添加了" ".join()来将单词列表连接在一起。

现在你的文本已经可以被分析了!您可以继续使用这些数据进行情感分析,可以使用评级或制造列作为基于单词相关性的目标变量。也许建立一个基于用户购买或商品评论或客户分类的推荐系统。可能性是无限的!

https://pixabay.com/photos/thank-you-neon-lights-neon-362164/

NLP 果酱:感恩而死和费西合唱团

原文:https://towardsdatascience.com/nlp-jam-the-grateful-dead-and-phish-4933063361d2?source=collection_archive---------26-----------------------

在这篇博文中,我将分享我在数据科学训练营中完成的一个项目。

介绍

我的数据科学训练营班级被分配了构建 NLP 模型的任务,该模型将接收 reddit 帖子,并根据文本将其分类为属于某个子编辑。项目的第一步是选择两个不同的子街道。

感恩而死乐队和费西合唱团经常被联系在一起,因为这两个乐队有着类似的艺术手法,这与大多数音乐不同,因为他们强调现场音乐会表演而不是录音室专辑。这两个粉丝群都很早就开始使用互联网,所以他们有非常活跃的 reddit 页面以及其他几个在线论坛。作为一个对这两个乐队都着迷的人,感恩而死乐队和费西合唱团·萨伯雷迪兹乐队似乎是一个显而易见的选择。

乐队的简短描述:

The Grateful Dead

感恩而死在 60 年代作为旧金山反文化运动的一部分而声名鹊起。他们吸收了各种音乐的影响——蓝草音乐、古典音乐、民谣、乡村音乐、蓝调音乐、爵士乐——并形成了自己独特的音乐风格。他们开创了一种演奏独特音乐会的风格,主要是即兴演奏。由于他们的演唱会与众不同,他们吸引了粉丝,这些粉丝成为了狂热的追随者,以至于一些粉丝会和乐队一起“巡演”。感恩而死的粉丝被称为“死鬼”。

Phish

费西合唱团成立于 1983 年,当时他还是大学生,并很快开发了一个疯狂原创的声音和歌曲目录。在大约 10 年内,他们在全国范围内拥有了自己的铁杆粉丝。尽管有不同的音乐影响和风格,他们遵循感恩而死的模式,使他们的音乐会与众不同,并强调他们的表演即兴。显然,他们的粉丝被称为“费西合唱团头”。

如果你对这几个乐队的音乐感兴趣,我会在这篇文章的最后链接到几个签名音乐。很明显,你能从一首歌或一段音乐中分辨出的东西是有限的,但是我希望能告诉你以下几点:

就乐队的乐器构成而言,有一些音乐上的相似之处,但总体而言,音乐风格相当独特。与此同时,这些乐队有一个共同的音乐表演方法,他们用自己的歌曲作为即兴创作空间的发射台。

对我来说,这是比较费西合唱团和死者最有趣的地方之一。有时候,我觉得有一种普遍的误解,认为这两个乐队有非常相似的音乐,但我认为真正将这些乐队联系在一起的是他们的粉丝。

死脑筋和费西合唱团头脑是出了名的忠诚。两个乐队都有数百首歌曲,任何给定的音乐会都由这些歌曲的一些样本组成,无论这些歌曲的顺序是在表演时自发构建的。此外,许多歌曲都附加了即兴部分,每个人的表演都不一样。结果是每场音乐会都是一场独特的演出。这也是为什么这些粉丝会不远千里重复观看演出的原因。对我来说,这表明了这两个歌迷群体在如何联系和消费音乐,以及他们如何对待生活方面的相似之处。

由于这种相似性,我希望——除了乐队本身的主要讨论主题——这两个留言板在某种程度上是可以互换的。这两个论坛大概都包含了很多关于音乐的类似讨论。这两个论坛可能都包含了很多关于时事、个人故事、哲学等各种各样的讨论。关键是,我确信有很多帖子,即使是像我这样的相关专家也能够准确分类。最重要的是,这也是我为什么要建立一个模型来对来自这些子主题的帖子进行分类的原因——我的 NLP 分类器会像经常访问这些留言板的人一样准确吗?

也许是这样,也许不是…

假设

I can tell your future, just look what’s in your hand…

在进行任何数据收集之前,我对 NLP 分类模型的性能有一些想法。

  1. 我认为建立一个精确的模型是相当简单的。这是基于这样一种想法,即会有许多特定于乐队的术语反复出现。这可能是像乐队成员姓名、歌曲名称、专辑名称或乐队不重叠的年份这样的词。我认为这些子主题的大部分帖子至少会包含一些这类术语。
  2. 我认为一个模特很难对模糊的帖子进行分类。我认为会有很多帖子不会明确提到任何一个乐队。
  3. 我认为该模型在分类“交叉”帖子时会有挑战,其中一个乐队在另一个乐队的子编辑中被讨论。由于两个乐队都有很多粉丝,我知道这种讨论确实经常发生。

数据

这个分析的数据是使用 Reddit pushshift API 收集的。我从这些子主题中收集了大约 6000 篇帖子,时间跨度大约为两年。我只收录了原帖标题和“自文”,没有收集到相应的评论。

The data called for some routine cleaning…

一旦有了数据,我必须执行一些数据清理操作:

  • 数据包含不包含任何“自我文本”的条目。这是用户附加到帖子上的文本,独立于帖子的标题。这些空值被替换为空白单元格。
  • 许多条目包含不代表用户语言的文本,如“\n”、“[已删除]”、“[已删除]”或 URL。这些都是从数据中过滤出来的(扔掉你最终不需要的东西)。
  • 我对文本进行了词条分类,以便将具有相同词根的单词组合在一起(保留重要的内容)。

这样做之后,数据就可以进行分析了。

建模

让我们认真对待事实真相吧!

我在分析中尝试了以下模型:

  • 计数矢量化逻辑回归
  • 计数矢量化的朴素贝叶斯
  • 采用 TF-IDF 矢量化的逻辑回归
  • 带 TF-IDF 矢量化的朴素贝叶斯
  • 计数矢量化的支持向量机
  • 带计数矢量化的随机森林
  • 具有 TF-IDF 矢量化的支持向量机
  • 带 TF-IDF 矢量化的随机森林

所有的模型都表现得相当准确,而且它们都有相当大的差异。

逻辑回归模型和朴素贝叶斯模型的精确度最高,但差异最大(约 90%的测试精确度/~99%的训练精确度)。

随机森林模型减少了方差,但是具有最大的偏差(大约 90%的测试精度/大约 85%的训练精度)。

带有 TF-IDF 矢量化的支持向量机模型是我的首选模型。它具有最低的方差,并且其测试精度足够接近表现最好的逻辑回归/朴素贝叶斯模型。该模型对测试数据分类的准确率为 90%,对训练数据分类的准确率为 94%。

结果

在这一部分,我将浏览一些我认为最有趣的结果。

在每个子编辑的帖子中,哪些区别词出现得最频繁?

我想找出哪些区别词或“流行语”在这些子词中最常见。这些词特指某个乐队。它们大多是乐队成员的名字、歌曲标题和相关日期。有趣的是,这些词中有许多在两个论坛中都频繁出现,所以仅仅出现一个流行语不足以做出准确的分类,尽管它可能是一个强有力的指标。

Buzzwords that appeared most frequently on the Dead subreddit

Buzzwords that appeared most frequently on the Phish subreddit

哪些词在误分类帖子中出现频率最高?

在调查分类错误的帖子时,我研究了哪些词出现得最频繁。为了构建下面的情节,我把普通的词过滤掉了。

Words that appeared most frequently in misclassified posts

死子旋涡和费西合唱团子旋涡的错误分类比例是多少?

有 161 个死帖被错误分类,相比之下,费西合唱团有 142 个帖子被错误分类。这个看起来比较平衡。看看这种趋势是否能在更大样本的结果中保持下去将会很有趣。这种轻微的不平衡可能是因为费西合唱团论坛包含了更多针对乐队的讨论,因为他们仍然是一个活跃的乐队,而感恩而死乐队的成员现在在场外表演。

哪些类型的帖子容易分类错误?

浏览错误分类的帖子时,我注意到有一些常见类型的帖子模型很难正确分类:

  • 与门票交易/销售相关的帖子经常被错误分类,因为这些帖子往往主要涉及日期、地点和位置。

一些例子:

最好的换票地点?我不是要硬着头皮或超越面值,只是想用我的 GA 换一个好的硬座。矮老婆意味着我需要第一排。

有人拿到票了吗?想知道价格范围是多少,这样我就知道该把什么放在一边,谢谢!

芝加哥门票警告…对于所有寻找便宜芝加哥门票的人来说,不要从 Craigslist 购买硬票。现在 CL 上到处都是假票。就像棕色的酸。离远点。但是如果你想尝试,那就去买彩票吧。注意安全,聪明点

  • 在一个乐队的子编辑中提到另一个乐队的帖子自然容易被错误分类

一些例子:

到今天为止,特雷比杰瑞活得久。永远感激我们能够听到和看到他们每个人。他们对音乐的贡献将会持续很长时间。

我在 Dead subreddit 上发了帖子,但是还有其他以感恩而死/网络钓鱼/甜蜜乐队为主题的梦幻棒球联盟吗?

1997 年秋,1977 年春,逝者乐队发行了 1977 年 5 月的套装和今年的康奈尔。我想现在是费西合唱团发布 97 秋季套装的时候了。今年夏天我花了很多时间听这两个巡演,他们都以自己的方式分享了好的放克,有着理想的能量和紧绷感。只是想说出来。我要我那该死的套装。

  • 没有明确提到任何一个乐队的模糊帖子自然有被错误分类的倾向。

一些例子:

YouTube 上最喜欢的完整节目?考虑今晚上演一出老剧。你会推荐什么?

谁知道星期天在凤凰城的表演结束后,我可以把车停在哪里?

你在场地上对邪教有什么体验?我一直在读关于十二个部落的书,并且很有兴趣听听你和他们或者任何其他邪教的冲突。我想写一篇关于它们的研究论文。你认为它们太危险了,不能去吗?谢谢!

声明似乎最终都是徒劳的…

结论

在测试各种不同的 NLP 模型时,这是一个有用的练习。我认为我的模型的性能总体来说相当不错,但仍有改进的潜力。

总的来说,我的假设——模型可能是准确的,但在某些类型的职位上容易被错误分类——被证明是正确的。

我的第一个想法是在未来改进这个模型,获取更多的数据。为此,我要么获取更多的帖子,要么包含我在建模过程中分析的每个帖子的评论文本。拥有更大的数据集将允许模型学习更多特定于乐队的流行语,并且它将允许模型潜在地辨别任何正在进行的内部笑话或重复出现的引用,这些引用是一个子编辑或另一个子编辑所独有的。

正如我的假设所反映的那样,我认为在这些子主题之间对帖子进行分类的任何模型中都存在一些不可避免的偏差是合理的。这两个子主题都包含了大量关于音乐和音乐会的类似对话,并不一定专门针对任何一个乐队。此外,两个留言板都包含了很多关于其他乐队的对话。费西合唱团和感恩而死乐队有很多粉丝,在两个子栏目中也有很多关于这两个乐队的讨论。

有趣的是,每个乐队的一些热门词汇在两个子栏目中都很常见。由于论坛之间有很多交叉讨论,“费西合唱团”和“死亡”是这样的词,虽然特别有可能出现在各自的子主题中,但也很有可能出现在其他子主题中。这意味着,仅仅有一个“流行语”不足以对每个帖子进行正确分类。这可能是许多错误分类的一个因素。

有趣的是,用另外两个在粉丝群方面联系不那么紧密的子乐队来重复这个练习。在两个非音乐子唱片上重复这个练习也是很有趣的。我想知道准确性如何比较,以及同类模型是否会成为最佳模型。

谢谢你迁就我!我相信你和我一样觉得这很有趣。不知何故,我继续寻找新的方式来娱乐费西合唱团和死者。在发展我对 NLP 的理解以及随之而来的工具方面,我还有很长的路要走,但至少我很享受这一过程!

最后,让空气中充满歌曲…

10/18/74 Dark Star — Winterland Ballroom

10/20/13 Tweezer — Hampton Coliseum

Kaggle 的 NLP 竞赛入门

原文:https://towardsdatascience.com/nlp-kaggle-competition-a3f22ecbbe6f?source=collection_archive---------22-----------------------

NLP 入门笔记本和探索性数据分析

Photo by Jon Tyson on Unsplash

Quora 不真诚问题分类竞赛是一项自然语言处理任务,目标是预测问题的意图是否真诚。

Quora 是一项帮助人们互相学习的服务。在 Quora 上,人们提问和回答问题——提供这种服务的一个关键挑战是过滤掉不真诚的问题。Quora 试图过滤掉有毒和分裂的内容,以维护他们的政策:

友善点,尊重点。

什么是不真诚的问题?

一个不真诚的问题被定义为一个旨在陈述而不是寻找有用答案的问题。根据 Kaggle 竞赛的描述,一个言不由衷的问题的特征包括:

有非中性声调的:

  • 用夸张的语气来强调一群人的观点。
  • 是修辞性的,意在暗示对一群人的陈述。

具有贬义或煽动性:

  • 提出针对受保护人群的歧视性观点,或寻求对刻板印象的确认。
  • 对特定的人或人群进行诋毁性的攻击/侮辱。
  • 是基于一群人的古怪前提。
  • 贬低一种不可修正和不可测量的特性。

并不基于现实:

  • 基于错误的信息,或包含荒谬的假设。
  • 使用性内容(乱伦,兽交,恋童癖)来获得震撼价值,而不是寻求真正的答案。

基本上,任何问题的意图都是愤怒或冒犯,而不是为了获取信息。一些不真诚的问题包括:

  • 为什么中国人讨厌唐纳德·特朗普?
  • 去伊朗旅行的美国人有精神疾病吗?

我们可以清楚地看到,这些问题旨在煽动而不是获取信息,需要从 Quora 的平台上排除。

预期的困难

大型数据集

训练数据超过一百万行。我预计在处理大型数据集时会有挑战。挑战可能包括遇到内存错误和过长的处理时间。

为了应对大型数据集,可以尝试几种技术,包括使用较小的数据样本进行训练和降维。我预计功能选择和工程以及模型优化将是重要的。

不平衡数据集

数据集非常不平衡,只有 6%的样本属于目标(不真诚)类。我预计这将导致召回的挑战。最大化回忆,或真正的阳性率,在这里可能是一个困难,因为少量的虚假样本。我预计重采样技术和数据扩充可以提高模型性能。

向他人学习的重要性

正如威尔·科尔森在他的住宅信贷违约风险篇中所说:

数据科学家不是站在巨人的肩膀上,而是站在成千上万为了所有人的利益而公开其工作的个人的背上。

他称 Kaggle 竞赛为“合作项目”,这是千真万确的。Kaggle 社区非常支持,不仅是学习新技术和技能的好地方,也是挑战自我提高的好地方。

探索性分析

这个的第一个笔记本被设计用来熟悉手头的问题,并设计一个前进的策略。

一个很好的开始是想象我们目标的分解。

Distribution of Questions

从上面的图中我们可以看到我们有一个阶级不平衡的问题。

Comparison of Number of Tokens per Question

上面的图显示了每个类别中标记数量的显著差异。这可以通过完成 t 检验来证实:

  • t 值:-106.72
  • p 值:0

Number of Sentences per Questions (plotted on log scale)

通过 t 检验,每个问题的句子数量的差异也被确认为显著:

  • t 值:-56.09
  • p 值:0

另一件有趣的事情是在真诚和不真诚的问题中出现的最常见的单词。

Insincere Questions Most Common Words

Sincere Questions Most Common Words

阶级不平衡

正如我们上面看到的,我们有一个阶级不平衡的问题。

不平衡类是机器学习分类中的一个常见问题,其中每个类中的观察值比例不成比例。(在这篇帖子中,我探索了处理阶级不平衡的方法。)

只有 6.6%的数据集属于目标类,我们肯定会有一个不平衡的类!

这是一个问题,因为许多机器学习模型被设计成最大化整体准确性,特别是对于不平衡的类,这可能不是使用的最佳度量。

分类准确度被定义为正确预测的数量除以总预测数乘以 100。例如,如果我们简单地预测所有问题都是真诚的,我们将获得 93%的分类准确率!

竞争指标

在继续创建基线模型之前,了解我们的竞争指标很重要。

这项比赛使用 F1 分数,它平衡了精确度和召回率。

  • 精度是真正肯定的数量除以所有肯定的预测。精度也叫阳性预测值。它是对分类器准确性的一种度量。低精度表示大量的误报。
  • 召回率是测试数据中真阳性的数量除以阳性值的数量。回忆也称为敏感度或真实阳性率。它是对分类器完整性的一种度量。低召回率表示大量的假阴性。

数据准备

因为我们有一个不平衡的数据集,所以我们将对多数类进行缩减采样,使其等于少数类的大小。这不仅会平衡我们的数据集,还会由于训练数据中样本数量的减少而减少处理时间。

在建模之前,我们使用 Gensim 应用一些基本的文本预处理。

Gensim 是一个很棒的 NLP 库——它的速度非常快,并提供了文本清除和 n-gram 生成的工具——我们在这个基线建模内核中使用了这两种工具。

基线模型

对于我们的基线模型,我们将尝试:

  • 逻辑回归:分类的线性模型。它们训练和预测速度快,伸缩性好,易于解释,因此是基线模型的良好选择。
  • 朴素贝叶斯:这些分类器训练速度非常快,可以很好地处理高维稀疏数据,包括文本。它们是基于应用贝叶斯定理的,并且是“幼稚的”,因为它们假设了特征之间的独立性。Scikit-Learn 实现了几种广泛用于文本数据的朴素贝叶斯分类器,包括 Bernoulli(我们在这里使用)和多项式。
  • XGBoost(极限梯度提升):梯度提升决策树的实现,旨在提高速度和性能。因此,它经常胜过其他算法——似乎是 Kaggle 竞赛中非常受欢迎的选择。
  • 集成模型: Scikit-learn 陈述了“集成方法的目标是组合用给定学习算法构建的几个基本估计量的预测,以提高单个估计量的可推广性/稳健性。”我们将使用 scikit-learn 的投票分类器来组合上述三个模型。

解释结果—分类报告

  • 精度是真阳性的数量除以所有阳性预测。精度也叫阳性预测值。它是对分类器准确性的一种度量。低精度表示大量的误报。
  • 召回是测试数据中真阳性的数量除以阳性值的数量。回忆也称为敏感度或真实阳性率。它是对分类器完整性的一种度量。低召回率表示大量的假阴性。
  • F1-得分是精确度和召回率的调和平均值。
  • Support 是每个类的真实结果数。

基线测试集结果

  • 逻辑回归 F1: 86.9
  • 朴素贝叶斯 F1: 86.5
  • XGBoost F1: 70.9
  • 合奏 F1: 86.6

这些结果看起来很有希望。

然而,当提交给比赛时,我得到了 0.483 的公共排行榜分数。根据 F1 分数的下降,我们可以假设我们的模型不能很好地概括未知的验证数据。我们绝对有很大的提升空间!

结论

这篇文章和介绍性的内核展示了我对 Kaggle 竞赛的开始,并提供了改进的基线。在未来的内核和文章中,我们将探索其他重采样技术和深度学习,以提高我们的竞争分数。

TensorFlow.js 浏览器中的 NLP Keras 模型

原文:https://towardsdatascience.com/nlp-keras-model-in-browser-with-tensorflow-js-f4d5035466a2?source=collection_archive---------6-----------------------

如何在带有 tensorflow.js 的浏览器中使用 Keras 模型

在这篇文章中,我将尝试涵盖三件事:

  1. 如何编写简单的命名实体识别模型——典型的自然语言处理 (NLP)任务。
  2. 如何将此模型导出为 TensorFlow.js 格式。
  3. 如何制作一个简单的 WEB 应用程序在没有后端的情况下搜索字符串中的命名实体?

你可以在我的个人网站上测试一下。

首先,这篇博客是写给那些了解深度学习主要阶段(RNN,注意)和 JavaScript 基础的人的。如果你不擅长 RNN,我推荐你阅读 Andrej Karpathy 的《循环神经网络的不合理有效性》。

TensorFlow.js 是一个 JavaScript 库,用于用 JavaScript 开发和训练 ML 模型,并在浏览器或 Node.js 上部署。

对于这个例子,我们将使用简单的 keras 模型来解决经典的 NER 任务。我们将在 2003 年的数据集上进行训练。我们的模型只是单词嵌入、GRU 和非常简单的注意机制。之后,我们将在浏览器中可视化注意力向量。如果你熟悉解决类似任务的现代方法,你知道,这种方法不是最先进的。但是,对于在浏览器中运行它,例如,它就足够了。此外,如果您熟悉 NER 任务,您可以跳过 Keras 上关于命名实体识别、数据和 NER 神经网络模型的下两个部分,查看源代码。

任务和数据

根据你的经验,你可能以不同的名称来了解它,比如序列标签、词性标签或者像我们的任务中的命名实体识别。

通常,命名实体识别(NER)任务是 seq2seq 任务。对于来自 x_i 的每个标记,我们必须预测标记 y_i,其中 x 是输入序列,y 是命名实体的序列。

在本例中,我们将寻找人员(B-PER,I-PER)、地点(B-LOC,I-LOC)和组织(B-ORG,I-ORG),此外,该模型将定义特殊的实体-杂项-命名的实体,而不是人员、地点和组织。

首先,我们必须为计算机准备数据(是的,我们将使用计算机来解决这个任务:)。

在这篇博文中,我们的目标并不是在 CoNLL2003 数据集上得到 SOTA 结果,这就是为什么我们的预处理不是很好。但仅举一个例子,我们将通过 load_data 的方法加载数据:

如你所知,神经网络不能处理文字,只能处理数字。这就是为什么我们应该用数字来表示单词。这不是一个困难的任务,我们可以列举所有独特的单词,并写单词的数量,而不是单词。为了储存数字和单词,我们可以创造词汇。这个词汇表应该支持“未知”()的单词,因为当我们用词汇表中没有的新单词对一个新字符串进行预测时。单词“padded”()是因为对于神经网络来说,所有的字符串应该具有相同的大小,当一些字符串比另一个小时,我们用这个单词来填充间隙。

此外,让我们写一个简单的助手,把句子翻译成数字序列。

正如你在上面读到的,我们应该用神经网络填充序列,为此,你可以使用内部 Keras 方法pad _ sequences

模型

让我猜猜……RNN?

是的,是 RNN。更具体地说,它是 GRUs(门控循环单元)和简单的注意层。作为文字表述用手套。在这篇博文中,我将不再赘述细节,只留下模型的代码。希望很好理解。

建立模型后,要对模型进行编译、训练和保存。您可以猜测,为了在浏览器中运行这个模型,我们不仅要保存模型的权重,还要保存模型描述以及单词和标签的词汇表。让我们定义将模型和词汇表导出到 JavaScript 支持的格式(基本上是 JSON)的方法。

最后,让我们编译、训练和导出模型:

这个步骤的完整代码,你可以在我的 GitHub 资源库中找到 train.py.

发展环境

模型已经准备好了,现在,我们应该开始开发一个 web 应用程序,在浏览器中评估这种模式。我们需要一个开发环境。基本上,如何存储模型、权重和词汇并不重要,但是对于“简单开始”,我将向您展示我的解决方案——node . js 本地服务器。

我们需要两个文件: package.jsonserver.js.

在 server.js 中,我们定义了静态文件夹来存储模型、js 脚本和所有其他文件。要使用此服务器,您应该输入

npm 安装& &节点 server.js

在你的终端里。之后,您可以通过 http://localhost:8081 在浏览器中访问您的文件

网络应用

有【index.html】、 predict.js 和上一步生成的文件。如你所见,这是一个非常小的网络应用程序。index.html 包含输入字符串的要求和输入字段。

现在,博文最有趣的部分—关于 tensorflow.js .你可以通过TF . loadlayersmodel方法调用 await 操作符来加载模型。这很重要,因为我们不想在加载模型时阻塞我们的 web 应用程序。如果我们加载模型,我们将得到只能预测令牌的模型,但注意力向量呢?如何从关注中获得激活?为了从内部层获取数据,在 tensorflow.js 中,我们应该创建一个新模型,其输出层将包含原始模型的输出和其他层,如下所示:

这里, 模型 是原始模型, emodel 是以注意力向量为输出的模型。

预处理

现在我们必须像在 Python 脚本中一样实现字符串的预处理。对我们来说这不是一个困难的任务,因为 Python 和 JavaScript 上的正则表达式非常相似,其他方法也很相似。

做预测

现在我们应该提供从简单的文本字符串格式到 TF 格式的转换数据—张量。在上一节中,我们编写了将字符串转换为数字数组的助手。现在我们应该从这个数组中创建 tf.tensor 。如你所知,模型的输入层有形状 (无,113) ,这就是为什么我们要扩大输入张量的维数。好了,就这些了,现在我们可以通过 在浏览器中进行预测。预测 的方法。之后,您应该将预测数据打印到浏览器中,您的无后端神经网络 web 应用程序就准备好了。

结论

TensorFlow.js 是一个用于在 chrome、Firefox 或 safari 等浏览器中使用神经网络的库。如果你在 iPhone 或 Android 智能手机上打开这个网络应用,它也能工作。

可以通过这个链接在我的个人网站上测试:http://deep division . net/2019/03/20/NLP-keras-model-in-browser-with-tensorflowjs . html

此外,你可以在我的 GitHub 中找到这段带有一些补充的代码。

深度学习的文本预处理方法

原文:https://towardsdatascience.com/nlp-learning-series-part-1-text-preprocessing-methods-for-deep-learning-20085601684b?source=collection_archive---------11-----------------------

NLP 学习系列(第一部分)

深度学习的文本预处理权威指南

Photo by Raychan on Unsplash

最近,我在 Kaggle 上发起了一个名为 Quora 问题不真诚挑战的 NLP 竞赛。这是一个关于文本分类的 NLP 挑战,在经历了比赛以及 kaggle 专家提出的宝贵内核后,问题变得更加清晰,我想到了分享知识。

因为我们有大量的材料要覆盖,我将这篇文章分成一系列的文章。第一篇文章,即这篇文章,将基于与深度学习模型一起工作的预处理技术,我们还将讨论增加嵌入覆盖。在第二篇文章的中,我将试着带你了解一些基本的传统模型,如 TFIDF 和 SVM,它们已被用于文本分类,并试着评估它们的性能以创建一个基线。我们将在第三篇文章中更深入地研究深度学习模型,这些模型将专注于解决文本分类问题的不同架构。我们将尝试使用我们在本次比赛中未能使用的各种其他模型,如系列文章第四篇中的 ULMFit 迁移学习方法。

作为旁注:如果你想了解更多关于 NLP 的知识,我想推荐这个关于高级机器学习专精中自然语言处理的超赞课程。您可以免费开始 7 天的免费试用。本课程涵盖了自然语言处理中从基础到高级的各种任务:情感分析、摘要、对话状态跟踪等等。

我可能需要一点时间来写完整个系列。在那之前,你可以看看我的其他帖子:【Kagglers 正在使用什么进行文本分类,其中谈到了 NLP 中使用的各种深度学习模型和如何从 Keras 切换到 Pytorch 。

首先让我解释一下文本分类的问题。文本分类是自然语言处理中的一项常见任务,它将一个长度不定的文本序列转换成一个文本类别。你怎么能利用这一点?

  • 去寻找一篇评论的感悟。
  • 在脸书这样的平台上找有毒评论
  • 在 Quora 上找不真诚的问题。kaggle 上目前正在进行的比赛
  • 在网站上寻找虚假评论
  • 文字广告会不会被点击?

这些问题都有一些共同点。从机器学习的角度来看,这些本质上是相同的问题,只是目标标签发生了变化,其他什么都没有。也就是说,添加业务知识可以帮助使这些模型更加健壮,这就是我们在预处理数据以进行测试分类时想要加入的内容。虽然我在这篇文章中关注的预处理管道主要围绕深度学习,但大多数也适用于传统的机器学习模型。

但是,在经历所有步骤之前,让我先经历文本数据的深度学习管道的流程,以获得关于整个过程的更高层次的观点。

我们通常从清理文本数据和执行基本 EDA 开始。在这里,我们试图通过清理数据来提高数据质量。我们还试图通过移除 OOV(词汇外)单词来提高我们的 word2vec 嵌入的质量。这两个步骤之间通常没有太多的顺序,我通常在这两个步骤之间来回切换。接下来,我们创建一个可以输入深度学习模型的文本表示。然后我们开始创建模型并训练它们。最后,我们使用适当的指标评估模型,并获得相关股东的批准来部署我们的模型。如果这些术语现在没有多大意义,也不用担心。我将在这篇文章中尝试解释它们。

在这个连接处,让我们绕一点弯子来谈谈单词嵌入。在为我们的深度学习模型预处理数据时,我们必须考虑它们。

word2vec 嵌入入门:

我们需要一种方法来表示词汇。一种方法是使用单词向量的热编码,但这并不是一个好的选择。一个主要的原因是,一个热门词向量不能准确地表达不同词之间的相似度,如余弦相似度。

给定一个热编码向量的结构,不同单词之间的相似度总是为 0。另一个原因是,随着词汇量的增加,这些热编码向量变得非常大。

Word2Vec 通过为我们提供单词的固定长度向量表示,并通过捕捉不同单词之间的相似性和类比关系,克服了上述困难。

单词向量的学习方式允许我们学习不同的类比。它使我们能够对单词进行代数运算,这在以前是不可能的。比如:什么是王者——男人+女人?它出来是女王。

Word2Vec 向量还帮助我们找出单词之间的相似性。如果我们试图找到与“好”相似的词,我们会发现“棒极了”、“棒极了”等等。word2vec 的这一特性使得它在文本分类中具有不可估量的价值。现在我们的深度学习网络明白了,“好”和“伟大”本质上是意思相近的词。

因此,简单来说,word2vec 为单词创建了向量。因此,对于字典中的每个单词(常见的二元模型也是如此),我们都有一个 **d** 维向量。我们通常使用预先训练的词向量,这些词向量是在对维基百科、推特等大型文本语料库进行训练后由他人提供给我们的。最常用的预训练单词向量是具有 300 维单词向量的 Glove 和 Fasttext。我们将在这个岗位上使用手套。

文本数据的基本预处理技术:

在大多数情况下,我们观察到文本数据并不完全干净。来自不同来源的数据具有不同的特征,这使得文本预处理成为分类管道中最重要的步骤之一。例如,来自 Twitter 的文本数据与 Quora 或一些新闻/博客平台上的文本数据完全不同,因此需要区别对待。有益的是,我将在这篇文章中讨论的技术对于你在 NLP 的丛林中可能遇到的任何类型的数据都足够通用。

a)清除特殊字符并删除标点符号:

我们的预处理管道在很大程度上依赖于我们将用于分类任务的 word2vec 嵌入。原则上,我们的预处理应该匹配在训练单词嵌入之前使用的预处理。由于大多数嵌入并不提供标点符号和其他特殊字符的向量值,所以您首先要做的是消除文本数据中的特殊字符。这些是 Quora 问题数据中的一些特殊字符,我们使用replace函数来去除这些特殊字符。

这也可以借助简单的正则表达式来完成。但我通常喜欢上面的做法,因为它有助于理解我们从数据中删除的字符类型。

b)清洁编号:

为什么我们要用# s 来代替数字?因为大多数嵌入都这样预处理过它们的文本。

小 Python 技巧:我们在下面的代码中使用了一个if语句来预先检查一个数字是否存在于一个文本中。因为if总是比re.sub命令快,而且我们的大部分文本不包含数字。

c)消除拼写错误:

找出数据中的拼写错误总是有帮助的。由于这些单词嵌入在 word2vec 中不存在,我们应该用正确的拼写替换单词,以获得更好的嵌入覆盖率。下面的代码工件改编自 Peter Norvig 的拼写检查器。它使用 word2vec 单词排序来近似单词概率。因为 Google word2vec 显然在训练语料库中以频率递减的顺序排列单词。你可以用它在你的数据中找出一些拼写错误的单词。

一旦我们找到了拼写错误的数据,接下来要做的就是使用拼写错误的映射和正则表达式函数来替换它们。

d)消除收缩:

缩写是我们用撇号写的单词。缩写的例子是像“不是”或“不是”这样的词。因为我们想标准化我们的文本,所以扩展这些缩写是有意义的。下面我们使用收缩映射和正则表达式函数来完成。

除了上述技术之外,还有其他文本预处理技术,如词干提取、词汇化和停用词去除。由于这些技术没有与深度学习 NLP 模型一起使用,所以我们不会讨论它们。

表示:序列创建

让深度学习成为 NLP 的 goto 选择的原因之一是,我们实际上不必从文本数据中手工设计特征。深度学习算法将一系列文本作为输入,像人类一样学习文本的结构。由于机器不能理解文字,它们希望数据是数字形式。所以我们希望将文本数据表示为一系列数字。为了理解这是如何做到的,我们需要了解一些关于 Keras Tokenizer 函数的知识。人们也可以使用任何其他记号赋予器,但 keras 记号赋予器对我来说似乎是个不错的选择。

a)记号赋予器:

简单来说,记号赋予器是一个将句子拆分成单词的实用函数。keras.preprocessing.text.Tokenizer将文本标记化(拆分)成标记(单词),同时仅保留文本语料库中最常出现的单词。

num_words 参数只在文本中保留预先指定的字数。这是有帮助的,因为我们不希望我们的模型因为考虑很少出现的单词而受到很多干扰。在真实世界的数据中,我们使用 num_words 参数留下的大多数单词通常都是拼写错误的。缺省情况下,记号赋予器还会过滤掉一些不想要的记号,并将文本转换成小写。

一旦适合于数据,记号赋予器还保持单词的索引(单词字典,我们可以使用它来为单词分配唯一的数字),它可以被记号赋予器. word_index 访问。索引词典中的单词按频率顺序排列。

所以使用 tokenizer 的完整代码如下:

其中train_Xtest_X是语料库中的文档列表。

b)填充序列:

通常,我们的模型期望每个序列(每个训练示例)具有相同的长度(相同数量的单词/标记)。我们可以使用maxlen参数对此进行控制。

例如:

现在我们的训练数据包含了一个数字列表。每个列表都有相同的长度。我们还有word_index,它是文本语料库中最常出现的单词的字典。

嵌入浓缩:

正如我所说,我将使用手套 Word2Vec 嵌入来解释丰富。手套预训练向量在维基百科语料库上训练。(你可以在这里下载它们)。这意味着一些可能出现在数据中的单词可能不会出现在嵌入中。我们该如何应对呢?让我们首先加载手套嵌入第一。

一定要把下载这些手套向量的文件夹路径放进去。这个glove_embedding_index包含什么?它只是一个字典,其中的键是单词,值是单词向量,一个长度为 300 的np.array。这部词典的长度大约是十亿。因为我们只想要我们的word_index中的单词的嵌入,我们将创建一个只包含所需嵌入的矩阵。

上面的代码运行良好,但是有没有一种方法可以让我们更好地利用 GLoVE 中的预处理?是的。当对 glove 进行预处理时,创建者没有将单词转换成小写。这意味着它包含一个单词的多个变体,如“usa”、“Usa”和“USA”。这也意味着,在某些情况下,虽然存在像“word”这样的单词,但它的小写模拟词(即“Word ”)并不存在。我们可以通过使用下面的代码来解决这个问题。

以上只是一个例子,说明了我们如何利用我们的嵌入知识来获得更好的覆盖率。有时,根据问题的不同,人们也可以通过使用一些领域知识和 NLP 技能向嵌入内容添加额外的信息来获得价值。例如,我们可以通过添加 Python 中 TextBlob 包中单词的极性和主观性,将外部知识添加到嵌入本身。

我们可以使用 TextBlob 获得任何单词的极性和主观性。相当整洁。因此,让我们尝试将这些额外的信息添加到我们的嵌入中。

工程嵌入是在后期阶段从深度学习模型获得更好性能的重要部分。通常,在项目阶段,我会多次重温这部分代码,同时尝试进一步改进我的模型。你可以在这里展示你的创造力,以提高你的word_index的覆盖率,并在你的嵌入中包含额外的特性。

更多工程特性

人们总是可以添加句子特定的特征,如句子长度、独特单词的数量等。作为向深度神经网络提供额外信息的另一个输入层。例如,我创建了这些额外的功能,作为 Quora 不真诚分类挑战的功能工程管道的一部分。

结论:

NLP 在深度学习领域仍然是一个非常有趣的问题,因此我鼓励你做大量的实验,看看什么可行,什么不可行。我试图为任何 NLP 问题的深度学习神经网络的预处理步骤提供一个完整的视角。但这并不意味着它是确定的。如果你想了解更多关于 NLP 的知识,这里有一门很棒的课程。如果你认为我们可以增加一些东西,请在评论中提及。

尾注和参考文献:

这篇文章是许多优秀的 Kagglers 们努力的结果,我将在这一部分尝试引用他们。如果我漏掉了某个人,请理解我不是故意的。

  • 如何:使用嵌入时进行预处理
  • 通过一些文本预处理提高你的分数
  • Pytorch 基线
  • Pytorch 启动器

这里的 是下一个帖子。

原载于 2019 年 1 月 17 日mlwhiz.com

传统的文本分类方法

原文:https://towardsdatascience.com/nlp-learning-series-part-2-conventional-methods-for-text-classification-40f2839dd061?source=collection_archive---------13-----------------------

NLP 学习系列(第二部分)

教机器学习文本

这是 NLP 文本分类系列的第二篇文章。给你一个回顾,最近我在 Kaggle 上开始了一个 NLP 文本分类比赛,叫做 Quora 问题不真诚挑战。我想通过一系列关于文本分类的博客文章来分享这些知识。的第一篇帖子谈到了各种与深度学习模型和一起工作的预处理技术,增加了嵌入覆盖率。在这篇文章中,我将尝试带你了解一些基本的传统模型,如 TFIDF、计数矢量器、哈希等。并尝试评估它们的性能以创建一个基线。我们将在第三篇文章中更深入地研究深度学习模型,这些模型将专注于解决文本分类问题的不同架构。我们将尝试使用我们在本次比赛中未能使用的各种其他模型,如系列文章第四篇中的 ULMFit 迁移学习方法。

作为旁注:如果你想了解更多关于 NLP 的知识,我想推荐高级机器学习专精中关于自然语言处理的这门超棒的课程。您可以免费开始 7 天的免费试用。本课程涵盖了自然语言处理中从基础到高级的各种任务:情感分析、摘要、对话状态跟踪等等。您可以免费开始 7 天的免费试用。普通

我可能需要一点时间来写完整个系列。在那之前,你也可以看看我的其他帖子:【Kagglers 正在使用什么进行文本分类,它谈论了 NLP 中使用的各种深度学习模型和如何从 Keras 切换到 Pytorch 。

所以我们再次从第一步开始:预处理。

文本数据的基本预处理技术(续)

所以在上一篇文章中,我们讨论了各种用于深度学习的文本预处理方法。传统方法的大部分预处理保持不变。我们仍然会删除特殊字符、标点符号和缩写。但是当涉及到传统方法时,我们可能也想做词干化/词汇化。让我们来谈谈它们。

出于语法原因,文档将使用不同形式的单词,如 organize、organize 和 organizing。此外,还有一系列具有相似含义的衍生相关词,如民主、民主和民主化。

由于我们将在特征创建步骤中为单词创建特征,因此有必要将单词简化为一个共同的标准,以便“组织”、“组织”和“组织”可以由单个单词“组织”来引用

a)词干

词干提取是使用粗略的启发式规则将单词转换成其基本形式的过程。例如,一个规则可以是从任何单词的末尾去掉“s”,这样“cats”就变成了“cat”。或者另一个规则是用“我”代替“ies ”,这样“ponies”就变成了“poni”。这里要注意的一个要点是,当我们对这个单词进行词干处理时,我们可能会得到一个像“poni”这样的无意义的单词。但是它仍然适用于我们的用例,因为我们计算特定单词的出现次数,而不是像传统方法那样关注这些单词的含义。出于完全相同的原因,它对深度学习不起作用。

通过在 python 中使用这个函数,我们可以非常简单地做到这一点。

b)词汇化

词汇化与词干化非常相似,但它的目的是仅当字典中存在基本形式时才删除词尾。

一旦我们完成了对文本的处理,我们的文本必然会经历以下这些步骤。

文本表示

在传统的机器学习方法中,我们应该为文本创建特征。为了实现这一目标,有很多的表现形式。让我们一个一个来说。

a)单词包—计数矢量器功能

假设我们有一系列的句子(文档)

X = [ 'This is good', 'This is bad', 'This is awesome' ]

单词包将创建一个所有句子中最常用单词的字典。对于上面的例子,字典应该是这样的:

word_index {'this':0,'is':1,'good':2,'bad':3,'awesome':4}

然后用上面的字典对句子进行编码。

This is good - [1,1,1,0,0] 
This is bad - [1,1,0,1,0] 
This is awesome - [1,1,0,0,1]

在 Python 中,我们可以通过使用 Python 中的 CountVectorizer 类非常简单地做到这一点。不用太担心名字重,它只是做了我上面解释的事情。它有许多参数,其中最重要的是:

  • ngram_range: 我在代码(1,3)中指定。这意味着在创建要素时,将考虑单字、双字和三元字。
  • min_df: 一个 ngram 应该出现在语料库中作为特征使用的最小次数。

然后,我们可以将这些特征用于任何机器学习分类模型,如逻辑回归、朴素贝叶斯、SVM 或 LightGBM。例如:

# Fitting a simple Logistic Regression on CV Feats 
clf = LogisticRegression(C=1.0) 
clf.fit(xtrain_cntv,y_train)

这里的是一个内核链接,我在 Quora 数据集上测试了这些特性。如果你喜欢,请不要忘记投赞成票。

b) TFIDF 功能

TFIDF 是一种从句子中寻找特征的简单技术。在计数特征中,我们计算文档中出现的所有单词/ngrams,而在 TFIDF 中,我们只计算重要单词的特征。我们如何做到这一点?如果你想一个语料库中的文档,我们将考虑关于该文档中任何单词的两件事:

  • 词频:这个词在文档中有多重要?

  • 逆文档频率:术语在整个语料库中的重要性如何?

TFIDF 就是这两个分数的乘积。

直观上,一个人可以理解,如果一个单词在文档中出现多次,它就是重要的。但是这就产生了一个问题。像“a”、“the”这样的词在句子中多次出现。他们的 TF 分会一直很高。我们通过使用逆文档频率来解决这个问题,如果这个词很罕见,那么它就很高,如果这个词在整个语料库中很常见,那么它就很低。

本质上,我们希望在文档中找到不常见的重要单词。

在 Python 中,我们可以通过使用 Python 中的 TFIDFVectorizer 类非常简单地做到这一点。它有许多参数,其中最重要的是:

  • ngram_range: 我在代码(1,3)中指定。这意味着在创建要素时,将考虑单字、双字和三元字。
  • min_df: 一个 ngram 应该出现在语料库中作为特征使用的最小次数。

同样,我们可以将这些特征用于任何机器学习分类模型,如逻辑回归、朴素贝叶斯、SVM 或 LightGBM。这里的是一个内核的链接,我在 Quora 数据集上尝试了这些特性。如果你喜欢,请不要忘记投赞成票。

c)散列特征

通常在一个文档语料库中会有很多元语法。我们的 tfidf 矢量器生成的特征数量超过了 2,000,000 个。这可能会在非常大的数据集上导致一个问题,因为我们必须在内存中保存一个非常大的词汇字典。解决这个问题的一个方法是使用哈希技巧。

人们可以将散列看作是将任何 ngram 映射到一个数字范围(例如 0 到 1024 之间)的单个函数。现在我们不必把语法存储在字典里。我们可以使用函数来获取任何单词的索引,而不是从字典中获取索引。

由于可能有超过 1024 个 n gram,不同的 n gram 可能映射到同一个数字,这称为冲突。我们提供的散列函数的范围越大,冲突的机会就越少。

在 Python 中,我们可以通过使用 Python 中的 HashingVectorizer 类非常简单地做到这一点。它有许多参数,其中最重要的是:

  • ngram_range: 我在代码(1,3)中指定。这意味着在创建要素时,将考虑单字、双字和三元字。
  • n_features: 你要考虑的特性的数量。上面我给的范围。

这里的是一个内核链接,我在 Quora 数据集上测试了这些特性。如果你喜欢,请不要忘记投赞成票。

d) Word2vec 功能

在之前的帖子中,我们已经谈了一些关于 word2vec 的内容。我们也可以使用单词到 vec 特征来创建句子级别的专长。我们想为句子创建一个d维向量。为此,我们将简单地对一个句子中所有单词的单词嵌入进行平均。

我们可以在 Python 中使用以下函数来实现这一点。

这里的是一个内核的链接,我在 Quora 数据集上测试了这些特性。如果你喜欢,请不要忘记投赞成票。

结果

以下是不同方法在 Kaggle 数据集上的结果。我做了一份五层简历。

这里的是代码。如果你喜欢,请不要忘记投赞成票。还要注意,我没有对模型进行调优,所以这些结果只是粗略的。您可以尝试通过使用 hyperopt 执行超参数调整或只是老式的网格搜索来获得更多性能,之后模型的性能可能会发生显著变化。

结论

虽然深度学习在 NLP 分类任务中表现得更好,但了解这些问题在过去是如何解决的仍然是有意义的,这样我们就可以了解问题的本质。我试图提供一个关于传统方法的视角,人们应该在转向深度学习方法之前也用它们进行实验来创建基线。如果你想进一步了解 NLP ,这里是一门很棒的课程。您可以免费开始 7 天的免费试用。如果你认为我可以为这个流程添加一些东西,请在评论中提及。

尾注和参考文献

这篇文章是许多优秀的 Kagglers 们努力的结果,我将在这一部分尝试引用他们。如果我漏掉了某个人,请理解我不是故意的。

  • 在 Kaggle 上逼近(几乎)任何 NLP 问题
  • 如何:使用嵌入时的预处理

这里的 是下一个帖子。

注意,CNN 和什么不适合文本分类

原文:https://towardsdatascience.com/nlp-learning-series-part-3-attention-cnn-and-what-not-for-text-classification-4313930ed566?source=collection_archive---------2-----------------------

NLP 学习系列(第三部分)

让机器为我们阅读

Photo by Francesco Ungaro on Unsplash

T 他的帖子是 NLP 文本分类系列的第三个帖子。给你一个回顾,我在 Kaggle 上开始了一个 NLP 文本分类竞赛,叫做 Quora 问题不真诚挑战。所以我想通过一系列关于文本分类的博文来分享这些知识。第一篇帖子谈到了与深度学习模型和一起工作的不同的预处理技术,增加了嵌入覆盖面。在第二篇中,我讲述了一些基本的常规模型如 TFIDF、计数矢量器、哈希等。已经被用于文本分类并试图评估它们的性能来创建基线。在这篇文章中,我深入研究了深度学习模型和我们可以用来解决文本分类问题的各种架构。为了使这个帖子平台通用,我打算用 Keras 和 Pytorch 来编码。我将使用我们在本次比赛中未能使用的各种其他模型,如系列中第四篇文章中的 ULMFit 迁移学习方法。

另外,如果你对在工作中使用的定制深度学习工作站或服务器感兴趣,Exxact Corporation 有一系列基于人工智能的解决方案,起价为 3700 美元,带有几个英伟达 RTX 30 系列 GPU,3 年保修和深度学习软件堆栈。

因此,让我试着介绍一下人们用来进行文本分类的一些模型,并试着为他们提供一个简单的直觉——还有,Keras 和 Pytorch 中的一些代码。所以你可以自己尝试一下。

1.TextCNN

Yoon Kim 在论文卷积神经网络用于句子分类中首次提出了使用 CNN 对文本进行分类的想法。

表象:这个想法的核心直觉是将我们的文档视为图像。怎么会?假设我们有一个句子,maxlen = 70,嵌入大小= 300。我们可以创建一个形状为 70x300 的数字矩阵来表示这句话。对于图像,我们也有一个矩阵,其中各个元素是像素值。任务的输入不是图像像素,而是用矩阵表示的句子或文档。矩阵的每一行对应一个单词向量。

卷积思想:对于图像,我们水平和垂直移动我们的 conv 过滤器,对于文本,我们将内核大小固定为 filter_size x embed_size,即(3,300),我们将垂直向下移动进行卷积,同时查看三个单词,因为在这种情况下我们的过滤器大小为 3。这个想法似乎是正确的,因为我们的卷积滤波器不分裂字嵌入。它会查看每个单词的完整嵌入。人们也可以把过滤器的大小想象成一元、二元、三元等。因为我们正在分别查看 1、2、3 和 5 个单词的上下文窗口。

下面是用 Pytorch 编码的文本分类网络:

对于 Keras 爱好者来说:

我是 Kaggle Kernels 的忠实粉丝。人们无法想象免费拥有所有这些计算机。你可以在这个 kaggle 内核中找到上面两个代码片段的运行版本。在分叉和运行代码之后,一定要尝试使用它。如果你觉得有帮助,也请投票支持内核。

keras 模型和 Pytorch 模型表现相似,Pytorch 模型以微弱优势击败 Keras 模型。Pytorch 模型的折外 CV F1 分数为 0.6609,而 Keras 模型的相同分数为 0.6559。我在两个模型中使用了相同的预处理,以便更好地比较平台。

2.双向 RNN(LSTM/GRU):

TextCNN 很适合文本分类。它在近距离内处理单词。它可以一起看《纽约》。然而,它仍然不能处理特定文本序列中提供的所有上下文。它仍然不知道数据的顺序结构,其中每个单词都依赖于前一个单词。还是前一句的一句话。

RNN 会帮我们的。他们可以使用隐藏状态记住以前的信息,并将其与当前任务联系起来。

长短期记忆网络(LSTM)是 RNN 的一个子类,专门用于长时间记忆信息。此外,双向 LSTM 保持了两个方向上的上下文信息,这在文本分类任务中非常有用(但是对于时间序列预测任务不起作用,因为在这种情况下我们不知道未来)。

对双向 RNN 最简单的解释是,把 RNN 单元想象成一个黑盒,接受一个隐藏状态(向量)和一个字向量作为输入,给出一个输出向量和下一个隐藏状态。这个盒子具有一些权重,这些权重将使用损耗的反向传播来调整。此外,相同的单元格应用于所有单词,以便句子中的单词共享权重。这种现象被称为重量共享。

Hidden state, Word vector ->(RNN Cell) -> Output Vector , Next Hidden state

对于长度为 4 的序列,如“你永远也不会相信”,RNN 单元给出 4 个输出向量,这些向量可以连接起来,然后用作密集前馈架构的一部分。

在双向 RNN 中,唯一的变化是我们以通常的方式以及相反的方式阅读文本。因此,我们并行堆叠两个 rnn,因此我们可以追加 8 个输出向量。

一旦我们得到了输出向量,我们就将它们发送通过一系列密集层,最后通过 softmax 层来构建文本分类器。

在大多数情况下,您需要了解如何在神经网络中堆叠一些层以获得最佳结果。如果性能更好,我们可以在网络中尝试多个双向 GRU/LSTM 层。

由于 RNNs 的局限性,如不能记住长期依赖关系,在实践中,我们几乎总是使用 LSTM/GRU 来建模长期依赖关系。在这种情况下,你可以把上图中的 RNN 单元想象成 LSTM 单元或 GRU 单元。下面提供了一个示例模型。在构建模型时,可以将 CuDNNGRU 与 CuDNNLSTM 互换使用。(CuDNNGRU/LSTM 只是 LSTM/GRU 的实现,创建它们是为了在 GPU 上运行得更快。在大多数情况下,总是使用它们而不是普通的 LSTM/GRU 实现)

这是 Pytorch 中这个网络的一些代码。

此外,这里是相同的代码在 Keras。

你可以用 Pytorch 和 Keras kaggle 内核在我的 BiLSTM 中运行这段代码。如果你觉得有帮助,请投票支持内核。

同样,在 BiLSTM 案例中,Pytorch 模型以微弱优势击败了 keras 模型。Pytorch 模型的折外 CV F1 分数为 0.6741,而 Keras 模型的相同分数为 0.6727。这个分数比 TextCNN 的表现提高了大约 1-2 %, text CNN 的表现相当不错。另外,请注意,它比传统方法大约好 6–7%。

3.注意力模型

Dzmitry Bahdanau 等人在他们的论文中首次通过联合学习对齐和翻译提出了注意力的神经机器翻译,但我发现 CMU 和微软在 2016 年联合撰写的关于文档分类的层次注意力网络的论文更容易阅读,并提供了更多的直觉。

所以让我们先谈谈直觉。过去的传统方法如 TFIDF/CountVectorizer 等。我们过去常常通过提取关键词来从文本中寻找特征。有些词比其他词更有助于确定文本的类别。然而,在这种方法中,我们丢失了文本的顺序结构。使用 LSTM 和深度学习方法,虽然我们可以照顾序列结构,但我们失去了对更重要的单词给予更高权重的能力。我们能两全其美吗?

答案是肯定的。实际上,注意力是你所需要的全部。用作者的话说:

不是所有的单词都对句子意思的表达有同等的贡献。因此,我们引入注意机制来提取对句子意义重要的词,并聚合这些信息词的表示以形成句子向量

本质上,我们希望为文本中的每个单词创建分数,这就是一个单词的注意力相似度分数。

为此,我们从权重矩阵(W)、偏差向量(b)和上下文向量 u 开始。优化算法学习所有这些权重。在这一点上,我想强调我非常喜欢神经网络的一点——如果你不知道一些参数,让网络学习它们。我们只需要担心如何创建要调优的架构和参数。

然后就是一系列的数学运算。请参见图中的详细说明。我们可以将 u1 视为 RNN 字输出的非线性。之后,v1 是 u1 与上下文向量 u 的点积,u 的乘幂。从直觉的角度来看,如果 u 和 u1 相似,v1 的值将会很高。因为我们希望分数的总和为 1,所以我们用 v 除以 v 的总和来得到最终分数 s

然后,这些最终得分乘以 RNN 单词输出,根据单词的重要性对其进行加权。然后将输出相加,并通过密集层和 softmax 发送,用于文本分类任务。

下面是 Pytorch 中的代码。务必通读 pytorch 关注层代码。它只是做我上面解释的事情。

Keras 的代码也一样。

同样,我对 Pytorch 和 Keras Kaggle 内核的关注包含了这段代码的工作版本。如果你觉得内核有用,请投票支持它。

该方法表现良好,Pytorch CV 分数达到约 0.6758,Keras CV 分数达到约 0.678。这个成绩超过了我们通过 BiLSTM 和 TextCNN 所能达到的。但是,请注意,我们还没有对任何给定的方法进行调优,因此分数可能会有所不同。

至此,我让您尝试新的架构,并尝试堆叠多个 GRU/LSTM 层来提高您的网络性能。你也可以考虑在这些网络中加入更多的技术,比如木桶,手工制作等。我的博客中提到了一些技巧和新技术:我的第一枚银牌在文本分类和 Kaggle 方面教会了我什么?。另外,这是另一个 Kaggle 内核,它是我在这次比赛中获得银牌的参赛作品。

结果

以下是我在 Kaggle 数据集上尝试的所有不同方法的最终结果。我做了一份五层简历。

a.常规方法:

b.深度学习方法:

PS: 注意,我并没有对上述模型进行调优,所以这些结果只是粗略的。您可以尝试通过使用 hyperopt 或老式的网格搜索来执行超参数调整来获得更高的性能。

结论

在这篇文章中,我解释了人们用于文本分类任务的各种深度学习架构。在下一篇文章中,我们将进一步探究 NLP 空间中的下一个新现象 BERT 和 ULMFit 凭借他们的直觉进行迁移学习。在媒体上关注我,或者订阅我的博客来了解我的下一篇文章。

另外,如果你想了解更多关于 NLP 的知识,这里的是一门很好的课程。您可以免费开始 7 天的免费试用。

让我知道,如果你认为我可以添加更多的东西;我会试着融入它。

干杯!!!

这里的 是下一个帖子。

原载于 2019 年 3 月 9 日mlwhiz.com

用于文本分类的迁移学习直觉

原文:https://towardsdatascience.com/nlp-learning-series-part-4-transfer-learning-intuition-for-text-classification-4eb90495c19f?source=collection_archive---------11-----------------------

NLP 学习系列(第四部分)

让机器为我们阅读

这篇文章是 NLP 文本分类系列的第四篇文章。给你一个回顾,我在 Kaggle 上开始了一个 NLP 文本分类竞赛,叫做 Quora 问题不真诚挑战。所以我想通过一系列关于文本分类的博文来分享这些知识。的第一篇帖子谈到了不同的预处理技术,这些技术与深度学习模型一起工作,增加了嵌入覆盖率。在第二篇中,我讲述了一些基本的常规模型如 TFIDF、计数矢量器、哈希等。已经被用于文本分类并试图评估它们的性能来创建基线。在第三篇文章中,我深入研究了深度学习模型和我们可以用来解决文本分类问题的各种架构。在这篇文章中,我将尝试使用 ULMFit 模型,这是一种用于 NLP 的迁移学习方法。

作为旁注:如果你想了解更多关于 NLP 的知识,我想推荐高级机器学习专精中自然语言处理的这门优秀课程。您可以免费开始 7 天的免费试用。本课程涵盖了自然语言处理中从基础到高级的各种任务:情感分析、摘要、对话状态跟踪等等。您可以免费开始 7 天的免费试用。

在将迁移学习的概念引入 NLP 应用程序之前,我们首先需要了解一点语言模型。

语言模型和 NLP 迁移学习直觉;

用最基本的术语来说,语言模型的目标是在给定一串输入单词的情况下预测下一个单词。过去,许多不同的方法被用来解决这个特殊的问题。使用马尔可夫假设的概率模型就是这种模型的一个例子。

在最近的时代,人们已经使用 RNNs/LSTMs 来创建这样的语言模型。它们将单词嵌入作为输入,并在每个时间状态返回字典单词上下一个单词概率的概率分布。下面显示了这样的一个例子,其中下面的神经网络使用多层堆叠的 RNN 细胞来学习语言模型以预测下一个单词。

现在,我们为什么需要语言建模的概念?或者预测下一个单词如何与当前的文本分类任务联系起来?直觉与神经网络的训练方式有关。在维基百科这样的大规模语料库上训练后,可以预测下一个单词的神经网络已经学习了特定语言的大量结构。我们能在网络的权重中使用这些知识来为我们带来优势吗?是的,我们可以,这也是 NLP 中迁移学习思想的来源。为了让这种直觉更具体,让我们认为我们的神经网络分为两部分-

  • 语言特定:神经网络的下半部分是语言特定的。也就是说学习语言的特征。这一部分可以用来将我们从语言语料库中获得的知识转移到我们当前的任务中
  • 特定于任务的:我将我们网络的上部称为特定于任务的。训练这些层中的权重,以便它学习预测下一个单词。

现在,随着它进入许多图像的迁移学习模型,我们将语言特定部分与一些密集和 softmax 层堆叠在一起(我们的新任务),并在我们的新任务上进行训练,以实现我们想要做的事情。

ULMFit:

现在,NLP 中迁移学习的概念并不是全新的,早在 2015-16 年,人们就已经使用语言模型进行迁移学习,但效果不佳。那么现在发生了什么变化?

发生变化的是,像杰瑞米·霍华德和塞巴斯蒂安·鲁德这样的人已经就如何训练这些网络做了大量的研究。因此,我们已经用迁移学习方法在许多文本数据集上取得了最先进的结果。

让我们跟随他们写的 ULMFit 论文中的关键研究发现和代码一起跟进。

迁移学习网络训练方式的改变:

为了按照 ULMFiT 训练模型,我们需要采取以下三个步骤:

a) 创建基本语言模型:在捕获高级自然语言特征的通用领域语料库上训练语言模型
b) 在任务特定数据上微调基本语言模型:在目标任务数据上微调预训练的语言模型
c) 在任务特定数据上微调基本语言模型层+任务特定层:在目标任务数据上微调分类器

因此,让我们按照 FastAI 库提供给我们的代码,一个接一个地完成这三个步骤。

a)创建基础语言模型:

这项任务可能是最耗时的任务。这个模型类似于视觉任务的 resnet50 或 Inception。在论文中,他们使用了语言模型 AWD-LSTM,这是一种常规的 LSTM 架构,通过各种调整的压差超参数进行训练。该模型在 Wikitext-103 上进行训练,Wikitext-103 由 28,595 篇预处理的维基百科文章和 1.03 亿个单词组成。我们不会自己执行这个任务,将使用令人难以置信的 FastAI 库来使用这个模型,如下所示。以下代码将获取我们的数据并对其进行预处理,以便在 AWD_LSTM 模型中使用,同时加载该模型。

这也是我们根据 FastAI 模型所需的用法对数据进行预处理的地方。例如:

print(train_df)

print(data_lm)
--------------------------------------------------------------------TextLMDataBunch;

Train: LabelList (1306122 items)
x: LMTextList
xxbos xxmaj how did xxmaj quebec nationalists see their province as a nation in the 1960s ?,xxbos xxmaj do you have an adopted dog , how would you encourage people to adopt and not shop ?,xxbos xxmaj why does velocity affect time ? xxmaj does velocity affect space geometry ?,xxbos xxmaj how did xxmaj otto von xxmaj guericke used the xxmaj magdeburg hemispheres ?,xxbos xxmaj can i convert montra xxunk d to a mountain bike by just changing the tyres ?
y: LMLabelList
,,,,
Path: .;

Valid: LabelList (375806 items)
x: LMTextList
xxbos xxmaj why do so many women become so rude and arrogant when they get just a little bit of wealth and power ?,xxbos xxmaj when should i apply for xxup rv college of engineering and xxup bms college of engineering ? xxmaj should i wait for the xxup comedk result or am i supposed to apply before the result ?,xxbos xxmaj what is it really like to be a nurse practitioner ?,xxbos xxmaj who are entrepreneurs ?,xxbos xxmaj is education really making good people nowadays ?
y: LMLabelList
,,,,
Path: .;

Test: None

标记化的准备数据基于 FastAI 开发人员的大量研究。为了让这篇文章更完整,我也分享了一些令牌定义

  • xxunk 代表未知单词(当前词汇表中没有的单词)
  • xxpad 是用于填充的标记,如果我们需要将几个不同长度的文本成批重组的话
  • xxbos 表示数据集中文本的开始
  • xxmaj 用于表示原文中下一个单词以大写字母开头
  • xxup 用于表示原文中的下一个单词全部大写

b)根据任务特定数据微调基本语言模型

当我们看代码时,这个任务也很简单。我们如何进行培训的具体细节才是最重要的。

本文介绍了这一学习阶段的两个一般概念:

  • 区别性微调:

主要思想是:由于不同的层捕捉不同类型的信息,所以要对它们进行不同程度的微调。区别微调允许我们以不同的学习速率调整每一层,而不是对模型的所有层使用相同的学习速率。在论文中,作者建议首先只微调最后一层,然后以 2.6 的因子降低学习速率来解冻所有层。

  • 倾斜三角形学习率:

根据作者的说法:“为了使其参数适应特定任务的特征,我们希望模型在训练开始时快速收敛到参数空间的合适区域,然后优化其参数”

的主要思想是在开始阶段使用高学习率来增加学习,在时期的后期阶段使用低学习率来微调。

在 Quora 数据集上训练我们的语言模型之后,我们应该能够看到我们的模型在语言模型任务本身上的表现。FastAI 库为我们提供了一个简单的函数。

# check how the language model performs 
learn.predict("What should", n_words=10)
---------------------------------------------------------------
'What should be the likelihood of a tourist visiting Mumbai for'

c)在任务特定数据上微调基本语言模型层+任务特定层

这是特定任务学习发生的阶段,即我们添加分类层并微调它们以执行我们当前的文本分类任务。

作者用两个额外的线性块扩充了预训练的语言模型。每个块使用批量归一化和丢弃,中间层使用 ReLU 激活,最后一层使用 softmax 激活输出目标类的概率分布。这些任务特定层的参数是唯一从零开始学习的参数。

在这里,作者还推导出一些新颖的方法:

  • 串联池:

作者不仅使用所有隐藏状态的连接,而且使用所有隐藏状态的最大池和平均池表示作为线性层的输入。

  • 逐步解冻:

作者建议从最后一层开始逐渐解冻模型,因为这一层包含最少的一般知识,而不是一次微调所有层,这将冒着灾难性遗忘(忘记我们迄今为止从语言模型中学到的一切)的风险。作者首先解冻最后一层,并微调所有解冻层一个历元。然后,他们解冻下一个较低的冻结层,并重复,直到他们微调所有层,直到在最后一次迭代收敛。函数slice(2e-3/100, 2e-3)意味着我们用从最大值到最小值的不同学习率来训练每一层。

人们可以使用以下公式立即得到试验数据的预测值:

test_preds = np.array(learn.get_preds(DatasetType.Test, ordered=True)[0])[:,1]

我是 Kaggle Kernels 的忠实粉丝。人们无法想象免费拥有所有这些计算机。 你可以在这个 kaggle 内核 中找到上面代码的运行版本。在分叉和运行代码之后,一定要尝试使用它。如果你觉得有帮助,也请投票支持内核。

结果:

以下是我在 Kaggle 数据集上尝试的所有不同方法的最终结果。我做了一份五层简历。

a.常规方法:

b.深度学习方法:

c.迁移学习方法(ULMFIT):

与深度学习方法相比,取得的结果不是很好,但我仍然喜欢迁移学习方法的想法,并且使用 fastAI 实现它非常容易。此外,运行代码花费了 9 个小时,而其他方法需要 2 个小时。

即使这种方法不适用于该数据集,但它对其他数据集来说是一种有效的方法,因为该论文的作者在不同的数据集上取得了相当好的结果——这绝对是一种值得尝试的真正方法。

PS: 注意,我没有对上述模型进行调优,所以这些结果只是粗略的。你可以尝试通过使用 hyperopt 或老式的网格搜索来执行超参数调整来获得更高的性能。

结论:

最后,这篇文章总结了我的 NLP 学习系列。写这篇文章花了很多时间,但这种努力是值得的。我希望它对你的工作有所帮助。当我有时间的时候,我会试着写一些关于这个话题的文章。Medium关注我,或者订阅我的博客以了解我的下一篇文章。

另外,如果你想进一步了解 NLP,这里有一门很好的课程。您可以免费开始 7 天的免费试用。

让我知道,如果你认为我可以添加更多的东西;我会试着融入它。

干杯!!!

原载于 2019 年 3 月 30 日 mlwhiz.com**T21

基于 2019 年爱丁堡边缘数据的 NLP

原文:https://towardsdatascience.com/nlp-on-edinburgh-fringe-2019-data-aa71dca818b4?source=collection_archive---------27-----------------------

对爱丁堡边缘事件的网页抓取和文本分析

在这篇文章中,我们深入到基本的刮网站,清理文本数据,和自然语言处理(NLP)。我把这个项目的背景建立在爱丁堡边缘艺术节上,这是世界上最大的艺术节,目前正在 8 月 2 日到 26 日之间举行。

从网页抓取获取 Python 中的数据

为了便于分析,我想获取有关条纹节期间发生的所有事件的文本。此文本数据位于多个网页中,手动提取会花费很长时间。

Python 库请求就是在这里帮助我们的,因为它可以用来对特定的网页进行 HTTP 请求。从作出 HTTP 请求的响应中,可以获得网站文本数据。然而,这个文本数据是一个很大的文本卷轴,在这里实现了库beauty lump来解析从网页得到的返回 HTML,这样我们就可以高效地只提取我们想要的内容。

下面的代码片段演示了如何向网页发出请求,并通过 BeautifulSoup 解析响应:

import requests
from bs4 import BeautifulSoup# URL to query
url = '[https://url_to_query'](https://url_to_query')# Scrape html from the URL
response = requests.get(url)# Use html parser on webpage text
soup = BeautifulSoup(response.text, 'html.parser')

在返回的变量 soup 中,我们可以使用诸如soup . find _ all(‘,CLASS _ =‘CLASS _ NAME’)之类的命令来搜索 HTML 中的特定类。使用这种方法,我获得了 5,254 个节日事件的数据,包括事件名称字段、事件的简短描述、票价和正在执行的演出数量。

探索边缘数据

获得数据集之后,下一步通常是探索你所拥有的。我很想知道这些活动的票价分布情况。此数据的受限视图如下所示:

Distribution of events by ticket price (view limited to cost up to £60)

从图表中,我们可以看到,超过 25%的活动是免费参加的,其中 5-20 持有很大一部分的分布。对数据进行更深入的分析后发现,这些节目的成本超过 60 英镑,其中大多数都是技术大师班或食品/饮料品尝会。我真正感兴趣的是节目类型,为此我们需要开始处理文本数据。

清洁

在数据科学项目中使用文本时,数据在传递给我们要应用的任何模型之前,几乎总是需要某种程度的清理。利用这些数据,我将事件名称和描述文本组合到一个名为df[“text”]的字段中。下面的代码显示了为清理文本而采取的一些步骤:

import string
import pandas

def remove_punctuation(s):
 s = ‘’.join([i for i in s if i not in frozenset((string.punctuation))])
 return s# Transform the text to lowercase
df[‘text’] = df[‘text’].str.lower()# Remove the newline characters
df[‘text’] = df[‘text’].replace(‘\n’,’ ‘, regex=True)# Remove punctuation
df[‘text’] = df[‘text’].apply(remove_punctuation)

词汇袋(BOW)

现在,数据帧中的每一行都包含一个经过清理的文本数据字段,我们可以继续检查它背后的语言。一种更简单的方法叫做单词包(BOW ),它创建了一个包含数据中出现的所有独特单词的词汇表。我们可以使用从 sklearn 引入的计数矢量器来完成这项工作。作为设置矢量器的一部分,我们包含了参数stop words =‘English’,,它从数据集中删除常见的单词,例如 the,and,of,to,in,等。以下代码对我们的文本执行此操作:

from sklearn.feature_extraction.text import CountVectorizer

# Initialise our CountVectorizer object
vectorizer = CountVectorizer(analyzer=”word”, tokenizer=None, preprocessor=None, stop_words='english')

# fit_transform fits our data and learns the vocabulary whilst transforming the data into feature vectors
word_bag = vectorizer.fit_transform(df.text)

# print the shape of our feature matrix
word_bag.shape

最后一行打印了我们创建的矩阵的形状,在本例中,它的形状为(5254,26,869)。这是我们语料库中所有单词的稀疏矩阵,以及它们在每个提供的句子中的出现。这个矩阵的一个好处是它可以显示我们数据集中最常见的单词;以下代码片段显示了如何操作:

# Get and display the top 10 most frequent words
freqs = [(word, word_bag.getcol(idx).sum()) for word, idx in vectorizer.vocabulary_.items()]
freqs_sort = sorted(freqs, key = lambda x: -x[1])
for i in freqs_sort[:10]:
    print(i)

根据边缘数据,我们的数据中出现频率最高的前十个词是:

('comedy', 1411)
('fringe', 1293)
('new', 927)
('theatre', 852)
('edinburgh', 741)
('world', 651)
('life', 612)
('festival', 561)
('music', 557)
('join', 534)

这是意料之中的,并没有告诉我们太多的深度。让我们试着绘制事件之间的联系。

TF-IDF 和余弦相似性

当在 NLP 中工作时,我们通常旨在通过查看组成文本的单词来理解特定的文本字符串是关于什么的。衡量一个单词有多重要的一个标准是它的词频。这是一个单词在文档中出现的频率。但是,有些词可以出现很多次,但可能并不重要;其中一些是已经被删除的停用词。

我们可以采取的另一种方法是查看一个术语的逆文档频率 (IDF),它减少了常用词的权重,增加了在文档集合中不经常使用的词的权重。我们可以把 TF 和 IDF 结合起来(TF-IDF)。TF-IDF 是一种用于强调在给定观察中频繁出现的单词,同时不强调在许多观察中频繁出现的单词的方法。这种技术在确定哪些单词将成为好的特征方面非常有用。对于这个项目,我们将使用来自 scikit-learn 的 TF-IDF 矢量器。我们可以使用以下代码使我们的文本适合 TF-IDF 模型:

from sklearn.feature_extraction.text import TfidfVectorizer as TFIV

vctr = TFIV(min_df=2,
 max_features=None,
 strip_accents=’unicode’,
 analyzer=’word’,
 token_pattern=r’\w{1,}’,
 ngram_range=(1, 2),
 use_idf=True,
 smooth_idf=1,
 sublinear_tf=1,
 stop_words = ‘english’)

X = vctr.fit_transform(df.text)

从矩阵 X 中,我们可以以单词向量的形式理解每个事件的文本。为了找到相似的事件,我们将使用一种叫做余弦相似度的方法,我们也可以从 sklearn 导入这种方法。下面的代码片段演示了如何对单个事件(X[5])执行此操作,输出显示了最相关的事件及其相似性得分(得分为 1 表示相同的文本)。

from sklearn.metrics.pairwise import linear_kernelcosine_similarities = linear_kernel(X[5], X).flatten()
related_docs_indices = cosine_similarities.argsort()[:-5:-1]
cos = cosine_similarities[related_docs_indices]print(related_docs_indices)
print(cos)[5  33         696        1041      ]
[1\. 0.60378536 0.18632652 0.14713335]

对所有事件重复这一过程会创建所有事件以及相似事件如何联系在一起的地图。

Gephi network graph showing cosine similarities >0.2 for all events, coloured by LDA topic

关于上面的网络图,有趣的是大量的事件与网络中的其他事件没有关系。这些分散在网络的边缘,突出了边缘艺术节上展示的原创程度。在中间,我们可以看到一些事件之间高度重叠的集群。在项目的最后阶段,我们对这些集群进行建模,并尝试为它们分配主题。

主题建模

潜在狄利克雷分配(LDA)是一种基于词频生成主题的模型。我们在这里使用它来寻找我们的边缘数据中关于正在发生的事件类型的特定主题。下面的代码显示了如何开始使用这种方法:

from sklearn.decomposition import LatentDirichletAllocationvectorizer = CountVectorizer(analyzer="word",
                             min_df=20,
                             token_pattern=r'\w{1,}',
                             ngram_range=(2, 4),
                             preprocessor=None,
                             stop_words='english')

word_bag = vectorizer.fit_transform(df.text)lda = LatentDirichletAllocation(n_topics=25,
   max_iter=50,
   learning_method=’online’,
   learning_offset=40.,
   random_state=0).fit(word_bag)names = vectorizer_stop.get_feature_names()for topic_idx, topic in enumerate(lda.components_):
    print("Topic %d:" % (topic_idx))
    print(" ".join([names[i]
                    for i in topic.argsort()[:-5 - 1:-1]]))

上面的代码只是运行 LDA 模型并打印输出主题和最重要的单词的一个例子。根据 LDA 的输出,我使用主坐标分析来创建我们主题的 2D 投影:

Topic modelling from LDA method

能够通过运行 LDA 来绘制主题对于观察主题重叠的地方和调整模型非常有用。它还提供了一种方法来理解节日期间发生的不同类型的事件,如音乐、喜剧、诗歌、舞蹈和写作。

结束语

我们的分析表明,有了 NLP 方法和技术的基础,我们可以询问一个小的文本数据集来获得洞察力。尽管 BoW 模型很简单,但它可以快速查看文本中出现的单词数量和主要使用的单词,尽管对于我们的数据来说,像“喜剧”、“边缘”和“爱丁堡”这样的单词是最常见的,这并不令人惊讶。

在此基础上,TF-IDF 提供了一种开始考虑句子而不是单词的方法,增加了余弦相似性,提供了一种开始分组观察的方法。这向我们展示了原始事件的范围,在其他事件之间很少出现共同的文本。

最后,使用 LDA,我们让我们的模型产生主题,其中事件组被分配给一个主题。这使我们能够衡量整个节日期间发生的主要事件类型。

NLP 还有其他几种方法值得研究。作为项目的一部分,我还使用了 Word2Vec 和 TSNE;然而,这些研究的结果还没有公布。

NLP 第 3 部分|文本数据的探索性数据分析

原文:https://towardsdatascience.com/nlp-part-3-exploratory-data-analysis-of-text-data-1caa8ab3f79d?source=collection_archive---------3-----------------------

让我们从员工评估中收集一些见解

Photo by Luke Chesser on Unsplash

这是关于使用 python 的 NLP 的三部分系列的继续。请随意查看我的其他文章。(第一部分,第二部分)

让我们更好地理解我们新清理的数据集。
探索性数据分析(EDA)是数据分析师熟悉他们的数据以推动直觉并开始制定可测试假设的过程。这个过程通常利用描述性统计和可视化。

像往常一样,让我们从导入必要的库并打开数据集开始。

import pandas as pd
import numpy as np
import nltk
import pickle
import pyLDAvis.sklearn
from collections import Counter
from textblob import TextBlob
from nltk.tokenize import word_tokenize
from nltk.probability import FreqDist
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.decomposition import LatentDirichletAllocation, NMF
from wordcloud import WordCloud, ImageColorGenerator
import matplotlib.pyplot as plt
import seaborn as sns%matplotlib inline
pd.options.mode.chained_assignment = None
pd.set_option('display.max_colwidth', 100)with open('indeed_scrape_clean.pkl', 'rb') as pickle_file:
    df = pickle.load(pickle_file)

如果您还记得我们以前的教程,我们经历了一系列预处理步骤来清理和准备我们的数据进行分析。我们的最终数据集包含许多列,但最后一列“lemmatized”包含我们最终清理的单词列表。我们将覆盖现有的数据框架,因为我们只对“rating”和“lemmatized”列感兴趣。

df = df[['rating', 'lemmatized']]
df.head()

情感分析

情感分析是确定作者的态度或观点的过程,其范围从-1(消极态度)到 1(积极态度)。我们将使用 TextBlob 库来分析情感。TextBlob 的情绪()函数需要一个字符串,但我们的“lemmatized”列当前是一个列表。让我们把列表转换成一个字符串。

df['lemma_str'] = [' '.join(map(str,l)) for l in df['lemmatized']]
df.head()

现在我们可以将“lemma_str”列传递到情感()函数中来计算情感。因为我们有“评级”栏,我们可以验证情感分析能够多好地确定作者的态度。也就是说,我们确实看到了明显的错误,因为评级#5 的评级为 5,但情绪相当低。

df['sentiment'] = df['lemma_str'].apply(lambda x: TextBlob(x).sentiment.polarity)
df.head()

当比较我们的情绪直方图时,我们可以看到,我们得出的绝大多数情绪评级都是非常积极的。当我们将其与“评级”栏进行比较时,我们可以看到类似的模式出现。我们不仅对情绪分析的准确性感到满意,而且可以看到员工对公司的整体态度非常积极。难怪谷歌经常被列入福布斯最佳工作场所名单。

plt.figure(figsize=(50,30))
plt.margins(0.02)
plt.xlabel('Sentiment', fontsize=50)
plt.xticks(fontsize=40)
plt.ylabel('Frequency', fontsize=50)
plt.yticks(fontsize=40)
plt.hist(df['sentiment'], bins=50)
plt.title('Sentiment Distribution', fontsize=60)
plt.show()

x_rating = df.rating.value_counts()
y_rating = x_rating.sort_index()
plt.figure(figsize=(50,30))
sns.barplot(x_rating.index, x_rating.values, alpha=0.8)
plt.title("Rating Distribution", fontsize=50)
plt.ylabel('Frequency', fontsize=50)
plt.yticks(fontsize=40)
plt.xlabel('Employee Ratings', fontsize=50)
plt.xticks(fontsize=40)

plt.figure(figsize=(30,10))
plt.title('Percentage of Ratings', fontsize=20)
df.rating.value_counts().plot(kind='pie', labels=['Rating5', 'Rating4', 'Rating3', 'Rating2', 'Rating1'],
                              wedgeprops=dict(width=.7), autopct='%1.0f%%', startangle= -20, 
                              textprops={'fontsize': 15})

polarity_avg = df.groupby('rating')['sentiment'].mean().plot(kind='bar', figsize=(50,30))
plt.xlabel('Rating', fontsize=45)
plt.ylabel('Average Sentiment', fontsize=45)
plt.xticks(fontsize=40)
plt.yticks(fontsize=40)
plt.title('Average Sentiment per Rating Distribution', fontsize=50)
plt.show()

让我们创建两个额外的特性“word_count”来确定每次评论的字数,创建“review_len”来确定每次评论的字数。

df['word_count'] = df['lemmatized'].apply(lambda x: len(str(x).split()))df['review_len'] = df['lemma_str'].astype(str).apply(len)

虽然差异并不大,但基于字母和单词计数的最长评论似乎是负面和中性的。似乎心怀不满的员工通常会在他们的评估中提供更多细节。这种结果并不少见,因为人类倾向于抱怨细节,而赞美简短。这可以通过检查下面的相关矩阵来进一步确认。评分和情绪都与“review_len”和“word_count”负相关。这可以解释相反的关系,因为每次评论的字母和单词数增加了总体评分,而情绪下降了。然而,相关性再次相当小,然而是负的。

letter_avg = df.groupby('rating')['review_len'].mean().plot(kind='bar', figsize=(50,30))
plt.xlabel('Rating', fontsize=35)
plt.ylabel('Count of Letters in Rating', fontsize=35)
plt.xticks(fontsize=40)
plt.yticks(fontsize=40)
plt.title('Average Number of Letters per Rating Distribution', fontsize=40)
plt.show()

word_avg = df.groupby('rating')['word_count'].mean().plot(kind='bar', figsize=(50,30))
plt.xlabel('Rating', fontsize=35)
plt.ylabel('Count of Words in Rating', fontsize=35)
plt.xticks(fontsize=40)
plt.yticks(fontsize=40)
plt.title('Average Number of Words per Rating Distribution', fontsize=40)
plt.show()

correlation = df[['rating','sentiment', 'review_len', 'word_count']].corr()
mask = np.zeros_like(correlation, dtype=np.bool)
mask[np.triu_indices_from(mask)] = True
plt.figure(figsize=(50,30))
plt.xticks(fontsize=40)
plt.yticks(fontsize=40)
sns.heatmap(correlation, cmap='coolwarm', annot=True, annot_kws={"size": 40}, linewidths=10, vmin=-1.5, mask=mask)

词频分析

让我们深入看看实际的评论本身。最常见的词是什么?按评分最常见的词有哪些?对这些问题的回答将为谷歌员工的观点提供进一步的见解。

NLTK 有一个很棒的名为“FreqDist”的库,它允许我们确定语料库中最常见术语的数量。首先,我们需要将我们单独的标记化评论列表转换成一个综合的可重复标记列表,将所有评论存储在一起。最后,我们向 FreqDist()传递“allwords”对象,并应用“most_common(100)”函数来获取 100 个最常见的单词。

words = df['lemmatized']
allwords = []
for wordlist in words:
    allwords += wordlistprint(allwords)

mostcommon = FreqDist(allwords).most_common(100)wordcloud = WordCloud(width=1600, height=800, background_color='white').generate(str(mostcommon))
fig = plt.figure(figsize=(30,10), facecolor='white')
plt.imshow(wordcloud, interpolation="bilinear")
plt.axis('off')
plt.title('Top 100 Most Common Words', fontsize=100)plt.tight_layout(pad=0)
plt.show()

mostcommon_small = FreqDist(allwords).most_common(25)
x, y = zip(*mostcommon_small)plt.figure(figsize=(50,30))
plt.margins(0.02)
plt.bar(x, y)
plt.xlabel('Words', fontsize=50)
plt.ylabel('Frequency of Words', fontsize=50)
plt.yticks(fontsize=40)
plt.xticks(rotation=60, fontsize=40)
plt.title('Frequency of 25 Most Common Words', fontsize=60)
plt.show()

词频分析的结果肯定支持评论的总体积极情绪。诸如“伟大”、“工作”、“人”、“团队”、“公司”等术语都指向一个积极的公司环境,员工喜欢一起工作。

基于诸如“工作”、“谷歌”、“工作”和“公司”等术语在语料库中出现频率如此之高的事实,移除它们可能是个好主意(即将它们添加到我们的停用词中)。

也就是说,一个公司总是可以改进的。因此,让我们来看看每个评价中最常用的词。

这似乎是评分= 1 的评论中最常见的词,与“管理”、“经理”、“人”有关。我们在解释这些结果时必须小心,因为根据上面打印的饼状图,只有 2%的评论评级为 1。

group_by = df.groupby('rating')['lemma_str'].apply(lambda x: Counter(' '.join(x).split()).most_common(25))group_by_0 = group_by.iloc[0]
words0 = list(zip(*group_by_0))[0]
freq0 = list(zip(*group_by_0))[1]plt.figure(figsize=(50,30))
plt.bar(words0, freq0)
plt.xlabel('Words', fontsize=50)
plt.ylabel('Frequency of Words', fontsize=50)
plt.yticks(fontsize=40)
plt.xticks(rotation=60, fontsize=40)
plt.title('Frequency of 25 Most Common Words for Rating=1', fontsize=60)
plt.show()

评分为 2 的评论有一个共同的主题“经理”、“管理”。评级分布再次非常不均衡,但这确实给了我们一些改进组织的线索。

group_by_1 = group_by.iloc[1]
words1 = list(zip(*group_by_1))[0]
freq1 = list(zip(*group_by_1))[1]
plt.figure(figsize=(50,30))
plt.bar(words1, freq1)
plt.xlabel('Words', fontsize=50)
plt.ylabel('Frequency of Words', fontsize=50)
plt.yticks(fontsize=40)
plt.xticks(rotation=60, fontsize=40)
plt.title('Frequency of 25 Most Common Words for Rating=2', fontsize=60)
plt.show()

很难从“中性”评级中获得准确的见解,因为员工对公司没有任何过于积极或消极的看法。话虽如此,有趣的是,“管理”再次成为十大热门词汇。到目前为止,大约 14%的员工对谷歌的管理层持负面或中立的态度(没什么好或不好的可说)。像“工作”和“谷歌”这样的词似乎扭曲了所有评级的分布,从未来的分析中删除这些词是一个好主意。

请注意“…”,我们还需要执行一些数据处理。😞

group_by_2 = group_by.iloc[2]
words2 = list(zip(*group_by_2))[0]
freq2 = list(zip(*group_by_2))[1]
plt.figure(figsize=(50,30))
plt.bar(words2, freq2)
plt.xlabel('Words', fontsize=50)
plt.ylabel('Frequency of Words', fontsize=50)
plt.yticks(fontsize=40)
plt.xticks(rotation=60, fontsize=40)
plt.title('Frequency of 25 Most Common Words for Rating=3', fontsize=60)
plt.show()

评分为 4 和 5 的术语非常相似,因为员工似乎喜欢他们的工作,喜欢与他们一起工作的人,并且重视谷歌的环境/文化。比如“设计”、“学习机会”、“人”、“时间”、“团队”都有出现。也就是说,我们在排名前 10 位的单词中没有看到“管理”或“经理”。这是非常有见地的,因为它有助于验证评级 1、2 和 3 的结果。最后但同样重要的是,这些词频(即。等级 4 和 5)是从大量评论中得出的,这只会增加这些结果的有效性;管理当然是一个需要改进的领域。

group_by_3 = group_by.iloc[3]
words3 = list(zip(*group_by_3))[0]
freq3 = list(zip(*group_by_3))[1]
plt.figure(figsize=(50,30))
plt.bar(words3, freq3)
plt.xlabel('Words', fontsize=50)
plt.ylabel('Frequency of Words', fontsize=50)
plt.yticks(fontsize=40)
plt.xticks(rotation=60, fontsize=40)
plt.title('Frequency of 25 Most Common Words for Rating=4', fontsize=60)
plt.show()

group_by_4 = group_by.iloc[4]
words4 = list(zip(*group_by_4))[0]
freq4 = list(zip(*group_by_4))[1]
plt.figure(figsize=(50,30))
plt.bar(words4, freq4)
plt.xlabel('Words', fontsize=50)
plt.ylabel('Frequency of Words', fontsize=50)
plt.yticks(fontsize=40)
plt.xticks(rotation=60, fontsize=40)
plt.title('Frequency of 25 Most Common Words for Rating=5', fontsize=60)
plt.show()

主题建模

最后,让我们应用一些主题建模算法来帮助我们的评论导出特定的主题。在我们确定每个评级的主题之前,我们必须执行一个额外的处理步骤。现在我们的数据/文字对我们人类来说仍然是可读的,而计算机只能理解数字。我们需要将文本转换成数字或向量。

计数矢量器

对记号进行矢量化的 CountVectorizer 方法将所有单词/记号转置为特征,然后提供每个单词的出现次数。结果称为文档术语矩阵,如下所示。

首先,我们创建矢量器对象。Max_df=0.9 将删除出现在 90%以上评论中的单词。Min_df=25 将删除出现在少于 25 条评论中的单词。接下来,我们创建备用矩阵作为 fit_transform()的结果。最后,我们创建一个所有单词/特征的列表。结果就是我们的文档术语矩阵。每行代表单个员工的评价,并统计每个词/特征在每次评价中出现的次数。

tf_vectorizer = CountVectorizer(max_df=0.9, min_df=25, max_features=5000)tf = tf_vectorizer.fit_transform(df['lemma_str'].values.astype('U'))
tf_feature_names = tf_vectorizer.get_feature_names()doc_term_matrix = pd.DataFrame(tf.toarray(), columns=list(tf_feature_names))
doc_term_matrix

潜在狄利克雷分配(LDA)主题建模

既然我们已经为主题建模准备好了数据,我们将使用潜在狄利克雷分配(LDA)方法来确定语料库中的主题。在我们的模型中,我们将产生 10 个单独的主题(即 n _ 组件)。一旦创建了模型,让我们创建一个函数来显示确定的主题。每个题目由 10 个单词组成。该函数将有三个必需的参数;LDA 模型、来自文档术语矩阵的特征名称以及每个主题的字数。

lda_model = LatentDirichletAllocation(n_components=10, learning_method='online', max_iter=500, random_state=0).fit(tf)no_top_words = 10def display_topics(model, feature_names, no_top_words):
    for topic_idx, topic in enumerate(model.components_):
        print("Topic %d:" % (topic_idx))
        print(" ".join([feature_names[i]
                          for i in topic.argsort()[:-no_top_words - 1:-1]]))

display_topics(lda_model, tf_feature_names, no_top_words)

确定 LDA 模型产生的主题当然需要一点想象力。既然我们知道“工作”、“谷歌”、“工作”是很常见的作品我们几乎可以忽略它们。

主题 0:良好的设计流程

话题 1:良好的工作环境

话题 2:弹性工作时间

主题 3:技能培养

话题 4:困难但愉快的工作

话题 5:伟大的公司/工作

话题 6:关心员工

主题 7:优秀承包商薪酬

主题 8:客户服务

话题九:?

皮尔戴维斯

pyLDAvis 是一个交互式 LDA 可视化 python 库。每个圆圈代表一个独特的主题,圆圈的大小代表主题的重要性,最后,每个圆圈之间的距离代表主题之间的相似程度。选择一个主题/圆圈将显示一个水平条形图,显示与该主题最相关的 30 个单词,以及每个单词在该主题和整个语料库中出现的频率。

相关性度量有助于区分不同于/专用于主题的单词(λλ更接近 0.0)和具有被包括在所选主题中的高概率的单词(λλ更接近 1.0)。

pyLDAvis.enable_notebook()
panel = pyLDAvis.sklearn.prepare(lda_model, tf, tf_vectorizer, mds='tsne')
panel

TF-IDF

LDA 不是主题建模的唯一方法。让我们尝试另一种方法,名为非负矩阵分解(NMF)的方法,看看我们的主题是否可以稍微更加明确。我们将使用 TF-IDF(术语频率-逆文档频率)方法,而不是使用简单的 CountVectorizer 方法来对我们的单词/标记进行矢量化。TF-IDF 方法有助于降低高频词的权重/影响(即在我们的例子中是“工作”、“谷歌”和“工作”)。

与 CountVectorizer 方法非常相似,我们首先创建矢量器对象。Max_df=0.9 将删除出现在 90%以上评论中的单词。Min_df=25 将删除出现在少于 25 条评论中的单词。接下来,我们创建备用矩阵作为 fit_transform()的结果。最后,我们创建一个所有单词/特征的列表。

tfidf_vectorizer = TfidfVectorizer(max_df=0.90, min_df =25, max_features=5000, use_idf=True)tfidf = tfidf_vectorizer.fit_transform(df['lemma_str'])
tfidf_feature_names = tfidf_vectorizer.get_feature_names()doc_term_matrix_tfidf = pd.DataFrame(tfidf.toarray(), columns=list(tfidf_feature_names))
doc_term_matrix_tfidf

非负矩阵分解(NMF)

nmf = NMF(n_components=10, random_state=0, alpha=.1, init='nndsvd').fit(tfidf)display_topics(nmf, tfidf_feature_names, no_top_words)

与 LDA 相比,通过 NMF 制作的主题似乎更加独特。

话题 0:有趣的工作文化

主题 1:设计过程

话题 2:愉快的工作

主题 3:

话题四:绝佳体验

话题 5:额外津贴

主题 6:学习机会

话题 7:伟大的公司/工作

主题 8:承包商员工体验

主题 9:管理

让我们把 LDA 和 NMF 的话题都添加到我们的数据框架中,以便进一步分析。让我们也将整数主题重新映射到我们主观导出的主题标签中。

nmf_topic_values = nmf.transform(tfidf)
df['nmf_topics'] = nmf_topic_values.argmax(axis=1)
lda_topic_values = lda_model.transform(tf)
df['lda_topics'] = lda_topic_values.argmax(axis=1)lda_remap = {0: 'Good Design Processes', 1: 'Great Work Environment', 2: 'Flexible Work Hours', 3: 'Skill Building', 4: 'Difficult but Enjoyable Work', 5: 'Great Company/Job', 6: 'Care about Employees', 7: 'Great Contractor Pay', 8: 'Customer Service', 9: 'Unknown1'}df['lda_topics'] = df['lda_topics'].map(lda_remap)nmf_remap = {0: 'Fun Work Culture', 1: 'Design Process', 2: 'Enjoyable Job', 3: 'Difficult but Enjoyable Work', 
             4: 'Great Experience', 5: 'Perks', 6: 'Learning Opportunities', 7: 'Great Company/Job', 
             8: 'Contractor Employee Experience', 9: 'Management'}df['nmf_topics'] = df['nmf_topics'].map(nmf_remap)

检查由 NMF 产生的主题的频率,我们可以看到前 5 个主题以相对相似的频率出现。请记住,这些是所有评论(正面、中立和负面)的主题,如果您记得我们的数据集是负面倾斜的,因为大多数评论都是正面的。

nmf_x = df['nmf_topics'].value_counts()
nmf_y = nmf_x.sort_index()
plt.figure(figsize=(50,30))
sns.barplot(nmf_x, nmf_y.index)
plt.title("NMF Topic Distribution", fontsize=50)
plt.ylabel('Review Topics', fontsize=50)
plt.yticks(fontsize=40)
plt.xlabel('Frequency', fontsize=50)
plt.xticks(fontsize=40)

让我们将数据分开,根据评分 1 和 2 检查负面评论的主题。有趣的是,尽管有负面评价,员工们仍然非常喜欢他们的工作、文化和整个公司。由于我们数据集的偏斜,很难获得关于负面评论主题的准确观点(即相对少量的负面评论)。

df_low_ratings = df.loc[(df['rating']==1) | (df['rating']==2)]nmf_low_x = df_low_ratings['nmf_topics'].value_counts()
nmf_low_y = nmf_low_x.sort_index()
plt.figure(figsize=(50,30))
sns.barplot(nmf_low_x, nmf_low_y.index)
plt.title("NMF Topic Distribution for Low Ratings (1 & 2)", fontsize=50)
plt.ylabel('Frequency', fontsize=50)
plt.yticks(fontsize=40)
plt.xlabel('Review Topics', fontsize=50)
plt.xticks(fontsize=40)

因为我们有更多正面的评论,所以通过 NMF 获得的话题会更准确。似乎承包商雇员构成了许多评论。员工们发现了一个高效的设计过程,工作虽然艰难但却令人愉快,并且对谷歌有一种总体上愉快的情绪。

df_high_ratings = df.loc[(df['rating']==4) | (df['rating']==5)]nmf_high_x = df_high_ratings['nmf_topics'].value_counts()
nmf_high_y = nmf_high_x.sort_index()
plt.figure(figsize=(50,30))
sns.barplot(nmf_high_x, nmf_high_y.index)
plt.title("NMF Topic Distribution for High Ratings (3 & 4)", fontsize=50)
plt.ylabel('Frequency', fontsize=50)
plt.yticks(fontsize=40)
plt.xlabel('Review Topics', fontsize=50)
plt.xticks(fontsize=40)

结论

从调查结果来看,谷歌的员工似乎非常乐于在谷歌工作。我们看到一个负偏态分布,84%的员工给谷歌打了 4 或 5 分(满分为 1-5 分的李克特量表)。一项情绪分析证实了这些结果,即使给谷歌打 2 到 3 分的员工平均情绪得分为正。

随着我们对数据的进一步挖掘,我们发现了一个有趣的现象,这需要用更多的数据来验证。当我们观察每个等级的术语/词频时,似乎“经理/管理层”周围的术语似乎出现在等级 1、2 和 3 中。如前所述,数据是有偏差的,因为大多数评级都是正面的,但有趣的是,有负面或中性评级的员工似乎经常提到【管理层】

另一方面,给谷歌打 4 到 5 分的员工似乎在使用诸如、【伟大】、【工作】、【工作】、【设计】、【公司】、【好】、【文化】、【人】等词汇。这些结果通过对我们语料库中的话题/主题的检查得到了轻微的证实。NMF 对主题的分析表明,给谷歌打 4 或 5 分的员工渴望讨论困难但愉快的工作、伟大的文化和设计过程。有趣的是,我们还看到没有提到“经理”和“管理”这样的术语,这也说明并有助于验证我们之前的见解。

谷歌仍然是许多人首选的雇主,84%的评论是正面的。也就是说,我们从谷歌的管理者和/或管理技术中发现了一个潜在的改进领域。

你能想到我们可以探索的任何其他 EDA 方法和/或策略吗?把它们贴在下面的评论里。此外,如果你有任何建设性的反馈或看到我犯了一个错误,请叫我出来😃

谢谢!

[NLP]不同单词嵌入对文本分类的性能

原文:https://towardsdatascience.com/nlp-performance-of-different-word-embeddings-on-text-classification-de648c6262b?source=collection_archive---------3-----------------------

Photo by Kate Stone Matheson on Unsplash

在 word2vec、TF-IDF 加权、GloVe 和 doc2vec 之间进行比较

诱因

已经有一段时间不能写新帖了,很难过,但现在我终于又回来分享我刚刚获得的一些知识。这次是关于 NLP 的。

作为 NLP 的新手,我想尝试一下,测试一下创建文档向量的不同方法在文本分类上的表现。这篇文章将高度关注特征工程方面,即单词矢量化,而不是建模。因此,没有进一步的原因,让我们开始吧。

简介

这里研究的单词嵌入是 word2vec、TF-IDF 加权 word2vec、训练前手套 word2vec 和 doc2vec。需要的软件包是 Gensim、Spacy 和 Scikit-Learn。Spacy 用于文档预处理,包括停用词去除和基于其词性的自定义标记选择。Gensim 主要用于训练 word2vec 和 doc2vec,最后,Scikit-Learn 用于分类器构建和训练。

快速小结

在对不同的单词嵌入/平均方法进行一系列比较后,结果表明定制训练单词嵌入及其平均方法,无论是简单均值还是 TF-IDF 加权都具有最佳性能,而相反,手套单词嵌入或定制训练 Doc2vec 的性能略差于前者。

此外,即使我们试图将 word2vec 和 doc2vec 连接成一个完整的特性集,它的性能与只使用平均单词嵌入是一样的。换句话说,不需要同时使用 word2vec 和 doc2vec。

特别鸣谢以下帖子和作者

在创建我的用于文本预处理的 python 类对象时,我参考了这些写得很好的帖子。

  • nadbor 的文章“使用 Word2vec 的文本分类”演示了如何编写自己的类来计算 doc 的平均单词嵌入,无论是简单平均还是 TF-IDF 加权。
  • 《多类文本分类模型比较与选择》Susan Li教我如何写出漂亮的平均函数用于单词嵌入。
  • 本教程“关于 IMDB 情感数据集的 Gensim Doc2vec 教程”对如何通过 Gensim 创建 Doc2vec 进行了逐步指导。
  • Le&的《句子和文档的分布式表示》Mikolov 对 doc2vec 下发生的事情做了清晰易懂的解释。

数据准备

我将在这里使用的数据集是帖子[1]中提到的关于金融产品/服务的消费者投诉数据集。数据集由美国州长 CFPB 收集并发布,同时我们也可以从 Kaggle 下载数据集。

原始数据集包含 50 多万条记录,列包括产品、子产品、问题、消费者投诉、公司回应消费者等..我们将使用产品作为文本标签,使用消费者 _ 投诉 _ 叙述作为文本本身。在删除了消费者投诉中的几行缺失值后,我们只剩下大约 6 万条记录。为了减轻计算压力,我将只对前 25000 条记录进行实验。

现在,让我们看看频率是如何在每个标签中分布的。

Distribution of Each Label in the Dataset

我们可以看出,这是一个高度不平衡的数据集,其中讨债和抵押占总记录的一半,而最稀缺的类别预付卡和其他金融服务在数据集中仅占不到 1%。

以下是(标签、文本)示例的演示。

Demo of Product(Label), Consumer Complaints(Text)

文档预处理

现在是第一步——文档预处理。在我们基于输入文本创建自己的单词嵌入之前,我们需要对文本进行预处理,使其符合 Gensim 要求的输入格式。它包括从单词标记化、二元语法检测、词条化等开始的多个步骤..

在这里,我写了一个名为 DocProcess 的 python 类。这个类为我们实现了上面提到的所有底层工作,例如:

  1. 首先,该类接收一系列文本,然后标记文本并删除所有标点符号。
  2. 它有一个选项build_bi,表示是否建立二元语法,函数采用 Gensim。默认值为 False,如果选项build_bi设置为 True,那么该类将训练一个双字母检测器并为文本创建双字母单词。
  3. 现在,所有经过处理的标记被连接起来,再次形成一个句子。
  4. 文本再次被标记化,但这一次,文本中不允许的停用词词性都将被移除,所有标记都将被符号化。这些标记存储为self.doc_words —每个文本的标记列表(doc)。
  5. 最后,这些self.doc_words被打包成 TaggedDocument ,这是 Gensim 中的一个对象类型,供以后在 doc2vec 训练中使用。它存放在self.tagdocs

Snippet of Class “DocPreprocess”

有了这个类,我只需一行代码就可以轻松实现文档预处理。

from UtilWordEmbedding import DocPreprocess
import spacynlp = spacy.load('en_core_web_md')
stop_words = spacy.lang.en.stop_words.STOP_WORDSall_docs = DocPreprocess(nlp, stop_words, df['consumer_complaint_narrative'], df['product'])

现在我们来看看 doc 预处理的输出是什么样的。

The Content Stored in DocPreprocess Class

从上面我们可以看出,这个类已经存储了标记化的单词、标签和标记文档,这些都可以在以后使用。

单词模型— Word2vec 培训

由于文本被正确处理,我们准备通过 Gensim 训练我们的 word2vec。在这里,我为每个单词的嵌入选择了尺寸 100,窗口尺寸为 5。训练迭代 100 次。

word_model = Word2Vec(all_docs.doc_words, min_count=2, size=100, window=5, workers=workers, iter=100)

Photo by Daria Nepriakhina on Unsplash

现在是休息时间,很快,让我们继续…

每个文档的平均单词嵌入

好吧!现在我们手头有了单词嵌入,我们将使用单词嵌入来计算整个文本的代表向量。然后作为文本分类模型的特征输入。有多种方法可以得出 doc vector。首先,我们从简单的开始。

(1)对单词嵌入的简单平均

这是一个相当简单的方法。它直接对文本中出现的所有单词嵌入进行平均。在这里,我改编了这两篇文章[2][3]中的代码,并创建了类meanwodembedding vectorizer

Class of MeanWordEmbeddingVectorizer

它有self.fit()self.transform()方法,以便与 scikit-learn 中的其他功能兼容。这个类做的事情相当简单。使用单词模型(训练单词嵌入)初始化该类,然后它可以将文本中的所有标记转换为向量,并进行平均以得出代表性的 doc 向量。如果 doc 没有标记,那么它将返回一个零向量。

只是提醒一下,self.transform()的输入必须是文档标记列表,而不是文档文本本身。

from UtilWordEmbedding import MeanEmbeddingVectorizermean_vec_tr = MeanEmbeddingVectorizer(word_model)
doc_vec = mean_vec_tr.transform(all_docs.doc_words)

(2)单词嵌入的 TF-IDF 加权平均

不仅仅满足于简单的平均?我们可以进一步采用 TF-IDF 作为每个单词嵌入的权重。这将放大有效词在计算文档向量中的作用。这里,整个过程是在类TfidfEmbeddingVectorizer下实现的。同样,代码改编自相同的帖子源。

值得注意的一点是,我们在对文本进行平均时已经考虑到了词频,而没有考虑到逆文档频率,因此权重字面上就是 IDF,默认设置中未看到的词被赋予最大 IDF。代码片段可以在 this gist 中查看。

另一件要注意的事情是,我们需要先用标记来拟合类,因为它必须事先遍历所有单词,以便计算 IDF。

from UtilWordEmbedding import TfidfEmbeddingVectorizertfidf_vec_tr = TfidfEmbeddingVectorizer(word_model)
tfidf_vec_tr.fit(all_docs.doc_words)  # fit tfidf model first
tfidf_doc_vec = tfidf_vec_tr.transform(all_docs.doc_words)

(3)利用预训练手套单词嵌入

让我们包括另一个选项—利用现有的预训练单词嵌入,看看它在文本分类中的表现如何。在这里,我按照斯坦福大学自然语言处理课程(CS224N)笔记本的说明,将 GloVe word embedding 导入 Gensim 进行计算,以计算文本上的平均单词嵌入。

顺便说一句,我还尝试对手套向量应用 TF-IDF 加权方法,但发现结果与 Tf-IDF 加权平均 doc 向量的结果基本相同。因此,我省略了演示,这里只包括手套字向量的简单平均。

# Apply word averaging on GloVe word vector.
glove_mean_vec_tr = MeanEmbeddingVectorizer(glove_word_model)
glove_doc_vec = glove_mean_vec_tr.transform(all_docs.doc_words)

(4)直接应用 Doc2vec 培训

最后但同样重要的是,我们还有一个选择—直接训练 doc2vec,不需要对所有单词嵌入进行平均。这里我选择了 PV-DM 型号来训练我的 doc2vec。

该脚本主要参考自 Gensim 教程[4]。同样,为了节省所有的劳动,我为它创建了一个类 DocModel 。这个类只需要接受 TaggedDocument 然后我们调用self.custom_train()方法,doc 模型会自己训练。

Class of DocModel

注意到self.custom_train()可以选择使用固定学习率。据说固定的学习速率达到更好的效果[5]如这里所引用的,

1.随机化输入句子的顺序,或者

2.在几次迭代过程中手动控制学习速率。

但这并没有发生在我的实验中。当我手动降低学习率时(下面的代码),我发现 doc2vec 模型不能正确推断最相似的 doc。也就是说,如果我输入来自同一个文档的文档向量,self.test_orig_doc_infer()不会返回与最相似文档相同的文档,尽管它应该这样做。

顺便提一下,self.test_orig_doc_infer()方法用于测试给定来自原始文档的文档向量的预测文档是否确实返回与最相似文档相同的文档。如果是这样,我们可以公平地判断该模型成功地捕捉了整个文档的隐含意义,从而给出了具有代表性的文档向量。

# Failed Attempt (Not achieving better result.)
for _ in range(fixed_lr_epochs):
   self.model.train(utils.shuffle([x for x in self.docs]),
                total_examples=len(self.docs),
                epochs=1)
   self.model.alpha -= 0.002
   self.model.min_alpha = self.model.alpha  # fixed learning rate

因此,相反,只保留默认设置就足以达到更好的效果。这里,学习率被设置为 0.025,训练时期为 100,并且应用负采样。

from UtilWordEmbedding import DocModel# Configure keyed arguments for Doc2Vec model.
dm_args = {
    'dm': 1,
    'dm_mean': 1,
    'vector_size': 100,
    'window': 5,
    'negative': 5,
    'hs': 0,
    'min_count': 2,
    'sample': 0,
    'workers': workers,
    'alpha': 0.025,
    'min_alpha': 0.025,
    'epochs': 100,
    'comment': 'alpha=0.025'
}# Instantiate a pv-dm model.
dm = DocModel(docs=all_docs.tagdocs, **dm_args)dm.custom_train()

(5)标签

最后,不要忘记标签!!!

target_labels = all_docs.labels

准备分类模型

现在,我们已经准备好了所有必要的材料——不同类型的功能。让我们通过实验来观察它们对分类性能的影响。在这里,我将使用基本逻辑模型作为基础模型,并加入之前创建的不同类型的特征。因此,要比较它们的有效性。

除了比较每种单词嵌入平均方法的效果,我还尝试将 word2vec 和 doc2vec 连接在一起,看看它是否能进一步提升性能。

我一起用了 TF-IDF 加权词嵌入和 PV-DM doc2vec。结果表明,它提高了训练数据集的准确性(也许是过拟合的标志?),但与单独使用 TF-IDF word2vec 相比,在测试数据集上没有显著改善。

反光

我们来考察一下哪个单词嵌入的表现最差。令人惊讶的是,预训练手套单词嵌入和 doc2vec 在文本分类上的表现相对较差,准确率分别为 0.73 和 0.78,其他都在 0.8 以上。也许,这是因为定制训练的 word2vec 特别适合这个数据集,因此为手头的文档提供了最相关的信息。

这并不一定意味着我们不应该再使用 GloVe word embedding 或 doc2vec,因为在推理阶段,我们可能会遇到单词模型中没有单词嵌入的新单词。在这种情况下,手套单词嵌入将对其在宽词汇量上的覆盖有很大帮助。

至于 doc2vec,我们可以说它可以帮助训练好的单词嵌入来进一步提高文本分类模型的性能,尽管它很小,也很适合选择退出。

Table of Classification Performance over Different Word Embedding

完整的 jupyter 笔记本可以在这个链接下找到。

参考

[1] Susan Li,用 Doc2Vec 进行多类文本分类& Logistic 回归 (2018),走向数据科学

[2]纳德博尔,文字分类用 Word2Vec (2016), DS 绝杀

[3]苏珊·李,多类文本分类模型比较与选择 (2018),走向数据科学

[4] Gensim Doc2Vec 关于 IMDB 情感数据集的教程(2018)github

[5]雷迪姆·řehůřek's, Doc2vec 教程 (2014),稀有技术

[NLP]具有预训练令牌的空间分类器 2vec 与没有预训练的空间分类器

原文:https://towardsdatascience.com/nlp-spacy-classifier-with-pre-train-token2vec-vs-one-without-pre-train-2f05d2179290?source=collection_archive---------16-----------------------

Photo by Mark Zamora on Unsplash

尝试 spaCy 的伯特风格的预训练语言模型

继我之前的文章关于利用文字嵌入建立文本分类器。在这篇文章中,我将在另一个众所周知的 NLP 包 spaCy 上进行实验,并尝试不同的建模来看看它们的性能如何。

从 spaCy v2.1 开始,它引入了pretrain命令的新特性,允许我们为手头的文档启动语言模型定制。它被宣称可以进一步提高精确度,并且在我们只有有限的标记数据集的情况下特别有用[1]。标记数据的不可用性或有限大小对我来说是一个真正令人头痛的问题,我相信对大多数其他数据科学从业者来说也是如此。因此,新推出的功能对我们所有人来说都是一剂强有力的止痛药。今天,我将尝试并检查它如何在准确性和 f1 的得分上有利于文本分类器。

快速小结

结果表明,未经预训练的分类器在 f1 和准确率上都有较高的得分。尽管如此,还是要有所保留。如果我们仔细观察,经过预训练的人在识别稀有类方面表现得更好。如果识别稀有类很重要,它仍然有自己的优点。

值得注意的是,spaCy pretrain函数或类似的 BERT 风格预训练背后的概念不同于常用的词向量[2],词向量指的是我们通过 gensim 训练的自定义词 2vec,例如,并作为文本分类器的输入。Spacy pretrain发起并训练所谓的语言模型。我还不太明白这两者的区别,希望几天后,一旦我对这两者有了更好的理解,我可以分享另一篇关于其背后理论的文章。但是我们不要推迟体验新功能,为什么不尝试一下呢。

再次,首先,让我向下面的贡献者致敬。思路和做法参考自以下帖子。

  • 努兹克[3]的太空之旅(第二部分)
  • Poonam Ligade 使用 SpaCy 进行文本分类[4]

熟悉数据

在这个案例中,我将使用的数据是消费者对金融产品/服务的投诉。也可以从这个 Gov. link 和 Kaggle 中拉出。

该数据集包括“接收日期、产品、问题、消费者投诉、公司”等列特别是,我将使用product作为类标签,使用consumer_complaint_narrative作为建模输入。此外,我对一个包含 5000 条记录的样本集进行了子集划分,从而减少了计算资源的消耗。这些记录都是无缺失值的。下面是每个类标签的分布。

Distribution of Class Label in Sample Dataset

我们可以说这是非常不平衡的,前两个班级占了所有记录的一半。这对识别稀缺类别的模型提出了挑战。

Preview of product(label) and input(consumer_complaint_narrative)

准备训练、有效和测试数据集

使用 spaCy 构建文本分类器的一个好处是我们可以跳过繁琐的数据预处理阶段。Spacy 会为我们做得很好。我们需要做的就是通过 spaCy 把原始的文本数据转换成需要的文本格式,然后剩下的就交给它了。这里我写了一个代码片段来计算每个数据分割的大小——训练 60%,有效 20%,测试 20%。然后我调用train_test_split两次,分别将数据分成三组。

Train/Valid/Test Dataset Split

将数据集转换为 spaCy 兼容格式

现在是核心部分,首先我对标签进行一次性编码,并编写一个自定义函数将文本输入和标签转换为列表。

之后,特别是在有效和测试集上,我再次将文本和标签分开,为以后的计算精度做准备。

Dataframe to List in Compliance with spaCy Input Format

现在我们准备构建空间分类器。注意,我们需要在模型本身中添加每个类标签,以便它可以在训练时识别它们。另外,我们事先从 sklearn 导入f1_scoreaccuracy_score

Construct Spacy Text Classifier

培养

现在,我们已经具备了开始训练的所有先决条件。在训练片段中,我采用了一些技巧。一个是训练过程将每几次迭代评估模型。另一个是提前停止。一旦模型在几次连续迭代中没有表现出 f1 分数提高的迹象,训练过程将停止并立即保存最佳性能模型。这种做法使培训过程更有效率。从进度打印输出中,我们观察到一条非常平滑的学习曲线,表明 textcat 很好地捕捉了输入数据,并能够逐渐做出更好的预测。该模型在 f1 中的得分为 0.78,在验证集中的准确率为 0.79。然而,它在未知测试集上的表现如何?

Training Block of spaCy Textcat

Training Progress

测试集评估

在这里,我编写了一个自定义函数evaluate来评估模型的性能。有趣的是,经过训练的模型在测试集上获得了更高的分数,其中 f1 分数为 0.81,准确度为 0.82。

Trained Model Performance on Test Set

Photo by Nuno Silva on Unsplash

使用预训练 token2vec 语言模型进行训练

我们从没有预先训练语言模型的分类器中看到相当令人满意的结果。但是,让我们试验一下,看看当我们应用一个时,它会进一步提高多少。首先,我们需要在文档上实现 spaCy pretrain并保存 token2vec 模型。但是在我们开始预培训之前,我们需要将文件转换成需要的格式,这里我将其保存为text.jsonl格式转换的详细实现可以在的笔记本附录部分找到。

注意到,预训练过程是极其计算密集型的。我在 GCP 上启动了一个计算引擎,配备了 8 核 CPU 和 32GB RAM 来支持训练,但完成前 500 次训练迭代仍然需要 10 个多小时。训练速度大概是每秒 9000 字。因此,在应用训练前功能时,请牢记这一挑战。下面是启动空间预训练的命令。此外,我设置--use-vectors使用现有英语模型的向量。

python -m spacy pretrain <docs> en_core_web_lg <output_dir> --use-vectors 

构造简单的 CNN 文本

正如在github 问题中所提到的,如果我们想要合并预训练语言模型,并加载预训练权重,我们需要将模型架构切换到simple_cnn。下面的代码片段只强调了与以前模型的区别。

  • 指定模型架构。
if 'textcat' not in nlp.pipe_names:
    textcat = nlp.create_pipe('textcat',
                              config={'architecture':'simple_cnn',
                              'exclusive_classes':True})
    nlp.add_pipe(textcat, last=True)
# otherwise, get it, so we can add labels to it
else:
    textcat = nlp.get_pipe('textcat')
  • 加载训练前重量。
# Train model
other_pipes = [pipe for pipe in nlp.pipe_names if pipe != 'textcat']
with nlp.disable_pipes(*other_pipes):  # only train textcat
    optimizer = nlp.begin_training() # initiate a new model

    with open(pretrain_model_path, 'rb') as file_:
        textcat.model.tok2vec.from_bytes(file_.read())

培养

与之前的模型相比,我们可以看出培训损失在一开始就显著下降。但另一方面,f1 的分数和准确性不如以前的车型。那很有趣。似乎合并预训练模型并没有提高文本分类器的性能。

Training Progress with pre-train tok2vec

测试集评估

但是让我们更深入地研究一下。我们可以看出,虽然预训练的分类器具有较低的 f1 和准确度分数,但它在识别稀有类方面表现得稍好。例如,在“货币转账、发薪日贷款、预付费卡”的类别上,新的分类器成功地识别了每个类别中 10 ~ 30%的情况,但是,先前的分类器在所有情况下都失败了。

结论

通过比较具有预训练语言模型的分类器和没有预训练语言模型的分类器,我们可以更好地判断具有预训练语言模型的分类器是否性能更好,如果是,性能提高多少。从上面的实验来看,结果是预训练的一个在 f1 和准确性上得分较低,但它在识别罕见情况上工作得更好。这取决于我们希望应用这些模型的使用场景。如果我们更强调一般性能,那么我们可能只是坚持以前的分类器。尽管如此,如果我们对识别罕见的案例更感兴趣,也许,预培训的实践可能值得一试。

如果你有兴趣了解更多,完整的脚本可以在这本笔记本中找到。

参考

[1] 伯特/乌尔姆菲特/埃尔莫式的预训,空间文件

[2] 通过迁移学习提高准确性,空间文档

[3] Nuszk,spaCy 的牛逼功能之旅(第 2/2 部), Eliiza-AI

[4] Poonam Ligade,文本分类使用 SpaCy , Kaggle

自然语言处理文本预处理:实用指南和模板

原文:https://towardsdatascience.com/nlp-text-preprocessing-a-practical-guide-and-template-d80874676e79?source=collection_archive---------3-----------------------

传统上,文本预处理是自然语言处理(NLP)任务的重要步骤。它将文本转换为更容易消化的形式,以便机器学习算法能够更好地执行。

文本预处理的重要性

为了说明文本预处理的重要性,让我们考虑一个针对客户评论的情感分析任务。

假设一个客户反馈说“他们的客户支持服务是一场噩梦”,一个人肯定可以清楚地识别评论的情绪是负面的。然而对于机器来说,这并不简单。

为了说明这一点,我用 Azure 文本分析 API 进行了实验。馈入同一个评论,API 返回 50%的结果,即中性情绪,这是错误的。

Azure text analytics API results as of publication date (30 Aug 2019)

然而,如果我们已经执行了一些文本预处理,在这种情况下只是删除一些停用词(下面将进一步解释,但现在,将停用词视为非常常见的词,这样它们在我们的 NLP 任务中不会有太大帮助),我们将看到结果变成 16%,即负面情绪,这是正确的。

Azure text analytics API results after our own preprocessing

因此,如图所示,如果处理得当,文本预处理有助于提高 NLP 任务的准确性。

边注:上面的 Azure 例子实际上更有趣,因为按理说, Azure 的文本分析 API 应该已经将文本作为其模型 的一部分进行了处理,但不知何故,停用词似乎混淆了其模型。

文本预处理概述

那么我们如何着手进行文本预处理呢?通常,有 3 个主要组件:

  • 标记化
  • 正常化
  • 噪声消除

简而言之,记号化就是将文本串分割成更小的片段,或者“记号”。段落可以被标记成句子,句子可以被标记成单词。规范化旨在将所有文本置于一个公平的竞争环境中,例如,将所有字符转换为小写。噪声去除清理文本,例如,去除多余的空白。

详情请参考马修·梅奥的这篇伟大的文章。

文本预处理步骤列表

根据上面的概述,我们在每个组件下执行了一系列步骤。

  1. 删除 HTML 标签
  2. 删除多余的空格
  3. 将重音字符转换为 ASCII 字符
  4. 扩大收缩
  5. 删除特殊字符
  6. 小写所有文本
  7. 将数字转换成数字形式
  8. 删除号码
  9. 删除停用词
  10. 词汇化

完整代码的链接可以在文章的底部找到,但是请继续阅读以理解所采取的重要步骤。

必要的依赖关系如下:

from bs4 import BeautifulSoup
import spacy
import unidecode
from word2number import w2n
import contractions# load spacy model, can be "en_core_web_sm" as well
nlp = spacy.load('en_core_web_md')

删除 HTML 标签

如果评论或文本是从网上搜集来的,它们很可能会包含一些 HTML 标签。因为这些标签对我们的 NLP 任务没有用,所以最好删除它们。

Highlighted texts show HTML tags

为此,我们可以使用 BeautifulSoup 的 HTML 解析器,如下所示:

def strip_html_tags(text):
    """remove html tags from text"""
    soup = BeautifulSoup(text, "html.parser")
    stripped_text = soup.get_text(separator=" ")
    return stripped_text

转换重音字符

“你想去我们的咖啡馆喝拿铁吗?”

带有像“latté”和“café”这样的重音符号的单词可以被转换并标准化为“latte”和“cafe ”,否则我们的 NLP 模型会将“latté”和“latte”视为不同的单词,即使它们指的是同一事物。为此,我们使用模块 unidecode。

def remove_accented_chars(text):
    """remove accented characters from text, e.g. café"""
    text = unidecode.unidecode(text)
    return text

扩大收缩

缩写是缩短的单词,例如,不要和不能。将这样的词扩展到“不要”和“不能”,有助于规范文字。

我们使用收缩模块来扩展收缩。

def expand_contractions(text):
    """expand shortened words, e.g. don't to do not"""
    text = contractions.fix(text)
    return text

注意:根据您的 NLP 任务,这一步是可选的,因为 spaCy 的标记化和词条化函数将执行相同的效果来扩展诸如 can't 和 don't 之类的缩写。稍微不同的是,spaCy 会把“we 're”扩展成“we be ”,而 py 缩略会给出结果“we are”。

数字处理

我们处理数字有两个步骤。

其中一个步骤涉及将数字字转换成数字形式,例如 7 到 7,以标准化文本。为此,我们使用 word2number 模块。示例代码如下:

text = """three cups of coffee"""doc = nlp(text)tokens = [w2n.word_to_num(token.text) if token.pos_ == 'NUM' else token for token in doc]

print(tokens) # result: [3, cups, of, coffee]

另一步是删除数字。稍后您将会看到,我们能够通过将参数设置为值来打开或关闭这些步骤。移除数字对于情感分析可能是有意义的,因为数字不包含关于情感的信息。然而,如果我们的 NLP 任务是提取发送给聊天机器人的消息中订购的机票数量,我们肯定不希望删除数字。

停用词

如前所述,停用词是非常常见的单词。像“我们”和“是”这样的词可能对诸如情感分析或文本分类这样的 NLP 任务没有任何帮助。因此,我们可以删除停用词,以节省处理大量文本的计算时间和精力。

在我们的例子中,我们使用了 spaCy 内置的停用词,但是我们应该谨慎,并相应地修改停用词列表。例如,对于情感分析,单词“not”在诸如“not good”的文本的含义中是重要的。然而,spaCy 将“not”作为停用词。因此,我们通过以下代码修改停用词:

# exclude words from spacy stopwords list
deselect_stop_words = ['no', 'not']
for w in deselect_stop_words:
    nlp.vocab[w].is_stop = False

词汇化

词汇化是将一个词转换成其基本形式的过程,例如,“caring”转换成“care”。我们使用 spaCy 的引理器来获得单词的引理或基本形式。示例代码:

text = """he kept eating while we are talking"""
doc = nlp(text)# Lemmatizing each token
mytokens = [word.lemma_ if word.lemma_ != "-PRON-" else word.lower_ for word in doc]print(mytokens) 
# result: ['he', 'keep', 'eat', 'while', 'we', 'be', 'talk']

另一种获得单词基本形式的方法是词干分析法。我们没有在文本预处理代码中使用它,但是如果处理速度是最重要的考虑因素,你可以考虑使用词干。但是请注意,词干分析是一种粗糙的启发式方法,它将单词的词尾砍掉,因此,结果可能不是好的或真实的单词。例如,堵塞“关心”将导致“汽车”。

现在和接下来的步骤

综上所述,全文预处理代码如下:

https://gist . github . com/jiahao 87/d57a 2535 C2 ed 7315390920 ea 9296d 79 f

运行该函数的示例代码如下:

# text = """I'd like to have three cups   of coffee<br /><br />from your Café. #delicious"""

text_preprocessing(text) 
# result: ['like', 'cup', 'coffee', 'cafe', 'delicious']

要打开或关闭特定步骤,我们可以将相关参数设置为值。例如,为了不删除数字,将参数“remove_num”设置为

# example to not remove numbers
text_preprocessing(text, remove_num=False)

之后,我们可以将处理过的文本转换成可以用数字表示的东西。这样做的两种主要方法是一键编码和单词嵌入向量。我们将在下一篇文章中探讨这些问题。

最后,请注意,有专家表达了文本预处理负面影响而不是增强深度学习模型性能的观点。尽管如此,文本预处理对于非深度学习模型来说无疑是至关重要的。

感谢阅读,我希望代码和文章是有用的。如果您有任何问题或建议,也请随时发表评论。

参考

  • https://www . kdnugges . com/2017/12/general-approach-预处理-text-data.html
  • https://www . kdnugges . com/2018/08/practices-guide-processing-understanding-text-2 . html
  • https://docs . Microsoft . com/en-in/azure/cognitive-services/text-analytics/how-tos/text-analytics-how-to-情操分析
  • https://pypi.org/project/contractions/
  • https://pypi.org/project/word2number/

Python 中的 NLP 文本预处理和清理管道

原文:https://towardsdatascience.com/nlp-text-preprocessing-and-cleaning-pipeline-in-python-3bafaf54ac35?source=collection_archive---------21-----------------------

我们通过语言表达人类的经历。语言是我们交流、表达情感、倾听、思考和交谈的方式。在过去的十年中,自然语言处理(NLP)取得了巨大的进步,计算机可以像人类一样分类、生成和响应语言。这些模型和算法已经开始给计算机提供理解人类经验的工具。这些领域增长的最重要原因是因为可以进行特征工程设计然后输入模型的数据呈指数增长。

特征工程:

站在自然语言处理前沿的数据科学家、博士、机器学习工程师和数据工程师花了大部分时间清理和探索数据集。

垃圾进垃圾出

如果向模型提供最新的数据,它们将产生最新的结果;模型如果被喂以垃圾就会产生垃圾,因此数据清洗是整个机器学习过程中最重要的部分之一。如果你训练的是像 BERT 或老派 word2vec 这样的艺术级变形金刚,那也没关系。您提供给模型的数据质量将决定您获得的结果的质量。

garbage in garbage out; data on fire in data on fire out

特征工程和数据清理不是乏味和无意义的任务——它们是重要的过滤机制,其工作方式与人脑处理语言的方式相同。当人类年轻时,他们学会如何从一种语言中分离噪音,然后通过该语言中最重要的单词和短语找到该语言的意义。这个过程类似于文本预处理。文本预处理将语料库分解成更小的部分,然后从这些部分中提取最重要的信息,模型将从这些信息中获取意义。

给我看看代码!

管道中的步骤

📜👀,📊(加载、查看和分析数据) :

任何机器学习管道的第一步都是加载数据!为了更好地衡量,我们还将查看数据以确保所有内容都正确加载,并收集一些基本的统计数据,如字数、行数和字符数。这将让我们很好地了解我们在管道中的下一步工作是什么。我使用的是路透社的数据集,可以在这里找到。

data_folder = Path("/Users/emilyelia/Downloads/reuters/reuters/reuters/training")
file_to_open = data_folder / "104"
f = open(file_to_open)print(f.read())
num_lines =0
num_words =0
num_chars =0
with open(file_to_open, 'r') as f:
    for line in f:
        words = line.split()num_lines += 1
        num_words += len(words)
        num_chars += len(line)print ("numbers of words", num_words)
print("number of lines", num_lines)
print("number of chars", num_chars)

符号化:

标记化是下一个预处理步骤。它获取文本语料库,并将其拆分为“标记”(单词、句子等)。).

这个过程不像使用某种分离器那么简单。分隔符在很多不同的情况下都不起作用,例如带点的缩写,如“Dr .”或句点。在句末。需要一个更复杂的模型来正确地进行标记化,但是不要担心,因为标记化是 nltk 等常用 NLP 库中的内置特性。

from nltk.tokenize import sent_tokenize, word_tokenize
f = open(file_to_open)
#use built in tokenize to seperate each indiviual word
nltk_words = word_tokenize(f.read())
print(f"Tokenized words: {nltk_words}")

清洁:

清理是从语料库中删除所有不必要内容的过程。不必要的内容包括停用词和标点符号,因为它们不会给整个语料库增加任何价值或意义。

标点

标点去除是一个重要的步骤,因为标点不提供任何附加的价值或对整个语料库和语料库的矢量化的洞察。最好在标记化步骤之后删除标点符号,因为之前这样做可能会导致一些不可预见的结果。

停止字

停用词是你正在使用的语言中最常见的词。根据您使用的库,有 50-100 个停用词,它们不像“the”、“an”和“it”那样增加意思。移除这些单词不会改变您正在处理的语料库的含义,并且会导致更好的结果,因为剩余的单词对于确定语料库的含义是最重要的。

print(nltk_words)
punctuation = list(string.punctuation)
stopWords = set(stopwords.words('english'))
filter = []
for w in nltk_words:
    if w.lower()not in stopWords and w not in punctuation:
        filter.append(w)

正常化

正常化是返回到标准形式或状态的过程。就文本预处理而言,它意味着获取数字、缩写和特殊字符,并将其转换为文本。这一过程使用了我们的大脑在处理特殊字符、拼写错误和缩写时所使用的相同联想,即把它们与我们用自己选择的语言说、读或想的单词联系起来。我正在使用可以在这里找到的库规格化。

最常见的标准化特征是日期、数字、缩写、货币、百分比和拼写错误。在 normalise 中,你必须列出你想要拼写的缩写,然后调用 normalise 函数来执行其余的规范化。

from normalise import normalise
abbr = {
    "lb": "pounds",
    "USDA": "United States Department of Agriculture",
    "cts": "cents",
    "U.S.": "United States"
}
normalise(text, user_abbrevs=abbr)
nt =normalise(filter, user_abbrevs=abbr)
display( ' '.join(nt))

这些规范化确保模型能够理解所有必须处理的文本,因为数字、特殊字符、拼写错误和缩写将与语料库中的所有其他内容具有相同的表示。

点击这里查看整个项目!

[## emil yelia/自定义-NLP-文本-预处理-管道

此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…

github.com](https://github.com/emilyelia/Custom-NLP-Text-Preprocessing-Pipeline)

NLP——使用 SpacyR 分析总统演讲

原文:https://towardsdatascience.com/nlp-using-spacyr-to-analyze-presidential-speeches-49c10ef37aef?source=collection_archive---------35-----------------------

词类分析的简单指南

Photo by History in HD on Unsplash

友好的名词

2018 年 4 月,以色列 Herzliya 跨学科中心的两名研究人员 Michal Reifen-Tagar 和 Orly Idan 发表了论文 “玫瑰还有其他名字吗?微妙的语言暗示会影响棘手冲突中的愤怒和相应的政策支持”。作者测量了在巴以冲突背景下对某些政策的不同支持和厌恶程度。有趣的是,他们发现,为了减少紧张和增加支持,在制定政策时,最好更多地依靠名词而不是动词。

受这些发现的启发,我想知道美国总统过去是否使用过这种技巧来释放一些紧张情绪并获得支持,即使这是在直觉层面上发生的。为此,我利用自然语言处理方法分析了他们的第一次和第二次就职演说。

斯帕西尔

对于词性分析,我使用了 SpacyRSpacyr 是 Python (Cython) spaCy 的 R 包装器,它被集成到 quanteda 中。这个包,除了别的以外,帮助解析和标记文档,同时标记每个标记作为语音的一部分的功能(名词、动词、代词、形容词等)。

注意:SpacyR 的安装可能会比较棘手。这里参考文档

密码

第一步是为第一个和第二个学期的演讲数据集创建tibles,解析它们,并删除空格和标点符号。变量 doc_id 包含演讲的年份和发表演讲的总统;文字栏发言的转写;并且 pos 列为每个单词提供了一个标记,表示其类型。

#Loading packages
library("spacyr")
library(tibble)
spacy_initialize()#Creating tibble
First_term <- as_tibble( data.frame(doc_id = first_term$doc_id, text = first_term$text, stringsAsFactors = F)#Parsing tibble
first_term_parsed <- spacy_parse(first_term)#Removing spaces and punctuation
first_term_parsed <- first_term_parsed [first_term_parsed$pos!=”SPACE” & first_term_parsed$pos!=”PUNCT”, ]first_term_parsedtable(first_term_parsed$pos)sum(table(first_term_parsed$pos))

一旦我们有了解析过的词表,就该找出演讲中名词和动词用法的区别了。使用余弦相似性,我选择了三个最相似和最不相似的演讲,并为它们创建了一个名词/动词比率。

注意:余弦相似性的代码没有显示,因为它是一个独立的主题。如果你对我们如何确定文档之间的相似性感到好奇,并且对这个在文本分析中非常重要的话题感到好奇,我推荐你 这篇文章 或者在这里 看一下 text2vec 文档

我们词类分析的第一步是找出名词相对于演讲中使用的其他类型单词的份额。

#Share of nouns **sum**(first_term_parsed**$**pos**==**"NOUN")**/sum**(**table**(first_term_parsed**$**pos))*****100#Share of verbs 
**sum**(first_term_parsed**$**pos**==**"VERB")**/sum**(**table**(first_term_parsed**$**pos))*****100

有了演讲中的名词和动词的份额后,我们需要计算一个名词/动词比,用名词的总数除以动词的总数。这是结果:

最相似的演讲

上表显示,克林顿的第二次就职演说的名词/动词比高于里根的第二任期演说。这可能表明克林顿在第二任期的演讲中比里根更倾向于和解/呼吁团结。然而,乔治·w·布什的第二任期演讲(2005 年)是这三个演讲中名词/动词比率最高的一个。很可能,由于处于伊拉克战争的中期,布什在相对“平静”的年代比其他总统使用了更多与动词相关的名词,旨在为他的政策和对外干预获得更多支持。

现在让我们看看三个最不同的演讲的名词动词比率。

最不相似的演讲

这里我们可以看到,特朗普的名词动词比率最低。巧合吗?用一种好的方式来说,他较少使用名词和动词,这可能表明,不太在乎传递和解信息的外交官和政治家的名词/动词比率较低。面临战争的艾森豪威尔的名词/动词比率高于特朗普和杰克逊,但低于 2005 年的小布什。处于战争状态和在就职演说中使用名词之间有关联吗?我们将不得不把这个问题留待下次讨论。

激烈的对话?

所以现在你知道了。每当你发现自己处于一个棘手的情况下,使用更多的名词而不是动词可以帮助你获得对你的想法的支持,甚至可能减少房间里的紧张气氛!

感谢阅读!欢迎随时在下方留言或联系LinkedInTwitter。我很乐意与您联系,分享有关政治、通信和数据科学的故事。

具有管道和网格搜索的 NLP

原文:https://towardsdatascience.com/nlp-with-pipeline-gridsearch-5922266e82f4?source=collection_archive---------16-----------------------

[Source](http://Photo by Rodion Kutsaev on Unsplash)

自然语言处理,简称 NLP,在 Alexa、Siri 和谷歌助手等人工智能助手中风靡一时。当我第一次在钢铁侠电影中看到 J.A.R.V.I.S .的时候,好像就在昨天。看到这一点激发了我对我们如何与计算机互动的兴趣。一台能像人一样听和反应的电脑?它是如何工作的?这看起来像魔术,但实际上计算机正在将单词分解成更简单的形式,在某些情况下,还会创建这些形式的列表进行排序。计算机寻找特定单词之间的模式或关系,然后根据这些关系做出预测。

我们将使用 Pipeline 和 GridSearch 来运行几个模型,并确认哪一个模型最适合预测给定博客主题的帖子的位置。例如,如果我的帖子会出现在 NHL 或 Fantasy Hockey 中,一个模型能够有效地判断出来吗?为此,我将使用我自己的数据集,但是代码在大多数情况下是可重复的。

[Source](http://Photo by Andrik Langfield on Unsplash)

让我们开始建设吧!

首先,您需要导入库和数据集,这一步我不会显示导入,因为列表会变得很长。我们将在数据已经被清理并且处于可以开始建模的形式之后开始。

让我们声明我们的变量!我们将需要创建 X 和 Y 变量,并使用训练测试分割。

# Creating X, y Variables
X, y = df[‘post’], df[‘blog_topic’]# Setting up train test split
X_train, X_test, y_train, y_test = train_test_split(X, y)

我们在这里所做的是将我们的数据集分成两个数据集:训练数据和测试数据。现在,我们已经将 X 变量声明为博客文章,将 Y 变量声明为博客主题。我们希望我们的模型接受一个博客帖子,并预测该帖子是否应该在 NHL 或 Fantasy Hockey 主题中。

管道

Pipeline 将接收带有某些参数的模型,然后我们可以通过 GridSearch 来查看哪个模型和参数给出了最好的结果。

# Pipeline & Gridsearch setup
# TFIDF pipeline setup
tvc_pipe = Pipeline([
 (‘tvec’, TfidfVectorizer()),
 (‘mb’, MultinomialNB())
])# Randomforest pipeline setup
rf_pipe = Pipeline([
 (‘tvec’, TfidfVectorizer()),
 (‘rf’, RandomForestClassifier())
])# Fit
tvc_pipe.fit(X_train, y_train)
rf_pipe.fit(X_train, y_train)# Setting params for TFIDF Vectorizer gridsearch
tf_params = {
 ‘tvec__max_features’:[100, 2000],
 ‘tvec__ngram_range’: [(1, 1), (1, 2), (2, 2)],
 ‘tvec__stop_words’: [None, ‘english’],

}# Setting up randomforest params
rf_params = {
 ‘tvec__max_features’:[2000],
 ‘tvec__ngram_range’: [(1, 2)],
 ‘tvec__stop_words’: [‘english’],
 ‘rf__max_depth’: [1000],
 ‘rf__min_samples_split’: [100],
 ‘rf__max_leaf_nodes’: [None]
}

现在我们有了自己的模型,让我给你一个公平的警告。RandomForest 需要一些时间来运行,如果你有合适的计算能力,我建议只运行一个模型。

P 参数必须被指定给一个模型,并被构建成一个带有键和值的字典。这里的方法是 RandomForest 的模型变量是“rf ”,我们需要在变量和参数之间使用双下划线“__”。例如,如果我们想在 RandomForest 中设置叶节点的数量,我们需要在我们的参数中写出来,就像这样:“RF _ _ max _ leaf _ nodes”:[None]”。为了避免出错,我们需要使用方括号'[ ]'以列表形式传递每个字典值,即使只有一个。您不需要调用每个参数,只需要调用您试图在模型中使用的那些参数。

网格搜索

为了设置 GridSearch,我们将使用我们构建的参数传递我们的管道。我们将对我们的五折模型进行标准交叉验证。

# Setting up GridSearch for Randomforest
rf_gs = GridSearchCV(rf_pipe, param_grid=rf_params, cv = 5, verbose = 1, n_jobs = -1)# Setting up GridSearch for TFIDFVectorizer
tvc_gs = GridSearchCV(tvc_pipe, param_grid=tf_params, cv = 5, verbose =1, n_jobs = -1)# Fitting TVC GS
tvc_gs.fit(X_train, y_train)# Fitting Randomforest CV GS
rf_gs.fit(X_train, y_train)

当使用 GridSearch 时,我们将管道作为估计器。然后我们必须给它一个 param_grid,这是我们在构建管道时设置的参数。建议您使用三重或五重交叉验证。我更喜欢使用五重交叉验证,但你可以为“cv”传递三个。

我建议在运行任何模型时设置“verbose = 1”和“n_jobs = -1”。Verbose 将告诉我们运行时间以及模型运行需要多长时间。n_jobs 参数允许我们指定我们希望在 CPU 上使用多少个内核。这可以减少运行模型的时间。在这里使用-1 将告诉它使用 CPU 上的所有内核。这个过程需要的时间最长,因为模型现在正在数据集上进行自我训练。然后,我们将使用它给出一个准确度分数,它将告诉我们我们的模型执行得有多好。

[Source](http://Photo by JOSHUA COLEMAN on Unsplash)

得分

既然我们已经构建并拟合了我们的模型,我们希望对训练数据和测试数据进行评分。你还记得我们之前把它分成了两个数据集吗?我们在训练数据集上“训练”或“拟合”了我们的模型。我们还将使用训练数据集对其进行评分,以查看它是否可以使用特征(X 变量)来确定我们的目标(y 变量)。

让我们给模型打分:

# Scoring Training data on TFIDFVectorizer
tvc_gs.score(X_train, y_train)#score: 0.8742193813827052# Scoring Test data on TFIDFVectorizer
tvc_gs.score(X_test, y_test)#score: 0.8627148523578669# Scoring Training data on RandomForest
rf_gs.score(X_train, y_train)#score: 0.9380648005289839# Checking Test score on RandomForest
rf_gs.score(X_test, y_test)#score: 0.881004847950639

貌似两款都表现不错!事实上,TFIDF 矢量器的性能优于 RandomForest。当我们查看分数时,我们希望训练分数和测试分数尽可能接近。在这里,RandomForest 的训练和测试分数之间的距离更大,而我们的 TFIDF 矢量器的分数几乎相同。我们可以看看这两个模型,看到 RandomForest 由于分数的不同而过度拟合。我们希望选择 TFIDF 矢量器作为用于预测的模型。

重要

所以我们知道哪种型号性能最好。它用来做那些预测的词呢?当使用管道时,我们需要“进入”估算器,从那里我们可以看到在进行预测时它发现什么特征(词)是最重要的。让我们用这个做一个数据框列,按最重要的排序。

tvc_title = pd.DataFrame(rf_pipe.steps[1][1].feature_importances_, tvc_pipe.steps[0][1].get_feature_names(), columns=[‘importance’])tvc_title.sort_values(‘importance’, ascending = False).head(20)

上面的代码将为我们提供一个数据框架,其中包含我们的模型用来进行预测的前 20 个最重要的单词。从这里,我们可以创建一些可视化来更好地表示我们的模型。

结论

根据上面的信息,我们可以得出结论,利用自然语言处理的能力,我们可以预测一篇帖子可能位于哪个博客主题,准确率为 88%。这怎么可能有用呢?从商业的角度来看,我们希望知道一个帖子是否会出现在我们的目标主题中,这样我们就可以关注最有可能看到该帖子的受众。我们还可以显示在生成预测时最重要的特征,并查看每个特征对我们预测的影响程度。

自然语言处理综合指南。

原文:https://towardsdatascience.com/nlp-with-spacy-part-1-beginner-guide-to-nlp-4b9460652994?source=collection_archive---------26-----------------------

带有空间的自然语言处理。(第一部分)

自然语言处理在几乎每个领域都有广泛的应用,在动手之前需要一定的深度知识。

Applications of NLP.

这是 spaCy 系列自然语言处理(NLP)的第一部分。下一篇文章给出了使用 spaCy 的 NLP 代码的基础知识。

简介:

我们都知道不断发展的技术以结构化的形式产生大量的原始数据,这些数据具有预定义的格式,可用于在数据库中搜索,如数字、文本等。另一方面,非结构化数据没有预定义的格式,不容易找到,这使得收集、处理和分析图像、视频、文件等变得更加困难。这些类型的数据每天都在生成,数量太大了 2.5 万亿字节的数据,而且刚刚开始加速。我从来没有听说过这个词“Quintillion”除非在网络上指出。

你知道吗??

代表百万的零的个数是 6,代表万亿的零的个数是 18。

百万-> 1000000

万亿->1000000000000000000

相当于每天产生10 亿千兆字节的数据。你可能想知道这是一个很大的数字。这是因为数据来自各个地方,比如用来收集购物者信息的传感器、社交媒体网站上的帖子、数码照片、视频购买交易、手机 GPS 信号等等。

问题是我们如何处理、分析和转换这些对我们有意义的数据,这有助于解决我们自己的需求和新的技术问题。

自然语言处理将有助于分析文本相关问题。因为这篇文章是关于 NLP 的,所以我们只关注它。其他类别的数据不在本文讨论范围之内。

您将从本文中学到什么:

  1. 什么是自然语言处理?
  2. 自然语言处理的子集。
  3. NLP 有哪些应用?

1.什么是自然语言处理?

在一系列算法和规则的帮助下,计算机能够理解人类并用大量人类语言与人类交流,并扩展其他语言相关的任务。使用 NLP,可以在更短的时间内执行某些任务,如自动语音和自动文本书写。由于大数据(文本)的发展,为什么不使用具有高计算能力、能够全天工作并且能够运行几种算法来立即执行任务的计算机呢?

继语音识别和视觉研究取得成功之后,自然语言处理是人工智能中最有针对性的研究领域。

虽然它是几十年前开始的,但大多数人缺乏 NLP 的经验。因为很难通过下面列出的挑战来训练机器:

  • 歧义:当一个单词有不同的意思或者一个句子在上下文中有不同的意思甚至一个句子指的是讽刺的时候就是挑战。

Lack of clarity in meaning.

  • 它包括歧义,分为两种类型:词汇歧义和句法歧义

词汇歧义是一个单词中存在两种或两种以上可能的意思。

句法歧义是在一个句子或单词序列中存在两种或两种以上可能的意思。

Source: ThoughtCo.

  • 句法:想想一个句子如何有效,它基于两个叫做句法和语义的东西,其中句法指的是语法规则,另一方面,语义是那个结构内的词汇符号的含义。人们改变句子的顺序,这在某些情况下是有效的,但不是所有的情况。

  • 共指:指同一个人、事物、国家..前面用代词提到的句子或短语。

Coreference.

  • 标准化:I t 是一种众所周知的技术,用于机器学习和深度学习。完成此步骤是因为数据具有不同的单位比例,并将这些值转换回相同的单位比例。在自然语言处理中,我们将非正式单词转换成标准形式,并使其适合于进一步处理。

Source: Slideshare.net

它包括规范来自社交媒体的文本、URL、文本表情符号、带有特殊字符的公司名称,例如 Yahoo!,还包括拼写错误的单词、标签、新单词和术语。标准化没有唯一的最佳方式。

为了完成这个任务,我们使用了 NLU 的形态学部分。

  • 讥讽:同字异义指歧义话题。假设有人做错了什么,你回答说非常好或做得很好。对于计算机来说,理解讽刺也是一个挑战,因为这与普通对话有很大不同。

Your Machine asks.

2.自然语言处理的子集。

当我谈到 NLP 时,它不只是一个。它包含嵌入其中的两个主题。自然语言理解(NLU)和自然语言生成(NLG)。

Source: Sciforce

Classification of NLP.

== >自然语言处理(NLP):

  • 这是一个将输入(非结构化)文本数据转换为人类可读格式并使用统计技术处理文本的过程。

== >自然语言理解(NLU):

  • 顾名思义,在任何建模和分析之前都要理解原始文本,只有在开始处理之前,机器才应该得到底层术语。
  1. 音系学:系统地组织声音的研究。
  2. 形态学:它是一门研究词的结构、构成、词与词之间的关系、构成事物、分析词义和词汇功能的学科。
  3. 语用学:它是研究如何使用单词、符号、标志和推断的意思
  4. 句法:是指将单词或词组排列成有意义的句子,遵循语法规则。
  5. 语义学:它关注的是单词的意义以及如何将单词组合成有意义的短语和句子。

== >自然语言生成(NLG):

  • 当计算机把数据从某种内在的表达形式写成有意义的短语或句子时。
  • 它包括——文本规划、句子规划、文本实现

文本规划:从知识库中保留相关信息。

句子规划:帮助选择完成有意义句子所需的单词。

文本实现:根据维基百科,实现也是自然语言生成的一个子任务,涉及到用一种人类语言(英语、法语等)创建一个实际的文本。)从语法表示。

3.NLP 有哪些应用?

Sentiment Analysis.

情感分析有助于公司从数据中了解利弊和见解,也能够对业务战略做出必要的改变。

Chatbots.

聊天机器人为客户常见问题提供标准解决方案,并为客户提供个性化帮助。

Virtual Assistants.

仅举几个应用,如文本分类、信息提取、语义解析、问题回答、释义检测、语言生成、多文档摘要、机器翻译、语音和字符识别等等。

结论:

  1. 自然语言处理是人工智能的一个子集,它负责教计算机理解人类语言并对其采取行动。
  2. 它面临着挑战,这些挑战既缺乏流程,也缺乏性能。
  3. NLP 包括两个子集,称为自然语言理解和自然语言生成,这有助于将文本处理到下一个级别。
  4. 这涉及到对语言学的大量学习和理解。
  5. 大量的应用比如情感分析、聊天机器人、虚拟助手等等,这些都有利于我们使用自然语言处理。
  6. 通过利用数据和高级计算硬件的力量,我们可以很快训练出模型。

就这样,希望你们喜欢 NLP 的总结。下一部分将使用 spaCy 对 NLP 基础知识进行编码。

快乐学习:)

参考资料:

  1. IBM "https://www . slide share . net/yun Yao Li/adaptive-parser centric-text-normalization"研究经理兼研究人员李云耀。
  2. Sigmoider,NLP 入门https://medium . com/@ gon . es buyo/get-started-with-NLP-part-I-d 67 ca 26 cc 828
  3. 阿玛·朱昆特拉,书名是《学问》,【https://www.slideshare.net/amarjukuntla/learning-93260612】。
  4. https://www . upgrad . com/blog/5-面向企业的自然语言处理应用/
  5. http://michealaxelsen.com/blog/?p=347

NLP 和 Python 的 NLTK 应用程序

原文:https://towardsdatascience.com/nltk-applications-for-nlp-and-python-dc8c5381668a?source=collection_archive---------20-----------------------

The Natural Language toolkit’s (NLTK) development started in 2001 by Steven Bird and Edward Loper of the University of Pennsylvania

上周我完成了一个朴素贝叶斯分类器,它决定了宋飞抑制你的热情剧本之间的区别。我开始利用自然语言工具包( NLTK )的一些功能,但是还有一些额外的部分我本来可以使用,这样可以简化我的代码并节省我的时间。我将在这里介绍 NLTK 的一些预处理和分析功能。

清洁

自然语言处理(NLP)最流畅的部分是清理原始文本数据。这个过程根据文本的内容和项目的总体目标而有所不同。文本分类项目和文本预测项目将具有完全不同的预处理步骤,因为文本的顺序在分类中并不像在预测中那样重要。上周我的项目的目标是根据它们所属的节目对抄本进行分类,所以我不需要维护每个文档中文本的顺序。

我最初的清洁功能很简单。首先,我用 regex 删除了 stage 注释,然后用一个自定义列表删除了文本中的一些标点符号,使所有文本都变成小写,用空格分割文本,删除字符朗读指示和停用词,最后返回文本。我没有借助 NLTK 的力量就做到了这一点。这个功能大部分是成功的,结果各不相同,因为文字记录是由不同的爱好者用不同的风格偏好写的。该函数最值得注意的问题是,它只删除指定的停用词,这意味着语料库的维数非常大。由于包含停用词而导致的高维度对于深度学习任务来说是站不住脚的,这意味着该功能将是不够的。

NLTK 库包含每种支持的语言的停用词列表(在撰写本文时,有 22 种支持的语言有停用词列表,您可以通过访问 nltk.org 或在您的本地机器上检查 *user/nltk_data/corpora/stopwords* 来检查它们)。您必须指定要使用哪种语言的停用词列表,否则 NLTK 将在您的分析中包括所有语言的所有停用词。在 python 中,你可以通过输入from nltk.corpus import stopwords来导入停用词表,通过输入import string来导入标点符号表。您可以将这些列表保存为自定义变量,以提取项目中不需要的字符。下面是更新的清理功能,它利用 NLTK 并指定只使用英语。

An updated text cleaning function that uses NLTK. Note that “English” is a parameter for the ‘stopwords’ method. Also, you can add or remove any stop word or punctuation mark included in the NLTK library, which makes customization easier.

完成清理步骤后,您可以继续进行词干化和词汇化。

分析

NLTK 还包括几个分析函数,允许您轻松地从语料库中计算重要的统计数据。例如,NLTK 有自己的令牌频率计数方法。FreqDist创建两个元素元组的列表,其中每个元组代表一个单词及其频率计数。您可以通过调用.most_common()方法来进一步访问最常见的元素。如果给定一个数字参数,该方法将按照降序返回文档或语料库中最常见的标记的数量。如果您要比较不同大小的多个文档,那么您可以对频率计数进行标准化,以便进行更合适的比较。

结论

NLTK 包含用于文本预处理和语料库分析的有用工具。您不需要为每个 NLP 项目创建自己的停用词列表或频率函数。NLTK 为您节省了时间,这样您就可以专注于 NLP 任务,而不是重写函数。

NLU 系列:建立理解人类语言的 Alexa 技能

原文:https://towardsdatascience.com/nlu-series-building-an-alexa-skill-which-understands-human-language-b63b82a273f?source=collection_archive---------37-----------------------

Photo by Rock'n Roll Monkey on Unsplash

(这篇文章也可以在我的博客中找到)

毫无疑问,人工智能已经出现在我们的日常生活中。从无人驾驶汽车到无收银商店,这个主题越来越自然地出现了。这两个例子是计算机视觉+机器学习的结果。它们是机器如何看待和理解主题的例子。但是,对机器来说,倾听和理解人类也很重要。一个例子是语音助手,像亚马逊 Alexa 。驱动语音助手的技术是 NLU,自然语言理解。根据维基百科,“自然语言理解(NLU)或自然语言解释(NLI)是人工智能中自然语言处理的一个子主题,处理机器阅读理解。自然语言理解被认为是一个人工智能难题

我正在写一个关于如何用 AWS 技术构建 NLU 应用程序的系列文章。在这篇文章中,我将展示如何建立一种能够理解人类语言并做出反应的技能。它可以部署在亚马逊 Echo 设备上运行,如 Echo show 5 、 Echo dot 或 New Echo 。

首先,我们需要了解 NLU 的基本情况。

意图

意图是对用户自然语言输入的响应。例如,在航空订票应用程序中。意图可以是预订门票、取消门票或查看门票详情。当用户输入进来时,NLU 需要分类以找到合适的(最有可能匹配的)意图。这依赖于训练基于话语的模型。

言论

话语是用户为了实现意图而向 NLU 输入的口头或打字短语。简单地说,这就是用户如何用语言表达他们的意图。例如“我可以预订一张从西雅图到北京的机票吗?”或者“我想买一张 9 月 19 日的票”。为了使 NLU 能够基于话语对意图进行分类,需要用预定义的话语示例来训练模型。

时间

语槽是实现意图所需要的话语中的变量。例如,在预订机票时,变量可以是出发日期、返回日期、目的地、出发城市。

创造技能

如果你还没有一个开发者账户,那就开一个吧。

然后开始创建自定义技能,选择“从头开始”。

创建一个意图

接下来,我们需要创建一个意图。在这篇文章中,我将建立一个可以告诉客户股票历史价格的技巧。我们添加了一个名为“股票报价”的意向,然后点击“创建自定义意向”。

如果没有要使用的内置,请添加插槽类型

接下来,我们必须为股票名称创建自定义插槽类型,因为没有这样的内置插槽类型。创建一个名为“STOCK_NAMES”的新槽类型,并给它一些值。为了简单起见,我在这里只添加了四个股票名称。

添加话语来训练模型

现在,我们将回到目的,开始使用新的槽类型来定义我们的槽(变量)。这里有两个槽,一个用于股票名称,另一个用于日期。它们的类型是“股票名称”和“亚马逊”。日期”分别。

我们将为该技能提供一些话语示例,以便它能够理解这一意图。然后点击“建立模型”,就会建立一个可以理解这种意图的自然语言的模型。含义相似但不一定相同的输入将被归类为股票报价意向。

如果你对这是如何存储的感兴趣,你可以点击“json 编辑器”,它以 JSON 格式显示模型。

{
    "interactionModel": {
        "languageModel": {
            "invocationName": "medium stock quote",
            "intents": [
                {
                    "name": "AMAZON.FallbackIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.CancelIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.HelpIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.StopIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.NavigateHomeIntent",
                    "samples": []
                },
                {
                    "name": "StockQuote",
                    "slots": [
                        {
                            "name": "stock_name",
                            "type": "STOCK_NAMES"
                        },
                        {
                            "name": "date",
                            "type": "AMAZON.DATE"
                        }
                    ],
                    "samples": [
                        "give me the {stock_name} price on {date}",
                        "what's the {stock_name} price",
                        "tell me the price of {stock_name} on {date}",
                        "can you tell me how much {stock_name} is worth on {date}",
                        "what's the price of {stock_name} on {date}"
                    ]
                }
            ],
            "types": [
                {
                    "name": "STOCK_NAMES",
                    "values": [
                        {
                            "name": {
                                "value": "facebook"
                            }
                        },
                        {
                            "name": {
                                "value": "microsoft"
                            }
                        },
                        {
                            "name": {
                                "value": "tesla"
                            }
                        },
                        {
                            "name": {
                                "value": "amazon"
                            }
                        }
                    ]
                }
            ]
        }
    }
}

验证模型是否能理解人类

点击调用,用人类语言测试。正如你所看到的,我使用稍微不同的短语来询问关于 face book 的股票价格,NLU 可以识别这是为了股票报价的意图,并正确地提取插槽。

到目前为止,我们已经成功地建立了一个理解人类语言的模型(分类以获得正确的意图)。在下一篇文章中,我将展示如何开发一个托管在 AWS lambda 上的端点来处理用户的请求。敬请期待!

如果你想了解更多关于机器学习的知识,educative.io 网站上有一系列课程很有帮助。这些课程包括像基本的 ML,NLP,图像识别等主题。

参考:

介绍亚马逊 Lex:构建语音/文本聊天机器人的服务——2017 年 3 月 AWS 在线技术讲座

自然语言处理实践:用 Python 理解、分析和生成文本第一版

以前的帖子:

我关于金融和科技的帖子

我关于 FAANG 访谈的帖子

全栈开发教程:将 AWS Lambda 无服务器服务集成到 Angular SPA 中

全栈开发教程:用运行在 AWS Lambda 上的无服务器 REST API 提供交易数据

全栈开发教程:在 Angular SPA 上可视化交易数据

强化学习:Q 学习简介

无代码数据管道:云数据融合的第一印象

原文:https://towardsdatascience.com/no-code-data-pipelines-a-first-impression-of-cloud-data-fusion-2b6f117a3ce8?source=collection_archive---------14-----------------------

云数据融合本质上是一个构建数据管道的图形化、无代码工具。它看起来像这样:

Cloud Data Fusion in action. GIF borrowed from Google’s announcement.

在本帖中,我将分享我对该产品的第一印象。这绝不意味着是一个完整的回顾——我只是触及了表面。希望您能了解什么是云数据融合,以及是否值得花时间仔细研究一下。

在深入细节之前,让我们考虑一下云数据融合的历史背景。

ETL /数据集成/数据管道的简史

如果你在 data scientist 成为 21 世纪最性感的工作之前在数据/分析领域工作过,你可能知道图形 ETL(提取-转换-加载)工具已经在企业数据仓库环境中广泛使用。事实上,如果你访问任何大型银行或零售商的总部,很有可能他们的数据仓库环境仍然被锁定在一些专有的图形 ETL 工具中,如 DataStage 或 SSIS 。

随着初创公司和大型科技公司的崛起——它们都严重依赖数据进行产品开发——代码(通常是开源的)对于构建数据管道变得更加重要。这方面的一个例子是气流在数据管道编排中的流行——无论是在初创公司还是大型科技公司。

谷歌已经通过 Cloud Composer 利用了气流的出现。

传统企业世界和勇敢的新技术世界之间的鸿沟,在这两个阵营的语言中表露无遗。企业人士称之为“数据集成”,而技术人员则称之为“数据管道”。

在云数据融合的营销中,谷歌使用了这两个术语,但“数据集成”如此突出并非巧合:

Cloud Data Fusion: Data integration FTW

谷歌正在寻求云数据融合的公司。他们的企业定价起价约为每月 3,000 美元,这进一步证明了这一点。

与此同时,即使在创业潮人中,也有一股大趋势朝着 #NoCode 发展(只需查看 Twitter 中的大量例子)。因此,谷歌推出云数据融合作为无代码数据管道产品的时机看起来很合适。

云数据融合入门

与大多数谷歌云平台(GCP)产品一样,云数据融合非常容易上手。您只需启用云数据融合 API,创建一个实例,并配置适当的 IAM 权限。在我的例子中,在asia-east-1区域中启动一个基础版实例需要大约 15 分钟。

一旦您的实例启动,确保您为服务帐户设置了权限,如这里的所述。

云数据融合方便地使用谷歌认证,当你登录时,你可以浏览一下界面。

快速补充说明:术语“数据治理”在入职培训中使用的事实进一步证明了 Google 的目标是企业:

Data governance — a term seldom heard in the startup world!

云数据融合有一个“枢纽”,在这里你可以获得单独的组件或完整的数据管道。一个简单管道的例子是他们的 quickstart,它读取存储在云存储中的《纽约时报》(NYT)的文章,解析和清理数据,并将 25 美元以下的顶级书籍加载到 BigQuery 中。

选择此管道(并可选地定制它)后,单击“部署”使管道可执行。

从那里,有一个“运行”按钮,您可以使用它来执行作业。如您所料,您还可以安排作业定期运行。

遇到的问题

下面是我在使用云数据融合时遇到的一些问题。如果我读过文档,我很有可能会发现这里到底发生了什么。如果从事云数据融合工作的人看到这篇文章,这些错误可能会成为人们可能遇到的问题。

When trying to output the schema of a BigQuery table.

Isn’t NUMERIC a fairly standard data type? And how do I get around the isse? I don’t understand how I can remove ‘difficulty’.

Looks like I’ve exceeded some kind of quota?

结论

总的来说,云数据融合真的感觉像是一个针对大型企业的产品,这些企业可能希望将他们的 ETL 工作转移到 Google 云平台。

我个人怀疑云数据融合会在创业公司中获得牵引力,但似乎很明显,这不是谷歌这款产品的目标受众。

对于传统企业来说,至少有两个原因可以解释为什么迁移到云数据融合是有意义的。

首先,每月 1-3,000 美元的价格很有可能低于企业数据集成领域的许多替代产品。看看的 DataStage ,了解一下竞争对手可能会收取多少费用。

其次,由于云数据融合建立在木桶数据应用平台(CDAP) 之上,因此锁定风险较低。具体来说,您可以获得可移植性,因为您可以导出您的数据管道,并将它们带到另一个支持 CDAP 的平台上。旁注:谷歌大约一年前收购了卡斯克(CDAP 的主要贡献者)。

你对云数据融合有什么想法?

Alex Svanevik,数据科学家 D5 —数据科学家

没有数据治理,就没有数据智能!

原文:https://towardsdatascience.com/no-data-governance-no-data-intelligence-9b45bf819638?source=collection_archive---------16-----------------------

Photo by Amanda Jones on Unsplash

任何大型传统公司都梦想成为像谷歌、脸书或亚马逊那样的公司,但有一点可以将互联网诞生前存在的前者与互联网诞生后的后者区分开来:它们天生就没有数据挖掘和机器学习的基因。

数据,资源变成了资产

对于现任者来说,数据是开展业务的信息技术(IT)资源,因此,它被委托给首席信息官及其组织来管理。后者的任务是建立全球数据架构,选择数据库供应商,并设计所有必要的应用程序来处理从数据库到业务和职能领导屏幕的数据。

我们经历了企业资源规划(ERP)时代来管理财务、供应链、物流和人力资源职能部门的数据。在 ERP 时代之后,我们进入了客户管理关系(CRM)时代来管理营销、销售、服务和支持数据。随后,互联网出现了,公司网站、社交媒体页面和可下载的移动应用程序开创了一个新时代。

与前两个时代不同,互联网时代产生了一种新型的数据和流程,与现有企业习惯的 ERP 和 CRM 数据完全不同。谷歌、脸书、亚马逊、优步和 Airbnb 天生就有先进的数据挖掘技术。他们分析的范围不仅仅是已经发生的事情,还包括正在发生的事情和可能发生的事情。这就是大数据和高级分析的全部内容。

与此同时,在任者的分析仅限于所发生的事情。这就是商业智能(BI)的含义。但此后情况发生了变化。现任者改变了他们对数据的看法,将数据从一种必要的资源变成了一种有价值的资产,并开始雇用数据分析专业人员,他们的头衔各不相同:统计学家、数据矿工、数据分析师、数据科学家……但现任者仍然落后于谷歌、脸书、亚马逊等已经处于深度学习时代的公司,这是一种类固醇数据挖掘。作为证据,我邀请读者看一看网上连续不断的公告。

细心的读者可能会问,尽管现有企业拥有跨越几十年的大型数据库(如零售商、银行和保险),并且最近在大数据和数据科学方面进行了投资,但为什么它们仍然落后?

对我来说,答案不在于处于黑暗中的现任者,他们的高管不知道他们的公司几十年来积累的内部数据的价值,也不在于他们的数据专业人员不如谷歌、脸书和亚马逊的专业人员了解。这是关于他们所拥有的数据的年龄、结构、格式、质量和多样性。在职者的数据比人们想象的要复杂得多。因此,像在线平台那样挖掘它来提取见解和预测,并不是自动的。为了达到在线平台的复杂程度,现任者别无选择,只能添加数据治理,作为对数据管理和数据科学的补充,如下文所述。

数据治理,数据科学的必备工具

像任何新的首字母缩写词一样,人们对它的定义没有一致的看法。为了获得一个直观的想法,想象一下数据科学家为每个项目所做的所有数据准备工作,并想象所有这些工作只做一次,并定期为所有项目更新。这是数据治理在发挥作用。

在分层数据架构中,数据治理位于数据管理(也称为关系数据库、大数据、ETL、云存储)之上,数据科学(也称为统计建模、预测分析、机器学习)之下,至少涵盖以下功能:

  • 摄取、集成和协调来自所有数据库的数据,这些数据库构成了公司的数字神经系统。根据公司的行业和业务,数字神经系统可以由数字流程组成,这些数字流程将公司的思想和行动的每个方面(财务、生产、客户等)紧密联系在一个系统中(罕见情况)或分成多个互连的系统(常见情况)
  • 从数据捕获到面向客户的应用程序(客户关系管理)到后台应用程序使用数据(分析、报告),对数据质量进行测量和跟踪
  • 数据隐私法规的应用(例如,GDPR、加州消费者隐私法、纽约州隐私法)以及特定于公司行业的任何其他法规,如医疗保健、银行和保险
  • 引用所有外部数据(购买的或开源的),旨在将其与客户数据交叉,以推断公司营销部门的洞察力
  • 网络安全是公司面临的最大威胁,现在几乎所有面向客户的活动和后台活动都是数字化进行的。对我来说,网络安全即使不高于数字化转型和业务数据化,也应该处于同样的优先级别

顾名思义,数据治理的技术性不如数据管理和数据科学。这一级的大部分工作是组织性的:定义过程,并非所有过程都是自动化的,以及决定考虑哪些数据、以何种顺序、如何管理数据、在数据缺失的情况下如何做、如何推断、何时以及如何更新数据以保持数据总是准确、最新和高质量的委员会,等等。正如这些任务的例子所显示的,这并不是因为它听起来不如数据科学迷人,所以应该被忽略。

正如定期报道的那样,大多数数据项目确实被卡住了,不是因为他们没有合适的数据科学家或合适的模型和算法。在报告的案例中,这是由于数据可用性、质量或多样性的问题。数据准备通常是数据挖掘项目中最耗时的部分。因此,制定出一个服务于广告、营销、销售和客户关系管理或财务、供应链、运营和人力资源的所有项目(当前和计划中的)的数据治理策略将会更加有效和高效。

现在我已经定义了数据治理,让我们看看如何构建一个数据战略,使现有企业达到谷歌、脸书、亚马逊等公司的成熟水平?

数据分层架构

分层架构允许将数据呈现到一组层中,其中每一层都服务于上一层并指导下一层。与其说它是一个技术栈,不如说它是一个代表性的视图。

数据战略层面:在最高层,应该是定义哪些数据对公司有价值的企业数据战略。并非所有的企业都是平等的。对一些人来说,要考虑的最重要的数据与广告、营销、销售和客户关系管理有关。对其他人来说,它与财务、供应链、物流、运营和人力资源有关。然而,对其他人来说,数据是一种可以赚钱的产品。

函数级:数据策略级下面,应该是函数。例如,如果数据与广告、营销、销售和客户关系管理功能相关,则这些功能可以是:

  • 计算广告归属,优化媒体规划,分配广告预算
  • 改进直接营销活动
  • 利用现有客户了解潜在客户
  • 降低信用风险
  • 交叉销售、追加销售和推荐
  • 减少客户流失
  • 预测销售额

数据科学级:低于职能级,应为数据科学级。正是在这个层次上,公司将模型定制或开发为服务于功能目标的算法。在同一个例子中,数据科学家将帮助回答以下问题:谁将保持忠诚的客户,谁不会?哪些信息在哪些时段、哪些日子最有效?如果媒体预算一半用于电视,另一半用于户外,会怎么样?

要回答这些问题和其他问题,需要依靠来自公司数据库的高质量数据,这正是数据治理发挥作用的地方。没有数据治理,即使最复杂的模型和算法也不会有效。正如现在所承认的,数据科学的力量更多地存在于高质量的数据中,而不是复杂的模型中。

数据治理级别:在数据科学级别之下,数据治理使数据科学家能够确保使用最高质量的数据,因此不会在无用、过时或不可行的数据上浪费时间。如果工作已经完成,那么数据科学的数据准备将比没有数据治理的情况短得多——如果没有数据治理工作,数据准备估计会吃掉高达 80%的数据项目。

数据管理层:数据治理层之下是所有传统和新的数据技术,从关系数据到大数据,再到云上的数据。It 部门应该根据数据治理定义的标准来调整架构、提取-转换-加载流程以及数据库之间的管道。

总结

所有大型传统公司都梦想成为谷歌、亚马逊或脸书,但它们的 DNA 中并没有天生的数据挖掘和机器学习功能。他们需要将数据治理添加到他们的数据源策略中,以达到数据挖掘和机器学习有效所需的质量。

数据治理应该位于数据管理之上,以所需的质量、安全性和一致性需求来指导 it,并位于数据科学之下,以减少数据准备的时间和成本。因此,所有数字化转型和业务数据化计划都应该包括数据治理层。这样的大型程序构成了处理这一层的最佳机会,没有它就没有数据智能。

关于作者

技术、创新和转型方面的战略顾问和过渡执行官,在广告、营销、销售和客户关系管理的数据和技术方面拥有丰富的经验。

本文受益于为顶级消费者研究公司、数字和数据机构、消费品/快速消费品零售商、奢侈品和美容品牌以及大型相互保险公司所做的战略和实施工作。

欢迎评论。请将它们张贴在此处,以私人消息的形式发送,或通过电子邮件发送到 hbmjpartners dot com 的 hlaasri。

数据#战略#数据科学#数字转型#分析

没有数据集?没问题。自己刮一个。

原文:https://towardsdatascience.com/no-dataset-no-problem-scrape-one-yourself-57806dea3cac?source=collection_archive---------17-----------------------

啊…网页抓取。我敢肯定你听说过它,你可能已经这样做了,或者至少想过这样做。

Photo by Markus Spiske on Unsplash

我已经做过很多次了。见鬼,几个月前,我在一个本地数据科学会议上做了一个报告,主题是将数据科学用于房地产市场分析。

前 30 多张幻灯片是关于网络搜索的,以及我如何搜索最受欢迎的本地房屋买卖网站。观众中有这样一个人,他在演讲结束时的问答部分做了自我介绍,他是那个网站的经理之一。

呀。

不用说,这次谈话不太愉快。所以这里的要点是——小心使用网络抓取,它会让你很快陷入麻烦。

“那我为什么还要考虑网络抓取?”

我很高兴你问了。主要原因是——在现实世界中很难找到好的数据集——有时自己制作一个更容易。

就像我的情况一样,有一些关于房价的数据集,但没有一个与我居住的国家有关,当然也与我所在的城镇无关。网络抓取是唯一的出路。

为什么你应该考虑网络抓取的另一个好理由是下面的— 做起来很有趣!当然,在你学会正确的语法之前,你会不断地敲打自己的脑袋,但是几次之后,这真的变成了一个令人愉快的过程。

‘好吧,好吧,说重点!’

这足够做一个介绍和基本的推理了。

在开始网络搜集之前,请务必阅读这篇关于网络搜集中的道德规范的精彩文章。

现在,让我们进入正题。

寻找要刮的网站

今天早些时候,我努力寻找一个体面的页面刮除。不是说没有——肯定有——但是,你怎么说呢,让我向你展示如何从 CNN 抓取文章并不是最合法的事情。

然后我偶然发现了这一页——要刮的书——这确实是展示刮是如何工作的最好的地方,没有人会生气。

当你打开这个页面时,你会在左侧看到主题浏览器,当你点击其中任何一个,你会被重定向到包含该主题书籍的网页。

顺利!

点击“旅行”,网址将变为:

[http://books.toscrape.com/catalogue/category/books/**travel_2**/index.html](http://books.toscrape.com/catalogue/category/books/travel_2/index.html)

我真的不知道他们为什么需要加上' _2 ',但事情就是这样。点击了几个主题类别后,我列出了以下列表:

  • 旅行 _2
  • 谜 _3
  • 音乐 _14
  • 诗歌 _23
  • 幽默 _30

你可能已经猜到了,这是一个主题列表,我将会得到这些主题的书籍。以下是《旅行》中第一本书的样子:

A book thumbnail obtained from http://books.toscrape.com

这就是每本书的样子,这意味着我必须有一些方法来获得感兴趣的数据,这些数据是:

  1. 主题
  2. 标题
  3. 评级
  4. 价格
  5. 有效性
  6. 图书 URL
  7. 缩略图 URL

第一步。查找 HTML 标签及其类别

等等,什么?我需要了解 HTML?

就一点点。对你来说,知道最基本的 HTML 标签就足够了——这很容易被谷歌搜索到——所以我不会在这上面花时间。

现在打开这个链接就能看到“旅游”类别的所有书籍。按下 CTRL + SHIFT + I 启动开发者控制台。在这里,您可以检查并进一步深入任何 HTML 标签。

我已经通过右键单击其中一本书并按下 Inspect 进行了操作。所以现在开发人员控制台看起来像这样:

Developer Console after Inspecting the Book

你看到这个 文章 标签了吗?这是这个网页抓取过程的基线。在这个标签中包含了上面列出的 7 个点的所有数据。你可以通过点击箭头图标展开某个标签来找到它们。

如果你不想深入研究,以下是列表:

  1. 标题:H3->-T20(标题属性)
  2. 图书链接:div(classimage _ container)->-a(hrefproperty)
  3. 图书缩略图:div(classimage _ container)->img(srcproperty)
  4. 等级 : p (等级星级 ) - > ( 等级属性)-最后一项
  5. 价格:div(classproduct _ Price)->p(classPrice _ color)
  6. 供货:div(classproduct _ price)->p(classin stock 供货)
  7. 主题 —将从 URL 中提取

好了,现在你什么都知道了!嗯,除了如何把这变成一个有意义的代码。这就是下一节的内容。

第二步。编写一个抓取脚本

这是这个想法的大纲。您需要编写一个脚本:

  • 接受主题列表作为参数
  • 基于提供的主题参数生成完整的 URL 列表
  • 打开每一个 URL,提取主题中每本书的 7 个兴趣点
  • 将结果保存到字典中
  • 为用户提供一些基本的信息
  • 返回填充字典的熊猫数据帧表示

‘但看起来工作量很大……’

我知道,相信我。我已经编写了获取 100 多个属性的脚本,所以这个对我来说不是什么大问题,但是如果这是你的第一次,可能会有问题。

幸运的是,每次的想法都是一样的。标签和类别会变,但理念不变。

哦,差点忘了给你提供必要的进口( facepalm )。他们在这里:

import datetime
import numpy as np
import pandas as pd
from collections import OrderedDictimport requests
from bs4 import BeautifulSoup

我现在要用整个剧本来抨击你——一开始可能看起来有点吓人,但我相信你:

Web scraping script — https://gist.github.com/dradecic/2cf982730b0f9f1666a0117c9987ffe9

我真的尽力解释了里面的每一行代码。现在该由你来深入研究脚本,看看为什么一切都是这样进行的( 剧透警告 :这真的没有那么难)。

第三步。享受成果

现在,运行这个脚本并将结果存储在一个变量中是世界上最简单的事情:

Calling get_books function

这很快。从更大的网站抓取更多的内容有时需要几个小时,所以不要习惯这种 0 秒完成的事情。

现在,您可以检查新创建的数据帧的外观:

Scraped DataFrame

最后的话

恭喜你。你刚刚获得了一项新技能。我认为这是任何有抱负的数据科学家的基本原则。但是记住这一点,

能力越大,责任越大——蜘蛛侠本·帕克

所以明智地使用你的新技能,不要让自己陷入困境。

直到下一次…

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

[## 通过我的推荐链接加入 Medium-Dario rade ci

作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…

medium.com](https://medium.com/@radecicdario/membership)

没有智能储能,就没有快速(足够)的能量转换!

原文:https://towardsdatascience.com/no-fast-enough-energy-transition-without-intelligent-energy-storage-72cfbd3c096b?source=collection_archive---------25-----------------------

人工智能和能量存储快速需要强耦合,以便针对激烈的气候变化与可再生能源进行有效过渡

Credit: Photo by Adrian Schwarz on Unsplash

AI 现在越来越多的用于市场(数据)分析,用于政治预测或者用于无人驾驶汽车运营等。这可能在政治上,经济上,甚至科学上都很有趣,但是我们在更危急的情况下需要人工智能。在人类无法独自解决的挑战中,我们正面临着全球性的威胁。无论是与医疗“对抗”(疫情病毒或癌症扩散),还是增加我们金融系统的弹性或稳健性,或是预测风暴或恶劣天气事件。人工智能就像是我们大脑的延伸,我们需要它来帮助我们。

但是有一个挑战压倒了我们,那就是气候变化。而且它发生的速度比我们想象的要快得多!因此,我们需要在人工智能和能量存储之间建立密切的关系,以确保所需的能量转换跟上全球变暖加速的步伐。

[## 气候危机引发了激烈的争论。只有激进的措施才会奏效

全球变暖将要求我们的生活方式发生巨大变化

www.theguardian.com](https://www.theguardian.com/environment/2019/may/18/climate-crisis-heat-is-on-global-heating-four-degrees-2100-change-way-we-live)

Credit: Photo by h heyerlein on Unsplash

人工智能,服务于能源转型?

虽然人工智能多年来一直在能源领域取得进展,但许多人担心,有一天,它可能会妨碍人类日常生活中的行为。这些恐惧激发了许多像《黑客帝国》这样的电影。它令人着迷,但也令人恐惧,几乎令人恐惧!

但是今天,这些恐惧有了新的转变,它们来自另一个根源。一些报告显示,62%的全球温室气体排放(GHG)直接或间接归因于材料和能源的提取和加工,这些材料和能源构成了我们的消费产品、服务和生计,它们在很大程度上依赖于“所谓的”无限资源。

[## 格陵兰岛的冰盖在不断扩大。现在,它正以惊人的速度下滑

格陵兰冰盖的融化速度是 20 世纪 80 年代的 6 倍。所有的融水都直接抬高了…

www.livescience.com](https://www.livescience.com/65302-greenland-ice-melting-so-much-faster.html?jwsource=cl)

为了对抗这种 GHG 污染,有必要彻底审查我们的经济和消费模式,重新思考我们的产品(生命周期、生产、寿命终止)或能源来源和分配。这一次,随着对人工智能在某些领域的重要性的理解,我们可以将其视为解决方案,而不是可怕的事情。在能量转换中尤其如此。人工智能简化了这种高度复杂的过渡,尤其是节省了宝贵的时间!

不管怎样,如果我们不改变解决问题的方式和方法,那不仅仅是一场对抗气候变化的战斗,而是一场战争。从各方面来看,我们都处于弱势。一个主要原因是能量转换的速度(有点)慢。我们无法满足能源需求。这就是为什么人工智能如果使用得当,可以增强我们应对这一威胁的能力。

Credit: Intelligent Energy Storage (CC BY-NC-SA 2.0), © Smart Phases Inc. (DBA Novacab) https://flic.kr/p/2eJYwpE

能源转换的长期性

温室效应和气候变化的长期、复杂动态,化石燃料长达几个世纪的路径依赖、持续使用或路径依赖,锁定战略,现有能源行为者和机构的应对和不稳定,甚至公平和正义问题,都是许多相关挑战的基础,并增加了国家和全球(公共或私人)治理解决这些挑战的难度。

因此,历史专业知识可能会增强我们的理解,许多研究表明,摆脱当前的全球能源系统是至关重要的,包括牛津大学的 Sovacool 或 Grubler 令人信服地写道,“下一次能源过渡的必要性是显而易见的,因为当前的能源系统在社会、经济和环境标准的所有方面都是不可持续的”。芙凯曾指出

“能源转换相对罕见且旷日持久的性质意味着,从历史经验中寻找未来可能如何发展的教训至关重要。”

此外,通常情况下,转型会持续很长时间或比预期的时间更长(“持久”的性质),他概述说,这里观察到的最快的历史能源转型是三十年(在特定部门的情况下)。一个特定部门需要 30 年,而涉及所有部门和服务的全面(或大规模)能源转型需要更长的时间。在气候变化不可逆转地超过 1.5-2.0 摄氏度的门槛之前,我们没有足够的时间来应对气候变化。

[## 联合国警告说,我们有 12 年的时间来限制气候变化灾难

IPCC 称,迫切需要改变以降低极端高温、干旱、洪水和贫困的风险

www.theguardian.com](https://www.theguardian.com/environment/2018/oct/08/global-warming-must-not-exceed-15c-warns-landmark-un-report)

由能源转换历史研究确定的几个问题领域,提出了关于能源转换的性质、多样性和复杂性的知识发展的重要而棘手的问题。它们包括许多种“小调”和“大调”(或“大”)转场之间的区别。这对我们理解过渡的规模、速度、持续时间、平滑度和(不)连续性或其他“特殊”属性的能力,以及对我们指导或管理它们的能力,都是很重要的。事实上,研究表明,能源服务的价格在创造刺激能源转型的激励措施方面发挥了至关重要的作用。但另一个关键因素是新技术是否为消费者提供了新的价值特征,即使初始价格更高,这也有助于创造一个市场。相反,可能推迟转型的一个关键因素是现有行业和衰落行业的反应。然而,政府已经,在几个(只是几个!)的例子,创造了监管环境,以刺激能源向低污染能源的过渡。是的,这可以再做一次,但前提是政治意愿与替代能源项目同时存在。

人工智能和专家系统的巧妙结合

智能人工智能和可再生能源储能的巧妙结合可能会起到催化剂的作用,刺激导致某些能源转换的过程。过去的能源转型对衰落的现有产业产生了重大影响,但也改善了能源独立、经济转型甚至不平等。这就是我们需要用创新的理论和方法,以可持续发展的方式在更大范围内复制的东西。

根据颇具影响力的可持续发展转型研究网络的研究议程,该领域的研究认识到,许多环境问题需要在人类活动和社会的关键领域进行深刻的结构性变革,包括能源系统。它断言,一个密钥:

“可持续发展面临的挑战是,现有系统往往很难被‘驱逐’,因为它们被各种锁定过程所稳定,导致路径依赖型发展和‘陷阱’”。

能源电网的转型、新服务的出现、新参与者: prosummers 、consumer ' actors以及自我消费等新模式,改变了电网本身的运营要求和约束,并对日益庞大的数据进行管理,如果不求助于人工智能,这些数据将无法工作。智能电网这个术语已经出现了很多年。它承诺电网将适应新的用途,更有弹性,更高效,一言以蔽之:智能。

Credit: Intelligent Power Generation Control (CC BY-NC-SA 2.0), © Smart Phases Inc. (DBA Novacab) https://flic.kr/p/Sbb1K4

踢(AI)轮胎!

理解指数增长潜力的另一种方法是用现在可用的多种方法之一来实践这项技术。你无法想象它是如何在数量惊人的主题上工作的,以及这个生态系统如何真正感觉像一群拓荒者在清理土地,等待被征服。你必须触摸它,尝试它,踢轮胎!就在几年前,在我的领域,在能源领域,通过储能或人工智能获得的收益似乎是无法实现的。你现在可以找到许多有效使用人工智能的用法和技术。所有这一切都取决于有能力塑造这些算法。因为,我们经常考虑人类的教育,但是人工智能的无限学习曲线。我们更喜欢务实和具体的方法,在前进的时候让我们慢下来。这种人工智能的能源转换就像 30 年前在商业中使用计算机和数据库一样重要。

世界上有很多这样的例子。这一术语不仅适用于电力,它还被称为智能燃气电网、智能水电网、智能区域供热甚至智能工厂网络或电网,所有规模的电网都受到关注。然而,特别是在今天,智能电网是没有真正学习能力的自动化网络,这是掺有人工智能的真正智能网络的前提。

Credit: AlphaGo Zero: Learning from scratch, © DeepMind Technologies Limited https://buff.ly/2vcRdDK

如果我们将这些智能电网的人工智能成熟度与人工智能游戏的成熟度进行比较,我们目前更接近于 IBM 象棋游戏人工智能( DeepBlue ,1997),而不是谷歌围棋游戏(deep mind 博客中的 AlphaGo Zero 或自然界中的 alpha Go Zero,2017)。可以看看 alpha go“The Film”踢踢轮胎!亲眼看看人工智能学习曲线的一个例子。

日益增加的复杂性

你可以想象这样一个智能工具在能源领域会产生什么样的影响。在部署中,智能储能( IES )的集成甚至更早。具体而言,智能电网和储能的“真正智能”集成所面临的挑战是应对能源消费者和生产者的新需求,以及他们的状态和运营所需的大量数据。直接影响是能源网络的复杂性急剧增加。复杂性的增加是个好消息!它告诉我们,我们正在进行或实现我们的能量转换。

真的开始了,但还没实现。这种转变导致了几次破裂。以我将在本文中重点讨论的电网为例,我知道它适用于上述所有其他类型的智能电网。第一次颠覆是从分层不对称网格向一组分布式动态网格的转变。我们从发电厂生产能源并分配给消费者的模式转向每个人都可以自己或在社区内生产、消费、销售、购买甚至自我消费的模式。简而言之,新的网络模型是一个动态的分布式模型,其中每个人都可以是个人、城市、个人或城市的社区、行业或中心。

Peak shaving, load shifting, valley filling, conservation while the total load is growing

第二次破裂是从变化很小的接近恒定的生产转变为与可再生能源(ENR)和必要的能源储存相关的大量间歇和致命的生产。

第三个是电网运营商对电网的部分失控,原因是出现了有自己平衡逻辑的新用途:电动汽车、自耗社区等。这一切都需要完成,同时还需要调峰、移载、填谷、节能,因为总负荷仍在增长。这导致了电网结构的流量和孤岛的出现,矛盾地加强了平衡全球网络的需要。

天才工具

有些人正在用一种简单的方式来定义人工智能是“能够以相关的方式学习和决定的软件”。其他人会说它是“一套开发复杂计算机程序的理论和技术,能够模拟人类智能的某些特征(推理、学习……)”去年一月在达沃斯举行的世界经济论坛讨论了不同的主题(参考文献。EnergyVoice )包括人工智能在真正目的驱动的技术开发中的能源转换中的用途。有人解释说,人工智能可以促进产品的生态设计,更好地将可再生能源纳入能源组合,简化新商业模式的开发,新商业模式的设计将更加节能,特别是管理(和减少)大规模的各种废物。人工智能可以允许快速发展有利于能源转型的可实现的循环经济,而且有紧迫性!

Credit: Realizing the Energy Transition (CC BY-NC-SA 2.0), © World Economic Forum / Ciaran McCrickard https://flic.kr/p/2dgYGyN

而且,它可以帮助应对最大的挑战,并确保扩大规模是可以实现的。引领低碳能源转型所需的复杂技术网络需要能够扩大规模,以适应全球需求。这方面最突出的例子之一是大规模和长期的能量储存。具体来说,人工智能会在关联数据之前快速计算出许多数据,从而使它们变得可用。

现在几乎每个人都清楚,人工智能本身不是一个简单的话题,而是一个影响每个可以想象的领域的天才工具。将能量存储与 AI(智能能量存储)进行优化集成,以高效地执行清洁能源的能量转换是一条自然的前进道路。这将“扰乱”传统方式,但这种结合有可能解决最大的(指数级增长的)挑战。解释组合工具这种指数能力的一种方式是,随着世界变得日益复杂,人工智能算法在处理高度复杂和非线性的情况时极其有效。没有从 IES 中获得的优化,能量转换不能做得又好又快,返回不再是一个选项!在“组合效应中,工业企业还可以帮助满足偏远地区的某些短缺,从而减少地域不平等。

因此,IES 是一种新的解决方案,既能减少我们对环境的影响,又能将可持续发展完美地融入全球经济。

快速可靠地控制能源消耗和生产

因此,人工智能可以适应电力行业的许多行业,如果不是所有行业的话。但是这是怎么回事呢?当用于生产或能源消耗时,人工智能可以通过传感器工作,这些传感器安装在控制系统中。这些传感器可以分析任何数据,例如温度、振动或流量。

这允许数据的实时处理。由于这一点,系统的异常或故障检测和支持更快。一旦问题突出,有缺陷的系统或设备可以被替换,这最大限度地提高了能源效率,同时避免浪费(例如:蒸汽管线泄漏或太阳能电池板或存储模块间歇性故障)。

很快,人工智能甚至能够检测微弱的信号,分析组件的过时情况,并在醒来时推荐它!系统的维护将得到优化,生产不会中断。

简而言之,人工智能代表了更好地考虑能源过渡的真正解决方案。它的主要优点是:它适用于不同的行业。此外,想法融合推动它,使它总是更优。

电网现代化战略的工业工程

IES 可以帮助运营商或监管机构建立多年的转型电网现代化计划。重点是能力建设,从增强态势感知到部署智能基础设施。工业工程师确保大规模和分布式可再生能源的整合以及成为客户未来的电网是未来战略的核心原则。这是一个复杂的集成计划,包括分析、客户授权、DER 和批量可再生能源管理、集成系统、网络自动化以及物理和网络安全。因此,对于智能电网部署,ie 应该从一开始就存在。这意味着探索互联客户市场,交易能源的未来可能会是什么样子,以及像纽约州改革能源愿景或加利福尼亚州 AB 2868 这样的创新监管是否会对其他管辖区产生影响。

[## 改革能源愿景(修订版)

改革能源愿景(REV)是州长科莫为纽约州制定的全面能源战略。REV 帮助消费者…

rev.ny.gov](https://rev.ny.gov/)

通过严格的假设、敏感性和情景分析,人工智能为公用事业开发商业案例,以确保对新技术的投资得到优化和加速,并确保为未来的可再生能源项目很好地整合了能源存储。

Credit: Optimizing power generation with Hybrid Energy Storage and AI (CC BY-NC-SA 2.0), © Smart Phases Inc. (DBA Novacab), https://flic.kr/p/SbanLV

2018 年,法国议会议员、著名数学家塞德里克·维拉尼(Cédric Villani)提交了一份议会报告,严肃地命名为 ,赋予人工智能 一种意义。在一个由七名专家组成的团队的包围下,他质疑了法国和欧洲在人工智能方面的战略:

“像许多在 20 世纪 90 年代开始职业生涯的数学家一样,我深深低估了人工智能的影响,在那个时候,人工智能最终给出了很少的结果,……在 2010 年代见证其性能的惊人改善是多么令人惊讶。[……]此外,近年来,没有人能够逃避这个主题的多样性,因此他在经济和社会讨论中变得无处不在,”Cédric Villani 在他的前言中说。

Credit: Photo by Steve Halama on Unsplash

在全球减少碳足迹的优先目标方面,报告建议将人工智能的努力集中在两个领域:优化运输模式和向更合理和污染更少的农业过渡。

怎么会?维拉尼甚至提出了一项行业政策,这将产生不可忽视的质量效应,并构成能源转型的一大进步。与此同时,不要忘记对接收这些特殊工具的数据中心产生的热量进行系统化回收!因为有了明天的人工智能,任何东西都不会再丢失了。

好的一面是,人工智能和能源存储也带来了生态和能源转型方面的一整套解决方案。2018 年议员维拉尼的报告补充道:

“人工智能为理解和保护环境开辟了全新的视角。无论是在识别和保护生物多样性、修复损害、模拟我们行动的影响、优化资源利用、开发可再生能源方面,人工智能都可以帮助减少我们的所有消耗,并放大我们的所有行动。”

这是一个好消息,但我们不能等待政策开始将这些创新技术整合到我们的电网中,无论是大电网还是小电网。这也将极大地有助于在日益增加的(强度和发生率)风暴、火灾、干旱、洪水和其他气候变化影响面前快速提高电网的弹性;不仅改善二氧化碳排放,还改善能源效率、独立性和响应能力,尤其是在偏远社区。能量转换需要尽快进行。现在是我们“奋力”建设未来的时候了。

所以,热身你的生物神经元吧!

前方可能会有一场“快速而激烈”的能量转换!

Photo by toine Garnier on Unsplash


这篇文章是荷兰国际集团的夏羽·比洛多关于人工智能和能量储存的系列文章的一部分。工程博士,对外经济合作中心。智能阶段首席技术官( Novacab )、加拿大工程师协会会员和能源中心专家撰稿人。

您可以在此找到其他文章:

[## 人工智能在一个“别无选择,只能让它聪明”的能源行业!

可再生能源的繁荣对电力部门来说是一个很好的机会&用聪明的方式对抗气候变化…

towardsdatascience.com](/artificial-intelligence-in-a-no-choice-but-to-get-it-smart-energy-industry-1bd1396a87f8) [## 组合效应对抗蝴蝶效应

人工智能促进储能,为可再生能源提供弹性和效率…

towardsdatascience.com](/the-combo-effect-against-the-butterfly-effect-bf7dd7a507a0)

没有人能打败 AlphaGo,这是一件好事

原文:https://towardsdatascience.com/no-human-can-beat-alphago-so-what-3401b40fa0f0?source=collection_archive---------17-----------------------

为什么围棋大师李世石不应该为输给 AlphaGo 感到遗憾

Photo from Netflix

韩国围棋大师李时斗最近宣布退出职业围棋比赛。原因?他觉得无论自己怎么努力,都赢不了 AlphaGo 这样的 AI 围棋手。这是他在与谷歌 DeepMind 的 AlphaGo 的竞争中历史性失败的一个相当可悲的决定和发展。这给了整件事情一个更戏剧性的基调。然而,人类围棋选手输给 AI,对围棋比赛和人类棋手来说,都不是世界末日。恰恰相反,我认为这可能意味着围棋游戏的一个全新篇章,也是我们回到围棋游戏发明初衷的一个机会。

AlphaGo 对李时斗

Photo from androidheadlines.com

F 或者那些不熟悉发生的事情,据维基:

AlphaGo 对 Lee Sedol ,也被称为谷歌 DeepMind 挑战赛,是 18 届世界冠军 Lee Sedol 和 AlphaGo 之间的五局围棋比赛,AlphaGo 是由谷歌 DeepMind 开发的计算机围棋程序,于 2016 年 3 月 9 日至 15 日在韩国首尔进行 AlphaGo 赢了除了第四局以外的所有比赛;【1】所有比赛都是靠辞职赢的。这场比赛被拿来与 1997 年深蓝和加里·卡斯帕罗夫的历史性比赛相比较。—维基百科

除了看似戏剧性的失败,李时斗实际上是唯一一个真正打败 AlphaGo 的人类棋手,即使只有一场比赛。但这次失败深深伤害了这位人类围棋大师的信心,他在首尔接受韩联社采访时说:

“随着人工智能在围棋比赛中的首次亮相,我意识到即使我通过疯狂的努力成为第一,我也没有达到顶峰,”李说。“就算我成为第一,也有一个实体是无法被打败的,”

为了纪念他的退役,他计划与韩国 NHN 娱乐公司开发的另一名人工智能围棋手 HanDol 进行比赛,Han dol 已经击败了 5 名韩国顶级围棋手。

那么,如何看待所有这些呢?这是否意味着围棋手不再有价值,因为人工智能已经可以做得更好了?既然人类永远赢不了机器,围棋就不值得玩吗?这是否意味着人类智慧的终结和人工智能统治人类的开始?答案是一个响亮的不,但要问为什么,我们需要回到最初的围棋比赛。

围棋游戏的起源

Go is a very ancient game. It’s said that Emperor Yao(尧) of ancient China invented the Go game to teach his naughty son. His son DanZhu(丹朱) was very combative, yet refused to read any book his parents throw his way. How do you talk sense into this kind of kid? Well, entice him to play games of course! It turns out, DanZhu enjoyed the Go game very much. The competitive nature of the game plays into his combative personality, yet to win consistently, he needs to be more patient, smart and strategic. So he gradually learned all these and his parents were much happier. It’s a rather old and simplified story, but it tells one thing: Go is not created to see who is the best, it is created for educational purposes. I’ve learned to play Go when I was 12 years old and I still remembered our teacher telling us:

“要赢得围棋比赛,你需要擅长计算当前的棋步,同时也要考虑长远。你需要积累一些小的优势,但永远不要忘记大局。你需要足够的勇气在需要的时候打一场漂亮的仗,但如果你知道你赢不了,也不要太鲁莽。当你落后时,你需要有耐心等待最佳出击时机。当你领先时,不自满和犯错就更难了。做到这些,你就可以开始在围棋比赛中竞争了”

这个游戏有如此多的深度和如此高的“技能上限”,没有人可以声称他已经掌握了它。据说那是天堂里的人玩的游戏。抛开神话不谈,围棋作为一种游戏,绝对可以塑造一个人的性格,磨砺他的心智,强化他的意志。所有这些都比赢得比赛本身更有价值。

围棋是一种交流方式

There is an old saying in Chinese that goes “a person’s Go game style echos his personality(棋如其人)”. It’s easy to hide one’s true nature under well-organized words, but it’s much harder to hide when you’re in a fiercely played game. Go game used to be part of the interview process when ancient Chinese emperors hire his officers. It’s also a way to communicate. Since it’s very popular in ancient China, anyone knows how to read knows how to play Go. Engaging in a healthy competitive Go game is the fastest way to know another person. From your opponent’s playstyle, you’ll quickly know what kind of person he is. Is he conservative and not taking any risks? Is he used to follow some textbook moves or like to think out-of-the-box? After several games, no matter who wins or loses, you’ll know.

人类在围棋上被 AI 打败,没什么大不了的

So the million-dollar question is: Does human beaten by AI on Go game change any of the above traits of the game? The answer is obviously no. People can still use Go to cultivate their brain and will. Making friends and finding respect for opponents. It is still a fun game with tons of depth. Winning is not all that important. There is a saying in Go community that goes “A game with a heavy reward can never generate beautiful and brilliant matches(争棋无名局)”. This means if people care too much about winning, their creativity will get surpassed and they will all play safe, resulting in very boring games.

没错,人类现在连赢围棋都不如 AI,但这有什么大不了的?有些事情人类做得更好,有些事情计算机做得更好。事实上,有很多事情电脑比人类做得更好。计算数字,处理信息,不犯错误。我很少看到有人心情不好说“ OMG,我再也不做数学了,因为我的电脑比我好!“人们只是说,“好吧,计算机在计算数字上比我们强。太好了。让我们用它来做脏活,让我们专注于发明新的更强大的算法。对吗?事实上,这正是导致 AI 发明并最终导致 AlphaGo 诞生的原因。围棋游戏也不例外。如果我们停止“人工智能对人类的心态,拥抱“人工智能为人类工作”的理念,那么新的巨大可能性将会出现。

人工智能围棋的未来将是光明的

Ke Jie, Photo from Sohu.com

Lee Se-dol 的故事可能有点悲伤,但与 AlphaGo 有关的另一个故事完全是另一种风格。在中国职业比赛中排名第一的中国年轻围棋大师柯洁也与 AlphaGo 进行了一场三局比赛,输得很惨。三场比赛都输了,他毫无胜算。他的反应是什么?他显然对他强大的机器对手心存敬畏,但同时,他很好奇,非常好奇。他说,与 AlphaGo 对弈感觉就像打开了另一个完全不同的世界的大门。AlphaGo 玩游戏的方式不像他以前遇到的任何事情,他已经是一名经验丰富的球员,并在中国和国外赢得了大量奖项。然后,他彻底研究了他输掉的三场比赛,试图从中吸取教训,并从中成长。你知道后来发生了什么吗?他在职业比赛中取得了令人兴奋的 12 连胜,击败了路上的每一个对手。

不同的心态导致不同的结果。相似的输球游戏,不同的玩家,不同的结果,让我们思考。也许输给 AI 并不是一件坏事。我们人类总是最善于从过去的错误中学习,变得更好。

适应和成长,学习和创造,这是人类肯定能比计算机做得更好的事情,只有天空才是极限。

一切都是可能的

Photo by Dominik Schröder on Unsplash

自从我们改变了心态,围棋手可以做很多事情。

首先,也许李时斗先生可以加入一个人工智能团队,尝试帮助开发一种可以击败 AlphaGo 的新算法。他已经计划玩“HanDol”人工智能,也许在未来,他可以建立一个“人工智能围棋联盟”,并通过击败 AlphaGo 来复仇,他帮助开发了一个名为“Se-dol Go”的新人工智能棋手。

或者,柯洁先生可以利用他从 AlphaGo 中学到的知识,帮助开发一个基于人工智能的围棋训练系统,以提高人类棋手的游戏水平。用 AI 做测试工具,探索验证。

也许人工智能社区和围棋社区应该合作开发不同风格的人工智能围棋选手,并让他们在一个联盟中比赛,我们可能会看到许多漂亮的游戏,并推进围棋游戏理论。

当 AI 和人类一起工作时,只有天空才是极限。

觉得这篇文章有用?在 Medium 上关注我(李立伟)或者你可以在 Twitter @lymenlee 或者我的博客网站【wayofnumbers.com】T4 上找到我。你也可以看看我下面最受欢迎的文章!

[## “这是 CS50”:开始数据科学教育的愉快方式

为什么 CS50 特别适合巩固你的软件工程基础

towardsdatascience.com](/this-is-cs50-a-pleasant-way-to-kick-off-your-data-science-education-d6075a6e761a) [## 一枚硬币的两面:杰瑞米·霍华德的 fast.ai vs 吴恩达的 deeplearning.ai

如何不通过同时参加 fast.ai 和 deeplearning.ai 课程来“过度适应”你的人工智能学习

towardsdatascience.com](/two-sides-of-the-same-coin-fast-ai-vs-deeplearning-ai-b67e9ec32133) [## 你需要了解网飞的“朱庇特黑仔”:冰穴📖

是时候让 Jupyter 笔记本有个有价值的竞争对手了

towardsdatascience.com](/what-you-need-to-know-about-netflixs-jupyter-killer-polynote-dbe7106145f5)

没有基础研究就没有创新

原文:https://towardsdatascience.com/no-innovations-without-fundamental-research-cdb4b2b5df37?source=collection_archive---------36-----------------------

如今数学无处不在。但是,为什么资助纯数学研究对任何经济的创新都是必要的呢?下面是我脚踏实地的解释。

1.什么是数学,它研究什么?

数学经常被认为是深奥的。许多人不知道职业数学家真正做什么,也不知道数学中是否还有什么有待发现的东西。我将尝试解决下面的第一个问题。第二个问题的答案是:不,数学是无限的,总会有东西被发现(你可以从数学上证明)。

数学的来源在历史上在于两个领域:几何和数论。我们每个人都在学校学过几何:计算三角形、正方形、圆形等的面积。问题是这种几何学是几百年前人们做的。目前,几何已经采用了如此复杂的形式,以至于试图在一篇短文中解释它会错过目标(简言之,现代几何通过观察它们的形状和动力学来研究复杂的几何对象。Etale 上同调、栈、层、方案——这些都是数学术语。另一方面,我们有数论,它着重于研究自然数:1,2,3,4,…每个自然数都可以表示为质数的乘积:2,3,5,7,11,…,即只能被自身和 1 整除的数。

经过三千年的发展,素数及其研究仍然在现代数学中发挥着主要作用。它们也被用于工业——由于对质数的研究,我们可以安全地在网上购物,而不用担心我们的数据。了解非常大的素数有助于数据加密。数字是计算机的母语。

在数学中,人们通过给出证明来确保给定的陈述是正确的。简单来说,证明是一系列逻辑句子,以确定性(公理)开始,并导致所需假设的推导。例如,我们可以问是否有无穷多个质数。这是真的;证据很短。然而,一个稍微复杂一点的问题——是否存在无限多对差为 2 的素数(我们称这样的素数为“孪生”),比如 3 和 5、5 和 7、11 和 13、17 和 19——直到今天仍然没有证明。数学家们认为这是真的,但是还没有人能够找到一个论证来证明这种说法。

直到 2013 年,张一堂才取得了突破,尽管这是对孪生素数理解的一大进步,但仍然无法完全回答这个问题。数学是活的。现在有很多数学家解决不了的问题。有新的答案,但也有新的问题,因为每一个被证实的说法都开启了新的可能性。

2.数学研究是什么样子的?

纯抽象数学的研究主要在于阅读和思考。假设我对一个公开的问题感兴趣——就像我上面描述的关于素数对的问题。我该如何证明呢?第一步是了解到目前为止关于这个问题的所有知识。我会阅读并试图理解解决这个问题的最新数学文章。正如我所说的,数学家现在无法解决它,所以我不会在任何地方找到证明,而只会找到可能接近结果的结果。例如,张证明了存在某个数 N,使得存在无穷多对最多相差 N 的素数,如果我们能够证明可以取 N 等于 2,那么问题就解决了。

在第一步中,我将考虑是否可以改进张的结果,例如通过证明差为 n 的素数对的结果,其中 n 小于 n。这将使我们更接近于解决初始问题。

进一步的研究阶段是思考和更多的阅读。此外,还有与其他数学家的合作。在这个问题上思考足够长的时间,我将能够制定更简单的问题,可以被其他数学家更好地理解。数学是一种社会活动——仅仅找到一个证明是不够的,还需要能够向他人解释它。验证是必要的。这就是为什么会议和研讨会对数学家来说如此重要,因为它们是讨论正在进行的研究和交流思想的平台。

不幸的是,最常见的是原始问题无论如何都无法解决。尽管如此,情况并不坏,因为一般来说,有可能在目前已取得的成果上取得小小的进步,或者注意到其他人在他们的研究中所忽略的东西。这是写文章的基础,这将是进一步研究的基础。数学是几代数学家累积的成果。

3.为什么有必要资助纯数学?

创新。这个词在最近几年经常被重复。我们希望我们的经济具有创新性。我们需要处于全球发展前沿的高素质专家和专业人员。如何实现?知识是关键。

像生物学、化学和物理学这样描述世界的领域的核心是数学。物理学家用数学方法模拟我们的世界。它在生物学、化学以及 It 方面都是相似的。没有良好的数学基础,就不可能改进现代技术。最抽象的数学扮演着公理的角色——我们的进步基于此。多亏了它,我们有了电脑、互联网、智能手机、飞机或太空旅行。

有人可能会问,为什么不直接资助生产有用产品的工程师?问题是工程师们把他们的计算建立在来自物理学的理论基础上。首先,在我们着手做某件事之前,我们必须知道它在理论上是可能的。但是我们只能资助物理学家吗?然而这是必要的,如果没有抽象数学的数学基础,他们的工作是不可能的,因为抽象数学的培养没有考虑到应用。

从事抽象数学研究的数学家参与跨学科项目提高了研究的质量。数学家对研究的本质有更正式的看法和更广阔的视角,因为他们不寻求直接的应用。他们感兴趣的是完全理解这个主题。这就是为什么他们经常设计元语言来描述现象。这方面的一个例子是逻辑的正式发展,它允许计算机的创造和编程。第一批 IT 专家来自逻辑,而逻辑本身仍然是处理编程所必需的。在未来,同样的事情可能会发生在经济学、社会学或生物学领域,这些领域需要精确的语言来获得有价值的结果。在这里,我将只提到博弈论,它已经在经济学和社会学中找到了应用,以及加密货币比特币,它是基于密码学(再次是数论!).

数学家自己处理数学,因为他们在其中发现美。对他们来说,申请的问题实际上是次要的。反正也不可能先验地说哪个数学领域会有用,哪个不会。英国数学家 g .哈代夸口说,他研究的数学是如此抽象,以至于永远无法应用。Fate 希望他的研究目前被生物学家和 IT 专家用来解决具体问题(见 Hardy-Weinberg 原理)。

从经济角度来看,大多数数学研究都没有经济上的正当理由——它们在五年或十年内都不会有回报。然而,它们是几十年来最好的投资,因为它们可以留住高素质的科学家,为任何进一步的发现奠定基础,并为其他领域和企业的团队提供支持。这也适用于其他基础研究,即旨在理解某些东西而非构建任何东西的研究。基础研究的例子包括:了解大脑的功能、原子的结构或质数之间的关系。

4.数学与经济

我认为数学是一个任何国家都可以在相对较短的时间内取得世界级成功的领域。与化学家、生物学家或实验物理学家需要的昂贵实验室相比,研究是廉价的。通过雇用合适的人和建立数学家可以思考的环境,一个人有机会与世界上最发达的国家竞争。

数学家不需要太多。他们所需要的是不用教学生的时间,这样他们就可以完全投入到研究中去。效果将很快显现。国家的数学水平越高,潜在的科技水平就越高,因为没有数学就无法理解现代科学或工程。

创新只有通过数学的发展才有可能——深入的分析思维和对细节的关注可以推动科学和工程的发展,创造出真正独一无二的东西。

不,机器学习不会让理解变得过时

原文:https://towardsdatascience.com/no-machine-learning-does-not-make-understanding-obsolete-22ef3e2515d5?source=collection_archive---------21-----------------------

数据科学之道

将决策权交给预测型人工智能将是灾难性的

Sometimes you need more than prediction. Copernicus’s heliocentric model did not initially provide more accurate predictions than the geocentric model it replaced.

数据科学之道 专栏探讨了几个世纪以来哲学家们是如何攻克机器学习和数据科学的关键问题的。

你可能已经在媒体上看到了以下文章:

[## 机器学习扩大了知识和理解之间的差距

给了我们下一步进化的工具

onezero.medium.com](https://onezero.medium.com/machine-learning-might-render-the-human-quest-for-knowledge-pointless-5425f8b00a45)

这篇文章成为流行趋势是一件坏事。这是一个迹象,表明我们正在慢慢接近另一个冬天。

作者戴维·温伯格的中心论点是:

  • 人类努力理解复杂的系统。然而,我们基于“人类理解”做出的预测并不像人工智能那样准确,人工智能并不真正理解任何东西。
  • 然而,AI 的预测比基于人类理解的预测更准确。
  • 因此,我们应该放弃对理解的追求,专注于构建能够为我们做出决定的人工智能。
  • 将统治权交给预测性人工智能将迎来人类进化的下一个阶段。

第四点看起来更像是一部超人类科幻小说的奇思妙想,而不是一个论点,温伯格没有提供支持,所以我在这里专注于解构前三点。

没有理解的预测不能推进科学

要有效地遏制一个文明的发展,并在如此长的时间跨度内解除它的武装,只有一个办法:扼杀它的科学。—刘慈欣,《三体问题》

我想当然地认为,我们希望科学进步有很多原因,比如改善医学或我们制造有用东西的能力。良好的工程实践会让你从弓箭变成十字弓。科学带你从弓箭到巡航导弹。

摘自温伯格的文章:

深度学习的算法之所以有效,是因为它们比任何人都更好地捕捉到了复杂性、流动性,甚至是万物相互影响的宇宙之美。我们开始接受世界的真正复杂性远远超出了我们用来解释它的法则和模型。我们需要放弃我们对总是理解我们的世界和事情如何在其中发生的坚持。

但是坚持理解我们的世界是科学进步的方式。

在这种情况下,“理解”意味着一个模型——定义为一组关于特定问题领域内事物如何工作的假设,以逻辑形式表达。这些假设包括系统的核心组件,它们如何相互影响,以及改变一个变量对另一个变量的影响。

你可能听过统计学家乔治·博克斯的说法,“所有的模型都是错的,有些是有用的。”例如,我们知道我们当前的系统生物学模型是不完整的,在许多方面是错误的,但它提供了有用的救命药物和基因疗法。科学的进步是一个新模型取代旧模型的过程,因为新模型可以用旧模型无法解释的方式解释经验数据(参见托马斯·库恩的结构和科学革命理论以深入了解这一论点)。

Weinberger 本质上支持模型盲/基于模型二分法中模型盲的一面。基于模型的方法在模型的约束下预测经验数据,而模型盲方法摆脱这些约束,专注于构建具有最佳准确性的预测算法。这些方法通常在预测准确性上超过基于模型的方法。

但是更准确的预测并不是科学进步的方式。哥白尼的太阳系日心说模型没有像之前的托勒密地心说模型那样预测天空中物体的运动。但这是一个“错误更少”的模型,并为凯普勒更好的模型铺平了道路,从那里,谷歌地图。

正如温伯格所说,尖端的预测机器学习工具预测良好,但缺乏理解,如深度神经网络,通过在高维空间中发现复杂的相关性而令人惊叹。每个人都在《统计 101》中学到,相关性本身(无论多么细微)并不意味着因果关系,其中因果关系是关于系统中的组件如何相互影响的假设。你需要理解。

预测准确性不是我们关心的唯一性能指标

摘自温伯格的文章:

Deep Patient 不仅能够诊断个体患者患特定疾病的可能性,在某些情况下,它比人类医生更准确,包括一些迄今为止完全无法预测的疾病。

但是预测并不代表一切。我最近在推特上写道:

90%听起来相当不错!也许,我可以更进一步,在我把桶扔进接收器之前,对桶旋转时发出的声音训练一个深度网络,也许可以达到 95%的准确率。

我的观点很明显;预测的准确性并不是决策中唯一重要的事情。非常准确的预测引擎有时仍然会出错,出错的后果可能是灾难性的。统计学家和医学专家迈克尔·乔丹举了一个个人的例子,他根据超声波做出了一个错误的预测,即他未出生的婴儿会有智力残疾。这个预测导致医生推荐一个有风险的医疗程序。得到这一预测导致许多准父母决定终止妊娠。

在医学诊断领域,你更关心的是假阳性的风险,而不是预测的准确性。在某些领域,你可能更关心假阴性的风险,例如,如果你的工作是阻止恐怖分子登上飞机,或者阻止黑客获取有价值的机密,或者让一个将炸毁你的投资银行的流氓交易通过。

在复杂系统中,基于算法的高度准确预测的决策可能会导致灾难,在极少数情况下,它的预测是错误的。

在实践中,我们通常可以通过调整决策阈值来解决这种情况,在更敏感的和更具体的之间切换。但是这并没有解决黑天鹅的情况,在这种情况下,具有严重后果的事件非常罕见,不会出现在用于训练预测算法的数据中。

算法偏差。另一个无法直接解决的预测风险是算法偏差。ProPublica 在 2016 年发表的一篇文章首次强调了在刑事司法背景下使用的机器学习算法中的种族偏见问题,特别是在预测一个人是否会犯下未来的罪行以及根据该预测做出判决或假释决定方面。最近亚马逊因向警察部门出售面部识别服务而受到审查;这项技术后来被证明有种族偏见。当然,算法偏差的问题远远超出了种族。

即使这些刑事司法算法没有明确使用种族作为特征,它们也可以设计这样的特征。当工作申请没有直接询问种族时,种族代理如姓名(如 Daniel vs. Darnell)仍然可以向招聘经理表明种族。这些预测算法也可以使用这样的代理,除了这些代理可以被编码为深度神经网络中节点之间的复杂关系,使得它们对于人类来说太复杂而无法检测或理解。

一些人会认为,预测黑人犯罪风险较高是黑人犯罪率较高的逻辑结果。与其争论种族政治和犯罪统计数据的解释,我想指出准确的预测完全是题外话。公正是我们的业绩衡量标准!正义是我们刑事司法系统的核心原则,正义意味着根据人们能够控制的因素而不是他们不能控制的因素来判断他们,例如他们的种族、性别、邮政编码、他们是否有被监禁的家庭成员等。

如果在《犯罪与惩罚》中使用机器学习时唯一重要的衡量标准是预测准确性,那么我们将生活在少数报告风格的反乌托邦中,低收入单身母亲生下的婴儿在出生时就被附加了缓刑追踪器。

当我们的模型预测但不理解时,我们会做出错误的决定

摘自温伯格的文章:

我们人类长期以来一直认为,如果我们能够理解事情如何发生的不变法则,我们就能够完美地预测、规划和管理未来。如果我们知道天气是如何发生的,天气预报可以告诉我们是否要带伞去上班。

让我们遵循温伯格的建议,放弃人类理解天气的尝试,而是根据历史天气数据训练一个深度神经网络,并用它来预测每天早上当天是否会下雨。每天结束时,我们将当天的天气数据输入算法,因此算法会更新其权重,使其与当前的气候保持一致。

假设我们用这个算法的预测来决定要不要带伞。在上一节中,我认为当五级风暴来袭时,这种无需理解的高度准确的预测引擎可能会杀死我们。但如果我们忽略这一点,那么温伯格为他的论点提供了一个极好的 ML 案例研究。

现在让我们考虑一个类似的商业案例。根据上个月的内部财务信息和市场情况,我们将预测您的电子商务网站在给定月份的收入,而不是天气。如果 deep net 预测下个月收入会下降(雨天预测),那么我们将开展广告活动来提振需求(带把伞)。

然而,在第一种情况下,天气不受我们是否带伞的影响。在第二种情况下,未来收入会受到我们是否开展广告活动的影响。这些影响通过未来的收入数据反馈到算法中,从而影响预测,影响未来的决策,等等,形成一个反馈循环,导致次优的决策。

这个问题的解决方案是用和因果模型建立一个预测算法,这样它就可以在进行预测时根据因果关系进行调整。

风险可能比收入损失高得多。几项广泛的观察研究查看了绝经后妇女的医疗记录,发现激素的使用(雌激素和孕激素)预示着冠心病(CHD)的减少。基于此,医生开始给绝经后妇女开补充激素的处方,作为预防冠心病的一种手段。

然而,当妇女健康倡议进行随机试验时,他们发现补充激素的妇女有增加冠心病发病率。

为什么会这样?这里有一个猜测。也许在这些最初的研究中,一些绝经后的妇女很富有。他们有钱报名参加昂贵的健身课程,比如交叉健身和室内攀岩。他们听取了富裕的健身房伙伴的建议,通过补充激素来减轻更年期的影响。此外,所有这些锻炼都增强了他们的心脏,抵消了荷尔蒙造成的任何损害。

或者,可能不是富裕和过度运动,而是其他一些未被观察到的原因,统计学家称之为混杂因素。试验中的随机化消除了这些混杂因素的影响,证明了激素补充的实际效果。混杂因素的性质无关紧要。关键是,在混杂因素存在的情况下,从预测直接转向政策是一个坏主意。在这种情况下,代价是人的生命。

但是在大数据时代,我们难道不能衡量所有重要的东西,这样就不会有任何混淆吗?不会。产生大数据的流程不关心您计划做出的决策,除非您是流程的设计者。

那些你在数据中没有测量到的重要的东西不会戳着你的肩膀告诉你它们就在那里。他们只是继续在沉默中混淆。

解决方案不是放弃理解,而是建立理解的人工智能

温伯格把 AI高度精确的黑盒预测混为一谈,却不理解。事实是,有一些机器学习算法可以对某个领域内的因果关系做出自己的假设。换句话说,他们试图理解。这些算法可以从数据的被动观察中学习这些关系(例如;PC 算法),他们还可以尝试干预数据生成过程,以更直接地了解什么影响什么。以这种方式,他们表现得像一个人类科学家。

我没有贬低深度学习。这类算法的最前沿确实采用了深度神经网络架构,这在 NeurIPS 的 2018 因果学习研讨会上显而易见,深度学习专家如 Yoshia Bengio 出席了。

是的,复杂的系统很难建模。但是放弃理解并让愚蠢的人工智能做出艰难的决定将是一场灾难。相反,我们应该专注于构建能够理解的人工智能。

不再做实验了

原文:https://towardsdatascience.com/no-more-experiments-4919630675d9?source=collection_archive---------30-----------------------

大数据和算法是对自由项目的重大挑战。收集透明胶片可能是一个解决方案。

Photo by Kristina V on Unsplash

1960 年,经济学家弗雷德里希·冯·哈耶克出版了《自由宪法。这是一本非凡的书,散发着作者的智慧,似乎是深刻和批判性思考的典范指南,并且根据哈耶克帮助建立的世界,无疑对现在有所启发。

然而,哈耶克构建的世界正在发生变化,随之而来的是哈耶克自由的支柱开始出现裂缝。当然,自由是一件有趣而又难以实现的事情。例如,(市场)自由意志论者是最先抗议任何削减其自由的概念的人之一,但自由似乎只存在于资本主义现实主义的核心中。美国人对自由主义一词的挪用无助于这种混乱,社会自由主义和财政保守主义等术语更多地表达了我们对资本主义的顺从,而不是我们对自由的看法。

接下来是哲学上的自由辩论,在那些相信我们生来自由,社会摆脱了强加的约束(积极自由)的人和那些相信我们生来受约束的人之间,我们应该努力废除所有仍然不合理的强制焦点(消极自由)。人们可能会问自己是哪种类型的自由主义者,但我认为这个问题没有说到点子上。像许多事物一样,自由不是一系列的绝对,而是一个光谱。至少,自由太复杂了,无法用政治象限来理解…

最好的方法是你自己的方法

的《自由的宪法中,哈耶克对于他认为自由是什么以及何时可以受到限制的解释非常简短,这与约翰·斯图亚特·密尔在 中关于自由 的思想以及密尔的伤害原则非常接近。考虑到哈耶克花了一段时间管理穆勒的著作,这并不奇怪。

那么,更有趣的是哈耶克在本书其余部分的讨论——这一讨论肯定受到了当时地缘政治形势的影响——为什么以个人为中心的自由(尽管不是严格的自由民主)优于替代的集体化制度。其中一个论点是我称之为“多次实验”的论点。

自由思想的很大一部分是犯错误并从中吸取教训的能力。这就是为什么伤害原则只在保护他人的自由时证明胁迫是正当的;我们完全有权利犯自己的错误,在这样做的过程中,我们从错误中学习并发展。穆勒认为这一点,哈耶克当然也同意。哈耶克认为,通过人们的尝试和偶尔的成功(但经常失败),社会进步了。因此,允许人们自由地走自己的路并进行试验,将比集体化下更快地产生更多的成功(和更多的失败),在集体化下,单个行动者——比如说国家——一次只能尝试一个计划。

这是一个非常政治化的想法,但在资本主义内部,它非常重要。最好的方法是你自己的方法。

数据更了解

“许多实验”的论点能经得起数据、算法和 21 世纪的考验吗?让我们假设论点是正确的;那么,如果我们能把每一种结果模拟一万亿次,我们还需要人类自由吗?这难道不是更合乎道德吗?因为现在人们不必为了一些人的成功而失败。在越来越短的时间内,最大限度地增加我们可以进行的实验数量,难道不是更有效率吗?

显然,这是一个有争议的论点。首先,模拟世界有多精确?几十年来,金融家和学者在数十亿美元的帮助下,试图对股票市场进行建模,但弥漫在交易大厅的许多动物精神仍未被驯服。

第二,接受我们可以模拟世界,我们应该选择谁或者从谁的角度来构建模拟?对算法偏见的研究已经表明刑事司法算法中的负面种族偏见,以及面部识别软件。这些偏见的原因似乎不同,但效果是一样的——现实的均质化。

第三,在算法的 cosh 下,社会和进步到底意味着什么?这就是我称之为“矩阵问题”的东西,在关于狗屁工作的文献中有广泛涉及。如果算法的目的是服务于人类的进步,但是人类的进步存在于一个服务和等级的社会内部,那么任何结果都可以被描述为进步吗?或者,我们必须给这个世界贴上静止的标签吗?压迫感?超真实?

裂缝出现的地方

大数据的激增使得第一个论点变得大胆,而且很可能不正确。随着数据和算法对社会的影响——从 YouTube 激进化到脸书大选推动——显著增长,数据的价值越来越被认识到。是的,我们可能还没有驯服动物精神,但随着我们的数据基础设施扩展数据的能力和亲密度,我们很可能会达到这一点——我将这样的概念称为数据景观。

剩下的争论继续对数据的统治地位提出挑战,但只是在我们继续关心它们的范围内。刑事司法算法歧视黑人男性的趋势是因为长期持有的执法偏见,而面部识别软件识别白人男性的效率是因为主要是白人男性编写程序。这些都是社会问题,也是一个例子,说明允许少数观点(如果不是少数个人)来创造我们的数据驱动的未来将如何使该项目变得非常不自由。

重拾动物精神

不过,有一些防止这种情况发生的建议。数据经济学家恩斯特·哈芬(Ernst Hafen)建议,所有人都应该被赋予获得副本的权利:要求任何收集我们数据的人向我们提供副本的权利。他建议我们可以将这些副本集体化——我称之为集体透明的概念——创建一个数据中心:一个数据公共区。这将为算法提供相对无偏见并反映社会的数据,但也将使数据收集民主化和非货币化。

想象一下,如果脸书的价值在于提供高质量的服务,而不是因为你和你所有的朋友已经给了他们太多的数据,让你很容易地换到另一家公司?想象一下,如果我们决定,出于道德原因,一些数据不应用于算法,就像我们在道德上反对人体器官市场一样?

反常的是,这种数据集体化可能是自由主义项目的未来;一个解决数据垄断、扩大数据自由和使数据使用民主化的系统。所有这一切,同时继续受益于大数据和算法。一个不再有实验的世界,我们被赋予了前所未有的实验能力。

无需知道结局:递归算法和数学归纳法

原文:https://towardsdatascience.com/no-need-to-know-the-end-recursion-algorithm-and-mathematical-induction-5a9e4c747c3c?source=collection_archive---------16-----------------------

当我第一次学习数学归纳法和用线性代数解线性系统时,它们对我来说是如此神奇,我觉得自己就像电影《黑客帝国》中最终看到矩阵的尼奥。

我已经多年没有学习它们了(不要问我有多少年了,我不想让你猜我的年龄),但我清楚地记得,我认为我理解计算机的思维和世界是如何在很短的时间内工作的——我可以一次解多个线性方程,我可以证明系统中模式的存在。我很快会告诉你数学归纳法是如何工作的(希望你能有一秒钟像 Neo 一样的感觉),但让我先告诉你这个。当我最近了解到一个递归算法时,它让我想起了我学习数学归纳法的时候。好神奇好聪明!每当我得到这些让我震惊的神奇技术时,我一定要仔细分析它们,直到我知道它们是如何工作的。在这篇文章中,我想与你分享我在递归算法和数学归纳法之间发现的相似之处,以及它们如何帮助我实现该算法。

数学归纳法是一种证明数学性质或公式的技术,适用于每个自然数(0 和正整数)或每个整数(正整数)。

例如,让我们证明从 0(或 1)到 n 的正整数相加的等式:

首先证明当 n = 0 时:

第二,假设从 0 到 n-1 的加法等式成立:

第三,使用上一步中的假设,证明该等式适用于从 0 到 n 的加法:

这证明了该方程适用于每个自然数,因为:

  1. 它适用于最小的数字 0(或者有时是 1);
  2. 如果等式对一个自然数成立,那么对下一个连续的数也成立;
  3. 对 0 为真所以对 1 为真,然后对 2 为真,对 3 为真以此类推……(这是我脑子被炸飞的点!)

递归算法是一种调用自身的算法。例如,我有一个自然数, m,,我想检查一下 m 是否是从 0 到某个数字 n 的连续自然数之和,并找出数字 n 。这意味着:

这是我们之前证明的方程的倒退。如果我选择 m 为 6,那么 n 就是 3,因为 6 = 1+2+3。然而,如果我选择 m 为 7,那么 n 不存在。要在 Python 中构建一个算法来查找 n,让我们像下面这样计划:

  1. 如果 m 是 0,那么 n=0
  2. 如果 m>0,更新 n = n+1,然后检查 m-n 是否=0
  3. 如果 m-n =0,我们找到 n。如果 m-n>0,则更新 m =m-n,并返回步骤 2。如果 m-n<0,则 n 不存在

我们重复第 2 步和第 3 步,直到相减后的数字变成 0 或负数。我们不知道要重复多少次,所以我们不应该使用 for 循环。当我们需要在不知道终点的情况下重复这个过程时,递归算法非常有用。

我发现数学归纳法和递归算法在三点上非常相似:

  1. 基本案情应当成立;在第一个例子中,n=0,在第二个例子中,m = 0
  2. 换人是用来过箱子的;在第一个例子中,数列中的最后一个数用于等式中,而在第二个例子中,m 和 n 被更新,直到 m 变为 0 或小于 0

3.没有固定的终点:数学归纳法用于无限数量的序列,递归算法用于没有固定索引范围的迭代。

当我意识到这些相似性时,似乎更容易知道何时使用递归算法以及如何构建它。使用这三样东西,递归算法被分解成两个部分,这两个部分也是何时使用该算法的指示符:

  1. 找到一个代表基本情况的参数值,看看它能否结束您将要构建的循环
  2. 找到一个重复的模式,看看是否可以简单地通过更新变量值来表达

为了查看这些部件的运行情况,让我们使用欧几里德算法,创建一个函数来计算两个整数 a 和 b 的最大公约数(gcd ),其中 a >b。

从步骤 1 和步骤 4 中,我们看到基本情况是一个数可以被另一个数整除。此外,当余数为正时,对于下一步,我们更新除数和被除数:r₀ = b,r₁,…,rₖ,前一步的余数成为下一步的除数。因此,我们看到递归算法将是一个很好的函数。

高维空间中没有真正的效果

原文:https://towardsdatascience.com/no-true-effects-in-high-dimensions-1f56360182cd?source=collection_archive---------10-----------------------

生命科学的数理统计和机器学习

我们能相信从高维数据中得到的结果吗?

Image source

这是 生命科学的数理统计与机器学习 栏目的第五篇文章。在本专栏中,我将介绍我们在生命科学中面临的数据和分析挑战,如生物医学、生物信息学、细胞生物学、遗传学、进化生物学等。也许主要的分析挑战是处理高维数据,对这一事实的不当解释可能会导致错误的结论,这对医疗保健中的患者安全尤其有害。

在这篇文章中,我将展示当增加数据的维度时,分析模型如何不能重建变量之间的真实关系。

高维多变量分析

考虑一个简单的线性模型 Y ~ X ,其中 Y 是响应,X 是解释变量(预测值)。Y 可以是表型向量,例如 n 个个体/样本中每一个的疾病状态(患病/健康),而 X 是具有 n 个样本p 个特征/维度的矩阵。为简单起见,X 和 Y 均取自正态分布。假设低维情况 n > > p:

结果看起来不错,Y 和 X 变量不像预期的那样相关,因为它们来自正态分布。只要 n > p,数学工作没有问题。现在让我们增加特征/维度 p 的数量,看看会发生什么。

发生了什么事?我们可以看到,X 中的一些特征,即 X2、X6、X9、X10,开始与 Y 显著相关。看看调整后的 R 平方,它是 X 解释的 Y 方差的分数,我们现在解释 Y 方差的 28%** ,尽管 Y 和 X 不应该相关,因为它们是从正态分布中独立采样的。好了,如果特征数 p 等于样本数 n,会发生什么?**

有意思!当 p = n 时,r 拒绝计算多元线性模型,尽管我们只有 20 维。我们在这里观察到的效果被称为过拟合,这可以被认为是 维度诅咒 的一种表现形式。过度拟合意味着我们不能使用我们想要的那么多的拟合参数,而是应该基于一些附加的标准来选择它们的最佳数量,例如【AIC】【阿卡科信息标准】,或者执行交叉验证,因为预测器的数量实质上是多元线性模型的超参数

所以我们对 R 抛出了一个“奇点”误差,对于仅仅 20 个维度来说,事实上我们通常有数万个****(RNA seq)****甚至数百万个 ( 基因组学 ,****甲基化 ) 个维度在这是生命科学中多变量分析的主要障碍,也是为什么单变量特征选择 ( 关联研究 、差异基因表达、差异甲基化)通常优于多变量特征选择的一个原因,尽管后者的预测能力更高。典型生物设置n<p的另一个结果是,必须用套索/脊/弹性网预选信息特征,并进行降维。

对协变量进行调整隐藏了真实的影响

现在想象 X 不是一个矩阵而是一个向量,例如一个基因型的向量,所以我们正在进行一项关联研究,表型 Y 与基因型 X。我经常观察到试图解释可能混淆这种关联的其他因素(协变量)。事实上,如果个体来自不同的人类群体,如非洲人、欧洲人、亚洲人,这种异质性可以解释表型 Y 中的显著百分比变异,而我们感兴趣的是由基因型解释的表型变异,换句话说,群体异质性是一个混杂因素,应在模型 Y~X 中进行调整。通常,对所有可用的遗传变异体进行主成分分析(PCA)** ,并选择少量 PC 作为关联的协变量:Y~X + PC1 +在这种情况下,协变量的数量是根据常识任意选择的,而在这里,我想证明这个数量对于恢复表现型与基因型关联的真实效果可能是至关重要的。**

让我们模拟 X 和 Y 之间的一个线性关系: Y=2*X +噪声。假设我们有一个线性模型 Y~X,让我们针对逐渐增加的与 Y 稍微相关的 PCs 数量来调整这个模型,即 PC1=0.9Y,PC2=0.8Y 等等。:

我们在此观察到,当添加与 Y 相关的 PCs 时,Y 和 X 之间关联的真实效应 2 变得越来越难以恢复。尽管我们仍有 n>p,但当添加 10 个 PCs 时,恢复的效应约为 0.5,这与真实效应 2 相差甚远。此外,我们观察到调整后的 R 平方(方差解释)几乎达到 1,这意味着我们通过仅包括 10 个协变量来解释 Y 中的所有方差。

在上面的代码中,请注意(1-i/10)前面的系数 1。我们称之为 Y 和 PCs 之间的协变系数。我们刚刚看到,对于协变=1 的情况,真实效应 2 可能被错误地计算为 0.5。如果我们增加 Y 和 PCs 之间的协变,即协变=2 和 3,现在会发生什么?

我们观察到,Y 与协变量 PCs 越相关,就越难重建真实的效果。当协变=3 时,重构的效应基本上是,这意味着 Y 和 X 之间没有关联,尽管我们已经将该效应模拟为 2 。因此,尽管可以从生物学角度调整 covarites 的线性模型,但这应该谨慎执行,因为由于维数灾难,数学可能无法忍受。

摘要

在本文中,我们已经了解到,由于维数灾难,当特征/维度的数量接近样本的数量时,多元分析会爆炸。此外,进行关联研究时,您应该特别注意线性模型调整的协变量的数量。过多的协变量可能会** 模糊真实效果并使其无法重建。**

在下面的评论中让我知道生命科学中的哪些分析对你来说似乎特别神秘,我会在这个专栏中尝试回答它们。在媒体尼古拉·奥斯科尔科夫关注我,在 Twitter @尼古拉·奥斯科尔科夫关注我,在 Linkedin 关注我。下次我们将比较单变量与多变量特征选择,敬请关注。

Node2Vec —图节点嵌入方法

原文:https://towardsdatascience.com/node2vec-graph-embedding-method-f306ac87004e?source=collection_archive---------9-----------------------

简介

图形是用连接来表示信息的常见数据结构。例如,蛋白质-蛋白质相互作用,其中节点表示蛋白质,边表示一对蛋白质之间的生物相互作用。另一个例子是脸书网络,其中节点是用户,边是用户之间的连接。

如果我们想使用深度学习方法对那些图表进行预测,我们需要一种方法将它们转换成实数的 d 维向量。因此,我们使用图嵌入,这是一种低维表示,有助于更好地概括输入数据。

在 Node2Vec [1]中,我们的目标是保持节点的网络邻域,因此我们的目标是找到作为实向量的图的表示,其中邻域之间具有小的欧几里德距离,同时表示节点结构。

Graph Embedding — Representation Learning on Networks, snap.stanford.edu/proj/embeddings-www

Word2Vec

为了理解 Node2Vec 的概念,我们首先需要了解 Word2Vec 是如何工作的。有几种方法可以产生单词嵌入,它是单词的浓缩表示。在 Word2Vec SGNS- skip-gram(上下文表示)负采样(训练方法)中,我们基于单词预测上下文。我们希望在上下文中有正确单词的概率高,而在上下文中有随机单词的概率低。例如:

(The,baby,is,微笑,at,her,mom)——我们会给预测上下文“baby _ _,at,her,mom”
(The,baby,is,飞翔,at,her,mom)——我们会给预测上下文“baby _ _,at,her,mom”

我们如何构建元组作为算法的输入?
这是一个非常重要的问题。我们构造学习嵌入的样本的方式影响嵌入空间。例如使用目标词周围的小窗口的实词(CBOW)将强调主题的相似性[2]。其中,使用通过依存边缘连接到目标单词的内容单词将强调单词功能之间的相似性。

functional vs topical similarities [2]

如果我们把句子看作图表,节点就是单词,边定义了我们如何在单词之间行走。在第一种情况下,我们假设一个句子是一个有向图,其中每个节点(单词)通过边连接到它的右边邻居。在第二种情况下,我们使用依赖解析器来创建定义边的有向图。

dependency parser from spaCy package

Node2Vec

现在让我们回到 Node2Vec,我们想找到一种方法来创建这些元组。同样,我们构建元组的方式会影响图的嵌入。我们的目标是保存邻域和结构,因此我们需要一种兼容的方式来探索图形。我们使用二阶随机游走来采样在 BFS 和 DPS 之间、在探索邻居和探索其他邻居之间、在微观和宏观之间权衡的图。

BFS vs DFS [1]

通过使用超参数 p 和 q 来计算非规格化跃迁概率来实现折衷。
p —回报率
q —探索率
假设我们从 t 走到 v 现在我们需要决定探索哪个节点 x_i 。我们计算 t 和可能的 x_i 节点之间的边数。
如果距离为零(意味着它是 t 本身),我们将原始边权重乘以 1/p。
如果距离为 1,我们保留原始边权重。
如果距离为 2,我们将边权重乘以 1/q。
我们稍后将编辑后的边权重归一化以获得概率值。

请注意,低 p / q 导致高回报概率/勘探概率。

Node2Vec [1]

比如[1],看 Les Misérables 网络,节点是人物,边代表人物之间的合作。当使用 p= 1 和 q= 0.5 时,我们允许高度探索,并且我们得到基于它们所属的社区组织的聚类(同质性)。当使用 p = 1 和 q = 2 时,我们不鼓励探索,我们根据结构相似性组织聚类。

homophily (top) and structural similarity (bottom) [1]

结论

总而言之,图嵌入是有用的。Node2Vec 定义了一种智能的方式来探索图形,从而在表示中体现了同质性和结构等价性。探索允许为经典的 SGNS 算法创建样本,这创建了有用的图嵌入。

参考文献

[1] Grover & Leskovec,node2vec:网络的可扩展特征学习
[2] Levy & Goldberg,基于依存关系的单词嵌入

噪声对比估计

原文:https://towardsdatascience.com/noise-contrastive-estimation-246446ea9aba?source=collection_archive---------12-----------------------

温和的介绍

本文原载于blog.zakjost.com

介绍

我最近致力于理解噪声对比估计(NCE),这是一个艰难的旅程。这篇文章的目的是让其他人更容易通过不太正式,并通过实现的细节工作。在深入了解它如何工作的细节之前,让我们先谈谈它要解决的问题。

背景

假设你想学习单词的矢量嵌入来帮助完成自然语言任务。著名的 word2vec 方法做了一些聪明的事情:

  1. 以一句话开始:“快速的棕色狐狸跳”
  2. 使用一个横跨句子的滑动窗口来创建(context, target)对,其中目标是中心词,上下文是周围的词:([the, brown], quick)([quick, fox], brown)([brown, jumps], fox)…等等。
  3. 使用查找嵌入层将上下文单词转换为向量,并对其进行平均,以获得代表完整上下文的单个输入向量。
  4. 使用上下文向量作为具有 Softmax 变换的全连接神经网络层的输入。这导致在给定当前上下文的情况下,你的整个词汇表中的每个单词成为正确目标的概率。
  5. 最小化交叉熵损失,其中label = 1用于正确的目标单词,而label = 0用于所有其他单词。

通过这样做,网络学习单词在句子中出现频率的统计数据。因为嵌入查找表的权重是可学习的,所以它倾向于在嵌入空间中将相似的单词比不相似的单词放得更近。酷毙了。

但是让我们考虑一下上面第 4 步中的计算。你的网络的密集层有一个大小为(embedding_dim, vocab_dim)的权重矩阵,它将上下文嵌入转换成数字,帮助你预测每个词汇单词的概率。这需要两个步骤:1)从密集层的输出中获取每个单词的值(我们将这些值称为 z_i ,其中 i 索引词汇表中的特定单词),然后 2)通过使用 Softmax 变换将这些值转换为概率:

注意,分母需要一个超过整个词汇表大小的总和。如果你有一个巨大的词汇表,那么通过对每个词汇表单词的输出求和来标准化每个训练样本就变得昂贵而缓慢。

在步骤 5 中,我们计算交叉熵损失:

即使损失函数被表示为整个词汇表的总和,唯一非零的项是标签 y = 1 的地方;即对应于实际目标单词的术语。问题是每个 p_i 项都被同一个分母除尽,而这个分母本身就是整个词汇表的总和。这使得我们的损失函数依赖于网络中的每个输出,这意味着每个网络参数将具有非零梯度,因此需要针对每个训练示例进行更新。

There has to be a better way!

负采样

解决这个问题的一个想法是:不要把分母中每个不正确词汇的概率相加,只挑选几个。这些被选择的非目标单词被称为负样本。所以:按照上面相同的步骤,但是在步骤 4 中,只对目标单词和其他单词的随机样本进行预测,并假设它代表整个词汇。

这显然不是给定的正确规范化,因为你没有对绝大多数词汇求和,但这是一个近似值,结果证明效果很好。它还有一个额外的优点,就是你不需要更新每个词汇单词的权重,这可能有数百万个参数,而只需要更新目标单词和负样本的权重。由于这种概率仅使用目标词和几个负样本而不是整个词汇表进行标准化,因此涉及的变量要少得多。因此,渐变/更新的数量从|embed|*|V|到|embed| * |samples + 1|不等。这在直觉上也很有意义。我们真的应该为每个可用句子的每个片段使用/更新单词“zebra”的参数吗?

噪声对比估计

NCE 在实现上非常类似于负抽样,但是它增加了一些理论上的牙齿。让我们首先讨论他们是如何构建问题的,然后再讨论实现的调整。

通过比较学习

在负采样中,我们用 1 标记真正的目标词,用 0 标记不正确的目标词的随机样本。这有点像训练一个模型来预测,“其中哪些是真实的,哪些是噪声?”NCE 使用逻辑回归模型来直接回答这个问题。

回想一下,LogReg 对输入来自一个类而不是另一个类的对数优势比进行建模:

我们想要一个类来自于真实字分布 P 而不是噪声分布 Q 的对数概率:

这将我们试图了解的数据分布与参考噪声分布进行比较,因此得名噪声对比估计。我们不知道真正的分布 P ,但是我们可以随意指定 Q 为我们想要的。 Q 分布是我们用来生成负样本的。例如,也许我们以相等的概率对所有词汇进行采样,或者考虑到一个词在训练数据中的稀有程度。关键是:这取决于我们,这使得计算log(Q)部分非常简单。

非常清楚地说,我认为值得再看一次 word2vec 网络,并思考如何使用 Q :

我们使用一个上下文向量作为密集层的输入。但是我们没有计算词汇表中每个单词的输出,而是做了以下事情:从我们指定的分布中随机抽取单词: Q 。然后只计算真实目标单词和我们从噪声分布中随机采样的单词的网络输出值。如果我们随机抽取 5 个样本,那么我们将只评估 6 个输出(样本+目标)的网络,而忽略其余的词汇表。

现在,由于我们定义了决定我们如何抽取负样本的噪声分布,我们可以根据该分布分析计算任何特定单词的概率, Q 。例如,如果我们定义“单词-1”的概率为 10%,而“单词-2”的概率为 90%,并且我们碰巧抽取了“单词-1”的样本,那么Q= 0.10;它只是对我们定义的分布的引用。这样我们就可以得到 log( Q )中的一部分

那么 P 呢?

这就是我们使用神经网络的目的——在给定的上下文中预测 P 。然后,我们使用网络输出和分析计算的 Q 来计算上面的 logit 方程。通过将此视为正常的逻辑回归任务来训练网络,其中目标词用 1 标记,而阴性样本都用 0 标记。

使用这个框架,我们将学习数据概率分布无监督任务转化为有监督* LogReg 问题,在这个问题中,我们仅仅通过指示一个单词是真正的目标还是来自噪声分布来发明标签。通过学习一个模型来分辨真实的东西和我们发明的一个东西的区别, Q ,它就学会了理解真实的东西。非常聪明的框架。*

履行

现在我们知道了我们想要创建一个逻辑回归模型来预测真实数据相对于噪声分布的对数概率,让我们描述一下我们需要如何改变 word2vec 实现。步骤 1-3 是相同的:我们创建相同的(context, target)对,并对上下文单词的嵌入进行平均以获得一个上下文向量。

  • 在步骤 4 中,您做与负采样相同的事情:使用上下文嵌入向量作为神经网络的输入,然后收集目标单词的输出和来自噪声分布的随机样本 k 负样本, Q
  • 对于网络输出的每一个选中的单词, z_i ,减去 log( Q ):

  • 不要使用 Softmax 转换,而是应用 sigmoid 转换,如在逻辑回归中。这是因为我们试图建立对数模型。

  • label=1标记正确的目标词,用label=0标记阴性样本。
  • 将这些用作逻辑回归的训练样本,并最小化二元交叉熵损失:

这里, N = k + 1 (负样本数加上目标字), l_i 是目标或负样本的标签, p_i- hats 是如上定义的 sigmoid 的输出。

与负采样的唯一实际实现差异是添加了一个校正,它考虑了单词被采样的概率,然后将其转换为逻辑回归/二进制分类任务。通过使用我们的网络输出 P 并最小化二元交叉熵,我们的网络学习 P

注意:在这种形式中,网络在技术上并不输出标准化的值——没有什么固有地强制输出总和为 1。添加显式规范化需要对整个词汇表求和,这违背了整个目的。最初的论文建议每个输入上下文的归一化常数是一个可学习的参数,并且这被证明是有效的。然而, 已经表明 令人惊讶的是,仅仅假设网络输出归一化值给出了等效的性能,并且网络学习到大部分是自归一化的,因为这是最优解。

结论

噪声对比估计是一种通过与我们定义的噪声分布进行比较来学习数据分布的方法。这允许我们将无监督的问题转换为有监督的逻辑回归问题。它的实现类似于负采样,这是一种近似机制,旨在通过对整个词汇表求和来降低标准化网络输出的计算成本。nce 和负抽样在实现上的主要区别在于,在 NCE,样本来自噪声分布的概率被明确地考虑,并且问题被转换为特定样本来自真实数据分布而不是噪声分布的对数优势比的正式估计。

最初发表于https://blog.zakjost.com

资源

  • 原 NCE 论文
  • 用于学习单词嵌入的 NCE 的改编
  • 总结 NCE 理论的一套有用的笔记
  • TensorFlow 的候选采样参考,总结了不同采样技术之间的异同,如负采样和 nce
  • 对 word2vec 的深入探究。第 1 部分有基础知识,第 2 部分涉及负抽样和其他改进。

非线性回归:基础扩展、多项式和样条

原文:https://towardsdatascience.com/non-linear-regression-basis-expansion-polynomials-splines-2d7adb2cc226?source=collection_archive---------6-----------------------

如何用多项式和样条捕捉非线性关系?

本文基于优秀的 Hastie,t .,Tibshirani,r .,& Friedman,J. H. (2009)的一章。统计学习的要素:数据挖掘、推理和预测。第二版。纽约:斯普林格。

基础扩展

用于分类和回归的流行线性模型将预期目标表达为特征的线性函数。这种近似是方便的,有时也是必要的。方便,因为线性模型很容易解释,而且是必要的,因为对于稀缺的数据,线性模型可能是我们能够在不过度拟合的情况下拟合的全部。然而,真正的基础函数通常不是线性的。因此,在模型中捕捉这种非线性可能会产生更多的预测和解释能力。一类建模方法通过用一些变换增加输入特征𝑋,然后在线性模型中使用变换后的特征来解决这个问题。这种模型采取以下形式

xT7 中称为线性基展开,其中 hm 是𝑋.的第 m 个变换这种方法的美妙之处在于,一旦确定了基函数ℎ,模型在这些新的转换变量中就是线性的,并且拟合与基本线性模型一样简单。

一些广泛使用的基函数有:

  • ℎ𝑚(𝑋) = 𝑋𝑚,它恢复了原来的线性模型;
  • ℎ𝑚(𝑋) = 𝑋 j 或ℎ𝑚(𝑋) = 𝑋𝑗𝑋𝑘,这允许用多项式项增加输入以实现高阶泰勒展开;
  • ℎ𝑚(𝑋) = 𝑙𝑜𝑔(𝑋𝑗)、𝑠𝑞𝑟𝑡(𝑋𝑗)等,其允许其他非线性变换;
  • ℎ𝑚(𝑋) = 𝐼(𝐿𝑚 < 𝑋𝑘 < 𝑈𝑚), which is an indicator for the region of 𝑋𝑘. By breaking the range of 𝑋𝑘 into a set of non-overlapping regions we obtain a model with piecewise-linear contributions of 𝑋𝑘.

Piecewise Polynomials

A 分段多项式函数是通过将𝑋的定义域划分为连续的区间,并在每个区间内用单独的多项式来表示函数而得到的。下面相当长的 Python 代码块将一些简单的分段多项式拟合到模拟数据中,并将它们很好地绘制出来。请注意,大部分代码是用于绘图的。

左上面板显示了具有三个基函数的分段常数函数:

结𝜀1 和𝜀2 分别等于 1.5 和 4.5。分段常数拟合归结为每个区域的𝑌平均值。

右上面板显示了分段线性拟合。除了前面的三个基本函数,这一个还需要另外三个,每个区域一个,以通常的线性回归方式添加𝑋和𝑌之间的关系:

注意,结果是,在每个区域中,𝑌被建模为其在该区域中的平均值加上𝑋的影响乘以其系数 β 。要了解这一点,只需将六个基函数ℎ代入本文开头的基展开式即可!

分段线性模型的一个问题是它在节点处是不连续的。这是不希望的,因为我们希望模型为每个输入 X 产生一个唯一的输出 Y 。当𝑓( X 不连续时,情况并非如此,因为在节点处没有唯一的输出!因此,在大多数情况下,人们更喜欢有一个连续的模型,比如左下方面板中的模型。它可以通过在基函数中加入适当的约束来加强节点处的连续性而获得:

其中𝑡+表示阳性部分。作为一个例子,右下面板显示了基函数ℎ3。

回归样条

分段多项式,即使是那些在节点处连续的多项式,也往往不是光滑的:它们会迅速改变节点处的斜率。为了防止这种情况并增加它们的平滑度,增加局部多项式的阶数并要求纽结两侧的前两个导数相同就足够了。连续且具有连续一阶和二阶导数的函数称为三次样条,可用以下基函数表示:

下面的代码块将这个三次样条拟合到之前模拟的数据中。

上面的三次样条似乎很适合这些数据。然而,使用这种技术有一个危险:三次样条的行为在边界附近往往是不稳定的,即超出𝑋.的观测值为了平滑边界附近的函数,可以使用一种特殊的样条,称为自然样条

自然三次样条增加了额外的约束,即函数在边界节点之外是线性的。对于这种相当粗糙的近似,边界附近的偏差将是一个代价,但假设边界附近是线性的,无论如何,我们的信息较少,这通常被认为是合理的。

带有𝐾节点的自然三次样条由𝐾基函数表示如下:

在哪里

现在,让我们采用三次和自然样条来模拟工资和年龄之间的关系,这可以合理地预期为非线性——样条的完美用例。对于这个实际的例子,我们将使用 statsmodels 包来装配花键,使用 patsy 来定义公式。数据改编自 T. Hastie 等人的《统计学习导论》。

两条样条曲线看起来相似,但是请注意,与三次样条曲线相比,自然样条曲线在图的右边缘是线性稳定的!现在让我们看看另一种获得样条的方法。

平滑样条

到目前为止讨论的所有方法都要求我们选择结的数量和位置。平滑样条是一种通过使用一组最大节点来避免节点选择问题的方法。在这种方法中,拟合曲线的复杂性不是由节点控制的,而是由正则化控制的。

人们可以认为平滑样条函数是从所有可能的函数中选择一个𝑓(𝑋函数,该函数具有两个最小化损失残差平方和(RSS)的连续导数。实际上,𝑓(𝑋)几乎总是被选为三次函数。

上面 RSS 公式中的第一项衡量与数据的接近程度,而第二项惩罚函数的曲率。两者之间的权衡由正则化参数 λ 控制:

  • λ = 0,𝑓(𝑋)可以通过任何任意复杂的函数对数据进行插值,这几乎肯定会导致过拟合;
  • λ = ∞,第二项占优势,𝑓(𝑋)是简单的线性拟合,因为根本不容许曲率。

将正则化参数设置在这两个极端之间的某个位置将有望产生一个很好地拟合数据但不会过度拟合的模型。

让我们用平滑样条来拟合工资年龄数据。我们将为此使用 csaps 包,它定义的正则化惩罚略有不同:它接受 0 到 1 之间的值,其中 0 是直线,1 是自然三次样条插值。软件包还要求我们在拟合模型之前准备好数据。对于每个𝑋.,它只能处理一个𝑌值因此,我们将按年龄分组,并使用中位数计算工资总额。

参数选择

定义回归样条的参数包括样条的阶数以及节点的数量和位置。有时关于被建模的关系的领域知识可以提供一些关于结应该放置在哪里的指示。对于平滑样条,必须选择平滑参数。在实践中,对于所有类型的样条,参数可以通过交叉验证进行调整,或者根据残差图的分析进行设置,这取决于建模的目标。

总结和结论

  1. 多项式和样条函数允许对非线性关系进行建模,比线性模型具有更强的预测和解释能力。他们通过对输入要素进行一些变换,然后在线性模型中使用变换后的要素来实现这一点。
  2. 分段多项式通过将输入特征域划分为连续的区间,并在每个区间中拟合一个单独的多项式来获得。它们可以被迫在节点处连续,但它们往往不是平滑的。
  3. 三次样条是对分段多项式光滑性问题的一种回答。它们通过要求节点两侧的前两个导数相同来确保节点处的光滑性。然而,它们也有自己的缺点:三次样条的行为在输入的观察值之外往往是不稳定的。
  4. 自然样条增加了额外的约束,即函数在边界节点以外是线性的,这使得它在那些区域更加可靠。
  5. 平滑样条通过平衡模型与数据的接近度和拟合曲线的复杂性之间的平衡获得:正则化参数惩罚可能导致过度拟合的过于复杂的函数。
  6. 回归(三次和自然)样条曲线的参数包括结的数量和位置。对于平滑样条,需要选择正则化参数。参数选择可以基于领域知识、交叉验证或残差属性。

本文中的所有例子都以单变量样条为特色:只有一个输入变量。在实践中,人们通常希望在模型中包含多个预测值。不用担心:所有讨论的方法都自然地延伸到多元情况。例如,检查 csaps 包中的multivariatecubismoothingspline类。

对于熟悉 R 语言的读者来说,最后一句话是:在样条建模方面,R 比 Python 提供了更多。查看 样条 包中的 bs() 函数(顺便说一下,这是 Python 的 statsmodels 在幕后模仿的)和mgcv。**

感谢阅读!我希望你已经学到了对你的项目有益的东西🚀

如果你喜欢这篇文章,试试我的其他文章。不能选择?从这些中选择一个:

* [## 线性回归中收缩法和选择法的比较

详细介绍 7 种流行的收缩和选择方法。

towardsdatascience.com](/a-comparison-of-shrinkage-and-selection-methods-for-linear-regression-ee4dd3a71f16) [## 增强你对助推的把握

揭秘著名的竞赛获奖算法。

towardsdatascience.com](/boost-your-grasp-on-boosting-acf239694b1) [## 插补的不确定性

你在预测中考虑到它了吗?

towardsdatascience.com](/uncertainty-from-imputation-8dbb34a19612)

来源

  1. Hastie,Tibshirani,r .,,j . h . Friedman(2009 年)。统计学习的要素:数据挖掘、推理和预测。第二版。纽约:斯普林格。
  2. https://pypi.org/project/csaps/*

非最大抑制(NMS)

原文:https://towardsdatascience.com/non-maximum-suppression-nms-93ce178e177c?source=collection_archive---------2-----------------------

一种过滤物体探测器预测的技术。

典型的对象检测流水线具有一个用于生成分类建议的组件。提议只不过是感兴趣对象的候选区域。大多数方法在特征图上采用滑动窗口,并根据在该窗口中计算的特征来分配前景/背景分数。邻域窗口在某种程度上具有相似的分数,并且被认为是候选区域。这导致了数百个提议。由于建议生成方法应该具有高召回率,所以我们在这一阶段保持宽松的约束。然而,通过分类网络处理这么多建议是很麻烦的。这就产生了一种基于某种标准(我们很快就会看到)过滤建议的技术,称为非最大抑制。

NMS:

输入:建议框 B 的列表,对应的置信度得分 S 和重叠阈值 n

输出:过滤后的建议列表

算法:

  1. 选择具有最高置信度得分的提议,将其从 B 中移除,并将其添加到最终提议列表 D 中(最初 D 为空)。
  2. 现在,将该提议与所有提议进行比较,计算该提议与所有其他提议的 IOU(交集/并集)。如果 IOU 大于阈值 N,则从 b 中删除该建议。
  3. 再次从 B 中的剩余提议中取出置信度最高的提议,并将其从 B 中移除,然后将其添加到 d 中。
  4. 再次用 B 中的所有建议计算该建议的 IOU,并排除 IOU 高于阈值的方框。
  5. 重复这个过程,直到 b 中不再有建议。

IOU 计算实际上用于衡量两个方案之间的重叠部分。

Intersection over Union

下面是 NMS 的伪代码。为了更好地理解它,我添加了一些评论。

Non-Max Suppression Algorithm

现在如果你观察上面的算法,整个过滤过程依赖于单个阈值。因此,阈值的选择是模型性能的关键。然而,设置这个阈值是棘手的。让我们看看这个场景。

假设重叠阈值 N 是 0.5。如果有一个建议的 IOU 为 0.51,并且具有良好的置信度得分,则该框将被移除,即使其置信度高于许多其他 IOU 较少的框。正因为如此,如果有两个物体并排,其中一个就会被消除。具有 0.49 IOU 的提议仍然被保留,即使其置信度非常低。当然,这是任何基于阈值的技术的已知问题。现在我们该如何处理?下面是这种情况的一个例子。仅保留 0.9 的建议,其他建议将被删除。这降低了模型的精度。

处理这种情况的简单而有效的方法是使用软 NMS。思路很简单——“不是完全剔除 IOU 高、可信度高的提案,而是降低与 IOU 值成正比的提案的可信度”。现在让我们把这个想法应用到上面的例子中。不是完全删除得分为 0.8 的建议,而是保留这些建议,但降低其得分,如下图所示。

Soft-NMS

正如我前面提到的,两份建议书的 0.4 分都是根据借据价值计算的。分数计算如下

si — score of proposal i, bi — box corresponding to proposal i, M — box corresponding to maximum confidence, Nt — IOU threshold

因此,这只是 NMS 算法实现中的一行变化,它在很大程度上提高了精度。下图显示了两种算法(NMS 和软 NMS),这是我从软 NMS 论文。

这些技术对于过滤单个模型的预测很有效,如果您有来自多个模型的预测呢?加权盒融合是一种结合目标检测模型预测的新方法。查看我的文章以了解更多信息。

[## 加权盒融合

一种组合来自集合目标检测模型的盒子的方法

towardsdatascience.com](/weighted-boxes-fusion-86fad2c6be16)

我在下面的参考资料中给出了 NMS 和软 NMS 实现的 github 链接。这就是这篇文章的全部内容,非常感谢你和我在一起。

参考文献:

  1. 【https://arxiv.org/pdf/1704.04503.pdf
  2. https://github . com/rbgirshick/fast-rcnn/blob/master/lib/utils/NMS . py
  3. https://github.com/bharatsingh430/soft-nms
  4. https://github.com/DocF/Soft-NMS—Python 实现。

订阅 FOCUS——我的每周简讯,获取人工智能的最新更新和最新进展,以及来自机器学习媒体的精选故事。

假设检验中的非参数检验

原文:https://towardsdatascience.com/non-parametric-tests-in-hypothesis-testing-138d585c3548?source=collection_archive---------7-----------------------

KS 测试、曼-惠特尼 U 测试、KW 测试等等

z 检验,学生 T 检验,配对 T 检验,ANOVA,MANOVA?实际上,它们都属于参数统计家族,该家族假设样本数据来自可以通过概率分布充分建模的人群,该概率分布具有一组固定的参数(平均值、标准偏差),也称为正态分布

Normal Distribution

参数测试通常假设三件事:

  • 病例的独立性:样本是独立的观察值
  • 正态性:样本数据来自正态分布(或者至少是对称)
  • 方差齐性:样本数据来自具有相同方差的总体

然而,在现实生活中,这些假设几乎无法满足。非参数检验的假设要宽松得多,它们要么是无分布的,要么是有指定的分布,但分布的参数未指定。

我们什么时候使用非参数测试?

在我最近的项目中,我比较了有折扣和没有折扣时消费者购买调味品的平均数量。显然这两个样本分布不是参数分布。这是否意味着我不能使用参数测试?

不一定。

别忘了中心极限定理!样本看起来不对称并不一定意味着总体不是正态分布的。中心极限定理表明如果样本量足够大,任何独立随机变量的均值的抽样分布将是正态或接近正态的。多大才算够大?通常,当总体分布大致呈钟形时,样本量至少为 30 是安全的。

正态性检验

如果样本量很小(小于 30),第一步总是检验总体的正态性。 Kolmogorov-Smirnov 检验(KS 检验)可用于此!Kolmogorov–Smirnov 统计量量化了样本的经验分布函数和参考分布的累积分布函数之间的距离,或者两个样本的经验分布函数之间的距离。

KS 检验的无效假设是样本取自参考分布。在 Python 中,使用 Scipy 库非常容易。

import scipy.stats as statst, pvalue = stats.kstest(sample, 'norm')

假设你的阿尔法水平是 0.05。如果 p 值大于 0.05,这意味着您不能拒绝空值。你可以说样本来自正态分布,置信水平为 95%。

方差相等性检验

如果你的样本足够大,检验方差的相等性(homoscedasticity)实际上更重要。Levene 的测试就是为此而设计的。Levene 检验可用于评估两组或多组变量的方差相等性。Levene 检验的无效假设是样本取自方差相同的总体。如果观察到显著的结果,应该转换到像韦尔奇的 T 检验或其他非参数检验。

python 代码如下:

import scipy.stats as statst, pvalue = stats.levene(sample1, sample2, ..., center = 'mean')

请注意,“中心”可以是平均值、中间值或修整值。

常用的非参数检验

Kolmogorov-Smirnov 检验(2 个样本的 KS 检验)

这是对两个独立样本取自同一连续分布的零假设的双边检验。如果 K-S 统计量很小或者 p 值很高,那么我们不能拒绝两个样本的分布相同的假设。

import scipy.stats as statst, pvalue = stats.ks_2samp(sample1, sample2) 

曼-惠特尼 U 检验(2 样本 t 检验的非参数版本)

当因变量不是正态分布时,Mann-Whitney U 检验通常用于比较两个独立组之间的差异。它通常被认为是独立 t 检验的非参数替代方法。Mann-Whitney U 的零假设是从具有相同分布的总体中选择两个独立的样本。

import scipy.stats as statst, pvalue = stats.mannwhitneyu(sample1,sample2, alternative=None) 

克鲁萨尔-沃利斯 H 检验(KW 检验——单向方差分析的非参数版本)

Krusal-Wallis H-test 检验所有组的人口中位数相等的零假设。它是方差分析的非参数版本。一个显著的 Kruskal-Wallis 检验表明,至少一个样本随机支配另一个样本。测试并不确定这种随机优势发生在哪里,也不确定有多少对群体获得随机优势。因此,需要在组之间进行事后比较,以确定哪些组是不同的。

import scipy.stats as statst, pvalue = stats.kruskal(sample1, sample2, ...,) 

作为一个总结,在选择任何测试方法之前,总是要确保你有一个坚实而清晰的假设陈述,说明你是在测试均值还是分布。

然后,确保您的样本数据和总体符合您将要进行的测试的假设。正态性和方差是需要考虑的事情。然后如果你最终得到的是非参数测试,玩得开心,正确解读!下面的流程图在选择最佳测试时非常方便。

享受测试!

Hypothesis Tests Flow Chart

非线性动力学和混沌

原文:https://towardsdatascience.com/nonlinear-dynamics-and-chaos-14b20a41c19a?source=collection_archive---------20-----------------------

这篇文章是我最近从圣达菲研究所的在线课程中学到的非线性动力学和混沌理论的总结。所有的材料都归研究所所有。

[## 复杂性浏览器

关于课程:在本课程中,你将学习科学家用来理解复杂系统的工具。的…

www.complexityexplorer.org](https://www.complexityexplorer.org/courses/97-introduction-to-complexity)

动力学是数学的一个分支,研究系统如何随时间变化。直到 18 世纪,人们都相信,只要知道“所有使自然运动的力量,以及组成自然的所有项目的所有位置”(那个人被称为拉普拉斯恶魔),未来就可以被完美地预测。

现在,假设我们相信世界是完全确定的,那么这个陈述是有意义的。问题是在现实中,测量值(例如力和位置)通常是近似值。我们当时没有意识到的是,即使一个人知道所有变量的值,一个稍微不准确的近似值可能会导致完全不同的未来。这相当令人沮丧,因为它表明,在现实中,即使我们可以建立一个类似拉普拉斯恶魔的超级计算机,为了让它对未来做出任何有意义的预测,所有变量的值都必须完美地获得;一点偏差都不允许。这种“初始条件的小差异在最终现象中产生非常大的差异”(庞加莱)的现象是用混沌理论来研究的。

在下一节中,我们将探索一个简单的动态系统,并展示它如何产生混沌。

人口模型

假设一个地方的人口增长可以用下面的等式来模拟。在时间 t+1 的人口数 n(t+1)等于在时间 t 的当前人口数 n(t)减去死亡率,用 n(t) /k 表示,或者一个地方相对于最大允许人口数 k 的人口过剩程度,乘以新生儿出生率。

通过一些代数运算,我们可以把它转换成一个三变量的方程。

关于 x(t)和 x(t+1)的最后一个方程是迭代方程的典型例子。为了更直观地了解这个等式意味着什么,我们将用三张图来分析它。所有这些模拟都是用 netlogo 完成的。课程中也提供了代码。

x(t)与 x(t+1)

该图表(或地图)绘制了当前状态 x(t)与下一个状态 x(t+1)的关系。我们可以看到图表上显示了一个单峰地图(这基本上是一个 Rx{t}(1-x{t})的图)。随着时间的推移,我们追踪这个点的行程,我们可以看到它在 x 等于 0.64 之前振荡了一段时间。

然而,如果我们将参数 R 的值设置为其他值,比如 3,这种行为就会改变。该点永远在两个位置之间振荡。它仍然稳定下来,虽然不是在一个静态的位置,而是两个可能的值。

t 对 x(t)

对于上面的每个逻辑图,我们还可以看到点的位置是如何随时间变化的,即通过绘制时间 t 对 x(t)的曲线。

R = 2.82

对于第一个逻辑图(R = 2.82),我们看到 x 的值最终稳定为单一值。这就是为什么我们看到前面图表中的蓝点在一段时间后停止移动。

R = 3.2

同时,对于第二个逻辑图(R = 3.2),我们看到 x 最终在两个值之间振荡,这解释了为什么之前图表中的蓝点永远在两个位置之间移动。

r 对 x

请记住,从 x(t) vs x(t+1)图表中可以看出,R 的值决定了动态如何随时间收敛。在这一节中,我们将绘制 R 与系统稳定下来的稳定点数的关系图(也称为吸引子)。

我们可以看到,对于 R = 2.82,只有一个吸引子(大约 0.64 到 0.65),而对于 R =3.2,观察到两个吸引子。注意,随着 R 的增加,吸引子的数量有增加的趋势。在某一点上(当 R 约为 3.569946……),吸引子的数量达到无穷大(见图中深色阴影区域)。此时,系统振荡幅度很大,几乎没有显示任何模式。这一点也被称为混沌的开始。

混乱

当吸引子的数量巨大时,从不同条件出发的两个点不会收敛到同一个稳定点。这与例如当 R = 2.82 时不同,在 R = 2.82 时,无论初始点是什么,系统最终都将收敛到相同的吸引子。

在混沌开始时,有时一个稍微不同的初始点会导致非常不同的结果。例如,请参见下面的模拟。

两个点,一个从 0.20000 开始,另一个从 0.20001 结束,当 R = 4 时,轨迹完全不同(参考分叉图,我们看到这导致了巨大数量的吸引子)。

混沌的普遍性

现在研究人员开始询问一个混沌系统是否完全混沌。似乎可以从这种系统中观察到一些模式。

例如,科学家发现所有单峰/单峰地图都有一个共同的费根鲍姆常数。这是通过将分支点(也称为分叉)之间的电流间隙与下一个电流间隙之比得出的。

Lines marking all bifurcations

Feigenbaum Constant

对此的解释是,每次分叉发生的速度大约是前一次的 4.6692016 倍。这一发现让我们看到了“混沌中有秩序”的希望。

摘要

在这篇文章中,我们通过剖析一个人口增长模型简要分析了非线性动力学和混沌。这是圣达菲学院提供的复杂系统课程的一部分。

数据科学家的非技术性职业技能

原文:https://towardsdatascience.com/nontechnical-career-skills-for-data-scientists-b420d592aba6?source=collection_archive---------26-----------------------

苹果 | 谷歌 | SPOTIFY | 其他 | 剪辑

苏珊·霍尔科姆在 TDS 播客

编者按:这是迈向数据科学播客“攀登数据科学阶梯”系列的第三集,由 Jeremie Harris、Edouard Harris 和 Russell Pollari 主持。他们一起经营一家名为sharpes minds的数据科学导师创业公司。可以听下面的播客:

很容易将数据科学视为一门技术学科,但在实践中,事情并不真的是这样。如果你要成为一名成功的数据科学家,人们将需要相信你能增加价值以便雇佣你,人们将需要相信你的宠物项目以便在你的公司内部认可它,人们将需要根据你从数据中得出的见解做出决策。

虽然很容易忘记人的因素,但如果你想爬上数据科学的阶梯,获得第一份工作或你追求的晋升,管理它是你可以发展的最有用的技能之一。这就是为什么我们采访了世界上第一家智能手表公司 Pebble 的前数据主管 Susan Holcomb。

当 Pebble 第一次聘用她时,苏珊刚刚从物理学研究生院毕业,从未领导过团队,也没有与初创公司高管打过交道。随着公司的发展,她必须想办法让 Pebble 的领导层支持她努力推动公司朝着更加数据驱动的方向发展,同时她还必须第一次管理一个数据科学家团队。在我们的谈话中,Susan 讲述了她从这个过程中学到的很多东西:

  • 重要的是要考虑你的个性与你的目标角色有多契合。如果你想在早期创业公司工作,那很好——但不要指望能整天摆弄模型和优化 AUC 分数。越早进入公司的舞台,你就越需要扮演一个多面手的角色。这通常意味着同时担任分析师、数据科学家和数据工程师。
  • 数据科学家是问题解决者,而不是算法生成者。苏珊加入 Pebble 后不久,她注意到自己的数据中有一个异常:似乎许多用户都是在带着智能手表睡觉的。她主动在办公室里做了一项民意调查,果然,结果是 10%的人都是这么做的。这种见解导致了一套强大的睡眠跟踪和健康监测功能,远远领先于他们的时代。其中大多数没有使用像神经网络这样的复杂算法,甚至没有决策树;他们是简单的基于规则的系统,但他们做到了。这个故事的寓意是:优秀的数据科学家不会过度设计花哨的算法——他们能快速发现数据趋势,并利用它们解决明显的业务问题。
  • 大多数人都不擅长向他人寻求推荐或技术帮助。他们最终在 LinkedIn 上给人们发信息,却没有给他们提供价值(例如,“我想知道你是否可以把我介绍给你网络中的一些人……”),或者在招聘人员找工作时向他们发送数百封自我服务、复制/粘贴的电子邮件。值得花时间研究你联系的人,并在你的信息中向他们展示你已经做到了。猜测他们的问题可能是什么(例如,“我在看你的网站,注意到你的产品推荐并不像他们应该的那样具体……”),并在询问你想要什么之前提供解决方案(“我有一些关于你可以改进的方法的想法……”)。

不幸的是,数据科学家经常忽视该行业的商业和个人现实,但与 Susan 的交谈明确了一件事:当你允许自己以更人性化的视角看待该领域时,数据科学中的个人成长(和职业发展)会变得容易得多。

TDS 播客—剪辑

如果你在推特上,随时欢迎和我联系 @jeremiecharris !

正态性检验:图解方法

原文:https://towardsdatascience.com/normality-testing-the-graphical-way-20902abd8543?source=collection_archive---------32-----------------------

下面的要点提供了全部代码

在处理回归问题时,有一些特定的假设是适用的。以线性回归为例,我们有以下假设-

1)我们在自变量和目标变量之间有一个线性关系。
2)我们的数据是同方差的
3)残差具有正态分布
4)最小多重共线性

本笔记的主题是第三点:我们如何知道线性回归模型的残差是正态分布的?这就引出了一个更普遍的问题。给定一个数据集,我们能说数据是正态分布的吗?这似乎是一个相当小的问题,只需绘制数据的直方图,看看它是否像正态分布。直方图可能具有欺骗性,它取决于您选择的箱数,而箱数又取决于可用数据点的数量。

幸运的是,我们可以使用某些工具来确定一个数据集是否来自正态分布。

在这本笔记本中,我们将介绍两种图形工具:
1)图形方式:直方图
2)图形方式:分位数-分位数(qq)图

用于确定数据是否来自正态分布的检验称为正态性检验。

在我们进入之前,让我们设置一个问题。我们生成一个数据集并建立一个线性回归问题。我们给它拟合一个模型,得到残差。

# # generate data and visualize it
np.random.seed(1)
x = np.arange(0,1000)
noise = np.random.normal(0,10,1000)
slope = 0.1
b = 5.0y = (slope*x)+b 
y_noised = y+noise# test train split 
x_train, x_test, y_train, y_test = train_test_split(x,y_noised, test_size=0.2, random_state=1)x_train_shape = x_train.shape[0]
y_train_shape = y_train.shape[0]x_train_reshaped = x_train.reshape(x_train_shape, 1)
y_train_reshaped = y_train.reshape(y_train_shape, 1)x_test_shape = x_test.shape[0]
x_test_reshaped = x_test.reshape(x_test_shape, 1)# fitting the model in sklearn 
lr = LinearRegression()
lr.fit(x_train_reshaped, y_train_reshaped)pred_slope = lr.coef_
pred_b = lr.intercept_
y_pred= lr.predict(x_test_reshaped)
residuals = y_test — y_pred.reshape(y_pred.shape[0],)# fitting the model line to the data 
model_line = (pred_slope*x)+pred_b
model_line_reshaped = model_line.reshape(model_line.shape[1])fig = make_subplots(rows=1, cols=2,subplot_titles=[“Linear data”, “Residual Plot”])fig.add_trace(go.Scatter(x=x,y=y_noised, mode=’markers’, marker={‘color’:’green’}, name=”noised data”), row=1, col=1)
fig.add_trace(go.Scatter(x=x, y=model_line_reshaped, mode=’lines’, marker={‘color’:’red’}, name=’model’), row=1, col=1)
fig.add_trace(go.Scatter(x=x_test, y=residuals, mode=’markers’, marker={‘color’:’blue’}, name=’residuals’), row=1, col=2)fig.update_xaxes(title_text=”x” ,row=1, col=1)
fig.update_xaxes(title_text=”x”, row=1, col=2)
fig.update_yaxes(title_text=”Y noised”, row=1, col=1)
fig.update_yaxes(title_text=”error = predicted-observed” , row=1, col=2)
fig.update_layout(title_text=”Figure 1")iplot(fig)

直方图的问题

图 1 右边的图是残差图。残差是实际值(图 1 左侧图中的绿点)和预测值(红线)之间的差值。线性回归的假设之一是残差来自正态分布,另一种说法是直方图类似正态分布。请看下面的图 2。直方图具有单峰,在面元-5 到 0 周围有 20 个面元,并在两侧下降。但是,我们能说这个直方图代表的是正态分布吗?也许吧。当我们改变箱的大小时,我们的结论变得更加模糊,因为没有简单的方法来说明正态分布的峰值在哪里。这使得我们很难判断哪种箱大小适合解释分布。

直方图是说明数据来自正态分布的一种图形方式,但直方图可能具有欺骗性,因为改变条柱的数量会改变分布的形状,这可能会导致一些混淆。我们需要一种更好的方法来识别数据是否来自正态分布。这就是分位数-分位数图的用处。

residual_df = pd.DataFrame(data=residuals,columns=[“residuals”])# callback function for the slider**def** change_bins(number_bins):
 return px.histogram(residual_df, x=”residuals”, nbins=int(number_bins), title=”Figure 2")slider_obj = widgets.FloatSlider(value=20, min=10, max=100,step=5, description=”Num of bins”, continuous_update=False)
interact(change_bins, number_bins=slider_obj);

使用 Plotly 的简单分位数-分位数图

使用直方图的替代方法是使用分位数-分位数图。分位数-分位数图(qq 图)是一种散点图,其中我们绘制数据集值与从数据集确定的分位数的正态分布值。qq 图的 y 坐标是数据集值,x 坐标是正态分布的值。

为了生成分位数-分位数图的数据,我们必须定义需要正态分布值的分位数,所以首先我们写-

num_divisions = residuals.shape[0]+1
quantiles = np.arange(1,residuals.shape[0])/num_divisions 

num_divisions 告诉我们在正态分布中我们需要多少个除法。如果你运行上面的代码,你会看到分位数是-

[0.00497512, 0.00995025, 0.01492537, 0.0199005 …]

所以如果一个数据集中有n个数据点,我们需要把正态分布分成n+1个区域,从正态分布得到n

例如,在我们的案例中,数据集中有 200 个点,因此我们需要在正态分布中有 201 个分区。一旦我们有了分位数值,我们就将它们插入 ppf 函数。这是累积分布的倒数,它给出了给定分位数值的正态分布的 z 得分。

我们输入到 ppf 函数中的分位数值只不过是正态曲线下面积与 1 的比值。

 qq_x_data = sps.norm.ppf(quantiles) 

这些值是 qq 图的 x 值,我们通过对残差排序得到 y 值

qq_y_data = np.sort(residuals) 

接下来,我们需要获取绘制参考线的数据。为此,我们需要两点来确定直线的斜率和 y 轴截距。为此,我们将采用克里夫兰在可视化数据方面的建议[1]。
第一个和第三个四分位数的 x 值将来自正态分布。y 值将来自我们的有序数据集。因此我们写道-

# guide line data
line_x0 = sps.norm.ppf(0.25)
line_x1 = sps.norm.ppf(0.75)line_y0 = np.quantile(residuals, 0.25)
line_y1 = np.quantile(residuals, 0.75)

用这两点我们组成一条线-

slope = (line_y1-line_y0)/(line_x1-line_x0)
line_intercept = line_y1 — (slope*line_x1)x_range_line = np.arange(-3,3,0.001)
y_values_line = (slope*x_range_line) + line_intercept

注意:不要对 qq 图上的点拟合回归线,这将不会满足线性回归的假设(想想吧!为什么?)

现在我们有了 qq 图和参考线的数据,我们将使用 plotly 来绘制它们。

fig = go.Figure()fig.add_trace(go.Scatter(x=qq_x_data,
 y=qq_y_data,
 mode=’markers’,
 marker={‘color’:’blue’},
 name=”qq data”))
fig.add_trace(go.Scatter(x=x_range_line,
 y=y_values_line,
 mode=’lines’,
 marker={‘color’:’red’},
 name=”guide line”))fig[‘layout’].update(title=’Figure 3',
 xaxis={
 ‘title’: ‘Theoritical Quantities’,
 ‘zeroline’: True
 },
 yaxis={
 ‘title’: ‘Sample Quantities’
 },
 showlegend=True,
 )iplot(fig)

看一个 qq 图的方法是看有多少点落在参考线上。如果大多数点落在这条线上,那么我们假设数据代表正态分布。如果大多数点不遵循这一趋势,那么我们可以说数据不具有正常趋势。通常在这种情况下,我们应该尝试其他的正态性检验,如安德森-达林检验、KS 检验等,以确保数据不是正态的。我们将在下一个笔记本中深入研究,看看如何结合和解释正态性的图形和假设检验。

从该图中可以得出的主要结论是,qq 图是解读数据集是否遵循正态分布的简单图形方式。

分位数-各种分布数据的分位数图

在本节中,我们将研究来自不同分布类型的数据,并展示如何使用 qq 图将它们与正态分布进行比较。

假设我们有一个服从均匀分布的数据集。那么 qq 剧情看起来就不一样了。

uniform_data = np.random.uniform(0,10,1000)num_divisions = uniform_data.shape[0]+1
quantiles = np.arange(1,uniform_data.shape[0])/num_divisions# scatter data 
qq_uniform_x = sps.norm.ppf(quantiles)
qq_uniform_y = np.sort(uniform_data)line_y0 = np.quantile(uniform_data, 0.25)
line_y1 = np.quantile(uniform_data, 0.75)slope = (line_y1-line_y0)/(line_x1-line_x0)
line_intercept = line_y1 — (slope*line_x1)# points to plot the line 
x_uniform = np.arange(-3,3,0.001)
y_uniform = (slope*x_range_line) + line_interceptfig = make_subplots(rows=1, cols=2,subplot_titles=[“Data histogram”, “QQ plot”])fig.add_trace(go.Histogram(x=uniform_data,
 name=”uniform data”),
 row=1,
 col=1)
fig.add_trace(go.Scatter(x=qq_uniform_x,
 y=qq_uniform_y,
 mode=’markers’,
 marker={‘color’:’blue’},
 name=”qq data”),
 row=1,
 col=2)
fig.add_trace(go.Scatter(x=x_uniform,
 y=y_uniform,
 mode=’lines’,
 marker={‘color’:’red’},
 name=”guide line”),
 row=1,
 col=2)fig.update_xaxes(title_text=”data values”, row=1, col=1)
fig.update_xaxes(title_text=”theoretical quantiles”, range=[-4,4], row=1, col=2)
fig.update_yaxes(title_text=”Count”, row=1, col=1)
fig.update_yaxes(title_text=”observed quantiles” , row=1, col=2)iplot(fig)

您可以看到分散点呈 s 形曲线,许多点不在参考线上。这是一个好迹象,表明观察到的数据不是来自正态分布。在直方图中也可以看到同样的情况。

事实上,我们可以对许多其他分布类型这样做。这是一个比较残差数据和多重分布的图表。为此,我们将使用 ipython 小部件将多个情节浓缩成 plotly。

在分布函数中探讨分布的参数,以生成不同形状的数据分布。例如,更改对数正态分布的平均值和标准差,以查看直方图和 qq 图会发生什么变化。这将有助于您查看不同类型的数据及其 qq 图。

def get_qqdata(observed_data):
 np.random.seed(0)
 num_divisions = observed_data.shape[0]+1
 quantiles = np.arange(1,observed_data.shape[0])/num_divisions# scatter data 
 qq_x = sps.norm.ppf(quantiles)
 qq_y = np.sort(observed_data)line_y0 = np.quantile(observed_data, 0.25)
 line_y1 = np.quantile(observed_data, 0.75)slope = (line_y1-line_y0)/(line_x1-line_x0)
 line_intercept = line_y1 — (slope*line_x1)# points to plot the line 
 x_line = np.arange(-3,3,0.001)
 y_line = (slope*x_range_line) + line_interceptqq_data = {‘qqx’: qq_x, ‘qqy’:qq_y, ‘linex’: x_line, ‘liney’:y_line}

 return qq_datadef dist_qqplot(dist_data, dist_name) :
 qq_data = get_qqdata(dist_data)fig = make_subplots(rows=1, cols=2,subplot_titles=[“Data histogram”, “QQ plot”])
 fig.add_trace(go.Histogram(x=dist_data, name=dist_name), row=1, col=1)
 fig.update_xaxes(title_text=”data values” ,row=1, col=1)
 fig.add_trace(go.Scatter(x=qq_data[“qqx”] , y=qq_data[“qqy”], mode=’markers’, marker={‘color’:’blue’}, name=”qq data”), row=1,col=2)
 fig.add_trace(go.Scatter(x=qq_data[“linex”], y=qq_data[“liney”], mode=’lines’, marker={‘color’:’red’}, name=”guide line”), row=1,col=2)fig.update_xaxes(title_text=”theoretical quantiles”, range=[-4,4], row=1, col=2)
 fig.update_yaxes(title_text=”Count”, row=1, col=1)
 fig.update_yaxes(title_text=”observed quantiles” , row=1, col=2)

 return iplot(fig)def distributions(dist): 

 # change parameter values here to see how the qq plot can change
 selected_data ={“triangular”: np.random.triangular(10,100,115,1000),
 ‘lognormal’: np.random.lognormal(10,1,1000),
 ‘chi square’: np.random.chisquare(8,1000)}

 return dist_qqplot(selected_data[dist], dist )toggle_obj = widgets.ToggleButtons(description=”Distribution:”, options=[“triangular”,”lognormal”, “chi square”])
interact(distributions, dist=toggle_obj);

Histogram and qq plot for a triangular distribution with right value = 10, mode = 100, left = 115 with 1000 samples.

Histogram and qq plot for a lognormal distribution with a mean = 10 and std dev = 1. 1000 samples were generated

Histogram and qq plot for a chi-square distribution with degree of freedom = 8 and 1000 samples are generated

标准化与规范化—定量分析

原文:https://towardsdatascience.com/normalization-vs-standardization-quantitative-analysis-a91e8a79cebf?source=collection_archive---------0-----------------------

停止使用 Sklearn 的 StandardScaler 作为默认的特征缩放方法可以让你的精度提高 7%,即使你的超参数已经调好了!

https://365datascience.com/standardization/

每个 ML 从业者都知道特征缩放是一个重要的问题(在这里阅读更多)。

讨论最多的两种缩放方法是规范化和标准化。 正常化 通常意味着将值重新调整到[0,1]的范围内。 标准化 通常意味着重新调整数据,使平均值为 0,标准差为 1(单位方差)。

在这篇博客中,我进行了一些实验,并希望回答如下问题:

  1. 我们应该总是缩放我们的特征吗?
  2. 有没有单一的最佳缩放技术?
  3. 不同的缩放技术如何影响不同的分类器?
  4. 我们应该考虑缩放技术作为我们模型的一个重要的超参数吗?

我将分析在多个实验设置中对特征应用不同缩放方法的实验结果。

竞赛表格

  • 0.我们为什么在这里?
  • 1.现成的分类器
  • 2.分类器+缩放
  • 3.分类器+缩放+ PCA
  • 4.分类器+缩放+ PCA +超参数调整
  • 5.更多的数据集:
  • — 5.1 澳大利亚的降雨数据集
  • — 5.2 银行营销数据集
  • — 5.3 收入分类数据集
  • — 5.4 收入分类数据集
  • 结论

0.我们为什么在这里?

首先,我试图理解规范化和标准化之间的区别。因此,我遇到了 Sebastian Raschka 写的这个优秀的博客,它提供了满足我好奇心的数学背景。如果您不熟悉规范化或标准化概念,请花 5 分钟时间阅读本博客。
著名的 Hinton 在这里也对处理使用梯度下降方法(如神经网络)训练的分类器时缩放特征的需要做了很好的解释。

好吧,我们抓了些数学,就这样?不完全是。当我检查流行的 ML 库 Sklearn 时,我看到有许多不同的缩放方法。有一个伟大的形象化的不同的定标器对有异常值的数据的影响。但他们没有显示它如何影响不同分类器的分类任务。

我看到很多 ML pipelines 教程使用 StandardScaler(通常称为 Z-score 标准化)或 MinMaxScaler(通常称为 min-max 归一化)来缩放特征。为什么没有人使用其他缩放技术进行分类?有没有可能 StandardScaler 或者 MinMaxScaler 是最好的缩放方法?
我在教程中没有看到任何关于为什么或何时使用它们的解释,所以我想通过运行一些实验来研究这些技术的性能。这就是这款笔记本的全部内容

项目详情

像许多数据科学项目一样,让我们读取一些数据,并用几个现成的分类器进行实验。

资料组

声纳数据集。它包含 208 行和 60 个特征列。这是一项分类任务,以区分从金属圆柱体反弹的声纳信号和从大致圆柱形的岩石反弹的信号。

这是一个平衡的数据集:

sonar[60].value_counts() # 60 is the label column nameM    111
R     97

该数据集中的所有要素都在 0 到 1 之间,但是不能保证 1 是每个要素中的最大值或 0 是最小值。

我选择这个数据集是因为,一方面,它很小,所以我可以很快地进行实验。另一方面,这是一个困难的问题,没有一个分类器达到接近 100%的准确率,所以我们可以比较有意义的结果。

在最后一节中,我们将尝试更多的数据集。

代码

作为预处理步骤,我已经计算了所有的结果(这需要一些时间)。所以我们只加载结果文件并使用它。

产生结果的代码可以在我的 GitHub 中找到:
https://GitHub . com/shaygeller/Normalization _ vs _ standardization . git

我从 Sklearn 中挑选了一些最流行的分类模型,表示为:

(MLP 是多层感知器,一种神经网络)

我使用的定标器表示为:

*不要混淆 Normalizer,上面列表中的最后一个缩放器和我之前讨论的最小-最大归一化技术。最小-最大归一化是列表中的第二个,命名为 MinMaxScaler。Sklearn 的规格化器类将样本分别规格化为单位范数。它不是基于列的,而是基于行的标准化技术。

实验详情:

  • 当需要再现性时,使用相同的种子。
  • 我随机将数据分成 80%-20%的训练测试集。
  • 所有结果都是来自训练集的 10 倍随机交叉验证分割的准确度分数。
  • 我在这里不讨论测试集的结果。通常,测试集应该保持隐藏,并且我们关于分类器的所有结论应该仅来自交叉验证分数。
  • 在第 4 部分中,我执行了嵌套交叉验证。一个内部交叉验证使用 5 个随机分割进行超参数调整,另一个外部 CV 使用 10 个随机分割使用最佳参数获得模型得分。同样在这一部分中,所有数据仅取自训练集。一张图胜过千言万语:

https://sebastianraschka.com/faq/docs/evaluate-a-model.html

让我们阅读结果文件

import os
import pandas as pdresults_file = "sonar_results.csv"
results_df = pd.read_csv(os.path.join("..","data","processed",results_file)).dropna().round(3)
results_df

1.现成的分类器

**import** operatorresults_df.loc[operator.and_(results_df["Classifier_Name"].str.startswith("_"), **~**results_df["Classifier_Name"].str.endswith("PCA"))].dropna()

不错的结果。通过查看 CV_mean 列,我们可以看到目前 MLP 领先。SVM 表现最差。

标准差也差不多,所以主要可以通过平均分来判断。以下所有结果将是 10 倍交叉验证随机分裂的平均分数。

现在,让我们看看不同的缩放方法如何改变每个分类器的分数

2.分类器+缩放

import operator
temp = results_df.loc[~results_df["Classifier_Name"].str.endswith("PCA")].dropna()
temp["model"] = results_df["Classifier_Name"].apply(lambda sen: sen.split("_")[1])
temp["scaler"] = results_df["Classifier_Name"].apply(lambda sen: sen.split("_")[0])def df_style(val):
    return 'font-weight: 800'pivot_t = pd.pivot_table(temp, values='CV_mean', index=["scaler"], columns=['model'], aggfunc=np.sum)
pivot_t_bold = pivot_t.style.applymap(df_style,
                      subset=pd.IndexSlice[pivot_t["CART"].idxmax(),"CART"])
for col in list(pivot_t):
    pivot_t_bold = pivot_t_bold.applymap(df_style,
                      subset=pd.IndexSlice[pivot_t[col].idxmax(),col])
pivot_t_bold

第一行,没有索引名称的一行,是没有应用任何缩放方法的算法。

import operatorcols_max_vals = {}
cols_max_row_names = {}
for col in list(pivot_t):
    row_name = pivot_t[col].idxmax()
    cell_val = pivot_t[col].max()
    cols_max_vals[col] = cell_val
    cols_max_row_names[col] = row_name

sorted_cols_max_vals = sorted(cols_max_vals.items(), key=lambda kv: kv[1], reverse=True)print("Best classifiers sorted:\n")
counter = 1
for model, score in sorted_cols_max_vals:
    print(str(counter) + ". " + model + " + " +cols_max_row_names[model] + " : " +str(score))
    counter +=1

每个模型的最佳分类器:

1.SVM +标准缩放器:0.849
2。MLP +电源变压器-Yeo-Johnson : 0.839
3。KNN + MinMaxScaler : 0.813
4。LR +量化转换器-统一:0.808
5。n b+ power transformer-Yeo-Johnson:0.752
6。LDA+power transformer-Yeo-Johnson:0.747
7。手推车+量化器-制服:0.74
8。射频+归一化因子:0.723

让我们分析结果

  1. 没有一个单一的缩放方法可以统治所有的人。
  2. 我们可以看到缩放改善了结果。SVM、MLP、KNN 和 NB 从不同的扩展方法中得到了显著的提升。
  3. 请注意,NB、RF、LDA、CART 不受某些缩放方法的影响。这当然与每个分类器的工作方式有关。树不受缩放的影响,因为分割标准首先对每个要素的值进行排序,然后计算分割的基尼\熵。一些缩放方法保持这种顺序,因此准确度分数没有变化。
    NB 不受影响,因为模型的先验由每个类中的计数决定,而不是由实际值决定。线性判别分析(LDA)使用类之间的变化来找到它的系数(检查这个,所以缩放也无关紧要。
  4. 一些缩放方法,如 QuantileTransformer-Uniform,不保留每个特征中值的确切顺序,因此即使在上述分类器中分数也会发生变化,而这些分类器对其他缩放方法是不可知的。

3.分类器+缩放+PCA

我们知道一些众所周知的 ML 方法如 PCA 可以从缩放中获益(博客)。让我们尝试将 PCA(n_components=4)添加到管道中,并分析结果。

import operator
temp = results_df.copy()
temp["model"] = results_df["Classifier_Name"].apply(lambda sen: sen.split("_")[1])
temp["scaler"] = results_df["Classifier_Name"].apply(lambda sen: sen.split("_")[0])def df_style(val):
    return 'font-weight: 800'pivot_t = pd.pivot_table(temp, values='CV_mean', index=["scaler"], columns=['model'], aggfunc=np.sum)
pivot_t_bold = pivot_t.style.applymap(df_style,
                      subset=pd.IndexSlice[pivot_t["CART"].idxmax(),"CART"])
for col in list(pivot_t):
    pivot_t_bold = pivot_t_bold.applymap(df_style,
                      subset=pd.IndexSlice[pivot_t[col].idxmax(),col])
pivot_t_bold

让我们分析结果

  1. 大多数时候缩放方法使用 PCA 改进模型,但是没有具体的缩放方法负责。
    我们再来看“QuantileTransformer-Uniform”,这个方法得分最高的占大多数。
    在 LDA-PCA 中,它将结果从 0.704 提高到 0.783(准确度提高了 8%!),但在 RF-PCA 中却让事情变得更糟,从 0.711 降到 0.668(准确率下降 4.35%!)
    另一方面,使用带有“QuantileTransformer-Normal”的 RF-PCA,将精度提高到 0.766(精度跃升 5%!)
  2. 我们可以看到,PCA 只是提高了 LDA 和 RF,所以 PCA 不是一个神奇的解决方案。
    没事。我们没有超调 n_components 参数,即使我们这样做了,PCA 也不能保证改善预测。
  3. 我们可以看到,StandardScaler 和 MinMaxScaler 仅在 16 个案例中的 4 个案例中取得最佳成绩。所以我们应该仔细考虑选择什么样的缩放方法,即使是默认的缩放方法。

我们可以得出结论,尽管 PCA 是一种受益于缩放的已知成分,但没有一种缩放方法总能改善我们的结果,其中一些方法甚至会造成伤害(带标准缩放器的 RF-PCA)。

数据集在这里也是一个重要因素。为了更好地理解缩放方法对 PCA 的影响,我们应该对更多样化的数据集进行实验(类别不平衡、不同尺度的特征以及具有数值和分类特征的数据集)。我在第 5 节做这个分析。

4.分类器+缩放+PCA+超参数调整

对于给定的分类器,不同的缩放方法之间的准确度分数有很大的差异。人们可以假设,当超参数被调整时,缩放技术之间的差异将是微小的,我们可以使用 StandardScaler 或 MinMaxScaler,就像在网络上的许多分类管道教程中使用的那样。让我们检查一下!

第一,NB 不在这里,那是因为 NB 没有参数可以调。

我们可以看到,与上一步的结果相比,几乎所有的算法都受益于超参数调整。一个有趣的例外是 MLP,结果更糟。这可能是因为神经网络很容易过度拟合数据(特别是当参数的数量远大于训练样本的数量时),我们没有仔细地提前停止以避免它,也没有应用任何正则化。

然而,即使调整了超参数,使用不同缩放方法的结果之间仍然存在很大差异。如果我们将不同的缩放技术与广泛使用的标准缩放技术进行比较,当使用其他技术时,我们可以获得高达 7%的精度提升 (KNN 列)。

从这一步得出的主要结论是,即使调整了超参数,改变缩放方法也会显著影响结果。因此,我们应该将标度方法视为我们模型的一个关键超参数。

第 5 部分包含对更多样化的数据集的更深入的分析。如果不想深究,可以直接跳到结论部分。

5.更多的数据集

为了更好地理解和得出更一般化的结论,我们应该用更多的数据集进行实验。

我们将在具有不同特征的几个数据集上应用分类器+缩放+PCA,如第 3 节,并分析结果。所有数据集均取自 Kaggel。

  • 为了方便起见,我只从每个数据集中选择了数字列。在多元数据集(数值和分类要素)中,关于如何缩放要素一直存在争议。
  • 我没有超调分类器的任何参数。

5.1 澳大利亚的降雨数据集

链接
分类任务:预测是不是要下雨了?
度量:精度
数据集形状 : (56420,18)
每个类的计数 :
否 43993
是 12427

这是一个 5 行的例子,我们不能在一张图中显示所有的列。

dataset.describe()

我们怀疑,由于特征的不同比例,缩放将改善分类结果(检查上表中的最小最大值,它甚至在一些其余的特征上变得更差)。

结果

结果分析

  • 我们可以看到 StandardScaler 从未得到最高分,MinMaxScaler 也是如此。
  • 我们可以看到标准定标器和其他方法之间的差异高达 20% 。(购物车-PCA 列)
  • 我们可以看到缩放通常会改善结果。以 SVM 为例,从 78%跃升至 99%。

5.2 银行营销数据集

链接
分类任务:预测客户是否认购了定期存款?
指标 : AUC (数据不平衡)
数据集形状 : (41188,11)
每个类的计数 :
否 36548
是 4640

这是一个 5 行的例子,我们不能在一张图中显示所有的列。

dataset.describe()

同样,不同比例的特征。

结果

结果分析

  • 我们可以看到,在该数据集中,即使要素处于不同的比例上,使用 PCA 进行缩放并不总能改善结果。然而,每个 PCA 列中的第二好的分数非常接近最好的分数。这可能表明超调 PCA 的组件数量并使用缩放将比根本不缩放改善结果。
  • 同样,没有一个单一的缩放方法脱颖而出。
  • 另一个有趣的结果是,在大多数模型中,所有的缩放方法都没有产生太大的影响(通常有 1%-3%的改善)。让我们记住,这是一个不平衡的数据集,我们没有超调参数。另一个原因是 AUC 分数已经很高了(~90%),所以更难看到重大改善。

5.3 斯隆数字巡天 DR14 数据集

链接
分类任务:预测一个物体是星系、恒星还是类星体。
度量:精度(多类)
数据集形状 : (10000,18)
每个类的计数 :
星系 4998
恒星 4152
类星体 850

这是一个 5 行的例子,我们不能在一张图中显示所有的列。

dataset.describe()

同样,不同比例的特征。

结果

结果分析

  • 我们可以看到缩放极大地改善了结果。我们可以期待它,因为它包含了不同尺度的特征。
  • 我们可以看到,当我们使用 PCA 时,RobustScaler 几乎总是获胜。这可能是由于该数据集中的许多异常值移动了 PCA 特征向量。另一方面,当我们不使用 PCA 时,那些异常值不会产生这样的影响。我们应该做一些数据探索来验证这一点。
  • 如果我们将 StandardScaler 与另一种缩放方法进行比较,精确度会有 5%的差异。因此,这是需要试验多种缩放技术的另一个指标。
  • PCA 几乎总是受益于缩放。

5.4 收入分类数据集

链接
分类任务:预测收入是否> 50K,< =50K。
度量 : AUC (不平衡数据集)
数据集形状 : (32561,7)
每个类的计数:
<= 50K 24720

50K 7841

这是一个 5 行的例子,我们不能在一张图中显示所有的列。

dataset.describe()

同样,不同比例的特征。

结果

结果分析

  • 同样,我们有一个不平衡的数据集,但我们可以看到缩放在改善结果方面做得很好(高达 20%!).这可能是因为与银行营销数据集相比,AUC 得分较低(~80%),因此更容易看到重大改进。
  • 即使没有突出显示 StandardScaler(我在每个专栏中只突出显示了第一个最好的分数),但在许多专栏中,它达到了与最好相同的结果,但并不总是如此。从运行时间的结果(没有出现在这里),我可以告诉你,运行 StandatdScaler 比许多其他的 Scaler 快得多。因此,如果你急于得到一些结果,这可以是一个很好的起点。但是如果你想从你的模型中榨取每一个百分比,你可能想体验多种缩放方法。
  • 同样,没有单一的最佳扩展方法。
  • PCA 几乎总是受益于规模化

结论

  • 尝试多种缩放方法可以显著提高您在分类任务中的得分,即使您的超参数已经调优。所以,你应该把缩放方法作为你的模型的一个重要的超参数。
  • 缩放方法对不同的分类器有不同的影响。基于距离的分类器,如 SVM、KNN 和 MLP(神经网络)极大地受益于缩放。但是,即使树(CART,RF)不知道某些缩放方法,也可以从其他方法中受益。
  • 了解模型\预处理方法背后的数学基础是理解结果的最佳方式。(例如,树是如何工作的,为什么一些缩放方法不会影响它们)。当你的模型是随机森林时,如果你知道不应用 StandardScaler,也可以节省你很多时间。
  • 像 PCA 这样的预处理方法,已知受益于缩放,但确实受益于缩放。如果不符合,可能是由于 PCA 的成分数参数设置错误、数据中存在异常值或缩放方法选择不当。

如果你发现一些错误或者有改进实验的覆盖面或有效性的建议,请通知我。

统计规范如何改进建模

原文:https://towardsdatascience.com/norms-penalties-and-multitask-learning-2f1db5f97c1f?source=collection_archive---------21-----------------------

介绍

正则化器通常用于机器学习中,根据统计规范或先前的假设将模型的能力限制在一定范围内。这增加了模型假设空间中一个解决方案相对于另一个解决方案的偏好,或者学习算法被允许选择作为解决方案的函数集[1]。这种方法的主要目的是提高模型的概化能力,或者提高模型在以前看不到的数据上的性能。使用正则化器提高了泛化能力,因为它减少了模型对训练数据的过度拟合

最常见的做法是在学习过程中对目标函数增加一个范数惩罚。下面的等式是正则化的目标函数:

Regularized objective function adding a penalty to the original objective function. From [1].

原始目标函数 J、是参数θ、真实标签 y 和输入 x 的函数。正则化器由罚范数函数ω和对ω的贡献进行加权的罚α组成。下一节将介绍一些常用的惩罚规范。

常用的统计规范

范数是测量向量的长度大小的一种方法。向量范数是使用某种度量来计算的,这种度量可以概括向量离原点的距离。这些不同的度量通常是 L 范数和 L 范数。

L 范数是通过绝对差之和计算出来的,通常被称为曼哈顿范数:|x||₁= |x₁|+ |x₂|+|x₃|+..+| x ₙ|其中| ●|是给定变量的绝对值。虽然这是向量范数,但应用于矩阵时,计算略有不同。例如矩阵 l 的范数是||A|| = |a₁₁|+|a₁₂| +…+|aᵢⱼ|.

L 范数也就是通常所说的欧几里德范数。本定额测量从原点到点 x 的距离。

The Euclidean Norm for a vector.

L∞范数max-norm 测量向量的最大值作为长度:| |t49】xt51】| | |∞= max(|x₁|+ |x₂|+|x₃|+..+| x ₙ|).

这些标准及其变化可以使用 Lᵖ 或 p 标准进行测量。 p-norm 通过以下方式测量:

The p-norm for vectors. From Wikipedia.

The p-norm for matrices. From Wikipedia.

p =1 时,我们得到 L,当 p =2 时,我们得到 L 范数。当 p 接近无穷大时,你得到 L∞范数。

规范是如何用于正则化的

权重衰减是一种优先选择小于 L 范数的权重的方法,使权重更接近原点(见图 1)。结果是,在执行梯度更新之前,学习规则在每一步都以常数因子倍增地缩小权重[1]。换句话说,它将权重限制在由 L 范数限定的区域内。

Figure 1. A toy visual example of weight decay.

不同的ω范数选择会导致不同的首选解决方案(见图 2)。L 和 L 罚范数的行为之间的一个共同区别是 L 导致更稀疏的解,这意味着一些参数的最佳值是 0。这通常用于特征选择,其中移除参数最佳为 0 的特征。

Figure 2. A toy visual example of other choices for Ω.

多任务学习是同时学习几个相似任务的学习问题。例如,在多类学习问题中,任务可以是不同的类。对于每项任务,学习一组不同的参数。这个想法是在任务之间共享信息,他们可以从中受益。换句话说,“在解释与 different 任务相关的数据中观察到的变化的因素中,一些因素是两个或更多任务共有的”[1]。这种方法的目标是提高整体的可推广性。

Figure 3. Toy visualization of Multi-task learning.

通常使用关于任务如何相互关联的先验知识来约束每个任务的不同权重向量(再次参见图 2)。这些约束可以与上面提到的相同,例如 L 范数。这通常是通过对矩阵的列应用范数来实现的。

一个示例是 L 和 L 范数的组合,其中 L 范数应用于每一列,而 L 范数应用于所有列:

The penalty function where R is equivalent to Ω.

结论

还有其他不涉及统计规范的正则化方法,如添加噪声、提前停止学习算法和数据扩充。然而,本文主要关注使用统计规范向学习算法添加约束,作为提高模型可推广性的一种手段。

参考

[1]伊恩·古德费勒、约舒阿·本吉奥和亚伦·库维尔。深度学习。麻省理工出版社。2016.

北极星——麻省理工学院和布朗大学最新最棒的拖放式数据分析

原文:https://towardsdatascience.com/northstar-the-latest-greatest-in-drag-and-drop-data-analytics-from-mit-and-brown-university-4946dd1107cb?source=collection_archive---------12-----------------------

来自麻省理工学院和布朗大学的研究人员开发了一个交互式数据分析系统,该系统运行在触摸屏上,让每个人都可以使用机器学习模型来预测医学研究、销售等。

我们不断听到术语‘面向所有人的数据科学’它真正的含义是什么?
从企业到当地的店主,每个人都有一些问题,他们希望用数据来解决,但尽管企业可能能够聘请数据科学家来为他们做这项工作,但当地的咖啡店老板可能没有这种奢侈。
我们的目标是让数据科学变得如此简单,每个人都可以在日常生活中利用它做出数据驱动的决策。承认大问题可能仍然需要大的解决方案,但是解决日常问题应该不难。正是在消除这一困难的过程中,北极星迈出了重要的一步。

Northstar’s aim is to democratize data science by making it easy to do complex analytics, quickly and accurately.

这是什么?

北极星不是突然出现震惊世界的东西。这是麻省理工学院和布朗大学的研究人员多年合作的结果,产生了这个交互式数据科学系统,它在云中运行,但有一个界面支持任何触摸屏设备,包括智能手机和大型交互式白板。
用户输入系统数据集,并使用手指或数字笔在用户友好的界面上操作、组合和提取特征,以揭示趋势和模式。

ACM SIGMOD 大会上展示了一个新组件,称为“虚拟数据科学家的 VDS”,它可以立即生成机器学习模型,以在数据集上运行预测任务。VDS 基于一种越来越受欢迎的人工智能技术,称为自动机器学习(AutoML),让数据科学知识有限的人训练人工智能模型,根据他们的数据集做出预测。目前,该工具领先于 DARPA D3M 自动机器学习竞赛,该竞赛每六个月评选一次性能最佳的 AutoML 工具。

“即使是不了解数据科学的咖啡店老板也应该能够预测他们未来几周的销售额,以确定购买多少咖啡,在有数据科学家的公司中,数据科学家和非专家之间有很多交流,所以我们也可以将他们带到一个房间一起进行分析。合著者、北极星项目长期负责人蒂姆·菲利普·克拉斯卡说

它是如何工作的?

底部视频中演示的使用案例是必看的。

加载数据— 北极星启动时为空白,白色界面。用户将数据集上传到系统中,然后可以探索、连接、过滤和执行各种类型的 EDA,并具有类似于 Power BI 或 Tableau 的可视化功能。

“这就像一个巨大的无界画布,您可以在其中展示您想要的一切,然后,您可以将事情联系在一起,以创建有关您的数据的更复杂的问题。”“北极星”交互界面的主要发明者兹格拉根说。

近似 AutoML — 借助 VDS,用户现在还可以通过定制适合其任务的模型来对该数据进行预测分析,例如数据预测、图像分类或分析复杂的图形结构。
系统将自动寻找性能最佳的机器学习管道,以标签的形式呈现,并不断更新准确率。用户可以随时停止这一过程,优化搜索,并检查每个模型的错误率、结构、计算和其他内容。

“我和我的合著者花了两年时间设计了来模仿数据科学家的思维方式”尚说

该系统根据各种编码规则,立即识别哪些模型和预处理步骤应该或不应该在某些任务上运行。它首先从那些可能的机器学习管道的大型列表中进行选择,并在样本集上运行模拟。这样做时,它会记住结果并优化选择。在提供快速近似结果后,系统在后端对结果进行细化。但是最终的数字通常非常接近第一近似值。

“对于使用预测器,你不会想等四个小时才得到第一个结果。您希望已经看到发生了什么,如果您发现了错误,您可以立即纠正它。这在任何其他系统中通常都是不可能的。”菲利普·克拉斯卡说

研究人员在 300 个真实世界数据集上评估了该工具。与其他最先进的 AutoML 系统相比,VDS 近似法同样精确,但在几秒钟内生成,这比其他需要几分钟到几小时的工具要快得多。

下一步是什么?

研究人员正在寻求增加一个功能,提醒用户潜在的数据偏差,异常值或错误。新用户可能无法识别数据中存在的此类问题,因此他们的分析将会偏离正轨。

“如果你是一个新用户,你可能会得到结果,并认为它们很棒,但我们可以警告人们,事实上,数据集中可能有一些异常值,这可能表明有问题。”菲利普·克拉斯卡说。

Northstar in all it’s glory

参考

官方麻省理工学院关于北极星
Vimeo
蒂姆·菲利普·克拉斯卡的新闻。北极星:交互式数据科学系统。PVLDB,11(12):2150–2164,2018

不是 1,不是 2…而是 5 种关联方式

原文:https://towardsdatascience.com/not-1-not-2-but-5-ways-to-correlate-6ac92cf42f0f?source=collection_archive---------6-----------------------

寻找相关性的各种算法

Photo by Jonathan Petersson on Unsplash

关联是指两个事物之间的相互关系或关联。几乎在任何业务中或出于个人原因,用与他人的关系来表达某事是有用的。例如,当营销在电视广告上花费更多时,销售额可能会增加,或者当温度升高时,冰淇淋的销售额会增加。通常,相关性是理解这些关系并随后构建更好的业务和统计模型的第一步。

那么,为什么相关性是一个有用的指标呢?

相关性可以(但通常不,正如我们将在下面的一些例子中看到的)表明因果关系的存在

相关性有助于从一个量预测另一个量

相关性被用作许多其他建模技术的基本量和基础

有各种算法来寻找相关性。然而,理解需要相关性的原因是选择正确算法的关键。在本文中,我们将看到寻找相关性的不同算法和技术,以及如何选择合适的算法来确定相关性的提示和技巧

1.散点图——基本技术

散点图是理解两个事物之间是否有任何关联或关系的最简单的方法之一。为了举例说明,让我们来看一个数据集,它包含一些小动物的体重和大脑重量的信息。下面显示了该数据集中的一个示例

Sample Body weight and brain weight (Image by author)

看着这些数据,我们可以提出这样一个问题:体重和大脑重量之间有什么联系或关系吗?查看是否存在任何关联或关系的最简单方法之一是绘制体重与大脑重量的散点图。正如我们从下面的散点图中看到的,体重增加,大脑的重量往往会增加

Scatter Plot (Image by author)

2.皮尔逊相关系数——有可测量的东西

散点图观想技术可以给你一种“感觉”,不管有没有关系。然而,它不允许具体衡量这种关系的强度。这就是算法发挥作用的地方。在算法术语中,关系的强度被称为相关系数。最广泛使用的测量相关系数的算法之一是皮尔逊相关。皮尔逊相关度量连续变量之间的线性关联。换句话说,这个系数量化了两个变量之间的关系可以用线描述的程度。值得注意的是,虽然相关性可以有多种解释,但卡尔·皮尔逊在 120 多年前开发的同一公式至今仍被最广泛地使用

让我们用皮尔逊相关来找出体重和大脑重量之间的关系强度。皮尔森关联将试图拟合体重和大脑重量之间的直线。这条线的斜率给出了关系的强度

下图显示了体重与大脑重量之间的散点图,以及一条适合两点之间的线。线的斜率是 0.955,这是皮尔逊相关系数。皮尔逊系数值在-1 和 1 之间。值-1 表示强负相关,值 0 表示没有相关,值 1 表示强正相关。因此,在本例中,我们的相关值为 0.955,这表明体重和大脑重量之间有很强的正相关性。事实上,我们可以得出结论,在给定的数据中,大脑重量随着体重的增加而增加

Pearson Correlation (Image by author)

现在让我们再举一个产品销售的例子。如下图所示,数据集包含面包、卷饼、松饼等产品的销售额以及当天的温度

下面还显示了一个负相关的例子。下图中使用的数据是咖啡销售额与温度的关系(单位为华氏度)。

Sales and Temperature data (Image by author)

计算出的皮尔逊系数为-0.741,表明负相关。这意味着随着温度的升高,咖啡的销量会下降。

Negative Correlation (Image by author)

下面给出了一个不相关的例子。这个例子对应于有温度的面包的销售。正如你所看到的,直线拟合几乎是直的。皮尔逊相关系数为-0.09,几乎为零。在这种情况下,两个变量之间没有相关性

No Correlation (Image by author)

在这里,您看到了相关性的基础知识,以及我们如何使用散点图和皮尔逊系数来计算相关性。然而,个人相关性有一些缺点,尤其是当数据是非线性的时候。作为一个例子,让我们来看一个数据集,它有墨尔本一个月的平均温度。数据表明从一月到三月气温很高。然后从四月到十月下降;然后在 11 月和 12 月再次上升

该数据集是非线性数据的一个示例,其中温度不遵循线性路径,而是随着月份的变化而上升、下降和上升。如果计算皮尔逊系数的话,会是-0.38,也就是说月份和温度有些负相关。这意味着从一月到十二月气温会下降。然而,事实并非如此。所以皮尔逊系数的缺点是当数据是非线性的时候它就不起作用了

Non-linear data (Image by author)

3.使用相关矩阵—变大…矩阵风格

上述技术,如散点图和皮尔逊相关显示两个变量之间的相关性。如果您的数据集有许多变量,您可能有兴趣找出每个变量组合之间的相关性。为每个组合制作散点图或皮尔逊相关可能很麻烦,尤其是当数据集有许多变量时。在这种情况下,相关矩阵非常有用。

让我们借助产品销售的数据集来说明相关矩阵。正如您在上表中看到的,有许多列。计算所有列组合之间的相关性将非常有用,例如咖啡销售与温度、松饼销售与温度、咖啡与松饼等。然而,在所有组合之间制作散点图或皮尔逊相关性将会使您疲劳和困倦。所以让我们用相关矩阵来保持活跃和清醒。

下面显示的是每个变量组合之间的相关矩阵。相关矩阵以热图的形式显示。单元格越红,表示正相关性越高。单元格越蓝意味着负相关性越高。例如,我们看到温度和汽水有很强的正相关性。此外,正如已经观察到的,温度和咖啡有负相关。同样,松饼和饼干也有很强的正相关性。

因此,相关矩阵是一个很好的视图,可以了解许多列的相关性,而不必单独计算每个组合的相关性。

Correlation Matrix (Image by author)

4.主成分分析(PCA)——发现相关性的另一种有趣的方法

相关性算法不是计算相关性的唯一算法。还有一些其他有趣的方法。一种这样的算法是主成分分析(PCA)。这通常用于数据集维数非常高时的降维。它用于将具有许多列的数据集减少到较少的列,而不丢失数据的本质。作为副产品,它也给出了变量之间的相关性

我们将在产品销售数据集上使用 PCA。这个数据集几乎有 30 列。不可能对 30 列进行数据可视化。所以我们会用 PCA 把数据降维,而不会失去用 PCA 得到的数据的本质。

在我们的产品销售示例中,您可以将 30 列减少到更少的列(例如 2 或 3 列)。在这样做的时候,主成分分析也给出了在特征影响分数方面在实现降维中起重要作用的变量。我们产品销售栏目的特色影响力如下图所示。负侧的列彼此相关,正侧的列彼此相关。所以你可以看到温度和苏打水是正相关的,松饼和咖啡也是正相关的。还有,这意味着温度和咖啡是负相关的。

这些结果与我们用皮尔逊相关技术得到的结果相同。

Feature Influence on dimension reduction (Image by author)

5.套索回归…只看到重要的东西

为了继续我们寻找不同方法来给出相关性的探索,下一站是套索回归。该算法是普通最小二乘法(OLS)的变体。OLS 算法试图拟合两个变量之间的直线,因此本质上是试图找到两个变量之间的相关性。套索是 OLS 的一个变体,它去掉了不相关的变量,从而给了我们相关的变量。

套索算法采用一个目标变量(Y)和多个独立变量(X1,X2 等……)。该算法将试图找出所有自变量与目标变量之间的相关性。Lasso 将尝试计算每个独立变量的系数,该系数给出了与目标变量相关的指示

如果我们以产品销售为例,目标变量(Y)可以是温度,所有独立变量都可以是(咖啡销售、果汁销售等)。Lasso 的结果是独立变量的系数,如下所示

你可以看到咖啡的系数是负的,这意味着咖啡和温度是负相关的。同样,汽水的系数也很高,这意味着汽水和温度正相关

Lasso Regressor coefficient for variables (Image by author)

在这个故事中,你们对相关性有了一个大概的了解,有五种不同的方法可以用来确定相关性。还有其他方法,如斯皮尔曼相关以及 SVM 或神经网络来寻找非线性相关性

你最终将使用的算法的选择取决于你试图解决什么问题,但是看到和匹配不同方法的结果总是好的。如果结果彼此一致,那么你就在正确的轨道上。

额外资源

网站(全球资讯网的主机站)

你可以访问我的网站进行零编码分析。https://experiencedatascience.com

订阅每当我发布一个新的故事时,请及时通知我。

[## 每当 Pranay Dave 发表文章时,您都会收到电子邮件。

每当 Pranay Dave 发表文章时,您都会收到电子邮件。注册后,如果您还没有,您将创建一个中型帐户…

pranay-dave9.medium.com](https://pranay-dave9.medium.com/subscribe)

你也可以通过我的推荐链接加入 Medium。

[## 通过我的推荐链接加入 Medium—Pranay Dave

作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…

pranay-dave9.medium.com](https://pranay-dave9.medium.com/membership)

https://www.youtube.com/c/DataScienceDemonstrated 的 YouTube 频道
这里是我的 Youtube 频道
的链接

“并非所有数据都是平等的”

原文:https://towardsdatascience.com/not-all-data-is-equal-63ad1b53b086?source=collection_archive---------33-----------------------

人在回路中的机器学习专家轶事,作者 Jennifer Prendki

我正在分享我的书《人在回路中的机器学习》中的第一个专家轶事。我有幸与机器学习社区的许多领导者聊过他们的经历。许多人和我分享了值得更多人关注的个人趣闻。

对于书中提到的每个领导者,有两个选择标准:

  1. 他们早期的职业是工程师或科学家。书中所有的专家都是软件工程师、物理学家、语言学家或类似的人,在他们职业生涯的早期阶段。因此,他们知道注释数据和/或构建机器学习模型是什么样的。
  2. 他们成立了一家使用机器学习的公司。因此,专家们也知道考虑推出能够影响现实世界的机器学习产品意味着什么。

对于想在数据科学领域发展的人来说,所有的领导者都是很好的榜样。

第一个轶事伴随着关于主动学习的章节:为人类评论选择正确数据的过程。大多数部署的机器学习模型使用监督学习,有数千甚至数百万人类标记的数据项。主动学习确定哪些原始数据项最适合人工查看和注释。

第一位专家是 Alectio 的创始人兼首席执行官 Jennifer Prendki。她曾在 Atlassian、Figure Eight 和沃尔玛领导数据科学团队,并拥有粒子物理学博士学位。珍妮弗的公司,Alectio ,专门研究数据效率,帮助机器学习团队用更少的数据建立他们的模型。

“并非所有数据都相等”

如果你关心你的营养,你不会去超市,从货架上随机选择商品。你可能最终通过吃超市货架上的随机物品来获得你需要的营养,但是,在这个过程中你会吃很多垃圾食品。我认为很奇怪的是,在机器学习中,人们仍然认为“随机抽样超市”比弄清楚他们需要什么并在那里集中精力更好。

我建立的第一个主动学习系统是必然的。我正在构建机器学习系统,以帮助一家大型零售店确保当有人在网站上搜索时,出现正确的产品组合。几乎就在一夜之间,一家公司的重组意味着我的人工标签预算减少了一半,而我们需要贴标签的库存增加了 10 倍。因此,我的标签团队每件商品的预算只有我们之前的 5%。我创建了我的第一个主动学习框架来发现哪一个是最重要的 5%。结果比预算更大的随机抽样要好。从那以后,我在我的大部分项目中使用了主动学习,因为不是所有的数据都是相等的!

詹尼弗·普伦斯基,《人在回路中的机器学习》,罗伯特·芒罗,曼宁出版公司

You don’t go shopping by randomly sampling from every shelf, so why are you doing this with your data?

我非常感谢 Jennifer 与我以及我的书和这篇文章的读者分享她的专业知识!

有关主动学习的更多信息,请参见我最近分享的多样性抽样和不确定性抽样的备忘单:

[## 多样性抽样备忘单

主动学习的四种常见多样性抽样策略的快速参考。

towardsdatascience.com](/https-towardsdatascience-com-diversity-sampling-cheatsheet-32619693c304) [## 不确定性采样备忘单

用于主动学习的四种常见不确定性抽样策略的快速参考。

towardsdatascience.com](/uncertainty-sampling-cheatsheet-ec57bc067c0b)

你的数据已经有偏差了

许多数据科学家坚持认为随机抽样仍然是他们的首选,因为他们可能会通过主动学习来偏向他们的数据。我认为这是看待你已有数据的错误方式。

继续类比,超市不是食品的无偏样本。首先,有各种各样的因素决定什么会出现在货架上,包括商店的位置、一年中的时间、特定的供应商合作关系、促销和预期利润。

原始数据可能也是如此:有许多因素导致了您可用的原始数据的创建和存储,并且您的原始数据有可能以许多不同的方式过采样和欠采样。正如我在书中指出的,数据中的偏差通常与现实世界中的偏差相关联,因此,如果您不注意如何处理您的数据注释策略,您就有重复或放大现实世界中的偏差的风险。

我建议您假设您的原始数据已经由于最初生成数据的过滤和采样技术而存在偏差。主动学习是帮助你的数据更加公平的一种方式,同时也让你的模型更加准确。

罗伯特·芒罗

2019 年 11 月

并不总是需要预测性分析,探索性分析可以创造奇迹

原文:https://towardsdatascience.com/not-always-predictive-analytics-is-required-exploratory-analysis-can-do-wonders-c1a8d795a4f2?source=collection_archive---------16-----------------------

探索性数据分析

在这个人人都在谈论 ML-Al 驱动的东西的时代,人们不太关心探索性的数据分析。

我经常看到那些刚刚开始数据分析或数据科学职业生涯的人,他们总是倾向于建立模型,经常谈论 ML-AI,但很少关注探索性的数据分析。

但是,在转向 ML-AI 算法之前,人们必须理解探索性数据分析的重要性,因为它提供了如此多的数据信息,它们的特征可以为业务产生许多见解。

探索性数据分析的基本步骤

  1. 了解您的数据:任何数据驱动的任务的第一步也是最重要的一步是了解您的数据集。寻找几个问题的答案:

a)这些数据是怎么回事?

b)有多少个变量?

c)不同类型的变量,如连续变量、分类变量、顺序变量等。

d)您的回应/目标变量是什么?它有多少面旗帜?

让我们为访问个人贷款部分的现有客户获取一个样本数据,我们需要知道,个人贷款的潜在候选人是谁?

Sample data

有三个连续变量——访问量、贷款计算器页面上的浏览量、过去的收入和三个分类变量——国家、现有贷款、贷款需求。

这里,目标变量是需要贷款,它只有两个标志:是,否

2。探索分类变量:现在你已经理解了你的数据,接下来是时候识别分类变量下的数据模式了。例:需要贷款的客户的数量和百分比。

从分类变量中提取信息的方法有多种,可视化和列联表是重要的方法之一。

条形图和饼图是(众多图表中)最重要的两种图表,有助于彻底分析分类变量。

Pie Chart showing the distribution of customers

在我们的例子中,饼图可以告诉我们需要贷款的人与不需要贷款的人的比例。所以我们可以看到,在我们现有的客户中,只有一小部分人需要个人贷款。

Bar Chart showing breakup by country and status

而在另一边,一个条形图显示了国家间的划分,因此,可以给我们关于分布的信息。在这里,我们可以看到英国是最需要贷款的国家,其次是德国。

另一种方法是,当您需要表格格式的数字时,创建列联表,在一个地方提供比例和绝对信息。

Contingency table with a loan against the country

在我们的案例中,我们可以看到,大多数线索来自英国,但德国需要贷款的人的比例更高。

3.探索连续变量:同样在连续变量的情况下,我们有图形可视化以及其他描述性统计方法的可行性。

在可视化的情况下,直方图和箱线图是非常方便和有见地的。它告诉你变量的分布和它的范围。它还有助于发现数据集中的异常值。

Frequency Histogram

在这种情况下,通过查看客户在贷款计算器页面 wrt #上的视图直方图,我们了解到,大约 60%的客户在此期间的访问次数少于 6 次。

在查看需要贷款的人的直方图时,我们可以看到没有客户的访问次数超过 25 次,这意味着他们可能是经常与我们交易但不需要贷款的用户。

在进行描述性统计时,还可以查看最大值、最小值、平均值、四分位数、十分位数、等,从而可以收集关于数据的大量信息。

4。探索多元关系:在此之下,我们建立多个变量之间的关系,试图找出不同变量之间的关系。

散点图是推断多元关系的最佳可视化方法之一。这是两个变量之间的关系图,有助于我们理解两个变量之间是否有任何关系。关系可以是线性的,也可以是非线性的。

Scatter Plot

因此,在这里我们可以推断,在过去的收入和客户的访问之间存在线性关系。越来越多的游客给这个行业带来了越来越多的收入。

除此之外,我们可以简单地寻找两个变量之间的相关性。相关性越高,变量之间的关系越强。

5.衍生新变量:模型构建中的一项重要任务是特征工程(创建新变量),这有助于发现更多关于数据的逻辑信息。分析师必须找到在可用数据集中设计新变量的方法。它可以是分类变量,也可以是连续变量。

在我们的数据集中,由于是关于个人贷款的信息,我们可以假设大多数客户会在下班时间寻找这些信息。所以我们可以设计新的变量

a)“一天的类型”——工作日/周末

b)“一天中的某个时间”——办公时间/个人时间

c)“电子邮件 Id 类型”——个人/企业

d)“访问过的贷款计算器页面”——是/否

现在,让我们看看上面创建的变量的描述性统计数据。

Contingency table for Visited loan page and Type of Hour

因此,上面的应急表为寻找贷款的用户提供了很好的洞察力。因此,如果您需要在短时间内扭转局面,那么您可以对企业说,任何在个人时间内查找信息并访问过贷款计算器页面的用户,都是实际查找贷款的潜在目标。因此,这种有用的见解可以通过 EDA 交付。

额外收获:有时,它也有助于发现异常磁场。例如:如果您的数据集包含位置的 pin 码(数值),则默认情况下,该工具会将其视为连续变量,但您可能希望将其视为分类变量来查找地理混合。当你做探索性的数据分析时,这种微小但不规则的事情可以被识别出来。

因此,探索性数据分析是数据建模中最重要和不可或缺的部分之一。即使你不做预测建模,它也能帮助你深入了解数据。有时候,EDA 给出的信息太多,你甚至不需要创建一个模型。此外,它还可以帮助您进行特征工程,这在模型构建过程中非常有效。

不是每个人都需要实时分析,包括你

原文:https://towardsdatascience.com/not-everyone-needs-real-time-analytics-including-you-d5bb86103e6a?source=collection_archive---------12-----------------------

艺术是为你的度量标准找到一个好的节奏

“实时分析”是一个你经常听到的性感词汇,现在比十年前稍微多一点。营销文案称,获取数据并“实时”做出决策,谁不想这样呢?但以我的经验来看,对于绝大多数用户来说,实时分析并不是人们实际需要的解决方案。ROI 只是在组织到达某一点时才出现。

大多数人可以忍受对查询执行时间和报告延迟的明显放松的限制,节省大量成本和基础设施,并且除了吹嘘的权利之外,不会牺牲任何东西。

有什么吸引力?

有很多市场营销让人们觉得,如果你没有所有的数据,你就会错过机会,并将被一个每毫秒都在做人工智能的世界甩在后面。像往常一样,营销人员会做他们的营销,我们应该对他们兜售的东西持怀疑态度。

不过,基本前提很简单,而且一开始就很有说服力:“我们需要数据/分析/信息来做决策。很难说我们什么时候会需要这些数据来做决定,所以让我们确保我们一直都有这些数据。”还有一种暗示是,神奇的人工智能/人工智能酱可以洒在这样的系统上,“改变你的业务”。

但是所有的事情都是有代价的,那么我们会付出什么代价,我们会得到什么呢?这是给我的吗?

俗话说:好,快,便宜。选两个。

首先,分析基础设施不是免费的,所以通常的权衡适用。

良好(质量和可靠性)

好的分析,广义上是指你能做的分析和得到的结果是好的。从根本上来说,它包含许多内容:

  1. 良好的数据收集—您确信进入分析系统的数据质量良好,没有欠计数/多计数,没有奇怪的偏差,没有错误和奇怪的缺失数据
  2. 好的分析工具——不是所有的分析对所有的数据都有意义,但是你可以访问的那些与你相关,无论是 A/B 测试输出,还是保留/群组分析等。这些问题从简单到极其复杂,但无论如何,您都有信心他们做的是正确的事情

快速(延迟)

在这里,我说的是“关于分析系统如何运行/给出结果的快速”。你可能会说还有一个“快速的,如开发时间”的组件,但是在这个框架中,我认为这是一个成本,并在下一节中讨论它。

一般的经验法则是,你希望分析周转越快,你被迫做出的妥协就越多。我们有限的计算能力是有实际限制的,存储、移动和处理大量数据的硬件也是有限的。唯一的解决方法是使用更复杂的方法,进行大量的预处理、缓存,甚至可能使用定制系统来获得您想要的性能。

便宜($$$$)

构建一个系统需要大量成本,从开发人员的时间和相关的机会成本,到运行分析所需的系统和软件的原始成本。替换现有的系统更加昂贵,到处都有重构、测试和大量的压力。

因为没有人应该在“好”的方面妥协(太多),因为没有人愿意使用一个怀疑数字是否准确的系统。所以最终归结为交易速度和成本。

但我只知道我需要实时分析!

你可能是对的。是不是每个人都在抱怨他们需要一些东西来做决定,而它还没有准备好?是否因为无法及时准备好数据而犯下了可以避免的错误?然后,您应该考虑升级您的基础架构,以减少延迟。它不必是一个$$$的完整大数据 lambda 体系结构堆栈。但是有些事。

如果(这种情况更常见)瓶颈在于人们坐下来用数据做决策。还是只是决策过程本身比较慢?那可能性就小很多了。

拥有数据和分析的最佳时机是你做决定的时候。

我甚至可以说,决策时间(或准备决策的时间)是你需要可用数据分析的最重要的时间。当您的系统崩溃时,来自 metrics 的通知是另一个让它们可用的关键时间(可以说您也需要在那时做出决定)。几乎所有其他东西都是值得拥有的。我觉得这是决定如何平衡好、快、便宜等式的关键。

关键是了解和确定决策的时机,并构建您的度量基础架构来满足这些需求。如果您的系统发生变化,您需要在 5 分钟(或 5 毫秒)内做出响应,您的分析必须比这更快,以便给您时间做出反应。在这种情况下,拥有低数据分析延迟对您来说是有价值的,您会希望投资系统来保持速度。

与此同时,如果管理销售客户,其中每份最后的销售合同都需要几个月才能达成,并且合同持续数年,那么您极不可能从低延迟分析系统中受益,延迟存在于其他地方。类似地,如果您只是将您的数据用于季度报告,并且没有任何实际的业务用例可以让它做得更快,那么您可能也不需要一个花哨的系统。

请注意,这主要是一个组织问题,而不是技术问题。再多的快速分析也无法迫使一个结构像糖蜜一样的组织像糖蜜一样运转。

了解你的决策节奏有助于降低成本

成比例的实时分析系统往往是非常复杂 猛兽。一定程度的规模是不言而喻的,因为(在某种程度上)你可以用高度优化的强大数据库进行相当低延迟的分析。(是的,我在这里把实时和低延迟混为一谈了。)

然而,一旦达到调优数据库所能做的极限,就需要处理传入的数据流,进行一些工程上的欺骗,在快速的短期数据和慢得多的永久数据存储之间架起一座桥梁。您将需要更多的计算能力来处理不断增长的数据量,您将需要更多的网络和存储,然后需要更多的人来维护系统。这是一项重大投资,你需要为维护所有这些机器付出成本。

同时,批处理作业可以简单得多,在极端情况下,当您有 8 个小时的运行时间时,一个弱分析数据库、一个 SQL 查询和一个发送电子邮件的 cron 脚本就可以按时提交报告。

但是互动探索呢?为此,我们需要低延迟。

听着,我是一名分析师,我知道等待 10k+秒(大约 2 小时 45 分钟)是很糟糕的事情。)对于死神回来的一大疑问。但是您的组织愿意花多少钱来将 10k 秒降低到 5k 秒呢?100 分?1s?

由于收益递减,当你的时间需求变短时,成本往往会飙升。通常会有一些唾手可得的成果,比如升级到固态硬盘或更新的硬件。但是没有一个架构是可以永远扩展的,所以最终你不得不把所有的东西都拆了,然后组合一些新的东西,这是很昂贵的。因此,如果有商业案例,是的,争取降低您工作所需的延迟,直到老板愿意为此买单。

如果我们不知道我们需要一个实时分析系统,该怎么办?

是的,这绝对是可能发生的事情。拥有更及时的分析可以导致组织运营方式的根本改变,并产生各种奇妙的独角兽。但是访问大量嘈杂的最新数据也会分散注意力。从纯技术的角度来看,很难预测你应该在这里做什么。

相反,我会后退一步。这是一个关于组织结构本身的问题。如果能够更快地访问数据,it 部门是否愿意甚至有能力做出改变?是否有人了解如何使用数据来制定决策,并且能够改变流程来与之匹配?也许他们想模仿竞争对手的一个用例?

把技术扔给一个没有准备好利用它的组织很难奏效。因此,如果您计划更快地升级您的分析基础架构,您可能需要额外的培训预算。

不是你想的那样:人机关系的未来

原文:https://towardsdatascience.com/not-what-you-think-the-future-of-human-machine-relationship-b890d7f2072b?source=collection_archive---------26-----------------------

机器人会继续为我们工作吗?还是反过来?未来会是什么样子?更重要的是,我们能做些什么来弥补呢?

自从工业革命以来,我们就一直和机器生活在一起。我们每天都在使用手机、笔记本电脑、咖啡机和洗碗机。我们如此习惯于让机器在我们生活的各个方面为我们工作,以至于我们甚至没有注意到机器和我们之间的这些互动。

这次有什么不同?人工智能(AI)时代,机器人与人类之间有哪些新的动态?

你会为机器工作吗?或者你已经是了?

场景一——算法管理:工人被算法管理

越来越多的公司开始用算法来管理他们的劳动力。优步和 Lyft 等共享或零工经济公司率先开发了自动化工具来管理他们的远程员工,包括用户评级系统和自动化“轻推”。

在物流行业,像 UPS 和亚马逊这样的公司正在使用自动化系统来跟踪他们的工人并优化吞吐量。这些算法收集工人的数据,并实时做出(半)自动决策来激励工人的行为。

一些初创公司也开始提供监控工人或司机行为的人工智能解决方案。与人工监管相比,这些技术能够更好地扩大运营规模,并越来越多地被更多公司采用。

场景二——蓝领工人为算法工作,例如数据贴标机

之前我谈到了三种主要的 ML 类型:监督学习、非监督学习和强化学习。今天,超过 90%的 ML 算法仍然是基于监督学习的。

[## 如何管理机器学习产品—第 1 部分

为什么管理机器学习产品这么难?为什么你应该关心?

towardsdatascience.com](/how-to-manage-machine-learning-products-part-1-386e7011258a)

换句话说,这些算法从标记的训练数据中学习和归纳。为了提供标记的训练数据,一个不断增长的行业出现了,让人类手动组织数据集,以便机器可以消化和学习。

Scale AI 是许多与人类工人合作对数据进行分类以训练 ML 模型的创业公司之一。该公司成立仅三年,最近完成了一笔高达 1 亿美元的 c 系列交易。Scale 与大约 3 万名承包商合作,为自动驾驶汽车和其他人工智能公司(包括 Waymo、Airbnb 和 Lyft)标记具有人类洞察力的数据集。

场景三——遥控和模仿学习,例如人类为(或假装)机器人工作。

当用大量数据训练时,深度学习优于传统的 ML。然而,获得高质量的数据既困难又昂贵。

解决这种数据低效问题的方法之一是使用模仿学习:用专家演示来训练算法。FortressIQ 是将模仿学习应用于自动化流程的创业公司之一。它的系统捕捉并分析人类软件的交互,因此它可以在之后自动执行这些过程。

另一方面,像 Cobalt Robotics 这样的安全机器人初创公司,利用机器学习来巡视工作区并识别异常,同时让人类监控机器人车队,并在必要时接管控制权。

这不是科幻小说。它现在正发生在我们认识的人身上,并将很快影响我们每一个人。

我们开始看到这些新形式的人机交互的一些副作用。

机器人缺乏透明度和同情心。

在最近的一项研究中,Lior Zalmanson 和 Robert W. Gregory 发现,优步司机觉得这款应用程序了解他们很多,但他们对算法如何工作和做出决策却知之甚少。

司机感到孤立无援,缺乏人性。他们质疑该系统的公平性,尤其是当他们在没有明确解释的情况下受到处罚时。

零工经济工作者也感觉到他们不断被算法监视和审查。他们不知道这些数据将被用来做什么。他们不知道工作分配、评级或报酬是否公平。如果不公平,他们有没有可以倾诉的人或其他方式来投诉?

缺乏可解释性和可解释性是 ML 的一个主要问题。使用这些自动化工具管理员工效率更高,可扩展性更强。但是生产力不应该是唯一的目标。需要考虑透明度和同理心。

人机团队苦于角色和责任不清。

在钴机器人的案例中,人类扮演了一个关键的角色,因为他们处理所有机器人无法处理的案件。但是随着机器人变得越来越聪明,它们可能会得出与人类不同的结论。

人类应该总是能够否决机器人的决定吗?

考虑另一个例子:机器人轴。Waymo 已经推出了 robotaxi pilot。特斯拉还宣布了推出 robotaxis 的计划,作为其 2020 年自主共乘网络愿景的一部分。

自主机器人应该由谁来做决定?那辆车。后备人类安全驾驶员?远程监控机器人轴心舰队的人?还是乘客?

在什么情况下,什么时候?如果你只有一瞬间的反应时间,答案会不一样吗?谁应该对任何后果负责?那些公司?备用驱动程序?还是设计算法的工程师?

研究人员正在研究迁移学习和元学习,以设计能够“学会如何学习”的模型。但老实说,我们离人工通用智能还很远。

在可预见的未来,我们仍然需要教会机器,帮助它们变得更加自主。我们将需要调整自己,并与支持人工智能的机器一起进化。我们需要学习与智能机器一起工作的最佳方式。我们准备好迎接如此剧烈的社会转变了吗?我们能做些什么来创造我们想要的未来?我们将在下一篇文章中详细讨论这一点!

C 想看更多这样的文章就点这里吧!

[## 亚马逊不想让你知道的自动化战略

作为自动化的前沿,亚马逊为什么要淡化 AI 和机器人的影响?

medium.com](https://medium.com/swlh/what-amazon-doesnt-want-you-to-know-about-its-automation-strategy-9046dd9289aa) [## 它在这里!人工智能机器人将如何革新制造业

虽然制造业一直被认为是自动化程度最高的行业,但全自动化…

towardsdatascience.com](/its-here-how-ai-robot-will-revolutionize-manufacturing-44ce784438d4)

Bastiane Huang 是 OSARO 的产品经理,OSARO 是一家总部位于旧金山的初创公司,致力于开发软件定义的机器人。她曾在亚马逊的 Alexa 小组和哈佛商业评论以及该大学的未来工作倡议中工作。她写关于 ML、机器人和产品管理的文章。跟着她到这里

又一篇关于机器学习的文章!

原文:https://towardsdatascience.com/not-yet-another-article-on-machine-learning-e67f8812ba86?source=collection_archive---------9-----------------------

你能和你的老板进行一次对话,简单解释一下机器学习的基础知识吗?现在你可以…

Photo by James Pond on Unsplash

如果你一直在关注技术的最新趋势,你可能已经注意到,机器学习(ML)不再只是一个时髦词,而是人工智能(AI)中最重要的突破。有很多例子来验证这些说法(从图像分类到文本生成到语言翻译),但这篇文章是为那些从零开始或经过简明总结的人提供的关于 ML 的快速概述。

这不仅仅是另一篇关于 ML 的介绍性文章…这是关于 ML 的介绍性文章!🏆

ML —这是什么?

ML 使计算机能够发现数据中的模式,然后利用这些模式做出决策,而不是被明确编程来执行某项任务。

工作流程非常简单:

  • 您拥有包含 模式的 数据。
  • 你将它提供给一个 ML 算法,该算法 找到 模式并生成一个模型。
  • 模型 在呈现新数据时识别 这些模式。

ML Workflow

每天的例子包括:

医疗诊断
客户的还贷能力
市场分析/股票交易
信用卡欺诈检测
客户细分
垃圾邮件

谁是数据科学家?

2012 年 HBR 的文章具有预言性…

数据科学家是“21 世纪最性感的工作”。

快进到 2019 年,数据科学家是指拥有多学科技能的人,包括数学、统计学、机器学习、计算机科学、编程和商业领域的专业知识。史蒂文·格林勒称之为独角兽是正确的,因为“传说中有神奇力量的野兽,但从未在野外见过”😄—哦,是的,他们有!。**

Venn diagram of a data science unicorn [Copyright Steven Geringer]**

ML 管道

当数据流经他们的 ML 解决方案时,数据科学家为数据定义了一个管道。流水线的每一步都被馈送从其前一步处理的数据。术语“管道”稍有误导性,因为它意味着数据的单向流动;相反,ML 流水线是循环的和迭代的,因为每一步都被重复以最终实现成功的算法。
关键阶段描述如下:

  1. ****问题定义:定义您需要答案的业务问题。
  2. ****数据摄取:识别并收集您想要处理的数据。
  3. ****数据准备:由于数据是原始的、非结构化的,因此很少以正确的形式进行处理。它通常包括填充缺失值或删除重复记录,或标准化和纠正数据中的其他缺陷,例如同一列中相同值的不同表示。这也是特征提取、构建和选择发生的地方。
  4. 数据分离**:分割数据子集训练模型,测试模型,并进一步验证它对新数据的表现。**
  5. ****模型训练:使用数据的训练子集,让 ML 算法识别其中的模式。
  6. ****候选模型评估:使用测试和验证数据子集评估模型的性能,以了解预测的准确性。这是一个迭代的过程,可能会测试各种算法,直到你有一个足以回答你的问题的模型。
  7. ****模型部署:一旦选定的模型产生,它通常通过某种 API 公开,并作为分析解决方案的一部分嵌入到决策框架中。
  8. ****性能监控:持续监控模型,观察其在现实世界中的表现,并进行相应的校准。收集新数据来逐步改进它。

并把它们放在一个图表中:

ML Pipeline

训练算法分类法

ML 算法分为两大类:

监督学习

你要预测的 的值是训练数据中的 ,所以算法可以以合理的方式预测未来的输出。

数据被标记为****

无监督学习(UL)

你要预测的 的值不是训练数据中的 ,所以算法找到隐藏模式(根据相似或不同)或内在值。

数据未标记****

ML Taxonomy

主要的子类别包括:

分类

Supervised Learning — Classification

SL 分类的一个子类是预测分类/离散响应的过程,即输入数据被分类。另一个应用是异常检测,即识别不出现在正态分布中的异常值/异常对象。
例子:

是/否
正版/垃圾邮件
男/女
欺诈/合法交易

回归

Supervised Learning — Regression

SL 的另一个子类,回归是预测连续响应(即数值)的过程,通常回答“多少”/“多少”之类的问题。
例子:

价格变化
温度波动
销售数字
产品需求

使聚集

Unsupervised Learning — Clustering

聚类是 UL 的一个子类,是用于探索性数据分析的过程,以发现隐藏的模式或数据的分组/分区
例子:

客户细分
市场调研
推荐引擎

结局

机器学习是一门令人兴奋的学科;这是艺术,也是科学!在这篇文章中,我们刚刚探索了基础知识——我的目标是让 ML ' 尽可能简单,但一点也不简单【T6’——就像爱因斯坦常说的那样!

感谢阅读!

我定期在 媒体 上撰写关于技术&的数据——如果你想阅读我未来的帖子,只需“关注”我!

给好奇者的人工智能、机器学习和深度学习笔记

原文:https://towardsdatascience.com/notes-on-artificial-intelligence-ai-machine-learning-ml-and-deep-learning-dl-for-56e51a2071c2?source=collection_archive---------1-----------------------

Source: Gerd Leonhard/Flickr Creative Commons

根据麦肯锡的数据,人工智能已经成为 2018 年最有趣的话题。在 Gartner 2019 年十大战略技术趋势的排名中,It 被列为第一和第三名。

人工智能成为一个包罗万象的术语,指的是任何自动做某事的计算机程序。许多人在不知道人工智能真正含义的情况下向其推荐。关于它是 T4 的恶魔还是人类的救星,公众争论不休。因此,这是另一个尝试,为非从业者和好奇的人编译&解释介绍性 AI/ML 概念,以超越这种嗡嗡声。

人工智能作为一门学科创建于 50 年代。事实上,“人工智能”一词是由美国计算机科学家约翰·麦卡锡在 1956 年的达特茅斯会议上创造的。根据约翰·麦卡锡的说法,人工智能是“制造智能机器,尤其是智能计算机程序的科学和工程”。

Evolution of AI — Source: https://www.embedded-vision.com/

尽管直到最近,由于大数据可用性和可负担的高计算能力的进步,它才成为日常生活的一部分。 AI 通过将大量数据集与快速、迭代处理和智能算法相结合,发挥出最佳效果。这使得人工智能软件能够从庞大的数据集中自动学习模式或特征。现在我们在主流新闻上看到人工智能新闻和例子是很典型的。可以说,具有公众意识的流行里程碑是 AlphaGo 人工智能程序,该程序在 2017 年 5 月的古代棋盘游戏 Go 中使用一种叫做“强化学习的机器学习算法,结束了人类【2,500 年的霸主地位。然后,这些人工智能新闻成为我们日常摘要的一部分,自动驾驶汽车,Alexa/Siri 喜欢数字助理狂潮,机场实时人脸识别,人类基因组计划,亚马逊/网飞算法,人工智能作曲家/艺术家,手写识别,电子邮件营销算法,等等。虽然深度神经网络是人工智能的最高级形式,处于 Gartner 2018 年炒作周期的顶端,这是一个预期膨胀的迹象,但自动驾驶汽车已经行驶了数百万英里,安全记录相对令人满意。

Source: Gartner

人工智能技术将在 2019 年继续颠覆,并将由于负担得起的云计算和大数据爆炸而变得更加广泛。我不记得现在有任何其他技术领域吸引了如此多的聪明人&同时来自开源/制造商社区和最大企业的大量资源。

人工智能(AI)、机器学习(ML)和深度学习(DL)有什么区别?

虽然人们经常互换使用这些术语,但我认为下面是区分这 3 个术语的一个很好的概念性描述。人工智能真的是一个宽泛的术语,这也导致现在每个公司都声称他们的产品有人工智能🙂那么 ML 就是人工智能的一个子集,由更先进的技术和模型组成,使计算机能够从数据中找出东西,并提供人工智能应用。ML 是在没有明确编程的情况下让计算机行动的科学 ( 斯坦福大学 )。

Source: https://blogs.oracle.com/bigdata/difference-ai-machine-learning-deep-learning

最后,DL 是 ML 的一个较新领域,它使用多层人工神经网络来提供高精度的任务,如对象检测、语音识别、语言翻译和其他您在新闻中听到的最新突破。DL 的优点和优势在于,它们可以从图像、视频或文本等数据集自动学习/提取/翻译特征,而无需引入传统的手工编码代码或规则。印象深刻!

Source: https://www.xenonstack.com/blog/data-science/log-analytics-deep-machine-learning-ai/

双击传统机器学习模型:

在机器学习中有不同的模型,通常分为 3 个不同的类别:(1)**,(2)** 无监督学习 ,(3) 强化学习

  1. 监督学习:**涉及与数据集中每个实例相关联的输出标签。该输出可以是离散/分类(红色、狗、熊猫、福特野马、停车标志、垃圾邮件……)或实值。现在,几乎所有的学习都是被监督的。您的数据有已知的标签作为输出。它涉及一个比神经网络本身更有知识的管理者。例如,主管提供一些主管已经知道答案的示例数据。主管通过标记输出来指导系统。比如一个有监督的机器学习系统,可以学习哪些邮件是‘垃圾邮件’,哪些不是‘垃圾邮件’。该算法将首先用可用的输入数据集(亿万封电子邮件)进行训练,该数据集已经用这种分类进行了标记,以帮助机器学习系统学习“垃圾”电子邮件的特征或参数,并将它与“非垃圾”电子邮件区分开来。就像一个三岁的孩子知道“积木”和“毛绒玩具”之间的区别一样,有监督的机器学习系统知道哪些电子邮件是“垃圾邮件”,哪些不是“垃圾邮件”。诸如线性或逻辑回归和决策树分类等技术都属于这种学习范畴。

Source: https://www.slideshare.net/SebastianRaschka/nextgen-talk-022015/8-Learning_Labeled_data_Direct_feedback

****回归:这是一种我们需要预测和预报连续响应值的问题。一些例子是,在一个特定的城市有 3 间卧室和 2000 平方英尺以上的房子的价格是多少?预测财务结果、股票价格或板球比赛中的总得分。您有一个现有的数据集&输出(监督学习),并且您的算法基于拟合函数预测结果。

****分类:您需要将某个观察归类到一个组中。在下图中,如果给你一个点,你需要把它归类为蓝点或红点。还有几个例子可以用来预测一封给定的电子邮件是不是垃圾邮件?被探测到的粒子是希格斯玻色子还是普通的亚原子粒子?将某篇新闻文章归入一个组,如体育、天气或科学。今天到底会不会下雨?这张图到底是不是猫?检测欺诈或评估欺诈风险或书面保险。

Source: https://medium.freecodecamp.org/using-machine-learning-to-predict-the-quality-of-wines-9e2e13d7480d

2。无监督学习 —当你的数据通常没有已知的输出标签或任何反馈循环时,这是一种“独立”类型的学习。当没有已知答案的示例数据集,并且您正在搜索隐藏模式时,这很有用。在这种情况下,基于现有数据集执行聚类,即根据某个未知模式将一组元素分成组。系统必须从我们提供的数据集中了解自己。一般来说,无监督学习有点难以实现,因此它没有像有监督学习那样被广泛使用。最流行的类型是聚类关联如下。

****聚类:这是一种无监督学习问题,我们将相似的事物分组在一起。一些例子是:给定新闻文章或书籍,将它们分成不同类型的主题。给定一组 tweet,根据 tweet 的内容对它们进行聚类。也可用于政治、医疗保健、购物、房地产等。

Source: https://brilliant.org/wiki/k-means-clustering/

****关联:关联规则是您发现描述大部分数据的确切规则的地方。例如:购买 X 的人也是倾向于购买 y 的人。当我们收到基于以前购买或搜索的书籍或电影推荐时,我们可能会遇到这种情况。这些算法也用于使用我们的在线或离线零售商购物(销售点)数据的购物篮分析。很快给定许多篮子,关联技术帮助我们理解一个篮子里的哪些项目预测同一个篮子里的另一个项目。

Associations between selected items using a data set on an actual grocery transaction over 30 days. Larger circles imply higher support, while red circles imply higher lift. i.e. The most popular transaction was of pip and tropical fruits. Relatively many people buy sausage along with sliced cheese. Source: kdnuggest

****3。强化学习(RL)现在,当孩子做出正确的选择时,你会奖励孩子一个“大大的拥抱”,而不是告诉孩子把哪个玩具放在哪个盒子里,或者当孩子做出错误的动作时,你会做出“悲伤的表情”。在几次迭代之后,孩子很快就学会了哪些玩具需要放入哪个盒子——这被称为 强化学习 。系统通过接受虚拟的“奖励”或“惩罚”来训练,本质上是通过试错来学习。

Source: Wikipedia

这种策略建立在观察和试错的基础上,以实现目标或最大化回报。代理通过观察其环境做出决策。如果观察结果是否定的,该算法调整其权重,以便能够在下一次做出不同的所需决定。根据隐藏节点的数量和算法的复杂性(稍后将详细介绍),人们可以将强化学习视为深度学习的一部分。强化学习算法试图找到最佳的方法来获得最大的回报。奖励可以是赢得一场比赛,赚更多的钱或击败其他对手。他们展示了非常人性化的任务的最新成果,例如,多伦多大学的这篇论文展示了计算机如何在老派的雅达利电子游戏中击败人类。

谷歌 DeepMind 已经使用强化学习开发了可以玩游戏的系统,包括视频游戏和围棋等棋盘游戏。AlphaGo 以 10 的 170 次方比国际象棋赢了一局棋,比一个 den 9 围棋大师赢了宇宙中的原子数量还要多。强化学习和人工监督学习的结合被用来建立“价值”和“政策”神经网络,该网络还使用搜索树来执行其游戏策略。该软件从人对人游戏中的 3000 万个动作中学习。

在写这篇博客的时候,另一个由 RNN 推动的突破性新闻发布了,谷歌 DeepMind 开发的人工智能代理在星际争霸 II中击败了人类职业选手——这是人工智能世界的第一次。对于电脑来说,像《星际争霸 2》这样的游戏比像国际象棋或围棋这样的棋盘游戏更难玩。

Source: https://www.theverge.com/2019/1/24/18196135/google-deepmind-ai-starcraft-2-victory

谷歌 DeepMind 的研究人员使用强化学习来训练这些 AlphaStar 代理。代理人通过试错来玩游戏,同时试图达到某些目标,如获胜或仅仅是活着。他们首先通过模仿人类玩家来学习,然后互相游戏,最强的代理生存下来,最弱的被淘汰。DeepMind 估计,它的 AlphaStar 代理人都以这种加速的方式积累了大约 200 年的游戏时间。至少在游戏的背景下,RNN 把人类带到了奇点!

如果你第一次遇到 ML 类型,这听起来可能有点令人不知所措,但是下面是一个总结 ML 的直观总结。

Source: https://www.newtechdojo.com/list-machine-learning-algorithms/

深度学习

麦肯锡声称深度学习技术有潜力在 19 个行业每年创造 3.5 万亿到 5.8 万亿美元的价值!

和 ML 一样,“深度学习”也是一种从原始数据集中提取特征或属性的统计学习方法。区别的主要点是 DL 通过利用多层人工神经网络来实现这一点,其中许多隐藏层一个接一个地堆叠。DL 也有更复杂的算法,需要更强大的计算资源。这些是专门设计的计算机,配有高性能 CPU 或 GPU。它们可以是本地的($$)或作为云上的工作负载。您仍然可以使用您的笔记本电脑进行原型制作… 参见我的另一篇文章中的应用示例。

在本文中,我将介绍 3 款流行的 DL 型号。它们是卷积神经网络、递归神经网络 生成对抗网络。我还将分享自然语言处理如何使用 DL 的观点。

深度学习是从人脑中获得灵感的吗?有哪些人工神经网络?

一个小孩子如何学会辨别校车和普通公交的区别?我们是如何下意识地执行复杂的模式识别任务,甚至没有注意到?答案是我们有一个与神经系统相连的生物神经网络。我们的大脑是非常复杂的网络,大约有 100 亿个神经元,每个神经元都与 1 万个其他神经元相连。

这些神经元中的每一个都接收电化学信号,并将这些信息传递给其他神经元。事实上,我们甚至不知道我们的大脑神经元是如何工作的。我们对神经科学和大脑的深层功能了解不够,无法正确模拟大脑的工作方式。DL 只是受到了我们称为神经元的脑细胞的功能的启发,这导致了人工神经网络(ANN)的概念。使用人工神经元层来接收输入并应用激活函数以及人类设定的阈值来模拟 ANN。对于非从业者来说,这可能听起来很科幻,但 DL 已经在我们的日常生活中了。深度学习已经实现了接近或超过人类水平的图像分类、语音/手写识别,当然还有自动驾驶。当我们在网上冲浪时,复杂的广告定位或新闻供稿都结束了。

Source: https://www.datacamp.com/community/tutorials/deep-learning-python

在最基本的前馈神经网络(右上)中,人工神经元有五个主要组件。从左到右,它们是:

  1. ****输入节点。每个输入节点都与一个数值相关联,该数值可以是任何实数。例子可以是图像的一个像素值。
  2. ****人脉。类似地,离开输入节点的每个连接都具有与之相关联的权重(w ),并且这可以是任何实数。人工神经网络运行和传播数百万次,以优化这些“w”值。你需要强大的计算能力才能在短时间内完成。
  3. 接下来,将输入节点的所有值和连接的权重集合在一起。它们被用作加权和的输入。
  4. 该结果将作为转移或激活功能的输入。就像生物神经元只有在超过某个阈值时才会激活一样,人工神经元也只有在输入总和超过某个阈值时才会激活。这些是我们设定的参数(稍后将详细介绍道德规范)。
  5. 结果,您得到了输出节点,它与输入节点的加权和函数相关联。

深度学习中的“深”是什么?

深度学习网络与更一般的单隐层神经网络的区别在于它们的深度。深度是节点层的数量,其中有一个以上的隐藏层,因此在训练、测试和最终运行这些神经网络时,需要更多的计算能力来进行向前/向后优化。

Source: https://verneglobal.com/blog/deep-learning-at-scale

在这些层中,您可以区分输入层、隐藏层和输出层。这些层的作用就像你在上面读到的生物神经元。一层的输出作为下一层的输入。

卷积神经网络(CNN): 这是最流行的应用 DL 案例之一。它们非常适合图像/视频处理或计算机视觉应用。CNN 是深度人工神经网络,主要用于对图像进行分类(例如,标记他们看到的内容),通过相似性对它们进行聚类(照片搜索),并在场景中执行对象识别。这些算法可以识别人脸、个人、街道标志、肿瘤、花朵和视觉数据的许多其他方面。自动驾驶汽车或无人机将越来越多地使用 CNN 功能。最受欢迎的应用公司案例可能是光学字符识别(OCR ),将文本数字化以实现数据输入自动化。

Source: https://cdn-images-1.medium.com/max/1000/1*eEKb2RxREV6-MtLz2DNWFQ.gif

在上面的例子中,我们的 CNN 算法看到的图像与人脑不同。每张图片都是一个三维数字阵列,称为像素,其中有宽度、高度和深度。宽度和高度取决于图像分辨率。第三维(深度)是颜色代码的红绿蓝(RGB)值(除非您使用黑色&白色图像作为输入)。

How our DL algorithm sees an image. — source: http://cs231n.github.io/classification/

从技术上来说,深度学习 CNN 接收这些图像是为了通过一系列带有过滤器的卷积层(下面是基本描述)。CNN 下面各层的工作方式是一个更长的独立话题,这里有一篇很好的文章作为开始。

当然,最初这些过滤器不知道在哪里寻找图像特征,如边缘或曲线,前面提到的权重是随机数(就像一个具有新鲜思维的婴儿)。我们通常有一个大型的训练数据集,包含数千张带有预先识别标签的图像。该模型首先向前传递,计算初始权重,预测结果标签(即这是一只狗),并将其与现有训练集标签的真实值进行比较。因为这是一个训练集,我们已经知道结果标签,因此取决于预测的成功,计算一个损失函数,并且网络在更新其权重时进行回传。计算机能够调整其权重以减少损失的方法是通过一种叫做 反向传播 的方法。现在,该模型通过网络执行反向传递,确定哪些权重对损失贡献最大,并找到微调这些权重的方法,以便通过连续传递减少损失。

最初,预计计算的损耗非常高,并且预计在多次(但固定)向前/向后通过后,损耗会降至最低。最后,希望网络训练得足够好,以便正确调整各层的权重。

然后我们运行测试来看看我们的 CNN 模型是否有效。我们应该有一个不同的图像集加上其各自的标签,并通过 CNN 的图像测试集。我们将输出与测试集进行比较,以查看我们的网络是否工作以及工作情况如何!当然,你拥有的数据越多,你的模型就能通过训练和测试得到更好的调整。这就是为什么大数据能够实现深度学习。当我们有了一个足够好的模型后,它就可以用于现实生活场景了…同时我们继续调整模型。

显然它比这要复杂得多,但这是大多数人工神经网络如何进行训练和测试的超高层次和简化的逻辑。

Source: Unknown Let me know if anyone knows the source. These are some DL terminology examples 😃

计算机视觉的另一个现实例子是在中国。阿里巴巴在其发源地中国杭州推出了城市大脑系统,人工智能中心优化了交通控制。

https://www.youtube.com/watch?v=v4_2QuS4Xns

类似 CNN 的算法已经主宰了我们的日常生活:脸书——自动标记,谷歌——照片搜索,Pinterest——主页订阅个性化。我真的很期待有一天美国有线电视新闻网会帮助治疗视力障碍者。

递归(Recurrent)神经网络(RNN): 有时可互换使用递归神经网络只是一个递归网络的推广,同时具有相同的缩写。RNN 只是在计算中使用以前的输入源。假设你正在分析笔迹,如果你记得以前的字母,你可以更好地预测单词和未来的字母。考虑 rnn 的另一种方式是,它们有一个“存储器”,可以捕获到目前为止已经计算过的信息。RNN 可以记住以前的输入,这使它们在处理语音识别等顺序和上下文相关的任务时,比其他人工神经网络具有很大的优势。

Source: https://towardsdatascience.com/understanding-recurrent-neural-networks-the-prefered-neural-network-for-time-series-data-7d856c21b759

RNNs 被认为可能是 NLP 最强大的模型。rnn 还用于语言翻译,作曲,写小说,维基百科文章或莎士比亚诗歌,写 AI 推文……你可以训练它写机器生成的奥巴马演讲或创作不存在的“披头士”歌曲。有趣吧! Karpathy 的博客,他是 Tesla AI 的现任负责人,写了一篇最受欢迎的深度学习 RNN 文章,供进一步参考。

AI 还是真正的莎士比亚?

Source: Karpathy — RNN generated Shakespearean piece

****生成对抗网络(GAN):GAN 是由 Ian Goodfellow 和他蒙特利尔大学的同事在 2014 年发明的,他现在是谷歌大脑的研究人员。脸书人工智能的主任 Yann LeCun 说:“在过去的十年里,生成对抗网络是机器学习中最有趣的想法。”GAN 通过允许神经网络进行创建而不仅仅是用数据集来训练它,从而使神经网络更加人性化。

生成对抗网络由两个神经网络组成:一个生成网络和一个判别网络。在开始阶段,生成器模型将随机噪声信号作为输入,并生成随机噪声(假)图像作为输出。渐渐地,在鉴别器的帮助下,它开始生成看起来真实的特定类别的图像。

鉴别器是生成器的建议,同时接收生成的图像和某一类图像,使其能够告诉生成器真实图像的样子。

Source: O’Reilly. Generator and Discriminator are pitting one against the other (thus the “adversarial”) and compete during the training where their losses push against each other to improve behaviors (via backpropagation). The goal of the generator is to pass without being caught while the goal of the discriminator is to identify the fakes.

在到达某个点之后,鉴别器将无法辨别生成的图像是真实的还是虚假的图像,这就是我们可以看到某个类别(鉴别器所训练的类别)的图像是由我们的生成器生成的,而该生成器以前从未实际存在过!专家有时将此描述为生成网络试图“愚弄”辨别网络,该网络必须经过训练才能识别特定的模式和模型集。

Source: https://github.com/junyanz/CycleGAN There are other very interesting examples and the source code at this githib account by Jun-Yan Zhu, Researcher at MIT CSAIL.

Source: another video GAN example by Jun-Yan Zhu

GANs 可用于提高图像的分辨率,重建流行图像或绘画或从文本生成图像,制作产品原型的照片级逼真描述,生成真人的逼真语音音频 ( OMG!)以及制作时装/商品镜头。

Source: Wikipedia. GANs were used to create the 2018 painting Edmond de Belamy which sold for $432,500.

生成性对抗网络在社交媒体中非常流行。当心 deepfake 视频!如果你给它输入足够多的人脸数据集,它可以创造出全新的假的人脸,这些人脸超级逼真,但却是不存在的!下面是 NVIDIA 的 AI 使用 GAN 制作的假人类照片。

NVIDIA’s AI produces Fake Human Photos with Unbelievable Quality | QPT

****自然语言处理(NLP)的深度学习:实际上NLP 是一个更广泛的话题,尽管它最近由于机器学习而变得非常流行。NLP 是计算机分析、理解和生成包括语音在内的人类语言的能力。例如,你可以对任何文本进行情感分析。NLP 可以通过电影/书评或网络进行解析后提出人工智能建议。NLP 可以使用文本或音频交互运行聊天机器人/数字助理来完成前端任务。Alexa/Siri/Cortana/Google Assistant 是使用 NLP 引擎的著名数字人物角色。

NLP 的下一个阶段是自然语言交互,它使人们能够使用日常语言与计算机进行交流,以完成任务。我相信你看过谷歌首席执行官桑德尔·皮帅展示谷歌助手如何打几个电话,为你预约理发。其他已知的使用案例有企业搜索或意见挖掘(情感分析)。无论是呼叫中心、聊天机器人、翻译器、自动预测器、垃圾邮件过滤器还是新的广阔的数字助理领域,已经有大量可供选择的自然语言处理引擎可以嵌入到日常生活中。

Behavior of the sentiment neuron. Colors show the type of sentiment. Source: https://blog.openai.com/unsupervised-sentiment-neuron/

如何成为机器学习的实践者?

(1)学习一些 Python 入门,(2)尝试 Keras(或下面其他流行的 DL 库之一)。(3)拿一个现实世界的实际问题来解决它。

作为编译器/编辑器,我更喜欢用 Jupyter 来做我的实验,尽管你有很多其他代码编辑器的选择。没有必要从一开始就变得完美。保持敏捷,快速而廉价地失败,在需要时改变路线,最终你会成功的。

深度学习框架正在快速变化。虽然我的偏好是 Keras,因为它的用户友好的 API, TensorFlow 是目前支持 Google 的冠军,如下图所示。另一个重量级人物 PyTorch 得到了脸书的支持。CNTK 有微软做后盾。Apache 的 MXnet 是一个易于扩展的框架,由 Amazon 提供支持。简而言之,这种情况是非常动态的,并将继续发展。挑一个做实验吧!

Source: https://towardsdatascience.com/deep-learning-framework-power-scores-2018-23607ddf297a

您需要有一个正确设置的笔记本电脑环境来开始。我建议从安装 Anaconda 包开始。这将满足最初的需求,然后你将继续安装其他需要的库。

Source: https://towardsdatascience.com/data-scientist-is-it-the-sexiest-job-of-the-21st-century-35a5bf409363

为了进一步扩大规模,你可以利用大型云 ML 平台之一,如 AWS SageMaker 、微软 Azure AI 、谷歌云平台 ML&tensor flow和其他替代玩家。使用免费点数创建一个帐户。

最后,还有许多在线资源和课程。没有包罗万象的地方,但你可以从中型文章、YouTube 视频、人工智能博客、斯坦福课程、在线书籍或 Coursera/Udemy/Datacamp 项目上的优秀课程开始。

领先的人工智能公司:

英伟达和英特尔生产的特殊微处理器大大加快了最大似然计算。谷歌、亚马逊、微软和 IBM(以及更多的公司)提供云基础设施、ML 服务以及更高级别的框架来加速建模、培训和测试工作。2019 年,几乎每个中/大型公司都会在业务中使用 ML 或 DL。在世界的其他地方,大多数中国人工智能公司都与百度、阿里巴巴和腾讯有联系。比赛开始了。

人工智能在工作场所——企业智能流程自动化

我认为这个领域将在我们之前提到的所有人工智能能力之后呈指数级增长。用机器人流程自动化(RPA) 取代重复性的手动任务,我们仅仅触及了表面。下一个前沿是转化和数字化 E2E 认知过程。传统的 RPA 现在正与人工智能和其他数字自动化工具相结合,例如光学字符识别(OCR)、工作流(业务流程管理)、聊天机器人(NLP)、人在回路中的认知处理、虚拟员工、自动 ML。这些将会扰乱未来的工作场所和整个业务流程外包行业。

智能流程自动化 (IA)是一个呈指数增长的领域,已经有许多参与者……公认的 RPA 参与者有 Blueprism、UI Path、Automation Anywhere 和 Workfusion 以及许多其他新兴的初创企业。较大的蓝筹股公司(IBM、SAP、SalesForce、Microsoft、Pega、Oracle、SAP……)也开始提供或收购类似的 IA 能力。

OK 明白了那数据科学和机器学习的区别是什么?

Nisarg Dave 的下图很好地展示了数据科学的跨学科性质,它处于所有这些不同领域的交汇点。数据科学家需要具备多学科技能,以便能够创建数据集进行测试,创建算法所需的代码,并提供创新的业务洞察力。这也许就是为什么它是 21 世纪最性感的工作!话虽如此,做人工智能工作并不需要成为数据科学家。一点也不。

Source: Nisarg Dave

人工智能与伦理

今天,人工智能没有自由意志或意识,但聪明的人在人工智能模型部署之前进行学习。虽然人工智能的核心目标是增强人类,但也有很多关于人工智能伦理的讨论。以下是其他一些需要思考和反思的重要话题。

微软首席执行官塞特亚·纳德拉“我们需要为我们创造的人工智能负责……”

AI 会制造失业吗?这不是新的恐惧。起初,人工智能将消除一些人类任务,但如果我们能够找到方法来适应和重新掌握自己的技能,那么它有可能创造更多的就业机会。这可能有点类似于第一次工业革命期间从马到汽车的过渡。类似的故事当自动取款机或电脑在 70 年代和 80 年代出现时。

有偏见的机器人:算法是由人类编程和设计的,因此这是一个重要的话题,以提高认识,制定政策,也许监管是一种好的力量。我们应该确保我们的训练集、算法或参数不会“偏离”关键应用程序的目标。

安全/隐私:这可能是目前讨论最多的话题。我们可能需要更好的法规和政策,就像欧洲的 GDPR 一样。

人工智能能力的不平等:随着北美/欧盟和中国主导人工智能世界,当然已经存在数字鸿沟。有机会在全世界进一步民主化人工智能教育。鉴于免费在线信息和开源工作的可用性,我对这种情况更乐观。

人为错误和失误:软件故障很容易导致人工智能错误。我认为需要有明确的责任和规则所有权。即如果自动驾驶汽车或无人机发生严重事故,谁负责?社会需要确保我们复杂的人工智能系统做我们希望它们做的事情。

人际互动和认知技能:这是一个真实的社会影响,并且已经在发生。我们越多地利用机器人,互动就会减少,我们对人工智能的依赖就会增加。解决方法是什么?

最后是奇点。我们可能离机器人超越人类的时代还很遥远,尽管从现在开始考虑这一点是值得的!

【www.weforum.org】来源:

结论

我认为机器和深度学习,就像一般的数据科学一样,既是科学也是艺术。当你开始研究人工智能领域时,你的脑袋可能会在开始时转向模型、数据集、方法等等。我会鼓励选择一个最喜欢的 ML 领域并深入研究。这几天对我来说就是计算机视觉。就像生活中的其他事情一样,只有通过练习才能达到流利。

2019 年,我们将看到更多人工智能领域的新闻和发明。我还希望看到更多的先进技术和应用案例出现在移动电话、耳塞、手表和其他便携式设备上,而不仅仅是高性能计算机。所以要多加小心!

我想用我最喜欢的塞特亚·纳德拉的一句话来结束我的演讲“我相信这个世界将会有大量的人工智能,但真正的智能和人类品质将会稀缺,就像 移情 。我认为伟大的创新来自于你对你想为人们解决的问题的同理心。”**

2019 年深度学习快乐!

资源:

https://www.pyimagesearch.com/

https://www . McKinsey . com/business-functions/McKinsey-analytics/our-insights/an-executives-guide-to-ai。

https://blogs . Oracle . com/big data/difference-ai-machine-learning-deep-learning

https://towards data science . com/machine-learning-vs-deep-learning-62137 a1c 9842

https://towards data science . com/cousins-of-artificial-intelligence-DD a4 EDC 27 b 55

https://www . tutorialspoint . com/人工智能/人工智能 _ 神经网络. htm

http://us blogs . PwC . com/emerging-technology/demysiting-machine-learning-part-2-supervised-unsupervised-and-reinforcement-learning/

https://www . technology review . com/s/612746/a-neural-network-can-learn-to-organize-the-world-it-see-into-concepts just-like-we-do/

https://www . newtechdojo . com/list-machine-learning-algorithms/

https://becoming human . ai/understanding-and-building-generative-adversarial-networks-gans-8de 7 C1 DC 0 e 25

从《代码全集》看软件工程

原文:https://towardsdatascience.com/notes-on-software-construction-from-code-complete-8d2a8a959c69?source=collection_archive---------4-----------------------

Source

从“Code Complete:A Practical Handbook of Software Construction”中获得的经验及其在数据科学中的应用

当人们问我作为数据科学家的工作中最难的部分时,他们经常希望我说建立机器学习模型。假设我们所有的 ML 建模都是在大约 3 行代码中完成的:

from sklearn import modelmodel.fit(training_features, training_targets)predictions = model.predict(testing_features)

我回答说,机器学习是这项工作中比较容易的部分之一。相反,作为一名工业数据科学家,最困难的部分是建立基础设施所需的软件工程,该基础设施用于在生产中持续运行机器学习模型。

一开始,(在 Cortex Building Intel )我可以为一个一次性的机器学习项目写一个好的 Jupyter 笔记本,但是我不知道“在生产中运行机器学习”是什么意思,更不用说怎么做了。在半年的时间里,我已经建立了几个人工智能系统,日以继夜地进行预测,以帮助工程师更有效地运行建筑,我已经了解到这需要大量的软件构建和一点点数据科学。此外,虽然在数据科学中还没有标准的实践,但是有一些经过时间考验的编写软件的最佳实践,可以帮助你成为一名更有效的程序员。

由于我的工作相对缺乏软件工程技能,我不得不快速学习。其中大部分来自于与其他软件工程师的互动和吸收他们的知识,但也有一些来自于教科书和在线教程等资源。其中一本教科书是史蒂夫·麦康奈尔写的长达 900 页的关于构建高质量软件的杰作 代码全集:软件构建实用手册 。在这篇文章中,我想概括一下我从阅读本书中学到的关于软件构造的高层次观点。这些措施如下:

  1. 在触摸键盘之前彻底计划你的项目
  2. 写可读的代码,因为读的比写的多
  3. 降低你程序的复杂性,释放你的脑力
  4. 测试和检查程序中的每一行代码
  5. 做一个没有自我的程序员
  6. 重复你的设计,反复测量进度

尽管这本书的第二版是在 2004 年写的,但是软件工程中被证实的观点在这几年中并没有改变,这本书仍然与今天的软件工程师高度相关。从这本书里你不会学到任何关于 Python 中数据科学的具体细节,但是你会学到如何计划、构建、构建、测试和评审软件项目的基础知识。我试图将这里的想法保持在一个相当高的水平,并计划在以后的文章中更深入地讨论具体的问题。

Code Complete by Steve McConnell (900 pages for only $35!)

虽然这些实践可能看起来与数据科学无关,因为目前正在教授,但我认为数据科学受到了当前对软件工程缺乏重视的伤害。毕竟,机器学习系统是一个软件项目。如果有交付成功软件项目的经过测试的最佳实践,那么我们作为数据科学家应该实践这些方法,超越 Jupyter 笔记本,开始交付机器学习解决方案。这里涵盖的六个主题不像最新的机器学习算法那样令人兴奋,但它们对于行业中的数据科学家来说是至关重要的想法。

  1. 在触摸键盘之前彻底计划你的项目

就像你永远不会在没有蓝图的情况下开始盖房子一样,你也不应该在没有详细的书面程序设计的情况下开始编码。如果你不知道你的程序的预期结果,你将会浪费大量的时间编写混乱的代码,而这些代码并不能实现特定的目标。我在数据科学方面经常遇到的问题是深入数据集非常有趣。你很难抗拒把手放在键盘上的诱惑,制作图表,寻找异常,并一起黑客模型。几个小时后,你不可避免地会得到许多混乱的代码,没有清晰的可交付成果,这个问题本可以通过花时间规划你的程序来避免。

你接手的每个软件项目——包括机器学习模型——都应该从一个问题定义开始:一个要解决的问题的高级陈述。我工作中关于需求预测模型的一个例子是“我们希望提前 7 天准确预测建筑能源需求,以帮助建筑工程师为下周做准备。”该陈述捕获了项目的期望结果和商业价值。

在问题陈述之后是项目需求,一组目标——在问题陈述的较低层次上——解决方案必须满足。这些可以涵盖指标——误差小于 10%——或最终用户体验——图表必须清楚地显示最佳估计和不确定性。这些需求将指导你的项目的详细设计,并允许你评估项目是否成功。

在描述和需求之后是架构规范,在这里你开始计划组成你的程序的文件、类和例程(函数)。此时,您可以开始了解设计的细节,例如错误处理、输入/输出、用户界面和程序中的数据流。

这些文档应该像实际代码一样被审查和讨论,因为设计阶段的错误和决策会影响项目的其余部分。在这里你需要理解你的程序被要求做什么,以及你将如何处理这个问题。在项目的设计阶段,计划您预见到的困难,为项目估计时间,概述替代方法,并分配责任,只有在每个人都同意描述、需求和体系结构计划后,您才应该想到敲击键盘。

上面的具体步骤可能会改变,但重要的是你永远不要通过写一堆代码来开始一个项目。即使是小的、一次性的个人数据科学项目,我现在也花时间计划并写下我的总体目标和对我的项目的一系列要求。开始是个好习惯;请记住,大型项目不是人们在键盘上敲出来的,它们是按照设计过程中绘制的详细蓝图,一次一个地规划和构建的。

在我目前的公司,我们所有的机器学习项目都涉及到一个实质性的设计阶段,在这个阶段,我们与公司的业务部门、我们的客户和客户成功进行讨论,以确保我们满足最终用户的需求。这个过程通常最终会创建几十页的文档,我们会在项目的其余部分引用这些文档。虽然需求确实会在项目过程中发生变化,但拥有一份需要代码完成的任务清单是至关重要的,因为否则你只是在修改和构建一些最终不可用的东西。对我们来说,设计往往会占用平均项目时间的 30%,这是一项值得的投资。提前计划和写下我们的设计意味着,当我们开始编码时,我们不是漫无目的地敲打锤子和钉子,而是遵循一个大纲,一次构建一个坚固的结构。

2。编写可读的代码,因为读的比写的多

代码被读取的次数将比它被写入的次数多得多,所以永远不要为了写入时的方便而牺牲读取时的方便——你的代码有多容易理解——你可以多快地编写代码。

数据科学传授了一些关于代码可读性的坏习惯,最明显的是变量名。虽然对你来说很明显Xy代表特性和目标,因为你已经见过几百次了,为什么不调用变量featurestarget来帮助那些不太熟悉 ML 语法的人呢?阅读代码不应该是一种试图破译写代码的人的神秘编造语言的练习。

提高代码可读性意味着对函数、类、数据对象和程序中的任何变量使用描述性名称!例如,不要对循环变量使用ijk。而是用它们实际代表的:row_indexcolumn_indexcolor_channel。是的,键入要多花半秒钟的时间,但是使用描述性的变量名将为您和任何阅读您的代码的人节省几十个小时的调试或试图修改代码的时间。

下面是另一个非描述性变量名的例子:

value = value * 2.25
value = value * 5.89

这些代码还受到使用“神奇”数字的困扰:描述某些东西的未定义常量值(一个转换、传感器读数的数量、速率等)。)只是没有人能告诉什么是,因为它们就像变魔术一样出现了。你应该永远不要在你的代码中有一个神奇的数字,因为它们使程序变得难以理解,是错误的主要原因,并且使更新这些值变得困难,因为你必须寻找所有使用它们的地方。相反,采取以下方法:

total_widgets_sold = hours * widgets_sold_per_hour
total_revenue_from_widgets = total_widgets_sold * price_per_widget

widgets_per_hourprice_per_widget应该是函数参数,或者是命名的常量,如果它们在你的代码中使用的话(在 Python 中用所有的大写字母表示)。现在,任何人都可以理解这段代码,通过改变参数值来修改就容易多了。

使代码可读的想法所包含的其他实践是,代码的视觉结构应该反映逻辑结构(例如当编写循环时),您的注释应该显示代码的意图,而不仅仅是陈述代码做什么,最小化变量的跨度和生存时间,将相关语句分组在一起,避免过于复杂的 if-else 语句,并使函数尽可能短。

如果你发现自己在想“为了节省时间,我会尽量缩短这些变量名”或者“当我写完代码后,我会回去记录这些代码”,停下来,帮你未来的自己一个忙,让代码更可读。正如 McConnell 所强调的,可读代码对以下所有方面都有积极影响:

  • 易懂
  • 可变性
  • 出错率
  • 排除故障
  • 开发时间——可读性更好的代码可以在项目过程中缩短开发时间
  • 外部质量——由于上述因素,可读性更好的代码为最终用户创造了更好的产品

我认为在数据科学中编写混乱代码的实践是个人开发只打算运行一次的代码的结果。虽然这对于个人项目来说可能没什么问题,但在行业中,代码可读性比构建模型的速度更有价值。我在工作中写的第一段代码很多连我自己都不理解,因为我没有考虑到将来会有哪些人阅读它。因此,这些代码不适合生产,在 GitHub 上闲置着。记住,永远不要把写作速度放在阅读理解的前面。

3。降低程序的复杂性以释放脑力

正如《代码完成》中所强调的,软件构建的首要任务是管理复杂性。这是什么意思?这是关于在编程时限制你必须记住的信息量,减少武断的决定。与其扩展你的智力去写更复杂的代码,不如把你现有的代码简化到你现在的智力可以理解的程度。

作为限制回忆信息的一个例子,考虑你有两个函数的情况,一个给用户发邮件,一个给他们发短信。如果你想让事情变得对你自己很难,你可以这样做:

def notify_user_method_one(user, message):
    """Send a text to a user"""   
    ...def notify_user_method_two(message, user): 
    """Send an email to a user"""
    ...

这段代码的问题在于,你必须记住哪个函数对应哪个方法,以及变量的顺序。一种更好的方法是:

def text_user(user, message):
    ...def email_user(user, message):
   ...

现在函数名准确地描述了函数的功能,参数也是一致的,所以你不用浪费精力去考虑它们的顺序。

一致性 的 概念对于降低代码复杂度至关重要。拥有标准/约定的理由是,你不必对与编码无关的事情(比如格式)做出多个小决定。选择一个标准,并将其应用到整个项目中。与其担心变量名的大小写,不如对项目中的所有变量应用相同的规则,这样你就不必做出决定。标准的选择通常没有实际标准本身重要,所以不要太纠结于应该使用 2 个空格还是 4 个空格。只需选择一个,设置您的开发环境以自动应用它,然后开始工作。

(我不想太深入具体的技术,但是如果你使用 Python,我不得不推荐[black](https://black.readthedocs.io/en/stable/) 自动套用格式器。这个工具已经完全解决了我们团队在代码格式和样式方面的问题。我们设置它来自动格式化我们的代码,并且永远不用担心行的长度或者我们是否应该在逗号后面加空格。我在 vscode 中将它设置为保存时自动运行。

你可以降低复杂性的其他方法是,为你所有的函数和类提供一致的接口( sklearn 就是一个很好的例子),在任何地方使用相同的错误处理方法,避免深度嵌套循环,尽可能采用约定,保持函数简短。在函数这个主题上,确保每个函数做一个单一的任务,并且做得很好!一个函数的名字应该是自文档化的,准确描述该函数完成的单个动作(比如email_user)。如果您发现自己正在编写一个函数文档字符串,其中包含单词“and”来描述该函数的功能,那么您需要简化该函数。只做一件事的较短的函数更容易记忆,更容易测试,减少出错的机会,并允许更大的可修改性。

你不能真的让自己变得更聪明,但是你可以让你的代码更简单,从而释放你的精神资源来专注于解决棘手的问题。在解释技术概念时,大师的标志不是使用复杂的行话,而是使用任何人都能理解的简单语言。同样,在编写代码时,一个有经验的开发人员的代码可能会执行一个复杂的任务,但它会隐藏这种复杂性,让其他人能够理解并构建它。编写只有你自己理解的复杂代码可能会让你暂时感到满足,但是最终,你会意识到一个有效的程序员写的是最简单的代码。降低复杂性提高了代码质量,并限制了您必须做出的决策数量,这样您就可以专注于程序的困难部分。

4。测试并检查程序中的每一行代码

测试是数据科学教育中覆盖最少的领域之一,但它对生产代码绝对至关重要。即使是专业程序员写的代码,每 1000 行代码中也有15–50 个错误。测试是尝试发现错误,或者至少断言您的程序按预期工作的几种技术之一。没有测试,我们就无法将我们的机器学习模型投入生产,因为存在意外失败的风险。失去客户的最快方法之一是让关键任务代码失败,因为它没有经过彻底的测试。

测试的一个很好的经验法则(这种技术被称为结构基础测试)是你的代码需要每if, for, while, and, or, elif进行一次测试。至少,您希望对程序中的每条语句至少测试一次。我们的代码库对每项功能都进行了测试,从加载数据、转换数据、特征工程、建模、预测、存储预测、生成模型解释,到验证模型,涵盖了我们代码库中的每一行代码。

测试至少应该有自己的文章(或者可能是本书),但是从 Pytest 开始是一个很好的起点。幸运的是,这些现代化的库使得设置和开发测试变得不那么乏味。此外,您可以设置 pytest(或其他框架)通过 CircleCI 这样的持续集成服务,在每次提交 GitHub 时自动运行您的测试套件。

除了测试(而不是替代测试),为项目编写的每一行代码都应该由多个程序员审查。这可以通过正式的代码检查或非正式的代码评审,目的是让多只眼睛盯着代码以清除错误、检查代码逻辑、实施一致的约定,并通过反馈提高总体代码质量。代码审查是一些最好的学习机会,尤其是如果你没有经验的话。经验是一位伟大的老师,但它需要很长时间才能获得。作为一条捷径,你可以通过听取他们的建设性批评,让别人的后知之明——他们所犯的错误——成为你的远见。

还有,当你知道别人会在评审中看你的代码,这就迫使你写出更好的代码(想想你私下和公开写的东西在质量上的区别)。此外,一旦你开始考虑你需要运行你的代码的测试,它会提高初始代码的质量(有些人甚至建议在你写代码之前写测试)。

在我们的团队中,我们通常花几乎和一开始写代码一样长的时间来测试和审查代码,以确保它完全符合我们的要求,没有副作用。起初,这令人非常沮丧——我的典型反应是“我编写了代码,它在我的机器上运行了一次,所以我为什么要测试它”——然后我意识到我没有在代码中捕捉到所有的错误,因为我没有测试它。测试对于许多数据科学家来说可能是陌生的,但它是软件工程中一种被证明是通用的方法,因为它提高了代码质量并减少了错误。

如果您正在处理一个单独的项目,您仍然可以添加测试并征求反馈。然而,这有时会很难,所以另一种选择是让开始为开源做贡献。大多数库,尤其是主要的数据科学库,都有严格的测试和代码审查要求。起初这些可能令人生畏,但是要认识到过程的存在是有原因的——确保代码继续按预期运行——并且不尝试和失败就不会变得更好。我认为测试在数据科学中被忽视了,因为缺乏部署的机器学习系统。您不需要测试来编译 Jupyter 笔记本,但是当您的代码正在帮助运行曼哈顿最大的办公楼时,您肯定需要测试!

5。做一个没有自我的程序员

在每次代码审查之前,我都会花时间告诉自己:“你在代码中犯了一些错误。他们将在这篇评论中被指出,但不要把它当成个人的。承认自己的错误,并利用这段经历来学习如何成为一名更好的程序员。”我不得不这样做,因为我发现当我错了的时候很难承认,和大多数人一样,我对批评的最初反应是消极的。然而,随着时间的推移,我认识到不承认自己是错的和需要改变是提高编码水平(以及任何活动)的最大障碍之一。

我对成为一名无自我的程序员的解释是,把你的失败当成一次学习的机会。不要把对你的代码的反馈当成个人的,要意识到其他人是真心实意地想在代码评审中提供帮助。无我编程还意味着当你心爱的框架或标准过时时,你愿意放弃它们(换句话说,不要抗拒改变)。麦康奈尔指出,在软件工程这个领域,如果有更多经验的人在开始工作后没有更新自己的知识,那么 10 年的经验可能比 1 年更糟糕。最好的工具在不断变化,尤其是在数据科学领域,标准也会随着时间而变化。

这并不意味着立即跳槽到最新的技术,但它确实意味着如果转换有被证实的好处,那么不要如此固定你的方式,以至于你拒绝改变。软件开发不是一个确定性的过程,它是启发式的——由经验法则驱动——你必须愿意尝试许多不同的方法,而不是坚持完全相同的方法。有时这意味着放弃一个明显不起作用的模型——即使你已经在它上面花了几十个小时——并且当其他人的解决方案明显比你自己的好的时候接受他们。

从更早的“建造房子的比喻”来说,建筑工人不使用单一的工具——锤子——来建造房子。相反,他们有一个完整的工具箱,里面装满了不同的工具,可以完成建筑中的各种任务。同样,在软件工程或数据科学中,只知道一种方法的人不会走得很远。如果你是一个没有自我意识的程序员,你会乐于向他人学习,对反馈做出建设性的回应,并用适当的技术填满你的工具箱。承认自己的错误比断言自己永远不会犯错要快得多。

6。迭代你的设计,反复测量进度

软件开发(和数据科学)基本上是一个迭代过程。伟大的解决方案不会在一个人的手指第一次接触键盘时就完全成形。更确切地说,它们是在漫长的过程中开发出来的,随着设计的改进和功能的增加,会有许多早期阶段的重复。编写好的软件需要不断解决问题的意愿,通过回应反馈和深入思考问题(有时最好的工具是写下想法的铅笔和纸),随着时间的推移,使代码更可读、更高效、更不容易出错。不要期望第一次就把事情做对!

迭代——这可能是数据科学家熟悉的概念——应该通过重复测量来了解。没有测量,你实际上是盲目的。如何知道优化是否提高了代码的速度?如何知道代码的哪些部分最容易出错?你怎么知道用户花在哪些功能上的时间最多?你如何知道一个项目的哪些部分花费的时间最多?答案是你收集数据并分析它。基于这些结果,您可以在下一次迭代中改进您的方法。

在整个代码完成过程中,麦康奈尔强调测量的必要性,以做出更好的决策。每当我们看到一个流程可以变得更高效时,我们需要寻找一些数据可以帮助我们优化的机会。例如,当我在工作的最初几个月开始跟踪我的时间时,我注意到我在编写和调试测试上花费了超过 75%的编码时间。这是一个不可接受的大份额,所以我决定花时间阅读如何编写好的单元测试,练习编写测试,并且我开始在编码之前考虑我将编写的测试。结果,我将编写测试的时间百分比减少到了不到 50%,并且能够花更多的时间来理解问题领域(数据科学的另一个很难教授的重要方面)。

跟踪数据最重要的部分是观察随时间的相对变化。在大多数情况下,观察值的绝对值不如该值相对于上次测量值的变化重要。注意到您的模型性能一直在下降吗?嗯,可能是因为大楼的一个电表坏了,需要修理。随着时间的推移,跟踪结果只需要建立一个记录数据的系统,并确保有人定期检查。

度量应该有助于了解软件构建过程的所有方面,从设计到代码调优。当估计一个项目需要多长时间时,你应该看看过去的估计,看看为什么它们不准确。如果你想尝试优化你的代码(总是确保你的代码在尝试提高性能之前工作),你必须测量每一个增量变化。书中有许多例子指出,假设的性能增强实际上产生了相反的效果!如果你不衡量变化的效果,你就无法知道你所做的事情是否真的值得。

数据科学的目标不是收集数据和构建漂亮的图表,而是通过数据做出更好的决策和改进流程。通过跟踪你的发展习惯,找出你最薄弱的地方,并专注于需要改进的地方,你可以将这一点应用到你自己的工作中。随着时间的推移跟踪变化,以确保你朝着正确的方向前进,并根据需要经常保持正确。

将这些想法付诸实践

我们已经在高层次上讨论了软件构造的一些关键思想,下一步是通过实际编写(更好的)代码将它们付诸实践。首先,要意识到你不可能一下子采用这些:和任何职业一样,提高编码水平需要时间。(Peter Norvig 有一篇关于如何在 10 年内学会编程的文章,这是一个比“在 24 小时内学会 Python”更现实的目标。)相反,一次专注于一两个想法,无论是在工作中还是在个人项目中,都要努力付诸实践。

如果你有机会在工作中向他人学习,那么采取一种无我的态度,充分利用这一机会(假设他们正在使用最佳实践)。如果你是自学的,看一看参与开源。有很多项目在寻求帮助。如果这有点吓人,您可以尝试阅读一些编写良好的库中的代码。(Python 的搭便车指南中列出的一些 Python 例子有: Flask 、 Werkzeug 、 Requests 和 Diamond )。

结论

我从 900 多页的 代码全集 中得出的总主题是,优质的软件是通过严格的设计和开发过程产生的。数据科学往往缺乏这种严谨性,它倾向于通过复杂的代码来获得一次解决方案,而不是可以运行数百万次而不出错的代码。许多从事数据科学的人——包括我自己——缺乏计算机科学和软件工程最佳实践方面的正规培训。然而,这些编程实践相对容易掌握,并且将在您编写生产级数据科学代码的能力方面获得回报。

高质量的软件开发是一个过程,我希望数据科学家开始采用彻底的过程,允许他们将他们的工作转化为可交付的产品。当然,当你开发出一个能比人类更好地玩电脑游戏的新人工智能时,这是令人兴奋的,但当你的代码帮助帝国大厦每年节省近一百万美元时,这就更酷了。当数据科学领域证明它能够交付具有商业价值的有用产品时,它将超越曲线的炒作阶段,正如软件工程几十年来所做的那样。数据科学可以对现实世界产生巨大的影响,但这种影响不会发生,除非数据科学家使用实践让我们的代码能够经受住现实世界的严峻考验。

我写数据科学,有时写其他有趣的活动。关注我最好的地方是在推特上 @koehrsen_will 。

只有数字:从零开始理解和创建带有计算图的二元分类神经网络

原文:https://towardsdatascience.com/nothing-but-numpy-understanding-creating-binary-classification-neural-networks-with-e746423c8d5c?source=collection_archive---------1-----------------------

Nothing but Numpy 是我的神经网络系列的延续。要查看本系列的前一篇博客或重温神经网络,你可以点击 这里

这篇文章延续了从零开始理解和创建带有计算图的神经网络。

当你打开 20 个浏览器标签试图理解一个复杂的概念,而你遇到的大多数文章都重复着同样肤浅的解释时,你很容易感到困惑。在 Nothing but NumPy 的第二部分中,我将再次努力让读者更深入地了解神经网络,因为我们将更深入地研究一种称为“二进制分类神经网络”的特定神经网络。如果你读过我的 上一篇文章 那么这看起来会很熟悉。

理解“二元分类”将有助于我们放下主要概念,这些概念有助于我们理解我们在多分类中做出的许多选择,这就是为什么这篇文章也将作为“从头开始理解和创建具有计算图的 Softmax 层”的前奏。

这篇博文分为两部分,第一部分将理解二进制分类神经网络的基础知识,第二部分将包含实现从第一部分学到的所有内容的代码。

第一部分:了解二元分类

让我们开始吃吧🍽️

二元分类是一种常见的机器学习任务。它包括预测一个给定的例子是属于一个类还是另一个类。这两个类可以被任意分配为一个或一个【1】用于数学表示,但更常见的是感兴趣的对象/类被分配为一个1【正标签】 ,其余的为一个0(负标签)例如:

  • 给出的图片是猫( 1 )还是非猫( 0 )?
  • 给定一个病人的检查结果,肿瘤是良性的(0);无害)或恶性(1);有害)?
  • 给定一个人的信息(如年龄、教育程度、婚姻状况等)作为特征,预测他们的年收入是低于 5 万美元( 0 )还是高于 5 万美元( 1 )。
  • 给定的电子邮件是垃圾邮件(1)还是非垃圾邮件(0)?

在上述所有示例中,感兴趣的对象/类别被分配了正标签( 1 )。

大多数时候,一个给定的机器学习问题是否需要二元分类是相当明显的。一般的经验法则是二元分类帮助我们回答是(1)/否(0)问题。**

现在,让我们构建一个简单的 1 层神经网络(仅输入和输出层),并手动求解它以获得更好的图像。(我们将制作一个与我的* 上一篇文章 中阐述的神经网络相同的神经网络,但有一个关键的区别, 神经网络的输出被解释为概率 而不是原始值)。*

Fig 1. Simple input-output only neural network

让我们扩展这个神经网络来揭示它的复杂性。

Fig 2. Expanded neural network

对于那些不熟悉神经网络所有不同部分的人,我将简要介绍一下它们。(在我的上一篇文章中提供了更详细的解释)

Fig 3. Annotated Expanded Neural Network

  • 输入: x₁x₂ 是两个特征的输入节点,这两个特征表示我们希望我们的神经网络从中学习的示例。由于输入节点形成网络的第一层,因此它们被统称为“ 输入层 ”。
  • 权重:w₁&w₂分别代表我们与输入&【x₂】关联的权重值。 权重控制每个输入对下一个节点计算的影响。神经网络“学习”这些权重以做出准确的预测。最初,权重是随机分配的。**
  • 线性节点(z):z”节点从所有进入它的输入中创建一个线性函数,即***z =w₁x₁+w₂x₂+b*****
  • 偏置:*****b代表偏置节点。偏差节点将一个加性量插入线性函数节点( z )。顾名思义,偏置会摆动输出,以便更好地与我们期望的输出保持一致。偏差的值被初始化为 b=0 并且也在训练阶段被学习。***
  • ****Sigmoid 节点:这个 σ 节点,称为 Sigmoid 节点,从前面的线性节点( z )获取输入,并将其传递给下面的激活函数,称为 Sigmoid 函数(因为它是 S 形曲线),也称为逻辑函数:

Fig 4. Output sigmoid/logistic node

Sigmoid 是神经网络中使用的许多“激活函数”之一。激活函数是非线性函数(不是简单的直线)。他们通过扩展其维度为神经网络添加非线性,反过来帮助它学习复杂的东西(更多细节请参考我之前的 帖子 ) 。由于它是我们神经网络中的最后一个节点,它是神经网络的输出,因此被称为“输出层”。

*一个线性节点(z)结合一个偏置节点(b)和一个激活节点*,如乙状结肠节点(σ),在人工神经网络 中形成一个“神经元”

Fig 5. A neuron in a neural network

**在神经网络文献中,假设人工神经网络中的每一个神经元都有一个线性节点及其对应的偏置,因此线性节点和偏置节点在神经网络图中没有显示,如 图 1 为了更深入地理解神经网络中的计算,我将在这篇博文中继续展示神经网络的扩展版本,如图 图 2

在输出层使用单个 Sigmoid/Logistic 神经元是二元分类神经网络的支柱。*** 这是因为一个 Sigmoid/Logistic 函数的 输出可以方便地解释为估计的 probability(p̂, 读作 p-hat ),即给定的输入属于“正”类。 如何?让我们再深入一点。*

Sigmoid 函数将任何输入压缩到输出范围0<σ<1内。因此,例如,如果我们正在创建一个基于神经网络的“cat(1) vs. not-cat(0)”检测器,给定图像作为输入示例,我们的输出层仍将是一个单个* Sigmoid 神经元,将先前层的所有计算转换为 简单的 0–1 输出范围。*

Fig 6. Structure of the output layer of any binary classification neural network

然后我们可以简单地将【p̂解释为给定的输入图像是猫的概率是多少?”,其中“猫”为阳性标签。如果 p̂≈0 ,那么极不可能输入图像是猫的,另一方面, p̂≈1 那么很可能输入图像是猫的。简单来说,* 就是我们的神经网络模型在预测输入是一只猫也就是正类的时候有多自信( 1 )。*

这在数学上可以简单地概括为条件概率:

Fig 7. Piecewise probability equation

由于每个二元分类神经网络架构在输出层都有一个单个 Sigmoid 神经元,如上面 图 6 所示,Sigmoid 的输出(估计概率)取决于与神经元相关联的线性节点(z)的输出。如果线性节点的值()z)为:**

Fig 8. Sigmoid Curve interpreted as a probability distribution

  1. 大于零(z > 0) 那么 Sigmoid 节点的输出是 大于 0.5(σ(z)>0.5),可以解释为“输入图像是猫的概率是 大于 大于 50%”。
  2. 小于零(z < 0) 那么乙状结肠节点的输出是 小于 0.5(σ(z) < 0.5) ,可以解释为“输入图像是猫的概率是 小于 小于 50%”。
  3. 等于零(z=0) 那么 Sigmoid 节点 的输出等于 0.5(σ(z)=0.5) ,也就是说“输入图像是猫的概率是 正好是 50%”。

现在我们知道了我们的神经网络中的每样东西代表什么,让我们看看我们的二元分类神经网络在给定以下数据集的情况下执行什么计算:

Fig 9. AND logic gate data and plot

上面的数据代表 AND 逻辑门,其中只有当两个输入都是 x₁=1x₂=1 时,输出才被赋予一个正标签( 1 ),所有其他情况都被赋予一个负标签( 0 )。数据的每一行都代表了我们希望我们的神经网络从中学习然后进行分类的一个例子。我还在二维平面上绘制了这些点,以便于可视化(红点表示类(* y )为 0 的点,绿色十字表示类为1)的点)。这个数据集也恰好是 线性可分的 ,即我们可以画一条直线来将阳性标记的样本与阴性标记的样本分开。*

Fig 10. Showing linear separation of AND gate data points

上面显示的蓝线,称为**,把我们两个阶级分开。线上是我们的阳性标记示例(绿色十字),线下是我们的阴性标记示例(红色十字)。在幕后,这条蓝线是由 z (线性函数)节点形成的。我们稍后将看到神经网络如何学习这个决策边界。**

像我之前的博文一样,首先,我们将执行 随机梯度下降 ,这是使用来自我们训练数据的一个例子来训练神经网络。然后,我们将把我们从随机过程中学到的知识推广到 批量梯度下降 ( 首选方法),在这里,我们使用训练数据中的所有示例来训练神经网络。

随机梯度下降

神经网络中的计算从左向右移动,这被称为 正向传播。 让我们来看一下当提供了仅第一个训练示例 x₁ = 0x₂ = 0 时,我们的神经网络将执行的所有正向计算。此外,我们将随机初始化权重为 w₁=0.1w₂=0.6 ,偏差为 b=0。

Fig 11. Forward propagation on the first example from AND gate table

所以,神经网络的预测是p̂=0.5.的回想一下,这是一个二进制分类神经网络,【p̂】这里代表输入例子的估计概率,具有特征的&【x₂=0,属于正类( 1 )。我们的神经网络目前认为有一个 0.5 (或 50% )的几率第一个训练样本属于正类(从概率方程回忆这等同于 P(1∣ x₁,x₂;w,b)=p̂=0.5 )。****

呀!这有点可怜😕,尤其是因为标签与第一个示例相关联,即 y=0。 估计概率应该在 p̂≈0 左右; 第一个例子属于积极阶层的可能性应该很小,这样一来, 属于消极阶层的几率就高(即 P(0∣ x₁、x₂; )

如果你读过我以前的文章,那么你知道在这一点上,我们需要一个损失函数来帮助我们。那么,我们应该用什么损失函数来告诉一个 二元分类神经网络来修正它的估计概率呢?进来的是 二进制 交叉熵损失函数 来解救我们。

二元交叉熵损失函数

注:在大多数编程语言中“log”是自然对数(log 以-e),在数学上表示为“ ln ”。为了代码和等式之间的一致性,请将“log”视为自然对数,而不是“log₁₀”(以 10 为底的 log)。

二元交叉熵(BCE)损失函数定义如下:

Fig 12. The Binary Cross-Entropy Loss function

所有损失函数本质上都告诉我们,我们的预测输出离我们的期望输出有多远,仅举一个例子。简单地说,损失函数计算预测值和实际值之间的误差。考虑到这一点,当训练示例的关联标签为 y=1 【正】时,二元交叉熵(BCE)损失函数计算不同的损失,并且当标签为 y=0 【负】时,计算不同的损失。让我们看看:**

Fig 13. Binary Cross-Entropy Loss function broken down into piecewise equation

现在很明显 图 12 中的 BCE 损失函数只是分段方程的优雅压缩版本。****

让我们绘制上面的分段函数来可视化下面发生的事情。

Fig 14. Visualizing the BCE Loss function for each class

因此,BCE 损失函数捕捉了当估计的概率相对于训练示例的标签完全错误时,神经网络应该支付高惩罚( 损失→∞ )的直觉。另一方面,当估计的概率相对于训练示例的标签是正确的时,损失应该等于零( 损失=0 )。简而言之,BCE 损失应该仅在两种情况下等于零:

  1. 如果该示例被正标记(y=1),则神经网络模型应该完全确定该示例 属于正类 ,即 p̂=1.
  2. 如果该示例被负标记(y=0),则神经网络模型应该是 c 完全确定该示例 不属于正的 类,即 p̂=0.

在神经网络中,损失函数的梯度/导数决定了是增加还是减少神经网络的权重和偏差。让我们看看二元交叉熵(BCE)损失函数的导数是什么样子的:

Fig 15. The derivative of the Binary Cross-Entropy Loss function

我们还可以将导数分解成分段函数,并可视化其效果:

Fig 16. Breaking down the derivative of the loss function and visualizing the gradient

正的导数意味着减少权重,负的导数意味着增加权重。 坡度越陡,预测越不正确。 让我们先拿一会儿来确定我们理解了这种说法:****

  • 如果梯度为 ,这将意味着我们正在查看第一条损失曲线,其中示例的实际标签为正(y=1) 。将损耗降低到零的唯一方法是沿着斜率(梯度)的相反方向移动,从负到正。因此,我们需要增加权重和偏差以便z = w₁x₁+w₂x₂+b>0图 8)并依次估计归属概率****
  • 同样,当梯度为 时,我们看到的是第二条损耗曲线,该示例的实际标签为负(y=0)。将损耗降至零的唯一方法是再次向斜率(梯度)的相反方向移动,这一次从正到负。在这种情况下,我们将需要减少权重和偏差,以便z = w₁x₁+w₂x₂+b<0并因此估计属于阳性类别* p̂≈σ(z)≈0.的概率*

到目前为止,对 BCE 损失的解释足以满足所有意图和目的,但你们中的好奇者可能想知道这个损失函数是从哪里来的,为什么不像在上一篇文章中那样使用均方误差损失函数呢?稍后将详细介绍。

现在我们知道了损失函数的目的和二元交叉熵损失函数如何工作,让我们在我们当前的例子( x₁ = 0x₂ = 0 )上计算 BCE 损失,对于这个例子,我们的神经网络估计属于正类的概率是【p̂=0.5,而它的标签( y )是 y=0

Fig 17. Loss on the first example

损失约为 0.693 (四舍五入到小数点后 3 位)。我们现在可以使用 BCE 损失函数的导数来检查我们是否需要增加或减少权重和偏差,使用称为* 反向传播的过程; 它与正向传播相反,我们从输出到输入反向跟踪。反向传播允许我们计算出神经网络的每个部分造成了多少损失,然后我们可以相应地调整神经网络的这些部分。*

如我之前的帖子所示,我们将使用以下图形技术将梯度从输出层传播回神经网络的输入层:

Fig 18. Gradient Flow

在每个节点,我们只计算局部梯度(该节点的偏导数)。然后,在反向传播期间,当我们从上游接收梯度的数值时,我们将上游梯度与局部梯度相乘,并将它们传递到它们各自连接的节点。 这是对 链式法则 的概括,来自微积分。

让我们一步一步地回顾反向传播:

Fig 19.a. Backpropagation on the 1ˢᵗ example

下一次计算,我们需要 Sigmoid 函数的导数,它在红色节点形成局部梯度。Sigmoid 函数的导数(在我的上一篇文章中有详细推导):

Fig 20. The derivative of the sigmoid function

现在让我们使用 Sigmoid 节点的导数,并进一步反向传播梯度:

Fig 19.b. Backpropagation on the 1ˢᵗ example

梯度不应传播回输入节点(即红色箭头不应朝向绿色节点),因为我们不想改变我们的输入数据,我们只想改变与它们相关的权重。

Fig 19.c. Backpropagation on the 1ˢᵗ example

最后,我们可以通过执行 梯度下降来更新神经网络的参数(权重和偏差)。

梯度下降

梯度下降 是通过向梯度的负方向移动,即从倾斜区域向更平坦的区域移动来调整神经网络的参数。

Fig 21. Visualizing Gradient Descent on Binary Cross-Entropy Loss function

梯度下降的一般方程为:

Fig 22. The general equation for gradient descent

学习率, α (读作 alpha) 用于控制损耗曲线下降的步长( 图 21 )。学习率是神经网络的 超参数 ,这意味着它不能通过梯度的反向传播来学习,必须由神经网络的创建者来设置,理想情况下是在一些实验之后。更多关于学习率影响的信息,你可以参考我之前的帖子。

请注意,梯度下降的步长(蓝色箭头)越来越小,这是因为当我们从倾斜区域向更平坦的区域移动时,在最小点附近,梯度的幅度也会减小,从而导致步长逐渐变小。

我们将学习率* ( α )设为 α=1。*

Fig 23. Calculating new weights and bias

现在我们已经更新了权重和偏差(实际上我们只能在这次训练迭代中更新我们的偏差),让我们对同一个例子和进行正向传播计算新的损失来检查我们是否做了正确的事情。

Fig 24. Forward propagation with the updated bias on 1ˢᵗ example

Fig 25. New loss after training on the 1ˢᵗ example

现在,属于正类( )的 1ˢᵗ示例的估计概率从 0.5 下降到大约 0.378 (四舍五入到 3 d.p),因此,BCE 损耗也减少了一点,从 0.693 下降到大约(到 3 d.p)。**

到目前为止,我们已经执行了 随机梯度下降。 我们仅使用了一个示例( x₁=0x₂=0 ),来自我们的四个示例的与门数据集,以执行单个训练迭代(每个训练迭代是前向传播,计算损耗,随后是反向传播,并通过梯度下降更新权重)。

我们可以继续通过一次从一个例子中学习来更新权重,但理想情况下,我们希望一次从多个例子中学习,并减少所有例子中的损失。

批量梯度下降

在批量梯度下降 ( 也称为完全批量梯度下降)中,我们在每次训练迭代中使用数据集中的所有训练样本。(如果由于某种原因,批量梯度下降是不可能的,例如,所有训练数据的大小太大而不适合 RAM 或 GPU,我们可以在每次训练迭代中使用数据集的子集,这被称为 小批量梯度下降 )。)

一批只是一个充满训练样本的向量/矩阵。

在我们继续处理多个例子之前,我们需要定义一个 成本函数。

二元交叉熵代价函数

对于批量梯度下降,我们需要调整二元交叉熵(BCE)损失函数以适应批量中的所有样本,而不仅仅是一个样本。这种调整后的损失函数称为 代价 函数(在神经网络文献中也用字母 J 表示,有时也称为 目标函数 )

不是计算一个示例的损失,成本函数计算批次中所有示例的平均 损失。****

Fig 26. Binary Cross-Entropy Cost function

当执行批量梯度下降(或小批量梯度下降)时,我们对成本函数而不是损失函数求导。接下来,我们将看到如何对二元交叉熵成本函数求导,使用一个简单的例子,然后从那里推广。

二元交叉熵代价函数的导数

在矢量化形式中,我们的 BCE 成本函数如下所示:

Fig 27. Cost function taking vectorized inputs

Fig 28. Calculation of Cost on a simple vectorized example

正如所料,成本只是两个示例的平均损失,但我们所有的计算都是矢量化的,允许我们一次性计算一个批次的二元交叉熵成本。我们更喜欢在神经网络中使用矢量化计算,因为计算机硬件(CPU 和 GPU)更适合矢量化形式的批量计算。(注意:如果我们在批次中只有一个示例,BCE 成本将只是计算 BCE 损失,就像我们之前经历的随机梯度下降示例一样

接下来,让我们推导这个矢量化成本函数的偏导数。

Fig 29. Calculation of Jacobian on a simple example

由此,我们可以推广二元交叉熵代价函数的偏导数。

Fig 30. The generalized derivative of the Cost Function

成本函数的一个非常重要的结果是因为它计算一批样本的平均损耗,它计算一批样本的梯度平均值,这有助于计算出一个噪声更小的总方向,其中所有样本的损耗减少。相反,随机梯度下降(只有一个例子的批次)给出了一个非常嘈杂的梯度估计,因为它在每个训练迭代中只使用一个例子来引导梯度下降。**

对于矢量化(批处理)计算,我们需要调整神经网络的线性节点( z ),以便它接受矢量化输入并使用成本函数而不是损失函数,也是出于同样的原因。

Fig 31. Vectorized implementation of Z node

Z 节点现在计算适当大小的权重矩阵( W )和训练数据( X )之间的 点积Z 节点的输出现在也是一个矢量/矩阵。

现在我们可以设置我们的数据( X,W,b & Y )进行矢量化计算。

Fig 32. Data setup for batch(vectorized) processing

我们现在终于准备好使用 XₜᵣₐᵢₙYₜᵣₐᵢₙW、b 执行正向和反向传播。

(注:以下所有结果均四舍五入至小数点后 3 位,仅为简洁起见)

****

Fig 33. Vectorized batch forward propagation on AND gate dataset

通过向量化计算,我们进行了前向传播;一次性计算批次中每个示例的所有估计概率。

现在我们可以计算这些输出估计概率的 BCE 成本(P 、̂ )。(下面,为了便于阅读,我用蓝色突出显示了成本函数中计算正例损失的部分,用红色突出显示了负例损失的部分)

Fig 34. Calculation of Cost on the OR gate data(highlighted Loss in red for negative examples and blue for positive examples)

因此,用我们当前的权重和偏差计算的成本大约是0.720。我们现在的目标是使用反向传播和梯度下降来降低这个成本。让我们一步一步地进行反向传播。**

****

Fig 35.a. Vectorized Backpropagation on AND gate dataset

****

Fig 35.b. Vectorized Backpropagation on AND gate dataset

****

Fig 35.c. Vectorized Backpropagation on AND gate dataset

就像这样,我们使用矢量化计算,一次性计算了整批训练样本的成本函数的所有梯度。我们现在可以执行梯度下降更新权重和偏差。

(对于那些对上一个反向传播步骤中∂Cost/∂W 和∂Cost/∂b 是如何计算的感到困惑的人,请参考我之前的博客,在那里我分解了这个计算,更具体地说,为什么点积的导数会导致转置矩阵)****

Fig 36. Updating weights and bias using batch gradient descent

为了检查我们是否做了正确的事情,我们可以使用新的权重和偏差来执行另一个 前向传播计算新的成本。****

****

Fig 37. Forward propagation with updated weights and bias

Fig 38. New Cost(highlighted Loss in red for negative examples and blue for positive examples)

通过一次训练迭代,我们已经将二进制交叉熵成本从 0.720 降低到大约 0.618。我们将需要执行多次训练迭代,然后才能收敛到良好的权重和偏差值,从而实现整体较低的 BCE 成本

在这一点上,如果您想试一试并自己执行下一个反向传播步骤,作为一个练习,下面是成本 w.r.t 权重( W )和偏差( b )的近似梯度,您应该得到(四舍五入到 3 d.p):

  • 【∂cost/∂w =[-0.002,0.027】
  • ∂cost/∂b =【0.239】

在大约 5000 个历元之后(当神经网络在一次训练迭代中遍历所有训练示例时,一个历元完成),成本稳定地降低到大约 0.003 ,我们的权重稳定到大约W =【10.678,10.678】,** 偏差稳定到大约b =[-16.1818] 我们通过下面的成本曲线看到,网络已经收敛到一组良好的参数(W&b)😗*

Fig 39. Plotting the Cost Curve(left) and the Decision Boundary(right)

成本曲线**(或学习曲线)是神经网络模型随时间的表现。它是每隔几个训练迭代(或时期)后绘制的成本。请注意成本最初下降的速度有多快,然后逐渐接近,回想一下 图 21 这是因为最初梯度的幅度很高,但是随着我们下降到接近最小成本的较平坦区域,梯度的幅度下降,并且进一步的训练仅略微改善了神经网络参数。**

在神经网络已经训练了 5000 个时期之后,Xₜᵣₐᵢₙ上的预测输出概率(【p̂】)是:

**[[9.46258077e-08,  4.05463814e-03,  4.05463814e-03, 9.94323194e-01]]**

让我们来分解一下:

  1. 对于 x₁=0,x₂=0,预测产量为p̂≈9.46×10⁻⁸≈0.0000000946****
  2. 对于 x₁=0,x₂=1 预测产量为t23】p̂≈4.05×10⁻≈0.00405****
  3. 对于 x₁=1,x₂=0 预测产量为p̂≈4.05×10⁻≈0.00405****
  4. 对于 x₁=1,x₂=1 预测产量为p̂≈9.94×10⁻≈0.994****

回想一下,标签是y =【0,0,0,1】。因此,仅对于最后一个示例,神经网络有 99.4%的置信度认为它属于正类,对于其余的,它的置信度小于 1%。还有,还记得 图 7 的概率方程吗?p(0)=1-p̂,所以的预测概率(*)证实我们的神经网络知道它在做什么👌。*****

既然我们知道神经网络预测的 概率 是正确的,我们需要定义何时应该是 1 以及何时应该是 0 ,即根据这些概率对示例进行分类。为此,我们需要定义一个 分类阈值( 也叫 决策阈值)。 那是什么?让我们开始吧**

分类阈值

在二元分类任务中,常见的是,如果估计的 probability(p̂大于某个阈值,则将神经网络的所有预测分类到正类(1),并且类似地,如果估计的概率低于该阈值,则分类到负类(0)。

这可以用数学方法写成如下:

Fig 40. Class prediction model

阈值的值定义了我们的模型在将输入分配给阳性类别时的严格程度。假设如果阈值是 thresh=0, 那么所有的输入实例将被分配到正类,即预测类【ŷ】将总是。类似地,如果 thresh=1 ,那么所有的输入实例将被分配给负类,即预测类【ŷ】将始终是 ŷ=0. (回想一下,sigmoid 激活函数在两端渐近线,因此它可能非常接近 0 或 1,但绝不会完全输出 0 或 1)**

Sigmoid/Logistic 函数为我们提供了一个自然的阈值。回想一下前面的 图 8

Fig 41. The natural threshold value from the sigmoid function

因此,利用自然阈值 0.5 ,可以如下预测类别:

Fig 42. Class prediction model with thresh=0.5

我们如何解读这一点?嗯如果神经网络至少有 50%(0.5)的置信度比输入属于正类( 1 )那么我们就把它分配给正类(【ŷ=1),否则我们就把它分配给负类(ŷ=0******

回想一下我们如何在 图 10 中预测,神经网络可以通过绘制一条线来分隔阳性类别(绿色十字)和阴性类别(红色十字)来分隔与门数据集中的两个类别。嗯,那条线的位置是由我们的阈值定义的。我们来看看:

Fig 43. Deconstructing the inequality equation for class prediction

回想训练后我们的权重和偏差分别收敛到大约W =【10.678】b = [-16.186] 。我们把这些代入上图 图 43 中导出的不等式。

Fig 44. Plugging in values into the inequality

此外,认识到这个不等式给我们一个等式,一条线把我们两个阶级分开:

Fig 45. Deriving equation of the line that forms the Decision Boundary

图 45 中 标记的一条线的这个方程构成了判定边界决策边界是神经网络将其预测从正类变为负类的线,反之亦然。落在线上的所有点(【x₁,x₂】)的估计概率恰好为 50%,即【p̂=0.5】其上的所有点的估计概率大于 50%,即 p̂ > 0.5, 线下的所有点的估计概率为****

我们可以通过给区域加阴影来可视化决策边界,其中神经网络预测正类(1) 神经网络预测负类(0) 。**

****

Fig 46. (left) Decision Boundary with thresh=0.5. || (right) Decision Boundary shaded with thresh=0.5

在大多数情况下,我们可以在二元分类问题中设置 0.5 的阈值。那么,在深入了解阈值之后,有什么收获呢?我们是不是应该把它设置为 0.5,然后忘掉它?没有!在某些情况下,您会希望阈值很高,例如,如果您正在创建一个癌症检测神经网络模型,您会希望您的神经网络非常有信心,可能至少有 95%(0.95)甚至 99%(0.99)的患者患有癌症,因为如果他们没有,他们可能不得不白白经历毒性化疗。另一方面,猫检测器神经网络模型可以设置为低阈值,大约 0.5 左右,因为即使神经网络将猫错误分类,这也只是一个有趣的事故,没有伤害也没有犯规。**

现在,为了阐明分类阈值的概念,让我们将分类阈值对决策边界的位置以及神经网络模型的结果准确性的影响可视化:

Fig 47.a. thresh=0.000000001, all the values assigned to the positive class (accuracy = 25%)

Fig 47.b. thresh=0.00001, only one point(red cross) correctly assigned to negative class, rest to the positive class (accuracy = 50%)

Fig 47.c. thresh=0.5, all points correctly assigned their respective class(accuracy = 100%)

Fig 47.d. thresh=0.9999, all points assigned negative class (accuracy = 75%)

在上述四幅图中训练神经网络之后,我绘制了决策边界(左)、阴影决策边界(中)和每个点离决策边界的最短距离(右),分类阈值的范围从 0.000000001 到 0.9999。

分类阈值也是神经网络 模型 的超参数,需要根据手头的问题 进行调整。 分类阈值不直接影响神经网络(它不改变权重和偏差),它仅用于将输出概率转换回我们类别的二进制表示,即转换回 1 和 0。**

最后说明一下, 决定边界的不是数据集 的属性,它的形状(直的、弯曲的等等。)是神经网络的权重和偏差的结果,并且它的位置是分类阈值的结果。

到目前为止我们已经学到了很多,对吗?😅在很大程度上,我们几乎知道关于二元分类问题的一切,以及如何通过神经网络来解决它们。不幸的是,我有一些坏消息,我们的二元交叉熵损失函数有一个严重的计算缺陷,它在目前的形式下非常不稳定😱。

放心吧!通过一些简单的数学运算,我们就能解决这个问题

二元交叉熵函数的实现

让我们再来看看二元交叉熵(BCE)损失函数:

Fig 48. The Binary Cross-Entropy Function

从分段方程中注意到,二元交叉熵损失函数的所有特征都依赖于" log" 函数(回想一下,这里的"log "是自然对数)。

让我们画出 log 函数,并形象化其特征:

Fig 49. The Natural Logarithm function plotted

二值交叉熵损失中的 log 函数定义了神经网络何时付出高惩罚( 损失→∞ )以及神经网络何时正确( 损失→0 )。的域log函数是0<x<∩其范围是无界的-∩<log(x)<∩,*更重要的是,作为因此,接近零的值的微小变化会对二进制交叉熵损失函数的结果产生极大影响,此外,我们的计算机只能以一定的浮点精度存储数字,当有函数趋向于无穷大时,它们会导致 数字溢出 (溢出是指数字太大而无法存储在计算机内存中,下溢是指数字太小而无法存储在计算机中)。原来二元交叉熵函数的优点,即对数函数,也是它的弱点,使得它在小值附近不稳定。*****

**这对梯度的计算也有可怕的影响。随着数值越来越接近零,梯度趋向于接近 无穷大 使得梯度计算也不稳定

Fig 50. Near zero the gradient of the log function also becomes unstable

考虑下面的例子:

Fig 51. Instability of the natural Log function making it unable to calculate the Cost

类似地,在计算上述示例的梯度时:

Fig 52. Unable to calculate gradient because we used derivate of natural Log, which is also unstable

现在让我们看看如何解决这个问题:

Fig 53. Making the Binary Cross-Entropy Loss Function stable

我们已经成功地将 then 自然对数( log )函数带出危险地带!【1+e⁻ᶻ】的范围大于 1* (*** 1+e⁻ ᶻ > 1) 结果 BCE 损耗中【log】函数的范围变得大于 0 ( log( 1+e⁻ 总体二元交叉熵函数不再是临界不稳定的。****

我们可以就此打住,但让我们更进一步,进一步简化损失函数:

Fig 54. Further simplified Binary Cross-Entropy Loss Function

我们已经极大地简化了二进制交叉熵(BCE) 表达式,但是它有一个问题。看着从 1+e⁻ ᶻ 的曲线,你能猜出来吗?图 53**

Fig 55. 1+e⁻ ᶻ unstable for negative values

表达式为“1+e⁻ᶻ趋于无穷大为负值( 1+e⁻ ᶻ →∞, 当 z < 0 )! 所以,不幸的是,这个简化的表达式在遇到负值时会溢出。让我们试着解决这个问题。

Fig 56. Second simplification of Binary Cross-Entropy Loss function

现在,通过这个“ eᶻ+1 ”表达式,我们已经解决了对数函数在负值时不稳定的问题。不幸的是,现在我们面临相反的问题,新的二元交叉熵损失函数对于大的正值是不稳定的😕因为“eᶻ+1对于正值趋向于无穷大( eᶻ+1 →∞, 当 z > 0 )!

让我们想象一下这两个指数表达式:

Fig 57. eᶻ+1(blue)and 1+e⁻ ᶻ(green) visualized

我们需要以某种方式将这两个简化的函数(在 图 54&56中)组合成一个二元交叉熵(BCE)函数,使得整体损失函数在所有值正和负之间都是稳定的。****

Fig 58. Final stable and simplified Binary Cross -Entropy Function

让我们确认它对负值和正值进行了正确的计算:

Fig 59. Example calculations with new stable Binary Cross-Entropy Function

花点时间理解这个,试着把它和来自 图 58 的分段稳定二元交叉熵损失函数拼凑起来。**

因此,通过一些简单的高中数学,我们解决了基本的二元交叉熵函数中的数值缺陷,并创建了一个 稳定的二元交叉熵损失和成本函数。

注意,先前的 【不稳定】 二元交叉熵损失函数 标签( y )和来自最后一个 sigmoid 节点的概率(【p̂)作为输入但是新的稳定成本函数也是如此。**

现在我们有了一个稳定的 BCE 损失函数及其对应的 BCE 成本函数,我们如何找到二元交叉熵函数的稳定梯度呢?**

答案一直就在眼前!

回想一下二元交叉熵损失函数的导数( 图 15 ):**

Fig 60. The derivative of the Binary Cross Entropy Loss Function

还记得在反向传播期间,该导数流入 sigmoid 节点并与 Sigmoid 节点处的局部梯度相乘,这正是 Sigmoid 函数的导数( 图 19.b. ):

Fig 61. The derivative of the Sigmoid function

当我们将两个导数相乘时,会发生一些美妙的数学现象:

Fig 62. Reduction of derivative into simple expression after multiplying the two derivatives

所以为了计算导数 ∂Loss/∂z 我们甚至不需要计算损失函数的导数或者乙状结肠节点的导数,相反我们可以绕过乙状结肠节点并传递“”作为到最后一个线性节点( z )的上游梯度!**

Fig 63. Visualizing the forward and backward training step after optimization

这种优化有两大好处:

  1. 我们不再需要使用二元交叉熵函数的不稳定导数。
  2. 我们也避免与 Sigmoid 函数的 饱和梯度 相乘。

什么是饱和梯度?回想一下 Sigmoid 函数曲线

Fig 62 Sigmoid curve with flat gradients at either end

在 Sigmoid 曲线的两端变得平坦。当权重大量增加或减少使得相关线性节点( z )的输出变得非常大或非常小时,这在神经网络中成为一个巨大的问题。在这些情况下,梯度(即 sigmoid 节点处的局部梯度)变为零或非常接近零。因此,当进入的上游梯度在 Sigmoid 节点处与非常小的或零的局部梯度相乘时,上游梯度值没有多少或没有能够通过。

Fig 63. A consequence of saturating gradients is that very little of the upstream gradient is able to pass through

在本节的最后一点上,我们可以找到稳定二元交叉熵函数的导数,并得出相同的结论,但我更喜欢上面的解释,因为它帮助我们理解为什么我们可以在二元分类神经网络中反向传播梯度时绕过最后一个 sigmoid 节点。为了完整起见,我还得出以下结论:**

Fig 64. The derivative using the piecewise stable Binary Cross-Entropy Loss function

现在,让我们将我们所学的一切应用到稍微复杂的 XOR 门数据上,我们需要一个多层神经网络(一个深度神经网络),因为单层神经网络的简单直线不会切割(查看我的以前的帖子以了解关于这一现象的更多信息):**

Fig 65 XOR data and plot

为了对 XOR 数据集的数据点进行分类,我们将使用以下神经网络架构:

Fig 66. A 2-layer neural net architecture

神经网络中的一层是具有可调权重的同一深度的任意节点集。神经网络分为两层,中间(隐藏)层和最后一层输出层。

在我们继续向前和向后传播之前,让我们扩展这个 2 层神经网络:

Fig 67. Expanded 2-layer neural net

现在我们准备执行 批量梯度下降 ,从转发传播开始:

********

Fig 68.a. Forward propagation on 2-layer neural net

********

Fig 68.b. Forward propagation on 2-layer neural net

我们现在可以计算出**的稳定成本:**

Fig 69. Calculation of Stable Binary Cross-Entropy Cost

在计算了成本之后,我们现在可以继续进行反向传播并改进权重和偏差。回想一下,我们可以通过优化技术绕过最后一个乙状结肠节点。****

********

Fig 70.a. Backpropagation on the 2-layer neural net

********

Fig 70.b. Backpropagation on the 2-layer neural net

********

Fig 70.c. Backpropagation on the 2-layer neural net

********

Fig 70.e. Backpropagation on the 2-layer neural net

伙计,太多了!😅但是现在我们已经深入了解了关于二分类神经网络的一切。最后,让我们继续进行 梯度下降 并更新我们的权重。

Fig 71. Batch gradient descent update

在这一点上,如果你想自己执行下一个训练迭代并进一步理解,下面是你应该得到的近似梯度(四舍五入到 3 d.p):

Fig 72. Derivatives computed during 2ⁿᵈ training iteration

因此,在 5000 个历元之后,成本稳定地降低到大约0.0017,并且当 分类阈值设置为 0.5 (在编码部分,您可以摆弄阈值,看看它如何影响决策边界):****

Fig 73. (right) The learning curve, (middle) Decision Boundary, (left) Shaded Decision Boundary green positive label, red negative label

在结束这一部分之前,我想回答一些可能困扰你的问题:

1-这不就是逻辑回归吗?

是的一个只有一个 sigmoid 神经元,没有隐含层的神经网络,如图 1 所示,就是逻辑回归**。单 sigmoid-neuron 神经网络/逻辑回归可以对可以用直线分离的更简单的数据集进行分类(如与门数据)。对于一个复杂的数据集(如 XOR) 特征工程 需要手工执行,以使单 sigmoid-neuron 神经网络/逻辑回归充分工作(在前一篇文章中解释过)。****

具有多个隐层和多个神经元的多层神经网络称为深度神经网络。深度神经网络可以捕获关于数据集的更多信息,而不是单个神经元,并且可以在很少或没有人工干预的情况下对复杂数据集进行分类,唯一的警告是,它需要比简单分类模型(如单 sigmoid-neuron 神经网络/逻辑回归)多得多的训练数据。**

此外,单 sigmoid 神经元神经网络/逻辑回归的二元交叉熵成本函数是凸的(u 形),具有保证的全局最小点。另一方面,对于深度神经网络,二元交叉熵代价函数不保证有全局最小值;实际上,这对训练深度神经网络没有严重影响,研究表明,这可以通过更多的训练数据来缓解。****

2-我们可以按原样使用原始输出概率吗?

是的 ,也可以使用来自神经网络的原始概率,这取决于你试图解决的问题的类型。例如,你训练一个二元分类模型来预测每天在一个路口发生车祸的概率, P(事故∣日) 。假设概率为 P(事故∣日)=0.08。 所以在一年的那个关口,我们可以预期:

P(事故∣日)× 365 = 0.08 × 365 = 29.2 起事故

3-如何找到最优分类阈值?

准确度是计算分类阈值的一个度量。我们需要一个分类阈值来最大化我们模型的准确性。

不幸的是,在许多现实世界的案例中,准确性本身就是一个很差的指标。这在数据集中 类倾斜 的情况下尤其明显(简单来说,一个类的例子比另一个多)。我们前面看到的与门也有这个问题;o 只有一个积极类的例子,其余的消极类。如果您回过头来查看 图 47d .,其中我们将分类阈值设置得如此之高( 0.9999 ),以至于模型预测了我们所有示例的负类,您会看到模型的准确度仍然是 75%! 这听起来挺能接受的,但看看数据就不是了。

考虑另一种情况,您正在训练一个癌症检测模型,但是您的 1000 个患者数据集只有**一个患有癌症的患者的例子。现在,如果模型总是输出一个负类(即 not-cancer, 0 ),不管输入是什么,您都会得到一个在数据集上具有 99.9%准确率的分类器!****

因此,为了处理现实世界中的问题,许多数据科学家使用使用的指标。**

精度 :分类器得到了多少个正确的肯定预测?(真阳性/预测阳性总数)

回忆 :分类器能够识别的正面例子比例是多少?(真阳性/实际阳性总数)

这两个指标都可以通过一个称为“ 混淆矩阵 ”的 2×2 矩阵来可视化:

Fig 74. The Confusion Matrix and metrics derived through it

调优分类阈值是精度召回之间的拉锯战。如果精度高(即高分类阈值)召回将低,反之亦然。理解精度与召回之间的权衡是一个主题超出了本文的范围,也将是未来 Nothing but Numpy 博客的主题。****

大多数数据科学家用于调整分类阈值的一个常见指标是 F1 得分 ,该指标结合了精度召回。****

为了简洁起见,以下问题有自己的简短帖子,作为对我们讨论的补充(点击/轻触问题,转到相应的帖子)

4- 这个二元交叉熵损失函数从何而来?

5- 为什么不像你上一篇博客那样直接用均方差(MSE)函数呢?毕竟,您能够使用 MSE 解决相同的示例。

6-tensor flow 和 Keras 是如何实现二进制分类和二进制交叉熵函数(Bonus)的?

第一部分到此结束

****

If you’re enjoying it****

第二部分:模块化二元分类神经网络编码

这个实现建立在上一篇文章的代码基础上(要了解更多细节,您可以查看上一篇文章*的编码部分,或者阅读代码中的文档)。***

线状图层的代码 类保持不变。

Fig 92. Linear Layer Class

Sigmoid 图层类的代码也保持不变:

Fig 93. Sigmoid Activation Layer class

二进制交叉熵(BCE)代价函数(及其变体)是上次代码表单的主要新增内容。

首先,让我们看看“不稳定的”二元交叉熵成本函数compute_bce_cost(Y, P_hat),它将真实标签(Y)和来自最后一个 Sigmoid 层的概率(P_hat)作为自变量。成本函数的这个简单版本返回二元交叉熵成本(cost)及其关于概率的导数(dP_hat)的不稳定版本:**

Fig 94. Unstable Binary Cross-Entropy Function

现在,让我们看看二进制交叉熵成本函数compute_stable_bce_cost(Y, Z)的稳定版本,它将真实标签(Y)和来自最后一个线性层的输出(Z)作为自变量。该成本函数返回由 TensorFlow 计算的二进制交叉熵成本(cost)的稳定版本,以及关于最后一个线性层的导数(dZ_last):**

Fig 95. Stable Binary Cross-Entropy Function

最后,我们也来看看 Keras 实现二元交叉熵代价函数的方式。compute_keras_like_bce_cost(Y, P_hat, from_logits=Flase将真实标签(Y)、最后一个线性层(Z)或最后一个 s 形层(P_hat)的输出作为自变量,这取决于可选自变量from_logits。If from from_logtis=Flase(默认)然后 all 假设P_hat包含需要转换为 logits 的概率,用于计算稳定成本函数。如果来自from_logtis=True,那么所有假设P_hat包含来自线性节点(Z)的输出,并且可以直接计算稳定的成本函数。该函数返回成本(cost)和最后一个线性层的导数(dZ_last)。

Fig 96. Keras-like Stable Binary Cross-Entropy Function

此时,你应该从这个 资源库 中打开1 _ layer _ toy _ network _ on _ Iris _ petals笔记本,在一个单独的窗口中并排浏览这个博客和笔记本。

我们将使用 Iris flower 数据集,它恰好是为统计分析创建的第一批数据集之一。Iris 数据集包含属于 3 个物种的 150 个鸢尾花样本——鸢尾-刚毛鸢尾、鸢尾-杂色鸢尾和鸢尾-海滨鸢尾。每个例子都有 4 个特征——花瓣长度、花瓣宽度、萼片长度和萼片宽度。

Fig 97. Three Species of Iris Flowers (courtesy thegoodpython)

对于我们的第一个二元分类神经网络,我们将创建一个 1 层神经网络,如 图 1 所示,仅使用花瓣长度和花瓣宽度作为输入特征来区分鸢尾-海滨鸢尾与其他。让我们来构建我们的神经网络层:

Fig 98. Defining the layers and training parameters

现在我们可以继续训练我们的神经网络:

Fig 99. The training loop

注意,我们是通过导数, *dZ1* ,直接进入线性层 *Z1.backward(dZ1)* 绕过乙状结肠层, *A1* ,因为优化的原因,我们想到了更早。

在运行 5000 个纪元的循环后,在笔记本中,我们看到成本稳步下降到大约 0.080。

*Cost at epoch#4700: 0.08127062969243247
Cost at epoch#4800: 0.08099585868475366
Cost at epoch#4900: 0.08073032792428664
Cost at epoch#4999: 0.08047611054333165*

导致以下学习曲线和决策边界:

Fig 100. The Learning Curve, Decision Boundary, and Shaded Decision Boundary.

我们的模型对训练数据的准确度是:

*The predicted outputs of first 5 examples: 
[[ 0\.  0\.  1\.  0\.  1.]]
The predicted prbabilities of first 5 examples:
 [[ 0.012  0.022  0.542  0\.     0.719]]The accuracy of the model is: 96.0%*

查看 资源库 中的其他笔记本。我们将在以后的博客中学习更多的东西,因此,你应该从记忆中创建层类(如果你以前没有)和二进制交叉熵代价函数作为练习,并尝试重新创建来自 部分***的 and 门示例。*****

博客到此结束🙌🎉。感谢你花时间阅读这篇文章,希望你喜欢。

如有任何问题,请随时通过推特推特推特@拉法亚克联系我

****

If you enjoyed it!****

如果没有以下资源和人员,这个博客是不可能的:

  • TensorFlow 文档和 GitHub (特别是这个)
  • Keras 文档和 GitHub(特别是这个和这个)
  • 赛特雪拉比的博客
  • 谷歌的 ML 速成班
  • 詹姆斯·d·麦卡弗里的博客
  • 威尔·沃尔夫(@威尔·沃尔夫 _ )关于通过 MLE 推导函数的惊人帖子
  • 安德烈·卡帕西( @ 卡帕西)斯坦福课程
  • 克里斯托弗·奥拉赫( @ ch402 ) 博客 s
  • 吴恩达(@安德温)和他的 Coursera 关于深度学习和机器学习的课程
  • 伊恩·古德费勒( @ 古德费勒 _ 伊恩)和他那本令人惊叹的书
  • Reddit 和 StackExchange
  • 伯克利 CS294 讲义
  • 斯坦福 CS229 课堂讲稿
  • 斯坦福概率图形模型讲座
  • 最后,哈桑-乌兹-扎曼( ,@OKidAmnesiac )和哈桑·陶凯尔()@ _ 哈桑·陶凯尔 )进行宝贵的反馈。

11 月版:深度学习

原文:https://towardsdatascience.com/november-edition-deep-learning-6d97357a975b?source=collection_archive---------33-----------------------

Photo by Brian on Unsplash

我们生活在一个无论好坏都被深度学习算法包围的世界。从社交网络过滤到无人驾驶汽车到电影推荐,从金融欺诈检测到药物发现到医学图像处理,深度学习算法每天都在影响我们的生活和决策。

在基本层面上,深度学习是基于学习数据表示而非特定任务算法的机器学习家族的一部分。深度学习的灵感来自人脑过滤信息的方式。它教会计算机通过层层过滤图像、文本或声音等输入,以学习如何预测和分类数据。它的目的是模仿人类大脑如何工作来创造一些真正的魔法。

深度学习入门需要什么?做好它需要什么?哪些库和框架最适合深度学习问题,最好的使用方法是什么?我们已经看到深度学习的局限性了吗?为了研究这些问题,我们收集了一些最好的文章,很高兴与你分享。

— 安妮·邦纳,TDS 编辑

深入探究深层网络背后的数学

作者皮奥特·斯卡斯基 — 9 分钟阅读

神经网络的奥秘

用深度学习检测疟疾

由迪潘詹(DJ)萨卡尔 — 16 分钟阅读

人工智能促进社会公益——医疗保健案例研究

如何用图卷积网络在图上做深度学习

由 Tobias Skovgaard Jepsen—9 分钟阅读

图形卷积网络的高级介绍

一个神经网络,多种用途

By Paras Chopra — 15 分钟阅读

使用单一模型构建图像搜索、图像标题、相似文字和相似图像

哪个深度学习框架发展最快?

由杰夫·黑尔 — 8 分钟阅读

TensorFlow 与 PyTorch

神经 ODEs:又一次深度学习突破的崩溃

由亚历山大·巴甫洛夫·洪查尔 — 11 分钟阅读

如果你正在阅读这篇文章,很可能你正在赶上人工智能世界最近的进展。

深度学习是否已经触及其极限?

托马斯·尼尔德 — 11 分钟阅读

又一个人工智能的冬天来了吗?

测量等变卷积网络的简单指南

由迈克尔·基斯纳——12 分钟阅读

几何深度学习是一个非常令人兴奋的新领域,但它的数学正在慢慢漂移到代数拓扑和理论物理的领域。

我们也感谢最近加入我们的所有伟大的新作家,加里·科普利克,莎拉·伊德,蒂莫西·谭,戴夫·洛伦兹,鲍林·于,阮庆,乔丹·瑞达,加贺·尹,什拉万·库奇库拉,普拉纳夫·普拉什维克我们邀请你看看他们的简介,看看他们的工作。

如何从原始网络脚本创建电视情景喜剧数据集?

原文:https://towardsdatascience.com/now-we-have-tv-sitcom-f-r-i-e-n-d-s-dataset-created-from-web-transcripts-908af7777977?source=collection_archive---------18-----------------------

到目前为止,除了网络记录之外,还没有可用的 F.R.I.E.N.D.S 或任何流行情景喜剧的数据集(在这次演示中,我使用了来自这个链接的记录-https://fangj.github.io/friends/)。因此,我创建了这个数据集,供对探索这个数据集感兴趣的每个人使用,并使用这里描述的方法创建类似的数据集。

先睹为快数据:

最终创建的数据集如下所示。关于这个的 csv 文件可以在https://raw . githubusercontent . com/shilpbhattacharyya/Friends _ Analysis/master/Friends _ dataset . CSV获得

A peek into the created dataset

代码演练:

这种方法和数据集创建的完整代码可以在我的 github repo(【https://github.com/shilpibhattacharyya/Friends_Analysis】T4)中找到。此数据有一个 93335 行 5 列的形状(93335,5)。我在这里粘贴一个片段来说明我是如何创建这个数据集的。

下面是网页文字链接(https://fangj.github.io/friends/)的一瞥:

Transcript files for the Friends different seasons (only 3 shown)

Transcript file for Season1 Episode1 to get an idea of the transcripts

该算法可以总结如下:

  1. 将每集的 html 内容复制/转换为 txt/csv 文件。
  2. 为每一季的所有剧集副本创建单独的文件夹。

Folder layout in the github repo

  1. 将每一季的剧集合并成一个. csv 文件(mergedx.csv ),我们可以从中读取数据。
  2. 我首先提取了上图中的场景内容,然后根据逗号(,)分隔符将其分割成[Location,Scene]。
  3. 然后提取每个字符对应的文本,保存在以关键字为‘字符’的字典中。
  4. 用文本加场景创建一个熊猫系列,并分割以创建一个由列[位置、场景、季节、演讲者、文本]组成的数据帧,定义如下。

地点:说这段文字的地方

场景:画周围环境的活动

季节:说这段文字的季节

说话者:说这段文字的人物【瑞秋,钱德勒,菲比,乔伊,莫妮卡,罗斯】

文本:对应以上属性的角色所说的文本。

5.我打乱了数据,使其在分布中更加分散。

import re
friends_chars={} 
Rachel=''
Ross=''
Joey=''
Chandler=''
Phoebe=''
Monica=''
Scene=''
with open("transcripts_friends/season1/merged1.csv", "r+") as fp:
    for cnt, line in enumerate(fp):
        if line.startswith('[Scene:'):
            Scene=(line[7:].replace("]", "").replace(":", ","))
        if line.startswith('Rachel:'):
            string=Scene.replace("\n", "")+"*"+(line[8:].replace(":", ""))
            Rachel=Rachel+re.sub(r'\(.*\)', '', string)
        elif line.startswith('Ross:'):
            string=Scene.replace("\n", "")+"*"+(line[6:].replace(":", ""))
            Ross=Ross+re.sub(r'\(.*\)', '', string)
        elif line.startswith('Monica:'):
            string=Scene.replace("\n", "")+"*"+(line[8:].replace(":", ""))
            Monica=Monica+re.sub(r'\(.*\)', '', string)
        elif line.startswith('Chandler:'):
            string=Scene.replace("\n", "")+"*"+(line[10:].replace(":", ""))
            Chandler=Chandler+re.sub(r'\(.*\)', '', string)
        if line.startswith('Phoebe:'):
            string=Scene.replace("\n", "")+"*"+(line[8:].replace(":", ""))
            Phoebe=Phoebe+re.sub(r'\(.*\)', '', string)
        if line.startswith('Joey:'):
            string=Scene.replace("\n", "")+"*"+(line[6:].replace(":", ""))
            Joey=Joey+re.sub(r'\(.*\)', '', string)friends_chars['RACHEL']=Rachel
friends_chars['ROSS']=Ross
friends_chars['MONICA']=Monica
friends_chars['PHOEBE']=Phoebe
friends_chars['CHANDLER']=Chandler
friends_chars['JOEY']=Joeys=pd.Series(friends_chars['RACHEL'].split('\n'))
df1 = pd.DataFrame({'Text':s.values})
df1 = pd.DataFrame(df1.Text.str.split('*',1).tolist(), columns = ['Scene','Text'])
s=df1.Text
df1=  pd.DataFrame(df1.Scene.str.split(',',1).tolist(),
                                   columns = ['Location','Scene'])
df1['Text']=s
df1['Speaker']='Rachel'
df1['Season']='1'
df1.head(20)s2=pd.Series(friends_chars['ROSS'].split('\n'))
df2 = pd.DataFrame({'Text':s2.values})
df2 = pd.DataFrame(df2.Text.str.split('*',1).tolist(), columns = ['Scene','Text'])
s=df2.Text
df2=  pd.DataFrame(df2.Scene.str.split(',',1).tolist(),
                                   columns = ['Location','Scene'])
df2['Text']=s
df2['Speaker']='Ross'
df2['Season']='1' 
df2.head(20)s3=pd.Series(friends_chars['MONICA'].split('\n'))
df3 = pd.DataFrame({'Text':s3.values})
df3 = pd.DataFrame(df3.Text.str.split('*',1).tolist(), columns = ['Scene','Text'])
s=df3.Text
df3=  pd.DataFrame(df3.Scene.str.split(',',1).tolist(),
                                   columns = ['Location','Scene'])
df3['Text']=s
df3['Speaker']='Monica'
df3['Season']='1'                         
df3.head(20)s4=pd.Series(friends_chars['JOEY'].split('\n'))
df4 = pd.DataFrame({'Text':s4.values})
df4 = pd.DataFrame(df4.Text.str.split('*',1).tolist(), columns = ['Scene','Text'])
s=df4.Text
df4=  pd.DataFrame(df4.Scene.str.split(',',1).tolist(),
                                   columns = ['Location','Scene'])
df4['Text']=s
df4['Speaker']='Joey'
df4['Season']='1'                            
df4.head(20)s5=pd.Series(friends_chars['PHOEBE'].split('\n'))
df5 = pd.DataFrame({'Text':s5.values})
df5 = pd.DataFrame(df5.Text.str.split('*',1).tolist(), columns = ['Scene','Text'])
s=df5.Text
df5=  pd.DataFrame(df5.Scene.str.split(',',1).tolist(),
                                   columns = ['Location','Scene'])
df5['Text']=s
df5['Speaker']='Phoebe'
df5['Season']='1'                           
df5.head(20)s6=pd.Series(friends_chars['CHANDLER'].split('\n'))
df6 = pd.DataFrame({'Text':s6.values})
df6 = pd.DataFrame(df6.Text.str.split('*',1).tolist(), columns = ['Scene','Text'])
s=df6.Text
df6=  pd.DataFrame(df6.Scene.str.split(',',1).tolist(),
                                   columns = ['Location','Scene'])
df6['Text']=s
df6['Speaker']='Chandler'
df6['Season']='1'                            
df6.head(20)df_1 = pd.concat([df1, df2,df3,df4,df5,df6])
df_1 = df_1.sample(frac=1).reset_index(drop=True)df_1.head()
df2.head()

6.我将这十个季节的内容结合起来,并将内容写入。csv 文件,这是我们创建的数据集。

df = pd.concat([df_10, df_9,df_8,df_7,df_6,df_5,df_4,df_3,df_2,df_1])
df = df.sample(frac=1).reset_index(drop=True)df.to_csv('friends_dataset.csv')

同样,可以从在线提供的网络脚本中为所有想要的电视情景喜剧创建数据集。

备注:

  1. 创建这个数据集的动机是有一个简单的方法来为电视情景喜剧创建结构化数据,我们今天只有非结构化的 web 脚本可用。

2.如果你正在使用这个数据集或方法,请注明链接(【https://github.com/shilpibhattacharyya/Friends_Analysis】T2)或这篇文章的链接。

单词嵌入用法的细微差别:语义和句法关系

原文:https://towardsdatascience.com/nuances-in-the-usage-of-word-embeddings-semantic-and-syntactic-relationships-780940fe28f?source=collection_archive---------29-----------------------

Photo by Dan Gold on Unsplash

注:前面是超级短帖。我想只是精神食粮吧?😃

介绍

在过去的几周里,我一直在写关于单词嵌入的文章。

我如何为新加坡英语这样的口语语言从头开始创建单词嵌入,以及我如何将其扩展到处理拼写错误或带有翻译向量的不在词汇表中的单词。

在后一篇文章中,我测试了我的实验对下游文本分类准确性的影响。

然而,通过更多的阅读和研究,我开始意识到单词嵌入用法的细微差别及其真正的含义。

请允许我详细说明。

你看, 使用 单词嵌入进行自然语言处理(NLP)是一回事,每个人都可以做到。

但是…

理解 它对下游任务的影响是另一回事。

为了理解它的含义,你首先需要知道所使用的单词嵌入学到了什么语义和句法关系。

什么是语义和句法关系?

我想【什么】在我说到“为什么”的时候就说清楚了。

那么,这有什么关系呢?

这很重要,因为它以比你想象的更多的方式影响你的语言模型的下游准确性。

以情感分析这样的 NLP 任务为例。

如果所使用的单词嵌入更多地捕捉了单词的语义(单词的意思)或它们之间的句法(英语语法结构)关系,你的情感模型会更好吗?

斯坦福大学的 Global Vectors (GloVe)等现成的单词嵌入似乎在与语义相关的任务中表现得更好,如他们的研究论文所示。

Figure 1 — Example of a Semantic Relationship Task

另一方面,Google 的 Word2Vec 虽然在大多数自然语言处理任务中表现不如 GloVe,但似乎在与相关的任务中表现更好。

Figure 2 — Example of Syntactic Relationship Task

话虽如此,语义和句法关系对于语言模型的良好表现同样重要。

唉,这个世界上没有什么是完美的。

没有任何预先训练好的单词嵌入在这两方面都很出色。我个人认为,GloVe 在大多数 NLP 任务中表现出色。

此外,这个世界似乎已经脱离了预先训练的单词嵌入。

注意力模型是现在中的

看看谷歌 10 月 25 日的这篇文章吧,比以往更好地理解搜索。

谷歌最近实现了他们著名的算法“BERT ”,这是一种注意力模型——注意力模型基本上能够给在不同上下文中使用的相同单词赋予不同的单词嵌入。

例如:

“我去 银行 存工资。它坐落在一条 河边

作为人类,我们知道“银行”这个词的第一个用法是指金融机构,而这个词的最后一个用法是指河流。

注意模型对单词“银行”给出了不同的单词嵌入,例如金融银行和河岸银行。

很酷的东西,是吧?

公平地说,我也想指出百度的 厄尼

厄尼实际上是 NLP 世界中最新最受关注的模型。到目前为止,ERNIE 在所有标准基线 NLP 任务中的表现都超过了 BERT,甚至在普通话方面也是如此。不知道为什么人们不怎么谈论它。

抱歉,在谈论注意力模型时分心了。

让我们回到最初的话题!

结尾注释

我想我在这篇短文中想要表达的是:

对于所有的 NLP 任务,没有神奇的预训练单词嵌入。

你必须记住你要解决的 NLP 任务,并训练最适合的单词嵌入类型。

就拿我的新加坡英语文章来说,我肯定不会用 GloVe 或 Word2Vec。

记住,单词嵌入最终会影响你下游的准确性。

垃圾进来,垃圾出去。

希望这篇关于使用单词嵌入时所涉及的细微差别的短文能给你一些启发!

下次见,再见!

LinkedIn 简介:蒂莫西·谭

基于 U-网的细胞核分割

原文:https://towardsdatascience.com/nucleus-segmentation-using-u-net-eceb14a9ced4?source=collection_archive---------6-----------------------

深度学习如何用于分割医学图像?

被困在付费墙后面?点击这里阅读完整故事与我的朋友链接!

显微图像的自动分割是医学图像处理和分析中的一项重要任务。细胞核检测是这项任务的一个重要例子。想象一下加快对几乎所有疾病的研究,从肺癌和心脏病到罕见疾病。2018 年 数据科学碗 提供了我们迄今为止最雄心勃勃的任务:创建一种算法来自动检测细胞核。我们都见过人们遭受癌症、心脏病、慢性阻塞性肺病、老年痴呆症和糖尿病等疾病的折磨。想想看,如果治疗来得更快,会有多少人的生活发生改变。通过自动化细胞核检测,您可以帮助更快地找到从罕见疾病到普通感冒的治疗方法。

这个项目是在 Kaggle 上举行的 2018 年数据科学碗的一部分。

环境和工具

  1. sci kit-学习
  2. sci kit-图像
  3. numpy
  4. 克拉斯
  5. 熊猫
  6. matplotlib
  7. 张量流

数据

数据可以从 kaggle 网站下载,可以在 这里 找到。

基础

这是一个典型的实例分割问题。在这方面非常成功的两个架构是 U-Net 和 Mask-R-CNN。我在这个项目中使用了 U-Net。

  • 图像分类:对图像中的主要物体类别进行分类。
  • 对象检测:识别对象类别,并使用图像中每个已知对象的边界框定位位置。
  • 语义分割:为图像中每个已知的物体识别每个像素的物体类别。标签是类感知的。
  • 实例分割:识别图像中每个已知对象的每个像素的每个对象实例。标签是实例感知的。

代码在哪里?

事不宜迟,让我们从代码开始吧。github 上的完整项目可以在这里找到。

让我们从加载所有的库和依赖项开始。

我们还应该设置一些参数值,并加载训练集和测试集图像。

接下来我们应该以我们想要的形式准备数据。为了降低计算复杂度,我们需要调整所有图像的大小。

下一步可能是项目中最重要的部分,但却经常被忽视。是的,这就是数据增强。我使用图像剪切来克服过度拟合。由于在这种情况下数据集的大小很小,过度拟合在这里不是一个主要问题。

让我们展示一些有分割和没有分割的显微图像。

without segmentation

with segmentation

让我们也创建一个生成遮罩和图像的生成器。

优信网

该建筑看起来像一个“U”形,名副其实。这个架构由三个部分组成:收缩部分、瓶颈部分和扩展部分。收缩段由许多收缩块组成。每个模块接受一个输入,并应用两个 3×3 卷积层,然后是一个 2×2 最大池。每个块之后的核或特征图的数量加倍,以便架构可以有效地学习复杂的结构。最底层位于收缩层和膨胀层之间。

但是这个架构的核心在于扩展部分。类似于收缩层,也是由几个膨胀块组成。每个模块将输入传递到两个 3X3 CNN 层,然后是一个 2×2 上采样层。此外,在每个块之后,卷积层使用的特征图的数量减半以保持对称性。扩展块的数量与收缩块的数量相同。之后,所得到的映射通过另一个 3X3 CNN 层,其特征映射的数量等于期望的分段数量。

U-net architecture

让我们继续定义 Union (IOU)度量上的 交集。

然后我们应该使用 keras 图层建立如上图所示的 U-Net 模型。

我使用早期停止标准作为参数对模型进行了三次迭代训练,它给出了相当好的结果,平均 IOU 为 0.416。请随意使用这里的超参数。

最后,我为最后的预测写了几行。

结果

结论

这是我参与过的最具挑战性的项目之一,同时也很有趣。虽然这不是一个典型的计算机视觉项目,其中计算复杂性是一个挑战,但它更多的是在相对较大的图像中找到小特征。坦率地说,在图像中分割细胞核是一个挑战。有时,即使是专家也可能在这方面犯错误,因此自动化整个流水线,看起来像是细胞核分割的未来。

参考资料/进一步阅读

[## U-Net:生物医学图像分割的卷积网络

人们普遍认为,深度网络的成功训练需要成千上万个带注释的训练样本。在…

arxiv.org](https://arxiv.org/abs/1505.04597) [## 2018 数据科学碗

在不同的图像中找到细胞核以推进医学发现

www.kaggle.com](https://www.kaggle.com/c/data-science-bowl-2018) [## 综述:U-Net(生物医学图像分割)

在这个故事中,我们回顾了 U-Net。U-Net 是生物医学图像领域著名的全卷积网络(FCN)之一

towardsdatascience.com](/review-u-net-biomedical-image-segmentation-d02bf06ca760)

在你走之前

相应的源代码可以在这里找到。

[## abhinavsagar/ka ggle-教程

Kaggle 竞赛笔记本样本。显微图像的自动分割是医学图像处理中的一项重要任务

github.com](https://github.com/abhinavsagar/Kaggle-tutorial)

联系人

如果你想了解我最新的文章和项目,请关注我的媒体。以下是我的一些联系人详细信息:

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

快乐阅读,快乐学习,快乐编码。

零假设和 P 值

原文:https://towardsdatascience.com/null-hypothesis-and-the-p-value-fdc129db6502?source=collection_archive---------8-----------------------

最初发表于我的个人博客。

当你开始机器学习之旅时,你会遇到零假设和 p 值。在你旅程的某一点上,当设计你的机器学习模型时,知道这些对做出有意义的决定意味着什么变得相当重要。所以在这篇文章中,我会试着解释这两件事的意思,你也试着去理解。

现在,如果你没有统计学的背景,零假设和 p 值的定义对你来说将毫无意义。这只是你脑子里的胡言乱语。这就是我头几次试图理解他们时的遭遇。我花了好几天时间才明白它们的意思。直到今天,我的理解仍然可能是错误的。我相信你们会比我更了解这一点,并且会在评论中纠正我。所以我很期待。

无效假设

为了理解这一点,我们来看一些真实世界的数据。我刚才看了我居住的城市(班加罗尔)的空气质量指数(AQI ),它说目前的 AQI 是 162,比“令人满意”的质量指数高出 62 个单位。

对于那些不知道的人来说,如果空气质量指数在 0-50 范围内,空气质量就很好,超过这个范围但在 100 以内的都是中度污染。任何超出这个范围的都是不健康的。

现在,我会参考这个网站,或任何其他网站,告诉你我的城市的空气质量指数是 162,这是不健康的。在这份声明中,我陈述了一些事情,并证明了它的价值,以及为什么它是不健康的。所以现在,这个陈述变成了无效假设。换句话说,我们可以说一个测试的结果可以被认为是零假设。零假设表示为 H0 (H-not)。

对统计和零假设有足够经验的人会首先指出,我为这个例子选择的陈述可以分解成两个零假设,这是真的。这两个是:

  • 班加罗尔的空气质量指数现在是 162。
  • 空气质量指数超过 150 是不健康的。

为了使这个例子简单,我们考虑第一个陈述,AQI 是 162。

零假设->2019 年 11 月 8 日下午 6 点 Bangalore 的空气质量指数是 162。

这种说法可能是错误的。发布这个值的人用他们的工具做了一堆测试,在测试结束时得出这个值。但你可能有自己的工具来测量空气质量,或者你可能觉得空气看起来太干净了,没有这么高的值。所以你想对这种说法提出质疑,你准备证明在那个日期、时间和地点,空气质量指数远小于 162。所以你的“替代假设”变成了:

替代假设 - >班加罗尔 2019 年 11 月 8 日下午 6 点的空气质量指数小于 162。

这里要注意的一点是,零假设通常是科学家们想要证明错误的陈述,但他们会在假设零假设为真的情况下朝着那个目标开始研究。无效假设的真实例子如下:

  • 科技行业男性的平均收入与女性的平均收入相同。
  • 挫折和攻击性之间没有关联。

正如你所看到的,科学家们假设这些陈述是真实的,或者是事实,并将开始他们的研究或测试来证明这些是错误的。但是类似于在法庭上发生的事情,这些陈述被认为是正确的,除非被证明是错误的。当证明他们错误的过程开始时,科学家们将形成另一个与这些无效假设相反的陈述,这些新的陈述成为替代假设。因此,上述陈述的替代假设是:

  • 科技行业中男性的平均收入与女性的平均收入是不一样的
  • 挫折和攻击性之间有一种关联

可选假设表示为 H1 或哈。

我希望你理解这个非常混乱的概念。记住无效假设,我们将继续讨论 P 值。

p 值

我们可以将 p 值定义如下:

在统计学中,p 值是在假设零假设正确的情况下,获得某个测试的观察结果的概率。

这只是 p 值的定义之一。理解了什么是零假设之后,理解 p 值就相对容易了。p 值是您得出与零假设相同结果的概率。因此,如果我们考虑上一节中技术行业的平均收入,我们可以说 p 值是发现技术行业中男性和女性的平均收入相同的概率。我们考虑的是收入相同的情况下的概率(而不是收入不同的情况),因为我们相信零假设是正确的。

最常用的 p 值是 0.05。如果计算出的 p 值小于 0.05,则零假设被认为是错误的或无效的(因此称为零假设)。如果该值大于 0.05,则认为零假设为真。让我详细说明一下。

请记住,p 值是我们得到与零假设相同结果的概率,在我们的例子中,该概率的阈值是 0.05。因此,如果计算的 p 值小于 0.05,这意味着我们得到与零假设相同的结果的可能性非常小。而如果 p 值大于 0.05,那么得到与零假设相同结果的概率非常高,所以我们可以认为零假设为真。

再次,我希望你明白这一点。我真的不知道如何解释这些事情,而不会让你或我自己感到困惑。但我尽力了。如果你有更好更简单的例子,请在下面留下评论。

在 Twitter 上关注我,了解更多数据科学、机器学习,以及通用技术更新。此外,你可以关注我的个人博客,因为我在 Medium 之前发布了许多我的教程、操作方法帖子和机器学习的优点。

数论——历史与概述

原文:https://towardsdatascience.com/number-theory-history-overview-8cd0c40d0f01?source=collection_archive---------13-----------------------

第一部分——什么是数论&为什么它与今天相关?

Originally Published On https://www.setzeus.com/

数学是宇宙的自然语言。自从我们作为一个物种存在以来,这些数字就深深地吸引着我们。经常邀请我们最伟大的思想家来揭开宇宙的许多深层奥秘,对自然数、**、数论、**的研究是数学最古老的分支之一。

数论的纯粹性吸引了一代又一代的数学家——每个人都对卡尔·高斯称之为“数学女王”的分支做出了贡献直到最近的突破,数论一直是纯数学之王。然而,今天,对数论的基本理解是尖端软件工程,特别是基于安全的软件的绝对关键的先驱。数论是密码学的核心——密码学本身正在经历一个迷人的快速发展时期,从著名的 RSA 算法到广受欢迎的区块链世界。

Article Originally Published On https://www.setzeus.com/

历史上两个不同的时刻是数论发展的转折点。首先,在古代,欧几里德提出了他的 GCD(最大公约数)算法——这是一套利用几何观察将分数简化为最简单形式的绝妙步骤。然后,大约两千年后,卡尔·高斯将欧几里得的非正式著作和他自己在永恒的《算术论文集》中的广泛证明结合在一起,使欧几里得的原理正式化。

欧几里德&最大公约数

数论作为一门分支学科的起源可以追溯到公元前,特别是欧几里得的一生。一位杰出的数学家,欧几里得,也被称为“几何之父”,提出了有记录以来最古老的“算法”(这里指的是一系列逐步操作)之一。这个算法,即最大公约数,经受住了时间的考验,成为我们数论的起点,因为它突出了自然数的迷人特性。

公元前 300 年左右,欧几里德推出了他的经典的 【元素】 丛书;一个十本书的系列,涵盖了从整数到线段&表面区域的一系列主题。有趣的是,他的 GCD 算法在这个系列中不是一次而是两次被列出来——首先是在第 7 本书中(用数字呈现),然后是在第 10 本书中(通过几何呈现)。

根据数学史家的说法,很可能是后一种形式的算法,一种基于几何的算法(第 10 册),实际上早于第 7 册中基于数字的算法。从长度、面积和体积的角度来看,理论上 GCD 算法对欧几里得非常重要,因为它提供了一种方法来(a)&(b)**找出任意两个线段之间的最大公共长度。鉴于他生活的时代,这一观察很可能对任何人都有很大用处&任何参与任何类型建筑(石工、木工等)的人。**

扩展前面的定义,两个长度 (a) & (b) 的最大公约数,是平均度量**&b的最大长度(g);或者, 长度(a)&【b】都是长度(g) 的整数倍。下面是一个几何示例——假设我们的任务是铺设 15 米 x25 米的地板。为了最大限度地降低成本,我们只想购买相同尺寸的瓷砖长度;这就要求我们计算出最大的瓷砖长度(以米为单位),既要有长度&又要有宽度,而且不能断裂。换句话说,15 & 25 的最大公约数是多少?**

Originally Published On https://www.setzeus.com/

对于我们的例子,我们忽略了计算 GCD 的具体步骤,但是,希望上面的插图提供了对所涉及的几何图形的直观理解。正如圈起来的,我们的示例问题的答案是 5 m ,这确实是在 15 & 25 中找到的最大的普通整数。

高斯&算术的基本定理

接下来数论的巨大飞跃源于欧几里得大约 2000 年后的突破。在令人惊叹的 21 岁时,卡尔·高斯提出了一篇论文,将欧几里得的《几何原本》与当时的现代数学结合起来。他的代表作《T2》研究算术 (粗略翻译为“算术调查”)包含了多种卓越的&精确方法,尽管不一定是他所有的原创作品,但这些方法汇总了&系统化的数论领域。通过这份出版物,他建立了这个分支,将以前分散的&非正式方法正式化,为重要的未决问题提供了原始答案,&为未来的贡献者奠定了基础。

研究 的基石灵光一现是一个永恒的定理,被称为算术基本定理:

任何大于 1 的整数要么是一个素数,要么可以写成素数的唯一乘积(忽略顺序)。****

上面的维基百科定义通过分成两个独立的部分变得易于理解。第一,陈述了 任何大于 1 的 整数要么是质数本身 要么是质数 可以通过严格的质数相乘来构造。第二部分保证对于每一个非质数(合数)来说,这些质数相乘的方式只有一种,也是唯一的(再次忽略顺序)。

换句话说,素数是整数的(乘法)“构建块”:素数的乘积将(唯一地)生成所有整数。这个结果无疑是过去几个世纪的数学家都知道的,但是高斯在的论文中第一个正式陈述了这个结果并给出了严格的证明。

Ulam Spiral

巧妙的加密应用

现在有了数论的基本历史&对其影响深度的快速预览,是时候让我们熟悉数论中最适用的主题:密码学了。

正如我们接下来将看到的,当高斯正式为这个分支搭建舞台的时候,密码系统的早期例子已经存在了,而且相当大胆。通过其中的几个例子,我们将推断出基本的、通用的密码学原理;之后,这将帮助我们分解和理解现代最重要的安全算法之一:RSA 算法。

最初发布于

https://www.setzeus.com/

来源

数论简介

https://www.cs.purdue.edu/homes/spa/courses/cs182/mod5.pdf

数据科学家的 Numpy 和熊猫

原文:https://towardsdatascience.com/numpy-and-pandas-for-data-scientists-2be4a093b4b5?source=collection_archive---------27-----------------------

Photo by Kevin Ku on Pexels

Numpy 是一个用于科学计算的 python 包。它支持大型多维数组和矩阵。Pandas 是用于数据操作和分析的 python 库。对这两个库有扎实的了解对于特征工程、数据插补和模型构建非常有用。

在这篇文章中,我将回顾 numpy 和 pandas 的一些简单应用,包括数据标注、工程特性和输入缺失值。

出于本帖的目的,我们将使用来自UCI ML 回购的在线零售数据集,该数据集可在 Kaggle 上找到。该数据包含一家英国在线商店从 2010 年 1 月 12 日到 2011 年 9 月 12 日的交易信息。这家商店出售独特的节日礼品。

现在让我们开始吧!

首先,让我们将数据读入 pandas 数据帧,并打印前五行:

import pandas as pd 
df = pd.read_csv("online_retail.csv")
print(df.head())

输入缺失值

用零估算缺失/错误的数值

在处理真实数据列时,经常会包含缺失值或错误值。缺少的值通常显示为“nan ”,它代表“不是一个数字”,错误的值可能是那些与现实中出现的值不一致的值。错误值的一个例子可能是负数或无穷大的价格。输入缺失数值的一种方法是用零替换它们。该数据不包括缺失值,因此我们可以人为地添加一些无穷大的缺失值:

np.random.seed(42)
df['column_with_bad_values'] = df['UnitPrice']/np.random.randint(4, size = len(df))
df['column_with_bad_values'].iloc[3] = np.nan
print(df.head())

我们可以使用 fillna()将缺失的值替换为零:

df['column_with_bad_values'].fillna(0, inplace = True)
print(df.head())

我们可以使用 np.isinf()对无穷大的值做类似的事情:

df.loc[np.isinf(df['column_with_bad_values']), 'column_with_bad_values'] = 0

用平均值估算缺失的数值

假设我们的数据有以下缺失值(注意,我已经删除了无限值):

np.random.seed(42)
df['column_with_bad_values'] = np.random.randint(4, size = len(df))
df['column_with_bad_values'].iloc[0] = np.nan
df['column_with_bad_values'].iloc[2] = np.nan
df['column_with_bad_values'].iloc[4] = np.nan
print(df.head())

我们可以将“nan”值替换为该列的平均值,如下所示:

df['column_with_bad_values'].fillna(df['column_with_bad_values'].mean(), inplace = True)
print(df.head())

请注意,所有以前的“nan”值都已替换为平均值 1.500803。如果我们保持无穷大的值,这就行不通了。让我们尝试在同时具有无穷大和“nan”值的情况下,使用均值法进行插补:

np.random.seed(32)
df['column_with_bad_values'] = df['UnitPrice']/np.random.randint(4, size= len(df))
df['column_with_bad_values'].iloc[0] = np.nan
df['column_with_bad_values'].iloc[2] = np.nan
print(df.head())

如果我们有无限值和“nan”值,我们希望用平均值估算,我们可以将无限值转换为“nan”值,然后用平均值填充“nan”值:

df.loc[np.isinf(df['column_with_bad_values']), 'column_with_bad_values'] = np.nan
df['column_with_bad_values'].fillna(df['column_with_bad_values'].mean(), inplace = True)

我们可以看到,无穷大值和缺失值都被平均值 2.692406 所取代。请注意,这个平均值是不同的,因为我们更改了随机数种子,我们使用它来生成用于演示的随机整数。

用正态分布的随机数估算缺失/错误的数值

我们可以使用 fillna()和 np.random.normal()用正态分布的随机数填充缺失值。首先,让我们重新生成缺失值的数据帧:

np.random.seed(32)
df['column_with_bad_values'] = np.random.randint(4, size= len(df))
df['column_with_bad_values'].iloc[0] = np.nan
df['column_with_bad_values'].iloc[2] = np.nan
print(df.head())

正态分布是根据列的平均值和标准差构建的。然后,我们可以使用 fillna()和 np.random.normal()的值来填充缺少的值:

mu, sigma = df['column_with_bad_values'].mean(), df['column_with_bad_values'].std()
df['column_with_bad_values'].fillna(np.random.normal(mu, sigma), inplace = True)
print(df.head())

用模式估算缺失/错误的分类变量

我们可以使用 fillna()和 mode()来估算缺失分类变量的值。首先,让我们生成测试数据框架:

df['column_with_bad_values'] = df['Description']
df['column_with_bad_values'].iloc[0] = np.nan
df['column_with_bad_values'].iloc[2] = np.nan
print(df.head())

然后,我们可以使用统计包中的模式来填充这些缺失值:

from statistics import mode
mode = mode(list(df['column_with_bad_values'].values))
df['column_with_bad_values'].fillna(mode, inplace = True)
print(df.head())

特色工程

数值数据的对数变换

出于演示的目的,我将对数据进行一些过滤。我将只考虑单价大于或等于$5 且小于或等于$30 的记录。此外,“单价”列类型需要从字符串转换为数字类型。为了简单起见,我将价格转换为整数:

df['UnitPrice'] = df['UnitPrice'].astype(int)
df = df[df['UnitPrice'] >= 5]
df = df[df['UnitPrice'] <= 30]
print(df.head())

特征工程的一个流行例子是获取数据集中某个数字列的日志。为了形象化,我们将比较记录前后的价格分布:

df['UnitPrice'].hist()

进行对数变换后,我们得到:

import numpy as np 
df['log_price'] = np.log(df['UnitPrice'])
df['log_price'].hist()

如您所见,这种转换使价格值符合某种看起来更像正态分布的东西。当涉及到模型构建时,这具有有利的属性。

特征工程使用 np.where()

我们可以使用 np.where()将新列定义为机器学习模型目标或作为模型输入的附加特征。例如,我们可以使用 np.where()创建一列布尔值。首先让我们看一下原始数据的前五行:

df = pd.read_csv("online_retail.csv")
print(df.head())

现在,让我们创建一个新列,该列的值为 True,描述值为“白色悬挂心形 T 形灯座”,对应于第一行:

df['bool_description'] = np.where(df['Description'] == 'WHITE HANGING HEART T-LIGHT HOLDER', True, False)
print(df.head())

您也可以对多个描述值执行相同的操作。我们可以定义一个描述值列表,我们的新列将为其提供真实值:

description_list = ['WHITE HANGING HEART T-LIGHT HOLDER',
'CREAM CUPID HEARTS COAT HANGER', 'RED WOOLLY HOTTIE WHITE HEART.']df['bool_description'] = np.where(df['Description'].isin(description_list), True, False)
print(df.head())

也可以基于其他列生成字符串要素。这里我们生成字符串输出“是”和“否”:

df['string_description'] = np.where(df['Description'].isin(description_list), 'Yes', 'No')
print(df.head())

甚至二进制整数输出:

df['int_description'] = np.where(df['Description'].isin(description_list), 1, 0)
print(df.head())

数据标注

最后,我经常发现自己需要根据其他列的值来标记数据。假设我们想预测一个产品是否会卖出超过十个单位。我们可以使用 np.where()来分配二进制标签,其中值 1 被分配给销售十个或更多单位的产品,值 0 被分配给销售少于十个单位的产品:

df['new_target'] = np.where(df['Quantity'] >= 10, 1, 0)
print(df.head())

我就停在这里。这篇文章的代码将在 GitHub 上发布。请随意摆弄数据和代码,如果有任何问题,请在下面留下。感谢您的阅读。祝你好运!

NVIDIA Jetson Nano 和乐高迷你人偶

原文:https://towardsdatascience.com/nvidia-jetson-nano-and-lego-minifigures-e62e57cf3f21?source=collection_archive---------30-----------------------

乐高迷你人物与 NVIDIA 杰特森纳米对象检测。

NVIDIA Jetson Nano 是一台小型人工智能计算机,人们经常称它为“类固醇上的树莓 Pi”几天前我收到了我的 Jetson Nano 开发工具包,并决定用它来建立一个小项目:乐高迷你人物对象检测。

设置 Jetson Nano 非常容易,NVIDIA 提供了一个很好的教程:“开始使用 Jetson Nano 开发工具包请注意,您需要 micro USB 电源和 microSD 卡,它们不包含在开发工具包中。此外,我在这个项目中使用了标准的 Raspberry Pi v2 相机。

在初始设置和 SD 卡映像安装之后,我能够启动 Jetson Nano 并登录到设备上的 JupyterLab 服务器。

JupyterLab server running in “headless” mode

为了这个项目,我必须建立一个旋转平台,我决定使用乐高助推。我的想法是将乐高迷你人物放在平台的顶部,将树莓 Pi 摄像头固定在它的前面,并以不同的速度旋转平台,以测试 Jetson Nano 识别的工作原理。

Platform base made with the LEGO Boost

我在 iPhone 上安装的 LEGO Boost 应用程序通过蓝牙连接到乐高积木,它允许我为平台顶部旋转的电机设置不同的速度。在我把不同的乐高迷你模型和其他乐高物品放在平台上之前,我必须把它加长一点。

Platform top used to place LEGO Minifigures

为了建立我的训练数据集,我花了几个小时在互联网上搜索乐高迷你玩具图片,并手动注释它们。我知道你现在在想什么,但是为了科学和互联网的荣耀,必须有人这么做!😉我已经在 AWS 上建立了一个 NVIDIA DIGITS 实例,创建了数据集,并训练了我的模型。

Model training on NVIDIA DIGITS

如果你想用乐高迷你玩具做一个类似的项目,我训练过的模型可以在这里找到。如果你用它做了一些很酷的东西,请随时告诉我!

最后,我把模型转移到杰特森纳米,我测试了它是如何工作的。你可以在下面的视频中看到:

1280*720px @ 7.6 FPS

我用这个设置做了几次测试,我对 Jetson Nano 的性能很满意。设置它、训练模型和测试的整个过程进行得很顺利。如果您想构建类似的项目,我肯定会建议您尝试一下。

如果你决定购买 Jetson Nano,我建议你参加 NVIDIA 的关于 Jetson Nano 的“人工智能入门”课程,这是免费的。它将带你通过几个样本图像分类和图像回归项目,这足以让你开始你的人工智能之旅。完成本课程后,您将获得一份证书:

NVIDIA Jetson Nano Certificate

对于这个项目,我要特别感谢我的儿子简,他帮助我组装了乐高助推平台。

感谢阅读,我希望你喜欢它!

Nvidia 的新数据科学工作站——回顾和基准

原文:https://towardsdatascience.com/nvidias-new-data-science-workstation-a-review-and-benchmark-e451db600551?source=collection_archive---------6-----------------------

数据科学炙手可热。

我为学习者写了一份名为《强大的知识》的时事通讯。每一期都包含链接和最佳内容的关键课程,包括引文、书籍、文章、播客和视频。每一个人都是为了学习如何过上更明智、更快乐、更充实的生活而被挑选出来的。 在这里报名

在过去的几年里,人们对数据科学的兴趣激增,以至于许多公司正在重新调整其业务战略,并将自己标榜为“数据驱动”。

这有一个很好的理由,而且这不是什么秘密:更多的数据给了我们更大的机会来提取洞察力并创造更大的商业价值。

大数据集需要大计算能力。你需要一个好的 CPU,最好是像至强处理器那样的多核处理器。大量内存是一个明确的要求,数据科学家购买 64 甚至 128GB 内存的情况并不少见,有时这甚至不够!

The Nvidia Quadro RTX 8000 GPU has 48GB of VRAM

最重要的是,在深度学习中变得非常流行之后,GPU 现在正在进入数据科学。GPU 现在也可以用来加速大型数据帧的处理和可视化(类似于熊猫)。一直受欢迎的 XGBoost 库自带内置 GPU 加速。

Nvidia 最近发布了他们的数据科学工作站,一台将所有数据科学硬件和软件整合到一个漂亮的包中的 PC。工作站是一台完全强大的机器,拥有所有的计算能力和软件,非常适合处理数据。

我最近有机会测试和评估数据科学工作站,我们将在本文中详细介绍。

规格

我测试的工作站是由 Boxx 打造的。它附带所有预构建的硬件和预安装的软件,外加一些额外的电缆以防万一。预建机器非常棒,因为这可能需要几个小时。以下是主要的硬件规格:

  • CPU — 2 个英特尔至强处理器 Gold 5217 ,每个处理器 8 个内核/ 16 个线程,3.0Ghz
  • RAM—192 GB DDR 4–2933 MHz ECC
  • 存储— 1.0TB 固态硬盘 M.2 PCIe 硬盘
  • GPU — 2 个 NVIDIA Quadro RTX 8000 ,每个 48GB VRAM

外加鼠标、键盘和 3 年保修。

当涉及到让您的钱发挥最大作用时,构建一台定制机器始终是一条可行之路。这台机器配备的部件挑选得恰到好处:来自并行处理 CPU 的 32 个线程,大量的高速 RAM,一个 PCIe SSD(比标准 SATA 驱动器快得多,示例),以及两个各带 48GB VRAM 的 GPU。

The Data Science Workstation from Boxx. Although it’s designed for Data Science, it still comes with all the standard ports including USB, audio, mic, and a disk drive

接下来是经常被低估的部分:软件。该工作站预装了 Ubuntu 18.04,以及几乎所有你想从 source 安装的数据科学和机器学习库和软件。仅举几个例子:

  • 数据和 ML — pandas、numpy、scipy、numba、matplotlib、xgboost、dask、scikit-learn、h5py、cython
  • 深度学习— TensorFlow、Keras、PyTorch、NLTK
  • Nvidia — GPU 驱动,CUDA 10,cuDNN,急流

所有这些 Python 库都打包在一个 Python 虚拟环境中,以避免任何未来的冲突。

从源代码安装 TensorFlow 可能是一项重大挑战。让 GPU 驱动程序和 CUDA 与上述任何一个库一起工作会更加困难。因此,预装所有软件是避免大麻烦的一大解脱。

那么,这些听起来很棒的硬件和软件能做什么呢?

让我们找出答案。

XGBoost 基准测试

XGBoost 是一个开源库,提供了梯度增强决策树的高性能实现。底层的 C++代码库与顶层的 Python 接口相结合,使它变得超级快速和易于使用。这是数据科学家的首选图书馆,尤其是在 Kaggle 竞赛中。

我们将运行一个基准测试,看看工作站在使用 XGBoost 处理一个非常大的数据集时表现如何。我们将使用来自 Rapids.ai 的演示笔记本来运行测试。

Rapids 是一套软件库,旨在通过利用 GPU 来加速数据科学。它使用低级的 CUDA 代码来实现快速的、GPU 优化的实现算法,同时仍然在顶部有一个易于使用的 Python 层。

How rapids speeds things up

笔记本使用 Numpy 的random.rand()函数生成数据帧。为了突破极限,我将数据帧的大小设置为 1,000,000 行乘以 5000 列 float32 数字;这是我在笔记本上能做的最大的内存了。如果您更有效地读取数据,您可能会挤出更多的空间,因为一旦培训开始,机器上的 RAM 使用量似乎就稳定下来了。

笔记本然后在数据上运行我们的 XGBoost 模型的训练。

即使有如此庞大的数据集,仅使用 CPU,总共 16 核/ 32 线程的 2 个至强处理器也能很好地处理它。一旦训练开始,所有 32 个线程的使用率都将达到 100%。我们还有足够的内存空间,如果我们想的话,可以运行另一个更小的训练任务。

一旦我们添加了 GPU,XGBoost 的速度在单个 GPU 和 5X 在两个 GPU 的情况下无缝加速了约 4.5 倍。

深度学习基准

深度学习在数据科学中有自己稳固的地位。计算机视觉和自然语言处理中几乎所有的挑战都是由最先进的深度网络主导的。

人们可能想要购买具有这种 GPU 能力的机器的一个重要原因是为了训练深度学习模型。

对于大型深度学习数据集,GPU 内存越多越好。那些数百层深的深度网络需要大量的内存空间,尤其是如果您想要增加批量大小来帮助加快训练速度。

高端消费 GPU,如 2080 Ti 和 1080 Ti,配有 11GB 的内存。它们是非常强大的卡,但 11GB 通常不足以在内存中容纳一个大的神经网络。你可以使用更强大的东西,比如云上的 V100 GPU,但按需每小时收费 3.06 美元!

为了测试我们能从这些 RTX 8000 中得到多少,我们将使用 TensorFlow 的官方 tf_cnn_benchmarks 。该存储库包含在 ImageNet 分类数据集上运行标准图像分类模型训练的脚本。训练以设定的迭代次数运行,而平均速度以图像/秒为单位测量。

为了真正测试工作站的能力,我们将使用不同的批处理大小和 GPU 数量来运行基准测试。我在这个基准上训练一只 ResNet152 的结果如下表所示。

即使是一台 RTX 8000 也能每秒处理 100 多张图像,对于 ResNet152 来说已经非常快了。我们也有足够的空间来增加批量,进一步加快速度,达到 256。

由于我们能够充分利用我们的计算能力,较大的批量已经被证明能够持续地减少训练时间。在一些需要大量内存的应用中,如用于视频处理的 3D CNNs,即使是 1 的批处理大小也无法在标准的消费级 11GB GPU 上运行!RTX 8000 中的 48GB 为批量大小和型号大小提供了充足的空间。

最后几点

总而言之,数据科学工作站是一台伟大的机器。真的很难不与所有高质量的硬件在一起。

最棒的是,一切都“正常工作”。所有库和软件都更新到最新版本并完全安装。几乎令人惊讶的是,打开电脑,你会发现你可以毫无困难地运行通常需要安装源代码的 TensorFlow 代码。仅此一项就能节省大量的时间、金钱和挫折!

硬件选择是正确的。拥有如此多的 RAM 和 GPU 内存带来的灵活性非常方便。没有运行许多 GPU 通常带来的额外工作或问题。获得越来越多的 GPU 也有递减的回报,因为你超过了 4 张牌。如果您确实喜欢不同的硬件设置,您可以在订购机器时定制您的 CPU、RAM 和 GPU 选择,以满足您的需求。

获得一台内部工作站可能是一笔相当大的前期投资——你一次性购买了大量硬件。但是,在本地工作的便利性,没有云成本,一切都设置得很完美,远远超过了前期的价格。这是一个“管用”的数据科学包。

喜欢学习?

在推特上关注我,我会在那里发布所有最新最棒的人工智能、技术和科学!也在 LinkedIn 上和我联系吧!

目标探测精度(mAP)备忘单

原文:https://towardsdatascience.com/object-detection-accuracy-map-cheat-sheet-8f710fd79011?source=collection_archive---------4-----------------------

6 个免费赠品,帮助您提高对象检测模型的性能

物体检测是机器学习(ML)应用中的一种,已经获得了一般人工智能社区越来越多的关注。处于当代计算机视觉应用的中间,包括运动识别、图像分类、生物识别、自动驾驶汽车、法医、真实世界机器人等等,显而易见,人工智能研究人员和工程师都将长期驻扎在这一趋势上。

此外,作为一个重要的研究领域和前沿创新,大公司处于投资对象检测研究和开发的前沿,另一方面,研究人员集中精力提高对象检测神经网络的性能。

本指南探讨了对象检测领域的研究人员可以应用的经过验证的通用方法,以在不增加任何计算成本的情况下,将不同网络结构的模型性能提高多达 5%。研究人员肯定需要探索这些调整,并考虑将它们应用于对象检测训练以提高性能。

用于物体检测的视觉连贯图像混合(+3.55%地图增强)

在用 YOLOv3 模型在 COCO 2017 和 PASCAL 数据集上进行测试后,该方法已经被证明可以成功减轻网络分类中的对立恐惧。

这里的不同之处在于,研究人员引入了自然图像呈现中常见的遮挡和空间信号扰动,特别是使用几何保留位置进行图像混合,以避免初始训练迭代期间图像失真。他们还寻求具有更直观的一致性比率的 beta 分布,包括 a >= 1 和 b >= 1,而不是遵循实现实际模型性能改进的传统图像分类。

这些性能免费赠品直接来自我在建立我的每周人工智能研究时事通讯 AI Scholar 时发现的一篇研究论文。立即注册 ,了解最新动态,成为第一个了解这些和更多信息的人

分类头标签平滑(+2.16%地图增强)

现有模型应用 Softmax 技术来计算类别的概率分布。但是有一个风险是模型对它的预测过于自信,这可能导致过度拟合。一个可能的解决办法是放松我们对标签的信心。例如,我们可以将损失目标值从 1 稍微降低到 0.9。自然地,我们稍微增加了其他人的目标值 0。这种想法被称为标签平滑。有关更多信息,请参考此。

神奇的标签平滑实验

数据预处理(混合结果)

对于对象检测预处理,关键是要采取额外的谨慎措施,因为检测网络对几何变换很敏感。一些经过验证的数据扩充方法包括:

  • 用于随机裁剪(带约束)、随机扩展、随机水平翻转和随机调整大小(带随机插值)的随机几何变换。
  • 亮度、色调、饱和度和对比度的随机颜色抖动

训练调度器改造(+1.44%地图提升)

在模型训练中,步长调度是应用最广泛的学习速率调度。它包括在多次模型迭代后,将学习率乘以一个小于 1 的常数。例如,对于更快的 RCNN,默认的分步学习速率计划旨在在 60k 次迭代时将学习速率降低 0.1 倍。同样,YOLOv3 在 40k 和 45k 迭代时使用相同的比率来降低学习率。

在最先进的对象检测器中,步长调度器的缺点是学习速率急剧变化,这可能导致优化器在后续迭代中重新稳定。

更好的方法是对以下人员进行培训:

  • 余弦调度器— 根据 0 到 pi 的余弦函数值调整学习率。它从缓慢降低学习率开始,然后快速降低一半,最终达到一个微小的斜率,进一步将学习率降低到 0。
  • 预热调度器— 旨在避免初始模型训练迭代期间的梯度爆炸。

余弦调度器较少遭受平台现象,并且已经被证明优于步进调度器。应用这两个调度器可以帮助您获得更好的验证准确性。

同步批处理标准化(+0.56%地图增强)

诚然,在多台设备(GPU)上实现批量规范化速度很快,而且不会增加通信开销。但是,它减少了批量大小,并在计算过程中改变了统计数据,这会损害模型性能。这个问题的解决方案在于同步批处理规范化。使用 YOLOv3 对同步批处理规范化进行了评估,以显示相对较小的批处理大小对 GPU 的影响。

单级 ODN 的随机形状训练(+0.98%地图增强)

为了抑制内存限制并实现更简单的批处理,许多单级对象检测是用固定形状训练的。自然图像有各种不固定的形状。为了处理由固定图像训练引起的过拟合问题,并提高网络预测的泛化能力,最好的方法是实现随机形状模型训练。

如果你认为这些性能技巧有用,你会发现我的文章《深度学习性能备忘单》很有用

总之

为了比较和验证对象检测调整的增量改进,YOLOv3 和更快的 R-CNN 用于在 COCO 和 PASCAL VOC 数据集上表示单级和多级流水线。提议的免费赠品将 fast-RCNN 模型的绝对平均 AP 提高了大约 1.1%到 1.7%,超过了主流的最先进的实现方式。免费赠品也比 YOLOv3 模型高出 4.9%的绝对地图。

对于驱动物体探测领域的研究人员来说,这是一顿免费的午餐。方法代码和预训练权重可在这里访问

感谢阅读:)如果你喜欢它,尽可能多的点击下面的按钮!这对我意义重大,鼓励我写更多这样的故事

咱们也在 Twitter 上联系一下,LinkedIn,或者我的简讯 AI 书生

对象检测和人脸识别算法

原文:https://towardsdatascience.com/object-detection-face-recognition-algorithms-146fec385205?source=collection_archive---------15-----------------------

Photo by Skitterphoto downloaded from Pexels

卷积神经网络.第 2 部分:实现目标探测和人脸识别算法的详细卷积结构

卷积神经网络广泛用于解决基于图像的问题,例如对象/字符检测和人脸识别。在本文中,我们将重点介绍从 LeNet 到 Siamese networks 的最著名架构,其中大多数架构如下:

Image by Author

如果你没有任何关于卷积神经网络的知识,我建议你阅读这篇文章的第一部分 t,讨论 CNN 的基础知识。

注意:因为 Medium 不支持 LaTeX,所以数学表达式是作为图像插入的。因此,为了更好的阅读体验,我建议你关闭黑暗模式。

目录

1。交叉熵
2。图像分类
3。物体检测— YOLOv3
4。人脸识别—暹罗网络

1-交叉熵

当对图像进行分类时,我们通常在最后一层使用大小为( C ,1)的softmax函数,其中 C 是所讨论的类的数量。
向量的第I行是输入图像属于类别 i 的概率。predicted class被设置为与highest probability.相对应的那个

网络通过使用反向传播进行学习,并优化定义如下的cross entropy:

在哪里

  • p ( x)是参考概率,如果对象确实属于所填写的类,则等于 1,否则等于 0
  • q ( x)是网络通过 softmax 获知的对象 x 属于该类的概率

对于输入 xclass_j :

因此,我们把loss function设定为:

我们平均损失,其中 m 是训练集的大小。

2-图像分类

LeNet —数字识别

LeNet 是由 Yann Lecun 开发的一个架构,它的目标是检测输入中出现的数字。
给定从 0 到 9 的hand-written位数的gray-scale幅图像,卷积神经网络预测图像的位数。
训练集被称为MNIST,它是一个数据集,包含超过 70k 个具有 28x28x1 像素的图像。神经网络具有以下计算超过 60k 个参数的架构:

Official paper of LeNet

更多详情,建议你看官方论文。

AlexNet

AlexNet 是一个著名的建筑,它赢得了 2012 年的 ImageNet 竞赛。它类似于 LeNet,但有更多的层次,辍学和重新激活功能的大部分时间。

Official paper of AlexNet

训练集是ImageNet database的子集,T3 是 1500 万张标记的图像,具有高分辨率,代表超过 22k 个类别。
AlexNet 在训练集中使用了超过 120 万张图片,在验证集中使用了 50k,在测试集中使用了 150k,这些图片都被调整到了 227x227x3。该架构有多个60 million parameters,因此在2 GPUs上被训练,它输出一个大小为 (1000,1)softmax vector

要了解更多信息,我建议你阅读官方文件。

VGG-16

VGG-16 在一个卷积神经网络上进行图像分类,在同一个数据集ImageNet上训练,并且已经在多个138 million parametersGPU 上训练。
架构如下:

Official paper of VGG-16

它比 AlexNet 更准确、更深入,因为它用连续的 3x3 内核取代了大型内核 11x11x5 和 5x5。更多细节,请查看 VGG 项目的官方文件。

三物体检测— YOLO

目标检测是在图像中检测多个目标的任务,包括目标定位和目标分类。第一种粗略的方法是滑动具有可定制尺寸的窗口,并使用在裁剪图像上训练的网络来预测每次内容的类别。这个过程有很高的计算成本,幸运的是可以使用卷积来实现自动化。
YOLO 代表YouOonlyLookOnce,其基本思想是在图像上放置一个网格(通常为 19x19 ),其中:

只有一个单元,即包含对象中心/中点的单元,负责检测该对象

网格( ij )的每个单元格标记如下:

Image by Author

因此,对于每个图像,目标输出的大小为:

IOU & NMS

为了评估对象定位,我们使用IintersectionOverUnion 来测量两个边界框之间的overlap:

Image by Author

当预测给定网格单元中给定对象的边界框时,可能会给出许多输出,Non-Max Suppression帮助您检测对象only once。它取最高的概率,并抑制具有高重叠(IOU)的其他框。
对于网格的每个单元,算法如下:

Image by Author

锚箱

在大多数情况下,一个网格单元可能包含multiple objects,锚盒允许检测所有这些。在2 anchor boxes的情况下,网格的每个单元格标记如下:

Image by Author

更一般地,输出目标的大小为:

其中 N 为班数 M 为锚箱数。

YOLOv3 算法

YOLO 接受了 coco 数据集的训练,这是一个大规模的对象检测、分割和字幕数据库,包含 80 个对象类别。YOLOv3 有一个Darknet-53架构作为特征提取器,也称为backbone

通过使用梯度方法最小化loss function来进行训练。
combined的:

  • p_c 上的逻辑回归损失
  • b_i 的平方误差损失
  • 概率 c_i 的软最大损失(交叉熵)

在每个时期,在每个单元中,我们生成输出 y_(i,j)evaluate损失函数。
进行预测时,我们检查 p_c 是否足够高,对于每个网格单元,我们去除低概率预测,并对每个类使用非最大抑制来生成最终输出。
想了解更多信息,我建议你阅读官方论文。

4-人脸识别-连体网络

暹罗网络是神经网络,通常是卷积的,它允许计算两个输入(在我们的情况下是图像)之间的相似度,如下所示:

Image by Author

CNN 模块的目的是在另一个空间中表示图像上的信息,这要归功于一个函数,叫做embedding space。然后,我们使用某个距离比较两个嵌入。暹罗网络中的学习是通过最小化一个目标函数来完成的,该目标函数由一个叫做triplet的损失函数组成。

triplet函数以 3 个向量变量作为输入:一个锚点 A ,一个正的 P (类似于 A )和一个负的 N (不同于 A )。因此,我们希望:

其中∨x∨=<xx >为给定的标量积。

为了防止学习函数 f 为空,我们定义裕量 0 < α ≤1,从而:

因此,我们将loss函数定义如下:

从大小为 n 的学习数据库开始,要最小化的目标函数是:

在训练架构时,对于每个时期,我们固定三元组的数量,并且对于每个三元组:

  • 我们随机选择同一类别的两个图像(锚和积极的)
  • 我们从另一个类中随机选取一张图片(负面)

一个三联体( 一个NP )可以是:

  • 易负,当∩f(A)f(P)∩+αf(A)f(【T75
  • 半硬负,当∩f(A)f(P)∩+α>∩f(A)f(N)∩>∩
  • 硬负,当∩f(A)—f(N)∩<∩f(A)f(P)∩

我们通常选择聚焦在半硬底片上来训练神经网络。

应用:人脸识别

暹罗网络可以用来开发一个能够识别人脸的系统。给定相机拍摄的图像,该架构将其与数据库中的所有图像进行比较。由于我们的数据库中不能有同一个人的多个图像,我们通常在足够丰富的开源图像集上训练暹罗网络来创建三胞胎。

Image by Author

卷积神经网络学习相似性函数 f ,这是图像的嵌入。
给定一张相机照片,我们将其与数据库中的每张图像进行比较,从而:

  • 如果 d ( f ( 图像图像 _ j)≤τ,两幅图像代表同一个人
  • 如果 d ( f ( 图像图像 _ j)>τ,图像是两个不同的人

我们选择距离 d 最接近图像的人脸 image_j 。阈值 τ 以这样一种方式选择,即例如F1-得分最高。

结论

CNN 是图像处理中广泛使用的架构,它们能够实现更好更快的结果。最近,它们也被用于文本处理,其中网络的输入是标记的嵌入,而不是图像的像素。

不要犹豫,检查我以前的文章处理:

  • 深度学习的数学
  • 卷积神经网络的数学
  • 递归神经网络

参考

  • 深度学习专业化,Coursera,吴恩达
  • 机器学习,洛里亚,克里斯托夫·塞里萨拉

原载于 2019 年 2 月 15 日【https://www.ismailmebsout.com

基于 RetinaNet 的航空影像目标检测

原文:https://towardsdatascience.com/object-detection-on-aerial-imagery-using-retinanet-626130ba2203?source=collection_archive---------1-----------------------

ESRI 数据科学挑战赛 2019 第三名解决方案

(Left) the original image. (Right) Car detections using RetinaNet, marked in green boxes

Detecting cars and swimming pools using RetinaNet

介绍

为了进行纳税评估,通常需要在实地人工进行调查。这些调查对计算房产的真实价值很重要。例如,拥有一个游泳池可以提高房地产价格。类似地,一个街区或商店周围的汽车数量可以表明那个地方的经济活动水平。能够通过航空图像和人工智能实现这一点,可以通过消除低效率以及人类所需的高成本和时间来大大帮助这些过程。

为了解决这个问题,我们将尝试在 224x224 像素的航空图像的 RGB 芯片中检测汽车和游泳池。训练数据集具有 3748 个图像,具有 PASCAL VOC 格式的边界框注释和标签。

这个问题和数据集一起由 ESRI 在黑客地球上发布为 ESRI 数据科学挑战赛 2019 。我参加了比赛,并在公共排行榜中获得第三名,在IoU = 0.3时,我使用最先进的 RetinaNet 模型获得了 77.99 的地图(平均精度)。在下面的帖子中,我将解释我是如何尝试这个问题的。

RetinaNet

RetinaNet 是通过对现有的单级对象检测模型(如 YOLO 和 SSD)进行两项改进而形成的:

  1. 用于目标检测的特征金字塔网络
  2. 密集物体检测的焦点损失

特征金字塔网络

金字塔网络通常用于识别不同尺度的物体。特征金字塔网络(FPN)利用深层 CNN 固有的多尺度金字塔等级来创建特征金字塔。

一级 RetinaNet 网络架构在前馈 ResNet 架构(a)之上使用特征金字塔网络(FPN)主干来生成丰富的多尺度卷积特征金字塔(b)。RetinaNet 将两个子网络连接到该主干,一个用于分类锚盒(c ),一个用于从锚盒回归到地面真实对象盒(d)。网络设计非常简单,这使得这项工作能够专注于一种新的焦点损失函数,该函数消除了我们的一级检测器与最先进的两级检测器(如带 FPN 的更快 R-CNN)之间的精度差距,同时运行速度更快。

焦点损失

焦点损失是对交叉熵损失的改进,有助于减少分类良好的示例的相对损失,并将更多的注意力放在困难的、错误分类的示例上。

焦点损失使得能够在存在大量简单背景示例的情况下训练高度精确的密集物体检测器。

Focal Loss Function

如果你对这个模型的细节更感兴趣,我建议你阅读原始论文和这个非常有用的描述性博客“retina net背后的直觉”。

现在,让我们开始实际的实现并开始编码。这里有一个 Github 库,你可以跟随它:

[## kapil-varshney/esri_retinanet

通过在 GitHub 上创建帐户,为 kapil-varshney/esri_retinanet 的开发做出贡献。

github.com](https://github.com/kapil-varshney/esri_retinanet)

安装 Retinanet

我们将使用由 Fizyr 开发的 RetinaNet 的令人敬畏的 Keras 实现。我假设你有你的深度学习机器设置。如果没有,跟随我的指南这里。另外,我建议使用虚拟环境。以下脚本将安装 RetinaNet 和其他必需的包。

或者,您可以在 AWS 上使用一个 GPU 实例(p2.xlarge)和“使用 python 的计算机视觉深度学习”AMI。这个 AMI 预装了 keras-retinanet 和其他必需的包。通过workon retinanet命令激活 RetinaNet 虚拟环境后,就可以开始使用模型了。

注意:Retinanet 计算量很大。一批 4 张(224x224)图像至少需要 7–8gb 的 GPU 内存。

一旦安装了 RetinaNet,就为这个项目创建以下目录结构。

我将详细解释其中的每一个,但这里有一个概述:
build_dataset.py —创建训练/测试集
config/esri_retinanet_config.py的 Python 脚本—构建脚本使用的配置文件。
dataset/annotations —保存所有图像注释的目录
dataset/images —保存所有图像的目录
dataset/submission_test_data_images—Esri 数据科学挑战赛的提交测试目录。如果您正在处理自己的数据集和不同的项目,则可以忽略这一点。
snapshots —每个历元
models后保存所有训练快照的目录—为评估和测试转换快照的目录。将被保存
tensorboard —保存训练日志的目录,供 tensorboard
predict.py —脚本对提交的测试文件进行预测

构建数据集

首先,我们需要编写一个配置文件,它将保存图像、注释、输出 CSV——训练、测试和类,以及测试训练分割值的路径。有了这样的配置文件,代码就可以通用于不同的数据集。

在这个配置文件中,TRAIN_TEST_SPLIT = 0.75。标准做法是在原始数据集的训练数据集和测试数据集之间进行 75–25 或 70–30 甚至 80–20 的拆分。但是,为了这次比赛的目的,我没有制作测试数据集,而是使用完整的数据集进行训练。这样做是因为只提供了 3748 幅图像的小数据集。此外,还提供了一个由 2703 幅图像组成的测试数据集(没有注释),在此基础上,可以通过在线提交预测来测试该模型。

接下来,让我们编写一个 Python 脚本,该脚本将读取所有图像路径和注释,并输出训练和评估模型时所需的三个 CSV:

  1. train . CSV——该文件将保存所有用于训练的注释,格式如下:<path/to/image>,<xmin>,<ymin>,<xmax>,<ymax>,<label>
    每一行代表一个边界框,因此,一幅图像可以出现在多行中,这取决于该图像中有多少对象被注释。
  2. test.csv 格式类似于 train.csv,该文件将保存用于测试模型的所有注释。
  3. classes.csv 包含数据集中所有唯一类标签的文件,带有索引分配(从 0 开始,忽略背景)

让我们从创建一个build_dataset.py文件并导入所需的包开始。注意,我们导入之前在 config 目录中创建的esri_retinanet_config.py文件,并给它一个别名config

在上面的代码中,我们创建了一个参数解析器,可选地接收图像和注释路径、输出 CSV 路径和训练测试分割。是的,我知道我们已经在配置文件中定义了这些参数。但是,我也意识到,有时候我想为一个实验创建一个图像子样本,或者有一个不同的训练测试分割,等等。那时,在执行脚本时选择传递这些参数,而不改变配置文件,速度会更快。您可以看到,我已经为配置文件本身的每个参数提供了默认值。因此,除非您愿意,否则不要求您提供这些参数。解析参数后,为每个参数分配简单的变量名。

在前面的代码中,我们将图像路径读入一个列表,随机化该列表,将其分为训练集和测试集,并以(<dataset_type>, <list_of_paths>, <outpuCSV>)的格式将它们存储在另一个列表dataset中。我们还将初始化CLASS集合来保存数据集中所有唯一的类标签。

接下来,我们遍历每个数据集(训练和测试)并打开要写入的输出 CSV 文件。对于每个数据集,我们在每个图像路径上循环。对于每个图像,提取文件名并构建相应的注释路径。这是因为,通常,图像和注释文件具有相同的名称,但扩展名不同。例如,dataset/images/0000001.jpgdataset/annotations/0000001.xml中有其注释。如果数据集遵循不同的命名约定,请修改此部分。使用BeautifulSoup解析注释(XML)文件。然后,我们可以从解析的 XML 中找到“宽度”和“高度”以及“对象”。

对于每幅图像,找到所有的对象,并对每个对象进行迭代。然后,为注释中的每个对象找到边界框(xmin,ymin,xmax,ymax)和类标签(name)。通过截断图像边界外的任何边界框坐标来进行清理。此外,如果任何最小值错误地大于最大值,则进行健全性检查,反之亦然。如果我们找到这样的值,我们将忽略这些对象并继续下一个。

现在,我们已经有了所有的信息,我们可以继续写入输出 CSV,一次一行。此外,继续向CLASSES集合添加标签。这将最终拥有所有唯一的类标签。

构建所需格式的数据集的最后一件事是将带有各自索引的类标签写入 CSV。在 ESRI 数据集中,只有两个类-汽车(标签:' 1 ',索引:1)和游泳池(标签:' 2 ',索引:0)。这就是classes.csv查找 Esri 数据集的方式。

2,0
1,1

训练和评估模型

现在,数据集已经准备好,RetinaNet 已经安装,让我们继续在数据集上训练模型。

# For a list of all arguments
$ retinanet-train --help

为了训练模型,我使用了以下命令:

$ retinanet-train --weights resnet50_coco_best_v2.1.0.h5 \
--batch-size 4 --steps 4001 --epochs 20 \
--snapshot-path snapshots --tensorboard-dir tensorboard \
csv dataset/train.csv dataset/classes.csv

建议加载预训练的模型或权重文件,而不是从头开始训练,以加快训练速度(损失会更早开始收敛)。我在 COCO 数据集上使用了来自带有 ResNet50 主干的预训练模型的权重。使用以下链接下载该文件。

[https://github.com/fizyr/keras-retinanet/releases/download/0.5.0/resnet50_coco_best_v2.1.0.h5](https://github.com/fizyr/keras-retinanet/releases/download/0.5.0/resnet50_coco_best_v2.1.0.h5)

batch-sizesteps将取决于你的系统配置(主要是 GPU)和数据集。我通常从batch-size = 8开始,然后根据模型训练是否成功开始,增加或减少 2 倍。如果训练成功开始,我将终止训练(CTRL+C ),并以较大的批量开始,否则以较小的批量开始。

一旦决定了批量大小,您就需要计算在每个时期覆盖整个数据集所需的步骤。下面的命令将给出先前在dataset目录中创建的train.csv中的行数。

$ wc -l datatset/train.csv

步长的计算很简单:steps = count of rows in train.csv / batch-size。接下来,设置epochs的数量。根据我的经验,RetinaNet 收敛得很快,所以通常用较少的历元就可以完成这项工作。如果不是,你可以随时从上一个时代开始训练,并进一步训练你的模型。因此,我们将提供一个snapshot-path,在每个时期后模型将被保存在这里。

我们还将提供一个tensorflow-dir,所有的日志将被保存,tensorboard 可以运行,以可视化的培训进行。要启动 tensorboard,打开一个新的终端窗口并运行下面提到的命令。在运行 tensorboard 之前,请确保您已经安装了它。

# To launch tensorboard
$ tensorboard --logdir <path/to/logs/dir>

最后,提供带有训练数据集和类标签的csv文件。并执行训练命令。现在,当你的模型训练的时候,去做一个钢铁侠或者睡觉什么的。在 AWS p2.xlarge 实例上的 K80 Tesla GPU 上,每个包含 3748 张(224x224)图像的历元花费了 2 个多小时。

一旦模型训练到您满意的程度,就将模型转换成可用于评估和预测的格式。

# To convert the model
$ retinanet-convert-model <path/to/desired/snapshot.h5> <path/to/output/model.h5># To evaluate the model
$ retinanet-evaluate <path/to/output/model.h5> csv <path/to/train.csv> <path/to/classes.csv># Sample evaluation
95 instances of class 2 with average precision: 0.8874
494 instances of class 1 with average precision: 0.7200
mAP: 0.8037

在对 125 幅测试图像的样本评估中,该模型能够利用 18 个时期的 375 幅图像训练实现 80.37%的 mAP(平均精度)。对于如此小的数据集来说,这是一个很好的结果。

预言

构建一个脚本predict.py,它将使用训练好的模型,对提交的图像进行预测,并将其写在磁盘上。

在将图像输入模型进行预测之前,需要使用 keras_retinanet 实用程序中的一些方法对图像进行预处理。此外,导入我们之前创建的配置文件,用于加载几个路径。

构造参数解析器以在执行脚本时接受参数,然后解析参数。参数model将接受训练模型文件的路径,该文件将用于进行预测。对于类标签和预测输出目录,默认值取自配置文件。因此,这些不是必需的参数。参数input将接受包含图像的目录的路径来进行预测。此外,confidence参数可用于过滤弱预测。

接下来,从类标签 CSV 加载类标签映射,并将其创建到字典中。加载要用于预测的模型。使用input参数中提供的目录路径获取并列出所有图像路径。

迭代每个图像路径,以便我们可以对提供的数据集中的每个图像进行预测。上面代码中的第 6–9 行从图像路径中提取图像文件名,然后构造并打开一个输出文本文件路径,在该路径中保存对该图像的预测。在第 11–15 行中,我们加载图像,对其进行预处理,调整其大小,然后在将其传递给模型之前扩展其尺寸。在第 18 行,我们将预处理的图像传递给模型,它返回预测的框(边界框坐标)、每个框的概率得分以及相关联的标签。在上面块的最后一行,根据原始图像大小重新调整边界框坐标。

接下来,迭代模型预测的每个检测。跳过得分低于提供的置信度值的项目。虽然,如果你想计算地图(平均平均精度)保持所有的预测。为此,将参数confidence的值作为0.0传递。包围盒坐标将是float值,因此将其转换为int。按照所需的格式:<classname> <confidence> <ymin> <xmin> <ymax> <xmax>为每个预测构造一行,并将其写入文件。一旦该图像的所有检测结果都已写入相应的文件,请关闭该文件。

$ python predict.py --model models/output.h5 --input dataset/submission_test_data_images --confidence 0.0

运行上面的命令来执行predict.py脚本。请根据您的数据集和项目随意更改参数。

实验和结果

最初,我只使用 18 个时期 10%的数据(375 张图像)来训练模型。该模型在测试图像上具有置信度值为 0.5 的 71 的 mAP。我继续在另外 10 个时期的 3748 幅图像的完整数据集上训练该模型,以产生 74 幅增加的地图。我决定对模型进行一点工程设计,并对锚盒进行修改。数据集只有方形的边界框,我将这些框的长宽比从[0.5, 1, 2]改为[1]。这似乎是一个很好的尝试,但我意识到这不是因为锚盒的比例会随着图像的增加而改变。随着网络规模的减小,使用总数据集进行网络训练的速度比以前快得多。预测的准确性也有所提高,但随后开始下降。我决定使用置信值为 0.0 的第二代结果来包含所有预测。这就产生了77.99的地图,使我在挑战中获得了第三名。我还尝试了一些其他的实验,将图像的比例用于 FPN 和数据增强参数,但都没有成功,但最终提交时还是坚持使用早期的结果。

摘要

在这篇文章中,我们谈到了最先进的 RetinaNet 模型,以及我如何在 2019 年 Esri 数据科学挑战赛中使用它来检测 224x224 航拍图像中的汽车和游泳池。我们从构建项目目录开始。接下来,我们构建了模型要使用的训练/测试数据集。用适当的参数对模型进行训练,然后对训练好的模型进行转换以进行评估和预测。我们创建了另一个脚本来对提交测试图像进行检测,并将预测写到磁盘上。最后简单描述一下我尝试的实验和取得的成果。

参考

[## 密集物体探测的聚焦损失

迄今为止最高精度的物体探测器是基于一个由 R-CNN 推广的两阶段方法,其中…

arxiv.org](https://arxiv.org/abs/1708.02002) [## 用于目标检测的特征金字塔网络

特征金字塔是识别系统中的基本组件,用于检测不同尺度的对象。但是最近…

arxiv.org](https://arxiv.org/abs/1612.03144) [## 用 Python 进行计算机视觉的深度学习:用我的新书掌握深度学习

计算机视觉深度学习入门吃力?我的新书会教你所有你需要知道的。

www.pyimagesearch.com](https://www.pyimagesearch.com/deep-learning-computer-vision-python-book/)

感谢你阅读这篇文章。希望对你有帮助。欢迎留言,提出意见和建议。也可以在 LinkedIn 上和我联系。下面是 GitHub 存储库和代码:

[## kapil-varshney/esri_retinanet

通过在 GitHub 上创建帐户,为 kapil-varshney/esri_retinanet 的开发做出贡献。

github.com](https://github.com/kapil-varshney/esri_retinanet)

使用 YOLO 框架进行目标检测的综合指南—第一部分

原文:https://towardsdatascience.com/object-detection-part1-4dbe5147ad0a?source=collection_archive---------8-----------------------

YOLO 背后的理论,网络架构和更多

Cover Image (Source: Author)

目录:

  • 介绍
  • 为什么是 YOLO?
  • 它是如何工作的?
  • 并集上的交集
  • 非最大抑制
  • 网络体系结构
  • 培养
  • YOLO 的局限性
  • 结论

简介:

你只看一次(YOLO)是一种新的和更快的对象检测方法。传统系统重新利用分类器来执行检测。基本上,为了检测任何对象,系统采用该对象的分类器,然后对其在图像中不同位置的存在进行分类。其他系统使用区域提议方法在图像中生成潜在的边界框,然后对这些潜在的框运行分类器。这产生了一种稍微有效的方法。分类后,使用后处理来细化边界框,消除重复检测等。由于这些复杂性,系统变得缓慢且难以优化,因为每个组件都必须单独训练。

Object Detection with Confidence Score

为什么是 YOLO?

基本模型可以以每秒 45 帧的速度实时处理图像。作为网络的一个较小版本,快速 YOLO 可以每秒 155 帧的速度处理图像,同时达到其他实时检测器的两倍。它优于其他检测方法,包括 DPM(可变形部分模型)和 R-CNN。

它是如何工作的?

YOLO 将物体检测重新定义为一个单一的回归问题,而不是一个分类问题。该系统只需查看图像一次,就能检测出哪些物体存在以及它们的位置,因此得名 YOLO。

系统将图像分成一个 S×S 的网格。这些网格单元中的每一个预测 B 边界框和这些框的置信度得分。置信度得分表明模型对盒子包含对象的确信程度,以及它认为盒子预测的准确性。可以使用以下公式计算置信度得分:

C = Pr(object) * IoU

IoU:预测框和实际情况之间的交集。

如果单元格中不存在任何对象,则其置信度得分应该为零。

Bounding Box Predictions (Source: Author)

每个边界框由五个预测组成: x,y,w,h 和置信度其中,

(x,y): 代表盒子中心的坐标。这些坐标是相对于网格单元的边界计算的。

w: 边框的宽度。

h: 边框的高度。

每个网格单元还预测 C 个条件类概率 Pr(Classi|Object) 。它只预测每个网格单元的一组类别概率,而不考虑盒子 b 的数量。在测试期间,这些条件类别概率乘以单个盒子置信度预测,该预测给出每个盒子的特定类别置信度得分。这些分数显示了该类别的概率以及该框与对象的匹配程度。

Pr(I 类|对象)Pr(对象)IoU = Pr(I 类) IoU。*

最终的预测被编码为一个 S x S x (B*5 + C)张量。

交集超过并集(欠条):

IoU 用于评估对象检测算法。它是基础真实和预测边界框之间的重叠,即它计算预测框相对于基础真实有多相似。

Demonstration of IoU (Edited by Author)

通常,IoU 的阈值保持在 0.5 以上。尽管许多研究人员采用更严格的阈值,如 0.6 或 0.7。如果边界框的 IoU 小于指定阈值,则不考虑该边界框。

非最大抑制:

该算法可以找到同一物体的多次检测。非最大值抑制是一种算法仅检测一次对象的技术。考虑一个例子,其中算法检测到同一对象的三个边界框。下图显示了具有相应概率的方框。

Multiple Bounding Boxes Of the Same Object (Edited by Author)

盒子的概率分别是 0.7、0.9 和 0.6。为了消除重复,我们首先要选择概率最高的盒子,并将其作为预测输出。然后用预测输出消除任何 IoU > 0.5(或任何阈值)的边界框。结果将是:

Bounding Box Selected After Non-Max Suppression (Edited by Author)

网络架构:

基本模型有 24 个卷积层,后面是 2 个全连接层。它使用 1 x 1 缩减层,然后是 3 x 3 卷积层。快速 YOLO 使用的神经网络有 9 个卷积层,这些层中的过滤器较少。完整的网络如图所示。

Network Architecture (Source)

注:

  • 该架构设计用于 Pascal VOC 数据集,其中 S = 7,B = 2,C = 20。这就是为什么最终的特征图是 7×7,并且输出张量的形状也是(7×7×2 * 5+20)的原因。要将此网络用于不同数量的类或不同的格网大小,您可能需要调整图层尺寸。
  • 最后一层使用线性激活函数。其余的使用泄漏的 ReLU。

培训:

  • 在 ImageNet 1000 级竞争数据集上预训练前 20 个卷积层,然后是平均池层和全连接层。
  • 由于检测需要更好的视觉信息,请将输入分辨率从 224 x 224 提高到 448 x 448。
  • 训练网络 135 个纪元。在整个训练过程中,使用批量 64,动量 0.9,衰减 0.0005。
  • 学习率:对于第一个时期,将学习率从 10–3 提高到 10–2,否则模型会由于不稳定的梯度而发散。继续以 10–2 训练 75 个周期,然后 10–3 训练 30 个周期,然后 10–4 训练 30 个周期。
  • 为了避免过度拟合,请使用剔除和数据扩充。

YOLO 的局限性:

  • 边界框预测的空间约束,因为每个格网单元只能预测两个框,并且只能有一个类。
  • 很难检测成群出现的小物体。
  • 当模型学习从数据本身预测边界框时,它很难以新的或不寻常的纵横比来概括对象。

结论:

这是对研究论文的简要解释,以及从各种其他来源获得的细节。我希望我让你更容易理解这个概念。

虽然如果真的要检查自己的理解,最好的方法还是实现算法。在下一节中,我们将会这样做。许多细节无法通过文本解释,只能在实现时理解。

感谢您的阅读。点击这里进入下一部分。

利用 YOLO 框架进行目标探测的综合指南——第二部分

原文:https://towardsdatascience.com/object-detection-part2-6a265827efe1?source=collection_archive---------10-----------------------

使用 Python 实现

Cover Image (Source: Author)

在最后一部分,我们了解了 YOLO 是什么以及它是如何工作的。在本节中,让我们了解如何使用预先训练的权重应用它并获得结果。这篇文章受到了吴恩达深度学习专业化课程的极大启发。我还试图从各种其他文章/资源中收集信息,以使这个概念更容易理解。

现在是时候使用 Python 实现我们所理解的内容了。您可以借助 Jupyter 笔记本电脑(或您选择的任何其他 IDE)来完成这项工作。YOLO 的实现取自吴恩达的 Github 库。您还必须下载这个 zip 文件,其中包含预训练的权重和包来实现 YOLO。这里有一个链接到我的 GitHub 库,你可以在那里找到 Jupyter 笔记本。

为了更好地理解,我已经尝试对尽可能多的代码行进行注释。

导入库:

让我们首先导入所有需要的库。

import os
import imageio
import matplotlib.pyplot as plt
from matplotlib.pyplot import imshow
import scipy.io
import scipy.misc
import numpy as np
import pandas as pd
import PIL
import tensorflow as tf
from skimage.transform import resize
from keras import backend as K
from keras.layers import Input, Lambda, Conv2D
from keras.models import load_model, Model
from yolo_utils import read_classes, read_anchors, generate_colors, preprocess_image,draw_boxes, scale_boxes
from yad2k.models.keras_yolo import yolo_head, yolo_boxes_to_corners, preprocess_true_boxes, yolo_loss, yolo_body
%matplotlib inline

应用过滤器:

首先,我们将应用阈值过滤器。我们可以通过去掉那些分数低于所选阈值的盒子来做到这一点。

该模型包含 80 个不同的检测类别。它总共给出了 19x19x5x85 个数字,其中:

19x19:网格的形状

5:锚箱数量

85:每盒包含 85 个号码(Pc,bx,by,bh,bw,c1,c2…..c80)

def yolo_filter_boxes(box_confidence, boxes, box_class_probs, threshold = .6):'''
box confidence: tensor of shape (19,19,5,1) containing Pc
boxes: tensor of shape (19,19,5,4)
box_class_probs: tensor of shape (19,19,5,80)
threshold: if Pc<threshold, get rid of that box
'''
    #Computing box scores
    box_scores = box_confidence*box_class_probs #Finding the index of the class with maximum box score
    box_classes = K.argmax(box_scores, -1) #Getting the corresponding box score
    box_class_scores = K.max(box_scores,-1) #Creating a filtering mask. The mask will be true for all the boxes        we intend to keep (pc >= threshold) and false for the rest
    filtering_mask = box_class_scores>threshold #Applying the mask to scores, boxes and classes
    scores = tf.boolean_mask(box_class_scores, filtering_mask)
    boxes = tf.boolean_mask(boxes, filtering_mask)
    classes = tf.boolean_mask(box_classes, filtering_mask)'''
scores: contains class probability score for the selected boxes
boxes: contains (bx,by,bh,bw) coordinates of selected boxes
classes: contains the index of class detected by the selected boxes
'''    
    return scores, boxes, classes

实现并集上的交集(IoU):

现在我们要实现 IoU。这将用于评估边界框。

Intersection over Union (Edited by Author)

我们将使用它的两个角(左上角和右下角)来定义一个盒子。坐标可以命名为(x1,y1,x2,y2)。

我们还必须找出两个盒子的交点坐标。

xi1: 两个框的 x1 坐标的最大值。

yi1: 两个框的 y1 坐标的最大值。

xi2: 两个框的 x2 坐标的最小值。

yi2: 两个框的 y2 坐标的最小值。

相交后形成的矩形的面积可以使用公式计算:(xi2-xi1)*(yi2-yi1)

计算借据的公式是:

(Intersection area)/(Union area)

现在让我们定义一个函数来计算 IoU。

def iou(box1, box2): #Calculating (xi1,yi1,xi2,yi2) of the intersection of box1 and box2 
    xi1 = max(box1[0], box2[0])
    yi1 = max(box1[1], box2[1])
    xi2 = min(box1[2], box2[2])
    yi2 = min(box1[3], box2[3])
    #Calculating the area of intersection
    inter_area = (yi2-yi1)*(xi2-xi1) #Calculating the areas of box1 and box2 using the same formula
    box1_area = (box1[3] - box1[1])*(box1[2] - box1[0])
    box2_area = (box2[3] - box2[1])*(box2[2] - box2[0])
    #Calculating the union area by using the formula: union(A,B) = A+B-Inter(A,B)
    union_area = box1_area + box2_area - inter_area #Calculating iou
    iou = inter_area/union_area

    return iou

实施非最大抑制:

接下来,我们将实现非最大抑制来移除同一对象的所有重复边界框。涉及的步骤有:

  1. 选择得分最高的方框。
  2. 计算其与所有其他盒子的 IoU,并移除 IoU 大于所述阈值的那些盒子。
  3. 重复此操作,直到不再有分数低于所选框的框。

让我们来定义这个函数

def yolo_non_max_suppression(scores, boxes, classes, max_boxes = 10, iou_threshold = 0.5): #tensor used in tf.image.non_max_suppression()of size 'max_boxes' 
    max_boxes_tensor = K.variable(max_boxes, dtype = 'int32') #initiating the tensor 
    K.get_session().run(tf.variables_initializer([max_boxes_tensor])) #Using the tensorflow function tf.image.non_max_suppression to get the indices of boxes kept
    nms_indices = tf.image.non_max_suppression(boxes, scores, max_boxes, iou_threshold) #Using K.gather to individually access scores, boxes and classes from nms_indices
    scores = K.gather(scores, nms_indices)
    boxes = K.gather(boxes, nms_indices)
    classes = K.gather(classes, nms_indices)

    return scores, boxes, classes

调用上面定义的函数:

现在是实现一个函数的时候了,该函数获取深度 CNN 的输出,然后使用上述函数过滤盒子。

注意,有几种方法可以表示一个边界框,即通过它们的角或中点和高度/宽度。YOLO 在几种格式之间进行转换,其中有一个名为“yolo _ boxes _ to _ corners”的函数。

此外,YOLO 还接受了 608 x 608 尺寸图像的训练。如果我们提供的图像的尺寸大于或小于原始尺寸(YOLO 在其上被训练),那么我们将不得不相应地重新缩放边界框以适合图像。为此,我们将使用一个名为“scale _ boxes”的函数。

def yolo_eval(yolo_outputs, image_shape = (720., 1280.), max_boxes = 10, score_threshold = .6, iou_threshold = .5): '''
    yolo_outputs contains:
    box_confidence, box_xy, box_wh, box_class_probs
    '''    #Retrieving output
    box_confidence, box_xy, box_wh, box_class_probs = yolo_outputs #Converting the boxes for filtering functions
    boxes = yolo_boxes_to_corners(box_xy, box_wh) #Using the function defined before to remove boxes with less confidence score
    scores, boxes, classes = yolo_filter_boxes(box_confidence, boxes, box_class_probs, threshold = score_threshold) #Scaling the boxes
    boxes = scale_boxes(boxes, image_shape) #Using the function defined before for non-max suppression
   scores, boxes, classes = yolo_non_max_suppression(scores, boxes, classes, max_boxes, iou_threshold)

    return scores, boxes, classes

加载预训练模型:

现在,我们将在图像上测试 YOLO 预训练模型。为此,我们必须创建一个会话。此外,请记住,我们正在尝试检测 80 个类别,并使用 5 个锚盒。我们在“coco_classes.txt”和“yolo_anchors.txt”中有所有的课程信息,这些信息必须存在于您之前在“model_data”文件夹中下载的 zip 文件中。

YOLO 模型的训练需要很长时间,尤其是如果你没有一个高规格的系统。因此,我们将加载存储在“yolo.h5”中的现有预训练的 Keras YOLO 模型。这些是 YOLOv2 模型的预训练重量。

让我们创建一个会话并加载这些文件。

sess = K.get_session()
class_names = read_classes("model_data/coco_classes.txt")
anchors = read_anchors("model_data/yolo_anchors.txt")
yolo_model = load_model("model_data/yolo.h5")

注意: 在某些情况下,加载砝码时会弹出警告。如果是这种情况,就忽略警告。

#Converting the output of model into usable bounding box tensors
yolo_outputs = yolo_head(yolo_model.output, anchors, len(class_names))
#Filtering the boxes
scores, boxes, classes = yolo_eval(yolo_outputs, image_shape)

到目前为止,我们已经创建了一个会话图,它被提供给 yolo_model 来计算输出,由 yolo_head 处理,并经过过滤函数 yolo_eval。

在图像上应用 YOLO:

现在我们必须实现一个运行图形的函数来测试图像上的 YOLO。

def predict(sess, image_file): #Preprocessing the image
    image, image_data = preprocess_image("images/"+image_file, model_image_size = (608,608)) #Running the session and feeding the input to it
   out_scores, out_boxes, out_classes = sess.run([scores, boxes, classes],feed_dict = {yolo_model.input: image_data, K.learning_phase(): 0}) #Prints the predicted information
    print('Found {} boxes for {}'.format(len(out_boxes), image_file)) #Generates color for drawing bounding boxes
    colors = generate_colors(class_names) #Draws bounding boxes on the image file
    draw_boxes(image, out_scores, out_boxes, out_classes, class_names, colors) #Saving the predicted bounding box on the image
    image.save(os.path.join("out", image_file), quality = 150) #Displaying the results in notebook
    output_image = imageio.imread(os.path.join("out", image_file))
    plt.figure(figsize=(12,12))
    imshow(output_image) return out_scores, out_boxes, out_classes

在您的测试图像上运行以下单元格以查看结果。

#Loading the image
img = plt.imread('images/traffic.jpeg')#Calculating the size of image and passing it as a parameter to yolo_eval
image_shape = float(img.shape[0]),float(img.shape[1])
scores, boxes, classes = yolo_eval(yolo_outputs, image_shape)#Predicts the output
out_scores, out_boxes, out_classes = predict(sess, "traffic.jpeg")

输出是:

Output after feeding image to the model.

结论:

如果你已经走了这么远,非常感谢。请注意,如果使用相同的图像进行检测,结果可能相同,也可能不同。您可以进一步自定义每个图像的最大边界框数、阈值等。以获得更好的结果。

如果你有任何建议让这个博客更好,请在评论中提出。我会努力做出改变。

参考资料:

  • 你只看一次:统一的、实时的物体检测
  • Coursera-卷积神经网络
  • 用 Python 从零开始理解和构建对象检测模型

对象检测:简化

原文:https://towardsdatascience.com/object-detection-simplified-e07aa3830954?source=collection_archive---------9-----------------------

让我们来看看计算机视觉中最著名的问题陈述之一

什么是物体检测?

目标检测是一个常见的计算机视觉问题,它处理在图像中识别和定位某些类别的目标。可以用各种方式解释对象定位,包括在对象周围创建边界框或标记图像中包含对象的每个像素(称为分割)。

Object Detection using bounding boxes

Object Segmentation by predicting pixel-level masks

回到过去..

甚至在 CNN 在计算机视觉中大受欢迎之前,就已经研究了对象检测。虽然 CNN 能够自动提取更复杂和更好的特征,但看一眼传统方法在最坏的情况下可能是一个小弯路,在最好的情况下是一个灵感。

深度学习之前的对象检测是一个分几个步骤的过程,首先是使用 SIFT、HOG 等技术进行边缘检测和特征提取。然后将这些图像与现有的物体模板进行比较,通常是在多尺度水平上,以检测和定位图像中存在的物体。

了解指标

并集上的交集(IoU) : 不能期望边界框预测在像素级上是精确的,因此需要为 2 个边界框之间的重叠范围定义度量。

Union 上的交集确实如它所说的那样。它取所涉及的两个边界框的交集的面积,并用它们的并集的面积除之。这提供了介于 0 和 1 之间的分数,表示两个框之间的重叠质量。

平均精确度和平均召回率:精确度考虑我们的预测有多准确,而召回率则考虑我们是否能够检测到图像中存在的所有对象。平均精度(AP)和平均召回率(AR)是用于对象检测的两个常用度量。

两步目标检测

既然我们已经享用了这道汤,那就让我们直接进入主菜吧!!两步目标检测包括首先识别可能包含目标的边界框,然后分别对每个边界进行分类的算法。

第一步需要一个区域提议网络,提供多个区域,然后将这些区域传递给基于通用 DL 的分类架构。从 rcnn 中的分层分组算法(非常慢)到在快速 rcnn 中使用 CNN 和 ROI 池以及在更快 rcnn 中使用锚点(从而加速流水线和端到端训练),已经向这些区域提议网络(rpn)提供了许多不同的方法和变体。

已知这些算法比它们的一步目标检测对应物执行得更好,但是相比之下更慢。随着多年来提出的各种改进,两步目标检测网络的延迟的当前瓶颈是 RPN 步骤。关于基于 RPN 的物体检测的更多细节,你可以参考下面这个不错的博客。

[## 使用深度学习方法的对象检测:端到端的理论观点

物体探测领域最有影响力的论文详解

towardsdatascience.com](/object-detection-using-deep-learning-approaches-an-end-to-end-theoretical-perspective-4ca27eee8a9a)

一步目标检测

随着实时目标检测的需要,许多一步目标检测架构被提出,如 YOLO,YOLOv2,YOLOv3,SSD,RetinaNet 等。其试图将检测和分类步骤结合起来。

这些算法的主要成就之一是引入了“回归”边界框预测的思想。当每个边界框很容易用几个值(例如,xmin、xmax、ymin 和 ymax)来表示时,将检测和分类步骤结合起来就变得更容易,从而大大加快流水线的速度。

例如,YOLO 将整个图像分成更小的网格框。对于每个网格单元,它预测通过该网格单元的每个边界框的类概率和 x 和 y 坐标。有点像基于图像的验证码,你可以选择所有包含物体的小格子!!!

这些修改允许单步检测器运行得更快,且还可以在全局水平上工作。然而,由于它们不能单独作用于每个边界框,这可能导致它们在较小的对象或附近的类似对象的情况下表现更差。已经引入了多个新的体系结构来给予较低级别的特性更多的重视,从而试图提供一种平衡。

基于热图的对象检测

在某种意义上,基于热图的对象检测可以被认为是基于单镜头的对象检测的扩展。基于单镜头的对象检测算法试图直接回归边界框坐标(或偏移),而基于热图的对象检测提供边界框角/中心的概率分布。

基于热图中这些角/中心峰值的定位,预测得到的边界框。由于可以为每个类别创建不同的热图,因此该方法还结合了检测和分类。虽然基于热图的对象检测目前正在引领新的研究,但它仍然没有传统的一次性对象检测算法快。这是因为这些算法需要更复杂的主干架构(CNN)来获得可观的精度。

下一步是什么?

虽然对象检测是一个不断发展的领域,这些年来已经有了各种改进,但是这个问题显然还没有完全解决。对象检测的方法多种多样,各有利弊,人们总是可以选择最适合自己要求的方法,因此目前还没有哪种算法主宰这个领域。

这个博客是为机器学习领域创建简化介绍的努力的一部分。点击此处的完整系列

[## 机器学习:简化

在你一头扎进去之前就知道了

towardsdatascience.com](/machine-learning-simplified-1fe22fec0fac)

或者干脆阅读系列的下一篇博客

[## 知识蒸馏:简体

窥探师生网络的世界

towardsdatascience.com](/knowledge-distillation-simplified-dd4973dbc764)

参考

[1]林,宗毅,等.“微软 coco:情境中的公共对象”欧洲计算机视觉会议。施普林格,查姆,2014 年。
【2】基于 HOG 的高能效硬件实现,1080HD 60 fps,多尺度支持
【3】任,等,“更快的 r-cnn:面向区域建议网络的实时对象检测”神经信息处理系统进展。2015.
【4】Redmon,Joseph 等《你只看一次:统一的,实时的物体检测》。IEEE 计算机视觉和模式识别会议录。2016.
[5]刘,魏,等.“Ssd:单次多盒探测器”欧洲计算机视觉会议。施普林格,查姆,2016。
[6]周、邢毅、贾成卓、Philipp Krahenbuhl。"通过组合极值点和中心点的自下而上的物体检测."IEEE 计算机视觉和模式识别会议录。2019.

在定制数据集上使用掩模 R-CNN 的对象检测

原文:https://towardsdatascience.com/object-detection-using-mask-r-cnn-on-a-custom-dataset-4f79ab692f6d?source=collection_archive---------2-----------------------

在这篇文章中,我们将实现掩模 R-CNN,用于从自定义数据集 中检测对象

先决条件:

计算机视觉:从 CNN 到面具 R-CC 和 YOLO 的旅程第一部分

计算机视觉:从 CNN 到面具之旅 R-CNN 和 YOLO 第二部分

实例分割使用掩模 R-CNN

迁移学习

使用 ResNet50 转移学习

数据集

文章中使用了袋鼠数据集

屏蔽 R-CNN

Mask R-CNN 是用于实例分割的深度神经网络。该模型分为两部分

  • 区域提议网络(RPN)提出候选对象包围盒。
  • 二进制掩码分类器,为每个类别生成掩码

掩模 R-CNN 具有用于分类和包围盒回归的分支。它使用

  • ResNet101 架构从图像中提取特征。
  • 区域提议网络(RPN)生成感兴趣区域(RoI)

keras 中使用掩码 R-CNN 码的迁移学习

为此我们使用matter port Mask R-CNN。****

步骤 1:克隆屏蔽 R-CNN 库

git clone [https://github.com/matterport/Mask_RCNN.git](https://github.com/matterport/Mask_RCNN.git)
cd Mask_RCNN
$ python setup.py install

****第二步:从matter port下载 COCO 模型的预训练权重。

将文件放在名为“mask_rcnn_coco.h5”的 Mask_RCNN 文件夹中

第三步:导入所需的库

from mrcnn.config import Config
from mrcnn import model as modellib
from mrcnn import visualize
import mrcnn
from mrcnn.utils import Dataset
from mrcnn.model import MaskRCNNimport numpy as np
from numpy import zeros
from numpy import asarray
import colorsys
import argparse
import imutils
import random
import cv2
import os
import timefrom matplotlib import pyplot
from matplotlib.patches import Rectangle
from keras.models import load_model%matplotlib inlinefrom os import listdir
from xml.etree import ElementTree

步骤 4: 我们创建一个myMaskRCNNConfig类,用于在袋鼠数据集上进行训练。它是从基础Mask R-CNN Config类派生出来的,覆盖了一些值。

***class myMaskRCNNConfig(Config):**
    # give the configuration a recognizable name
    **NAME = "MaskRCNN_config"**

    # set the number of GPUs to use along with the number of images
    # per GPU
    **GPU_COUNT = 1
    IMAGES_PER_GPU = 1**

    # number of classes (we would normally add +1 for the background)
     # kangaroo + BG
    **NUM_CLASSES = 1+1**

    # Number of training steps per epoch
    **STEPS_PER_EPOCH = 131**

    # Learning rate
    **LEARNING_RATE=0.006**

    # Skip detections with < 90% confidence
   ** DETECTION_MIN_CONFIDENCE = 0.9**

    # setting Max ground truth instances
    **MAX_GT_INSTANCES=10***

步骤 5:创建一个 myMaskRCNNConfig的实例

***config = myMaskRCNNConfig()***

让我们显示所有的配置值。

***config.display()***

第六步:建立定制的袋鼠数据集。

数据集类提供了一种一致的方式来处理任何数据集。我们将为袋鼠数据集创建新的数据集进行训练,而无需更改模型的代码。

数据集类还支持同时加载多个数据集。当您想要检测不同的对象,而它们都不在一个数据集中时,这非常有用。

load_dataset 方法中,我们使用 add_classadd_image 方法遍历 image 和 annotations 文件夹中的所有文件来添加类、图像和注释以创建数据集。

extract _ boxes方法从注释文件中提取每个边界框。注释文件是使用 pascal VOC 格式的 xml 文件。它返回盒子,它的高度和宽度

load_mask 方法为图像中的每个对象生成遮罩。它为每个实例和类 id 返回一个掩码,这是实例掩码的类 id 的 1D 数组

image _ reference方法返回图像的路径

***class KangarooDataset(Dataset)**:
    # load the dataset definitions
    **def load_dataset(self, dataset_dir, is_train=True)**:

        # Add classes. We have only one class to add.
        **self.add_class("dataset", 1, "kangaroo")**

        # define data locations for images and annotations
        images_dir = dataset_dir + '\\images\\'
        annotations_dir = dataset_dir + '\\annots\\'

        # Iterate through all files in the folder to 
        #add class, images and annotaions
        **for filename in listdir(images_dir):**

            # extract image id
            image_id = filename[:-4]

            # skip bad images
            if image_id in ['00090']:
                continue
            # skip all images after 150 if we are building the train set
            if is_train and int(image_id) >= 150:
                continue
            # skip all images before 150 if we are building the test/val set
            if not is_train and int(image_id) < 150:
                continue

            # setting image file
            **img_path = images_dir + filename**

            # setting annotations file
           ** ann_path = annotations_dir + image_id + '.xml'**

            # adding images and annotations to dataset
            **self.add_image('dataset', image_id=image_id, path=img_path, annotation=ann_path)**# extract bounding boxes from an annotation file
    **def extract_boxes(self, filename):**

        # load and parse the file
        tree = ElementTree.parse(filename)
        # get the root of the document
        root = tree.getroot()
       ** # extract each bounding box**
        boxes = list()
        **for box in root.findall('.//bndbox'):
            xmin = int(box.find('xmin').text)
            ymin = int(box.find('ymin').text)
            xmax = int(box.find('xmax').text)
            ymax = int(box.find('ymax').text)
            coors = [xmin, ymin, xmax, ymax]
            boxes.append(coors)**

        # extract image dimensions
       ** width = int(root.find('.//size/width').text)
        height = int(root.find('.//size/height').text)
        return boxes, width, height**# load the masks for an image
    """Generate instance masks for an image.
       Returns:
        masks: A bool array of shape [height, width, instance count] with
            one mask per instance.
        class_ids: a 1D array of class IDs of the instance masks.
     """
    **def load_mask(self, image_id):**
        # get details of image
        **info = self.image_info[image_id]**

        # define anntation  file location
        **path = info['annotation']**

        # load XML
        **boxes, w, h = self.extract_boxes(path)**

        # create one array for all masks, each on a different channel
        **masks = zeros([h, w, len(boxes)], dtype='uint8')**

        # create masks
        class_ids = list()
        **for i in range(len(boxes)):
            box = boxes[i]
            row_s, row_e = box[1], box[3]
            col_s, col_e = box[0], box[2]
            masks[row_s:row_e, col_s:col_e, i] = 1
            class_ids.append(self.class_names.index('kangaroo'))
        return masks, asarray(class_ids, dtype='int32')**# load an image reference
     """Return the path of the image."""
    **def image_reference(self, image_id):**
        **info = self.image_info[image_id]**
        print(info)
        **return info['path']***

第七步:准备列车和测试装置

*# prepare train set
**train_set = KangarooDataset()
train_set.load_dataset(‘..\\Kangaroo\\kangaroo-master\\kangaroo-master’, is_train=True)
train_set.prepare()**
print(‘Train: %d’ % len(train_set.image_ids))# prepare test/val set
**test_set = KangarooDataset()
test_set.load_dataset(‘..\\Kangaroo\\kangaroo-master\\kangaroo-master’, is_train=False)
test_set.prepare()**
print(‘Test: %d’ % len(test_set.image_ids))*

步骤 8:使用我们创建的配置实例初始化“训练”的屏蔽 R-CNN 模型

*print("Loading Mask R-CNN model...")
**model = modellib.MaskRCNN(mode="training", config=config, model_dir='./')***

步骤 9:从 COCO 数据集中加载掩模 R-CNN 的预训练权重,不包括最后几层

我们从 ResNet101 的训练中排除了最后几层。排除最后的层是为了匹配新数据集中的类的数量。

*#load the weights for COCO
model.load_weights('.\\Mask_RCNN\\mask_rcnn_coco.h5', 
                   by_name=True, 
                   exclude=["mrcnn_class_logits", "mrcnn_bbox_fc",  "mrcnn_bbox", "mrcnn_mask"])*

第十步:训练学习率较高的头部,加快学习速度

我们可以通过提高学习速率来提高头层的学习速度

此外,我们可以将历元增加到 100–500 之间的任何值,并查看对象检测准确性的差异。我只用了 5 个纪元,因为我在 CPU 上训练它。

*## train heads with higher lr to speedup the learning
model.train(train_set, test_set, learning_rate=2*config.LEARNING_RATE, epochs=5, layers=’heads’)history = model.keras_model.history.history*

步骤 11:保存自定义数据集的训练权重

*import time**model_path = '..\\Kangaroo\\kangaroo-master\\kangaroo-master\\mask_rcnn_'  + '.' + str(time.time()) + '.h5'****model.keras_model.save_weights(model_path)***

步骤 12:利用来自训练模型的遮罩和包围盒检测图像中的对象

在推理模式下创建模型。从我们训练模型的数据集中加载模型的权重。

加载我们想要检测的图像的包围盒、类别和置信度百分比

*from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array#Loading the model in the inference mode
**model = modellib.MaskRCNN(mode="inference", config=config, model_dir='./')**# loading the trained weights o the custom dataset
**model.load_weights(model_path, by_name=True)**img = load_img("..\\Kangaroo\\kangaroo-master\\kangaroo-master\\images\\00042.jpg")
img = img_to_array(img)# detecting objects in the image
**result= model.detect([img])***

最后显示结果

*image_id = 20
**image, image_meta, gt_class_id, gt_bbox, gt_mask =    modellib.load_image_gt(test_set, config, image_id, use_mini_mask=False)****info = test_set.image_info[image_id]**
print("image ID: {}.{} ({}) {}".format(info["source"], info["id"], image_id, 
                                       **test_set.image_reference(image_id)))**# Run object detection
**results = model.detect([image], verbose=1)**# Display results

**r = results[0]**
**visualize.display_instances(image, r['rois'], r['masks'], r['class_ids'], 
                            test_set.class_names, r['scores'], 
                            title="Predictions")***

参考资料:

*** [## matterport/Mask_RCNN

这是 Mask R-CNN 在 Python 3、Keras 和 TensorFlow 上的实现。该模型生成边界框和…

github.com](https://github.com/matterport/Mask_RCNN/)

https://github . com/arshren/Mask _ RCNN/blob/master/Transfer % 20 learning % 20 Mask % 20 RCNN-Custom % 20 dataset . ipynb

[## 色彩的飞溅:使用掩膜 R-CNN 和张量流的实例分割

通过构建彩色飞溅滤镜来解释

engineering.matterport.com](https://engineering.matterport.com/splash-of-color-instance-segmentation-with-mask-r-cnn-and-tensorflow-7c761e238b46)

https://machine learning mastery . com/how-to-perform-object-detection-with-yolov 3-in-keras/***

使用 Keras 的 YOLOv3 对象检测

原文:https://towardsdatascience.com/object-detection-using-yolov3-using-keras-80bf35e61ce1?source=collection_archive---------3-----------------------

第一部分——CNN,R-CNN,快 R-CNN,更快 R-CNN

第二部分——了解 YOLO、约洛夫 2、YOLO v3

这是本系列的第三篇文章,我们将使用 YOLOv3 预测边界框和类。代码可用github

output from YOLO v3

你只需要看一次(YOLO)图像,就可以使用一个卷积网络来预测什么物体存在以及它们在哪里。YOLO 预测多个边界框和这些框的类别概率。

这段代码将使用 yolo v3 中预先训练的权重,然后使用 keras 库预测边界框和类概率

该代码受到 experiencor 的 keras-yolo3 projec 的强烈启发,用于使用 YOLOv3 模型执行对象检测。代码是将代码分解成简单的步骤,使用 yolov3 模型来预测边界框和类。原始代码可从 Huynh Ngoc Anh 的 github 获得。 Yolo3 预训练权重可从 YOLOv3 预训练权重 下载。

YOLOv3 模型使用预先训练的权重来解决标准对象检测问题,如袋鼠数据集、浣熊数据集、红细胞检测等。该模型将用于新图像上的对象检测。

第一步:导入所需的库

import os
import scipy.io
import scipy.misc
import numpy as np
import pandas as pd
import PIL
import struct
import cv2
from numpy import expand_dimsimport tensorflow as tf
from skimage.transform import resize
from keras import backend as K
from keras.layers import Input, Lambda, Conv2D, BatchNormalization, LeakyReLU, ZeroPadding2D, UpSampling2Dfrom keras.models import load_model, Model
from keras.layers.merge import add, concatenate
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_arrayimport matplotlib.pyplot as plt
from matplotlib.pyplot import imshow
from matplotlib.patches import Rectangle
%matplotlib inline

第二步:创建一个类 WeightReader 来加载 yolov3 的预训练权重

WeightReader 类将解析该文件并将模型权重加载到内存中,以在我们的 Keras 模型中设置它。

# class to load the pretrained Weights
**class WeightReader:**
    **def __init__(self, weight_file)**:
        with open(weight_file, 'rb') as w_f:
            major,    = struct.unpack('i', w_f.read(4))
            minor,    = struct.unpack('i', w_f.read(4))
            revision, = struct.unpack('i', w_f.read(4))if (major*10 + minor) >= 2 and major < 1000 and minor < 1000:
                w_f.read(8)
            else:
                w_f.read(4)transpose = (major > 1000) or (minor > 1000)

            binary = w_f.read()self.offset = 0
        self.all_weights = np.frombuffer(binary, dtype='float32')

    **def read_bytes(self, size)**:
        self.offset = self.offset + size
        return self.all_weights[self.offset-size:self.offset]**def load_weights(self, model):**
        for i in range(106):
            try:
                conv_layer = model.get_layer('conv_' + str(i))
                print("loading weights of convolution #" + str(i))if i not in [81, 93, 105]:
                    norm_layer = model.get_layer('bnorm_' + str(i))size = np.prod(norm_layer.get_weights()[0].shape)beta  = self.read_bytes(size) # bias
                    gamma = self.read_bytes(size) # scale
                    mean  = self.read_bytes(size) # mean
                    var   = self.read_bytes(size) # varianceweights = norm_layer.set_weights([gamma, beta, mean, var])if len(conv_layer.get_weights()) > 1:
                    bias   = self.read_bytes(np.prod(conv_layer.get_weights()[1].shape))
                    kernel = self.read_bytes(np.prod(conv_layer.get_weights()[0].shape))

                    kernel = kernel.reshape(list(reversed(conv_layer.get_weights()[0].shape)))
                    kernel = kernel.transpose([2,3,1,0])
                    conv_layer.set_weights([kernel, bias])
                else:
                    kernel = self.read_bytes(np.prod(conv_layer.get_weights()[0].shape))
                    kernel = kernel.reshape(list(reversed(conv_layer.get_weights()[0].shape)))
                    kernel = kernel.transpose([2,3,1,0])
                    conv_layer.set_weights([kernel])
            except ValueError:
                print("no convolution #" + str(i))     

    def reset(self):
        self.offset = 0

第三步:创建 Yolo v3 模型。

我们首先创建一个函数来创建卷积块

**def _conv_block(inp, convs, skip=True):**
    x = inp
    count = 0

    for conv in convs:
        if count == (len(convs) - 2) and skip:
            skip_connection = x
        count += 1

        if conv['stride'] > 1: x = ZeroPadding2D(((1,0),(1,0)))(x) # peculiar padding as darknet prefer left and top
        x = Conv2D(conv['filter'], 
                   conv['kernel'], 
                   strides=conv['stride'], 
                   padding='valid' if conv['stride'] > 1 else 'same', # peculiar padding as darknet prefer left and top
                   name='conv_' + str(conv['layer_idx']), 
                   use_bias=False if conv['bnorm'] else True)(x)
        if conv['bnorm']: x = BatchNormalization(epsilon=0.001, name='bnorm_' + str(conv['layer_idx']))(x)
        if conv['leaky']: x = LeakyReLU(alpha=0.1, name='leaky_' + str(conv['layer_idx']))(x)return add([skip_connection, x]) if skip else x

接下来,我们创建一个有 108 个卷积层的暗网。我在 CPU 上运行它,在 GPU 上它几乎快了 500 倍

**# creating the YOLO model**
def make_yolov3_model():
    input_image = Input(shape=(None, None, 3))# Layer  0 => 4
    x = _conv_block(input_image, [{'filter': 32, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 0},
                                  {'filter': 64, 'kernel': 3, 'stride': 2, 'bnorm': True, 'leaky': True, 'layer_idx': 1},
                                  {'filter': 32, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 2},
                                  {'filter': 64, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 3}])# Layer  5 => 8
    x = _conv_block(x, [{'filter': 128, 'kernel': 3, 'stride': 2, 'bnorm': True, 'leaky': True, 'layer_idx': 5},
                        {'filter':  64, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 6},
                        {'filter': 128, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 7}])# Layer  9 => 11
    x = _conv_block(x, [{'filter':  64, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 9},
                        {'filter': 128, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 10}])# Layer 12 => 15
    x = _conv_block(x, [{'filter': 256, 'kernel': 3, 'stride': 2, 'bnorm': True, 'leaky': True, 'layer_idx': 12},
                        {'filter': 128, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 13},
                        {'filter': 256, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 14}])# Layer 16 => 36
    for i in range(7):
        x = _conv_block(x, [{'filter': 128, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 16+i*3},
                            {'filter': 256, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 17+i*3}])

    skip_36 = x

    # Layer 37 => 40
    x = _conv_block(x, [{'filter': 512, 'kernel': 3, 'stride': 2, 'bnorm': True, 'leaky': True, 'layer_idx': 37},
                        {'filter': 256, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 38},
                        {'filter': 512, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 39}])# Layer 41 => 61
    for i in range(7):
        x = _conv_block(x, [{'filter': 256, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 41+i*3},
                            {'filter': 512, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 42+i*3}])

    skip_61 = x

    # Layer 62 => 65
    x = _conv_block(x, [{'filter': 1024, 'kernel': 3, 'stride': 2, 'bnorm': True, 'leaky': True, 'layer_idx': 62},
                        {'filter':  512, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 63},
                        {'filter': 1024, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 64}])# Layer 66 => 74
    for i in range(3):
        x = _conv_block(x, [{'filter':  512, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 66+i*3},
                            {'filter': 1024, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 67+i*3}])

    # Layer 75 => 79
    x = _conv_block(x, [{'filter':  512, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 75},
                        {'filter': 1024, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 76},
                        {'filter':  512, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 77},
                        {'filter': 1024, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 78},
                        {'filter':  512, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 79}], skip=False)# Layer 80 => 82
    yolo_82 = _conv_block(x, [{'filter': 1024, 'kernel': 3, 'stride': 1, 'bnorm': True,  'leaky': True,  'layer_idx': 80},
                              {'filter':  255, 'kernel': 1, 'stride': 1, 'bnorm': False, 'leaky': False, 'layer_idx': 81}], skip=False)# Layer 83 => 86
    x = _conv_block(x, [{'filter': 256, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 84}], skip=False)
    x = UpSampling2D(2)(x)
    x = concatenate([x, skip_61])# Layer 87 => 91
    x = _conv_block(x, [{'filter': 256, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 87},
                        {'filter': 512, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 88},
                        {'filter': 256, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 89},
                        {'filter': 512, 'kernel': 3, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 90},
                        {'filter': 256, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True, 'layer_idx': 91}], skip=False)# Layer 92 => 94
    yolo_94 = _conv_block(x, [{'filter': 512, 'kernel': 3, 'stride': 1, 'bnorm': True,  'leaky': True,  'layer_idx': 92},
                              {'filter': 255, 'kernel': 1, 'stride': 1, 'bnorm': False, 'leaky': False, 'layer_idx': 93}], skip=False)# Layer 95 => 98
    x = _conv_block(x, [{'filter': 128, 'kernel': 1, 'stride': 1, 'bnorm': True, 'leaky': True,   'layer_idx': 96}], skip=False)
    x = UpSampling2D(2)(x)
    x = concatenate([x, skip_36])# Layer 99 => 106
    yolo_106 = _conv_block(x, [{'filter': 128, 'kernel': 1, 'stride': 1, 'bnorm': True,  'leaky': True,  'layer_idx': 99},
                               {'filter': 256, 'kernel': 3, 'stride': 1, 'bnorm': True,  'leaky': True,  'layer_idx': 100},
                               {'filter': 128, 'kernel': 1, 'stride': 1, 'bnorm': True,  'leaky': True,  'layer_idx': 101},
                               {'filter': 256, 'kernel': 3, 'stride': 1, 'bnorm': True,  'leaky': True,  'layer_idx': 102},
                               {'filter': 128, 'kernel': 1, 'stride': 1, 'bnorm': True,  'leaky': True,  'layer_idx': 103},
                               {'filter': 256, 'kernel': 3, 'stride': 1, 'bnorm': True,  'leaky': True,  'layer_idx': 104},
                               {'filter': 255, 'kernel': 1, 'stride': 1, 'bnorm': False, 'leaky': False, 'layer_idx': 105}], skip=False)model = Model(input_image, [yolo_82, yolo_94, yolo_106])    
    return model

步骤 4:我们现在创建 yolo 模型并加载预训练的权重

**# create the yolo v3**
yolov3 = make_yolov3_model()**# load the weights trained on COCO into the model**weight_reader = WeightReader(‘yolov3.weights’)
weight_reader.load_weights(yolov3)

第五步:设置变量。

Yolov3 的输入图像大小是 416 x 416,我们使用 net_h 和 net_w 来设置。

对象阈值设定为 0.5,非最大抑制阈值设定为 0.45

我们设置锚框,然后为上下文中的公共对象(COCO)模型定义 80 个标签以进行预测

**net_h, net_w = 416, 416****obj_thresh, nms_thresh = 0.5, 0.45****anchors** = [[116,90, 156,198, 373,326], [30,61, 62,45, 59,119], [10,13, 16,30, 33,23]]**labels** = [“person”, “bicycle”, “car”, “motorbike”, “aeroplane”, “bus”, “train”, “truck”, “boat”, “traffic light”, “fire hydrant”, “stop sign”, “parking meter”, “bench”, “bird”, “cat”, “dog”, “horse”, “sheep”, “cow”, “elephant”, “bear”, “zebra”, “giraffe”, \
 “backpack”, “umbrella”, “handbag”, “tie”, “suitcase”, “frisbee”, “skis”, “snowboard”, “sports ball”, “kite”, “baseball bat”, “baseball glove”, “skateboard”, “surfboard”, “tennis racket”, “bottle”, “wine glass”, “cup”, “fork”, “knife”, “spoon”, “bowl”, “banana”, “apple”, “sandwich”, “orange”, “broccoli”, “carrot”, “hot dog”, “pizza”, “donut”, “cake”, “chair”, “sofa”, “pottedplant”, “bed”, “diningtable”, “toilet”, “tvmonitor”, “laptop”, “mouse”, \
 “remote”, “keyboard”, “cell phone”, “microwave”, “oven”, “toaster”, “sink”, “refrigerator”, “book”, “clock”, “vase”, “scissors”, “teddy bear”, “hair drier”, “toothbrush”]

第六步:将图像加载到右边 416 x 416 的输入形状

from numpy import expand_dimsdef **load_image_pixels(filename, shape)**:
 # load the image to get its shape
 image = load_img(filename)
 width, height = image.size

# load the image with the required size
 image = load_img(filename, target_size=shape) # convert to numpy array
 image = img_to_array(image)

# scale pixel values to [0, 1]
 image = image.astype(‘float32’)
 image /= 255.0

# add a dimension so that we have one sample
 image = expand_dims(image, 0)
 **return image, width, height**

步骤 7:为边界框创建一个类。

BoundBox 在输入图像形状和类别概率的上下文中定义每个边界框的角。

**class BoundBox:**
 **def __init__**(self, xmin, ymin, xmax, ymax, objness = None, classes = None):
 self.xmin = xmin
 self.ymin = ymin
 self.xmax = xmax
 self.ymax = ymax

 self.objness = objness
 self.classes = classesself.label = -1
 self.score = -1**def get_label(self)**:
 if self.label == -1:
 self.label = np.argmax(self.classes)

 return self.label

 **def get_score(self)**:
 if self.score == -1:
 self.score = self.classes[self.get_label()]

 return self.score

步骤 8:为定义函数

  • 间隔重叠-检查两个间隔是否重叠。当一个间隔在另一个间隔开始之前结束时,两个间隔不重叠。
  • 两个盒子的并集交集(IoU)
  • 非最大抑制,将包含对象的框以及非最大阈值作为参数
  • Sigmoid 函数
**def _sigmoid(x)**:
 return 1\. / (1\. + np.exp(-x))**def _interval_overlap(interval_a, interval_b**):
 x1, x2 = interval_a
 x3, x4 = interval_bif x3 < x1:
 if x4 < x1:
 return 0
 else:
 return min(x2,x4) — x1
 else:
 if x2 < x3:
 return 0
 else:
 return min(x2,x4) — x3

**def bbox_iou(box1, box2**):
 intersect_w = _interval_overlap([box1.xmin, box1.xmax], [box2.xmin, box2.xmax])
 intersect_h = _interval_overlap([box1.ymin, box1.ymax], [box2.ymin, box2.ymax])

 intersect = intersect_w * intersect_hw1, h1 = box1.xmax-box1.xmin, box1.ymax-box1.ymin
 w2, h2 = box2.xmax-box2.xmin, box2.ymax-box2.ymin

 union = w1*h1 + w2*h2 — intersect

 return float(intersect) / union**def do_nms(boxes, nms_thresh)**:
 if len(boxes) > 0:
 nb_class = len(boxes[0].classes)
 else:
 return

 for c in range(nb_class):
 sorted_indices = np.argsort([-box.classes[c] for box in boxes])for i in range(len(sorted_indices)):
 index_i = sorted_indices[i]if boxes[index_i].classes[c] == 0: continuefor j in range(i+1, len(sorted_indices)):
 index_j = sorted_indices[j]if bbox_iou(boxes[index_i], boxes[index_j]) >= nms_thresh:
 boxes[index_j].classes[c] = 0

第九步:解码网络的输出。

我们将遍历 NumPy 数组中的每一个,一次一个,并基于对象阈值解码候选边界框和类预测。

前 4 个元素将是边界框的坐标,第 5 个元素将是对象分数,后跟类别概率

**def decode_netout(netout, anchors, obj_thresh, net_h, net_w):**
 grid_h, grid_w = netout.shape[:2]
 nb_box = 3
 netout = netout.reshape((grid_h, grid_w, nb_box, -1))
 nb_class = netout.shape[-1] — 5boxes = [] netout[…, :2] = _sigmoid(netout[…, :2])
 netout[…, 4:] = _sigmoid(netout[…, 4:])
 netout[…, 5:] = netout[…, 4][…, np.newaxis] * netout[…, 5:]
 netout[…, 5:] *= netout[…, 5:] > obj_threshfor i in range(grid_h*grid_w):
 row = i / grid_w
 col = i % grid_w

 for b in range(nb_box):
 # 4th element is objectness score
 objectness = netout[int(row)][int(col)][b][4]
 #objectness = netout[…, :4]

 if(objectness.all() <= obj_thresh): continue

 # first 4 elements are x, y, w, and h
 x, y, w, h = netout[int(row)][int(col)][b][:4]x = (col + x) / grid_w # center position, unit: image width
 y = (row + y) / grid_h # center position, unit: image height
 w = anchors[2 * b + 0] * np.exp(w) / net_w # unit: image width
 h = anchors[2 * b + 1] * np.exp(h) / net_h # unit: image height 

 # last elements are class probabilities
 classes = netout[int(row)][col][b][5:]

 **box = BoundBox(x-w/2, y-h/2, x+w/2, y+h/2, objectness, classes)** boxes.append(box)**return boxes**

步骤 10:纠正 Yolo 框。

我们有边界框,但它们需要被拉伸回原始图像的形状。这将允许绘制原始图像和边界框,检测真实对象。

 **def correct_yolo_boxes(boxes, image_h, image_w, net_h, net_w):**
 if (float(net_w)/image_w) < (float(net_h)/image_h):
 new_w = net_w
 new_h = (image_h*net_w)/image_w
 else:
 new_h = net_w
 new_w = (image_w*net_h)/image_h

 for i in range(len(boxes)):
 x_offset, x_scale = (net_w — new_w)/2./net_w, float(new_w)/net_w
 y_offset, y_scale = (net_h — new_h)/2./net_h, float(new_h)/net_h

 boxes[i].xmin = int((boxes[i].xmin — x_offset) / x_scale * image_w)
 boxes[i].xmax = int((boxes[i].xmax — x_offset) / x_scale * image_w)
 boxes[i].ymin = int((boxes[i].ymin — y_offset) / y_scale * image_h)
 boxes[i].ymax = int((boxes[i].ymax — y_offset) / y_scale * image_h)

步骤 11:获取所有高于指定阈值的盒子。

get_boxes 函数将盒子、标签和阈值的列表作为参数,并返回盒子、标签和分数的并行列表。

 **def get_boxes(boxes, labels, thresh):**
    v_boxes, v_labels, v_scores = list(), list(), list()
    # enumerate all boxes
    for box in boxes:
        # enumerate all possible labels
        for i in range(len(labels)):
            # check if the threshold for this label is high enough
            if box.classes[i] > thresh:
                v_boxes.append(box)
                v_labels.append(labels[i])
                v_scores.append(box.classes[i]*100)
                # don't break, many labels may trigger for one box
    return v_boxes, v_labels, v_scores

步骤 12:在图像中的物体周围画一个白框。

from matplotlib.patches import Rectangle**def draw_boxes(filename, v_boxes, v_labels, v_scores):**

# load the image
 data = plt.imread(filename)

# plot the image
 plt.imshow(data)

# get the context for drawing boxes
 ax = plt.gca()

# plot each box
 for i in range(len(v_boxes)):box = v_boxes[i]
        # get coordinates
        y1, x1, y2, x2 = box.ymin, box.xmin, box.ymax, box.xmax
        # calculate width and height of the box
        width, height = x2 - x1, y2 - y1
        # create the shape
        rect = Rectangle((x1, y1), width, height, fill=False, color='red')
        # draw the box
        ax.add_patch(rect)
        # draw text and score in top left corner
        label = "%s (%.3f)" % (v_labels[i], v_scores[i])
        plt.text(x1, y1, label, color='red')
    # show the plot
plt.show()

最后,我们结合代码对新图像进行预测。

首先我们使用load _ image _ pixels()函数将图像加载到 416 x 416 的输入形状中。

预测盒子起诉 yolov 3T23 预测()方法

Yolov3 模型将预测同一对象的多个框。

然后,我们使用decode _ netout()函数基于对象阈值对候选包围盒和类别预测进行解码

我们通过使用correct _ yolo _ boxes()函数来校正边界框,以将其拉伸回原始图像的形状

边界框将根据 IoU 定义的重叠进行过滤,然后使用 do_nms() 函数应用非最大值抑制。

我们使用 get_boxes() 得到高于指定类阈值 0.6 的盒子,然后使用 draw_boxes() 函数在图像上绘制这些盒子。

# define our new image
photo_filename = 'eagle.png'# load and prepare image
image, image_w, image_h = **load_image_pixels**(photo_filename, (net_w, net_w))# make prediction
**yolos = yolov3.predict(image)**# summarize the shape of the list of arrays
print([a.shape for a in yolos])# define the anchors
anchors = [[116,90, 156,198, 373,326], [30,61, 62,45, 59,119], [10,13, 16,30, 33,23]]# define the probability threshold for detected objects
class_threshold = 0.6boxes = list()for i in range(len(yolos)):
        # decode the output of the network
    boxes += ***decode_netout***(yolos[i][0], anchors[i], obj_thresh, nms_thresh, net_h, net_w)# correct the sizes of the bounding boxes
**correct_yolo_boxes(boxes, image_h, image_w, net_h, net_w)**# suppress non-maximal boxes
**do_nms**(boxes, nms_thresh)# get the details of the detected objects
v_boxes, v_labels, v_scores = **get_boxes**(boxes, labels, class_threshold)
# summarize what we found
for i in range(len(v_boxes)):
    print(v_labels[i], v_scores[i])
# draw what we found
**draw_boxes**(photo_filename, v_boxes, v_labels, v_scores)

原象

绘制边界框和类后的图像

代码可从 Github 获得

参考资料:

YOLO V3 论文作者约瑟夫·雷德蒙、阿里·法尔哈迪

https://pjreddie.com/darknet/yolo/

[## experiencor/keras-yolo3

从 https://pjreddie.com/media/files/yolov3.weights. python 中抓取 yolo3 的预训练重量…

github.com](https://github.com/experiencor/keras-yolo3) [## 如何在 Keras 中使用 YOLOv3 执行对象检测

目标检测是计算机视觉中的一项任务,涉及识别一个或多个目标的存在、位置和类型

machinelearningmastery.com](https://machinelearningmastery.com/how-to-perform-object-detection-with-yolov3-in-keras/)

使用 python 通过基于颜色的图像分割进行目标检测

原文:https://towardsdatascience.com/object-detection-via-color-based-image-segmentation-using-python-e9b7c72f0e11?source=collection_archive---------3-----------------------

使用 python 和 OpenCV 绘制轮廓的教程。

Photo by rawpixel.com from Pexels

入门指南

如果你已经安装了 jupyter notebook 或者可以运行 python & OpenCV 的 IDE,只需跳到执行。

工具

我们今天的英雄是蟒蛇。一个免费的开源发行版帮助安装不同的软件包&把它们的混乱整理到隔离的环境中。

关于蟒蛇,维基百科的告诉了我们什么

Anaconda 是用于科学计算(数据科学、机器学习应用、大规模数据处理、预测分析等)的 Python 和 R 编程语言的免费开源发行版。),旨在简化包管理和部署。包版本由包管理系统 conda 管理。Anaconda 发行版有 1200 多万用户使用,它包含 1400 多个适用于 Windows、Linux 和 MacOS 的流行数据科学包。

下面是关于如何下载 Anaconda 的详细教程。
anaconda for Windows&anaconda for Linux。

创造环境

打开 bash (cmd)并键入以下内容

$ conda create -n myEnv python=3

当提示下载软件包时,键入 y (表示是)。

$ source activate myEnv
$ conda install anaconda
$ conda activate myEnv
$ conda install opencv$ jupyter notebook

这将为您在浏览器中打开 jupyter 笔记本。

一些重要术语

轮廓

轮廓可以简单地解释为连接所有连续点(连同边界)的曲线,具有相同的颜色或强度。轮廓是形状分析和物体检测与识别的有用工具。

阈值

对灰度图像应用阈值处理使其成为二值图像。您可以设置一个阈值,低于该阈值的所有值都变成黑色,高于该阈值的所有值都变成白色。

执行

现在,您已经拥有了开始工作所需的一切。
我们将从一个简单的例子开始,向您展示基于颜色的分割是如何工作的。

耐心听我说,直到我们找到好东西。

An Ombre circle — image made using photoshop

如果你想和我一起试试这个,你可以从这里免费得到这张图片。在下面的代码中,我将把这张图片分割成 17 个灰度级。然后用等高线测量每一层的面积。

import cv2
import numpy as npdef viewImage(image):
    cv2.namedWindow('Display', cv2.WINDOW_NORMAL)
    cv2.imshow('Display', image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()def grayscale_17_levels (image):
    high = 255
    while(1):  
        low = high - 15
        col_to_be_changed_low = np.array([low])
        col_to_be_changed_high = np.array([high])
        curr_mask = cv2.inRange(gray, col_to_be_changed_low,col_to_be_changed_high)
        gray[curr_mask > 0] = (high)
        high -= 15
        if(low == 0 ):
            breakimage = cv2.imread('./path/to/image')
viewImage(image)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
grayscale_17_levels(gray)
viewImage(gray)

The same image segmented into 17 gray levels

def get_area_of_each_gray_level(im):## convert image to gray scale (must br done before contouring)
    image = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
    output = []
    high = 255
    first = True
    while(1):low = high - 15
        if(first == False):# making values that are of a greater gray level black 
            ## so it won't get detected  
            to_be_black_again_low = np.array([high])
            to_be_black_again_high = np.array([255])
            curr_mask = cv2.inRange(image, to_be_black_again_low, 
            to_be_black_again_high)
            image[curr_mask > 0] = (0)

        # making values of this gray level white so we can calculate
        # it's area
        ret, threshold = cv2.threshold(image, low, 255, 0)
        contours, hirerchy = cv2.findContours(threshold, 
        cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)if(len(contours) > 0):output.append([cv2.contourArea(contours[0])])
            cv2.drawContours(im, contours, -1, (0,0,255), 3)high -= 15
        first = False
        if(low == 0 ):breakreturn output

在这个函数中,我简单地转换了我想要在这个迭代中轮廓化(突出显示)的灰度范围,将所有在这个范围内的灰度统一为一个灰度。我把除了这个范围之外的所有强度都变成黑色(包括更大和更小的强度)。第二步,我对图像进行阈值处理,这样现在只有我想要轮廓的颜色显示为白色,其他颜色都转换为黑色。这一步在这里变化不大,但必须完成,因为轮廓绘制在黑白(阈值)图像上效果最好。
在应用该步骤(阈值处理)之前,下图将是相同的,除了白色环将是灰色的(第 10 个灰度级的灰度(255–15 * 10))

The 10th segment appear alone to be able to calculate its area

image = cv2.imread('./path/to/image')
print(get_area_of_each_gray_level(image))
viewImage(image)

Contours of the 17 gray levels onto the original image

Array containing the value of the areas

这样我们就获得了每个灰度级的面积。

这真的很重要吗?

在我们继续之前,我想强调一下这个话题的重要性。
我是一名计算机工程专业的学生,我正在从事一个名为用于智能肿瘤检测和识别的机器学习项目
本项目使用基于颜色的图像分割来帮助计算机学习如何检测肿瘤。当处理 MRI 扫描时,程序必须检测所述 MRI 扫描的癌症水平。它通过将扫描分为不同的灰度级来实现,其中最暗的部分充满癌细胞,最接近白色的部分是健康的部分。然后计算肿瘤对每个灰度级的隶属度。有了这些信息,程序就能够识别肿瘤及其阶段。
这个项目基于软计算、模糊逻辑&机器学习,你可以在模糊逻辑上了解更多信息,以及它是如何治愈癌症的。

目标检测

Photo by Lukas from Pexels

你可以从这里的像素上免费获得这张图片。你只需要修剪它。

在这个图像中,我们只想描绘叶子的轮廓。因为这张图像的纹理非常不规则和不均匀,这意味着虽然没有太多的颜色。这幅图像中绿色的强度和亮度都会发生变化。所以,这里最好的办法是把所有这些不同色调的绿色统一成一种色调。这样,当我们应用轮廓时,它将把叶子作为一个整体对象来处理。

注意:这是在没有任何预处理的情况下对图像应用轮廓的结果。我只是想让你看看叶子的不均匀性是如何让 OpenCV 不明白这只是一个对象。

Contouring without pre-processing, 531 contours detected

import cv2
import numpy as npdef viewImage(image):
    cv2.namedWindow('Display', cv2.WINDOW_NORMAL)
    cv2.imshow('Display', image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

首先,你必须知道你的颜色的 HSV 表示,你可以通过把它的 RGB 转换成 HSV 来知道它,就像下面这样。

## getting green HSV color representation
green = np.uint8([[[0, 255, 0 ]]])
green_hsv = cv2.cvtColor(green,cv2.COLOR_BGR2HSV)
print( green_hsv)

Green HSV color

将图像转换为 HSV :使用 HSV 更容易获得一种颜色的完整范围。HSV,H 代表色调,S 代表饱和度,V 代表数值。我们已经知道绿色是[60,255,255]。世界上所有的果岭都位于[45,100,50]到[75,255,255]之间,即[60-15,100,50]到[60+ 15 ,255,255]。15 只是一个近似值。
我们将此范围转换为[75,255, 200 ]或任何其他浅色(第三个值必须相对较大),因为这是颜色的亮度,当我们对图像进行阈值处理时,该值将使该部分为白色。

image = cv2.imread('./path/to/image.jpg')
hsv_img = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
viewImage(hsv_img) ## 1green_low = np.array([45 , 100, 50] )
green_high = np.array([75, 255, 255])
curr_mask = cv2.inRange(hsv_img, green_low, green_high)
hsv_img[curr_mask > 0] = ([75,255,200])
viewImage(hsv_img) ## 2## converting the HSV image to Gray inorder to be able to apply 
## contouring
RGB_again = cv2.cvtColor(hsv_img, cv2.COLOR_HSV2RGB)
gray = cv2.cvtColor(RGB_again, cv2.COLOR_RGB2GRAY)
viewImage(gray) ## 3ret, threshold = cv2.threshold(gray, 90, 255, 0)
viewImage(threshold) ## 4contours, hierarchy =  cv2.findContours(threshold,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(image, contours, -1, (0, 0, 255), 3)
viewImage(image) ## 5

Left: Image just after conversion to HSV (1). Right: Image after applying the mask (color unification)(2)

Left: Image after conversion from HSV to gray(3), Right: Threshold Image, final step(4)

Final contour(5)

由于背景中似乎也有不规则性,我们可以用这种方法得到最大的轮廓,最大的轮廓当然是叶子。
我们可以得到轮廓数组中叶子轮廓的索引,从中我们可以得到叶子的面积和中心。
轮廓有许多其他可以利用的特征,如轮廓周长、凸包、边界矩形等。你可以从这里了解更多。

def findGreatesContour(contours):
    largest_area = 0
    largest_contour_index = -1
    i = 0
    total_contours = len(contours)
    while (i < total_contours ):
        area = cv2.contourArea(contours[i])
        if(area > largest_area):
            largest_area = area
            largest_contour_index = i
        i+=1

    return largest_area, largest_contour_index# to get the center of the contour
cnt = contours[13]
M = cv2.moments(cnt)
cX = int(M["m10"] / M["m00"])
cY = int(M["m01"] / M["m00"])largest_area, largest_contour_index = findGreatesContour(contours)print(largest_area)
print(largest_contour_index)print(len(contours))print(cX)
print(cY)

The result of the print statements

使用 Python 实现不到 10 行代码的对象检测

原文:https://towardsdatascience.com/object-detection-with-less-than-10-lines-of-code-using-python-2d28eebc5b11?source=collection_archive---------0-----------------------

找出图像中的对象

Home Office (Image by LEEROY Agency from Pixabay)

什么要知道图像中有哪些对象?

或者您可能想计算图像中苹果的数量?

在这篇文章中,我将展示如何用不到 10 行代码用 Python 创建自己的对象检测程序。

如果尚未安装以下 python 库,则需要进行安装:

opencv-python
cvlib
matplotlib
tensorflow

以下代码用于导入所需的 python 库,从存储中读取图像,对图像执行对象检测,并显示带有检测到的对象的边界框和标签的图像。

import cv2
import matplotlib.pyplot as plt
import cvlib as cv
from cvlib.object_detection import draw_bboxim = cv2.imread('apple-256261_640.jpg')bbox, label, conf = cv.detect_common_objects(im)output_image = draw_bbox(im, bbox, label, conf)plt.imshow(output_image)
plt.show()

下面是使用上述代码进行对象检测的一些结果。

(Left) Orignal image of an apple on top of some books (Image by Michal Jarmoluk from Pixabay), (Right) Object detection on original image

(Left) Orignal image of apples and bananas (Image by Michal_o79 from Pixabay), (Right) Object detection on original image

(Left) Orignal image of apples, bananas and oranges (Image by Jose Luis Montesino from Pixabay), (Right) Object detection on original image

你已经准备好了你的物体探测程序。

觉得这个帖子有帮助? 在下面留下你的想法作为评论。

希望实现人脸检测。查看我在 上的帖子如何使用 python 在不到 3 分钟的时间内实现人脸检测。

点击这里 阅读我其他关于 AI/机器学习的帖子。

要了解更多关于 cvlib 库的信息,可以访问下面的链接。

[## cvlib

用于 Python 的高级易用开源计算机视觉库。它的开发重点是实现简单的…

www.cvlib.net](https://www.cvlib.net/)

要了解使用该库可以检测到的所有物体,您可以访问下面的链接。

[## arunponnusamy/对象检测-opencv

此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…

github.com](https://github.com/arunponnusamy/object-detection-opencv/blob/master/yolov3.txt)

这里有一些进一步的阅读材料,有助于理解物体探测是如何工作的:

[## 使用深度学习方法的对象检测:端到端的理论观点

物体探测领域最有影响力的论文详解

towardsdatascience.com](/object-detection-using-deep-learning-approaches-an-end-to-end-theoretical-perspective-4ca27eee8a9a) [## 基本对象检测算法的逐步介绍(第 1 部分)

你花了多少时间在一个又脏又乱的房子里寻找丢失的房间钥匙?它发生在我们最好的人身上,而且…

www.analyticsvidhya.com](https://www.analyticsvidhya.com/blog/2018/10/a-step-by-step-introduction-to-the-basic-object-detection-algorithms-part-1/)

YOLO 物体检测|为自动驾驶汽车带来视觉

原文:https://towardsdatascience.com/object-detection-with-yolo-bringing-vision-to-self-driving-cars-980295226830?source=collection_archive---------8-----------------------

解释和使用 YOLO(你只看一次)计算机视觉算法的对象检测

编辑:写完这篇文章后不久,我制作了一个 YouTube 视频(VSauce Parody)来解释 YOLO。请随意查看!

我们都认为我们的愿景是理所当然的。它是数亿年进化的产物,从一片感光细胞进化成一种被称为人眼的复杂光学奇观。

纵观人类的生存历程,我们的生存依赖于我们理解和解释环境的能力。在我们漫游非洲平原的时候,原始人类需要立即识别威胁并做出反应。

即使在今天,这种情况仍然存在。

看到我们生活的世界的能力让克里斯托弗·哥伦布得以环游世界,让莱昂纳多·达·芬奇得以画出蒙娜丽莎,让小蒂米得以骑独轮车。干得好,提米。

自从智人出现以来,人类拥有了最好的视觉。然而,这种情况不会持续太久。因为人类很懒。最初人类认为:

"嘿,走路太累了,让我们驯养这些大的四足动物,然后骑着它们到处走."

然后我们想:

“喂,养这些马太费事了,让我们造这些大四轮车到处跑吧”

现在我们认为:

“嘿,驾驶这些汽车太费力了,让我们建立复杂的人工智能算法来为我们做这件事”

于是自动驾驶汽车诞生了——诞生于我们甚至连开车都懒得做的懒惰。

但是我们到底是如何制造出一辆能够自动驾驶的汽车的呢?仅仅将一台带有摄像头的电脑连接到汽车上是不够的,因为电脑看图像的方式与我们不同。看一看:

对我们来说,我们看到精致的形状和边缘,我们的大脑可以拼凑出一张脸。但是对一台计算机来说,他们看到的是一组多 的数字。

这么长时间以来,人类一直不知道如何教会计算机看东西。请想一想:

如果给你一个装满数字的格子,你会用它做什么?你怎么能看穿这个?

更不用说,我上面用的亚伯拉罕·林肯的照片是黑白的。正常的彩色图像是 RGB(红绿蓝)格式,有 3 个独立的颜色通道,而不是 1 个,这意味着图像不仅仅是一个二维数组,而是一个三维数组。计算机如何识别这些数字中的模式来观察物体?这次,仅仅有一堆 if-else 语句是不够的。

进入神经网络。

神经网络受人脑工作方式的启发,由许多层相互连接的神经元组成,这些神经元共同工作。毕竟,如果我们的大脑能学会看东西,为什么人工大脑不能做到呢?神经网络允许计算机自学识别它希望完成的特定任务所需的复杂模式。在这种情况下,目标是教计算机看到并理解它所处的环境。

教汽车看东西的最好方法是使用一种特殊类型的神经网络,称为卷积神经网络

卷积神经网络(CNN)因其理解空间信息的惊人能力而被用于计算机视觉。这意味着如果我有一张人的照片,即使我旋转它,移动它,挤压和拉伸它,CNN 仍然会识别出它是一个人。

CNN 强大背后的关键是他们使用了一种叫做卷积层的特殊层,从图像中提取特征。初始卷积层识别边缘和拐角等低级特征。随着特征通过更多的卷积层,检测到的特征变得复杂得多。例如,用于检测人的卷积层可能会从边缘到形状到四肢再到人的整体。你可以在这篇 文章 中阅读更多关于卷积神经网络的内容。

The architecture of Convolutional Neural Networks

卷积神经网络本身主要用于图像分类:给定一幅图像,网络将准确地指定给定的类别。例如,使用在皮肤病变数据集上训练的 CNN,它可以学习从给定的图像中诊断不同的皮肤癌。

但是,如果我想知道的不仅仅是图像是否属于某个类,更具体地说,对象的确切位置是什么呢?此外,如果一个图像中有多个不同类别的对象,该怎么办?自动驾驶汽车不能只知道该区域有 5 辆车和 20 个人,它需要知道他们相对于自己的位置,以便安全导航

这就是物体检测的用武之地。通过增强我们的卷积神经网络,我们可以重新利用其惊人的分类属性来定位图像中的类别。我们可以通过一种叫做 YOLO(你只看一次)的算法来做到这一点,这种算法可以进行实时物体检测,非常适合自动驾驶汽车。YOLO 非常快,使用 24 个卷积层,每秒可以处理高达 155 帧。这使得它很容易实现成为一辆自动驾驶汽车。那么它是如何工作的呢?

#YOLO 解释道

正如研究论文所述,YOLO:

单个卷积神经网络同时预测多个边界框和这些框的类概率

YOLO 使用整个图像的特征来预测每个边界框和它们的类别,它同时进行。与人类相似,YOLO 几乎可以立即识别出给定图像中的物体位置和内容。

在运行一幅图像时,YOLO 首先将图像分成一个由 S 组成的网格。

在每个网格单元内,YOLO 将预测预定数量的边界框位置大小置信度得分——本质上是预测一个物体可能存在的类别和潜在位置。如果对象的中心落在网格单元中,则该网格单元的边界框负责准确定位和预测该对象。

YOLO bounding boxes in action

每个边界框将有 5 个预测:x 坐标、y 坐标、宽度、高度和置信度。计算出的置信度得分表明模型认为在边界框内存在一个类的置信度,以及它认为该类适合该框的准确度,该框使用一种称为交集/并集的度量。

****并集上的交集用于对象检测,因为它将地面真实边界框与预测边界框进行比较。通过将重叠面积除以并集面积,我们得到一个函数,即奖励严重重叠惩罚不准确的边界框预测。边界框的目标是最终尽可能精确地将对象限制在图像内,IoU 是确定这一点的一个很好的度量。

****

在图像通过 YOLO 后,它输出 S x S x (B * 5 + C)张量中的预测,其中每个网格单元预测 C 个类别中 B 个边界框的位置和置信度得分。最终,我们得到了很多边界框——其中大部分与无关。****

为了过滤出正确的框,具有满足特定置信度分数的预测类的边界框将被保留。这允许我们隔离图像中的所有相关对象。

本质上,YOLO 定位和分类图像/视频中的对象。像 YOLO 这样的物体检测算法,结合像 Li-Dar 这样的自动驾驶汽车上的许多其他传感器,使我们能够建造完全自动驾驶的汽车,比任何人都更快、更安全、更好。如果你有兴趣深入研究自动驾驶汽车,我强烈推荐你阅读 这篇文章

既然你已经理解了 YOLO 的工作,让我们看看它是如何工作的

奔跑的 YOLO

要在您自己的计算机上试用 YOLO,将我的 GitHub 库克隆到您的计算机上。****

**[## 西吉尔-文/YOLO

用 YOLO 检测物体(你只看一次)。要跑 YOLO,首先,下载链接的预训练重量…

github.com](https://github.com/Sigil-Wen/YOLO)**

然后从这个 链接 下载预先训练好的重量,并将重量移动到名为 yolo-coco 的文件夹中

在您的命令终端中,找到克隆的存储库,导入所需的依赖项和库,并输入以下命令在任何视频上运行 YOLO。

**python yolo_video.py —输入 —输出

— yolo yolo-coco**

Terminal Window

运行该命令后,YOLO 将在输入视频上运行,最终产品将出现在输出路径中。下面是我在 YOLO 看到的一些东西:

https://www.youtube.com/watch?v=AxhBu2uK86I&

这就对了。你理解并运行了一个物体检测算法!令人难以置信的是,我们距离一个由人工智能司机主导的世界有多近。

  • 对跟随我的旅程感兴趣并想要更多这样的内容?跟着我上👇或者订阅我的 YouTube 频道
  • 你可以在 LinkedIn 和我联系,或者在 sigil.w3n@gmail.com 给我发邮件
  • 查看我的 个人网站作品集
  • 看看我对 YOLO 的恶搞吧:https://www.youtube.com/watch?v=AxhBu2uK86I&

使用 PyTorch 移动神经网络的对象检测器 Android 应用程序

原文:https://towardsdatascience.com/object-detector-android-app-using-pytorch-mobile-neural-network-407c419b56cd?source=collection_archive---------12-----------------------

图沙尔·卡普尔😦【https://www.tusharck.com/】T2

在移动设备上运行机器学习代码是下一件大事。 PyTorch ,在最新发布的 PyTorch 1.3 中,增加了 PyTorch Mobile ,用于在 Android 和 iOS 设备上部署机器学习模型。

在这里,我们将研究创建一个 Android 应用程序,用于图像中的对象检测;比如下图的 GIF。

Demo Run of the application

步骤 1:准备模型

在本教程中,我们将使用预先训练好的 ResNet18 模型。ResNet18 是最先进的计算机视觉模型,有 1000 个分类类别。

  1. 安装火炬视觉库
pip install torchvision

2.下载并追踪 ResNet18 模型。

我们跟踪模型,因为我们需要一个可执行的 ScriptModule 来进行实时编译。

import torch
import torchvisionresnet18 = torchvision.models.resnet18(pretrained=True)
resnet18.eval()example_inputs = torch.rand(1, 3, 224, 224)resnet18_traced = torch.jit.trace(resnet18, example_inputs = example_inputs)resnet18_traced.save("resnet18_traced.pt")

注:

  1. 将 resnet18_traced.pt 存储在一个已知的位置,我们将在本教程的后续步骤中用到它。
  2. 在 torch.rand 中,我们采用了 224,224 的尺寸,因为 ResNet18 接受 224*224 的尺寸。

步骤 2:制作 Android 应用程序

  1. 如果你还没有下载并安装 Android Studio,安装时说 YES 下载并安装 SDK
    链接:https://developer.android.com/studio
  2. 打开 Android Studio,点击:
    +开始一个新的 Android Studio 项目
  3. 选择空活动。

4.输入应用程序名称: ObjectDetectorDemo。然后按完成

5.安装 NDK 在安卓内部运行原生代码:

  • 转到工具> SDK 管理器。
  • 点击 SDK 工具
  • 勾选 NDK(并排)旁边的复选框。

6.添加依赖项。

  • build.gradle(模块:app)里面。在依赖项中添加以下内容。
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.0.2'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'**implementation 'org.pytorch:pytorch_android:1.3.0'
    implementation 'org.pytorch:pytorch_android_torchvision:1.3.0'**
}

7.添加一个基本布局来加载图像并显示结果。

  • 转到app>RES>layout>activity _ main . XML并添加下面的代码。
<ImageView
    android:id="@+id/image"
    app:layout_constraintTop_toTopOf="parent"
    android:layout_width="match_parent"
    android:layout_height="400dp"
    android:layout_marginBottom="20dp"
    android:scaleType="fitCenter" />

<TextView
    android:id="@+id/result_text"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="top"
    android:text=""
    android:textSize="20dp"
    android:textStyle="bold"
    android:textAllCaps="true"
    android:textAlignment="center"
    app:layout_constraintTop_toTopOf="@id/button"
    app:layout_constraintBottom_toBottomOf="@+id/image" />

<Button
    android:id="@+id/button"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Load Image"
    app:layout_constraintBottom_toBottomOf="@+id/result_text"
    app:layout_constraintTop_toTopOf="@+id/detect" />

<Button
    android:id="@+id/detect"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Detect"
    android:layout_marginBottom="50dp"
    app:layout_constraintBottom_toBottomOf="parent" />

你的布局应该如下图所示。

8.我们需要设置权限来读取设备上存储的图像。

  • 转到app>manifest>androidmanifest . XML并将下面的代码添加到 manifest 标签内。
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
  • 获取应用程序加载的权限(只有在您授予权限后才会询问)。

—进入主活动 java。将下面的代码添加到 onCreate() 方法中。

if (Build.VERSION.*SDK_INT* >= Build.VERSION_CODES.*M*) {
    requestPermissions(new String[]  {android.Manifest.permission.*READ_EXTERNAL_STORAGE*}, 1);
}

9.复制模型。
现在我们复制使用 python 脚本创建的模型。

  • 文件浏览器/查找器中打开您的应用程序。
  • 转到 app > src > main。
  • 创建一个名为资产的文件夹
  • 将您的模型复制到该文件夹中。
  • 当你打开你的 Android 工作室时,你会看到如下图所示。(如果没有,右击应用程序文件夹并点击同步应用程序)。

10.我们需要列出模型的输出类。

  • 转到 app > java。
  • 在第一个文件夹中创建一个新的 Java 类名 ModelClasses
  • 将类的列表定义为(完整的列表有 1000 个类,所以可以在这里复制所有的 check Json 或 check Git 。完整列表和下面列表中的副本):
public static String[] *MODEL_CLASSES* = new String[]{
        "tench, Tinca tinca",
        "goldfish, Carassius auratus"
        .
        .
        .
}

11.主活动 Java,这里将定义按钮动作,读取图像并调用 PyTorch 模型。参见代码中的注释以获得解释。

12.现在是测试应用程序的时候了。有两种方法:

  • 运行在仿真器上【点击此处】。
  • 使用安卓设备。(为此您需要启用 USB 调试 [ 点击此处)。
  • 运行应用程序后,它应该看起来像页面顶部的 GIF。

链接到 Git 资源库:https://github . com/tusharck/Object-Detector-Android-App-Using-py torch-Mobile-Neural-Network

免责声明:

  1. “Android”名称、Android 徽标、“Google Play”品牌和其他 Google 商标是 Google LLC 的财产,不属于 Android 开源项目的资产。
  2. PyTorch、PyTorch、PyTorch 徽标以及与 PyTorch 或网站相关的所有其他商标、服务标志、图形和徽标是 PyTorch 或 PyTorch 许可方的商标或注册商标。

面向对象的机器学习流水线与熊猫和考拉数据框架的 mlflow

原文:https://towardsdatascience.com/object-oriented-machine-learning-pipeline-with-mlflow-for-pandas-and-koalas-dataframes-ef8517d39a12?source=collection_archive---------12-----------------------

使用熊猫、考拉、scikit-learn 和 mlflow 在 Python 中开发支持 Spark 的机器学习管道的端到端流程

在文章 Python 数据预处理使用熊猫数据帧、Spark 数据帧和考拉数据帧中,我使用了一个公共数据集来评估和比较机器学习的典型数据预处理步骤中熊猫、 Spark 和考拉数据帧的基本功能。考拉的主要优势是支持类似 Spark 上熊猫的易用 API。

在本文中,我使用一个更具挑战性的数据集,Kaggle 竞赛的面试出席问题来演示使用熊猫、考拉、 scikit-learn 和 mlflow 用 Python 为熊猫和考拉数据帧开发面向对象的机器学习管道的端到端过程。这是通过以下方式实现的:

  • 使用 Pandas DataFrame 和 scikit-learn pipeline API 开发数据预处理管道
  • 结合 scikit-learn pipeline API 和 Koalas DataFrame 为 Spark 开发数据预处理管道
  • 结合 scikit-learn 和 mlflow 开发机器学习流水线

端到端开发流程基于数据挖掘的跨行业标准流程。如下图所示,它包括六个主要阶段:

  • 商业理解
  • 数据理解
  • 数据准备
  • 建模
  • 估价
  • 部署

图 1: CRISP-DM 流程图(参考维基百科中的来源)

为方便讨论,假设在 Mac 等本地机器上安装了以下 Python 库:

  • Anaconda (conda 4.7.10)和 Python 3.6、Numpy、Pandas、Matplotlib 和 Scikit-Learn
  • pyspark 2.4.4
  • 考拉
  • mlflow

使用 Python 3.6 的原因是当前版本的 mlflow 的某些功能(如部署)无法与 Python 3.7 兼容。

1.商业理解

第一阶段是业务理解。这个阶段的关键点是理解要解决的业务问题。作为一个例子,下面是对 Kaggle 面试出勤率问题的简要描述:

给定招聘人员在安排与候选人的面试时提出的一组问题,如何使用候选人对这些问题的回答来预测预期出席者是否会参加安排的面试(是、否或不确定)。

2.数据理解

一旦理解了业务问题,下一步就是确定在哪里(即数据源)以及我们应该如何收集数据,从这些数据中可以构建问题的机器学习解决方案。

研究人员在 2014 年 9 月至 2017 年 1 月的两年多时间里,从印度的招聘行业收集了 Kaggle 面试出勤问题的数据集。

这个数据集是用标签收集的(观察到的出勤的列保存标签),因此它适用于监督机器学习。

以下代码为本文中的所有源代码导入必要的 Python 库,并将数据集加载到考拉数据帧中,并显示数据帧的前五行,如上表所示。

import numpy as np
import pandas as pd
import databricks.koalas as ks
import matplotlib.pyplot as plt
import matplotlib as mpl
from   datetime import datetime
import osfrom sklearn.base import BaseEstimator, TransformerMixin
from sklearn.pipeline import Pipeline
from sklearn.externals import joblibimport mlflow
import mlflow.sklearnfrom sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCVfrom sklearn.metrics import make_scorer
from sklearn.metrics import accuracy_score
from sklearn.metrics import f1_score
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score%matplotlib inlineks_df = ks.read_csv('Interview_Attendance_Data.csv')
ks_df.head()

3.数据准备

数据准备的主要目标是清理收集的原始数据集并将其转换为适当的格式,以便转换后的数据可以被目标机器学习模型有效地使用。

在面试考勤原始数据集中, Name(Cand ID) 列包含候选人的唯一标识符,该标识符没有太大的预测能力,因此可以删除。此外,所有列(即对于考拉数据帧从 _c22_c26 的列,或者对于熊猫数据帧从未命名:22未命名:26 的列)都没有数据,因此也可以安全地删除。

除了采访日期,数据集中的所有其他列都有分类(文本)值。为了使用机器学习来解决问题,必须将这些分类值转换为数值,因为机器学习模型只能使用数值数据。

面试的日期一栏应拆分为日、月、年,以提高预测能力,因为与作为整体的一串日期相比,个别日、月、年的信息往往与季节性工作更密切相关。

技能组合的性质候选人籍贯列有大量唯一条目。这些将在一键编码后引入大量新的衍生功能。在数据集不够大的情况下,太多的特征会导致维数灾难问题。为了缓解这一问题,这两列的值被重新划分到更少的存储桶中。

上述数据预处理/转换可以概括为以下步骤:

  • 桶装技能组合
  • 存储候选人本地位置
  • 解析面试日期
  • 将分类值改为大写并删除不太有用的特征
  • 一次性编码分类值

这些步骤是通过将熊猫和考拉数据帧与 scikit-learn 管道 API(即 BaseEstimatorTransformerMixin管道)相结合,为熊猫和考拉数据帧开发面向对象的数据预处理管道来实现的。

3.1 转换列值

几个数据预处理步骤共享一个转换数据帧中特定列的值的通用操作。但是,如考拉系列所述,考拉系列不支持一些常见的熊猫数据帧和系列索引机制,如df . iloc【0】。因此,没有简单的方法来遍历和更改考拉数据帧中的列值。

另一个困难是,考拉不允许从头构建一个新的考拉系列对象,然后将它作为一个新列添加到现有的考拉数据框架中。它只允许从考拉数据帧的现有列构建新的考拉系列对象。

通过定义一个全局函数来调用考拉系列对象的 apply ()方法,可以避免上述困难。

def transformColumn(column_values, func, func_type): def transform_column(column_element) -> func_type:
        return func(column_element)

    cvalues = column_values
    cvalues = cvalues.apply(transform_column)
    return cvalues

3.2 铲斗技能组合

为了缓解维数灾难问题, BucketSkillset 转换类的转换()方法通过将出现次数少于 9 次的值更改为 Others 的一个相同字符串值,将 Skillset 列的唯一值划分为更小数量的桶。

class BucketSkillset(BaseEstimator, TransformerMixin):
    def __init__(self):
        self.skillset = ['JAVA/J2EE/Struts/Hibernate', 'Fresher', 'Accounting Operations', 'CDD KYC', 'Routine', 'Oracle', 
          'JAVA/SPRING/HIBERNATE/JSF', 'Java J2EE', 'SAS', 'Oracle Plsql', 'Java Developer', 
          'Lending and Liabilities', 'Banking Operations', 'Java', 'Core Java', 'Java J2ee', 'T-24 developer', 
          'Senior software engineer-Mednet', 'ALS Testing', 'SCCM', 'COTS Developer', 'Analytical R & D', 
          'Sr Automation Testing', 'Regulatory', 'Hadoop', 'testing', 'Java', 'ETL', 'Publishing']       

    def fit(self, X, y=None):
        return self

    def transform(self, X, y=None):  

        func = lambda x: x if x in self.skillset else 'Others'

        X1 = X.copy()
        cname = 'Nature of Skillset'
        cvalue = X1[cname]

        if type(X1) == ks.DataFrame:  
            cvalue = transformColumn(cvalue, func, str)
            X1[cname] = cvalue
        elif type(X1) == pd.DataFrame:
            X2 = map(func, cvalue)
            X1[cname] = pd.Series(X2)
        else:
            print('BucketSkillset: unsupported dataframe: {}'.format(type(X1)))
            pass

        return X1

3.3 存储候选人本地位置

与 bucketing skillset 类似,为了缓解维数灾难问题,bucket locationtransformer 类的 transform ()方法通过将那些出现次数少于 12 次的值更改为 Others 的一个相同值,将候选本地位置列的唯一值划分为更小数量的桶。

class BucketLocation(BaseEstimator, TransformerMixin):
    def __init__(self):
        self.candidate_locations = ['Chennai', 'Hyderabad', 'Bangalore', 'Gurgaon', 'Cuttack', 'Cochin', 
                          'Pune', 'Coimbatore', 'Allahabad', 'Noida', 'Visakapatinam', 'Nagercoil',
                          'Trivandrum', 'Kolkata', 'Trichy', 'Vellore']

    def fit(self, X, y=None):
        return self

    def transform(self, X, y=None):            
        X1 = X.copy()

        func = lambda x: x if x in self.candidate_locations else 'Others'

        cname = 'Candidate Native location'
        cvalue = X1[cname]
        if type(X1) == ks.DataFrame: 
            cvalue = transformColumn(cvalue, func, str)
            X1[cname] = cvalue
        elif type(X1) == pd.DataFrame:
            X2 = map(func, cvalue)
            X1[cname] = pd.Series(X2)
        else:
            print('BucketLocation: unsupported dataframe: {}'.format(type(X1)))
            pass

        return X1

3.4 解析面试日期

采访日期一栏的值很乱,因为使用了各种格式。例如,不仅使用不同的分隔符来分隔日、月和年,而且还遵循日、月和年的不同顺序。这由 ParseInterviewDate 转换器类的 _ parseDate ()和 transform_date ()方法来处理。 transform ()方法的总体功能是将采访日期字符串分成各个日、月和年的值。

class ParseInterviewDate(BaseEstimator, TransformerMixin):
    def __init__(self):
        pass   
    def __parseDate(self, string, delimit):
        try:
            if ('&' in string):
                subs = tuple(string.split('&'))
                string = subs[0]
        except:
            print ('TypeError: {}'.format(string))
            return None

        string = string.strip()

        try:
            d = datetime.strptime(string, '%d{0}%m{0}%Y'.format(delimit))
        except:
            try:
                d = datetime.strptime(string, '%d{0}%m{0}%y'.format(delimit))
            except:
                try:
                     d = datetime.strptime(string, '%d{0}%b{0}%Y'.format(delimit))
                except:
                    try:
                         d = datetime.strptime(string, '%d{0}%b{0}%y'.format(delimit))
                    except:
                        try:
                            d = datetime.strptime(string, '%b{0}%d{0}%Y'.format(delimit))
                        except:
                            try:
                                d = datetime.strptime(string, '%b{0}%d{0}%y'.format(delimit))
                            except:
                                d = None
        return d

    def fit(self, X, y=None):
        return self

    def transform(self, X, y=None):

        def transform_date(ditem):
            if (isinstance(ditem, str) and len(ditem) > 0):
                if ('.' in ditem):
                    d = self.__parseDate(ditem, '.')
                elif ('/' in ditem):
                    d = self.__parseDate(ditem, '/')
                elif ('-' in ditem):
                    d = self.__parseDate(ditem, '-')
                elif (' ' in ditem):
                    d = self.__parseDate(ditem, ' ')
                else:
                    d = None

                if (d is None):
                    return 0, 0, 0
                else:
                    return d.day, d.month, d.year

        def get_day(column_element) -> int:
            try:
                day, month, year = transform_date(column_element)
                return int(day)
            except:
                return 0

        def get_month(column_element) -> int:
            try:
                day, month, year = transform_date(column_element)
                return int(month)
            except:
                return 0

        def get_year(column_element) -> int:
            try:
                day, month, year = transform_date(column_element)
                return int(year)
            except:
                return 0

        def pandas_transform_date(X1):
            days = []
            months = []
            years = []
            ditems = X1['Date of Interview'].values
            for ditem in ditems:
                if (isinstance(ditem, str) and len(ditem) > 0):
                    if ('.' in ditem):
                        d = self.__parseDate(ditem, '.')
                    elif ('/' in ditem):
                        d = self.__parseDate(ditem, '/')
                    elif ('-' in ditem):
                        d = self.__parseDate(ditem, '-')
                    elif (' ' in ditem):
                        d = self.__parseDate(ditem, ' ')
                    else:
                        d = None

                    if (d is None):
                        # print("{}, invalid format of interview date!".format(ditem))
                        days.append(0) # 0 - NaN
                        months.append(0)
                        years.append(0)
                    else:
                        days.append(d.day) 
                        months.append(d.month)
                        years.append(d.year)
                else:
                    days.append(0)
                    months.append(0)
                    years.append(0)

            X1['Year'] = years
            X1['Month'] = months
            X1['Day'] = days

            return X1

        X1 = X.copy()

        if type(X1) == ks.DataFrame: 
            X1['Year'] = X1['Date of Interview']
            X1['Month'] = X1['Date of Interview']
            X1['Day'] = X1['Date of Interview']

            func_map = {'Year' : get_year, 'Month' : get_month, 'Day' : get_day}
            for cname in func_map:
                cvalue = X1[cname]
                cvalue = cvalue.apply(func_map[cname])
                X1[cname] = cvalue
        elif type(X1) == pd.DataFrame:
            X1 = pandas_transform_date(X1)
        else:
            print('ParseInterviewDate: unsupported dataframe: {}'.format(type(X1)))
            pass 

        return X1

3.5 将分类值改为大写,并删除不太有用的特性

features super casetransformer 类的 transform ()方法是将分类特性的值改为大写,同时丢弃不太有用的特性。

class FeaturesUppercase(BaseEstimator, TransformerMixin):
    def __init__(self, feature_names, drop_feature_names):
        self.feature_names      = feature_names
        self.drop_feature_names = drop_feature_names

    def fit(self, X, y=None):
        return self

    def transform(self, X, y=None):

        func = lambda x: x.strip().upper()

        X1 = X.copy()

        for fname in self.feature_names:
            values = X1[fname]
            values = values.fillna('NaN')
            if type(X1) == ks.DataFrame: 
                values = transformColumn(values, func, str)
            elif type(X1) == pd.DataFrame:
                values = map(lambda x: x.strip().upper(), values)
            else:
                print('FeaturesUppercase: unsupported dataframe: {}'.format(type(X1)))   
            X1[fname] = values

        # drop less important features
        X1 = X1.drop(self.drop_feature_names, axis=1)

        return X1

3.6 一次性编码分类值

onehotencodatatransformer 类的 transform ()方法调用 DataFrame 的 get_dummies ()方法对分类值的值进行一次性编码。

class OneHotEncodeData(BaseEstimator, TransformerMixin):
    def __init__(self):
        self.one_hot_feature_names = ['Client name', 
                        'Industry', 
                        'Location', 
                        'Position to be closed', 
                        'Nature of Skillset',
                        'Interview Type', 
                        'Gender', 
                        'Candidate Current Location',
                        'Candidate Job Location', 
                        'Interview Venue', 
                        'Candidate Native location',
                        'Have you obtained the necessary permission to start at the required time',
                        'Hope there will be no unscheduled meetings',
                        'Can I Call you three hours before the interview and follow up on your attendance for the interview',
                        'Can I have an alternative number/ desk number. I assure you that I will not trouble you too much',
                        'Have you taken a printout of your updated resume. Have you read the JD and understood the same',
                        'Are you clear with the venue details and the landmark.',
                        'Has the call letter been shared', 
                        'Marital Status']
        self.label_encoders   = None
        self.one_hot_encoders = None

    def fit(self, X, y=None):       
        return self

    def transform(self, X, y=None):  
        X1 = X.copy()
        if type(X1) == ks.DataFrame: 
            X1 = ks.get_dummies(X1)
        elif type(X1) == pd.DataFrame:
            X1 = pd.get_dummies(X1)
        else:
            print('OneHotEncodeData: unsupported dataframe: {}'.format(type(X1)))
            pass

        return X1

3.7 将变压器合并到管道中

PredictInterview 类的 PreprocessData ()方法中,所有的数据预处理转换器被组合成一个 scikit-learn 管道(详见第 4.3 节)。一旦调用管道对象的 fit_transform ()方法,这些变形器的 fit ()和 transform ()方法将被依次执行。

self.pipeline = Pipeline([
            ('bucket_skillset', BucketSkillset()),
            ('bucket_location', BucketLocation()),
            ('parse_interview_date', ParseInterviewDate()),
            ('features_to_uppercase', FeaturesUppercase(self.feature_names, self.drop_feature_names)),
            ('one_hot_encoder', self.oneHotEncoder)
        ])

4.建模

准备好数据集后,下一步是建模。建模的主要目标包括:

  • 识别机器学习模型
  • 训练机器学习模型
  • 调整机器学习模型的超参数

4.1 识别机器学习模型

有三种主要的高级类型的机器学习和深度学习算法/模型:

  • 监督机器学习和深度学习
  • 无监督机器学习和深度学习
  • 强化学习

有监督的机器学习和深度学习可以分为回归和分类等子类型。每个子类型包括各种机器学习和深度学习算法/模型。例如,监督机器学习分类模型包括决策树分类器、随机森林分类器、GBM 分类器等。

一般来说,给定一个业务问题,有许多不同类型的模型可以用作可能的解决方案。需要对这些不同的模型进行比较,以确定最有希望的模型作为目标业务问题的解决方案。因此,模型识别不能孤立地进行。它依赖于模型训练和模型性能度量的评估/比较。

在本文中,我们简单地选择 sci kit-learnRandomForestClassifier模型进行演示。

4.2 训练模型和调整超参数

一旦模型(例如, RandomForestClassifier )被识别,通常有多个超参数要被调整。超参数是在模型训练可以开始之前需要设置的参数,并且这种超参数值在模型训练期间不会改变。例如,随机森林分类器具有多个超参数,例如估计器的数量最大深度等。

sciket-learnGridSearchCV是一个流行的库,通过多次自动执行模型的实例来搜索给定模型的超参数的最佳组合。每次执行对应于所选超参数值的唯一组合。 GridSearch 类将使用这个库来寻找估计器的数量和最大深度的最佳组合:

class GridSearch(object):
    def __init__(self, cv=10):
        self.grid_param = [
            {'n_estimators': range(68,69), # range(60, 70) 
             'max_depth'   : range(8,9)}   # range(5, 10)} 
        ]
        self.cv = cv
        self.scoring_function = make_scorer(f1_score, greater_is_better=True) 
        self.gridSearch = None

    def fit(self, X, y):
        rfc = RandomForestClassifier()
        self.gridSearchCV = GridSearchCV(rfc, self.grid_param, cv=self.cv, scoring=self.scoring_function)
        self.gridSearchCV.fit(X, y)
        return self.gridSearchCV.best_estimator_

4.3 跟踪模型超参数和性能指标

mlflow 的一个设计功能是跟踪和比较不同模型执行的超参数和性能指标。

PredictInterview 类的 mlFlow ()的方法是训练一个模型,使用训练好的模型预测结果,获得各种模型性能指标,然后调用 mlflow API 来跟踪超参数和性能指标,同时将训练好的模型记录到一个文件中,供以后使用,如部署。

def mlFlow(self):
        np.random.seed(40)
        with mlflow.start_run():
            self.loadData()
            self.PreprocessData()
            self.trainModel()
            self.predictClasses()
            accuracy_score, f1_score, rmse_score, mae_score, r2_score = self.getModelMetrics() best_params = self.gridSearch.gridSearchCV.best_params_ mlflow.log_param("n_estimators", best_params["n_estimators"])
            mlflow.log_param("max_depth", best_params["max_depth"])            
            mlflow.log_metric("rmse", rmse_score)
            mlflow.log_metric("r2", r2_score)
            mlflow.log_metric("mae", mae_score)
            mlflow.log_metric("accuracy", accuracy_score)
            mlflow.log_metric("f1", f1_score) mlflow.sklearn.log_model(self.rfc, "random_forest_model")

下面的 PredictInterview 类的 Jupyter 记事本和本文中的所有其他源代码都可以在 Github [6]中找到。

class PredictInterview(object):
    def __init__(self, use_koalas=True):
        self.use_koalas = use_koalas
        self.dataset_file_name = 'Interview_Attendance_Data.csv'
        self.feature_names = ['Date of Interview', 
                       'Client name', 
                       'Industry', 
                       'Location', 
                       'Position to be closed', 
                       'Nature of Skillset',
                       'Interview Type', 
                       'Gender', 
                       'Candidate Current Location',
                       'Candidate Job Location', 
                       'Interview Venue', 
                       'Candidate Native location',
                       'Have you obtained the necessary permission to start at the required time',
                       'Hope there will be no unscheduled meetings',
                       'Can I Call you three hours before the interview and follow up on your attendance for the interview',
                       'Can I have an alternative number/ desk number. I assure you that I will not trouble you too much',
                       'Have you taken a printout of your updated resume. Have you read the JD and understood the same',
                       'Are you clear with the venue details and the landmark.',
                       'Has the call letter been shared', 'Marital Status']

        if self.use_koalas:
            self.drop_feature_names = [
                'Name(Cand ID)',
                'Date of Interview', 
                '_c22',
                '_c23',
                '_c24',
                '_c25',
                '_c26']
        else: # use Pandas
            self.drop_feature_names = [
                'Unnamed: 22',
                'Unnamed: 23',
                'Unnamed: 24',
                'Unnamed: 25',
                'Unnamed: 26']

        self.dataset = None
        self.rfc     = None
        self.gridSearch = None
        self.X_train = None
        self.y_train = None
        self.X_test  = None
        self.y_test  = None
        self.y_pred  = None
        self.X_clean = None
        self.y_clean = None
        self.X_train_encoded = None
        self.X_test_encoded  = None
        self.y_train_encoded = None
        self.accuracy_score  = None 
        self.f1_score        = None
        self.oneHotEncoder   = None
        self.X_test_name_ids = None
        self.pipeline = None

    def loadData(self, path=None):
        if (path != None):
            path = os.path.join(path, self.dataset_file_name)
        else:
            path = self.dataset_file_name

        if self.use_koalas:
            dataset = ks.read_csv(path)  
        else:
            dataset = pd.read_csv(path)

        # shuffle data 
        self.dataset = dataset.sample(frac=1.0) 

        return self.dataset     

    def PreprocessData(self):
        y = self.dataset['Observed Attendance']      # extract labels y
        if self.use_koalas:
            X = self.dataset.drop('Observed Attendance') # extract features X
        else:
            X = self.dataset.drop(['Observed Attendance'], axis=1) 

        self.oneHotEncoder = OneHotEncodeData()

        self.pipeline = Pipeline([
            ('bucket_skillset', BucketSkillset()),
            ('bucket_location', BucketLocation()),
            ('parse_interview_date', ParseInterviewDate()),
            ('features_to_uppercase', FeaturesUppercase(self.feature_names, self.drop_feature_names)),
            ('one_hot_encoder', self.oneHotEncoder)
        ])

        X_1hot = self.pipeline.fit_transform(X)

        # fill up missing labels and then change labels to uppercase
        y = y.fillna('NaN')

        if self.use_koalas:
            func = lambda x: x.strip().upper()
            y_uppercase = transformColumn(y, func, str) 
        else:
            y_uppercase = map(lambda x: x.strip().upper(), y.values)
            y_uppercase = pd.Series(y_uppercase)

        # separate labeled records from unlabeled records
        self.X_train_encoded = X_1hot[y_uppercase != 'NAN']
        self.X_test_encoded  = X_1hot[y_uppercase == 'NAN']

        # save Names/ID for reporting later one
        self.X_test_name_ids = self.dataset['Name(Cand ID)'].loc[y_uppercase == 'NAN']

        y_train = y_uppercase.loc[y_uppercase != 'NAN']

        # encode labels as follows: 0 - NO, 1 - YES, NAN - NAN
        if self.use_koalas:
            func = lambda x: 1 if x == 'YES' else 0
            y = transformColumn(y_train, func, int)
        else:
            y = map(lambda x: 1 if x == 'YES' else 0, y_train)
            y = pd.Series(y)

        self.y_train_encoded = y

        self.X_clean = X_1hot
        self.y_clean = y_uppercase

        return None

    def __splitData(self):
        if self.use_koalas:
            X_train_encoded = self.X_train_encoded.to_numpy()
            y_train_encoded = self.y_train_encoded.to_numpy()
        else:
            X_train_encoded = self.X_train_encoded.values
            y_train_encoded = self.y_train_encoded.values

        self.X_train, self.X_test, self.y_train, self.y_test = train_test_split(X_train_encoded, 
                                                                                y_train_encoded, 
                                                                                test_size = 0.25, random_state = 0)
        return (self.X_train, self.X_test, self.y_train, self.y_test)

    def trainModel(self):
        X_train, X_test, y_train, y_test = self.__splitData()
        self.gridSearch = GridSearch()
        self.rfc = self.gridSearch.fit(X_train, y_train)
        return self.rfc

    def predictClasses(self):
        if (self.rfc is None):
            print("No trained model available, please train a model first!")
            return None

        self.y_pred = self.rfc.predict(self.X_test)
        return self.y_pred

    def getModelMetrics(self):
        if (self.y_test is None or self.y_pred is None):
            print('Failed to get model performance metrics because y_test is null or y_pred is null!')
            return None

        self.accuracy_score = accuracy_score(self.y_test, self.y_pred)
        self.f1_score = f1_score(self.y_test, self.y_pred)

        pred = self.predictAttendanceProbability(self.X_test)[:, 1]
        actual = self.y_test.astype(float)

        self.rmse_score = np.sqrt(mean_squared_error(actual, pred))
        self.mae_score = mean_absolute_error(actual, pred)
        self.r2_score = r2_score(actual, pred)

        return (self.accuracy_score, self.f1_score, self.rmse_score, self.mae_score, self.r2_score)

    def predictNullAttendanceProbability(self):
        y_pred = self.rfc.predict_proba(self.X_test_encoded.to_numpy())
        return y_pred

    def predictNullAttendanceClasses(self):
        y_pred = self.rfc.predict(self.X_test_encoded.to_numpy())
        return y_pred

    def predictAttendanceProbability(self, X):
        y_pred = self.rfc.predict_proba(X)
        return y_pred

    def predictAttendanceClass(self, X):
        y_pred = self.rfc.predict(X)
        return y_pred

    def mlFlow(self):
        np.random.seed(40)
        with mlflow.start_run():
            self.loadData()
            self.PreprocessData()
            self.trainModel()
            self.predictClasses()
            accuracy_score, f1_score, rmse_score, mae_score, r2_score = self.getModelMetrics() best_params = self.gridSearch.gridSearchCV.best_params_ mlflow.log_param("n_estimators", best_params["n_estimators"])
            mlflow.log_param("max_depth", best_params["max_depth"])            
            mlflow.log_metric("rmse", rmse_score)
            mlflow.log_metric("r2", r2_score)
            mlflow.log_metric("mae", mae_score)
            mlflow.log_metric("accuracy", accuracy_score)
            mlflow.log_metric("f1", f1_score) mlflow.sklearn.log_model(self.rfc, "random_forest_model")

下面的代码显示了如何实例化 PredictInterview 类的一个对象,然后调用它的 mlFlow ()方法。

predictInterview = PredictInterview(use_koalas=True)
predictInterview.mlFlow()

4.4 比较模型超参数和性能指标

一旦在 mlflow 中跟踪了模型的超参数和性能指标,我们可以使用终端或 Jupyter 笔记本启动如下的 mlflow UI(用户界面),查看模型执行的历史记录:

!mlflow ui # for jupyter notebook

假设 mlflow UI 在本地机器上启动,以下 IP 地址和端口号可用于在 Web 浏览器中查看结果:

http://127.0.0.1:5000

下图是 mlflow UI 中模型执行历史的快照:

图 2: 在 mlflow UI 中跟踪超参数和指标

5.估价

一旦机器学习模型被训练成具有预期的性能,下一步就是在受控的接近真实的设置中评估模型的预测结果,以获得模型有效、可靠并且满足部署的业务需求的信心。

例如,对于 Kaggle 面试出勤项目,一种可能的评估方法是使用 mlflow 将模型部署为 Web 服务,然后开发客户端程序来调用模型 Web 服务,以在经过数据准备后获得测试数据集的预测结果。然后,这些预测结果可用于生成报告(例如,表格或 csv 文件),供招聘行业领域专家审阅。

出于演示目的,下面的代码使用阈值为 0.5 的预测结果来为“观察到的出席率”列中缺少值的每个候选人生成概率和预测,并将结果形成为 Pandas 数据帧。

pred_probs   = predictInterview.predictNullAttendanceProbability()
pred_classes = predictInterview.predictNullAttendanceClasses()x = predictInterview.X_test_name_ids.to_numpy() 
z = zip(x, pred_probs, pred_classes)
answers = ('no', 'yes')result = [[x1, p1[1], answers[c]] for x1, p1, c in z]
result_df = pd.DataFrame(np.array(result), columns=['Names/ID', 'Probability', 'Yes/No'])
result_df.to_csv('interview_prediction.csv')
result_df.head(15)

以下是数据帧的前 15 行:

6.部署

一旦模型评估得出模型可以部署的结论,最后一步就是将评估后的模型部署到生产系统中。如商业数据科学一书中所述,部署的细节取决于目标生产系统。

以 Kaggle 面试考勤项目为例,一种可能的场景是将模型部署为服务器上的 Web 服务,可以被目标生产系统中的其他组件调用,以获得预测结果来辅助工作面试安排。在目标生产系统的开发基于不同于建模语言(例如,Python)的编程语言(例如,Java)的更复杂的情况下,模型有可能需要作为生产系统的组件在目标编程语言中重新实现。

6.1 将模型部署为 Web 服务

如前所述,在 mlflow 中跟踪模型执行的过程中,一个经过训练的模型已经被记录到一个文件中。以下屏幕快照显示了已记录模型的信息:

图 3:ml flow UI 中的测井训练模型

与 mlflow 教程类似,下面的代码将使用 mlflow 内置功能来启动一个日志模型作为 Web 服务:

mlflow models serve -m /Users/xyz/machine-learning-spark/mlruns/0/258301f3ac5f42fb99e885968ff17c2a/artifacts/random_forest_model -p 1234

6.2 调用模型 Web 服务来预测结果

为简单起见,在本节中,假设 test_df 是只有一行测试数据的 Pandas 数据帧(面试出席特征向量):

test_df.head() 

以下代码可用于将测试数据行发送到模型 Web 服务,以获得预测的面试出席率(1 -是,0 -否):

import requests
import jsonheaders = {'Content-Type': 'application/json',
           'Format': 'pandas-split'}url = '[http://127.0.0.1:1234/invocations'](http://127.0.0.1:1234/invocations')headers_json_str = json.dumps(headers)
headers_json_obj = json.loads(headers_json_str)
data_json_obj = test_df.to_json(orient='split')response = requests.post(url, data=data_json_obj, headers = headers_json_obj)response.text

摘要

在本文中,我使用了一个接近真实的具有挑战性的数据集,即 Kaggle 竞赛的面试出勤问题,通过将熊猫和考拉数据帧与 scikit-learn pipeline API 和 mlflow 相结合,演示了一个用 Python 为熊猫和考拉数据帧开发面向对象的机器学习管道的端到端过程。这个端到端的开发过程遵循数据挖掘的跨行业标准过程。为标准流程的每个阶段(除了第一阶段)提供了简短的描述和示例实现代码。Github [6]中提供了一个 Jupyter 笔记本和相应的 Python 源代码文件。

参考

[1]教务长,f .,福塞特,T. (2013)。业务数据科学,奥赖利,2013 年 7 月

[2]杰龙,A. (2017)。使用 Scikit-Learn & TensorFlow 进行动手机器学习,奥赖利,2017 年 3 月

[3] mlflow 1.3.0 教程:https://www.mlflow.org/docs/latest/tutorial.html

[4]面试考勤问题:https://www . ka ggle . com/vishnusraghavan/The-Interview-Attendance-Problem/data

[5]张,于(2019)。使用熊猫数据帧、Spark 数据帧和考拉数据帧的 Python 数据预处理:https://towards Data science . com/python-Data-预处理-使用-熊猫-数据帧-Spark-数据帧-和-考拉-数据帧-e4c 42258 a8f

[6]张,于(2019)。Github 中的 Jupyter 笔记本

披露声明:2019 首创一。观点是作者个人的观点。除非本帖中另有说明,否则 Capital One 不隶属于所提及的任何公司,也不被这些公司认可。使用或展示的所有商标和其他知识产权是其各自所有者的财产。

面向对象编程和测试驱动开发的魔力

原文:https://towardsdatascience.com/object-oriented-programming-and-the-magic-of-test-driven-development-d377acae85fa?source=collection_archive---------14-----------------------

[Python](https://www.python.org/)是数据科学中最常用的编程语言之一。对于一些人来说,这是关于语言的灵活性和可读性,对于其他人来说,这是关于它相对较低的复杂性,对于大多数人来说,这是关于它的多面性。

我们称[Python](https://www.python.org/)多面语言,因为它允许你以四种不同的风格编码:功能性命令性面向对象过程性。这些编码风格在形式上被称为编程范例,代表了一种基于语言特性对语言进行分类的方法。

自从我开始了我的数据科学之旅,我就一直想更深入地研究 【面向对象编程(OOP) ,所以我利用本周的博客帖子全力以赴。

什么是面向对象编程(OOP)?

正如我前面说过的,OOP 是一种建立在对象概念之上的编程范式。在计算机科学中,object 这个词可以指代不同的概念,但在最基本的层面上,它是由标识符引用的内存中的值。

在面向对象的上下文中,对象是状态(变量)和行为(方法)的组合。面向对象方法的目标是通过四原则 : 封装抽象继承多态来创建更易于维护的可重用软件。

我们还可以在面向对象语言内部进一步区分,比如基于类的基于原型的

在基于类的 OOP 中,对象是一个类的实例。类是应该如何定义的蓝图,但它并不激活内容本身——它只是提供结构。

学习策略

学习和练习 OOP 的方法比我能想到的多得多,但我必须选择一种,所以我决定使用莎士比亚的《罗密欧与朱丽叶》的故事情节创建一个简单的基于文本的游戏。我的过程如下:

  1. 写这个故事
  2. 画出问题
  3. 识别问题的实体——这些将是你的类
  4. 创建实体层次结构
  5. 确定实体的责任
  6. 编写您的测试
  7. 检查测试是否失败——最初会失败,因为您没有编写任何代码!
  8. 写代码
  9. 重复!重构!精炼!

这个过程不是一成不变的,我们也不应该成为它的奴隶。只是帮助我起步的一系列步骤。面向对象不仅仅是一种编程范式,它还是一种解决问题的方法,尽管它并非没有批评,但在构建复杂系统时,它是一个很好的选择。

兔子洞

请注意步骤 6:编写您的测试。现在,这不是我最初计划的一部分。我计划编码我的类,就是这样!但是在我研究 OOP 的时候,我遇到了测试驱动 开发 (TDD) 的概念。

TDD 是一种编程实践,它始于为程序的每个功能设计和开发测试。这种方式迫使你在开始写代码之前考虑规范、需求或设计。换句话说,你写代码是为了在你写任何代码之前测试你的代码。

迷茫?我也是。但是做这个练习 100%值得。

测试驱动的开发和单元测试

TDD 的过程非常简单:

Image from Kanchan Kulkarni’s TDD Tutorial.

  1. 写一个测试
  2. 运行测试
  3. 写一些代码
  4. 运行测试
  5. 重构代码
  6. 重复

在我的例子中,我使用 单元测试 进行 TDD。单元测试是软件测试的第一级,目的是验证程序中的每个单元都按照设计执行。有不同的框架来执行单元测试,我用的是[unittest](https://docs.python.org/3/library/unittest.html#module-unittest)

当谈到 TDD 时,你会发现人们站在两边。我亲身经历的一些好处如下:

  • 强迫你在开始毫无目的地输入代码之前思考你试图解决的问题。
  • 在基于类的 OOP 的特殊情况下,它帮助你理解每个类的契约。他们的职责是什么?他们需要知道什么?—当您的目标是低耦合和高内聚时,这变得更加重要。
  • 尽管一开始它可能会降低您的速度,但从长远来看,它通过最大限度地减少调试时间来节省您的时间。
  • 它鼓励更好的设计,使代码更容易维护,更少冗余(保持干燥!),并且在需要时可以安全地重构。
  • 它可以作为活的文档——仅仅通过查看测试,您就可以理解每个单元应该做什么,使代码不言自明。

罗密欧与朱丽叶——代码和测试

在思考了游戏的故事之后,我决定有两条不同的故事线经典另类。第一个是我们所知道的罗密欧与朱丽叶的故事,第二个,嗯,不是。

故事中的实体(我将用它作为创建不同类的参考)如下:

  • 场景:假面舞会,阳台,决斗,编曲,药剂师,凯普莱特墓,另类结局。场景有两个主要的职责,为玩家描述场景,然后提示玩家一个是或否的问题,以获得他们的输入。
  • Map:Map 作为 有限状态机 工作。它有有限数量的状态(场景),一个转换函数(从一个场景移动到另一个场景),和一个开始状态(第一个场景)。
  • 故事情节:为故事情节定义两个唯一的常量值。

从场景的定义可以看出,所有场景的职责都是一样的,只有它们的内容发生了变化(场景的描述和提示)。这就是为什么我们将使用[inheritance](https://docs.python.org/3/tutorial/classes.html)的概念。这个概念允许我们定义一个从另一个类继承所有方法和属性的类;在这种情况下,最重要的是保持代码干燥

对于故事情节类,我用了[Python’s](https://www.python.org/) [enumeration type](https://docs.python.org/3/library/enum.html)或者[enum](https://docs.python.org/3/library/enum.html)。在文档中,它们被定义为“”一组绑定到唯一的常量值的符号名(成员)。在枚举中,成员可以通过标识进行比较,并且枚举本身可以被迭代。

接下来,我们有了Scene classTestScene class。测试代码中两个值得注意的特征:1 .一个MockMap class的使用;2.创造一个TestScene class来测试这个Scene class。在单元测试级别,您将创建一个Test class来为您的每个类编写测试。

最后,但同样重要的是,让我们看看Map classTestMap class。就像之前一样,我们为Scene class创建了一个 mock,但在本例中是用MockScene class创建的。

结论

首先编写测试,然后编写程序代码的练习并不是没有困难的。

我不否认我曾经想过放弃整个测试的想法,但是当我在这个过程中坚持下来的时候,我发现自己更像一个程序员,花更多的时间思考设计,并且在某种程度上,从脚本升级到编码

我邀请你来测试一下(双关语!)。并且,如果你在学习 TDD 的时候有不同的感受或者有其他的经历,请一定要伸出手来谈论它。

面向数据科学家的面向对象编程:构建您的 ML 估计器

原文:https://towardsdatascience.com/object-oriented-programming-for-data-scientists-build-your-ml-estimator-7da416751f64?source=collection_archive---------2-----------------------

逐步指南

通过构建您自己的 Scikit-learn-like 估计器,在机器学习环境中实现一些核心的 OOP 原则,并使其变得更好。

更新:在这里 你总能找到最新的 Python 脚本(带有线性回归类定义和方法) 。用它来进一步构建或实验。

有什么问题?

数据科学家的背景通常与传统的计算机科学/软件工程相去甚远——物理学、生物学、统计学、经济学、电子工程等。

Source: “Where do Data Scientists Come From?”

但是最终,他们被期望获得足够数量的编程/软件工程,以对他们的组织和业务产生真正的影响。

[## 成为数据科学家并不能让你成为软件工程师!

如何构建可扩展的机器学习系统——第 1/2 部分

towardsdatascience.com](/being-a-data-scientist-does-not-make-you-a-software-engineer-c64081526372)

大多数现代编程语言和软件工程范例的核心是什么?

面向对象编程。

但是对于外行人来说,OOP 的原则起初可能感觉有点陌生,甚至有点吓人。因此,数据科学家,其背景不包括计算机编程的正式培训,可能会发现 OOP 的概念在他们的日常工作中有些难以接受。

流行的 MOOCs 和数据科学/人工智能/人工智能训练营也没有帮助。

他们试图给初露头角的数据科学家一种混合汤的味道,包括统计学、数值分析、科学编程、机器学习(ML)算法、可视化,甚至可能还有一点 web 框架来部署这些 ML 模型。

几乎所有这些都可以学习和实践,即使没有严格遵守 OOP 的原则。事实上,年轻的数据科学家渴望学习最新的神经网络架构或最酷的数据可视化技术,如果被 OOP 编程范式的所有细节轰炸,他们甚至会感到窒息。因此,MOOCs 通常不会在他们的数据科学课程中混合或强调它。

一个简单的例子(还有更多…)

让我用 Python 来举例说明这个问题,因为它是数据科学和机器学习任务发展最快的语言。

算术示例

如果让你写一个程序来实现涉及两个数ab的加、减、乘、除,你最有可能做什么?

你很可能会打开一个 Jupyter 笔记本,在一个单元格中键入以下内容,点击 shift-enter 并获得结果。

a+b
a-b
a*b
a/b

如果你喜欢用函数来整理东西,那么你可以这样做,

def add(a,b):
    return a+b
...

但是你会定义一个 Calc 并把这些函数作为 方法 放在那个类里面吗?这些都是性质相似的操作,它们处理相似的数据。那么为什么不把它们封装在一个更高阶的对象中呢?为什么不是下面的代码?

class Calc:
    def __init__(self,a,b):
        self.a = a
        self.b = b
    def add(self):
        return self.a+self.b
    def sub(self):
        return self.a-self.b
    def mult(self):
        return self.a*self.b
    def div(self):
        return self.a/self.b

不,你不会这么做的。对于这个特殊的问题,这样做可能也没有意义。但是这个想法是有效的— 如果你有数据和函数(在 OOP 的说法中称为方法),它们可以逻辑地组合,那么它们应该封装在一个类中

但是对于一些简单的数值计算来说,快速得到答案看起来太麻烦了。那么,有什么意义呢?数据科学家的价值通常在于他们能否得到数据问题的正确答案,而不是他们在代码中使用了什么样的复杂对象。

数据科学家的例子

如果数据科学家不是以这种方式编码,难道不是吗,他们真的不需要使用这些精心设计的编程结构?

错了。

在没有意识到的情况下,数据科学家大量使用了 OOP 范例的好处。无时无刻

还记得import matplotlib.pyplot as plt后的plt.plot吗?

那些符号。你有一点面向对象编程的知识。就在那里。

或者,你还记得在 Jupyter 笔记本上学习很酷的技巧——在放一个点(.),从而显示可以与一个对象关联的所有功能?像这样,

这个例子说明了什么?

这个例子显示了对逻辑一致性的坚持。

如果没有 OOP 范例,我们将不得不把这些函数命名为linear_model_linear_regression_fitlinear_model_linear_regression_predict等等。它们不会被归入一个共同的逻辑单元。

为什么?因为它们是不同的函数,处理不同的数据集。当fit函数期望训练特征和目标时,predict只需要一个测试数据集。fit函数不会返回任何结果,而predict会返回一组预测。

那么,为什么它们在同一个下拉菜单下可见呢?尽管有所不同,但它们有一个共同点,即它们都可以被想象为整个线性回归过程的重要组成部分 —我们希望线性回归能够拟合一些训练数据,然后能够预测未来的未知数据。我们还希望线性回归模型能为我们提供一些关于拟合程度的指示,通常是以一个称为回归系数或 R 的单一数字量或分数的形式。正如我们所料,我们看到一个函数score,它确切地返回 R 数,也在fitpredict附近。

整洁干净,不是吗?

数据、函数和参数共存于单个逻辑单元中。

这是如何实现的?

这是可能的,因为我们超越了个体差异,将线性回归视为一个高层次的过程,并决定它应该服务于什么样的基本操作以及它应该告知用户什么样的关键参数。

我们创建了一个名为LinearRegression的高级类,在这个类下,所有那些明显不同的功能可以被组合在一起,以便于记账和增强可用性。

一旦我们从库中导入了这个类,我们只需要创建这个类的一个实例——我们称之为lm。就是这样。我们可以通过新定义的实例lm访问该类下的所有函数。

如果我们对函数的一些内部实现不满意,我们可以对它们进行处理,并在修改后将其重新附加到主类。只有内部函数的代码会改变,其他都不会改变。

看,这听起来多有逻辑性和可伸缩性?

创建您自己的 ML 估计器

传统的 OOP 入门会有很多使用类的例子,比如动物、运动、几何形状。

但是对于数据科学家来说,为什么不使用他们每天在代码中使用的一个对象的例子来说明这些概念呢——机器学习估计器。就像 Scikit-learn 库中的lm对象,如上图所示。

一个很好的、古老的线性回归估计器——有所改变

在这个 Github repo 中,我一步一步地展示了如何遵循 OOP 范例构建一个简单的线性回归(单变量或多变量)估计器类。

没错,就是好老的线性回归类。它有 Scikit-learn 的LinearRegression类中常见的fitpredict方法。但是它有更多的功能。这里先睹为快…

是的,这个估计器比 Scikit-learn 估计器更丰富,因为除了标准的fitpredict和 R score函数之外,它还有许多其他实用程序,这些实用程序对于线性回归建模任务是必不可少的。

尤其是对于数据科学家和统计建模人员来说,他们不仅想预测,而且也想

  • 测量拟合优度,
  • 验证线性回归的假设,
  • 检查数据中的多重共线性,或
  • 检测异常值。

[## 如何在 Python 中检查你的回归模型的质量?

线性回归在统计学习中根深蒂固,因此必须检查模型的“良好性”

towardsdatascience.com](/how-do-you-check-the-quality-of-your-regression-model-in-python-fa61759ff685)

你如何开始构建类?

我们从一个简单的代码片段开始定义这个类。我们把它命名为——MyLinearRegression

这里,self表示对象本身,__init__是一个特殊函数,当在代码中的某个地方创建了一个类的实例时,就会调用这个函数。顾名思义,__init__可以用来初始化带有必要参数(如果有的话)的类。

我们可以添加一个简单的描述字符串来保持它的真实性:-)

接下来我们添加核心的fit方法。注意 docstring 描述了该方法的用途、它做什么以及它期望什么类型的数据。所有这些都是好的面向对象原则的一部分。

我们可以生成一些随机数据来测试我们的代码。我们创建一个两个变量的线性函数。这是数据的散点图。

现在,我们可以创建一个名为mlr的类MyLinearRegression的实例。如果我们试图打印回归参数会发生什么?

因为self.coef_被设置为None,我们在试图打印mlr.coef_时得到相同的结果。请注意,self 一旦被创建,就变成了类实例的同义词。

但是fit的定义包括在拟合完成后设置属性。所以,我们可以直接调用mlr.fit(),打印出拟合的回归参数。

最典型的Predict方法

拟合之后,就是预测。我们可以很容易地将该方法添加到我们的回归类中。

如果我们想添加一个(或几个)绘图实用函数呢?

在这一点上,我们开始扩展我们的回归类,并且添加了标准 scikit-learn 类中没有的东西!例如,我们总是希望看到拟合值与地面真实值相比如何。为此创建一个函数很容易。我们就叫它plot_fitted

注意,方法类似于普通函数。它可以接受额外的参数。这里,我们有一个参数reference_line(默认设置为False),它在拟合与真实曲线上绘制了一条 45 度参考线。另外,请注意 docstring 描述。

我们可以通过简单地执行以下操作来测试方法plot_fitted,

m = MyLinearRegression()
m.fit(X,y)
m.plot_fitted()

或者,我们可以选择画一条参考线,

m.plot_fitted(reference_line=True)

我们得到以下情节!

一旦我们明白我们可以添加任何有用的方法来处理相同的数据(一个训练集),与相同的目的(线性回归)相关,就没有束缚我们的想象力了!我们把下面的情节加到我们班怎么样?

  • Pairplots (绘制所有特性和输出之间的成对关系,很像 R 中的pairs函数)
  • 拟合与残差图(这属于线性回归的诊断图,即检查基本假设的有效性)
  • 直方图分位数-分位数(Q-Q) 残差图(检查误差分布的正态假设)

继承——不要让你的主类负担过重

当我们热情地计划将实用方法添加到类中时,我们认识到这种方法可能会使主类的代码非常长,并且难以调试。为了解决这个难题,我们可以利用 OOP 的另一个美丽的原则— 继承

[## Python 中的继承- GeeksforGeeks

继承是一个类从另一个类派生或继承属性的能力。…的好处

www.geeksforgeeks.org](https://www.geeksforgeeks.org/inheritance-in-python/)

我们进一步认识到并非所有的图都属于同一类型。配对图和拟合与真实数据图具有相似的性质,因为它们只能从数据中获得。其他图与拟合优度和残差相关。

因此,我们可以用这些绘图函数创建两个独立的类— Data_plotsDiagnostic_plots

你猜怎么着!我们可以根据这些实用程序类 来定义我们的主MyLinearRegression。那是继承的一个例子。

注意:这看起来和标准的父类-子类继承实践有点不同,但是语言的相同特性在这里被用来保持主类的整洁和紧凑,同时从其他类似构造的类继承有用的方法。

注意以下代码片段仅用于说明。请使用上面的 Github 链接查看实际代码。

Data_plots class

Diagnostics_plots class

MyLinearregression的定义只是略有改变,

**class MyLinearRegression(Diagnostics_plots,Data_plots**):

    def __init__(self, fit_intercept=True):
        self.coef_ = None
        self.intercept_ = None
        self._fit_intercept = fit_intercept
...

通过简单地将Data_plotsDiagnostics_plots的引用传递给MyLinearRgression类的定义,我们继承了这些类的所有方法和属性。

现在,为了检查误差项的正态假设,我们可以简单地拟合模型并运行这些方法。

m = MyLinearRegression() # A brand new model instance
m.fit(X,y) # Fit the model with some data**m.histogram_resid()** # Plot histogram of the residuals
**m.qqplot_resid()** # Q-Q plot of the residuals

我们得到,

同样,代码分离在这里起作用。您可以修改和改进核心绘图实用程序,而无需触及主类。高度灵活且不易出错的方法!

利用 OOP 的强大功能做更多事情

我们不会进一步详述我们可以添加到MyLinearRegression中的各种实用程序类和方法。可以 查看 Github 回购

添加了其他类别

为了完整起见,我们补充说,

  • 用于计算各种回归指标的类Metrics——SSE、SST、MSE、 R 和调整后的 R
  • 一个类Outliers来绘制库克的距离、杠杆和影响图
  • 计算方差膨胀因子的类Multicollinearity(VIF)

总而言之,这个宏伟的计划看起来如下:

这个类比 Scikit-learn 的 LinearRegression 类丰富吗?你决定吧。

通过创建分组实用程序来添加语法糖

一旦你继承了其他类,它们的行为就像你熟悉的 Python 模块一样。因此,您可以向主类添加实用方法,以便一起执行子类中的多个方法。

例如,以下方法一次运行所有常规诊断检查。注意我们是如何通过放置一个简单的来访问绘图方法的。点号Diagnostics_plot.histogram_resid。就像从熊猫或 NumPy 库中访问一个函数一样!

run_diagnostics method in the main class

这样,我们可以在拟合数据后用一行代码运行所有的诊断。

m = MyLinearRegression() # A brand new model instance
m.fit(X,y) # Fit the model with some data**m.run_diagnostics()**

类似地,您可以在一个实用程序方法中添加所有异常值图。

模块化—将类作为模块导入

虽然这不是一个规范的 OOP 原则,但是遵循 OOP 范例的本质优势是 能够模块化你的代码

您可以在一个标准的 Jupyter 笔记本上试验和开发所有这些代码。但是为了实现最大的模块化,可以考虑将笔记本转换成独立的可执行 Python 脚本(扩展名为. py)。一个好的做法是,从这个文件中删除所有不必要的注释和测试代码,只保留在一起的类。

这里是我为这篇文章整理的脚本 的链接。

一旦你这样做了,你就可以从一个完全不同的笔记本中导入MyLinearRgression类。这通常是测试代码的首选方式,因为这不会触及核心模型,而只是用各种数据样本和功能参数来测试它。

此时,您可以考虑将这个 Python 脚本放在 Github 上,创建一个 Setup.py 文件,创建适当的目录结构,并将其作为独立的线性回归包发布,该包可以进行拟合、预测、绘图、诊断等工作。

当然,你必须添加许多文档串描述,函数用法的例子,断言检查,和单元测试来使它成为一个好的包。

但是作为一名数据科学家,现在你已经增加了一项重要的技能——遵循 OOP 原则的软件开发。

这并不困难,是吗?

收场白

动机和相关文章

为了写这篇文章,我受到了这篇精彩文章的启发,这篇文章在机器学习的背景下更详细地探讨了 Python 中 OOP 的概念。

[## 通过机器学习理解面向对象编程

面向对象编程(OOP)并不容易理解。你可以一个接一个的看教程,筛选…

dziganto.github.io](https://dziganto.github.io/classes/data science/linear regression/machine learning/object-oriented programming/python/Understanding-Object-Oriented-Programming-Through-Machine-Learning/)

我写过一篇类似的文章,在深度学习的背景下,触及了更基本的方法。看看这里,

[## 面向对象编程的简单混合如何增强你的深度学习原型

通过混合面向对象编程的简单概念,如函数化和类继承,您可以添加…

towardsdatascience.com](/how-a-simple-mix-of-object-oriented-programming-can-sharpen-your-deep-learning-prototype-19893bd969bd)

课程?

我试着寻找相关课程,发现如果你正在使用 Python,就很少。大多数软件工程课程都是用 Java 教授的。这里有两个可能会有帮助,

  • Python 中数据科学家的软件工程
  • Python 类和继承

如果您有任何问题或想法要分享,请联系作者在tirthajyoti【AT】Gmail . com。此外,您可以查看作者的 GitHub 资源库中其他有趣的 Python、R 或 MATLAB 代码片段和机器学习资源。如果你像我一样,对机器学习/数据科学充满热情,请随时在 LinkedIn 上添加我或在 Twitter 上关注我。

[## Tirthajyoti Sarkar - Sr .首席工程师-半导体、人工智能、机器学习- ON…

www.linkedin.com](https://www.linkedin.com/in/tirthajyoti-sarkar-2127aa7/)

用卷积神经网络估计密度图进行目标计数

原文:https://towardsdatascience.com/objects-counting-by-estimating-a-density-map-with-convolutional-neural-networks-c01086f3b3ec?source=collection_archive---------5-----------------------

撰写托马什加成 托马什戈兰

介绍

对图像中的物体进行计数是计算机视觉的基本任务之一。它有很多应用,特别是在:

  • 微生物学(如在培养皿中计数细菌菌落);
  • 监视(如清点人数);
  • 农业(如统计水果或蔬菜);
  • 医学(如组织病理学图像中肿瘤细胞的计数);
  • 野生动物保护(如清点动物)。

对我们人类来说,计数对象的任务相对容易,但对计算机视觉算法来说,这可能是一个挑战,特别是当一个对象的不同实例在形状、颜色、纹理或大小方面有很大差异时。如果一个问题从算法的角度来看很复杂,但从人类的角度来看很简单,那么机器学习方法可以成为一个答案。

目前,深度学习(DL)方法在数字图像处理中提供了最先进的性能。然而,它们需要收集大量带注释的数据,这通常很耗时,并且容易出现标注错误。

使用 DL 计数对象的常见方式是首先使用卷积神经网络(如 GCNet [1])检测它们,然后计数所有找到的实例。这是有效的,但需要边界框注释,如图 1(左)所示,这是很难获得的。为了克服这个问题,替代方法利用了对象位置的点状注释(见图 1 右侧),收集起来便宜得多。

Fig. 1: Example annotated images from COCO [2] (left) and Mall [3–6] (right) datasets.

在这篇文章中,我们描述了我们的研究计数图像中的对象与全卷积网络(FCN),训练数据与点状注释。在接下来的部分中,我们将详细介绍我们使用的模型,以及实现、考虑的数据集和我们获得的结果。

方法

我们从[7]中描述的方法开始。主要思想是通过估计密度图来间接计数对象。第一步是准备训练样本,以便每个图像都有相应的密度图。让我们考虑图 2 所示的例子。

Fig. 2: An example image (left) and its annotation (right) from Mall dataset.

图 2(左)中呈现的图像用行人头部位置的点来标注(图 2 右)。密度图是通过应用与高斯核的卷积而获得的(并被归一化,以便对其积分来给出对象的数量)。上述示例的密度图如图 3 所示。

Fig. 3: The visualization of a density map generated with a Gaussian filter.

现在,目标是训练一个完全卷积的网络,将图像映射到密度图,稍后可以集成该密度图以获得对象的数量。到目前为止,我们已经考虑了两种 FCN 架构:U-Net [8]和全卷积回归网络(FCRN) [7]。

优信网

U-Net 是一种广泛用于图像分割的 FCN,经常应用于生物医学数据。它具有类似自动编码器的结构(见图 4)。输入图像由卷积层块处理,之后是汇集层(下采样)。这一过程在随后的模块输出上重复几次,如图 4 的左侧所示。这样,网络对输入图像的关键特征进行编码(和压缩)。U-Net 的第二部分是对称的,但是池层被上采样所取代,因此输出尺寸与输入图像的尺寸相匹配。来自下采样部分中的较高分辨率层的信息被传递到上采样部分中的相应层,这允许重新使用所学习的较高级特征来更精确地解码收缩层。

Fig. 4: U-Net architecture.

FCRN

全卷积回归网络(FCRN)是在[7]中提出的。架构与 U-Net 非常相似。主要区别在于,来自下采样部分的较高分辨率层的信息没有被直接传递到上采样部分中的相应层。在该论文中提出了两种网络:FCRN-A 和 FCRN-B,它们在下采样强度方面不同。FCRN-A 在每个卷积层执行池化,而 FCRN-B 每隔一层执行一次池化。

履行

我们的实现可以在这里找到。它基于狄威·Xi 的 GitHub 的代码,但是用 PyTorch 代替了 Keras。

目前,U-Net 和 FCRN-A 已经实施。它们都使用固定滤波器大小为 3×3 的三个下采样和三个上采样卷积块。默认情况下,U-Net 的每个块中有两个卷积层,FCRN-A 有一个。对于 U-Net,我们为所有卷积层保持恒定数量的滤波器,而对于 FCRN-A,我们在每个后续层增加该数量,以补偿池化(不像 U-Net 那样直接传递)导致的更高分辨率信息的损失。

卷积块

构建 U-Net 和 FCRN 的基础是一个卷积模块,由卷积层、批量归一化和激活函数组成:

conv_block函数创建N个卷积层,每层使用ReLU激活函数和批量标准化的OUT个滤波器。

FCRN——一座建筑

通过堆叠多个这样的块,然后是下采样(最大池)或上采样层,获得 FCRN-A 架构:

U-Net 架构

U-Net 还要求将下采样路径的输出与上采样部分中相应层的输入连接起来,这由 ConvCat 类执行:

U-Net 下采样部分的构建方式与 FCRN 的情况相同:

然而,如上所述,上采样利用了ConvCat类:

数据

我们在研究中考虑了三个数据集。它们都标注了点状物体的位置,因此我们可以直接使用它们来生成所有图像的密度图,并测试上述方法。

数据预处理

我们提供了[get_data.py](https://github.com/NeuroSYS-pl/objects_counting_dmap/blob/master/get_data.py)脚本,将所有考虑的数据集预处理成存储在 HDF5 文件中的通用格式。每个条目由一幅图像和一个用generate_label函数生成的相应标签(密度图)组成;

请注意,在应用高斯滤波器之前,我们为每个对象位置设置了值 100,因此在整合密度图以获得图像上存在的对象数量时,结果必须正确归一化。

出于可视化目的,我们对图像上呈现的密度图使用了比我们实际应用于训练数据集的密度图更高的标准偏差值。

荧光细胞数据集

荧光细胞(FC)数据集由视觉几何组(VGG)使用[9]的计算框架生成。可以从 VGG 网站下载。图 5 中呈现了示例图像以及生成的密度图。

Fig. 5: An example image and corresponding density map (FC dataset).

UCSD 行人数据集

UCSD 数据集[10]包含在加州大学圣地亚哥分校的人行道上记录的行人视频。它广泛应用于各种问题,如计数、运动分割和行人行为分析。可以从统计可视化计算实验室网站下载。图 6 中呈现了示例图像以及生成的密度图。

Fig. 6: An example image and corresponding density map (UCSD dataset).

商城数据集

购物中心数据集[3–6]是为人群计数和分析而创建的。它包含一段由公开的网络摄像头录制的视频。每一帧都标注了每个行人的头部位置。可以从这里下载。图 3 中呈现了示例图像以及生成的密度图。

通过整合估计的密度图对图像中的对象进行计数的方法已经应用于荧光细胞和 UCSD 数据集[11]。我们选择 mall 数据集作为该方法的测试数据集。

结果

如上所述,测试了两个模型,即 U-Net 和 FCRN。使用 U-Net,我们能够获得更准确的结果,因此下面我们将展示使用该架构获得的结果。

在下面的表格中,我们的结果的总结是针对每个数据集呈现的,具有验证集中对象的最小和最大数量以及我们获得的平均绝对误差(MAE)。

我们使用 MAE 的标准定义:

其中 ti 为真, pi 为第 i 个样本的预测对象数。

 Dataset      | Min. #objects | Max. #objects | MAE  
 -------------------|---------------|---------------|------ 
  Fluorescent cells |            74 |           317 | 1.89 
  UCSD              |            20 |            47 | 2.27 
  Mall              |            20 |            48 | 2.86

图 7-9 显示了每个验证样品的真实( ti )与预测( pi )数量的散点图。正如预期的那样,尽管在单个图像中有大量的对象,该模型也能很好地处理相对简单的荧光细胞数据集。然而,在计算行人时,偏差要高得多。这可能是由于这样一个事实,即使是人类贴标机也很难决定站在植物后面的人还是从角落后面勉强可见的人应该被计算在内。

这只是我们研究对象计数的开始。我们期待进行更多的实验,包括尝试不同的架构和方法。

Fig 7. True vs predicted counts on fluorescent cells validation dataset.

Fig 8. True vs predicted counts on UCSD validation dataset.

Fig 9. True vs predicted counts on mall validation dataset.

参考

[1]曹,杨,徐,张,林,魏,胡海红(2019)。GCNet:非局域网络满足压缩激励网络及其他。 arXiv 预印本 arXiv:1904.11492

[2]林、T. Y .、梅尔、m .、贝隆吉、s .、海斯、j .、p .、拉马南、d .……、齐特尼克、C. L. (2014 年 9 月)。微软 coco:上下文中的公共对象。在欧洲计算机视觉会议(第 740–755 页)。斯普林格,查姆。

[3]钱来,龚,s .,&项,T. (2013).从半监督到转移人群计数。IEEE 计算机视觉国际会议论文集(第 2256–2263 页)。

[4]陈,龚,s,向,t .,&钱乐昌(2013)。年龄和人群密度估计的累积属性空间。在IEEE 计算机视觉和模式识别会议论文集(第 2467-2474 页)。

[5]罗正昌,陈,龚,龚,向,唐(2013)。人群计数和分析:方法和评估。在人群的建模、模拟和视觉分析(第 347–382 页)。纽约州纽约市斯普林格。

[6]陈,李,陈春春,龚,向,唐(2012 年 9 月)。用于局部人群计数的特征挖掘。在 BMVC (第 1 卷,№2,第 3 页)。

[7]x .狄威、J. A .诺布尔和 a .齐塞曼(2015 年)。用完全卷积回归网络进行显微细胞计数。在第一届深度学习研讨会上,医学图像计算和计算机辅助介入(MICCAI)

[8] Ronneberger,o .,Fischer,p .,& Brox,T. (2015 年 10 月)。生物医学图像分割的卷积网络。在国际医学图像计算和计算机辅助介入会议(第 234-241 页)。斯普林格,查姆。

[9] Lehmussola,a .,Ruusuvuori,p .,Selinummi,j .,Huttunen,h .,& Yli-Harja,O. (2007 年)。用细胞群模拟荧光显微镜图像的计算框架。 IEEE 医学影像汇刊26 (7),1010–1016。

[10]陈亚波,梁,张淑珍,,N. (2008 年 6 月).保护隐私的人群监控:计数没有人模型或跟踪的人。在 2008 年 IEEE 计算机视觉和模式识别会议上(第 1-7 页)。IEEE。

[11] Lempitsky,v .,& Zisserman,A. (2010 年)。学习计数图像中的物体。在神经信息处理系统的进展(第 1324-1332 页)。

11 月 20 日凯尔特人对快船的统计观察

原文:https://towardsdatascience.com/observations-from-celtics-vs-clippers-11-20-baa284112434?source=collection_archive---------44-----------------------

在经历了一个充满球员流动和球员名单变动的夏天之后,这里到底发生了什么?昨晚,世界上我最喜欢的一些球员进行了面对面的交流,我们必须谈谈这件事。

前言

作为联赛中两支最好的球队之间的一场全国电视转播的比赛,球迷们收看是很自然的事情。我们观看了一场经典常规赛,我们东海岸的所有人都因为熬夜而获得了免费篮球奖励——加时赛。凯尔特人必须成为今年的惊喜队。部分惊讶来自于媒体提供给我们的信息,但我认为我们大多数凯尔特人球迷并没有预料到这一点。 11 比 2,10 连胜在我们的口袋里?现在来吧。不管怎样,我确实对这个游戏有既得利益,因为我在夏天写了关于肯巴·沃克和科怀·伦纳德的文章。在赛季初观看比赛既富有诗意,也是我反应过度的原因。也许我写的并不是关于游戏本身,而是两个团队在这场游戏中的统计和分析性叙述。

快船

快船是今年夏天的突围队。他们的赛季在季后赛第一轮结束后,以 4-2 输给了金州勇士队(不过他们的 2 场胜利都是在甲骨文球馆取得的。不小的壮举)。快船完成了一个小抢劫,让科怀·伦纳德签下,然后在交易中巧妙地从俄克拉荷马雷霆队得到了保罗·乔治,就在他签下一份 max 合同的一年后。话虽如此,我认为真正有趣的是快船 VORP 的百分比分解。如果我们看这个饼状图,我所说的关于“科怀效应”的一切似乎都不存在:

我会说这是一个很好的,相当平均的分布。科怀的 VORP 是所有首发球员中最低的。但是什么是 VORP 呢?从字面上来看,它代表的是替代球员的价值。这支快船花名册的美妙之处就在于此。这个名单是如此的全面,以至于没有球员的 VORP 高于——等等——0.8(蒙特雷兹·哈雷尔科怀·伦纳德)。如果我们看一下这张图表,比较快船轮换球员每场比赛的得分和他们的 VORP,这证明了他们的阵容的实力:

保罗·乔治、科怀·伦纳德、卢·威廉姆斯、蒙特雷兹·哈雷尔都在进攻端做出了巨大的贡献。这显然并不令人惊讶,我也不是诺查丹玛斯,但让我们来看看这句话:

新的快船将会是致命的。2018-19 年版本的 Clips 是一支有趣的球队,超出了预期,并从金州勇士队(当时在甲骨文球馆)赢了两场比赛,预计 2019-20 年的快船看起来准备好将其他球队赶出体育馆。

哦,对了,我有没有提到谁是快船的替补?卢·威廉姆斯和蒙特雷兹·哈雷尔。特雷兹场均 16.6 PPG 和 6.5 RPG,同时带来了很多勇气和强度,而斯威特·卢将他一如既往的圆滑带到了场均 20 PPG 和 5.4 APG 的比赛中——在需要的时候也充当了夹子的终结者。只是为了好玩,让我们看看与前面提到的首发阵容相比,关键时刻的阵容可能会是什么样子。

这句话来自我写的上一篇文章。特雷兹和斯维特·卢的场均得分都将比上赛季高。快船坐在 11-5。科怀不会在背靠背的晚上打第二场比赛。保罗·乔治只打了 5 场比赛。凯尔特人快船黄金时间的比赛是科怀和 PG 第一次一起打比赛。快船只会变得更好,因为他们的身份得到了界定。关于他们的身份,如果有一件事我还没有提到,那就是他们的防御。他们的旋转可以在所有位置 1-5 无缝旋转。他们的防守排名联盟第 9,无论如何都不差,但随着快船的两位明星更多地一起打球,他们的防守只会变得更好。周三晚上,这种防守得到了充分的展示,压制住了凯尔特人队的新星肯巴·沃克。

凯尔特人

作为波士顿凯尔特人队的最新成员,肯巴·沃克已经蒸蒸日上。作为一名球迷,观看上赛季的比赛是痛苦的。想象一下,没有凯里·欧文参加东部决赛,带着勒布朗参加第七场比赛,输了 8 分,然后在接下来的赛季中退步。好的一面是,你不需要去想象——事实就是如此。没有人怀疑垂怜经的天赋。正如我在上一篇关于垂怜经和肯巴的文章中所说,垂怜经是一名超级巨星,拥有联盟中最好的控球能力和从任何地方得分的能力。话虽如此,数字告诉我们,肯巴应该是一个足够好的替代者——他绝对是。我不喜欢在肯巴和垂怜经之间做比较,我已经做过了。然而,任何关于波士顿凯尔特人的谈话似乎都不可能没有两者之间的某种比较。

Head to Head Comparison of Basic Stats

Head to Head comparison of 3P% and FG%

克里的场均得分和助攻比肯巴·沃克好得多。肯巴确实有更好的 3 分命中率,但所有这些数据都告诉我们,垂怜经更好。

肯巴·沃克的真正价值可以从杰森·塔图姆、杰伦·布朗、马库斯·斯马特和戈登·海沃德的表演中看出来。这四名球员都是关键的轮换球员,他们在凯里·欧文的第二个也是最后一个赛季表现不佳。这是去年和今年他们场均得分的对比。

Points Per Game from last year versus this year

这里绝对没有争论。之前有人批评我不能“在团队运动中量化化学”。我不确定是否真的有办法做到这一点,但如果有,这是一个可视化。今年的凯尔特人打得更加团结,作为一个整体,每个人都因此受益。如果球队中的每个球员都像这样打球,肯巴·沃克不需要每晚拿下 25-30 分。

旁注——对于所有批评杰伦·布朗续约的纸上谈兵的总经理们,请保持同样的精力。这个赛季他所做的一切就是投球。

结论和要点

季节是年轻的。这些都是过度反应。快船很可能会变得更好。凯尔特人确实需要海沃德回来,像他在新赛季开始时那样打球。但是,我确实相信这支凯尔特人队。“视力测试”和统计数据都支持今年他们是一支精英球队的观点。的确,凯尔特人在一场极度注重防守的比赛中输给了快船。然而,我认为基于他们在那场比赛和其他比赛中的表现,他们有很多值得高兴的地方。没有所谓的“好的损失”,但在那场比赛中我们看到了很多好的东西。凯尔特人看起来焕然一新,准备好迎接他们的新控卫肯巴·沃克,我就是为此而来。加油凯尔特人!

使用 Python 获取 CSV 格式的历史天气预报数据

原文:https://towardsdatascience.com/obtain-historical-weather-forecast-data-in-csv-format-using-python-5a6c090fc828?source=collection_archive---------4-----------------------

credit: https://www.pexels.com/photo/black-windmill-33493/

最近在做一个机器学习项目,需要多个城市的历史天气预报数据。尽管进行了大量的研究,我还是很难找到好的数据源。大多数网站只允许访问过去两周的历史数据。如果需要更多,需要付费。在我的例子中,我需要五年的数据——每小时的历史预测,这可能很昂贵。

概述……

1。免费—至少在试用期内

不需要提供信用卡信息。

2。灵活

灵活改变预测时间间隔,时间段,地点。

3。可重复

易于在生产阶段复制和实施。

最后,我决定使用来自世界天气在线的数据。这花了我不到两分钟的时间订阅免费试用高级 API——无需填写信用卡信息。(截至 2019 年 5 月 30 日,60 天内每天 500 次免费请求)。

https://www.worldweatheronline.com/developer/signup.aspx

您可以在这里尝试 JSON 或 XML 格式的请求。结果是嵌套的 JSON,在输入 ML 模型之前需要做一些预处理工作。因此,我写了一些脚本来将它们解析成熊猫数据帧,并保存为 CSV 以备后用。

介绍 wwo-hist 包

该 wwo-hist 包用于从世界天气在线中检索历史天气数据并解析成 pandas DataFrame 和 CSV 文件。

输入: api_key,location_list,start_date,end_date,frequency

输出:位置名称. csv

输出列名: date_time,maxtempC,mintempC,totalSnow_cm,sunHour,uvIndex,uvIndex,moon_illumination,moonrise,moonset,sunrise,sunset,DewPointC,FeelsLikeC,HeatIndexC,WindChillC,WindGustKmph,cloudcover,湿度,precipMM,气压,tempC,能见度,winddirDegree,windspeedKmph

安装软件包:

pip install **wwo-hist**

[## 世界历史

这个软件包是用来检索和转换历史天气数据从 www.worldweatheronline.com 到熊猫…

pypi.org](https://pypi.org/project/wwo-hist/)

导入包:

from **wwo_hist** import **retrieve_hist_data**

设置工作目录以存储输出 csv 文件:

import os
os.chdir(".\YOUR_PATH")

示例代码:

指定输入参数并调用retrieve _ hist _ data()有关参数设置的更多信息,请访问 my github repo 。

这将从 2018 年 12 月 11 日到 2019 年 3 月 11 日检索新加坡加州3 小时间隔历史天气预报数据,并将输出保存到 hist_weather_data 变量和 CSV 文件中。

frequency = 3
start_date = '11-DEC-2018'
end_date = '11-MAR-2019'
api_key = 'YOUR_API_KEY'
location_list = ['singapore','california']hist_weather_data = **retrieve_hist_data**(api_key,
                                location_list,
                                start_date,
                                end_date,
                                frequency,
                                location_label = False,
                                export_csv = True,
                                store_df = True)

This is what you will see in your console.

Result CSV(s) exported to your working directory.

Check the CSV output.

你有它!详细的脚本也记录在 GitHub 上。

感谢您的阅读。请尝试一下,并让我知道你的反馈!

考虑在 GitHub 、 Medium 和 Twitter 上关注我,在你的 feed 上获取更多文章和教程。如果你喜欢我做的,不要只按一次拍手按钮。击中它 50 次:D

从数据中获得洞察力:优化 NBA 职业生涯

原文:https://towardsdatascience.com/obtaining-insights-from-data-optimizing-an-nba-career-6605c9f07119?source=collection_archive---------18-----------------------

自从《Moneyball》出版以来,人们开始用更多的统计数据来审视体育,所以作为一个热衷于统计数据的体育迷,我想解决一个非典型的篮球问题:我们如何才能优化一个典型的篮球运动员在 NBA 的职业生涯?这个问题本身似乎是开放式的,所以为了更好地确定这个努力的范围,我将用赚到的钱来衡量成功。这篇文章的所有代码都可以在 https://github . com/aaronfredrick/B-Tier-Basketball-Career-Modeling 找到,作为参考和附加的上下文。

为了回答如何随着时间的推移使收入最大化的问题,我们必须知道哪支球队的工资中位数最高,并推荐我们的球员去那支球队。幸运的是,data.world 上的一位好心用户已经为每个球员的年薪和过去 30 年的球队策划了一个 csv。这使我们能够获得第一手信息——如下图所示的工资中位数最高的团队。

money_group = pay_df[[‘team’,’salary’]].groupby(by=[‘team’]).median()top10 = money_group.sort_values(by=’salary’, ascending=**False**).head(10)top10[‘Team’] = top10.index
top10[‘Salary’] = top10.salarycolor_order = [‘xkcd:cerulean’, ‘xkcd:ocean’, ’xkcd:black’, ’xkcd:royal purple’, ’xkcd:royal purple’, ‘xkcd:navy blue’, ’xkcd:powder blue’, ‘xkcd:light maroon’, ‘xkcd:lightish blue’, ’xkcd:navy’]sns.barplot(x=top10.Team, y=top10.Salary, palette=color_order).set_title(‘Teams with Highest Median Salary’)plt.ticklabel_format(style=’sci’, axis=’y’, scilimits=(0,0))

上面的代码让我们可以通过中值工资来可视化我们的高薪团队,加上一点点工作添加徽标,我们的最终图表如下所示:

很明显,我们的球员所在的球队并不是决定薪水的唯一因素,所以我们将探索盒子得分统计数据,看看什么有助于获得最高的收入。既然我们已经回答了第一个问题,是时候继续讨论篮球运动员更容易控制的事情了:他们可以提高哪些技能来获得更高的薪水。在探索了过去 20 年左右的拳击分数后,我将展示一种趋势,这种趋势会导致一个结论,即我们应该以最大限度地增加我们的比赛时间为目标,因为这给了我们的球员最大的潜力来获得更高的收入,并且在所述球员的控制下得多。

Dollars earned per average minutes played in the NBA

我获得的盒子分数是用 github 上的代码从 basketball-reference.com 刮来的。我发现了一种比以前更新的更有效的方式来抓取盒子分数,我强烈推荐使用熊猫图书馆的 read_html 函数。在下面的代码中,我将获取一个任意的框分数,并对其进行清理,以便与类似的数据帧一起使用和聚合:

url = 'https://www.basketball-reference.com/boxscores/200905240ORL.html'df_list = pd.read_html(url)
cavs = df_list[0]#Strip Multi-Indexed Column Headers
cavs = pd.DataFrame(cavs.values)#Drop Null Columns
cavs = cavs.dropna(axis=1)#Get New Column Headers from 'Reserves' row
colnames = cavs.values[5]
colnames[0] = 'Name'
cavs.columns = colnames

只需几行代码,我们就可以从一个网站(html 中有表格)获取基本的方框分数,并转换成一个干净的、ml 友好的数据框架。在收集了几百个盒子分数、执行了一些特征工程(将盒子分数统计数据转换成比率)以及 z-score 缩放数据之后,我们准备好检查每个指标对播放时间的影响。下面是一个热图,显示了各种功能之间的相互关系,我们的目标行在底部:

红色的阴影并没有告诉我们相关性的大小,而是一种关系的证据。这意味着一个框的颜色越深,行和列特征之间的相关性(任何数量级)就越明显。

我们可以从最下面一行(也是最后一列)的红色中看到,大多数统计数据显示与上场时间呈正相关,主要的例外是三分球尝试,篮板,抢断,盖帽和失误(都是每分钟的上场时间)没有明显的相关性,犯规和进攻篮板显示与上场时间呈负相关。在这里结束我们的分析是很好的,但我们可以更具体地告诉我们的篮球运动员提高他们的 2 分命中率,3 分命中率,命中率,罚球命中率和助攻率。通过对这些数据进行线性回归,我们可以了解这些统计数据中哪些是最重要的,以便玩得更多,并通过代理赚得更多。

用 Scikit-Learn 的 ElasticNetCV 类拟合线性回归模型后,我们可以获得对线性拟合有贡献的系数的值:

lambdas = [0.01,0.1,0,1, 10, 100, 1000, 10000, 100000]
score = 0
**for** ratio **in** range(11):
    model = ElasticNetCV(alphas=lambdas,l1_ratio=ratio/10)
    model.fit(X_train,y_train)
    **if** model.score(X_test,y_test) > score:
        score = model.score(X_test,y_test)
        optimal_model = model
        optimal_ratio = ratio

print(score)
print(optimal_ratio)

通过检查 optimal_model.coef_ 的输出,我们可以看到输入矩阵中指定的每个特性的系数数组。因为输入矩阵是 z 缩放的(平均值为 0,标准偏差为 1),所以系数可以从高到低排序,以指示在实现更多播放时间方面的重要性。

从我们前面的列表中,我们可以将最重要的技能缩小到 3 个:投篮命中率,三分球命中率和罚球命中率。

总之,我们希望我们的职业篮球运动员提高他们的投篮命中率。通过改善他们的投篮,我们的模型预测他们将增加他们的上场时间。通过增加他们的上场时间,我们的球员正在增加他们的工资潜力。当我们的球员在球场上培养他们的技能时,代理人应该如上所示向前十名球队投球,以最大限度地增加场外收入。

使用 Google 的 AutoML Vision 对扫描的数字进行 OCR

原文:https://towardsdatascience.com/ocr-for-scanned-numbers-using-googles-automl-vision-29d193070c64?source=collection_archive---------14-----------------------

AutoML —易用性展示

介绍

在之前的一篇博客文章,中,我详细介绍了我用来为扫描的数字创建 OCR 的步骤,如下图所示,通过使用梯度方向直方图(HOG)对从图像(数字)中提取的一组特征训练k-近邻(k-NN) 机器学习模型。****

Figure 1. Scanned numbers to OCR

概括来说,实现 OCR 的步骤以及每个任务或阶段中涉及的相应工作可以概括为:

  1. 图像处理寻找数字周围的边界框(25%)
  2. 从数字中提取数字,并创建一个训练/测试集(10%)
  3. 识别并应用合适的特征提取(梯度方向直方图)(35%)
  4. 实验并应用不同的机器学习算法(KNN vs SVM) (20%)
  5. 以有意义的方式展示数据(10%)

自动视觉

在这篇博客中,我将详细介绍使用 AutoML 为同一问题创建 OCR 的步骤。如下图所示, AutoML 消除了我工作中的一项繁琐任务,即寻找并应用合适的特征提取和机器学习技术。该模型达到了 98%的准确率,略好于之前博客中的解决方案。

本项目使用的数据集可下载:https://drive . Google . com/file/d/1 irpqo _ r V8 ygvz-hquq 0 hlpay 4 ed 7 wxfz/view?usp =分享

Figure 2. Stages replaced by AutoML

1 —图像处理:训练/测试数据集准备

概括一下我以前的博客,我的训练/测试集包括如下所示的数字(0、2、5、6 和 8 数据集的例子)。这些数字是从图 1 所示的扫描数字中提取的。

Figure 3. Splitting numbers into single digits

然后,训练/测试数据集被组织在文件夹中,其中每个文件夹的名称代表存储在该文件夹中的数字的标签。

****

Figure 4. Train / Test dataset sorted in folders

2-训练/测试数据集上传

Google AutoML 提供了两个上传训练/测试数据集的选项。

选项 1 :上传数字并存储在 Google cloud 上,并提供一个 CSV 文件,列出每个数字的 URL 及其对应的标签。

选项 2 (我博客里用的):压缩包含数据集的文件夹,上传压缩文件。Google ML 假设每个文件夹的名称是存储在其中的数字的标签。

Figure 5. Uploading train/test dataset to Google ML

AutoML 正确地识别了每个数字的标签(图 6)并提供了基本的数据集分析(图 7),并准备好创建 ML 模型(或模型?)点击“开始训练”。

Figure 6. Dataset uploaded and label identified

Figure 7. Basic dataset analysis

4 —模型精度

训练模型花了 15 分钟。ML 模型准确度/精度和混淆矩阵如下所示。

Figure 7. Model accuracy

5-混淆矩阵

混淆矩阵如下:

  • 该模型能够以 100%的准确度(基于训练/测试数据集)预测数字(4、9、0、1、2 和 7)。
  • 有 8.7%的几率会把 8 混淆为 6。
  • 1.8%的几率会把 5 误认为 3。
  • 有 2.9%的几率将 3 混淆为 5。

Figure 8. Confusion matrix

6 —预测

要测试模型,只需上传数字来运行预测,或者使用 Google 提供的 API(图 8)。

Figure 8. ML model is exposed as an API and hosted on Google Cloud

正确预测:例 1

Figure 9. Accurate prediction

正确预测:例二

Figure 10. Accurate prediction

错误预测:例 3

这是出乎意料的,该模型将 a 6 混淆为 A8,尽管混淆矩阵显示它可以 100%准确地预测 a 6。

作为未来的工作,我可能会训练第二个或更多的机器学习模型,每个模型都是为一对与第一个模型混淆的数字(即 6 和 8)量身定制的。我可能还会提供部分图像来训练模型,例如,只提供 6 位和 8 位数字的上半部分,因为这些数字在上象限大部分是不同的。

Figure 11. Wrong prediction

结束语

有趣的是看到 Google ML 如何自动化数据科学家的乏味工作,即寻找合适的特征提取技术和调整机器学习模型。然而,我认为数据科学家工作的困难部分实际上是确定可以使用机器学习解决的问题,最重要的是能够提取适合使用机器学习解决的数据集。后者需要扎实的编程技能和对不同机器学习技术如何工作的深刻理解。

八度卷积:退一步看输入?

原文:https://towardsdatascience.com/octave-convolution-taking-a-step-back-and-at-looking-inputs-235c313a362c?source=collection_archive---------19-----------------------

倍频程卷积的介绍、简要说明和详细 PyTorch 实现。

Figure from here

卷积神经网络(CNN)已经主导了计算机视觉领域。在这篇文章中,我们将看看最近从这篇文章中提出的倍频程卷积:降低一个倍频程:使用倍频程卷积减少卷积神经网络中的空间冗余。

倍频程卷积可以用来替代普通卷积。作者已经证明,使用倍频程卷积可以实现类似(有时更好)的精度,同时节省大量所需的触发器。八度和香草卷积的模型大小是相同的。

普通卷积在所有输入通道中执行高频卷积。另一方面,倍频程卷积将所有声道分为两部分:高频和低频。低频通道比高频卷积小一个倍频程(高度和宽度)。此外,在发送输出之前,高频和低频通道相互组合。

从图中可以看出,每个倍频程卷积模块内部最多可以有 4 个分支,每个分支执行普通卷积。绿色路径不会改变从输入到输出的空间维度。然而,红色路径会增加(从低到高)或减少(从高到低)从输入到输出的空间维度。

当从高频输入到低频输出(HtoL 路径)时,执行 2x2 合并操作,以获得用于卷积的缩减输入。所以,HtoL 路径是conv _ 香草(pool(in_high))

类似地,当从低频输入到高频输出(LtoH 路径)时,普通卷积以双线性插值为顶,以对低分辨率 conv 输出进行上采样。所以,LtoH 路径是bilenear _ interpolation(vanilla _ convolution(in _ low))

Figure from here

八度卷积的核心是α的概念(低频卷积使用的总通道的比率)。对于第一个卷积层,没有低频输入通道,所以α_{in} = 0。同样,对于最后一个卷积层,没有低频输出通道,α_{out} = 0。对于所有其他层,作者假设α_{in} = α_{out} = 0.5。

作者在论文中展示了大量结果。我觉得最有趣的一个如下图所示。如您所见,对于一小部分低频成分(0.125 或 0.25),网络性能优于所有高频通道的基线模型。

Figure from here

下面是 Pytorch 的实现。

完整的实现可以在我的 git repo 中找到。为了测试这个实现,我在 CIFAR10 上训练了一个 2 层的普通 CNN 大约 20 个时期。然后我把所有卷积都换成了八度卷积。网络表现稍好(2–3%)。我觉得,对于更大的网络,这种差异可能会更好。

十月版:闯入数据科学

原文:https://towardsdatascience.com/october-edition-breaking-into-data-science-2a845963816e?source=collection_archive---------17-----------------------

在过去十年中,数据科学领域呈指数级增长,无论是在应用的广度上,还是在有抱负的数据科学家理解其核心概念的深度上。这个月,我们选择了 8 篇文章,它们提供了进入数据科学的有用路线图,以及描述成功的数据科学家如何首次进入该领域并建立职业生涯的鼓舞人心的轶事。

数据科学领域的工作实际上是什么样的,现在的工作需要哪些技能?初级数据科学家在找工作时会遇到哪些潜在的陷阱,有抱负的技术人员和转行者如何为工作做好准备?进入数据科学领域需要 CS 学位吗?或者,是否有可能从非传统背景(如新闻业)深入研究数据科学?此外,对于更高级别的数据科学家,您如何继续推进您的职业发展?像这样一个快节奏和创新的行业,保持增长的心态是很重要的。

这些是我们在这个月的编辑精选中要解决的一些问题。今年十月,我们汇集了各种资源,帮助你在行业中导航,让你的职业生涯开花结果。

— 安珀·滕,TDS 编辑

要想被聘为数据科学家,不要从众

由杰瑞米·哈里斯 — 5 分钟读完

我还记得我哥哥决定卖掉他的比特币的那一刻。那是 2017 年,我们在星巴克。

成为 3.0 级数据科学家

由简·扎瓦日基 — 9 分钟读完

想成为大三,大四,还是首席数据科学家?了解您需要做些什么来驾驭数据科学职业游戏。

如何在你梦想的公司找到一份数据科学家的工作——我的 Airbnb 之旅

由彭凯莉 — 8 分钟读完

流程、提示和一些资源

从数据分析师成长为数据科学家的秘方

由娜塔莉亚·库帕努 — 11 分钟阅读

从数据分析横向迁移到数据科学的顶级技巧

在数据科学领域找份工作会是什么样子

克里斯汀·凯尔勒(Kristen ke hrer)—9 分钟阅读

备选标题:我的人生故事:)

没有学位如何学数据科学

由 Jason Jung — 7 分钟阅读

一位数据科学家的想法和建议

我如何从一名记者成为一名数据科学家

由姚洋 — 5 分钟读完

自我成长之旅

我的数据科学之旅

由 Rosebud Anwuri。 — 8 分钟读取

很多人问我关于我从化学工程转到数据科学的问题。

我们也感谢最近加入我们的所有伟大的新作家,萨里特·迈特拉,艾蒂安·拉姆斯坦,弗拉迪米尔·邦,艾伦·杰弗里斯,凯塔·宫崎,纳森·伯恩斯,侯赛因·贾夫达尼·萨达伊博士,米歇尔·贝内斯蒂,泰勒·福克曼, 多梅尼科·尼科利、汤姆·德拉巴斯、刘易斯·韦恩-琼斯、嘉豪·翁、萨米亚·海莫拉、卡蒂克·卡雷、李立伟、罗杰·黄、豪尔、卡丽·洛等等。 我们邀请你看看他们的简介,看看他们的工作。

ODS 早餐要来你的城市了!巴黎,还有…

原文:https://towardsdatascience.com/ods-breakfast-is-coming-to-your-city-paris-and-562b1244febd?source=collection_archive---------25-----------------------

…这取决于你!

这篇文章是对巴黎开放数据科学(ODS)早餐会的庆祝,这是一个关于数据科学和生活的非正式聚会,周六在 Malongo 咖啡馆(靠近圣米歇尔广场)举行。

Thanks for the logo to Yulia Dembitskaya

开放数据科学早餐不仅在巴黎提供,在世界各地的许多城市都有。在数据科学早餐会上,你可以和一位数据科学家同事边喝咖啡边谈论数据科学和其他任何事情。

在巴黎的数据科学早餐会上,你可以遇到来自工业界和学术界的人。你会发现数据科学及其他领域的各种专业知识。总的来说,我们拥有数学和物理、计算机科学、量化金融和交易、神经科学、尖峰神经网络、深度学习、优化、统计、网络科学、推荐系统、DevOps、软件和机器学习工程等方面的知识。

请继续阅读,了解你可以从 ODS 早餐中获得的各种健脑食物,并学习社区建设课程。

一切开始的地方

来自俄罗斯的爱

数据科学早餐的传统大约始于 2013 年的莫斯科。人们聚在一起吃早餐,在工作前谈论数据科学和生活。数据科学早餐传统传播到俄罗斯和其他国家的其他城市。

数据科学早餐由强大的国际社区——开放数据科学(ODS)提供支持。ODS 团结了数据科学和相关领域的所有研究人员、工程师和开发人员。

引用https://ods.ai/en/的话来说,该社区的目标是:

🔥创建令人敬畏的项目、事件和教育课程
💪分享经验,发展彼此的技能
📈促进开放数据科学,推动该领域向前发展

除了开放式数据科学早餐会,ODS 还在俄罗斯国内外组织了多项活动。

ODS slack 是俄语的,但是内容质量太好了,以至于很多不会说俄语的人都是带翻译来看的。幸运的是,有一个英语电报频道【https://t.me/opendatascience 聚合了主要的数据科学新闻(这仍然是你在 slack 上能找到的一小部分)。

巴黎的 ODS 早餐在 https://t.me/opendatascience和 http://opendatascience.slack.com/的 ODS slack上公布,在#_meetings_france 频道的https://ods.ai/en/获得邀请。你可以在https://data-science-breakfast-in-paris.github.io/找到关于巴黎早餐的各种信息,还可以提出下次早餐https://data-science-breakfast-in-paris.github.io/feedback/要讨论的话题。

在巴黎:开始、成长和未来

混乱办一直在国际上扩展它的触角,一路走来,把全世界的人都变成了数据科学教的忠实追随者。

这一切都是从 ODS 的一名积极分子度假路过巴黎时开始的,他于 2019 年 1 月 5 日在 Malongo 咖啡馆组织了第一次早餐,并在https://t.me/opendatascience上宣布。

The first Parisian ODS breakfast

他告诉我“你应该继续组织它,让它成为一个传统”。我很高兴我说“当然”,因为早餐吸引了许多聪明有趣的人。

有高潮也有低谷,但总的来说早餐是成功的。出现了低出席率和沉默的情况,但早餐一直在加速。对于标题中有数据的帖子来说,这种说法太定性了。当然,你想要更定量的东西。现在…你一直在等待的…女王陛下…数据。丨t丨e丨l丨e丨g丨r丨a丨m丨s丨 group 有 90 人,其中大多数至少参加过一次早餐会,而且人数还在增加:

Breakfast is growing. The sky is the limit?

为什么 DS 早餐社区增长如此稳定?

  1. 社区。它得到了非常强大的国际社会的支持,并通过其强大的渠道公布。
  2. 聚会的好形式,经验证明,世界各地的人都觉得 DS 早餐是一种好形式。
  3. 坚持。我懂得了坚持的重要性。在第一次有 8 个人参加的早餐后,我组织了第二次,只有我和约翰内斯·蒂勒。多么低谷啊!然而,这只是一个开始;我们只是向前看,这是值得的。在我三月底休假期间,也就是四月的前几周,我们有一段不太活跃的时期,但是我们重新变得更强了。我们不仅吃了早餐,还在其他聚会上见过面,还有两次课后活动。如果你现在来吃早餐,你极不可能只看到两个人。最有可能的是,我们会在 7 点左右(查看下面的整个分布)。
  4. 激活社交网络中的一个枢纽,被激活的枢纽会带来新的社区成员。猜猜我们最应该感谢谁?对,是国父基里尔给电报集团加了最多的人(见下文)。我在这场比赛中获得了第二名,第三名被柳波夫·图皮基纳获得。柳波夫为社区建设贡献良多。她是一名研究人员,也是社交网络的枢纽。有趣的巧合是,她恰好发表了网络科学方面的科学论文。

Distribution of the number of people

We should thank them for community development

下面,你可以看到谁会出现在巴黎数据早餐会上。

Demographics that is going to evolve

你很可能会看到俄罗斯人,但几乎总是有不讲俄语的人(至少一个),我们都讲英语,所以每个人都包括在内。我们可以通过吸引更多女性和不会说俄语的人来改进,您也可以加入我们=)

尽管说俄语的人约占 80%(见下图),但我们坚持说英语,总的来说,早餐服务员至少会说 11 种语言:俄语、英语、法语、德语、汉语、西班牙语、拉脱维亚语、葡萄牙语、芬兰语、吉尔吉斯语、阿拉伯语(如果我忘了什么,请原谅,我肯定忘了)。

We still have some work to do on diversity. If you don’t speak Russian, please come

ODS 为它的起源感到自豪,但我们有很大的国际野心,我们想吸引更多的非俄语人士。

We want you to join us!

对于一个技术社区来说,我们在性别平等方面做得并不差(大约 20%的女性),我怀疑我们的一些女性参与者正在策划在 ML meetup 中渗透巴黎女性,并使一些女士皈依 Data 山达基。

Gender balance that is going to evolve

最初,我们不太擅长记住拍集体照,但随着时间的推移,我们已经提高了我们的拍照纪律,并最终养成了稳定的拍照习惯。

Do you see this nice looking coffee on the bottom-right? It tastes very good as well.

坚持住,伙计们!让我们吸引新的聪明人加入我们的数据科学教派:)

这一切将走向何方

早餐的未来是光明的,这取决于社区的集体意志(取决于你!).

前段时间做了一个调查问卷,了解人们的需求。结果如下:

我感谢所有通过填写调查问卷或私下讨论提出想法的人。以下是综合结果:

  • 在一周内准备的,可选的不超过 3 DS 的相关主题列表,以供讨论:新闻,论文,我们一些人面临的问题(为人们提供一种简单的方式来提出一周内的主题,以便人们可以在早餐前投票和思考它)。搞定。
  • 构建关于社区、社区内服务的信息
  • DS 活动:演讲、黑客马拉松等
  • 尝试用周六早餐代替晚上的活动(啤酒?)
  • 职业发展相关活动:面试问题、模拟面试等

未来是光明的,来加入我们在 Malongo 咖啡馆。下周六 10:30 见。

如果您有兴趣在您的城市设立每周 ODS 早餐,请联系我们:【https://t.me/malev

的支持,正则化和套索的特征选择器!

原文:https://towardsdatascience.com/of-suppandi-regularization-and-lasso-the-feature-selector-2a09acfdbc1b?source=collection_archive---------18-----------------------

Suppandi

可以说,没有与印度常青树漫画英雄苏潘迪的会面,任何印度童年都是不完整的。苏潘迪是典型主角的反面角色,几乎每一项分配给他的任务都搞砸了。大多数关于苏潘迪的故事都是从他得到一条建议开始的,然后苏潘迪只是把这条建议应用到一个例子中,他把事情搞砸了,看起来很愚蠢,尽管他在故事的开始学到了新的知识。我认为没有什么比 Suppandi 的故事更好地解释了机器学习算法中的过度拟合问题。

Suppandi 的故事的第一部分几乎相当于机器学习算法的训练阶段,第二部分是测试阶段,他试图应用他的学习,但却完全错误。这就是当 ML 算法试图从每一个数据点学习而不进行归纳时会发生的情况。

过度拟合

在我的上一篇文章中,我谈到了曲线拟合问题中代价函数的选择。当代表性曲线复杂且曲线参数的数量/值较大时,成本函数往往会过度拟合训练样本,如下图所示。那么,我们如何制作“拟合曲线”,既能从训练数据中学习广泛的模式,又能稳健地应用于看不见的数据呢?实现这个看似难以置信的任务的技术被称为正则化。

The green line represents the Overfitting Problem (Image credits)

文献中谈到了三种正则化技术,它们与我们在上一篇文章中看到的Lp-范数有着很深的联系。我们将看到这些正则化函数及其性质背后的直觉,甚至看到它们如何成立的一些数学证明。

How many features are needed for humans to predict price of a house?

所有的正则化技术都是为了减少对太多变量的依赖。回到经典住房问题,输入因子或变量在 80 左右。我们知道,使用所有 80 个特征来预测房价是一种矫枉过正。作为人类,我们最多会考虑 10-20 个因素来估算价格。正则化的作用完全相同-尝试将观察到的样本拟合到曲线,但使曲线函数依赖于较少数量的变量。和前面一样,我们将使用线性回归的例子来更好地理解这一点

岭正则化

实现这一点最简单的方法是干预成本函数。请记住,在上一篇文章中,我们了解到,由于 L₂范数的包容性和可微性,它可能是成本函数的最佳选择。让我们回忆一下 L₂范数成本函数是什么样子的:

m 指的是我们观察到的总数。还记得 h(x)是基于各种输入因子 x 的线性函数。

现在,我们希望曲线受尽可能少的因素影响,而不出现误差激增。因此,我们可以修改成本函数,称为岭成本函数,如下所示:

在这个节骨眼上,你们很多人可能还记得,我们在上一篇文章中看到的新求和项的 L₂范数性质。这样做的目的是尽可能降低 xⱼ的权重或系数,并在此过程中降低这些变量的影响。λ的值越高,对正则化的关注就越大。

看待这个问题的另一种方法是最小化以下成本

符合以下标准(山脊函数)

换句话说,在上述项中,系数取值有上限。

一个有趣的问题出现了,这是否会减少无关因素的影响或完全消除无关变量。为了回答这个问题,我还想介绍另一种正则化技术和对比,正如你将看到的,将更好地揭示这个问题。

套索正则化

这种正则化技术被隐晦地称为 Lasso(“最小绝对收缩和选择算子”),它将成本函数修改如下:

如你所见,山脊和套索的区别就是 L2 范数和 L1 范数的区别。

这个问题可以重新表述为最小化下列成本

符合以下标准(套索功能)

哪个更好?

原来 Lasso 顾名思义是一个选择操作符。因此,从减少对太多因素的依赖和聚焦于最重要信号的角度来看,这样做更好。事实上,当脊函数降低了不相关信号的系数时,Lasso 将它们归零。这是如何发生的——让我们试着看看背后的数学原理。

套索和山脊功能的可视化

让我们先画出这些函数,以便更好地形象化。假设只有两个参数 w1 和 w2。

山脊函数显示为由圆形包围的区域,而套索函数显示为由菱形包围的区域。为了清楚起见,脊函数如下:

在这种情况下(两个变量)

注意,r 是脊圆的半径。

套索函数的公式如下:

在我们两个变量的例子中,套索图基于以下函数:

正如我们将要看到的,这两个函数的几何在它们的特征选择能力中起着重要作用。

此时,需要注意的是 圆和菱形与轴的交点是导致特征选择的点。

成本函数的等高线

现在让我们画出成本函数的等高线——共享相同成本的点(w1,w2)。

绿色椭圆是特定成本值的成本函数的轮廓。回想一下,成本函数如下:

根据轮廓的定义,椭圆边界中的所有点将具有相同的成本值。

在较高的成本值下,轮廓椭圆将会扩展并向山脊/套索功能移动。等值线椭圆与山脊/套索函数的交点将是满足山脊/套索条件的最低成本值。

特征选择-动画

请花一分钟时间观看下面的视频,看看等高线如何与山脊和套索图相交。

如视频所示,轮廓在轴外的一点接触脊圆。然而轮廓在轴上接触套索菱形,导致特征选择发生!

这就把我们带到了一个问题——我的十字路口视频只是一个“被操纵的用例”来突出套索的特征选择吗?这种可能性有多大?

Lasso 多久做一次特征选择?

假设一个随机的椭圆轮廓函数有一个概率 p 在一个特定的轴上相切于脊圆。

Let probability of ellipse tangential to Ridge circle be “p”

这表明脊函数已经完成了特征选择。换句话说,让脊函数的特征选择概率(P_r)为 P。

根据套索函数的几何结构,套索函数的特征选择概率(P_l)

P_l > P_r => P_l > p

(套索正方形完全位于脊圆内,因此与圆相切的椭圆也将与正方形相切)

让我们考虑在轴上与脊圆相交但不相切的椭圆。

Elliptical countours that intersect at the axes

椭圆轮廓与脊线圆以非相切方式相交的概率= 1 - p

请注意,非相切椭圆可能会像上图中的绿色椭圆或黑色椭圆一样相交。

绿色椭圆仍然是套索正方形的切线,但黑色椭圆不是!这意味着除了 p,Lasso 有一个额外的概率来自这样的椭圆。所以问题如下:

椭圆与正方形相切但不与脊线圆相切的概率是多少?

这取决于椭圆的任何部分是否落在蓝色区域内。

蓝色区域的面积由下式给出

因为蓝色区域由围绕原点的 4 个直角三角形组成。

圆的面积由下式给出

随机椭圆的一部分落入蓝色区域的概率由下式给出

这等于

大约是 0.6366

这意味着与脊圆相交的非相切椭圆与套索正方形相切的概率为= 1–0.6366 = 0.3634

P_l = p + 0.3634 (1 — p)

这意味着,即使 P 是零,P_l 也是 0.3634。换句话说,套索方法保证至少在 36%的情况下进行特征选择!

所以给定 Lasso 和 Ridge 是 L-p 范数,学习可以更一般化。我们看到,在删除要素时,Ridge 比 Lasso 更保守一些。随着 p 的降低,特征选择发生了——不太重要的特征开始被丢弃。还想提到的是,有一些技术如弹性网试图在这两者之间取得平衡,我不会在本文中详细讨论。

现在已经学会了套索,我们不禁想,如果我们能给可怜的苏潘迪配备一个套索特征选择器,并帮助他避免在应用阶段的那些尴尬!唉,那样的话,印度不仅会失去一个童年时代的漫画英雄,还会失去一个在我们生命的早期就教导我们需要正规化的人,而我们会从他的错误中吸取教训!苏潘迪虽然成了嘲笑的对象,但毕竟是我们的老师。

首次出现在印度分析杂志上。

去参加比赛

原文:https://towardsdatascience.com/off-to-the-races-f53c95354c07?source=collection_archive---------41-----------------------

靠近赛马场如何影响佛罗里达州禁止赛狗的投票

A greyhound in flight. (Wikipedia: AngMoKio)

2018 年 11 月 6 日,佛罗里达州选民以压倒性多数决定禁止一项近 90 年来合法且有利可图的活动:灰狗赛跑。最初于 1931 年合法化的第 13 号修正案将该州所有赛狗活动的截止日期定为 2020 年 1 月。

在当今这个极度极化的时代,该修正案是为数不多的实际上获得两党支持的提案之一:该修正案由时任州司法部长、共和党人帕姆·邦迪(Pam Bondi)提出,并得到了佛罗里达州民主进步党团、前阿肯色州州长迈克·哈克比(Mike Huckabee)、女性选民联盟(League of Women Voters)、该州年轻的共和党党团的支持——名单在上。那些支持禁令的人聚集在一个核心问题上:动物的福利。灵缇非常轻盈和敏捷,能够在跑道上以堪比汽车的速度翱翔。但是,与汽车不同的是,当他们撞到一起或撞到墙上时,没有安全气囊。自 2013 年有记录以来,数百只动物在佛罗里达州的赛道上被记录死亡。[1]即使它们没有在致命的事故中死亡,也经常发现狗被注射了兴奋剂;类固醇,促红细胞生成素,甚至安非他命和可卡因也经常出现在他们的血液中。

另一方面,所有者和轨道运营商大声争辩说,这些只是少数害群之马。他们声称,关闭铁路会扼杀他们的生计,对他们的社区和国家造成经济影响,并结束一个可以追溯到近一个世纪的传统。另外,他们声称,灰狗被培育成工作犬;据他们说,他们能为狗做的最好的事情就是让它们在安全、可控的环境中比赛。其他人,比如坦帕湾时报认为灰狗赛跑已经过时了。大多数歌曲都没有盈利,而且已经有一段时间没有盈利了;人们已经对赛狗失去了兴趣。他们的观点是,我们还不如等着经济窒息而死。

然而,到了最后,这些争论似乎都没有说服选民。超过 69%的人对这项措施投了赞成票,轻松超过了成为该州宪法一部分所需的 60%的门槛。

这太酷了!但是为什么呢?

作为一名专门研究政治行为的社会科学家,我经常发现自己在观察社会世界的事物时会想“哦,这太酷了!…但是为什么呢?”这次投票是其中的一次,在几个层面上对我来说很有趣。

首先,我注意到围绕这个问题的大部分报道都是关于动物权利的争议以及饲养者和赛道所有者的抵制。虽然这很有价值,但并没有太多关于什么激励了选民———540 万去投票的人声称他们希望这种做法结束。是什么因素激发了他们的立场?为什么他们去投票,为什么这么多人投赞成票?对于许多不同类型的人来说,这显然是一个重要的问题。我认为仅仅从这个角度再深入一点是值得的。

但是当我思考这个问题的时候,我越来越意识到这个问题有一个微妙的角度,这个角度挖掘了选民参与和选择的经典理论的核心。虽然他们的观点遭到了强烈的驳斥(可能是因为他们是多么赤裸裸的自私),但饲养者和所有者在一件事上是正确的:这些赛道可能会给它们周围的地区带来相当可观的经济利益。对于住在附近的人来说,有一种“理性”的动机让他们愿意留在身边。有人研究过选民对在附近修建体育场的投票提案的反应,但据我所知,还没有任何研究关注与现有资源的接近程度如何影响围绕保留资源的投票。

在思考了这些事情之后,有两个问题显得既重要又容易解决:

  1. 靠近铁轨如何影响人们对第 13 修正案的选择?
  2. 靠近铁轨是如何影响人们投票决定第 13 修正案的?

游戏中的一些皮毛

为了透明起见,我不能完全声称对这个话题完全没有偏见。还有一个原因让我想到了轨道如何影响选民选择和参与的问题。我在这场游戏中得到一些皮毛。

当选举日到来时,我在第 13 修正案的选票上留了空白,因为我不认为这个问题应该以某种方式成为我们宪法的一部分;这是一个政策问题,我认为,政策应该通过立法机构通过,而不是成为国家基本宪章的一部分而变得顽固不化。然而,我的妻子对这项禁令投了赞成票。当我读到通过这项法律意味着成千上万的狗将无家可归时,我坚持我们应该收养一只。毕竟,我们的家庭对他们的状况负有部分责任--至少我们可以向至少一个人敞开心扉。(无论如何,这可能符合也可能不符合我收养一只狗的长期愿望……)。

长话短说:见见我们的灰狗,那家伙(或简称为“家伙”)。

Such magnificent animals…

花花公子以“飞行骁龙的名字参赛了近 3 年。“在那段时间里,他参加了 167 场比赛,赢得了其中的近 10%。投票后一个月,他就退休了,尽管不管结果如何,这很可能会发生。赛狗通常在两岁到五岁之间比赛;这家伙上一场比赛只差不到 4.5 英里。

除了为了赌徒的利益而追踪的稀疏指标之外,我们对他头四年半的生活知之甚少。我们知道他可以(现在仍然可以)在三步之内达到将近 40 英里的时速。我们知道他喜欢鸡爪和兔肉干;我们在教他如何上下楼梯时利用了这一点。我们知道他在来我们家之前,到福斯特家的时候就有了他的第一个玩具。我们知道他的腹部和臀部已经秃顶——可能是不可挽回的,最有可能的原因是被迫在没有衬垫的表面上重复躺了太长时间。我们知道他仍然知道发射枪的声音;他僵硬地站着,他的肌肉明显绷紧,就像一个压缩的弹簧在努力解开,无论何时他听到任何声音,从一个散落的烟花到消声器回火。

我们知道他是一个快乐、深情的男孩,他正在享受退休生活。我们知道他很受宠爱,他再也不会缺少玩具和舒适的床上用品了。

我不想暗示所有参赛和拥有这些狗的人都是无情或邪恶的。我知道他们中的许多人非常关心他们的动物,并对他们可能会伤害它们的暗示犹豫不决。但在我看来,这是一个有问题的行业,充满了不正当的激励。我尽最大努力不让这种观点影响我的定量分析,但我不会在处理数据的时候假装自己神奇地破解了它,从而侮辱任何人的智慧。毕竟,它的存在是显而易见的,事实上我甚至选择了首先研究这个主题。我所能做的就是在我分析的每一步中尽可能的坦率和透明。

靠近灰狗赛道会如何影响选民投票率和偏好?

靠近心脏还是太近而不舒服?

一方面,我们可能认为住在铁轨附近(并投票)的人更喜欢让铁轨敞开着。这些赛道产生了大量的金钱,人们可能不想从它们身上获得有价值的经济资源。这与钱袋投票的经典理论相一致:人们投票支持符合自身经济利益的事情。

另一方面,住在铁轨附近的人可能不太支持保持铁轨畅通。在选举期间靠得更近(由于积极分子更活跃,反对这项运动的信息更容易获得)可能会让他们不愿意支持如此接近的争议性事物。毕竟,没有人喜欢觉得自己是虐待动物的同谋;身体上的接近可能会使责任感难以合理化。即使赛道附近的选民支持整个行业,并对动物权利活动家的说法持怀疑态度,他们可能也不希望赛道及其所有争议靠近他们的居住地。简而言之,他们可能不介意灰狗赛跑作为一项事业,但他们可能会优先考虑自己的感受。

鼓舞人心还是令人沮丧的投票率?

就像投票选择一样,是否投票的决定可以通过两种方式由赛道的接近度决定。那些离赛道更近的人可能会对问题更感兴趣,这可能会让他们更有可能就此投票。但这种接近可能意味着他们更加矛盾,在邻避感、经济利益和一系列其他因素之间更加矛盾。矛盾心理意味着人们不会对这个或那个问题有更强烈的感受;如果人们没有强烈地倾向于一个选项而不是另一个,他们一般不太可能就这个问题投票。

简而言之,靠近铁轨可能会以几种不同的方式影响选民在 2018 年的行为。我决定进行调查,如果有的话,经得起审查。在对选民投票率和投票数据进行空间分析后,我发现,平均而言,靠近灰狗赛道会使人们更有可能支持第 13 号修正案,但他们不太可能投票。

接下来的两节详细介绍了我的方法以及如何构造数据。任何仅对结果感兴趣的人都应该跳到分析标题。

我是如何进行分析的

方法

我有几个方法可以解决这个问题。理想情况下,我们可以查看该州每个人如何投票的记录,并将他们居住的地方与最近的赛马场进行比较。如果统计理论是我们唯一的考虑,那至少是理想的。一如既往,它不是。最大、最明显的问题是,这将违反无记名投票。一般来说,人们不希望每个人都知道他们是如何投票的——这对于这种方法是必要的。

另一种可能性是委托对从该州选民档案中随机选择的人进行调查,并询问他们如何投票。然而,虽然调查数据在试图充实人们为什么会这样做时非常有用(我为我的研究设计、实施和分析了调查;你永远也不会听到我大规模地说它们的坏话),当要求人们回忆一年前他们是如何投票的时候,它们可能没有太大的帮助。人们往往会忘记他们的实际立场,并合理化他们投票给了实际获胜的选项。

相反,我使用我为 VEST (投票和选举科学团队)构建的数据,这些数据从每个县(主要由不屈不挠的 Brian Amos 收集和构建)获取选区级形状文件,合并 2018 年每个州级竞选的选区级投票数,并将它们聚合成一个单一的全州文件。这让我可以看到佛罗里达州大约 6000 个选区中每个选区对第 13 修正案的支持程度和投票率,也可以看到它们离该州开放的灰狗赛道有多近。然后,我使用计算社会科学和机器学习中的常用工具线性回归[4]来估计邻近性对选区一级选民行为的影响,并看看这种影响在统计上是否显著。我在 R 中做了这个分析,并在我的 Github 中发布了我曾经这么做的所有代码——尽管我也会在整篇文章中发布代码来展示我是如何得出我的结论的。

数据来源

  • 2018 年佛罗里达州全州选举的背心形状文件
  • 该州开放灰狗赛马场的位置

r 分析所需的软件包

library(ggmap)
library(tidyverse)
library(sf)

准备数据

狗道位置

为了弄清楚靠近该州的灰狗赛道如何影响政治行为,首先可能有助于弄清楚 2018 年各州赛道在哪里。强调过去时态。根据你阅读的对象,2018 年有 11 、 12 或 13 首曲目在运营。2019 年,这一数字已经减少到六(在撰写本报告时)。令人震惊的是,没有一篇新闻报道附有这些痕迹所在位置的详细经纬度坐标。面对这些困惑,我决定去查阅̶t̶h̶e̶̶a̶l̶l̶-̶k̶n̶o̶w̶i̶n̶g̶̶o̶r̶a̶c̶l̶e̶维基百科。具体来说,我查阅了他们关于美国灰狗赛跑的文章,以获得该州所有记录在案的赛道名称。然后,我在谷歌上搜索这些名字,看看是否有任何日期在 2018 年 11 月之前的新闻文章谈到赛道关闭。如果选举的时候铁轨还在运行,我就数了一下。这让我在 2018 年有了 13 条活跃的赛道。[5]然后,我通过谷歌地图找到并记录下了地点的经纬度坐标。这些可以在上面的链接中找到,并通过阅读 csv 加载。

tracks <- read_csv("dogtracks.csv",col_names = T)

辖区地图

一旦我们确定了 2018 年该州有多少条赛道(以及它们位于何处),我们就可以继续加载佛罗里达州的选区形状文件。如上所述,我使用了sf库中的st_read函数。因为背心数据不记录 z 坐标(询问一个选区的海拔高度和询问单手鼓掌的声音一样有意义),所以我让 R 知道我们不需要担心这个特定的维度。

FL.2018.Precs <- st_read("VEST18Gen.shp")FL.2018.Precs<-st_zm(FL.2018.Precs, what = "ZM")

然而,我们所做的需要担心的是,我们如何将灰狗赛道(一个点)的位置与投票区(一个多边形——而且通常是怪异的、看起来不规则的多边形)进行比较。我选择实现的解决方案是测量从选区中心(也称为质心)到最近轨道的距离。这归结为假设选区质心代表住在那里的选民的平均家庭地址。严格地说,这不是 100%真实的。有时质心暗示人们正生活在一个无人居住的区域的正中央,像一个湖,一个森林,或者——以真正佛罗里达人的方式——一个沼泽。但是,没有人口普查数据或地理参考州选民登记文件中的每一项记录,这是一个有用的假设,反映了我们能够合理做到的最好情况。

幸运的是,st包也有st_centroid函数,正如它的名字所暗示的那样:寻找数据帧中所有空间对象的质心。

prec.cents<- st_centroid(FL.2018.Precs)

使用ggplotgeom_sf的组合,我们可以浏览一下所有这些质心的位置。

cent.pic<-ggplot()+geom_sf(data = FL.2018.Precs, fill = "#E8EAE8")+
  geom_sf(data = prec.cents, color= "#0856AF", size = .7)+theme_nothing()+
  ggtitle("Centroids of Florida's 2018 Election Precincts")+
  theme(plot.title = element_text(hjust = .5, size = 14))

cent.pic

这些点融化成无定形斑点的地方显示了许多选区紧密聚集在一起的区域。非巧合的是,这些也是该州人口最稠密的地区。

质心和狗轨迹之间的距离

现在我们已经有了选区的中心和该州狗的足迹的位置,我们正准备比较两者之间的距离。首先,我们必须让 R 知道tracks数据帧应该作为一个空间对象而不是一个标准数据帧来读取。

如果我们查看我收集的关于该州的轨迹的信息,我们可以看到地理信息以两列表示:经度()和纬度(纬度)。st_as_sf函数将使用这两列将其转换成空间数据。

tracks<- st_as_sf(tracks, coords = c("long","lat"),crs = 4269)

您会注意到,我为一串看似随机的数字设置了一个名为“crs”的选项。CRS 代表 C 坐标 R 参考 S 系统——是试图将一个 3D 球体展平为一个 2d 矩形的必然结果。卡尔·弗里德里希·高斯是第一个明确证明球体不可能在没有某种扭曲的情况下变成平面的人。[6]CRS 指定了我们正在使用的许多普遍的、方便的变形中的哪一种。4269 将其设置为联邦政府的标准 NAD83。我们需要将轨道的 CRS 设置为与区域质心相同,否则我们将无法充分比较它们之间的距离。

prec.cents.crs<-st_crs(prec.cents) #CRS for the Precinct Centroids

tracks.right.crs<-st_transform(tracks,prec.cents.crs) #Transforms the tracks spatial data to the right coordinate system.

现在数据可以相互关联了,我使用st_distance函数来测量区域质心和狗轨迹之间的距离。这创建了一个大矩阵(我将其命名为track.cent.dists),其中每行代表一个选区的质心,每列代表一条灰狗路线。该值是它们之间的距离,单位为米([m])。我将track.cent.dists转换成一个数据帧(我称之为dists.df)。我放了前五列和前五行的快照,让大家对它有个大概的了解。

track.cent.dists<-st_distance(prec.cents,tracks.right.crs) #Distance matrix

dists.df<-as.data.frame(track.cent.dists) #Converts into dataframe

选区质心和狗轨迹之间的最短距离

shapefile 中大约 6100 个区域中的每一个都与 13 个距离相关联;每个状态 13 对应一个距离,然后运行轨道。虽然这些信息很有趣,但我只对最近的轨道的距离感兴趣:也就是说,最小的距离。如果我只使用mutate并基于所有列(V1,V2,V3...V12,V13)像这样:

dist.min<-dists.df %>%
  mutate(mindist =  min(V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13))%>%
  select(mindist)

这会给我 6100 行 330.274 米的长度——这是投票区和赛狗场之间最短的距离。相反,我需要逐行选择最小值。tidyverse 中有一个非常方便的函数rowwise可以让我做到这一点。(我还将这个数字除以 1609 米,得到更符合美国标准的英里数)。[7]

dist.min<-dists.df %>%
  rowwise()%>%
  mutate(mindist =  min(V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12,V13)/1609) %>%
  select(mindist)

因为每个分区是按照它在质心数据帧中列出的顺序进行评估的,所以我们可以恢复使用cbind分配的分区标识符 VEST。

dist.min.ids<-cbind(dist.min, Pct_std = as.character(prec.cents$Pct_std))

然后,我们可以使用这些 id 与原始辖区状态文件中的数据合并。(在处理空间数据时,注意使用sp::merge而不是普通的merge!)

Spatial.Doggies <- sp::merge(x = FL.2018.Precs, y = dist.min.ids, by = "Pct_std")

投票选择和投票率

准备数据进行分析的最后一步是构建我的选区级投票选择和投票率的衡量标准。对于这些,我依靠最初在背心数据中发现的变量,这些变量现在在我称为Spatial.Doggies的数据框架中。对于投票选择,我将对第 13 号修正案的赞成票(G18AM13Yes)除以对该修正案的总票数(G18AM13Sum)。对于投票率,我将第 13 修正案的投票数除以该地区登记人数(SumRegis)。我将这个值编码为 1(相当于 100%的投票率),以说明除了那些在选区登记的人之外,还有哪些县计算了在选区投票的人。[8]我还删除了一个不包含任何数据的选区名称,它似乎被棕榈滩县用来指定空选区(PAL00NP)。

Spatial.Doggies <- Spatial.Doggies %>%
  mutate(per.yes = G18AM13Yes/G18AM13Sum,
         doggy.turnout = G18AM13Sum/SumRegis,
         doggy.turnout = case_when(
           doggy.turnout > 1 ~ 1,
           TRUE ~ doggy.turnout
         ))%>%
  filter(!(Pct_std == "PAL00NP"))

分析

第一眼

使用我们构建的数据和ggplot,我们可以看到距离如何影响投票选择和投票率。下图显示了距离如何影响第 13 号修正案的区级支持(左)和投票率(右)。

总的来说,该州的大多数选区都非常支持这项措施:平均支持率为 68.5%,与该州 69.0%的总体水平非常接近。在该州 75%以上的选区,它清除了成为该州宪法一部分所需的 60%的门槛。然而,即使有这种普遍的支持,橙色趋势线也显示了一个非常清晰的模式:该辖区越靠近灰狗赛道,支持禁止它们的投票者就越多。

投票率的情况要稍微复杂一些。2018 年的选举投票率非常高;自第一次世界大战前以来,我们还没有过这么高的中期投票率。这也让很多人——至少相对而言——对灰狗事件进行了投票;全州平均每个选区的投票率为 59.4%。但是越靠近铁轨的选区,投票率反而越高,估计投票率最低。数据显示了一种曲线模式,当我们远离最接近的位置时,投票率会上升,但一旦我们超过一个临界点,投票率就会开始下降。这可能是因为附近的人对赛道感到矛盾,阻止他们投票,而远处的人距离太远,无法强烈感受到这种或那种方式。

更精致的外观

虽然这很有启发性,但故事肯定会更加复杂。回顾该州赛马场所在的地方,似乎只有距离这些赛道 120 英里以外的地方是相当偏远的。狗和跑道的主人声称比赛是他们传统的一部分;这可能是一个更容易被该州农村地区的人们接受的论点,因为从历史上看,该州这些地区的居民往往不屑于政府对他们遗产的干预。另外,可能还有其他混淆因素。也许这个辖区更自由?即使该修正案是由该州当时的共和党司法部长提出的,动物权利也往往是自由主义者和进步人士更热衷的一项事业。也许他们更有可能支持修正案,因为他们已经参加了该州的州长或参议员竞选?赛狗可能不是人们特意去投票的事情,但如果他们已经出来了,为什么不去做呢?

这就是 OLS 回归派上用场的地方。OLS 越来越多地用于数据科学中(也是近半个世纪以来定量社会科学中的主力),它使研究人员能够估计特定变量的独立影响,同时保持模型中包含的所有其他变量不变。它有一些奇妙的统计属性,让它做到这一点(至少当一切正常时[9])——但对于这项研究的意图和目的,我们需要知道的是,它让我们看到当我们控制其他相关因素时,距离的影响是否仍然显著。

可惜这方面马甲数据欠缺。通常对于投票率和投票选择的研究,最好的做法是控制年龄、种族、性别、党派 ID、性别、教育水平、对政治的兴趣、对问题的感受,或者至少尽可能多的控制这些事情(以及其他事情)。背心数据没有任何心理变量——这有点超出了项目的范围——也没有任何描述性变量。理论上,应该可以从 2018 年开始获取该州的选民登记文件,并估计选区级别的特征。事实上,这实际上是项目的下一个计划步骤,我可以节省几个小时。有一些可行的替代概念,为理论提供了一个体面的测试。具体来说,选区面积(乡村性的代表)、注册选民的数量(选区人口的代表)、注册选民和选区面积的商(人口密度)、投票给民主党州长候选人 Andrew Gillum 的选区百分比(选区级政党 ID)以及州长竞选的投票率(向下投票刺激)。接下来的几行代码将这些变量添加到Spatial.Doggies数据帧中。

Spatial.Doggies <- Spatial.Doggies %>%
mutate(area = st_area(Spatial.Doggies),
      voter.density = SumRegis/area,
      gperc = G18GOVDGil/G18GOVSum,
      gturn = G18GOVSum/SumRegis,
      gturn = case_when(
        gturn > 1 ~ 1,
        TRUE ~ gturn
      ))

下一步是构建一组线性回归,将选区一级的投票选择和投票率作为结果变量。

choice.reg <- lm(data = Spatial.Doggies, per.yes ~ mindist + area + voter.density + gperc+ gturn +SumRegis)

turnout.reg <- lm(data = Spatial.Doggies, doggy.turnout ~ mindist + area + voter.density + gperc+ gturn +SumRegis)

上表显示了回归模型的结果和变量的统计显著性。(对于那些不熟悉回归模型的人:估计列中的正数意味着该数字的增加与结果变量的增加有关;阴性结果与结果的减少有关。符号显著性栏中的数字越小,表示统计显著性程度越高)。在解释选区的支持水平和投票人数时,离铁轨的距离具有统计学意义。一个选区距离最近的轨道每 10 英里,该措施的平均支持率就会下降约 1.1 个百分点。这与选民希望铁轨远离他们的隐喻后院的想法是一致的——从这一分析中还不清楚是因为越来越多的关注还是仅仅为了避免头痛。每 10 英里的距离,该选区的投票率预计会高出 0.2 个百分点。这与选民在这个问题上更加矛盾的想法是一致的;他们很可能受到迫使他们投赞成票和反对票的担忧的交叉压力,所以他们选择根本不投票。这两个值很容易超过传统的统计意义水平;我们可以很有信心,最近的赛道里程的影响不是零。这些数字看起来并不多,但当考虑到关于说服和投票效果的文献时,这是正常的高端——尽管这通常专注于个人水平,而不是投票区,所以这有点像苹果和橘子。

(作为一个有点书呆子气的统计题外话:即使我没有我喜欢的所有变量,模型仍然在解释结果方面做得很好。道岔模型的 R 为 2 . 36— —这实际上对社会科学研究来说相当不错——而道岔模型中的 R 2 约为 0 . 95,这是非常高且极其罕见的。这些数字意味着我的模型分别解释了结果中 36%和 95%的差异——这意味着即使是这些简单的模型也能很好地解释选区一级的投票选择和投票率。它总是可以改进的,但我相当有信心,这里观察到的关系至少是在正确的大方向上。)

为了总结我的分析,我决定将该州的每个选区可视化,基于它们相对于该州其他地区是否有低、中、高投票率以及低、中、高支持度[10]。我正在为另一个帖子保存我是如何制作这张地图的,但我认为它实在太酷了,不能不分享。

灰狗的下一步是什么?

尽管投票本身已经成为历史,但这个故事还远未结束。赛道和狗主人目前正在起诉该州,声称该州的宪法修订委员会违反宪法针对他们的行业。他们认为,至少,他们应该得到他们的动物和/或财产的价值补偿。一位主人声称他们的每只狗价值高达 5 万美元。如果是这样的话,那我们就有一个绝对便宜的家伙了。我们只花了 300 美元就从我们的本地灰狗救援美国分会领养了它,它给我们生活带来的快乐让这 5 万美元看起来微不足道。(相信我,考虑到我的学生贷款,我不会轻易这么说……)

也就是说,大多数观察家(包括我自己)认为,这些所有者从政府那里获得接近这一数额的可能性非常小。2018 年绝大多数选民发出信号,他们不希望灰狗赛跑在该州继续进行;这些资金将直接来自他们的税收,这可能会激怒他们。

很难争取到这些人真正想要的支持:废除死刑。在投票率很高的一年里,第 13 号修正案在该州大部分地区以压倒性的支持获得通过。甚至和其中一条赛道在同一个选区的选民也不倾向于投票让它们继续开放。这可能不一定是因为他们不同意赛狗的想法——来自辖区一级的投票率的证据与我们在附近的人高度矛盾的情况下看到的一致——但在离家这么近的地方有争议的事情是有代价的。

至少在佛罗里达,灰狗赛跑已经走到了尽头。

Peter R. Licari 是佛罗里达大学政治学博士生,专攻美国政治行为和政治方法论。所表达的意见是他自己的。在YouTube和推特(@ PRLPoliSci)上也能找到他。剩下的一点点业余时间都花在了长跑上,和他耐心的妻子斯蒂芬妮玩电子游戏,遛狗,和他的猫亚洲进行奇怪的富有成效的单边对话。

[1]也很少有证据表明这些数据是完整的。事实上,缺乏一丝不苟的记录是动物保护主义者的抱怨之一

2

[3]选区是由郡维持的地区,以便更好地管理选举。一般来说,人们根据选民登记中列出的地址被分配到特定的选区投票。每个选区可能有几个到几千人登记投票。

[4]我选择了线性回归而不是逻辑回归,因为尽管我使用了比例,但我无法获得潜在值的模式(由于无记名投票)。我可以想象使用 tobit 回归,但是没有审查的证据——价值观通常受到合理的约束。

[5]顺便说一句,这也让我拼凑出了歧义,因为即使是维基百科也注意到了 2018 年的 11 首歌曲。几条赛道由同一家公司运营,位于杰克逊维尔地区之外。对我的分析来说,重要的是人们在狗赛跑的地方附近--所以我坚持 13 这个数字。

[6]地图的应用显而易见,但由于地球不是一个完美的球体,这变得更加复杂。

[7]现任和前任田径运动员们,没错:一英里不是 1600 米。是 1609 以上的一毛。事实证明,很少有人真正记录过一英里赛跑的时间,而不是 1600 英里。这可能看起来很迂腐,但这意味着比世界纪录慢了 1.3 秒。

[8]在任何人过早行动之前(双关语):这并不意味着人们在错误的选区投票就犯了欺诈罪。有些县在允许人们投票的地方比其他县更宽松。人们很少去错误的地方——选民欺诈更是少之又少——所以这是数据中一个不幸但微不足道的错误。

[9]出于好奇,我还运行了控制误差项中地理聚类的模型。结果基本相似。

[10]我把低和高都定义为偏离平均值超过一个标准偏差。中等,然后,在 1 个标准偏差差异之内