TowardsDataScience-博客中文翻译-2016-2018-四十-

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

TowardsDataScience 博客中文翻译 2016~2018(四十)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

用于数据插值的无监督深度学习

原文:https://towardsdatascience.com/unsupervised-learning-for-data-interpolation-e259cf5dc957?source=collection_archive---------9-----------------------

使用前馈自动编码器的数据去噪

Image by Author

真实世界的数据是嘈杂的。噪声可能以不正确或缺失值的形式出现。本文描述了用自动编码器填充缺失值的方法。自动编码器在没有参考值可用于缺失条目的噪声数据上被训练。该程序是对图像重建的任务进行解释。该方法过去已成功应用于地震数据重建。Tensorflow 实现可用这里的

问题概述

想象一下这样一种情况:数据丰富,但是数据有噪声,并且无法访问参考。一个很好的例子是图像,如图 1 所示。这里,图片中的黑点是噪声——图像值设置为 0,我们假设没有它们可用的地面真实数据。数据类型不限于图像,可以是任何东西,例如,丢失部分数据的患者记录。

****

Figure 1: Example of corrupted data. In the given example images have 0’s in places where pixels are missing. Images are taken from the Standard Test image dataset.

理想情况下,如果具有参考的训练数据可用,我们可以通过将重构与目标进行比较来训练网络重构缺失值。但是在没有目标数据的情况下,这是不可能的,因为将重构与 0(即缺失值)进行比较是没有意义的。在这里,我讨论了一种在没有参考资料的情况下训练自动编码器完成数据重建任务的方法。

理论概述

这一节简要回顾了神经网络和自动编码器。

神经网络

简单的前馈人工神经网络(ANN)有几层。第一层是输入层,输入数据。接下来是一些隐藏层。最后是输出层。层由基本单元组成— 神经元。一层中的神经元与下一层中的神经元相连。在训练过程中优化了两种参数类型:权重,对应于每条连接神经元的边,以及一个偏差关联于每一个神经元。因此,神经元的输入是前一层神经元的加权输出和偏差的线性组合。通过激活函数,例如 sigmoid ,将神经元的输入映射到一个新的空间,从而获得神经元的输出。回归的任务可以与特征学习的任务相关。在人工神经网络中,一个特征是隐层中单个神经元的输入连接。

Figure 2: A simple feed forward neural network. Image by Author.

训练是一个迭代过程,分为两个阶段:前馈和反向传播。前馈是将数据输入到输入中,并通过人工神经网络向前传播,从而产生输出的过程。对于每一层,该过程可以描述为:

y=s(Wx+b),

其中 x 是当前层的输入向量, y 是当前层的输出, W 是权重矩阵,其中Wki=Wkiw kix i

Figure 3: A single neurone. Image by Author.

在前馈通过之后,需要评估目标函数,并且需要估计使其最小化的参数。一种常用的优化方法是 随机梯度下降 (SGD)或 亚当 优化器。

自动编码器

这项工作考虑了基于自动编码器的人工神经网络。这种选择是合理的,因为它旨在消除任何关于数据的先验假设。简单的自动编码器只有一个隐藏层,其单元数少于输入数。深度自动编码器由具有非线性激活函数的多个隐藏层形成。这种结构允许在人工神经网络的更深层学习抽象特征和复杂关系。

一个自动编码器被拆分成一个编码器- f 和一个解码器 g 。编码器的目的是将 D 维输入 x 映射到通常更低的 K 维特征空间,即f(x)=h。解码器旨在将特征空间映射回原始空间,从而重构输入,即g(h)=g(f(x)=r(x)~x****

缺少值的培训

因为没有给出信号丢失部分的参考值,所以训练神经网络仅重建信号的未被破坏部分。被破坏的数据被输入到神经网络中,然而,仅用于未被破坏的数据点的重建的误差被评估并用于反向传播。该过程基于这样的假设,即面片具有不同的噪声分布。如果在当前迭代的反向传播中没有使用信号值,则输入到神经网络中的后续面片将丢失不同位置的值。因此,在当前迭代中未更新的权重在下一次迭代中被更新。

Figure 5: Training with missing data. Edges marked with red colour are not updated in the given iteration. Image by Author.

由于在基于给定值的训练期间监控重建的良好性是有偏差的,所以对数据应用附加的二进制验证掩码。验证掩码包含 2%的噪声,并被投影到数据上。我确保数据中缺失的值和验证掩码中值为 0 的值不会重叠。在训练期间使用被验证掩码破坏的点。在每个时期之后,使用参考值计算被验证掩码破坏的值的误差。每当验证误差达到局部最小值时,保存网络的当前配置,并继续训练。

算法

该算法包括七个阶段(图 2)。首先,对数据进行预处理——在 0 和 1 之间进行缩放,并分割成小块。下一步,补丁通过人工神经网络。然后计算干净数据的误差,并更新参数。在下一阶段,使用验证掩码计算验证误差。如果 ANN 达到了局部最小值,则保存网络的当前状态。如果 ANN 不在其最小值,则跳过这一步。在下一步中,超参数被更新并且数据被混洗。如果满足停止条件,即达到最大历元,则获得缺失数据的重建,否则继续训练。

Figure 6: Algorithm stages. Image by Author.

结果

具有低频分量的图像比具有高频分量的图像重建得更好,即更复杂的场景更难重建。当使用更大的片时,即网络具有更多信息时,重构更好。最差的重建是在碎片的边缘和角落,那里的像素有五个或三个邻居,而在碎片的中心,像素被八个邻居包围。一种可能的解决方案是使用更大尺寸的补片,并且仅使用中心部分进行重建。这项工作可以通过使用 CNN 处理图像来改进,并在 RGB 图像上进行测试和应用于其他数据类型。

House: 30% missing(left) reconstructed (center) reference (right). 16x16 patches, 8 pix shift, averaged. Images are taken from the Standard Test image dataset.

Room: 50% missing(left) reconstructed (center) reference (right). 32x32 patches, 16pix shift, averaged. Images are taken from the Standard Test image dataset.

Lena: 50% missing(left) reconstructed (center) reference (right). 32x32 patches, 4pix shift, averaged. Images are taken from the Standard Test image dataset.

Baboon: 50% missing(left) reconstructed (center) reference (right). 32x32 patches, 4pix shift, averaged. Images are taken from the Standard Test image dataset.

Peppers: 70% missing(left) reconstructed (center) reference (right). 32x32 patches, 4pix shift, averaged. Images are taken from the Standard Test image dataset.

Lena: 90% missing(left) reconstructed (center) reference (right). 32x32 patches, 2pix shift, averaged. Images are taken from the Standard Test image dataset.

Lena 50% missing: reference (left) reconstructed (center) RMSE heatmap (right). 32x32 patches, 4pix shift, averaged. Images are taken from the Standard Test image dataset. The error map is generated by the author

看不见的数据

有趣的是,网络是否能够泛化,即在一幅图像上训练并重建另一幅图像。正如所料,当重建的图像与用于训练的图像相同时,重建会更好。下面是两个例子:网络训练狒狒和重建辣椒和训练辣椒和重建狒狒。

Peppers trained on baboon: 50% missing(left) reconstructed (center) reference (right). 32x32 patches, 4pix shift, averaged. Images are taken from the Standard Test image dataset.

Baboon trained on peppers: 50% missing(left) reconstructed (center) reference (right). 32x32 patches, 4pix shift, averaged. Images are taken from the Standard Test image dataset.

SELU 自动编码器(不是另一个 MNIST)上高斯混合模型的无监督学习

原文:https://towardsdatascience.com/unsupervised-learning-of-gaussian-mixture-models-on-a-selu-auto-encoder-not-another-mnist-11fceccc227e?source=collection_archive---------1-----------------------

MNIST 是一个经典的机器学习数据集。想象以下场景:

Figure 1 - Alien who cannot understand human handwritten digits images

你是一个不了解人类文化的外星人,出于某种原因,你设法从手写数字数据集中获取了所有图像(MNIST)。因为你是一个外星人,你不知道人类数字的概念是什么,或者他们相应的符号看起来像什么,仅仅通过分析图像数据,你必须猜测有多少不同的符号(数字)(如果可能的话,生成新的表示,而不是仅仅复制你已经有的表示)。在机器学习中,这个问题可以被看作是:“如何在有限混合模型中选择正确数量的组件”

有限混合模型是一种聚类算法,其目的是在除了观察值之外没有其他信息可用时确定数据的内部结构。

Figure 2 — Number 5

对 MNIST 进行聚类的第一个问题是,每个 28×28 像素的图像意味着每个数字有 784 个维度。

大多数聚类方法都受到维数灾难的困扰。这样,为了执行无监督学习,降维方法是必要的。此外,如标题所示,高斯混合模型将用于聚类的学习(这意味着压缩空间的高斯行为越多,拟合就越好..)

Figure 3 — SELU auto encoder with regularization to enforce space constraints (promote structure?)

SELU 是一种新的神经网络激活函数,具有自归一化的特性。如果我们制作一个经典的自动编码器并将激活函数切换到 SELUs,压缩空间收敛到一个明确定义的均值和方差。也许,代表压缩空间的一些分布将是高斯分布的,并且可以被高斯混合模型很好地捕获。在编码层上使用 L2 正则化来约束其权重空间。由于高斯拟合将在这一层上进行,这一约束连同仅使用 6 个神经元的事实将产生信息瓶颈,这将有利于数据的结构化表示。

首先,让我们通过绘制 pairplot(一个 6 维的 pair plot)来检查压缩空间的分布:

Figure 4 — Compressed Space Pairplot

该空间是通过将 MNIST 数据集从 784 维(28×28 像素)的图像压缩到 6 维空间而产生的。看起来终究还是有些高斯行为!请记住,autoencoder 无法访问标签,它们被包含在 pairplot 中的唯一原因是为了让我们对可能的集群有一个参考。

但是现在,一个问题出现了:如何为高斯混合模型选择正确的分量数?虽然有许多成本函数可以用来选择适当数量的组件,如贝叶斯信息标准(BIC)或阿凯克信息标准(AIC),但有算法可以为我们做这种选择(而不必为每个组件数量执行不同的拟合)。其中之一是在本文中提出的有限混合模型的无监督学习

为了适应高斯混合模型,通过自动选择组件,我将使用一个实现(仍然是 WIP ),它是我根据那篇论文的见解(我基本上将我教授的 Matlab 代码转换为 Python 代码)制作的。) Github 包

这段代码是使用 sklearn 范式构建的,并且可以与该库一起使用,因为它实现了 ModelTransformer。

Figure 5 — Training the autoencoder on the MNIST dataset and fitting the Gaussian Mixture Model

可以使用图 5 中的代码将高斯混合模型拟合到压缩空间,同时使用最小消息长度标准选择适当数量的组件。

模型拟合后,可以从高斯混合模型中采样新图像(在压缩空间中),每个分量代表这些图像的不同概念(数字!).采样的压缩空间通过之前训练的 SELU 解码器,输出是从高斯混合模型采样的新生成的数字。

恭喜你,你已经成功地使用了你的外星人算法,现在可以复制和创造人类的手指了!

下面的每个图都是从不同的高斯分量中采样的,

您可以创建您的外星人 0:

Figure 6 — Alien generated 0’s by learning what human digit 0 is

你可以创建你的外星人 1:

Figure 7— Alien generated 1’s by learning what human digit 1 is

你可以创造你的外星人 2:

Figure 8— Alien generated 2’s by learning what human digit 2 is

你可以创造你的外星人 9:

Figure 9— Alien generated 9’s by learning what human digit 9 is

10 个集群是描述所有数字图像的最佳选择,这是有道理的。但是如果你仔细想想,就很容易理解为什么一个聚类算法会识别一些 9 和 4 之间的相似性,为这个事件创建一个特定的聚类。请记住,由于这是一个高斯混合,这个群集可以完全包含在 4 和 9 的群集内!

聚类算法居然找到了 21 个聚类!你可以在用于这种介质的 jupyter 笔记本中查看它们。

“聚类结构的验证是聚类分析中最困难和最令人沮丧的部分。如果不朝这个方向努力,聚类分析将仍然是一门黑色艺术,只有那些有经验和巨大勇气的真正信徒才能接触到。”贾恩和杜贝斯(贾恩和杜贝斯,1988 年)

顺便说一句,这是一个很酷的聚类算法在一个玩具示例中的可视化效果:

Figure 10 — Unsupervised Learning of Gaussian Mixture Models

用来生成这个介质的代码这里是这里是。

无监督机器学习

原文:https://towardsdatascience.com/unsupervised-machine-learning-9329c97d6d9f?source=collection_archive---------8-----------------------

今天,我们就来看看一些无监督的机器学习吧!什么是无监督机器学习?

无监督学习是机器学习的一个分支,它从没有被标记、分类或归类的测试数据中学习。无监督学习不是对反馈做出反应,而是识别数据中的共性,并根据每个新数据中是否存在这种共性做出反应。备选方案包括监督学习和强化学习。

对我们来说,我们将举一个非常基本的例子,并试图理解这是如何工作的!我们将使用来自sk learn:Iris 数据集的内置数据集!

  1. 萼片长度,单位为厘米
  2. 萼片宽度,单位为厘米
  3. 花瓣长度(厘米)
  4. 花瓣宽度(厘米)
  5. 类别:
  • 刚毛鸢尾
  • 彩虹鸢尾
  • 海滨鸢尾

The Flowers in the Dataset

如果你还没有弄明白,这个数据集正在描述花!所以今天,我将用这个数据集直观地向你们展示无监督机器学习是如何工作的!

算法:

我们将使用聚类算法:

聚类是一种无监督学习的方法,是许多领域使用的统计数据分析的常用技术。在数据科学中,我们可以使用聚类分析,通过查看我们应用聚类算法时数据点属于哪些组,从我们的数据中获得一些有价值的见解。

特别是,我们将使用 K-Means

Kmeans 是最流行的“聚类”算法之一。K-means 存储 k 个用于定义聚类的质心。如果一个点比任何其他质心更靠*特定聚类的质心,则该点被认为是在该聚类中。

K-Means 通过在(1)根据当前质心将数据点分配给聚类(2)根据当前数据点分配给聚类选择质心(作为聚类中心的点)之间交替来寻找最佳质心。

我将展示我们如何通过这个 K = 5 的算法。这是我们迭代 Kmeans 算法的第一步:

First iteration of Kmeans

现在我们有了这些集群,我们需要做几件事情:

  1. 将最*的每个聚类分配给其最*的点
  2. 通过*均所有聚类的位置来更新中心。

请注意我是如何绘制 2 个维度的,虽然有 4 个维度,但这给了我一个很好的视觉理解。

下面是更新每个中心的伪代码算法。

将初始聚类分配给它们最*的点

现在我们已经了解了我们的算法如何找到最*的点并将它们分配给聚类,让我们看看第一次迭代后的曲线图:

Assigning each cluster the closest points

在我们分配这些点之后,我们希望继续更新每个聚类,直到我们收敛于一个解决方案。我跳过了几次迭代,但是正如你所看到的,这些点收敛得非常快!

下面,我提供一些用于更新中心的伪代码!

Updated the centroids centers

这是一个非常直观的算法示例,下面我为大家提供完整的算法

完整的算法定义

κ均值聚类算法使用迭代优化来产生最终结果。算法输入是聚类数κ和数据集。数据集是每个数据点的特征集合。算法从对κ质心的初始估计开始,这些质心可以是随机生成的,也可以是从数据集中随机选择的。该算法然后在两个步骤之间迭代:

1。数据分配步骤:

每个质心定义一个聚类。在此步骤中,根据*方欧几里得距离,将每个数据点分配到其最*的质心。更正式地说,如果 ci 是集合 C 中质心的集合,那么每个数据点 x 被分配给一个基于

其中 dist ( )为标准( L 2)欧氏距离。设具有群集质心的每个的数据点分配集为 Si

2。质心更新步骤:

在这一步中,质心被重新计算。这是通过取分配给该质心簇的所有数据点的*均值来完成的。

该算法在步骤一和步骤二之间迭代,直到满足停止标准(即,没有数据点改变聚类,距离的总和最小化,或者达到某个最大迭代次数)。

这个算法保证收敛到一个结果。结果可能是局部最优(即,不一定是最好的可能结果),这意味着用随机化的起始质心来评估算法的多次运行可能会给出更好的结果。

有问题吗?!请在评论中告诉我!一如既往,在 twitter 上关注更多精彩内容@ElliottSaslow

PyTorch 启动和运行—迷你批处理、数据加载和模型构建

原文:https://towardsdatascience.com/up-and-running-with-pytorch-minibatching-dataloading-and-model-building-7c3fdacaca40?source=collection_archive---------6-----------------------

我现在已经尝试了几个深度学习框架——tensor flow、Keras、MxNet——但是,PyTorch 最*成了我的首选工具。这并不是因为我认为它在客观上比其他框架更好,而是因为它感觉更简洁、直观,更适合我的学习和实验风格。

这篇文章介绍了 PyTorch,重点是构建一个简单的神经网络(前馈网络)来分离(即分类)一些玩具数据中的两个类。我的目标是介绍 PyTorch 的一些基本构建模块,同时强调深度学习如何用于学习非线性函数。这篇文章的所有代码都是这个 github repo 。这是一个更实际的帖子,如果你正在寻找 PyTorch 内部工作的游览,我强烈推荐这个帖子。

为了跟进,确保您的机器上安装了 PyTorch 。请注意,我使用的是版本 0.3.1.post2,pytorch 的下一个版本(0.4)将引入一些突破性的变化(在这里阅读它们)。同样值得关注的是 PyTorch 1.0 的发布,它的目标是“生产就绪”——我对此非常兴奋!。

这篇文章的学习任务是二元分类问题——将点分类成半月形。对于深度学习模型来说,这是一个简单的任务,但它可以突出他们学习复杂的非线性函数的能力。

例如,如果我们使用逻辑回归对这些数据进行分类,看看会发生什么:

尽管对预测输出应用了 softmax 变换(将预测输出 logits 压缩到总和为 1),但逻辑回归的参数是线性的,因此很难了解非线性关系。我们可以使用一个更高级的 ML 模型来完成这个任务,比如随机森林,但是这样我们就没有借口去玩神经网络了!

在构建模型之前,我们将首先创建一个定制的数据预处理器和加载器。在这个例子中,转换器将简单地把 X 和 y 从 numpy 数组转换成 torch 张量。然后,我们将使用 dataloader 类来处理数据如何通过模型传递。注意,我们必须为这个类定义 lengetitem 方法。

在这种情况下,我们将设置一个小批量例程。这意味着在每个时期,模型将对数据的小子集(批次)进行训练,也就是说,它将根据与每个小批次相关联的损失来更新其权重。这通常是比每个时期在完整数据集上训练更好的方法。使用较小的批次也是可取的——尽管这是一个超参数,所以要做实验!

定义模型

使用 PyTorch 定义深度学习模型的标准方法是将网络封装在一个类中。我非常喜欢这种方法,因为它确保所有的层、数据和方法都可以从单个对象访问。该类的目的是定义网络的体系结构,并管理通过网络的数据转发。为了定义模型,我们需要继承 nn.Module。

典型的方法是将层定义为变量。在这种情况下,我们定义一个单层网络。nn。线性函数需要输入和输出大小。在第一层中,输入大小是输入数据中特征的数量,在我们设计的例子中是两个,输出特征是隐藏层中神经元的数量。

输出层的输入是前一层中神经元的数量,输出是数据中目标的数量——在本例中是两个。

然后我们定义一个类方法forward来管理网络中的数据流。这里我们调用数据上的层,并在隐藏层上应用relu激活(来自 torch.nn.functional)。最后,我们对输出应用 sigmoid 变换,将预测值压缩为 1。

运行模型

接下来我们需要定义模型如何学习。首先我们从类中实例化一个模型对象,我们称之为model。接下来我们定义成本函数——在这种情况下是二进制交叉熵——更多信息请参见我之前关于日志损失的帖子。最后,我们定义我们的优化器,Adam。优化器将优化我们模型的参数,因此,params参数就是模型参数。

现在我们准备训练模型。我们将这样做 50 个时代。我已经对代码块进行了注释,以清楚地说明每个阶段发生了什么。我们设置了一个 for 循环来迭代数据(epoch ),每个 epoch 循环一次存储在ds中的小批 X 和 y,这是我们之前定义的。在每个循环中,我们制作输入和目标火炬Variables(注意,在 pytorch 的下一个版本中,这一步是不必要的,因为torch.tensorsVariables将被合并),然后指定向前和向后传递。

正向传递使用模型参数来预测输出。在第一遍中,预测将接*随机,因为参数是用随机数初始化的。在这一步中,我们使用实例化的成本函数计算与模型相关的损失。

在正向传递中,我们使用模型来预测给定 X 的 y,计算损失(和准确度)。所以我们只是通过模型传递数据。在反向传递中,我们通过模型反向传播损失,并且optimiser.step根据学习率更新权重。

我们可以看到损失迅速减少(波动性可以用小批量来解释),这意味着我们的模型正在工作——太棒了!您还可以看到模型学习的非线性决策区域。

此外,检查模型学习的决策区域:

很明显,神经网络可以学习数据的非线性特性!

摘要

这篇文章的目的是展示如何开始使用 pytorch 定义神经网络。这里定义的模型非常简单,但目的是突出构建模块。我也没有运行测试循环,所以我们不知道模型的测试性能。在我的下一篇文章中,我将定义一个更复杂的 pytorch 模型,敬请关注!

感谢阅读。

原载于 2018 年 5 月 3 日conorsdatablog.wordpress.com

提升您的数据科学简历—通过 ATS

原文:https://towardsdatascience.com/up-level-your-data-science-resume-getting-past-ats-64322f0cbb73?source=collection_archive---------12-----------------------

这个系列将深入探讨如何制作一份有效的简历来获得电话。当我调查我的电子邮件列表时,人们对简历最关心的三件事是:

  • 能够通过 ATS(申请人跟踪系统)
  • 写出强有力的要点,而不是列出“工作职责”
  • 如果你以前没有从事过数据科学工作,该如何定位自己

本文是涵盖上述主题的三部分系列文章的第一部分。今天我们将讨论如何通过 ATS。

如果你不熟悉 ATS,它代表申请人跟踪系统。如果你是直接在网站上申请一个职位,而该公司是中大型的,那么你的简历很可能会在以下时间之前通过 ATS:

1.你的简历在人力资源部的收件箱里

2.您会收到一封自动发送的电子邮件,内容如下:

很难代表所有的 ATS 系统,因为有许多 ATS 系统。看看 indeed.com 和 https://www.indeed.com/hire/ats-integration T2 集成的 ATS 系统的数量就知道了。

那么如何确保自己有很大的机会通过 ATS 呢?

1.让你的简历很有可能被 ATS阅读

2.丰富关键词,因为 ATS 寻找的是与工作相关的关键词

可由 ATS 读取:

最*出现了一种创造这些设计华丽的简历的运动。你会看到人们“表格化”他们的简历(即使用表格创建简历),包括徽标,或包括图表,这些图表是他们在某些技能方面的知识水*的主观图表。其中一个图表的示例如下所示:

ATS 不知道如何处理这些点,就像它不知道如何处理一个标志、你的图片或一张桌子一样;不要使用它们。要测试你的简历是否能被 ATS 很好地解析,试着复制文档并粘贴到 word 中。可读性强吗?还是有一堆其他的东西?你也可以试着把它存成纯文本,看看是什么样子。

作为一个喜欢数据的故事讲述者,我理解你想要展示你能够使用可视化来创建一份富有美感的简历的渴望。如果你是通过你的关系网申请,而不是在公司网站上,也许你会考虑这些风格。我不会假设我知道你的网络和他们在找什么。当然,你可以有多份简历,以备不时之需。

什么是可解析的:

我在数据世界里看到过一些博客帖子,说的是“没人想看那些无聊的旧简历。”然而,那些无聊的简历很可能在 ATS 中获得更高的分数,因为这些信息是可解析的。你可以创建一份美观、经典的简历。

一些旧的 ATS 系统只能解析。多克还是。docx 格式,其他人将能够解析。pdf,但不是所有的元素。如果你尝试使用上面提到的图片类型,pdf 将是可读的。

用关键词丰富你的简历:

这有两种形式:

1.确保这些职位描述中提到的技能在你的简历中用 JD 中的措辞明确地显示出来。

2.减少简历中“无关紧要”的内容。如果你的项目符号简洁,关键词和绒毛的比例会更高,会帮助你得分更高。

对于第一点,我在简历的顶部特别提到了我的技能:

我还会在简历的要点中特别提到这些项目和技能。如果一份工作描述需要逻辑回归,我会在简历中特别加入逻辑回归。如果 JD 只要求“回归”,我会在简历中把它列为回归。你明白了。

同样重要的是,在阅读职位描述时,不仅仅是技术技能很重要。公司正在寻找还能做到以下几点的员工:

  • 与企业沟通
  • 跨职能工作
  • 在适当的层次上向接收信息的受众解释结果。

如果你申请的是一个管理职位,你将会在与管理者素质相关的关键词上得分。职位描述是了解他们想要什么样的品质的正确起点。我会在我即将推出的简历课程中突出具体的例子。

对于第二点,你要让你的要点尽可能简洁。通常以动词开头,提及动作和结果。这将帮助你获得尽可能高的“关键词:一切”的比率。

在我这个系列的下一篇文章中,我将分享如何为换工作做好准备的建议。那篇文章在这里。

如果你在寻找数据科学领域工作的帮助,或者需要简历方面的帮助,我想推荐你去找凯尔。我很了解凯尔,这是他的人生目标!。他帮助数据科学家获得数据科学职位。你可以在这里观看他谈论这个话题的视频。

原载于 2018 年 8 月 20 日【datamovesme.com】

使用*衡数据升级您的图像分类器

原文:https://towardsdatascience.com/upgrade-your-image-classifier-with-balanced-data-ddea93859c0f?source=collection_archive---------6-----------------------

预处理和分层如何对图像分类器的性能产生奇迹

FER

本文将带您了解数据管理技术,以完善图像分类器的机器学习模型,特别是面部情感识别。包含源代码的 R notebook 可以在 GitHub 链接这里找到

在这个项目中,“面部情感识别”数据集,来自 Kaggle 竞赛 表征学习中的挑战:面部表情识别挑战 被使用。该数据由 27000 幅训练图像(48×48 像素的面部几乎居中,使得所有面部在图像中的相等空间上延伸)和包含 9000 幅图像的测试集组成。这是一个分类任务,将每张图片分为七类(0 =愤怒,1 =厌恶,2 =恐惧,3 =快乐,4 =悲伤,5 =惊讶,6 =中性)。

我尝试了几种算法,包括最*邻、贝叶斯分类器、决策树和神经网络,为这项任务建立机器学习模型。但是,他们中没有一个人的回报率超过 30%。这让我想知道哪里出了问题,以及如何以不同的方式完成这项任务。最*我看到了一篇文章,作者是植物幼苗分类挑战赛的一位顶级选手,文章建议读者在对图像进行分类之前,先处理不*衡的分类问题。

在这篇文章中,我将解释如何使用干净*衡的数据和可视化,用决策树算法构建一个更好的图像分类器。

第一步:浏览数据

在可视化数据集中每个类的分布时,我们知道数据集是严重不*衡的。

如果类不是*似相等的,则数据集被描述为不*衡的。[1]

Distribution of classes

有超过 7000 张“快乐”的图片,而“厌恶”的图片不到 500 张。这将导致有偏差的分类器将大多数图像预测为多数类。

决策树和逻辑回归等流行算法偏向于数据集中的大多数类[2]

为了理解算法的复杂性,我应用了技术t-分布式随机邻居嵌入 (t-SNE),这被认为是可视化高维数据的最佳方法。

t-SNE 是一种用于相似性数据可视化的技术,能够保留数据的局部结构,同时也揭示一些重要的全局结构,例如多尺度的聚类[3]

t-SNE 通过在二维或三维地图中给出每个数据点的位置来可视化高维数据[3]

原始数据集的 tSNE 可视化向我们展示了数据的类结构。

t-SNE Original Dataset

第二步:分区

下一步是将训练数据集划分为训练集和验证集。验证集将用于调整,最终模型将使用测试数据集进行评估

第三步:创建基准分类器

该基准为评估和比较从示例中学习的算法提供了基础。[4]

如果我们在这个阶段创建一个基准分类器,性能将低于 27 %。

Benchmark Classifier Results

第四步:数据预处理

在可视化一个随机实例时,很明显图像是水*对齐的,并且还存在一些噪声作为背景。

预处理方法对从非受控环境中获取的图像进行归一化。[5]

因此,所有的图像首先旋转和裁剪,如下图所示。

Fig: Sample Image (i) Original (ii) Rotated (iii) Cropped

然后将实例居中并缩放到范围{0.8,1.2}。变换前后每个像素中的值分布可以绘制为。

Distribution of values in each pixel

步骤 5:特征提取

这是一个拥有 2304 个特征的高维数据集。为了降低维数,我们可以使用最广泛使用的技术 PCA。

主成分分析(PCA)是一种统计过程,它使用正交变换将一组可能相关的变量(每个变量取不同数值的实体)的观察值转换为一组称为主成分的线性不相关变量的值。[6]

PCA Output

从主成分分析总结中可以清楚地看出,前 25 个主成分拥有超过 80%的数据。

PCA Summary

主成分分析后的 tSNE 可视化明显更好,但大多数类别的映射有点接*,没有清晰地分类。

t-SNE PC 1–25

相同的预处理步骤和来自 PCA 的正交旋转被应用于验证数据和测试数据

第五步:分层

在这一步中,我们将处理训练数据中的不*衡类问题。

SMOTE 是一种过采样方法,其中少数类通过创建“合成”样本进行过采样,而不是通过替换进行过采样[1]

少数类的合成过采样(SMOTE)和多数类的随机欠采样的组合将给出良好*衡的训练数据,该训练数据然后可用于构建执行得更好的分类器。从下面新列车数据的 tSNE 可视化中可以明显看出这一点

t-SNE Balanced Data

第六步:分类

我们使用准备好的训练数据建立分类器。从模型的混淆矩阵中,我们可以看到整体的准确率有所提高,接* 60 %。

Confusion matrix — Classifier trained using the processed data

第七步:超参数调整

通过调整复杂性参数(cp ),我们可以减少相对误差,如下图所示

Variation in Relative error with complexity parameter

第八步:建造最终模型

最后一步是用调整后的参数(具有最小 Xval 相对误差的 cp 值)构建最终模型,并使用测试数据对其进行评估。

混淆矩阵统计表明,分类器的性能有了显著提高,总体准确率超过 90 %。灵敏度、特异性等其他性能指标也更好。

Confusion Matrix — Final model

Other Performance metrics comparison for various classes

结论

预处理、降维和*衡数据集显著提高了决策树分类器的性能,从 27%提高到 91%。使用 tSNE 可视化高维数据可以让您更好地了解类的分布,这对于预处理可用于构建更好的分类器的数据非常有帮助。

参考文献

[1] N. Chawla,k .鲍耶,L. Hall 和 W. Kegelmeyer, SMOTE:合成少数过采样技术 (2002),《人工智能研究杂志》,第 16 期,第 321–357 页。

[2]客博,如何处理机器学习中的不*衡分类问题 (2017),【博客】Analytics Vidhya

[3] L. van der Maaten 和 G.Hinton,使用 t-SNE 可视化数据 (2008),《机器学习研究杂志》,第 9 期,第 2579-2605 页。

[4] Z. ZHENG,分类器学习的基准 (1993),澳大利亚人工智能联合会议。世界科学,第 281-286 页。

[5] M.G. Sumithra 和 P. Rajeswari,A Survey:Pre Processing techniques for face Expression Recognition(2015),《信息与通信工程应用国际期刊》第 1 卷:第 1 期:2015 年 1 月,第 47–51 页,第 1(1)卷,第 47–51 页。

[6]En.wikipedia.org,主成分分析 (2018),【在线】维基百科

深度学习能源前景的起伏

原文:https://towardsdatascience.com/ups-and-downs-of-deep-learning-energy-landscapes-6d5741c12877?source=collection_archive---------20-----------------------

Vincent van Gogh, The Starry Night, 1889, MoMA The Museum of Modern Art

尽管在行业中被广泛采用,但我们对深度学习的理解仍然滞后。

[20]由[21]很好地总结,确定了四个研究分支:

  • 非凸优化:我们处理一个非凸函数,但是 SGD 有效。为什么 SGD 甚至会收敛?
  • 过度参数化和泛化:深度神经网络如何避免维数灾难?

理论家们一直认为,拥有成千上万个神经元的网络,以及它们之间数量级更多的单独加权连接,应该会遇到一个基本问题:过度参数化【19】

  • 深度的作用:深度如何帮助神经网络收敛?深度和概括有什么联系?[21]
  • 生成模型:为什么生成对抗网络(GANs)如此有效?我们可以用什么理论性质来稳定它们或避免模式崩溃?[21]

在这一系列文章中,我们将关注两个方面:

  1. 损失函数的拓扑分析
  2. 最小值的宽度或*坦度

1.损失函数拓扑

[1]是一个很好的起点:作者将深度神经网络的经验风险函数与 H-球形自旋玻璃模型联系起来。

自旋玻璃模型似乎是一个非常丰富的研究方向的伟大起点。我们应该走这条路吗?[4]普鲁登斯警告说:

这个基于损失函数拓扑的理论图有几个缺点。首先,机器学习的最终衡量标准是泛化精度,而不是最小化损失函数,损失函数仅捕捉模型与训练数据的拟合程度[……]其次,根据经验,较深的最小值比较浅的最小值具有较低的泛化精度

在继续我们关于损失函数拓扑的工作之前,让我们看看什么是极小值的*坦性。

2.最小值的*坦性

考虑[5]中讨论的图 X 中的卡通能源景观(经验损失函数)。

robust and non-robust minima [5]

[5]注意,在参数的贝叶斯先验下,比如分别在位置 x_robust 和 x _ non-robust 的固定方差的高斯分布,较宽的局部最小值比右边的尖锐谷具有更高的边缘化可能性。换句话说,[5]指出,位于更宽的局部最小值(如 x_robust)中的参数可能比全局最小值具有更高的损失,应该比那些简单地位于全局最小值的参数概括得更好[9]。

*坦度的定义是什么?[6]概述了宽度(*坦度)的定义。定义包括:

  • 一个*坦的最小值作为权重空间中的一个大的连通区域,其中误差保持*似恒定【7】
  • 着眼于临界点周围损失函数的局部曲率的定义。特别是编码在 Hessian 特征值中的信息(谱范数,迹线)〔5〕
  • 局部熵[5]

我发现局部熵的概念在解释极小值的“*坦性”时非常有说服力和教育性。

从实践的角度来看,局部熵控制权重,这是显式正则化所尝试的:权重正则化(衰减)、丢弃和批量范数正则化。

*坦度=泛化?

在上一节中,通过查看局部熵,我们试图对定义一个好的解决方案的尝试有一个感觉。关于*面度的最佳定义仍然没有一致的意见。[6]指出

然而,当遵循*坦性的几个定义时,我们已经表明,*坦极小值应该比尖锐极小值概括得更好的结论在没有进一步的上下文的情况下不能照原样应用。以前使用的定义没有考虑到一些常用的深层架构的复杂几何结构。特别地,由对称性引起的模型的不可识别性允许人们改变最小值的*坦性而不影响它所代表的函数。此外,误差表面相对于参数的整个几何形状可以在不同的参数化下任意改变。本着[18]的精神,我们的工作表明,需要更加小心地定义*坦度,以避免所研究模型的几何形状退化。这种概念也不能脱离模型或输入空间的特定参数化

换句话说,*坦度的精确定义是一个活跃的研究课题,可以用来建立推广的充分必要条件[17]。

此外,虽然显式优化*坦度可能会有所帮助(正如我们在局部熵的情况下看到的),但从经验证据来看,DNN 和 SGD 可以完成这项工作,即使没有正则化的太多帮助。

What happens when I turn off regularizers? [16]

这鼓励了对深度学习经验损失函数的拓扑的研究。我们没有浪费时间去理解 Choromanska 等人的工作。H-球形自旋玻璃模型是非常有用的起点,并在深度学习研究人员的工作、统计物理学和随机矩阵理论之间建立了联系。

然而,正如作者自己在[11]中指出的,[1]依赖于相对粗糙的假设。然而,研究继续取得进展:[12]表明,在轻度过度参数化和类丢失噪声的情况下,具有一个隐藏层和分段线性激活的神经网络的训练误差在每个局部最小值处为零。[13]表明,在限制较少的假设下,每个局部最小值都是全局最小值,并且每个不是全局最小值的临界点都是鞍点。[12]和[13]中的结果得到了经验证据:例如,见[14],其中作者认为作为一阶特征,我们认为经验风险的景观只是一个(超)盆地的集合,每个盆地都有一个*坦的全局最小值

Over-parameterization? [15]

在下一篇文章中,我们将会看到[12],[13]以及麻省理工学院的 Tomaso Poggio 的工作([14],[15]);我们将尝试在损失函数拓扑研究、极小值*坦性和过度参数化的作用之间建立联系。

参考

[1] Choromanska,Anna 等人,“多层网络的损失表面”人工智能与统计。2015,链接

[2] Torben Krüger,讲义,研究生研讨会:随机矩阵、自旋眼镜和深度学习链接

[3]奥芬格、安东尼奥、热拉尔·本·阿鲁斯和 jiří·切尔内。"随机矩阵和自旋玻璃的复杂性."纯数学与应用数学通讯66.2(2013):165–201链接

[4]张,姚等,“机器学习中的能量-熵竞争与随机梯度下降的有效性”分子物理(2018):1–10链接

[5] Chaudhari,Pratik 等,“熵-sgd:偏向梯度下降进入宽谷” arXiv 预印本 arXiv:1611.01838 (2016)。链接

[6] Dinh,Laurent,et al .“ arXiv 预印本 arXiv:1703.04933(2017)链接

[7] Hochreiter、Sepp 和 Jürgen Schmidhuber。“*极小值。”神经计算9.1(1997):1–42。链接

[8] Martin,Charles“深度学习为什么有效:来自理论化学的观点”,MMDS 2016 链接

[9]] G. E. Hinton 和 D. Van Camp,《第六届计算学习理论年会论文集》(ACM,1993)第 5-13 页。

[10]内里·梅尔哈夫。"统计物理和信息理论."通信和信息理论的基础和趋势6.1–2(2010):1–212。链接

[11] Choromanska、Anna、Yann LeCun 和 Gérard Ben Arous。"公开问题:多层网络损耗面的景观."学习理论会议。2015 链接

[12] Soudry,丹尼尔和 Yair Carmon。"没有坏的局部极小值:多层神经网络的数据独立训练误差保证." arXiv 预印本 arXiv:1605.08361(2016)链接

[13]川口健二。“没有可怜的局部极小值的深度学习。”神经信息处理系统的进展。2016.链接

[14]廖、、托马索·波焦。"理论二:深度学习中经验风险的前景." arXiv 预印本 arXiv:1703.09833(2017)链接

[15]张,,等深度学习理论 sgd 的泛化性质。大脑、思维和机器中心(CBMM),2017 链接

[16]本·雷希特在 ICLR 2017 上的演讲,链接

[17] Sathiya Keerthi,深度神经网络中优化和泛化之间的相互作用,第三届真实世界机器学习年度研讨会,链接

[18] Swirszcz、Grzegorz、Wojciech Marian Czarnecki 和 Razvan Pascanu。"深度网络训练中的局部最小值."(2016) 链接

[19] Chris Edwards,深度学习在噪音中寻找信号,ACM 通讯,2018 年 6 月,第 61 卷第 6 期,第 13-14 页链接

[20] Sanjeev Arora,走向深度学习的理论理解,ICML 2018 链接

[21] Arthur Pesah,更好理解深度学习的最新进展第一部分链接

城市声音分类第 1 部分:声波、数字音频信号

原文:https://towardsdatascience.com/urban-sound-classification-part-1-99137c6335f9?source=collection_archive---------3-----------------------

Photo by Sora Sagano on Unsplash

距离我上次发帖已经有一段时间了。到目前为止,我主要写的是 NLP,但我应该承认,我的关注点非常狭窄。到目前为止,我已经写了 19 篇帖子,其中 13 篇是关于 NLP 的,更具体地说是情感分析。尽管它包含了许多次要任务来达到情感分类器的目标,但最终目标仍然是情感分析。当然,我离专家还差得很远,还有很多东西要学,但是为了让我的数据科学学习更加多样化,我转向了另一种类型的数据。

除了我将附上的简短代码块,你可以在这篇文章的末尾找到整个 Jupyter 笔记本的链接。

音频数据

在我尝试任何事情之前,我想做的第一件事是更好地了解这个新朋友。什么是声音?为了对我将要处理的数据有一个基本的了解,我必须先了解基础知识。

这种声音是耳朵可以听到的空气中的压缩和稀薄的声音。声音是空气的运动。通常以波形表示,显示空气粒子随着时间的推移来回移动的情况。垂直轴表示空气如何相对于零位置向前或向后运动。横轴表示时间。

以上解释摘自 Youtube 视频。他很好地解释了声音、采样和奈奎斯特定理。但是等等,声音的波形看起来是上下移动,但是他说的是前后移动。我错过了什么?老实说,我在这里花了很长时间来理清头绪。可能是基础物理,但我在学校期间并没有太关注物理课。我从没想过这件事会回来困扰我。

从这里开始,这将是一个介绍性物理的回顾,所以如果你已经熟悉它,你可能会发现这篇文章的内容有点太基础了。

我们经常听到一个术语“声波”,是的,声音是一种波。那什么是“波”呢?波是振动,它将能量从一个地方转移到另一个地方,而没有物质被转移。根据波的不同特性,存在不同种类的波。这里我就说其中的两种:横波和纵波。

Image courtesy of www.difference.wiki

横波是一种介质粒子在垂直于能量传输方向的方向上移动的波。你可以想象一根拉伸的绳子,通过一端上下移动来发送波。纵波是一种波,其中介质的粒子在*行于能量传输方向的方向上移动。从上图可以想象,slinky 就是一个例子。在拉伸 slinky(一端固定)的情况下,如果您握住 slinky 的另一端并来回移动 slinky,这将传递一个看起来类似于上图左侧的波浪。

横波的一个例子是水,纵波的一个例子是声音。然后我就迷茫了。好的,我现在知道声音是纵波,但是为什么我看到所有的声音曲线看起来都像横波?

你可能看过上面的图。在上图中,A、C 是音高,440HZ、535.25HZ 是它们的频率。经过大量的谷歌搜索,我终于找到了。顺便说一句,如果这对你来说太初级了,我很抱歉。但对我来说,这是一个灵光乍现的时刻。

对该图的不正确理解是,当空气分子从声音发出的地方到声音被听到的地方穿越空间时,它们会上下运动。这就好像一个特定的分子从声音的源头开始,最后到达听者的耳朵里。这不是声波图中所描绘的。从声源传到听者耳朵的是能量,而不是空气分子本身。

当我们听到声音时,我们不会像风一样让空气分子撞击我们的耳朵。我们只是听到声音,那是因为空气是传输能量(声音)的介质,而介质本身并没有被传输。因此,我们从声波图中看到的波不是绘制空气的上下运动,而是绘制空气粒子的压缩和稀薄。声波图中看起来像波峰的实际上是空气分子靠得很*的压缩,看起来像波谷的实际上是稀疏,空气分子更分散。按照同样的逻辑,看起来像*衡(y 轴上的 0)的是声音产生之前的环境压力。

数据集:UrbanSound8K

有了对声音和声波图的基本理解,我们可以看一看我们的数据集。数据集名为 Urbansound8K。

https://serv . cusp . NYU . edu/projects/urban sound dataset/urban sound 8k . html

您可以找到有关如何绘制类和收集数据的更多信息,但为了让您对数据有一个简短的概述,“此数据集包含来自 10 个类的 8732 个带标签的声音摘录(< =4s):空调、汽车喇叭、儿童玩耍、狗叫、钻孔、发动机空转、枪击、手提钻、警笛和街头音乐

根据原始论文,声音节选自 www.freesound.org,并且已经预先整理成十叠以供交叉验证。

让我们先来看看元数据。

import pandas as pd
import numpy as npdata = pd.read_csv("UrbanSound8K/metadata/UrbanSound8K.csv")
data.shape

data.head()

元数据包含 8 列。

  • 切片文件名:音频文件的名称
  • fsID:从中提取摘录的录音的 FreesoundID
  • 开始:切片的开始时间
  • 结束:时段的结束时间
  • 显著性:声音的显著性等级。1 =前景,2 =背景
  • 文件夹:该文件被分配到的文件夹编号(1–10)
  • classID:
    0 =空调
    1 =汽车喇叭
    2 =儿童玩耍
    3 =狗叫
    4 =打钻
    5 =发动机空转
    6 =枪火
    7 =手提钻
    8 =汽笛
    9 =街头音乐
  • 类别:类别名称

音频数据已经被切片和摘录,甚至分配到 10 个不同的文件夹。一些摘录来自相同的原始文件,但不同的切片。如果来自某个记录的一个切片在训练数据中,而来自同一记录的不同切片在测试数据中,这可能会错误地增加最终模型的准确性。由于最初的研究,这也已经通过将切片分配到折叠中来处理,使得来自相同自由声音记录的所有切片进入相同的折叠中。

现在让我们看看每个折叠的类分布,看看数据集有多*衡。

appended = []
for i in range(1,11):
    appended.append(data[data.fold == i]['class'].value_counts())

class_distribution = pd.DataFrame(appended)
class_distribution = class_distribution.reset_index()
class_distribution['index'] = ["fold"+str(x) for x in range(1,11)]
class_distribution

好的,看起来数据集不是完全*衡的。我们来看看总余额。

data['class'].value_counts(normalize=True)

与其他 8 个类别相比,有两个类别(汽车喇叭,枪支射击)的条目数量略少于一半。它看起来并不严重不*衡,所以目前,我已经决定不考虑这两个少数民族类的任何数据增加。

下面我定义了两个函数,首先获取 WAV 文件的完整路径名及其标签,然后用附加信息绘制波形,还可以用音频播放器播放声音文件。在我进入任何细节之前,让我们先绘制一个声音文件,看看它显示了什么。

fullpath, label = path_class('100263-2-0-117.wav')
wav_plotter(fullpath,label)

我已经简要地提到了声波的特征,但是我仍然没有看到数字音频信号的概念。没有对数字信号的理解,就很难理解所有这些信息的含义(采样率、比特深度等)。因此,请允许我绕道谈谈数字音频的基础知识。同样,如果这对你来说太初级,请随意跳过。

采样率、位深度

音频信号是连续的模拟信号,计算机不可能处理这种连续的模拟数据。它首先需要被转换成一系列的离散值,而“采样”就是这样做的。“采样率”和“位深度”是离散化音频信号时最重要的两个要素。在下图中,你可以看到它们与模数转换的关系。在图中,x 轴是时间,y 轴是振幅。“采样率”决定了采样的频率,“位深度”决定了采样的详细程度。

我们以 CD 为例。正常情况下,CD 的采样率为 44.1khz,深度为 16 位。首先,44.1khz 的采样率告诉我们每秒采样 44100 次。16 位告诉我们,任何样本都可以从与其幅度相对应的 65,536 个值中选取一个值。与 8 位相比,16 位的采样比 8 位的采样详细 256 倍。顺便说一下,如果你想知道为什么 CD 有 44.1khz 的采样率,我推荐我上面提到的同一个 Youtube 视频。它将让您对采样、混叠和奈奎斯特定理有一个直观的了解。

通道的数量告诉我们有多少个通道。当使用 2 个声道时,我们称之为立体声,当只使用一个声道时,我们称之为单声道。当然,单声道声音可以用多个扬声器播放,但它仍然是通过扬声器播放的信号的完全相同的副本。另一方面,立体声是用同一音频信号的两个不同输入通道录制的。我们通常看到的是左右立体声,这给了我们方向性、透视性和空间感。

现在我们有了一些重要的拼图来理解 WAVav 文件的元数据告诉我们什么。

采样率与 CD 质量相同,44.1khz,位深度也与 CD 质量相同。是立体声,从剧情上也能看出来。绿色表示一个通道,而蓝色表示另一个通道。这是一个 4 秒钟的剪辑。由于采样率为 44.1khz,持续时间为 4 秒,我们可以很容易地将 44100 乘以 4 计算出数据中的样本数,即 176400。

但坏消息是。再看一下 Urbansound8K 上的信息,有一条备注写着“WAV 格式的 8732 个城市声音的音频文件(见上面的描述)。采样率、位深度和声道数与上传到 Freesound 的原始文件相同(因此可能因文件而异)。”

啊哦。这意味着数据中可能有许多不同的采样率,这意味着即使持续时间相同,样本数量也会不同。这听起来不适合用来建立模型。此外,不同的位深度意味着它们可以取不同的取值范围。其中一些可能是立体声,而另一些是单声道。这听起来也不太好。

我花了大部分时间来复习声音信号的基本概念。在下一篇文章中,我将继续我的声音数据准备之旅,希望会涉及更多的编码。

感谢您的阅读。你可以从下面的链接中找到代码的 Jupyter 笔记本。

https://github . com/tthustlea/urban _ sound _ class ification/blob/master/urban _ sound _ class ification _ part 1 . ipynb

城市声音分类第 2 部分:采样率转换

原文:https://towardsdatascience.com/urban-sound-classification-part-2-sample-rate-conversion-librosa-ba7bc88f209a?source=collection_archive---------3-----------------------

Photo by Thomas Ribaud on Unsplash

这是我正在进行的城市声音分类项目的第二部分。你可以从下面的链接找到以前的帖子。

  • 第一部分:声波、数字音频信号

在上一篇文章的结尾,我刚刚意识到数据中的声音文件可能会有不同的采样率、位深度、不同文件的声道数。首先,让我从每个声音文件中提取这些信息,看看分布情况如何。

*除了简短的代码块之外,我还会在本文末尾附上整个 Jupyter 笔记本的链接。

声音数据格式调查

我在之前的帖子中没有解释清楚,但是在 WAVE 文件中,不仅有采样的声音数据,还有所有关于数据格式的信息。下图显示了 WAVE 文件中可用的信息类型。

Image courtesy of http://soundfile.sapp.org/doc/WaveFormat/

除了我在上一篇文章中定义的 path_class(从每个文件名构建完整的路径名)函数之外,我还将添加一个函数 wav_fmt_parser,以便从每个 WAVE 文件中提取我需要的三种信息,通道数、采样率、bit_depth。

现在,我们可以使用 wav_fmt_parser 函数向数据框添加额外的信息,以查看数据集中存在哪种不同的数据类型,以及它们是如何分布的。

wav_fmt_data = [wav_fmt_parser(i) for i in data.slice_file_name]
data[['n_channels','sampling_rate','bit_depth']] = pd.DataFrame(wav_fmt_data)
data.head()

data.sampling_rate.value_counts()

data.n_channels.value_counts()

data.bit_depth.value_counts()

从上面来看最令人担忧的是采样率。通道数可以通过仅从一个通道提取数据,或者取两个通道值的*均值来准备。比特深度是每个样本可以取的值的范围的问题,直觉上感觉可以通过考虑比特深度内它可以取的最大值和最小值来归一化这些值来准备。(警告:这只是我的直觉,我可能漏掉了一些陷阱。我越来越多地阅读和了解 DSP,我发现事情并不像我想象的那么简单)

采样率转换

我做采样率转换的原因是为了转换数据,使它们都具有相同的形状,并且易于用机器学习模型进行处理。但在现实生活中,采样率转换的用例要多得多。例如,典型的录音室录音音频为 192khz,要将此录音制作成 CD,应重新采样为 44.1khz 的 CD 采样率,不同的媒体可能有不同的采样率要求(DVD 的采样率为 48khz)。

我们看到大部分数据的采样速率为 44.1khz。假设我们想将数据重采样到 22.05khz,为什么呢?44.1khz 的音频质量更好,但对于声音分类来说,22.05khz 足以捕捉声音的差异。如果每个数据的大小变成其原始大小的一半,我们的模型将会更快。数据集中还存在其他采样速率,但首先让我们考虑最简单的情况,将音频从 44.1khz 重新采样至 22.05khz。

乍一看,这似乎并不复杂。22.05 正好是 44.1 的一半,由于采样率意味着从原始声音中获取样本的频率,感觉我们可以跳过每隔一个样本来获得原始采样率的一半。不要!我会告诉你当你这么做的时候会发生什么。

例如,让我们创建一个简单的正弦扫描。正弦扫描是一种信号,其频率随时间从起始频率变化到结束频率。如果我们创建一个起始频率为 20hz、结束频率为 22.05khz 的正弦扫描,持续 10 秒钟,我们可以听到音调随着时间的推移而增加的声音。

from scipy.signal import chirp
import soundfile as sffs = 44100
T = 10
t = np.linspace(0, T, T*fs, endpoint=False)w = chirp(t, f0=20, f1=22050, t1=T, method='linear')
sf.write('sine_sweep_44100.wav', w, fs)plt.figure(figsize=(15,3))
plt.specgram(w, Fs=44100)
plt.colorbar()
_=plt.axis((0,10,0,22050))
ipd.Audio('sine_sweep_44100.wav')

上面你看到的是正弦扫描的频谱图,x 轴是时间,y 轴是频率。通过播放实际的音频文件,你可以很容易地猜出声谱图显示的是什么。
它显示了随时间变化的频谱。由于我们的正弦扫描从 20hz 开始,您可以看到开始时红线从低电*开始,然后它的音调上升,直到达到 22.05khz。

如果我们简单地跳过每隔一个样本,将采样速率减半,会怎么样?

down_sampled = w[::2]
sf.write('sine_sweep_downsampled.wav', down_sampled, 22050)plt.figure(figsize=(15,3))
plt.specgram(down_sampled, Fs=22050)
plt.colorbar()
_=plt.axis((0,10,0,22050))
ipd.Audio('sine_sweep_downsampled.wav')

刚刚发生了什么??音调不再持续增加,而是先增加后减少。我唯一做的是跳过每隔一个样本,但我没有改变其他任何东西。

为了解释发生了什么,我们需要理解奈奎斯特采样定理。根据奈奎斯特定理,采样速率的一半,即奈奎斯特极限,是可以精确表示的最高频率成分。因此,在采样速率为 22.05khz 的信号中,它可以代表的最高频率为 11.025khz,但我们的原始正弦扫描频率(音高)增加到 22.05khz,因此所有那些无法用 22.05khz 采样速率(频谱范围为 11.025khz 至 22.05khz)表示的额外能量都进入了负频率,并产生了递减的正弦扫描。

在这种情况下,信号首先需要通过低通滤波器进行转换,然后每隔一个样本进行选择。取决于两个采样率的比率,这将使事情变得更加复杂。此外,在上采样的情况下,我们可能需要插值来获得原始采样信号中不包含的样本。

我之所以举上述例子,是为了向您展示在处理数字信号数据时的一些注意事项。但是这篇文章的目的不是为采样率转换创建一个新的包。那我们该怎么办?幸运的是,我们已经有了一个名为 Librosa 的很棒的库,它会为我们完成所有的转换,万岁!(Librosa 中实际的采样率转换部分由重采样默认完成,或者由 Scipy 的重采样完成)

利布罗萨

现在让我们从数据集中选择一个文件,用 Librosa 和 Scipy 的 Wave 模块加载同一个文件,看看它有什么不同。

data[data.slice_file_name == '100652-3-0-1.wav']

默认情况下, Librosa 的加载函数会将采样率转换为 22.05khz,同时将通道数减少到 1(单声道),并对数据进行归一化,使值的范围从-1 到 1。

import librosa
fullpath,_ = path_class('100652-3-0-1.wav')
librosa_load, librosa_sampling_rate = librosa.load(fullpath)
scipy_sampling_rate, scipy_load = wav.read(fullpath)
print('original sample rate:',scipy_sampling_rate)
print('converted sample rate:',librosa_sampling_rate)
print('\n')
print('original wav file min~max range:',np.min(scipy_load),'~',np.max(scipy_load))
print('converted wav file min~max range:',np.min(librosa_load),'~',np.max(librosa_load))

plt.figure(figsize=(12, 4))
plt.plot(scipy_load)

plt.figure(figsize=(12, 4))
plt.plot(librosa_load)

通过绘制从同一个源声音文件加载的两个数据,我们可以看到 Librosa 加载的数据已经减少到单声道(图上只有一条彩色线),而原始数据有两个声道(一个声道为绿色,另一个为蓝色)。

你猜怎么着。我对每种数据都有不同的采样速率、通道数量和不同的取值范围的所有担忧,都通过用 Librosa 加载声音数据完美地解决了!

我可以从一开始就使用 Librosa,甚至不用担心这些不同类型的 wave 文件格式,但通过研究 Librosa 在加载声音文件时实际上在做什么,现在我对不同的声音数据类型有了更好的理解,它们意味着什么。

我想我现在对我正在处理的数据有了很好的理解,接下来是有趣的部分,机器学习。在下一篇文章中,我将最终开始模型构建的第一阶段:特征提取。

感谢您的阅读。你可以从下面的链接中找到代码的 Jupyter 笔记本。

https://github . com/tthustlea/urban _ sound _ class ification/blob/master/urban _ sound _ class ification _ part 2 . ipynb

美国警察杀人:数据告诉我们什么

原文:https://towardsdatascience.com/us-police-killings-what-the-data-tells-us-563f8b052452?source=collection_archive---------5-----------------------

2015-2016 年警察杀人的探索性数据分析

Photo by Spenser Young on Unsplash

介绍

在这篇文章中,我们将分析美国最热门的政治话题之一,包括从制度种族主义到执法人员在社会中的角色等问题。但首先,我想请你帮个忙。在接下来的 10 分钟里,让我们把我们先入为主的关于什么是真的观念留在门口。先前的领域知识对于从数据中做出推论是至关重要的。但是,如果我们基于预先存在的信念建立我们的统计模型,我们就不太可能得到正确的答案,而更有可能提出错误的问题。那是我关于统计哲学的演讲。让我们开始吧。

背景和目标

由美国自由主义者和自由意志主义者推动、遭到坚定保守派强烈反对的越来越多的观点是,美国有一个有缺陷的执法系统,让太多无辜*民付出了生命代价。美国警察每年杀死大约 1000 人。如果我们将这一数字与芬兰等其他发达国家进行对比,2013 年芬兰警察只开了 6 枪,我们会看到一幅怪诞的画面。但是如果我们看看其他暴力犯罪和凶杀水*相似的国家,情况会变得更加模糊。在这个项目中,我们将把我们的范围限制在分析美国境内的警察杀人事件,并试图根据导致杀人的警察遭遇的数据得出有用的见解。事不宜迟,我们来挖掘一下数据。

使用的数据集

我们在这个项目中使用了 5 个数据集:
1)2016 年的警察杀人数据集
2)2015 年的相同框架数据集
3)2015 年 1 月至 6 月的数据集,其数据点少于 2)但事件的信息特征更多
4)2015 年美国各州人口和暴力犯罪事件数据集
5)包含 1000 多个美国城市统计数据的数据集

前两个是由英国报纸《卫报》的一个项目“统计的”编辑的。第三个由内特·西尔弗的五三八编辑。我从网站上收集了这三样东西,卡格尔。我自己定制了州人口的第四个数据集,减少了联邦调查局汇编的数据。第五组城市统计数据来自 www.simplemaps.com 的 T4。你可以在我的 GitHub 库上找到所有这些文件。

预处理:数据清理和特征工程

该项目将于 R 完成。数据可视化是 R 的主要优势之一,在这种分析中非常方便。我的编程脚本和情节在 GitHub 上公开。

合并数据集:我们使用的前两个数据集来自同一个来源,因此将它们合并在一起只需要一行代码。第三个数据集虽然相似,但来自不同的来源,因此我们需要解决其中的差异。尽管它拥有前两个版本的所有功能,但其中一些功能的命名略有不同。这一张还有其他特征,涉及发生杀戮的地区/区域的人口统计细节。我们不是试图将所有三个数据集合并在一起,而是将前两个数据集的较大合并数据集用于我们的大多数可视化,并在查看人口统计数据时专门使用第三个数据集。第四和第五组数据也将用于比较不同的州和城市在警察杀人方面的差异。

删除和转换特征:我们删除了 ID、姓名和街道地址等识别特征,因为它们对于每个案例几乎都是唯一的,不允许我们得出任何一般化的结论。我们还删除了日期功能:年、月和日。我检查以确保这些变量是均匀分布的,因此我们不会丢失任何有价值的信息。对于扩展特征数据集,我们还删除了任何用作发生凶杀的县/地区的名称/ID 的特征。这些值对于每个事件来说也是唯一的,并排除了一般趋势。我们确实留下了位置特征,例如城市、州、纬度和经度。当我们加载数据集时,这些要素中的许多以错误的格式导入到我们的数据框中。因此,我们必须手动检查数据集摘要,以确保数字特征确实保存为数字信息,分类特征保存为因子等,并在它们不正确时将其转换为正确的格式。

缺少值和数据子集:一小部分数据点缺少一些特征的值,比如经度和纬度。但是,当我们试图可视化某些特征时,与其将这些数据点从我们的数据框架中完全移除,不如相应地使用数据框架的子集来省略特定的数据点更有意义。

特征提取:接下来我们添加一些新的特征。我们将特征区域添加到我们的数据集中。根据谋杀发生的州,我们将数据点分配到美国的四个地区之一:西部、南部、中西部和东北部。我们还添加了另一个功能,年龄组,将死者分成不同的年龄组。

调整我们的特征后,我们的 5 个数据集具有以下特征:

A)具有扩展特征的 2015 年数据集- 467 起杀戮 1)年龄-死者年龄
2)性别-死者性别
3)种族-种族/死者种族
4)城市-事件发生的城市
5)州-事件发生的州
6)纬度-纬度,从地址地理编码
7)经度-经度, 从地址地理编码
8)执法机构-事件涉及的机构
9)原因-死亡原因
10)持有武器-死者如何/是否持有武器
11)地区-事件发生的美国地区
12)年龄组-死者所属的年龄组
13)份额 _ 白人-非西班牙裔白人人口的份额
14)份额 _ 黑人-黑人人口的份额, 不合并)15)份额 _ 西班牙裔-西班牙裔/拉丁裔(任何种族)人口的份额
16)p _ 收入-地区级个人收入中值
17)h _ 收入-地区级家庭收入中值
18)县收入-县级家庭收入中值
19)贫困率
20)尿酸-地区级失业率
21)大学-25+人口的份额与 BA

B)2015–16 数据集- 2226 杀戮-

数据集 A 的特征 1-12

C)*2015 年各州数据集 -
1)各州 ID
2)人口
3)2015 年暴力犯罪事件
*

D)城市数据集 1)城市
2)州 ID
3)州名
4)人口
5)人口规模
6)人口密度

分析:地理可视化&地图

首先,我们将比较不同的州,然后看看警察杀人最多的城市。

y 轴代表 2015 年每个州的暴力犯罪数量,x 轴代表同一时期该州的警察杀人数量。这条直线穿过原点,它的梯度是美国的暴力事件总数除以杀人总数。在大多数情况下,这两个因素是成比例的,但也有异常值。俄克拉何马州、亚利桑那州和加利福尼亚州(在这两个统计数据中均领先一英里)的警察杀人率高得不成比例,这是由暴力事件造成的。另一方面,与暴力事件相比,纽约的杀人率低得不成比例。鉴于暴力事件与一个州的人口成比例,如果我们要为每个州的人口、暴力事件和杀戮创建一个 3D 散点图,我们会看到类似于穿过 3D *面的直线的东西(它在我的 R 脚本中,但为了简单起见,我没有包括它)。

我们为 2015 年发生 10 起或更多警察杀人事件的城市绘制了类似的图。这次我们用城市的人口(适当)代替了暴力事件,我们仍然观察到类似的相关性,这并不奇怪,因为暴力犯罪事件通常也与城市人口成比例。纽约市比纽约州更是一个异数,就其人口而言,谋杀率低得不成比例。接下来,我们将在地块上放置一些地图,以便更好地显示位置。

地图方法- 对于所有的地图可视化,我们将使用 2015 年至 2016 年的大型数据集,并忽略阿拉斯加州和夏威夷州的杀戮,因此我们可以在地理上放大以查看更精细的细节。尽管遗漏了这两个州,我们仍然报道了美国 99%的谋杀案,所以我们没有遗漏太多信息。对于我们的地图,我们将利用 r 中的" ggplot2 "库。虽然这些绘图也可以使用" ggmap "库来完成,但我使用了" ggplot2 "和" sf "库的组合。如果你是一个有抱负的数据科学家,我强烈建议你学习如何充分利用这些 R 库。

对于第一张地图,我们正在查看 2015 年至 2016 年期间的所有警察杀人事件,圆点阴影表示死者的年龄。如果你注意到肯塔基、田纳西、弗吉尼亚和北卡罗来纳地区的点,似乎那些在那里被杀的人比其他地方被杀的人年龄稍大。第二个观点,如果你熟悉美国地图的话,应该很明显,那就是杀戮集中在城市,越大的城市越集中。这没什么好惊讶的。如果你看到下面的美国人口热图,你会注意到这两张图看起来有些相似。

Heat map representing US population density

现在让我们来看一个更小的数据子集,它只包含手无寸铁时被杀的人。这将是 389 人,或大约 17.4%的人在这两年中被杀害。

如果这些数据代表了现在仍在发生的事情,那么杀害手无寸铁的人似乎也是美国的一个普遍问题。枪击似乎也是这里死亡的主要原因(2015 年至 2016 年,枪击造成了超过 90%的死亡),羁押中死亡是第二大死亡原因。现在,让我们来研究一下种族/民族因素是如何影响这一情况的。

**

第一张地图涵盖了数据集中所有 8 个种族/族裔类别的杀人案件。但是因为群太多,有点难跟。因此,我们将我们的数据集子集化,只包括那些被杀害的“黑人”、“白人”、“西班牙裔/拉丁裔”或“土著美国人”。通过这样做,我们仍然保留了 95%以上的数据点,并获得了更清晰的视觉效果。似乎被杀害的白人遍布全国大部分地区。在巴尔摩、DC 和芝加哥犯罪猖獗的地区,黑人似乎占了死者的绝大部分。可以理解的是,西班牙裔/拉美裔在西班牙裔/拉美裔人口密集的州,如加利福尼亚、新墨西哥和得克萨斯州,占了更多的死者,也占了墨西哥边境城镇的大多数死者。南加州似乎是上述三个种族/民族的密集结合。印第安人的死亡似乎集中在亚利桑那州和新墨西哥州的印第安人保留地附*。

分析:条形图和直方图

停留在种族/民族的话题上,让我们快速地看一下不同的民族和种族是如何随着年龄而不同的。

遇害的阿拉伯裔美国人的*均年龄最低,而那些被归类为“未知”的人的*均年龄最高。但是这些群体没有大量的数据点。因此,让我们把注意力集中在构成大部分(几乎 95%)数据集的 3 个群体上:黑人、白人和西班牙裔/拉丁裔。我们可以看到这里也有明显的差异,所以让我们用一些直方图更深入地了解一下。

被杀害的西班牙裔/拉美裔人的年龄往往低于被杀害的白人,黑人的*均年龄最低。白人、西班牙裔/拉美裔和黑人的*均年龄分别为 38 岁、31 岁和 30 岁。然而,值得注意的是,这些群体的*均年龄分别为 42.9 岁、28.1 岁和 33.3 岁。这至少解释了为什么被杀害的白人群体的*均年龄最高。白人图表的尾端也延伸到更老的年龄,但可以理解的是,他们有更多的离群值,因为他们占了数据集的一半以上。同样值得注意的是,美国西班牙裔/拉美裔的中值年龄下降是因为他们社区的很大一部分是第一代移民,他们往往比美国的*均年龄更年轻。他们也倾向于比其他两个群体拥有更多的孩子。

继续谈论年龄这个话题,让我们来看看美国不同地区的情况是如何不同的,并通过更多的因素来缩小范围。

很难通过该图得出关于年龄和地区的结论,因为柱状图并不意味着显示实例的数量,而是侧重于按百分位数的细分。但是看起来(如果你检查一下数据就会发现)在中西部和西部死亡的人的年龄比在东北部和南部死亡的人要低。在所有地区,被杀害的持刀者的年龄都高于其对应部分(假设我们排除一小部分携带车辆的人,“其他人”,或案件“有争议”的人)。

枪击似乎是 90%以上案件的死因,确切地说是 2021/2226 起案件。除中西部地区外,所有地区在羁押中被杀者的年龄中位数(这是第二大死亡原因,共 82 起)都略高于被枪杀者。有趣的是,根据箱线图的上四分位数,死者被车辆撞击的案例涉及老年人。虽然他们只收集了一小部分数据,但这些病例数量巨大(总共 49 例,4 个地区各至少 9 例)。

让我们从我们在 538 数据集上找到的额外信息开始,按收入进行细分。请注意,这只是 2015 年 1 月至 6 月间死亡的不到 500 人的信息。首先,让我们看看收入。

这里需要注意的重要一点是,这些收入不是被杀害的个人的,而是居住在发生杀戮的地方的人们的收入。用消息来源的话说,“人口普查区域是通过使用 Bing 地图和 Google Maps APIs 将地址地理编码为纬度/经度,然后将点叠加到 2014 年人口普查区域上来确定的”。然而,我们确实看到了一些模式,表明相当数量的死者是在代表死者种族背景的县/市/地区被杀害的。在所有收入类别中,杀害土著美国人发生在收入最低的地区,而亚裔美国人则处于另一端。根据维基百科,2018 年每个种族/族裔的家庭收入中位数如下:亚裔-80,720,白人- 61,349,夏威夷土著和其他太*洋岛民-57,112,西班牙裔或拉丁裔(任何种族)-46,882,美洲印第安人和阿拉斯加土著- 39,719,黑人或非裔美国人- 38,555* 。有趣的是,美洲原住民的收入似乎比黑人高。但是根据杀人事件的数据,美国原住民在低收入地区被杀的人数比黑人多。在许多其他事情中,这可能表明,要么许多黑人在没有黑人家庭占主导地位的社区被杀害,要么当土著美国家庭被归类为与土著阿拉斯加人相同的群体时,他们的国民收入得到了提高。为了更好地理解它,我们将偏离这个项目范围之外的数据,所以我将把这个任务留给那些好奇的人。值得注意的是,我们看到的分类中值收入都明显低于任何种族/民族的全国中值收入。对于我们的数据集,杀戮发生在中等家庭收入为 42,759 美元的地区。美国 2018 年家庭收入中值为 57112 美元。2015 年至 2016 年,不到 24%的警察杀人事件发生在家庭收入高于全国中位数的人口普查区。如果我们 2015-16 年的数据代表了美国警察杀人的总体情况,那么杀人事件更有可能发生在贫困地区。让我们来看看这些地区的贫困率。*

类似的收入模式在小块土地上的贫困率中也可以看到,美洲原住民在最贫困的地方被杀害。众所周知,印第安人保留地的贫困率为 28.4 %,而所有印第安人的贫困率为 22%。这两个数字都远高于 12.7%的全国贫困率。现在让我们转到发生杀戮的地方的种族/民族人口统计。

超过 75%的白人死者是在非西班牙裔白人占 50%以上的社区被杀害的。据报道,黑人和西班牙裔/拉丁裔在他们各自的种族/民族背景的人比你在美国普通社区中发现的人占人口的比例相对较大的社区中也被杀害。

这个更有趣一点。看起来像是,出于某种原因,据报道,美洲原住民是在受教育程度较高的人群中被杀害的,而不是他们的同类。更有趣的是,如果我们看看黑人和西班牙裔被杀地区的大学教育水*,他们分别排在第二和第三位。我个人想不出好的假设来解释这种现象。如果你有答案,请随时告诉我。

现在,让我们离开该地区的人口统计数据,回到我们最初的 2015 年至 2016 年的一些堆积条形图数据集。在接下来的两个情节中,我们将探索一个我们还没有看到的特征,年龄组。

**

在讨论这两个图之前,我们应该注意到 38 名死者据报道年龄在 18 岁以下,而其他 2 个年龄组每个都有超过 1000 个数据点。由于 18 岁以下年龄组的数据样本量要小得多,因此从这个年龄组得出的推论比从其他两个年龄组得出的推论更不可能代表整个人口中发生的情况。话虽如此,让我们来看看图表。直觉上,年龄最大的一组白人比例最高是有道理的。在美国的老年人群中,白人的比例往往比 T2 人高。第二个挺有意思的。在这三个年龄组中,被杀害的未成年人携带武器或刀具的比例最低。18 岁以下年龄组的被杀者手无寸铁的比例也最高(26.3%)。请注意,这里没有足够的信息来得出这些统计数据反映了总体情况的结论。但是如果进一步分析发现它们具有代表性,就有理由担心了。

在上面的剧情中,我们看到了被不同地域杀死的人的“武装”状态。值得注意的是,每个地区被杀者中手无寸铁的比例高得惊人,不同地区之间的比例从 16.9%到 18.5%不等。

枪击似乎造成了每个种族的绝大多数死亡。第二大死因似乎更有趣一些。白人在羁押中的死亡率最低(不包括被杀害的 7 名阿拉伯裔美国人),而印第安人的死亡率最高。下一个情节也很有趣。

**如果我们假设我们的数据代表了当今警察杀人的总体趋势,那么被杀的黑人比其他任何种族/民族更有可能携带枪支(本案中有 49.1%)。这也意味着他们比其他种族/民族群体更不容易在被杀时持刀。更有趣的是,如果我们排除 7 名阿拉伯裔美国人,这将意味着黑人比任何其他种族/族裔群体更有可能在被杀时手无寸铁(2015-16 年被杀的黑人中有 20.9%没有武器)。这些见解,如果是真的,可以联系到备受争议的讨论,将黑人与拥有枪支联系起来的刻板印象是否会导致更多手无寸铁的黑人被杀。这使得一个完美的赛格威进入我们项目的下一部分。

讨论-理解种族偏见

为了给上面的图表提供数字,下面是 2015 年至 2016 年杀人总数的种族/民族汇总:

2015-16 警察杀害死者种族/民族:
-
阿拉伯裔美国人-7
-亚裔/太*洋岛民-45
-黑人-568
-西班牙裔/拉丁裔-378
-美洲原住民-34
-其他-1
-不详-43
-白人- 1150

你可能会注意到,黑人在死者中占了不成比例的大部分(超过 25%),而在美国总人口中仅占 12%。然而,试图纯粹基于这些统计数据找到有意义的结论将意味着我们忽略了它们背后的混杂因素。根据这份 FBI 报告,黑人男性的杀人率比白人男性高 8 倍。一个统计学新手可能会过早地得出结论,认为高犯罪率是黑人高死亡率的原因。但是,再一次,基于这样的零星数据得出关于种族/民族的结论不仅是不正确的,而且是危险的无知。我们将打破观察研究的黄金法则:相关性不等于因果关系。贫困率、教育背景和社会经济地位等更深层次的混杂因素可以更好地预测群体中的暴力犯罪事件。

如果你不确定什么是混杂因素,就去读读 这个 。这是一个既影响研究中的自变量又影响因变量的变量,如果不对其进行*衡,会导致研究人员得出错误的结论。例:吸烟者很可能喝咖啡,也很可能患胰腺癌。但是,如果一项调查喝咖啡影响的研究没有消除吸烟的影响,我们可能会错误地得出结论,喝咖啡会导致胰腺癌

如果我们有更多关于死亡个体的人口统计信息,我们将能够*衡几个混杂因素,并得出更好的结论。但是我们没有。这让我们面临一个最大的障碍:缺乏数据。没有一个全面跟踪所有警方互动的系统的问题是,我们只能获得导致杀戮的互动数据,即使这样,我们也只能获得不完整的数据。如果我们有关于警察与不同种族/民族的人有多少次互动的数据,以及其中有多少百分比导致了暴力/杀戮,我们就能更好地发现警察的偏见。目前,此类实例的数据只有在拥有数据的部门选择发布时才可用。那些选择这样做的部门可能根本不能代表美国警察部门的*均水*。正如你最*可能听说的,联邦调查局计划从 2019 年开始收集所有涉及警察使用严重暴力的案件的数据。在某种程度上,这种变化将允许更好的分析。但是,从警察局获得所有这些数据可能仍然不能给我们想要的直接答案。这是因为我们无法通过实验室环境下的随机试验找到确切的答案。在观察性研究中,我们必须确保消除所有的混杂因素,比如我前面提到的那些。这并不容易做到,因为可能有我们甚至没有想到的混淆因素。用研究警察偏见的心理学家和神经学家基思·佩恩的话说,“很难从经验上区分贫困、地理、种族、种族偏见和警察策略的影响”。

结论

虽然最后一段提到的复杂性可能会让我们这些试图找到这个令人不安的问题的结论的人感到有点沮丧,但我们有理由充满希望。即使有当前的限制,我们也能够对这个问题形成重要的见解(就像我们在这个项目中提出的那样)。我将以最后一个想法来结束这篇文章。我相信只有两件事让我们无法找到正确的答案。首先是足够的数据,我们正在缓慢但稳步地实现这一目标。第二是有更多好奇的人愿意看这些数据并提出正确的问题。这个小组可能由像你、是的,你这样的人组成,如果你已经在文章中提到了。

感谢你到目前为止的阅读。我希望这篇文章教会你一些新的东西,无论是关于 R 的探索性数据分析还是关于美国警察暴力的问题。如果你认为这对你认识的其他人来说是有趣或有教育意义的,请与他们分享。如果你喜欢这篇文章,并有什么想和我分享的,请随时发表评论,通过电子邮件联系我,地址是 nadir.nibras@gmail.com 或 https://www.linkedin.com/in/nadirnibras/T5。我致力于改进我的方法、分析或数据集,所以如果你有任何建议,请随时评论或告诉我。如果你想关注我在数据科学方面的更多工作,请在 Medium 和 Linkedin 上关注我。
此外,如果你是数据科学或其在理解世界中的应用的粉丝,请联系我。和其他统计爱好者聊天总是很有趣,我很乐意在有趣的项目上合作:)

都柏林自行车站的使用模式

原文:https://towardsdatascience.com/usage-patterns-of-dublin-bikes-stations-484bdd9c5b9e?source=collection_archive---------5-----------------------

Locations of all Dublin Bike stations colour coded by their weekday usage patterns. Click here for the full interactive map.

自从我 5 年前来到这里,我已经是都柏林自行车的长期用户了,像许多其他用户一样,我有一个关于一天中不同时间哪个车站繁忙或安静的心理模型。我最*的车站是波多贝罗,我发现在上午 10 点左右很难找到自行车,但是步行到镇上,我找到自行车的机会就会大大增加。我想更详细地了解这一点,并找出是否有一些不同的行为类型,所有的车站都可以分类,以及这在城市中可能如何变化。自行车主要用于上下班,因此出现某种空间模式似乎是很自然的。正如你在上面的地图上看到的,我们可以把这些站分成三种不同的行为类型,我们得到了一些非常有趣的结果!

在这篇文章中,我将更多地解释我做了什么,这些模式是什么,以及一些技术背景。因为我这篇文章的目标读者是普通读者以及更多的技术人员,所以我将首先讨论这些发现,把技术方法留到后面。你也可以点击这里获得上面显示的完整交互地图和点击这里获得 github repo ,在这里我已经公开了我的代码和一些示例数据。

有哪些模式,它们是如何被发现的?

从 2017 年 1 月到 2017 年 8 月,我每隔 2 分钟从公共 API 收集数据,以建立一个规模相当大的历史数据集,从中我们可以计算出 108 个站点中每个站点的典型工作日使用情况。这将*均化雨天、冷天、特殊事件等的影响。由此,我们可以找到不同的行为模式,我们可以将每个站配置文件分类。为了做到这一点,我使用了一种叫做 k-means 聚类的方法,这种方法的工作原理是预先假设我们的数据可以分成“k”个不同的类别。然后,该算法试图找到描述数据分段的“k”个最佳*均模式。在我们的例子中,我选择了 k=3,因为它给出了美学上令人愉悦的结果,尽管像轮廓评分这样的方法更严格。我希望将我 2017 年 10 月在都柏林 PyData 发表的一篇演讲放到网上,这篇演讲用更多的技术细节解释了这一点。然后根据与三个简档最接*的匹配对每个电台进行分类。我们可以自由选择更高的值,但是由于可能类别的数量不断增加,结果变得更加复杂,但是我们希望行为特征更符合实际数据。

我用颜色标记了用这种方法发现的每一种不同的行为,并绘制在下图中。回想一下,这些是使用每个站的*均工作日使用量找到的,所以一天中的时间是沿着 x 轴的。我还使用了每个站点的百分比容量,而不是原始的自行车数量,来处理一些站点的容量高于其他站点的事实。

Average weekday usage for the three types of stations

显而易见,最接*绿线的车站通常用于早上进城到蓝色车站的通勤,因此我们自然会认为绿色车站位于住宅区,蓝色车站位于市中心。晚上,当人们下班回家时,情况正好相反。红色加油站一天有稳定的供应,不符合其他两种行为。

当我们在地图上绘制车站并按类别用颜色编码时,一幅非常有趣的画面出现了,如上面的图片所示(或者点击此处打开互动地图的标签)。通过仅根据站点的使用模式来表征站点,我们可以看到这也导致了高度的空间聚类。虽然这是你期望看到的,但我对集群的清晰程度感到惊讶——蓝色站集中在都柏林 2 区周围,那里有许多商业办公室,与中间的红色站接壤,绿色站在市中心以外的更多住宅区。

方法学

为了收集数据,我写了一个简短的 Python 脚本,在我的 Raspberry Pi 上运行,每 2 分钟查询一次 Dublin Bikes API,并附加到一个每日 CSV 文件中,然后每晚将这个 CSV 文件转储到 S3 桶中。我从 2017 年 1 月开始运行这个,直到 8 月下旬,我终于再次想起了这个项目的想法。

如前所述,我然后计算了 108 个站点中每个站点的*均工作日概况,然后使用 k-means 聚类来确定三个原型行为类别,我将根据这些类别对每个站点进行分类。我使用欧几里德距离来确定不同时间序列的相似性,这有点简单,一般不推荐用于时间序列数据。我认为这个问题很简单,只有 3 种行为类型,尽管有这个假设,我对我的结果很满意。如果需要更鲁棒的方法,可以使用更高级的方法,如动态时间弯曲。

这个映射是使用 Python 库 leaf 完成的,它充当 JavaScript 库传单的包装器。它使用起来相当容易,而且似乎在其他 Python 映射库中脱颖而出,因为它可以输出到 HTML 中,然后可以嵌入到网站中或独立托管。

就未来的工作而言,可以利用这些数据做更多的事情,比如工作日之间的差异和天气的影响。在查询 bikes API 以构建用于本文的数据集时,我同时收集了都柏林的天气数据,因此观察它对使用模式的影响并为每个站点构建一些预测模型会很有趣。像 ARIMAX 这样的模型应该可以很好地解决这样的问题。

无论如何,这就是现在,希望这是有趣的都柏林自行车用户和技术人员一样。点击这里查看 github 回购项目或在 Twitter 上点击我。

为你的企业使用人群计数人工智能模型

原文:https://towardsdatascience.com/use-a-crowd-counting-ai-model-for-your-business-485da9c21db4?source=collection_archive---------7-----------------------

用数据做酷事!

背景

深度学习正在迅速将计算机视觉带入一个领域,企业可以开始在日常使用中集成强大的模型。过去,企业在采用人工智能方面面临的一些挑战——谁将建立和维护这些模型,我如何部署它们,它们是否足够准确——现在在 Unleashlive 的一个新*台中得到了解决,该*台旨在将模型开发者与最终用户联系起来。

我正在这个人工智能*台上推出一个人群计数模型。这个*台将允许企业通过我的模型运行他们的剪辑或图像或直播视频,并立即获得结果,而没有任何与设置环境或 GPU 相关的麻烦。你现在可以在释放云免费试用这个模型 1 小时。首次用户请建立一个新帐户。

人检测/计数模型是非常通用的,在许多领域都有应用。这里是我能想到的一些,以及我的应用程序使用 you tube 的一些视频的性能的一个小演示。

人计数器的有趣应用

  1. 零售

在零售业中,了解客流量对于组织过道中的商品、优化商店布局、了解高峰时段甚至潜在的防盗非常重要。你现在可以在商店里放一个摄像头,并将其连接到 Unleashlive AI *台,获得可以被摄取和分析的实时数据。请参见下面的实际模型

People Counter — Retail

2.基础设施规划

许多企业或政府机构可以使用人员计数器来了解各种情况,如在给定时间公共场所有多拥挤,或者每天有多少人使用特定的街道交叉口等。

Traffic Count

3.安全

另一个广泛的应用领域是安全。如果你正在寻找一个迷路的人,或者如果一个企业想在启动一台大型机器之前确保一个区域没有人。在下面的图片中,我的模型可以追踪一个在内陆徒步旅行的人。

Safety application of people counter

关于人工智能模型的更多信息

这里使用的人群计数模型是一个更快的 RCNN 初始模型,在不同规模的自定义人群数据集上进行训练。与使用在 COCO 数据集上训练的模型相比,它的工作速度更快,精度更高。它适用于*距离和远距离拍摄的人群图像,以及不同背景和闪电条件下的图像。

我想在我的业务中使用这种模式

如果你对这篇文章感兴趣,并想尝试人数统计模型,那么请登录并在https://cloud.unleashlive.com/创建一个账户

您将能够激活该模型并对其进行测试!最棒的是,“释放”向所有新用户提供 1 小时免费试用:)

我是一名开发人员,我想添加一个模型

这也很简单。只需在“释放生活”上创建一个帐户,并在顶部的个人资料中启用开发者标志(“以开发者身份开始”)。这为您的测试建立了一个私有的沙箱。有 tensorflow 1.6 和对象检测经验者优先。

一旦您启用了您的帐户,“开发者”将出现在顶部的导航栏上。只需点击并选择“沙盒”,然后按照提供的指示。这是一个非常简单的过程。

了解更多

要了解更多关于 Unleashlive *台和商业模式如何运作的信息,请查看以下常见问题:

http://developer.unleashlive.com/#a-i-apps-ecosystem

如果您有任何问题或需要帮助,请随时拨打getstarted@unleashlive.com联系我们。如果你对其他人工智能应用有想法,请在下面的评论中添加。

参考文献:

  • Google Tensorflow 物体检测 Github
  • COCO 数据集

用 AWS Glue 和 Databricks Spark-XML 处理 XML

原文:https://towardsdatascience.com/use-aws-glue-and-or-databricks-spark-xml-to-process-xml-data-21eaef390fda?source=collection_archive---------2-----------------------

快速介绍 Glue 和一些 XML 处理技巧,这从来都不容易

如果您对数据的质量和结构有严格的规定,使用非结构化数据有时会很麻烦,可能会包括对数据进行控制的庞大的任务。

在本文中,我将分享我使用 Glue transformations 和 Databricks Spark-xml 库处理 XML 文件的经验。

AWS Glue 是 AWS 提供的 ETL 服务。它有三个主要组件,即数据目录、爬虫和 ETL 作业。因为爬虫帮助你提取你的数据的信息(模式和统计),数据目录被用于集中的元数据管理。使用 ETL 作业,您可以使用 Glue proposed 脚本或带有附加库和 jar 的自定义脚本来处理存储在 AWS 数据存储上的数据。

XML…首先,您可以使用 Glue crawler 来探索数据模式。由于 xml 数据大多是多级嵌套的,所以爬行的元数据表将具有复杂的数据类型,如结构、结构数组……并且您将无法使用 Athena 查询 xml,因为它不受支持。所以有必要将 xml 转换成*面格式。要展* xml,您可以选择一种简单的方法来使用 Glue 的魔法(!),一个简单的技巧将其转换为 csv 格式,或者您可以使用 Glue transformations 来展*数据,稍后我将对此进行详细说明。

您需要小心展*,这可能会导致空值,即使数据在原始结构中是可用的。

我将给出一个替代方法的例子,根据您的用例选择哪一个取决于您。

  • 爬网 XML
  • 使用粘合作业转换为 CSV
  • 使用 Glue PySpark 转换来展*数据
  • 另一种方法是:使用 Databricks Spark-xml

数据集:【http://opensource.adobe.com/Spry/data/donuts.xml

代码片段:https://github.com/elifinspace/GlueETL/tree/article-2

0.将数据集上传到 S3:

从给定的链接下载文件,并转到 AWS 控制台上的 S3 服务。

Create a bucket with “aws-glue-” prefix(I am leaving settings default for now)

单击 bucket 名称,然后单击 Upload:(这是最简单的方法,您也可以设置 AWS CLI 以从本地机器与 AWS 服务交互,这需要更多的工作,包括安装 AWS CLI/配置等。)

点击添加文件,选择你想上传的文件,然后点击上传。

You can setup security/lifecycle configurations, if you click Next.

  1. 爬网 XML 元数据

首先,如果您知道 xml 数据中的标记可以选择作为模式探索的基础级别,那么您可以在 Glue 中创建一个定制的分类器。如果没有自定义分类器,Glue 将从顶层推断模式。

在上面的 xml 数据集示例中,我将选择“items”作为我的分类器,并像下面这样轻松地创建分类器:

转到 Glue UI,单击数据目录部分下的分类器选项卡。

“item” will be the root level for the schema exploration

我用分类器创建了爬虫:

Give the crawler a name and Select the classifier from the list

Leave everything as default for now , browse for the sample data location (‘Include path’)

添加另一个数据存储:否

您可以在 S3 存储桶上使用具有相关读/写权限的 IAM 角色,也可以创建一个新角色:

频率:按需运行

Choose the default db(or you can create a new one) and leave settings as default

查看并单击完成。

现在我们已经准备好运行爬虫了:选择爬虫并点击 Run Crawler,一旦状态为“ready ”,访问数据库部分并查看数据库中的表。

(Tables added :1 means that our metadata table is created )

转到表并过滤您的数据库:

单击表名,输出模式如下:

现在我们有了模式的概念,但是我们有复杂的数据类型,需要将数据扁*化。

2.转换为 CSV:

这很简单,我们将使用 Glue 提供的脚本:

转到 ETL 菜单中的作业部分并添加作业:

Name the job and choose the IAM role we created earlier simply(make sure that this role has permissions to read/write from/to source and target locations)

Tick the option above,Choose the target data store as S3 ,format CSV and set target path

现在是神奇的一步:(如果我们选择 parquet 作为格式,我们将自己进行展*,因为 Parquet 可以有复杂的类型,但对于 csv 来说,映射很容易显示。)

You can rename, change the data types, remove and add columns in target. I want to point that the array fields mapped to string which is not desirable from my point of view.

我把一切都保留为默认,审查,保存并继续编辑脚本。

粘附建议的脚本:

We can Run the job immediately or edit the script in any way.Since it is a python code fundamentally, you have the option to convert the dynamic frame into spark dataframe, apply udfs etc. and convert back to dynamic frame and save the output.(You can stick to Glue transforms, if you wish .They might be quite useful sometimes since the Glue Context provides extended Spark transformations.)

我在建议的脚本中添加了一些行来生成单个 csv 输出,否则输出将是基于分区的多个小 CSV 文件。

保存并单击“Run Job ”,这将带来一个配置检查,因此您可以将 DPU 设置为 2(最小的值)并按如下方式设置超时:

让我们运行并查看输出。您可以监视 Glue UI 中的状态,如下所示:

运行状态成功后,转到您的目标 S3 位置:

单击文件名并转到如下所示的“选择自”选项卡:

如果向下滚动,可以通过单击显示文件预览/运行 SQL(Athena 在后台)轻松预览和查询小文件:

The struct fields propagated but the array fields remained, to explode array type columns, we will use pyspark.sql explode in coming stages.

3.粘合 PySpark 转换用于取消嵌套

Glue 提供了两种 pyspark 变换:

  • Relationalize:取消嵌套列、透视数组列、为关系操作(连接等)生成连接键。),生成帧列表
  • UnnestFrame:取消框架嵌套,为数组类型的列生成 joinkey,生成一个包含所有字段(包括 join key 列)的框架。

我们将使用 Glue DevEndpoint 来可视化这些转换:

Glue DevEndpoint 是数据存储的连接点,用于调试脚本,使用 Glue Context 和 Sagemaker 或 Zeppelin 笔记本对数据进行探索性分析。

此外,您还可以从 Cloud9 访问这个端点,cloud 9 是基于云的 IDE 环境,用于编写、运行和调试您的代码。您只需要在 Cloud9 实例上生成 ssh 密钥,并在创建端点时添加公共 SSH 密钥。要连接到端点,您将使用端点详细信息中的“SSH 到 Python REPL”命令(在 Glue UI 中单击端点名称),用您在 Cloud9 实例上的位置替换私钥参数。

  • 创建一个 Glue DevEndpoint 和一个 Sagemaker 笔记本:

我将把这个端点也用于 Databricks spark-xml 示例,所以从https://mvnrepository . com/artifact/com . data bricks/spark-XML _ 2.11/0 . 4 . 1下载 jar 文件到您的 PC,上传 jar 到 S3 并相应地设置“依赖 jars 路径”:

Name it and choose the IAM role we used before.If you have a codebase you want to use, you can add its path to Python library path.

您可以将所有其他配置保留为默认配置,然后单击 Finish。大约需要。端点准备就绪需要 6 分钟。

一旦端点准备就绪,我们就可以创建一个笔记本来连接它。

选择您的端点,然后从操作下拉列表中单击创建 Sagemaker 笔记本。笔记本创建完成后,需要几分钟时间准备就绪。

Name it, leave default settings and name the new IAM role , click Create Notebook

打开笔记本并创建一个新的 Pyspark 笔记本:

您可以从我们之前创建的 csv 作业中复制并粘贴样板文件,如下所示更改 glueContext 行,并注释掉与作业相关的库和代码片段:

You can either create dynamic frame from catalog, or using “from options” with which you can point to a specific S3 location to read the data and, without creating a classifier as we did before ,you can just set format options to read the data.

你可以在https://docs . AWS . Amazon . com/glue/latest/DG/AWS-glue-programming-ETL-format . html中找到更多关于格式选项的信息

  • 关系化:

我在以下步骤中使用了由 from options 创建的框架:(即使您使用了 catalog 选项,输出也是一样的,因为 catalog 不会为数据保存静态模式。)

You can see that the transform returns a list of frames, each has an id and index col for join keys and array elements respectively.

如果看根表会更清楚。例如,填充在根表的这个字段中只有一个整数值,这个值与上面的根 _ 填充 _ 填充帧中的 id 列相匹配。

重要的是,我们看到“batters.batter”字段传播到多个列中。对于项目 2,“batters.batter”列被标识为 struct,但是对于项目 3,该字段是一个数组!。所以用胶水工作的难度就来了。

If you have complicated multilevel nested complicated structure then this behavior might cause lack of maintenance and control over the outputs and problems such as data loss ,so alternative solutions should be considered.

  • Unnest 框架:

让我们看看这个转换将如何给我们一个不同的输出:

We can see that this time everything is in one frame but again “batters.batter” resulted in multiple columns , this brings uncertainty around the number of columns also. Considering an ETL pipeline, each time a new file comes in, this structure will probably change.

和 unnest 可以展开上层结构,但在展*结构数组方面无效。因此,由于我们不能在动态帧上应用 UDF,我们需要将动态帧转换为 Spark 数据帧,并在列上应用 explode,以将数组类型的列分散到多行中。我将把这部分留给你自己调查。

Moreover I would expect to have not two different spread of “batters.batter” and imho there could be an “array of structs” type column for this field and the “item 2” would have an array of length 1 having its one struct data.

最后… Databricks spark-xml:

这可能不是最好的解决方案,但这个软件包在控制和精度方面非常有用。一个很好的特性是,不可解析的记录也会被检测到,并且一个 _corrupt_record 列会被添加相关信息。

Now here is the difference I expected 😃 . You can see that “batters.batter” is an array of structs. Moreover for more reading options, you can have a look at https://github.com/databricks/spark-xml

Batters : No nulls, no probs

因此,您不需要考虑是否存在结构或数组列,您可以通过使用提取的模式来编写一个用于展开数组列的通用函数。

顺便提一下,我在 Glue 环境中使用了 Databricks 的 Spark-XML,但是您可以将它用作独立的 python 脚本,因为它独立于 Glue。

我们看到,尽管 Glue 提供了一行转换来处理半/非结构化数据,但是如果我们有复杂的数据类型,我们需要处理样本,看看什么符合我们的目的。

希望你喜欢它!

用因果图!

原文:https://towardsdatascience.com/use-causal-graphs-4e3af630cf64?source=collection_archive---------7-----------------------

偶然的因果推断

这是关于数据科学因果关系系列的第二篇文章。你可以查一下第一个“数据科学中我们为什么需要因果关系?和下一个“观察不干预”。正如我们所说,目前有两个主要的框架来处理因果关系:潜在的结果和图表。在这里,我们将继续解释为什么因果推理是必要的,以及图形如何帮助它。

图形模型

图表是一个很棒的工具。通过图来模拟因果关系带来了一种合适的语言来描述因果关系的动态性。每当我们认为事件 A 是 B 的原因时,我们就在那个方向画一个箭头。

这意味着你的模型正在考虑从 A 到 B 的一个可能的因果关系。这从“A 是因果关系的主要来源”到“A 几乎不能解释关于 B 的任何事情”。具体来说,它包括 A 是 b 的原因而不是的情况。你可能会对现实建模过度,但模型不会是不正确的。这就是为什么,关键的假设是在你不放箭的时候出现的。在这种情况下,你声称变量之间是独立的,你应该能够论证和辩护为什么会这样。综上,假设越多,箭头越少。

谈论相关性是不够的

图表扩展了统计语言。最简单的例子就是相关性是对称的,而有向图则不是。我可以简单地写

下雨和地板潮湿之间的因果关系。反之, correlation(雨,湿地板)= correlation(湿地板,雨)。相关性是方向性盲的。如果要说因果关系,我们需要一种可以处理因果行为的语言。

就因果模型的公式而言,我们会写

湿地板:= f(雨,随机性)

这意味着潮湿的地板取决于雨水和其他一些随机变量(与雨水无关)。这里的关键是“:=”符号,这意味着雨影响潮湿的地板,而不是相反。这不是一个两边相等的数学方程,而是一个编程方程,其中湿地面的值是根据雨水计算的,但雨水的值不是根据湿地面设定的。

因果线性模型

线性模型是统计学的关键要素之一。通过因果透镜,他们很容易得出直接和间接影响的解释。首先,考虑下面的例子。一家飞机公司想将其业务扩展到一个新机场。他们选择一个机场,带上他们的飞机,设定价格,出售机票。在几个月的时间里,他们不断试验价格,直到达到一个有利可图的可持续价格。顾客在购买机票时,会考虑到从他们家到机场的距离以及航班的价格。由于他们是一家成长中的公司,他们在过去的 5 年里一直在这样做。这些事件可以通过下面的图表来描述,其中距离是与带来大部分客户的城市的距离,价格是月*均价格,航班是月*均航班数。

现在,他们想知道,对于他们想要合作的下一个机场,距离如何影响航班数量?通过观察数据,他们得出结论,在这种情况下,线性模型就足够了。然后他们执行线性回归,试图从距离价格表达航班

得到最终的线性模型

航班= -10 距离+ -5 价格

可以这样理解:固定一个特定的航班价格(比如 100 美元),如果你增加距离,航班数量将减少 10 个单位。但是,这不是你想要的!当你增加距离的时候,也会影响价格(不能固定)!你感兴趣的是当你改变一个单位的距离,又叫航班改变了多少单位。**

从图形模型的角度来看,我们可以在每条边上放置一个线性模型,并具有以下方程组:

价格:= -3 距离+ Random_1

航班:= -10 距离+ -5 价格+随机 _2

现在我们看到距离航班的两个影响:

  • 直接效应 ( 距离 - > 航班):客户对距离的负面感知。
  • 间接影响 ( 距离->-价格 - > 航班):距离的增加,迫使公司降低价格,从而产生航班的增加。**

利用上面的公式,通过变量价格距离的关系的替换,可以获得总效果:

航班:= -10 距离+ -5 价格+误差 _2 = (-10 + (-5)(-3))距离+随机 _3 = 5 距离+随机 _3

这种情况下的总效果是 5 (= -10 + (-5)(-3))。但这只是一个玩具例子。我们如何从数据中直接计算出总体效果?在这种情况下,您可以汇总所有直接和间接的影响,仅从距离表示航班。所以答案是只从距离航班进行线性回归。

观察结论与第一次和最后一次回归分析有何不同。第一个得出的结论是距离对航班数量有负效应-10,而最后一个得出的结论是正效应 5!如果价格管理补偿了顾客对距离的负面看法,你仍然可以在寻找不太容易到达的机场时对航班数量产生积极影响。

结论:

  1. 如果您想计算总的影响,您应该从距离执行航班的回归(与第一次回归将所有变量放入计算中不同)。
  2. 使用图表有助于理解、推理和讨论整个分析。

数据本身不会说话

我们已经看到,为了计算距离对航班数量的影响,我们依赖于图表。现在想象一种不同的情况。航空公司,而不是上面描述的过程,他们已经进行如下:他们设置一个价格,在这个价格上他们想要设置他们的航班。之后,他们寻找一个他们认为能满足他们需求的机场。在这种情况下,我们将得到下图:

请注意,从距离价格的箭头已经反转。在这种情况下,改变一个单位的距离根本不会改变价格!因此,如果我们想知道改变一个距离单位如何改变飞行中的一个单位,我们可以直接进行线性回归

航班= -10 距离+ -5 价格

答案是-10!这意味着数据生成的方式以及我们如何对这一过程建模非常重要。此外,这种知识不是来自数据,而是来自特定领域本身。我们最终可能会有两个相同的数据集,但是如果它们产生的方式不同,我们可能不得不以不同的方式来分析它们。

使用嵌入来预测临床研究的治疗领域

原文:https://towardsdatascience.com/use-embeddings-to-predict-therapeutic-area-of-clinical-studies-654af661b949?source=collection_archive---------15-----------------------

特定领域嵌入如何帮助分类

Image from Unsplash

临床研究是一个充满迷人概念的世界,其中存在大量可免费下载的数据集。我在understand(招聘)的任务之一是做一个概念验证,在大约 40 个手动定义的治疗领域中自动分类临床研究,如下所示:

Cardiology/Vascular Diseases  
Dental and Oral Health  
Dermatology  
Genetic Disease  
Hematology  
Infections and Infectious Diseases  
Musculoskeletal  
Neurology  
Nutrition and Weight Loss  
Obstetrics/Gynecology  
Oncology  
Ophthalmology  `
Pharmacology/Toxicology  
Psychiatry/Psychology  
Pulmonary/Respiratory Diseases  
...etc...

可供参考的大约 289000 项研究可以在 ClinicalTrials.gov 的网站上找到。正如我们将在下面看到的,由于 CTTI ( 临床试验转化倡议)提供了高质量的文档,人们可以下载完整的内容作为 CSV 文件或 Postgres 数据库供离线使用。特别是研究与一些医学术语相关联。

既然上述治疗领域是人工定义的,我们如何将它们与研究的医学术语联系起来?这就是 概念嵌入 的来源。下面介绍的所有代码都可以在 Jupyter 笔记本中找到

医学背景下的预训练嵌入

关于单词嵌入已经写了很多。这里有一个关于他们力量的很好的介绍。在本帖中,我们将使用预训练 ed 临床概念 嵌入将治疗区域映射到研究中。

美国国家医学图书馆(NLM)创建了统一医学语言系统(UMLS),这是一个令人难以置信的组织良好的医学概念和术语的来源,在其网站上有最好的描述:

UMLS 整合并分发关键术语、分类和编码标准以及相关资源,以促进创建更有效和可互操作的生物医学信息系统和服务,包括电子健康记录

特别是,一个核心概念是一个医学概念,像疟疾放射疗法肿瘤白血病一样多种多样。每个概念由一个概念唯一标识符 (CUI)标识,并映射到各种医学术语的数据源,如我们将在下面使用的 MeSH (医学主题标题)。

这里有一个 富发布格式 (RRF)浏览器的截图,这是 UMLS 提供的一个强大的工具,从 NLM 获得许可证后就可以下载。可以通过单词搜索概念,并且可以找到与其他概念的关系:

Rich Release Format Browser

由 De Vine 等人从 348,566 份医学杂志摘要(由作者提供)中学习到的 UMLS CUIs 的预训练嵌入可以在此处下载,这要感谢 D. Sontag 等人在那里所做的出色工作(参见学习医学概念的低维表示)。以下是如何加载它们的方法,这要感谢令人敬畏的 gensim 库:

Load concept embeddings with gensim

正如所料,密切相关的概念的余弦相似性很高。例如,以下是与头痛或肝炎最接*的概念:

Most similar concepts

通过概念嵌入将研究与治疗领域联系起来

我们将通过以下途径将临床研究与概念嵌入的治疗领域联系起来:

  1. 从 AACT 的 browse_conditions.txt 文件中获取研究 MeSH 术语(医学主题词)
  2. 使用来自NLM 国家医学图书馆的文件将网格术语转换为其唯一标识符(又名代码
  3. 使用 UMLS 文件加载 UMLS 概念标识符(Cui)及其关联的网格代码。在这一点上,Cui 不再是抽象的。
  4. 手动将治疗区域与 UMLS 概念标识符(CUIs)相关联
  5. 使用预先训练的嵌入来找到 Cui(在 4 中找到)的区域。上图)与研究中的最相似(见 3。以上)

下图总结了一组数据源和转换:

1.获取与研究相关的网格术语

来自 ClinicalTrials.gov 的的 CTTI 提供了非常有条理和有记录的数据。可以从 CTTI 下载网站下载研究和相关数据。下面是我们感兴趣的数据子集(CTTI 提供的模式图):

病历报告在文件studies.txt中,并链接到browse_conditions.txt中的网格术语。下面是研究**NCT01007578** 关于动脉粥样硬化的网状术语的例子:

grep **NCT01007578** ./clinical-trials-gov/browse_conditions.txt1508569|NCT01007578|Atherosclerosis|atherosclerosis
1508570|NCT01007578|Peripheral Arterial Disease|peripheral arterial disease
1508571|NCT01007578|Peripheral Vascular Diseases|peripheral vascular diseases
1508572|NCT01007578|Arterial Occlusive Diseases|arterial occlusive diseases

加载这些内容并从病历报告 ID 到其网格术语集构建一个字典很容易。load_df()是围绕熊猫的一个小包装器函数read_csv(). 然后字典被构建:

2.将网格术语转换为它们的唯一标识符

r 相关的网格文件可以从国家医学图书馆下载。解析细节在笔记本里。

Build MeSH terms to MeSH codes dictionary

3.加载 UMLS 概念

我们现在将加载概念和源文件(MRCONSO.RRF),这些文件来自大量 UMLS 文件这里。其格式在这里描述。在将这个 CSV 文件作为 pandas 数据框加载之前,我们可以通过只保留我们需要的列来将其大小(7148656 行,897Mb)减半。

Reduce Concepts File Size

short load_conso()函数将缩减后的文件加载到数据帧中。查看相同的概念(相同的 CUI)如何映射到不同的源特定代码(不同的 SAB/代码):

MRCONSO.RRF excerpt

3.1 将网格代码映射到 Cui

从上面的数据框创建一个从网格代码到 CUIs 的映射。这将在以后用于将研究与概念 Cui 关联(通过网格代码)

Mapping MeSH codes to CUIs

然后我们使用 1 的结果。, 2.和 3.1 来构建概念 Cui 的研究标识符的字典。对于第一遍,我们删除引用了不在 CTTI 文件中的网格术语的病历报告:

3.2 将概念 Cui 映射到字符串

从上面的数据框创建一个从 CUIs 到相应字符串集的映射。这将在以后用于将治疗区域映射到 Cui:

Mapping CUIs to Descriptions

为了以后的评估目的,使用该映射将病历报告与由相关 Cui 的字符串组成的描述字符串相关联是有用的:

Study terms for Evaluation Purposes

4.手动将治疗区域与 UMLS 概念(Cui)相关联

治疗区域是手动定义的,以满足战略业务需求。因此,要把它们与研究联系起来,我们需要把它们与概念 CUIs 联系起来。这是这篇文章最棘手的部分。

主题专家了解每个领域,因此能够识别哪些字符串或描述与之相关。使用上面的cui_to_strings 字典,使用子字符串匹配很容易识别哪个 CUI 匹配哪个字符串。

例如,对于心脏病学区域,让我们尝试保留其术语集至少包含cardiodiologcardiovascul子字符串的所有 Cui(结果被截断):

Finding Cardiology’s Concepts (output truncated)

Cardiology Concepts (output truncated)

通过在两组嵌入向量上使用 Gensim 的KeyedVector.n_similarity(),希望这组 Cui 与关于心脏病学的研究之间的相似性会很高。

在某些情况下,有必要要求术语来自多个集合。例如,对于区域感染和传染病,第一个集合[‘infectious’, ‘infected’, ‘infection’]返回与感染相关的概念,但不一定是疾病。以下尝试给出了更好的结果:

Finding Infectious Diseases’ Concepts (output truncated)

在其他情况下,一些术语匹配来自非期望区域的 Cui。对于牙齿和口腔健康区域,使用[‘tooth cavit’, ‘caries’, ‘cavities’]会从许多不需要的区域产生 Cui。关于与牙齿区域无关的一组相关的串,参见excluded_terms参数。下面的最终结果似乎没有异常值:

5.使用概念嵌入将研究与治疗领域相匹配

这是所有东西放在一起的地方。从目前构建的结构来看,不难使用蛮力来保留与使用 Gensim 的KeyedVector.n_similarity()的每项研究最相似的治疗区域:

  • 这个概念来源于这项研究(字典std_to_cuis)
  • 这个概念来源于各个治疗领域

Matching studies with therapeutic areas

结果

结果可以用以下代码显示:

Studies matched to therapeutic areas

以下是不同治疗领域的典型结果摘录。由于空间限制,它被截断。如果它太小而无法在你的设备上阅读,那么笔记本包含了更多的结果,有助于在不执行代码的情况下查看它们(执行代码需要从 UMLS 获得下载文件的许可,这并不困难,我得到了 NLM 的热情支持)。

对结果的一些评论

尽管一些研究被错误分类,结果还是很有趣。通常关注误分类有助于理解哪个崔导致(或影响)了错误的选择。

当关注一个错误的分类时,总是关注第二个和第三个治疗区域,看看它们与第一个有多接*。例如,在下面的错误分类中,第二个(正确的)区域Trauma, 0.49841与第一个(不正确的)区域Urology: 0.50133非常相似。这告诉我们,结果并不总是那么糟糕,重点应该放在更糟糕的错误分类上。

study: NCT03677856terms: {'thoracic diseases', 'anesthetic drug', 'anesthesia agent', 'thoracic diseases [disease/finding]', 'anaesthetics', 'thoracic disorder', 'anaesthetic drugs', 'anaesthetic agent', 'anesthetics drugs', 'anesthetic agent', 'diseases, thoracic', 'anesthetic', 'agents, anesthetic', 'anesthetic agents', '[cn200] anesthetics', 'thoracic disease', 'disease thoracic', 'anesthetic drugs', 'disease, thoracic', 'thoracic dis', 'anesthetics', 'drugs, anesthetic', 'anesthestic drugs', 'drugs causing loss of sensation'}ranks: [('Urology', 0.50133), ('Trauma', 0.49841), ('Neurology', 0.49322), ('Dermatology', 0.48437), ('Obstetrics/Gynecology', 0.47121)]

在某些情况下,可能需要手动验证每个 CUI,并从特定治疗区域或研究中删除或添加一些 CUI,并找到导致不匹配的 CUI(借助 gensim 的相似性函数)。然后试着推断这个崔和其他人的互动来理解引起不一致的语义方面。笔记本收录了一些值得调查的误分类。

结论和可能的改进

  • 获取每个治疗区域的 Cui 至关重要。这可能会变得棘手,如上面的例子所示(牙科传染病)。
  • 如果我们无法找到合适的折中方案,可以使用 NLM 的 RRF 浏览器(见上面的截图)浏览相关概念,并手动将每个 Cui 分配到一个有问题的治疗区域。有时一些概念重叠,相似性将无法给出好的结果。需要从负面案例开始进行更多的调整/调查。
  • 进行集成:在这里使用另外两个可用的 CUI 嵌入(更小,但可能仍然是好的)希望它们可以弥补这里尝试的嵌入中缺少的概念。由于这些其他嵌入更小,预计不会有很大的改进。
  • 如果不对病历报告进行分类比错误分类更好,请考虑对第一个区域和第二个区域之间的相似性差异使用阈值。只有当差异大于阈值时才预测治疗区域,因为第一和第二区域之间的间隔被认为足够宽。

用 K *邻(KNN)找更好的公司。

原文:https://towardsdatascience.com/use-k-nearest-neighbor-knn-for-a-better-company-35b343ed2050?source=collection_archive---------16-----------------------

介绍

大多数公司的问题是薪水的辞职,辞职的主要原因之一是他们对他们工作的地方不满意,无论是他们工作的团队,还是他们在同一个部门的办公室的员工,一个想法出现在脑海中,为什么不使用 KNN 对人们进行分类,这样我们就可以得到最好的工作地点,怎么样?在本文中,我将阐明这种分类是如何工作的。

我们将看看如何使用 K 最*邻算法来帮助我们完成这项劳动密集型任务。

下面是我们将要做的事情的概述:

  • 获取不同特征的人之间关系的数据集。
  • 根据从培训数据集生成的距离表计算两个薪资之间的距离。
  • 使用分类器将新的薪水分类到正确的部门。

数据

首先,我们需要一个数据集。为此,我建议从具有不同特征的人之间的关系中获取数据,这些数据可以从任何地方、社交媒体、法庭案件等中提取..—该数据集是一个数据集合,如兴趣、性别、家庭状况、宗教、根源、个人详细信息等..).

如何计算距离

我们将使用一个表,该表根据对工资两个特征之间的理解来确定距离,该表对角线上的值为 0,因为具有相同特征的两个雇员很接*,这些值可以随时改变,并且是从现实生活中提取的,例如,如果 A 国对 B 国的种族歧视很严重,A 国的工资与 B 国的工资之间的距离就会很长。

在 KNN 中,将使用距离之和而不是欧氏距离。

例如:

假设我们有一个有 3 份薪水和 3 个办公室的公司。我们想多招三个工资,前提是每个员工进一个办公室。最终,我们将在公司获得 6 份工资,按每个办公室两名员工的比率计算。我们将使用我之前解释过的方法,把适合他们的新工资放到办公室里。

薪资清单:

Figure 1 : List of Salaries (old and new ones )

距离表:

Figure 2 : Distances between characteristics .

注意:表格上的数字是随机数字,它们没有任何依据。

在本例中,我们采用 3 个属性来计算距离、熟悉情况、根源和兴趣。

注意:为了得到好的结果,你应该使用许多属性。

这是公司的状态 1:

Figure 3 : the state of the company before adding the new salaries.

我们将 3 个新的薪水分类,他们是:克里斯,乔丹和亚当。

我们需要将每个员工放在每个办公室,因此我们需要计算每个新工资和每个旧工资之间的距离。

计算距离:

对于克里斯:

D(克里斯,杰克)=D(单身,已婚)+D(非洲,美洲)+D(体育,艺术)

=1+1.1+0.9=3

D(克里斯,卡莉)=D(单身,已婚)+D(非洲,亚洲)+D(运动,体育)

=1+1+0=2

D(克里斯,阿丽亚娜)=D(单身,离异)+D(非洲,欧洲)+D(运动,旅行)

=2+1.8+0.6=4.4

代表约旦:

D(乔丹,杰克)=D(已婚,已婚)+D(非洲,美洲)+D(艺术,艺术)

=0+1.1+0=1.1

D(乔丹,卡莉)= D(已婚,已婚)+D(非洲,亚洲)+D(艺术,体育)

=0+1+0.9=1.9

D(约旦,阿丽亚娜)= D(已婚,离异)+D(非洲,欧洲)+D(艺术,旅行)

=1.5+1.8+1.2=4.5

对于亚当:

D(亚当,杰克)= D(单身,已婚)+D(阿拉伯,美国)+D(体育,艺术)

=1+2+0.9=3.9

D(亚当,卡莉)= D(单身,已婚)+D(阿拉伯,亚洲)+D(体育,运动)

=1+0.9+0=1.9

D(Adam,Ariana) = D(单身,离异)+D(阿拉伯,亚洲)+D(体育,运动)

=1.5+0.9+0=2.4

根据图 2 计算距离后,我们得到:

Figure 4 : The final result of calculation.

根据表格和图表,我们可以这样对 3 名新员工进行分类:

克里斯会和卡莉在 2 号办公室。

乔丹将和杰克在 1 号办公室。

亚当会和阿丽亚娜在 3 号办公室。

Figure 5 : the state of the company after adding the new salaries.

在这种情况下,K = 1,因为我们每个办公室只有 1 份工资,所以 K 比率可以根据公司的规模而变化。

结论:

我们能够避免公司中新工资的随机分类,现在当新工资进入公司时,我们有了一些依据,我们希望将它放在正确的生态系统中,以提高员工的生产力,减少公司中的冲突。

使用 Kaggle 开始(并指导)您的 ML/数据科学之旅——为什么和如何

原文:https://towardsdatascience.com/use-kaggle-to-start-and-guide-your-ml-data-science-journey-f09154baba35?source=collection_archive---------2-----------------------

https://www.kaggle.com/

我经常被我的朋友和大学同学问到——“如何开始机器学习或数据科学”。

所以,这是我的答案..

之前,我并不确定。我会说类似这样的话:先学这门课,或者先读这篇教程,或者先学 Python(只是我做过的事情)。但是现在,随着我在这个领域越来越深入,我开始意识到我所采取的方法的缺点。

所以,后知后觉的我认为,最好的【进入】 ML 或者数据科学的途径可能是通过

在这篇文章中,我会告诉你为什么我会这样想,如果你被我的推理说服了,你该怎么做。

( 谨慎 ):我是学生。我的职业不是数据科学家或 ML 工程师。我绝对不是 Kaggle 的专家。所以,对我的建议/意见要有所保留。 😃)

但首先,让我介绍一下 Kaggle,并澄清一些对它的误解。

你可能听说过 Kaggle,它是一个为大联盟比赛提供令人难以置信的现金奖励的网站。

Competitions hosted on Kaggle with the maximum prize money (yes those are MILLION DOLLAR+ prizes!)

正是这种名声也导致了对*台的许多误解,并使新来者感到比他们应该开始的时候更加犹豫。

(哦,如果你以前从未听说过 Kaggle,请不要担心,因此,不要分享下面提到的任何误解。这篇文章仍然有完整的意义。就当下一节是我给你介绍 Kaggle 吧。)

误解:

  1. “ka ggle 是一个举办机器学习竞赛的网站”

这是对 Kaggle 的一个不完整的描述!我相信竞赛(以及它们非常丰厚的现金奖励)甚至不是 Kaggle 的真正瑰宝。看看他们网站的标题——

Competitions are just one part of Kaggle

除了主持Competitions(它现在已经主持了大约 300 场)之外,Kaggle 还主持了三件非常重要的事情:

  • [**Datasets**](https://www.kaggle.com/datasets),甚至是那些与任何比赛都不相关的:它拥有 9500 多个数据集,相比之下只有 300 个比赛(在撰写本文时)。所以你可以通过选择任何你感兴趣的数据集来提高你的技能。

Some of the datasets that I find most interesting

  • 它们只是 Kaggle 版本的 Jupyter 笔记本,反过来,它们只是一种真正有效的和酷的方式来分享代码以及大量的可视化、输出和解释。“Kernels”选项卡将带您到一个公共内核列表,人们使用这些内核来展示一些新工具或分享他们关于某些特定数据集(/s)的专业知识或见解。
  • [**Learn**](https://www.kaggle.com/learn/overview) : 此选项卡包含免费的实用实践课程,涵盖了快速入门所需的最低先决条件。他们最大的优点是什么?—一切都是使用 Kaggle 的内核完成的(如上所述)。这意味着你可以互动和学习..不再被动阅读数小时的学习材料!

所有这些使得 Kaggle 不仅仅是一个举办比赛的网站。现在,它已经成为一个完整的基于项目的数据科学学习环境。我将在本节之后详细讨论 Kaggle 的这一方面。

2。“只有专家(博士或有多年经验的 ML 从业者)才能参加并赢得 Kaggle 竞赛”

如果你这样认为,我强烈建议你读读这个—

** [## 这个高中生自学成为一名人工智能巫师

如果你深入人工智能世界,你肯定知道谷歌云拥有的*台 Kaggle

mashable.com](https://mashable.com/2017/07/28/16-year-old-ai-genius/)

TL;博士: 一个高中生成为了 Kaggle 竞赛的大师简直就是(或者不那么简单,也许?)跟随自己的好奇心,一头扎进比赛中。用他自己的话说,

“我不知道算法背后的所有数学,但就实际使用它而言,我认为对它的工作原理有一个逻辑理解要重要得多。”

3。“我应该在参加 Kaggle 比赛之前多做几门课程,学习先进的机器学习理念,这样我赢的机会更大”——

机器学习最重要的部分是探索性数据分析(或 EDA)和特征工程,而不是模型拟合。事实上,许多 Kaggle 大师认为新手太快转向复杂的模型,而事实是简单的模型可以让你走得很远。

正如阿尔伯特·爱因斯坦所说—

“任何聪明的傻瓜都能把事情变得更大更复杂。朝着相反的方向前进需要一点天赋和很大的勇气。”

此外,许多挑战都涉及结构化数据,这意味着所有数据都存在于整齐的行和列中。没有复杂的文本或图像数据。因此,简单的算法(没有花哨的神经网络)通常是这类数据集的获胜算法。在这种情况下,EDA 可能是一个成功的解决方案与其他解决方案的不同之处。

现在,让我们继续讨论为什么应该使用 Kaggle 开始学习 ML 或数据科学..

为什么要入门 Kaggle?

原因 1——准确了解开始行动的必要条件

Kaggle Learn 上的机器学习课程不会教你 ML 算法背后的理论和数学。相反,它只专注于教授那些在分析和建模数据集时绝对必要的东西。同样,那边的 Python 课程不会让你成为 Python 专家,但它会确保你知道的足够多,可以进入下一个阶段。

这可以最大限度地减少你需要花费在被动学习上的时间,并确保你已经准备好尽快接受有趣的挑战。

原因 2——体现了培养学习能力的精神

我相信做项目是如此有效,以至于你的整个学习都应该围绕着完成一个项目。我想说的是,与其在你学到一些东西后寻找一个相关的项目,不如从一个项目开始,学习你所需要的一切来实现这个项目。

正如惠特尼·约翰逊在音阶大师播客中所说,

“基本上,你,我,每个人,我们都想学习和跳跃,然后重复。”

我相信这样学习会更令人兴奋和有效。

(几周前,我写了一篇关于上述方法论的文章。其名为—如何(以及为什么)开始构建有用的、现实世界中没有经验的软件。所以,如果你还没有 😃,就去看看吧)**

I believe that this is also true for courses and tutorials

但是,当你没有一个可以跳跃的项目时,这个想法就完全失败了。做一个有趣的项目是困难的,因为..

答..很难找到一个有趣的想法 而找到数据科学项目的想法似乎更加困难,因为需要有合适的数据集。

b)..我不知道该如何处理我知识中的那些漏洞。有时候当我开始一个项目时,我觉得有太多的事情我还不知道。感觉连学习构建这个东西的前提条件都不知道。我是不是力不从心了?我如何着手学习我不知道的东西?那就是所有动力开始消失的时候。

c)..我经常被“卡住”,好像在建立过程中我不断碰到一个又一个的障碍。如果我能有一群人,知道他们会如何解决这个问题,那该多好。

以下是 Kaggle 如何为所有这些问题提供解决方案的方法—

Soln。a → [**Datasets**](https://www.kaggle.com/datasets) [**Competitions**](https://www.kaggle.com/competitions) : 大约有 300 个竞赛挑战,都附有它们的公共数据集,总共有 9500+个数据集(还有更多在不断添加)这个地方就像是数据科学/ ML 项目创意的宝库。

索伦。b → [**Kernels**](https://www.kaggle.com/kernels) [**Learn**](https://www.kaggle.com/learn/overview) : 让我告诉你内核是如何有帮助的..
所有数据集都有一个公共内核标签,人们可以在这里发布他们的分析,以造福整个社区。所以,任何时候当你觉得不知道下一步该做什么的时候,你可以通过查看这些内核来获得一些想法。此外,许多内核是专门为帮助初学者而编写的。

Soln。c → [**Kernels**](https://www.kaggle.com/kernels) [**Discussion**](https://www.kaggle.com/discussion) : 随着我上面刚刚描述的公共内核,每个比赛和每个数据集也有自己的讨论论坛。所以,你总有地方提问。

除此之外,“在竞赛期间,许多参与者会写一些有趣的问题,强调数据集中的特性和怪癖,一些参与者甚至会在论坛上发布性能良好的基准测试代码。比赛结束后,获胜者通常会分享他们的获胜方案”(一篇名为《向最优秀的人学习》的文章)

原因#3 —解决实际问题的实际数据= >实际动机

Kaggle 上的挑战是由寻求解决他们遇到的真实问题的真实公司主办的。他们提供的数据集是真实的。所有的奖金都是真的。这意味着您可以学习数据科学/ ML,并通过解决现实世界的问题来实践您的技能。

如果你以前尝试过竞争性编程,当我说这些网站上的问题有时感觉太不现实时,你可能会有同感。我的意思是为什么我要写一个程序来找出一个数组中毕达哥拉斯三元组的个数?那有什么用呢!?

我并不是想断言这样的问题很容易;我发现它们非常难。我也不是想削弱存在此类问题的网站的重要性;它们是测试和提高你的数据结构和算法知识的好方法。

我想说的是这一切对我来说都太虚构了。当你试图解决的问题是真实的时候,你会一直想要改进你的解决方案。这将提供学习和成长的动力。这就是你参加 Kaggle 挑战赛的收获。

争论的另一方:“机器学习不是 Kaggle 竞赛”

我将不负责任地不提这场辩论的另一面,即认为 机器学习不是 Kaggle 竞赛 ,而 Kaggle 竞赛仅仅是 代表一种“旅游式 sh * t】的实际数据科学工作。**

嗯,也许那是真的。也许真正的数据科学工作并不像 Kaggle 竞赛中采用的方法。我没有从事过专业工作,所以我知道的不多,无法做出评论。

但是我所做的,很多时候,是利用教程和课程来学习一些东西。每一次,我都觉得教程/课程和我的学习动机之间存在脱节。我会学习一些东西,只是因为它在教程/课程中,并希望它在某个遥远、神秘的未来派上用场。

另一方面,当我在做 Kaggle 挑战时,我有一种学习的实际需求。我有一个阶段,可以让我立即应用我所学到的东西,并看到它的效果。这就给了动力和粘合剂,让所有的知识都粘在一起。

如何开始:

拥有所有这些雄心勃勃的、真实的问题有一个不利的方面,那就是对于初学者来说,这可能是一个令人生畏的地方。我理解这种感觉,因为我自己最*也开始使用 Kaggle。但是一旦我克服了最初的障碍,我完全被它的社区和它给我的学习机会所折服。

所以,在这里我试着告诉你如何开始:

第一步。涵盖基本要素

选择一种语言: Python 或者 R

一旦你做到了这一点,前往 Kaggle Learn 快速了解该语言、机器学习和数据可视化技术的基础知识。

Courses on Kaggle Learn

第二步。找到一个有趣的挑战/数据集

我建议你在出发时选择一个游乐场比赛或更受欢迎的比赛。通过这种方式,你至少可以找到一些旨在帮助新来者的公共内核。

记住你的目标不是赢得比赛。就是学习和提高自己的数据科学/ ML 知识。

Select one of these if you are still unsure

第三步。探索公共内核

他们将帮助你了解这个领域的一般工作流程,以及其他人在这个竞赛中采取的特殊方法。

通常,这些内核会告诉你一些你在 ML/ Data Science 中不知道的东西。当你遇到一个不熟悉的术语时,不要气馁。

知道你需要知道的是走向知识的第一步。

它们只是你需要学习来帮助你成长的东西。但在此之前..

第四步。开发自己的内核

去做你自己的分析吧。用你目前的知识尽可能多地构建。在您自己的内核中实现您从前面的步骤中学到的任何东西。

第五步。了解您需要做的事情,然后回到第 4 步

现在,你来学习。有时,它只是一篇短文,而有时它可能是一个有内容的教程/课程。请记住,您需要返回到步骤 3,并在您的内核中使用您所学的内容。这样你就创造了所需的循环——“学习、跳跃和重复”

第六步。通过返回到步骤 3 来改进您的分析

一旦你建立了一个完整的预测模型,你就到了这一步。所以,祝贺你!🎉

现在你可能想改进你的分析。要做到这一点,你可以回到第 3 步,看看其他人做了什么。可以给你改进模型的想法。或者,如果你觉得你已经尝试了所有的方法但是都碰壁了,那么在论坛上寻求帮助可能会有帮助。

An example of such a discussion

太好了!现在去做更多的挑战,分析更多的数据集,学习更新的东西!**

其他资源的链接

学习 Python:

Python 变得超级流行。这意味着有大量优秀的指南和教程可以帮助你开始学习这门语言。这是我第一次学习 Python 时使用的两个资源—

  1. https://www.python-course.eu/python3_interactive.php
  2. 向奥莱利学习 Python

显然,这些并不是学习 Python 的权威资源列表,但这些是我刚开始学习时最有用的。

机器学习文章:

在你深入研究一个领域之前,你可能想知道它是关于什么的。所以,这里有几篇文章对机器学习进行了有趣的介绍—

  1. 《如何学习机器学习,自我启动的方式 》作者 EliteDataScience 一篇写得很好的文章,在介绍机器学习方面做得很好,甚至还设计了一个自学课程!
  2. Vishal Maini本指南面向所有人。将讨论概率、统计、编程、线性代数和微积分中的基本概念,但要从本系列中获益,并不需要事先了解它们。”********
  3. 《最好的机器学习资源 作者Vishal Maini本文是上面提到的系列的一部分。我单独提到它,是因为它有一套非常好的、全面的与 ML 相关的链接。
  4. 机器学习很好玩byAdam geit gey看完这个系列就知道 ML 有什么酷了。虽然它很有技术性,但它可以成为对该领域了解更多的动力来源。****

数据科学博客:

这里有一些与数据科学相关的好博客,你可以去看看

  1. 方差解释
  2. 成为数据科学家
  3. https://www.markmeloon.com/
  4. https://juliasilge.com/blog/

编辑:发表这篇文章帮助我与世界各地令人惊叹的专业人士建立了数百种联系。

你想像我一样写作吗?

我开设了一门写作课程,教你如何在网上开始写作之旅。这就叫——清晰写作,清晰思考 而我是 免费赠送

Clear Writing, Clear Thinking — a free 5-week email course that’ll teach you how to write well

请在下面的评论区告诉我你的想法。

你可以在 Twitter 上关注我,或者在 LinkedIn 上联系我——我不会给你发垃圾信息。;-)

使用 nvidia-docker 为 R 和 Python 创建令人敬畏的深度学习环境

原文:https://towardsdatascience.com/use-nvidia-docker-to-create-awesome-deep-learning-environments-for-r-or-python-pt-i-df8e89b43a72?source=collection_archive---------6-----------------------

安装完整的支持 GPU 的深度学习环境(包括 RStudio 或 jupyter)和所有软件包需要多长时间?您必须在多个系统上这样做吗?在这篇博文中,我将向您展示我如何以及为什么使用支持 GPU 的 docker 容器来管理我的数据科学环境。在这第一篇文章中,你会读到:

  • 为什么我的数据科学工作流完全转向容器
  • docker 是什么,它与虚拟机相比如何(如果你已经知道,跳过它!)
  • 我如何构建我的数据科学映像
  • 如何在 GPU 支持下用 r-base、Keras 和 TensorFlow 构建容器

现状

您如何管理您的数据科学堆栈?我从来没有真正满意过我是如何做到的。在不同的机器上安装整个堆栈,包括我使用的所有包、GPU 支持、Keras 和 TensorFlow for R 以及底层的 Python 内容,是一个乏味而繁琐的过程。你最终会得到一个非常脆弱的工具链,而我是那种喜欢摆弄和破坏东西的人。这也有更多的负面影响。例如,不同机器上的环境不一样。我在至少三台不同的机器上进行数据科学研究:我的笔记本电脑,我的装有 GTX 1080 Ti 的工作站和 AWS 实例。我的开发环境和主机操作系统早就应该分离了。我一直都知道,虚拟机不是一个好办法,因为它们会产生很多开销,而且您必须提前分配所有想要使用的资源。

Docker 非常适合这个目的。它给你一个隔离的开发环境,保护你不把事情弄糟。当我看到英伟达 GPU 云(NGC)时,我知道这将解决我的问题。NGC 不是云服务,而是一个容器注册表,你可以在那里下载预构建和 GPU 支持的 docker 映像,这些映像针对不同的工作流进行了优化。有针对 TensorFlow,pytorch,caffe 等框架的图片。好的一点是:你不用关心任何驱动,框架或者包的安装。你可以马上启动 python,导入 TensorFlow,拷问你的 GPU。不幸的是,这些图像包含 NVIDIA 的专有软件来优化计算。你可以出于各种目的免费使用它,包括商业用途,但是你不允许重新发布他们的图片。这可能就是为什么你在像 Rocker 这样的项目中找不到它们的原因。你当然可以做的是发布 docker 文件,使用这些图像作为基础图像,这就是我在这篇博文中要做的。

为什么是 Docker?

如果你已经知道 Docker 是什么,以及它与虚拟机相比如何,你可以跳过这一节。我只给你一个简短的概述,有很多好的教程可以学习 Docker 是如何工作的。顺便说一下:我远不是 Docker 的专家,但你真的不需要成为这样的专家。看看下面这张图。左边显示了虚拟机是如何工作的:每个实例模拟一个完整的操作系统。对我来说,这从来都不是数据科学环境的选项。这会产生一些开销,但最重要的是,您必须提前分配资源,并且这些资源不会与您的主机系统共享。对于在同一台机器上使用主机作为通用系统和虚拟机进行数据科学的设置,这是不切实际的。

对于这种情况,使用容器隔离要好得多:它基本上只是一个隔离的文件系统。它使用你的主机系统的内核,这当然增加了很少的开销。不幸的是,对于 Windows 或 Mac 上的 Docker 来说,情况并非如此,因为它在底层使用的是 Linux 虚拟机。即使在我的笔记本电脑上,我也总是尝试完全切换到 Linux,正因为如此,我做到了。但是,即使你想坚持使用 Windows 或 Mac:你可能正在使用 Linux 的工作站或云实例。真正有趣的部分显示在图像的右侧:带有 nvidia-docker 运行时的容器。那些容器可以使用主机系统的 GPU。您只需要一个支持 CUDA 的 GPU 和主机系统上的驱动程序,仅此而已。

现在简单介绍一下 docker 的工作原理以及与之相关的术语。Docker 中最重要的两个概念是图像和容器。该图像包含创建容器的蓝图。它是分层构建的,可以只包含操作系统的基础知识,也可以包含更复杂的软件堆栈。容器是 docker 图像的一个实例。除了您可以访问您的主机系统的资源之外,它与虚拟机的感觉完全相同。因此,当您从一个映像启动 docker 容器(并告诉它是交互式的)时,您将进入一个 shell 环境,就像您登录到一个 VM 一样。容器启动速度也非常快。它几乎不可识别,而在虚拟机中,你必须启动操作系统。

要构建 docker 映像,您必须编写一个 docker 文件。有两种方式可以做到这一点:使用父映像或从头开始,只有当您想要创建新的基础映像时才需要这样做。在大多数情况下,您将使用基础映像作为父映像,并在此基础上构建您的软件堆栈。如果你想在 Ubuntu 16.04 上建立你的映像,你的 docker 文件的第一行应该是:FROM ubuntu:16.04。获取图像最常见的方式是从 docker hub 获取图像,docker hub 是一个共享图像的*台。Docker 自动完成这项工作,或者您也可以使用 docker pull ImageName 手动提取图像。在 Ubuntu 和其他常用图像的情况下,有来自 docker 工作人员的官方维护图像。正如您将在下一节中看到的,您还可以从 docker hub 之外的其他存储库中提取图像。

获取 Docker 和 TensorFlow 容器

Docker 和 nvidia 运行时非常容易安装。以下命令使用 get.docker.com 的安装脚本安装免费的 docker 社区版。这个脚本可以在所有常见的 Linux 发行版上安装 docker(详情请看 get.docker.com 的):

*#Install docker via get.docker script*
curl -fsSL get.docker.com -o get-docker.sh
sh get-docker.sh

要安装 nvidia-docker 运行时,您必须添加它们的软件包存储库,并安装和重新加载 docker 守护程序。我使用 Ubuntu 16.04 作为主机系统,但是这应该可以在任何使用 apt 的基于 debian 的发行版上工作。

*#Add the package repositories for nvidia docker*
curl -s -L [https://nvidia.github.io/nvidia-docker/gpgkey](https://nvidia.github.io/nvidia-docker/gpgkey) | \ 
    apt-key add -curl -s -L [https://nvidia.github.io/nvidia-docker/ubuntu16.04/amd64/nvidia-docker.list](https://nvidia.github.io/nvidia-docker/ubuntu16.04/amd64/nvidia-docker.list) | tee /etc/apt/sources.list.d/nvidia-docker.listapt-get update

#*Install nvidia-docker2 and reload the Docker daemon configuration* 
apt-get install -y nvidia-docker2 pkill -SIGHUP dockerd

要检查是否一切正常,您可以加载 cuda 映像并执行 nvidia-smi:

*#Test nvidia-smi with the latest official CUDA image*
docker run --runtime=nvidia --rm nvidia/cuda nvidia-smi

该命令从 docker hub 下载 cuda 映像,基于该映像启动一个容器,在容器内执行命令 nvidia-smi,然后立即离开容器并删除它。您应该会看到类似这样的内容:

这意味着我的 GTX 1080Ti 在集装箱内可用!这个 cuda 图像是 NVIDIA 在 docker hub 上托管的图像之一。对于优化的深度学习容器,你必须注册英伟达 GPU 云( NGC ),它不是云服务提供商,而是类似于 docker hub 的容器注册表。它是免费的,你可以将这些容器用于你自己的或商业的目的,但是你不允许再分发它们。注册后,在左侧菜单中选择配置,并生成一个 API 密钥。有了这个键,你可以在 NVIDIA 注册表中注册 docker 安装。你应该把钥匙保存在安全的地方。使用 docker login nvcr.io 命令进行注册。作为用户名,您必须使用\(oauthtoken(带\)符号!)和 API-Key 作为密码。现在,如果您使用以下命令,docker 应该下载优化的 TensorFlow 容器:

docker pull nvcr.io/nvidia/tensorflow:18.04-py3

我如何建造

我在创造我在不同阶段使用的环境。在第一张图中,我只是安装了 R-base、Python 和 R 的 Keras、R 的 TensorFlow 以及它们的依赖项。在下一张图中,我将在其上安装 RStudio-Server 和 jupyterlab。在第三张图中,我根据自己的需要定制了 RStudio,并安装了我想使用的所有包。

最后一步是安装更多的软件包。如果我意识到在工作会话期间我需要一个额外的包,我可以像在 RStudio 中那样自然地安装它。完成后,我将这个包添加到第四张图片中。如果我使用第三个,我每次都必须重新安装所有的软件包,这需要一些时间。使用 docker,您还可以提交对容器的更改。这也是永久安装新软件包的一种方式。我决定不这样做,以跟踪我添加到我的图像。分步创建这些容器还有另一个好处:您可以将图像用于不同的用例。例如,您可以使用 RStudio 图像创建一个神经网络并保存它。然后,您可以将这个模型加载到基本容器中,并创建一个基于 python 的 flask 微服务来部署它。或者你想做一个使用图像识别的闪亮应用程序。您可以使用 r-base 容器,添加 shiny 并部署它。或者您想为同事提供不同的定制 RStudio 版本。

安装 R-base 和 Keras

由于我们已经从 NVIDIA 获得了 TensorFLow 容器,现在我们可以开始构建 r-base 映像。构建 docker 映像本质上就是编写一个 shell 脚本,在您的映像中安装您想要的所有东西。就像我已经指出的,它被写在一个名为 Dockerfile 的文本文件中。当您运行 docker build -t YourNameTag 命令时。在您的 docker 文件的文件夹中,docker 从您用 from 定义的基本映像启动一个容器,并在这个容器中运行您在 docker 文件中编写的内容。docker 在这个容器中执行什么是用 RUN 定义的。看看下面的 docker 文件:

FROM nvcr.io/nvidia/tensorflow:18.04-py3

LABEL maintainer="Kai Lichtenberg <kai@sentin.ai>"

*#Arguments*
ARG USER="docker"
ARG myUID="1000"
ARG myGID="1000"

*#Specifiy R and Keras Version*
ENV R_BASE_VERSION=3.4.4
ENV KERAS_VERSION=2.1.5

*#Set a user* 
RUN groupadd --gid "${myGID}" "${USER}" \
  && useradd \
    --uid ${myUID} \
    --gid ${myGID} \
    --create-home \
    --shell /bin/bash \
${USER}

如果我在这个文件上运行 docker build,docker 会做以下事情:它基于我们下载的 TensorFlow 容器启动一个容器,添加一些环境变量(ARG 和 ENV)并创建一个组和一个用户。请注意,ARG 定义了仅在构建过程中可用的变量,您可以使用 docker build 命令为这些变量传递一个值。因此,当您使用 docker build-build-arg USER = Kai 启动命令时,默认的 USER="docker "将在构建过程中被覆盖。用 ENV 定义的变量是持久的,在从创建的映像启动的容器中也是可用的。下一步,我们安装 apt 所需的软件包:

*#Install packages needed*
RUN apt-get update \ 
  && apt-get install -y --no-install-recommends \
    ed \
    locales \
    vim-tiny \
    fonts-texgyre \
    gnupg2 \
    libcurl4-openssl-dev \
    libssl-dev \
    libssh2-1-dev \
    sudo \
    virtualenv \
&& rm -rf /var/lib/apt/lists/*

下一件事是安装 r。我用的是 CRAN 为 Ubuntu 提供的二进制文件。通常情况下,CRAN 很快就会发布最新版本,但目前(5 月 19 日)R 3.5 无法通过 CRAN 获得(阅读这里为什么)。我会等 3.5 出现在 CRAN 上。如果你非常想拥有 R 3.5,你可以像在这个docker 文件中一样安装它,并从源代码安装软件包。下一步中显示的安装与 Rocker 项目中的 r-base docker 文件相同。它正在安装 littler,这是一个方便的 CLI 接口,用于 R,r-base,r-base-dev 和 R-推荐用于 R_BASE_VERSION 环境变量中指定的 R 版本。它还在/usr/local/bin 中为 littler 创建了链接,使它在命令行中可用。

*#Add mirror* 
RUN echo "deb [http://cran.rstudio.com/bin/linux/ubuntu](http://cran.rstudio.com/bin/linux/ubuntu) xenial/" >> /etc/apt/sources.list \
  && gpg --keyserver keyserver.ubuntu.com --recv-key E084DAB9 \
  && gpg -a --export E084DAB9 | apt-key add -

*# Install R-base (rocker/r-base with little modification)
# Now install R + littler, create a link in /usr/local/bin
# Set a default CRAN repo, make sure littler knows about it too*
RUN apt-get update \
  && apt-get install -y --no-install-recommends \
    littler \
    r-cran-littler \
    r-base=${R_BASE_VERSION}-* \
    r-base-dev=${R_BASE_VERSION}-* \
    r-recommended=${R_BASE_VERSION}-* \
  && echo 'options(repos = c(CRAN = "https://cran.rstudio.com/"), download.file.method = "libcurl")' >> /etc/R/Rprofile.site \
  && echo 'source("/etc/R/Rprofile.site")' >> /etc/littler.r \
  && ln -s /usr/share/doc/littler/examples/install.r /usr/local/bin/install.r \
  && ln -s /usr/share/doc/littler/examples/install2.r /usr/local/bin/install2.r \
  && ln -s /usr/share/doc/littler/examples/installGithub.r /usr/local/bin/installGithub.r \
  && ln -s /usr/share/doc/littler/examples/testInstalled.r /usr/local/bin/testInstalled.r \
  && install.r docopt \
  && rm -rf /tmp/downloaded_packages/ /tmp/*.rds \
  && rm -rf /var/lib/apt/lists/*

R 的 TensorFlow 和 Keras 包通过 reticulate 包连接到 python。这意味着我们需要为 R 和 python 安装两个包。两个 R 包都是通过 littler 提供的 github 安装例程安装的。因为我们使用的是 NVIDIA TensorFlow 映像,所以我们只需要关心 python 的 Keras(tensor flow 已经安装)。如果您以前使用过 Keras for R,您可能会注意到您必须调用函数 install_keras()来安装 python 后端。在我们的情况下,这已经完成了。唯一附加的事情是该函数创建了虚拟环境 r-tensorflow。在 python 中使用虚拟环境是一个很好的实践,尽管在 docker 容器中这是不必要的,因为它是双重隔离的。

*#Install tensorflow and keras*
ENV WORKON_HOME=/home/${USER}/.virtualenvs

RUN install2.r devtools remotes \
  && installGithub.r rstudio/tensorflow \
  && installGithub.r rstudio/keras \
  && virtualenv --system-site-packages /home/${USER}/.virtualenvs/r-tensorflow --python=python3.5 \
  && /bin/bash -c "cd /home/${USER}/.virtualenvs/r-tensorflow/bin/; \
     source activate; \
     pip3 --no-cache-dir install git+git://github.com/fchollet/keras.git@${KERAS_VERSION}"

好了,现在我们有了用 R 进行深度学习的基本图像!你可以在这里找到完整的档案。在下一部分中,我将使用 RStudio、jupyter 和定制来创建图像。如果你想获得这方面的更新,请在推特上关注我!

最初发表于 凯·利希滕伯格

使用 t-SNE 降低代谢组学数据集的维数

原文:https://towardsdatascience.com/use-of-t-sne-to-reduce-the-dimensionality-of-metabolomics-datasets-f8a36120ca32?source=collection_archive---------4-----------------------

任何对代谢组学研究数据集有经验的人都会有需要降低其维数的经验。探索性分析所需的可视化极大地受益于将变量减少到可管理的数量。此外,一些变量可能是无信息的或多余的。当执行后面的统计分析或模型时,这些变量会增加计算时间,并会影响它们的性能。

降维可以基于信息特征的选择,或者基于更少数量的变量的合成,其最佳地保留了原始数据集中存在的信息。在代谢组学中执行维数减少的标准方法是主成分分析 (PCA)。然而,越来越多的新方法在减少变量数量时有望获得更好的性能。

一种趋势降维方法被称为 t 分布随机邻居嵌入 (t-SNE)。有多个在线例子显示了 t-SNE 优于 PCA 的优势(这里的例子)。然而,研究往往是根据以前是如何完成的来进行的。这种效应被称为路径依赖,会滞后研究效率,因为更好的方法会发现一些阻力,需要在该领域建立标准。我这篇博文的目的是展示 t-SNE 应用于代谢物定量数据集有多容易,以及应用它可能带来的好处。

MTBLS1 代谢研究包括对 48 名二型糖尿病患者的尿液样本和 84 份尿液对照样本之间的代谢差异的研究。存储库包含一个预处理代谢物量化数据集,包含 132 个观察值、188 个量化变量和一个标识符变量。许多变量是有噪声的,因为它们没有代表性的代谢物,或者是多余的,因为它们介导相同代谢物的信号。在 R 中,加载数据集和执行降维包括以下步骤:

库(tsne)
库(readxl)
ADG _ 变换 _ 数据< -读取 _ excel(" ADG _ 变换 _ 数据. xlsx ")
ADG _ 变换 _ 数据$ 主 id = NULL
tsne _ ADG _ 变换 _ 数据= tsne(ADG _ 变换 _ 数据,困惑=50)

通过比较变量降维前后的样本分类,可以检验降维方法是否有效地综合了数据集的信息。预计更好的降维技术有助于提高样本分类的性能,因为它们以所选的分类算法能够更好地“理解”的方式分布和合成数据。

在原始数据集中进行随机森林分类时,样本分类时的出袋预测误差为 21.97%。当对输出维数不断增加的原始数据集执行 t-SNE 和 PCA 时,结果如下图所示(原始数据集中 21.97%的误差用黑线标记):

可以观察到通过 PCA 的维数减少几乎不能提高 MTBLS1 数据集中样本分类的性能。为了开始改善原始性能,需要将减少限制到至少 25 个变量。相比之下,t-SNE 帮助样本分类实现了低于 15%的误差。此外,它只需要略多于 10 个输出变量来实现这些好处。

这是一个 t-SNE 是一种非常有前途且易于应用的技术的例子,以在代谢组学研究中的样品分类期间实现更好的性能。

利用文本检索和搜索引擎技术进行税收分类

原文:https://towardsdatascience.com/use-of-text-retrieval-and-search-engines-technology-for-tax-classification-d903fa3cf948?source=collection_archive---------2-----------------------

使用信息检索和人工智能(AI)技术来辅助财政分类(文本检索、信息检索、等级和产品税 HS 上应用的搜索)

摘要:使用 word2vec、BagofWords、unigram、bigram、标记化、文本相似性、OkapiBM25 +等技术来处理可用于税收分类建议的子项,如 TEC Mercosul(南美 HS(协调制度)本地定制)文本中所述,并根据搜索单词列表进行排序

正确的税收分类总是一个挑战。巴西版的共同对外关税文本有数万个单词,100 个章节,10,000 多个可用于分类的子项目,一个复杂且不总是统一的层次结构,此外还有章节注释、章节注释、总则等。在这项工作中,我们提议使用计算机来提高这些精确的数字,因为在这方面,计算机已经超过了人类(随着人工智能和机器学习的最新进展——人工智能机器学习和深度学习开始在处理文本的统计分析以及物体的视觉和识别方面达到我们,在某些情况下超过了人类)。

本文结构分为四个部分,相对独立。这样,读者可以直接跳到他最感兴趣的地方。第 1 部分处理概念部分,并对问题进行分析。第 2 部分和第 4 部分将更具技术性。如果您只想下载并测试演示本文概念的软件,可以直接阅读第 3 部分。

第 1 部分 —对技执委案文的分析以及对财政分类挑战的思考。首先是文字处理和选择路径。

第 2 部分—Python 编程语言中的测试和统计(带代码)。矢量化技术、二元模型、词干化、查询相似度和 OkapiBM25 +的应用。

第 3 部分——一个用 Java 编程语言开发的用户友好的全功能应用——在 GitHub 网站上有代码可以下载和“分叉”。

第 4 部分-讨论使用机器学习和其他技术的可能改进。

参考资料 —参考书目和在线资源

TEC/NCM——南方共同市场共同对外关税,将在第一部分中制定。

协调制度是 TEC 的国际版本,在第 1 部分也有解释。

第一部分

为了分析 TEC 文本,第一步是获取其最新版本。TEC 是一种法律规范,由 MDIC工业、外贸和服务部在巴西发布。MDIC 在下面的链接中以 Word 和 Excel 格式发布了 TEC 的最新版本。

【当前档案】www.mdic.gov.br MDIC

在 Word 中打开 TEC,我们可以开始分析它的结构。基本上,它有六个部分:

章节标题
缩写和符号
协调制度解释通则
补充通则
航空部门产品征税规则
南方共同市场共同术语(NCM)和共同税率

对于我们的工作来说,重要的部分是第六部分,依次划分如下:

章节(描述)
章节注释
章节(描述)
章节注释
表 NCM,描述,TEC

这里有一个附录和一个重要的观察:税收分类的任务是一项技术工作,它可能依赖于其他信息和具体知识,这些信息和知识不会写入技术执行委员会的文本,如冶金、化学或纺织方面的知识。除了关于税收分类规则的知识(在 TEC 中描述),语法和法律解释,产品分解混合案例,等等。因此,立法根据货物的税收分类(第 7.482 / 11 号法令第十九节第 15 条和 RFB 2014 年 5 月第 1464 号条例等)确定了税务机关(联邦税务局的财政审计员)。

还应当记住,我们现在所称的“TEC”是国际条约、传统、技术研究和标准的汇编,首先在世界海关组织签署的所谓的《布鲁塞尔国际公约》中的国际协调制度(HS)中进行汇编,然后扩大到南锥体共同市场 NCM——南锥体共同市场货物共同术语的经验和需要。此外,在巴西,还有 RIPI 的附加联邦法规—工业化产品税收法规以及 ICMS —州法规。

由于本文的总体重点不是财政分类或立法,我们不会深入探讨这个主题。一般分类问题暴露出来后才发现,在我们甚至研究 TEC 的文本之前,至少在现阶段,100%自动税收分类是一个乌托邦。这位作者设想的最佳解决方案是一个建议系统,非常类似于当我们在“谷歌”或另一个互联网搜索引擎上进行搜索时,我们从网页上收到的建议。

在这项工作中,所提出的系统将对 TEC 子项目进行“评分”,并以降序显示结果。毕竟有一万多种可能。然后我们会让计算机通过一个我们称之为“粗筛”的东西,我们只看几个排名更好的位置。如果运气好的话,我们可能只需要看看榜单的前三四名。

通过“运气”,我们也可以定义“正确”的问题。在这种情况下,问题是要分类的商品的描述。因此,当局(财政审计员)、进口商、制造商、技术助理、报关行、代理人或其他有责任描述商品的人必须这样做,以便正确识别产品并确定其正确的税收分类(RFB 680/2006 和海关条例第 711 条等)。

总之,我们可以从教学上把税收分类任务分成两步:描述产品;2.将描述插入正确的分类中。因为 TEC / NCM 是分等级的,我们可以用树来类比。通常,我们通过这棵树的树枝来寻找正确的位置。但是有一种可能性,我们正在看一个分支,而正确的项目在另一个分支,我们看不到它,因为我们在错误的分支中使用了非常相似的子项目。克服这种分层搜索是该系统的目标。

再打个比方,让我们想想一位埃及古物学者:在第一步中,他准确地定义了探险队要寻找的人工制品,并通过之前的研究描述了寻找的方式:人工制品怎么样,会是什么考古遗址,等等。第二步是探险本身。在这方面,团队被画廊,隧道等纠缠。你可以在一个房间里找到一件非常相似的艺术品,但是不要在隔壁房间里找,艺术品实际上是在那里被找到的。为了避免这种情况,我们的机器人将检查所有的房间,并根据与第一步中描述的工件的相似性对找到的工件进行评分。

该分数将基于描述所搜索内容的句子和每个 TEC 子项目之间的相似关系。

在税收分类的情况下,还有第三步,因为一个职位或章节或另一个职位或章节可能被排除在外,或者可能有一个条款或章节注释或其他类型的例外作为一般规则之一强加的条件。这项任务也可以通过自然语言处理技术实现自动化,但是这还不在 T2 的工作范围之内。

现在,我们所能理解的“TEC 的子项”。

分析“NCM 表,描述,TEC”部分,我们可以看到并不是所有的行在“TEC”列中都有值:

First page of TEC, Word version. Note the third column of the table

在屏幕上,我们可以很容易地注意到上面描述的结构(第二十章(描述),章节注释,NCM 表。我们还注意到,表中只有几行在第三列中有值(TEC%)。

因此,NCM 的结构是分等级的,按照协调制度:章(2 位数),位置(4 位数),子位置 1 和 2 (5 和 6 位数)。南方共同市场增加了两位数:项目和分项(分别为第 7 位和第 8 位)。只有包含 TEC 税率(以及 IPI 和 ICMS 自己的税率)的完整行、较高的订单才能用于税收分类。

但是回头看看表格,我们看到这些行中的描述字段通常是 Spartan。例如,分项 NCM 0102.21.10 只提到“怀孕或有脚印”,更糟糕的是,下面的 0102.21.90 只提到“其他”。

所以我们来创建一个概念,叫做“TEC List with full description”。这样,每个子项、项或子项都必须用其层次树的串联来描述。因此,我们知道,子目 0102.21.10 指的是“活牛——家畜——纯种配种动物”,子目 0102.31.90 指的是“活牛——水牛——纯种其他”。肯定比以前信息量大得多。我们仍然可以考虑在这个层次结构中添加章节的描述。

尽管每行提供的信息更多,但要搜索的单词总数会更大,因为许多单词会重复出现。还有,一些表格描述的字数本身就已经很大了,串联更多的描述会让一切变得更大。但是我们不能失去焦点:我们的目标是产生线条,以便计算机,而不是人类,寻找并包含单词的出现。在这一点上,计算机比我们人类好得多。这条被提议的线将被数字机器“消化”和(预)处理,它将只返回给人类它从 10,000 多个选项中寻找的“菲力”。

第二部分

GitHub 中提供了一个包含该文本所有代码的脚本。

[## 将论坛标记为已读

classifier fiscal——这个 JAVA 系统使用文本中的搜索和处理技术来评分…

github.com](https://translate.googleusercontent.com/translate_c?depth=2&hl=en&rurl=translate.google.com&sl=auto&sp=nmt4&tl=en&u=https://github.com/IvanBrasilico/ClassificadorFiscal&usg=ALkJrhhLSkthjCLrN65GJ4pSKq0h77GLhQ)

一般的想法放在第 1 部分(“创建带有层次树的级联描述的 TEC 列表,只用于带有非零值 TEC 列的表行。”),我们需要开始动手了。在 2017 年年中,要处理文本、字符、矢量,肯定没有比一个好的友好的 Python 脚本更快更有趣的方法了。

Beautiful is better than ugly. 
  Explicit is better than implicit. 
  Simple is better than complex. 
  Complex is better than complicated.In The Zen of Python

此外,为了处理我们获得的数据,Python 生态系统有许多库,如 scikit-learn、NLTK、Theano、Tensor Flow,它们以最先进的形式实现了我们可能需要的许多算法。所以不用多此一举KeepingItSimple*****S*tupid(如果可以的话),我们开始工作吧!

第一项任务是分析文件的行,并考虑组装单词列表的处理。这将是一个简单的,逐行处理的文本文件。我们将尝试确定列表组合的标准,我们将制作“手指”,希望没有例外,文件的结构尽可能统一。我们称之为我们的 TEC 列表。然后,我们将通过创建一个包含完整描述的列表来处理第一个。我们称之为 TECResumo。

给定一组文档,第二步是提取你的“词汇”。这是应用“单词矢量化”和“BagofWords”技术的最重要部分。我们通过创建唯一单词的向量来遍历整个集合,并将它们称为 vocab。然后,对于 TEC 列表中的每一行,我们将组装一个与词汇表大小相同的向量。这将是一个名为 TEC vectors 的向量列表,包含每个单词的出现次数。使用“文本检索”中的技术术语,SUM 列表中的每一行都是一个文档,所有行构成一个集合。TTC 向量是每个文档的字数,而 vectorVocab 是集合的字数。这将是我们工作的核心。

*## Format of generated variables: 
  ## 
  ## TEC list: string list with each line of the text file 
  ## listCapitulos: list of list containing title, description, and notes of each chapter 
  ##NCM list: list list with each line containing the line code and after the description 
  ##TECResumo list: string list containing the complete code and "complete" description of non-null TEC lines 
  ## vocab: dict with key word and value occurrence count 
  ##TEC vectors, vectorVocab: count of occurrences of the word per line and total count of occurrences of the word in the Collection 
  ## In technical terms, each line of the list will be a collection document, vocab is the collection vocabulary*

第一步,处理 TEC 并创建我们的第一个列表“TEC 列表”的函数。第一个列表将与 TEC 的原始数据(原始数据)组合在一起,向用户显示与原始文件中完全一样的列表。使用 Word 本身或 LibreOffice 中的文件 tec * *—Word-complete . docx,我们将内容导出到文本文件。该文件将类似于下图:

TEC file in plain text format

我们需要做的是找到具有以下结构的行:第 1 行至少有两个数字和一个点,其中点在第 2 列或更大的列中,后面跟着一行只有文本。我们也将尝试提取章节和笔记,寻找以字母“Cap”开头的行,然后提取下一行直到“Note”行将标题和注释设置为“__ ”,以捕获注释。

首先,我们用文件的所有行组装一个列表

*def montaTEC (): 
  arq = open ("src / org / sort / resources / tec.txt") 
  TACfileset = arq.readlines () 
  return TACWatchlist*

然后是章节列表

*def montaCapitulos (plistaTEC): 
  listCapitulos = [] 
  r = 0 
  while (r <len (plistaTEC)): 
  line = plistaTEC [r] 
  if (line [0: 3] == "Cap"): #Search chapters 
  chapter = line 
  description = "" 
  r = r + 1 
  line = TEC list [r] 
  while (line [0: 4]! = "Note"): 
  description = description + line + "" 
  r = r + 1 
  line = TEC list [r] 
  notes = "" 
  r = r + 1 
  line = TEC list [r] 
  while (line [0: 4]! = "____"): 
  notes = notes + line + "\ n" 
  r = r + 1 
  line = TEC list [r] 
  list.append.append ([chapter, description, notes]) 
  r = r + 1 
  return listCapitulos*

以下是 NCM 等级列表:

*def montaNCM (plistaTEC): 
  listNCM = [] 
  r = 0 
  while (r <len (plistaTEC)): 
  line = plistaTEC [r] 
  if (len (line) <12): 
  i = line.find (".") 
  if ((i> = 2) and (line [0] .isnumeric ())): 
  r = r + 1 
  line2 = plistaTEC [r] 
  if (not line2 == "\ n"): # Eliminates number sequences (in part 5 TEC Taxation Rule for Products of the Aeronautical Sector) 
  if (not line2 [0] .isnumeric ()): # First test if line is not empty 
  ncm = line 
  description = line2 
  line3 = plistaTEC [r + 1] 
  tec = "" 
  if ((not line3) or (line3 [0] .isnumeric ())): 
  r = r + 1 
  tec = row3 
  listNC.append ([ncm.strip (), description.strip (), tec.strip ()]) 
  r = r + 1 
  return listNCM*

最后,也是最重要的部分。汇集我们的“文档”,一个包含分类“可用”位置代码(第二列非零)的单词和字母(字符串)列表,以及整个层次结构的描述

*def montaTECResumo (plistaNCM): # Mounts TEC lines containing II with description containing concatenation of line description and "parents" - positions, subheadings, etc. 
  listTECResumo = [] 
  r = 0 
  while (r <len (plistaNCM)): 
  line = plistaNCM [r] 
  II = line [2] 
  if (not II == ''): # Is a valid / "selectable" Classification, search for "parents" 
  code = line [0] 
  description = line [1] 
  s = r-1 
  while (True): #Loop DNA.  Browse the "up" list by looking for the family tree ... 
  line = plistaNCM [s] 
  code2 = line [0] 
  description = line [1] 
  lcodigo = code [0: 2] + "." + code [2: 4] 
  if (lcode == code2): 
  description = description + "" + descricao2 
  listTECResumo.append (code + "" + description) 
  break 
  lcodigo = code [0: 6] 
  if (lcode == code2): 
  description = description + "" + descricao2 
  lcodigo = code [0: 7] 
  if (lcode == code2): 
  description = description + "" + descricao2 
  lcodigo = code [0: 8] 
  if (lcode == code2): 
  description = description + "" + descricao2 
  lcodigo = code [0: 9] 
  if (lcode == code2): 
  description = description + "" + descricao2 
  s = s - 1 
  if ((s == - 1) or ((rs)> 100)): # Exception found, abort! 
  listTECResumo.append (code + "" + description) 
  break 
  r = r + 1 
  return listTECResumo*

我们在这里已经编纂得够多了。所以,说好的编程实践已经过时了,可以写一些自动化测试,或者至少查看我们的结果。我们来做个小预告:

*def Display (): 
  listTEC = montaTEC () 
  print ("RAW File") 
  print (TEC list [0:19]) 
  print (TEC list [5001: 5020])listCapitulos = montaCapitulos (listTEC) 
  print ("Chapterlist") 
  print (ListCapitulos [1]) 
  print (ListCapitulos [50])listNCM = montaNCM (listTEC) 
  print ("listNCM") 
  for line in listNCM [0: 9]: 
  print (line) 
  for line in listNCM [1001: 1010]: 
  print (line)print ("Assembling documents ...") 
  listTECResumo = montaTECResumo (listNCM) 
  print ("Total documents in collection:") 
  print (len (listTECResumo)) 
  print ("First lines:") 
  for line in listTECResumo [0: 9]: 
  print (line) 
  print ("Some random lines:") 
  from random import randint 
  for i in range (1.10): 
  print (listTECResumo [randint (0, len (listTECResumo))])View ()(I.e. 
  ======= RESTART: D: \ Users \ Brazil \ Downloads \ Sorts \ ncmutils.py ======= 
  RAW file 
  \ n ',' \ n ',' \ n ',' \ n ',' \ n ',' \ n ' COMMON FOREIGN TARIFF (TEC) \ n ',' \ n ',' \ n ',' \ n ',' \ n ',' 'BRASIL \ n', '2 0 1 7 \ n'] 
  \ N ', '10 \ n', '1003.90.80 \ n', '1003.90.10 \ n', 'Other \ n', \ n ',' , in grain \ n ', '10 \ n', '1003.90.90 \ n', 'Other \ n', '10 \ n ',' \ n ',' \ n ',' \ n ', '10 .04 \ n ',' \ n ',' 1004.10.00 \ n '] 
  listCapitulos 
  ('Chapter 2', 'Meat and edible meat offal', '1 This chapter does not cover: \ n \ na) \ tFor items 02.01 to 02.08 and 02.10, products unfit for human consumption; \ n \ nb) \ tThe animal fats, bladders and stomachs (heading 05.04) or animal blood (headings 05.11 or 30.02); \ n \ nc) \ t Animal fat, excluding products of heading 02.09 (Chapter 15 ). \ n \ n '] 
  'For the purposes of subheadings 5209.42 and 5211.42, the expression "Denim fabrics" means woven fabrics of yarns of different colors, with a twill not exceeding 4, comprising broken twill (sometimes referred to as satin 4), with warp on the right side, the warp yarns having the same single color and those of the weft, whitened or dyed gray or a lighter shade than of the warp threads. \ n \ n '] 
  CNM list 
  ['01 .01 ',' Live horses, crabs and mules'] 
  ['0101.2', '- \ tHawks:', ''] 
  ['0101.21.00', - 'Pure-bred breeding animals', '0'] 
  ['0101.29.00', '- \ tOutros', '2'] 
  ['0101.30.00', '- \' Asinos', '4'] 
  ['0101.90.00', '- \ tOutros', '4'] 
  ['01 .02 ',' Live bovine animals', ''] 
  ['0102.2', - 'Domestic animals:', ''] 
  ['0102.21', - 'Pure-bred breeding animals', ''] 
  ['0903.00.10', 'Simply shackled', '10'] 
  ['0903.00.90', 'Other', '10'] 
  ['09 .04 ',' Pepper of the genus Piper;  chilies and peppers of the genus Capsicum or of the genus Pimenta, dried or crushed or ground.], 
  ['0904.1', '- \ Pepper of the genus Piper:', ''] 
  ['0904.11.00', '- \ tNot crushed or powdered', '10'] 
  ['0904.12.00', '-' or powdered ',' 10 '] 
  ['0904.2', - - Peppers and peppers (Capsicums of the genus Capsicum or of the genus Pimenta: ',' '] 
  ['0904.21.00', - - - - - - - - - - - - - - - - - - - - - - - 
  ['0904.22.00', '-' or 'powdered', '10'] 
  Assembling documents ... 
  Total documents in collection: 
  10147 
  First lines: 
  0101.21.00 - Pure-bred breeding animals - Horses: Live horses and cousins. 
  0101.29.00 - Other - Horses: Live horses and asses, mules and hinnies. 
  0101.30.00 - Asinines Horses, sharks and mules, live. 
  0101.90.00 - Other Live horses and asses, mules and hinnies. 
  0102.21.10 Pregnant or bred breeding animals - Pure-bred breeding animals - Domestic bovine animals: Live bovine animals. 
  0102.21.90 Other - Pure-bred breeding animals - Domestic bovine animals: Live bovine animals. 
  0102.29.11 Breeding or breeding on foot For breeding - Other - Domestic bovine animals: Live bovine animals. 
  0102.29.19 Other For breeding - Other - Domestic bovine animals: Live bovine animals. 
  0102.29.90 Other - Other - Domestic bovine animals: Live bovine animals. 
  Some Random Rows: 
  5112.19.20 Of fine hairs - Other - Containing 85% or more by weight of wool or fine animal hair: Woven fabrics of combed wool or of fine animal hair. 
  5403.41.00 - Of viscose rayon - Other multiple or cabled yarn: Artificial filament yarn (other than sewing thread), not put up for retail sale, including artificial monofilament of less than 67 decitex. 
  5102.11.00 - Of Kashmir goat - Fine hair: fine or coarse animal hair, not carded or combed. 
  4107.92.10 Of bovine animals (including buffaloes) - Divided with the blossom side - Other, including strips: Leather further prepared after tanning or crusting and parchment-dressed leather, of bovine (including buffalo) or of equine, without hair on, whether or not split, other than leather of heading 41.14\. 
  2916.20.90 Cyclanic, cyclenic or cycloterpenic monocarboxylic acids, their anhydrides, halides, peroxides, peroxyacids and their derivatives, unsaturated acyclic monocarboxylic acids and cyclic monocarboxylic acids, their anhydrides, halides, peroxides and peroxyacids;  their halogenated, sulphonated, nitrated or nitrosated derivatives. 
  5204.11.31 Of two ropes Of bleached or colored cotton yarn of a size not exceeding 5,000 decitex per single yarn - Containing 85% or more by weight of cotton - Not put up for retail sale: whether or not put up for retail sale: 
  8704.32.90 Other - Of a maximum permissible gross weight exceeding 5 tonnes - Other, with spark-ignition internal combustion piston engine (spark) *: Motor vehicles for the transport of goods. 
  5206.24.00 - Of a denomination less than 192,31 decitex but not less than 125 decitex (metric number exceeding 52 but not exceeding 80) - Single yarn of combed fibers: Cotton yarn (other than sewing thread) containing less than 85% by weight of cotton, not put up for retail sale. 
  8467.99.00 - Other - Parts: Tools, pneumatic, hydraulic or with self-contained electric or nonelectric motor,*

到目前为止,似乎一切都在按预期运行。理想的情况是,通过创建一个具有自动化测试的对象或函数,将一些样本行中人工生成的“基本事实”结果与我们的脚本生成的结果进行比较,来进一步完善这个测试。或者至少在更随机的位置浏览,并将它们与原始文件进行比较。

现在让我们组装向量。到目前为止,我们还没有处理文本中的单词,我们保留了与原始文本相同的内容,以供用户查看。既然“用户”将是计算机(在合计和排名中),我们必须记住,“章”、“章”、“章”、“章”和“章”对于计算机是不同的词。所以首先,在我们开始查找和比较单词之前,我们需要创建函数来“清理”特殊字符、标点符号等。并以最简单的方式对文本进行编码,以提高性能并避免意外。

*import re 
  from unicodedata import normalizedef remove_action (txt): 
  return normalize ('NFKD', txt) .encode ('ASCII', 'ignore'). decode ('ASCII')def only_read_and_numbers (raw): 
  raw = remove_acentos (raw) 
  clean = re.sub ("[^ a-zA-Z0-9]", "", raw) 
  return clean*

下一步,我们组装我们的词汇表,也就是说,搜索单词并只添加一次到我们的列表中。在这一步中,我们不仅仅是使用上述函数标准化单词,而是将所有字符都大写,去掉停用词* 和所有最多包含两个字符的单词。我们将利用 NLTK 库中的停用词

*停用词
(停用词)是简单的日常词汇,在搜索引擎索引过程中没有相关性。在元标签中使用这些词可能会产生负面影响,降低关键字的密度。
HTP://www . seopedia . com . br/dicionario-SEO/let ra-s/

要开始使用 NLTK,除了安装库之外,还需要通过在 Python 提示符下键入来下载数据库。然后,在界面中,选择“Forest”和“Stopwords”包。如果没有安装 NLTK 库,通常只需在命令提示符下键入 pip install nltk。

***>>> import** **nltk** 
  **>>>** nltk.download ()*

现在让我们使用 Python 字典来构建我们的词汇表:

*import nltk 
  stopwords = nltk.corpus.stopwords.words ('portuguese')def montaDictVocabulario (plistaTEC): 
  vocab = {} # Traverses all NCM COM subitems with full description.  Create vocabulary through this full description 
  index = 0 
  for line in (plistaTEC): 
  code = line [: 10] 
  description = line [11:] 
  list of words = description.split () 
  for word in lists of words: 
  if ((len (word)> 2) and (stopwords.count (word) == 0)): 
  word = only_letras_e_numeros (word) # Take anything other than AB and 0-9 
  word = word.upper () 
  if word not in vocab: 
  vocab [word] = index 
  index + = 1 
  return vocab*

接下来,字数统计向量的组装。让我们使用 numPy 库,它在阵列的组装和操作方面提供了高性能、灵活性和易用性:

*import numpy as np 
  # Scroll through all NCM COM subitems with full description.  Create a vector dict for each TEC item.  Create a vocabulary vector first 
  def montaVetores (plistaTEC, pvocab): 
  vectorVocab = np.zeros (len (pvocab), dtype = np.int16) 
  vectorsTEC = {} 
  for line in (plistaTEC): 
  code = line [: 10] 
  description = line [11:] 
  list of words = description.split () 
  tecvector = np.zeros (len (pvocab), dtype = np.int16) 
  for word in lists of words: 
  word = only_letras_e_numeros (word) # Take anything other than AB and 0-9 
  word = word.upper () 
  if word in pvocab: 
  index = pvocab [word] 
  tecvector [index] + = 1 
  vectorVocab [index] + = 1 
  vectorsTEC [code] = tecvector 
  return vectorsTEC, vectorVocab*

准备好了。我们的向量已经组装好了(这比看起来容易),我们有了一个词汇表,现在我们可以练习一下“了解你的数据”。所以我们来摘录一些统计数据。在函数视图()中添加一些行怎么样?

*print ("Mounting vectors ...") 
  vectorsTEC, vectorVocab = montaVetores (listTECResumo, vocab) 
  print ("Vocabulary Vector:") 
  print (vectorVocab.shape) 
  print ("Document Vector:") 
  print (len (TECs)) 
  >>> 
  Assembling vocabulary ... 
  Total TEC Vocabulary words: 
  12787 
  Riding vectors ... 
  Vocabulary vector: 
  (12787) 
  Vector of documents: 
  10147*

所以我们在词汇表中总共有 12,787 个单词(唯一的),分为 10,147 行,可以用于税收分类。这是因为我们消除了停用词、标点符号、双字、方框等。对一个人来说,这当然是很多信息了。

让我们来看一些更有趣的统计数据:

*allwordsTEC = str (listTEC) 
  list of allTEC.split () 
  print ("TEC word totals") 
  print (len (allTextText))   allwordsTECResum = str (listTECResumo) 
  list of all wordsTECResumo = allwordsTECResumo.split () 
  print ("Total words from TEC's NCM lines with complete description (Collection of documents):") 
  print (len (allTextRecords))   print ("Mean of words per line (Collection of documents):") 
  print (len (listofTextRecords) / len (listTECResumo))print ("Number of documents in the collection:") 
  print (len (TECs))print ("Statistics of occurrences of words in vocabulary:") 
  format (vectorVocab.mean (), vectorVocab.min (), vectorVocab.max ()) 
  >>> 
  Total TEC words: 
  170019 
  Total words from TEC's NCM lines with complete description (Collection of documents): 
  353167 
  Average words per line (Collection of documents): 
  34.80506553661181 
  Number of documents in the collection: 
  10147 
  Statistics of occurrences of words in vocabulary: 
  Average 18.51848900223143, min 1, max 8124*

好了,现在是时候创建您的浏览器,在单词搜索中排列这些行了:

*def pointerVector (ptexto, pvocab, pvetoresTEC, vectorVocab, weighted = False): 
  ### For efficiency, select only the columns with words that occur in the search 
  ## Therefore, first convert the TEC vectors list into a Dimension Matrix 
  ## number ofTECs x size of the Vocabulary 
After ## create an array of summing values query vocabulary columns 
matrizVetores = np.asarray (list (pvetoresTEC.values ()), DTYPE = np.int16) 
matrizCodigos = np.asarray (list (pvetoresTEC.keys ()) ) 
matrizSoma np.zeros = (len (pvetoresTEC)) 
wordlist = ptexto.split () 
explanation = "" 
for word in wordlist: 
word = somente_letras_e_numeros (word) # Strip everything is not AB and 0-9 
word = palavra.upper () 
if the word in pvocab: 
index = pvocab [word] 
vector matrizVetores = [index :,] 
explanation = explanation word + + '' + str (vetorVocab [index]) + ' 
matrizSoma = np.add (matrizSoma, vector)
indicesnaozero = np.nonzero (matrizSoma) 
matrizTemp np.vstack = ((matrizCodigos [indicesnaozero] matrizSoma [indicesnaozero])) 
. indices matrizTemp = [1:] argsort () 
indices indices = [:: - 1] 
matrizCodigoePontuacao = matrizTemp [:, indices] 
return matrizCodigoePontuacao, explanation*

最后,创建一个例程来测试搜索引擎:

*test = "T" 
while (test = ""): 
test = input ( "Enter a product-description words Enter simply Enter to end:.") 
matrizPontos explains = pontuaVetores (test, vocab, vetoresTEC, vetorVocab) 
print (explains) 
ind = 5 
if (ind> matrizPontos.shape [1]): 
ind = matrizPontos.shape [1] 
print ( "plus 5") 
is in code (matrizPontos [0: ind]): it 
is in line (listaTECResumo): 
codigo2 = line [10] 
if (code == codigo2): 
print (line)>>>>> 
Enter a product-describing words. Type simply enter to terminate: other tissues 
OTHER TISSUES 8124 569 
5 plus:
8517.62.79 Other Other emitting devices with embedded Digital Receiver - Machines for the reception, conversion, emission and transmission or regeneration of voice, images or other data, including switching and routing (forwarding *) - Other apparatus for transmission, transmission or reception of voice, images or other data, including apparatus for communication in networks wired or wireless network (such as a local area network (LAN) or wide area network (extended *) (WAN)): telephone sets including telephones for cellular networks or for other wireless networks; other devices for emission, transmission or reception of voice, images or other data, including apparatus for communication networks by wired or wireless network (such as a local area network (LAN) or wide area network (extended *) (WAN ))except devices
8517.62.93 Other personal receivers radio message Other - Machines for the reception, conversion, emission and transmission or regeneration of voice, images or other data, including switching and routing (forwarding *) - Other apparatus for transmission, transmission or reception voice, images or other data, including apparatus for communication in networks wired or wireless network (such as a local area network (LAN) or wide area network (extended *) (WAN)): telephone sets, including telephones for cellular networks or for other wireless networks; other devices for emission, transmission or reception of voice, images or other data, including apparatus for communication networks by wired or wireless network (such as a local area network (LAN) or wide area network (extended *) (WAN )), excluding devices
8517.62.59 Other apparatus for transmission or reception of voice, images or other data in wired network - Machines for the reception, conversion, emission and transmission or regeneration of voice, images or other data, including switching and routing (forwarding *) - other apparatus for transmission, transmission or reception of voice, images or other data, including apparatus for communication in networks wired or wireless network (such as a local area network (LAN) or wide area network (extended * ) (WAN)): telephone sets, including telephones for cellular networks or for other wireless networks; other devices for emission, transmission or reception of voice, images or other data,including apparatus for communication networks in a wired or wireless network (such as a local area network (LAN) or wide area network (extended *) (WAN)), excluding devices
8517.62.99 Other Other - Machines for the reception, conversion, emission and transmission or regeneration of voice, images or other data, including switching and routing (forwarding *) - Other apparatus for transmission, transmission or reception of voice, images or other data, including apparatus for communication networks by wired or wireless network (such as a local area network (LAN) or wide area network (extended *) (WAN)): telephone sets, including telephones for cellular networks and for other wireless networks; other devices for emission, transmission or reception of voice, images or other data, including apparatus for communication networks by wired or wireless network (such as a local area network (LAN) or wide area network (extended *) (WAN )), excluding devices
Other 8517.62.39 Other apparatus for switching - Machines for the reception, conversion, emission and transmission or regeneration of voice, images or other data, including switching and routing (forwarding *) - Other apparatus for transmission, transmission or reception of voice, images or other data, including apparatus for communication networks by wired or wireless network (such as a local area network (LAN) or wide area network (extended *) (WAN)): telephone sets, including telephones for cellular networks or for other wireless networks; other devices for emission, transmission or reception of voice, images or other data, including apparatus for communication networks by wired or wireless network (such as a local area network (LAN) or wide area network (extended *) (WAN )), excluding devices
Enter a product-describing words. Type simply enter to terminate: patterned knitted fabrics 
WOVEN FABRIC 569 54 31 STAMPING 
5 plus: 
5407.10.19 Other rubber thread No - fabrics woven from high tenacity yarn of nylon or other polyamides or polyester yarn fabrics of synthetic filaments, including tissues obtained from the products of heading 5404\. 
6001.21.00 - Cotton - rings fabrics: Pile fabrics (including woven fabrics called "long pile" or "the long") and tissue rings mesh. 
5407.20.00 - Woven fabrics obtained from strip or the like Woven fabrics of synthetic filament yarn, including woven fabrics obtained from the products of heading 5404.
5407.30.00 - "Fabrics" mentioned in Note 9 Section XI Woven fabrics of synthetic filament yarn, including woven fabrics obtained from the products of heading 5404\. 
5407.74.00 - Printed - Other fabrics containing at least 85% by weight of synthetic filament fabrics of synthetic filament yarn, including woven fabrics obtained from the products of heading 5404\. 
Enter a product-describing words. Type simply enter to terminate: knitted polyester synthetic fiber fabrics printed 
WOVEN FABRIC 569 839 SYNTHETIC FIBERS 54 281 74 polyester STAMPING 31 
5 plus:
9001.10.20 beams and optical fiber cables - Optical fibers, bundles of cables and optical fibers Optical fibers and optical fiber bundles; optical fiber cables other than those of heading 85.44; polarizing material in sheets and plates; lenses (including contact lenses), prisms, mirrors and other optical elements, of any material, unmounted, other than glass not optically worked. 
Other optical fibers 9001.10.19 - optical fibers, bundles of cables and optical fibers Optical fibers and optical fiber bundles; optical fiber cables other than those of heading 85.44; polarizing material in sheets and plates; lenses (including contact lenses), prisms, mirrors and other optical elements, of any material, unmounted, other than glass not optically worked.
9001.10.11 core diameter less than 11 micrometers (microns) Fiber Optics - Optical fibers, bundles of cables and optical fibers Optical fibers and optical fiber bundles; optical fiber cables other than those of heading 85.44; polarizing material in sheets and plates; lenses (including contact lenses), prisms, mirrors and other optical elements, of any material, unmounted, other than glass not optically worked. 
5511.10.00 - synthetic staple fibers, containing at least 85% by weight of such fibers yarns of synthetic or artificial staple fibers (excluding sewing thread), packaged for retail sale.
6001.22.00 - Of man-made fibers - rings fabrics: Pile fabrics (including woven fabrics called "long pile" or "the long") and tissue rings mesh. 
Enter a product-describing words. Enter simply Enter to end:*

嗯,上面你可以看到我们已经有一个搜索引擎。第一次搜索与我们想要的相差甚远。第二个变好了,第三个好了一点,以此类推。当我们使用搜索引擎时,我们总是不得不“精炼”搜索,并且,迭代地,我们更接*我们想要的。理解精致的关键在于其他 8124 面料 569 系列。这意味着“其他”一词在我们的系列和面料 569 中出现了 8124 次。在上一次调查中,我们进行了以下计数:织物 569 MALHA 54 纤维 839 合成纤维 281 聚酯 74 冲压 31

我们可以看到,有“非常常见”的词,“常见”的词,“不常见”的词和“罕见”的词。例如,扑热息痛只出现了 3 次。因此,单词“STAMPED”在一行中的出现应该比单词“FIBERS”在排名中计算更多的分数。因此,如果我们寻找衣服或织物,我们不会在第一个结果之间显示光纤。

现在,为了更好地解决问题,让我们调整与用户的交互方式,只搜索字数并进行一些查询:

*teste = "T" 
 while (teste!=""): 
 teste = input("Digite umas palavras-descrição de produto para ver suas ocorrências. Digite simplemente Enter para encerrar:") 
 matrizPontos, explica = pontuaVetores(teste, vocab, vetoresTEC, vetorVocab) 
 print(explica) 
 >>>>> 
 Digite umas palavras-descrição de produto para ver suas ocorrências. Digite simplemente Enter para encerrar:outros outras outro estampado estampados tintos tinto poliester poliesteres 
 OUTROS 8124 OUTRAS 3266 OUTRO 468 ESTAMPADOS 31 TINTOS 35 POLIESTER 33 POLIESTERES 74From the above results, we see that "OTHERS" is a super-frequent word, followed by "OTHERS". Already "STAMPED" occurs only 31 times, and "STAMPED" none. Already "POLYESTER" 33 AND "POLYESTERS" 74 times. To treat different versions of the same word as one, we will discuss the techniques below.
The solution to better score rankings is in a concept called TF-IDF. In a very short explanation, TF-IDF proposes to punctuate repetition in a document, and penalize repetition in the collection (most common word is worth less, rare is worth more).
Thus, we need to modify our score vector, which today contains only the word count, in a vector with the TF-IDF values. For this, in Python, we have the IDFTransformer package from the sklearn library:*

从上面的结果我们看到“别人”是一个超高频词,其次是“别人”。已经“盖章”只出现了 31 次,而“盖章”一次也没有。已经是“聚酯”33 和“聚酯”74 倍了。为了将同一个单词的不同版本视为一个,我们将在下面讨论这些技术。

更好的分数排名的解决方案在一个叫做 TF-IDF 的概念中。在一个非常简短的解释中,TF-IDF 建议对文档中的重复进行标点,并惩罚集合中的重复(最常见的词价值更低,罕见的词价值更高)。

因此,我们需要用 TF-IDF 值修改我们的得分向量,它现在只包含单词计数。为此,在 Python 中,我们有来自 sklearn 库的 IDFTransformer 包:

* [## sk learn . feature _ extraction . text . tfidftransformer-sci kit-learn 0 . 18 . 1 文档

使用 tf-idf 代替给定文档中某个标记的原始出现频率的目的是缩小…

scikit-learn.org](https://translate.googleusercontent.com/translate_c?depth=2&hl=en&rurl=translate.google.com&sl=auto&sp=nmt4&tl=en&u=http://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.TfidfTransformer.html&usg=ALkJrhhAF1WN325_6Mv1Ye5Kq-UGYXj0uQ)

让我们看看 TfidfTransfomer 对向量的影响:

from sklearn.feature_extraction.text import TfidfTransformer 
 transformer = TfidfTransformer() 
 matrizVetores = np.asarray(list(vetoresTEC.values()), dtype=np.int16) 
 tfidf = transformer.fit_transform(matrizVetores) 
 matriz_tfidf = tfidf.toarray()print (matrizVetores [1:10]) 
print (matriz_tfidf [1:10]) 
>>>> 
[[0 0 0 ... 0 0 0] 
[0 0 0 ... 0 0 0] 
[0 0 0 ... 0 0 0] 
..., 
[0 0 0 ... 0 0 0] 
[0 0 0 ... 0 0 0] 
[1 1 1 ... 0 0 0]] 
[[... 0\. 0\. 0\. 0\. 0\. 0.] 
[... 0\. 0\. 0\. 0\. 0\. 0] 
[0 ... 0 0., 0\. 0\. 0] 
..., 
[... 0\. 0\. 0\. 0\. 0\. 0.] 
[... 0\. 0\. 0\. 0\. 0\. 0.] 
[0.3453688 0.3453688 0.33742073\. .. 0\. 0\. 0.]]

为了比较结果,我们将创建一个稍加修改的评分函数(变化以粗体显示):

def pontuaVetores_tfidf (ptexto, pvocab, pvetoresTEC, vetorVocab = False weighted): 
### For efficiency, select only the columns with words that occur in the search 
## Therefore, first convert the TEC vectors list in a dimension Matrix 
## númerodeTECs tamanhodoVocabulario x 
## then create an array by adding the values of the query vocabulary columns 
matrizVetores = np.asarray (list (pvetoresTEC.values ()), DTYPE = np.int16) 
 **from sklearn.feature_extraction.text import TfidfTransformer 
transformer TfidfTransformer = () 
tfidf = transformer.fit_transform (matrizVetores) 
matriz_tfidf = tfidf.toarray ()** 
 matrizCodigos = np.asarray (list (pvetoresTEC.keys ()))
matrizSoma np.zeros = (len (pvetoresTEC)) 
wordlist = ptexto.split () 
explanation = "" 
for word in wordlist: 
word = somente_letras_e_numeros (word) # Strip everything is not AB and 0-9 
word palavra.upper = ( ) 
if the word in pvocab: 
index = pvocab [word] 
vector = **matriz_tfidf** [:, index] 
explanation = explanation word + + '' + str (vetorVocab [index]) + ' 
matrizSoma = np.add (matrizSoma, vector) 
indicesnaozero = np.nonzero (matrizSoma) 
matrizTemp np.vstack = ((matrizCodigos [indicesnaozero] matrizSoma [indicesnaozero])) 
. indices matrizTemp = [1:] argsort () 
indices indices = [:: - 1]
matrizCodigoePontuacao = matrizTemp [:, indices] 
return matrizCodigoePontuacao, explanation

最后,我们通过重复上一次测试来查看结果,并列出超出 TEC 线的分数。看看下面的列表,你会发现结果有了很大的改善。“光纤”从第一个位置列表中消失了,它只是与我们所寻求的不太一致。此外,我们注意到“光纤”和下面的项目得分相同,所以排名实际上是随机的。

teste="tecidos de malha fibras sinteticas poliesteres estampados" 
 matrizPontos, explica = pontuaVetores(teste, vocab, vetoresTEC, vetorVocab) 
 print(explica) 
 ind = 5 
 if (ind > matrizPontos.shape[1]): 
 ind = matrizPontos.shape[1] 
 print("5 mais:") 
 for codigo in (matrizPontos[0, :ind]): 
 for linha in (listaTECResumo): 
 codigo2 = linha[:10] 
 if(codigo2==codigo): 
 print(matrizPontos[1, :ind]) 
 print(linha) 
 >>> 
 TECIDOS 569 MALHA 54 FIBRAS 839 SINTETICAS 281 POLIESTERES 74 ESTAMPADOS 31 
 5 mais: 
 **['6.0' '6.0' '6.0' '5.0' '5.0']** 
 9001.10.20 Feixes e cabos de fibras ópticas - Fibras ópticas, feixes e cabos de fibras ópticas Fibras ópticas e feixes de fibras ópticas; cabos de fibras ópticas, exceto os da posição 85.44; matérias polarizantes em folhas ou em placas; lentes (incluindo as de contato), prismas, espelhos e outros elementos de óptica, de qualquer matéria, não montados, exceto os de vidro não trabalhado opticamente. 
 **['6.0' '6.0' '6.0' '5.0' '5.0']** 
 9001.10.19 Outras Fibras ópticas - Fibras ópticas, feixes e cabos de fibras ópticas Fibras ópticas e feixes de fibras ópticas; cabos de fibras ópticas, exceto os da posição 85.44; matérias polarizantes em folhas ou em placas; lentes (incluindo as de contato), prismas, espelhos e outros elementos de óptica, de qualquer matéria, não montados, exceto os de vidro não trabalhado opticamente. 
 **['6.0' '6.0' '6.0' '5.0' '5.0']** 
 9001.10.11 De diâmetro de núcleo inferior a 11 micrômetros (mícrons) Fibras ópticas - Fibras ópticas, feixes e cabos de fibras ópticas Fibras ópticas e feixes de fibras ópticas; cabos de fibras ópticas, exceto os da posição 85.44; matérias polarizantes em folhas ou em placas; lentes (incluindo as de contato), prismas, espelhos e outros elementos de óptica, de qualquer matéria, não montados, exceto os de vidro não trabalhado opticamente. 
 **['6.0' '6.0' '6.0' '5.0' '5.0']** 
 5511.10.00 - De fibras sintéticas descontínuas, que contenham pelo menos 85 %, em peso, destas fibras Fios de fibras sintéticas ou artificiais, descontínuas (exceto linhas para costurar), acondicionados para venda a retalho. 
 **['6.0' '6.0' '6.0' '5.0' '5.0']** 
 6001.22.00 -- De fibras sintéticas ou artificiais - Tecidos de anéis: Veludos e pelúcias (incluindo os tecidos denominados de “felpa longa” ou “pelo comprido”) e tecidos de anéis, de malha.test = "synthetic fiber fabrics knitted polyester patterned" 
matrizPontos explains = pontuaVetores **_tfidf** (test vocab, vetoresTEC, vetorVocab) 
print (explains) 
ind = 5 
if (ind> matrizPontos.shape [1]): 
ind = matrizPontos.shape [1] 
print ( "plus 5") 
is in code (matrizPontos [0: ind]): 
for line in (listaTECResumo): 
codigo2 = line [10] 
if (code == codigo2): 
print (matrizPontos [ 1: ind]) 
print (line) 
>>>> 
WOVEN FABRIC 569 839 sYNTHETIC FIBERS 54 281 74 polyester STAMPING 31 
5 plus: 
 **[ '1.5540693500933536' 1.2670506868422255 '1.2275553770539624'
"1.2042355691237416 '1.1558503446987298']** 
 6006.34.20 Of polyesters - Printed - Of synthetic fibers: Other knitted fabrics. 
 **[ '1.5540693500933536' 1.2670506868422255 '1.2275553770539624' 
'1.2042355691237416' 1.1558503446987298 ']** 
 6006.44.00 - Printed - of artificial fibers: Other knitted fabrics. 
 **[ '1.5540693500933536' 1.2670506868422255 '1.2275553770539624' 
'1.2042355691237416' 1.1558503446987298 ']** 
 5516.94.00 - Printed - Other: Woven fabrics of staple fibers. 
 **[ '1.5540693500933536' '1.2670506868422255' '1.2275553770539624' 
'1.2042355691237416' '1.1558503446987298'** 
] 6006.34.90 Other - Printed - Of synthetic fibers: Other knitted fabrics.
 **[ '1.5540693500933536' 1.2670506868422255 '1.2275553770539624' 
'1.2042355691237416' 1.1558503446987298 ']** 
 6003.30.00 - of synthetic fiber mesh fabrics width not exceeding 30 cm, excluding the positions 6001 and 6002.

这个算法的一个版本在我们的测试中表现出了更好的性能,Okapi BM25 +(更重要的[+]是由于我们收集的文档中单词数量之间的高度差异)。它是一个插值参数,用于减少短文档的惩罚。此外,让“b”参数默认 BM25 为 60%,而不是标准的 75%。“b”是一个线性插值参数,也有助于减轻短文档的损失。使用各种参数和超和最小化/消除实现的公式绘制排名。

要了解更多关于 TF-IDF 和 BM25 的信息,维基百科中有很棒的文章:

[## Tf-idf —维基百科,免费的百科全书

tf-idf 值(英文术语 frequency-inverse document frequency 的缩写,表示术语的频率…

pt.wikipedia.org](https://translate.googleusercontent.com/translate_c?depth=2&hl=en&rurl=translate.google.com&sl=auto&sp=nmt4&tl=en&u=https://pt.wikipedia.org/wiki/Tf%25E2%2580%2593idf&usg=ALkJrhilUYhP0Th-U_nKHMpwAygLVtVFmA) [## Okapi BM25 —维基百科

在信息检索中,Okapi BM25 (BM 代表最佳匹配)是搜索引擎用来对搜索结果进行排序的排序函数

en.wikipedia.org](https://translate.googleusercontent.com/translate_c?depth=2&hl=en&rurl=translate.google.com&sl=auto&sp=nmt4&tl=en&u=https://en.wikipedia.org/wiki/Okapi_BM25&usg=ALkJrhiBE-wbonyiPhC5mG9u8LNfazTniQ)

另一个有趣的解决方案是将相似的单词分组,处理复数,同一个单词的各种变体,等等:(other,Other,Another,stamped,embossed,printed,red,涤纶,涤纶…)。我们将尝试先从你的偏旁部首开始,而不是从词汇表中的整个单词开始。转换单词和减少变化的技术称为词汇化和词干化。我们可以把搜索词典想象成使用同义词词典,进一步缩小我们的词汇量。词干分析应用于系统的 Java 版本,dicionarizada 搜索将在不久的将来实现。

GitHub 上有一个 IPython 笔记本,用于使用 Python 测试词干和词尾。在伦敦可以买到葡萄牙斯特梅尔。

[## 茎干工

词干分析器从单词中去掉词缀,只留下单词词干。

www.nltk.org](https://translate.googleusercontent.com/translate_c?depth=2&hl=en&rurl=translate.google.com&sl=auto&sp=nmt4&tl=en&u=http://www.nltk.org/howto/stem.html&usg=ALkJrhjepmqIkzhOYdSVPAU3PLOBiEAUjQ)

from nltk.stem import * 
 stemmer = SnowballStemmer("portuguese") 
 palavras = ['TECIDOS', 'TECIDO', 'FIBRAS', 'FIBRA', 'SINTETICO', 'SINTETICA', 'OUTROS', 'OUTRAS', 'OUTRA'] 
 stems = [stemmer.stem(palavra) for palavra in palavras] 
 print(' '.join(stems)) 
 lista = list (set(stems)) 
 print(lista) 
 >>>> 
 tec tec fibr fibr sintet sintet outr outr outr 
 ['fibr', 'tec', 'sintet', 'outr']

完成剧本并展示给观众看

[## IvanBrasilico/classicadorfiscal

分类或分类——这是一个 JAVA 系统,它利用了商业和加工方面的技术

github.com](https://translate.googleusercontent.com/translate_c?depth=2&hl=en&rurl=translate.google.com&sl=auto&sp=nmt4&tl=en&u=https://github.com/IvanBrasilico/ClassificadorFiscal/blob/master/RanqueadorTEC.ipynb&usg=ALkJrhjn7E7rINwFizeFFoGK2c4HNpa0Bw)

为了继续开发这项工作并实现这些解决方案,Python 无疑是目前可用的最佳解决方案之一。然而,由于在我的工作中,Python 不是一种被广泛采用的开发语言,并且我目前参与了一个大型 Java 项目,甚至这个财政分类器也是该项目的一部分,因此从这一刻起,我将 Python 中的初始代码转换为 Java + Swing。有必要做一些调整,因为最初的版本使用了超过 1GB 的内存,我必须考虑一些优化,将内存的使用降低到 300MB 以下。代码变大了,性能稍微降低了,但是 Java *台也有一些功能,特别是在界面设计方面,最终变得有用。

完整的代码(Java 和 Python 都有)在我的 GitHubhttps://github.com/IvanBrasilico/中

Java 版本已经实现了 BM25 +,参数调整、词干、二元模型以及其他改进。我打算在本文的第 4 部分尽快描述它们,并以 Python 版本实现它们。

第三部分

A nd sta 部分是使用 Java 实现系统的简要手册,可在 GitHub 上获得。

[## 伊万布拉西利科

IvanBrasilico 有一个可用的存储库。在 GitHub 上关注他们的代码。

github.com](https://translate.googleusercontent.com/translate_c?depth=2&hl=en&rurl=translate.google.com&sl=auto&sp=nmt4&tl=en&u=https://github.com/IvanBrasilico/&usg=ALkJrhhEt-hgkfDQjzz3RnBXL6QeoO-2Ew)

该系统使用搜索技术和处理文本来获得概率分数。

该系统完全嵌入运行,完全可以在任何安装了 Java 的计算机上使用,而无需访问网络。

它被并入 MDIC 出版的最后一个 TEC 的全文系统文件中。当加载时,系统执行一些预处理,即使用人工智能技术和语言处理(矢量化单词、TF-IDF、词干、二元模型等)来处理 TEC 的所有文本,并将其以各种结构化形式安装。

该系统提供了七个选项卡用于研究。下面分别介绍。

NCM 完整选项卡
显示未经预处理的原始 TEC 文本。
按钮“搜索文本” —按单词或部分单词搜索或滚动文本。重要的是要记住这个标签搜索是准确的,区分大小写和图形符号(例如:acentos)即“章”、“章”、“章”、“章”是不同的搜索。在 TEC 中拼写为“章”。

(这是加载后唯一可以立即使用的选项卡。另一个选项卡必须等待预处理结束,这可能需要 1 到 2 分钟,具体取决于所用的计算机)

NCM 搜索标签
显示 TEC 本身,分层显示,只有子标题的文本和代码,以及最终分类和进口关税配额。
按钮【搜索代码】-按代码或部分代码搜索。

章节选项卡
显示 TEC 的章节列表。在列表中选择一个章节,显示您的注释

建议选项卡
这个选项卡是真正使用算法“智能”的地方。TEC 将 sub 显示为“完整的”文本,即添加到所有高级位置的 sub 文本。此外,该子项的单词根据在文本中出现的次数对匹配搜索文本的单词进行评分。结果按分数排序,从最高到最低。

位置反馈
该选项卡与 anterir 相同,但显示子项的位置

按钮“搜索点” —搜索单词、点,并在“建议”选项卡中显示结果。
参数:
使用加权权重 TF / IDF (S / N)
而不是简单地对 TEC 行中的搜索词的出现次数进行计数,考虑“权重”对 TEC 中出现频率较低的词进行更多评分,并且还考虑每行中一个词的相对权重。
纯文本(S / N)
只查找输入的单词。对方框和图形符号不敏感。
词干(信噪比)
搜索字根。压印线匝 Estamp,红色线匝 TINT。
Bigrams (S / N)
只是寻找输入的单词。对方框和图形符号不敏感。按照输入的顺序,成对查找单词。“其他织物”、“薄纸”、“网布”等。

解释选项卡
显示搜索词和一些统计数据。它让你知道键入的单词是否在 TEC 中找到,以及找到的频率。适合细化和研究修正。例如,如果搜索“Tylenol”,该选项卡将不会显示统计数据,因为该词在 TEC 中不存在。如果您搜索“扑热息痛”信息,则会出现“扑热息痛”。总事件数:3”。同样,搜索“浮雕”返回“盖章”。总点击量:45”。没有复数形式的" Printed "不返回任何内容。

示例屏幕

在这里,我们开始了一个简单的搜索,只输入“其他组织”并点击“搜索分数”
请注意,将鼠标指针停留在列表项上,会打开一个小窗口,其中包含该行和在搜索行中找到的每个单词以及每个单词的分数。

第二步,我们开始细化我们的搜索。请注意,单词“fabric”和“red”得分较高。

在搜索中添加“棉花”一词

在这里,我们选择“解释”选项卡来了解每个分数的原因。每个单词的分数总是与它的总出现次数成反比。

查看“位置”选项卡的结果

修改对其他类型组织的搜索:

可以用感叹号(!)这个词搜索之前。因此,这个单词的分数将变成负数,包含这个单词的行将排到列表的末尾。

下面是“NCM 完成”标签,如果有疑问,您可以在这里检索 TEC 的完整文本

“搜索 NCM”选项卡分层显示 NCM。

“章节和注释”选项卡允许您更方便快捷地查询每个章节、描述和注释

在“统计章节 NCM”选项卡中,可以看到各章节中巴西进口的原产国百分比。

以下屏幕显示了其他研究、结果、统计数据和分数,以展示使用的可能性

取自报告的复杂描述在第三个列表中显示所需的结果。注意,这个结果主要不是因为这一行,在 TEC 的“环氧树脂”中使用了“环氧树脂”和“环氧树脂”这两个词。炮泥找到了激进分子,但没有找到“树脂”和“环氧树脂”这两个词。并不总是单独解决词干问题,因此查看每行分数的系统返回并优化搜索很重要。

细化的一个例子:把“垫圈”换成“垫圈”,或者找两个术语。去掉“金属”一词,只需要塑料。

在下面的例子中,词干分析也解决了搜索问题。尝试各种组合,直到在第一行找到想要的子项,这比向下滚动几行更有趣。

第四部分

这部分讨论已经实施的技术的替代和/或补充。

Java 版本在汇编词汇表时已经实现了词干分析、二元模型和单元模型,并且在排序时提供了组合这些方法的可能性。此外,还实现了与 NCM 国家历史统计数据相结合的可能性。还应用了词库和词干来减少词汇量。

其他可能性是使用聚类,通过 k-means 或其他方法或通过层次结构,对整个章节和位置评分,例如,索引反转数据库以允许搜索单词的部分;通过 PCA 等降维,然后用回归树、SVM 或者甚至普通或递归神经网络进行排序。

就使用排名中的其他数据而言,除了原产国,NCM 还可以通过大约日期的趋势生成制造商、经济区域、运输的统计数据,而不是几年的统计数据。

所有的技术都可以与“集合”或简单地将结果相乘的方法相结合。在乘法的情况下,一个好的做法是在标准化结果之前。示例:

克服集合“listaTECResumo”中的一些文档太短这一事实的一种方法是以已经为子项目创建的相同方式为位置创建文档,并以相同方式排序。然后把位置的分数乘以每个分项的位置。为了在不考虑字数的情况下*等对待,首先将结果标题列表标准化,并细分所有得分行以获得最高得分的文档得分(因此,列表的第一个位置将是 100%,第二个位置稍低,以此类推)。)

除了新的评分可能性、产品组合和 ensenblimg 之外,您还可以创建测试示例“地面实况”,然后使用机器学习来改进参数和/或通过使用精度和召回 F-score 的评估技术、应用加权排名评估(评估方法克兰菲尔德/加权*均精度和召回)来发现已经实施的方法中的缺陷。

一旦进行了测试和改进,GitHub 上将会提供其中的一些替代方案,并在本文中进行讨论。

参考

[## 文本数据管理与分析:信息检索与文本应用导论

编辑描述

dl.acm.org](http://dl.acm.org/citation.cfm?id=2915031) [## 信息检索导论—剑桥大学出版社

类测试和连贯,这本教科书教经典和网络信息检索,包括网络搜索和搜索引擎。

www.cambridge.org](http://www.cambridge.org/catalogue/catalogue.asp?isbn=0521865719) [## 学习信息检索排名|刘铁燕|斯普林格

由于网络的快速增长和查找所需信息的困难,高效和有效的…

www.springer.com](http://www.springer.com/la/book/9783642142666) [## 文本挖掘和分析| Coursera

关于本课程:本课程将涵盖挖掘和分析文本数据的主要技术,以发现…

www.coursera.org](https://www.coursera.org/learn/text-mining) [## 文本检索和搜索引擎—伊利诺伊大学香槟分校| Coursera

关于本课程:*年来,自然语言文本数据急剧增长,包括网页、新闻…

www.coursera.org](https://www.coursera.org/learn/text-retrieval/) [## 机器学习课程简介| Udacity

免费课程模式识别的乐趣和利润开始免费课程机器学习是一个一流的门票…

www.udacity.com](https://www.udacity.com/course/intro-to-machine-learning--ud120)*

使用 Python 通过 AWS 的反向图像搜索引擎 Rekognition 收集图像标签

原文:https://towardsdatascience.com/use-python-to-collect-image-tags-using-aws-reverse-image-search-engine-rekognition-eccf1f259a8d?source=collection_archive---------7-----------------------

这篇博文讨论了如何将你的图片转化为描述图片内容的文本,这样你就可以在 Jupyter 笔记本上对图片的内容和主题进行分析。一个有用的例子是,如果你收到了数千条推文,你想知道图片媒体对参与度有没有影响。幸运的是,亚马逊、谷歌和微软的工程师没有编写自己的图像识别工具,而是完成了这项任务,并使他们的 API 可以访问。这里我们将使用 Rekognition,这是亚马逊基于深度学习的图像和视频分析工具。

本博客作为如何使用不同的 Rekognition 操作提取信息的示例,并不能代替阅读文档。我尽我所能提供链接,因为它们可能是有用的。

因此,为了收集图像的文本数据,我们将:

  1. 将图像存储在 AWS S3 桶中
  2. 使用 AWS Rekognition 反转图像搜索并返回每个图像的标签
  3. 将数据保存在长数据框和宽数据框中——您可能只需要一个数据框,但是我在代码中给出了将数据保存为两个数据框的方法。

亚马逊在这里描述了 Rekognition 是如何工作的。

https://aws.amazon.com/rekognition/

打开 Jupyter 笔记本并将数据存储为 pandas 数据框对象后,我们希望导入相关的库。我使用了来自 Twitter 的数据,那里的图像数据是 URL 形式的。

import boto
import boto3
conn = boto.connect_s3()
import requests

如果你在这里遇到了错误,安装 AWS CLI ,并确保你已经安装了 boto 和 boto3 。

现在连接到我们的桶:

*# Uses the creds in ~/.aws/credentials*
s3 = boto3.resource('s3')
bucket_name_to_upload_image_to = '#########' *#insert the name of your bucket here.*

你如何创建一个桶?什么是水桶?点击此处。

你连接到你的桶了吗?我从用户 GISD 对以下 StackOverflow 问题的回答中了解到这个检查。

*# Do this as a quick and easy check to make sure your S3 access is OK*
**for** bucket **in** s3.buckets.all():
    **if** bucket.name == bucket_name_to_upload_image_to:
        print('Good to go. Found the bucket to upload the image into.')
        good_to_go = **True**

**if** **not** good_to_go:
    print('Not seeing your s3 bucket, might want to double check permissions in IAM')

第一步:将图像存储在 AWS S3 桶中

我们所有的图像都是以网址的形式,我们想把它们都上传到一个 S3 桶,而不必先把它们存储在我们的硬盘上。方法如下:

请记住,这还会创建一个 mapping_dict,这样,如果您的图像 URL 列表是从另一个数据框中获得的,您就能够将其与在以下步骤中创建的图像标签数据框合并。

第二步:使用 AWS Rekognition 反向搜索图像并返回每个图像的标签

首先,我们将探索 AWS API 的三个特性,巧合的是,它们对我的目的最有帮助:检测标签、检测文本和识别名人。Rekognition 还拥有许多其他功能,包括检测和分析人脸,跟踪人脸,以及检测儿童的不安全内容。

检测标签

response will be a dictionary with keys [‘OrientationCorrection’, ‘Labels’, ‘ResponseMetadata’]

[Output]
{'Labels': [{'Confidence': 99.28775787353516, 'Name': 'Human'},
  {'Confidence': 99.2877426147461, 'Name': 'People'},
  {'Confidence': 99.28775787353516, 'Name': 'Person'},
  {'Confidence': 91.67272186279297, 'Name': 'Audience'},
  {'Confidence': 91.67272186279297, 'Name': 'Crowd'},
  {'Confidence': 91.67272186279297, 'Name': 'Speech'},
  {'Confidence': 78.27274322509766, 'Name': 'Clothing'},
  {'Confidence': 78.27274322509766, 'Name': 'Coat'},
  {'Confidence': 78.27274322509766, 'Name': 'Overcoat'},
  {'Confidence': 78.27274322509766, 'Name': 'Suit'}],
 'OrientationCorrection': 'ROTATE_0',
 'ResponseMetadata': {'HTTPHeaders': {'connection': 'keep-alive',
   'content-length': '536',
   'content-type': 'application/x-amz-json-1.1',
   'date': 'Mon, 04 Dec 2017 03:13:26 GMT',
   'x-amzn-requestid': '18599e6b-d8a1-11e7-8234-c9f1716fbb2e'},
  'HTTPStatusCode': 200,
  'RequestId': '18599e6b-d8a1-11e7-8234-c9f1716fbb2e',
  'RetryAttempts': 0}}

对于下图:

检测文本

text_in_image will be a dictionary with keys [‘TextDetections’, ‘ResponseMetadata’]

注意这里的输出是一个字典的字典。既然这么长,这里就不完整收录了。以下是 text _ in _ image[' text detections ']的简短输出:

[Output]
[{'Confidence': 87.87747955322266,
  'DetectedText': 'Protects',
  'Geometry': {'BoundingBox': {'Height': 0.0289202518761158,
    'Left': 0.8098856210708618,
    'Top': 0.3966602385044098,
    'Width': 0.05391734838485718},
   'Polygon': [{'X': 0.8098856210708618, 'Y': 0.3966602385044098},
    {'X': 0.863802969455719, 'Y': 0.3976689577102661},
    {'X': 0.8636319041252136, 'Y': 0.4265892207622528},
    {'X': 0.8097145557403564, 'Y': 0.4255805015563965}]},
  'Id': 0,
  'Type': 'LINE'},
 {'Confidence': 81.16915130615234,
  'DetectedText': 'Minorcuts',
  'Geometry': {'BoundingBox': {'Height': 0.025231996551156044,
    'Left': 0.8168795108795166,
    'Top': 0.4240514636039734,
    'Width': 0.06063205003738403},
   'Polygon': [{'X': 0.8168795108795166, 'Y': 0.4240514636039734},
    {'X': 0.8775115609169006, 'Y': 0.4253864288330078},
    {'X': 0.8773359060287476, 'Y': 0.4506184160709381},
    {'X': 0.8167038559913635, 'Y': 0.4492834508419037}]},
  'Id': 1,
  'Type': 'LINE'},
.
.
.
}]

对于下图:

See “Protects” and “Minorcuts”?

认识名人

celeb_detect will be a dictionary with keys [‘OrientationCorrection’, ‘CelebrityFaces’, ‘UnrecognizedFaces’, ‘ResponseMetadata’]

类似于 DetectText,recognize small ness 返回字典的字典。以下是 celeb_detect["CelebrityFaces"]的输出:

[Output]
[{'Face': {'BoundingBox': {'Height': 0.10687500238418579,
    'Left': 0.4807872474193573,
    'Top': 0.15562500059604645,
    'Width': 0.16026242077350616},
   'Confidence': 99.9999771118164,
   'Landmarks': [{'Type': 'eyeLeft',
     'X': 0.5403168201446533,
     'Y': 0.19756773114204407},
    {'Type': 'eyeRight', 'X': 0.5921167731285095, 'Y': 0.20492416620254517},
    {'Type': 'nose', 'X': 0.5595902800559998, 'Y': 0.22208547592163086},
    {'Type': 'mouthLeft', 'X': 0.5338063836097717, 'Y': 0.23306140303611755},
    {'Type': 'mouthRight', 'X': 0.5765158534049988, 'Y': 0.23889882862567902}],
   'Pose': {'Pitch': -3.3401520252227783,
    'Roll': 11.797859191894531,
    'Yaw': -0.263323575258255},
   'Quality': {'Brightness': 23.701353073120117,
    'Sharpness': 99.99090576171875}},
  'Id': '1ax3nr0o',
  'MatchConfidence': 94.0,
  'Name': 'Kim Kardashian',
  'Urls': ['www.imdb.com/name/nm2578007']}]

对于下图:

第三步:将数据保存在长和宽的数据框中

还不错!现在把它们放在一个 for 循环中,这样你就可以得到一个数据帧,其中包含了我们想要使用 Rekognition 检索的所有信息。

长数据将像这样存储:

Data Cleaning idea: If it is a celebrity, remove all other labels as celebrity fashion can be difficult for Rekognition.

宽数据将像这样存储,每张图片一行,列跨越标签、单词和它们的置信度。

这个 for 循环步骤需要很长时间才能用完你的 Jupyter 笔记本。对于 10,000 张图片,我花了大约 8 个小时。Try/except 语句包含在每个组成部分 detect_labels、detect_text 和 recognize _ 中,因为并非所有图像都会从所有三个操作中得到响应。

图像处理愉快!

关于这个主题有很多资源,你可以在我发现每个资源最有用的步骤中找到我使用的链接。我发现 Rekognition 非常有效,但它确实有一些问题(就像任何图像识别工具一样)。特别是,没有被很好分类的照片是特定身体部位(即:嘴)的特写,一张眼影化妆的图像被分类为巧克力或软糖。

I can see how this can be mistaken for chocolate or fudge.

如果您在执行分析之前使用了这段代码,请在评论中链接您的项目,我很乐意看到您的工作。如果 Rekognition 给你的图片带来了任何古怪的标签或者错误的分类,我也想听听。

在我的 GitHub 上找到我的 Jupyter 笔记本:https://GitHub . com/nmolivo/Blogs/tree/master/002 _ AWS recognition

使用 torchtext 加载 NLP 数据集—第一部分

原文:https://towardsdatascience.com/use-torchtext-to-load-nlp-datasets-part-i-5da6f1c89d84?source=collection_archive---------5-----------------------

PyTorch Tensors 管道的简单 CSV 文件

如果你是 PyTorch 用户,你可能已经熟悉了 torchvision 库,因为 torchvision 已经变得相对稳定和强大,而已经成为 PyTorch 的官方文档。鲜为人知的 torchtext 库试图实现与 torchvision 相同的东西,但使用 NLP 数据集。它仍在积极开发中,并且有些问题可能需要您自己解决【1】【2】。尽管如此,我发现它已经相当有用了。最好使用 torchtext 并在需要时定制或扩展它(如果你的用例是通用的,也许还可以创建一个 PR)。)而不是自己构建整个预处理管道。

在这篇文章中,我将使用有毒评论分类数据集作为一个例子,并尝试使用 torchtext 演示一个加载该数据集的工作管道。我以前在一次不成功的尝试中使用过这个数据集,我们将在这里使用相同的标记化方案:

[## [学习笔记]用于多标签文本分类的 StarSpace

StarSpace 是一个雄心勃勃的模型,试图解决广泛的实体嵌入问题。它已经被创建并且…

medium.com](https://medium.com/@ceshine/learning-note-starspace-for-multi-label-text-classification-81de0e8fca53)

证明文件

首先需要解决的是文档。在项目自述之外基本没有简洁的代码示例。下一个最好的事情是在 test 文件夹中的单元测试。你必须弄清楚东西在哪里,然后自己把它们放在一起。

您可以使用 sphinx 从 docstrings 构建文档(在本文中我们使用了 torchtext 0.2.1):

pip install sphinx sphinx_rtd_theme
git clone --branch v0.2.1 [https://github.com/pytorch/text.git](https://github.com/pytorch/text.git)
cd text/docs
make html

HTML 页面将位于 text/docs/build/html 文件夹中。

我个人觉得直接看源代码比较容易。

预处理 CSV 文件

import pandas as pd
import numpy as npVAL_RATIO = 0.2def prepare_csv(seed=999):
    df_train = pd.read_csv("data/train.csv")
    df_train["comment_text"] = \
        df_train.comment_text.str.replace("\n", " ")
    idx = np.arange(df_train.shape[0])
    np.random.seed(seed)
    np.random.shuffle(idx)
    val_size = int(len(idx) * VAL_RATIO)
    df_train.iloc[idx[val_size:], :].to_csv(
        "cache/dataset_train.csv", index=False)
    df_train.iloc[idx[:val_size], :].to_csv(
        "cache/dataset_val.csv", index=False)
    df_test = pd.read_csv("data/test.csv")
    df_test["comment_text"] = \
        df_test.comment_text.str.replace("\n", " ")
    df_test.to_csv("cache/dataset_test.csv", index=False)

和上一篇文章一样,我把原始数据放在数据文件夹中,所有从它导出的数据都放在缓存文件夹中。这个 prepare_csv 功能的存在主要有两个原因:

  1. 您必须自己将训练数据集分为训练数据集和验证数据集。torchtext 不会为你这样做。
  2. 需要删除换行符。否则 torchtext 无法正确读取 csv 文件。

是为了确保我们每次都有相同的分成。

标记化

如前所述,标记化方案与前一篇文章中的相同:

import reimport spacy
NLP = spacy.load('en')
MAX_CHARS = 20000def tokenizer(comment):
    comment = re.sub(
        r"[\*\"“”\n\\…\+\-\/\=\(\)‘•:\[\]\|’\!;]", " ", 
        str(comment))
    comment = re.sub(r"[ ]+", " ", comment)
    comment = re.sub(r"\!+", "!", comment)
    comment = re.sub(r"\,+", ",", comment)
    comment = re.sub(r"\?+", "?", comment)
    if (len(comment) > MAX_CHARS):
        comment = comment[:MAX_CHARS]
    return [
        x.text for x in NLP.tokenizer(comment) if x.text != " "]

这个函数返回一个注释的标记列表。很长的注释被修剪为 MAX_CHARS 个字符,否则 NLP.tokenizer 可能需要很长时间才能返回。

加载数据集

import loggingimport torch
from torchtext import dataLOGGER = logging.getLogger("toxic_dataset")def get_dataset(fix_length=100, lower=False, vectors=None):
    if vectors is not None:
        # pretrain vectors only supports all lower cases
        lower = True
    LOGGER.debug("Preparing CSV files...")
    prepare_csv()
    comment = data.Field(
        sequential=True,
        fix_length=fix_length,
        tokenize=tokenizer,
        pad_first=True,
        tensor_type=torch.cuda.LongTensor,
        lower=lower
    )
    LOGGER.debug("Reading train csv file...")
    train, val = data.TabularDataset.splits(
        path='cache/', format='csv', skip_header=True,
        train='dataset_train.csv', validation='dataset_val.csv',
        fields=[
            ('id', None),
            ('comment_text', comment),
            ('toxic', data.Field(
                use_vocab=False, sequential=False,
                tensor_type=torch.cuda.ByteTensor)),
            ('severe_toxic', data.Field(
                use_vocab=False, sequential=False, 
                tensor_type=torch.cuda.ByteTensor)),
            ('obscene', data.Field(
                use_vocab=False, sequential=False, 
                tensor_type=torch.cuda.ByteTensor)),
            ('threat', data.Field(
                use_vocab=False, sequential=False, 
                tensor_type=torch.cuda.ByteTensor)),
            ('insult', data.Field(
                use_vocab=False, sequential=False, 
                tensor_type=torch.cuda.ByteTensor)),
            ('identity_hate', data.Field(
                use_vocab=False, sequential=False, 
                tensor_type=torch.cuda.ByteTensor)),
        ])
    LOGGER.debug("Reading test csv file...")
    test = data.TabularDataset(
        path='cache/dataset_test.csv', format='csv', 
        skip_header=True,
        fields=[
            ('id', None),
            ('comment_text', comment)
        ])
    LOGGER.debug("Building vocabulary...")
    comment.build_vocab(
        train, val, test,
        max_size=20000,
        min_freq=50,
        vectors=vectors
    )
    LOGGER.debug("Done preparing the datasets")
    return train, val, test

该功能有两个主要组件:data.Fielddata.TabularDatasetcomment变量指定了comment_text列的预处理管道,并在trainvalidationtest数据集之间共享,因此它们使用相同的词汇。一些细节:

  1. sequential=True指定该列保存序列。
  2. tokenizer=tokenizer指定记号赋予器。如果输入列足够干净,可以使用内置的标记器,例如tokenizer="spacy"
  3. fix_length将所有序列填充或修剪到固定长度。如果未设置,长度将是每批中最长序列的长度。
  4. pad_first=True从左侧填充序列。例如,如果目标长度为 5,A text sequence将被填充为<pad> <pad> A text sequence
  5. tensor_type指定返回的张量类型。由于在大多数情况下我们使用 GPU 来训练模型,将其设置为torch.cuda.LongTensor将省去我们稍后将其移动到 GPU 内存的麻烦。
  6. lower指定我们是否将所有英文字符设置为小写。

另一个非常方便的特性是.build_vocab,它构建了词汇表,因此我们可以在以后将记号/单词转换成整数,并且可以选择性地为您加载预训练的单词向量(comment.vocab.vectors将是与当前词汇表对齐的加载向量)。在处检查可用的预训练矢量。max_size设置最大词汇量,min_freq设置一个单词在语料库中出现的最少次数。

字段toxicsevere_toxicobscenethreatinsultidentity_hate为二元变量。稍后我们需要将它们组合在一起作为模型的目标。

data.TabularDataset.splits做的基本和data.TabularDataset.__init__一样,但是同时读取多个文件。测试数据集在单独的调用中加载,因为它没有目标列。我们必须在 csv 文件中以精确的顺序指定字段,并且不能跳过任何列。因此,我们必须明确指定("id", None)来跳过第一列。

创建批处理并遍历数据集

def get_iterator(dataset, batch_size, train=True, 
    shuffle=True, repeat=False):
    dataset_iter = data.Iterator(
        dataset, batch_size=batch_size, device=0,
        train=train, shuffle=shuffle, repeat=repeat,
        sort=False
    )
    return dataset_iter

这应该很简单。它会返回一些我们可以迭代的东西,当整个数据集都被读取后就会停止。我们还没有使用高级的sort特性,因为我们使用的是固定长度,我们可能不需要这样做。

下面是一个简单的用法示例(针对一个时期):

for examples in get_iterator(
            self.train_dataset, batch_size, train=True,
            shuffle=True, repeat=False
        ):
    x = examples.comment_text # (fix_length, batch_size) Tensor
    y = torch.stack([
        examples.toxic, examples.severe_toxic, 
        examples.obscene,
        examples.threat, examples.insult, 
        examples.identity_hate
    ], dim=1)

并使用加载的预训练向量(假设您的单词嵌入位于model.word_em,训练数据集作为train_dataset加载):

model.word_em.weight.data = \
    train_dataset.fields["comment_text"].vocab.vectors

就是这样!我们差不多已经有了开始构建和训练模型所需的东西。

20180207 更新:我注意到get_iterator既没有random_state也没有seed参数。实际上是靠random内置模块来管理随机性。因此,您需要执行以下操作之一来获得不同时期之间的不同批次:

  1. 在历元之间用不同的种子运行random.seed(seed)(在调用get_iterator之前)
  2. get_iterator中使用repeat=True。您必须自己在循环内部定义一个停止标准,否则 for 循环将永远继续下去。

未完待续…

上述方法存在一个重大问题。真的很慢。在我的电脑上,整个数据集加载过程大约需要 7 分钟,而实际的模型训练大约需要 10 分钟。我们应该序列化标记化的序列,也许还应该序列化词汇表,以使它更快。一旦我想通了,我打算在下一篇文章中写下如何去做。

除了序列化,许多事情也可以改进。例如,一个更灵活的训练/验证分割方案会有很大帮助。高级排序机制和压缩序列可能也值得探索。

附加链接

更详细的教程:

[## Torchtext 教程

大约 2-3 个月前,我遇到了这个库:Torchtext。我漫不经心地浏览了自述文件,意识到…

阿尼.我](http://anie.me/On-Torchtext/)

第二部分出版:

[## 使用 torchtext 加载 NLP 数据集—第二部分

序列化和更容易的交叉验证

medium.com](https://medium.com/@ceshine/use-torchtext-to-load-nlp-datasets-part-ii-f146c8b9a496)

Python 环境

  • Python 3.6
  • 数字版本 1.14.0
  • 熊猫
  • PyTorch 0.4.0a0+f83ca63(应该很接* 0.3.0)
  • 火炬文本 0.2.1
  • 空间 2.0.5

这篇文章中使用的所有代码

(不包括示例用法。)

使用 torchtext 加载 NLP 数据集—第二部分

原文:https://towardsdatascience.com/use-torchtext-to-load-nlp-datasets-part-ii-f146c8b9a496?source=collection_archive---------2-----------------------

序列化和更容易的交叉验证

Source

[## 使用 torchtext 加载 NLP 数据集—第一部分

PyTorch Tensors 管道的简单 CSV 文件

towardsdatascience.com](/use-torchtext-to-load-nlp-datasets-part-i-5da6f1c89d84)

在第一部分中,我们讨论了如何从 csv 文件加载文本数据集,标记文本,并通过 torchtext 将它们放入张量。现在,我们将解决该解决方案中的两个问题(仍然使用有毒评论数据集):

  1. 加载时间太长:每次你想运行一个新的实验,重新加载数据集会浪费你很多时间。
  2. 交叉验证方法的有限选择:实际上只有一个选择——可以通过 seedVAL_RATIO 参数控制的随机分割。

序列化

首先,TabularDataset不幸的是不能直接序列化。我们从观察开始寻找替代方案,在__init__方法中,TabularDataset 将文件读入示例列表:

with io.open(os.path.expanduser(path), encoding="utf8") as f:
    if skip_header:
        next(f)                                   
    examples = [make_example(line, fields) for line in f]

下一个观察是TabularDataset的超类Dataset接受一个参数examples(一个例子列表)。所以现在很清楚,我们需要的是序列化来自 **TabularDataset** 实例的示例,并根据请求创建 **Dataset** 实例。额外的好处是序列化了comment字段实例。

更具体地说,以下是一般的工作流程:

def read_files():
    comment = data.Field(...)
    train = data.TabularDataset(...) 
    test  = data.TabularDataset(...)
    comment.build_vocab(...)
    return train.examples, test.examples, commentdef restore_dataset(train_examples, test_examples, comment):
    train = data.Dataset(...)
    test  = data.Dataset(...)
    return train, test

前两个返回的变量是重建数据集的基本组件。如果你愿意,你可以改装一个comment字段实例,但是如果你不这样做,它会更快。初始化数据集时,只需插入comment作为字段之一。

交叉验证

因为现在我们从一系列例子而不是 CSV 文件中创建数据集实例,所以生活变得容易多了。我们可以按照我们想要的任何方式拆分示例列表,并为每个拆分创建数据集实例。对于分类任务,我通常更喜欢分层 K-Fold 验证。但因为有毒评论数据集是多标签的,所以更难做分层。我们将在下面的章节中使用简单的 K-Fold 验证。

把它放在一起

完整代码请参考帖子末尾。以下是新解决方案与第一部分中的旧解决方案之间的一些比较:

  1. 我们使用和以前完全一样的记号赋予器。
  2. 尽管不必创建训练/验证分割,我们仍然需要一个简化的prepare_csv 函数来从原始 CSV 文件中删除 \n 字符。
  3. 这个简洁的库joblib可以消除通过pickle模块显式序列化的需要。它的一个特性是对输出值的透明和快速磁盘缓存,这可以通过创建一个缓存设置MEMORY并在任何想要缓存的函数上使用**@MEMORY.cache** 装饰器来实现(在本例中,函数read_files读入 CSV 文件并返回两个示例列表和一个字段实例)。
  4. 主函数get_dataset现在返回一个生成器一个测试数据集。生成器为每次迭代提供一个训练数据集和一个验证数据集,并在您运行所有可用的 K 次迭代后实现 K 重验证。

以下是在 5 重验证方案下训练 5 个模型的脚本示例:

train_val_generator, test_dataset = get_dataset(
    fix_length=100, lower=True, vectors="fasttext.en.300d",
    n_folds=5, seed=123
)
for fold, (train_dataset, val_dataset) in \
    enumerate(train_val_generator):
    # Initialize a model here...
    for batch in get_iterator(
        train_dataset, batch_size=32, train=True,
        shuffle=True, repeat=False
    ):
        # Train the model here...
    # Create prediction for val_dataset and get a score...
    # Create inference for test_dataset...

如果你忘了,这里有一个特征和目标提取的例子:

x = batch.comment_text.data
y = torch.stack([
        batch.toxic, batch.severe_toxic, batch.obscene,
        batch.threat, batch.insult, batch.identity_hate
    ],dim=1)

加速

这取决于你的 CPU 的能力和你的磁盘的读取速度。在我的电脑里,第一次调用get_dataset需要 6 分多钟,之后大约 1 分钟。

有毒注释数据集加载器的更新版本

使用无监督的机器学习来寻找你的产品的潜在买家

原文:https://towardsdatascience.com/use-unsupervised-machine-learning-to-find-potential-buyers-of-your-products-cd75edaeefc7?source=collection_archive---------18-----------------------

让算法自己学习…

什么是无监督机器学习

欢迎来到我关于数据科学的第三篇文章!在我之前的帖子中,我讨论了我如何使用监督机器学习来为一个慈善机构寻找捐助者。回想一下,在监督机器学习中,您有输入变量(X)和输出变量(Y ),并且您使用算法来学习从输入到输出的映射函数。相比之下,在无监督的机器学习中你只有输入数据(X)而没有相应的输出变量。无监督学习的目标是对数据中的底层结构或分布进行建模,以便了解更多关于数据的信息。这些被称为非监督学习,因为不像上面的监督学习,没有正确的答案,也没有老师。算法被留给它们自己的装置去发现和呈现数据中有趣的结构。

无监督学习问题可以进一步分为聚类和关联问题。聚类:聚类问题是您想要发现数据中的内在分组,比如按照购买行为对客户进行分组。关联:关联规则学习问题是你想要发现描述大部分数据的规则,比如购买 X 的人也倾向于购买 y。

项目亮点

在我将在这里描述的项目中,我使用了来自德国一家邮购销售公司的 Bertelsmann Arvato Analytics 的真实财务数据。我的任务是识别构成该公司用户基础核心的人群。换句话说,我处理了一个集群问题。

在接下来的段落中,我将详细阐述我实现目标的步骤。就像在大部分机器学习问题中,无论你的算法有多复杂,都必须先清理数据。我们开始吧:)

数据处理

有四个数据集与此案例相关:

  • Udacity_AZDIAS_Subset.csv:德国一般人口的人口统计数据;891211 人(行)x 85 个特征(列)。
  • Udacity_CUSTOMERS_Subset.csv:邮购公司客户的人口统计数据;191652 人(行)x 85 特征(列)。
  • Data_Dictionary.md:所提供数据集中要素的详细信息文件。
  • AZDIAS_Feature_Summary.csv:人口统计数据特征属性汇总;85 个特征(行)x 4 列

人口统计文件的每一行代表一个人,但也包括个人以外的信息,包括他们的家庭、建筑和邻居的信息。我使用这些数据将普通人群分成具有相似人口统计特征的群体。目的是了解客户数据集中的人如何适应这些创建的分类。

让我们看看我们将使用哪些功能。

*# Load in the general demographics data.*
azdias = pd.read_csv('Udacity_AZDIAS_Subset.csv', sep = ';')

*# Load in the feature summary file.*
feat_info = pd.read_csv('AZDIAS_Feature_Summary.csv', sep = ';')print(feat_info)

在字典文件中,所有这些特性都有更详细的描述。即,提供了它们在英语中的含义,以及这些特征的不同级别的含义。

请注意,特征属性摘要的第四列(在上面作为feat_info载入)记录了数据字典中的代码,这些代码表示缺失或未知的数据。虽然文件将它编码为一个列表(例如[-1,0]),但它将作为一个字符串对象读入。我将匹配“缺失”或“未知”值代码的数据转换为 numpy NaN 值。

*# turn missing_or_unknown to list* 
feat_info['missing_or_unknown'] = feat_info['missing_or_unknown'].apply(**lambda** x: x[1:-1].split(','))

*# Identify missing or unknown data values and convert them to NaNs.*
**for** attrib, missing_values **in** zip(feat_info['attribute'], feat_info['missing_or_unknown']):
    **if** missing_values[0] != '':
        **for** value **in** missing_values:
            **if** value.isnumeric() **or** value.lstrip('-').isnumeric():
                value = int(value)
            azdias.loc[azdias[attrib] == value, attrib] = np.nan

评估各栏缺失数据

*# Perform an assessment of how much missing data there is in each column of the*
*# dataset.*
missing_data = pd.Series(azdias.isnull().sum() / len(azdias))
missing_data.plot(kind='barh', figsize=(10, 20))missing_data[missing_data > 0.2].index.tolist()['AGER_TYP',
 'GEBURTSJAHR',
 'TITEL_KZ',
 'ALTER_HH',
 'KK_KUNDENTYP',
 'KBA05_BAUMAX']*# Remove the outlier columns from the dataset. (You'll perform other data engineering tasks such as re-encoding and imputation later.)*azdias = azdias.drop(['AGER_TYP','GEBURTSJAHR','TITEL_KZ','ALTER_HH','KK_KUNDENTYP','KBA05_BAUMAX'], axis = 1)

我已经用柱状图评估了缺失的数据。我已经将丢失值超过 20%的列归类为异常值。结果,我找到了 6 个这样的列,我放弃了。其他突出的异常值是有 13%缺失值的 PLZ8 特性;以及具有 15%缺失值的 KBA05 功能。

评估每行的缺失数据

就像评估列中缺失数据的情况一样,我寻找含有缺失数据的异常行。我将阈值设置为每行 10 个缺失值,并将数据分为两组:缺失值数量多的行(即高于 10),缺失值数量少的行(即低于 10)。我比较了这两组之间几个非缺失特征的分布。目的是了解我是否应该以特定的方式对待这些数据点。

*# How much data is missing in each row of the dataset?*
missing_data_rows = azdias.isnull().sum(axis = 1)missing_data_rows_low = azdias[azdias.isnull().sum(axis=1) < 10].reset_index(drop=**True**)

missing_data_rows_high = azdias[azdias.isnull().sum(axis = 1) >= 10].reset_index(drop=**True**)**def** countplot(columns, num):
    fig, axs = plt.subplots(num, 2, figsize=(15, 15))
    fig.subplots_adjust(hspace =2 , wspace=.2)
    axs = axs.ravel()

    **for** i **in** range(num):

        sns.countplot(missing_data_rows_low[columns[i]], ax=axs[i*2])
        axs[i*2].set_title('missing_data_rows_low')
        sns.countplot(missing_data_rows_high[columns[i]], ax=axs[i*2+1])
        axs[i*2+1].set_title('missing_data_rows_high')

countplot(missing_data_rows_high.columns, 3)

对于我检查过的一些特性,缺失值多的行和缺失值少的行之间似乎有不同的分布。这意味着缺失值数量多的行和缺失值数量少的行之间的数据在性质上是不同的。缺失数据数量少的行组将被考虑用于进一步分析,而缺失数据数量多的行组最终将被视为附加聚类。

数据角力

**def** clean_data(df):
    *"""*
 *Perform feature trimming, re-encoding, and engineering for demographics*
 *data*

 *INPUT: Demographics DataFrame*
 *OUTPUT: Trimmed and cleaned demographics DataFrame*
 *"""*

    *# Put in code here to execute all main cleaning steps:*
    *# convert missing value codes into NaNs, ...*

    df_copy = df.copy()

*# Identify missing or unknown data values and convert them to NaNs.*
    **for** col_name **in** df.columns:
        df_copy[col_name] = df_copy[col_name].map(**lambda** x: np.nan **if** str(x) **in** feat_info.loc[col_name].missing_or_unknown **else** x)

    *# remove selected columns and rows, ...*
    c_removed =['AGER_TYP','GEBURTSJAHR','TITEL_KZ','ALTER_HH','KK_KUNDENTYP','KBA05_BAUMAX']

    **for** c **in** c_removed:
        df_copy.drop(c, axis=1, inplace=**True**)

    df_copy = df_copy[df_copy.isnull().sum(axis=1) < 10].reset_index(drop=**True**)

    **for** col **in** df_copy.columns:
        df_copy[col] = df_copy[col].fillna(df_copy[col].mode()[0])

    *# select, re-encode, and engineer column values.*
    multi_level = []
    **for** column **in** df_copy.columns:
        **if** feat_info.loc[column].type == 'categorical' **and** len(df_copy[column].unique()) > 2:
            multi_level.append(column)

    **for** col **in** multi_level:
        df_copy.drop(col, axis=1, inplace=**True**)

    df_copy['decade'] = df_copy['PRAEGENDE_JUGENDJAHRE'].apply(create_interval_decade)
    df_copy['movement'] = df_copy['PRAEGENDE_JUGENDJAHRE'].apply(create_binary_movement)
    df_copy.drop('PRAEGENDE_JUGENDJAHRE', axis=1, inplace=**True**)

    df_copy['wealth'] = df_copy['CAMEO_INTL_2015'].apply(wealth)
    df_copy['life_stage'] = df_copy['CAMEO_INTL_2015'].apply(life_stage)
    df_copy.drop('CAMEO_INTL_2015', axis=1, inplace=**True**)

    df_copy = pd.get_dummies(data=df_copy, columns=['OST_WEST_KZ'])

    mixed = ['LP_LEBENSPHASE_FEIN','LP_LEBENSPHASE_GROB','WOHNLAGE','PLZ8_BAUMAX']

    **for** c **in** mixed:
        df_copy.drop(c, axis=1, inplace=**True**)

     *# Return the cleaned dataframe.*
    **return** df_copy

我创建了一个清理数据函数,可以应用于一般人口统计数据和客户统计数据。

主成分分析

PCA 是最常用的无监督机器学习工具之一。主成分是数据集中原始特征的线性组合,旨在保留原始数据中的大部分信息。主成分分析是一种基于现有特征从数据集中提取新的“潜在特征”的常用方法。想象一个主成分,就像你想象一个潜在特征一样。

当我们拥有包含成百上千个特征的数据集时,为了有效地构建模型,我们必须减少维数。有两种方法可以做到这一点:

a) 特征选择:特征选择包括从您确定最相关和最有用的原始数据特征中寻找一个子集

b) 特征提取:特征提取包括提取或构建称为潜在特征的新特征。

特征转换

我执行了特征缩放,这样主成分向量就不会受到特征缩放的自然差异的影响。

*# Fill the Nan values with the mode of that respective column.***for** col **in** missing_data_rows_low.columns:
        missing_data_rows_low[col] = missing_data_rows_low[col].fillna(missing_data_rows_low[col].mode()[0])*# Apply feature scaling to the general population demographics data.*normalizer = StandardScaler()
missing_data_rows_low[missing_data_rows_low.columns] = normalizer.fit_transform(missing_data_rows_low[missing_data_rows_low.columns])missing_data_rows_low.head()

降维

*# Apply PCA to the data.*

pca = PCA()
missing_data_rows_low_pca = pca.fit_transform(missing_data_rows_low)*# Investigate the variance accounted for by each principal component.***def** scree_plot(pca):
    *'''*
 *Creates a scree plot associated with the principal components* 

 *INPUT: pca - the result of instantian of PCA in scikit learn*

 *OUTPUT:*
 *None*
 *'''*
    num_components = len(pca.explained_variance_ratio_)
    ind = np.arange(num_components)
    vals = pca.explained_variance_ratio_

    plt.figure(figsize=(10, 6))
    ax = plt.subplot(111)
    cumvals = np.cumsum(vals)
    ax.bar(ind, vals)
    ax.plot(ind, cumvals)

    ax.xaxis.set_tick_params(width=0)
    ax.yaxis.set_tick_params(width=2, length=12)

    ax.set_xlabel("Principal Component")
    ax.set_ylabel("Variance Explained (%)")
    plt.title('Explained Variance Per Principal Component')

scree_plot(pca)

*# Re-apply PCA to the data while selecting for number of components to retain.*

pca = PCA(n_components=41)
missing_data_rows_low_pca = pca.fit_transform(missing_data_rows_low)

基于 PCA 图,解释的方差在 41 个成分之后变得极低,并且之后不变。所以我又用 41 个成分做了主成分分析。

每个主成分是一个指向最高方差方向的单位向量(在考虑了早期主成分捕获的方差之后)。权重离零越远,主分量在相应特征的方向上就越多。如果两个特征具有相同符号的较大权重(都是正的或都是负的),那么一个特征的增加会与另一个特征的增加相关联。相比之下,具有不同符号的特征可能会表现出负相关性:一个变量的增加会导致另一个变量的减少。

对普通人群应用聚类分析

**def** get_kmeans_score(data, center):
    *'''*
 *returns the kmeans score regarding SSE for points to centers*
 *INPUT:*
 *data - the dataset you want to fit kmeans to*
 *center - the number of centers you want (the k value)*
 *OUTPUT:*
 *score - the SSE score for the kmeans model fit to the data*
 *'''*
    *#instantiate kmeans*
    kmeans = KMeans(n_clusters=center)

    *# Then fit the model to your data using the fit method*
    model = kmeans.fit(data)

    *# Obtain a score related to the model fit*
    score = np.abs(model.score(data))

    **return** score*# Over a number of different cluster counts...*
*# run k-means clustering on the data and...*
*# compute the average within-cluster distances.*scores = []
centers = list(range(1,30,3))

**for** center **in** centers:
    scores.append(get_kmeans_score(missing_data_rows_low_pca, center))*# Investigate the change in within-cluster distance across number of clusters.*
*# HINT: Use matplotlib's plot function to visualize this relationship.*plt.plot(centers, scores, linestyle='--', marker='o', color='b');
plt.xlabel('K');
plt.ylabel('SSE');
plt.title('SSE vs. K')

*# Re-fit the k-means model with the selected number of clusters and obtain*
*# cluster predictions for the general population demographics data.*

*# Re-fit the k-means model with the selected number of clusters and obtain*
*# cluster predictions for the general population demographics data.*

kmeans = KMeans(n_clusters=22)
model_general = kmeans.fit(missing_data_rows_low_pca)predict_general = model_general.predict(missing_data_rows_low_pca)

根据该图,我们可以看到 22 似乎是一个足够的集群数量。后来的变化率是 SSE 极低。

将客户数据与人口统计数据进行比较

在对人口统计数据进行聚类之后,我们对客户统计数据应用相同的数据清理步骤和聚类。目的是看哪个对公司来说是强大的客户群。

如果与一般人群相比,客户数据的聚类中有更高比例的人(例如,5%的人被分配到一般人群的聚类,但是 15%的客户数据最接*该聚类的质心),则这表明该聚类中的人是公司的目标受众。另一方面,聚类中的数据在一般人群中的比例大于客户数据(例如,只有 2%的客户最接*捕获 6%数据的人群质心)表明该人群在目标人口统计之外。

分析客户数据过多的聚类

*# What kinds of people are part of a cluster that is overrepresented in the*
*# customer data compared to the general population?*
over = normalizer.inverse_transform(pca.inverse_transform(customers_clean_pca[np.where(predict_customers==11)])).round()
df_over = pd.DataFrame(data = over, columns = customers_clean.columns)
df_over.head(10)

这个细分市场由年龄在 46 岁到 60 岁之间的个人组成,他们不是财务上的最低要求者。也就是说,他们可能是退休或接*退休的人,渴望消费商品和服务。

分析客户数据代表性不足的聚类

*# What kinds of people are part of a cluster that is underrepresented in the*
*# customer data compared to the general population?*
under = normalizer.inverse_transform(pca.inverse_transform(customers_clean_pca[np.where(predict_customers==16)])).round()
df_under = pd.DataFrame(data=under, columns=customers_clean.columns)
df_under.head(10)

这部分人由较年轻年龄组(45 岁以下)的人组成,失业人口比例较大。

项目结束

回想一下,在数据处理步骤中,我们确定丢失数据数量较多的行组最终将被视为一个额外的聚类。上述组中的簇 22 是最后添加的簇。我们可以看到,在大多数集群中,人口百分比和客户百分比之间存在相当大的差异。在大多数集群中,一般人口所占比例过大。例如,在聚类 11 中,客户部分被过度表示;它由年龄在 46 岁到 60 岁之间的人组成,他们都不是财务上的极简主义者。也就是说,他们可能是退休或接*退休的人,渴望消费商品和服务。所以把它当成一个客户群是有道理的。另一方面,在聚类 16 中,客户细分未被充分代表。这部分人由较年轻年龄组(45 岁以下)的人组成,失业人口比例较大。由于他们大多失业,他们很可能依靠社会保障生活。因此,他们没有大量的可支配资金来购买销售给他们的产品。

结束语

如果你坚持到了最后,非常感谢你的阅读:)我知道这些帖子很长,并且包括许多代码片段,但我真的认为忽略机器学习的技术方面对于展示算法如何工作是不可行的。这个项目对我来说是有益的,因为它包含了真实世界的财务数据和真实世界的商业目标。

我希望这能让你理解无监督机器学习如何应用于商业和营销。如果你想浏览我写的所有代码,你可以在我的 github 上访问我的项目。

在 LinkedIn 上关注我:【https://www.linkedin.com/in/andreigalanchuk/

上帝保佑你!

检测盈余操纵和欺诈的有用工具

原文:https://towardsdatascience.com/useful-tools-for-detecting-earning-manipulation-and-fraud-b203ae02cb87?source=collection_archive---------9-----------------------

在 MSBA 的夏季学期,我遇到了当时我处理过的最大的数据集。这是财务会计课程的作业。该主题与利用公司会计数据检测盈余操纵和欺诈有关。

数据集来自 Compustat,这是一个关于全球活跃和不活跃的全球性公司的金融、统计和市场信息的数据库(引自维基)。老师给我们提供了数据库。我们的任务是通过不同的模型和工具来检测收入异常。

这个过程令人生畏,但充满乐趣。一个月后,我决定重温这些作业。在这篇文章中,我将介绍我所学到的检测盈余操纵和潜在欺诈的模型和工具。

这篇文章将从理论和实践两方面来写。我将尽力阐述我所知道的工具,并展示如何实现结果的代码。这些工具应用于 1988 年至 2017 年的年度数据,以及数据集中的每一家公司,这些数据展示了盈余操纵趋势的整体情况。

在下一篇文章中,我将介绍我是如何使用这些工具对全球最大的生物技术公司之一安进公司进行盈余操纵研究的。

工具和技能

主要工具:Python Spyder 和 R

使用的技巧:用熊猫清理数据,用 Matplotlib 和 ggplot2 可视化,线性回归,固定效应回归

分析工具和流程概述

A.清理和切片数据

B.简单的探索性数据分析

C.盈余管理的间接证据

D.本福特定律

E.全权应计模型

F.经营现金流和应计模型

A.清理和切片数据

Compustat 是一个庞大的数据集。在数据字典中,它包含* 1000 个变量,数据跨越*半个世纪,包含详细的公司信息。它的 CSV 文件将* 1.6GB,用户无法用一个简单的 excel 打开它,加载到 R 和 Python 需要一段时间。

在作业中,我的目标是描述某个数据块的经济真相。所以我按照教授的指导进行了数据清理和切片,后来我将数据导出为大小合适的 csv 文件,并将其附在我的 Github 中。如果感兴趣,可以下载并试用它。

数据清理过程需要几个步骤。

(1)仅选择几个变量,包括 gvkey(公司标识符)、datadate(报告期)、fyear(财政年度)、revt、rect、ppegt、epspi、ni、at、oancf、sic 和 rdq。

(2)样本年份限定在 1988 年至 2017 年之间。

(3)放弃任何缺少资产、收入、净收入、每股收益、应收账款和经营现金流的观察。

(4)如果 PPE 丢失,将其设置为零。

(5)放弃任何收入和应收账款为负数的观察。

(6)删除基于除列 rdq 之外的所有列的重复观察。

按照说明,我编写了如下 python 代码。在该过程之后,数据帧保持大约 248,288 行,这是可以接受的。

compustat = pd.read_csv("compustat_1950_2018_annual_merged.csv")
compustat_1 = compustat[["gvkey","datadate","fyear","revt","rect","ppegt","epspi","ni","at","oancf","sic","rdq"]]
compustat_2 = compustat_1.loc[compustat_1["fyear"] > 1987]
compustat_2 = compustat_2.loc[compustat_2['fyear'] < 2018]
compustat_3 = compustat_2[compustat_2["revt"] >=0]
com_3 = compustat_3[compustat_3['rect'] >= 0]
com_4 = com_3.dropna(subset = ['at','revt','ni','epspi','rect','oancf'])
com_5 = com_4.drop_duplicates(com_4.columns.difference(['rdq']))
com_6 = com_5.fillna(0)

B.简单的探索性数据分析

这一部分试图呈现我清理的数据的全貌。我先简单算一下文件中所有公司的组合 2017 年的营收、净收入、总资产的*均值。逻辑讲师选择这三个指标进行观察的原因非常简单。这些指标对投资者来说很容易理解,也成为操纵的首要目标。

此外,我用简单的代码块绘制了从 1988 年到 2017 年这三个指标的趋势。

df2 = df.groupby('fyear').agg({'revt':'mean', 'ni':'mean', 'at':'mean'})plt.figure(figsize=(10,8))
plt.plot(df2['revt'], linestyle = 'solid')
plt.plot(df2['ni'], linestyle = 'dashed')
plt.plot(df2['at'], linestyle = 'dashdot')
plt.legend(df2.columns.values.tolist())
plt.title('Trend for Revenue, Net Income & Total Asset 1988-2017')
plt.show()

从上面的图像中,我们可以看出,与收入和净收入相比,总资产的*均值大幅增加。对于整个行业来说,财政的资产数量正在增长。这是否意味着某种操纵?(暂时不知道)。至于净收入,其*均值多年来没有太大变化。也许这意味着净收入的质量或计算方式使其更难操纵。我将更进一步,并在稍后揭示这些工具的不同应用的更多细节。

C.盈余管理的间接证据

接下来,我计算了每个公司从 t 年到 t-1 年的每股收益(EPS)和资产回报率(ROA)的变化,并进一步在-0.1 和+0.1 的范围内绘制成直方图。这张图表可以给我们一个可能的盈余管理的更间接的暗示。

我使用 group by 和 shift 函数来创建滞后年度的 EPS 和 ROA。

df3 = df
df3['previous_eps'] = df3.sort_values(['fyear']).groupby('gvkey')['epspi'].shift()
df3['eps_change'] = df3.epspi - df3.previous_eps

我用 Matplotlib 创建了两个相似的图表。

plt.style.use('seaborn-white')
plt.figure(figsize = [15,6])
plt.hist(df4_eps, bins=20, align = 'left')
plt.plot((0,0),(0,8000),'r--')
plt.title('EPS Change Distirbution')

图表显示,在数据集中的所有公司中,每股收益的分布比净资产收益率的分布更不对称。此外,我们还观察到,对于每股收益,正数的频率略大于零,这意味着每年,公司的每股收益往往比前一年表现更好。

这种差异有几个原因。盈余管理可能是一个原因,其他原因如经理更加努力工作也是可能的。

通常,EPS 是利益相关者和市场更关心的指标。它比 ROA 更明显地反映了经理的表现。此外,可以通过回购或向市场释放更多股票来操纵或控制每股收益。这可能是两个关键指标图形对称性差异的原因。

变成单个公司范围,也可以让我们一窥盈余操纵的证据。我可以对某个公司的数据进行子集化,就像上面那样画出对称图,观察异常。

D.本福特定律

本福德定律,也称为首位数定律,是关于许多现实生活中的数字数据集中前导数字的频率分布的观察结果(引自维基百科)。对于一大组数据或列值,本福德定律告诉我们,第一个数字的出现遵循一些规则和概率。因此,如果计数/频率的结果与本福特定律有一些偏差,则存在更高的操纵可能性。

按照老师的指示,我将工具从 Python 切换到 benford.analysis 软件包可以轻松计算列的第一位和第二位。我用收入经营现金流总资产作为观测值。

revenue_bf <- data.frame(benford(abs(df$revt), number.of.digits = 1, sign = 'positive', discrete = TRUE, round = 3)$bfd)[,c("digits","data.dist", "benford.dist")]colnames(revenue_bf) <- c('Digit', 'Sample_Revenue', 'Benford_Distribution')ggplot(data = revenue_bf, aes(x = as.factor(Digit), y =Benford_Distribution)) +
  geom_bar(stat='identity') + 
  geom_line(aes(Digit, Sample_Revenue, col = 'Sample_Revenue'), linetype = 1) + 
  geom_point(aes(Digit, Sample_Revenue), size = 4, col = 'red')+
  ggtitle('Theoretical Distribution v.s. Sample Revenue Distribution - 1st Digits ')

从上面的三张图中,我们可以看到三列中第一位数字的理论分布和样本分布。视觉上,没有那么巨大的差别。

我决定利用卡方检验来看看理论分布和样本分布之间是否真的没有显著性差异。结果如下。

从 p 值来看,经营性现金流并不重要也就不足为奇了。然而,根据测试,收入不会偏离太多,这超出了我的预期,这表明在第一位数操纵的可能性很低。对于资产而言,当其 p 值较低且显著时,其第一位数被操纵的概率较高。还记得一年中的资产图表吗?它的*均值增长了很多。从本福德定律中,我进一步证实了操纵资产的可能性高于所有公司。

在查看第一个数字后,每个特定列的第二个数字也值得调查。与第一个数字略有不同,第二个数字包含数字零,这改变了每个数字的分布百分比。三个指标的结果如下所示。

从上面的三张图中可以明显看出,样本收入、现金流和资产中零的出现频率高于理论上的本福特分布。一种可能的解释是,当公司计算数字时,他们可能倾向于将 9 四舍五入到 10,这导致 0 多 9 少。这可能是有意或无意的,但绝对值得更多的检查,尤其是在分析单个公司时。

从卡方检验来看,所有三个指标的 p 值都非常显著。在所有的收入中,最重要的一项是,这可能意味着经理们倾向于做一些把戏,如收入四舍五入,以获得更好的数字表现。

E.全权应计模型

讲师告诉我们,证券交易委员会使用自主应计模型来筛选公司的不当盈余管理。公式如下:

在这个 OLS 模型中,应计项目是净收入减去经营现金流。除了 SIC 之外的所有变量都来自上一年的数据。因此,简单地说,OLS 模型试图测试以前的业绩指标对今年应计项目的预测能力。SIC 是行业分类器,这意味着对于不同的行业,可能有不同的组和不同水*的估计,可能授予不同的应计项目。

因此,使用面板数据回归来运行整个数据集是一个好主意。代码如下。

fixed_effect.accrual <- plm(accrual ~ cash_revenue + ppe + sic, data= accrual_df, index = c('sic'), model = 'within')

拟合直线后,模型的真正目标是找到残差的绝对值。对此的解释是,如果一个公司,与同行业的其他公司相比,有更高的残差绝对值。其收益更偏离行业标准,具有更高的操纵可能性。

accrual_df$residual <- fixed_effect.accrual$residuals
accrual_df$residual <- abs(accrual_df$residual)

我将在下一篇文章中展示 Amgen 公司的流程。

F.经营现金流和应计模型

该模型还使用 OLS 预测能力,使用应计项目和上一年的经营现金流来预测下一年的经营现金流。公式如下:

我决定对数据集中的每一行进行回归拟合。代码是这样的。我们得到拟合回归的总结。

df$accurals = df$ni - df$oancfdf2 <- df[,c('gvkey','fyear','oancf')]
df3 <- mutate(df2, fyear = fyear - 1) %>%
  rename(., next_oancf = oancf)
df <- left_join(df, df3, by = c('gvkey',"fyear"))oc_reg <- lm(df$next_oancf ~ df$accurals + df$oancf)
summary(oc_reg)

综上所述,应计项目和前期现金流量的 p 值显著,这意味着两者都与下一年的经营现金流量高度相关,并且与目标变量正相关。

之后,导师让我们把数据分成两组,2002 年之前和之后。因此,我在两组数据上运行相同的模型,并得到两个拟合的 OLS 模型的摘要。

1988–2002 Operating cash flow model

2003–2017 Operating cash flow model

从上面的总结中,我们可以从 r-squared 和估计中看出,模型的预测能力在 2002 年之前更为显著。这种差异的经济真相可能是,随着 2002 年后对应计项目或经营性现金流的更多操纵,该模型的预测能力从那时起就被扭曲了。

有了这个模型,它也有助于发现单个公司操纵现金流。策略是将数据分成相等的时间范围,并观察每个时间段的预测能力,以检测可能的盈余管理。在我的下一篇文章中,我也将再次讨论这个问题。

结论

在这篇文章中,我尽力阐述了我在课堂上学到的工具,并展示了将这些工具应用于整体数据的过程。这是一个真正具有挑战性的过程,但通过重新审视数据集和这些模型,我开始意识到进一步研究的深度。在不久的将来,我肯定会继续我的欺诈和利润操纵之旅。

  • 特别感谢我的财务会计课的老师,他给了我一个鼓舞人心的夏天。
  • 所有代码都可以在我的 Github 中找到。请随时给我一些反馈。
If you like the article, feel free to give me 5+ claps
If you want to read more articles like this, give me 10+ claps
If you want to read articles with different topics, give me 15+ claps and leave the comment hereThank for the reading

机器学习的用户体验

原文:https://towardsdatascience.com/user-experience-with-machine-learning-3bcb90fa88a0?source=collection_archive---------5-----------------------

众所周知,机器学习在可解释性方面存在困难,或者更确切地说,是缺乏可解释性。如果您的用户必须处理数字输出,就像在销售、交易或市场营销中使用的系统一样,这是一个问题。如果用户对 ML 输出的解释是错误的,那么实际的度量标准就无关紧要了,你最终会得到糟糕的用户体验。如果您尝试将用户从旧的透明算法切换到 ML,问题甚至会更大——不满意的用户可能会试图反对切换到 ML。此外,尽管听起来有些反直觉,但用户的数学能力可能会对你不利,因为最有经验的用户会给你最大的阻力。

在这里,我概述了当您开始将系统切换到 ML 时,克服用户推回的方法。坦率地说,这些想法中的大多数可以应用于任何黑盒系统,而不仅仅是 ML。其中一些与前景理论有关,这在一本很棒的书《T2 思考,快与慢》中有描述。

变速杆

一些司机喜欢手动档而不是自动档,仅仅是因为他们喜欢控制的感觉。

假设旧系统实现了一个简单易懂的算法,用户可能会选择永远保留它,只是因为他们喜欢清晰和可控的感觉。你的 ML 模型将缺乏对它如何得出特定结果的可解释性,甚至最简单的算法,如基于阈值的 if-condition,在用户眼中也可能胜过 ML。

来自有经验的用户的反推甚至更强,因为他们已经掌握了多个临时变通办法,补偿了简单算法的低复杂性。变通方法的一个例子是:“如果价格低于 100 美元,但周差价小于 2%,那么不要买股票”。他们越有经验,就越看不到 ML 的附加值。

有两种方法,你可以尝试用变速杆。强调当这些权宜的解决方法严重失败时的场景。此外,如果没有其他事情,尝试将你的新 ML 模型与旧算法并行推出,以吸引两种受众——喜欢手动挡的用户和喜欢自动变速器的用户。

概率不是直观的

您可能认为增加输出的可信度会使它更容易理解。例如,ML 输出不是说“购买 APPL 股票”,而是说“以 80%的信心购买 APPL 股票”。可惜概率不是直观的。例如,与 5%和 0%相比,65%比 60%好多少?大家一致认为,把某人的胜算从 0%提高到 5%,比 60%→65%更让人印象深刻。

我们倾向于给 0%→5%的增长赋予不成比例的显著性,这被称为可能性效应。类似地,我们倾向于给 95%→100%的增长赋予不成比例的巨大意义——确定性效应

例子

假设我们有一个 ML 系统,它会对你是否应该购买股票期权提出建议。它提出了两个建议:

购买股票期权 A,有 95%的机会获得 100 万美元
购买股票期权 B,有 100%的机会获得 91 万美元

大多数人会规避风险,选择 B,因为确定性效应,尽管第一笔交易的数学预期更好。

现在假设您的 ML 系统输出另一对推荐:

购买股票期权 C,有 5%的机会获得 100,000 美元
购买股票期权 D,有 100%的机会获得 5,100 美元

大多数人会冒险选择 C,再次无视数学期望。用户的偏见也会根据他们认为自己目前是处于赢还是输的情况而发生巨大变化,这可以用的四重模式来描述。

如果你在你的系统的输出中包括概率,你可能最终会被用户以他们自己的方式重新解释你的 ML 系统的输出,这取决于他们的个人因素。

解决方案之一是完全避免输出概率。例如,假设您的系统预测购买股票期权 A 将获得 1,000,000 美元的回报,其中 100,000 美元是标准差。您可以降低置信度,向用户推荐“购买股票期权 A 以获得 800,000 美元”,这里您忽略了这个推荐有 95%的置信度——2 个标准差。在某种程度上,你不是将评估概率的任务委托给用户,而是自己做决定。好处是用户之间对输出的解释不会有太大的不同。明显的缺点是,你要为自己打电话负责。

控制点

如果用户花时间思考系统的输出,那么参考点可能会出现在你面前。参考点是用户用来比较系统输出的东西。它可能是一些以前的历史数据,一些在过去发生的值得纪念的案例,或者一些他们用来最初测量输出的简单测量。

假设你的旧的简单算法根据股票价格的每日变化给出建议,例如,如果每日变化大于 5%,那么它建议买入。如果你的用户已经使用这个老算法很长时间了,那么他们可能已经开发了一个参考点——价格的每日变化。每次看到股票推荐,他们做的第一件事就是查看价格的每日变化。

你的新机器学习模型可能比旧算法更复杂,因为它可能能够挑选出与价格每日变化无关的其他信号。一旦你向用户提供的推荐没有显著的日常变化,用户可能会认为它们有问题而丢弃它们,你的系统将失去可信度。

了解用户是否有参考点以及参考点是什么非常重要。最好的方法是坐在用户旁边,让他们像*常一样使用你的系统。然后问关键问题:“当你开始查看系统的输出时,你做的第一件事是什么?”。答案很可能是参考点。

分三步走的计划

识别和处理变速杆可以让你照顾那些断然反对切换到 ML 的用户,独立于其质量。在用户界面中避免概率会让你摆脱大范围的人类偏见。有时最好自己打个电话,隐藏信心估计。参考点可能对你的 ML 模型有偏见,识别它将帮助你确保用户对你的 ML 系统有一个公正的评价。

照顾好这三个方面将会大大减少用户反对机器学习的机会。

使用 3D 可视化来调整 ML 模型中的超参数

原文:https://towardsdatascience.com/using-3d-visualizations-to-tune-hyperparameters-of-ml-models-with-python-ba2885eab2e9?source=collection_archive---------3-----------------------

这篇文章的大部分是交互式可视化,你可以在上面悬停、缩放和移动。在电脑上阅读比在手机上阅读更好,但手机上的横向模式至少会让你比纵向模式更好地看到情节。

想象一下,你正试图为 Kaggle 的
Rossmann 商店销售竞争开发一个解决方案。你已经做了大量的功能工程,并创造了大量的新变量,这可能有助于你更好地预测未来的销售。

您创建了一个随机森林,并试图找到其最佳超参数。大概有 1000 多种你想要评估的组合。您可以运行随机搜索来分析其中的一个子样本,或者运行网格搜索来探索整个参数网格。

Some of the parameters are evenly spaced on a log scale. You can do that with np.logspace

你做了后者,现在有了一些数据。使用 rf_gridsearch.best_params_ 可以获得在测试集上产生最佳结果的 3 个参数(max_features: 0.25,min_samples_split: 13,n_estimators: 45)。但是,如果你想在三维空间中可视化所有被训练的随机森林的表现呢?

等等,这些流行语是什么意思?

决策树 是一种受监督的机器学习算法,它给定一个数据集,将其递归地划分为具有彼此更相似的目标变量的子集。给定一些带有用于训练它的自变量的新数据,它可以预测因变量。

A decision tree used for regression. Credit: this great post from UC Berkeley

一个 随机森林 (从现在开始的 RF)是一个决策树的集合,这些决策树是在全部训练数据的子集上训练的,并且使用特征的子集。这允许它们具有较少相关的个体决策树,因此它们将更好地概括且具有较少的过度拟合。它们比神经网络训练起来更快,是解决结构化数据的分类和回归问题的一个很好的快速的首次尝试。

我们可以在 RFs 中设置几个超参数。请在 scikit-learn 的文档中阅读所有相关内容。其中一些最重要的是:

  • n _ estimators:RF 中树的数量。
  • min_samples_split:将一个子集(又名节点)再分成两个子集的最小样本数。与最小样本叶和最大深度相关
  • max_features : 分割节点时要考虑的最大特征数(独立变量)

RF 的复杂性随着较高的 n 估计量、最大特征和较低的最小样本分割而增加。

交叉验证是一种用于在机器学习模型中寻找最佳超参数的技术。为了执行它,我们必须将数据分成3 个子集:一个训练集(用于训练模型)、一个验证集(优化超参数)和一个测试集(最后检查模型的性能,就像我们已经在生产中一样)。我们使用一些分数来评估模型的性能,这些分数将根据我们试图解决的问题类型(回归、分类、聚类……)而变化。

A pic is always worth 1000 words!

对于回归, R2 (R *方)效果很好,是我用过的。一般来说,模型越复杂,训练集中的分数就越好。在测试集上,它也会随着模型复杂度的增加而增加,但在某个点之后,它不会增加,还会减少。我们所做的交叉验证就是试图找到那个点。

好了,我们走吧🔥

在我们的例子中,模型复杂度是 3 个超参数的函数。我们接下来要做的是,尝试可视化在超参数的 3D 网格中找到最佳模型的位置,以及所有组合的表现。请注意,在图中,我使用了词语测试集测试分数,但我指的是验证。

第一:2D 热图

作为一种快速的方法,我们可以用可能的不同参数对绘制热图,以查看在测试和训练集中实现最大 R2 的区域。这可以通过几行代码来完成:

R2 scores for the test sets

R2 scores for the training sets

但是这样做我们仍然只能看到结果的一小部分。为了看到所有这些(并且比热图更清晰),我们需要创建 3D 可视化。

散点 3D

使用 Plotly 我们可以创建各种各样的漂亮的交互式可视化。首先,让我们创建一个 3D 散点图,其中点的大小与训练时间成比例,颜色与测试集中的 R2 分数成比例。

See this in fullscreen mode here

很好,但我们还是看不到太多。我们可以说 max_features 越大,min_samples_split 越小,测试分数就越大,但是很难悬停在 3D 散点图中间的点上。

这样做的代码对于 Medium 来说太长了,但是你可以在这里看到所有的内容

更好:添加滑块

我们有 3 个独立变量,这 3 个参数是我们要优化的。更直观的方法是保持其中一个变量的值不变,绘制测试 R2 分数与其他两个变量的 3D 表面。
这更接*我们习惯看到的 1D 验证曲线,如果我们添加一个滑块来移动第三个变量,我们可以有效地看到与之前的图相同的信息,但以更清晰的方式

Fullscreen mode here.

或者,如果您更喜欢 3D 散点图,以便您可以看到每个单独的点,这就是。点数的大小与训练时间成比例,颜色与 R2 分数成比例。

Fullscreen

最后但同样重要的是…

How the size of the bubbles will be after scaling it.

有一种方法可以显示第一个 3D 散点图,显示所有的点,但使测试分数最高的点比其他点大得多,这样我们就可以专注于它们。这是通过将*均测试分数除以其最大值,并以一种特殊的方式进行缩放来获得我们想要的大小。

最后,如果我们这样做,这就是情节的样子。重要的几点现在看得更清楚了:

This is an image. To see the interactive plot go here

如果我们想更进一步,优化 4 个超参数,我们可以将第 4 个维度作为滑块添加到该图中,就像前面的例子一样,并且能够通过 4 个维度有效地可视化数据。想不到!

点击查看 Python 笔记本中创建这个的代码

玩得开心!

用 Python 中的马尔可夫链语句生成器生成‘真假新闻’。

原文:https://towardsdatascience.com/using-a-markov-chain-sentence-generator-in-python-to-generate-real-fake-news-e9c904e967e?source=collection_archive---------8-----------------------

Photo by rawpixel on Unsplash

实话实说:今天的新闻头条都很疯狂。如果他们关注唐纳德·特朗普,那他们就特别疯狂。有时疯狂到你会问自己它们是否真实!你所读到的是真实发生的事情,还是仅仅是随机收集的单词被做成新闻标题?
需要一个例子?

川普禁止朝鲜进口独角兽

很疯狂,对吧?当然,这个标题是基于女演员艾莉莎·米兰诺的小孩说的话。没有一个成年人会想出如此荒谬的事情…

“根据肖恩·斯派塞的说法,唐纳德·川普是“骑在彩虹之上的独角兽”

哦天啊。对我来说,这听起来像是由一个随机的句子生成器生成的。可惜事实并非如此,我想知道随机生成的新闻标题会有多疯狂(或者是否会如此)。所以我决定构建一个 Python 脚本,自己看看。

该脚本由一个快速的 web scraper 组成,可以获取尽可能多的新闻标题,并在马尔可夫模型句子生成器中使用它们来创建我自己的“真正的假新闻”标题。尽管 Python dictionary 数据类型看起来最初很适合马尔可夫模型,但我想为它使用数据框和熊猫。仅仅是因为我想练习一些熊猫的功能,在这种情况下,我最终对最“优雅”的方式不感兴趣,但我想快速得到结果,并在过程中学习一些东西。首先,我设置了一个脚本,该脚本使用关键字“Donald Trump”访问一个流行的新闻网站。然后,我分离出包含标题的文本,并将它们写入一个文本文件。我发现这个网站对设置我的小代码非常有帮助:

https://real python . com/python-web-scraping-practical-introduction/

在任何一天,这都会给我带来大约 100 到 120 条新闻标题。不错,但是当然这样做一次只能产生很少种类的单词,我的马尔可夫链有陷入一个独特的单词链的风险——在最坏的情况下——只是重复已经存在的新闻标题。谢天谢地,在 Windows 中设置一个任务调度程序很容易,它会每天在后台执行我的文件,让我的文本文件不断增长。我现在要做的就是耐心等待,直到积累了大量的头条新闻。大约一周半后,我有了 1000 多个头条新闻。我认为对于这样一个高度不科学和荒谬的项目来说,这已经足够了。在加载了我的文本文件,并做了一些粗略的清理,消除了一些重复出现的新闻出口签名和双标点符号等。,我终于可以开始把文本放进我的马尔可夫模型了。我决定使用一个单词的前缀或“引导”。我不想详细讨论马尔可夫链,但简单来说,我会总结如下:
对于每个单词,我们收集任何句子中的每个后续单词。基于一个跟随单词与其“对手”相比的频率,我们将分配一个单词跟随某个引导单词的可能性。然后,我们可以从文本中的整个单词列表中随机选择一个单词,然后根据我们指定的可能性随机选择句子中的下一个单词。我们将逐字逐句地创建一个新句子,它基于我们用作输入的文本的属性。真新闻进→真假新闻出。

在将文本文件分割成单个单词并将它们存储在变量‘words’中之后,我定义了一个包含三列的 pandas 数据帧:一列‘lead’定义了前导单词。对于每个引导词,都有一个“跟随”的词,并在我们的第二列‘follow’中被捕获。第三列- ‘freq’ -将显示我们可以在文本中观察到多少次“引导”和“跟随”的特定组合。我们将在这些列中填充什么?嗯,第一列很简单——简单地说,我们文本中的每个单词都将在这一列中写成一行。对于文本中每个索引为 i 的单词,接下来的单词就是索引为 i + 1 的单词。我们简单地从再次用我们的文本填充“follow”列开始,但是这次从文本中的第二个单词开始。对于最初 n 行的文本,这填充了 n-1 “跟随”字。我们文本中的最后一个单词没有自动的追随者,所以我们将使用一个合成的字符串变量来填补空白。我称之为“结束词”(请不要把它与总统在某个神秘的学徒磁带上说的类似的话混淆)。

import pandas as pd
dict_df = pd.DataFrame(columns = [‘lead’, ‘follow’, ‘freq’])
dict_df['lead']=words
follow = words[1:]
follow.append('EndWord')

在继续之前,我将创建一个单独的单词数组,包含每个句子的所有最后的单词。在我后面的代码中,我将使用这些结束词来“自然地”结束我随机生成的句子。这有一个很好的副作用,我不必担心我的马尔可夫链会“穿过”标题,这意味着一个标题的最后一个词不应该被认为是下一个标题的第一个词的线索。毕竟,我不是在处理一个连续的文本,而是在处理一个个独立的句子。通过在我的句子生成器到达这样一个end_word之后对我的句子进行删减,这不应该是一个问题。

end_words = []
for word in words:
    if word[-1] in ['.','!','?'] and word != '.':
        end_words.append(word)
print(end_words)

到目前为止一切顺利。现在,我统计引导词和跟随词的每个组合的出现次数,并使用 group_bytransform 将结果分配给 frequency 列。

dict_df['freq']= dict_df.groupby(by=['lead','follow'])['lead','follow'].transform('count').copy()

这些行仍然不是惟一的,所以在使用 Python 中的 pivot 功能创建一个大矩阵之前,我删除了重复的行,其中每个引导词作为行索引,每个跟随词作为列。然后,行 i 中的引导词和列 j 中的跟随词的组合的频率是该矩阵中的元素 a_ij

dict_df = dict_df.drop_duplicates()
pivot_df = dict_df.pivot(index = 'lead', columns= 'follow', values='freq')

对于每一行,我将所有的频率相加,并将行 i 中的每个元素除以行 i 的总和。这导致百分比总和为 1,当我的句子生成器为某个引导词选择跟随词时,它将用作概率分布。例如,如果在单词“fake”之后,我们观察到 7 次随后的单词“news”和 3 次单词“tan ”,则最终被选择的概率将分别是 0.7 和 0.3。

sum_words = pivot_df.sum(axis=1)
pivot_df = pivot_df.apply(lambda x: x/sum_words)

有了这些,我就可以为句子生成器定义我的函数了。我用一个起始词来初始化句子生成器。这个单词可以是从所有单词的集合中随机选择的单词。但由于我的文本只包含唐纳德·特朗普的标题,我认为确保他的名字也出现在我们的假新闻标题中是有意义的。因此,在我的例子中,我从“唐纳德”开始。从这个单词开始,生成器根据我们设置的概率矩阵选择一个后续单词。它将继续使用所选的跟随单词作为新的引导单词,一个单词接一个单词地添加到我们的句子中。如果句子生成器找到了我们的结束词数组中的一个词,句子将把这个词作为最后一个词并返回我们的句子。如果生成器到达我们之前定义的合成“EndWord ”,它将简单地为引导我们走上这条死胡同的引导词绘制一个新的跟随词。如果我们看到一个结束词,而我们的句子只有两个词长,这同样适用(我有几个例句,上面只有“唐纳德·特朗普”。。就像《唐纳德·特朗普》里那样。—努夫说)。

from numpy.random import choice
def make_a_sentence(start):
    word= start
    sentence=[word]
    while len(sentence) < 30:
        next_word = choice(a = list(pivot_df.columns), p = (pivot_df.iloc[pivot_df.index ==word].fillna(0).values)[0])
        if next_word == 'EndWord':
                continue
        elif next_word in end_words:
            if len(sentence) > 2:    
                sentence.append(next_word)
                break
            else :
                continue
        else :
            sentence.append(next_word)
        word=next_word
    sentence = ' '.join(sentence)
    return sentence
sentence = make_a_sentence('Donald')

仅此而已。

我肯定不会用这段代码赢得(特朗普主持的)选美比赛,但它快速、肮脏、Python-noob 友好,并且完成了工作。诚然,文本越大,分配概率的整个过程将变得越慢,但对于我的示例,它仍然只花了几秒钟,所以我认为还没有必要进行耗时的优化。让我们来看看一些“真正的假新闻”的标题:

唐纳德·特朗普批评特朗普痴迷星战燃烧。 -(听起来似乎有理)

唐纳德·特朗普打破了真正的唐纳德·特朗普忠诚度测试。——(如果发生那种事该有多酷?)

唐纳德·特朗普的团队投诉白人。——(耶…大概不会)

唐纳德胜过最会吹牛的人。 ——【他最差也是)

唐纳德·特朗普的助手们觉得他今年秋天会当选总统。 ——(我们都做……我们都做)

唐纳德·特朗普、罗莎和其他个人,包括第 45 任总统是造币厂的青年。 -(新鲜?)

唐纳德·特朗普,你到此为止。 ——(对我的口味来说可能有点太远)

当然这些都是一些成功的例子。很多句子出来绝对是胡言乱语(不值得 covfefe,但仍然是胡言乱语):

唐纳德·特朗普知道谁是阿撒·富兰克林为尤塔工作的前助手罗莎·马尼高尔特·纽曼。 -(???)

那么,我们从这件事中学到了什么?你作为一个读者,可能不多。但是我对我的代码感到很开心,并且开始用一种我通常不会遇到的结构来处理数据。如果您有反馈或建议,请随时联系我们。谢谢!

附言:

如果你想要一个更复杂的特朗普马尔可夫链,看看这个由更聪明的人制作的随机特朗普推特生成器:

https://filiph.github.io/markov/

使用人工智能转录从你已经给出的演示文稿中创建博客文章

原文:https://towardsdatascience.com/using-ai-transcription-to-build-blog-posts-form-the-presentations-you-already-give-a4cf9faf9aef?source=collection_archive---------25-----------------------

在我作为技术顾问的工作中,我最终要向我的公司 Pariveda 的客户、合作伙伴和其他人做很多介绍。我一直在努力寻找更有效地传播知识的方法。科技让这变得容易多了。有了现代的会议软件,你可以很容易地记录你正在向别人演示的东西。在过去的一年左右,我一直采取“记录一切”的方法。如果录音很糟糕,或者我说了不该说的话,我可以删除录音,但如果录音很棒,我可以用它来分享 PowerPoint 演示文稿无法捕捉的深度。

在今年 AWS re:invent 的筹备阶段,我花了很多时间与客户一起工作,帮助他们计划他们的一周,使用我整理的快速卡片来记录我的提示&技巧。我在网上搜索,看看是否还有人提供同样的建议,结果一无所获。我觉得这是一个写博客来填补空白的好机会。然而,我是一个非常慢的作家,所以我不想从零开始。

AI 来救援了!随着 AWS 的最新进展,我可以在几分钟内获得录制的演示文稿的转录,并且只需支付1 美元即可获得 40 多分钟的转录(在免费的 60 分钟/月之后)。我一直在想如何应用人工智能来帮助我提高效率,所以我采用了以下流程来构建这个帖子:

  1. 制作一个演示文稿,亲自进行演示
  2. 录制演示文稿(即使用网络会议软件或手机)
  3. 使用人工智能转录工具,如亚马逊转录从画外音获取文本
  4. 将文本复制到博客*台,添加幻灯片中的图像,并调整语气,使其看起来像一篇博客文章

4 steps to build a blog post from what you’re already presenting

使用这种方法,我能够在大约一个小时内完成一篇 1300 字的中型文章。在这篇文章中,我将向你介绍我使用的过程,并讨论一些我认为可以使用的其他方法。让我们开始吧…

第一步:制作一份精彩的演示文稿,

在这种情况下,我在当天早些时候向 Pariveda 的观众演示了最大化 re:invent,演示被录制下来,以便其他人可以在以后观看。我确信几乎每个阅读这篇文章的人都做了很棒的演讲,所以我把这部分留给你。你不一定需要幻灯片演示,白板会议或只是一个讲座就可以了。

第二步:向某人演示,并记录演示过程

有很多方法可以记录你这些天说的话。如果您正在演示幻灯片,您可以使用公司的软件轻松启动网络会议,并以这种方式录制音频和幻灯片。Pariveda 使用 zoom 进行网络会议(旁白:Zoom 是高质量视频会议的一个很好的工具),所以我使用 Zoom 来获得这个记录。如果你只是想要音频,你可以使用 iOS 上的内置语音备忘录应用程序或 Android 上的 Google Keep 来录制音频。关键是要获得音频记录文件,这样你就可以转录它,使你的职位。

Recording of the presentation video from Zoom

步骤 3:使用人工智能转录演示文稿

所有三大云供应商都提供人工智能转录服务( AWS 、微软、谷歌),许多其他供应商也是如此。在这种情况下,我正在为 AWS re:invent 做一个帖子,所以使用 AWS Transcribe 才有意义。为了使用这项服务,我首先将录音上传到 S3。接下来,我创建了一个指向该文件的新转录作业(您可以在控制台中完成)。

Creating a new Transcription Job

这将创建一个需要几分钟运行的作业。

Job completes after a few minutes

当作业完成时,您将能够找到并下载输出文本。在这种情况下,它运行了大约 6 分钟,并将结果文件放入我们的 S3 桶中。

{
    "TranscriptionJob": {
        ...,
        "Transcript": {
            **"TranscriptFileUri": "**[**https://s3.amazonaws.com/transcriptions-pariveda-chicago/Transcribe-reInvent-guide.json**](https://s3.amazonaws.com/transcriptions-pariveda-chicago/Transcribe-reInvent-guide.json)**"**
        },
        "CreationTime": "2018-11-14T20:35:20.418Z",
        "CompletionTime": "2018-11-14T20:41:02.633Z",
        "Settings": {
            "ChannelIdentification": false
        }
    }
}

当您下载 JSON 时,它会在一个名为“抄本”的字段中提供实际文本,该字段可用于从音频中捕获原始文本。

{
  "jobName": "Transcribe-reInvent-guide",
  "accountId": "336843223770",
  "results": {
    "transcripts": [
      {
        "transcript": "Sure. All right, so the biggest thing that i found last year reinvent was because **he's** grown so big..."
      }
    ],
    "items": [
      {
        "start_time": "1.954",
        "end_time": "2.304",
        "alternatives": [
          {
            "confidence": "0.5040",
            "content": "Sure"
          }
        ]
...

在浏览文档的过程中,您可能会发现一些特定的错误,这些错误基于您的讲话模式是非常常见的。我喜欢将内容复制到文本编辑器中,使用查找-替换来纠正单词,而不是那些人工智能一贯误认为这些单词的单词。此外,您还可以在此时向文本中添加段落。这也是更新你的自定义词汇的好机会。

另一个旁注:通过这个过程我学到的一件事是,我在我的谈话中经常使用“所以”这个词。我现在正在努力减少这种使用。

步骤 4:将文本复制到博客*台,添加幻灯片中的图像,并调整语气,使其看起来像一篇博客文章

现在您已经有了文本形式的演示文稿的编辑版本。你所需要做的就是添加一些图片,使帖子更有趣,并调整流程,使其感觉更像是书面的而不是口头的。这花了我大约一个小时,但这是我第一次经历这个过程。我希望接下来的几个会花更少的时间。

如果你有兴趣分享如何加快将有思想的内容发布到网上的技巧,请直接联系我或在评论中联系我。

利用数字实验数据进行方差分析

原文:https://towardsdatascience.com/using-analysis-of-variance-with-experimentation-data-40142980d5d8?source=collection_archive---------18-----------------------

单向方差分析(ANOVA)用于确定两个或两个以上独立(不相关)组的均值之间是否存在任何统计上的显著差异(尽管你倾向于只在至少有三个而不是两个组时使用)。

从以前的学者生涯进入数字分析领域——学习了生物力学和统计学——我有很多问题,关于我以前学到的统计技术如何融入我的“日常工作”。鉴于 Optimizely 的统计引擎使用连续的 AB 测试方法来比较两个或更多独立组的*均值,没有理由(只要流量允许)不能对分段数据执行方差分析(ANOVA ),以检测人口统计数据、设备、*台或区域数据之间的统计差异。

为此,本文将既是对这些方法的探索性报告,也是如何执行这种分析的逐步说明,前提是您已经与 AB 供应商建立了分析集成。

首先,确保你的分析集成正确地标记了然而你的流量是通过你的实验供应商节流。通过这种方式,您将能够拥有一个初始段,该段根据实验条件(即您正在执行分析的变化)来分离您的数据。确保您正确实施了标记,也意味着您可以跟踪您的指标。这对于 ANOVA 如何收集和组织数据至关重要。数据将处于浏览器级别(每个用户的单独数据点),但出于本指南的目的,我将数据导出显示为未折叠,因此您可以看到我将测试的组。为了这个分析的目的,我将着眼于我的一个实验组/变体的设备/*台比较;我们就叫它AAT7:

当这些数据折叠起来时,您可以看到各个浏览器和各种指标的性能。出于本指南的目的,我已经忽略了各个浏览器 ID。我不太擅长用颜料,所以我用山谬·里维的《突破点》把它们抹掉了:

在本文中,我将使用我们的每个浏览器的内容条目指标。通过进行 ANOVA,将计算该指标的*均值,因此对于我们的 AA 条件,我们将得到每个设备/*台的每个浏览器的*均内容项。这将告诉我们,对于该实验条件,每个设备/*台之间是否存在统计上的显著差异;这可以提供关于设备如何针对这种特定的 web 变化而执行的更加精细的统计分析。然后,您需要从您的分析工具执行数据下载,删除浏览器 ID(现在不需要 Keanu)和任何不感兴趣的指标。对于这种形式的分析,我将使用 R, so import your。csv 或。xlsx 到您的 R 环境中:

我们现在将执行单向 ANOVA,从而在实验组(设备/*台)之间比较相同的指标(每个浏览器的内容项目))。在 RStudio 中,你需要安装“stats”包。在某些时候,您可能希望开发一些脚本来自动处理数据,但对于本指南,您可以使用以下语法来执行单向方差分析:

您会希望将其分配给 R 中的一个新项目,这意味着您可以执行汇总分析以及可视化和事后程序:

对您的新项目调用 summary 将会得到以下输出:

您可以看到 R 为您提供了重要的代码,因此您可以分析 ANOVA 的总体效果。在这种情况下,我们寻找一个小于 0.05 的 p 值来检测统计上显著的影响。正如所见,我们在这个实验中的 p 值小于 0.001,这意味着我们在这个方差分析中有一个非常显著的 p 值。因此,我们可以自信地得出结论,在这个实验条件下,设备/*台类型和每个浏览器的内容项之间存在显著差异。确定统计分析如何帮助您对细分市场进行更精细的分析。

然而,这种整体输出并没有告诉我们显著差异在哪里,因此我们可以执行 Tukey 多重成对比较(事后分析),这是一种可以识别差异存在的工具。其语法和输出应该如下所示:

从上面的输出可以看出,对于我们的 AA 变量( p < 0.05),移动设备的表现明显比*板电脑和电脑差。这为我们提供了关于该实验条件下这些设备/*台之间的统计差异的宝贵信息。由此我们可以得出 UX 对这种变化的考虑;这可能是因为 AA 在移动设备上存在可用性或功能性问题(例如,它无法正确适应屏幕,它可能会在页面上移动项目)。这种分析意味着您可以将结果提供给利益相关者,他们随后可以执行后续的 web 分析,以评估移动设备性能如此之差的原因。

我很快在 ggplot 中绘制了一个图(请安装 ggplot2 来执行这个分析),只是为了描绘出这些数据绘制时的视觉效果。使用 stat_compare_means ,您可以将方法设置为“anova ”,这将在您的图上显示您的 p 值:

我知道上面的图显示了一些明显的统计异常值,我们将来可能会忽略这些异常值;但我只是想从视觉角度展示数据可能是什么样子——正如您可以看到的,移动设备的性能明显比其他设备差。我将在不久的将来发表一篇关于数据清理的文章。类似地,在执行方差分析之前,您还将调查您的数据的分布——这将是我将来与大家分享的另一篇文章。我要强调的是,这只是一个基本的一步一步的方法,你可以通过数字数据下载对你的细分市场进行统计分析。本文中讨论的方法可以帮助您更客观地描述不同变化下的细分市场表现,而不是单独呈现趋势和提升。

我期待每个人对这份报告的建设性反馈。我期待在不久的将来,随着更多 90 年代动作片英雄的出现,浏览器 id 将会消失。

使用分析进行更好的决策

原文:https://towardsdatascience.com/using-analytics-for-better-decision-making-ce4f92c4a025?source=collection_archive---------1-----------------------

日益复杂的世界、数据的大规模扩散以及保持竞争前沿的迫切愿望促使组织关注使用分析来推动战略业务决策。商业分析使经理们能够了解他们业务的动态,预测市场变化和管理风险。在维护库存、定价解决方案或招聘人才时,公司不再“凭直觉”,而是采用分析和系统的统计推理来做出提高效率、风险管理和利润的决策。

数据和分析正在破坏现有的商业模式和生态系统。新数据集的激增和大规模数据迁移功能的引入正在破坏现有的信息和技术孤岛。从使用粒度数据来个性化产品和服务,到扩展数字*台来匹配买家和卖家,公司正在使用业务分析来实现更快和基于事实的决策。事实上,研究表明,数据驱动的组织不仅可以做出更好的战略决策,还可以获得更高的运营效率、更高的客户满意度以及强劲的利润和收入水*。最*的研究还表明,以数据为中心的组织获得客户的可能性增加了 23 倍,保留这些客户的可能性增加了 6 倍,盈利的可能性增加了 19 倍。

今天的分析从业者拥有大量的分析能力和技术。这些技术包括最基本的技术,“描述性分析”,涉及为后续分析准备数据,到“预测性分析”,提供先进的模型来预测和预测未来,到顶级的分析,称为“规定性分析”,利用基于机器的学习算法和动态规则引擎来提供解释和建议。凭借其多样化的使用案例和应用,这些技术现在在组织层面上进入客户、劳动力、供应链、财务和风险战略已不再令人惊讶。

数据是新的石油,公司获取和理解数据的最佳方式是数字化他们的流程。数字化客户互动可以提供大量信息,公司可以将这些信息反馈到战略、销售、营销和产品开发中。详细和精细的数据可以使公司微定位他们的客户,并个性化他们的产品和服务。进一步的内部数字化生成了管理人员可以用来改善其运营的数据,包括路线和运输、资源分配和调度、产能规划和制造。这些趋势也导致许多公司在预测和高级分析的共同基础上融合他们的“商业智能”和“运营研究”部门。这两个团体现在都在使用统计和数学技术来解决战略性的商业问题,并使决策系统化。

数据分析凭借其深远的使用案例和多样化的应用,正在成为战略业务决策的基石。从帮助企业做出面向消费者的营销决策,到帮助他们解决关键的运营效率低下问题,分析正在从根本上改变人们对数据重要性的认识。先进的统计模型通过从非常规数据集提供有价值的见解,并使公司能够探索新的业务领域,进一步推动了这一事业。接下来的几个部分将探讨数据和分析给当今企业带来的巨大而多样的机遇。

充分利用消费模式:

在一个日益以客户为导向的时代,组织积累了大量的消费者信息和数据。为了保持竞争力,组织必须利用这些消费者洞察来塑造他们的产品、解决方案和购买体验。麦肯锡(Mckinsey)的研究表明,战略性地利用消费者行为洞察的组织,其销售增长利润率比同行高出 85%,毛利润高出 25%以上。因此,对管理者来说,考虑消费者信息的战略重要性是很重要的。

通过深思熟虑的市场细分对客户进行全面而精细的了解,可以为经理提供关于购买习惯和偏好的深刻见解。例如,一家电信公司可以使用先进的预测分析模型来减少客户流失并衡量营销活动的有效性。类似地,在线零售商可以通过寻找新老访问者的组合、跳出率和*均会话持续时间等问题的答案来了解其网络存在。这些问题提供了重要的见解,让我们了解什么类型的内容、通过什么渠道和形式可能对关键的消费群体产生最大的影响。

此外,模式数据还可以生成有价值的客户洞察,用于指导营销支出。例如,一家汽车销售商研究了其消费者的购买和行为历史,发现其大部分高端消费者更有可能依赖经销商分销商的产品推荐,而不太可能受贸易展览和营销宣传材料的影响。这反过来帮助营销人员重新分配预算。因此,商业分析使管理者能够获得关于市场条件的竞争情报,更成功地锁定消费者并优化流程。

利用数据推动绩效:

虽然组织花费大量时间分析消费者数据和一线盈利机会,但同样重要的是专注于提高生产力和绩效。数据和分析在降低效率和简化业务运营方面可以发挥巨大作用。例如,报告和分析仪表板可以识别数据相关性,并为经理提供详细的见解,以执行成本评估、同行基准和定价细分。同样,使用分析来衡量卓越运营、产品创新和劳动力规划等领域的关键绩效指标,可以产生经过计算的见解,以解决复杂的业务场景。

商业分析还可以改善组织吸引、保留和发展人才的方式。例如,亚洲的一家咨询集团最*决定进行重大重组。作为该计划的一部分,领导层希望确定具有高度成功潜力的员工,并更好地了解关键绩效指标。分析团队首先简化数据点,如职业历史、教育背景、绩效、年龄、婚姻状况和人口统计数据。在通过多元回归模型运行整理后的数据后,团队能够确定在特定角色中最有机会成功的员工档案。研究和分析还提出了对公司整体增长影响最大的关键角色。因此,公司围绕关键职能角色和人才群体进行了重组。

数据分析提供独特价值主张的另一个领域是供应链。供应链是寻找战略机会和优势的好地方,部分是因为它们错综复杂的性质,部分是因为它们对公司成本结构的重大贡献。通过使用分析,公司不仅可以识别现有结构中隐藏的低效率,以实现更大的成本节约,还可以通过执行风险建模和评估来分析重要的供应链投资和决策。然后,管理人员可以深入研究具体的改进机会,如库存管理、渠道管理、采购和物流。

通过分析管理风险:

如今,组织面临着来自结构化数据(如数据库)和非结构化数据(如网站、博客和社交媒体渠道)的巨大风险。通过利用风险分析,公司可以更好地量化、衡量和预测风险。管理人员需要将风险分析视为一种企业范围的方法,并应开发将不同组织级别和职能的数据整合到一个中央*台的方法。通过建立衡量和管理风险的标准基线,公司将能够将风险考虑纳入其核心战略决策过程,并预测可能的情况。

银行正在通过发现利用交易和行为消费者数据的新方法来引领这一分析领域。事实上,他们通常会超越传统的结构化信息,如信用评分报告,并且还会寻找非常规的信息来源,如会员卡消费者数据和政府信息。通过获取如此庞大的数据集,银行能够提高其信贷风险模型的准确性、覆盖范围和可预测性。从在执行前识别高风险付款到预测客户拖欠抵押贷款付款的可能性,风险模型通过提供先进和有价值的见解而处于领先地位。因此,公司应该专注于增强和探索运营商业模式。

高级数据模型将使有风险的业务决策更加统一,提高数据质量,并提供更大的灵活性来满足非常规的数据需求。通过提高风险意识,管理者将更善于应对不确定性,并更善于战略性地做出决策。

结论:

在这种由数据驱动的动荡环境中,业务经理需要同时透过两个镜头来看问题。首先,他们必须识别高风险和有回报的机会,如进入新的市场和改变现有的商业模式。其次,他们必须继续关注将分析纳入其核心业务决策流程。通过将数据分析嵌入其核心战略,业务经理可以简化内部业务流程,识别消费者趋势,解释和监控新出现的风险,并建立持续反馈和改进的机制。推动分析转型将因此使公司获得竞争优势,并站在数字颠覆的最前沿。

参考资料:

  1. 分析时代:在数据驱动的世界中竞争
  2. 捕捉数字消费者
  3. 风险分析三分钟指南
  4. 数据分析和劳动力战略对绩效改善和税收效率的新见解
  5. People analytics 揭示了人力资源可能犯的三个错误
  6. 从您的客户数据中获取价值

使用 API 和 Google Sheets 评估梦幻英超的前景

原文:https://towardsdatascience.com/using-apis-google-sheets-to-assess-fantasy-premier-league-prospects-1a2598c4b25e?source=collection_archive---------0-----------------------

我是一名狂热的 FPL 球员,使用梦幻英超的 API 和 Google Sheets 来轻松分析球员数据。

你可能会因为不得不依赖他人的零星数据(例如,进入梦幻英超 Reddit )而感到沮丧,并想要做自己的分析。

使用 Fantasy Premier League API 和一个电子表格工具,我们可以将球员数据加载到 Google Sheet 中,并过滤不同的选秀权、总得分、每场比赛的得分等等。

电子表格的伟大之处在于,几乎每个人都知道如何在某种程度上使用它们,而且通过对 Google Sheets 进行一些非常小的修改,就可以很容易地使用 Google Sheets 的 API,所以如果你不是技术人员,这不是问题。

在这之后的下一步将是真正地将数据加载到像 Tableau Public 这样的工具中以评估数据,但现在我们只想得到数据并开始使用它。如果对 Tableau 公共教程有足够的需求,我也会写的,所以如果你想看的话,请鼓掌或者回应。

设置 Google 工作表

我们要做的第一件事是在谷歌工作表中设置一个新的工作表。重要的是使用 Google Sheets 而不是 Excel 之类的东西,因为 Google Sheets 是可脚本化的,通常更擅长处理与互联网交互的东西,如 API。Excel 并不是真正为一个必须与互联网对话的世界而设计的。

我在这里使用了几个技术术语,因此,对于外行来说,API 是从数据库访问数据的常用方法(我们将使用的 API 被 FPL 用来生成他们的球员信息屏幕), JSON 是输出这些数据的标准格式。技术专家喜欢 JSON,因为它受到许多不同*台的支持,它有简单的标记,格式化后很容易阅读和查询。

但是 Google Sheets 不支持现成的 API 或 JSON,所以我们需要添加一个脚本,该脚本可以获取 API URL (Fantasy Premier League 的数据提要)并以 JSON 格式返回我们想要的数据,然后将其格式化为我们可以阅读的电子表格。

做到这一点真的很容易。

转到工具>脚本编辑器

然后,您应该会看到这样的屏幕:

首先,您希望删除 Code.gs 文件中的所有内容,因此它是空白的:

接下来,我们将重命名该文件:

我们将把它命名为“ImportJSON”

您的屏幕现在应该看起来像这样:

接下来,转到这个 pastebin,将所有内容复制到那里,并粘贴到 ImportJSON 文件中。屏幕现在应该看起来像这样:

我们已经完成了这里的工作,是时候回到我们的 Google 工作表并加载数据了。点击文件>保存保存我们的功能。

我们刚才所做的实际上是向这个 Google Sheet 添加一个名为 ImportJSON 的新函数,我们现在就要使用它。

返回到您的电子表格,它应该在另一个选项卡中打开。

使用 ImportJSON 提取梦幻英超 API 数据

现在,我们将使用刚刚创建的函数从梦幻英超 API 中提取数据。

在电子表格中,将此公式复制到单元格 A1:

= ImportJSON("【https://fantasy.premierleague.com/drf/bootstrap-static】T2")

重要提示:在敲 enter 之前,复制最后一个引号(在 bootstrap-static 之后),替换掉 https:// 之前的花引号,否则会出错。Medium 自动将引号转换为花引号,Google Sheets 无法识别。

注意:这个 API 没有被 FPL 官方记录或以任何方式支持,并且它会随着 FPL 网站的更新而不断变化。然而,这个特殊的 API 端点在过去的几个赛季中工作得很好,所以希望这个继续工作。如果我发现它坏了,我会进来更新这个帖子。

修改后的公式应该如下所示:

你会知道它起作用了,因为配方已经变绿了。然后你应该按回车键。如果你看到的不是上面的内容(比如公式后面的引号),Google Sheets 已经破坏了这个公式,你应该再次粘贴这个公式。

然后,电子表格应该在第一个单元格中显示“正在加载”。不要担心当你悬停在上面时它会显示错误,Google Sheets 只是有一个想法:

如果一切正常,数据应该已经加载到您的电子表格中,并按照每个玩家的数字 ID 进行排序。每个球员在整个赛季中都持有自己的 ID,这对于与其他数据源进行交叉引用非常有用,所以我不会删除“元素 ID”字段。

Google Sheets / Excel 中的数据分析

我们就快成功了,但是在我们开始分析数据之前,还有几个重要的步骤要做。

我们需要做的第一件事是将这些数据复制到一个静态电子表格中。尽管 ImportJSON 非常擅长从 API 中提取数据,但它往往在排序和过滤数据方面有问题。

ImportJSON 还有一个令人讨厌的倾向,那就是不断尝试刷新数据,这使得处理起来很麻烦,并且很快就会达到 API 的极限。使用静态文档更容易(也更快),因为它不会不断地试图下拉数据。

旁白:不过,有帮助的是,你可以在每个游戏周之后回到谷歌电子表格(把这个放在你的谷歌硬盘里),它会提取最新的数据。我不建议在比赛周进行的时候这么做,因为我们都知道 FPL 在比赛周进行的时候似乎有问题。

不过,获得静态工作表的最简单方法是简单地将数据下载为 Excel 电子表格。这样,您就可以利用 Excel 的优势——处理相对大量的数据而不会出现延迟。

如果您确实想使用 Google Sheets 中的数据,您可以随时将数据导入到 Google Sheets 中,就像我在这里所做的那样。

您将会看到单元格 A1 现在是#NAME,因为这个新的电子表格不知道“=ImportJSON”是什么(保存时函数不会被转移)。请随意将该字段更改为 ID。

字段标题应该是不言自明的(包括一些看起来非常有趣的标题),一旦你进入静态电子表格,你可以随意修改。

您的第一步应该是设置一些过滤器:

  • 按每场比赛的点数排序(AJ 列)
  • 将列 AJ 转换为数字列(格式>数字),并过滤掉小于 4 的行。
  • 将“元素选择方式”转换为数字列(“格式”>“数字”),并过滤到 15%以下(如果您正在寻找差异)。

你也可以在不同的栏目中进行计算来制定你自己的标准,设置条件格式来突出显示符合特定条件的绿色玩家,或者过滤列表来匹配你在 FPL 的观察列表。

除了 Excel/Google Sheets,下一步将是使用 Tableau 之类的工具来绘制数据图表。这方面的一些高级示例如下:

  • 梦幻英超数据分析
  • FPL 球员表现与成本对比图

就是这样。现在你有数据知道是否真的值得在卡尔弗特-勒温身上下注,或者是否真的值得在阿圭罗身上花额外的钱而不是耶稣。

现在去看看剩下的列,过滤/排序到你的心满意足。即使您没有在 Tableau 中创建图表,这也会给您一些数据,帮助您研究您的选择。

使用 Bagging 和 Boosting 提高分类树的准确性

原文:https://towardsdatascience.com/using-bagging-and-boosting-to-improve-classification-tree-accuracy-6d3bb6c95e5b?source=collection_archive---------1-----------------------

Bagging 和 boosting 是两种可以用来提高分类回归树(CART)准确性的技术。在这篇文章中,我将从我在早期文章中开发的单个 90+点葡萄酒分类树开始,并将其分类精度与两个新的袋装和提升算法进行比较。

因为打包和提升都依赖于分类器的集合,所以它们被称为“集成”方法。这两种分类器本身都不是一种分类器,而是通过聚合其他几个子分类器的预测来产生分类预测。

我将再次使用从《葡萄酒爱好者》杂志上搜集的葡萄酒评论数据,该杂志可在 https://www.kaggle.com/zynicide/wine-reviews 的免费获得。它包含了 150,000 种葡萄酒的分数,以及每瓶葡萄酒的价格、酒厂、产区、品种&等信息。对于这个项目,我将只使用美国种植的葡萄酒。

首先,我将使用 sci-kit learn 的 DecisionTreeClassifier 对我的 70%的数据(训练样本)训练一个单一的分类树,无需超参数调整。这将作为未来合奏表演的基准:

制袋材料

Bagging 使用了一种简单的方法,这种方法在统计分析中反复出现——通过合并多个估计值来改进一个估计值。Bagging 使用训练数据的引导抽样构建 n 个分类树,然后组合它们的预测以产生最终的元预测。

Sci-kit learn 实现的 bagging ensemble 是 BaggingClassifier,它接受一个基础分类器的名称作为输入,bagging ensemble 将复制该分类器 n 次。BaggingClassifier 的主要调整超参数是在元预测中创建和聚合的基本分类器的数量。

以下是 bagging 系综在改变(1)基本估计量的数量和(2)基本估计量的大小(叶子的数量)时的表现:

如上所示,bagging 预测精度对基础估计量的限制很敏感。在实践中,限制基估计量的大小在 bagging 系综中是多余的,因为 bootstrap 抽样获得了与限制基树相似的结果。

另一个关键的观察是,bagging 集成的性能不会超过单一 CART 基准,直到估计器的数量超过阈值水*。单树装袋集成的准确性比单个 CART 差很多——如果你问这是怎么回事,可以用 bootstrap 采样来解释:由于 bootstrap,单树装袋集成中的基本估计器不会使用 100%的训练数据。Bootstrap 采样是一种可调参数的 bagging 分类器。

助推

为了展示 boosting 方法的功效,我将使用 AdaBoost,它在 sci-kit learn 中实现为 AdaBoostClassifier。这种类型的集成创建了 n 个基本估计量,就像 bagging 一样,但它是以迭代的方式实现的,如下所示:

  1. 使用正常方法训练基于估计值#1
  2. 观察基础估计器#1 错误预测的训练数据样本,并为这些样本创建权重 D>1.0
  3. 训练基础估计量#2,在计算同质性基尼/熵度量时将权重 D 应用于样本
  4. 重复 n 次。

通过这种方式,增强创建了连续的基本分类器,这些基本分类器被告知对来自训练数据的误分类样本给予更大的重视。像 bagging 一样,来自所有提升基本分类器的结果被聚集以产生元预测。

与 bagging 相比,boosting 集成的精度随着基估计量的增加而迅速提高。此外,在我的示例中,无论基础估计器是终止的树桩还是完整的树,提升集成的精度都收敛到超过估计器数量= 15+时的原始 CART 精度。

Boosting 和 bagging 是两种能够从分类算法中挤出额外预测准确性的集成方法。使用任一方法时,应仔细调整超参数,以找到模型灵活性、效率和预测改进的最佳*衡。

[## dasotelo/Wine_Bag_Boost.py

github.com](https://github.com/dasotelo/Python_Projects/blob/master/Wine_Bag_Boost.py)

将 Bash 用于数据管道

原文:https://towardsdatascience.com/using-bash-for-data-pipelines-cf05af6ded6f?source=collection_archive---------12-----------------------

作为一名数据科学家,使用 bash 脚本创建数据管道非常有用。这些脚本的可能性几乎是无限的,但是在这里,我将通过一个非常基本的 bash 脚本来下载数据并计算数据集中的行数和列数。

一旦你掌握了使用 bash 脚本的诀窍,你就可以拥有创建物联网设备的基础,以及更多,因为这一切都与 Raspberry Pi 一起工作。有一个很酷的项目,你可以用它来使用 twitter api 下载你所有的 twitter 消息,然后预测 twitter 上某个用户的消息是否是垃圾消息。它可以在你房间的树莓 Pi 服务器上运行!不过这有点超出了本教程的范围,所以我们将从查看旧金山的 汽车速度数据集开始!

此外,获取实时数据的能力、复制结果的能力对于数据科学来说是非常必要的。在本教程中,我将向您展示如何使用 bash 和 Unix 命令创建数据管道,然后您可以作为数据科学家在工作中使用这些命令

先决条件

  1. 熟悉命令行(知道如何创建目录、更改目录和创建新文件)
  2. Linux 或苹果电脑
  3. 互联网连接

目标:创建一个 bash 脚本来完成以下任务

  • 从在线资源下载数据
  • 计算数据中的行数
  • 记录数据中列的名称
  • 遍历多个文件并给出所有这些信息

第 1 部分:下载数据文件

对于本教程的第一部分,假设我们正在使用 旧金山限速数据 ,我们想通过命令行创建我们的整个管道。我们需要开始为这个作品创建一个文件夹,我称之为cars_pipeline

要在 Unix 中做到这一点,您需要在命令行上执行以下命令:

  • 制作目录

mkdir cars_pipeline

  • 搬进新主任

cd cars_pipeline

一旦我们进入这里,我们将创建一个新的 bash 脚本,我称之为:download_data.sh你可以随意命名,只要它以扩展名.sh结尾

  • 创建文件的命令是:

touch download_data.sh

现在我们已经创建了这个文件,我们将把数据下载到我们正在工作的文件夹中。为此,我们将使用名为 nano 的文本编辑器。

  • 为了在 nano 中打开我们的文件,我们在命令行中执行以下命令:

nano download_data.sh

一旦打开它,您将通过粘贴以下代码来创建您的第一个 bash 脚本:

  • 除了 #,带#的文本都是注释!/bin/bash ,它被称为 shebang ,是每个 bash 脚本所必需的
#!/bin/bash # Command below is to download the data
curl -o speed.csv https://data.sfgov.org/api/views/wytw-dqq4/rows.csv?accessType=DOWNLOAD

要保存:

  • 控制+ o
  • 进入
  • 控制+ x

现在我们已经保存了文件,让我们来看看这个用来下载数据的大命令:

curl -o speed.csv https://data.sfgov.org/api/views/wytw-dqq4/rows.csv?accessType=DOWNLOAD

  • curl是下载命令
  • -o是输出的 a 标志
  • speed.csv是输出名称
  • [https://data.sfgov.org/api/views/wytw-dqq4/rows.csv?accessType=DOWNLOAD](https://data.sfgov.org/api/views/wytw-dqq4/rows.csv?accessType=DOWNLOADis)是下载数据的网址

现在,要下载,我们只需在终端中使用以下命令运行 bash 脚本:

bash download_data.sh

如果您现在查看该文件夹,您将看到您已经下载了文件 cars.csv!

如果您对此有任何疑问,请询问,您可以随时通过替换 url 来下载不同的文件。同样,您可以向脚本传递一个命令行参数,这样您就可以使用该脚本下载您想要的任何数据。

这个脚本非常简单,所以让我们转到一个稍微难一点的脚本,它会告诉我们数据集中的行数和列数。

第 2 部分:为所需信息解析文件

在这里,我们将创建一个更复杂的脚本,这将更深入。我将仔细检查每一行,解释它是做什么的,然后在最后把它们作为一个脚本放在一起。

我将第二个脚本命名为:process_data.sh,您可以随意命名,只要它以扩展名.sh结尾。

您将使用与上面相同的过程来编辑和保存您的 bash 脚本。您可以跟随文章,或者向下滚动并使用 nano 复制整个脚本。

第一行:shebang

  • 在计算中,a shebang 是由字符数字符号和感叹号 (#!)在一个脚本的开头。

#!/bin/bash

我们将把文件名作为命令行参数传入,并用我们的结果保存一个文本文件。因此,我们将使用一个名为echo的命令,它打印出跟随其后的值。为了访问参数,我们将列举它们,第一个是$1,第二个是$2,依此类推…

我们希望它保存文件的名称,因此我们将使用命令:

echo "The name of the file is:" $1

现在,我们将使用以下命令来计算 csv 中的行数:

lines=$(wc -l < $1)echo "The file has" $lines "lines"
  • 我们创建了变量 lines 来计算我们作为命令行参数传入的文件中的行数!更多关于 wc 命令 的信息,请点击
  • 然后我们打印出文件的行数!

接下来,我们将从 csv 文件中获取列名!为此,我们将在 bash 脚本中使用以下命令。

colnames=$(head -n 1 < $1)

这将创建一个变量,其中只包含 csv 的第一行!将所有这些放在一起(以及我添加的一些内容,以便日期自动填充到文本文件中),我们得到以下脚本:

#!/bin/bashecho "Data Processed by Elliott Saslow"DATE=`date +%Y-%m-%d`echo "Date is: "$DATEecho ""echo "The name of the file is:" $1echo ""lines=$(wc -l < $1)echo ""echo "The file has" $lines "lines"echo ""colnames=$(head -n 1 < $1)echo ""echo "Column names are: "echo ""echo $colnames

现在,要运行该脚本,我们像上面使用 nano 一样保存它,并在命令行中使用以下命令运行它:

bash process_data.sh speed.csv > text.txt

该命令执行以下操作:

  • 调用脚本
  • 传递我们正在查看的文件(speed.csv)
  • 将输出传递给一个名为text.txt的文本文件

如果您运行了这个程序,并且正确地完成了其他所有工作,那么您的文件夹中就会有一个文本文件,它包含质量控制检查的开始,您可以将它用于您的数据管道!

请在评论中告诉我你在哪里遇到了困难,以及我可以如何帮助你!

干杯

利用双向生成对抗网络估算市场风险管理的风险价值

原文:https://towardsdatascience.com/using-bidirectional-generative-adversarial-networks-to-estimate-value-at-risk-for-market-risk-c3dffbbde8dd?source=collection_archive---------3-----------------------

我们将探索双向生成对抗网络(甘比)在市场风险管理中的应用:评估投资组合风险度量,如风险价值(VaR)。生成敌对网络(GAN)允许我们隐式地最大化复杂分布的可能性,从而允许我们从这种分布中生成样本——这里的关键点是隐式最大似然估计原理,由此我们不指定这种复杂分布被参数化为什么。在许多其他金融服务用例中,处理可能来自复杂分布的高维数据是市场风险管理的一个关键方面。GAN,特别是本文中的,将允许我们处理潜在的复杂金融服务数据,这样我们就不必显式指定分布,如多维高斯分布。

市场风险管理:风险价值(VaR)

风险值是对投资组合风险的一种度量。例如, -5%1% VaR 意味着有 1%的机会获得低于 -5% 的投资组合回报。把它想象成投资组合回报分布的(较低)百分位或分位数,也就是说,我们关心的是尾部风险——损失非常大的投资组合价值的小概率。如此巨大的损失是由我们自己的资金来弥补的,也就是说,与其他人的资金相比,资本是一种昂贵的资金来源,也就是债务。因此,风险值的估计和类似的市场风险管理措施告知银行和保险公司他们需要持有的资本水*,以便缓冲意外的经济下滑——市场风险。

出于我们的目的,让我们从从 Yahoo 获取 5 只股票的数据集开始。股票有苹果、谷歌、微软、英特尔和 Box。我们对 2016 年的数据使用每日频率。我们使用股票的每日收盘价来计算连续复利:

让我们假设我们投资组合中的 5 种资产的权重相等。基于这个投资组合权重的假设,我们可以计算投资组合的回报。

让我们估计预期收益向量、波动向量、相关性和方差-协方差矩阵。方差-协方差矩阵从估计的波动率向量和相关矩阵中恢复:

在哪里

是哈达玛的产品。

投资组合波动估计为:

我们考虑市场风险管理中使用的 3 种主要方法,特别是对 VaR 的估计。请注意,有多种不同的方法来估计风险值和其他更一致的风险衡量指标,如条件风险价值(CVaR),但是我们只考虑少数几个主要的方法。

VaR:方差-协方差法

第一种是方差-协方差方法,使用估计的投资组合波动率

在高斯假设下估计 VaR。让我们假设我们试图估算 1%的 VaR:这意味着有 1%的概率获得低于 VaR 值的投资组合回报。使用方差-协方差方法,计算如下:

VaR:历史模拟法

第二种方法是一种非参数方法,我们从历史数据中进行替换采样,以估计投资组合的回报分布。1%的风险值只是这个投资组合回报分布样本的适当分位数。

VaR:蒙特卡罗方法

第三种方法是使用上述方法从多维高斯分布进行蒙特卡罗采样

最后,1%的 VaR 仅仅是这个投资组合回报分布样本的适当分位数。

VaR:估计值

对于我们的股票回报数据,来自上述 3 种银行常用的市场风险管理方法的 1% VaR 估计值如下:

方差-协方差:-2.87%历史模拟:-3.65%
蒙特卡洛模拟:-2.63%

现在我们转向使用双向生成敌对网络(甘比)进行 VaR 市场风险管理。

双向生成对抗网络(甘比)

生成性对抗网络(GAN)的两个主要组件是生成器和鉴别器。这两个组成部分相互竞争。这样,发生器学习如何从噪声中创建真实的合成样本,即潜在空间 z ,而鉴别器学习如何区分真实样本和合成样本。关于甘的详细解释,请看我下面这篇文章:

甘比通过添加第三个组件扩展了 GAN:编码器,它学习从数据空间 x 映射到潜在空间 z 。发生器的目标保持不变,而鉴别器的目标被改变以在真实样本和合成样本之间进行分类,此外还在真实编码(即由编码器给出的)和合成编码(即来自潜在空间 z 的样本)之间进行分类。

发电机

假设我们事先知道潜在空间 z 的位置:

给定从这个潜在空间的抽取,生成器 G,深度学习器,输出合成样本。

编码器

这可以显示为发生器的反转。给定从数据空间的抽取,深度学习器编码器 E 输出真实的编码。

鉴别器

鉴别器 D 是一个深度学习器,目的是分类样本是真实的还是合成的,即样本是否来自真实数据分布,

或合成数据分布。

此外,它旨在对编码是否真实进行分类,

或者合成的。

让我们将鉴别器 D 表示如下。

我们假设正面的例子是真实的,即,

而反面例子是合成的,即,

最佳鉴别器、编码器和发生器

类似于 GAN,甘比具有以下目标函数。

让我们仔细看看鉴别器的目标函数。

我们已经找到了给定一个生成器和一个编码器的最佳鉴别器。现在让我们关注发生器和编码器的目标函数,其本质上是最小化鉴别器的目标函数。

我们将注意到发生器和编码器的上述目标函数中的 kull back-lei bler(KL)偏差。

回想一下λ发散的定义。

如果λ取值为 0.5,这就称为詹森-香农(JS)散度。这种发散是对称的和非负的。

记住这一点,让我们再次看看发生器和编码器的目标函数。

从上面的生成器和编码器的目标函数中可以清楚地看出,获得的全局最小值是 -log(4) ,这发生在以下条件成立时。

当上述保持詹森-香农发散时,即,

将为零。因此我们证明了最优解如下。

给定上述结果,我们可以证明最佳鉴别器将是 0.5

最佳编码器和生成器是彼此的反函数

在最优生成器和编码器中,我们可以证明生成器和编码器是彼此的反函数。回想一下前面的生成器和编码器的定义。

此时,最佳鉴别器是 0.5 ,即鉴别器不能有效地区分真实数据和合成数据,因为合成数据是真实的。请记住,在这一点上,可能性已经被隐含地最大化,因此从合成分布中获取的任何样本都应该与从真实分布中获取的样本相似。简而言之,如果发生器、编码器和鉴别器的最优性成立,那么合成数据应该看起来与真实数据相似,或者更确切地说是相同。记住这一点,让我们稍微重写一下最佳发生器和编码器函数。

进一步回想一下,以下适用于最佳发生器和编码器。

在上面请注意以下几点;还要注意,我们假设生成器不是编码器的反函数,以提供反证法。

回想一下发生器和编码器最优性条件。

在上面请注意以下几点。

如果最优性成立,那么如下所示成立。

然而,由于我们假设生成器不是编码器的反函数,因此上述条件不成立,从而违反了最优性条件。

因此,我们通过矛盾证明了在生成器和编码器的最优性下,生成器是编码器的反函数。

对于与发生器相反的编码器,可以显示出上述相同的论点。

在上面请注意以下几点;还要注意,我们假设编码器不是通过矛盾提供证明的生成器的反函数。

回想一下发生器和编码器最优性条件。

在上面请注意以下几点。

如果最优性成立,那么如下所示成立。

然而,由于我们假设编码器不是生成器的反函数,因此上述条件不成立,从而违反了最优性条件。

因此,我们已经通过矛盾表明,在生成器和编码器的最优性下,编码器是生成器的反函数。

因此,我们已经通过反证法证明了最优编码器和生成器是彼此的反函数:如果它们不是彼此的反函数,那么这将违反编码器和生成器的最优条件,即,

甘比与自动编码器的关系

此时,在这里回顾我以前关于自动编码器的文章可能是个好主意:https://goo.gl/qWqbbv

注意,给定一个最佳鉴别器,生成器和编码器的目标函数可以被认为是自动编码器的目标函数,其中生成器扮演解码器的角色。发生器和编码器的目标函数仅仅是最小化鉴别器的目标函数,即,我们没有明确地指定重建损失的结构,就像自动编码器那样。这种重建损失的隐式最小化是甘比的另一个优点:不需要明确定义重建损失。

让我们提醒自己生成器和编码器的目标函数。

让我们来处理

首先,然后是

以类似的方式第二次。这些定义如下。

简要回忆一下 Radon-Nikodym 导数的定义:

接下来就是。

现在是第二个学期:

接下来就是。

还要注意。

现在我们将证明这一点

为了证明这一点,假设

因此,

随着

几乎到处都是。这意味着

定义得很好。

现在我们将证明这一点

为了证明这一点,假设

因此,

随着

几乎到处都是。这意味着

定义得很好。

在...的支持之外

0 。同样,在

在...的支持之外

0 。我们从前者开始。

注意,因为

这意味着

假设这个成立,我们清楚地表明

这是一个矛盾。

因此,

几乎无处不在

这意味着

几乎无处不在

因此

在支架上

0 ,即:

在...的支持之外

0

在...的支持之外

0

注意,因为

这意味着

假设这个成立,我们清楚地表明

这是一个矛盾。

因此,

几乎无处不在

这意味着

几乎无处不在

因此

在支架上

0 ,即:

在...的支持之外

0

因此,前面提到的 KL 偏差很可能是非零的

在这个空间中,我们展示了

让我们假设在这个地区

这一套

这意味着

因此,以下成立。

显然,上述内容意味着

并且与早先关于支持的定义相矛盾,即,

因此

是一个空集,因此

最后请注意,这意味着

让我们假设在这个地区

这一套

这意味着

因此,以下成立。

显然,上述内容意味着

并且与早先关于支持的定义相矛盾,即,

因此

是一个空集,因此

最后请注意,这意味着

我们已经清楚地表明

这意味着

是唯一一个

可能非零。

因此。

我们已经清楚地表明

因此,

我们已经清楚地表明

因此,

在上面的大量证明中,我们已经展示了甘比与自动编码器的关系。甘比可用于表示学习或自动特征工程。

在这一点上,我们已经定义了甘比,现在我们将实现它并将其用于我们前面提到的特定用例。

履行

我在这里做的工作是用 Python 和 R 代码在下面的 git repo 上维护的:【https://github.com/hamaadshah/market_risk_gan_keras】T4

结论

在我们结束这篇文章之前,让我们来看看一个未经训练的甘比的投资组合回报分布。

从上图可以清楚地看出,未经训练的甘比的样本投资组合收益分布与实际的投资组合收益分布明显不同。我们可以想象,这是可以预料的。

与经过训练的甘比形成对比:下图将清楚地显示 GAN 类型模型对于市场风险管理的价值,因为我们已经获得了这种学习的投资组合回报分布,而不必依赖于关于实际投资组合回报分布的可能不正确的假设,例如多维高斯分布。

请注意,我们也许应该使用进化算法或强化学习器来自动学习适当的 GAN 或甘比架构:也许这将是未来文章的主题。

最后,我们更新了使用不同市场风险管理方法的风险值估算表,如下所示。我们可以看到,甘比提供的风险值估计与其他市场风险管理方法提供的估计相似,如果不是完全相同的话。这为我们使用甘比进行市场风险管理提供了一个很好的健全性检查,因为它提供了相对于完善的现有市场风险管理方法的竞争结果。

方差-协方差:-2.87%历史模拟:-3.65%
蒙特卡洛模拟:-2.63%

双向生成对抗网络:-4.42%

与我们可能拥有衍生品或其他投资组合组成部分的潜在投资组合相比,我们必须处理的 5 只股票的投资组合并不特别复杂。在一个潜在复杂的投资组合中,获得正确的投资组合回报分布是一个已经被证明可以通过深度学习解决的问题,特别是甘比。这个结果对于市场风险管理和任何其他不同的问题空间都是有用的,在这些问题空间中,我们需要从一个潜在的复杂的,也许是未知的分布中产生样本。

在我的后续文章中,我们可能会看到一个复杂的回溯测试场景,即验证甘比提供的市场风险管理 VaR 类型估计是否适用于我们尚未看到的未来投资组合回报分布,并可能使用更复杂的投资组合。

我的这篇文章的目的是清楚地表明,一个训练有素的甘比可以用于给定投资组合的市场风险管理风险值估计。

参考

1.古德费勒,我,本吉奥,y 和库维尔(2016)。深度学习(麻省理工出版社)。
2。Geron,A. (2017)。用 Scikit-Learn&tensor flow(O ' Reilly)动手进行机器学习。
3。金玛博士和韦林博士(2014 年)。自动编码变分贝叶斯(【https://arxiv.org/abs/1312.6114】T2)。
4。http://scikit-learn.org/stable/#5。https://towards data science . com/learning-rate-schedules-and-adaptive-learning-rate-methods-for-deep-learning-2c8f 433990 D1
6 .https://stack overflow . com/questions/42177658/how-to-switch-back end-with-keras-from-tensor flow-to-the ano
7 .https://blog.keras.io/building-autoencoders-in-keras.html
8。https://keras . io9。f . chollet(2018)。用 Python 深度学习(曼宁)。10。约翰·赫尔(2010 年)。风险管理和金融机构(皮尔逊)。
11。https://towards data science . com/automatic-feature-engineering-using-deep-learning-and-Bayesian-inference-application-to-computer-7 B2 bb 8dc 7351
12 .https://towards data science . com/automatic-feature-engineering-using-generative-adversarial-networks-8e 24 B3 c 16 BF 3
13 .Donahue,j .,krhenbüHL,p .和 Darrell,T. (2017 年)。对抗性特征学习(https://arxiv.org/pdf/1605.09782)。
14。https://github.com/eriklindernoren/Keras-GAN

使用 BigQuery 的新地理空间函数来插值温度

原文:https://towardsdatascience.com/using-bigquerys-new-geospatial-functions-to-interpolate-temperatures-d9363ff19446?source=collection_archive---------5-----------------------

当我写博文宣布来自全球历史气候网络(GHCN)的天气观测公共 BigQuery 数据集时,我展示了两个查询,一个是在某个边界框内查找气象站,另一个是提取某个气象站的最*天气数据。但是,查找边界框的查询使用了难看的纬度-经度限制检查,并且没有简单的方法将两个查询连接起来,以简单地从最*的气象站提取最*的气象数据(并非气象站数据集中的所有气象站现在都在运行,因此不能只使用限制)。

为什么不容易呢?因为 BigQuery 不支持地理空间功能。但是现在有了!因此,让我们将用例重写为一个单独的查询,并使它变得更好。我们不只是从最*的站获取数据。相反,我们将从附*的站点插入数据。如果您使用过 PostGIS 的 ST_ functions ,那么 BigQuery 中的地理空间函数对您来说会很熟悉。

到点的距离

假设我们在纬度为(41.88,-87.63)的地方有一家比萨饼店,首先计算该点 50 公里范围内所有车站的距离:

#standardSQL
WITH params AS (
  SELECT ST_GeogPoint(-87.63, 41.88) AS center,
         50 AS maxn_stations,
         50 AS maxdist_km
),distance_from_center AS (
  SELECT
    id,
    name,
    state,
    ST_GeogPoint(longitude, latitude) AS loc,
    ST_Distance(ST_GeogPoint(longitude, latitude), params.center) AS dist_meters
  FROM
    `bigquery-public-data.ghcn_d.ghcnd_stations`,
    params
  WHERE ST_DWithin(ST_GeogPoint(longitude, latitude), params.center, params.maxdist_km*1000)
)SELECT * from distance_from_center

我设置了三个参数:中心位置、要使用的气象站的最大数量和插值的最大距离。然后,我使用 ST_Distance 计算距离,使用 ST_DWithin 过滤站点。(为什么不在 WHERE 子句中使用计算的距离?因为 DWITHIN 可以进行避免计算距离的优化,并且这样,仅针对足够*的站计算距离)。

此时的结果如下所示:

Distance of stations from our pizza joint

排名超过

50 公里内有 320 个车站。让我们把这个列表删减到前 50 名。我们不能使用 LIMIT,因为 LIMIT 需要硬编码的数字,而我们希望使用上面参数中的 maxn_stations。所以,有一种方法可以做到:

...nearest_stations AS (
  SELECT 
    *, 
    RANK() OVER (ORDER BY dist_meters ASC) AS rank
  FROM 
    distance_from_center
),nearest_nstations AS (
  SELECT 
    station.* 
  FROM 
    nearest_stations AS station, params
  WHERE 
    rank <= params.maxn_stations
)SELECT * from nearest_nstations

现在,结果按距离排序,并限制为 50:

Sorted by distance and limited to closest 50

使用 BigQuery GeoViz 可视化

我们可以用 BigQuery mapper 来实现这一点:

Stations with opacity set by distance

连接表格

现在,让我们通过将上述表格与天气数据表连接起来,并通过 id 将其连接起来,来获取每个站点的最*天气数据:

wxobs AS (
  SELECT
    wx.date AS date,
    IF (wx.element = 'PRCP', wx.value/10, NULL) AS prcp,
    IF (wx.element = 'TMIN', wx.value/10, NULL) AS tmin,
    IF (wx.element = 'TMAX', wx.value/10, NULL) AS tmax,
    station.id AS id, 
    station.name AS name, 
    station.dist_meters AS dist
  FROM
    `bigquery-public-data.ghcn_d.ghcnd_2018` AS wx
  JOIN nearest_nstations AS station ON wx.id = station.id
  WHERE
    DATE_DIFF(CURRENT_DATE(), wx.date, DAY) < 15
),daily_wx AS (
  SELECT
    date,
    MAX(prcp) AS prcp,
    MAX(tmin) AS tmin,
    MAX(tmax) AS tmax,
    id,
    MAX(name) AS name,
    MAX(dist) AS dist
  FROM 
    wxobs
  GROUP BY
    date, id
  HAVING tmin > -100 AND tmax > -100
  ORDER BY
    date ASC
)

上面的奇怪之处是因为 gchnd_2018 表中的每条记录只包含一个观测值(tmin、tmax 或 prcp ),因此我们必须合并多行才能获得完整的观测值集。结果现在看起来像这样:

Daily weather from the two(!) stations with temperature data for each day

插入文字

现在,我们可以添加插值代码:

SELECT 
  date,
  ROUND(SUM(tmin/(dist*dist))/SUM(1/(dist*dist)),1) AS tmin,
  ROUND(SUM(tmax/(dist*dist))/SUM(1/(dist*dist)),1) AS tmax,
  ROUND(SUM(prcp/(dist*dist))/SUM(1/(dist*dist)),2) AS prcp
FROM 
  daily_wx
GROUP BY date
ORDER BY date desc

这给了我们:

Recent weather, interpolated to our pizza parlor

下面是全查询。试试吧!

离多边形的距离

在上面的查询中,我计算了两点之间的距离。相反,如果您想找到邮政编码方圆 10 公里内的所有气象站,该怎么办呢?这里有一个查询可以做到这一点:

#standardsql
WITH params AS (
  SELECT 60626 AS zipcode,
         10    AS maxdist_km
),zipcode AS (
   SELECT **ST_GeogFromText(WKT)** AS polygon 
   FROM `cloud-training-demos.demos.zipcode_polygon2017`, params 
   WHERE ZCTA5CE10 = params.zipcode
),stations AS (
  SELECT
    id,
    name,
    ST_GeogPoint(longitude, latitude) AS loc,
    **ST_Distance**(ST_GeogPoint(longitude, latitude), zipcode.polygon) AS dist_meters
  FROM
    `bigquery-public-data.ghcn_d.ghcnd_stations`,
    params,
    zipcode
  WHERE **ST_DWithin**(ST_GeogPoint(longitude, latitude), zipcode.polygon, params.maxdist_km*1000)
)SELECT * from stations
ORDER BY dist_meters ASC
LIMIT 100

需要注意的关键是,zipcodes 的 BigQuery 表包含众所周知的文本(WKT)的几何信息,所以我使用 ST_GeogFromText 来解析它。【注意:不是将列存储为字符串,我可以将它存储为地理类型——这样,我只需解析字符串一次,而不是在每个分析函数中】。一旦我有了多边形几何,我就可以将它传递到 ST_Distance 和 ST_DWithin 函数中,类似于我传递一个点的方式,并可视化结果:

请注意,到前两个站点的距离为零,因为它们在邮政编码范围内。其余的在邮政编码边界 10 公里以内。

尽情享受吧!

使用 CNN 和 RNNs 进行音乐流派识别

原文:https://towardsdatascience.com/using-cnns-and-rnns-for-music-genre-recognition-2435fb2ed6af?source=collection_archive---------8-----------------------

用数据做很酷的事情!

音频数据正在成为机器学习的重要组成部分。我们正在使用音频与 Siri 和 Alexa 等智能代理进行交互。音频对于自动驾驶汽车也很重要,这样它们不仅可以“看到”周围的环境,还可以“听到”周围的声音。我想探索音频文件和音乐分析的深度学习技术,这似乎是一个有趣的领域,有很多有前途的研究。在这篇博客中,我研究了结合 CNN 和 RNNs 的架构,将音乐片段分为 8 种不同的类型。我也在不同的 CNN 层中可视化过滤器激活。如果你是深度学习的新手,想了解 CNN 和计算机视觉的深度学习,请查看我的博客这里。

这个项目的代码可以在我的 Github 上找到。我希望这里提到的技术有更广泛的应用,而不仅仅是在音乐上。希望你喜欢!

Music Classification

数据集和转换成 Mel 光谱图

有几个不同的音乐数据集——GTZan和百万首歌曲数据集( MSD )是最常用的两个。但是这两个数据集都有局限性。GTZan 每个流派只有 100 首歌曲,而 MSD 有 100 万首歌曲,但只有它们的元数据,没有音频文件。我决定使用免费音乐存档小数据集。您可以使用他们的 github 链接下载小数据集(8 GB ),其中包含原始音频文件和元数据。我使用的 FMA 小数据集有 8 个流派,每个流派*均分布着 1000 首歌曲。这八个流派是电子、实验、民谣、嘻哈、器乐、国际、流行和摇滚。

将音频数据转换成频谱图

每个音频文件都被转换成频谱图,这是频谱随时间变化的直观表示。常规频谱是音频信号的短期傅立叶变换(STFT)的*方幅度。这种常规频谱使用 mel scale 进行压缩,将
音频转换为人类更容易理解的内容。我使用 librosa 库中的内置函数将音频文件直接转换成 mel-spectogram。变换中使用的最重要的参数是——窗口长度,它表示执行傅立叶变换的时间窗口,以及跳跃长度,它是连续帧之间的样本数。这种变换的典型窗口长度是 2048,转换成大约 10ms,这是人耳能够分辨的最短合理周期。我选择跳长为 512。此外,由 Librosa 产生的 Mel-光谱图由对数函数定标。这将
声音数据映射到正常的对数标度,该标度用于确定以分贝(dB)为单位的响度,因为它与人类感知的音高相关。作为这种变换的结果,每个音频文件被转换成形状为 640,128 的 mel 谱图。

如图 1 所示,不同的流派在他们的 Mel-spectrogram 中有明显的差异,这给了我们使用 CNN 进行分类的信心。

Spectogram — Pop(TL), Instrumental (TR), Experimental (BL) and Folk(BR)

Librosa 使得创建光谱图变得非常容易。一个 3 行代码可以将一个音频文件转换成一个频谱图!

y, sr = librosa.load(filename)
spect = librosa.feature.melspectrogram(y=y, sr=sr,n_fft=2048, hop_length=512)
spect = librosa.power_to_db(spect, ref=np.max)

为了加快训练速度,我将数据集分为训练、测试和验证,将它们各自的音频文件转换为频谱图,并挑选结果,以便这些经过腌制的数据可以直接加载。你可以在驱动链接上找到这些数据。

构建 CNN-RNN 模型

为什么要用 CNN 和 RNNs?

出现的一个问题是,为什么我们需要同时使用 CNN 和 RNNs。频谱图是跨越频率和时间维度的音频的视觉表示。CNN 是有意义的,因为一首歌的频谱有点像一幅图像,每一幅都有自己独特的模式。rnn 通过使时间 t 的隐藏状态依赖于时间 t-1 的隐藏状态,在理解顺序数据方面表现出色。频谱图具有时间成分,并且 RNNs 可以更好地识别歌曲中的短期和长期时间特征。

我尝试了两种有趣的 CNN-RNN 架构——卷积递归模型和并行 CNN-RNN 模型。这两个模型都是用 Keras 编写的,你可以在我的 Github 上找到代码。

卷积递归模型

这个模型的灵感来自于 deep sound 的工作和 Keunwoo Choi 等人的论文,这个模型使用的是 1D CNN,它只在时间维度上执行
卷积运算。每个 1D 卷积层从光谱图的一小片中提取特征。卷积运算后应用 RELU 激活
。完成批量归一化,最后执行 1D 最大池,这降低了图像的空间维度并防止过拟合。这个操作链——1D 卷积——RELU——批量归一化——1D 最大池被执行 3 次。来自 1D 卷积层的输出被馈送到 LSTM,该应该找到歌曲的短期和长期结构。LSTM 使用 96 个隐藏单元。来自 LSTM 的输出被传递到一个由 64 个单元组成的
密集层。模型的最终输出层是具有 Softmax 激活和 8 个隐藏单元的密集层,以将概率分配给 8 个类别。在所有层之间使用了丢弃和 L2 正则化来减少模型的过拟合。下图显示了该模型的整体
架构。

CRNN Model

使用 Adam optimizer 以 0.001 的学习率训练该模型,损失函数是分类交叉熵。该模型被训练 70 个时期,并且如果验证准确度稳定在至少 10 个时期,则学习率降低。

参见下面的训练和验证样品的损失和准确度曲线。正如所看到的,该模型具有低偏差但高方差,这意味着即使在使用了几种正则化技术之后,该模型对于训练来说还是有点过度拟合。

CRNN — Loss and Accuracy

总的来说,这个模型在验证集上达到了大约 53%的准确率。

并行 CNN-RNN 模型

受林芬和刘深兰的作品的启发,我也尝试了一个*行的 CNN-RNN 模式。这个网络背后的关键思想是,即使 CRNN 有 RNNs 作为时间摘要器,它也只能从 CNN 的输出中总结时间信息。在使用 CNN 的操作期间,原始音乐信号的时间关系没有被保留。该模型将输入频谱图并行通过 CNN 和 RNN 层,连接它们的输出,然后通过 softmax 激活的密集层发送,以执行分类,如下所示。

Parallel CNN-RNN Model

该模型的卷积块由 2D 卷积层和随后的 2D 最大汇集层组成。这与使用 1D 卷积和最大池层的 CRNN 模型形成对比。卷积最大池层有 5 个块。最终输出是*坦的,并且是无形状的张量 256。
复发块从池大小为 4,2 的 2D 最大池层开始,以在 LSTM 手术之前减小频谱图的大小。这种特征减少主要是为了加速处理。缩小的图像被发送到具有 64 个单元的双向 GRU。该层的输出是无形状的
张量,128。
来自卷积和递归块的输出然后被连接,产生形状张量,无,384。最后,我们有一个 softmax 激活的密集层。
使用 RMSProp 优化器训练模型,学习率为 0.0005,损失函数为分类交叉熵。该模型被训练 50 个时期,并且如果验证准确度稳定在至少 10 个时期,则学习率降低。

下图显示了该模型的损耗和精度曲线

该模型的验证损失约为 51%。这两个模型具有非常相似的整体精度,这很有趣,但它们的类智能性能非常不同。并行 CNN-RNN 模型对于实验、民谣、嘻哈和器乐流派有更好的表现。这两个模型的组合应该会产生更好的结果。

我问自己的一个问题是,为什么准确率只有 51%左右。我认为这有两个原因:

  • 对于从零开始构建深度学习模型来说,1000 个光谱图的样本量实际上是一个非常小的样本。从损失曲线可以看出,两种模型都很快过度拟合。理想情况下,我们有一个更大的训练集,或者可以尝试的一件事是将每首歌曲分成 3 段,每段 10 秒,每个都有相同的标签,并使用它将数据集的大小增加两倍。
  • FMA 的数据集很有挑战性,特别是它有几个容易混淆的类,比如实验类和国际类。在 FMA 流派识别挑战赛上的最高分只有 0.63 分左右

使用 Keras 可视化工具包可视化不同层中的激活

我研究了卷积模型的初始层和后续层的特征。对于这个分析,我使用了 Keras 可视化包并选择了并行 CNN-RNN 模型,因为它使用了更容易可视化的 2D CNN 层。

该模型中的第一卷积块具有 16 个滤波器,第五卷积块具有 64 个滤波器。为了理解过滤器关注的是什么,我们来看看什么样的输入最大化了过滤器中的激活。下图显示了第一个卷积块中所有 16 个滤波器与第五个卷积块的前 24 个滤波器的滤波器激活。

Filter Activations for first and fifth convolutional block

我在这里观察到的是,第一层的过滤器相对简单。有在看一个 3,1 的小内核大小。因此,他们主要关注 50-200 db 之间的不同波动模式。在第五个卷积块中,由于卷积和最大池化操作导致特征图缩小,同一滤波器正在查看更大的输入图像
。现在,它能够聚焦于不同的特征,如振幅急剧增加至 250 db,以及振幅非常低的时段显示为黑色区域。

我希望您喜欢这个分析,并尝试自己的代码。

我有自己的深度学习咨询公司,喜欢研究有趣的问题。我已经帮助许多初创公司部署了基于人工智能的创新解决方案。请在 http://deeplearninganalytics.org/的入住我们的酒店。

你也可以在https://medium.com/@priya.dwivedi看到我的其他作品

如果你有一个我们可以合作的项目,请通过我的网站或 info@deeplearninganalytics.org 联系我

参考

  • http://deepsound.io/music_genre_recognition.html
  • 免费音乐档案—https://github.com/mdeff/fma
  • 天秤座
  • 用于音乐分类的卷积递归神经网络
  • 并行递归卷积神经网络的音乐流派分类

使用联合数据

原文:https://towardsdatascience.com/using-conjoint-data-371b237f7533?source=collection_archive---------17-----------------------

德瓦希什·迪曼&维克拉姆·德瓦塔

联合分析有助于确定消费者如何评价产品的不同属性。这是一种常用的统计技术,用于模拟新产品发布时的消费决策和产品市场份额。在这里,我们将联合分析的原则应用于 Partworth 的数据,这些数据来自对 7 个知名啤酒品牌的 317 名受访者的调查。以下是我们处理这个话题的方式:

首先,我们探索数据集,以更好地理解应答者的人口统计数据。接下来,我们根据给定的 Partworth 数据对啤酒品牌进行细分,并使用这些数据对每个细分进行个性化。然后,我们尝试判别分析,以检查该模型是否可以用来分类新的反应。我们计算目前的市场份额,以及当一种新啤酒在同一个市场推出时,市场份额如何变化。根据市场份额的变化,我们确定了新啤酒品牌的最佳细分市场。

这里有原始数据:【https://goo.gl/nP91hF】T2。Tableau 和 R 是本分析中使用的主要工具。

探索人口统计

数据集中提供了以下人口统计详细信息:

年龄直方图显示,大多数受访者年龄在 30-45 岁之间。年龄变量的箱线图显示它有轻微的偏斜,没有异常值。

大多数受访者收入超过 50,000 美元,没有异常值。尽管该分布显示了左偏斜,但它并没有大到足以保证对数变换。

类别变量(年龄和收入)通过取类别*均值转换成整数对应变量。年龄变量的第一类被假定为“21 岁以下”,而不是数据集中给定的“22 岁以下”。

“每周消费量”直方图显示,大多数受访者在任何给定的一周内消费不到 10 瓶啤酒。箱线图揭示了几个异常值,但考虑到领域(“啤酒”)和数据生成过程(“消费模式”),我们选择不转换数据,并保留异常值。

大多数受访者是大学毕业生,其次是研究生。缺少值(用' 4 '代替)的很少,用'高中'及以下的很少。数据集的男性数量明显多于女性,任何建议都需要牢记这一点。

根据 Partworth 数据对品牌进行细分

我们对 Partworth 数据使用 K-Means 聚类,为不同数量的聚类生成“组内*方和”的 scree 图,如下所示。我们找不到一个显著的弯头来给出最佳分段数的直观感觉。

我们尝试使用 3 个段和 4 个段进行聚类,但我们发现用 2 个段描述数据最好。由于数据集很小,我们使用凝聚层次聚类使用欧几里德距离与病房的方法。我们将树分为两段,如下所示:

导出结果成员数据,以便在 Tableau 中可视化和描述受访者。

拟人化并描述每个片段

我们将人口统计数据与从聚类算法中获得的成员详细信息“连接”在一起,注意如下:

与细分市场 2 中的受访者相比,细分市场 1 中的受访者年龄略小,收入略高,啤酒消费量也更多。进一步按性别区分,我们得到以下结果:

*均而言,在这两个群体中,男性年龄更大,收入更高,每周消费更多瓶啤酒。然而,第二部分的男女*均收入差距大于第一部分,而第一部分的男女*均周消费差距大于第二部分。

基于以上所述,我们将分段 1 命名为“年轻快乐”,分段 2 命名为“年老成熟”。

通过在 Tableau 中可视化按比例缩放的 Partworth 数据,并使用细分成员数据按颜色区分,我们获得以下金字塔图。

我们发现,“老熟”更喜欢价格为 5.49 美元的普通酒体、日本或加拿大啤酒,具有普通卡路里和浓郁的余味,而“年轻和快乐”则倾向于喜欢欧洲的醇厚啤酒,酒体清脆、清澈,余味温和。

我们可以计算每个回答者赋予每个属性的重要性,即。分配给属性级别的 Partworth 实用程序的范围除以总数。将这些数据导入 Tableau 有助于我们直观地了解每个细分对每个属性的相对重要性,如下所示。

虽然这两个部分似乎对所有属性给予了同等的重视,但我们看到年轻和快乐的人比其他部分更重视啤酒中的卡路里数,而年老和成熟的人比其他部分更重视杯子。

执行判别分析

人口统计数据中的描述符可用于基于以上获得的片段执行判别分析。我们尝试了线性判别分析(又名 Fischer 判别)来区分这两个细分市场,并使用该模型来预测新消费者将属于哪个细分市场。人口统计数据与细分成员数据“结合”,然后分成训练和验证数据集(比例为 80:20)。

使用来自 r 中质量包的 lda 函数进行线性判别分析。区段 ID 作为类别变量(因变量), 5 个分类变量(年龄、教育程度、性别、收入和每周消费)作为解释变量。结果如下所示:

下面给出了来自训练集的混淆矩阵:

准确率仅为 69.57%,实际错误率(AER)为 30.43%。然后将 LDA 模型应用于验证数据集,以测试其有效性。获得了以下结果:

准确率仅为 57.81%,实际错误率(AER)为 42.19%。线性判别分析似乎不能很好地处理给定的数据集,我们不建议使用该模型来区分两个细分市场中的新消费者。

计算目前的市场份额

每位受访者对某一属性的重视程度被用来计算他/她消费某一品牌啤酒的可能性。每个啤酒品牌的属性和级别用于创建二元矩阵,如下所示:

每个应答者的 Partworth 效用与上述二进制矩阵交叉相乘,然后取幂。通过计算每个品牌占总和的比率,我们获得了新产品发布前每个品牌的市场份额。

目前的市场份额也按细分市场进行了分析,如下所示

虽然大多数品牌在每个细分市场的份额几乎相同,但我们观察到 HH 和 al 在细分市场 1(年轻和快乐)的渗透率更高,而 BB、BG、MN 和 SA 在细分市场 2(成熟和成熟)的表现可能更好。

计算新的市场份额

如果一个新品牌 NB 被引入市场,那么新产品被插入二元矩阵,如下所示:

可以通过新品牌的潜在渗透率来重新计算市场份额,即每个受访者的 Partworth 效用与二元矩阵相乘,然后取幂。新产品发布后,每个品牌占总市场份额的比率。新的市场份额如下:

市场份额减少情况汇总如下:

选择目标细分市场

按细分市场划分的新市场份额如下所示。

我们还比较了新啤酒品牌发布后的市场份额变化,如下所示:

由于新品牌的出现,HH、BB、AL 和 s a 的细分市场 1(“年轻和快乐”)的市场份额有所下降,而 HH、BB 和 SA 的细分市场 2(“老和成熟”)的市场份额有所下降。新啤酒品牌在“年轻快乐”人群中占有 4.10%的市场份额,在“老年成熟”人群中占有 3.26%的市场份额,这使得瞄准细分市场 1 比细分市场 2 的利润略高。

此外,由于这一部分有较高的*均收入和较高的*均每周消费,这是一个更好的选择给定的两个部分。由于数据集中男性数量明显多于女性,因此上述分析可能更适用于男性。因此,该公司可以将目标锁定为“年轻快乐的男性”,年龄 36 岁,年收入 56-57 万美元,*均每周消费 10 瓶啤酒。

关于我们

在 LinkedIn 上找到我们,地址是https://www.linkedin.com/in/devashishdhiman/和https://www.linkedin.com/in/vikramdevatha/

参考

Orme,B. (2010 年)。解释联合分析的结果。在 B. Orme,联合分析入门:产品设计和定价研究策略(第 77-88 页)。美国威斯康星州麦迪逊:研究出版有限责任公司。可从这里获得:https://sawtooth software . com/resources/books/getting-started-with-combint-analysis

PPT 实验室。(2014 年 2 月 25 日)。为什么消费者不买:产品采纳心理学。从 PPT 实验室检索:http://PPT Lab . com/PPT/Why-Consumers-don-Buy-The-Psychology-of-The-New-Product-Adoption-16

Qualtrics。(2018).什么是联合分析?联合类型&何时使用。2018 年 11 月 5 日检索,来自 qual trics:https://www . qual trics . com/experience-management/research/types-of-connect/

维基百科。(2018 年 10 月 24 日)。联合分析。2018 年 11 月 9 日检索,来自维基百科,免费百科:https://en.wikipedia.org/wiki/Conjoint_analysis

使用数据分析来预测、检测和监测慢性自身免疫性疾病

原文:https://towardsdatascience.com/using-data-analytics-to-predict-detect-and-monitor-chronic-autoimmune-diseases-ca062e9cb12c?source=collection_archive---------20-----------------------

根据美国自身免疫性相关疾病协会的数据,自身免疫性疾病是美国最流行的疾病之一,影响着大约 5000 万美国人,即 20%的人口。在研究人员已经确定的 80-100 种不同类型的自身免疫性疾病中,每年的直接医疗费用总计约为1000 亿美元。

从这个角度来看,癌症相关医疗保健的支出实际上更低——根据美国癌症协会的估计,2015 年美国花费了大约 802 亿美元。

众所周知,医疗保健支出在美国经济中发挥着巨大作用,根据医疗保险和医疗补助服务中心的数据,2016 年医疗保健支出达到 3.3 万亿美元。根据 Express Scripts 的 2017 年药物趋势报告,成本只会上升,特别是治疗许多自身免疫疾病所需的专业药物,这些药物占药房福利总支出的 40.8%。

如何解决这些成本?预测和说明性分析的时代已经到来,许多医疗保健领域的趋势表明,当机器学习和人工智能(AI)用于挖掘大型数据集以获得模式,从而实现更快、更准确的决策和更好的结果时,可以产生价值。比如现在有一个 AI *台,可以利用代谢标志物诊断寨卡病毒等疾病。同样,根据该公司的 2017 年药物趋势报告,Express Scripts 的 SafeGuardRx 正在使用分析来降低处方药成本,使计划节省 3.4 亿美元。以同样的方式,我参与了构建 IQuity 的技术,该技术使用机器学习来通过血液测试检测自身免疫性疾病。

医疗保健分析为医疗专业人员提供了新的信息,这些信息由知识渊博的数据科学家进行处理和验证,以确定准确的诊断和最佳的治疗计划。未来更有希望,因为预测和说明性分析提供了预测和监控疾病的能力,而不仅仅是检测疾病。分析的信息可以从索赔数据、电子病历(EMR)甚至实时健康源(如 Fitbits 和监控体重减轻和睡眠模式的移动应用程序)中收集,从而提供比以往任何时候都更全面的患者视图。

机器学习和人工智能管道可以分析并不断从这些数据源中学习。这些工具可用于获得关于特定患者群体的见解,融入性别、地理、社会经济或生活方式数据等因素,以确定即将被诊断为慢性疾病的患者、被误诊的患者以及被诊断患有疾病的患者的管理效率。

自动化机器学习技术的最新进展使其能够在诊断疾病时加快速度,确定治疗何时有效,何时无效,影响护理提供的监控方式,并优化医疗保健的支付方式,从而共同提高患者生活的质量和长度。它还将降低整个医疗保健连续体的成本:那些面临医疗保健费用风险的人(如自我保险的雇主和付款人)和越来越多地不得不自掏腰包支付自己医疗保健费用的病人。

作为这项技术威力的一个例子,让我们来看看这种方法如何应用于多发性硬化症(MS)等自身免疫性疾病患者的整个诊断和治疗过程。

预测

我们公司最*进行了一项试点研究,分析了纽约 2000 万人的医疗保健索赔。该方法包含 40 亿个数据点,专注于多发性硬化症,预测准确率超过 90 %,在传统方法(包括核磁共振成像、脊椎穿刺和进一步监测症状的等待期)最终结束之前,该患者群体中的个体多发性硬化症发作至少八个月

尽早了解哪些患者将被诊断为多发性硬化症对所有利益相关者都有好处:

  • 提供者可以利用这些信息进行早期、准确的诊断,从而加快治疗速度,减轻这种疾病造成的长期损害。
  • 支付者——包括自我保险的雇主和商业保险公司,两者都有成本风险——可以从提供者早期行动中受益,以减轻疾病的严重程度并识别误诊,帮助控制特殊药品成本。
  • 拥有更深入信息的护理管理团队可以通过微调护理计划、药物、疗法和其他资源来更好地管理高费用患者,以确保最佳结果。
  • 最重要的是,这些信息可以防止患者在治疗过程中出现复发或其他不良事件,从而提高生活质量。患者的费用也将显著降低,因为费用通常在诊断之前就累积,并且在复发或不良事件发生时最大。

根据 MS 脑健康(第 30 页),MS 等疾病的早期检测可以在大脑出现不可逆损伤和并发症之前进行干预。因此,使用数据分析来预测患者的健康状况并相应地根据数据采取行动,可以改善患者的整体健康状况,降低疾病的严重程度,并减少患者一生中的身体损伤。

检测

在我们针对多发性硬化症的试点研究中,我们的团队能够识别出被正确诊断的患者以及被误诊的患者。误诊在患有自身免疫性疾病的患者中并不罕见,因为大约 100 种不同疾病中的每一种都涉及免疫系统攻击身体,这可能导致类似的症状,尤其是在许多这些疾病的早期表现中。

全科医师通常不知道各种类型的自身免疫性疾病是如何相互关联的,而专家尽管知道这些关系,却无法获得能够明确指出自身免疫性疾病的工具,并且经常不得不依靠各种方法以“试错”方式或复杂的排除过程来间接识别自身免疫性疾病。根据美国自身免疫相关疾病协会的说法,“最初的症状往往是间歇性的,不确定的,直到疾病变得急性。”这使得正确诊断患者成为一项困难的任务,尤其是对于最初可能不会怀疑自身免疫并且没有接受过诊断和治疗这些疾病的专门培训的初级保健医生而言。

然而,从卫生保健数据集获得的见解可用于开发诊断*台,帮助提供者达成最终诊断。最初,通过将基因组数据与机器学习技术结合起来,我们公司能够创建算法来分析患者的 RNA 基因表达模式,以确定它们是否符合特定的疾病。我们能够针对各种自身免疫性疾病和相关疾病(包括多发性硬化症和纤维肌痛)修改这项技术,以便为提供者提供关于患者是否患有该疾病的明确答案。

我们的分析*台通过将相同的技术、流程和专业知识应用于更大的人口级数据集,将这一成就向前推进了一步。这使我们能够进一步增强我们的预测能力,仅使用数据在大量患者群体中识别自身免疫性和相关疾病,包括共病。与需要血液样本的基因组测试不同,我们的人口级分析*台能够在患者同意的情况下,通过保险索赔信息、临床观察或电子健康记录中记录的测试结果,以及允许我们收集患者及其环境的完整视图的其他公共或私人数据元素,使用归属于每个患者的数据来预测疾病。将机器学习应用于现有数据,不仅可以检测,还可以预测这些疾病的存在,这为早期治疗和改善结果带来了巨大的希望。

监控

来自多个数据集的见解可用于监测诊断后的患者。预测分析可以确定自身免疫性疾病患者何时可能发病,病情是变好还是变坏,以及患者对特定治疗方案的反应,所有这些都可以为未来的治疗计划决策提供信息,以及如何调整这些决策以确保最佳结果和高总体患者生活质量。

监测患者还可以为护理管理团队提供洞察力,以确定导致更差结果的特征。例如,由于各种原因,药物依从性对于患有自身免疫性疾病的患者来说是一个重大问题,包括特殊药物的成本障碍、订购或获得某些药物的障碍以及患者不想忍受的治疗的常见副作用。当患者不遵循他们的护理提供者的处方药物治疗计划时,治疗通常更加困难和昂贵。

我们的分析策略可以监控这些患者是否有可能降低药物依从性,并为护理人员提供一个改变治疗计划或让患者接受与降低依从性相关的陷阱教育的机会,最终为所有相关利益方带来更好的结果和成本节约。

将所有这些放在一起

美国国立卫生研究院(NIH) 自身免疫疾病研究计划将自身免疫研究称为“最有希望的新发现领域之一”,基于过去十年中取得的创新。在预测分析和各种可用患者数据集的帮助下,我们可以以超乎想象的速度做出这些发现,改善患者的生活,同时降低美国慢性病患者的直接护理成本

或许医疗保健数据分析以及人工智能和机器学习的力量最棒的部分是,像我们正在开发的那些技术,并不局限于任何特定类别的疾病。这种方法可以应用于任何疾病,这种方法改善甚至挽救生命的潜力是不可估量的。

【Chase Spurlock 博士是 IQuity 的首席执行官和联合创始人,IQuity 是一家位于纳什维尔的数据科学公司,使用基因组和专有医疗保健数据集来预测、检测和监测慢性病。更多信息,请访问

利用数据科学造福社会

原文:https://towardsdatascience.com/using-data-science-for-social-good-c654a6580484?source=collection_archive---------4-----------------------

在混乱的代码和无情的技术浪潮中,我们很容易忽略我们工作的更大目标。

虽然我们都有不同的动机,但我相信我们都渴望影响我们的工作,并以某种方式做出有意义的贡献。随着我们不断学习和职业发展,我们也在寻求理解如何运用我们的技能进行创造性和批判性思考,以解决现实生活中的问题。

数据科学作为一个领域,往往会被太多的流行语(“AI!”“深度学习!”“大数据!”)这涉及到我们做什么,而没有太多关于为什么我们会首先这么做。这是一个不断发展的领域,潜力巨大,但我认为改变叙述方式很重要。是的,机器学习,但是为什么呢?是的,大数据,但是为了什么?

我们如何利用数据科学及其多功能工具来解决现实生活中的问题?对社会“好”有什么影响?技术进步和发展,数据变得更加丰富和有用。作为受益于这一势头的数据科学家,我们如何帮助世界其他地区迎头赶上?

由于这似乎是目前网上讨论的一个有限的话题,这里概述了一些可用的投稿途径。为了找到合适的贡献途径,未来的数据科学行善者当然需要更多的主动性,但这并不是不可能的。

面向社会的数据科学项目/组织的志愿者 一些面向社会的数据科学奖学金,通常与非营利组织和地方政府合作提供。这包括芝加哥大学的数据科学社会公益奖学金和 Thorn 创新实验室。这些研究金使人们能够更深入地了解通过应用数据和分析工具可以解决的无数问题。

DataKind 是一家数据科学组织,专门致力于社会公益,并提供各种志愿服务机会,无论是通过指导还是使用您的数据科学技能来帮助解决他们 DataCorps 项目中的一个社会问题。DataKind 还与许多非营利组织合作,举办类似的竞赛和黑客马拉松。

通过竞赛做出贡献 数据科学竞赛的主要目的地, Kaggle 举办了无数旨在测试您的数据科学技能的竞赛。其中一些比赛关注社会问题。

一个更新的、面向社会的竞赛*台, DrivenData 与各种组织合作。这些组织通常是非盈利性的,专注于具有现实影响的社会难题。

Some competitions currently being hosted by DrivenData

开发人员和数据科学家能够贡献解决方案来帮助解决这些问题。他们的解决方案将被合作组织所利用,这样他们就可以更有效地完成他们的使命。

其他组织偶尔也会举办以“做好事”为导向的其他数据科学竞赛和黑客马拉松。

考虑你所遇到的现实世界问题的解决方案 虽然在构思和提出问题时,竞争是有用的,但对于解决问题来说,竞争并不是完全必要的。一个足智多谋的数据科学家可以利用他们可用的数据,自己识别并努力解决社会公益问题。Gap Minder Foundation 是一个很好的数据资源,它提供统计数据来了解全球趋势。Gap Minder 强调客观性,而不是用情绪或戏剧模糊统计数据,以促进对我们世界的真正理解,以便我们能够更好地工作,使它变得更好。

Sample data produced by Gap Minder Foundation, demonstrating the relationship between life expectancy and country’s income level

Data for Democracy 是一个由电子志愿者组成的社区,他们构思并贡献自己的问题解决方案。任何人都可以做出贡献,一切都由社区主导,提交的解决方案有可能推动对各种问题的有效干预。

在你的专业工作中要深思熟虑 从私营部门到公共和非营利部门,数据科学职位在所有行业中都存在并不断涌现。在你的职业生涯中,有很多机会可以产生有意义的社会影响。在私营部门中,肯定有公司为更大的社会问题开发创新的解决方案。例如,医疗保健和其他以科学为导向的领域(见:气候变化)继续快速发展,其增长基本上是由数据和技术驱动的。深度学习和其他分析工具可以帮助改善健康诊断或空气污染解决方案等事情,这将对人口健康产生重大影响。

面向公众利益的组织也可以从事数据科学工作。各国政府开始认识到数据在了解其公民身份方面的重要性,特别是在实施有效的循证干预措施和政策方面的使用。

同样,非营利组织也继续需要数据科学家来帮助实现他们的使命。

在结束这一部分时,我不想忽略两个特别有趣的组织: Bayes Impact 和前面提到的 DataKind。像 DataKind 一样,Bayes Impact 是一个具有社会意识的数据科学组织,利用数据解决世界问题。Bayes Impact 与其他大型非营利组织合作,解决与健康、失业和司法相关的问题。这两个组织都为充实和进步的数据科学职业生涯提供了巨大的机会。

结论 作为数据科学家,我们有能力做重要的事情。我们拥有资源,尽管这些资源看起来可能有些混乱和难以理解,但我们确实有所作为。无论我们的道路通向何方,我相信我们努力成为有思想的公民数据科学家是不可或缺的,要始终考虑我们的工作如何影响社会。

在日常生活中使用数据科学

原文:https://towardsdatascience.com/using-data-science-in-everyday-life-f9b58f1f74af?source=collection_archive---------19-----------------------

我最*为我们社区组织了一次社交聚会。我们通过引入游戏和文化活动来组织这个特殊的聚会,并让达拉斯沃斯堡内的不同城市相互竞争一个总奖杯。由于我们有一个混合的聚会(保守派,自由派,在我们之外出生和长大的人,在美国出生和长大的人,孩子,18 到 50 岁的成年人),组织这个聚会并确保每个人的参与是一个挑战。最后结果是个好玩的活动(至少我是这么认为的!!),尽管中间下雨扫了兴。

聚会结束后不久,反对者们就开始对此议论纷纷。正如任何有着不同背景和品味的大群体一样,每个人都会有自己的看法。因此,我们发出了谷歌调查,以衡量满意度,以确保每个人的声音都被听到和衡量,而不是少数害群之马抹黑我们的努力。

作为一名组织者,衡量更广泛人群的总体满意度对我来说很重要,因此我决定利用我在数据科学、Python 和自然语言处理方面的技能来接受这一挑战..

技术背景

与任何数据科学项目一样,当我们处理结构化和非结构化数据时,大部分工作都花在组织数据、清理数据上。在仔细研究数据后,数据质量/特性工程工作包括以下
1)确保所有满意度度量都是整数(将字符串转换为整数,将 NaN 更改为 0 等)。)
2)删除所有特殊字符(/、@、。等等。)使用正则表达式
3)通过删除所有停用词并将所有词改为小写来清理数据

最后,没有足够的数据来对一些相关性指标得出有意义的结论。我很想使用 NaiveBayes 分类算法,但同样,没有太多的数据可供使用。

Python 库的详细信息 在这个项目中,我们计划衡量各种因素的满意度——总体满意度、与通信、食品、文化活动、体育等相关的满意度。这里是使用的各种 python 库

  1. 利用 pandas 数据帧读取 CSV 文件并进行数据转换(添加列、测量相关性等。)
  2. 使用 NLTK — FreqDist 和 NLTK 单词 tokenize 来统计在各种调查问题中使用最频繁的单词
  3. 使用 matplotlib.pyplot 绘制各种满意度指标的直方图、条形图
  4. 使用正则表达式( reLambda 来清理数据和进行转换
  5. 使用 TextBlob 使用极性测量情绪(积极或消极),使用主观性测量主观性
  6. 使用 WorldCloud 为非结构化数据生成单词云
  7. 使用 seaborn 库绘制相关矩阵热图,柱状图

结论
经过分析,我很高兴地得出结论,大多数人喜欢这个活动(满意度指标的综合直方图中,4 分和 5 分表示人们喜欢这个活动)。世界云有助于挖掘非结构化数据,了解人们最关心的是什么。显然,人们最关心食物(事后看来,这是显而易见的:)
所以我们能够科学地压制反对者的声音。

下面是我使用的代码片段和图表。完整的代码在我的 github 库—https://github.com/yasimk/

##词云表示食品、文化、体育、小吃、奖项和节目被提及最多

下面的满意度矩阵综合了所有指标。如你所见,大多数分数在 4 或 5 分左右。这一结果证明这次活动是成功的

还为每个满意度分数创建了单独的直方图(由于缺乏实际资料,此处仅显示总体满意度)

情感分析的条形图如下所示。如你所见,结果显示没有因小数据集而产生负面情绪。一个丰富而庞大的数据集,如 Twitter 选举反馈,会告诉我们一个不同的故事。我期待着分析 2018 年 11 月中期选举的推特数据

参见下面相关矩阵的热图分析

总体满意度与男性体育赛事相关(0.59)。这是有道理的,因为喜欢运动的人是积极的类型,得分与总得分相关。

迎送家属满意度与颁奖和结案相关(0.71)。这很直观,因为颁奖典礼将所有团体(女士、男士和小孩)聚集在一起,因此我们为会员提供了见面和问候的机会

体育赛事男性和女性的相关性最小(0.23),这是有道理的,因为我们分开举办赛事

体育赛事男性和见面问候家庭(0.26)的相关性不是那么大。这是有道理的,因为人们参加男性活动,他们不能花足够的时间见面和问候。

我试图检查特定城市的这些指标,以检查是否有任何相关性。然而,没有足够的数据来得出结论

代码可以重新用于 Twitter 情绪分析或任何非结构化数据分析。

完整代码可在 GitHub—https://GitHub . com/yasi MK/NLP-opinion-analysis-python/blob/master/NLP _ opinion _ analysis _ social _ gathering . ipynb获得

希望您喜欢阅读关于如何在日常生活中使用数据科学的内容。你也可以每天利用数据科学的力量为你带来优势。如有任何问题或反馈,请给我留言。

利用数据科学实现营销效率的成倍增长

原文:https://towardsdatascience.com/using-data-science-to-achieve-a-multifold-increase-in-marketing-effectiveness-ebe25da7b00e?source=collection_archive---------7-----------------------

在随着技术的出现而改变的所有商业方面中,也许最深刻地受到影响的是营销的作用。营销人员可以简单地通过在杂志上刊登整版广告、在镇上张贴明亮的广告牌,甚至与迷人的名人签约拍电视广告来吸引顾客的日子已经一去不复返了。由于大量客户数据的可用性和数据科学工具的结合,今天的营销人员有能力比过去更加有效。建立对各种可能性的理解将极大地丰富任何营销人员的工具箱。

最根本的变化之一是客户细分观念的转变。我们现在生活在一个 【一个人的一部分】 的时代,每个顾客都是自己的一部分。公司和品牌对目标个人的理解要深刻得多,甚至可以说是亲密得多,这使他们能够个性化地对待每一位顾客。能够有效地做到这一点的第一步是建立对典型客户生命周期的理解。虽然客户生命周期可能有行业特定的细微差别,但大致代表如下:

Image 1: Phases of a Customer Lifecycle

红线代表典型客户将如何经历这些阶段。在获得客户后,他们的消费会随着品牌/产品的加入而增加。在经历“增长”阶段时,It 部门的支出会有一定程度的快速增长,直到客户脱离并走向流失时,支出才开始减少。

绿线是营销人员希望引导这类典型客户的途径,即理想客户生命周期。每个阶段都要求营销人员采取独特的方法来弥合红线和绿线之间的差距。

阶段 1:获取新客户

目标:确定正确的目标潜在客户。通过最有可能对每个人起作用的方式来锁定目标。

作为一个数据问题,获取可能是最棘手的。在这一阶段,你的目标客户尚未与你进行交易,因此还不属于你的数据生态系统。这极大地限制了你对他们的了解。幸运的是,人们可以使用数据库,有时是免费的,但通常是收费的。

一旦你有了可用的数据,就可以挖掘出最符合你的理想客户特征的目标。在这个阶段,由于你几乎没有关于实际购买行为的数据,你必须主要关注人口统计信息。令人欣慰的是,在大多数情况下,基本的人口统计数据能够相当准确地识别目标。人口统计数据可能包括大量参数,如性别、年龄、位置、婚姻状况、家庭规模、教育、职业等。

既然已经确定了目标客户,我们就可以进入第二个关键目标,即寻找目标客户的最佳方式。用更专业的术语来说——我们如何最大化“转化率”。同样,由于现阶段数据有限,人们将不得不依靠代理指标来设计收购活动。一个有效的替代方法是分析对以往收购活动的历史反应,看看哪些措施对微观群体有效。如果没有交易或行为数据,微观群体可能只需要通过人口统计学来定义。例如,如果在过去的某个周末,18-24 岁的男性学生通过外拨电话获得了最高的转化率,那么我们也可以将此用于潜在的营销活动。

阶段 2:新客户入职

目标:深入了解客户。还有,勾住他们,建立忠诚度。

从营销人员的角度来看,这可能是最关键的阶段。到现在为止,你已经成功地争取到了一个新客户,所以你已经迈出了第一步。他们现在需要培育和发展,以便相互关系变得富有成效。把它想象成第一次约会——如果你想有第二次、第三次和第四次约会(作为一名营销人员,你总是希望这样!),那么你最好确保在最初的交流中你把球打出了公园。

为了能够做到这一点,你首先需要了解客户。这可能包括人口统计方面的更多细节,但也包括其他内容,包括:

  • 交易细节(Transactional Details):他们买了什么,花了多少钱,如何付款,他们是在网上购买还是在商店购买,等等。
  • 行为参数:他们是否倾向于寻找折扣/便宜货,他们一起购买什么类型的商品,他们更喜欢在工作日还是周末购物,等等。
  • 体验细节:他们是否谈论过他们的体验(例如在社交媒体上),是积极的还是消极的,他们最*是否与客户支持人员交谈过,等等。

通过捕捉人口统计、交易、购买行为和体验等所有这些方面的细节,营销人员将开始深入了解客户。除此之外,这种做法还有助于确定客户的“钱包大小”——类似于定量评估他们在你销售的产品类型上可能会花多少钱。你也可以开始初步了解是什么让他们这么做的——他们喜欢打折还是免费?他们是只为自己还是家人购买?他们通常买很多小东西还是去大采购?

虽然忠诚度计划本身是一个独立的话题,但有必要提及的是,在入职阶段,将客户注册到忠诚度*台可能非常有用——这不仅能够实现更丰富的数据采集,还有助于建立客户粘性——这是整个入职阶段的主要目标。

第三阶段:增长

目标:最大化每个客户的潜在收入。

市场营销人员最喜欢的客户生命周期阶段!客户已经进来了,他们已经尝试和测试,并喜欢他们所看到的,你们都很好地理解对方,一切都很好。他们会更频繁地购买更多的东西,从而增加他们在你身上的总支出。因此,这一阶段的挑战是,随着客户的成长,如何增加他们自己的支出。

为了实现这一点,营销人员专注于优化他们的营销活动,以便针对每个客户,他们能够击中所有正确的触发器。

Image 2: Getting it Right!

有许多分析方法可以用来设计活动。让我们来关注这样一种方法,它经常被使用并且被发现非常有效——聚类分析。前提很简单:

  • 通过某种形式的聚类模型识别行为相似的客户,即构建聚类 DNA

Image 3: Identifying Different Clusters and Cluster DNA

  • 将每个个体客户的 DNA 与其集群的 DNA 进行比较,并根据个体客户偏离集群行为的地方采取行动。

Image 4: Cluster DNA vs. Customer Behavior

也可以应用其他模型和方法,以便为每个客户确定正确的触发因素。事实上,一项活动的有效性是通过利用一整套分析技术而不是专注于任何一种方法来最大化的。

阶段 4:衰落和损耗

目的:识别客户流失的【预警信号】,并及时采取干预措施,重新吸引流失的客户。

生命周期的这个阶段经常得不到应有的关注,这很不幸。经常被忽视的事实是,重新获得一个失去的客户的成本几乎与获得一个新客户的成本一样高,而挽救一个逐渐消失的客户的成本要低得多。

早期预警信号可以通过多种方式表现出来,理想的目标应该是发出危险信号并进行干预。衰落信号的一些例子:

  • 客户总支出下降
  • 购买频率降低
  • 减少客户购买的典型产品篮
  • 负面客户体验
  • 类似于过去流失的其他客户的行为

虽然最基本的营销用例仍然是关于获取客户、增加参与度和防止流失,但营销人员当然可以通过利用数据科学或人工智能驱动的应用程序来实现多个其他目标——情感分析、产品捆绑、定价优化、忠诚度分析等。举几个例子。

随着技术工具(如客户关系管理系统、忠诚度*台、活动管理工具、复杂的销售点系统等)的激增。)围绕客户接触点捕获丰富数据的可能性很大。这个数据是营销人员的金矿。使用它,结合强大的数据分析支持的战略,提供了大量的机会来激发组织内营销职能的效力。我们只是触及了表面——可能性是无限的!尤其是一旦机器学习驱动的人工智能应用开始成为营销人员工具包的主流。

利用数据科学帮助女性做出避孕选择

原文:https://towardsdatascience.com/using-data-science-to-help-women-make-contraceptive-choices-8673eb9cdbfd?source=collection_archive---------10-----------------------

你或你认识的人是否曾花数小时担心什么样的避孕药最适合你,并想知道它们的副作用是什么?你是否浏览过无数的在线论坛,试图了解其他女性对避孕药的感受?我自己也经历过这种情况,所以在为期 4 周的洞察数据科学项目中,我决定开发一个工具来帮助女性做出这些明智的决定!我从波士顿洞察研究员和项目总监那里学到了很多,没有他们我不可能开发出这个应用!

我的 webapp 是为了做三件事而构建的:

  1. 根据其他女性使用的避孕方法,向女性推荐避孕方法
  2. 分析其他女性对每种避孕药的副作用的感受
  3. 显示与避孕药相关的最热门的话题

让我们来分解一下这三个部分。

第一步:建议避孕

我的目标是能够根据其他像她们一样的女性使用的避孕方法向她们推荐避孕方法。为了做到这一点,我使用了全国家庭增长调查中几年的数据。该调查是分批进行的,每一批都跨越 3-4 年的收集数据(2006 年至 2015 年)。这项全国性调查包含来自妇女的报告信息,包括她们的人口统计数据和她们当时使用的避孕药具。一旦我把每次调查的数据合并成一个熊猫的数据框架,我采取了一些步骤来清理它。

数据清理:

  1. 更改了避孕药的名称,以匹配不同批次的采集。例如,“植入”和“Nexplanon 和 Implanon”被简单地改为“植入”
  2. 删除各个字段中带有 NAs 的行

清理之后,我只剩下了大约 12000 名女性的数据。

探索性数据分析:

我决定从一些探索性的数据分析(EDA)开始。下面是一些图表,显示了每种避孕药具的使用者人数,以及按年龄组分列的每种避孕药具的直方图。

Number of Users of Each Contraceptive Type

Examples of Contraceptive Use by Age

显然,一些避孕药比其他的更受欢迎,使用更频繁,导致了阶层之间的不*衡。我们可以尝试在项目的建模部分解决这个问题。

特点:

一些特征包括年龄、种族、婚姻状况、伴侣数量等。我对我想要制造的工具想了很久,并且知道除非使用我的工具的妇女输入所有必要的信息,否则我将无法推荐避孕药,并且询问性伴侣的数量将会太具侵犯性。出于这个原因,我选择在我的模型中只包含三个特征:年龄、种族*和婚姻状况。因为有几种类型的婚姻状况(“分居”、“已婚”、“同居”、“丧偶”等)。),我将他们分为三个层次,概括了所有这些类型的关系——单身、已婚或恋爱中。此外,使用 sklearn 预处理对种族进行了一次性编码。

我们准备好做模特了!

*使用这个数据集的一个不幸的限制是只有三个种族——白人、黑人和西班牙裔。要么只有这些种族的妇女被包括在内,要么在调查的原始数据收集中妇女只有这三个种族可供选择。

建模:

最初,我试图创建一个模型,预测女性最有可能使用的避孕药,不管是哪种类型。然后,根据我的 Insight 技术顾问的一些有价值的反馈,我将避孕药分为两个小组——半永久性和非永久性——并为每个小组创建了两个模型。每个亚组有四种避孕药作为预测类,使用 sklearn 的模型选择将数据随机分为 80%的训练集和 20%的测试集。

由于这是一个多类分类问题,我从高斯朴素贝叶斯模型开始,而不是逻辑回归,后者往往在二元分类场景中做得更好。我决定在没有任何过采样或欠采样的情况下开始,看看基线模型会如何。

对于这两个亚组,GNB 模型比随机模型(0.60)具有稍高的准确性,在这种情况下,随机模型每次都会预测多数类(0.57)。然而,GNB 模型假设特征之间完全独立——在这里,我们知道年龄和婚姻状况肯定是相关的。为了考虑特征相关性,我使用的下一个模型是随机森林(RF),它的性能比 GNB (0.65)略好。我选择在产品中实现 RF,因为随着我们添加更多功能,它也可以轻松扩展。下面,你会看到一个半永久群体混淆矩阵的例子。

Confusion Matrix for Semi-permanent Contraceptives

显然,这些阶层是不*衡的。为了减轻这个问题,我使用了合成少数过采样(SMOTE from unbalanced-learn API imb learn;下图)来生成少数类中的一些数据点,以帮助更好地训练模型。SMOTE 通过基于少数类中的 k 邻居生成数据来工作。我考虑过对多数类进行欠采样,但意识到在我已经有限的数据集下,我将在更少的数据上训练我的模型。正如所料,测试集的准确性下降了,召回率没有提高。

An example of SMOTE

您可能会问,为什么我使用准确性作为度量标准来衡量我的模型的性能?我希望这个模型的预测能够反映出女性使用避孕药的真实情况。与欺诈检测和识别乳腺癌等二元分类场景不同,我不希望我的模型针对特定类别的精确度或召回率进行优化。在这种情况下,模型的准确性最好地捕捉了所有类的整体性能。因为这是我的目标,我选择保持我的原始随机森林模型,没有任何过采样。

此外,我注意到测试集的精度(0.65)几乎与训练集的精度(0.66)完全相同,这表明我需要更多的预测功能来提高模型的精度。

前进:

将来,随着手头有更多的时间和资源,我会寻找其他可能更能预测避孕选择的数据来源,如地理上与诊所的距离、收入水*等。我收到的反馈是,纳入对患有某些疾病的人的排除可能是有用的——纳入这一点很好,但我必须小心地在建议工具和医疗建议之间取得*衡。我还可以花时间调整随机森林的额外超参数,如树的深度、一片树叶的最小样本等,这将是更有效的预测功能。

第二步:分析避孕药的副作用

为了了解女性对各种节育方式的感受,我使用 pushshift.io Reddit API 搜集了 r/BirthControl 两年的帖子。这导致了大约 21,000 个职位。从每个帖子的正文开始,我使用了各种工具来清理文本。

正文清理:

  1. 删除停用词。为了确保围绕避孕药的情绪保持准确,我保留了自然语言工具包(NLTK)语料库中英语停用词集中的“否定”词。
  2. 通过删除 URL 和其他不必要的字符,但保留标点符号来标准化文本。

Code snippet to Standardize Text

3.使用 NLTK 中的 sent_tokenize 将标记化(分隔)的句子彼此分开。

4.词干单词删除其后缀,以便相同的单词不会被计算多次(即药丸成为药丸)。

一旦我把所有的句子都分离出来,我特别想看看那些提到了上述预测模型中使用的八种避孕方式的句子。我提取了中只有提到上述避孕药的句子,并将其细分到各自的熊猫数据框架中(即所有提到“药丸”的句子都进入“药丸”数据框架)。为了使情感分析尽可能准确,我只提取了提到感兴趣的避孕药的句子。因此,一个提到避孕药和宫内节育器的句子不会出现在避孕药或宫内节育器的数据框架中。虽然这减少了我必须处理的数据量,但它尽可能准确地分析了每个句子的情绪。

提取副作用提及:

我根据 FDA 网站上列出的潜在副作用,以及女性向我提到的其他副作用,列出了一个清单。使用这个列表,我创建了一个新的熊猫数据框架,包括每个句子以及是否提到了特定的副作用(1 或 0)。你可以把这想象成一个定制的“词汇袋”模型,计算某个副作用在某个关于避孕药的句子中被提及的次数。

情感分析:

我将 VADER(效价感知词典和情感推理器)包中的 NLTK 情感强度分析器(SIA)应用于每个句子。这种情绪分析器已经过社交媒体数据的预训练,并使用基于词典的方法,不仅考虑情绪的类型(消极或积极),还通过“极性得分”考虑所表达的情绪的强度。这里有一篇关于这个 SIA 是如何建造的以及它是如何运作的文章。

下面是代码和结果数据集的示例。

我能够:

  1. 相对于所有提及特定避孕药的句子,计算副作用提及的频率
  2. 对于每种避孕药,将“极性得分”乘以句子中提到的特定副作用。

这导致了我的最终数据框架,如下:

由此,我能够在 Dash 中使用 Plotly 构建我的应用程序的第二部分。

Screenshot of Side-Effect Portion of WebApp

验证 VADER

Insight 项目的一位主管给了我宝贵的反馈,说我的情感分析器没有经过验证是没有用的。他建议我让和其他洞察力研究员看着同样的句子,并给它们打分,要么肯定,要么否定,要么中立。为此,我首先将 VADER 的极性得分分成三个子集:

  1. 极性得分> 0.1 = 1(正)
  2. 极性得分< 0.1 = -1(负)
  3. 极性得分在-0.1 和 0.1 之间= 0(中性)

基于 VADER 和其他洞察研究员对大约 200 个句子的评价,我能够开发出下面的困惑矩阵:

显然,VADER 在将一个句子正确分类为积极、消极或中性方面做得比机会稍好,这对于以前不知道其他女性对每种避孕药及其副作用的感受的女性来说仍然是有价值的。

向前发展:

我能想到几种方法来改进产品的这一部分:

  1. 使用命名实体识别的形式来识别副作用,以全面了解所有经历的副作用。
  2. 从头开始构建情感强度分析器。首先,要让女性给句子贴上积极、消极或中性的标签。有了足够数量的这些带标签的句子,我可以使用分类模型训练一个基本的情感分析器。

步骤 3:提供相关的建议帖子

虽然该产品的前两个方面让女性了解了什么样的避孕药可能对她们有效,以及其他女性的感受,但她们可能仍会在网上论坛上花费数小时,试图更好地了解其他女性对这些避孕药的看法。为了避免这种情况,我决定使用主题建模来提供一些相关的 Reddit 帖子,供女性在应用程序中阅读。

主题建模是如何工作的?

主题建模是一种统计方法,用于发现文本语料库下的抽象“主题”。在这种情况下,特定主题建模技术可以使用 reddit 帖子内和所有 reddit 帖子之间的单词分布来创建主题,并将特定 reddit 帖子归属于特定主题。有一些很棒的文章描述主题建模技术(这里的、这里的和这里的),但是我将简要描述我选择的一个——潜在狄利克雷分配(LDA)。

LDA 是一个概率模型,本质上意味着它给出了一个事件的概率分布。相反,确定性模型会给出事件的单一结果。在主题建模的情况下,LDA 由两个矩阵组成(如下所示)——在主题中选择单词的概率,以及在 reddit 帖子中选择主题的概率。它使用一个词在文章中出现的频率来创建主题。

例如,假设我有三篇非常简单的文章:

  1. “狗猫香蕉”
  2. “香蕉香蕉香蕉”
  3. 《猫猫猫猫》

LDA 将记录单词在三篇文章中出现的概率,并基于这些分布创建主题。这里,主题 1 可以是“狗”,主题 2 可以是“猫”,主题 3 可以是“香蕉”。然后,LDA 会将帖子 1 分配为具有来自主题 1、2 或 3 的相等概率,而其他两个帖子几乎肯定分别来自主题 2 或主题 3。

用 Reddit 帖子实现 LDA

对于 webapp 的这一部分,我需要了解对于每种避孕药,女性中最流行的讨论话题是什么。此外,我需要显示与这个特定主题最相关的帖子。使用 LDA 帮助我提取了每种避孕药最受欢迎的话题,以及与该话题相关的前 3 篇帖子。步骤如下。

  1. 使用 sklearn 计数矢量器创建一个单词包模型

2.确定主题的数量(因为 LDA 本身不能自动这样做),并从 sklearn.decomposition 运行算法

3.显示生成的主题,指定帖子的数量

这让我可以在我的应用程序上显示来自 Reddit 的相关帖子:

虽然非负矩阵分解也是一个很好的主题建模工具,但当我尝试实现它时,它并没有在这个特定的上下文中产生可理解的主题。

主题建模的缺点:

不幸的是,使用主题建模有一些缺点。首先,你必须指定 k 个主题。我是怎么选择 10 作为题目数量的?老实说,我尝试了各种主题编号,10 产生的主题既不太宽泛也不太具体。第二,你必须给主题贴上标签——我从与宫内节育器相关的帖子中提取的最受欢迎的主题的一个例子是“只是月经来潮”。这在语义上没有什么意义,但我们可以看出它与月经的时间框架和痉挛的副作用有关。标签将帮助我们验证我们的主题建模是否正确地构建了主题并将帖子分组到这些主题中。

向前发展:

我很想在我的应用程序中建立一个反馈功能,允许女性标记主题,或对主题是否对她们有意义进行评级。

摘要

简而言之,我的希望是(在 4 周内)创建一个应用程序,它不仅可以向女性推荐避孕药,还可以分析其他女性对其副作用的看法,并为她们提供其他女性所说的相关信息。你可以点击查看整个 webapp 。我真的很高兴使用数据科学和机器学习来创建这样一个工具,在规模上,它可以帮助女性做出重要的决定。在创建这个 webapp 的过程中,我学到了很多东西,如果没有波士顿 Insight 研究员和项目主管的帮助,这是不可能的!!

如果您有任何问题或建议,请随时发表评论——我希望听到您的反馈!

用数据将用户推向你理想中的 UX

原文:https://towardsdatascience.com/using-data-to-nudge-users-towards-your-ideal-ux-e2918e63b4d3?source=collection_archive---------4-----------------------

选择指标如何帮助弥合产品的现实 UX 和理想 UX 之间的差距。

Source

产品设计通常是通过理想主义的视角来执行的。你的团队设计的用户界面和 UX 可能源于你脑海中的长期印象——用户如何看待你的产品并与之互动的乌托邦版本。如果你幸运的话,实际开发的版本将非常接*你的设想,尽管在这个过程中几乎总是要做出让步。(特别是关于 UX。)

尽管如此,你脑海中的形象仍在演变,以至于你会为你的产品的生产版本选定一个理想的 UX。无论是转化率、会话时长,还是其他形式的参与,你和你的团队都知道你的用户应该得到什么样的体验。

但是他们的经历并不完全是那样的。

介意差距

用户体验的现实往往与你和你的团队精心设计的理想版本不同。换句话说, r UX(现实版)和 i UX(理想版)之间是有差距的。虽然这种差距的存在并不出人意料,但如果你不确定缩小差距的最佳方式,这种差距可能会令人沮丧、不安,甚至令人生畏。

一旦你意识到存在 UX 差距,对你和你的团队来说,采取一些步骤是很重要的:确定差距实际在哪里(稍后会有更多内容),如果可以的话,确定是什么导致了差距,并开始考虑不同的方法来缩小差距。

例如:

  • 是否缺少一项产品功能来弥补这一差距?
  • 我们需要考虑一个程序(人,而不是技术)来改变用户的行为吗?
  • 如果是这样,我们是推他们…还是轻推他们…让他们做出我们想要的行为?

快速浏览一下上面的选项,你会发现功能开发的成本很高,把你的用户推进一个新的行为模式是有风险的。研究表明后者——轻推你的用户——可能是改变他们的行为并达到 i UX 的最有效方法。

点拨心理

轻推用户是什么意思?本质上,这意味着一点一点地改变他们的行为,这样随着时间的推移,他们会以不同的方式行事——希望对你的产品来说是一种更理想的方式。

关于推动行为的更多信息,请查阅理查德·塞勒和卡斯·桑斯坦的书《推动:改善关于健康、财富和幸福的决定》。

[## 推动:改善关于健康、财富和幸福的决定

对于马尔科姆·格拉德威尔的眨眼和诺贝尔奖得主丹尼尔·卡内曼的思维快慢的粉丝来说,一个启示性的新…

www.amazon.com](https://www.amazon.com/Nudge-Improving-Decisions-Health-Happiness/dp/014311526X)

你希望他们做出的行为重定向可以来自不同的、或许更有限的选择,这些选择将他们引导到更一致的行为模式中,向他们提供或展示一个隐喻性的胡萝卜,将他们(和他们的行为)引向特定的方向,甚至实施更一致的沟通策略,包括入站和出站渠道。

(微调策略的列表是无穷无尽的,对你来说最好的策略都取决于你的产品和你试图缩小的差距。)

试图用一次产品变化来打动你的用户是不明智的。相反,最好的办法可能是一点一点地把他们推向你心目中的理想 UX。

以数据为导向

不管你选择什么样的策略来弥补你的产品的 UX 差距,最好用数据来确定差距到底在哪里。您和您的团队可能对正在发生的事情有很好的感觉,但是使用可量化的指标将确保您将精力集中在正确的地方。

您的 i UX KPI 可能足以弥补您产品 UX 的差距,也可能不足。许多企业家将虚荣心指标视为 KPI,但像“每日活跃用户”或“流失率”这样的东西可能过于宽泛,无法帮助缩小 UX 差距。

你的团队设计的用户界面和 UX 可能源于你脑海中的长期印象——用户如何看待你的产品并与之互动的乌托邦版本。

使用数据来弥补 UX 差距的关键是使用描述你的产品的清晰度指标。清晰度指标是构成顶级虚荣心指标的运营指标。像你的产品每天实际使用的分钟数这样的事情更能说明 UX 差距,可能会给你更多切实的 UX 互动来关注。(又名:哪里轻推你的用户。)

(如果您还没有产品的 i UX 的 KPI,请先建立这些 KPI。这可能需要一些市场研究,以确保您与其他类似产品保持一致,但是拥有良好的清晰性指标 KPI 将允许您测量 UX 差距,并监控您努力缩小差距的有效性)

一旦你使用了正确的清晰度指标来监控 UX 差距,你就可以开始开发一些方法来推动你的用户,从而消除 UX 差距。希望用户每天使用你的产品的时间更长吗?首先要想出种方法来推动他们,让他们多增加 5%的时间。这些推动努力的累积效应——如果集中在正确的地方——将会缩小你的产品的 UX 差距。

有形的外卖

这里有 5 个使用数据将你的用户从你产品的 r UX(现实版)推向 i UX(理想版)的关键。这些要点将帮助您的团队确定工作的优先顺序,并弥补您产品中的 UX 差距:

  • 深入表面,定义你的清晰度指标

使用数据识别和弥补产品 UX 差距的真正价值在于产品的清晰度指标。关于清晰度度量值的更多信息,这里有一篇很棒的文章。

  • 跟踪测量这些指标所需的数据

为您的产品建立和/或确保正确的清晰度 KPI,并确认您的生产数据库或 SaaS 包含您测量产品 UX 细节所需的数据。

  • 优先考虑你的努力

您可能有不止一个 UX 差距需要解决,确定哪个更重要将有助于您确定团队工作的优先级。要决定哪一个是最重要的,比较你的团队定性的想法和通过数据揭示的最大差距。如果关闭/修复,哪个差距会产生最大的影响?(如果“最大的”差距是相对低影响的特性,那么它可能不是最佳选择。)

  • 调查你的用户以证实你在数据中看到的

用户研究对产品开发至关重要,虽然它通常发生在产品发布之前,但在产品发布后很长时间内使用相同的程序来证实您通过数据看到的差距非常有用。顺便说一下, 用户研究有多种形式——不仅仅是调查等。

  • 选择正确的时间框架

当你开始解决你的产品的 UX 差距时,在一个现实的时间框架内监控有效性是很重要的。这似乎是显而易见的,但很容易太快或太频繁地深入细节。在弥补产品的 UX 缺口时,森林往往比树木更重要。

使用数据可视化快速回答业务问题

原文:https://towardsdatascience.com/using-data-visualizations-to-quickly-answer-business-questions-de815be0ede0?source=collection_archive---------19-----------------------

学习如何交流从数据中获得的洞察力是你能拥有的最重要的技能之一。通常,交流数据信息的最引人注目的方式是可视化。但是,构建伟大的数据可视化的关键是让它们能够回答你想要回答的问题。

例如,假设我开了一个博客,我想知道我哪个月的流量最大。

我可以使用一个汇总表,基本上列出了每月的流量和数量。就像下面的表格,但是它的问题是,它不能帮助我很容易地比较每个月的流量。

但是这次绘制同样的数据,把它扩展到 12 个月的流量的条形图或帕累托图。显而易见,11 月和 7 月的流量最高。而一月最少。

Bar Chart

Pareto Chart

条形图或帕累托图最好地捕捉了每月的流量分布,尤其是帕累托图。帕累托图按照流量从高到低的顺序排列月份。每个条形代表特定月份的流量。

如果我想知道流量是否随着时间的推移而增加,最好的图表是折线图。

Line Chart

这里显示的是相同的信息,但更容易看到的是,从条形变为线状,整体流量似乎在增加。如果我有多年的数据,折线图也将有助于确定特定月份的流量是高于还是低于其他月份。也许一月总是低的,而十一月总是比一年中的其他月份高。

让我们试着回答更多的商业问题

我有多年的数据,我想知道访问者数量的分布情况,例如:

  1. 一个月内有超过 200 名访客的频率是多少?
  2. 最常见的访客人数是多少?

Histogram

无论是从条形图还是折线图来看,这都很难判断。这两个问题都不是为了理解时间成分。我对具体的计数感兴趣。

访问者数量的柱状图有助于更好地了解一个月内的典型访问者数量。条形图的高度告诉我一定数量的访问者出现的频率。

在博客上看到 500 个访问者的情况很少见吗?我能很快看出 500 是很少的。我也能看到总有 200 多的访客,但很少有超过 1167 人的。

最常见的访客数量在 321 到 442 之间。在条形图或帕累托图上很难看到这些观察结果。

同样,由于数据中的时间成分,折线图可能是最好的,但它最终取决于您想要传达的信息。用同样的数据,我只是找到了三种呈现数据的方式。可视化数据的正确方式是最能帮助你回答问题的方式。

分类变量

当观察一段时间内的变量或比较两个定量变量时,用于可视化这些情况的选择被标准化为折线图和散点图。然而,当您将分类变量引入可视化时,更多的选项现在变得可用。以及如何可视化分类变量之间的关系以及分类变量和定量变量之间的关系。

例如,我想知道三个地方的顾客最喜欢的可口可乐产品。为了比较两个分类变量,我可能会使用类似并排条形图的东西,显示一个类别的分组。在这种情况下,芬达、雪碧和可口可乐按照另一个变量的颜色分组,在这种情况下是三个位置。我可以快速识别每个地点最喜欢的汽水。中环芬达,西区雪碧,东区可乐。

Side-by-Side bar chart

如果我有两个以上的变量,比如我想查看不同产品在一段时间内的销售额,这里我有三个变量:销售额、时间和产品。我可能会从折线图开始,因为我在和时间打交道。然后,我可以将每种产品分成不同的系列。给线条着色并添加图例以提供产品名称。现在,我可以看到哪种产品表现良好,这可以帮助我做出更多针对具体产品的决策,而不是只看总体销售额。

Line Chart

在这种情况下,我还可以使用基本堆积面积图或 100%堆积面积图。当您想要显示部分到整体关系随时间的变化时,堆积面积图很有意义。视觉效果提供了基本相同的信息,但在 100%堆积面积图中,每种产品都以占总销售额的比例显示。

与基本堆积面积图不同,100%堆积图结果显示总销售额,以及每个产品线对总销售额的贡献。

Basic Stacked Area Chart

100% Stacked Area Chart

另一种方法是使用按年份排列的堆叠条形图。每个产品在条中都有一种颜色,条的高度就是销售额。

Stack Bar Chart

通过折线图、堆积折线图和堆积条形图,让我们来看看使用每个图表可以轻松回答的一些问题。

问题

  1. 哪种产品 1-7 月销量增长最快?

这在其他一些图中很难看到,但在折线图中更容易看到。产品 3 和其他产品一样起步缓慢,但在 4 月至 7 月间有所增长。

2.产品 1 在哪一个月的销售额超过 50%?

从百分比堆积面积图中,您可以看到产品 1 在二月份的销售额超过了 50%。同样,选择图表要基于它对你回答问题的帮助程度。

3.总销量曾经超过 100 台吗?

是的在 11 月!基本堆积面积图或堆积条形图都适合这个问题。因为它们清楚地显示了这三种产品每个月的总销售额。

总之,构建信息丰富的数据可视化在很大程度上取决于您对现有绘图类型的理解以及您试图强调的洞察力。您使用的可视化方式还取决于您正在处理的数据类型,以及您希望在单个绘图中查看的数据集中有多少列。

利用深度学习克隆驾驶行为

原文:https://towardsdatascience.com/using-deep-learning-to-clone-driving-behavior-51f4c9593a57?source=collection_archive---------1-----------------------

在我关于自动驾驶汽车和相关的 Udacity Nano degree 项目的上一篇帖子中,我写的是深度神经网络在交通标志分类中的应用。这一次,我将使用深度神经网络方法来模仿人类的驾驶行为(在这种特殊情况下,在模拟器中驾驶汽车)。

项目目标

这里的总体思路是通过在模拟器中驾驶汽车来收集训练数据,然后用这些数据训练深度神经网络,最后让汽车由深度神经网络生成的模型来驾驶。

You can find the simulator git repo here

训练数据分析

Udacity 已经提供了一些预先录制的圈数,但我决定自己用模拟器玩一玩。所以我在赛道的每个方向记录了 5 圈。为了避免深度神经网络偏向于转向道路的左侧,两个方向都是需要的。

该记录产生了 36 534 个捕获的图像。图像包含从汽车上的三个摄像头捕获的数据:左,中,右。

Captured images from left, center and right camera from the car

为了训练的目的,我只使用了中央摄像头,这足以获得非常好的最终效果。为了使模型更通用,建议对汽车使用所有三个摄像机,以便能够更好地处理返回轨道中心的场景。

当使用多个摄像机时,重要的是要记住,左右摄像机的转向角需要用一个常数进行适当调整。

Multiple camera capturing

训练数据还包含 CSV 文件,该文件包含带有时间戳的图像捕获以及转向角、油门、刹车和速度。

CSV file contains the metadata from the training data

由于训练数据包含两个轨道方向上的圈数,因此转向角没有偏差:

80%的数据用于培训,20%用于验证。所有的训练数据都可以在这里找到。

数据扩充和预处理

为了进一步增加训练数据集的大小,我将每张图像都绕水*轴翻转。

在这种情况下,图像的预处理是在模型本身中完成的,因为与 CPU 相比,在 GPU 上完成的成本更低。我从每张图片的顶部裁剪了 50 个像素,从底部裁剪了 20 个像素,以去除图片中不必要的噪声(汽车的前部,天空,树木等)。).

模型架构

我实现了来自英伟达论文的深度神经网络架构:自动驾驶汽车的端到端学习在 Keras 后台运行 TensorFlow 。这是一篇优秀的论文,如果你更了解这种深度神经网络在现实世界中的应用,我建议你通读一下。

以下是 NVidia 在现实生活中基于上面的架构运行相同模型的汽车的短视频:

深度神经网络本身获取输入图像(160 x 320 x 3)。在最开始,它包含标准化和裁剪层。接着是 3 个卷积层,步长为 2x2,内核为 5x5。随后是额外的 2 个无跨距卷积层和 3×3 内核。卷积层连接到三个完全连接的层,从而产生一个输出控制值。用 RELU 函数在所有网络层之间引入非线性。ADAM 用于我们的学习率。

Deep neural network architecure used from NVidia’s paper

辍学层是没有必要的,因为我没有注意到在培训期间任何重大的过度拟合。

培训和最终结果

训练在配备了 GPU 的 Amazon EC2 实例上进行。训练完成后,赛车能够自己完成赛道:

结论

这绝对是本课程迄今为止最有趣的项目。我的计划是将从这个项目中学到的知识应用到现实生活中的遥控汽车上,并在我的公寓里建造一个小型赛车道,在那里我可以训练它自动驾驶。

项目可以在我的 Github repo 上找到:

[## 行为克隆 P3

行为克隆-P3-uda city 行为克隆项目的启动文件

github.com](https://github.com/bdjukic/CarND-Behavioral-Cloning-P3)

使用深度学习来估计咖啡收成

原文:https://towardsdatascience.com/using-deep-learning-to-estimate-coffee-harvest-yields-8edb1b94c698?source=collection_archive---------10-----------------------

我前阵子写过一篇旧文章,讲的是用 OpenCV 检测成熟的水果。虽然简单的颜色检测器是计算机视觉的有趣入门,但有时我们的问题需要更多的复杂性和前瞻性思维。因此,深度学习允许我们开发一种健壮的方法来解决计算机视觉中的大多数问题。我将在本文中使用的算法称为 Mask R-CNN。

Kauai Coffee Company. Source: Hawaii Coffee Association

全球的咖啡果园在很大程度上依赖于手工计算树枝上成熟和未成熟咖啡果的数量,以估计收获时间。根据这个简单的指标,需要大量的专业知识来对何时收割做出更快、更有根据的估计。错误可能会使公司在某一特定领域失去丰收。收获少,钱少。

How many cherries can you count? Now, how long should we wait until harvest?

培训计算机

如果你不熟悉机器学习,对于这种类型的问题,你只需要知道一件事。没有它,我们将不得不手工编码这些咖啡果的每一个特征,以便被程序识别。无论你怎么说,都有太多的代码要写,而且咖啡果不能*似为绿色的圆圈(我也绝对没有这个想法)。

因此,我们采取以下方法:

  1. 给我们感兴趣的物体拍大约 100 张照片
  2. 手绘标签/注释~30 张图片
  3. 把图像输入我们的网络
  4. 评估模型
  5. 重复这个过程,直到我们能够以 90%以上的准确率检测到我们的目标。
  6. 额外收获:让我们的模特给我们贴上新图片标签

屏蔽 R-CNN

这篇文章的目的是面向这种算法的应用,所以如果你对如何网络功能感兴趣,请查阅原始论文。简单来说,这个算法返回对象的位置和组成它的像素。非常适合能够:

  1. 确定咖啡果的位置/数量(边界框)
  2. 确定每个咖啡果的颜色(图像分割)。

Network architecture. Source: https://arxiv.org/abs/1703.06870

VGG 图像注释器(VIA) 可能是我发现的最好的多边形对象注释工具。他们更新了一些功能来保存项目,加载以前的注释等。在这种情况下,注释对象需要长的时间。在这个阶段很容易陷入不确定性:我真的应该注释所有这些图片吗?通常需要这么长时间吗?如果不行呢?

是的。绝对的。忍忍吧。我们打败了苏联,登上了月球,却不知道它会成功。回到注释咖啡果。

This really is the hardest part of the process.

花了大约 4 个小时来注释所有这些图片,这个方法必须有效。对吗?最简单的测试方法是通过迁移学习和其他人对算法的实现。如果需要,可以对模型进行微调和调整。不要感到羞耻。

马特波特的人们有很好的基础可以利用。这里是 github 回购。

结果呢

在与 Amazon Web Services 和包依赖问题进行了无休止的斗争之后,最终结果如下:

Trained model in the wild.

This is art.

一点也不差,尤其是考虑到它工作所需的图片数量很少。下一步将是通过在类似于其应用的设置中拍摄更多照片来完善该模型,并最终将其部署用于一般用途。

如果你喜欢这篇文章,一定要关注我,了解机器学习和计算机视觉在农业中的更多应用。如果您有任何问题,请留言或发电子邮件至 jamesthesken@gmail.com 给我。

—詹姆斯

利用深度学习生成攻击性车牌

原文:https://towardsdatascience.com/using-deep-learning-to-generate-offensive-license-plates-619b163ed937?source=collection_archive---------8-----------------------

将丰富的语料库与 R

如果你已经在互联网上呆了足够长的时间,你就会看到由深度学习算法生成的优质内容。这包括在乐队名称、视频游戏名称和神奇宝贝上训练的算法。作为一名想要跟上该领域现代趋势的数据科学家,我认为没有比找到一个有趣的主题来生成文本更好的方式来学习如何使用深度学习。有了这样做的愿望后,我等了一年才找到合适的数据集来做这件事,

我偶然发现了亚利桑那州禁止牌照的名单。这份名单包含了所有的个性化牌照,人们要求,但被亚利桑那州汽车部门拒绝。这个数据集包含超过 30,000 个车牌,这为深度学习算法提供了一组很好的文本。我将数据作为文本包含在我的 GitHub 库中,这样其他人就可以选择使用它。不幸的是,数据来自 2012 年,但我有一个活动的公共记录请求亚利桑那州更新名单。我强烈建议你看一看,它非常有趣。

下一步是实际了解深度学习是如何工作的,并编写代码。因为我的大部分工作都是在 R 中完成的,所以我希望使用它,谢天谢地,Rstudio 有一个叫“keras”的包,它使这变得很容易。虽然这个工具本身很容易使用,但我不得不通过仔细阅读互联网,自己拼凑出一个关于深度学习的介绍。现在回想起来,我大概应该只买一本书。这篇文章的其余部分是我对我所学到的东西的总结,以便其他人可以阅读它,并找出如何生成他们自己的有趣文本。如果你想看我的实际代码,请查看我的 GitHub 库。

深度学习如何用于文本生成的口语化介绍

当人们谈论使用深度学习来生成文本时,他们几乎总是指的是递归神经网络(RNN)。这是一种特殊形式的人工神经网络,可以很好地处理数据点序列(例如,书中的单词序列)。忽略这背后的数学,想法是给定一个单词序列,例如“这是一个单词序列的无聊例子,”我们可以训练一个模型,根据序列中的单词预测序列中的单词(以及单词的顺序)。因此,在选择下一个单词之前,我们选择少量的前一个单词来考虑。如果我们之前的单词数是 3,那么我们的小序列将创建一个看起来像这样的数据集:

由于递归神经网络不能处理单词,而是需要数字,所以我们任意将每个单词分配给一个数字。例如,a = 1,boring = 2,this = 7,等等。那么我们的数据就变成了:

但不幸的是,即使这样,对 RNN 来说还是太复杂了。我们需要通过将每个数字转换成一个二进制向量来将它表示为一个分类变量。例如,我们可以将 7 个单词中的第 5 个编码为长度为 7 的二进制向量,只有第 5 个元素为 1。(0,0,0,0,1,0,0).如果我们对整个数据集这样做,我们会得到:

这是 RNN 可以研究的数据。该模型将适合它,然后我们可以给它一组前三个单词,让它猜下一个单词是什么。由于有许多可能的下一个单词,最终发生的是模型产生所有可能单词的组合,这些单词具有不同的权重,加起来等于 1。这些代表每个单词成为下一个单词的概率:

An example of a prediction generated from an RNN

为了让生成一个单词序列,我们选择三个单词作为起点,然后从模型预测的每个单词的概率中抽取第四个单词。例如,在上面的示例数据中,如果我们使用预测的下一个单词分布作为一组可能单词的权重,我们可以从样本中提取。如果我们画出与单词“boring”相对应的第二个元素,它将是序列中的下一个单词。然后,我们将它放入序列中,并使用序列中最*的元素来生成第五个单词,依此类推。

设置牌照数据

对于牌照数据,我们必须对这个主要思想进行一些修改。

  • 这里的“单词”是指盘子里的字母和数字(不是完整的单词)。
  • 由于车牌可能不是全长的,我们想知道何时停止它。因此,我们在每个牌照上附加一个终止字符'+'。因此板块 ABC001 变成了 ABC001+。如果在生成新的牌照时,我们生成了符号“+”,这就意味着我们需要停止这个序列。
  • 我们用于训练数据的序列是数据中每个*板的子序列。例如,如果 ABC001+在数据中,我们希望在(A → B,AB →C,ABC →0,…)上训练模型。因为每个训练数据序列的长度必须相同,所以我们在开头填充数据(A → B,AB →C, * * * * ABC→0,…)。我们从每个板中生成所有序列,并将它们放入一个大的训练集中。

对张量流使用 R 和 Keras

我最终使用了三种相互叠加的不同技术来运行这个模型。这些术语经常出现,所以最好能清楚地区分每一个:

  • TensorFlow(基础技术):TensorFlow 是一组开源的库,用于运行深度学习算法。它非常强大,但是直接部署起来有点麻烦。
  • Keras (Python API): Keras 是一个 Python 库,它使得 TensorFlow 更容易使用。它消除了设置和部署 TensorFlow 的所有麻烦,并真正使深度学习对 Python 用户可用。
  • keras (R 包):这是 RStudio 的包,允许你在 R 中使用 keras 而不是 Python。这不是 Keras 本身,而是 Keras Python 库之上的一个包装器。好消息是它工作得非常好,遵循现代 R 编程原则,并且易于安装。坏消息是,它是一个包装上的包装,所以有时寻求帮助并不容易。但是据我所知,在 Python Keras 中可以做的任何事情在 R Keras 中也可以做。

通过遵循 keras 包的文本生成示例,我弄清楚了这些东西是如何工作的。我一行一行地运行他们的代码,以了解它是如何工作的,然后为我的车牌项目修改它。要让代码运行起来,你需要安装 TensorFlow 和 Python, Rstudio 包会帮助你。

他们的示例文本生成代码实际上只做了几件关键的事情:

  1. 加载示例文本数据并进行任何必要的格式化。在我的例子中,我需要添加上一节中的牌照修改。
  2. 创建单词序列以用作训练数据,并将它们格式化为三维数组 x。数组的维数是:数据来自哪个序列,我们引用序列中的哪个元素,以及哪个单词。元素 X[i,j,k] =1 如果序列 i 在第 j 个字中作为 k. 预测被存储在一个二维数组 y 中。
  3. 对数据运行 keras 模型。当指定一个模型时,你需要列出不同层的神经元来创建一个人工神经网络。老实说,我几乎不知道如何制定一个“好的”规范,所以对于我的代码,我使用了与 Rstudio 示例相同的规范。为神经网络选择层的艺术感觉是整个过程中最不清楚的部分,我希望了解更多。如果你是第一次尝试编写自己的深度学习代码,我建议借鉴正在解决类似问题的其他人的规范。
  4. 使用创建的模型生成单词,并从这些单词创建新的序列。

一旦我让模型工作了,我就把一堆随机生成的盘子扔到一个图像里。这个项目总共花了我大约 8 个小时,如果我的代码中没有一些一个接一个的错误,这个时间会更快。我对结果非常满意,并对整个过程的简单明了感到惊讶。如果我知道会这么容易,我几个月前就做了。如果你对深度学习感兴趣,我强烈建议你获取一个文本语料库,并尝试自己生成新文本。它教会了我很多关于这个过程的知识,我觉得自己更有能力将深度学习用于更高级的项目。

代码是 GitHub 上的,如果你对我做过的其他项目感兴趣,请查看推特混搭或我的 F#物联网按钮。

利用深度学习改进 FIFA 18 图形

原文:https://towardsdatascience.com/using-deep-learning-to-improve-fifa-18-graphics-529ec44ea37e?source=collection_archive---------0-----------------------

Comparison of Cristiano Ronaldo’s face, with the left one from FIFA 18 and the right one generated by a Deep Neural Network.

游戏工作室花费数百万美元和数千个开发小时来设计游戏图形,试图使它们看起来尽可能接*现实。虽然图形在过去几年看起来非常逼真,但仍然很容易将它们与现实世界区分开来。然而,随着使用深度神经网络的图像处理领域取得的巨大进步,是时候我们可以利用它来改善图形,同时减少创建图形所需的工作了吗?

让我们试着用游戏 FIFA 18 来回答这个问题…

足球(即英式足球)是我最喜欢的运动,FIFA 成为我所有深度学习实验的自然选择。为了找出深度学习的最新发展是否可以帮助我回答我的问题,我试图专注于使用(in?)著名的 deepfakes 算法。它是一个深度神经网络,可以被训练来学习和生成极其逼真的人脸。我在这个项目中的重点在于从游戏中重新创建玩家的面孔,并改进他们,使他们看起来完全像真正的玩家。

注: 这里的 很好的解释了 deepfakes 算法是如何工作的。TL;博士版本:它可以使用自动编码器和卷积神经网络将视频中任何人的脸与其他任何人的脸交换。

收集培训数据

Unlike the game developers, I could collect all required data from Google search without having to trouble Ronaldo with any motion-capture fancy dress.

让我们先看看 FIFA 18 中设计最好的面孔之一,克里斯蒂亚诺罗纳尔多的面孔,看看我们是否可以改进它。为了收集 deepfakes 算法所需的数据,我只是从游戏中的即时重放选项中记录了玩家的面部。现在,我们想把这张脸换成 c 罗的真实面孔。为此,我从谷歌上下载了一堆图像,这些图像从不同的角度清晰地显示了他的脸。这就是我们开始模型培训过程所需要的全部内容。

模型架构和培训

deepfakes 算法涉及被称为自动编码器的深度神经网络的训练。这些网络用于无监督学习,并具有编码器和解码器,编码器可以将输入编码为称为“编码”的紧凑表示,解码器可以使用该编码来重建原始输入。这种架构迫使网络学习输入的底层分布,而不是简单地鹦鹉学舌般地重复输入。对于作为输入的图像,我们使用卷积网络作为编码器,使用去卷积网络作为解码器。这种结构被训练以最小化无监督学习的重建误差。

对于我们的例子,我们同时训练两个自动编码器网络。一个网络学会从 FIFA 18 图形重现罗纳尔多的脸。另一个网络学会了从罗纳尔多的真实照片中重建面孔。在 deepfakes 中,两个网络共享相同的编码器,但使用不同的解码器进行训练。因此,我们现在有两个网络知道了罗纳尔多在游戏中和现实生活中的样子。

First autoencoder network learning from FIFA graphics

Second autoencoder network from learning actual pictures

当在其他人脸上使用预训练模型进行训练时,在 GTX 1070 上,总损失在 4 小时内从大约 0.06 下降到 0.02。在我的例子中,我在原始的 CageNet 模型上继续训练,该模型已经被训练成生成 Nicolas Cage 的脸。

使用训练好的模型来交换面部

现在有趣的部分来了。该算法能够通过采用一种巧妙的技巧来交换面孔。第二个自动编码器网络实际上由第一个网络的输入馈入。通过这种方式,共享编码器能够从 FIFA face 获得编码,但是解码器使用这种编码来重建真实的 face。瞧,这个设置只是把国际足联的脸转换成了罗纳尔多的脸。

The second network converting FIFA face to real face of Ronaldo

结果

下面的 GIF 显示了在其他玩家脸上运行该算法的结果的快速预览。我认为进步是惊人的,但也许我有偏见,所以你来判断。

Comparison of FIFA 18 vs deepfakes faces for Ronaldo, Morata and Ozil.

更多这样的视频格式的结果可以在我的 YouTube 频道上找到,视频嵌入在下面。如果你喜欢这个视频,请订阅我的频道。

我们可以用这个算法把自己放在游戏里吗?

Me as Alex Hunter. To turn it completely into myself, all that’s needed is the ability to add longer hair, match the skin and make the biceps bigger.

如果你能以自己的身份玩游戏的“旅程”模式,而不是以亚历克斯·亨特的身份玩,会怎么样?你所要做的就是上传一分钟长的视频,然后在几个小时内下载训练好的模型。好了,你现在可以以自己的身份玩全程模式了。这将是下一个层次的沉浸式游戏!

它擅长的地方和需要更多努力的地方

我觉得我们用这种方法得到的最大好处是令人惊讶的逼真的面孔和图形,很难与现实世界区分开来。所有这些只需要几个小时的训练就可以实现,相比之下,游戏设计师用目前的方法需要几年时间。这意味着游戏发行商可以更快地推出新游戏,而不是花费数十年时间进行开发。这也意味着电影公司可以节省数百万美元,这些钱可以用来雇佣像样的故事作家。

到目前为止,最明显的限制是这些人脸是事后生成的,就像电影中的 CGI 一样,而游戏要求它们实时生成。然而,一个很大的区别是,一旦模型被训练,这种方法不需要任何人为干预来生成结果,唯一阻碍它的是生成输出图像所需的计算时间。我相信用不了多久,我们就会有重量轻、不太深的生成模型,可以在不影响输出质量的情况下运行非常快,就像我们现在有 YOLO 和 SSD MobileNets 用于实时对象检测一样,这是 RCNNs 等以前的模型所无法实现的。

结论

如果像我这样没有图形设计经验的人可以在几个小时内做出改进的面孔,我真的相信,如果游戏开发商在这个方向上投入巨资,它可以在不太遥远的未来改变游戏行业的面貌(是的,是有意的)。现在,如果 EA sports 的任何人正在阅读这篇文章…

使用深度学习解决网站所有者的常见问题

原文:https://towardsdatascience.com/using-deep-learning-to-solve-common-problems-of-website-owners-16d776fd34bd?source=collection_archive---------10-----------------------

作为一名数据科学家,我在一家管理三代网站建设*台的公司工作。这个行业启发我们的是,已经有超过 18 亿个网站,89%的企业家声称网站是吸引客户的最有效工具——比社交媒体或移动应用程序有效得多。

如果你看看这篇文章,你会发现这部分网站仍有很大的增长潜力。增长的因素之一是当前网站建设工具的简单性。这种简单是由技术支持的。

技术对不断增加的网站数量有很大影响。

但是随着技术的过时,用它们建立的网站也会过时。

举个例子。Flash 技术在 21 世纪初被广泛用于网站动画,现在被官方宣布为过时——2020 年甚至被宣布为其“到期日”。采用 HTML5 作为新标准已经三年了,然而,许多网站所有者没有时间将他们的网站升级到 HTML5 和其他现代趋势。

因为企业家必须专注于他们的事业。

考虑到这一点,机器学习、深度学习和人工智能开始改善我们创建、更新和维护网站的方式。

让我们看看 AI 到目前为止取得了什么成就

技术在处理业务相关任务时是否足够高效?尽管我相信你已经知道人工智能变得更高效的例子,但我想强调一下最新的、最令人印象深刻的例子,如图像分类和阅读比赛,它们证明了机器可以超越人类。

今天,人工智能经常被训练来减少你测试设计想法所需的时间。

LogoJoy 是一项服务,它会问你问题,试图了解你的偏好,然后为你生成名片、商标和其他东西的可视化效果,该服务已经声称它帮助了超过 160 万用户。去年, pix2code 展示了设计师可以用一个生成 HTML 代码的工具将他们的草图转化为交互界面。

已经有几十个概念和测试项目可以帮助业余爱好者和设计师创造几乎所有类型的数字对象。我们的同事兼朋友 Yuri Vetrov 收集了一些人工智能在网页设计中的应用实例——请随意查看。

现在想象你有一个商业网站

你肯定想知道你的网站的哪些部分真正吸引了你的访问者的注意力:是菜单、产品描述还是右上角的那张小图片?麻省理工学院的visi importance项目可以通过从网页截图中构建热图来帮助你。它预测访问者的注意力将如何在你的网站上传播。它给了你一些见解,但仍然…

你希望你的访问者和客户对你的网站感到满意。从你的角度来看,你的网站很好,但是其他人会怎么说呢?

即使你的页面是用现代技术开发的,有方便的菜单,高质量的产品图片和描述,还有支持表单——仍然有一个问题:“它是否足够吸引人,或者可能需要重新设计?”

Scores assigned by design professionals for a fee

直到 2018 年,还没有找到普通人的思维方式的选项,你只能使用像 AWWWARDS 这样的网站来询问创意专业人士。但是如果你是当地的中小企业,他们就不是你的客户。为了了解普通人的想法,我们推出了服务,模拟普通用户对名片网站和在线商店的看法。

Free website scoring tool, WebScore AI (machine learning model)

我们已经处理了不同年份在不同*台上创建的 12,000 个网站和在线商店,收集了超过 140,000 个评估员的评估,并继续从 https://webscore.ai 的访问者那里收集网站示例及其得分。

让我们试着给一个网站打分

一个有好的字体、彩色图片、联系页面和社交网络链接的网站。大多数用户会认为这样的网站是好的。

这一假设是我们开发“手工”功能的基础。

特征提取过程由两部分组成:我们将使用 HTML/CSS 作为源的“手工”特征提取与使用截图作为源的卷积神经网络特征提取相结合。CNN 的特征是用流行的特征提取器 resnet50 获得的。

因此,我们的系统学会了寻找分数和特征之间的对应关系。结果,我们得到了一个*均误差为 0.5 点的模型。比评估员的*均误差要好。

现在任何人都可以检查他们的网站的美丽。但是网络上的人工智能仍然有一些高峰需要攀登

Webscore 项目是迈向 uKit 人工智能技术的一个步骤,这是我们今年的主要目标。

在使用基于人工智能的服务方面,企业有很大的潜力:推荐系统、聊天机器人、个性化设计等等。

但是,正如我之前说过的,数百万的网站已经过时了。聊天机器人不会让它们变得更有效,除非有人或事让这些页面再次变得有吸引力。深度学习也可以在这方面有所帮助——所以我们正在通过使用大数据来实现日常重新设计任务的完全自动化。网络包含大量数据,这些数据应该为企业所用。如果你有同样的感觉,我希望你继续关注我们团队的新闻。

P.S. 基于 2018 年 3 月 16 日 uKits 首席数据科学家 Roman Steinberg 在零售深度学习峰会上的演讲。

在 FIFA 18 中使用深度 Q-Learning 完善任意球艺术

原文:https://towardsdatascience.com/using-deep-q-learning-in-fifa-18-to-perfect-the-art-of-free-kicks-f2e4e979ee66?source=collection_archive---------3-----------------------

Tensorflow 中的一个代码教程,使用强化学习来踢任意球。

Free-kicks taken by the AI bot, trained through 1000 epochs of the Reinforcement Learning process.

在我的上一篇文章中,我展示了一个使用监督学习技术训练来玩国际足联游戏的人工智能机器人。通过这种方法,机器人很快学会了传球和射门等游戏的基本知识。然而,进一步改进它所需的训练数据很快变得难以收集,并且几乎没有改进,使得这种方法非常耗时。出于这个原因,我决定转向强化学习,就像几乎所有评论那篇文章的人所建议的那样!

Previous article: Building a Deep Neural Network to play FIFA 18

在这篇文章中,我将简要介绍什么是强化学习,以及我如何将它应用到这个游戏中。实现这一点的一个大挑战是我们无法访问游戏的代码,所以我们只能利用我们在游戏屏幕上看到的东西。由于这个原因,我无法在完整的游戏中训练 AI,但可以找到一个变通办法,在练习模式中为技能游戏实现它。在本教程中,我将尝试教机器人踢 30 码的任意球,但你也可以修改它来玩其他技能游戏。让我们从理解强化学习技术和我们如何制定我们的任意球问题来适应这一技术开始。

什么是强化学习(以及深度 Q 学习)?

与监督学习相反,在强化学习中,我们不需要手动标记训练数据。相反,我们与环境互动,并观察互动的结果。我们多次重复这个过程,获得正面和负面经验的例子,作为我们的训练数据。因此,我们通过实验而不是模仿来学习。

假设我们的环境处于一个特定的状态s,当采取一个动作a时,它会改变到状态s’。对于这个特定的动作,你在环境中观察到的直接回报是r。这个行动之后的任何一系列行动都会有它们自己的直接回报,直到你因为一个积极或消极的经历而停止互动。这些被称为未来奖励。因此,对于当前状态s,我们将尝试估计所有可能的行动中,哪个行动将为我们带来最大的当前+未来回报,用称为 Q 函数的Q(s,a)表示。这给了我们Q(s,a) = r + γ * Q(s’,a’),它表示在状态s中采取行动a的预期最终回报。在这里,γ是一个贴现因子,用来考虑预测未来时的不确定性,因此我们希望更多地相信现在而不是未来。

Image Source

深度 Q 学习是一种特殊类型的强化学习技术,其中 Q 函数由深度神经网络学习。给定环境的状态作为这个网络的图像输入,它试图预测所有可能行动的预期最终回报,如回归问题。具有最大预测 Q 值的行动被选为我们在环境中要采取的行动。因此得名深度 Q-Learning。

将国际足联的任意球视为一个 Q 学习问题

  • 状态:通过 MobileNet CNN 给128-dimensional flattened feature map处理的游戏截图图片。
  • 动作:四种可能采取的动作shoot_low, shoot_high, move_left, move_right
  • 奖励:如果按下射击键,游戏内得分增加超过 200,我们就进了一个球r=+1。如果我们错过了目标,得分保持不变,所以r=-1。最后,r=0为与向左或向右移动相关的动作。
  • 策略:双层密集网络,以特征地图为输入,预测所有 4 个动作的最终总奖励。

Reinforcement Learning process for the bot interacting with the game environment. The Q-Learning Model is the heart of this process and is responsible for predicting the estimated future reward for all possible actions that the bot can take. This model is trained and updated continuously throughout this process.

注:如果我们在 FIFA 的开球模式中有一个像练习模式中那样的性能表,我们可能已经能够为玩完整场比赛制定这个问题,而不是限制我们自己只罚任意球。或者我们需要访问游戏的内部代码,但我们没有。不管怎样,让我们充分利用我们所拥有的。

结果

虽然机器人还没有掌握所有不同种类的任意球,但它已经很好地学会了一些情况。它几乎总是在没有玩家墙的情况下击中目标,但在有玩家墙的情况下却挣扎。此外,当它在训练中没有经常遇到像不面对目标这样的情况时,它会表现得疯狂。然而,随着每个训练时期,这种行为被发现*均减少。

The figure shows, for epoch 1 through 1000, average number of free-kicks that got converted per attempt, calculated over a moving average window of 200 attempts. So, for example, a value of 0.45 at epoch 700 means 45% of attempts got converted to a goal (on an average) around this epoch.

如上图所示,训练 1000 个时代后,*均进球率*均从 30%增长到 50%。这意味着当前机器人的任意球得分约为其尝试的一半(作为参考,人类的*均得分约为 75-80%)。请注意,国际足联倾向于表现出不确定性,这使得学习非常困难。

Good examples of free kicks (model trained till 1000 epochs). The bot almost always scores in absence of the yellow player cutouts blocking the goal. In presence of the player wall, it gives mixed results.

Bad examples of free kicks. In some cases like above, the bot keeps transitioning between two states by alternating between left and right actions, making it stuck in a never ending loop. Probably a weakness of Reinforcement Learning setup.

更多视频格式的结果可以在我的 YouTube 频道、上找到,下面嵌入了视频。如果你想了解我所有的项目,请订阅我的频道。

代码实现

我们将使用深度学习的 Tensorflow (Keras)和 OCR 的 pytesseract 等工具在 python 中实现这一点。下面提供了 git 链接以及存储库描述中的需求设置说明。

[## ChintanTrivedi/DeepGamingAI _ FIFARL

DeepGamingAI_FIFARL -使用强化学习玩 FIFA

github.com](https://github.com/ChintanTrivedi/DeepGamingAI_FIFARL)

出于理解本教程的目的,我推荐下面的代码,因为为了简洁起见,已经删除了一些代码。运行 g it 时,请使用 git 的完整代码。让我们看一下代码的 4 个主要部分。

1.与游戏环境互动

我们没有任何现成的 API 可以让我们访问代码。所以,还是自己做 API 吧!我们将使用游戏的截图来观察状态,模拟按键来在游戏环境中采取行动,光学字符识别来读取我们在游戏中的奖励。在我们的 FIFA 类中有三个主要方法:observe(), act(), _get_reward()和一个额外的方法is_over()来检查任意球是否被罚。

2.收集培训数据

在整个培训过程中,我们希望存储我们所有的经验和观察到的奖励。我们将用它作为 Q-Learning 模型的训练数据。因此,对于我们采取的每一个行动,我们都将经验<s, a, r, s’>和一个game_over标志存储在一起。我们的模型将尝试学习的目标标签是每个行动的最终回报,它是我们回归问题的实数。

3.培训过程

现在,我们可以与游戏进行交互,并将我们的交互存储在内存中,让我们开始训练我们的 Q-Learning 模型。为此,我们将在探索(在游戏中采取随机行动)和开发(采取我们的模型预测的行动)之间取得*衡。通过这种方式,我们可以在游戏中进行试错以获得不同的体验。参数epsilon用于此目的,它是一个*衡勘探和开采的指数递减因子。起初,当我们一无所知时,我们想做更多的探索,但随着时代数量的增加和我们了解的更多,我们想做更多的开发和更少的探索。因此。epsilon参数的衰减值。

在本教程中,由于时间和性能的限制,我只训练了1000 epochs的模型,但在未来,我想把它推到至少 5000 个纪元。

4.模型定义和开始培训过程

Q 学习过程的核心是一个具有 ReLU 激活的 2 层密集/全连接网络。它将 128 维特征图作为输入状态,并为每个可能的动作输出 4 个 Q 值。具有最大预测 Q 值的动作是根据给定状态的网络策略要采取的期望动作。

这是执行这段代码的起点,但你必须确保游戏 FIFA 18 在第二台显示器上以窗口模式运行,并在技能游戏:射门菜单下加载任意球练习模式。确保游戏控件与 FIFA.py 脚本中硬编码的按键同步。

结论

总的来说,我认为结果相当令人满意,尽管它未能达到人类的性能水*。从监督学习转换到强化学习有助于减轻收集训练数据的痛苦。如果有足够的时间探索,它在学习如何玩简单游戏等问题上表现得非常好。然而,强化设置在遇到不熟悉的情况时似乎会失败,这使我相信将其公式化为回归问题不能像在监督设置中公式化为分类问题一样外推信息。也许两者的结合可以解决这两种方法的缺点。也许在那里我们会看到为游戏构建人工智能的最佳结果。以后给我尝试的东西!

致谢

我要感谢这个深度 Q-Learning 教程和这个 git 游戏库提供了大部分代码。除了 FIFA 的“自定义 API ”,大部分代码的主干都来自这些来源。多亏了这些家伙!

感谢您的阅读!如果你喜欢这个教程,请关注我的媒体、 github 或者订阅我的 YouTube 频道。

使用 Docker 在 AWS 上建立深度学习环境

原文:https://towardsdatascience.com/using-docker-to-set-up-a-deep-learning-environment-on-aws-6af37a78c551?source=collection_archive---------2-----------------------

在我之前的文章中,我一步一步地解释了如何在 AWS 上建立深度学习环境。重要的一步是安装 CUDA 工具包和 cuDNN 。然而,这一步非常耗时。在本文中,我将使用 docker,特别是 nvidia-docker 来简化安装过程,从而加快安装过程。

我们将使用与上次相同的亚马逊的 EC2 GPU 实例:

  • 图片:ami-b 03 ffedf(Ubuntu Server 16.04 LTS(HVM),SSD 卷类型)
  • 区域:欧盟中部-1(欧盟法兰克福)
  • 实例类型:g2.2xlarge
  • 存储:30 GB(建议至少 20gb 以上)

1.创建新的 EC2 GPU 实例

Select the Ubuntu Server 16.04 LTS AMI.

Take the g2.2xlarge GPU Instance. Alternatively, you could also take the g2.8xlarge if you need more computing power.

Change the standard storage size to 30 GB.

Launch the cluster and assign an EC2 key pair.

2.更新 NVIDIA 驱动程序并安装 docker+nvidia-docker

NVIDIA 驱动程序

更新图形驱动程序:

$ sudo add-apt-repository ppa:graphics-drivers/ppa -y
$ sudo apt-get update
$ sudo apt-get install -y nvidia-375 nvidia-settings nvidia-modprobe

码头工人

安装 Docker 社区版(查看官方指南了解更多关于安装的信息):

$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
# Verify that the key fingerprint is 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88
$ sudo apt-key fingerprint 0EBFCD88
$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
$ sudo apt-get update
$ sudo apt-get install -y docker-ce

英伟达-Docker

安装 nvidia-docker 及其插件:

$ wget -P /tmp https://github.com/NVIDIA/nvidia-docker/releases/download/v1.0.1/nvidia-docker_1.0.1-1_amd64.deb
$ sudo dpkg -i /tmp/nvidia-docker_1.0.1-1_amd64.deb && rm /tmp/nvidia-docker_1.0.1-1_amd64.deb

3.测试您的环境:

现在,我们可以使用 nvidia-docker 来测试一切是否按预期工作:

$ sudo nvidia-docker run --rm nvidia/cuda nvidia-smi

注意:如果您第一次运行该命令,它将首先提取图像。此外,如果您不想作为 *sudo* 运行,那么您需要将 EC2 用户添加到 docker 组 *sudo usermod -a -G docker ubuntu* (更多详细信息,请参见 AWS 指南 )。

这是您应该看到的输出:

你现在可以使用官方 TensorFlow docker 映像或 Theano 映像来启动你的深度学习环境,或者你可以编写自己的docker 文件并将其推送到 docker hub 。

张量流示例:

在 shell 中启动最新的 TensorFlow 容器(对于其他选项,如作为 Jupyter 笔记本运行 TensorFlow 程序,请查看官方 TensorFlow 指南):

$ sudo nvidia-docker run -it tensorflow/tensorflow:latest-gpu bash

在 python 中运行一个简单的示例,检查 TensorFlow 在 GPU 支持下能否正常工作:

import tensorflow as tfa = tf.constant(5, tf.float32)
b = tf.constant(5, tf.float32)with tf.Session() as sess:
    sess.run(tf.add(a, b)) # output is 10

这是您应该预期的输出:

结论

在这篇博文中,我用 docker 在 AWS 上搭建了一个深度学习环境。这大大加快了安装过程。这对于家里没有自己的 GPU 的人来说特别有用;)

在推特上关注我: @datitran

使用 FastText 和 SVD 即时可视化单词嵌入

原文:https://towardsdatascience.com/using-fasttext-and-svd-to-visualise-word-embeddings-instantly-5b8fa870c3d1?source=collection_archive---------4-----------------------

不久前,当我开始学习自然语言处理的基础知识时,我对单词被表示为向量的方式很感兴趣。更吸引人的是单词被标绘在图表上,那些具有相似含义和上下文的单词被组合在一起。因此,我努力生成自己的嵌入,这是一场“斗争”,因为我缺乏计算能力。用于生成向量的 Word2Vec 和用于可视化的 T-SNE 是流行的选择,但是花费了我很多时间。

嗯,到现在也没变。然而,我发现脸书的快速文本让我大吃一惊。过去需要几个小时才能完成的事情,现在只需几秒钟就能完成,而且性能几乎相同。除此之外,我使用了一些线性代数来找出可能是“最快”生成你自己的单词嵌入可视化的方法。让我们现在就开始这个过程,写一些代码。

1。获取数据

我决定从 Whatsapp 获取聊天数据。我占用了我大学的文学和辩论俱乐部(LDC)的数据。这是因为我们已经讨论了广泛的话题,而且数据总量接* 1.1 Mb,对于任务来说已经足够了。

2。一些预处理

有些问题需要注意。首先,如果没有保存联系人姓名,在每一个新行的开头都有联系人的电话号码。此外,在聊天中有一些奇怪的特殊字符代表表情符号,但这对我们的任务来说是一个头痛的问题。所以,我使用了一些正则表达式技巧来清理文本。

3。设置快速文本

现在让我们来看看这个大家伙。设置脸书的快速文本是小菜一碟。你所需要的只是一个现代的 C++编译器(C++ 11)和一个 make 命令。FastText 是用纯 C++编写的,这也是它实现如此之快的另一个原因。

a.去https://github.com/facebookresearch/fastText克隆回购。

b.切换到下载的目录,在你的终端上输入 make 命令

c.瞧啊。FastText 可以使用了。

4。对我们的数据使用 fast text

我们现在将使用 fasttext 库为我们清理的数据生成单词向量。为此,在 fasttext 目录中打开您的终端并键入-

'''.' '/fast text skip gram-input LDC _ clean . txt-output model ' ' '

让我给你解释一下这个声明。

。/fasttext —使用我们刚刚编译的 fasttext 模块退一步,咄?

skigram —有两种流行的方法来生成单词的矢量表示。CBOW 和 Skipgram。我们在这里选择 skipgram。

-input ldc_clean.txt —我们将包含文本数据的文件名指定为输入参数。

-output model——它指定了 FastText 将生成的两个输出文件的名称。model.vec是包含单词 vectors 的文本文件,每行一个。model.bin是一个二进制文件,包含模型参数、字典和所有超参数

5。从生成的 model.vec 设置 python 列表

现在,我们在一个. vec 文件中有了单词和向量,但是为了绘制它们并对向量执行 SVD,我们需要将单词转换为一个列表,并将相应的向量转换为另一个列表。在此过程中,我们还需要将向量值从 string 转换为 numpy 的 float32 类型,以实现上述操作。

6。利用奇异值分解降低维数。

当我第一次在谷歌上搜索时,我发现 T-SNE 到处都在通过降低维度来产生一些令人惊讶的可视化效果。毫无疑问,我是它的忠实粉丝。但可悲的是我的计算能力没有。所以,我决定,为什么不用老式的奇异值分解。它非常有效。这也是使用 FastText 的首要目的,也就是说,给出真正快速的结果。

7。有趣的部分。绘制我们的数据以创建有洞察力的可视化

现在,我们需要的东西都有了。一个很好的列表,包含了所有的单词和一个非常简化的表示,我们最初的高维向量表示。我们现在要做的就是使用 Matplotlib 并生成一些视觉效果。

就在那里,伙计们,这可能是你能找到的最快的方法,用脸书的快速文本在几秒钟内训练它生成单词的向量表示,然后做一点线性代数魔法,让可视化完全不实时。

我计划发布一个帖子来解释隐藏在幕后的所有复杂的数学问题。它将讨论 FastText 如何在如此短的时间内实现 SOTA 结果,以及如何帮助它击败现有的竞争对手,如 Word2Vec,特别是在训练时间方面。所以,如果你喜欢这个,你肯定会喜欢那个。所以,敬请期待,继续嵌入!

Who’s up for a debate night?

页(page 的缩写)图像被高度放大,因为视觉化的密度极高。使用 matplotlib 的缩放功能来做到这一点。

使用 GANS 进行半监督学习

原文:https://towardsdatascience.com/using-gans-for-semi-supervised-learning-df1bfc289601?source=collection_archive---------3-----------------------

在监督学习中,我们有一个输入 x 和类别标签 y 的训练集。我们训练一个以 x 为输入,y 为输出的模型。

在半监督学习中,我们的目标仍然是训练一个以 x 为输入,生成 y 为输出的模型。然而,并非所有的训练示例都有标签 y。我们需要开发一种算法,通过研究标记的(x,y)对和未标记的 x 示例,能够更好地进行分类。

我们将使用 GAN 鉴别器作为 n+1 类鉴别器。它将识别 n 个不同类别的标记数据,以及来自生成器的第(n+1)类伪图像。鉴别器将在真实的标记图像、真实的未标记图像和虚假图像上进行训练。通过利用三个数据源而不是一个数据源,它将比只利用一个数据源训练的传统分类器更好地推广到测试集。

发电机:

输出与真实图像尺寸相同的假图像的典型发生器。

需要注意的事项:

  • 由于输出激活是 tanh(值范围从-1 到+1),这意味着当我们训练鉴别器时,我们需要将真实图像缩放到相同的范围。
  • 我们对生成器的每一层使用标准卷积转置、批量范数和泄漏 relu。
def generator(z, output_dim, reuse=False, alpha=0.2, training=True, size_mult=128):
    with tf.variable_scope('generator', reuse=reuse):
        # First fully connected layer
        x1 = tf.layers.dense(z, 4 * 4 * size_mult * 4)
        # Reshape it to start the convolutional stack
        x1 = tf.reshape(x1, (-1, 4, 4, size_mult * 4))
        x1 = tf.layers.batch_normalization(x1, training=training)
        x1 = tf.maximum(alpha * x1, x1)

        x2 = tf.layers.conv2d_transpose(x1, size_mult * 2, 5, strides=2, padding='same')
        x2 = tf.layers.batch_normalization(x2, training=training)
        x2 = tf.maximum(alpha * x2, x2)

        x3 = tf.layers.conv2d_transpose(x2, size_mult, 5, strides=2, padding='same')
        x3 = tf.layers.batch_normalization(x3, training=training)
        x3 = tf.maximum(alpha * x3, x3)

        # Output layer
        logits = tf.layers.conv2d_transpose(x3, output_dim, 5, strides=2, padding='same')

        out = tf.tanh(logits)

        return out

鉴别器:

由于无监督的组件,鉴别器比生成器更复杂。

需要注意的事项:

  • 积极和广泛使用辍学。这是因为我们在一小组带标签的训练样本上有一个深度卷积层的大锤(注意,大多数训练样本是无标签的),这使得很难不对训练数据进行过度拟合,并教导鉴别器更好地进行概括。
  • 我们不在鉴别器的第一层使用批量标准化,因为鉴别器从真实和虚假数据中查看数据的分布是很重要的。
  • 我们在鉴别器的最后一层没有使用批处理规范化。Bn 会将每个特征的*均值设置为 Bnμ参数。该层用于特征匹配损失,仅当鉴别器对数据运行时的*均值与鉴别器对生成器样本运行时的*均值不同时,该层才起作用。
  • 与标准 GAN 鉴别器一样,我们对每层使用卷积步长、批量范数和泄漏 relu,并且我们使用卷积步长而不是最大池。
  • 对于最后一层,我们使用全局*均池来获取特征,而不是密集层。
  • class_logits =不同类上的 softmax 分布。
  • gan_logits 使得 P(输入是真实的还是虚假的)= sigmoid(gan_logits)
def discriminator(x, reuse=False, alpha=0.2, drop_rate=0., num_classes=10, size_mult=64):
    with tf.variable_scope('discriminator', reuse=reuse):
        x = tf.layers.dropout(x, rate=drop_rate/2.5)

        # Input layer is 32x32x3
        x1 = tf.layers.conv2d(x, size_mult, 3, strides=2, padding='same')
        relu1 = tf.maximum(alpha * x1, x1)
        relu1 = tf.layers.dropout(relu1, rate=drop_rate)

        x2 = tf.layers.conv2d(relu1, size_mult, 3, strides=2, padding='same')
        bn2 = tf.layers.batch_normalization(x2, training=True)
        relu2 = tf.maximum(alpha * x2, x2)

        x3 = tf.layers.conv2d(relu2, size_mult, 3, strides=2, padding='same')
        bn3 = tf.layers.batch_normalization(x3, training=True)
        relu3 = tf.maximum(alpha * bn3, bn3)
        relu3 = tf.layers.dropout(relu3, rate=drop_rate)

        x4 = tf.layers.conv2d(relu3, 2 * size_mult, 3, strides=1, padding='same')
        bn4 = tf.layers.batch_normalization(x4, training=True)
        relu4 = tf.maximum(alpha * bn4, bn4)

        x5 = tf.layers.conv2d(relu4, 2 * size_mult, 3, strides=1, padding='same')
        bn5 = tf.layers.batch_normalization(x5, training=True)
        relu5 = tf.maximum(alpha * bn5, bn5)

        x6 = tf.layers.conv2d(relu5, 2 * size_mult, 3, strides=2, padding='same')
        bn6 = tf.layers.batch_normalization(x6, training=True)
        relu6 = tf.maximum(alpha * bn6, bn6)
        relu6 = tf.layers.dropout(relu6, rate=drop_rate)

        x7 = tf.layers.conv2d(relu5, 2 * size_mult, 3, strides=1, padding='valid')
        # Don't use bn on this layer, because bn would set the mean of each feature
        # to the bn mu parameter.
        # This layer is used for the feature matching loss, which only works if
        # the means can be different when the discriminator is run on the data than
        # when the discriminator is run on the generator samples.
        relu7 = tf.maximum(alpha * x7, x7)

        # Flatten it by global average pooling
        features = tf.reduce_mean(relu7, (1, 2))

        # Set class_logits to be the inputs to a softmax distribution over the different classes
        class_logits = tf.layers.dense(features, num_classes + extra_class)

        # Set gan_logits such that P(input is real | input) = sigmoid(gan_logits).
        # Keep in mind that class_logits gives you the probability distribution over all the real
        # classes and the fake class. You need to work out how to transform this multiclass softmax
        # distribution into a binary real-vs-fake decision that can be described with a sigmoid.
        # Numerical stability is very important.
        # You'll probably need to use this numerical stability trick:
        # log sum_i exp a_i = m + log sum_i exp(a_i - m).
        # This is numerically stable when m = max_i a_i.
        # (It helps to think about what goes wrong when...
        #   1\. One value of a_i is very large
        #   2\. All the values of a_i are very negative
        # This trick and this value of m fix both those cases, but the naive implementation and
        # other values of m encounter various problems)

        if extra_class:
            real_class_logits, fake_class_logits = tf.split(class_logits, [num_classes, 1], 1)
            assert fake_class_logits.get_shape()[1] == 1, fake_class_logits.get_shape()
            fake_class_logits = tf.squeeze(fake_class_logits)
        else:
            real_class_logits = class_logits
            fake_class_logits = 0.

        mx = tf.reduce_max(real_class_logits, 1, keep_dims=True)
        stable_real_class_logits = real_class_logits - mx gan_logits = tf.log(tf.reduce_sum(tf.exp(stable_real_class_logits), 1)) + tf.squeeze(mx) - fake_class_logits

        out = tf.nn.softmax(class_logits)

        return out, class_logits, gan_logits, features

模型损失函数和优化器:

d_loss :鉴频器的损耗为:

  1. GAN 问题的损失,其中我们最小化二进制真假分类问题的交叉熵:d_loss_real 和 d_loss_fake
  2. 真实监督数据(带标签)多分类问题的损失:d_loss_class。对于 d_loss_class,我们仅考虑迷你批次中具有标签的样本,但是迷你批次中可能没有样本具有标签,因此以下表达式将为 0/1,并且 d_loss_class 的损失为 0。" TF . reduce _ sum(label _ mask * class _ cross _ entropy)/TF . maximum(1。,tf.reduce_sum(label_mask))"

发电机的损耗是由 Tim Salimans 在 OpenAI 发明的“特征匹配”损耗。这种损失包括最小化数据上的预期特征和生成样本上的预期特征之间的绝对差异。这种损失对于半监督学习比传统的 GAN 损失更有效。随着时间的推移,这将迫使生成器生成与真实数据相似的样本。

请注意,使用生成器的特征损失,生成器样本不会像在传统 DCGAN 中生成的样本一样好,但是这里的目标是使用小的标记数据集和大的未标记数据集来实现多类分类的高鉴别器准确度。

def model_loss(input_real, input_z, output_dim, y, num_classes, label_mask, alpha=0.2, drop_rate=0.):
    """
    Get the loss for the discriminator and generator
    :param input_real: Images from the real dataset
    :param input_z: Z input
    :param output_dim: The number of channels in the output image
    :param y: Integer class labels
    :param num_classes: The number of classes
    :param alpha: The slope of the left half of leaky ReLU activation
    :param drop_rate: The probability of dropping a hidden unit
    :return: A tuple of (discriminator loss, generator loss)
    """

    # These numbers multiply the size of each layer of the generator and the discriminator,
    # respectively. You can reduce them to run your code faster for debugging purposes.
    g_size_mult = 32
    d_size_mult = 64

    # Here we run the generator and the discriminator
    g_model = generator(input_z, output_dim, alpha=alpha, size_mult=g_size_mult)
    d_on_data = discriminator(input_real, alpha=alpha, drop_rate=drop_rate, size_mult=d_size_mult)
    d_model_real, class_logits_on_data, gan_logits_on_data, data_features = d_on_data
    d_on_samples = discriminator(g_model, reuse=True, alpha=alpha, drop_rate=drop_rate, size_mult=d_size_mult)
    d_model_fake, class_logits_on_samples, gan_logits_on_samples, sample_features = d_on_samples

    # Here we compute `d_loss`, the loss for the discriminator.
    # This should combine two different losses:
    #  1\. The loss for the GAN problem, where we minimize the cross-entropy for the binary
    #     real-vs-fake classification problem.
    #  2\. The loss for the SVHN digit classification problem, where we minimize the cross-entropy
    #     for the multi-class softmax. For this one we use the labels. Don't forget to ignore
    #     use `label_mask` to ignore the examples that we are pretending are unlabeled for the
    #     semi-supervised learning problem.
    d_loss_real = tf.reduce_mean(
        tf.nn.sigmoid_cross_entropy_with_logits(logits=gan_logits_on_data,
                                                labels=tf.ones_like(gan_logits_on_data)))
    d_loss_fake = tf.reduce_mean(
        tf.nn.sigmoid_cross_entropy_with_logits(logits=gan_logits_on_samples,
                                                labels=tf.zeros_like(gan_logits_on_samples)))
    y = tf.squeeze(y)
    class_cross_entropy = tf.nn.softmax_cross_entropy_with_logits(logits=class_logits_on_data,
                                                                  labels=tf.one_hot(y, num_classes + extra_class,
                                                                                    dtype=tf.float32))
    class_cross_entropy = tf.squeeze(class_cross_entropy)
    label_mask = tf.squeeze(tf.to_float(label_mask))
    d_loss_class = tf.reduce_sum(label_mask * class_cross_entropy) / tf.maximum(1., tf.reduce_sum(label_mask))
    d_loss = d_loss_class + d_loss_real + d_loss_fake

    # Here we set `g_loss` to the "feature matching" loss invented by Tim Salimans at OpenAI.
    # This loss consists of minimizing the absolute difference between the expected features
    # on the data and the expected features on the generated samples.
    # This loss works better for semi-supervised learning than the tradition GAN losses.
    data_moments = tf.reduce_mean(data_features, axis=0)
    sample_moments = tf.reduce_mean(sample_features, axis=0)
    g_loss = tf.reduce_mean(tf.abs(data_moments - sample_moments))pred_class = tf.cast(tf.argmax(class_logits_on_data, 1), tf.int32)
    eq = tf.equal(tf.squeeze(y), pred_class)
    correct = tf.reduce_sum(tf.to_float(eq))
    masked_correct = tf.reduce_sum(label_mask * tf.to_float(eq))

    return d_loss, g_loss, correct, masked_correct, g_model

https://github . com/mchablani/deep-learning/blob/master/semi-supervised/semi-supervised _ learning _ 2 _ solution . ipynb

演职员表:来自讲稿:【https://classroom.udacity.com/nanodegrees/nd101/syllabus

使用 ggplot 在地理地图上绘制饼图

原文:https://towardsdatascience.com/using-ggplot-to-plot-pie-charts-on-a-geographical-map-bb54d22d6e13?source=collection_archive---------8-----------------------

在这篇文章中,我们将详细介绍在世界地图上绘制饼图的步骤,如下图所示。

Plot showing the leading causes of death in the year 2014 for various countries

当我意识到我需要创造一个和这个一样的东西时,这张图片可能让你和我一样害怕。“我连 R 编程都不擅长,事实上,还是个新手,我该怎么做这件事呢?”你可能正在问自己这个问题,或者你已经问过了。我理解你,但我得到了你。我在做我的第一个地图绘制时挣扎了很久,这就是为什么我将与你分享如何使用 ggplot 一步一步完成它的方法,让你从所有的谷歌搜索和试错中解脱出来。

这样,在我们进行这些步骤时,我们将使用真实世界的数据来回答一个特定的问题。

"每个国家的死亡原因分布有差异吗?"

我设法从kaggle.com获得了一个关于世界上每个国家死亡原因的体面数据,这些数据将用于我们的插图和模拟。

准备数据

我们需要做的第一件事是确保我们的数据是完整的,在绘图之前我们有我们需要的东西。在这种情况下,我们需要每个国家的死亡原因数据以及每个国家的坐标。然后,我们将它加载到我们的工作环境中,如下所示。

一旦我们完成了所有需要的数据,我们将继续决定我们将要做的地图绘制的方法。我们有几个选项用于 ggplot,因为它很容易获得世界地图数据。

Rdocumentation.org 有一个非常友好的文档,包含了大部分 r 包和函数,所以如果你是 r 新手,我真的建议你去看看

其中 map 是 maps 包中提供的地图的名称。map_data("world ")即时获取我们绘制世界地图所需的数据。

其中 database 是要绘制的地图数据(查看 maps::map()以获取可用的地图)。borders("world ")获取数据以创建世界的边界。

最后,使用形状(。shp)文件。我们需要获得我们感兴趣的地图的形状文件。在这种情况下,我研究了一个. shp 文件并使用

其中 dsn 是我们感兴趣的形状文件。从 readOGR 获得的数据还不能用于绘图。我们将使用

其中“模型”是需要转换为数据框的模型或 R 对象。fortify(world)将我们从。shp 文件转换为有用的数据框,以备打印。

我已经决定使用这三个工具,但是你可以在你的项目中选择一个,最简单和最适合你的。

基础地图地块

这些代码的输出看起来很接*。

World map

添加馅饼

为了将饼图添加到地图绘图中,我们将在原始 ggplot 公式中添加一个 geom_scatterpie 函数,如下所示。

World map with the distribution of death causes per country

添加标签、图表标题、轴标题等

为了改善我们可视化的外观,我们将通过向 ggplot 公式添加一些新函数来为图表添加一些附件。

这就对了。我们在世界地图上标出了每个国家的死亡原因分布。我们可以看到,除了白俄罗斯和格鲁吉亚之外,几乎所有这些国家都有相同的分布,因为与其他国家相比,白俄罗斯和格鲁吉亚的循环系统疾病发病率较高。

我上面给你展示的方法只是一种方法。其他可以尝试的地图绘制方法有:tmap 包中的 ggmap 、 mapplot 、 qtm 、传单等。我强烈建议你也试一试。

在这个库中可以获得在这个模拟中使用的所有文件的副本。

原载于 2018 年 10 月 25 日www.spectdata.com Marriane Makahiya,作者是 SpectData 的数据科学家。SpectData 是一家数据分析公司,旨在帮助公司更好地利用他们的数据。

从 Git 到 Colab,通过 SSH

原文:https://towardsdatascience.com/using-git-with-colab-via-ssh-175e8f3751ec?source=collection_archive---------9-----------------------

如何将 Git 与 Colab 集成,以便克隆您的公共/私有存储库。

当你使用谷歌的联合实验室(Colab)来运行你的深度学习模型时,访问大型数据集最明显的方法是将它们存储在谷歌驱动器上,然后将驱动器安装到 Colab 环境中。但是许多用于研究目的的开源大型数据集都托管在 Github/Gitlab 上。幸运的是,Colab 提供了一种集成 Github 和访问存储库的简单方法。那么,让我们来详细看看这些步骤。

Colab — Git —集成:

我将在两种情况下解释集成:

  1. 使用公共 Git 存储库(没有 SSH)
  2. 使用私有 Git 存储库(使用 SSH)

克隆一个公共 Git Repo:(没有 SSH)

集成只是几行代码——当您想要克隆的 git 存储库是一个公共存储库时。

  • 将 Google Drive 安装到您的 Colab 环境中。

在执行上面的 2 行代码时,系统会提示您转到所示的 Google Accounts URL 进行身份验证。单击显示在笔记本单元格输出部分的 URL。这将带您进入如下页面:

点击允许按钮。这将把你带到下一页,在那里显示一个授权码(我用红色标出)。

复制此代码并将其粘贴到单元格(如第一个图像所示)中显示“输入您的授权码”的位置,然后单击 Enter。Google Drive 现在已安装,您会收到确认消息。

  • 将您的公共 Git repo 克隆到您的驱动器文件夹中。执行上述步骤后,驱动器文件将出现在路径 "/content/drive/My Drive" 中,您可以使用左侧的面板浏览它们。

然后,您可以将任何驱动器文件夹设置为工作目录。然后将公共 git repo 克隆到您的工作目录中。这两个步骤的实现如下:

克隆一个私有 Git Repo:(使用 SSH)

不幸的是,你不能轻易地克隆你的私有库。事实上,在这种情况下,您可以使用一行程序,如下所示:

也就是说,提供您的用户名:密码以及存储库链接来克隆一个私有存储库。这是可行的,但是问题是密码存储在 git/config 和 bash 历史日志中。因此,以上述方式克隆您的私有回购协议是不可取的。相反,我们将使用 SSH 协议将您的私有 github/gitlab repo 连接到 colab。

  • 第一步是在本地机器上生成 ssh 密钥对(私有-公共)。你可以通过这篇优秀的文章(文章的第 1 步和第 2 步)来了解如何做到这一点。但是我会马上提供必要的步骤:

ssh-keygen-t RSA-C " your _ email @ your email . com "

出现提示时输入文件名:~/。ssh/id_rsa_<some_name></some_name>

输入密码短语:只需按“Enter”(无密码短语)

  • 私钥保存在文件: ~/。ssh/id _ RSA _并且公钥保存在文件: ~/。ssh/id_rsa_ < some_name >。pub 将这两个文件复制到一个文件夹中。我将这两个文件的副本放在一个文件夹中,并将其命名为‘ssh-colab’
  • 接下来创建一个配置文件

触摸配置

编辑配置

  • 配置文件的内容应该如下所示:

  • 现在将配置文件也放在在‘ssh-colab’之前创建的文件夹中。然后存档为 'ssh.tar.gz' :

tar-czvf ssh.tar.gz ssh-colab

  • 这个包含私钥、公钥和配置文件的归档文件夹必须上传到 Colab。我们马上就会看到这一点。但在此之前,我们先把公钥放在服务器上(Github/Gitlab)。
  • 将文件 id_rsa_ < some_name >中的公钥内容复制到剪贴板。发布会
  • 登录 Github
  • 点击你的个人资料>设置> SSH 和 GPG 键>新建 SSH 键
  • 粘贴剪贴板的内容并保存
  • 现在是在 Colab 上执行的步骤。首先让我们上传档案文件‘ssh . tar . gz’。

  • 现在我们需要将密钥对文件和配置文件移动到/root/中。ssh 文件夹。下图详细给出了要执行的 shell 命令:

  • 下一步是将私钥加载到本地 ssh-agent 中。这背后的原因在这个 stackoverflow 帖子的标记答案中解释得很清楚。我将在下面给出它的要点:

“您希望在登录时在后台运行ssh-agent。一旦你登录,这个想法就是运行ssh-add一次并且只运行一次,以便给代理你的密码,解码你的密钥。然后,代理将您的密钥解锁并加载到内存中,随时准备在您每次 ssh 时使用。然后,所有 ssh-family 命令 1 将咨询代理,并自动能够使用您的私钥。”

  • 因此,要运行您的 ssh-agent,请使用以下命令

  • 在单元的输出部分,您会收到一条警告消息,ssh-agent 开始运行。您会得到一个可以执行 shell 命令的提示。请参见下图,我们在其中添加了私钥,然后检查新密钥是否已保存:

  • 在下一步中设置您的 Git 帐户

  • 我们现在可以克隆我们的私有 git 存储库了。将工作目录更改为驱动器内的一个文件夹。然后运行 git clone。

仅此而已!我们已经从 Colab SSH-ed 进入我们的 Git 帐户,并克隆了我们的私有存储库。

参考资料:

  1. https://stack overflow . com/questions/48350226/methods-for-use-git-with-Google-colab
  2. https://stack overflow . com/questions/10054318/how-to-provide-username-and-password-when-run-git-clone-git remote-git?noredirect=1 & lq=1

谷歌搜索商标的图片。版权分别属于 Colaboratory 和 Github。其他图片是我的作品截图。

原载于 2018 年 6 月 5 日techsupportallbugs.wordpress.com

使用 Google Apps 脚本从您的 Google Analytics 帐户获取数据

原文:https://towardsdatascience.com/using-google-apps-script-to-fetch-data-from-your-google-analytics-account-6f5fb800e98d?source=collection_archive---------5-----------------------

只需点击一个按钮,所有的谷歌分析数据都可以在谷歌工作表中找到,这怎么样?

Photo by Myriam Jessier on Unsplash

谷歌分析无需介绍。绝对是互联网上最受欢迎的网络分析服务,帮助企业收集和分析数据,并使用它们来发展和增强他们的服务或产品。访问 Google Analytics 数据的最常见方式是通过主仪表板和预定义的报告。为了处理数据并提取更有价值的见解,您可以创建标准或自定义报告来呈现您需要的数据,然后通常将它们导出到电子表格中。方法是使用 GA 控制台中提供的导出功能(PDF、Google Sheets、Excel 或 CSV 格式),然后将文件导入 Google 电子表格或任何其他电子表格软件。

Image by Author

但是,如果您需要对多个文件这样做,或者在一段时间内定期这样做(例如,生成定期报告),该怎么办呢?这很痛苦,不是吗?好吧,谷歌应用程序脚本来拯救!💪💪

Google 企业应用套件脚本

那么,什么是 Google Apps 脚本呢? Google Apps Script 是一种 JavaScript 云脚本语言,提供了跨 G-Suite 产品和第三方服务自动执行任务以及构建 web 应用的简单方法。简而言之,使用 JavaScript,我们可以增加我们最喜欢的、已经很强大的谷歌应用程序的功能,比如电子表格、文档、日历、邮件等等。在我们的案例中,我们将关注 Google 电子表格和 Google Apps 脚本之间的集成。要访问脚本编辑器,我们可以在其中构建我们的应用程序,我们可以创建一个新的电子表格,并从顶部菜单中单击工具>脚本编辑器

Image by Author

连接 Google 电子表格和 Google APIs

上述选项将使用脚本编辑器控制台打开一个新标签。使用这个控制台,我们可以构建我们的应用程序,创建脚本文件,连接资源等。在我们的例子中,我们将使用 Google Analytics API 作为资源来获取我们需要的数据。要启用 Google 电子表格和 Google 分析 API 之间的连接,我们必须遵循以下步骤:

  1. 单击顶部菜单上的“资源”选项。
  2. 点击“高级谷歌服务…”选项。
  3. 为我们的项目命名(在这种情况下,我们将命名为“测试项目”)。
  4. 搜索 Google Analytics API ,点击开关将其打开。

Image by Author

5.先别急着关窗。为了获得完全访问权限,我们还必须在 Google API 控制台中启用我们选择的服务。如果我们点击提供的链接,我们将被直接重定向到 GCP 控制台,通过搜索顶部搜索栏上的“分析 API ”,我们将找到我们选择的服务。

Image by Author

6.点击启用,你就可以开始了!👏

查询浏览器

在处理数据和报告时,最重要的是我们的数据要一致和可信。建立别人对你数据的信任需要很长时间,但失去信任只需一分钟。在这个过程中我们最好的朋友是谷歌的一个非常有用的工具,叫做查询浏览器。Query Explorer 通过使用各种参数进行查询和测试响应来帮助我们处理 Google Analytics 数据。我们可以选择想要查询数据的帐户—属性—视图,只需添加参数(开始日期、结束日期、指标、维度、筛选器、细分等)。然后,我们可以下载 TSV 格式的数据(制表符分隔的文件),或将直接 API 查询 URI 保存到该报告中。通过 Google Apps 脚本查询数据是模拟查询浏览器数据的一种方式,就我个人而言,我总是让查询浏览器在一个选项卡中打开来验证查询。

构建脚本

说够了。让我们开始行动吧。在我们创建了项目并启用了分析 API 之后,下一步是实际构建脚本来获取我们需要的数据。我们将需要 2 个标签不断在点击之外。

  1. 查询浏览器(构建和验证查询)
  2. Google Apps 脚本电子表格参考(一个非常详细且写得很好的文档)

为了从谷歌分析中查询数据,我们需要下面的函数。该函数接受 5 个参数作为输入,并返回一个报告作为输出。

function gaGet(tableId, startDate, endDate, metrics, options)

这些论点是:

  1. tableId: 实际上是我们要查询的视图的 Id。在查询资源管理器中,当我们选择适当的帐户-属性-视图时,会自动设置表 id(格式:“ga:xxxxxxx”)。
  2. startDate: 查询的开始日期(格式:“yyyy-MM-dd”或 NdaysAgo)。
  3. 结束日期:查询的结束日期(格式:“yyyy-MM-dd”或 NdaysAgo)。
  4. 指标:保存查询指标的表(例如 ga:用户或 ga:会话)
  5. 选项:包含所有其他必要信息的对象(如维度、过滤器、分段、排序等)

*注意: 关于这些参数的完整参考,你可以在这里查阅文档。

上面脚本中我们最应该关心的核心命令是:

return Analytics.Data.Ga.get(tableId, startDate, endDate, metrics, options);

这是实际查询来自 Google Analytics 的数据并返回报告的命令。代码片段的所有其他部分只是为了处理任何可能的错误。

用例

因此,在我们的用例中,我们将获取一些核心指标,如浏览量、*均。我们网站前 5 页的页面时间和跳出率,并写在我们的电子表格中。为此,您需要复制下面的脚本,并将其粘贴到应用程序脚本控制台。

*注意:您需要为工作表(不是电子表格)的名称、要查询的表 id(您可以通过选择“帐户”—“属性”—“视图”)以及查询的开始和结束日期指定您自己的值。

粘贴了上面的脚本并添加了自己的参数后,选择运行>运行函数> main 。如果需要,进行身份验证,瞧!您的数据可以在电子表格中找到。在第一列中,我们看到了页面,接下来的三列分别是页面浏览量、页面*均停留时间和跳出率,正如我们在“指标”数组中声明的那样。

结论

在这篇小文章中,我们看到了一种从 Google Analytics 查询数据并使用应用程序脚本将其写入 Google 电子表格的简单方法。当然,应用程序脚本的能力是无限的,它能做的远不止获取简单的数据。把手弄脏,当你越来越习惯使用 Apps Script 时,你会意识到你能实现多少,你能自动化多少任务和报告。

页(page 的缩写)s:该指南已更新,以适应最*的变化。

如果您需要帮助或希望优化您的跟踪和分析设置,请联系我们!我们支持所有领域和规模的客户取得巨大成功,我们能够展示高质量的结果。我们的程序和经验确保您能够找到、跟踪、测试和分析所有重要的部分,并对您的业务绩效有一个全面的了解。

使用谷歌数据工作室

原文:https://towardsdatascience.com/using-google-data-studio-55ccf4a828c4?source=collection_archive---------6-----------------------

Simple Explorer Dashboard

谷歌推出谷歌数据工作室已经有一段时间了,并提供免费使用(其中一个版本)。谷歌数据工作室是一个报告和可视化工具。

在设计报告、仪表板和/或演示文稿时,我们应考虑并阐述以下问题:

  • 这个仪表板是给谁的?
  • 仪表板的用途是什么?
  • 我们将回答哪些问题?
  • 什么是比较期?
  • 理解起来简单吗?
  • 信息的处置情况如何?

如果我们回答了这些问题,我们将拥有一个简单的、包含我们需要的信息的仪表板!

这是一个示例仪表板,您可以使用此 Google Data Studio 报告和 Google Analytics 数据源(拥有一个 Google 帐户并为您自己制作一份副本)默认情况下在 Google Analytics 中使用演示 Google 帐户,但您可以使用默认数据按钮更改为您自己的数据。

Data Sources Connectors on Data Studio

Google Data Studio 用户社区现在创建了多个数据源来进一步扩展它的用途!

在我们的左边,你可以看到本地数据源连接器。

有一些超级用户对谷歌分析和谷歌数据工作室的区别感到困惑?
嗯,它们是不同的工具谷歌分析是一个网络分析工具,而谷歌数据工作室是一个报告和仪表板的生成器,谷歌分析是一个数据源,还有其他数据源,如谷歌广告词。

使用谷歌地图的位置历史来计算和可视化我自己的交通拥堵成本

原文:https://towardsdatascience.com/using-google-maps-location-history-to-calculate-and-visualize-my-own-costs-of-traffic-congestion-26553cf07ea6?source=collection_archive---------8-----------------------

“cars passing through north and south” by Alexander Popov on Unsplash

在阿姆斯特丹自由大学(Vrije Universiteit)工作的一年里,我设计了一个可交易道路许可计划的模型,以应对高峰时段的交通拥堵。现在我从事咨询工作,我成了问题的一部分。我每周开车 4 次去一个离我公寓* 60 公里的客户那里,我亲身经历了“福利损失”,经济学上称之为被拥挤的交通所困扰。但是,当我最*寻找一个免费数据集进行实验时,我的日常通勤证明是派上了用场。当我使用谷歌地图作为我的 GPS 时,我的位置历史包含了我所有的旅行(甚至更多!)而现在它只等着我用在自己的目的上!

我可以用它来计算我在过去 18 个月中经历的福利损失吗?我可以用它来计算我在交通堵塞中花费的总时间吗?我可以用它来调查学校假期或我的出发时间对我的通勤时间有什么影响吗?所有这些问题的答案都是“是的”……或者至少是“在某种程度上”。

谷歌地图数据基本上由坐标、时间戳、精确度和活动变量组成,因此很容易找到你在特定时间点的位置,以及在某种程度上你在做什么。但是后一种方法非常不可靠,尤其是对我来说,因为汽车中的慢速经常被理解为骑自行车甚至走路。因此,我需要做的是将位置快照结合到旅行中,并将我在车上的通勤与其他旅行隔离开来。

我使用了 Python 和 pandas dataframes,这里只显示更关键的代码,但如果需要整个笔记本,请随时联系我。

我的 json 文件产生了将* 800,000 行原始数据。首先,我将时间戳和坐标转换成可以被 datetimegeodesic 模块解释的格式。

with open (‘Location History.json’) as f:
 data = json.load(f)
df = pd.DataFrame(data[‘locations’])
df = df[[‘accuracy’,’timestampMs’,’latitudeE7',’longitudeE7']].copy()
df[‘timestampMs’] = df[‘timestampMs’].astype(float)/1000
df[‘datetime’] = df[‘timestampMs’].apply(lambda t: dt.datetime.fromtimestamp(t))
df[‘latitudeE7’] = df[‘latitudeE7’]/10**7
df[‘longitudeE7’] = df[‘longitudeE7’]/10**7

现在我已经可以删除 2017 年之前的所有内容了,因为那时我还没有车。通过将时间戳拆分成时间和日期,并应用 datetime.weekday 功能,我可以识别周末,并将它们从数据集中删除。然后,我输入我的公寓和我要去的客户的坐标作为参考点。使用测地线模块,我可以计算出每个时间点我与客户的距离。按天分组,我会选择那些我离客户办公室的最小距离小于 500 米的日子。我 100%确定我在业余时间从来没有经过那里,所以这个属性立即标识了我通勤上班的那一天。

distance_client_by_date = df.groupby('date', as_index = False)['distance_client'].min().apply(lambda x: x)
trip_days = distance_client_by_date.loc[distance_client_by_date['distance_client']<0.5].copy()
df_trips=df.loc[df['date'].isin(trip_days['date'])].copy()

接下来,我定义了两个不同的高峰,一个是早上 7:00 到 9:30 的高峰,另一个是晚上 4:00 到 8:30 的高峰。不在这些时间段内的所有内容都将被删除。早上,确定旅程很容易,因为我的位置要么在家里,要么在车里。没有其他可能性。一旦我离家有了一段距离(> 100 米),这意味着我已经在车上,正在路上。当我离我客户的位置比较*的时候(< 200 米,因为接收不好,所以准确度较低),我就到了。我为行程设置了一个二进制指示器:

np.where((df_trips['distance_home'] > 0.1) & (df_trips_periods['distance_client'] > 0.2) & (df_trips_periods['period']=='Morning'), 1,0 )

具有这些属性的某一天早高峰期间的所有数据点构成一次旅行。
晚上,事情有点复杂,因为到家后,我不一定会呆在家里。我需要确定离开客户办公室后最早的时间点,即我与公寓的距离小于 100 米。否则,再次去 oude kaasblokjes 商店可能会被错误地计入我的通勤时间。因此,我创建了一个到家时的标志,然后选择最早的(“最小”)时间点,这发生在每个晚高峰:

df_trips['arrived'] = np.where((df_trips_periods['smth_dist_home'] < 0.1) & (df_trips_periods['period']=='Evening'), 1,0)df_trips['arrival_time'] = df_trips.loc[df_trips['arrived']==1].groupby('peak')['time'].transform('min')

通过时间增量功能,我计算出高峰旅行中最早和最晚时间点之间的时间增量。在清除了一些奇怪的异常值后,我可以从有趣的部分开始,调查大约 300 次旅行(通过比较谷歌地图在同一天记录的内容,很容易检查异常值。好像有几天我都没有察觉就瞬移了)。我可以运行一些回归模型,但是图片胜于雄辩。

我感兴趣的一件事是,在学校放假期间,我的通勤时间是否会明显减少。主观上,道路感觉更加空旷,但是数据会支持我的直觉吗?我在学校正式放假期间添加了一个标记,并在密度图中绘制了假期和非假期的旅行时间:

图表支持了我的直觉。假期的出行时间分布更窄,峰值更靠左。我似乎在学校假期之外的路上时间更长。但这并不意味着交通流量马上就会减少。也许我在夏天温暖的日子里提早下班,这也是学校假期,因此通过在高峰的早期边缘时段离开来避免高峰交通拥堵(如果读者碰巧是我的雇主:这是一个严格的假设场景,当然我每天都工作直到我崩溃)。

密度图显示我的出发时间与学校假期无关。

出发时间一般对我的旅行时间有影响吗?我预计会出现非线性影响,传播时间一开始会增加,但在大部分峰值过去后,传播时间会再次下降。我使用出发时间作为因变量旅行时间的线拟合的解释变量来选择 regplots。为了验证我对非线性效应的怀疑,我们可以用不同次数的多项式来比较几个图。

在所有情况下,高峰期间的曲线凹度显示了可疑的影响,但鉴于在稍后的出发时间观察到的少数数据点,这不应该太认真——如果你打算这样做的话。我的另一个问题是,一周中有明显的不同吗?在荷兰,周三是典型的“爸爸日”,父母可以休育儿假,交通也更加顺畅。

周三虫群当然有很重的底(这样的语境下用“thicc”可以吗?),表明更多的观察和更短的传播时间,但是更多的观察当然有助于进一步研究差异是否真正显著。
最后,我是否调整了自己的出行行为以避免拥堵?毕竟,经济学家通常期望在更长的时间内建立均衡。我是否从我的日常经验中学到了,现在的旅行时间比我刚开始时短了,而且我对其他通勤者的行为一无所知?

没有。

看不到学习效果。我一次又一次驾驶同一条路线的经验并没有体现出任何避免拥堵的能力。

形象化就说到这里,作为运输经济学家,我当然也对我可怜的灵魂因交通拥堵而遭受的福利损失感兴趣。基于 41 分钟的最短行程时间和 59 分钟的*均行程时间,我得出*均 18 分钟的行程时间是由于交通拥堵造成的额外时间。对所谓的“时间价值”应用 15 欧元的标准值,这是一种在经济学中用财务术语表达时间的方法,可用于成本效益分析,这意味着我每天的福利损失大约为 9 欧元。从项目开始到现在,我进行了大约 300 次旅行,所以我的总福利损失约为 1.300 欧元,我在拥堵中度过了大约 6.000 分钟或 100 小时或 4 天。不在路上。而是纯粹靠因拥堵而多出来的出行时间。
我在车里听有声读物来打发时间,在《智人》中,作者解释道,佛教徒认为所有的痛苦都是由渴望造成的。渴望更多愉快的经历,或者渴望逃避不愉快的经历。因此,我内心隐藏的佛教徒应该克制自己,不要去想在交通拥堵中损失 4 天是否太多,因为这可能会导致对减少拥堵的渴望,最终导致我自己的痛苦。佛教徒很少是优秀的运输经济学家。

利用人性和大数据解决问题

原文:https://towardsdatascience.com/using-humanity-and-big-data-to-solve-problems-15186024c465?source=collection_archive---------5-----------------------

“Pattern Recognition” by Lachlan Hardy is licensed under CC BY 2.0

人类擅长很多事情。其中之一是模式识别,即在大量数据、图片或文本中发现突出部分的能力。

我们非常善于在相当一致的图像中发现事物。我们可以在一堆白点中发现一个星系斑点,或者在一页信中发现一个真实的单词。我们甚至可以 t8k3 a r@nd0m jumbl3 0f numb3r5 和 l3tt3r5 以及其中的 m@k3 s3ns3(我现在就不说那个了)。

人类的心灵是一种美丽而奇妙的东西。它能做这么多,比我们现在知道的还要多。这是有史以来最不可思议的计算机。

想象一下,如果你能让十几个、一百个、一千个甚至上万个人一起工作来发现模式,会有什么样的成就。你可能会有令人难以置信的新发现,发现以前从未被理解的事物,或者发现以前从未见过的事物。

Zooniverse Galaxy 3D project

这是 Zooniverse 项目背后的想法之一。它是“世界上最大、最受欢迎的人力研究*台”。

研究人员创建了一个项目,比如说尝试在恒星图片中寻找星系。他们解释要寻找什么,并提出问题来帮助识别。然后,志愿者们开始着手这项工作,并对他们认为可以处理的尽可能多的数据进行分类。

你让尽可能多的人对随机照片进行分类,希望你能得到一个可验证的数据——比如十几个人说“是的,那个斑点是一个星系,就是这种类型的星系”。然后你可以用望远镜(无论哪种最好)对准那个星系来验证数据,节省随机搜索的时间来验证可能不存在的东西。

它已经被用于旧文件,寻找物种,寻找粒子,当然还有更多的星系搜索。

The Hunt for Planet 9

Zooniverse 说:“21 世纪研究的主要挑战是处理我们现在可以收集的关于我们周围世界的大量信息。计算机可以提供帮助,但在许多领域,人类的模式识别能力——以及我们的惊讶能力——让我们更胜一筹。”

我自己对一些项目进行了分类,与成千上万的其他志愿者一起,项目背后的研究人员能够产生真正的科学,真正的数据,并做出可能需要几十年才能完成的发现。

在志愿者的帮助下,Zooniverse 正在以前所未有的速度拓展理解的边界。

通过机器学习图像分割增加发展中国家对太阳能的采用

原文:https://towardsdatascience.com/using-image-segmentation-to-identify-rooftops-in-low-resolution-satellite-images-c791975d91cc?source=collection_archive---------9-----------------------

这项工作由 Jatinder Singh 和 Iresh Mishra 共同完成。也感谢索拉博·辛格的指导。

过去,我曾写过机器学习如何在清洁能源领域带来一个新时代,以及我们如何利用一个 ML 爱好者社区来构建解决方案。在本文中,我将分享其中一项任务的结果(从卫星图像中识别屋顶)。

由于来自印度(和大多数发展中国家)的卫星图像的质量是低分辨率的,手头的任务的复杂性增加了。类似的解决方案如谷歌天窗项目仅适用于高分辨率图像,不适用于大多数发展中国家。

Satellite images of Delhi

我们的第一步是确定最适合这项任务的算法。

步骤 1:算法的识别

我们最初开始使用计算机视觉的图像分割算法。目标是通过识别屋顶的边缘将图像分割成屋顶和非屋顶。我们的第一次尝试是使用分水岭图像分割算法。当提取图像中的接触或重叠对象时,分水岭算法特别有用。该算法速度很快,计算量小。在我们的例子中,一幅图像的*均计算时间是 0.08 秒。

以下是分水岭算法的结果。

Original image(left). The output from the Watershed model(right)

如你所见,输出不是很好。接下来,我们实现了 Canny 边缘检测。像 Watershed 一样,这种算法也广泛用于计算机视觉,并试图从不同的视觉对象中提取有用的结构信息。在传统的 Canny 边缘检测算法中,有两个固定的全局阈值来滤除伪边缘。然而,随着图像变得复杂,不同的局部区域将需要非常不同的阈值来准确地找到真正的边缘。所以有一种技术叫做 auto canny,自动设置下限和上限。下面是自动报警的 Python 函数:

Canny 边缘检测器处理一幅图像的*均时间约为。0.1 秒,很不错了。其结果优于分水岭算法,但精度仍不足以满足实际应用。

The output from the Canny Edge detection algorithm

上述两种技术都使用图像分割,并且在不理解我们试图检测的对象(即屋顶)的上下文和内容的情况下工作。当我们用物体(即屋顶)的样子来训练算法时,我们可能会得到更好的结果。卷积神经网络是理解图像上下文和内容的最先进技术。

如前所述,我们希望将图像分割成两部分——屋顶或非屋顶。这是一个语义切分问题。语义分割试图将图像划分成语义上有意义的部分,并将每个部分分类到预定的类别之一。

Semantic Segmentation (picture taken from https://www.jeremyjordan.me/semantic-segmentation/)

在我们的例子中,图像的每个像素都需要被标记为屋顶的一部分或者不是。

We want to segment the image into two segments — roof and not roof(left) for a given input image(right).

步骤 2:生成训练数据

为了训练 CNN 模型,我们需要一个带有印度建筑及其相应面具的屋顶卫星图像的数据集。没有可用于印度建筑物带有面具的屋顶图像的公共数据集。所以,我们必须创建自己的数据集。一组学生标记了图像并创建了蒙版图像(如下)。

Generating dataset by marking the edges

这是屏蔽后的最终输出。

虽然我们知道 U-Net 模型使用较少数量的图像作为数据,但首先,我们的训练集中只有 20 张图像,这远远低于任何模型,甚至我们的 U-Net 也无法提供结果。处理较少数据的最流行的技术之一是数据扩充。通过数据扩充,我们可以使用数据集中的图像生成更多的数据图像,只需在原始图像中添加一些基本的改变。

例如,在我们的例子中,任何屋顶图像当旋转几度或水*或垂直翻转时,将作为新的屋顶图像,假设旋转或翻转是以精确的方式,对于屋顶图像和它们的遮罩。我们在已经标记的图像上使用 Keras 图像生成器来创建更多的图像。

Data Augmentation

步骤 3:预处理输入图像

我们试图锐化这些图像。我们使用了两种不同的锐化滤镜——低/软锐化和高/强锐化。锐化之后,我们应用双边滤波器来减少锐化产生的噪声。下面是一些用于锐化的 Python 代码行

低锐化滤波器:

高锐化滤波器

下面是输出。

我们将单独写一篇关于锐化图像的文章,所以这里将跳过更多的细节。

步骤 4:训练和验证模型

我们生成了 445 幅图像的训练数据。接下来,我们选择使用 U-Net 架构。U-net 最初用于生物医学图像分割,但由于它能够达到良好的效果,U-net 正在应用于各种其他任务。是图像分割的最佳网络架构之一。在我们使用 U-Net 模型的第一种方法中,我们选择使用学习率为 0.0001 的 RMSProp 优化器,具有骰子损失的二元交叉熵(这里的实现来自)。我们运行了 200 个时期的训练,*均(最后 5 个时期)训练骰子系数是. 6750,验证骰子系数是. 7168

以下是我们从验证集(40 幅图像)中获得的第一种方法的结果:

Predicted (left), Target (right)

Predicted (left), Target (right)

正如你所看到的,在预测的图像中,在预测的遮罩的中间和角落有一些建筑物结构的 3D 痕迹。我们发现这是由于骰子的丢失。接下来,我们使用学习速率为 1e-4、衰减速率为 1e-6 的 Adam 优化器来代替 RMSProp。我们使用 IoU 损耗而不是 BCE+Dice 损耗和 Keras 的二进制精度指标。训练进行了 45 个周期。*均(最后 5 个时期)训练精度为:0.862,*均验证精度为:0.793。以下是来自第二种方法的验证集上的一些预测掩码:

这是测试数据的结果

Test data

Test data

我们很高兴看到目前的结果,并希望通过更多的数据进一步改善结果。

最后,我们还要感谢 Abhigyan 和 Aman 提供的训练数据。如果有人想进一步帮助我们,请加入我们的 git 回购或联系 rudradeb@omdena.com

用整数线性规划解决数独难题

原文:https://towardsdatascience.com/using-integer-linear-programming-to-solve-sudoku-puzzles-15e9d2a70baa?source=collection_archive---------1-----------------------

如果你更擅长线性编程,而不是用传统的方法解决数独难题,那么这篇博文就是为你准备的!

我刚刚结束了研究生院的第三个学期,我想写一篇关于我在算法课程中学到的一些东西的短文。我最喜欢的话题是线性编程,事实证明同样的原理也适用于解决数独难题。

如果你可以用一个线性目标函数和线性不等式约束,线性规划 (LP)来表述一个问题,那么它就是寻找其最优解的有力工具。换句话说,如果你能把一个问题写成:

Primal (left) and dual (right) formulations of linear programming problems — maximize or minimize an objective function, subject to inequality constraints where b, c, x and y are vectors and A is a matrix.

你可以找到最优参数 x 或者 y. (比如 LP 可以用来分配工作,最小化运输成本,或者创造健康饮食。)LP 的一种特殊类型是整数线性规划 (ILP),由此我们将参数 xy 限制为整数

在这篇文章中,我想研究 ILP 的一个特殊应用:解决数独。(感谢西南航空机组提供我的拼图和零食!)

Courtesy of the December 2017 issue of Southwest Magazine. I will show how to solve “Hard 1” using LP.

目标函数

与典型的 LP 或 ILP 问题不同,数独没有比另一个更好的解决方案。在我们的例子中,我们希望找到任何可行的解决方案——一个满足我们的约束的方案。因此,我们可以指定一个任意的目标函数。

线性约束

一个难题包括填充一个 9×9 的网格,这样每一行、每一列和每一个 3×3 的子网格只包含一个整数值。换句话说,你不能在左下方的第一行、第一列或第一个子格子中输入另一个数字。

因为每个框可以填充九个值,并且我们被约束在九行九列中的每一行,所以我们有 9 = 729 个参数。下面我们将用 v (值) r (行) c (列)来索引 x 中的这些值。

更具体地,我们可以将我们的目标函数和线性约束公式化如下:

Primal formulation for solving a generic sudoku problem. Note the arbitrary objective function mentioned earlier. Most of the heavy lifting occurs within the four constraints above. Adapted from http://profs.sci.univr.it/~rrizzi/classes/PLS2015/sudoku/doc/497_Olszowy_Wiktor_Sudoku.pdf.

第一个约束要求每个单元格(由其行和列表示)包含一个值。第二个和第三个约束保持列和行中分别只包含一个值。最后一个约束确定了在每个子网格中只能找到一个值。

当您试图解决任何特定的数独时,甚至需要指定更多的约束,即每个非空单元格的初始状态。

解开谜题

我使用名为 PuLP 的用于解决 LP 问题的 Python 包来解决上面的“困难 1”数独。纸浆有一些很好的现有文档关于如何使用它的软件来解决这个问题。这是用 LP 解决数独难题的又一个详解,附带补充码。

我改编的纸浆的数独例子可以在这里找到。请注意,我的编辑约束只是满足我的特定谜题的起始状态。

我希望你喜欢我解决数独难题的乐趣。说到捣乱,请注意:以下是我的谜题解答。

相关阅读

  • 达斯古普塔、帕帕迪米特里奥和瓦齐拉尼的算法,第 7 章
  • CLRS ,第 29 章

使用 SSH 在远程 Docker 容器上运行 Jupyter

原文:https://towardsdatascience.com/using-jupyter-notebook-running-on-a-remote-docker-container-via-ssh-ea2c3ebb9055?source=collection_archive---------3-----------------------

Own source

设置您的环境,使之与远程实例中运行的 Docker 和 Jupyter 一起工作

在我的研究中,我使用机器学习/深度学习算法,我主要使用 Python 开发这些算法。因此,我发现测试不同的框架很有用(比如 Keras、PyTorch、Tensorflow… )。这导致我使用 Docker ,特别是 ufoym/deepo 图像,因为它提供了一个非常完整的环境。

我使用一台装有 GPU 的远程机器,在那里我安装了 Docker。在编程和测试一些代码片段的时候,我发现使用 Jupyter 真的很有帮助。我以前在本地使用过 Jupyter…但是这里的问题是我如何远程使用运行在另一台机器上的 Jupyter。除此之外,如果我在我的远程机器上使用 Docker 容器会怎么样呢?

在本教程中,我将尝试分享我是如何解决这个难题并使本地使用 Jupyter web 应用程序在远程机器上运行代码成为可能的经验。

我的工作环境

让我首先说明我的工作环境设置。

Own source, drawn using Google Draw

  1. 我用我的普通笔记本电脑作为主机。
  2. 我通过 ssh 连接到我部门的服务器(远程)。
  3. 然后,我连接到服务器中一台特定的机器,这台机器有 GPU。
  4. 最后,我启动了那台机器中的码头工人集装箱。

在我的例子中,我使用的机器是上图中标为 GPU 的机器,它恰好只能从服务器中的另一台机器访问。因此有了双 ssh……但是在你的情况下,你可以从外部世界直接连接到你的 GPU 机器。

这听起来很乱,但请耐心听我说,你只需要一劳永逸地组织起来。

先决条件

码头工人

确保在你的远程机器上安装了docker。如果你不熟悉 Docker,请查看一些可用的资源(我发现这个和这个很有帮助)。如果您的目标是 GPU 支持环境,请查看下一步。

GPU 支持

如果您的远程机器有 GPU,您可能想利用这一事实。确保你已经安装了 NVIDIA 驱动 。还需要安装 nvidia-docker 。请注意,通过安装 nvidia-docker,我们会自动安装最后一个稳定版本的 docker-ce ,因此您之前不需要显式安装 docker。

设置连接

主机—远程

Jupyter 笔记本运行在机器的某个端口上。因此,基本的想法是使该端口可以从您的主机到达。幸运的是, ssh 提供了-L 选项来指定端口转发。

$ ssh -L <host port>:localhost:<remote port> user@remote

在我的例子中,我在两端使用端口 9999,即 <主机端口> = <远程端口> = 9999。

远程— GPU

这里的方法和以前完全一样。

$ ssh -L <remote port>:localhost:<GPU port> user@GPU

再次,我用 <主机端口> = <远程端口> = 9999

GPU — docker

这一步略有不同。首先,您需要使用您喜欢的 docker 映像创建一个 docker 容器。在我的例子中,如上所述,我使用的是 ufoym/deepo 。因为我想要 GPU 支持,所以我将使用nvidia-docker来创建容器。

$ nvidia-docker run -it \
-p <GPU port>:<container port> \
--name <container name> \
ufoym/deepo  bash

注意选项-p,它告诉 docker 容器进行端口转发。通过这种方式,我们可以从外部世界访问在某个端口上运行的应用程序。这里我也用 <主机端口> = <远程端口> = 9999

顺便说一下,创建容器时一个非常有用的选项是-v,它允许您从 docker 容器中访问机器文件。

运行 Jupyter

一旦所有的隧道都建立好了,我们就可以启动我们的 jupyter 应用程序了。我们将使用0.0.0.0 ip 和创建 docker 容器实例时使用的相同端口。同样,在我的例子中,我使用了选项--allow-root,因为我在我的容器中是 root,除非我使用这个选项,否则 Jupyter 不会运行。

$ jupyter notebook --ip 0.0.0.0 --port <container port> --allow-root

哦,如果你喜欢新的很酷的 jupyter lab ,就用下面的命令代替。

$ jupyter lab --ip 0.0.0.0 --port <container port> --allow-root

现在,在我的主机上,我只需简单地进入 localhost:9999 就可以了。

旁注

启用更多端口

如果您有一个类似的工作环境,我建议启用更多的远程访问端口。您可以使用-L <local port>:localhost:<remote port>将它们添加到您的 ssh 命令中。这样,如果您碰巧在 docker 机器的某些端口上运行其他服务,您可以轻松地远程访问它们。

自动 ssh 登录

当您向 ssh 命令添加更多选项时,它会增加大小。一个选项是在~/.ssh/config文件下定义一个主机。在我的例子中,我添加了一个用户<name>:

Host <name>
  Hostname <remote IP>
  Port <remote port for SSH (typically 22)>
  IdentityFile <path to rsa key>
  LocalForward 9999 127.0.0.1:9999

有误差吗?

测试隧道是否工作的一个好方法是使用 python 中的http.server。这样,您可以检查每个阶段端口是否被正确转发。使用以下命令在特定端口上运行简单的 http 服务器。

$ python -m http.server <remote port>

注意,这适用于 python3,对于 python2 版本,使用python -m SimpleHTTPServer <remote port>代替。

如果你有任何其他困难,请在评论中留下,我很乐意帮助你!

使用 LDA 构建缺失的 Yelp 特征

原文:https://towardsdatascience.com/using-lda-to-build-a-missing-yelp-feature-43436e575d65?source=collection_archive---------9-----------------------

如果你曾经在旧金山的金融区外出喝酒,你可能会偶然发现 Mikkeller 酒吧。这家丹麦啤酒馆是下班后和朋友一起去的好地方,这里的气氛非常活跃,足以进行精彩的交谈。有着丰富的名单和选择,这是我想经常去喝酒的地方。

现在,如果我在 Yelp 上搜索 Mikkeller,我不仅会得到酒吧本身,还会得到该地区类似简介的酒吧,如果我想尝试一个有类似氛围的地方,这很好。

但是,当您在不同的位置搜索时,这种类型的搜索不会转换。例如,如果我试图搜索芝加哥的 Mikkeller 酒吧:

虽然通过搜索特定的关键字(如 beer hall 或腹肌)可能会得到类似的结果,但我觉得应该实现更具体的搜索方法。为什么 Yelp 没有一个功能可以让用户在他们喜欢的栏上输入内容,然后在用户选择的位置上扩展搜索?这种搜索方法也能够捕捉到不太明显的方面,如环境。因此,我决定在我的第四个 Metis 项目中,我将使用无监督学习和 NLP 技术来构建这个功能。

数据

数据来源:

为了这个项目,我最终从 Yelp 挑战数据集中获得了我的数据。Yelp 提供了一个公开的数据集,这是一个无价的资源,因为 Yelp 的 TOS 是非常反网络抓取的。该数据集本身非常庞大,因为有超过 600 万条针对 800,000 多家不同企业的评论,分布在美国和加拿大的 10 多个不同的大都市地区。如此多的地理多样性是我的项目的额外收获,因为我希望它是位置不可知的。Yelp 的数据存储在。json 格式,所以我使用本地 MongoDB 实例查询和过滤数据。回想起来。json 文件非常大(评论文本 JSON 为 4.72 GB),如果我将所有内容都转移到一个大内存 AWS 实例中,那么这个项目的数据分析会更加高效。我的 Macbook Air 的 8 GB 内存不足以在不微观管理计算机资源的情况下对数据进行分析。

数据过滤:

将我的数据加载到 MongoDB 后,我进行数据处理的第一步是只过滤酒吧的企业列表。我的第一个方法(使用 pymongo )是执行一个正则表达式,匹配其类别类型中包含“bar”的任何业务。“酒吧”还必须有至少 50 个评论,以便有足够的文本数据进行推断:

# Create subset of business that contain bars in question
db.business.aggregate([
     {"$match": {'categories': {'$regex': 'Bars'}}},
     {"$match": {"review_count": {"$gte": 50}}},
     {"$out": "bars"}]);

这种方法最终将搜索的企业数量从 180,000+减少到 5000+。然而,我很快意识到的一个怪癖是,regex 方法不仅捕获酒吧或体育酒吧等酒吧类型,还捕获寿司店。我最终变得更加严格,编写了两个函数来返回一个只包含特定类别(在本例中为“酒吧”)的企业:

def check_for_cat(categories, cat_type):
    """
    Returns whether business is a given type, returns a boolean
    """
    # splits input category list from json file
    categories_list = categories.split(',')
    # loop through each category to see if it is equal to cat_type
    for category in categories_list:
        # lowercase the category & strip any extra spaces
        mod_cat = category.strip().lower()
        if mod_cat == cat_type:
            return True

    return False

def filter_yelplist(locations, cat_type):
    """
    Function that returns list of filtered yelp locations
    """
    return [loc for loc in locations
            if check_for_cat(loc['categories'], cat_type) == True]

这种额外的过滤给了我大约 4000+条。

接下来,我必须将每个酒吧的评论加入酒吧列表。通常在 SQL 数据库中,这可以通过一个简单 join 命令来完成。然而,MongoDB 有一个 NoSQL 数据库结构,所以我不能这样做(我用$lookup 命令做了实验)。我最终编写了以下查询来获取相关数据:

# Create subset of reviews that contain the bar ids
locations = list(db.bars.find({}, {'_id': 0, 'business_id': 1, 'categories': 1}))
filtered_bars = filter_yelplist(locations, 'bars')
allbar_ids = [i['business_id'] for i in filtered_bars]db.reviews.aggregate([
   {'$match': {'business_id': {'$in': allbar_ids}}},
   {"$out": "bar_reviews"}]);

在所有的数据处理之后,我最终得到了一个包含 4000 多个棒线的数据子集,每个棒线至少有 50 条评论。总共有 800,000 多条评论可供我分析。

文本处理

在过滤了数据之后,我仍然需要处理评论文本本身,然后将它传递给分词器。我做了三件事:

  1. 使用正则表达式删除数字和标点符号
  2. 将所有大小写类型转换为小写
  3. 将所有单词词条化

词汇化很重要,因为我不想让模型包含同一个单词的不同形式。词汇化完成这个任务是因为它返回单词的词汇或“词典形式”,所以给定单词的复数和分词形式被替换为基本形式。例如,“行走”的引理会是“行走”,而“更好”的引理会是“好”。

特征工程

我觉得酒吧的氛围非常重要,因此我在用户评论中使用了 NLP 来捕捉这种氛围。在尝试了不同的令牌矢量化工具和降维技术之后,我最终使用了计数矢量化和潜在狄利克雷分配(LDA)的组合来给我最大的可解释性。

…向量化…

在执行矢量化的过程中,我需要从评论文本中生成一个相关的标记列表。虽然 NLTK 提供了要排除的英语停用词的基本集合,但是在主题生成中还需要排除一些额外的标记。最终出现在排除列表中的令牌类型分为两类:与位置相关的和与食物相关的。为了使模型不可知位置,排除了与位置相关的标记,同时排除了与食物相关的标记,以便主题集中在饮料和环境上。就矢量器的类型而言,CountVectorizer 模型最终比 TFIDF 的性能更好。我相信 CountVectorizer 比 TFIDF 表现得更好,因为描述一个酒吧的重要词(如啤酒、音乐、饮料)会重复出现,CountVectorizer 最终会促进重复,而 TFIDF 则会惩罚它。

主题建模

通过使用 LDA,我能够执行主题建模并生成 9 个主题,我认为这些主题代表了我的数据集中不同类型的条形:

其中两个酒吧原型最终成为最具描述性的(户外和早午餐),因为大多数酒吧最终都被这两个主题所描述。这可以通过这两个主题如何映射到 TSNE 图来证明:

其余的 7 个主题最终变得更加具体,因为它们通常描述了数据集中的几个条形。举例来说,街机和视频游戏酒吧最终被映射到我的 TSNE 情节如下:

分类特征

除了 NLP 生成的特征之外,模型中还添加了一些有价值的分类特征。Yelp 数据集实际上包含许多分类特征:例如,一个地方是否适合跳舞,或者他们是否有电视可用。然而,我决定不利用这些特性,因为我想通过主题建模来确定这些特性的代理。因此,我最终直接从数据集中提取的唯一分类特征是企业的价格范围。

虽然主题建模让我了解了酒吧的氛围,但我也希望我的模型关注酒吧的主要酒精类型。为了做到这一点,我决定在评论中放大某些关键词的存在。例如,对于每个小节,我检测到标记“威士忌”被提及的次数。将该计数除以总评论数,我得到了一个比例,它表明了一个给定的酒吧有多少是威士忌酒吧。我最终在关键词上创建了这些存在类型分类特征:威士忌、伏特加、啤酒、葡萄酒、龙舌兰酒、朗姆酒、烈酒、杜松子酒、白兰地、烧酒、苹果酒和清酒。

推荐引擎

给出建议

随着要素的建立,我创建了一个管道来为我的数据集中的每个条生成要素。通过将输入条形图的余弦相似度与数据集中的所有其他条形图进行比较,给出了一个建议。如果有多个条形图作为输入,则使用输入条形图*均矢量的余弦相似度。这种相似性比较形成了我的推荐引擎的基础。基于数据集,以下是一些可能的建议:

Some recommendations if you are the TGIF’s type of person

If you are interested in Irish pubs there appears to be plenty of options

该推荐引擎随后通过 dashboard 应用程序和交互式 Tableau 仪表板部署在 Heroku 上,如下所示:

如果您想自己尝试一些建议,您可以在这里访问应用程序。

未来的工作

如果给我更多的时间来扩展这个项目,我会做一些改进:

  • 更多相关数据:当前的数据集不包括旧金山或纽约州等主要都会区的酒吧位置,我认为这将有助于创建更相关的建议
  • 链接交互图形:如果这个功能真的是通过 Yelp 或者类似的服务部署的,我觉得交互图形会是一个很大的卖点。因此,我希望链接 Tableau 仪表盘和 dashboard 界面,以便对最终用户进行更大程度的控制。

如果你想了解更多关于这个项目的信息,你可以在我的 Github repo 找到代码和数据。

用线性回归法模拟大学篮球比赛中的得分差距

原文:https://towardsdatascience.com/using-linear-regression-to-model-point-spreads-in-college-basketball-f7da5811c3da?source=collection_archive---------3-----------------------

显而易见,预测谁将赢得大学篮球赛的最简单的方法就是预测谁将获得更多的分数。维加斯簿记员预测的点差可以高度预测获胜概率,但有时点差不可用,例如当你为锦标赛整理数据并试图预测第二轮、第三轮和第四轮比赛的结果时。对于这些情况,这篇文章描述了三种预测分数分布的尝试:

  1. 试探法:一种线性模型,使用分析师根据直觉或探索性分析的结果选择的预测值。
  2. 双向逐步模型:一种线性模型,使用由算法选择的预测因子,该算法根据赤池信息标准(AIC)设计用于优化模型拟合。
  3. 最小角度回归:一种线性模型,使用数据集中的所有预测值,但对不同的预测值赋予不同的权重。这是一个与双向逐步相似的过程,但它不是从模型中删除预测值,而是降低其系数的权重。

这些模型是使用从 sports-reference.com 的下载的 351 支甲级队的游戏日志数据构建和测试的。训练数据由 2014–2017 年的游戏日志组成,模型在 2017–18 年的游戏日志上进行测试。

模型拟合

启发式模型

尝试的第一个模型是线性模型,使用从领域专业知识和探索性分析的组合中选择的预测器。这里考虑的所有数据都是差距——一个队与另一个队在某些事件(如盖帽)上的差异。说tov.spread = 5意味着一个队比他们的对手多失误五次。

一个方便的探索工具是GGally::ggpairs()绘图工具。它生成一个图形矩阵,显示数据集中每对变量之间的关系以及它们的相关性和分布。最下面一行显示了不同变量与点扩散的相互作用。

关注图的底部行,其显示了各种表现指标和分差之间的线性关系,投篮命中率、三分命中率、助攻、防守篮板和失误似乎与分差有很强的关系。

使用这些变量的线性模型是一个好的开始!调整后的 R *方为 0.901 意味着我们已经解释了数据中 90%的方差。残差——单个预测值与其实际值之间的差异——似乎以零为中心,这很好。但当点差最大时,错误率会更高,这表明可能还有改进的空间。

也许更多的算法方法会产生更好的模型!

双向逐步

一种这样的算法方法是使用双向逐步变量选择的线性建模-一种迭代测试预测变量组合并选择最小化 AIC 的模型的方法。在每一次迭代中,新的变量被添加到模型中,模型被测试,如果变量不能提高拟合度,就被删除( ISLR )。

用这种方法选出的最佳模型包括 10 个变量。这次我们包括价差,但也包括三分球和罚球的数量以及进攻篮板的价差。

这个模型更好!它解释了点差变化的 95.5%。投篮命中率仍然是模型中最强的预测因素,但加入其他变量显然是有帮助的。

我们的残差仍然具有重尾分布,换句话说,当利差非常高或非常低时,我们的预测仍然不太准确。

到目前为止,我们尝试的每一个模型都是“贪婪的”,在某种意义上,预测变量被包括或不被包括在没有灰色区域的范围内。最终尝试的模型采用了不同的方法。

最小角度回归

最小角度回归(LAR)也是一种迭代预测值选择方法,但它不是包含或排除变量的二元决策,而是包含有助于提高模型拟合度的变量。

使用与目标具有最高相关性的变量来启动模型。然后调整预测变量的系数,直到另一个变量具有比它更高的相关性,此时第一个系数被锁定到下一个系数的运动中。重复该过程,直到找到最佳模型。如果变量的系数缩小到零,变量可以从模型中排除,但这个过程允许在决策中有更多的细微差别( ESLR )。

LAR 产生的变量和系数看起来比双向逐步方法更类似于启发式,更侧重于分布变量(A 队比 B 队多 5 次失误),而不是计数变量(A 队有 15 次失误,B 队有 10 次失误)。

至于模型拟合,LAR 正好介于其他两种方法之间。该模型解释了数据中 92%的差异。

模型评估

测试数据由 2017–2018 游戏日志组成,涵盖 3316 款游戏。我们的三个模型是根据误差项的分布以及*均绝对误差(MAE)来评估的。除了上述三个模型拟合,还测试了另外两个集合预测:

  1. 总体*均值—三次初始预测的*均值
  2. 总体中值-三个模型的预测中值

没有一个模型完美地反映了实际分数的分布,特别是在极端情况下。但是,这就是说,双向逐步看起来相当不错!在零附*有一个适当的倾斜,重尾描绘了实际点差分布的大致轮廓。

双向逐步回归也使 MAE 最小化,然后是总体*均值和中位数模型。

结论

双向逐步模型证明了样本外的准确性,并解释了数据中的最大差异。这显然是预测点扩散的最佳模型。

接下来,我计划使用点数分布作为分类模型的输入,来预测团队获胜的可能性。

测试集中的游戏日志于 2018 年 1 月 27 日下载

代码和数据可以在这里找到: github 。

使用 LSTMs 进行股市预测(Tensorflow)

原文:https://towardsdatascience.com/using-lstms-for-stock-market-predictions-tensorflow-9e83999d4653?source=collection_archive---------1-----------------------

在本教程中,你将看到如何使用一个被称为长短期记忆的时间序列模型。从设计上来说,LSTM 模型非常强大,尤其是在保留长期记忆方面,你将在后面看到。在本教程中,您将处理以下主题:

  • 理解为什么你需要能够预测股票价格的变动;
  • 下载数据——您将使用从 Alphavantage/Kaggle 收集的股市数据;
  • 拆分训练测试数据,并执行一些数据标准化;
  • 激发并简要讨论 LSTM 模型,因为它允许提前一步以上进行预测;
  • 用当前数据预测和可视化未来股票市场

注意:但在我们开始之前,我并不主张 LSTMs 是一个高度可靠的模型,可以完美地利用股票数据中的模式或者可以在没有任何人在回路中的情况下盲目使用。我这样做是作为一个实验,纯粹出于机器学习的兴趣。在我看来,该模型已经观察到了数据中的某些模式,从而使其能够在大多数时候正确预测股票走势。但是这个模型能不能用于实际用途,就看你自己了。

为什么需要时间序列模型?

您希望正确地模拟股票价格,因此作为股票购买者,您可以合理地决定何时买入股票,何时卖出股票以获取利润。这就是时间序列建模的用武之地。你需要好的机器学习模型,它可以查看数据序列的历史,并正确预测该序列的未来元素将会是什么。

警告:股票市场的价格是高度不可预测和不稳定的。这意味着数据中没有一致的模式可以让你*乎完美地模拟一段时间内的股票价格。不要相信我,相信普林斯顿大学的经济学家伯顿·马尔基尔,他在他 1973 年的书《漫步华尔街》中认为如果市场是真正有效的,股票价格一公布就立即反映了所有的因素,那么一只蒙着眼睛的猴子向报纸上的股票上市投掷飞镖应该和任何投资专业人士做得一样好

然而,我们不要完全相信这只是一个随机或随机的过程,机器学习没有希望。让我们看看您是否至少可以对数据进行建模,以便您做出的预测与数据的实际行为相关联。换句话说,你不需要未来的确切股票价值,而是股票价格的变动(也就是说,它在不久的将来是上涨还是下跌)。

下载数据

您将使用来自以下来源的数据:

  1. 阿尔法优势。然而,在开始之前,你首先需要一个 API 密匙,你可以在这里免费获得。之后,您可以将该键分配给api_key变量。
  2. 使用本页中的数据。您需要将 zip 文件中的股票文件夹复制到您的项目主文件夹中。

股票价格有几种不同的风格。他们是,

  • 开盘:当天的开盘价
  • 收盘:当天的收盘价
  • 高:数据的最高股票价格
  • 低:当天最低的股票价格

从 Alphavantage 获取数据

您将首先从 Alpha Vantage 加载数据。因为您将利用美国航空公司的股票市场价格来进行预测,所以您将自动收报机设置为"AAL"。此外,您还定义了一个url_string,它将返回一个 JSON 文件,其中包含美国航空公司在过去 20 年中的所有股票市场数据,以及一个file_to_save,它将是您保存数据的文件。您将使用预先定义的ticker变量来帮助命名这个文件。

接下来,您将指定一个条件:如果您还没有保存数据,您将继续从您在url_string中设置的 URL 获取数据;你将把日期、盘低、盘高、成交量、收盘价、开盘价存储到 pandas 数据框架df中,然后保存到file_to_save。但是,如果数据已经存在,您只需从 CSV 加载它。

从 Kaggle 获取数据

Kaggle 上的数据是 csv 文件的集合,您不必做任何预处理,因此您可以直接将数据加载到 Pandas DataFrame 中。确保将数据下载到项目主目录中。因此股票文件夹应该在项目主目录中。

数据探索

在这里,您将把收集的数据打印到数据框中。您还应该确保数据按日期排序,因为数据的顺序在时间序列建模中至关重要。

数据可视化

现在让我们看看你有什么样的数据。您需要随时间推移出现各种模式的数据。

这张图表已经说明了很多事情。我选择这家公司而不是其他公司的具体原因是,随着时间的推移,这张图表充满了不同的股价行为。这将使学习更加稳健,也给你一个机会来测试对各种情况的预测有多好。

另一个需要注意的是,接* 2017 年的数值要比接* 20 世纪 70 年代的数值高得多,波动也更大。因此,您需要确保数据在整个时间段内表现为相似的值范围。您将在数据标准化阶段处理这个问题。

将数据分成训练集和测试集

您将使用中间价,该中间价通过取一天中最高和最低记录价格的*均值来计算。

现在,您可以拆分训练数据和测试数据。训练数据将是时间序列的前 11,000 个数据点,其余的将是测试数据。

现在您需要定义一个 scaler 来规范化数据。MinMaxScalar将所有数据缩放到 0 和 1 的范围内。您还可以将训练和测试数据整形为形状[data_size, num_features]

根据您之前的观察,即不同时间段的数据具有不同的值范围,您可以通过将整个系列拆分为多个窗口来规范化数据。如果不这样做,早期的数据将接*于 0,不会给学习过程增加太多价值。这里你选择一个大小为 2500 的窗口。

提示:当选择窗口大小时,确保它不要太小,因为当你执行窗口归一化时,它会在每个窗口的最后引入一个断点,因为每个窗口都是独立归一化的。

在本例中,4 个数据点将受此影响。但是假设你有 11,000 个数据点,4 点不会引起任何问题

将数据重塑回[data_size]的形状

现在,您可以使用指数移动*均来*滑数据。这有助于你摆脱股票价格中数据固有的混乱,并产生一个更*滑的曲线。

注意:我们仅使用训练数据训练最小最大缩放器,通过将最小最大缩放器拟合到测试数据来标准化测试数据是错误的

注意你应该只*滑训练数据。

评估结果

我们将使用均方差来计算我们的模型有多好。均方误差(MSE)可以通过计算前一步的真实值和预测值之间的*方误差,并对所有预测进行*均来计算。

*均作为股票价格建模技术

在原始教程中,我谈到了对于这种类型的问题,欺骗和糟糕的*均是如何的。结论是,

*均法可以很好地预测一个时间点(这对于股市预测来说不是很有用),但对于未来却没有多少时间点。更多详情可以在原创教程中找到。

LSTMs 简介:预测遥远未来的股票走势

长短期记忆模型是非常强大的时间序列模型。他们可以预测未来的任意步数。一个 LSTM 模块(或细胞)有 5 个基本组成部分,使其能够模拟长期和短期数据。

  • 细胞状态(c _ t)——这代表细胞的内部记忆,它既存储短期记忆又存储长期记忆
  • 隐藏状态(h_t) —这是根据当前输入、先前隐藏状态和当前单元格输入计算的输出状态信息,您最终使用这些信息来预测未来的股票市场价格。此外,隐藏状态可以决定仅检索存储在单元状态中的短期或长期或两种类型的记忆来进行下一次预测。
  • 输入门(i_t) —决定有多少信息从电流输入流向单元状态
  • 遗忘门(f_t) —决定有多少来自当前输入和前一单元状态的信息流入当前单元状态
  • 输出门(o_t) —决定有多少信息从当前单元状态流入隐藏状态,这样,如果需要,LSTM 只能选择长期记忆或短期记忆和长期记忆

下图是一个单元格。

并且用于计算这些实体中的每一个的等式如下。

  • I_ t =σ(W * x_ t+W * h _ { t-1 }+b _ I)
  • \ tilde { c }_ t =σ(W * x_ t+W * h _ { t-1 }+b _ c)
  • f_ t =σ(W * xt+W * h _ { t-1 }+b _ f)
  • c _ t = f_ t * c+I _ t * \波浪号{c}_t
  • o_ t =σ(W * xt+W * h _ { t-1 }+b _ o)
  • h_t = o_t * tanh(c_t)

为了更好地(更技术性地)理解 LSTMs,你可以参考这篇文章。

数据生成程序

下面,您演示了如何可视化地创建一批数据。基本思想是,我们将数据序列分成 N/b 个段,使每个段的大小为 b,然后我们定义游标,每个段 1 个。然后对单批数据进行采样,我们得到一个输入(当前段游标索引)和一个真预测(在[当前段游标+ 1,当前段游标+ 5]之间随机采样的一个)。请注意,我们并不总是得到输入旁边的值,就像它的预测一样。这是减少过度拟合的一个步骤。在每次采样结束时,我们将光标增加 1。你可以在原教程中找到更多关于数据生成的信息。

定义超参数

在本节中,您将定义几个超参数。D是输入的维数。这很简单,因为你把前一个股票价格作为输入,预测下一个,应该是1

然后你有num_unrollings,表示你为一个优化步骤考虑多少个连续的时间步骤。越大越好。

然后你就有了batch_size。批量大小是指您在一个时间步长中考虑的数据样本数量。越大越好,因为在给定的时间内,数据的可见性更高。

接下来定义num_nodes,它代表每个细胞中隐藏神经元的数量。您可以看到,本例中有三层 LSTMs。

定义输入和输出

接下来,为训练输入和标签定义占位符。这非常简单,因为您有一个输入占位符列表,其中每个占位符包含一批数据。列表中有num_unrollings占位符,将在单个优化步骤中立即使用。

定义 LSTM 和回归图层的参数

你将有一个三层的 LSTMs 和一个线性回归层,用wb表示,它获取最后一个长短期记忆单元的输出,并输出下一个时间步的预测。您可以使用 TensorFlow 中的MultiRNNCell来封装您创建的三个LSTMCell对象。此外,您可以让 dropout 实现 LSTM 单元,因为它们可以提高性能并减少过拟合。

计算 LSTM 输出并将其馈送到回归层以获得最终预测

在本节中,首先创建 TensorFlow 变量(ch),这些变量将保存长短期记忆单元的单元状态和隐藏状态。然后你把train_inputs的列表转换成[num_unrollings, batch_size, D]的形状,这是用tf.nn.dynamic_rnn函数计算输出所需要的。然后用tf.nn.dynamic_rnn函数计算 LSTM 输出,并将输出拆分回一个num_unrolling张量列表。预测和真实股价之间的差距。

损失计算和优化程序

现在,你将计算损失。但是,您应该注意,在计算损失时有一个独特的特征。对于每批预测和真实输出,计算均方误差。你将所有这些均方损失相加(不是*均)。最后,您定义将用于优化神经网络的优化器。在这种情况下,您可以使用 Adam,这是一个非常新的、性能良好的优化器。

在此定义与预测相关的张量流运算。首先,为输入定义一个占位符(sample_inputs),然后类似于训练阶段,为预测定义状态变量(sample_csample_h)。最后用tf.nn.dynamic_rnn函数计算预测,然后通过回归层(wb)发送输出。您还应该定义reset_sample_state操作,它重置单元格状态和隐藏状态。每次进行一系列预测时,都应该在开始时执行这个操作。

运行 LSTM

在这里,您将训练和预测几个时期的股票价格运动,并查看预测随着时间的推移是变好还是变坏。您遵循以下程序。我不分享代码,因为我分享的是完整 Jupyter 笔记本的链接。

*在时间序列上定义一组测试起点( *test_points_seq* ),以评估上的模型

*对于每个时期

** 训练数据全序列长度

** * 展开一套 *num_unrollings* 批次

** * 用展开的批次训练神经网络

** 计算*均培训损失

** 对于测试集中的每个起始点

** * 通过迭代在测试点之前找到的先前 *num_unrollings* 数据点来更新 LSTM 状态

** * 连续对 *n_predict_once* 步骤进行预测,使用之前的预测作为当前输入

** * 计算预测的 *n_predict_once* 点与该时间点的真实股价之间的 MSE 损失

可视化预测

你可以看到 MSE 损失是如何随着训练量的增加而下降的。这是一个好迹象,表明模型正在学习一些有用的东西。为了量化您的发现,您可以将网络的 MSE 损失与进行标准*均(0.004)时获得的 MSE 损失进行比较。你可以看到 LSTM 的表现比标准*均值要好。你知道标准*均法(虽然不完美)合理地跟随真实的股票价格运动。

虽然不完美,LSTMs 似乎能够在大多数时候正确预测股票价格行为。请注意,您做出的预测大致在 0 到 1.0 的范围内(也就是说,不是真实的股票价格)。这没关系,因为你预测的是股票价格的变动,而不是价格本身。

结论

我希望这篇教程对你有用。我应该提到这对我来说是一次有益的经历。在本教程中,我了解到设计一个能够正确预测股价走势的模型有多困难。你从为什么需要对股票价格建模的动机开始。接下来是解释和下载数据的代码。然后你看了两种*均技术,它们可以让你对未来进行预测。接下来你会看到,当你需要预测未来不止一步的时候,这些方法是没有用的。此后,您讨论了如何使用 LSTMs 对未来进行预测。最后,您将结果可视化,并发现您的模型(尽管并不完美)在正确预测股票价格变动方面非常出色。

在这里,我陈述几个本教程的要点。

  1. 股票价格/运动预测是一项极其困难的任务。就我个人而言,我不认为任何股票预测模型是理所当然的,也不应该盲目依赖它们。然而,模型可能在大多数情况下能够正确预测股票价格的变动,但并不总是如此。
  2. 不要被那些显示预测曲线与真实股价完美重叠的文章所迷惑。这可以用一个简单的*均技术来复制,但实际上这是没有用的。更明智的做法是预测股价走势。
  3. 模型的超参数对您获得的结果极其敏感。因此,一个非常好的做法是对超参数运行一些超参数优化技术(例如,网格搜索/随机搜索)。这里我列出了一些最关键的超参数;优化器的学习速率,层数和每层的隐藏单元数,优化器(我发现亚当表现最好),模型的类型(GRU/LSTM/带窥视孔的 LSTM)
  4. 在本教程中,你做了一些错误的事情(由于数据量小)!那就是你利用考试损失来降低学习速度。这间接地将关于测试集的信息泄露到训练过程中。一个更好的处理方法是拥有一个单独的验证集(与测试集分开)和关于验证集性能的衰减学习率。

这里

参考

我参考了这个库来了解如何使用 LSTMs 进行股票预测。但是细节可能与参考资料中的实现有很大不同。

想在深度网络和 TensorFlow 上做得更好?

检查我在这个课题上的工作。

[1] (书)张量流 2 在行动——曼宁

[2] (视频教程)Python 中的机器翻译 — DataCamp

[3] (书)TensorFlow 中的自然语言处理 1 — Packt

利用 LSTMs 预测时间序列

原文:https://towardsdatascience.com/using-lstms-to-forecast-time-series-4ab688386b1f?source=collection_archive---------1-----------------------

Photo by Nick Chong on Unsplash

有几种时间序列预测技术,如自回归(AR)模型、移动*均(MA)模型、霍尔特-温特斯、ARIMA 等。,不一而足。那么,还有什么必要用另一个像 LSTM-RNN 这样的模型来预测时间序列呢?这是一个非常合理的问题,以下是我能想到的理由(如果你知道更多,我很想知道,请在下面回答)—

  • RNN(LSTM)非常擅长在输入特征空间中提取模式,其中输入数据跨越长序列。鉴于 LSTM 的门控结构具有操纵其记忆状态的能力,它们是解决这类问题的理想选择。
  • LSTMs 几乎可以无缝地模拟具有多个输入变量的问题。我们需要的只是一个 3D 输入向量,它需要被输入到 LSTM 的输入形状中。只要我们找到一种方法,将所有的输入变量转换成三维矢量形式,我们就可以很好地使用 LSTM。这在时间序列预测中增加了很大的好处,在这种情况下,经典的线性方法可能很难适应多变量或多输入预测问题(此处对多变量预测的补充说明—请记住,当我们使用多变量数据进行预测时,我们还需要“未来多变量”数据来预测未来的结果!)
  • 总的来说,在使用 LSTM 的方法时,我发现它们在建模问题时提供了很大的灵活性——这意味着我们可以很好地控制时间序列的几个参数。特别是我们可以—
  • 灵活使用 seq2seq LSTM 模型的多种组合来预测时间序列——多对一模型(当我们希望在给定所有先前输入的情况下预测当前时间步长时有用),多对多模型(当我们希望在给定所有先前输入的情况下一次预测多个未来时间步长时有用)以及这些模型的其他几种变体。我们可以定制一些东西,例如,在当前步骤进行预测的回顾窗口的大小,我们希望预测未来的时间步骤的数量,将当前预测反馈到窗口中以在下一个时间步骤进行预测(这种技术也称为向前移动窗口)等等。

另一方面,在使用 LSTM(或任何 DNN 架构)时,有一些常见的缺点需要小心——需要大量数据,需要调整多个超参数等。,我也看到一些文章提到 LSTM 并不擅长自回归类型的序列。所以不要全信这个。

使用一个简单的正弦波作为模型数据集来模拟时间序列预测。你可以在我的 github 简介中找到我自己对这个例子的实现。这个例子的核心思想和数据取自的博客,但为了便于理解,我做了自己的修改。

那么我们给定的数据是什么样的呢?下面是整个正弦波数据集的曲线图。

fig 1: Plot of entire sine wave data

在我们深入研究细节之前,先简要介绍一下整体方法—

  1. 使用大小为 50 的向前移动窗口,这意味着我们将使用前 50 个数据点作为输出输入 X 来预测 y1-第 51 个数据点。接下来,我们将使用 1 到 51 个数据点之间的窗口作为输入 X 来预测 y2,即第 52 个数据点,依此类推…这是前 50 个数据点的图—

2.使用两层 LSTM 架构和密集输出层进行预测。

3.我们将查看预测输出的几种方法,a .)逐步预测测试数据集, b.) 通过向前移动一步,将先前的预测反馈到输入窗口,然后在当前时间步进行预测。

现在让我们深入细节—

数据准备—

  1. 使用 minmax scaler 标准化数据(参见下面的代码片段)

2.将移动窗口大小固定为 50。为此,我们使用 pandas shift 函数,按照我们指定的数字移动整个列。在下面的代码片段中,我们将列 向上 移动了 1(因此使用了-1。如果我们想将 向下 移动 1,我们必须使用+1),然后将其连接到原始数据。

我试图在下面的一个玩具数据集上说明这一点,上面的循环 的 是如何为 3 的窗口大小工作的。**

注意——在上面的代码片段中,我们删除了所有包含 Nan 值的行。

如果仔细观察玩具数据集,您会发现它以我们希望输入到 LSTM 中的方式模拟了输入数据。上表中的最后一列成为目标 y ,前三列成为我们的输入 x1、x2x3 特征。如果你熟悉在自然语言处理中使用 LSTM,那么你可以把它看作是一个长度为 3 的句子的固定序列,每个序列包含 3 个单词,我们的任务是预测第 4 个单词。

3.为 LSTM 准备 3D 输入矢量。记住,LSTM 的输入向量是 3D 数组:(样本数,时间步数,特征数)。在这种情况下,我们有时间步数= 50* 和数量 _ 特征= 1 (扩展我们在上一点中看到的相同类比,我发现这在理解为什么输入形状必须是这样非常有用——比方说,我们在一个句子中有 50 个单词,每个单词由一个单词向量表示。因此,我们需要 50 个时间步长来遍历句子中的每个单词向量,作为每个时间步长的 LSTM 的输入。每个观察有一个句子,因此 num_features = 1 。像这样,我们需要迭代训练数据中的所有句子,以提取所有句子中单词之间的模式。这也正是我们在时间序列预测中想要的—我们想要识别窗口中每个先前值之间存在的所有模式,以预测当前时间步长!)*

模型架构—

下面是所使用的模型架构,这一点不言而喻—(它是一个双层堆叠的 LSTM 层,第一个 LSTM 在每个时间步的输出被馈送到第二个 LSTM)

Model architecture

做预测—

  1. 逐步预测测试数据(参考下面的代码片段)。这很简单。给定从训练数据中学习到的所有参数,我们使用它们来一次一个地预测所有的测试序列。

**预测值与实际值的曲线几乎相互重叠,以至于我们无法区分下图中的蓝色曲线和红色曲线。

然而,以上通常不是进行预测的现实方式,因为我们不会有所有可用的未来窗口序列。

2.因此,如果我们想要预测未来的多个时间步长,那么更现实的方法是一次预测未来的一个时间步长,并将该预测反馈到后面的输入窗口,同时在窗口开始时弹出第一个观察值(以便窗口大小保持不变)。参考下面做这部分的代码片段—(如果你浏览我上面提到的 github 链接中的代码,代码中的注释是不言自明的)—

使用这个预测模型,结果绘制如下—

可以看出,可以理解的是,我们试图预测的时间越远,在每个时间步上建立在先前预测误差上的误差就越大。然而,该函数的行为仍然像一个阻尼正弦波!正如我前面说过的,这是任何时间序列问题的更现实的模型,因为我们没有所有的未来序列。

这个代码可以很好地扩展到预测任何时间序列。请注意,您可能需要注意数据准备的其他方面,如在将数据提供给 LSTM 进行预测之前,对序列进行去趋势化、差分以使数据稳定等。

就是这样!希望这篇文章对使用 LSTM 预测时间序列有一个很好的理解。如果这篇文章中有一些摘录,请鼓掌表示感谢:)

使用机器学习模型推荐航空公司——第一部分

原文:https://towardsdatascience.com/using-machine-learning-models-to-recommend-airline-carriers-part-i-ed02fcb729a0?source=collection_archive---------10-----------------------

Photo by Gary Lopater on Unsplash

机器学习是任何数据科学家都必须拥有的一项技能,但这并不是一项容易获得的技能。我是一名训练有素的物理学家,在欧洲核子研究中心和 T2 BNL 等实验室做过物理研究,数据分析对我来说很自然。但是,我不得不承认,当我想为机器学习解渴的时候,我纠结了!在这篇博客中,我的目的是通过一个真实的例子来展示机器学习的力量,从而帮助任何数据科学爱好者。

问题形式化

目标是根据数据集中提供的信息预测航班是否会被取消。该机构只能出售三家航空公司(AA、UA 和 DL)的机票,并且希望能够告知其客户哪家航空公司的取消最少。

当你在旅行中寻找一个可以休息的地方时,酒店评论在预订住宿时相当重要。为什么,因为你至少会在一个特定的地方住一晚,舒适和预算是非常重要的。然而,在预订航空公司时,人们的观点大相径庭。我个人想预订最便宜的航班,而不去关注评论。原因很简单,如果我在国内旅行,我只会花几个小时。这在假期会变得特别棘手,因为大多数人都会去见家人。至少在美国,当你带着孩子旅行并且你的航班延误时,感恩节和圣诞节会是一个非常紧张的时刻。机器学习算法如何在这样的场景中派上用场?我的目的是证明这一点。

我学了很多课程来学习机器学习。我将在这里总结一些最有用的材料。吴恩达在 coursera 上的机器学习;在 udemy 上进行深度学习的 tensorflow;和这本书是我学习这套技能的旅程中最有用的垫脚石。

我在这个博客中的大部分工作都是受威尔·科尔森的 GitHub 资源库的启发。请参考我的 GitHub 资源库,完整了解这篇博客中定义的问题,以及这里使用的数据集。

关于数据集的信息

Figure I: Data set information

首要任务是确定我们正在处理什么类型的问题?基于上面的问题定义和数据集信息,这可以被归类为监督分类类型的问题。

这是一个监督问题,因为数据集包含预期结果的例子,也称为标签,这是一个分类类型问题,因为结果是二元的。代理商希望根据对未来取消率的预测来推荐某家航空公司。

好了,现在我们已经定义了我们正在处理的问题的类型,在我们深入数据分析部分之前,让我们首先建立一个机器学习清单。清单帮助我对手头的问题有更全面的了解,并保持专注。

机器学习项目清单

  1. 定义问题,看大局。
  2. 执行探索性数据分析(EDA)以获得洞察力。
  3. 清理和准备数据,以更好地揭示其中的潜在模式。
  4. 探索许多不同的机器学习模型,并选择最佳模型。
  5. 执行模型交叉验证,以确保分析是稳健的。

既然我们已经定义了更大的图片,让我们从将数据加载到 pandas 数据框中开始,并查看前五条记录。

Using pandas library for data manipulation

数据类型和缺失值

dataframe.info()方法是一种快速评估数据的方法,它显示每一列的数据类型和非缺失值的数量。查看下面的输出,这是一个相对容易分析的数据集,因为这里没有重大的数据质量问题。在给定的数据集中有 6000 个实例,只有四列缺少一些数据值。在这种情况下,我们将直接进入数据的探索性分析。

探索性数据分析

EDA 是一种数据分析的图形化方法,允许我们最大限度地洞察我们的数据集;发现潜在模式;启用特征提取;发现异常值和异常情况;并测试潜在的假设。

单变量分析

让我们首先分析“距离”变量,以获得关于我们拥有什么类型的航空公司数据的信息,国内的还是国际的。

Python method for plotting a variable using matplotlib library.

Figure 2: Distribution of distance as observed in the data set.

上面的图 2 显示了一个偏离正态分布的分布。它是一种概率分布,描述了变量的值是如何填充的。这种分布是对称的,其中大部分观察值聚集在中心峰值周围,并且距离*均值较远的值的概率在两个方向上逐渐变小。大自然的大部分现象都倾向于遵循正态分布。例如,身高、血压测量误差、智商得分等..

距离不遵循正态分布是不足为奇的,然而,图 2 显示了大于大约 3000 英里的距离的非常稀疏的值。还建议将对数标度图可视化,以便能够评估距离中的异常值。假设这些数据仅对应于美国境内的国内航班,那么谨慎地移除可能导致对航班取消的有偏见和/或不正确预测的数据点是很重要的。很难解释飞行距离约为 10000 英里的国内航班。上面的“距离”图显示了一个带有长尾的朗道(向右倾斜的分布)型分布。同样,假设这些航班仅是国内航班,下一步是想出一个策略来删除这些数据点。我再怎么强调也不为过,仅仅因为数据点看起来可疑,就在删除任何数据点时保持谨慎是极其重要的。它们可能是需要进一步调查的实际现象的结果。

移除异常值

对于这个项目,我使用了一种标准的物理方法来消除异常值,在这种情况下,这是*均值周围的三个标准偏差。

Figure 4: Distribution of flight distance after dropping values greater than three standard deviations.

查看数据点是否确实被删除。

当去除大于三个标准偏差的距离观察值时,大约 1%的数据点被丢弃。

由于有限的统计数据导致的偏差

我想提醒我的读者,我们正在处理的数据集只有非常有限的统计数据,只有 6000 个实例。请记住,从下面的分析中推断出的结论可能会有偏差。由偏差引起的误差被定义为我们的模型的预期预测和我们试图预测的正确值之间的差异。最小化这种偏差的最好方法是多次重复整个模型建立过程;在每次迭代中,您运行新的分析,在新收集的数据集上创建新的模型。由于基础数据集中的随机性,生成的模型将具有一系列预测。偏差衡量的是这些模型的预测与正确值的差距。

最常用的航空公司

Figure 5: Most used airline carrier.

上面的图显示,在给定的数据集中,美国航空公司是使用最多的航空公司,但它是最可靠的航空公司吗?

最可靠的航空公司

现在,我们已经很好地理解了手头的数据集,让我们进行分析,以确定最可靠的航空公司。

Figure 6: Flight cancellation rate for individual carriers.

下面我简单地绘制了图 6 中获得的取消率,显示在图 7 中。

Figure 7: Usage and reliability for each airline carrier.

  1. 根据数据集,上述数字不足为奇,AA 航空公司是使用率最高的航空公司,使用率为 41%,相比之下,UA 为 30%,DL 为 28%。
  2. AA 航空公司未被取消的可靠度为 80%,而 UA 的可靠度为 81 %, DL 航空公司的可靠度约为 90%。

所以达美航空是这个数据集中最靠谱的航空公司。借助 EDA,我们能够证明达美航空是最可靠的航空公司。我们现在可以使用机器学习模型来预测这家航空公司未来的取消率。

双变量分析

图 8(下图)显示了该数据集中不同变量之间的相关矩阵。也称为热图,是一个强大的工具,可以直观地显示我们目标标签背后引人注目的特征。

Figure 8: Correlation matrix between different variables present in this data set.

图 8 中的外卖信息:

  1. 目标标签“已取消”与“月”、“SchedElapsedTime”、“ArrDelay”、“DepDelay”和“距离”呈负相关。
  2. 取消列不依赖于“出发时间”。
  3. 到达延误(ArrDelay)发生在有出发延误(DepDelay)的时候。这两个变量是高度相关的,这是理所应当的!
  4. 鉴于给定数据集中的信息,航班取消可能会因技术故障而发生,但我们没有可用的信息。所以我们将使用“月”列。

下图 9 展示了每个航空公司每月的使用情况。除了 12 月份,美国航空公司仍然是最常用的承运人。

Figure 9: Month-wise usage for each airline carrier.

类似地,可以绘制每个航空公司每月的取消百分比。重要的是要看相对百分比值,而不是看绝对数字。有趣的是,我们发现 AA 在四月份的使用率最高。也许他们在那个月提供最便宜的票价?从 1 月到 4 月,AA 的取消趋势上升,而其他两家航空公司的趋势相反。尽管如此,除了 6 月、7 月、9 月和 11 月,达美航班取消的可能性最低。

Figure 10: month-wise cancellation percentage for each airline carrier.

有了上述所有准备,我们现在将更深入地模拟未来航班取消的预测。请参考我博客的第二部分。

使用机器学习模型推荐航空公司——第二部分

原文:https://towardsdatascience.com/using-machine-learning-models-to-recommend-airline-carriers-part-ii-f87ea6d74728?source=collection_archive---------16-----------------------

Photo by Andrew Palmer on Unsplash

在使用机器学习模型解决问题时,没有什么灵丹妙药。我还没有见过一种模式适合所有人。因此,强烈建议对您可能正在处理的任何问题使用多个模型,并评估为什么一个特定的模型比其他模型更好。请参考我博客的第一部分,了解所用数据集的详细信息。

在这篇博文中,我的目的是展示如何使用几个机器学习模型找到一个解决方案,为最可靠的航空公司推荐未来的取消率,并讨论每个模型的利弊。

创建训练和测试数据集

Figure 1: Creating test, train data sets using train_test_split method in sci-kit learn.

对于手头的分类问题,我将使用以下模型:

  1. 逻辑回归
  2. 支持向量机
  3. 决策图表
  4. 随机森林

L 逻辑回归:与其名称相反,逻辑回归用于因变量为二分变量(二元/分类)的分类类型问题。计算感兴趣特征出现的概率。

logit(p) = ln(特性存在的概率/特性不存在的概率)

逻辑回归中的估计不是选择最小化线性回归中误差*方和的参数,而是选择最大化观察样本值可能性的参数。

Figure 2: Logistic regression. Source

Figure 3: Logistic regression. Source

图 4 展示了如何实例化逻辑回归类,以及如何在自变量(X_train)和因变量(y_train)上使用“fit”方法。我们得到了大约 83%的准确率。这是一个相当低的准确度分数,让我们试着理解为什么这个模型的性能如此之差。

Figure 4: Using logistic regression model training data set.

Figure 5: Applying logistic regression model on test data set.

在上面的图 5 中,我们在测试数据集上获得了大约 84%的准确率。下面的相关矩阵图(图 6)显示,逻辑回归模型在预测取消时没有考虑“月”列。这也许解释了为什么这个模型的性能如此之差。

Figure 6: Driving factor behind poor performance of logistic regression model.

利弊:

  1. 逻辑回归是一个广义的线性模型,所以我们不能用这个模型解决非线性问题——不管是赞成还是反对,这取决于你试图解决的问题的类型。
  2. 由于参数和输入向量的线性组合,计算非常简单。
  3. 输出可以解释为概率;所以你可以用它来排名而不是分类。
  4. 树木通常很难计算出精确的概率。
  5. 遭受多重共线性。

支持向量机:SVM 是一个非常强大和通用的最大似然模型,能够解决线性以及非线性分类,回归甚至异常检测类型的问题。是 ML 中最受欢迎的型号之一。缺点是 SVM 只适用于中小型数据集。

Figure 7: Support vector machines aka large margin classification.

SVM 分类器试图在不同类别之间拟合最宽的可能街道(由图 7 中的蓝色矩形表示)。这就是所谓的大幅度分类。图 7 左侧的黑线很好地将两个类别分开,但是没有最大的余量(也称为街道/超*面),如在右手侧。请注意,在“街道之外”添加更多实例根本不会影响决策边界。决策边界完全由街道边缘的实例决定。这些实例被称为支持向量,因此命名为支持向量机。

Figure 8: Instantiating the SVC class.

由于我们使用的是一个相当小的数据集(只有 6000 个实例),计算相对来说并不费力。SVM 模型的精确度约为 99.9%。

与逻辑回归不同,SVM 分类器不会输出每个类别的概率。

缺点:

  1. 训练这种模型可能会非常低效。不建议用于大型数据集。
  2. 支持向量机对特征缩放很敏感,与数据集中的其余特征相比,具有小得多的缩放比例的特征将在大幅度确定中被忽略。

D 决策树:与 SVM 相似,决策树是非常通用的 ML 算法,可以执行分类和回归任务。这是一个流程图类型的算法,其中每个决策节点后面都有一个结果。

Figure 9: Using decision tree model.

Figure 10: Simple decision tree.

利弊:

  1. 决策树的众多特性之一是它们需要很少的数据准备。它们根本不需要特征缩放或居中。
  2. 该模型易于解读、解释、易于使用、功能多样且功能强大。
  3. 决策树还可以估计某个实例属于某个特定类 k 的概率:首先,它遍历树来查找该实例的叶节点,然后返回该节点中类 k 的训练实例的比率。
  4. 决策树最大的缺点是它们对训练数据的微小变化非常敏感。他们倾向于过度拟合数据。

我有一种不可思议的感觉,100%准确的决策树过度拟合了这里的数据。

andom Forest:是一种集成学习算法。一组预测器称为集合;这项技术被称为集成学习。这里训练一组决策树分类器,每个分类器基于训练集的不同随机子集。为了进行预测,我们可以获得所有单个树的预测,然后预测获得最多投票的类。这样的决策树集合被称为随机森林。

随机森林模型的成功可以用大数定律来解释。最简单的解释是:拿一个装有 100 枚金币的盒子。在任何给定的时间点,期望值大约是 50 头和 50 尾。但是,我摇一次箱子,可能得不到预期的值。但是诀窍是通过摇动盒子来进行合理的大量观察,使得头和尾的数量的*均值接*期望值。

随机森林不需要纯粹基于决策树作为唯一的预测器。可以有一组不同的分类器,并预测得到最多投票的类别,如下图 11 所示。

Figure 11: Diverse set of classifiers. Source.

图 12 显示了随机森林分类器是如何实例化的。

Figure 12: Random forest classifier.

利弊:

  1. 与决策树相比,随机森林不是一个容易直观解释的模型。
  2. 易于在可能具有相关特征的数据集上使用。

摘要

在这篇博文中,我展示了各种 ML 模型的使用,以及它们的优缺点。大家 ML 快乐!

使用机器学习为 Google Home 构建对话式放射学助手

原文:https://towardsdatascience.com/using-machine-learning-to-build-a-conversational-radiology-assistant-for-google-home-28ef210cb6fb?source=collection_archive---------4-----------------------

介绍

一段时间以来,我一直对对话代理感到兴奋,之前我构建了一个 iOS 聊天机器人,模拟由沃森驱动的人类放射科医生。

作为一个令人愉快的周末项目,我和我的光荣的柯基犬坐下来,喝了很多咖啡,为谷歌主页制作了一个放射学助手。它旨在以快速、对话、免提的方式帮助医疗保健提供者满足其放射学需求。一些视频演示:

智能扬声器是一项革命性的技术,像 Google Home 和 Amazon Echo 这样的工具有潜力为医疗保健提供巨大的价值。这项技术强大而有趣,原因如下:

  1. 方便查看和联系我们的患者。患者讨厌医生持续盯着电脑或*板电脑,这种行为有损医患关系。智能扬声器有助于绘制数据和获取信息,同时继续与患者进行眼神交流。
  2. 无菌的需要。在无菌手术室中访问信息很麻烦,外科医生基本上无法使用标准的桌面/智能手机技术。智能音箱很好地解决了这个问题。
  3. 独有的低摩擦信息检索。医疗保健提供商面临着不堪重负的工作负载,无缝访问即时信息非常重要。当然,我可以花 3 分钟查找 Fleischner 标准,但是如果我可以简单地“询问房间”并在 5 秒钟内得到答案,那就好得多了。此外,新的 Google Home 应用程序可以立即使用,不需要单独下载和管理 100 个分散的应用程序。
  4. 交谈的力量。我们天生就被编程为通过对话与世界互动,精心制作的对话软件非常直观且易于使用。这对于不喜欢传统图形用户界面的老年患者/医生尤其有用。

您现在已经理解了为什么这个*台很酷,但是我们的放射科助理到底能做什么呢?当前功能的示例包括:

  1. 偶发病变随访建议(例如肺结节 Fleischner 标准
  2. 对比过敏预处理方案
  3. 大小阈值信息(例如肥厚性幽门狭窄的阈值)
  4. 临床评分计算器(例如 MELD 评分)

在本文中,我将向您详细描述这个 Google Home 工具是如何构建的。

构建对话式放射学助理

步骤 1:使用 DialogFlow 理解语言

首先,我向您提交一个令人难以置信的图表,它提供了应用程序中信息流的概述:

When a user queries the Google Home device, natural language processing is performed by DialogFlow to understand the user input and parse it into useful variables of interest. These variables are passed to a webhook for further processing. Following webhook processing, information is returned to DialogFlow and used to create the Google Home output message.

要构建这种工具,首先需要强大的自然语言处理来理解用户输入,并将其分解成有意义的块。这可以通过使用 Google 提供的服务 DialogFlow 来实现(通过收购流行的 API)。AI)。

在 DialogFlow 中,功能模块被称为意图。还记得应用程序如何为肺结节提供 Fleischner 随访建议吗?这就是肺结节的意图。同样,也有计算 MELD 评分、对比过敏预处理和幽门正常尺寸的意图。看看所有这些美妙的意图:

Intents!

但是程序如何获取给定的用户输入并将其与适当的意图配对呢?它能做到这一点,是因为训练数据让它变得聪明。也就是说,我们提供一堆用户可能会说的事情的例子来触发特定的意图——我们提供的越多,人工智能就越聪明——程序“学习”正确识别感兴趣的意图。下面是一个用于训练“MELD 分数”意图的数据类型的示例,这只是用户可能询问 MELD 分数的一系列方式:

所以,我们现在明白了程序是如何确定用户到底在问什么。DialogFlow 执行的下一个重要的 NLP 任务是将用户输入解析成可以理解和处理的有意义的块。

以肺结节评估为例。为了提供 Fleischner 建议,我们需要关于结节的四位信息:(1)结节特征(实性、部分实性、毛玻璃),(2)结节大小,(3)患者风险水*(低或高),以及(4)结节数量(单个或多个)。在 DialogFlow 中,像这样的数据位称为实体,我们为这四个变量中的每一个变量创建一个单独的实体(从技术上讲,我们使用通用的“单位长度”实体来表示结节大小,但在本讨论中可以忽略)。它最终看起来有点像这样:

DialogFlow 很酷的一点是,它提供了智能的自然语言处理,可以在给定适当的训练数据的情况下,自动从任意句子中提取感兴趣的实体。这意味着,当用户说“我在一个高风险患者中有一个 6 毫米的固体肺结节”时,DialogFlow 会自然地解析数据,并将结节大小(6 毫米)、结节特征(固体)和患者风险(高)存储为可用变量。在这种情况下,它认识到它仍然需要知道“结节数”,因此将使用上面列出的“提示”询问该变量。如果用户查询包含所有 4 个必要的信息,它会立即继续并给出推荐。相反,如果用户简单地说“肺结节”,它会询问所有四个参数。

DialogFlow 是如何聪明到可以知道句子的哪些部分代表哪个实体的?当然是训练数据!你只需将句子的相关部分标记为特定实体,它就会学习在新句子中识别这些实体。看起来是这样的:

Yellow label = nodule number; orange label = nodule size; pink label = nodule character; purple label = risk level. Note that you can specify that “smoker” is equivalent to saying “high risk.” Pretty cool!

步骤 2:使用 webhook 处理理解的语言

到目前为止,我们已经使用了奇特的自然语言处理来获取用户输入,理解用户想要什么(意图),并将其分解为感兴趣的有意义的参数(实体)。

现在我们有了这些参数,我们使用一个“webhook”来处理它们,并向用户提供他们想要的信息(MELD 评分、Fleischner 推荐等。).出于我们的目的,您可以将 webhook 想象成一段代码,它接受来自 DialogFlow 的数据,对其进行处理,并返回感兴趣的最终值。

在肺结节的情况下,webhook 采用上述四个结节特征,并执行一系列简单的逻辑语句来识别和返回相关的 Fleischner 建议。也就是说,它采用了这里描述的基本逻辑:

变成了这样:

在这个 webhook 处理之后,一个适当的答案被返回给 DialogFlow,它将这个答案输入到 Google Home,然后,,你就有了一个智能放射学助理。

结论

希望你觉得这个教程有用!此外,我希望你花些时间思考这个迷人的新*台如何为医生和他们的病人提供价值。如果你有任何问题,请告诉我,如果你想聊天,请随时联系 twitter 或 LinkedIn 。感谢阅读!

使用机器学习来模拟世界杯比赛

原文:https://towardsdatascience.com/using-machine-learning-to-simulate-world-cup-matches-959e24d0731?source=collection_archive---------2-----------------------

世界杯正在进入一个新的阶段,很少有人能够预测小组赛的结果。现在是时候进入一个更加激动人心的阶段了,世界上最伟大的人将会面对面。本文的目标是,通过 Python 使用数据科学的力量,尝试揭示这些游戏将呈现的一些统计数据。

在本帖中,我们将:

  • 创建一个爬虫,从网上获取团队统计数据
  • 预处理、探索和可视化数据
  • 下载具有匹配结果的另一种数据
  • 组合这两个数据集并构建一个模型来预测匹配结果
  • 创建一个简单的蒙特卡洛模拟,并获得 2018 年世界杯淘汰赛阶段的赢家赔率

我们将要使用的一些库:

  • 熊猫
  • Numpy
  • Sklearn
  • Plotly

这里的想法是制作一个机器学习算法来预测单场比赛的获胜者,并从那里建立一个蒙特卡洛模拟,可以推断出每个淘汰赛获胜者的概率,以及随后世界冠军的概率。

这篇文章将提供一些图表和代码,但是如果你愿意的话,可以随意跳过它,我会尽量让它更直观。

我们的策略

大多数游戏模拟器倾向于使用一个代表团队表现的总数。在这里,我们正在尝试一种不同的方法,以一种更复杂的方式,不仅与整体,而且与其他三个价值观(进攻、防守、中路)一起工作,以避免简单地将所有特征集中到一个决定球队实力的单一因素上。

该模型将建立在 Sklearn 库的基础上,使用 Pandas dataframes 来操作表中的数据,并 Plotly 来可视化一些有趣的功能。

获取数据

因此,获取数据的第一步是制作一个小爬虫,从国际足联索引中获取信息,这是从 2004 年开始收集国际队数据的一个很好的来源。以下是表格在网站上的排列方式:

用这种方式显示表格,很容易就能得到这样一个网站。为此,我使用了漂亮的 Soup 库来访问 HTML 代码,并使用 Pandas read_html 函数将其转换成可读的数据帧。

我必须承认这个爬虫有点懒惰,它可能会在我们的数据集上复制一些东西。不过,不用担心,因为我们可以稍后删除那些关于熊猫的重复数据(在本文中,我还将提供一些原始数据集的链接)。

我不会进入这个 scrapper 是如何建立的细节,但代码将留在下面,如果你想检查一下。如果你有其他兴趣,请随时联系我。

web_address = '[https://www.fifaindex.com/teams/fifa'](https://www.fifaindex.com/teams/fifa%27)df = pd.DataFrame()for day in range(1,260,1):
     for pag in range(1,30):

         source_address = web_address + '05_' + str(day) + '/' + str(pag) + '/' + '?type=1'
         print('Day:', str(day))
         print(pag)try:
             soup = get_soup(source_address)
             result_list =  soup.find('div', {'id': 'no-more-tables'})
         except:
             print('Page not found.')
             breakdate = str(soup.find('ol', {'class': 'breadcrumb'}))if df.empty:
             df = pd.read_html(str(result_list))[0]
             df['date'] = date
         else:
             temp_df = pd.read_html(str(result_list))[0]
             temp_df['date'] = date
             df = df.append(temp_df)

弄乱原始数据集后,我保存了一个更干净的版本(使用 Pickle ),我们将使用这个数据集作为起点。

df = read_pickle('team_stats.pickle')
df.head()

探索和可视化

该表包含了 2004 年至 2018 年国际足联对多支国际球队的评分。原始数据也包括月和日,但是为了简单起见,我将每个团队的表现按年进行了*均,因此我们需要处理的数据点很少。让我们使用 Plotly 在散点图中查看各队每年的总得分:

Plotly 拥有令人惊叹的交互式图表,当你悬停在它上面时,它实际上可以显示信息。不过,这份报告信息量不大。让我们试着在条形图中检查每个日期表现最好的团队,看看它们在这些年中是如何变化的。下图显示了按年度排名的最佳团队以及所有团队的*均表现(如白线所示)。

这是一个很好的图表!西班牙长期以来一直处于领先地位。现在让我们打开包含国际队比赛结果信息的 CSV 文件:

results = pd.read_csv('match_results.csv')
results.head()

结果数据集来自 github ,由 1872 年的足球比赛结果组成,包括球队、比分和其他一些信息。让我们清理一下,只保留对我们有用的特性。

results = results.drop(['city', 'tournament', 'country'], axis=1)
results.home_team = results.home_team.apply(text_norm) #lower_case
results.away_team = results.away_team.apply(text_norm) #lower_case
results.index = pd.DatetimeIndex(results.date).year
results = results.drop('date', 1)
results.head()

三个步骤对我们利用这些数据非常重要:

  • 首先,由于我们只有 2004 年的统计数据,我们应该去掉其他年份的数据(不幸的是)。
  • 其次,我们不应该与不在我们主要数据框架内的团队合作,因为我们没有他们的评分。
  • 最后,我们必须解决这种主客场球队的情况,因为对于世界杯的预测,我们将考虑所有体育场是中立的。
results = results.loc[2004:2017]df_teams = list(df.name.unique())
results = results.reset_index()for index, row in results.iterrows():
    if row.home_team not in df_teams:
        results.loc[index, 'home_team'] = None
    if row.away_team not in df_teams:
        results.loc[index, 'away_team'] = None

results = results.dropna()

现在让我们将团队的统计数据输入到结果数据框中。为此,我们将创建 8 个新列,代表每个团队的 4 项技能(赢家和输家)。这是我们现在得出的结论:

现在我们需要从 away_score 中减去 home_score ,这样我们就只有一个因素代表哪支球队赢了(负的或正的进球数)。请注意,我使用术语“主场”和“客场”只是因为这是原始数据集的来源,但这不会对我们的分析产生任何影响,因为我们将只研究世界杯比赛中的中立比赛。从现在开始,我将只称他们为团队 1团队 2 (从左到右,团队 1 总是第一个出现在我们的数据集中)。

因此,让我们将每个团队的目标数量压缩到一个单独的特性中,并创建一个 winner 列,这将是要预测的目标。如果 winner > 0,表示队 1 胜,< 0 表示队 2 胜。我们也将丢弃有*局的数据点,因为淘汰赛总是有赢家。

results['score'] = results.home_score - results.away_score
results = results.drop(['home_score', 'away_score', 'home_team', 'away_team'], 1)results['winner'] = None
results['winner'][results.score > 0] = 1
results['winner'][results.score < 0] = -1
results['winner'][results.score == 0] = 0results = results[results.winner != 0]

为了进一步简化问题,我将“帮助”模型从数据中提取信息,提供技能之间的差异,而不是处理性能本身。例如,的攻击 (att) 将会是队的 1 次攻击减去队的 2 次攻击

results['att'] = results['att1'] - results['att2']
results['def'] = results['def1'] - results['def2']
results['mid'] = results['mid1'] - results['mid2']
results['ovr'] = results['ovr1'] - results['ovr2']to_drop = results[results.winner == 1].sample(247)
results = results.drop(labels=to_drop.index, axis=0)

这就是我们目前的数据:

让我们检查一下团队 1 的总体得分之间的相关性:

这对我们有好处。您可以看到这些特征之间的正相关,这表明我们的数据似乎是有意义的(团队的整体得分越高,我们应该期望的目标数量就越多)。

创建模型

为了应用机器学习,我构建了一个小函数来准备数据,删除不必要的属性,使用 Numpy 将其转换为数组格式,并将其分成训练测试集,以便我们可以评估我们模型的精度。

在这个例子中,我将上下文视为一个分类问题,我们的目标是:

  • 1: 第一队获胜
  • -1: 第二队获胜

使用的分类器算法是逻辑回归、随机森林分类器和线性支持向量分类器:

lr = LogisticRegression()
lr.fit(x_train, y_train)rf = RandomForestClassifier()
rf.fit(x_train, y_train)svc = SVC(kernel='linear')
svc.fit(x_train, y_train)

以下是这些模型的准确度得分:

LR → 68.4%

射频→ 67.9%

SVC → 70.1%

在这里,SVC 似乎比其他产品的性能更好,让我们分别检查一下每个类的性能:

我们可以在 Team 1 上观察到多一点的准确性。这可能与这样一个事实有关,即在原始数据集中,这支球队是主队,也许它有更多的胜利,这可能以某种方式影响了模型的行为。但除此之外,这也可能是随机的,所以我继续。

好的。我们有一个预测器,可以以 70%的准确率猜测哪个队会赢。足够建立一个模拟。我们走吧。

模拟比赛

我们首先需要的是通过小组赛的世界杯球队的表现数据。我们将建立一个类似于我们前些年建立的刮刀,但现在使用的是国际足联指数中的 2018 年世界杯数据。

不幸的是,这一数据似乎与 2018 年(非世界杯)的数据没有太大差异,因为德国仍然占据排名第二的位置,而实际上它已经出局了。无论如何,我们将坚持这个来源来收集我们的数据。

wc = read_pickle('world_cup_teams.pickle')
wc.head()

太好了。我们现在离拥有模拟器只有几步之遥。我们将使用我们的机器学习模型作为蒙特卡洛模拟的规则。如果你很少或没有接触过蒙特卡洛,我推荐你从麻省理工学院开放课程软件的这个课程开始。

让我们构建一个比较团队能力的函数,用我们的 SVC 模型评估获胜者(分别为团队 1团队 2、的 1 或-1),并返回获胜者姓名。

def match(wc, team1, team2, model):

    match = pd.DataFrame(columns=['att1','def1','mid1','ovr1','att2','def2','mid2','ovr2'], index=[0])

    match['att1'] = wc[wc.name == team1]['att'].iloc[0]
    match['def1'] = wc[wc.name == team1]['def'].iloc[0]
    match['mid1'] = wc[wc.name == team1]['mid'].iloc[0]
    match['ovr1'] = wc[wc.name == team1]['ovr'].iloc[0]match['att2'] = wc[wc.name == team2]['att'].iloc[0]
    match['def2'] = wc[wc.name == team2]['def'].iloc[0]
    match['mid2'] = wc[wc.name == team2]['mid'].iloc[0]
    match['ovr2'] = wc[wc.name == team2]['ovr'].iloc[0]

    match['att'] = match['att1'] - match['att2']
    match['def'] = match['def1'] - match['def2']
    match['mid'] = match['mid1'] - match['mid2']
    match['ovr'] = match['ovr1'] - match['ovr2']

    match = match[['att', 'def', 'mid', 'ovr']]

    match_array = match.values

    prediction = model.predict(match_array)

    winner = None

    if prediction == 1:
        winner = team1
    elif prediction == -1:
        winner = team2

    return winner

嗯……巴西对西班牙会有什么表现?

match(wc, 'brazil', 'spain', svc)>>> 'spain'

哦不。没想到我们会有如此悲惨的结局!但是这里有一个主要的问题,球队的表现有很大的不同,本届世界杯的第一阶段就证明了这一点。因此,让我们添加一些随机性,以避免每次运行模拟时结果都相同。

def match(wc, team1, team2, model, random_scale=5):

    match = pd.DataFrame(columns=['att1','def1','mid1','ovr1','att2','def2','mid2','ovr2'], index=[0])

    att1 = wc[wc.name == team1]['att'].iloc[0]
    def1 = wc[wc.name == team1]['def'].iloc[0]
    mid1 = wc[wc.name == team1]['mid'].iloc[0]
    ovr1 = wc[wc.name == team1]['ovr'].iloc[0]att2 = wc[wc.name == team2]['att'].iloc[0]
    def2 = wc[wc.name == team2]['def'].iloc[0]
    mid2 = wc[wc.name == team2]['mid'].iloc[0]
    ovr2 = wc[wc.name == team2]['ovr'].iloc[0]

    match['att1'] = np.random.normal(att1, scale=random_scale)
    match['def1'] = np.random.normal(def1, scale=random_scale)
    match['mid1'] = np.random.normal(mid1, scale=random_scale)
    match['ovr1'] = np.random.normal(ovr1, scale=random_scale)match['att2'] = np.random.normal(att2, scale=random_scale)
    match['def2'] = np.random.normal(def2, scale=random_scale)
    match['mid2'] = np.random.normal(mid2, scale=random_scale)
    match['ovr2'] = np.random.normal(ovr2, scale=random_scale)

    match['att'] = match['att1'] - match['att2']
    match['def'] = match['def1'] - match['def2']
    match['mid'] = match['mid1'] - match['mid2']
    match['ovr'] = match['ovr1'] - match['ovr2']

    match = match[['att', 'def', 'mid', 'ovr']]

    match_array = match.values

    prediction = model.predict(match_array)

    winner = None

    if prediction == 1:
        winner = team1
    elif prediction == -1:
        winner = team2

    return winner

在这里, random_scale 将是决定我们想要对一个团队的表现应用多少随机性的因素。

下一步也是最后一步是创建一个函数,多次运行 match 函数,并计算每个团队的胜利概率。

def simulate_matches(team1, team2, n_matches=10000):

    match_results = []
    for i in range(n_matches):
        match_results.append(match(wc, team1, team2, svc, random_scale=5))

    team1_proba = match_results.count(team1)/len(match_results)*100
    team2_proba = match_results.count(team2)/len(match_results)*100

    print(team1, str(round(team1_proba, 2)) + '%')
    print(team2, str(round(team2_proba,2)) + '%')
    print('-------------------------')
    print()

    if team1_proba > team2_proba:
        overall_winner = team1
    else:
        overall_winner = team2

    return {'team1': team1,
            'team2': team2,
            'team1_proba': team1_proba, 
            'team2_proba': team2_proba, 
            'overall_winner': overall_winner,
            'match_results': match_results}

让我们看看下周日克罗地亚击败丹麦有多难:

simulation_test = simulate_matches('croatia', 'denmark', n_matches=10000)

克罗地亚:40.62%
丹麦:59.38%

好的,这里你看到模型估计丹麦击败克罗地亚的概率更高,那可能是因为 Fifa 指数数据集很可能没有考虑克罗地亚在世界杯开始后的表现。

随着我们进行越来越多的模拟,让我们来衡量两个团队概率之间的差异:

p_list = []
for i in range(len(simulation_test['match_results'])):
    denmark = simulation_test['match_results'][:i].count('denmark') / (i+1) * 100
    croatia = simulation_test['match_results'][:i].count('croatia') / (i+1) * 100
    p_list.append(denmark - croatia)

我们可以看到,赢家概率稳定在大约 8,000 场比赛模拟中,这就是我们要使用的值。让我们建立冠军树:

仅此而已。2018 世界杯全模拟——淘汰赛!

考虑到我们的模型有 30%的误差,让我们计算一下西班牙击败所有球队并实际成为冠军的几率:

spain_proba = 0.817 * 0.862 * 0.718 * 0.593 * 100 * (0.7 ** 4)print('Chance of Spain winning:', str(round(spain_proba,2)) + '%')

西班牙获胜的几率:7.2%

嗯,我觉得这很公*。只是仍然希望巴西证明它是错的!

这个帖子到此为止。本文旨在展示如何使用机器学习来计算模拟中的概率,并不试图实际获得正确的结果,因为使用的数据还不够(或者事件本身根本不可预测)。请把这当成一个教程,用世界杯比赛只是因为这是一个很酷的和最新的主题。应该使用更深入的方法来提高结果的清晰度,使它们在任何级别都有意义!

可以增加一些步骤来改进模型,包括:

  • 尝试更复杂的机器学习算法和微调超参数
  • 收集更多的数据,不仅仅是国际数据,还有国家队的训练数据
  • 更进一步,基于玩家统计数据建立一个模型,这篇文章对这种方法有很好的介绍

这是我的第一篇文章,所以谢谢你一直读到最后。我会试着每个月发布一些与数据科学和机器学习相关的好材料。欢迎发表任何评论或关注,如果你喜欢,别忘了为鼓掌!谢谢,下次发帖再见。

用马尔可夫链蒙特卡罗方法进行项目估算

原文:https://towardsdatascience.com/using-markov-chain-monte-carlo-method-for-project-estimation-cd641f8038ce?source=collection_archive---------14-----------------------

用张量流概率进行哈密顿取样

Free photo from https://pixabay.com

我收到的对之前项目评估工作的一种批评是对数正态分布有短尾巴。这是真的,尽管对数正态分布有很多好处。原因很简单:当将数据拟合到分布形状时,我们选择最可能的参数μμ和σσ。这种方法,无论多么简单,总是导致短尾巴,特别是对于我们拥有的少量数据。事实上,对数正态分布的参数可能不同于我们基于五个数据点得到的最可能的参数。合适的方法是获得预测和参数的联合分布,然后根据参数进行边缘化。在正态分布的情况下,我们将得到具有漂亮长尾的学生 t 分布。对于对数正态分布,我们会得到一个更复杂的分布,但也有长尾。

为了提醒您我们正在处理的问题,我们的任务是根据历史数据来估计一个敏捷迭代/sprint 中可以容纳的故事点的数量。特别是,我们感兴趣的是找到我们可以在一次迭代中完成的故事点的数量,并且有 95%的置信度。

我们将从定义大小为 1 的样本的似然函数开始:

让我们选择μ和σ的先验。

对于σ,我们选择非信息先验:

对于μ,我们选择共轭先验,它是具有 L2 正则化超参数λ的正态分布:

这种情况下的后验概率正比于:

因此,让我们计算百分位数的联合概率分布是:

因此,我们可以通过忽略参数μ和σ来计算所有百分点。答案可以通过分析得出,但在我们的情况下,我想用 MCMC 哈密顿取样法数值求解。

这种方法的思想是得到一个联合分布 p(x,μ,σ2|x(i))的样本。之后,我们可以计算 x 的百分位数。这相当于通过后验分布的参数边缘化。

正如我前面说过的,答案可以通过分析得出,但是我们将使用一种可以用于分布的方法,对于这种分布,很难或者不可能获得样本。这种方法叫做马尔可夫链蒙特卡罗。该方法的思想是在变量空间中进行随机行走,但是尝试更频繁地访问更可能的区域,以便在结果样本中直方图遵循概率分布。在这种情况下,一些不太可能的值必须被拒绝。

MCMC 的一个特殊风格是哈密尔顿采样方法。它有点类似于梯度下降算法,除了 MCMC 中的步长足够大,而不是试图收敛到成本函数的最小值,因此它也探索变量空间中可能性较小的区域,但是倾向于更频繁地访问高可能性区域。

为此,我们需要取联合分布函数的对数(忽略常数):

有很多库做哈密顿取样。甚至还有为此优化的概率编程语言,比如 Stan 。但是这里我们将使用 TensorFlow Probability,这是一个由 Google 创建的概率库

**import** **numpy** **as** **np**
**import** **pandas** **as** **pd**
**import** **tensorflow** **as** **tf**
**import** **tensorflow_probability** **as** **tfp**lamb = 2e-1
**def** log_likelihood(x, mu, sigma2):
    'The (negative) log likelihood function for one sample'
    **return** (tf.log(x)-mu)**2/2.0/sigma2**def** get_unnormalized_log_probability(data):
    **def** joined_probability(x, mu, sigma2):
        result = -(2.0+len(data))/2*tf.log(sigma2) - lamb * mu**2/2.0 -log_likelihood(x, mu, sigma2) *#sigma2*
        **for** datum **in** data:
            result -= log_likelihood(float(datum), mu, sigma2)
        **return** result
    **return** joined_probability

我们希望确保我们的功能正常工作,最好的方法是编写一个单元测试

**import** **unittest**
**import** **math****class** **TestUnnormalizedLogProbability**(unittest.TestCase): **def** test_get(self):
        tf.reset_default_graph()
        data=np.array([1.0,1.0])
        x = tf.constant(value=1.0)
        mu = tf.constant(value=0.0)
        sigma2 = tf.exp(1.0)
        probability_function = get_unnormalized_log_probability(data)
        probability = probability_function(x, mu, sigma2)

        init = tf.global_variables_initializer() **with** tf.Session() **as** sess:
            sess.run(init)
            self.assertTrue(abs(-2-probability.eval())<1e-5)

unittest.main(argv=[''], verbosity=0, exit=**False**);*----------------------------------------------------------------------
Ran 1 test in 0.088s**OK*

我们将使用与之前相同的数据

data=np.array([14, 12,  7, 14, 13])
*# Create state to hold updated `step_size`.*
step_size = tf.get_variable(
    name='step_size',
    initializer=1e-1,
    use_resource=**True**,  *# For TFE compatibility.*
    trainable=**False**)*# Initialize the HMC transition kernel.*
hmc = tfp.mcmc.HamiltonianMonteCarlo(
    target_log_prob_fn=get_unnormalized_log_probability(data),
    num_leapfrog_steps=3,
    step_size=step_size,
    step_size_update_fn=tfp.mcmc.make_simple_step_size_update_policy(),
    seed=1398)*# Run the chain (with burn-in).*
samples, kernel_results = tfp.mcmc.sample_chain(
    num_results=int(1e5),
    *#num_burnin_steps=int(1e1),*
    current_state=[10.0,2.0,0.2],
    kernel=hmc)*# Initialize all constructed variables.*
init_op = tf.global_variables_initializer()**with** tf.Session() **as** sess:
    init_op.run()
    samples_, kernel_results_ = sess.run([samples, kernel_results])all_samples = np.array(samples_)
all_samples.shape*(3, 100000)*

我们的结果有三行,分别是 x,μ和σ。我们可以利用这三个变量

all_samples.mean(axis=1)*array([14.040146  ,  2.4572225 ,  0.21323058], dtype=float32)*

出乎意料的是,x的均值比我们想象的要高(12)。让我们绘制直方图来查看概率分布:

%**matplotlib** inline
**import** **matplotlib.pyplot** **as** **plt**
**import** **seaborn** **as** **sns**
fig, ax = plt.subplots(figsize=(11.7, 8.27))
sns.distplot(all_samples[0,:], hist=**False**);

我们看到最大值约为 12,因为我们将使用最大后验分布。

该曲线具有不规则的形状,但对于多变量 MCMC 结果来说,这在某种程度上是意料之中的。还要注意,对数正态分布的尾部更长。这是忽略后验分布参数的结果。让我们看看我们 95%的信心会落在哪里:

np.percentile(all_samples[0,:], q=5)*7.160015678405762*

95%的置信度也非常接*我们用更简单的方法得到的结果。然而,用 MCMC I 进行的实验发现,该方法不稳定,并且强烈依赖于播种、初始值和超参数的选择。随着维度的增加,这个问题变得更加严重。

结论

在这个故事中,我们试图在敏捷项目评估中使用贝叶斯方法,而不是分析性地计算百分位数,我们展示了如何使用马尔可夫链蒙特卡罗和哈密尔顿抽样来实现这个结果。我们还演示了如何在 TensorFlow 概率包中实现它。

利用最大似然法自动检测汽车牌照

原文:https://towardsdatascience.com/using-ml-to-automatically-detect-vehicle-number-plates-8e5bebc8b7dc?source=collection_archive---------6-----------------------

概观

我们讨论底层技术,它在不同领域的应用,如收费站,犯罪预防等。然后,我们给出了一个如何使用张量流实现这一点的演练。

然后我们讨论代码和算法,浏览最终的输出和精度数字。

简介:

LPR(license plate recognition)是一种技术,主要是软件,它使计算机系统能够从数字图片中自动读取车辆的注册号码(牌照号码)。

自动读取车牌号意味着将数字图像的像素转换成车牌的 ASCII 文本。

由于车辆的日益增多,车牌识别(LPR)在这个繁忙的世界中扮演着重要的角色。偷窃车辆、违反交通规则、进入受限空间也呈线性增长,因此想要阻止这种行为。

车牌识别是车辆自动识别的一种有效方法。在诸如车牌检测、字符分割和每个字符的识别的基本处理步骤中,分割起着重要的作用,因为识别的准确性基于分割的完美程度。这项工作特别处理印度车牌的识别,也可以扩展到识别。

ANPR 是如何工作的?

当车辆到达指定的入口时,摄像头会自动检测并读取车牌。随后生成的数据被立即存储(在停车场的情况下),或者可以基于生成的数据和预先确定的设置来准许或拒绝访问。该数据被存储以供将来分析(在 IT 园区或门禁社区的情况下)。通过在两端安装不同的摄像机,可以并行管理入口和出口系统。每台摄像机都有一个 IP 地址,整个系统以高度的连通性连接在一起。

该系统利用互联网协议进行控制和通信,但该结构通过加密数据流保持高度安全。可以在安装时设置访问权限。

技术要求:

从 LPR/ANPR 的角度来看,图像质量始终是关键因素。捕捉快速运动的车辆需要特殊的技术来避免运动模糊,运动模糊会大大降低识别精度。为了确保正确的图像质量,短快门时间需要与高功率照明结合使用。

只有专用的 ANPR 相机才能满足这些要求,如 AHR 的 ANPR 相机,它提供灵活的快门控制,内置红外闪光灯,能够捕捉高达 250 公里/小时的车辆,适用于各种车牌读取应用。

使用案例:

执法:全国和世界各地的执法机构越来越多地采用自动车牌识别(ALPR)系统来增强他们的执法和调查能力,扩大他们的相关数据收集,并加快将车辆牌照与被盗、被通缉和其他相关车辆的列表进行比较的冗长耗时的过程。德国、瑞典、丹麦、加拿大等多个国家已经部署了 ALPR 用于执法目的。

交通控制:软件可以分析视频数据,并可以计算交通流量参数,从而计算出以下标准交通特征:

  • *均速度[公里/小时];
  • 交通量(每小时车辆数)[车辆/小时];
  • 交通密度[车辆/公里]。

任何违反标准限制的车辆都可能被黑启动,并根据国家法律采取进一步的行动。

收费公路:借助这个 ANPR,我们可以减少整个收费过程中的人为交互,提高系统的安全水*。这项技术将用于全国各地的不同收费亭,在那里可以很容易地控制交通和有效地管理时间。

犯罪威慑:自动车牌识别(ANPR)技术用于在地方、部队、地区和国家层面帮助检测、威慑和破坏犯罪活动,包括打击流窜犯、有组织犯罪集团和恐怖分子。ANPR 为犯罪调查提供线索和证据,被英格兰、威尔士、苏格兰和北爱尔兰的执法机构广泛使用。

印度车牌的自动车牌检测:

印度车牌的数据集不可用,因此需要从头开始创建。为此,从谷歌下载了大约 700 张图片,并对数据进行了清理。清理后的数据集有 250 幅图像,这些图像被上传到 Dataturks 注释工具(矩形边界框)并进行手动注释。

The Dataset on Dataturks

该工具自动解析图像,允许我们创建感兴趣的实体的注释,并生成 JSON 格式的训练数据,每行包含图像链接以及注释细节。

数据快照如下所示:

上面的数据集由 230 张带注释的图像组成,可以在这里找到。我们用 200 份简历数据训练模型,在 30 张图片上测试。

由 Dataturks 注释工具生成的 JSON 格式的数据示例如下:

为运行 Tensorflow 模型准备数据集:

带注释的数据被下载(到一个包含图像和 JSON 文档的文件夹中)并被分成训练和测试数据,如上所述。然后,训练和测试文件夹作为 python 脚本的输入,用于将数据转换为 Pascal VOC(这里是演示)。

由代码生成的 pascal voc 的 XML 格式数据的示例如下:

从 json 到 Pascal VOC 脚本获得的 xml 文档和图像然后被转换成一组 csv 记录和图像。最后,这些数据被转换成张量记录用于训练和测试。生成的张量记录示例如下:

github 上提供了将数据转换为不同格式的代码:

培训:

模型的训练是在 Ubuntu 16.04 LTS GPU 箱上完成的,该 GPU 箱具有 NVIDIA TESLA K80 和 7GB RAM、12GB 显卡以及 30 GB 硬盘。训练进行了 10,000 步,耗时约 2.5 -3 小时。

可以在 Dataturks 博客帖子中找到详细的培训教程,标题为使用 Tensorflow 和 GCP 在电子商务中自动标记服装。

因为我使用了 MobileNet 模型,所以我对相同的配置文件进行了更改。训练好的模型可以在这里下载。

配置文件中的更改:

后面部分:

number-plate-detection . Pb txt:

运行培训作业

可以使用以下命令运行本地培训作业:

其中${PATH_TO_YOUR_PIPELINE_CONFIG}指向流水线配置,而${PATH_TO_TRAIN_DIR}指向训练检查点和事件将被写入的目录。默认情况下,训练作业将无限期运行,直到用户终止它或者它完成了提到的步骤数。

运行评估作业

评估作为单独的作业运行。eval 作业将定期轮询 train 目录中的新检查点,并在测试数据集上对其进行评估。可以使用以下命令运行该作业:

其中${PATH_TO_YOUR_PIPELINE_CONFIG}指向流水线配置,${PATH_TO_TRAIN_DIR}指向保存训练检查点的目录(与训练作业相同),而${PATH_TO_EVAL_DIR}指向保存评估事件的目录。与培训作业一样,默认情况下,eval 作业会一直运行,直到终止。

测试:

模型准备变量单元格:

在被检测的第一个单元中:

这将完成您的模型的测试。

对测试图像进行测试:

对真实视频帧的测试:

请不要说我没有在 CCTV 视频上测试过,而是在 CCTV 视频帧上测试过。为此,需要将 opencv 视频捕获附加到该代码上,并对每一帧运行它。这可能是一个有趣的扩展,并且将向实时部署迈进一步。

注意:关于培训、测试、tensorboard 和运行评估工作的详细教程可以在 Dataturks 博客帖子中找到,标题为使用 Tensorflow 和 GCP 在电子商务中自动标记服装。

结论:

结果令人印象深刻,在 30 幅测试图像中,有 27 幅得到了正确的分类。分类的置信度在 85%到 99%之间。

移动互联网似乎在实时检测方面发挥了惊人的作用。许多类似的应用程序也已经使用 inception net 开发出来,但是移动网络的结果已经被证明比 inception net 更适合实时应用。

为什么选择 MobileNets?

研究表明,inception net 是 CPU 密集型的,全速运行时使用 25-30%。有道理,因为我们会以和汽车经过一样快的速度行驶。我们希望降低到 5%以下,我们将通过降低它运行的频率来做到这一点,因为我们的用例不需要连续运行推理来实现我们上面讨论的隐私目标。将它改为每 18 帧分类一次(大约每秒一次)会将*均使用率降低到大约 5.5%。所以 MobileNet 模型是 Inception 的 1/30 大。每帧运行速度提高了 3 倍以上。而且它使用的 CPU 资源要少得多。

应用:

这些用于图像分类的定制模型可以部署在停车场、科技园或任何其他门禁社区的现场汽车监控中。

我希望听到任何建议或疑问。请在 devika.mishra@dataturks.com 给我写信

资源:

所有代码:车牌检测代码

数据集:车辆号牌检测数据集

使用蒙特卡洛树搜索你的梦幻足球选秀

原文:https://towardsdatascience.com/using-monte-carlo-tree-search-for-your-fantasy-football-draft-6509b78a1c20?source=collection_archive---------9-----------------------

本帖中的代码也可作为 Jupyter 笔记本

离下一个美式足球赛季开始还有两个月,这意味着世界各地的梦幻足球运动员正在为他们即将到来的联赛选秀做准备。在这篇文章中,我们将使用蒙特卡罗树搜索算法来优化我们在一个典型的蛇草案中的下一个选择。如果你不熟悉梦幻足球或者蛇选秀,你可以在 ESPN 的梦幻足球 101 找到很好的介绍。我们将看到一个由十支球队组成的标准 PPR 得分联盟,但是这些设置应该很容易改变以适应你自己的联盟。我们将主要关注草案逻辑的 Python 3 实现,将算法的细节留给文本中的参考,同时仍然提供代码。

Photo by Karri Terra on Pixy

草案

选秀是你的联赛赛季的开始。每个竞争者挑选真实世界的足球运动员来组成他的初始名单。糟糕的选秀真的会毁了你的赛季,所以很多研究都花在为你的球队挑选合适的球员上。在大多数联赛中,选择是按照蛇的顺序依次进行的(1 比 10,然后 10 比 1,等等)。).这意味着在正确的时间填补正确的位置是你战略的重要组成部分。如果你的大部分竞争对手都是从挑选外接球手开始的,你应该从众还是逆势而为?这正是我们想用算法回答的问题。

但首先是逻辑草案。我们需要一个对象来描述我们草稿的确切状态。在每个回合中,我们需要知道到目前为止每个花名册选择了哪些足球运动员,哪些足球运动员仍然可用(自由球员),接下来回合的顺序是什么,以及哪个竞争者最后移动(因此算法可以从该竞争者的角度评估最后移动)。

class DraftState:
    def __init__(self, rosters, turns, freeagents, playerjm=None):
        self.rosters = rosters
        self.freeagents = freeagents
        self.turns = turns
        self.playerJustMoved = playerjm

让我们看看如何准确地评估一个草案状态。我们的名单包括一名四分卫(QB),两名跑卫(RB),两名外接员(WR),一名紧逼端(TE),一名灵活端(RB,WR 或 TE),一名防守端(D),一名踢球者(K)和七名替补。首先,让我们假设我们可以根据每个足球运动员的赛季总幻想点数来评估他的价值。然后,我们可以根据一些权衡来评估阵容中的每个位置。重量是至关重要的,因为我们不能在赛季的每一周都使用相同的球员阵容,因为赛季期间的周、伤病或战略决策。

根据一些实验,下面的重量看起来还可以。

由于草案的逻辑都是关于将足球运动员转移到联盟的名单上,所以包含一个NflPlayer类也是有意义的。

class NflPlayer:
    def __init__(self, name, team, position, points):
        self.name = name
        self.team = team
        self.position = position
        self.points = points

现在可以通过将每个球员(从第一个选秀权开始向下移动)映射到其位置的最高可用权重来评估名册。具体来说,如果出现*局,我们将降低灵活头寸的优先级。如果最后的任何权重没有映射到名册上的球员,则相应位置的前三名自由球员的*均值将映射到该权重——有点像对该位置进行分流。代码如下所示。

import numpy as npdef GetResult(self, playerjm):
    """ Get the game result from the viewpoint of playerjm.
    """
    if playerjm is None: return 0

    pos_wgts = {
        ("QB"): [.6, .4],
        ("WR"): [.7, .7, .4, .2],
        ("RB"): [.7, .7, .4, .2],
        ("TE"): [.6, .4],
        ("RB", "WR", "TE"): [.6, .4],
        ("D"): [.6, .3, .1],
        ("K"): [.5, .2, .2, .1]
    } result = 0
    # map the drafted players to the weights
    for p in self.rosters[playerjm]:
        max_wgt, _, max_pos, old_wgts = max(
            ((wgts[0], -len(lineup_pos), lineup_pos, wgts) for lineup_pos, wgts in pos_wgts.items()
                if p.position in lineup_pos),
            default=(0, 0, (), []))
        if max_wgt > 0:
            result += max_wgt * p.points
            old_wgts.pop(0)
            if not old_wgts:
                pos_wgts.pop(max_pos)

    # map the remaining weights to the top three free agents
    for pos, wgts in pos_wgts.items():
        result += np.mean([p.points for p in self.freeagents if p.position in pos][:3]) * sum(wgts) return resultDraftState.GetResult = GetResult

注意,这个方法包含了很多假设。最值得注意的是,它纯粹基于季节预测,忽略了诸如(共)方差或(强度)时间表之类的东西。此外,它只是孤立地看待每个花名册的价值,而不是相互比较。这些假设应该在以后研究。

让我们继续下一个选秀逻辑——在给定选秀状态的情况下,找出当前竞争对手的可用移动。理论上,你可以选择任何可用的自由球员,但幸运的是,我们可以大大简化事情。因为我们的估价只是基于每个球员的赛季预测,所以选择一个预测比另一个相同位置的自由球员低的自由球员是没有意义的。这将可用的移动限制为选择一个位置(然后选择该位置上最有价值的自由球员)。此外,由于估值中使用的权重,例如起草三个四分卫是没有意义的(第三个四分卫不会增加任何价值)。实际上,以下每个位置的限制似乎是合理的。

这导致了下面的代码。

def GetMoves(self):
    """ Get all possible moves from this state.
    """
    pos_max = {"QB": 2, "WR": 6, "RB": 6, "TE": 2, "D": 2, "K": 1} if len(self.turns) == 0: return [] roster_positions = np.array([p.position for p in  self.rosters[self.turns[0]]], dtype=str)
    moves = [pos for pos, max_ in pos_max.items() if np.sum(roster_positions == pos) < max_]
    return movesDraftState.GetMoves = GetMoves

最后一部分逻辑涉及到在每次选择后更新草稿状态。代码很简单。

def DoMove(self, move):
    """ Update a state by carrying out the given move.
        Must update playerJustMoved.
    """
    player = next(p for p in self.freeagents if p.position == move)
    self.freeagents.remove(player)
    rosterId = self.turns.pop(0)
    self.rosters[rosterId].append(player)
    self.playerJustMoved = rosterId

DraftState.DoMove = DoMove

最后,我们的算法需要一个Clone方法,这样多个模拟运行就不会相互干扰。

def Clone(self):
    """ Create a deep clone of this game state.
    """
    rosters = list(map(lambda r: r[:], self.rosters))
    st = DraftState(rosters, self.turns[:], self.freeagents[:],
            self.playerJustMoved)
    return stDraftState.Clone = Clone

该算法

蒙特卡洛树搜索是一种启发式搜索算法,用于在基于回合的游戏中寻找最佳的下一步棋,在这种游戏中,几乎不可能考虑所有可能的棋步(及其最终结果)。它被成功地用于玩游戏,如国际象棋和扑克,最*是谷歌战胜世界冠军围棋手的一个非常重要的部分。因为我们的蛇形选秀也是回合制的,每回合都有很多可能的走法,所以 MCTS 看起来是击败我们竞争对手的绝佳选择。该算法背后的基本思想是模拟大量的游戏——首先通过选择随机移动,然后通过专注于最有希望的移动来收敛到最佳移动。它*衡了探索(寻找更有前途的步骤)和开发(关注最有前途的步骤)之间的权衡。

我们下面使用的实现来自 MCTS 研究中心,在那里你也可以找到对算法的很好的介绍。另一个精彩的介绍请看一下杰夫·布拉德伯里的博客文章。

# This is a very simple implementation of the UCT Monte Carlo Tree Search algorithm in Python 2.7.
# The function UCT(rootstate, itermax, verbose = False) is towards the bottom of the code.
# It aims to have the clearest and simplest possible code, and for the sake of clarity, the code
# is orders of magnitude less efficient than it could be made, particularly by using a 
# state.GetRandomMove() or state.DoRandomRollout() function.
# 
# Written by Peter Cowling, Ed Powley, Daniel Whitehouse (University of York, UK) September 2012.
# 
# Licence is granted to freely use and distribute for any sensible/legal purpose so long as this comment
# remains in any distributed code.
# 
# For more information about Monte Carlo Tree Search check out our web site at [www.mcts.ai](http://www.mcts.ai)from math import *
import randomclass Node:
    """ A node in the game tree. Note wins is always from the viewpoint of playerJustMoved.
        Crashes if state not specified.
    """
    def __init__(self, move = None, parent = None, state = None):
        self.move = move # the move that got us to this node - "None" for the root node
        self.parentNode = parent # "None" for the root node
        self.childNodes = []
        self.wins = 0
        self.visits = 0
        self.untriedMoves = state.GetMoves() # future child nodes
        self.playerJustMoved = state.playerJustMoved # the only part of the state that the Node needs later

    def UCTSelectChild(self):
        """ Use the UCB1 formula to select a child node. Often a constant UCTK is applied so we have
            lambda c: c.wins/c.visits + UCTK * sqrt(2*log(self.visits)/c.visits to vary the amount of
            exploration versus exploitation.
        """
        UCTK = 200
        s = sorted(self.childNodes, key = lambda c: c.wins/c.visits + UCTK * sqrt(2*log(self.visits)/c.visits))[-1]
        return s

    def AddChild(self, m, s):
        """ Remove m from untriedMoves and add a new child node for this move.
            Return the added child node
        """
        n = Node(move = m, parent = self, state = s)
        self.untriedMoves.remove(m)
        self.childNodes.append(n)
        return n

    def Update(self, result):
        """ Update this node - one additional visit and result additional wins. result must be from the viewpoint of playerJustmoved.
        """
        self.visits += 1
        self.wins += resultdef UCT(rootstate, itermax, verbose = False):
    """ Conduct a UCT search for itermax iterations starting from rootstate.
        Return the best move from the rootstate.
    """ rootnode = Node(state = rootstate) for i in range(itermax):
        node = rootnode
        state = rootstate.Clone() # Select
        while node.untriedMoves == [] and node.childNodes != []: # node is fully expanded and non-terminal
            node = node.UCTSelectChild()
            state.DoMove(node.move) # Expand
        if node.untriedMoves != []: # if we can expand (i.e. state/node is non-terminal)
            m = random.choice(node.untriedMoves) 
            state.DoMove(m)
            node = node.AddChild(m,state) # add child and descend tree # Rollout - this can often be made orders of magnitude quicker using a state.GetRandomMove() function
        while state.GetMoves() != []: # while state is non-terminal
            state.DoMove(random.choice(state.GetMoves())) # Backpropagate
        while node != None: # backpropagate from the expanded node and work back to the root node
            node.Update(state.GetResult(node.playerJustMoved)) # state is terminal. Update node with result from POV of node.playerJustMoved
            node = node.parentNode return sorted(rootnode.childNodes, key = lambda c: c.visits)[-1].move # return the move that was most visited

从字面上看,这段代码唯一的变化是在UCTSelectChild中,我们应用了UCTK来更好地权衡勘探和开发。这是必要的,因为原始代码是基于 0(输)和 1(赢)之间的比赛结果,而我们的结果是一个团队的总预测分数,这是完全不同的尺度。值 200 是根据经验设置的。

运行代码

我们现在应该有了运行草案的所有组件。唯一缺少的是季节预测。你可以找到许多网站提供这些预测,但我解决了 ESPN 的预测,因为这是我的联盟主办。我创建了一个 CSV ,对 2018 年的预测如下。

我们可以运行一个完整的草案,其中每个竞争者草案,他的团队使用蒙特卡罗树搜索算法。让我们试一试。

import pandas as pdnfl_players = pd.read_csv("nfl_players.csv", index_col=0)
freeagents = [NflPlayer(*p) for p in nfl_players.itertuples(index=False, name=None)]num_competitors = 10
rosters = [[] for _ in range(num_competitors)] # empty rosters to start withnum_rounds = 16
turns = []
# generate turns by snake order
for i in range(num_rounds):
    turns += reversed(range(num_competitors)) if i % 2 else range(num_competitors)

state = DraftState(rosters, turns, freeagents)
iterations = 1000
while state.GetMoves() != []:
    move = UCT(state, iterations)
    print(move, end=".")
    state.DoMove(move)

到目前为止,一切顺利。虽然代码相当慢,但一切似乎都运行良好。速度还不是我们关注的焦点,需要对实现做进一步的研究。但是现在我认为结果看起来很有希望,我们可以对算法有一个很好的总体想法。需要注意的一点是,上面的代码每轮使用 1000 次迭代,目前看来还可以,但这也需要进一步研究。

各参赛队的最终结果如下所示。

后续步骤

现在我们有了一个应用于梦幻足球选秀的蒙特卡洛搜索树算法的工作版本,我们应该花一些时间来分析性能。我会在我的下一篇文章中尝试一下,所以请关注我的博客…

感谢阅读!请提供反馈。

使用 R 中的 networkD3 创建简单明了的 Sankey 图

原文:https://towardsdatascience.com/using-networkd3-in-r-to-create-simple-and-clear-sankey-diagrams-48f8ba8a4ace?source=collection_archive---------5-----------------------

我发现桑基图对于说明人员流动或偏好非常有用。R 中的networkD3包提供了一种直接生成这些图的方法,不需要知道实际 D3 代码的来龙去脉。

为了说明我的意思,我生成了一个桑基图,以显示英国的 12 个地区如何对 2016 年英国退出欧盟公投的整体结果做出贡献,在公投中,选民以 17,410,742 票对 16,141,241 票选择离开欧盟。

如果你想看到完全交互式的 Sankey 图,你可以在 RPubs 这里通过 RMarkdown 文档查看代码。不幸的是,媒体上只能显示静态图像。

使数据成形

关于英国退出欧盟公投的非常详细的数据可以从英国选举委员会的网站上获得。第一步是加载我们的库,并将数据放入 r 中。由于数据非常详细,直到最本地化的投票中心,我们需要汇总所有的离开和剩余投票,以获得每个地区的总数。

## load librarieslibrary(dplyr)
library(networkD3)
library(tidyr)# read in EU referendum results datasetrefresults <- read.csv("EU-referendum-result-data.csv")# aggregate by regionresults <- refresults %>% 
  dplyr::group_by(Region) %>% 
  dplyr::summarise(Remain = sum(Remain), Leave = sum(Leave))

然后我们需要创建两个数据帧供networkD3在其sankeyNetwork()函数中使用:

  1. 一个nodes数据帧,对源节点(即 12 个英国区域)和目的节点(即离开和留下)进行编号,从零开始。
  2. 一个links数据框架,使用sourcetargetvalue列逐项列出每个流程。例如,西米德兰兹地区为休假投了 1,755,687 票,因此在这种情况下,source将是西米德兰兹的节点,target将是休假的节点,value将是 1,755,687 票。

以下是以这种方式构建数据的一些简单代码:

# format in prep for sankey diagramresults <- tidyr::gather(results, result, vote, -Region)# create nodes dataframeregions <- unique(as.character(results$Region))
nodes <- data.frame(node = c(0:13), 
                    name = c(regions, "Leave", "Remain"))#create links dataframeresults <- merge(results, nodes, by.x = "Region", by.y = "name")
results <- merge(results, nodes, by.x = "result", by.y = "name")
links <- results[ , c("node.x", "node.y", "vote")]
colnames(links) <- c("source", "target", "value")

现在我们已经以正确的方式构建了数据,我们可以简单地使用networkD3::sankeyNetwork()函数来创建图表。这产生了一个简单有效的图表,滚动交互显示每个投票流的细节。这里展示的是静态版本。

# draw sankey networknetworkD3::sankeyNetwork(Links = links, Nodes = nodes, 
                         Source = 'source', 
                         Target = 'target', 
                         Value = 'value', 
                         NodeID = 'name',
                         units = 'votes')

Brexit Referendum 2016 vote flows by region

最初我是一名纯粹的数学家,后来我成为了一名心理计量学家和数据科学家。我热衷于将所有这些学科的严谨性应用到复杂的人的问题上。我也是一个编码极客和日本 RPG 的超级粉丝。在 LinkedIn Twitter上找我。

用自然语言处理检测阿尔茨海默病患者的语言线索

原文:https://towardsdatascience.com/using-nlp-to-detect-linguistic-cues-in-alzheimers-diseases-patients-3364301b0299?source=collection_archive---------7-----------------------

这篇论文旨在从阿尔茨海默病(AD)患者生成的语音转录中检测语言特征语法模式。这被认为是自然语言处理和深度学习技术在计算健康方面的一个重要应用。

简介

作者提出了几种神经模型,如 CNN 和 LSTM-RNNs——以及它们的组合——来增强广告分类任务。训练好的神经模型通过 激活聚类一阶导数显著性 技术用于解释 AD 患者的语言特征(包括性别差异)。

动机

语言变异可以作为监控患者认知功能如何受到影响(例如,单词查找和推理障碍)的代理。这可以使机器具备诊断能力,这对于治疗 AD 特别有效,因为它既不可治愈也不可逆转。

挑战与局限

检测 AD 阳性患者的挑战在于它需要不同的语言和世界知识。考虑下面的例子:

"嗯…有个妈妈站在那里嗯嗯地洗碗,水槽满溢…满溢"有几个语言提示,比如“溢出……溢出,表示混乱记忆丧失的迹象,这在 AD 阳性患者中非常常见。因此,作者提出了一种从数据中自动学习这些语言线索的神经模型,而不是依赖于手工制作的特征。从以前的文献中观察到的其他重要问题如下:

  • 手工制作的特征可能不适合分析 AD 患者数据,这些数据传达了语言模式的渐进变化。
  • 随着语言和文化的发展,手工制作的功能很快就会过时。
  • 仅仅依靠神经网络并不能提供太多的可解释性。

数据

这项工作使用了痴呆银行数据集,它由 AD(和对照组)患者的抄本和音频记录组成。这些记录是通过对几项任务的采访收集的,如“回忆测试”和“波士顿饼干盗窃”。抄本被分割成带有词性(POS)标签的单独话语。

车型

提出了三种类型的神经方法:CNN(嵌入+卷积层+最大池层)、LSTM-RNN(嵌入+ LSTM 层)和 CNN-LSTM(基本上是在 CNN 之上放置一个 LSTM——架构如下图所示)。(详见论文。)

结果

表现最好的模型(POS tags + CNN-LSTM)达到了 91.1%的准确率,这为广告分类任务设定了新的基准。参见下面的其他结果。

作者观察到,几乎所有的 AD 阳性结果都被正确分类,而对非 AD 样本的分类有更多的错误。这可能是因为数据集包含了具有与 AD 相关的不同程度症状的患者。(更多结果见论文。)

分析

男性和女性 AD 患者的语言模式没有显著差异。

此外,使用两种可视化技术对由神经模型捕获的语言线索进行解释:

  • 激活聚类 —提供对句子级模式的洞察
  • 一阶导数显著性 —提供对单词重要性的洞察

通过激活聚类,在 AD 患者中发现的三种常见语言模式从聚类中出现:简短回答和突发言语(例如,“和”和“哦!”),反复要求澄清(例如,“我说的是事实吗?”),并以感叹词(“所以”和“嗯”)开头。此外,对于 Cookie 和 Recall 等几个任务,广告聚类最常用的 POS 标签是不同的。

通过显著性热图,可以看出对照组和 AD 患者之间单词重要性的差异。如下图(左)所示,单词“uh”和“um”是对 AD 患者进行分类的重要且可区分的言语特征。右图显示,控制组没有大量使用这类填充词。

未来工作与结论

  • 结合可视化技术的神经模型可以为 AD 患者的语言线索和变化提供更多的见解。也就是说,这种模型可以推广到研究其他神经疾病。
  • 上下文感知模型和会话上下文可以帮助提高模型的预测性能,并且还提供更多的可解释性。

参考文献

通过解释神经模型检测阿尔茨海默氏痴呆的语言特征——(Sweta Karlekar,Tong Niu,和 Mohit Bansal

使用 NLP 识别控制多个帐户的 Redditors

原文:https://towardsdatascience.com/using-nlp-to-identify-redditors-who-control-multiple-accounts-837483c8b782?source=collection_archive---------7-----------------------

Photo by Daniel Monteiro on Unsplash

介绍

我建立了一个模型,可以确定两个 Reddit 帐户是否由同一个用户控制,仅仅基于他们的写作风格。代码是用 Python 和 Spark 写的,可以在我的 Github 上找到。如果您有任何问题或改进建议,可以通过 Linkedin 联系我。

语境

几个世纪以来,作者可以匿名写作,认为他们的真实身份永远不会被揭露。然而,在过去的几年里,这一切都改变了,因为机器学习方法提高了笔形测量的效率。文体学是对写作风格的研究,涉及通过揭示单词选择、句子结构、标点符号等方面的独特模式来识别作者的写作倾向。

一些最著名的文体分析的例子包括使用它来确定詹姆斯·麦迪逊和亚历山大·汉密尔顿是匿名撰写的《联邦党人文集》的作者,成功地将 J.K .罗琳与《布谷鸟的呼唤》一书的匿名作者联系起来,并确定莎士比亚实际上写了哪些莎士比亚戏剧,哪些是他合写的,哪些是由完全不同的人写的。

但这些都是分析专业人士撰写的大量文本的例子。文体学在文本样本较少的非正式场合(如社交媒体)是否仍然有效?在我们开始区分一个作者的写作风格和另一个作者的写作风格之前,我们需要多少单词?在我们开始看到两个写作风格非常相似的用户之前,我们可以比较多少个作者的匿名文本?

履行

对于这个项目,我想看看能否通过分析 Reddit 上的用户来回答这些问题。网站上的所有用户都以给定的用户名匿名提交帖子和评论,每个人的评论都是公开的。创建 Reddit 帐户所需的唯一信息是一封电子邮件,因此一些用户创建了多个帐户。当一个用户的账户因为不文明的讨论而被禁止进入子编辑时,这就产生了一个问题。他们可以简单地创建另一个帐户来重新获得子编辑访问权。也许,如果我幸运的话,我可以识别两个或更多属于同一个用户的账户,以此帮助 subreddit 版主在他们的社区中保持更健康的讨论。

因为这是一个无监督的学习问题,我需要一些方法来验证我的模型的准确性。为了做到这一点,我获取了一个用户的全部评论历史,并随机抽取了一半的评论,用这些评论创建了一个新的伪用户。然后,我测量了我的模型是否成功地将这个伪用户与包含另外 50%评论的原始用户正确匹配。

基线

文体学中最古老的技术之一可以追溯到 19 世纪,当时通过使用不同长度单词的频率来比较作者。一些人倾向于更多地使用两三个字母的单词,而另一些人倾向于使用更大的词汇量。使用这些单词长度的频率的技术被称为门登霍尔的组成特征曲线(MCCC)。虽然这种技术相当粗糙,但仍然可以用来准确地识别作者。我们可以通过确定具有最低*均 RMSE 的曲线来确定谁的合成曲线与匿名文本的曲线最相似。在 7 个用户的评论历史被分成子集 1 中的伪用户和子集 2 中的原始用户之后,MCCC 首先在 7 个随机选择的 Redditors 的小组上进行测试。

通过遍历子集 1 中的每个伪用户,并将其与子集 2 中的每个用户进行比较,MCCC 实际上能够正确识别 7 个用户中的 5 个。虽然很有希望,但这种技术过于简单,无法大规模使用。

模拟陋居的三角洲

许多自然语言处理应用,如主题建模,通常使用词频-逆文档频率(TF-IDF)来识别可用于帮助描述文本的罕见关键词。在文体学中,最重要的词实际上是虚词,常见的词如“大约”、“因为”、“之上”、“而”。作者通常会写一个广泛的主题,因此他们使用的词汇变化很大。然而,虚词出现在每篇文章中,并且对于给定的作者,它们在不同的文档中的使用频率往往保持相当一致。

在我的分析中,150 个最常用的虚词被用来通过 Delta 方法识别用户的写作风格。记录每个功能词的频率,然后通过减去*均值并除以标准偏差进行标准化,给出每个特征值的 z 得分表示。结果是一个 150 维的向量,在作者比普通用户更频繁地使用一个词的特征维度上是正的,而在作者比普通用户更少地使用一个词的特征维度上是负的。然后,通过余弦相似性的测量,可以最精确地将伪用户的向量与每个用户的向量进行比较。

这种方法大大改善了结果。之前分析的 7 个用户现在以 100%的准确度匹配回他们的正确用户。从一个随机的 40 人小组中识别用户(过滤掉那些评论少于 200 条的用户,这些用户的历史太小,无法识别写作倾向)返回了 95%的准确率。

Cosines of pseudo-users to their original matching accounts vs non-matches

除了词法分析,我们还可以用句法来区分独特的写作风格。使用 nltk 的词性(POS)标记和跳格,我找到了 100 个最常用的词性跳格序列,并对每个用户使用它们的频率进行了矢量化,就像对虚词进行矢量化一样。对于同样的 40 个用户,该模型返回了 90%的准确率。然而,通过将这两种技术结合在一起,我达到了 100%的准确率。

按比例放大

通过继续添加随机用户,该模型继续完美地预测多达 100 个用户的作者身份。超过这一点,当从 3000 个用户中识别出一个用户时,准确率开始稍微下降,一直下降到 92.2%。

准确度下降的原因主要是由于缺乏数据。所有超过 1000 条评论的用户仍然被 100%准确地预测到。评论历史较少的人不容易被识别出来。我还发现某些用户的写作风格不是很独特;它们的绝大多数特征值都在*均值附*徘徊。下图所示的用户 KhasminFFBE 就是这种情况。此外,更多用户的引入增加了一些用户将具有高度相似的写作风格的机会。如果用户倾向于“代码转换”,即在不同的上下文中改变他们的写作风格,他们可能会被意外地识别为具有非常相似的写作倾向的另一个用户。

comparing the feature vectors of two users

为了进一步改进模型,我在特征向量中加入了标点符号的使用和 Reddit 上常用的某些 markdown 格式化方法(比如“ ”用于显示超链接)。我还添加了一些社交媒体上常见的俚语词,这些词类似于之前的一些虚词。这些包括像“耶”、“将要”和“哈哈”这样的词。这使得我的模型在一组 3000 个用户中正确匹配用户的准确率提高到了 93.8%。

Probability distribution of the final model

Alpha for non-matching accounts

从分布中,我能够确定临界值,在该临界值上,我可以拒绝用户不匹配的无效假设。因为错误地禁止用户为假阳性比确定假阴性更有害,所以α应该尽可能小,但是也应该相对于用户总数来选择。

最终应用

使用分层聚类模型来确定任何随机选择的账户实际上是否是由共同用户创作的。下面的树形图显示了 40 个用户的作者聚类分析。选择 0.1%的α水*是考虑到被比较的用户相当少,并且发现误报的可能性极小。对所有 3000 名随机选择的用户也进行了聚类,毫不奇怪,他们都不匹配。

解释结果

当应用于一小群用户或者一个很长的匿名文本(超过 1000 条评论)时,所创建的模型非常准确。较小的子编辑的版主肯定可以使用这种方法来查看他们的用户,看看他们中是否有属于被禁止用户的备用帐户。对于具有较大社区的子街道,这将更加困难,除非在进行风格比较之前可以将可能的嫌疑人缩小到较小的群体。

来源

数据是从谷歌大查询获得的

引用的研究:

理解和解释作者归属的 Delta 度量

使用频繁词类跳转图的小集合的作者归属

更好地理解伯罗斯的文学作者归属三角

也非常感谢 Shlomo Argamon ,他在 2008 年首次引入余弦相似度作为用于作者身份识别的最佳距离度量(并在上述资料中引用)。

使用物体检测实现更智能的零售结账体验

原文:https://towardsdatascience.com/using-object-detection-for-a-smarter-retail-checkout-experience-3f39acef857b?source=collection_archive---------2-----------------------

用数据做酷事!

我一直在玩 Tensorflow 对象检测 API ,对这些模型的强大感到惊讶。我想分享一些实际用例的 API 的性能。

第一个用例是更智能的零售结账体验。在亚马逊 Go 商店宣布后,这是一个热门领域。

商店可以设计成智能货架,跟踪顾客从里面挑选的商品。我通过构建两个对象检测模型来做到这一点——一个跟踪手并捕捉手拾取的东西。第二个独立的模型监控货架空间。见下图 GIF。通过使用两个模型,你可以最小化单一方法的误差。

Hand Tracking and Inventory Monitoring

计算机视觉在零售结账中的另一个应用是,在结账系统中,不是一件一件地扫描物品,而是将所有东西放在一起,摄像头能够检测和记录所有东西。也许我们甚至不需要收银台。购物车可以安装摄像头,你可以推着购物车走出来,当你走出商店时,购物车会给你开账单。这不是很酷吗!我用 API 设计了一个有 3 个随机物品的“迷你”模型,该模型可以很容易地检测出放置了什么和数量。见下图 GIF。通过各种实验,我发现该 API 甚至在仅部分可见的项目上表现得非常好。

Detection of items with high accuracy

那么我们如何建造它呢?

  1. 收集数据

可以通过查看在线公开的数据集或创建自己的数据来收集图像。每种方法都有其优点和缺点。我通常混合使用两种。例如,可以通过使用公开可用的数据集,如 Ego Hand 数据集,来构建手部检测器。该数据集在手形、颜色和姿势方面有很多可变性,当该模型应用于现实世界时,这将是有用的。另一方面,对于货架上或购物车中的商品,最好收集您自己的数据,因为我们不希望有太多的可变性,也希望确保从各个方面收集数据。在你建立你的模型之前,通过使用像 PIL 和 OpenCV 这样的图像处理库来增加你的数据来创建额外的图像总是一个好主意,这些图像在亮度、缩放、旋转等方面有随机的变化。这个过程可以创建大量的额外样本,使模型稳健。

对于对象检测模型,我们需要注释——感兴趣对象周围的边界框。为此,我使用了标签。用 Python 写的,接口用 Qt。这是一个非常方便的工具,注释是以 Pascal VOC 格式创建的,这使得使用 Tensorflow Github — [create_pascal_tf_record](https://github.com/tensorflow/models/blob/master/research/object_detection/create_pascal_tf_record.py).py[create_pet_tf_record.py](https://github.com/tensorflow/models/blob/master/research/object_detection/create_pet_tf_record.py).中共享的脚本创建 TFRecord 文件变得很容易

2。建立模型

我写过一个非常详细的教程,关于在你的自定义数据集上训练 Tensorflow 物体检测 API——用 Tensorflow 物体检测 API 构建一个玩具检测器。以及关联的 Github 。请用这个开始。

在构建模型时,您必须做出的一个重大决定是将哪个对象检测模型用作微调检查点。已在 COCO 数据集上接受培训的可用型号的最新列表如下:

Tensorflow COCO Trained Models

黑白速度和准确性之间存在直接的权衡。对于实时手部检测,最好使用 SSD 模型或更快的 RCNN 初始,这是我个人更喜欢的。对于货架或购物车上的物品检测,我更喜欢速度较慢但精度较高的模型,如更快的 RCNN Resnet 或更快的 RCNN Inception Resnet。

3。测试和改进模型

我个人认为真正的工作是在你建立了模型的第一个版本之后才开始的!由于没有一个模型是完美的,当你开始使用它时,你会注意到它的性能差距。然后,您将需要使用您的直觉来决定是否可以填补这些缺口并改进模型,或者是否需要另一个模型或非模型来达到您期望的准确性。如果幸运的话,您只需要添加额外的数据来提高性能。

如果你想了解更多关于物体检测和 Tensorflow 物体检测 API 的知识,请查看我的文章—Google tensor flow 物体检测 API 是实现图像识别最简单的方法吗?

给我一个❤️,如果你喜欢这个职位:)希望你拉代码,并尝试自己。如果你对这个话题有其他想法,请在这篇文章上发表评论,或者给我发邮件,地址是 priya.toronto3@gmail.com

其他著述:【http://deeplearninganalytics.org/blog】T4

PS:我有自己的深度学习咨询公司,喜欢研究有趣的问题。我已经帮助几家初创公司部署了基于人工智能的创新解决方案。请到 http://deeplearninganalytics.org/的来看看我们吧。

如果你有一个我们可以合作的项目,请通过我的网站或 priya.toronto3@gmail.com 联系我

参考文献:

  • Google Tensorflow 物体检测 Github

在复杂图像分类场景中使用对象检测第 1 部分:

原文:https://towardsdatascience.com/using-object-detection-for-complex-image-classification-scenarios-part-1-779c87d1eecb?source=collection_archive---------10-----------------------

人工智能计算机视觉革命

TLDR;本系列基于在下面的现实生活代码故事中检测复杂策略的工作。该系列的代码可以在这里找到。

第 1 部分:人工智能计算机视觉革命

计算机视觉的最新发展已经改变了计算机视觉的前景。很多曾经被认为只有科幻才有可能的场景,最*变得和消费一个 API 一样容易。

例如,仅在四年前,以下漫画出现在 XKCD 上。

XKCD September 24th 2014

早在 2014 年,对普通开发人员来说,执行基本图像分类的能力被认为接*科幻小说,仅仅三年后,我们不仅可以确定图片是否是鸟类,我们还可以告诉你鸟类的种类,鸟在图片中的位置,并实时跟踪鸟类的迁徙模式。

Microsoft Developer Blog Bird Detection with Azure ML and Active Learning for Object Detection in Partnership with Conservation Metrics November 6, 2018

实际上,并不是每一个计算机视觉问题都与鸟、花、猫和狗有关。

在本系列中,我们将回顾一个来自零售业的真实世界计算机视觉用例,并比较和对比一些可用于解决该问题的不同方法和技术。

一年多前,微软与中欧和东欧的一家大型糖果产品制造商合作,建立了一个机器学习模型,用于验证经销商是否正确库存巧克力。我们合作的公司在超过 14 个国家拥有庞大的连锁超市分销网络。这些经销商中的每一个都被要求根据标准化的政策来安排他们摊位上的巧克力。每个政策都描述了给定的巧克力应该放在哪个货架上,以及应该以什么样的顺序储存。

执行这些政策的“例行”审计活动会产生巨大的成本。我们的合作伙伴希望开发一个系统,让审计员或商店经理可以拍一张照片,并立即被告知货架的库存是否正确,如上图所示。

即使采用最先进的方法,这也具有挑战性,原因有很多,例如:

  • 图像质量
  • 图像角度
  • 微妙的违反政策行为

It’s easy for state of the art models to tell that there are no chocolates in this

尽管一些错误存储货架的图像(如上图右侧所示)是公然违反政策的行为,很容易分类,但其他图像(如下面的“违反一次”图像)则更加微妙,更难正确分类。

It is very difficult to for image recognition models to know that this image is off by one chocolate.

系列挑战

在本系列中,我们将构建一个复杂的策略分类器,类似于上述场景中的分类器。对于要有效存储的图像,必须按以下顺序存储。

  • 顶层搁板(苏打水)
  • 中间搁板(果汁)
  • 底部搁板(水)

On the left we have a Valid Image on the Right we have an Invalid Image

这个问题的潜在技术解决方案

微软提供了一系列人工智能服务,可以用来解决像这样的计算机视觉任务,每个解决方案都可以在 Azure 上运行。

从 Azure Cognitive Services 到 Azure DSVM 和 Azure Machine Learning 每种技术和方法都有不同的优势和权衡,符合计算机视觉用例的范围。

认知服务

Azure 认知服务是一组开箱即用的 API 和高级服务,帮助您在不需要任何领域经验的情况下开始人工智能任务。

Azure DSVM & ML 服务

数据科学虚拟机是 Azure 上的一个虚拟机(VM)映像。它已经安装和配置了许多流行的数据科学和深度学习工具。这些图片附带了流行的数据科学和机器学习工具,包括 Microsoft R Server Developer Edition、Microsoft R Open、Anaconda Python、Julia、Jupyter notebooks、Visual Studio Code、RStudio、xgboost 等等。您可以配置一个 DSVM,而不是自己部署一个类似的工作区,从而在安装、配置和软件包管理过程中节省大量时间。一旦部署了 DSVM,您就可以立即开始您的数据科学项目。

有关 DSVM 的更多信息,请参见在 Azure 上使用 Linux 数据科学虚拟机的数据科学

Azure Machine Learning Service

Azure ML 服务 让你可以更快地建立和训练机器学习模型,并通过 Azure 机器学习服务轻松部署到云或边缘。使用最新的开源技术,如 TensorFlow、PyTorch 或 Jupyter。在本地进行试验,然后通过云中支持 GPU 的大型集群快速向上或向外扩展。通过自动化机器学习和超参数调整加快数据科学的发展。使用集成的 CI/CD 工具跟踪您的实验、管理模型并轻松部署。

深度学习框架和 Keras

通常,深度学习工程师不会完全手动实现矩阵代数运算。相反,他们使用 PyTorch 或 TensorFlow 等框架。Keras 是用 Python 编写的开源神经网络库。它能够在 TensorFlow、微软认知工具包或 Theano 上运行。旨在实现深度神经网络的快速实验,它专注于用户友好、模块化和可扩展。维基百科(一个基于 wiki 技术的多语言的百科全书协作计划ˌ也是一部用不同语言写成的网络百科全书ˌ 其目标及宗旨是为全人类提供自由的百科全书)ˌ开放性的百科全书

[## 在数据科学虚拟机上使用 Jupyter、Docker 和 PyTorch 进行交互式深度学习…

学习使用 Jupyter、PyTorch 和数据科学虚拟机来训练深度学习模型。

docs.microsoft.com](https://docs.microsoft.com/learn/modules/interactive-deep-learning/?WT.mc_id=medium-blog-abornst)

在接下来的系列文章中,我们将探索其中的一些技术和架构,以解决我们自己复杂的策略分类场景。

系列目标

在本系列结束时,您应该更好地

  • 了解人工智能计算机视觉领域
  • 能够构建和部署定制的愿景服务模型
  • 用 Keras 和迁移学习建立 CNN 图像识别模型
  • 使用 VoTT 和 FasterRCNN 来注释和训练用于复杂分类场景的对象检测模型
  • 使用 Azure ML 服务和 ACI 在云上训练和部署定制的计算机视觉模型

资源

[## Pythic Coder 推荐的 Azure 机器学习入门内容

Tldr 由于 DevOps 资源上的帖子很受欢迎,而且很难找到文档,所以我…

medium.com](https://medium.com/microsoftazure/the-pythic-coders-recommended-content-for-getting-started-with-machine-learning-on-azure-fcd1c5a8dbb4) [## aribornstein -概述

@ pythiccoder。aribornstein 有 68 个存储库。在 GitHub 上关注他们的代码。

github.com](https://github.com/aribornstein) [## 认知服务|微软 Azure

微软 Azure Stack 是 Azure 的扩展——将云计算的灵活性和创新性带到您的…

azure.microsoft.com](https://azure.microsoft.com/en-us/services/cognitive-services/?v=18.44a)

下一个帖子

本系列的下一篇文章将讨论如何使用定制视觉服务完成这项任务。后续文章将讨论以下内容:

  • 【Keras CNNs、MobileNet 和迁移学习的政策识别
  • 使用 Keras RetinaNet 进行策略检测
  • 使用 Azure ML 服务在云上训练和计算机视觉模型
  • 使用 Azure 机器学习在远程集群上训练计算机视觉模型

如果您有任何问题、评论或希望我讨论的话题,请随时在 Twitter 上关注我。如果您认为我错过了某个里程碑,请告诉我。

关于作者

亚伦(阿里)博恩施泰因 是一个狂热的人工智能爱好者,对历史充满热情,致力于新技术和计算医学。作为微软云开发倡导团队的开源工程师,他与以色列高科技社区合作,用改变游戏规则的技术解决现实世界的问题,然后将这些技术记录在案、开源并与世界其他地方共享。

将对象检测用于复杂的图像分类场景第 2 部分:

原文:https://towardsdatascience.com/using-object-detection-for-complex-image-classification-scenarios-part-2-54a3a7c60a63?source=collection_archive---------10-----------------------

定制视觉服务

TLDR;本系列基于在下面的现实生活代码故事中检测复杂策略的工作。该系列的代码可以在这里找到。

第二部分:定制视觉服务

在系列文章的最后一篇文章中,我们概述了复杂图像分类任务的挑战。在这篇文章中,我们将介绍并评估 Azure Custom Vision 服务作为解决我们挑战的技术。

定制视觉服务为您的应用带来了机器学习的力量

自定义视觉服务是一个用于构建自定义图像分类器的工具。它使得构建、部署和改进图像分类器变得简单而快速。我们提供了一个 REST API 和一个 web 界面来上传您的图像和训练。

定制视觉服务能做好什么?

定制视觉服务是一个工具,用于构建定制图像分类器,并随着时间的推移使它们变得更好。例如,如果你想要一个可以识别“雏菊”、“水仙花”和“大丽花”图像的工具,你可以训练一个分类器来做这件事。为此,您可以为每个想要识别的标签提供定制视觉服务。

当您尝试分类的项目在您的图像中很突出时,定制视觉服务效果最佳。自定义视觉服务进行“图像分类”,但不进行“对象检测”这意味着自定义视觉服务识别图像是否属于特定对象,但不识别该对象在图像中的位置。

创建一个分类器只需要很少的图像— 每个类 30 张图像就足够启动你的原型。Custom Vision Service 使用的方法对差异具有很强的鲁棒性,这使您可以用很少的数据开始原型制作。但是,这意味着定制视觉服务不太适合您想要检测非常细微差异的情况(例如,质量保证情况下的微小裂缝或凹痕)。)

定制视觉服务旨在简化分类器的构建,并帮助您随着时间的推移提高分类器的质量。

开发者还可以导出他们的模型,在边缘设备上运行,比如 iOS、Android 或 RaspberryPi

下面的步骤将指导您使用 python 和自定义视觉服务为我们的挑战训练一个模型。

以下步骤基于文档快速入门。

准备密钥:

通过登录自定义视觉服务并导航至如下所示的帐户设置,获取您的培训和预测密钥。

创建自定义视觉服务项目

接下来,我们需要使用您在上面获得的密钥,有计划地创建一个新的定制视觉服务项目。

**from** **azure.cognitiveservices.vision.customvision.training** **import** CustomVisionTrainingClient
**from** **azure.cognitiveservices.vision.customvision.training.models** **import** ImageUrlCreateEntryENDPOINT = "https://southcentralus.api.cognitive.microsoft.com"*# Replace with a valid key*
training_key = '' *#<your training key>*
prediction_key = '' *#<your prediction key>*trainer = CustomVisionTrainingClient(training_key, endpoint=ENDPOINT)*# Create a new project*
print("Creating Beverage Policy Classifier...")
project = trainer.create_project("Beverage Policy Classifier")
Creating Beverage Policy Classifier...

将标签添加到项目中

运行以下代码,为我们的有效无效示例创建标签

*# Make two tags in the new project*
valid_tag = trainer.create_tag(project.id, "Valid")
invalid_tag = trainer.create_tag(project.id, "Invalid")

将图像上传到项目

要将图像添加到项目中,请在标记创建后插入以下代码。这将上传带有相应标签的图像。

print ("Adding images...")**import** **os**
**from** **multiprocessing.dummy** **import** Pool **as** ThreadPool**def** upload(filepath):
    **with** open(filepath, mode="rb") **as** img_data:
        **if** "Invalid" **in** filepath:
            trainer.create_images_from_data(project.id, img_data.read(), [ invalid_tag.id ])
        **else**:
            trainer.create_images_from_data(project.id, img_data.read(), [ valid_tag.id ])
    print('.', end='')

**def** upload_parallel(filepaths, threads=5):
    pool = ThreadPool(threads)
    results = pool.map(upload, filepaths)
    pool.close()
    pool.join()valid_dir = "dataset/Beverages/Train/Valid/"
invalid_dir = "dataset/Beverages/Train/Invalid/"
valid_paths = [valid_dir + os.fsdecode(image) **for** image **in** os.listdir(os.fsencode(valid_dir))]
invalid_paths = [invalid_dir + os.fsdecode(image) **for** image **in** os.listdir(os.fsencode(invalid_dir))]
img_paths = valid_paths + invalid_paths
upload_parallel(img_paths)print("Added **{}** images, **{}** valid, **{}** invalid.".format(len(img_paths), len(valid_paths), len(invalid_paths)))
Adding images...
....................................................................................................................................................................................Added 180 images, 90 valid, 90 invalid.

培训项目

既然我们已经向项目添加了标签和图像,我们就可以训练它了。这将创建项目中的第一个迭代。然后我们可以将这个迭代标记为默认迭代。

**import** **time**print ("Training...")
iteration = trainer.train_project(project.id)
**while** (iteration.status == "Training"):
    iteration = trainer.get_iteration(project.id, iteration.id)
    print ("Training status: " + iteration.status)
    time.sleep(1)
Training...
Training status: Training
Training status: Training
Training status: Training
Training status: Training
Training status: Training
Training status: Training
Training status: Training
Training status: Training
Training status: Training
Training status: Completed

评估模型

现在让我们在服务从未见过的本地测试数据集上评估模型。

azure . cognitive services . vision . custom vision . prediction导入customvisionpedictionclient

*# Now there is a trained endpoint, it can be used to make a prediction*predictor = CustomVisionPredictionClient(prediction_key, endpoint=ENDPOINT)project_id = project.id
**def** predict(filepath):
    **with** open(filepath, mode="rb") **as** test_data:
        results = predictor.predict_image(project_id, test_data.read(), iteration.id)
    pred  = max(results.predictions, key=**lambda** x:x.probability).tag_name
    true ='Invalid' **if** "Invalid" **in** filepath **else** 'Valid'
    print('.', pred , end='')
    **return** (true, pred)

**def** predict_parallel(filepaths, threads=2):
    pool = ThreadPool(threads)
    results = pool.map(predict, filepaths)
    pool.close()
    pool.join()
    **return** zip(*results)test_valid_dir = "dataset/Beverages/Test/Valid/"
test_invalid_dir = "dataset/Beverages/Test//Invalid/"
test_valid_paths = [test_valid_dir + os.fsdecode(image) **for** image **in** os.listdir(os.fsencode(test_valid_dir))]
test_invalid_paths = [test_invalid_dir + os.fsdecode(image) **for** image **in** os.listdir(os.fsencode(test_invalid_dir))]
test_img_paths = test_valid_paths + test_invalid_pathsy_true, y_pred = predict_parallel(test_img_paths)
. Valid. Valid. Valid. Valid. Valid. Valid. Valid. Valid. Valid. Valid. Valid. Valid. Valid. Valid. Valid. Valid. Valid. Valid. Valid. Valid. Valid. Valid. Valid. Valid. Valid. Valid. Valid. Valid. Invalid. Valid. Invalid. Valid. Invalid. Invalid. Invalid. Invalid. Invalid. Invalid. Invalid. Invalid. Invalid. Invalid. Invalid. Invalid. Invalid. Invalid. Invalid. Invalid. Invalid. Invalid. Invalid. Invalid. Invalid. Invalid. Invalid. Invalid. Invalid. Invalid. Invalid. Invalid

第七步:基准测试

**from** **utils** **import** classification_report
classification_report(y_true, y_pred)

precision    recall  f1-score   support Invalid       1.00      1.00      1.00        30
       Valid       1.00      1.00      1.00        30 micro avg       1.00      1.00      1.00        60
   macro avg       1.00      1.00      1.00        60
weighted avg       1.00      1.00      1.00        60Confusion matrix, without normalization
[[30  0]
 [ 0 30]]
Normalized confusion matrix
[[1\. 0.]
 [0\. 1.]]

结论

正如您所看到的,custom vision 服务是一个很好的工具,可以用相对较少的数据和较少的工作生成强大的模型。在大多数用例中,它是一个 go too 工具,也是一个很好的起点。当您尝试分类的项目在您的图像中很突出时,定制视觉服务效果最佳。

该服务是任何分类任务的起点。但是,在为生产进行部署时,有几个事项需要考虑。

  1. 服务失败的情况有哪些(可能是 2%的错误情况在生产中出现 30%,或者是您的用例中要考虑的最重要的情况。
  2. 您正在对多少个类别/策略进行分类(2-10 个策略的模型效果更好)
  3. 你的任务是什么领域?

资源

[## Pythic Coder 推荐的 Azure 机器学习入门内容

Tldr 由于 DevOps 资源上的帖子很受欢迎,而且很难找到文档,所以我…

medium.com](https://medium.com/microsoftazure/the-pythic-coders-recommended-content-for-getting-started-with-machine-learning-on-azure-fcd1c5a8dbb4) [## aribornstein —概述

@ pythiccoder。aribornstein 有 68 个存储库。在 GitHub 上关注他们的代码。

github.com](https://github.com/aribornstein) [## 认知服务|微软 Azure

微软 Azure Stack 是 Azure 的扩展——将云计算的灵活性和创新性带到您的…

azure.microsoft.com](https://azure.microsoft.com/services/cognitive-services/?v=18.44a&v=18.44a&v=18.44a&WT.mc_id=medium-blog-abornst)

下一篇文章

本系列的下一篇文章将回顾如何通过 Keras CNNs、MobileNet 和迁移学习的政策认可来完成这项任务后续文章将讨论以下内容:

  • 使用 Keras RetinaNet 进行策略检测
  • 使用 Azure ML 服务在云上训练和计算机视觉模型
  • 使用 Azure 机器学习在远程集群上训练计算机视觉模型

如果您有任何问题、评论或希望我讨论的话题,请随时关注我的 Twitter 如果您认为我错过了某个里程碑,请告诉我。

关于作者

亚伦(阿里)博恩施泰因 是一个狂热的人工智能爱好者,对历史充满热情,致力于新技术和计算医学。作为微软云开发倡导团队的开源工程师,他与以色列高科技社区合作,用改变游戏规则的技术解决现实世界的问题,然后将这些技术记录在案、开源并与世界其他地方共享。

使用开源 Prophet 包在 R

原文:https://towardsdatascience.com/using-open-source-prophet-package-to-make-future-predictions-in-r-ece585b73687?source=collection_archive---------2-----------------------

几乎每个公司都希望回答一周/一月/一年后他们会在哪里。在规划公司的基础设施、KPI(关键绩效指标)和员工目标时,这些问题的答案可能很有价值。
因此,使用数据预测工具是数据专业人员需要承担的常见任务之一。

最*作为开源发布的一个工具是脸书的时间序列预测包 Prophet 。R 和 Python 都可以使用,这是一个相对容易实现的模型,带有一些非常需要的定制选项。
在这篇文章中,我将回顾 Prophet,并接着介绍一个简单的 R 代码示例。这个代码流的灵感很大程度上来自于官方软件包用户指南。

我们将使用从 wikishark 提取的开放数据集,保存勒布朗·詹姆斯维基百科文章页面的每日数据入口。接下来,我们将基于历史数据构建每日预测。

  • wikishark 在文章发布后被关闭。你可以使用另一个有用的网站获取数据。

阶段 1 —安装和导入 prophet

**install.packages(‘prophet’)
library(prophet)
library(dplyr)**

阶段 2 —加载数据集

**stats <- read.csv(“lebron.csv”, header=FALSE, sep=”,”)
colnames(stats) <- c(“ds”, “y”)
head(stats)
#daily data points starting from 2014–01–0**

**stats$y <- log10(stats$y)**

对于我们的代码示例,我们将转换数据并使用入口日志。这将有助于我们理解预测可视化。

第 3 阶段—探索数据

**View(summary(stats))
plot(y ~ ds, stats, type = "l")**

我们可以看到这些数据是从 2014 年 1 月 1 日到 2016 年 12 月 31 日,从 4 月到 6 月有一些年度季节性高峰。

第 4 阶段—基本预测

**m <- prophet(stats)
future <- make_future_dataframe(m, periods = 365)
forecast <- predict(m, future)**

像机器学习模型一样,第一个命令适合数据帧上的模型,接下来将使用 predict 命令部署模型,以便接收所需天数的预测。

**plot(m, forecast)**

prophet 软件包的开箱即用可视化非常好,具有预定义的刻度线、数据点和不确定性区间。这是这个开源包的优点之一,不需要额外的定制,第一个结果足够快和好,可以满足大多数需求。

predicting one year of future data points

使用这个图表,我们可以更清楚地发现年度趋势和季节性,以及如何利用它们进行预测。

**tail(forecast[c(‘ds’, ‘yhat’, ‘yhat_lower’, ‘yhat_upper’)])**

预测对象保存原始数据以及按天和不确定间隔的预测值。还可以通过以下方式访问预测趋势和季节性成分:

**tail(forecast)**

阶段 5-检查模型组件

**prophet_plot_components(m, forecast)**

为了保持简单性,查看模型的组件很容易。显示总体趋势、每周和每年的季节性。

Model components

第 6 阶段—定制假期和活动

最后一个组件图显示了在 NBA 季后赛和 NBA 总决赛期间对勒布朗·詹姆斯的兴趣增加。此时,模型识别每年返回的年度季节性。另一方面,勒布朗·詹姆斯目前保持着连续 6 年参加 NBA 季后赛的记录,从迈阿密开始,继续在骑士队。所以我们应该期待年复一年的季节性。

增加假期和活动是该套餐的一大优势。首先,通过使预测更准确,并允许用户考虑已知的未来事件。开发人员已经使这种定制比以前的时间序列包更容易,在以前的时间序列包中,为了进行预测,应该手动更改或忽略事件和假日。设想一个电子商务网站,它可以添加所有重复出现的活动和促销,并根据已知的未来活动日期设定收入目标。

添加事件和假日是通过创建一个新的数据帧来完成的,在该数据帧中,我们传递事件的开始或结束日期以及天数。在这个例子中,我们将添加 NBA 季后赛和 NBA 总决赛作为事件

**playoff_brackets <- data_frame(
 holiday = ‘playoffs’,
 ds = as.Date(c(‘2017–04–16’ ,’2016–04–17', ‘2015–04–19’, ‘2014–04–19’)),
 lower_window = 0,
 upper_window = 45
)****playoff_finals <- data_frame(
 holiday = ‘playoff_finals’,
 ds = as.Date(c(‘2016–06–02’, ‘2015–06–04’, ‘2014–06–05’)),
 lower_window = 0,
 upper_window = 20
)**

使用较低和较高的窗口参数,用户可以设置假期的长度。这些映射将被行绑定到单个对象,并在 holidays 参数中传递。

**holidays <- bind_rows(playoff_brackets, playoff_finals)
m <- prophet(stats, holidays = playoff_brackets)
forecast <- predict(m, future)
plot(m, forecast)**

请注意,该模型可以更好地预测峰值期间的值。再次打印出组件将显示增加的假日行对预测的影响。从理论上讲,您可以绘制许多对业务至关重要的事件,并获得更好的预测。

第 7 阶段—去除异常值

构建预测时,从历史数据中移除异常值非常重要。尽管这些数据点是单次事件或者只是错误的事件日志,但是模型使用这些数据点将它们的影响添加到预测中。与其他包不同,当传递安娜值和历史数据时会崩溃,Prophet 将忽略这些日期。

在本例中,我们将删除一系列单次事件,其中 NBA 球员宣布他将离开迈阿密前往克利夫兰,这可能会引起人们对他的维基百科页面的注意。

**outliers <- (as.Date(stats$ds) > as.Date(‘2014–07–09’)
 & as.Date(stats$ds) < as.Date(‘2014–07–12’))
stats$y[outliers] = NA**

第 8 阶段—更多功能

此时,我们可以看到开发人员在创建这个包时所考虑的简单性和健壮性。一些我没有展示但应该使用的额外功能:

  • 变化的季节性和假日效应量表
  • 绘制关键趋势变化点
  • 编辑不确定性区间

使用 Prophet 进行异常检测

我希望开发人员的下一步是使用这个包,并利用它对时间序列数据进行异常检测。先前的软件包提供了这样的功能,但是严重依赖于数据结构和严格的季节性。

让我们使用现有的模型来映射数据中的异常。我们将原始值(y)与预测模型值(yhat)进行比较,并创建一个名为 diff_values 的新列。

**combined_data <- cbind(head(forecast, nrow(stats)), stats[order(stats$ds),])
combined_data$diff_values <- (combined_data$y - combined_data$yhat)
summary(combined_data$diff_values)**Min. 1st Qu. Median Mean 3rd Qu. Max. 
0.05269 0.07326 0.10780 0.13490 0.16520 0.29480

为了更好地概括异常检测,我们还将添加标准化的 diff 值,表示与实际值的百分比差异。

**combined_data$diff_values_normalized <-
(combined_data$y - combined_data$yhat) / combined_data$y**

让我们继续观察随时间变化的标准化 diff 值。

**plot(diff_values_normalized ~ ds, combined_data, type = “l”)**

Normalized difference prediction to actual values

大多数预测值都非常接*实际值,因为图表倾向于在 0 值附*移动。我们还可以通过过滤 diff_values_normalized 列的绝对值来询问异常数据点的百分比。设置一个数据点被视为异常的阈值是一种观察方法。在这个例子中是 10%

**nrow(combined_data[abs(combined_data$diff_values_normalized) > 0.1
& !is.na(combined_data$y),]) / nrow(combined_data)**

我们得到 0.02,这表明基于给定的阈值,2%的数据点是异常的。

结束语

做预测是数据专业人员的一项重要技能。感谢像 Prophet 这样的开源项目,这不需要太困难。这个软件包*衡了简单性、计算速度和适当的定制量,因此初学者和高级用户都可以使用它。

感谢阅读,
Harel Rechavia ,
Viber 的数据分析师

如何使用 pix2pix 创建 SnapChat 镜头

原文:https://towardsdatascience.com/using-pix2pix-to-create-snapchat-lenses-e9520f17bad1?source=collection_archive---------12-----------------------

我们都喜欢 SnapChat 镜头/滤镜,但有没有想过如何自己制作?

是的,我知道副标题来自我的上一篇文章,在那里我展示了如何使用 dlib 和 openCV 使 SnapChat 像 live filters 一样。但今天我想展示我们如何使用名为 pix2pix 的深度学习网络来创建相同的过滤器。这种方法有助于从以前的方法中消除手动特征工程步骤,并且仅通过神经网络的一次推理就可以直接输出目标图像。那么,我们开始吧。

Demo

pix2pix 是什么?

它发表在论文用条件对抗网络进行图像到图像的翻译(俗称 pix2pix)。

名称“pix2pix”来自于网络被训练成从输入像素映射到输出像素,其中输出是输入的某种转换。你可以在下图中看到一些例子,

Source Paper

pix2pix 真正吸引人的地方在于它是一种通用的图像到图像的转换。它不是为上面的每个任务设计定制的网络,而是处理所有任务的同一模型——只是在每个任务的不同数据集上进行训练。Pix2pix 可以用更少的训练图像和更少的训练时间产生有效的结果。给定一个只有 400 个(外观,图像)对的训练集,并且在单个 Pascal Titan X GPU 上进行不到两个小时的训练,pix2pix 可以做到这一点:

Source Paper

pix2pix 网络如何工作?

pix2pix 网络使用 2 个网络进行训练。

  1. 发电机
  2. 鉴别器

这里,生成器将尝试从输入训练数据生成输出图像,鉴别器将尝试识别输出是假还是真。因此,两个网络都将努力提高精度,最终形成一个真正优秀的发电机。所以,你可以把网络的基本结构想象成编码器-解码器。

例如,生成器被输入一个实际的图像(输入),我们想把它“翻译”成另一个结构相似的图像(实际输出)。我们的生成器现在产生假输出,我们希望它与真实输出无法区分。因此,我们简单地收集大量“真实事物”的例子,并要求网络生成无法与它们区分的图像。

方法

今天,我们将使用上述模型来创建 SnapChat 过滤器。我将使用下面的图像来显示结果。所有的图像都是 256x256 因为我是在同样的尺寸上训练的(是的,我没有足够的 GPU 能力来训练高清)

现在,让我们收集训练数据!为此我将使用我以前的 教程代码 我下载了一堆人脸图像数据集,还用谷歌下载了人脸图像。

我将“暴徒生活眼镜”应用到所有的图像上,并将它们并排放置,因为训练数据需要这种格式。我使用下面的 pix2pix 训练库,它使用 tensorflow 来训练和显示结果。

[## affini layer/pix2pix-tensor flow

有条件对抗网络的图像到图像翻译的张量流端口 https://phillipi.github.io/pix2pix/…

github.com](https://github.com/affinelayer/pix2pix-tensorflow)

一旦您完成生成训练数据,它将如下所示:

现在我们开始训练。为了训练,我们应该在 pix2pix-tensorflow 存储库中使用以下命令

python pix2pix.py --mode train --output_dir dir_to_save_checkpoint --max_epochs 200 --input_dir dir_with_training_data --which_direction AtoB

这里,AtoB 定义了训练模型的方向。例如,在上面的图像中,AtoB 表示模型将学习将正常的脸转换为戴眼镜的脸。

您可以在 tensorboard 中的训练数据和图形上看到结果,您可以通过以下命令启动 tensor board:

tensorboard --logdir=dir_to_save_checkpoint

一旦你开始看到你的模型有不错的结果,就停止训练,用评估数据来检查实时表现。如果您认为结果对于实时性能来说不够好,可以从最后一个检查点开始训练。

python pix2pix.py --mode train --output_dir dir_to_save_checkpoint --max_epochs 200 --input_dir dir_with_training_data --which_direction AtoB --checkpoint dir_of_saved_checkpoint

结论

条件对抗网络是许多图像到图像翻译任务的有前途的方法。你需要适当地训练,请使用一个好的 GPU,因为我得到了以下输出,训练较少,没有太多的训练数据差异。

如果你喜欢这篇文章请在 上关注我或者Github或者订阅我的 YouTube 频道**

在本地计算机上使用 pyspark 和 Jupyter

原文:https://towardsdatascience.com/using-pyspark-with-jupyter-on-a-local-computer-edca6ae64bb6?source=collection_archive---------4-----------------------

Image orogin: LinkedIn

在版本 2.0 发布之后,随着许多新特性和改进的 SQL 功能的出现, Apache Spark 成为我所掌握的更强大的工具之一。
因此,我想通过添加从 Jupyter notebook / IPython 控制台使用它的功能来增加这一强大工具的易用性。由于能够添加自定义内核,我创建了一组非常简单的指令(在 Ubuntu / CentOS 上测试)来在本地机器上安装带有 Jupyter 内核的 Spark。

在 Linux 上安装 Spark

本手册在 2.2.0 版上进行了测试,但应该适用于所有版本。我假设您已经安装了 Python 和 Java。为了在您的机器上安装 Spark,请遵循以下步骤:

  1. 从 Apache 网站下载 tar.gz 文件(我假设你是下载到 /opt ):
    wget [https://www.apache.org/dyn/closer.lua/spark/spark-2.2.1/spark-2.2.1-bin-hadoop2.7.tgz](https://www.apache.org/dyn/closer.lua/spark/spark-2.2.1/spark-2.2.1-bin-hadoop2.7.tgz)
  2. 提取文件并创建一个软链接到文件夹:
    tar -xvzf spark-2.2.1-bin-hadoop2.7.tgz ln -s spark-2.2.1-bin-hadoop2.7 spark
  3. 验证 py4j 版本(我们将需要它来连接 Spark 和 Jupyter):
    ls -1 /opt/spark/python/lib/py4j* | awk -F "-" '{print $2}' 我得到的输出是 0.10.4,我们稍后将使用它作为<>
  4. 验证你使用的 Python 路径:
    which python 我得到的输出是/HOME/Nimrod/miniconda/envs/compass/bin/Python 2,我们将此作为<<Python _ HOME>>

完成以上操作后,创建一个内核 json 文件:
mkdir -p ~/.local/share/jupyter/kernels/spark2-local

编辑文件:
vim ~/.local/share/jupyter/kernels/spark2-local/kernel.json ,添加以下内容(不要忘记替换两个占位符):

{
 "display_name": "spark2-local-compass",
 "language": "python",
 "argv": [
  "*<<PYTHON_HOME>>*",
  "-m",
  "IPython.kernel",
  "-f",
  "{connection_file}"
 ],
 "env": {
  "SPARK_HOME": "/opt/spark/",
  "PYTHONPATH": "/home/Nimrod/dev/theGarage/:/opt/spark/python/:/opt/spark/python/lib/py4j-*<<PY4J_VERSION>>*-src.zip",
  "PYTHONSTARTUP": "/opt/spark/python/pyspark/shell.py",
  "PYSPARK_SUBMIT_ARGS": "--master local[*] --driver-memory 3g --executor-memory 2g pyspark-shell",
  "PYSPARK_PYTHON": "*<<PYTHON_HOME>>*"
 }
}

现在,您应该能够观察到在jupyter kernelspec list中列出的新内核,或者在 jupyter UI 中的新笔记本类型下。

Example of The new kernel in the Jupyter UI

上面提到的当前问题是,使用--master local[*]参数是将 Derby 作为本地 DB 使用,这导致无法在同一个目录下打开多个笔记本。

对于大多数用户来说,论文并不是一个真正的大问题,但是自从我们开始使用数据科学 Cookiecutter 以来,文件系统的逻辑结构将所有笔记本放在同一个目录下。每当我们想要在多台笔记本电脑上同时工作时,这会导致一个问题。

我花了很长时间寻找解决方案,最终在很长时间后,Amit Wolfenfeld 很快找到了解决方案。第一步是安装 postgresql 并确保其运行!

为了让 pySpark 使用 postgresql,我们需要 JDBC 驱动程序,从这里的下载它们并保存到 /opt/spark/jars/中。

接下来,将用户更改为 postgres ( sudo su postgres)并运行psql :
CREATE USER hive; ALTER ROLE hive WITH PASSWORD 'mypassword'; CREATE DATABASE hive_metastore; GRANT ALL PRIVILEGES ON DATABASE hive_metastore TO hive; \q

运行该命令后,确保重启 postgreql 服务。最后一步是在 Spark 的 config 目录下创建一个文件(假设您遵循了我上面建议的路径,命令应该是:vim /opt/spark/conf/hive-site.xml

将以下内容添加到文件中:

<configuration>
<property>
  <name>javax.jdo.option.ConnectionURL</name>
  <value>jdbc:postgresql://localhost:5432/hive_metastore</value>
</property><property>
  <name>javax.jdo.option.ConnectionDriverName</name>
  <value>org.postgresql.Driver</value>
</property><property>
<name>javax.jdo.option.ConnectionUserName</name>
  <value>hive</value>
</property><property>
  <name>javax.jdo.option.ConnectionPassword</name>
  <value>mypassword</value>
</property></configuration>

就是这样!现在,您可以开始尽可能多的 pyspark 笔记本。

在 Power BI 中使用 Python

原文:https://towardsdatascience.com/using-python-in-power-bi-ee95a6b71443?source=collection_archive---------3-----------------------

自【2019 年 4 月 Python 集成已经在 Power BI 中普遍可用。就像 R 支持一样,现在您可以使用 Python 来导入数据、数据转换和数据可视化。在本文中,我们将一步一步地准备 Python 环境,在 Power BI 中启用 Python,导入数据并将聚类应用于数据,并使用 Python 在 Power BI 中创建自定义的可视化效果。复制该示例所需的所有材料都可以在 GitHub 中找到。本文假设您有一个工作的 Python 环境,并且安装了 Power BI。

在 Python 中创建数据导入脚本

我们将使用的数据集是波士顿住房数据集,可在 scikit-learn 中获得。数据集最常用于回归示例,但我们将采用不同的方法,并将其用于聚类。我们将使用主成分分析来降低维度,以便在二维空间中可视化数据。在此之后,我们将应用 k 均值聚类来尝试识别数据中的任何同质组。

由于本文的主要重点是展示如何在 Power BI 中使用 Python,所以我不会详细介绍创建导入代码的步骤。数据准备阶段可以作为 Jupyter 笔记本提供给那些有兴趣了解它是如何创建的人。我建议创建您将要使用的代码的独立脚本,以便在 Power BI 中使用它之前测试和调试任何问题。Power BI 提供的错误消息并不总是那么有用。

在 Power BI 中启用 Python

使用所需的库设置 Python 虚拟环境

有几种方法可以管理您的 Python(虚拟)环境。除了virtualenvpipenv你也可以使用conda分布。

在这个例子中,我使用 pipenv 来管理 Power BI 将使用的 Python 环境。为了开始,打开一个Command PromptPower Shell控制台,导航到您想要用作 Python 代码工作目录的文件夹。如果您正在使用我的 GitHub 库,请转到您克隆/下载示例代码的位置。我们将运行以下命令来创建 Python 环境并安装所需的库。

pipenv install numpy pandas matplotlib seaborn scikit-learn

如果你用的是我从 GitHub 下载的代码,运行pipenv install就足够了,因为它会自动从现有的Pipfile安装所需的库。

最后,我们希望检查这个虚拟环境的实际 Python 路径,因为我们需要引用 Power BI 中的路径。

pipenv --venv

我的虚拟环境的位置是C:\Users\tomra\.virtualenvs\python_and_powerbi-0r4DNLn9,所以我把路径复制到剪贴板。

注意:您可以使用conda来管理 Power BI 的虚拟环境。如果你和我使用过类似的 conda 安装/配置,conda 环境安装在 Windows %userprofile%\AppData的一个系统文件夹中。默认情况下,您不能从 Power BI 导航到该文件夹来选择您的 Python 主目录。解决方法是在 Windows 资源管理器中显示隐藏文件。请注意,在常规的 Windows 使用中,不要意外删除任何系统文件。另一种选择是将 conda 环境放在非系统文件夹中。

配置 Power BI 以使用 Python

启动电源 BI 并转到Options处,您应该会看到左侧的Python scripting部分。点击该按钮打开Python script options。默认情况下,Power BI 列出了能够在系统中检测到的 Python 环境。我们需要更改这些设置,因为我们为 Power BI 创建了单独的虚拟环境。从Detected Python home directories中选择Other选项。将 Python 主目录设置为虚拟环境所在路径中的Scripts文件夹。我的情况是C:\Users\tomra\.virtualenvs\python_and_powerbi-0r4DNLn9\Scripts

现在我们已经准备好在 Power BI 中使用 Python 代码,所以准备好吧!

功率 BI

使用 Python 脚本导入数据

我们转到功能区中的Home选项卡,单击Get data并选择More选项开始我们的数据导入。转到Other面板,在那里你会找到Python script选项。选择并点击Connect。将打开一个 Python 脚本对话框,您可以在其中添加自己的代码。将以下代码复制并粘贴到Script文本区,然后点击OK

import pandas as pd
import numpy as np
from sklearn.datasets import load_boston
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.cluster import KMeans# utilize the sklearn.datasets package to load the Boston Housing dataset
boston = load_boston()# scale the data to same value range first since PCA
# is sensitive to the scaling of data
sc = StandardScaler()
X = sc.fit_transform(boston.data)# create PCA with n_components=2 to allow visualization in 2 dimensions
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X)# divide data into 5 clusters (refer to .ipynb for motivation)
kmeans = KMeans(n_clusters=5, init='k-means++', max_iter=300, n_init=10)
y_kmeans = kmeans.fit_predict(X_pca)# create pandas dataframe of the housing data for Power BI
columns = np.append(boston.feature_names, ['MEDV', 'PC1', 'PC2', 'CLUSTER'])
data = np.concatenate((boston.data,
                       boston.target.reshape(-1, 1),
                       X_pca,
                       y_kmeans.reshape(-1, 1)),
                      axis=1)
df_housing = pd.DataFrame(data=data, columns=columns)
# we need to convert all columns as string because of different
# decimal separator in Python (.) and Finnish locale (,) that Power BI uses.
# comment out below line if Power BI uses dot as a decimal separator.
df_housing = df_housing.astype('str')# create pandas dataframe of the pca data for Power BI
columns = np.append(boston.feature_names, ['VARRATIO'])
data = np.concatenate((pca.components_,
                       pca.explained_variance_ratio_.reshape(-1, 1)),
                      axis=1)
df_pca = pd.DataFrame(data=data, columns=columns, index=['PC1', 'PC2'])
df_pca = df_pca.astype('str')

在下一个窗口中,我们可以选择要导入的数据集。选择df_housingdf_pca数据集,并点击Load。接下来,我们将对导入数据进行最后的调整。点击功能区中的Edit Queries

由于 Python 和 Power BI 中的区域设置可能存在差异,我选择在 Python 脚本中将所有列保存为字符串。需要设置正确的数据类型,根据您的地区/设置,我们可能需要采取不同的路线。目标是将每一列转换成数字。

带小数点的幂 BI

虽然我还没有测试过,但是您应该能够移除Changed Type步骤,选择所有列,并从功能区的Transform选项卡中选择 Power BI Detect Data Type,以便获得正确的数据类型。对两个数据集重复上述步骤。

另一个选项是修改导入脚本,删除/注释我们将数据类型设置为字符串df_housing = df_housing.astype('str')df_pca = df_pca.astype('str')的行。Power BI 应该在导入过程中正确识别数据类型。

带十进制逗号的幂 BI

我们需要替换点(.)改为逗号(,),以便设置正确的数据类型。选择所有列,并从功能区的Transform选项卡中单击Replace Values。用逗号替换点,点击OK

之后,点击Detect Data Type,让 Power BI 检测正确的数据类型。对两个数据集重复这些步骤。

最后一步是将一个Index Column添加到df_housing数据集。这可以通过功能区中的Add Column选项卡来完成。完成后,转到Home选项卡并点击Close & Apply

使用 Python 创建自定义可视化

我们回到Reports视图,开始我们的可视化工作。计划是使用主成分作为轴在图表上可视化聚类。散点图是这种可视化的一个很好的替代方案。点击Scatter chart将其添加到页面中。按照以下方式将df_housing列拖动到可视化效果窗格:

  • PC1拖至X Axis
  • PC2拖至Y Axis处。
  • CLUSTER拖到Legend上,以可视化集群的分组方式。
  • Index拖至Details,因为这将删除图表中的聚合。

最终结果应该类似于下图。由于 k-means 聚类中初始质心的随机选择,您可能会有不同的聚类顺序(着色)。

接下来,我们将想象每个特征如何影响每个主要成分。该信息可在df_pca数据集中获得。我们将通过热图展示这些信息。Seaborn Python 库提供了一种创建热图的简单方法,因此我们将向页面添加一个Python visual。Power BI 可能会警告您脚本视觉效果,请单击Enable继续。每个特征需要单独拖到Data fields区域。从数据集中拖动除VARRATIO之外的每一列。将下面的代码片段复制到代码区,点击Run script

import matplotlib.pyplot as plt
import seaborn as snsdataset.index = ['PC1', 'PC2']
plt.figure(figsize=(8, 2))
plt.xticks(rotation=45)
data = dataset.loc['PC1', :].to_frame().sort_values(by='PC1').transpose()
sns.heatmap(data,
            cmap='plasma',
            square=True,
            annot=True,
            cbar=False,
            yticklabels='')
plt.show()

您现在应该会看到类似下图的热图。根据您的屏幕分辨率,您可能需要隐藏脚本窗格才能看到视觉效果。

重复相同的步骤为第二个主成分创建热图,但使用下面的代码片段来使用来自第二个主成分的数据,并制作可放置在散点图左侧的垂直可视化效果。

import matplotlib.pyplot as plt
import seaborn as snsdataset.index = ['PC1', 'PC2']
plt.figure(figsize=(2, 8))
data = dataset.loc['PC2', :].to_frame().sort_values(by='PC2', ascending=False)
sns.heatmap(data,
            cmap='plasma',
            square=True,
            annot=True,
            cbar=False,
            xticklabels='')
plt.show()

我建议在其他工具中测试你的 Python 可视化,例如使用 Jupyter Notebook,特别是在可视化很复杂或者你想微调可视化的所有小细节的情况下。还值得考虑在 Python 可视化中使用与 Power BI 报告中相同的字体,以获得统一的外观和感觉。这很容易用 Matplotlib 和它的兄弟实现。

注意:有些 python 包只生成 HTML,为了克服这个限制,绘图被保存为图像,然后使用 matplotlib 显示。要写入 png 文件,你需要安装 chrome 驱动程序,例如将 exe 文件放在C:\chromedriver中。一旦你这样做了,你应该把这个文件夹放在PATH环境变量中。在我们的情况下,不需要这一步。

我们现在已经可视化了关于两个主成分的已识别数据簇,这两个主成分一起解释了数据中的大部分差异。热点图显示了哪些要素以积极或消极的方式影响主成分值的每个主成分。让我们做一些最后的润色,使报告看起来更好一点:

  • 将其中一种灰色聚类颜色更改为紫色。
  • 为数据添加标题和引用。
  • 添加显示每个分类的*均中值价格的可视化效果。
  • 添加解释功能的文本框。
  • 添加一个可视化,说明每个主成分解释的差异。

这就是我的版本最后的样子。

最重要的是,我们只需再创建一个报告,在该报告中,我们将仔细查看所选要素、中值住房价值(目标)和已识别的聚类之间的关系。通过观察可视化,我们可以得出结论,仅第一主成分就解释了数据中几乎一半的差异。此外,我们可以从图表中看到,较低的主成分值*均转化为较高的中值房价。Distance功能对小幅降低 PC1 值的影响最大,因此让我们更仔细地看看它在不同集群中的表现。我们创建了一个新页面,并进行了以下更改:

  • 添加描述性标题。
  • 添加一个Scatter chart,其中X Axis值为DIS列,Y Axis值为MEDV,并且LegendDetails字段的设置与之前的散点图类似。
  • 右键单击DIS列,选择New group,创建尺寸为 1 的箱子。
  • 添加一个Stacked column chart,通过使用DIS新创建的装箱列显示距离值的分布。按轴而不是计数对图表进行升序排序。

这就是我对这份报告的看法。

摘要

在本文中,我们建立了一个 Python 虚拟环境,并安装了数据转换和可视化所需的库。如果您想利用一些 Python 库,可以在环境中安装额外的库。接下来,我们设置 Power BI 来利用 Python 脚本。这是一次性设置,这意味着您不必在下一个报告中重复这些相同的步骤。最后,我们利用 Python 脚本来导入数据和创建定制的视觉效果。还可以使用 Python 脚本对已经导入 Power BI 的数据集进行数据清理和转换。相对于在 Power BI 之外准备数据并导入可用于可视化的数据集,在哪些用例中利用 Python 脚本更有意义还有待观察。Python 视觉效果的表现也可以更好。但是请记住,这仍然是一个预览功能,它看起来非常有前途!您认为在 Power BI 中使用 Python 有哪些用例?加入讨论,分享你的想法。

用 Python、Pandas 和 Plotly 生成 NBA 投篮图表

原文:https://towardsdatascience.com/using-python-pandas-and-plotly-to-generate-nba-shot-charts-e28f873a99cb?source=collection_archive---------4-----------------------

自从我在阅读 Kirk gold berry court vision 关于 Grantland.com 的一篇文章时偶然发现 NBA 投篮图表可视化以来,我就对体育数据可视化着迷,并对它们如何能够增强球队和球员的决策产生兴趣。因此,当我最*开始学习数据科学时,我很自然地知道,我的第一个兼职项目之一将是试图重建一个 NBA 球员的投篮图表。

收集数据

我的第一步是收集每个镜头的位置数据。随着体育分析发展到几乎每个球队都有专门的分析部门,职业联盟也纷纷效仿,加强了他们的统计部门。NBA 在其网站上提供了一系列详细的统计数据,这些数据是使用安装在每个赛场的第二光谱摄像机收集的,这些摄像机跟踪球员和球的实时运动。从第二光谱收集的数据示例包括速度、行驶距离、油漆接触等。

不幸的是,NBA 不允许在其统计页面上访问 API,所以我不得不深入挖掘以找到我想要的东西——每个球员的详细投篮数据。在每个球员的击球细节页面上,如下所示,你可以查看各种击球情节,并筛选出每个击球的基本细节的电子表格,只需点击播放按钮,就可以看到每个击球的视频。

Kristaps Porzingis Shot Detail Page — https://stats.nba.com/events/?flag=3&CFID=33&CFPARAMS=2017-18&PlayerID=204001&ContextMeasure=FGA&Season=2017-18&section=player&sct=hex

尽管网页上有大量的数据,但这些数据的结构无法让我对其进行正确的分析,我也无法获得我所寻求的全部数据。然而,使用谷歌 Chrome 开发工具,特别是 XHR (XMLHttpRequest),我能够获得一个 json 文件,可以使用 Pandas 轻松读取和转换。

Chrome XHR tab and resulting json linked by url

虽然这正是我在寻找的数据,但我渴望有一种方法来收集任何玩家或一组玩家的数据,而不必重复这些繁琐的步骤。在注意到 725 个字符的 url 字符串只有一个条件值——player _ ID——需要更改才能调出其他人的击球数据后,我编写了一个 python 脚本来收集给定了 nba.com ID 的任何球员的数据。使用 Requests python 库,我能够获取 json 数据,而不必实际访问网站。

Code to grab json data from stats.nba.com and transform into Pandas DataFrame

清理数据

一个不可思议的 python 库中的 Pandas,除了其他特性之外,它还允许我将 json 转换成 DataFrame,并清理数据,只显示我想要的值和列。Pandas 不费吹灰之力就将难看的 json 结构转换成了一种干净、易读的格式。Pandas 还提供了一些简洁的功能,比如。describe()方法,该方法自动计算并输出相关统计数据的样本,例如所有数值列的*均值、中值和标准偏差。如下图所示,这一行代码让我立即了解了纽约尼克斯队的明星前锋克里斯塔普斯·波尔津吉斯的投篮选择。例如,波尔津吉斯的*均投篮距离是 14.28 英尺,他的典型投篮距离篮筐左侧非常*。

Sampling of data from Pandas DataFrame

.describe() method for Kristaps Porzingis’ DataFrame

策划拍摄

现在,我已经以正确的格式获得了我需要的所有数据,我可以使用 Plotly(一个图表和可视化库)绘制每个镜头了。首先,我用 Savvas Tjortjoglou 的惊人的模板画出一个精确尺寸的球场轮廓。接下来,我将所有的镜头分为两类——成功和失败——然后我可以用不同的颜色绘制出来。使用 Plotly graph objects 模块,我能够将所有的得分和失误绘制为球场轮廓上的散点图,将 X 和 Y 值分别设置为 X_LOC 和 Y_LOC,这表示每次击球尝试的坐标。

Code for creating scatter plot for all shots.

从那里,我需要做的就是运行我的程序,就像变魔术一样,每一个镜头都按照设计的那样被绘制出来。

结论

对我来说,这是一个非常有趣和充实的兼职项目。它将我对体育的热情与我开始编程后一个月左右学到的各种技能结合了起来。在未来,我想让我的拍摄情节互动,并润色它们,使它们在视觉上更具吸引力,并增强可读性。我还打算引入一些变化,比如用代表每个投篮位置的频率和效率的六边形代替重叠的单个投篮数据点,或者增加一个与联盟*均水*的比较。

用 Python 给自己找了个出租房

原文:https://towardsdatascience.com/using-python-to-find-myself-a-rental-home-a0b1bf6f02e?source=collection_archive---------8-----------------------

通过网络抓取、网络地图和数据可视化缩小我对房屋的搜索范围

HDB flats in Singapore

“你好,世界!”

随着我在欧洲的冬季交流项目接*尾声,我意识到了现实:我需要在新加坡找到一个新的公寓。

这个简单!我所要做的就是登录这些网站,输入一些搜索参数来找到我的理想公寓。以前租过房子,这个过程相当熟悉和舒适。然而,在快速浏览 Python 一段时间后,我认为这将是创建一个更加高效的搜索过程的好方法,并通过处理一个真实世界的问题来测试我的技能。

在我们深入研究这个项目之前,先花些时间浏览一下 iProperty 的robot . txt文件。虽然他们确实允许机器人抓取他们的网站,但保持谨慎和不滥用赋予我们的这一特权总是很重要的。

语境

现在,当我找到一个出租公寓时,我寻找什么?简单地说,我的最优出租公寓可以描述为这两个变量的函数:

  • 靠*捷运(地铁)站,方便随时随地通勤。
  • 价格合理(因为我是一个破产的学生)。

通常,我会采取以下步骤来找到最佳公寓:

  1. 在房产网站上搜索,找到一个价格合适的单位。
  2. 在谷歌地图上查找地址,看看它是否位于捷运站附*。
  3. 如果位置是我想要的,太好了!不管怎样,我会把它记在某个地方。
  4. 如果位置不是我想要的,那么我会再次重复步骤 1 到 3。

如果重复 3 到 4 次,上面的步骤看起来很容易。然而,对于任何潜在的租户来说,我们知道这种情况很少发生。我们通常必须运行许多迭代来创建足够大的单元池,以便我们进行比较并做出决定。此外,在上面提到的过程之后,接下来是与代理人交谈的过程,根据我的喜好找到单位都是循规蹈矩的,等等。如果在任何时间点出了问题,那么将再次回到步骤 1 到 4。

必须有一种方法,我可以在一个工作空间中编辑所有我想要的搜索结果,只需点击一个按钮就可以进行更有效的比较。

我已经下定决心要在一个叫 Ang Mo Kio 的地方找到一套三居室公寓,这个地方位于新加坡的 20 区。至于网站,我将主要关注 iProperty 。记住这些参数,因为它们会在这篇文章中反复出现:地区= 20,卧室= 3。

考虑到这一点,我想到了可以帮助我做出这样一个决定的视觉辅助形式。它们是:

  • 一个交互式地图,它可以显示我在一个地区的所有出租屋的位置。
  • 描绘该地区价格分布的图表,这样我就知道会发生什么。

让我用 Python 来做这件事吧!这个项目回购的链接可以在这里找到。现在让我们开始吧。

第 1 部分:数据源

我需要的数据可以从房地产网站上获得。问题是,这不是我习惯的通常的 excel 或 csv 文件。数据以 HTML 的形式出现,看起来有点不同…

为此,我可以使用 Python 漂亮的 Soup 4 包。它允许我从网站上删除 HTML 数据。不过在刮之前,需要增加一些手续:

我需要什么信息?也许是公寓的价格、地址和大小。让我从抓取地址的数据开始。我不是 HTML 专家,但我知道一些元素类型中包含各种形式的信息。图 1 将演示这一点。通过检查源代码,我们可以看到,对于这个特定的单元,关于它的地址的信息包含在这个元素< a >中,在类‘fsKEtj’的 main < div >下。

Figure 1: Inspecting the source code

提取信息并将其存储在空的“地址”列表中的代码如下:

Figure 2

地址输出?

Figure 3: First five rows of the addresses scraped from the website

太好了!现在已经完成了,我们只需重复同样的过程来查找包含价格大小信息的元素,并通过调整图 2 中的代码来提取这些信息。

这是 iProperty 搜索页面的第一页,显示了 10 套公寓。我需要更多的信息来进行适当的比较。在这篇文章中,我会选择从 5 页搜索结果中提取数据,给自己一个可供选择的公寓池。如何做到这一点?幸运的是,iProperty 的 URL 相当简单:

[https://www.iproperty.com.sg/rent/district-20/hdb/?bedroom=3&page=1](https://www.iproperty.com.sg/rent/district-20/hdb/?bedroom=3&page=1)

如您所见,它只包含三个部分:地区、卧室数量和页码。这让生活变得容易多了,因为我现在可以循环浏览第 1 页到第 5 页。在每个循环之间,我还植入了一个 time.sleep 函数,只是为了让我的网页抓取器表现得有点像人类,并防止我自己被阻止访问网站。

有了这个,我现在有了一个合理大小的公寓池,有三个变量:价格、地址和大小。在使用 pandas 将它们组合成一个数据框之后(还要注意,没有错误显示行数不同,这意味着显示的每个单元都有地址、价格和大小),我现在需要清理数据。让我们看一下数据集的前五行。

Figure 4: First five rows of the full data set

在球棒的右边,你可以看到数据的各个方面需要调整。首先,我希望价格尺寸列是数字。因此,SGD、build-up 和必须删除。此外,仔细检查 size 列,有几个单位用“sq”表示。m 而不是 sq。英尺。。这些也需要清洗。所有采取的数据清理步骤都可以在我的项目报告中的脚本中看到。请看一下图 5 中清理过的数据集!

Figure 5: The cleaned data set

快到了!注意到单元有什么问题吗?似乎有一个“流氓”公寓(指数 1),面积很小(100 *方英尺),但非常昂贵(2400 美元/月)。作为一项预防措施,我检查了移除这些单元。

现在我有了 iProperty 上列出的所有公寓的完整数据集,参数区= 20,卧室= 3,让我们开始创建一个交互式地图。

第 2 部分:创建交互式地图

诚然,这部分是项目中最具挑战性的方面。为了在地图上绘制我的数据集中的公寓,我需要上述公寓的坐标。在这里,我将使用 Geopy 包根据我的数据集中的地址检索坐标,并使用 follow 利用这些坐标来创建地图及其交互功能。

首先,我们遍历数据集中包含的所有地址,并提取出每个公寓的纬度和经度。然后,这两个变量将被添加到主数据集中。

Figure 6

Figure 7: Full data set with new latitude and longitude columns

在获得每个公寓的坐标后,我们现在准备将它们全部标绘在新加坡地图上!让我们创建基本地图:

location = [1.3521,103.8198]
sgmap = folium.Map(location,zoom_start = 12)

Figure 8: Base map of Singapore

现在该添加标记了!对于我的记号笔,我包含了两个可以帮助我更有效地整合信息的特性。

  • 每个标记都根据其价格进行了颜色编码。所有租赁价格都是有序的,并计算它们各自的百分位数。绿色标记表示公寓的租金在 0-30%之间,橙色标记表示 30-70%之间,红色标记表示 70%以上的租金价格。
  • 每个标记处都会弹出一个窗口,显示公寓的地址和价格。

最终产品看起来像这样:

Figure 9: Interactive map with all rental units in the Ang Mo Kio area

从地图上,我可以看到大约有 5 个单位靠*捷运站。有两个相对昂贵的单位(红色),两个价格适中的单位(橙色)和一个相对便宜的单位(绿色)。如果我点击这些单位的标记,将会出现一个如地图所示的弹出窗口。

第 3 部分:显示租金价格分布

这部分相当简单,因为我有我们需要的所有数据。我现在需要做的就是使用 Matplotlib 和 plot charts 来帮助我更好地理解这个地区的价格分布。我更喜欢使用箱线图:

箱线图显示了价格的分布和*均价格。它让我推断出,在 Ang Mo Kio 的大多数三居室单元每月花费大约 2300 美元到 2600 美元。

结论和未来的改进

这个项目有许多方面可以改进。我将来非常想探索的一个领域是在展示公寓时加入一个排名系统。例如,可以使用诸如到 MRT(地铁)的距离、到超市的距离、到学校的距离等因素来给特定公寓分配分数,并且具有较高分数的公寓将更有利地显示在地图上。现在,我的空闲时间到了,我不得不满足于现有的模式。

另一个方面是,所有这些都是在笔记本 IDE 上完成的。如果我想让其他人使用这个工具,他们首先需要访问一个笔记本环境。在未来,我一定会把这变成一个基于网络的应用程序!

通过这个项目,我创造了一个简单的工具,可以帮助我更有效地找到未来的家。摆弄 Python 和它的库是一次愉快的旅程,我一定会回来学习更多!

参考

https://towards data science . com/master-python-through-building-real-world-applications-part-2-60d 707955 aa3—一份精彩的使用 real 的指南

使用 Python 的多重处理模块高效地评估一组算法。

原文:https://towardsdatascience.com/using-pythons-multiprocessing-module-to-evaluate-a-set-of-algorithms-efficiently-1412d29ff849?source=collection_archive---------9-----------------------

Power.

有时,在看到数据集后,您的第一直觉是想到可能对其有效的多种算法。然后,您自然会想尝试所有这些方法,看看它们在基线结果上的表现如何。但是有一个因素总是让你重新考虑这个决定。时间的因素。那么,我们如何绕过它呢?让我们试试多重处理。

进程是计算机中的一个工作单元。就 python 而言,您可以将流程视为程序的实例(例如 Jupyter notebook、Python 解释器、独立脚本)。您的操作系统能够同时运行多个进程,您可以将进程映射到系统中的内核数量。如果您有多个内核(这种情况很常见),您可以在不同的内核上同时并行运行多个进程。

我们面临的问题是在同一个数据集上评估多种算法,获取它们的指标,并查看哪种算法的性能最好。这非常适合在分布式内核上轻松运行。这是因为它们彼此独立。也就是说,随机森林训练和测试运行不关心 SVM 训练测试评估的中间结果。因此,我们可以在不同的内核上同时运行它们,并更快地获得结果,而不是在一个内核上逐个运行它们。

不幸的是,python 代码默认作为单个进程在单个内核上运行。幸运的是,使用内置的多处理模块可以很容易地使代码并行运行,并利用所有的 CPU 内核。现在让我们开始研究代码,看看它是如何工作的。

Use them all! (Image Source:Vindictus)

假设我们已经将我们的训练和测试数据分开,并准备好像在常规机器学习管道中一样使用。我们还有一个函数 find_rmse(reg ),它接受 sklearn 的回归算法函数,并使用它来训练,然后在数据集上进行测试,并提供我们获得的*均均方根误差。该问题是一个监督回归问题,我们希望在同一数据集上看到四种算法的结果,即随机森林、nuSVM、岭回归和 ElasticNet。

首先,我们将从多处理模块中导入池函数。Pool 对象提供了一种方便的方法,可以跨多个输入值并行执行一个函数,并将输入数据分布到多个进程中。它需要一个参数,这个参数等于您想要生成的工作进程的数量。为了最大限度地利用资源,您可以将其保持为 CPU 中的核心数。但是,请记住,因为所有这些都将主要由这个 python 程序使用,所以在程序执行时,您可能无法在系统上执行另一个处理器繁重的工作。

然后,让我们创建一个我们想要比较结果的回归变量列表。我们的工作非常方便,因为 python 可以将函数作为函数的参数。

现在,让我们将使用回归器训练模型并对其进行测试后计算 rmse 的函数映射到我们的回归器列表。这将把这些回归函数列表并行传递给我们的父函数 find_rmse(reg )!

最后,让我们埋葬我们的池对象的遗骸。

瞧啊。我们只是大大减少了比较这么多回归算法所需的时间。如果你大规模地这样做,这是我目前正在做的研究项目的一部分,这是我们正在谈论的几天和几个月的差异。我的系统有 64 个 CPU 内核,使用它们可以帮助我以指数级的速度实现这一目标。但是如果不使用这种技术,这 64 个内核将会被浪费掉。即使您的个人计算机通常也有 4 个以上的内核,因此您也可以使用这种技术来大幅提高速度。祝您愉快地并行学习!

用 R 将代码点打开的 CSV 文件合并成一个大文件

原文:https://towardsdatascience.com/using-r-to-merge-the-csv-files-in-code-point-open-into-one-massive-file-933b1808106?source=collection_archive---------0-----------------------

Map courtesy Trafford Innovation and Intelligence Lab

如果你有一个有邮政编码的数据集,例如客户数据或资产信息,你可以做的最有用的事情之一就是把数据放到地图上。为此,需要对每条记录进行地理参考。英国国家测绘局有一个开放的数据集,叫做 Code-Point Open ,你可以从他们的开放数据网站上获得。该数据集允许您在自己的数据中查找邮政编码,以找到它们的坐标,这样您就可以将它们放在地图上。

英国国家测绘局的数据集包含在一个 zip 文件中,当您提取它时,它由 120 个 csv 文件组成。这可能是一个棘手的问题,所以我将展示如何使用 R(实际上是 R Studio)将所有这些 csv 文件合并成一个文件。还有其他方法可以做到这一点——手动(😱)、编写批处理文件、MS Visual Basic 等,但这是一种优雅而快速的完成方式。

首先,打开 R Studio,创建一个新项目。在项目文件夹中新建一个文件夹,命名为‘temp’。你现在需要从英国测绘局复制 120 个 csv 文件到这个文件夹。

之后,在 R Studio 控制台中,我们需要将这个项目的工作目录设置为 temp 文件夹:

setwd(‘temp/’)

然后,我们需要将该文件夹中所有内容的文件名传递到一个变量中:

filenames <- list.files(full.names=TRUE)

这将遍历该文件夹中的文件,挑选出文件名,并将它们传递到变量‘filenames’中。我们现在将使用这些文件名来遍历文件,从每个 csv 文件中提取数据,并将其合并到一个列表中(注意,这将需要几秒钟的时间来完成):

All <- lapply(filenames,function(i){
read.csv(i, header=FALSE, skip=4)
})

这会将数据推入变量“All”中。如果我们查看“环境”选项卡,我们可以看到这是一个包含 120 个元素的“大列表”,大小为 156Mb。

为了使用数据集,或者在 R 中进行匹配,或者保存为它自己的 csv 文件,我们需要将它转换为 dataframe。为此,我们可以运行以下命令:

df <- do.call(rbind.data.frame, All)

为了检查数据帧的内容,我们可以使用 head 函数显示前几行数据:

head(df)

这给了我们这个:

这看起来不错(尽管将列重命名为更有意义的名称可能是个好习惯)。V1 有邮政编码,V3 和 V4 是英国坐标系参考。最后,要将这个大的邮政编码列表保存为一个新的 csv 文件,我们可以使用 write.csv:

write.csv(df,”all_postcodes.csv”, row.names=FALSE)

这将在 R Studio 项目文件夹的 temp 文件夹中创建一个新的(大量的)csv 文件。从这里,您可以将邮政编码文件与您自己的数据合并,以便在 R 中进行地理参考,或者您可以在 Excel 中进行 vlookups。

请注意,本练习之所以有效,是因为每个 csv 文件在数据列数方面具有相同的形状。对于不同的数据集,这种过程变得更加复杂。

下面是一次性完成的所有代码:

setwd(‘temp/’)
filenames <- list.files(full.names=TRUE)
All <- lapply(filenames,function(i){
read.csv(i, header=FALSE, skip=4)
})
df <- do.call(rbind.data.frame, All)
write.csv(df,”all_postcodes.csv”, row.names=FALSE)

用递归神经网络进行噪声中的轨迹检测

原文:https://towardsdatascience.com/using-recurrent-neural-networks-for-track-detection-in-noise-5e6395c8afae?source=collection_archive---------9-----------------------

动机

通过观察声纳或雷达屏幕,人类可以很容易地探测到轨迹,这些轨迹是由通常距离很远且只能作为点来观察的物体形成的。即使在有噪声的图像中,也可以在视觉上检测到相应的点图案。此外,当轨迹在噪音中不断出现和消失时,训练有素的操作员可以快速判断不相关的轨迹本身是否形成了可能与同一物体相关的轨迹模式。

需要上述观察来做出关于物体存在或不存在的决定。例如,如果物体与噪声相比非常亮,那么可以通过观察(或检测)单个亮点来做出这样的决定。然而,如果与噪声相关的点表现出与感兴趣的对象相当的亮度,我们最终会得到许多错误的检测。作为对象检测的下一步,我们假设噪声是均匀的,因此与噪声相关的点不会形成轨迹。然而,如果噪声分布不均匀,与噪声相关的点也会形成短轨迹。因此,我们以错误的轨迹检测结束。当由于噪声,感兴趣对象的轨迹很短,使得它们出现和消失,表现出噪声轨迹间歇性时,就会出现这种情况。在这种情况下,人类观察者会寻找与单个物体相关的轨迹模式。一旦发现这种轨迹模式,就可以宣布感兴趣的物体的存在。

另一方面,随着噪声水*的增加和要跟踪的对象数量的增加,现有的基于对象运动建模的跟踪算法必须处理指数级增加的计算复杂度。还应该注意,执行各自的计算增加了数据处理功耗,同时需要强大的处理器和增加的存储器。

最*在机器学习(例如深度学习, DL )的各种应用中取得的重大进展已经证明了匹配甚至超过人类能力的结果(例如在下棋或下围棋方面)。在 Raspberry Pi 等小型单板计算机上成功实现训练好的 DL 表明,使用廉价的自主、低功耗机器人解决目标检测、跟踪和定位问题可能是 DL 应用的新方向。

方法

在这项工作中,我将研究二进制(即黑白)图像中轨迹检测的玩具问题。各自的 Python 代码,写为 Jupyter notebook,使用 Keras 框架,可在这里获得。下面,我展示了这段代码的主要模块和计算的输出。

下面显示的问题不是一个小问题,它的成功保证了在这个领域的进一步研究。下面我实现了一种循环神经网络( RNN ),叫做长短期记忆( LSTM )网络。想法是应用可以同时使用空间和时间信息的算法,以便能够捕获在噪声中呈现间歇出现和消失的对象的模式。

在开始具体示例之前,我导入了这项工作所需的所有 Python 模块。

现在我加载 LSTM 训练和测试所需的预先生成的人工数据。注意,我分别使用了 3000 和 300 幅图像进行训练和测试。这些图像被堆叠成 3D 矩阵,每个图像具有 10×30 像素的尺寸。每个图像被标记为噪声( y[i] = 0 )或包含轨迹( y[i]=1 )。

接下来,为了展示数据的结构,我们看几个示例图像。

例子

上图中,左图显示了由黑色矩形标记的典型噪波分布。在右边,三个图像被连接在一起。从左到右,第一个图像对应于左侧显示的噪声,接下来的两个图像显示了一个线性轨迹,看起来像一个由黑色小矩形框组成的楼梯,向下穿过中间和最右侧的图像。

为了 LSTM 处理的目的,在这项工作中,图像按 10 的顺序进行处理。下面,我只展示了前三个,以强调数据的 3D 排列。

利用长短时记忆模型学习检测轨迹

我在带有 Tensorflow 后端的 Keras 框架中使用 LSTM 模型架构。下面,如果“keras_model_load”设置为 True,将使用预训练模型。如果“keras_model_load”设置为 False,则从头开始训练模型。

现在,我们使用经过训练的模型来预测用于训练和测试的输入图像的标签。

为了估计每个图像的一个标签,我们需要对每个图像的 10 个时间步长生成的 10 个标签进行*均。

由于预测输出是实值,使用阈值 0.5,我将输出分为两类:对应于轨道存在的输出( y =1),以及对应于轨道不存在的输出( y =0)。下面的 y 对应于 Y_estim_testY_estim_train

结果

下面显示了训练和测试结果的子集。在每个连接图像的顶部,绘制了*均标签的分布。蓝色和红色分别显示真实和估计的标签。请注意,对于下面显示的训练子集,这两种标签类型完全匹配。

最后,我估计了应用于测试和训练数据的检测概率(Pd)和虚警概率(Pfa)。该指标通常用于接收器操作特性估计。

讨论

查看上面显示的输出,可以看到训练的模型倾向于过度拟合(比较训练的 Pd=0.988 和测试数据的 Pd=0.629)。我对大量测试运行的经验(此处未显示)表明,对于该数据集,过度拟合往往会随着训练数据大小的增加而减少,这是意料之中的。

通过寻找更好的 RNN 结构和微调超参数来提高精度是未来潜在的研究课题之一。

尽管所呈现的数据生成算法简单,但是数据生成模型输出非常类似于活动声纳的真实场景。

在这项工作中分析的情况,在任何给定的时间,仅限于检测一个单一的轨道。轨迹检测是在没有对象运动建模算法的帮助下进行的。后者不需要任何训练(除了一些微调),但在操作上需要更昂贵的计算。

这项研究是基于 LSTM 神经网络的第一步,旨在通过发现和检测属于同一物体的轨迹(或轨迹拼接)模式来提高物体检测的可信度,这些轨迹由于噪声而在声纳或雷达屏幕上出现和消失。

用递归神经网络预测明天的比特币(BTC)价格

原文:https://towardsdatascience.com/using-recurrent-neural-networks-to-predict-bitcoin-btc-prices-c4ff70f9f3e4?source=collection_archive---------5-----------------------

深度学习案例研究

利用 TensorFlow 和 Keras |监督深度学习,使用递归神经网络预测第二天的加密货币价格

如果你正在阅读这篇文章,我确信我们有着相似的兴趣,并且现在/将来会从事相似的行业。那么我们就通过 Linkedin 来连线吧!请不要犹豫发送联系请求!Orhan g . yaln—Linkedin

Photo by Andre Francois on Unsplash

如果你能以某种方式预测明天的比特币(BTC)价格,这不是很棒吗?众所周知,加密货币市场在过去一年经历了巨大的波动。比特币的价值在 2017 年 12 月 16 日达到顶峰,攀升至* 2 万美元,然后在 2018 年初出现了急剧下降。然而不久前,确切地说是一年前,它的价值几乎是现在的一半。因此,如果我们看看每年的 BTC 价格图表,我们可以很容易地看到,价格仍然很高。仅在两年前,BTC 的价值仅为其当前价值的十分之一,这一事实更令人震惊。您可以使用下图亲自探索 BTC 的历史价格:

Historical Bitcoin (BTC) Prices by CoinDesk

关于这种波动背后的确切原因有几个阴谋,这些理论也被用来支持加密价格的预测推理,特别是 BTC。这些主观论点对预测加密货币的未来很有价值。另一方面,我们的方法评估历史数据,从算法交易的角度预测加密货币的价格。我们计划使用数值历史数据来训练一个递归神经网络( RNN )来预测 BTC 价格。

获取历史比特币价格

我们可以使用相当多的资源来获取历史比特币价格数据。虽然其中一些资源允许用户手动下载 CSV 文件,但其他资源提供了一个 API,用户可以将其与自己的代码挂钩。因为当我们使用时间序列数据训练模型时,我们希望它做出最新的预测,所以每当我们运行程序时,我更喜欢使用 API 来获得最新的数字。经过快速搜索,我决定使用 CoinRanking.com 的 API,它提供了我们可以在任何*台上使用的最新硬币价格。

递归神经网络

由于我们使用的是时间序列数据集,使用前馈神经网络是不可行的,因为明天的 BTC 价格与今天的最相关,而不是一个月前的。

递归神经网络(RNN)是一类人工神经网络,其中节点之间的连接沿着序列形成有向图。— 维基百科

RNN 显示时间序列的时间动态行为,它可以使用其内部状态来处理序列。实际上,这可以通过 LSTMs 和 GRUs 层来实现。

这里您可以看到常规的仅前馈神经网络和递归神经网络(RNN)之间的区别:

RNN vs. Regular Nets by Niklas Donges on TowardsDataScience

我们的路线图

为了能够创建一个根据历史 BTC 价格进行训练并预测明天 BTC 价格的程序,我们需要完成如下几个任务:

1-获取、清理和规范化历史 BTC 价格

2 —与 LSTM 共建 RNN

3-训练 RNN 并保存训练好的模型

4 —预测明天的 BTC 价格,并将其“反序列化”

奖励:反序列化 X_Test 预测并创建 Plot.ly 图表

获取、清理和规范化历史 BTC 价格

获取 BTC 数据

正如我上面提到的,我们将使用 CoinRanking.com 的 API 来处理 BTC 数据集,并使用以下代码将其转换为熊猫数据框架:

Obtaining the BTC Prices with CoinRanking API

默认情况下,该函数针对 5 年期 BTC/美元价格进行调整。但是,您可以通过传入不同的参数值来更改这些值。

使用自定义函数清理数据

在获得数据并将其转换为 pandas 数据框架后,我们可以定义自定义函数来清理我们的数据,对神经网络进行标准化,因为这是获得准确结果的必要条件,并应用自定义训练-测试分割。我们创建了一个定制的训练测试分割函数(不是 scikit-learn 的),因为我们需要保持时间序列,以便正确地训练我们的 RNN。我们可以通过下面的代码实现这一点,您可以在下面的代码片段中找到进一步的函数解释:

Defining custom functions for matrix creation, normalizing, and train-test split

定义这些函数后,我们可以用下面的代码调用它们:

Calling the defined functions for data cleaning, preparation, and splitting

与 LSTM 共建 RNN

在准备好我们的数据之后,是时候构建模型了,我们稍后将使用清理和规范化的数据来训练该模型。我们将从导入我们的 Keras 组件开始,并使用以下代码设置一些参数:

Setting the RNN Parameters in Advance

然后,我们将使用以下代码创建具有两个 LSTM 和两个密集层的顺序模型:

Creating a Sequential Model and Filling it with LSTM and Dense Layers

训练 RNN 并保存训练好的模型

现在是时候用清理后的数据训练我们的模型了。您还可以测量训练过程中花费的时间。遵循这些代码:

Training the RNN Model using the Prepared Data

不要忘记保存它:

Saving the Trained Model

我热衷于保存模型并在以后加载它,因为知道您实际上可以保存一个训练好的模型并在下次使用时重新加载它,这是非常令人满意的。这基本上是 web 或移动集成机器学习应用的第一步。

预测明天的 BTC 价格并将其“反序列化”

在我们定型模型之后,我们需要获取用于预测的当前数据,因为我们对数据进行了规范化,所以预测也将被规范化。因此,我们需要反规范化回它们的原始值。首先,我们将使用以下代码以类似的、部分不同的方式获取数据:

Loading the last 30 days’ BTC Prices

我们将只有用于预测的标准化数据:没有训练测试分割。我们还将手动重塑数据,以便能够在我们保存的模型中使用它。

在清理和准备我们的数据后,我们将加载训练好的 RNN 模型进行预测,并预测明天的价格。

Loading the Trained Model and Making the Prediction

但是,我们的结果将在-1 和 1 之间变化,这没有太大意义。因此,我们需要将它们反规范化回它们的初始值。我们可以通过一个自定义函数来实现这一点:

We need a deserializer for Original BTC Prediction Value in USD

定义自定义函数后,我们将调用这些函数,并用以下代码提取明天的 BTC 价格:

Calling the deserializer and extracting the Price in USD

使用上面的代码,您实际上可以获得模型对明天 BTC 价格的预测。

反序列化 X_Test 预测并创建 Plot.ly 图表

你也可能对 RNN 模型的总体结果感兴趣,更喜欢把它作为一个图表来看。我们也可以通过使用本教程培训部分的 X_test 数据来实现这些。

我们将首先加载我们的模型(将其视为单一预测案例的替代方案)并对 X_test 数据进行预测,以便我们可以使用以下代码对适当的绘图天数进行预测:

Loading the Trained Model and Making Prediction Using the X_test Values

接下来,我们将导入 Plotly 并设置属性以获得良好的打印体验。我们将通过以下代码实现这一点:

Importing Plotly and Setting the Parameters

设置完所有属性后,我们最终可以用下面的代码来绘制我们的预测和观察值:

Creating a Dataframe and Using it in Plotly’s iPlot

当您运行此代码时,您将得到以下图形的最新版本:

Plot.ly Chart for BTC Price Predictions

这些结果有多可靠?

如你所见,它看起来一点也不差。但是,您需要知道,即使模式非常匹配,如果您每天都检查结果,结果仍然彼此相差很大。因此,必须进一步开发代码以获得更好的结果。

恭喜

您已经成功创建并训练了一个可以预测 BTC 价格的 RNN 模型,甚至还保存了训练好的模型以备后用。通过切换到面向对象编程,您可以在 web 或移动应用程序上使用这种经过训练的模型。为自己成功开发了一个与人工智能、区块链和金融相关的模型而沾沾自喜。我认为用这个简单的项目同时触及这些领域听起来很酷。

订阅邮件列表获取完整代码

如果你想在 Google Colab 上获得完整的代码,并获得我的最新内容,可以考虑订阅邮件列表:✉️

立即订阅

喜欢这篇文章

如果你喜欢这篇文章,可以考虑看看我的其他类似文章:

[## 使用卷积自动编码器在 10 分钟内降低图像噪声

在时尚 MNIST 的帮助下,使用深度卷积自动编码器清洁(或去噪)有噪声的图像

towardsdatascience.com](/image-noise-reduction-in-10-minutes-with-convolutional-autoencoders-d16219d2956a) [## 使用 MNIST 数据集在 10 分钟内完成图像分类

利用 TensorFlow 和 Keras |监督深度学习使用卷积神经网络来分类手写数字

towardsdatascience.com](/image-classification-in-10-minutes-with-mnist-dataset-54c35b77a38d) [## 利用生成性对抗网络在 10 分钟内生成图像

使用无监督深度学习生成手写数字与深度卷积甘斯使用张量流和…

towardsdatascience.com](/image-generation-in-10-minutes-with-generative-adversarial-networks-c2afc56bfa3b) [## TensorFlow Hub & Magenta 在 5 分钟内实现快速神经风格转换

利用 Magenta 的任意图像风格化网络和深度学习,将梵高的独特风格转移到照片中

towardsdatascience.com](/fast-neural-style-transfer-in-5-minutes-with-tensorflow-hub-magenta-110b60431dcc)

一般建议警告

本网站发布的信息仅供一般参考,并不作为对任何特定人士的具体建议。本文包含的任何建议都是一般性建议,不考虑任何人的特定投资目标、财务状况和特殊需求。

在根据本建议做出投资决定之前,无论是否有合格顾问的帮助,您都应该考虑本建议是否适合您的特定投资需求、目标和财务状况。金融产品过去的表现并不能保证未来的表现。

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

使用 sci kit-学会发现恶霸

原文:https://towardsdatascience.com/using-scikit-learn-to-find-bullies-c47a1045d92f?source=collection_archive---------14-----------------------

到目前为止,我所做的大部分工作都是关于神经网络的。然而,这些有一个明显的缺点:它们需要大量的数据。

The loss of my Quora NLP neural network. The fact that validation loss is much greater than training loss is indicative of overfitting, and this happens quite early in the training.

当我训练一个自然语言处理神经网络来识别相似的 Quora 问题时,这一点非常清楚。即使有 300,000 个数据点可用于训练网络,它仍然没有花很长时间就开始过度拟合。

在本文中,我将使用一个小得多的数据集来练习分类。我将使用各种工具来完成这项工作,包括 SpaCy (一种自然语言处理工具),以及不同的 scikit-learn 算法。

在这个过程中,我将探索我所使用的算法到底是做什么的。

内容:

  1. 问题定义和设置
  2. 用 scikit-learn 算法求解
    a. 逻辑回归
    b. 随机森林
    c. 支持向量机
  3. 结论

问题定义和设置

链接到代码

为了找到一个小数据集来玩,我找到了一个很久以前的 Kaggle 比赛:检测社会评论中的侮辱。训练集有 3000 个数据点,比我上次解决的自然语言处理挑战小 100 倍。

挑战:确定一条评论是否会被认为是对对话中另一位参与者的侮辱。

这些评论来自评论网站、留言板等,以 csv 文件的形式提供。

下面是一个非侮辱性评论的例子:

"Celebrity Big Brother IS a mistake."

和一个侮辱性的评论:

"You are stuck on stupid obviously...give me a break and don\'t vote.\\nmoron"

清理数据

正如上面的例子所示,清理句子是必要的。我将使用单词嵌入来量化单词,所以我想在句子中分离出单词,没有任何诸如换行符或撇号之类的无用信息。

为了做到这一点,我把注释中的换行符都去掉了('\\n'在数据中特别常见,所以我专门做了一点去掉),只保留字母。

这样做将上面的注释更改为:

You are stuck on stupid obviously give me a break and don t vote  moron

符号化

SpaCy 非常擅长文字处理,尤其是非常擅长将数据符号化。这意味着它善于识别不同单词在句子中的位置(这很有用,因为它们不总是由空格分隔)。

SpaCy 的另一个非常酷的部分是,它根据手套词嵌入(我在这里探索)自动为这些令牌分配 300 维向量。因此,对我来说,获取一个句子,并从中生成一个嵌入矩阵非常容易。

然而,使用嵌入从句子创建矩阵的直观方法不适用于小数据集。如果我在训练一个神经网络,我的方法只是将所有嵌入向量附加在一起:

The intuitive approach to generating a matrix using word embeddings. Each word has its own 300 dimensional embedding. They are all appended together to create a ‘sentence matrix’.

这样做的问题是,随着句子长度的增加,特征的数量(即矩阵的大小)会激增。该数据集中的*均句子长度为33个单词;这将产生一个大小为(33, 300)的矩阵,有 9900 个元素。

鉴于我的 3000 训练点,这是乞求超负荷。

我的解决方案是找到矩阵中每个元素的*均值,因此我最终得到了每个句子的 300 维“*均值”向量:

这意味着每个输入将有 300 个特征;这要合理得多。

使用 scikit 求解-学习

链接至代码

本次竞赛的指标是 AUC ROC 。粗略地说,AUC ROC 分数可以解释为积极分类项目实际上是积极的可能性有多大,以及消极分类项目是消极的可能性有多大。

这比简单的准确性要好,因为它也考虑了数据集中的偏差。例如,如果我的评论中有 95%是侮辱性的,那么一个将每个评论都归类为侮辱性的分类器将有 95%的准确率,但它将是一个无用的分类器。AUC ROC 避免了这一点。

考虑到这一点,现在让我们分别研究每一种算法。

逻辑回归

它是如何工作的?该分类器将为我的输入特征中的每个变量定义系数(因此,因为我的输入是 300 维变量,所以定义了 300 个系数)。这就定义了一个函数:

This relationship does not have to be linear; different x terms could be multiplied together, for instance. However, LIBLINEAR, the library used by scikit-learn, does assume a linear relationship.

然后训练这些系数,使得如果输入特征是侮辱,则输出为 1,否则输出为 0。通常使用 sigmoid 函数来简化最后一步:

This function is called the sigmoid function, and restricts the output to between 1 and 0, which is ideal for classification, where something either is an insult (1) or is not (0). Particularly, it allows f(X) to get very large or small if it is confident in a classification, as the function is asymptotic.

它做得怎么样?微调这个模型非常容易,因为它只有一个真正可以改变的参数:C,或者正则化强度的倒数(基本上,C 控制系数可以变化的程度。这防止了数据的过度拟合)。

逻辑回归得出以下训练曲线:

These plots show the success of the models on a training set and cross validation set (the cross validation set was made with 20% of the data) as the training set grew from just 100 samples to all the training data available (to 80% of the data). The size of the cross validation set remains fixed. Making these plots of model success against training set size is useful to uncover the performance of the model, and to identify under/overfitting.

这种算法的简单性解释了为什么它训练起来如此之快。它的成功表明,取句子中单词向量的*均值是捕捉句子中情感的高效方式,因为它线性地映射到一个句子是否令人不快。

随机森林

它是如何工作的?为了理解随机森林,理解决策树是有帮助的。这篇文章在这方面做得很好,我不会试图重复,但非常广泛:给定一些数据集(即下面的一些工作机会),信息被用来将数据分成越来越小的子集,直到它被分类为“接受”或“拒绝”(在我的例子中,或者是“侮辱”或“不侮辱”)。更好的数据被用在树的更高层——所以在下面的例子中,薪水将是关于一份工作是否应该被接受或拒绝的最具指示性的指标。

Credit: http://dataaspirant.com/2017/01/30/how-decision-tree-algorithm-works/

随机森林(直观地)通过将数据随机分成(许多)子集来使用许多决策树。然后,在组合结果以生成结论之前,它对每个子集训练决策树。

怎么办到的?训练随机森林时要调整的重要参数是决策树的数量(大约 100 是一个好的起点)和每个数据子集中的特征数量(这里,建议使用特征数量的*方根-大约 17,300 个特征)。

这对我来说证明是最成功的,产生了下面的训练曲线:

这里发生了一些严重的过度拟合。训练集的 AUC-ROC 得分接* 1,而交叉验证集的最终得分为 0.87。

当考虑随机森林如何工作时,这确实是有意义的;绝大多数决策树将会是垃圾(并且将会过拟合)。然而,它们应该互相抵消,留下几棵树,这些树可以归纳到交叉验证集(然后是未来的数据)。

支持向量机

它是如何工作的?逻辑回归使用线性系数来定义函数,然后使用该函数来预测数据的类别。

支持向量机不是线性系数,而是将数据的每个维度的距离与某个标志进行比较。这定义了一个新的特征空间,然后可以用它来预测数据的类别。

这有点令人困惑,所以让我们考虑一维数据(想象一下,如果不是长度为 300 的输入向量,而是长度为 1):

The sigma defines L1’s ‘circle of influence’. If it is larger, then F1 will be big even if D is large (if X1 and L1 are further apart). If it is smaller, then F1 will vanish if D gets large.

我的特征 X1 现在已经转换为一个特征,然后我可以在一个方程中使用它,就像逻辑回归一样:

这使我能够以比简单的线性逻辑回归更复杂的方式分离数据,从而获得更好的性能。

它是怎么做的?与逻辑回归一样,最重要的训练超参数是正则化常数 c。

Note: SVC stand for support vector classification

最终 AUC ROC 为 0.89,是迄今为止最好的分类器。然而,因为它需要定义一个全新的特征空间来进行分类,所以它也比其他算法慢得多,在这个数据集上训练需要 14.8 秒(相比之下,逻辑回归需要 421 毫秒)。

算法对比

这些都是怎么做的?

SVM 是最好的,但是定义新的特征空间导致显著的计算成本,并且它比逻辑回归花费 35 倍的时间来训练(对于 0.01 AUC ROC 的相对小的改进)。

结论

从这里可以得到一些启示:

  1. 我一直惊讶于单词嵌入有多棒,尤其是考虑到它们是如何产生的。2012 年在 Kaggle 上发起这个比赛的时候(单词嵌入之前),获胜分数是 0.84249。单词嵌入让我不费吹灰之力就把这个分数提高到了 0.89。
  2. 除了准确性,还有其他指标需要考虑。SVM 和逻辑回归之间的训练时间差异的重要性给我留下了深刻的印象,尽管 SVM 最终更好,但它可能不是最好的算法。
  3. 所有这些算法都被设计用来处理扔给它们的任何东西,因此相当健壮。考虑到这些算法处理问题的不同,它们的表现非常相似;AUC ROC 评分最大差距只有 0.019——ka ggle 比赛第 1 名和第 10 名的差距。

使用 Scrapy 构建自己的数据集

原文:https://towardsdatascience.com/using-scrapy-to-build-your-own-dataset-64ea2d7d4673?source=collection_archive---------0-----------------------

Web Scraping (Scrapy) using Python

当我刚开始在工业界工作时,我很快意识到的一件事是,有时你必须收集、组织和清理你自己的数据。在本教程中,我们将从一个名为 FundRazr 的众筹网站收集数据。像许多网站一样,该网站有自己的结构、形式,并有大量可访问的有用数据,但很难从该网站获得数据,因为它没有结构化的 API。因此,我们将从网站上抓取非结构化的网站数据,并以有序的形式构建我们自己的数据集。

为了抓取网站,我们将使用 Scrapy 。简而言之,Scrapy 是一个框架,旨在更容易地构建 web 抓取工具,并减轻维护它们的痛苦。基本上,它允许您专注于使用 CSS 选择器和选择 XPath 表达式的数据提取,而不是蜘蛛应该如何工作的复杂内部。这篇博客文章超越了来自 scrapy 文档的伟大的官方教程,希望如果你需要更难的东西,你可以自己做。就这样,让我们开始吧。如果你迷路了,我建议在一个单独的标签中打开视频。

入门(先决条件)

如果你已经有了 anaconda 和 google chrome(或者 Firefox),跳到创建一个新的 Scrapy 项目。

1。在你的操作系统上安装 Anaconda (Python)。您可以从官方网站下载 anaconda 并自行安装,也可以遵循下面的 anaconda 安装教程。

Installing Anaconda

2。安装 Scrapy (anaconda 自带,只是以防万一)。您也可以在终端(mac/linux)或命令行(windows)上安装。您可以键入以下内容:

conda install -c conda-forge scrapy

3.确保你有谷歌浏览器或火狐浏览器。在本教程中,我使用的是谷歌浏览器。如果你没有谷歌浏览器,你可以使用这个链接在这里安装。

创建一个新的 Scrapy 项目

1.打开终端(mac/linux)或命令行(windows)。导航到所需的文件夹(如果需要帮助,请参见下图)并键入

scrapy startproject fundrazr

scrapy startproject fundrazr

这将创建一个包含以下内容的 fundrazr 目录:

fundrazr project directory

在 Google Chrome(或 Firefox)上使用 Inspect 寻找好的开始网址

在蜘蛛框架中, start_urls 是一个 URL 列表,当没有指定特定的 URL 时,蜘蛛将从该列表开始爬行。我们将使用 start_urls 列表中的每个元素作为获取单个活动链接的手段。

1.下图显示,根据您选择的类别,您会得到不同的起始 url。黑色突出显示的部分是可能要刮除的 fundrazrs 类别。

Finding a good first start_url

对于本教程,列表中的第一个 start_urls 是:

https://fundrazr.com/find?category=Health

2.这一部分是关于获取额外的元素放入 start_urls 列表。我们正在寻找如何转到下一页,这样我们就可以获得更多的 URL 放入 start_urls

Getting additional elements to put in start_urls list by inspecting Next button

第二个开始网址是:https://fundrazr.com/find?category=Health&page = 2

下面的代码将在本教程后面的蜘蛛代码中使用。它所做的就是创建一个 start_urls 列表。变量 npages 就是我们希望从多少个附加页面(在第一页之后)获得活动链接。

Code to generate additional start urls based on current structure of website

Scrapy 外壳用于查找个人活动链接

学习如何用 Scrapy 提取数据的最好方法是使用 Scrapy shell。我们将使用 XPaths,它可以用来从 HTML 文档中选择元素。

我们将尝试获取 xpaths 的第一件事是单独的活动链接。首先,我们检查一下 HTML 中的活动的大致位置。

Finding links to individual campaigns

我们将使用 XPath 提取下面红色矩形中包含的部分。

The enclosed part is a partial url we will isolate

在终端类型(mac/linux)中:

scrapy shell '[https://fundrazr.com/find?category=Health'](https://fundrazr.com/find?category=Health')

在命令行中键入(windows):

scrapy shell “[https://fundrazr.com/find?category=Health](https://fundrazr.com/find?category=Health)"

在 scrapy shell 中键入以下内容(为了帮助理解代码,请查看视频):

response.xpath("//h2[contains([@class](http://twitter.com/class), 'title headline-font')]/a[contains([@class](http://twitter.com/class), 'campaign-link')]//@href").extract()

There is a good chance you will get different partial urls as websites update over time

下面的代码用于获取给定起始 url 的所有活动链接(稍后在第一个蜘蛛部分会有更多)

通过键入 exit() 退出 Scrapy Shell。

exit scrapy shell

检查单个活动

虽然我们应该先了解各个活动链接的结构,但本节将介绍各个活动的位置。

  1. 接下来,我们转到一个单独的活动页面(见下面的链接)进行搜集(我应该注意到,有些活动很难查看)

https://fundrazr.com/savemyarm

2.使用与前面相同的检查过程,我们检查页面上的标题

Inspect Campaign Title

3.现在,我们将再次使用 scrapy shell,但这一次是一个单独的活动。我们这样做是因为我们想了解各个活动是如何格式化的(包括了解如何从网页中提取标题)。

在终端类型(mac/linux)中:

scrapy shell '[https://fundrazr.com/savemyarm](https://fundrazr.com/savemyarm')'

在命令行中键入(windows):

scrapy shell “[https://fundrazr.com/savemyarm](https://fundrazr.com/savemyarm)"

获取活动标题的代码是

response.xpath("//div[contains([@id](http://twitter.com/id), 'campaign-title')]/descendant::text()").extract()[0]

4.我们可以对页面的其他部分做同样的事情。

筹集的金额:

response.xpath("//span[contains([@class](http://twitter.com/class),'stat')]/span[contains([@class](http://twitter.com/class), 'amount-raised')]/descendant::text()").extract()

目标:

response.xpath("//div[contains([@class](http://twitter.com/class), 'stats-primary with-goal')]//span[contains([@class](http://twitter.com/class), 'stats-label hidden-phone')]/text()").extract()

货币类型:

response.xpath("//div[contains([@class](http://twitter.com/class), 'stats-primary with-goal')]/@title").extract()

活动结束日期:

response.xpath("//div[contains([@id](http://twitter.com/id), 'campaign-stats')]//span[contains([@class](http://twitter.com/class),'stats-label hidden-phone')]/span[[@class](http://twitter.com/class)='nowrap']/text()").extract()

贡献者人数:

response.xpath("//div[contains([@class](http://twitter.com/class), 'stats-secondary with-goal')]//span[contains([@class](http://twitter.com/class), 'donation-count stat')]/text()").extract()

故事:

response.xpath("//div[contains([@id](http://twitter.com/id), 'full-story')]/descendant::text()").extract()

网址:

response.xpath("//meta[[@property](http://twitter.com/property)='og:url']/@content").extract()

5.键入以下命令退出 scrapy shell:

exit()

项目

抓取的主要目标是从非结构化的源(通常是网页)中提取结构化数据。Scrapy 蜘蛛可以将提取的数据作为 Python 字典返回。虽然方便和熟悉,但 Python 字典缺乏结构:很容易在字段名中打错字或返回不一致的数据,尤其是在有许多蜘蛛的大型项目中(几乎逐字逐句地复制自伟大的 scrapy 官方文档!).

File we will be modifying

items.py 的代码在这里是。

将其保存在 fundrazr/fundrazr 目录下(覆盖原来的 items.py 文件)。

本教程中使用的 item 类(基本上是我们在输出数据之前存储数据的方式)如下所示。

items.py code

蜘蛛

蜘蛛是你定义的类,Scrapy 用它从一个网站(或一组网站)抓取信息。我们蜘蛛的代码如下。

Fundrazr Scrapy Code

在这里下载的代码。

将其保存在 fundrazr/spiders 目录下的一个名为的文件中。

当前项目现在应该有以下内容:

File we will be creating/adding

运行蜘蛛

  1. 转到 fundrazr/fundrazr 目录并键入:
scrapy crawl my_scraper -o MonthDay_Year.csv

scrapy crawl my_scraper -o MonthDay_Year.csv

2.数据应该输出到 fundrazr/fundrazr 目录中。

Data Output Location

我们的数据

  1. 本教程中输出的数据应该大致如下图所示。随着网站的不断更新,单个广告活动也会有所不同。此外,在 excel 解释 csv 文件时,每个活动之间可能会有空格。

The data should roughly be in this format.

2.如果你想下载一个更大的文件(它是通过将 npages = 2 改为 npages = 450 并添加 download_delay = 2)你可以通过从我的 github 下载文件来下载一个更大的文件,其中大约有 6000 个战役。该文件名为 MiniMorningScrape.csv(这是一个大文件)。

Roughly 6000 Campaigns Scraped

结束语

创建数据集可能需要大量的工作,这通常是学习数据科学时被忽略的一部分。有一点我们没有注意到,虽然我们收集了大量数据,但我们仍然没有清理足够的数据来进行分析。不过这是另一篇博文的内容。如果你对本教程有任何问题或想法,欢迎通过 YouTube 或 Twitter 发表评论。如果你想学习如何使用 Pandas、Matplotlib 或 Seaborn 库,请考虑参加我的数据可视化 LinkedIn 学习课程。

利用信号处理提取 Python 中的神经事件——锋电位排序

原文:https://towardsdatascience.com/using-signal-processing-to-extract-neural-events-in-python-964437dc7c0?source=collection_archive---------13-----------------------

生物神经网络,如人脑,由称为神经元的特殊细胞组成。有各种类型的神经元,但它们都基于相同的概念。被称为神经递质的信号分子在突触(两个神经元之间的连接点)释放。神经递质通过与细胞膜内的离子通道相互作用来改变突触后细胞的膜电位。如果突触后细胞的去极化足够强,就会在轴突小丘产生动作电位。动作电位将沿着轴突传播,并触发神经递质释放到突触间隙中,这将影响下一个神经元的膜电位。通过这种方式,信号可以通过(整个)网络从一个细胞传递到下一个细胞,动作电位是突触释放神经递质的触发器。神经通信本质上是电化学的,知道何时以及在何种条件下产生动作电位可以对大脑的工作提供有价值的见解。

By BruceBlaus [CC BY 3.0 (https://creativecommons.org/licenses/by/3.0)], from Wikimedia Commons

但是研究活体大脑中单个神经元的活动是一项具有挑战性的任务。没有一种非侵入性的方法可以在单细胞水*上实时监测神经活动。通常在大脑中插入一个电极来记录其附*的电活动。在这些类型的电生理记录中,动作电位表现为快速高振幅尖峰。但是由于神经元在大脑中密集分布,记录电极通常一次会从不止一个神经元上获得尖峰信号。因此,如果我们想了解单个神经元的行为,我们需要从记录中提取尖峰信号,并检查它们是由一个还是潜在的几个神经元产生的。从数据中提取尖峰并对其进行聚类被称为尖峰排序。在下文中,我们将概述从原始数据中提取单个尖峰并将它们准备用于尖峰排序的过程。

入门指南

所以首先我们需要数据。Matlab 有一个流行的尖峰排序算法叫做波簇。在其网页的数据部分,他们提供了一个测试数据集,我们将在这里使用。根据网页上提供的信息,该录音长约 30 分钟,来自一名癫痫患者。数据存储在。 ncs 文件,这是制造记录系统的公司的数据格式。因此,如果我们想将记录读入 Python,我们需要了解数据是如何存储的。关于有详细的描述。公司网页上的 ncs 文件格式,我们可以用它来导入文件:

>>> # Define data path
>>> data_file = './UCLA_data/CSC4.Ncs'>>> # Header has 16 kilobytes length
>>> header_size   = 16 * 1024>>> # Open file
>>> fid = open(data_file, 'rb')>>> # Skip header by shifting position by header size
>>> fid.seek(header_size)>>> # Read data according to Neuralynx information
>>> data_format = np.dtype([('TimeStamp', np.uint64),
>>>                         ('ChannelNumber', np.uint32),
>>>                         ('SampleFreq', np.uint32),
>>>                         ('NumValidSamples', np.uint32),
>>>                         ('Samples', np.int16, 512)])>>> raw = np.fromfile(fid, dtype=data_format)>>> # Close file
>>> fid.close()>>> # Get sampling frequency
>>> sf = raw['SampleFreq'][0]>>> # Create data vector
>>> data = raw['Samples'].ravel()

在上面的代码中我们可以看到。ncs 文件还包含一些关于录音的附加信息。最重要的是,采样频率告诉我们每秒记录了多少数据点。有了采样频率和数据中的样本数,我们现在可以创建一个时间向量,以便绘制信号随时间的变化图。下面的代码将做到这一点,并绘制信号的第一秒。

>>> # Determine duration of recording in seconds
>>> dur_sec = data.shape[0]/sf>>> # Create time vector
>>> time = np.linspace(0, dur_sec,data.shape[0])>>> # Plot first second of data
>>> fig, ax = plt.subplots(figsize=(15, 5))
>>> ax.plot(time[0:sf], data[0:sf])
>>> ax.set_title('Broadband; Sampling Frequency: {}Hz'.format(sf), >>>               fontsize=23)
>>> ax.set_xlim(0, time[sf])
>>> ax.set_xlabel('time [s]', fontsize=20)
>>> ax.set_ylabel('amplitude [uV]', fontsize=20)
>>> plt.show()

好吧,我们看到尖峰了吗?…不,我们没有。但是我们确实在数据中看到了某种有节奏的活动。那么这是一个有意义的信号吗?同样,答案是否定的。如果我们要计算第一秒数据中的峰值数量,我们最终会得到 60 个峰值,这意味着我们看到的是 60 Hz 的振荡。我们可以通过绘制信号的功率谱来进一步证实这一点,该功率谱在 60 Hz 处显示出清晰的峰值。

我们在看什么?在我们获得数据的网页上说录音来自伊扎克·弗里德在美国加州大学洛杉矶分校的实验室。美国的供电频率是 60 Hz。因此,我们看到的实际上是数据收集期间房间内电子设备发出的电噪声。

找到信号中的尖峰

即使数据中有 60 Hz 噪声,我们仍然可以处理它。幸运的是,动作电位是只持续 1 到 2 毫秒的快速事件。因此,我们可以在排除 60 Hz 噪声的范围内对原始宽带信号进行滤波。典型的滤波器设置为 500 至 9000 Hz,我们的 Python 实现如下所示:

>>> # Import libarys
>>> from scipy.signal import butter, lfilter>>> def filter_data(data, low=500, high=9000, sf, order=2):
>>>     # Determine Nyquist frequency
>>>     nyq = sf/2>>>     # Set bands
>>>     low = low/nyq
>>>     high = high/nyq>>>     # Calculate coefficients
>>>     b, a = butter(order, [low, high], btype='band')>>>     # Filter signal
>>>     filtered_data = lfilter(b, a, data)
>>>    
>>>     return filtered_data

用上述函数处理数据将得到信号的高频带或尖峰通道。我们的期望是,该棘波通道包含动作电位,并且不再有 60 Hz 噪声。让我们看看滤波后的尖峰通道,并将其与原始宽带信号进行比较。

正如所料,尖峰通道不再显示 60 赫兹的振荡。最重要的是,我们终于可以看到记录中的第一个尖峰。在记录开始大约 0.5 秒时,它在过滤数据中清晰可见。同样,既然我们现在看哪里,我们可以在未过滤的数据中看到它。然而,由于 60 赫兹的噪音,它更难被发现。

从信号中提取尖峰信号

既然我们已经将高频尖峰信号带从噪声低频带中分离出来,我们就可以提取单个尖峰信号。为此,我们将编写一个简单的函数来执行以下操作:

  1. 找到信号中高于特定阈值的数据点
  2. 围绕这些事件定义一个窗口,并“将它们剔除”
  3. 将它们对准它们的峰值振幅

此外,我们还将定义一个上限。高于该阈值的数据点将被拒绝,因为它们可能是高频伪影。这种伪影可能是由于患者的移动而产生的,或者可能反映了电气事件,如打开或关闭房间中的灯泡。可以详细看看 Jupyter 笔记本里的尖刺提取功能。这里我们只看一下用我们的函数从信号中提取的 100 个随机尖峰。

在上图中,我们可以看到数据中至少有两种类型的波形。一组尖峰具有尖锐的高振幅峰值,第二组具有较宽的初始峰值。所以这些尖峰信号很可能是由不止一个神经元产生的。因此,下一个任务是找到一种将波形分组到不同簇的方法。但是因为这不能用两三行来编码或解释,我们将在下一篇文章中看到尖峰排序的主题。

同时,你可以在这里查看完整的代码,在 Twitter 上关注我或者通过 LinkedIn 联系我。

这个项目的代码可以在 Github 上找到。

[## akcarsten/spike _ 排序

在 GitHub 上创建一个帐户,为 akcarsten/spike_sorting 开发做贡献。

github.com](https://github.com/akcarsten/spike_sorting)

使用星巴克应用程序用户数据预测有效优惠

原文:https://towardsdatascience.com/using-starbucks-app-user-data-to-predict-effective-offers-20b799f3a6d5?source=collection_archive---------11-----------------------

对于我的 Udacity 数据科学家 Capstone 项目,我使用星巴克奖励应用程序的模拟数据来预测用户接受要约的倾向

Image cropped from Kaique Rocha

项目概述

在我的顶点项目中,我的目标是回答两个主要的业务问题:

  1. 星巴克应用程序上有效报价的主要驱动因素是什么?
  2. 提供的数据,即要约特征和用户人口统计数据,能否预测用户是否会接受要约?

这两个问题背后的商业动机是双重的:首先,从商业角度来看,星巴克可以更好地将他们的优惠瞄准更有接受优惠倾向的顾客。通过这样做,他们有可能最大限度地提高从正确客户的报价中获得的收入,并通过发送更相关的报价来节省营销和促销成本。

其次,从顾客的角度来看,顾客在星巴克和应用程序上获得了更好的体验,因为他们将收到个性化的、符合他们口味的相关优惠。

这个顶点项目使用 Udacity 提供的数据作为数据科学家纳米学位课程的一部分。它包含模拟星巴克奖励移动应用程序上的客户行为的模拟数据。

手机 app 上提供的背景信息是,每隔几天,星巴克就向手机 app 的用户发出一次优惠。有些用户可能在特定的几周内收不到任何优惠,而且并非所有用户都收到相同的优惠。

问题陈述

如上所述,我要回答的问题陈述是(1)发现要约有效性的主要驱动因素,以及(2)探索我们是否可以预测用户是否会接受要约。

提供的数据由 3 个数据集组成:

  • 优惠组合,由每个优惠的属性组成
  • 每个客户的人口统计数据
  • 应用程序上发生的事件的交易记录

使用提供的数据,我使用 3 个分类监督机器学习模型回答了上述两个问题,输入了来自三种不同报价类型的数据。

我使用该模型来揭示特征的重要性,以确定要约有效性的驱动因素,同时探索该模型本身是否可以用来预测用户是否会接受要约。

最后,我还探索了接受或不接受要约的用户的特征。

我的项目旨在回答上面的两个问题,但我最后还添加了两个额外的模型作为探索点,这将在第 4 部分中阐述——第一个,评估是否可以使用一体化模型代替 3 个不同的模型,优惠类型作为分类变量。其次,我还建立了一个回归模型,看看我们是否可以预测用户将花费的金额,假设优惠有效地影响了他们。

如果我能够成功实现上述模型,我的预期解决方案将是找到有效报价的驱动因素,这可能是用户的人口统计属性,例如用户的会员资格。

理想情况下,一个成功的模型还能够预测用户接受要约的倾向,准确率至少为 75%。这将是我计划实现的 3 个模型的基准精度。

为了评估我的模型的性能,我将使用的指标是准确性,并与 F1 分数进行比较,因为这些是分类模型。

与纯粹的准确性相比,F1 分数提供了更好的模型性能感觉,因为在计算中同时考虑了假阳性和假阴性。对于不均匀的类别分布,F1 通常比准确性更有用。

在这种情况下,值得注意的是,F1 分数是基于精确度和召回率的调和*均值,并且侧重于正面案例。对于这里的星巴克应用程序来说,这很好,因为我们会更优先考虑优惠是否有效,而不是为什么优惠无效。

同时,准确性提供了一个很好的总体指标来评估我的模型性能,并且足以用于预测用户接受要约的倾向,因为我们不会太担心负面分类的情况。事实上,出于商业目的,我们可能会允许一些错误分类的负面案例,因为我们可能会通过优惠的激励抓住可能的产品销售,而不是允许错过机会。

至此,我将在以下几个部分解释我的项目:

  1. 数据探索 —我探索所提供数据的属性,并决定用于建模的数据预处理方法
  2. 数据预处理 —我在这部分做了大量的数据清理和特征工程,为建模准备数据
  3. 模型实现 —我实现了我的 3 个模型,并对模型实现进行了细化,考虑了每个版本中的模型性能,并根据结果决定了最佳模型。
  4. 侧面探索 —在实现了模型之后,我探索了一些用于建模数据的替代方法,以及上面提到的一些额外的模型。我还执行了一些进一步的探索性数据分析,以从提供的数据中提取进一步的见解。
  5. 结论 —我对该项目的最终想法,以及我对如何进一步改进数据分析和建模实现的一些思考。

虽然如果需要了解我是如何实现这个项目的,我会深入研究我的代码输出,但我不会深入研究每一步的细节。关于这方面的更多细节,你可以查看我的 Github repo,其中包含了这个项目的 Jupyter 笔记本。

第一部分。数据探索

a.报价组合数据

根据 Udacity 提供的信息,模式如下:

portfolio.json

  • id(字符串)—优惠 id
  • offer_type (string) —优惠的类型,如 BOGO、折扣、信息
  • 难度(int) —完成报价所需的最低花费
  • 奖励(int) —为完成一项提议而给予的奖励
  • 持续时间(整数)
  • 频道(字符串列表)

此外,关于报价的一些进一步信息是,有 3 种不同的报价类型:

  • BOGO——买一送一
  • 折扣——购买折扣
  • 信息—提供有关产品的信息

因此,该模式非常简单,因为它包含 3 种不同报价类型的属性。虽然没有解释持续时间,但我从上下文中推测这是天数。

在获取数据的快照视图后,我注意到在预处理阶段进行数据清理的一些关键元素。其中包括:

  • 稍后在预处理过程中扩展channel列,使其成为我的数据集中的分类变量
  • 特征比例——每个的比例是不同的,例如difficulty是以美元为单位,而duration是以天为单位。
  • 没有空值,我们可以保持原样。

b.人口数据

profile数据集中提供了客户的人口统计数据。模式和变量如下:

profile.json

  • 年龄(整数)—客户的年龄
  • 成为会员日期(整数)—客户创建应用程序帐户的日期
  • 性别(str) —客户的性别(请注意,有些条目包含“O”代表其他,而不是 M 或 F)
  • id (str) —客户 id
  • 收入(浮动)—客户的收入

它也相对简单,因为它包含了客户的人口统计资料。

我对income列做了一些数据可视化,发现需要一些进一步的数据预处理步骤。

  • genderincome列中的空值——如果它们没有占据数据集的大部分,则需要删除

Income also has a relatively normal distribution, ignoring the null values

  • 清洁age=118

Distribution for agecolumn

  • became_member_on柱的特征工程

c.交易记录

事务数据的模式如下:

抄本. json

  • 事件(str) —记录描述(即交易、收到的报价、查看的报价等。)
  • 人员(字符串)—客户 id
  • time (int) —以小时为单位的时间。数据开始于时间 t=0
  • value —(字符串字典)—报价 id 或交易金额,具体取决于记录

这个数据看起来有点复杂,因为它是按时间排序的,并且有一个事件和值。特别是,value列必须根据事件进行预处理。

我还发现抄本中的人数(即唯一 id 的数量)与人口统计数据中的人数相同,所以这是个好消息。但是为了从这个数据集中提取有意义的见解,需要做大量的预处理。

现在,我对抄本数据集进行了一些数据清理。为了从值列中提取细节,我根据事件将值展开到各个列中。这样,我就有了一个干净的转录数据集来做进一步的分析。

d.定义预处理模型数据的方法

在为模型预处理数据之前,我首先回顾了我的目标。在对数据进行了初步探索之后,我不得不重新评估我将如何为我打算构建的模型清理和准备数据。

为了确定有效报价的主要驱动因素,我必须首先定义星巴克应用程序中的“有效”报价。因此,我对数据集以及这三者如何相互作用做了进一步的探索。

首先,我研究了每种报价类型中的事件种类。

Events grouped by offer_type

我们知道有 4 种类型的事件:offer completedoffer receivedoffer viewedtransaction。但是我们的数据显示我们没有任何与transactions相关联的 offer_id,因为它们没有记录在抄本事件数据中。因此,数据预处理的第一个目标是定义一种方法来将 offer _ ids 分配给特定的事务。

此外,我们还知道 BOGO 和折扣优惠在优惠完成时会有一个offer completed事件。但是,信息优惠没有与此事件相关联。因此,我们还规定了定义有效报价的方法,如下所示:

对于 BOGO 和折扣优惠,如果按正确的时间顺序记录了以下事件,则定义为有效优惠:

offer received->-offer viewed->-transaction->-offer completed

同时,对于信息性报价,由于有offer completed事件与之关联,我必须将交易定义为有效报价的转换:

offer received->-offer viewed->-transaction

第 2 部分:数据预处理

a.为交易分配优惠 id

在定义了上面的方法之后,我们现在必须探索将 offer _ ids 分配给特定事务的方法。考虑因素之一是定义以下主要客户群:

  1. 受影响并成功转化的人群—有效优惠:
  • 已收到报价->已查看报价->交易->已完成报价(BOGO/折扣报价)
  • 已收到报价->已查看报价->交易(信息报价-必须在报价有效期内)

2。收到并查看了优惠但未成功转换的人员—无效优惠:

  • 收到的报价->查看的报价

3。购买/完成优惠而不考虑任何优惠的人:

  • 交易
  • 报价已收到->交易->报价已完成->报价已查看
  • 交易->收到报价->完成报价->查看报价
  • 已收到报价->交易->已查看报价->已完成报价
  • 收到报价->交易(信息报价)
  • 收到报价->交易->查看报价(信息报价)

4。收到聘用但未采取行动的人员:

  • 收到报价

对于第 2 组中的人,我需要检查是否有事件,其中有offer receivedoffer viewed事件,但没有转换事件,即offer completedtransaction——这些是无效报价的情况。

我必须将组 2 中的人与组 4 中的人分开,因为组 2 中的人可能已经查看了报价,但没有采取任何行动,而组 4 中的人甚至没有offer viewed事件。

区分有效优惠的转化(第 1 组)和购买/完成优惠而不考虑任何优惠的人(第 3 组)尤其棘手。对于第 3 组中的人,如果offer completedtransaction出现在offer viewed之前,则转换无效(即,不是从要约的成功转换)。也可能有这样的情况,在查看报价之后发生了offer completed,但是在查看报价之前已经完成了交易。在这种情况下,要约可能已经完成,但它也不是有效的转换。

定义目标变量 **effective offer** :

定义这些条件后,我们必须决定目标变量是什么。

我们知道第 1 组客户将是我们的目标变量effective_offer=1,但对于第 2-4 组客户,有许多无效的报价定义。

那么,我们如何定义无效要约呢?如上所述,第二组属于无效要约的定义范围;用户知道一个提议,但是该提议是无效的,因为它没有将用户转化为顾客。所以第二组可以定义为我们的目标变量effective_offer=0

第三组和第四组呢?组 3 由可能已经收到报价但无论如何都要购买的用户组成。从商业的角度来看,我们不想给他们任何报价。

同时,组 4 用户将被认为是低优先级客户,因为他们不做任何动作,不管他们是否收到报价。

因此,我们可以从模型中取消组 3 和组 4 用户的优先级。仍然值得对第 3 组和第 4 组做一些探索性分析,只是为了探索他们的人口统计数据。

上述条件是我可以通过确保交易发生在offer viewed事件之后来分配“影响”交易的报价 id 的基础。

因此,属于组 1 的任何唯一的 person-offer_id 都可以在我们的目标变量effective_offer=1组中考虑。

同时,组 2 在我们的目标变量effective_offer=0组中。对于第 3 组和第 4 组中的客户,我在模型实现中取消了他们的优先级,但是将在第 4 部分中对他们进行一些探索性分析。

因此,我通过将第 1 组和第 2 组客户数据集附加在一起,为每种包含有效和无效报价的报价类型创建了一个数据集,并成功地为我们的 BOGO 和折扣数据集准备了目标变量。

同时,特别是对于信息优惠,在我们可以标记有效优惠列之前,还有一个额外的考虑—优惠的有效性。这是因为转换事件不是offer completed事件,而是transaction事件。

对于信息性报价,报价的duration可以认为是影响的持续时间。因此,我们可以假设,只有在要约的duration范围内,要约才应被视为有效。

同时,对于 BOGO 和折扣优惠,我们可以假设,如果有转换/ offer completed事件,它应该在持续时间内,因为如果优惠超过其有效期,则完成优惠没有意义。

d.特征工程

现在,我们必须回头看看这些功能,看看如何创造性地创造新功能。

待设计的内径 **became_member_on**

回想我最初的数据探索步骤,became_member_on列是日期格式的。因此,为了从该特征中提取有意义的见解,我们可以将其转换为指示成员任期的特征。一个人成为会员的时间长短可能会对他是否接受邀请产生一些影响。

因此,我从became_member_on列中提取了每个人的会员任期天数,使用 2018 年作为当前年份。

d.ii .收到的报价数

作为进一步数据探索的一部分,我发现每个人可能会收到多个报价。

Multiple offers received per person

我们可以从上面看到,在交易数据中,每个人收到的报价范围可以是 1 到 6 个。我有一个假设,即每个人收到的报价频率可能会导致更有效的报价,所以决定设计一个功能offer_received_cnt来解释这个频率。

d.ii .通过交易分离用户行为

我还想知道根据我的定义,有多少事务被认为是“无效”的。通常,这些是不属于第一组的人完成的交易的总和。优惠的目的是推动购买,因此在交易中花费高的用户将被标记为effective_offers

我们已经定义了第 3 组和第 4 组中的人,他们是独立的用户群,是忠实的消费者,已经倾向于购买更多,不受优惠的影响。

但是对于组 1 中的用户来说,在优惠的效果之外有大量的“无效消费”,可能对优惠的有效性有一些预测能力;因为忠诚的用户可能更倾向于接受报价。

其逻辑是想知道,对于受某些优惠(第 1 组)和第 2 组影响很大的用户,是否存在某种消费基线水*,以及“无效交易”的这种基线水*是否具有某种预测能力,可以预测用户接受优惠的倾向。

因此,我计算了每个人的“无效”交易,作为一个附加特征。

然而,在这样做的时候,我发现在这个工程特性列中缺少的值非常多。

High % of missing values in amount_invalid column for BOGO dataset

由于稀疏性,这个列amount_invalid包含在模型中是否有用是有争议的。由于它是如此“稀疏”,它可能没有太多的信息。我计划稍后在模型实现阶段再次评估这个特性。现在,我决定用 0 填充缺失的amount_invalid列,因为它可能代表只有 4%的用户倾向于购买没有优惠的商品;其余 96%的人只会在知道有持续优惠的情况下购买。

同时,我们已经在上面对incomegender列进行了分析,我已经选择删除它们,因为当它们为空时没有用,并且它们只占数据集的 7%。

丁三世。收到报价的间隔时间

我还想将时间作为一个潜在的特征包含到我的数据集中,但是由于事务性数据从时间=0 开始,我怀疑如果没有一些特征工程,它不会有太大的预测能力。我有一个假设,如果一个人在某段时间内收到了多个报价,那么在收到报价之间的时间间隔可能会有一些预测能力。

第 3 部分:实现

既然数据集已经准备好了,我们就可以开始实现模型了。回到我们的目标,我们想分析有效报价的驱动因素,目标变量是effective_offer

由于我们有 3 种报价类型,因此需要构建 3 种不同的模型。由于我们预测一个提议是否有效,这实际上是一个二元分类监督学习模型。

我决定将简单决策树分类器模型作为基线模型,与集成随机森林分类器模型进行性能比较。我选择决策树作为基线模型的原因是因为我想优先考虑模型的可解释性。回到目标,因为我们打算分析特性的重要性来确定有效报价的驱动因素,所以决策树将为我们的分析提供良好的可解释性。

同时,我还选择了随机森林作为替代模型来比较基线模型,作为对决策树简单集成打包的改进,以提高模型训练的准确性。

在我们继续之前,我们必须确保我们预测的类在每个数据集中是*衡的。

Class breakdown between BOGO, discount and informational offers respectively

我们可以看到,所有三种报价类型的等级很不均衡,但也没有不*衡到会造成问题的程度。因此,我们可以着手实现模型。

关于模型评估和验证的说明:因为所有 3 个模型的类是不*衡的,我决定实现准确性和 f1 分数作为模型评估度量,正如前面已经提到的。

a.模型实现

回顾我们的目标,我们创建了 3 个模型来预测每种类型的优惠的有效性,具体取决于优惠属性和用户统计数据。

我执行了建模通常所需的步骤:

  • 定义目标和特征变量
  • 拆分为训练和测试数据
  • 应用特征缩放器

我定义了模型管道函数来实现我的模型,因为我计划实现 3 个不同的模型;因此,重复实现会更容易。

我使用决策树分类器作为我的基线模型,并使用随机分配参数的随机森林分类器来比较性能。

BOGO 公司提供型号

Results for baseline DecisionTree (DT) classifier model on BOGO offers dataset

Results for RandomForest (RF) classifier model with randomly set parameters on BOGO offers dataset

随机森林分类器(RF)模型的准确性实际上最终略微优于决策树分类器(DT)模型,但总体而言,两种模型的性能大致相同(就准确性而言,分别为 82.14%和 81.77%)。第一次尝试的准确率相当高,超过 80%。我将尝试进一步调整模型,以获得更好的准确性。

然而,就 F1 分数而言,两个模型都低于 80%,随机森林模型与决策树分类器相比表现更差,分别为 75.91%和 79.63%。为了分析这一点,我们必须参考精确度、召回率和 F1 分数的公式:

回忆或敏感度或 TPR(真阳性率):

根据 sklearn 文档,召回直观上是分类器找到所有阳性样本的能力。

全部真阳性中被正确识别为阳性的项目数:真阳性/(真阳性+假阴性)

精度:

根据 sklearn 文档,分类器直观地具有不将阴性样品标记为阳性的能力。

在被识别为阳性的项目总数中,被正确识别为阳性的项目数:真阳性/(真阳性+假阳性)

F1 得分:

因为我的 F-beta 分数是 F1,beta=1,所以我认为召回率和精确度同等重要。

公式由精度和召回率的调和*均值给出:F1 = 2 精度召回率/(精度+召回率)

我们可以看到,DT 的 F1 分数略高于 RF,但都低于准确度。这将表明 DT 模型在不将负面事件错误分类为正面事件方面比 RF 模型做得稍好(意思是,将哪些提议无效的人错误分类为哪些提议有效的人)。

F1 得分与准确性的差异表明,可能存在两个模型都错误地将负面分类为正面的情况,这可能是由于类别的不*衡。但是与 F1 分数相比总体较高的召回率/准确度表明,与预测负面情况(即,要约无效的情况)相比,该模型预测正面情况(即,要约有效的情况)更准确,这在给定不均匀的类别的情况下是可以预期的..

然而,回顾我们的用例,我们可能不太关心这些错误分类,因为我们不介意给人们发送比他们想要的更多的报价;我们不想错过任何一个报价有效的人。

鉴于这种情况,我仍然会选择 RF 型号。

因为我的目标是分析有效报价的驱动因素,所以在我从优化中选择最佳模型后,我将检查模型的功能重要性。

a.ii .折扣优惠模式

我重复上面相同的步骤,但是使用我的 offer_discounts 数据集。

Results for baseline DecisionTree (DT) classifier model on discount offers dataset

Results for RandomForest (RF) classifier model with randomly set parameters on discount offers dataset

这一次,随机森林分类器模型在准确性方面也比决策树分类器有更好的表现(87.23%比 86.72%),F1 得分也更低(81.43%比 82.87%)。

与准确性得分相比,这些模型的 F1 得分总体较低。这可能表明,在某些情况下,两个模型都错误地对负面情况(effective_offer = 0)进行了分类。同样,我对此并不太担心,因为我更关心准确预测阳性病例的模型,所以我宁愿选择更高准确性的模型,其中病例effective_offer=1的 F1 得分更高,我们的 RF 分类器在这方面具有更好的性能(0.9317 比 0.9280)。

a .三.信息优惠模式

offers_info数据集重复上述步骤:

Results for baseline DecisionTree (DT) classifier model on informational offers dataset

Results for RandomForest (RF) classifier model with randomly set parameters on discount offers dataset

与其他两个数据集相比,这些模型的性能更差,两个模型的精度都低于 80%,但 RF 模型的性能仍然更好。F1 得分也更差,为 67.54% RF 分类器,比 DT 模型的 68.66%差。

性能较差的一个潜在原因可能是由于我有一个重要的假设,将转换事件指定为仅在查看要约之后且在指定的持续时间内发生的交易;由于删除了那些不管发生的事务,我可能错过了一些有价值的信息。我们可以从总体样本数据集比其他两个报价的数据集小(大约一半)看出这一点,BOGO 和折扣分别只有大约 5K 个样本,而 10K 只有大约 5K 个样本。

b.精炼

在优化模型时,我将首先尝试对 3 个 RF 模型进行参数调整,然后尝试删除或添加特性来提高模型性能。

b. i .网格搜索发现最佳参数

我决定做 GridSearch 来确定模型的最佳参数。

对于所有三个选项,随机森林模型都有相对较好的性能,所以我使用网格搜索来确定最佳参数。

BOGO:

当我使用最佳参数重新运行 BOGO 数据集的模型时,我获得了以下结果:

RF model results with params from GridSearch

与第一个模型相比:

Comparing results for 1st model with 2nd model for BOGO dataset

RF 模型的准确性略有提高,从 82.14%提高到 82.51%,F1 得分从 75.91%提高到 77.64%。这是一个很好的性能提升,但幅度很小,这表明可能无法通过参数调整来提高模型的性能。

因此,我将不得不探索其他途径来进一步提高模型的性能。

对于折扣:

同时,对于折扣数据集,运行 GridSearchCV 获得了以下参数:

Best parameters for discount offers dataset according to GridSearchCV

使用这些参数实现模型获得了以下结果:

RF model results with params from GridSearch

Comparing results for 1st model with 2nd model for discount dataset

模型的准确率略有提高,从 87.23%提高到 87.47%,F1 评分从 81.43%提高到 82.06%。好的一面是,现在 RF 模型的准确性和 F1 分数都比 DT 模型好。

但是因为增加很少,我们可以再次得出结论,调整参数不会真正显著提高模型的性能。

对于信息优惠:

最后,对于信息性报价数据集,运行 GridSearch 获得了以下参数:

Best parameters for informational offers dataset according to GridSearchCV

RF model results with params from GridSearch

Comparing results for 1st model with 2nd model for informational dataset

我们再次看到 RF 模型的准确性有所提高,从 75.09%提高到 75.30%,F1 分数从 67.54%略微提高到 67.78%。这种改进是最小的,所以我们研究改进模型的特征选择。

b.ii 去除稀疏特征,例如 **amount_invalid**

就特征选择而言,我想试试看移除amount_invalid变量是否会有帮助,我们已经注意到它是稀疏的,因此在预测报价的有效性方面可能没有用处。

我从我的数据准备中删除了该特征,并使用通过 GridSearch 找到的相同最优参数重新训练了该模型,将 DT 模型作为基线。

Comparing model 2 with model 3 for BOGO model

模型准确性和 F1 分数确实提高了,所以我将在模型中去掉 amount_invalid 特征。

Comparing model 2 with model 3 for discount model

模型的准确性实际上增加了,而 F1 模型保持不变。在这种情况下,我还将删除折扣模型的 amount_invalid 特性。

Comparing model 2 with model 3 for informational model

对于 info 模型,模型的准确性实际上降低了,所以我也将保留这个特性。这是意料之中的,因为与其他两个模型相比,该模型已经有了更差的性能,所以与其他模型相比,该模型稍有不足。因此,该模型需要更多的特征来学习更好地预测。

b. iii。删除一级虚拟变量/一键编码

当涉及到热编码时,使用树模型和使用回归模型是有争议的。对于回归分类模型(如逻辑回归),我们通常应移除一个级别的变量,以防止变量之间的多重共线性。一般来说,我们不应该在我这里使用的基于树的模型中遇到这个问题。

然而,关于一个人是否应该这样做还有一些争论。根据一些文章(如这里的)),通常不建议对分类变量进行编码,因为它们会生成稀疏矩阵,导致:

  1. 由此产生的稀疏性实际上确保了连续变量被赋予更高的特征重要性。
  2. 分类变量的单个级别必须满足非常高的标准,以便在树构建的早期被选择进行拆分。这可能会降低预测性能。

在 RF 和 DT 的 scikitlearn 实现中,必须对变量进行编码。因此,我决定测试我的模型性能,如果我放弃一个级别的分类变量(在我的数据中——渠道变量和性别变量),只是为了减少我的模型数据中的稀疏性和噪声。

然而,我发现,总体而言,仅仅通过减少一个级别的分类特征,模型性能并没有太大的改善。

虽然这三个模型都达到了我的基准利率 75%,特别是 BOGO 和折扣模型,我想探索是否可以改善信息模型的性能。

我将暂时把 BOGO 和折扣模型放在一边,因为我对模型的性能很满意。

b. iv。使用多项式特征

由于 info 模型的低精度分数可能是由于模型拟合不足,所以我决定尝试进一步变换特征是否可以提高模型性能。我对 info 模型中的变量应用了多项式特征变换来检查模型性能。

Comparing best info model so far (model 2) with current model 5

我们可以看到,RF 模型的性能实际上略有下降。因此,保持模型不变可能是一个更好的主意。信息报价的最大准确度为 75.30%,这是可以接受的,尽管它没有 BOGO 或折扣报价高。毕竟,我们已经根据持续时间对报价的“影响”做了一些假设。

绘制到目前为止 RF info 模型的训练和测试精度会产生以下图表:

我们可以从上面看到,当我们通过多项式特征为每个模型添加更多变量并移除 amount_invalid 特征时,该模型在训练准确性方面表现得更好。这只是测试精度降低,我们可以看到这是由于过度拟合。

我可以通过使用 RF info model 5 来进一步提高 info model 的准确性和性能,但要添加更多数据,因为我们已经注意到,offers_info数据集的大小是 BOGO 和折扣数据集的一半。因此,最终有了更多的数据和性能调整,删除了不必要的变量和特征转换,有了更多的数据,我可能最终得到的模型性能可能超过 80%。

b .四、关于最佳模式和特性重要性的讨论

现在,我已经完成了对 3 个模型的优化,我们可以检查所有 3 个模型的最佳模型的结果,并检查功能的重要性,以查看产品有效性的主要驱动因素。使用我的best_model函数,我得到了下面的结果数据:

#get best model overall for bogo,discount and info offers
best_model('bogo').append([best_model('discount'),best_model('info')]).transpose()

Model performance for best models

总的来说,我们可以看到,表现最好的模型是第三个模型(使用 GridSearch 查找最佳模型参数并删除 amount_invalid 列),用于预测 BOGO 和折扣优惠的有效性,而表现最好的信息优惠模型是在执行 GridSearch 查找最佳参数之后。

为了找到有效报价的最有影响力的驱动因素,我们可以检查上面我们的最佳模型的特征重要性。

针对 BOGO 车型:

对于折扣型号:

对于信息模型:

检查功能重要性以分析有效优惠的主要驱动因素,我们可以看到,在所有三个方面,有效优惠的最重要驱动因素是会员资格。然而,第二个最重要的特点是三种型号各不相同。

对于 BOGO 要约,成员任期是最重要的特征,其他变量在比例上要小得多。收入、年龄和 offer_received_cnt 是第 2、3、4 位最重要的特征,但所占比例很小。

对于折扣优惠,在会员资格之后,年龄和收入是下一个最重要的变量。但是比例还是很小的。

与 BOGO 和折扣模型相比,信息优惠模型的特征重要性更加分散,收入是第二重要的特征。年龄是第三位,有趣的是移动渠道是第四位。

第 4 部分:侧面探索

a.探究第 3 组和第 4 组用户——不看任何优惠就购买的人

我们之前将第 3 组和第 4 组的人描述为不管是否看到任何报价都会购买的人。现在我们可以做一些探索性的分析,看看这个用户群是由什么样的人组成的。

人工智能数据准备

观察第 3 组和第 4 组的人与第 1 组和第 2 组的人的对比会很有趣,所以我决定在这三组人之间进行比较。

我将来自三种报价类型的所有组的数据附加在一起,然后通过可视化比较每个组的特征。

我还清除了数据集的空值,类似于上面为建模而准备的数据集。

Size of each group of customers in overall dataset

比较 3 个组的大小,我们可以看到组 1 最大,而组 2 最小,这并不奇怪,因为我们已经看到我们的数据集中的类不*衡,有利于正类(即effective_offers=1)。同时,对于第 3 组和第 4 组的人来说,也有相当多的人,比第 2 组的人多。

a .二.人口特征探索

同时,为了有效地比较各组,我将各组一起可视化。

首先,我们可以探讨 3 个群体之间的收入分配。

在这三个部分中,大多数人都属于中等收入范围(5 万-10 万)。这三个部分之间的收入分配相对相似。

三个组之间的年龄分布看起来也相对相似,大多数人在 40-80 岁之间。

第二组是根本没有消费的人,因为优惠对他们无效,因此他们不在图表中。但对于第 1 组和 3+4 组,我们可以看到花费的金额相对相似,只是第 1 组的人花费略多。这是意料之中的,因为我们可能会认为,这些优惠设法刺激他们购买更多,因此他们的总体支出增加了。

会员任期的分布在 3 个细分市场之间看起来也很相似,大多数人的任期在 0-700 天之间。至少在目前提供的数据中,这三个组之间似乎没有太多的人口统计学特征差异。

b .潜力一体机型号

出于好奇,我想知道如果要约类型作为一个分类特征包含在内,我们是否可以预测要约的有效性。优惠的类型会影响用户的反应吗?

DT baseline model for all-in-one dataset

RF model for all-in-one dataset

在初始化和运行模型之后,我对照一体化模型检查了我之前构建的所有三个模型的性能。

将每种优惠类型的 3 个最佳型号的性能与 all_in_one 型号进行比较,我们可以看出,all-in-one 型号不如 RF bogo 和 discount 型号,大约略好于 info 型号。这可能是由于信息模型拉低了性能,导致一体化模型的准确性降低。我怀疑,如果我们将一体化模型的性能分解为只看它预测信息提供类型的有效性的能力,它也将比它预测其他 2 种类型的性能差。

如果我们退一步,从全局来看,3 个独立的模型具有更高的精度比一个一体化模型更有用。这是因为 BOGO 和折扣优惠实际上旨在通过一些促销成本来推动销售,而信息性优惠基本上是免费的,没有成本,如果它们能够推动销售,那将是一种奖励。

因此,我实际上建议 3 个独立的模型更有用。

c .给定一个有效的报价,我们能预测某人会花多少钱吗?

除了一体化模型之外,由于我们已经保存了有效交易的数据集,我很想知道我是否可以建立一个回归模型来预测某人在给定有效报价的情况下会花多少钱。我可以为每种优惠类型分别建立一个模型来预测他们的消费,但是我很想知道优惠类型是否也会决定用户的消费水*。

Comparing results for both regression models

然而,回归模型在预测支出金额方面表现不佳。根据我们第 1 组客户的当前数据,似乎没有足够的信息来预测该优惠类型可以推动的金额。我们可以看到决策树回归模型确实过度拟合了数据,训练分数非常高,但测试分数低于标准。同时,线性回归模型(具有岭/l2 正则化)也显示了特征和目标变量之间的最小相关性。这个模型确实对数据拟合不足。

如果我再次根据优惠类型将模型分成 3 个不同的模型,我可能会获得更好的性能;或者甚至尝试包含不受影响的/无效的事务,但这可能是另一次的探索。

第五部分:结论

总的来说,我发现这个项目很有挑战性,主要是因为transcript数据集中的数据结构。我从两个商业问题开始:

  1. 星巴克应用程序上有效报价的主要驱动因素是什么?
  2. 提供的数据,即报价特征和用户人口统计数据,能否预测用户是否会接受报价?

a.反射

人工智能问题 1 调查结果

对于问题 1,所有 3 个模型给出的特征重要性是,成员的任期是要约有效性的最大预测因素。进一步的研究将能够表明什么样的*均任期天数将导致有效的 BOGO 要约。

对于所有三个模型,前三个变量是相同的——成员任期、收入和年龄。但是,收入和年龄会根据优惠类型改变订单。

对于 BOGO 和折扣优惠,特征重要性的分布相对相等。然而,对于信息提供,分布稍微*衡一些,收入是第二重要的变量。

二.问题 2 调查结果

我决定使用 3 个独立的模型来预测每种优惠类型的有效性,最终 BOGO 和折扣模型的准确性较好(BOGO 为 82.83%,折扣为 87.35%),而信息性优惠的准确性稍差(75.3%)。然而,在商业环境中,我认为 75%是可以接受的,至于信息性报价,通知用户产品是没有成本的。

与此同时,对于 BOGO 和折扣模型,我对 80%及以上的准确性非常满意,因为在向人们显示报价的商业环境中,即使模型错误分类了一些,整体收入的增加也可能证明这几个错误是正确的。

b.主要挑战和潜在改进

在分析和构建机器学习模型来回答上述问题时,我对主要挑战和发现的思考如下:

为交易分配 offer _ ids 的 b.i .归属框架

为了回答问题 1,我必须首先使用交易记录来定义“有效要约”的含义。这被证明是项目中最棘手的部分。我必须定义一个有效转化的漏斗,因为我们有有效和无效转化的数据。因此,我根据每个人之前发生的事件,为转换事件(offer completedtransaction事件)设计了一个归因模型。

最后,我不得不根据用户在脚本数据中的行为,将他们分成 4 个不同的池:

  • 第 1 组:受优惠影响并因此购买/完成优惠的人(成功/有效转换优惠)
  • 第 2 组:收到要约但未受影响的人,因此没有转换事件(要约的无效转换)
  • 第三组:有转化事件但实际上没有受到要约影响的人
  • 第 4 组:收到提议但没有意见或行动的人

即使在将组分开后,根据事务数据将人分配到组 3 也是一个挑战。我必须先定义事件空间,在这个空间中,正确的事件序列将会发生,然后我才能为事务分配一个 offer id(它没有 offer_id),本质上是设计一个基于事件/序列的属性窗口。

在将转化归因于特定的优惠之后,剩下的数据准备和清理就相对简单了。我很高兴没有很多丢失的值,分类变量的准备也相对简单。

b.ii .特征工程

我决定做一些基本的特征工程,因为我发现这个模型在这个项目中的第一次尝试中有点不足,所以我后来添加了特征工程部分。它略微提高了模型的性能,我从became_member_on列中设计出的 membership _ tension 特性最终成为最重要的预测变量。

然而,总的来说,我发现我想不出使用时间数据的额外功能,即使我有预感,收到要约的时间可能对确定它是否有效有很大影响。

b .三.模式实施决定

根据我对问题陈述的定义,我决定根据报价类型建立 3 个独立的模型,因为我想发现什么会推动有效的报价,我认为通过将数据分成报价类型来消除数据中的干扰更有意义。我的决定最终是一个相当好的决定,因为与一体化模型的总体分数相比,单一 BOGO 和折扣模型在测试分数中获得了良好的表现。

对于信息模型,准确性稍差,因为我们有更少的记录(BOGO 和折扣模型的一半)。如上所述,我相信如果我们有更多的数据,我可以获得更高的准确性,因为在我决定改进模型拟合(如添加多项式特征和移除“有噪声”的特征,如 amount_invalid 特征)时,训练和测试得分之间出现了明显的背离模式。由于数据有限,我的决策以模型过度拟合而告终,因此我相信更多的数据会有助于模型的准确性。

关于模型选择的补充说明—我选择了基于树的模型,因为我想评估特征的重要性,但我可以通过测试参数/回归模型(例如,用于分类任务的逻辑回归)来进一步扩展这项研究。假设回归模型和基于树的模型具有不同的数据分析方式,那么这两种模型的系数权重可能会与基于树的模型的特征重要性形成对比。与本研究中的情况相反,功能membership_tenure_days可能不是权重最高的功能。

b .四、探索不同客户群的人口统计

我很想知道第 3 组和第 4 组的特点是什么,他们是完全不受报价影响的客户。然而,在将他们的特征与第 1 组和第 2 组进行比较后,我看不出他们在人口统计学上有任何显著差异。

我希望有更多的数据来了解为什么这部分客户往往不受优惠的影响,以便提出有用的建议,告诉他们如何给他们提供良好的客户体验,即使我们不向他们提供任何优惠。

b.v .模型在有效报价下预测花费金额的准确性

我出于好奇建立了一个回归模型,看看我们能否预测用户的消费金额,因为他们会受到优惠的有效影响。这样做的动机是,如果我们能预测给定一个报价,某人会花多少钱,也许我们就能评估哪个报价能带来最多的收入。

然而,我的模型发现,所提供的功能(即,应用程序用户的特征和人口统计数据)与每个用户的消费金额之间几乎没有相关性。这些功能还不足以预测每个用户的花费。也许如果我们也有一个报价的价值,例如,一个折扣报价,以美元计算的折扣价值,也许我们能够更好地预测。

也许我可以把它们分成 3 个不同的模型,用于 3 种报价类型,就像我对二元分类模型所做的那样,以便得到更好的结果。然而,考虑到这只是一种好奇,我想探究报价类型是否是一个具有统计显著性的预测特征,我为此实例构建了一个一体化模型。如果有更多的时间和数据,这将值得进一步探索。

c.最后的想法

transcript数据集的顺序、基于事件的性质带来了最大的挑战,但它在应用程序数据或许多数字分析数据(包括 web 在内的交易数据)中很常见。因此,我发现这次挑战是一次有益的经历。

如果提供更多种类的产品数据以及产品价格,这个项目肯定可以进一步扩大。它可以扩展到更长时间的客户细分练习,以确定偏好某些优惠类型或产品的客户的属性,甚至预测优惠的相关价格范围。

然而,数据准备和清理会更具挑战性,因此在这种情况下,我很感激所提供的数据更加有限和可控。我对我的车型在此范围内的表现感到满意。

如上所述,这篇文章虽然包含了理解所需要的代码输出,但缺少项目中的详尽细节。如果你想进一步了解我的代码和分析,可以点击这里的链接。

使用统计数据进行数据驱动的决策

原文:https://towardsdatascience.com/using-statistics-for-data-driven-decisions-5df26043608b?source=collection_archive---------4-----------------------

需要做出决定是不确定性的明显表现。当存在不确定性时,就存在风险,我们都想降低风险。数据分析是我们用来减少不确定性的工具之一。

随着数字时代的到来,数据量超出了我们所有人的处理能力,每个人都可以访问某种类型的数据。不幸的是,并不是每个人都有足够的知识来创建和使用数据,所以有很多错误的见解/信息被有意或无意地创造出来。我们需要确保我们不是在试图验证先入为主的想法。先入为主的想法会产生偏见,而偏见会损害你的分析。我们,分析专家,特别是当我们年轻时,我们可能会被我们的高级经理陷入这种情况,但我们需要小心做我们应该做的事情。我们都有一个最高目标,那就是尽可能多地获得真相。我们都想找到帮助我们更好地理解数据集的秘密模式。不要让别人把你引向欺骗的道路。

数据挖掘试图发现有意义的模式,统计试图确认这些发现的模式。如果你思考数据和信息,你会意识到它一直在变化。每一秒都有新的点击,新的客户,新的销售等等。当我们从现有的数据分析中得出一些结论时,我们能确定我们能从新的数据中得出同样的结论吗?这就是进退两难的境地…

有一点我们必须永远记住:即使我们在分析所有的流量、所有的客户、所有的人口,我们也总是在处理样本数据。因为每次我们从数据中得出结论,都属于那个特定的瞬间。我们真的不知道下一分钟,或者下一天,或者下一年,会不会出现同样的结论。通过数据分析,我们都在尝试预测未来。因此,如果我们想要进行预测,有时与较小的团队合作也是有意义的。

如果没有统计学背景或学历,可以从简单的统计学入手。我会从的零假设开始。它只是暗示观察到的差异仅仅是由于偶然。这项技术的目的是确保我们不会简单地自动接受任何表面价值的差异。我们想确保这个事实不会被推翻。

据(https://explorable.com/null-hypothesis)

零假设 (H 0)是研究者试图反驳、拒绝或取消的假设“无效”通常指的是对某事物的普遍看法,而另一种假设则是研究者真正认为是某一现象的原因。

为了量化零假设,我们使用 P 值

据(http://www.statsdirect.com/help/basics/p_values.htm)

当研究问题的零假设(H 0)为真时, P 值或计算概率是发现观察到的或更极端的结果的概率——“极端”的定义取决于假设如何被检验。

如果 p 值很大,这意味着观察到的差异可能更多,这是预期的,零假设为真,意味着实际上没有真正的差异

如果 p 值很小,观察到的差异可能是真实的,因为这不是预期的。例如,如果 p 为 5%,这意味着观察到的差异可能在 95%的置信水*内可信。这 95%称为 q 值。

虽然谷歌分析帮助每个人访问你在线资产的数据,但它也对分析和人才产生了错误的假设。一些可以访问谷歌分析的人开始填写 Linkedin 的职位描述,成为数据分析师或分析大师。由于许多高级管理人员是数据概念的新手,他们一直在雇佣那些只能从谷歌分析中阅读的人,并对他们抱有期望。

当数据分析没有得到统计数据的支持时,您可能会遇到严重的问题,或者您可能不会得到任何有意义的结果。如果你是一名新的分析师,或者你是一名基于数据做出决策的经理,你应该通过统计测试来检验所有重要的见解。

更多即将推出…

西贝尔·阿克切卡亚

同时发布于:http://www . webanalyticspower . com/en/2017/09/using-statistics-for-data-driven-decisions/

使用 Tableau 可视化维基百科上最棒的视频游戏列表

原文:https://towardsdatascience.com/using-tableau-to-visualize-the-list-of-greatest-video-games-from-wikipedia-eee804459f29?source=collection_archive---------1-----------------------

几周前,我在博客上发布了一篇文章,回顾了我对一个维基百科页面的抓取,该页面列出了有史以来最棒的视频游戏。与此同时,当我忙于其他事业时,我想重温我收集的信息,看看我是否能以有趣的方式将数据可视化,并练习我的紧急画面技巧。

Solid Snake and Liquid Snake from Metal Gear Solid (1998). Original artwork by Yoji Shinkawa

为此,我使用了 Tableau Public ,这是一个免费下载的应用程序,具有相当的深度。使用这个程序的一个注意事项是,您需要创建一个 Tableau 配置文件来保存您创建的任何可视化效果。这些将由 Tableau 公共网站托管,因此在保存您的作品之前,您需要了解与您的数据相关的任何专有问题。

简要回顾一下数据,我在这个过程中使用的最伟大的游戏列表包括 1978 年至 2013 年期间发布的 100 款不同的游戏。这些数据包括每款游戏的发布年份、游戏名称、发布的原始*台/主机、游戏类型以及游戏出现在“最伟大游戏”列表中的次数。以下是数据表内容的部分快照:

Basic structure of the “Greatest Games” data table.

我最初在 pandas 中将这些信息保存为数据帧,然后将数据转换并保存为本地 csv 文件。Tableau Public 在可以处理的文件类型方面非常灵活。它可以导入或连接到单个文件(excel,JSON 等。)或远程数据服务器。要处理 csv 文件,您需要从开始菜单中选择“文本文件”。

Tableau Public 的另一个重要特性是,它可以直观地读取和理解每个数据列中存在的数据类型(例如,分类、连续、地理空间),这使得“拖放式”可视化更容易生成。

The data structure of my csv file, as interpreted by Tableau. Categorical columns are labeled “Abc”, while continuous variables are labeled “#”. I generated an additional column of information “Console Developer” to ease some of my later visualizations.

创建任何给定的绘图时,只需打开一个新的工作表(参见 Tableau 窗口的左下角),然后将感兴趣的变量拖到它们各自的列、行或标记字段中。这里有几个额外的字段可以以有趣的方式使用,我不会在这里深入讨论。(例如,左上角的“pages”字段可与时间序列数据一起使用,创建一种数据活页本,显示您的时间数据的每一天/月/年。)

下面快速浏览一下 Tableau 窗口,其中一些数据已经放置到位。该图在 x 轴上描绘了年份,在 y 轴上描绘了最伟大的游戏列表出现的数量,游戏作为每个单独的点,由原始*台着色。

虽然 Medium 还不允许将 Tableau 可视化直接嵌入到帖子中,但我可以发布图像捕获,然后在图像中嵌入链接,将您带到 Tableau 公共网站上这些可视化的交互版本。(对于其他介质用户,可以在 Mac 上使用 Command+K,在 PC 上使用 Control+K,在图片上嵌入链接。)

下面是上述情节的一个更加完美的版本,它链接到交互式 Tableau 版本:

使用该链接,你可以将光标悬停在图中的任何数据点上,以显示每个游戏的名称、发布年份和原始*台,以及它出现在最伟大游戏列表中的数量(根据维基百科)。

乍一看,这个最初的情节非常有趣。我们可以看到,在 90 年代中后期和 21 世纪初,游戏数量和最伟大游戏列表的数量呈现出总体上升趋势,在 21 世纪中期和以后再次下降。这可能部分是由于历史偏见,90 年代末和 21 世纪初出现在足够远的距离,以至于流行观点已经就这些游戏的伟大之处达成一致,而其他更现代的经典游戏,如《最后的我们》,自发布以来还没有足够的时间巩固它们在各种最伟大游戏列表中的位置。

虽然一簇簇的点可能有些说明问题,但使用分段条形图可以更容易地查看每年最伟大游戏的数量。探索互动的情节,游戏出现在每年最伟大的游戏名单上的数量下降的顺序。:

当确定过去几十年中每年发布的“最伟大的游戏”的数量时,从表面上看这个图表要容易得多。很明显,1998 年和 2001 年是这里最突出的年份。仅在 1998 年就出现了诸如《塞尔达传说:时间之笛》、《合金装备 2:自由之子》、《口袋妖怪红》、《灵魂口径》、《星际争霸》、《半条命》和《生化危机 2》等开创性经典作品,而 2001 年则出现了诸如《光环:战斗进化》、《超级粉碎兄弟:肉搏》、《合金装备 2:自由之子》、《最终幻想 X》、《侠盗猎车手 3》和《寂静岭 2》等其他具有历史意义的重磅作品。

在查看了按年度发布的最伟大游戏的数量后,我想更仔细地看看由主机发布的游戏的数量:

通过发布的原始控制台绘制游戏对于 PC 和街机游戏来说有些复杂。这在一定程度上是因为这些*台在某种程度上超越了一代游戏机的概念——在家用游戏机被广泛采用之前,街机*台显然占据了主导地位,而个人电脑是一种不受其他家用游戏机占据的不同时间段限制的永恒*台。不过,有趣的是,在最棒的游戏数量排名中,Playstation 游戏机位列前六名。有趣的是,看看有多少任天堂创造的游戏机出现在这个列表中。

为了让 PC 和 Arcade 拥有*等的竞争环境,我按照主机开发商对游戏进行了分类,以了解不同的主机开发商(如索尼、微软、任天堂)在所有不同*台(如 Playstation 1、Playstation 2、Playstation 3 与 NES、SNES、N64 等)上的表现。)

我决定按照列表中提及次数的降序来绘制每款游戏,并由主机开发人员进行着色:(注意,点击交互式绘图,您可以滚动到右侧查看所有列出的游戏)

我认为有趣的是,尽管索尼的个人游戏机比大多数任天堂*台表现更好,但任天堂开发的游戏在最受好评的游戏中表现强劲,被提到的最伟大游戏数量也很多。

我希望你喜欢点击这些最伟大的游戏的可视化。我真的很喜欢在和 Tableau 一起工作的短暂时间里制作它们。我还希望您已经了解了 Tableau 的工作原理,以及如果您决定尝试一下,它会有多友好。

如果你有任何反馈,请告诉我!

使用 Tensorflow 对象检测控制第一人称射击游戏

原文:https://towardsdatascience.com/using-tensorflow-object-detection-to-control-first-person-shooter-games-c2c7f1daf2e9?source=collection_archive---------8-----------------------

在这篇文章中,我将解释我如何使用 tensorflow 的对象检测模型来玩经典的 FPS 游戏《反恐精英》。

Playing Counter Strike with my webcam recording and a Tensorflow Object Detection model.

不久前,我偶然发现了这个非常有趣的项目,在这个项目中,文章作者使用一个网络摄像头来玩名为真人快打的经典格斗游戏。他利用卷积神经网络和递归神经网络的组合来从他的网络摄像头记录中识别踢和打的动作。然后,他将模型的预测转化为游戏中要采取的适当行动。玩游戏的方式真的很酷!

Playing Mortal Kombat with webcam and deep learning. Original article can be found here.

以此为灵感,我创建了一个类似的控制器界面,可以使用 Tensorflow 对象检测模型的预测来玩第一人称射击游戏。

这个项目的代码可以在我的 Github 页面上找到,下面也有链接。

[## ChintanTrivedi/DeepGamingAI _ FPS

一款使用网络摄像头和深度学习来玩游戏的 FPS 游戏控制器——ChintanTrivedi/DeepGamingAI _ FPS

github.com](https://github.com/ChintanTrivedi/DeepGamingAI_FPS)

该控制器设计用于处理游戏中的以下动作:-

1。瞄准枪

首先,为了在游戏中环视四周,我在一个网球上使用了对象检测。根据屏幕上检测到的球的位置,我们可以设置鼠标的位置,这反过来控制我们的玩家在游戏中的目标。

2。移动播放器

接下来,为了指示玩家在游戏中向前移动,我正在使用我的食指的检测。当手指指向上方时,玩家向前移动,再次放下手指会停止玩家的移动。

3。射击枪

这里支持的第三个动作是开枪。因为在瞄准和移动的时候两只手都用光了,所以我用张嘴的姿势来控制枪的射击。

目标检测模型

Image Source

这里用于物体检测的模型教程是 MobileNet 结合单镜头多盒检测器 (SSD)进行图像定位。它被训练成各种各样的图像,比如网球、竖起的手指和张着嘴的牙齿。它设法以合理的速度运行,使得实时使用轻量级模型来控制我们的游戏成为可能。

模型性能

就模型的性能而言,玩游戏时手指和牙齿的检测似乎相当可靠。主要的问题是要把枪准确地瞄准我们想要的地方,因为模型运行的帧率比游戏低得多,因此鼠标的移动是跳动的,不是很*滑。此外,对朝向图像边缘的球的检测很差,使其不可靠。这个问题可以通过调整模型来解决,以可靠地检测离摄像头稍远的物体,这样我们就有足够的空间来移动网球,从而更好地控制我们的目标。

这款机型的游戏内性能结果可以在我的 YouTube 频道上找到,下面嵌入了视频。

结论

我觉得只用网络摄像头而没有额外硬件来控制游戏的整体体验仍然是一个非常诱人的概念。由于深度学习模型的进步,这已经变得非常可能。这种控制机制的实际实现需要完善,以便取代玩这些游戏的更常规的方式。我可以看到这个想法的完美实现是玩 FPS 游戏的一种有趣的方式。

感谢您的阅读!如果你喜欢这篇文章,请在媒体、 GitHub 上关注我,或者订阅我的 YouTube 频道。

使用张量流对象检测进行逐像素分类

原文:https://towardsdatascience.com/using-tensorflow-object-detection-to-do-pixel-wise-classification-702bf2605182?source=collection_archive---------1-----------------------

用数据做酷事!

过去,我使用 Tensorflow 对象检测 API 来实现对象检测,输出是图像中不同感兴趣对象周围的边界框。更多请看我的文章。Tensorflow 最*增加了新功能,现在我们可以扩展 API 来逐个像素地确定感兴趣对象的位置。请参见下面的示例:

Tensorflow Object Detection Mask RCNN

代码在我的 Github 上。

实例分割

实例分割是对象检测的扩展,其中二进制掩码(即对象与背景)与每个边界框相关联。这允许关于框内对象范围的更细粒度的信息。

那么我们什么时候需要这种额外的粒度呢?我想到的一些例子有:

I)自动驾驶汽车——可能需要知道另一辆汽车在路上的确切位置,或者过马路的人的位置

ii)机器人系统——如果机器人知道两个部件的确切位置,那么它们将会表现得更好

有几种实现实例分割的算法,但是 Tensorflow 对象检测 API 使用的算法是 Mask RCNN。

屏蔽 RCNN

让我们从简单介绍一下 Mask RCNN 开始。

Mask RCNN Architecture

快速 RCNN 是一种用于目标检测的非常好的算法。更快的 R-CNN 由两个阶段组成。第一阶段,称为区域提议网络(RPN),提议候选对象包围盒。第二阶段本质上是快速 R-CNN,使用 RoIPool 从每个候选框中提取特征,并执行分类和包围盒回归。这两个阶段所使用的特征可以被共享以用于更快的推断。

屏蔽 R-CNN 在概念上很简单:更快的 R-CNN 对每个候选对象有两个输出,一个类标签和一个边界框偏移量;为此,我们添加了第三个分支,输出对象遮罩—这是一个二进制遮罩,指示对象在边界框中的像素位置。但是额外的遮罩输出不同于类和框输出,需要提取对象的更精细的空间布局。为此,RCNN 使用下面描述的完全卷积网络 k (FCN)。

Fully Convolutional Network Architecture

FCN 是一种流行的语义分割算法。该模型使用各种卷积块和最大池层,首先将图像解压缩到其原始大小的 1/32。然后,它在这个粒度级别上进行分类预测。最后,它使用采样和反卷积层来调整图像的大小到原始尺寸。

简而言之,我们可以说 Mask RCNN 将两种网络——更快的 RCNN 和 FCN——结合在一个大型架构中。模型的损失函数是进行分类、生成包围盒和生成掩模的总损失。

掩模 RCNN 有几个额外的改进,使它比 FCN 更准确。你可以在他们的论文中读到更多关于他们的信息。

实施

图像测试

为了在图像上测试这个模型,你可以利用 tensorflow 网站上分享的代码。我测试了他们最轻量级的型号——mask _ rcnn _ inception _ v2 _ coco。下载模型升级到 tensorflow 1.5 就行了(这个很重要!).请参见下面的示例结果:

Mask RCNN on Kites Image

视频测试

对我来说,更有趣的练习是在 you tube 的样本视频上运行模型。我用 keepvid 从 you tube 下载了几个视频。我喜欢处理视频文件的图书馆电影。

主要步骤是:

  • 使用 VideoFileClip 函数从视频中提取每一帧
  • fl_image 函数是一个很棒的函数,它可以获取一个图像并用修改后的图像替换它。我用这个对从视频中提取的每张图像进行物体检测
  • 最后将所有修改后的剪辑图像组合成一个新的视频

你可以在我的 Github 上找到完整的代码。

接下来的步骤

关于进一步探索这个 API 的几个额外想法:

  • 尝试更精确但开销大的模型,看看它们能带来多大的不同
  • 使用 API 在自定义数据集上训练掩码 RCNN。这是我接下来要做的事情。

给我一个❤️,如果你喜欢这个职位:)希望你拉代码,并尝试自己。

我有自己的深度学习咨询公司,喜欢研究有趣的问题。我已经帮助许多初创公司部署了基于人工智能的创新解决方案。请到 http://deeplearninganalytics.org/的来看看我们。

你也可以在https://medium.com/@priya.dwivedi看到我的其他作品

如果你有一个我们可以合作的项目,请通过我的网站或 info@deeplearninganalytics.org 联系我

参考文献:

  • 口罩 RCNN 纸
  • 谷歌 Tensorflow 物体检测 Github
  • COCO 数据集
  • 了解黑白实例切分和语义切分的区别
  • 非常好的解释屏蔽 RCNN

使用 tf。在 TensorFlow 中打印()

原文:https://towardsdatascience.com/using-tf-print-in-tensorflow-aa26e1cff11e?source=collection_archive---------0-----------------------

我听说你想印一些张量。

我知道你每次都以正确的方式使用调试器,并且永远不会使用 print 语句来调试你的代码。对吗?

因为如果您这样做了,您可能会发现 TensorFlow 的Print语句与典型的 print 语句不太一样。

今天我将展示 TensorFlow 的打印语句是如何工作的,以及如何最大限度地利用它们,希望能帮你解决一些困惑。

TensorFlow 打印

在编写 TensorFlow 代码时,有几种方法可以将内容打印出来。当然,还有经典的 Python 内置的print(或者函数print(),如果我们是 Python 3 的话)。然后还有 TensorFlow 的打印功能,tf.Print(注意大写的P)。

当使用 TensorFlow 时,重要的是要记住一切最终都是图形计算。这意味着如果您使用 Python 的print打印 TensorFlow 操作,它将简单地显示该操作的描述,因为还没有任何值通过它传递。如果已知的话,它通常还会显示该节点中预期的维度。

Hmm, where are the values? At least we have the shape and type 😃

如果你想打印执行时流经图形特定部分的,那么我们需要使用tf.Print

构建您的打印节点

我们通常认为打印是我们在事情发生后添加的东西,让它运行,然后回到我们正常的运营流程。在 TensorFlow 中,只有图中需要执行来计算输出的节点才会被执行。因此,如果您的图形中有一个“悬空”打印节点,它将不会被执行。

那我们该怎么办?我们需要将打印调用拼接到图形本身中,就像这样:

这在代码中的体现方式是将 Print 调用作为其第一个参数传递给作为其“输入”的节点,然后将返回值tf.Print赋给一个变量,该变量将作为图中后面节点的输入,从而将 Print 语句串行链接到操作流中。(实际使用这个返回的节点是至关重要的,因为如果不使用,它就会悬空。)

虽然 Print 语句不做任何计算,只是向前传递张量,但它确实打印了所需的节点,这是一个副作用。

另一个有点不同于我们在 print 语句中看到的行为是,我们引入到图中的 Print 节点仅仅是设置 Print 语句何时发生,即何时到达计算图中的节点。但是,对打印的内容没有太多限制。

也就是说,它只是在图中标记您希望打印语句出现的位置,但是您可以打印图中它可以访问的任何节点。这是调用tf.Print的第二个参数:要打印的节点数组。通常我们只使用同一个节点作为第一个参数,也就是输入,但是如果我们愿意,我们可以在输出中包含更多的节点。

还有第三个论点,一个信息。这允许您在打印节点之前预先考虑一些字符串,因此您可以很容易地在日志中找到给定的 print 语句。

付诸实践

简单地说,tf.Print就是这样。但是你可以在哪里利用 tf 呢?在代码中打印?

经常发现自己在用 tf。在我的输入函数中打印,以调试传递到我的训练循环中的确切内容。这里仅仅使用 Python print是不够的,因为它只会在构造输入函数图时打印一次。

相反,我们将介绍 tf。打印对输入函数数据管道的调用。请注意,我们只是打印了作为输入传入的相同值,但是您当然也可以打印其他节点。

一些更多的建议

请注意,打印输出显示在我的 Jupyter 笔记本控制台的 stderr 中,而不是作为笔记本本身的输出。搜索打印输出时,请记住这一点!

另一个警告:如果你使用 tf。在你的输入函数中,一定要限制你传入的数据量,否则你可能会滚动一个很长的控制台窗口:)

TensorFlow 的打印语句在许多方面都不是典型的打印语句,但当您需要查看图形中流动的张量时,它可以发挥很大的作用。

感谢阅读本集云 AI 冒险。如果你喜欢这个系列,请为这篇文章鼓掌让我知道。如果你想要更多的机器学习动作,一定要关注 Medium 上的 me 或者订阅 YouTube 频道来观看未来的剧集。更多剧集即将推出!

现在,看看 TensorFlow 的打印语句如何帮助您更清楚地了解您的机器学习是如何运行的!

使用神经网络背后的度量来预测软件进化

原文:https://towardsdatascience.com/using-the-proprieties-behind-the-neural-networks-zoo-for-predicting-software-evolution-eda24632966a?source=collection_archive---------9-----------------------

阿西莫夫研究所发表了这篇文章,向我们展示了下图所示的不同种类的网络。神经网络现在很热门,但以这种方式表示知识的想法来自二十世纪,当时逻辑学家有一个想法,即使用图通过构建顶点和边来形式化两个集合的映射[1],以便对形式知识进行建模。最早的形式被称为存在图,由哲学家查尔斯·桑德斯·皮尔士 发明,作为符号逻辑的线性符号的替代:皮尔士对有机化学中的分子图印象深刻,认为逻辑的图形符号可以简化推理规则。皮尔斯的洞察力卓有成效,许多类型的图表今天被用来建模知识。随着人工智能的发展,语义图不仅被用来显示概念,如认知图[2],[3],而且被用来"以抽象的形式捕获人类知识,以便于计算机程序对其进行处理"[4]。经验图表结合了知识和数据,定性和定量项目。

source: Asimov Institute

使用图度量预测软件演化

在这篇文章 [5]中,他们使用图来理解软件演化,并构建促进其开发和维护的预测器。为了实现这个目标,他们创建了基于图形的模型,这些模型捕获了 11 个开源软件系统的几个图形度量。研究结果表明,这些模型可以检测结构变化,可以预测错误的严重性,减少维护工作,并改善未来的版本。这篇论文很重要,因为它是第一篇使用动态图来跟踪软件发展的论文。

他们接受源代码仓库和缺陷跟踪系统中的图模型的输入。然后,他们构建图形:他们定义图形度量(表 1)并评估每个软件的属性,接下来他们绘制图形,显示这些属性在软件的每个新版本中的演变(表 2)。最后,他们证明他们的假设,并发展预测。

Table 1. Graph Metrics. One example when it level of the metric is high, another when the level is low

图形构造可以从两个来源获取数据:基于代码的图形或开发者协作图形。第一个来源与软件每个版本中使用的功能和模块有关。当它只接受函数时,它是一个"调用图,当它接受函数及其模块时,它是一个调用"模块协作图。大部分实验工作都是通过“调用图”方法论来完成的。第二个来源是基于随着软件的发展,开发人员如何交流。如果开发者之间的联系仅依赖于解决 bug 问题,则称之为“基于 bug 的开发者协作”,但如果它还依赖于除 Bug 修复之外的事件,则称之为“基于提交的开发者协作”。实验结果显示在表 2 中,对于每个应用程序,它显示了度量如何随时间演变,以及这些变化如何影响软件工程方面。

Table 2. Adapted from Bhattacharya’s paper: Graph-Based Analysis and Prediction for Software Evolution

总的来说,这个结果表明软件的进化遵循共同的规律。图度量揭示了软件发展中的重要事件,例如关键时刻,或者代码重构。他们的方法使用节点等级来识别错误的严重性。他们发现在节点等级和 bug 严重性之间有很高的相关性(0.6–0.86),这意味着节点等级可以预测 bug 严重性,并可以识别关键功能和模块。然而,节点度并不能很好地预测 bug 的严重性。此外,当模块的模块化比率增加时,相关的维护工作也会减少。这意味着更好内聚性(模块内调用)和更低的耦合性(模块间调用)将改进软件结构。此外,基于 Bug 的开发人员协作图显示,编辑距离的增加会增加缺陷数量。这意味着合作者之间更密切的关系将提高开发人员的生产力和软件质量。

这项工作开发了一种使用图分析来揭示软件过程的关键属性的方法。这些属性在图形度量中暴露出来,揭示了软件结构和演化中的差异和相似之处。它们还捕获重要的度量来预测软件生命周期中的事件:节点等级可用于预测 bug 严重性,模块比率用于预测维护工作,编辑距离用于预测软件质量。

这项研究可以应用于其他复杂的系统和过程,例如供应链管理。可以在参与者和活动之间构建图表,然后可以研究图表的演变,以检测参与者做出挑战性决策的点(具有高节点排名的节点),并帮助他们做出更好的选择。此外,通过寻求增加供应链管理图的模块化比率,可以提高供应链的生产率,通过减少编辑距离也可以提高质量。

[1] R. Diestel,图论(数学研究生教材)。美国纽约:施普林格出版社,2000 年。

[2] J. F. Sowa,“从概念图生成语言”, Comput。数学。附申请,第 9 卷,第 1 期,第 29-43 页,1983 年。

[3] W. H. Warren,D. B. Rothman,B. H. Schnapp,J. D. Ericson,《虚拟空间中的虫洞:从认知地图到认知图》,认知,第 166 卷,第 152–163 页,2017 年。

[4] R. J. Brachman,“概念中有什么:语义网络的结构基础”。j .曼。马赫。种马。,第 9 卷,第 2 期,第 127-152 页,1977 年。

[5] P. Bhattacharya,“基于图的软件演化分析和预测”,第 1–2 页。2012

用不确定性来解释你的模型

原文:https://towardsdatascience.com/using-uncertainty-to-interpret-your-model-c7b8c9a63072?source=collection_archive---------7-----------------------

这是一个与 约尔·泽尔德斯 的联名帖。最初发布于 taboola engineering 博客

随着深度神经网络(DNN)变得更加强大,它们的复杂性也在增加。这种复杂性带来了新的挑战,包括模型的可解释性。

可解释性对于构建更健壮、更能抵抗恶意攻击的模型至关重要。此外,为一个新的、没有被很好研究的领域设计一个模型是具有挑战性的,能够解释模型正在做什么可以在这个过程中帮助我们。

模型解释的重要性促使研究人员在过去几年里开发了各种各样的方法,去年在 NIPS 会议上,一个完整的研讨会专门讨论了这个主题。这些方法包括:

  • LIME :通过局部线性*似解释模型预测的方法
  • 激活最大化:一种理解哪些输入模式产生最大模型响应的方法
  • 特征可视化
  • 将 DNN 层嵌入到低维解释空间
  • 运用认知心理学的方法
  • 不确定性评估方法——这篇文章的重点

在我们深入探讨如何使用不确定性来调试和解释您的模型之前,让我们了解一下为什么不确定性很重要。

你为什么要关心不确定性?

一个突出的例子是高风险应用。假设您正在构建一个模型,帮助医生决定患者的首选治疗方案。在这种情况下,我们不仅要关心模型的准确性,还要关心模型对其预测的确定程度。如果不确定性太高,医生应该考虑到这一点。

自动驾驶汽车是另一个有趣的例子。当模型不确定路上是否有行人时,我们可以使用该信息来减慢汽车速度或触发警报,以便司机可以控制局面。

不确定性也可以帮助我们找出数据之外的例子。如果模型没有使用与手边的样本相似的例子进行训练,那么如果它能够说“对不起,我不知道”可能会更好。这本来可以避免谷歌照片将非裔美国人错误归类为大猩猩的尴尬错误。像这样的错误有时会因为训练不够多样化而发生。

不确定性的最后一种用法,也是这篇文章的目的,是作为从业者调试模型的工具。我们一会儿会深入探讨这个问题,但首先,让我们来谈谈不同类型的不确定性。

不确定性类型

有不同类型的不确定性和建模,每一种都有不同的用途。

模型不确定性,又名认知不确定性:假设你有一个单一的数据点,你想知道哪个线性模型最好地解释你的数据。没有好的方法来选择图片中的不同线条—我们需要更多的数据!

左边:数据不足导致高度不确定性。右边:给定更多数据,不确定性降低

认知不确定性解释了模型参数的不确定性。我们不确定哪个模型权重能最好地描述数据,但是给定更多的数据,我们的不确定性会降低。这种类型的不确定性在高风险应用中以及在处理少量稀疏数据时非常重要。

举个例子,假设你想建立一个模型,得到一个动物的图片,并预测这个动物是否会吃你。假设您在狮子和长颈鹿的不同图片上训练模型,现在它看到了一个僵尸。由于该模型不是在僵尸图片上训练的,因此不确定性会很高。这种不确定性是模型的结果,如果有足够多的僵尸图片,这种不确定性就会减少。

数据不确定性,或随机不确定性,捕捉观察中固有的噪声。有时候世界本身是随机的。在这种情况下,获得更多的数据对我们没有帮助,因为噪音是数据中固有的。

为了理解这一点,让我们回到我们的食肉动物模型。我们的模型可以识别出一幅图像包含一只狮子,因此你很可能会被吃掉。但是如果狮子现在不饿呢?这一次的不确定性来自于数据。另一个例子是两条看起来一样的蛇,但其中一条有毒,另一条则没有。

任意不确定性分为两种类型:

  1. 同方差不确定性:所有输入的不确定性是相同的。
  2. 异方差不确定性:取决于手头具体输入的不确定性。例如,对于预测图像中深度的模型,无特征的墙预计比具有强消失线的图像具有更高的不确定性。

测量不确定度:不确定度的另一个来源是测量本身。当测量有噪声时,不确定性增加。在动物的例子中,如果一些照片是用质量差的相机拍摄的,模型的可信度会受到损害;或者,如果我们正在逃离一只可怕的河马,结果我们只能处理模糊的图像。

嘈杂的标签:通过监督学习,我们使用标签来训练模型。如果标签有噪声,不确定性就会增加。

每种不确定性都有不同的建模方法。这些将在本系列的后续文章中讨论。现在,让我们假设我们有一个黑盒模型,它暴露了关于其预测的不确定性。我们如何使用它来调试模型?

让我们考虑一下 Taboola 中的一个模型,它用于预测用户点击内容推荐的可能性。

使用不确定性来调试您的模型

该模型具有许多由嵌入向量表示的分类特征。该模型在学习稀有值的广义嵌入时可能会有困难。解决这一问题的常见方法是使用特殊的词汇外(OOV)嵌入。

想想一篇文章的广告词。所有罕见的广告客户共享相同的 OOV 嵌入,因此,从模型的角度来看,他们本质上是一个广告客户。这个 OOV 广告商有许多不同的项目,每一个都有不同的点击率。如果我们只用广告客户作为点击率的预测指标,我们会得到 OOV 的高度不确定性。

为了验证 OOV 模型输出的高度不确定性,我们采用了一个验证集,并将所有的广告客户嵌入转换到 OOV。接下来,我们考察了转换前后的不确定性。不出所料,由于切换,不确定性增加了。该模型能够学习给定一个信息丰富的广告客户,它应该减少不确定性。

我们可以对不同的特征重复这一过程,并寻找用 OOV 嵌入替换时导致低不确定性的特征。要么是这些特征没有提供信息,要么是我们将它们输入模型的方式不理想。

我们甚至可以达到更精细的粒度:一些广告客户在不同项目的点击率之间有很高的可变性,而另一些项目的点击率大致相同。我们预计第一类广告客户的模型具有更高的不确定性。因此,一个有用的分析是着眼于广告客户的不确定性和点击率可变性之间的相关性。如果相关性不是正的,这意味着该模型未能了解与每个广告客户相关联的不确定性。这个工具允许我们了解在训练过程中或者在模型的架构中是否出了问题,这表明我们应该进一步调试它。

我们可以执行类似的分析,并查看与特定项目相关的不确定性是否随着我们展示它的次数增加而降低(例如,向更多用户/在更多地方展示它)。同样,我们希望模型变得更加确定,如果不确定,我们会调试!

另一个很酷的例子是标题特性:带有罕见单词的独特标题应该招致高度的模型不确定性。这是模型没有从所有可能标题的区域中看到大量示例的结果。我们可以在验证集中寻找一组罕见的相似标题,并估计模型在这些标题上的不确定性。然后,我们将使用其中一个标题重新训练模型,并查看整个小组的不确定性是否已经降低。事实上,我们可以看到这正是所发生的:

等等……通过向模型展示一些标题,它能够变得更好,并且对一堆新标题更加确定。也许我们可以利用这一点来鼓励对新物品的探索?嗯,是的,我们可以!在本系列的后续文章中会有更多的介绍。

最后的想法

不确定性在许多领域都很重要。识别哪种不确定性类型是重要的取决于具体的应用。一旦你知道如何建模,你就可以用各种方式使用它们。在这篇文章中,我们讨论了如何使用它们来调试你的模型。在下一篇文章中,我们将讨论从模型中获得不确定性估计的不同方法。

使用无监督学习优化儿童 t 恤尺寸

原文:https://towardsdatascience.com/using-unsupervised-learning-to-optimise-childrens-t-shirt-sizing-d919d3cbc1f6?source=collection_archive---------3-----------------------

这篇文章的所有代码和数据都可以在 Github 上找到。本分析使用了 Python 3、Numpy 1.12.0、Pandas 0.19.2、Scikit-Learn 0.18.1、matplotlib 1.4.3 和 Seaborn 0.7.1。

U 在处理低维数据时,监督学习,特别是 K-Means 并不难理解。然而,随着变量数量的增加,可能很难理解你在看什么,更不用说试图弄清楚它是否有用了。

使用儿童身体测量的大型数据集,这项探索的目的是使用无监督学习来提出三种不同的 t 恤尺寸,适合大多数儿童的小号、中号或大号。

本次研究中使用的数据集包含儿童的人体测量数据,以及一些与人口统计相关的属性。有 122 个变量的 3900 个观察值。

数据清理

第一步是检查数据,发现许多对象包含空值。因此,任何包含超过 2000 个空值(在本例中为零)的变量都将被删除。

import pandas as pddf = pd.read_csv('data.csv', index_col=0)

remove_cols = []

*for* i *in* df.columns:
    *if* 3900 - df.loc[:,i].astype(bool).sum() > 2000:
        remove_cols.append(i)

df = df.drop(remove_cols, axis = 'columns')

使用该标准去除了 76 个变量。

如上所述,数据集包含人体测量和人口统计数据。在这种情况下,人口统计数据被认为是没有用的,因为目的是设计 t 恤,所以 22 个人口统计变量也被删除了。

demographic_attributes = ['AGE IN YEARS', 'LOCATION',
       'BIRTH DATE', 'MEASUREMENT DATE', 'MEASUREMENT SET TP',
       'MEASURER NUMBER', 'COMPUTER NUMBER', 'RACE', 'GRADE LEVEL',
       'HANDEDNESS', 'NUMBER OF BROTHERS', 'NUMBER OF SISTERS', 'TWIN','BIRTH ORDER', 'MOTHERS OCCUPATION', 'FATHERS OCCUPATION',
       'MOTHERS EDUCATION', 'FATHERS EDUCATION', 'YEARS IN COMMUNITY','ANTHROPOMETER NO', 'CALIPER NO', 'GIRTH NO']

df = df.drop(demographic_attributes, axis = 'columns')

探索性数据分析

2 对聚类有很大影响的重要变量是年龄(以月为单位)和性别(1 或 2)。尚不清楚 1 号或 2 号是雄性还是雌性,但这不是分析的必要信息。对年龄范围的研究表明,年龄范围为 0 至 240 个月(20 岁),中位数约为 128 个月(10 岁零 8 个月)。

print(df.loc[:,'AGE IN MONTHS'].describe())

显然,为所有年龄设计一个单一的 t 恤尺寸是不合适的,因此使用直立坐姿高度作为尺寸的代表,绘制了一个图表,以查看这一测量值如何随着儿童年龄的变化而变化(0 岁、1 岁、19 岁和 20 岁的儿童被删除,因为没有足够的准确性观察)。

shoulder_data = df[['ERECT SITTING HEIGHT', 'AGE IN MONTHS']]
shoulder_data['YEAR'] = shoulder_data['AGE IN MONTHS'].apply(*lambda* x: x//12)x = list(shoulder_data.groupby('YEAR').mean().index[1:-2])y = list(shoulder_data.groupby('YEAR').mean()['ERECT SITTING HEIGHT'][1:-2])

这显示了一个大致线性的增长率,在两个年龄阶段,身高有了显著的增长。6-7 岁和 12-13 岁是这两个年龄跳跃点,增长率明显增加。因此,有三个需要确定衬衫尺码的年龄区间;0 到 6,7 到 12,13 到 20。小、中、大之间也有重叠的空间,也就是说,7-12 岁的大衬衫可能与 13-20 岁的小衬衫尺寸相似。

同样有趣的是性别和体型之间的关系。第一性和第二性的每个年龄的*均坐高图表明,在 15 岁左右之前,男性和女性之间没有太大的差异,这时男性会稍微长高一些。有了这些信息,估计 1 号性别是男的,2 号性别是女的。

shoulder_data = df[['ERECT SITTING HEIGHT', 'AGE IN MONTHS', 'SEX']]
shoulder_data['YEAR'] = shoulder_data['AGE IN MONTHS'].apply(*lambda* x: x//12)y_1 = shoulder_data[shoulder_data['SEX'] == 1].groupby('YEAR').mean()['ERECT ' \
                        'SITTING HEIGHT'][1:-2]y_2 = shoulder_data[shoulder_data['SEX'] == 2].groupby('YEAR').mean()['ERECT ' \
                        'SITTING HEIGHT'][:-1]x = list(shoulder_data.groupby('YEAR').mean().index[1:-2])

区分男性和女性的另一个有用的变量是胸围。下图显示了每个年龄的*均测量值。

这再次表明,主要的分歧发生在 15 岁左右。因此,我认为有 12T 的球衣尺寸需要改进:

  • 0-6 岁小号、中号和大号男女通用
  • 年龄 7-12 岁小号、中号和大号男女通用
  • 年龄 13-20 岁小、中、大男性和女性

出于这个练习的目的,我将把重点放在 7-12 岁。

这里需要注意的是,这两张图有些矛盾。在我看来,女性的胸围应该考虑到乳房的大小,这样的差异表明性别 1 是女性,而身高数据表明性别 1 是男性。我找不到这个数据的模式,所以无法解决这个问题。不管结果是什么,只要记住,无论何时我指定了男性 vs 女性,他们都可以互换。

无监督学习

第一步是将数据分成子集,删除值为 0 的行(本例中为 1584 行中的 59 行),然后转换为 numpy 矩阵进行聚类:

import numpy as npt_shirt_columns = ['CHEST CIRCUMFERENCE', 'WAIST CIRCUMFERENCE',
                   'SHOULDER-ELBOW LENGTH', 'ERECT SITTING HEIGHT',
                   'SHOULDER BREADTH']

young = df[df['AGE IN MONTHS'] < 84].loc[:,t_shirt_columns]middle = df[(df['AGE IN MONTHS'] < 156) & (df['AGE IN MONTHS'] >= 83)].loc[:,t_shirt_columns]old_1 = df[(df.SEX == 2) & (df['AGE IN MONTHS'] >= 156)].loc[:,t_shirt_columns]old_2 = df[(df.SEX == 2) & (df['AGE IN MONTHS'] >= 156)].loc[:,t_shirt_columns]

drop_list = []
*for* i *in* range(len(middle.index)):
    *if* 0 *in* middle.ix[i,:].values:
        drop_list.append(i)

middle = middle.drop(middle.index[drop_list])

data = middle.as_matrix()

下一步是决定数据中有多少个聚类。我们想要三个,但我们也希望它们包含足够的观察,值得为它们创建一个特定的 t 恤尺寸。找出数据中聚类数的一种方法是使用惯性图,并寻找“弯头”。

import matplotlib.pyplot as pltinertias = []
ks = range(1,11)
*for* k *in* ks:
    inertias.append(KMeans(n_clusters=k).fit(data).inertia_)
plt.plot(ks, inertias, '-o')
plt.xticks(ks)
plt.show()

由此看来,似乎有 2 或 3 个集群。我们还可以通过查看树状图来了解聚类顺序:

*from* scipy.cluster.hierarchy *import* linkage, dendrogrammergers = linkage(data, method='complete')
dendrogram(mergers, leaf_rotation=90, leaf_font_size=6)
plt.show()

这看起来不错,有两个容易识别的集群,绿色和红色。第三个不太容易看到,但我们可以解决这个问题。这是有希望的。

为了找出聚类,是时候执行 K-Means 聚类了。我们的目标是找到代表大部分观测值的三个聚类。从n_clusters=2开始,我运行下面的代码,直到我有了三个大的不同的集群。这适用于 3 个集群。

*from* sklearn.cluster *import* KMeanskmeans = KMeans(n_clusters=3).fit(data)
samples = kmeans.predict(data)

names = middle.index

ns = pd.DataFrame({'names': names, 'cluster': samples})
clusters = ns.set_index(names).iloc[:,0]

print(clusters.value_counts())

打印每个集群中的实例数量显示:

这太棒了。我们已经将所有观察结果分成了三个不同的组!现在,看看聚类中心,我们可以看到它们之间的差异:

print(kmeans.cluster_centers_)

这太棒了。我们可以看到,在所有类别中,分类 0 包含最小的值,分类 1 包含最大的值,分类 2 包含中间的值。这意味着这些质心值代表了三种不同体型的中间值,应该在为 7 至 12 岁的孩子制作 t 恤时使用。

扩展ˌ扩张

现在,制造不同尺寸的 t 恤很烦人,所以制造商希望在尽可能多的体型上使用相同的模板。因此,我之前假设不同年龄组之间可能有小/大的重叠。让我们来验证一下这个理论。

对最年轻的年龄段做同样的处理,我们得到下面的树状图:

这不像上一个那样清晰,因为我们在左边有一个高度相似的聚类,但只包含少量的值。这不是很好,但也不重要。当我们使用 KMeans 进行集群时,我们将会看到它们的归属。同样,从n_clusters=2开始并逐渐增加该值,我们可以看到,在 4 个聚类中,大部分(95.5%)数据被聚类到 3 个良好的聚类中。

查看聚类中心(忽略聚类 2,因为它包含的观察值太少):

同样,我们看到有 3 种不同的大小:小型(群集 0)、中型(群集 3)和大型(群集 1)。不幸的是,这个年龄段的大码和中年组的小码似乎没有太多相似之处。

对于较大的年龄组,可以执行类似的过程,并且男性和女性的小型集群的大小如下所示:

Small Sizing for Males

Small Sizing for Females

正如所料,男性和女性的小尺寸在一些变量上有很大不同,最明显的是肩宽。因此,最初的假设,即不同性别在 13-20 岁年龄组需要不同的尺寸,似乎是正确的。

值得注意的另一点是,13-20 岁年龄组男性的小尺寸与 6-12 岁年龄组的大尺寸不太接*,因为腰围有很大差异。这可能也在意料之中

结论

该分析显示了即使是简单的聚类分析也能从大型脏数据集中产生的结果。一如既往,处理错误和不相关的数据是至关重要的,垃圾输入=垃圾输出。通过一些简单的试错聚类,我们已经确定了跨 3 个年龄组的 t 恤设计的关键尺寸,并排除了多个年龄组使用同一尺寸的可能性!对于 145 行代码来说还不错!

同样,所有用于分析的代码和数据都可以在https://github.com/Padam-0/cluster_t-shirt_sizing获得

如果你喜欢这篇文章,请点击❤按钮让你的关注者知道,或者让我知道你的想法。

使用无监督学习计划去巴黎的假期:地理位置聚类

原文:https://towardsdatascience.com/using-unsupervised-learning-to-plan-a-paris-vacation-geo-location-clustering-d0337b4210de?source=collection_archive---------3-----------------------

The Eiffel Tower in the City of Love but there are so many great sights in Paris — how can I help her organise her trip?

当我的朋友告诉我她计划去巴黎旅行 10 天时,我想我可以帮上忙。

她:“我和我的朋友正在考虑去巴黎度假。”我:“哦,听起来很有趣。也许我也可以加入。”
她:“对!我们计划报名参加一个法语课程,然后去购物!我们已经列出了所有我们想去的购物中心,还有…“
我:“啊,听起来很棒…那么你需要我什么时候开车送你去机场?”

因为我自己也去过巴黎几次,我想我可以在其他方面有所帮助,比如为旅游景点列表做贡献。在列出所有的景点之后,我创建了一个谷歌地图,每个位置都有一个图钉。

The initial Google Map with pins for sights to visit — but in what order should these sights be visited?

很明显,要想参观完巴黎所有的景点,需要做一些日程安排工作——但是她怎么能决定先看什么,按什么顺序看呢?这在我看来就像是一个 聚类 的问题,而 无监督学习 方法可以帮助解决它。

像 K-Means 或 DBScan 这样的算法可能会成功。但首先,必须准备好数据,以便于此类算法按预期执行。

地理位置收集和数据准备

首先,我必须以 2D 格式收集谷歌地图的地理位置(可以存储在一个 numpy 数组中)。将这些图钉翻译成[经度,纬度]将是完美的。

由于这是一次性的,我寻找一种快速的方法从谷歌地图中提取这些信息。这个 StackOverflow 查询给了我所需要的一切。

基本上,你需要去 google.com/maps/d/kml?mid={map_id}的下载一个。kmz 文件。然后,手动更改的扩展名。kmz 文件转换为。zip 文件。提取文件,并在您选择的文本编辑器中打开doc . KML(sublime text是我个人的首选)。*

然后,你可能会决定手动 CTRL+F 来搜索字段,或者决定而不是这么懒,使用 BeautifulSoup (如下图)!

从 XML 文件中提取坐标后,我将坐标存储在一个数据帧中。地标总数为 26(存储在 XML 文件中的<地标> < / 地标> )。

Dataframe populated with info from the XML file (first 7 rows only shown)

从存储坐标和地标/景点名称的数据帧中,我生成了一个散点图。

Google Map Pins Scatter Plot

k 均值聚类

一般来说,无监督学习方法对于没有标签的数据集是有用的,并且当我们不一定知道结果时,我们会尝试预测。这些算法通常采取以下两种形式之一:(1)聚类算法,或(2)降维算法。

在这一节中,我们将重点关注k——意为,这是一种聚类算法。使用 k 均值,提供预定数量的聚类作为输入,并且算法在未标记的数据集中生成聚类。

k -means 生成一组 k 聚类质心和一个输入数组 X 的标签,该标签将 X 中的每个点分配给一个唯一的聚类。该算法将分类质心确定为属于该分类的所有点的算术*均值,并定义分类,使得数据集中的每个点与其自己的分类中心比与其他分类中心更接*。

source: https://bit.ly/1z29ZIV

它可以使用 sklearn 在 Python 中实现,如下所示:

从下面的散点图中可以看出,我生成了 10 个聚类——每个假期一个。但巴黎市中心的景点彼此靠得很*,很难区分这两个集群。由此产生的预测也被分类并存储在数据帧中。

k-means was used to generate 10 clusters (one for each day), the black dots represent cluster centers

使用由 k 生成的 10 个集群,我生成了一个数据帧,为每个集群分配一周中的某一天。这将构成一个时间表的例子。

k-means results as Vacation Days of the Week (first 3 days only shown)

现在,在这个阶段,我可以简单地交出排序后的数据帧,按层重新组织谷歌地图图钉(即每层代表一天),就这样——旅程完成了。

但是有些事情仍然困扰着我,那就是 k -means 正在根据点与点之间的欧几里得距离(即地图上两个大头针之间的直线距离)生成聚类。

但是我们知道,地球不是*的(对吗?)所以我想知道这种*似是否会影响正在生成的星团,特别是因为我们有相当多的地标远离巴黎市中心的高密度区域。

因为地球不是*的:输入 HDBSCAN

因此,我们需要一种能够处理地理距离的聚类方法,即地球表面两点之间最短曲线的长度。

基于 DBScan 算法的密度函数 HDBSCAN 可能对此有用。

HDBSCAN 和 DBSCAN 算法都是基于密度的空间聚类方法,它们根据距离度量和最小点数将彼此靠*的点组合在一起。它还将低密度区域中的点标记为异常值。

幸运的是,HDBSCAN 支持哈弗线距离(即经度/纬度距离),这将正确计算地理位置之间的距离。关于 HDBSCAN 的更多信息,请查看这篇博客文章。

HDBSCAN 不包含在您的典型 Python 发行版中,因此您必须 pipconda 安装它。我这样做了,然后运行了下面的代码。

最后得到了下面的散点图和数据图。我们看到孤立点聚集在聚类'-1 '中,这意味着它们被识别为'噪声'。

HDBSCAN generated 9 clusters and 3 data points as ‘noise’

HDBSCAN results as Vacation Days of the Week (first 3 days only shown)

不出所料,我们最终有几个点被标记为噪声。由于 HDBSCAN 聚类的最小点数是 2,像凡尔赛宫这样的孤立位置被归类为噪声。万森斯的圣小教堂和罗丹博物馆遭遇了相似的命运。

然而,有趣的是 HDBSCAN 识别出的集群数量为 9,比设定的假期天数少一天。我猜对于我们选择的景点/数据点的数量,10 天听起来没问题。

最终,来自 k 均值的结果是我们用来制定时间表的结果,因为 k 均值生成的聚类与 HDBSCAN 生成的聚类相似,并且包含了所有数据点。

这里介绍的聚类方法当然可以改进。一个可能的改进是为数据点增加一个权重特性。例如,权重可以表示完全参观一个特定场所所需的时间量(例如,勒卢浮宫很容易花一整天来欣赏),因此这将影响具有高权重点的聚类中的数据点的总数,这将在未来的项目中进行调查。

这个迷你项目的 Jupyter 笔记本可以在这里找到。

使用 Word2Vec 更好地嵌入分类特征

原文:https://towardsdatascience.com/using-word2vec-for-better-embeddings-of-categorical-features-de75020e1233?source=collection_archive---------6-----------------------

回到 2012 年,当神经网络重新受到欢迎时,人们对训练模型而不必担心特征工程的可能性感到兴奋。事实上,大多数最早的突破是在计算机视觉领域,其中原始像素被用作网络的输入。

很快,事实证明,如果你想使用文本数据、点击流数据或几乎任何具有分类特征的数据,在某些时候你必须问自己——我如何将我的分类特征表示为我的网络可以使用的向量?

最常用的方法是嵌入图层,即向网络中添加一个额外的图层,为分类要素的每个值分配一个矢量。在训练期间,网络学习不同层的权重,包括那些嵌入。

在这篇文章中,我将展示这种方法何时会失败的例子,介绍 category2vec,这是一种使用第二个网络学习嵌入的替代方法,并将介绍在您的主网络中使用这些嵌入的不同方法。

那么,嵌入图层有什么问题呢?

嵌入层经过训练以适应特定的任务,即训练网络的任务。有时候这正是你想要的。但是在其他情况下,您可能希望您的嵌入捕获一些关于问题领域的直觉,从而降低过度拟合的风险。你可以把它看作是在你的模型中增加了先验知识,这有助于它进行归纳。

此外,如果您在相似的数据上有不同的任务,您可以使用来自一个任务的嵌入来改进您在另一个任务上的结果。这是深度学习工具箱中的主要技巧之一。这被称为迁移学习,预训练或多任务学习,取决于上下文。潜在的假设是,解释数据的许多未观察到的随机变量是跨任务共享的。因为嵌入试图隔离这些变量,所以它们可以被重用。

最重要的是,将嵌入作为网络的一部分来学习会增加模型的复杂性,因为这会给模型增加许多权重,这意味着您需要更多的标记数据来学习。

所以不是说嵌入层不好,而是我们可以做得更好。让我们看一个例子。

示例:点击预测

Taboola 的研究小组开发了算法,根据用户当前阅读的内容向他们推荐内容。我们可以把它想成一个点击预测问题:给定你的阅读历史,你点击每篇文章的概率是多少?

为了解决这个问题,我们训练深度学习模型。自然地,我们从学习嵌入作为我们网络的一部分开始。

但是我们得到的很多嵌入没有意义。

您如何知道您的嵌入是否有意义?

最简单的方法是获取几个项目的嵌入,并查看它们的邻居。他们在你的领域里相似吗?这可能会让人精疲力尽,而且不会让你看到全局。因此,另外你可以使用 PCA 或者 t-SNE 来减少你的向量的维数,并根据特定的特征给它们上色。

一个物品的广告主是一个强特征,我们希望相似的广告主有相似的嵌入。但这就是我们为不同广告客户嵌入的样子,用广告客户的语言来着色:

哎哟。事情显然不对劲。我的意思是,除非我们假设我们的用户是多语言天才,他们阅读一篇西班牙语文章,然后毫不费力地阅读另一篇日语文章,否则我们可能会希望我们嵌入空间中的类似广告商拥有相同语言的内容。

这使得我们的模型更难解释。人们很不安。有些人甚至失眠了。

我们能做得更好吗?

Word2Vec

如果你听说过嵌入式,你可能听说过 word2vec 。这种方法将单词表示为高维向量,因此语义相似的单词将具有相似的向量。它有两种风格:连续单词包(CBOW)和跳过单词。CBOW 训练网络根据上下文预测单词,而 Skip-Gram 则相反,根据特定的目标单词预测上下文。

我们可以用同样的想法来提高我们的广告植入吗?是的我们..嗯,你明白了。

从 Word2Vec 到 Category2Vec

想法很简单:我们根据用户的点击历史来训练 word2vec。每个“句子”现在是用户点击的一组广告商,我们试图根据用户喜欢的其他广告商(“上下文”)来预测特定的广告商(“单词”)。唯一的区别是,与句子不同,顺序不一定重要。我们可以忽略这个事实,或者用每个历史的排列来增强数据集。您可以将这种方法应用于任何种类的高模态分类特征,例如,国家、城市、用户 id 等..查看更多详情此处和此处。

如此简单,却又如此有效。还记得我们之前看到的混乱的嵌入可视化吗?这是它现在的样子:

好多了!所有语言相同的广告客户都聚集在一起。

现在我们有了更好的嵌入,我们能用它们做什么呢?

使用来自不同模型的嵌入

首先,请注意,category2vec 只是一般实践的一个示例:将任务 A 中学习到的嵌入用于任务 b。我们可以用不同的架构、不同的任务,在某些情况下,甚至是不同的数据集来替换它。这是这种方法的最大优势之一。

在我们的模型中有三种不同的方式来使用新的嵌入:

  1. 使用新嵌入作为新网络的特征。例如,我们可以对用户点击的所有广告商的嵌入进行*均,以表示用户历史,并使用它来学习用户的口味。这篇文章的重点是神经网络,但实际上你可以用任何 ML 算法来做。
  2. 用我们刚刚学过的嵌入初始化网络中嵌入层的权重。这就像告诉网络—这是我从其他任务中了解到的,现在为当前任务进行调整。
  3. 多任务学习 —取两个网络,参数共享一起训练。你可以强迫它们共享嵌入(硬共享,或者当它们的权重相差太大时,通过“惩罚”网络来允许它们具有稍微不同的权重(软共享)。这通常是通过调整重量之间的距离来实现的。你可能会认为这是将知识从一个任务传递到另一个任务,但也是一种正则化技术:word2vec 网络充当另一个网络的正则化器,并迫使它学习具有我们感兴趣的特征的嵌入。

好吧,让我们回顾一下。

有时候,我们可以简单地通过采用一些现有的方法,但把它应用到新的东西上,从而获得很好的结果。我们使用 word2vec 为广告商创建嵌入,我们的结果比使用嵌入层获得的结果更有意义。正如我们在 Taboola 中所说——有意义的嵌入=有意义的生活。

你有没有以不寻常的方式使用 word2vec?有一些关于分类特征的专业建议吗?看了一篇有趣的相关论文?我很想在评论中了解一下:)

使用 Word2vec 进行音乐推荐

原文:https://towardsdatascience.com/using-word2vec-for-music-recommendations-bb9649ac2484?source=collection_archive---------3-----------------------

我们如何使用神经网络将数十亿条数据流转化为更好的推荐。

Each point represents a song. The closer the points, the more similar the songs are.

流媒体服务改变了我们体验内容的方式。虽然推荐系统以前专注于向您提供您可能想要购买以供以后消费的内容,但现代流媒体*台不得不转而专注于推荐您可以并且想要立即享受的内容。由于任何内容都可以立即访问,流媒体模型使得个性化电台或推荐播放列表形式的新发现方法成为可能,其中现在的重点是生成可以很好搭配的相似歌曲序列。

现在每月有超过 7 亿首歌曲在流媒体上播放, Anghami 是中东和北非地区领先的音乐流媒体*台。这也意味着,所有这些数据流产生的数据量被证明是一个非常宝贵的训练集,我们可以用它来教机器学习模型更好地理解用户的口味,并改进我们的音乐推荐。

在这篇文章中,我将介绍一种神经网络方法,我们使用它从我们拥有的大量流媒体数据中提取歌曲嵌入,以及我们如何使用该模型来生成相关的推荐。

推荐系统

推荐系统分为两大类:

  • 基于内容的系统是基于我们想要推荐的商品特征的推荐系统。当谈到音乐时,这包括例如歌曲的类型或每分钟多少拍。
  • 基于协同过滤的系统是依靠历史使用数据来推荐其他类似用户先前已经交互过的项目的系统。这些系统不理会内容本身的特征,并且将它们的推荐基于这样的原则,即拥有许多共同歌曲或艺术家的人通常会喜欢相同风格的音乐。

有了足够的数据,协同过滤系统在推荐相关项目上证明是有效的。协同过滤背后的基本思想是,如果用户 1 喜欢艺术家 A & B,而用户 2 喜欢艺术家 A B&C,那么很可能用户 1 也会对艺术家 c 感兴趣

观察所有用户的全球歌曲偏好,并应用经典的协作过滤方法,例如对用户项目评级矩阵进行矩阵分解,这为我们提供了关于歌曲组如何相关的有价值的信息。所以如果一群用户有一大套他们喜欢的共同的歌曲,我们可以推断那些是对音乐有非常相似品味的用户,他们听的歌曲彼此相似。

这些跨多个用户的全球共现因此给了我们关于歌曲如何相关的有价值的信息;然而,他们没有捕捉到的一件事是,歌曲如何能够在时间上局部地同时出现。所以他们可能会告诉我们,宋立科 A 的用户也可能会宋立科 B,但他们会在同一个播放列表或收音机里听吗?因此,我们不仅可以看到用户一生中播放的歌曲,还可以看到他们在什么环境下播放这些歌曲。或者换句话说,在同一个会话中,他们还会在之前或之后播放哪些歌曲?

所以我们感兴趣的是一个模型,它不仅能捕捉到相似的人对什么歌曲普遍感兴趣,还能捕捉到在非常相似的背景下 T2 经常一起听什么歌曲。这就是 Word2vec 的用武之地。

那么……什么是 Word2vec?

Word2vec 是一类神经网络模型,最初用于学习对自然语言处理任务非常有用的单词嵌入。*年来,该技术还被应用于更一般的机器学习问题,包括产品推荐。神经网络接收大量文本,对其进行分析,并为词汇表中的每个单词生成一个代表该单词的数字向量。这些数字向量正是我们所追求的,因为正如我们将会看到的,它们编码了与单词出现的上下文相关的单词含义的重要信息。

定义了两个主要模型:连续词袋模型和跳跃式模型。在接下来的讨论中,我们将把自己限制在 Skip-gram 模型,因为这是我们使用的模型。

Word2vec Skip-gram 模型是一个具有单一隐藏层的浅层神经网络,它将一个单词作为输入,并试图预测其周围单词的上下文作为输出。让我们以下面这句话为例:

在上面的句子中,单词“back-lanches”是我们当前的输入单词,单词“little”、“dark”、“behind”和“the”是我们在给定输入单词的情况下想要预测的输出单词。我们的神经网络看起来像这样:

W1W2 表示权重矩阵,用于控制我们应用于输入以获得输出的连续变换的权重。训练神经网络包括学习那些权重矩阵的值,这些值为我们提供最接*所提供的训练数据的输出。

给定一个输入单词,我们通过网络进行第一次前向传播,以获得输出单词是我们根据训练数据所期望的单词的概率。因为我们确切地知道在输出端我们期望什么样的单词,所以我们可以测量预测中的误差,并且使用反向传播通过网络传播该误差,并且通过随机梯度下降调整权重。通过这一步,我们稍微修改了 W1W2 的值,因此它们可以更准确地预测给定示例输入单词时我们想要的输出单词。完成这一步后,我们将上下文窗口移到下一个单词,并再次重复上述步骤。

我们对训练集中的所有句子重复上述过程。当我们完成时,权重矩阵的值会收敛到产生最准确预测的值。

有趣的部分来了:如果两个不同的单词在相似的上下文中大量出现,我们预计,给定这两个单词中的任何一个作为输入,神经网络将输出非常相似的预测作为输出。我们之前提到过,权重矩阵的值控制输出端的预测,因此如果两个单词出现在相似的上下文中,我们希望这两个单词的权重矩阵值在很大程度上是相似的。

特别地,权重矩阵 W1 是一个具有与我们的词汇表中的单词一样多的行的矩阵,每行保存与特定单词相关联的权重。所以,既然相似的词需要输出相似的预测,那么它们在矩阵 W1 中的行应该是相似的。与这个矩阵中的每个单词相关联的权重是我们将要用来表示该单词的“嵌入”。

但是这和音乐推荐有什么关系呢?好吧,我们可以把用户的收听队列想象成一个句子,句子中的每个单词就是用户听过的一首歌。因此,在这些句子上训练 Word2vec 模型本质上意味着,对于用户过去听过的每首歌曲,我们使用他们之前和之后听过的歌曲来教导我们的模型,这些歌曲在某种程度上属于相同的上下文。这里有一个用歌曲代替单词的神经网络的想法:

这是与上面讨论的文本分析相同的方法,除了我们现在为每首歌曲有一个唯一的标识符,而不是文本单词。

在训练阶段结束时,我们得到的是一个模型,其中每首歌曲都由高维空间中的权重向量表示。关于这些向量有趣的是,相似的歌曲将比不相关的歌曲具有更接*的权重。

宋矢用例

使用 Word2vec,我们已经将寻找出现在相似上下文中的歌曲的问题转化为捕捉这些局部共现的数学数字。我们可以将权重视为高维空间中的坐标,每首歌曲由该空间中的一个点来表示。这个空间由几十个维度定义,作为人类我们不容易想象,但我们可以使用维度缩减技术,如 t-SNE 将高维向量缩减为 2 维,并将其绘制在图表上:

上图中的每个点代表一首歌,点与点之间的距离越*,歌曲越相似。

这些向量可以以多种方式使用,例如,作为其他机器学习算法的输入特征,但是它们也可以单独用于查找相似的歌曲。

正如我们之前提到的,两首特定的歌曲在相似的上下文中出现的次数越多,它们的坐标就越接*。因此,给定一首特定的种子歌曲,我们可以通过取该种子歌曲和所有其他歌曲的向量之间的余弦相似性来找到 k 首其他相似的歌曲,同时保留具有最高余弦的前 k 首歌曲(其对应于最低的角度,因此最相似)。例如,黎巴嫩经典歌手 Fayrouz 的 Shayef El Baher Shou Kbir 和同一歌手的 Bhebbak Ma Baaref Laych 之间的余弦相似度为 0.98,而现代黎巴嫩流行艺术家 Elissa 的 Shayef El Baher Shou KbirSaharna Ya Leil 之间的相似度仅为-0.09。这是有道理的,因为听 Fayrouz 等经典歌曲的人不太可能在排队时将它们与 Elissa 的流行音乐交替播放。

我们可以使用歌曲向量的另一种有趣的方式是将用户的收听习惯映射到这个空间,并基于此生成推荐。既然我们现在在处理向量,我们可以用基本的算术将向量相加。让我们以听了三首歌的用户为例:基顿·汉森的《早晨的、伦敦文法学院的《浪费我的青春的和女儿的青春的。我们能做的是得到对应于这三首歌中每一首的向量,然后将它们*均在一起,找到一个与这三首歌等距的点。我们所做的基本上是将用户已经听过的歌曲列表转换成坐标向量,该坐标向量在我们的歌曲所在的相同向量空间中表示用户。现在我们有了一个定义用户的向量,我们可以使用以前使用的相同技术来查找与用户相*的相似歌曲。以下动画有助于形象化地展示生成这些建议所涉及的不同步骤:**

我们发现诸如《头和心在山谷中》、狐狸乐队的、米克诺斯的和本·霍华德的小事情等歌曲都与我们的输入歌曲具有相同的独立民谣风格。请记住,我们所做的这一切不是基于对音频声学的研究,而是通过简单地查看其他人在这些特定歌曲周围听过的歌曲。

结论

Word2vec 允许我们用一个坐标向量精确地模拟每首歌曲,这个坐标向量捕捉了这首歌曲播放的上下文。这使得我们可以轻松地识别相似的歌曲,并使用向量算术来找到定义每个用户的向量。

Word2vec vectors 目前与其他音乐推荐功能模型一起用于生产,主要用于基于用户收听习惯的音乐发现。所以,下次你通过推荐发现一首好歌时,想想在你之前有成千上万的人演奏过这首歌,他们接下来还会演奏哪首你最喜欢的歌曲。

想成为这样有趣故事的一部分吗? 我们在招聘

使用 XGBoost 预测献血量,而无需使用 Dataiku 编写任何代码

原文:https://towardsdatascience.com/using-xgboost-to-predict-blood-donations-without-writing-any-code-using-dataiku-1d7c9af82087?source=collection_archive---------8-----------------------

我决定用一个类似 Kaggle 的比赛的数据集来测试Data taiku 的数据科学工作室技术,这个比赛是由一个叫做驱动数据的组织举办的。驱动数据主办数据科学竞赛,以解决具有社会影响的问题。

Dataiku 为清理数据、训练模型和部署模型提供了编码环境和点击式界面。

我想比较在 Jupyter 笔记本中手动编写每一步代码与使用 Dataiku 的点击界面,并尝试回答以下问题:

  1. 使用点击式界面会显著提高我的工作效率吗
  2. 我会得到更好的结果吗?
  3. 我会被介绍到通常不属于我的标准剧目的新算法吗?

我从一个竞赛中挑选了一个超级简单的数据集来预测谁会献血,然后开始在大台库工作。在这篇博文中,我将概述我是如何使用 Dataiku 的,学到了什么,我的最终结果和我的结论。

清理数据

在大台库清理数据其实挺容易的,甚至“好玩”!而不是煞费苦心的把字符串编码成类别,整数等。在熊猫身上,大太酷是自动完成的。我喜欢这个功能。

加载数据集:

注意—不要在此界面中更改列名。如果有必要,可以稍后在脚本中完成。否则,当您加载您的测试数据时,您将不得不再次手动更改名称,否则模型将无法工作。

快速统计和直方图:

你可以很容易地点击任何功能,以获得快速统计和直方图。虽然这很酷,但不利的一面是,当信息太容易获取时,你可能会花更少的时间来真正消化它。我还发现直方图格式比使用旧的 matplotlib 更难阅读。 (Matplotlib 是 Python 的开源数据可视化工具。)

基础数据准备:

Dataiku 正确地猜到我的字符串应该被转换成整数。以下是下拉菜单中的其他快捷选项。同样,如果您打算使用具有相同原始模式的附加数据集,请不要在这里进行更改。

你也可以做其他漂亮的事情,比如过滤、排序、着色。这对于了解数据非常有用。

数据探索

是时候做一些散点图和条形图了!只是拖放。您可以存储图表、下载图表并将其发布到仪表板。这很方便,但是当然你需要花时间去学习这个软件的功能,并且熟练地使用它。

不利的一面是,如果你已经掌握了 matplotlib,对你的图表没有相同程度的控制是令人沮丧的。此外, Seaborn (另一个 python 可视化库)有一个叫做 pairplot 的漂亮函数,让你使用一行代码生成一个散点图矩阵,其中包含你的所有特征。据我所知,这里你必须一次创建一个散点图。

我对数据探索功能的另一个批评是,我无法像在 Jupyter Notebook 中那样系统地展示我的分析和评论。Jupyter 笔记本让你创建一个按时间顺序排列的记叙文来记录你的整个思考过程。

然后,我发现了 Dataiku 的“仪表板”功能。这种“排序”让你建立一个叙述,通过保存你的图表作为一个仪表板的瓷砖,并添加到每个瓷砖的洞察力。然而,你不能同时查看你的‘洞察力’和你的图表,我觉得这有点烦人。我也更喜欢年表,而不是瓷砖的排列,但也许我可以及时适应这个新系统。

现在,Dataiku 的一个非常好的功能是,如果你对点击太不耐烦,你可以随时跳到 Jupyter 笔记本上做你的事情。

建模时间!

现在是时候去“实验室”做一些功能工程和建模了。你可以做一个“视觉分析”,即点击,使用空白笔记本,或使用预定义的笔记本。

这里有几个截图,让你知道有什么可用的。Dataiku 还有额外的“插件”,你可以用它来获得更多预定义的选项,比如处理 Twitter 数据。

Keep it simple — do you want to predict or cluster?

Do some topic modeling, PCA, time-series forecasting, etc. in a prebuilt note book. Or just get a blank notebook up and running.

我将向您展示我是如何使用可视化分析选项对数据建模的。

创建数据预处理脚本

首先,我创建了一个脚本来处理我的数据。这里,我删除了一个列,因为它与另一个列完全相关,并且我创建了一个每月捐款的新特性。

当你点击“添加新步骤”时,你会得到大量的选项。坦率地说,这些选项给了我新的想法,让我知道我可以用这些数据做些什么,这是我以前可能没有想到的。此外,这个接口减少了大量的时间,否则你可能要花在弄清楚如何编写代码来实现你伟大的特性工程思想

我认为,如果人工智能可以查看我的数据,并根据文献给我具体的建议,以实现更好的特征工程,那将是绝对美妙的。

一旦您完成了数据预处理,请确保将脚本部署到您的“流”中,以便它可以在您的测试数据中重用,等等。

运行一些模型

使用 Dataiku(我认为是所有的数据科学*台),你可以同时训练多个模型,并方便地为你总结所有的统计数据。

这里有一些截图,让你知道什么是可能的。对建模功能可以做的每一件事做一个深入的教程太多了。如果您想了解更多,Dataiku 有一个免费层,可以让您了解该产品。

玩你的功能和运行许多模型是非常容易的。优化参数的网格搜索在后台自动完成,但您也可以自己调整参数。

这里的另一个便利是不必自己下载和安装某些算法的包。例如,我在让 XGBoost 工作时遇到了很多麻烦,所以不用在这里处理安装问题就很好了。

一个方便的并排比较分数!我运行的模型比这多得多,但这个截屏只显示了其中的几个。

查看每个型号的功能重要性和其他详细信息。

不看看自己的困惑矩阵,就不能称自己是数据科学家。

我希望我可以在彼此之上绘制多条 ROC 曲线,这样我就可以同时看到所有的模型。

这个自动特征生成“功能”也非常棒。

还有很多,但这些是我的亮点。同样,太容易获得所有这些信息的缺点是,你可能会跳过一些步骤,花更少的时间来真正消化正在发生的事情。有了这个界面,就很难创建一个叙述来记录你的思维过程。下一次我想我会打开一个记事本来整理我的思绪。

部署您的模型并对测试数据进行评分

《大台库》中有两个概念理解起来很重要,我还没有涉及到:“菜谱”和“流量”。下图中的黄色小扫帚代表了数据清理的方法(我们之前部署的脚本/步骤)。绿色图标代表模型、预测和评分。

正如你在这里看到的,我把我的训练数据,做一些数据清理,训练一个模型,然后用在测试数据上。然后,我获取测试数据,运行数据准备程序,然后进行评分。我还在测试数据的最后做了一个额外的数据准备步骤,为 DrivenData 竞赛提交做准备。

这无疑(现在仍然有点)令人困惑。但是,我认为一旦你掌握了窍门,这一切真的很有意义。

所有这一切的美妙之处在于,您可以在您的流程中使用点击和编码方法!所以,你可以两全其美。我觉得这很酷。

Flow

Recipes

附加功能

Dataiku 还具有更多功能,可用于构建 web 应用程序、自动化任务、监控、创建实时预测 API 等。

比赛结果

我向比赛提交了我的测试数据,得到了以下结果。

这是一位领导者的 github repo (截至 2017 年 1 月),他使用各种算法记录了他的模型结果。作为直接比较,你可以看到他的 XGBoost 模型的笔记本。他的原木损耗分数是 0.4851,而我使用大台库的原木损耗分数是 0.4607(越低越好)。

如果你想看到更多的比较,这是与各种竞赛领导者提交的代码链接的回购。我想我可以通过尝试这些回复中的功能工程思想来大大提高我的分数。

结论

让我们重温一下我最初的问题。

  1. 大台库让我更有生产力了吗?是啊!我认为使用 Dataiku 进行分析所花的时间比编写代码要少得多,即使有学习 Dataiku 的加速时间。
  2. 大台库让我得到了比其他方式更好的结果吗?不是 100%确定,但我认为是这样,因为所有的自动优化工具在后台做的。
  3. 我接触到新算法了吗?不完全是。我没有展示完整的列表,但是他们所有的预烤的都已经在我的 repetoire 里了。相比之下,我看到了一个数据机器人(一个竞争的数据科学*台)演示,其中有相当多我以前从未听说过的算法。

总体而言,我对数据科学“*台”有什么看法?

我认为,一旦你掌握了技术并有了一个好的工作流程,使用数据科学*台会是一个很大的优势。它允许您:

  1. 多思考,少编码。
  2. 更快获得结果。
  3. 让非编码人员掌握领域专业知识

我很想听听其他人对数据科学*台的体验。我希望你喜欢这篇文章,如果你有任何问题,请随时联系我。

利用 Yelp 数据预测餐馆倒闭

原文:https://towardsdatascience.com/using-yelp-data-to-predict-restaurant-closure-8aafa4f72ad6?source=collection_archive---------3-----------------------

米恰伊尔·阿里菲拉克斯是一名有抱负的数据科学家,也是普林斯顿大学的化学工程博士生,他在普林斯顿大学模拟复杂材料的机械和电子特性。他是 2017 年秋季的 洞察数据科学研究员 。在 Insight,他在三周内建立了一个模型,预测餐馆在四年内关闭。

作为 Insight Data Science 的研究员,我有机会花三周时间构建餐馆成功模型:一个评估餐馆在未来四年内可能成功还是失败的模型。这个项目最具挑战性的部分是建立正确的数据集,其中包含有关过去某个时间点存在的餐馆的当前信息,并设计预测功能。

过去利用 Yelp 数据预测餐馆成功的努力都没有成功。另一方面, Yelp 评论文本在短时间尺度上对餐厅关闭具有很强的预测性。在我的工作中,我使用 Yelp 评论的元数据设计了更大时间范围(四年)内的预测功能,以及基于周围餐馆相对表现的功能。这个问题的更多细节、使用的程序和获得的结果在下面给出。

1.定义问题

美国餐饮业确实很大,2016 年创造的收入约为7990 亿美元,分布在 100 多万家企业之间,这些企业雇佣了约 10%的美国劳动力。鉴于小企业的数量和这个行业的总规模,我决定创建一个模型,可以帮助餐馆贷款人(如银行)和投资者根据某个餐馆在未来几年内倒闭的可能性来决定他们是否应该贷款/投资该餐馆。

餐厅关闭是一个非常明确的成功衡量标准,尽管可以设计更复杂的成功衡量标准。餐馆关闭度量标准的选择允许我将这个问题作为一个分类问题,这使得获得标记数据变得更加容易。很难找到关于每家餐厅业绩的更详细信息,因为大多数餐厅都是私营公司。

2.构建数据集

据我所知,不存在可用于解决上述餐馆关闭问题的标记数据集。首先,要构建这样的数据集,我必须找到过去某个时候存在的餐馆列表,然后将该信息与餐馆的当前信息进行匹配。

我的起始数据集是 2013 年发布的 Yelp 数据集。该数据集包含亚利桑那州凤凰城地区的商业信息。使用该数据集的训练数据,我决定只研究餐馆,并且只研究在获得该数据集时仍在营业的餐馆。

这个数据集和 Yelp 发布的所有其他用于学术用途的数据集不包含真实的企业识别码或电话号码。如果有这些代码,从 Yelp API 获取当前数据将变得很容易。为了克服缺少业务 id 的问题,我使用 Yelp 搜索 API 从旧列表中搜索每个餐馆,使用它们的名称和地址,但是结果令人失望。

使用这种方法,只有三分之二的餐馆与当前信息相匹配。其余的搜索给出的结果与真正的餐馆不相符。不过,这种搜索方法的基本问题不是数据点的数量,而是返回结果的方式存在偏差。

通过 Yelp 搜索正确返回的餐馆要么是仍在营业的餐馆,要么是最*关闭的餐馆。这产生了一个包含几乎所有成功餐馆的数据集(因为即使是关闭的餐馆也是自原始数据集发布以来设法保持营业约四年的餐馆)。至于其余的餐厅,在我获得每家餐厅的具体信息之前,我无法确定它们是否已经关门。

2a)获得正确的当前餐馆信息的解决方案

尽管 Yelp 不会通过 Yelp 搜索 API 返回关闭很长时间的餐馆的结果,但它会在数据库中保留这些信息。我的解决方案是使用 Google Search API 来搜索 yelp.com 域,并提取尚未匹配的餐馆的业务 id。这些业务 id 用于通过 Yelp 业务 API 直接从 Yelp 获取当前数据。这使我能够获得大多数剩余餐馆的信息,并建立一个有意义的模型。

2b)连接新旧数据集

我确认新旧数据集中的餐馆是否相同的方法是,检查新旧餐馆名称的前四个字符是否包含在新旧餐馆名称中,以及地址的前四个字符是否相同。对于只符合上述两个标准之一的餐厅,我手动检查以确定原因,并创建了一个自 2013 年以来在 Yelp 数据库中发生变化的餐厅名称字典(例如,肯德基改为 K.F.C .)。

最终的数据集总共包含 3,327 家餐馆,其中约 23%自 2013 年以来已经关闭。下图概述了创建该数据集的过程。

Graph of process of creating the discussed dataset. The percentages indicate the percentage of data points carried from the previous step.

3.特征工程

Yelp 提供的原始特征(例如 Yelp 星级)的预测能力非常差。如下图所示,Yelp 星级分布对于开放和关闭的餐馆来说看起来非常相似。

Yelp star distribution for restaurants that remained open in the 4-year period (black) and for restaurants that closed (red). On the left, the percentages per category are shown, where the similarity of the two categories becomes apparent. On the right, the absolute numbers are presented, which give a better picture of the class imbalance.

生成有意义的特征是建立这个模型的关键,为此我使用 yelp 评论和位置元数据生成了特征。其中一些功能如下:

  • 这家餐厅是连锁餐厅的一部分吗?如果餐馆名称在列表中出现不止一次,那么它被认为是连锁店的一部分。这包括全国或地方连锁店。由于连锁店的定义方式,在特定列表中仅由一家餐厅代表的一些连锁店不算为连锁店。
  • 当地的餐厅密度是多少?根据餐馆坐标,我为列表中的每个餐馆创建了一个半径 1 英里内的餐馆列表。
  • 点评数星级价格(即一般用餐费用)相对于周边餐厅是多少?识别每个餐馆 1 英里半径内的周围餐馆(类似于餐馆密度计算),并且通过从每个单独的餐馆中减去该组餐馆的*均值并除以该组餐馆的值的标准偏差来计算每个餐馆的评论计数、星级和价格的相对值。
  • 每个餐厅的年龄是多少?这个值大约是 yelp 第一次评论的日期。这意味着加入 yelp 较晚或没有经常收到评论的餐厅看起来比其实际价值相对年轻。此外,餐厅的年龄受到 Yelp 成立日期(即 2004 年)的限制。

4.机器学习模型和优化

使用分层采样将数据集分为 80%的训练集和 20%的测试集。这个数据集的基本问题是,即使引入了附加的特性,它也没有很好地分离,其中一些特性已经在上面描述过了。

一家餐厅成功或失败的原因有很多,但不包括在我们的特征空间中(例如,其他邻*的餐厅、周围的场地、更新的税收系统、健康检查结果等)。).在这种情况下,复杂的决策边界没有好处。通过使用准确度、精确度、召回率和 F1 分数作为评估指标,在我们的数据上测试不同机器学习模型的性能,这一点得到了证实。

由于我从使用更复杂的模型中获得的这种改进的缺乏,我选择使用线性逻辑回归模型,它简单并且具有良好的可解释性。基于餐馆贷款的用例,我选择优化我的模型参数,使用交叉验证的网格搜索来提高开放餐馆的精确度。优化的参数是正则化强度(使用 L2 正则化)和截距比例因子。我的参数选择结果如下所示。

On the left, there is a list of evaluation metrics for the model performance. On the right, the confusion matrix is presented, which gives a different perspective on model performance.

如上图所示,开放餐馆的准确率为 91%。这意味着,在被模型识别为开放的餐馆中,91%的餐馆实际上仍然开放。剩下的 9%是误报。基于这种模型做出贷款决定的银行,其 4 年违约率可能为 9%,而不加选择地向列表中的所有餐馆提供贷款的银行,其 4 年违约率约为 23%(相当于我们数据集中的餐馆倒闭率)。

看上面的混淆矩阵可以看出,在餐厅关门的情况下,模型的预测能力很差。在被预测将会关闭的餐馆中,只有 36%的餐馆在 4 年内最终关闭。这是在我们的特征空间中实现的两个类之间的不良分离的结果。封闭式餐厅的精确度可以进一步提高,但开放式餐厅的精确度总是需要权衡。基于我们的用例(即餐馆贷款),我选择将注意力集中在提高开放餐馆的精确度上。为了提供更多贷款,应该根据银行愿意接受的风险进一步调整模型。

5.特征重要性和模型解释

该模型产生的特性重要性如下所示。促使餐馆继续营业的要素显示为黑色,而促使餐馆关闭的要素显示为红色。

A list of features ranked on decreasing importance. Features that contribute towards the restaurants remaining open are shown in black, while features that contribute towards restaurant closure are shown in red.

根据我们的模型,最重要的特征是餐厅是否是连锁餐厅的一部分。连锁餐馆更有可能继续营业。这并不奇怪,因为连锁餐厅的利润率通常高于个体餐厅。

相对评论数(即相对于周围 1 英里半径内餐馆的评论数)是促使餐馆保持营业的第二个最重要的特征。很难将这一指标严格定义为成功的标志或原因。大量的评论表明餐馆的流量更高,但这也是在 Yelp 搜索结果中出现更高的原因,这本身就可以带来更多的流量。

餐厅密度与较高的关闭率相关。这可能是由于竞争加剧。与相似的餐厅密度(即半径 1 英里内属于同一食品类别的餐厅密度)相比,观察这一特征很有意思。高餐馆密度对餐馆成功是负面的,而高相似餐馆密度是正面的。举例来说,在一个有很多餐馆的地区拥有一家中国餐馆通常对这家中国餐馆是不利的,但是如果这家中国餐馆在一个有很多其他中国餐馆的地区(例如唐人街),那么这就降低了失败的风险。从消费者的角度来看,这种观察的一个可能的假设是,像唐人街这样的地区的餐馆缺乏差异化减少了个体餐馆之间的竞争(对于一般商品来说这通常是不正确的,但是当尝试一家新餐馆时,从消费者的角度来看通常缺乏信息)。另一个可能的假设是,消费者的胃口不容易改变,因此唐人街受欢迎的餐馆可能会在他们太忙而无法满足需求的时候吸引周围餐馆的流量:去受欢迎的中国餐馆寻求中餐的人会更喜欢去附*的类似餐馆,如果他们的第一选择太忙而无法为他们服务的话。这一主题有待进一步研究,通过关注一些类似餐馆密度高的特定区域的数据,可以获得更深入的理解。

Yelp 上宣称的餐厅更有可能继续营业。所谓的 Yelp 业务是指所有者努力在 Yelp 上运营,并声明该业务是他们自己的。从这个意义上说,与餐馆成功的正相关是意料之中的。

每周相对评论数量的增加似乎对餐馆的成功有负面影响。这是一个反直觉的结果,并且可能是由两个原因引起的:1)每周的相对评论是通过相对评论的数量除以餐馆的餐馆年龄(自最老评论起的时间)来计算的;餐厅年龄与餐厅成功正相关,用这个数字除一个指标会产生负相关,这可能比评论数效应更重要,2)每周相对评论数与模型已经考虑的相对评论数相关。逻辑回归模型不擅长处理相关特征。

6.建议的改进

这一模型的结果非常有希望,它们表明相对于随机模型,贷款目的有了显著的改善。在我看来,进一步改进的关键是添加更多的功能,可能通过利用不同的数据源。

  • 餐馆倒闭的一个可能原因是健康检查评级。将健康检查评级作为一个特性添加到我们的模型中可以提高它的精确度。
  • 餐馆关闭的另一个原因是高昂的租金。增加每个地区的租金定价可能有助于解释更多餐馆倒闭的原因。
  • 城市特定区域人口统计数据的变化会增加或减少某些餐馆的客流量。
  • 新的周边场馆是另一个原因,它可以带动餐馆的客流量,并带来目前这种模式无法预测的成功。
  • 餐馆的成功目前被定义为餐馆保持营业。一个更准确的成功定义将更适合贷款的目的,将与餐馆收入相关。即使大多数餐馆的收入不是公开信息,也可以构建相关指标。例如,将餐馆每周收到的评论数量乘以餐馆的价格(即,一般餐饮成本)可以作为有用的度量。

摘要

  • 该模型是为餐馆贷款目的而构建的,可以识别在 4 年内仍在营业的餐馆,准确率为 91%。
  • 该数据集是通过 Yelp 和谷歌搜索 API 提取 2013 年在亚利桑那州凤凰城存在的餐馆的最新信息建立的。
  • 该模型的一些非常有预测性的功能是使用 Yelp 评论和位置元数据构建的。这有助于构建相对指标,如相对于周围餐厅的餐厅密度和数量。
  • 使用的机器学习模型是简单的逻辑回归模型,该模型使用交叉验证的网格搜索针对开放式餐馆的精确度进行了优化。
  • 我们得到的一个教训是,决定一家餐馆是否继续营业的最重要因素是它是否是连锁店的一部分。属于连锁店的餐馆关门的频率较低。
  • 另一个经验是,在有许多其他餐馆的地区建造餐馆通常是负面的,除非这些餐馆提供类似的食物(例如在唐人街建造一家中国餐馆)。
  • 该模型可以通过进一步的数据集进行改进,如健康检查数据(目前在亚利桑那州菲尼克斯不公开),以及关于周围场馆的信息。

这个项目的代码可以在这个 github 库中找到。

利用流行病模型提高脸书的广告点击率

原文:https://towardsdatascience.com/utilising-epidemic-modelling-to-improve-advertising-click-rates-on-facebook-6f294205a43f?source=collection_archive---------5-----------------------

本文是与安迪·麦克斯威尼合写的

社交媒体的年度广告预算在过去几年中出现了大幅增长,预计到 2019 年仅在美国就将达到173.4 亿美元。脸书、Twitter 和 Snapchat 等社交媒体公司所展示的直接瞄准巨大市场的能力,为营销机构提供了一种全新、更强大的接触客户的方式。

为了让广告商满意,社交媒体公司通过其网络有效分发广告的方法需要有效地锁定最有可能对广告做出回应的用户。作为他们服务的费用,脸书收取“每次观看”和“每次点击”的费用,所以广告商必须权衡他们的成本和暴露的用户数量。

很明显,脸书计算的是每个用户回复广告的可能性,并且只锁定可能性高的用户。这对营销人员来说是有效的,因为他们的“每次观看”成本是固定的,“每次点击”成本理论上可以被销售额抵消。不清楚的是,如果脸书利用友谊信息,更具体地说,假设:

如果用户点击广告,他们的连接也会点击广告的概率会增加。

基于这种假设,是否可以探索用户网络,以病毒式方式“传播”广告,以获得类似(或更高)的点击量,同时向更少的人显示广告?

为了探索这个想法,我们采用了一个小的子图,即由 4039 个节点和 88234 条边组成的脸书“社交圈”数据集。为了便于理解,你最好把这个网络想象成喜欢脸书网页的用户。大约有 4000 人,他们都是至少一个喜欢这个页面的人的朋友。他们中的一些人非常受欢迎,一个人有 1045 个朋友也喜欢这个页面,而其中的 75 个人只认识一个喜欢这个页面的人。总体而言,学位分布如下:

Lots of nodes have low degree, a few have a high degree. Turns out that’s pretty normal for Facebook

现在,根据一些特征(他们喜欢页面帖子的频率,查看页面的频率,他们喜欢的相似页面等),脸书对每个人真正喜欢这个主题的程度有了一个不错的想法。

我们的第二个假设是,用户与页面交互的概率分布与页面用户的程度分布非常相似。一些人真的很可能会与之互动,而很多人则相当矛盾。这就是为什么你会看到有几千个赞的页面,但只有几百个赞。

这是一个指数分布,如果我们将“与页面互动的概率”替换为“点击与页面主题相关的广告的概率”,我们就有了一个粗略的衡量用户点击广告的潜在概率的方法。我们无法准确衡量这一点,因为我们没有脸书的数据,但我们有一个起点。

Per user likelihood of clicking on an ad that relates to the group. Most users have a small chance, and a few have a decent chance.

为了提出一个“基础案例”来比较我们的流行病模型,我们选择了阻力最小的方法。将广告展示给小组中的每个成员,使用独立的伯努利试验,看看有多少人根据他们的潜在概率做出了回应。

我们进行了 1,000 次测试,在 4039 次浏览中,*均点击次数为 88.54 次,即每次浏览的点击率为 0.0198。每次点击量(CPV)和总点击量是对广告客户很重要的两个指标。

知道了我们必须打破的数字,我们设计了一种方法,利用用户如何连接的信息来更慢地传播广告,但希望有更好的结果

首先,每个用户的潜在概率是使用均值为 0.03 的指数分布来确定的,与基本情况一样。根据用户共享的连接数量,用户之间的每个连接都被赋予 0 到 1 之间的“强度”。如果两个用户都有 12 个朋友,但其中 8 个是他们共有的,他们的优势是 66%。

由此,在沙地上画了一条线。共享超过 50%好友的用户连接被认为是“强”连接,而那些少于 50%的用户连接被认为是“弱”连接。这很容易想象,只要想想和一个亲密的友谊团体的关系,在那里每个人都认识每个人,和一个你认识的同事或亲戚,但不是你朋友的朋友。

考虑到这一点,还有 3 个因素有待确定。

  • 假设用户的一个连接先前点击了广告,那么对用户点击广告的概率的实际影响是什么?
  • 广告的“传染性”如何,或者它如何在用户之间传播?
  • 广告应该如何开始,或者需要多少个“耐心零”?

所有这些因素都必须设置在两个界限之间。太低的话,广告会很快消失,也许会产生很高的点击率,但总点击率很低。对广告商不利。太高,假设不切实际,也不适用。

第一个因素被设定在 10%的最大增幅,与友谊的强度成线性比例。也就是说,如果用户点击了广告,他们的所有连接都会看到他们点击广告的潜在概率增加了一个数量。如果这两个人之间的友谊强度是 60%,那么数量将是 6%。如果人与人之间的力量是 25%,那么这个量就是 2.5%。每次迭代后都会重新计算,如果越来越多的朋友点击广告,用户可以看到多倍的概率增加。

接下来,广告的病毒式传播取决于“广告服务”的构成。也就是说,当用户点击一个广告时,在下一次迭代中,他们的多少个连接以及哪些连接将被显示广告?广告服务的组成范围从 10 个强连接和 0 个弱连接到 16 个强连接和 24 个弱连接。总共测试了 28 篇作文,让 10 人、20 人、30 人或 40 人看一些强朋友和弱朋友的组合。

改变这些数字的目的很简单。虽然强连接在他们的朋友点击广告后出现概率最高,但只向强连接显示可能会使广告停留在小社区或网络的子图中,并限制其传播。另一方面,仅向弱连接显示广告有广告消失的风险,因为调整的概率较低。我们想测试这种*衡行为是如何影响结果的。

最后一个因素,即“种子”组,或“患者零”的数量在 10 到 40 之间变化。由于假设这些人是第一个点击广告的人,他们被选为具有总体最高原创概率的人。这个假设有点牵强,特别是对于 40 人的 seed 组,稍后会有更多的介绍。

在设置了所有因素的情况下,模拟被设置为针对每个广告组合、每个种子组大小在 20 个随机图上运行(因为概率的原始分布是随机的,所以我们复制了模拟以获得更一般化的结果)。当 4000 个用户看过广告,或者在一次迭代中没有新的点击时,每个模拟都结束了。

在第一次模拟中,我们采用了“最佳”每次点击观看比率(针对所有种子组大小),并将结果与广告服务构成和生成的总额外点击量(TACG,或总点击量减去种子组大小)进行了对比。结果如下所示:

我们首先看到的是我们最初的恐惧被证实了。小型广告组合产生了较高的点击率(红点),但整体点击率较低(黑线)。为了避免这种情况,我们根据视图总数过滤了这些点。蓝点达到了 4000 的观看阈值,红点没有(*均而言)。

剔除这些数据后,结果令人振奋。表现最好的广告服务比率是 20 强/ 20 弱,仅播种 12 个初始最高概率用户。

这在 4025 次浏览中*均产生了 122.45 次额外的广告点击,CPV 比率为 0.0304,比基本情况下增加了 53%!

有趣的是,不同的广告组合之间似乎没有太大的区别。尽管那些拥有大量强关系的人在概率上有优势,但弱关系的强度似乎使这种优势达到了*衡!

这非常有趣,因为我们证明了只要减慢广告在网络中的移动速度,每次点击量就会显著增加。

然而,如上所述,我们并不喜欢我们的一些假设。潜在的概率分布和种子用户的选择基本上是随机的,我们想知道是否有更好的方法来模拟这一点。

然后,我们试图对社交媒体“影响者”的真实趋势进行建模。在过去的几年里,社交媒体上“有影响力的人”的崛起经历了巨大的增长。影响者可以被定义为在社交媒体上拥有大量追随者的人,并由公司支付报酬,向他们的网络推广产品。

基于用户的等级(连接的数量),我们可以用它来代表他们在网络中的影响力。然后,我们让用户点击广告的潜在概率等于他们的朋友数量除以网络中任何人的最大朋友数量(1045)。这产生了一个非常接*指数的概率分布!稍微调整一下(将所有概率乘以 0.7),我们得到了一个非常接*我们最初假设的分布。

现在最大的不同是潜在概率不再是随机的!这意味着我们对模拟结果有了更多的信心。

像最初的模拟一样,种子用户仍然是组中概率最高的用户,但现在这些用户是组中实际的影响者。不要认为这些人“最有可能”点击广告,他们实际上可能是那些付费推广广告的用户。对于广告如何被引入生态系统,这是一个更加有机和现实的假设。

我们做的第二个改变是,在用户的连接点击广告后,用户的概率是如何调整的。之前是连接强度乘以 10%。现在是连接强度乘以 5%,加上 15%乘以影响力。这代表了一个事实,即用户更有可能受到网络中某个名人的影响,而不是“某个人”。

5 + 15 系数纯粹是假设,但模型的妙处在于实际数字有些无关紧要。如果它们是 0%和 0%,我们将回到基本情况。如果模型显示出任何非零系数的改进,这就证明了病毒式广告方法是有效的!

话虽如此,我们还是来看看结果吧。模拟以与原始情况类似的方式运行,除了没有 20 个随机图形(因为图形现在是确定性的)。

该图显示了与原始情况大致相同的结果,但是每次查看的点击量和总的额外点击量更高!事实上,最好的情况是使用 36 个强的和 4 个弱的广告组合,用 24 个影响者播种,产生 0.0341 的 CPV。这又产生了 137 次点击。

24 个影响者有点多,他们不便宜这些影响者,所以我们看看是否有稍微差一点的结果,使用较少的影响者。而且有:

16 强 24 弱的广告组合产生了 0.0335 的 CPV 比率和 135 次额外点击,仅使用了 14 个影响者!比基本情况好 70%!

因此,我们已经看到我们的广告服务病毒式营销模式在小图表上产生了惊人的结果,我们想看看它与更大的模式相比会如何。使用 Albert-Barabási 优先模型,我们生成了更大的图形,这些图形非常接*原始脸书图中的度数分布:

The tails of each distribution are a little different, but they’re close enough for what we’re trying to do

我们生成了具有 4,039 个(直接比较)、10,000 个和 20,000 个节点的图,在每种情况下,为每个新节点附加 20 条额外的边(原始脸书图中的*均度数约为 21)。

令人放心的是,这些网络产生了非常相似的结果,并让人们相信该模型可以扩展到脸书或 Twitter 开发的更大的真实世界图表。

从这一建模实践中得出的最终结论是,无论实际调整值是多少,用户通过朋友点击广告而看到的点击广告的概率的任何增加,病毒式营销模型都将产生 CPV 和 TACG 的增加,从而增加社交网络和广告商的收入。

所有的代码和稍微多一点的技术报告都可以在 https://github.com/Padam-0/facebook_viral_advertising 获得

如果你喜欢这篇文章,请点击❤按钮让你的追随者知道,或者让我知道你的想法。

再次衷心感谢安迪·麦克斯威尼对这篇文章的贡献。

为企业利用人工智能云解决方案

原文:https://towardsdatascience.com/utilizing-artificial-intelligence-cloud-solutions-for-business-52780794a69c?source=collection_archive---------15-----------------------

Cloud computing

钻研人工智能解决方案来简化业务流程似乎是一项艰巨的任务。幸运的是,有越来越多的资源和基于云的服务可以用来外包或促进商业人工智能的努力。

人工智能解决方案可以集成到业务流程中,以提高生产能力并降低劳动密集型成本负担。

基于云的通用机器学习

几家著名的互联网技术公司提供通用的机器学习和人工智能解决方案,作为端到端数据驱动流程的*台。这些解决方案结合了各种组件来传递数据、安全地托管数据,并提供一系列算法来为决策和相关流程提供及时的分析。

通用解决方案旨在满足不同的需求,能够选择集成的机器学习模块,以便从数据中实现所需的预测输出。人工智能模块可以按顺序连接,一个模块的输出可以作为下一个模块的输入。实时数据处理可以受益于虚拟内核资源上的快速并行处理,因此预测输出可以在终端应用中以非常低的延迟使用。

考虑到可用资源的可扩展性,通用机器学习云解决方案可以适用于简单到多维的人工智能应用。这些解决方案的示例包括:

  • 亚马逊 AWS 机器学习 —在人工智能解决方案和内容交付方面拥有多种服务产品。
  • 谷歌云人工智能——高度模块化的*台,通过有针对性的集成人工智能解决方案来瞄准特定的用户案例。
  • 微软 Azure AI —支持开源 AI 解决方案,重点关注云和本地托管的应用程序组件之间的集成。
  • IBM Watson —包括一个专门的业务分析解决方案,可以从多种文档格式中进行人工智能模式识别。

特定任务的人工智能云解决方案

人工智能的云解决方案也适用于特定领域的问题解决和流程自动化。特定于任务的解决方案相对于通用解决方案的优势在于可以简化实施,并提高定制方法的相关性。

利用符合特定业务流特征的云人工智能系统也可以补充更广泛的通用解决方案的使用。在这些场景中,数据从一个解决方案的输出传递到另一个解决方案的输入,直到自动化决策过程获得所需的结果。人工智能特定任务解决方案的示例包括:

  • Diffbot AI:X —通过智能分析关系,从 web 内容中提取数据和结构化元数据。
  • 猴子学习 —自然语言处理(NLP)和从文档中挖掘文本,具有流程工作流自动化智能。
  • 向量空间 —预测金融市场和加密货币趋势的 NLP 机器学习算法。
  • 现场智能 —处理多种格式的业务文档,提取信息进行分析和智能处理。
  • Tisane Labs —从多语言文本内容中提取见解和情感分析的经济实惠的 NLP *台。
  • Chatler AI —具有学习和推荐智能的客户支持功能的实时聊天引擎。
  • Semanti—IPTC 媒体标准下具有主题标识提取和分类的 Web 内容提取 API。
  • Edge Verve —致力于特定领域业务应用的人工智能模块,涵盖供应链管理、金融和营销流程。
  • Wipro Holmes —结合技术和咨询,定制解决方案,实现业务流程自动化并重新定义运营。
  • Rainbird —整理企业知识和专业技能,结合人工智能解决方案,实现更快、更高效的商业决策。
  • Ayasdi —业务和流程驱动数据流的模式发现和预测引擎。
  • Receptiviti —沟通和语言分析,用于开发实时响应流程的心理和情绪特征。

开源人工智能工具

开源解决方案存在于云或本地开发*台上,可以以更低的成本为商业人工智能工作提供更多的控制。由于许多云解决方案也支持开源模块,在这些模块上进行内部开发可以是测试潜在实现的良好起点。

开源人工智能解决方案的进一步优势包括灵活性和保留定制解决方案知识产权的能力。开源人工智能工具的例子包括:

  • WIT AI —一个社区驱动的自然语言处理算法 API,将文本转换成可操作的流程。
  • R 编程 —为 R 编程环境开发 AI 解决方案的机器学习包库。
  • Acumos AI —一个面向数据科学家和开发人员的人工智能引擎,可以访问用于构建可部署解决方案的机器学习模块市场。
  • Caffe 2 —由脸书开发的支持跨*台部署的模块化轻量级深度学习框架。
  • 张量流 —谷歌开发的面向数字和科学数据流的机器学习框架。

将人工智能集成到业务流程中

利用人工智能云解决方案需要商业环境中的一些先决条件。需要对要考虑的业务流程进行实施人工智能解决方案的成本效益分析。被认为从人工智能中获益最多的过程将会对它们周围的过程产生影响;因此,对执行情况的流动和整体分析也将是建设性的。

人工智能的实施可能会扰乱员工的士气,特别是当成本降低是通过资本替代劳动力实现的时候。这需要进行管理,以便让那些参与实现的人参与进来,并让那些被替换的人参与到令人满意的过渡场景中。

技术开发需要与现有的过程基础设施、编程语言和输入/输出要求无缝集成。设计可以从定义存在什么输入和期望的输出开始。然后,可以围绕这些定义选择和调整适合的解决方案,以确保最终结果符合所需的值增益。

利用 quosures 在 R Shiny 中创建超灵活的过滤控件

原文:https://towardsdatascience.com/utilizing-quosures-to-create-ultra-flexible-filtering-controls-in-r-shiny-f3e5dc461399?source=collection_archive---------5-----------------------

我构建了很多闪亮的应用程序,其中一个常见的用途是允许动态过滤底层数据,这样你就可以根据感兴趣的特定子集来调整图表或表格。

通常,我们将过滤选项硬编码到某种形式的侧边栏菜单中,并为感兴趣的字段定义输入选项列表。例如,如果我们正在过滤mtcars数据集,我们可能会在 UI 端提供这样的输入选项列表:

shiny::selectInput('cyl', "Select no of cylinders", choices = mtcars$cyl %>% unique() %>% sort())

然后我们可以在服务器端使用input$cyl过滤mtcars,例如:

df <- shiny::reactive({
   mtcars %>% dplyr::filter(cyl == input$cyl)
})

我一直致力于创建一个更通用的结构,它允许完全灵活的动态过滤系统(类似于 MSExcel 电子表格中的过滤),允许用户选择他们希望过滤的任何字段,以及他们感兴趣的任何字段值。我还想对它进行设置,以便它可以通用地应用于任何数据集,只需要用户指定数据集和允许过滤的列名子集。

闪亮输入的参照透明度

为了做到这一点,我们必须避开非标准的评估问题。在上面的mtcars示例中,cylinput$cyl的处理方式不同。cylmtcars的上下文中是引用透明的,但是input$cyl作为输入变量被传递,其值被引用。例如,如果我们选择input$cyl = 6,这将被解释为我们在 dplyr 中所期望的:

df <- mtcars %>% dplyr::filter(cyl == '6')

这很好,但是如果我们想选择这个列作为闪亮的输入呢?例如,您可能希望您的用户能够选择 20 或 30 个不同的列进行筛选。也许我们可以为要过滤的选定列创建一个input$col,为选定的值创建一个input$val,如下所示:

df <- shiny::reactive({
   mtcars %>% dplyr::filter(input$col == input$val)
})

嗯,不,我们不能,因为input$col是作为引用值传递的,并且不是引用透明的。

这就是 quosures 真正有用的地方,它可以让你抽象出你的过滤能力(以及你的分组、选择和所有其他我们喜欢的关于dplyr的可爱的事情)。

考虑设置以下简单函数,允许您选择要筛选的列和值:

filter1_by <- function(df, fcol1, fv1) {

  filter_var1 <- dplyr::quo(fcol1) df %>% filter_at(vars(!!filter_var1), all_vars(. == fv1))}

这个简单的小函数允许我们使用filter_at()将列选择(fcol1)与值选择(fval1)分开处理。fcol1现在被捕获为带引号的表达式及其环境,使其在引用上透明,然后我们简单地使用!! (bangbang)操作符去掉引号,这样dplyr就可以接受不带引号但在引用上透明的列名。

不用说,这可以扩展到从任意数量的列中选择任意数量的输入进行过滤。例如,允许三个过滤器的函数如下所示:

filter3_by <- function(df, fcol1, fv1, fcol2, fv2, fcol3, fv3) {
  filter_var1 <- dplyr::quo(fcol1)
  filter_var2 <- dplyr::quo(fcol2)
  filter_var3 <- dplyr::quo(fcol3)df %>% 
     filter_at(vars(!!filter_var1), all_vars(. == fv1)) %>% 
     filter_at(vars(!!filter_var2), all_vars(. == fv2)) %>%
     filter_at(vars(!!filter_var3), all_vars(. == fv3))
)

让我们构建一个完整的示例

让我们继续使用mtcars构建一个完整的例子。假设我们希望用户能够从mtcars中的任何可用列中选择三列进行过滤。

我们首先从mtcars的列名创建一个向量,我们将使用它作为我们的初始输入选择:

fields <- colnames(mtcars)

让我们设置三个函数来基于一列、两列或三列进行筛选:

# filter on 1 columnsfilter1_by <- function(df, fcol1, fv1) {
  filter_var1 <- dplyr::quo(fcol1)df %>% 
     filter_at(vars(!!filter_var1), all_vars(. == fv1))
)# filter on 2 columnsfilter2_by <- function(df, fcol1, fv1, fcol2, fv2) {
  filter_var1 <- dplyr::quo(fcol1)
  filter_var2 <- dplyr::quo(fcol2)df %>% 
     filter_at(vars(!!filter_var1), all_vars(. == fv1)) %>% 
     filter_at(vars(!!filter_var2), all_vars(. == fv2))
)# filter on 3 columnsfilter3_by <- function(df, fcol1, fv1, fcol2, fv2, fcol3, fv3) {
  filter_var1 <- dplyr::quo(fcol1)
  filter_var2 <- dplyr::quo(fcol2)
  filter_var3 <- dplyr::quo(fcol3)df %>% 
     filter_at(vars(!!filter_var1), all_vars(. == fv1)) %>% 
     filter_at(vars(!!filter_var2), all_vars(. == fv2)) %>%
     filter_at(vars(!!filter_var3), all_vars(. == fv3))
)

现在,让我们构建一个闪亮的输入结构,允许我们至少过滤一列,但最多三列,使用复选框允许用户决定他们是否需要额外的过滤器:

shiny::mainPanel(
  # select first filter column from fields vector 
  shiny::selectInput("filter1", "Select filter column 1:", 
                     choices = fields),
  # reference a uiOutput that will offer values for first column
  shiny::uiOutput("filter1choice"),
  # offer a checkbox to allow user to select a second filter
  shiny::checkboxInput("filter2req", "Add second filter?"),
  # set further conditional panels to appear in the same fashion
  shiny::conditionalPanel(condition = 'input.filter2req', 
                          shiny::uiOutput("filter2eval"),
                          shiny::uiOutput("filter2choice"),
                          shiny::checkboxInput("filter3req", 
                                               "Add third filter?")),
  shiny::conditionalPanel(condition = 'input.filter3req & 
                                       input.filter2req', 
                  shiny::uiOutput("filter3eval"),
                  shiny::uiOutput("filter3choice"))

)

现在我们需要构建uiOutputs,它根据所选的过滤器列进行填充,并对已经选择的内容进行响应:

# vector of picklist values for the first selected filter 
choicevec1 <- reactive({
    mtcars %>%  dplyr::select(input$filter1) %>% unique() %>% dplyr::arrange_(input$filter1)
})# renders the picklist for the first selected filter
output$filter1choice <- renderUI(
  selectizeInput("filter1val", "Select filter 1 condition:", choices = choicevec1(), multiple = TRUE)
)# second column chosen from all remaining fields
output$filter2eval <- renderUI({
  selectInput("filter2", "Select filter criteria 2:", choices = sort(fields[fields != input$filter1]))
})# vector of picklist values for the second selected filter
choicevec2 <- reactive({
    filter1_by(mtcars, input$filter1, input$filter1val) %>% 
                       dplyr::select(input$filter2) %>% 
                       unique() %>% 
                       dplyr::arrange_(input$filter2)
})# renders picklist for filter 2
output$filter2choice <- renderUI(
  selectizeInput("filter2val", "Select filter 2 condition:", choices = choicevec2(), multiple = TRUE)
)# third column selected from remaining fields
output$filter3eval <- renderUI({
  selectInput("filter3", "Select filter criteria 3:", choices = sort(fields[!fields %in% c(input$filter1, input$filter2)]))
})# vector of picklist values for third selected column
choicevec3 <- reactive({
    filter2_by(mtcars, input$filter1, input$filter1val, 
               input$filter2, input$filter2val) %>% 
               dplyr::select(input$filter3) %>% 
               unique() %>% 
               dplyr::arrange_(input$filter3)
})# render picklist for filter 3
output$filter3choice <- renderUI(
  selectizeInput("filter3val", "Select filter 3 condition:", choices = choicevec3(), multiple = TRUE)
)

所以这就是我们在 UI 端需要做的全部。

在服务器端,我们现在只需要根据选择的输入定义我们需要的过滤器:

filtered_mtcars <- reactive({ # case when all three filters are used
  if (input$filter3req & input$filter2req) {
    filter3_by(mtcars, input$filter1, input$filter1val, 
               input$filter2, input$filter2val,
               input$filter3, input$filter3val) 
  } else if (input$filter2req) {
  # case when two filters are used
    filter2_by(mtcars, input$filter1, input$filter1val, 
               input$filter2, input$filter2val) 
  } else {
  # case when only one filter is used   
    filter1_by(mtcars, input$filter1, input$filter1val)
  }})

现在你可以显示你的反应数据框filtered_mtcars()或者在上面进行操作。

在实践和进一步发展中使用这种方法

这些功能可以很容易地移植到你正在设计的任何需要这种灵活过滤的应用程序中。通过简单地编写进一步的函数filter4_byfilter5_by等,您可以轻松地扩展到更多的过滤器选择。您还可以通过使用selectizeInput()并将==替换为filter_at()中的%in%来轻松调整选项列表中的多值选择。

见这里一个非常简单的演示应用程序,我构建了显示奥运会奖牌统计,允许多达三个过滤器。Github 的代码是这里是。

你能帮助改善这一点吗?理想情况下,我们只需要一个如下所示的过滤函数,而不是编写所有这些独立的函数filter1_byfilter2_by等:

filter_by <- function (df, ...) {
  filter_conditions <- quos(...)
  df %>% dplyr::filter(!!!filter_conditions)
}

其中输入是条件列表。这些输入将需要某种调整来应对非标准的评估,但我还没有想出它们应该如何措辞。

如果你破解了就告诉我。

最初我是一名纯粹的数学家,后来我成为了一名心理计量学家和数据科学家。我热衷于将所有这些学科的严谨性应用到复杂的人的问题上。我也是一个编码极客和日本 RPG 的超级粉丝。在LinkedInTwitter上找我。

数据科学家和人工智能产品 UX 设计指南

原文:https://towardsdatascience.com/ux-design-guide-for-data-scientists-and-ai-products-465d32d939b0?source=collection_archive---------3-----------------------

当查找 UX 人工智能产品的设计策略时,我几乎没有找到相关的资料。在我发现的少数几个中,大部分要么过于专业,要么完全专注于 web UIs 的视觉设计。我遇到的关于这个主题的最好的文章是 Vladimir Shapiro 的“ UX 的《人工智能:作为设计挑战的信任》”和 Dávid Pásztor 的“人工智能 UX:设计好的人工智能产品的 7 个原则”。意识到 UX 设计师和数据科学家之间存在着合理的知识差距,我决定尝试从数据科学家的角度来解决这些需求。因此,我的假设是读者对数据科学有一些基本的了解。对于几乎没有数据科学背景的 UX 设计师来说,我避免使用复杂的数学和编程(尽管我鼓励阅读迈克尔·加拉尼克的《如何建立数据科学组合》和我的《数据科学面试指南》。

人工智能正在接管我们日常生活的几乎每个方面。这将改变我们的行为方式以及我们对这些产品的期望。作为设计师,我们的目标是创造有用、易于理解的产品,为这个阴暗的新世界带来清晰。最重要的是,我们想用人工智能的力量让人们的生活变得更轻松、更快乐。

确定关键目标

甚至在我们试图设计我们的产品之前,我们需要理解我们的产品试图解决的整体商业模式。一些常见的问题是:

  • 该模型试图解决什么业务问题?是分类问题还是回归问题?
  • 谁是最终用户?他们是技术性的还是非技术性的?他们期望从该产品中获得什么价值?
  • 数据是什么?数据是静态的还是动态的?模型是基于状态的还是无状态的?正在收集的数据的粒度和质量如何?我们如何最好地表达这些信息?对数据使用是否有监管限制,如 PCI 、 HIPAA 或 GDPR ?
  • 这种模式的更大含义是什么?市场有多大?这个市场的其他参与者是谁?他们是在称赞你的产品还是直接竞争对手?转换成本是多少?需要考虑哪些关键的监管、文化、社会经济和技术趋势?

更好地了解最终产品将使我们能够更有效地满足需求。我推荐一些关于这个主题的书,如伯纳德·马尔的《智能公司:基于证据的管理成功的五个步骤》和亚历山大·奥斯特瓦尔德的《商业模式的产生:远见者、游戏改变者和挑战者手册》。

构建可解释的模型

虽然大多数人的目标是一个精确的模型,但是经常忘记理解模型为什么会这样做。模型的优缺点是什么?为什么它为给定的输入要素提供预测?虽然这个问题看起来微不足道,但许多行业都需要提供这个答案,作为其产品价值主张的一部分。

Model interpretation on Credit Karma, Netflix and Amazon

下面是一些真实生活中的用例,其中模型解释是最终用户所要求的:

  • 为什么你的信用评分没有现在高?
  • 为什么亚马逊推荐我购买某些产品?
  • 为什么自动驾驶汽车即使识别了行人也要撞车?

大多数机器学习模型,如决策树和逻辑回归,本质上都是可以解释的。我们可以分析权重系数,可视化树或计算熵来预测最终预测的主要贡献(详情此处)。虽然在过去,大多数商业问题依赖于简单的可解释的模型,但像神经网络这样的“黑箱”模型已经开始变得非常流行。这是因为神经网络以较低的成本为具有复杂决策边界的问题(例如图像和语音识别)提供了高得多的准确性。然而,与大多数传统模型相比,神经网络很难解释。对于有非技术人员的团队来说尤其如此,因为分析神经网络是一项重要的任务。

有些神经网络模型比其他模型更容易解释,例如下面的图像识别模型。

Visualizing Convolutional Neural Networks of an Image Classification Model (Source: Simonyan et al. 2013)

其他时候,我们可以根据预测和输入来推断工程特征。例如,模型可能不具有道路上存在冰的特征。然而,如果道路上的水的存在和道路的表面温度被模型拾取作为输入,我们可以直观地说,冰的存在可以通过特征工程由隐藏层导出。特斯拉的自动驾驶仪导致了致命事故,这只是为什么我们在自动驾驶汽车领域需要可解释的人工智能的一个例子。

Example of how Neural Networks create higher-order features in their hidden layers on self-driving vehicles

有关可解释模型的更多信息,请查看 Lars Hulstaer 的“解释机器学习模型”。

模型解释并不总是需要数学。定性地观察输入及其相应的输出通常可以提供有价值的见解。下面是一个智能安全摄像头误将一名窃贼识别为正在自拍的人,仅仅因为他像拿自拍杆一样拿着吧台。

Source: Mark West — Building a Smart Security Camera with Raspberry Pi Zero, Node.js and The Cloud

处理边缘案例

AI 可以生成内容,并采取以前没有人想到的行动。对于这种不可预测的情况,我们必须花更多的时间来测试产品,并找到怪异、有趣、甚至令人不安的不愉快的边缘情况。一个例子是对聊天机器人ٍbelow.的曲解

Chatbot fails due to unexpected user commands

广泛的实地测试有助于最大限度地减少这些错误。在生产模型上收集清晰的日志有助于在出现意外问题时进行调试。有关测试和 DevOps 相关主题的更多信息,请阅读我的“ DevOps for Data Scientists:驯服独角兽”。

从最终用户的角度来看,清楚地传达产品的功能可以帮助他们理解这些意外情况。例如,在许多情况下,模型必须在精确度和召回率之间进行权衡。

  • 优化召回意味着机器学习产品将使用它找到的所有正确答案,即使它显示一些错误的答案。假设我们构建了一个可以识别猫图片的 AI。如果我们优化召回,算法将列出所有的猫,但狗也会出现在结果中。
  • 为精确而优化意味着机器学习算法将只使用明显正确的答案,但它会错过一些边缘阳性的情况(看起来有点像狗的猫?).它只会显示猫,但会漏掉一些猫。它不会找到所有的正确答案,只会找到明确的案例。

当我们在人工智能 UX 上工作时,我们帮助开发者决定优化什么。提供关于人类反应和人类优先事项的有意义的见解可以证明是人工智能项目中设计师最重要的工作。

管理期望

虽然相信一个给定的模型可以解决世界上的任何场景是很有诱惑力的,但了解局限性并向最终用户坦诚这些局限性是很重要的。在她的演讲“我们不了解的信任”中,英国哲学家奥诺拉·奥尼尔指出了信任的三个组成部分:能力诚实可靠性。坦诚向客户表明,我们有足够的能力、诚实和可靠来维持成功业务所需的长期关系。否则,当产品不能交付时,满足过高的期望和失去信任就更加困难了。

金融产品就是很好的例子。根据政府规定,您的信用评分可能只考虑价值超过 2000 美元的资产。因此,在计算您的分数时,任何低于 2000 美元的资产都不会被模型考虑在内。网络安全产品也是如此。如果该模型每天或每周收集数据,就不能指望它监控 DDoS 攻击。

At 1.3 seconds before impact, Uber’s car decided emergency braking was necessary — but didn’t have the ability to do that on its own. The yellow bands show distance in meters, and the purple indicates the car’s path. (Source: National Transport Safety Board)

最*的优步自动驾驶车祸更是如此:

报告称,在撞击前大约一秒钟,“自动驾驶系统确定需要紧急制动来减轻碰撞。”然而,优步不允许其系统自行进行紧急制动。优步依靠其人类操作员来观察道路并在出现问题时进行控制,而不是冒着“车辆行为不稳定”的风险,如急刹车或转弯以避开塑料袋。

一个自然的反应是自行车上的摄像头没有拍摄到。然而,摄像头确实识别出了行人,但系统选择不停车。这是因为该模型不是为完全取代驾驶员而设计的。

提供反馈机会

好的 UX 设计的目标是交付最终用户满意的产品。为了确保你的用户得到他们想要的,给他们机会对人工智能内容给出反馈。这可以包括电影的评级系统或让银行知道他们的信用卡交易不是欺诈性的。下面是 Google Now 的一个例子。

Google Now asking for feedback on the Recommendation System’ s predictions

请记住,用户反馈也可以作为模型的训练数据。如果我们向机器学习算法提供更多数据,人工智能产品的用户体验会越来越好。

最终外卖

归根结底,人工智能的设计是为了解决一个问题,让生活变得更简单。在开发一个成功的产品时,必须始终以人为中心的设计为核心。没有解决客户需求是主要行业破产并被更好的服务提供商取代的原因。理解客户的需求是前进的关键。

如果你有想法或评论,欢迎订阅我的博客,在推特上关注我。

疫苗和数据科学是未来吗?

原文:https://towardsdatascience.com/vaccines-and-data-science-a-future-503d00716e4e?source=collection_archive---------8-----------------------

Made in Tableau

这个博客有双重目的。首先是给出我的项目是什么,它的目的的一个总体想法。二是更深入的讨论我的 EDA(探索性数据分析)的技术方面。所有的 EDA 都是使用 Anaconda 和 Tableau 完成的。

《英国医学杂志》已经并将继续认为疫苗是人类历史上最伟大的医学进步之一。有了疫苗,我们已经从人群中根除了天花甚至麻疹(短期内)。然而,随着越来越多的被误导的演员、政治家和家长参与进来,他们主张取消儿童疫苗接种,声称疫苗会导致自闭症;*年来,罗马尼亚的麻疹病例激增,爆发了约 3400 起病例,17 人死亡。后者已被一项系统综述无数次否定。2012 年发表在 Cochrane Collaboration 上的一项研究(5 项随机对照试验、1 项对照试验、27 项队列研究、17 项病例对照研究、5 项时间序列试验、1 项病例交叉试验、2 项生态学研究和 6 项自身对照病例系列研究)显示,没有证据表明 MMR 疫苗和自闭症之间存在关系。

As HealthCare Triage(由 Carroll 博士主持的关注健康领域的 Youtube 频道)讨论了各种研究疫苗和自闭症之间关系的研究,以及这些研究如何在让父母给孩子接种疫苗方面不起作用。

作为一名具有生物化学背景的数据科学家和一名在医学领域有着深厚投资的人。我开始研究是否有任何我可以公开使用的数据集来观察第一世界国家可预防疾病的趋势。经过搜索,我找到了一张地图,上面汇集了世界各地可预防疾病的爆发,甚至是对医疗服务提供者的袭击。这张地图是由外交关系委员会编制的。

[## 地图:疫苗可预防的疫情

外交关系委员会的全球健康项目自 2008 年以来一直在跟踪新闻报道,以产生一个…

www.cfr.org](https://www.cfr.org/interactives/GH_Vaccine_Map/#introduction)

在查看了数据和数据清理(主要涉及重命名数据帧中的行和列)之后。我决定忽略的数据是暴力,因为它不符合我接种疫苗和预防疾病的最初目标,并且影响了我的死亡率。我将公告作为变量之一,以观察它是否对任何疾病有任何影响。公告显示,在这两个地区与所有疾病呈负相关。我将北美和欧洲划分为两个独立的数据框架,因为它们有不同的人口和地理类型。这将影响数据相关性和统计。以及了解两个地区之间的差异。

Outbreaks in North America and European Nations using Tableau

总结:

欧洲的*均死亡人数为 226,456 例,占 20.29%,北美的*均死亡人数为 93,810 例,占 14.70%。当我们深入研究影响规模等变量时,我们发现地区是影响事件发生数量的一个重要因素。

了解每个区域的影响范围对于每个区域的行为非常重要。这种流行病更糟糕,因为它涉及到疾病病例数量的增加。其次是聚集性,是疾病病例的集合,但在时间和地点上是紧密分组的。继发性感染是指小于群集或大小相同但感染不局限于一个地方的病例。欧洲比北美有更多的流行病,这与地理和国家边界如何影响疾病的传播有关。

群体免疫是我们接种疫苗的主要原因之一,因为它们可以保护那些由于免疫系统受损而无法接种疫苗的人,或者他们太年轻而无法接种疫苗的人,例如新生儿。R0(R 0)> 1 的疾病成为疫情或流行病的可能性更高。麻疹的 R0(R 零)= 18,因此,如果一个人患有这种疾病,它会将麻疹传播给*均 18 个人。因此,MMR 疫苗(麻疹、腮腺炎、风疹)需要达到 92-95%的群体免疫。旨在实现这种群体免疫的疫苗接种计划至关重要。

变量的相关性

Europe Correlation Heatmap

North America Correlation Heatmap

在两张热图中都可以看到一些有趣的相关性。

  • 麻疹与其他疾病呈负相关,甚至与风疹和腮腺炎也呈负相关,而这两种疾病都是用同一种疫苗治疗的
  • 这两个地区的公告与病例和死亡呈负相关
  • 麻疹与北美的继发性麻疹和欧洲的流行性麻疹相关性最强
  • 在北美,百日咳与流行病有较高的相关性,在欧洲,百日咳与死亡有相关性

最后,这个项目有很多有趣的变量相关性。这需要进一步调查。

未完待续…

我在这个项目中的下一个目标是拟合一个模型,并尝试回答以下问题:

  • 我们能改进疫苗接种计划吗?
  • 我们能预测小热点吗?
  • 我们应该针对特定的城市进行疫苗接种吗?

如果你想知道这个项目是如何完成的,以及我接下来还有哪些医疗保健项目,你可以关注我这里的哈维尔·冈萨雷斯-Compte 或者查看我的 Github !随便打个招呼吧!

  1. 征服无法治愈的疾病。BMJ 2007;334 补充 1: s19。可用:www.bmj.com/cgi/data/334/suppl_1/DC2/1
  2. 随着麻疹在欧洲激增,官员们准备迎接艰难的一年。可用:http://www . NPR . org/sections/goatsandsoda/2017/04/07/522867040/as-麻疹-浪涌-在欧洲-官员-支撑-为一个粗糙的年
  3. 德米切利 V,里韦蒂 A,德巴利尼 MG,迪皮特兰托尼 c .https://www.ncbi.nlm.nih.gov/pubmed/22336803

vaex:Python 和快速可视化的核心数据框架

原文:https://towardsdatascience.com/vaex-out-of-core-dataframes-for-python-and-fast-visualization-12c102db044a?source=collection_archive---------7-----------------------

1,008,842,985 taxi dropoff location visualized in 1 second with vaex.

数据越来越大

有些数据集太大,不适合你的台式电脑的主存,更不用说你的笔记本电脑了。尽管如此,我们还是希望在大数据时代使用大型数据集。然而,我们真的不想为了一个小实验而学习设置 Hadoop 或 Spark 基础设施。

我们的梦想

如果您可以立即加载 1tb 的数据文件,只读取您需要的部分,并使用聪明的内核程序员花了几十年时间优化的策略,这不是很好吗?在提出疯狂请求的同时,我们为什么不请求一个感觉有点像熊猫的 API,我们都在使用它。哦,对了,请不要在我的 2013 MacBook Air 上占用太多内存。因为现在是 2018 年,我们都在 Jupyter 笔记本上工作,所以也让它工作,好吗?请确保我所有打开的笔记本也共享该数据集的内存。

如果能瞬间加载 1 TB 的数据文件岂不是很棒。

让我们的梦想成为可能

所有这些都可以通过内存映射来实现,这是一种告诉操作系统您希望一块内存与磁盘上的内容同步的技术。它在技术上非常类似于交换磁盘。如果一块内存没有被修改,或者有一段时间没有被使用,内核将丢弃它,以便 RAM 可以被重用。此外,打开相同文件的所有进程共享相同的物理内存。

内存映射非常出色,你可以立即对一个 1 TB 的文件进行内存映射,内核会智能地决定读取或丢弃什么。现在假设您想过滤掉一些包含不相关数据的行。在 pandas 中,使用我们的 1 TB 数据帧,我们可以执行df_filtered = df[df.x > 0],这将复制所有数据,再占用 0.8 TB……实际上,您会看到一个内存错误。

遇见 vaex

Vaex 是一个 Python 库,使得处理如此大的数据集变得轻而易举。除了内存映射之外,除非明确请求,否则它永远不会接触或复制数据。这使得处理硬盘大小的数据集成为可能。此外,它可以进行惰性计算,使用虚拟列,进行有效的数据清理,计算快速的 N 维统计数据,创建交互式可视化等等。
我猜又是一种新的文件格式?不,我们使用好的 ol' hdf5 格式,任何有自尊的语言都支持这种格式。Vaex 并不真正关心文件格式,只要你能内存映射数据,你就会长寿,繁荣🖖.

阿帕奇箭头

hdf5 不够新颖性感吗?好的,我们支持 Apache Arrow ,它也允许内存映射和与其他语言的互操作性。

所以…没有熊猫🐼?

原作者韦斯·麦金尼(Wes McKinney)在他颇有见地的博客文章中概述了熊猫的一些问题:“ 阿帕奇箭头和“我讨厌熊猫的 10 件事”。这些问题中的许多将在下一版本的熊猫(pandas2?),构建在 Apache Arrow 和其他库之上。Vaex 从头开始,同时保持 API 相似,并准备好今天使用

Vaex 很懒

Vaex 不仅仅是熊猫的替代品。尽管在执行像np.sqrt(ds.x**2 + ds.y**2)这样的表达式时,它有一个类似 pandas 的 API 用于列访问,但是不会发生任何计算。而是创建一个 vaex 表达式对象,当打印出来时,它显示一些预览值。

Calling numpy functions with vaex expression leads to a new expression, which delays a computation and saves RAM.

使用表达式系统,vaex 仅在需要时执行计算。此外,数据不需要在本地:表达式可以通过网络发送,统计数据可以远程计算,这是vaex-server包提供的。

虚拟列

我们还可以向数据帧添加表达式,这将产生虚拟列。虚拟列的行为类似于常规列,但不占用内存。Vaex 不区分真实列和虚拟列,它们被*等对待。

Adding a new virtual column to a DataFrame takes no extra memory.

如果一个表达式在运行时计算起来非常昂贵,该怎么办?通过使用python或 Numba ,我们可以使用手动实时(JIT)编译来优化计算。

Using Numba or Pythran we can JIT our expression to squeeze out a better performance: > 2x faster in this example.

甚至远程数据帧也支持 JIT 表达式(JIT 发生在服务器上)。

内存充足吗?只是物化这个列。你可以选择以 RAM 为代价挤出额外的性能。

Materializing a column converts a virtual column into an in-memory array. Great for performance (~8x faster), but you need some extra RAM.

数据清理

对数据帧的过滤,例如ds_filtered = ds[ds.x >0],仅仅导致对现有数据的引用加上一个布尔掩码,该掩码跟踪哪些行被选择,哪些行没有被选择。几乎没有内存使用,也没有内存复制。

df_filtered has a ‘view’ on the original data. Even when you filter a 1TB file, just a fraction of the file is read.

几乎没有内存使用,也没有内存复制。

除了过滤数据帧,选择还可以定义数据的子集。通过选择,您可以在单次通过数据时计算多个子集的统计数据。这对于不适合内存(核外)的数据帧非常有用。

Passing two selections results in two means in a single pass over the data.

缺失的价值观可能是一种真正的痛苦,并不总是很容易决定如何对待它们。使用 vaex,您可以轻松地填充或删除缺少值的行。但是事情是这样的:dropna 和 fillna 方法都是通过过滤和表达式实现的。这意味着,例如,无论数据集的大小如何,您都可以在没有额外内存开销的情况下尝试多个填充值。

You can try several fill values at virtually no extra memory cost.

分类统计

Vaex 在统计方面真的很强。因为我们正在处理大数据,所以我们需要一种替代 groupby 的方法,一种计算速度更快的方法。相反,您可以在一个常规的 N 维网格上计算统计数据,这非常快。例如,即使数据集包含 10 亿行(是的,每秒 10 亿行),也要花大约一秒钟来计算常规箱中一列的*均值!)。

Every statistic method accepts a binby argument to compute statistics on regular Nd array.

是的,每秒 10 亿行!

形象化

制作有意义的图表和可视化是理解数据的最佳方式。但是,当你的数据框架包含 10 亿行时,制作标准散点图不仅需要很长时间,而且会产生无意义和难以辨认的视觉效果。如果您关注聚合属性(如计数、总和、*均值、中值、标准差等),您可以更好地了解数据的结构。)的一个或多个特征/列。当在箱中计算时,这些统计数据给出了数据如何分布的更好的想法。Vaex 擅长此类计算,结果很容易可视化。

让我们看看这些想法的一些实际例子。我们可以使用直方图来可视化单个列的内容。

这可以扩展到二维,产生一个热图。我们可以计算*均值,取总和的对数,或者任何自定义的统计数据,而不是像典型的热图那样简单地计算落入每个箱的样本数。

我们甚至可以使用 ipyvolume 制作三维体积渲染。

由于在 N 维网格上计算统计数据的底层机制如此之快,我们可以在运行中完成它们,并拥有交互式可视化
(基于 bqplot )。

Interactively exploring 150 million taxi trips using vaex+bqplot

更多?

是的,vaex 包括一个厨房水槽,但它是一个模块化厨房水槽。Vaex 实际上是一个元包,它将安装 vaex 家族中的所有 Python 包。以下是软件包列表:

  • vaex-core : DataFrame 和核心算法,将 numpy 数组作为输入列。
  • vaex-hdf5:向 vaex 数据帧提供内存映射的 numpy 数组。
  • vaex-arrow:类似,但是用的是阿帕奇箭。
  • vaex-viz:基于 matplotlib 的可视化。
  • vaex-jupyter:基于 Jupyter widgets/ipywidgets、 bqplot 、 ipyvolume 和 ipyleaflet 的交互可视化。
  • vaex-astro:天文学相关的转换和 FITS 文件支持。
  • vaex-server:提供远程访问数据帧的服务器。
  • vaex-distributed:(概念验证)将多个服务器/集群组合成一个数据框架,用于分布式计算。
  • vaex-ui:基于 Qt 的交互式独立 app/GUI。

想要更多吗?

我们一直在努力让 vaex 变得更好。但这还不是全部。我们也在非常努力地开发vaex-ml,这是一个为 vaex 增加机器学习能力的包。一些非常酷的东西即将推出,敬请关注!与此同时,请查看这个现场演示,了解 vaex 的实际操作和vaex-ml的预览。

通过我们在 PyParis 2018 上的现场演示,了解有关 vaex 和 vaex-ml 的更多信息

您也可以使用 mybinder 在 Jupyter 笔记本上在线试用这篇文章的片段:

Click the button to launch a Jupyter notebook to try out the code snippets from the article

结论

你准备好接受大表格数据了吗?我们是!零内存复制策略、内存映射、类似 pandas 的 API 以及 N 维网格上极快的统计计算速度,使 vaex 成为探索和分析海量数据集的首选 Python 库。所有这一切都来自您舒适的笔记本电脑或个人电脑。Vaex 是开源的(MIT),在 GitHub 上,查看它的主页,文档文档,或者在 gitter 上提问。尝试一下,让我们知道你的想法。

Maarten Breddels 是一名企业家和自由职业开发人员/顾问/数据科学家,主要从事 Jupyter 生态系统中的 Python、C++和 Javascript 工作。 的创始人 vaex.io 。他的专业领域从快速数值计算、API 设计到 3d 可视化。他拥有 ICT 学士学位,天文学硕士和博士学位,喜欢编码和解决问题。

股票图片来自https://pixabay.com/

可变自动编码器

原文:https://towardsdatascience.com/variational-auto-encoders-fc701b9fc569?source=collection_archive---------2-----------------------

当我们遇到没有标签的数据会怎样?大多数深度学习技术需要干净标签的数据,但这有多现实?其核心是,这种技术本质上是说,如果你有一组输入和它们各自的目标标签,你可以尝试和学习一个特定标签对于一个特定目标的概率。当然,所以美化图像映射?在这篇文章中,我将探索变分自动编码器,以更深入地探索未标记数据的世界。该模型将在对没有标签的图像集合进行训练之后生成独特的图像。

自动编码器顺序地将输入数据解构造成隐藏的表示,并使用这些表示来顺序地重建与其原始数据相似的输出。从本质上讲,数据压缩是特定于数据的,这意味着它只能压缩与其接受训练的数据相似的数据。众所周知,自动编码器也是有损耗的,因此解压缩后的输出与原始输入相比会有所下降。那么,如果它们导致质量下降,为什么它们有用呢?好问题是,它们对数据去噪非常有用,我们训练自动编码器从其自身的损坏版本中重建输入,以便它可以消除类似的损坏数据。

在这篇文章中,我通过他的 youtube 频道使用我的主要男人,Siraj 的支持,并潜入变分自动编码器(VAE)。

让我们从贝叶斯推断说起。阅读这篇文章的每个人可能都知道深度学习及其在逼*复杂函数时的有用性,然而,贝叶斯推理提供了一个推理不确定性的独特框架。在其中,所有的不确定性都用概率来表示。如果你想一想,这是有意义的,在任何给定的时间都存在支持或反对我们已经知道的东西的证据,这些证据可以用来创造一个新的概率。进一步延伸,当我们学习新的东西时,我们必须考虑到我们已经知道的东西,并加入新的证据来创造新的概率。贝叶斯理论基本上从数学上描述了这个想法。

VAE 是这些思想的产物。从贝叶斯的角度来看,我们可以将 VAE 的输入、隐藏表示和重构输出视为有向图形模型中的概率随机变量。假设它包含某些数据的特定概率模型 x 和潜在/隐藏变量 z。我们可以将模型的联合概率写出如下:

Joint Probability of a Model

给定一个由模型产生的角色,我们不知道潜在变量的什么设置产生了这个角色,我们的模型本质上是随机的!

现在,让我们打开深度学习镜头,VAE 由 3 个主要部分组成:

  • 编码器
  • 解码器
  • 损失函数

给定一些输入 x,假设我们有一个 28 乘 28 的手写数字图像,它有 784 个维度,其中每个像素是一维的。现在,这将编码成一个潜在的/隐藏的表示空间,这将比 784 少得多。我们现在可以对高斯概率密度进行采样,以获得表示的噪声值。

酷毙了。让我们用代码来写吧!(我已经在这篇文章的末尾链接了完整的代码)

首先,我们导入库并找到我们的超参数。

import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm
from keras.layers import Input, Dense, Lambda
from keras.models import Model
from keras import backend as K
from keras import objectives
from keras.datasets import mnist# Hyperparameters
batch_size = 100
original_dim = 784
latent_dim = 2
intermediate_dim = 256
nb_epoch = 10
epsilon_std = 1.0

接下来,我们初始化我们的编码器网络。这个网络的工作是将输入映射到我们隐藏的分布参数。我们获取输入,并通过 ReLU(压缩维度的经典非线性)的密集全连接层发送。接下来,我们将输入数据转换成隐藏空间中的两个参数。我们使用密集、完全连接的层来预定义大小——z 均值和 z 对数西格玛。

#encoder
x = Input(batch_shape = (batch_size, original_dim))
h = Dense(intermediate_dim, activation = ‘relu’)(x)
z_mean = Dense(latent_dim)(h)
z_log_var = Dense(latent_dim)(h)print(z_mean)
print(z_log_var)

解码器将“z”作为其输入,并将参数输出到数据的概率分布。让我们假设每个像素是 1 或 0(黑或白),现在我们可以使用伯努利分布,因为它将成功定义为一个二进制值来表示单个像素。因此,解码器将获得一个数字的潜在/隐藏表示作为其输入,并且它输出 784 个伯努利参数,每个像素一个,因此本质上是 0 和 1 之间的 784 个值。

我们将使用 z_mean 和 z_log_var,通过定义采样函数,从隐藏/潜在正态分布中随机采样新的相似点。下面代码块中的ε是一个随机正规张量。

def sampling(args):
 z_mean, z_log_var = args
 epsilon = K.random_normal(shape=(batch_size, latent_dim), mean=0.)
 return z_mean + K.exp(z_log_var / 2) * epsilon

# note that “output_shape” isn’t necessary with the TensorFlow backend
z = Lambda(sampling, output_shape=(latent_dim,))([z_mean, z_log_var])#latent hidden state
print(z)

一旦我们得到 z,我们可以把它输入到我们的解码器,解码器会把这些潜在空间点映射回原始输入数据。因此,为了构建一个解码器,我们首先用两个完全连接的层和它们各自的激活函数来初始化它。因为数据是从一个小的维度提取到一个更大的维度,所以在重建过程中会丢失一些数据。

#decoder
# we instantiate these layers separately so as to reuse them later
decoder_h = Dense(intermediate_dim, activation=’relu’)
decoder_mean = Dense(original_dim, activation=’sigmoid’)
h_decoded = decoder_h(z)
x_decoded_mean = decoder_mean(h_decoded)print(x_decoded_mean)

酷,但是一些多少钱?所以我们将建立损失函数来精确测量。下面的第一项测量重建损失。如果解码器输出在重建数据方面表现不佳,此时将考虑损失方面的成本。下一个术语是正则化,这意味着它尽可能保持每个数字的表示形式多样化。举个例子,如果两个不同的人写出数字 3,结果可能看起来非常不同,因为,当然,不同的人写的不同。这可不好,正则来救援!我们惩罚不良行为(像这里的例子),并确保类似的表现是紧密联系在一起的。我们的总损失函数被定义为我们的重建项和 KL 散度正则化项之和。

#loss
def vae_loss(x, x_decoded_mean):
 xent_loss = original_dim * objectives.binary_crossentropy(x, x_decoded_mean)
 kl_loss = — 0.5 * K.sum(1 + z_log_var — K.square(z_mean) — K.exp(z_log_var), axis=-1)
 return xent_loss + kl_lossvae = Model(x, x_decoded_mean)
vae.compile(optimizer=’rmsprop’, loss=vae_loss)

现在是训练部分,我们通常使用梯度下降来训练该模型,以优化编码器和解码器参数的损失。但是我们如何对随机变量的参数求导呢?

事实证明,我们已经将随机性融入了我们的模型本身。现在,梯度下降通常期望对于一组固定的参数,给定的输入总是返回相同的输出。在我们的例子中,随机性的唯一来源是输入。那么我们如何解决这个问题呢?我们参数化!我们将对样本进行参数化,以使随机性与参数无关。

我们将定义一个确定性地依赖于参数的函数,因此我们可以通过引入一个随机变量将随机性注入到模型中。编码器将生成均值向量和标准差向量,而不是生成实值向量。我们对包含 z 的函数求关于其分布参数的导数。我们已经将模型的优化器定义为 rmsprop,将损失函数定义为 vae_loss。

我们通过导入 MNIST 数据集并根据给定的历元数和批量大小将它们输入到我们的模型中来开始下面的训练。

# train the VAE on MNIST digits
(x_train, y_train), (x_test, y_test) = mnist.load_data()x_train = x_train.astype(‘float32’) / 255.
x_test = x_test.astype(‘float32’) / 255.
x_train = x_train.reshape((len(x_train), np.prod(x_train.shape[1:])))
x_test = x_test.reshape((len(x_test), np.prod(x_test.shape[1:])))vae.fit(x_train, x_train,
 shuffle=True,
 nb_epoch=nb_epoch,
 batch_size=batch_size,
 validation_data=(x_test, x_test),verbose=1)

下面我们在一个 2D *面上画出了邻*区域。每个彩色的簇代表一个数字表示,紧密的簇实质上是结构相似的数字。

# build a model to project inputs on the latent space
encoder = Model(x, z_mean)# display a 2D plot of the digit classes in the latent space
x_test_encoded = encoder.predict(x_test, batch_size=batch_size)
plt.figure(figsize=(6, 6))
plt.scatter(x_test_encoded[:, 0], x_test_encoded[:, 1], c=y_test)
plt.colorbar()
plt.show()

Digit Representation

表示这一点的另一种方式是通过扫描潜在*面、以规则的间隔对潜在点进行采样并为这些点中的每一个生成相应的数字,如下所示:

# build a digit generator that can sample from the learned distribution
decoder_input = Input(shape=(latent_dim,))
_h_decoded = decoder_h(decoder_input)
_x_decoded_mean = decoder_mean(_h_decoded)
generator = Model(decoder_input, _x_decoded_mean)# display a 2D manifold of the digits
n = 15 # figure with 15x15 digits
digit_size = 28
figure = np.zeros((digit_size * n, digit_size * n))
# linearly spaced coordinates on the unit square were transformed through the inverse CDF (ppf) of the Gaussian
# to produce values of the latent variables z, since the prior of the latent space is Gaussian
grid_x = norm.ppf(np.linspace(0.05, 0.95, n))
grid_y = norm.ppf(np.linspace(0.05, 0.95, n))for i, yi in enumerate(grid_x):
 for j, xi in enumerate(grid_y):
 z_sample = np.array([[xi, yi]])
 x_decoded = generator.predict(z_sample)
 digit = x_decoded[0].reshape(digit_size, digit_size)
 figure[i * digit_size: (i + 1) * digit_size,
 j * digit_size: (j + 1) * digit_size] = digitplt.figure(figsize=(10, 10))
plt.imshow(figure, cmap=’Greys_r’)
plt.show()

Generated Digits

这在一定程度上让你大吃一惊!

因此,在这个练习的本质上,有三个要点:

  • 变分编码器允许我们通过执行无监督学习来生成数据
  • VAEs =贝叶斯推理+深度学习
  • 重新参数化允许我们通过网络反向传播,通过使随机性独立于允许我们导出梯度的参数。

在机器学习的宇宙中,这是一个非常迷人的世界,我希望我能够通过这篇文章给你带来一些价值!

解释了各种自动编码器

原文:https://towardsdatascience.com/variational-autoencoders-explained-6f9456ee030c?source=collection_archive---------7-----------------------

想知道变分自动编码器(VAE)模型是如何工作的吗?你想知道 VAE 是如何能够生成与它所训练的数据集相似的新样本的吗?

读完这篇文章后,你将对 VAE 的内部运作有一个理论上的理解,并且能够自己实现它。

在未来的一篇文章中,我将为你提供一个在手写数字图像数据集上训练的 VAE 的工作代码,我们将有一些生成新数字的乐趣!

生成模型

VAE 是一个生成模型,它估计训练数据的概率密度函数(PDF)。如果这样的模型是在看起来自然的图像上训练的,它应该给狮子的图像分配高概率值。另一方面,随机乱码的图像应该被赋予低概率值。

VAE 模型还可以从学习过的 PDF 中抽取样本,这是最酷的部分,因为它能够生成看起来与原始数据集相似的新样本!

我将使用 MNIST 手写数字数据集来解释 VAE。模型的输入是 2828 维空间(ℝ[28∙28]).)中的图像如果输入看起来像一个数字,模型应该估计一个高概率值。

对图像建模的挑战

像素之间的相互作用带来了巨大的挑战。如果像素是彼此独立的,我们将需要独立地学习每个像素的 PDF,这很容易。采样本来也是轻而易举的——我们只是独立地对每个像素进行采样。

在数字图像中,像素之间有明显的相关性。如果你看一个图像的左半部分,看到一个 4 的开始,你会非常惊讶地看到右半部分是一个 0 的结束。但是为什么呢?…

潜在空间

你知道一个数字的每个图像应该包含一个单独的数字。ℝ[28∙28 的输入]并不明确包含该信息。但是它一定存在于某个地方…某个地方的就是潜在空间。

The latent space. Photo by Samuel Zeller on Unsplash

你可以把潜在空间想象成ℝ[k 】,其中每个矢量都包含绘制一幅图像所需的 k 条基本信息。假设第一维包含由数字表示的数字。第二维可以是宽度。第三——角度。诸如此类。

我们可以把生成图像的过程想象成一个两步过程。首先,这个人有意识或无意识地决定他要画的数字的所有属性。接下来,这些决定转化为笔触。

VAE 试图对这一过程进行建模:给定一幅图像 x ,我们想要找到至少一个能够描述它的潜在向量——一个包含生成 x 的指令的向量。使用全概率的定律公式化它,我们得到

让我们给这个等式注入一些直觉:

  • 积分意味着我们应该在整个潜在空间中寻找候选者。
  • 对于每一个候选 z ,我们问自己:是否可以使用 z 的指令生成 xP(x|z) 够大吗?例如,如果 z 对数字为 7 的信息进行编码,则 8 的图像是不可能的。然而,1 的图像可能是可能的,因为 1 和 7 看起来相似。
  • 我们找到一个好的 z ?很好!但是等一下…这有可能吗? P(z) 够大吗?让我们考虑一个颠倒的 7 的给定图像。描述相似外观 7 的潜在向量将是完美匹配,其中角度维度被设置为 180 度。然而,那个 z 不太可能,因为通常数字不会以 180 度角绘制。

VAE 的训练目标是最大化 P(x) 。我们将使用多元高斯𝓝 (f(z),𝜎I)P(x|z) 建模。

f(z) 将使用神经网络建模。 𝜎 是一个将单位矩阵 I 相乘的超参数。

你应该记住 f 是我们在使用训练好的模型生成新图像时要用到的。强加高斯分布仅用于训练目的。如果我们使用 Dirac delta 函数(即 x = f(z) 确定性),我们将无法使用梯度下降来训练模型!

潜在空间的奇迹

潜在空间方法有两个大问题:

  1. 每个维度包含哪些信息?一些维度可能与抽象的信息有关,例如风格。即使解释所有维度很容易,我们也不想给数据集分配标签。这种方法无法扩展到新的数据集。
  2. 潜在空间可能是纠缠的,即维度可能是相关的。例如,一个手指画得非常快,可能会导致有角度的和更细的笔触。指定这些依赖关系很难。

深度学习拯救世界

事实证明,每个分布都可以通过对标准多元高斯函数应用足够复杂的函数来生成。

因此,我们将选择 P(z) 作为标准多元高斯。由神经网络建模的 f 因此可以分为两个阶段:

  1. 第一层将高斯映射到潜在空间的真实分布。我们无法解释维度,但这并不重要。
  2. 然后,后面的层将从潜在空间映射到 P(x|z)

那么我们该如何训练这只野兽呢?

P(x) 的公式很难处理,所以我们将使用蒙特卡罗方法来*似它:

  1. 样本{ zᵢ } (i = 1…n)来自先前的 P(z)
  2. *似使用p(x)(1/n)∙∑p(x|zᵢ)

太好了!因此,我们只需对一些 z 进行采样,然后让反向传播派对开始!

不幸的是,由于 x 具有高维数,因此需要许多样本来获得合理的*似。我的意思是,如果你对 z 进行采样,你最终得到一个看起来和 x 有关的图像的可能性有多大?顺便说一下,这解释了为什么 P(x|z) 必须为任何可能的图像分配正概率值,否则模型将无法学习:采样的 z 将产生几乎肯定不同于 x 的图像,如果概率为 0,梯度将不会传播。

那么,我们如何解决这个烂摊子呢?

我们走捷径吧!

Photo by Stefan Steinbauer on Unsplash

大多数被取样的 z 对 P(x)没有任何贡献——它们太差了。如果我们能提前知道从哪里取样就好了…

我们可以引入 Q(z|x)Q 将被训练为向可能已经生成 xz 给出高概率值。现在,我们可以使用来自 Q 的更少样本来计算蒙特卡罗估计。

不幸的是,新的问题出现了!而不是最大化

我们将最大化以下内容

这两者之间有什么关系?

变分推理

变分推理是一个自成一帖的话题,这里就不细说了。我要说的是,这两者确实通过这个等式联系在一起:

KL 是kull back–lei bler 散度,它直观地衡量两个分布有多相似。

一会儿你会看到我们如何最大化等式的右边。这样,左侧也将被最大化:

  • P(x) 将被最大化。
  • P(z|x)Q(z|x) 有多远——我们不知道的真实后验——将被最小化。

等式右边背后的直觉是我们有一个张力:

  1. 一方面,我们希望最大化从 z ~ Q 解码 x 的效果。
  2. 另一方面,我们希望Q(z | x)(编码器)类似于先前的 P(z) (多元高斯)。人们可以把这个术语看作是正则化。

给定正确的分布选择,最小化 KL 散度是容易的。我们将把 Q(z|x) 建模为神经网络,其输出是多元高斯的参数:

  • 一个*均值 μ_Q
  • 对角协方差矩阵σ_ Q

KL 散度然后变得解析可解,这对我们(和梯度)是很好的。

解码器部分有点棘手。天真的是,我们会用蒙特卡罗来解决这个棘手的问题。但是从 Qz 进行采样不会允许梯度通过 Q 传播,因为采样不是可微分的操作。这是有问题的,因为输出σ_ Qμ_Q 的层的权重不会被更新。

重新参数化的技巧

我们可以用无参数随机变量的确定性参数化变换来代替 Q :

  1. 来自标准(无参数)高斯的样本。
  2. 将样本乘以σ_ Q的*方根。
  3. μ_Q 加到结果上。

结果将具有等于 Q 的分布。现在采样操作将从标准高斯。因此,梯度将能够通过σ_ Qμ_Q 传播,因为现在这些是确定性路径。

结果呢?该模型将能够学习如何调整 Q 的参数:它将集中于能够产生 x 的好的 z

将这些点连接起来

VAE 模式可能很难理解。我们在这里讨论了很多材料,可能会让人不知所措。

因此,让我总结一下实施 VAE 需要掌握的所有步骤。

左侧是模型定义:

  1. 输入图像通过编码器网络。
  2. 编码器输出分布参数 Q(z|x)
  3. Q(z|x) 中采样潜在向量 z 。如果编码器学会做好它的工作,大多数机会是 z 将包含描述 x 的信息。
  4. 解码器将 z 解码成图像。

右边是损失:

  1. 重构误差:输出应该类似于输入。
  2. Q(z|x) 应该类似于先验(多元标准高斯)。

为了生成新的图像,可以直接从先验分布中采样一个潜在向量,并将其解码成图像。

在下一篇文章中,我会给你提供一个 VAE 的工作代码。此外,我将向您展示如何使用一个巧妙的技巧来调节潜在向量,以便您可以决定要为哪个数字生成图像。敬请期待:)

笔记

这篇文章是基于我的直觉和以下来源:

  • 变分推理和深度学习:一种新的综合
  • 变型自动编码器教程

这个帖子最初是我在www.anotherdatum.com发的。

变型自动编码器详细解释

原文:https://towardsdatascience.com/variational-autoencoders-explained-in-detail-d585327c660a?source=collection_archive---------2-----------------------

在本系列的前一篇文章中,我介绍了变分自动编码器(VAE)框架,并解释了其背后的理论。

在这篇文章中,我将更详细地解释 VAE,或者换句话说,我将提供一些代码:)

读完这篇文章后,你会理解实现 VAE 所需的技术细节。

作为奖励,我将向您展示如何通过对一些潜在向量的维度施加特殊作用,该模型可以根据手指类型生成图像。

该模型将在MNIST——手写数字数据集上进行训练。输入是ℝ[28∙28].的图像

接下来,我们将定义将要使用的超参数。

随意使用不同的值来感受模型是如何被影响的。笔记本可以在这里找到。

模型

该模型由三个子网络组成:

  1. 给定 x (图像),将其编码成潜在空间上的分布——在前一篇文章中称为Q(z|x)。
  2. 给定 z 在潜空间(一个图像的代码表示),解码成它所表示的图像——在上一篇文章中称为 f ( z )。
  3. 给定 x ,通过将其映射到大小为 10 的层来对其数字进行分类,其中第 I 个值包含第 I 个数字的概率。

前两个子网络是普通的 VAE 框架。

第三个用作辅助任务,它将执行一些潜在维度来编码图像中的数字。让我解释一下动机:在上一篇文章中,我解释过我们不在乎潜在空间的每个维度包含什么信息。该模型可以学习编码它认为对其任务有价值的任何信息。因为我们熟悉数据集,所以我们知道数字类型应该很重要。我们希望通过向模型提供这些信息来帮助它。此外,我们将使用这些信息生成以手指类型为条件的图像,我将在后面解释。

给定数字类型,我们将使用一种热编码对其进行编码,即大小为 10 的向量。这 10 个数字将被连接成潜在向量,因此当将该向量解码成图像时,该模型将利用数字信息。

有两种方法为模型提供一个热编码向量:

  1. 将其作为输入添加到模型中。
  2. 将它添加为标签,这样模型将必须自己预测它:我们将添加另一个预测大小为 10 的向量的子网络,其中损失是与预期的一个热向量的交叉熵。

我们将采用第二种选择。为什么?在测试时,我们可以以两种方式使用这个模型:

  1. 提供图像作为输入,并推断潜在向量。
  2. 提供潜在向量作为输入,并生成图像。

因为我们也想支持第一个选项,所以我们不能为模型提供数字作为输入,因为我们在测试时不会知道它。因此,模型必须学会预测它。

既然我们已经了解了组成模型的所有子网,我们就可以对它们进行编码了。编码器和解码器背后的数学细节可以在之前的文章中找到。

培养

我们将使用 SGD 训练模型来优化两种损失——VAE 损失和分类损失。

在每个时期结束时,我们将对潜在向量进行采样,并将它们解码成图像,这样我们就可以直观地看到模型的生成能力如何随着时期的推移而提高。取样方法如下:

  1. 根据我们想要生成图像的数字,确定性地设置用于数字分类的维度。例如,如果我们想要生成数字 2 的图像,这些尺寸将被设置为[0010000000]。
  2. 根据先验——多元高斯随机抽取其他维度的样本。我们将把这些采样值用于我们在给定时期生成的所有不同数字。通过这种方式,我们可以对其他维度的编码有一种感觉,例如笔画风格。

步骤 1 背后的直觉是,在收敛之后,模型应该能够使用这些维度对输入图像中的数字进行分类。另一方面,这些维度也用于解码步骤以生成图像。这意味着解码器子网络了解到当这些维度具有对应于数字 2 的值时,它应该生成该数字的图像。因此,如果我们手动设置这些维度来包含数字 2 的信息,我们将得到该数字的生成图像。

让我们验证一下这两种损失看起来都不错,也就是说——在减少:

此外,让我们绘制生成的图像,看看模型是否真的能够生成数字图像:

最后的想法

很高兴看到使用一个简单的前馈网络(没有花哨的卷积),我们能够在仅仅 20 个时期后生成好看的图像。该模型很快学会了使用特殊的数字维度——在第 9 纪元,我们已经看到了我们试图生成的数字序列。

每个纪元对其他维度使用不同的随机值,因此我们可以看到不同纪元之间的风格如何不同,而每个纪元内部的风格是相似的——至少对于某些纪元而言是如此。例如,与时段 20 相比,在时段 18,所有的数字都更粗。

我邀请你打开这个笔记本和 VAE 一起玩耍。例如,超参数值对生成的图像有很大影响。玩得开心:)

原文由我在发表。

变分推理:伊辛模型

原文:https://towardsdatascience.com/variational-inference-ising-model-6820d3d13f6a?source=collection_archive---------9-----------------------

在二值图像去噪的应用中

本文主要研究 Ising 模型的变分推理在二值图像去噪中的应用。

Noisy gray-scale image (left) and denoised binary image (right)

例如,在上图中,左边是一幅有噪声的灰度图像,右边是一幅去噪的二值图像。

伊辛模型是马尔可夫随机场(MRF)的一个例子,它起源于统计物理学。伊辛模型假设我们有一个节点网格,其中每个节点可以处于两种状态之一。在二进制图像的情况下,您可以将每个节点看作是一个黑色或白色的像素。每个节点的状态通过相互作用势依赖于相邻节点。在图像的情况下,这转化为*滑度约束,即像素喜欢与相邻像素具有相同的颜色。

在图像去噪问题中,我们假设我们有一个潜在真实图像的噪声像素观察的 2-D 网格,并且我们想要恢复真实图像。因此,我们可以将图像建模为网格:

Variational approximation (left) and the Ising model [1] (right)

上图显示了 Ising 模型1,其中阴影节点是{-1,+1}中二元潜在变量(无阴影节点)x _ i \的噪声观测值 y_i。左边的方程代表我们的变分*似,我们将在下面得到。

我们可以将联合分布写为:

其中,对于一组边 E 中的每对节点 x_s 和 x_t,相互作用势由ψ_ ST 表示,并且观察值 y_i 是具有等于σ*方的均值 x_i 和方差的高斯型。这里,w_st 是耦合强度,并且被假设为常数,并且等于 J>0,指示对于作为邻居的相同状态的偏好(即,当 x_s 和 x_t 都是+1 或-1 时,potential \Psi(x_s,x_t) = \exp{x_s J x_t}较高)。

变分推断背后的基本思想是选择接*原始分布 p(x)的*似分布 q(x ),其中距离通过 KL 散度来测量:

这将推理转化为优化问题,目标是最小化 KL 散度或最大化证据下限(ELBO)。我们可以导出 ELBO 如下:

在伊辛模型的应用中,我们有:

*均场变分推断中,我们假设一个全因子*似 q(x):

可以证明[2]q(x _ I;最小化 KL 发散的μI 由下式给出:

其中 E_{-q_i}表示除 j=i 之外的所有 q_j 的期望值,为了计算 q_i(x_i),我们只关心涉及 x_i 的项,也就是说,我们可以将它们分离如下:

其中 N(i)表示节点 I 的邻居,\mu_j 是二进制随机变量的*均值:

为了计算这个*均值,我们需要知道 q_j(x_j=+1)和 q_j(x_j=-1)的值。设 m_i = \sum_{j\in N(i)} w_ij mu_j 为邻居的*均值设 l_{i}^{+} = n(x _ I =+1;σ)和 l_{i}^{-} = n(x _ I =-1;sigma),那么我们可以如下计算*均值:

换句话说,我们在迭代 k 时参数\mu_i 的*均场变分更新计算如下:

我们增加了一个学习率参数λ。既然我们得到了我们的变分更新,我们可以用 python 实现二值图像去噪。

ELBO objective (left) and average entropy (right)

上图显示了实验结果。注意左边的 ELBO 图是单调增加的,在大约 10 次*均场迭代后变*。右图显示了*均熵的减少:

由于随机初始化,我们期望*均熵在开始时很高。然而,随着迭代次数的增加,*均场更新收敛于与观测值及其邻居一致的 x_i 的二进制值,导致*均熵减小。

密码

实现基于*均场变分推理的二值图像去噪的所有代码可以在下面的 ipython 笔记本中找到。

参考

[1] E. Sudderth,“CS242:概率图形模型”,【http://cs.brown.edu/courses/cs242/lectures/

[2] K. Murphy,“机器学习:概率视角”,麻省理工学院出版社,2012 年

电报信息主题的变化

原文:https://towardsdatascience.com/variations-of-topics-of-messages-on-telegram-16ca81f00169?source=collection_archive---------15-----------------------

Photo by Ketut Subiyanto: https://www.pexels.com/photo/serious-woman-using-smartphone-4353614/

介绍

你有没有想过你的网上足迹对你的行为有什么影响?我最*读了塞思·斯蒂芬斯的书,他在书中描述了基于搜索引擎和社交搜索查询等在线来源的数据对人类行为的见解。我发现这很有趣,因为有了互联网,数据科学家可以访问大量人的各种公共使用数据。随着我对的深入阅读,我开始把我生活中的每一件事想象成一张图表,把对话想象成我头脑中的原始数据,也许我可以利用它们。**

在我的脑海中,每个人都在撒谎,我很有兴趣看看在我自己使用的网站和应用程序中,我可以访问哪些类型的数据。因此,许多主要的社交网站和应用程序都有可以访问使用数据的 API。作为一名数据科学家,我发现一旦我学会了如何利用 API,这项技能就为各种探索打开了许多大门。通过使用 API,我获得了所有这些可能性,我受到启发,去做与 Stephens 在他的书中所做的类似的项目,但更多地与我自己的生活和兴趣相关。

大约在这个时候,在美国呆了一年后,我回到了哈萨克斯坦的家。即使我搬回了世界的另一端,我仍然想和我的一位名叫约书亚的美国密友保持联系。最后,我们每天通过即时通讯应用 Telegram 聊上几个小时。我们互相了解生活的最新情况,谈论政治、人际关系、旅行和许多其他事情。发了这么长时间短信,我突然意识到我们正在创建一个我个人非常熟悉的大数据集,我可能会出于兴趣对其进行分析。

该项目

第一步是访问 Telegram 的 API 。Telegram 的 API 允许访问我自己的使用数据。我还从一个朋友那里请求了聊天 id,以便访问双方的聊天数据。我用 Python 做了所有的工作,并用 Jupyter Notebook 作为这个项目的内核。在开始加载所有数据之前,我下载了所有需要的包。您可以在本文末尾的 GitHub 库中找到我的完整代码和一步一步的说明。

我的项目包括 4 个月的聊天数据。数据分两批下载。我总共处理了 17904 条信息。这些消息包括字符串、媒体内容、gif、贴纸和表情符号。

Final data saved in two batches

我首先删除了不是文本的信息,比如媒体和贴纸。这从数据集中筛选出了 2202 条信息,留下了我们之间发送的多达 15702 条短信。然后我用两个用户名来划分数据。我很惊讶我们每个人发的短信数量有这么大的差异。

Number of messages by usernames

然后,我努力排除停用词,如:语法冠词、连词和其他与我们谈话内容无关的语言的外围用法。

图表 1 —每天的消息数

第一个图表包括每天的邮件数量。令人惊讶的是,一天之内竟然有 350 条信息,大概是我醒着的时候每 3 分钟就有一条信息发出或收到。过去,当我们中的一个人在旅行或生病时,邮件数量为零。我还观察到,在我们开始打电话后的一月份,这一数字有所上升,这显然与我们更多地互相发短信的时间相吻合。一月中旬,当我回到美国,我们开始面对面交谈时,这个峰值再次下降。总的来说,图表的变化非常大,当我们处于相反的时区时,会观察到更高的计数。

Graph 1

图 2 —基于一天中时间的消息数量

下一张图显示了基于时间的*均消息交换数量。这张图没有图 1 变化大。图表上的时间是哈萨克时区(GMT+6),当时我正在为一家美国公司远程工作,我的日程安排发生了重大变化。很明显,在凌晨 3 点到 5 点和下午 3 点到 7 点之间会有一个消息高峰。此外,*均数字从来不会接*零,这意味着在这四个月中,我们没有一天不发信息。

Graph 2

图书馆上的文字

sci-kit-learn 的一个最大的优点是,该软件包使用户能够使用网格搜索策略来找到特征提取组件和分类器的良好配置。在我的例子中,我使用 scikit-learn 将我的库中的单词划分为使用阈值较高和较低的单词。它还确定了不适用于阈值、与我们的对话主题无关或没有重要意义的单词(即“真的”)。我运行了四次这个测试,每次代码都会生成一组不同的相关单词,我称之为“主题”在本文中,我选择显示第三组结果,在所有四个测试中,它的单词分组对我来说最有意义。

主题

以下十个主题由具有较高阈值的单个单词组成。我称之为“话题”的那几组单词,是在我们的对话中频繁使用的、彼此紧密相关的单词。

图 3——每日话题变化动态

此图显示了每周的邮件数量(Y 轴)、时间轴(X 轴),并按主题进行了颜色编码,每个主题都以不同的颜色显示。每个主题中的单词都在图例中明确标识。通过观察图表,人们可以看到我们的对话如何随着时间的推移在不同的高频词组之间移动,这显示了在这四个月中哪些话题与我们相关。

总结

这个简单的图表和数据分析让我对我和我朋友的信息历史有了更全面的了解,并成为我们之间有趣的讨论点。在一个充斥着小聊天框中的短信的生活中,很容易忘记所有关系的历史和发展,因为这些大量的数据隐藏在过去,并且在线性滚动界面中。通过做这个练习,我们可以带着更大的熟悉感和意识回顾我们的课文。

请随意查看我在 GitHub 库中的全部代码。

艾索玛/最长-聊天-分析-

最长——聊天——分析——这是我的第一个个人项目。我很好奇,分析了我和我朋友在…github.com的聊天记录

协同过滤的各种实现

原文:https://towardsdatascience.com/various-implementations-of-collaborative-filtering-100385c6dfe0?source=collection_archive---------0-----------------------

利用协同过滤构建推荐系统的不同方法比较

我们看到推荐系统在我们周围到处都在使用。这些系统正在个性化我们的网络体验,告诉我们买什么(亚马逊)【网飞】****【脸书】【Spotify】等等。这些推荐系统利用我们的购物/观看/收听模式,并根据我们的行为模式预测我们未来可能喜欢的东西。推荐系统最基本的模型是协同过滤模型,它基于这样一种假设,即人们喜欢与他们喜欢的其他事物相似的事物,以及被具有相似品味的其他人喜欢的事物。**

Figure 1: Example of collaborative filtering. Reference: here

**建立有针对性的推荐模型很容易,那么为什么不为自己的客户建立一个呢?我写这篇文章是为了让你更容易理解。**本帖大部分内容灵感来源于 fast.ai 深度学习 part 1 v2 课程。

这里是笔记本的链接,它实现了下面讨论的技术。

介绍

在这篇文章中,我讨论并比较了不同的协同过滤算法来预测电影的用户评分。为了进行比较,我使用了 MovieLens 数据,它有来自 671 个独立用户对 9066 部独立电影的 100004 个评分。读者可以将这篇文章视为一站式资源,了解如何在 python 上进行协同过滤,并在自己的数据集上测试不同的技术。 (我也根据我的分析提供了我自己关于使用哪种技术的建议)。

在进一步阅读之前,我希望您对协同过滤及其在推荐系统中的应用有基本的了解。如果没有,我强烈推荐你浏览下面的博客,这些博客是 USF 大学的一个学生写的:Shikhar Gupta

****博客:协同过滤和嵌入— 第一部分和第二部分

职位布局

  • **协同过滤技术的类型
    基于记忆的
    基于模型的
    矩阵分解
    聚类
    ***** 深度学习
  • Python 实现
    惊喜包
    fast . ai 库
  • 比较和结论

协同过滤技术的类型

关于协同过滤(CF)已经做了很多研究,最流行的方法是基于低维因子模型(基于模型的矩阵分解。这些我会详细讨论)。CF 技术大致分为两种类型:

Figure 2: Types of collaborative filtering approaches. Reference: Wikipedia

假设我们想向我们的产品用户推荐一件新商品(例如,向网飞的订户推荐一部电影,或者向亚马逊的在线买家推荐一件衣服)。为此,我们可以使用下面讨论的许多技术中的一种。

1。基于记忆的方法:

Agnes Johannsdottir 在她的博客中引用

基于记忆的协同过滤 方法可以分为两个主要部分: 用户-项目过滤和项目-项目过滤。一个 用户项目过滤 取一个特定的用户,基于评分的相似性找到与该用户相似的用户,并推荐那些相似用户喜欢的项目。相比之下, 物品-物品过滤 会取一个物品,找到喜欢过那个物品的用户,再找到那些用户或者类似用户也喜欢过的其他物品。它接受项目并输出其他项目作为推荐。

物品-物品协同过滤:“喜欢这个物品的用户也喜欢……”
用户-物品协同过滤:“和你相似的用户也喜欢……”

基于记忆的方法与基于模型的技术(等等,将在下一段讨论)的关键区别在于,我们没有使用梯度下降(或任何其他优化算法)来学习任何参数。最*的用户或项目仅通过使用余弦相似度或皮尔逊相关系数来计算,它们仅基于算术运算。
编辑:如上一段所述,不使用参数化机器学习方法的技术被归类为基于记忆的技术。因此,
像 KNN** 这样的非参数 ML 方法也应该属于基于记忆的方法。当我最初写这篇博客的时候,我用的是基于模型的方法,这是不对的。**

引用于这篇博客

一个常见的距离度量是 余弦相似度 。如果将评级矩阵中给定用户(项目)的行(列)视为一个向量,则可以从几何角度考虑该指标。对于基于用户的协同过滤,两个用户的相似性被度量为两个用户的向量 之间的角度的 余弦。对于用户 u 和 u’,余弦相似度为:

我们可以通过取来自所有其他用户(u)的电影 1 评级的加权和来预测用户 u 对电影 1 的评级,其中加权是每个用户和用户 u 之间的相似性数

我们还应该通过 u’(其他用户的)评级总数来标准化评级。

****关于基于记忆的方法的最后一句话:由于不涉及训练或优化,这是一种易于使用的方法。但是当我们有稀疏的数据时,它的性能会下降,这阻碍了这种方法对于大多数现实世界问题的可伸缩性。

如果您有兴趣尝试这种方法,下面是展示 python 一步一步实现这种方法的精彩文章的链接。
(我没有在这里讨论实现,因为我个人会使用可扩展的基于模型的方法)

****链接 1:用 Python 实现自己的推荐系统链接 2:推荐系统简介:协同过滤

2。基于模型的方法

在这种方法中,使用机器学习算法来开发 CF 模型,以预测用户对未评级项目的评级。根据我的理解,这种方法中的算法可以进一步细分为 3 个子类型。

Figure 3. Types of model based collaborative filtering approaches

编辑:名称基于上图的“基于聚类的算法有误。它没有生成集群。我们只是在 KNN 找到 k 个最接*的训练例子。“非参数方法”是更好的术语。****

上述算法的简要说明:

  • 矩阵分解(MF): 这种模型背后的思想是,用户的态度或偏好可以由少量的隐藏因素来决定。我们可以称这些因素为嵌入。****

矩阵分解可以转化为一个带有损失函数和约束的优化问题。 现在,约束是基于我们模型的属性来选择的。例如,对于非负矩阵分解,我们希望结果矩阵中有非负元素。

Figure 4. Visualization of matrix factorization

嵌入:
直观上,我们可以把嵌入理解为物品和用户的低维隐藏因素
。例如,假设我们有 5 维
(即上图
中的 D 或 n _ factors = 5)项目和用户的嵌入(随机选择# 5)。那么对于 user-X & movie-A,我们可以说这 5 个数字可能*代表关于电影的 5 个不同特征,比如【I】movie-A 有多科幻【ii)电影【iii】有多新同样,用户嵌入矩阵中的 5 个数字可能表示,(I)user-X 有多喜欢科幻电影(ii)user-X 有多喜欢最*的电影……等等。在上图中,user-X 和 movie-A 矩阵的点积数值越大,意味着 movie-A 是 user-X 的好推荐。***

(我并不是说这些数字实际上代表了这样的信息。我们实际上不知道这些因素意味着什么。这只是建立一种直觉)

在 USF 大学的另一位同学 Kerem Turgutlu 的这篇博文中,可以了解更多关于嵌入的知识。
链接:结构化深度学习

矩阵分解可以通过各种方法完成,并且有一些研究论文。在下一节中,将介绍正交分解(SVD)或概率分解(PMF)或非负分解(NMF)的 python 实现。

  • 非参数方法(KNN): 这个想法和基于记忆的推荐系统是一样的。在基于内存的算法中,我们使用用户和/或项目之间的相似性,并将它们用作权重来预测用户和项目的评分。不同之处在于,这种方法中的相似性是基于无监督学习模型计算的,而不是基于皮尔逊相关或余弦相似性。在这种方法中,我们还将相似用户的数量限制为 k ,这使得系统更具可扩展性。**
  • 神经网络/深度学习:有大量关于使用矩阵分解或相似矩阵的协同过滤的研究材料。但是缺乏在线材料来学习如何使用深度学习模型进行协同过滤。这是我在 fast.ai 深度学习 part 1 v2 中学到的东西。****

下面是解释当我们使用神经网络解决这个问题时会发生什么的可视化。

Figure 5. Matrix factorization and embeddings for neural net

我们可以把这看作是矩阵分解方法的扩展。对于 SVD 或 PCA,我们将原始稀疏矩阵分解成 2 个低秩正交矩阵的乘积。对于神经网络实现,我们不需要它们是正交的,我们希望我们的模型学习嵌入矩阵本身的值。对于特定的电影-用户组合,从嵌入矩阵中查找用户潜在特征电影潜在特征。这些是进一步线性和非线性图层的输入值。我们可以将此输入传递给多个 relu、线性或 sigmoid 层并通过任何优化算法(Adam、SGD 等)学习相应的权重。).**

___________________________________________________________________

Python 实现

Github 回购链接: 此处

让我们看看上面讨论的算法的 python 实现。我研究了 2 个不同的 python 包,它们提供了各种算法供选择。****

(一) 惊喜套餐 :

这个软件包是专门开发来使基于协同过滤的推荐变得容易的。它有各种 CF 算法的默认实现。

第一步: 下载 MovieLens 数据并在熊猫 dfhttp://files . group lens . org/datasets/movie lens/ml-latest-small . zip中读取

第二步: 安装惊喜包通过 pip install scikit-surprise. 加载数据到 *Dataset class*

Code chunk 1. Surprise dataloader

第三步: 现在在数据准备后实现任何 MF 算法都是运行 1 行代码那么简单。下面是奇异值分解(SVD)和非负矩阵分解(NMF)的代码和输出。该代码也可用于 KNN,只需更改以下代码中的 *algo = KNNBasic()* 。(请查看维基百科上SVDNMF)****

Code chunk 2. SVD and NMF using Surprise

验证奇异值分解和 NMF 的 RMSE 分数

Figure 6. RMSE scores of SVD and NMF using Surprise

最佳 RMSE = 0.8967 (SVD),对应的均方误差为 0.804

(b) fast.ai 库 :

fast.ai 是一个庞大的 python 库,它使具有基本编码技能的人可以轻松进行机器学习和深度学习。

浅薄的学问

下面是为 CF 实现概率矩阵分解的 5 行代码。该实现利用了这样一个事实,即 2 个分解的矩阵只是嵌入矩阵,可以通过在神经网络中添加嵌入层来建模(我们可以称之为浅层学习)。**

Code chunk 3. Collaborative filtering using fast.ai (based on concept of PMF)

培训结果:

Figure 7. Left: Training MSE, Right: Validation MSE. Rows: Epochs

从 PMF 的 fast.ai 实现获得的最佳验证 MSE 是 0.801,这接*于我们从 SVD 获得的结果。

深度学习

我们可以向我们的神经网络添加更多的线性和非线性层,使其成为深度神经网络模型。

使用 fast.ai 制作用于协同过滤的深度神经网络的步骤

第一步: 加载数据到 PyTorch 数据加载器。fast.ai 库建立在 PyTorch 之上。如果你想为特定格式的数据定制数据集类,在这里 学习

我用了 fast.ai 的ColumnarModelData.from_data_frame函数加载数据集。您还可以定义自己的数据加载器函数。 X 具有关于用户 Id、电影 Id 和时间戳的数据,而 Y 仅具有关于收视率(目标变量)的数据。****

Code chunk 4. Data-loader (fast.ai function)

步骤 2: 定义自定义神经网络类(语法特定于 PyTorch,但相同的逻辑也可用于 Keras)。

我们必须创建两个函数。init(),该类的构造函数为和 forward(),该函数向前传递。**

Code chunk 5. Neural net on PyTorch

关于的更多信息,这些层已经在正向通道中使用:**

  • dropout该层将删除具有给定概率参数的激活。激活有 p1,p2 概率变为 0。这样做是为了减少过度拟合。
  • embedding该层为对应于唯一用户和唯一电影的嵌入创建查找表。该层中的值通过反向传播来更新。
  • linear加偏的线性矩阵乘法。
  • relu使用非线性图层。
  • sigmoid用于限制来自训练数据的预测评级 b/w 最小值和最大值。

第三步: 模型拟合和预测。

Code chunk 6. Training deep neural net (fast.ai functions)

结果:

Figure 8. Left: Training MSE, Right: Validation MSE. Rows: Epochs

最佳验证 MSE = 0.7906。这是上面讨论的所有模型中最好的。

比较和结论

下面是从 MovieLens 100k 数据的不同方法获得的 MSE 图。

Figure 9. Comparison of MSE scores using different CF methods

神经网络(DL)和奇异值分解给出了最好的结果。与其他 MF 算法不同,神经网络实现也将在不经常使用的不*衡数据上表现良好。

为你的产品/服务建立客户目标推荐系统是很有用的。最简单和研究充分的方法是协同过滤。我写这篇文章的目的是,读者可以在一个地方找到所有有用的资料,以及实现,而不是浏览技术研究论文和花费几个小时来学习协同过滤。

参考资料和其他有用资源:

  1. 我的 GitHub 回购链接与 python 实现
  2. 推荐系统
  3. 协同过滤使用 Fast.ai
  4. 惊喜:用于推荐系统的 Python scikit
  5. 协同过滤和嵌入—第一部分和第二部分 【https://medium.com/@shik1470/63b00b9739ce】T21
    https://medium.com/@shik1470/919da17ecefb
  6. Python 中的协同过滤和矩阵分解教程
  7. 研究论文 http://www . science direct . com/science/article/pii/s 1877050915007462
    https://www.cs.toronto.edu/~amnih/papers/pmf.pdf

评估机器学习模型性能的各种方法

原文:https://towardsdatascience.com/various-ways-to-evaluate-a-machine-learning-models-performance-230449055f15?source=collection_archive---------1-----------------------

因为找准了还不够。

在这篇博客中,我们将讨论检查我们的机器学习或深度学习模型的性能的各种方法,以及为什么要使用其中一种来代替另一种。我们将讨论以下术语:

  1. 混淆矩阵
  2. 准确(性)
  3. 精确
  4. 回忆
  5. 特征
  6. F1 分数
  7. 精确回忆或 PR 曲线
  8. ROC ( R 接收者 O 操作者 C 特征)曲线
  9. PR 对 ROC 曲线。

为了简单起见,我们将主要讨论二进制分类问题,比如说我们必须找到一张图片是猫还是狗。或者患者患有癌症(阳性)或被发现健康(阴性)。需要明确的一些常见术语有:

真阳性(TP) :预测阳性和实际阳性。

假阳性(FP) :预测为阳性,实际为阴性。

真否定(TN) :预测否定,实际否定。

假阴性(FN) :预测阴性,实际阳性。

所以让我们开始吧!

混淆矩阵

它只是上述参数的一个矩阵形式的表示。更好的可视化总是好的:)

精度

判断一个模型最常用的指标,实际上并不是一个明确的性能指标。当阶级不*衡时,情况会变得更糟。

以癌症检测模型为例。实际上患癌症的几率非常低。假设 100 个病人中,90 个没有患癌症,剩下的 10 个实际上患了癌症。我们不想错过一个患有癌症但未被发现的患者(假阴性)。检测每个人是否患有癌症的准确率高达 90%。这个模型在这里什么也没做,只是给出了所有 100 个预测中没有癌症。

我们当然需要更好的选择。

精度

阳性实例占 总预测阳性 实例的百分比。这里的分母是从整个给定数据集得到的正的模型预测。把它当成是找出'模型说对了有多少是对的'。

召回/灵敏度/真阳性率

阳性实例占 总实际阳性 实例的百分比。因此,分母( TP + FN) 这里是数据集中存在的阳性实例的实际数量。把它当作找出'当显示正确的时候,模型错过了多少额外的正确的。

特异性

中的负实例占总实际负 实例的百分比。因此,分母( TN + FP) 这里是数据集中存在的否定实例的实际数量。它类似于回忆,但转移是在否定的情况下。比如找出有多少健康的患者没有患癌症,并被告知他们没有患癌症。这是一种衡量等级的方法。

F1 得分

它是精度和召回率的调和*均值。这需要两者的贡献,所以 F1 分数越高越好。请注意,由于分子中的乘积,如果一个值变低,最终的 F1 分数会显著下降。因此,如果正面预测实际上是正面的(精确度),并且没有错过正面而预测它们是负面的(回忆),那么模型在 F1 分数中表现良好。

一个缺点是,精确度和召回率同等重要,根据我们的应用,我们可能需要一个比另一个高,F1 分数可能不是它的精确度量。因此,加权 F1 分数或查看 PR 或 ROC 曲线会有所帮助。

PR 曲线

是各种阈值下的精度和召回率之间的曲线。在下图中,我们有 6 个预测值,显示了它们在不同阈值下各自的精度-召回曲线。图的右上部分是我们获得高精度和召回率的理想空间。基于我们的应用,我们可以选择预测值和阈值。PR AUC 就是曲线下的面积。其数值越高越好。

image link

ROC 曲线

ROC 代表接收机工作特性,该图是针对不同阈值的 TPR 和 FPR 绘制的。随着 TPR 增加,FPR 也增加。正如您在第一张图中看到的,我们有四个类别,我们希望阈值使我们更接*左上角。在给定的数据集上比较不同的预测值(这里是 3 个)也变得很容易,如图 2 所示,可以根据手边的应用选择阈值。ROC AUC 就是曲线下的面积,它的数值越高越好。

wiki link

PR 对 ROC 曲线

这两个指标被广泛用于判断一个模型的性能。

用 PR 还是 ROC 哪个?

答案在于真正的否定。

由于精确召回方程中没有 TN,它们在不*衡类中很有用。在阶级不*衡的情况下,当消极的阶级占多数时。该度量标准没有太多地考虑占多数的否定类别的大量真实否定,从而对不*衡提供了更好的抵抗力。当阳性类别的检测非常重要时,这是很重要的。

我喜欢检测癌症患者,这有很高的不*衡,因为在所有被诊断的患者中很少有人患有癌症。我们当然不希望漏掉一个未被发现的癌症患者(回忆),并确保被发现的人患有癌症(精确)。

由于考虑到 TN 或 ROC 方程中的负类,当这两类对我们都重要时,这是有用的。像猫狗的探测。真实否定的重要性确保了两个类都被赋予了重要性,就像 CNN 模型在确定图像是猫还是狗时的输出一样。

结论

要使用的评估标准在很大程度上取决于手头的任务。很长一段时间,准确性是我使用的唯一衡量标准,这确实是一个模糊的选项。我希望这篇博客对你有用。那都是我这边的。随时建议改正和改进。

机器学习中的矢量化实现

原文:https://towardsdatascience.com/vectorization-implementation-in-machine-learning-ca652920c55d?source=collection_archive---------3-----------------------

介绍

在机器学习领域,高级玩家需要编写自己的成本函数或优化算法来实现更定制的模型,而不仅仅是使用现有的机器学习库。为了充分利用当今计算机的计算能力,算法实现的现有技术是对所有计算进行矢量化。这允许您实现并行计算,例如充分利用 GPU 的处理器。本文介绍了机器学习矢量化的实现。本帖使用的所有代码都可以在我的 github 中找到。

先决条件:Numpy 数组

我们将在 numpy array 的矢量化过程中使用的最重要的工具。注意,我们不使用 numpy 矩阵,因为 numpy 矩阵是严格的二维矩阵。实际上,numpy 矩阵是 numpy 数组的子集。因此,为了方便起见,我们总是使用 numpy 数组。这里回顾一下 numpy 数组算法,以便更好地理解后面的内容。下面是如何定义 numpy 数组:

# import numpy
import numpy as np# define two numpy arrays
a = np.array([[1,2],[3,4]])
b = np.array([[1,1],[1,1]])print(a)
>>> array([[1, 2],
           [3, 4]])
print(b)
>>> array([[1, 1],
           [1, 1]])

Numpy 数组加法

# addition
print(a + b)>>> array([[2, 3],
           [4, 5]])

Numpy 数组减法

# substraction
print(a - b)>>> array([[0, 1],
           [2, 3]])

Numpy 数组乘法

注意,如果直接使用' * '乘法,这不同于称为点积矩阵乘法。两个数组之间的' * '操作只是将相同位置的元素相乘。

# multiplication: 
print(a * b)>>> array([[1, 2],
          [3, 4]])

Numpy 数组点积

我们使用 numpy 的点函数来实现矩阵乘法。一个如此方便的方法是通过使用“@”符号,它以完全相同的方式工作。

# matrix multiplication
print(np.dot(a,b))>>> array([[1, 2],
          [3, 4]])# matrix product alternative
print(a@b)>>> array([[3, 3],
          [7, 7]])

Numpy 数组维数

这里我们展示了两个例子,展示了 dimension 如何在 numpy 数组中工作。请注意,在第一种情况下,它是一个一行三列的数组,而在第二种情况下,它是一个三行一列的数组。

# numpy array with one row
a =  np.array([1,2,3])
print(a.shape)>>> (3,)# numpy array with three rows
b = np.array([[1],[2],[3]])
print(b.shape)>>> (3, 1)

Numpy 数组索引和切片

对于 2D numpy 数组,当我们在表示为 A 的数组中切片一个元素时,我们可以使用 A[i,j],其中 I 是行索引,j 是列索引。如果想选择一整行 I,使用 A[i,:],类似地对于选择一整列 j 使用 A[:,j]。

# Define an 3x3 2d array
a = np.array([[1,2,3],[4,5,6],[7,8,9]])
print(a)>>> array([[1, 2, 3],
          [4, 5, 6],
          [7, 8, 9]])# select first element in the array
print(a[0,0])>>> 1# select first row of the array
print(a[0,:])>>> array([1, 2, 3])# select second coulumn of the array
print(a[:,1])>>> array([2, 5, 8])

先决条件:线性回归成本函数

在这一节中,我们将回顾线性回归的一些概念及其数学表达式。由于我们需要使用这些公式来实现梯度下降算法,在下一节,看看如何实现矢量化。

线性回归的假设定义为:

线性回归的成本函数定义为:

成本函数对每个θ的导数定义为:

在梯度下降的每次迭代中,我们使用以下等式更新所有θ:

资料组

我们使用的数据集是来自 UCI 机器学习资源库的“波士顿住宅”。它使用了房屋面积大小、建造年份等特征。来预测波士顿地区的房价。数据如下所示:

我们的数据集有 506 个条目,我们将其表示为条目数 m。特征数 n=14,包括我们初始化为全 1 的截取特征。见下文:

# Insert X0 Column
Xd = df.drop(columns=['MEDV'])
Xd.insert(0, 'X0', 1)
Xd.head()

# numpy array format
X = Xd.values
y = df.MEDV.values# sample size
m = len(df.index)
print(m)>>> 506# number of features
n = X.shape[1]
print(n)>>> 14

对于循环垂直向量化

在本节中,我们通过对线性回归应用梯度下降算法,对 for 循环和矢量化方法进行逐步比较。我们在线性回归部分比较了每个公式实现的运行时间。

我们将所有 thetas 初始化为 1:

# Initialize theta
theta = np.ones(n)print(theta)
>>> array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])

假设实现:For 循环

为了实现线性回归的假设功能,如果我们使用 for 循环,可以使用下面的代码来实现:

# hypothesis for the first sample
hypo = 0
for j in range(n):
    hypo += theta[j]*X[0,j]

为了获得每个样本的假设,我们需要一个列表来存储它,并需要另一个 for 循环来迭代所有样本:

%%time
# hypothesis for all the samples
all_hypo = []
for i in range(m):
    hypo_i = 0
    for j in range(n):
        hypo_i += theta[j]*X[i,j]
    all_hypo.append(hypo_i)>>> Wall time: 4 ms

我们可以看到运行时间是 4 ms,这并不太疯狂,因为这个实现足够简单,数据集也很小。

结果显示为:

假设实现:矢量化

每个样本的假设可以使用以下公式进行矢量化:

为了实现将所有样本作为一个列表的假设,我们使用下面的数组点积:

代码实现非常简单明了:

%%time
# matrix format
hypo = X@theta>>> Wall time: 0 ns

我们可以发现,它只需要很少的时间来计算,甚至可以不显示。计算结果如下所示。与 for 循环结果相比,我们可以看到我们获得了完全相同的结果。

成本函数实施:For 循环

基于我们从假设中获得的结果,我们需要另一个循环来迭代所有样本以计算成本函数。

%%time
# cost function
cost = 0
for i in range(m):
    hypo_i = 0
    for j in range(n):
        hypo_i += theta[j]*X[i,j]
    cost_i = (hypo_i - y[i])**2
    cost += cost_i
cost = (1/(2*m))*cost>>> Wall time: 4 ms

运行时间为 4 ms,结果显示如下:

print(cost)>>> 1.399752908228425

成本函数实现:矢量化

基于假设的矢量化,我们可以很容易地将成本函数矢量化为:

代码实现仍然非常简洁:

%%time
# cost function
cost = (1/(2*m))*np.transpose((X@theta - y))@(X@theta - y)>>> Wall time: 0 ns

同样,这种矢量化计算是即时的。计算结果与 for 循环结果相同:

print(cost)>>> 1.3997529082284244

派生实现:For 循环

计算成本函数对指定θ的导数,编码如下:

dev_sum = 0
for i in range(m):
    hypo_i = 0
    for j in range(n):
        hypo_i += theta[j]*X[i,j]
    dev_i = (hypo_i - y[i])*X[i,k]
    dev_sum += dev_i
dev_sum = (1/m)*dev_sum

为了计算所有θ的导数并输出一个列表,我们需要另一个 for 循环迭代所有列:

%%time
# derivation
dev_list = []
for k in range(n):
    dev_sum = 0
    for i in range(m):
        hypo_i = 0
        for j in range(n):
            hypo_i += theta[j]*X[i,j]
        dev_i = (hypo_i - y[i])*X[i,k]
        dev_sum += dev_i
    dev_sum = (1/m)*dev_sum

    dev_list.append(dev_sum)>>> Wall time: 47 ms

运行时间为 47 ms,随着循环的增多,for 循环和矢量化的时间成本差异开始变得显著。

for 循环的推导结果是:

print(dev_list)>>> [0.9999999999999983,
 0.07814620360307895,
 -0.11042922261438312,
 0.2620302340552936,
 0.05504439083525137,
 0.23892542562534522,
 -0.06454255823702795,
 0.2611634394125097,
 -0.1453677181065729,
 0.43106386997897883,
 0.38303455280215737,
 0.16591512402899725,
 -0.09920797306076046,
 0.1835280968258358]

派生实现:矢量化

关于每个θ的成本函数的推导可以矢量化为:

成本函数对所有θ的推导可矢量化为:

代码实现仍然非常简洁:

%%time
dev = (1/m)*np.transpose(X)@(X@theta - y)>>> Wall time: 999 µs

直接比较是 999μs vs . s . 47 ms,以下是矢量化计算结果:

print(dev)array([ 1\.        ,  0.0781462 , -0.11042922,  0.26203023,  0.05504439, 0.23892543, -0.06454256,  0.26116344, -0.14536772,  0.43106387, 0.38303455,  0.16591512, -0.09920797,  0.1835281 ])

两种方法的结果也是一样的。

将一切放在一起:优化

在本节中,我们使用我们之前开发的所有实现,并编写一个梯度下降迭代来比较这两种方法。

梯度下降:用于循环

为了获得下降优化结果,我们将迭代次数设置为 10 万次。为了实现梯度下降算法,我们需要嵌套四个 for 循环。学习率被设置为 0.0005,θ被初始化为全 1。代码如下所示:

%%time
a = 0.0005
theta = np.ones(n)cost_list = []for itr in range(100000):

    dev_list = []
    for k in range(n):
        dev_sum = 0
        for i in range(m):
            hypo_i = 0
            for j in range(n):
                hypo_i += theta[j]*X[i,j]
            dev_i = (hypo_i - y[i])*X[i,k]
            dev_sum += dev_i
        dev_sum = (1/m)*dev_sumdev_list.append(dev_sum)

    theta = theta - a*np.array(dev_list)

    cost_val = cost_loop(theta)

    cost_list.append(cost_val)>>> Wall time: 1h 15min 58s

总运行时间为 1 小时 15 分钟。以下是我们获得的最小成本。我们还提供了一个曲线图,显示了成本函数相对于迭代的变化。

print(cost_val)>>> 0.017663350184258856

梯度下降:矢量化

矢量化梯度下降的实现非常干净优雅。

%%time
a = 0.0005
theta = np.ones(n)cost_list = []for i in range(100000):

    theta = theta - a*(1/m)*np.transpose(X)@(X@theta - y)

    cost_val = cost(theta)
    cost_list.append(cost_val)>>> Wall time: 1.75 s

矢量化方法具有如下最小成本函数值。同样,提供了关于迭代的成本变化:

print(cost_val)>>> 0.017663350184258835

我们可以看到两种方法的最小成本值几乎完全相同。但是使用矢量化的算法实现时间为 1.75 秒,而使用 for 循环的算法实现时间为 1 小时 15 分钟。

结论

这里有一个图,显示了实现相同算法并使用完全相同的学习速率和初始θ值的两种方法的运行时间差异。这两种方法达到了同样的精度。然而,矢量化方法花费了 1.75 秒,而 for 循环花费了 4558 秒。矢量化方法比 for 循环方法快 2600 倍。

矢量化方法的时间复杂度为 O(s),其中 s 为迭代次数。相比之下,for 循环方法的时间复杂度为 O(snm*n),其中 s 是迭代次数,m 是数据集样本数,n 是数据集特征数。在这种情况下,我们的数据集足够小,m=506,n=14,但是我们观察到时间复杂度的巨大差异。为大数据成像,这种差异会有多大。由于 noway 的计算机和 GPU 是由成千上万个“核心”组成的,我们甚至可以有多个 GPU 或使用一个计算机集群,我们需要充分利用这些计算能力。方法是通过并行计算实现你的算法。因此,在我们的机器学习算法中使用矢量化是提升算法并节省大量训练时间的关键。矢量化是我们需要考虑的一个很好的方法,值得花时间去研究。

栅格向多边形的矢量化

原文:https://towardsdatascience.com/vectorization-of-raster-to-polygons-dc56acc3aa5f?source=collection_archive---------10-----------------------

如果有免费的库,我绝不会开始写任何矢量化代码。

然而,最*我作为技术负责人参与了一个与几何和光栅矢量化相关的有趣项目。我需要计算各种形状的复杂投影。我从一个“干净”的数学解决方案开始,很快以大量与多边形三角剖分相关的计算结束——O(log n!).我花了一周的时间才发现自己真的遇到了麻烦——在真实的场景中,这个过程只持续了几分钟。然后,我决定将我们的目光转向离散化(正如在开始时声明的那样),我做了这项工作,并得到了矩阵形式的结果。那天是星期五,结果需要在下周一公布。但是以向量的形式。

我在 R 包中搜索光栅矢量化,发现T5包,因为函数 rasterToPolygons 看起来不错,我们认为它可能为多边形产生了太多的点。因为没有必要的 R 包,所以我需要创建自己的。嗯,仍然有半个周末,我们做了一些 C++编码,并创建了这个函数,它一步就完成了工作。

这是带有飞地和不允许飞地的选项的初始位图,结果如下:

来自火山数据集的示例:

library(fasteraster); 
library(datasets); 
inp = volcano; res = raster2vector(volcano, 120, 200, 20); image(inp, col = rev(grey.colors(100)), useRaster = TRUE)
plot(0, type = "l", xlim = c(0, nrow(inp)), ylim = c(0, ncol(inp))) a = lapply(res, function(x) lines(rbind(x, x[1,])))

生产:

你可以在这里找到源码包:faster raster _ 1 . 0 . 4 . tar和 Linux 64 二进制:faster raster _ 1 . 0 . 4 _ R _ x86 _ 64-PC-Linux-GNU . tar新鲜版本权自克兰:https://cran.r-project.org/package=fasteraster

附言(同 postscript);警官(police sergeant)

对于个人问题,请在 Linkedin 或脸书联系我,有时我会在那里发布一些关于人工智能的简短新闻和想法。如果你在人工智能方面有需求,或者你需要建立一个数据科学咨询团队,请联系我

反向传播的矢量化实现

原文:https://towardsdatascience.com/vectorized-implementation-of-back-propagation-c4ce1d3eb684?source=collection_archive---------8-----------------------

在之前的帖子中,我们解释了反向传播背后的基本原理以及神经网络是如何工作的。在本帖中,我们将解释如何利用优化的数学库来加速学习过程。

“向量化”(简化)是重写一个循环的过程,这样它不是处理数组的单个元素 N 次,而是同时处理数组的几个或所有的元素

让我们从一个数据集的例子开始,这个数据集在一个特定的城市出售了 1000 套房子。对于每栋房子,我们有 5 个信息:它的面积,房间数量,建造年份,支付的价格和代理费。目标是训练一个模型,根据前 3 个特征预测价格和代理费。

Dataset example

让我们考虑一个简单的线性前馈模型,具有 6 个权重(W11,W12,W13,W21,W22,W23),其中:

  • 价格= W11。面积+ W12。NbRooms + W13。年
  • 费用= W21。面积+ W22。NbRooms + W23。年

正如前面更详细解释的那样,机器学习的目标是找到这 6 个权重的哪个值最符合最接*数据集真实输出的模型输出。我们从随机初始化权重开始。然后,我们向前传播以计算预测价格和代理费。通过将结果与来自数据集的真实价格和费用进行比较,我们可以获得误差的梯度,以便稍后反向传播,并相应地更新权重。

一个简单的实现如下所示:

https://gist . github . com/Assad/EC 33987 c 6273293 af 2f 648572 fa 85 a3d

然而,数据集上的这种顺序 for 循环太慢,并且没有利用 CPU 和 GPU 中的现代并行性。

为了获得高性能,我们需要将数据集转换成矩阵表示。如果我们采用基于列的表示,来自数据集的每个输入都被复制到矩阵中的一列。

  • 我们的权重矩阵将是一个 2 行 x 3 列的矩阵。
  • 我们的输入矩阵将是一个 3 行 x 1000 列的矩阵。
  • 我们的输出矩阵将是一个 2 行 x 1000 列的矩阵。

我们正在寻求解决的线性模型可以用以下基于矩阵的形式表示:

Matrix or a vectorized-form of: Weights x Inputs = Outputs

这种表示起作用的原因是因为这正是矩阵乘法的运行方式:

Matrix multiplication

Matrix-multiplication: a row i of the first matrix is multiplied by a column j of the second matrix to calculate the value of the cell (i , j) of the output

有了矢量化实现,以前需要 1000 次迭代的 for 循环现在只需很少的高性能矢量化运算即可完成,如下所示:

Predictions = Matrix.Multiply(Weights, Inputs)
Error = Matrix.Substract(Predictions, Outputs)

在大数据集上,使用 GPU(有些有 1000 个内核),我们可以期待在数千倍的加速!在 CPU 上,有很多实现高性能矩阵运算的高级数学库,比如 openBLAS 。

向量化前向传播简单明了,它遵循模型定义。挑战在于误差反向传播的矢量化。

  • 有了数字,如果我们通过一个函数 f 传递一个数字 x 得到y = f(x)****f的导数f’给我们 y 的变化率,当 x 变化
  • 对于矩阵,我们需要使用 雅可比矩阵 ,这是一个由关于输入矩阵的不同元素的偏导数组成的矩阵。

背后的理由是固定输入矩阵中的所有元素,除了一个元素,其中我们向其添加一个小增量 𝛿 ,并查看输出矩阵中的哪些元素受到影响,影响到哪个比率,并将它们相加在一起。我们对输入矩阵的所有元素都这样做,我们在输入端得到它的梯度矩阵。因此它具有相同的形状(行数和列数)。

考虑下面的矩阵运算。RxP=S,(以及计算输出 S 的前 3 个元素的前 3 个等式)

等式 1: s11 = r11.p11 + r12.p21 + r13.p31(红色输出)

等式 2: s12 = r11.p12 + r12.p22 + r13.p32(绿色输出)

等式 3: s21 = r21.p11 + r22.p21 + r23.p31(黄色输出)

假设我们在输出 S 处已经有了梯度矩阵δS,我们想将其反向传播到输入 R (分别为 P )以计算δR(分别为。δP)。由于 r11 只参与 s11s12 的计算(红绿不黄),我们可以预计只有 𝛿s11𝛿s12 反向传播到 𝛿r11

  • 为了找到 𝛿s11 的反向传播的速率,我们相对于 r11 对等式 1 进行部分求导(并认为其他一切为常数),我们得到 p11 的速率(另一种解释方式:在 r11 中的小变化,将被 s11 中的 p11 因子放大)。
  • 通过对 𝛿s12 和等式 2 做同样的事情,我们得到 p12 的速率。
  • 如果我们试图将 𝛿s13 反向传播到 r11 ,并且相对于 r11 推导等式 3,我们得到 0,因为等式 3 根本不依赖于 r11。另一种理解方式:如果我们有一个错误或 s21,在 r11 上无法做任何事情来减少这个错误。由于 r11 不参与 s21 的计算!这同样适用于 S 矩阵的所有其他元素(s21、s22、s31、s32)。
  • 最后,加起来,我们得到 𝛿r11=𝛿s11.p11 + 𝛿s12.p12

通过对矩阵 R 的所有元素做同样的处理,我们得到如下结果:

  • 𝛿r11=𝛿s11.p11 + 𝛿s12.p12
  • 𝛿r12=𝛿s11.p21 + 𝛿s12.p22
  • 𝛿r13=𝛿s11.p31 + 𝛿s12.p32
  • 𝛿r21=𝛿s21.p11 + 𝛿s22.p12
  • 𝛿r22=𝛿s21.p21 + 𝛿s22.p22
  • 𝛿r23=𝛿s21.p31 + 𝛿s22.p32
  • 𝛿r31=𝛿s31.p11 + 𝛿s32.p12
  • 𝛿r32=𝛿s31.p21 + 𝛿s32.p22
  • 𝛿r33=𝛿s31.p31 + 𝛿s32.p32

如果我们仔细观察该模式,我们会发现我们可以将其转化为矢量化矩阵乘法,如下所示:

**ΔR = ΔS x Transpose(P)**

类似地,如果我们按照相同的过程反向传播到 P,我们得到下面的等式:

**ΔP = Transpose(R) x ΔS**

每个神经网络层由几个数学运算组成。如果我们设法在向前和向后传递中用矩阵运算来定义每个数学运算,我们在学习中得到最大加速。

在第一步中,每个矩阵 M 必须被一个伴随矩阵δM增加,以在返回的路上保持其梯度。

第二步,每个矩阵运算都必须定义自己的向前和向后运算。例如:

在创建了这个数学运算的矢量化库之后,我们可以使用这个库来链接运算,并创建层、激活函数、损失函数、优化器。反向传播将被自动定义为每层中使用的数学函数的回调栈(或计算图)。这就是 Tensorflow 在一定程度上的工作原理。

我们可以将完整的机器学习过程视为一堆抽象的:

An abstraction of machine learning library stack

原载于 2018 年 6 月 1 日【medium.com】

矢量让你看到 3D 眼镜看不到的东西?

原文:https://towardsdatascience.com/vectors-let-you-see-what-3d-glasses-cant-e1385d9ef879?source=collection_archive---------5-----------------------

警告:我假设你知道矢量是什么。如果没有,请在评论区告诉我,我会尽力另发一篇帖子。原因是,你要么知道向量,要么不知道。句号。因此,至少 500 字的解释是必须的,根据我的资格是一个单独的职位。

在之前一篇关于降维的文章中,我谈到了降维将如何帮助我们快速得出一些结论。我也提到过,我们将在后面的文章中讨论数学,现在我们来谈谈向量!是的,向量在降维方面很有用:)。事实证明,线性代数在研究像 PCA、SVD 等机器学习技术时非常有用。如果您对这些术语不熟悉,可以将线性代数视为删除不需要的数据、压缩图像、检测图像边缘等的有用工具。我打算很快就这些话题进行写作,并承诺让它们变得更简单。

如果你没有看过我之前的帖子,你可以查看这里的。虽然这不是理解这篇文章的先决条件,但在着色之前,你会先画一个草图。有些人喜欢直接着色!;)

让我们先熟悉一些术语,如跨度、线性组合等。

你可以在下面看到一个向量的跨度。在我们的例子中,两个向量(v⃗和 w⃗)的“跨度”只不过是 v⃗和 w⃗的线性组合的表示,也就是说,你将 v⃗和 w⃗组合起来,得到一个合成向量 x⃗.

I know that’s confusing!

因此,简单地说,跨越就是将按比例缩放的向量相加,产生一个覆盖高维空间的合成向量。看下面的 gif 图片来理解我的意思。

缩放矢量??只是乘以标量,结果向量要么压缩要么拉伸!

因此,矢量 v⃗在大小为“a”的方向上移动,而另一个矢量 w⃗在与 v⃗正交的另一个方向上作用,大小为“b”。所以,通过改变大小,你可以看到这两个向量可以覆盖几乎所有的空间!这也叫向量空间。这些标量在特定的方向上拉伸或挤压矢量。

看下面的 gif 图片,看看整个矢量空间被缩放矢量覆盖的结果。请记住,这里我们有两个维度。想象一架飞机在 3D 情况下被覆盖。我不知道你如何形象化(几何)4D 等等;).然而,事实证明这些向量可以帮助我们处理几何学限制的更高维度。我们将在后面的文章中看到这是如何发生的。

这就是多个向量的线性组合是如何容易地被想出来的。

一个例子应该让我们清楚地记住这一点。我们试图说,上面的‘a’和‘b’的任何组合都会把我们带到向量 av⃗ + bw⃗.

比方说,

使用 v⃗和 w⃗的线性组合的最终向量是 x⃗,其中

向量的值会是什么样子,

上述等式意味着,

这是一个两个未知数的线性系统,我们有两个方程,因此我们可以得到一个解,即我们可以找到 a 和 b。花一些时间来计算这些值(提示:这很容易!).

上述方程的解是,

现在,让我们说,你想找到得到矢量 x⃗=[0 ^ 6]的线性组合是什么?

答案很简单,方程式是,

因此,代入上述值后,最终方程将为:

现在,这可能看起来没有什么魔力,因为我故意举了一个简单的例子,你可以试着做一些难的,你仍然可以得到答案!

我们可以把这个想法扩展到任何维度,我把它作为家庭作业留给你们。但是,让我给你一点提示,看看这个等式在 3D 的情况下会是什么样子。

让我们来看一个向量的 3D 演示。为了直观地理解,红色向量在 x、y、z 方向上分别移动了 5 个单位、8 个单位、3 个单位。

a=5, b=8, c=3 in the x, y, z axis respectively.

我希望这能让事情变得简单,并帮助你思考更高的维度!

这就是这篇文章的内容。尽管对这些方程大谈特谈,我还是要证明这些向量在机器学习中的用处。我们将在随后的帖子中涉及更多关于向量的主题,并最终将所有的点连接起来,以显示线性代数对于机器学习是多么有用!

下次见,机器学习快乐!😃

车辆检测和距离估计

原文:https://towardsdatascience.com/vehicle-detection-and-distance-estimation-7acde48256e1?source=collection_archive---------0-----------------------

Udacity SDCND

开车时,要做两件非常重要的事情:a)保持在你的车道上 b)避开其他车辆。为此,我们需要知道车道在哪里,其他车在哪里。自动驾驶汽车也是如此,因此 Udacity 的家伙们决定,自动驾驶汽车 Nannodegree 的最后两个项目。在我以前的帖子中,我已经谈到了如何找到车道线,并使其对光线变化和噪声具有鲁棒性。这篇文章解决了在图像上找到车辆并估计它离我们的车的距离的问题。

该项目的目标/步骤如下:

  • 提取用于分类的特征
  • 构建和训练分类器
  • 滑动车窗,在图像上识别汽车
  • 过滤掉假阳性
  • 计算距离
  • 在视频上运行管道

这里用到了《高级寻巷》中的一些部分,所以如果你对更深入的描述感兴趣,你可以在这里阅读我之前的帖子。

所有的代码和训练数据都可以在 这个 Github 库 中找到

汽车分类器

我们需要做的第一件事是创建一个分类器来区分汽车和非汽车。为此需要数据集,我已经使用了 Udacity 提供的数据集。(下载:车辆、非车辆)。该数据集是 KITTI vision 基准套件和 GTI 车辆图像数据库的组合。GTI 汽车图像分为远、左、右、中*。汽车和非汽车的例子如下:

Car images from left to right: 1)KITTI, 2)GTI Far 3)GTI Near 4)GTI Left 5)GTI Right

Non-car images

要建立一个分类器,首先必须识别特征。将要使用的特征是直方图、全图像和 HOG-s 的混合。

提取特征

彩色空间

在颜色编码的意义上,颜色空间与图像的表示有关。有些编码更适合一种用途,但不适合其他用途。例如,从硬件的角度来看,RBG 很好,因为它是如何捕捉和显示像素的( Bayer filter 就是一个很好的例子),但它没有捕捉人类感知颜色的方式,而这对于分类任务很重要。对于汽车分类的任务,我确信没有一个规定的颜色空间是最好的。所以只能通过试错来选择。我所做的是,我已经建立了分类器,基于 HOG、颜色直方图和完整图像,然后改变颜色空间,直到我在测试集上获得最佳分类结果。也许我是从上到下描述问题,但是颜色空间对于解释和可视化特征是非常重要的。经过一番试用,我发现 LUV 色彩空间效果最好。它具有发光分量 L,以及两个( uv )色度分量。该颜色空间始终给出更好的分类结果。

作为特征的子采样和归一化图像

第一个也是最简单的特征是二次抽样图像。再次,通过尝试和检查分类结果,二次抽样图像的大小被选择为 20×20。此外,图像是伽玛标准化。这是在观看 YouTube解释猪的视频时产生的想法。据说,对图像求*方根可以使其标准化,并获得均匀的亮度,从而减少阴影的影响。我试了一下,它在分类上有了微小的改进。因为这是一个非常简单的操作,所以它保留在我的代码中,因为它提供了额外的健壮性。在归一化和二次采样之后,图像被整形为矢量而不是矩阵。原始图像归一化转换成 LUV 的有:**

**

Car images from left to right: 1) Original 2) Normalized 3) LUV color space**

颜色直方图

第二组特征是颜色直方图。最初,我试图只使用发光通道 L 的直方图。汽车可以有不同的颜色,所以省略色度通道对我来说是一个自然的选择。经过一些测试后,我发现包括所有三个颜色通道的直方图提高了几个百分点的测试精度,这可以产生很大的差异。基于测试精度选择直方图中的仓数量,128 个仓产生最佳结果。以下是之前显示的图像的直方图示例:

Histograms of all three channels

最后,但可能是最重要的特征是梯度方向直方图——HOG。围绕 HOG 的主要思想是基于使用一些边缘检测器计算的每个像素的方向来计算直方图。边缘上的像素比边缘上的像素对直方图的贡献大得多。图像被分成多个单元,并且对于每个单元,方向被分箱。所以猪基本上显示了每个细胞的主导方向。你可以在这个 YouTube 视频中找到关于这头猪的详细信息。计算凸起的图像大小为 64x64。每个单元的像素数量是 8,而每个块的单元数量是 1。方向的数量是 12。HOG 是在归一化图像的所有三个通道上计算的。我对这些参数进行了大量测试,最终发现这是最佳选择。我在选择时考虑的是以这种方式生成的特征的数量以及在测试集上获得的准确性。当使用这组参数时,每个通道总共创建了 768 个特征。如果每个块的单元数增加到 2,则每个通道的特征数会增加到 2352。当每块使用 2 个单元时,分类精度的提高并不显著,所以我选择每块使用 1 个单元。此外,我还尝试了增加每个单元的像素数,在这种情况下,大量信息会丢失,精度会下降,而降低每个单元的像素数会增加特征的数量。每个通道的图像可视化 HOG 为:

HOG of a car

HOG of a non-car

训练分类器

使用的分类器是线性支持向量分类器。数据集是通过遍历车辆和非车辆的图像并计算这些图像的特征而获得的。接下来要做的是缩放特征,这对任何机器学习算法都非常重要。之后,数据集被分成训练集和测试集,其中测试集占所有数据的 10%。使用 C=1e-4 训练分类器,其中该特征是基于训练和测试集的精度选择的。如果两个精度之间的差异很大,则训练过拟合数据,因此降低了 C 。当测试精度较低但与训练精度相同时,出现了欠拟合,因此增加了 C 的值。在测试集上获得的最终准确度为 99.55% 。训练完成后,分类器和定标器被酸洗并保存,以便在处理来自摄像机的图像时可以重复使用。

在图像/视频上寻找汽车

在图像和视频中寻找汽车的管道非常相似。事实上,在视频中寻找汽车遵循的是在静态图像中寻找汽车的相同流程,只是增加了一些功能。为此,将首先描述单个图像的流水线。

滑动窗户

首先要做的是在屏幕上滑动窗口,并尝试识别在定义的分类器上产生正面命中的区域。将要滑动的窗口总是大小为 64x64,重叠 75%。在某些情况下,汽车可能大于 64x64 像素,因此为了涵盖这些情况,整个图像被缩小。结果,在原始图像和 5 个缩小的图像上搜索汽车,选择这些图像使得原始图像上的汽车的尺寸为 80×80、96×96、112×112、128×128 和 160×160。对于每个缩小的图像,只计算一次 HOG,如果有汽车,则在测试每个窗户时使用 HOG 的子区域。滑动窗口后,为每个窗口计算的整批特征被分类。这是一个原始图像的例子,2 个搜索汽车的区域和检测到汽车的区域:

****

Search region for cars of dimension from left: 1) 64x64, 2) 160x160 pixels. The dimension of the car is calculated with respect to original image

****

Images from left: 1) Original image 2)image with detected cars

计算热图和识别汽车

由于对同一辆汽车有多次检测,所以必须以某种方式对车窗进行分组。在这种情况下,将使用热图。热图中的每个像素包含包含该像素的已识别汽车的窗口数量。热图中像素的值越高,它越有可能是汽车的一部分。热图的阈值为 1,这消除了任何可能的错误汽车检测。之后,连接的组件被标记,边界框被计算。生成的图像是:

Images from left 1)Heatmap 2)Thresholded 3) Heatmap Labels

道路拆除

这样做的原因是,我们想估计我们前面多远是确定的汽车。在我们之前的项目中,我们发现了透视变换,它将路面映射到图像上,使我们能够测量距离。透视变换假设被变换的物体是*面的,所以为了精确地测量距离,我们需要一个在路面上的点。使用边界框下边缘的中点来测量距离。移除路面,以便对被识别汽车的后轮进行测量。为此,找到边界框的最后 8 行的中间颜色。超过 20%的点远离中间颜色的从底部开始的第一条线被认为是边界框的新的底部边缘。在下图中,颜色为“远”的点用紫色表示。

**

Images from left 1)Original 2)Points near in color 3)Cropped**

估计距离

在检测到的车辆周围的矩形被绘制之前,车道线被识别。另外,我们会试着估计离车的距离。一旦我们获得了边界框及其底边的中点,使用透视变换,我们就可以从高级车道寻找项目中计算出它在扭曲图像上的位置。我们不需要扭曲整个图像,而只需要重新计算扭曲图像上的单个位置。在该图像上,像素位置和以米为单位的距离之间存在直接的相关性,因此计算出的中点位置和图像底部之间的距离乘以每个像素的米数就代表了我们的汽车和我们检测到的汽车之间的距离。通过观察帧与帧之间的距离变化,我们可以计算汽车的相对速度,将两帧之间的差异乘以每秒帧数和 3.6,将其转换为每小时公里数,而不是每秒米数。检测到汽车的图像和测量距离的扭曲图像是:

****

Images from the left 1) Detected cars 2) Warped image

关于透视变换的更多信息,请阅读 我之前的帖子

最后一步就是在一张图片上画出所有的东西。最终结果如下所示:

Final result

在视频中寻找汽车

对于视频,管道遵循应用于单个图像的基本管道。此外,由于时间维度,应用了一些额外的过滤。以下是所做的工作:

  1. 当计算热图时,使用所有已经检测到的汽车的边界框。这些边界框被认为是汽车已经在该地点被识别。这有助于避免已经识别的汽车闪烁和松动。
  2. 边界框是最后 21 帧的*均值
  3. 如果在连续 5 帧中没有发现汽车,则它已经消失。新车,需要在 5 个连续的帧中被发现,才能被绘制并被认为是现有的。

管道在提供的视频上运行,效果很好。不会出现错误检测或无法识别现有车辆的情况。视频结果是:

讨论

所描述的管道对所提供的视频非常有效,但需要在变化的照明条件下对更多的视频进行彻底的测试。我发现有趣的是,在项目视频中有一部分,两辆车被归类为一辆。第一辆车部分遮挡了第二辆车,但它仍被归类为一辆车。车没有消失,只是被遮挡了。必须找到关于这个问题的更强有力的程序。

计算到汽车的距离工作得很好,甚至比我预期的还要好。然而,当道路表面的颜色改变时,仍然存在一些问题,从识别的边界框的底部移除道路给出了错误的读数。此外,速度是相当跳动的,所以它也必须被过滤,但即使在这种形式下,它也可以给出检测到的汽车是否正在接*或远离我们的信息。

最后一点就是这个程序非常耗时。*均每次迭代大约需要 1.4 秒(Ubuntu 16.06,2 个英特尔酷睿 i7–4510 u CPU @ 2.00 GHz,8GB DDR3)来检测汽车和车道。它远不是实时的,因此它可以在真正的自动驾驶汽车中使用。通过分析,我注意到大约 50%的时间用于计算直方图。这段代码需要优化,可能需要用 C/C++重写。

车辆检测和跟踪

原文:https://towardsdatascience.com/vehicle-detection-and-tracking-44b851d70508?source=collection_archive---------0-----------------------

“只要有摄像头,你绝对可以成为超人”。埃隆·马斯克在 TED 演讲。

这是 Udacity 的自动驾驶汽车工程师纳米学位项目 第一学期的期末项目 。源代码和更详细的技术文章可以在 GitHub上找到****

目标

编写一个软件管道,从汽车上的前置摄像头识别视频中的车辆。

在我的实现中,我使用了深度学习方法来进行图像识别。具体来说,我利用卷积神经网络(CNN)的非凡能力来识别图像。

然而,手头的任务不仅仅是检测车辆的存在,而是指出它的位置。事实证明,CNN 也适用于这类问题。在 CS231n 课程 中有一个专门针对本地化的 讲座 ,我在我的解决方案中采用的原则基本上反映了该讲座中讨论的区域提议的思想,并在诸如fast R-CNN等架构中实现。

主要思想是,由于存在二进制分类问题(车辆/非车辆),模型可以以这样的方式构建,即它将具有小训练样本的输入大小(例如,64×64)和在顶部的 1×1 的单特征卷积层,其输出可以用作分类的概率值。

训练了这种类型的模型后,输入的宽度和高度维度可以任意扩展,将输出层的维度从 1x1 转换为纵横比*似匹配新的大输入的地图

本质上,这在某种程度上相当于:

  1. 将新的大输入图像切割成模型初始输入尺寸的正方形(例如,64×64)
  2. 在每一个方块中探测目标
  3. 将得到的检测结果拼接回去,将与源输入中的相应正方形相同的顺序保存到一个中,其边的纵横比*似匹配新的大输入图像的纵横比。

Consider each of these squares to be processed individually by its own dedicated CNN, producing a 4x20 detection map

数据

Udacity 为学生提供了训练分类器的强大资源。 车辆非车辆 已使用KITTI vision benchmark suite的样本进行训练。

最终的模型在检测项目视频中的白色雷克萨斯时遇到了困难,所以我用大约 200 个样本增加了数据集。此外,我使用了与 项目 2 中相同的随机图像增强技术对交通标志进行分类 ,从项目视频中产生了大约 1500 幅车辆图像。用于训练、验证和测试的车辆图像总数约为 7500 张。显然,每个样本都被水*翻转过,使数据集膨胀了 2 倍。结果,我有大约 15000 个数据点。

Class IDs are vehicles and non-vehicles

增加了相同数量的非车辆图像作为反面例子。

Typical vehicle and non-vehicle samples with their corresponding labels

模型

我从Max Ritter的实现中借用了构建网络顶部的技术,他显然采用了相同的方法。****

已经测试了许多具有不同复杂性的模型架构,以获得最终的模型。

我开始从 VGG16 架构转移学习,权重在 ImageNet 上训练。VGG 是一个伟大的和经过充分测试的架构,ImageNet weights 显然认为它应该对车辆的功能有所了解。我添加了我的顶级单特征二元分类器并对模型进行了微调。正如所料,它产生了相当高的测试精度,大约为 99,5% 。VGG 的另一面是它相当复杂,使得预测的计算量很大。**

然后,我测试了一些不同层数和形状的定制 CNN 配置,逐步降低复杂性并评估测试精度,最终得到了只有大约 28,000 个可训练参数的模型,测试精度仍然约为 99.4% :

**Epoch 5/5
607/607 [==============================] - 48s - loss: 0.0063 - acc: 0.9923 - val_loss: 0.0073 - val_acc: 0.9926

Evaluating accuracy on test set.
test accuracy:  [0.0065823850340600764, 0.99373970345963758]**

将模型的复杂性降低到极致对预测的计算成本过拟合都有好处。虽然数据集可能看起来不太大,但很难假设 28000 个参数的模型可能能够记住它。此外,我还积极利用辍学来进一步降低过度适应的风险。

该模型已经使用 KerasTensorFlow 后端实现和训练。

样本预测结果:

使用训练好的模型进行车辆检测

视频流中的原始帧如下所示:

严格来说,它不是原创的,因为它已经受到了不失真的影响,但这值得一个属于它自己的故事。对于手头的任务,这是要由车辆检测管道处理的图像。

车辆检测的感兴趣区域从顶部起大约第400个像素开始,垂直跨越大约 260 个像素。因此,我们有一个尺寸为260×1280的感兴趣区域,从垂直方向的第400 个像素开始。

这就把顶层卷积层的维度从(?,1,1,1)(?,25,153,1) ,其中 25153 是预测的微型高度宽度尺寸,反过来,最终将投影到原始高分辨率图像上。

车辆扫描流水线包括以下步骤:

  1. 获取感兴趣的区域(见上文)

2。使用训练好的 CNN 模型生成检测图😗***

3。应用置信度阈值生成二值图:

预测非常两极化,即对于车辆和非车辆点大多坚持。因此,即使是置信度阈值的中点 0.5 也可能是一个可靠的选择。为了安全起见,我坚持使用 0 .7

4。用scipy.ndimage.measurements包的label()功能标记获得的检测区域。这一步可以勾勒出标注的边界,从而有助于在构建热点图时将每个检测到的“孤岛”保持在其要素标注的边界内。

这也是被检测车辆 的第一*似值。

5。将检测点的特征标签投影到原始图像的坐标空间,将每个点转换成 64x64 的正方形,并将这些正方形保持在特征的区域边界内。

为了说明这种点到*方的转换投射到原始图像上的结果:

6。创建热图。上图中重叠的方块实际上是在积聚“热量”。

7。再次标记热图,为实际车辆的边界框生成最终的“岛”。这个特定热图的标记创建了 2 个检测“孤岛”。很明显。

8。热图的标记特征保存到标记列表中,这些特征将被保存一定数量的后续帧。****

9。最后一步是获得车辆的实际边界框。[**OpenCV**](http://opencv.org)提供了便捷的功能cv2.groupRectangles()。正如在文档中所说:“它使用矩形等价标准将所有的输入矩形聚类,该标准将具有相似大小和相似位置的矩形组合在一起。”正是需要的。该函数有一个groupThreshold参数,负责“最小可能矩形数减 1 ”。也就是说,它不会产生任何结果,直到历史积累了至少该数量的帧的边界框。**

视频实现

我已经将车辆和车道检测 合并到一个单独的管道中,生成一个包含车道投影和车辆边界框的组合镜头。

反光

我彻底研究了将 SVM 分类器应用于 HOG 特征的方法,该方法涵盖了项目课程,但我仍然非常自信地认为深度学习方法更适合车辆检测任务。在我开始提到的一个讲座中,猪只只从历史的角度来看。此外,还有一篇 论文 认为 DPMs (那些基于 HOGs )可能被认为是某种类型的卷积神经网络。

花了一些时间来弄清楚如何导出一个模型,当扩展它以接受全尺寸感兴趣区域的输入图像时,该模型将产生可靠分辨率的检测图。

即使是我最终选择的微型模型,也需要大约 0.75 秒才能在 2014 年中期的 3GHz 四核 i7 MacBook Pro 上生成 260x1280 输入图像的检测图。也就是每秒 1.33 帧。

致谢

我想亲自感谢 David Silver 和 Oliver Cameron 为 Udacity 的自动驾驶汽车 Nanodegree 项目开发的精彩内容,以及所有 Udacity 团队提供的非凡学习体验。

车辆检测和跟踪

原文:https://towardsdatascience.com/vehicle-detection-and-tracking-6665d6e1089b?source=collection_archive---------0-----------------------

在这个车辆检测和跟踪项目中,我们通过滑动窗口在视频管道中检测可能包含车辆的潜在盒子,使用支持向量机分类器进行预测以创建热图。然后,热图历史被用于在识别车辆之前过滤掉误报,方法是在它周围画一个边界框。

Vehicle Detection Sample

车辆检测项目

该项目的目标/步骤如下:

  • 对图像的标记训练集执行定向梯度直方图(HOG)特征提取,并训练分类器线性 SVM 分类器
  • 或者,您还可以应用颜色变换,并将入库的颜色特征以及颜色直方图添加到 HOG 特征向量中。
  • 注意:对于前两步,不要忘记规格化你的特征和随机选择用于训练和测试。
  • 实施滑动窗口技术,并使用您训练的分类器在图像中搜索车辆。
  • 在视频流上运行管道(从 test_video.mp4 开始,然后在完整的 project_video.mp4 上实施),并逐帧创建重复检测的热图,以剔除异常值并跟踪检测到的车辆。
  • 估计检测到的车辆的边界框。

使用了 jupyter/iPython 数据科学笔记本,可在 github 完整项目报告 — 车辆检测项目笔记本上找到(注意交互式 ipywidgets 在 github 上不起作用)。由于笔记本变得相当大,我将一些代码提取到 python 文件 utils.py(提取函数,加载助手),features.py(特征提取和类),images.py(图像和窗口切片处理),search.py(保存搜索参数类),boxes.py(窗口和框类)和 detection.py(协调图像处理的主车辆检测类)。该项目是用 python 编写的,使用了 numpy 、 OpenCV 、 scikit learn 和 MoviePy 。

方向梯度直方图(HOG)

通过一点试错,我找到了一组猪参数。

HOG 特征提取和参数

创建了一个函数 extract_hog_features ,它采用 64x64x3 的图像数组并返回一组特征。这些是并行提取的,它依次使用 HogImageFeatures 类。

由于 hog 算法主要集中在灰度图像上,我最初使用 Y 通道的 YCrCB 颜色空间(用于表示灰度图像)。然而,我发现它在检测阶段的选择性不够。因此,我使用了所有 3 个颜色通道。为了减少特征的数量,我增加了每个单元格的 HOG 像素的数量。我在我的笔记本中使用了一个交互功能,找到了一个 32 的方向设置,它显示了车辆的独特特征。样本如下。

Training Vehicle HOG Sample

最终的参数设置使用了color_space = 'YCrCb'orient = 32pix_per_cell = 16hog_channel = 'ALL'。使用颜色直方图特征进行了实验,但是它减慢了特征提取,并且后来增加了检测到的假阳性的数量。根据下面的可视化图形,您可以看到 Cr 和 Cb 色彩空间具有可检测的 hog 特征

Sample HOG Channel Output form a video window slice

分类器训练

一旦从 car ( GTI 车辆图像数据库和 Udacity Extras)和 not _ car(GTI)图像集中提取出 HOG 特征(无彩色 Hist 或 Bin 空间)。然后,它们被堆叠并转换为浮动在车辆检测笔记本中。

然后使用 Sklearn 鲁棒定标器对特征进行定标,结果如下。

实验发生在分类器实验笔记本中的 LinearSVC ( 支持向量机分类器)、RandomForest 和 ExtraTrees 分类器之间。选择 LinearSVC 是因为 10 个标签的预测时间为 0.00228 秒,而其他两个标签的预测时间约为 0.10 秒。

滑动窗口搜索

构建推拉窗

在这个项目中,选择了四种尺寸的窗户——32x 32、48x48、64x64 和 128x128,并以不同的深度透视放置在图像的右下方,以覆盖道路。较大的窗户靠*驾驶员,较小的窗户靠*地*线。x,y 的重叠设置在 0.5 和 0.8 之间,以*衡更好的覆盖需求和生成的盒子数量——目前为 937 个。滑动窗口的方框越多,每个视频图像的计算就越多。

分类器示例和优化

使用 Python 异步方法和 VehicleDetection 类中的 asyncio.gather 在搜索的并行化上花费了一些时间。在对每个窗口进行特征提取和预测之前,该搜索提取每个大小的搜索窗口的有界框图像并将其缩放到 64×64。

搜索hot_box_search返回分类器预测包含车辆的热盒阵列。

这些方框重叠在一起,用于创建一个 255 的二维热点图。为了消除初始误报,保持计数> 4。在应用另一个阈值之前,热图被标准化

heatmap = apply_threshold(heatmap, 4)
heatmap_std = heatmap.std(ddof=1)
if heatmap_std != 0.0:
    heatmap = (heatmap-heatmap.mean())/heatmap_std
heatmap = apply_threshold(heatmap, np.max([heatmap.std(), 1]))

将这个阶段重新绘制到图像上

热图有一个历史记录

然后作为输入输入到 Scipy 标签中,该标签具有链接维度的模糊二进制结构,给出

最后,在每个框上应用方差过滤器,如果对于一个检测到的标签框,方差< 0.1 (its just a few close points0 or if multiple with a variance < 1.5 (more noise).

Video Implementation

Vehicle Detection Video

The 忽略 GitHub 上的项目 VehicleDetection mp4,包含结果( YouTube Copy )

跟踪车辆检测

scipy . ndimage . measurements . label函数的一个很好的特性是,它可以处理 3d 数组,给出 x,y,z 空间中的标签。因此,当使用热图历史的数组作为输入时,它在 x、y、z 中标记连接。如果返回的标记框没有在至少 3 个(热图历史最大值-2)z *面中表示,则它被拒绝为假阳性。结果是,车辆在保存的热图历史中被跟踪。

讨论

当构建这个管道的时候,我花了一些时间来并行化窗口搜索。我发现这样做很可能不会提高整体性能。图像必须连续处理,在生成视频时,我的 cpu 没有得到充分利用。

事后看来,我应该用一个大范围的搜索来探测车辆,然后用一个更小范围的搜索来探测最后已知的位置。可以以更大的间隔或者当车辆检测丢失时运行大重量搜索。

如果车辆在汽车的左侧或中间,我的管道将立即失效。我怀疑卡车、摩托车、骑自行车的人和行人不会被检测到(因为他们不在训练数据中)。

基于前置摄像头的车辆检测和跟踪

原文:https://towardsdatascience.com/vehicle-detection-and-tracking-from-a-front-face-camera-a9b83c842f58?source=collection_archive---------3-----------------------

Udacity 自动驾驶工程师 Nanodegree —学期 1,作业 5。

目标

这是为 Udacity 自动驾驶汽车工程师 Nanodegree 第一学期的第五次也是最后一次任务创建的报告。挑战在于创建一种算法,利用前置摄像头获取的视频来检测道路上的其他车辆。

这是 Github 库。

特征抽出

为了检测车辆或任何其他物体,我们需要知道它们与相机拍摄的其他图像有何不同。颜色和渐变是很好的区分因素,但最重要的特征将取决于对象的外观。

颜色单独作为一个特征可能是有问题的。依赖于颜色值(或颜色直方图)的分布可能最终在图像的不需要的区域中找到匹配。渐变可以提供更强大的演示。它们在围绕中心的特定方向上的存在可以解释为形状的概念。然而,使用梯度的一个问题是,它们使签名过于敏感

HOG 方向梯度直方图

HOG 是一种计算图像局部梯度方向出现次数的计算机视觉技术。如果我们计算每个像素的梯度
大小和方向,然后将它们分组为小单元,我们可以使用这个“星形”直方图来建立该单元的主要梯度方向。

“Star” histogram of gradient directions

这样,即使很小的形状变化也会保持签名的唯一性。各种参数,如方向箱的数量、网格(单元)的大小、单元的大小、单元之间的重叠,对于微调算法非常重要。

HOG、色彩空间、空间和彩色宁滨参数

在最终的特征提取函数中,我们对 YCrCb 应用了颜色变换。然后,我们将装箱的颜色特征向量、颜色向量的直方图与 HOG 特征向量连接起来。对所有颜色通道进行 HOG 计算。

color_space = ‘YCrCb’ 
spatial_size = (16, 16)               # Spatial binning dimensions
hist_bins = 32                        # Number of histogram bins
orient = 9                            # HOG orientations
pix_per_cell = 8                      # HOG pixels per cell
cell_per_block = 2                    # HOG cells per block
hog_channel = “ALL”                   # Can be 0, 1, 2, or “ALL”

训练分类器

一旦提取了特征,就该建立和训练分类器了。课程中介绍的方法是建立一个分类器,可以区分汽车和非汽车图像。然后,这个分类器通过对小块进行采样而在整个图片上运行。每个补丁然后被分类为汽车或非汽车。

数据集

为了训练分类器,我使用了车辆和非车辆示例的标记数据。这些示例图像来自 GTI 车辆图像数据库、KITTI vision 基准套件和从项目视频本身提取的示例的组合。

数据被随机打乱后分成训练集和测试集,以避免数据中可能出现的排序效应

训练基本上是为训练集中的每幅图像提取特征向量。这些向量和它们各自的标签(汽车非汽车)提供给训练算法,该算法迭代地改变模型,直到预测和实际标签之间的误差足够小。(或者在多次迭代后误差停止减小。)

归一化特征向量的大小

在开始训练分类器之前,我们将特征向量归一化为零均值和单位方差。这是必要的,因为基于颜色的特征和基于渐变的特征之间存在大小差异,这可能会导致问题。

# Fit a per-column scaler
X_scaler = StandardScaler().fit(X)# Apply the scaler to X
scaled_X = X_scaler.transform(X)

支持向量机分类器

正如课程中所建议的,我们使用支持向量机对数据进行分类。我们也实现了一个决策树分类器,但是准确性看起来不太好,所以我们决定继续微调 SVM。

3.26 Seconds to train SVC...
Test Accuracy of SVC =  0.9926

滑动窗口方法

既然我们已经训练了分类器,我们将不得不在帧中搜索汽车。前提是我们在图像中定义小块,然后对每个小块运行分类器。然后,分类器将决定该小块是否“是”汽车。

在滑动窗口技术中,我们在图像上定义一个网格,并在其上移动以提取训练的特征。分类器将在每一步给出预测,并判断网格元素是否包含汽车特征。

鉴于图像的视角,远离汽车摄像头的物体会显得较小,而靠*的汽车会显得较大。因此,网格细分根据图像上的位置考虑不同的大小是有意义的。我们也不考虑地*线以上的任何区域,忽略有天空、山脉和树木的区域。

跟踪问题

不足为奇的是,分类器将返回大量的假阳性。这些区域没有汽车,但是图像中的照明或纹理会欺骗分类器称其为汽车。对于自动驾驶汽车应用程序来说,这显然是一个大问题。假阳性可能导致汽车改变方向或启动刹车,这是事故的潜在原因。

为了过滤掉误报,我们记录每一帧的所有检测的位置,并与在后续帧中发现的检测进行比较。检测的群集很可能是一辆真实的汽车。另一方面,在一帧中出现而在下一帧中没有再次出现的检测将是误报。

热图和边界框

搜索find_cars返回分类器预测包含车辆的热盒阵列。我们创建了一个热图来识别重叠盒子的集群。使用apply_threshold,我们可以移除假设的误报。

import collections
**heatmaps** = collections.deque(maxlen=10) 

def process_frame(source_img): out_img, boxes = find_cars(source_img, ystart, 
                           ystop, scale, svc, 
                           X_scaler, orient, pix_per_cell, 
                           cell_per_block, spatial_size, 
                           hist_bins, False) current_heatmap =   
                 np.zeros_like(source_img[:,:,0]).astype(np.float)
    current_heatmap = **add_heat**(current_heatmap, boxes)
    **heatmaps.append**(current_heatmap)
    heatmap_sum = sum(heatmaps)

    heat_map = **apply_threshold**(heatmap_sum, 2)
    heatmap = np.clip(heat_map, 0, 255)
    labels = label(heatmap)  
    labeled_box_img = draw_labeled_bboxes(source_img, labels)return labeled_box_img

上面的例子是针对单个帧的。如前所述,我们要考虑时间顺序,以避免一次性考虑。我们使用了一个deque数据结构来保存最后 10 帧的盒子。

管道和视频

总结我们的整体跟踪渠道:

  • 处理带标签的数据集以定义训练和测试集
  • 从数据集图像中提取特征
  • 训练分类器。
  • 对于每个视频帧:使用滑动窗口技术运行搜索,并过滤掉误报

Generated video

考虑

值得注意的是,一些检测到的是高速公路对面的汽车。虽然这不是一件坏事,但我们可以通过缩小考虑范围来避免它们。

当汽车进入视频帧时,检测会有一点延迟,这种情况可以通过调整*均框计算中考虑的帧数来解决。

最*使用深度神经网络的技术可以通过提高准确性、减少假阳性的发生和提高性能来改善特征检测。微小的 YOLO 似乎是一种常见的方法。

Janai 等人(2017) 发表了一份关于技术如何改进以及仍需解决的挑战的评估。

这是一个总结第一学期的伟大项目。我可以看到我从使用 OpenCV 寻找车道的第一个任务中学到了多少,我期待着在第二学期学到更多。感谢出色的 Udacity 团队让这一切成为可能。

基于机器学习和 HOG 的车辆检测和跟踪

原文:https://towardsdatascience.com/vehicle-detection-and-tracking-using-machine-learning-and-hog-f4a8995fc30a?source=collection_archive---------5-----------------------

我进入了 Udacity 自动驾驶汽车 Nanodegree 的第一个学期,我想分享我关于第一学期最终项目的经验,即车辆检测和跟踪。完整的代码可以在这里找到。

介绍

这个项目的基本目标是应用 HOG 和机器学习的概念从仪表板视频中检测车辆。等一下?机器学习和 2018 年的物体检测?听起来过时了,不是吗?当然,利用卷积神经网络的深度学习实现,如 YOLO 和 SSD,在这方面表现突出,但如果你是这一领域的初学者,最好从经典方法开始。所以让我们开始吧!!

收集数据

对于任何机器学习问题来说,最重要的是带标签的数据集,这里我们需要两组数据:车辆和非车辆图像。这些图像取自一些已经可用的数据集,如 GTI 和 KITTI Vision 。图像大小为 64x64,看起来有点像这样:

Figure 1. Vehicle Images

Figure 2. Non Vehicle Images

提取特征

一旦我们得到了数据集,下一个明显的步骤就是从图像中提取特征。但是为什么呢?为什么不能把图像原样喂给机器学习分类器?我的朋友,如果我们这样做,将需要很长时间来处理图像,只是提醒一下,我们不是在这里向 CNN 提供图像,这毕竟不是一个深度学习问题!

明白了,但是如何提取特征呢?如果你想从图像中提取特征,有三种好方法。

  1. 颜色直方图- 最简单直观的方法就是从图像的各个颜色通道中提取特征。这可以通过绘制各种颜色通道的直方图,然后从直方图的箱中收集数据来完成。这些箱给了我们关于图像的有用信息,并且在提取好的特征方面非常有帮助。

Figure 3. Color Histograms for Vehicle Image

Figure 4. Color Histograms for Non Vehicle Image

2.空间宁滨- 彩色直方图确实很酷,但是如果图像的特征如此重要,那么为什么我们不能使用某种 numpy 函数来提取所有的特征呢?在这一点上你肯定是正确的。我们可以通过使用 numpy.ravel()展*图像来提取图像中的所有信息。但是等一下,让我们做一些计算,图像大小是 64x64,它是一个 3 通道图像,所以提取的特征总数是 12,288!!单个图像中接* 12k 的特征不是一个好主意!所以这里空间宁滨来图片!如果我说,一个 64x64 的图像提供的信息和 16x16 的图像提供的信息是一样的呢?当然有一些信息丢失,但我们仍然能够从图像中提取出好的特征!因此,如果我将 numpy.ravel()应用于 16x16 的图像,我将只能获得 768 个特征!

Figure 5. Spatial Binning Intuition

  1. HOG(梯度方向直方图)——上面讨论的特征提取技术很酷,但肯定比不上 HOG。HOG 实际上拍摄了一幅图像,把它分成不同的块,在块中我们有细胞,在细胞中我们观察像素并从中提取特征向量。单元内的像素被分类到不同的方向,并且块内特定单元的结果向量由最强向量的幅度决定。注意——这里我们不计算某个像素在某个特定方向上的出现次数,而是对该像素在该特定方向上的大小感兴趣。阅读更多关于猪这是一个很好的链接。

Figure 6. HOG with 9 orientations. CPB(Cells Per Block) PPC (Pixels Per Cell)

这里只需要注意一点。OpenCV HOG 返回 HOG 图像和特征向量,但是 image.ravel()的长度不等于特征向量长度。这是因为 HOG 在内部执行一些计算,减少数据中的冗余,并返回优化的特征向量。此外,您在图像中看到的行数越多,意味着它将返回更多的特征。

生成数据集和数据预处理

好了,酷,现在我们知道如何提取特征,所以我们将处理所有图像的这些步骤?是的,你是对的,但是没有必要使用上述所有方法的所有功能。让我们暂时只使用 HOG,忽略颜色直方图和空间宁滨。

让我们决定提取特征的 HOG 参数。经过多次尝试,我决定采用以下方法:

  • 方向- 9
  • 每块电池- 2
  • 每个单元格的像素- 16
  • 色彩空间- YUV

酷,用这些参数通过 HOG 函数运行图像后,最终的参数大小是 972,非常酷!

数据预处理 现在我们的特性已经准备好了,下一步是预处理数据。不要担心,sklearn library 总是在那里帮助完成这些任务。我们可以执行以下预处理:

I)混洗数据
ii)将数据集分成训练集和测试集
iii)数据的标准化和缩放(数据集的拟合和变换)

这里要注意的非常重要的一点是,在步骤(ii)之后,我们必须拟合和转换数据,但是我们不应该拟合测试集中的数据,因为我们不希望我们的分类器将峰值偷偷带入我们的数据中。

训练分类器

嗯,特征提取,数据预处理!接下来呢?是的,现在轮到我们的分类器了。你可以选择分类器,但是有很多分类器可供选择:

  • 支持向量机
  • 朴素贝叶斯
  • 决策图表

我决定用支持向量机,因为它们和 HOG 有很好的兼容性。现在在 SVM,我们有 SVC(支持向量分类器),在这里,我们也可以选择不同的核和不同的 C 和γ值。

我在线性核和 rbf 核上训练我的分类器。线性核花费大约 1.8 秒来训练,测试精度为 98.7%,而 rbf 核花费大约 25 分钟来训练,测试精度为 98.3%。我决定使用带有默认参数的 LinearSVC,仅仅是因为它运行时间更短,而且比 rbf 内核更精确。

推拉窗

酷我们的分类器现在训练有素,它将有 99%的时间能够正确预测车辆和非车辆。那么下一步是什么?好吧,下一步是将分类器应用到你的图像中,以便找到汽车在图像中的确切位置!

但是首先你需要决定各种重要的参数。第一件事是从哪里开始搜索汽车,显然你不应该在天空中搜索汽车,因此你可以忽略图像的上半部分,所以基本上确定一个地*线,在这个地*线下你将搜索你的汽车。第二件重要的事情是你要找的窗口大小是多少,两个窗口应该重叠多少?这取决于你的输入图像长度,因为这里是 64x64,所以我们将只从 64x64 的基本窗口大小开始。下一件重要的事情,也是这里要注意的非常重要的一点是,你在地*线附*搜索较小的汽车,当你走向仪表板摄像头时,你搜索较大的汽车。这是因为如果汽车靠*地*线,它们就越小,因为它们远离你的汽车,而靠*的汽车则相反。

但是我应该增加多少窗口大小和多少重叠?那要看你的眼光了。我决定使用 4 种不同尺寸的窗户。在下面的图片中,我将尝试用相应的窗口大小来说明我的搜索区域。

Figure 7. My Choice of Window Sizes with Overlap and Y coordinates

Figure 8. Window Size 64x64 Coverage

Figure 9. Window Size 80x80 Coverage

Figure 10. Window Size 96x96 Coverage

Figure 11. Window Size 128x128 coverage

我的总窗口大小为 470!因此,一旦我们定义了我们将搜索的所有滑动窗口,下一步就是逐个窗口提取所有补丁的特征,并运行我们的分类器来预测找到的窗口是否是汽车。请记住,我们在从 64x64 图像提取的特征上训练我们的模型,因此对于大小不同的窗口,我们需要首先将它们的大小调整为 64x64,以保持特征相同。让我们看看我们的分类器是如何工作的。

Figure 12. Refined Windows after running the classifier.

热图

因此,我们能够检测滑动窗口,但有一个问题。这么多窗口相互重叠,如何画出最终的包围盒?答案是热图。我们将创建一个与原始图像大小相同的空白黑色图像,对于所有已识别的优化窗口,我们将为优化窗口的整个区域增加一个像素值。这样,我们将得到具有不同强度的区域,其中公共区域是最强的。然后,我们可以应用一个阈值来裁剪最终的图像,并获得最终盒子的坐标。

Figure 13. Heatmap drawn after increasing the pixel intensities of refined windows

Figure 14. Final Image After applying the threshold

Figure 15. Testing Pipeline On a New Image

好吧,太酷了,就这样?嗯,是也不是!当您在更多的测试图像上运行代码时,还有一个问题。

Figure 16. Applying Heatmap on some more Images

正如你所观察到的,在我们的图像中检测到了一些误报,从左车道驶来的车辆也被检测到,那么我们如何解决这个问题呢?首先我们需要观察这个问题是如何出现的?我们的分类器有 98.7%的准确率。我们总共有 470 扇窗户。因此,在生成的窗口中,我们将有大约 6 个窗口是误报的。如果最终热图图像中的阈值较低,这些窗口可以出现在任何地方。因此,要解决汽车驶入另一条车道的问题,一些误报可以通过提高阈值来解决。在我的例子中,我将阈值设置为值 4,但是阈值设置还是取决于许多因素,使用的色彩空间,SVM 精度等等。

求*均值

我们现在差不多完成了!管道处理图像的效果非常好,但是如果你要对来自视频流的图像运行管道,还是有一个问题。最终检测到的框将变得非常不稳定,无法提供流畅的体验,在某些帧中框可能会消失。那么解决办法是什么呢?解决方案非常直观,存储所有从前 15 帧检测到的细化窗口,并*均当前帧中的矩形。此外,你需要调整阈值到一个更高的水*。通过这样做,最终的边界框看起来不那么抖动,并提供一个*滑的流程。我在项目视频上尝试了我的管道,结果有点像这个。

一些提示和技巧

  1. 如果您在视频上运行管道时处理时间过长,请先尝试缩小窗口。
  2. 如果处理时间仍然很长,请尝试减少提取的要素数量。
  3. 如果你有一个包含 10,000 张图片的测试集,你的特征大小是 8000,即使测试集的准确率超过 95%,SVM 也不会达到标准。使用具有“rbf”内核或 reduce 特征的 SVM。
  4. 如果管道运行仍然需要很长时间,请尝试跳过一半或三分之二的帧。它会加速。记住,我所说的跳过帧是指跳过对帧的处理,并将该帧的细化窗口设置为从存储在某个数据结构中的前 15 帧中收集的矩形。

你可以在这里观察最终的视频输出。

当然,视频并不完美,但我很高兴最终的输出。有较少的滞后,也没有检测到来自其他方向的汽车。还有。我正在研究 YOLO 和 SSD 方法,并将很快写下从中得到的经验。万岁!!第一学期结束了,是时候自我反省了,也为第二学期感到非常兴奋。

基于支持向量机(SVM)的车辆检测

原文:https://towardsdatascience.com/vehicle-detection-using-support-vector-machine-svm-19e073b61d16?source=collection_archive---------1-----------------------

下面是从视频中成功检测到汽车的输出视频:

分析:

我已经完成了 Udacity 自动驾驶汽车项目的车辆检测项目。在这里,我试图提供使用支持向量机(SVM)检测车辆的详细分析。

在此之前,为了理解使用 SVM 实现车辆检测,我们需要知道一些术语:

图像特征提取:

我做的第一件也是最重要的事情是从图像中提取特征。图像中有许多可以提取的特征,这些特征可以帮助训练我们的分类器。通过仅从称为特征描述符的图像中提取有用的信息来表示图像。我用于车辆检测的一个重要的 T4 特征描述符是猪:

梯度方向直方图(HOG):

形状是表征任何物体的重要参数之一。HOG 是一种特征描述符,用于根据对象的形状来表征对象。该技术计算图像提及部分中每个梯度方向的直方图(出现次数)。但是等等,到底什么是渐变定向???正如我们所知,每张图像都有颜色和亮度。这些性质的方向变化可以称为梯度取向。以下是特征提取的逐步过程,其中也包括 HOG:

  1. 提取图像的空间特征:

调整图像大小后,我们仍然保留了图像的所有特征。因此,我们调整了图像的大小,有了它的帮助,我们的代码会运行得更快,而不会丢失任何信息。这可以在打开 cv 函数 cv2.resize()的帮助下完成。

2。图像色彩空间转换:

将图像转换到特定的色彩空间以从所选色彩通道中提取信息:

我们可以将图像转换为以下任何色彩空间:

RGB、HSV、YCrCb、YUV、LUV、HLS

例如,如果你想识别一个物体在阴影下的图像,我们可以使用它们的一些属性,如图像的亮度或饱和度,来更有效地对一些阴影下的车辆进行分类。这可以通过使用 HLS 色彩空间通道来完成。

3。颜色直方图提取:

我们借助函数 numpy.histogram()获取图像的颜色直方图。这在存储图像的不同特征时非常重要。

4。猪:

如上所述,HOG 是我在特征提取过程中使用的最后一步。我为 hog 使用的函数是 HOG()。下面是图像的 hog 特征的可视化:

Hog feature of a car

特征提取完成后,现在开始训练我们的分类器。我用过 rbf SVM(支持向量机中的径向基函数)。早些时候,我尝试使用线性 SVM 模型,但由于准确性较低,我的代码在许多地方无法检测到车辆。使用 rbg SVM 将我的准确率提高到 99.13 %。

使用滑动窗口检测汽车:

既然分类器被训练,我们使用滑动窗口概念。对于车窗的每个区域,我们应用图像分类器来检查是否在该区域检测到车辆。请注意,汽车的大小将根据汽车离我们的汽车有多远而有所不同。下面是一个这样的例子,由于汽车与中央摄像机的距离不同,汽车尺寸也不同:

因此,我使用了 3 个不同大小的矩形窗口,它们将贯穿整个图像并检测汽车,如果有的话。我选择的窗口尺寸是 64x64、96x96 和 128x128。如果有汽车出现在窗口,我们将窗口位置保存到一个变量中。实施之后,我仍然面临两个问题:

  1. 单个汽车图像的窗口太多:

虽然在图像的某些部分检测到了汽车,但是还有许多窗口在检测汽车。下面是我为图片中的两辆车准备的窗户:

Multiple windows

我的目标是只有一个窗口,而不是这么多的窗口。

2。误车检测(误报)

False positive

现在是项目的最后一部分,热图。我创建了所有汽车检测的热图,对于每个检测,我将热图[window_img]增加 1。现在,在热图的帮助下,我将只保留一个窗口,而不是一辆车的多个窗口。此外,我将拒绝一些窗口的基础上,一些阈值。这是我的热图中具有多个(重叠)窗口的图像的外观:

以下是应用热图后的结果图像:

Detected cars from an image

虽然汽车被正确地检测到,但我仍然觉得这个视频有一些局限性。处理这段视频花了大约 30 分钟。此外,这在我们有其他物体(如行人)的其他场景中可能并不完美。在接下来的日子里,我一定会尝试 YOLO 来提高准确性!!

通过图像处理识别外部环境中的车辆

原文:https://towardsdatascience.com/vehicle-recognition-in-external-environments-through-image-processing-87dd00237dc8?source=collection_archive---------2-----------------------

这是我 2015 年为伯南布哥大学做的科学研究的结果。

这个研究项目旨在协助开发一个低成本的本地系统,不依赖于外部条件就能监控十字路口的车辆流量。使用数字图像处理技术来识别车辆,并在需要的情况下做出决策。在一个简化的方法中,提出了在城市环境中检测车辆的计算方法。本文中的解决方案已经用 VisualStudio C++实现,并使用 OpenCV 库来实现识别。针对两种类型的条目提出了解决方案:图像和视频。图像中侦察车辆的算法结果更接*本研究的目标。然而,还提出了一种在视频中使用识别算法的解决方案。

在文献中有不同的方法探索车辆的检测和识别。可以在已处理的对象和初始数据库的对象之间进行比较,也可以获得优化场景减法和使用连续帧之间的对称差的结果。

还有混合方法,除了计算机视觉之外,还寻求其他方法来优化识别和检测,例如使用基于激光的传感器。

也可以使用感兴趣区域的分割和选择技术、车辆的检测和识别以及阴影的去除技术,集中于使用静态摄像机的方法,目的在于主动交通监控。在体积计数的方法中,我们可以突出那些使用静态监控摄像机的方法。

神经网络应用于车辆检测。但是神经网络有两个主要问题:不能保证达到全局最小值,第二个问题意味着它定义了代表真实世界的数据集,并且没有理想的神经网络模型。模糊逻辑测量用于检测车辆。光强度值用作漫射测量。当强度值落在某个范围内时,必须使用失真的测量来确定它是否是车辆。

首先,我使用基于级联分类器的 Haar 特征来检测对象。这个特性最初是由保罗·维奥拉提出的,后经雷纳·林哈特改进。一个分类器(即具有相似 Haar 特征的工作驱动分类器的级联)由特定对象(即人脸或汽车)的数百个样本视图组成,这些样本视图被称为正样本,它们的大小相同(例如,20x20),负样本是相同大小的任意图像。

在分类器被训练以应用于感兴趣的区域(与训练期间使用的大小相同)之后。如果该区域可能显示对象(即面部/汽车),则分类器产生“1”,否则产生“0”。要在图像中搜索对象,您可以在图像中移动搜索窗口,并使用分类器检查每个位置。分类器被设计成可以容易地“调整大小”,以便能够定位不同大小的感兴趣的对象,这比调整图像本身的大小更有效。因此,为了在图像中找到未知大小的物体,检查过程应该在不同的比例下进行几次。

几个分类器用于测试。有些被证明在某些特定位置对汽车有效,但没有一个被证明在正常交通情况下有效。

Vehicle Recognition using Haar feature

Vehicle Recognition using Haar feature

Vehicle Recognition using Haar feature

由于发现的分类器的结果不完全令人满意,因此需要训练一个分类器来满足这项工作的需要。但是没有用于训练分类器的数据库。有必要创建一个数据库,其中包含各种位置的汽车图像。

该项目的最初想法是开发一种工具来实时计算车辆的体积。然而,由于开发一个通用计数项目非常复杂,为了使实现可行,做了一些简化。这些简化涉及图像、风景和物体的获取。

图像采集:必须通过读取之前存储的视频文件来执行,因为算法没有足够的计算效率来处理实时视频。

场景:它最好是静态的,虽然系统能够很好地处理*滑的运动,但关键是摄像机的位置要确保它能够提供赛道的最佳视图。这种场景的选择旨在避免遮挡的发生,并简化图像分割和对象处理的过程。

对象:对对象进行了概括,即所有对象都被视为车辆。由于我们使用了特定的场景和视频,这是一个有效的概括,它允许更简单的识别过程。

OpenCV 库用于图像处理和分割。对于操作,使用了库的基本功能,允许图像的读取、访问、写入和呈现。

分割包括利用图像的某些属性的技术,以便根据要解决的问题将图像细分成组成图像的区域或对象。在这种情况下,将视频的每一帧细分成两种类型的区域:场景和运动物体。检测这些对象的简单方法是从当前帧中减去场景图像。

Original

MOG2

Binary Image

Result

在不同环境和更高分辨率的视频中的结果不如图 4、5、6 和 7 中呈现的结果令人满意。

作为这个算法的一个应用。提出了一种交通控制算法的组成。这种合成识别双向运动,选择两者中感兴趣的区域,并通过像素计数返回到交通流量更多的区域。计数可以根据地点、时间、车流量和各种其他情况而变化。最简单的解决方案是绘制信息图,并将其分为几类:密集流量、正常流量和少量流量,然后根据这些预定义的信息,做出释放或抑制流量的决定。

该系统在 VisualStudio C ++中开发,使用 Intel 的 OpenCV 库。使用的 OpenCV 版本是 2.4.10。实验结果在由单个摄像机制作的实时视频中进行了演示。测试是在英特尔酷睿 i5–2.60 GHz 笔记本电脑上进行的,该笔记本电脑配有 4,000 GB 内存和 Windows 8.1。

高速车辆以及如何追踪它们

原文:https://towardsdatascience.com/velocious-vehicles-and-how-to-find-them-6e4a8b45f770?source=collection_archive---------8-----------------------

成为自动驾驶汽车工程师之路:第一部分

A view of NVIDIA’s self driving car technology

毕业后,我把探索课堂上没有机会探索的话题作为自己的目标。我的目标是每天阅读两篇关于人工智能技术最新进展的文章(即机器学习、深度学习、人工智能在游戏中的应用,等等)。我一直在阅读关于 OpenCV 和自动驾驶汽车的文章,并在过去一个月的一些兼职项目中受到启发来实践 OpenCV。现在自动驾驶汽车很热门!大概还有至少 15 个其他帖子是关于爱好者是如何制作它们的。尽管如此,我很兴奋也很荣幸成为第 n 个分享我的尝试的人。在写了一个简短的车辆检测脚本后,我偶然看到了 Udacity 的无人驾驶汽车纳米学位项目,,我意识到我可以做更多的工作来改进算法…

Basic vehicle detection code

我没有参加这个项目,所以我在这里完全靠自己。我仍然认为用我从自己的研究中学到的东西来实现我自己的解决方案会很有趣!

数据和算法

自动驾驶汽车的目标是创造能够在任何可能的道路条件下自动驾驶的车辆,特别是在被高速司机包围的情况下。研究人员得出结论,使用 SVM 分类器,以下算法会产生快速且最优的结果:

  • 通过将图像分解成区域来执行定向梯度直方图特征提取,并使用光梯度或边缘检测用局部对象来训练分类器。
  • 对所有分辨率和大小的图片执行色彩空间转换和空间宁滨,以实现最佳图像处理。
  • 用训练好的分类器实现滑动窗口算法在图像中搜索车辆。
  • 估计并绘制检测到的车辆的最终包围盒。

使用的车辆数据集来自 GTI 车辆图像数据库,路测视频和图像来自 KITTI vision 基准套件。Udacity 还发布了一个标签为的数据集,它可能会用于这个项目的后续组件。

数据准备

我从组织图像开始。我制作了列表,将所有标记的图像分组,然后为训练数据制作了额外的列表,以避免过拟合。这只是为了验证数据是否组织正确。

Side by side comparison between a vehicle and the road

Side by side comparison between a vehicle and an aerial image

特征抽出

梯度方向直方图(HOG)的思想是通过描述光强梯度或边缘分布方向来检测局部目标。通过将图像分解成更小的区域(单元),每个单元生成一个梯度方向直方图,或者可以表示这些组合的像素单元边缘方向直方图。为了提高准确性,可以在图像的较大区域(称为块)中评估局部直方图,比较光强作为标准化的度量,然后使用该值(measure)标准化块中的所有细胞。

HOG feature extraction example.

但是,对于这个特定的分类任务,什么样的特征是有用的呢?让我们用一个例子来讨论这一点。例如,假设我们想要构建一个对象检测器来检测衬衫和外套上的按钮。纽扣是圆形的,通常有几个用于缝纫的孔。你可以在一个按钮的图像上运行一个边缘检测器,仅仅通过观察边缘图像就可以很容易地判断出这是不是一个按钮。在这种情况下,边缘信息是“有用的”,而颜色信息不是。此外,特征还需要具有辨别能力。例如,从图像中提取的良好特征应该能够区分按钮和其他圆形物体,如硬币和汽车轮胎。这就是如上所述的光强度有用的地方。

在 HOG 特征描述符中,梯度方向(定向梯度)的分布(直方图)被用作特征。图像的梯度是有用的,因为边缘和拐角(突然强度变化的区域)周围的梯度幅度很大,并且我们知道边缘和拐角比*坦区域包含更多关于物体形状的信息。因此,HOG 描述符特别适合于人体检测。

注意在 HOG 图像中检测到的车辆和道路边缘。这些相同的特征在下面的附加图像中突出显示:

Road and Vehicle HOG

Road and Vehicle features

Road and Vehicle HOG with lower resolution pictures

Road and Vehicle features with lower resolution pictures

训练分类器

对于分类器,我使用了线性支持向量机 (SVM),这是一套用于分类、回归和离群点检测的监督学习方法。这是一个合适的分类器,因为我们已经标记了要处理的数据。

我存储了从车辆和非车辆图像中提取的特征,并将这些特征用于训练数据和测试数据。我使用了scikit-learn中的帮助函数来分割数据进行训练。

分类器达到了 0.9817 的精度。现在我们可以开始测试了!

形象化

滑动窗口是一个应用在照片上的盒子。它有一个特定的高度和宽度,这个盒子从上到下滑过一幅图像。对于每个位置,我们训练的分类器应用于该区域,并寻找所需的对象。

Sliding window example looking for a face, courtesy of pyimagesearch.com

这是计算机视觉中的一种常见技术,因为我们将能够检测到不同尺度和位置的物体,特别是如果这在路上工作的话。

Bounding boxes drawn with a Sliding Window algorithm. It’s clear that there are some false positives

在上面的六幅测试图像中,分类器返回了肯定的检测结果,但是在道路的左侧有一些假阳性。一个建议的替代方法是尝试使用热图。热图背后的想法是,通过给值分配颜色,而不是简单地看图像,可以有效地可视化数据和模式。

热图

Heat map of detected vehicles

对于在边界框中发现的每个像素,添加热量并突出显示构成检测到的车辆的像素。映射和阈值算法计算汽车被检测到的次数。贴图中较亮的色调表示每个边界框中重复检测到的像素。因此我们增加了更多的热量。热图肯定更容易解读,尤其是在边界框更突出的情况下出现假阳性:

结果

Detection results

在应用检测算法之前,我使用了imageiomoviepy来*滑测试视频的帧。每个检测到的对象都存储在一个队列中。每次我们在剪辑的当前帧或后面的帧中检测到车辆时,我们都会检查是否在过去的帧中检测到类似的对象。如果我们这样做了,我们会添加检测到的对象,并在多个帧中增加对象的数量。下面的 gif 展示了一个成功的车辆检测程序示例:

Vehicle detection demo

结论

当我第一次尝试这个项目时,我只使用了预先训练的车辆级联。我从最*的尝试中学到了很多,并且能够制作出一个假阳性更少的演示。使用传统的机器学习技术很有趣,所以我很乐意使用深度学习来实现一个解决方案(PyTorch 是我的堡垒,但在阅读了这篇帖子后,我不得不尝试 Tensorflow 的对象检测 API)。我不会使用 Udacity 的确切课程,但我很高兴能继续构建这个项目。请继续关注未来组件的更多工作!

创业思维——数据和规模的革命

原文:https://towardsdatascience.com/venture-ideation-the-revolution-of-data-and-scale-a423bdcd3aee?source=collection_archive---------7-----------------------

View from Potsdam Boat Ride

我们需要明白,非洲的革命不会被电视转播。这听起来可能像是陈词滥调,但这不是吉尔·斯科特-赫伦的歌词,现实更加不祥,因为革命几乎肯定会直播。事实上,它正发生在“ koro-koro ”之前,在我们的“非常的眼前。

席卷非洲的技术革命,在规模和范围上,以及最终在直接影响和间接影响上,将会更加混乱和/或更具破坏性(取决于你的估计)。发令枪已经开火了,尽管它被消音器扭曲了——这是非洲生活节奏的消音效果。但你可以感觉到它开始发挥出来,那些知情人士正在定位。与人工智能、机器学习和物联网的综合效应相比,这将使当前由移动驱动的技术相形见绌,因为这些技术是由我们的数据的离岸捕获驱动的。

我将数据中的“D”大写,以强调其重要性、相关性和影响。任何没有意识到这种中心性的组织或企业都已经奄奄一息或死亡;他们可能还不知道。面对这场革命,重要的是向现有的、新兴的和未来的创业人才发出响亮的号召,无论是盈利性的还是其他的。至少在短时间内,挑战带来的机遇为我们在当地的“霍布斯”环境中建立长期的企业提供了动力,促使我们现在就采取行动——特别是在创新的利基市场,或者永远保持和*。在这个新时代,数据积累的规模和范围是迄今为止单调乏味的模拟方法所无法比拟的。

恰当的例子:归根结底,互联网(这简直是人类历史上最指数化的数据增长工具)本质上是推动数据革命的真实*台的增值,是能源获取的嗡嗡声和鼓声。有能源丰富的国家和能源贫乏的国家;很明显,前者(数据殖民主义者)将永远智胜并超越后者(数据殖民地),除非我们现在就开始行动,至少强迫谈判解决。但是在我们开始谈判之前,为了确保取得一点点成功;在即将到来的对抗中,我们的 BATNA(谈判协议的最佳替代方案)是什么?很明显,快速失败、学习和调整的广泛和积极的游戏中的皮肤迭代必须超越任何存在的限制,以玩我们的进攻游戏和扩充我们的数据。

AE4H Innovation Lab 2017 Group Photo

我现在正在德国波茨坦的“人类可负担能源”(AE4H)创新实验室(https://ae4h.org/innovation_lab);这已经改变了我的想法。在评估其能源获取主题(以及潜在的实施考虑和可持续性动态)时,我的基本总结是,推动非洲在*等的基础上重新出现在全球舞台上所需的基础设施必须包含多元化利益相关者(角色)和价值(交换)网络的概念,交叉补贴提供基础设施所需的各种产品、服务、渠道和*台。对于许多非洲初创公司来说,理解快速和可持续地部署可用、可负担和可获得的技术支持产品和服务的需求(在我们缺乏支持基础设施的情况下)和即将到来的数据革命之间的联系需要更加清晰和明显。

事实上,维克多·阿塞莫塔在他最*的开创性文章(https://medium . com/@ as emota/the-age-of-zero-excuses-13fd 66265134)中概述了我们现在所承担的责任以及作为其特征的参数。根据他的前提,我试图强调这样一个事实,即这一责任不仅适用于软件或互联网支持的企业(在我们的地区相对更容易构思、开发和测试,基于物流的),也适用于我们在这样做时必须克服的物理(和其他邻*)基础设施的缺乏。

简而言之,数据稳定流动(尤其是来自金字塔底层用户)的一个关键障碍是持续缺乏可持续和可扩展的解决方案来解决普遍的能源获取难题。能源获取和数据之间存在共生关系;毕竟,在我们以移动为先的环境中,当用户因为相关运营成本而无法可靠地充电或使用智能手机时,使用智能手机的机会成本是多少?或者当提供商的服务或产品由于质量或服务水*差而经常无法获得时?由于网络拥塞、错误、故障或彻底崩溃,有多少价值被抹去?这应该被认为是驱动、塑造并时常限制用户行为(和参与)的核心考虑因素,是解锁迅速增长的有洞察力的数据的必要条件。

当我们站在另一场争夺非洲的风口浪尖时,尽管这是一场技术驱动的新殖民主义,但这种交付基础设施(及其支持的数据增长*台)的局限性必须作为战略要务(从一开始)纳入颠覆性的商业计划和模式。这种合并是必要的,既要对价值创造和交换网络进行证券化和交叉补贴,我们需要在成功规划我们的谈判僵局时采用这种网络。

换句话说,我们必须在相应的价值网络(参考框架)中准确描述相关(直接和间接)利益相关者,以便进行适当的交换,及时在市场上交付(和维持)我们的解决方案。这其中的一个关键部分围绕着(不太明显)直接和辅助的软硬件(read smart)基础设施。例如,转述一下我们的祖先,因为很明显电信公司头上顶着一头大象,我们不能指望他们用脚去寻找蚂蚁。创新必须来自当前“利益相关者”矩阵之外,这就是我们颠覆的机会。

从这个意义上说,借用我上一篇关于开源软件、商品化(嵌入式)计算硬件和日益减少的可再生能源三连胜所释放的创新的数量、速度和价值的文章,我们必须创造新的*台来帮助我们抵御随之而来的冲击。我们必须交付价值,在革命完全成熟之前,尽快将尽可能多的用户和客户带入我们的利基市场。因为如果我们成功地解放了我们 10 亿多美元的市场,那么当“成为的时候,我们就有机会比 Ojadili 用 10 头灵【1】更有把握地遇到巨人。这尤其是因为非洲当前数据驱动的殖民扩张的影响,这种扩张正被新兴新时代的技术巨头和互联网巨头无情地追求和维持。**

出于我们的目的,数据策略的整合(及其释放或可能释放的价值)跨越 3 个主要领域【2】:

用于业务流程和决策优化的数据(提高生产力和运营效率)

用于产品/服务增强或创造的数据(提高满意度、保留率和终身价值)

销售或转售给新市场或客户的数据(对第三方,如广告商、顾问等的分析)。)

因此,当我们计划和发展我们的事业时,这个数据三位一体的圣杯必然会告知我们对我们所确定的利基中的价值(及其交换)的评估。这是因为至少,它们提供了新的方法和手段来提供基础的软件和硬件基础设施,以及增强我们当地环境所需的各种产品和服务。

顺便说一句,从 20 世纪 90 年代的互联网繁荣开始,席卷全球的互联网革命(部分)是以一种古老的商业模式为前提的,这种模式整合了数据的聚合、挖掘和分析,仍然在以谷歌、脸书、亚马逊等公司集体价值的货币化为基调。在此之前,报纸、广播和电视都是以相同的多面*台模式为前提的。事实上,像雅虎这样的前巨头已经消失了,这只是一个先行者未能认识到技术时代的流沙的作用;对自己的企业家也是一个警示。

在非洲,即使像我提到的那样降低了技术构建模块的成本,但现实是有限的人均购买力和其他大众市场规模扭曲抑制了向金字塔底层(BOP)用户提供大多数产品和服务,而这些用户正是随后的冲击的目标。尽管围绕互联网供电产品的接入、覆盖和服务进行了各种调整和创新,但仍有很大一部分眼球和思想份额在今天的非洲没有得到服务。赢得并保持这些大众所代表的数据矿脉的最终责任,是我们必须为自己设定的任务。

最终,非洲真正的购买力和价值的表面被锁定在未实现的潜在消费者身上,他们在我们关注的数字利基和领域中的直接和间接活动,可以在我们的形象和相似性中催生一个重新构建的新时代的曙光。我们可以直面数据驱动的革命,在公*价值交换的谈判僵局中。如果我们失败了,墙上那面镜子中最美丽的人将会以征服者的方式出现;我们都知道这个故事的结局。

所以,是的;这场革命不会被电视转播。因为它将从数以亿计像素有限的迷你屏幕上直播(我们希望如此),我们可以让这些屏幕点击它们的方式,从无能和服务不足的低迷状态中,到我们的数据 Eldorado。但话说回来,也许我错了。也许我的视力僵化了。然而,我们想打赌吗?如果——在我所有迷惑的*似中——如果我是对的呢?

乌切·奥努拉

联合创始人/首席宣传员——HITCH(由 Flexfinity 负责)

【网页:】【www.tryhitch.com】

推特:@HITCHStream

脸书:/HITCHStream

https://books.google.de/books?id=0WKFCwAAQBAJ&lpg = PA40&ots = pz 65 sb 8 bxz&dq = oja Dili&pg = PA43 # v = one page&q = oja Dili&f = false

【2】http://Sloan review . MIT . edu/article/how-to-money-your-data/

Jupyter 笔记本的版本控制

原文:https://towardsdatascience.com/version-control-for-jupyter-notebook-3e6cef13392d?source=collection_archive---------1-----------------------

Credit

Jonathan Whitmore 的 Jupyter 笔记本数据科学最佳实践非常有用,我一直强烈鼓励团队成员至少采用其中的一部分,特别是 post-save 挂钩和笔记本命名约定。

[## Jupyter 项目

Jupyter 笔记本是一个基于网络的交互式计算*台。该笔记本结合了现场代码,方程式…

jupyter.org](http://jupyter.org/)

保存后挂钩

这样做的目的是在保存笔记本时自动保存一份 Python 脚本和 HTML 格式的副本。

我曾经在提交到版本控制之前清除笔记本中的所有输出,以使变更历史更加清晰,但是这产生了两个问题:

  1. 如果笔记本的数据处理部分需要 10 分钟以上的时间来运行,这将会产生一种强烈的激励,让审查者跳过实际运行笔记本,而只是通读代码,并假设它做了它看起来要做的事情。这是假设训练好的模型以某种方式被序列化以供审阅者加载,否则可能需要花费数小时在审阅者的系统上训练。预训练模型的分布带来了下一个问题:
  2. 没有简单的方法将数据和模型文件与笔记本一起分发。对于数据科学家来说,存储和传输千兆字节的数据不是那么容易的,而让数据工程师专门为此在内部构建一些东西可能不划算。对于“大数据”场景,您不希望将 Spark 访问凭据保存在笔记本电脑中(非常危险),因此您需要找到一些安全管理集群访问的方法。(有一个叫做数据版本控制的新框架,看起来很有前途。但你需要向谷歌或亚马逊支付云存储费用。)

总而言之,解决这些问题最直接的方法就是只需将笔记本的输出纳入版本控制。(尽管我建议在提交之前重启内核并重新运行整个笔记本。)

将笔记本转换为 Python 脚本和 HTML 文件。在评审过程中使用 Python 脚本进行代码差异。HTML 文件最适合作为跨团队沟通电子邮件的附件。(就我个人而言,只有当项目的积极参与者没有真正使用 Jupyter 时,我才会将 HTML 文件添加到版本控制中。)

以下要点基本上是从 Jupyter 笔记本数据科学最佳实践中直接复制的。它是根据最新的 Jupyter 测试的,放在这里供快速参考:

使用上述脚本有两种方式:

  1. 放在~/.jupyter/jupyter_notebook_config.py的顶部。(如果还没有,运行jupyter notebook --generate-config创建它)
  2. 如果你想要不同项目的不同配置,使用export JUPYTER_CONFIG_DIR=~/.jupyter_profile2来指定配置文件夹。
  3. 将其作为jupyter_notebook_config.py放在项目文件夹的根目录下(在那里运行jupyter notebook命令)。

还有呢!

如果使用得当,Jupyter notebook 可以成为一个非常有效的工具,提高团队协作的效率。请查看 Jupyter 笔记本数据科学最佳实践了解更多信息。

[## Jupyter 笔记本电脑数据科学最佳实践-硅谷数据科学

Jupyter 笔记本是一个神奇的工具,可以用在许多不同的方面。因为它的灵活性,工作…

svds.com](https://svds.com/jupyter-notebook-best-practices-for-data-science/)

20190313 更新

Github 上有一个新工具可以直接区分 Jupyter 笔记本:

[## 点评 nb:GitHub 的 Jupyter 笔记本差异

Jupyter 笔记本的 HTML 渲染差异。告别凌乱的 JSON diff。通过审阅评论在笔记本上协作…

www.reviewnb.com](https://www.reviewnb.com/)

我还没有找到时间真正尝试它,但我听说过它的好处:

Jupyter 笔记本的 Git 版本控制

原文:https://towardsdatascience.com/version-control-with-jupyter-notebooks-f096f4d7035a?source=collection_archive---------4-----------------------

Don’t loose your version control history.

版本控制是数据科学工作流的重要组成部分。在多个实验之间,了解哪个团队成员做了哪些更改和哪些更新是非常重要的。不幸的是,默认的 jupyter 设置在这方面严重不足。

Jupyter 笔记本是以Json格式存储的,因此很难看出笔记本上的差异,也很难在团队层面上进行代码审查。为了解决这个问题,我们将以.ipynb.Rmd (r-markdown 格式)存储笔记本。这将使我们能够做差异以及合并,因为.Rmd只是一个文本文件。

介绍 R-Markdown 及其优于普通 Markdown 的优势

R-Markdown 与 Markdown 格式相同,但有一个额外的优势,即您可以从它制作值得发布的 pdf/word-doc(和其他格式)。因此,如果你的笔记本存储为.Rmd格式,你不仅可以控制它,还可以将其转换为纸质出版格式。

更多关于 R-Markdown 的信息可以在这里找到。此外,如果您打算使用 R-Markdown 编写一本书,请检查 R bookdown 包。它允许你用 markdown+code+outputs 写一本书。

以多种格式保存的方法

  • 小钩和大钩
  • Jupytext 并另存为.Rmd

尽管第一种方法更容易设置,为什么我们选择 Jupytext?

第一种方法只是将它保存为代码,而 Jupytext 将其保存为 readme,因此它在 github 中可以很好地呈现,并保持文档完整。

安装和设置 Jupytext

您需要在将 git repo 用于笔记本的所有系统上执行此操作。这意味着你所有的队友都必须配置 jupytext。

我们使用 Jupytext 库(https://github.com/mwouts/jupytext)

pip install jupytext --upgrade
  • 接下来用jupyter notebook --generate-config生成一个 Jupyter 配置,如果你还没有的话
  • 编辑.jupyter/jupyter_notebook_config.py并添加以下内容:
c.NotebookApp.contents_manager_class="jupytext.TextFileContentsManager"
c.ContentsManager.default_jupytext_formats = ".ipynb,.Rmd"
  • 并重启 Jupyter,即运行
jupyter notebook

: .jupyter大多出现在你的主目录里。

  • 打开现有笔记本或创建新笔记本。
  • 禁用 Jupyter 的自动保存以进行往返编辑,只需在顶部单元格中添加以下内容并执行。
%autosave 0
  • 您可以在 Jupyter 和文本编辑器中编辑.Rmd文件,这可以用于检查版本控制更改。

可能的 Git 工作流(2 种方式)

1.仅保存 Rmd 文件

我们将删除.ipynb文件并对.Rmd文件做一个小的修改。

ipynb文件的所有输出都在它们的 json 源中,因此当这些输出存储在源代码管理中时,即使实际变化很小,也会在 diff 中增加巨大的变化。此外,他们有所有的图像/情节编码为字符串,所以它是沉重的源代码控制。因此,您只需要将 Rmd 文件签入源代码控制中。

要在你的.gitignore文件中做到这一点,在新的一行中添加下面一行。

*.ipynb

注意:你的所有队友也需要这样做,这样他们才不会将ipynb文件提交到 git 中。

如果您已经签入了ipynb文件,那么在签入.Rmd文件后,从源代码管理中删除它们。从 gitrepo 而不是本地目录中删除文件(请参阅此处的)

git rm --cached file1.ipynb
git commit -m "remove file1.ipynb"

接下来我们对.Rmd文件做一个小的修改。

  • 打开vi中的.Rmd文件
  • 在以jupytext_formats: ...开头的行,修改为:
jupytext_formats: ipynb,Rmd:rmarkdown
  • 保存文件并退出vi

注意:第一次创建.Rmd文件并推送至 git remote 时,对该文件的修改只需要一次。

克隆回购并创建笔记本

一旦您删除了ipynb笔记本,当您克隆回购时,您就要创建笔记本。让我们看看怎么做。

  • 从文件浏览器打开 jupyter 中的.Rmd文件。
  • 您可以直接使用.Rmd文件,但是它不会在会话之间保持输出,所以我们将创建一个 jupyter 笔记本。
  • 点击File->Save (Cmd/Ctrl+S)。
  • 关闭.Rmd文件(*File->Close and Halt*)
  • 现在打开 Jupyter 的ipynb
  • 开始编辑和保存。您的.Rmd文件将不断更新。

2.保存 Rmd 和 Ipynb 文件

不要将.ipynb添加到您的.gitignore中。

.Rmd文件做一个小改动。

  • vi中打开.Rmd文件
  • 在以jupytext_formats: ...开头的行上,将其改为:
jupytext_formats: ipynb,Rmd:rmarkdown
  • 保存文件并退出vi

注意:.Rmd文件的更改只需要在您创建它并第一次将其推送到 git remote 时进行一次。

在此工作流程中,由于您保存了这两个文件,因此在克隆时不需要做任何额外的工作,因此.ipynb已经可用,因此只需在克隆回购后开始使用它。

记得将 %autosave 0放入笔记本的第一个单元格,并一直运行它。因为你已经禁用了自动保存,所以记得经常保存你的笔记本。

更新

  • 也可以只使用.Rmd格式。基本上不用.ipynb.Rmd。将.Rmd签入 git 进行版本控制。这样做的缺点是,当你登录 git 时,你的图/结果等将被删除,因为.Rmd是纯文本格式。任何下载你的笔记本的人都必须运行代码才能看到图形/结果。

参考

[## mwouts/jupytext

Jupyter 笔记本作为 Markdown 文档,Julia,Python 或 R 脚本

github.com](https://github.com/mwouts/jupytext) [## Jupyter 笔记本的版本控制

Jonathan Whitmore 撰写的 Jupyter 笔记本数据科学最佳实践非常有用,我一直…

towardsdatascience.com](/version-control-for-jupyter-notebook-3e6cef13392d)

非常简单的 Python 脚本,用于从故事中提取最常见的单词

原文:https://towardsdatascience.com/very-simple-python-script-for-extracting-most-common-words-from-a-story-1e3570d0b9d0?source=collection_archive---------1-----------------------

简单的 Python 脚本,不使用繁重的文本处理库,从语料库中提取最常见的单词。

莎士比亚戏剧中使用最多的词是什么?“king”比“Lord”用得多,还是反之亦然?

为了回答这类有趣的问题,人们通常需要快速检查和绘制文本文件中最常见的单词(通常从开源门户网站下载,如古腾堡项目)。然而,如果你在网上或 Stackoverflow 上搜索,你很可能会看到【nltk】计数矢量器 的使用的例子。虽然它们非常强大,使用起来也很有趣,但事实是,如果您只想提取单个文本语料库中出现的最常见的单词,就不需要它们。

下面,我将展示一个非常简单的 Python 3 代码片段来实现这一点——只使用了一个字典和简单的字符串操作方法。

请随意复制代码,并使用您自己的停用词来使它变得更好!

import collections
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline# Read input file, note the encoding is specified here 
# It may be different in your text file
file = open('PrideandPrejudice.txt', encoding="utf8")
a= file.read()# Stopwords
stopwords = set(line.strip() for line in open('stopwords.txt'))
stopwords = stopwords.union(set(['mr','mrs','one','two','said']))# Instantiate a dictionary, and for every word in the file, 
# Add to the dictionary if it doesn't exist. If it does, increase the count.
wordcount = {}# To eliminate duplicates, remember to split by punctuation, and use case demiliters.
for word in a.lower().split():
    word = word.replace(".","")
    word = word.replace(",","")
    word = word.replace(":","")
    word = word.replace("\"","")
    word = word.replace("!","")
    word = word.replace("“","")
    word = word.replace("‘","")
    word = word.replace("*","")
    if word not in stopwords:
        if word not in wordcount:
            wordcount[word] = 1
        else:
            wordcount[word] += 1# Print most common word
n_print = int(input("How many most common words to print: "))
print("\nOK. The {} most common words are as follows\n".format(n_print))
word_counter = collections.Counter(wordcount)
for word, count in word_counter.most_common(n_print):
    print(word, ": ", count)# Close the file
file.close()# Create a data frame of the most common words 
# Draw a bar chart
lst = word_counter.most_common(n_print)
df = pd.DataFrame(lst, columns = ['Word', 'Count'])
df.plot.bar(x='Word',y='Count')

语料库中 10 个最常用单词的代码输出和绘图示例。正文是' 《傲慢与偏见》 '而且可以看到大家熟悉的伊丽莎白和达西先生的名字!😃

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

[## 通过我的推荐链接加入 Medium—Tirthajyoti Sarkar

作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…

medium.com](https://medium.com/@tirthajyoti/membership)

Jupyter 笔记本中的视频流

原文:https://towardsdatascience.com/video-streaming-in-the-jupyter-notebook-635bc5809e85?source=collection_archive---------6-----------------------

ipywidgets 在 Jupyter 生态系统中起着至关重要的作用;它带来了用户和数据之间的交互性。

小部件是多事件的 Python 对象,通常在 Jupyter 记事本或 JupyterLab 中有一个可视化的表示:一个按钮、一个滑块、一个文本输入、一个复选框…

The user can get access and set the value of the slider writing Python code, and of course, interact with it using the mouse

表示小部件的 Python 对象在服务器端(后端)是活动的,在 Python 内核(负责执行 Jupyter 笔记本中的代码的部分)内部。Python 对象包含关于微件状态的所有信息。在 滑块 小部件的情况下,Python 对象包含滑块的最小值、最大值和当前值。这个 Python 对象(在后端,服务器端)与小部件的 Javascript 模型(在前端,客户端)同步,后者包含关于小部件的相同信息。每次用户在笔记本中显示小部件时,它都会创建一个与 Javascript 模型保持同步的视图。在 滑块 示例上,可以看到两个视图是同步的。

不仅仅是一个交互式小部件库,ipywidgets是一个强大的框架,基于它可以直接创建新的定制小部件。开发人员可以使用widget-cookiecutter项目,用代码结构和打包的最佳实践快速启动他们的 widget 库。****

已经创建了许多不同的小部件库。您可以使用 mybinder 在线试用它们,无需安装任何东西!:

  • bq plot:二维交互数据( 绑定链接 )
  • ipyleaflet: 互动地图( 活页夹链接 )
  • python reejs:交互式三维场景( 活页夹链接 )
  • ipyvolume: 三维交互式数据可视化和多体绘制( binder link )
  • nglview: 三维交互式分子可视化( binder link )
  • gmaps:Google-maps 上的数据可视化
  • itk-jupyter-widgets:交互式二维和三维数据可视化( 活页夹链接 )

自从ipywidgets7.4 以来,我们有了两个新的小部件:音频和视频小部件,这使得在 Jupyter 笔记本和 Jupyterlab 中进行图像/音频处理变得很容易。****

图片 小部件一样,新的 音频视频 小部件在后端和前端之间同步二进制数据。您可以使用自己喜欢的库(OpenCV、sci kit-image……)轻松操作这些数据,并动态更新小部件值。

Edge detection using OpenCV on a Video widget

这两个小部件是创建 ipywebrtc 库的很好的构件。 ipywebrtc 已由 马腾 创作(马腾是牛逼库 vaexipyvolume 的作者)。它使用 WebRTC 浏览器 API 的强大功能来允许 Jupyter 笔记本内部的视频流。

ipywebrtc的 API 非常简单:首先,用户会创建一个我们称之为 MediaStream 的小部件。一个 媒体流 小部件可以是:****

  • 一个 WidgetStream 小部件,给定任何输入小部件
  • 一个 VideoStream 小部件,给定一个 Video 小部件作为输入
  • 一个 ImageStream 小部件,给定一个 Image 小部件作为输入
  • 一个 音频流 小部件,给定一个 音频 小部件作为输入
  • 一个 CameraStream 小部件,它根据用户的网络摄像头创建视频/音频流

使用 MediaStream 小部件,您可以:

  • 使用 录像机 小工具录制电影
  • 使用image recorder小工具拍摄快照******
  • 使用 录音机 小工具录制音频
  • 使用简单的 聊天 功能将其传输给同伴

至于其他的 widget 库,现在只要点击 这个链接 就可以现场试用了。你将能够尝试所有这些工作流程。

比方说,你想使用连接到电脑的摄像头动态执行图像处理,并运行人脸识别、边缘检测或任何其他复杂的算法。使用 ipywebrtc 真的很容易实现。您需要做的就是创建一个 CameraStream 小部件的实例,创建一个image recorder给定相机视频流作为输入,并实现处理图像的回调(例如使用 scikit-image)。******

Creation of an ImageRecorder taking snapshots of the CameraStream, and process images on the fly using scikit-image

ipywebrtc的另一个很好的特性是能够从任何小部件创建 MediaStream 小部件。这意味着您可以轻松地从您喜欢的小部件库中记录图像和视频,以进行二维或三维数据可视化(此处为 ipyvolume )。****

Create a WidgetStream with an ipyvolume widget as input and record a video using the VideoRecorder

一旦你使用了库的这些好特性,你就可以下载你创建的视频/图片了。或者,您可以使用 聊天 功能直接分享。该功能将聊天室名称和您想要共享的流(默认为 CameraStream )作为输入,并允许您将您的 Jupyter 笔记本变成会议室!

Chatroom created live with ipywebrtc during a presentation at PyParis

你可以在 Github 上找到用来制作那些图片的例子:https://Github . com/quant stack/quant stack-talks/tree/master/2018-11-14-py Paris-widgets/notebooks

关于作者

我叫马丁·雷诺,我是 QuantStack 的科学软件工程师。在加入 QuantStack 之前,我就读于 SUPAERO 。我还在巴黎的 Logilab 和剑桥的 Enthought 工作过。作为 QuantStack 的开源开发人员,我参与了各种项目,从 C++的 xsimd 和 xtensor 到 Python 和 Javascript 的 ipyleaflet 和 ipywebrtc 。

VideoFi —简化视频注释和见解查找

原文:https://towardsdatascience.com/videofi-annotating-videos-and-finding-insights-simplified-6c939c83b74c?source=collection_archive---------6-----------------------

看视频很好玩,但是尝试手动分析视频,就没那么好玩了!你可能会错过重要的细节,这是非常耗时的。如果这个过程可以自动化呢?它肯定能让少数人的生活更轻松。

能够在传媒公司工作,一切都围绕着视频。这就像宝藏一样,当我们试图涉足最新的流行词——人工智能时,分析视频是我和我的团队想到的最有用的用例之一。

先决条件

为了分析视频,我们必须采取的第一步是将视频转换成一系列图像。我们用 python 写了代码,用了一个叫做 ffmpeg 的工具。在为 python 安装了 ffmpeg 库之后,我们以每秒 10 帧的速度从视频中提取图像。图像的名称反映了图像帧出现在视频中的时间。有了这个,我们就知道图像在视频中的位置。

可以在 github 这里找到将视频转换为一系列图像的代码。

我们想找的东西

当时,我们一直在使用 AWS API 构建 ML 模型,并认为尝试他们最*的人工智能服务( Amazon Rekognition )—对象检测 API (现在,对象和场景检测)和名人识别 API 是一个好主意。

所以实际上,我们的目的是通过找到视频中的物品和名人的标签来发现视频中正在发生的事情。

拼接零件

这是我们用来完成使命的架构图:

VideoFi Architecture

我们将提取的图像上传到 AWS s3 存储桶中。我们通过 Rekognition APIs 发送对每个图像的请求,并收到对每个图像的响应。然后我们过滤数据并使用我们需要的参数。让我进一步解释一下。

名人识别一个图像的请求看起来像这样,其中每个图像被下载到本地机器上并被转换成字节:

client.recognize_celebrities(Image={'Bytes': imgBytes,})

对象检测 API 也有类似的请求。

API 以下列格式返回响应:

{
    "CelebrityFaces": [
        {
            "Face": {
                "BoundingBox": {
                    "Height": 0.6766666769981384,
                    "Left": 0.273333340883255,
                    "Top": 0.09833333641290665,
                    "Width": 0.4511111080646515
                },
                "Confidence": 99.9476089477539,
                "Landmarks": [
                ],
                "Pose": {
                },
                "Quality": {
                    "Brightness": 56.59690475463867,
                    "Sharpness": 99.9945297241211
                }
            },
            "Id": "1SK7cR8M",
            **"MatchConfidence": 100**,
            **"Name": "Jeff Bezos"**,
            "Urls": [
                "[www.imdb.com/name/nm1757263](http://www.imdb.com/name/nm1757263)"
            ]
        }
    ],
    "UnrecognizedFaces": []
}

我们用来构建数据库的参数以粗体 (匹配置信度和名称)突出显示。另一个重要的参数是边框,它可以用来在名人的脸周围画框,但是我们没有画那么多。

来自标签检测 API 的响应更简单:

{
    "Labels": [
        {
            "Confidence": 99.25341796875,
            "Name": "Skateboard"
        },
        {
            "Confidence": 99.25341796875,
            "Name": "Sport"
        },
        {
            "Confidence": 99.24723052978516,
            "Name": "People"
        },
],
}

我们在这里使用了两个参数(置信度和名称)。

For all you DiCaprio fans — AWS Celebrity Recognition found him!

构建数据库

得到响应后,我们构建了两个独立的表——一个用于名人,另一个用于物品。我们将每个图像的标签和置信度与图像名称、视频名称以及它们在视频中出现的时间戳粘贴在一起。随着我们收到更多的响应,我们不断地向表中添加行。为此,我们使用了 AWS 提供的 RDS DB。

上面讨论的过程的代码可以在这里找到。

我们使用 AWS batch 进行伸缩,以便可以同时运行多个流程。

带有完整管道的 github repo 可以在这里找到。

结果

事实证明,AWS 的对象检测和名人识别 API 的工作相当不错。它非常擅长探测物体,虽然它不能识别每个名人,但它能识别很多名人!

我们在这里学到的一点是,每秒的帧数很重要——每秒 2 或 3 帧无法捕捉到 10 帧所能捕捉到的信息。这是一个完美的数字——既不太高也不太低,给出了我们想要的结果。但是,作为一个起点,使用更少的帧数将是一件好事,因为调用 API 的次数会很少,并且可能会低于 AWS 提供的免费 API 调用限制。

此外,API 返回结果的可信度也起着重要作用——它检测到了许多对象和名人,但它对此并不十分有信心,因此我们以 80%的可信度过滤结果,在应用该过滤器后,结果非常准确。

这是我们项目最终结果的一个简短演示——名人的名字在左上角,物品和标签在视频的正下方。尽情享受吧!

VideoFi in Action

限制

没有什么是完美的,我们的项目和结果也是如此。虽然我们使用的 API 训练有素,但我们缺少的一项能力是——能够用我们想要预测的数据类型(例如 NBA 球员)来训练 API。希望 AWS 在听!😃

结论

这个原型的目的是展示人工智能和机器学习是如何变得如此容易,以至于任何想要解决其用例的人都可以用更少的复杂性和少量代码来完成。不仅仅是 AWS,还有其他云*台,比如 Google Cloud,Azure,IBM 等等。提供类似的服务。

我希望你喜欢这篇文章,并用它来解决至少一个你的 AI 用例。

最后但同样重要的是,我要感谢我的团队成员乔希·库尔茨和瓦伦·沃赫拉,他们是这个项目不可或缺的一部分。

如果您有任何问题或建议,请随时通过 LinkedIn 联系我们,地址是 Shivangi Shroff 和 Varun Vohra 。我们非常乐意与您联系并获得反馈。

“懒惰”人的虚拟环境,或自动环境魔术。

原文:https://towardsdatascience.com/virtual-environment-for-the-lazy-people-or-automatic-environment-magic-ee5c94bb53d9?source=collection_archive---------6-----------------------

当您努力开发或部署大量不同的 python 项目时,您通常会使用一个 virtualenv 来分离和隔离 Python 环境。这绝对是一个好的实践,不仅对于开发人员,而且对于在生产环境中进行部署的人员也是如此。隔离环境使您的系统保持安全和清晰,也给了您很大的灵活性。

但是,当您更改目录时,经常会忘记激活所需的虚拟环境,或者当您离开时,又忘记禁用它。我发现自己经常这样做,所以我开始思考如何让这个例行程序自动化。嗯,我不是唯一一个有这种想法的人,善良的人们已经采取了必要的措施来解决这个问题。

我想向您介绍几个实用程序,它们可以让您更轻松地配置和自动更改每个目录的不同环境。这个实用程序像标准 bash cd 命令的包装器一样工作。每次当你“光盘”在一些目录,其中包含一些具体的。env 文件,它们为您激活先前配置的环境。还有,你出门的时候,他们会自动停用。还不错。

经过一番搜索,我停在了两个最有趣的项目上, DirenvAutoenv 。你可以选择任何一个,但我更喜欢 Direnv,因为它是一个编译程序,所以我希望它能快一点。

Direnv 易于安装,因为它像一个包一样出现在最流行“apt”和“yum”发行版中,你也可以从源代码安装它几秒钟。

安装 direnv 后,您需要在~/中添加一个字符串。bashrc 文件:

eval "$(direnv hook bash)"

我们已经准备好了一些例子:

$ mkdir /home/projects && cd /home/projects 
$ mkdir project1 project2

然后我们需要在两个目录中创建一个. envrc 文件,在 direnv 在目录中找到这个文件后,它将准备/启用新的环境并导出所有列出的本地变量。

出于检查的原因,我们将为每个项目目录声明不同的 python 版本。

$ echo "layout python" > project1/.envrc
$ echo "layout python3" > project2/.envrc

出于安全原因,您需要批准新的或更改的。envrc 文件首先,direnv 会要求您确认。

$ cd project1/ 
direnv: error .envrc is blocked. Run `direnv allow` to approve its content.$ direnv allowdirenv: loading .envrc 
Running virtualenv with interpreter /usr/bin/python 
New python executable in /home/projects/project1/.direnv/python-2.7.13/bin/python 
Installing setuptools, pkg_resources, pip, wheel...done. 
direnv: export +VIRTUAL_ENV ~PATH

在您批准之后,direnv 将继续创建新的 python 2 环境。让我们对 project2 目录执行相同的步骤。

$ cd .. 
direnv: unloading$ cd project2/ 
direnv: error .envrc is blocked. Run `direnv allow` to approve its content.$ direnv allowdirenv: loading .envrc 
Already using interpreter /usr/bin/python3 
Using base prefix '/usr' 
New python executable in /home/projects/project2/.direnv/python-3.5.3/bin/python3 
Also creating executable in /home/projects/project2/.direnv/python-3.5.3/bin/python 
Installing setuptools, pkg_resources, pip, wheel...direnv: ([direnv export bash]) is taking a while to execute. Use CTRL-C to give up. 
done. 
direnv: export +VIRTUAL_ENV ~PATH

正如你现在看到的,我们得到了 python 3,让我们“cd”到每个目录,并尝试安装不同的包或库。

$ cd project1/ 
direnv: loading .envrc 
direnv: export +VIRTUAL_ENV ~PATH$ pip install ansible skip skip skip... :) Successfully installed MarkupSafe-1.0 PyYAML-3.13 ansible-2.7.1 asn1crypto-0.24.0 bcrypt-3.1.4 cffi-1.11.5 cryptography-2.3.1 enum34-1.1.6 idna-2.7 i
paddress-1.0.22 jinja2-2.10 paramiko-2.4.2 pyasn1-0.4.4 pycparser-2.19 pynacl-1.3.0 six-1.11.0$ ansible --version 
ansible 2.7.1 
  config file = None 
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules'] 
  ansible python module location = /home/projects/project1/.direnv/python-2.7.13/local/lib/python2.7/site-packages/ansible 
  executable location = /home/projects/project1/.direnv/python-2.7.13/bin/ansible 
  python version = 2.7.13 (default, Sep 26 2018, 18:42:22) [GCC 6.3.0 20170516]$ which ansible 
/home/projects/project1/.direnv/python-2.7.13/bin/ansible$ cd ..
direnv: unloading$ ansible  
-bash: ansible: command not found$ cd project1 
direnv: loading .envrc 
direnv: export +VIRTUAL_ENV ~PATH$ ansible
Usage: ansible <host-pattern> [options] 
bla bla bla...

正如你所看到的,我们刚刚在 project1 目录中安装了一个 Ansible,在我们离开这个目录之后,所有的环境都被卸载,所以在 project1 目录之外就没有 Ansible 了。同样,当我们返回时,我们将得到可工作的 Ansible 包。

这真的很方便,当您创建一个专用的 Ansible 部署服务器时,将使用这个 Ansible 安装的人可以直接“cd”到所需的目录来获得工作项目,以及所有导出的本地环境和变量。事实上,你可以在这个服务器上有几个不同的 Ansible 项目,有不同的参数和所有你需要的正确配置的环境,只需“cd”到所需的目录。有用,不是吗?

此外,我们可以在。例如,envrc 文件:

$ echo "export FOO=Hello" >> .envrc  
direnv: error .envrc is blocked. Run `direnv allow` to approve its content. $ direnv allow
direnv: loading .envrc 
direnv: export +FOO +VIRTUAL_ENV ~PATH $ echo $FOO 
Hello

您可以在项目主页上找到关于安装和使用的所有附加信息。希望它对你也很方便有用。

祝你好运。

美德信号还是新闻阅读?参议员在推特上相互追随的原因探究

原文:https://towardsdatascience.com/virtue-signals-or-news-reading-an-exploration-on-why-senators-follow-each-others-on-twitter-f9805ab381c2?source=collection_archive---------5-----------------------

当你上唐纳德·特朗普的推特时,你首先注意到的一件事是他关注的账户很少。截至 2017 年 6 月 13 日,这一数字为 45。新闻 文章的一个号对他关注的账号进行了报道。

所以我就纳闷了,为什么会这样呢?为什么他只关注少数几个 Twitter 账户?但我很快意识到,我真的无法回答这个问题——我不认识唐纳德·特朗普,也不知道他脑子里在想什么。相反,我决定解决一个稍微简单一点的问题:为什么美国参议员在 Twitter 上互相关注?

在 Twitter 上关注某人是一个相对来说没有成本的行为。因此,有人可能会认为这里没有任何有趣的事情发生。然而,当一名参议员(比如说伯尼·桑德斯)追随另一名参议员(比如说苏珊·科林斯)时,两件事情发生了变化。首先,每个人现在都可以观察到一个参议员跟着另一个参议员的事实。也许这可以被认为是这两位参议员喜欢合作的信号。其次,桑德斯参议员的新闻订阅现在将包括柯林斯参议员的活动。这让桑德斯参议员获得了关于柯林斯参议员的有价值的信息

这篇文章探讨的问题是:*均而言,哪种效应占主导地位?参议员们互相跟踪是为了获取信息,还是为了表示合作?请注意,如果参议员相互关注以获取信息,twitter 关注作为合作信号的价值会大幅下降,因为接收的参议员希望他们收到关注,因为其他参议员希望监控他们的 Twitter 内容。

推特网

为了找到这个问题的答案,我需要构建一个数据集,描绘出参议员们在 Twitter 上是如何联系的。我使用 Python 和 Twitter API 来收集这些信息。我稍微清理了一下,然后用 Gephi 绘制出来。由此产生的网络可以在下面看到:

Senate Twitter network: Who follows who in US Senate

我用原力图谱算法创建了这个图像。直观上,彼此连接的节点被拉在一起,而彼此不连接的节点被推开。然后,我把每个参议员的政党作为每个节点的颜色:红色代表共和党,蓝色代表民主党,灰色代表无党派人士。一条蓝线意味着连接来自一个民主党节点。共和党人和无党派人士的红线和灰线相似。最后,节点大小表明他们关注多少参议院账户。

你可以看到民主党人和共和党人在 Twitter 关注方面的明显分歧——大多数人倾向于关注自己党内的人。没有一个参议员会过多地关注另一个政党的 twitter 账户,而不关注自己政党的账户。

此外,两位独立人士:安格斯·金和伯尼·桑德斯的行为相对不同。在这张图表中,桑德斯看起来更像民主党人,而金看起来像中间派。众所周知的两党参议员,如参议员柯林斯,也在中间位置有代表。

乍一看,这看起来很棒。Twitter 网络确实根据党派划分得很好,我们知道两党参议员也位于中心位置。

但是这普遍适用吗?为了检验这个问题,我们需要衡量参议员们是如何合作的。核心假设是这样的:如果*均而言,参议员们相互跟随以表示合作,那么 Twitter 中的网络结构将类似于合作的度量。如果参议员们相互追随以获取新闻,那么 twitter 中的网络结构就不像是合作的尺度。我们对因果关系不感兴趣。

共同赞助法案

合作的好尺度是什么?参议员可以给出的最廉价的合作信号之一是共同提案。法案联合提案只需要你在法案上签字,并没有明确承诺他们会投赞成票,甚至支持该法案。

我使用 python(和 scrapy)访问了国会的网站,收集到目前为止参议院已经审议的所有法案(超过 1200 个法案)的赞助数据。然后我用 Gephi 绘制了这个网络,使用了与 Twitter 网络相同的逻辑:

Senate Co-sponsorship network: Who co-sponsor with who in Senate

关于我是如何生成这个图的,还需要一个额外的说明。你可能会注意到有些箭头比其他的粗。这是因为共同赞助数据的结构方式。用专业术语来说,我们面对的是一个双向网络。两名参议员可能共同发起了多项立法,每个关联的权重就是这些参议员共同发起的立法的总和。

我们注意到一些我们之前看到的相同趋势:我们可以看到共和党和民主党之间的某种分离。伯尼·桑德斯表现得像一个民主党人,安格斯·金是一个中间派,苏珊·科林斯也似乎超越了党派界限(甚至看起来更像一个民主党人而不是共和党人)。)

你还会看到其他动态。麦卡斯基尔在推特上被定位在民主党的中间,但现在是共同赞助网络的中心。我们需要能够更普遍地量化这两种网络结构。

把它们放在一起

我提议的是比较每个网络中特定节点的中心性。图论中的中心性是衡量一个节点有多中心的指标——当你只使用现有的连接时,你可以多容易地到达任何其他节点。有许多中心性度量标准,但是今天,我将集中讨论两个度量标准:中间性和紧密性。

紧密中心性衡量一个节点与其他节点的紧密程度。直观地说,当您可以使用较短的路径到达其他节点时,您的亲密度中心性得分较高。

介数中心性衡量一个节点连接其他节点的位置。直观地说,当你位于大量连接其他节点的路径上时,中间中心性得分就高。

我计算两个网络的接*度和介数,并进行比较。如果它们彼此相关,这将支持我们的假设,即 twitter 关注更多地被用作合作的信号。否则,人们更有可能通过关注 twitter 来获取信息。

我在这里做了一个简单的回归。请注意,我并不特别关心内生性(在某种程度上被解释为“因果关系”,尽管这种解释有点问题),因为我真的只关心 twitter 是否有一些战略方面,我们也可以在参议员如何共同提案法案中看到。此回归的结果如下所示:

重点关注亲密度 _ 共同赞助线。“估计”一栏大致告诉了我 twitter 网络中的亲密度如何跟随共同赞助者网络中的亲密度。这并不重要。让我们来看看中间中心性的结果:

也差远了。从这两张表中我们可以看出,两个网络之间的中心性*均来说并不相似。一般来说,参议员倾向于使用 twitter 作为一种收集信息的方式,而不是信号合作。这是非常整洁的。

警告

不幸的是,这还不是故事的全部。需要讨论一些重要的假设和警告。

假设 1: 共同赞助是没有成本的。我们可以把 twitter 的关注和比尔的共同赞助放在一起的主要原因之一是,我们认为这两者都是免费的。例如,如果共同发起一项法案引入了一笔可观的成本,那么围绕你如何共同发起法案的决定可能与你使用 twitter 表示合作的方式不同。这意味着在 Twitter 上表示的合作可能并不总是转化为这种更昂贵的合作形式。

假设二:党派路线无关紧要。这里的另一个重要假设是,参议员不分党派,都以同样的方式对待彼此。这可能是本分析中使用的最不现实的假设。跟随和你在同一个政党的人的决定和跟随和你在不同政党的人的决定可能看起来不同。例如,两个民主党人之间的 twitter 关注的价值可能非常低,因为由于他们在同一个政党中,他们已经有了强烈的合作信号。另一方面,民主党决定追随共和党可能是一个更强烈的信号。在以后的帖子中,我希望探索这个想法。

假设 3: 议案协办“完成”。本届国会刚刚成立 6 个月。也许以共同提案法案为代表的合作还未能充分展现出来。这可以通过在将来使用一套更全面的立法再次查看这一分析来相对容易地解决。

需要远见

原文:https://towardsdatascience.com/vision-needed-d2b0c7fd2387?source=collection_archive---------1-----------------------

我成功地让一辆汽车自动跟踪了一条轨迹,但是我想不出一个更好的标题来写这篇文章。所以,这里引用一句话来代替!

“那些疯狂到认为自己可以改变世界的人,才是真正改变世界的人。”

―史蒂夫·乔布斯

“Think Different” Original Apple Ad Campaign

嗯,我做到了!我终于完成了 Udacity 自动驾驶汽车 Nanodegree 的第一学期。至少可以说,过去的三个月是一段坎坷的旅程,我已经成功地克服了这段时间所面临的障碍,无论是实际上还是象征性的!

在此期间,我花了很多个通宵,大口大口地喝着红牛和咖啡,试图摄入足够的咖啡因来坚持下去,并通过课程抛给你的各种障碍。我曾多次花数天时间研究一个想法,结果却对结果和进展如此失望,以至于完全放弃了它。后来才意识到我一直都是对的,只是在执行过程中犯了一个小小的错误!

事后看来(*剧透警告),这一切麻烦都是值得的!

以下是我对这门课程的想法…

*** 免责声明 :我希望这篇文章能帮助任何人辩论是否要参加这样的课程!我曾计划在完成每个项目后提供一个深入的回顾,但我的时间管理技能又一次让我失望了。因此,我不会对这些项目进行深入的回顾(我的同行已经广泛地讨论过了),而是描述我到目前为止的经历……

我为什么选择这门课程?

去年毕业后,我完全不知道自己下一步想做什么。我在大学的最后一个学期看着周围的每个人都在找工作或者已经申请了一个特定的硕士项目。我知道我想继续深造,但是我不知道该主修哪个领域,我也不想在一家专门招聘工程毕业生的 IT 公司工作。

所以,我决定休息一下,想清楚自己下一步想追求什么。我一直对数学很有兴趣,这也是我完成工程的原因。在大学期间,我还通过使用 Arduino、Raspberry Pi 和 Lego Mindstorms 等原型*台参与许多迷你项目,对机器人技术有所了解。

因此,我把我的重点放在了机器人技术和人工智能领域。在加入 SDCND 之前,我在 Coursera 上完成了 Magnus Egerstedt 博士的“移动机器人的控制”课程,在 Udacity 上完成了巴斯蒂安·特龙本人的“机器人的人工智能”课程。这两门课都很棒,我建议任何想进入机器人领域的人都去上。

我的本科和移动机器人课程让我对机器人的传统控制系统方法有了深入的了解,但我仍然需要获得人工智能方面的知识,以学习其认知应用。

因此,我报名参加 SDCND 并不是为了进入 ADAS( 高级驾驶辅助系统)行业本身,而是为了参加一个主要涉及人工智能和机器人领域的应用特定课程。

我过去在线学习的经历

我过去参加过在线课程,但从未真正完成过任何课程。起初,兴奋和兴趣总是显而易见的,但很快课程就变得像一个单调的例行公事,从而失去了它的魅力。一旦发生这种情况,这门课程被搁置只是时间问题,会被你的日常活动所掩盖。

这是****进行在线学习的最大弊端。大学教育提供的同龄人和老师之间日常互动的缺乏仍然是激励学生完成手头任务的最大激励因素之一。与同龄人互动产生的恐惧因素是在线课程无法复制的。

我发现 Udacity 最接*于复制这些特征而没有缺点。它肯定还不完美,但它肯定是下一个最好的选择。我将尽我所能在下面阐述我的观点…

无与伦比的学习方式

www.udacity.com/drive

****“明天的工作从这里开始”,这是 Udacity 的使命宣言。他们的目标是通过为每个人提供一个在最受欢迎和要求最高的领域获取知识的机会来实现教育的民主化。

他们的工作直到现在都是不可否认的。在很短的时间内(成立于 2012 年),它们已经成为当今最好的 MOOC 之一,我想就我认为它们与竞争对手的区别提供一点见解。

第一学期概述:

特别是 SDCND,每学期花费 800 美元(卢比。53,000)和三个任期的跨度。术语划分如下:

  • 学期一:计算机视觉和深度学习
  • 术语 2:传感器融合、定位和控制
  • 学期 3:路径规划、浓度和系统

每个学期预定为三个月,可以在更短的时间内完成。学期 1 跨越 5 个核心项目,唯一的重点是在计算机视觉、神经网络和深度学习领域建立一个强大的基础和基础。

以下是关于第一学期核心项目的细节,并附有我尝试的一个片段:

  1. ****车道线检测使用传统的计算机视觉技术(颜色渐变、canny 边缘检测和 hough 变换)

Pipeline Visual

P1 Output Video

****2。基于卷积神经网络模型,使用 Tensorflow 构建一个交通标志分类器,该分类器可以基于使用德国交通标志检测基准(GTSRB)数据集设置的 43 个类别,最终预测交通标志。

P2- Traffic Sign Classifier

****3。自动驾驶汽车(当然是在模拟器上!)使用行为克隆(在馈入我驾驶机器人绕赛道行驶的数据后学习驾驶赛道)和深度学习。

The Simulator

P3 Output Video

****4。高级车道寻找使用高级计算机视觉技术,如梯度和颜色阈值、透视变换和使用直方图的车道寻找。

Pipeline Visualization

P4 Output Video

5。使用 HOG 技术和监督分类算法(我使用支持向量机)在道路上检测车辆

Pipeline Visualization

P5 Output Video

你可以在这里查看所有这些项目的代码。

这些项目需要调整和进一步的修改,重新审视这些项目,没有一个期限悬在你的头上,将有望使世界变得不同。

优势

很明显,读完这些资料后,我非常喜欢 Udacity 和他们的纳米学位学习方式,尤其是他们的 SDCND 项目。因此,总结一下 Udacity 优于大多数竞争对手以及脱颖而出的主要原因:

  • 课程材料: Udacity 投入了大量资源为他们的课程开发高质量的内容,并根据学生的反馈定期更新。为了进一步加强这一点,他们与业内最优秀的人合作,开发获得理想工作所必需的课程材料。提供的课程材料对于完成指定的项目是绰绰有余的。然后提供资源对其进行改进。这提供了一种自由,可以随意摆弄和深入学习刚刚学到的概念。
  • ****导师项目:课程中的每个学生都有一名导师。导师的角色是帮助和指导学生克服他们在学习过程中遇到的任何障碍。导师是学生的直接联系点,每周提供有关他们的进展和面临的困难的最新情况。虽然,导师的表现无疑会因人而异,但与他人分享你的目标和进展的行为会让人感到更有责任感,从而推动他们完成这些目标。
  • ****项目:课程设置中的核心项目确实令人惊叹。它们很实用,有助于简洁地形象化所学的概念,这使得学习困难的话题变得更容易。这些项目组合起来就像一个拼图游戏,每个项目都是为了教授一个特定的方面,所有在第一学期学到的概念在最终项目中完美地结合在一起。
  • ****社区:除此之外,学习这门课程的学生最大的财富是有机会与世界各地志同道合的人交流。Udacity 开发了一个*台,让人们聚集在一起,讨论当今技术世界中最具智慧的话题。由于思维过程因人而异,看到别人对一个概念的理解和他们实现这个概念的想法是令人惊讶的。同样,看到你的同事的工作就像一种催化剂,激励你产生类似的结果,同时也教会你新的概念。

同样值得一提的是…

# Udacity 职业支持:除了课程材料,Udacity 还通过提供课程来帮助学生建立个人档案,从而帮助他们改善职业前景。我必须承认,我没有太注意这些,因为我参加课程的主要目的是进一步学习,而不是特别找工作。乍看之下,它看起来确实很棒,而且我有充分的理由相信它非常有帮助。无论如何,更多信息点击这里。

缺点

虽然到目前为止,我对这门课程给予了高度赞扬,但它也不是没有缺点。

  • ****留学生招聘:这是很多学生心中的一大问号。Udacity 已经与世界上一些最好的公司合作,如 Mercedez、优步、福特、宝马、英伟达等等。很自然,任何想在自动驾驶汽车行业发展的人都不会介意与他们合作。但是作为一个来自次大陆的人,我知道很多在这里参加课程的人对如何进行这种雇佣缺乏透明度感到特别不安,因为涉及到各种麻烦,如签证审批等。
  • 小组项目:我认为 Udacity 应该在他们的纳米学位课程中实施这个项目(至少作为选修项目)。将学生分成小组来完成一个项目将有助于进一步丰富学习体验。小组项目类似于现实生活中很少单独完成的项目。更重要的是,这将有助于培养团队合作、授权、沟通等重要技能。也有助于汇集他们的知识,从而帮助提高。
  • ****请停止填鸭式的喂养:在过去的几年里,自动驾驶汽车行业的受欢迎程度大幅上升。因此,像 SDCND 这样的课程有很大的需求,因为人们希望转向未来有前途的职业道路。这对于整个领域来说是很好的,但是对球场产生了负面影响。预备组的学生被提供了最低限度的必要资料,包括基本概念和完成项目所需的额外阅读材料。但是,随着时间的推移,为了帮助参加课程的学生清除项目,至少可以说这些项目并不简单,Udacity 提供了越来越多的补充材料来帮助学生清除他们面临的障碍。这严重阻碍了学习过程。在这些涉及大量研究的领域,学会学习是至关重要的,因为一切都还没有弄清楚,需要更多的创新和工作。

你认为呢?

在当今资源有限的世界,没有技术创新的全球化是不可持续的。人工智能是未来之路。一个人能叫进来一个妖孽的那一天(也就是如果它能枯萎当前的风暴!)无人驾驶汽车将到达你的住处,带你到达目的地,这并不遥远,希望不会太遥远。

当然,在这一切成为现实之前,有很多事情(至少可以说是轻描淡写)需要解决。但就我个人而言,我已经对这个领域产生了足够的热情,可以继续努力,展望未来。

以下是马丁·福特的畅销书《机器人的崛起:技术和失业未来的威胁》中关于人工智能现状的摘录:

*“特别是,像谷歌、脸书和亚马逊这样的公司的崛起推动了巨大的进步。从未有过如此财力雄厚的公司将人工智能视为其商业模式的绝对核心——也从未有过人工智能研究如此接*如此强大的实体之间的竞争关系。类似的竞争态势正在各国间展开。在威权国家,人工智能对军队、情报机构和监控机构来说正变得不可或缺。事实上,一场全面的人工智能军备竞赛很可能在不久的将来迫在眉睫。”
马丁·福特

硅谷所有领先的科技巨头都对人工智能进行了深入投资,希望实现突破,从而发挥主导作用,创造垄断。

特别看看自动驾驶汽车,深度学习的概念,如神经网络和 ConvNets,已经建立了一段时间,但在该领域没有取得重大进展。这些年来技术的进步,特别是 GPU 的引入,使得硬件最终能够赶上并处理如此大量的数据。

因此,SDC 所谓的领导人都拥有相同的硬件(在某些情况下,不像最*的指控那样同时发生),只是由于他们的软件实现而完全脱颖而出。

由于这一领域的急剧出现和炒作,与人工智能研究携手合作的自动驾驶汽车行业似乎即将取得重大突破!

对于无人驾驶汽车领域的任何人来说,希望未来是令人兴奋的时代,并最终改变好莱坞对该领域的看法……

Total Recall — Johnny Cab!

为什么选择这样的课程?

“数以千计的高技能信息技术岗位的消失,很可能是对知识型就业产生更广泛影响的前兆。”
马丁·福特
机器人的崛起:技术和失业未来的威胁****

我只想说明一点,这不是一门容易的课程,也不适合所有人。它需要对学习的高度承诺以及灵活的时间安排。Udacity 表示,每周 10 小时左右足以完成课程,但这与我花在这上面的时间相差甚远。大多数概念虽然解释得很好,但本质上是非直观的,因此需要更多的研究。

也就是说,随着人工智能和机器学习的接受度越来越高,越来越多的工作岗位招聘不足,并有被自动化的风险。卡尔·纽波特(Cal Newport)在其畅销书《深度工作:分散世界中专注成功的规则》(Deep Work:Rules for Focused Success in a Distracted World)中创造的“新经济”即将出现。这是他的书的节选,内容大致相同…

“在新经济中繁荣有两个核心能力:

1.快速掌握硬东西的能力。

2.就质量和速度而言,有能力以精英水*进行生产。"
――卡尔·纽波特

像 SDCND 这样的课程为世界各地的学生提供了一个在这些领域工作的完美*台,专注于未来最苛刻领域的实践和应用学习。

虽然,它可能还没有一个标准学位的可信度,但在这样的课程上工作证明了个人有努力工作的毅力,更重要的是愿意学习。在这个时代,终身学习是成功的关键。

作为一个非计算机科学背景的人,这门课程是我迄今为止面临的最大的智力挑战。作为回报,它给人工智能领域注入了非常强烈的吸引力,我希望能在其中工作。我们这一代人面临着创造和想象新技术的艰巨挑战,以确保一个更加和*和繁荣的未来。

"教育是点燃火焰,而不是填满容器."
苏格拉底

该表扬就表扬

我要感谢乌达城提供了一个机会,让我了解目前世界上最令人垂涎的领域之一。我特别感谢奥利弗·卡梅伦、瑞安·基南和大卫·西尔弗以及 Udacity 的其他工作人员,他们确保了课程的体验是一流的。

我还想感谢在课程中我有幸与之互动的许多人,我期待着见到更多的人。

现在我们来看几天后开始的第二学期。超级兴奋开始自动驾驶的机器人方面!

参考

****神经网络揭秘:http://www . Welch Labs . com/blog/2015/1/16/Neural-Networks-demystalized-part-1-data-and-architecture(所有 Welch Labs 的视频都值得观看)

P2 深度评论 by 杰伦 (你的文章太神奇了 btw!):https://medium . com/@ jeremyeshannon/uda city-自驾-汽车-纳米度-项目-2-交通-标志-分类器-f52d33d4be9f

****卷积神经网络如何工作作者布兰登·罗尔:【https://www.youtube.com/watch?v=FmpDIaiMIeA】T2&t = 311s

****P3 深度回顾byVivek Yadav:https://chatbotslife . com/learning-human-driving-behavior-using-nvidias-neural-network-model-and-image-augmentation-80399360 efee

****试图通过Param Aggarwal:https://medium . com/computer-car/试图实时可视化卷积神经网络-1edd1f3d6c13

克隆汽车模仿人类驾驶byMohan kart hik:https://medium . com/@ mohankarthik/Cloning-a-car-to-mimic-human-driving-5 C2 f 7 e 8d 8 aff

深度回顾阿莱士:http://navoshta.com/detecting-road-features/****

P5 深度回顾作者 阿纳尔多·冈兹:https://chatbotslife . com/vehicle-detection-and-tracking-using-computer-vision-baea 4 df 65906

查看 聊天机器人生活 更多精彩文章!

麻省理工学院的 SDC 公开课:http://selfdrivingcars.mit.edu

Fast.ai,一个致力于教授深度学习和神经网络的令人惊叹的博客:http://www . fast . ai

你毕业后做什么比你在哪里上学重要得多

如果你喜欢这篇文章,请分享并推荐给任何想参加这类课程的人。谢谢!😃

深度学习中的视觉注意模型

原文:https://towardsdatascience.com/visual-attention-model-in-deep-learning-708813c2912c?source=collection_archive---------1-----------------------

摘要

本练习的主要目的是研究视觉注意模型的发展现状和主要工作。研究了两个数据集:扩展 MNIST 和支持向量回归机。前一个数据集侧重于规范问题——手写数字识别,但具有杂乱和翻译,后一个数据集侧重于现实世界的问题——街景门牌号码(SVHN)转录。在本练习中,我们以培养良好直觉的方式研究了以下论文,以选择合适的模型来应对上述挑战。

对于扩充的 MNIST 数据集:

  • 基线模型基于经典的 2 层 CNN
  • 参考文献[2],目标模型是具有 LSTM 循环注意模型(RAM)

对于 SVHN 数据集:

  • 基线模型基于 11 层 CNN:用卷积网络提取图像特征,然后用多个独立的密集层预测有序序列,参考文献[1]
  • 参考文献[3],目标模型是具有 LSTM 和卷积网络深度循环注意模型(DRAM)

此外:

  • 空间变换网络也作为视觉注意机制的最新发展进行了研究,参见论文[5]

上述两个数据集挑战都集中在数字识别上。在本练习中,MNIST 用于演示一位数识别的解决方案,而 SVHN 用于显示多位数序列识别的结果。

扩充 MNIST 数据集

数据扩充

由于原始 MNIST 数据集是用于说明深度学习的规范数据集,其中简单的多层感知器可以获得非常高的精度,因此原始 MNIST 被增加了额外的噪声和失真,以便使问题更具挑战性,并导致诸如 SVHN 的真实世界问题。

增强后的 MNIST 数据集示例如下所示:

上面的增强 MNIST 数据集杂乱无章,没有中心。增强过程如下:
(1)在 100x100 的画布中随机选择一个位置对原始的 28x28 图像进行*移,生成*移。
(2)通过随机选择一个训练/验证 28x28 图像,然后随机裁剪 8 次 9x9 补丁,然后将所有 8 个裁剪的图像拼接成增强的 100x100 图像,来产生失真噪声

对于经典方法来说,扩充的 MNIST 数据集似乎很难,让我们首先尝试一下。

数据预处理

除了数据扩充之外,每个图像像素值在[0,1]的范围内被归一化。

MNIST 数据集非常*衡。没有应用额外的数据预处理。

基线方法:仅 CNN

基线方法是使用经典卷积模型架构,该架构适用于原始 MNIST 数据集。MLP 没有被用作基线模型,因为它没有表现出经典模型的最佳效果。卷积模型架构取自 keras 示例,该示例声称在原始 MNIST 数据集上达到 99.25%的准确率。

模型架构如下所示:

由于 MNIST 手写数字相对简单,因此只有 2 个卷积层和最大池用于特征减少和空间不变性。退学用于转正。*坦/密集图层用于要素交互。

有 60k MNIST 图像数据,其中 54k 用于训练,6k 用于验证,10k 用于测试。测试数据在最后一步只使用一次。

验证动态如下所示。我们可以看到,验证准确度稳定在大约 50%的准确度。并且最终的一次性测试准确率在 100 个历元时为 50.87% (由于每个训练图像为 100x100,所以在 Tesla K80 GPU 服务器中的总训练时间需要几个小时)。

目标方法:重复注意模型(RAM)

为了更好地解决上述问题,谷歌在 2014 年发布了一个非常简洁和酷的想法,请参考论文[2]。

I 灵感 大意是从人眼的工作原理,即视网膜中获取灵感,如下图所示。我们的眼睛可以捕捉到一个非常广阔的世界,然而,我们倾向于“扫视”全景,只关注视图的特定区域,而其他部分则有点“模糊不清”。

source: https://en.wikipedia.org/wiki/Visual_perception

视觉注意力模型试图利用这一想法,让神经网络能够将其“注意力”集中在图像的有趣部分,在那里它可以获得大部分信息,而在其他地方给予较少的“注意”。

这种方法的优点是:
(1)模型可以更多地关注图像的相关区域
(2)因此降低了所需的图像处理能力
(3)“离焦”模糊区域仍然捕捉到正在发生的事情的一般概念

这种直觉可能有助于我们的增强 MNIST 数据集挑战,其中只有手指周围的图像区域需要更多的关注。

A 架构 整体架构中组件很少。

惊鸿传感器 惊鸿传感器是视网膜的实现,如下图所示:

这个想法是让我们的网络“看一眼”给定位置周围的图像,称为一瞥,然后提取这一瞥并将其调整为不同比例的图像作物,但每个比例都使用相同的分辨率。例如,上述示例中的 glimpse 包含 3 个不同的刻度,每个刻度具有相同的分辨率(也称为传感器带宽),例如 12x12。因此,中间最小比例的作物最清晰,而外环最大的作物最模糊。总之,Glimpse 传感器拍摄全尺寸图像和位置,输出给定位置周围图像的“类似视网膜”的表示。

Glimpse Network
一旦我们定义了 glimpse sensor,Glimpse Network 就是一个简单的环绕 Glimpse Sensor,拍摄全尺寸图像和位置,通过 Glimpse Sensor 提取图像的视网膜表示,展*,然后使用隐藏层和 ReLU 将提取的视网膜表示与 Glimpse 位置组合,发出单个矢量 g。该矢量包含“什么”(我们的视网膜表示)和“哪里”(图像内的聚焦位置)的信息。

递归网络
递归网络从 Glimpse 网络获取特征向量输入,通过其隐藏状态(和记忆单元)记忆有用信息。

位置网络
位置网络将递归网络中的隐藏状态作为输入,并尝试预测下一个要查看的位置。该位置预测将在展开的递归网络中的下一个时间步中成为 Glimpse 网络的输入。位置网络是整个想法中的关键组成部分,因为它直接决定了在下一个时间步骤中要注意的地方。为了最大化这个位置网络的性能,本文引入了一个随机过程(即高斯分布)来产生下一个位置,并使用强化学习技术进行学习。它也被称为“硬”注意,因为这个随机过程是不可微的(与“软”注意相比)。随机性背后的直觉是*衡开发(利用历史预测未来)和探索(尝试前所未有的东西)。请注意,这种随机性使得组件不可微,这将在反向传播期间引发问题。并采用强化梯度策略算法来解决这一问题,具体在强化学习部分讨论。

激活网络
激活网络将递归网络中的隐藏状态作为输入,并尝试预测位数。此外,预测结果用于生成奖励点,奖励点用于训练位置网络(因为随机性使其不可微)。

架构组合
结合以上所述的所有元素,我们就有了下面的网络架构。f_g 是瞥见网络,f_h 是循环网络,f_l 是位置网络,f_a 是激活网络。下图是为说明目的而展开的 2 个时间步长的递归。特别是,时间步数=每张图片的扫视次数

R 强化学习
由于位置网络是不可微的,所以采用强化学习,具体来说就是策略梯度法来训练网络的这一特殊部分。首先让我们看一下强化学习的概述。

概述 强化学习就是试错。强化学习的概述如下图所示。我们有以下组件:

  • 代理人:大脑,也就是我们正在建模的神经网络。
  • 环境:地球,是我们可以与之互动的未知世界。默认情况下,我们对环境一无所知。
  • 相互作用:红色箭头,是代理和环境之间的相互作用。它可以是行动(将改变环境的代理输出)、观察(作为代理行动的结果的环境变化的结果)和奖励(代表代理行动“有多好”的一些标量值)。代理的目标是最大化它收集的报酬。

source: http://www0.cs.ucl.ac.uk/staff/d.silver/web/Teaching.html

强化学习的各种方法取决于我们试图优化的目标,分类如下:

  • 政策:从状态到行动的映射。给定我们所处的位置(即状态),执行哪个操作

  • 价值:评价一个状态有多好。处于某个状态有多好

  • 模型:预测环境会怎样。了解敌人有助于赢得战争。

关于 RL 的更详细和全面的解释可以在这里找到。本文选择政策梯度作为 RL 方法,属于上述第一类。

应用到我们的问题 回到我们的问题,既然我们在用政策梯度来解决我们的问题,那我们就来谈谈“政策”本身。在我们的问题中,“政策”决定了我们如何选择下一个瞥见的地点。我们的答案(即策略)是,通过从参数为μ和σ的高斯分布中抽样,其中μ是均值,σ是标准差。这个高斯分布就是我们的随机过程。在这个实现中,我们将σ固定为网络超参数,只尝试学习μ。

为了说明随机网络的训练过程,下图显示了一个高级概念。蓝色箭头代表向前传球,红色箭头代表向后传球。我们的过程从将输入图像传入我们的网络开始。可微分网络将正常工作(例如 XW + b),表示为机器人头部。然后,随机网络(在我们的情况下是位置网络)将应用随机过程(在我们的情况下是高斯分布)来生成结果(在我们的情况下是下一次扫视位置的预测)。它被表示为抛硬币,以表示一个随机过程。然后由环境评估位置预测(以及使用 glance 的分类结果),现在我们有了开始反向传播的奖励。从概念上讲,通过随机网络的反向传播可以被认为是我们使我们的硬币更偏向于未来会给我们带来更多回报的方向,换句话说,我们学习高斯分布参数。这一步被描绘成一把锤子砸在一枚硬币上,来表示我们想要“锻造”对我们有利的硬币。

那么如何锤我们的硬币呢?我们来看看政策梯度的推导。假设我们有一个函数 f(x ),它可以告诉我们,如果我们有一个样本点 x,我们会得到多少回报,也就是一个得分/回报函数

Source: http://karpathy.github.io/2016/05/31/rl/

上面告诉我们,如果我们有一个样本点 x,为了在下一轮有更高的得分,我们应该“锻造”我们硬币的方式是得分函数的梯度方向(方程的左手边),这与样本点 x 的对数似然最大化的方向相同,具有 f(x)本身的振幅(方程的右手边)。

正式地说,我们“敲打”硬币的方式是增强算法,它代表REwardIncrement =Non negativeFactor timesOffsetRE enforcement timesCcharacter isticEligility(有人非常努力地拼出“增强”…)。原文参见[6]

Source: http://www0.cs.ucl.ac.uk/staff/d.silver/web/Teaching.html

安德烈·卡帕西的博客有一个更好的解释:

A visualization of the score function gradient estimator. Left: A gaussian distribution and a few samples from it (blue dots). On each blue dot we also plot the gradient of the log probability with respect to the gaussian’s mean parameter. The arrow indicates the direction in which the mean of the distribution should be nudged to increase the probability of that sample. Middle: Overlay of some score function giving -1 everywhere except +1 in some small regions (note this can be an arbitrary and not necessarily differentiable scalar-valued function). The arrows are now color coded because due to the multiplication in the update we are going to average up all the green arrows, and the negative of the red arrows. Right: after parameter update, the green arrows and the reversed red arrows nudge us to left and towards the bottom. Samples from this distribution will now have a higher expected score, as desired.

现在我们知道如何计算随机网络的梯度。然而,在实践中,tensorflow 计算图将默认自动计算梯度。因此,为了实现如 REINFORCE 所述的定制梯度更新,有两种方法可以做到:
(1)设置tf.stop_gradient将梯度直接传递到可微分网络,然后使用混合损失函数仅训练可微分网络作为*似。这里的论点是,由于我们固定了高斯分布的 std,并且仅试图“学习”均值作为分布参数,所以锤打硬币本身将大致等同于锤打我们的可微分网络参数,以便从可微分网络发出我们期望的均值。参考本回购和本回购
(2)用优化器构建一个单独的计算图,并使用tf.gradients具体计算所需的梯度 w.r.t 相关参数,然后使用optimizer.apply_gradients仅更新这些参数。参考本回购

Training Methodology
作为上面讨论的实现细节,在本练习中,在实现中使用了混合损耗,方法(1)如上。

R = actual reward, b = score function, b_freeze = tf.stop_gradients(b)

由于 plus gate 在反向传播过程中充当梯度分配器,因此我们仅使用以下 3 个具有相同权重的目标来有效地优化我们的可微分网络:(1)用于预测正确性的交叉熵(2)用于回归最优μ作为随机网络的参数输入的 MLE)用于将分数函数回归到实际回报的分数函数(因此分数函数更准确)。

另一个技巧是蒙特卡罗抽样。由于我们在网络中有随机过程,我们可以复制相同的图像 10 次(由于随机性,这将产生 10 个略有不同的结果),然后将它们*均作为我们对训练和测试的预测。

训练参数如下所示。只比较了两种情况。

培训动态如下所示。上表中的训练时间是使用 Tesla K80 GPU 服务器进行基准测试的。训练准确率(每批*均)稳定在 80%,最终一次测试准确率为 79.68% ,与基准方法 50% 相比有显著提高。

L 仿 本节讨论的 RAM 方法的局限性包括:

(1) Glimpse 传感器使用扁*化+致密层。对于 MNIST 特征可能是足够的,然而,为了适合真实世界的图像,可以使用卷积层

(2)递归网络使用单层 RNN 单元。这个 RNN 细胞应该学习图像特征(为了预测数字标签)和位置特征(为了预测下一个扫视位置)。这种责任混合可能会导致一些内部问题。

(3)在展开 RNN 的初始步骤,位置网络随机选择一个位置聚焦其扫视作为起点。这可以改进为具有“更少的随机”开始。

谷歌在参考文献[3]中发表的后续论文解决了上述所有限制。本文将在下一节中作为处理 SVHN 数据集的目标架构进行讨论。

SVHN 数据集

SVHN 数据集是真实世界的街景门牌号数据集。如下图所示:

source: reference [1] paper

在 SVHN 数据集中,提供了以下信息:
(1)位数的长度
(2)每个位数
(3)位数的最大长度是 5

SVHN 数据集是我们的增强 MNIST 数据集挑战的扩展,从某种意义上说:
(1)图像中有噪声和模糊效果
(2)有数字的转换
(3)在我们的增强 MNIST 数据集中,它是有序的数字序列,而不是单个数字

数据预处理

对于图像,进行以下预处理:

  • 从训练(和测试)数据中获取边界框位置
  • 裁剪边界框的联合,以便将图像缩小到最大
  • 调整到 32x32
  • 转换为灰度
  • 在[0,1]之间归一化

下图显示了一个示例图像:

对于标签,进行以下预处理:

  • 0–9 代表数字,10 代表结束标记(或空标记,如果有多个)
  • 将最大序列长度设置为 5
  • 使用结束/空标记 10 填充
  • 丢弃长度超过 5 位数的数据

例如,上面的图像标签将是:[1, 0, 5, 10, 10]

简介

研究了以下两种方法。

(1)一种“仅 CNN”的方法。主要思想是同时查看多个数字,并且如果该数字丢失,目标是以固定长度的数字顺序用空白填充来“分类”数字序列。这一思想借用了文献[1]中发表的论文。然而,为了快速建立比较基准,实现在一定程度上不同于本文。

(2)一种“RNN + CNN”的深度循环注意模式方法。其主要思想是引入深度视觉注意模型(DRAM ),参考文献[3]以扩展他们先前工作[2]中的循环注意模型(RAM)。其中提出了两层 LSTM 来分离扫视位置预测和图像特征处理。

基线方法:仅 CNN

问题描述 门牌号转写问题有以下几个因素需要我们注意:

  1. 存在多个数字(我们需要识别所有数字)
  2. 所有的数字都是有序的(我们需要识别序列)
  3. 有一个特定长度的数字序列(序列的长度不同)

设 P 表示概率,S 表示输出数字序列,L 表示数字序列的长度,X 表示输入图像数据。我们的目标可以解释为最大化以下内容:

在测试时,我们的预测是上述模型的 argmax:

这个模型包含了上面提到的所有 3 个因素。在本练习中,为了快速形成基线,实施了上述模型的一个小变化,但仍保留了以下 3 个因素:

  1. 长度大于 5 的门牌号将被丢弃
  2. 该模型将 5 个数字按顺序分类,每个数字的范围从 0 到 10。0–9 代表数字,10 代表空白填充。例如,门牌号“258”将导致正确的标签序列[2,5,8,10,10]
  3. 没有使用长度,因为空白填充意味着长度信息

方法 本练习采用的总体思路是在架构上有两个网络:卷积网络和分类网络。

卷积网络用于从馈送图像中提取门牌号数字的特征,然后是分类网络,该分类网络使用 5 个独立的密集层来共同分类 5 个数字的有序序列,其中 0–9 表示数字,10 表示空白填充。

我们期望分类网络通过反向传播来学习数字布局的空间信息,使得每个密集层分别只拾取序列中的一个数字。

网络架构 原论文采用 8 卷积层的网络架构。在本练习中,为了快速形成基线,使用了一个更简单的网络(同时仍保留图层类型),如下所示:

请注意,在分类网络中,5 个独立的密集层负责将现有要素分类为 0-10 类标签,其中 0-9 表示数字标签,10 表示空白填充。

训练方法 本文在 SVHN 数据集上取得了 96.03%的转录准确率,模型性能最好。在本练习中,随着模型、图像预处理和网络架构的变化,准确率达到了 87.64%,参见本文

限制 理想情况下,图像预处理步骤应仅适用于训练数据(例如,裁剪掉边界框的并集),其中保持验证/测试数据不变。然而,在实施中,参考本报告,验证/测试数据也在边界框周围裁剪。原始论文提到在图像预处理阶段首先定位数字周围的包围盒矩形。然而,它没有提到执行这种定位的确切方法。

TODO :或者,仅使用裁剪训练数据执行另一个基准

目标方法:深度循环注意模型(DRAM)

除了以前在循环注意模型(RAM)中的工作,让我们扩展以修复限制并应用于 SVHN 数据集。这个想法被称为深度循环注意模型(DRAM)。

架构 DRAM 的架构与 RAM 类似,除了:

  • 位置网络→发射网络
  • 提出了两层 RNN 单元:专用于预测下一个扫视位置位置 RNN(表示为 r 上标 2),以及专用于预测数字标签的分类 RNN(表示为 r 上标 1)。
  • 引入上下文网络,利用下采样的粗糙图像设置位置 RNN 的隐藏状态。想法是将图像的一般上下文馈送到位置 RNN,以便它生成对聚焦扫视的第一位置的良好猜测(与 RAM 方法中开始的随机位置相比)。

顺序分类 为了扩展 RAM 的思想并申请顺序分类,提出了以下工作。

M onte Carlo 采样 它与 RAM 的想法相同,通过多次复制相同的图像,然后取*均值作为预测(文中提到的取对数*均值给出最佳性能)

C 通过这种方式,网络将更专注于对具有迫*误差的有序序列进行分类。

A 累积奖励 为了简化多对象分类,使用累积奖励,即与正确预测的标签成比例的奖励。

S 序列对数似然 序列对数似然呈现在以下目标函数中:

该目标函数是 MLE,其合并了来自发射网络(与 RAM 中的位置网络相同)的位置概率和来自分类网络(与 RAM 中的动作网络相同)的分类概率。

F 这里的解决方案是采用相同的训练数据,但让网络预测数字的反向序列,然后取*均值作为最终预测。这种方法提高了准确性。

结果 DRAM 在这个练习中没有实现(至少没有成功)。

Accuracy 参考论文,下表报告了 DRAM 在 SVHN 数据集上的准确率:

相对于我们的 11 层 CNN 的基线方法(3.96%的错误率),这不是一个显著的改进(3.9%的错误率)。然而,这种改进更多的是在计算开销上。

C 计算成本 计算成本如下图所示:

正如所观察到的,就所使用的参数数量和浮点操作数量而言,DRAM 明显更好,这是因为它采用了用于视觉注意力的一瞥的想法。

还有一件事:空间变压器网络

我觉得有义务提一下这篇论文(太受欢迎就不提了)。它以一种全新的不同方式解决这个问题。这个想法不是使用“硬”注意力,远离强化学习,而是建立一个完全可区分的“软”注意力模型。详情请参考文献[5]。

直觉是,既然注意力都是关于选择性地裁剪图像的一部分作为“注意力”,为什么不使用仿射变换,它以完全可微分的方式处理裁剪、*移、旋转、(各向同性)缩放和倾斜。神经网络需要做的唯一事情是学习这些仿射变换参数。因此,下图展示了一个很酷的想法。

u 是我们的原始输入图像。它首先被传递到定位网络,定位网络是具有可学习参数θ的仿射变换,例如如下所示。

然后,采样器将对变换图像的输出进行采样,以提供原始输入图像的“校正和调整大小”版本。通常,采样过程是双线性插值,这也是一个可微分的过程,如下所示。

这样,原始图像将被仿射变换(或处理)成校正后的输出图像,如下所示:

这个视频展示了空间转换器的效果,令人印象深刻。

结论

总之,我们已经讨论了以下方法来解决增广的 MNIST 和 SVHN 问题:

对于 MNIST:
(1)使用经典的 2 层 CNN,参考 keras 例子
(2)使用“硬”注意力模型 RAM,参考论文【2】

对于 SVHN:
(1)使用 11 层 CNN,参考文献[1]
(2)使用 DRAM 作为 RAM 的扩展,参考文献[3]

最后但同样重要的是,空间转换网络,作为“软”注意力解决方案

关于数据集

MNIST

原始的 MNIST 数据集可以从这里获得:http://yann.lecun.com/exdb/mnist/

SVHN

谷歌街景门牌号图片(SVHN),可从这里获得:http://ufldl.stanford.edu/housenumbers/

  • 10 类,每个数字一类。数字“1”的标签为 1,“9”的标签为 9,“0”的标签为 10。
  • 73257 位用于训练,26032 位用于测试,以及 531131 个额外的、难度稍低的样本,用作额外的训练数据

参考

[1]使用深度卷积神经网络从街景图像中识别多位数。Ian J. Goodfellow、Yaroslav Bulatov、Julian Ibarz、Sacha Arnoud 和 Vinay Shet (2013 年)。https://arxiv.org/abs/1312.6082

[2]视觉注意的循环模型,沃洛季米尔·姆尼,尼古拉斯·赫斯,亚历克斯·格雷夫斯,科雷·卡武克库奥卢,https://arxiv.org/abs/1406.6247

[3]视觉注意下的多物体识别,吉米·巴,沃洛季米尔·姆尼,柯雷·卡武克库奥格鲁,

[4]用无监督的特征学习读取自然图像中的数字,尤瓦尔·内策尔、王涛、亚当·科茨、亚历山德罗·比萨科、吴波、安德鲁·y·Ng 在 2011 年 NIPS 深度学习和无监督的特征学习研讨会上发表。http://ufldl . Stanford . edu/house numbers/nips 2011 _ house numbers . pdf

[5]空间变换网络,马克斯·贾德伯格,卡伦·西蒙扬,安德鲁·齐塞曼,科雷·卡武科库格卢,https://arxiv.org/abs/1506.02025

[6]联结主义强化学习的简单统计梯度跟踪算法,Williams 等,http://www-anw . cs . umass . edu/~ barto/courses/cs 687/Williams 92 Simple . pdf

[7] Github 回购

可视通信

原文:https://towardsdatascience.com/visual-communication-4f674699cb69?source=collection_archive---------26-----------------------

视觉传达是一个可以在不同领域听到的术语。这也是我们理解数据世界的主要技能。但是它实际上是如何工作的呢?我们生活在信息时代,被成堆的数据所包围,但我们需要翻译这些数据的能力,以便每个人都能理解。当您开始进行更详细的分析时,探索您的数据可以为您节省大量时间。通过图形可视化数据是快速探索和产生未来分析想法的好方法。

探索数据应该是任何分析的第一步,它包括汇总、可视化和对数据集中记录级细节的评估。为此,我将使用开源工具: pythonNumpy (科学计算)、 pandas (数据操作)使 python 可用于数据分析、matplotlib/seaborn(制作图形)。

我们来探究一些实际数据。

https://www . ka ggle . com/Megan risdal/la-county-restaurant-inspections-and-violations/home

这是来自 kaggle 的洛杉矶县餐馆检查和违规数据集。

背景:洛杉矶县的餐馆和市场定期接受卫生法规违规检查。根据卫生部的说法,严重的违规行为会导致食物污染或疾病。一些严重的违规行为,如厨房里的啮齿动物,往往会引起公众的警觉,而一些违规行为,如错误的食物温度或未标记的清洁化学品,最容易开始传播食源性疾病。

在开始之前,最好在头脑中有一些问题和假设。

所以我们有两个文件:inspections.csv 和 violations.csv。

违规:该数据集包含洛杉矶县餐馆和市场的环境卫生违规。洛杉矶县环境卫生部门负责检查所有未合并地区和该县 88 个城市中的 85 个城市的食品违规行为。

检查:该数据集包含洛杉矶县餐馆和市场的环境健康检查结果。

我希望找到最有可能出现严重违规的食品机构,以便首先检查它们,并让关心的人避开它们。为此,我们需要计算完整检查的数量,并探索风险水*。

设置图书馆:

import numpy as np 
import pandas as pd 
import seaborn as sns
import plotly.plotly  as py
import matplotlib.pyplot as plt

要获得数据集的第一个视图,我们可以使用以下 pandas 命令:

  • df.describe()
  • df.head() #显示了几行
  • df.shape()
  • df.columns() #列名
  • df.info() #数据类型

inspections.info() 的输出应该是这样的:

在这里,我们可以看到数据集中有多少行,具有给定的 20 列数据类型的名称,以及关于空值的信息。Inspections.csv 不包含任何空值,这在现实生活中很少见。通常情况下,数据需要一些清理和转换。

正如所定义的,让我们按检验日期探究食品检验的次数。使用来自 inspections.info() 的信息,我们可以看到 activity_date 列的数据类型为“object ”,但是由于我们想要查看时间序列数据,我们需要将其更改为 dateTime。因此,下一步是创建一个数据框架,我们可以在其中计算每天的检查量,并创建一个时间序列数据图。

# groupby activity_day to create new column with the name count
count_ins = inspections.groupby(['activity_date']).size().reset_index(name='count')
x = pd.DataFrame(count_ins['activity_date'])
y = pd.DataFrame(count_ins['count'])# create separate df 
timePlot = pd.concat([x,y], axis=1)# change data type 'object' to 'dateTime'
timePlot.activity_date = pd.to_datetime(timePlot.activity_date)
timePlot.set_index('activity_date', inplace=True)# show the first 10 raws, what we get
timePlot.head(10)

确保在设置数据帧timePlot的索引时包含inplace参数,以便实际修改原始索引并将其设置为'activity_date'

我们还可以找到最小/最大日期,因此我们可以定义执行检查的确切时间段。

inspections.activity_date.max()
'2017-12-29'
inspections.activity_date.min()
'2015-07-01'

现在我们有了一切可以在图中形象化的东西:

timePlot.plot.area(figsize=(20,6), linewidth=5, fontsize=15, stacked=False)
plt.xlabel('Activity Date', fontsize=15)

Number of Food Inspections by Inspection Date

鉴于检查员必须完成大量的检查,发现严重违规行为所花费的时间和精力可能意味着在一些食品企业长期暴露在潜在的疾病和不卫生的条件下。

从这张图表中,你可以立即开始思考一些问题,以便进一步分析:

每个检验员执行多少次检验?一个月中是否有增加或减少检查的时间?

现在只看检查员检查*均值就足够了:

count_id = inspections.groupby(['employee_id']).size().reset_index(name='count')
x = pd.DataFrame(count_id['employee_id'])
y = pd.DataFrame(count_id['count'])
count_id = pd.concat([x,y], axis=1)
count_id['count'].describe()

我们在这里可以看到,有 250 个不同的检查员,他们的“雇员 id”和*均值是:在给定的时间内,每个检查员大约检查 765 次。

我们调查的下一步是找到最严重违规的食品企业,这些企业需要长期特别关注。我们有 18 种不同的风险等级。从下面的柱状图可以看出,最大的群体是餐馆高风险等级。

*# Number of Food Inspections by Risk*sns.set(rc={'figure.figsize':(14.7,8.27)}) # set size for a chartg = sns.countplot(x="pe_description", data=inspections, order = inspections['pe_description'].value_counts().index, palette="Blues_d")
g.set_xticklabels(g.get_xticklabels(),rotation=90)
g.tick_params(labelsize=10)

Number of Food Inspections by Risk (sorted by count):

让我们来定义餐厅(0-30)座位风险高的前 20 家餐厅。

rsk = inspections.loc[inspections['pe_description'] == "RESTAURANT (0-30) SEATS HIGH RISK"]
pd.crosstab(index=rsk['facility_name'], columns='count').sort_values(by=['count'],ascending=False).head(20)

要查看整个高级别风险组,我们需要创建一个新要素,该要素仅包含餐馆和食品市场的风险级别。我们有三组级别:高、中、低。

55.37%的检查是针对高风险餐厅的。

为了得到这个图表,我做了以下工作:

# new feature: risk_level
inspections['risk_level'] = inspections['pe_description'].apply(lambda x: x.split(")")[1])

制作图表:

# replace SEATS with RESTAURANT to make it clearinspections['risk_level'] = inspections['risk_level'].str.replace('SEATS', 'RESTAURANTS')

ax = inspections['risk_level'].value_counts().plot(kind='barh',colormap='Blues_r', figsize=(15,7), fontsize=13);
ax.set_alpha(0.5)
ax.set_title("Risk Level", fontsize=18)
totals = []

*# find the values and append to list*
for i **in** ax.patches:
    totals.append(i.get_width())

*# set individual bar lables using above list*
total = sum(totals)

*# set individual bar lables using above list*
for i **in** ax.patches:
    *# get_width pulls left or right; get_y pushes up or down*
    ax.text(i.get_width()+.3, i.get_y()+.38, \
            str(round((i.get_width()/total)*100, 2))+'%', fontsize=10, color='dimgrey')

*# invert for largest on top* 
ax.invert_yaxis()

在下一个条形图中,我们可以看到检查数量最高的食品企业:

inspections['facility_name'].value_counts().nlargest(20).plot(kind="bar", figsize=(15, 6), fontsize=12, colormap='Blues_r')

The top 20 Food Establishments (sorted by count of inspections)

地铁检查量最高。让我们调查一下风险水*。

subway = inspections.loc[inspections['facility_name'] == 'SUBWAY']
pd.crosstab(index=subway['risk_level'], columns='count').sort_values(by=['count'],ascending=False)

Risk Level for Subway

正如我们所看到的,赛百味只有中度风险。

现在,如何可视化风险级别组和食品机构检查已经足够清楚了。让我们继续讨论健康法规。

我想看到十大违反卫生法规的描述。我们可以在水*视图中使用条形图来查看前 10 个代码描述。为此,我们需要合并两个数据集。

df_merge = inspections.merge(right=violations.reset_index(), how='left', on='serial_number', suffixes=('', '_codes_'))# create a plot using seaborn
sns.set(rc={'figure.figsize':(14.7,10.27)})
top10 = sns.countplot(y="violation_description", data=df_merge, order = df_merge['violation_description'].value_counts().nlargest(10).index, palette="Blues_d")
top10.tick_params(labelsize=20)

排名第一的健康准则是№44 层楼、墙和天花板:正确建造,保持良好的维修和清洁。我想说,这是意料之中的事。

在这篇文章中,我最不想看到的是按邮政编码排列的食品检验数量。

Number of Food Inspections by Zip

结论:

我完成了第一阶段的探索。在对数据集进行简要分析后。我们发现,在洛杉矶县有持续的检查,检查食品企业是否违反卫生法规。不同的违法行为反映了对公众健康和安全的不同程度的风险。从 2015 年 7 月 1 日到 2017 年 12 月 29 日,共进行了 191371 次检查,其中 55.37%为高风险级别。我们还创建了一份清单,列出了检查次数和检查风险水*最高的食品企业。除此之外,我们还有 10 大代码描述和今天遇到它们的概率。

对于探索性数据分析、数据收集和处理,需要记住以下几点:

  • 这可能会占用数据科学家 80%的时间
  • 这是从数据语言到人类语言的转换
  • 这是一种分析数据集以总结其主要特征的方法
  • 它应该为您提供一个新问题列表,以探索您的数据集。

祝你胃口好。😃

卷积神经网络的视觉可解释性

原文:https://towardsdatascience.com/visual-interpretability-for-convolutional-neural-networks-2453856210ce?source=collection_archive---------3-----------------------

通信网中的可视化技术介绍

Photo by Shane Aldendorff on Unsplash

更新:我已经在 PyData meetup 的一次演讲中详细介绍了这篇博文。可以看下面的 YouTube 视频。

在应用程序编程中,我们有调试和错误检查语句,如 print、assert、try-catch 等。但是当涉及到深度神经网络时,调试变得有点棘手。幸运的是,卷积神经网络(ConvNets 或 CNN)具有人类可以视觉解读的输入(图像),因此我们有各种技术来理解它们如何工作,它们学习什么以及它们为什么以给定的方式工作。而对于其他深度神经网络架构,可视化甚至更加困难。尽管如此,可视化神经网络给了我们关于神经网络世界的良好直觉。在这篇文章中,我们将深入研究 convnet,了解图像分类器如何工作,以及当我们将 224x224x3 的图像输入到 conv net 时会发生什么。

具体来说,我们将尝试各种可视化技术来了解:

  1. 每次卷积操作(可视化中间激活)后的输出是什么
  2. 每个过滤器从输入图像中提取什么特征(可视化过滤器/内核)
  3. 如何将每个卷积层的输出追溯到输入图像(使用解卷积网络又名解卷积/转置卷积进行可视化)
  4. 为 convnet 的每个图层在输入图像中可视化感兴趣区域(可视化热图)

“尽管取得了这么多进展,但人工智能领域的几乎所有重要问题似乎都没有答案。许多人甚至还没有被正式问过。”—弗朗索瓦·乔莱

VGG16 卷积神经网络

本文假设读者对 convnets 中的前向传播及其架构组件(如卷积、池和激活函数)有基本的了解。在整篇文章中,我们将使用 VGG16 模型进行可视化。每个可视化的 Jupyter 笔记本都是用 Keras 编写的,可以在我的 GitHub 存储库中找到:

[## himanshurawlani/conv net-可解释性-keras

使用 Keras-himanshurawlani/conv net-可解释性-keras 可视化 VGG16 卷积神经网络

github.com](https://github.com/himanshurawlani/convnet-interpretability-keras)

让我们看看 VGG16 模型是什么样的:

VGG16 convolutional neural network

每个卷积块的输出通过一个激活函数(本例中为 ReLU)传递。

可视化中间激活

在这种技术中,给定一幅输入图像,我们将简单地绘制出在每一层中卷积运算后每个滤波器提取的内容(输出特征)。例如,在 VGG16 中,输入层尺寸为 224x224x3,第一次卷积运算后的输出尺寸为 224x224x64(参见block1_conv1)。这里,64 是用于在第一次卷积运算后提取输入特征的滤波器数量,因此我们将只绘制这 64 个 224x224 输出。

Visualizing the output of convolution operation after each layer of VGG16 network

释义:

  1. 初始层(block1block2)保留了大部分输入图像特征。看起来卷积滤波器在输入图像的每个部分都被激活。这给了我们一种直觉,即这些初始滤波器可能是原始的边缘检测器(因为我们可以认为一个复杂的图形是由不同方向的小边缘组合而成的。)
  2. 随着我们越来越深入(block3block4),过滤器提取的特征在视觉上变得越来越难以解释。对此的直觉是,convnet 现在正在提取输入图像的视觉信息,并试图将其转换到所需的输出分类域。
  3. block5(尤其是block5_conv3)中,我们看到很多空白的卷积输出。这意味着在输入图像中找不到由过滤器编码的图案。最有可能的是,这些图案必须是不存在于该输入图像中的复杂形状。

为了详细说明第 2 点和第 3 点,我们可以将这些见解与我们自己的视觉感知进行比较:当我们看一个物体(比如自行车)时,我们不会坐下来观察该物体的每个细节(比如把手、挡泥板、车轮防滑钉等)。).我们所看到的是一个有两个轮子的物体,轮子由一根金属棒连接着。因此,如果我们被告知要画一辆自行车,这将是一个简单的草图,仅仅传达了两个轮子和一个金属杆的想法。这些信息足以让我们决定给定的对象是一辆自行车。

类似的事情也发生在深层神经网络中。它们充当信息提取管道,将输入图像转换到视觉上不太容易理解(通过移除不相关的信息)但数学上对 convnet 从其最后一层的输出类中做出选择有用的域。

可视化过滤器

我们上面看到的可视化是卷积运算的输出。卷积运算最基本的术语是滤波器/内核和输入图像之间的相关性。与给定输入区域最匹配的滤波器将产生幅度更高的输出(与来自其他滤波器的输出相比)。通过可视化过滤器,我们可以了解每一层已经学会从输入中提取什么模式。

我们首先将一些随机噪声作为输入图像,并使其通过 convnet。我们获取给定层的输出,我们希望可视化该层的过滤器,并找到该层中每个过滤器的*均值。这个寻找每个滤波器的*均值的步骤形成了我们的损失函数。例如,block1_conv1的输入为 224x224x3,输出为 224x224x64,因此它有 64 个过滤器。这里,我们沿着 x 和 y 方向找到每个 224x224 滤波器的*均值,并且我们对所有 64 个滤波器都这样做。在每一步中,我们采用一个滤波器,计算其*均值(即损失)并更新我们的输入图像,使得该滤波器的输出最大化。我们使用梯度上升来更新我们的输入图像,以便最大化损失(特定滤波器的响应)。所得的输入图像将是所选滤波器最大程度响应的图像。

Visualizing the filters/kernels of each layer of VGG16 network

释义:

  1. convnet 中的每一层都简单地学习一组滤波器,使得它们的输入可以表示为这些滤波器的组合。初始图层(block1block2)滤镜看起来像是简单的方向性边缘和颜色(或者在某些情况下是彩色边缘)的集合。这是我们在之前的视觉化中的第一个观察的原因。
  2. 随着我们深入(block4block5),我们看到更多复杂的形状被过滤器编码。这些过滤器可能有助于提取眼睛、鼻子、耳朵等。随着形状变得越来越复杂,它们出现在给定输入图像中的机会越来越少。这就是我们在之前的可视化中的第三个观察的原因。
  3. 许多这样的滤波器是相同的,但是旋转了一些非随机的因子(通常为 90 度)。这意味着,通过找到一种使卷积滤波器旋转不变的方法,我们有可能大幅压缩 convnet 中使用的滤波器数量。

这种经过训练的模型的可视化不仅可以洞察其操作,而且有助于诊断和选择更好的架构。ZF 网(2013) [1]的论文使用这种技术来可视化 AlexNet (2012) [2]架构的第一层和第二层过滤器。他们发现,第一层过滤器是极高和极低频率信息的混合,很少覆盖中频(图像中的低频意味着像素值在空间中缓慢变化,而高频内容意味着像素值在空间中快速变化)。此外,第二层可视化显示了由第一层卷积中使用的大步幅引起的混叠伪像。

他们通过将第一层滤波器大小从 11x11 减小到 7x7 来解决这些问题,并将卷积的步长从 4 改为 2。新架构在第一层和第二层功能中保留了更多信息。更重要的是,它还提高了分类性能。

使用 deconvnets 可视化

解进化网络(deconvnet),是由泽勒等人提出的,2011 [3]。deconvnet 可被视为使用相同组件(过滤、池化)的 convnet 模型,但方向相反,因此 deconvnet 不是将像素映射到要素,而是将要素激活(卷积输出)投影回输入像素空间。

A deconvnet layer (left) attached to a convnet layer (right). [1]

为了可视化 convnet,deconvnet 被附加到它的每个层,提供返回图像像素的连续路径。首先,将输入图像呈现给 convnet,并计算各层的特征。为了检查给定的 convnet 激活,我们将该层中的所有其他激活设置为零,并将特征映射作为输入传递给附加的 deconvnet 层。然后,我们连续地(I)取消 pool,(ii)校正和(iii)过滤,以重建引起所选激活的下层中的活动。然后重复这一过程,直到到达输入像素空间。参见 ZF 网论文[1]的第 2.1 节,了解更多关于未冷却、精馏和过滤的详细信息。

对于给定的层,我们取具有最高激活(幅度)的前 4 个滤波器的输出。我们使用类似的函数来计算激活幅度,就像我们对可视化过滤器所做的那样(损失函数)。在那里,我们计算所有维度的*均值,但在这里,我们计算所有维度的总和,并按降序对过滤器进行排序。例如,对于给定的输入图像block1_conv1,要激活前 4 个滤波器,我们找到沿 x 和 y 方向的所有 64 个 224x224 滤波器的输出之和,按降序对它们进行排序,并将前 4 个输出馈送到我们的 deconvnet。这给了我们由这些滤波器看到的输入图像的 4 种不同变化。

释义:

  1. 每个图层的投影显示了网络中要素的等级性质。
  2. block1响应角点和其他边缘/颜色连接。block2block3具有更复杂的不变性,捕捉相似的纹理(例如网格图案)。
  3. block4尝试定位图像的部分,如眼睛、鼻子、嘴等。block5显示整个局部人脸。

将特征激活投影回输入空间,让我们类似地了解这些层中的过滤器是在什么情况下被激活的。我们看到一些投影具有突出的水*边缘,一些具有突出的垂直边缘。一些投影覆盖眼睛,鼻子,嘴,一些覆盖整个脸。将每个顶部激活分别向下投影到像素空间揭示了输入图像中激发给定特征图的不同结构。

可视化热图

在这项技术中,我们使用 GradCAM 并试图了解输入图像的哪些部分导致了 convnet 做出特定的分类决策。该技术的一般类别被称为“类激活图”(CAM)可视化,包括在输入图像上产生“类激活”的热图。“类别激活”热图是与特定输出类别相关联的分数的 2D 网格,针对输入图像中的每个位置计算,指示每个位置相对于所考虑的类别有多重要。这有助于我们调试卷积神经网络的决策过程。我们也可以使用相同的技术来定位图像中的特定对象。看看这个演示:http://gradcam.cloudcv.org/

在 GradCAM 中,我们采用给定输入图像的卷积层的输出,并通过预测类的梯度对该输出中的每个通道进行加权。假设我们给 convnet 输入了一些图像,得到了“大象”作为预测。最后一个预测层可以被认为是具有一些输入的函数(在这种情况下是block5_conv3的输出)。所以,如果f是预测层,xblock5_conv3的输出,那么预测层的输出可以被给定为y,其中y=f(x)。同样的,我们可以证明block5_conv3是一个有一些输入的函数g(本例中是block5_conv2的输出)。让我们把block5_conv2的输出看作z然后x(可以把block5_conv3)的输出看作x=g(z)等等…

使用上述类比,我们可以将具有输入的预测层的输出视为其所有先前层(以嵌套方式)。我们对某个先前层(我们希望热图可视化的层)中的每个通道的预测输出 w.r.t .进行偏导数,这给出了每个通道对预测输出的重要性。然后,我们将每个通道与其对应的梯度(重要性)相乘,以对负责预测输出的每个通道进行加权,并计算通道*均值,以获得该层的热图。

Heatmap visualization using GradCAM technique for each layer of VGG16 network

释义:

  1. VGG16 网络只是一个图像分类器,能够在输入图像中定位大象。
  2. 该网络以 90%的准确率预测了输入图像中的“非洲象”,主要是因为小象的面部和耳朵部分(见block5_conv3)。这大概就是网络如何区分非洲象和印度象的。

当我们看到不同层的热图时,我们看到图像的不同部分被激活。这是因为早期的图层有滤镜,可以看到图像的不同部分。但是类别预测很大程度上取决于预测之前层的激活,因此,可视化预测层之前层的热图(在这种情况下为block5_conv3)告诉我们输入图像的哪个部分导致了特定的预测。

结论

  • 这些可视化技术不仅告诉我们模型已经学会在图像中识别什么,还告诉我们它的性能可以在哪里改进。它为我们提供了关于模型可解释性的有用见解,因此我们可以放心地在现实世界的用例中部署这些模型。
  • 令人惊讶的是,我们不仅可以重新训练分类器来识别图像中的对象,还可以使用 GradCAM 可视化技术来*似定位它们。看看这个演示:https://www.youtube.com/watch?v=COjUB9Izk6E
  • 在一天结束时,由 convnets 学习的所有参数和过滤器的目标是最小化给定训练数据的成本函数。这个成本函数和训练数据定义了我们的 convnet 的能力。

进一步阅读

  1. 可解释性的基石:https://distill.pub/2018/building-blocks/
  2. 通过深度可视化理解神经网络:http://yosinski.com/deepvis
  3. 想象一下康夫尼特学到了什么:http://cs231n.github.io/understanding-cnn/
  4. 跟踪网络中发生的事情的有用工具箱:https://cs.stanford.edu/people/karpathy/convnetjs/

参考

[1]可视化和理解卷积网络,https://arxiv.org/abs/1311.2901v3

[2]使用深度卷积神经网络的 ImageNet 分类,https://papers . nips . cc/paper/4824-ImageNet-class ification-with-Deep-convolutionary-Neural-Networks

[3]用于中高级特征学习的自适应去进化网络,【https://ieeexplore.ieee.org/document/6126474

[4]可视化 convnets 学习的内容,https://github . com/fchollet/deep-learning-with-python-notebooks/blob/master/5.4-Visualizing-what-conv nets-learn . ipynb

[5]卷积神经网络如何看待世界,https://blog . keras . io/How-convolutionary-neural-networks-see-the-world . html

数据框可视化概述入门

原文:https://towardsdatascience.com/visual-overview-of-the-data-frame-4c6186a69697?source=collection_archive---------5-----------------------

数据可视化不仅是在清理数据后分析数据和交流结果的一种方式,也是在初始阶段理解整个数据框架的一种方式。在这里,我举例说明了 3 个简单的方法(每个方法 2 行代码),用于可视化地探索整个数据帧的组成、相关性和分布。

ggpairs

ggpairs 将绘制变量矩阵,并根据它们是分类的还是数字的来使用合适的视觉类型。

library(GGally)
ggpairs(iris, aes(colour = Species, alpha = 0.4))

特色剧情

插入符号中的特征图可以在方框/密度图中单独绘制每个变量的网格,或者在散点图矩阵中成对绘制。

library(caret)
featurePlot(x=iris[,1:4], y=iris[,5], plot="box", scales=list(x=list(relation="free"), y=list(relation="free")), auto.key=list(columns=3))

表格图

Tableplot 将绘制每个变量的表格。对于范畴来说,这是探索其构成的好方法。如果存在缺失值,它也会显示出来。

library(tabplot)
tableplot(iris)

这些方法更适用于少于 10 维的数据帧,其中的列主要不是自由文本,因为它们可以相对容易地可视化数字和分类变量。探索更多适合不同类型的数据框架(重文本、高维)的方法。

这是我第 100 天项目的第 6 天。

用 R 视觉化伦敦的犯罪(上)

原文:https://towardsdatascience.com/visualising-crime-in-london-using-r-part-i-de7853c92ba8?source=collection_archive---------3-----------------------

我最*在使用 r 可视化伦敦犯罪的时间序列数据。我忍不住创建了地图,让我可以更好地分析数据。

我创建本教程是为了:

  1. 有一个用 R 绘制地图的简单例子
  2. 展示在地图中可视化数据的优势,以便更容易地识别模式和趋势。

在本教程中,您将学习如何使用SpatialPolygonsDataFrame访问绘制行政区所需的数据,以及如何使用ggplot2创建相应的地图。

本教程的代码和数据可以在 github 链接上找到。

访问数据

犯罪数据

本教程中使用的数据集来自伦敦数据存储库,这是一个开放的数据共享*台,其统计数据由伦敦市长办公室提供。为了使教程简单,我只包含了一个名为crime_data.csv的 CSV 文件,其中只包含绘制犯罪率所需的数据。

上面的代码加载犯罪数据并更改标题的名称。它将显示以下内容:

行政区的空间数据

你现在需要使用readOGR来加载LondonBoroughs.shp

LondonBoroughs.shp是项目的‘Map _ data’文件夹中的 shapefile。您会注意到几个名为“LondonBoroughs”的文件具有不同的文件扩展名。你需要它们,因为 shapefile 是由许多不同的文件组成的。prj,。dbf 和. shp。

readOGR将简单地提取 shapefile 中的信息。

上面的代码将显示以下数据:

将犯罪数据与空间数据联系起来

既然您已经有了两个数据集,那么您需要将它们链接在一起。为此,您只需使用left_join并将namebourough用作 id。

运行代码后,您会注意到两个数据集现在已经链接在一起:

将空间数据转换为数据帧

准备好数据的最后一步是使用fortify将其转换成数据帧。这是必需的,因为ggplot需要一个数据帧来创建地图。

如果您运行上面的代码,您会看到数据看起来是一样的。唯一的区别是它现在是一个数据帧(注意,您不再需要使用@data来查看信息):

如果你不信任我,就在你的控制台上运行下面的代码,仔细检查你使用的数据类型😃

Just a test!

可视化地图

现在,您已经有了绘制第一批图表的数据。

如下图所示,你需要的只是ggplot。使用fill=2013``根据列“2013”中的数据创建颜色渐变,这是相应年份每个区的犯罪率。

假设您不需要longlat出现在图形中,那么您需要删除轴和记号。

通过运行上面的代码,您应该能够看到您的第一个图表:

如果您想创建一个 GIF 来显示一段时间内的变化,您需要首先以下列方式之一将每年的图表保存为图片:

  • 通过使用ggsave()(例如:ggsave("plot_2013.png")),或者
  • 通过右键单击图表并导出

确保所有图表的图例值保持相同(如果图例发生变化,可能会影响地图的大小)。为此,只需将limits(0, max_value)添加到scale_fill_gradient2中。在这种情况下,max_value 可以是 140。scale_fill_gradient2的最终结果如下所示:

scale_fill_gradient2(low = "#BDBDBD",high = "#2196F3", # colors
                        name = "Crime rate", limits = c(0, 140))

然后你需要做的就是把这些图片添加到 gif 创建工具中,就像从 Giphy 中得到的一样。最终结果将如下所示:

从上面的图表中,你可以注意到随着时间的推移,所有行政区的犯罪率都下降了。远离市中心的行政区似乎犯罪率最低,而靠*市中心的行政区似乎犯罪率最高。

犯罪率最高的行政区

如果您只想给犯罪率高于特定水*(例如 90)的行政区着色,那么您需要做的就是将填充中的值更改为fill=2013>90

该图的完整代码如下所示:

结果如下图所示:

Boroughs with crime rates above 90 in 2013

从上面可以看到,2013 年犯罪率在 90 以上的行政区有兰贝斯、哈克尼、哈林盖、纽汉等。

下一个教程

在下一个教程中,我将展示如何在一个图表中绘制每年的地图。这真的很容易。

我希望你喜欢这个教程❤.

如果您有任何问题,请使用下面的评论部分。

谢谢!

关于作者

我是 Valeria,我热衷于通过美丽的可视化和分析进行数据发现。我希望你喜欢这篇文章!

你可以在 Twitter 和 Instagram 上找到我,或者访问我在 valeria.io 的页面。

使用 Plotly 可视化经济数据

原文:https://towardsdatascience.com/visualising-economic-data-using-plotly-a07f96f58160?source=collection_archive---------9-----------------------

因为我是一名经济学家,热爱编程和数据科学,所以我想把这些激情结合起来,做一些有趣的数据分析。这篇文章利用各种 python 库来抓取和可视化经济数据。我希望这能对你们中的一些人有用,并且你们能像我一样喜欢阅读这篇文章。

我需要做的第一件事是获取一些数据。既然维基百科是所有互联网知识的来源(不是!!)就从这里开始吧。我决定从下面的维基百科页面中抓取一个表格:[ 维基 ]。我认为观察世界上一些最富有和最贫穷的国家会很有趣。这张表是根据人均 GDP 对各国进行排名的。

在我继续讲下去之前,简单解释一下什么是人均 GDP 可能是个好主意(你会想当然地认为很多人并不真正讲“经济学”)。简单来说,它是衡量一个国家富裕程度的指标。它实质上是一年内在一个国家境内生产的所有商品和服务的价值除以人口。这给了我们一种描述该国人均财富水*的方法。这是一个非常重要的经济变量,通常用于比较不同国家和不同时期的财富水*。

一般来说,人均国内生产总值可以增加,原因如下。
1。国内生产总值增加
2。人口减少
3。两者的结合。

这一指标通常被认为比 GDP 更能反映一个国家的富裕程度。现在我们有了简单的经济学入门,让我们深入分析一下。正如我之前提到的,我将废弃维基百科上的数据,所以使用美丽的汤似乎是显而易见的。这个库极大地简化了从网页中提取数据的过程,是 python 中 web 抓取的首选库。

什么是 BeautifulSoup?

Beautiful soup 是一个 python 库,用于从 html 和 xml 文件中提取数据。这使得这个库对于从网页中提取信息非常有用。如果你想知道更多关于这个库是如何工作的,以及你可以用 beautiful soup 执行的各种任务的信息,请随意阅读[文档

为了使用漂亮的汤,有必要了解一些简单的 html 标签。对 html 有一点了解将会使我们更容易搜索到我们想要的数据。例如,维基百科在其网页上显示的表格中使用了表格标签。知道了这一点,我们就可以简单地解析 html,只寻找包含在这些标签中的信息。

首先,我需要导入分析所需的所有库。

import requestsfrom bs4 import BeautifulSoup​import matplotlib.pyplot as pltimport seaborn as sns%matplotlib inlinefrom bubbly.bubbly import bubbleplot​from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplotimport plotly as pyimport plotly.graph_objs as goinit_notebook_mode(connected=True) #do not miss this linefrom plotly import tools

现在我已经加载了库,我们准备开始分析。下面的代码允许我们将网页加载到我们的 Jupyter 笔记本中,并将其传递给 BeautifulSoup 类以创建一个 Soup 对象。

web_page=“[https://en.wikipedia.org/wiki/List_of_countries_by_GDP_(PPP)_per_capita](https://en.wikipedia.org/wiki/List_of_countries_by_GDP_(PPP)_per_capita)"req=requests.get(web_page)
page = req.text
soup = BeautifulSoup(page, ‘html.parser’)
soup.title

好了,看起来它工作了,我们可以在 soup 对象上使用一些函数并提取我们想要的数据。我之前提到过我们对表标记感兴趣。下面是从 wiki 页面提取所有表格的代码。

table = soup.find_all(“table”, “wikitable”)
len(table)from IPython.display import IFrame, HTML
HTML(str(table))

上面的代码返回一个列表,其中每个条目包含页面上的一个表。这个页面只有五个表,所以很容易得到我们需要的表,它恰好是列表中的第一个条目。我们还可以通过使用 IPython.display 中的 HTML 命令来确认它是否正确,该命令会打印出维基百科上显示的表格。

现在我们有了表格,接下来的问题就是得到国名和人均 GDP。要做到这一点,我们需要知道更多关于 HTML 表格的结构。特别要知道、和标签。它们分别代表表头、表行和单元格。好的,让我们试着提取一些数据。

GDP_PC = table[0]
table_rows = GDP_PC.find_all(‘tr’)
header = table_rows[1]table_rows[1].a.get_text()

这段代码查找所有指示表格行的 tr 标签。然后我们得到表格的标题,并打印出来,给出下面的结果。这对应于国家名称,我们使用 a.get_text()提取我们需要的名称。table_rows 中的每个索引对应一个国家,国家名位于标签中,对于索引的每个值都是相同的。

现在,我们需要做的就是遍历 table_rows,提取数据并添加到一个列表中。

countries = [table_rows[i].a.get_text() for i in range(len(table_rows))[1:]]
cols = [col.get_text() for col in header.find_all(‘th’)]

Python 有一个非常好的简洁的方法,使用列表理解来编码这类循环。注意我跳过了 table_rows 的第一个条目,因为它不对应于一个国家。我们还使用列表理解来提取列标题,这在以后会很有用。上面的代码相当于下面的 for 循环。

country = []
for i in range(len(table_rows))[1:]:
 country.append(table_rows[i].a.get_text())

接下来是标签。这是我们的人均 GDP 数据存储在表中的位置。然而,数据是相当混乱的,我们可以使用许多变通方法将正确的数据转换成正确的格式。让我们快速看一下其中一个数据点。

temp = GDP_PC.find_all(‘td’)
temp[5].get_text()

这给了我们' 114,430\n '。我们可以看到所有的数据都被定义为字符串
,每个单元格中都有逗号和换行符,所以我们需要稍后修复这个问题。首先,让我们集中精力将数据放入一个列表中。

temp = GDP_PC.find_all(‘td’)
GDP_per_capita = [temp[i].get_text() for i in range(len(temp)) if “,” in temp[i].get_text()]
GDP_per_capita = [i for i in GDP_per_capita if ‘\xa0’ not in i]temp_list = []
for i in range(len(temp)):
 temp_list.append(temp[i].get_text())
new_list = temp_list[-11:]numbers = [i for i in new_list if “\n” in i]for i in numbers:
 GDP_per_capita.append(i)rank = list(range(len(countries)))

上面的代码中有很多内容,让我们一步一步来看。我做的第一件事是找到 GDP_PC 中的所有单元格,并存储在一个临时变量中。
下一行循环遍历该变量,并获取包含逗号的文本。我这样做是因为大多数条目都是以千为单位的,因此包含一个逗号。然而,这种方法确实错过了最后四个条目,因为它们花费了数百美元,所以我必须创建一个解决方法,这就是 new_list 和 numbers 变量正在做的事情。最后,我将这些条目添加到人均 GDP 列表中,并生成一个 rank 列,其中只有从 1 到 192 的数字。这可能不是最有效的方法,可能有更好的方法,但它确实有效,所以我很满意。

在提取了排名、国家和人均 GDP 这三列列表后,我们需要将它们合并在一起,创建一个熊猫数据框。这将使绘制和分析数据更加简单。有一个名为 zip 的便捷函数允许我们创建两个独立的数据框。一个是最富有的 20 个国家,一个是最贫穷的 20 个国家。下面的代码实现了这一点。

data = zip(rank[0:21],countries[0:21], GDP_pc[0:21])
import pandas as pd
cols = [‘Rank’, ‘Country’, ‘GDP Per Capita’]
data1 = pd.DataFrame(list(data), columns = cols)data2 = zip(rank[-21:],countries[-21:], GDP_pc[-21:])
data2 = pd.DataFrame(list(data2), columns = cols)

我们现在有了熊猫数据框中排名前 20 和后 20 的国家。在我们绘制数据之前,我们需要做一些清理工作。数据目前被定义为字符串,所以我们需要解决这个问题,以便使用某些熊猫函数。下面的代码删除了 HTML 换行符“\n”、逗号,并将数据类型定义为 int。

data1['GDP Per Capita'] = data1['GDP Per Capita'].apply(lambda x: x.replace('\n', '')).astype(int)data2['GDP Per Capita'] = data1['GDP Per Capita'].apply(lambda x: x.replace(',', '')).astype(int)

我们终于准备好数据来创建一些好看的可视化。

Plotly 简介

现在我们可以进入 Plotly 来创建我认为非常好的可视化。我真的很喜欢这个库,它足够简单,可以制作出非常互动的情节。如果你想知道你能创建什么样的图表,我鼓励你阅读文档[ 网站

下面的代码创建了一个简单的世界上最富有的 10 个国家的条形图。首先,我们将数据传递到。条形图创建一个条形图,x 轴表示国家名称,y 轴表示人均 GDP。然后,我们将它存储在一个列表中,并传递给 go。图形方法。这里的相同步骤适用于在 Plotly 中创建所有不同类型的地块。有些结果可能会让你吃惊,也可能不会。例如,排名前 10 位的国家中,不乏卡塔尔和科威特等高度依赖石油生产的国家,这些国家政府收入的大约 70%至 94%来自石油。这些国家中的许多往往人口相对较少,经济规模较大,因此根据这一标准(相对较少的人口分享了大量财富),它们非常富有并不令人惊讶。

trace1 = go.Bar(
 x = data1.Country,
 y = data1[‘GDP Per Capita’])data = [trace1]
layout = go.Layout(
 title=’Top 20 countries ranked by GDP per Capita’)fig = go.Figure(data = data, layout = layout)
py.offline.iplot(fig)

很简单,对吧?现在对于最贫穷的国家来说。毫不奇怪,这些国家往往集中在非洲,那里人口增长迅速,经济落后于更发达的国家。

在快速了解了排名前 10 和后 10 的国家之后,让我们试着从整体上对世界进行更广泛的了解。做这件事的一个好方法是使用地图。在 Plotly 中,你可以创建 choropleth 地图,它基于一些变量对不同的区域进行着色。在我们的例子中,这是人均国内生产总值。人均 GDP 较高的国家会有较深的红色阴影。关于这段代码,需要注意的最重要的事情是传递到 locations 参数和 location mode 参数中的国家名称。这些必须匹配,情节才能起作用。你也可以使用国家代码,甚至经度和纬度来实现相同的情节,但我认为这可能是最简单的方法。请注意,Plotly 允许您放大特定区域以进行*距离观察,这是一个非常好的功能。

我们可以看到,最富裕的国家往往集中在北美和欧洲,而最贫穷的国家在非洲,用较浅的颜色表示。

data = [ dict(
 type=’choropleth’,
 locations = data_all[‘Country’],
 autocolorscale = True,
 z = data_all[‘GDP Per Capita’],
 locationmode = ‘country names’,
 marker = dict(
 line = dict (
 color = ‘rgb(255,255,255)’,
 width = 2
 )
 ),
 colorbar = dict(
 title = “Millions USD”
 )
 ) ]layout = dict(
 title = ‘Top Countries by GDP per capital’)fig = go.Figure(data = data, layout = layout)
py.offline.iplot(fig)

富裕国家的人更长寿吗

好了,现在我已经用 Plotly 展示了一些简单的情节,我想更进一步,创造一些真正酷的东西。有一个名为 bubbly 的非常好的库,它可以创建气泡图,并且有一些有趣的功能来增强您与图表的交互性。你可以用 Plotly 做到这一点,但是要达到想要的效果需要相当多的编码,而 bubbly 让它变得超级简单。此库归功于[Aashitak]。还有一个漂亮的[ kaggle 内核]展示了这个库是如何工作的,绝对值得一试。

我想做的是创建一个气泡图,看看人均 GDP 和预期寿命。该图表还考虑了每个国家的人口以及该国位于哪个洲。我从世界银行网站上获得了所有的数据。下面是在使用 pandas 中读取数据的代码,我创建了一个国家、大陆和年份的唯一值的列表,这对处理数据很有用。事实证明,这是一个由 gapminder 基金会创造的非常著名的可视化。他们有一个非常好的工具来绘制这个和其他可用的图表[在这里],如果任何人
想看看的话。

我在这里使用的世界银行数据与 Kaggle 上的 gapminder_indicator 数据集(该图最初是基于该数据集)的格式完全不同。要使用 bubble 库,我们需要数据采用后者的格式,因此需要一些数据操作。我之所以使用世界银行的数据,是因为它的时间序列稍微长一点,我想了解更多最*的发展情况。下面的代码将数据集加载到中,并提取 gapminder 数据集中使用的相同国家。

gdp = pd.read_csv(“gdp_per_capota.csv”, engine = “python”)
life = pd.read_csv(“LifeExp.csv”, engine = “python”)
pop = pd.read_csv(“population.csv”, engine = “python”)
gapminder_indicators = pd.read_csv(“gapminder_indicators.csv”, engine = “python”)countries = gapminder_indicators.country.unique()
continents = gapminder_indicators.continent.unique()
years = gapminder_indicators.year.unique()[‘Country Name’,
 ‘1982’,
 ‘1987’,
 ‘1992’,
 ‘1997’,
 ‘2002’,
 ‘2007’,
 ‘2010’,
 ‘2013’,
 ‘2016’]# Filter countries first
gdp_new = gdp[gdp[‘Country Name’].isin(countries)]
life_new = life[life[‘Country Name’].isin(countries)]
pop_new = pop[pop[‘Country Name’].isin(countries)]# # Now filter years
years = [str(year) for year in years]
years = years[6:]
for i in [‘2010’, ‘2013’, ‘2016’]:
 years.append(i)years.insert(0,”Country Name”)gdp_new = gdp_new[years]
life_new = life_new[years]
pop_new = pop_new[years]

gapminder_indicator 数据集具有用于绘图的正确格式(长格式,见下文)的数据,因此本质上我们需要将三个数据集处理成相同的格式,并在我可以使用 bubbly 绘制它们之前将它们合并在一起。

 country      continent year  lifeExp  pop      gdpPercap
 Afghanistan  Asia     1952   28.801  8425333  779.445314 
 Afghanistan  Asia     1957   30.332  9240934  820.853030
 Afghanistan  Asia     1962   31.997  10267083 853.100710
 Afghanistan  Asia     1967   34.020  11537966 836.197138
 Afghanistan  Asia     1972   36.088  13079460 739.981106

世界银行数据集的格式不同,每年的人口被分配到不同的列(宽格式)。下面是我用来将世界银行数据转换成正确格式的代码。

Country name  1960      1961      1962
 Aruba        54211.0   55438.0   56225.0
 Afghanistan  8996351.0 9166764.0 9345868.0
 Angola       5643182.0 5753024.0 5866061.0
 Albania      1608800.0 1659800.0 1711319.0
 Andorra      13411.0   14375.0   15370.0 melted_gdp = pd.melt(gdp_new, id_vars = ["Country Name"], var_name = "Year", value_name = "Data")grouped_gdp = melted_gdp.groupby(["Country Name"]).apply(lambda x: x.sort_values(["Year"], ascending = True)).reset_index(drop=True)​melted_life = pd.melt(life_new, id_vars = ["Country Name"], var_name = "Year", value_name = "Data")grouped_life = melted_life.groupby(["Country Name"]).apply(lambda x: x.sort_values(["Year"], ascending = True)).reset_index(drop=True)​​melted_pop = pd.melt(pop_new, id_vars = ["Country Name"], var_name = "Year", value_name = "Data")grouped_pop = melted_pop.groupby(["Country Name"]).apply(lambda x: x.sort_values(["Year"], ascending = True)).reset_index(drop=True)​temp = pd.merge(grouped_gdp, grouped_life, on = ['Country Name', 'Year'], how = 'inner')temp = pd.merge(temp, grouped_pop, on = ['Country Name', 'Year'], how = 'inner')cols= ['Country Name', 'Year', 'Data_x', 'Data_y', 'Data']temp = temp[cols]​data = temp.copy()

让我解释一下我在这里做什么。melt 函数将所有年份列折叠成一行,并在值行中列出每年的值。然后,我按国家名称分组,并按年份对每一行进行排序,这样我就得到一个数据集,其中国家按字母顺序排序,年份按时间顺序排序。这与 gapminder_indicators 相同。然后,这些数据集是根据国家名称和年份合并的数据集。我认为你可以用一个 Pandas 函数来完成,但是我决定用一种更像手工的方式来完成,因为这是一种逐步练习如何操作数据的好方法。

我们现在需要做的另一件事是创建一个大陆列,它将国家映射到正确的大陆,因为这些信息将在绘图时使用。为此,我们使用 gapminder 数据集创建一个字典,然后将这个字典映射到我的合并数据集中的一个新列。

dictionary = dict(zip(gapminder_indicators[‘country’], gapminder_indicators[‘continent’]))
data[“continent”] = data[“Country Name”].map(dictionary)data.rename(columns = {‘Data_x’: ‘GDP_pc’, ‘Data_y’: ‘Life Expectancy’, ‘Data’: ‘Population’}, inplace=True)

最后,我们有一个完成的数据集,我们可以创建我们的图。我们使用 bubbly 库中的 bubbleplot 函数来完成这项工作。该函数创建了一个美丽的预期寿命与人均 GDP 的互动图,并根据该国人口绘制了泡沫的大小。气泡还被大陆着色,我们能够绘制所有这些跨时间的信息,这真的很好。最显著的变化是中国和印度,用最大的紫色气泡表示。在样本开始时,它们属于最贫穷的国家,预期寿命相对较低。然而,随着时间的推移,出现了向图表右上方的大幅移动,表明人均国内生产总值和预期寿命都有大幅增长。这很大程度上反映了我们所看到的中国在过去 20 年左右成为经济强国的情况。

从图表中还可以清楚地看出,人均国内生产总值和预期寿命之间存在正相关关系。随着一个增加,另一个也趋于增加。当然,这并没有告诉我们任何因果关系,也不清楚是因为富裕国家的预期寿命更长,还是因为富裕国家的预期寿命更长。这也许是一篇经济学研究论文的问题,而不是这篇博文。

这就是你如何使用漂亮的汤从互联网上提取数据,以及如何使用数据可视化来解释和揭示数据中的趋势,这些趋势在原始数据中看起来可能并不明显。

from bubbly.bubbly import bubbleplotfigure = bubbleplot(dataset=data, x_column=’GDP_pc’, y_column=’Life Expectancy’, 
 bubble_column=’Country Name’, time_column=’Year’, size_column=’Population’, color_column=’continent’, 
 x_title=”GDP per Capita”, y_title=”Life Expectancy”, title=’Gapminder Global Indicators’,
 x_logscale=True, scale_bubble=3, height=650)iplot(figure, config={‘scrollzoom’: True})

我的博文原文链接:https://d poly . github . io/blog/2018/08/10/Economic-data-plot ly . html