TowardsDataScience-博客中文翻译-2020-八十七-

TowardsDataScience 博客中文翻译 2020(八十七)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

具有记忆的神经网络

原文:https://towardsdatascience.com/neural-networks-with-memory-27528a242b78?source=collection_archive---------19-----------------------

Infralist.comUnsplash 上拍照

深度学习

了解 LSTM RNN 不到 5 分钟

我们总是听说神经网络 ( NNs )是受生物神经网络的启发。这个巨大的展示是以一种奇妙的方式完成的。

图 1 显示了单个神经元的解剖结构。中心部分称为细胞核所在的细胞体。有各种导线将刺激传递到细胞体,少数导线将输出发送到其他神经元。树突的厚度暗示了刺激的重量/偏向/力量。许多具有不同细胞体的神经元堆叠在一起,形成了生物神经网络。

图 1:单个神经元的解剖(来源,作者编辑)

在神经网络中也实现了同样的结构。输入通过带加权边的激活函数传递。生成的输出可以传递给另一个激活函数。许多激活功能可以堆叠起来,其中的每一个都被称为一个。在一层中,我们可以有多个神经元。

图 2:单神经元神经网络(图片由作者创建)

这些激活函数可以像 sigmoid 函数一样简单

神经网络相对于传统机器学习算法的优势

  • 可以处理各种类型和大小的数据
  • 可以轻松配置多种功能
  • 可以有效地处理非线性数据

具有记忆的神经网络

神经网络和生物神经网络的主要区别在于记忆。虽然人脑和神经网络都有能力从可用的记忆中读取和写入,但大脑也可以创建/存储记忆。研究人员发现这一关键差异是当今人工智能系统达到人类智能水平的主要障碍。

DeepMind 的研究人员旨在通过构建一个神经网络并将其连接到外部存储器来构建一台可区分的计算机。神经网络将充当带有存储器的 CPU。这种可微分计算机旨在从输入和输出数据中学习程序(算法)。

当数据量巨大时,使用神经网络。例如,文本数据具有大量的维度,或者图像数据被分割成大量的像素。

递归神经网络

一部电影由一系列场景组成。当我们观看一个特定的场景时,我们不会试图孤立地理解它,而是联系以前的场景来理解。以类似的方式,机器学习模型必须通过利用已经学习的文本来理解文本,就像人类神经网络一样。

在传统的机器学习模型中,我们无法存储模型的先前阶段。然而,递归神经网络(通常称为 RNN)可以为我们做到这一点。下面我们来仔细看看 RNNs。

图 3:基本 RNN 的工作原理(图片由作者提供)

RNN 有一个重复模块,它接收前一级的输入,并将其输出作为下一级的输入。然而,在 RNNs 中,我们只能保留最近阶段的信息。这就是 LSTM 的问题所在。

长短期记忆网络

为了了解长期依赖关系,我们的网络需要记忆能力。LSTMs 是可以做到这一点的 rnn 的特例。它们具有与 RNNs 相同的链状结构,但具有不同的重复模块结构。

图 4:LSTM 的工作(图片由作者提供)

LSTM 在序列到序列建模任务中有广泛的应用,如语音识别、文本摘要、视频分类等。

要想快速了解这些网络在现实生活中的应用,请阅读下面的文章。

[## 检测电子邮件中的垃圾邮件

应用自然语言处理和深度学习进行垃圾邮件检测

towardsdatascience.com](/spam-detection-in-emails-de0398ea3b48)

垃圾邮件检测模型可以通过将文本数据转换成向量、创建 LSTM 模型并用向量拟合该模型来实现。

履行

为了实现这些完整的神经网络,Keras 和 TensorFlow 将其简化。

我们正在实现一个带有 ReLU 激活功能的双向 LSTM。

#Importing necessary libraries
import tensorflow as tf
from keras.layers import LSTM, Activation, Bidirectional#Addding Bi-directional LSTM
model.add(Bidirectional(tf.keras.layers.LSTM(64)))#Relu allows converging quickly and allows backpropagation
model.add(Dense(16, activation='relu'))model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

创建每一层只是一行代码。

摘要

在这篇文章中,我们学习了神经网络如何与生物神经网络相联系,以及具有记忆的神经网络的工作原理(即 RNN,LSTM)。

谢谢你的阅读。我也将在未来写更多初学者友好的帖子。请在媒体上关注我,以便了解他们。我欢迎反馈,可以通过 Twitter ramya_vidiyala 和 LinkedIn RamyaVidiyala 联系我。快乐学习!

完全初学者用的神经网络从零开始第 3 部分:逻辑回归

原文:https://towardsdatascience.com/neural-networks-with-numpy-for-absolute-beginners-part-3-logistic-regression-18b474096a4e?source=collection_archive---------32-----------------------

sigmoid 激活函数是神经网络中最基本的概念。在本教程中,您将学习实现使用 sigmoid 激活函数和 Numpy 进行分类的逻辑回归。

无论是机器学习还是深度学习,都会遇到两种问题,分别是分类

回归问题 中,你预测一个连续的实数值,而在 分类问题 中,你预测不同类别的对象。

在前面的教程中,我们深入探讨了什么是感知器,后来又学习了它如何使用线性回归来学习预测。如果你是这个领域的绝对初学者,我推荐你去看看我以前的简短教程。

* [## 神经网络与 Numpy 的绝对初学者:简介

在本教程中,您将简要了解什么是神经网络以及它们是如何发展起来的。在…

towardsdatascience.com](/neural-networks-with-numpy-for-absolute-beginners-introduction-c1394639edb2) [## 绝对初学者用的带 Numpy 的神经网络第 2 部分:线性回归

在本教程中,您将详细学习使用 Numpy 实现预测的线性回归,并可视化…

towardsdatascience.com](/neural-networks-with-numpy-for-absolute-beginners-part-2-linear-regression-e53c0c7dea3a)

在本教程中,您将了解用于分类问题的逻辑回归。

像以前一样,会涉及到一些数学知识,但我会确保从基础开始,这样你就可以很容易地理解。

如果你不确定使用哪种环境来实现本教程中的代码,我推荐 Google Colab 。该环境已经安装了许多重要的软件包。安装新的包以及导入和导出数据非常简单。最重要的是,它还带有 GPU 支持。所以,开始编码吧!

最后,我建议您在开始之前先浏览前两个教程。然而,如果你已经对线性回归和神经网络有所了解,或者只是想学习逻辑回归,你可以马上开始!

Sigmoid 激活函数

使用最早和最普遍的激活功能之一是s 形函数

sigmoid 函数的等式如下:

该函数的图形如下:

Sigmoid 函数

因此,具有 sigmoid 激活函数的感知器对给定的数据集进行二元分类。这个二元分类的过程俗称 逻辑回归 。在下一节中,我们将深入研究逻辑回归,并了解模型是如何被训练的。

逻辑回归

那么,什么是逻辑回归呢?

逻辑回归是一种用于二元分类的技术。它在数据点之间创建一个决策边界,以便将它们归类到两个类别中的任何一个。下图就是这样一个例子。我们将通过实际操作来深入理解和训练一个逻辑回归模型。理解逻辑回归将为理解神经网络模型提供基础。

要实施的逻辑回归的计算图如下图所示。

我们有两个输入 x₁x₂ ,它们分别乘以权重 w₁w₂ 。将附加偏置 b 加到它们的和上,得到 z 。这些参数( w₁w₂b )是在梯度下降过程中学习到的。

现在让我们开始编码吧!

第一步是导入所需的包。

您将使用 sklearn 包来执行两项任务:

  1. 生成 blobs 数据集
  2. 将数据分成训练集和测试集。

您将使用 matplotlib 来可视化结果。

在你开始定义代码之前,在任何机器学习项目中,你的第一个任务将是定义超参数。超参数可以是数据集大小、学习率、时期数等。你一定想知道为什么这些变量被称为超参数!您稍后会发现,参数是在模型中学习到的,我们使用 hyperparameter 来微调模型,以实现更高的准确性。

在这里,我们还定义了创建数据集所需的输入要素数和聚类数。

继续定义它们吧!

接下来,我们用 make_blobs 函数从 scikit-learn 导入数据集,该函数创建类的 blob。我们也将同样想象。

现在,让我们绘制一个图形来可视化生成的数据。

这两组数据点属于这两类。我们的目标是找到一个区分这两类的最优决策边界。

下一步将把数据分成训练集和测试集。我们这样做是为了验证所学算法的准确性。

Shape of X_train (400, 2) 
Shape of y_train (400, 1) 
Shape of X_test (100, 2) 
Shape of y_test (100, 1)

现在,您将随机初始化参数 W 和 b,它们是在训练过程中学习到的。

Initializing weights... 
W: [[-0.59134456] [-0.31427067]] 
b: -1.6078558751252707

在我们随机初始化参数后,下一步是执行正向传播,并查看网络如何预测。

现在,您将利用generate_mesh_grid函数绘制数据集和等高线。

现在是时候定义损失函数了!!

成本/损失函数

与线性回归的 MSE 不同,这里我们使用逻辑损失函数。这是因为当我们通过 sigmoid 激活函数传递总和 z 时,输出是非线性的(因为 sigmoid 函数是非线性的)。这会导致非凸误差。

但是你说的非凸是什么意思?

简单来说,非凸函数看起来就像右图。

在这种情况下,虽然我们的目标是找到最小点,但由于波谷和波峰,找到一个点变得极其困难。相反,如果我们有一个简单的函数(就像左边的那个),我们可以很容易地找到最小点,我们就可以使我们的问题变得简单。这是左边的凸函数。

因此,我们使用一个对数函数,它实际上将非线性函数转换回线性函数,从而产生一个凸函数!

凸优化和非凸优化。来源:https://bit.ly/3d9ESRL

损失可以定义为:

测井曲线( x ) 如上图所示。可以推断给定 y = 1 如果y→0,那么 loss → 0 而当 y' → 0 时,那么 loss → ∞。同样,如果y’→0,那么 loss → 0 而当y’→1**,那么 loss → ∞给定 y = 0 。这意味着当预测错误时,参数会受到严重惩罚,而当预测正确时,参数不会受到惩罚。

在这里,函数简化为ᅳ log( y' )y = 1log(1y ')y = 0 正如我们

虽然以上只是一个例子(数据点)的错误,我们需要考虑所有的例子。因此,我们将所有误差相加,然后除以示例数量,得出误差的平均值,如下所示。

这方面的代码如下:

1.0579769986979133

让我们画出损失图。您将跟踪所有迭代(时期)的损失,之后您将能够可视化误差的减少。

[1.0579769986979133]

梯度下降

这通常是最难理解的部分,但是我用了非常简单的术语。

来源:吉菲

用外行人的话说梯度下降就像走下一座小山。这座山指的是我们的错误。误差越大,山越高!!所以当你滚下山的时候,误差( 损失 )就下降了。

来源:吉菲

因此,我们的目标是滚到误差最小的点。

嘿,但是等一下!我该如何改变损失?🤔

现在你必须观察到,如果你调整参数 Wb损耗 也会改变!!

因此,我们找到关于参数W&b的导数(即变化率),并相应地更新它们。

嗯,那就简单了!只要找到它的导数或者斜率。数学上,斜率在极小点(minima)处为 【如果你不了解导数和斜率,可以参考这个精彩的可汗学院视频。]而如果你观察敏锐的话,斜率在极小值左边是负的,在极小值右边是正的。当 p 在最小值的左边时,我们需要增加一些值,以便它向最优值 p 移动,当 p 在右边时,减去一些值。

在我们的例子中,我们找到了 损失 相对于 Wb 的导数。

我跳过了几个不必要的步骤,但是如果感兴趣,你可以参考下面的视频。

更新参数

至于更新参数的最后部分,利用斜率,我们将斜率乘以阻尼因子 α ,使得参数在具有非常高的误差时不会过冲。

您现在将实现与下面相同的gradient_descent算法。

现在还有最后一件事要做,即将两个绘图功能合并为一个。

我们获得了一个美丽的决定边界以及损失的情节。

现在,作为你们的最后一项任务,让我们把你们到目前为止所做的一切汇总起来,自己看看结果。

所以,你首先要定义超参数。您可以摆弄这些值,尤其是学习率l_repoch,以观察模型如何学习预测。

现在,您可以一次性编写从创建数据集到训练逻辑回归模型的代码,如下所示。

Shape of X_train (400, 2) 
Shape of y_train (400, 1) 
Shape of X_test (100, 2) 
Shape of y_test (100, 1) 
Initializing weights... 
W: [[ 0.43753829] [-1.70958537]] 
b: -0.8793505127088026
--------------------------------------------------------------------
Iteration: 0 
W = [[ 0.43753829] [-1.70958537]] 
b = -0.8793505127088026 
Loss = 0.3991070405361789

-------------------------------------------------------------------- Iteration: 5 
W = [[ 0.09634223] [-1.73455902]] 
b = [[-0.87943027]] 
Loss = 0.10346899489337041

--------------------------------------------------------------------Iteration: 10 
W = [[-0.02440044] [-1.73555684]] 
b = [[-0.87945069]] 
Loss = 0.06810528539660123

--------------------------------------------------------------------Iteration: 15 
W = [[-0.09215724] [-1.73617853]] 
b = [[-0.87945614]] 
Loss = 0.0569509026646708

--------------------------------------------------------------------Iteration: 20 
W = [[-0.13607178] [-1.737859 ]] 
b = [[-0.87945457]] 
Loss = 0.05224655857924122

--------------------------------------------------------------------Iteration: 25 
W = [[-0.16649094] [-1.74055496]] 
b = [[-0.87944893]] 
Loss = 0.04996979153280091

预言;预测;预告

我们之前已经创建了一个测试数据集,现在您将根据它测试您的回归模型并确定其准确性。

精确度的公式为:

Prediction: Loss = 0.2929627097697204 Accuracy = 95.0%

Hence W = [[ 3.9538485] [-3.9152981]] b = [[-0.68703193]]

我们已经获得了 95%的准确率,这是相当不错的!

结论

在本教程中,您学习了

  1. Sigmoid 激活函数
  2. 创建逻辑回归模型
  3. 训练逻辑回归模型

在下一篇教程中,您将学习仅使用 Numpy 从头实现神经网络!*

神经结构化学习和对抗正则化

原文:https://towardsdatascience.com/neural-structured-learning-adversarial-regularization-378523dace08?source=collection_archive---------33-----------------------

张量流中用对立正则化提高分类模型的鲁棒性

作者拥有的图像

介绍

正如我们许多人无疑都知道的那样,计算机视觉领域取得的不变进展已经在多个学科领域取得了一些令人难以置信的成就,从医疗保健和自动驾驶汽车,到气候研究和游戏,不一而足。

从最先进的液氮冷却硬件形式的张量处理单元(TPU) 到日益复杂的数百万参数深度卷积网络,如 GoogLeNetAlexNet 这种技术的能力继续打破以前无法逾越的障碍。

对抗性脆弱性

尽管取得了这些令人难以置信的成就,但事实证明,即使是最熟练的模型也不是绝对可靠的。多项研究表明,这些模型对输入数据结构中的微小变化非常敏感。最初是在谷歌和纽约大学的联合研究论文的发现中:“神经网络的有趣特性,2014”模型易受对立例子影响的主题现在被认为是如此重要的主题,以至于现在存在解决它的竞赛

这些错误的存在提出了各种各样的关于样本外泛化的问题,以及如何使用这样的例子来滥用已部署的系统。

神经结构化学习

在某些应用中,这些误差可能不是有意产生的,而且,它们可能是由于人为误差或仅仅是由于输入不稳定而产生的。在采矿业,计算机视觉有无数非常有用的应用,例如,从流式处理工厂传送带图像以预测矿石纯度,到使用卫星图像检测商品库存水平和非法运输/采矿。

我们经常会发现,由于相机未对准、振动或可能导致错误分类的非常独特的样本外示例,此类图像数据在收集过程中遭到破坏。

为了克服诸如此类的例子,并总体上改进我们的模型以对抗损坏或扰乱的数据,我们可以采用一种形式的 神经结构化学习 称为 对抗正则化

神经结构化学习(NSL) 是一个相对较新的开源框架,由 TensorFlow 的优秀人员开发,用于使用结构化信号训练深度神经网络(与传统的单一样本相反)。NSL 实现了神经图形学习,其中使用图形(见下图)训练神经网络,图形携带关于目标(节点)的信息和通过节点边缘连接的其他节点中的相邻信息。

图片来自 TensorFlow 博客:在 TensorFlow 中引入神经结构化学习,2019

这样,这允许训练模型通过以下方式同时利用标记和未标记的数据:

  1. 在标记数据上训练模型(任何监督学习问题中的标准程序);
  2. 偏置网络以学习图上相邻节点的相似隐藏表示(相对于输入数据标签)

图片来自 TensorFlow 博客:神经结构化学习,对抗性例子,2019

与第二点一致,我们可以在上述表达式中观察到经验损失(即监督损失)和邻居损失的最小化。在上面的例子中,这被计算为目标隐藏层内的计算的权重向量与输入、 X、和添加了某种程度的噪声的相同输入之间的距离度量(即,L1、L2 距离)的点积:

典型地,通过计算输出相对于输入的梯度 x_i,然后最大化损失来创建对立的例子。例如,如果您有一个对吉娃娃和松饼进行分类的模型,并且您希望创建对立的示例,您可以将一个 128 x 128 像素的吉娃娃图像输入到您的网络中,根据输入计算损失的梯度(128 x 128 张量),然后将负梯度(扰动)添加到您的图像中,直到网络将图像分类为松饼。通过使用正确的标签再次对这些生成的图像进行训练,网络变得对噪声/干扰更加鲁棒。

为什么用 NSL?

  • 更高的精度:样本间的结构化信号可以提供在特征输入中并不总是可用的信息。
  • 更强的鲁棒性:用对立的例子训练的模型在对抗为误导模型的预测或分类而设计的对立扰动方面明显更强。
  • 需要更少的标记数据 : NSL 使神经网络能够利用标记和未标记的数据,迫使网络学习类似的“邻近样本”的隐藏表示,这些样本可能有也可能没有标记。

对抗性规则

如果没有这样明确的结构作为输入,我们能做什么?

关于 TensorFlows 神经结构化学习库,特别有用的是提供了一些方法,使用户能够通过对抗扰动,从原始输入数据中动态构建诱导的对抗示例作为隐式结构。NSL 的这种一般化被称为对抗正则化,在这种情况下,对抗示例被构造成在训练期间有意混淆模型,从而产生对小输入扰动具有鲁棒性的模型。

实践中的对抗性规范

在下面的例子中,我们将比较基线图像分类模型(特别是卷积神经网络)与利用对抗正则化的变体的性能。不幸的是,我们无法在上述任何采矿数据上演示 AR 的使用,因为这是专有的。

相反,我们将对在著名的图像分类数据集— Beans 上训练的两个模型进行分析。我们将比较基线模型的结果,与一个经过对抗性例子训练的结果,以充分理解对抗性规则对每个模型的能力和性能的影响。

包含本文所用代码的 Colab 笔记本可以在这里找到。一个优秀的教程,这篇文章的灵感和一些代码的来源,可以在 TensorFlow NSL 页面上找到。

在开始之前,我们必须先安装 TensorFlow 的神经结构学习包:

!pip install neural_structured_learning

进口

import matplotlib.image as mpimg
import matplotlib.pyplot as plt
import numpy as np
import keras_preprocessing
import neural_structured_learning as nsl
import tensorflow as tf
import tensorflow_datasets.public_api as tfdsfrom tensorflow.keras import models
from keras_preprocessing import image
from keras_preprocessing.image import ImageDataGenerator

加载和检查图像数据

TensorFlow 在其 TensorFlow 数据集集合中托管了许多著名的数据集。

我们可以使用tfds.load()方法加载我们想要训练模型的 Beans 数据集,该方法执行两个操作:

  1. 下载数据集并将其保存为[tfrecord](https://www.tensorflow.org/tutorials/load_data/tfrecord)文件。
  2. 加载tfrecord文件并返回[tf.data.Dataset](https://www.tensorflow.org/api_docs/python/tf/data/Dataset)的实例
# load dataset
dataset = 'beans' #@paramdataset = tfds.load(dataset, shuffle_files=True)
train, test = dataset['train'], dataset['test']IMAGE_INPUT_NAME = 'image'
LABEL_INPUT_NAME = 'label'

在执行任何图像缩放或图像增强/扰动之前,我们可以检查数据集中的图像样本,以了解卷积层可能作为特征提取的各种结构和组成,并了解数据集中各种类之间的差异:

# Get random batch
raw_images = train.take(10)# Tensor to np format
raw_images = [item['image'] for item in
raw_images.as_numpy_iterator()]# Plot batch
fig = plt.gcf()
fig.set_size_inches(10, 10)
for i, img in enumerate(raw_images):
  sp = plt.subplot(2, 5, i+1)
  sp.axis('Off')
  plt.imshow(img)plt.show()

默认情况下,[tf.data.Dataset](https://www.tensorflow.org/api_docs/python/tf/data/Dataset)对象包含一个由[tf.Tensor](https://www.tensorflow.org/api_docs/python/tf/Tensor)组成的dict,我们可以通过在我们的列表理解中调用raw_images上的.as_numpy_iterator()来迭代这批图像(tf.data.Dataset 键值)。该方法返回一个生成器,该生成器将数据集的批处理元素从tf.Tensor格式转换为np.array格式。然后,我们可以绘制生成的一批图像:

由作者生成的图像:“豆”数据集中的 10 个训练图像的样本批次,描绘了 3 个不同的类别:“健康”、“豆锈病”和“角斑病”

预处理

我们对图像数据执行简单的缩放操作,将输入映射到 0 和 1 之间的浮点张量(Beans 数据集是 500 x 500 x 3 图像的集合)。有益的是,TDFS 数据集将要素属性存储为字典:

FeaturesDict({
    'image': Image(shape=(500, 500, 3), dtype=tf.uint8),
    'label': ClassLabel(shape=(), dtype=tf.int64, num_classes=3),
})

因此,我们可以访问各个图像及其标签,并使用我们的训练和测试tf.Dataset实例的.map()属性就地执行这些预处理操作:

def normalize(features):
  """Scale images to within 0-1 bound based on max image size."""
  features[IMAGE_INPUT_NAME] = tf.cast(
    features[IMAGE_INPUT_NAME], 
    dtype=tf.float32) / 500.0)
  return featuresdef examples_to_tuples(features):
  return features[IMAGE_INPUT_NAME], features[LABEL_INPUT_NAME]def examples_to_dict(image, label):
  return {IMAGE_INPUT_NAME: image, LABEL_INPUT_NAME: label}# Define train set, preprocess. (Note: inputs shuffled on load)
train_dataset = train.map(normalize)
                     .batch(28)
                     .map(examples_to_tuples)test_dataset = test.map(normalize)
                   .batch(28)
                   .map(examples_to_tuples)

功能examples_to_dict将在稍后解释。

基线模型

然后,我们构建一个简单的基线卷积神经网络模型,并使其适合我们的图像数据:

def conv_nn_model(img_input_shape: tuple) -> tf.keras.Model():
  """Simple Conv2D Neural Network.
    Args:
      img_input_shape: An (mxnxo) tuple defining the input image   
      shape.
    Returns:
      model: An instance of tf.keras.Model.
  """
  model = tf.keras.models.Sequential([
      tf.keras.layers.Conv2D(16, (3,3), activation='relu',   
          input_shape=input_shape),
      tf.keras.layers.MaxPooling2D(2, 2),
      tf.keras.layers.Conv2D(32, (3,3), activation='relu'),
      tf.keras.layers.MaxPooling2D(2,2),
      tf.keras.layers.Conv2D(32, (3,3), activation='relu'),
      tf.keras.layers.MaxPooling2D(2,2),
      tf.keras.layers.Flatten(),
      tf.keras.layers.Dense(64, activation='relu'),
      # Note to adjust output layer for number of classes
      tf.keras.layers.Dense(3, activation='softmax')])
  return model# Beans dataset img dims (pixel x pixel x bytes)
input_shape = (500, 500, 3)# Establish baseline
baseline_model = conv_nn_model(input_shape)
baseline_model.summary()baseline_model.compile(
    optimizer='adam',
    loss='sparse_categorical_crossentropy',
    metrics=['acc'])baseline_history = baseline_model.fit(
    train_dataset,
    epochs=5)

我们的基准 Conv2D 模型架构

results = baseline_model.evaluate(test_dataset)
print(f'Baseline Accuracy: {results[1]}')3/3 [==============================] - 0s 72ms/step - loss: 0.1047 - acc: 0.8934 
Baseline Accuracy: 0.8934375

我们可以看到,我们的基线模型在测试数据集上表现良好,达到了 89%的准确率。

对抗正则化模型

我们现在将检查该模型如何针对包括对立干扰示例的测试集执行,并将其与在包括所述示例的数据集上训练的模型进行比较。我们首先创建另一个卷积神经网络模型,只是这一次我们将把对抗性训练纳入其训练目标。

接下来,使用 TensorFlow 的 NSL 框架,我们用 NSL 的助手函数[nsl.configs.make_adv_reg_config](https://www.tensorflow.org/neural_structured_learning/api_docs/python/nsl/configs/make_adv_reg_config)定义一个配置对象:

#@title ADV Regularization Config# Create new CNN model instance
base_adv_model = conv_nn_model(input_shape)# Create AR config object 
adv_reg_config = nsl.configs.make_adv_reg_config(
    multiplier=0.2,
    adv_step_size=0.2,
    adv_grad_norm='infinity')# Model wrapper 
adv_reg_model = nsl.keras.AdversarialRegularization(
    base_adv_model,
    label_keys=[LABEL_INPUT_NAME],
    adv_config=adv_config)

我们可以注意到,这个函数要求我们设置许多超参数。其中一些不需要明确的值,其他的需要我们的输入:

  • **multiplier**:训练中对抗性损失相对于标签损失的权重,w.r.t 我们 AR 模型的目标函数。我们应用 0.2 作为正则化权重。
  • **adv_step_size**:训练中要应用的对抗性扰动的程度/幅度。
  • **adv_grad_norm**:归一化梯度的张量范数(L1 或 L2),即对抗性扰动幅度的测量。默认为 L2。

然后,我们可以使用nsl.keras.AdversarialRegularization函数包装我们新创建的模型,这将把我们之前使用adv_reg_config对象配置的对抗性正则化添加到我们基本模型的训练目标(要最小化的损失函数)中。

在这个阶段需要注意的重要一点是,我们的模型期望它的输入是特性名称到特性值的字典映射。可以看到,当我们实例化我们的对抗性模型时,我们必须将label_keys作为参数传入。这使得我们的模型能够区分输入数据目标数据。这里,我们可以使用我们的examples_to_dict函数,并将其映射到我们的训练和测试数据集:

train_set_for_adv_model = train_dataset.map(convert_to_dictionaries)
test_set_for_adv_model = test_dataset.map(convert_to_dictionaries)

然后,我们正常编译、拟合和评估我们的对抗性正则化模型:

4/4 [==============================] - 0s 76ms/step - loss: 0.1015 - sparse_categorical_crossentropy: 0.1858 - sparse_categorical_accuracy: 0.8656 - scaled_adversarial_loss: 0.1057  accuracy: 0.911625

类似地,我们的对抗性正则化模型很好地推广到我们的测试数据集,达到了与我们的baseline_model相似的精度(0.91%)。

针对不利扰动数据的评估

现在是有趣的部分。

就像我们在测试集上评估一个训练过的模型的能力一样,我们将在我们的两个模型上执行相同的操作。然而,在这种情况下,我们将比较我们的两个模型;基线 CNN,以及已经针对包含对抗性扰动示例的测试数据集对对抗性扰动输入数据进行训练的变体。

为了生成上述示例,我们必须首先创建一个参考模型,其配置(损耗、指标和校准/学习权重)将用于生成扰动示例。为此,我们再次用nsl.keras.AdversarialRegularization函数包装我们的性能基线模型并编译它。请注意,我们并未将该模型应用于我们的数据集,我们希望保留与基础模型相同的学习权重):

# Wrap baseline model
reference_model = nsl.keras.AdversarialRegularization(
    baseline_model,
    label_keys=[LABEL_INPUT_NAME],
    adv_config=adv_reg_config)reference_model.compile(
    optimizer='adam',
    loss='sparse_categorical_crossentropy',
    metrics=['acc']models_to_eval = {
    'base': baseline_model,
    'adv-regularized': adv_reg_model.base_model}metrics = {
    name: tf.keras.metrics.SparseCategoricalAccuracy()
    for name in models_to_eval.keys()}

如果此时你和我一样,喜欢理解这些事情背后的逻辑,你可以在这里找到包含对抗性正则化类源代码

然后我们存储我们的两个模型;字典中的基线和对抗性正则化变量,随后在我们的测试数据集的每一批上循环(成批评估是对抗性正则化模型的一个要求)。

使用我们新包装的reference_model.perturb_on_batch()方法,我们可以生成与我们的adv_reg_config对象一致的对抗性扰动批处理,并在其上评估我们的两个模型的性能:

labels, y_preds = [], []# Generate perturbed batches, 
for batch in test_set_for_adv_model:
  perturbed_batch = reference_model.perturb_on_batch(batch)
  perturbed_batch[IMAGE_INPUT_NAME] = tf.clip_by_value(
      perturbed_batch[IMAGE_INPUT_NAME], 0.0, 1.0)
  # drop label from batch
  y = perturbed_batch.pop(LABEL_INPUT_NAME)
  y_preds.append({})
  for name, model in models_to_eval.items():
    y_pred = model(perturbed_batch)
    metrics[name](y, y_pred)
    predictions[-1][name] = tf.argmax(y_pred, axis=-1).numpy()for name, metric in metrics.items():
  print(f'{name} model accuracy: {metric.result().numpy()}')>> base model accuracy: 0.2201466 adv-regularized model accuracy: 0.8203125

结果

相对于 adv_reg_model,我们的基线模型在对抗扰动数据上的性能显著降低,对抗学习在提高模型稳健性上的有效性立即变得明显。

我们的基线模型的性能下降了 69% 相比于我们的对抗性正则化模型,只实现了 14%的性能下降。

借助 Kera 的 Layers API,我们可以通过可视化卷积层来了解扰动前后提取的特征,从而检查恶意扰动数据对基线模型的影响:

扰动前

*# Random img & conv layer idxs
IDX_IMAGE_1=2
IDX_IMAGE_2=5
IDX_IMAGE_3=10
CONVOLUTION_NUMBER = 10# Get baseline_model layers 
layer_outputs = [layer.output for layer in baseline_model.layers]
activation_model = tf.keras.models.Model(
    inputs =baseline_model.input, 
    outputs = layer_outputs)# Plot img at specified conv
f, axarr = plt.subplots(3,2, figsize=(8, 8))
for x in range(0, 2):
  f1 = activation_model.predict(test_images[IDX_IMAGE_1].reshape(
      1, 500, 500, 3))[x]
  axarr[0,x].imshow(f1[0, : , :, CONVOLUTION_NUMBER],cmap='inferno')
  axarr[0,x].grid(False)
  f2 = activation_model.predict(test_images[IDX_IMAGE_2].reshape(
      1,500, 500, 3))[x]
  axarr[1,x].imshow(f2[0, : , :, CONVOLUTION_NUMBER],cmap='inferno')
  axarr[1,x].grid(False)
  f3 = activation_model.predict(test_images[IDX_IMAGE_3].reshape(
      1, 500, 500, 3))[x]
  axarr[2,x].imshow(f3[0, : , :, CONVOLUTION_NUMBER],cmap='inferno')
  axarr[2,x].grid(False)*

由作者生成的图像:给定卷积层的中间图像表示

我们可以在上面的图像中观察到,我们的基线模型似乎已经确定了定义每个类别的相关区别特征:角叶锈病、健康叶锈病和豆状叶锈病,通过不同的颜色梯度变得可见。

扰动后

现在,我们可以检查基线模型在扰动数据中识别的特征:

*# Pertubed test data
perturbed_images = []
for batch in test_set_for_adv_model:
  perturbed_batch = reference_model.perturb_on_batch(batch)
  perturbed_batch[IMAGE_INPUT_NAME] = tf.clip_by_value(
  perturbed_batch[IMAGE_INPUT_NAME], 0.0, 1.0)
  perturbed_images.append(perturbed_batch)# Get images
pt_img = [item['image'] for item in perturbed_images]IDX_IMAGE_1=0
IDX_IMAGE_2=1
IDX_IMAGE_3=2
CONVOLUTION_NUMBER = 11base_mod_layer_out = [layer.output for layer in baseline_model.layers]base_mod_activ = tf.keras.models.Model(
  inputs = baseline_model.input,
  outputs = base_mod_layer_out)f1 = base_mod_activ.predict(pt_img[IDX_IMAGE_1].numpy())[x]
f2 = base_mod_activ.predict(pt_img[IDX_IMAGE_2].numpy())[x]
f3 = base_mod_activ.predict(pt_img[IDX_IMAGE_3].numpy())[x]*

作者生成的图像:中间图像表示;敌对扰乱数据。

正如我们在上面的表示中所观察到的,网络很难表示每幅图像中的原始像素,并且由于扰动而变得更加抽象。在最右边的图像中,似乎网络成功地保留了代表‘角叶锈病’的特征,但是叶子的基本结构大部分丢失了。当然,这只是我们未经调整的网络中的一个卷积层,但它仍然是一个可信的演示,说明了一个以前熟练的模型是如何被敌对的输入数据推翻的。

结论

在本文中,我们研究了如何使用对抗正则化显著提高卷积神经网络模型在对抗扰动数据上的鲁棒性和泛化性能。此外,我们还探索了:

  • 如何在 Keras 模型中添加对抗性规则?
  • 如何将一个对抗性的规范化模型与一个基线性能模型进行比较?
  • 如何通过可视化中间层来检查敌对扰动数据对传统训练模型的影响。

如果您发现错误或有任何建设性的批评/构建,请评论。

感谢您的阅读。

参考

神经类型转移——一种高级方法

原文:https://towardsdatascience.com/neural-style-transfer-a-high-level-approach-250d4414c56b?source=collection_archive---------20-----------------------

保罗·本丹迪https://unsplash.com/photos/hZUlyk-EeuU

今天我想谈谈神经风格转移和卷积神经网络(CNN)。已经有相当多的文章和教程可用。有时内容只是复制,有些提供了新颖的实现。所有的共同点是快速深入细节。在我看来太具体了。不仅如此,通常还有一些实现细节,这使得从整体上关注主要概念变得更加困难。

这篇文章可以被认为是对其他文章(列在我的“灵感”部分)的概述和理解,在更高的层次上理解这个概念。我的意图是去掉一些实现细节,对初学者来说足够高,并激发阅读原始研究论文和后续实现的好奇心。

目录

放弃

我与本文中使用的任何服务都没有关联。

我不认为自己是专家。如果你觉得我错过了重要的步骤或者忽略了什么,可以考虑在评论区指出来或者联系我。

我总是乐于听取建设性的意见以及如何改进。

这篇文章写于 2020 年 10 月 17 日。我无法监控我的所有文章。当你阅读这篇文章时,提示很可能已经过时,过程已经改变。

如果你需要更多关于某些部分的信息,请在评论中指出来。

要求

我假设理解卷积神经网络(CNN)。架构对于计算机视觉和深度学习中的许多事情都非常关键。网上有很多可用的资源。作为复习,我建议这篇文章

神经类型转移

研究论文一种艺术风格的神经算法——Leon A . Gatys,Alexander S. Ecker,Matthias Bethge

在美术中,尤其是绘画,人类已经掌握了通过在图像的内容和风格之间构建复杂的相互作用来创造独特视觉体验的技能。到目前为止,这个过程的算法基础还是未知的,也不存在具有类似能力的人工系统。然而,在视觉感知的其他关键领域,如物体和人脸识别,最近一类被称为深度神经网络的生物启发视觉模型展示了接近人类的表现。在这里,我们介绍一个基于深度神经网络的人工系统,它可以创建高感知质量的艺术图像。

该系统使用神经表示来分离和重组任意图像的内容和风格,为艺术图像的创建提供神经算法。此外,鉴于性能优化的人工神经网络和生物视觉之间惊人的相似性,我们的工作提供了一条通往人类如何创造和感知艺术意象的算法理解的道路。

架构和流程概述

对于 CNN 如何处理神经类型转移,有许多很好的可视化。本来想自己画的,后来发现已经有很好看的了。所以我只展示这些并引用创建者。

以下是我认为很棒的。

首先是这个。它非常漂亮地展示了损失是如何计算的,以及它是如何在总体结果中组合在一起的。

来自迈克·高斯的博客的知识共享许可

这个也不错。示出了不同层上的重建过程。

来自 arxiv 许可要求下的原始研究论文

为了理解随后的计算,有必要说一下 CNN 的不同层代表什么。

  • CNN 的较浅层倾向于检测较低级别的特征,例如边缘和简单纹理。
  • 更深的层倾向于检测更高级的特征,例如更复杂的纹理以及对象类别。

因为生成的图像应该具有与输入图像相似的内容。建议在中间使用一个层,高度表示内容。

研究论文中的 VGG19 架构使用深度卷积神经网络和 SVM 分类器知识共享许可进行乳房自动肿块检测

迁移学习与风格迁移

另一个重要的概念是使用预先训练的网络。最常见的是 VGG-19。值得注意的是,我们利用了所谓的“迁移学习”。

这里我们有两个概念需要区分:

  1. 迁移学习
  2. 风格转移

尽管两者都使用了“传输”这个词,但从实现的角度来看,它们是完全不同的。

1.迁移学习

这个概念本身非常有趣,并且可以通过使用已建立的模型来创建新的解决方案。

精彩的介绍,我可以推荐这篇文章:https://machine learning mastery . com/transfer-learning-for-deep-learning/

理解它在风格转换的概念中是如何使用的是至关重要的。

简而言之,我们可以说

迁移学习和领域适应指的是这样一种情况,在一种环境中所学的知识被用来提高在另一种环境中的概括能力

这在计算机视觉中特别有用,因为这些模型的计算和训练非常耗费资源。使用一个在大型数据集上训练过的模型,其结果现在可以免费获得,实际上非常适合个人实验。

您可以将迁移学习用于:

  1. 直接使用预先训练的模型
  2. 预训练模型的特征提取
  3. 改变预训练模型的最后一层的权重

在我们的例子中,我们将使用第二种方法。使用特征提取,其中来自输出层之前的层的模型输出被用作新分类器的输入。

2.风格转移

来自原始论文:

概念上最密切相关的是使用纹理转移来实现艺术风格转移的方法。然而,这些先前的方法主要依赖于非参数技术来直接操纵图像的像素表示。相比之下,通过使用在对象识别上训练的深度神经网络,我们在明确表示图像的高级内容的特征空间中执行操作。

因此,这意味着深度学习方法的专长是提取图像的风格,而不是仅仅通过风格图片的像素观察,而是结合风格图像的内容提取预训练模型的特征。所以,本质上,为了发现图像的风格,我们

  1. 通过分析样式图像的像素来处理样式图像
  2. 将该信息馈送到预训练模型的层,以“理解”/将所提供的输入分类为对象

如何做到这一点,我们将在“风格成本”一节中探讨。

风格和内容

基本思想是将图像的风格转换为图像的内容。

因此,我们需要理解两件事:

  1. 图像的内容是什么
  2. 图像的风格是什么

不严格地说,图像的内容就是我们人类在图像中识别的对象。汽车、桥、房子等。风格更难定义。这很大程度上取决于形象。就是整体质感,选色,对比等。

这些定义需要以数学方式表达,以便在机器学习的世界中实现。

成本计算

一、为什么要进行成本/损失计算?重要的是要明白,在这种情况下,成本仅仅是原始图像和生成图像之间的差异。关于如何计算它有多种方法(MSE、欧几里德距离等)。通过最小化图像的差异,我们能够传递风格。

当我们开始在损失上有很大差异时,我们会看到风格转移并不是那么好。我们可以看到风格的转移,但这似乎是粗糙和不直观的。随着成本最小化的每一步,我们都朝着更好地融合风格和内容的方向前进,最终得到更好的图像。

正如我们所看到的,这个过程的核心要素是损失计算。需要计算 3 项成本:

  1. 内容成本
  2. 风格成本
  3. 总(变动)成本

在我看来,这些步骤是最难理解的,所以让我们一个一个地深入研究。

请始终记住,我们是在将原始输入与生成的图像进行比较。这些差异就是成本。我们希望将这一成本降至最低。

理解这一点非常重要,因为在这个过程中还会计算其他差异。

内容成本

什么是内容成本?正如我们之前发现的,我们通过图像的对象来定义图像的内容。我们人类能够识别的事物。

了解了 CNN 的结构后,现在很明显,在神经网络的末端,我们可以访问一个层,它很好地代表了对象(内容)。通过池层,我们失去了图像的风格部分,但就获取内容而言,这是所期望的。

现在,在不同物体的存在下,CNN 的更高层中的特征地图被激活。因此,如果两幅图像具有相同的内容,它们在较高层中应该具有相似的激活。

这是定义成本函数的前提。

下图有助于理解图层是如何展开的,以便为计算做准备(本文不涉及):

来自阿迪蒂亚·古普塔斯的文章麻省理工学院的许可下

风格成本

现在它变得越来越复杂。

一定要理解图像的风格和图像的风格损失之间的区别。两种计算都不一样。一个是检测“风格表示”(纹理、颜色等),另一个是将原始图像的风格与生成图像的风格进行比较。

总样式成本分两步计算:

  1. 所有卷积层的样式开销。识别样式图像的样式

a.从卷积层获取特征向量

b.将这些向量与另一层的特征向量进行比较(找出其相关性)

2.原之间的风格成本(原风格形象!)和生成的图像。

为了找到风格,通过将特征图与其转置相乘来捕捉相关性,从而得到 gram 矩阵。

来自Aditya Gupta 的文章麻省理工学院的许可下

幸运的是,CNN 为我们提供了多个层次,我们可以选择找到正确的风格。比较不同的层和它们的相互关系,我们可以识别图像的风格。

因此,我们不使用层的原始输出,而是使用单个层的特征图的 gram 矩阵来识别图像的风格。

第一个成本是这些 gram 矩阵之间的差异,即相关性的差异。第二个成本也是原始图像和生成图像之间的差异。这实质上是“风格转移”。

总变动成本

它的作用就像一个正则化器,可以提高生成图像的平滑度。这在原始论文中没有使用,但是改进了结果。本质上,我们在生成的图像中消除了风格和内容传递之间的差异。

灵感

本节提供了撰写本文时使用的阅读材料。这是一个与风格转移相关的文章选集。

代码实现:

研究论文:

关于

丹尼尔是一名企业家、软件开发人员和商业法毕业生。他曾在各种 IT 公司、税务咨询、管理咨询和奥地利法院工作。

他的知识和兴趣目前围绕着编程机器学习应用程序及其所有相关方面。从本质上说,他认为自己是复杂环境的问题解决者,这在他的各种项目中都有所体现。

如果您有想法、项目或问题,请不要犹豫与我们联系。

你可以在 https://www.buymeacoffee.com/createdd上支持我

连接到:

神经风格转移:乐队作为他们的专辑封面

原文:https://towardsdatascience.com/neural-style-transfer-bands-as-their-album-covers-64a1dd12b71e?source=collection_archive---------80-----------------------

上帝保佑你!计算机视觉模型

我们头脑中的热芯片+通过神经类型转移(第一帧致谢:立体树胶/热芯片)

最早在 Gatys et al. (2015) 提出的神经风格迁移方法,已经被广泛讨论和复制。这是一项非常酷的技术,通过这种方式可以将两幅图像组合在一起,从而保留一幅图像的大部分内容,同时向另一幅图像的风格移动。这使得创建两个图像的混合图像成为可能,人类将很难预先想象这两个图像,但是当该方法工作良好时,一旦人们看到它们,这两个图像就很有意义(即,“如果以 B 的风格完成,那IsAA看起来会是什么样子”)。**

我尝试了一下,按照 Keras 文档中的例子,使用 VGG16 卷积模型的中间层来计算图片在内容和风格上的相似性。我强烈推荐这篇文章,它展示了部分算法的改变如何影响结果。Keras 的例子在这方面已经做好了准备。我试验了内容、风格和总变化损失的相对权重,以及用于内容损失的层,但主要是我在这里利用了其他人已经完成的关于风格转移的探索工作。

对于我尝试的任何参数值来说,找出“什么有效”作为样式图像是很有趣的。该方法理想地适用于绘画风格,其由调色板和笔触技术的组合组成,后者被视觉捕捉并被模型捕捉为图像中的一个或多个中等大小的形状或结构。对于非绘画图像,如果图像太详细(太多的颜色或太小比例的图案),这种方法就不好用了。要成功定义一种风格,图像需要有某种重复的结构和/或独特的配色方案。

我实现了这个算法,将我最喜欢的专辑的封面作为风格图像,将他们各自的艺术家作为内容图像,来重新设计乐队作为他们专辑封面的风格。在某些情况下,这非常有效。这里说明了这个想法:拍摄一个标准的 Go 波段图像!团队作为内容,并添加 的封面、雷霆、闪电、 的封面作为风格,使用 TLS 封面的调色板和一些结构方面,得到的结果不再是照片,而是乐队的“艺术家印象”:

**

图片鸣谢:1songday.com;维基百科等。

我的原始结果!团队+雷霆,闪电,打击

在这种情况下,也许不太清楚这张照片现在是不是相册封面的“风格”;相反,这只是一个我们以前没有想象过的新形象。在其他示例中,风格可以更容易地被描述,并且更明显地被转移到内容图像。

这种技术有很多很好的选择。我尝试了其中的一些,这里有一些效果不错的例子。我非常喜欢制作这些,所以我建立了一个网站来展示当前的一批和未来的补充:乐队作为专辑封面

这是 Idlewild 主唱罗迪·温布尔的风格 偏远地区 :

奥马尔和安凯臣从汽车电影院出来,按 的关系指挥 :

我真的很喜欢这首:祝你好运!黑皇,以 的风格,抬起瘦骨嶙峋的双拳像天线一样指向苍天 :

这里使用了较高的内容权重来保留带的轮廓,因为红线样式相对较强。

以下是在 滑道太窄 : 的缤纷世界中玩耍的小腿

Joy Division 的 任逍遥的 显然是这种技术的候选,正如所料,它工作得非常好:

这就好像乐队正在消失在电波信号中。

爱尔兰歌手丽莎·汉尼根,穿着针织风格的 海缝 :

她在麦克风前拿着一把尤克里里琴,但内容图像的细节被样式强烈修改了。

在户外玩耍的 Sigur Ros,被val tari:的绿霾追上

最后,我最喜欢的,如上图所示,由我们头脑中的**:参差不齐的颜色构成的热薯片**

还值得展示一个内容权重更高的版本,它保留了乐队的面孔,让人想起电咖 中的发电厂乐团。

基于 VGG 模型的神经风格迁移

原文:https://towardsdatascience.com/neural-style-transfer-using-vgg-model-ff0f9757aafc?source=collection_archive---------18-----------------------

一种采用不同图像风格的数字图像变换技术

简介:

在我们开始之前,让我们去这个网站获取一些灵感。在网站上,我们从本地计算机中选择一张照片(假设图片名为 Joey.jpg)。我们姑且称之为内容图像。然后,我们选择另一个图像,说风格图像命名为 style1.jpg 从本地计算机。该网站所做的是生成一个混合图像,它保留了内容图像的轮廓,并将样式图像的纹理和颜色模式添加到内容图像中。以下是结果。

左:原始图像,右:风格图像,中间:混合图像

描述:

这被称为神经风格转移(NST),通过使用深度学习,具体来说是卷积神经网络(CNN)来完成。我想你对 CNN 很熟悉。如果没有,我会强烈推荐 CNN的吴恩达课程。

让我们借助下面的流程图来理解 NST 的基础知识。它显示了具有 13 个卷积层的样式转移算法(为简单起见,仅显示了几个)。两个图像被输入到神经网络,即内容图像和风格图像。我们的目的是生成一个混合图像,它包含内容图像的轮廓和样式图像的纹理、颜色模式。我们通过优化几个损失函数来做到这一点。

内容图像的损失函数最小化在一层或多层上为对应于混合图像(最初只是逐渐改善的噪声图像)的内容图像激活的特征的差异。这将内容图像的轮廓保留到合成的混合图像中。

而风格图像的损失函数最小化了风格图像和混合图像之间的所谓 Gram 矩阵之间的差异。这是在一层或多层完成的。Gram 矩阵的用途是识别在给定的层上哪些特征被同时激活。然后,我们模仿同样的行为,将其应用于混合图像。

使用 TensorFlow,我们将内容和风格图像的这些组合损失函数的梯度更新到令人满意的水平。Gram 矩阵的某些计算,存储效率的中间值,图像去噪的损失函数,归一化组合损失函数,使得两个图像相对于彼此缩放。

编码:

现在我们已经理解了算法,让我们开始编码。原纸用的是 VGG-19 型号。但是这里我们将使用公开的 VGG-16 模型。从这里下载 VGG-16 模型(请记住是~550MB 文件)。

在根目录下,新建一个文件夹,命名为 vgg16 ,将上面的文件和 Github 链接中的 vgg.py 粘贴过来。此外,我们通过注释掉 maybe_download 函数修改了 vgg16.py 文件(因为您已经下载了 vgg16.tfmodel 文件)

让我们先导入库。然后导入 vgg16 型号。

让我们为图像操作定义几个辅助函数。

load_image 加载一个图像并返回一个 numpy 浮点数组。图像被调整到最大高度或宽度。

save_image 将图像保存为像素值在 0 ad 255 之间的 jpeg 文件

plot_image_big 绘制更大的图像。

plot_images 绘制内容、样式和混合图像。

接下来,我们将定义在 Tensorflow 中用于优化的损失函数。

mean_squared_error 运算将返回一个张量,即两个输入张量之间的均方误差(MSE)差。

create_content_loss 将计算内容和混合图像之间的 MSE。损失被最小化,使得内容的激活特征与混合图像相似,从而将轮廓从内容图像转移到混合图像。

接下来,我们的动机是捕捉混合图像的风格特征。为了做到这一点,我们将做一些类似的事情,即测量哪些功能同时激活的风格层,并复制这个模式到混合图像。一种有效的方法是计算 Gram 矩阵。Gram 矩阵本质上是特征激活层向量的点积。如果矩阵中的条目具有较小的值,则意味着给定层中的两个特征不会同时激活,反之亦然。

让我们首先将计算文法矩阵定义为 gram_matrix ,然后是 create_style_loss ,它计算 gram 矩阵的 MSE,而不是两个原始张量(正如我们在 create_content_loss 中所做的)。

为了减少合成混合图像中的噪声,我们使用一种称为“全变差去噪”的去噪滤波算法,使用以下代码。

下一段代码是核心。我们将定义计算损失函数梯度下降的风格转移算法。该算法使用归一化,使得损失值等于一,这有助于选择独立于内容和样式层的损失权重。

首先,我们将载入我们希望包含在混合图像中的具有轮廓特征的内容图像。在这里,我把它命名为 1.jpg

现在,我们将加载我们希望其颜色和纹理出现在混合图像中的样式图像。

此外,我们将定义我们想要匹配内容图像的层索引。通常是刚开始几层。VGG-16 中的第 5 层(指数为 4)似乎工作良好。类似地,样式图像的层索引。通常,它位于总图层的末尾。这里我们将定义第 13 层。

执行的最后一部分是将样式转换应用于我们定义的内容和样式图像。根据定义,它自动为内容和样式层创建损失函数,并根据迭代次数执行优化。最后,显示混合图像。

结果:

这个过程可能在 CPU 上运行缓慢(我用的是 CPU)。看看给出什么结果。

结论:

还不错!结果证明了组合两个图像的基本思想。他们并不像这些技术的先驱迪帕克那样不相上下。也许更多的迭代、更小的步长、更高分辨率的图像、变化的样式和内容层索引或者更高的计算能力会提高混合图像的质量。

感谢您朗读这篇文章。希望有帮助。

你可以在这个链接找到 github repo。

参考:

[1] Hvass-Labs,TensorFlow 教程#15 Style Transfer (2018),来源

张量流中枢神经式传递

原文:https://towardsdatascience.com/neural-style-transfer-with-tensorflow-hub-dfe003df0ea7?source=collection_archive---------22-----------------------

我不会画画,但是机器学习可以…

阿德里安娜 geoUnsplash 拍摄的照片

介绍

我不是艺术鉴赏家,但上面这幅画看起来不错。

我也不是画家,但在本文结束时,我将创建一个与上面的图像具有相似绘画风格的图像。

本文将涵盖以下内容:

  • 神经类型转移的描述
  • 神经类型转移如何工作
  • 样式传递的代码实现

对于热心的读者,请随意向下滚动到 *code* 部分。

什么是神经类型转移

神经风格转移(NST)是一种涉及利用深度卷积神经网络和算法从一幅图像中提取内容信息并从另一幅参考图像中提取风格信息的技术。在提取样式和内容之后,生成组合图像,其中所得图像的内容和样式源自不同的图像。

NST 是一种图像风格化的方法,这是一种涉及使用输入参考图像来提供具有从输入图像导出的风格差异的输出图像的过程。

NST 技术出现在 Leon A Gatys 等人的论文“艺术风格的神经算法”中。

它是如何工作的

深度神经网络(DNN),更具体地说,卷积神经网络(CNN)具有一个至关重要的特征,即能够学习图像内内容和风格的空间表示。这一特性使得 NST 技术成为可能。

由 CNN 生成的输入图像的空间表示捕获了图像的风格和内容的统计信息。NST 将提取的样式和内容组合成一个生成的输出图像。

CNN 层结构内的中间层中的激活功能提供了捕获输入图像的内容和风格统计信息的能力。

在卷积操作之后,CNN 图层输出一个特征图,卷积操作包括在输入图像上滑动一个过滤器。一幅图像的内容其实就在生成的每一层的特征图之内。

从中间层的特征图中提取内容将提供输入图像的高级结构和几何信息。

特征图获得输入图像的风格。为了获得图像的风格,需要评估中间层中特征图的均值和相关性。该过程提供的信息提供了输入图像的纹理图案信息。

风格和内容重建

密码

精彩的部分来了。

我们将创建一个图像的内容和下面的图像风格。

左:内容图片(在 Unsplash 上由斯特凡·斯特凡·基克拍摄),右:风格图片(在 Unsplash 上由阿德里安娜·吉奥拍摄)

为了使用两个参考图像成功实现神经类型转移的过程,我们将利用 TensorFlow Hub 上的模块

TensorFlow hub 提供了一套可重用的机器学习组件,如数据集、权重、模型等。

对于本文的实现部分,我们将利用一系列工具和库来加载图像和执行数据转换。

  • TensorFlow :机器学习模型的实现、训练、部署的开源平台。
  • Matplotlib :用于在 Python 中创建可视化绘图的工具,如图表、图形等
  • Numpy :启用数组数据结构的几种数学计算和运算。
  • tensor flow Hub:模型、数据集等可重用机器学习组件的库

我们将使用 Jupyter Notebook 进行代码实现。本文末尾还包含了一个到笔记本 Github 资源库的链接。

首先,我们将导入所需的工具和库。

import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
import PIL.Image
import tensorflow_hub as hub

接下来,我们声明两个变量,保存输出结果的内容和样式的图像的目录路径。此外,我们将显示图像。

content_path = 'images/human.jpg'
style_path = 'images/painting.jpg'content_image = plt.imread(content_path)
style_image = plt.imread(style_path)plt.subplot(1, 2, 1)
plt.title('Content Image')
plt.axis('off')
imshow(content_image)plt.subplot(1, 2, 2)
plt.title('Style Image')
plt.axis('off')
imshow(style_image)

内容和风格图像

要求将图像转换成张量表示。下一步,我们将利用 TensorFlow 的图像处理方法。

我们将创建一个接受图像路径的函数,然后使用“tf.io.read_file”将图像转换为张量。我们进一步使用“tf.image.decode_image”将张量中值的数据类型更改为介于 0 和 1 之间的浮点数。

def image_to_tensor(path_to_img):
    img = tf.io.read_file(path_to_img)
    img = tf.image.decode_image(img, channels=3, dtype=tf.float32)

    # Resize the image to specific dimensions
    img = tf.image.resize(img, [720, 512])
    img = img[tf.newaxis, :]
    return img

需要与上述相反的实现来可视化 TensorFlow Hub 模块的结果。我们需要将返回的张量转换成我们可以可视化的图像。

我们只是通过将每个元素乘以 255,将包含 0 和 1 之间的值的张量反规格化为实际像素值。下一步是使用 Numpy 创建一个数组,其中包含我们需要的适当数据类型。

我们从张量返回一个图像对象。

def tensor_to_image(tensor):
    tensor = tensor*255
    tensor = np.array(tensor, dtype=np.uint8)
    tensor = tensor[0]
    plt.figure(figsize=(20,10))
    plt.axis('off')
    return plt.imshow(tensor)

到目前为止,我们已经完成了以下工作:

  • 查看内容和样式图像参考
  • 创建一个函数,将图像转换为张量,并将张量转换为图像

现在我们将把图像转换成张量,并通过。TensorFlow Hub 包中的 load()'方法。

我们期望从我们的参考图像中得到样式和内容的组合结果;因此,我们将创建一个变量来保存模块的操作结果。

为了可视化结果,我们只需利用我们之前创建的“张量到图像”函数。

content_image_tensor = image_to_tensor(content_path)
style_image_tensor = image_to_tensor(style_path)hub_module = hub.load('[https://tfhub.dev/google/magenta/arbitrary-image-stylization-v1-256/2'](https://tfhub.dev/google/magenta/arbitrary-image-stylization-v1-256/2'))
combined_result = hub_module(tf.constant(content_image_tensor), tf.constant(style_image_tensor))[0]
tensor_to_image(combined_result)

神经类型转移结果

结论

我们已经成功地结合了两个参考图像的风格和内容,并生成了一个网格图像。

接下来,我建议你更详细地探讨神经类型转移的话题。

下面是一个 GitHub repo 的链接,它提供了本文中的代码。

[## Richmond alake/tensor flow _ 2 _ 教程

github.com](https://github.com/RichmondAlake/tensorflow_2_tutorials/blob/master/03_neural_style_transfer.ipynb)

我建议您探索的另一个主题是图像分类。下面是一篇文章的链接,其中我介绍了如何使用 TensorFlow 和 Keras 实现图像分类。

[## 使用 TensorFlow 2.0 进行(深入)机器学习图像分类

理解实现用于图像分类的神经网络的过程。

towardsdatascience.com](/in-depth-machine-learning-image-classification-with-tensorflow-2-0-a76526b32af8)

NeurIPS 2019 亮点

原文:https://towardsdatascience.com/neurips-2019-highlights-part-1-cc4acc46f8c2?source=collection_archive---------21-----------------------

我在最大的机器学习大会上学到的总结。

温哥华会议中心海滨景色[图片由本人拍摄]

NeurIPS 2019 有 13000 名参与者,1428 篇被接受的论文(来自 6743 篇提交的论文),58 场研讨会,16K 页的会议记录,是我参加过的最具影响力也是最有成效的会议之一。主席们在“我们从 NeurIPS 2019 数据中学到了什么”上展示了一份精彩的会议数据分析。

考虑到会议的规模,要涵盖所有的曲目、演讲和海报几乎是不可能的。在这篇文章(以及后续文章)中,我将从我个人的角度提供一些大会的亮点。

1.专题讲座:

Yoshua Bengio | 从系统 1 深度学习到系统 2 深度学习
Vivienne Sze | 深度神经网络的高效处理:从算法到硬件架构
Celeste Kidd |如何知道
Mohammad emti yaz Khan |深度学习与贝叶斯原理
Blaise Aguera y Arcas |

从系统 1 深度学习到系统 2 深度学习 ( 幻灯片 ): Yoshua Bengio 的演讲是大会最受欢迎的主题演讲。Yoshua 对深度学习的现状及其未来提供了一个奇妙的见解。受《思考 、快与慢 这本书的启发,他提出了一条从深度学习擅长的系统 1 (直觉、快速无意识非语言、习惯性决策/推理)到其未来的系统 2 (缓慢、逻辑、顺序、有意识、语言、算法、决策)的路径。他将意识(以及 注意力 作为其关键成分)作为系统 2 的基础,以稀疏因子图作为意识先验,以元学习作为理论框架,将深度学习从系统 1 扩展到系统 2。

系统 1 与系统 2 学习[图片取自 Yoshua Bengio 的幻灯片

深度学习与贝叶斯原理 ( 幻灯片 ): 深度学习贝叶斯学习被认为是两个完全不同的领域,经常在互补的设置中使用。Emtiyaz Khan 在他的演讲中介绍了现代贝叶斯原理来弥合这一差距,通过结合它们的优势来解决具有挑战性的现实世界问题。

贝叶斯 vs 深度学习[图片取自https://emtiyaz.github.io/papers/neurips_tutorial.pdf

我们可以使用贝叶斯原则作为一般原则,通过计算后验近似来设计、改进和推广一系列学习算法。我们可以将现有的算法(例如 Adam optimizer)作为特例,或者设计新的深度学习算法,用于不确定性估计、小数据集上的推广和终身学习。训练贝叶斯神经网络特别是后验近似仍然是一个具有挑战性和计算昂贵的问题。因此,可以使用近似方法,如变分推论 (VI)。

进一步阅读可以参考论文“实用深度学习与贝叶斯原理”、“变分推理的自然梯度下降”、“概率方法—变分推理”。PyTorch 实现也是一个即插即用的优化器。

2.趋势:

下图显示了 NeurIPS 2019 所有已接受论文标题的最常用标记(单词)的单词云(经过一些预处理,如删除自定义停用词,如“neural”&“network”)。获取标题和令牌频率的代码可以在 Github 上找到。

论文标题中最常见标记的词云和频率图—neur IPS 2019[源代码可在此处获得

最常用的 10 个词如下:优化、强化、对抗、图、高效、随机、最优、生成、贝叶斯。我对以下关键词进行了进一步分析:优化、强化学习、对抗、图形、生成和贝叶斯神经网络(代码可在此处找到),发现了一些有趣的结果:

按主题分类的论文标题中最常见标记的词云—neur IPS 2019[源代码可在此处获得

从我的角度来看(基于会议出席人数和上述数据),以下主题是会议的趋势:

  • 强化学习 : RL 仍然是人工智能会议中最热门的话题之一。彼得·阿比尔等人的深度强化学习工作坊。艾尔。Katja Hofmann 的教程强化学习:过去、现在和未来的观点 ( 幻灯片)是今年 Neurips 最受欢迎的课程之一。最近受到很多关注的一个非常有趣的话题是 多智能体 RL (MARL) 在复杂的环境中,多个智能体相互竞争和/或协调以实现一个目标。The Nature paper, 星际争霸 2 中的特级大师级使用多智能体强化学习 ,是 DRL 工作坊的重头戏。Katja Hofmann 在她的演讲中概述了我们目前所处的位置,以及对未来研究和 RL 实际应用的关键机会的展望。关于 MARL 的介绍可以在这篇博客文章中找到,关于这个主题的论文的完整列表可以在蓝涛宇的报告中找到。
  • 对抗网络:gan 为知识获取提供了一个很好的机制,然而,它们也可以被用作对抗例子来产生对 DNN 模型的攻击(例如,来自攻击者的对抗输入可以在训练图像中引起难以察觉的变化来欺骗分类模型)。评估深度学习模型针对这种攻击的对抗性 健壮性 一直是 OpenAI、Google 和 IBM 等 AI 巨头(例如 IBM 的对抗性健壮性工具箱)的优先事项,并且不出所料是该领域的主导话题。
  • 新增****贝叶斯深度学习:请参考第一节 深度学习与贝叶斯原理
  • 图形神经网络:在这次 NeurIPS 大会上,图形几乎无处不在。图是非常强大的非欧几里得数据结构,可以表示对象之间的复杂关系和相互依赖性。因此,大量应用(如社交网络、物理科学、化学、电子商务、知识库、推荐系统和组合问题)中的数据可以用图来表示。图的不规则结构(可变大小和节点的无序邻居集)使得对它们执行诸如卷积的操作具有挑战性。因此,人们对图形神经网络(GNNs) 算法越来越感兴趣,以便推广深度学习方法,如针对图形数据的 CNN、RNNs 和自动编码器。gnn 可以分为四类:递归图神经网络、卷积图神经网络(cgnn)、图自动编码器和时空图神经网络,目前 cgnn 的权重最大。

左边的 2D 卷积与右边的图卷积(节点的邻居是无序的,大小可变)的比较[图片取自本文]。

要了解更多关于 GNNs 的知识,可以看看关于图神经网络的温和介绍的帖子或者下面的调查论文:
关于图神经网络的全面调查
Stanford SNAP 的图神经网络教程
图神经网络:方法和应用回顾
本次回购中还收集了一份不错的 GNN 论文清单。图不仅可以用作数据结构,还可以表示神经网络的输出,例如,任何联合分布都可以表示为因子图,正如 Yoshua Bengio 在他的特邀演讲中所指出的。

3.新方向奖:

杰出新方向论文奖授予了 Vaishnavh Nagarajan 和 j .济科·科尔特的统一收敛可能无法解释深度学习中的泛化(幻灯片博客代码)。

深度学习理论中最大的公开挑战之一是泛化难题,因为深度网络模型(与经典学习理论相反)尽管存在严重的过度参数化,但仍能很好地泛化。为了解释这种反直觉的行为,理论工作试图推导出深度网络的泛化差距(模型在训练数据和来自同一分布的未看到的数据上的表现之间的差距)的上限。这项工作退一步说,追求一致收敛为基础的界限可能不会真正导致我们对这个难题的完整解决方案。特别地,它表明 1)理论泛化界限随着训练集大小而增长(而经验差距减小),以及 2)任何类型的一致收敛界限将被证明无法解释深度学习中某些情况下的泛化。

4.车间

在为期 3 天的 54 场研讨会中,以下是最受与会者欢迎的研讨会:

深度强化学习
图形表征学习
元学习 ( 大卫·阿贝尔笔记,第 4 节,对本次工作坊有个牛逼的总结)
贝叶斯深度学习
生物和人工强化学习
用 ML 应对气候变化
以及对对话式 AI 感兴趣的人

关于与 ML 一起应对气候变化的研讨会[图片来自 Paul Save 的推特 ]

5.民众

在会议期间的 28 个演示中,以下是我个人最喜欢的(有些偏向 NLP):
ex BERT:一个解释 BERT 的学习表示的可视化分析工具
Streamlit, 机器学习工具的新应用程序框架
allenlp 解释器:解释 NLP 模型的预测
密码:人类和人工智能代理之间的合作猜字游戏
趣味演示: 机器人辅助梳头旋律吃角子老丨虎丨机 互动音乐系统、 与人工智能化身的一对一健身训练

6.社区、社交和聚会:

NeurIPS 2019 强调多样性和包容性。有 15 次正式的社交聚会把有共同兴趣的人聚集在一起。此外,与会者通过大会的官方移动应用程序(Whova)交流了大量信息。例如,有超过 300 个聚会由参与者组织和(几乎)无数的主题讨论!!

AI 名人:

看到一些人工智能名人并与他们交谈是非常令人兴奋的,因为他们非常热情和谦逊:)

我和艾名人[图片由我自己]

8.其他摘要:

奇普·胡延的惊人之帖:来自 NeurIPS 2019 的关键趋势
大卫·阿贝尔的牛逼 NeurIPS 2019 笔记 (70 页)
罗伯特·兰格的优美手记

9.相关链接

神经元,激活函数,反向传播,历元,梯度下降:这些是什么?

原文:https://towardsdatascience.com/neurons-activation-functions-back-propagation-epoch-gradient-descent-what-are-these-c80349c6c452?source=collection_archive---------32-----------------------

如果你听到像深度学习、神经网络、激活函数、梯度下降、纪元这样的术语,但不知道它们真正的意思,那么这篇文章就是为你准备的。本文是对深度学习的介绍,其中您将了解什么是神经网络,它们如何学习,激活函数的类型,以及深度学习与机器学习的区别。让我们开始吧。

克里斯托夫·高尔在 Unsplash 上拍摄的照片

深度学习:为什么是现在

深度学习和神经网络自 80 年代以来就已经存在,但由于缺乏强大的处理能力和数据,直到最近才出现大的飞跃。回到 80 年代或 90 年代,存储内存有限且昂贵,这意味着我们无法加载大量数据进行处理。此外,CPU 和 GPU 非常昂贵,负担不起。如今,只需几美元,你就可以在 AWS 或 GCP 或 Azure cloud 上安装一个高端 NVIDIA GPU 和几千兆字节的内存。

直到最近,处理能力和内存还不足以进行深度学习。来源

为了让你知道 CPU 和内存有多贵,看看这些 90 年代中期的广告就知道了。2000 多美元的 16MB 内存和 120MHz CPU 是 90 年代中期的顶级产品。现在,在亚马逊或当地的百思买上查找 GPU 和内存,看看有多大的存储和强大的处理器可以以非常实惠的价格提供。

深度学习:它是什么

深度学习基于神经网络,它们旨在模仿人类大脑,这是地球上最强大的工具。

深层与浅层神经网络。来源

这些神经网络由许多神经元组成,它们有一个输入层、一个输出层和隐藏层。每个输入、输出或隐藏节点是一个神经元,具有一个 激活函数 ,用于神经网络学习。我们将在本文后面讨论他们是如何学习的。

隐藏层越多,神经网络就越深。关于是什么使神经网络变浅和变深有不同的观点,但是拇指的作用是隐藏层越多,神经网络就越深,很少有隐藏层(有人说 2 或 3 层)使它变浅。

在学习时,这些神经元将具有不同的权重,这些权重在学习期间被调整。神经元的权重调整是学习的结果。使用 反向传播梯度下降 来调整权重,这将在本文的后面介绍。

深度学习与机器学习

深度学习是机器学习的一个子集, 每一个深度学习算法都被认为是机器学习但不是每一个机器学习算法都被认为是深度学习。

AI vs. ML vs. DL。来源

机器学习和深度学习最大的区别在于它们是如何学习的。

机器学习:选择模型(例如某个分类器)进行训练,手动对要学习的模型进行特征提取。

深度学习:你选择神经网络的架构(层数、激活函数)和特征 自动从美联储标注的训练数据中提取

为了更好地理解这一点,让我们以汽车和公共汽车的分类为例。在机器学习中,您将定义您想要使用的分类器,然后执行特征提取,例如,您教导模型汽车的特征是某些尺寸、2 或 4 个门、4 个轮胎、4 个窗户等。对于公共汽车,你告诉模型,公共汽车的特征是有一定的尺寸,1 或 2 个门,8 个轮胎,10 个窗户,等等。在这里,您手动提取特征并将其输入到您的模型中。

机器学习与深度学习

深度学习中,不需要做特征提取,甚至不需要知道特征。你首先选择你的网络,例如卷积神经网络(CNN ),因为我们将处理图像。定义层数和要使用的激活函数,然后将你的网络指向一个贴有汽车和公共汽车标签的文件夹。神经网络将自动浏览图片并捕捉汽车和公共汽车的特征。就是这样,你的神经网络教会了自己如何区分汽车和公交车。

激活功能

激活功能 是神经元中发生的事情,每个神经元都有一个激活功能,当神经元被激发时就起作用。

神经网络中的激活函数。来源

神经元的输入将通过激活函数,得到处理,然后发送到下一层或输出神经元。这是神经网络学习的方式,并最终决定将什么发送给下一个神经元。

有许多不同的激活功能,但我在这里将涵盖主要的五个。

阈值(二进制步长)激活函数。来源

阈值函数

也称为二元阶跃函数,它是一个基于阈值的激活函数。如果输入值高于或低于某个阈值,神经元就会被激活,并向下一层发送完全相同的信号。这是一个是或不是的函数。

乙状结肠(逻辑)激活功能。来源

s 形函数

主要用于逻辑回归,比阈值函数平滑。它在神经网络的输出层也非常有用。一些数据科学家抱怨这种方法计算量很大。

ReLU 激活功能。来源

整流器(ReLU)功能

这是神经网络最受欢迎的功能之一。它可以帮助减轻消失和爆炸梯度下降问题。ReLU 是一个非线性函数,计算效率很高。

Tanh 激活函数。来源

双曲正切函数

它类似于乙状结肠,但它低于零,不像乙状结肠。它主要用于输入值为强负值、中性值或强正值的情况。

Softmax 激活功能。来源

Softmax 功能

这主要用于多类预测的分类问题。它通常位于神经网络的输出层。

同一神经网络中的不同激活函数。来源

您可以对隐藏层和输出层应用不同的激活功能。在此图中,ReLU 应用于隐藏层,而 Sigmoid 应用于输出层。这是预测某事发生的概率的常见方法。

神经网络:它们如何学习

学习是通过将带标签的数据从输入层一直传递到输出层,然后再返回来进行的。由于数据被标记,神经网络知道什么是预期输出,并将其与神经网络的实际输出进行比较。

在第一个 时期 中,被标记的数据在输入层被输入,并被传播到输出层,在那里你的神经网络将计算出一个输出。你的神经网络的实际输出与预期输出之间的差异被称为 成本函数 。你的神经网络的目标是尽可能地减少这个 成本函数 。因此,您的神经网络将 从输出层一直反向传播 到输入层,并相应地更新神经元的权重,以尝试最小化这个 成本函数

将数据从输入层发送到输出层,然后一路返回的行为称为 时期 。在每个时期,神经网络更新神经元的权重,这也被称为 学习 。在多个时期和权重更新之后,损失函数(神经网络输出与实际输出之间的差异)应该达到最小值。

学习阶段的神经网络

在学习时,神经元将具有不同的权重,这些权重将决定未来的输出。例如,在我们之前的汽车与公共汽车分类场景中,神经元可以通过查看窗口的数量来确定该对象是汽车还是公共汽车,显然,该神经元比通过查看对象的颜色来确定该对象是汽车还是公共汽车的神经元具有更高的权重。这是对神经元功能的过度简化,但我希望你能根据重要性来理解神经元的权重。

梯度下降

梯度下降。来源

梯度下降 是一种最小化代价函数以更新神经元权重的方法。此方法告诉您的神经网络如何以快速有效的方式计算成本函数,以最小化实际和预期输出之间的差异。

最容易理解也是最常见的例子是将您的成本函数比作一个球,通过更新其斜率来试图找到最低点。

随机梯度下降

随机梯度下降 建立在梯度下降的基础上,可以处理复杂的成本函数。

梯度下降陷入局部极小值,错过真正的极小值。来源

梯度下降仅在只有一个最小值的凸成本函数的情况下工作良好。然而,在复杂的成本函数的情况下,梯度下降很容易陷入局部最小值,这破坏了你的神经网络学习。

随机下降与梯度下降

为了理解随机下降和梯度下降有什么不同,让我们举个例子。我们将假设您已经将数据标记为行,并将它们输入到您的神经网络中进行训练。

梯度(批量)下降 当你的神经网络一次遍历一行数据,计算每一行的实际输出。然后,在完成数据集中的所有行后,神经网络将所有行的累积总输出与预期输出进行比较,并反向传播以更新权重。这意味着神经网络在作为一个大批量处理整个数据集之后更新一次权重,这是一个非常及时的时期。神经网络会这样做几次来训练网络。

梯度下降与随机梯度下降。来源

随机梯度下降 当你的神经网络一次遍历一行数据,计算每行的实际输出。神经网络立即将第一行的实际输出与预期输出进行比较,并反向传播以更新权重,从而完成一个时期。然后对第二行进行同样的操作,比较输出并反向传播以更新权重。一直到最后一行,因此多个历元和多个权重更新会贯穿整个数据集,而不是像梯度下降那样将其视为一个大批次。这有助于避免局部极小值,它比梯度下降法更快,因为它不需要将所有数据加载到内存中并一次遍历它们,而是一次加载一行并更新权重。

有一种两全其美的方法叫做 小批量梯度下降 ,它基本上是将两者结合起来。您可以决定一次运行和更新多少行。因此,您可以灵活地选择运行任意数量的行,而不是将整个数据集作为一批运行,或者一次运行一行。

反向传播

现在你应该知道什么是反向传播,如果你不知道,那么它只是在计算成本函数后调整你的神经网络中所有神经元的权重。反向传播是你的神经网络学习的方式,它是计算成本函数的结果。需要知道的重要概念是反向传播同时更新所有神经元的所有权重。

出于训练目的,在开始时,神经元的权重用小数字随机初始化,然后通过学习和反向传播,权重开始用有意义的值更新。

最后,我希望你喜欢这个深度学习的快速介绍,现在你应该对一些常见术语有了更好的理解,如神经元、反向传播、权重、激活和成本函数。

机器学习、人工智能和深度学习是非常令人兴奋的话题,将改变每个行业,取决于你的工作职能,你需要对它们有一些了解。

新精算师必须了解机器学习

原文:https://towardsdatascience.com/new-actuaries-must-know-about-machine-learning-846dd65647d9?source=collection_archive---------17-----------------------

Unsplash 上由斯特凡·斯特凡·契克拍摄的照片

这个职业正在发展

机器学习(ML)是一个不可回避的话题——它也在精算行业引起了轰动。机器学习可以简单地定义为“对计算机编程的科学(和艺术),以便它们可以从数据中学习”,这是 A. Géron 在他的 2019 年中提供的。事实证明,它是一个无价的工具,拥有海量数据的公司可以利用它来提取洞察力,以改进他们的产品和服务。

精算师的情况也是如此。精算师偶尔会被描述为第一批数据科学家,因为他们长期从事数据和建模技术的工作。这两个研究领域之间显然有很大的重叠——这就是为什么越来越多的精算师发现自己在日常工作中应用机器学习工具。无论是为了释放传统上被忽视的数据的潜力(例如,从文本字段或图像中提取洞察力,而不仅仅是冰冷的硬数字数据),还是为了利用更强大的技术和算法来利用他们已经拥有的数据,有一点是明确的-机器学习将会继续存在。

只有一个问题

尽管自 20 世纪 90 年代以来,一些机器学习算法一直在后台悄悄工作,但似乎这个世界已经迅速变得越来越多地与人工智能有关。商业用例非常丰富,人工智能和人工智能存在于各种产品和服务中(为我们的手机、我们最喜欢的网站和我们每天依赖的工业生产过程提供动力)。但是 ML 在精算领域也有应用:分析死亡率经验以发现新趋势,保险产品定价,预测金融数据…

然而,需要教授给培训中的精算师的材料仍然是静态的。世界在前进,这种教育脱节在加剧。精算大纲看起来有过时的危险。

解决方案

也就是到 2019 年。教学大纲被修改了——引入了新鲜的新材料,重要性日益下降的旧材料被淘汰了。瞧,精算师协会(IFoA)科目 CS2 考试的新增加内容之一是机器学习,以及科目 CM1 中密切相关的数据分析主题。这些变化是为了“确保课程是相关的、最新的,并反映在不断变化的全球商业环境中精算师所需的技能、知识和属性。”这听起来是一个足够好的理由——但是这种新材料符合这种说法吗?

根据新大纲,机器学习现在占 CS2 考试的 10%,涵盖五个学习目标,即:

  • ML 的分支及其解决的问题类型
  • 关于从数据中学习的高级概念
  • 关键技术的描述和示例
  • 将 ML 技术应用于简单问题
  • 了解其他非精算定量研究人员(数据科学家、统计学家……)的观点

听起来像是对这个主题的全面介绍。让我们来看看核心阅读材料(CS2 考试的可测试材料)中涉及了哪些关键主题。

照片由女牛仔Unsplash 上拍摄

洗钱的定义和范围

相当合理的是,我们从一些基本的定义和解释开始,关于 ML 对于什么样的问题是有用的。在经典方法可以解决的情况下,开发一个花哨的 ML 算法没有多大意义——同样,如果在数据中没有真正的模式可以检测,ML 也没有什么可以提供的。

在从一些具体的例子(如定向广告、预测选举、预测贷款违约)开始之后,材料变得更加正式——将机器学习过程描述为逼近一个目标函数,该目标函数将一组可测量的变量映射到输出。这些材料不怕揭示算法和问题的数学本质——这对于那些只听说过 ML 的不精确术语的人来说可能是一个受欢迎的变化(或者只是被各种相关的流行词汇反复击中头部)。

关键概念概述

接下来是对该领域关键概念的讨论。特别是:

  • 损失函数
  • 评估模型的方法(准确度、精确度、召回率、混淆矩阵等)
  • 参数和超参数
  • 训练集、验证集和测试集
  • 过度拟合
  • 模型正则化

这些概念被描述得很好——但这仅仅是一个描述。机器学习是那些你需要亲自动手才能真正掌握概念以及它们为什么重要的领域之一。建议使用一些优秀的 ML 在线资源或书籍来查看这些概念的端到端实现,并真正让您的理解更上一层楼。

机器学习的分支

不同类型的最大似然算法之间的本质区别是在这里,涵盖监督,无监督,半监督和强化学习技术。这一部分还处理回归与分类和生成与判别模型,以及额外的理论,例子和精算应用。同样,这是一个很好的主题调查,但你会想做一些进一步的研究,以巩固一些概念。观看视频,阅读书籍和博客——试着为自己建立联系,以便最大限度地利用这些材料。

机器学习过程

ML 项目的一般步骤在注释中给出了合理的范围,这是正确的。机器学习不仅仅是开发、训练和评估模型——在成功部署 ML 解决方案的过程中,还有很多事情要做。在这里我们讨论:

  • 收集数据
  • 探索性数据分析
  • 数据准备
  • 模特培训
  • 验证和测试
  • 提高模型性能
  • 文件和再现性的重要性

精算专业的学生将会对他们在课程中遇到的模型的数学驾轻就熟——但是知道这只是 ML 故事中的一章是至关重要的。如果您想继续将您的知识应用到真实世界的业务用例中,您需要对全局有一个坚实的把握。

关键算法

接下来,我们将讨论一些关键算法,特别是:

  • 惩罚广义线性模型
  • 朴素贝叶斯分类
  • 决策树
  • k 均值聚类

这方面有大量的材料,这是一件好事——它建立在前面介绍的一些概念之上。更重要的是,它建立在本课程其他部分所涵盖的一些主题之上。那些熟悉 CS1 中的回归、广义线性模型和主成分分析以及 CS2 中其他地方的比例风险模型的人会很高兴看到这些概念的扩展。

其他定量研究者的观点

最后,我们讨论了一个 ML 从业者的观点如何不同于更传统的研究者和建模者,例如统计学家。本节讨论了团队之间沟通的困难——特别是当不同的术语可能用于本质上相同的概念时,或者当两个团队可能对分析的不同方面感兴趣时。机器学习绝对是一个跨学科的研究领域,因此从业者将经常与其他背景的专业人士交流。“缩小”来讨论一些更普遍但同样重要的问题,这些问题是在现实世界中开发和应用 ML 解决方案时出现的,这很好地完成了材料,因为我们从理论的深度开始,以务实的方式结束。

车头拍摄

那么到底是什么出现在了考试中呢?

任何一个学生(勇于承认这一点的人)都会知道,更多的努力倾向于放在那些经过实际测试的材料上。严格来说,阅读材料中的所有内容都是可考查的,但这是自从新材料加入后,两次讨论中出现的内容。

【2019 年 4 月 —关于监督与非监督学习的简短问题以及各自的示例。关于模型性能度量的计算和解释的更长的问题。

2019 年 9 月 —讨论列车验证测试方法的一个更长的问题。评估机器学习在给定的示例场景中是否合适。讨论具有更多参数的更复杂模型的利弊。

密码在哪里?

不让学生参与一些更实用的、端到端的 Python 或 R ML 实践项目,这似乎是一个错失的机会——尤其是现在 R 的数据分析和精算统计现在已经成为不止一次而是两次 IFoA 考试的一部分。即使是该学院全新的数据科学证书也不需要编写任何代码就能完成。一方面,这可能看起来完全疯狂——毕竟,学习数据科学或机器学习的最佳方式可以说是让自己沉浸其中,并开始摆弄你感兴趣的数据集。

然而,值得注意的是,IFoA 并没有试图创造数据科学家。相反,他们的目标是“通过实例和案例研究,帮助处于职业生涯任何阶段的精算师获得对数据科学工具和技术的基本理解,以及如何将它们应用到精算实践中”(见此处,以及关于数据科学证书的其他常见问题)。从本质上来说,你不必成为机器学习的专家,但你需要知道它是什么,以及随着它在行业和整个社会中变得越来越普遍,它是如何使用的。

前景

精算的角色正在演变。IFoA 主席约翰·泰勒在去年主持了该行业内的快速数据科学扩张。很明显,这只是第一步——更新整个职业当然不是一件容易的事情,但不可否认这是正确的做法。数据科学和机器学习技术在 IFoA 学生课程中的正式化是巩固精算师作为专业人士的地位的举措,可以为客户增加真正的价值——随着精算师继续在更远的行业工作,这只会证明越来越有用。

更多信息和积分

Andrew Hetherington 是英国伦敦的一名见习精算师和数据爱好者。

  • LinkedIn 上和我联系。
  • 看看我在 GitHub 上鼓捣什么。

斯特凡·斯特凡·契克、 女同胞前进拍摄的照片。

物体检测的新方法

原文:https://towardsdatascience.com/new-approaches-to-object-detection-f5cbc925e00e?source=collection_archive---------12-----------------------

center net(Objects as Points)简介,TTFNet 及其在 TensorFlow 2.2+中的实现。

来源:pexels.com

我将从简单介绍不同的物体检测方法开始。在介绍了传统方法和新方法之后,您可以阅读 CenterNet 和 TTFNet 的最重要部分。两个模型中的许多想法是相似的,因此将一起介绍它们。我们实现了一个由两个网络启发的包。如果你有兴趣,请查看我们的 GitHub

需要深度学习和卷积神经网络(CNN)的基础知识。

传统方法

在计算机科学中,当我们遇到一个无解的难题时,我们会试图将其转化为一个我们知道其解的问题或者一个更简单的问题。所谓的两阶段检测模型就是很好的例子。在这种情况下,更简单的问题是图像分类或标记。(将给定图像放入一个类别或给给定图像分配标签)简单地说,我们可以将图像分成多个区域,然后对这些区域进行分类,对吗?是的……但是要花很多时间。因此,你需要聪明一点。使用这种方法的算法的一个例子是 R-CNN (2014)。后来演变成快速 R-CNN (2015)甚至更快的 R-CNN (2016)。

尽管这些模型的性能相当好,但研究人员显然在问自己,这个过程是否可以变得简单,从而更有效。在一个阶段,没有区域提案。这个问题的一个可能答案是YOLO——你只看一次 (2015)。现在是第四版 (2020)。或 SSD —单次多盒探测器 (2015)。最后,还应提及 RetinaNet (2017 年),特别是因为它曾被用于引入物体检测的焦点损失,这是现在经常使用的方法。

新方法

近年来,另一个想法越来越受欢迎。物体可以被转换成一组点。并且检测任务可以被认为是关键点估计问题。这种方法在 CornerNet:将对象检测为成对关键点中有所介绍。顾名思义,一个对象被表示为一对关键点,左上角和右下角。

在介绍 CenterNet 的 Objects as Points 论文中探讨了类似的想法。在那里,我们使用热图检测包围盒的中心点。使用回归直接预测诸如边界框大小的其他属性。

来源:pexels.com

这种方法的缺点是训练速度较慢。为了解决这个问题,提出了 TTFNet(训练时间友好网络)。它遵循相同的基本思想,因此我们决定在一个中实现来自两个网络的思想。

神经网络布局

让我们开始吧!我将从头开始,向您介绍网络布局。然后,将讨论重要的单个部分,主要是热图和不同的损失函数。

我们可以使用专门为此类任务设计的网络。例如沙漏网络。或者,正如我们已经决定要做的,选择一个标准的图像分类 CNN,并根据我们的需要进行修改。我们选择测试 ResNet (18,50)和 EfficientNet (b0,b1,b2)。

在所有标准的迁移学习任务中,我们放弃了顶部的密集层。但是留在顶部的层甚至与我们需要的输出相差甚远。因此,一些上采样是必要的。除此之外,来自较低层的连接提高了性能。当我们在网络的末端有一个正确大小的层时,我们可以将它“分割”成所需数量的头。

使用 ResNet18 简化 CenterNet 的可视化,使用上采样和连接。(黄色:卷积层,红色:最大池化,蓝色:上采样。)

为了让网络更快,热图的一边正好是输入图像的 1/4。我们每节课都有一张热图。然后,CenterNet 中有另外两个头(用于基本的对象检测),TTFNet 中有一个头。

对于中心网,有

  • 一个尺寸头,包含一个边框的宽度和高度
  • 偏移头,包含使用下采样热图时产生的中心的 x 和 y 偏移。

两者都只有两个过滤器——在热图的任何给定点都可能只有一个对象。如果您对一个对象的其他属性感兴趣,可以添加更多的头。

TTFNet 中,只有一个带有四个滤镜的额外云台来计算物体的尺寸——到侧面的距离。

热图

那么,热图是什么样子的呢?它是一个填充了从 0.0 到 1.0 的值的矩阵。这种地图上的峰表明某个物体的存在。

下面,你会看到一些生成的训练热图。只有一个点正好是 1.0。在这一点上,概率正在慢慢消失。

CenterNet(左)和 TTFNet(右)的热图。

可变形卷积

网络的上采样部分可以通过多种方式实现。我们已经向您展示了级联、上采样和标准卷积层的简单方法。为了提高性能,使用了可变形卷积。

毫无疑问,卷积神经网络给深度学习带来了一场伟大的革命。它们使我们能够提取从完全连接的层中很难得到的特征。再加上另一项布局改进,我们的网络可能会变得非常深入。尽管如此,基本思想还是一样的。特别地,过滤器的形状总是矩形的。可变形回旋正试图对此进行改进。它们学习到标准网格的偏移,并用这个“变形的”内核执行卷积。

标准与可变形卷积值的选择。船方不负担装货费用

不幸的是,可变形卷积层尚未在 TensorFlow 和 TensorFlow 插件 (TFA)中实现。我们正在使用TFA的一个分支,支持可变形 Conv2d,希望它能很快被合并。(参见拉动请求 1129 。)

损失函数

现在,当我们有了网络布局和输出的样子,只有一个关键的东西不见了。损失函数。

焦点损失

热图有一个问题——它们非常稀疏。大多数情况下,没有检测到(零),只是偶尔我们会看到一个物体(一个物体,周围的值递减)。在这种情况下,标准的度量标准不太适用。幸运的是,有一个解决方案——一个焦损失。CenteNet 和 TTFNet 都使用它。

基于并集交集的损失(IoU)

为了优化边界框的大小,中心网使用 L1 损失。它是真实边界框坐标和预测边界框坐标之差的简单总和。这似乎是合理的,但另一方面,我们并不经常使用它进行评估。我们使用 IoU 指标——并集上的交集。因此,当我们对改进这个指标感兴趣时,为什么不把它也用于优化呢?我们可以从 1 中减去借据的价值,把它变成亏损。还是没有?

可惜,如果没有交集,欠条就是零。因此,在这种情况下,损失总是 1。提出了两种基于 IoU 的损失函数。TTF net 中使用的联合损耗上的广义交集解决了这个问题。 Distance-IoU Loss 还关注于在函数中添加一个距离信息,换句话说,我们离边界框的中心有多远。

最后的想法

你可以在 GitHub 上找到我们的实现。我要感谢 Michal Lukac 与我合作这个项目,感谢 Ximilar 允许我们开源它。如果你想尝试没有任何编码的模型,请查看这篇关于 Ximilar App 中物体检测的博文。

如何打入数据科学

原文:https://towardsdatascience.com/new-data-science-f4eeee38d8f6?source=collection_archive---------17-----------------------

今年,我完成了一个训练营,并立即找到了一份深度学习的工作。如果我必须回去自学所有的东西,以下是我将学习的内容。

照片由凯罗尔·斯特法斯基Unsplash 上拍摄

更新—加入脸书小组:

[## 闯入数据科学

一个分享数据科学和机器学习资源的组织。一月-概览二月-统计三月…

www.facebook.com](https://www.facebook.com/groups/breakingintodatascience)

当谈到在线学习数据科学时,这些简历代表了我在过去三年培训 Python分析生产机器学习模型中遇到的最好的、大部分免费的资源。一个数据科学家应该是一个伟大的程序员,一个体面的分析师,一个相当好的工程师。你还需要对统计学有坚实的理解——为此,有 ESL

要了解其他一切,让我们开始吧。

免责声明: 本帖不以任何方式赞助,也不代表除本人以外任何人的观点。如果这些建议对你不起作用,就这么说吧。

Python 已经迅速成长为机器学习的通用语言。它超过了 R,为科学计算提供了丰富的软件包。数据科学家必须是熟练的 Python 程序员。

除了拥有良好的编码能力,期望数据科学家拥有一些核心分析技能也是合理的,包括数据可视化。我提供了一些关于流行的第三方工具 Tableau 的技巧,用于拖放分析。数据科学家应该能够自如地交流他们的见解,有时会使用可视化工具。

最后,要做到真正的全栈,数据科学家应该熟悉从原型到生产模型的所有步骤。我喜欢运营指南中的这句话:“将模型投入生产是模型旅程的开始,而不是结束。”数据科学家应该知道生产一个模型需要什么。

🐍学习 Python

为编码开发肌肉记忆

Codecademy 是我告诉人们在进入数据科学之前学习 Python、命令行和 Git 的第一个地方。该平台的简单界面可以帮助你练习编码,直到让计算机做你想做的事情不再是困难的部分——这释放了大脑空间,以专注于与实际数据科学相关的挑战。不免费,但值得!)

[## 学习 Python 3 | Codecademy

学习世界上最流行的编程语言的最新和最棒的版本!

www.codecademy.com](https://www.codecademy.com/learn/learn-python-3)

涵盖数据科学的要点

Flatiron School 是我进行数据科学训练营的神奇机构,它提供完全免费的在线迷你课程。很有帮助。

[## 学习编码、数据科学和网络安全分析

一点也不。虽然取得进展,在我们的免费课程是最好的方式,以加强您的申请,我们的全日制…

flatironschool.com](https://flatironschool.com/free-courses/data-science-bootcamp-prep)

适应机器学习

凯蒂(无与伦比的,现在不幸倒闭的,线性离题播客)和塞巴斯蒂安(T4 胜利自动驾驶汽车)提供了一个真正友好的机器学习概述。

[## 机器学习课程介绍| Udacity

机器学习是当今数据分析领域最令人兴奋的职业的头等舱门票。作为数据源…

www.udacity.com](https://www.udacity.com/course/intro-to-machine-learning--ud120)

发展计算机科学基础

埃里克·格里姆森有点像你那严厉而聪明的叔叔——他正从十几台不再工作的笔记本电脑中收集部件来建造一台量子计算机。他的经典课程是学习 CS 最佳实践同时加深您的 Python 知识的好方法。

[## 计算机科学和使用 Python 编程简介

麻省理工学院 edX 6.00.1x

courses.edx.org](https://courses.edx.org/courses/course-v1:MITx+6.00.1x+2T2017_2/course/)

尝试一个样本数据科学项目

以下是让你开始的几个想法:

[## 演练:在 Python 中映射 GIS 数据

通过 GeoPandas DataFrames 和 Google Colab 提高您对地理空间信息的理解

towardsdatascience.com](/walkthrough-mapping-gis-data-in-python-92c77cd2b87a) [## 开始使用 Spotify 的 API & Spotipy

《数据科学家快速入门指南》,指导如何浏览 Spotify 的 Web API 并使用 Spotipy Python 访问数据…

medium.com](https://medium.com/@maxtingle/getting-started-with-spotifys-api-spotipy-197c3dc6353b) [## 12 小时 ML 挑战

如何使用 Streamlit 和 DevOps 工具构建和部署 ML 应用程序

towardsdatascience.com](/build-full-stack-ml-12-hours-50c310fedd51)

通过对数据科学感到兴奋来更快地学习

选择你有激情的事情,深入钻研。首先,看看这个常规资源列表——博客、YouTube 频道和播客。您还可以在 LinkedInTwitter 上关注我,了解我最喜欢的学习资源的实时更新。

[## 2020 年增强数据科学学习的资源

通过这个有用的期刊、视频和讲座的集合,推进你对机器学习的理解。

towardsdatascience.com](/supercharge-data-science-5bb7376d8572)

🎨学习数据,即

Tableau 工作表,尺寸为蓝色,度量为绿色。最左侧的侧栏显示了用于基本汇总统计的现成分析工具。通过画面

当你的数据需要打扮的时候, Tableau 是一个防呆风格的服务。它提供了一个时尚的拖放式数据分析界面,通过本机集成从 CSV、JSON 文件、Google Sheets、SQL 数据库以及烘干机的后角(你不可避免地会忘记带袜子)中提取数据。

数据被自动分为维度(定性的)和度量(定量的)——并被假定为可以制作图表。当然,如果还有一些数据清理步骤要做,Tableau 也可以处理脏衣服。例如,它支持重新格式化数据类型和将数据从宽格式转换为高格式。

准备制作图表时,只需按住 ctrl 键并单击感兴趣的功能和“演示”框中的默认选项。这种交互的简单性使得即使是设计能力最差的数据科学家也能轻松地将数据整理成可展示的格式。Tableau 会把你的数据装进西装和领带里,然后发送到会议室。

遵循这些提示,让你的数据可视化能力从“好”变得“好”。

从制图员大师那里获得灵感

在我作为四大公司的商业分析师的整个时间里,这三个博客是我如何创建一个好看的、功能性的 Tableau 仪表板的指南。

[## Tableau 博客

Tableau 公共团队的定期派遣。

public.tableau.com](https://public.tableau.com/en-us/s/blog) [## 来自数据专家的分析技巧和见解| Evolytics 博客

Evolytics 分享操作方法文章、分析技巧、专家建议、行业见解和新闻。了解有关及时的更多信息…

evolytics.com](https://evolytics.com/blog/?blog-search=tableau) [## Tableau 档案|网络

点菜吧!我们为您准备了又一个月的最新热门数据资源。在这篇博客综述中,…

interworks.com](https://interworks.com/blog/channel/tableau/)

请记住这 4 条准则

1 —床单是艺术家的画布,仪表板是画廊的墙壁。工作表用于创建艺术作品(咳咳,图表),然后您将这些艺术作品连同任何格式元素一起放置到仪表板上(使用带有容器的平铺布局 —稍后将详细介绍)。

2-为了节省时间,为尺寸和测量设置默认属性。这将为颜色、小数点位数、排序顺序等提供统一的方法。并防止您在每次使用给定字段时不得不摆弄这些设置。

3——按照这些思路,使用总体的格式工作簿格式仪表板选项,而不是一次性的格式调整。

4——避免将浮动对象放入仪表盘。一旦你有两个或三个以上的图表要处理,拖动图表就变得令人头疼。你可以让你的图例成为浮动的物体,但是要远离这个“长切口”

取而代之的是使用平铺布局,如果你改变了你的仪表板的尺寸,它会强制对象对齐并自动调整大小。从长远来看更快更简单。

开始使用您的第一个仪表板

总之,Tableau 平台比手指画更容易使用,所以如果你准备好开始使用, Tableau Public 是一个免费版本,它将允许你创建可公开访问的可视化效果——就像这个我在网上搜集了一些来自华盛顿 DC 分区办公室的有问题的豁免开发项目的信息后整理出来的——并将它们共享到云上。

准备向高管们展示财务状况。由 Lisa Fotios像素上拍摄的照片。

在调查了来自当地社区的数据后,另一个很好的示例项目是提取您的支票账户数据,并假装您正在将其提交给 CEO 进行分析。

阅读有关数据科学家和数据分析师之间的区别的更多信息:

[## 数据分析师、数据科学家和机器学习工程师有什么区别?

以田径运动会为例,探究这些常见职位之间的区别。

towardsdatascience.com](/data-analyst-vs-data-scientist-2534fc1057c3)

现在,如果你不那么秘密地热爱数据 viz,并且需要找到更多的时间投入到你的模型的生产中(🙋‍♀️),让我们继续…

🦁学习开发

你的机器学习模型的好坏取决于它在现实世界中对数据的预测和分类。通过至少获得对 DevOps(负责集成开发和 IT 的领域)的基本理解,给你的模型一个战斗的机会。

重新思考数据科学是什么或不是什么

在这篇精彩的文章中,深度学习的英雄 Andrej Karpathy 认为,机器学习模型是软件中的新热点——数据不是遵循如果-那么规则,而是它们的代码库。

[## 软件 2.0

我有时看到人们将神经网络称为“你的机器学习工具箱中的另一个工具”。他们有一些…

medium.com](https://medium.com/@karpathy/software-2-0-a64152b37c35)

了解这在企业中是如何工作的

这部巧妙的小说虚构了devo PS 手册 并且具有惊人的可读性。(不是免费的——但是如果你买了一份,给你的同事,希望他们会对生产你的模型充满热情)。

* [## 吉恩·金(凤凰计划的作者)的独角兽计划

这是一个关于反叛的开发者和商业领袖与时间赛跑的故事,在一个…

itrevolution.com](https://itrevolution.com/the-unicorn-project/)

向外界介绍你的机器学习模型

查看这篇关于如何使用 Streamlit 进行部署和数据探索的文章。如果我没有提到 DockerKubernetes 作为生产化的企业级工具,那我就失职了。

[## 最有用的 ML 工具 2020

每个懒惰的全栈数据科学家都应该使用的 5 套工具

towardsdatascience.com](/the-most-useful-ml-tools-2020-e41b54061c58)

如果你喜欢阅读这篇文章,请在媒体LinkedInYouTubeTwitter 上关注我,了解更多提升你的数据科学技能的想法。

当“ 资源在 2020 年 的最后几个月为您的数据科学增压”发布时,注册即可获得通知。

🤸‍♀️其他有用的话题

[## 像我五岁一样解释计算机科学

了解互联网,编程,机器学习和其他计算机科学的基础知识,通过清晰和…

medium.com](https://medium.com/coderbyte/eli5-computer-science-f8dfd7910311) [## 如何不费吹灰之力通过 AWS 云从业者认证

预测:多云,第一次尝试有 100%的机会通过。

medium.com](https://medium.com/@nicolejaneway/how-to-ace-the-aws-cloud-practitioner-certification-with-minimal-effort-39f10f43146) [## 数据仓库综合指南

了解数据仓库作为分析就绪数据集的主存储库的角色。

towardsdatascience.com](/data-warehouse-68ec63eecf78)*

新数据显示新冠肺炎死亡率较低

原文:https://towardsdatascience.com/new-data-shows-a-lower-covid-19-fatality-rate-1d69361a50af?source=collection_archive---------36-----------------------

新的数据和分析提供了更多的准确性——它显示的死亡率是原始报告的十分之一

1 月和 2 月新冠肺炎的经验表明,该疾病的总死亡率在 3.5%至 5%之间。如此高的死亡风险是可怕的,整个世界都跑去躲避。

三月, 纽约时报 描述了一份报告,称新冠肺炎可能在美国杀死多达 220 万人。这份早期报告启动了我们当前的许多政策。

自 3 月以来,我们已经积累了大量关于该病毒的经验和更多的数据。早期的推测现在可以被明智的分析所取代。

在本文中,我将解释多个更新的数据来源如何显示新冠肺炎的总体死亡率大约是最初声称的十分之一——在 0.4%到 0.6%之间,可能接近 0.5%。

如果你研究图 4 中简单的 CFR 曲线,很明显为什么一些早期报道的死亡率如此之高。根据具体报告的时间,一个人可以察觉到几乎任何高达 35%的死亡率。

照片来自粘土堤的 Unsplash

第一步:了解疾病的一般进展

我们现在对新冠肺炎发展的时间线的了解比 3 月份时更多。了解疾病的时间线使我们能够分析数据并得出更准确的结论。

用数学术语来说,这种疾病的一般发展过程如图 1 所示。首先,一个人被感染了。2.3 天后,此人具有传染性。4.5 天后,患者出现症状。5 天后,这个人将接受测试。在第 11 天,他们仍然生病,但不再传染。如果他们会死,他们会在 18 天后死去。否则,它们会在第 21 天恢复并产生抗体。

图 1-新冠肺炎的一般级数,基于纯数学平均时间值。

当然,每个时间段都有范围、概率和置信限。都没有我刚才描述的那么具体。真正的进展看起来更像图 2 所示,其中粉红色阴影区域代表时间线的概率。

图 2——新冠肺炎的总体发展,显示了时间段范围。平均值都是基于数据。症状和传染性的范围基于数据;其他范围是概念上的,并且是为了解释的目的而显示的。

传染性始于感染后 1 至 3 天。症状在 4-5 天左右开始。测试平均在 5 天后进行。有时在症状出现之前就进行(例如,如果一个人知道自己接触了感染者)。有时直到病人住院后才进行测试。有些人死得很快,有些人活得更久。有迹象表明传染性和抗体发展是非正态分布(它们不是钟形曲线)。

在这些范围内存在可变性的事实不会改变我们使用疾病进展数据得出结论的能力。如图 3 所示,我们知道,出于统计目的,在“A”点感染的人,要么在“B”点 18 天后死亡,要么在“C”点 21 天后康复并产生抗体。

图 3

知道了这个时间线,我们就有了计算总死亡率的基础——如果我们能找到 A 点、B 点和 c 点的数据。

根据纽约州的抗体检测计算死亡风险

由于在纽约州的一个周末进行了广泛的抗体测试,我们有了“C”点的可靠数据,即截至 2020 年 4 月 19 日,纽约州 13.9%的人口产生了抗体。我们知道这些人平均至少在 21 天前,即 3 月 29 日被感染。

为了使这个数字有用,我们需要把它与 3 月 29 日感染但后来死亡的人数放在一起。

根据图 3,我们需要查看 3 月 29 日之后 18 天的死亡人数,以便对抗体和死亡人数进行比较。18 天后是 4 月 16 日。纽约州报告的死亡人数为 12,192 人。

问题不在于是否存在可变性。问题是,“这种可变性对死亡率的计算有多大影响?”

这告诉我们,在 2020 年 3 月 29 日或之前感染新冠肺炎病毒的 271.6 万纽约州居民中,0.449%的人死亡。因此,对于纽约州的人口,新冠肺炎的总死亡率约为 0.449%(在“平均置信水平”)。这有时被称为 IFR ,或感染致死率,但该术语在许多已发表的文章中使用不一致,因此在本文中我使用术语致死率

这种分析的精度水平并不能证明显示三位小数的结果是正确的,但是,为了那些想了解计算结果的人,我在这篇文章中使用了这种精度水平。

在最初的抗体测试项目后,纽约州继续进行抗体测试,并公布了另外两组测试结果。使用与上述相同的计算,这些测试结果意味着死亡率为 0.520%和 0.686%。

在这些后来的测试中,关于测试周期和人口抽样方法的细节较少,这使得死亡率比第一组测试结果更不确定。我没有完全排除后面的这些结果,而是计算了一个加权名义值,其中第一组结果的权重比第二组结果的权重大。这产生了 0.500%的名义死亡率。(我在文章末尾的注释部分提供了关于这个计算的注释。)

如果排除这些结果,名义利率仍为 0.449%,两个数字之间 11%的差异将贯穿本文的其余计算。

计算美国总体感染死亡率

事实证明,新冠肺炎对年龄高度敏感——它对老年人的致命性明显高于年轻人。纽约州的人口平均年龄略高于美国人口。根据该病毒特定年龄的死亡率,以及纽约州与美国整体的人口统计数据,纽约州的死亡率应该是美国整体的 1.05 倍。

然而,在纽约州,病毒一直集中在纽约市,纽约市的平均人口比美国整体人口年轻得多。再次基于特定年龄的死亡率和人口统计数据,纽约市的死亡率应该是美国整体死亡率的 0.88 倍。

为了调和这些对立的观点,我首先对纽约市的年龄进行了加权,然后根据每个地区死于新冠肺炎的人数对纽约州其他地区的年龄进行了加权。(我认为死亡比 PCR/病毒检测更能代表这两个地区的疾病流行程度,因为 PCR/病毒检测随着时间的推移一直不一致。)根据这一权重,纽约州的总人口比美国人口略年轻 0.98 倍。

详情如表 1 所示。

表 1

为了调整纽约与美国整体人口统计数据的差异,我将纽约州的死亡率除以 0.98(实际上是 0.984),得出美国的死亡率为 0.508%。

这一死亡率明显低于疫情早期报道的 3.5-5%的死亡率。

根据上周五个区的死亡人数和纽约市的总人口,即使 100%的人被感染,死亡率也不会低于 0.19%。

死亡率的可变性

如果你在想,“所有这些都有相当多的假设,一些数据点肯定有一些与之相关的可变性”,那么你是对的。

但问题不在于是否存在可变性。问题是,“这种可变性对死亡率的计算有多大的影响?”我考虑了七个可能的可变性领域。

纽约州多重抗体检测。正如我先前所述,纽约报告了三组抗体检测结果。这些结果的差异表明,总死亡率可能从 0.78 倍的标称值变化到 1.22 倍的标称值。

抗体检测中的偏倚。抗体检测的公开讨论集中在检测个体的准确性上。测试大组的精度考虑是不同的。只要我们知道测试的“敏感性”和“特异性”,我们就可以用数学方法解释测试中的不准确性。在纽约州的测试中,官员说测试已经被校准,“为了避免产生假阴性——漏掉一些可能有抗体的人。”这表明他们的测试可能低估了感染人数。我对这个因素使用了 0.9 倍标称值到 1.0 倍标称值的可变性。

额外的抗体开发。发现人们需要 21 天来产生抗体的研究特别发现,不是 100%的人在 21 天后产生抗体,而是 95%的人产生了抗体。在名义死亡率中,我没有考虑抗体阳性人数比检测阳性人数多 5%的情况。根据是否包括在内,美国的死亡率可以从名义值的 0.95 倍调整到 1.0 倍。

纽约州人口统计。我可以只使用纽约市或纽约州的人口统计数据。我可以用 PCR 检测来衡量而不是死亡。基于我如何调整纽约州的人口统计数据与美国整体人口统计数据的差异,美国的总体死亡率可以通过 0.95 至 1.14 倍的名义系数进行调整。

感染到抗体滞后。如果 21 天的研究平均值不正确,则会更改相关的感染日期。考虑到 3 月 27 日至 3 月 31 日的感染日期,美国的死亡率可以通过 0.89 至 1.10 倍的系数进行调整。

感染致死滞后。如果普通人的死亡时间长于或短于 18 天,那么相关的感染日期也会改变。计算方法与抗体滞后的可变性相同。它产生从 3 月 27 日到 3 月 31 日的相同日期范围,以及对美国死亡率 0.89x 到 1.10x 的相同调整范围。

死因。关于新冠肺炎死亡人数是被高估了还是低估了,已经有了很多讨论。有很多强烈的感觉,但很少有数据。我没有考虑到这个因素的调整。

表 2 总结了这些可变性来源及其对死亡率计算的影响。

表 2

当结合起来时,这些可变性的来源产生 0.398%到 0.619%的 95%置信范围。

正如我前面提到的,包含三个小数位是为了让对计算感兴趣的人知道。分析和数据的潜在准确性实际上只证明了 0.4%到 0.6%的粗略范围。

对于那些对统计数据感兴趣的人,我在注释部分添加了额外的注释。

纽约市人口和死亡的死亡率下限

大多数关于病死率的错误推测都过高,但也有少数过低,包括一些断言,病死率可能接近流感,即 0.1%左右。

可能的死亡率下限来自对纽约市死亡人数的分析。根据上周五个区的死亡人数和纽约市的总人口,即使 100%的人被感染,死亡率也不会低于 0.19%。如果只有 50%被感染,病死率不可能低于 0.38%。

表 3 提供了纽约市五个区和整个纽约市的死亡人数、人口和最低可能死亡率的具体情况。

表 3

最近美国阳性检测和死亡数据的死亡率上限

美国最近的测试和死亡数据为估计可能的死亡率上限提供了基础。

初始 CFR 的计算方法是将某一天的死亡人数除以 13 天前的阳性检测人数。这 13 天来自图 1-3 所示的时间表。

初始 CFR 中的 CFR 代表病死率。之所以称之为天真 CFR,是因为我们并不真正知道有多少真实病例存在,以便计算真实的病死率。我们使用阳性测试的数量作为病例数量的代表但是这个代表并不十分准确。因此,我们将结果计算称为朴素* CFR。*

在疫情的最初几个月,测试是有限的。只有病情最严重的人才被允许接受检测,因此阳性检测的数量被人为地压低,死亡率被人为地抬高。事实上,3 月份的初始 CFR 高达 35%,如图 4 所示。这种明显的高死亡率并不是由于疾病本身的致命性,而是由于当时进行的测试数量有限。

图 4。图表右侧的增加是由于新泽西增加了 1800 例被认为是来自新冠肺炎的死亡病例,全部发生在 6 月 25 日,而不是将死亡人数分配到实际发生的日期。

随着测试变得更加全面,初始 CFR 稳步下降。从图中可以看到,天真的 CFR 现在已经降到了 1.5%。如果我们目前对所有感染进行 100%的检测,这意味着死亡率的上限为 1.5%。

然而,我认为没有人相信目前的检测可以捕获多达 100%的感染,所以真正的死亡率很可能低于 1.5%。如果你认为我们目前正在检测一半的感染,那么病死率将是初始 CFR 的一半,即 0.75%。如果你认为我们目前正在测试三分之一的感染,那么病死率将是初始 CFR 的三分之一,即 0.5%。

0.5%的致死率与纽约抗体研究计算的致死率一致,我们目前正在测试三分之一感染的想法似乎是合理的。

包括表 2 中显示的可变性使我得出结论:美国新冠肺炎的总死亡率在 0.4%和 0.6%之间,可能接近 0.5%。

底线:更好的数据和提高的准确性的好处

如果你研究一下简单的 CFR 曲线,你就会明白为什么一些早期报道的死亡率如此之高。根据具体报告的时间,一个人可以察觉到几乎任何高达 35%的死亡率。

新冠肺炎致死率的底线是它比流感致命 3-4 倍。这是一种严重的疾病,但是我们现在知道它远没有致命到杀死 220 万人的地步,《纽约时报》三月份报道。我们现在可以计算出,要达到这个死亡人数,需要有 4.4 亿人受到感染。这比美国人口还多 1 亿。

至少有一件事我们不用担心。

这是关于新冠肺炎死亡率的 5 集系列报道的第 1 集:

  • 第一部分 :为美国建立一个全面的基础 IFR
  • 第二部分 :基于年龄的 IFRs
  • 第 3 部分:基于人口统计的各州和各国 IFRs 的差异
  • 第 4 部分:有和无共病的 IFRs
  • 第 5 部分:按年龄和共病状况分列的 IFRs

我的背景

20 年来,我一直专注于理解软件开发的数据分析,包括质量、生产率和评估。我从处理噪音数据、坏数据、不确定性和预测中学到的技术都适用于新冠肺炎。

感谢

感谢詹姆斯·D·科顿、博士、布莱恩·唐纳森布拉德·波特对本文早期草稿的极其有用的评论。

更多详情请访问新冠肺炎信息网站

更多美国和州级数据,请查看我的新冠肺炎信息网站。

笔记

关于参考文献的注释

新冠肺炎传染的时机这里

纽约抗体检测时间表第一组抗体检测此处

纽约州三套抗体检测总结这里

测试的时间延迟

从感染到出现症状的时间间隔这里

产生抗体的时滞这里

每日各州死亡人数记录此处

纽约州各县的死亡人数在这里,各县的感染人数在这里

关于置信区间计算的注记

我没有为每个可变性来源创建概率分布。

在考虑纽约州抗体测试结果的范围时,我根据六组结果计算了 95%的置信范围(第一组 4 次,第二组 1 次,第三组 1 次)。这产生了 0.393%至 0.608%的 95%置信区间。这些数字除以 0.984,从纽约州数字转换为美国数字。

对于表 2 所示的总体置信度范围,我通过取每个范围下限的最小调整因子与每个范围上限的最大调整因子的乘积来近似 6 ∂范围。这种方法得出调整系数为 0.504 至 1.659 的 6 ∂范围。我将这些乘数应用于 0.508%的标称(平均)值,这产生了 0.257%至 0.844%的死亡率的 6 ∂范围。将该范围除以 6 得到 0.098%的估计∂。对于置信区间的计算,我使用 0.508%作为平均值,使用值 3 作为样本数,基于 3 组抗体测试结果。使用样本大小为 1 将产生 0.317%至 0.700%的 95%置信范围。

新冠肺炎对策的新数据集

原文:https://towardsdatascience.com/new-dataset-of-covid-19-countermeasures-abfa4e02c5e5?source=collection_archive---------28-----------------------

我们正在发布一个新冠肺炎对策的公共数据集,让数据科学家能够找出击败病毒的最有效的工具。

我们为什么需要这些数据?

疫情冠状病毒传播速度惊人,全球 190 个国家都有病例报告。在每天都很重要,而明确的答案又难以找到的情况下,各级决策者都在争先恐后地采取最佳行动。也许任何人现在最重要的问题是:我们应该做什么?

许多国家目前正在进行严格的封锁,希望这将减缓病例数量的惊人增长,并以某种方式重新控制局势。与此同时,我们有许多亚洲国家的例子,如新加坡和韩国,在武汉最初爆发的早期就有许多携带者到达,尽管他们远没有处于一个舒适的位置,但至少保持了一个低得多的病例数增长。虽然有许多关于为什么会这样的假设,但几乎没有确凿的证据。

为了帮助回答这些和其他问题,我们正在建立一个由世界各国政府应对新冠肺炎疫情的综合数据库。截至 3 月 24 日,我们的数据集目前包含 1300 个条目,由 15 名志愿者收集,记录了来自 96 个国家的措施。同一天,在全球 418 678 例确诊病例中,有记录的国家占 338 203 例。数据集中的中值国家记录了 8 项行动,记录最完整的国家是中国,记录了 118 项措施,到目前为止,我们只记录了他们截至 2 月 24 日的反应。

我们的核心重点是开发一个旨在减少新冠肺炎传播的措施的综合数据集。这些措施包括封锁、追踪接触者、暂停营业、旅行禁令和公共卫生。虽然数据集包含了一些经济刺激和治疗措施,但我们已经停止收集这些项目,专注于减少传播的核心问题。

对数据科学家的邀请

我们认为这个数据集可以回答许多有影响的问题。因此,我们公开发布它,希望世界各地的数据科学家将使用它来发现新的见解。

如果您对使用有任何疑问,可以在这里联系我们。请注意,截至 3 月 26 日,我们正在努力提高数据可用性,我们预计在 3 月 28 日前完成升级。

组织

创建该数据集的一个挑战是,世界各国政府做出了大量不同的回应。例如,虽然几乎每个国家都隔离新冠肺炎确诊病例,但可能出现的情况是,他们有症状的密切接触者也被要求隔离,或者不顾症状隔离密切接触者,或者他们的整个工作场所被关闭。被隔离的人可能只是被指示呆在家里,或被发出正式命令,可能会或不会得到津贴,可能会或可能不会受到警察的检查。一个国家可能会以如此多的方式对阳性检测做出反应,这对数据收集者来说是一个挑战——我们需要找出哪些信息最终可能是有用的,以及如何最好地组织这些信息。我们的解决方案是以关键字或标签的形式记录数据。这允许我们对数据施加一些结构——在我们发现已经实现了相同措施的地方重用标记——同时允许收集器添加他们认为最终可能重要的任何标记。

该数据集目前包含 200 个独特的标签。标签的最终数量可能在这个数字左右——我们正在努力组织标签集,以减少其数量,但我们也经常发现需要添加新标签的新型对策。

标签的数量给分析带来了挑战——显然不可能推断出每个标签的独特因果关系。虽然有可能使用算法方法来找到似乎具有特别大影响的标签,但是这种方法无法捕获大量的数据结构(例如,我们可以猜测公共交通清洁公共设施清洁可能具有类似的影响)。虽然我们不知道我们最终将如何处理这个问题,但我们目前正在努力改进数据的结构(例如,将“超过 100 个被禁止的集会”替换为“禁止的集会”,强度为 100)。我们还在研究一个聚合标签的方案,以产生一个“准备好”用于数据分析的数据集。

数据源

我们从许多来源获取了数据,包括国家卫生部门和新闻网站,但维基百科的编辑们值得特别感谢,因为他们如此迅速地汇编了如此多的信息,介绍了世界上每个国家在疫情方面的经历。我们还要感谢我们的数据世界,我们从他们那里整合了一个测试数据的数据集。

据我们所知,还有许多其他的政府回应数据库:人道主义数据交换中心在记录世界各地政府回应方面做了令人难以置信的工作,牛津大学发布了令人印象深刻的全面的新冠肺炎政府回应跟踪系统。我们相信我们的每个数据集都有独立的优势,我们正在联系两个团队,讨论如何最好地集中我们的资源。

经验教训

令人惊讶的是,世界上有这么多的人渴望自愿抽出时间来帮助这项研究工作。每当我在任何地方提到这个项目,我都会得到大量的帮助,虽然我真诚地期望许多人可能会做出一点努力,然后被常规生活分散注意力,但我发现大多数来帮助的人都非常专注,不仅致力于填写数据集,而且理解最终目标,并提供如何改进的建议。我非常感谢迄今为止做出贡献的每一个人,我相信这是一个将帮助人们在未来几周和几个月做出拯救生命决定的数据集。

未来的步骤

提高数据可用性是我们当前的首要任务。我们也在努力使这个数据库达到“相对完整”的状态(在这一点上,我们预计将有大约 3000 个测量值),并保持我们的数据是最新的。

我们还希望整合不同类型的数据。例如,我们对获取社交距离测量和口罩使用影响的数据感兴趣——您可以为我们的努力做出的一个简单贡献就是今天就填写这份调查

我们真诚地希望这个数据集以及世界各地数据科学家的技能能够帮助决策者找到度过这场快速发展的危机的最佳方式,在这场危机中,所有后果都是不确定的,每个决定都有可怕的利害关系,每天都很重要。

Python 3.10 中的新功能

原文:https://towardsdatascience.com/new-features-in-python-3-10-66ac05e62fc7?source=collection_archive---------3-----------------------

看看 Python 最新版本中包含的最佳特性

照片由本·斯威特Unsplash 上拍摄

Python 3.10 的第二个 alpha 版本于 11 月初发布,通过它,我们可以一窥 Python 的未来。

一些令人兴奋的举措正在实施,这些举措可能会将未来的 Python 生态系统改变为更明确、更可读的代码——同时保持我们都知道和喜爱的易用性。

由于新的年度发布时间表[ PEP 602 ],我们现在可以看到更短的开发窗口,这意味着我们可以在 2021 年 10 月预期的许多功能已经以某种形式出现,我们将涵盖迄今为止的所有新功能:

**Further Extensions to Type Annotations**
  - Postponed Evaluation of Annotations
  - Type Union Operator
  - TypeAlias Annotation**Why Typing is Important****New Methods and Behaviors
 ** - Equal Length Flag for zip()
  - Bit Count for Integers
  - Mapping for Dictionary Views

如果您更喜欢视频,我们在这里涵盖了本文中的所有内容:

*所有文章图片均由作者制作,除非另有说明。

类型注释的进一步扩展

版本 3.9 引入了对 Python 中的类型提示和注释的大检修和清理。这看起来像是一个持续的趋势,在 3.10 中会进一步增加输入功能。

从 Python 3.0 到现在类型注释的变化时间表。

1.注释的延期评估

类型注释的计算总是在函数定义时执行,这意味着类型注释是以自顶向下的方式逐行计算的。

虽然这看起来合乎逻辑,但这样做有两个问题:

  • 引用尚未定义的类型的类型提示(前向引用)不起作用,必须表示为字符串。我们将需要编写"int"而不是int(尽管这只适用于自定义,而不是内置/预定义类型)。
  • 它降低了模块导入的速度,因为那时会执行类型提示。

因此,相反,注释将存储在__annotations__中,对它们的评估可以一起执行——允许前向引用并首先执行模块导入(减少初始化时间)。

2.类型联合运算符

3.10 引入了带有|操作符的条件逻辑。在注释数据类型时,我们可以将|用作 OR。例如,我们有一个预期为intfloat的变量,我们把它写成int | float,就像这样:

def f(x: **int | float**) -> float:
    return x * 3.142f(1)  # pass
f(1.5)  # pass
f('str')  # linter will show annotation error

在 3.10 之前,等效的操作将使用typing.Union方法编写,就像Union[int, float]一样。

3.TypeAlias 批注

回到前向引用问题,避免前向引用的一个常见解决方案是将它们写成字符串。

然而,将类型写成字符串会在将这些类型赋给变量时产生问题——因为 Python 会假设我们的字符串文字类型注释只是一个字符串。

在我们通常使用类型注释的地方使用该类型注释变量将会返回一个错误。例如:

MyType = "ClassName"  # ClassName is our type annotation
def foo() -> MyType:
    ...

这里,我们试图使用MyType作为类型的别名,但是,MyType将被读取为字符串值——而不是类型别名。

只要在代码的后面定义了ClassName,这就是有效的。目前,这将抛出注释错误。

为了解决这个问题,增加了一个方法来显式地将MyType标识为类型别名:

**from typing_extensions import TypeAlias**MyType: **TypeAlias** = "ClassName"
def foo() -> MyType:
    ...**OR**MyType: **TypeAlias** = ClassName *# if we have defined ClassName already*
def foo() -> MyType:
    ...

为什么打字很重要

虽然这肯定不是一个巨大的、改变游戏规则的举动,但是看到 Python 开发者加倍努力增强类型化特性是非常酷的。

Python 的优势来自于它的易用性和没有陡峭的学习曲线。其中一个原因是我们的代码中不需要显式定义类型。

这可能看起来违反直觉,但是给开发人员选项来定义类型可以极大地增强代码库的可读性和可维护性。例如,从变形金刚库的源代码中提取这些内容:

即使没有上下文,我们也可以阅读这些代码,并立即掌握我们应该期望将哪些数据提供给这些函数、类和方法,以及我们应该期望返回哪些数据类型。

在复杂的代码库(甚至是简单的代码库)中,类型注释可以极大地提高可读性。同时,不是每个人都想(或需要)使用它们——所以一个可选的、无异常的功能达到了完美的平衡。

这些变化表明了对 Python 的类型注释特性的承诺。我们最喜欢的库(和我们自己的代码)更加清晰,这可能会对 Python 生态系统产生有趣的长期影响。

新的方法和行为

除了新的类型变化,我们还对其他核心 Python 功能进行了一些更新和新特性。

邮政编码的等长标志

第一个是 PEP 618,它为zip()函数添加了一个可选的strict标志。如果我们设置了strict=True,如果zip的两个输入长度不相等,就会出现错误。

如果没有 strict=True 标志(左),则不会产生错误,并且较长的列表会被截断以创建压缩生成器。当 strict=True 时,产生一个错误。

新的strict参数允许我们控制zip的行为,而不是盲目地截断不匹配的数据——这将使许多开发人员在未来某个时候不再头疼。

整数的位数

也被称为总体计数,这种新方法允许我们计算一个整数的二进制表示中一的数量。我们写的都是int.**bit_count()**

我们只是返回代表每个整数的二进制值中的正位数:

0   = 00000000
1   = 00000001
2   = 00000010
3   = 00000011
10  = 00001010
11  = 00001011
12  = 00001100
100 = 01100100
101 = 01100101
102 = 01100110

字典视图的映射

三个字典方法dict.keys()dict.values()dict.items()都返回一个字典的不同视图。现在,每个视图对象都添加了一个mapping属性。

这个新属性是一个包装原始字典的types.MappingProxyType对象——如果我们在视图上调用它,我们将返回原始字典。

这就是目前的全部内容——虽然我们进入 3.10 的开发时间表才几个月,但是已经有很多有趣的变化了!

Python 的发展还在继续,看起来随着时间的推移,会有更多有趣的特性加入到这种语言中。

我希望你喜欢这篇文章。如果你想要更多,我已经开始在 YouTube 这里发布编程教程。或者如果你有任何问题、想法或建议——请通过推特或在下面的评论中告诉我。

感谢阅读!

如果您还在使用 Python 3.9,我在这里介绍了完整版本中的所有内容:

[## Python 3.9

有什么新的,下一步是什么?

towardsdatascience.com](/python-3-9-9c2ce1332eb4)

🤖《变形金刚》课程 NLP 的 70%折扣

Python 3.9 中的新功能

原文:https://towardsdatascience.com/new-features-in-python39-2529765429fe?source=collection_archive---------1-----------------------

看看 Python 最新版本中包含的最佳特性

Pablo GuerreroUnsplash 上拍摄的照片

又到那个时候了,Python 的新版本迫在眉睫。现在是测试版(3.9.0b3),我们很快就会看到 Python 3.9 的完整版本。

一些最新的特性令人难以置信地兴奋,在发布后看到它们被使用将是令人惊奇的。我们将讨论以下内容:

  • 字典联合运算符
  • 类型提示
  • 两种新的弦乐方法
  • 新的 Python 解析器——这非常酷

让我们先来看看这些新特性以及如何使用它们。

( 意大利文 )

字典联盟

我最喜欢的新特性之一,语法简洁。如果我们有两个字典ab需要合并,我们现在使用联合操作符

我们有合并操作员|:

a = {1: **'a'**, 2: **'b'**, 3: **'c'**}
b = {4: **'d'**, 5: **'e'**}c = **a | b**
print(c)

**[Out]:** {1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e'}

更新操作符|=,它更新原始字典:

a = {1: 'a', 2: 'b', 3: 'c'}
b = {4: 'd', 5: 'e'}**a |= b**
print(a)

**[Out]:** {1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e'}

如果我们的字典共享一个公共键,将使用第二个字典中的键-值对:

a = {1: 'a', 2: 'b', 3: 'c', **6: 'in both'**}
b = {4: 'd', 5: 'e', **6: 'but different'**}print(a | b)

**[Out]:** {1: 'a', 2: 'b', 3: 'c', **6: 'but different'**, 4: 'd', 5: 'e'}

用 Iterables 更新字典

|=操作符的另一个很酷的行为是能够使用一个可迭代对象用新的键值对更新字典——比如一个列表或生成器:

a = {'a': 'one', 'b': 'two'}
**b = ((i, i**2) for i in range(3))**a |= **b**
print(a)

**[Out]:** {'a': 'one', 'b': 'two', **0: 0, 1: 1, 2: 4**}

如果我们用标准的 union 操作符|进行同样的尝试,我们将得到一个TypeError,因为它只允许dict类型之间的联合。

类型提示

Python 是动态类型的,这意味着我们不需要在代码中指定数据类型。

这没什么,但有时会令人困惑,突然之间 Python 的灵活性变得比其他任何东西都更令人讨厌。

从 3.5 开始,我们可以指定类型,但这相当麻烦。这次更新确实改变了这一点,让我们举个例子:

无类型提示(左)使用 3.9 的 v 类型提示(右)

在我们的add_int函数中,我们显然想给自己加上相同的数字(出于某种神秘的未定义的原因)。但是我们的编辑器不知道这一点,使用+将两个字符串加在一起是完全可以的——所以不会给出警告。

我们现在可以做的是将预期的输入类型指定为int。利用这一点,我们的编辑立即发现了问题。

我们还可以非常具体地了解所包含的类型,例如:

类型提示可以在任何地方使用——多亏了新的语法,它现在看起来更简洁了:

我们将 sum_dict 的参数指定为 dict,返回值指定为 int。在测试定义期间,我们也确定它的类型。

字符串方法

不像其他新功能那样吸引人,但仍然值得一提,因为它特别有用。添加了两个用于删除前缀和后缀的新字符串方法:

"Hello world".remove**prefix**("He")

**[Out]:** "llo world"

Hello world".remove**suffix**("ld")

**[Out]:** "Hello wor"

新解析器

这是一个看不到的变化,但有可能成为 Python 未来发展中最重要的变化之一。

Python 目前主要使用基于 LL(1)的语法,该语法又可以被 LL(1)解析器解析,该解析器从上到下、从左到右解析代码,并且只对一个标记进行前瞻。

现在,我几乎不知道这是如何工作的——但我可以给你一些当前 Python 中由于使用这种方法而出现的问题:

  • Python 包含非 LL(1)语法;正因为如此,当前语法的某些部分使用了变通方法,造成了不必要的复杂性。
  • LL(1)在 Python 语法中造成了限制(没有可能的变通办法)。这个问题强调了下面的代码根本无法使用当前的解析器实现(引发一个 SyntaxError ):
with (open("a_really_long_foo") as foo,
      open("a_really_long_bar") as bar):
    pass

所有这些因素(以及更多我无法理解的因素)都对 Python 产生了重大影响;它们限制了语言的发展。

基于 PEG,的新解析器将让 Python 开发者拥有更大的灵活性——从 Python 3.10 开始我们将开始注意到这一点。

这是我们对即将到来的 Python 3.9 所能期待的一切。如果你真的等不及了,最新的测试版 3.9.0b3 — 在这里可以找到。

如果您有任何问题或建议,请随时通过 Twitter 或在下面的评论中联系我们。

感谢阅读!

如果您喜欢这篇文章,并且想了解 Python 中一些鲜为人知的特性,您可能会对我以前的文章感兴趣:

[## 鲜为人知的 Python 特性

一些鲜为人知和被低估的 Python 特性的示例

towardsdatascience.com](/lesser-known-python-features-f87af511887)

scikit 中的新功能-了解

原文:https://towardsdatascience.com/new-features-in-scikit-learn-f0ceb7e9d2ad?source=collection_archive---------26-----------------------

照片由 Jungwoo HongUnsplash 上拍摄

0.23 版最新发展概述

如果你对数据科学感兴趣并使用 python,那么 scikit-learn 可能是你联系人列表中的快速拨号。您可能需要更新此联系人。

两个月前,scikit-learn 发布了0.23 版本 引入了许多令人兴奋的特性和改进。该版本将至少兼容 Python 3.6 。这篇文章将引导你了解一些有趣的新增内容。稍后,我还会先睹为快地介绍目前正在开发的下一个版本 0.24 中即将推出的一些特性。

主要特点

1)新的回归模型

Scikit-learn 引入了以下三个新的回归变量:

a)泊松回归变量
b)伽马回归变量
c)特威迪回归变量

from sklearn.linear_model import PoissonRegressor
from sklearn.linear_model import GammaRegressor
from sklearn.linear_model import TweedieRegressor

这三种模型都被归类为广义线性模型(GLMs ),支持非正态损失函数。它们在建模误差遵循非正态分布的分布的情况下很有用,例如泊松或伽马分布总是正的,正如Kida所很好地解释的那样。

选择哪种分布在很大程度上取决于用例,例如目标变量的正性质,分布的尾部如何,等等。潜在应用的几个例子是风险建模、气候事件预测和保险定价。

2)稳定和快速的 k 均值估计器

众所周知的算法将样本分成预定义数量的具有相等方差的聚类,该算法现在应该被优化,并且对于大样本具有比 0.23 之前版本更好的可扩展性。

3)改进的基于直方图的梯度提升估计器

改进是双重的:首先,回归器和分类器,即HistGradientBoostingClassifierHistGradientBoostingRegressor都支持模型训练期间的样本权重,如这里的所示

其次,如果已知先验,现在可以指定 单调约束 的性质,即特性可以对响应/目标变量具有的约束。例如,在预测房价时,较大的卧室面积可能会对价格产生积极影响(约束值= 1),而距离市中心的距离可能会对价格产生消极影响(约束值= -1)。值为 0 将表示不受约束的要素。

4)改进的套索和弹性网

两个著名的线性回归器现在支持模型训练期间的样本权重。在功能上,这导致了一个新的参数sample_weight,它在fit()函数中接受一个数组或一个列表,代表数据集中每个样本的权重。

5)管道和估算器的交互式 HTML 可视化

如果你正在 Jupyter 笔记本上建模,你现在可以交互地可视化你的模型管道和估算器的概要工作流程。这需要调用display='diagram'选项。此功能的交互性质允许您悬停在某个估计器上,并扩展它以获得更多细节。看看这个很酷的官方演示。****

其他有趣的功能

1)将内置数据集作为数据帧加载

Scikit-learn 提供了几个内置数据集,例如load_irisload_digitsload_breast_cancerload_diabetesload_wineload_linnerudfetch_california_housing.现在您可以使用关键字as_frame=True将这七个数据集加载为 pandas DataFrames

早些时候,这些嵌入的数据集被加载为asklearn.utils.Bunch类型。

from sklearn.datasets import load_iris

df = load_iris(as_frame=True)# 0.25 onwards, type(df) should return pandas.core.frame.DataFrame

2)在一次热编码期间丢弃所选类别

标准例程preprocessing.OneHotEncoder对分类特征进行一次热编码,现在允许丢弃每个二元特征的第一个类别(只有两个类别)。这是用标签drop='if_binary'实现的。具有 1 个或 2 个以上类别的功能将不受此标志的影响。最新版本还有一个更高效的OneHotEncoder实现。

3)高斯斑点的中心

在生成各向同性高斯簇(斑点)时,你现在可以通过return_centers=True参数访问每个簇的中心。

from sklearn.datasets import make_blobsX, y, centers = make_blobs(n_samples=20, centers=3, n_features=2,
                  random_state=0, return_centers=True)

即将到来的 v-0.24 中即将到来的变化

很快,目前正在开发的下一个版本 0.24 就要发布了。以下是一些你可以期待的有趣特性。

1)估算值的逆变换

来自sklearn.imputeSimpleImputer允许对数据集中的缺失数据进行插补。很快,就可以将估算的数据转换回原来的状态。首先,需要在调用SimpleImputer()时设置一个标志add_indicator=True,然后在这个很酷的功能上使用函数inverse_transform.阅读更多信息

2)平均绝对百分比误差(MAPE)

这将是回归问题可用的新评估指标。这种度量对目标变量的全局缩放不敏感。在数据数量级差异较大的情况下,通过计算误差相对于真实值的相对百分比,它可以作为误差的公平衡量标准,例如,如下面的代码片段所示。下面例子中的mean_absolute_error将是 100001.8。

平均绝对百分比误差。ϵ是一个任意小的正数,例如 1e-6。变量 y 和 y_hat 代表真实值和预测值。

# Implementation in upcoming version 0.24from sklearn.metrics import mean_absolute_percentage_errorimport numpy as npy_true = np.array([1, 10, 1e6])
y_pred = np.array([0.9, 15, 1.2e6])mape = mean_absolute_percentage_error(y_true, y_pred)
>>> 0.2666....#============ My implementation below ============eps = 1e-6dev = [np.abs(x-y)/max([eps, np.abs(x)]) for x, y in zip(y_true,
                                                          y_pred)]mape = sum(dev)/len(dev)
>>> 0.2666....

3)**confusion matrix plot**中的可选颜色条

在绘制混淆矩阵时,颜色条现在是可选的。如果不需要的话,这就不需要一个替代解决方案来隐藏色条。

plot_confusion_matrix(estimator, X, y, colorbar=False)

这让我想到了这篇文章的结尾。在你更新了你的 scikit-learn 并想用 python 可视化数据之后,你可以关注我最近的文章Matplotlib 3 的新特性** 这里。**

机器学习快乐!

新一代计算机视觉:AWS DeepLens

原文:https://towardsdatascience.com/new-generation-computer-vision-aws-deeplens-45052e39b4bc?source=collection_archive---------54-----------------------

如何使用 AWS DeepLens 部署对象检测模型

( 来源 )

AWS DeepLens 可以被描述为一种可配置的摄像机,使用户能够在更短的时间内找到练习实时流媒体处理技术的机会。

AWS DeepLens 可能部署三种不同类型的建模。在这篇文章中,我们将研究预先训练好的物体检测模型。

[## 新一代计算机视觉:AWS DeepLens

AWS DeepLens 是一个可编程的摄像机,使开发人员能够开始实践深度学习…

www.commencis.com](https://www.commencis.com/thoughts/new-generation-computer-vision-aws-deeplens/)

  1. 预训练模型

该项目使用户能够将初始训练的模型部署到他们的设备上。可以通过以下路径选择 项目>创建项目

预训练模型导入项目页面(图片由作者提供)

2。亚马逊 SageMaker 训练模型

使用此模型类型,您可以在 AWS SageMaker 中创建和训练您的模型,并提供以下信息,然后单击导入按钮:“作业 ID”、“模型名称”、“模型框架”。

亚马逊 SageMaker 训练模型选择页面(图片由作者提供)

为了能够使用这种模型类型将您的模型部署到您的设备中,AWS Sagemaker是打开一个 SageMaker 笔记本实例 作为代码编辑器所必需的服务。

如果您是 AWS 服务的新手,以前从未使用过 AWS SageMaker,AWS 会为您提供一个 AWS 自由层 。通过使用这个帐户,您可以在头两个月开始使用 AWS SageMaker。

3。外部培训模型

通过选择这种类型的模型,预计您已经在 AWS 环境之外训练了您的模型,并将您的模型上传到 AWS S3 存储桶中。为了能够将您的模型上传到 DeepLens,您需要填写以下字段,然后单击导入按钮:“模型工件路径”、“模型名称”、“模型框架”。

外部培训模型选择页面(图片由作者提供)

AWS 深度镜头

在开始使用任何服务之前,必须在链接中设置必要的权限,以便能够正确使用它们。将使用的第一个服务是 AWS DeepLens。为了能够使用此服务,您的地区将从以下地区中选择:

欧洲(法兰克福)欧盟-中部-1
美国东部(北弗吉尼亚州)美国东部-1
亚太地区(东京)AP-东北-1

在设置开发环境策略和区域之后,通过使用 AWS 管理控制台,在“Find Services”标题下,您将能够通过使用 search 按钮键入服务的名称来快速找到任何服务,如下所示。

AWS 管理控制台(图片由作者提供)

此页面包括关于服务的基本信息。更多详细的技术细节,可以访问“更多资源选项卡下的文档。**

AWS Deeplens 介绍页(图片由作者提供)

设备注册

产品拆箱后,第一步是将您的设备正确注册到 AWS DeepLens 服务中。

注册设备介绍屏幕(图片由作者提供)

将设备连接到 PC 后,点击 【注册设备】 按钮,然后选择您的硬件版本,点击如下图所示的 开始 按钮。

设备硬件版本选择(图片由作者提供)

首先,应使用适配器将设备连接到电源,并打开电源按钮。当设备打开时,电源 led 将变为蓝色。

将 USB 电缆插入设备的“ 注册 ”端口,即可将 PC 与设备连接。

DeepLens 注册 USB 口(图片由作者提供)

当您能够成功注册 AWS DeepLens 时,您将能够通过“ 已注册 ”状态在页面左侧的资源>设备选项卡下看到您的设备。

设备选项卡(图片由作者提供)

部署预先训练的模型

在“ 项目 ”部分下,需要点击位于右上方的“ 新建项目 按钮才能够看到项目类型。

创建新项目(图片由作者提供)

在这一步中,需要选择一个预先填充的项目模板。选择“ 使用项目模板 ”作为项目类型,并从列表中选择“ 对象检测 ”,向下滚动到屏幕,单击“ 创建 ”。

选择项目模板(图片由作者提供)

指定项目详细信息 页面中,接受项目名称和描述提要中的默认值。

指定项目细节部分(图片由作者提供)

在同一页面的底部,您将看到项目内容选择设置。对于 型号功能, 接受默认值并点击 【创建】 继续。

项目内容部分(图片由作者提供)

在此步骤中,您将把对象检测项目部署到您的设备上。您当前创建的项目将成功列在“ 项目 ”部分。查看完相应的项目后,点击单选按钮,并在右上方选择【部署到设备】

项目页面(图片由作者提供)

【目标设备】 页面上,您需要选择您的设备并点击 【查看】 按钮。

目标设备页面(图片由作者提供)

将有一个额外的页面,其中有您的部署细节,包括关于 【类型】【λ】 【型号】的信息。 仔细检查后,选择 【部署】 按钮继续。

审查和部署模型(图片由作者提供)

当点击“部署”时,您的模型将通过向 AWS DeepLens 显示其下载百分比上传到您的设备。

正在向设备部署(图片由作者提供)

部署后,在“ 设备 ”选项卡上,在您的项目部署后,单击 【查看输出】 选择您的浏览器进行相应的流认证导入。

流媒体认证的浏览器选择(图片由作者提供)

模型输出

有两种不同的方式来查看我们的模型输出。下面列出了这些,并在单独的主题中进行了解释。

  • JSON 格式的 MQTT 主题值输出
  • 项目流
  1. AWS 物联网核心— MQTT 话题值

成功导入证书后,浏览器会通过弹出屏幕要求您选择合适的证书版本。

当您想要 JSON 格式的输出时,您可以 【复制】 唯一生成的主题,并点击【AWS 物联网控制台】** 打开 AWS 物联网核心 服务。**

JSON 格式的输出(图片由作者提供)

复制后的主题格式如下" $ AWS/things/deep lens _***<uuid>***/infer "粘贴到 【订阅主题】 下,点击 【发布到主题】 按钮。

AWS 物联网核心— MQTT 客户端(图片由作者提供)

点击 发布到主题 后,JSON 格式的输出开始发布。如果您想停止发布,可以选择右上方的 【暂停】

AWS 物联网核心—主题发布后(图片由作者提供)

2。项目流

在为我们的浏览器导入证书后,我们可以单击“ 【视频流】 部分下的“ 【查看视频流】 来打开一个新的选项卡,其 IP 地址为“ 192.168.1.47:4000”。

视频流部分(图片由作者提供)

当在指定的 IP 地址上启用流时,我们可以看到两个不同的选项卡。第一个选项卡称为“ ”项目流“ ,这是应用了我们的对象检测模型的流。在这个流中,我们看到对象周围的蓝色框架,在框架的顶部,检测到对象的名称及其可能性百分比。因为模型是在有限数量的对象中训练的,所以不能识别帧中的所有对象。如果我们想要检测比预训练的对象检测模型更多的对象,我们需要通过导入外部自定义模型 来导入我们的自定义模型。

项目流输出(图片由作者提供)

第二个流叫做 “直播流”。 当我们选择此选项卡时,我们可以查看普通摄像机流,它显示帧的速度比“项目流”快,因为它没有在对象上应用任何模型。

直播流输出(图片由作者提供)

非常感谢您的提问和评论!

参考文献:

  1. 自动气象站深度镜头
  2. AWS 物联网核心
  3. AWS Lambda
  4. AWS SageMaker
  5. AWS SageMaker 定价
  6. 亚马逊网络服务 YouTube 频道

面向新常态的新黑客马拉松

原文:https://towardsdatascience.com/new-hackathon-for-the-new-normal-fad366e62cbd?source=collection_archive---------54-----------------------

如果没有别的,我们已经通过疫情了解了我们的互联网的力量以及还有多少工具有待开发。作为开发人员,我们正处于一个激动人心的位置,为我们的新常态设定标准,并为下一个前沿领域铺平道路。本周末,我们将举办我们的第一次先锋黑客马拉松,试图为那些与世隔绝的人提供社区,并提供一点奖励激励的、富有成效的乐趣来对抗全球幽居热。

帮助将真实世界上传到互联网。让数十亿呆在家里的人在网上工作变得更有趣。在 Zoom 通话中叠加心率。提高视频会议质量。建立一个串联的竞争对手,一个朋友而不是同事。舞台是你的。

我们将于本周六上午 11 点开始。在 24 小时内,您将有机会体验我们定期在网上举办的许多活动:专家 ama、反馈会议和餐饮。我们也在尝试一些新的形式:有奖迷你黑客、剪刀石头布锦标赛、《我的世界》@午夜和实时项目投票。

由专家、你的黑客伙伴和我们选出的最佳项目,将有机会在评委面前展示他们的作品,并向全世界直播。评委包括 Zeit 首席执行官 Guillermo Rauch ,Repl.it 首席执行官 Amjad Masad ,前可汗学院研发负责人和 iOS 构建者 Andy Matuschak 和 Tandem 首席执行官 Rajiv Ayyangar 等。

前三名项目有一个$5k 现金奖金池和超过$150,000 的开发者积分。每个参与的人都可以免费获得三个月的 Repl.it。最重要的是,你将有机会见到来自世界各地的黑客——目前有 50 多个国家的代表。

物理会议中心有明显的能量,当独自在家时,滚动浏览项目提要时,这种能量很容易丢失。我们的目标是把这种能量带到网络上,在一个 24 小时在线黑客宫殿里。

在这里报名:https://pioneer.app/hackathon

杰克逊&先锋队

Java 15 的新特性

原文:https://towardsdatascience.com/new-java-15-features-47dac2333aa8?source=collection_archive---------28-----------------------

本地记录和密封类在 Java 15 中找到了自己的路

Photo by 五玄土 ORIENTO on Unsplash

保持六个月周期的传统,在 2020 年 3 月 17 日发布了 Java 14 之后,我们现在有了 Java 15,下一个非 LTS 版本将于 2020 年 9 月 15 日推出。

下面快速浏览一下 Java 15 的一些特性:

  • 密封类(预览)— JEP 360
  • instanceof(第二次预览)— JEP 375 的模式匹配
  • 记录(第二次预览)— JEP 359
  • 文本块(标准)— JEP 378
  • 隐藏类— JEP 371
  • 移除 Nashorn JavaScript 引擎— JEP 372
  • 重新实现传统 DatagramSocket API — JEP 373
  • 禁用和反对偏向锁定— JEP 374
  • 谢南多厄:一个低停顿时间的垃圾收集器——JEP 379
  • 删除 Solaris 和 SPARC 端口— JEP 381
  • 外部存储器访问 API(第二个孵化器)— JEP 383
  • 不赞成激活 RMI 进行删除— JEP 385

Mac OS 上的 Java 15 安装设置

  • 要开始使用 Java 15,请从这里的下载 JDK。
  • 复制并提取/Library/Java/JavaVirtualMachines中的 tar 文件,如下图所示:
$ cd /Library/Java/JavaVirtualMachines 
$ sudo cp ~/Downloads/openjdk-15_osx-x64_bin.tar.gz /Library/Java/JavaVirtualMachines$ sudo tar xzf openjdk-15_osx-x64_bin.tar.gz 
$ sudo rm openjdk-15_osx-x64_bin.tar.gz

一旦完成,使用任何文本编辑器打开bash_profile。我用的是vim ~/.bash_profile。将 Java15 的路径设置为 JAVA_HOME,保存更改并执行source ~/.bash_profile以反映更改。

export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-15.jdk/Contents/Home

最后,您已经准备好使用 Java 15 编译和运行程序了。我们将使用 JShell,一个交互式 REPL 命令行工具,用于快速测试 Java 15 的新特性。

值得注意的是,Java 15 中发布的许多特性都在预览版中。这意味着尽管他们现在正在全力工作,但将来可能会有所改变。有些可能会成为标准,或者在下一个发布周期中被删除。为了测试预览功能,您需要在运行 JShell 或 Java 程序时显式设置--enable-preview,如下所示:

jshell --enable-preview javac --release 15 --enable-preview Author.java

在接下来的几节中,让我们讨论 Java 15 中的重大语言变化。

1.密封类(预览)

Kotlin 中的密封类已经存在一段时间了,Java 15 最终引入了这个特性,以便更好地控制继承。

顾名思义,密封类允许您将类层次结构限制或允许给某些类型。

这对于模式匹配非常有用,因为您有特定数量的类要在它们之间进行switch

以下语法在 Java 15 中定义了一个密封类:

public sealed class Vehicle permits Car, Bike, Truck { ... }

所以,上面的代码意味着,只有在关键字permits之后定义的类才被允许扩展Vehicle sealed类。

如果您已经在与Vehicle相同的文件中定义了类CarBikeTruck,您可以省略关键字 permissions,编译器将隐式处理它,如下所示:

sealed class Vehicle {...}final class Car extends Vehicle {...} 
final class Bike extends Vehicle {...} 
final class Truck extends Vehicle {...}

正如你在上面看到的,我们已经定义了每个类的最终修饰符。现在,你需要记住密封类的一个重要规则:每个允许的类都必须设置一个显式修饰符。可以是final也可以是sealed或者non-sealed

以下是每个修改器如何影响继承:

  • 声明为final的允许子类不能进一步扩展。
  • 声明为sealed的允许子类可以进一步扩展,但是只能由该子类允许的类来扩展。
  • 一个被允许的子类可以被声明non-sealed可以被任何类进一步扩展。超类不能进一步限制这个类层次结构中的子类。

在 Java 15 之前,开发者只能使用final关键字或范围修饰符来控制继承。因此,在定义类层次结构时,密封类为 Java 开发人员带来了额外的灵活性。

Java 的反射 API 还获得了两种处理密封类的新方法:

java.lang.constant.ClassDesc[] getPermittedSubclasses();boolean isSealed()

2.记录(第二次预览)

记录是作为 Java 14 中的预览特性引入的,目的是在编写基于 POJO 的数据载体类时减少样板代码。这在 Kotlin 中以数据类的形式存在了很长时间。

现在,有了 Java 15,记录得到了第二次预览。虽然没有任何重大变化(只是一些小的增加),但仍然有一些您应该知道的主要说明和限制:

  • 在 Java 15 之前,人们可以在记录中声明原生方法(尽管这不是一个好主意)。现在,JEP 明确禁止在记录中声明本机方法。可以理解的是,定义一个native方法通过引入外部状态依赖偷走了 USP 记录。
  • 对应于记录类的记录组件的隐式声明字段是final,现在不应该通过反射修改,因为它将抛出IllegalAccessException

记录意味着数据载体类,您应该完全避免在其中定义本机方法。

密封类型的记录

我们知道记录是最终的,不能延长。令人高兴的是,记录可以实现接口。

因此,您可以定义一个密封的接口,并通过以下方式在您的记录中实现它们:

sealed interface Car permits BMW, Audi { ... } 
record BMW(int price) implements Car { ... } 
record Audi(int price, String model) implements Car { ... }

地方志

也可以在方法中定义记录来存储中间值。与本地类不同,本地记录是隐式静态的。这意味着它们不能访问变量和封闭方法的实例成员,这实际上很好,因为它防止了记录捕获值。

本地记录对于以前必须创建助手记录的 Java 开发人员来说是一大福音。

使用以下方法,了解本地记录的引入如何帮助在流 API 中执行值的计算:

List<Merchant> findTopMerchants(List<Merchant> merchants, int month){
// Local record
record MerchantSales(Merchant merchant, double sales) {}return merchants.stream().map(merchant -> new MerchantSales(merchant, computeSales(merchant, month)))
.sorted((m1, m2) -> Double.compare(m2.sales(), m1.sales()))
.map(MerchantSales::merchant)
.collect(toList());}

结论

虽然上面两个是 Java 15 中的两个主要语言特性,但我们在第二个预览版中也有模式匹配以获得用户反馈,文本块现在是一个标准特性,最重要的是一个新的隐藏类特性。

隐藏类是与框架开发者相关的 JVM 特性。它允许通过使用Lookup::defineHiddenClass定义类实现来使它们不可被发现。这样做的话,既不能使用Class.forName找到这样的类,也不能在字节码中引用它们。

这些是 Java 15 中引入的主要变化。

新泽西正在成为新冠肺炎感染的新伦巴第

原文:https://towardsdatascience.com/new-jersey-is-on-the-path-to-be-the-new-lombardy-for-covid-19-infections-bdd2d44948d2?source=collection_archive---------34-----------------------

美国的新泽西州和意大利的伦巴第地区在美国报告数据的前 18 天的人口密度、总人口和活跃新冠肺炎病例方面非常相似。新泽西州大约有 890 万人口,密度约为每平方英里 1213 人。伦巴第大约有 1000 万人口,每平方英里 1100 人。意大利总人口密度为每平方英里 533 人,总人口约 6040 万。这对新冠肺炎的传播意义重大,因为人们普遍认为在人口更密集的中心发生的人与人之间更密切、更频繁的互动会导致病毒更快速的社区传播。还推测新泽西和意大利在实施广泛测试之前已经建立了社区传播。从第 1 天到第 18 天,当新泽西州的活跃案件的增长与意大利的增长重叠时,新泽西州的可能轨迹出现了一幅格外严峻的画面。

新泽西和意大利每天的活动和新病例增加了一倍,并实施了抑制措施。数据来源:【https://github.com/CSSEGISandData/COVID-19

上图以暗黄色条显示了意大利的活跃病例(在意大利疫情爆发的早期主要集中在伦巴第),橙色条显示了该国每天的新增病例。新泽西州的活动案例用绿色条显示,每天的新案例用蓝色条显示。所有案例数据都对应于左边的 y 轴。来自这两个地区的数据从每个地点的明显“开始”起相互重叠,并以天而不是离散的日期向前发展,因为检测到的开始发生在每个地点的不同时间。意大利数据的第一天是 2 月 21 日,新泽西数据的第一天是 3/10。以天为单位的翻倍率(或病例以当前增长率翻倍所需的时间)每天计算一次,意大利用灰色绘制,新泽西用绿色绘制,对应于代表天数的右侧 y 轴数字。垂直黄线表示伦巴第和整个意大利实施缓和措施的日期。绿色竖线表示新泽西州关闭所有非必要业务的日期,并命令居民待在家中。值得注意的是,相比意大利,新泽西将更多的商业开放视为“必需”,而且自 3 月 20 日起,意大利居民受到了更严格的限制。

在疾病发展的最初几天,新泽西州的倍增时间一直低于意大利——这意味着新泽西州的病例倍增时间更短。从 3 月 26 日的一份报告中可以清楚地看到,伦巴第仍然受到严重影响,病例在一天之内跃升了 2500 例,该地区仍然严重影响着意大利的总体数字——所以这种比较可能仍然成立。

编者按: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里

新报:塑造行为的激励

原文:https://towardsdatascience.com/new-paper-the-incentives-that-shape-behaviour-d6d8bb77d2e4?source=collection_archive---------17-----------------------

人工智能校准和安全

因果模型如何描述代理人的动机。

瑞安·凯里 和埃里克·朗罗伊,介绍 塑造行为的激励机制。

机器学习算法通常非常有效,但很难确定它们的安全性和公平性。通常,机器学习系统的属性是通过测试来建立的。然而,即使系统在测试环境中表现安全,在部署时也可能表现得不安全或不公平。或者,可以通过分析输入扰动个体决策网络激活来研究模型的属性,但这通常很困难、耗时,并且对专业知识要求很高。

我们的替代方法不是检查或测试单个模型,而是观察给定的培训环境是否会刺激不安全或不公平的决策。

这种方法并不是全新的——激励是一个直观且切题的讨论对象。例如,参见下面 Stuart Russell 对竞争推荐系统的激励的讨论。(其他例子包括哈德菲尔德-门内尔等人的注释 1和史蒂夫·奥莫亨德罗的基本人工智能驱动。)

图片来自 Pixabay

放入[社交媒体推荐]机器的目的是什么?给人们提供他们想点击的东西,因为这是我们赚钱的方式。你如何最大化点击率——你只是给人们发送他们喜欢点击的东西,对吗?就这么简单。事实上,这不是算法在做的事情…这不是强化学习的工作方式。强化学习通过改变世界的状态来最大化回报。在这种情况下,世界的状态是你的大脑……[所以]它以一种更可预测的方式改变你,这样它就可以给你发送它知道你会点击的东西。”—斯图尔特·罗素

改变用户行为的压力可以被视为一种不受欢迎的激励。像这样的基于激励的论点是强有力的,因为它们独立于系统架构而应用。然而大多数 以前的 关于激励的工作都集中在具体的问题上,这使得它很难应用到新的问题和情况中。在我们最近的工作中,我们已经开始开发一个通用的激励的因果理论,它允许我们在一个统一的框架中陈述和制定多种公平和安全问题的解决方案。

在我们的理论中,一个激励,粗略地说,是一个代理人为了最好地实现其目标而必须做的事情。我们考虑两种类型的激励:当代理必须控制其环境的某个组件以最大化其效用时,存在控制激励(例如上面的社交媒体推荐示例中的“用户意见”)。当智能体的决定必须对其环境的某个组成部分做出因果反应时,就会出现反应激励,例如,移动机器人在崎岖地形上导航时应该注意障碍物的位置。

控制激励

示例

为了使激励分析形式化,我们可以使用因果影响图。因果影响图通过将决策问题分解成图形来表示,其中每个变量都依赖于其父变量的值(如果有箭头 X- > Y,则 X 是 Y 的父变量)。它由三种类型的节点组成:

例如,斯图尔特·罗素的社交媒体操纵例子可以用下面的影响图来表示。

控制对用户意见的激励

在这个模型中,推荐算法选择一系列帖子显示给用户,以最大化用户点击的帖子数量。如果我们把用户对每个帖子的回复看作是一个独立的事件,那么用户欣赏的内容就会收到更多的点击。然而,这些职位也有间接影响。如果用户浏览了许多两极分化的文章,那么他们可能会采纳其中的一些观点,并且在点击内容方面变得更加可预测。这可以允许该算法在该系列中后面的帖子上实现更高的点击率,并且意味着对受影响的用户意见有控制激励。

为了减轻 Stuart Russell 的担忧(同时保留系统的功能),我们希望去除对用户意见的控制激励,同时保留对点击的激励。我们可以重新设计这个系统,这样就不会因为真实点击率而获得奖励,而是因为基于原始用户意见模型的帖子的预测点击而获得奖励。以这种方式训练的代理人会认为用户意见的任何修改都与改进其性能无关。

为了在实践中工作,点击预测本身必须不包括用户意见修改的影响。我们可以通过使用假设帖子之间独立的预测模型来实现这一点,或者通过只向每个用户显示一个帖子来学习。这说明了在考虑激励时的一个重要考虑:只有当没有一个变量(如预测的点击)作为另一个变量的“代理”时,一个变量(如点击)缺乏激励才有实际意义。否则,即使对点击没有控制激励,对预测点击的控制激励也可能系统地诱导与对点击的控制激励所诱导的相同类型的决策。在未来的工作中,我们计划分析代理变量会产生什么样的隐性激励。

对用户意见没有控制激励

这个例子符合控制激励与安全和性能相关的循环模式:一些控制激励对于良好的性能是必要的,但是错误的控制激励可能导致系统不安全。例如,AlphaGo 工作得很好,因为它有保护其石头(性能)但不保护其服务器(安全)的控制激励。确保控制激励符合用户的偏好是安全激励设计的核心问题。

定义控制激励

既然我们有了控制激励的基本直觉,我们可以考虑如何定义它们。假设有某个变量 X(比如用户的政治观点)。我们可以考虑如果 AI 系统表现不同,X 可以获得的。如果将 X 设置为任何可达到的值 X(如“左翼”、“中间派”或“右翼”)会改变绩效,那么我们说 X 上有一个控制激励。根据这个定义,从决策到效用的因果路径上的任何变量都可能出现控制激励。

Everitt 等人定义了干预激励的相关概念。如果可以通过直接设置其值来获得效用,则变量面临干预激励。(这相当于控制的值不为零。干预激励对代理人行为的预测不如控制激励,因为它们没有考虑代理人能够用其决策影响什么——因此我们的论文的标题是“塑造行为的激励”。

让我们回到我们的例子来强调这两种激励之间的区别。所有导致效用的变量都有干预激励,但只有那些也在行动下游的变量才有控制激励。

回应激励

最佳决策必须响应哪些事件?

这个问题对人工智能的安全和公平都有重要的影响。为了人工智能的安全,如果变量是一个关机命令,人工智能系统的行为最好能对这个变量作出反应。这样的反应激励不足以保证安全,但这是一个好的开始。相反,如果缺乏这种激励,那么最优政策很容易变得不安全。同样理想的是,对人类的一般命令有一个响应激励,对价值学习系统有一个对人类价值的响应激励。

这对公平也有重要影响。如果种族或性取向等敏感变量有反应激励,那么这表明训练算法的激励是反事实的不公平。我们在论文中指出,如果在一个敏感的属性上有一个反应激励,那么所有的最优政策相对于该属性都是反事实不公平的。我们的论文采取了一些步骤来定义不公平激励:主要关注如何在给定的图表中排除不公平激励的存在。

因此,响应激励的可取性取决于变化的变量。对于一些变量,我们希望人工智能系统对它们做出响应,以便安全地运行。对于其他变量,如果一个人工智能系统对此做出反应,那么我们认为该系统是不公平的。

应用、限制和后续步骤

这个理论已经通过它的应用证明了它的价值。除了讨论的安全和公平问题,还被应用于分析 AI 拳击方案奖励篡改问题 ( 博文)。正如公平的例子所示,这个理论并不一定要求代理人进行因果推理或有因果模型,只是我们,设计者,可以对代理人的行为进行因果推理。

从长远来看,我们的愿望是,当研究人员预计到可能的安全或公平问题时,他们会使用这一理论来对他们的人工智能系统进行激励分析。在应用我们的图形标准来自动辨别存在哪些激励之前,这通常涉及绘制各种代理组件如何能够配合在一起的因果图,并形成关于应该(或不应该)存在哪些激励的判断。在非常乐观的情况下,激励分析将成为建立人工智能系统可信度的标准工具,类似于统计方法如何用于描述人工智能性能。但在短期内,我们预计使用这些方法需要一些工作,因此我们很乐意在需要的地方提供建议。

这个理论还没有完成,因为它目前仅限于单代理设置。我们正在努力将其扩展到多决策的情况,最终,我们希望它能够处理多个代理。该文件可从以下网址获得:

r .凯里、E .朗罗伊、T .埃弗里特和 S .莱格。塑造行为的激励机制 (2020),SafeAI@AAAI。

迁移学习的新视角

原文:https://towardsdatascience.com/new-perspectives-on-transfer-learning-285035f01589?source=collection_archive---------74-----------------------

构建机器学习概念

映射关于域、任务和顺序的问题

在专栏“构建机器学习概念”中,我试图从机器学习(ML)空间中提取概念,并将它们投射到新的、可能不寻常的框架中,以提供新的视角。该内容面向数据科学社区的人们,以及对 ML 领域感兴趣的精通技术的个人。

由作者创建。包括由 Vectra AItaviphoto 通过 iStock 制作的图形。

介绍

构建机器学习概念的最后一期致力于引入混合处理,并将其与主动学习和直推式&归纳半监督学习一起映射到一个新的框架中。

引发我写这篇文章的原因是,如今迁移学习无处不在,并向许多方向发展。它有各种各样的形状和颜色,但是方法论缺乏一个更高层次的框架。让我们详述一下。

框架:迁移学习的八种途径

转移学习(TL)可能是深度学习中最重要的发展之一,使其适用于现实世界的应用。许多人可能还记得“ImageNet 时刻”,当时 AlexNet 击败了 ImageNet T21 竞赛,并使神经网络成为计算机视觉挑战的标准。然而,有一个问题——你需要大量的数据来完成这项工作,而这些数据通常是不可用的。

随着 TL 的引入,这个问题得到了解决。这使我们能够在 ImageNet 上预先训练一个卷积神经网络 (CNN),冻结第一层,只在一个较小的数据集上重新训练它的头部,使 CNN 进入行业大规模采用。

2018 年,自然语言处理 (NLP)的这个“ImageNet 时刻”终于到来了。我们第一次从重复使用静态单词嵌入转向共享完整的语言模型,这显示了捕捉一系列语言信息的非凡能力。在这一发展中,塞巴斯蒂安·鲁德发表了他的论文关于 NLP 的神经 TL,该论文已经绘制了 TL 中四个不同概念的树形分解图。

映射维度

这让我思考:使用一两个数据集的洞察力来学习一项或多项任务有哪些不同的方式。这些是我能想到的维度:

  1. 任务:我们是在预训练和微调阶段尝试教我们的网络相同的任务,还是利用第一个任务的知识将其用于不同的第二个任务?(例如,预训练“动物分类器”并将模型微调为“狗品种分类器”与使用“动物分类”网络的主干来训练“绒毛耳朵对象检测器”)
  2. 域:我们的数据集来自同一个域还是不同的域?(例如,两个数据集都是“在野外”拍摄的彩色图像,而一个数据集是灰度 x 射线图像)
  3. 顺序:我们是同时学习任务还是依次学习?(例如,我们共同计算所有任务的损失,并将其用于训练,而不是完成第一次训练,移植网络的权重,然后开始第二次训练)

我也考虑过增加“重要性”来包含辅助任务,但是我们不要把事情弄得太复杂。因此,我最终得到了与 Ruder 用于 NLP 的维度相似的维度。让我们绘制出所有八种组合,由三个二元维度产生。

轻量级定义

我将对这些术语做出一些自以为是的决定,这些决定没有广泛的文献支持——请耐心等待。

  • 任务微调:当我们预训练一个模型,然后用相同的任务将其微调到相同域中的另一个数据集时,这适用于我们的问题(例如,使用预训练的 ImageNet 分类模型(INCM),然后将其微调到狗品种分类器)。
  • 领域适应:我们正在进行相同的任务,但是正在将我们的模型转移到由手头的另一个数据集给出的新领域中(例如,采用预先训练的 INCM,并在基于 x 射线对健康和患病患者进行分类时对其进行微调)。
  • 任务适应:利用预训练模型的知识(即,其中间输出作为嵌入)来训练它执行不同的任务(例如,使用 INCM 的主干作为特征提取器,并添加第二个网络来执行对象检测)。
  • 模态转换:即使领域和任务不同,使用在图像等方面预先训练的网络可能是有意义的。至少,该网络已经掌握了该模式(例如,使用 INCM 主干网在 x 射线中对乳腺癌进行目标检测)。
  • 数据集合并:如果你想在相同的任务上同时训练来自相同领域的两个数据集,请随意合并它们(例如,将从 Instagram 抓取的图像添加到 ImageNet 数据集,以训练更好的分类器)。
  • 权重共享:即使您正在同时训练两个问题,共享一些中间权重也是有意义的(例如,使用 OCR 生成的文本和 PDF 文档的原始图像来馈入一个联合的中间表示,以对页面的上下文进行分类,以及它是否是一个新文档的开始)。
  • 多任务学习:最受欢迎的实例之一是特斯拉的大型视觉网络,其中一个共享的主干网同时接受多项任务的联合训练(例如,使用特斯拉中摄像机的相同镜头并行运行对象检测和道路标记分割)。
  • 并行训练:最后,如果你有两个不同的问题(域和任务)并且你想同时训练它们,就并行进行(例如,为同一个客户端执行内容审核和电子邮件分类)。

扩展的 2x2x2 矩阵

2x2x2 矩阵、映射任务、域和顺序。由作者创建。

使用维度任务顺序,我们最终得到这个 2x2x2 矩阵,映射出之前介绍的概念。对于 2D 可视化,我在 x 轴上放置了两个维度,并将二进制条目加倍,最终得到 8 个不同的单元(例如,左上角的单元将是相同域相同任务顺序顺序)。

关闭

在这篇文章中,我们使用了任务、领域和顺序的维度来构建我们执行 TL 的方式。我喜欢沉迷于我的咨询过去,将它们扩展到一个更大的矩阵,让我思考全新的场景,同时试图填充空白的领域。这导致了一些相当明显的情况(例如,“数据集合并”和“并行训练”),一直到一些已知的还没有普遍使用的名称的过程(例如,“任务微调”)。

如果你有任何其他非传统的映射,对此事的想法,或者对我们在 Luminovo 的工作感兴趣,我很乐意收到你的来信。你可以在 Linkedin 上发表评论或联系我。

敬请关注下一篇文章。

用于统计测试的新 Python 库—比 statsmodels 更简单,比 scipy.stats 更丰富

原文:https://towardsdatascience.com/new-python-library-for-statistical-tests-simpler-than-statsmodels-richer-than-scipy-stats-ff380d4673c0?source=collection_archive---------30-----------------------

PYTHON 中的统计模型

统计建模变得更加简单

Pingouin 统计建模 Python 库

Python 的 statsmodelsscipy 库令人难以置信。但是,当涉及到执行简单但最广泛使用的统计测试时,如 t 测试、方差分析(ANOVA)和回归,这两个库似乎同时做了太多和太少。

Statsmodels 功能强大,但是它的输出对初学者来说是多余的,难以解析。然而,Scipy.stats 更容易使用,但是提供的输出有些欠缺(例如,只有测试统计和概率值)。

有没有介于两者之间的东西——为最常见的统计测试提供简单而详尽的输出的库?

Pinguoin 前来救援

于 2018 年 4 月发布,目前正在进行积极开发

是一个相对较新的库,旨在为许多常见的统计测试提供简单而详尽的输出。

安装并导入 pingouin

如果你不想安装,打开我的共享 Deepnote Python 笔记本,在你阅读这篇文章的时候一个单元一个单元地运行它。否则,pingouin 可通过 pip 和 conda 获得,因此选择您喜欢的安装方法。

pip install pingouin
conda install -c conda-forge pingouin

这篇文章将只涉及 t 检验、方差分析、回归,以及 pingouin 如何与 熊猫集成,但是 pingouin 可以做的不止这些(例如,中介),所以查看它的文档

“学生”t 检验

很容易进行 t 检验并得到最小但重要的结果,这些结果被方便地存储在熊猫数据帧中。

import pingouin as pgx = [1, 2, 3, 4, 5]
y = [0, 1, 2, 3, 6]model = pg.ttest(x, y)  # output is a pandas dataframe
print(model)

熊猫数据帧中 t-test 的清晰但全面的输出(运行代码此处

真正令人难以置信的是,结果不仅包括 T 统计量(T)和 p 值(p-val),还包括其他统计量,所有这些都在熊猫数据框架的一行中:自由度(dof)、95%置信区间(CI95%)、科恩的 d 效应大小度量(cohen-d)、反映假设证据强度的贝叶斯因子(BF10)和统计功效(power)。

方差分析(ANOVA)

执行方差分析同样简单。我们将使用 pingouin 中的内置数据集,并改编一个来自官方文档的示例,在该示例中,我们可以看到胆固醇是否可以通过性别(男性或女性)和药物(A、B、C)来预测。

当我们使用 pingouin 时,我们也可以使用与 pandas 数据帧相关联的anova方法。也支持相当多的其他方法。或者也可以使用等价的pg.anova函数来代替 pandas 方法。

dt = pg.read_dataset('anova3')# pandas method anova
dt.anova(dv="Cholesterol", between=["Sex", "Drug"]).round(3)# pingouin function anova
pg.anova(dv="Cholesterol", between=["Sex", "Drug"], data=dt)

熊猫数据帧中 ANOVA 的清晰而全面的输出(运行代码此处)

同样,输出是在熊猫数据帧中。Pingouin 几乎使得用 Python 来适应简单的统计模型变得太容易了,并且产生的输出清晰但非常全面——甚至可能比强大的统计计算语言 r 提供的输出更好。

回归

Pingouin 还执行线性和逻辑回归。这里,我们导入了 seaborn 库,这样我们就可以使用内置的 iris 数据集。我们使用萼片长度和萼片宽度来预测花瓣长度。

import seaborn as sns
iris = sns.load_dataset("iris")X = iris[['sepal_length', 'sepal_width']]  # predictors/features
y = iris['petal_length']  # outcome/target
pg.linear_regression(X, y)

熊猫数据框架中线性回归的清晰而全面的输出(运行代码此处)

给 Pingouin 一个机会,我很好奇你对它的想法,以及你是否认为你会使用它。另外,如果你喜欢这篇文章,可以看看我的其他几篇关于 Python 和 pandas 数据科学的文章。

** [## 用 Python 中的 pivot_table 重塑熊猫数据框—教程和可视化

使用 pd.pivot_table 将 long 转换为 wide

towardsdatascience.com](/reshape-pandas-dataframe-with-pivot-table-in-python-tutorial-and-visualization-2248c2012a31) [## 在 Python 中更有效地循环的两种简单方法

使用枚举和压缩编写更好的 Python 循环

towardsdatascience.com](/two-simple-ways-to-loop-more-effectively-in-python-886526008a70) [## 真实或虚假的关联:你约会的有魅力的人更令人讨厌

使用 Python 模拟数据、测试直觉并提高数据科学技能

towardsdatascience.com](/real-or-spurious-correlations-attractive-people-you-date-are-nastier-fa44a30a9452)

更多帖子, 订阅我的邮件列表 **

带有 Huggingface、AWS Lambda 和 AWS EFS 的新型无服务器 Bert

原文:https://towardsdatascience.com/new-serverless-bert-with-huggingface-aws-lambda-and-aws-efs-5d8954ce654?source=collection_archive---------31-----------------------

使用无服务器框架、AWS Lambda、AWS EFS、efsync、Terraform、HuggingFace 的变形金刚库,构建一个无服务器问答 API

Jean-Philippe Delberghe 在 Unsplash 上拍摄的照片

原载于 2020 年 11 月 15 日https://www . philschmid . de

介绍

4 个月前,我写了文章“使用 HuggingFace 和 AWS Lambda 的无服务器 BERT”,演示了如何通过 AWS Lambda 和 HuggingFace 的 Transformers 库以无服务器方式使用 BERT。

在这篇文章中,我已经预测过 “伯特和他的朋友罗伯塔、GPT-2、艾伯特和 T5 将在未来几年推动商业和商业理念,并将像互联网曾经做的那样改变/颠覆商业领域。”

从那以后,BERT 在谷歌搜索中的使用从 10%的英文查询增加到几乎 100%的英文查询。但不是这样。谷歌现在用 BERT 为谷歌搜索提供超过 70 种语言的能力。

https://youtu.be/ZL5x3ovujiM?t=484

在本文中,我们将解决我上一篇文章中的所有缺点,比如模型加载时间、依赖大小和使用。

我们将构建和上次一样的“无服务器的 BERT 驱动的问答 API”。但是,我们没有使用压缩技术来将 Python 依赖关系融入 AWS Lambda 函数,而是使用了一个名为 efsync 的工具。我构建了 efsync 来自动将依赖项上传到 AWS EFS 文件系统,然后将它们挂载到我们的 AWS Lambda 函数中。这允许我们将我们的机器学习模型包含到我们的函数中,而不需要从 S3 加载它。

TL;DR;

我们将使用无服务器框架AWS LambdaAWS EFSefsyncTerraform 、HuggingFace 的 transformers 库以及在 SQuADv2 上微调的 Google 的mobileBert模型来构建一个无服务器问答 API。

你可以在这个 Github 库中找到它的完整代码。

库和框架

无服务器框架

无服务器框架

无服务器框架帮助我们开发和部署 AWS Lambda 功能。它是一个 CLI,开箱即可提供结构、自动化和最佳实践。

自动气象站λ

AWS Lambda 标志

AWS Lambda 是一种无服务器的计算服务,让你无需管理服务器就能运行代码。它只在需要的时候执行你的代码,并且自动伸缩,从每天几个请求到每秒几千个请求。

亚马逊弹性文件系统(EFS)

亚马逊 EFS 是一项完全托管的服务,可以轻松设置、扩展和优化亚马逊云中的文件存储。自 2020 年 6 月起,您可以将 AWS EFS 安装到 AWS Lambda 函数

Efsync

Efsync 是一个 CLI/SDK 工具,可以自动将文件和依赖项同步到 AWS EFS。它使您能够将 AWS Lambda 运行时的依赖项直接安装到 EFS 文件系统中,并在 AWS Lambda 函数中使用它们。

将(行星)地球化(以适合人类居住)

Terraform 标志

Terraform 是一款基础设施即代码(IaC)工具,用于安全高效地构建云原生基础设施。Terraform 使您能够使用 HCL (HashiCorp 配置语言)来描述您的云原生基础架构。

拥抱脸的变形金刚库

HugginFace 标志

变形金刚库为自然语言理解(NLU)和自然语言生成(NLG)提供最先进的机器学习架构,如 BERT、GPT-2、罗伯塔、XLM、DistilBert、XLNet、T5。它还提供了 100 多种不同语言的数千个预训练模型。

建筑

由菲利普·施密德创造

辅导的

在我们开始之前,确保您已经配置并设置了无服务器框架平台。此外,您需要访问 AWS 帐户来创建 EFS 文件系统、API 网关和 AWS Lambda 函数。

在教程中,我们将使用来自 Google 的预训练BERT模型构建一个问答 API。

我们将向 lambda 函数发送一个上下文(一小段)和一个问题,lambda 函数将使用问题的答案进行响应。

我们要做什么:

  • 使用terraform创建所需的基础设施。
  • 使用efsync上传我们的 Python 依赖到 AWS EFS。
  • 用无服务器框架创建一个 Python Lambda 函数。
  • BERT模型添加到我们的函数中,并创建一个推理管道。
  • 配置serverless.yaml,添加 EFS,设置一个 API 网关进行推理。
  • 部署和测试功能。

您将需要一个名为serverless-bert的新 IAM 用户,并使用aws configure --profile serverless-bert在 AWS CLI 中对其进行配置。这个 IAM 用户在完整教程中使用。如果你不知道怎么做,看看这个链接

注意: 我不建议使用 *AdministratorAccess*为生产使用创建 IAM 用户

在我们开始之前,我想说的是我们不会对每一步都进行详细说明。如果你想更多地了解如何在 AWS Lambda 中使用深度学习,我建议你看看我的其他文章:

您可以在这个 Github 库中找到完整的代码。

使用terraform创建所需的基础设施

首先,我们使用 terraform 定义和创建所需的基础设施。如果你还没有设置,你可以看看这个教程。

作为基础设施,我们需要一个 AWS EFS 文件系统、一个访问点和一个挂载目标,以便能够在 AWS Lambda 函数中使用它。我们也可以创建一个 VPC,但出于本教程的目的,我们将使用默认的 VPC 和他的子网。

接下来,我们创建一个目录serverless-bert/,其中包含本教程的所有代码,还有一个包含我们的main.tf文件的子文件夹terraform/

之后,我们用我们首选的 IDE 打开main.tf,并添加 terraform 资源。我为他们所有人提供了一个基本模板。如果您想定制它们或添加额外的资源,请查看文档了解所有可能性。

要更改 EFS 的名字,您可以编辑aws_efs_filesystem资源中的值creation_token。否则,EFS 的名字将是“无服务器-伯特”。此外,我们在最后为efs_access_point_id创建了一个 SSM 参数,以便稍后在我们的serverless.yaml中使用。

为了使用 terraform,我们首先运行terraform init来初始化我们的项目和提供者(AWS)。请注意,我们必须在terraform/目录中。

之后,我们用terraform plan检查我们的 IaC 定义

完成后,我们用terraform apply创建我们的基础设施

使用efsync将我们的 Python 依赖关系上传到 AWS EFS

下一步是在 AWS EFS 文件系统上添加和安装我们的依赖项。因此我们使用一个叫做efsync的工具。我创建了 efsync 来将 AWS Lambda 运行时的依赖项直接安装到您的 EFS 文件系统中,并在 AWS Lambda 函数中使用它们。

运行pip3 install efsync安装 efsync

安装完成后,我们在根目录serverless-bert/中创建一个requirements.txt,并向其中添加我们的依赖项。

Efsync 提供不同的配置。这次我们使用带有yaml配置的 CLI。为此,我们在根目录中创建一个efsync.yaml文件。

这里我们必须调整efs_filesystem_idsubnet_Id的值。通过在管理控制台中查找或使用这两个 CLI 命令来获取这些值。

注意,如果您之前更改了creation_token,您必须在此处进行调整。

您可以为efsync.yaml配置选择一个subnet_Ids。如果你想了解更多的配置选项,你可以在这里阅读更多的。

在配置完我们的efsync.yaml之后,我们运行efsync -cf efsync.yaml在我们的 AWS EFS 文件系统上安装我们的 Python 依赖项。这大约需要 5-10 分钟。

使用无服务器框架创建 Python Lambda 函数

第三,我们通过使用带有aws-python3模板的无服务器 CLI 创建 AWS Lambda 函数。

这个 CLI 命令将创建一个包含handler.py.gitignoreserverless.yaml文件的新目录。handler.py包含一些基本的样板代码。

BERT 模型添加到我们的函数中,并创建一个推理管道

因为我们没有将 Python 依赖项包含到 AWS Lambda 函数中,所以我们有大约 250MB 的存储空间用于模型文件。对于那些不太熟悉 AWS Lambda 及其局限性的人,你可以查看这个链接

如果您想使用大于 250MB 的模型,您可以使用 efsync 将它们上传到 EFS,然后从那里加载它们。更多 此处阅读

要将我们的BERT模型添加到我们的函数中,我们必须从 HuggingFace 的模型中枢加载它。为此,我创建了一个 python 脚本。在执行这个脚本之前,我们必须将transformers库安装到我们的本地环境中,并在我们的function/目录中创建一个model目录。

在我们安装了transformers之后,我们在function/目录下创建了get_model.py文件,并包含了下面的脚本。

为了执行这个脚本,我们在function/目录中运行python3 get_model.py

提示 :将 *model* 目录添加到 gitignore 中。

下一步是调整我们的handler.py,包括我们的serverless_pipeline()

首先,我们将所有需要的导入和我们的 EFS 文件系统添加到PYTHONPATH中,这样我们就可以从那里导入我们的依赖项。因此我们使用sys.path.append(os.environ['EFS_PIP_PATH'])。我们将在稍后的serverless.yaml中定义EFS_PIP_PATH

我们创建了serverless_pipeline()函数,它初始化我们的模型和标记器,并返回一个predict函数,我们可以在handler中使用它。

配置serverless.yaml,添加 EFS,设置推理的 API 网关。

我为这个例子提供了完整的serverless.yaml,但是我们检查了我们的 EFS 文件系统所需的所有细节,并省略了所有的标准配置。如果你想了解更多关于serverless.yaml的知识,建议你去看看从零到英雄的缩放机学习。在本文中,我介绍了每种配置,并解释了它们的用法。

我们需要用下面的命令安装serverless-pseudo-parameters插件。

我们使用serverless-pseudo-parameters插件让我们的AWS::AccountIDserverless.yaml中被引用。在custom下或我们的functions部分中引用了所有自定义变量。

自定义:

  • efsAccessPoint应该是你的 EFS 接入点的价值。这里,我们使用我们的terraform模板先前创建的 SSM 参数。
  • LocalMountPath是 EFS 在 AWS Lambda 函数中的安装路径。
  • efs_pip_path是我们使用efsync安装 Python 依赖项的路径。

功能:

  • securityGroupIds可以是 AWS 帐户中的任何安全组。我们使用default安全组 id。这个应该是这样的sg-1018g448

  • subnetsId应该与 EFS 文件系统具有相同的 id。它们应该是这样的subnet-8f9a7de5

部署和测试功能

为了部署功能,我们运行serverless deploy --aws-profile serverless-bert

这个过程完成后,我们应该看到类似这样的东西。

为了测试我们的 Lambda 函数,我们可以使用失眠症、邮差或任何其他 REST 客户端。只需在请求体中添加一个带有contextquestion的 JSON。让我们用 colab 笔记本中的例子来尝试一下。

我们的serverless_pipeline()83.1正确回答了我们的问题。此外,您可以看到完整的第一个请求花费了 2900 毫秒或 29 秒。其中 15 秒用来初始化我们函数中的模型。

第二个请求只用了 390 毫秒。

最棒的是,如果有几个传入请求,我们的 BERT 模型会自动扩展!它可以扩展到数千个并行请求,而不用担心任何问题。

结论

我们已经成功地实现了一个无服务器问答 API。对于实现,我们以无服务器的方式使用 IaC 工具和“最先进的”NLP 模型。从开发人员的角度来看,我们降低了复杂性,但包含了许多 DevOps/MLOps 步骤。我认为有必要包括 DevOps/MLOps,如果你想在生产中运行可扩展的无服务器机器学习,它可以处理你的部署和供应。

你可以在这里找到 GitHub 库和完整的代码

感谢阅读。如果你有任何问题,随时联系我或评论这篇文章。你也可以在 Twitter 或者 LinkedIn 上和我联系。

抖音算法和 Trump 的塔尔萨拉力赛的新研究

原文:https://towardsdatascience.com/new-study-on-tiktoks-algorithms-and-trump-s-tulsa-rally-508ffb2a5ac5?source=collection_archive---------47-----------------------

这一事件说明了抖音的算法是如何让大众政治沟通变得更容易实现的,但这仍然不是民主乌托邦。

今年夏天,我分析了大约 8 万个抖音视频中的数据,这些视频与特朗普在塔尔萨竞选连任集会上的恶作剧有关。我的主要兴趣是理解抖音的算法是如何在这场恶作剧中发挥作用的。这篇文章总结了我的研讨会研究论文的发现,该论文在 RecSys 2020 研讨会上提出了负责任的建议

背景

为什么川普政府想要禁止抖音?几周前,这款应用似乎离死亡只有几天了。但我们中的许多人仍然在问:特朗普到底为什么要禁止它?亚洲记者埃沃特综合了三种主要解释:

  • 美国和中国之间的紧张关系
  • 抖音青少年和 K-pop 斯坦坦克他的塔尔萨集会
  • 抖音的政治权力

所有这三个因素很可能影响了禁令,可能还有更多我们永远不知道的。但鉴于特朗普政府在 2020 年 7 月才开始采取行动,完整的时间表表明,塔尔萨的恶作剧可能是某种催化剂:

  • 2017 年:特朗普上任
  • 2018:字节跳动将 Musical.ly 融入抖音(来源)
  • 2019 年:抖音全球下载量突破 10 亿(来源)
  • 2020 年 6 月 14 日:特朗普的连任竞选活动吹嘘即将在塔尔萨举行的集会创纪录的出席人数(80 万+)

在恶作剧的前几天,前竞选经理布拉德·帕斯科吹捧破纪录的注册

  • 2020 年 6 月 20 日:只有 6200 人参加的拉力赛在一个有 19000 个座位的竞技场举行

[## 由于出席人数低于预期,特朗普取消了在塔尔萨集会上的户外演讲

特朗普总统在塔尔萨周六晚上的集会上取消了对竞技场外拥挤人群的演讲计划…

www.businessinsider.com](https://www.businessinsider.com/trump-canceled-outdoor-speech-at-tulsa-rally-over-low-turnout-2020-6)

  • 2020 年 6 月 20 日:报道称抖音青少年和 K-pop 歌手集体注册参加塔尔萨集会,用人为夸大的注册号码来恶作剧

国会议员亚历山大·奥卡西奥·科尔特斯回应布拉德·帕斯科,强调了韩国流行音乐斯坦斯和抖音用户的恶作剧

  • 2020 年 7 月 7 日:川普建议禁止抖音(来源

当我读到这些事件时,我想知道抖音的“为了你”推荐算法是否在促进恶作剧中发挥了作用。因为与脸书、推特和其他主要依赖朋友、关注者或其他用户决定的网络的平台不同,抖音的应用程序采取更主动的方式向你展示媒体。一位记者这样总结这个算法:

"为什么不开始向人们展示一些东西,看看他们会怎么做?"(约翰·赫尔曼)

第一次打开抖音应用程序时,你从一个简短的类别列表中选择兴趣(例如,烹饪、舞蹈、动物、运动等。).紧接着,抖音的推荐算法“为你”筛选出无限的视频源,使用广泛的信号来推断你的兴趣,并进一步个性化推荐。在很大程度上,抖音的推荐算法似乎决定了创作者视频的命运。

这让我想知道抖音的算法是如何决定塔尔萨集会恶作剧宣传视频的命运的,我和我的顾问尼克·迪亚克普洛斯(Nick Diakopoulos)就此进行了一项小型研究。由于无法直接获得抖音的数据,我们在寻找答案方面受到了一定的限制,但我们仍然能够解决三个主要的研究问题:

  1. 塔尔萨的视频和其他视频相比,的总体受欢迎程度如何?
  2. 个人用户如何体验塔尔萨视频的受欢迎程度?
  3. 基于统计模型,在控制其他因素的情况下,塔尔萨视频的受欢迎程度是否得到了独特的提升?

资料组

我们使用大卫·蒂瑟创建的非官方 API 收集数据集。从记者 Jenna Amatulli 收集的[视频种子开始,我们使用种子视频的标签和配乐来滚雪球般地收集样本。我们最终得到了 600 多个号召行动的塔尔萨视频,鼓励用户注册参加集会的门票作为恶作剧。然后,我们从遇到的所有用户那里收集了多达 300 个最近的视频,以此作为比较的基准。总数据集约为 80,000 个视频。](https://twitter.com/ohheyjenna/status/ 1274558069876367361)

数据集有几个值得注意的限制。首先,在抖音的界面中,所有计数都是四舍五入的,因此,例如,4,300,021 次播放被报告为“430 万次播放”第二,所有的剧都是平等报道的。“为了你”页面中的一个播放,直接分享视频的一个播放,以及第四次观看视频的人的一个播放——它们都被计算在同一个桶中。尽管如此,这些数据足够丰富,足以提供一些有力的见解。

结果

1.总体模式

我们首先观察了视频受欢迎程度的总体模式,发现视频的受欢迎程度逐例增加。本质上,我们发现了参与度反馈循环的证据,其中喜欢和评论导致更多的播放:

正如大多数抖音创作者会告诉你的,点赞越多的视频往往会获得更多的播放。

值得注意的是,我们发现创作者的观众规模并不能可靠地保证他们的视频播放。换句话说,如果一个创作者有 20 万名粉丝,就没有办法持续预测他们的新视频会吸引多少次播放——这取决于具体情况,例如视频计数和评论计数。这对许多抖音用户来说很直观,但我们的数据为这一现象提供了一些经验证据:

在我们的数据中,一些追随者很少的创作者发布了受欢迎的视频,而有很多追随者的创作者并没有持续获得大量播放。

这一阶段的分析还表明,塔尔萨的视频(促进注册)比其他视频更有可能受欢迎。例如,70%的塔尔萨视频的播放量不到 1000 次,而 85%的其他视频的播放量不到 1000 次。此外,塔尔萨相关视频的播放量中值为 292 次,而数据集其余部分的视频播放量中值为 155 次。在下图中,播放次数越多,代表 Tulsa 视频的线条明显向右移动:

塔尔萨视频的受欢迎程度分布略高,例如,只有 70%的塔尔萨视频获得 1,000 次或更少的播放,而 85%的其他视频获得 1,000 次或更少的播放。

总体受欢迎程度的“S 曲线”表明了高度的不平等。本·韦斯特(Ben West)研究了抖音的不平等,并在一份 2 万份视频样本中发现基尼系数为 0.93(“抖音几乎完全不平等”)。我们样本中的基尼系数为 0.94,证实了抖音作为一个平台的高度不平等。值得注意的是,这种模式并不是抖音独有的,事实上之前的工作表明“S 曲线”在用户生成的视频平台中相当普遍:

S 曲线流行模式在以前的工作中已经发现,如查等人(2009)的“分析大规模用户生成内容系统的视频流行特征”中的图表所示。

2.用户特定的模式

在分析的第二阶段,我们放大了特定用户,以查看他们在塔尔萨的视频表现如何。Mary Jo Laupp 的视频是我们数据集中最受欢迎的 Tulsa 视频,似乎受益于算法放大。在收集数据时(集会后几天),Laupp 的视频播放次数远远超过 200 万次,尽管她只有大约 18,000 名粉丝,她的第二大热门视频播放次数不到 10 万次。在她所有视频的图表中,塔尔萨的视频遥遥领先于其他所有视频:

Mary Jo Laupp 的视频是我们数据集中最受欢迎的塔尔萨视频,播放量超过 200 万次。由于她当时只有大约 18000 名粉丝,我们可以有把握地推断,抖音的算法放大了视频。

正如我们在论文中报道的那样,我们发现了一些类似的案例,尽管大多数没有像玛丽·乔·劳普那样经历急剧的增长。尽管如此,对于数据集中 76%的用户来说,他们的塔尔萨视频比他们的中值视频获得了更多的播放,这证明了塔尔萨视频的总体受欢迎程度有所提高。

3.统计建模

最后,我们使用统计建模来确定塔尔萨视频是否经历了系统性的受欢迎程度的增加。同样,我们的数据集不能说明一切,但我们能够控制视频长度和参与度统计等因素(即计数、评论计数、分享计数),伪 R 表明这些因素解释了数据中约 67%的变化。

塔尔萨视频获得了更高的参与度,从而带来了更高的播放量

根据我们的统计模型,塔尔萨的视频并没有经历系统的普及。相反,由于更高的参与度,它们获得了更高的播放次数,与我们数据集中的其他流行视频一样。换句话说,我们没有发现抖音的算法对塔尔萨视频给予特殊对待的证据。

统计模型发现,塔尔萨视频的播放量没有出现系统性增长。

的论文中有更多的统计细节(例如相关性测试和 Wilcoxon 符号等级测试),这些数据都指向同一个结论:塔尔萨视频吸引了更多的用户参与,从而导致更多的播放,但它们并没有从抖音的算法中获得特殊待遇。

限制

即使在这样的博文中,也要注意到科学研究的局限性。我们不得不使用抖音的全面统计数据,在收集数据时,我们可能错过了一些相关的视频。给定我们的研究问题,最大的限制是我们使用总播放计数来估计算法为你页面的受欢迎程度。换句话说,我们无法区分“来自‘为你’页面的剧本”和“来自其他地方的剧本”这是媒体曝光研究中的一个标准限制,但也是一个值得注意的重要限制。

同样值得注意的是,抖音的透明度努力可以提供关于算法推荐的视频的更多信息。例如,他们可以发布该算法推荐了 50 万次或更多次的视频列表,这将有助于提供一些问责制。

那又怎样?

对我来说,从我们的分析中最大的收获是抖音用户可以帮助决定哪些视频变得流行。在许多情况下,抖音的创作者不需要大量的追随者来接触大量的观众,他们只需要一个引人入胜的视频。这个原理相当简单,并在其他平台上使用,但抖音似乎已经破解了代码,并微调了他们的算法,不再强调朋友/追随者的作用。

在某些方面,这使得抖音成为一个非常民主的平台,因为用户可以通过简单的喜欢、评论、分享或完成一个视频来为哪些视频变得流行进行投票。事实上,创作者经常要求观众“喜欢并分享这个视频”,“保持高比例”,或者(我个人最喜欢的)“给这个视频加油。”抖音应该如何处理这种行为?Instagram 采取了惩罚性的方式。就我个人而言,我希望抖音认识到这种行为不是“游戏系统”,而是基本上为人们在应用程序中看到的视频投票。

关于投票和民主的问题,还值得考虑的是,抖音不允许政治广告。在我看来,这使得抖音对威权领导人构成了威胁,尤其是考虑到视频流行的民主、草根式投票。但是,与此同时,抖音本身在某些方面是集权和独裁的。平台定期删除数百万视频,其强大的算法产生了明显的不平等——我们数据集中前 1%的视频占所有播放的 76%。此外,尽管在透明度方面做出了努力,但该平台的不透明性在其向创作者付费的新方法中得到了强调,用户称这种方法“T6”充满了问题

简而言之,抖音不仅仅是一个分享视频的有趣应用程序——它具有现实世界的社会、政治和经济后果,需要进一步关注。有时,后果很有趣,比如特朗普在塔尔萨集会上的恶作剧,或者在内森·阿波达卡(Nathan Apodaca)在一个标志性的抖音喝了越橘汁后,Ocean Spray 的品牌彻底改造:

[## 病毒海洋喷雾抖音视频如何一夜之间改变了一个 90 岁的公司

在商业中,时机就是一切。汤姆·海斯,我们在这里说你接任 90 岁的首席执行官的时机…

finance.yahoo.com](https://finance.yahoo.com/news/how-the-viral-ocean-spray-tik-tok-video-transformed-a-90-yearold-company-overnight-173804141.html)

但有时后果并不像对特朗普的恶作剧或讽刺性的蔓越莓汁品牌那样有趣。我们知道像抖音这样的算法可以放大危险的虚假声明、极端主义信息和其他有问题的媒体,例如抖音在 7 月份放大的反犹太迷因。

不管后果是有趣还是令人担忧,越来越明显的是,抖音教对我们的社会产生了重大影响。鉴于这种影响,我们应该继续让抖音为它放大的信息和它制造的不平等负责。这款应用可能会对威权领导人构成威胁,但它离民主乌托邦还很远。

如果你对我在本帖中总结的 研究有任何问题或意见,请联系我!

凯特琳·皮特尔、布鲁克·艾琳·达菲和艾米丽·洪德写了一篇关于 Instagram pods 的令人着迷的 研究论文 。维多利亚·奥米拉还写了一篇关于现象的的精彩论文。两者都极大地帮助了我的研究。

新 TF2 对象检测 API

原文:https://towardsdatascience.com/new-tf2-object-detection-api-5c6ea8362a8c?source=collection_archive---------16-----------------------

ML 提示和技巧/ TF2 OD API

欢迎新动物进入动物园——模型评估

(图片由作者提供)

Tensorflow 对象检测 API (TF OD API)刚刚变得更好。最近,Google 发布了新版本的 TF OD API,现在支持 Tensorflow 2.x,这是我们一直在等待的巨大改进!

介绍

物体检测(OD)技术的最新进展是由行业广泛采用该技术推动的。汽车制造商使用物体检测来帮助车辆在道路上自主导航,医生使用它来改善他们的诊断过程,农民使用它来检测各种作物疾病…… 还有许多其他的使用案例(有待发现),在这些案例中,OD 可以提供巨大的价值。

Tensorflow 是一个深度学习框架,为自然语言处理(NLP)、语音合成、语义分割和对象检测中的许多最先进的(SOTA)模型提供支持。TF OD API 是一个开源的对象检测模型集合,由深度学习爱好者和该领域的不同专家使用。

现在,当我们介绍了基本术语后,让我们看看新的 TF OD API 提供了什么!

新的 TF OD API

新的 TF2 OD API 引入了急切执行,使得对象检测模型的调试更加容易;它还包括 TF2 模型动物园支持的新 SOTA 模型。对于 Tensorflow 1.x .用户来说,好消息是新的 OD API 是向后兼容的,所以如果你喜欢,你仍然可以使用 TF1,尽管强烈建议切换到 TF2!

除了之前 TF1 模型动物园有的 SSD (MobileNet/ResNet)、更快的 R-CNN (ResNet/Inception ResNet)、Mask R-CNN 模型外,TF2 模型动物园还推出CenterNetExtremeNetefficent det新 SOTA 模型。

TF2 OD API 模型动物园中的模型在 COCO 2017 数据集上进行了预训练。如果你对这个数据集中已经包含的类别感兴趣,预先训练的模型可以用于开箱即用的推理,或者在新数据集上训练时用于初始化你的模型。使用 TF OD API 模型而不是自己实现 SOTA 模型可以让您有更多的时间关注数据,这是实现 OD 模型高性能的另一个关键因素。然而,即使您决定自己构建模型, TF OD API 模型提供了一个很好的性能基准

您可以根据自己的需求(速度与精度)从一长串不同的型号中进行选择:

TF2 OD API 模型动物园中包含的模型。

在上表中,您可以看到中仅给出了平均 COCO mAP 指标。尽管对于模型的性能来说,这可能是一个相当好的方向,但是如果您对模型在不同大小的对象或不同类型的对象上的表现感兴趣,那么附加统计信息可能会很有用。例如,如果你对开发你的高级驾驶辅助系统 ( ADAS )感兴趣,你不会真的关心探测器探测香蕉的能力是否差!

在这篇博客中,我们将重点解释如何对 TF2 模型动物园中现成的不同预训练efficient det检查站进行详细评估。****

效率检测— SOTA OD 模型

EfficientDet 是一个与 RetinaNet 模型非常相似的单次检测器,有几处改进: EfficientNet 主干 、加权双向特征金字塔网络(BiFPN)和复合缩放方法

BiFPN 是非常流行的 FPN 的改进版本。它学习表示不同输入特征重要性的权重,同时重复应用自上而下和自下而上的多尺度特征融合。

特征网络设计 : a) FPN 引入自上而下的路径融合多尺度特征,b) BiFPN 在现有自上而下的路径上增加自下而上的路径,创建双向 FPN。来源:https://arxiv.org/pdf/1911.09070.pdf

提高目标检测模型精度的常用方法是增加输入图像的大小或使用更大的主干网络。复合缩放不是在单个维度或有限的缩放维度上操作,而是联合放大主干、特征网络和盒/类预测网络的分辨率/深度/宽度。

TF2 OD API Model Zoo中包含了具有不同缩放因子的 EfficientDet 模型,缩放因子在模型名称中用{ X} 表示,而输入图像分辨率用{ RES }X {RES }efficient det D {X }{RES }X {RES }表示。

用于高效检测的复合缩放配置。来源:https://arxiv.org/pdf/1911.09070.pdf

EfficientDet 架构采用 EfficientNet 作为主干网络,BiFPN 作为特征网络,以及共享类/箱预测网络。来源:https://arxiv.org/pdf/1911.09070.pdf

预训练 EfficientDet 模型的评估

我们希望进行详细的精度比较,以研究复合扩展配置对网络本身性能的影响。出于这个原因,我们创建了一个 Google Colab 笔记本,在其中我们解释了如何对模型进行评估,以及如何有效地比较评估结果。我们对详细的评估统计感兴趣,包括每个类和不同对象大小的统计

不幸的是,TF OD API 不支持这种现成的统计数据。这就是为什么我们创建了 TF OD repo 的一个分支,并更新了相关脚本,以按照本期中给出的说明引入该功能。

在笔记本中,我们提供了如何设置tensor flow 2TF2 OD API的说明。我们还包括脚本,可以轻松下载 EfficientDet 检查点,以及额外的脚本,可以帮助您获取 COCO 2017 Val 数据集,并创建 tfrecord 文件,供 TF OD API 在评估阶段使用。

最后,我们修改 EfficientDet 检查点的pipeline.config文件,为后续评估 8 EfficientDet 检查点做好准备。TF OD API 使用它们来配置培训和评估过程。培训管道的模式可在object_detection/protos/pipeline.proto中找到。在高层次上,配置文件分为 5 个部分:

  1. model的配置。这定义了将被训练的模型的类型(即,元架构、特征提取器……)。
  2. train_config,决定用什么参数来训练模型参数(即 SGD 参数、输入预处理、特征提取器初始化值……)。
  3. eval_config,它决定将报告什么样的组指标进行评估。
  4. train_input_config,它定义了模型应该在哪个数据集上进行训练。
  5. eval_input_config,其中定义了模型将在上评估的数据集。通常,这应该不同于训练输入数据集。
model {
(... Add model config here...)
}train_config : {
(... Add train_config here...)
}train_input_reader: {
(... Add train_input configuration here...)
}eval_config: {
}eval_input_reader: {
(... Add eval_input configuration here...)
}

我们只对配置文件的eval_configeval_input_config部分感兴趣。仔细查看 Google Colab 中的单元格,了解我们如何设置评估参数的更多详细信息。TF OD API 中另外两个没有启用的标志是include_metrics_per_categoryall_metrics_per_category。在应用了 Colab 笔记本中给出的补丁后,当设置为true时,这两个选项将启用我们感兴趣的详细统计(按类别和大小)

Allegro Trains —高效的实验管理

为了能够有效地比较模型评估,我们使用一个名为 开源实验管理工具来训练**** 。很容易将它集成到您的代码中,并且它支持开箱即用的不同功能。它可以作为张量板的替代品,用于可视化实验结果。

来源:https://allegro . ai/WP-content/uploads/2019/11/allegro-logo-1 . jpg

OD API 中的主脚本是object_detection/model_main_tf2.py。它处理训练和评估阶段。我们创建了一个小脚本,它在一个循环中调用model_main_tf2.py来评估所有 EfficientDet 检查点。

为了将 Allegro Trains 实验管理集成到评估脚本中,我们必须添加 2 (+1)行代码。在model_main_tf2.py脚本中,我们添加了以下几行:

from trains import Tasktask = Task.init(project_name="*NAME_OF_THE_PROJECT*", task_name="*NAME_OF_THE_TASK*")# OPTIONAL - logs the pipeline.config into the Trains dashboard
task.connect_configuration(FLAGS.pipeline_config_path)

火车会自动开始为你记录许多事情。你可以在这里找到全面的特性列表

比较不同的效率检测模型

在这个 链接 上,可以找到 TF2 OD API 收录的 8 款 EfficientDet 车型的评测结果。我们将实验命名为efficientdet_d{X}_coco17_tpu-32,其中{x}表示 EfficientDet 模型的复合比例因子。如果您运行示例 Colab 笔记本,您将得到相同的结果,并且您的实验将显示在演示训练服务器上。

在本节中,我们将向您展示如何有效地比较不同的模型,并验证它们在评估数据集上的性能。我们使用 COCO 2017 Val 数据集,因为它是 TF OD API 中评估对象检测模型的标准数据集。

Trains 自动捕获代码、超参数和度量(图片由作者提供)。

我们感兴趣的是 COCO 对象检测模型评价指标 按下这里的查看实验结果。该页面包含我们感兴趣的所有指标的图表。

我们可以先看一下DetectionBoxes_Precision图,它包含数据集中所有类别的平均精度度量。地图度量的值对应于 TF2 动物园模型的表格中报告的地图度量。

COCO 2017 评估数据集中所有类别的 detection boxes _ Precision metrics(图片由作者提供)。

多亏了我们对pycocotools应用的补丁,我们还可以得到每个类别的地图度量。由于 COCO 数据集中有 90 个类别,我们想知道每个类别对平均准确度的贡献。通过这种方式,我们可以对被评估模型的性能有更加的深入了解。例如,您可能只对某个类别中的小对象的模型表现感兴趣。从汇总的统计数据来看,不可能获得这样的洞察力,而建议的补丁可以做到这一点!

EfficientDet D0 模型的每个类别映射指标(图片由作者提供)。

我们还使用 Allegro Trains 的功能来比较多个实验。实验对比显示了模型之间的所有差异。我们首先可以获得相关统计数据的详细标量和绘图比较。在我们的示例中,我们将比较 EfficientDet D0、D1 和 D2 模型的性能。显然,复合缩放对模型的性能有积极影响。

拥有每个类别的统计数据的额外好处之一是,您可以分析复合比例因子对某个感兴趣类别的准确性的影响。例如,如果您对检测监控视频中的公交车感兴趣,您可以分析显示公交车类别的地图性能与 EfficientDet 模型的复合比例因子的图表。这有助于决定使用哪种模型,以及性能和计算复杂性之间的最佳平衡点在哪里!

“bus”类别的映射指标与 EfficientDet 模型的复合比例因子(图片由作者提供)。

您还可以比较的一件有趣的事情是模型配置文件** pipeline.config.您可以看到 EfficientDet 模型之间的基本差异在于输入图像的尺寸和滤波器的数量/深度,如前所述。**

(图片由作者提供)

下一个图包含 3 个 EfficientDet 模型的 mAP 值。有一个明显的好处是增加输入图像的分辨率,以及增加模型中的滤镜数量。虽然 D0 模型实现了 33.55%的平均动脉压,但 D2 模型优于它,它实现了 41.79%的平均动脉压。您还可以尝试执行每个类的比较、其他 EfficientDet 模型的比较,或者您对应用程序感兴趣的任何事情。

EfficientDet D0、D1 和 D2 车型的地图对比(图片由作者提供)。

TF OD API 是如何用于提高工地安全的?

Forsight 是一家早期创业公司,我们的使命是将建筑工地变成工人的安全环境。 Forsight 利用计算机视觉和机器学习,处理实时闭路电视镜头,帮助安全工程师监控个人防护设备(PPE)的正确使用,以保持现场安全。

我们的施工现场监控管道建立在 TF OD API 之上,其功能包括 PPE 检测和监控、社交距离跟踪、虚拟地理围栏监控、禁止停车区监控和火灾探测。在 Forsight,我们还使用 Trains 来跟踪我们的实验,在团队成员之间分享它们,并记录一切,以便我们可以重现它。

(图片由作者提供)

随着新冠肺炎疫情的继续,世界各地的建筑项目都在积极寻找在保证工人安全的同时重启或继续项目的方法。计算机视觉和机器学习可以帮助建筑经理确保他们的建筑工地是安全的。我们建立了一个实时监控渠道,跟踪员工之间的社交距离。

使用 TF OD API 进行社交距离监控(图片由作者提供)。

除了新的无形的 COVID 威胁之外,所有建筑工人每天都面临一些古老的危险,特别是“致命四大危险”:坠落、被物体击中、夹在物体之间以及触电危险。确保工人穿戴个人防护装备对建筑工地的整体安全至关重要。TF OD API 是构建自主 PPE 监控管道的一个很好的起点。我们的下一篇博客将讨论如何使用新的 TF OD API 训练一个基本的头盔探测器。****

使用 TF OD API 的个人防护装备(PPE)监测(图片由作者提供)。

建筑工地的某些区域比其他区域更危险。创建虚拟地理围栏区域并使用 CCTV 摄像机对其进行监控,为施工经理增加了巨大的价值,因为他们可以专注于其他任务,同时了解工地上发生的任何地理围栏违规事件。此外,地理围栏可以很容易地扩展到监控机器和重型设备的访问。

使用 OD API 进行地理围栏监测(图片由作者提供)。

结论

在这篇博客中,我们讨论了使用新的 TF2 OD API 的好处。我们已经展示了如何有效地评估 TF2 OD API 模型动物园中现成的预训练 OD 模型。我们还展示了如何使用 Allegro Trains 作为高效的实验管理解决方案,实现强大的洞察力和统计。最后,我们展示了一些建筑环境中物体检测的真实应用。****

这个博客是提供关于使用 TF2 OD API 的指导和建议的博客系列中的第个博客。在下一篇博客中,我们将展示如何训练一个定制的对象检测器,使您能够检测穿着 PPE 的工人。请关注我们,获取更多实践教程!此外,如果您有任何问题或意见,请随时联系我们!****

[1]“现代卷积物体探测器的速度/精度权衡”
黄 J、拉特霍德 V、孙 C、朱 M、科拉迪卡拉 A、法蒂 A、菲舍尔 I、沃伊娜 Z、
宋 Y、S、墨菲 K、2017

[2] TensorFlow 对象检测 API,https://github . com/tensor flow/models/tree/master/research/Object _ Detection

[3]“Efficient det:可扩展和高效的对象检测”谭明兴,庞若明,郭诉乐,

[4]“efficient net:卷积神经网络模型缩放的再思考”谭明星和郭诉乐,2019,

数据可视化新手?从纽约市开始

原文:https://towardsdatascience.com/new-to-data-visualization-start-with-new-york-city-107785f836ab?source=collection_archive---------11-----------------------

视频教程

我是如何利用纽约的大量公开数据以及 Plotly 和 Pandas 来发展我的数据可视化技能的

本文附有视频,并演示了第一个示例的代码。

介绍

像许多其他人一样,由于冠状病毒,我已经在家工作了几个星期。部分受 Terence Shin 关于隔离期间尝试数据科学项目的文章的启发,我决定利用一些空闲时间来提高我的数据科学技能。我是一名高中计算机科学教师,鉴于数据科学在当今世界日益突出,将数据科学技能添加到我可以教给学生的内容组合中对我来说很重要。我学到的一件事是,如果你想自学数据可视化,纽约市是一个很好的起点,我将在本文中解释为什么。在这个过程中,我将提供一些小型的纽约主题项目的例子,您可以试着更加熟悉如何用 Python 处理和可视化数据。

曼哈顿的 choropleth 地图,其中每个地块根据其到最近的公共图书馆的距离进行着色。

原因 1:数据,数据,数据

纽约市提供了大量高粒度的公共数据(在某些情况下可以精确到单个建筑)。你可以很容易地找到关于评估财产价值、按邮政编码划分的收入等级、公共设施位置等信息。此外,有很好的定制下载程序可以得到你需要的数据。

纽约市开放数据网站是搜索公开可用数据集和下载文件的一个很好的起点。

纽约开放数据门户:https://opendata.cityofnewyork.us/

纽约市政府发布了一个名为 PLUTO 的数据集,其中包含了该市每一个地段的税务相关信息。使用这个庞大的数据集,您可以获得关于城市中任何给定地块的各种信息,例如建筑面积的平方英尺数、楼层数、用于税收目的的评估财产价值、所有者的姓名等等。此外, MapPLUTO 数据集将这些数据与地理数据合并,为城市中的每个地块提供多边形。访问这些数据的一个很好的工具是 Chris Whong 的自定义 PLUTO downloader,它可以让您准确地选择您想要下载的城市区域,以及您想要的 PLUTO 数据的列。

Chris Whong 的纽约冥王星自定义数据下载器:【https://chriswhong.github.io/plutoplus/

纽约市首都规划平台是另一个优秀的自定义下载平台,您可以在其中查看所有公共设施,如公园、学校、医院、青年中心、停车场等。一旦您细化了您的选择,您可以下载数据作为一个 CSV 文件。

纽约市首都规划平台:https://Capital Planning . NYC . gov/map/facilities # 10/40.7128/-74.0807

原因 2:可识别性

作为一个标志性的全球城市,纽约既是商业圣地,又是旅游热点,还是无数电影和电视剧的背景,它的品牌知名度很高。大多数人可能对纽约的地理有一些基本的了解,如中央公园、五个区、纽约的一些街区(如上东区、哈莱姆区等)。).

照片由杰梅因·EeUnsplash 上拍摄

这种可识别性可以帮助您在预处理数据时理解数据,或者在您点击 run 时对结果进行检查。但是,即使你对这个城市不熟悉,其他观看你作品的人也很有可能会很熟悉。这使得涉及纽约市数据的项目非常适合个人作品集、博客或其他您希望与其他人分享以展示您的技能的媒体。

原因 3:多样性和密度

纽约既人口稠密又非常多样化。这些因素有助于使与纽约市相关的可视化更加有趣;可以在单个邻域的水平上进行非常有意义和数据丰富的可视化。它的多样性提供了许多分析和可视化数据的维度,尤其是以视觉或地图的形式,包括以下示例:

  • 社会经济地位与地理的关系
  • 种族/民族和地理之间的关系
  • 语言和地理的关系

伊恩·杜利Unsplash 上拍摄

范例项目#1:根据到最近图书馆的距离绘制曼哈顿地图

目标

这个项目的目标是可视化每个地块到最近图书馆的距离。但是,使用非常类似的过程,您还可以可视化到许多不同感兴趣要素的距离,例如地铁站、公园、学校或医院。choropleth 地图提供了一种极好的方式来直观显示大量地理数据。使用这种方法,很容易识别城市中潜在的“阅读沙漠”或“绿色空间沙漠”。

数据

我使用了 MapPLUTO 数据集来加载曼哈顿所有地块的信息,包括它们的纬度和经度。我还使用纽约市首都规划平台下载了曼哈顿所有图书馆的数据,包括它们的名称和纬度/经度。然后,我将这些数据作为熊猫数据帧加载到我的 Python 程序中。

计算到最近图书馆的距离

我第一次尝试计算每个批次的最近库是一种幼稚的蛮力方法,如下面的代码片段所示。由于大量的冗余计算,这被证明太慢了。

df['dist'] = df['coord'].apply(lambda x: min([geopy.distance.distance(x, y).km for y in libs['coord']]))

我的重大突破是想起了大学的一次讲座,教授提到了一种叫做 K-D 树的东西。这是一种为快速找到给定点的最近邻而优化的数据结构。这个的一个实现包含在sklearn.neighbors库中。因为我们处理的是(纬度,经度)坐标对,所以我们应该使用带有“哈弗辛”距离度量的BallTree。使用这个库来计算最近的库将运行时间加快了几个数量级。

到最近图书馆的距离是在单个批次的水平上计算的,给出了图书馆访问的细粒度视图。

我学到了什么

  1. 明智地使用 choropleth 地图。它们在某些情况下可能很棒,但在其他情况下可能会误导人。例如,美国 2016 年总统选举结果的县级 choropleth 地图会给人以该国绝大多数人投票给红色的印象,但这是误导性的,因为人口密度更高的地区倾向于投票给蓝色。
  2. 算法效率至关重要。尤其是在处理大型数据集时,要注意你是否在执行许多冗余的计算。做一些研究,看看是否有工具可以更好地完成你的部分任务,这样你就不会重复发明轮子。

代码

https://github.com/thomashikaru/nycvisualization访问数据文件和代码。

范例项目#2:根据人口密度绘制纽约市社区地图

目标

这个项目的目标是可视化纽约市不同社区的人口密度。稍加变化,同样的方法可用于可视化种族、收入或其他特征的分布。

数据

除了将城市划分为单独的地段或邮政编码之外,还可以将城市划分为相邻的制表区域。这些对应于纽约熟悉的街区,如上西区、唐人街或公园坡。找到包含每个邻域人口的数据文件相对容易,使用纽约开放数据工具下载包含邻域边界多边形的 GeoJSON 文件也相对容易。

从人口转换到密度

用总人口数来给地图着色可能会产生误导,因为社区的大小差别很大。相反,我们可以根据人口密度给地图上色。这需要计算每个邻域的面积,而这并不直接包含在数据中。使用area库,我们可以计算每个 GeoJSON 多边形的面积,然后使用这些值计算密度(人口除以面积)。

Choropleth 地图根据人口密度显示纽约市的邻近地区。

我学到了什么

  1. (再次)明智地使用 choropleth 地图。每个邻域的大小变化很大,有些随意。可视化每个邻域的密度比绝对人口更有意义。
  2. 将不同来源的数据结合起来。每个邻域的人口数据存储在一个 CSV 文件中(我将该文件读入 Pandas DataFrame),而每个邻域的多边形存储在 GeoJSON 文件中。我浏览了 GeoJSON 文件,制作了一个字典,将每个社区代码映射到它的区域,然后使用了熊猫。Series.map()函数将数据帧中的邻域与相应的区域进行匹配,以计算密度值。

代码

https://github.com/thomashikaru/nycvisualization访问数据文件和代码。

摘要

如果您是数据科学或数据可视化的新手,可以考虑选择纽约市作为起点,这样可以花更少的时间寻找数据,花更多的时间获取新技能。利用现有的大量数据和优秀的定制下载程序。

尝试上面提到的项目之一,熟悉有用的数据科学工具如 Pandas 和 Plotly,以及常用的数据格式如 GeoJSON 和 CSV。

我希望你学到了新东西。祝你在学习旅途中好运!

参考

[1] T. Shin, 14 天隔离期间要做的 14 个数据科学项目 (2020),中等。

[2] N. Piepenbreier,用 Python 漂亮地可视化新冠肺炎数据(不超过 5 分钟) (2020),中等。

[3] E .马尔迪,如何用 plottly(2020)创建交互式地图地块,中。

[4] T. Shin,如何用 Choropleth 图谱可视化疫情冠状病毒 (2020),中等。

新的 Windows 终端:你不能要求更多

原文:https://towardsdatascience.com/new-windows-terminal-the-best-you-can-have-9945294707e7?source=collection_archive---------2-----------------------

新的 Windows 终端在一个智能和高度可定制的包中结合了一切。

新的微软视窗终端

GNOME 终端终结者CmderHyper……很多用户信誓旦旦的 shell 接口和终端模拟器。有些提供更好的功能,有些提供便利或扩展的可定制性。

GNOME 终端,Terminator,Cmder,Hyper…很多用户信誓旦旦的 shell 接口和终端模拟器。但是神话和现实有交换思想的倾向。因此,每隔一段时间就会出现一种新的力量来统治他们。

依我拙见,《终结者》是天赐之物,直到最近还是我的司机。它提供了你能从终端模拟器中得到的一切,没有 Cmder 或 Hyper 的小故障。但是神话和现实有交换思想的趋势,因此,经常会出现一个新的国王来统治他们。

这一次,王者不知从哪里冒出来,而且是新的微软 Windows 终端。我的意思是,谁会想到微软会开发一个新的终端模拟器,它结合了你想要命令行工具做的任何事情,是开源的和高度可定制的?在这个故事中,我们将深入了解新的微软终端,熟悉它的功能,并看看我们如何对它进行定制。

学习率是我每周给那些对 AI 和 MLOps 世界好奇的人发的简讯。你会在每周五收到我关于最新人工智能新闻、研究、回购和书籍的更新和想法。在这里订阅!

新的 Windows 终端

Windows 终端是一个现代的、快速的、高效的、强大的和多产的终端应用程序。它结合了许多命令行工具和 Shell,如命令提示符、PowerShell 和 WSL(Linux 的 Windows 子系统)。因此,在一个应用程序中,我们可以为 Windows 用户提供命令提示符和 Powershell,为 Linux 终端高级用户提供 bash。

PowerShell 和 Ubuntu 并肩运行

Windows 终端的主要功能包括多个选项卡,其中有不同的命令行工具,分割区域,Unicode 和 UTF-8 字符支持,GPU 加速的文本渲染引擎,以及在主题和配置选项之间切换的简单方法。Windows 终端是一个开源项目,它将利用不断增长的贡献者社区继续扩展其功能。

装置

安装再简单不过了;只需前往微软商店并安装应用程序。Windows 终端也将继续通过商店接收自动更新;因此,您将始终拥有最新的稳定版本。

关键特征

新的 Windows 终端不会取代 PowerShell 或命令提示符。它们都在那里,您可以将它用作单独的控制台。但是它将它们结合在一个新的简洁的界面中。您还可以运行其他终端,就像我们将看到的那样,因此,让我们来看看主要功能。

  • 多标签:终端最需要的特性是多种标签支持。使用新的 Windows 终端,您可以运行自己选择的不同命令行工具或应用程序(例如,命令提示符、PowerShell、WSL 上的 Ubuntu、通过 SSH 的 Raspberry Pi 等)。)

多标签支持

  • 活力文字:新的 Windows 终端使用了 GPU 加速的文字渲染引擎。你可以在那里展示任何你想要的东西,无论是图标还是表情符号。由于一种叫做卡斯卡迪亚码的新字体,CJK 表意文字和编程连字也成为可能。

卡斯卡迪亚码字符

  • 可配置性:新的 Windows 终端——本质上是一个大型 JSON 文档——的设置为您提供了对每个 shell 外观的大量控制。您可以为 PowerShell、命令提示符、Ubuntu 终端甚至 SSH 连接创建不同的配置文件,每个文件都有自己的字体样式和大小、颜色主题、背景模糊/透明级别等。要获得灵感,请前往 Windows 终端主题

Windows 终端主题

bash on Windows 上的 Ubuntu

Bash on Ubuntu on Windows 微软在 //Build 2016 发布的巨大公告。自那时以来,我们走过了漫长的道路。WSL 2 现已正式发布,Windows 10 内部运行完整的 Linux 内核。

因此,作为一个例子,我们将定制在新的 Windows 终端中运行的 Ubuntu 终端。但是首先,如果您需要安装说明以及为什么要这样做,请阅读下面的文章:

[## 双重引导已死:Windows 和 Linux 现在合二为一了。

用 WSL 2 把你的 Windows 机器变成一个开发者工作站。

towardsdatascience.com](/dual-boot-is-dead-windows-and-linux-are-now-one-27555902a128)

有了这个设置和准备,很容易使它看起来像标准的 Ubuntu 终端。前往 Windows 终端主题并搜索 Ubuntu 主题。

当您按下Get theme按钮时,一个配置对象被添加到您的剪贴板中。这个对象看起来像这样:

{
  "name": "Ubuntu",
  "black": "#2e3436",
  "red": "#cc0000",
  "green": "#4e9a06",
  "yellow": "#c4a000",
  "blue": "#3465a4",
  "purple": "#75507b",
  "cyan": "#06989a",
  "white": "#d3d7cf",
  "brightBlack": "#555753",
  "brightRed": "#ef2929",
  "brightGreen": "#8ae234",
  "brightYellow": "#fce94f",
  "brightBlue": "#729fcf",
  "brightPurple": "#ad7fa8",
  "brightCyan": "#34e2e2",
  "brightWhite": "#eeeeec",
  "background": "#300a24",
  "foreground": "#eeeeec"
}

这些是关于每种颜色在您的终端中应该是什么样子的说明。现在,打开终端设置,将这个对象粘贴到一个名为schemes的数组中。你会看到这个物体有一个名字:Ubuntu。将该名称复制并粘贴到配置文件列表中指定 Ubuntu 终端的对象中。因此,该对象现在应该如下所示:

{
  "guid": "{07b52e3e-de2c-5db4-bd2d-ba144ed6c273}",
  "hidden": false,
  "colorScheme": "Ubuntu",
  "acrylicOpacity": 0.75,
  "useAcrylic": true,
  "name": "Ubuntu-20.04",
  "source": "Windows.Terminal.Wsl"
}

作为额外的奖励,我已经相应地将acrylicOpacityuseActylic选项设置为0.75true。这为窗口设置了一个很好的不透明度。此外,要在启动应用程序时将 Ubuntu 终端用作默认终端,请在设置的开头将guid代码复制到defaultProfile中:

"defaultProfile": "{07b52e3e-de2c-5db4-bd2d-ba144ed6c273}"

仅此而已。现在你有了运行在 Windows 10 内部的 Ubuntu,有了漂亮的终端应用,让你有家的感觉!

结论

在这个故事中,我们介绍了新的 Windows 终端,它是什么,如何获得它,它的主要功能是什么,以及如何让它遵循您自己的风格。你可以设置更多的选项:背景图片、按键绑定、自定义提示等。要摆弄这些选项和更多信息,请查阅官方文档,或者像这样的 GitHub 库。

学习率是我每周给那些对 AI 和 MLOps 世界好奇的人发的简讯。你会在每周五收到我关于最新人工智能新闻、研究、回购和书籍的更新和想法。在这里订阅!

关于作者

我的名字叫迪米特里斯·波罗普洛斯,我是一名为 BigDataStack 工作的机器学习研究员。我也是希腊比雷埃夫斯大学的博士生。我曾为欧洲委员会、欧盟统计局、国际货币基金组织、欧洲中央银行、经合组织和宜家等主要客户设计和实施人工智能和软件解决方案。

如果你有兴趣阅读更多关于机器学习、深度学习、数据科学和数据运算的帖子,请在 twitter 上关注我的媒体LinkedIn@james2pl

COVID 数据中的新手冒险

原文:https://towardsdatascience.com/newbie-adventures-in-covid-data-e54550704b1e?source=collection_archive---------55-----------------------

图片来自 CDC 开源

给许多有兴趣探索或掌握数据科学的人的建议是,找到一些让你感兴趣的数据,看看你能学到什么。当新冠肺炎重创马萨诸塞州,该州开始公布数据供下载时,这似乎是一个很好的起点。虽然大部分工作也可以在 Excel 中完成,但我使用 Python 来处理,以考虑到可重复性和潜在的数据增长。

注意,对于那些读过我写的更多商业媒体文章的人来说,这篇文章有点“编码”。欢迎来到人工智能产品管理思维的极客部分:你的客户有一个问题需要回答,这可能需要一些代码。然而,由于这个例子不需要复杂的机器学习,所以很容易理解。

作为一名自学成才的程序员,我承认可能有更好的方法来完成这项工作,并使用更多的 Python 函数进行设计,但这个故事更多的是关于旅程,而不是编码专业知识。

马萨诸塞州在这里发布其 COVID 数据:https://www . mass . gov/info-details/新冠肺炎-更新-信息#每日更新-

如果您对您所在州的相同分析感兴趣,这可能允许下载半原始数据,我在最后提供了一些州的开放数据链接示例。您还可以从 CDC 或其他网站(如 COVID data tracker)获取数据。我发现关注和使用我所在州的数据让我更好地了解了如何做出最有可能影响我生活的决定。对我来说,有时候做工作是理解别人如何看待这个问题的最好方式。

注意:这需要一个简单的 Python 3 Anaconda 环境。

首先加载一个库:

import numpy as np
import pandas as pd
import zipfile
from zipfile import ZipFile
from download import download
import csv
from io import BytesIO
import requests
import os
import matplotlib.pyplot as plt

在马萨诸塞州,每天都有一个压缩数据集,文件名中包含日期。为了下载,我做了一个函数:

def get_zip(zip_file_url):
 url = requests.get(zip_file_url)
 zipfile = ZipFile(BytesIO(url.content))
 zip_names = zipfile.namelist()
 if len(zip_names) == 1:
 file_name = zip_names.pop()
 extracted_file = zipfile.open(file_name)
 return extracted_file
 return [zipfile.open(file_name) for file_name in zip_names]

我发现随着时间的推移,命名约定会发生一些变化,因为数据格式从五月更新到六月,所以我分解了链接的组件,这样就可以很容易地只更改每次运行的日期。

June_Date_Name = “june-7–2020"Website_name = [https://www.mass.gov/doc/covid-19-raw-data-](https://www.mass.gov/doc/covid-19-raw-data-)Download_String = “/download”
june_zip_file_url = Website_name + June_Date_Name + Download_String

所以接下来需要做的就是运行这个函数:

get_zip(june_zip_file_url)

如果这是一次生产运行,我会将数据缓存或加载到云中,但是当我在探索时,文件格式和 zip 文件结构每月都有变化,我会将文件下载并解压缩到磁盘。

file_path = (“Extracts-June”)path = download(june_zip_file_url, file_path, kind=”zip”,replace=True,verbose=True)

作为一个新手,我确信有一个更好的方法来获得所有的区别。csv 文件转换成数据帧,但是对于这项工作,我只是将它们列出来(并不是所有文件都用于启动)。进一步的改进只会把所有的。csv 文件并忽略。xlsx 文件及其包含的计算和所需数据的过滤器,但如果您正在关注一个问题,该问题是主要的。

June_County_data = pd.read_csv(June_Directory + “/County.csv”) 
June_Age = pd.read_csv(June_Directory + “/Age.csv”) 
June_Age_means = pd.read_csv(June_Directory +”/Age Means.csv”) 
June_Cases = pd.read_csv(June_Directory + “/Cases.csv”) 
June_DateofDeath = pd.read_csv(June_Directory +”/DateofDeath.csv”) 
June_Admissions = pd.read_csv(June_Directory +”/Hospitalization from Hospitals.csv”) 
June_LTC_Facilities = pd.read_csv(June_Directory +”/LTC Facilities.csv”) 
June_Race_Ethnicity = pd.read_csv(June_Directory +”/RaceEthnicity.csv”) 
June_Sex = pd.read_csv(June_Directory + “/Sex.csv”) 
June_Testing = pd.read_csv(June_Directory + “/TestingByDate.csv”)

由于我的兴趣,首先,主要是重新打开和测试的效果,我从 5 月开始关注(同样,更好的代码将通过日期而不是文件位置来指定数据,但这是关于冒险的。)

June_Testing_Format = June_Testing[[“Date”,”Molecular New”,”Molecular Positive New”,
 “Serology New”, “Serology Positive New”]]
May_on_Testing_Data = June_Testing_Format.iloc[100:] # Start on May 1

当我开始研究分子检测数据(检测你是否感染了病毒)时,马萨诸塞州州长提出了一个目标,即每天进行 45,000 次检测,目标阳性率为 5%。

当我在五月底运行代码时,这是图表:测试趋势上升…

5 月份,测试开始下降。

现在,在六月的第一周,每天的测试仍然在下降,但是在重新开放的第二阶段之前,阳性率似乎降到了 5%以下。我玩了 7 天均线,但是平的趋势线看起来更好。

May_on_Testing_Data[‘Days’] = np.arange(len(May_on_Testing_Data))
x = May_on_Testing_Data[“Days”]
y = May_on_Testing_Data[“Molecular New”]plt.plot(x, y, ‘o’)
m, b = np.polyfit(x, y, 1)
plt.plot(x, m*x + b)
plt.title(“New Molecular Tests per Day for COVID-19 in Massachusetts from 05–01 to 06–09”)
plt.axhline(y= 20000, xmin=0, xmax=1, color=”g”)
plt.xlabel (‘Days’)
plt.show()

6 月,该州增加了抗体血清学检测。在马萨诸塞州,你可以要求你的医生推荐这项测试或者直接报名。保险范围是可变的。我很好奇,想知道抗体测试进行得如何,测试水平有多高,以及即使考虑到 CDC 抗体测试的不确定性和测试提供商的警告,抗体呈阳性的趋势是否存在。请参见下面 Quest Diagnostics(马萨诸塞州领先的 COVID 测试公司)的示例。注意:普通感冒是一种冠状病毒。

到目前为止,似乎没有很多抗体测试。无论这是由于直接支付的费用(119 美元),还是由于人们不被鼓励进行检测,还是由于新闻中关于假阳性的消息。

在波士顿,马萨诸塞州总医院的最新研究显示,在 750 名居民的代表性样本中,抗体阳性率为 9.9%。

从 5 月至今的总体血清学阳性率来看(自 5 月 1 日以来进行了 41,228 次检测,约占人口的 0.06%),有些日子的峰值约为 10%,但由于样本可能包含很高比例的知道自己感染了病毒的人,因此得出人口中抗体水平正在上升的结论似乎还为时过早。

随着黑人的命也是命的抗议和媒体对可变存活率的关注,我开始想知道马萨诸塞州的数据是什么样的,所以我从种族/民族数据中提取了最后一部分数据,绘制了种族/民族的死亡百分比,并查看了这些数据。

Race_Data = June_Race_Ethnicity[-6:]Race_Data_Total = Race_Data[‘Deaths’].sum()
Race_Data [‘Death Percents’] = Race_Data [‘Deaths’] / Race_Data_Total
Race_Data [‘Death Percents’]= round(Race_Data [‘Death Percents’], 3)
Race_Data.head(10)

我真正需要了解的是,这是否代表了人群中的爆发。我能找到的最新数据是 2017 年的。认识到误差幅度,看起来黑人实际上比白人做得更好。

Race_Census_Data = {‘Race/Ethnicity’: [‘Non-Hispanic White’, ‘Non-Hispanic Black/African America’,
 “Hispanic”, “Non-Hispanic Asian”, “Non-Hispanic Other”, “Other”],

 ‘Census Percents’: [.714,.089,.123,.071,0,.031]
 }Race_Census = pd.DataFrame (Race_Census_Data, columns = [‘Race/Ethnicity’,
 ‘Census Percents’])

根据新闻,我对此感到惊讶,并四处查看这是否是一种异常现象。果然,凯泽家庭基金会也采取了同样的观点,认为马萨诸塞州的病例与人口统计数据相当,黑人的死亡率略低于人口分布的预期。

Covid 立即行动的人口统计数据页面中的图片

所有这些让我再次对测试感到好奇。设定一个日期,看看我是否会加入血清学阳性,如果不会,至少增加另一个数据点。然后可能会回到线性回归之外的东西,使用 Tensorflow,在云和 GPU 中运行,以及所有这些复杂性。甚至可能测试 COVID ACT NOW API

你将带着数据走向何方?你会确定一个模型,说我们中有足够多的人已经暴露,它是安全的兴高采烈地去海滩吗?你会更好地理解你的本地数据,并做出自己的“哇,这是趋势上升/下降决策/ 超过 5% 积极决策”吗?

你会将你的阳性结果趋势与国家出版物和其他外部分析进行比较吗?当范围从 4%到 10%时,您会质疑加权/平滑措施吗?

你会四处搜寻什么血清学测试看起来最有效的数据吗?

你会绕过所有的数据工作,直接注册警报或监控网站让你知道你住的地方什么时候有危险吗?

或者你会在秸秆市场上购买最好的芜菁价格(我对内幕和期货交易的基本了解的推荐)?

冒险是你的追求!

系列中的下一个:https://medium.com/me/stats/post/a54e5f51e1fa

样本数据链接:(注意:有些州不提供数据可视化)。

加州:https://www . cdph . ca . gov/Programs/CID/DCDC/Pages/Immunization/ncov 2019 . aspx

科罗拉多州:【https://data-cdphe.opendata.arcgis.com/search?tags=covid19】T2

康涅狄格州:【https://data.ct.gov/browse?】T4 类别=健康+和+人类+服务

明尼苏达州:https://mn.gov/covid19/data/index.jsp

纽约州:https://www1 . NYC . gov/site/doh/covid/新冠肺炎-data . page #下载

华盛顿州https://www.doh.wa.gov/Emergencies/Coronavirus

美国疾病控制中心:https://www.cdc.gov/nchs/covid19/index.htm

covid Act Nowhttps://covidactnow.org/?s=44750(还提供了一个状态数据源列表和一个API用于它们的数据)

Github 链接:https://github . com/AlisonDoucette/covid 19/blob/master/State % 20 of % 20MA % 20 covid % 20 data % 20 analysis % 20-% 20 trends . ipynb

COVID 数据中的新手冒险——将 API 用于聚合数据,将 Plotly 用于图表

原文:https://towardsdatascience.com/newbie-adventures-in-covid-data-leveraging-apis-for-aggregated-data-and-plotly-for-charts-a54e5f51e1fa?source=collection_archive---------78-----------------------

来自 COVID ACT NOW APIs 的标准化数据允许对各州的每日阳性率进行比较

图片由 Alison Doucette 提供

在《COVID 数据历险记》的第一集中,我们开始探索使用 Python 基础知识(类似于 Excel 的函数)来查看新冠肺炎数据和马萨诸塞州的趋势。本周的挑战是利用由 COVID ACT NOW 发布的 API 来探索所有给定了标准化数据集的州,并利用 Plotly 进行可视化。

如果你想继续学习,你可以在这里找到 COVID ACT NOW API 的文档。GitHub 存储库非常有用,因为它展示了如何调用 API 以及如何提取数据。虽然有可能提取。CSV 文件(在我们的第一次冒险中,我们从一个. zip 文件导入)这次我要求 JSON 作为格式。

对于那些对 PLOTLY 感兴趣的人,这里有一个到文档的链接。虽然有很多复杂的图表可用,但我只是复制了我用 Matplotlib 做的简单图表。

首先是一些图书馆。(由于这是在 Anaconda 中使用 Juypter 笔记本,在开始之前,我按照这里的说明在终端中进行了 conda 安装。

import numpy as np
import pandas as pd
import requests
from pandas import DataFrame
import matplotlib.pyplot as plt 
import plotly.graph_objects as go
import plotly.express as px

因为我知道我将为美国的不同州调用 API,所以我决定在组件中构建 URL,前缀是州代码(例如:MA 或 TX)作为一个单独的变量,后缀包括对 trends 和 JSON 格式的“时间系列”数据的请求。这将允许我在将来的某个时候比较不同的状态。

注意:从 7 月 5 日起,API 的输出不再与记录的 JSON 相匹配,所以这段代码不再起作用。根据 GIThub 链接:“从 6/5 开始,cumulativePositiveTestscumulativeNegativeTeststimeseries行中移除。该数据在actualsTimeseries字段中仍然可用。

URL_prefix = “[https://data.covidactnow.org/latest/us/states/](https://data.covidactnow.org/latest/us/states/)"state_code = “MA”URL_suffix = “.OBSERVED_INTERVENTION.timeseries.json”Call_URL = URL_prefix + state_code + URL_suffix

然后是时候用请求调用 API,请求数据并打印出状态代码。

response = requests.get(Call_URL)
data = response.json()
print(“Status Code”,response.status_code)

一旦我有了数据,我们的目标就是为每日检测率以及 COVID 检测的阳性率绘制趋势图。API 的伟大之处在于每个州的数据格式都是标准化的。缺点是 API 不包含抗体测试的数据。

正如本周《纽约时报》指出的那样,缺乏抗体并不一定意味着你从未被感染,或者你缺乏免疫力,拥有抗体也不一定意味着它们不会随着时间的推移而消失,但观察这些数据很有趣。

一旦接收到数据,我只需要将数据划分到我想要的列中,包括包含阴性测试的第一行作为开始日期,并排除尚未进行测试的日期。

*COVID_Series = (data[“timeseries”])
COVID_Run_Date = (data[“lastUpdatedDate”])
COVID_df = DataFrame(COVID_Series,columns=[‘date’,”cumulativePositiveTests”, “cumulativeNegativeTests”])
Start_Row = COVID_df[‘cumulativeNegativeTests’].notna().idxmax()
End_Row = COVID_df[‘cumulativeNegativeTests’].notna()[::-1].idxmax()
COVID_df = COVID_df.iloc[Start_Row:End_Row]*

然后,我需要确定每天的新测试,并计算每天的阳性率。

*COVID_df[‘date’] = pd.to_datetime(COVID_df[‘date’], format=’%Y-%m-%d’)
COVID_df['State'] = state_code
COVID_df[‘Dly_PosTests’] = COVID_df[‘cumulativePositiveTests’].diff()
COVID_df[‘Dly_NegTests’] = COVID_df[‘cumulativeNegativeTests’].diff()
COVID_df[‘Dly_Tests’] = COVID_df[‘Dly_PosTests’] + COVID_df[‘Dly_NegTests’]
COVID_df[‘Dly_Pos_Rate’] = (100* (COVID_df[‘Dly_PosTests’] / COVID_df[‘Dly_Tests’]))*

这给了我一组数据来绘制图表:

我对阳性测试结果的增长很感兴趣。

*fig = px.line(COVID_df, x=”date”, y=”cumulativePositiveTests”)
fig.update_layout(
 title=”Cumulative Positive Tests to Date”,title_x=0.5,
 xaxis_title=”Month”,
 yaxis_title=”Positive Tests”,
 font=dict(
 family=”Courier New, monospace”,
 size=12,
 color=”#7f7f7f”
 )
)
fig.show()*

考虑到数据隐私问题,如果可能对第一反应者进行重复检测,则不可能绘制出已检测人群的百分比,但可以绘制出每日阳性率。

每天的测试总数可以给你一个关于测试模式的想法。

最后,我们可以看看用天数代替时间后的一些趋势:

*COVID_df[‘Days’] = np.arange(len(COVID_df))fig = px.scatter(COVID_df, x=”Days”, y=”Dly_Tests”, trendline=”ols”)
fig.update_layout(
 title=”Total Tests per Day Trend”,title_x=0.5,
 xaxis_title=”Days of Completed Testing”,
 yaxis_title=”Tests per Day”,
 font=dict(
 family=”Courier New, monospace”,
 size=12,
 color=”#7f7f7f”
 )
)
fig.show()*

**

利用 COVID ACT NOW APIs 提供美国各州的标准化数据。也就是说,数据有点混乱,需要更多的清理,因为数据输入错误可能会导致一些扭曲的值:(下面第 4 行是佛罗里达州的数据)。

结果图如下:

而不是更可能匹配真实情况的东西:(从第 14 行开始)并使用 LOWESS 趋势:

**

在这次冒险中,我们坚持一次只为一个州调用 COVID ACT NOW APIs,但是我们可以为所有的州调用它们,并开始比较各个州。我们可以使用移动平均线来平滑给定的周模式数据。我们可以建立一个用户界面,使整个过程更加用户友好。谁知道我们会去哪里?

当你和云雀一起起床时,你的每一天都是以冒险开始的!

接下来的系列文章:https://medium . com/@ Alison . doucette/newbie-adventures-in-covid-data-maps-for-hotspots-and-positivity-rates-64 FBE f1 a 163

图片由 Alison Doucette 提供

Python-igraph 新手指南

原文:https://towardsdatascience.com/newbies-guide-to-python-igraph-4e51689c35b4?source=collection_archive---------11-----------------------

python-igraph 常用函数的简单指南,包含示例和代码

目前,随着不同模块的出现,处理图形/网络数据变得更加容易。对于 python 来说,其中两个这样的模块是 networkxigraph 。我使用 python-igraph 模块已经有一段时间了,我发现它在我的研究中非常有用。我在我最新发布的工具 GraphBin 中使用了 python-graph。在本文中,我将向您介绍 python-igraph 的一些基本功能,这些功能只需一个调用就可以使实现变得更加容易。

你可以阅读我的前一篇文章用 python-igraph 可视化图形数据,在那里我介绍了 Python-igraph 模块。

[## 用 Python-igraph 可视化图形数据

使用 CiteSeer 数据集介绍 python-igraph 模块

towardsdatascience.com](/visualising-graph-data-with-python-igraph-b3cc81a495cf)

在本文中,我们将介绍执行以下任务的函数。

  1. 创建图表
  2. 将图表可视化
  3. 获得关于图的顶点和边的信息
  4. 获取顶点的相邻顶点
  5. 从顶点开始的广度优先搜索(BFS)
  6. 从顶点确定最短路径
  7. 获得图的拉普拉斯矩阵
  8. 确定源顶点和目标顶点之间的最大流量

1.创建图表

图一。示例图表

让我们从绘制如图 1 所示的示例图开始。

这是一个包含 5 个顶点的有向图。我们可以创建如下的图表。

# Create a directed graph
g = Graph(directed=True)# Add 5 vertices
g.add_vertices(5)

顶点将被标记为从 0 到 4 和 7 个加权边(0,2)、(0,1)、(0,3)、(1,2)、(1,3)、(2,4)和(3,4)。

# Add ids and labels to vertices
for i in range(len(g.vs)):
    g.vs[i]["id"]= i
    g.vs[i]["label"]= str(i)# Add edges
g.add_edges([(0,2),(0,1),(0,3),(1,2),(1,3),(2,4),(3,4)])# Add weights and edge labels
weights = [8,6,3,5,6,4,9]
g.es['weight'] = weights
g.es['label'] = weights

2.将图表可视化

现在我们已经创建了我们的图表,让我们使用 igraph 的绘图功能来可视化它。

visual_style = {}out_name = "graph.png"# Set bbox and margin
visual_style["bbox"] = (400,400)
visual_style["margin"] = 27# Set vertex colours
visual_style["vertex_color"] = 'white'# Set vertex size
visual_style["vertex_size"] = 45# Set vertex lable size
visual_style["vertex_label_size"] = 22# Don't curve the edges
visual_style["edge_curved"] = False# Set the layout
my_layout = g.layout_lgl()
visual_style["layout"] = my_layout# Plot the graph
plot(g, out_name, **visual_style)

图二。彩色图形

运行这段代码将得到如图 1 所示的图形。如果你想的话,你可以给顶点上色,如图 2 所示,通过添加g.vs[“color”] = ["red", "green", "blue", "yellow", "orange"]代替线visual_style[“vertex_color”] = ‘white’。你可以从我以前的文章用 Python-igraph 可视化图形数据中读到更多关于可视化图形和分析它们的内容。

3.获取图的顶点和边的信息

通过调用vcount()ecount()is_directed()maxdegree()get_adjacency()函数,可以获得图的一些基本信息,如顶点数、边数、图是否有向、最大度、图的邻接矩阵等。

print("Number of vertices in the graph:", g.vcount())
print("Number of edges in the graph", g.ecount())
print("Is the graph directed:", g.is_directed())
print("Maximum degree in the graph:", g.maxdegree())
print("Adjacency matrix:\n", g.get_adjacency())

输出如下所示。

Number of vertices in the graph: 5
Number of edges in the graph 7
Is the graph directed: True
Maximum degree in the graph: 3
Adjacency matrix:
 [[0, 1, 1, 1, 0]
 [0, 0, 1, 1, 0]
 [0, 0, 0, 0, 1]
 [0, 0, 0, 0, 1]
 [0, 0, 0, 0, 0]]

4.获取顶点的相邻顶点

您可以使用函数neighbors(vid, mode=ALL)获得给定顶点的相邻顶点。如果我们考虑顶点 0,相邻的顶点或邻居将是顶点 1、2 和 3。

print(g.neighbors(0, mode=ALL))

5.从顶点开始的广度优先搜索(BFS)

从顶点开始执行广度优先搜索,可以使用函数bfs(vid, mode=OUT)

print(g.bfs(0)[0])

返回的顶点 id 将是[0, 1, 2, 3, 4]

6.从顶点确定最短路径

您可以使用函数get_shortest_paths(vid)获得从给定顶点开始的最短路径。你想指定目标顶点为get_shortest_paths(vid, to=destination)

print(g.get_shortest_paths(0))

上面的线将导致从顶点 0 开始到所有顶点的所有最短路径,这将是[[0], [0, 1], [0, 2], [0, 3], [0, 2, 4]]

print(g.get_shortest_paths(0, to=4))

上面这条线将返回从顶点 0 到顶点 4 的最短路径,即[[0, 2, 4]]

7.获得图的拉普拉斯矩阵

您可以使用laplacian()函数获得图的拉普拉斯矩阵

print("Laplacian matrix of a graph:\n",g.laplacian())

输出如下所示。

Laplacian matrix of a graph:
 [[3, -1, -1, -1, 0], [0, 2, -1, -1, 0], [0, 0, 1, 0, -1], [0, 0, 0, 1, -1], [0, 0, 0, 0, 0]]

8.确定源顶点和目标顶点之间的最大流量和最小切割

让我们假设在我们的例子中源顶点是顶点 0,目标顶点是顶点 4。我们可以使用函数maxflow(source, target, weights)确定源和目标之间的最大流量和最小切割(根据最大流量最小切割定理)。

maxflow = g.maxflow(0,4,weights)print(maxflow.value)
print(maxflow.flow)
print(maxflow.cut)
print(maxflow.partition)

图三。图中最大流量与对应于
流量的最小切割

上面的行将输出一个图形流对象,流的最大值为13,每个顶点的流值为[4.0, 6.0, 3.0, 0.0, 6.0, 4.0, 9.0],边上的最小割 id 为[5, 6],顶点之间的划分为[[0, 1, 2, 3], [4]]

图 3 表示与最大流量和最小切割相关的值,切割用紫色标记。边上紫色的值是流量值。我们可以看到,顶点 0、1、2 和 3 在一个分割中,顶点 4 在另一个分割中,这两个分割由割形成。

你可以从我的文章 10 图算法直观解释中读到更多关于图算法的内容。

[## 直观解释的 10 种图形算法

10 种基本图形算法的快速介绍,包括示例和可视化

medium.com](https://medium.com/@vijinimallawaarachchi/10-graph-algorithms-visually-explained-e57faa1336f3)

最后的想法

如果您遇到一个不知道如何使用的函数,您可以简单地打印它的 docstring,它将描述该函数的输入、输出以及它的作用。举个例子,

print(g.bfs.__doc__)
print(g.laplacian.__doc__)
print(g.maxflow.__doc__)

就个人而言,我发现 python-igraph 是我工作中非常有用的模块。您可以使用提供的函数轻松地表示图形和执行不同的分析任务。

我附上了 jupyter 笔记本,其中包含了我在本文中使用的所有示例和代码。请随意使用它,并希望您也能在工作中使用 igraph。

感谢您的阅读!

干杯!

参考

[1]https://igraph.org/python/doc/igraph-module.html的 Python-igraph 手册

[2]示例图改编自https://www.youtube.com/watch?v=u6FkNw16VJA

新手学习强化学习指南

原文:https://towardsdatascience.com/newbies-guide-to-study-reinforcement-learning-8b9002eff643?source=collection_archive---------4-----------------------

在强化学习领域迈出小步

本指南中介绍的入门资源包

如果计量付费墙困扰着你,请点击此链接

如果你想知道我的深度学习之路,可以看看我在新手深度学习指南上的文章。

我在这里要谈的不是强化学习,而是如何研究强化学习,我采取了哪些步骤,以及我在学习过程中发现哪些是有帮助的。如果你发现一些有用的东西,请在评论中告诉我。如果您有其他想要推荐的路径,请将它们留在评论中让其他人看到(我会在适当的地方编辑、添加和更新文本)。和平的人们!

阻止信息泛滥

强化学习有相当多的概念需要你去思考。看到 RL 技术的完整分类后,你的脑袋会转得更快。一旦你开始阅读所有最酷和最新的研究,以及它们让事情运转的技巧和细节,事情就会变得更加复杂。但是看那些 OpenAI 机器人玩 DoTA 太酷了,你可能会想学习它的所有技术和技巧,并建立自己的机器人。首先,停在那里。暂时忘记如何实现自己版本的 OpenAI Five。你最终可能会回到起点;也就是说,永远离开 RL,却发现自己在三个月后试图重新学习。

你需要从大量的教程(我的两分钱教程)和 YouTube 视频中抽身出来,告诉他们你可以用 20 行代码在 5 分钟内编写出“一些棒极了的 RL 东西”之类的东西。因为他们都没教你什么!是的,什么都没有(除了 git 克隆和/或复制代码)。一旦你足够努力地去弄清楚价值迭代是如何工作的,并意识到这个想法如此简单,但对于一个简单的玩具例子来说却非常有效,你就会知道知识的真正味道。这就是你学习的方式,也是你在这条学习道路上前进的方式。

在线课程

所以,让我们理清思路,重新开始,让自己保持冷静,参加 Coursera 的实用强化学习课程。本课程将不是在公园散步,但挑战是锻炼你的大脑和质疑自己是否完全掌握了核心概念。它从非常基本的交叉熵方法开始,逐渐发展到策略迭代、值迭代、Q 学习和 SARSA。课程的后半部分包括:深度 Q 网络和演员-评论家算法。这门课程的一个好处是,你不需要担心繁重的计算资源,因为你可以在 Coursera 或 Google Colab 的 Jupyter 笔记本上完成作业(他们有在 Colab 上设置的说明),甚至可以在你自己的机器上用你最喜欢的 IDE 完成。就个人而言,我更喜欢在我的本地 IDE 中编写代码,因为我拥有所有的调试工具。事实上,我甚至会引导您在 IDE 中运行和调试代码,因为您需要理解 OpenAI gym 对象实际包含的内容(使用 print 语句并不理想)。否则,你会觉得事情是在黑盒子里,尽管它们不是。查看 OpenAI 文档,感受特定的环境并愉快地开始调试(是的,当我进行调试会话时,我非常高兴;不确定你会有什么感觉)。

当你学习新概念时,你的 IDE 和调试器是你最好的朋友。我发现 Jupyter 笔记本在跳跃、查找文档和调试时非常笨重。但那是我个人的看法。

但是课程视频会变得非常乏味,你不想吸收任何东西。如果是这种情况,停止视频,直接开始编程作业。我有时发现这真的很有帮助,因为它给了我一个更好的动机,为什么我应该学习课程视频喋喋不休的内容。结合阅读我将在下面提到的教科书。

身边放一本教科书(这会给你很大帮助!)

课本很无聊。我明白了。但有时,他们是那些能在网上文章的海洋中给你一些安慰的人。我在强化学习方面的首选教材是萨顿和巴尔托的《强化学习:导论。如果你曾经搜索过强化学习教材,这不会让你感到惊讶,而且它是大多数大学课程的首选教材。

萨顿和巴尔托写了这么好的教科书,真是太棒了。我发现阅读和查找我想知道的东西是一件非常愉快的事情。事实上,我甚至强烈推荐你阅读教材的第一章,对强化学习有一个非常温和的介绍。我发现它比任何其他在线教程或媒体帖子都好。

这本教材的另一个真正的好处是,即使在学习 Coursera 课程时,我有时也会发现阅读教材比课程视频本身对我的帮助更大。这有点奇怪,因为大多数时候情况正好相反。所以,我所做的就是在课本和课程视频之间来来回回,填补我的知识空白。然后,我尝试编程作业,以真正检查我是否理解算法的技术细节。

通过编码学习,而不仅仅是通过阅读

当我开始进入强化学习的世界时,我总是对“价值函数”、“Q 值”、“最优策略”和“策略”之间的联系感到困惑。相信我,在你实施并使用这些概念来训练你的特工之后,这些概念就会变得一清二楚。阅读文本,观看课程视频,实现功能,运行,调试,重复。

四处玩耍

当你在学习 Coursera 课程的时候(最好是在你完成了课程的第三周,并且对 Q-Learning 有所了解之后),看看 Lex Fridman 关于深度强化学习的讲座。这不是技术性的,但现在,你会对幻灯片中的 Q-learning 部分有更好的理解。关于强化学习的事情是,如果你在需要知道某些概念的时候用谷歌搜索它们,你会暂时记住这些知识,但如果你对这些概念背后的作用没有深刻的理解,你将永远感到困惑。这也是我建议你在充分理解基本概念后去查阅那些讲座的原因之一。然后,试用深度流量。有几个参数可供选择,如果你不确定这些参数的含义,查看的文档并阅读论文以更好地了解为什么某些参数会有帮助。然后,去试试 Karpathy 的深度 Q-Learning Demo 。现在,您应该非常熟悉各种超参数。

尝试几个随机参数并得到好的结果是有趣的,但是不要忘记了解你的变化背后的“为什么”。[ 深度交通

参数是脆弱的,但首先检查错别字!

当你开始研究强化学习问题时,你会开始意识到这些参数是多么脆弱。将您的 epsilon 调整到一个特定的数字,以便在您的代理开始开发之前进行足够的探索,这与为您的 DQN 网络建立一个具有确切参数的确切架构一样重要。所有这些都会让您认为,如果您的代理没有做好工作,您就没有将所有这些讨厌的超参数调得足够好。但是通常情况下,您可能在代码中的某个地方有一个打字错误。在更新 Q 值时,您可能错误地传递了当前状态,而不是下一个状态。所以,在你花一整天的时间调优一个参数而没有得到任何好的结果之前,一定要先检查你的代码。

走向广阔

一旦你很好地掌握了基本的强化学习概念,就开始跟随加州大学伯克利分校深度强化学习课程的讲座和大卫·西尔弗关于强化学习的讲座。这有助于重申你所学到的东西,并确保你仍然可以跟上,尽管在符号等方面有细微的变化(我们在机器学习文献中也看到了很多;人们使用稍微不同的符号只是为了让你更困惑!).

既然你对强化学习的基础有了很好的理解,你应该开始阅读关于 DQN 的开创性论文。如果你只理解深度学习部分而不理解强化学习部分,直接进入深度强化学习是不可取的。这是那些非常精通深度学习但不知道强化学习是什么的人的一个主要谬误。

配备了基本的强化学习知识,就可以开始阅读各种深度强化学习论文(并开始实施)。你在某些概念上会有一些知识缺口,但你应该已经有了工具箱中的核心概念,学习额外的技术不再那么困难。我个人的技巧是使用思维导图软件来绘制概念和论文(描述于新手深度学习指南)。

其他资源

不管怎样,伙计们,我希望这篇指南能给你足够的动力,让你真正认真对待强化学习,让你从永无止境的 YouTubing 和在线阅读教程的循环中解脱出来。

两周内的新闻聚合

原文:https://towardsdatascience.com/news-aggregator-in-2-weeks-5b38783b95e3?source=collection_archive---------24-----------------------

一种简单快速的新闻分类和聚类方法

图片由 Pezibear 通过 Pixabay 拍摄

数据聚类大赛是 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨 在 11 月举办的为期两周的数据科学竞赛。丨t丨e丨l丨e丨g丨r丨a丨m丨s丨 团队希望参与者建立一个简单而有效的新闻聚合器,将来自不同出版商和网站的数以千计的文章整合到一个页面中,显示最新的新闻和头条新闻,就像谷歌新闻必应新闻所做的那样。

提交的公共测试屏幕。作者图片

尽管比赛于 2019 年 12 月 2 日结束,主办方还是在一周前宣布了结果。我们的团队“用心松鼠”在最终排行榜中排名第三。在本帖中,我们简要概述了我们的方法,并讨论了我们遇到的主要挑战。完整的解决方案可从 GitHub 上获得。所有培训脚本都在 Colab 中共享。

任务概述

竞赛包括五个子任务,预计将在原始数据上按顺序运行:

  1. 语言识别(只需要英文和俄文文本)
  2. 从其他文本中过滤新闻
  3. 分为 7 个主题
  4. 将与同一事件相关的文章聚类成线索
  5. 对每个主题中的线索进行排名

竞赛任务。图片由作者提供,使用 draw.io 创建

语言检测这一步似乎非常清楚,而其他任务却提出了一堆问题。没有给出“新闻”的严格定义;主题标准没有很好地定义;聚类粒度和排名标准也缺失。

竞赛规则要求最终提交的作品在 Debian 的一台机器上本地运行,该机器有 8 个内核和 16 GB 内存,不使用网络。此外,该应用程序必须能够在 60 秒内处理任何一批 1000 篇文章。限制的第一个版本还包括对超过 200 MB 磁盘空间的解决方案的惩罚。

解决办法

这些限制严重影响了适用仪器和算法的范围。第一个想法是采用 SOTA 模式,如埃尔莫伯特。但是,它们太大,不符合要求。因此,我们广泛依赖于一个快速文本库。这是脸书人工智能研究所在 2016 年创建的用于学习单词嵌入和训练文本分类模型的库。整个提交代码都是用 C++写的,唯一复杂的模型是用 Python 和 Keras 训练的。

语言检测

这项任务的解决方案很简单。我们利用了由 fastText 团队提供的预训练模型。

过滤和主题分类

我们将这两个任务合并成一个单一的多类分类问题。由于任何监督分类器都需要一定数量的训练数据,我们利用了 Yandex。Toloka 标注一小部分输入数据。Toloka 是俄罗斯的众包平台,就像亚马逊机械土耳其人一样。我们花了 60 美元购买了俄文和英文的标签。我们使用机器翻译英语文本到俄语,以方便说俄语的工作人员。

我们还扩展了数据集,增加了俄语新闻数据集 Lenta.ru 和英语新闻数据集 BBCHuffPost 的公开数据。

分类数据集。图片由作者提供,使用 draw.io 创建

利用所有标记的数据,我们训练了一个简单的快速文本分类器。默认的快速文本分类算法学习所提供数据上的单词嵌入,然后使用它们的平均值进行预测。在缺少标记数据的情况下,利用丰富的预训练单词表示通常会提高分类器的性能。我们在由 RIA“所有新闻”语料库扩展的先前数据集上训练这样的无监督向量。

新闻聚类

新闻聚类的两个基本要素是丰富的文本嵌入和健壮的聚类算法。

对单词向量进行简单的平均不会产生好的结果,这迫使我们应用一些更复杂的东西。我们使用结合了点积、密集层和顶部的 sigmoid 的连体神经网络架构来训练最终的文本嵌入。该分支的体系结构由单词向量上的平均池、最小池和最大池串联而成的单一密集层组成。我们将每个文本分成两半,然后训练网络来预测这些部分是否属于同一篇文章。我们从同一出版商的其他文本中挖掘与正面例子时间接近的负面例子。作为一个目标函数,我们使用了对数损失函数,尽管我们应该使用三重损失

用于构建文本嵌入的暹罗网络。图片由作者提供,使用 draw.io 创建

该模型仍然尽可能简单,只有一个可训练矩阵。在实际的 C++应用中,我们没有使用任何神经网络框架,只使用了矩阵乘法的特征库。

我们利用了 SLINK 凝聚聚类。该算法有一些缺点,其中最重要的是传递链接。第一个点可能与第二个点相关联,第二个点可能与第三个点相关联,因此,第一个点和第三个点属于同一群,尽管它们可能相距甚远。

凝聚集群。图片由作者提供,使用 draw.io 创建

SLINK 的时间复杂度为 O(n ),这使得我们无法一次聚类所有的文档。为了克服这个问题,我们假设时间上遥远的文档不应该属于同一个集群。这个假设允许我们将整个时间线分成 10,000 个文档的块,其中有 2,000 个项目重叠。然后,我们在每个块中应用聚类,最后,通过重叠的文档链接连续的块。

按块聚类。图片由作者提供,使用 draw.io 创建

线程命名和排序

我们在一个线程中的标题选择基于三个部分的乘积:新鲜度、与其他线程文档的相似性以及文档的源权重。

我们将新鲜度定义为文档日期和线程中最新鲜文档的日期之差的缩放后的 sigmoid。

使用与聚类中相同的文本向量来计算线程的文档之间的内部相似性。对于每个线程中的每个文档,我们计算了到线程中其他文档的平均距离。

对文档内部链接的 PageRank 算法允许我们评估来源的重要性。

新鲜度、源权重和簇大小形成了线程排序的基础。所有发布日期的第 99 百分位被选为整个数据集的“当前时刻”,因为可能存在异常值。线程的年龄是从这个“当前时刻”计算的。

结论

挑战的最重要部分是建立一个满足严格硬件限制的系统。这些限制以及短暂的比赛持续时间迫使我们依赖简单的机器学习算法(如 fastText),而不是复杂的 SOTA 模型。我们没有足够的时间进行所有我们想要的实验或完善最终的解决方案。尽管我们在比赛结束后做了一些修改,但仍有改进的空间。我们还构建了一个 CI 工作流,将每个版本的代码输出与规范结果相匹配,并发布到 GitHub 页面

最后,我们要感谢竞赛组织者给了我们一个挑战性的任务。这绝对是一个需要解决的大问题。

链接:

  1. GitHub 库:用心松鼠的电报数据聚类竞赛解决方案
  2. 这篇俄语文章:новостнойагиегатораадвенедедели
  3. 另一篇关于数据聚类大赛的文章:从零开始构建新闻聚合器:新闻过滤、分类、按线索分组和排名

牛顿 vs 神经网络:人工智能如何腐蚀科学的基本价值观。

原文:https://towardsdatascience.com/newton-vs-neural-networks-how-ai-is-corroding-the-fundamental-values-of-science-368c93e01906?source=collection_archive---------31-----------------------

科学就是寻找解释。随着数据的丰富,我们已经不再要求解释,并满足于仅仅是相关性。我们很高兴知道某事会发生,但不知道它为什么会发生。这从根本上破坏了科学探究的精神,我们可能永远无法恢复。

在过去的四百年里,科学方法引导了科学的发展。该方法包括仔细记录观察结果,制定一个有意义的假设,并严格检验该假设。基于这些测试的结果,假设被一次又一次地改进,直到它能解释观察结果。科学家被告知相关性并不意味着因果关系。对他们来说,知道有事发生是不够的;他们需要了解导致这种情况发生的潜在机制。

人工智能(AI)是一种非常不同的野兽。大多数人工智能系统使用一种称为机器学习的技术,通过向计算机提供与任务相关的大型数据集,来教会计算机如何执行任务。构建这种数据驱动的人工智能系统的开发人员被称为数据科学家。与真正的科学家不同,数据科学家满足于相关性,而不关心因果关系。他们蔑视科学方法的原则,嘲笑其严谨性。他们公然忽略了理论的必要性,只对经验模型感兴趣,这些模型在不理解他们预测什么的情况下给出预测。

地球、太阳和月亮的运动是三体的经典例子(图片来自 Pixabay)

三体问题是物理学中一个被充分研究的问题,由艾萨克·牛顿爵士在他不朽的论文数学原理中首次描述。假设给你空间中的三个大物体——比如太阳、月亮和地球——以及它们的初始位置和速度,你能在固定的时间间隔后确定它们的最终位置吗?为了解决这个问题,你需要计算每个物体对另外两个物体的引力的影响。这听起来可能很简单,但这个问题已经困扰了物理学家几个世纪。没有人能够推导出提供最终解的方程。计算机模拟用于使用运动定律费力地计算每个物体在每个时间步的运动。这些计算是混沌的,即对微小的变化非常敏感。由于这种混乱的性质和涉及的大量计算,模拟需要几周或几个月的时间来运行,可能会被卡住,有时根本不可行。

2019 年 10 月,人工智能研究人员宣布他们开发了一种神经网络,可以在几秒钟内找到三体的精确解。这比今天最好的模拟快了惊人的 1 亿倍。神经网络是最受欢迎的机器学习算法,它们构成了大多数人工智能解决方案的核心。让他们无比强大的是他们成为通用近似者的能力。给定足够的训练数据,他们可以学习近似描述输入和输出之间关系的任何方程。在上述案例中,研究人员在 10,000 个三体构型的数据集上训练了他们的神经网络。神经网络处理了这个数据集,并学习了描述初始配置和最终配置之间关系的方程,而不知道任何运动规律

人工智能正在物理、化学、生物、金融、经济甚至社会科学领域迅速取得进展,它正在迅速取代传统的理论方法。1973 年,费希尔·布莱克、迈伦·斯克尔斯和罗伯特·默顿为股票期权定价开发了著名且极具影响力的布莱克-斯科尔斯公式,为此默顿和斯科尔斯获得了诺贝尔经济学奖。他们的方法受到了物理学家用来模拟流体中悬浮粒子运动的布朗运动的启发。在过去十年中,理论驱动的布莱克-斯科尔斯模型实际上已经被数据驱动的神经网络淘汰,这些神经网络学习仅从过去的价格预测未来的价格,而对金融市场一无所知。

在医疗保健领域,人工智能模型通常用于从医学图像中诊断结核病和各种癌症等疾病。再说一次,人工智能对放射学、医学或人体解剖学一无所知。

科学就是寻找解释。随着数据的丰富,我们已经不再要求解释,并满足于仅仅是相关性。我们很高兴知道某事会发生,但不知道它为什么会发生。这从根本上破坏了科学探究的精神,我们可能永远无法恢复。

科学思维是一种技能,我们作为一个社会,不是一夜之间发展起来的。我们花了几千年才发现它,然后又花了几个世纪才采纳并开始实践它。就像我们正在失去记忆、心算或在没有全球定位系统的情况下在街上导航的能力一样,我们还需要多久才能在这个快速增长的能力列表中加入科学思想呢?

如果你喜欢这篇文章,可以在 Medium 上查看我的其他作品,在LinkedInTwitter,查看我的 个人网页 ,或者发邮件给我viraj@berkeley.edu

牛顿方法:视觉直觉。

原文:https://towardsdatascience.com/newtons-method-the-visual-intuition-12a346f4d89?source=collection_archive---------30-----------------------

如果第一次你没有成功,试着再试一次。

牛顿和拉夫森

我们将在这个博客中讨论的方法也被称为牛顿-拉夫森方法。从名字上看,你可能会想象牛顿和拉夫森作为一个团队一起工作,像好朋友一样提出这个想法。但实际上,他们是独立发现的。这似乎是与牛顿共同的主题。还记得他是如何和莱布尼茨一起发现微积分的吗?为什么这个人在别人也有想法的时候有这么多想法?这实际上是很有可能的,因为,对于处于一个领域研究前沿的许多人来说,接下来的步骤通常不会太模糊。

和多个独立团队发现英特尔芯片的安全漏洞(Spectere 和 Meltdown)是一个道理。

不管怎样,历史已经足够了,让我们进入它是如何工作的。

x 是什么?

代数的本质(源自阿拉伯语,Al-Jabr——把零件拼在一起)是求解未知量的方程。例如,找到 x,其中:

2x + 5 = 7 __(1)

很容易看出上面方程的解是 x=1。另一种方法是将所有东西放在一起,称表达式为 y,我们得到:y = 2x 2。然后,我们可以试着找到 y=0 的 x。

但是当 y 用 x 来表示变得越来越复杂时会发生什么呢?我们能找到满足 y=0 的 x 的所有(或至少一个)值吗?例如,下面的图 1 显示了 y 与 x 之间的一些更复杂的关系。但是,在所有情况下,x=1 时满足 y=0(尽管可能不是唯一的)。

图 1:在 x=1 时都有零点的不同函数。

如果线性函数是最简单的,那么下一个可能是二次函数(涉及 x)。现在,如果我们有一个二次方程,我们将如何着手解决它?嗯,我们可以简单地使用二次公式(当只有一个变量 x 时)。但是让我们假设我们不知道这个公式。我们只知道如何求解像方程(1)这样的线性系统。我们可以用解一个线性方程的知识来解一个非线性(这里是二次)方程吗?

y=x __(2)

我们可以,但前提是我们要坚持不懈。让我们从任意一个点 x 开始,现在,计算我们的二次函数在这个 x 上的值,称之为 y,我们的工具是一个线性方程求解器,但我们有一个二次方程。所以,让我们把二次方程转换成一次方程。为此,只需用一个线性方程近似二次方程(使用泰勒级数)。当我们解这个线性方程时,我们会得到 x 的“答案”,但我们不能指望这个答案是“正确的”,因为我们“作弊了”——解了一个线性方程,而不是一个二次方程。既然疯狂的定义是做同样的事情却期待不同的结果,我们就不断重复这个过程。唯一的不同是,这一次我们使用线性方程的前一个解作为我们的起点。最终,这个过程将我们引向二次方程的解,如下图所示。

图 2:抛物线的牛顿拉夫森迭代使我们越来越接近抛物线与 x 轴相交的一个点。

加大尺寸

现在,你可能已经看到了和上面非常相似的东西。但是,这如何扩展到多维度呢?例如,代替一个变量 x,假设我们现在有两个变量 x 和 y。将等式(2)扩展到二维的最自然的方式是:

z=x +y __(3)

这是它的情节:

图 3:抛物面,一种多维的二次方程。这里,x 和 y 是尺寸,z 轴代表抛物面的功能形式。

像以前一样,我们想求解 z=0。这发生在上图中的绿色圆圈处,也就是我们的抛物面方程与 x-y 平面相交的地方。但绿圈是无穷多个点,而不是一个、两个或三个。这很自然,因为我们将变量的数量增加到两个,但保持方程的数量不变。为了得到有限个解,我们需要有和变量一样多的方程,也就是两个。

对于我们的第二个方程,有许多候选项可供选择。为了简单起见,让我们复制现有的等式,并稍微移动一下。就这样,我们现在有了两个方程。

图 3:我们想演示求解多个方程。为了简单起见,我们只需将抛物面的现有方程复制,形成第二个方程。

此外,第二个方程也与 x-y 平面相交于一个圆,这两个圆相交于两个不同的点,这两个点是方程组的解。这是下图中的两个黄色点。

图 4:两个抛物线代表我们的两个二次方程相交于两点。

现在,我们如何使用之前的方法得到这些解中的一个?

我们将从 x-y 平面上的任意点开始(下图 5 中的粉红色点)。这可以投影到绿色抛物面上的绿点(这是我们的第一个二次方程)和黄色抛物面上的黄点(我们的第二个二次方程)。然后我们可以在绿色和黄色点画出绿色和黄色抛物面的最佳线性近似。因为线性方程是平面,这给了我们绿色和黄色的平面。这些平面将在紫色线处相交,然后在某点与 x-y 平面相交。这一点是两个线性方程组的解(两个抛物线的近似)。

图 5: NR 次迭代——我们重复求解通过逼近两个二次方程得到的线性方程组。这使我们越来越接近原二次系统的一个真实解。

这一点当然不是二次方程组的解,因为我们“作弊”,用线性方程组近似。但是我们从这个新的点开始重复整个过程。而这样反复做,就把我们带到了两个二次方程的其中一个解(两个黄点)。

如果我们想要第二种解决方案呢?那么,我们从一个不同的随机起点开始,重复这个过程,直到找到一个我们以前没有见过的解。

注意:你会在最优化的背景下看到牛顿拉夫森,而在这里,我们把它描述为一种解方程的方法。但是当我们注意到最优化通常涉及到寻找梯度(导数的向量)并将其设置为零时,它就变成了求解方程组的问题。

看看这个博客的视频版本:

利用天气数据用 SARIMAX 预测纽约出租车需求

原文:https://towardsdatascience.com/newyork-taxi-demand-forecasting-with-sarimax-using-weather-data-d46c041f3f9c?source=collection_archive---------12-----------------------

如何使用 SARIMAX 统计模型预测纽约市未来的出租车需求?

卢克·斯塔克波尔Unsplash 上拍摄的照片

axi 需求预测对于打车(和电子打车)公司来说已经变得极其重要,这是了解他们需求和优化车队管理的一种方式。

在这篇文章中,我们将介绍一种预测纽约某一地区出租车载客数量的方法。我们将执行时空时间序列分析,然后对包括天气数据在内的聚合数据应用众所周知的统计方法 SARIMAX。

数据描述:

出租车数据:

我们将使用纽约出租车需求公共数据,这些数据可从以下网址获得:https://www1 . NYC . gov/site/TLC/about/TLC-trip-record-data . page

这里我们就用 2015 年 1 月到 2016 年 2 月的数据。

要从纽约数据集网站快速下载大量数据到你的 google drive 账户,你可以通过这个链接跟随我的教程。

天气数据:

对于天气数据,我们将使用来自视觉交叉提供者的数据:https://visualcrossing.com/weather-data

理论的味道:

时间序列预测是数据科学领域的研究热点之一。从统计方法到深度神经网络,已经测试了各种模型和方法。

当涉及到时间序列预测时,机器学习爱好者往往会直接跳到机器学习模型,避免使用统计方法,在许多情况下,统计方法在精度测量和所有预测范围内都表现出更好的性能,尤其是对于单变量时间序列,让我们首先了解一下如何对时间序列问题进行分类。Jason Brownlee 博士在他的书中介绍了一个框架来对时间序列问题进行分类,如下所示:

输入与输出:

输入:提供给模型的历史数据,以便进行单一预测。

输出:除了作为输入提供的数据之外,对未来时间步长的预测或预报。

内源与外源:

内生变量:受系统中其他变量影响的输入变量,也是输出变量所依赖的变量。

外生变量:不受系统中其他变量影响的输入变量,也是输出变量所依赖的变量

回归与分类:

预测一个数字量 vs 分类为两个或多个标签中的一个。

单变量与多变量:

一段时间内测量的一个或多个变量

单步与多步:

预测下一个时间步与预测多个未来时间步。

静态与动态:

拟合模型一次并用于进行预测 vs 在每次预测之前根据新获得的数据拟合模型

连续与不连续:

观测值一致与观测值不一致。

现在你对我们面临的时间序列问题有了一个概念,让我们介绍一下 SARIMAX 模型:

SARIMAX 有点解释:

SARIMA 代表(季节性自回归综合移动平均)ARIMA 模型的一种变体,该模型用于单变量时间序列预测,支持序列的季节性成分。它支持自回归和移动平均组件。它有三个超参数来指定序列的季节性成分的自回归(AR)、差分(I)和移动平均(MA ),以及季节性周期的附加参数。

x 代表包含外生变量。

萨里玛(P,D,Q)

p :趋势自回归顺序。

d :趋势差序。

q :趋势移动平均订单。

  • P :季节性自回归顺序。
  • D :季节性差异订单。
  • Q :季节性移动平均订单。
  • m :单个季节周期的时间步数。

理论到此为止,现在让我们进入代码吧!

数据预处理:

在任何机器学习项目中,数据清理/预处理都是非常重要的步骤,但这是一个很累的步骤,如果你对应用 SARIMAX 方法比对清理数据更感兴趣,你可以跳过这一部分,因为我将通过驱动器文件夹为你提供结构化和清理的数据,但理解数据是如何清理和结构化的很重要。

PS:在“已清理数据文件夹链接”部分找到指向已清理数据文件夹的链接

data_Jan_2015 = dd.read_csv("/content/drive/My Drive/nyc-data/yellow_tripdata_2015-01.csv")data_Jan_2015.head()

我们在 dask dataframe 上导入 2015 年第一个月的数据,该数据包含许多特征,但我将仅展示我们清理数据所需的特征:

tpep_pickup_datetime: 提货的日期和时间

tpep_dropoff_datetime: 下车的日期和时间

皮卡 _ 经度:皮卡的经度

皮卡 _ 纬度:皮卡的纬度

落客 _ 经度:落客的经度

落客 _ 纬度:落客的纬度

行程 _ 距离:行程距离

首先,我们只选择需要的列,计算 trip_duration 和 speed,以便在数据清理过程中使用它。

准备好数据框后,我们将通过分析每列的四分位图来移除错误值:

行程距离四分位数:

出行距离四分位数

在打印四分位数和百分位数后,我们观察到第 99.9 个百分位数的出行距离为 22.58 英里,然而,第 100 个百分位数的值为 15420004.9 英里,这非常高。因此,我们将删除行程距离大于 23 英里的所有数据点。

在其他量化变量上做同样的过程(ِCheck 的 GitHub 回购代码)

速度四分位数:

速度四分位数

总票价:

总票价

取货/卸货清洁:

纽约的皮卡

通过可视化纽约外的一些接送,一些在海洋中,这些将从数据中删除。

使用 KMeans 对需求进行聚类:

在清除了纽约的需求之后,我们继续使用 Kmeans 算法对皮卡的需求进行聚类。我们把它分成 30 组。

#Clustering pickupscoord = new_data_Jan_2015[["pickup_latitude", "pickup_longitude"]].valuesregions = MiniBatchKMeans(n_clusters = 30, batch_size = 10000).fit(coord)cluster_column = regions.predict(new_data_Jan_2015[["pickup_latitude", "pickup_longitude"]])new_data_Jan_2015["pickup_cluster"] = cluster_column

接下来,我们将按地区对需求进行分组。

#Grouping the mounthly data by regionnew_data_Jan_2015.rename(columns={'tpep_pickup_datetime':'time','trip_distance':'demand',},inplace=True)new_data_Jan_2015['time'] = pd.to_datetime(new_data_Jan_2015['time'])grouped_new_data_Jan_2015 = new_data_Jan_2015[["pickup_cluster", "time", "demand"]].groupby(by = ["pickup_cluster", "time"]).count()

让我们想象一下这些区域:

最后,我们通过添加天气成分并以 1 小时为时间步长对需求进行重新采样来准备每个聚类的需求。

#Cluster example
cluster = grouped_new_data_Jan_2015.loc[0]
#Resampling Data in region j into one hour step
cluster = cluster.resample('1h').sum()
#Feature Engineering
cluster['Date time'] = cluster.index
cluster['Date time'] = pd.to_datetime(cluster['Date time'].dt.strftime('%Y-%m-%d %H'))
cluster['hour']=cluster['Date time'].dt.hour
cluster['day']=cluster['Date time'].dt.day
cluster['dayofweek']=cluster['Date time'].dt.dayofweek
#Merging with weather data
df_merge_col = pd.merge(cluster, weather_data, on='Date time')
cluster['temperature'] = df_merge_col.Temperature.values
cluster['wind_speed'] = df_merge_col['Wind Speed'].values
cluster = cluster[['hour','day','dayofweek','temperature','wind_speed',
'demand']]

群集(区域)将如下所示:

集群中的需求

这代表了一个地区的需求时间序列,我们将把它输入到我们的模型中以预测未来的需求。

每个区域将保存在一个单独的文件中。

我们将采取同样的步骤来准备其他月份的数据(预处理、清理、聚类、添加天气特征、将每个地区的需求保存在相应的文件中)

导入清理的数据:

我正在通过这个驱动器文件夹提供清理后的数据,

在这里,您可以找到所有按区域清理和聚类的 NewYork 数据,我们将使用这些文件来训练和测试我们的模型。

现在我们将开始研究预测问题,我们提醒你这是一个时间序列预测问题,我们需要测试时间序列的平稳性以便能够应用 SARIMAX 模型。

季节性/趋势分解(一月一月)

从分解图中,我们可以发现一天(24 小时)的季节性

平稳性检验

#Stationarity test
import statsmodels.tsa.stattools as sts
dftest = sts.adfuller(train.iloc[:,:].demand)
print('ADF Statistic: %f' % dftest[0])
print('p-value: %f' % dftest[1])
print('Critical Values:')
for key, value in dftest[4].items():
  print('\t%s: %.3f' % (key, value))

平稳性测试结果

增强迪基-富勒测验:

零假设(H0):这表明时间序列有一个单位根,这意味着它是非平稳的。它有一些依赖于时间的结构。

替代假设(H1):它表明时间序列没有单位根,这意味着它是平稳的。它没有依赖于时间的结构。

p 值> 0.05:接受零假设(H0),数据有单位根,非平稳。

p 值<= 0.05: Reject the null hypothesis (H0), the data does not have a unit root and is stationary.

Here we have the p-value <= 0.05 which means that the data is stationarity.

Reading cleaned data:

Now we confirmed that our process is stationary, we will read each regions demands and split the available data between train and test sets. We have data from January 2015 to February 2016.

Train / Test split:

列车数据:2015 年 1 月至 2015 年 12 月

测试数据:【2016 年 1 月和 2 月

split_date = pd.Timestamp('2016-01-01')
train = cluster_cleaned.loc[:split_date]
test =  cluster_cleaned.loc[split_date:]

测试数据时间序列

可视化测试集,我们可以观察到 1 月 24 日左右数据的奇怪行为。这几点会影响模型的结果,所以我们会考虑到这一点。快速谷歌研究我们可以发现,这种行为是由于 2016 年 1 月 24 日那一周发生在美国和纽约市的怪异事件,特别是封闭道路影响了出租车需求。

来源:https://www . NBC NewYork . com/news/local/NYC-new York-city-blizzard-biggest-ever-23-2016 年 1 月/831660/

使用 SARIMAX

现在我们的数据已经准备好,让我们开始吧,SARIMAX 有订单和季节性订单超参数需要调整,首先将对每个地区需求数据应用超参数调整,以使用 get_sarima_params 函数找到最佳模型设置:

接下来,我们使用此函数应用 sarimax 模型,请注意,在 get_sarima_params 中,我们在季节顺序 24 中指定了季节性,因为我们在时间序列中检测到了 24 小时的季节性。

不要忘记忽略 2016 年 1 月 23 日至 26 日之间的测试数据,因为纽约市的暴风雪导致了需求的错误行为。

让我们在第一个集群上测试该模型,并使用 MAE 和 RMSE 指标评估结果。

群集 1 上的梅& RMSE 训练和测试错误

可视化预测

现在我们将使用 Plotly 库来可视化测试集上的预测结果:

测试集上的预测可视化

我们可以看到,SARIMAX 模型在检测时间序列的季节性方面表现良好,而在检测变化(趋势)值方面表现不佳,这可以解释为某些问题中的异常检测。

我们还可以看到 1 月 23 日至 26 日期间,模型无法检测到奇怪的行为。

清理的数据文件链接:

在这个 drive 文件夹 中找到,纽约出租车需求数据被清理并整理成 30 个簇,你可以将这个文件夹复制到你的 drive 中,导入到你的笔记本中,直接应用。黑客快乐!

笔记本代码:

[## k4der 2r g/new York-Taxi-需求预测-带 SARIMAX

此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…

github.com](https://github.com/k4der2rg/NewYork-Taxi-demand-prediction-with-SARIMAX)

结论:

我希望这个教程对你有用。你从打车和电子呼叫公司需要预测未来需求的动机开始。接下来是时间序列预测和 SARIMAX 模型背后的理论。然后你开始下载、探索和清理需求数据。这使我们能够更好地理解时空预测问题的行为和结构,并检验时间序列的季节性和平稳性。最后,我们实现了在纽约数据上应用 SARIMAX 模型的方法。

需要改进的领域:

要改善 SARIMAX 模型在数据上的结果,您可以尝试多种方法,例如:

  • 将数据重新排列成更小的时间步长(比如 10 分钟),以便模型更好地检测波动。
  • 根据更多值调整 SARIMAX 模型。
  • 将需求聚集到更多的区域。

参考

  • Python 时间序列预测简介 Jason Brownlee 博士
  • 关于数据清理的一些步骤,我参考了这个 repo

新一代企业数据科学家

原文:https://towardsdatascience.com/next-gen-enterprise-data-scientists-d9ef729d80b9?source=collection_archive---------47-----------------------

EY 和 IBM 是如何改变现状的

自 2016 年以来,我们都听说过由 Gartner 使“公民数据科学家”成为主流的术语。如果你没有,那么你可能处在一个不断缩小的行业圈子里,这个圈子还没有被数字颠覆所颠覆。

公民数据科学家是能够使用或生成模型的人,这些模型利用了高级诊断分析或预测和规定功能。他们经常使用自动化工具,如 Alteryx 或 Power BI,通常可以生成比一般数据分析师稍微复杂一些的见解。

公民数据科学家是一种组织的数字化方式,通过提高现有员工的技能来挖掘通常可以在组织中找到的未使用的数据。安永(EY)通过向员工提供在 Udemy 上免费学习大量技术课程的机会来做到这一点。

但这就够了吗?公民数据科学家能否发掘组织内部潜在的洞察力宝库,同时必须能够在日常运营和实践之间周旋,同时努力更加以数据为中心?

进入企业数据科学家。

W 什么是企业数据科学家?

公民数据科学家和企业数据科学家的主要区别在于工作重点和范围。企业数据科学家通常来自组织或行业背景,已经完全转变为数据科学家的角色。他们曾经面向行业或客户的角色已经不复存在,使他们能够主要专注于数据科学和数据工程研究和任务。

企业数据科学家是一个成熟的数据科学家,但来自一个有着不同视角的组织或行业背景。

面对现实吧,一个数据科学家的工作并不容易。大量的时间花在研究和理解数据的本质上,然后测试和开发初始模型,然后进一步完善和重新完善。这还不是全部,还必须仔细实施该方法,记录流程和结果。

这样做了一遍又一遍。

毕竟,科学的脊梁是建立在细致的文献记录和复制结果的能力之上的。我们对昙花一现的奇迹不感兴趣。

这不是公民数据科学家拥有的奢侈品。他们的底线仍然是交付产品或服务,技术只是一个使能器。会有捷径和半生不熟的努力,但它肯定比没有任何技术支持的传统方式要好。

然而,企业数据科学家通过内部定位来填补这一空白,例如在组织的 R&D 或创新部门。在那里,他们可以与公民数据科学家合作,将他们最初的想法或原型开发成成熟的应用程序甚至软件。

我本人是作为一名企业数据科学家写这篇文章的。我之前是一个面向客户的角色,后来在内部转向专注于研究和开发供内部和商业使用的数据软件和平台。

不断增长的联盟

组织和企业不断增长的数据需求并没有被忽视。一些组织已经开始采取战略步骤,进一步加快工作的数字化。就在最近,EY 和 IBM 宣布了一项全球多年联盟,这无疑将使双方咨询业务的客户受益。

除了商业附加值,这种性质的合作为研究和开发提供了难得的机会,从长远来看,这可能会推动更大比例的价值。

EY 是一家跨国企业集团,业务遍及全球所有行业;而 IBM Watson Group 专注于商业和企业人工智能和自然语言。

Watson 拥有自己的服务套件,可以轻松实现日常数据科学活动。值得注意的是 IBM Cloud Pak for Data 采用完全集成的数据平台,允许存储资产、管理笔记本电脑和提供人工智能服务。最重要的是,这提供了一个环境,企业数据科学家可以直接与 IBM 的数据专家合作构建模型、应用程序和产品。

随着商业数据和智能的结合,我们可能会看到下一代智能“人工顾问”在行业中取得突破。这是成为企业数据科学家的大好时机!

角色和职能

连接点

在过去的几年里,作为 EY 公司的企业数据科学家,我与 IBM 密切合作。两个组织有两种传统上不同的商业模式,你可以想象在工作方式上会有很大的差异。

然而,我在这里要分享的是,这种体验在某种程度上是无缝的,因为每个团队的角色都是为联合交付技术产品而设置的。下图是我们在此类产品开发过程中典型的数据科学团队结构。

合作技术开发环境中各种角色的说明

行业本地的企业数据科学家(内部数据专家)应该与技术本地公司的外部数据科学同行保持第一接触点。能够执行简单数据处理和分析的数据分析师或公民数据科学家可以进一步帮助他们。与完全专注的企业数据科学家不同,公民数据科学家通常轮流担任角色,并提供从其特定领域获得的特定见解。

鉴于企业数据科学家对领域知识的理解和对数据架构的熟悉,他们负责为组织设计整体数据策略。这是传达给外部技术-本地数据科学家,建筑师和工程师,他们可以处理开发的纯技术方面。

结合工业和技术专业知识

因为企业数据科学家专注于行业/领域,所以他们通常对其领域中的数据如何表达以及在建模中使用它们的细微差别有最完整的理解。

作为一名在医疗保健领域拥有 10 年经验的从业者,并不意味着你是医疗保健数据方面的专家。相反的情况通常是正确的,有经验的领域从业者可能基于他们的经验怀有偏见,并且不能客观地查看数据。

另一方面,非特定领域的数据科学家具备处理数据的统计专业知识和技能。然而,需要大量的时间将他们的专业知识调整到他们没有经验的新的复杂领域。

通过拥有内部的企业数据科学家,组织可以节省宝贵的时间和资源来弥合这一巨大差距。

可解释性的层次

最后,产业本地组织和技术本地组织之间的成功合作取决于达到的沟通水平。

任何经历过数字重组的组织都明白,技术素养是一个现实问题。

除非你从事技术工作,否则你不太可能理解数据处理。同样,技术原住民也很难理解需要几十年经验才能掌握的领域。

回到弥合差距的功能,企业数据科学家充当沟通者,或者作为可解释性的附加层。对产业本地人和技术本地人都有利。

从行业的角度来看,他们可以以对业务有意义的方式捕获和解释数据,从而推动更容易的采用。从技术的角度来看,他们理解架构和工程的局限性,并且能够将令人痛苦的不合理的要求保持在最低限度。

为了证明对企业数据科学家的需求,请考虑以下示例:

在会计领域,我们有外部审计师和内部会计师。组织永远不会雇佣一个对会计有所了解的人来担任内部职务;他们将雇用一名真正的会计师。

同样,在技术和数据占据中心舞台的未来,组织需要具备内部数据科学能力。

组织需要有自己的企业数据科学家

感谢阅读!

如果你觉得这篇文章有用就分享吧!如果你想看我以上任何一个实验的更多故事,请告诉我。

使用 PySpark 进行新一代测序数据分析

原文:https://towardsdatascience.com/next-generation-sequencing-data-analysis-with-pyspark-888a1e0a079?source=collection_archive---------14-----------------------

了解如何使用 PySpark 在 Google Colab 中分析基因组数据

信用:pix abay/monar

有了 DNA,你必须能够分辨哪些基因是打开的,哪些是关闭的。目前的 DNA 测序无法做到这一点。下一代 DNA 测序需要能够做到这一点。如果有人发明了这个,那么我们就可以开始非常精确地确定疾病的治疗方法。——埃隆·马斯克

单细胞 RNA 测序(scRNA-seq)等下一代测序技术的快速发展要求对大数据进行高效的并行处理和分析。Hadoop 和 Spark 是存储和处理海量数据集的首选开源框架。Spark 最显著的优势是其迭代分析能力与内存计算架构相结合。打电话。弹性分布式数据集(RDD)上的 cache()有效地将其保存在内存中,并使其立即可用于计算;因此,后续的过滤、映射和归约任务变得即时。Spark 有自己的查询语言 Spark SQL,它的 MLlib 库非常适合机器学习任务。

scRNA-seq 可以做马斯克指出的事情——以细胞分辨率计算出哪些基因被打开/关闭。但这不是灵丹妙药——因为基因表达的调控并不停留在转录水平。mRNA 或信使 RNA——基因蛋白质编码区的代表——也包含决定核糖体蛋白质合成水平的序列。表达的蛋白质也可以经历一系列激活或抑制它的翻译后修饰。

设置笔记本

这些年来,我一直喜欢用 Google Colab 做我所有快速而肮脏的项目原型。使用 Colab,您可以跳过启动项目所需的所有初始步骤。无需设置虚拟环境、依赖关系等。此外,Colab 还配有免费的 GPU/TPU,可满足您所有的机器学习需求。

首先,去 Colab,按照上面的链接,启动一个新的 Python 3 笔记本。PySpark 需要 Java (Java 1.8)和 Scala,所以我们接下来会安装它们。

现在安装 PySpark。这里我们将安装 pyspark[sql],因为它将允许我们处理。gtf,。床,。砰然后。萨姆稍后归档。

!pip install pyspark[sql]

从 NCBI 序列读取档案(SRA)下载数据

已发表研究的序列数据可从 SRA 下载。在使用 sra 文件之前,您需要解压缩。使用 SRA 工具包中的 fastq-dump 工具。除了 SRA 文件,你可以直接下载。fastq、. fa.gz 或. fastq.gz 格式;现在可以用 PySpark 读取这些文件。

注意文件的大小。

PySpark 的魔力

PySpark 的核心是弹性分布式数据集(RDD);它代表了可以并行操作的不可变的数据分区集合。

信用:【https://cwiki.apache.org/】T4

首先初始化一个 spark 上下文。

import pyspark as spark
from pyspark import SparkConfsc = spark.SparkContext.getOrCreate(conf=set_conf())

为您的工作流传递一个最佳配置也是一个很好的实践。

数据分析

现在是时候读取我们的数据并将其转换到 RDD 了。

data = sc.textFile(path/to/fastq)
# in case you have a list of sequences
data = sc.parallelize(your_list)# lets take a look at the first read
# each read in fastq is represented by 4lines 
data.take(4)

让我们只从数据中提取序列。

sequences = data.filter(lambda x: x.isalpha())
sequences.count() # outputs the size of RDD - the number of reads
# => 1843156

看一下前四段。

sequences.take(4)

找出读数的长度怎么样?这只需要一行代码!

read_lengths = sequences.map(lambda seq: len(seq))
read_lengths.take(10)

接下来,计算读取的平均长度。

len_sum = read_lengths.reduce(lambda a, b: a+b)
len_sum//read_lengths.count()
# => 564

最后,我们来算一下基数。首先,我们将使用 list() 将序列分成单独的碱基,然后使用 flatMap 将列表合并成一个。然后,我们遍历各自的基并创建一个元组,将第一个元素作为基,将“1”作为其值。然后我们使用 reduceByKey 通过元组的第一个元素——key——来聚合值。

base_count = sequences.flatMap(lambda seq: list(seq))\
                       .map(lambda c: (c, 1)) \
                       .reduceByKey(lambda a, b: a+b)
base_count

我们这里只关心 A,T,G,C;剩下的都是神器。如你所见,这些序列富含 GC。

我在这里只触及了皮毛,您可以使用 PySpark 做许多很酷的事情。我会带着另一篇文章回来。

你可以在 这个 colab 笔记本 里找到代码示例。

我希望我已经介绍了足够的基础知识,可以帮助您开始学习。下次再聊。

下一级数据可视化

原文:https://towardsdatascience.com/next-level-data-visualization-f00cb31f466e?source=collection_archive---------28-----------------------

完整的 Plotly 手册

制作能激发灵感的图表/第 1 部分:制作定制图表

在古印度文献中,对哲学概念的解释通常以否定这个概念是关于什么而不是关于什么开始。利用一个反复出现的短语 neti neti (意思是既不是这个也不是那个),这个想法是,告诉什么东西不是,至少和解释那个概念/想法的实际意义一样重要。跟随这些古代哲学家的脚步,让我首先列举出本文不涉及的内容:

  • 这篇文章不是关于如何在 plotly 中快速制作图表,通常只有一行代码,就像 plotly express 一样。如果这是你感兴趣的,请跟随威尔·科尔森的这篇惊人的媒体文章
  • 本文也不是要列出所有可用于数据可视化的不同图表类型。如果这是你正在寻找的,看看这篇非常翔实的文章萨曼莎·李乐。事实上,本文只讨论了两种不同的图表类型:折线图和散点图。

介绍

任何数据分析项目都有两个基本目标。首先,以易于理解的形式整理数据,揭示隐藏的模式,并确定关键趋势。第二,也许更重要的是,通过深思熟虑的数据可视化将这些发现有效地传达给读者。这是一篇介绍性文章,讲述了如何开始考虑定制可视化,以方便地将关键数据特性传播给查看者。我们通过超越使 plotly 在数据分析师中如此受欢迎的单线图,并专注于个性化的图表布局和美学来实现这一目标。

本文中使用的所有代码都可以在 Github 上获得。这里展示的所有图表都是交互式的,并且是使用 jovian 渲染的,这是一个用于共享和管理 jupyter 笔记本的不可思议的工具。Usha Rengaraju 的这篇文章包含了如何使用这个工具的所有细节。

来源

Plotly

Plotly 是数据可视化的自然选择库,因为它易于使用,文档记录良好,并允许定制图表。在接下来的章节中,我们先简要总结一下 plotly 架构,然后再进行可视化。

虽然大多数人更喜欢使用高级的plotly.express模块,但在本文中,我们将关注使用plotly.graph_objects.Figure类来呈现图表。虽然 plotly 网站上有大量的文档,但这些材料对于那些不熟悉可视化的人来说可能有点难以接受。因此,我努力提供一个清晰和简洁的语法解释。

我们将使用的 plotly graph_objects由以下三个高级属性组成,绘制一个图表主要涉及指定这些属性:

  • data属性包括从超过 40 种不同类型的轨迹中选择图表类型,如[scatter](https://plotly.com/python/line-and-scatter/)[bar](https://plotly.com/python/bar-charts/)[pie](https://plotly.com/python/pie-charts/)[surface](https://plotly.com/python/3d-surface-plots/)[choropleth](https://plotly.com/python/choropleth-maps/)等,并将数据传递给这些函数。
  • layout属性控制图表的所有非数据相关方面,如文本字体、背景颜色、轴&标记、边距、标题、图例等。在处理大型数据集时,我们将花费相当多的时间操纵这个属性来进行更改,如添加一个额外的 y 轴或在一个图形中绘制多个图表。
  • frames用于指定制作动画图表时帧的顺序。本系列的后续文章将广泛利用这一属性。

对于本文中制作的大多数图表,下面三个是我们将使用的标准库:

对于 python 的新手,可以看看我之前的一篇关于使用 pandas 进行数据争论的文章。其中一些工具将用于提取和转换可视化数据。

[## 使用熊猫进行数据争论的备忘单

将原始数据转换成函数形式

towardsdatascience.com](/data-wrangling-in-pandas-a-downloadable-cheatsheet-84326d255a7b)

本文的其余部分分为以下几个部分:

  1. 折线图
  • 基本折线图
  • 定制的折线图
  • 何时不使用折线图

2。散点图

  • 基本散点图
  • 带有下拉菜单的图表
  • 散点图矩阵

折线图

基本折线图

还有什么比折线图更常规的呢?当考虑数据可视化时,这是首先想到的事情之一。我们首先利用 gapminder 数据集来呈现一个包含许多数据点的折线图。对于那些不熟悉这种数据可视化经典的人,请查看他们的网站这种基于 gapminder 数据的动画,它在不到 5 分钟的时间内捕捉了近 200 年的世界历史。

首先,我们使用一行plotly.express代码制作折线图,其中绘图主要涉及指定xy变量,绘图title和用于color编码数据的变量。

现在让我们使用 plotly graph_objects制作同样的图表。

我们首先使用fig1 = go.Figure()初始化一个空的 go figure 对象。然后,我们通过使用来自plotly.graph_objectsgo.Scatter类为每个国家添加一个轨迹fig1.add_trace来绘制一个折线图。这个类可以通过改变mode参数来制作折线图和散点图,该参数可以采用由+连接的"lines""markers"、&、"text"的任意组合。add_trace用于向go.Figure()对象提供数据参数。此外,我们还可以为后续图表提供布局参数框架参数,我们将在后续文章中介绍。

这是基本的折线图。我们使用只有一行代码的plotly.express和使用基本上做同样事情的graph_objects的稍长代码来绘制它。

这张图表看起来不可怕吗?只有我有这种感觉吗?到处看到这样的图表,你不烦吗?

我们使用 plotly graph_objects类制作这个图表的原因是,在决定定制图表的数据布局 ( & 框架)属性时,它提供了很大的灵活性。

定制的折线图

就数据可视化美学而言,我一直很欣赏 Nathan Yau 在流动数据中的作品。例如,检查这张图表,然后将其与我们刚刚制作的图表进行比较。从默认设置的世界走向这种定制的图表是我在这篇文章和本系列后续文章中的最终目标。

让我们开始定制那个可怕的图表。

配色方案。所有数据要么是离散的,要么是连续的。离散数据集是指各个数据点相互独立的数据集。在我们刚刚可视化的 GDP 数据集中,每个国家的 GDP 独立于其他国家的 GDP,因此我们必须使用来自px.colors.qualitative模块的颜色来可视化它。查看 plotly 文档以获得该模块中所有可用颜色集的完整列表。这种颜色集中的所有颜色具有不同的色调但是具有相似的饱和度和值

连续数据集的值在一个范围内变化,就像这张失业率图一样。我们使用顺序配色方案来可视化这种数据,其中数据的大小映射到颜色的强度。本系列的后续文章将更多地关注颜色以及如何有效地将颜色用于数据可视化。

回到定制我们的折线图。我们使用cycle工具通过palette = cycle(px.colors.qualitative.Pastel)交互**Pastel**调色板中的不同颜色。每次我们绘制数据点时,我们使用marker_color=next(palette).选择其中一种颜色

轴。让我们开始格式化轴,去掉矩形网格,在长度为 10 的轴外添加记号(showgrid=False, ticks="outside", tickson="boundaries", ticklen=10)。我们也去掉了 y 轴,有了粗黑的 x 轴(showline=True, linewidth=2.5, linecolor='black')。所有这些参数都被传递给update_xaxesupdate_yaxes.

布局。最后,我们指定几个参数来定义图表的整体布局,即:

将所有这些放在一起,这就是我们得到的结果:

这张图表可能与 Nathan Yau 的一些作品不一样,但它仍然比默认的 plotly 图表好得多。这个图表代码也代表了我们将在本文中绘制的所有其他图表的基本框架。上图中的几个关键变量可以很容易地改变,以改变剧情的整体美感。这些包括绘图和纸张背景颜色(plot_bgcolor='#ffffff' & paper_bgcolor = '#ffffff'))、渲染数据的颜色集(px.colors.qualitative.Pastel)和轴布局(update_xaxes & update_yaxes))。一定要花时间玩这些。

何时不使用折线图

现在让我们制作一个类似于上图的图表,但是是针对不同的数据集。

随着变量数量的增加,折线图变得难以解释,因为不同变量对应的颜色可能难以区分,或者至少需要一些努力。一种选择是使用堆积面积图。只需将stackgroup=’one’添加到上面代码中的 add_trace 函数中,就可以获得相同数据集的堆积面积图。

为了比较不同的数据点,面积图优于线图。在上面的图表中,我们不仅可以看到一个国家排放了多少二氧化碳,还可以比较它与其他国家的表现。中国排放的二氧化碳略多于美国和 EU-28 国的总和,这是我们可以从堆积面积图中立即得出的结论,而同样的结论很难从简单的线图中得到解释。

散点图

基本散点图

虽然折线图呈现了一个变量随时间变化的过程,但散点图也可用于绘制两个或多个相关或不相关变量之间的变化。我们从绘制一个公开可用的数据集开始,该数据集包含两个指数( GCAGGISTEMP ),测量自 1880 年以来的平均地表温度变化。这次我们使用plotly.graph_objectsgo.Scatter类和mode='markers' 。代码的整体主干与以前基本相同。

现在让我们添加另一个变量,在(大致)相同的持续时间内的平均海平面数据。结果是,当两个温度指数从-0.5 到 1.5 变化时,海平面从 0 到 10 变化。如果我们在同一条轴上绘制这两条曲线,温度曲线基本上会变平。所以我们用fig = make_subplots(specs=[[{"secondary_y": True}]])初始化一个有两个不同 y 轴的图形。现在,当使用fig.add_trace将每个轨迹添加到该图时,我们必须通过提供一个额外的参数secondary_y.来指定绘制它的 y 轴

带有下拉菜单的图表

如果我们想在同一张图表上绘制更多的变量呢?我们可以利用下拉菜单来选择单个变量,一次显示一个。为此,我们需要做到以下几点:

  1. layout添加一个新的参数,它包括所有要添加的按钮的列表buttons= list_updatemenus和这个下拉菜单的位置x=1.2,y=0.8updatemenus=list([dict(buttons= list_updatemenus, x=1.2,y=0.8)])
  2. 使用list_updatemenus. 指定下拉菜单的选项列表,包括:
  • label:出现在下拉菜单中的变量名称
  • method:决定当从下拉菜单中选择特定选项时如何修改图表。它可以是下列之一:restyle(修改数据)、relayout(修改布局)、update(修改两个数据的&布局)和animate(开始或结束动画)。
  • args:这包括(1) visible一个列表,指定哪个数据集将以布尔列表的形式绘制。该列表的大小与添加到该图中的迹线数量相同。'visible': [True, False]表示将显示两个go.Scatter图中的第一个。(2) 'title'绘制变量时显示在顶部的标题。

将所有这些放在一起,我们得到以下结果:

尝试使用下拉菜单选择单个变量。

散布矩阵

使用下拉菜单可能并不总是一个好的选择,因为我们经常希望同时可视化几个变量,以揭示它们之间可能的关系。我们可以使用散点图来做到这一点,散点图是探索性数据分析的一部分。

我们将使用的天气数据集记录了几个变量,如最高和最低温度、风向和风速、阳光量和相对湿度。对于每个数据点,我们也知道结果,即是否下雨以及降雨量。现在的目标是可视化所有这些变量是如何影响降雨结果和降雨量的。我们首先给结果变量分配标签(0 表示无雨,1 表示下雨)。然后,我们使用go.Splom模块在矩阵上绘制所有这些变量。同样,基本的代码主干保持不变。

注意,我们没有指定调色板,而是使用了 colorscale 来代替colorscale='temps'。查看 plotly 文档获得所有可用的colorscales.列表showupperhalf参数设置为 true 时将产生一个完整的矩阵,其中每个变量都绘制两次,一次在对角线下方,一次在对角线上方。

结论

在本文中,我们讨论了如何绘制基本的折线图,以及何时用面积图替换它。然后,我们讨论了如何绘制散点图以及何时用散点图替换散点图。在此过程中,我们讨论了如何定制 plotly graph_objects 来生成符合我们要求的图表。我们通过对基本的代码主干做一些小的改动来实现这种定制。

本系列的后续文章将重点讨论绘制地图,深入使用颜色和动画来实现高级数据可视化。感谢阅读。请分享您的反馈。

基于自然语言处理和深度学习的下一个单词预测

原文:https://towardsdatascience.com/next-word-prediction-with-nlp-and-deep-learning-48b9fe0a17bf?source=collection_archive---------1-----------------------

虚拟助理项目

使用 LSTM 设计单词预测系统

来源:照片由阿玛多·洛雷罗在 unsplash 上拍摄

如果你的设备能够预测你打算输入的下一个单词是什么,这不是很酷吗?这类似于预测文本键盘在 What's App、Facebook Messenger、Instagram、电子邮件甚至谷歌搜索等应用上的工作方式。下面是一张理解这些预测性搜索的图片。

作者截图

当我们输入天气如何时,我们已经收到了一些预测。我们可以看到某些接下来的单词是天气预报。对特定用户发短信或打字的下一个单词的预测可能非常棒。通过了解用户的短信模式,可以节省大量时间。这也可以被我们的虚拟助手用来完成某些句子。总的来说,预测搜索系统和下一个单词预测是一个非常有趣的概念,我们将实施。

注: 这是虚拟助手系列的 part-2。同一主题将有更多即将到来的部分,我们将介绍如何使用深度学习技术和 python 构建自己的虚拟助手。

来源:乔恩·泰森在 unsplash 上拍摄的照片

简介:

本节将介绍构建的下一个单词预测模型将确切执行什么。该模型将考虑特定句子的最后一个单词,并预测下一个可能的单词。我们将使用自然语言处理、语言建模和深度学习的方法。我们将从分析数据开始,然后对数据进行预处理。然后,我们将对这些数据进行符号化,最终建立深度学习模型。深度学习模型将使用 LSTM 的来构建。完整的代码将在文章的最后提供,并带有一个到 GitHub 库的链接。

方法:

文本数据的数据集很容易找到,我们可以考虑古登堡计划,这是一项数字化和存档文化作品的志愿者工作,旨在“鼓励电子书的创作和发行”。从这里我们可以得到许多故事、文档和文本数据,这些都是我们问题陈述所必需的。数据集链接可以从这里获得。我们将使用弗朗兹·卡夫卡的《变形记》一书中的文本。你可以从这里下载数据集。然而,如果你有时间收集自己的电子邮件和短信数据,那么我强烈建议你这样做。这将对你的虚拟助理项目非常有帮助,在这个项目中,预测关键词将做出类似于你的短信风格或类似于你撰写电子邮件的风格的预测。

来源:布雷特·乔丹在 unsplash 上拍摄的照片

预处理数据集:

第一步是从变形数据集中移除所有不必要的数据。我们将删除数据集的起点和终点。这是与我们无关的数据。起始行应该如下所示:

一天早上,当格雷戈尔·萨姆萨从烦恼的梦中醒来时,他发现

数据集的结束行应该是:

第一个站起来伸展她年轻的身体。

这一步完成后,将文件保存为变态 _ 干净. txt。我们将通过使用 utf-8 编码来访问变态 _ 干净. txt。我们清理过程的下一步包括替换所有不必要的额外新行、回车和 Unicode 字符。最后,我们将确保我们只有独特的话。我们将每个单词只考虑一次,并删除任何额外的重复。这将有助于模型训练更好地避免由于单词重复而造成的额外混淆。下面是文本数据预处理的完整代码。

标记化: 标记化是指将较大的文本数据、短文或语料库分割成较小的片段。这些较小的片段可以是较小的文档或文本数据行的形式。它们也可以是一本单词词典。

Keras 标记器允许我们对文本语料库进行矢量化,方法是将每个文本转换为整数序列(每个整数是字典中标记的索引)或向量,其中每个标记的系数可以是二进制的,基于单词计数,基于 tf-idf。要了解更多关于使用 Keras 的 Tokenizer 类和文本数据预处理的信息,请访问此处

然后我们将文本转换成序列。这是一种将文本数据解释为数字的方式,以便我们可以对它们进行更好的分析。然后,我们将创建训练数据集。“X”将包含输入文本数据的训练数据。“y”将包含训练数据的输出。因此,“y”包含每个输入“X”的所有下一个单词预测。

我们将通过使用从 tokenizer.word_index 中提取的长度来计算 vocab_size,然后给它加 1。我们添加 1 是因为 0 是为填充保留的,我们想从 1 开始计数。最后,我们将把我们的预测数据“y”转换成 vocab 大小的分类数据。这个函数将一个类向量(整数)转换成二进制类矩阵。这将有助于我们的损失,这将是分类 _ 交叉熵。用于数据标记化、创建数据集以及将预测集转换为分类数据的其余代码如下:

注:可在预处理中进行改进。您可以尝试不同的方法来改进预处理步骤,这将有助于在更少的时期内实现更好的损失和准确性。

来源:照片由 Clement H 在 unsplash 上拍摄

创建模型:

我们将建立一个连续模型。然后我们将创建一个嵌入层,并指定输入维度和输出维度。将输入长度指定为 1 是很重要的,因为预测将只针对一个单词进行,我们将收到该特定单词的响应。然后,我们将添加一个 LSTM 层到我们的架构。我们会给它一个 1000 单位,并确保我们返回的序列为真。这是为了确保我们可以通过另一个 LSTM 层。对于下一个 LSTM 层,我们也将通过另一个 1000 单位,但我们不需要指定返回序列,因为它默认为假。我们将使用 relu 设置为激活的密集层函数,通过一个具有 1000 个节点单元的隐藏层来传递它。最后,我们让它通过一个具有指定 vocab 大小和 softmax 激活的输出层。softmax 激活确保我们接收到一堆与 vocab 大小相等的输出概率。我们的模型结构的完整代码如下所示。在我们看完模型代码之后,我们还将看一下模型概要和模型情节。

模型摘要:

模型图:

回访:

我们将为下一个单词预测模型使用的回调如下面的代码块所示:

我们将导入培训我们的模型所需的 3 个回调。3 个重要的回调是 ModelCheckpoint、ReduceLROnPlateau 和 Tensorboard。让我们看看每个回调函数执行什么任务。

  1. ModelCheckpoint —这个回调用于存储我们的模型在训练后的权重。通过指定 save_best_only=True,我们只保存模型的最佳权重。我们将使用损失指标来监控我们的培训。
  2. ReduceLROnPlateau —该回调用于在指定数量的时期后降低优化器的学习率。这里,我们将耐心指定为 3。如果准确度在 3 个时期后没有提高,那么我们的学习率相应地降低 0.2 倍。这里用于监控的指标也是损耗。
  3. tensor board—tensor board 回调用于绘制图形的可视化,即精度和损耗的图形绘制。这里,我们将只看下一个字预测的损失图。

我们将把基于度量损失的最佳模型保存到文件 nextword1.h5 中。在访问预测功能和尝试预测我们的下一个单词时,该文件将是至关重要的。我们将等待 3 个时期来改善损失。如果没有改善,那么我们将降低学习率。最后,如果需要,我们将使用 tensorboard 函数来可视化图形和直方图。

编译和调整:

下面是编译和拟合模型的代码块。

我们正在最后一步编译和装配我们的模型。这里,我们正在训练模型并将最佳权重保存到 nextword1.h5,这样我们就不必重复地重新训练模型,并且可以在需要时使用我们保存的模型。这里我只根据训练数据进行了训练。但是,您可以选择同时使用训练数据和验证数据进行训练。我们使用的损失是 categorical _ crossentropy,它计算标签和预测之间的交叉熵损失。我们将使用的优化器是 Adam,学习率为 0.001,我们将编译度量损失模型。我们的结果如下所示:

图表:

预测:

对于预测笔记本,我们将加载以 pickle 格式存储的记号化器文件。然后,我们将加载保存在目录中的下一个单词模型。我们将使用这个相同的标记器对我们应该进行预测的每个输入句子执行标记化。在这一步之后,我们可以通过使用保存的模型对输入句子进行预测。

我们将在运行预测时使用 try 和 except 语句。我们使用这个语句是因为万一在查找输入句子时出现错误,我们不希望程序退出循环。只要用户希望脚本运行,我们就希望运行脚本。当用户想要退出脚本时,用户必须手动选择这样做。只要用户愿意,程序就会运行。

让我们简单地看一下模型所做的预测。这是按如下方式完成的:

进入你们的行列:在沉闷的
天气
进入你们的行列:收集纺织品
样品
进入你们的行列:多么艰苦的
事业
进入你们的行列:停止脚本
结束节目.....

这可以通过使用预测脚本来测试,该脚本将在本文的下一节中提供。我将在下一节给出 GitHub 库的链接。正如我们所看到的,预测模型可以对大多数行进行最佳预测。“停止脚本”行将结束模型并退出程序。当我们输入行“停止脚本”时,整个程序将被终止。对于所有其他的句子,对输入行的最后一个单词进行预测。我们将考虑每行的最后一个单词,并尝试将其与下一个概率最高的单词匹配。

注意:在某些情况下,程序可能不会返回预期的结果。这是显而易见的,因为每个单词只被考虑一次。这将导致特定句子的某些问题,您将不会收到想要的输出。为了提高模型的准确性,你可以考虑尝试二元模型或三元模型。在这种方法中,我们只使用了一元语法。此外,在预处理步骤中还可以完成一些额外的步骤。总的来说,有很大的改进余地。

观察:

我们能够为变形数据集开发高质量的下一个单词预测。我们能够在大约 150 个时期内显著减少损失。我们开发的下一个单词预测模型在所提供的数据集上相当准确。预测的总体质量是好的。然而,可以对模型进行某些预处理步骤和某些改变,以改进模型的预测。

就这样,我们到了文章的结尾。整个代码可以通过这个链接访问。下一个单词预测模型现在已经完成,并且在数据集上表现得相当好。我建议你们所有人利用电子邮件或短信数据来预测下一个单词。这对你的虚拟助理项目会更好。请随意参考 GitHub 库获取完整代码。我也强烈推荐 Machine Learning Mastery 网站,这是一个可以了解更多信息的神奇网站。这对这个项目有很大的帮助,你可以查看网站这里。非常感谢你阅读这篇文章,我希望你们都有美好的一天!

NFL 球员呼吁与期望

原文:https://towardsdatascience.com/nfl-play-calling-vs-expectation-61074fa77a60?source=collection_archive---------30-----------------------

蒂姆·米尔克在 Unsplash 上的照片

哪些教练和四分卫对传球/跑位影响最大?

介绍

美式足球的独特之处在于,教练的决策和准备对比赛有着相对强烈的影响。在足球、曲棍球、篮球和几乎任何其他运动项目中,运动员并不按照教练设计的脚本(也称为“比赛”)排好队。当然,这些运动中有设计好的打法——但它们远不是这项运动的核心。对于裁判来说,在曲棍球 2 v 1 休息时吹哨子并说,好吧,你有 40 秒的比赛时间来计算你想如何接近这个得分机会,这将是很奇怪的。

打电话决策自然是很有争议的。永恒的斗争之一是基于结果的事后分析,尤其是在高杠杆的情况下。说“好吧,你应该把球跑到那里”是人类的天性。例如,第四下,短码的情况往往可以决定整个比赛的结果。有关于是否尝试完全转化的决定,也有关于如何转化的决定。如果球队最终失败,球迷们将不可避免地批评这两个决定。我确实认为,在过去的十年左右,随着梦幻足球、公开数据等的出现,球迷的知识显著增加了。所以很有可能他们在某些评论中是正确的。

这可能是最臭名昭著的“你应该运行它”的戏剧之一

打电话的决策经常受到批评,但球迷们迄今为止提供支持证据的能力有限。我们真的需要详细的数据来测试这种假设。每一个决定都有情境背景,一个人必须适应情境来评论这个行动号召。最著名的是,nflscrapR 数据集使这成为可能。这个图书馆通过使其易于访问而使详细资料大众化。

我在这篇文章中的目标并不是批评 NFL 的教练,而是分析他们对传球和跑位的影响。很有可能我最终会批评一小撮教练,但这不是我的使命。我确实认为应该尊重教练,因为他们已经达到了他们职业的顶峰,并且比我学习这项运动的时间更长。我也认为称他们不会犯错是错误的,因为最终,有太多的证据表明,一些人通过基本的决策来花费或获得他们的团队分数。在其他体育运动中也有类似的情况,公共数据分析显示传统信仰效率低下。最著名的大概是篮球中多投三分球的想法。

方法

最终,我感兴趣的是团队如何称之为游戏与期望。当球队落后时,他们往往会传球更多,因为传球变化更大,花费的时间更少。另一方面,如果一个团队经常领先,他们更有可能叫停比赛,因为他们更稳定,跑得更快。对于每一场比赛,我们可以找到一个联盟预期值,然后比较球队的表现。我从 CardinalsViz 在 Twitter 上的一条推文中获得了这个想法,我建议关注这条推文:

我将比较几种不同的方法,并展示每种方法的优缺点。这实际上是一个突出不同方法的很好的例子。我将从贝叶斯推理开始,然后转向更传统的机器学习方法。

什么是贝叶斯推理?

贝叶斯推理是一种测量未观测变量的方法。去看一场足球比赛,我们知道比赛结束的时间、距离和剩余时间。这些是独立的观察变量。如果我们想知道一个队通过的机会呢?一种解决方法是使用逻辑回归、决策树或机器学习方法。这些都很棒,但是它们有一个缺陷,就是它们是黑箱,而且只给出了点估计。贝叶斯推理以相似的准确性实现了相同的目标,但也量化了不确定性,并允许您进入过程的窗口。代价是这些概率规划推理方法需要一定水平的统计知识,增加了计算时间,并且难以扩展。缩放贝叶斯方法是一个非常活跃的研究领域。如果它们的规模更大,它们将成为许多领域的主导方法。

贝叶斯推理方法尤其适用于足球。另一个好处是,它们允许我们用少量数据更新先前的猜测。在一个 16 场比赛的赛季中,这是至关重要的。例如,我们有红人队临时主教练比尔·卡拉汉 11 场比赛的数据,所以我们应该比约翰·哈博更不确定他对比赛的影响,我们有他 10 个赛季的数据。

还有一个优点是,贝叶斯允许我们对教练的行为进行事先猜测。Kliff Kingsbury 承诺通过传球,或基本上是短码传球,彻底改革 NFL。比尔·卡拉汉在接手之前曾表示,他相信“建立跑步记录”会带来成功。对于这两位教练来说,我们的通过率会有很大不同。这看起来像是欺骗,但这是帮助模特的真实生活专家信息。经典方法没有直接的类比来整合专家信息。

或许同样重要的是,你可以告诉模型“我不知道这个家伙会如何表现”。第三位新教练扎克·泰勒,直到比赛开始我才知道。贝叶斯分析将允许我们对像他这样的人使用无知的先验。

这听起来像推销吗?如果是的话,我很抱歉,但我认为贝叶斯推理在许多领域都没有得到充分利用,所以我倾向于积极支持它。另一方面,这个问题实际上也很好地展示了它的弱点。

通过率模型

让我们从头开始,从头开始构建我们的模型。首先,我将从我们的 360,000 部戏中选取 5000 部戏,并找出一个基本通过率。为什么我要限制样本量?我之所以限制它,是因为我之前描述过的弱点——贝叶斯推理扩展性不好。对于那些实践机器学习方法的人来说,限制数据似乎很奇怪,因为数据越多几乎总是越好。

我也给通过率模型一个 beta (3,3)先验,说“我不认为真正的通过率会接近 100%或接近 0%”。如果你看过一两场足球比赛,这是显而易见的。我们真的不需要这么多数据的先验,但我想增加这一步,因为对于一些应用程序来说,良好的先验是必不可少的。在选择先验知识时,一个人可能犯的唯一大罪是对可能发生的事情赋予零概率。由于贝叶斯规则涉及乘以先验,所以在可能区域中具有零概率的先验将实际似然数据乘以零。Christopher Fonnesbeck 在 youtube 上有很多很棒的概率编程讲座,如果你想深入了解 prior choice 和其他相关模型,我建议你看几个。我也很乐意回答任何问题。

最后,这是我们简单通过率模型的代码:

这个 PyMC3 代码为我们提供了过去 10 年 NFL 球队通过率的可信区间:

注意,我只使用了第一次到第三次的数据。

右图显示了我们的 MCMC 样本链。我试图避免沉重的数学细节,所以我会掩饰它。我用 4 条链运行了 MCMC 算法,因此有 4 种颜色。如果右边的图看起来与上面的“毛毛虫”有任何不同,这意味着链没有收敛,您的结果有问题。

即使我们的样本很小,我们也可以确信 NFL 球队的真实通过率在 58%到 61%之间。你可能会说,“取平均值就行了!”。取平均值也是可行的,但是它不会给你任何不确定性区间。在预测结果和解释预期时,不确定性区间是必不可少的。当样本量很小时,它们也更重要——这在足球界经常发生。

最后,这个分析没有时间因素。一个潜在的改善方法是一个赛季接一个赛季的提高通过率。

基本逻辑回归模型

假设我们观察到球队落后时传球更多的行为。我们可以用分数差作为协变量来模拟通过率。添加一个预测变量会导致模型发生根本变化。我们不会像上面那样输出一个漂亮、干净的通过率分布,因为我们说通过率取决于分数差。

好消息是,这个新模型可以推广到你想要的任何特征,甚至是分类特征。当然,功能选择将变得很重要。使用更多的功能将是下一步。以下是我的逻辑回归模型代码,该模型使用了一个预测值,即分数差:

注意:我使用学生的 t 分布作为先验。它非常类似于正态分布,但是具有更宽的尾部(假设 nu 较低)。这在文学作品中很常见,但正常在这里也适用,因为我使用了广泛的无知先验。

现在,我们有了一个可以根据分数差异进行大幅调整的模型:

我想指出两件事。首先,随着更多数据接近零分差,我们的后验概率更加确定。在尾部附近,后验线呈扇形散开——我们对领先或落后 20 分的球队的数据更少。其次,分数差为零时的通过率与二项分布中的通过率相匹配。这是一个好兆头!如果有不匹配,我会担心某处出错。

添加分类变量

假设我们想要比较多个教练。在 PyMC3 中,很容易将分类变量添加到贝叶斯分析中。让我们比较一下即将到来的超级碗教练趋势:

鉴于相同的得分差距,安迪·雷德肯定比凯尔·沙纳汉更有可能通过。一个可能的原因是安迪·雷德有一个潜在的世代 QB 和沙纳汉有平均 QB 发挥。我们怎么能知道安迪·雷德是否因为他的四分卫而传球更多呢?通过更多的贝叶斯推断!

不过,我们很快就遇到了问题。为了准确捕捉预测变量,我们需要尽可能多的数据。然而,随着数据量的增加,MCMC 采样变得更加难以计算。其核心是,MCMC 试图“作弊”来解决积分——随着更多的数据和更多的特征,这些积分最终变得难以处理。实际上,这意味着我能够在大约 10,000 部戏剧上运行这些模型。过去 10 年的播放数据集有 360,000 次播放,因此这是不令人满意的。

标度贝叶斯推理

有多种方法来扩展这个模型,但没有一种是完美的。我会掩饰一些线索,但我不想陷入困境。正如我之前提到的,这是一个活跃的研究领域,有用的解决方案可以极大地促进多个学科的发展。首先,并非所有的 MCMC 算法都是相同的,因此并非所有算法的规模都相同。

那些来自机器学习背景的人可能会倾向于使用更多的 GPU 来解决这个问题。这是可能的,但 MCMC 采样要求链之间有一定的通信量。如果你正在寻找如何做到这一点,我建议探索 EP-MCMC 和近似 MCMC。

变分推理

变分推理结合了机器学习、梯度下降和贝叶斯推理背后的引擎。它使用一种算法来执行梯度下降,以调整和转换后验分布,直到它们最小化误差(误差通常计算为 Kullback-Leibler 散度)。这很好,因为它避免了计算边际似然积分和 MCMC 样本。不幸的是,正确执行 VI 可能需要大量精力来寻找正确的参数和避免局部极小值。即使是简单的线性回归也需要大量的参数化工作。产出不确定性中的误差也很难量化。

矢量化 MCMC

最初我打算列出这篇文章,因为我无法超越我上面所做的。相反,两天前,我在我的时间线上看到了这条非常及时的推文:

@903124S 发了一个关于逻辑回归的矢量化 MCMC 实现,这正是我需要的。这允许我将计算时间减少到一个合理的水平。因此,我能够描绘出安迪·雷德在他打更多普通四分球时的顶级四分球:

不出所料,我们可以相信帕特里克·马霍斯在中锋位置上时,安迪·雷德传球更多。我还输入其他变量,如停机时间、距离和剩余时间。这允许我们通过将不同的情况输入到模型中来调整情况:

请注意,y 轴与之前的可视化相比已经发生了变化。这显然是一种暂时的情况。

情境调整倾向是非常强大的,可能对那些为 NFL 比赛总数建模的人非常有用。一个很好的例子就是即将到来的超级碗 49 人队。他们在最近几个赛季遭受了许多伤病,这造成了一些奇怪的分裂。有了吉米·加罗波洛,他们在第一次到第三次进攻中有 53.6%的时间传球。有了他的替补四分卫,他们有 61.2%的机会通过。这清楚地表明,主教练凯尔·沙纳汉相信他的替补会比首发投得更多,对吗?如果没有其他信息,p 值等传统指标将显示完全的统计确定性,即凯尔·沙纳汉与吉米·加洛波洛的传球次数更多。相反,49 人队在他的许多快照上都领先。他的后援没有这种奢侈。通过贝叶斯推理,我们可以看到,无论四分卫是谁,凯尔·沙纳汉的传球量大致相同:

我在这里没有包括联盟平均水平,因为它几乎完全等于没有吉米 G 线。

问题

我们还有一些问题。我使用的贝叶斯逻辑回归模型只能处理以一致速率增长的单调特征。此数据集中的要素并不都具有这种质量。例如,在上半场结束前,球队很快就会传球,这是很常见的。我上面展示的模型不能正确区分上半场还剩两分钟和下半场开始。比赛中期的高通过率给它带来了麻烦,使它更难估计后面的情况。

支持向量机(SVM)和深度神经网络都能够处理这些线性但非单调的特征。这里我将重点介绍支持向量机,因为与其他众所周知的方法相比,它非常适合这个数据集,而且速度也非常快:

最右边的 SVM 明显优于其他常用方法。上面使用的逻辑回归是最左边的。

这些传统机器学习方法的快速性和准确性是很大的好处。当然缺点是无法用小样本对教练建模,无法给出不确定性的量化估计。一个 SVM 会给出一个通过率的点估计,不管是 3 号和 3 号的菜鸟主教练,还是 3 号和 15 号的 10 年主教练。当然,我们知道其中一种情况应该非常准确,而另一种情况应该非常不确定。

SVM 应用

众所周知,西雅图的头蔻驰·皮特·卡洛尔致力于跑步(除了我之前嵌入的比赛视频)。今年,这种理念受到了审视,因为他没有伟大的跑位,却拥有联盟最好的四分卫之一。我的假设是,他因为过早的跑动而损失了球队的分数,而不是像安迪·雷德那样进攻。我还没有测试过这个,所以也许他没有。

是的,这里有缺陷和警告。教练会告诉你跑位会设置传球。聪明的足球人可能会说传球的回报在减少,尽管支持这一点的证据有限。很多人也用卡罗尔的输赢记录来为他的职业生涯辩护。

而且,皮特卡罗尔对足球的了解也比我多。最后,传球可以让时钟停止,所以一般来说,叫更多的传球会导致更多的传球——因此有一些我没有考虑的二阶效应。

记住所有这些警告,我发现皮特·卡罗尔在 2019 年比联盟平均教练多跑 10%的时间。这是极端的,这也是我选择这个例子的原因。在我测试的其他皮特·卡罗尔赛季中,差异并没有这么大。这也不太合理,因为今年他的跑位和传球效率的差异更大。

这意味着他本赛季比一个普通的联盟主教练在同样情况下多跑了大约 107 分。他的传球,使用 nflscrapR 的 EPA/play,比他在那段时间的跑位效率高出近 0.17 分。这意味着他让他的球队在整个赛季中因为没有达到联盟平均水平而损失了大约 19 分。

结论

对于比较各种机器学习方法的优缺点来说,这是一个很好的玩具问题。在这篇文章的研究中,我还偶然发现了最近开发的贝叶斯神经网络和贝叶斯支持向量机。它们承诺消除我在这里描述的模型的一些弱点。就像我之前说的,这是一个非常活跃的领域,我迫不及待地想以新的方式应用新的方法。

我赶在超级碗之前发表这篇文章,所以我的代码没有平时那么干净,评论也没有平时多。很快会有更新,但是我想享受这个游戏。这里的是我的 Kaggle-GPU 驱动的矢量化 MCMC 代码,这里的是我在本地机器上使用的代码。

NGBoost

原文:https://towardsdatascience.com/ngboost-aca51711c8f5?source=collection_archive---------23-----------------------

梯度助推器

梯度增强中的自然梯度

保罗·吉尔摩Unsplash 上拍摄的照片

在表格数据领域,梯度助推器的统治几乎已经完成。在大多数真实世界以及竞赛中,几乎没有一个解决方案不具有来自梯度推进算法之一的至少一个模型。但是,随着机器学习社区的成熟,机器学习应用程序开始得到更多的使用,对不确定性输出的需求变得很重要。对于分类,梯度增强的输出形式已经可以让您了解模型预测的可信度。但是对于回归问题,情况并非如此。模型吐出一个数字,告诉我们这是它的预测。如何从点预测中获得不确定性估计?这个问题不仅仅是梯度推进算法的问题。但几乎适用于所有主要的 ML 算法。这是新成员 NGBoost 试图解决的问题。

如果你还没有读过本系列的前几部分,我强烈建议你去读一读,至少是第一部分,在那里我谈到了梯度增强算法,因为我认为你已经知道了什么是梯度增强。我也强烈建议阅读 VI(A) ,这样你会对什么是有更好的理解。

自然梯度增强

NGBoost 的关键创新是在 boosting 算法中使用自然渐变而不是常规渐变。通过采用这种概率途径,它在协变量的条件下,模拟了结果空间上的全概率分布。

该文件将他们的方法模块化为三个部分

  1. 基础学习者
  2. 参数分布
  3. 评分规则

基础学习者

在任何增强技术中,都有一些基础学习者被组合在一起以得到一个完整的模型。NGBoost 不做任何假设,并声明基础学习者可以是任何简单的模型。该实现支持决策树和岭回归作为开箱即用的基础学习器。但是您可以轻松地用任何其他 sci-kit 学习风格模型来替换它们。

参数分布

在这里,我们不是训练一个模型来预测作为点估计的结果,相反,我们预测的是一个完整的概率分布。每个分布都由几个参数来参数化。对于 eg,正态分布由其平均值和标准偏差来参数化。你不需要其他任何东西来定义一个正态分布。因此,如果我们训练模型来预测这些参数,而不是点估计,我们将有一个完整的概率分布作为预测。

评分规则

任何机器学习系统都有一个学习目标,通常情况下,它的任务是最小化一些损失。在点预测中,用损失函数将预测与数据进行比较。评分规则类似于概率回归世界。评分规则将估计的概率分布与观察到的数据进行比较。

适当的评分规则 S 将预测的概率分布 P 和一个观察值 y (结果)作为输入,并给预测分配分数 S(P,y) ,使得结果的真实分布获得预期中的最佳分数。

最常用的适当评分规则是对数分数 L ,当最小化时,我们得到 MLE

这就是我们在很多地方看到的对数可能性。评分规则由θ参数化,因为这是我们作为机器学习模型的一部分所预测的。

另一个例子是 CRPS(连续排名概率得分)。对数分数或对数似然将均方误差推广到概率空间,而 CRPS 对平均绝对误差做了同样的事情。

广义自然梯度

在这个系列的最后一部分,我们看到了什么是自然梯度。在那次讨论中,我们谈到了 KL 散度,因为传统上,自然梯度是根据 MLE 评分规则定义的。但本文提出了这一概念的推广,并提供了将这一概念推广到 CRPS 评分规则的方法。他们将 KL 散度推广为一般散度,并为 CRPS 评分规则提供了推导。

把所有的放在一起

现在我们已经看到了主要组件,让我们看看所有这些组件是如何协同工作的。NGBoost 是一种用于概率预测的监督学习方法,它使用 boosting 来估计条件概率分布 P(y|x) 的参数。如前所述,我们需要提前选择三个模块化组件:

  1. 基础学习者( f
  2. 参数概率分布( P 由θ 参数化)
  3. 合适的评分规则( S

对新输入 x 的预测 y|x 以条件分布 p 的形式进行,其参数θ通过对 M 个基本学习器输出和初始θ₀.的相加组合来获得让我们用 f ⁽ᵐ⁾[2].来表示 m 个基本学习者学习到的所有参数的组合函数并且对于所选择的概率分布中的每个参数,将有一组单独的基础学习者。例如,在正态分布中,μ有 f ⁽ᵐ⁾,log σ有 f ⁽ᵐ⁾。预测的输出也用一个特定阶段的比例因子(ρᵐ)和一个通用的学习速率η进行缩放:

这里需要注意的一点是,即使你的概率分布有 n 个参数,ρ仍然是一个标量。

算法

让我们看看论文[2]中解释的算法。

让我们考虑一个数据集

助推迭代 M ,学习率η,带参数θ的概率分布,合适的评分规则 S ,基础学习器 f

  1. 初始化θ₀到边缘。这只是估计分布的参数,不考虑任何协变量;类似于初始化为均值。数学上,我们解这个方程:

  1. 对于 M 中的每次迭代:
  2. 针对数据集中的所有 n 个示例,计算评分规则 s 相对于前一阶段θᵢᵐ⁻的参数的自然梯度 gᵢᵐ。
  3. 用于迭代 f ⁽ᵐ⁾的一组基本学习器适合于预测自然梯度 gᵢᵐ.的相应分量这个输出可以被认为是自然梯度在基础学习者类别的范围上的投影,因为我们正在训练基础学习者预测当前阶段的自然梯度。
  4. 该投影梯度然后通过比例因子ρᵐ.进行缩放这是因为自然梯度依赖于局部近似(正如我们在前面的帖子中看到的),这些局部近似在远离当前参数位置的地方不会保持良好。
    在实践中,我们使用线搜索来获得最佳的比例因子,使整体评分规则最小化。在实现中,他们发现在线搜索中将缩放因子减半效果很好。
  5. 一旦估计了缩放参数,在通过学习速率进一步缩放之后,我们通过将负缩放投影梯度添加到前一级的输出来更新参数。

履行

该算法在https://github.com/stanfordmlgroup/ngboost具有现成可用的 Sci-kit 学习风格实现。让我们来看看调整模型的关键参数。

超参数

  • Dist:该参数设置输出的分布。目前,该库支持用于回归的正态、对数正态和指数分布,用于分类的k _ 分类和伯努利默认:正常**
  • 评分:指定评分规则。目前,选项在 LogScore 或 CRPScore 之间。默认值:LogScore**
  • 基础:这指定了基础学习者。这可以是任何 Sci-kit 学习估计器。默认为三层决策树**
  • n_estimators:提升迭代的次数。默认值:500**
  • learning_rate :学习率。*默认值:0.01*
  • minibatch_frac :在每次提升迭代中使用的行的百分比子样本。这与其说是性能调优,不如说是性能黑客。当数据集很大时,这个参数可以大大加快速度。

解释

尽管在使用来自机器学习模型的重要性之前需要相当多的谨慎,NGBoost 也提供了特性重要性。对于它估计的每个参数,它都有单独的一组重要性。

来源:NGBoost 文档[3]

但最精彩的部分不仅仅是这个,还有那辆 SHAP ,也是现成的型号。您只需要使用 TreeExplainer 来获取值。(要了解更多关于 SHAP 和其他可解释技术的信息,请查看我的另一个博客系列——可解释性:打开黑盒)。

来源:NGBoost 文档[3]

实验

本文还研究了该算法与其他流行算法相比的性能。有两种不同类型评估——概率评估和点估计

概率回归

在来自 UCI 机器学习知识库的各种数据集上,NGBoost 与其他主要的概率回归算法进行了比较,如蒙特卡洛丢失深度集成混凝土丢失、高斯过程、位置、规模和形状的广义加法模型(GAMLSS)分布式森林

点估计

他们还针对其他回归算法(如弹性网络、随机森林(Sci-kit Learn)、梯度推进(Sci-kit Learn))评估了点估计用例上的算法。

结论

NGBoost 的性能与现有算法一样好,甚至更好,但它还有一个额外的优势,就是为我们提供了一个概率预测。并且公式和实现足够灵活和模块化,使其易于使用。

但是这里的一个缺点是算法的性能。时间复杂度随着我们必须估计的每个额外参数而线性增加。所有效率方面的改进/改变都已经成为 LightGBM 或 XGBoost 等流行的梯度提升包的一部分,但在当前的实现中并不存在。也许它会很快被移植过来,因为我看到回购正在积极发展,并将其视为他们的目标行动项目之一。但是在这之前,这是相当慢的,尤其是对于大数据。一种解决方法是使用 minibatch_frac 参数来加快自然梯度的计算。

现在我们已经看到了所有主要的梯度助推器,让我们挑选一个样本数据集,看看它们在本系列的下一部分如何表现。

中的其他文章

参考

  1. 甘利顺一。自然梯度在学习中很有效。神经计算,第 10 卷,第 2 期,第 251–276 页。
  2. 段,托尼。NGBoost: 用于概率预测的自然梯度推进,arXiv:1910.03225 v4【cs .2020 年 6 月 9 日
  3. *NGBoost 文档,【https://stanfordmlgroup.github.io/ngboost *

原载于 2020 年 6 月 27 日 http://deep-and-shallow.com**

NGBoost 算法:解决概率预测问题

原文:https://towardsdatascience.com/ngboost-algorithm-solving-probabilistic-prediction-problems-fdbe1858ca61?source=collection_archive---------25-----------------------

ICML 2020 年

预测目标变量的分布,而不仅仅是点估计

照片由穆罕默德·阿里扎德Unsplash 拍摄

在翻阅 ICML 2020 录取论文时,我发现了一篇有趣的论文:

[## NGBoost:用于概率预测的自然梯度推进

我们提出了自然梯度推进(NGBoost),一种算法的一般概率预测梯度…

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

你可能会问,我们还需要多少关于梯度推进的论文?但事实上,GBT 算法家族在表格数据上表现得非常好,一直在 Kaggle 排行榜上名列前茅。这项技术非常成功,现在已经扩展到表格数据以外的领域,例如,NLP。

问题陈述

我们在这里处理的问题是,几乎所有的回归算法都不返回给定预测值 P(y|X)的目标变量的分布,而是返回目标变量 E(y|X)的期望,即点估计。这与大多数返回类别概率的分类算法相反。例如,在 scikit-learn 中,分类器有方法predict_proba(),它返回类的概率。回归子缺少这种方法,只有回归概率。

为什么这是一个问题?假设你正试图预测下周的天气。如果您需要提供一个预测范围,即预测 15–20 度,而不是预测 17.25 度,该怎么办?如果你想知道气温不会降到冰点以下的概率?你能用一个模型做所有这些预测吗?是的,如果你的模型返回给定预测值的目标变量的条件概率分布。虽然这不是一个新问题,但大多数解决方案都是针对特定问题的,我们缺少开箱即用的通用算法。

NGBoost 算法解决了这一问题:

概率推理

NGBoost 如何找到目标变量分布?

因此,首先,这不是一个非参数模型(如果您对连续变量的非参数建模感兴趣,可以尝试离散化或分位数转换等技术)。你必须对条件目标变量分布做一个假设。例如,它可以是正态分布(但是μ和σ都取决于 X),或者高斯混合(对于许多回归问题来说更现实的情况),或者偏斜的正态分布。对于生存分析,它将是指数分布,对于预测正值,它是伽玛分布的变体,等等。一旦你选择了你的条件分布,问题就简化为学习给定输入变量的分布的参数向量 θ

我们在优化什么?

在处理常规回归问题时,我们通常会最小化均方误差。如果我们试图预测的是一个概率分布,我们如何选择一个损失函数?在这种情况下,我们使用一个评分规则:

对于许多问题,我们可以使用负对数似然作为评分函数

在这种情况下,我们试图得到的是给定用 θ 参数化的分布,目标值 y 的可能性有多大。参数 θ 最佳选择的评分规则是最小的评分规则。评分规则之间的差异称为离差,是概率分布之间“距离”的度量。如果 Q 是真实分布,P 是预测分布,则散度为:

如果我们使用 MLE,那么散度就变成了 kull back–lei bler 散度,广泛用于度量概率分布之间的差异。

自然梯度

NGBoost 中的“NG”代表“自然渐变”。(或者可能是因为它是论文合著者之一吴恩达的姓氏?)为什么非要引进呢?

一旦您开始使用基于梯度的方法来学习参数 θ ,您会很快意识到两个分布之间的距离不是由它们参数的差异定义的,因此参数的梯度方向不一定表示模型的最佳改进方向

自然梯度通过使用散度而不是参数差来纠正这个问题:

所以,我们不是在参数空间里画一个单位球在点周围,寻找最大改善的方向,而是画一个散度取相同值ε的曲面。自然梯度通过统计流形的黎曼度量与规则梯度相联系:

如果我们用 MLE,矩阵 I 就是费希尔信息矩阵

把所有东西放在一起

使用所介绍的技术,可以创建基于 GBT 的算法来预测条件分布的参数:

虽然这看起来像一个常规的 GBT 算法,但它有几个重要的区别:

  1. 对于每个例子和迭代计算梯度,然后通过逆黎曼度量来改进,在 MLE 的情况下,这是逆信息矩阵。如果有几个分布参数,这不是一个大问题。
  2. 使用不依赖于示例的缩放因子,这允许对拟合的弱学习器进行全局调整

与其他方法相比,该算法表现出良好的性能。比较自然梯度和规则梯度的实验结果非常有趣:

我们可以看到,使用自然梯度显著提高了学习,结果更正确地描述了条件方差。

有趣的是,该算法也擅长预测点估计,即使它是在不同的目标上训练的。

Github 知识库https://github.com/stanfordmlgroup/ngboost有一个很好的例子,你可以在一个简单的数据集上使用它:

结论

预测连续变量的条件分布是困难的,预测点估计要容易得多。这与分类问题不同,在分类问题中,更多的算法能够预测类别概率。NGBoost 算法允许在给定预测值的情况下容易地获得目标变量的条件分布的参数预测。对于 NGBoost 可以处理的分发类型,几乎没有什么假设。事实上,如果正态分布不适合给定的问题,可以选择另一种分布(可能有更多的参数)来更好地适应模型。正如论文结论中所指出的,该算法有许多改进的可能性,探索理论问题和更复杂的问题。但是即使在这个阶段,NGBoost 也可以用于大多数实际问题的概率回归。

使用 Python 进行 NHL 分析

原文:https://towardsdatascience.com/nhl-analytics-with-python-6390c5d3206d?source=collection_archive---------14-----------------------

我用数据理解 NHL 的冒险

这就是我们今天要做的!分析的最终结果显示,亚历克斯·奥韦奇金是左翼之王。

阿纳达。曲棍球。有些人可能会说,他们是一体的,然而我从来没有真正成为一个超级体育迷。在枫叶队进入季后赛的罕见情况下,我会穿上蓝色的衣服,和我的朋友一起去酒吧等待不可避免的失望,但是当他们开始谈论球员和他们在赛季中的表现时,我开始感觉有点疏远。因此,为了更好地理解这款游戏,我决定戴上数据分析帽,深入研究一些 NHL 球员的数据。

我做的第一件事是查看什么样的数据是可用的,哦,我没有失望!实际上有一个未记录的 NHL 数据 API,包含从球队日程和花名册到 的所有内容,包括在冰上拍摄的每一个镜头,包括地点,涉及的球员和发生的时间 。对于那些好奇的人,一个很棒的人创建了一个 GIT 页面,其中有 API 调用的摘要( NHL API 文档)。有了这个,我就有了提取数据和开始做一些球员分析所需的一切。

正在提取 NHL API 数据

我所有的分析都是用 Python 完成的,为了更简单,我使用 Kaggle 作为我的编码平台。如果你还没有检查 Kaggle 出来,你真的应该。他们有一堆开放的数据集、竞赛以及分享和存储你的笔记本的方式(Jupyter)。我将在这里展示的所有代码都可以从我的 Kaggle 帐户上公开获得(参见底部的参考资料),所以请随意探索和使用它。由于数据集如此之深,我决定只提取 2019-2020 赛季的游戏事件数据进行分析。这让我可以访问到目前为止的所有比赛,包括所有冰上项目(击球、击球、对抗等。).

和往常一样,首先要做的是加载包和初始化变量。这里你会看到我使用请求从 API 获取数据,使用 pickle 保存数据以备后用。

import requests
import pickle**# Set up the API call variables**
game_data = []
year = '2019'
season_type = '02' 
max_game_ID = 1290

API 的格式允许我们传入赛季的年份,选择比赛类型,如预赛/常规赛/季后赛(本例中 02 是常规赛),最后是 max_game_ID 。这是给定年份中游戏事件的最大数量。

是时候提取数据并将 json 格式的数据存储到一个列表中了。

**# Loop over the counter and format the API call**
for i in range(0,max_game_ID):
    r = requests.get(url='[http://statsapi.web.nhl.com/api/v1/game/'](http://statsapi.web.nhl.com/api/v1/game/')
        + year + season_type +str(i).zfill(4)+'/feed/live') data = r.json()
    game_data.append(data)

现在所有的甜蜜数据都存储在一个列表中,我们可以把它保存为一个 pickle 文件。我这样做的原因是,我可以把它上传到 Kaggle 上,并让任何想做一些分析的人都可以使用它。Pickle 文件还允许存储对象,并且加载速度非常快。

with open('./'+year+'FullDataset.pkl', 'wb') as f:
    pickle.dump(game_data, f, pickle.HIGHEST_PROTOCOL)

这样我们就有了一个名为 2019FullDataset.pkl 的新文件,我们将其保存为 Kaggle 上的数据集。您可以查看底部的参考资料,获取指向我的数据集的链接。

现在是有趣的事情!你可以做很多事情,但我想做的是观察任何球员在冰面上不同位置的投篮效率,并将它们与整个联盟的平均成功率进行比较。

分析球员投篮数据

利用 NHL 的数据,我想看看在哪里球员的投篮效率最高(进球/总投篮百分比)与联盟平均水平相比。首先,让我们导入所有必需的包。注意我使用 matplotlib 进行所有的绘图。我还安装了 枕头 来导入图像数据。

*import numpy as np 
import pandas as pd 
import pickle    
import matplotlib
import matplotlib.pyplot as plt
color_map = plt.cm.winter
from matplotlib.patches import RegularPolygon
import math
from PIL import Image**# Needed for custom colour mapping!** from matplotlib.colors import ListedColormap,LinearSegmentedColormap
import matplotlib.colors as mcolors*

对于我所有的绘图,我将使用 matplotlib 方法 ListedColormap 来使用自定义的颜色图。因为我想给正值涂上不同于负值的颜色,所以我做了两个颜色映射。

*c = mcolors.ColorConverter().to_rgb()
positive_cm = ListedColormap([c(‘#e1e5e5’),c(‘#d63b36’)])
negative_cm = ListedColormap([c(‘#e1e5e5’),c(‘#28aee4’)])* 

现在我们已经解决了这个问题,让我们加载 2019 年常规赛的 pickle 数据文件,其中包含了每场比赛的所有事件数据。注意,我们正在加载之前生成的 pickle 文件。

*with open(‘../input/nhl-data/2019FullDataset.pkl’, ‘rb’) as f:
    game_data = pickle.load(f)*

计算平均投篮命中率%

加载数据后,我想首先计算出联盟在冰上每一点的平均命中率。使用字典中的事件坐标对象输入数据。在我们的分析中,我们只想关注“射门”和“进球”类型的事件。

下面是一步一步的细分:

首先,我们创建一个字典来保存整个联盟的所有射门和进球数据坐标。

***# Do some dictionary initialisation to hold our cleaned and condensed league data**
league_data = {};league_data[‘Shot’] = {};
league_data[‘Shot’][‘x’] = [];
league_data[‘Shot’][‘y’] = [];league_data[‘Goal’] = {};
league_data[‘Goal’][‘x’] = [];
league_data[‘Goal’][‘y’] = [];*

我们只想保留射门和进球数据中的事件。

*event_types = ['Shot','Goal']*

最后,我们循环播放每一个游戏,并将相关信息提取到我们的字典中。

***# First loop over the elements of game_data. Each one of these is an NHL game and contains all of the game event data.**
for data in game_data: **# It is possible that the game data is not assigned to the data
   set, so to handle this we look for the key ‘liveData’ which 
   contains all of the data we are looking for, otherwise we
   continue**
   if 'liveData' not in data:
        continue **# Drilling down into the dataset to extract the play by play
   information for the game**
   plays = data['liveData']['plays']['allPlays'] 

    for play in plays: **# For each play**
         for event in event_types: ** # For each event (Shot,Goal)** **# If the play contains one of the events**
            if play['result']['event'] in [event]:              **# If the event contains coordinates**
               if 'x' in play['coordinates']: **# Save the coordinates to the growing list**                  league_data[event]
                       ['x'].append(play['coordinates']['x'])
                    league_data[event]
                       ['y'].append(play['coordinates']['y'])*

现在我们有了联赛数据,我们可以对给定的球员做同样的事情。唯一的区别是,在提取数据时,我们将筛选射手子事件类型。

在咨询了一些冰球迷后,我被告知亚历克斯·奥韦奇金是一个很好的测试案例。他活跃在一个非常独特的领域,我们应该能够基于此来验证事情。

球员数据提取与联赛数据提取非常相似,所以我在这里只注意变化:

***# Initialise the player dictionary
full_name = 'Alex Ovechkin'**
player_data = {};player_data['Shot'] = {};
player_data['Shot']['x'] = [];
player_data['Shot']['y'] = [];player_data['Goal'] = {};
player_data['Goal']['x'] = [];
player_data['Goal']['y'] = [];*

现在我们基本上做和以前一样的过程,但是寻找球员数据。

***# Same code as before** ...for play in plays:
   **if 'players' in play:
      for player in play['players']:
         if player['player']['fullName'] in [full_name]  
            and player['playerType'] in ["Shooter","Scorer"]:**for event in event_types:

...*

在上面加粗的部分,你可以看到我们正在过滤作为射手得分手的玩家。每场比赛都包括谁参与其中,所以我们可以简单地看看奥韦奇金是否被列为射手或得分手。有了它,我们可以处理一些数字,做一些很酷的分析。

计算基本统计数据

在我们绘制位置数据之前,我想计算一下与联盟平均水平相比,玩家的高水平数据。

***# Get the total number of shots made by the player** player_total_shots = len(player_data['Shot']['x']) +
   len(player_data['Goal']['x'])**# Find the players goal score percentage**
player_goal_pct = len(player_data['Goal']['x'])/player_total_shots**# Find the total number of shots taken in the league** league_total_shots = len(league_data['Shot']['x']) +
   len(league_data['Goal']['x'])**# Get the league percentage**
league_goal_pct = len(league_data['Goal']['x'])/league_total_shots**# Calculate the spread of the SOG (Shots on Goal) %**
PL_e_spread = player_goal_pct-league_goal_pct*

汇总统计数据

这是我们的第一个结果。我们可以把它与官方数据进行比较,结果是一致的。

我们可以看到,奥韦奇金 5.85%的利差意味着他是一个高效的得分手。

但是在冰面上所有的点都是这样吗?他有强势的一面吗,或者有什么弱点吗?现在我们可以开始位置分析了。

射击位置分析和标绘

我们首先要做的是建立一个宁滨网格。我想知道在冰上的什么地方拍摄,但我不想看到所有的个人镜头。通过进行空间平均,我们可以做出更有洞察力和更直观的表示。来自 API 的位置数据来自:

  • X: -100 至 100 米
  • Y: -42.5 至 42.5 米

对于我们的宁滨,我们使用来自 matplotlib 的十六进制图来提取原始的宁滨数据,并将使用绘制的矩形(同样是 matplotlib)来获得最终的视觉效果。

首先,我们定义我们的图形尺寸和网格大小:

***# To keep the aspect ration correct we use a square figure size**
xbnds = np.array([-100.,100.0])
ybnds = np.array([-100,100])
extent = [xbnds[0],xbnds[1],ybnds[0],ybnds[1]]**# We are going to bin in 30 unit increments.  It is fun to play with this!** 
gridsize= 30;mincnt=0*

接下来我们会发现联盟在冰上各个位置的效率。为此,我们调用 hexbin 方法并提取位置顶点和计数数据。

需要注意的一点是,由于记分员从不在自己的网上得分,我们必须确保反面位置总是代表进攻方。

这都是因为每一个周期玩家都会换边,而坐标系是固定的。

***# First concatenate the arrays for x and y league data** league_x_all_shots = league_data['Shot']['x'] 
   + league_data['Goal']['x'];
league_y_all_shots = league_data['Shot']['y'] 
   + league_data['Goal']['y']**# Perform the coordinate flipping!** league_x_all_shots_normalized = [];
league_y_all_shots_normalized = []**# Enumerate the list so we can use the index for y also**
for i,s in enumerate(league_x_all_shots):
    if league_x_all_shots[i] <0:
        league_x_all_shots_normalized.append(-league_x_all_shots[i])
        league_y_all_shots_normalized.append(-league_y_all_shots[i])
    else:
        league_x_all_shots_normalized.append(league_x_all_shots[i])
        league_y_all_shots_normalized.append(league_y_all_shots[i])

**# Do the same treatment for the goals**
league_x_goal_normalized = [];
league_y_goal_normalized=[]
for i,s in enumerate(league_data['Goal']['x']):
    if league_data['Goal']['x'][i] <0:
       league_x_goal_normalized.append(-league_data['Goal']['x'][i])
       league_y_goal_normalized.append(-league_data['Goal']['y'][i])
    else:
       league_x_goal_normalized.append(league_data['Goal']['x'][i])
       league_y_goal_normalized.append(league_data['Goal']['y'][i])*

酷毙了。现在是为了钱!调用 hexbin 图并提取计数和位置。这部分有点长,但只要跟着评论走,就应该很清楚了。

***# First we will used the hexbin function to simply bucket our shot data into basically a 2D histogram**
league_hex_data = plt.hexbin(league_x_all_shots_normalized,
   league_y_all_shots_normalized,gridsize=gridsize,
   extent=extent,mincnt=mincnt,alpha=0.0)**# Now we extract the bin coordinates and counts**
league_verts = league_hex_data.get_offsets();
league_shot_frequency = league_hex_data.get_array();**# Do the same thing for the goal data**
league_goal_hex_data =  plt.hexbin(league_x_goal_normalized,
   league_y_goal_normalized,gridsize=gridsize,
   extent=extent,mincnt=mincnt,alpha=0.0)**# Since the grid is the same we can use a shared bin coordinate set from the above. So here we just get the counts**
league_goal_frequency = league_goal_hex_data.get_array();*

现在我们有了拍摄数据的位置和数量,我们将尝试以一种有用的方式展示它。首先,我们加载半个 NHL 溜冰场的比例模型图像。然后,我们将确保缩放我们的坐标,以匹配图像的大小,从而获得照片在冰上的准确位置。

***# Using matplotlib we create a new figure for plotting**
fig=plt.figure(figsize=(10,10))
ax = fig.add_subplot(111)**# Clean up the figure to be completely blank**
ax.set_facecolor("white")
fig.patch.set_facecolor("white")
fig.patch.set_alpha(0.0)**# Remove the labelling of axes**
ax.set_xticklabels(labels = [''], fontsize = 18,
   alpha = .7,minor=False)
ax.set_yticklabels(labels = [''], fontsize = 18,
   alpha = .7,minor=False)**# Using pillow to get the rink image and extract the image size**
I = Image.open('../input/nhl-images/half.png')
ax.imshow(I);width, height = I.size*

此时,我们应该有一个曲棍球场的图像被绘制成 matplotlib 图像。接下来,我们要确定一些缩放因子和偏移,以对齐我们的图像和数据坐标系。

***# Calculate the scaling factor and offset (trial and error)**
scalingx=width/100-0.6;
scalingy=height/100+0.5;
x_trans=33;
y_trans=height/2**# We will want to scale the size of our hex bins with the image so we calculate a "radius" scaling factor here**
S = 3.8*scalingx;*

终于我们准备好了。Matplotlib 允许在给定的多边形形状中添加面片元素。所以我们将使用六边形元素在溜冰场图像上添加补丁。

***# Loop over the locations and draw the hex**
for i,v in enumerate(league_verts): **# Ignore empty locations**
   if league_shot_frequency[i] < 1:continue

   **# Normalize the shot frequency data between 0-1** 
   scaled_league_shot_frequency =
      league_shot_frequency[i]/max(league_shot_frequency) **# Scale the hexagon size based on shot frequency**
   radius = S*math.sqrt(scaled_league_shot_frequency) **# Finally we will plot the hexagon including the scaling and
   translations we found earlier**
   hex = RegularPolygon((x_trans+v[0]*scalingx, 
      y_trans-v[1]*scalingy),numVertices=6, radius=radius,
      orientation=np.radians(0),alpha=0.5, edgecolor=None) ax.add_patch(hex)*

成功!我们在联盟中有一个很好的拍摄分布

你可以看到,平均而言,这些射门相当对称,而且大多发生在网前。你也可以在蓝线上看到一个大的下降,这也是有道理的。

现在让我们对球员数据做同样的事情。唯一的区别是所有的变量都用“球员”替换了“联赛”前缀。例如:

***player**_x_all_shots = **player**_data['Shot']['x'] 
  + **player**_data['Goal']['x'];**player**_y_all_shots = **player**_data['Shot']['y'] 
  + **player**_data['Goal']['y']*

现在,我们将不再只是绘制照片,而是用绿色的显示的目标。**

展示了奥韦奇金的射门和进球。

非常酷!我们可以看到他在圆圈上方的左侧非常活跃。在和我的冰球朋友商量后,我发现这真的是他的地盘!但是现在我们应该看看他在冰上的效率。这是他的地盘吗,因为他经常在那里投篮?

为了做到这一点,我将使十六进制的大小,射击频率和颜色代表他的效率。

***# Get some lists initialised** 
league_efficiency = []
player_efficiency = []
relative_efficiency = []**# Looping over the league shots (which are the same in length as player)**
for i in range(0,len(league_shot_frequency)): **# We will only look at positions on the ice where the player or
    league had more than two shots during the season**
    if league_shot_frequency[i]<2 or player_shot_frequency[i]<2:
        continue **# Calculate the efficiencies** 
league_efficiency.append(
   league_goal_frequency[i]/league_shot_frequency[i])

player_efficiency.append(
   player_goal_frequency[i]/player_shot_frequency[i])

**# And the relative efficiency**
relative_efficiency.append(
   (player_goal_frequency[i]/player_shot_frequency[i]-
   (league_goal_frequency[i]/league_shot_frequency[i]))**# Keep track of the max so we can scale the colour and radius of the hex plot after**
max_league_efficiency = max(league_efficiency)
max_player_efficiency = max(player_efficiency)
max_relative_efficiency = max(relative_efficiency)
min_relative_efficiency = min(relative_efficiency)*

最后,我们为绘制在给定位置拍摄的相对效率的最后阶段做好了准备。

***# Loop over the locations and draw the hex**
for i,v in enumerate(player_verts): **# Here we will only include locations where the player made at
    least on shot.  We will adjust this later for plotting.**
    if player_shot_frequency[i] < 1:continue

   ** # Scaling the frequencies**
    scaled_player_shot_frequency =
        player_shot_frequency[i]/max(player_shot_frequency) **# Calculate a radius of the hex**
    radius = S*math.sqrt(scaled_player_shot_frequency)

 **# Find the player efficiency and relative at this point on the
    ice.** player_efficiency =
        player_goal_frequency[i]/player_shot_frequency[i]
    league_efficiency =
        league_goal_frequency[i]/league_shot_frequency[i] **# This is what we were after the whole time!** 
    relative_efficiency = player_efficiency - league_efficiency

   **# Since there can be positive and negative efficiencies
   (relative) we colour the more efficient locations red and the
   less blue.** if relative_efficiency>0:
        colour = positive_cm(math.pow(relative_efficiency,0.1))
   else:
        colour = negative_cm(math.pow(-relative_efficiency,0.1))

   **# And finally we plot!   ** 
   hex = RegularPolygon((x_trans+v[0]*scalingx,
       y_trans-v[1]*scalingy),numVertices=6, radius=radius,
       orientation=np.radians(0),facecolor=colour,alpha=1,
       edgecolor=None)
   ax.add_patch(hex)*

看起来不错,但是有点忙。

最后一步,我们可以增加要查看的数据点的阈值。让我们只看看他在赛季中拍摄超过 4 张照片的地点。

最终图像可用于后期处理和发布。

哇!现在看起来相当不错!我们可以清楚地看到奥韦奇金在左路是一个超级高效的球员,这也是他投篮最多的地方。与联盟平均水平相比,他是惊人的。

我们确实发现的一件事是,当谈到在网前投篮时,他低于平均水平(根据十六进制尺寸,这看起来很常见)。这可能是帮助他提高或用来对付他的东西!

最后,我把这个给了我的曲棍球朋友,经过回顾,他们基本上说:

”丫显然嗯了一声。那完全是他的地盘!”

你知道吗?这是我能收到的最好的评论。

参考和代码

图片

本文中的所有图片都是我自己用 python + Photopea 制作的

数据抓取

* [## NHL 分析-数据收集

使用 Kaggle 笔记本探索和运行机器学习代码|使用来自非数据源的数据

www.kaggle.com](https://www.kaggle.com/kapastor/nhl-analytics-data-collection)

数据集

[## NHL 数据

2015-2019 赛季常规 NHL 数据。包括所有游戏和事件。

www.kaggle.com](https://www.kaggle.com/kapastor/nhl-data)

数据分析

[## NHL 分析-镜头分布

使用 Kaggle 笔记本探索和运行机器学习代码|使用来自多个数据源的数据

www.kaggle.com](https://www.kaggle.com/kapastor/nhl-analysis-shot-distribution)

NHL API

http://statsapi.web.nhl.com/api/v1/game/*

让 python 代码看起来更好的九个简单步骤

原文:https://towardsdatascience.com/nine-simple-steps-for-better-looking-python-code-87e5d9d3b1cf?source=collection_archive---------6-----------------------

来源com break,经由 pixabay 。(Pixabay 许可证)

我会定期查看补充学术论文、发布数据集的代码,或者分析 Kaggle 竞赛的解决方案。

我非常尊重分享代码以复制他们的结果的研究人员,以及参与机器学习(ML)竞赛并分享他们的解决方案的人。

有代码总比没有好,但我相信它的可读性还可以提高。

我看到的代码让我想起了我在学术界写的代码。我不喜欢它。这是我进入工业界的原因之一。在现代社会,能够编写代码变得和懂英语一样重要。

成为一个更好的程序员的最好方法是加入一个高编码标准的公司。尽管如此,在这篇博文中,我将谈论当你独自在代码库工作时的情况。

本文的目标读者是研究人员、数据科学家和初级软件开发人员。

成为一个更好的程序员是一个持续的过程。你写的代码越多,你就变得越好。

我不会告诉你如何变得更好,我会告诉你如何通过对你的开发过程做一些简单的调整来让你的代码看起来更好。

简单,我的意思是容易实现,每一步少于 5 分钟,并且改变应该迫使你做得更好。

我们很懒。如果某件事属于“很好做”的范畴,我们会找到很多正当的理由来避免去做。你被迫做的事情会更好。首先,你会去做,因为你没有选择,后来这就变得很自然了。

另一个原因是决策吸意志力。你在一个小决定上花了一点意志力,结果,增加了第二天早上在健身房睡过头的机会。当我们强迫行为时,我们节省了宝贵的能量。对那些感兴趣的人来说,《意志力:重新发现人类最大的力量》一书广泛地讨论了这个话题。

I:使用版本控制来跟踪代码中的变更

对代码进行版本控制看起来似乎是一个显而易见的必备条件,但事实并非如此。在研究生院,我的导师是一个非常聪明的人,他开发了一种算法来执行哈伯德模型的量子蒙特卡罗。世界各地的许多研究人员使用该代码来推进理论凝聚态物理。当我开始使用它时,我很惊讶竟然没有一个集中的存储库。交换密码是通过电子邮件进行的。一位科学家开发的错误修复和新功能没有传播给其他用户。此外,我还见过我的同事如何使用不同的文件夹进行代码版本控制。

代码版本控制和在 GitHub 或其他服务上使用集中的存储库是必须的。许多研究人员正在这样做,但如果你离开计算机科学,大多数教授和研究生都处于用文件夹版本化和在电子邮件中发送代码的阶段。

问:你什么时候需要开始在你的项目中使用 git?
T5 A:从代码的第一行开始。

:什么时候需要在 GitHub 上创建一个资源库,并将代码推送到那里?
答:从第一行代码开始。如果您认为由于法律或其他原因,您的代码不能公开共享,请创建一个私有存储库。在所有其他情况下,选择公开回购。

当人们等到代码看起来不错的时候才公开它,这是一个错误。我的许多同事感到非常不安全,因为他们的 GitHub 库中会有不完美的代码。他们担心人们会认为他们是糟糕的程序员。现实一点,没人会评判你。此外,你现在写的每一个代码在六个月后看起来都会很糟糕。

私有存储库比没有存储库要好。公共存储库比私有存储库更好。

我也喜欢 Kaggle 比赛的参与者在比赛结束后释放管道的方式。这是一个好习惯,对他们和社区都有帮助。

此外,有一个叫做 Sourcegraph 的工具,它允许你在所有公共 Github 库的代码中执行搜索。极其方便。这会让你更有效率。

链接:

第二:不要推到总分行

当你在一个团队中工作时,你不要直接推进到主分支。您创建一个单独的分支,在其中工作,创建一个拉请求(PR),将拉请求合并到主服务器。这比直接推动掌握更复杂。原因是为了合并拉请求,您的更改应该通过各种检查。手动检查是由您的合作者进行的代码审查。自动检查包括语法、风格、测试等。

当您独自工作时,您没有机会审查代码,但是自动检查的力量仍然存在。

重要的是调整 GitHub 上的设置,这样即使你想推送也无法到达 master。正如我们上面讨论的,这可以防止滑倒,节省意志力。

III:使用持续集成/持续交付(CI/CD)系统

经历创建分支和合并的过程是一种开销。主要原因是它允许对代码变更进行检查。设置持续集成系统后,将检查您创建的每个拉式请求,只有在通过所有检查后,才会合并拉式请求。

有许多服务提供 CI/CD 功能。GitHub Actions、CircleCi、Travis、Buildkite 等

我会推荐 GitHub Actions。它是免费的,在私有和公共库上都可以工作,易于设置。

所有这些听起来可能非常复杂,但是实际上,您只需要向存储库添加一个配置文件。

  • 一个简单的例子:我的带有帮助函数的库。我检查代码样式、格式,并运行测试。
  • 复杂示例:在albuminations库中,我们检查语法、代码风格、运行测试、检查自动文档构建,并且我们为不同的 python 版本和操作系统 Linux、Windows、Mac OS 执行这些操作

重要!您需要更改 GitHub repo 中的设置,以便在所有检查都处于绿色区域的情况下,您将无法合并请求。

链接:

四:代码格式器

有许多方法可以格式化同一段代码。

  • 函数之间有多少空格?
  • 代码中的行有多长?
  • 进口的排序是怎样的?
  • 应该用什么样的引号来定义字符串?
  • 等等

有一些工具叫做代码格式化器。如果你在你的代码上运行它们,它们会修改代码以符合格式化程序的要求。

通用类型格式化程序:

  • YAPF:非常灵活,你可以配置它来适应你想要的风格。
  • 黑色:无弹性。只能配置线路的长度。

选择一个并将其添加到您的 CI/CD 配置中。我喜欢黑色的。它让我所有的项目和使用黑色的项目看起来都一样。

代码格式化程序减少了上下文切换,这使得代码的阅读更加容易。

还有更具体的格式化程序。例如 。Isort 只是对导入进行排序。

您需要在两个地方运行格式化程序:

  1. 在 CI/CD 中。在这里,您以检查模式运行它:格式化程序会告诉您有他们想要格式化的文件,但是代码将保持不变。
  2. 在提交更改之前。它会重新格式化你的代码。

链接:

V:预提交挂钩

在上一步中,我们讨论了在提交之前在本地运行格式化程序的重要性。

比如说,我们用异色

我们需要运行:

black .isort

这很烦人。更好的解决方案是用这些命令创建一个 bash 脚本,比如“code_formatter.sh”并运行它。

创建这样的脚本是一种流行的方法,但是问题是,除非你强迫他们,否则人们不会这样做。

有一个更好的解决方案叫做预提交挂钩。这个想法类似于 bash 脚本,但是您希望在每次提交之前运行的东西将会在您提交时准确地运行

git commit -m “<commit message>”

这看起来是一个很小的区别,其实不是。使用预提交,您的行为是强制的,并且,正如我们上面讨论的,它工作得更好。

Q : PyCharm 执行良好的格式化。为什么我需要一个预提交钩子?
A :你可能忘了用 PyCharm 格式化你的代码。此外,当你有两个或更多的人,你要确保他们的格式是相同的。对于预提交挂钩,所有人都将拥有相同的配置,这是您的存储库的一部分。我建议两者都做,使用预提交钩子并用 PyCharm 格式化代码。

问:如果我不从控制台执行提交,而是直接从 PyCharm 执行,会怎么样?
答:您可以配置 PyCharm 在每次提交时运行预提交钩子。

链接:

六:棉绒

不改变你的代码,但是检查它并且寻找可能的问题的工具,叫做 linters。最常见的是 flake8

它可以寻找:

它是一个强大的工具,我建议将它添加到您的 CI/CD 配置以及预提交钩子中。

链接:

VII: Mypy:静态类型检查器

从 Python 3 开始,您可以向代码中的函数添加类型注释。这是可选的,但强烈推荐。

一个原因是有类型注释的代码更容易阅读。

当您在代码中看到:

x: pd.DataFrame

它的信息量远远超过

x

当然,你首先不应该把你的变量命名为“x”。尽管如此,在这篇博文中,我谈论的是改进代码的简单、自动的方法,好的命名比简单要难一些。

类型注释是可选的。没有它们,代码也能很好地工作。有一个叫做 Mypy 的工具可以检查:

  • 函数和输入参数的类型注释
  • 变量类型及其操作之间的一致性

这是一个非常有用的工具。所有大的科技公司都会检查他们 python 代码的每一个 pull 请求。

它迫使你编写更容易阅读的代码,重写过于复杂、写得不好的函数,并帮助你识别错误。

应将 Mypy 检查添加到 CI/CD 和预提交挂钩中。

链接:

VIII:对预提交挂钩进行更多检查

你可以用许多不同的东西来扩展你的预提交钩子。

  • 删除尾随空白。
  • 文件的结尾在新的一行。
  • 排序要求 txt。
  • 检查 yaml 文件的正确格式。
  • 等等

您可以为应该自动发生的代码格式化和检查创建自己的挂钩。

链接:

九:外部工具

使用 ML 来分析每个拉请求的代码的工具有一个活跃的开发领域。

所有这些对公共存储库都是免费的,其中一些对私人存储库也是免费的。我看不出有什么理由不为您的公共代码启用它们。

链接:

结论

如果一个人至少实现了这些技术中的一些,他/她的代码将变得更容易阅读。

但这只是第一步。

还有其他标准技术,如:

  • 单元测试
  • 使用假设的单元测试
  • Python 环境
  • 建筑包装
  • 码头化
  • 自动文档
  • 等等

但是它们不能像我上面描述的步骤那样简单地实施。因此,我们将把它们留给另一个时间。😃

对于那些在实现我所描述的技术时有问题的读者,请随时联系我,我会扩展相应的要点。

熊猫高级索引的本质

原文:https://towardsdatascience.com/nitty-gritty-of-advanced-indexing-in-pandas-9850b2d50220?source=collection_archive---------56-----------------------

为什么多级索引并不像看起来那么令人生畏

奥兹古·奥兹登Unsplash 拍摄的照片

我经常听到这句美丽的名言,

“有时我们看不到眼前的东西”

任何事情都是如此——无论是错误的原因还是错误本身,拼写错误的变量名,没有设置inplace = True,想知道为什么我的数据帧没有改变,等等。不仅仅是错误或打字错误,甚至是功能。我们不认为基本功能是产品的组成部分。熊猫的指数是一个经常被忽视但在数据分析和处理中起着关键作用的东西。

索引、序列和数据帧是 Pandas 的核心数据结构。索引是数据帧中某个位置的标识符或地址。而操作一维和二维索引是最常见的做法。学习处理任意数量的维度有时会非常方便。幸运的是,Pandas 使能够将高维数据使用和存储到一维数据结构(如序列)和二维数据结构(如数据帧)中。这就是众所周知的分级索引、高级索引或多级索引。

在这篇文章中,我将解释现实世界中多级索引的基本操作方法。

首先,我从 Kaggle 获得了这个数据集。数据集包含一些关于汽车的样本数据,如下图所示。

样本汽车数据

繁琐的道:

比方说,我想知道是否有丰田汽车的车身样式是轿车,燃料类型是柴油。

这是我们找到想要的结果的方法之一。如果我们想知道所有车身样式为旅行车的柴油汽车的品牌,并检查其价格是否在 20,000 美元以内,该怎么办?

我们仍然获得了想要的输出,但是代码并不整洁。随着查询变得越来越复杂,代码变得越来越单调和冗长。

高级索引或分层索引:

分级索引可以帮助我们处理任意数量的维度。它可以帮助我们过滤、聚合、组织和操作数据,进行真正强大的数据分析。

1)操纵索引:

让我们从为数据帧设置索引开始。为了创建多索引数据帧,我们向属性index传递一个值列表,而不是一个字符串。我的数据集中有如此多的分类特征,但我将首先考虑make,因为我想知道不同汽车组的详细信息。另外,为了更好的组织,我会考虑body_stylefuel_type

集合 _ 索引

让我们看一下索引,看看它们为我们带来了什么。

多级索引

多索引包含三个不同的属性,即级别、代码和名称。

  • levels属性指的是索引的标签名。索引从左开始排序。在这种情况下,make是最高的索引,其值为level = 0。也可以简称为level = 'make'
  • codes属性指的是编码级别的每个数据点的标签。
  • 属性包含了级别的字符串名称。

行和列都可以有多级索引。我们可以通过简单地将reset_index()函数传递给 DataFrame 来重置索引。

使用多级索引时需要注意的是,在尝试执行任何切片操作之前,先对索引进行排序。切片操作会故意抛出如下所示的警告。

未排序的多索引数据框的警告

我们可以通过将sort_index()函数传递给多索引数据帧来避免这种情况。此外,Pandas 依赖于被排序的索引来进行最优的检索和搜索操作。我们可以使用返回布尔值的index.is_lexsorted()函数来检查索引是否已经排序。

其他有用的功能有

  • swap_level()
  • 堆栈()
  • 拆分()

swap_level()可用于交换数据帧内的级别。它采用两个参数ij,这两个参数是作为字符串传递的级别名称。传递这个函数不会改变值的顺序。

stack()unstack()功能带有一个附加参数,您可以选择堆叠或不堆叠的层级,其中堆叠的层级成为新的最低层级(最右边)。

你可以继续检查官方的熊猫文档来获得更多的索引修改。

2)访问数据:

让我们看看是否可以使用我们的多索引数据框架找到任何车身类型为轿车、燃料类型为柴油的丰田汽车。

  • 使用.loc

。通信线路(LinesofCommunication)

.[loc](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.loc.html)主要用于基于标签的选择,其中标签名称在元组内传递。有时它与pd.IndexSlice结合在一起。例如,查找所有柴油汽车。

警察。索引切片。通信线路(LinesofCommunication)

注意,在pd.IndexSlice内部,第一个:选择所有make的车厢,第二个:选择所有body_style的车厢,而外部的:选择所有列。

  • 使用.xs

。特小号

.[xs](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.xs.html)获取数据帧的特定横截面,其中轴参数默认为零axis=0,并获取一个level参数,该参数指示要使用的级别。

  • 使用.query

。询问

.[query](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.query.html)使用布尔表达式进行过滤或切片。注意查询中使用的andor超过了&|。这是因为查询方法中的表达式是使用[eval()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.eval.html#pandas.eval)函数动态计算的。此外,默认情况下,该方法使用修改后的 Python 语法。

  • 使用get_level_values

获取级别值

[get_level_values](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Index.get_level_values.html)对请求的级别使用标签值的向量。这里,级别值可以作为整数或字符串传递。

更一般地说,locxs用于基于标签的选择,而queryget_level_values有助于生成用于过滤的条件表达式。并非所有这些方法都同样有效,每种方法在不同的情况下效果最好。我们有责任选择最佳的检索方法!

3)汇总数据:

所有内置的数据聚合方法,如mean()min()max()sum()都可以应用于分层数据框架。它与level参数一起传递,该参数影响计算聚合的数据部分。一个简单的例子是找出所有大众汽车的平均价格。

平均价格

使用熊猫索引一直是有趣和好奇的!请随意查看我的 GitHub repo 这里的包含了文章中提到的所有代码。

感谢你一路阅读到这里。如果你有任何问题、反馈或批评,请在评论区告诉我。祝你今天开心!玩的开心!

自然语言处理与图形密切相关

原文:https://towardsdatascience.com/nlp-and-graphs-go-hand-in-hand-with-neo4j-and-apoc-e57f59f46845?source=collection_archive---------6-----------------------

了解如何使用 Neo4j 设置 NLP 管道并分析其结果

准备好,因为今天我们将角色扮演《黑客帝国》中的 Neo。在他得到启示的时刻之后,Neo 意识到,尽管这个世界看起来非常混乱无序,但在所有这些混乱背后隐藏着一个结构化的绿色代码。我们将利用他在混乱中寻找隐藏结构的知识,并将其应用于文本。一旦我们戴上 Neo4j 眼镜,起初可能看起来只是无组织的混乱,很快就会变得非常结构化,充满洞察力。

议程

  1. 设置 Neo4j 桌面
  2. 图形导入
  3. 文本分类
  4. 命名实体识别
  5. 情感分析
  6. 二部网络的单部投影
  7. 社区检测
  8. 数据丰富

设置 Neo4j 桌面环境

这是我们第一次在博客中使用 Neo4j 桌面。可以在 Neo4j 下载中心获得。这是一个 GUI 应用程序,它使本地 Neo4j 数据库的管理更加舒适和方便,因为它提供了只需几次点击就可以启动数据库实例等功能。由于这也可能是您第一次与它交互,我准备了一个简短的指南,介绍如何设置 Neo4j 环境并做好一切准备。

成功安装 Neo4j 桌面后,您应该能够在显示器上看到图形界面。我们将通过点击添加数据库按钮来创建一个新的数据库实例。

选择创建本地图形,设置密码,按创建。我们现在已经成功地实例化了一个新的数据库。下一步是向数据库实例添加插件。单击数据库实例右上角的三个点,并选择管理

转到插件选项卡,安装您需要的插件。对于这篇博文,你将需要 APOC图形数据科学插件。

附言:是的,GDS 图书馆现已推出 Neo4j 4.x 版本

APOC NLP 程序存储在一个单独的文件中,因此,我们必须手动安装它们。我们可以安装任何自定义插件,只需将其复制到插件文件夹。打开如下所示的插件文件夹,将 APOC NLP 依赖关系复制到那里。

APOC 静态值存储器

APOC 允许我们在静态值存储器中存储敏感信息,比如 JDBC 凭证或 API 密钥。可以把它看作是 Neo4j 的环境文件,我们在其中定义了以后可以用 cypher 轻松访问的变量。我们将把 GCP 和 AWS 凭证存储在静态值存储中。第一步是获取 API 凭证:

获得凭证后,我们继续在$Neo4j/conf文件夹中创建apoc.conf。将这三行存储在文件中。

apoc.static.aws.apiKey=$yourAwsApiKey
apoc.static.aws.apiSecret=$yourAwsApiSecret
apoc.static.gcp.apiKey=$yourGcpApiKey

我们现在可以启动 Neo4j 实例,并调查静态存储是否按照查询的预期工作。

RETURN apoc.static.getAll("aws") AS aws;

您应该会看到类似这样的内容:

美国焊接协会

{
  "apiKey": "$yourapiKey",
  "apiSecret": "$yourapiSecret"
}

如果到目前为止您已经成功地完成了所有步骤,那么您应该有一个添加了 APOC NLP 和 GDS 库的 Neo4j 实例在运行。如果您不想设置静态值存储,只需将您的云凭证直接复制并粘贴到查询中即可。

图形导入

我们将使用由 Kevin Toms 提供的新闻数据集。它包含大约 10000 篇新闻文章的内容。该数据集于 2019 年 1 月编制。不幸的是,作者没有提供关于数据集的来源和时间线的信息。在开始之前,我们必须下载数据集并将其复制到导入文件夹。您可以从 Neo4j 桌面访问导入文件夹,如下所示。

我们将每篇文章作为一个单独的节点导入,标题和内容作为节点的属性存储。

LOAD CSV WITH HEADERS FROM "file:///text_summarizer_data.csv" as row
CREATE (a:Article{title:row.title, content: row.content})

用谷歌进行文本分类

我们将从由谷歌的自然语言 API 支持的 APOC 文本分类程序开始我们的分析。它将输入文本分为不同的内容类别。据我所知,它对新闻文章最有效,但对虚构文学不太有效。谷歌每月提供 30,000 个免费分类请求,所以这足够启动一个爱好项目了。

由于我们需要处理 10.000 篇文章,我们将使用apoc.periodic.iterate 过程来处理批处理过程。在文档中了解更多信息。这个过程需要几分钟,所以在你等待的时候,请随意喝杯咖啡或者做你最喜欢的瑜伽姿势。

CALL apoc.periodic.iterate("
   // get all articles
   MATCH (node:Article) RETURN node
  ","
   // classify each article
   CALL apoc.nlp.gcp.classify.graph(node, {
       // we retrieve gcp api key from static value storage
       key: apoc.static.get('gcp.apiKey'),
       // node property that contains the text
       nodeProperty: 'content',
       write:true
    }) YIELD graph RETURN distinct 'done'",
    {batchSize:10})

当你啜饮美味的咖啡时,我们可以看看分类的结果。让我们从查看一些类别名称的例子开始,这样我们就知道我们在处理什么了。

MATCH (n:Category)
RETURN n.name as category
LIMIT 5

结果

类别名称的深度在一至三层之间。级别由斜杠字符(/)分隔。比如"/新闻"只包含一级,而"/金融/保险"包含两级类别。我们将提取每个分类名称的顶级类别,并将其存储回我们的图中。这将使我们能够更直接地根据顶级类别进行筛选和分组。新的图表模式将如下所示:

在 Neo4j 中处理层次树时,我学到了一些规则,可以帮助我们简化和优化查询。其中之一是我们应该在整个树中只有一个单一的关系类型。这样,我们可以很容易地查询一个或两个层次的深度,正如我们将看到的。

让我们为顶级类别节点定义一个惟一的约束。

CREATE CONSTRAINT ON (t:TopCategory) ASSERT t.name IS UNIQUE;

我们可以通过拆分分类名称来提取和存储顶级类别。

MATCH (n:Category)
WITH n, split(n.name,'/')[1] as top_level
MERGE (t:TopCategory{name:top_level})
MERGE (n)-[:CATEGORY]->(t)

让我们通过顶级类别来查看文章的数量。您可以观察到,由于我们在类别树中只处理一种关系类型,所以遍历两个层次非常简单。

MATCH (t:TopCategory)
RETURN t.name as category, 
       size((t)<-[:CATEGORY*2..2]-()) as number_of_articles
ORDER BY number_of_articles DESC LIMIT 10

结果

需要注意的一点是,查询结果显示的文章比图表中实际显示的要多。这是因为有些文章有不止一个分类。我们将通过查看来自科学类别的两篇文章的内容来快速检查结果。

MATCH (t:TopCategory{name:"Science"})<-[:CATEGORY*2..2]-(article)
RETURN article.content as text LIMIT 2

结果

两篇文章似乎都非常关注科学和技术。我们并没有对结果进行深入的分析,但是我们会假设自然语言 API 很好地完成了对新闻文章进行分类的工作。

命名实体识别

本质上,NER 是一个识别文本中各种实体并将它们按类别(如人员、组织、位置等)分组的过程。我们寻找的实体类型完全取决于用例。有时我们想知道在给定的文章中提到了哪些人和组织,而其他时候我们可能更有兴趣知道提到了哪些基因和蛋白质。有很多预先训练好的模型可供你使用,如果没有一个适合你,你可以训练你自己的 NER 模型,但是这超出了这篇博文的范围。让我们看一个在上面的科学文章中找到的命名实体的例子。

显示可视化

我们可以观察到,该模型善于发现文本中的人物和组织,但并不完美。我们真的不能怪它给“Kibble”贴上组织的标签。该模型被训练来识别新闻文章中的人和组织,而不是真正被设计来阅读科学文章。AWS 和 GCP 都在其云 API 组合中提供了自己的 NER 模型。我们将在两个随机的故事中比较它们,并选择更适合我们的用例。

MATCH (node:Article)
WITH node LIMIT 2
RETURN node.content as text

结果

NER 和 GCP

我们将从使用 Google 的自然语言 API 识别命名实体开始。有一个专用的 APOC 过程apoc.nlp.gcp.entities.*,这使得与 API 的交互非常容易。该程序有两种不同的模式:

  • 串流:串流结果
  • 图形:创建一个虚拟图形,并选择性地存储结果

我们将使用程序的图形模式。如上所述,图形模式创建了一个虚拟图形,我们可以用 Neo4j 浏览器来可视化它。通过设置参数write:false,我们不会将结果存储回 Neo4j。

MATCH (node:Article)
WITH node LIMIT 2
CALL apoc.nlp.gcp.entities.graph(node, {
    // Your api key
    key: apoc.static.get('gcp.apiKey'),
    // Property of the node that
    // contains the text
    nodeProperty: 'content',
    // do not store results in graph
    write:false
}) YIELD graph as g
RETURN g

结果

实体类型:

  • 绿色:人
  • 蓝色:数字
  • 橙色:位置
  • 红色:其他
  • 黄色:事件

GCP 发现了五种不同类型的实体。如果我们看看实体类型的人,我们会注意到,在“艾琳·麦肯”之上,GCP 也把“母亲”和“女人”这样的词作为一个人。有趣的是,它将“搜索”识别为一个事件。在我看来,GCP 试图给尽可能多的词贴上标签,这可能是一件好事,也可能是一件坏事,取决于用例。

带 AWS 的 NER

与 GCP 类似,我们也有专门的 APOC 程序apoc.nlp.aws.entities.*用于 AWS NER 请求。

MATCH (n:Article)
WITH n LIMIT 2
CALL apoc.nlp.aws.entities.graph(n, {
    // AWS api key
    key: apoc.static.get('aws.apiKey'),
    // AWS api secret
    secret: apoc.static.get('aws.apiSecret'),
    // Property of the node
    // that contains the text
    nodeProperty: 'content',
    write:false
}) YIELD graph as g
RETURN g

结果

实体类型:

  • 绿色:人
  • 布朗:组织
  • 橙色:日期
  • 红色:位置
  • 黄色:数量
  • 蓝色:商业项目

乍一看,我们可以观察到 AWS 找到的实体比 GCP 少。它也不包括人实体下的“女人”和“母亲”这样的词。我的观点是,如果你试图做某种主题建模,那么 GCP 可能更适合,而对于创建知识图,AWS 可能更好。我们将使用 AWS 来分析和提取数据库中所有文章的实体。因为我们需要批处理我们的 NER 过程,我们将使用apoc.periodic.iterate过程。

CALL apoc.periodic.iterate("
    MATCH (n:Article)
    WITH collect(n) as total
    // Create a batch of 25 articles
    CALL apoc.coll.partition(total,25) 
    YIELD value as nodes
    RETURN nodes
    ","
    CALL apoc.nlp.aws.entities.graph(nodes, {
       key: apoc.static.get('aws.apiKey'),
       secret: apoc.static.get('aws.apiSecret'),
       nodeProperty: 'content',
       relationshipType: 'AWS_ENTITY',
       // store the results to Neo4j
       write:true
    }) YIELD graph
     RETURN distinct 'done'", {batchSize:1})

如果你抓紧时间,在 NER 结束之前,你还有时间做另一个伟大的瑜伽姿势。让我知道进展如何。好了,我们现在可以检查 NER 进程的结果了。我们将从调查文章中提到最多的人开始。

MATCH (n:PERSON) 
RETURN n.text as person, 
       size((n)<-[:AWS_ENTITY]-()) as mentions
ORDER BY mentions DESC LIMIT 10

结果

我们选择 AWS 是因为它不包括 person type 下的“orphan”或“genealogist”这样的词。我想没有一个模型是完美的,因为我们可以看到“项目经理”、“首席执行官”和“总裁”是作为人实体出现的。解决这个问题的一个方法是添加共指解析作为 NER 管道的一个步骤,但是由于我们正在处理第三方 NLP 管道,我们没有这个闲心。现在让我们看看体育文章中提到最多的人。

MATCH (n:PERSON) 
RETURN n.text as person,  
    size((n)<-[:AWS_ENTITY]-()-[:CATEGORY*2..2]->({name:'Sports'})) as mentions
ORDER BY mentions DESC LIMIT 10

结果

所有十大提及的体育名人都是印度板球运动员。Virat Kohli 确实很突出,所以我猜他是队长。这种 NER 提取法的一个弱点是 Virat Kohli 和 Kohli 被视为两个独立的实体。这可以解释,他有时被提到全名,其他时候只提到姓。另一个有趣的用例是查看哪些位置和事件共享了最多的文章。

MATCH (a:Article)-[:AWS_ENTITY]->(event:EVENT),
      (a)-[:AWS_ENTITY]->(location:LOCATION)
RETURN location.text as location,
       event.text as event,
       count(*) as mentions
ORDER BY mentions DESC
LIMIT 10

结果

结果看起来相当不错。看起来像 CES 2019 在拉斯维加斯举行,联合印度在加尔各答举行集会,20 国集团在阿根廷举行论坛,世界经济论坛在达沃斯举行。除此之外,英国和欧盟还在讨论英国退出欧盟问题。

情感分析

AWS 还在其理解 API 包中提供情绪分析。它将文本分为四个不同的情感组:

  • 积极的
  • 中立的
  • 否定的;消极的;负面的;负的
  • 混合的

我们将对所有文章进行情感分析。我认为新闻应该或多或少是中性的,除了体育。有一个特殊的 APOC 程序apoc.nlp.aws.sentiment.*使用与 NER 处理程序相同的两种模式(流&图)处理 AWS 情绪 API 请求。

CALL apoc.periodic.iterate("
    MATCH (n:Article)
    WITH collect(n) as total
    CALL apoc.coll.partition(total,25) 
    YIELD value as nodes
    RETURN nodes
    ","
    CALL apoc.nlp.aws.sentiment.graph(nodes, {
       key: apoc.static.get('aws.apiKey'),
       secret: apoc.static.get('aws.apiSecret'),
       nodeProperty: 'content',
       write:true
    }) YIELD graph
     RETURN distinct 'done'", {batchSize:1})

我们将看看体育文章中被 AWS 理解为积极的人和事件的共同提及。

MATCH (a:Article)
WHERE a.sentiment = 'Positive' AND 
      (a)-[:CATEGORY*2..2]->({name:'Sports'})
MATCH (a)-[:AWS_ENTITY]->(person:PERSON),
      (a)-[:AWS_ENTITY]->(event:EVENT)
RETURN person.text as person,
       event.text as event,
       count(*) as mentions
ORDER BY mentions DESC LIMIT 10

结果

看起来网球运动员正在赢得网球比赛。由 Virat Kohli 担任队长的印度板球队赢得了 2011 年世界杯和墨尔本测试赛。从结果来看,我大概是这么想的。

图形数据科学图书馆

如果你读过我的博客文章,你就会知道我喜欢写关于图形数据科学库的文章。这个博客也不例外。首先,我们将借助节点相似性算法将一个二分网络投影到一个一分网络。在下一步中,我们将使用 Louvain 算法在投影的单分图中搜索社区。

二部网络的单部投影

二分网络只是一种奇特的说法,即图包含两组不同的节点,同样,一个一分网络只包含一组节点。在我们的例子中,我们将从一个包含文章和 NER 实体的双向网络开始。下一步,我们将借助 GDS 的相似性算法,把它投射到一个单片式网络上。这里有一个图表,显示了幕后实际发生的事情。

我们可以把单向投射看作是把间接关系转化为直接关系的过程。相似性算法之间的区别只是用于计算相似性得分或权重的度量。例如,节点相似性算法使用 Jaccard 相似性分数。它被定义为交集的大小除以并集的大小。如果我们愿意,我们也可以投射一个由文章而不是人组成的单部分网络,并检查相似的文章是如何基于其中提到的实体的。

在我们运行任何算法之前,让我们快速回顾一下 GDS 图书馆是如何工作的。

这个形象是善意地借用了 官方文件

图表分析管道由三个主要部分组成。在第一部分中,图形加载器从 Neo4j 中读取存储的图形,并将其作为内存中的投影图形加载。我们可以使用本机投影cypher 投影来加载投影图。第二步,我们按顺序执行图算法。我们可以使用一个图算法的结果作为另一个图算法的输入。最后但同样重要的是,我们将结果存储或流回 Neo4j。

我们将使用 cypher 投影来加载内存中的图形。如果你需要快速复习一下它是如何工作的,我建议你看一下官方文档。在 node 语句中,我们将描述顶级新闻类别中的所有文章以及所有 person 实体。在关系陈述中,我们将描述新闻文章和人实体之间的所有链接。

CALL gds.graph.create.cypher("person_similarity",
 // match articles that are in the 'News' category
 "MATCH (a:Article) WHERE (a)-[:CATEGORY*2..2]->({name:'News'})
  RETURN id(a) as id, labels(a) as labels
  UNION
  // match all person entities
  MATCH (p:PERSON) RETURN id(p) as id, labels(p) as labels
  ","
  // match all links between news articles and person entities
  MATCH (a:Article)-[r:AWS_ENTITY]->(p:PERSON) 
  WHERE (a)-[:CATEGORY*2..2]->({name:'News'})
  RETURN id(p) as source, id(a) as target, type(r) as type")

下一步是在节点相似性算法的帮助下推断人实体之间的相似性网络。我们可以用以下三个参数来影响相似性网络的稀疏或密集程度:

  • DegreeCutoff:算法必须考虑的节点的最少链接数
  • similarityCutoff:仍被视为相似的一对节点之间的最小相似性得分
  • topK:对每个节点相似关系数量的限制

通常,我们很少或根本不知道图会有多稀疏。我们绝对不想以一个完整的图结束。我们可以用算法的stats模式来评价相似度网络。这样,在对上述三个参数进行微调之前,我们不会存储或改变任何结果。

CALL gds.nodeSimilarity.stats('person_similarity')
YIELD nodesCompared, similarityDistribution
RETURN nodesCompared as nodes,
       apoc.math.round(similarityDistribution.min,2) as min, 
       apoc.math.round(similarityDistribution.p25,2) as p25, 
       apoc.math.round(similarityDistribution.p50,2) as p50,
       apoc.math.round(similarityDistribution.p75,2) as p75,
       apoc.math.round(similarityDistribution.p90,2) as p90,
       apoc.math.round(similarityDistribution.mean,2) as mean

结果

乍一看,节点似乎不是很相似。这很好。我们想推断一个稀疏网络,因为社区检测算法在非常密集的图上表现不佳。确定最佳的相似性参数值需要艺术和科学的结合,但是有了一些经验,你会变得很擅长。我们将把similarityCutoff设置为 0.6,同时将degreeCutofftopK参数保留为默认值。使用mutate模式,我们将算法的结果存储回内存中的投影图。

CALL gds.nodeSimilarity.mutate('person_similarity', 
    {degreeCutoff:1, similarityCutoff:0.6, topK:10,
     mutateRelationshipType: 'SIMILAR', mutateProperty: 'score'})

社区检测

社区检测算法旨在帮助我们理解复杂网络的结构。最明显的应用是在社交网络中寻找朋友群体。我们认为社区是一组紧密相连的节点,类似于一群朋友是如何高度互联的。让我们看看一些社区结构的可视化,以获得更好的理解。

这是我几年前做的一个可视化,当时我正在分析漫威宇宙中的社区结构。节点的颜色表示组从属关系。我们可以观察到,社区由高度互连的节点组成,这些节点与其他集群的链接较少。在这篇博文中,我们将使用 Louvain 算法来检查我们推断的相似性网络的社区结构。

CALL gds.louvain.stream('person_similarity', 
    {nodeLabels:['PERSON'], relationshipTypes:['SIMILAR']})
YIELD nodeId, communityId
RETURN communityId, 
        collect(gds.util.asNode(nodeId).text) as members
ORDER BY size(members) DESC LIMIT 5

结果

发现的社区相对较小。这是similarityCutoff参数值的直接结果。如果我们选择一个较低的阈值,更多的节点将被认为是相似的,我们可能会得到更大的社区。同样,如果我们增加数据集的规模,多处理几千篇文章,我们也会得到更大的社区。也就是说,是时候进入数据丰富的章节,为我们的实体添加一些上下文了。

数据丰富

我们在图表中发现了几个小社区。有些人相当有名,不难找到社区成员之间的共同点。例如,我知道哈里森·福特、哈莉·贝瑞和吉姆·帕森斯都是演员,所以我会假设其他人也是演员。我们可以去谷歌一下。一个更好的想法是,使用外部数据提供者,如 Google Knowledge GraphWikiData ,有计划地丰富我们图表中的实体。这正是我们下一步要做的。

我们将只充实在前一个查询中返回的人员(前五个最大社区的成员)。为了避免多次运行社区检测,我们将首先把 Louvain 算法的结果存储回 Neo4j。

CALL gds.louvain.write('person_similarity', 
    {nodeLabels:['PERSON'], relationshipTypes:['SIMILAR'], 
     writeProperty:'louvain'})

谷歌知识图

很久以前我已经在我的一篇博客文章中使用了谷歌知识图 API。我写作的原因之一是我有一个有用的 cypher 查询库,我可以从中复制粘贴并在以后的分析中使用。

我们将使用知识图 API 通过描述和详细描述属性来丰富最大社区的成员。

// get the members of the top five communities
MATCH (p:PERSON)
WITH p.louvain as communityId, collect(p) as members 
ORDER BY size(members) DESC LIMIT 5
UNWIND members as member
WITH member, apoc.text.urlencode(member.text) as name, 
     apoc.static.get('gcp.apiKey') as key
// send a request to KG API
CALL apoc.load.json("https://kgsearch.googleapis.com/v1/entities:search?query=" + 
     name + "&key=" + key + "&limit=1&indent=True")  YIELD value
WITH member, value['itemListElement'][0]['result'] as results
// store results back to Neo4j
SET member.kg_description = results.description,
    member.kg_detailed_description = results.detailedDescription.articleBody

现在让我们来看看最大的五个人群,包括他们的知识图表描述。

MATCH (p:PERSON)
RETURN p.louvain as communityId, 
       collect(p.text) as members,
       collect(DISTINCT p.kg_description) as description 
ORDER BY size(members) DESC LIMIT 5

结果

随着丰富描述的增加,我们对谁是社区成员有了更好的认识。我们可以观察到最大的集群由网球运动员组成。知识图表没有识别第二大组的任何成员。然而,它知道“乌鲁比亚”实际上是印度的一个城市,而不是一个人。

维基数据浓缩

我订阅每周一期的 twin4j 开发者简讯的主要原因是我可以从其他人那里复制粘贴密码查询。马克·李约瑟做了一个关于如何用密码查询维基数据的系列。他做了所有的艰苦工作,所以我们可以通过复制粘贴他的密码查询来享受他的劳动成果。他还开发了我们刚刚使用的 APOC NLP 程序,这是对 Mark 的称赞!

对于那些以前从未听说过 Wikidata 的人来说,他们将自己描述为一个自由开放的知识库,可以被人类和机器阅读和编辑。检查了一下之后,我可以说它的信息非常丰富,绝对值得一看。我们将向最大社区的成员添加出生日期、职业和国籍信息。查看维基数据查询服务了解更多关于数据丰富选项的细节。

CALL apoc.periodic.iterate(
  // get all persons from the biggest five communities
  "MATCH (p:PERSON) 
   WITH p.louvain as communityId, 
          collect(p) as members 
          ORDER BY size(members) DESC LIMIT 5
   UNWIND members as member
   RETURN member
   ","
    // prepare a sparql query
    WITH 'SELECT *
    WHERE { ?person
                  rdfs:label \"' + member.text + '\"@en ;
                  wdt:P569 ?dateOfBirth ;                
                  wdt:P106 [ rdfs:label ?occupation ] ;
                  wdt:P27 [ rdfs:label ?countryName ] .
           filter(lang(?countryName) = \"en\" && lang(?occupation) = \"en\")
           }' AS sparql, member
    // make a request to wikidata
    CALL apoc.load.jsonParams(
      \"https://query.wikidata.org/sparql?query=\" + apoc.text.urlencode(sparql),
      { Accept: \"application/sparql-results+json\"},
      null
    )
    YIELD value CALL apoc.do.when(
      // if there are any results
      size(value.results.bindings) > 0,
      // store results
      'WITH value.results.bindings[0] AS result, member
       SET member.dateOfBirth = date(datetime(result.dateOfBirth.value)),
           member.wikidataImportDone = true
       // store nationality
       MERGE (c:Country {name: result.countryName.value })
       MERGE (member)-[:NATIONALITY]->(c)
       // store occupation
       MERGE (o:Occupation {name: result.occupation.value})
       MERGE (member)-[:HAS_OCCUPATION]->(o)
       RETURN member',
      // else if no results 
      'SET member.wikidataImportDone = true RETURN member',
      {value: value, member: member})
    YIELD value AS result
    RETURN count(*)",
  {batchSize: 20})

现在让我们来看看最大的社区,包括我们从维基数据获得的额外信息。

MATCH (p:PERSON) 
RETURN p.louvain as communityId,
       collect(p.text) as members,
       apoc.math.round(avg(duration.inMonths(p.dateOfBirth, date()).years),2) as average_age,
       collect(distinct [(p)-[:NATIONALITY]->(n) | n.name][0]) as nationalities,
       collect(distinct [(p)-[:HAS_OCCUPATION]->(o) | o.name][0]) as occupations
ORDER BY size(members) DESC LIMIT 5

结果

结果看起来令人印象深刻。我打赌你不知道至少有两个人叫吉姆·帕森斯。其中一个是演员,另一个是赛车手。我们只是触及了维基数据 API 提供的信息的表面。

结论

如果你还在这里,我向你致敬。这是我迄今为止最长的一篇博文。尽管有时感觉就像我在写一本迷你书或我那本不存在的书的一个章节,但我很高兴,因为我认为它真的很好,我在这个过程中学到了很多。我希望你也是。如果你喜欢它,并希望我写更长的帖子,请让我知道。同时,你可以下载 Neo4j 并开始开发你自己的 NLP 管道。别忘了订阅 Twin4j 简讯

代码可在 GitHub 上获得。

数据匿名化的定制 NLP 方法

原文:https://towardsdatascience.com/nlp-approaches-to-data-anonymization-1fb5bde6b929?source=collection_archive---------6-----------------------

消除真实世界私人数据身份的实用方法

随着互联网服务变得无处不在,对互联网隐私的渴望持续增长。近年来,不同的法律,如 GDPR,开始规范服务收集私人信息的方式。这引起了每个公司对隐私方面的关注,并增加了在处理和匿名私人数据方面的投资。

我在微软商业软件工程(CSE)团队的工作是与微软最具战略意义的客户合作。我们共同开发人工智能、大规模数据、物联网等领域的新工作负载。在与这些客户打交道的过程中,我们意识到 PII(个人身份信息)问题是许多希望扩展其解决方案集(无论是内部部署还是在云中)的公司反复提到的话题和障碍。

因此,我们决定创建 Presidio ,这是一个生产就绪的开源服务,免费提供给任何希望解决数据隐私问题的人。

Presidio 允许任何用户创建标准且透明的流程,用于匿名化结构化和非结构化数据上的 PII 实体。为此,它公开了一组预定义的 PII 识别器(用于姓名、信用卡号和电话号码等常见实体),以及一些工具,用于使用新的逻辑对其进行扩展,以识别更具体的 PII 实体。在这篇博文中,我们将关注如何利用自然语言处理来识别不同类型的私有实体。

PII 探测过程

Presidio 利用了一组识别器,每个识别器都能够检测一种或多种语言中的一个或多个 PII 实体。图 1 中描述的过程通常包括 8 个不同的步骤:

  1. 从用户处获取匿名化请求
  2. 将请求传递给预识别分析器以识别 PII 实体
  3. 提取自然语言处理特征(词条、命名实体、关键词、词性等。),供各种识别器使用
  4. 获取所有 PII 识别器(预定义+来自识别器存储服务的自定义)
  5. 运行所有识别器
  6. 汇总结果
  7. 传递给预识别匿名器进行身份识别
  8. 将去标识的文本返回给呼叫者

图 1——presi dio中识别过程的动画

图 2 中的动画演示了一个特定示例的相同过程。请注意,当我们将上下文从“电话号码”更改为“pool card number”时,电话号码识别器的可信度会降低。这是 Presidio 演示的截图。看看这个

图 2 —输入和输出示例

数据匿名的 NLP

需要 PII 识别器来检测自由文本中不同类型的实体。对于这样的任务,不同的 NLP 方法浮现在脑海中:

  • 对于共享一个模式的实体,我们可以利用周围单词的正则表达式验证(例如校验和)和上下文。例如,这种逻辑可以用来检测信用卡号或电话号码。
  • 对于有限的选项列表,我们可以使用黑名单。它可以是静态黑名单(例如,所有头衔:先生、女士、小姐、博士、教授……)或动态黑名单(即,连接到数据库并查询所有可能的选项)。
  • 对于可以使用特定逻辑识别的实体,我们可以编写基于规则的识别器。
  • 对于需要自然语言理解输入的实体,我们可以训练机器学习模型,特别是针对命名实体识别 (NER),或者使用预先训练好的模型。

在下一节中,我们将重点介绍我们在提高人名、地点和组织的命名实体识别率方面所做的工作。

人名、地点和组织的 NER

为了提高这三个实体的检测率,我们用不同的模型进行了实验。以下部分描述了使用的数据集、评估的不同模型和结果。运行这个过程的代码可以在我们的 GitHub repo for research 上找到。

数据集

虽然有一些标注数据集可用,但我们希望增加名称、组织和位置的覆盖范围。因此,我们从一个带标签的数据集开始(例如, OntoNotesCoNLL-2003 ),并对其进行处理以提取模板。这些例子后来被用来生成比原始数据集具有更广泛的实体值(名称、组织和位置)的新句子。

比如来自句子“谢谢你 乔治 !”,其中 George 被手动标记为 person,我们提取了以下模板:“谢谢[PERSON]!”。图 3 提供了另一个例子:

图 3 —数据扩充示例

我们使用了一个假的 PII 数据集和多个假的 PII 生成器来对实体进行采样并创建新的句子。这些句子在生成过程中被自动标记,因此训练新的 NER 模型很容易应用。

然而,这一过程要求我们对数据集进行一些预处理,并针对不同的问题提出创造性的解决方案。仅举几个例子:

  • 如何看待国家vs国籍?在许多情况下,“位置”实体指的是国籍(或民族男子或民族女子)。例如,在句子“萨尔瓦多[LOC]拳手赢得世界冠军”中,我们不能用“埃塞尔比亚”替换“萨尔瓦多”,因为这会使句子不正确。因此,我们为国家、民族、民族-男人和民族-女人创造了新的中间实体。
  • 性别应该如何处理?有些句子最初谈论的是男性或女性,但在数据生成过程中,我们可能会用异性的名字替换一个名字。
  • 现实生活中的知识重要吗?如果原句描述的是两个国家之间的冲突,是不是就应该用任意的国名来代替这些国家?
  • 数据集中的一些人名是机构或组织的名称,如“艾伦人工智能研究所”或“特朗普政府”。在这种情况下,我们是否应该用一个任意的名字来代替“特朗普”?

从 8000 个独特的模板中,我们提取了 80000 个不同的标记句子。我们还获得了比以前更干净的数据集,因为在这个过程中处理了许多未标记的实体。新数据集被分成训练/测试/验证集,来自同一模板的样本不会出现在多个集中。此外,我们将 10%的样本设为小写,因为这通常代表了部署模型时我们可能遇到的小写文本的比例。据我们所知,这是迄今为止最大的 PII 数据集

模型

评估了不同的建模方法。具体来说,我们研究了条件随机场、基于空间的模型和基于天赋的模型。

spaCy: spaCy 是一个生产级的 NLP 库,用于标记化、词性标注、实体提取、文本分类等。它包含了一个卷积神经网络模型,被认为是最快的深度学习 NLP 模型。虽然其他模型在公共数据集上具有更高的准确性,但它们可能需要更长的训练和推理时间。spaCy 还提供了快速标记化和词条化,用于 Presidio 中的上下文分析模块。我们评估了不同风格的空间:首先,我们查看了预训练空间模型(2.1.0 和 2.2.0)的结果,然后,我们查看了预训练空间模型的微调,最后,在利用预训练单词嵌入(FastText)的同时,从头开始训练空间模型。

Flair: Flair 是一个深度学习 NLP 工具包,在公共数据集上有很好的结果。它建立在 PyTorch 之上,具有特殊的嵌入技术(称为 Flair 嵌入)和预测模型。此外,它还提供了与其他嵌入模型(如 BERT、ELMo)的轻松集成,以及来自不同模型和来源的嵌入的堆叠。我们评估了两种不同的基于 Flair 的模型:具有 BERT 嵌入的 Flair 模型,以及具有 Flair 嵌入和手套嵌入的堆叠的 Flair 模型。

条件随机场(CRF):CRF 是一类用于序列标记的方法。这些有区别的图形模型学习预测之间的依赖性,并且是命名实体识别任务的自然适合。在引入递归和卷积神经网络之前,CRFs 在公共数据集上的 NER 任务上取得了最先进的性能。它们在训练和预测方面比基于神经网络的模型快得多,并且提供相对可解释的结果。我们使用 L-BGFS 优化,使用 sklearn-crfsuite Python 包,只评估了普通的 CRF 模型。

总之,以下是我们试验过的模型:

  1. 使用默认的预训练模型进行评估:

2.从头开始训练:

  • 条件随机字段 (CRF)

3.使用预训练嵌入进行训练:

  • 带有快速文本嵌入的空间
  • 天赋伯特嵌入
  • 天赋手套天赋嵌入

4.微调现有的已训练模型:

  • 版本 2.2.0

韵律学

我们关注 PII/诺-PII 二元决策的 F2(回忆比精确更重要)。我们还研究了特定的 F2 类和计算性能。最后,可解释性是需要考虑的另一个因素。

结果

如图 4 所示,所有模型都取得了不错的结果,但基于 Flair 的模型更胜一筹。

图 4 —各种模型和实体的 F2 结果

来自这些结果的一些见解:

  • 基于 Flair 的模型比基于 spaCy 的模型获得了更高的结果,基于 spaCy 的模型在所有实体上获得了比 CRF 更高的结果。
  • 我们可以看到 spaCy 2.2.0 比 2.1.0 提供了更好的结果,但并没有太多。
  • spaCy 和 CRF 模型与 Org 实体相冲突,Org 实体经常与人名相混淆。Flair 模型在 Org 上实现了更高的结果,这可能暗示对 Org 生成的假 PII 实体的过度拟合。
  • 训练空间模型或对其进行微调无法提高模型的 F2 分数。这可能是由于训练集的性质,它是从 spaCy 最初训练的同一数据集(OntoNotes)中导出的。其他数据来源可能会从微调或训练这些模型中受益。

计算性能

虽然 Flair 模型获得了更高的 F2 分数,但是它们的训练和预测速度也慢得多。表 1 显示了使用各种评估方法的近似训练和推理时间。分析是在一台 GPU 机器【1】上进行的。

表 1 —不同模型的推理和训练时间

【1】Azure 上的 NC6 实例:6 个 vCPU,56GiB 内存,半个 NVIDIA Tesla K80,GPU 内存 12GiB

结论

在这项工作中,我们评估了各种模型在 Presidio 中更好的检出率。我们考虑了检测率和计算性能之间的权衡,这在许多用例中是至关重要的。对于我们评估的数据集,我们发现没有实际的理由来替换我们在 Presidio 中使用的当前空间模型。然而,可以将数据扩充框架和不同的评估模型应用于新数据,并使 Presidio 面向更多特定领域的数据集。我们还看到,通过用 CRF 模型代替 spaCy,我们可以潜在地提高 Presidio 的运行时间。如果性能不是问题,例如对于离线作业,我们应该考虑使用基于 Flair 的方法,可能使用 Flair 嵌入+手套,以提高 Presidio 中的检测率。

Presidio 是完全开源的,对任何希望解决数据隐私问题的人都是免费的。我们也欢迎贡献者,拉请求或任何类型的反馈。点击这里开始

了解更多信息

  1. Presidio 的 GitHub 回购
  2. 通用 Presidio 文档
  3. 研究、数据集创建和建模代码

其他参考文献

  1. 空间
  2. 天赋
  3. 假名字生成器
  4. 骗子

关于作者

Omri Mendels 是微软的高级数据科学家。你可以在 LinkedInGitHub 或者 Quora 上和他联系。

基于自然语言处理的信息检索系统

原文:https://towardsdatascience.com/nlp-based-information-retrieval-system-answer-key-questions-from-the-scientific-literature-b8e5c3aa5a3e?source=collection_archive---------13-----------------------

回答科学文献中的关键问题

来源:https://www . FDA . gov/food/food-safety-during-emergencies/food-safety-and-coronavirus-disease-2019-新冠肺炎

在这篇文章中,我们将了解如何用文本数据构建一个推荐系统。这里的文本数据由关于新冠肺炎、SARS-COV-2 和相关冠状病毒的学术文章组成。该数据集被称为 CORD-19,由白宫和一个领先的研究团体联盟准备。这个免费提供的数据集提供给全球研究界,以应用自然语言处理和其他人工智能技术的最新进展,产生新的见解,支持正在进行的抗击这种传染病的斗争。由于新型冠状病毒文献的快速增长,使得医学研究界难以跟上,因此对这些方法的需求越来越迫切。

1.先决条件

对于这个帖子,我们将需要 Python 3.6spacyTensorflowNLTKDask ,我们将在需要时逐步安装它们。

2.数据集描述

这里使用的数据集来自 Kaggle 竞赛。数据集包含 doc_id、源、标题、摘要和正文。doc_id 是文档 id,source 是像 biorxiv 一样从哪里提取论文的地方,abstract 是论文的摘要,text body 是研究论文的正文或内容。

3.任务

我们的任务是基于以下问题检索信息。

任务 1(新冠肺炎开放研究数据集挑战(CORD-19))

  • 关于传播、潜伏期和环境稳定性有哪些已知信息?
  • 关于该病毒的自然史、传播和诊断,我们知道些什么?关于感染预防和控制,我们学到了什么?

具体来说,我们想知道文献报道的是什么:

  • 该疾病在人类中的潜伏期范围(以及这如何随年龄和健康状况而变化)以及个体在多长时间内具有传染性,即使在康复后。
  • 无症状传播的流行率(例如,特别是儿童)。
  • 传播的季节性。
  • 冠状病毒的物理科学(例如,电荷分布、对亲水/疏水表面的粘附、环境生存,以告知受影响区域的净化工作,并提供有关病毒脱落的信息)。
  • 在多种底物和来源(如鼻涕、痰、尿、粪便、血液)上的持久性和稳定性。
  • 病毒在不同材料(如铜、不锈钢、塑料)表面的持久性。
  • 病毒的自然史和从感染者身上的传播
  • 实施诊断和产品以改善临床流程
  • 疾病模型,包括感染、疾病和传播的动物模型
  • 监测病毒表型变化和潜在适应性的工具和研究
  • 免疫反应和免疫
  • 卫生保健和社区环境中预防二次传播的运动控制策略的有效性
  • 个人防护设备(PPE)的有效性及其在卫生保健和社区环境中降低传播风险的有用性
  • 环境在传播中的作用

4。流程

4.1 导入所需的库

4.2 加载数据集

4.3 EDA

探索性数据分析(EDA)是数据分析师熟悉其数据以推动直觉的过程。这个过程通常利用描述性统计和可视化。作为数据科学家或 NLP 专家,可视化地表示文本文档的内容是文本挖掘领域中最重要的任务之一。然而,在可视化非结构化(文本)数据和结构化数据之间存在一些差距。

首先理解数据并尝试从中收集尽可能多的见解是一个很好的做法。EDA 就是在数据被弄脏之前,理解手头的数据。

让我们安装一些必需的包并导入它们。我们将使用科学空间进行分析。 scispaCy 是一个 Python 包,包含用于处理生物医学、科学或临床文本的 spaCy 模型。

照常导入它们!!

空间语言处理流水线

当您在一个文本上调用nlp时,spaCy 首先对该文本进行标记以产生一个Doc对象。然后在几个不同的步骤中对Doc进行处理——这也被称为处理流水线默认模型使用的管道由标记器、解析器和实体识别器组成。每个管道组件返回处理过的Doc,然后传递给下一个组件。

资料来源:https://spacy.io/usage/processing-pipelines/

  • 记号赋予器:将文本分割成记号。
  • 标签:分配词性标签。
  • 解析器:分配依赖标签。
  • ner :检测并标记命名实体。

处理流水线总是依赖于统计模型及其能力。例如,如果模型包括对实体标签进行预测的数据,则管道只能包括实体识别器组件。

注意:您可以创建自己的管道组件,以便进一步处理

现在,创建一个函数来清理数据,这将删除所有的停用词,标点符号,多余的空格,网址,电子邮件和货币。有时动词、副词、代词不需要,可以去掉。这个函数将返回 word 的基本形式,这就是所谓的词汇化。

频率图

4.3.2 词云

4.4 预处理

4.4.1 从文本中提取所有缩写和完整形式

文本包含许多缩写和完整形式,这个代码用于提取文本中的所有缩写和各自的完整形式,并将其放入字典中,其中键是缩写,值是完整形式。

现在,我们需要创建一个函数,将所有缩写替换为它们各自的完整形式。

同样,我们将创建删除电子邮件 id,网页链接,论文参考,多余的空格,不需要的字符等功能。

4.4.2 删除电子邮件 Id

4.4.3 移除网络链接

删除引用

4.4.5 删除幽灵字符

4.4.6 拆除支架

4.4.7 删除多余的空格

4.4.8 实施 Dask 以实现快速处理和更好地利用 CPU

在这里,我们将使用 Dask 进行处理,Dask 是 python 中一个灵活的并行计算库,在大于内存的数据集上提供多核执行。

“Dask 为分析提供高级并行性,为您喜爱的工具提供规模化性能”——https://dask.pydata.org/en/latest/

现在,调用上面的函数来预处理文本

4.5 使用 USE 进行单词嵌入

该模型针对大于单词长度的文本进行训练和优化,例如句子、短语或短段落。它在各种数据源和各种任务上接受训练,目的是动态适应各种各样的自然语言理解任务。输入是可变长度的英文文本,输出是一个 128 维的向量。通用语句编码器模型用深度平均网络 (DAN)编码器训练。

让我们安装需要使用的软件包

从模型的 URL 加载模型

现在,把研究论文的正文用新的一行分割成单独的段落,这样我们可以为每个段落创建嵌入。例如,如果一个文本有 100 个段落,那么我们将得到这 100 个元素的列表。

将每行文本的不同段落列表转换为一个列表

4.5.1 创建嵌入(深度学习)

现在创建嵌入

这将返回 nx128 形状的张量对象,其中 n 是段落或句子的数量,因为句子的数量是 1052935,因此张量的形状将是 1052935x128

TensorShape([1052935, 128])

4.6 余弦相似性

在数学上,它测量的是在多维空间中投影的两个向量之间的角度余弦。在这个上下文中,我所说的两个向量是包含两个文档嵌入的数组。

xy 为两个向量进行比较。使用余弦度量作为相似性函数,我们有

其中| ||x| |是向量 x=(x1,x2,…,xn)的欧氏范数,定义为 x12+x22+⋯+xn^2.从概念上讲,它是向量的长度。同样,| ||y| |是向量 y 的欧氏范数。该度量计算向量 xy 之间的角度余弦。余弦值为 0 表示这两个向量互成 90 度(正交)且不匹配。余弦值越接近 1,角度越小,向量之间的匹配度越大。

余弦相似性是有利的,因为即使两个相似的文档由于大小而相距欧几里德距离很远,它们之间仍然可以有较小的角度。角度越小,相似度越高。

请参考链接查看更多关于余弦相似度的信息。

4.7 推荐文本

这个函数基于查询从语料库中提取信息。它计算查询与所有段落或句子的余弦相似度,将其标准化以固定其范围 b/w 0 到 1,并基于阈值返回句子。

4.8 任务结果

4.8.1 潜伏期

输出:

['statements of incubation period and sources of original incubation period data for', ' the incubation period of yellow fever is around 3-6 days. the incubation period of dengue fever is around 8-10 days.', ' the incubation period of lassa fever ranges from 3 to 21 days. symptoms of new world haemorrhagic fever typically develop over 7-14 days.',
 ]

传输

输出:

 ' determination of the dynamics of disease transmission in geographically widespread areas global spread of foot-and-mouth disease; spread of newcastle disease virus in asia distinction between pathovars and nonpathovars pathogenic and nonpathogenic escherichia coli in petting zoos addressing hospital and institutional infectious disease problems',' respiratory viruses detected in outbreaks in institutions reflect those known to be major causes of acute respiratory disease in the community; prevalence varies based on geographic location, season, and detection methods . free access to such institutions by members of the community , in conjunction with communal close quarters of residents, creates an ideal environment for propagation of viral respiratory outbreaks .', ' incidence of infection within a community social economic status of the community season per capita water use time of day age distribution within the community chronic infections table 2 concentration of enteric viruses in feces.']

4.8.3 环境在传播中的作用

输出:

[' disease control efforts can also make it challenging to determine effects of climate change on disease. for instance, if climate change causes range shifts of parasites from tropical to temperate countries, this might result in an overall reduction, rather than increase, in human diseases because temperate countries often have superior health infrastructures . regardless of the outcome of climate change on diseases, integrating control efforts into projections should improve predictions of future disease risk for humans and wildlife. furthermore, given that control measures could obscure increases in transmission, incorporating control measures into models could reveal underlying increases in disease risk that might otherwise be missed.', ' environmental variables can affect responses of mice in experimental situations. changes in respiratory epithelial physiology and function from elevated levels of ammonia, effects of temperature and humidity on metabolism, effects of light on eye lesions and retinal function, and effects of noise on neurophysiology are examples of complications that can vary with the form of insult and the strain of mouse employed. ', ' effects of meteorological factors on transmission. climate change can influence the occurrence and spread of infectious diseases through its effect on transmission. for example, climate change can cause air pollution and shortages of food and clean water , leading to changes of high-incidence areas and outbreak patterns, thereby affecting the occurrence and spread of infectious disease.', ' future studies that focused on other components of air pollution and environmental factors are necessary to more fully understand the possible impact on infectious disease transmission . studies are in need to establish the relationships between particle attachment and survival of influenza virus, and also methods should be developed to quantify airborne influenza virus and measure the concentration of influenza virus in ambient air especially for extremely low virus concentrations . we set the number of cases to zero on hot days due to there being no significant effect of pm 2.5 on influenza incidence on hot days .']

4.8.4 传播的季节性

输出:

[' seasonal patterns were observed for hmpv, rhinovirus, enterovirus and influenza viruses with peak prevalence in late winter and spring . in addition, a seasonal pattern was detected for tuberculosis . no distinct seasonal patterns were observed for other microbes.',
 'not disperse low pathogenic avian influenza virus during autumn migration .', 'the severity of seasonal influenza epidemics is unpredictable and influenced by the predominant circulating virus strains and level of immunity in the population . during peak community influenza activity, hospitals and emergency rooms may be overwhelmed by patients presenting with influenza-like illness and more severe disease , . illness attack rates may be higher among most age groups during pandemics than observed for seasonal influenza due to limited immunity among exposed populations . the re-emergence of highly pathogenic avian influenza a virus among poultry with sporadic transmission to exposed persons and the resulting high mortality has stimulated global influenza pandemic preparedness .',' the two gastrointestinal viruses in the study both also presented with winter seasonality, often with norovirus preceding rotavirus epidemics . norovirus and influenza a virus epidemics usually overlapped, but the norovirus epidemics had broader peaks, and numbers tended to start increasing earlier than influenza a virus diagnoses levels and decreased after the disappearance of influenza a virus. also, rotavirus outbreaks usually occurred before influenza a outbreaks started.','influenza viruses circulate in temperate climates from early autumn to late spring, and in tropical climates throughout the year with unpredictable peaks, usually occurring during the wet season and cooler months. routine surveillance for influenza and influenzalike illness can provide estimates of the relative severity of influenza seasons, and can also provide clinical specimens from which influenza viruses can be detected. this allows comparison of circulating influenza strains with vaccine strains in the current influenza season, and may provide potential vaccine strains for future seasons.]

4.8.5 冠状病毒的物理学

(例如,电荷分布、对亲水/疏水表面的粘附、环境存活,以通知受影响区域的净化工作并提供关于病毒脱落的信息)。

输出:

[' antiadhesive surfaces target microbial adhesion usually by the interaction of antagonist physicochemical properties. easy-clean surfaces that are hydrophobic repel bacteria better than glass-coated controls , while hydrophilic surfaces favour water sheeting and subsequent cleaning. similarly, polyethylene glycol coated surfaces promote a hydrophilic interaction against bacteria, preventing attachment . the use of diamond-like carbon films has already been tried for medical implanted devices such as joint prostheses and stents in order to repel microbial adhesion . despite being non-toxic and appealing, the lack of biocidal properties may turn discouraging a more generalized implementation of such easy-clean technologies.', ' in vitro testing compared the adhesion of representative proteins, prokaryotes, and eukaryotes on nanostructured and flat si3n4 surfaces with lysine-coated glass slides as positive controls. flat si3n4 is moderately hydrophilic and known to vigorously promote cell adhesion and proliferation due to increased adsorption of proteins when compared to more hydrophilic surfaces 33,34\. hence, we further increased the hydrophilicity of the si3n4 surface by varying the aspect-ratios of the nanostructures from 0.15 to 0.90 and systematically controlled surface hydrophilicity . once strong hydrophilicity is achieved , a nanostructure-mediated aqueous barrier forms on the surface and limits protein adsorption and cell adhesion to provide an anti-adhesion property 6,35,36.', ' for htcc nanofibers to become an adsorptive membrane material, the fibers must not dissolve in water. crosslinking of polymer structures is a common method to impart membrane stability in water soluble polymers. 21 pva fibers were crosslinked with maleic anhydride to create a filtration membrane. 22 htcc blended with polyvinyl alcohol was photo-crosslinked to impart antimicrobial resistance to the fibers. 10 glutaraldehyde vapor was used to crosslink htcc-pva fibers to create an antimicrobial surface. 7 here, we demonstrate that htcc nanofibers can be crosslinked while retaining their nonwoven structure and their ability to bind to negatively-charged viruses. we have explored the crosslinking conditions that give the greatest water stability. these conditions allowed for high virus removal. our model viruses include the non-enveloped porcine parvovirus , one of the smallest known mammalian viruses and the enveloped virus, sindbis virus. this nanofiber material has the potential to become an inexpensive defense against water-borne diseases.',

4.8.6 实施诊断和产品以改善临床流程

输出:

[" therefore, china's advancements in research and development, technical and scientific capacity transferring can support african next generation of proactive scientists to develop more sensitive simplified diagnostic tools and reduce the costs of laboratory diagnosis and medical equipment. furthermore, research and development is needed in examining the biological mechanisms of stressors or risk factors exposure and health effects, assessing evidence-based mitigation or adaptation interventions and benefits . innovative solutions and breakthroughs in human-animal-environment fields would not only enable africa to meet its own growing needs, but also support integrating health systems, including strengthening the capacities of laboratory diagnostics and medical care, as well as establishing the china-africa platforms that could generate evidence-based low-cost, available and easy-to-use health packages and solutions for the reduction of public health burden.", ' 1\. access to data and samples to enable and accelerate research, which would involve rapid sharing of epidemiological surveillance and clinical data to inform outbreak control strategies; incentives and platforms for open sharing and access to genomic sequencing data; access to specimen samples . 2\. appropriate conduct of research, including improved ethical standards for research and development ; previous agreement about experimental protocols, such as trial design, to speed clinical trials when outbreaks strike; 80 access to clinical trial data, such as publication of negative and positive results; clear pathways for approval by stringent regulatory authorities and in countries of use; and building on and investing in research capacities in epidemicaff ected countries. 3\. equitable access to the benefi ts of research, including priority, aff ordable access to newly developed health technologies for aff ected populations, including health workers; and ethical guidelines for rationing products with limited availability. an overarching framework is needed to bring coherence and fi ll gaps in the fragmented system of international rules shaping outbreak-related research (including the international health regulations, pandemic',' clinical laboratories are highly regulated, and general laboratory and testing requirements apply to all molecular diagnostic assays reported for patient care90\. quality control is paramount, and methods must be developed to ensure analytic accuracy throughout the assay workflow. important quality control steps can include initial sample quality checks, library parameters , sequence data generation , recovery of internal controls and performance of external controls. validation data generated during assay development and implementation should be recorded and made available to laboratory inspectors or submitted to regulatory agencies, such as the fda in the usa or the european medicines agency in europe, for approval.', ' future applications of advanced molecular diagnostics in clinical laboratories will enhance significantly capabilities to diagnose bacterial, parasitic, and viral agents in the early course of disease through enhanced assay sensitivities and specificities and improved turnaround times, theoretically leading to more timely and directed therapeutic intervention. until such time, clinicians must continue to rely on clinical judgment and the diverse battery of traditional culture techniques, direct examination , and immunoassays that are available. cost considerations and the ever-increasing array of infectious agents responsible for infectious gastroenteritis will continue to drive the development of practice guidelines to assist practitioners with reasoned and reasonable approaches to management of diarrheal illnesses. ']

4.8.7 疾病模型,包括感染、疾病和传播的动物模型

输出:

[' this paper reviews animal models currently in use for the study of influenza pathogenesis and immune responses to influenza virus infections and to assess vaccine and antiviral drug efficacy. models that will be reviewed will include: models of benign influenza, typical severe seasonal influenza and pneumonia, influenza-associated sepsis, models using h5n1 viruses, models in which acute respiratory distress syndrome is induced, models of influenzaassociated neurologic disease, models for virus transmission studies, immunocompromised models, and models of host resistance.', ' pregnancy poses an increased risk of severe maternal illness due to a number of acute and chronic viral infections; the common rhinovirus, influenza virus, sars coronavirus and varicella zoster, hepatitis e/b, hiv and cytomegalovirus . viral infections can also lead to pre-term birth and other pregnancy complications . however, few murine models are available to study pathogenesis of viral infections.', ' coronaviruses can cause a variety of diseases in animals and humans . of economical importance are coronaviruses such as porcine transmissible gastroenteritis virus, bovine coronavirus, feline infectious peritonitis virus, and avian infectious bronchitis virus. mhv, a natural mouse pathogen, has been extensively studied in the context of host immune responses and pathogenesis . there are many different and well-characterized strains of mhv which, depending on organ tropism, virulence and host strain, can cause a wide array of diseases ranging from hepatitis, respiratory symptoms and gastroenteritis to cns infection, demyelination, and acute meningitis [2, 17, . therefore, by using appropriate combinations of virus and mouse strains, mhv infections provide suitable models for a number of diseases that are of medical importance, such as encephalitis, immune-mediated demyelination , hepatitis and acute respiratory infections .', ' although in most host-virus interaction studies typically protein-coding genes have been the center of attention, there are few examples of virus and host lncrna interactions in human and mouse models . for instance, hepatitis b virus infection altered lncrna profiles in patients, with about 4% of human lncrnas showing more than 2-fold changes in hbv infected liver tissue . winterling et al. identified a virus inducible lncrna, which is induced by vesicular stomatitis virus and several strains of influenza a virus .']

同样,我们可以为其他查询检索信息,您只需键入 query 并调用" recommend_text "函数。

参考文献:

[1]韩家伟,简佩,米凯琳·坎伯,数据挖掘:概念和技术提供了概念和技术 (2012),爱思唯尔公司

[2]丹尼尔·瑟尔、·杨、孔胜义、南华、尼科尔·利姆蒂亚科、罗慕尼·圣约翰、诺亚·康斯坦、马里奥·瓜哈尔多-塞斯佩德斯、史蒂夫·袁、克里斯·塔尔、宋云轩、布赖恩·斯特罗普、雷·库兹韦尔、通用句子编码器 (2018)、arXiv.org

NLP:使用全局向量构建文本摘要

原文:https://towardsdatascience.com/nlp-building-a-summariser-68e0c19e3a93?source=collection_archive---------40-----------------------

蒂姆·莫斯霍尔德在 Unsplash 上的照片

一篇文章的摘要是一个简短的版本,它包含了文章的关键点,目的是把文章浓缩成几个要点,并且用文章本身的语言来表达。主要地,只有那些我们认为最重要的元素/句子被提取出来,通常,这些元素/句子传达了主要思想,或者基本的支持点。

总结不是对文章的分析。两者是不同的东西。摘要在很多情况下是有用的,例如,获得一篇大文章的要点,用热门词汇介绍一个复杂的想法,从大文章中获得意义等等。

在学术上,提取摘要是一项有点挑战性的任务。谢天谢地,机器学习来拯救我们了。机器学习的自然语言处理(NLP)模块提供了许多可用于文本摘要的算法。有两种主要的文本摘要方法:

抽象摘要:
这种技术使用先进的自然语言处理方法来产生一个摘要,它在所使用的单词/句子方面是全新的。也就是说,摘要是用文章中没有用到的词写成的。

E 提取摘要:
在这种技术中,最重要的单词/句子被提取出来并组合在一起以创建摘要。因此,摘要中使用的单词/句子来自文章本身。

在本文中,我们将使用抽取技术构建一个新闻摘要,从一篇大型新闻文章中抽取 4-5 个主要的重要句子。我们将检查一些流行和有效的策略来处理大量的文本,并从中提取 4-5 个有意义的句子。

我们将使用全局向量,也称为手套算法,这是单词的向量表示。用外行人的话来说,我们将使用手套算法生成句子向量,并将选择每页排名最高的句子算法。事不宜迟,让我们深入研究代码。我在这个练习中使用了 python。

流程新闻 RSS 提要

我选择在印度最受欢迎的新闻服务之一 TimeOfIndia 的 RSS feed 上工作。在这个练习中,我选择了新闻的“世界”部分。但是它足够灵活,可以处理各种新闻服务多个 RSS 提要。

让我们读取 RSS 提要,并将新闻条目链接传递给 BeautifulSoup 进行 HTML 解析。注意,这里我只取了一个 RSS 提要,并一步一步地进行解析。后来,我将这些步骤结合在一起,无缝地处理多个提要。

# import basic required libraries
import pandas as pd
import numpy as np
import os# for web and HTML
import requests
from bs4 import BeautifulSoup# create a dict of various rss feed link and their categories. Will iterate them one by one.
# Have mentioned only one feed for demo purposes
timesofindia = {'world':'[http://timesofindia.indiatimes.com/rssfeeds/296589292.cms'](http://timesofindia.indiatimes.com/rssfeeds/296589292.cms')}
for category, rsslink in timesofindia.items():
    print('Processing for category: {0}. \nRSS link: {1}'.format(category,rsslink))
    # get the webpage URL and read the html
    rssdata = requests.get(rsslink)
    #print(rssdata.content)
    soup = BeautifulSoup(rssdata.content)
    print(soup.prettify())

在 BeautifulSoup 解析之后,应该彻底检查网页 HTML 内容(如上所述,通过使用 prettify 函数)以找到标签/模式或标签序列,从而导航到所需的新闻标题、链接和发布日期。在我们的例子中,这些元素在“item”标签中。所以让我们提取它来遍历每个“item”标签并提取每个单独的元素。

# get all news items. It has title, description, link, guid, pubdate for each news items. 
# Lets call this items and we will iterate thru it
allitems = soup.find_all('item')# print one news item/healine to check
for item in range(len(allitems)):
    print('Processing news-item #:',item)
    title = allitems[item].title.text
    link = allitems[item].guid.text
    pubdate = allitems[item].pubdate.text
    print('TITLE:',title)
    print('LINK:',link)
    print('PUBDATE:',pubdate)

输出:

Total news items found: 20
TITLE: Boris Johnson's pregnant fiancee says she is 'on the mend' from coronavirus
LINK: [https://timesofindia.indiatimes.com/world/.](https://timesofindia.indiatimes.com/world/uk/boris-johnsons-pregnant-fiancee-says-she-is-on-the-mend-from-coronavirus/articleshow/74994200.cms)...
PUBDATE: Sun, 05 Apr 2020 17:15:04 IST
TITLE: US to airlift 22,000 Americans stranded overseas; many in India
LINK: [https://timesofindia.indiatimes.com/world/.](https://timesofindia.indiatimes.com/world/us/us-to-airlift-22000-americans-stranded-overseas-many-in-india/articleshow/74992196.cms)...
PUBDATE: Sun, 05 Apr 2020 14:08:04 IST
TITLE: Ecuador VP apologizes after virus corpses left on streets
LINK: [https://timesofindia.indiatimes.com/world/.](https://timesofindia.indiatimes.com/world/rest-of-world/ecuador-vice-president-apologizes-after-virus-corpses-left-on-streets/articleshow/74992101.cms)...
PUBDATE: Sun, 05 Apr 2020 14:01:42 IST

要求的元素,即标题,链接,发布日期期待。让我们转到下一节,我们将创建一个从链接中获取新闻文章文本的基本函数。

摘录新闻文章

在本节中,我们将通过解析网页的 HTML 链接来提取新闻文章文本。从 RSS feed 收到的链接中,我们将获取网页并使用 BeautifulSoup 解析它。

应该对网页 HTML 进行彻底的分析,以识别其中包含所需新闻文本的标签。我创建了一个从链接中获取新闻文本的基本函数。使用 BeautifulSoup,将提取特定 html 标签中可用的新闻文本。

# Function to fetch each news link to get news essay 
def fetch_news_text(link):
    # read the html webpage and parse it
    soup = BeautifulSoup(requests.get(link).content, 'html.parser') # fetch the news article text box
    # these are with element <div class="_3WlLe clearfix">
    text_box = soup.find_all('div', attrs={'class':'_3WlLe clearfix'})
    # extract text and combine
    news_text = str(". ".join(t.text.strip() for t in text_box))
    return news_text# using the above function, process text
news_articles = [{'Feed':'timesofindia',
                  'Category':category, 
                  'Headline':allitems[item].title.text, 
                  'Link':allitems[item].guid.text, 
                  'Pubdate':allitems[item].pubdate.text,
                  'NewsText': fetch_news_text(allitems[item].guid.text)} 
                     for item in range(len(allitems))]news_articles = pd.DataFrame(news_articles)
news_articles.head(3)

获取新闻文本后的新闻文章详细信息

以上数据看起来符合预期。注意,新闻文本的提取依赖于指定的 HTML 标签,所以如果新闻提供者碰巧改变/修改标签,上述提取可能不起作用。为了解决这个问题,我们可以在新闻文本为空时放置一个通知警报/标志,指示修改代码/标签的时间。

文本预处理

对于文字清理,我使用了 这篇 文章中详述的预处理步骤。这些步骤是删除 HTML 标签、特殊字符、数字、标点符号、停用词、处理重音字符、扩展缩写、词干化等。这些步骤在 这篇 文章中有详细阐述,所以一定要查看一下细节。

在这里,我将这些预处理步骤放在一个函数中,该函数将返回一个干净且规范化的语料库。

# test normalize cleanup on one article
# clean_sentences = normalize_corpus([news_articles['NewsText'][0]])
clean_sentences = normalize_corpus(news_articles['NewsText'])

生成句子向量

使用手套单词嵌入,我们将生成句子的向量表示。对于这个练习,我使用的是预先训练好的维基百科 2014 + Gigaword 5 手套矢量可用 这里

# define dict to hold a word and its vector
word_embeddings = {}# read the word embeddings file ~820MB
f = open('.\\GloVe\\glove.6B\\glove.6B.100d.txt', encoding='utf-8')
for line in f:
    values = line.split()
    word = values[0]
    coefs = np.asarray(values[1:], dtype='float32')
    word_embeddings[word] = coefs
f.close()# check the length
len(word_embeddings) # 400000

在这个集合中,我们有 400K 的单词嵌入。这些单词嵌入的大小是 822 MB。大小可能因嵌入的令牌而异。嵌入越多,精确度越高。使用这些单词嵌入,让我们为规范化的句子创建向量。对于一个句子,我们将首先获取每个单词的向量。然后将取所有句子单词向量分数的平均分数,以得到一个句子的综合向量分数。

# create vector for each sentences
# list to hold vector 
sentence_vectors = []# create vector for each clean normalized sentence
for i in clean_sentences:
    if len(i) != 0:
        v = sum([word_embeddings.get(w, np.zeros((100,))) for w in i.split()])/(len(i.split())+0.001)
    else:
        v = np.zeros((100,))
    sentence_vectors.append(v)print('Total vectors created:',len(sentence_vectors)) 

取前 N 个句子

向量只是平面上的一个指针。使用余弦相似度方法,会发现句子之间的相似之处。向量将低余弦角将被计数器视为更相似。文章中每隔一个句子计算一个句子的余弦值。这里,也可以使用像欧几里德距离这样的其他方法,并且它们之间的距离越小的向量越相似。

from sklearn.metrics.pairwise import cosine_similarity# define matrix with all zero values
sim_mat = np.zeros([len(sentences),len(sentences)])# will populate it with cosine_similarity values 
# for each sentences compared to other
for i in range(len(sentences)):
    for j in range(len(sentences)):
        if i != j:
            sim_mat[i][j] = cosine_similarity(sentence_vectors[i].reshape(1,100), sentence_vectors[j].reshape(1,100))[0,0]

接下来,让我们将这个余弦相似性矩阵转换成一个图,其中节点代表句子,边代表句子之间的相似性得分。在这个图表上,将应用 PageRank 算法来得出每个句子的排名。

import networkx as nx# build graph and get pagerank
nx_graph = nx.from_numpy_array(sim_mat)
scores = nx.pagerank(nx_graph)# print final values of sentences
scores

输出:

{0: 0.0651816121717921,
 1: 0.0642861521750098,
 2: 0.06399116048715114,
 3: 0.06432009432128397,
 4: 0.06385988469675835,
 5: 0.06400525631019922,
 6: 0.06520921510891638,
 7: 0.06320537732857809,
 8: 0.06298228524215846,
 9: 0.06399491863786076,
 10: 0.0640726538022174,
 11: 0.06349704017361839,
 12: 0.06357060319536506,
 13: 0.057627597033478764,
 14: 0.058463972076477785,
 15: 0.05173217723913434}

因为我们在最初的文章中有 16 个句子,所以我们得到了 16 个分数,即每个句子一个分数。是时候根据上面计算的排名选出前 N 个句子了。

最后的步骤和结论

如上所述,最终文本需要一些处理才能呈现。这些处理可以是大写每个句子的第一个字符,从每篇文章的开头删除位置名称,删除多余的空格/制表符/标点符号,纠正换行符等。

最后,我们可以将所有这些步骤放在一起,创建一个摘要引擎/脚本。这个脚本可以被安排在每天早上选择的 RSS 提要上运行,并将新闻摘要发送到您的收件箱。这样你就不需要浏览所有文章来获取最新信息。或者您可以创建一个漂亮的 HTML 页面/小部件来显示主要出版物的新闻摘要。注意,在上面,我使用了单个 RSS 提要,但是在创建管道时,可以指定的 RSS 提要很少。此外,我使用了一些打印语句来显示中间值,可以删除这些中间值以获得无缝体验。

希望你喜欢这篇文章。如果你想分享关于任何方法的任何建议,请在评论中畅所欲言。读者的反馈/评论总是给作家带来灵感。

NLP:构建文本清理和预处理管道

原文:https://towardsdatascience.com/nlp-building-text-cleanup-and-preprocessing-pipeline-eba4095245a0?source=collection_archive---------8-----------------------

马克·拉斯姆森在 Unsplash 上拍摄的照片

自然语言处理,简称 NLP,是研究语言学和人类语言的机器学习/人工智能的子领域。NLP 处理计算机和人类语言之间的交互。换句话说,它使计算机能够理解人类语言,并对计算机进行编程,处理和分析大量的自然语言数据。

但在计算机程序能够理解和解释人类语言之前,大量的预处理工作都是在幕后进行的。你有没有想过情感分析、文本分类、推文分析等等的幕后发生了什么??由于预处理,程序可以很容易地将语言或文本转换成更易于吸收的形式,以便机器学习算法可以更好地执行。

这些最常用于情感分析、反馈分类、翻译、摘要等。在许多情况下,预处理步骤提高了算法的准确性。通常,输入数据以自然形式呈现,即文本、句子、评论、段落、推文等格式。在这种输入可以被传递给机器学习算法之前,它需要一些清理或预处理,以便算法可以专注于主要/重要的单词,而不是增加最小价值或没有价值的单词。
说够了,让我们深入探讨 NLP 预处理技术。在这个例子中,我使用 python 作为编程语言。

移除 HTML 标签

通常,非结构化的文本包含许多噪音,尤其是当您使用 web 或屏幕抓取等技术时。HTML 标签通常是对理解和分析文本没有太大价值的组件之一,因此应该删除。我们将使用 BeautifulSoup 库来清理 HTML 标签。

# imports
from bs4 import BeautifulSoup# function to remove HTML tags
def remove_html_tags(text):
    return BeautifulSoup(text, 'html.parser').get_text()# call function
remove_html_tags( ‘<html> \
 <h1>Article Heading</h1> \
 <p>First sentence of some important article. And another one. And then the last one</p></html>’)

输出:

' Article Heading First sentence of some important article. And another one. And then the last one'

删除重音字符

重音字符是重要的元素,用于在发音或理解过程中表示对特定单词的强调。在某些情况下,重音符号还可以澄清单词的意思,如果没有重音符号,单词的意思可能会有所不同。虽然它们在英语中的使用很有限,但是你很有可能在自由文本语料库中遇到带重音的字符/字母。诸如简历、咖啡、测试、离婚、协调、曝光、latt 等词。

口音可能是由某人的键盘默认设置或打字风格引起的。处理带重音的字符变得更加重要,尤其是如果你只想分析英语的话。因此,我们需要确保这些字符被转换并标准化为 ASCII 字符。一个简单的例子——把é转换成 e。

# imports
import unicodedata# function to remove accented characters
def remove_accented_chars(text):
    new_text = unicodedata.normalize('NFKD', text).encode('ascii', 'ignore').decode('utf-8', 'ignore')
    return new_text# call function
remove_accented_chars('Sómě Áccěntěd těxt. Some words such as résumé, café, prótest, divorcé, coördinate, exposé, latté.')

输出:

'Some Accented text. Some words such as resume, cafe, protest, divorce, coordinate, expose, latte.'

扩张收缩

缩写是单词或音节的缩写。它们是通过从单词中去掉特定的一个或多个字母而产生的。通常不止一个单词组合成一个缩略词。在书写中,撇号被用来表示遗漏字母的位置。在英语语言/文本中,缩写经常以书面或口头形式存在。

现在很多编辑都会默认诱导收缩。比如说不要不要,我要我要,你要你要。将每个缩写转换为其扩展的原始形式有助于文本标准化。

为了消除缩写,我利用了缩写库中可用的一组标准缩写。

# imports
from contractions import CONTRACTION_MAP # from contractions.py
import re # function to expand contractions
def expand_contractions(text, map=CONTRACTION_MAP):
    pattern = re.compile('({})'.format('|'.join(map.keys())), flags=re.IGNORECASE|re.DOTALL)
    def get_match(contraction):
        match = contraction.group(0)
        first_char = match[0]
        expanded = map.get(match) if map.get(match) else map.get(match.lower())
        expanded = first_char+expanded[1:]
        return expanded     new_text = pattern.sub(get_match, text)
    new_text = re.sub("'", "", new_text)
    return new_text# call function 
expand_contractions(“Y’all i’d contractions you’re expanded don’t think.”)

输出:

'You all i would contractions you are expanded do not think.'

另一种方式可以是:

# imports
from pycontractions import Contractions
cont = Contractions(kv_model=model)
cont.load_models()# function to expand contractions
def expand_contractions(text):
    text = list(cont.expand_texts([text], precise=True))[0]
    return text

删除特殊字符

众所周知,特殊字符是非字母数字字符。这些字符最常见于评论、参考文献、货币数字等。这些字符对文本理解没有任何价值,而且会给算法带来干扰。幸运的是,正则表达式( regex )可以用来去掉这些字符和数字。

# imports
import re# function to remove special characters
def remove_special_characters(text):
    # define the pattern to keep
    pat = r'[^a-zA-z0-9.,!?/:;\"\'\s]' 
    return re.sub(pat, '', text)

# call function
remove_special_characters(“007 Not sure@ if this % was #fun! 558923 What do# you think** of it.? $500USD!”)

输出:

'007 Not sure if this  was fun! 558923 What do you think of it.? 500USD!'

移除数字

正如您在上面看到的,文本被保留了下来。但是有时这些可能不是必需的。由于我们处理的是文本,所以数字可能不会给文本处理增加多少信息。所以,数字可以从文本中删除。我们可以使用正则表达式( regex )来去掉数字。这一步可以与上一步结合,一步完成。

# imports
import re# function to remove numbers
def remove_numbers(text):
    # define the pattern to keep
    pattern = r'[^a-zA-z.,!?/:;\"\'\s]' 
    return re.sub(pattern, '', text)

# call function
remove_numbers(“007 Not sure@ if this % was #fun! 558923 What do# you think** of it.? $500USD!”)

输出:

' Not sure if this  was fun!  What do you think of it.? USD!'

删除标点符号

这可以通过删除特殊字符的步骤来实现。去掉标点符号相当容易。这可以通过使用字符串、标点符号和保留列表中没有的内容来实现。

# imports
import string# function to remove punctuation
def remove_punctuation(text):
    text = ''.join([c for c in text if c not in string.punctuation])
    return text# call function
remove_punctuation('Article: [@First](http://twitter.com/First) sentence of some, {important} article having lot of ~ punctuations. And another one;!')

输出:

'Article First sentence of some important article having lot of  punctuations And another one'

堵塞物

词干化是将词尾变化/派生的单词简化为词干、词根或词根形式的过程。词干不必与原词相同。有许多方法来执行词干提取,如查找表、后缀剥离算法等。这些主要依赖于从单词的末尾截掉s、【es】、【ed】、【ing】、【ly】等,有时这种转换是不可取的。但是尽管如此,词干帮助我们标准化文本。

# imports
import nltk# function for stemming
def get_stem(text):
    stemmer = nltk.porter.PorterStemmer()
    text = ' '.join([stemmer.stem(word) for word in text.split()])
    return text# call function
get_stem("we are eating and swimming ; we have been eating and swimming ; he eats and swims ; he ate and swam ")

输出:

'we are eat and swim ; we have been eat and swim ; he eat and swim ; he ate and swam'

词汇化

虽然词干化和词元化都生成词根形式的词形变化/所需单词,但词元化是词干化的高级形式。词干化可能不会产生实际的单词,而词汇化会通过使用词汇进行适当的转换,通常旨在仅删除屈折词尾,并返回单词的基本形式或词典形式,这就是所谓的词汇。

在使用词干化之前,我们应该意识到它比词干化慢得多,所以在选择词干化或词干化之前,应该考虑性能。

# imports
import spacy
nlp = spacy.load('en',parse=True,tag=True, entity=True)# function to remove special characters
def get_lem(text):
    text = nlp(text)
    text = ' '.join([word.lemma_ if word.lemma_ != '-PRON-' else word.text for word in text])
    return text# call function
get_lem("we are eating and swimming ; we have been eating and swimming ; he eats and swims ; he ate and swam ")

输出:

'we be eat and swim ; we have be eat and swim ; he eat and swim ; he eat and swam'

删除停用词

停用词经常被添加到句子中以使其语法正确,例如, a、is、an、the 和等词。这些停用词不太重要,在公开文本、文章、评论等中随处可见。这些应该被删除,以便机器学习算法可以更好地专注于定义文本含义/想法的单词。我们使用来自 nltk.corpus 的列表,并且可以根据手头的情况通过添加或删除自定义单词来进一步增强该列表。

# imports
import nltk
from nltk.tokenize import ToktokTokenizer
tokenizer = ToktokTokenizer()
stopword_list = nltk.corpus.stopwords.words('english')
# custom: removing words from list
stopword_list.remove('not')# function to remove stopwords
def remove_stopwords(text):
    # convert sentence into token of words
    tokens = tokenizer.tokenize(text)
    tokens = [token.strip() for token in tokens]
    # check in lowercase 
    t = [token for token in tokens if token.lower() not in stopword_list]
    text = ' '.join(t)    
    return text# call function
remove_stopwords("i am myself you the stopwords list and this article is not should removed")

输出:

'stopwords list article not removed'

删除多余的空格和制表符

额外的空格和制表符不会给文本处理添加任何信息。处理这些应该相当容易。

# imports
import re# function to remove special characters
def remove_extra_whitespace_tabs(text):
    #pattern = r'^\s+$|\s+$'
    pattern = r'^\s*|\s\s*'
    return re.sub(pattern, ' ', text).strip()# call function
remove_extra_whitespace_tabs('  This web line  has \t some extra  \t   tabs and whitespaces  ')

输出:

'This web line has some extra tabs and whitespaces'

小写字母

使用 lower 函数可以将大小写改为小写。

# function to remove special characters
def to_lowercase(text):
    return text.lower()# call function
to_lowercase('ConVert THIS string to LOWER cASe.')

输出:

'convert this string to lower case.'

结论

这些步骤中的一些可以合并在一个步骤中。此外,请注意,根据上下文和要求,其中一些可能不是必需的。此外,我们可以定义一个新的函数来封装所有上述预处理函数,以形成一个文本规范化器管道。这些步骤应该能让您很好地了解如何构建清理和预处理策略。经过这些预处理步骤后,文本集就可以用于 NLP 算法,如 Word2Vec、GloVe 等。这些预处理步骤肯定会提高模型的准确性。

希望你喜欢这篇文章,如果是的话,请在评论中说出来。如果你想分享关于任何方法的任何建议,请在评论中畅所欲言,我会马上回复。

Python 中的 NLP 文本分类:PyCaret 方法与传统方法的比较

原文:https://towardsdatascience.com/nlp-classification-in-python-pycaret-approach-vs-the-traditional-approach-602d38d29f06?source=collection_archive---------16-----------------------

传统教学法与 PyCaret 教学法的对比分析

一.导言

在本帖中,我们将看到用 python 中的两种不同方法演示 NLP 分类问题:

1-传统方法:在这种方法中,我们将:
-使用不同的 NLP 技术预处理给定的文本数据
-使用不同的嵌入技术嵌入处理过的文本数据
-在嵌入的文本数据上从一个以上的 ML 族构建分类模型
-查看不同模型的性能,然后调整一些选择的模型的超参数
-最后,查看调整后的模型的性能。很明显,用 python 来做意味着要写数百行代码,这至少要花你两到三个小时的时间。

2-PyCaret 方法:一种新方法,其中我们使用一个低代码 Python 库 py caret 来完成上述传统方法中的所有工作,但我们只需编写不到 30 行代码,几分钟就能获得结果和见解。

为了让您了解这两种方法之间的区别,请查看下面的粗略对照表:

您可以看到 PyCaret 方法提供了更多的解决方案和功能,而且花费的时间和精力更少!

二。自然语言处理分类问题

这里的任务是识别给定的短信是垃圾短信还是火腿。这里是原始数据的一瞥,你可以从这个 链接 找到原始数据。数据集有 5574 条短信待分类。

原始数据集的头部和尾部

您可能已经发现,这个问题分两个阶段:对原始文本数据进行 NLP,然后对处理后的文本数据进行分类。

让我们现在开始,看看这两种方法!我会在这篇文章的底部分享我在 Github 上的代码链接。

三。传统方法

第一阶段。文本数据的数据设置和预处理

在预处理之前,我们将把标志列从分类数据类型转换为数字数据类型。生成的数据集如下所示:

带有标志列的数据集的头部和尾部被转换成数值/虚拟值

接下来,在预处理步骤中,我对文本数据执行了以下操作:
-移除 HTTP 标签
-降低大小写
-移除所有标点符号和 Unicode
-移除停用词
-词汇化(考虑到与单词相关的相关词性,将单词转换为其根形式)

执行完上述所有 5 个操作后,数据集看起来如下:

预处理操作后数据集的头部和尾部

在我们开始嵌入之前,对最常见的单词和最罕见的单词进行快速的探索性分析可能会让我们了解垃圾短信和业余短信之间的区别。

15 个最常见的单词:它们似乎最常出现在火腿短信中

15 个最罕见的词:它们似乎大多出现在垃圾短信中

一般来说,这种探索性分析有助于我们识别和去除预测能力非常低的单词(因为这种单词大量出现)或可能在模型中引起噪声的单词(因为这种单词出现得非常少)。但是,我没有从处理过的文本数据中删除更多的单词,并且已经进入了嵌入阶段。

第二阶段。在处理后的文本数据上嵌入

我在这里使用了两种嵌入技术。
a. 单词包方法:该方法创建一个术语文档矩阵,其中每个唯一的单词/术语成为一列。在 Python 中,我们对 BoW 嵌入使用 CountVectorizer() 函数。

嵌入 BoW 的变换数据集

b.术语频率-逆文档频率方法:该方法创建一个术语文档矩阵,其中将一些权重应用于矩阵中的每个术语。权重取决于单词在文档和整个语料库中出现的频率。在 Python 中,我们使用 TfidfVectorizer() 函数进行 TF-IDF 嵌入。

嵌入 TF-IDF 的变换数据集

第三阶段。模型结构

在决定构建什么模型之前,我已经将数据分成了 85%的数据(4737 行)在训练数据集中,剩下的 15%(837 行)在测试数据集中。
测试数据集允许我们在看不见的数据上评估模型性能

数据的训练/测试分割的输出

  • 这里,我从四个随机决定的 ML 家族建立了分类模型:随机森林分类器、Adaboost 分类器、梯度推进分类器、朴素贝叶斯分类器。
  • 我首先在 BoW embedded 数据集上构建了上述模型,然后在 TF-IDF embedded 数据集上构建了上述模型。
  • 使用的模型性能指标有:混淆矩阵、准确度分数、精确度分数、召回分数和 ROC-AUC 分数
  • 我在这里只分享在嵌入了BoW的数据集上构建的基础模型的结果(未调整超参数)。我已经在我的 Github 存储库中与TF-IDF embeddeding 共享了数据集上的模型性能结果。您可以在下面提供的链接上查看:

1。随机森林分类器的结果

2。AdaBoost 分类器的结果

3。梯度推进分类器的结果

4。朴素贝叶斯分类器的结果

第四阶段。超参数调谐

为了方便起见,我用嵌入了的 BoW 对建立在数据集上的模型进行了超参数调优。对 TF-IDF 嵌入式数据集上的模型做同样的事情将需要重复和添加大约 30–40行代码。**

我进一步决定继续调整随机森林分类器Adaboost 分类器模型的超参数,因为这两个模型似乎比其他两个模型表现得更好。对于超参数调整,我使用了网格搜索方法。

这里是 hyperparameter 调优的代码片段,完整代码请见本文底部链接的 Github 代码库链接。

使用与之前相同的模型性能度量:混淆矩阵、准确度分数、精确度分数、召回分数、ROC-AUC 分数。* 结果还显示调整后的超参数值,以及调整后模型的准确度得分的 10 倍交叉验证值。*

以下是调整后模型的性能结果:

1。调整后的 AdaBoost 分类器模型的结果

2。调整后的随机森林分类器模型的结果

比较两个调整后的模型, AdaBoost 分类器交叉验证准确度得分上表现更好。

现在让我们探索 PyCaret 方法..!

四。PyCaret 方法

我们将重复传统方法下执行的所有步骤,但是您会注意到这种方法是多么快速和简单。

第一阶段。文本数据的数据设置和预处理

在 PyCaret 中执行任何 ML 实验之前,您必须设置一个 PyCaret 模块环境。这允许多次进行的 ML 实验的可再现性、可扩展性和部署。您可以看到,这样做只需要 2 行命令。

设置 PyCaret 的 NLP 模块的输出

这个函数的伟大之处在于,它自动对原始文本数据执行所有的 NLP 预处理操作(降低大小写、删除所有标点符号和停用词、词干、词汇化和其他操作)。这整个步骤在 21 秒内完成!

第二阶段。在处理后的文本数据上嵌入

PyCaret 目前只支持主题建模嵌入技术。在本例中,我们将使用潜在狄利克雷分配(LDA)* 技术和非负矩阵分解(NMF) 技术进行嵌入。因此,这不是苹果对苹果的比较,因为我们在传统方法中使用了 BoW 嵌入和 TF-IDF 嵌入*

PyCaret 中的嵌入过程要简单得多。您可以在下面的代码片段中看到,我们只需要 2 行代码来嵌入处理过的数据。默认情况下 nlp 模块的 create_model() 创建 4 个主题。您可以通过在此函数中传递所需的数值来更改主题编号。

用于 LDA 嵌入和结果数据集的片段

使用同样的 2 行代码,但是改变模型参数,您可以创建一个嵌入了 NMF 的数据集。

此外,PyCaret 还提供了带有多个图表的选项,用于此阶段的探索性数据分析。同样,你只需要一行代码就可以做到。但是,必须注意,探索性数据分析基于嵌入阶段创建的主题

evaluate _ model()命令的输出。单击 5 个选项卡中的任何一个,并从下拉菜单中选择 4 个主题中的任何一个,以获得更多探索性分析和见解。

第三阶段。模型结构

NLP 之后,整体问题的第二部分是分类。因此,我们需要不同的设置环境来执行分类实验。

我们将在嵌入 LDA 的数据集和嵌入 NMF 的数据集上构建模型。然而,我们将不得不放弃不必要的变量(短信,主导话题等)。)从两个嵌入的数据集中提取,以便可以在其上建立分类模型。

删除三个不必要变量后的 LDA 嵌入数据集

我们使用 PyCaret 的 nlp 模块进行 nlp 操作,同样,我们使用 PyCaret 的分类模块进行问题的分类部分。设置分类模块只需要 2 行代码。此外,我们还必须指定目标变量试车分流比率。

分类设置命令的输出。

就像在自动执行预处理操作的 nlp 设置中一样,在分类设置中,根据数据,PyCaret 自动创建新特征并执行其他预处理步骤!

如果您认为设置 PyCaret 环境和获得自动化特征工程很容易,那么模型构建就更容易了!你所要做的就是只写一个命令,然后看看结果!

比较模型命令的输出。此处使用了 LDA 嵌入式数据集

您可以看到 PyCaret 从 18 个不同的 ML 分类家族中自动构建基础模型,并按照准确度得分的降序排列 15 个最佳模型。它进一步指出,对于特定的性能指标,哪种模型表现最好(指标得分以黄色突出显示)。

所有这些只需一个命令就能完成,结果在大约 1 分钟内就能显示出来!

我们看到随机森林分类器模型准确性方面表现最好。我们来调一下随机森林分类器模型。**

第四阶段。超参数调谐

这是 PyCaret 中的一个 3 步过程:创建一个模型,调整它,评估它的性能。每个步骤只需要一行代码!

调优T8随机森林分类器建立在 LDA 嵌入 datase t:**

  • 在下面的输入输出片段中,每个步骤只需要 1 行代码。
  • 为了创建一个随机森林分类器模型,你必须传递‘RF’
  • 您可以观察到调整后的模型指标优于基础模型指标
  • PyCaret 提供 15 个评估图。单击 15 个选项卡中的任何一个,选择您想要用来获得进一步见解的评估图。

调整模型和评估其性能结果的 3 个步骤

我重复了同样的过程来调整建立在 NMF 嵌入数据上的模型。我这次调整了一个额外树分类器模型,做了一些改动。

  • 建立新环境后, compare_models ()的结果显示 Extra Trees Classifier 模型表现最佳,因此我决定对其进行调优。

setup()和 compare_model()命令输出 NMF 嵌入数据

  • 在这里,我重复了与 LDA 嵌入数据相同的步骤: create_model(),然后是 tune_model(),然后是 evaluate_model()。
    您可以看到,要创建和调整一个
    额外树分类器模型,您必须传递‘et’值。
    这次我决定优化 AUC 值而不是
    准确度分数,同时调整超参数。为此,我必须传递‘AUC’值。

在嵌入 NMF 的数据上创建、调整和评估额外树分类器模型

动词 (verb 的缩写)两种方法的比较

可以看出,与传统方法相比,PyCaret 以更少的代码行和更少的执行时间提供了具有更多选项和功能的解决方案。

我想进一步指出,将传统方法的模型性能结果与 PyCaret 方法的模型性能结果进行比较并不是苹果与苹果之间的比较,因为这两种方法对文本数据使用不同的嵌入技术。我们必须等待 PyCaret 的 nlp 模块的更新版本,它支持传统方法中使用的嵌入技术。

然而,根据业务问题,重要的是要看到节省的时间和精力,以及在 PyCaret 方法下获得的洞察力选项远比在传统方法下获得增加了一些十进制值的评估指标值更有价值。

下面是粗略的比较表,再次强调了这两种方法之间的主要区别。

不及物动词重要链接

感谢你阅读这篇文章。快乐学习!

NLP:分类和推荐项目

原文:https://towardsdatascience.com/nlp-classification-recommendation-project-cae5623ccaae?source=collection_archive---------34-----------------------

使用 arxiv 数据的逐步 NLP 项目

Unsplash 上的Cup 先生/杨奇煜·巴拉拍摄的照片

NLP 是从文本数据中提取意义和学习的科学,它是数据科学项目中使用最多的算法之一。文本数据无处不在,总之,NLP 有许多应用领域,如下图所示。

在这种背景下,我决定做一个覆盖 arxiv 数据的 NLP 项目。通过这个项目,我的目标是对文章的标签进行分类,并通过文章的摘要、标题、作者和体裁特征建立一个推荐系统。

第一步:数据知识

为了实现我的目标,我提取了一个包含 41000 行和 6 列的 arxiv 数据集:作者、链接、摘要、标签、标题和年份。我的数据集包含 1998 年至 2018 年之间的文章。如左图所示,它包含了大部分计算机科学领域的文章。

步骤 2:文本清理

我的一些特性是字典类型的,所以我将这些列转换成列表类型,以便有一个可用的数据结构。

from ast import literal_eval
# convert 'stringfield' lists to usable structure
features = ['author', 'link', 'tag']
for feature in features:
    arxivData[feature] = arxivData[feature].apply(literal_eval)

在执行 literal_eval 之后,我为列表转换编写了三个函数:

def get_names(x):
    if isinstance(x, list):
        names = [i['name'] for i in x]
        #Check if more than 3 elements exist. If yes, return only first three. If no, return entire list.
        if len(names) > 3:
            names = names[:3]
        return namesdef get_link(x):
    for i in x:
        return i['href']

def get_tag(x):
    if isinstance(x, list):
        terms = [i['term'] for i in x]
        #Check if more than 5 elements exist. If yes, return only first five. If no, return entire list.
        if len(terms) > 5:
            terms = terms[:5]
        return terms

好了,我现在准备写一个文本清理函数。这些是 NLP 项目中构建健壮模型结构的最重要的部分之一。为此,我们需要删除大写字母、标点和数字:

# Data Cleaning & Preprocessing techniques
def clean_text(text):
    # remove everything except alphabets
    text = re.sub("[^a-zA-Z]", " ", text)
    # remove whitespaces
    text = ' '.join(text.split())
    text = text.lower()
    return text

没有停用词的 25 个最常用词

步骤 3:文本挖掘算法

现在是时候从文本数据中提取特征了。文本文件最初只是一系列的单词。为了运行机器学习算法,我们必须将文本文件转换成数字特征向量。有两种常用的方法:CountVectorizer 和 Tfidf。

  • count vectorizer:count vectorizer提供了一种简单的方法,既可以标记一组文本文档,构建已知单词的词汇表,还可以使用这个词汇表对新文档进行编码。
  • Tfidf: TF-IDF 是一种统计度量,用于评估一个单词与文档集合中的一个文档的相关程度。这是通过将两个度量相乘来实现的:一个单词在一个文档中出现的次数,以及该单词在一组文档中的逆文档频率。

它们之间的区别基本上是,一个统计所有的单词来矢量化,另一个使用统计方法来代替。

为了在我的数据集上执行文本挖掘,我首先编写了一个 lemmatize 函数,然后执行矢量化。

# Lemmatization process
'''
Words in the third person are changed to first person and verbs in past and future tenses are changed into the present by the 
lemmatization process. 
'''
lemmatizer = WordNetLemmatizer()def tokenize_and_lemmatize(text):
    # tokenization to ensure that punctuation is caught as its own token
    tokens = [word.lower() for sent in nltk.sent_tokenize(text) for word in nltk.word_tokenize(sent)]
    filtered_tokens = []

    for token in tokens:
        if re.search('[a-zA-Z]', token):
            filtered_tokens.append(token)
    lem = [lemmatizer.lemmatize(t) for t in filtered_tokens]
    return lem

有了这个矩阵,我们现在可以建立一个机器学习模型。

# Defining a Count Vectorizer object
count_vec = CountVectorizer(stop_words='english', max_features=10000)# Defining a TF-IDF Vectorizer
tfidf_vec = TfidfVectorizer(stop_words='english', ngram_range=(1, 2), tokenizer=tokenize_and_lemmatize, max_features=10000, use_idf=True)

第四步:分类

有各种算法可用于文本分类。嗯,我从探索这些模型开始:逻辑回归、朴素贝叶斯、线性 SVC 和随机森林。我的方法是,在运行完本节中的所有模型后,选择最佳模型进行优化。因此,我用默认参数运行了所有的模型,以查看结果。

这是我的分类模型的结果。准确性和 f1 分数之间冲突的原因是一篇文章有多个标签。

机器学习模型未能预测一篇文章的所有标签。尽管如此,f1 分数还是高于准确度,因为我把 f1 的平均参数设置为‘微’。

我跳到了模型评估之后的优化部分。为此,我使用了 GridSearchCV:

param = {'estimator__penalty':['l1', 'l2'], 'estimator__C':[0.001, 0.01, 1, 10]}# GridSearchCV
kf=KFold(n_splits=10, shuffle=True, random_state=55)
lr_grid = GridSearchCV(oneVsRest, param_grid = param, cv = kf, scoring='f1_micro', n_jobs=-1)
lr_grid.fit(xtrain_tfidf, y_train)

由于准确性得分,我选择了逻辑回归进行网格搜索,结果,我得到的 F1 得分增加到了%64,1。以下是优化回归模型的一些结果:

第五步:推荐引擎

我做了两个推荐系统,第一个基于摘要,另一个基于标题、标签和作者。为了建立一个推荐器,首先我计算了矢量化文本数据的余弦相似度。

# TfIdf matrix transformation on clean_summary column
tfidf_matrix = tfidf_vec.fit_transform(arxivData['clean_summary'])
# Compute the cosine similarity
cosine_sim = linear_kernel(tfidf_matrix, tfidf_matrix)

根据计算结果,我编写了推荐函数:

def get_recommendations(title, similarity):
    idx = indices[title]
    # pairwsie similarity scores
    sim_scores = list(enumerate(similarity[idx]))
    # sorting
    sim_scores = sorted(sim_scores, key=lambda x: x[1],  reverse=True)
    sim_scores = sim_scores[1:11]
    article_indices = [i[0] for i in sim_scores]
    # Return the top 10 most related articles
    return arxivData[['link', 'title']].iloc[article_indices]

它获得两个参数,然后通过余弦相似值对文章进行排序。最后,它返回 10 篇最相关的文章作为结果。

步骤 6:结论和进一步的工作

  • 我们已经了解了 NLP 项目基本级别的一般方法。
  • 我们已经知道有两种常见的方法来预处理我们的文本数据:计数和 Tfidf 矢量器。
  • 我们看到,我们的分类模型在多类问题上失败了,但当我们将 f1 分数作为成功指标进行评估时,我们并没有那么糟糕。
  • 写得最多的文章来自计算机科学研究,最常用的词是“神经网络”。
  • 最后,我们学习了如何使用余弦相似度来构建推荐器。
  • 作为进一步的工作,我计划做一个 Flask 应用程序,使我的推荐者在线。

最常用的词

好了,暂时就这些了。下一篇文章再见!

另外,如果你想了解更多,也可以看看我的 Github 简介!

通用语言模型微调的自然语言处理分类

原文:https://towardsdatascience.com/nlp-classification-with-universal-language-model-fine-tuning-ulmfit-4e1d5077372b?source=collection_archive---------17-----------------------

在本文中,我们将看到如何使用优于以前文本分类方法的 ULMFiT 建立一个 NLP 分类模型。

马库斯·温克勒在 Unsplash 上的照片

文本分类是自然语言处理的重要应用之一。诸如情感分析和识别垃圾邮件、机器人和攻击性评论等应用属于文本分类。到目前为止,用于解决这些问题的方法包括从头开始建立机器学习或深度学习模型,在你的文本数据上训练它们,并用超参数进行微调。尽管这种模型对于像分类电影评论是正面还是负面这样的应用程序来说给出了不错的结果,但如果事情变得更加模糊,它们可能会表现得非常糟糕,因为大多数时候没有足够多的标记数据可供学习。

但是等一下?Imagenet 不是用同样的方法对图像进行分类吗?那么,它是如何用同样的方法取得巨大成功的呢?如果我们不是从零开始建立一个模型,而是使用一个经过训练可以解决一个问题(对 Imagenet 中的图像进行分类)的模型作为基础来解决其他一些有点类似的问题(文本分类),会怎么样呢?由于微调后的模型不必从头开始学习,因此它不需要大量数据就能提供更高的准确性。这就是迁移学习的原理,通用语言模型微调(ULMFiT)就是建立在这个原理上的。

今天,我们将了解如何利用这种方法进行情感分析。您可以在此阅读更多关于 ULMFiT、其优势以及与其他方法的比较的信息。

fastai 库提供了训练和使用 ULMFiT 模型所需的模块。你可以在这里查看库

我们要解决的问题是美国航空公司的情绪分析。你可以从这里下载数据集。所以事不宜迟,我们开始吧!

首先,让我们导入所有的库。

现在,我们将把数据的 CSV 文件转换成 Pandas Dataframe 并查看数据。

现在我们检查数据帧中是否有空值。我们观察到在 negative_reason 列中有 5462 个空值。这些空属于积极+中性的情绪有道理。我们通过统计所有非负面推文来验证这一点。两个号码都匹配。negativereason_confidence 计数与 negativereason 计数不匹配的原因是 negativereason_confidence 列中的 0 值对应于 negativereason 列中的空白。

如果我们看看数据样本的总数,它是 14640。列 airline _ 情操 _ 黄金,negativereason _ 黄金& tweet_coord 有大量空白,即在 13000–14000 范围内。因此可以得出结论,这些列不会提供任何重要的信息&因此可以被丢弃。

现在我们有了相关的数据,让我们开始构建我们的模型。

当我们用 Fastai 制作 NLP 模型时,有两个阶段:

  • 创建 LM 模型并使用预先训练的模型对其进行微调
  • 使用微调模型作为分类器

这里我使用的是数据块的一部分 TextList ,而不是使用工厂方法TextClasDataBunchTextLMDataBunch,因为 TextList 是 API 的一部分,更加灵活和强大。

我们可以看到,由于我们正在训练一个语言模型,所有的文本都连接在一起(在每个新的时期,它们之间有一个随机的洗牌)。

现在,我们将使用在更大的语料库 Wikitext 103 上预先训练的模型的权重来微调我们的模型。这个模型已经被训练来预测作为输入提供给它的句子中的下一个单词。由于推文的语言并不总是语法上完美的,我们将不得不调整我们模型的参数。接下来,我们将找到最佳的学习速度,并将其可视化。可视化将帮助我们发现学习率的范围,并在训练我们的模型时从中进行选择。

默认情况下,学习者对象是冻结的,因此我们需要首先训练嵌入。这里,我不是运行一个时期的循环,而是运行 6 个时期,看看精度如何变化。我挑选的学习率是借助于我们上面得到的图。

我们得到了非常低的精度,这是预料中的,我们模型的其余部分仍然是冻结的,但我们可以看到精度正在增加。

我们看到精度略有提高,但仍在相同范围内。这是因为,首先,模型是在一个预先训练好的模型上用不同的词汇训练的&其次,没有标签,我们在没有指定标签的情况下传递了数据。

现在我们将用随机输入来测试我们的模型&看看它是否能准确地完成句子。

现在,我们将创建一个新的数据对象,它只获取带标签的数据并保留这些标签。

分类器需要稍微少一点的漏失,所以我们传递 drop_mult=0.5,将所有漏失乘以这个量。我们不加载预先训练好的模型,而是加载前一节中经过微调的编码器。

我们再次执行与语言模式相似的步骤。这里我跳过了最后 15 个数据点,因为我只对 1e-1 感兴趣。

在这里,我们看到,如果我们与步骤 1 中提供标签时的语言模型进行比较,准确性有了很大的提高。

现在我们将通过一次解冻一层来部分训练模型&差分学习率。这里我使用了 slice 属性,它将在 3 组模型中划分指定的学习率。

我们看到,随着我们逐渐解冻各层,精确度正在逐步提高。更多的层提供更多的深度。

最后,我们将解冻整个模型并可视化学习率,以选择并用于最终训练。

我们看到,在这个模型结束时,我们已经达到了 80%的最高准确率。

对于我们的最终结果,我们将取模型预测的平均值。由于样本是按文本长度排序进行批处理的,因此我们传递参数 ordered=True 来按照文本的顺序获得预测。

我们得到了 80.09%的准确率

现在是时候用新的文本输入来测试我们的模型了&看看它的表现如何!

databunch 已将文本标签转换为数字标签。它们如下:

  • 0 = >负数
  • 1 = >空档
  • 2 = >正

我们看到我们的模型表现得相当好!!

您可以使用负面以及混合情感文本来测试模型,并验证结果。

希望这篇文章对你有所帮助,😄

此外,欢迎任何建议/更正。

编码快乐!!

NLP 数据应用:Streamlit 和 HuggingFace 附带的电池

原文:https://towardsdatascience.com/nlp-data-apps-batteries-included-with-streamlit-and-huggingface-828083a89bb2?source=collection_archive---------26-----------------------

了解数据科学前端的运行速度有多快!

在构建数据科学项目时,需要完成的最后一项任务(但不是最重要的)是前端的实现,它使模型对最终用户可用,并从用户界面下的所有机器中抽象出来。

这样做的常见方法有:

  1. 用 Angular/React 或你选择的其他框架构建用户界面
  2. 依托 Tableau、Power Bi、Qlik 等仪表盘工具…

如果你真的不喜欢摆弄 JS 框架(像我一样),或者希望能够构建一个真正的端到端管道,那么你必须至少使用一次 Streamlit。

正如网站所说,Streamlit 是构建数据应用的最快方式。虽然这听起来有些傲慢,但这绝对是事实。

为了展示弄脏手有多快,我用 Streamlit 和 HuggingFace 的变形金刚建立了一个原型,使用了一个预先训练好的问答模型。

先决条件:安装变压器和简化

是的,我说“包括电池”,但你必须先买!

打开终端(或 Anaconda 提示符,取决于您的选择)并运行:

pip install transformers
pip install streamlit

代码和结果

安装完成后,获取您的编辑器并首先导入必要的包:

import streamlit as st
from transformers import AutoTokenizer,AutoModelForQuestionAnswering
from transformers.pipelines import pipeline

这允许你使用预先训练的拥抱脸模型,因为我不想从头开始训练。然后,您可以构建一个函数来加载模型;注意,我使用了 @st.cache() decorator 来避免每次都重新加载模型(至少它应该有助于减少一些开销,但是我必须更深入地研究 Streamlit 漂亮的文档):

st.cache(show_spinner=False)
def load_model():
    tokenizer = AutoTokenizer.from_pretrained("twmkn9/distilbert-  base-uncased-squad2")
    model = AutoModelForQuestionAnswering.from_pretrained("twmkn9/distilbert-base-uncased-squad2")
    nlp_pipe = pipeline('question-answering',model=model,tokenizer=tokenizer) return nlp_pipenpl_pipe = load_model()

添加一个标题和一些文本来填补空白,并添加一个侧边栏:

t.header("Prototyping an NLP solution")
st.text("This demo uses a model for Question Answering.")add_text_sidebar = st.sidebar.title("Menu")
add_text_sidebar = st.sidebar.text("Just some random text.")

考虑到我选择了一个问题回答模型,我必须提供一个用于写问题的文本单元格和一个用于复制文本的文本区域,作为查找答案的上下文。这可以通过两行来完成:

question = st.text_input(label='Insert a question.')
text = st.text_area(label="Context")

现在你可以调用模型来回答宇宙中最深最难的问题。为了避免第一次加载应用程序时出现错误,我将推理代码包装在一个 if 语句中(必须承认,这完全是糟糕的代码):

if (not len(text)==0) and (not len(question)==0):
    x_dict = npl_pipe(context=text,question=question)
    st.text('Answer: ',x_dict['answer'])

这将输出您在提供的文本中提出的问题的答案。
完整代码在此:

import streamlit as stfrom transformers import AutoTokenizer, AutoModelForQuestionAnswering
from transformers.pipelines import pipelinest.cache(show_spinner=False)
def load_model():
    tokenizer = AutoTokenizer.from_pretrained("twmkn9/distilbert-base-uncased-squad2") model = AutoModelForQuestionAnswering.from_pretrained("twmkn9/distilbert-base-uncased-squad2") nlp_pipe = pipeline('question-answering',model=model,tokenizer=tokenizer) return nlp_pipenpl_pipe = load_model()st.header("Prototyping an NLP solution")
st.text("This demo uses a model for Question Answering.")add_text_sidebar = st.sidebar.title("Menu")
add_text_sidebar = st.sidebar.text("Just some random text.")question = st.text_input(label='Insert a question.')
text = st.text_area(label="Context")if (not len(text)==0) and not (len(question)==0):
    x_dict = npl_pipe(context=text,question=question
    st.text('Answer: ',x_dict['answer'])

要运行该脚本,只需键入:streamlit run script _ _ name . py,它将默认在 localhost:8501,上运行,因此在浏览器中打开它。
这里是输出的截图:

代码的输出。

当然,这并不意味着为 Streamlit 的每个特性提供详尽的指南,而只是一种让其他人像我一样通过实验来了解这个伟大工具的方式。

谢谢,下次再见!

NLP:使用关系抽取理解评论数据

原文:https://towardsdatascience.com/nlp-deep-learning-for-relation-extraction-9c5d13110afa?source=collection_archive---------10-----------------------

注释、依存解析树和链接指南

在这篇文章中,我们将关注文本挖掘和评论分析。我们将推出自己的关系提取深度学习实现。假设你有一大堆关于你的公司或产品的评论,你想快速浏览一下关于你的公司或产品的某些部分或特征的描述符或形容词。最终目标大概是这样的:

假设耳机评论的汇总结果

对成千上万的评论进行这样的操作,并将其汇总在一起,可以构建一个非常强大的摘要工具,用于快速、全面地了解关于特定公司或产品的评论。此外,我们可以放大我们特别感兴趣的领域,如交付时间或服务质量。既然已经有这么多好的情感分析工具,我们的重点将放在实现关系抽取上。这里有一些例子,我们想提取,鉴于审查句子。

“X 有最便宜的价格和超级快速的交货”

价格——最便宜

交货 —超快

“我对电池寿命印象深刻”

电池寿命:令人印象深刻

我们将使用一些与信息抽取相关的 NLP 技术来解决这个问题。大致来说,我们将给出几个例子,说明我们希望它如何与我们句子中每个单词的相关数据一起工作,并让神经网络找出其中可能隐藏的模式。我想强调的事实是,我们不会将实际的单词本身作为一个特性,否则这是一种非常常见的方法。这意味着该模型将更好地概括在其训练集中没有见过的单词。

下面列出了我们将采取的实施步骤。

1。注释

机器学习的强大之处在于,当你不确定如何用算法解决一个问题时,只要你提供一些你希望它如何工作的例子,以及你的数据中的相关内容,你就可以得到一个非常接近的估计。

我们将为我们的模型创建一些例子。我们将使用分块策略来表示实体或描述符组。例如,如果电池寿命超级惊人,我们会希望确保所有这些词作为一组出现在那里。我们将使用一个版本的 BIO (开始、内部、外部)标签标准来标记单词组的开始和结束时间:

使用 BIO 的注释示例

我们希望包含尽可能多的例子,在你自己写了几个之后,你会意识到这可能不是你在生活中要做的事情。考虑把这个外包给机甲土耳其人

这一步是手动的,但是不要被它琐碎的外表所迷惑。非常重要的是,使用持久的方法一丝不苟地进行标记。如果您在整个训练集中没有遵循相同的方法,您将在训练过程中混淆您的模型。

2。功能选择

现在我们已经有了一些标记数据,我们需要的只是模型的特性。特征是关于您的一个训练示例的单个可测量的属性。您的每个培训示例都有多个特征。在我们的例子中,特征是关于每个单词的信息,它们如何与其他单词相关,以及它们有什么属性。有不少从文本中提取特征的库和服务,比如 SpaCyTextRazorNLTK 。我们将使用斯坦福 CoreNLP,因为它拥有世界上最好的依赖解析器之一。

依存解析树

我们可以使用依存解析树来提取句子的句法结构。这将很有帮助,因为它为我们提供了关于单词的词性 (POS)标签的信息。词性标签是一个词类,它描述了这个词的语法性质,一些例子是名词、动词和形容词。依存解析树还为我们提供了单词在结构上如何与其他单词相关的信息。这表现为句子中单词的进出链接。斯坦福 CoreNLP 使用通用依赖关系标准来表示依赖关系。

一个依赖关系解析树。“显著”一词有一个传入的 advmod 链接,其定义为:“一个词的状语是一个(非从句)副词(rb)或状语短语(ADVP),用于修饰该词的意思。”

依存解析树在内部是一个使用经过训练的模型的预测过程,即使准确度很高,我们也有可能得到不正确的解析树,这取决于句子。我们将基于该树创建一些特征。每个单词将具有以下特征:

  • 词类(POS)-单词的标签
  • 前面两个和后面两个词的词性标记。
  • 一个布尔指示器(0 或 1 ),用于每个输出链接类型,例如‘out _ adv mod’= 1
  • 一个布尔指示符(0 或 1 ),用于每一个输入链接类型,例如‘in _ nsubj’= 1

交货将具有如下特征向量:

句子“deliveries 非常快”中单词“deliveries”的特征向量

3。模特培训

为了将我们的特征向量作为神经网络的输入,我们需要将当前的特征向量转换成浮点值。注意,我们当前的特征向量包括字符串类型的值。如何将字符串转换成浮点数?你没有。

我们将为此使用一种标准方法:一种热编码。对于每个可能的位置标签,我们将创建一个新的二元特征。然后,我们将通过在代表该标签的子特性中放置 1 来标记当前特性的值。像这样:

为什么叫一热编码?因为其中一个特征是热的,并且标记为 1。你可以把这个步骤想象成把一个单词放入一个分类箱,这个分类箱的名字就是单词本身,而不是把它放入任何其他分类箱。

这种方法通常在您使用实际单词作为特征时使用,但是会将特征的维度提高到几千个维度(这通常是好的,因为矩阵是稀疏的)。在我们的例子中,我们没有将实际的单词作为一个特性,但是我们仍然必须这样做,因为 POS 标签是字符串。

观察力敏锐的读者可能已经注意到,我们已经为 in 和 out-links 特性做了一个稍微类似但不同的版本。因为我们将我们的特性定义为二进制,并将其命名为‘in _ nsubj’等,所以我们基本上为我们的链接特性创建了一个类似的编码。我们会将 1 分别放入所有有输入或输出链接的容器中。这里唯一的区别是,一个单词可能有多个 in 链接和多个 out 链接,因此要分开。

给定我们的 27 个训练句子,我们总共有 253 个使用过的特征(编码后),导致大小为 253 的输入层。我们将使用几个不同大小的隐藏层和一个大小为 5 的输出层,每个类别一个。

训练模型非常简单,只需将所有训练示例的特征向量和正确标签输入到我们定义的神经网络模型中。然后,我们可以交叉验证(或使用单独的测试集)来衡量我们模型的性能(我的示例代码包含 27 个训练句子,准确率约为 81%)。

由于我们已经用分类输出训练了这个模型(我们的最后一层有 5 个输出),所以我们可以在预测期间获得分配给给定单词的每个输出的概率:

4。链接

这是一个后预测步骤,其中我们将实体和描述符链接在一起。在模型做出预测后,我们将再次查看依赖关系解析树,并遵循以下简单的启发式规则:

如果实体组中的任何单词与描述符组中的任何单词之间存在链接,我们就说它们是相连的。如果描述符多于实体,我们允许多个描述符链接到同一个实体,反之亦然。

我们还将寻找否定,并将单词转换成它们的词条形式(例如,impressed → impressive)。例如,想象这样一句话:

“我对电池寿命印象深刻,但不是设计。”

我们的分类器产生了正确的分类:

遵循所有原始相关性分析树链接(针对预测组):

印象深刻→[nmod→生活

设计→

设计→ 【否定】 →不

要产生结果:

****电池寿命:令人印象深刻

设计:没什么印象

一切就绪后。对许多句子运行这个,然后汇总结果,这就是有用的地方。可以容易地对描述符执行情感分析。想象一下,你的一个产品有几百或几千条评论(看看你的亚马逊..),你会有一个该产品的优点和缺点的总结,就像介绍图片建议的那样:

Github 上有一些不完整的源代码。

NLP:用 TensorFlow 检测垃圾邮件(第一部分)

原文:https://towardsdatascience.com/nlp-detecting-spam-messages-with-tensorflow-b12195b8cf0e?source=collection_archive---------9-----------------------

训练递归神经网络进行文本分类

来源:来自 Pixabay免费照片

下面是一个如何使用递归神经网络来检测垃圾邮件的示例。本例中使用的数据集来自 Kaggle (原作者 Almeida 和 Hidalgo,2011 )。

在训练集中,某些邮件被标记为“垃圾邮件”(为此已用 1 替换)。非垃圾邮件被标记为“ham”(为此用 0 替换)。

递归神经网络是使用 TensorFlow 作者的原始单词嵌入和情感笔记本构建的——原始笔记本可在此处获得。

该分析通过以下步骤进行:

  1. 数据被加载,句子被分成训练集和测试集。
dataset = pd.read_csv('spam.csv')
datasetsentences = dataset['Message'].tolist()
labels = dataset['Category'].tolist()# Separate out the sentences and labels into training and test sets
training_size = int(len(sentences) * 0.8)training_sentences = sentences[0:training_size]
testing_sentences = sentences[training_size:]
training_labels = labels[0:training_size]
testing_labels = labels[training_size:]# Make labels into numpy arrays for use with the network later
training_labels_final = np.array(training_labels)
testing_labels_final = np.array(testing_labels)

2.数据集被标记化。换句话说,每个单词都被分配了一个唯一的数字——这是神经网络解释输入所必需的。

vocab_size = 1000
embedding_dim = 16
max_length = 100
trunc_type='post'
padding_type='post'
oov_tok = "<OOV>"from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequencestokenizer = Tokenizer(num_words = vocab_size, oov_token=oov_tok)
tokenizer.fit_on_texts(training_sentences)
word_index = tokenizer.word_index

3.然后将这些记号分类成序列,以确保每个单词的记号遵循每个句子所规定的正确顺序。

sequences = tokenizer.texts_to_sequences(training_sentences)

4.然后引入填充——在每句话尾引入 0。当一个句子比另一个句子长时,这是必要的,因为出于 RNN 分析的目的,每个句子必须具有相同的长度。

padded = pad_sequences(sequences,maxlen=max_length, padding=padding_type, 
                       truncating=trunc_type)testing_sequences = tokenizer.texts_to_sequences(testing_sentences)
testing_padded = pad_sequences(testing_sequences,maxlen=max_length, 
                               padding=padding_type, truncating=trunc_type)

5.递归神经网络在 20 个时期内建立和训练——输入层由一个嵌入层组成,该层用密集向量表示法表示句子。

递归神经网络(RNN)

以下是递归神经网络配置:

model = tf.keras.Sequential([
    tf.keras.layers.Embedding(vocab_size, embedding_dim, input_length=max_length),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(6, activation='relu'),
    tf.keras.layers.Dense(1, activation='sigmoid')
])
model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['accuracy'])
model.summary()

下面是对模型参数的详细介绍:

Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding (Embedding)        (None, 100, 16)           16000     
_________________________________________________________________
flatten (Flatten)            (None, 1600)              0         
_________________________________________________________________
dense (Dense)                (None, 6)                 9606      
_________________________________________________________________
dense_1 (Dense)              (None, 1)                 7         
=================================================================
Total params: 25,613
Trainable params: 25,613
Non-trainable params: 0

该模型产生以下训练和验证损失:

num_epochs = 20
history=model.fit(padded, training_labels_final, epochs=num_epochs, validation_data=(testing_padded, testing_labels_final))

来源:Jupyter 笔记本输出

在这种情况下,我们看到验证损失在 5 个时期后达到最低点。在这点上,选择 5 个时期再次运行模型。

来源:Jupyter 笔记本输出

对看不见的数据进行测试

现在模型已经建立,让我们看看分类器如何识别以下邮件中的垃圾邮件(我随机发明的):

  • 格雷格,你听到留言后能给我回个电话吗?(意图为正版)
  • 恭喜你有了新的 iPhone!点击此处领取您的奖品……'(意为垃圾邮件)
  • 真的很喜欢你的新照片(有意为之)
  • 你今天听到新闻了吗?‘发生了什么可怕的事情……’(本意是真诚的)
  • 立即参加免费的 COVID 网络研讨会:立即预订您的会议…’(意为垃圾邮件)

以下是生成的分数(分数越接近 1,该句子是垃圾邮件的概率越高:

['Greg, can you call me back once you get this?', 'Congrats on your new iPhone! Click here to claim your prize...', 'Really like that new photo of you', 'Did you hear the news today? Terrible what has happened...', 'Attend this free COVID webinar today: Book your session now...']
Greg, can you call me back once you get this?
[0.0735679]

Congrats on your new iPhone! Click here to claim your prize...
[0.91035014]

Really like that new photo of you
[0.01672107]

Did you hear the news today? Terrible what has happened...
[0.02904579]

Attend this free COVID webinar today: Book your session now...
[0.54472804]

我们看到,对于两个旨在作为垃圾邮件的消息,分类器显示两者都有很大的可能性。在句子的情况下,“今天参加这个免费的 COVID 网络研讨会:现在就预订您的会议……”-分类器在标记高于 50%的垃圾邮件概率方面表现相当好-即使在构建训练集时 COVID 不是一个术语。

在这方面,很明显,分类器依赖于使用单词的上下文,而不是简单地将单个单词标记为垃圾邮件。

鉴于递归神经网络在模拟序列数据和识别单词之间的模式方面是有效的,这个使用 TensorFlow 构建的简单垃圾邮件检测器已经被证明在我们用于测试目的的有限数据上是非常有效的。

结论

在本例中,我们看到:

  • 递归神经网络如何用于文本分类
  • 使用标记化、序列和填充为分析准备文本数据
  • 用于分析文本数据的神经网络模型的配置

此外,我们还看到了如何使用该模型来预测看不见的数据(或本例中的消息),以确定该模型在真实场景中的潜在工作方式。

非常感谢阅读,这个例子的相关 GitHub 库可以在这里找到。

更新:您还可以在本文的第二部分中找到对这个模型的更新,可以在这里找到

免责声明:本文是在“原样”的基础上编写的,没有任何担保。本文旨在提供数据科学概念的概述,不应被解释为任何形式的专业建议。作者与本文中提到的任何一方都没有关系,本文或其调查结果也没有得到同样的认可。

NLP:用 TensorFlow 检测垃圾邮件(第二部分)

原文:https://towardsdatascience.com/nlp-detecting-spam-messages-with-tensorflow-part-ii-77826c8f1abf?source=collection_archive---------65-----------------------

构建垃圾邮件检测模型时防止过度拟合

来源:图片来自 Pixabay

在我的上一篇文章中,TensorFlow 中的递归神经网络被用来检测垃圾短信。

这是通过以下方式实现的:首先通过标记化、文本排序和填充等方法以正确的方式操纵文本数据,然后最终训练模型来检测消息是垃圾邮件= 1 还是不是垃圾邮件= 0。

如果您不熟悉 NLP,我建议您先阅读我以前的文章——因为这篇文章的细节会更有意义:)

原始分析

示例中使用的数据集来自 Kaggle (原始作者 Almeida 和 Hidalgo,2011 )。

此外,递归神经网络是使用 TensorFlow 作者的原始单词嵌入和情感笔记本构建的——原始笔记本可在此处获得

尽管之前的模型被证明可以有效地为垃圾邮件分配更高的概率,但是仍然有改进的空间。

作为参考,使用以下神经网络配置:

Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding (Embedding)        (None, 100, 16)           16000     
_________________________________________________________________
flatten (Flatten)            (None, 1600)              0         
_________________________________________________________________
dense (Dense)                (None, 6)                 9606      
_________________________________________________________________
dense_1 (Dense)              (None, 1)                 7         
=================================================================
Total params: 25,613
Trainable params: 25,613
Non-trainable params: 0

此外,使用了最大长度为 100 的 1000 个词汇:

vocab_size = 1000
embedding_dim = 16
max_length = 100
trunc_type='post'
padding_type='post'
oov_tok = "<OOV>"

然而,当训练网络超过 30 个时期时,我们可以看到,随着验证损失在某个点之后开始增加,网络出现过拟合的迹象,而训练损失继续减少。

来源:Jupyter 笔记本输出

这表明该模型在训练数据的基础上过于一般化,因此该模型在预测现有消息方面表现良好,但在预测新消息方面表现不佳。

例如,我们可以看到,虽然该模型在为句子“恭喜您的新 iPhone!单击此处领取您的奖品……”,该模型只产生了以下可能是垃圾邮件的消息的 37% 概率:“立即参加免费的 COVID 网络研讨会:立即预订您的会议……”。

['Greg, can you call me back once you get this?', 'Congrats on your new iPhone! Click here to claim your prize...', 'Really like that new photo of you', 'Did you hear the news today? Terrible what has happened...', 'Attend this free COVID webinar today: Book your session now...']
Greg, can you call me back once you get this?
[9.670509e-06]

Congrats on your new iPhone! Click here to claim your prize...
[0.91056645]

Really like that new photo of you
[3.0444193e-05]

Did you hear the news today? Terrible what has happened...
[0.00360294]

Attend this free COVID webinar today: Book your session now...
[0.37343866]

在这方面,模型参数将被稍微调整,以查看模型的拟合度是否可以提高,即训练和验证损失都在减少的情况。

扁平化与全球平均池

在最后一个例子中,你会注意到使用了一个展平层。这样做的目的是为了将多维张量简化为一维张量,以便进行分析。

然而,全局平均池可以通过对数据进行平均来更好地表示向量,而扁平化可能会导致过度拟合的风险,这取决于数据量。

对此,我们再来训练一下模型。这一次,使用了一个 GlobalAveragePooling1D() 层来代替 Flatten。

Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding (Embedding)        (None, 100, 16)           16000     
_________________________________________________________________
global_average_pooling1d (Gl (None, 16)                0         
_________________________________________________________________
dense (Dense)                (None, 6)                 102       
_________________________________________________________________
dense_1 (Dense)              (None, 1)                 7         
=================================================================
Total params: 16,109
Trainable params: 16,109
Non-trainable params: 0

来源:Jupyter 笔记本输出

在训练时,我们可以看到训练和验证损失都显著下降,这表明模型没有过度拟合。

以下是尝试检测大量句子中的垃圾邮件的概率:

['Greg, can you call me back once you get this?', 'Congrats on your new iPhone! Click here to claim your prize...', 'Really like that new photo of you', 'Did you hear the news today? Terrible what has happened...', 'Attend this free COVID webinar today: Book your session now...']
Greg, can you call me back once you get this?
[0.02485983]

Congrats on your new iPhone! Click here to claim your prize...
[0.9198217]

Really like that new photo of you
[0.00754593]

Did you hear the news today? Terrible what has happened...
[0.00529179]

Attend this free COVID webinar today: Book your session now...
[0.42277685]

对于最后一句话,概率增加到 42%。然而,不清楚(甚至肉眼也不清楚)免费的 COVID 网络研讨会上的句子是否会被视为垃圾邮件。这将取决于其他因素,例如文本消息是否被请求、发送者的号码以及其他因素。在这方面,分配的概率似乎是合理的。

也就是说,在训练模型时,假设验证损失较低,我们可以更有信心认为每条短信的指示概率是可信的。

如上所述,使用了最大长度为 100 的 1000 个词汇。用 30 个时期训练,在时期 30 的验证损失为 0.0642,验证准确度为 0.9848。假设验证精度已经相当高,那么如果这些参数减少,模型还会产生准确的结果吗?

为了测试这一点,让我们将词汇量设置为 600,最大长度为 60。

来源:Jupyter 笔记本输出

在这种情况下,验证准确度为 0.9865,验证损失为 0.0455。在这种情况下,模型实际上表现得稍好一些,这表明模型中的词汇大小可以在不影响性能的情况下减少。

下面是我们在上面看到的一系列假设消息的更新概率:

['Greg, can you call me back once you get this?', 'Congrats on your new iPhone! Click here to claim your prize...', 'Really like that new photo of you', 'Did you hear the news today? Terrible what has happened...', 'Attend this free COVID webinar today: Book your session now...']
Greg, can you call me back once you get this?
[0.01641327]

Congrats on your new iPhone! Click here to claim your prize...
[0.9475718]

Really like that new photo of you
[0.00675001]

Did you hear the news today? Terrible what has happened...
[0.00826639]

Attend this free COVID webinar today: Book your session now...
[0.3014569]

结论

这个例子是上一个教程使用递归神经网络检测垃圾短信的后续。

具体来说,我们看到了扁平化和全局平均池在训练模型时的不同之处——在较小的训练集上使用扁平化有过度拟合的风险,这里似乎就是这种情况。此外,我们还看到了正确的模型配置如何在较小的词汇表中产生出色的结果。

TensorFlow 作者(版权 2020)在这里提供了这个例子的原始模板。此外,我推荐 Udacity 提供的深度学习 TensorFlow 的简介课程,以便更深入地理解这个主题。

上面例子的 GitHub 库可以在这里找到。

免责声明:本文是在“原样”的基础上编写的,没有任何担保。本文旨在提供数据科学概念的概述,不应被解释为任何形式的专业建议。作者与本文中提到的任何一方都没有关系,本文或其调查结果也没有得到同样的认可。

python 中常见术语的 NLP 简易解释

原文:https://towardsdatascience.com/nlp-easy-explanation-of-common-terms-with-python-dc7c323a4691?source=collection_archive---------49-----------------------

自然语言处理 ( NLP )是数据科学处理语言学的领域,人工智能涉及计算机系统与人类语言的交互,以解释和分析系统中的自然语言,这是数据科学中一个不断扩展的领域,其中各种技术被应用于分析大量的自然语言数据。**

NLP[作者图片]

用于这项工作的最流行的库是 nltk,它可以通过下面的代码行导入。

**import nltk**

下面给出了我们在讨论 NLP 模型时使用的几个常用术语及其含义和实现。

  1. ****标记化:将文本分解成更小的部分称为标记化。它可以把段落分成句子,把句子分成单词。
**# Tokenizing sentences
sentences = nltk.sent_tokenize(paragraph)

# Tokenizing words
word = nltk.word_tokenize(paragraph)**

段落[图片由作者提供]

段落被分割成句子[图片由作者提供]

段落被拆分成单词[图片由作者提供]

****2)词干化:将许多相似的词化简为一个词干或基词,称为词干化。

英语中最流行的词干分析器叫做波特斯特梅尔,它是 nltk 的一个库。

斯特梅尔函数的例子如下:

词干[作者图片]

优点: 这是快速算法,可以用在需要速度的模型中。

缺点: 没有考虑到 stem 函数的意义,只是把它简化为 stem。

在 python 中,它是这样完成的:

**#import
from nltk.stem.porter import PorterStemmer
ps = PorterStemmer()
review = [ps.stem(word) for word in review if not word in set(stopwords.words('english'))]**

示例如下:

词汇化[图片由作者提供]

优点: 它主要用于聊天机器人,因为给出有意义的回应是它的主要思想。

缺点: 比炮泥慢,时间是主要考虑的地方就是时间。

*****#import*
from nltk.stem import WordNetLemmatizer
wordnet=WordNetLemmatizer()
review = [wordnet.lemmatize(word) for word in review if not word in set(stopwords.words('english'))]****

4) 停用词: 在语言处理中不是很重要的词,可以在对其应用任何模型之前,或者在对其进行情感处理之前去除。像 is,an,you,the 这些词可以称为停用词,可以从 nltk.corpus 导入为' nltk.corpus 导入停用词'。

停用词[图片由作者提供]

在 Python 中:

****#import
from nltk.corpus import stopwords
review = [wordnet.lemmatize(word) for word in review if not word in set(stopwords.words('english'))]****

5) 单词包这是机器学习算法中一种表示和处理单词的方式。它代表单词的出现和频率。它是在自然语言处理中使用的模型,表示为其单词 (multiset),不考虑语法甚至单词的顺序,而是保持其出现的次数。****

优点:

考虑了它的速度和频率。容易实现。

缺点:

它没有将数据表示成信息,也就是说,在这样做的时候,单词的含义丢失了。它假设所有的单词都是相互独立的。

仅适用于小数据。

例如:

她是一个非常好和体面的女人,她也是一个很好的艺术家。

他是个坏人,但却是个好司机。

第三句:体面社会男女平等。

单词包[图片由作者提供]

****# Creating the Bag of Words model
from sklearn.feature_extraction.text import CountVectorizer
cv = CountVectorizer(max_features = 1500)
X = cv.fit_transform(paragraph).toarray()****

6) TFIDF: 词频-逆文档频率,是一个统计公式,在该公式中评估一个词在文本集合中的文本中的相关程度。它是通过两个指标的乘积获得的,即术语频率和逆文档频率。

词频 =一句话中的重复字数/一句话中的字数。

逆文档频率 =log(句子数量/包含单词的句子数量)

例如:

她是一个非常好和体面的女人,她也是一个很好的艺术家。

第二句:他是个坏人,但却是个好司机。

第三句:体面社会男女平等。

把停用词去掉,句子就可以变得更简洁。

第一句:很好很正派的女人好艺术家。

第二句:坏人好司机。

第三句:男女平等体面社会。

其计算方法如下:

TF[作者图片]

IDF[图片由作者提供]

tfi df[作者图片]

优点: 易于计算和实现。它可以给出一些基本的度量来提取文本中最具描述性的术语。使用它可以很容易地计算两个文本之间的相似度。搜索引擎可以使用它。

缺点: TF-IDF 不能捕获文本中单词的语义或出现位置。

在 Python 中,这可以通过以下方式实现:

******# Creating the TF-IDF 
from sklearn.feature_extraction.text import TfidfVectorizer
cv=TfidfVectorizer()
X=cv.fit_transform(paragraph).toarray()******

7) Word2Vec 是一种自然语言处理(NLP)的技术。word2vec 算法使用神经网络模型从大型文本语料库中学习单词语义及其关联。一旦经过训练,这种模型可以检测相似的单词,或者让我们知道部分句子的附加单词。顾名思义,word2vec 用称为向量的特定数字列表来表示每个不同的单词。

仔细选择向量,使得向量之间的简单数学余弦表示由这些向量表示的单词之间的语义相似度。

word 2 vec[图片由作者提供]

优点:

这通过将目标词映射到与其有上下文关系的词来将未标记的原始语料库转换成标记的数据,从而学习词在分类模型中的表示。

目标词与其上下文关系词之间的映射将次线性关系嵌入到词的向量空间中,从而可以通过词向量来推断类似于“国王:男人作为王后:女人的关系。****

易于理解和实施。

缺点:

单词序列丢失,因此子线性关系没有被很好地定义。

数据必须在线提供给模型,并且可能需要预处理,这需要存储空间。

如果类别的数量太大,即语料库太大并且词汇太多,则该模型可能非常难以训练。

在 Python 中,它可以实现为:

****from gensim.models import Word2Vec
from gensim.models import KeyedVectorssentences = nltk.sent_tokenize(paragraph)
sentences = [nltk.word_tokenize(sentence) for sentence in sentences]# Training the Word2Vec model
model=Word2Vec(sentences, min_count=1)
words=model.wv.vocab

# Most similar words
similar=model.wv.most_similar('woman')#Output[ ('driver', 0.15176300704479218),
 ('artist', 0.06272515654563904),
 ('good', 0.0425836481153965),
 ('man', -0.0059792473912239075)]****

结论:

值得注意的是,每种技术都是在发现它的缺点之后发展起来的,比如词汇化比词干化更好,因为它可以将相似的单词转换成一些有意义的单词。TFIDF 比单词袋更好,因为它可以包含比单词袋更好的信息。Word2Vec 比 TFIDF 更好,因为它可以预测单词之间的上下文关系。

同样,在所有这些技术中,语义或单词顺序丢失,为此 RNN 或递归神经网络出现,其中按照单词顺序的所有重要信息保持完整,并且情感分析以惊人的方式完成。

希望通过阅读这篇博客,许多术语必须清楚,NLP 可能看起来更容易。

感谢阅读!

原载于 2020 年 10 月 26 日 https://www.numpyninja.comT21

NLP:单词嵌入技术去神秘化

原文:https://towardsdatascience.com/nlp-embedding-techniques-51b7e6ec9f92?source=collection_archive---------9-----------------------

词袋 vs TF-IDF vs word 2 vec vs doc 2 vec vs doc 2 vec

乔纳斯·雅各布森在 Unsplash 上拍摄的照片

单词嵌入是一种单词表示技术,允许具有相似含义的单词被机器学习算法理解。从技术上讲,它是使用神经网络、概率模型或对单词共现矩阵进行降维,将单词映射到实数向量。

可以使用各种语言模型来学习单词嵌入。比如一只 ' 狗' 会用向量【0.75,0.22,0.66,0.97】来表示。如果字典中的所有单词都以这种方式编码,就有可能相互比较单词的矢量,例如通过测量矢量之间的余弦距离或欧几里德距离。单词的良好表示将使得有可能发现单词 ' 宠物' 比单词 ' 足球''引擎 ' 更接近单词 ' 狗' 。所以这些表象让我们希望,在嵌入的向量空间里,我们会有方程 国王-男人+女人=王后 甚至方程 伦敦-英格兰+意大利=罗马

单词嵌入在减轻维数灾难方面也非常有用,维数灾难是人工智能中经常出现的问题。如果没有单词嵌入,表示单词的唯一标识符会生成分散的数据,即大量稀疏表示中的孤立点。另一方面,使用单词嵌入,空间在维度方面变得更加有限,语义信息量更加丰富。有了这些数字特征,计算机更容易执行不同的数学运算,如矩阵分解、点积等。这是强制使用浅层和深层学习技术。有许多技术可供我们使用来实现这种转变。在本文中,我们将涉及:B ag-Of-Words、TF-IDF、Word2Vec、Doc2vec 和 doc 2 vec。

1.词汇袋

词袋( a.k.a. BOW)是一种流行的生成文档表示的基本方法。文本被表示为包含大量单词的包。语法和词序被忽略,而频率保持不变。词袋生成的特征是一个向量,其中 n 是输入文档词汇中的字数。

例如,有两个文档:

  • doc_1: “我喜欢意大利菜和突尼斯菜。”
  • doc_2: “我喜欢这里的食物。”

这两份文件的词汇是:

【“我”、“爱”、“意大利”、“美食”、“和”、“突尼斯”、“这里”】

这个词汇将产生长度为 8 ( 词汇基数)的特征向量。给定这样的词汇表,这两个文档的词袋特征表示为:

  • BOW(doc _ 1):【1,1,1,2,1,1,0,0】
  • BOW(doc _ 2):【1,1,0,1,0,0,1,1】

使用这种技术,我们为数据集中的每个文档创建单词包表示。如果我们的数据集包含大量独特的单词,其中一些并不经常使用,这是通常的情况。因此,在这些词中,我们选择了 N 个最频繁出现的词,并创建了一个维度为 Nx1 的特征向量。这些特征向量然后被用于任何机器学习任务。

2.术语频率-逆文档频率

术语频率-逆文档频率( a.k.a. TF-IDF)是基于单词表示文档的另一种方式。利用 TF-IDF,通过 TF-IDF 重要性而不仅仅是频率来给单词赋予权重。TF-IDF 提供了一种统计度量,用于评估单词相对于集合或语料库中的文档的重要性。每个数据集都有许多常用词,它们在文档中多次出现,但并不提供任何重要信息。权重与该单词在文档中出现的次数成比例增加。它还根据该词在语料库中的出现频率而变化。原始公式的变体经常在搜索引擎中使用,以基于用户的搜索标准来评估文档的相关性。

根据定义,TF-IDF 嵌入由两项组成:第一项计算归一化词频(TF),也称为一个单词在文档中出现的次数,除以该文档中的单词总数;第二项是逆文档频率(IDF ),它计算语料库中文档数量的对数除以特定术语出现的文档数量。

如下图所示, scikit-learn 库在子模块[**sklearn.feature_extraction.text**](https://scikit-learn.org/stable/modules/classes.html#module-sklearn.feature_extraction.text)中包含了从文本文档构建特征向量的收集工具,在其中我们会发现[**CountVectorizer**](https://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.CountVectorizer.html#sklearn.feature_extraction.text.CountVectorizer)**.** [**CountVectorizer**](https://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.CountVectorizer.html#sklearn.feature_extraction.text.CountVectorizer)可以轻松地将一组原始文档转换成 TF-IDF 数字特征矩阵。

使用 Sklearn 的 tfidf 矢量器

3.Word2Vec

表示单词的最有效的技术之一是 Word2Vec。Word2vec 是一个计算效率高的预测模型,用于从原始文本中学习单词嵌入。它在多维向量空间中绘制单词,其中相似的单词倾向于彼此接近。一个单词的周围单词提供了该单词的上下文。

让我们从一个高层次的视角来看我们要去哪里。Word2Vec 在深度学习中使用了一个众所周知的技巧。在这个技巧中,我们训练了一个具有单个隐藏层的简单神经网络来执行一个假任务,而不需要我们训练它的任务的结果。相反,主要目标包括学习输入数据的表示,其实际上是从学习的隐藏层的权重收集的 【字向量】 。这种方法可能会让我们想起我们训练自动编码器进行降维的方式。

Word2Vec 可以依赖两种模型架构中的任何一种来生成输入单词的分布式表示: 连续单词包(CBoW)连续跳格,如下图所示。向量表示基于数据集中单词的共现来提取语义关系。

使用二元分类来训练 CBoW 和 skip-gram 模型,以区分真实的目标单词和相同上下文中的其他单词。模型预测单词的准确性取决于模型在整个数据集中的相同上下文中看到这些单词的次数。在训练过程中,通过更多的单词和上下文共现来改变隐藏表示,这允许模型具有更多的未来成功预测,从而导致单词和上下文在向量空间中的更好表示。Skip gram 比 CBOW 慢得多,但是对于不常用的单词执行得更准确。

[Word2Vec 训练模型架构](http://@misc{mikolov2013efficient, title={Efficient Estimation of Word Representations in Vector Space}, author={Tomas Mikolov and Kai Chen and Greg Corrado and Jeffrey Dean}, year={2013}, eprint={1301.3781}, archivePrefix={arXiv}, primaryClass={cs.CL} })

让我们更深入地了解 CBOW 体系结构和连续跳转程序之间的区别。

  • 第一个选项中,CBOW;该模型从周围上下文单词的窗口中预测当前单词。上下文单词的顺序不影响预测(单词袋假设)。例如,如果你给训练好的网络输入单词、【NBA】、【游戏】、、【网球】、,那么像、【网球】、这样的单词的输出概率要比像、【选举】、这样的不相关单词的输出概率高得多。
  • 而在使用 连续跳格架构的第二选项中; 该模型使用当前单词来预测周围窗口中的上下文单词。跳格结构比更远的上下文单词更重视附近的上下文单词。输出概率将与在我们的输入单词附近找到每个词汇单词的可能性有关。例如,如果你给训练好的网络输入单词"欧洲",那么像"比利时""大陆"这样的单词的输出概率要比像"水果""猫"这样的不相关单词的输出概率高得多。

在这两个模型中,当我们说 【环绕】 时,实际上有一个 【窗口大小】 参数给算法。上下文窗口的大小限制了给定单词前后有多少单词将被包括作为给定单词的上下文单词。例如, 3 的窗口大小将包括句子中每个观察到的单词左边的 3 单词和右边的 3 单词作为上下文。增加窗口大小会增加训练时间,因为需要训练更多的单词上下文对。它还可以捕获与当前单词不相关的上下文单词。减少上下文单词可以捕获单词和停用单词之间的关系,这不是优选的。

4.Doc2Vec

Doc2Vec 是另一种广泛使用的技术,它创建文档的嵌入,而不考虑其长度。Word2Vec 为语料库中的每个单词计算特征向量,Doc2Vec 为语料库中的每个文档计算特征向量。Doc2vec 模型基于 Word2Vec,只是在输入中增加了另一个向量(段落 ID) 。与 Word2Vec 类似,Doc2Vec 模型可以依赖于两种模型架构中的一种:段落向量的分布式存储器版本 (PV-DM) 和段落向量的分布式单词包版本 (PV-DBOW)。

在下图中,我们展示了 PV-DM 的模型架构:

Doc2Vec 模型架构

上图是基于 CBOW 模型的,但是我们没有使用邻近的单词来预测单词,而是添加了另一个特征向量,它是文档特有的。因此,当训练单词向量 W 时,文档向量 D 也被训练,并且在训练结束时,它保存文档的数字表示。

输入由单词向量和文档 Id 向量组成。单词 vector 是一个一维的 hot vector1xV。文档 Id 向量的维数为1xC,其中 C 是文档总数。隐藏层的权重矩阵 W 的维数为NxV。隐藏层的权重矩阵 D 的维数为CxN

5.Doc2vecC

Doc2vec 通过捕获文档的语义来包含全局上下文,从而解决了 doc 2 vec 的问题。架构与 Word2vec 非常相似。在 Doc2VecC 中,使用文档中单词嵌入的平均值来表示全局上下文。但是,与 Word2vec 不同,在每次迭代中,单词都是从文档中随机抽取的(文档损坏)。然后,对这些单词的向量进行平均,以获得文档向量。该文档向量然后被用于使用局部上下文单词以及全局上下文来预测当前单词。全球环境是通过无偏见的辍学腐败产生的。此损坏的文档表示为:

然后,给定局部上下文 c_t 和全局上下文 x_i ,观察到单词 w_t 的概率被给出为:

一旦我们使用神经网络学习了 U ,每个文档就可以简单地表示为嵌入在该文档中的单词的平均值。因此,文档向量 I 被给定为:

模型的输出共享数据集的全局和局部语义。平均还帮助我们获得看不见的文档的向量,因此解决了 Doc2vec 提出的问题。因为只有一小部分单词用于训练,所以与 Doc2vec 相比,训练时间要少得多。在任何文档中,单词都从其相邻单词中获得上下文。因此,为了提供更多的上下文,我们将公开可用的数据集附加到我们的数据集,这些数据集是用于商业、评论的文本数据以及用于个人、教育和学术目的的用户数据的子集。

了解你的作者

拉贝赫·阿亚里是首席数据科学家,致力于信用风险建模和欺诈分析的应用人工智能问题,并在机器学习方面进行原创研究。我的专业领域包括使用深度神经网络的数据分析、机器学习、数据可视化、特征工程、线性/非线性回归、分类、离散优化、运筹学、进化算法和线性编程。随时给我留言这里

印度语言的自然语言处理

原文:https://towardsdatascience.com/nlp-for-indian-languages-310d1d8a10b6?source=collection_archive---------11-----------------------

和我一起探索在印度本土语言环境中自然语言处理的需求、挑战和工具

需求

如果你正在阅读这篇文章,你很有可能已经掌握了相当不错的英语。如果你来自印度,也有可能英语不是你唯一知道的语言。大多数印度人会说多种语言💬在学校里学习不止一种语言。

杰基山·帕特尔Unsplash 上拍摄的照片

然而,你能猜出这个国家说英语的人的百分比吗?答案可能会让你大吃一惊。试一试!🏃

图 1: 印度母语人数的语言。信用: Filpro维基百科

印度说英语的比例是… 刚好 10%【1】。那是十几亿人口的 10%!

大多数印度人以印地语为第一语言,其次是马拉地语、泰卢固语、旁遮普语等。对于生活在农村社区的许多人来说,英语甚至不是他们能理解或说的语言。

顺便提一下,要了解印度说英语的人口统计概况,请参考[2]。

自然语言处理,通常简称为 NLP,是一个跨学科领域,处理计算机和人类之间使用自然语言的交互。

NLP 是一种让计算机以智能和有用的方式从人类语言中分析、理解和推导含义的方法。

既然印度的语言背景和 NLP 的目的已经很清楚了,让我们更深入地了解一下为什么这很重要。

有人可能认为熟悉计算机的人已经熟悉了英语界面。然而,值得注意的是,在印度的大多数印度人仍然生活在农村地区,那里的教学和学习将使用当地语言,那里的社区有文化,但仍然不熟悉英语。所以,是的,在印度提升 NLP 研究是值得的。[3]

如果不把印度的自然语言处理研究和应用提升到与英语等语言同等的水平,就无法实现无所不包的数字印度的梦想。

当使用智能手机时,语言障碍对许多人来说是一个巨大的障碍。

以长期以来被视为印度支柱的农民和农业为例。农民在养活这个国家方面显然起着重要的作用。帮助这些农民改进他们的方法(通过精准农业、农民帮助热线、聊天机器人等)一直是发展项目的目标,也是抗击全球饥饿的重要组成部分。但是许多小农场主不懂英语,这意味着他们很难分享和学习新的农业实践,因为大部分信息都是英语的。

即使我们的农民可以使用互联网或工具,如果他不能用母语与他们交流,他可能不知道如何使用它们。(照片由南杜·库马尔Unsplash 上拍摄)。)

你能想象一个像谷歌助手一样,但却是为印度农民量身定制的移动应用吗?这将允许他们用自己的母语提问,系统将理解他们的查询并给出来自全球的相关信息🌏。

您认为没有印度地区语言的自然语言处理,这可能吗?

这只是一个可能的使用案例。从让信息更容易获取 了解农民自杀【4】,NLP 扮演着巨大的角色。

因此,很明显需要加强对印度语言的自然语言处理研究,这样那些不懂英语的人就可以真正意义上的“在线”,用他们的母语提问并得到答案。

事实上, AI4Bharat(一个加速印度人工智能创新的平台)的人非常恰当地总结了这种情况:

虽然印度有丰富的语言,但却缺乏这些语言的资源。

当我们看到 NLP 在印度的一些应用时,这种需求也变得很明显。

应用程序

它们是:

  1. 印度智能手机用户在 2019 年突破 5 亿。企业感到有必要增加当地用户的参与度。NLP 在实现这一点上还有很长的路要走——通过提高搜索准确度(谷歌助手现在支持多种印度语言)、聊天机器人和虚拟代理等。
  2. NLP 在帮助残疾人方面有着巨大的应用——手语翻译、文本到语音、语音到文本等。
  3. 印度手稿的数字化保存其中包含的知识。
  4. 从本地语言翻译招牌让旅行更便捷。
  5. 印度文字字体用于提高广告、招牌、演示、报告等的影响力/可读性。

还有很多。理想的情况是拥有和英语一样高质量的语料库和工具来支持这些领域的工作。

顺便说一下,人工智能(自然语言处理)越来越多地被用于像讲故事这样的创造性任务。已经有人工智能故事生成器可以生成令人信服的英文故事情节。想象有一天,印度的孩子们可以玩这样的人工智能发电机,用印度方言创作故事!如今,我们还可以使用人工智能将文本的画外音添加到我们的视频中。

挑战

总的来说,有些问题会影响到自然语言处理,

  • 不同层次的歧义——句法、语义、语音歧义等。
  • 处理习语和隐喻。
  • 处理情绪。
  • 寻找回指和下指的指称对象。
  • 语用学中的理解话语与挑战。

但是,由于英语和印度语之间的差异,出现了一些问题。因此,它们是印度语言特有的。

Below an attempt has been made to gather information about work in NLP for specific regional languages. If you feel something is amiss or some work has not been properly credited, contact me via [email](mailto:singh.navkiran1515@gmail.com) and I'll fix it.

以印地语为例。它在几个方面不同于英语。

这些差异包括:

1.在句子结构上,英语使用主语-动词-宾语语序,而印地语使用主语-宾语-动词。

图 2:英文版 SOV 订单 vs SVO 订单。

2.存在后置格标记而不是介词。

图 2: 印地语的后置格标记。

3.在许多印度语言中,单词可以自由移动而不改变意思。

图 3: 印地语句子中的动名词。

处理印地语的问题:

1.缺少带注释的语料库和工具。

2.缺乏教育和培训机构。

3.大量的形态变异。

与英语相比,学习印度语言 NLP 的在线资源是有限的。

旁遮普语特有的一些问题:

1.大量的形态变体和词根复杂性。

2.旁遮普在旁遮普的不同地区有不同的方言,略有不同。这增加了预处理工作。

  • Maajhi——在阿姆利则、古尔达斯普尔和塔恩-塔恩地区使用
  • 马尔瓦伊 —巴丁达、帕蒂亚拉、菲罗兹布尔和莫加
  • Doabi——Jalandhar、Hoshiarpur 和 Nakodar

图 3: 不同的旁遮普方言。(来源)

图 4: 马尔瓦伊语、多比语和马杰哈语中不同的几个词的例子。有关详细信息,请参考[4]。

3.很难找到与特定地区相关的数据集。

4.理解旁遮普语中的讽刺。

5.理解诗歌。

像 Kaggle,UCI 机器学习库等可靠来源提供的许多数据集都是英文的。

有限的数据集、语料库和其他资源是一个巨大的障碍。只有一个停用词列表,总共有 184 个词,早在 2016 年就向公众发布了。更多细节参见[5]。

其他一些观察结果:

有趣的是,当我搜索泰卢固语 NLP 的资源时,我找到的最上面的 GitHub 结果是 this ,并且在撰写本文时它已经 4 年了,没有更新。

然而,泰卢固语在 Kaggle 上确实有一个数据集。还有一个泰米尔语的数据集。尽管如此,讨论和内核很少,似乎没有引起印度数据科学界的关注。

许多问题是所有地区语言共有的,例如:

  • 缺乏数据集/语料库。
  • 缺乏统一的努力。
  • 大量的形态变异。
  • 缺乏标准。

更多细节参见[6]。

工具

下面列出了我能找到的一些工具及其官方描述和文档链接。

My purpose is to include these for completeness. Their documentation is pretty informative and detailed with relevant usage examples. For api usage examples, it's best to refer to the source documentation, since it will always be up-to-date.Nonetheless, if more examples are needed, I’ll add them in a future update or a future post. Let me know if there's any other tool that should be mentioned here.
  1. 印度文自然语言程序库

从官方描述来看:

The goal of the Indic NLP Library is to build Python based libraries for common text processing and Natural Language Processing in Indian languages. Indian languages share a lot of similarity in terms of script, phonology, language syntax, etc. and this library is an attempt to provide a general solution to very commonly required toolsets for Indian language text.The library provides the following functionalities:1\. Text Normalization
2\. Script Information
3\. Tokenization
4\. Word Segmentation
5\. Script Conversion
6\. Romanization
7\. Indicization
8\. Transliteration
9\. Translation

api 用法和示例请参考官方文档

  1. iNLTK
iNLTK aims to provide out of the box support for various NLP tasks that an application developer might need.Supported languages at the time of writing:1\. Hindi  
2\. Punjabi 
3\. Sanskrit   
4\. Gujarati   
5\. Kannada  
6\. Malayalam   
7\. Nepali   
8\. Odia   
9\. Marathi   
10\. Bengali   
11\. Tamil  
12\. Urdu   
13\. English 

api 用法和示例请参考官方文档

3.Stanford NLP——尽管我在 Stanford CoreNLP(网站链接)上找不到印度语言的语言包,但我确实找到了一种可能的方法来使用它,请参考这里的。我个人没试过。

结论

NLP 在印度的旅程似乎漫长而令人生畏,但正如一句著名的谚语所说:

千里之行始于足下!

好消息是,由于数百名研究人员、行业专家和学生的努力,我们在很短的时间内取得了重大进展。NLP 在印度的前景似乎一片光明,应用前景无限。

照片由 Gayatri MalhotraUnsplash 上拍摄

但是,正如罗伯特·弗罗斯特在他的诗《雪夜林边驻足》中所写的,我们在睡觉前还有很长的路要走。

参考

[1] 印度的多语制,维基百科上根据印度人口普查数据 (2011)等来源汇编的统计数据。(2020 年 3 月 20 日访问)

[2] Rukmini S (2019),在印度,谁说英语,在哪里?,Livemint。(2020 年 3 月 20 日访问)

[3]马达利、德维卡&帕特尔、酒窝。(2009).印度语言计算中的问题,特别是泰卢固语的搜索和检索。图书馆高科技。27.450–459.10.1108/07378830910988568.

[4]辛格,贾斯普里特&辛格,古尔文德&辛格,拉金德&辛格,普里特维帕尔。(2018).使用深度学习分类的旁遮普语文本的形态评价和情感分析。沙特国王大学学报-计算机与信息科学。10.1016/j.jksuci.2018.04.003

[5] Kaur,Jasleen & Saini,Jatinderkumar。(2016).旁遮普语停止词:一部古尔姆基语、沙赫姆基语和罗马脚本编年史。32–37 岁。10.1145/2909067.2909073.

[6]c . Kurian 和 k . Kannan Balakrishnan,2008 年。印度自然语言处理的前景和挑战。在关于“计算科学的最新趋势的国际会议记录中。

您已到达终点!感谢您的阅读,祝您度过愉快的一天。😄我希望这些内容对你有用。

如果你有任何反馈💭或者注意到了错误,请留下评论。我想❤️to 听听你的想法。

从时间序列的角度看 NLP

原文:https://towardsdatascience.com/nlp-from-a-time-series-perspective-39c37bc18156?source=collection_archive---------24-----------------------

时间序列分析如何补充自然语言处理

来源:来自 Pixabay免费照片

从表面上看,自然语言处理(NLP)和时间序列分析似乎没有太多的共同点。

在数据科学的背景下,分析文本的主要原因通常如下:

  1. 文本摘要(即对文本进行摘要以便更好地理解)
  2. 文本分类(例如,根据某些特征对文本进行分类,如检测垃圾邮件)
  3. 情感分析(使用文本分类来确定特定群体对某个主题的情感,例如书评)
  4. 文本生成(即使用机器学习技术生成特定主题的新文本)

当文本分类模型失败时

在这方面,我特别希望解决文本分类和情感分析的领域。

让我们考虑一个例子。假设有人在 2019 年建立了一个情绪分析模型,以衡量旅行情绪。数据可能来自各种社交网络,如 Twitter、Reddit 等。

尽管由于旅游对气候变化的影响存在一定程度的担忧,但人们对旅游的情绪可能仍然相当积极。

然而,2020 年对于旅行来说是一个非常不同的场景(或者说没有),由于新冠肺炎疫情,航空乘客数量急剧下降。

因此,如果今天运行,任何根据 2019 年数据训练的情绪模型都可能表现很差。旅行限制、对病毒的恐惧和经济问题可能在任何用于训练文本分类模型以衡量旅行情绪的语料库中都没有得到充分的体现。此外,术语“新冠肺炎”在今年之前并不存在,并且文本分类模型不知道在旅行的上下文中将负面情绪分配给该术语。

时间序列分析的潜力

文本分类和情感分析技术是最近的创新。

因此,在很长一段时间内,即几年内,没有太多的空间来制定一个跟踪情绪的时间序列。然而,随着 NLP 技术现在变得越来越普遍,这种技术很可能从这里开始变得越来越普遍。

回到旅行的例子,假设我们有一个随时间整理的训练集,其中包含按日期排序的句子,这些句子表达了对旅行的特定情感。仅举两个例子:

来源:作者创建的图像和数据

现在,假设一个情绪分数是通过每周的所有个人分数相加计算出来的。以下时间序列仅仅是假设性的,但出于所有意图和目的,让我们假设从 2019 年初到现在的旅行情绪看起来像这样:

来源:作者创建的数据

在这个假设的例子中,在新冠肺炎到来之前,市场情绪总体上是积极的,尽管时间序列往往会伴随着不可避免的“波动和低谷”。

如上图所示,COVID 之后,旅游人气可能会比之前更加不稳定。有些人发誓在疫情完全被控制之前不进行任何形式的旅行,而有些人则选择在任何限制取消后立即旅行。

在现实世界中,用于情感模型的训练数据需要不断更新,以确保在所有单独的文本条目中准确地衡量情感。

然而,情感数据时间序列的公式不仅允许随着时间的推移跟踪这种情感,而且还可以与时间序列建模技术一起使用,以与预测常规时间序列相同的方式预测未来的情感。这可以通过传统的时间序列技术(如 ARIMA)或基于机器学习的技术(如 LSTM、CNN 等)来完成。

在旅游环境中,如果有足够的情绪数据,预测情绪趋势以确定旅游情绪何时会上升是可能的。这不一定是万无一失的,因为这个特殊的例子更依赖于新冠肺炎的结果,而不是从过去的趋势推断,但很可能是一种有用的分析形式。

事实上,考虑到 NLP 是一个相当新的研究领域,关于情感分析是否可能在某些时间序列领域中作为领先指标的问题仍然存在。

例如,假设在某个时间点,在社交媒体帖子中检测到股市的异常负面情绪。根据主要股票指数(如标准普尔 500)的价格变化,人们可以使用时间序列来验证情绪在股票价格波动中的作用。

股价是在负面情绪表达的那一刻下跌的——还是有一个小时左右的滞后?另一方面,在任何负面情绪通过社交媒体表达出来之前,市场调整了吗?

结合时间序列分析和 NLP 来回答这些问题,可以在确定情绪分析在金融市场中扮演的角色方面产生巨大的洞察力。

结论

作为一名时间序列专家,我的观点是 NLP 是一种很好的分析形式——但是当与时间序列技术结合时,它的潜力可以被完全释放。

为了充分理解情绪分析对某些业务领域的影响,我们还必须了解情绪如何随着时间的推移而变化,以及支撑这种变化的催化剂。

到目前为止,NLP 还是一个相当新的领域,这个领域还没有被充分开发。然而,我认为,如果正确使用,自然语言处理和时间序列分析可以证明是向前发展的杀手组合。

非常感谢您的阅读,您也可以在michael-grogan.com找到更多我的数据科学内容。

免责声明:本文是在“原样”的基础上编写的,没有担保。它旨在提供数据科学概念的概述,不应以任何方式解释为专业、医疗或投资建议。

Python 中的 NLP 数据清理

原文:https://towardsdatascience.com/nlp-in-python-data-cleaning-6313a404a470?source=collection_archive---------6-----------------------

使用 Kaggle 的真实或虚假新闻数据集的典型 NLP 机器学习模型管道中涉及的数据清洗步骤。

来自 UnsplashRoman Kraft 的照片

在任何机器学习模型中,数据清洗都是非常关键的一步,但对于 NLP 来说更是如此。如果没有清理过程,数据集通常是计算机无法理解的一串单词。在这里,我们将回顾在典型的机器学习文本管道中完成的清理数据的步骤。

我们将使用一个将新闻分为真假的数据集。数据集可以在 Kaggle 上找到,数据集的链接在下面,

https://www . ka ggle . com/clmentbisaillon/fake-and-real-news-dataset

有两个数据集 Kaggle 数据集中的假新闻和真新闻。我把假新闻和真实新闻的数据集连接起来。十大真假新闻如下:

news.head(10)

10 条假新闻

news.tail(10)

10 条真实新闻

我们将通过几个步骤来清理新闻数据集,删除不必要的内容,并突出适合 ML 模型的关键属性。

第一步:标点

标题文本有几个标点符号。标点符号通常是不必要的,因为它不会增加 NLP 模型的价值或意义。“字符串”库有 32 个标点符号。标点符号是:

import string
string.punctuation

字符串库中的标点符号

要删除数据集中的标点符号,让我们创建一个函数并将该函数应用于数据集:

def remove_punctuation(text):
    no_punct=[words for words in text if words not in string.punctation]
    words_wo_punct=''.join(no_punct)
    return words_wo_punctnews['title_wo_punct']=news['title'].apply(lambda x: remove_punctuation(x))
news.head()

新闻数据集(包括标题,不带标点符号)

步骤 1 之后的列已经从标题文本中删除了标点符号。

步骤 2:标记化

标记化是将字符串拆分成单词列表的过程。我们将利用正则表达式或正则表达式来进行拆分。正则表达式可以用来描述一个搜索模式。

def tokenize(text):
    split=re.split("\W+",text) 
    return split
news['title_wo_punct_split']=news['title_wo_punct'].apply(lambda x: tokenize(x.lower()))
news.head()

这里,“\W+”拆分一个或多个非单词字符

新闻数据集(包括标题,不带标点和拆分)

步骤 2 之后的列通过拆分所有非单词字符创建了一个列表。

第三步:停用词

现在,我们有一个没有任何标点符号的单词列表。让我们继续并删除停用词。停用词是不相关的词,无助于识别文本的真伪。我们将对停用词使用“nltk”库,该库中的停用词包括:

stopword = nltk.corpus.stopwords.words('english')
print(stopword[:11])

这个库中有 179 个停用词。

def remove_stopwords(text):
    text=[word for word in text if word not in stopword]
    return text
news['title_wo_punct_split_wo_stopwords'] = news['title_wo_punct_split'].apply(lambda x: remove_stopwords(x))
news.head()

新闻数据集(包括标题,不带标点,不带停用词和拆分)

步骤 3 之后的列已经删除了不必要的停用词。

第四步:词尾/词干

词干化和词尾化是将一个单词简化为其词根形式的过程。主要目的是减少同一个单词的变化,从而减少模型中包含的单词集。词干化和词汇化的区别在于,词干化会去掉单词的末尾,而不考虑单词的上下文。然而,词汇化考虑单词的上下文,并根据字典定义将单词缩短为其词根形式。与词干化相比,词干化是一个更快的过程。因此,这是速度和准确性之间的权衡。

让我们以“信念”这个词为例。相信的不同变体可以是相信、被相信、相信和相信。

print(ps.stem('believe'))
print(ps.stem('believing'))
print(ps.stem('believed'))
print(ps.stem('believes'))

以上所有的 stem 结果是相信

print(wn.lemmatize(“believe”))
print(wn.lemmatize(“believing”))
print(wn.lemmatize(“believed”))
print(wn.lemmatize(“believes”))

按照书面陈述的顺序,词汇化结果是——相信、相信、相信和相信。

如果单词不在语料库中,Lemmatize 会产生相同的结果。Believe 被词条化为 belief(词根)

新闻数据集(词汇化与词干化)

如上图所示,lemmatize 和 stem 产生不同的结果。我们可以为我们的最终模型选择任何一个。

第五步:其他步骤

可以基于该数据执行其他清洁步骤。我在下面列出了其中的一些,

  1. 删除 URL
  2. 删除 HTML 标签
  3. 移除表情符号
  4. 删除号码

我很想听听你对我的文章的想法和反馈。请在下面的评论区留下它们。

Python 中的 NLP 矢量化

原文:https://towardsdatascience.com/nlp-in-python-vectorizing-a2b4fc1a339e?source=collection_archive---------20-----------------------

在典型的 NLP 机器学习模型管道中使用的常见矢量化技术,使用来自 Kaggle 的真实假新闻数据集。

来自 UnsplashRoman Kraft 的照片

在本文中,我们将学习矢量化以及 NLP 模型中采用的不同矢量化技术。然后,我们将把这些概念应用到一个问题的上下文中。

我们将使用一个将新闻分为真假的数据集。该数据集可在 Kaggle 上获得,数据集的链接如下:

https://www . ka ggle . com/clmentbisaillon/fake-and-real-news-dataset

典型的机器学习文本管道的第一步是数据清理。这一步在以前的文章中有详细介绍,链接如下:

[## Python 中的 NLP 数据清理

使用真实或虚假新闻数据集的典型 NLP 机器学习模型管道中涉及的数据清洗步骤…

towardsdatascience.com](/nlp-in-python-data-cleaning-6313a404a470)

数据清理后的数据集

原始新闻标题被转换成一种干净的格式,只包含基本信息(上图的最后一栏)。下一步是将清洗后的文本进一步转化为机器学习模型可以理解的形式。这个过程被称为向量化。在我们的上下文中,每个新闻标题都被转换成一个代表该特定标题的数字向量。有许多矢量化技术,但在本文中,我们将重点介绍三种广泛使用的矢量化技术——计数矢量化、N-Grams、TF-IDF,以及它们在 Python 中的实现。

  1. 计数矢量化

如上所述,矢量化是将文本转换为矩阵形式的数字条目的过程。在计数矢量化技术中,生成文档术语矩阵,其中每个单元是对应于新闻标题的计数,指示单词在文档中出现的次数,也称为术语频率。文档术语矩阵是一组虚拟变量,指示特定单词是否出现在文档中。语料库中的每个单词都有一个专栏。该计数与新闻标题类别的相关性成正比。这意味着,如果一个特定的词在假新闻标题或真实新闻标题中出现多次,那么该特定的词具有确定该新闻标题是假还是真的高预测能力。

def clean_title(text):
   text = "".join([word.lower() for word in text if word not in            string.punctuation])
   title = re.split('\W+', text)
   text = [ps.stem(word) for word in title if word not in nltk.corpus.stopwords.words('english')]
   return text
count_vectorize = CountVectorizer(analyzer=clean_title) 
vectorized = count_vectorize.fit_transform(news['title'])

剖析上面的代码,函数“clean _ title”——连接小写的新闻标题,不加标点。然后,在任何非单词字符上拆分文本。最后,对不间断单词进行词干分析,并以列表的形式呈现出来。这篇文章中给出了清洁过程的详细描述。

接下来,我们使用了 sklearn 库中 sk learn . feature _ extraction . text 下的“计数矢量器”包。默认值和定义可在 scikit-learn — 计数矢量器文档中找到。在上面的代码中,我们实例化了计数矢量器并定义了一个参数— 分析器。其他参数是它的默认值。分析器参数调用一个字符串,我们传递了一个函数,它接收原始文本并返回一个干净的字符串。

文档术语矩阵的形状是 44898,15824。共有 44898 个新闻标题,所有标题中有 15824 个独特的词。

新闻标题中 15824 个唯一单词的子集

矢量器产生稀疏矩阵输出,如图所示。为了节省空间,只存储非零值的位置。因此,矢量化的输出如下所示:

<20x158 sparse matrix of type '<class 'numpy.int64'>'
	with 206 stored elements in Compressed Sparse Row format>

但是,将上述内容转换为数组形式会产生以下结果:

如图所示,大多数单元格包含 0 值,这被称为稀疏矩阵。许多矢量化输出看起来与此类似,因为许多标题自然不会包含特定的单词。

  1. N-Grams

与计数向量化技术类似,在 N 元语法方法中,生成一个文档术语矩阵,每个单元代表一个计数。N-grams 方法的区别在于,计数表示标题中长度为 N 的相邻单词的组合。计数矢量化是 N 元语法,其中 n=1。比如“我爱这篇文章”有四个字,n=4。

如果 n=2,即 bigram,那么列将是— [“我爱”,“爱这个”,“这篇文章”]

如果 n=3,即三元组,那么列将是— [“我喜欢这个”,“喜欢这篇文章”]

如果 n=4,即 4 克,那么列应该是-['“我喜欢这篇文章”]

基于性能选择 n 值。

对于 python 代码,清理过程的执行类似于计数矢量化技术,但单词不是以标记化列表的形式。将标记化的单词连接起来形成一个字符串,因此可以将相邻的单词聚集在一起以有效地执行 N 元语法。

清理后的标题文本如下所示:

剩下的矢量化技术与我们上面使用的计数矢量化方法相同。

权衡是在 N 个值之间进行的。选择较小的 N 值可能不足以提供最有用的信息。而选择一个高的 N 值,将产生一个具有大量特征的巨大矩阵。N-gram 可能很强大,但是需要多一点小心。

3。术语频率-逆文档频率(TF-IDF)

与计数矢量化方法类似,在 TF-IDF 方法中,生成一个文档术语矩阵,每一列代表一个唯一的单词。TF-IDF 方法的不同之处在于,每个单元格都不表示词频,但是单元格值表示一个权重,它突出了特定单词对文档的重要性。

TF-IDF 公式:

等式的第二项有助于抽出生僻字。那是什么意思?如果一个单词在许多文档中多次出现,那么分母 df 将增加,从而减少第二个词的值。词频或 tf 是一个词(x)在文档(y)中出现的次数除以 y 中总字数的百分比。

对于 python 代码,我们将使用与计数矢量器方法相同的清理过程。Sklearn 的 TfidfVectorizer 可以用于 Python 中的矢量化部分。

该方法的稀疏矩阵输出显示代表文档中单词权重的小数。高权重意味着该单词在几个文档中出现多次,低权重意味着该单词在许多文档中出现的次数较少或者在多个文档中重复出现。

总结思路

选择矢量化方法没有经验法则。我经常根据手头的业务问题做出决定。如果没有限制,我经常从最简单的方法开始(通常是最快的)。

我很想听听你对我的文章的想法和反馈。请在下面的评论区留下它们。

张量流中的 NLP

原文:https://towardsdatascience.com/nlp-in-tensorflow-generate-an-ed-sheeran-song-8f99fe76662d?source=collection_archive---------52-----------------------

生成一首艾德·希兰歌曲

写歌是有史以来最困难的任务之一。在本文中,我将向您介绍我编写一个模型的经历,这个模型将学习一些艾德·希兰歌曲,并尝试为一首歌曲创作一些开头的句子。我很清楚,最好是制作一个能产生声音的模型,而不仅仅是一首诗,因为艾德·希兰的作品主要是留在我们脑海中的朗朗上口的节奏。然而,我并不想创造莎士比亚的文本。我想要更现代的东西。用它的音频乐队创作歌词应该很棒,但让我们先集中精力创作歌词,一步一步来!

摄影爱好在 Unsplash

让我们开始吧!

对于我的代码的基本概念,请看看我的文章在 Tensorflow 的 NLP:情绪分析

首先,让我们导入一些艾德·希兰歌曲的库和源文件。我拿了最后两张专辑开始我们的训练。你可以在我的 Github 这里找到它。

在标记化、排序和填充之后,我们就可以预测了。生成文本就是预测下一个单词是我们语料库中的哪个单词。一个几乎简单的多类预测不是吗?!是的,差不多了!

所以让我们建立一个简单的模型。我们从嵌入层开始。请看我之前关于嵌入的文章。

通过嵌入,我们得到了每个单词的向量。向量按距离排序。例如“草是……”下一个单词预测应该是“绿色”。简单!但是有时候你需要在段落的开头提供信息。那么我们如何分析我们的句子,并在记忆中保留之前的单词,不管之前有多少个句子。

答案是 RNN 循环神经网络。对于视频中的帧序列、文字序列中的单词、音乐序列中的音符,它都非常方便。所以序列数据通常需要 RNN。请阅读 Christopher Olah 关于理解 LSTM 网络的基础文章和 Andrej Karpathy 的递归神经网络的不合理有效性以获得更多信息。

如果你对 RNN 和 LSTM 背后的数学或理论不感兴趣,请随意跳到文章的结尾,但我希望你会和我一样发现学习人工智能背后的数学魔力是令人惊讶和兴奋的。

简而言之,RNN 是一个神经网络,其中每个细胞都有来自前一个细胞的隐藏信息作为其条目之一。这里有三个带有 tanh 激活功能的节点。

图片来自 Christopher Olah 博客

理论上,这应该能很好地记忆上下文,但事实并非如此。这可以用消失梯度问题来解释。事实上,为了测量我们预测的质量,我们需要知道输出单元——预测向量(通过权重乘以先前单元输出的激活函数加上偏差的连续计算——顺便说一下,这是正向传播)和实际向量之间的差异。在我们的例子中,输出是一个单词的预测。所以预测向量减去实际向量,得到损失值或误差值。这种差异越小,我们的预测就越接近。最小化这个误差就是通过提高我们的权重值(学习的能力)来最大化我们预测的准确性。在数学中,为了最小化一个函数,我们计算偏导数,从最后一个节点到第一个节点。这是反向传播。我们在每一层反向传播误差梯度。通常,梯度很小,以至于导数变得越来越小,然后消失。因此,当我们开始反向传播时,改变权重值的幅度在最后的节点中比在第一个节点中更有效。所以当我们反向传播时,我们不能记住梯度的大小。那么我们如何记住节点间的梯度呢?RNN 的黄金之星 LSTM 来了!

LSTM

LSTM 或长短期记忆。对于每个 RNN 单元格,我们用一个 LSTM 单元格来代替,如下所示:

图片来自克里斯托弗·奥拉的博客

在每个细胞中,我们制作一个小的神经网络,它的度量能够基于梯度下降来学习要记住什么和要注意什么。是不是很神奇?!

模型

所以,回到我们的艾德·希兰艾歌。我们的简单模型是一个嵌入层,一个双向的 LSTM - 请阅读 本文 了解更多信息- 所以我们解析过去和未来的句子,并用一个密集的层来包装这一切。让我们创作歌曲吧!

因此,我们的艾德·希兰人工智能模型将从“爱是什么”这句话中创造出什么:

以下是生成的文本:

I don't know about me 
know i love someone else 
i've either way to dress 
that i really wanna know
that i'll be creeping a long time 
a bit too way up we found love 
right where we are 
oh a mystery 
a purse a time to move home 
that could breathe 
still oh still time can it takes to get a long

让我们试试“爱是什么”

What love is a blaze time 
that it takes to give out all 
when you stand upon my bed 
are changed of crisps 
but i guess that plays never leave me 
a stage a song that i wrote 
that mixing fitting at my erasing 
and a song my heart is a getting ahead of a couple of days 
a new you take a

对于第一个简单的模型来说还不错。它可以给人灵感来重写它,使它更准确,但不知何故,它是诗意的。

我肯定会在我的语料库中添加更多的歌曲,看看它的表现如何。但是在内存饱和之前,我们不能添加那么多到我们的语料库中。

你可以在 Github 这里找到我的代码。

我希望你喜欢这个与 TensorFlow 艾德·希兰一代歌曲代码的演练。喜欢的请给它掌声。这是一个基线,所以请随意复制我的代码,并让我知道你对它的看法。编码快乐!

金融市场中的 NLP 情绪分析

原文:https://towardsdatascience.com/nlp-in-the-financial-market-sentiment-analysis-9de0dda95dc?source=collection_archive---------8-----------------------

最新的自然语言处理模型在多大程度上优于传统模型——从词汇方法到用于金融文本情感分析任务的 BERT

马库斯·斯皮斯克在 Unsplash 上的照片

D 自 2012 年先驱 CNN 在 ImageNet 上推出 AlexNet 以来,计算机视觉中的 eep 学习已经成功应用于各种应用中。相反,NLP 在深度神经网络应用方面已经落后了。许多声称使用人工智能的应用程序通常使用某种基于规则的算法和传统的机器学习,而不是深度神经网络。2018 年,一种名为 BERT 的最先进(STOA)模型在一些自然语言处理任务中的表现超过了人类的分数。在这里,我将几个模型用于情绪分析任务,看看它们在我所在的金融市场中有多大用处。代码在 jupyter 笔记本中,可以在 git repo 中获得。

1.介绍

NLP 任务可以大致分为以下几类。

  1. 文本分类—过滤垃圾邮件,对文档进行分类
  2. 单词序列—单词翻译、词性标签、命名实体识别
  3. 文本含义—主题建模、搜索、问题回答
  4. 序列对序列—机器翻译、文本摘要、问答
  5. 对话系统

不同的任务需要不同的方法,在大多数情况下是多种自然语言处理技术的结合。开发机器人时,后端逻辑通常是基于规则的搜索引擎和排名算法,以形成自然的交流。

这是有充分理由的。语言有语法和词序,这可以通过基于规则的方法更好地处理,而机器学习方法可以更好地学习搭配和单词相似性。word2vec、词袋等矢量化技术有助于模型以数学方式表达文本。最著名的例子是:

King - Man + Woman = QueenParis - France + UK = London

第一个例子描述了性别关系,第二个例子描述了首都的概念。然而,在这些方法中,由于在任何文本中相同的单词总是由相同的向量表示,所以上下文没有被捕获,这在许多情况下是不正确的。递归神经网络( RNN )架构使用来自输入序列的先前信息并处理时间序列数据,在捕获和记忆上下文方面表现良好。典型的架构之一是长短期记忆( LSTM ),由输入门、输出门和遗忘门组成,以克服 RNN 的清漆梯度问题。有许多基于 LSTM 的改进模型,例如双向 LSTM,不仅可以从前面的单词中捕捉上下文,还可以从后面捕捉上下文。这些对于一些特定的任务是好的,但是在实际应用中不太好。

2017 年,我们看到了一种无需递归或卷积架构即可解决该问题的新方法。注意力是你需要的全部提出了一种 transformer 架构,这是一种基于注意力机制的编解码栈。来自 Transformers ( BERT ) 的双向编码器表示,是 Google 在 2018 年推出的具有多个编码器堆栈的掩码语言模型,在 GLUE、SQuAD 和 SWAG 基准测试中实现了较大的改进。有很多文章和博客解释这个架构,比如 Jay Alammar 的文章。

在金融行业工作,我很难看到过去几年在交易系统中生产使用的 NLP 上的机器学习模型在我们过去的 R&D 中足够稳健的性能。现在,由于 Huggingface 的实施,基于 BERT 的模型变得越来越成熟和易于使用,并且许多预先训练的模型已经公开。我的目标是看看 NLP 的最新发展是否达到了在我的领域中使用的良好水平。在这篇文章中,我在一个相当简单的金融文本情感分析任务上比较了不同的模型,作为判断是否值得在实际解决方案中尝试另一个 R & D 的基线。

这里比较的模型有:

  1. 使用词典的基于规则的方法
  2. 使用 Tfidf 的传统机器学习方法
  3. 作为递归神经网络结构的 LSTM
  4. 伯特(和艾伯特)

2.输入数据

对于情感分析任务,我采用以下两种输入来代表行业中的不同语言。

  1. 金融标题作为更正式的风格
  2. 来自 Stocktwits 的 Tweets 作为交易者的非正式谈话

后者我会再写一篇,所以这里重点说一下前者的数据。这是一个包含更正式的金融领域特定语言的文本示例,我使用了 Malo 等人(2014) 的 FinancialPhraseBank,它由 16 个人的 4845 个手写标题文本组成,并提供了 agree 级别。我用 75%同意的标签和 3448 个文本作为训练数据。

## Input text samples**positive** "Finnish steel maker Rautaruukki Oyj ( Ruukki ) said on July 7 , 2008 that it won a 9.0 mln euro ( $ 14.1 mln ) contract to supply and install steel superstructures for Partihallsforbindelsen bridge project in Gothenburg , western Sweden."**neutral** "In 2008 , the steel industry accounted for 64 percent of the cargo volumes transported , whereas the energy industry accounted for 28 percent and other industries for 8 percent."**negative** "The period-end cash and cash equivalents totaled EUR6 .5 m , compared to EUR10 .5 m in the previous year."

词云为第一次输入训练文本,图片由作者提供

请注意,所有的数据属于来源,人们必须尊重他们的版权和许可条款。

3.模型

下面是我对比的四款机型的性能。

NLP 模型评估,图片由作者提供

A.基于词典的方法

创建特定领域的词典是一种传统的方法,在某些情况下,当来源来自特定的人或媒体时,这种方法简单而有效。拉夫兰和麦克唐纳感情词表。这个列表包含超过 4k 个单词,出现在带有情绪标签的财务报表上。注意:这些数据需要许可证才能用于商业应用。请在使用前查看他们的网站。

## Samplenegative: ABANDON
negative: ABANDONED
constraining: STRICTLY

我用了负 2355 字,正 354 字。它包括单词形式,所以不要对输入进行词干分析和词条解释。对于这种方法,考虑否定是很重要的。不,不,不要等词语。把否定词的意思改成肯定词,如果否定词之一出现在肯定词之前的三个词里,我就简单地颠倒一下情绪。

然后,音调分数定义如下,并沿正/负计数送入分类器。

tone_score = 100 * (pos_count — neg_count) / word_count

使用默认参数训练 14 个不同的分类器,然后使用网格搜索交叉验证进行随机森林的超参数调整。

B.基于 Tfidf 向量的传统机器学习

输入由 NLTK word_tokenize()进行标记化,然后移除词条和停用词。然后输入到 tfidf 矢量器,通过逻辑回归和随机森林分类器进行分类。

C.LSTM——一种递归神经网络

由于 LSTM 被设计为记住表达上下文的长期记忆,所以使用定制的标记器来提取字母,因为它们没有词条满足或停用词移除。然后输入被送入一个嵌入层,然后是两个 lstm 层。为了避免过度拟合,通常情况下应用 dropout,然后是完全连接的层,最后是 log softmax。

作为替代,也尝试了斯坦福的 GloVe word embedding,这是一种无监督学习算法,用于获取单词的矢量表示。在这里,采取了预先训练的维基百科和千兆字 6B 令牌,40 万词汇大小和 300 维向量。我们的词汇库中大约 90%的单词是在这个手套词汇库中找到的,其余的是随机初始化的。

D.伯特(还有阿尔伯特作为伯特模型的替代)

我用 pytorch 实现了来自 Huggingface 的变形金刚的 BERT 模型。现在(v3)他们提供了标记器和编码器,可以生成文本 id、填充掩码和段 id,可以直接在他们 BertModel 中使用,标准训练过程不需要定制实现。

类似于 LSTM 模型,来自 BERT 的输出然后被传递到退出的、完全连接的 layters,然后应用 log softmax。如果没有足够的计算资源预算,也没有足够的数据,从头开始训练模型不是一个选项,所以我使用预训练的模型并进行微调。预训练模型使用如下:

  • 伯特:伯特-基地-无壳
  • 艾伯特:艾伯特-基地-v2

预训练的 bert 的训练过程如下所示。

4.估价

首先,输入数据以 8:2 的比例分成训练集和测试集。测试集保持不变,直到所有参数都固定下来,并且每个模型只使用一次。由于数据集不大,交叉验证用于评估参数集。此外,为了克服不平衡和较小数据集的问题,分层 K-Fold 交叉验证被用于超参数调整。

交叉验证和测试集分割,按作者分类的图像

由于输入数据不平衡,评估基于 F1 分数,同时也参考了准确性。

网格搜索交叉验证用于模型 A 和 B,而定制交叉验证用于深度神经网络模型 C 和 d

5.结果

在花费或多或少相似的时间进行超参数调优后,基于微调的 BERT 模型明显优于其他模型。

每个模型的评估分数,按作者排序的图像

模型 A 表现不佳,因为输入过于简化为音调得分,这是判断情绪的单个值,随机森林模型最终对大多数数据标注了中性的多数类别。简单线性模型仅通过将阈值应用于音调得分而表现得更好,但是在准确性和 f1 得分方面仍然相当低。

每个分类器的准确性,按作者分类的图像

混淆矩阵,作者图片

我们没有使用欠采样/过采样或 SMOTE 等方法来平衡输入数据,因为它可以纠正这个问题,但会偏离不平衡存在的实际情况。对该模型的潜在改进是,如果为要解决的每个问题建立词典的成本是合理的,则建立定制词典来代替 L-M 词典。更复杂的否定也可以提高预测的准确性。

模型 B 比前一个模型好得多,但是它以几乎 100%的准确度和 f1 分数过度适合训练集,并且未能被通用化。我试图降低模型的复杂性,以避免过度拟合,但它最终在验证集中得分较低。平衡数据可以帮助解决这个问题或收集更多的数据。

网格搜索交叉验证结果,按作者排序的图像

混淆矩阵,作者图片

模型 C 产生了与先前模型相似的结果,但改进不大。事实上,训练数据的数量不足以从零开始训练神经网络,并且需要多个时期,这往往会过度拟合。预训练的手套嵌入不会改善结果。对后一种模型的一个可能的改进是使用来自类似领域(如 10K、10Q 财务报表)的一串文本来训练手套,而不是使用来自维基百科的预训练模型。

混淆矩阵,作者图片

D 型表现相当不错,在交叉验证和最终测试中,准确率和 f1 分均超过 90%。它对负面文本的正确分类率为 84%,而对正面文本的正确分类率为 94%,这可能是由于输入的数量,但最好仔细观察以进一步提高性能。这表明,由于迁移学习和语言模型,预训练模型的微调在这个小数据集上表现良好。

最终测试集上的混淆矩阵显示了良好的性能,图片由作者提供

训练数据的丢失随着训练的进行而减少,图片由作者提供

验证数据的损失并没有像训练数据那样下降

5.结论

这个实验显示了基于 BERT 的模型在我的领域中的应用潜力,在这个领域中,以前的模型未能产生足够的性能。然而,结果是不确定的,并且基于在自由层 GPU 上的相当简单的手动超参数调整,并且它可能根据输入数据和调整方法而不同。

同样值得注意的是,在实际应用中,获得适当的输入数据也是相当重要的。如果没有高质量的数据,就不能很好地训练模型,这通常被称为“垃圾输入,垃圾输出”。

我将在下次讨论这些问题。这里使用的所有代码都可以在 git repo 中获得。

现实世界中的 NLP:Google Duplex

原文:https://towardsdatascience.com/nlp-in-the-real-world-google-duplex-d96160d3770b?source=collection_archive---------36-----------------------

随着 NLP 的所有最新进展,看到该领域的实际应用中的新发展令人耳目一新。

几年前,我看到谷歌展示了他们新的谷歌双工系统。如果你不熟悉 Duplex,它本质上是一个人工智能,可以帮助通过电话完成任务(例如,安排约会,预订预订等。).

照片由米切尔罗Unsplash

问题。也许这只是我这一代人,但我宁愿发短信也不愿打电话,因为发短信意味着我可以发短信,然后很快忘掉它。然而,这并不总是可能的,因为许多任务都需要给企业打电话。这就是 Duplex 的用武之地。

想法。Duplex 背后的 overaching 思想是,例如,你只需让谷歌助手在某个餐馆预订,然后输入一些参数,如人数、日期和时间,以及预订名称。一旦你这样做了,Google Assistant 将自动使用 Duplex 给那家餐馆打电话并为你预订,一旦完成就发送一个确认。双工将在模仿人类的同时尝试这样做,以便电话对话是自然的(并且不会惊动另一端的人)。

这里有一个系统打电话安排发廊预约的例子。

这是另一个 Duplex 呼叫餐馆的例子。

Duplex 的成功。在这些例子中,我对 Duplex 模仿人类的能力印象深刻。这些声音听起来像真人,Duplex 甚至添加了像“嗯”这样的感叹词,让它听起来更像人(确实没有比说“嗯”更像人的方法了)。双工还可以控制其响应的延迟。例如,如果这个人说“你好?”然后你必须迅速做出反应,但如果他们说了一个很长的句子,你必须花一些时间在模仿思维时间之前做出反应。尽管它很强大,但 Duplex 在这些示例呼叫中仍然会犯一些小错误(例如,当 Duplex 在第一次呼叫中说“上午 10 点至下午 12 点之间的任何时间”时,“下午 12 点”会有不自然和机械的音调变化),但这些甚至不是真正的问题,因为它们足够小,电话另一端的人不会太在意,如果他们甚至注意到它的话。

需要改进的地方。尽管 Duplex 可以很好地处理基本任务,但总有一些边缘情况需要进一步调查。双工可能无法轻松处理复杂的语句[ 示例 ]或背景噪音或音质问题。这些案例需要进一步改进。目前,在 Duplex 无法完成其任务的情况下,内置了一个故障保险来移交给人类操作员来完成任务。

双工系统的简单示意图。RNN 使用来自电话呼叫的音频、自动语音识别(ASR)软件和对话参数来获得文本响应。该响应通过文本到语音转换程序运行,以获得口头响应。

Duplex 与 NLP 的关系。当然,能够在打电话时模仿人类需要一些疯狂的自然语言处理。首先,需要有一个准确的语音到文本的翻译器,甚至能够理解打电话的人在说什么。接下来,另一个模型必须在电话呼叫目标的上下文中解释这一点。然后必须做出适当的反应。最后,文本到语音转换模型需要将这种响应翻译成类似人类的声音在电话中说出来。这些步骤需要在整个通话过程中实时地不断重复,因此模型需要既准确又快速。

必要的 NLP 模型。为了做到这一点,Duplex 使用递归神经网络(RNN)结合谷歌的自动语音识别(ASR)技术、对话参数(例如,所需时间、姓名)和文本到语音(TTS)系统。值得注意的是,这些模型必须在狭窄的领域进行训练。例如,预约和预订需要单独的培训——Duplex 不是作为一般的聊天机器人进行培训的,谷歌希望使用 Duplex 的任何新领域都需要新的培训。

结论。该系统已经推出,并将逐步完善。尽管还有待改进,但我仍然对 Google 如何能够结合多种 NLP 模型并创建一个像 Duplex 一样工作的可用应用程序印象深刻。我相信,如果我们能够以这种方式不断进行新的创新,NLP 将有一个光明的未来,因为单个模型很棒,但将多个模型组合起来形成一个发电站系统可能是在现实世界中应用 NLP 的未来所在。

延伸阅读:

股票市场中的自然语言处理

原文:https://towardsdatascience.com/nlp-in-the-stock-market-8760d062eb92?source=collection_archive---------4-----------------------

金融中的人工智能

利用对 10k 填充物的情感分析作为优势

图片来源:纽约时报

在交易中实现的机器学习模型通常根据历史股价和其他定量数据进行训练,以预测未来的股价。然而,自然语言处理(NLP)使我们能够分析财务文档,如 10-k 表单,以预测股票走势。10-k 表是由公司提交的年度报告,用于提供其财务业绩的综合摘要(这些报告是由证券交易委员会强制要求的)。对投资者来说,梳理这些报告通常很乏味。通过自然语言处理的一个分支——情感分析,投资者可以快速了解报告的语气是积极的、消极的还是诉讼的等等。以 10-k 形式表达的总体情绪可以用来帮助投资者决定他们是否应该投资该公司。

NLP 解释道

图片来源:亚当·盖特基

自然语言处理是人工智能的一个分支,涉及教计算机阅读并从语言中获取意义。由于语言如此复杂,计算机在理解文本之前必须经过一系列的步骤。以下是对典型 NLP 管道中出现的步骤的快速解释。

  1. 句子分割
    文本文档被分割成单独的句子。
  2. 一旦文档被分解成句子,我们进一步将句子分解成单个单词。每个单词称为一个标记,因此得名标记化。
  3. 词性标注
    我们将每个单词及其周围的一些单词输入到预先训练的词性分类模型中,以接收该单词的词性作为输出。
  4. 词汇化
    词语在指代同一个物体/动作时,往往以不同的形式出现。为了防止计算机将一个单词的不同形式视为不同的单词,我们执行了词条化,即将一个单词的各种词形变化组合在一起,作为一个单一项目进行分析的过程,通过该单词的词条(该单词在字典中的出现方式)进行识别。
  5. 停用词
    非常常见的词,如“and”、“the”和“a”不提供任何值,因此我们将它们标识为停用词,以将其排除在对文本执行的任何分析之外。
  6. 依存解析
    给句子分配一个句法结构,并通过将单词输入依存解析器来理解句子中的单词是如何相互关联的。
  7. 名词短语
    把一个句子中的名词短语组合在一起,有助于在我们不关心形容词的情况下简化句子。
  8. 命名实体识别
    命名实体识别模型可以标记对象,例如人名、
    公司名称和地理位置。
  9. 共指消解
    由于 NLP 模型分析单个句子,它们会被其他句子中指代名词的代词所混淆。为了解决这个问题,我们使用了共指消解来跟踪句子中的代词以避免混淆。

关于 NLP 更深入的描述:阅读 这个

完成这些步骤后,我们的文本就可以进行分析了。现在我们更好地理解了 NLP,让我们来看看我的项目代码(来自 Udacity 的 AI for Trading 课程的项目 5)。点击这里查看完整的 Github 库

导入/下载

首先,我们进行必要的进口; project_helper 包含各种实用程序和图形函数。

import nltk
import numpy as np
import pandas as pd
import pickle
import pprint
import project_helper

from tqdm import tqdm

然后,我们下载停用词语料库来移除停用词,并下载 wordnet 语料库来进行词汇化。

nltk.download('stopwords')
nltk.download('wordnet')

获得 10 公里

10-k 文档包括公司历史、组织结构、高管薪酬、股权、子公司和经审计的财务报表等信息。为了查找 10-k 文档,我们使用每个公司的唯一 CIK(中央索引键)。

cik_lookup = {
    'AMZN': '0001018724',
    'BMY': '0000014272',   
    'CNP': '0001130310',
    'CVX': '0000093410',
    'FL': '0000850209',
    'FRT': '0000034903',
    'HON': '0000773840'}

现在,我们从 SEC 提取一个已备案的 10-k 列表,并显示 Amazon 数据作为示例。

sec_api = project_helper.SecAPI()from bs4 import BeautifulSoupdef get_sec_data(cik, doc_type, start=0, count=60):
    rss_url = '[https://www.sec.gov/cgi-bin/browse-edgar?action=getcompany'](https://www.sec.gov/cgi-bin/browse-edgar?action=getcompany') \
        '&CIK={}&type={}&start={}&count={}&owner=exclude&output=atom' \
        .format(cik, doc_type, start, count)
    sec_data = sec_api.get(rss_url)
    feed = BeautifulSoup(sec_data.encode('ascii'), 'xml').feed
    entries = [
        (
            entry.content.find('filing-href').getText(),
            entry.content.find('filing-type').getText(),
            entry.content.find('filing-date').getText())
        for entry in feed.find_all('entry', recursive=False)]return entriesexample_ticker = 'AMZN'
sec_data = {}for ticker, cik in cik_lookup.items():
    sec_data[ticker] = get_sec_data(cik, '10-K')pprint.pprint(sec_data[example_ticker][:5])

我们收到一个 URL 列表,指向包含与每次填充相关的元数据的文件。元数据与我们无关,所以我们通过用填充 url 替换 url 来提取填充。让我们使用 tqdm 查看下载进度,并看一个示例文档。

raw_fillings_by_ticker = {}for ticker, data in sec_data.items():
    raw_fillings_by_ticker[ticker] = {}
    for index_url, file_type, file_date in tqdm(data, desc='Downloading {} Fillings'.format(ticker), unit='filling'):
        if (file_type == '10-K'):
            file_url = index_url.replace('-index.htm', '.txt').replace('.txtl', '.txt')            

            raw_fillings_by_ticker[ticker][file_date] = sec_api.get(file_url)print('Example Document:\n\n{}...'.format(next(iter(raw_fillings_by_ticker[example_ticker].values()))[:1000]))

将下载的文件分解成相关的文件,这些文件被分割成多个部分,每个文件的开头用标签表示,每个文件的结尾用标签表示。

import redef get_documents(text): extracted_docs = []

    doc_start_pattern = re.compile(r'<DOCUMENT>')
    doc_end_pattern = re.compile(r'</DOCUMENT>')   

    doc_start_is = [x.end() for x in      doc_start_pattern.finditer(text)]
    doc_end_is = [x.start() for x in doc_end_pattern.finditer(text)]

    for doc_start_i, doc_end_i in zip(doc_start_is, doc_end_is):
            extracted_docs.append(text[doc_start_i:doc_end_i])

    return extracted_docsfilling_documents_by_ticker = {}for ticker, raw_fillings in raw_fillings_by_ticker.items():
    filling_documents_by_ticker[ticker] = {}
    for file_date, filling in tqdm(raw_fillings.items(), desc='Getting Documents from {} Fillings'.format(ticker), unit='filling'):
        filling_documents_by_ticker[ticker][file_date] = get_documents(filling)print('\n\n'.join([
    'Document {} Filed on {}:\n{}...'.format(doc_i, file_date, doc[:200])
    for file_date, docs in filling_documents_by_ticker[example_ticker].items()
    for doc_i, doc in enumerate(docs)][:3]))

定义 get_document_type 函数以返回给定的文档类型。

def get_document_type(doc):

    type_pattern = re.compile(r'<TYPE>[^\n]+')

    doc_type = type_pattern.findall(doc)[0][len('<TYPE>'):] 

    return doc_type.lower()

使用 get_document_type 函数从填充物中过滤出非 10k 文档。

ten_ks_by_ticker = {}for ticker, filling_documents in filling_documents_by_ticker.items():
    ten_ks_by_ticker[ticker] = []
    for file_date, documents in filling_documents.items():
        for document in documents:
            if get_document_type(document) == '10-k':
                ten_ks_by_ticker[ticker].append({
                    'cik': cik_lookup[ticker],
                    'file': document,
                    'file_date': file_date})project_helper.print_ten_k_data(ten_ks_by_ticker[example_ticker][:5], ['cik', 'file', 'file_date'])

预处理数据

删除 html 并使所有文本小写,以清理文档文本。

def remove_html_tags(text):
    text = BeautifulSoup(text, 'html.parser').get_text()

    return textdef clean_text(text):
    text = text.lower()
    text = remove_html_tags(text)

    return text

使用 clean_text 函数清理文档。

for ticker, ten_ks in ten_ks_by_ticker.items():
    for ten_k in tqdm(ten_ks, desc='Cleaning {} 10-Ks'.format(ticker), unit='10-K'):
        ten_k['file_clean'] = clean_text(ten_k['file'])project_helper.print_ten_k_data(ten_ks_by_ticker[example_ticker][:5], ['file_clean'])

现在我们对所有数据进行假设。

from nltk.stem import WordNetLemmatizer
from nltk.corpus import wordnetdef lemmatize_words(words):

    lemmatized_words = [WordNetLemmatizer().lemmatize(word, 'v') for word in words]

    return lemmatized_wordsword_pattern = re.compile('\w+')for ticker, ten_ks in ten_ks_by_ticker.items():
    for ten_k in tqdm(ten_ks, desc='Lemmatize {} 10-Ks'.format(ticker), unit='10-K'):
        ten_k['file_lemma'] = lemmatize_words(word_pattern.findall(ten_k['file_clean']))project_helper.print_ten_k_data(ten_ks_by_ticker[example_ticker][:5], ['file_lemma'])

删除停用词。

from nltk.corpus import stopwordslemma_english_stopwords = lemmatize_words(stopwords.words('english'))for ticker, ten_ks in ten_ks_by_ticker.items():
    for ten_k in tqdm(ten_ks, desc='Remove Stop Words for {} 10-Ks'.format(ticker), unit='10-K'):
        ten_k['file_lemma'] = [word for word in ten_k['file_lemma'] if word not in lemma_english_stopwords]print('Stop Words Removed')

10k 上的情感分析

使用 Loughran-McDonald 情感词表对 10-k 进行情感分析(这是专门为与金融相关的文本分析而构建的)。

sentiments = ['negative', 'positive', 'uncertainty', 'litigious', 'constraining', 'interesting']

sentiment_df = pd.read_csv('loughran_mcdonald_master_dic_2018.csv')
sentiment_df.columns = [column.lower() for column in sentiment_df.columns] *# Lowercase the columns for ease of use*

*# Remove unused information*
sentiment_df = sentiment_df[sentiments + ['word']]
sentiment_df[sentiments] = sentiment_df[sentiments].astype(bool)
sentiment_df = sentiment_df[(sentiment_df[sentiments]).any(1)]

*# Apply the same preprocessing to these words as the 10-k words*
sentiment_df['word'] = lemmatize_words(sentiment_df['word'].str.lower())
sentiment_df = sentiment_df.drop_duplicates('word')

sentiment_df.head()

使用情感单词列表从 10k 文档生成情感单词包。单词包统计每篇文档中的情感词数量。

from collections import defaultdict, Counter
from sklearn.feature_extraction.text import CountVectorizerdef get_bag_of_words(sentiment_words, docs):

    vec = CountVectorizer(vocabulary=sentiment_words)
    vectors = vec.fit_transform(docs)
    words_list = vec.get_feature_names()
    bag_of_words = np.zeros([len(docs), len(words_list)])

    for i in range(len(docs)):
        bag_of_words[i] = vectors[i].toarray()[0]return bag_of_words.astype(int)sentiment_bow_ten_ks = {}for ticker, ten_ks in ten_ks_by_ticker.items():
    lemma_docs = [' '.join(ten_k['file_lemma']) for ten_k in ten_ks]

    sentiment_bow_ten_ks[ticker] = {
        sentiment: get_bag_of_words(sentiment_df[sentiment_df[sentiment]]['word'], lemma_docs)
        for sentiment in sentiments}project_helper.print_ten_k_data([sentiment_bow_ten_ks[example_ticker]], sentiments)

雅克卡相似性

现在我们有了单词包,我们可以将它转换成一个布尔数组,并计算 jaccard 相似度。jaccard 相似性被定义为交集的大小除以两个集合的并集的大小。例如,两个句子之间的 jaccard 相似度是两个句子之间的常用单词数除以两个句子中唯一单词的总数。jaccard 相似性值越接近 1,集合就越相似。为了更容易理解我们的计算,我们绘制了 jaccard 的相似点。

from sklearn.metrics import jaccard_similarity_scoredef get_jaccard_similarity(bag_of_words_matrix):

    jaccard_similarities = []
    bag_of_words_matrix = np.array(bag_of_words_matrix, dtype=bool)

    for i in range(len(bag_of_words_matrix)-1):
            u = bag_of_words_matrix[i]
            v = bag_of_words_matrix[i+1]

    jaccard_similarities.append(jaccard_similarity_score(u,v))    

    return jaccard_similarities# Get dates for the universe
file_dates = {
    ticker: [ten_k['file_date'] for ten_k in ten_ks]
    for ticker, ten_ks in ten_ks_by_ticker.items()}jaccard_similarities = {
    ticker: {
        sentiment_name: get_jaccard_similarity(sentiment_values)
        for sentiment_name, sentiment_values in ten_k_sentiments.items()}
    for ticker, ten_k_sentiments in sentiment_bow_ten_ks.items()}project_helper.plot_similarities(
    [jaccard_similarities[example_ticker][sentiment] for sentiment in sentiments],
    file_dates[example_ticker][1:],
    'Jaccard Similarities for {} Sentiment'.format(example_ticker),
    sentiments)

TFIDF

从情感词表中,让我们从 10k 文档中生成情感词频-逆文档频率(TFIDF)。TFIDF 是一种信息检索技术,用于揭示一个单词/术语在所选文本集合中出现的频率。每个术语被分配一个术语频率(TF)和逆文档频率(IDF)分数。这些分数的乘积被称为该项的 TFIDF 权重。较高的 TFIDF 权重表示较罕见的术语,较低的 TFIDF 分数表示较常见的术语。

from sklearn.feature_extraction.text import TfidfVectorizerdef get_tfidf(sentiment_words, docs):

    vec = TfidfVectorizer(vocabulary=sentiment_words)
    tfidf = vec.fit_transform(docs)

    return tfidf.toarray()sentiment_tfidf_ten_ks = {}for ticker, ten_ks in ten_ks_by_ticker.items():
    lemma_docs = [' '.join(ten_k['file_lemma']) for ten_k in ten_ks]

    sentiment_tfidf_ten_ks[ticker] = {
        sentiment: get_tfidf(sentiment_df[sentiment_df[sentiment]]['word'], lemma_docs)
        for sentiment in sentiments}project_helper.print_ten_k_data([sentiment_tfidf_ten_ks[example_ticker]], sentiments)

余弦相似性

根据我们的 TFIDF 值,我们可以计算余弦相似度,并绘制出随时间变化的曲线。与 jaccard 相似性类似,余弦相似性是一种用于确定文档相似程度的度量。余弦相似性通过测量在多维空间中投影的两个向量之间的角度余弦来计算相似性,而不考虑大小。对于文本分析,使用的两个向量通常是包含两个文档字数的数组。

from sklearn.metrics.pairwise import cosine_similaritydef get_cosine_similarity(tfidf_matrix):

    cosine_similarities = []    

    for i in range(len(tfidf_matrix)-1):

cosine_similarities.append(cosine_similarity(tfidf_matrix[i].reshape(1, -1),tfidf_matrix[i+1].reshape(1, -1))[0,0])

    return cosine_similaritiescosine_similarities = {
    ticker: {
        sentiment_name: get_cosine_similarity(sentiment_values)
        for sentiment_name, sentiment_values in ten_k_sentiments.items()}
    for ticker, ten_k_sentiments in sentiment_tfidf_ten_ks.items()}project_helper.plot_similarities(
    [cosine_similarities[example_ticker][sentiment] for sentiment in sentiments],
    file_dates[example_ticker][1:],
    'Cosine Similarities for {} Sentiment'.format(example_ticker),
    sentiments)

价格数据

现在我们将通过与股票的年度定价进行比较来评估阿尔法因子。我们可以从 QuoteMedia 下载价格数据。

pricing = pd.read_csv('yr-quotemedia.csv', parse_dates=['date'])
pricing = pricing.pivot(index='date', columns='ticker', values='adj_close')

pricing

转换为数据帧

Alphalens 是一个用于 alpha 因子性能分析的 python 库,它使用数据帧,所以我们必须将字典转换成数据帧。

cosine_similarities_df_dict = {'date': [], 'ticker': [], 'sentiment': [], 'value': []}for ticker, ten_k_sentiments in cosine_similarities.items():
    for sentiment_name, sentiment_values in ten_k_sentiments.items():
        for sentiment_values, sentiment_value in enumerate(sentiment_values):
            cosine_similarities_df_dict['ticker'].append(ticker)
            cosine_similarities_df_dict['sentiment'].append(sentiment_name)
            cosine_similarities_df_dict['value'].append(sentiment_value)
            cosine_similarities_df_dict['date'].append(file_dates[ticker][1:][sentiment_values])cosine_similarities_df = pd.DataFrame(cosine_similarities_df_dict)
cosine_similarities_df['date'] = pd.DatetimeIndex(cosine_similarities_df['date']).year
cosine_similarities_df['date'] = pd.to_datetime(cosine_similarities_df['date'], format='%Y')cosine_similarities_df.head()

在我们可以使用许多 alphalens 函数之前,我们需要对齐索引并将时间转换为 unix 时间戳。

import alphalens as alfactor_data = {}
skipped_sentiments = []for sentiment in sentiments:
    cs_df = cosine_similarities_df[(cosine_similarities_df['sentiment'] == sentiment)]
    cs_df = cs_df.pivot(index='date', columns='ticker', values='value')

    try:
        data = al.utils.get_clean_factor_and_forward_returns(cs_df.stack(), pricing.loc[cs_df.index], quantiles=5, bins=None, periods=[1])
        factor_data[sentiment] = data
    except:
        skipped_sentiments.append(sentiment)if skipped_sentiments:
    print('\nSkipped the following sentiments:\n{}'.format('\n'.join(skipped_sentiments)))
factor_data[sentiments[0]].head()

为了与 alphalen 的 factor _ rank _ 自相关和 mean_return_by_quantile 函数兼容,我们还必须使用 unix time 创建因子数据帧。

unixt_factor_data = {
    factor: data.set_index(pd.MultiIndex.from_tuples(
        [(x.timestamp(), y) for x, y in data.index.values],
        names=['date', 'asset']))
    for factor, data in factor_data.items()}

因子回报

让我们来看看一段时间内的因子回报

ls_factor_returns = pd.DataFrame()for factor_name, data in factor_data.items():
    ls_factor_returns[factor_name] = al.performance.factor_returns(data).iloc[:, 0](1 + ls_factor_returns).cumprod().plot()

正如预期的那样,表达积极情绪的 10-k 报告产生了最多的收益,而包含消极情绪的 10-k 报告导致了最多的损失。

营业额分析

使用因子等级自相关,我们可以分析阿尔法随着时间的推移有多稳定。我们希望阿尔法等级在不同时期保持相对一致。

ls_FRA = pd.DataFrame()for factor, data in unixt_factor_data.items():
    ls_FRA[factor] = al.performance.factor_rank_autocorrelation(data)ls_FRA.plot(title="Factor Rank Autocorrelation")

夏普比率

最后,让我们来计算夏普比率,即平均回报减去无风险回报除以投资回报的标准差。

daily_annualization_factor = np.sqrt(252) (daily_annualization_factor * ls_factor_returns.mean() / ls_factor_returns.std()).round(2)

夏普比率 1 被认为是可接受的,比率 2 是非常好的,比率 3 是极好的。正如所料,我们可以看到积极情绪与高夏普比率相关,而消极情绪与低夏普比率相关。其他情绪也与高夏普比率相关。然而,由于影响股票价格的复杂因素如此之多,要在现实世界中复制这些回报要困难得多。

参考

[1] Udacity,用于交易的人工智能,Github

先别走

我是 Roshan,16 岁,对人工智能和金融的交叉领域充满热情。关于人工智能在金融领域的广泛观点,请查看这篇文章:https://towards data science . com/artificial-intelligence-and-its-application-in-finance-9f1e 0588 e 777

在 Linkedin 上联系我:https://www.linkedin.com/in/roshan-adusumilli-96b104194/

ESG-BERT: NLP 符合可持续投资

原文:https://towardsdatascience.com/nlp-meets-sustainable-investing-d0542b3c264b?source=collection_archive---------11-----------------------

Parabole ,我在 Charan Pothireddi 的指导下工作,探索自然语言处理如何应用于可持续性分析。这篇文章概述了我们的发现。

照片由 Nathália RosaUnsplash 拍摄

可持续投资是一种不断发展的投资策略,旨在寻求丰厚的财务回报,同时让世界变得更加美好。然而,对于许多投资者来说,这往往是一种具有挑战性的投资策略。幸运的是,自然语言处理可以帮上忙,下面是方法—

什么是可持续投资?

可持续、负责任和有影响力的投资(SRI)是一种投资原则,它考虑了环境、社会和公司治理(ESG)标准,以产生长期有竞争力的财务回报和积极的社会影响。

作者图片

可持续投资有几个动机,包括个人价值观和目标、机构使命以及客户、委托人或计划参与者的需求。

可持续投资者的目标是强劲的财务表现,但也相信这些投资应该用于促进社会、环境和治理实践。[6]

他们可能会积极寻找可能提供重要社会或环境效益的投资,如社区发展贷款基金或清洁技术投资组合。

一些投资者采用可持续投资策略来管理风险和履行受托责任;他们审查环境、社会和公司治理标准,以评估其投资组合公司的管理质量和应对未来挑战的可能弹性。一些人寻求长期的财务优势;越来越多的学术研究表明,ESG 和财务表现之间有着密切的联系。[1]

全球可持续投资的增长(万亿美元)—作者图片

以可持续为卖点的投资——这意味着它们专注于将环境和社会公司治理实践纳入长期公司战略的公司——正在经历爆炸式增长。

尽管可持续投资出现于 20 世纪 70 年代,但这一运动在过去几年获得了令人瞩目的发展。

自 2012 年以来,可持续投资的总资产增加了一倍多。[2]

随着可持续投资成为主流,它不会简单地作为一个更广泛的战略中的利基——相反,它将自然地融入整个投资组合。

“随着可持续性对投资回报的影响越来越大,我们相信可持续投资是客户投资组合未来最坚实的基础。”

—贝莱德董事长兼首席执行官拉里·芬克

可持续发展是一种全球性的力量,将继续成为日常决策的考虑因素。

可持续投资——挑战

目前围绕可持续发展的数据过于依赖企业自愿披露,如机构投资者汇总的年度可持续发展报告和公司问卷——其中许多人会提出不同的问题。[3]

“个人投资者很难以容易获得的方式获得这种类型的信息,并为投资决策提供信息”

——琼·罗杰斯,首席执行官,非营利组织可持续发展会计标准委员会的创始人

对于投资者来说,仅仅依靠年度可持续发展报告等做出可持续的投资选择是具有挑战性的。它们通常长达数百页,并占用大量人力资源进行分析。随着时间的推移,随着可持续资产数量的增加,这个问题会变得更加复杂。这些报告也从来不是完全透明的。公司可能会选择在年度报告中略去某些内容。

年度可持续发展报告等也非常静态。它们并不实时反映公司的变化,它们只反映一段时间内变化的累积。这种方法错过了所有实时发生的变化,这些变化可能会反映在新闻报道中。

一种更具活力的可持续投资方法将考虑实时变化,同时降低分析年度可持续性报告的复杂性。这将使可持续投资更具可扩展性,提高效率,同时减少人为失误。

NLP 如何提供帮助

自然语言处理可用于分析可持续发展报告和新闻文章,从中提取重要的 ESG 中心见解。这降低了手动分析报告的复杂性,同时还通过查看新闻文章中的实时变化使该方法更加动态。

让我们来看一个例子:

我们自豪地为苹果设施实现了 100%的可再生电力,并为苹果的企业排放实现了碳中和,包括商务旅行和员工通勤。我们正在着手一个新的目标,即到 2030 年实现我们整个碳足迹的碳中和。

——摘自 2020 年苹果可持续发展报告[4]

NLP 模型可以对报告执行下游 NLP 任务,如文本分类情感分析,而不是手动读取和分析报告,从而降低分析报告的复杂性,并使整个过程更加节省时间和资源。在这种情况下,NLP 模型会将摘录分类为与“气候变化”相关,情绪值为“积极”。

NLP 使投资者能够对报告和文章进行更好和更有效的分析,从而做出更明智的可持续投资决策。

在我在parabole . ai的实习中,我能够通过进一步预先训练谷歌的“BERT”语言模型,在大型非结构化可持续发展文本语料库上开发 ESG-BERT。

我曾尝试使用' sci-kit learn 模型和'计数矢量器'来解决这个问题。鉴于这一领域的性质及其独特的词汇,传统的 ML 模型并没有产生令人满意的结果。另一方面,深度学习模型需要大量的结构化文本数据,这正是我们在这种情况下所缺乏的。有大量的非结构化文本数据,但是结构化数据却很少。

在尝试了这些方法之后,我转向了谷歌的 BERT,它是在大型非结构化文本语料库上预先训练的,因此对于下游的 NLP 任务,例如文本分类,需要更少的结构化数据。这似乎非常符合我们的情况。[5]

BERT(来自变形金刚的双向编码器表示)是 Google 开发的一项技术,用于自然语言处理模型的预训练。官方的 BERT repo 包含不同的预训练模型,可以在下游 NLP 任务上进行训练,增加了一个输出层。然而,这些模型是在通用英语文本语料库上预先训练的,并且它们不能够理解特定领域的词汇。[5]

可持续投资作为一个领域有一个独特的词汇,ESG-BERT 能够理解。 ESG-BERT 在非结构化文本数据上进一步训练,准确率为 100%98% ,用于下一句预测和屏蔽语言建模任务。针对文本分类的微调 ESG-BERT 产生了 0.90 的 F-1 分数。作为对比,一般的 BERT (BERT-base)模型在微调后得分 0.79 ,sci-kit learn 方法得分 0.67

作者图片

ESG-BERT 的应用可以扩展到不仅仅是文本分类。它可以进行微调,以执行可持续投资领域中的各种其他下游 NLP 任务。

如何使用 ESG-BERT?

预先训练好的特定领域 ESG-BERT 模型可以从 GitHub 资源库这里下载。可以对其进行微调,以执行下游的 NLP 任务,如情感分析等。

ESG-BERT 也进行了微调,以对可持续投资文本数据进行文本分类。如 GitHub repo 的 readme 部分所述,可以下载并提供微调后的模型。

照片由诺亚·布舍尔Unsplash 上拍摄

结论

这是可持续投资文本挖掘的重要一步。

ESG-BERT 可用于让投资者更容易获得可持续投资。它通过弥合复杂的可持续性数据和投资者之间的差距,使可持续性作为一个目标更容易实现。然而,它的影响不仅仅局限于文本挖掘。可持续发展报告通常长达数百页,充斥着大多数人无法理解的 ESG 术语。这个工具使这些可持续发展报告更具可读性,每个人都可以访问,因此增加了可持续投资的影响。这让我们离更绿色、更安全、更可持续的未来更近了一步。

在不久的将来,我将发布教程,介绍我如何进一步预训练 BERT 以创建 ESG-BERT,我如何使用 PyTorch 微调 BERT,并讨论其他使用“计数-矢量器”和“单词袋”模型的 NLP 方法。

参考

[1] — 可持续投资基础知识,美国 SIF:可持续和负责任投资论坛

[2] — I 曼·戈什,可视化可持续投资的全球崛起(2020) ,视觉资本家

[3] — Alex Davidson,《可持续投资指南》(2015) ,华尔街日报

[4] — 环境进度报告(2020) ,苹果

[5] —Jacob Devlin 和 Chang Ming-Wei,开源 BERT:自然语言处理的最先进预培训 (2018),谷歌人工智能博客

[6] —凯伦·华莱士,对可持续投资感兴趣?以下是你需要了解的关于可持续基金的信息

随时在 LinkedIn 上联系我,给我发消息 这里

Office 系列中的 NLP

原文:https://towardsdatascience.com/nlp-on-the-office-series-cf0ed44430d1?source=collection_archive---------38-----------------------

利用文本挖掘技术,如标记化、tf-idf 和情感分析来分析电视连续剧的脚本。

负责💬👂:为了让你相信我的分析和发现是有效的,你需要对这个节目“相当”熟悉。否则,您可能无法认识到文本挖掘和 NLP 提供了多么强大的工具来进行具有惊人发现的研究项目。

这篇博客有两个主要目标

  1. 介绍文本分析方法,如标记化、n-grams、tf-idf、不同的情感提取和评分工具,并涵盖可用于查找主题/“聚类”文本的 LDA 算法的基础知识。
  2. 当粉丝阅读他们最喜欢的节目时,给他们一种怀旧的感觉,看看数据科学如何支持信念和假设,例如安吉拉总体上是一个卑鄙的人,但对德怀特最好,或者如何从文本中轻松提取个人词汇,例如安迪著名的(大)金枪鱼,或瑞安的 WUPHF,并用于识别人。

我将在整个过程中使用 R,并将利用以下库:

  • tidyversedata.table 进行数据操作
  • 用于 NLP 相关工作的 tidytext、stringr、textdata、textstem、stopwords、sentimentr 和 topicmodels
  • 用于可视化的 ggplot、igraphvisnetwork

我不会做任何文本分析的深度学习,所以请不要期待任何嵌入层知识或 RNN / LSTM 网络。

在进行任何分析之前,我需要从互联网上获取所有的脚本(所有季节的所有剧集),为此我使用了网络抓取。要找到刮刀,请访问以下链接到我的 GitHub。

[## kristofrabay/web_scraping

网页抓取任务。在 GitHub 上创建一个帐户,为 kristofrabay/web_scraping 开发做贡献。

github.com](https://github.com/kristofrabay/web_scraping/blob/master/the_office/office_transcripts_scraper.R)

我还预先在 GitHub 上粘贴了实际分析代码的链接。分析的原始输出是一个闪亮的仪表板应用程序,所以代码可以在应用程序中找到。r 文件。我会在博客中嵌入 Github Gists,但是如果有人对我的部分分析特别感兴趣,可以在脚本的服务器端找到剧情和网络渲染。(对于不熟悉 Shiny 的,抱歉,有问题联系我,或者拉我回购,运行 app。享受我创建的漂亮的仪表板吧!)

[## kristofrabay/办公室-NLP

对 Office 系列进行 NLP(符号化、tf-idf、情感、主题建模)。在闪亮的应用程序中输出…

github.com](https://github.com/kristofrabay/The-Office-NLP/blob/master/app.R)

我想提到几个人,他们给了我与世界分享我的分析的想法:(1)爱德华多·阿里诺,他是硅谷的首席数据科学家,并教会了我 NLP(https://www.linkedin.com/in/earino)和(2)米哈里·奥索斯,他举办了 R 课程并展示了快速有效的网络抓取——这是一项非常非常有用的技能(https://github.com/misrori)。这两门课程都是匈牙利布达佩斯 CEU 大学商业分析硕士项目的选修课程(https://economics . ceu . edu/program/Master-science-Business-Analytics)。

我们开始吧!

资料来源:giphy

我把整篇博文分成 4 块。这是“教学大纲”:

  1. 按季节统计字数,选择前 x 名合作者(有限的数据用于更好的可视化,更容易理解的结果)
  2. 分析最常用的单词、短语(二元模型)和最个性化的单词(tf-idf)
  3. 运行有无季节性的情绪分析,确定“谁对谁好,谁对谁坏,坏到什么程度”
  4. 展示 LDA 的能力——注意:在此用例中没有用,使用新闻文章或博客的主题建模(其中可指定的主题数量确实有限)

#1.熟悉数据,选择要处理的子数据

如上所述,我将和有限的几个人一起工作来降低我的视觉效果的复杂性。我会选出整个系列中台词最多的前 12 个人。他们覆盖了几乎 80%的台词,所以我觉得这是一个很好的比例。此外,当比较 12 个人时,我可以使用 3×4 的 ggplot 网格结构,使我的图形对称。

让我们看看这些人总共有多少条线,按季节划分。

前 12 个字符的总行数

很明显迈克尔有最多的台词,即使没有参加最后两季。如果我们按季节检查线路数,我们就能确切地看到谁在迈克尔离开后得到了大多数线路。

按季节的行数

ggplot 提供了一个很好的方法来自动排序每个类别/方面中的条形/柱形(在本例中是季节)。我提供了一个示例代码供您查看:

数据帧有 3 列使用:(1)姓名,表示谁说的线,(2)实际的线,和(3)给定季节的#号。我们在这里所做的是按季节和名称对数据进行分组,汇总计数,按季节选择前 12 个结果(人),然后在季节内重新排列条形(指示名称)。这个简单的 reorder_within 给了我们非常漂亮、平滑的图表。

现在我们知道了我们将和哪些人一起工作,我们可以开始做一些文本分析了。

#2:文本分析(标记化、二元模型、tf-idf)

A.标记化—检查最常用的单词

作为第一步,让我们看看人们最常用的词是什么。TidyText 提供了一个非常容易使用的函数,名为 unnest_tokens ,可以在任何字符串向量上运行,从其中取出每个字符串(单词)并将其存储在数据帧的“列”中。如果我们的字符串是‘我的名字是约翰’,那么它会把这个句子 unnest 成一个 4×1 的字符串向量,元素有[‘我的’,‘名字’,‘是’,‘约翰’]

第二步,让我们意识到,在前面的字符串向量示例中,4 个单词中只有 2 个有意义/兴趣:“name”和“John”。“My”和“is”被视为停用词。这些是没有意义的常用词,在没有进一步信息的情况下增强文本。幸运的是,包含任何给定语言的停用词的词典是公开可用的,我们只需要将它们加载到我们的脚本中。英语的例子有‘onix’,‘snowball’,‘SMART’,但是有你想要的任何语言。

为了去掉新创建的字符串列中的停用词,其中每个单元格包含一个单词,我们需要做的是与 join 方法相反的事情。通过一个简单的连接(假设是左连接),我们可以匹配左侧可以找到的所有内容。然而,在这里,如果一个停用词出现在左列,我们希望删除该观察/行。这就是为什么 dplyr 库提供 R 用户 anti_join 的原因,这就是为什么。在对先前的字符串向量应用了停用词的 anti_join 之后,我们从 ['My ',' name ',' is ',' John']['name ',' John']

在结果出来之前,这里是代码,使用 2 个不同的停用词词典和一个手动创建的字符串向量,这些字符串在文本中很常见,但没有“意义”。这里,我们取消了包含人的行的“文本”列,以创建一个名为“单词”的新列。然后我们删除带有停用词的行。

这是实际输出。

人们最常说的话

这里有些有趣的东西。对于每个人来说,包含他们的热门单词的列表包含其他人的名字。这是合乎逻辑的,因为这是一个基于对话的系列,当不考虑停用词时,最常见的标记是当人们转向他们的同事时,称呼他们的名字。有趣的是,有些人,像德怀特和帕姆,他们的名字在最上面。这是因为他们必须通过电话介绍自己:德怀特是推销员,帕姆是办公室接待员。

这真的给了我一个想法:让我们看看人们通常和谁交谈。为此,我将指示谁说了那句台词的列移动一行,然后我将看到谁说了那句台词以及这句台词是对谁说的,最后我将删除由同一个人说的和对同一个人说的台词(多行,或关闭和打开一个场景)。

不幸的是,我不能在这里粘贴一个交互式的 visNetwork 对象,但这里有一个截图。

它试图表明大多数谈话发生在 Michael、Dwight、Jim 和 Pam 之间,同时我还选择了 Dwight 来展示如何按人检查结果。我将边缘的宽度设置为与两个字符之间的行数一致,并将节点的大小设置为代表总行数。visNetwork 是一个很棒的工具,非常容易使用!

B.二元模型(n grams)——频繁短语分析

我们现在知道热门词汇包括其他人的名字,偶尔还有一些暗示一个人身份的符号(例如:达里尔说的“迈克”,安迪说的“金枪鱼”,菲利斯说的“万斯”)。让我们开始寻找人们最常用的短语。

短语是指你有不止一个单词。你可以分析任意数量的互相跟随的单词——这就是为什么这种方法被称为 ngrams analytics。如果 n 恰好是 2,那么我们称它们为二元模型。这就是我们现在要做的。

下面是如何做到这一点的代码。

我们可以利用相同的 unnest_tokens 函数,但是这次我们将调用输出列“bigram”,我们将使用“text”列来创建输出,我们将 token 参数设置为“ngrams”而不是“words”(默认设置),并将“n”参数设置为 2,表示我们想要创建 bigram。

坚持'我的名字是约翰'的例子,而 tokenization (token = 'words ')创建了这个向量: ['我的','名字','是','约翰'] ,现在,bigram 方法产生了下面这个向量: ['我的名字','名字是','是约翰'] 。然后我们通过获取二元模型的第一个和第二个令牌,将这个新列分成两部分。下一步,我们只对两个单词都不是停用词的二元模型感兴趣,因此两个单词都包含某种信息,所以我们从第一个和第二个单词向量中过滤出停用词。最后一步,我们用一个空间把两个柱子粘在一起。我们完成了,我们已经“大化”了文本数据。以下是按人分类的结果:

顶级人物使用的顶级二元模型(短语)

这下可好了!如果你熟悉这个节目,你会清楚地看到双面人物非常有能力识别人。除了安迪,还有谁会用‘纳德狗’和‘西兰花劫’呢?除了瑞安,还有谁会谈论“商学院”和“米夫林无限”?德怀特显然喜欢“区域经理”和“区域助理”这两个词。如果我们使用三元组(3 个单词组成一个短语),我们肯定会在德怀特的列表中看到“助理区域经理”。

二元模型比简单的记号更能识别某个人。然而,有一种方法甚至比 ngrams 更值得信赖。它叫做 tf-idf ,是下一个话题的主题。

C.tf-idf —按个人查找最个性化/独特的词语

我暗示了这个算法的能力,但是让我快速解释一下它是如何做到的。tf-idf 的 tf 部分代表词频,idf 表示逆文档频率。

第一部分很简单:它获取单词,按照文档中单词的绝对数量对它们进行排序(例如,Michael 在这里是一个“文档”,至少他的词汇表是——TF 找到 Michael 的热门单词)。基本的标记化和计数聚合。

IDF 是奇迹发生的地方。IDF 进行检查,考虑某些单词排名的所有文档(在这种情况下是人的词汇表)。它决定了,如果一个词出现在大多数文档中,那么它是常见的,如果它只出现在某些文档中,那么它是罕见的。

然后,tf-idf 将某个文档内的总频率与逆文档频率进行比较(相乘),并确定任何单词的对于某个文档是否是唯一的。例如,迈克尔可能说过很多次狂犬病,但是其他人并没有真正提到这个词。因此,tf-idf 算法将确定狂犬病在迈克尔的词汇中是一个独特的词。

理解了算法的基础之后,让我们将它应用到数据中,看看它发现了什么。首先是代码,然后是解释。

这里面好像有很多东西,但是很简单。

  1. 我将字符串数据转换成记号——简单的单词
  2. 这次我应用术语化。这是一个尝试将单词恢复到“正常”、“词根”形式的过程。它可以采用以下单词:[' studing ',' studies ',' studied ',' study'] 并且在词汇化之后,所有单词都将是 ['study'] ,因为所有单词都源自这个单词。通过这种方式,我删除了单词的“结构”信息,但获得了关于哪个“词根”单词最常用的信息。
  3. 然后我按人对单词进行计数,这是 tf-idf 确定一个单词的 idf 所必需的输入( count 函数是一个 group_by 函数,然后是一个 summary(count)函数)
  4. 然后是最重要的部分:tidytext 的 bind_tf_idf 函数。没有比这更简单的了。它接受文档(人名)列、标记列(词汇化和取消嵌套后的单词)和计数列(单词在给定文档中出现的次数)并运行 tf-idf 数学公式。
  5. 最后一步,由于关系,我决定只可视化每个人的前 8 个独特的单词。

tf-idf 前 12 名

让我们来看看。已经识别出最独特的单词。真的,所有人看 tf-idf 的字就能被一个真正的办公室粉丝识别出来。

  • 安迪:金枪鱼,纳德,高音,杰西卡
  • 安琪拉:糖粉,小鼓手男孩送的帕伦彭
  • 达里尔:杰斯丁的豆豆,迈克
  • 德怀特:副警长,摩西,警长,农场
  • 等等…

如此简单的工具却能产生如此巨大的效果。

熟悉词汇之后,让我们开始关注人们通常将 NLP 与联系在一起的“另一件大事”:情感分析。

#3.情感分析

对文本数据进行情感分析/情感评分有多种方式。一些可能的方法是

  • 按词分类的情感(即积极/消极类,如 Bing 词典,或情绪类,如愤怒、喜悦、信任、NRC 词典中的预期)
  • 情绪的数字评分(AFINN 词典:美丽、令人惊叹+3、困扰、不便-2)
  • 在 ngram /句子级别上运行情感评分—算法确定句子的总体情感,介于-1 和 1 之间,其中-1 表示全部负面,+1 表示全部正面,0 表示中性/不可分类。

在上述方法中,我将利用 3:

  1. 我将标记分为正面和负面,按人计数,并为每个人创建一个列表,列出他们最常用的正面和负面词汇。
  2. 我将应用 AFINN 词典,对每个单词进行评分,然后用该单词的频率乘以情绪得分,并创建一个单词列表,这些单词对人们的词汇产生了最积极或消极的影响。
  3. 我将按字符级别对说出的句子/句子进行情感评分,并通过 AFINN 分数将结果与令牌级别的情感聚合进行比较。

A.使用类别分类运行情感分析

这只是一个简单的介绍步骤。我把所有的单词,分成正反两类,统计每个单词,按人确定最常用的正反两类单词。这真的只是一个热身运动。

按字符排列的最常用的正面和负面单词

我们在这里看到的是,比较正面和负面词汇的数量,大多数人使用正面词汇的频率高于负面词汇。安吉拉可能是个例外,她最积极的词(好)和最不积极的词(坏)出现的次数几乎一样多(约 22 次)。这本身并不能真正代表个性。为此,我将使用 AFINN 词典。

B.使用 AFINN 的数字情感评分

这一次,我不是简单地将单词分类,而是给每个单词分配代表积极和消极的数字。然后,我会将情感分数乘以单词数,得出一个“贡献”因子:一个单词对一个人的词汇有多少积极或消极的贡献。例如,‘恶心这个词的分数是-3,而‘漂亮这个词的分数是+1。这意味着需要 3 个漂亮的来抵消 1 个恶心的

在显示结果之前,让我向您展示这样做的代码。

事情是这样的:

  1. 我们由人们将台词分解成单词(保留关于谁说了台词的信息)
  2. 我们应用词汇化使单词回到它们的词根形式(“学习”→“研究”)
  3. 我们从 2 个词典、一个手动创建的列表和人名列表中删除了停用词(我们不能对姓名进行情感评分,它们将被归类为中性,并影响平均值和中值统计数据)
  4. 我们应用“计数”函数,该函数首先按“名称”对数据进行分组,然后按计数聚合对数据进行“汇总”。我们现在有 3 列:(1)名称,(2)单词和(3)计数。
  5. 我们通过“单词”列将 AFINN 词典加入到我们的数据中。现在每个单词的分数都在-3 到+3 之间(我们使用内部连接,所以最后只保留匹配)
  6. 最后一步,我们将“分数”乘以“计数”来获得贡献因子

让我们检查一下视觉效果。

人们贡献的情感

现在我们需要寻找的是红色条最长的地方,以找到对他们的谈话贡献最消极的人。安吉拉、达里尔和德怀特似乎是红色条的平均长度接近绿色(正)条的人。

C.人与人之间的感情

我意识到我应该对情感做更多的事情。其中之一是检查谁对谁最好,谁对谁最刻薄。为此,我将使用与我的“对话网络”相似的方法。我将确定谁对谁说了这句话,通过“ from — to ”列进行情感评分,并可视化我的结果!

人与人之间的情感(条形图)

就拿安吉拉来说吧:她对德怀特最好,对奥斯卡最差。条形图很容易理解,但是网络会让它看起来更好。同样,我不能在这里粘贴一个 HTML 元素,所以请查看另外两个交互式网络的截图。

情感网络

多好啊!我还能做一件事让它看起来更好。我不一定要把所有的关系形象化,而是把重点放在最积极和最消极的关系上。但是,如何决定哪些“边缘”保留给网络呢?让我们按人对分数进行分布分析,去掉平均值/中值,只显示“极端”关系。

分数分布

下面是上图的意思。以吉姆为例——他对其他人的情感评分在 15 到 100 之间,有很高的极端值。大多数分数都在-10 到+30 之间,所以我会把所有的分数都保持在这个范围之外,以应对极端情况。包含大多数“极端”关系的 visNetwork 如下:

具有表示积极/消极度量的边的情感网络

我们可以看到(再次抱歉,这是一个互动网络)吉姆和帕姆之间的绿色边缘最宽,这意味着他们之间的情绪是所有人中最积极的。奥斯卡和安吉拉互相相当消极对方采取另一个例子,从网络。

D.季节性情绪趋势

作为情绪分析的最后一步,让我快速运行所有人的逐集和逐季情绪趋势,看看我们是否能跟踪他们的快乐/悲伤。

首先,剧集层面的概述。

上面的图表没有提供任何信息。每集的平均情绪(通过使用senmentr包的情绪 _by 函数计算,其中每行的情绪得分在-1 和 1 之间)波动太大,无法提供任何见解。让我们检查季节性数据。

这在某种程度上更容易解释,但无法提取出明确的趋势。也许安迪的解雇是有暗示的,但季节平均情绪得分和人的快乐/悲伤之间没有明确的关系。

除此之外,我们还可以看到办公室的两个主要竞争对手吉姆和德怀特之间的平均情绪是如何随着时间的推移而发展的。

我对此运行了两个算法,首先在标记级别使用 AFINN,然后在行/句子级别使用 sentimentR,结果非常相似。

两人都暗示这对情侣的关系在接近尾声时变得更好,这与故事相符,因为竞争停止了,友谊开始了。这是有争议的,情感趋势很难在这里建模。

#4.LDA 快速介绍

在结束之前,让我向您展示另一个典型的 NLP 工作:使用 LDA(潜在 Dirichlet 分配)运行主题建模。对我来说,这非常类似于一种无监督的机器学习算法,k-means 聚类完成它的工作。它在方法论上有很大的不同,但结果是相似的:最后,聚类找到多少“属于”在一起的数据点,形成“相似但未标记的组”。LDA 的输出是一个单词列表,这些单词“属于一起”,“组成一个未标记的主题”。

我不会详细说明算法实际上是如何运行的,但我会给你一个例子。我们一直在和前 12 名合作(按行数)。在这种情况下,我们可以使用 LDA 来寻找词汇相似的人。也就是让(force) LDA 创建 12 个聚类/主题,并吐出某个人是给定主题的一部分的概率。

我们就这么做吧。

下面是上面 3 行代码中发生的情况

  1. 输入数据具有 3 列:(1)说出该行的人的姓名(通常称为文档),(2)单词列(在标记化之后)以及(3)指示该单词在给定文档中出现了多少次的列
  2. 我们需要为运行 LDA 创建一个文档术语矩阵
  3. 我们将集群/主题的数量设置为 12,并设置一个随机状态以使我们的工作可重复
  4. 一旦 LDA 算法完成,我们可以提取两个概率:(1)beta——一个单词成为主题的一部分的概率,以及(2) gammas —一个主题成为文档的一部分的概率:这里我们提取 gammas ,因为我们想要一个主题(词汇)成为文档(人)的一部分的概率

这是我们可视化后得到的结果

12 个人的 LDA 词汇

大多数人都有自己使用的特定词汇,然而德怀特和迈克尔似乎都根据他们选择的词汇组成了 2-2 个词汇。Oscar 和 Angela 共享一个群集,这意味着他们有相似的发音词汇(他们都是会计师),有趣的是,虽然 Jim 和 Pam 有各自的话题,但他们共享一个话题(话题# 8 ),可能是他们的个人(办公室之外)生活,如他们的家庭、女儿、婚礼策划等…

这远非完美,LDA 不保证实际的主题,如“金融”或“IT”,这些主题需要由分析师在一些创造性的,但可能是主观的思考后命名。

收尾工作

在这篇博文中,我提到了以下 NLP 主题:

  1. 标记化、双分枝化和 tf-idf 来从文本数据中提取单词、短语和唯一标记
  2. 使用分类和数字结果的情感分析,如何使用它们来显示对文本的情感贡献
  3. 最小 LDA 将发音相似的人“聚集”在一起,或者至少提取一个人与另一个人分享话题的可能性

我在 Office 脚本中展示了所有上述 NLP 方法,作为一个非常熟悉该节目的人,我可以诚实地说,这些方法中的一些,虽然很容易使用,但会产生令人敬畏的结果。关于 tf-idf 和 ngrams,毫无疑问它们能够对任何文本数据创造奇迹。甚至情感评分似乎也站得住脚,尽管句子级别的聚合和趋势分析很困难,但标记级别的比较是有希望的。关于 LDA,让我们只是“小心行事”。

总的来说,这是我尝试这些方法的一个很好的方式,看看它们如何处理“实时”数据。如果对我的代码有疑问,请访问我的 GitHub 页面(https://github.com/kristofrabay)并在那里联系我。

资料来源:giphy

NLP:使用 TensorFlow2 为深度学习模型准备文本

原文:https://towardsdatascience.com/nlp-preparing-text-for-deep-learning-model-using-tensorflow2-461428138657?source=collection_archive---------8-----------------------

TensorFlow2 中的文本预处理(标记化、排序、填充)是如何工作的。

作者图片

自然语言处理(NLP)通常用于文本分类任务,例如垃圾邮件检测和情感分析、文本生成、语言翻译和文档分类。文本数据可以被认为是字符序列、单词序列或句子序列。最常见的是,对于大多数问题,文本数据被认为是单词序列。在本文中,我们将深入研究使用简单示例文本数据的预处理。然而,这里讨论的步骤适用于任何 NLP 任务。特别是,我们将使用 TensorFlow2 Keras 进行文本预处理,包括:

  • 标记化
  • 定序
  • 填料

下图描述了文本预处理过程以及示例输出。

从原始句子开始到填充序列的逐步文本预处理示例

首先,让我们导入所需的库。(我的 GitHub 页面里有完整的 Jupyter 笔记本)。

import tensorflow as tf
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences

Tokenizer 是 TensorFlow Keras 中提供的一个 API,用来对句子进行分词。我们将文本数据定义为句子(每个句子用逗号分隔)和一组字符串。共有 4 个句子,包括 1 个最大长度为 5 的句子。我们的文本数据还包括标点符号,如下所示。

sentences = ["I want to go out.",
             " I like to play.",
             " No eating - ",
             "No play!",
            ]
sentences['I want to go out.', ' I like to play.', ' No eating - ', 'No play!']

标记化

由于深度学习模型不理解文本,我们需要将文本转换成数字表示。为此,第一步是标记化。TensorFlow Keras 的 Tokenizer API 将句子拆分成单词,并将这些单词编码成整数。以下是在记号赋予器 API 中使用的超参数:

  • num_words:限制训练时保留的最常用单词的最大数量。
  • 过滤器:如果没有提供,默认情况下过滤掉所有标点符号(!idspnonenote)。"#$%&()*+,-./:;<=>?@[]^_'{|}~\t\n).
  • 下限=1。这是默认设置,将所有单词转换为小写
  • oov_tok:当它被使用时,词汇外标记将被添加到用于建立模型的语料库中的单词索引中。这用于在 text_to_sequence 调用期间替换词汇表外的单词(不在我们的语料库中的单词)(见下文)。
  • word_index:将所有单词转换为整数索引。单词完整列表可用作键值属性:key =单词,value =单词的令牌

让我们使用分词器并打印出单词索引。我们已经使用了 num_words= 100,这对于这个数据来说是很多的,因为只有 9 个不同的单词和用于词汇外令牌的< OOV >字符串。

tokenizer = Tokenizer(num_words=100, lower= 1, oov_token="<OOV>")
tokenizer.fit_on_texts(sentences)
word_index = tokenizer.word_indexprint(word_index)
{'<OOV>': 1, 'i': 2, 'to': 3, 'play': 4, 'no': 5, 'want': 6, 'go': 7, 'out': 8, 'like': 9, 'eating': 10}

如上所述,我们句子中的每个单词都被转换成了数字符号。例如,“I”的值为 2。分词器也忽略了单词后面的感叹号。例如,单词“play”或“play!”只有一个标记即 4。

排序

接下来,让我们使用来自 tokenizer 对象的 texts_to_sequences 用数字序列表示每个句子。下面,我们打印出原始句子、单词索引和序列。

sequences = tokenizer.texts_to_sequences(sentences)
print(sentences)
print(word_index)
print(sequences)['I want to go out', ' I like to play', ' No eating - ', 'No play!']{'<OOV>': 1, 'i': 2, 'to': 3, 'play': 4, 'no': 5, 'want': 6, 'go': 7, 'out': 8, 'like': 9, 'eating': 10}[[2, 6, 3, 7, 8], [2, 9, 3, 4], [5, 10], [5, 4]]

如上所示,文本由序列表示。举个例子,

  • “我要出去”——>[2,6,3,7,8]
  • “我喜欢玩”——>[2,9,3,4]
  • “不准吃东西”——>[5,10]
  • “不玩了!”— -> [5, 4]

填充

在任何原始文本数据中,自然会有不同长度的句子。然而,所有的神经网络都要求具有相同大小的输入。为此,需要进行填充。下面,我们用 pad_sequences 进行填充。 pad_sequences 使用 sequences、padding、maxlen、truncating、value 和 dtype 等参数。

  • 序列:我们之前创建的序列列表
  • padding = 'pre '或' post(默认 pre)。通过使用 pre,我们将在每个序列之前填充(添加 0 ), post 将在每个序列之后填充。
  • maxlen =所有序列的最大长度。如果没有提供,默认情况下它将使用最长句子的最大长度。
  • truncating = 'pre '或' post '(默认为' pre ')。如果序列长度大于提供的 maxlen 值,则这些值将被截断为 maxlen 值。“前”选项将在序列的开头截断,而“后”将在序列的结尾截断。
  • 值:填充值(默认值为 0)
  • dtype:输出序列类型(默认为 int32)

让我们关注一下 pad_sequences 中使用的重要参数:padding、maxlen 和 truncating。

前后填充

使用“前”还是“后”填充取决于分析。在某些情况下,开头填充是合适的,而在其他情况下则不合适。例如,如果我们使用递归神经网络(RNN)进行垃圾邮件检测,那么在开始填充将是合适的,因为 RNN 不能学习长距离模式。开始时的填充允许我们保留最后的序列,因此 RNN 可以利用这些序列来预测下一个。然而,在任何情况下,填充都应该在仔细考虑和业务知识之后进行。

下面显示了“前置”和“后置”填充的输出,带有序列最大长度的默认 maxlen 值。

**# pre padding**
pre_pad = pad_sequences(sequences, padding='pre')print("\nword_index = ", word_index)
print("\nsequences = ", sequences)
print("\npadded_seq = " )
print(pre_pad)word_index =  {'<OOV>': 1, 'i': 2, 'to': 3, 'play': 4, 'no': 5, 'want': 6, 'go': 7, 'out': 8, 'like': 9, 'eating': 10}

sequences =  [[2, 6, 3, 7, 8], [2, 9, 3, 4], [5, 10], [5, 4]]

padded_seq = 
[[ 2  6  3  7  8]
 [ **0**  2  9  3  4] <---------- **0** Padded at the beginning
 [ **0  0  0**  5 10] 
 [ **0  0  0**  5  4]]

在我们上面的例子中,最大长度的序列是[ 2,6,3,7,8],对应的是“我想出去”。当使用 padding ='pre '时,在所有其他序列的开头添加填充值 0。因为其他序列比[ 2,6,3,7,8]更短,填充实际上使所有其他序列与此序列大小相同。

然而,当使用 padding =“post”时,在序列的末尾添加填充值,即 0。

**# post padding**
post_pad = pad_sequences(sequences, padding='post')
print("\nword_index = ", word_index)
print("\nsequences = ", sequences)
print("\npadded_seq = " )
print(post_pad)word_index =  {'<OOV>': 1, 'i': 2, 'to': 3, 'play': 4, 'no': 5, 'want': 6, 'go': 7, 'out': 8, 'like': 9, 'eating': 10}

sequences =  [[2, 6, 3, 7, 8], [2, 9, 3, 4], [5, 10], [5, 4]]

padded_seq = 
[[ 2  6  3  7  8]
 [ 2  9  3  4  **0**]<---------- **0** Padded at the end
 [ 5 10  **0  0  0**]
 [ 5  4  **0  0  0**]]

使用 maxlen 和截断选项进行前后填充

如果需要,我们可以同时使用填充和截断参数。下面我们展示了两种情况,1)预截断的预填充和 2)后截断的预填充

使用“pre”选项截断允许我们在开始时截断序列。然而,用“post”截断将在最后截断序列。

让我们看一下使用前置截断进行前置填充的例子。

**# pre padding, maxlen and pre truncation**
prepad_maxlen_pretrunc = pad_sequences(sequences, padding = ‘pre’, maxlen =4, truncating = ‘pre’)
print(prepad_maxlen_pretrunc)[[ 6  3  7  8]<-----Truncated from length 5 to 4, at the beginning
 [ 2  9  3  4]
 [ **0  0**  5 10]<---------- Padded at the beginning
 [ **0  0 ** 5  4]]

通过使用 maxlen =4,我们将填充序列的长度截断为 4。如上所示,maxlen=4 的使用影响了第一个序列[2,6,3,7,8]。该序列的长度为 5,被截断为 4。截断发生在开始时,因为我们使用了 truncating = 'pre '选项。

让我们看看 truncation = 'post '选项。

**# pre padding, maxlen and post truncation**
prepad_maxlen_posttrunc = pad_sequences(sequences, padding = 'pre', maxlen =4, truncating = 'post')
print(prepad_maxlen_posttrunc)[[ 2  6  3  7]<-----Truncated from length 5 to 4, at the end
 [ 2  9  3  4]
 [ **0  0**  5 10]<---------- Padded at the beginning
 [ **0  0**  5  4]]

当我们使用 truncating = 'post '选项时,截断发生在最后。当应用后截断时,它影响第一个序列[ 2,6,3,7,8]并被截断为长度 4,从而产生序列[ 2,6,3,7]。

总结

在本文中,我们专注于预处理原始文本数据,并为深度学习模型做准备。具体来说,我们讨论了对句子进行标记,将其表示为序列,并对其进行填充以使所有序列长度相同。该填充序列现在准备好用于神经网络的训练/测试分割。请参考 Laurence Moroney 的 NLP zero to hero 的视频进行进一步阅读。

在未来的文章中,我将解释我们如何在真实世界的数据中使用预处理,并在深度学习模型中使用这种嵌入的填充序列数据。

感谢您的阅读,如果您有任何意见或建议,请留下。

快乐学习!!!

NLP-预处理临床数据以找到切片

原文:https://towardsdatascience.com/nlp-preprocessing-clinical-data-to-find-sections-461fdadbec77?source=collection_archive---------46-----------------------

清洗医学文本

在本帖中,我们将使用医疗图表笔记数据 ( 医生的潦草笔记 ) 对临床笔记中存在的主题进行建模。记住,写这些笔记是没有结构的。

在后面的故事中,我们将总结这些笔记。

将在 4 篇文章中讨论的 NLP 任务:

  1. 预处理和清洗
  2. 文本摘要
  3. 使用潜在狄利克雷分配(LDA)的主题建模
  4. 聚类

如果您想亲自尝试整个代码或跟随,请访问我在 GitHub 上发布的 jupyter 笔记本:https://GitHub . com/gaurikatyagi/Natural-Language-Processing/blob/master/introduction % 20 to % 20 NLP-Clustering % 20 text . ipynb

数据:

来源:https://mimic.physionet.org/about/mimic/

医生在他们的电脑上做笔记,80%的记录是没有结构的。这使得信息处理更加困难。我们不要忘记,解释医疗术语也不是一件容易的事情。它需要大量的上下文来解释。让我们看看我们有什么:

按作者分类的图像:作为输入的文本数据

我们立即注意到的事情:

  1. 这是没有标记的纯文本。如果它有标记,我们可以使用像美丽的汤这样的库
  2. 这些行被人工换行(每当您看到单个\n
  3. 没有错别字..哇哦,但是太多首字母缩写和大写字母了
  4. 有像逗号、撇号、引号、问号这样的标点,还有像“后续”这样的连字符描述
  5. 使用了大量有序数据,因此出现了“1”, '2.'诸如此类。但是,请注意,即使在这些数字之前,实际上也有一个单线制动(如 2 中所示)
  6. 看看那些不确定的名字是如何被替换成“姓”或“名 3”,“医院病房名”之类的,好在这些都在方括号内,很容易识别。这些后面也总是跟着一个括号。耶!一些我们可以从一开始就去除的东西!
  7. 注意可能需要如何处理日期(如果它们都不是相同的格式)
  8. 注意一些格式:比如:\n\n ******* \n\n 或者 n??????\tT。我们需要处理好这一切

1.预处理

a.正则表达式:我们将使用正则表达式模式来清理我们的文本。是的,我们确实需要多次反复的清理!

图片作者:Regex Cleaning

作者图片:正则表达式清理的输出

b.添加 Context 和 Lemmatize text: 看,我们是怎么讲 Lemmatize 和 not stemming 的。理解两个之间的差异很重要。

在本节中,我们使用大写单词提取“潜在主题”来识别图表中的子主题。然后,专家手动将这些短语标记为“T”或“F”,以表示接受。一旦我们有了它,我们就改变了所有其他单词的大小写。等等,没那么容易,记住我们需要把它归类。

作者图片:为上下文添加子部分

作者图片:确定了 124 个副标题

现在,我们将把所有大写单词的大小写改为小写,除非它们是上面确定的主题

通过运行 lemmatizer 找到上述所有主题的词条。我们删除了主题中的停用词,以便在“大写单词列表”中捕捉更多的主题。

那么,这里发生了什么变化?

for index in range(len(lemmatized_topics_index)):
    print("Original Topic: %s \n New Topic Index: %s\n New Topic value: %s"%(topics[index],                                                                                       lemmatized_topics_index[index],                                                                lemmatized_topics_values[index]
)
)
    ##you can remove this to see all pairs
    if index>2:
        break
    print("\n\n")

作者图片:词汇化和词干化的区别

比较每个主题的词干,如果与词条化主题的词干不匹配,则将其改为小写。

为什么先做词条解释,然后只匹配词干?因为词汇化是根据单词属于哪个词类来完成的。然而,词干提取只是试图通过去除常见的复数(etc)字母来找到单词的词根。

因此,我们与词干部分进行比较,但保留已识别主题的词汇作为最终主题。这甚至允许我们在不同的图表注释中获得标准化的主题

作者图片:已清理主题

这里是我们最终的主题列表,分析师可以使用 Spacy 中的 spans 来解析和提取所需的信息。这不是很好吗!

在我的下一篇文章中,我将谈论文本摘要。

用 NLTK 进行文本预处理

原文:https://towardsdatascience.com/nlp-preprocessing-with-nltk-3c04ee00edc0?source=collection_archive---------8-----------------------

自然语言处理的常用预处理方法

照片由卡洛斯·穆扎Unsplash 上拍摄

介绍

几乎每个 自然语言处理(NLP) 任务都需要在训练模型之前对文本进行预处理。深度学习模型不能直接使用原始文本,因此需要我们研究人员自己清理文本。根据任务的性质,预处理方法可以不同。本教程将使用 NLTK(自然语言工具包) 教授最常见的预处理方法,以适应各种 NLP 任务。

为什么是 NLTK?

  • 流行度 : NLTK 是处理语言数据的领先平台之一。
  • 简单性:为多种文本预处理方法提供易于使用的 API
  • 社区:它有一个庞大而活跃的社区来支持和改进图书馆
  • 开源:免费开源,适用于 Windows、Mac OSX 和 Linux。

现在你知道了 NLTK 的好处,让我们开始吧!

教程概述

  1. 小写字母
  2. 删除标点符号
  3. 标记化
  4. 停用词过滤
  5. 堵塞物
  6. 词性标注器

本教程中显示的所有代码都可以在我的 Github repo 中访问。

导入 NLTK

在预处理之前,我们需要先下载 NLTK 库

pip install nltk

然后,我们可以在 Python 笔记本中导入这个库,并下载它的内容。

小写字母

举个例子,我们从《傲慢与偏见》一书中抓取第一句话作为正文。我们通过text.lower()将句子转换成小写。

删除标点符号

要去掉标点符号,我们只保存不是标点符号的字符,可以用[string.punctuation](https://docs.python.org/3/library/string.html)来检查。

标记化

可以通过[nltk.word_tokenize](https://www.nltk.org/api/nltk.tokenize.html)将字符串标记成标记。

停用词过滤

我们可以使用[nltk.corpus.stopwords.words(‘english’)](https://www.nltk.org/book/ch02.html)来获取英语词典中的停用词列表。然后,我们删除停用词。

堵塞物

我们使用[nltk.stem.porter.PorterStemmer](https://www.nltk.org/_modules/nltk/stem/porter.html)对标记进行词干处理,以获得经过词干处理的标记。

POS 标签

最后,我们可以使用[nltk.pos_tag](https://www.nltk.org/book/ch05.html)来检索列表中每个单词的词性。

完整的笔记本可以在这里看到

结合在一起

我们可以结合上面所有的预处理方法,创建一个接受一个preprocess函数。txt 文件并处理所有的预处理。我们打印出标记、过滤的单词(在停用词过滤之后)、词干单词和词性,其中一个通常被传递给模型或用于进一步处理。我们使用傲慢与偏见这本书(此处可访问)并对其进行预处理。

此笔记本可在处访问。

结论

对于任何 NLP 应用程序来说,文本预处理都是重要的第一步。在本教程中,我们讨论了几种流行的使用 NLTK 的预处理方法:小写、删除标点、标记化、停用词过滤、词干提取和词性标记。

文本分类建模的 NLP 管道教程

原文:https://towardsdatascience.com/nlp-python-pipeline-tutorial-for-text-classification-modeling-6eb1000f909c?source=collection_archive---------27-----------------------

关于使用 sklearn 的 FeatureUnion、Pipeline 和 transformers 预处理组合文本和数字数据的数据科学 python 教程

文本和数字特征转换器的 Python 代码。作者截图来自GitHub【1】代码。

目录

  1. 什么是特征转换?
  2. NLP 对您的模型的好处
  3. 关于数据
  4. 文本和数字转换器教程
  5. 摘要
  6. 参考

什么是特征转换?

机器学习最困难的方面之一是为您的模型摄取文本数据。在构建模型时,有您的输入或特征,然后是您试图预测的内容。虽然某些类型的模型可以按数值或分类预测值或目标变量进行分组,但当您不仅要使用数值,还要使用文本作为要素类型时,并没有太多的文档说明该如何操作。要素变换是一种将两种类型结合起来并将其转换为可用格式的方法,可作为 X 变量来预测 Y 预测值或变量。下面的代码使用 sklearn 库将这两种类型的数据转换并组合成一个输入。

NLP 对您的模型的好处

NLP,也称为自然语言处理,可用于将文本特征转换为数字表示。好处如下:

  • 将输入要素转换为较小的尺寸
  • 将目标变量转换成较小的大小
  • 将分类数据转换成数字
  • 将文本数据转换为数字
  • 标准化您的输入数据
  • 清理您的数据

关于数据

这里的数据集是随机的,有三个数字特征的虚拟数据;‘已确认 _ 测试’,‘已确认 _ 恢复’,‘已确认 _ 新建’,具有一个文本特征;‘正文 _ 特写’。在这种情况下,目标变量被标记为‘Text _ Predictor’。正常情况下,这个数据集很容易被消化到机器学习模型中,但这里我们引入了一个文本特征,这确实带来了一个问题。问题是,我们有两种截然不同的数据。按照下面的教程,这个问题是用 Python、sk learn【2】和pandas【3】解决和描述的。

仔细观察所用的数据帧。作者截图来自GitHub【1】代码。

文本和数字转换器教程

下面是如何设置 Jupyter 笔记本的教程。ipynb 文件或您的 Python。py 文件。使用 sklearn 的库,您可以读入数据帧,转换输入要素和目标变量,然后开发一个随机森林模型来帮助预测新标签。

  • TfidfVectorizer —术语频率-逆文档频率矢量器,根据您的特征在词的语料库中找到您的术语的唯一性
  • base estimator——sk learn 库的基类
  • 用于 sklearn 库的 transformer Mixin-Mixin 类
  • 管道-将要素和分类器结合在一起
  • FeatureUnion 组合所有特征;文本和数字一起
  • pandas.get _ dummies 将分类目标转换为数字

要遵循本教程,请查找一个类似的数据集,该数据集同时具有数字和文本特征以及分类目标变量。首先,导入必要的库。参考 sklearn 代码和类:

BaseEstimator, TransformerMixin that are used in TextTransfomer and NumberTransformer classes.

接下来,读入你的数据帧。然后,创建您的 vec_tdidf 对象,该对象使用 TfidVectorizer ,通过利用其术语频率逆文档频率矢量器将文本计数转换为术语重要性的加权矩阵。使用管道创建一个管道对象,为“文本特征”一起编译转换器和矢量器。将相同的规则应用于数字要素,并分别对其进行标注。现在所有的特征类型都被转换了,使用 FeatureUnion 将它们合并成一个。

下一步是创建您的随机森林分类器。然后,将特征和分类器结合在一起,这就是你的模型对象。使用 pd.get_dummies 将目标变量从分类变量转换为数字变量也很重要。

为文本和数字特征创建一个列表,并分配目标变量。这些新项目将在 train_test_split 中从您的数据帧中引用。接下来,使用 X_trainy_train 装配您的模型。然后,可以从测试集 X_test 中预测。

最后,使用 sklearn 指标,从你的 y_testpreds (预测)计算出你的 accuracy_score

整个 nlp-example.py 文件。由作者连同sk learn【2】和熊猫【3】一起编码。

摘要

总之,sklearn 及其作者,以及 pandas,已经使编译杂乱和异构的数据变得简单,以便干净有效地输入到您的机器学习模型中。使用这些公共库,每个数据科学家现在不必仅仅依靠数字特征来预测他们的目标变量,而是也可以使用文本/单词/术语数据。使用这些 NLP 技术,可以很容易地对文本分类问题(如术语分类)进行建模。

参考

旁注——在我的代码、文本和文件中,我使用术语“预测器”作为预测的东西,也称为目标变量,或人们试图分类的东西。

[1] M.Przybyla, GitHub (2020)

[2] sklearn, sklearn (2020)

[3]熊猫,熊猫 (2020)

NLP 情感分析手册

原文:https://towardsdatascience.com/nlp-sentiment-analysis-for-beginners-e7897f976897?source=collection_archive---------12-----------------------

逐步了解文本块、NLTK、Scikit-Learn 和 LSTM 网络的方法

Romain VignesUnsplash 上拍摄的照片

介绍

自然语言处理(NLP)是机器学习的领域,专注于语言的生成和理解。它的主要目标是让机器能够理解人类,以自然的方式与人类交流和互动。

自然语言处理有许多任务,如文本生成、文本分类、机器翻译、语音识别、情感分析等。对于 NLP 的初学者来说,查看这些任务以及处理这些任务所涉及的所有技术可能会令人望而生畏。而且事实上,对于一个新手来说,确切地知道从哪里开始以及如何开始是非常困难的。

在所有的 NLP 任务中,我个人认为情感分析(SA)可能是最容易的,这使得它成为任何想开始进入 NLP 的人最合适的起点。

在本文中,我编译了各种如何执行 SA 的技术,从简单的 TextBlob 和 NLTK 到更高级的 Sklearn 和长短期记忆(LSTM)网络。

读完这篇文章后,你可以理解以下内容:

  1. 在 SA: TextBlob 和 NLTK 中使用的工具包
  2. SA 中使用的算法:朴素贝叶斯、SVM、逻辑回归和 LSTM
  3. 术语如停用词移除、词干、单词包、语料库、标记化等。
  4. 创建一个字云

这篇文章的流程:

  1. 数据清理和预处理
  2. 文本 Blob
  3. 算法:逻辑回归,朴素贝叶斯,SVM 和 LSTM

我们开始吧!

远程办公

问题定式化

在本文中,我将介绍由 3000 个句子组成的sentiment数据集,这些句子来自对imdb.comamazon.comyelp.com的评论。每个句子根据它是来自正面评论(标记为1)还是负面评论(标记为0)来标记。

数据可以从网站下载。或者也可以从这里下载(强烈推荐)。文件夹sentiment_labelled_sentences(包含数据文件full_set.txt)应该和你的笔记本在同一个目录下。

加载和预处理数据

设置和导入库

%matplotlib inline
import string
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
matplotlib.rc('xtick', labelsize=14) 
matplotlib.rc('ytick', labelsize=14)

现在,我们加载数据并查看前 10 条评论

with open("sentiment_labelled_sentences/full_set.txt") as f:
    content = f.readlines()content[0:10]

## Remove leading and trailing white space
content = [x.strip() for x in content]## Separate the sentences from the labels
sentences = [x.split("\t")[0] for x in content]
labels = [x.split("\t")[1] for x in content]sentences[0:10]
labels[0:10]

分开句子和标签

我们可以在这里停下来。但对我来说,我更喜欢把 y 变换成(-1,1)的形式,其中-1 代表负,1 代表正。

## Transform the labels from '0 v.s. 1' to '-1 v.s. 1'
y = np.array(labels, dtype='int8')
y = 2*y - 1

请注意,到目前为止,我们还没有对单词做任何修改!!!下一节重点是句子中的单词。

预处理文本数据

要将数据输入到任何模型中,输入的数据必须为矢量形式。我们将进行以下转换:

  • 删除标点和数字
  • 将所有单词转换成小写
  • 删除停用词(例如,the,a,that,this,it,…)
  • 将文本符号化
  • 使用单词袋表示法将句子转换成向量

我将在这里解释一些术语。

  1. Stop words:对手头的任务不感兴趣的常用词。这些通常包括冠词,如“a”和“the”,代词,如“I”和“他们”,以及介词,如“to”和“from”,…
## Demonstrate ##
def removeStopWords(stopWords, txt):
    newtxt = ' '.join([word for word in txt.split() if word not in stopWords])
    return newtxt stoppers = ['a', 'is', 'of','the','this','uhm','uh']
removeStopWords(stoppers, "this is a test of the stop word removal code")

或者,如果我们确实想要使用一套完整的常用停用词,我们可以使用NLTK

from nltk.corpus import stopwordsstops = stopwords.words("English")removeStopWords(stops, "this is a test of the stop word removal code.")

同样的结果

2.Corpus:简单的文字集合。语序事关。“不伟大”和“伟大”是不同的

3.Document-Term MatrixBag of Words (BOW)只是文本句子(或文档)的矢量表示

像这样表示一组要素的一种常见方法称为一键矢量。例如,假设我们文本集中的词汇是:

*today, here, I, a, fine, sun, moon, bird, saw*

我们要为之造弓的句子是:

*I saw a bird today*

*1 0 1 1 0 0 1 1*

为了创造一个单词包,我们需要将一个长句或一份文件分解成更小的部分。这个过程叫做Tokenization。最常见的标记化技术是将文本分解成单词。我们可以在 Scikit-Learn 中使用CountVectorizer来实现这一点,其中每一行代表一个不同的文档,每一列代表一个不同的单词。

现在让我们把所有东西放在一起,组成我们的数据集

def full_remove(x, removal_list):
    for w in removal_list:
        x = x.replace(w, ' ')
    return x## Remove digits ##
digits = [str(x) for x in range(10)]
remove_digits = [full_remove(x, digits) for x in sentences]## Remove punctuation ##
remove_punc = [full_remove(x, list(string.punctuation)) for x in remove_digits]## Make everything lower-case and remove any white space ##
sents_lower = [x.lower() for x in remove_punc]
sents_lower = [x.strip() for x in sents_lower]## Remove stop words ##
from nltk.corpus import stopwords
stops = stopwords.words("English")def removeStopWords(stopWords, txt):
    newtxt = ' '.join([word for word in txt.split() if word not in stopWords])
    return newtxtsents_processed = [removeStopWords(stops,x) for x in sents_lower]

让我们看看现在我们的句子是什么样子的

嗯,等一下!去掉很多停用词会让很多句子失去意义。例如,“way plug us unless go converter”对我来说没有任何意义。这是因为我们使用 NLTK 删除了所有常见的英语停用词。为了克服这个意义问题,让我们创建一套自己的停用词。

stop_set = ['the', 'a', 'an', 'i', 'he', 'she', 'they', 'to', 'of', 'it', 'from']sents_processed = [removeStopWords(stop_set,x) for x in sents_lower]

就此打住,转到标记化就可以了。然而,人们可以继续使用stemmingstemming的目标是去掉单词中的前缀和后缀,将单词转换成它的基本形式,e.g. studying->study, beautiful->beauty, cared->care,…在 NLTK 中,有两种流行的stemming技术,称为 porter 和 lanscaster。[参考:数据营

import nltk
def stem_with_porter(words):
    porter = nltk.PorterStemmer()
    new_words = [porter.stem(w) for w in words]
    return new_words

def stem_with_lancaster(words):
    porter = nltk.LancasterStemmer()
    new_words = [porter.stem(w) for w in words]
    return new_words ## Demonstrate ##    
str = "Please don't unbuckle your seat-belt while I am driving, he said"print("porter:", stem_with_porter(str.split()))

print("lancaster:", stem_with_lancaster(str.split()))

让我们试试我们的sents_processed看看它是否有意义。

porter = [stem_with_porter(x.split()) for x in sents_processed]porter = [" ".join(i) for i in porter]porter[0:10]

出现一些奇怪的变化,例如非常->真实,质量->质量,价值->价值,…

4.Term Document Inverse Document Frequency (TD/IDF)。这是在多个文档的上下文中,一个单词在一个文档中的相对重要性的度量。在我们这里,多重审查。

我们从 TD 部分开始——这只是文档中单词的归一化频率:

(word count in document) / (total words in document)

IDF 是所有文档中单词唯一性的加权。以下是 TD/IDF 的完整公式:

td_idf(t,d) = wc(t,d)/wc(d) / dc(t)/dc()

其中:
wc(t,d)=【t 项在文档 d
中的出现次数】— wc(d) =【文档 d】中的字数
dc(t)=【t 项在集合中至少出现 1 次的文档数】— dc() =【集合中的文档数】

现在,让我们创建一个单词包,并规范文本

from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformervectorizer = CountVectorizer(analyzer = "word", 
                             preprocessor = None, 
                             stop_words =  'english', 
                             max_features = 6000, ngram_range=(1,5))data_features = vectorizer.fit_transform(sents_processed)
tfidf_transformer = TfidfTransformer()
data_features_tfidf = tfidf_transformer.fit_transform(data_features)
data_mat = data_features_tfidf.toarray()

现在data_mat是我们的文档术语矩阵。输入已准备好投入模型。让我们创建训练集和测试集。在这里,我将数据分为 2500 个句子的训练集和 500 个句子的测试集(其中 250 个是正面的,250 个是负面的)。

np.random.seed(0)
test_index = np.append(np.random.choice((np.where(y==-1))[0], 250, replace=False), np.random.choice((np.where(y==1))[0], 250, replace=False))train_index = list(set(range(len(labels))) - set(test_index))train_data = data_mat[train_index,]
train_labels = y[train_index]test_data = data_mat[test_index,]
test_labels = y[test_index]

文本 Blob

  1. **TextBlob**:语言学研究者根据他们的专业领域给单词的情感贴上标签。单词的情感可以根据它在句子中的位置而变化。TextBlob模块允许我们利用这些标签。TextBlod找到它可以分配极性主观性的所有单词和短语,然后将它们全部平均
  2. 情感标签:语料库中的每个单词都根据极性和主观性进行标记(还有更多标签,但我们现在将忽略它们)。一个语料库的情感是这些的平均值。
  • 极性 :一个字有多正或多负。-1 是非常消极的。+1 很正。
  • 主观性 :一个词有多主观,或者说有多固执己见。0 是事实。+1 在很大程度上是一种观点。
from textblob import TextBlob#Create polarity function and subjectivity functionpol = lambda x: TextBlob(x).sentiment.polaritysub = lambda x: TextBlob(x).sentiment.subjectivitypol_list = [pol(x) for x in sents_processed]sub_list = [sub(x) for x in sents_processed]

这是一种基于规则的方法,决定了评论的情绪(极性和主观性)。

下一节将介绍各种算法。

逻辑回归

from sklearn.linear_model import SGDClassifier## Fit logistic classifier on training data
clf = SGDClassifier(loss="log", penalty="none")
clf.fit(train_data, train_labels)## Pull out the parameters (w,b) of the logistic regression model
w = clf.coef_[0,:]
b = clf.intercept_## Get predictions on training and test data
preds_train = clf.predict(train_data)
preds_test = clf.predict(test_data)## Compute errors
errs_train = np.sum((preds_train > 0.0) != (train_labels > 0.0))
errs_test = np.sum((preds_test > 0.0) != (test_labels > 0.0))print("Training error: ", float(errs_train)/len(train_labels))
print("Test error: ", float(errs_test)/len(test_labels))**Training error:  0.0116
Test error:  0.184**

影响力大的词

决定一个句子是否为肯定的,哪些词最重要?作为对此的第一近似,我们简单地取其系数在w中具有最大正值的单词。

同样,我们看那些在w中系数具有最大负值的单词,我们认为这些单词对负面预测有影响。

## Convert vocabulary into a list:
vocab = np.array([z[0] for z in sorted(vectorizer.vocabulary_.items(), key=lambda x:x[1])])## Get indices of sorting w
inds = np.argsort(w)## Words with large negative values
neg_inds = inds[0:50]
print("Highly negative words: ")
print([str(x) for x in list(vocab[neg_inds])])## Words with large positive values
pos_inds = inds[-49:-1]
print("Highly positive words: ")print([str(x) for x in list(vocab[pos_inds])])

创建字云

from wordcloud import WordCloud
wc = WordCloud(stopwords=stop_set, background_color="white", colormap="Dark2",
               max_font_size=150, random_state=42)#plt.rcParams['figure.figsize'] = [16, 6]wc.generate(" ".join(list(vocab[neg_inds])))plt.imshow(wc, interpolation="bilinear")
plt.axis("off")    
plt.show()

朴素贝叶斯

from sklearn.naive_bayes import MultinomialNB
nb_clf = MultinomialNB().fit(train_data, train_labels)nb_preds_test = nb_clf.predict(test_data)
nb_errs_test = np.sum((nb_preds_test > 0.0) != (test_labels > 0.0))
print("Test error: ", float(nb_errs_test)/len(test_labels))**Test error:  0.174**

我们来做一些预测案例。[1]表示正,而[-1]表示负

print(nb_clf.predict(vectorizer.transform(["**It's a sad movie but very good**"])))**[1]**print(nb_clf.predict(vectorizer.transform(["**Waste of my time**"])))**[-1]**print(nb_clf.predict(vectorizer.transform(["**It is not what like**"])))**[-1]**print(nb_clf.predict(vectorizer.transform(["**It is not what I m looking for**"])))**[1]**

最后一个测试用例有问题。这应该是负面评论,但模型预测是正面的。

SVM

from sklearn.linear_model import SGDClassifiersvm_clf = SGDClassifier(loss="hinge", penalty='l2')
svm_clf.fit(train_data, train_labels)svm_preds_test = svm_clf.predict(test_data)
svm_errs_test = np.sum((svm_preds_test > 0.0) != (test_labels > 0.0))print("Test error: ", float(svm_errs_test)/len(test_labels))**Test error:  0.2**

再次,让我们做一些预测

print(svm_clf.predict(vectorizer.transform(["**This is not what I like**"])))**[-1]**print(svm_clf.predict(vectorizer.transform(["**It is not what I am looking for**"])))**[-1]**print(svm_clf.predict(vectorizer.transform(["**I would not recommend this movie**"])))**[1]**

SVM 可以正确预测评论“这不是我要找的”。然而,它无法预测评论“我不推荐这部电影”。

LSTM 网络公司

关于 LSTM 网络的详细讨论可以在这里找到。

from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from keras.layers import SpatialDropout1D
from keras.layers.embeddings import Embedding
from keras.preprocessing import sequence
from keras.preprocessing.text import Tokenizer
from keras.callbacks import EarlyStoppingmax_review_length = 200tokenizer = Tokenizer(num_words=10000,  #max no. of unique words to keep
                      filters='!"#$%&()*+,-./:;<=>?@[\]^_`{|}~', 
                      lower=True #convert to lower case
                     )
tokenizer.fit_on_texts(sents_processed)

截断并填充输入序列,使它们长度相同

X = tokenizer.texts_to_sequences(sents_processed)
X = sequence.pad_sequences(X, maxlen= max_review_length)
print('Shape of data tensor:', X.shape)**Shape of data tensor: (3000, 200)**

回想一下,y 是 1 和-1 的向量。现在我把它改成一个有 2 列的矩阵,分别代表-1 和 1。

import pandas as pd
Y=pd.get_dummies(y).values
Y

np.random.seed(0)
test_inds = np.append(np.random.choice((np.where(y==-1))[0], 250, replace=False), np.random.choice((np.where(y==1))[0], 250, replace=False))
train_inds = list(set(range(len(labels))) - set(test_inds))train_data = X[train_inds,]
train_labels = Y[train_inds]test_data = X[test_inds,]
test_labels = Y[test_inds]

创建网络

EMBEDDING_DIM = 200model = Sequential()
model.add(Embedding(10000, EMBEDDING_DIM, input_length=X.shape[1]))
model.add(SpatialDropout1D(0.2))
model.add(LSTM(250, dropout=0.2,return_sequences=True))
model.add(LSTM(100, dropout=0.2, recurrent_dropout=0.2))
model.add(Dense(2, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
print(model.summary())

epochs = 2
batch_size = 40model.fit(train_data, train_labels, 
          epochs=epochs, 
          batch_size=batch_size,
          validation_split=0.1)

loss, acc = model.evaluate(test_data, test_labels, verbose=2,
                            batch_size=batch_size)print(f"loss: {loss}")
print(f"Validation accuracy: {acc}")

在迄今为止训练的所有模型中,LSTM 表现最好,即逻辑斯蒂、朴素贝叶斯和 SVM。现在让我们看看它如何预测一个测试用例

outcome_labels = ['Negative', 'Positive']new = ["**I would not recommend this movie**"]

seq = tokenizer.texts_to_sequences(new)
padded = sequence.pad_sequences(seq, maxlen=max_review_length)
pred = model.predict(padded)
print("Probability distribution: ", pred)
print("Is this a Positive or Negative review? ")
print(outcome_labels[np.argmax(pred)])

new = ["**It is not what i am looking for**"]

new = ["**This isn't what i am looking for**"]

在这种情况下,否定和肯定的概率差别不大。LSTM 模型认为这是积极的。

new = ["**I wouldn't recommend this movie**"]

这个评论也是如此。因此,这意味着我们的模型不能区分n'tnot。一个可能的解决方案是,在预处理步骤中,不是删除所有标点符号,而是将所有的n't简写改为not。这可以简单地用 Python 中的re模块来完成。您可以亲自查看一下,看看我们的模型预测是如何改进的。

将“不”改为“不”并再次运行模型后

就是这样!希望你们喜欢这篇文章,并从中有所收获。如果你有任何问题,请在下面的评论区写下来。谢谢你的阅读。祝您愉快,保重!!

照片由卢卡斯·克拉拉Unsplash 上拍摄

NLP:使用深度学习检测短信(文本)数据中的垃圾邮件

原文:https://towardsdatascience.com/nlp-spam-detection-in-sms-text-data-using-deep-learning-b8632db85cc8?source=collection_archive---------3-----------------------

TensorFlow2 中使用密集网络、LSTM 和双 LSTM 架构的文本分类

作者图片

介绍

如今,互联网和社交媒体已经成为获取信息最快捷、最简单的方式。在这个时代,评论、意见、反馈、信息和建议已经成为重要的信息来源。由于技术的进步,我们现在能够使用各种自然语言处理(NLP)技术从这些数据中提取有意义的信息。NLP 是人工智能(AI)的一个分支,它利用计算机和人类自然语言输出有价值的信息。NLP 通常用于文本分类任务,例如垃圾邮件检测和情感分析、文本生成、语言翻译和文档分类。

目的

本文的目的是了解我们如何使用 TensorFlow2 来构建垃圾短信检测模型。特别地,我们将建立一个二进制分类模型来检测一个文本消息是否是垃圾邮件。此外,我们将了解如何在 TensorFlow2 Keras API 中实现密集的长短期记忆(LSTM)和双向 LSTM(双 LSTM)深度学习模型。

数据

短信(文本)数据是从 UCI 数据集下载的。它包含 5,574 条手机短信。这些数据是为了手机垃圾邮件研究而收集的,已经被贴上了垃圾邮件或垃圾邮件的标签。

方法

我们将使用密集文本分类器,LSTM 和双 LSTM,并比较这些方法在性能方面,并选择一个最终的。

以下是我们在本文中涉及的部分:

  • 加载并浏览垃圾邮件数据
  • 准备列车测试数据
  • 使用上述三种方法训练垃圾邮件检测模型
  • 比较并选择最终型号
  • 使用最终训练的分类器对新消息进行分类

让我们开始吧,首先确定 TensrFlow 的版本。

import tensorflow as tf
print(tf.__version__)
2.2.0

导入所需包

将所有的导入放在代码的开头是一个很好的做法。

# import libraries for reading data, exploring and plotting
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from wordcloud import WordCloud, STOPWORDS, ImageColorGenerator
%matplotlib inline# library for train test split
from sklearn.model_selection import train_test_split# deep learning libraries for text pre-processing
import tensorflow as tf
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences# Modeling 
from tensorflow.keras.callbacks import EarlyStopping
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Embedding, GlobalAveragePooling1D, Dense, Dropout, LSTM, Bidirectional

加载并浏览垃圾邮件数据

数据可以从 UCI 数据集下载并保存在本地文件夹中。文本文件(和一个完整的 Jupyter 笔记本)也在我的 github 位置提供,因此可以使用下面的语法阅读。文本文件是一个制表符分隔的(\t)文件,因此,我们可以使用 pandas 来读取数据。我们还可以通过传递名称来提供列名,称之为标签和消息。

url = '[https://raw.githubusercontent.com/ShresthaSudip/SMS_Spam_Detection_DNN_LSTM_BiLSTM/master/SMSSpamCollection'](https://raw.githubusercontent.com/ShresthaSudip/SMS_Spam_Detection_DNN_LSTM_BiLSTM/master/SMSSpamCollection')
messages = pd.read_csv(url, sep ='\t',names=["label", "message"])
messages[:3] 

数据帧的前 3 行

让我们获得汇总统计数据并可视化数据。熊猫的 describe() 方法提供了一个汇总统计数据。例如,有 5,572 个标签和消息。有两个独特的标签标明“火腿”和“垃圾邮件”。我们还可以观察到,唯一消息(5,169)比总消息数(5,572)少,这表明有一些重复的消息。最上面的标签是“火腿”,数据中最上面的消息是“对不起,我稍后再打”。下面的重复箭头显示,有 403 条重复消息。

messages.describe()

汇总统计数据

duplicatedRow = messages[messages.duplicated()]
print(duplicatedRow[:5])

重复行

与 747 条垃圾消息相比,有 4,825 条 ham。这表示不平衡的数据,我们稍后会修复。最受欢迎的业余消息是“对不起,我稍后再打”,而最受欢迎的垃圾消息是“请打电话给我们的客户服务部……”,分别出现了 30 次和 4 次。

messages.groupby('label').describe().T

按标签(垃圾邮件)统计摘要

下面,我们通过创建一个 WordCloud 和一个条形图来进一步探索标签组的数据。首先,让我们为 ham 和 spam 消息创建一个单独的数据帧,并将其转换为 numpy 数组以生成 WordCloud。

# Get all the ham and spam emails
ham_msg = messages[messages.label =='ham']
spam_msg = messages[messages.label=='spam']# Create numpy list to visualize using wordcloud
ham_msg_text = " ".join(ham_msg.message.to_numpy().tolist())
spam_msg_text = " ".join(spam_msg.message.to_numpy().tolist())

为了使用 WordCloud() 进行可视化,我们提取了在垃圾邮件中最常见的单词,删除了无意义的停用词,如“the”、“a”、“is”等,并绘制了它。单词云将给定文本中最常用的单词可视化。

# wordcloud of ham messages
ham_msg_cloud = WordCloud(width =520, height =260, stopwords=STOPWORDS,max_font_size=50, background_color ="black", colormap='Blues').generate(ham_msg_text)
plt.figure(figsize=(16,10))
plt.imshow(ham_msg_cloud, interpolation='bilinear')
plt.axis('off') # turn off axis
plt.show()

下面的火腿消息 WordCloud 显示,“现在”、“工作”、“怎么样”、“还好”、“对不起”是火腿消息中最常出现的词。

业余消息的单词库

下面的垃圾短信词云显示,“免费”、“通话”、“短信”、“认领”、“回复”是垃圾短信中最常出现的词。

# wordcloud of spam messages
spam_msg_cloud = WordCloud(width =520, height =260, stopwords=STOPWORDS,max_font_size=50, background_color ="black", colormap='Blues').generate(spam_msg_text)
plt.figure(figsize=(16,10))
plt.imshow(spam_msg_cloud, interpolation='bilinear')
plt.axis('off') # turn off axis
plt.show()

垃圾短信的文字云

现在,让我们进一步探讨不平衡的数据。下面的条形图显示了班级的不平衡。最常见的垃圾邮件(85%)多于垃圾邮件(15%)。

# we can observe imbalance data here 
plt.figure(figsize=(8,6))
sns.countplot(messages.label)
# Percentage of spam messages
(len(spam_msg)/len(ham_msg))*100 # 15.48%

显示不平衡数据的条形图

有几种方法可以处理不平衡数据,例如

  • 使用适当的评估指标
  • 对训练集进行重采样:过采样/上采样或欠采样/下采样
  • 集成不同重采样数据集

然而,对于我们的问题,我们使用下采样只是为了说明它是如何实现的。当然,您可以尝试其他技术并比较结果。

缩减采样是从多数类中随机删除一些观察值的过程,以便多数类和少数类中的数字相匹配。下面,我们对 ham 消息进行了缩减采样(多数类)。现在每个班有 747 条消息。

# one way to fix it is to downsample the ham msg
ham_msg_df = ham_msg.sample(n = len(spam_msg), random_state = 44)
spam_msg_df = spam_msg
print(ham_msg_df.shape, spam_msg_df.shape)(747, 2) (747, 2)

下图显示了在考虑不平衡数据后,不同消息类型之间的类似分布。

# Create a dataframe with these ham and spam msg
msg_df = ham_msg_df.append(spam_msg_df).reset_index(drop=True)
plt.figure(figsize=(8,6))
sns.countplot(msg_df.label)
plt.title('Distribution of ham and spam email messages (after downsampling)')
plt.xlabel('Message types')

考虑不平衡数据后的条形图

此外,平均而言,ham 消息具有 73 个字的长度,而 spam 消息具有 138 个字。当我们稍后设置 maxlen 参数时,长度信息可能有用。

# Get length column for each text
msg_df['text_length'] = msg_df['message'].apply(len)#Calculate average length by label types
labels = msg_df.groupby('label').mean()
labels

表中显示了垃圾邮件的文本长度

准备培训/测试数据和预处理文本

在探索和解决不平衡数据之后,接下来让我们将文本标签转换为数字,并将数据分成训练集和测试集。此外,将标签转换为 numpy 数组,以适应深度学习模型。80%的数据用于训练,20%用于测试。

# Map ham label as 0 and spam as 1
msg_df['msg_type']= msg_df['label'].map({'ham': 0, 'spam': 1})
msg_label = msg_df['msg_type'].values# Split data into train and test
train_msg, test_msg, train_labels, test_labels = train_test_split(msg_df['message'], msg_label, test_size=0.2, random_state=434)

现在,让我们使用文本预处理,包括标记化、排序和填充。

下图描述了文本预处理的流程示例以及预期输出。

关于使用 TensorFlow2 预处理文本数据的基本理解,请参考我之前的文章关于预处理深度学习模型的数据。

标记化

由于深度学习模型不理解文本,让我们将文本转换为数字表示。为此,第一步是标记化。TensorFlow Keras 的 Tokenizer API 将句子拆分成单词,并将这些单词编码成整数。 Tokenizer() 执行所有必需的预处理,例如

  • 将符号化为单词或字符——这里我们在单词级别使用
  • num_words 表示唯一令牌的最大数量,因此我们可以过滤掉罕见的单词
  • 过滤掉标点符号
  • 将所有单词转换成小写
  • 将所有单词转换为整数索引

首先,定义用于预处理的超参数。我们稍后将描述这些超参数。

# Defining pre-processing hyperparameters
max_len = 50 
trunc_type = "post" 
padding_type = "post" 
oov_tok = "<OOV>" 
vocab_size = 500

下面,我们用 Tokenizer() 对单词进行分词。

tokenizer = Tokenizer(num_words = vocab_size, char_level=False, oov_token = oov_tok)
tokenizer.fit_on_texts(train_msg)

Tokenizer 对象中使用的超级参数是:num_words 和 oov_token,char_level。

  • num_words:指示在训练和测试数据中要加载多少个唯一的单词。出于我们的目的,我们选择了 500 个单词(vocab_size)
  • oov_token:当它被使用时,词汇外的 token 将被添加到用于建立模型的语料库中的单词索引中。这用于在 text_to_sequence 调用期间替换词汇表之外的单词(不在我们的语料库中的单词)(见下文)。
  • char_level:如果为“真”,那么每个字符都将被视为一个令牌。我们将其设置为“假”,因此每个将被视为一个令牌。

我们可以使用 tokenizer.word_index 得到 word_index。下面是 word_index 的快照。

# Get the word_index 
word_index = tokenizer.word_index
word_index

印刷单词索引的快照

# check how many words 
tot_words = len(word_index)
print('There are %s unique tokens in training data. ' % tot_words)There are 4169 unique tokens in training data.

排序和填充

在标记化之后,我们使用来自标记化器对象的 texts_to_sequences() 用数字序列表示每个句子。随后,我们使用 pad_sequences() 使得每个序列具有相同的长度。对训练和测试数据进行排序和填充。

# Sequencing and padding on training and testing 
training_sequences = tokenizer.texts_to_sequences(train_msg)
training_padded = pad_sequences (training_sequences, maxlen = max_len, padding = padding_type, truncating = trunc_type )testing_sequences = tokenizer.texts_to_sequences(test_msg)
testing_padded = pad_sequences(testing_sequences, maxlen = max_len,
padding = padding_type, truncating = trunc_type)
  • padding = 'pre '或' post(默认 pre)。通过使用 pre,我们在每个序列之前填充,通过使用 post,我们在每个序列之后填充。
  • maxlen =所有序列的最大长度。这里 max_len=50 因此,我们在一个句子中只使用 50 个单词。如果没有提供,默认情况下它将使用最长句子的最大长度。
  • truncating = 'pre '或' post '(默认为' pre ')。如果序列长度大于提供的 maxlen 值,则这些值将被截断为 maxlen。“pre”选项将在序列的开头截断,而“post”将在序列的结尾截断。
# Shape of train tensor
print('Shape of training tensor: ', training_padded.shape)
print('Shape of testing tensor: ', testing_padded.shape)Shape of training tensor:  (1195, 50)
Shape of testing tensor:  (299, 50)

在填充之前,第一个序列是 27 个字长,而第二个是 24 个字长。一旦应用了填充,两个序列的长度都是 50。

# Before padding
len(training_sequences[0]), len(training_sequences[1])Output:
(27, 24)# After padding
len(training_padded[0]), len(training_padded[1])Output:
(50, 50)

如下所示,填充序列的长度为 50。

print(training_padded[0])

第一句的填充序列

密集垃圾邮件检测模型

随着数据的加载和预处理,我们现在已经准备好使用神经网络架构对文本消息进行分类。让我们使用 LSTM 和双 LSTM 之后的密集架构来训练模型。

定义超参数:

vocab_size = 500 # As defined earlier
embeding_dim = 16
drop_value = 0.2 # dropout
n_dense = 24

下面是密集垃圾邮件检测模型的模型架构。

#Dense model architecture
model = Sequential()
model.add(Embedding(vocab_size, embeding_dim, input_length=max_len))
model.add(GlobalAveragePooling1D())
model.add(Dense(24, activation='relu'))
model.add(Dropout(drop_value))
model.add(Dense(1, activation='sigmoid'))
  • 顺序调用 Keras 顺序模型,其中各层按顺序添加
  • 第一层,即嵌入层,将每个单词映射到实数的 N 维向量。embeding _ dim 是这个向量的大小,在我们的例子中是 16。嵌入层表明具有相似意思的两个单词倾向于具有非常接近的向量。因为,嵌入层是我们模型网络中的第一个隐藏层,我们需要传递由 input_length (max_len =50)定义的输入层的形状。
  • 池层有助于减少模型中的参数数量,从而有助于避免过度拟合。我们在这里使用了平均池,并将层转换为一维。
  • 接下来,我们使用一个带有激活函数“relu”的密集层,然后是一个用于避免过拟合的下降层和一个带有 sigmoid 激活函数的最终输出层。由于只有两类(垃圾邮件或业余爱好者)要分类,我们只使用一个输出神经元。sigmoid 激活函数输出 0 到 1 之间的概率。

这里,我们使用一个相当浅的神经网络结构,然而,你可以通过增加更多的层使它更密集。

下面的 model.summary() 提供了层、形状和每个层中使用的参数数量。在嵌入层,8000 参数来自 500 个单词(vocab_size),每个单词有一个 16 维的单词向量空间(500×16 = 8000)嵌入层通过globalaveragepool1d并进入具有 16 形状的密集层(由于沿 16 嵌入维度的平均汇集)。我们为密集隐藏层选择了 24 个神经元。密集层中的 24 个神经元中的每一个都从来自 GlobalAveragePooling1D 层的 16 个值中的每一个获得输入,总共 384 (16 X 24)个权重和 24 个偏差(每 24 个神经元一个)。因此,总参数是 408。最后,输出层有 24 个权重(每个神经元一个)和一个偏置项,总共产生 25 个参数。

model.summary()

密集模型体系结构的模型概述

编译密集模型

让我们编译我们的密集垃圾邮件分类器模型。由于二进制输出,我们使用“二进制交叉熵”作为损失函数,“adam”作为优化器,其利用动量来避免局部最小值,而“准确性”作为模型性能的度量。

model.compile(loss='binary_crossentropy',optimizer='adam' ,metrics=['accuracy'])

训练和评估密集模型

接下来,让我们使用 model.fit() 参数来拟合我们的密集分类器。它使用填充的训练数据和训练标签来训练模型,并使用验证数据来进行验证。

  • epoch:学习算法在整个训练数据集中工作的次数。我们把它设置为 20。
  • 回调:回调用于传递早期停止参数。early stopping(monitor = ' val _ loss ',patience=2)用于定义我们希望监控验证损失,如果验证损失在两个时期后没有改善,则停止模型训练。它有助于避免过度适应问题,并在学习者开始过度适应之前指示何时停止训练。如下面的历史结果所示,在时段 23 之后的 2 个时段(时段 24: 0.12 和时段 25: 0.13)中,验证损失连续增加(即,没有改善),因此模型拟合已经在时段 26 处停止。
  • verbose =2:让打印每个时期的损失和准确性
# fitting a dense spam detector model
num_epochs = 30
early_stop = EarlyStopping(monitor='val_loss', patience=3)history = model.fit(training_padded, train_labels, epochs=num_epochs, validation_data=(testing_padded, test_labels),callbacks =[early_stop], verbose=2)

各时期的准确性和损失:密集分类器

模型得出,训练损失:0.07,训练准确率:97%,验证损失:0.13,验证准确率:94%。

# Model performance on test data 
model.evaluate(testing_padded, test_labels)Output: loss: 0.13 - accuracy: 0.94

我们可以通过按时期数绘制损失和准确性来进一步可视化历史结果。

# Read as a dataframe 
metrics = pd.DataFrame(history.history)
# Rename column
metrics.rename(columns = {'loss': 'Training_Loss', 'accuracy': 'Training_Accuracy', 'val_loss': 'Validation_Loss', 'val_accuracy': 'Validation_Accuracy'}, inplace = True)def plot_graphs1(var1, var2, string):
    metrics[[var1, var2]].plot()
    plt.title('Training and Validation ' + string)
    plt.xlabel ('Number of epochs')
    plt.ylabel(string)
    plt.legend([var1, var2])

下图显示了训练和验证数据集的历元数损失。正如预期的那样,随着历元数的增加,损耗在减少。在大约 5 个时期之后,验证损失高于训练损失,并且随着时期的增加,差异更加明显。

plot_graphs1('Training_Loss', 'Validation_Loss', 'loss')

跟踪各时期的损失:密集分类器

下面的精度图显示,精度随着时间的推移而增加。正如预期的那样,该模型在训练集中的表现优于验证集。然而,如果模型在训练数据上表现得非常好,那么它在测试数据中的表现就更差,那么它是过度拟合的指示。在我们的模型中,我们没有看到过度拟合的重大问题。此外,我们已经通过前面使用的丢弃层和回调解决了过拟合问题。

plot_graphs1('Training_Accuracy', 'Validation_Accuracy', 'accuracy')

跟踪不同时期的准确性:密集分类器

长短期记忆(LSTM)模型

下面,我们使用 LSTM 拟合垃圾邮件检测模型。下面是在 LSTM 使用的一些新的超级参数 n_lstmreturn_sequences

  • n_lstm = 20 是 lstm 单元内隐藏层中的节点数
  • return_sequences=True 确保 LSTM 单元格返回一段时间内展开的 LSTM 单元格的所有输出。如果不使用该参数,LSTM 单元将简单地提供上一步中 LSTM 单元的输出。

以下是用于 LSTM 模型的超参数。

#LSTM hyperparameters
n_lstm = 20
drop_lstm =0.2

让我们定义一下 LSTM 垃圾邮件检测模型架构。在 Keras,通过简单地添加 LSTM,我们可以适应 LSTM 模型。

#LSTM Spam detection architecture
model1 = Sequential()
model1.add(Embedding(vocab_size, embeding_dim, input_length=max_len))
model1.add(LSTM(n_lstm, dropout=drop_lstm, return_sequences=True))
model1.add(LSTM(n_lstm, dropout=drop_lstm, return_sequences=True))
model1.add(Dense(1, activation='sigmoid'))

编制 LSTM 模型

model1.compile(loss = 'binary_crossentropy', optimizer = 'adam', metrics=['accuracy'])

培训和评估 LSTM 模型

训练和评估与我们对上面的密集模型所做的相同。

num_epochs = 30
early_stop = EarlyStopping(monitor='val_loss', patience=2)
history = model1.fit(training_padded, train_labels, epochs=num_epochs, validation_data=(testing_padded, test_labels),callbacks =[early_stop], verbose=2)

来自 LSTM 的验证损失和准确度分别为 0.31%和 91%。

跨时代的准确性和损失:LSTM

# Create a dataframe
metrics = pd.DataFrame(history.history)# Rename column
metrics.rename(columns = {'loss': 'Training_Loss', 'accuracy': 'Training_Accuracy',
                         'val_loss': 'Validation_Loss', 'val_accuracy': 'Validation_Accuracy'}, inplace = True)
def plot_graphs1(var1, var2, string):
    metrics[[var1, var2]].plot()
    plt.title('LSTM Model: Training and Validation ' + string)
    plt.xlabel ('Number of epochs')
    plt.ylabel(string)
    plt.legend([var1, var2])plot_graphs1('Training_Loss', 'Validation_Loss', 'loss')
plot_graphs1('Training_Accuracy', 'Validation_Accuracy', 'accuracy')

记录跨时代的损失:LSTM

跟踪不同时代的准确性:LSTM

双向长短期记忆模型

与 LSTM 不同,双 LSTM 从文档中给定标记的前后学习模式。双 LSTM 在时间上向后和向前两个方向反向传播。因此,与 LSTM 相比,计算时间增加了。然而,在大多数情况下,双 LSTM 导致更好的准确性。

下面,我们可以看到双向 LSTM 架构,与 LSTM 的唯一区别是,我们使用双向包装器到 LSTM。

# Biderectional LSTM Spam detection architecture
model2 = Sequential()
model2.add(Embedding(vocab_size, embeding_dim, input_length=max_len))
model2.add(Bidirectional(LSTM(n_lstm, dropout=drop_lstm, return_sequences=True)))
model2.add(Dense(1, activation='sigmoid'))

编译 BiLSTM 模型

model2.compile(loss = 'binary_crossentropy', optimizer = 'adam', metrics=['accuracy'])

培训和评估 BiLSTM 模型

# Training
num_epochs = 30
early_stop = EarlyStopping(monitor='val_loss', patience=2)
history = model2.fit(training_padded, train_labels, epochs=num_epochs, 
                    validation_data=(testing_padded, test_labels),callbacks =[early_stop], verbose=2)

BiLSTM 的验证损失和准确度分别为 0.18 和 95%。

跨时代的准确性和损失:BiLSTM

# Create a dataframe
metrics = pd.DataFrame(history.history)# Rename column
metrics.rename(columns = {'loss': 'Training_Loss', 'accuracy': 'Training_Accuracy',
                         'val_loss': 'Validation_Loss', 'val_accuracy': 'Validation_Accuracy'}, inplace = True)
def plot_graphs1(var1, var2, string):
    metrics[[var1, var2]].plot()
    plt.title('BiLSTM Model: Training and Validation ' + string)
    plt.xlabel ('Number of epochs')
    plt.ylabel(string)
    plt.legend([var1, var2])# Plot
plot_graphs1('Training_Loss', 'Validation_Loss', 'loss')
plot_graphs1('Training_Accuracy', 'Validation_Accuracy', 'accuracy')

记录跨时代的损失

跟踪不同时期的准确性:BiLSTM

比较三种不同的型号,选择最后一种

所有密集、LSTM 和双 LSTM 模型在损失和准确性方面都是可比较的。这三个模型的验证损失分别为 0.13、0.31 和 0.18。验证准确率分别为 94%、91%和 95%。

其中,Dense 和 BiLSTM 的表现都优于 LSTM。基于损失、准确性和上面的图,我们选择密集架构作为用于分类垃圾邮件或 ham 的文本消息的最终模型。密集分类器具有简单的结构,并且在历元上的损失和精度比 BiLSTM 更稳定。

# Comparing three different models
print(f"Dense architecture loss and accuracy: {model.evaluate(testing_padded, test_labels)} " )
print(f"LSTM architecture loss and accuracy: {model1.evaluate(testing_padded, test_labels)} " )
print(f"Bi-LSTM architecture loss and accuracy: {model2.evaluate(testing_padded, test_labels)} " )

3 个模型的验证损失和准确性

预测新邮件中的垃圾邮件

场景 1:使用我们数据中的原始文本:

让我们评估我们的密集垃圾邮件检测模型如何根据原始数据中的文本预测/分类垃圾邮件或火腿。下面的第一条和第二条消息是垃圾邮件,而第三条是垃圾邮件。我们使用了之前在代码中创建的相同的标记器来将它们转换成序列。这确保了新单词将具有与训练集中相同的标记。标记化后,我们像前面一样使用填充,并提供与训练集中相同的维度。

# display long string 
pd.options.display.max_colwidth=100
messages[:3]

原始数据的前 3 个观察值

predict_msg = ["Go until jurong point, crazy.. Available only in bugis n great world la e buffet... Cine there got amore wat...",
          "Ok lar... Joking wif u oni...",
          "Free entry in 2 a wkly comp to win FA Cup final tkts 21st May 2005\. Text FA to 87121 to receive entry question(std txt rate)T&C's apply 08452810075over18's"]

predict_spam 函数定义如下。

# Defining prediction functiondef predict_spam(predict_msg):
    new_seq = tokenizer.texts_to_sequences(predict_msg)
    padded = pad_sequences(new_seq, maxlen =max_len,
                      padding = padding_type,
                      truncating=trunc_type)
    return (model.predict(padded))predict_spam(predict_msg)

如下所示,该模型正确地预测前两个句子不是垃圾邮件,而第三个句子是垃圾邮件。第三句有 99%的可能是垃圾邮件。

原始数据的预测结果

场景 2:使用新创建的文本消息,看看模型如何对它们进行分类。

下面,第一句更像是垃圾,而其余两句更像是火腿。

# The third one gives 0.99 indicating very high probabilty of spam
predict_msg = ["You are awarded a Nikon Digital Camera. Call now",
               "Call me",
          "What's up?"]
predict_spam(predict_msg)

我们的模型正确地将第一封邮件分类为垃圾邮件(94%的机会是垃圾邮件),其余的分类为垃圾邮件。

新短信的预测结果

摘要

我们使用来自 UCI 数据集的文本消息,拟合深度学习模型,如密集架构、LSTM 和双 LSTM,并比较这些模型的准确性和验证集损失。最后,我们选择密集架构深度学习模型来将文本消息分类为垃圾邮件或 ham,并使用它来分类新的文本消息。本文概述了使用 TensorFlow2 Keras 使用不同的架构深度学习模型来解决 NLP 问题。

下一步/改进

接下来,我们可以探索更多的采样方法,如上采样、SMOTE、整体采样。我们还可以尝试使用不同的超参数,增加样本量,以进一步改善模型。

鸣谢!

我要感谢乔恩·克罗恩的书《深度学习图解》,感谢懒惰程序员公司的优秀课程《Tensorflow 2.0:深度学习和人工智能》,感谢何塞·波尔蒂利亚在 Udemy 上的精彩课程《完整的 Tensorflow 2 和 Keras 深度学习训练营》。

谢谢大家!

感谢大家的阅读,并请随时留下意见/建议。

快乐学习!!!

自然语言处理文本预处理:步骤、工具和例子

原文:https://towardsdatascience.com/nlp-text-preprocessing-steps-tools-and-examples-94c91ce5d30?source=collection_archive---------23-----------------------

为自然语言处理任务预处理文本的标准逐步方法。

文本数据无处不在,从你每天的脸书或 Twitter 新闻,到教科书和客户反馈。数据是新的石油,文本是我们需要钻得更深的油井。在我们真正使用油之前,我们必须对它进行预处理,使它适合我们的机器。对于数据也是一样,我们必须清理和预处理数据以符合我们的目的。这篇文章将包括一些简单的方法来清理和预处理文本分析任务的文本数据。

我们将在新冠肺炎推特数据集上模拟这种方法。这种方法有三个主要组成部分:
首先,我们清理和过滤所有非英语的推文/文本,因为我们希望数据的一致性。
其次,我们为复杂的文本数据创建一个简化版本。
最后,我们对文本进行矢量化处理,并保存它们的嵌入内容以供将来分析。

如果您想查看代码:请随意查看第 1 部分第 2 部分第 3 部分嵌入这里的代码。你也可以在这里查看整个项目的 blogpost 和代码

(来源)

第 1 部分:清洁&过滤器文本

首先,为了简化文本,我们希望将文本标准化为只有英文字符。此功能将删除所有非英语字符。

def clean_non_english(txt):
    txt = re.sub(r'\W+', ' ', txt)
    txt = txt.lower()
    txt = txt.replace("[^a-zA-Z]", " ")
    word_tokens = word_tokenize(txt)
    filtered_word = [w for w in word_tokens if all(ord(c) < 128 for c in w)]
    filtered_word = [w + " " for w in filtered_word]
    return "".join(filtered_word)

我们甚至可以通过删除停用词做得更好。停用词是英语句子中出现的对意思没有多大贡献的常用词。我们将使用 nltk 包来过滤停用词。由于我们的主要任务是使用词云可视化推文的共同主题,这一步是必要的,以避免常见的词,如“the”、“a”等。
然而,如果你的任务需要完整的句子结构,比如下一个单词预测或语法检查,你可以跳过这一步。

import nltk
nltk.download('punkt') # one time execution
nltk.download('stopwords')
from nltk.corpus import stopwords
stop_words = set(stopwords.words('english'))def clean_text(english_txt):
    try:
       word_tokens = word_tokenize(english_txt)
       filtered_word = [w for w in word_tokens if not w in stop_words]
       filtered_word = [w + " " for w in filtered_word]
       return "".join(filtered_word)
    except:
       return np.nan

对于 tweets,在清理之前我们需要考虑一个特殊的特性:提及。您的数据可能有(或没有)这样的特殊特性,这是具体情况具体分析,而不是普遍要求。因此,在盲目清理和预处理之前,要充分了解您的数据!

def get_mention(txt):
    mention = []
    for i in txt.split(" "):
        if len(i) > 0 and i[0] == "@":
            mention.append(i)
            return "".join([mention[i] + ", " if i != len(mention) - 1 else mention[i] for i in range(len(mention))]

之前,我们清理非英语字符。现在,我们移除非英语文本(语义上)。Langdetect 是一个 python 包,允许检查文本的语言。它是 Google 的语言检测库从 Java 到 Python 的直接端口。

from langdetect import detect
def detect_lang(txt):
    try:
        return detect(txt)
    except:
        return np.nan

然后我们过滤掉所有非英语的列。

第一部分的所有代码都可以在这里找到。

第 2 部分:简化复杂的数据—位置?

对于数字数据,好的处理方法是缩放、标准化和规范化。这个资源有助于理解并将这些方法应用于您的数据。在这篇文章的范围内,我不会进一步讨论,因为其他资源已经做了很好的工作。

对于分类数据,有许多方法。两种名义上的方法是标签编码器(为每个标签分配不同的数字)和一种热编码(用 0 和 1 的向量表示)。关于这些分类值的更多细节可以在这里找到。这个资源非常丰富,比我提到的这两种编码类型更多。

本帖将介绍一些降低数据复杂度的方法,尤其是位置数据。在我的数据集中,有一个位置栏,有作者的地址。然而,我不能对这些原始数据进行太多的分析,因为它们太杂乱和复杂了(有城市、县、州、国家)。因此,我们可以对文本进行标准化,并将其简化到“国家”级别(如果您感兴趣,也可以是州)。处理位置数据的包是 geopy 。它可以识别正确的地址并将这些位置重新格式化为标准格式。然后,您可以选择保留您需要的任何信息。对我来说,国家已经够体面了。

from geopy.geocoders import Nominatim
geolocator = Nominatim(user_agent="twitter")def get_nation(txt):
    try:
        location = geolocator.geocode(txt)
        x = location.address.split(",")[-1]
        return x
    except:
        return np.nan

Python 有这么多包,太牛逼了。我相信你总能找到满足你特定需求的东西,就像我处理我杂乱的位置数据一样。祝你好运,简化这些杂乱的数据。

第二部分的代码可以在这里找到。

第 3 部分:矢量化和嵌入

文本矢量化是将文本转换成值的向量来表示它们的含义。早期,我们有一种热门的编码方法,它使用一个向量,这个向量的大小是我们的词汇量,在文本出现的地方取值 1,在其他地方取值 0。如今,我们有更先进的方法,如空间手套,甚至伯特嵌入。对于这个项目的范围,我将向您介绍 GloVe in python 和 Jupiter 笔记本。

首先,我们下载嵌入。你可以在这里手动下载或者直接在笔记本上下载。

!wget [http://nlp.stanford.edu/data/glove.6B.zip](http://nlp.stanford.edu/data/glove.6B.zip)
!unzip glove*.zip

然后,我们创建一个函数来矢量化每个数据点。这个句子是每个单词的意思表示。对于空句子,我们将其默认为零向量。

def vectorize(value, word_embeddings, dim = 100):
    sentences = value.to_list()
    sentence_vectors = []
    for i in sentences:
        if len(i) != 0:
            v = sum([word_embeddings.get(w, np.zeros((dim,))) for w in      i.split()])/(len(i.split())+0.001)
        else:
            v = np.zeros((dim,))
        sentence_vectors.append(v)
    sentence_vectors = np.array(sentence_vectors)
    return sentence_vectors

最后,我们对整个数据集进行矢量化,并将矢量化的 numpy 数组保存为一个文件,这样我们就不必在每次运行代码时都重复这个过程。矢量化版本将保存为 numpy 数组,格式为。npy 文件。Numpy 包便于存储和处理海量数组数据。

作为我个人的标准实践,我尝试在每个部分之后将所有数据保存为单独的文件,以便更灵活地评估数据和修改代码。

def vectorize_data(data = data, value = 'english_text', dim = 100):
    # Extract word vectors
    word_embeddings = {}
    f = open('glove.6B.{}d.txt'.format(str(dim)), encoding='utf-8')
    for line in f:
        values = line.split()
        word = values[0]
        coefs = np.asarray(values[1:], dtype='float32')
        word_embeddings[word] = coefs
    f.close() text_vec = vectorize(data[value], word_embeddings, dim)
    np.save("vectorized_{}.npy".format(str(dim)), text_vec)
    print("Done. Data:", text_vec.shape)
    return True

第三部分的代码在这里。

结论

数据预处理,特别是文本,可能是一个非常麻烦的过程。你的机器学习工程师工作流程的很大一部分将是这些清理和格式化数据(如果你的数据已经非常干净,那你是幸运的&所有数据工程师都为此做出了贡献)。

本帖所有的代码都很抽象,可以应用到很多数据项目中(只需要改成列名,应该都可以正常工作)。在笔记本中,我还添加了异常函数来处理失败情况,确保您的代码不会中途崩溃。我希望它对你的项目有所帮助,就像我对我的项目有所帮助一样。

你可以在这里查看项目博客

祝你的项目好运,如果有什么需要改变和改进的地方,请告诉我!谢谢,下一篇帖子再见!

参考资料:
黑尔,J. (2020 年 2 月 21 日)。使用 Scikit-Learn 进行扩展、标准化或规范化。检索自https://towards data science . com/scale-standard-or-normalize-with-scikit-learn-6 CCC 7d 176 a 02
KazAnova。(2017 年 9 月 13 日)。包含 160 万条推文的 Sentiment140 数据集。检索自https://www.kaggle.com/kazanova/sentiment140
普雷达,G. (2020 年 8 月 30 日)。COVID19 推文。检索自 https://www.kaggle.com/gpreda/covid19-tweets(2020 年 4 月 25 日)。关于分类变量编码的一切。检索自https://towardsdatascience . com/all-about-category-variable-encoding-305 f 3361 FD 02

抽象主题建模

原文:https://towardsdatascience.com/nlp-topic-modeling-to-identify-clusters-ca207244d04f?source=collection_archive---------37-----------------------

从长文本中引出主题

这是 4 部分文章的第 3 部分。到目前为止,我们一直在谈论:

  1. 预处理和清洗
  2. 文本摘要
  3. 使用潜在狄利克雷分配(LDA)的主题建模——我们在这里
  4. 聚类

在本文中,我们将使用长文本文档 的摘要版本来查找构成每个文档 的主题。我们在主题建模之前对文本进行总结,因为在一些文档中可能会有额外的细节。然而,其他人可能只是抓住了要点。

等等,但是为什么要模型题目呢?这到底是什么意思?

主题建模用于发现文档集合中出现的抽象“主题”。它是一个常用的文本挖掘工具,用于发现文本中隐藏的语义结构。

作者图片:原始文本文档

我们希望保持简洁明了的信息,以便识别每个长文档的主题。所以,我们把这段文字总结成这样:

图片 bu 作者:总结文字

主题建模

我们将不会做任何进一步的预处理,因为我们已经基本上预处理时,清理文本最初,只有短语在总结中。

和前面的章节一样,我们首先证明了总结是否可行。让我们看看集群是否可行。

from numpy import dot
from numpy.linalg import normexam = nlp.parser.vocab[u"exam"]# cosine similarity
cosine = lambda v1, v2: dot(v1, v2) / (norm(v1) * norm(v2))allWords = list({w for w in nlp.parser.vocab if w.has_vector and w.orth_.islower() and w.lower_ != "exam"})# sort by similarity to Exam
allWords.sort(key=lambda w: cosine(w.vector, exam.vector))
allWords.reverse()
print("Top 5 most similar words to exam:")
for word in allWords[:5]:   
    print(word.orth_)

哇!!!那么这是否意味着我们甚至可以找到文档之间的相似之处呢?是啊!!因此,我们有可能找到这些不同文档的集群!!!!

寻找主题的最佳数量

潜在狄利克雷分配(LDA) 是文本文档的贝叶斯概率模型。它从未被观察的组中确定观察集。因此,解释了数据的相似部分。

观察是来自文档的单词。每个文档都是少量主题的组合。每个单词的出现都归因于文档的一个主题。

主题建模

你们中有多少人真正理解了上面部分发生的事情?如果你不知道,请告诉我,我很乐意再写一篇关于这本字典解释的文章!

我们能想象一下上面的话题吗?是的,我们可以。

作者图片:点击每个主题,了解它是如何由术语组成的

这表明话题是根据谈论的疾病/状况来分配的。太好了,让我们看看成绩单中的话题倾向。

当 LDA 找到上面的主题时,它本质上是试图在组中找到单词的出现。这确实意味着我们有一个与每个主题的每个图表相关联的概率分数。但是,我们并不是对它们都有信心。所以我们只提取 90%以上倾向的。

如果仔细观察,并不是所有的图表都有主题。这是因为该算法不符合我们的话题倾向性截止标准。

作者提供的图片:带有最终主题和主题倾向的图表注释(范围为 0–1)

让我们想象一下我们已经确定的图表的主题/集群和频率

作者图片:话题频率

结论

这里可以看到 topic_21 的图表最多。紧随其后的是 topic_15topic_14

接下来,我们对这些文本文档进行聚类!

如果你想自己尝试整个代码或跟随,请到我在 GitHub 上发布的 jupyter 笔记本:https://GitHub . com/gaurikatyagi/Natural-Language-Processing/blob/master/introduction % 20 to % 20 NLP-Clustering % 20 text . ipynb

2020 年的 NLP 趋势和使用案例

原文:https://towardsdatascience.com/nlp-trends-and-use-cases-in-2020-dc8fb84a6e58?source=collection_archive---------9-----------------------

业界最喜欢的 NLP 技术、最大的趋势、挑战和使用案例

由两张 Adobe Stock 照片创建的图像

自然语言处理(NLP)是人工智能中最令人兴奋的领域之一,它使计算机能够理解人类语言。NLP 技术在不断发展,越来越多的组织开始使用有前途的应用程序来解决各种各样的问题。

公司使用 NLP 到底是为了什么?在实际环境中,什么是令人兴奋的自然语言处理技术?应用它们时有什么挑战?

我们与不同行业中应用 NLP 的思想领袖谈论了他们最喜欢的 NLP 技术、最大的趋势以及 NLP 在 2020 年的机遇和挑战。他们是这样说的:

你认为最近你的组织在应用 NLP 方面最大的变化是什么?

“在数据不断变化的情况下训练越来越大的模型。我们推出的功能越来越复杂,这意味着他们通常需要更大的 ML 模型来支持他们,这反过来又会影响基础设施和培训时间。同时,特别是使用 COVID,我们需要为用户提供的信息会不断变化,这意味着我们需要确保我们的模型不断更新。幸运的是,我们已经能够调整我们的开发和数据维护流程,以适应频繁但更长的培训时间,但要跟上这一过程是一个相当大的挑战。”—Bespoke 首席技术官 Christine Gerpheide

“AI 和 NLP 的准确性主要基于大量和多样化的训练数据,这是许多组织所不具备的。合成训练数据只能到此为止。因此,让我们的客户能够收集丰富多样的培训数据已成为我们的首要任务。

更具体地说,将道德第一的方法引入培训数据收集,帮助我们的客户进一步提高了在聊天、电子邮件、网络和移动设备上个性化客户体验的能力。”— 彼得·斯塔德林格,Freshworks CRM 产品负责人

在未来 1-3 年内,您认为哪个 NLP 使用案例是让您的行业受益的最大机会?

“要创建高质量的生产就绪型 NLP 应用程序,缺乏足够的格式化/标记数据以及经济实惠的计算/GPU 机器仍然是该行业大多数人面临的最大挑战。随着迁移学习/预训练模型的出现,更多由 NLP 技术驱动的应用将会更快地进入市场。我们将在未来 1 到 3 年内开始看到新的和改进的数字和虚拟助理(下一代现代机器人和聊天机器人)进入市场。在不久的将来,在房地产、法律和教育等领域使用 NLP 的垂直目标企业将开始激增。”—Unify Consulting/加州大学伯克利分校数据科学总监 Vamsi sistra

“医疗保健或任何其他特定领域面临的挑战是文档中使用的独特术语和有限的数据集,以便能够训练现有的模型。目前,该行业正在收集和预处理原始数据,我认为在未来 1-3 年内,我们将看到许多新的名称实体识别模型的实现,以及分类和总结。”— 约翰·斯诺实验室的高级数据科学家艾莉娜·佩图霍娃

“我们为旅游部门和紧急通信制作了一个聊天机器人通信平台。现在,许多交流仍然是通过电话、联络中心或纸张进行的。这些媒体对许多人来说是一种痛苦,尤其是那些使用其他语言的人。我认为 NLP 在这些领域推动社会进步的最大机会之一是充分提高对自然语言的理解,以便我们可以几乎完全依赖自动化的即时客户服务来提供旅行和紧急咨询。这个想法本身并不新鲜,但研究现在已经存在,所以在产品公司内部,我们需要保持全速前进,利用研究来实现这一理想。”Bespoke 首席技术官 Christine Gerpheide

“我对 NLP 如何用‘结构化’文本来提高自动化非常感兴趣,比如编程语言和专业通信(例如,我在想飞行员和空中交通管制员是如何通信的。)通过对这些语言的分析,我们能理解什么?我们能否自动检测错误,如软件错误或空中交通管制中的沟通失误?”—Anyscale 的开发者关系主管迪恩·万普勒

“虽然聊天机器人多年来一直处于上升趋势,并得到了广泛的采用,但它们在本质上仍然非常基础,不容易增强或扩展,更不用说自我训练了。不可否认的是,像 GPT 3 这样的突破性技术将推动下一代聊天机器人——对话聊天机器人的进步和采用。这些人将能够不断自我提高,并处理更复杂的对话。

在商业软件中,这将使品牌能够显著改善客户体验,同时保持甚至降低成本。我和我的团队处于开发和普及这种聊天机器人的最前沿。——peterstadlinger,Freshworks 的 Freshworks CRM 产品主管

“像伯特、GPT 或其他衍生工具这样的大型语言模型将成为主流,并将全面惠及所有行业。它们捕捉大量语言结构的能力可以作为许多应用程序的基础。这些语言模型的迁移学习或微调将导致许多形式的监督学习 NLP 任务的性能飞跃。”—Adarga 的机器学习工程师 Sebastian Reitz

你个人对哪种新的 NLP 技术和想法最感兴趣?

“自然语言处理在医疗保健领域带来了一些令人兴奋的机会。在医疗保健中实现自然语言处理是未来的趋势,因为这些技术在很大程度上改善了医疗服务。

对我个人来说,最令人兴奋的想法之一是它在临床决策中的规则,因为自然语言处理和医疗保健中的机器学习帮助医生为他们的患者做出更好的医疗决策,因为 NLP 用于帮助他们检查症状、诊断、药物、过敏、程序和副作用以及正在治疗的病例的每一个可能的原因。

另一个引人入胜的应用是计算机辅助编码,因为 NLP 承诺提高编码器的准确性,因为计算机辅助编码提取关于所有症状、诊断、程序和药物的信息,以捕获每个可能的代码并最大化索赔,因此这两种用途对患者和整个医疗保健系统都非常有益。约翰·斯诺实验室的临床数据研究员玛丽安·麦

“基于变形金刚的语言模型,如伯特或 GPT,是自然语言处理的突破性进展。然而,它们非常大,包含数百万个参数。因此,这些模型越大,快速和大规模的推理就越慢或成本越高。较小的模型版本如 ALBERT 或 DistilBERT 是应对这种情况的好方法。它们仍然可以捕获大量的结构和语义知识,同时允许更快速的微调和推理。”Adarga 的机器学习工程师 Sebastian Reitz

“可控一代。NLP 和 ML 在生成自然对话方面最近有了实质性的进展。但是,在旅行尤其是紧急通信中,往往会有特定的内容需要我们以某种语气回复或回复。因此,我们面临的最大技术挑战之一是将策划的对话内容与生成的内容相融合,前者质量高,但制作起来需要大量劳动力,后者是自动生成的,但不可预测。因此,我对最近的进展和可控生成的潜力感到非常兴奋,它可以帮助我们实现生成的、听起来自然的内容,同时保留我们需要的细节或细微差别。”Bespoke 首席技术官 Christine Gerpheide

“将我们在卷积神经网络中用于图像分类的方法应用于文本处理的想法让我非常兴奋,例如 CNN 层和注意力机制。现在我感兴趣的焦点是图形神经网络在自然语言处理中的应用。”—约翰·斯诺实验室的高级数据科学家 Alina Petukhova

你认为在你的行业中成功应用 NLP 的最大挑战是什么?

“如果我必须选择一个:在 R&D 和组织的其他部分之间建立桥梁,以确保产品公司有效地利用研究。这些天有很多令人惊讶的 NLP 研究,对这种职业道路的兴趣已经飙升。但是现在我们需要确保我们知道如何将 NLP 用例的范围扩大到那些将使真正的客户受益的用例。最直接的例子是确保我们不会过度工程化简单的事情,并且我们的目标用例具有适合 NLP 或 ML 的正确的安全性、隐私性和可再现性需求。

在我看来,更致命的是在选择研究领域时没有考虑过程。例如,你的 R&D 团队可能开发了一个杀手级的新模型,但是如果它不能用当前的公司流程来维护,那么在它有用之前必须解决这个问题。更新组织范围内的流程不是一件容易的事情,过去我已经看到它扼杀了有前途的研究项目。”Bespoke 首席技术官 Christine Gerpheide

“许多监督学习任务明显缺乏训练数据,尤其是在国防和安全行业。该行业对训练数据的高特异性和可靠性的需求加剧了这种情况。因此,训练和测试数据的标记需要由主题专家来完成——就像在许多 NLP 任务中一样。这使得获取数据更加困难,成本也更高。”Adarga 的机器学习工程师 Sebastian Reitz

“在商业软件中,NLP 中有许多“小数据”问题,只有通过使企业能够从其员工和客户那里收集更精细和相关的培训数据,才能解决这些问题——通过用户界面无缝收集。用户界面显然已经成为商业软件中人工智能和自然语言处理的新战场。”— Peter Stadlinger,Freshworks 的 Freshworks CRM 产品主管

“在过去的两年中,NLP 的突破主要是由类似 BERT 的架构(即变压器)推动的。然而,与经典的预训练嵌入相比,这些方法在预训练、下游任务训练和推理期间需要大量的计算资源(存储器、时间)。此外,我最担心的是,研究人员正在远离 NLP 的基本原理,同时试图用另一个 BERT 来击败最新的 BERT 基准。我在面向客户的实际工作项目中的亲身经历告诉我,变形金刚并不是一根能够解决所有问题的魔杖。有时,即使简单的计数矢量化也比复杂的 BERT 方法做得更好。

另一个问题是,只有少数研究人员对变压器有足够的了解,而且由于高级别的易于使用的包和包装,在行业中工作的人使用这些工具时并不太担心其内部机制。如果不了解它是如何工作的,以及在引擎盖下发生了什么,这些块盒模型通常无法解决来自特定领域的真实世界的情况,在这些领域中,带有一点特征工程的更简单的模型会用更少的努力做得更好,并且从长远来看易于维护和修改。”— 约翰·斯诺实验室首席数据科学家兼 ML 工程师维塞尔·科贾曼

“管理所有工件,包括数据和模型,尤其是满足受控生产部署的需求,是一项挑战。做特别的实验是一回事,做精心控制的模型开发和生产部署是另一回事,然后监控他们做得如何。您需要完整的生命周期管理。”Anyscale 的开发者关系主管迪安·万普勒

你喜欢这本书吗?你想深入实际的 NLP 应用和趋势吗?加入由约翰·斯诺实验室提交的# NLP 会议的思想领袖们,会议将于 10 月 6 日至 9 日举行。该活动将包括 30 多场独特的会议和高级认证培训研讨会。

沃森和 GPT 的 NLP 视频摘要

原文:https://towardsdatascience.com/nlp-video-summarization-with-watson-and-gpt-4d4db219b599?source=collection_archive---------49-----------------------

Siri,请观看我长达 1 小时的大学讲座视频,并为我做一个总结

阿玛多·洛雷罗在 Unsplash 上的照片

在这个项目中,我探索了 GPT2(它有大约 10 亿个参数)的能力,并且只能想象最近的 GPT3(它有 1750 亿个参数)的能力!,可以写从软件代码到艺术诗。在这个项目中,我使用了 Silvia Salini 教授(米兰大学数据科学负责人)的大学讲座-统计学习入门课程,并让 AI (IBM WATSON)观看了整个讲座并为我写下它,然后我训练了 GPT 2 模型,因此它可以将沃森写的 500 行文本总结为 10 行。

  • 我使用 IBM Watson 是因为它可以让你免费使用 500 分钟的语音到文本,而不需要输入任何信用卡信息,不像 Google Cloud 和 Azure。
  • 在 GPT2 模型中,我保持了低概率和高词汇使用率,因此 GPT2 不会从自身制造任何新信息,从而使讲座摘要完全错误
  • 我只通过一次讲座来训练模型,从而创建了一个原型,但是为了更好地学习模型和词汇,您可以尝试特定主题的多次讲座。

1 将讲座转换成音频文件

2 让沃森观看讲座并学习

IBM Watson 基于文件持续时间和大小对免费用户的语音转文本文件有限制,所以我把 1 小时的演讲音频文件分成 6 个不同的音频文件。

Watson API 凭证可以从 cloud.ibm.com 的演讲文本资源中获得

让沃森听完我制作的所有 6 段音频,并将其写入文本,
我选择了第一个对准确性最有信心的选项。

将结果写入文本文件,并将所有音频的结果合并到一个名为 lecture.txt 的文本文件中

3 GPT 2 模型调优

GPT 2 是一个因果文本生成,来自开放人工智能的预训练模型,用于预测。

GPT-2 生成合成文本样本,以响应用任意输入启动的模型。这个模型就像变色龙一样——它适应条件文本的风格和内容。这使得用户可以根据他们选择的主题生成真实且连贯的续篇—https://openai.com/blog/better-language-models/

4 讲座摘要生成

结果

虽然 GPT2 模型的能力令人印象深刻,但我们仍然不能依赖 GPT2 的确凿事实,尽管我发现它更准确,更省时,例如,当你在 NLP 上投资的资源较少时,像 GPT2 或罗伯塔这样的预训练模型显然会比一个人做单词嵌入和训练一周的 NLP 模型工作得更好,所以,GPT 2 是一个不错的开始,或者是引入像聊天机器人这样的实验项目, 或者会说话的网站,但是对于更专业的使用,好的资源需要根据自己的需要花在定制的 NLP 模型上。

关于完整的 jupyter 笔记本和代码,你可以在 github.com——https://github . com/Alexa Mann/NLP-Video-summarying-with-Watson-and-GPT上查看我的知识库

带 CNN 的 NLP

原文:https://towardsdatascience.com/nlp-with-cnns-a6aa743bdc1e?source=collection_archive---------8-----------------------

一步一步的解释,以及该架构的 Keras 实现。

https://en.wikipedia.org/wiki/Convolutional_neural_network

卷积神经网络(CNN)是图像处理和图像识别中最广泛使用的深度学习架构。鉴于他们在视觉领域的至高无上,尝试在机器学习的不同领域实现是很自然的。在本文中,我将尝试从自然语言处理的角度解释有关 CNN 的重要术语,还将提供一个简短的 Keras 实现和代码解释。

滑动或卷积预定数据窗口的概念是 CNN 如此命名背后的核心思想。这个概念的一个例子如下。

作者图片

这里首先要注意的是将每个单词(记号)表示为三维单词向量的方法。然后,一个 3×3 的权重矩阵在句子中水平滑动一步(也称为步幅),一次捕获三个单词。这个权重矩阵被称为过滤器;每个滤波器也由一个激活函数组成,类似于前馈神经网络中使用的那些。由于一些数学性质,激活函数 ReLU(校正线性单元)主要用于细胞神经网络和深度神经网络。回到图像分类,这些滤波器背后的一般直觉是,每个滤波器可以检测图像的不同特征,滤波器越深,就越有可能捕捉到更复杂的细节,例如,Convnet 中的第一批滤波器将检测边缘和线条等简单特征,但最后面的特征可能能够检测某些动物类型。所有这些都是在没有对任何过滤器进行硬编码的情况下完成的。反向传播将确保从数据中学习这些滤波器的权重。
下一个重要步骤是计算输出(卷积特征)。例如,下面我们将考虑一个 55 的图像和一个 33 的过滤器(在处理 CNN 时,您将主要使用正方形矩阵)。当每个过滤器在数据窗口上滑动一个步长时,通过对元素乘法求和来计算输出图层,每个像素乘以其在过滤器中的相应权重。以下示例说明了如何计算输出图层中的第一个像元;图像中的红色数字代表过滤器中的权重。

作者图片

计算如下:(1∫2)+(1∫1)+(1∫0)+(0∫1)+(2∫0)+(0∫1)+(0∫0)+(2∫1)+(0∫4)= 5

具有激活功能的 python 代码应该是:

z0 = max(sum(x * w),0)

在 2D 滤波器的情况下,可以使用以下公式计算输出层的大小:

(N-F)/S +1

N =图像的大小,F =滤波器的大小,S =步幅(在我们的例子中为 1)

当应用于文本时,您将使用在一维窗口中水平滑动 3 步的过滤器:

作者图片

填充

最后两个示例产生的输出大小小于输入的大小。也不难想象过滤器不完全适合给定数量幻灯片的矩阵的情况。为了应对这些复杂情况,可以通过两种方式使用衬垫:

  1. 用零向量填充外部边缘(零填充)
  2. 忽略不适合过滤器的矩阵部分(有效填充)

作者图片

统筹

池化相当于 CNN 中的降维。中心思想是,我们必须将输出层划分为子部分,并计算最能代表输出的值。之所以如此有效,是因为它有助于算法学习数据的高阶表示,同时减少参数的数量。联营的类型:

  1. 总和池
  2. 最大池化
  3. 平均池

以下是最大池的一个示例:

作者图片

全连接层

末端的全连接层接收来自先前池化和卷积层的输入,然后执行分类任务。在我们的例子中,我们将把 300 个单词的表征窗口分类为 1-积极情绪。0-负面情绪。全连接层中的最后一个神经元将 250 个神经元的加权平均值作为 sigmoid 函数(返回(0,1)之间的值)

Keras 实施

在这一节中,我们将尽量保持代码对于 NLP 用例的通用性。为了简单起见,我们将不深入数据预处理的细节,但是一般的过程是对数据进行标记化和矢量化。在我们的示例中,使用了 word2vec 嵌入,每个标记表示为一个 300 维的单词向量。我们的数据也被填充,每个句子包含 400 个标记,长句在 400 个标记后被删除,而短句用零填充。每个句子的最终尺寸是 300*400。然后我们把数据分成 x_train 和 x _ test 我们不会在这个项目中使用验证数据集。现在我们已经准备好数据,我们可以定义一些超参数。

##hyper parameters
batch_size = 32
embedding_dims = 300 #Length of the token vectors
filters = 250 #number of filters in your Convnet
kernel_size = 3 # a window size of 3 tokens
hidden_dims = 250 #number of neurons at the normal feedforward NN
epochs = 2

现在我们可以开始使用 Keras 库构建模型了。

model = Sequential()
model.add(Conv1D(filters,kernel_size,padding = 'valid' , activation = 'relu',strides = 1 , input_shape = (maxlen,embedding_dims)))

这里我们知道填充是有效的,这意味着我们不会保持输入的大小,得到的卷积矩阵的大小将是 100*1。在两个窗口中取最大值的最大池层。

model.add(GlobalMaxPooling1D())
#GlobalMaxPooling1D(n) default = 2.

然后,我们以 0.2 的丢失率添加完全连接的层(我们用它来应对过度拟合)。最后,输出神经元将基于 sigmoid 激活函数触发。Keras 会把低于 0.5 的归为 0,高于 0.5 的归为 1

model.add(Dense(hidden_dims))
model.add(Dropout(0.2))
model.add(Activation('relu'))
model.add(Dense(1))
model.add(Activation('sigmoid'))

最后一步是编译和拟合模型。

model.compile(loss = 'binary_crossentropy',optimizer = 'adam', metrics = ['accuracy'])
model.fit(x_train,y_train,batch_size = batch_size,epochs = epochs , validation_data = (x_test,y_test))

现在你可以坐下来看你的模型训练了。我们能够使用斯坦福大学 60%的训练数据达到 90%的准确率。你可以在本书的第 7 章找到更多细节:自然语言处理在行动。

摘要

  1. 在自然语言处理中,细胞神经网络可以用于不同的分类任务。
  2. 卷积是在更大的输入数据上滑动的窗口,重点是输入矩阵的子集。
  3. 在正确的维度上获取数据对于任何学习算法都是极其重要的。

使用朴素贝叶斯似然的特征选择的文本分类

原文:https://towardsdatascience.com/nlp-with-naive-bayes-feature-selection-in-python-15c4d327aad5?source=collection_archive---------34-----------------------

使用 Python 和一个小型说明性数据集的教程

在本文中,我将讨论如何使用朴素贝叶斯似然法来确定重要的特征,即 P(feature | class)。

假设我们有一个文本分类任务,作为第一步,我们将把单词标记化和词条化成特征。接下来的问题是,在分类任务中,哪些特征具有最强的预测能力。

为了简单起见,我们将考虑这个人工玩具天气数据集,其中的特征包括九个与天气相关的英语术语,因变量使用一些未指定的标准来指示天气是否“适合”。

因为这只是一个说明性的研究,所以我不想分成训练集和测试集。对全部特征集运行朴素贝叶斯分类会得到以下结果:

接下来,计算要素可能性 p(要素|类)得出:

在这里,我按照两个类之间可能性的绝对差异进行排序。你可以看到,多风的特征最能说明问题:在不适宜的天气(0.27)发生的频率是适宜天气(0.09)的三倍。无风温和特征具有高度预测性,仅在合适的天气中被提及。而特征多云根本没有预测能力,在合适和不合适的天气中同样可能发生。

接下来,我将重新运行仅具有前三个特征的朴素贝叶斯分类:多风平静 & 温和:

你可以看到准确率提高了 11 个百分点。

另请注意,重要的是,由于我们将特征集从九个减少到三个,朴素贝叶斯分类器使用的特征可能性也发生了变化:

实际值与预测值的比较:

总之,基于条件似然概率区分能力的特征选择可以提高查准率和查全率。

当然,数据集非常简单,结果可能会有所不同。在我的下一篇博文中,我将尝试将这种方法应用于更大的 tweets 语料库。

Python 代码

我现在将强调实现的一些特性。完整的 Python 代码在这里:https://github . com/benlaird/tweet _ 情操/blob/master/feature _ selection . py

函数compute _ relative _ freq _ df使用相对频率计算可能性:

内置 Python 函数 SelectKBest 调用的可调用函数:

我使用的管道:

#原色

原文:https://towardsdatascience.com/nlprimaries-1a97c61b223c?source=collection_archive---------90-----------------------

使用自然语言处理分析提及 2020 年民主党总统候选人的推文

自由股Unsplash 上的照片

*** 该分析在二月中旬进行

虽然今年早些时候民主党初选激烈激烈,但我和我的合作伙伴 Julia 认为,在我们的数据科学训练营期间,对政治推特进行自然语言处理(NLP)项目是一个好主意。由于 Twitter 是一个非常受欢迎的新闻和人们分享观点的论坛,我们想看看我们是否可以根据 Twitter 的活动发现关于这场比赛将如何进行的任何见解。

我们是这样做的:

数据

为了获得推文,我们使用了一个名为 Twint 的高级 Twitter 抓取工具,它允许您在不使用 Twitter API 的情况下抓取推文。为了避免明显的偏见,我们专注于提到候选人的推文,而不是候选人自己写的推文

  1. 每条推特只包含一个候选人的名字和/或推特账号
  2. 使用来自验证过的账户的推文,只使用来限制推文的数量,因为推文太多了
  3. 从推文中移除了链接图片,并使用 语言检测 移除了非英语

情感分析

为了运行情感分析——从文本中提取感觉/情感——我们使用了 VADER 情感分析 (价感知词典和情感推理机)。正如其文档所述,VADER 是“一个词汇和基于规则的情绪分析工具,专门适应社交媒体中表达的情绪。”

  1. 获得每位候选人推文的正面、负面、中性和复合得分:
# Create sentiment analysis functions analyzer = SentimentIntensityAnalyzer()def positive_sentiment(row):
    scores = analyzer.polarity_scores(row['tweet'])
    positive_sentiment = scores['pos']
    return positive_sentimentdef neutral_sentiment(row):
    scores = analyzer.polarity_scores(row['tweet'])
    neutral_sentiment = scores['neu']
    return neutral_sentimentdef negative_sentiment(row):
    scores = analyzer.polarity_scores(row['tweet'])
    negative_sentiment = scores['neg']
    return negative_sentimentdef compound_sentiment(row):
    scores = analyzer.polarity_scores(row['tweet'])
    compound_sentiment = scores['compound']
    return compound_sentiment

2.获得每个候选人在每个类别中的平均极性得分

3.根据哪个分数更高,将每条推文标记为正面或负面

4.为每位候选人创建了一个包含正面和负面推文平均数量的字典,用于可视化:

(将特朗普总统纳入分析进行比较)

我们看到,总体而言,大多数关于每位候选人的推文都被认为是“积极的”,围绕更具争议性的候选人的“消极”情绪有所上升。

主观性分析

对于我们的主观性分析——提取个人意见/观点/信念——我们求助于 TextBlob ,这是一个用于处理文本数据的 Python 库。“TextBlob”提供了一个一致的 API,用于处理常见的自然语言。

  1. 获得每条推文的情感
  2. 使用 正则表达式 捕获浮点值,然后将字符串转换为浮点值

主观性是在[0.0,1.0]范围内的浮动,其中 0.0 非常客观,1.0 非常主观

正如我们所看到的,大多数关于伯尼·桑德斯的推文似乎都非常客观,而其余的主观性得分呈正态分布。

TF–IDF

TF–IDF(词频–逆文档频率),在这种情况下,反映了一个词在整个推文中对一条推文有多重要。“TF–IDF 值随着一个词在[Tweet]中出现的次数成比例增加,并被包含该词的[Tweet 集合]中的[Tweet]数量抵消。”对于我们的 TF–IDF 分析,我们使用 Scikit-Learn 的 特征提取 方法。

  1. 符号化 所有的 Tweets 使用 NLTK 函数,并将所有的符号小写
  2. 删除了 NLTK 的 停用词 列表中的词
  3. 将我们的推文集合转换为令牌计数矩阵
  4. 使用 TfidfVectorizer()、TfidfTransformer()、CountVectorizer()、fit_transform()和 fit()函数获得每个候选人推文的 TF–IDF 向量

通过 TF–IDF 分析,我们可以深入了解我们收集的推文中的重要词汇。

单词云

单词云是很好的可视化工具,可以看到候选人的每条推文中哪些单词出现的频率最高。我们利用 NLTK 的 FreqDist() 函数来制作我们的单词云:

word_freqdist = FreqDist(biden_bank)
most_common_biden = word_freqdist.most_common(100)
biden_common_df = pd.DataFrame(most_common_biden, columns=['word', 'count'])
biden_common_df.set_index('word').to_dict()
biden_common_df = pd.DataFrame({biden_common_df['word']:biden_common_df['count']}) # Create the Word Cloud:from wordcloud import WordCloudwordcloud = WordCloud(colormap='Spectral').generate_from_frequencies(biden_dictionary)  # Display the generated image w/ Matplotlib:plt.figure(figsize=(10,10), facecolor='k')
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis("off")
plt.tight_layout(pad=0)

这个词在“云端”出现得越大,它在推特上的使用频率就越高:

与 TF–IDF 类似,我们从每位候选人的推文中反复出现的词语中获得了洞察力。

基于 LDA 的主题建模

LDA 或潜在的狄利克雷分配,根据潜在的、未被观察到的相似主题来分离推文中的标记,以帮助用户解释它们。对于我们的 LDA,我们使用了 pyLDAvis ,这是一个用于主题建模可视化的 Python 库。

  1. 创建了一个候选人所有推文的列表,并删除了给定和选择的停用词
  2. 对 Tweets 运行 CountVectorizer()和 TfidfVectorizer()函数,然后运行 LatentDirichletAllocation()函数
  3. 尝试使用 TF 或 TF–IDF 创建七个不同主题的主题模型(民主党初选候选人各一个,特朗普总统一个):

每个泡泡代表一个不同的主题,由算法决定

总体而言,提到候选人的推文都非常相似,因此很难区分彼此。Twitter 经常是一个非常两极分化的平台,意见从光谱的两端传达,可能导致整体中立。朱莉娅和我觉得,将这一分析与 2016 年总统选举期间大约同一时间的推文进行比较,或者建立一个分类模型,试图区分候选人的推文,这将是有趣的未来工作。然而,就目前而言,看看提到拜登和特朗普的推文可能会很有趣,因为他们是 2020 年总统大选的最后两个人。

如果你有兴趣看我们项目的完整代码,请查看我的 GitHub!

你的 B2B 人工智能项目没有足够的数据?

原文:https://towardsdatascience.com/no-adequate-data-for-your-b2b-ai-project-5e05a40fb4c8?source=collection_archive---------43-----------------------

别担心,这种方法可能会让你留住你的客户。

艾米丽·莫特在 Unsplash 上的照片

人工智能现在比以往任何时候都更受科技行业的青睐。你会发现全球各地涌现出新的创业公司,试图利用炒作赚钱,有时他们在人们中间制造更多的混乱,他们将人工智能描绘成某种将永远改变你生活的超人机器。真的是这样吗?

技术上来说是的,但不是这些人说的那样。人工智能是真实的,并且会一直存在。它将增强人类的能力,重新定义人机交互,这已经在发生了。

但是不久的将来会怎样呢?嗯,我觉得这将是智能自动化,我们已经可以看到趋势朝着有利于它的方向转变。

越来越多的公司正在采用更智能的工作方法,并走上全面数字化转型的道路。现在是从事人工智能和人工智能的创业公司和小公司向更大的客户群提供专业知识和知识的时候了,以帮助他们实现数字化转型。说起来容易做起来难,对吧?

构建生产就绪的机器学习(ML)或深度学习(DL)应用程序在许多方面都具有挑战性。需要考虑的事情太多了,以至于你经常会得到一个训练很差的模型,或者你有一个 ML 后端,这对于响应时间来说是一个灾难。

但这是否意味着你正在解决的问题太复杂了,或者不能用统计学习工具来解决?

嗯,也许吧,但在做出任何结论和失去一个潜在客户之前,看看我们帮助客户理解他们的人工智能项目的范围的策略,并告诉他们我们可以提供什么样的附加值。也许它可以帮助你根据你公司的投资组合设计你自己的方法。

照片由普里西拉·杜·普里兹Unsplash 拍摄

与任何人工智能或人工智能项目一样,成功或失败在很大程度上取决于学习机(LM)可用的数据。我们经常会遇到各种规模的公司,要么拥有大量非结构化数据,要么根本没有数据。

后者更具挑战性,因为没有数据或数据非常少,我们无法理解问题的规模,开发一个好的人工智能模型变得很困难,因为我们可能无法为现实世界的突发事件准备模型。

如果你觉得用例没有什么开创性的东西,很容易走开,但是如果用例看起来很酷,如果你决定处理它,你可能会发现一些东西,但是数据是垃圾,那该怎么办?

我学到的是,缺乏数据不应该成为你放弃它的理由。

我们采用了一些方法来帮助我们的客户利用人工智能的能力来转变他们的工作流程。一个叫做反馈学习或迭代学习的简洁的小概念是这个的关键。这一步更关注正确的数据采集,而不是模型的完善。

它帮助客户提前接触人工智能技术,并帮助他们以正确的方式教育自己如何定位这项技术。这种方法也可以用于大量非结构化数据的情况,这些数据只能由领域专家进行注释。

例如,如果您有一个数据集,其中包含一组定义人们贷款资格的属性。只有来自银行领域的专家才能确定定义一个人是否合格的属性的正确组合。这种见解决定了数据的质量和基于数据训练的模型的能力。

这种洞察力在大多数时候可能会从数据集中消失,因为现实生活与 Kaggle 数据集相去甚远。那么在这种情况下你会怎么做呢?

反馈学习到救援!!!

正如我提到的,反馈学习的主要目的是从客户端获取正确的数据集,模型改进是次要的。反馈学习有一些关键要素。

交互式仪表板是拼图的主要部分。它让用户/客户/数据操作员能够快速与我们的后端进行交互,以进行数据注释、模型训练、版本控制模型、管理部署、查看数据集等。

数据列表屏幕(图片由 Vysakh S Mohan 提供)

数据注释编辑器(图片由 Vysakh S Mohan 提供)

上图显示了智能 IVR 的反馈学习仪表板。该模型的目的是基于从语音到文本模型转录的文本来学习意图和实体。

该应用程序的主要挑战是良好数据集的可用性,而可用的数据是非结构化的。客户需求决定了需要一个高度可扩展和可移植的学习后端,该后端可以迁移到不同的服务提供商,以满足不同用户群的需求。

这意味着模型必须动态地学习识别各种意图和实体,这使得我们很难考虑所有可能的场景。

除此之外,该模型还需要轻量级和超快的响应时间,因为它将在 IVR 之后运行,那里的呼叫流量将非常高,我们不希望该模型在工作流中造成任何延迟。

我们最初是通过查阅现有的数据开始的。根据客户的观点,我们确定了构建基线模型所需的意图和实体。一旦构建了模型并确定了超参数,我们就交付了具有端到端能力的仪表板来构建数据集、对其进行注释、训练模型等。人工智能后端被集成到 IVR 系统中。这通常是我们的 alpha 版本。

现在,无论何时来电,转录的文本都可以被发送到人工智能后端以获得预测,在那里模型试图从句子中提取意图和实体。

该信息被记录到数据库中,并且可以由客户端操作员查看。如果他在人工智能解析的输出中发现错误,他可以编辑并发送它来重新训练模型。操作员可以根据用例添加/删除意图和实体。

最终,随着时间的推移,我们会获得一个良好的基线数据集来构建一个合适的人工智能模型。这将作为我们的生产测试版发布。

上面的例子很基本,但是你也可以扩展到许多其他的用例。我们还没有在计算机视觉问题上进行尝试,但对于自然语言处理(NLP)、预测建模、时间序列等用例,我们已经用这种方法取得了相当大的成功。

是的,它确实有其局限性。例如,超参数调整就是其中之一。由于模型训练是由非人工智能专家通过仪表板迭代完成的,因此正确的模型训练和基准测试可能是不可能的。此外,根据数据类型和注释方案,可能会出现过拟合或欠拟合的情况。

那么真正的目的是什么呢?这个练习的真正目的是建立适当的带注释的数据,以防你的客户想要用 AI 自动化他的工作流,但是缺少适当的数据或者可用的数据太零碎。

这也有助于他们了解人工智能如何帮助他们实现数字化转型路线图。

这种方法是一年前由我们孵化的,在它的帮助下,我们已经成功地交付了 NLP、预测建模等多个人工智能项目。一家领先的制药公司、欧盟的一家食品配送服务公司、美国的一家电信公司是我们的一些主要客户,他们从上述方法中受益匪浅。

希望这能启发你制定更新的方法来扩展和帮助你的客户用人工智能的力量无缝地转变他们的工作流程。

不,艾不是公正的。人工智能基于性别、种族和隶属关系进行歧视。

原文:https://towardsdatascience.com/no-ai-isnt-impartial-ai-discriminates-based-on-gender-race-and-affiliations-6535fa7023f3?source=collection_archive---------32-----------------------

照片由 sebastiaan stam 拍摄。

一个常见的误解是机器是无偏的。没有什么比这更偏离事实了。

我这是一个常见的论点,我看到它一直在被使用。“我们应该实现人工智能(AI),因为它是无偏见的。它不在乎你的性别、种族、民族和性取向——它不像我们人类那样歧视。”我甚至从大型科技公司那里听到过类似的观点。人们普遍认为人工智能是一个中立的实体,一个客观的灯塔,一个不偏不倚的圣人。

可悲的是,这是一个谎言。

性别歧视的招聘工具。

亚马逊精通人工智能。他们使用人工智能来推动他们业务的许多部分,他们甚至通过亚马逊网络服务向客户出售人工智能解决方案。亚马逊本质上是一家科技公司,存在于一个由男性主导的行业。像许多同行一样,亚马逊正试图变得更加多样化。《多元化使命》中的一个大问题是,人力招聘人员和经理存在偏见。研究表明,人类在招聘过程中会歧视他人。此外,对于拥有成千上万名申请人的公司来说,确定哪个申请人是任何给定职位的更好选择是非常具有挑战性的。

对于一家注入人工智能的公司来说,获得更加多样化的劳动力的自然步骤是在招聘过程中使用人工智能。毕竟,招聘人员是有偏见的,而众所周知机器不会。

亚马逊就是这么做的。他们雇佣了一个人工智能来帮助审查申请人的简历。我的梦想是拥有一个机器人,它可以输入一百份简历,分析它们,并推荐最好的五份——不管他们的性别或种族。不幸的是,人工智能更喜欢男人而不是女人。机器学习模型已经研究了十年的简历。由于科技行业男性占主导地位,这些数据主要由男性简历组成。因为人工智能从它被喂养的数据中学习,人工智能学会了偏爱男人的特征。例如,机器学习算法对简历中使用的词汇具有重要意义,这些词汇在性别之间存在显著差异。亚马逊发现男性和女性在简历中使用不同的词汇。事实上,男性比女性更有可能使用动词,例如,执行的和捕获。由于人工智能从男性简历中学习,它学会了优先选择符合这些条件的申请人。

对于不在机器学习领域的人来说,简单地告诉人工智能在选择申请人的过程中忽略性别,听起来似乎是显而易见的。但是,正如你所看到的,这并不容易。

这只是众多关联之一。由于多年来的政治议程将人们引入刻板印象,男性和女性学习了不同的科目。不同的性别也有不同的业余爱好。发现这些相关性是困难的。非常难。纠正它们更难。对于你给人工智能的每一条规则和每一次引导它向特定方向的尝试,你都把你自己的偏见应用到人工智能上。无论你做什么,人工智能都会有一定程度的偏差。

你如何应对这种情况?你是否试图找到更多样的数据?你从哪里得到的?你会从竞争对手那里买简历吗?他们也没有。你不能伪造简历;没用的。你需要真实的数据。

在这一整节中,我只讨论了性别歧视。不同种族之间的歧视呢?如果你的公司成立于一个白人占主导地位的国家,并且碰巧有 99.8%的白人员工,那该怎么办?即使你有来自地球上各大洲的人的可靠混合数据,如果你有一个来自你没有数据的国家的申请人,并且申请人在他们的简历中有你的 AI 从未见过的 prio 经历,那该怎么办?为这些场景设计不考虑性别或种族等因素的公平算法不仅具有挑战性,甚至可能是不可能的。平衡有利于多样性的限制是一种方式,然而,每增加一个限制,组合中也会增加一些偏差。

无论你最终做什么,人工智能都会有偏见。

通往人工智能的道路布满了堆积如山的有偏见的数据。由亚历山大·米洛拍摄。

警方数据有种族歧视。因此,警察人工智能是种族主义者。

在我以前的一篇文章中,我讨论了世界各地的警察部队如何使用歧视性的人工智能系统。事实上,世界各地的警察当局现在都在使用人工智能来跟踪和识别公民。警察使用人工智能的最大问题之一是歧视,人工智能正在放大现有的偏见。

几十年来,警察系统地、不成比例地针对少数民族。有报道称,警察为了达到逮捕配额,在无辜的少数民族身上种植非法药物,也有记录称警察完全伪造报告。这些可怕的数据现在被输入到世界各地警察部门使用的机器学习算法中。该系统使用这些数据来学习在他们的犯罪预测中进行区分。在英国,警察经常发现自己不同意机器学习人工智能做出的预测,表示人工智能本身创造了一个自我实现的预言。

然而,警察部队仍然欢迎人工智能系统,因为它们让他们的生活更轻松。人工智能提供了更快的决策和更轻的良心,使其成为打击犯罪的另一个工具。

有时候,保持中立是不可能的。

在许多情况下,不偏不倚是不可能的。即使你有世界上最广泛的数据库和最复杂的算法,一个必须在招聘过程中决定选择哪个申请人的人工智能也总是要做出主观选择。

认为人工智能是公正的误解可能源于这样一个事实,即传统的编程机器确实是公正的。无论你是谁,你的电子邮件客户端都会像对待其他人一样给你发送邮件。你的微软 Word 文档不关心你是谁;它会给你和其他人一样的编辑功能。

然而,机器学习的不同之处在于它从数据中学习。由于一些数据是人类努力的直接产物,并且由于人类不可能是无偏见的,基于这些数据教授的 AI 也不可能是无偏见的。

人工智能的例子:它仍然可以比人类中立得多。

尽管如此,人工智能仍然是对抗偏见的未来。我这篇文章的重点是强调人工智能是有偏见的——T4 而不是 T5,它比人类更有偏见。一个人工智能被提供了一组不同的数据,被给予了公平的约束,并被赋予了适当的变量权重,尽管如此,它仍然比任何人都不偏不倚。人类永远是有偏见的。对我们的大脑进行重新编程以使其不偏不倚是不可能的(除非我们进入一些非常先进的基因工程领域)。计算机的大脑更容易编程。

一个训练有素的人工智能肯定不会像人类那样偏心。要做到这一点,人工智能的实现不能操之过急。他们需要接受不同数据的培训,并且需要仔细管理和测试。

此外,我想强调在实现机器学习人工智能时应该遵循的三条规则。

一个。AI 必须有一个可解释的日志。一定有某种机制告诉你为什么人工智能会做出这样的决定。通常情况下,人工智能会做出决定,但没有人有能力解释它为什么会做出这样的决定。

两个。必须减轻偏见。人工智能必须根据不同的数据进行训练。如果无法找到不同的数据,必须应用约束和适当的权重。我一直强调约束和权重——虽然它们确实增加了某种程度的人为偏见,但它们对于减轻薄弱的数据集是必要的。

第三。不能让人类过度依赖人工智能。虽然人工智能可能经常比人类更少偏见,但它并非完美无缺。它会犯错误。质疑一下。

虽然使用人工智能完全自动化一个过程可能很诱人,但有时最好通过使用人工智能作为指导决策的助手来开始一个人的人工智能之旅。毫无疑问,未来在于人类与人工智能的合作,机器与人类平等相处,但我们还没有到那一步。例如,在今天,招聘人员不能被人工智能取代。然而,有了人工智能的陪伴,招聘人员的工作会变得容易得多。在阅读简历时,人工智能可以提供总结和见解,同时还可以清楚地展示其信念旁边的确定性。在对候选人进行面试时,人工智能可以实时推荐后续问题,并向招聘人员提供行为分析。

看一看这篇文章中关于这些规则的更多细节,以及一些如果你选择忽视它们可能会发生什么的可怕故事。

[## 为什么人工智能必须是道德的——以及我们如何做到这一点

当人工智能决定谁是有价值的,谁是正确的,谁是罪犯,你只能希望它使…

towardsdatascience.com](/why-ai-must-be-ethical-and-how-we-make-it-so-b52cdb1dd15f)

和人类打交道的 AI 永远是有偏见的。

我们有责任减少这种情况。

用于小儿肺炎检测的无代码人工智能

原文:https://towardsdatascience.com/no-code-ai-for-pediatric-pneumonia-detection-1641f9c89f31?source=collection_archive---------61-----------------------

使用胸部 X 射线图像创建并公开部署 98%准确的图像分类模型。

由弗朗切斯科·帕尔马和厄恩·纪勤撰写

小儿肺炎是 5 岁以下儿童的主要杀手,每年有超过 800,000 人死亡。世卫组织报告称,大多数儿童临床肺炎病例发生在东南亚和撒哈拉以南非洲等地区。

尽管肺炎导致的儿童死亡大多发生在发展中国家,但在发达国家,仍有大量与肺炎相关的医疗相关费用。

肺炎导致的死亡人数超过了疟疾、脑膜炎、营养不良和艾滋病的总和。

细菌和病毒病原体是肺炎的主要原因(Mcluckie,2009),但需要非常不同的管理形式。细菌性肺炎需要紧急转诊和立即使用抗生素治疗,而病毒性肺炎则接受支持性治疗。因此,准确及时的诊断至关重要。诊断的一个关键方法是使用放射数据,因为胸部 X 射线是常规获得的,以确定这些症状的原因,并有助于区分不同类型的肺炎。然而,图像的快速放射学解释并不总是可用的,特别是在儿童肺炎最流行且死亡率最高的低资源环境中。

在本文中,我们创建并部署了一个人工智能模型,以 98.89% 的准确率从胸部 x 光图像中自动识别肺炎。所有的开发都不需要写一行代码,也不需要专家的监督。如果给系统数百张看不见的图像,分析它们只需要不到一秒钟的时间。

我们部署的可以用来分类看不见的图像的网络应用程序可以在这里找到:https://cloud.giotto.ai/ic/pneumonia

密码:肺炎

Web 应用程序显示

当前的检测方法和局限性

除了 X 射线和血液检测,还有多种方法用于检测儿童肺炎,但它们往往缺乏同样的准确性和可靠性,或者对于这种类型的疾病来说过于先进。其中包括:

  • 痰培养:通过测试从肺部咳出并进入口腔的粘液来识别感染(通常很难从幼儿身上收集到这些样本)
  • 脉搏血氧仪:测量血液中的含氧量
  • 胸部 CT 扫描:使用胸部结构的图像(很少进行)
  • 支气管镜检查:用于观察肺部气道内部的分析(也很少使用)
  • 胸膜腔液体培养:从胸膜腔(肺和胸壁之间的区域)抽取液体样本进行测试

脉搏血氧仪使用光和光电探测器来测量远离心脏的身体最深处(通常是手指或脚趾)的血氧含量。

在医疗基础设施相对较差的国家,诊断通常依赖于非常基本的方法,如呼吸率(高呼吸率通常被标记为肺炎的潜在迹象),或呼吸时胸腔内的视觉迹象(当他们吸气时,他们的下胸部可能会收缩或收缩,健康人的胸部在吸气时会膨胀)。

由于该地区缺乏强大的医疗基础设施,并且缺乏 x 光或血液检测的效率和准确性,这些方法经常被使用。

即使在有基础设施的地方,医学专家也不总是能够及时提供准确的评估,这正是自动化系统派上用场的地方。

直观、易用:使用 Giotto 对 X 射线进行分类

人工智能的美妙之处在于它可以向该领域的专家学习,使技术传播到可能无法接触到这些专业人员或复杂技术系统的社区,从而改善疾病的诊断和治疗,并最终拯救无数生命。

我们的目标是创建和部署一个人工智能图像分类模型,该模型能够及时地以高准确度从 X 射线中识别肺炎病例。该系统需要对之前由训练有素的医疗专业人员标记的图像进行训练,但之后可以被任何有互联网接入的人用来对新图像进行分类

对于我们的任务,我们使用了无代码 AI** 平台 Giotto ,在这里可以访问。Giotto 的目标是在一个易于使用的平台上提供最先进的人工智能技术,所有人都可以访问,不需要编码技能。最重要的是,网络应用部署功能**允许用户与每个人分享他们的模型。****

有了 Giotto 等无代码人工智能平台,任何有互联网连接的人都可以点击几下就能访问最高效的深度学习基础设施和 GPU 计算系统,并将其用于自己的目的。

如果你想通过 一步一步的教程 来了解如何开始使用 Giotto,你可以看看我们之前的博客帖子,在那里我们使用包含各种花卉物种的大型数据集上的图像分类模型来探索这个平台。

在这项任务中,我们使用了来自一项名为“通过基于图像的深度学习识别医疗诊断和可治疗疾病”的研究的数据(Kermany 等人,2018 年)**

**** [## 通过基于图像的深度学习识别医疗诊断和可治疗的疾病

开发了一个采用迁移学习技术的人工智能系统

www.cell.com](https://www.cell.com/cell/fulltext/S0092-8674(18)30154-5)

在本文中,该团队使用迁移学习模型来创建生物医学成像中的通用、高效应用。该数据集由 5,853 张人工标记的胸部 x 光图像组成,分为两类:正常描述肺炎。数据可以通过在这里访问。

为了训练我们的模型,我们在两个文件夹中上传了之前标记为的图像,正常和描绘肺炎。Giotto 上的流程非常直观并且不需要任何监督。上传数据后,您将被要求选择数据增强技术。在模型选择阶段,您选择 resNet 大小和您希望用来训练它的历元数

如果您在过程中的任何步骤不确定,您可以随时使用“使用 Giotto 自动选择”选项。

模型性能,以及在医疗保健中使用人工智能的进一步含义

医学成像的临床决策支持算法经常面临审查。让一台机器来诊断潜在威胁生命的疾病的想法仍然让许多人对其可靠性和可解释性产生怀疑。这就是为什么对我们来说,达到至少相当于(如果不是更好的话)医疗专业人员的精确度水平是很重要的。

一旦通过我们的机器学习模型,我们就能够在我们的测试数据集上实现 98.89% 的准确性,使用 resnet 34 和少至 15 个时期。通过查看混淆矩阵,我们还观察到特异性、灵敏性和精确性都在 98%以上。这一结果类似于一个由训练有素的放射科医师组成的团队,他们拥有多年的放射影像解释经验。而且只需要 30 分钟就可以教会我们的机器区分两组肺所需的细微差别。****

Giotto 在培训后展示的模型结果

鉴于胸部 X 射线成像的复杂性(即相对大量的可变对象,包括与肺炎检测无关的肺外大面积),结合我们的模型所达到的令人印象深刻的准确性,这表明类似的模型将能够使用相对较小的数据集日益复杂的图像中学习,具有高度的泛化能力

这个迁移学习框架为生物医学图像的进一步探索和分析提供了一个有趣的机会,它使用一个直观的模型,世界各地的人,无论他们在该领域的背景和专业知识水平如何,都可以很容易地训练和部署(T21)。 Giotto 因此可用于使用类似的 X 射线成像数据集区分不同形式的肺炎,但也可用于其他基于胸部的呼吸问题的进一步应用,甚至不同且更复杂的医学成像应用。

结论

使用人工智能平台促进对医学图像的快速准确诊断有助于减少疾病对发达国家和发展中国家的影响。它不仅有助于减轻识别疾病的经济负担,还可以通过减少诊断疾病所需的时间来拯救无数的生命,从而确保更快地实施拯救生命的治疗。

降低与人力相关的成本,如训练有素的放射科医生和其他医疗专业人员,也可以让政府和非政府组织更多地投资于医疗基础设施,如 x 光机,以抗击疾病。

随着时间的推移,我们可以预测这种技术的成本会降低,可部署性会提高。将这一点与 Giotto 这样的平台的好处结合起来,可能确实会对全球数百万人产生真正的积极影响。****

无代码/低代码人工智能:新的商业模式和数据科学家的未来

原文:https://towardsdatascience.com/no-code-low-code-ai-new-business-models-and-future-of-data-scientists-a536beb8d9e3?source=collection_archive---------6-----------------------

无代码人工智能和低代码人工智能平台:正在使用哪些商业模式,数据科学家的未来是什么?

来源

随着无代码/低代码人工智能平台的兴起,我想写这篇文章来解释这些解决方案背后的商业模式,以及它对数据科学家意味着什么。数据科学家的工作会消失还是会进化?

这些无代码的解决方案通常出现在引导平台中,为适合初学者和机器学习专业人员的全自动机器学习服务提供经典的拖放功能。

未开发市场

今天的现实是,机器学习专家很难找到,也很难留住。将你的企业转变为人工智能驱动的组织需要时间和投资。因此,一些公司几乎不可能采用人工智能。

就中型公司而言,对数据科学家的需求很高,因为公司缺乏构建可扩展人工智能解决方案所需的技术人才,但无法雇用开发人员的公司面临着被落在后面的风险。因此,越来越多的公司转向机器学习的无代码平台

无代码平台:这种平台可以让公司和没有或只有很少编程经验的商务人士构建应用程序,填补他们组织中的人才缺口。

帮助数据科学家的新工具

除了无代码人工智能解决方案,我们还看到了许多低代码解决方案。事实上,越来越多的工具有望让数据科学领域变得更加触手可及。显然,考虑到数据科学和机器学习管道的复杂性,这不是一项容易的任务。然而,包括 Keras、FastAI 和 Weka 在内的许多库和工具为我们提供了一个易于使用的高级界面和许多预构建的组件,从而使创建数据科学项目变得非常容易。

我意识到,一家公司通常很难吸引到高素质的机器学习专家,这种需求正在增长,很多时候超过了供应。这里的解决方案可能是提供对自动化机器学习工具的访问。

自动化机器学习:将机器学习应用于现实世界问题的过程自动化的过程。AutoML 涵盖了从原始数据集到可部署的机器学习模型的完整管道。

这个想法是为了挑战传统的学习技术机器学习的方法,并引入更容易理解的机器学习。

新的商业模式

这些商业模式的潜在目标是利用没有数据科学团队或数据科学团队有限的中小型企业的规模和国际范围。

其次,通过构建低代码或无代码的人工智能平台,市场领导者将更容易将自己确立为中央人工智能生态系统,并进一步建立联盟来扩展用例及交付。

我还认为,大型科技公司投资于无代码人工智能模型构建平台,以加速人工智能民主化,并从品牌的角度建立这种顶级意识。此外,它有助于公司赢得将构建自己模型的程序员或最终用户。商业模式可能是创建一个相对容易使用但有限的平台,并为更好的人工智能相关服务(培训、协助等)提供高级订阅。).从今天开始,我希望这些公司根据用户的请求数量来收费。

来源

我相信大型科技公司实际上正在建立人工智能生态系统,拥有一个无代码人工智能平台可以帮助客户提供一种无需大脑的方法来保持在那个品牌的生态系统和路线图,这加强了客户锁定效应。此外,它增加了大型科技公司的用户覆盖范围,使他们能够不仅向数据科学家,而且向商业用户提供服务。

领先的人工智能公司正在开发各种平台战略,以加速大型企业的采用,但与此同时,中小企业市场仍未开发…

理想情况下,这些公司希望企业用户从小型概念验证开始,看看这项技术能做什么,并消除所有可能的进入壁垒。随着他们对技术和流程越来越熟悉,他们会对人工智能如何解决具体的业务问题有其他想法。

我相信现在人工智能领域实际上正在进行两场竞赛:

—一个拉拢程序员,一个拉拢用户。“问题是,有多少最终用户会真正构建他们自己的模型,即使它像使用拖放机制一样简单?”。

大型科技公司开源或开发无代码应用程序,因为他们希望成为其他人创新的基础。通过这样做,他们将能够收集许多中小企业的所有最具战略意义的数据……

开源和无代码人工智能平台服务于这些公司保持技术前沿的更广泛目标。从这个意义上说,他们没有放弃成功的钥匙:他们在为自己的未来铺路。

除了所有这些元素,无代码人工智能平台还使这些公司有可能通过顾问和计算资源提出额外的人工智能专业知识,快速高效地完成人工智能在线培训,从而进行一些交叉/向上销售。

另一个有趣的观点是,无/低代码人工智能平台可以帮助缺乏正式人工智能实践的初创公司快速构建更好的应用程序和解决方案,而无需任何编码经验,成本低得多。这也是另一个非常有趣的市场……

解决方法

数据科学家执行的许多任务都将实现自动化…事实上,每个主要的云供应商都在某种类型的 AutoML 计划或无/低代码 AI 平台上进行了大量投资。

如今,大多数解决方案都提供了预建算法和简单的工作流,具有拖放建模和可视化界面等功能,可以轻松连接数据,加快服务/应用的上市速度。

  • 谷歌的 Cloud AutoML 训练无代码机器学习模型,界面简单(基于拖放)。它侧重于人工视觉、自然语言和翻译。谷歌还提供 Teachable Machine,这是一个更简单的工具,专为对机器学习实验和理解其工作原理感兴趣的业余爱好者设计。Teachable Machine 只需一个摄像头(网络摄像头或手机摄像头),就可以在浏览器中为小型神经元网络提供信息,而不必将图像发送到服务器,并将其导出到网站、应用程序、物理机器等。
  • 优步·艾开发了路德维希(Ludwig)这款无代码深度学习工具箱,让深度学习更容易被非专家使用。非专家可以快速训练和测试深度学习模型,而不必编写代码。专家可以获得强大的基线来比较他们的模型,并拥有一个实验设置,通过执行标准的数据预处理和可视化来轻松测试新想法和分析模型。

来源

  • 百度的 EZDL 是一个简单的拖放平台,允许用户设计和构建定制的机器学习模型。
  • 显然,ai 是一家初创公司,用户只需用自然语言提问,就可以对数据进行复杂的预测和分析。

这些无代码的机器通常出现在引导平台中,提供经典的拖放功能到适合初学者和机器学习专业人员的全自动机器学习服务

我认为,这种不断增长的无/低代码人工智能解决方案将对应用平台供应商构成更大的竞争威胁,包括缺乏低代码战略的 MEAP 和 PaaS 提供商。

通过无/低代码 AI 有什么可能?

大多数现有解决方案可以:

当谈到用例时,可以创建一个算法,它可以

  • 从房屋内部图像中自动识别设计风格和房间类型
  • 识别制造环境中的缺陷产品
  • 监控道路和人行道的裂缝
  • 检测客户是否可能流失
  • 贷款是否会被批准等。

在这一点上,领先的只是帮助网络的实际实现和训练,而不是功能工程、数据分析或测试。

数据科学家呢

当前解决方案的局限性

这些解决方案听起来很棒,但是……你肯定仍然需要数据专家。的确,商业用户必须知道拖动什么和放在哪里...然而,复杂的项目有成千上万的任务,需要数据科学家。

如果你只需要拖放一些东西,拖放工具看起来很棒,但是现实并不那么容易。我看过很多人工智能项目的工作流程,我可以向你保证,为了扩大规模并达到生产,你的人工智能项目将有数千个任务。

关于数据科学家

可以肯定的是,您的数据科学家不会对使用无代码/拖放工具感到舒服。事实上,他们已经知道如何编写代码,所以他们不需要拖放式 UI。你可能会听到他们抱怨这些工具缺乏可扩展性…

尽管有这些合理的因素,数据科学家的收获是提高他们在不可自动化的事情上的技能。

我相信数据科学家的角色将仍然是人工智能项目成功的一个重要因素(取决于复杂性)。

在我看来,没有,也永远不可能有一个人工智能或无代码工具,你可以用最温和的商业规则来喂养它,让它生成一个应用程序。总会有人的因素来完成功能工程、架构、测试和维护。

此外,随着无/低代码人工智能解决方案的兴起,我们可能会看到数据科学家最终花费太多时间来修复他们同事的工作,因为他们可以完成自己的任务。

可以有把握地假设,随着我们继续让人工智能民主化,许多机器学习元素的任务将会自动化。这种转变将使数据专家在解决问题时更具战略性和创造性。

没有数据专家的帮助,人们很难指望企业能够使用自动化机器学习的结果。无论如何,人工智能项目的数据准备、结果解释和其他阶段仍然需要数据专家。

在我看来,数据科学将继续具有战略意义,但世界正在向功能性数据科学转变,从业者可以进行自己的分析。您需要数据工程师,而不是数据科学家来启用数据管道和集成数据结构。

未来的数据科学家应该更加专业化,解决最关键、最复杂的业务挑战,帮助他们的业务创造附加值。

所有这些平台和工具仍然有其局限性,但这是业余爱好者的 ML——简化和几乎自制的 AI——越来越近的一个标志。

不怕机器学习——如何用不到 10 行代码对文本进行分类

原文:https://towardsdatascience.com/no-fear-of-machine-learning-classify-your-textual-data-in-less-than-10-lines-of-code-2360d5cec798?source=collection_archive---------34-----------------------

文本数据的机器学习导论

图片来自 Pixaby

这篇文章建立在我前两篇文章的基础上,在那两篇文章中,我分享了一些关于如何开始使用 Python(或 R) 进行数据分析的技巧,并解释了一些关于 Python 中文本分析的基本概念。在这篇文章中,我想更进一步,谈谈如何在机器学习的帮助下开始文本分类。

写这篇文章背后的动机和之前的一样:因为有足够多的人受困于对给定任务来说不是最佳的工具,例如使用 MS Excel 进行文本分析。我想鼓励人们使用 Python,不要害怕编程,尽可能多地自动化他们的工作。

说到自动化,在我的上一篇文章中,我介绍了一些如何从文本数据中提取信息的方法,以铁路事故报告为例。我展示了如何从数据集中提取最常见的词(以获得数据的整体概念),如何查找特定的词,如“损害”或“危险材料”,以记录损害是否发生,以及如何在正则表达式的帮助下提取损害的成本,而不是必须阅读每个事件文本。

但是,要找的词太多怎么办?以犯罪报告为例,如果您对未成年人是否参与其中感兴趣,该怎么办?你可以用很多不同的词来描述未成年人:未成年人、未成年人、青年、少年、少年、青春期等。记住所有这些单词将是相当乏味的。但是,如果您已经标记了过去的数据,有一个简单的解决方案。假设您有一个手动标记的以前犯罪报告的数据集,您可以训练一个分类器,该分类器可以学习标记的犯罪报告的模式,并将它们与标签进行匹配(是否涉及未成年人,此人是否喝醉,等等)。如果您得到一批新的未标记的犯罪报告,您可以对新数据运行分类器,并自动标记报告,而不必阅读它们。听起来很棒,不是吗?如果我告诉你这只用 7 行代码就可以完成,会怎么样?令人震惊,我知道。

在这篇文章中,我将回顾机器学习和自然语言处理(NLP)中的一些主要概念,并链接文章以供进一步阅读。需要一些文本预处理的知识,比如停用词移除和词条满足,我在我的上一篇文章中描述过。然后,我将展示一个真实世界的例子,使用我在最近的博士研究中获得的数据集,如何训练一个分类器。

分类问题

分类的任务是识别一个新观察值属于哪一组类别。一个简单的例子是将电子邮件分类为垃圾邮件和垃圾邮件(二进制分类)。如果你有两个以上的类别,这就是所谓的多类分类。有几种流行的分类算法,我不会深入讨论,但邀请您查看提供的链接并进行自己的研究:

培训和测试数据

当您收到一封新邮件时,发件人不会将该邮件标记为“垃圾邮件”或“垃圾邮件”。您的电子邮件提供商必须将收到的电子邮件标记为垃圾邮件并将其发送到您的收件箱,或者标记为垃圾邮件并将其发送到垃圾邮件文件夹。为了告诉你的分类器(机器学习模型)在现实世界中工作得有多好,你在开发期间将你的数据分成个训练集和个测试集。

假设你有 1000 封邮件被标记为垃圾邮件。如果您使用全部数据训练您的分类器,您就没有数据来判断您的分类器有多准确,因为您没有模型没有看到的任何电子邮件示例。因此,您希望将一些电子邮件排除在训练集之外,让经过训练的模型预测这些被排除的电子邮件的标签(测试集)。通过将预测的标签与实际标签进行比较,您将能够知道您的模型对新数据的概括程度,以及它在现实世界中的表现。

以计算机可读格式(数字)表示文本

好了,现在你有了你的数据,你已经把它分成了训练集和测试集,让我们开始训练分类器,不是吗?假设我们正在处理文本数据,我们还需要做一件事。如果我们处理的是数字数据,我们可以将这些数字直接输入分类器。但是计算机不理解文本。文本必须被转换成数字,这被称为文本矢量化。做这件事有几种方法,但我只讲一种。查看这些文章,进一步了解 tf-idf单词嵌入

一种流行且简单的利用文本数据进行特征提取的方法被称为文本的词袋模型。让我们以下面这句话为例:

苹果很好,但梨也很好,不过,有时我想吃桔子,有时我想吃香蕉

这句引语被用作我们的词汇。这个句子包含 17 个不同的单词。下面三个句子可以用我们的词汇表示为向量:

  • 《我喜欢苹果》
    【1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0】
  • “香蕉很棒。香蕉很牛逼,
    【0,2,1,0,0,0,0,0,0,0,0,0,0,2】
    或者
    【0,1,1,0,0,0,0,0,0,0,0,0,0,1】如果你不在乎一个词出现的频率。
  • 《她吃猕猴桃》
    【0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

下面你可以看到表格形式的句子向量。

你可以看到我们计算了词汇中的每个单词在句子的向量表示中出现的频率。不在我们初始词汇表中的单词当然是不知道的,因此最后一句话只包含零。现在你应该能够看到分类器在预测句子的标签时是如何识别模式的。想象一个包含关于不同水果的句子的训练集。在向量表示中,谈论苹果的句子在索引 1 处的值将大于 0,而在向量表示中,谈论香蕉的句子在索引 17 处的值将大于 0。

测量精度

太好了,现在我们已经训练了我们的分类器,我们怎么知道它有多准确呢?这取决于你的数据类型。衡量分类器准确性的最简单方法是将测试集上的预测与实际标签进行比较。如果分类器获得 80/100 的正确率,则准确率为 80%。然而,有几件事需要考虑。我不会讲太多细节,但我会举一个例子来证明我的观点:假设你有一个关于信用欺诈的数据集。该数据集包含信用卡交易,并显示两天内发生的交易,其中 284,807 笔交易中有 492 笔欺诈。您可以看到数据集高度不平衡,欺诈仅占所有交易的 0.172%。你可以给所有的交易分配“非欺诈”,并获得 99.98%的准确率!这听起来很棒,但完全忽略了检测欺诈的要点,因为我们准确地识别出了 0%的欺诈案例。

这里有一篇文章,解释了评估机器学习模型的不同方法。这里的是另一个,描述了如何处理不平衡数据的技术。

交叉验证

在介绍编码示例之前,我还想介绍一个概念,那就是交叉验证。有许多很棒的视频文章解释了交叉验证,所以,我将再次从准确性评估的角度快速介绍一下。交叉验证通常用于避免模型对训练数据的过拟合和欠拟合。这是机器学习中的一个重要概念,所以我邀请你仔细阅读。

当将您的数据分成训练集和测试集时,如果您幸运地使用了测试集,并且模型在测试集上的性能高估了您的模型在现实生活中的性能,该怎么办?或者相反,如果你运气不好,你的模型在真实世界的数据上可能比在测试集上表现得更好。因此,为了更全面地了解您的模型的准确性,有必要执行几次不同的训练和测试分割,并对每次迭代获得的不同准确性进行平均。

对人们对潜在新冠肺炎疫苗的担忧进行分类。

最初,我想使用来自英国广播公司的公共数据集,该数据集由 2225 篇文章组成,每篇文章都标有 5 个类别:商业、娱乐、政治、体育或技术,并训练一个可以预测新闻文章类别的分类器。然而,通常流行的数据集给你很高的准确性分数,而不必对数据做太多的预处理。笔记本可以在这里找到,在这里我演示了不需要对文本数据做任何事情就可以获得 97%的准确率。这很好,但不幸的是,对于现实生活中的大多数问题,这并不奏效。

所以,我使用了我自己的小数据集,这是我在最近的博士研究中收集的。一旦我写完论文,我会把它链接到这里。我收集了一些反对研发新冠肺炎疫苗的人的意见。我部分自动地标记了数据,部分手动地标记了论点所针对的“关注”。毫不奇怪,最普遍的担忧是疫苗的潜在副作用,其次是对政府缺乏信任,以及担心疫苗开发速度过快导致测试不足。

我使用 Python 和 scikit-learn 库来完成这个任务。Scikit-learn 可以为您做很多繁重的工作,正如本文标题中所述,它允许您用少至 7 行的代码为文本数据编写分类器。所以,我们开始吧!

读入数据后,这是一个 CSV 文件,包含 2 列、参数和指定的关注点,我首先对数据进行预处理。我在我的上一篇文章中描述了预处理方法。我将包含预处理参数的新列添加到数据框中,并将使用预处理参数来训练分类器。

我将参数和它们的标签按 80:20 的比例分为训练集和测试集。Scikit-learn 有一个 train_test_split 函数,它也可以为你对数据进行分层和洗牌。

接下来,我实例化一个 CountVectoriser,将参数转换成稀疏向量,如上所述。然后,我调用 fit() 函数从测试集中的参数中学习词汇,之后,我对参数调用 transform() 函数,将每个参数编码为一个向量(scikit-learn 提供了一个同时执行这两个步骤的函数)。现在注意,我只对测试参数调用了 transform() 。为什么?因为我不想从测试参数中学习词汇,也不想在分类器中引入偏见。

最后,我实例化了一个多项式朴素贝叶斯,将其拟合到训练参数上,在测试参数上对其进行测试,并打印出准确度分数。差不多 74%。但是如果我们使用交叉验证呢?那么准确率下降到 67%。所以我们只是幸运地拥有随机状态产生的测试数据。随机状态确保您生成的分割是可重复的。

出于好奇,我打印出笔记本中的预测,并检查分类器出错的参数,我们可以看到,最令人担忧的“副作用”是错误标记的参数。这是有道理的,因为数据集是不平衡的,而且解决副作用的论点是第二大最受关注的问题,即缺乏政府信任的两倍多。因此,将副作用指定为一个关注点比指定另一个关注点更有可能是正确的。我已经尝试过欠采样,并放弃了一些副作用的论点,但结果并不太好。我鼓励你尝试一下。

我又编写了几个分类器,我们可以看到它们的准确率都在 70%左右。我设法用支持向量机把它提高到 74%,并去掉了大约 30 个副作用参数。我还使用 tensorflow 编写了一个神经网络,这超出了本文的范围,它将准确性提高了近 10%。

我希望这篇文章为您提供了开始对文本数据进行机器学习的必要资源。请随意使用笔记本中的任何代码,我鼓励你尝试不同的预处理方法、分类算法、文本矢量,当然还有数据集。

逐步增加自定义对象检测中的每秒帧数(FPS)

原文:https://towardsdatascience.com/no-gpu-for-your-production-server-a20616bb04bd?source=collection_archive---------7-----------------------

Unsplash 上的 chuttersnap 拍摄

如何提高物体检测中的 FPS 率

你可能用过很多机器学习或者深度学习模型。但是,当谈到在云中或任何服务器上部署您的模型时,我们面临许多问题。如果你正在云中部署深度学习模型,那么主要问题是 GPU。云对在你的模型中使用 GPU 收取大量费用。您的行业不想投资 GPU,但仍然需要更好的准确性和对象检测速度。那你来对地方了。在本文中,我将介绍如何在云机器或“本地主机”机器上使用 CPU 获得更好的性能和准确性。

喝杯茶,好好休息,享受旅程。

物体检测是一种计算机视觉技术,它允许我们识别、定位、跟踪图像或视频中的物体。通过这种识别、定位和跟踪,对象检测可以对场景中的对象进行计数,并确定和跟踪它们的精确位置,同时准确标记它们。

所需步骤:

在这里,我将简要地向您介绍我们计划提高每秒帧数(FPS)的所有其他必要步骤。FPS(每秒帧数)定义了对象检测模型处理视频并生成所需输出的速度。

  1. 任何自定义对象检测的第一步都是获取图像进行标记。你可以从互联网上抓取照片,或者你可以出去寻找需要训练你的模型的对象,然后自己点击一些图像。
  2. 给你的图片贴上标签。为这一步提供大量数据,因为这对你的准确性至关重要。您可以使用任何工具来标注数据。没有自动标记自定义数据的方法。你必须手动操作。这是客体滞留中最令人沮丧也是最费时的部分,但是如果你把你的奉献给这一部分,你肯定会得到一个丰硕的成果。我使用了“LabelImg”工具进行标注。要了解更多关于这个工具是如何工作的,请跟随这篇文章如何为物体检测标记图像
  3. 您必须选择适当的对象检测算法。在这里,我们将使用 YOLO-泰尼。您可以参考这里的自定义对象检测代码https://github.com/pranjalAI/Yolo-tiny-insurance
  4. 在从步骤 3 中获得 Yolo 体重文件后,您需要将 Yolo 生成的体重文件转换为 TensorFlow 服务,以便使用 TensorFlow 服务于我们的网页。
  5. 要将暗网格式的重量文件转换为 TensorFlow 格式,您需要遵循以下步骤。

克隆这个目录【https://github.com/pranjalAI/tensorflow-yolov4-tflite

照片由约书亚·苏考夫Unsplash 上拍摄

您需要使用命令提示符进入目录。

安装库

如果您安装了 Anaconda,您需要按照下面指定的命令在一个环境中安装所有需要的库。执行完命令后,将创建一个新环境。环境名的名称可以在。yml 文件。

# Tensorflow CPU
conda env create -f conda-cpu.yml
conda activate yolov4-cpu

# Tensorflow GPU
conda env create -f conda-gpu.yml
conda activate yolov4-gpu

如果您没有安装 Anaconda,那么请使用 pip 命令。我建议使用 Anaconda。

# TensorFlow CPU
pip install -r requirements.txt

# TensorFlow GPU
pip install -r requirements-gpu.txt

因此,创建了具有各自依赖性的新环境。现在,要使用新创建的环境,您需要激活它。(这一步是为那些使用 Anaconda 创建环境的人准备的。)

照片由 Serghei TrofimovUnsplash 上拍摄

环境激活

conda activate yolov4-gpu

这里“yolov4-gpu”是环境名。您可以在中更改它。yml 文件。(这一步是为那些使用 Anaconda 创建环境的人准备的。)如果您使用的是 pip,那么直接进行下一步。

现在,如果您进入了刚刚克隆的文件夹,并且已经激活了环境,最后,您需要在克隆的文件夹中进行两项更改。

首先,复制并粘贴您的自定义。重量文件到'数据'文件夹,并复制和粘贴您的自定义。“数据/类/”文件夹中。

其次,您需要对代码进行的唯一更改是“core/config.py”文件的第 14 行。更新代码以指向您的自定义。names 文件,如下所示。(我的习俗”。names”文件称为“custom.names ”,但您的文件可能会有不同的名称)

注意:如果你使用的是已经训练好的 yolov4,确保第 14 行保持 coco.names

开始了。!现在,我们需要一个命令行来使代码 TensorFlow 兼容。

python save_model.py - weights。/data/your _ weight _ file . weights-output。/check points/yolo-tiny-416-input _ size 416-model yolov 4

这里,416 是您在训练“Yolo-tiny”模型时在配置文件中定义的图像大小。运行上面的命令后,您将得到一个“.pb”文件

的”。pb”文件给 yolo-tiny

现在,您需要在检测对象时给出这个文件夹的位置。而且,跑了”。py”文件来使用您训练过的对象检测器。

在这里,使用 GPU,我用 YoloV4-Tiny 达到了 70 FPS,甚至有更好的准确性,可以进一步提高。使用 CPU,我达到了大约每秒 7 帧的速度。

进一步提高 FPS 速度的技巧

我用过 416 的图像尺寸。通过将图像大小缩小到 32 的倍数,可以获得更高的帧速率。这里是速度和准确性之间的权衡。您可以减小图像尺寸,直到您的用例达到满意的精度。

你走之前……

如果你喜欢这篇文章,并希望关注更多关于 Python &数据科学精彩文章——请点击这里https://pranjalai.medium.com/membership考虑成为中级会员。

请考虑使用我的推荐链接注册。通过这种方式,会员费的一部分归我,这激励我写更多关于 Python 和数据科学的令人兴奋的东西。

还有,可以随时订阅我的免费简讯: Pranjal 的简讯

没有标签?没问题!

原文:https://towardsdatascience.com/no-labels-no-problem-30024984681d?source=collection_archive---------16-----------------------

使用通气管的无标签机器学习

浮潜可以使标记数据变得轻而易举

具有一定讽刺意味的是,机器学习,一种用于任务和过程自动化的工具,往往始于高度手工的数据标记过程。

创建标签以教会计算机新任务的任务正迅速成为 21 世纪的蓝领工作。

它创造了复杂的供应链,而这些供应链往往以低收入国家为终点,如 T2、肯尼亚、印度和菲律宾。虽然这一新兴行业创造了数千个工作岗位,但工人们可能会受到低薪和剥削。

数据标签市场在 2018 年超过 5 亿美元,到 2023 年将达到 12 亿美元。它占了构建人工智能技术时间的 80%。

人工智能正在向人类学习。许多人类。纽约时报

因此,从成本、时间甚至伦理的角度来看,使创建数据标签的过程自动化的能力是非常需要的。

在本文中,我们将通过 Python 中的一个工作示例,使用优秀的通气管库来探索如何实现这一点。

有更智能、更快捷的方法来标记您的数据

进入通气管

浮潜是一个真正创新的概念;创建一系列“杂乱”的标签函数,并以智能的方式组合这些函数来为数据集构建标签。然后,这些标签可以用于以与标准机器学习工作流完全相同的方式训练机器学习模型。虽然这超出了本文的范围,但值得注意的是,该库也有助于促进增加训练集的过程,并监控数据集的关键区域,以确保模型被训练为有效地处理这些问题。

自 2016 年以来,浮潜本身已经存在,但仍在继续发展。它现在被行业中的许多大公司(Google、IBM、Intel)使用。2019 年的 0.9 版本带来了一种构建标签模型的更复杂的方式,以及一套覆盖软件所有关键领域的文档齐全的教程。即使你以前遇到过,这些更新也值得你再看一眼。

何时使用通气管

在我们开始一个工作示例之前,值得考虑一下什么时候应该使用这个库而不是传统的(手动)创建标签的方法。如果以下所有问题的答案都是肯定的,那么就值得考虑浮潜:

  • 您有一个没有标签或标签集不完整的数据集。
  • 手动标记数据集将花费大量的时间和精力。
  • 你有数据的领域知识(或者可以和有知识的人密切合作)。
  • 您可以想出一个或多个简单的函数来将数据分成不同的类(例如,通过使用关键字搜索,或者为某个值设置特定的阈值)。

浮潜是怎么工作的?

使用通气管的过程很简单:

  1. 🏅【可选】为数据集中的项目创建一小部分“黄金”标签(这有助于审查最终模型的性能,但不是必需的。另一种方法是“目测”结果,以了解模型的表现。)
  2. 写了一系列的‘标签函数’,定义了训练数据的不同类别。
  3. 🏗构建一个标签模型并将其应用于数据集以创建一组标签。
  4. 📈在你正常的机器学习管道中使用这些标签(即使用产生的标签训练一个模型)。

这个过程是迭代的,你会发现自己在评估结果,重新思考和提炼标签函数,以提高输出。

成功的例子

让我们用一个现实生活中的问题来展示如何将浮潜用于机器学习管道。

我们将尝试在一个开源的商业数据集中从“合同”中分离出“框架”(来自 Contracts Finder ,这是一个英国透明系统,记录了所有超过 10k 的政府合同)。

什么是框架?

一个框架可以被认为是一个“母协议”。这是一种与一个或多个供应商解决“条款和条件”的方式,这样就可以达成合同,而不必从头再来一遍。

问题是,由于框架和契约之间存在父子关系,这可能导致在分析数据时重复计算。因此,能够将框架从合同中分离出来是很重要的。

数据

本例中的数据由合同标题、描述和值组成。下面是我们必须处理的一个例子:

请注意“框架”列中缺少的标签

我们有一个名为“框架”的占位符列,我们将使用它来添加标签。我们将使用的命名约定是:

 **1** = Framework
 **0** = Not Framework
**-1** = Abstain (ie not sure!)

创建我们的第一个标签函数:

我们将从创建一系列标签函数开始。这些函数本质上可以是任何标准的 Python 函数,并且可以根据您的需要而变得简单(或复杂)。

我们将从数据集上的简单关键字搜索开始。本示例搜索短语:

“英国公共部门机构使用”

因为这只可能出现在框架的描述中。通气管让这变得非常简单,你所要做的就是用装饰器@labeling_function()包装一个标准的 Python 函数:

from snorkel.labeling import labeling_function@labeling_function()
def ccs(x):
    return 1 if "use by uk public sector bodies" in x.desc.lower() else -1

太好了,我们刚刚创建了第一个标签函数!我们现在构建了许多其他的函数来帮助将框架从契约中分离出来。

创建有效标签功能的技巧

使用该库后,以下指导原则将有助于设计有效的标签函数:

  • 🤔设计标签功能时,始终牢记最终结果。特别是思考精度,回忆。这将有助于决定在生产的标签中是覆盖面更重要还是特异性更重要。
  • 📑在对潜在的功能进行编码之前,仔细考虑它们。用简单的英语创建一个列表有助于让你在编码之前优先考虑最有效的标签功能。
  • 🎯少即是多。采用散弹枪的方法来构建函数通常很有诱惑力,但是少量的经过深思熟虑的函数总是比大量不太精确的标签函数更有效。
  • ⚗️ 在添加标签函数之前,总是要单独测试数据集上的任何新函数。它返回什么结果?这是你所期待的吗?

应用和评估我们的标签功能

一旦您建立了一个或多个标签函数,您需要应用它们来创建一组数据点。这可以通过使用PandasLFApplier来实现,它允许你直接从熊猫数据框架中建立这些数据点。

from snorkel.labeling import PandasLFApplier

lfs = [ccs,Other_label_functions...]

applier = PandasLFApplier(lfs=lfs)L_train = applier.apply(df=df_train) #unlabelled dataset
L_dev = applier.apply(df=df_test)    #small label dev set

请注意,在本例中,我们有一组训练和“开发”数据。dev 集是一个手动标记项目的小型数据集(我们的“黄金”标签)。这使得快速了解标签函数的执行情况变得更加容易(这是目测结果的替代方法)。

一旦您应用了您的标签功能,通气管提供了使用LFAnalysis轻松访问标签性能

LFAnalysis(L=L_dev, lfs=lfs).lf_summary(Y=Y_test)

由于我们有一组带标签的开发信息,这将为我们提供以下信息:

这些术语的含义如下(直接来自通气管文件):

  • 极性:该 LF 输出的唯一标签集合(不包括弃权)
  • 覆盖率:LF 标记的数据集的分数
  • 重叠:该 LF 和至少一个其他 LF 标签所在数据集的分数
  • 冲突:该 LF 和至少一个其他 LF 标记和不一致的数据集部分
  • 正确:该 LF 正确标注的数据点数(如果有金色标注)
  • 不正确:该 LF 标注错误的数据点数(如果有金色标注)
  • 经验精度:该 LF 的经验精度(如果有金标)

创建标签模型

一旦我们对我们的标签函数满意了,我们就可以把它们放在一个概率模型中。这是浮潜的“神奇来源”,它结合了每个函数的输出,或者返回具有特定标签的数据点的概率,或者返回标签本身。

from snorkel.labeling import LabelModellabel_model = LabelModel(cardinality=2, verbose=True)label_model.fit(L_train=L_train, n_epochs=500, lr=0.001, log_freq=100, seed=123)

过滤数据集

根据我们标签函数的覆盖范围,在使用标签训练机器学习模型之前,我们需要过滤掉一些训练数据。原因是一些数据点不会被我们的任何标签函数拾取。我们希望删除这些项目,因为它们会给训练数据增加噪声。通气管有一个内置的功能,使这很容易:

from snorkel.labeling import filter_unlabeled_dataframe#For label probabilities (optional):
probs_train = label_model.predict_proba(L=L_train)#For actual labels:
probs_train = label_model.predict(L=L_train,return_probs=False)#filtering the data:
df_train_filtered, probs_train_filtered = filter_unlabeled_dataframe(X=df_train, y=probs_train, L=L_train)

你们都完了!

现在,您拥有了一个带有标签的训练数据集,而无需对数据集执行任何手动标签操作。

您可以将这些作为监督机器学习任务的起点。

进一步阅读

正如前面所强调的,关于通气管的文档非常优秀,并且有许多深入的教程深入介绍了库中可用的功能:

[## 通气管

手工建立标签和管理训练数据集是机器学习的最大瓶颈之一。在…

www.snorkel.org](https://www.snorkel.org/)

图像来源:

没人需要你的数据

原文:https://towardsdatascience.com/no-one-needs-your-data-a175756b2c16?source=collection_archive---------53-----------------------

降低数据产品不增值的风险

尼克·西格雷夫在 Unsplash 上的照片

本文是系列文章的第一部分。 查看这里的介绍

我的手机跟随着我,并与谷歌分享我的位置。他们每年收集大约 22 万条关于我所在位置的观察信息,我把这些信息交给他们,以换取地图服务和广告(他们还让我访问我在 timeline.google.com⁠的数据——如果你还没有的话,可以看看,这很有趣)。

当然,这些数据是有价值的。位置数据包含丰富的信息。谷歌用它们来做广告。但是它们的原始形态有多少价值呢? TechCrunch 报道通过数据经纪人和交易所,一个位置数据本身价值约 0.0007 美元,这意味着我可以以每年约 150 美元的价格出售我的数据。这并非一无是处,但对我来说,出售数据可能不值得努力。

让我们把这个放大一点。拼车公司 Lyft 在 2018 年完成了 6.2 亿次乘车。假设上述定价估算有效,Lyft 的旅行目的地数据在 2018 年⁠将价值约 43.4 万美元——同样有价值,但与他们 2018 年 22 亿美元的收入相比微不足道。

尽管有潜在的额外收入,拼车公司不愿意向他人提供他们的数据是出了名的。为什么?除了原始数据的直接货币价值,Lyft 还对他们正在收集的数据有更大的计划。Lyft 正在完善他们的原始位置数据,以得出支持他们自己平台的结果,从提高到达估计到测试自动驾驶汽车。

数据本身不会增加价值

2019 年我的手机在北美去哪儿。图片作者。

原始位置数据是有价值的,但它们本身不会增加价值。这是因为最终目标永远不是获取数据。最终目标是完成工作。因此,人们获得的价值并不是数据所固有的,而是取决于与备选方案相比,它能在多大程度上实现结果。

如果我的个人位置数据带有额外的衍生信息,比如我是谁,我喜欢什么,那么它的价值就会上升。这些额外的数据增加了更多可操作的信息。对于一家广告公司来说,去年我只去过我当地的咖啡店七次(尽管 114 次都在 100 米范围内),这一事实比知道我也是一名年龄在 24 岁至 39 岁之间的男性(这一人群中,比其他人花费更少但消费更多的咖啡,并且更有可能在家而不是在咖啡店喝咖啡)更不具信息性。

根据我的人口统计,我会在杂货店买很多当地烘焙的咖啡,在家里煮。一家咖啡公司会发现,知道我喝咖啡的概率比仅仅知道我去其他咖啡店的频率更有价值,更不用说知道我的年龄和性别或获得一堆我去过的地方的数据了。

类似地,尽管原油公司和运输公司都使用石油作为投入,但它们向完全不同的客户提供完全不同的产出。大多数人不提炼他们自己的原油来给他们的汽车提供燃料,或者甚至不关心它是如何提炼的或者在哪里提炼的。当我给汽车加满汽油时,我是在购买一种衍生产品,这样我就可以四处走动了。如果我使用拼车服务或购买电动汽车,我甚至不需要那种精致的产品来满足我的主要需求:四处走动

数据中不同类型的值

数据的价值会因其产品化方式的不同而发生巨大变化。如上所述,原始数据通常不如经过进一步处理的表单有价值,因为使用它们进行工作更加困难。更高层次的 outputs⁠——例如构建算法来支持甚至自动化 decisions⁠——涉及更多的复杂性,但会产生不同的结果。

这在数据产品类型的金字塔中得到了很好的体现:

数据产品金字塔。作者图片,基于设计数据产品中的内容。

我喜欢这个概念,因为它阐明了结果。从根本上说,你的数据产品只是原始信息。在中间,你的数据产品是基于一些输入的计算。在顶部,您的数据产品是决策。

这个金字塔恰好符合对产品不断增长的要求和需求。原始数据是最基础的,因为它们是最不精确的,在数据科学家和工程师的需求层次结构中,每一个连续的层次都建立在前一个层次之上(更高的层次通常需要更多的技术开发)。因此,它也与您对用户的要求密切相关。金字塔的较低层次必然需要更多的技术用户。

数据产品金字塔是一种工具,用于考虑您的数据能为谁带来什么结果。言下之意是,数据产品和生产这些产品的公司并不都一样。它们相当多样化。 Cassie Kozyrkov,谷歌的首席决策科学家,用面包解释了商业的后果:

如果你要开一家面包店,雇佣一名经验丰富的面包师是个好主意,他精通制作美味面包和糕点的细微差别。你也会想要一个烤箱。虽然它是一个重要的工具,但我敢打赌,你不会让你的顶级糕点师承担知道如何制作烤箱的任务;那么,为什么你的公司专注于机器学习的等价物呢?

你是做面包的吗?还是做烤箱?

有时候,替代方案已经足够好了

想象一下,我想把我的位置数据卖给一家自动驾驶汽车制造商(并得到我的 150 美元!).他们为什么要我的数据?自动驾驶汽车制造商面临的一个市场问题是让消费者安全地从 A 点到 B 点。获取新数据可以帮助这些公司更好地完成这项工作,方法是根据我在哪里开得快或慢来训练它们的车辆。

我的数据的价值随着它为特定结果的提炼而上升。例如,我是否提供我的车辆位置(原始数据)或我加速和减速的导数(派生数据)?使用数据产品金字塔,从原始车辆位置数据到推导出的速度数据,再到根据交通状况建议速度的算法,再到警告乘客车辆将减速让行人过街的自动决策系统,都会增加价值(和工作量)。

但自动驾驶汽车如何训练对消费者来说并不重要,只要它经过训练。(培训是厂商的终极问题。)对于上面的第一步,制造商可能能够利用我的数据实现飞跃,但他们也可以只是在赛道上进行一些现场测试。第二或第三,他们可以从另一家供应商那里购买总流量数据。如果最后一步是他们的主要目标,他们可能甚至不需要真实的位置数据。这些都是我的数据的替代品(竞争对手),最终,如果不做一些额外的工作,我的数据可能无法真正满足他们的需求。

我认为这可能就是为什么福特*等公司决定收购模拟公司来支持自动驾驶汽车开发,而不是仅仅购买一堆位置数据。他们正在购买比通过收集真实世界数据更快获得高阶结果的能力。

*披露:我在一家福特公司的全资子公司工作。

如何确保数据产品增值

确保数据产品的价值就像任何其他产品一样:它需要考虑客户问题、产品解决方案和备选方案。但是,数据产品对每一步都有一些独特的限制。

识别客户需求。

数据产品解决的问题不一定是新颖的,即使方法或输出是新的。另外,你的客户不太可能是技术型的。事实上,有时通过发现客户现有的效率低下问题,可以更容易地确定数据可以解决的问题,这些客户在其他解决方案方面有很好的框架问题。例如, sabermetrics 发展成为棒球队获得战略竞争优势的量化方法。你的问题需要验证吗?如果你在过程的早期,也许不会,但是记住,没有问题的产品是一个假设。(Sabermetrics 用了大约 20 年才开始流行,因为客户没有认识到的价值。)

确定客户需求几乎就像任何其他产品发现一样。但是,如果您正在阅读本文,您可能会认为数据产品是解决某些问题的好方法。鉴于此,数据产品的一个主要挑战是从对话中移除解决方案,以避免确认偏差。数据产品、机器学习和人工智能是超级装载的嗡嗡声,如果你不小心,可能会给你假阳性。[在未来的版本中,我会用一些警示故事来阐述!]

阐明您的数据提供的结果。

通过在转向数据产品金字塔之前从问题开始,您可以保护自己免受针对数据产品的常见批评,这些数据产品没有解决预期结果。先了解客户问题有什么帮助?因为您定位解决方案的方式(以及您提供的解决方案类型)将取决于用户及其需求。比如,你是否在帮助其他软件公司了解他们的产品使用情况?如果您的用户是产品经理(例如 Pendo),那么您可能需要在漂亮的图表中提供一些派生输出。如果您的用户是软件工程师和数据科学家(例如,Segment),那么您可能需要一个原始数据 API。

了解您在数据产品金字塔中的位置将有助于您明确您可以向客户交付哪些成果。一般来说,金字塔顶端的结果更复杂,可以吸引更多的价值,但情况并非总是如此,在接下来的几周,当我谈到复杂对复杂环中人时,我们会看到这一点。因此,选择合适的解决方案对于实现价值最大化非常重要。如果您不能确定您的数据产品如何有助于解决问题,那么您可能需要先做一些验证,以确保您的问题需要解决。

解释与备选方案的区别。

所有产品都有竞争对手。对于数据产品,这些也可能包括不依赖于您的数据类型的替代方案。你可以通过区分你的产品和其他产品来展示你的价值。没有你的产品,人们怎么能做同样的事情呢?可能有人在手工记录信息或者需要做大量的手工重新整理信息。也许他们需要自己进行计算。也许有人在依靠直觉做决定…也许有人需要做决定!关注这些竞争优势也将有助于您阐明您可以提供什么样的结果。

数据产品的一个常见卖点是它们“更快、更准确、更一致、更透明”他们有时也更昂贵,无论是在金钱上还是在努力。正因为如此,保持怀疑和批判性地询问为什么你的产品真的比替代品更有价值是有益的。例如,当一个公司可以用更少的钱让一个人做到 80%的准确率时,为什么要花更多的钱去买一个准确率为 90%的新系统呢?有人能在电子表格中得到类似的结果吗?额外的 10%是否提供了足够的附加值?如果你不能区分你的结果,那么你可能需要回到数据产品金字塔,重新评估你所提供的。

摘要

没有人需要你的数据,但这可能有助于他们更好地完成工作。您的数据增加了多少价值取决于您可以支持什么类型的结果。

确保你为客户增加价值取决于发现需求,阐明你如何解决它,并解释为什么你的方法比其他方法更好。对于数据产品,对炒作保持中立,关注有形的结果,并对你的产品与众不同的原因保持怀疑,可以降低不增加价值的风险。

跟随系列?看看第二部分,这是关于为你的企业增加数据产品可行性的策略。联系LinkedInTwitter想多聊聊,我很想听听你的看法。

未选择切片器 Power BI 中没有图表

原文:https://towardsdatascience.com/no-slicer-selected-no-chart-in-power-bi-17ce5d36cd40?source=collection_archive---------7-----------------------

了解如何轻松定制您的 Power BI 报告并更改默认设置

卡罗琳娜·格拉博斯卡在 Pexels.com 拍摄的照片

在日常使用 Power BI 时,我喜欢不时地“挑战”工具,看看它在一些非标准设置中的表现。我的意思是,我们都喜欢在短时间内完成任务,Power BI 有一个的各种功能来帮助我们实现这一点,但有时我觉得改变默认行为可以增强用户体验。

方案

比方说,我想创建一个图表,只有在切片器中选择了至少一个特定值时,该图表才会显示。像往常一样,我将使用示例 Contoso 数据库进行演示。

您可能知道,默认情况下,如果在切片器中没有选择特定的值,Power BI 将显示所有切片器值的数字:

现在,我们的想法是隐藏这些条,直到在切片器中至少有一个选择。如果不是这样,我们想显示一个空白图表。我们如何实现这一目标?

达克斯是你的朋友!

我们将使用 ISFILTERED() 函数来检查指定的列是否被直接过滤。在我们的例子中,它是来自 Product 维度的列 BrandName。该函数的结果属于布尔类型(真/假)。

让我们写下我们的度量:

Filtered Brands = ISFILTERED('Product'[BrandName])

我将把这一措施放在卡片视觉中,只是为了检查一切是否如预期那样工作:

一旦我在切片器中选择了一个特定值,我的度量将返回一个不同的结果:

我们需要做的下一件事是删除当前的过滤器上下文。为此,我们将使用all selected()函数。这是一个相当复杂的函数,可以用于各种不同的事情,所以如果你想完全理解 ALLSELECTED()函数,我推荐你阅读 Marco Russo 和 Alberto Ferrari 的这篇文章。

所以,让我们扩展一下我们的衡量标准:

Filtered Brands = CALCULATE(
                        ISFILTERED('Product'[BrandName]),
                        ALLSELECTED('Product'[BrandName])
)

基本上,我们报告的当前外观不会发生任何变化,但我们扩展了衡量标准的逻辑,并为我们试图实现的最终目标奠定了基础。

三,二,一…我们到了!

现在,让我们创建我们的最终度量:

Filtered Sales Amt = IF(
                        [Filtered Brands] = TRUE,
                        [Sales Amt],
                        BLANK()
                        )

让我停下来解释一下我们在这里做什么:通过使用 IF,我们可以控制度量的最终结果。简单地说,如果我们之前创建的 measure Filtered Brands 的结果为真,我们希望返回 Sales Amt measure 值;如果没有,我们将返回空白。

让我们看看这是否可行:

看起来不错,我会说:)

抛光以获得更好的体验

尽管我们实现了最初的目标,但乍一看这似乎有悖常理。想象一下当用户打开一个报告,看到默认切片器设置的空白画面时的反应!我打赌你会接到一些电话,抱怨什么东西坏了…

所以,让我们做最后的润色,让我们的用户开心!我要做的第一件事是创建一个度量,它将为我的用户保存消息:

Message = IF ( 
            [Filtered Brands] = TRUE,
            "",
            "Please select a value in BRAND slicer!" 
            )

同样,IF 函数将允许我们定义流:如果用户在切片器中进行选择,它将返回一个空字符串;如果没有,它将显示指定的文本。

现在,让我们在报告画布上放置一个可视卡片,将我们的消息度量放入其中,并在可视卡片的格式窗格中进行一些重要的调整:

我们将关闭类别,并将透明度设置为 100%。当我把卡片放到我的簇状柱形图上时,我会看到我的消息显示在上面,指示用户他需要做什么。一旦他在品牌切片器中选择了一个或多个值,他将看到数据条而不是消息出现。

让我们检查一下这是否如预期的那样工作:

挺牛逼的吧:)

结论

正如我一直喜欢强调的,Power BI 是一个了不起的工具!它为您提供了以多种不同方式讲述数据故事的灵活性。这个例子展示了如何根据特定的业务需求,轻松地更改默认设置和定制报表的外观。

当然,您不应该在每一个场景中都使用这种技巧——老实说,在 99%的情况下,您应该坚持使用默认行为。但是,拥有另一个工具也不错,而且您知道您可以使用它来定制您的 Power BI 报告。

成为会员,阅读媒体上的每一个故事!

订阅这里获取更多有见地的数据文章!

无应力高斯过程

原文:https://towardsdatascience.com/no-stress-gaussian-processes-40e238597864?source=collection_archive---------29-----------------------

如何处理无穷多个函数的分布?

当人们第一次接触到高斯过程时,他们会听到类似“高斯过程允许你在回归任务中使用无限空间的函数”这样的话。这是一件很难处理的事情。事实上,简而言之,高斯过程非常简单,这一切都始于(多元)正态(高斯)分布,它具有一些我们可以用于 GPs 的良好特性。作为这篇文章的经验法则,我建议当有疑问时,看一看 GP 方程,然后文本应该变得清晰。

高斯过程有什么好处?从理论的角度来看,它们是通用函数逼近器,所以答案是你需要拟合某种函数的任何东西。但是有一些计算上的考虑要做,我们稍后会得到这些考虑,它们会影响是否使用它们的决定,以及数据的可用性。

高斯过程在机器学习的大背景中处于什么位置?首先,GPs 是非参数模型,也就是说我们对于某种基于训练数据的模型参数并没有一定的更新规则。非参数算法的另一个例子是 k-最近邻。总而言之,这里(在 GPs 最基本的情况下)我们没有梯度,没有可以直接优化的目标函数。

其次,在机器学习中,GPs 很好地服从贝叶斯观点(我建议当看到贝叶斯时,考虑量化预测中的不确定性或信息量)。

因此,在我们进入 GPs 之前,我们需要了解高斯分布的这些良好特性。正如您将在后面看到的,除了使用众所周知的多元高斯分布的结果,GPs 并没有带来更多的东西。为简单起见,让我们只看高斯的二元情况,它是用均值向量μ和协方差矩阵σ定义的:

为了有个感觉,下图显示了以 0(零均值)为中心的二元高斯分布的密度。试着找出不同高斯分布下的协方差矩阵。

洗牌属性。我们可以分别取均值向量和协方差矩阵,并将它们混洗,使得各自的协方差和均值归在一起。新的发行版和旧的一样,没有变化。

边际财产。多元高斯分布定义了一组变量的联合分布。这些变量中的每一个也是按照高斯分布分布的,事实上我们可以从协方差矩阵中读出这个分布的协方差,例如,我们可以取第一维的平均向量,μ₁和所属的协方差矩阵将是σ₁₁.边际高斯则是σ₁₁).的 N(μ₁

调节性质。如前所述,多元高斯定义了变量的联合分布。事实上,对这些变量中的一个进行调节也会产生高斯分布。此外,计算得到的分布的协方差和均值是简单的,并且可以以封闭的形式进行。这是我们将在 GPs 中使用的一个基本属性。

从多元高斯到推论

现在我们已经讨论了高斯函数的性质,我们可以谈谈 GPs 是如何工作的。首先,让我们记住我们有一个回归的一般任务,我们有一个( x,y )对的训练数据集。正如我先前所说的:

高斯过程完全由均值函数 μ 和核函数 k 指定

下面的等式只是说函数 f 的概率分布是按照 GP 分布的:

核函数将是数据点相似性的度量,或者更好地说, k( x ₁, x ₂) 告诉我们 y₁和 y₂.有多接近本质上,通过指定均值函数和核函数,我们指定了无限多个函数的先验分布。我们可以把这个 GP 分布看作是多元正态分布的占位符,因为最终,我们将只处理多元正态分布,但是我们计算多元正态分布的均值和协方差的方式是高斯过程的美妙之处。当我们将前面的等式扩展一点时,这可能会更清楚:

我们可以看到,为了计算这个多元正态分布的均值向量和协方差矩阵,我们只需要将均值函数应用于训练集中的每个点,将核函数应用于训练集中的所有点对,这就产生了协方差矩阵。这里值得注意的是,我们显然不能使用任何函数作为核函数,协方差矩阵必须是正定的,因此需要相应地选择核函数。

现在我想把你的注意力再次转移到句子“在函数上的分布”。为什么我们会这样看?为了更清楚地说明这一点,请看下图。 x 轴定义输入变量,y 轴定义函数值。在蓝色部分,我们看到特定值 x 的不同函数实现。红线指定在 x 上的函数的采样实现。我们如何进行这样的采样?从全科医生的定义来看,这一点非常清楚。我们可以从变量的联合分布中抽取某一组 Y ,即 f(X) 。我们说一个多元高斯的边际分布也是高斯的,这就是我们从同一个 x 得到多个值 f(x) 的原因,因为 x 是正态分布。

这是如果我们有更多的数据,更多的 xs 时的样子,同样,它只是从多元高斯定义的联合分布中取样。

但是当然,我们还没有做任何适当的推论,不是吗?我们刚刚看到,我们可以对无限数量的函数进行采样,我们希望实际预测未知点 x 处的函数值。这正是我们通过调节所实现的,让我们假设我们的训练数据集包含变量 x₂x ₄.我们想预测 x₁ 和 x₃ 的函数值。合乎逻辑的做法是以已知值为条件。通过调节,我们减少了靠近点的不确定性(函数 f 的可能值)。“接近”的实际含义是由内核函数定义的。

或者用多一点的函数来展示(说多一点,并没有固定数量的函数,我们只是从无限的函数集中抽出 N 个函数):

你可能想知道:“但是,等等,我们是以某种值 f(x) 为条件的,但是 f(x) 甚至没有出现在分布的定义中”。我承认,当谈到 GPs 时,这可能会令人困惑。但实际上, f(x) ,也就是 y 确实出现了。它出现在条件分布和预测点的均值和协方差的封闭解中。等式如下所示(在我们的均值函数μ为 0 的情况下):

小 K 是核函数,不要与大 K 混淆,大 K 是我们通过将核函数应用于训练集 x 而指定的“设计矩阵”。μ是新的均值,ν是条件分布的协方差。

如你所见, y 对于计算新的平均值是必不可少的,这基本上是我们在预测中最有信心的一点。这是我们不假设噪声数据的情况。但是如果我们的数据实际上是有噪声的呢?在机器人应用中,这种情况很常见,我们通常假设噪声正态分布,均值为 0。对条件方程的改变很小,正如你所看到的,我们只是在设计矩阵中增加了对角方差。直观来看,这意味着什么?这意味着我们正在增加我们的边缘的不确定性,这正是我们的训练数据点,这就是我们在存在噪声的情况下想要做的。

通过向协方差矩阵添加额外的不确定性,我们考虑了噪声训练数据/观察值。

做完这一小部分线性代数后,我们可以画出函数的条件分布:

其他注意事项和有趣的事实

这里也许还有一些值得思考的事情。

计算协方差的倒数。众所周知,计算协方差矩阵的逆矩阵在数值上是不稳定的,尤其是在大型数据集的情况下。请注意,在高斯过程中,推理的计算复杂度与数据集大小成比例,而在参数模型中并非如此。因此,您选择的求逆方法对性能至关重要,最常用的方法之一就是采用乔莱斯基分解。

推理的计算复杂度是多少?严峻的事实是,增加训练数据量会增加推理的计算复杂性。为了缓解这种情况,一些人研究稀疏高斯过程,该过程基本上以一种聪明的方式选择以矩阵 K 的哪一部分为条件。直觉上,我们不需要使用所有的训练点来进行预测,我们只需要使用那些“接近”的训练点。通过减小调节中使用的协方差矩阵的大小,我们降低了计算复杂度。

我应该使用高斯过程还是深度神经网络?这是一个争论激烈的问题。当然,提出随着数据集规模的增加,推理的计算复杂性增加的观点可能是神经网络的一个论点,但有工作表明高斯过程在许多任务上大大优于神经网络。也有理论工作表明,一个非常“大”的神经网络基本上是一个 GP。

高斯过程有过拟合的问题吗?不一定。原因是我们在预测中有一个不确定性的度量,它高度依赖于设计矩阵的核函数的选择。

这些果仁到底是怎么回事?我写了一篇关于这个话题的博文,内容可能很丰富。简而言之,核是两个事物之间相似性的度量,或者你可以称之为距离度量。这是一个有点不幸的名字,因为术语“内核”在 ML 的不同上下文中使用,例如“卷积内核”与内核函数无关,或者内核技巧。

哪里有数据,我就确定,哪里没有,我就不确定,这不是太傻了吗?不,不仅仅是“哪里有数据”,“确定性”的大小高度依赖于内核函数的选择以及“接近”意味着什么。但是,是的,它和为当前问题选择的核函数一样愚蠢。

一些有用的链接

高斯过程暑期学校

高斯过程游乐场

高斯过程书

我关于内核的博文

谢谢!

数据本身不会说明任何问题

原文:https://towardsdatascience.com/no-the-data-never-says-anything-510edbd9b43a?source=collection_archive---------32-----------------------

不要让数据说话

丽贝卡·巴里在 Flickr 上的图片

我被类似“很明显,数据表明……”或“从数据来看,很明显……”的陈述所困扰。很多时候,既不清晰,也不明显。我们需要推理。数据甚至不会说话——它怎么可能自己说话呢?

等等,不,让我试试。听起来很有趣。咳咳。这里的结论很清楚:

图片由泰勒·维根提供

我遇到过一些种族至上主义者,他们引用一些统计数据作为某些种族或性别不如其他种族或性别的“证据”,这让我很不高兴。当然,如果“数据不言自明”,我们应该同意他们的观点?然而,我们许多人不同意。即使那些没有统计背景的人也能感觉到一些东西——统计数据没有捕捉到更大的画面,并且有一些复杂性(强大的不可测量的混杂因素或中介因素)阻止我们从表面上看数字。如果我们可以将这种健康的怀疑态度正式化,那不是很好吗?

很长一段时间,我很难表达这个想法,直到我看到凯西的文章。她指出:

推断=数据+假设

是我们的假设赋予了数据声音。我想进一步分解这一点,因为有一个微妙但重要的区别:

推断=数据+统计假设+因果假设

为什么要分开?即使是像“人口的平均高度是 X”或“森林中有 Y 棵树”这样的单参数估计,我们也需要假设一些数据生成机制,比如简单的随机抽样——一种因果陈述。

数据科学家/数据分析师可能是统计假设方面的专家,但他们可能不太了解因果假设。例如,如果你是一名处理医疗数据的统计学家,你会疯狂地认为你比医学博士或公共卫生硕士更了解医学。有些人是统计学和科学领域的专家,但他们很少。

假设的质量极大地影响了洞察力的质量。然而,人们很少谈论假设。团队最好召开会议来讨论这些问题。

推理意味着抛开你的自我。你必须表现出谦逊,尊重他人的专业知识,这样你才能将他们的知识融入到模型中。这是一个团队的努力。

辛普森悖论

UCB 招生数据集是说明因果假设重要性的最简单和最好的例子之一。你可能会从辛普森悖论中了解到这一点。数据(列名不是我的):

问题:UCB 的录取过程中存在性别歧视吗?

安娜计算了一些数字。她把计数加起来,像这样:

并运行逻辑回归:

安娜总结道:“女性的系数是负值,p 值很小。很明显,数据显示招生过程存在性别歧视。

芭芭拉也处理了这些数据,但她保留了原始数据。她运行逻辑回归,控制部门:

Barbara 总结道“女性的系数是正的,p 值很大。很明显,数据显示招生过程是性别歧视。”

等等,什么?

他们都使用相同的数据。他们都有合理的统计假设。然而,由于方法不同,他们得出了截然不同的结论。谁是对的?

我重申我希望在统计学课程中教授的内容:

数据+统计假设不足以得出推论。我们需要因果假设。

那么我们应该如何解决这个问题呢?为了简化,假设我们已经测量了所有相关变量。我们提出了一些因果假设:

  1. 性别直接影响录取率(性别歧视)
  2. 院系直接影响录取率(有些院系比较难进)
  3. 性别直接影响部门(男性申请者比女性申请者更喜欢不同的专业)

(1)是我们要测试的。出于形式上的考虑,我们假设(1)为真,这样我们就可以通过将它放入模型中来测试它。

那(2)和(3)呢?如果你问我,这两个都是合理的假设,我们可以假设它们是真实的。

“哇,别着急!”有人可能会说。“那太不舒服了!不能随便假设那些东西!”但是,但是,但是!我们必须做出这些选择;我们不能成为不可知论者。当我第一次了解因果建模时,我也有同样的保留,并最终对这个想法产生了兴趣。对于任何给定的变量对 X 和 Y,我们必须选择其中之一:

  • x 直接影响 Y
  • y 直接影响 X
  • x 和 Y 并不直接相互影响

在(2)的情况下,“录取率影响院系”没有意义,而“院系和录取率没有直接关系”肯定是假的(取决于其他假设,这可能意味着“所有院系的录取率相同”)。剩下的唯一说得通的就是“院系影响录取率”。

尽管一种方法可以对应多组假设,但是即使没有口头说明,假设的选择也是由分析师的方法暗示的。没有说出来并不意味着这些假设不存在。如果有什么不同的话,那些没有明说的假设往往是最没有意义的(见我以前的文章)。这几乎就像为了显得“客观”而通过省略来撒谎。

我们所有问题的解决方案:如果我们看不到假设,它们就不存在。(来源)

这三个假设合在一起暗示了这个因果图:

为什么要经历这么多麻烦?如果你不熟悉因果图,我建议阅读我关于因果关系的文章的后三分之一。事实证明,假设告诉我们应该如何分析数据:

  • (1)或(1) + (3)规定我们汇总所有数据,并使用性别作为预测值
  • (1) + (2)规定我们使用原始数据并使用性别作为预测值
  • (1) + (2) + (3)规定我们使用原始数据,并使用性别部门作为预测值

安娜的方法论假设院系和录取率没有直接关系。我对此深表怀疑,所以她的分析是错误的。(小心。即使错误的分析也可能意外地得出正确的结论。)

芭芭拉的方法论假设(2)和(3)。这比安娜的假设合理多了,所以我更倾向于相信她的结论,录取过程没有性别歧视。

因果建模

“控制 X”与“通过 X 切割”是一样的,除了你的变量不必是绝对的。

因果建模是以“正确”的方式分割数据的艺术。

FiveThirtyEight 制作了一个有趣的互动页面,在这里你可以 p-hack 你的方式进入统计学意义。试试看。如果你回归州长的就业率,共和党对经济有积极的影响(p 0.01)。如果你回归总统的就业率,共和党对经济有负面影响(p = 0.02)。那么数据说明了什么?不要混淆建模选择和数据的内在质量。

一个老笑话说“当你把 10 个经济学家放在一个房间里,你会得到什么?11 条意见。”一个更准确的笑话应该是“当你把 10 个统计学家放在一个房间里,你会得到什么?10 估计。”

这就是问题所在。人们根据他们对数据的选择得出不同的结论。甚至“正确”的结论是什么?存在吗?是神话生物吗?柏拉图式的理想?

与其争论我们不同的结论,不如讨论一下因果假设?也许我们可以让整个团队同意用一种方式来分割数据。而且,希望所有相关方都有足够的宽容度来接受这种分割方式得出的结论。本质上,这就是因果建模。

我们把你的头发切得恰到好处!相信我。我是专家。(照片由 Flickr 上的 MTSOfan 拍摄

A/B 测试是有价值的,因为这是我们完全知道因果图的唯一时间(警告:如果你有缺失的数据,或者如果有来自其他部分重叠实验的效应修正,或者如果新奇效应很强,或者…)不成立。这是我们不必做因果假设的唯一情况。我们确切地知道如何正确地分割数据。这个问题纯粹归结为统计假设。

当然,因果建模有很多问题,比如这个批评。然而,尽管有缺陷和限制,因果建模是我们得到的最好的工具。

这会让你成为一个应声虫吗?

本着贝特里奇定律 :

在 UCB 招生的例子中,我们可以就假设(1) + (2) + (3)达成一致,但有人反对这个结果。我们可以问:你对哪些假设有异议?

例如,如果他们不同意(3),只要团队作为一个整体诚信行事,其他团队成员应该附和说(3)是最合理的选择。假设是团队的努力。

如果他们同意所有的因果假设,但仍然反对,那么问题可能出在统计假设上。这是一整篇文章本身,所以我将跳过它。

如果他们同意所有的因果和统计假设,但仍然怀疑结论,那么,团队更容易看到这种反对是不合理的。

而且,就像如何通过双盲来改进实验一样,团队可以在任何人都不知道这些假设的结果的情况下讨论这些假设。

我想知道当假设驱动的分析成为常态时,团队会变得更加快乐和协作吗?每个人在分析中都有发言权,而不是只留给统计人员,通过事先就条款达成一致,结果和决定将被认为更加公平。

预测模型被高估了

好了,我说了。

我总是告诉人们,在做任何事情之前,先问问自己:预测还是推理?两者不可兼得。(嗯,好吧,可以,但只是有时候,作为一种享受。不幸的是,许多人甚至没有意识到这种区别,因为大多数数据科学都与预测有关。

对于许多应用程序,我们只关心预测——想想将模型投入生产。我们需要得出的唯一结论是“这个模型能做出好的预测吗?”这是一种特权。

然而,根据数据做出决策需要推理。从数据中得出结论需要推理。从数据中推荐行动需要推理。

自然,纯粹的预测模型对这些任务是不利的。考虑像 random forest 这样的模型,除了 LIME 之外,没有任何可解释性的外表,它在一个地点之外不做任何陈述。根据可变重要性图,您应该采取什么措施?它如何以任何方式帮助决策?

是的,但这意味着什么?我不知道数据科学是抽象艺术!(照片由 Flickr 上的戴尔·克鲁斯拍摄)

即使你使用一个像 elasticnet 这样更容易解释的模型,你也不能把所有东西都扔进去,最大化预测能力,并期望得到好的推论。你可能会在对撞机上进行条件反射,得到虚假的关联,或者你可能会阻断因果路径,隐藏影响(如果你不明白这意味着什么,请阅读我关于因果关系的文章的后三分之一)。一个例证:

控制气压,珠穆朗玛峰与死海的高度相同。(来源)

这肯定是一个愚蠢的结论,但是人们总是通过“控制一切”来不知不觉地得出这种结论。很少很明显。或者,同样糟糕的是,人们认为打开洒水装置可以防止下雨。(嘿,它一个优秀的预测器。)

因果建模是一个“我们有客户(商业利益相关者)需要的产品,但是客户不知道这是他们需要的”的例子。

“可操作的见解”已经成为数据科学中的一个流行词。然而,人们追逐纯粹的预测模型,这些模型不可能产生“可操作的见解”,同时他们忽略了推理/因果建模。很奇怪。因果建模应该是分析的核心。

最后

如果有人试图用数据吓唬别人,说“数据明明说 X!”,试着问问他们的因果假设是什么。很有启发性。如果他们声称没有假设,要么数据来自 A/B 测试,要么它可能是:

我对数据研究得越多,对结论就越不确定。那些在统计数据周围炫耀的人,就像是对真理的一瞥一样,很可能处于 T2·邓宁-克鲁格效应之下:他们做出了强有力的推论,却不知道假设在推论中的作用。

我们很少知道我们是否以“正确”的方式分割数据,尽管有些方式比其他方式更可信。尽管我们喜欢认为科学和信仰是截然相反的,但许多科学都建立在无法证实的假设之上,这需要信仰的飞跃。永远不要忘记出错的可能性。

不,你不会和机器人一起工作

原文:https://towardsdatascience.com/no-you-wont-work-alongside-robots-dbc716175d78?source=collection_archive---------40-----------------------

人工智能的新进展预示着人机共生时代的到来

照片由 Jehyun SungUnsplash 上拍摄

1997 年,IBM 的“深蓝”击败了当时的世界象棋冠军加里·卡斯帕罗夫。世界震惊了。似乎迄今为止被认为只不过是美化了的计算器的计算机,最终侵入了人类想象力和创造力的领域。

担心是徒劳的。深蓝没有创造力。它仅凭蛮力就赢了,每秒钟评估 2 亿个位置。将如此初级的算法与人类的创造力相提并论是令人厌恶的。当这个没有头脑的机器在试错中辛苦工作时,卡斯帕罗夫被他的潜意识温柔地召唤着采取有希望的行动。他有直觉,仍然只是一个装有类固醇的算盘。

和之前无数的人工智能一样,深蓝也不得不抑制自己的雄心。它不是取代我们,而仅仅是补充。卡斯帕罗夫意识到“计算机擅长的就是人类薄弱的地方,反之亦然。”在这种洞察力的鼓舞下,他组织了一场比赛,让人类和机器可以搭档比赛。果然,一对人机,一个凭直觉,一个精于计算,证明了它比任何纯人工对手都优越。即使只有一个屁股,我们人类仍然可以证明我们坐在游戏凳上是合理的。

深蓝的寓言经常被认为是人类和计算机天生互补的证明。“当然,机器一天比一天聪明”,碳-硅共生体承认,“但是只渴望我们发现平凡的乏味任务,它们永远不会完全取代我们。自动取款机并没有让银行出纳员变得过时。相反,这些设备解放了职员,让他们从事更有意义的工作,比如提供金融专业知识。

人类和计算机不可分割地交织在一起,没有对方就不完整,这种观点和计算机本身一样古老。早在 1843 年,世界上第一个计算机程序的作者阿达·洛芙莱斯就宣称,她所工作的现代计算机的前身“没有任何创造任何东西的野心”。它可以跟随分析,但它没有能力预测任何分析关系或真理。”

艾伦·图灵后来称之为“洛夫莱斯夫人的反对意见”,大约一个世纪后,控制论先驱诺伯特·维纳将其引入主流。当他在麻省理工学院的同事马文·明斯基和约翰·麦卡锡正在寻求创造在各方面都超过人类的智能机器时,维纳认为一条更有成效的道路是“设计出能与人类思维很好合作的机器,而不是试图取代它们。”

他的信念或许更适合宗教领袖,而不是头脑冷静的科学家,他宣扬道:“计算机越强大,将它与想象力、创造力和高级人类思维联系起来的价值就越大。”

在众多被维纳福音带走的研究人员中,有约瑟夫·利克里德。作为一名多才多艺的科学家,Licklider 在技术和心理学方面都游刃有余,他是想象人和机器如何在合作伙伴关系中一起工作的大师。他开创了去中心化网络和分时共享的概念,这两个概念在现代互联网的创建中都是不可或缺的。

但在 Licklider 的所有贡献中,他在 1960 年发表的具有里程碑意义的论文《人机共生》在硅谷的精神景观中留下了最大的陨石坑。“计算机技术的大多数重大进步——包括我的团队在 PARC 施乐公司所做的工作——都只是对利克设想的推断,”PARC 计算机科学实验室的创始人罗伯特·泰勒证实道。

幸运的是,在 70 年代末,乔布斯和沃兹尼亚克将其中的一些进步,包括鼠标和图形用户界面,整合到苹果 2 中,这是世界上第一台大规模销售的个人电脑。最后,计算机进入了普通美国人的家庭,不是为了嘲弄,而是为了增强主人的智力。乔布斯将新机器比作一种工具,称之为“大脑的自行车”。

从苹果手中接过接力棒的软件远见者也有类似的倾向:人类应该被赋予权力,而不是被取代。微软将开发一些程序,把办公室工作人员从手工文档管理的恐惧中解放出来。MATLAB 将帮助科学家进行机械计算,允许他们以前所未有的速度测试原始假设。谷歌地图将弥合从比特到原子的鸿沟,帮助我们在现实世界中导航。

甚至是 IBM 的沃森,的 Jeopardy!-在节目中扮演支配人类对手的计算机,是在增强意识的基础上开发的。至少有一段时间,它在医生身边找到了自己的家,帮助他们理解病人表现出的无数症状。正如 IBM 研究部主任约翰·凯利所说:“……在认知系统的时代,人类和机器将合作产生更好的结果,每个人都为这种合作带来自己的优势技能。”

在今天,有了智能助手在我们手中,我们向 Licklider 预言的人机共生体的蜕变一如既往地完整。但是,即使计算的历史讲述了无数人与机器之间的友谊故事,我们也不能自欺欺人地认为,后者融入劳动力大军无疑对所有人都有好处。

当数字时代的技术专家沉浸在个人电脑革命的兴奋中时,他们在社会科学部门的朋友们却在焦虑不安。西方世界自 20 世纪 70 年代以来经历的经济不平等的急剧上升似乎与个人电脑的出现完全吻合。

衡量财富不平等的一种方法是使用 T4 技能的概念,或者一个人的正规教育水平。不管是好是坏,这个看似粗糙的近似值与工人的工资密切相关。现在,经济学家绘制了每一个职业在过去几十年中平均工资(或在总就业中的份额)的变化,作为该工作所需技能水平的函数。他们所看到的使他们震惊。历史上第一次,图表被扭曲成 u 形。

新技术似乎对低技能和高技能工人都有帮助,但对中等技能的工人帮助不大。正如经济学家丹尼尔·苏斯金德(Daniel Susskind)在他的新书《一个没有工作的世界》(A World Without Work)中所说,“许多经济体传统上为中产阶级提供高薪工作的丰满腹部正在消失。”。我们可以在下图中清楚地看到这一趋势:

1995 年至 2015 年选定经济区域总就业份额的百分点变化。来源:OECD 2017 年就业展望

“作为整体就业的一部分,现在有更多的高收入专业人士和经理,以及更多的低收入护理人员和清洁工,教学和医疗助理,护理员和园丁,服务员和理发师。但中等收入的秘书和行政职员、生产工人和销售人员却越来越少。更重要的是,尽管劳动力市场已经变成了两级市场,但是高技能人群的工资却大幅上涨。

为了理解新的经济现实,一个由三名麻省理工学院经济学家组成的小组提出了一个理论,这个理论后来以“奥托-利维-默南(ALM)假说”而闻名首先,男人们认识到许多中产阶级的工作很大程度上由日常任务组成,这些任务可以通过遵循明确、易于表达的规则来完成。第二,他们观察到这样的任务特别适合自动化,因为遵循一套清晰的指令正是现代计算机擅长的。

因此,ALM 假说在劳动力市场的空心化和 Licklider 的人机互补理论的广泛采用之间建立了联系。它表明,即使我们认知能力的部分自动化也会对我们的就业前景产生有害影响。是的,人和机器现在确实在办公室里并肩工作。但是一双这样的鞋被证明是如此的有效,以至于每一双鞋就有十个人在麦当劳从穿西装变成穿围裙。

至少就目前而言,还有一线希望。经济学家一致认为低技能和高技能工作是安全的。在光谱的一端,遛狗者和出租车司机,在另一端,工程师和医生,没有可辨别的正式规则可循。这类任务缺乏可以翻译成计算机代码的明确说明手册,因此不受自动化的影响。也就是说,直到最近…

大约在阿达·洛芙莱斯宣称她怀疑计算机能“创造”任何东西的时候,与她同时代的作家玛丽·雪莱构想了一个完全不同的装置。她笔下的弗兰肯斯坦怪物不仅具有想象力,而且还拥有一大堆人类天赋。与阿达的客观机器形成鲜明对比的是,这种生物感受到了情感,它巨大的爱的能力——以及令读者恐惧的恨——甚至挑战了我们自己的情感。

1956 年,雪莱的文学思考在如今颇具传奇色彩的达特茅斯研讨会上以严格的数学形式化,在那里,一群志趣相投的科学家在弗兰肯斯坦式的渴望驱使下,创造出比 Licklider 和他的追随者认为实用的更接近他们形象的机器,为他们称为人工智能的研究领域奠定了基础。这个研讨会的提议是“……学习的每个方面或智力的任何其他特征原则上都可以被精确地描述,以至于可以用机器来模拟它”,这是这个新领域的主要原则。

模拟智力的确切方法还没有具体说明。很快,一些根本不同的方法开始崭露头角,这个新生的学科一分为二。

大多数研究人员认为人类的知识可以直接提取到软件中。他们试图记下专家在执行任务时遵循的所有可能的逻辑规则,并费力地亲手将它们硬编码到计算机中。IBM 的深蓝和沃森就是这种方法的例子,也是《经济学人》的资产负债管理假说的基础。这种技术在解决算法问题上结出了丰硕的果实,我们大多数人都觉得这是一项脑力劳动,比如定理证明,但事实证明,当面对人类下意识完成的任务时,比如从大量像素中识别出一只猫的轮廓,这种技术完全不够用。

另一小组科学家很早就预见到了这些局限性。他们没有刻意将大脑建模为事实和规则的固定组合,而是试图让计算机自己学习世界是如何运转的。

机器学习阵营强势冲出盖茨。1958 年,就在达特茅斯研讨会两年后,哈佛大学心理学家弗兰克·罗森布拉特从我们大脑的工作中获得灵感,开发了一个能够学习识别数字的生物神经元的简化模型。这个模型被称为感知器,引发了一阵兴奋,《纽约时报》甚至宣称它“……将能够走路、说话、看、写、自我复制并意识到自己的存在。”

尽管最初大肆宣传,单个神经元只能做这么多。赋予大脑巨大能力的是数以百万计的神经元,它们被组织成一个深层次的堆栈,每一个连续的层都形成了对感官所感知的事物的更好理解。然而,将罗森布拉特的感知器组织成这样的层级结构,却比预期更困难。目前还不清楚不同层次的神经元应该如何相互交流,以形成对世界的共同理解。在接下来的几十年里,进展甚微。

20 世纪 80 年代,当几个独立的研究人员,其中包括图灵奖获得者杰弗里·辛顿,发现了通过神经元层次传递的正确信号时,事情又有了转机。随着主要障碍的克服,狂热的研究随之而来。1989 年,另一位图灵奖获得者 Yann LeCun 开发了一个能够识别手写数字的人类视觉皮层的原始模型。八年后,德国科学家 Juergen Schmidhuber 和 Sepp Hochreiternd 将神经网络提升到序列领域,赋予它们理解长段文本、音频和 DNA 的能力。

不幸的是,在 21 世纪初,研究遇到了另一个障碍。虽然在图像和语音识别等任务上已经取得了很大的进步,但模型的表现远不及人类。很明显,进一步的进展需要更大的模型。人类大脑由数十亿个神经元组成,形成数万亿个连接,但它们的人工对应物只有数万个参数。即便如此,那些相对较小的型号已经达到了当代 CPU 硬件的极限。研究人员陷入了僵局。

2012 年,当 Hinton 的门徒 Alex Krizhevsky 意识到神经网络背后的数学几乎与计算机图形学中的数学相同时,一个解决方案出现了。两者的核心都是巨大的矩阵乘法,游戏行业已经投入了数十亿美元进行优化。在这种观点的驱动下,Krizhevsky 放弃了通用 CPU,转而使用显卡。后者支持的模型比迄今为止所设想的任何模型都要大一个数量级,这导致了 Krizhevsky 在当年所有领先的图像识别比赛中的尤塞恩·博尔特式的统治地位。

其他研究人员很快跟上,开始了对越来越大的神经网络的军备竞赛。建立了一个又一个图形卡仓库,其中有超过一亿个参数的巨大模型。在过去几年中,这些非常强大的模型已经在语音转录、物体检测和视频游戏等多种任务中超越了人类。他们甚至创作音乐和艺术。简而言之,他们终于摆脱了非原创性的枷锁,步入了直觉和创造力的领域。当然,艾达在九泉之下也不会安宁。

他的新科技景观留给人类的空间很少。21 世纪初提出的 ALM 假说没有考虑到机器学习革命。计算机只限于执行有明确指令的任务这一假设不再成立。向低技能劳动力和高技能专家承诺的安全港正在消失。

以送餐为例。没有任何其他领域的人机共生像这里这样堪称典范,机器处理数据以找到最佳路线,而人则做实际的跑腿工作。但是,随着车轮上的电脑证明了它们比车轮上的青少年优越,这种原始的安排已经开始瓦解。自动送货机器人充斥着街道,很快,人类不再能够对送货过程的任何部分做出有意义的贡献。机器正在接管整个管道。

或者参加医学诊断。Alphabet 的人工智能部门 DeepMind 开发了一种神经网络,在诊断五十多种眼病方面优于眼科医生。它还推出了一种算法,能够在 x 射线中准确地发现乳腺癌,甚至比放射科医生更好。更引人注目的是,牛津的一个团队利用机器学习开发了一种“指纹”,可以用来预测未来几年的致命心脏病发作。趋势很明显:未来的诊断医生将由硅制成。

诸如此类的例子并非个别现象,而是常态。现在,在蛮力计算和直觉模式匹配方面都优于我们的机器,正在让我们变得多余。我们不再增加合作的价值。随着机器人涌向街头工作,我们被集体推到街头乞讨。人们只能希望他们给我们一两个季度。

节点嵌入

原文:https://towardsdatascience.com/node-embeddings-e28799478cb9?source=collection_archive---------32-----------------------

入门

乌列尔 SCUnsplash 上的照片

介绍

这是从克里斯特斯·齐亚卡斯扬·吕廷格到里希特的节点嵌入调查。它是在 TUM 数据分析和机器学习小组的机器学习实验室中进行的。我们感谢 Oleksandr Shchur 监督我们的项目,并感谢günnemann 博士教授让我们有可能在他的团队中进行研究。

这个项目的代码可以在 GitHub 上找到。

我们希望这篇文章有助于理解现代节点嵌入模型的基础,并提供一些不同方向的最佳实践。当然,类似的评估协议也是公开的。

为什么是图表?

图表已经变得无处不在。你不能只把社交网络理解为图形结构,还可以理解为生物结构、搜索引擎等等。甚至图像分类任务也在用图结构进行探索。因此,对信息强大表示的研究兴趣增加了。然而,很难将经典的机器学习模型应用于图结构,因为它们是为不同的数据表示而设计的。此外,天真地将它们应用于图结构被证明是低效的。

应用程序

节点嵌入的潜在动机在于捕捉图或图的节点的特征的可能性。社区、邻近或节点的角色只是有趣应用的几个例子。利用嵌入式空间中的计算,可以利用矢量数据的标准机器学习模型。这样,就可以应用广泛和成熟的方法,如分类、预测或聚类。

节点分类,按作者分类的图像

节点分类可用于对节点进行分类,例如,如果某个机构的社交网络中的人更可能是博士生或教授。在我们的实验中,这种分类完全依赖于非属性图,基于图的结构和已知节点的类别。

链接预测,作者图片

例如,在给定两个人已经见过的人的情况下,链接预测可以回答这两个人见面的可能性有多大的问题。在这种情况下,甚至不需要考虑节点的类。

节点聚类,按作者分类的图像

由于社交网络中的人彼此接近,节点聚类可以应用于将他们分组在一起,例如,为了将大学教职员工中的机构聚集在一起。在这个例子中,来自一个研究所的员工比来自其他研究所的员工彼此更接近。这种接近可以表述为“相互了解”。

动机

许多科学家正在研究这一有趣的现象。在不同的想法之后,取得了巨大的成果。然而,这导致了不可比性。使用不同的评估协议,并且大多数资源当然被投入到新颖的方法中,而不是要击败的前辈。因此,进步的其他原因,如技术优势或更多的投入资源,可能不会在比较中进行审查。这些和其他方面导致在该领域中不完全可比的结果。这项工作的目标是提供一个基本原则的可靠比较,这些基本原则是大多数新颖想法的基础。为了实现这一目标,尽可能使用相同的环境和相同的评估协议。这使得结果具有可比性。在这个项目中,我们只依赖于非属性图,这意味着只有节点的类和图的结构是已知的。

嵌入技术

我们遵循嵌入技术,除了流行的图形神经网络,奠定了节点嵌入的大多数新方法的基础。相比之下,我们更多地放弃了调整模型的现代方法。因此,这项工作为节点嵌入的基础技术提供了比较。这些模型被细分为不同的相似性得分,即显示图中节点邻近性的度量。

图 1:节点嵌入的损失,作者图片

伯努利(4 种型号)

对于伯努利模型,真实图的相似性得分以邻接矩阵的形式给出。因此,如果两个节点相连,则条目为 1,否则为 0。解码器给出嵌入空间中的相似性得分,其可以是 sigmoid、指数、高斯或基于距离的嵌入。因此,给定嵌入矩阵,我们对损耗建模以生成邻接

伯努利可能性,作者图片

其中内核可以是

Sigmoidal,作者提供的图像

指数,作者图片

高斯(也是径向基函数核),图片作者

基于距离的#2,图片由作者提供

训练模型,即。让嵌入尽可能接近原图,对数似然最大化。

伯努利可能性,作者图片

KL 分歧(3 个模型)

KL 散度是一个概率分布与另一个概率分布的不同程度的度量。在我们的例子中,图表被建模为一个概率分布,即。图形矩阵的行数总和为 1。使用不同的模型来捕获概率分布中的真实图形特征,即个性化页面排名、转移的幂和以及转移矩阵。当然,嵌入空间中的图也需要是有效的概率分布,以便 KL 散度有意义,因此 Softmax 应用于嵌入节点。为了使嵌入的图形尽可能接近原始图形,或者更准确地说,接近在各个编码器中捕获的图形特征,KL 散度被最小化。

KL Divergence,作者图片

奇异值分解(7 种型号)

在奇异值分解中,众所周知的方法被应用于能够捕捉图形特征的不同矩阵。这样,矩阵被嵌入到低维空间中。

奇异值分解,作者图片

实验

总共 14 种嵌入方法使用 3 个评估任务在 4 个流行的图数据集上进行比较。

实验概述,作者图片

调查的结果

对于结果,在不同的嵌入技术下,相同的相似性度量(例如邻接矩阵)之间的比较是特别有趣的。

关于链路预测:

对于相同的相似性度量,对于随机矩阵,基于 KL 的模型优于基于 SVD 的模型。

链接预测的结果,图片由作者提供

关于节点分类:

对于节点分类,所有模型都表现出相似的性能。

节点分类结果,按作者分类的图像

关于节点群集:

基于 KL 的模型比基于 Bernoulli 和 SVD 的模型表现更好。特别是 SVD 由于在更高的维度中包含了太多的噪声而失去了这种比较。在奇异值分解结果中,对此进行了进一步分析。

节点聚类的结果,按作者分类的图像

在 SVD 上:

随着嵌入维数的增加,SVD 模型的节点聚类性能下降。

增加嵌入维数下的奇异值分解结果,图片由作者提供

关于伯努利:

基于 z_i - z_j 的模型比基于 ZZ^T 的模型表现更好。其原因可能是随着乘法运算而出现的正则化的必要性。为了便于比较,正则化被排除在外。

关于收敛时间:

尤其引人注目的是,基于 KL 的模型比基于 Bernoulli 的模型收敛得更快。

结论

在这项工作中提供了节点嵌入的基本原则的基准。所进行的实验证明了这样的假设,即在开发新方法之前,应该重新考虑基本原理,因为结果可能是显著不同的性能。我们公开提供我们实验的代码。如有疑问和反馈,请随时联系我们!

节点嵌入:使用 Neo4j 的 Node2vec

原文:https://towardsdatascience.com/node-embeddings-node2vec-with-neo4j-5152d3472d8e?source=collection_archive---------23-----------------------

了解如何使用 Neo4j 图形数据科学训练您的自定义 node2vec 算法

我上一篇关于将图形与 NLP 技术相结合的博文是迄今为止最成功的。这促使我写更多关于这个话题的东西。在我的研究过程中,我偶然发现了 node2vec 算法,并注意到用 Neo4j图形数据科学库来实现它是多么容易。我想这让我别无选择,只能戴上我的 Neo4j 数据科学眼镜并展示实现它是多么容易。

图形导入

今天我们将使用 Kaggle 上的匙羹鱼食物数据集。它包含营养信息以及 1600 多种菜肴中使用的配料。不幸的是,它没有包含酸奶面包的配方。

图表模式

图形模式中有三种类型的节点。一道菜由一种或多种食材组成,我们将其表示为一道菜与其食材之间的联系。食谱分为不同的类别或类型,如午餐、早餐等等。我们使用apoc.schema.assert过程来定义图表模式。它允许我们在一个查询中描述多个索引和唯一约束。

CALL apoc.schema.assert(
  // define indexes
  null,
  // define unique constraints
 {Ingredient:['name'], Dish:['id'], DishType:['name']})

在执行导入查询之前,我们必须下载数据集并将其复制到 Neo4j 导入文件夹中。在导入查询中,我们做了一点点预处理,将配料的名称小写,并用空格替换破折号(-)。

LOAD CSV WITH HEADERS FROM "file:///newfood.csv" as row
CREATE (d:Dish{id:row.id})
SET d += apoc.map.clean(row, ['id','dishTypes','ingredients'],[])
FOREACH (i in split(row.ingredients,',') | 
    MERGE (in:Ingredient{name:toLower(replace(i,'-',' '))}) 
    MERGE (in)<-[:HAS_INGREDIENT]-(d))
FOREACH (dt in split(row.dishTypes,',') | 
    MERGE (dts:DishType{name:dt}) 
    MERGE (dts)<-[:DISH_TYPE]-(d))

基本图形探索

首先,我们将进行一些图形探索。我们来看看哪些食材用的最多。

MATCH (n:Ingredient) 
RETURN n.name as ingredient, 
       size((n)<--()) as mentions
ORDER BY mentions DESC 
LIMIT 10

结果

橄榄油是迄今为止最受欢迎的,因为它在超过一半的食谱中使用。慢慢接着是大蒜、盐和黄油。我不知道黄油如此受欢迎。我也发现凤尾鱼被如此广泛地使用是相当令人惊讶的。或者也许数据集只是偏向于含有凤尾鱼的菜肴。

我们可以在这个数据集的基础上构建一个应用程序,根据我们想要烹饪的配料来搜索食谱。我从马克·尼达姆Lju Lazarevic 写的什么是烹饪系列中借用了这个密码查询。比方说,你今天想吃西葫芦和羊乳酪,但不知道该吃哪种食谱。幸运的是,我们的应用程序可以通过下面的 cypher 查询帮助我们解决这个问题。

WITH ["feta cheese", "zucchini"] as ingredients
MATCH (d:Dish)
WHERE 
  all(i in ingredients WHERE exists(
  (d)-[:HAS_INGREDIENT]->(:Ingredient {name: i})))
RETURN d.title AS dish
ORDER BY size(ingredients)
LIMIT 10

结果

我们可以配沙拉或鱼。我想我会跳过去 node2vec 吃甜点。

Node2vec 算法

node2vec 算法相对较新。它是在 2016 年由 Jure Leskovac 和 Aditya Grover 在一篇文章 node2vec:可扩展的网络特征学习中提出的。要了解它是如何工作的,首先要了解 word2vec 算法。Word2vec 算法是由谷歌的托马斯·米科洛夫领导的研究团队在 2013 年提出的。使用神经网络来学习单词嵌入是一种流行的技术。它将一个句子列表作为输入,并为文本语料库中出现的每个单词生成一个向量或嵌入。词义相近的词在嵌入空间上要更近一些。比如苹果和梨应该比苹果和汽车更相似。word2vec 有两种训练算法。第一种方法被称为连续单词袋(CBOW),它使用单词的上下文来预测目标术语。上下文被定义为出现在文本中目标单词附近的单词。第二种方法叫做跳格法。它不是试图从上下文中预测目标单词,而是试图预测给定术语的上下文。如果您想了解更多关于 word2vec 算法的知识,互联网上有大量关于它的好文献。

你可能会问我们是如何从 word2vec 到 node2vec 的。这其实很简单。我们不使用句子列表作为输入,而是使用随机漫步列表。这是唯一的区别。

Neo4j 图形数据科学库

Neo4j 图形数据科学库支持随机游走算法,这使得我们实现 node2vec 算法变得非常容易。如果你需要快速复习一下 GDS 图书馆是如何运作的,你可以看看我之前的博客文章。我们将从投影内存中的图形开始。我们将所有三个节点标签和项目关系描述为无向的。

CALL gds.graph.create('all',
    ['Dish', 'Ingredient'],
    {undirected:{type:'*', orientation:'UNDIRECTED'}})

现在我们准备训练我们的第一个 node2vec 模型。该流程将包括三个部分:

  1. 从图中的每个节点开始执行随机行走算法
  2. 将随机漫步输入 word2vec 算法
  3. 通过查看最相似的邻居来检查结果

随机行走算法有一个可选的start参数,可以用来定义行走的起始节点。我们还可以用steps 设置指定行走的长度,用walks参数指定行走的次数。请注意,每次执行随机漫步时,我们都期望得到不同的结果。

我们将使用 gensim 库中的 Word2vec 算法实现。它还有几个我们可以定义的超参数。最值得注意的是:

  • 大小:嵌入向量的维数
  • 窗口:当前字和预测字之间的最大距离
  • min_count :训练模型时要考虑的最小字数;出现次数少于此计数的单词将被忽略。
  • sg :训练算法:跳格 1;否则默认 CBOW

查看官方文档了解更多关于 word2vec 超参数的信息

结果

[('anchovy fillet', 0.6236759424209595),
 ('pork shoulder roast', 0.6039043068885803),
 ('penne', 0.5999650955200195),
 ('cherry', 0.5930663347244263),
 ('cooked quinoa', 0.5898399353027344),
 ('turkey', 0.5864514112472534),
 ('asiago cheese', 0.5858502388000488),
 ('pasillas', 0.5852196216583252),
 ('fresh marjoram', 0.5819133520126343),
 ('prunes', 0.5735701322555542)]

如果我知道有这么简单,我早就写 node2vec 算法了。另一方面,结果有点可疑。我不知道这个数据集和凤尾鱼有什么关系。看起来食谱大多是由真正喜欢它们的人写的。你可能会得到完全不同的结果。

最初的 node2vec 论文中,作者定义了两个控制随机漫步执行的参数。第一个是返回参数。

返回参数 ,p .参数 p 控制在行走中立即重访一个节点的可能性。将其设置为较高的值(> max(q,1))确保我们不太可能在接下来的两步中对已经访问过的节点进行采样(除非遍历中的下一个节点没有其他邻居)。该策略鼓励适度探索,并避免采样中的 2 跳冗余。另一方面,如果 p 较低(< min(q,1)),它将导致遍历返回一步(图 2),这将使遍历“局部”靠近起始节点 u。

第二个参数称为输入输出参数。

In-out 参数 ,q .参数 q 允许搜索区分“向内”和“向外”节点。回到图 2,如果 q > 1,则随机行走偏向于靠近节点 t 的节点。这种行走相对于行走中的开始节点获得基础图的局部视图,并且在我们的样本包括小局部内的节点的意义上近似 BFS 行为。相反,如果 q < 1,walk 更倾向于访问离节点 t 更远的节点。这种行为反映了鼓励向外探索的 DFS。然而,这里的一个本质区别是我们在随机游走框架内实现了类似 DFS 的探索。因此,被采样的节点与给定的源节点 u 的距离不是严格递增的,但是反过来,我们受益于易处理的预处理和随机行走的优越采样效率。注意,通过将πv,x 设置为行走 t 中前一节点的函数,随机行走是二阶马尔可夫的。

总之,return 参数指示随机漫步多长时间回溯一步或两步。进出参数控制随机行走是更侧重于局部探索(类似于 BFS)还是更倾向于向外探索(类似于 DFS)。尽管随机游走算法仍处于 alpha 层,但它支持这两个 node2vec 参数。让我们在实践中尝试一下。

结果

[('leg of lamb', 0.7168825268745422),
 ('anise seeds', 0.6833588480949402),
 ('basic bruschetta', 0.6759517192840576),
 ('dried chilli flakes', 0.6719993352890015),
 ('tuna in olive oil', 0.6697120666503906),
 ('spaghetti pasta', 0.669307291507721),
 ('prime rib roast', 0.661544919013977),
 ('baby artichokes', 0.6588324308395386),
 ('rice vermicelli', 0.6581511497497559),
 ('whole wheat fusilli', 0.6571477651596069)]

看结果让我很饿。羊腿和橄榄油要不要算类似食材,真的不好说。如果我们观察图表,在八个包含羊腿的食谱中,有七个也使用橄榄油。按这种逻辑,两者颇为相似。

在下一个例子中,我们将展示如何运行 node2vec 算法并将结果嵌入存储回 Neo4j。我们将返回内部的 Neo4j 节点 id,而不是返回菜肴和配料的标题。这将有助于我们有效地将结果链接回 Neo4j。

这些嵌入现在在 word2vec 模型的词汇表中可用。我们将使用UNWIND cypher 语句将它们一次性存储到 Neo4j 中。如果可能的话,尽量避免每行提交一个事务,因为这不是很高效。

Word2vec 模型使用余弦相似度来查找最相似的单词。图形数据科学库还支持余弦相似度算法,可用于推断相似度算法。与所有相似性算法一样,我们必须微调similarityCutofftopK参数以获得最佳结果。它们直接影响推断的相似性图的稀疏程度。

MATCH (node) 
WITH id(node) as id, node.embedding as weights 
WITH {item:id, weights: weights} as dishData 
WITH collect(dishData) as data 
CALL gds.alpha.similarity.cosine.write({
    nodeProjection: '*', 
    relationshipProjection: '*', 
    similarityCutoff:0.5, 
    topK:5, 
    data: data,
    writeRelationshipType:'COSINE_SIMILARITY'}) 
YIELD nodes, similarityPairs 
RETURN nodes, similarityPairs

结果

为了完成这个分析,我们将使用标签传播算法检查推断网络的社区结构。由于我们只对社区结构的大致轮廓感兴趣,我们可以使用算法的stats模式为我们提供一些基本的社区结构统计数据。

CALL gds.labelPropagation.stats({
    nodeProjection:'*', 
    relationshipProjection:'COSINE_SIMILARITY', 
    maxIterations:20}) 
YIELD communityCount, communityDistribution
RETURN communityCount,
       apoc.math.round(communityDistribution.p50,2) as p50,
       apoc.math.round(communityDistribution.p75,2) as p75,
       apoc.math.round(communityDistribution.p90,2) as p90,
       apoc.math.round(communityDistribution.p90,2) as p95,
       apoc.math.round(communityDistribution.mean,2) as mean,
       apoc.math.round(communityDistribution.max,2) as max

结果

标签传播算法在相似性网络中找到 118 个组。其中大多数成员不到 40 人。有一些大型社区,最大的有 393 名成员。

结论

node2vec 算法是一种学习图中节点的低维表示的有用方法,可以在机器学习管道的下游使用。在这篇博文中,我意识到改变随机游走算法参数以及 word2vec 超参数可以产生非常不同的结果。尝试一下,看看什么最适合你。

和往常一样,代码可以在 GitHub 上获得。

正则化方法:用于改进深度学习模型的噪声

原文:https://towardsdatascience.com/noise-its-not-always-annoying-1bd5f0f240f?source=collection_archive---------16-----------------------

将随机噪声引入训练过程

当你开始学习神经网络时,你学到的第一个概念是 过拟合欠拟合 的含义。有时,训练一个完美概括数据的模型是一项挑战,尤其是当您有一个小数据集时,因为:

  • 当您使用小数据集训练神经网络时,网络通常会记住训练数据集,而不是学习我们数据的一般特征。因此,该模型在训练集上表现良好,在新数据(例如:测试数据集)上表现不佳
  • 一个小的数据集不能很好地描述我们的问题,因此,它可能会导致一个难以学习的问题。

获取更多的数据是一项非常昂贵和艰巨的任务。然而,有时你可以应用一些技术(正则化方法)来获得更好的模型性能。

在本文中,我们将重点关注使用噪声作为神经网络中的正则化方法。这种技术不仅减少了过度拟合,而且还可以更快地优化我们的模型,提高整体性能。

你可以在我的 GitHub 中找到完整的代码!😃

目标

这一条的目标如下:

  • 使用 sklearn 生成合成数据
  • 正则化方法
  • 训练一个基本的神经网络作为基线(MLP)
  • 使用噪波作为正则化方法-输入图层
  • 使用噪波作为正则化方法-隐藏层
  • 使用噪声作为正则化方法-输入和隐藏层
  • 网格搜索以查找模型最佳性能的值

正则化方法

训练一个机器学习模型是一个挑战,它将在以前看不见的输入上表现良好,而不仅仅是那些我们的模型被训练的输入。这个特性被称为 泛化 对未观测到的输入表现良好。有一些像训练测试分割交叉验证的方法来衡量我们的模型有多一般化。

我们可以将模型的性能分为三种情况:

  • 该模型在训练数据集和新数据上表现不佳— 欠拟合模型。
  • 该模型在训练数据集上表现良好,而在看不见的数据上表现不佳— 过拟合模型。
  • 该模型学习我们的训练数据集,并在看不见的数据上表现良好,它能够进行归纳— 良好拟合模型

在我们的问题中更有可能面临过拟合模型因此,在训练期间监控性能以检测其是否过拟合是很重要的。通常在训练过程中绘制准确度的演变和损失,以检测常见模式。

合身、合身和合身

正则化 是修改我们的学习算法,减少它的泛化误差而不是训练误差。神经网络中最常见的正则化方法有:

  • 丢弃 :以概率 p. 在每次迭代中关闭某个神经元
  • 提前停止 : 提供在模型开始溢出之前可以运行多少次迭代的指导。
  • 权重约束 : 将权重缩放到预定义的阈值。
  • 噪声 : 将随机噪声引入训练过程。

这些方法在神经网络中很流行,其中大多数已被证明可以减少过拟合。然而,噪声对深度学习模型的影响从未被系统地研究过,准确性提高的潜在原因也没有。上述观察的一个假设是放松一致性将随机噪声引入训练过程。这隐含地减轻了模型的过度拟合,并且更好地概括了模型以分类测试数据。

使用 Sklearn 生成数据

我们想了解在过度拟合的神经网络中使用噪声作为正则化方法的效果,我们决定使用二元分类问题来解释这一点。因此,我们将应用 sklearn 生成一个二进制数据集,具体来说就是生成 2 个二维同心圆的make_circles。这些参数是:

  • n_samples=100(生成的总点数)
  • noise=0.09(加到数据上的高斯噪声的标准偏差)
  • param_random=24(通过多个函数调用传递一个 int 以获得可再现的输出)

生成并绘制数据我们数据

培训用数据

我们需要评估我们的网络的性能,看看我们是否有过度拟合,因此,我们需要分割我们的数据,以生成另一个数据集x_test进行测试。我们将数据分为train_set (30%)和test_set (70%)。

因为我们需要强制过度拟合,所以我们为我们的训练集选择了较小的大小(30%),因为我们希望创建一个不会概括我们的数据并且在测试数据集上具有较高错误率的神经网络。

分割和绘制我们的训练和测试数据

我们可以绘制出X_trainX_test的分布图:

训练和测试集的分布

我们选择了这种类型的数据,称为圆形数据,,因为这些类是不可线性分离的(我们不能使用直线分割我们的数据)。为此,我们需要一个神经网络来解决这个非线性问题。

因为我们需要在我们的模型中找到过度拟合,以作为一种正则化方法来研究噪声的影响,所以我们只生成了 100 个样本。这是一个训练神经网络的小样本,它使我们能够过拟合训练。

第一步:基本神经网络——MLP

为了研究噪音如何影响我们的训练,我们训练了一个基本的神经网络作为基线。我们定义了一个多层感知器(MLP) 来解决我们的二元分类问题。

第一层是使用400 nodesrelu激活函数的隐藏层。在输出层,我们使用了一个sigmoid,因为我们想要预测 0 或 1 的类值。我们使用binary_crossentropy作为损失(适用于二元分类),使用adam作为优化器。

我们为5000 epochs训练神经网络,并使用X_testy_test作为验证数据。

基本神经网络作为基线

我们绘制了一个图表来表示训练集和测试集的准确性和损失。可以观察到,我们的神经网络具有过拟合,因为该图具有过拟合模型的预期形状,test accuracy增加到一点,然后再次开始降低。同时,loss是发散性的。

基本神经网络训练精度和损失的演变

结果基本神经网络

我们可以观察到,测试机组的精度约为train_acc=1,测试机组的精度约为test_acc=0.5857。它在训练集上表现出比在测试数据集中更好的性能;这可能是过度合身的迹象。****

现在,我们将使用 Keras 的Gaussian Noise Layer添加噪声,并比较结果。该层应用加性的零中心高斯噪声,这对于减轻过拟合是有用的。高斯噪声(GS)是实值输入破坏过程的自然选择。

这个正则化层只在训练时有效。

但是什么是高斯噪声呢?

高斯噪声 是概率密度函数(PDF)等于正态分布的统计噪声。它也被称为高斯分布。高斯随机变量𝑧的概率密度函数𝑝由下式给出:

概率密度函数

其中𝑧代表灰度级,𝜇代表平均值,𝜎代表标准差。综上所述,噪声可能呈现的值是高斯分布的。

2 个概率密度函数—高斯噪声

为了理解高斯噪声的含义,假设我们有一幅图像,并绘制了两个概率密度函数。如果我们观察红色 PDF: 噪声的平均值将是-2 。因此,平均而言,图像的所有像素将减去 2。但是,如果我们观察橙色的 PDF,平均值是 3 。所以平均来说,所有像素加 3。例如,如果我们拍摄这张图像,并应用高斯噪声:

左:原始图像—右:带有高斯噪声的图像

我们可以检查每个图像的直方图,以评估应用高斯噪声的效果:

直方图—左侧:原始图像。右图:带有高斯噪声的图像

虽然我们已经用图像解释了高斯噪声,但是在 Keras 中应用高斯噪声作为正则化方法的方法应用了相同的理论。

添加噪声会增加我们的训练数据集的大小。当我们训练神经网络时,随机噪声被添加到每个训练样本中,这是数据扩充的一种形式。此外,当我们使用噪声时,我们增加了数据的随机性,并且模型不太能够从训练样本中学习,因为它们在每次迭代中都是变化的。因此,神经网络学习更多的一般特征,并具有更低的泛化误差。

当我们应用噪声时,我们在训练样本的附近创建新的样本,因此,输入数据的分布被平滑。这使得神经网络更容易从我们的数据中学习。

神经网络中的输入层噪声

我们将添加一个高斯噪声层作为输入层,我们将分析这是否有助于提高泛化性能。当我们添加噪声时,我们会创建更多的样本,并使数据分布更加平滑。

具有输入层噪声的神经网络

在线图中可以看出,由于我们在训练中引入的具有噪声的点与训练数据集的点冲突,噪声导致模型的准确性和损失跳跃。我们使用std=0.1作为输入噪声,这可能有点高。

精度的演变和训练损失——输入层噪声

通过在输入层使用噪声作为正则化方法,我们减少了模型中的过拟合,此外,我们还改进了test_accuracy=0.642

结果神经网络-输入层噪声

神经网络中的隐含层噪声

现在,我们将尝试用高斯噪声创建一个隐藏层。这必须在应用激活功能之前完成。我们将使用 0.1 的标准偏差,也是任意选择的。

具有隐含层噪声的神经网络

训练精度的演变和损失——隐含层噪声

在这种情况下,可以看到train_accuracy保持不变,尽管我们设法增加了test_accuracy=0.671。似乎将噪声添加到我们的模型中允许改进神经网络的训练,并且对于减轻过拟合是有用的。

结果神经网络—隐藏层噪声

神经网络中的输入+隐含层噪声

我们结合了前面的两个例子,通过同时添加一个input layer noise和一个hidden layer noise来研究我们的模型的性能。我们将使用 0.1 的标准偏差,也是任意选择的。

输入+隐含层噪声的神经网络

训练——输入+隐含层噪声——精度和损失的演变

再次可以看到,随着噪声的使用,如input_layerhidden_layer,同时,我们减少了模型中的过拟合。此外,它增加了test_accuracy=0.6857,似乎高斯噪声作为一种正则化方法允许模型更好地概括我们的数据。

结果神经网络—输入+隐藏层噪声

应用噪声,我们在训练样本附近创建新的样本,从而平滑输入数据的分布。

网格搜索-噪波图层

我们将开发一个网格搜索来找出噪声的确切数量和隐藏层中的节点,从而使我们能够获得性能最佳的模型。

我们将使用带有隐藏层噪声的神经网络作为网格搜索的例子。我们需要用模型创建一个函数来搜索噪声的最佳值。

网格搜索-隐藏图层噪波

我们已经创建了一个名为grid_values的字典,其中包含了模型中每个参数的值的范围。最后,我们将模型create_model()插入到名为KerasClassifier的包装器中,该包装器实现了 Scikit-Learn 分类器接口。

计算网格搜索

**Best: 0.833333 using {'nodes': 300, 'noise_amount': 0.001} 0.766667 (0.133333) with: {'nodes': 50, 'noise_amount': 0.001} 0.766667 (0.133333) with: {'nodes': 50, 'noise_amount': 0.01} 0.766667 (0.133333) with: {'nodes': 50, 'noise_amount': 0.1} 0.766667 (0.081650) with: {'nodes': 50, 'noise_amount': 0.2} 0.700000 (0.066667) with: {'nodes': 50, 'noise_amount': 0.7} 0.633333 (0.124722) with: {'nodes': 50, 'noise_amount': 1} 0.800000 (0.163299) with: {'nodes': 100, 'noise_amount': 0.001} 0.800000 (0.163299) with: {'nodes': 100, 'noise_amount': 0.01} 0.766667 (0.133333) with: {'nodes': 100, 'noise_amount': 0.1} 0.800000 (0.124722) with: {'nodes': 100, 'noise_amount': 0.2} 0.766667 (0.169967) with: {'nodes': 100, 'noise_amount': 0.7} 0.666667 (0.105409) with: {'nodes': 100, 'noise_amount': 1} 0.833333 (0.149071) with: {'nodes': 300, 'noise_amount': 0.001} 0.800000 (0.163299) with: {'nodes': 300, 'noise_amount': 0.01} 0.766667 (0.133333) with: {'nodes': 300, 'noise_amount': 0.1} 0.833333 (0.105409) with: {'nodes': 300, 'noise_amount': 0.2} 0.666667 (0.105409) with: {'nodes': 300, 'noise_amount': 0.7} 0.633333 (0.124722) with: {'nodes': 300, 'noise_amount': 1} 0.800000 (0.163299) with: {'nodes': 500, 'noise_amount': 0.001} 0.800000 (0.163299) with: {'nodes': 500, 'noise_amount': 0.01} 0.800000 (0.124722) with: {'nodes': 500, 'noise_amount': 0.1} 0.833333 (0.105409) with: {'nodes': 500, 'noise_amount': 0.2} 0.600000 (0.133333) with: {'nodes': 500, 'noise_amount': 0.7} 0.600000 (0.133333) with: {'nodes': 500, 'noise_amount': 1}**

我们可以看到,使用在隐藏层中具有300 neurons和具有大约 83%精确度的noise_amount=0.001的网络获得了最好的结果。

未来的实验

我们可以用下面的想法来改进这个添加噪声作为正则化方法的实验:

  • 用噪波添加更多的层来研究他的效果。
  • 用更深层次的神经网络重复同样的实验。
  • 在没有过度拟合的情况下,在模型中研究噪声作为正则化方法的影响。
  • 尝试在激活和权重中添加噪声。

欢迎建议和评论。关注我,感谢你的阅读!😃

带 ML 的非母语口音反馈

原文:https://towardsdatascience.com/non-native-spanish-speaker-accent-feedback-with-ml-7f33f9a0fbb7?source=collection_archive---------37-----------------------

使用谷歌云平台评估 20 多种语言的口音

乔恩·泰森在 Unsplash 上的照片

一位非母语人士正在学习西班牙语。你如何利用机器学习对他们的发音提供实时反馈?在本帖中,我们将介绍如何使用谷歌的语音转文本 API 在 20 多种语言中实现这一点。

如果您可以访问包含给定单词的非本地和本地语音记录的数据库,则可以很容易地进行口音识别。事实上,机器学习甚至可能不是必要的——人们可以比较音频片段的频谱图和梅尔频率倒谱系数。对于那些不熟悉的人来说,频谱图和 Mel 系数代表录音中的频率/音高。对本地和非本地录音的系数进行简单的比较就可以做到这一点。

重音不正确的“Hola”声谱图

适当重音的“Hola”声谱图

图中是两张“Hola”的光谱图。第一个声谱图显示不正确的重音,而第二个声谱图显示正确的重音。人们可以计算两个图形之间的差异来量化发音之间的相似性。然而,这种方法并不可靠。不同的音调会改变计算结果以及说话的速度。此外,如前所述,这种方法需要来自母语使用者的录音数据库。

然而,如果没有录音数据库,我们必须采用不同的解决方案。我们可以使用谷歌的语音转文本 API,而不是创建自己的模型。谷歌的模型已经根据母语人士的声音进行了训练,因此只能识别与母语人士的声音足够相似的录音。因此,如果谷歌的文本到语音模型能够识别我们的发音,我们就可以假设我们正确地发音了。正如我们将看到的,如果我们提供一个带有刺耳口音的音频剪辑,模型将无法识别该语音。

我们开始吧

1.如果您还没有 Google Cloud 帐户,请务必先创建一个。https://cloud.google.com/

2.在 Google Cloud 中创建一个新项目(您可以从您的 Google Cloud 控制台执行此操作)。

3.启用语音转文本 APIhttps://console . cloud . Google . com/APIs/library/speech . Google APIs . com

4.录制自己朗读西班牙语单词,并将音频剪辑保存为 MP3。

5.安装 python 谷歌云语音库

pip install google-cloud-speech

6.如果您没有应用程序密钥,请创建一个。https://cloud . Google . com/docs/authentic ation/get-started

7.将这一行添加到 python 文件的开头,以使用密钥

import os
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = PATH TO YOUR APPLICATION KEY.json

7.将这段 python 代码添加到语音到文本识别中。该功能将转录音频,并给出一个置信度得分。

from google.cloud import speech_v1p1beta1
client = speech_v1p1beta1.SpeechClient()def sample_recognize(local_file_path):
    """
    Print confidence level for individual words in a transcription of a short audio
    file.Args:
      local_file_path Path to local audio file, e.g. /path/audio.wav or .mp3
    """client = speech_v1p1beta1.SpeechClient()# When enabled, the first result returned by the API will include a list
# of words and the confidence level for each of those words.

    enable_word_confidence = True# The language of the supplied audio
    language_code = "es-ES"
    config = {
        "enable_word_confidence": enable_word_confidence,
        "language_code": language_code,
        "encoding": "MP3",
        "audio_channel_count": 2}
    with io.open(local_file_path, "rb") as f:
        content = f.read()
    audio = {"content": content} response = client.recognize(config, audio, ) if len(response.results == 0):
        return "FAILED" result = response.results[0] alternatives = result.alternatives[0]

    return result

请注意几个要素:

  • 通过设置 enable_word_confidence = True,模型将输出每个单词的概率,这允许我们更精确地看到用户的表现如何
  • language_code = "es-ES "将语言从西班牙设置为西班牙语。如果你想改变语言或国家,语言代码是 https://cloud.google.com/speech-to-text/docs/languages
  • “audio _ channel _ count”:2 对应于您的话筒设置方式。大多数电脑使用立体声音频(双声道)录音,但如果您的电脑只在一个声道录音,您可能需要更改这一点
  • 请注意,如果 Google 的 API 无法识别这个单词,它将返回一个空列表,因此 if len(response.results) == 0
  • 变量 alternatives 提供了该函数中未使用的替代结果列表

通过检查该函数的输出是否等于您试图发音的单词,您可以评估您的口音。为了得到更精确的分数,你可以在结果中使用置信度这个词。

我已经在 react 网站上实现了这种口音识别算法:【https://hablame.org/accent。

带口音识别软件的 Flask App 代码:https://github.com/DanielLongo/AccentRecognition

非参数元学习

原文:https://towardsdatascience.com/non-parametric-meta-learning-bd391cd31700?source=collection_archive---------42-----------------------

这个故事涵盖了非参数少镜头学习算法,其中包括暹罗网络,匹配网络和原型网络。本课程是对课程‘斯坦福 CS330:多任务和元学习,2019 |第四讲——非参数元学习者’的简短总结。

via Wor tart

这个故事涵盖了非参数少镜头学习算法,其中包括暹罗网络,匹配网络和原型网络。它还涵盖了元学习算法的属性。这是课程的总结‘斯坦福 CS330:多任务和元学习,2019 |第四讲——非参数元学习者’

非参数方法

非参数方法是简单的,并且在 ML 中的低数据状态下工作良好,例如最近邻。在元测试期间,少量学习正好处于低数据状态,因此这些非参数方法可能表现得相当好。但是在元训练期间,我们仍然希望参数化,因为我们希望能够扩展到大型数据集。非参数方法的关键思想是我们能使用参数元学习器来产生有效的非参数学习器吗?

将测试图像与训练图像进行比较。来源:课程幻灯片

关键思想是使用非参数学习器,例如最近邻。方法是获取一个测试数据点,并将其与所有训练数据集数据点进行比较,找到看起来最相似的一个训练数据,然后返回与该训练数据对应的标签。问题是你在什么空间比较?用什么距离度量?我们可以在像素空间中用 L2 距离来做这件事。

像素空间中的 L2 距离效果不佳。来源:课程幻灯片

但是 L2 距离效果不佳。例如,L2 距离会选择右边的图像作为与中间的图像最相似的图像。因此,我们可以使用元训练数据来学习比较,而不是使用像素空间中的 L2 距离。

暹罗网络

暹罗网络。来源:课程幻灯片

一种方法是训练连体网络来预测两个图像是否是同一类。所以你本质上只是在学习比较成对的图像,并对它们是否属于同一类进行分类。你可以在两个图像之间了解到更多的语义距离。因此,您可以从 met-training 数据集中获取两幅图像,并根据它们是否属于同一类,将这两幅图像标记为 1 或 0。对元训练数据集中的不同图像对重复这一过程。在元测试时,我们将每个图像 X-test 与该任务的训练数据集中的每个图像进行比较,然后输出与最接近的图像对应的标签。简而言之,在元训练时,我们训练这个二元分类器,然后在元测试时,我们通过进行每一个两两比较来执行 N 向分类。既然元训练(训练一个二元分类器)和元测试(测试一个 n 路分类器)互不匹配,我们能不能做得更好来匹配这两个过程?

匹配网络论文中的关键思想是:如果我们要在测试时做最近邻以便将我们的测试查询图像与我们的每个训练数据点匹配,我们 训练一个嵌入空间以便最近邻产生准确的预测 怎么样?

匹配网络。来源:课程幻灯片

因此,我们将训练数据集中的每幅图像放入一个学习过的嵌入空间。我们还将测试查询图像嵌入到一个嵌入空间中。我们比较每一个嵌入来做一个预测。因此,这些黑点中的每一个(其中 fθ点)将对应于测试嵌入和训练嵌入之间的比较。我们取对应于我们的每个训练图像的标签,并且我们的预测将对应于由它们的相似性分数加权的训练标签。 对模型进行端到端训练。 最重要的是,元训练是为了展示元测试中发生的事情。在元训练期间,你对训练数据集中的所有图像进行比较,在元测试时,你做同样的事情,对每个 n 向分类问题进行预测。

非参数方法的一般算法。来源:课程幻灯片

非参数方法的通用算法与摊销(黑盒)方法的算法基本相同。我们首先对一组任务进行采样(步骤 1),对每个任务的训练和测试数据集进行采样(步骤 2),然后使用学习到的相似性度量计算预测(步骤 3)。注意这里不同于参数方法,我们没有参数 phi,它本质上被整合到这个比较中。然后,一旦我们有了这些预测,我们就根据我们的预测在测试集上有多准确的损失函数来更新这个学习的嵌入函数的参数(步骤 4)。例如,这个损失函数类似于交叉熵,我们使用测试标签上的预测分布,而不仅仅是 max 标记的输出。

对于每个类都有一个示例的一次性分类,匹配网络非常简单,因为它会对每个类进行比较。但是如果我们有不止一次机会呢?如果每个类别有多个数据点,那么匹配网络会独立执行这些比较。也许我们可以用一种比执行这些独立的比较更聪明的方式来聚合每个类的信息。这就是原型网络所做的。

原型网络

原型网络聚集类信息以创建该类的原型嵌入,然后对这些原型类嵌入中的每一个进行比较,以便预测对应于我们的测试图像的标签。

原型网络。来源:课程幻灯片

所以这看起来更具体的是,我们将有许多不同类别的图像。在左图中,不同的颜色对应于我们针对特定任务的训练数据集中的不同图像类别。我们将每个训练图像嵌入到这个嵌入空间中。然后在这个嵌入空间中取平均值,以便计算类别 1、2 和 3 的原型嵌入。然后,我们将测试图像嵌入到相同的空间,相同的精确空间,并计算到每个原型类嵌入的距离。最后,我们可以输出它在这个嵌入空间中最接近的类。

原型网络方程。来源:课程幻灯片

该等式表明,它会将特定类别的每个图像嵌入到该嵌入空间中,然后对这些图像中的每个图像取平均值。为了计算我们的测试数据点的类别,我们将获取每个类别中嵌入的测试数据点之间的距离,并对每个负距离执行 softmax,以便计算测试数据点的概率。在这种情况下,d 对应于欧几里德距离或余弦距离。

其他非参数方法

基本上,这些非参数方法嵌入你的数据点,然后在学习嵌入空间做最近邻。一个挑战是,如果你想推理数据点之间更复杂的关系,而不仅仅是在你的嵌入空间中做最近邻怎么办? 原则上,如果你的嵌入空间中有一个足够有表现力的编码器,那么最近邻应该能够表示广泛的复杂关系,特别是对于高维嵌入空间。但是在实践中,人们发现考虑用更有表现力的方式来进行这种比较是很有用的。

其他非参数方法。来源:课程幻灯片

例如, 关系网络 基本上采用原型网络,并在那些嵌入的基础上学习非线性关系模块。这基本上对应于在原型网络中学习函数 D,而不是使用欧几里德距离度量或余弦距离度量。所以它学习嵌入和距离度量。另一种方法 是代替每个类有一个单一原型,每个类有一个混合原型。举例来说,这允许你在一个类中表现更多的多模态类分布。最后, 另一篇论文 对我们所有的数据点执行嵌入,然后执行某种消息传递方案,以便思考这些不同的数据点如何相互关联,并做出预测的输出。它所做的是使用图形神经网络来执行这种信息传递,并通过它进行区分。

元学习算法的性质

参数方法。首先,我们从计算图的角度对此进行比较。

来源:课程幻灯片

黑盒方法以完全的黑盒方法抑制了这个计算图。基于优化的方法可以视为将优化嵌入到计算图中。这种观点也适用于非参数方法。对于您的测试数据点,原型网络将其嵌入并与您的每个类原型进行比较,其中每个任务原型是使用嵌入的每个类的数据点计算的。

混合动力车型。来源:课程幻灯片

有了这个视图,我们还可以混合计算图的组件来生成混合模型 。因此, 一种方法 有点像是黑盒和基于优化的方法 的混合,或者可能是基于优化的非参数方法(这取决于你看待事物的方式)。这种混合方法试图在嵌入训练数据集的基础上调整模型,并在该模型上运行梯度下降。尽管通过直接方式以及梯度下降对数据进行调节的这些信息来源可能是多余的,但在实践中效果很好。 另一种方式 就是对你的函数进行嵌入,然后在那个嵌入空间上做梯度下降。因此,本文使用关系网络来嵌入您的训练数据集,并考虑不同的数据点如何相互关联。然后他们将这种嵌入解码到神经网络的参数中,对新的数据点进行预测。他们不是在那个函数的参数上运行梯度下降,而是在学习过的嵌入空间 Z 中运行梯度下降,这产生不同的函数。本质上,你可以把它看作是在你的权重的低维空间中运行梯度下降,而不是在你的权重的原始空间中运行梯度下降。 最后一种方法 是做一些看起来完全像 MAML 的事情,但是将网络的最后一层初始化为对应于原型网络 。它基本上是 MAML 网络架构的特定选择的特定形式,初始化它以做类似基于比较的预测的事情。

基于优化的方法(s. tMAML 和 SNAL)在歪斜数字上工作得很好,这在训练时间期间没有被训练;而黑盒方法(metaNet)在非分发任务上表现不佳。来源:课程幻灯片

我们也可以在 算法属性透视图 中比较这三种方法。 一致性表现力 是对大多数应用都很重要的两个属性。E 表达能力是代表一系列学习过程的能力,它衡量一系列领域的可扩展性和适用性一致性意味着学习的学习程序将解决具有足够数据的任务,而不管该任务的性质如何。例如,梯度下降方法对应于一致的学习过程,因为如果我们只是在测试时运行梯度下降,你可以期望给定足够的测试任务数据,无论你的元训练数据是什么,你都能够解决一个任务。一致性将减少对元训练任务的依赖,从而带来良好的分布外(ood)性能

对于监督学习,非常深度的模型通常是富有表现力的 (这对于一些 RL 算法不成立)。因此,黑盒方法具有完全的表达能力,而基于优化的方法对于非常深的模型具有表达能力,而非参数方法对于大多数架构具有表达能力。就一致性而言,黑盒根本不一致,而基于 o 优化的方法是一致的,因为它简化为梯度下降问题。非参数方法在这个意义上是一致的 如果你的嵌入没有丢失关于输入的信息,这对于做决策是很重要的, 那么随着你积累越来越多的数据,它最终会渐近地到达一个任意接近你的测试数据点的数据点,然后能够对那个测试数据点做出正确的预测

这些方法还有其他一些优点(缺点)。由于黑盒方法容易与各种学习问题结合,如监督学习和 RL;但是它通常是数据低效的,因为你需要从头开始训练一个神经网络,并且优化是具有挑战性的,因为在初始化时没有归纳偏差。** 基于优化的方法在肉学习开始时具有正归纳偏差,并且它很好地处理变化的 k 和大 k。例如,如果你的数据比你训练的数据多,这些方法仍然可以很好地工作,因为它们是一致的。它是与模型无关的。但它包括二阶优化,这导致这种方法计算和内存密集型。非参数方法完全是前馈,它们不会在计算图中演化出任何反向传播,因此,它们往往在计算上非常快速并且易于优化。但是,如果你在比它们被训练的更多的 k 上测试它们,它们的表现往往不如其他算法能够达到的。因此,它们很难推广到变化的 K 值很难扩展到非常大的 K 值。况且,到目前为止,他们仅限于分类**。

一般来说,在现有的少数几个基准测试中,每个版本的性能都相当。使用哪种方法取决于您的用例

参考

  1. 斯坦福 CS330:多任务和元学习,2019 |讲座 4——非参数元学习者
  2. T 何航向滑梯
  3. 深度特征作为感知度量的不合理有效性
  4. 用于一次性图像识别的连体神经网络
  5. 用于一次性学习的匹配网络
  6. 少量学习的原型网络
  7. 用于少量学习的无限混合原型— arXiv
  8. 用图形神经网络进行少量学习
  9. 学习比较:少投学习的关系网络
  10. 概率模型不可知元学习— arXiv
  11. 具有潜在嵌入优化的元学习

使用 Python 中的 Choropleth 地图可视化印度尼西亚学校参与率

原文:https://towardsdatascience.com/noobs-guide-to-create-choropleth-map-using-python-geopandas-d6269e9e9a0c?source=collection_archive---------25-----------------------

逐步了解印度尼西亚不同年龄组的学校参与率如何使用 python geopandas 绘制 choropleth 地图

在本文中,我们将通过利用地理空间数据来了解 2019 年印度尼西亚不同年龄组的入学率。这些数据将会用一个 choropleth 图来可视化,我们将会一步一步地分解它来制作它。

费利佩·斯基亚罗利在 Unsplash 上的照片

如今,我们可以很容易地利用地理空间数据。各种应用程序和编程语言为使用这些空间数据提供服务。例如,众所周知,ArcGIS 和 QGIS 是处理空间数据的常用应用程序。

另外,数据科学家常用的两种编程语言,如 R 和 Python,提供了一个可以处理这项任务的库。但是这次我们将只讨论 python 中的一个库,它就是 GeoPandas。

这个 choropleth 是什么?根据维基百科:

宗谱图是一种专题地图,其中各区域按照代表每个区域内地理特征汇总的统计变量的比例进行着色或图案化。

简单来说,这个 choropleth 图是一个用不同颜色表示不同值的图。

谷歌 Choropleth 地图搜索结果

该等值线图可用于显示该区域内某一区域的不同测量值。

因此,让我们深入了解如何使用 Python 中的 GeoPandas 创建 Choropleth 地图。我们将看到印度尼西亚不同年龄组的入学率。

第一步:安装需要的 Python 库

在制作地图之前,我们应该安装 Geopandas 库及其依赖项。GeoPandas 是一个可以帮助我们使用 python 处理地理空间数据的库。该库使用了 pandas 的数据框概念,但具有几何功能。在这个 geopandas 中,几何运算由 shapely 执行。Geopandas 进一步依赖 fiona 进行文件访问,依赖 Descartesmatplotlib 进行绘图。

安装 geopandas 的一种方法是使用 conda,这也是我们将用来创建地图的另一个库。

conda install pandas
conda install matplotlib
conda install numpy
conda install geopandas
conda install descartes

其他方法可以从 geopandas 文档这里查看。然后把图书馆叫进笔记本。

# Library usedimport pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import geopandas as gpd

第二步:下载数据集

在本练习中,我们将使用两个数据集:

  • 将被映射到我们的地图的数据。在这种情况下,我们将使用不同年龄组的印度尼西亚学校参与率。该数据最初来自 Badan Pusat Statistik。然而,在我对数据做了一些预处理之后,我也在我的 GitHub 中做了一个拷贝。你可以在这里下载这些数据
  • 包含几何信息的 shapefile。我们将使用 GADM的印尼省 GeoJSON 格式。这个数据也可以从我的 Github 页面这里下载。其次,是将被映射到我们的地图的数据。

第三步:数据准备

现在,所有的数据都应该已经下载了。因此,我们可以通过将数据导入笔记本来开始准备数据。

首先,我们导入学校参与率数据。该数据由 5 栏组成,第一栏是一个省,其余是不同年龄组的入学率。

# Import School Partitipations Ratepath = './Angka Partisipasi Sekolah.xlsx'
df = pd.read_excel(path)
display(df.head())

其次,我们用 geopandas read_file 函数导入 GeoJSON 数据。此函数将创建地理数据框架类型的数据。

# Import GeoJSON Datapath = './gadm36_IDN_1.json'
df_geo = gpd.read_file(path)
display(df_geo.head())

然后,我们将这些数据集组合成一个地理数据框架,并检查结果。

df_join = df_geo.merge(df, how='inner', left_on="NAME_1", right_on="Province")df_join = df_join[['Province','7-12', '13-15', '16-18', '19-24','geometry']]df_join.head()

第四步:创建地图

通过使用 GeoPandas,此地理数据框架可以在没有数据的情况下轻松绘制。

df_geo.plot()

然而,我们将超越添加数据和一些可定制的地图。我们将在地图底部添加地图标题、颜色条和注释。我们还将删除地图上的轴。

# set a variable that will call whatever column we want to visualise on the mapvalues = '19-24'# set the value range for the choroplethvmin, vmax = 0,100# create figure and axes for Matplotlibfig, ax = plt.subplots(1, figsize=(30, 10))# remove the axisax.axis('off')# add a titletitle = 'School Participations Rate for Age {}'.format(values)
ax.set_title(title, fontdict={'fontsize': '25', 'fontweight' : '3'})# create an annotation for the data sourceax.annotate('Source: Badan Pusat Statistik Indonesia',xy=(0.1, .08),  xycoords='figure fraction', horizontalalignment='left', verticalalignment='top', fontsize=12 ,color='#555555')# Create colorbar as a legendsm = plt.cm.ScalarMappable(cmap='Blues', norm=plt.Normalize(vmin=vmin, vmax=vmax))# add the colorbar to the figurecbar = fig.colorbar(sm)# create mapdf_join.plot(column=values, cmap='Blues', linewidth=0.8, ax=ax, edgecolor='0.8',norm=plt.Normalize(vmin=vmin, vmax=vmax))

接下来,我们可以添加这行代码来在地图上添加省份名称或覆盖值。

# Add Labels Province Namedf_join['coords'] = df_join['geometry'].apply(lambda x: x.representative_point().coords[:])
df_join['coords'] = [coords[0] for coords in df_join['coords']]
for idx, row in df_join.iterrows():
    plt.annotate(s=row['Province'], xy=row['coords'],horizontalalignment='center')

# Add Value Labelsdf_join['coords'] = df_join['geometry'].apply(lambda x: x.representative_point().coords[:])
df_join['coords'] = [coords[0] for coords in df_join['coords']]
for idx, row in df_join.iterrows():
    plt.annotate(s=row['19-24'], xy=row['coords'],horizontalalignment='center')

搞定了。我们的 choropleth 地图已经可以保存和共享了。我们可以通过添加这行代码来保存我们的情节。

fig.savefig('map_export.png', dpi=300)

第五步:制作所有地图

在最后一步中,我们将把代码封装到一个 python 函数中,这样我们就可以循环该函数来绘制地理数据框中的所有值。

def make_plot(geo_df,values):
    # set a variable that will call whatever column we want to visualise on the map
    values = geo_df.columns[values]# set the value range for the choropleth
    vmin, vmax = 0,100# create figure and axes for Matplotlib
    fig, ax = plt.subplots(1, figsize=(30, 10))# remove the axis
    ax.axis('off')# add a title
    title = 'School Participations Rate for Age {}'.format(values)
    ax.set_title(title, fontdict={'fontsize': '25', 'fontweight' : '3'})# create an annotation for the data source
    ax.annotate('Source: Badan Pusat Statistik Indonesia',xy=(0.1, .08),  xycoords='figure fraction', horizontalalignment='left', verticalalignment='top', fontsize=12 ,color='#555555')# Create colorbar as a legend
    sm = plt.cm.ScalarMappable(cmap='Blues', norm=plt.Normalize(vmin=vmin, vmax=vmax))# add the colorbar to the figure
    cbar = fig.colorbar(sm)# create map
    geo_df.plot(column=values, cmap='Blues', linewidth=0.8, ax=ax, edgecolor='0.8',norm=plt.Normalize(vmin=vmin, vmax=vmax))

    # Add Labels
    geo_df['coords'] = geo_df['geometry'].apply(lambda x: x.representative_point().coords[:])
    geo_df['coords'] = [coords[0] for coords in geo_df['coords']]
    for idx, row in df_join.iterrows():
        plt.annotate(s=row['Province'], xy=row['coords'],horizontalalignment='center', color = 'Red')

然后我们调用函数来绘制所有数据。

for i in range(1,5):
    make_plot(df_join,i)

作为总结,我们可以看到不同年龄组的学校参与率在 choropleth 图中的变化。通过这样做,我们可以看到,与早期年龄组相比,老年组的参与率较低。我们可以看到 16 -18 岁年龄段的人数下降,随后是 19-24 岁年龄段的人数大幅下降。这告诉我们,一些印度尼西亚学生只在初中之前上学,没有继续上高中和大学。

查看 19-24 岁年龄组 choropleth 的更多细节,日惹的颜色最深。这意味着这个地区的参与率最高。

在日惹特区,有四所国立大学,大约 16 所私立大学,以及许多专门从事艺术、科学、技术、教育、农业和商业管理等学科的研究所和学院。与其他地区相比,日惹为 19-24 岁年龄段的人提供了更多的学习场所。这也是高中分区背后的原因之一。此外,日惹也因此被印尼人称为“学生城”。

不,从项目中学习不是一件容易的事情

原文:https://towardsdatascience.com/nope-learning-from-projects-is-not-an-easy-task-eb35c64da6e7?source=collection_archive---------52-----------------------

从自己的迷你项目中最大化学习的五个步骤

micha Parzuchowski 在 Unsplash 上的照片

一个月前,我发表了这篇文章,在这篇文章中,我阐述了自己的观点,即为什么单靠在线课程无法帮助我们成为更好的数据科学家。这篇文章的关键是关于应用学习在数据科学中的重要性,它获得了很多积极的关注,并在社交媒体上得到积极的分享。然而,我确实意识到基于项目的学习并不容易,因为它固有的缺乏框架。因此,在这篇文章中,我将尝试更深入地从项目中学习,以及如何最大限度地利用我们在新项目上花费的时间。

虽然我是基于项目或实践学习的严肃支持者,但我想首先说明这种方法的一些局限性。

通过项目自学并非没有缺点

当我们提倡项目和应用学习时,我们需要认识到一个基本事实, “在线课程和 MOOCs 仍然非常受欢迎,是全世界学习者的需求” !就连你和我也经常每周花至少一个小时浏览热门 MOOC 网站,调查所提供的课程类型,我们中的一些人甚至加入了一些课程,但由于其他活动,未能坚持完成。但是,真正的问题是 “如果不是为了证书,为什么课程仍然受到青睐?” 。在我看来,这有三个主要原因—

  • 课程是从接触和理解能力远胜于我们的人那里学习新概念的好方法。从别人已经清楚理解并用更简单的语言解释的东西中学习总是更容易。
  • 基于项目的学习是非结构化的,充满了不确定性。我们大多数人在自学时缺乏制定计划并坚持下去的信念。此外,善变是每个初学者的天性。这并不是因为初学者缺乏专注,只是他们被新概念的虚饰和刺激所驱使。这导致在某个特定领域出类拔萃的能力悄然下降。
  • 基于项目的学习要求我们“量化”我们的进展,这正是我们最害怕的事情之一。我们如何衡量自己在某个领域的专业知识?什么时候我们知道我们已经不仅仅是一个初学者了?

上述三个原因中的两个是基于项目的学习的直接限制,因此,认识到这种学习没有灵丹妙药是相当直观的。

但是等等!如果我们能找到解决这些限制的方法,并打开从我们的迷你项目中有效学习的机会,会怎么样?

周末静修的时间到了

娜塔莉亚·扎里茨卡娅Unsplash 上的照片

谁不喜欢周末度假呢?我们都渴望周末能从繁忙的工作日中解脱出来休息一下。对我个人来说,周末意味着自由。这些时候,我可以工作或学习一些我在大学里由于大量的课堂作业和其他课外活动而无法学习的东西。

废话说够了。让我们开门见山吧。

这个想法是将我们的个人迷你项目视为远离我们必须履行的日常职责的周末休假。对学生来说,这些“日常职责”可以是日常的作业和课程,而对专业人士来说,这些可以是他们的工作。所以,这里有 5 个步骤可以帮助我们把迷你项目当作周末静修,更有效地学习这些!

第一步。计划你的撤退

大多数周末静修都从这一步开始,如果不是每一步的话。我们都会制定一个计划,规划我们的整个旅程,在网上寻找我们可以去的地方和我们可以做的事情,甚至可能拿起一张地图,描绘出我们希望的旅程。

现在,这就是我们需要扩展到我们的迷你项目中的内容——我们需要制定一个计划,并创建我们自己的地图,标出我们在接下来的两天中可以学习的内容。

当我们试图学习时,没有“放之四海而皆准”的计划方法。当我们有一个固定的目标时,计划会起作用,而不是当它像“在 X 领域学习新东西”那样抽象时。然而,既然我们正在谈论把我们的项目作为一个周末静修,让我们同意像计划我们的假期或旅行那样计划我们的项目大纲——一丝不苟。

做到这一点的一个好方法是在我们的计划中创建 4 个部分(如下图所示),并根据我们希望通过个人周末项目实现的目标来填充这些部分。

演职员表:Ramshankar Yadhunath

  • 时间:我们愿意在这件事上花费多少时间,不受其他截止日期或职业约定的干扰?如果你回到你的日常工作中,这就不再是一次静修了!
  • 概念:我们想通过这个迷你项目学习什么概念或工具?事实上,我们想要学习的主题可能会有一个很大的列表,但是我们需要将列表精简为几个主题,这些主题可以作为整个项目的单独部分一起学习。
  • 产出:这个项目的产出会是什么?它会是一个分析报告,可能是一篇博客文章,它会是一个端到端的应用程序,甚至会是公开的吗?没有必要写下或展示我们所做的每一个小项目,尽管互联网强烈建议这样做。
  • 资源:互联网上有哪些文章/链接/资源库/教程/课程可以帮助我们完成这个项目?现在,很多好的资源只有当我们开始真正的工作时才会被发现因此,以后追加到这个列表也没问题。但是,在开始之前至少有一些链接将有助于保持专注。

虽然以上几节提供了一个很好的方法来制定一个明确的计划,但这并不意味着我们要完成或使用其中的所有内容。这样想吧— 多少次,我们精心计划去一个新地方的多个景点,但最后总是错过至少一个景点 😞。但是,这是否意味着一次糟糕的旅行呢?从来没有。

数一数你的点击率比为你的失误而生气要有利得多。

第二步。到达目的地

制定计划后,我们接下来需要收拾行李。本质上,这意味着“为大撤退做好准备”。清单被创建,手提箱被放在上面,关于拿什么和留什么的冲突出现了。

在我们的项目中,“做好准备”有几个含义:

  • 安装必要的库和包
  • 维护一份关于我们想学什么的清单以及监控它的方法
  • 最好是笔记本来记笔记
  • 我们还需要什么吗

预先安装库通常是不可能的,因为我们可能不知道我们需要的所有库。然而,我们可以确保我们至少有初步的,我们可能需要工作。建立一个虚拟环境也与我们正在进行的任何项目高度相关。

维护清单和其他生产力提示本质上是高度主观的,如果每个人都遵循一种似乎对他们很有效的方法,那将是最好的。

最后,在基于项目的学习期间,最好尽量减少我们对社交媒体的使用,避免分心,除非你想带着一桶罪恶感结束。

前期准备的小行动将在主要任务中发挥重要作用。

第三步。享受学习,享受乐趣

到达目的地后,想法通常很简单——玩得开心!

我不知道是否每个读者都觉得学习可以很有趣,但考虑到我们在这个项目中从计划到要使用的工具都是精心挑选的,喜欢我们正在做的事情应该不会有太大的问题!

因为这些迷你项目是我们个人建立技能的尝试,所以最好尝试走出我们在学习中的舒适区。我们最初创建的计划可以作为一个框架,但是不需要考虑这些硬性的规则。我们需要做的就是记录下我们采取的每一个行动。例如,如果我们在进行小型项目时遇到了一个我们感兴趣的新主题或概念,问几个简单的问题可以帮助确定这个主题是否值得追求——

  • 这个主题对生成最终输出有帮助吗?
  • 与概念列表中的现有主题相比,这个主题是否与行业更相关?
  • 有没有好的资源可以深入学习这个话题?
  • 它能在剩下的短时间内学会吗?

根据您的个人需求,您可以添加更多内容。

聪明一点,行使学习带给你的自由。

第四步。记录你的撤退

当然,我们都喜欢拍照和记录我们的假期。这是储存快乐时光记忆的好方法。当然,也是为了向我们的同龄人展示,除了工作,我们还有自己的生活。

然而,我们很多个人迷你项目的最大问题是它们被埋没了。我们甚至不记得我们在一个项目中学到了什么,因为我们从来不愿意把它写下来。所以,当我们最终不得不与某人谈论我们做过的事情时,我们所拥有的只是空洞的话语。老实说,这不太可信。

这里的文档不需要太复杂,简单到足以帮助我们回顾和记住我们曾经做过一些有价值的事情,以及那个项目如何帮助我们学习我们以前不知道的东西。如果我们希望将我们的工作公之于众,这又会有所帮助,因为潜在的采访者或同行会很容易认同我们的努力。 Github 是一个存储你的库和展示你的项目的好地方。

没有被记载的努力工作是从未存在过的工作。

第五步。你回来后

我们中的许多人喜欢在旅行结束后回来,和我们的同伴讨论所有的事情。但是,我们中的一些人甚至不告诉任何人我们的旅行,我们是保守的那种。

同样,一旦我们完成了项目,也没有必要讨论它。然而,这样做将有助于我们从社区获得积极的反馈,如果我们要改进,这样的反馈总是非常重要的。我们可以将我们的项目以博客的形式发布,或者在我们的个人网站上发布,甚至在社区驱动的平台上分享,比如 MadewithML

现在,世界并不都是美好的。当人们批评的时候,他们通常是非常粗鲁的。但是,对我们亲爱的迷你项目的负面评论生闷气就像试图拍一只苍蝇一样没有意义——太费时间,而且通常不值得。相反,我们可以试着认同批评家的思维过程,并利用它来改进。

如果你想提高,学会接受反馈。

为什么这种荒谬会有帮助?

这个问题很重要。乍一看,试图将从事数据科学项目和周末休假相提并论听起来像是极端疯狂的行为。但是,让我回顾一下我们在本文开始时看到的基于项目的学习的 2 个缺点——

  • 基于项目的学习是非结构化的,充满了不确定性
  • 基于项目的学习要求我们“量化”我们的进展,这正是我们最害怕的事情之一。

第一步,即计划我们的撤退,帮助我们围绕我们的项目创建一个局部结构。它非常灵活,但它确实有一个框架让我们保持在正确的轨道上。没有严格遵循计划的牢不可破的规则,但是我们所做的每一个决定都受到它对我们的学习成果 产生积极影响的能力的指导。 在技能培养的宠物项目中,比如这里正在谈论的那些,责任在于我们能学到多少,以及我们如何利用这些来支持我们的成长。

无法量化我们的进展可以通过创建我们自己的度量标准来衡量我们的进展。实现这一点的几种方法(并非详尽无遗)是—

  • 计算在这个周末静修项目中学到的全新主题/概念的数量
  • 对这些新主题中的每一个,用 1-10 的等级来评价你的理解水平。所以,下次你拿起同样的话题作为另一个周末静修项目的一部分时,你就知道你需要改进多少了。
  • 如果你的项目是公开的,向你不认识的人寻求反馈。你可能有很多东西要学。

最后,没有完成我们计划的 100%也没关系。当我们希望通过一个项目学习的 10 个主题对我们来说都是新的时,即使深入学习其中的 5 个也是一项出色的工作(至少对我来说是这样)。

最后几点

最后但并非最不重要的,我不想给你留下无根据的证据或提示,因为那对你没有帮助。下面的链接是我大约一周前用我上面详述的“周末静修”方法做的一个项目。

[## ry05/库里科

为在线课程建立一个简单的课程推荐系统 CouReco 是一个建立在……

github.com](https://github.com/ry05/couReco)

通过参与这个项目,我学到的新概念是—

  • 使用 beautifulsoup4 进行网页抓取
  • 使用 Streamlit.io 部署 ML 应用程序
  • 基于内容推荐器的基本理论

如果这些是你想学习的技能,这个库可能会有所帮助:)

我创建的数据集可以在这里找到。它有 1000 个实例和 14 个特性。你可以在你未来的项目中使用它(如果你曾经使用过它,我会很感激提到它😃)

下一个周末,弄脏你的手,投入到你不懂的事情中去!相信我。这比我们所能理解的更有帮助。

正规方程:线性回归的矩阵方法

原文:https://towardsdatascience.com/normal-equation-a-matrix-approach-to-linear-regression-4162ee170243?source=collection_archive---------43-----------------------

了解 python 中使用法线方程进行线性回归的推导、实现和限制

Unsplash 上拍摄的 ThisisEngineering RAEng

线性回归可能是数据科学和机器学习中最基础的统计模型,它假设输入变量 (x) 和单个输出变量 (y) 之间存在线性关系,并试图通过观察到的数据拟合直线虽然您可能熟悉如何使用梯度下降作为选择的算法来最小化线性回归问题中的成本函数【J(θ)的成本函数,但是我们可以使用另一种方法来解析地获得最佳值,而无需通过梯度下降的多次迭代来获得全局最小值或选择 alpha(学习速率)。**

什么是正规方程?

让我们首先推导正规方程,看看矩阵方法是如何用于线性回归的。

给定以下将输入映射到输出的假设函数,

我们希望最小化最小平方成本函数,

其中 m = 训练样本数,xs =输入变量,ys =第 i 个 样本的输出变量

现在,回归系数 θ 本质上是一个向量,每一个 m 个输入样本也是一个 n+1 维的向量(为方便起见,设 x0 = 1)。因此,在矩阵符号中,我们得到

重写最小平方成本函数并使用矩阵乘法,我们得到,

让我们应用一些矩阵转置恒等式并忽略 (1/2m) ,因为我们将在计算的后面计算导数。我们最后得到一个简化的方程为【J(θ)】****

为了找到上述函数的最小值,我们将找到导数 wrt θ, 并等于 0。

我们假设矩阵 ( X'X) (撇号代表转置)可逆。两边乘以 (X'X)^(-1). 我们只剩下了法线方程,

正态方程

Python 实现:

法线方程在 python 中的实现请参考 jupyter 笔记本这里。我使用了来自 sklearn 库的波士顿房价数据集numpy 包,使用上面推导的矩阵方法计算回归系数。

局限性:

  1. 计算(X’X)然后将其求逆的过程是昂贵的,并且花费 O(N ) 其中 NX 矩阵中的行数/观察数。根据斯坦福大学计算机科学兼职教授吴恩达的说法,法线方程应该避免用于超过 10K 的特征。
  2. 【X ' X】可能是不可逆的,违背了我们的假设。在这种情况下,线性相关的冗余特征可能会被删除,或者像套索这样的正则化方法被用来减少特征的数量。

Python 中的 10 个正态性测试(分步指南 2020)

原文:https://towardsdatascience.com/normality-tests-in-python-31e04aa4f411?source=collection_archive---------1-----------------------

正态性检验用于检查变量或样本是否具有正态分布。

作者形象

在讨论正态性检验之前,让我们先讨论正态分布及其重要性。

正态分布

正态分布也称为高斯分布是一种概率函数,描述了变量值的分布情况。这是一种对称分布,其中大部分观察值落在中心峰值附近,远离平均值的值的概率在两个方向上等量递减,在数据范围的高端和低端有较少的异常值。

高斯分布的术语指的是德国数学家卡尔·弗里德里希·高斯。

正态分布有一些重要的性质:

  1. 平均值、中值和众数都代表分布的中心。
  2. 分布呈钟形
  3. 大约 68%的数据落在平均值的 1 个标准偏差内,大约 95%的数据落在平均值的 2 个标准差内,大约 99.7%的数据落在平均值的 3 个标准差内

图片来自 Christian Hubicki。

为什么它如此重要

正态分布是统计学中最重要的概率分布,因为

  1. 自然界中的许多过程都遵循正态分布,例如人的年龄、身高、体重和血压
  2. 线性回归假设误差或残差遵循正态分布
  3. 有些 ML 算法像线性判别分析和二次判别分析都是在正态分布的假设下推导出来的。

常态检验

在统计学中,正态性检验用于检查数据是否来自高斯分布,或者简单地检查变量或样本是否具有正态分布。

有两种方法可以检验正态性,

  1. 正态性检验图
  2. 正态性统计检验

1。正态性测试图

各种图表可以用来检验变量的正态性。使用图表我们可以直观地看到正态性,但是图表作为统计方法并不十分准确。

1。Q Q 或分位数-分位数图

它绘制了两组相对的分位数,即理论分位数相对于变量的实际分位数。

图片来自作者

如果我们的数据来自正态分布,我们应该看到所有的点都位于直线上。

2。方框图

盒状图也称为盒须图是另一种可视化变量正态性的方式。它显示了基于五个数字汇总的数据分布,即最小值、第一个四分位数(Q1)、中值(Q2)、第三个四分位数(第三季度)和最大值。

图片来自作者

如果你的变量有一个正态分布,我们应该看到中间的均值和中位数。

3。直方图

直方图是一种流行且常用的图形,可以直观地显示数据的分布。它还允许我们检查数据的潜在异常值、偏斜度等。它将数据分成等宽的仓。每个条柱被绘制成一个条形,条形的高度取决于该条柱中数据点的数量。

图片来自作者

如果你的变量有一个正态分布,我们应该看到一个钟形曲线。

2。正态性的统计检验

另一方面,有许多统计测试来检查变量的分布是否为正态/高斯分布。在这一部分,我不会谈论背后的数学,但我会向您展示每个测试的 python 代码。

  1. 夏皮罗-维尔克检验

我们应该从夏皮罗-维尔克试验开始。这是检验变量正态性的最有力的测试。它是由塞缪尔·桑福德·夏皮罗和马丁·维尔克在 1965 年提出的。

图片来自作者

  • 如果p 值≤ 0.05,那么我们拒绝零假设,即我们假设变量的分布不是正态/高斯分布。
  • 如果p 值>为 0.05,那么我们无法拒绝零假设,即我们假设变量的分布为正态/高斯分布。

2。达戈斯蒂诺的 K 平方检验

达戈斯蒂诺的 K 平方检验基于偏度和峰度检查变量的正态性。它是由拉尔夫·达戈斯蒂诺命名的。

偏斜度是对对称性的一种度量。

峰度是衡量数据相对于正态分布是重尾还是轻尾的指标。

图片来自作者

  • 如果p 值≤ 0.05,那么我们拒绝零假设,即我们假设变量的分布不是正态/高斯分布。
  • 如果p 值>为 0.05,那么我们无法拒绝零假设,即我们假设变量的分布为正态/高斯分布。

3。安德森-达林正态性检验

安德森-达林正态性检验是另一种一般的正态性检验,旨在确定数据是否来自特定的分布,在我们的情况下,正态分布。它是由西奥多·安德森和唐纳德·达林在 1952 年发明的。

图片来自作者

它给出了一个临界值范围,在该范围内,如果计算的统计量小于临界值,则零假设可能会被拒绝。在我们的例子中,在每个显著性水平上,数据具有高斯分布。

4。卡方正态性检验

检验变量正态性的另一种方法是卡方正态性检验。它不像其他方法那样受欢迎。

图片来自作者

  • 如果p 值≤ 0.05,那么我们拒绝零假设,即我们假设变量的分布不是正态/高斯分布。
  • 如果p 值>为 0.05,那么我们无法拒绝零假设,即我们假设变量的分布为正态/高斯分布。

5。Lilliefors 正态性检验

Lilliefors 检验是基于 Kolmogorov-Smirnov 检验的正态性检验。与上述所有方法一样,该检验用于检查数据是否来自正态分布。它是以乔治·华盛顿大学统计学教授休伯特·利里福斯的名字命名的。

图片来自作者

  • 如果p 值≤ 0.05,那么我们拒绝零假设,即我们假设变量的分布不是正态/高斯分布。
  • 如果p 值>为 0.05,那么我们无法拒绝零假设,即我们假设变量的分布为正态/高斯分布。

6。jarqueBera 正态性测试

Jarque-Bera 检验测试样本数据的偏度和峰度是否符合正态分布。

注意:这个测试只对足够大数量的数据样本有效(> 2000)。

图片来自作者

  • 如果p 值≤ 0.05,那么我们拒绝零假设,即我们假设变量的分布不是正态/高斯分布。
  • 如果p 值>为 0.05,那么我们无法拒绝零假设,即我们假设变量的分布为正态/高斯分布。

7.科尔莫戈罗夫 - 斯米尔诺夫正态性检验

对拟合优度执行(一个样本或两个样本)Kolmogorov-Smirnov 测试。单样本检验针对给定的分布 G(x)(即正态分布)对观察到的随机变量的分布 F(x)进行检验。

图片来自作者

  • 如果p 值≤ 0.05,那么我们拒绝零假设,即我们假设变量的分布不是正态/高斯分布。
  • 如果p 值>为 0.05,那么我们无法拒绝零假设,即我们假设变量的分布为正态/高斯分布。

结论

我们创建机器学习模型,通过对从群体中提取的样本进行训练来模拟宇宙/群体中的过程。该过程可以是检测癌症、欺诈交易等。我们假设总体的分布是正态的,样本代表总体。代表总体的好样本在生产中工作良好。因此,在训练模型之前,建议用正态性检验来检查样本是否能很好地代表总体(即正态分布)。有很多方法来检查变量的正态性。人们可以选择通过可视化使其易于理解的图,或者选择统计检验,这给出了检验正态性的 p 值。

参考

[## SciPy - SciPy v1.5.2 参考指南

SciPy(读作“叹息派”)是数学、科学和工程领域的开源软件。已完成的教程…

docs.scipy.org](https://docs.scipy.org/doc/scipy/reference/index.html) [## 简介-统计模型

statsmodels 是一个 Python 模块,它为许多不同的统计数据的估计提供了类和函数

www.statsmodels.org](https://www.statsmodels.org/stable/index.html) [## 维基百科(一个基于 wiki 技术的多语言的百科全书协作计划ˌ也是一部用不同语言写成的网络百科全书ˌ 其目标及宗旨是为全人类提供自由的百科全书)ˌ开放性的百科全书

维基百科是一个免费的在线百科全书,由世界各地的志愿者创建和编辑,由维基媒体托管…

www.wikipedia.org](https://www.wikipedia.org/)

感谢您的阅读!

非常感谢您的任何反馈和意见!

我的其他一些帖子你可能会感兴趣,

[## 4 种超参数调整技术

每个数据科学家都应该知道的流行超参数调整技术

medium.com](https://medium.com/swlh/4-hyper-parameter-tuning-techniques-924cb188d199) [## 超参数调整的数据泄漏

超参数调优有时会打乱您的模型,并导致对看不见的数据产生不可预测的结果。

towardsdatascience.com](/data-leakage-with-hyper-parameter-tuning-c57ba2006046) [## Python 中的“是”和“==”

加快字符串比较的速度

medium.com](https://medium.com/swlh/is-and-in-python-f084f36cbc0e)

2 分钟内标准化和规范化

原文:https://towardsdatascience.com/normalization-and-standardization-in-2-minutes-e0609a01e76?source=collection_archive---------31-----------------------

来源: Clker ,via pixabay

规范化和标准化是相似的-它们重新缩放要素。它们用于数据分析以理解数据,并用于机器学习以通过某些算法进行更好的训练。

这篇文章包括:

  • 正常化。为什么要正常化?
  • 标准化。为什么要标准化?
  • 差异?
  • 何时使用,何时不使用
  • 用于简单要素缩放、最小值-最大值、Z 值、log1p 变换的 Python 代码

导入库,读取数据

使用来自 Kaggle 的房价数据集。

正常化

它是在[0,1]之间重新调整值的过程。

为什么要正常化?

  1. 归一化使训练对特征的尺度不太敏感,因此我们可以更好地求解系数。离群值已经消失,但在规范化数据中仍然可见。
  2. 使用标准化方法将改善某些模型的分析。
  3. 规范化将确保收敛问题没有巨大的差异,使优化可行。

标准化

这是重新调整要素的过程,使其具有均值为 0、标准差为 1 的高斯分布的属性。

为什么要标准化?

  1. 比较具有不同单位或比例的要素。
  2. 标准化往往使训练过程表现良好,因为优化问题的数值条件得到改善。

差异?

  1. 当使用标准化时,您的新数据是不受限制的(不像标准化)。
  2. 当您不知道数据的分布或您知道它不是高斯分布时,请使用归一化。如果您的数据具有高斯分布,请使用标准化。
  3. 有时,当标准化不起作用时,标准化可能会起作用。

何时使用,何时不使用

用于以下算法:

  • k-最近邻
  • k 均值
  • 逻辑回归
  • SVM
  • 感知器
  • 主成分分析和线性判别分析

不要用于以下算法:

  • 朴素贝叶斯
  • 决策图表
  • 随机森林
  • XGBoost
  • LightGBM

归一化方法 1-简单要素缩放

数据被重新缩放,新值在[0,1]中。我们将每个值除以最大值。

归一化方法 2 —最小值-最大值

数据被重新缩放,新值在[0,1]中。

标准化— Z 值

这是重新调整要素的过程,使其具有μ=0 和σ=1 的高斯分布的属性

其中,μ是平均值,σ是平均值的标准差;样本的标准分数(也称为 z 分数)计算如下:

最后,让我们看看每种方法是如何转换数据的。

加成:转化——log1p 转化。

通常用于将价格值转换为日志。然后,应用统计学习就变得容易多了。

此外,在正偏斜的情况下,对数变换通常工作得很好。

参考资料:

[## 标准化还是常态化?Python 中的示例

一个常见的误解是,什么是标准化数据以及何时标准化数据与标准化日期之间的区别。

medium.com](https://medium.com/@rrfd/standardize-or-normalize-examples-in-python-e3f174b65dfc) [## 标准化与规范化

在整个知识发现过程中,数据挖掘本身之前,数据预处理起着至关重要的作用。其中一个…

www.dataminingblog.com](http://www.dataminingblog.com/standardization-vs-normalization/) [## 关于特征缩放和规范化

部分标准化(或 Z 值标准化)的结果是要素将被重新缩放,以便它们将…

sebastianraschka.com](http://sebastianraschka.com/Articles/2014_about_feature_scaling.html)

Python 中使用 NumPy 的规范化技术

原文:https://towardsdatascience.com/normalization-techniques-in-python-using-numpy-b998aa81d754?source=collection_archive---------2-----------------------

入门

使用 Python 和 NumPy 规范化数据集以进行分析和建模。

作者通过 Flickr 拍摄的照片

数据科学不仅仅是开发模型。大量工作涉及清理数据和选择要素。将具有相似分布但显著不同均值的要素或比例差异极大的要素插入模型可能会导致错误的预测。这些问题的一个常见解决方案是首先“归一化”特征以消除均值和方差的显著差异。

术语“规范化”可能会引起误解(也不应该与数据库规范化相混淆),因为它在统计学中意味着许多事情。然而,标准化技术中有一个共同的主题,就是将单独的数据集对齐,以便于比较。我们将重点介绍的两种技术是残差提取和重新缩放,残差提取会改变数据集的均值,而重新缩放会拉伸和压缩数据集中的值,以适应从 0 到 1 的范围。不用说,这两种技术都将消除应用于数据集的单元。幸运的是,移位和缩放技术都可以在 Python 中轻松完成,并使用 NumPy Python 包高效地进行计算。

提取残差

我们先来探讨一下残差提取技术。残差是数据集中的值与数据集平均值之间的相对差值。当数据集具有相似的分布但显著不同的均值,从而使数据集之间的比较变得困难时,这种技术非常有用。例如,假设我们有一个由两个同等规模的不同班级参加的考试。问题一样,顺序一样,答案也一样。但是两个班的平均分不一样。一班在考试中平均得了 82 分,二班平均得了 77 分。我们怎样才能把两个班的分数结合起来呢?

让我们从设置 Python 环境开始:

import numpy as np
import scipy.stats as st
from sci_analysis import analyze
%matplotlib inlinenp.random.seed(12)

上面的代码导入 NumPy 包作为np,SciPy stats 模块作为st——它将用于创建我们的数据集,sci_analysis Python 包中的analyze函数用于绘制结果,最后,我们设置随机数生成器种子值,以便结果是可重复的。作为参数传递给np.random.seed()的数字 12 是任意选择的。现在,让我们创建两个数据集,每个类一个:

dist1 = st.norm.rvs(82, 4, size=25).astype(int)
dist2 = st.norm.rvs(77, 7, size=25).astype(int)
print(dist1)
print(dist2)

输出:

[83 79 82 75 85
 75 82 81 78 93
 79 83 86 77 87
 81 86 78 77 86
 84 82 84 84 77][61 65 64 61 72
 73 76 78 74 75
 77 70 72 77 72
 72 76 86 79 74
 72 76 92 54 80]

类别 1 由dist1表示,类别 2 由dist2表示。两个变量都是 25 个正态分布随机变量的 NumPy 数组,其中dist1的平均值为 82,标准差为 4,而dist2的平均值为 77,标准差为 7。两个数组都被转换成整数,以完成我们的考试分数示例。我们可以用下面的代码来可视化课堂成绩:

analyze(
    {'dist1': dist1, 'dist2': dist2},
    title='Different means',
    nqp=False,
)
print(f'dist1 mean: {np.mean(dist1)} std dev: {np.std(dist1)}')
print(f'dist2 mean: {np.mean(dist2)} std dev: {np.std(dist2)}')

输出:

dist1 mean: 81.76 std dev: 4.197904239022134
dist2 mean: 73.12 std dev: 7.7785345663563135

从上图以及dist1dist2的均值和标准差,我们可以看出分布不匹配。

现在让我们计算dist1dist2的残差:

dist1_norm = dist1 - int(np.mean(dist1))
dist2_norm = dist2 - int(np.mean(dist2))
print(dist1_norm)
print(dist2_norm)

输出:

[   2  -2   1  -6   4 
   -6   1   0  -3  12 
   -2   2   5  -4   6
    0   5  -3  -4   5
    3   1   3   3  -4][ -12  -8  -9 -12  -1
    0   3   5   1   2
    4  -3  -1   4  -1
   -1   3  13   6   1  
   -1   3  19 -19   7]

残差是每个值与该值的分布平均值之间的差。换句话说,每个残差都是距离每个分布的平均值的距离,现在平均值为零。因为现在每个分布的平均值为零,所以它们可以直接相互比较。

analyze(
    {'dist1': dist1_norm, 'dist2': dist2_norm},
    title='Normalized',
    nqp=False,
)
print(f'dist1 mean: {np.mean(dist1_norm)} std dev: {np.std(dist1_norm)}')
print(f'dist2 mean: {np.mean(dist2_norm)} std dev: {np.std(dist2_norm)}')

输出:

dist1 mean: 0.76 std dev: 4.197904239022134
dist2 mean: 0.12 std dev: 7.7785345663563135

我们可以看到平均值现在接近于零(如果在将值转换为整数时没有舍入误差,平均值应该为零),但是每个分布的方差没有改变。这显示了计算残差是如何有效地移动每个分布的平均值,使它们对齐以便直接比较的。

最小-最大重新缩放

另一种标准化技术是重新缩放数据集。这在尝试比较不同因素或使用不同单位的数据集时非常有用,例如比较英里和米。让我们生成两个新的分布,它们的比例相差 100 倍:

dist3 = st.gamma.rvs(1.7, size=25)
dist4 = st.gamma.rvs(120, size=25)
print(dist3)
print(dist4)

输出:

[   0.49529541   1.42598239   0.38621773   0.96738928   0.53575876
    1.72574991   0.3431045    0.80584646   0.77543188   1.84272915
    2.049985     0.76373308   3.54020309   0.36979422   4.67967817
    0.6311116    2.51371776   1.12812921   0.62183125   2.03923847
    1.15269735   0.72795499   1.86093872   0.52560778   0.65314453] [113.88768554 108.94661696 118.40872068 124.94416222 150.91953839
  116.86987547 107.05486021  89.61392457 126.28254195 123.32858014
  108.31036684 114.52812809 109.43092709 114.17768634 114.54545154
  111.21616394 102.08437696 127.42455395 105.82224292 127.28966453
  114.03632754 120.02256655 120.77792085 103.43640076 112.24143473]

从上面的输出中,您可以看到dist3在 0 到 10 的范围内,而dist4dist3大 100 倍。通过检查平均值和标准偏差,我们可以看到这些分布不能相互比较。

analyze(
    {"dist3": dist3, "dist4": dist4},
    title="Different Scales",
    nqp=False,
)
print(f'dist3 mean: {np.mean(dist3)} std dev: {np.std(dist3)}')
print(f'dist4 mean: {np.mean(dist4)} std dev: {np.std(dist4)}')

输出:

dist3 mean: 1.3024508282047844 std dev: 1.0372657584518052
dist4 mean: 115.42402875045401 std dev: 11.29662689178773

幸运的是,有一种技术可以通过使用每个数据集中每个值与最小值之间的距离与每个数据集中值的范围之比来重新调整分布。该比率由以下等式表示:

(x - min) / (max - min)

通过在 Python 中应用这个等式,我们可以得到dist3dist4的重新缩放版本:

max = np.max(dist3)
min = np.min(dist3)
dist3_scaled = np.array([(x - min) / (max - min) for x in dist3])
max = np.max(dist4)
min = np.min(dist4)
dist4_scaled = np.array([(x - min) / (max - min) for x in dist4])
print(dist3_scaled)
print(dist4_scaled)

输出:

[0.03509474 0.24970817 0.00994177 0.14395807 0.04442546
 0.3188336  0\.         0.10670681 0.09969331 0.34580864
 0.39360118 0.09699561 0.7372407  0.00615456 1\.        
 0.06641352 0.50053647 0.18102418 0.0642735  0.39112306
 0.18668952 0.08874529 0.35000771 0.04208467 0.07149424] [0.39594679 0.31534946 0.46969265 0.57629694 1\.        
 0.44459144 0.28449166 0\.         0.59812822 0.54994402
 0.30497113 0.40639351 0.32324939 0.4006772  0.40667608
 0.35236968 0.20341453 0.6167564  0.26438555 0.61455612
 0.3983714  0.49601725 0.50833838 0.22546836 0.36909361]

通过重新缩放dist3dist4,每个数据集的最大值现在是 1,而最小值现在是 0。这很方便,因为每个数据集现在都在相同的比例上,并且每个分布的形状都得以保留。实际上,每个分布都被压缩并移动到 0 和 1 之间。现在,让我们检查重新缩放的dist3dist4的平均值和标准偏差:

analyze(
    {'dist3': dist3_scaled, 'dist4': dist4_scaled},
    title='Scaled',
    nqp=False,
)
print(f'dist3 mean: {np.mean(dist3_scaled)} std dev: {np.std(dist3_scaled)}')
print(f'dist4 mean: {np.mean(dist4_scaled)} std dev:{np.std(dist4_scaled)}')

输出:

dist3 mean: 0.2212221913870349 std dev: 0.2391901615794912
dist4 mean: 0.42100718959757816 std dev: 0.18426741349056594

我们现在可以看到,dist3_scaleddist4_scaled的均值在相似的标准差下有显著的不同。

使用 NumPy 规范化大型数据集

残差和重定标都是归一化数据集以进行分析的有用技术。然而,这些数据集通常不只是 25 个值,因此值得考虑如何有效地计算残差和执行重缩放。幸运的是,NumPy 可以帮助快速有效地执行这些计算。

如果您不熟悉 NumPy,它是一个用于高性能科学计算的 Python 包。与使用常规 Python 列表相比,NumPy 有两个使计算更快、更有效的特性。首先,NumPy 使用数组作为其主要数据结构,与 Python 列表相比,它使用的内存更少,并且要求数组中的每个值都是相同的类型。标量也可以对数组进行操作——对数组的每个值应用标量操作。事实上,当我们通过从分布(一个数组)中减去分布(一个标量)的平均值来计算残差时,我们已经看到了这一点。

让我们比较一下使用 Python 列表理解和数组操作计算残差的速度差异。我们将首先创建一个包含 100,000 个值的随机正态分布变量数组:

dist5 = st.norm.rvs(82, 5, size=100000)

让我们看看使用列表理解计算dist5的残差需要多长时间:

avg = np.mean(dist5)
%timeit [val - avg for val in dist5]

输出:

10 loops, best of 3: 24.9 ms per loop

列表理解需要大约 25 毫秒来遍历dist5中的每个值,这还不算太糟糕。然而,让我们再次计算dist5的残差,但是使用 NumPy 标量运算:

avg = np.mean(dist5)
%timeit dist5 - avg

输出:

10000 loops, best of 3: 144 µs per loop

仅仅从dist5(这是一个 NumPy 数组)中减去平均值就需要 144 微秒!这得益于 NumPy 阵列的高效设计。

现在,如果我们想用一个函数而不仅仅是一个简单的标量来操作一个数组呢?这是 NumPy 以通用函数的形式对 Python 的第二次性能提升。通用函数是“矢量化”操作,在迭代数组中的每个值时,利用 CPU 优化来实现计算加速。NumPy 内置了无数的通用函数,但是我们也可以使用 NumPy 的frompyfunc()函数编写自己的函数。

让我们来看看使用列表理解和自定义通用函数来重新调整数组值在速度上的差异:

min = np.min(dist5)
max = np.max(dist5)
%timeit [(val - min) / (max - min) for val in dist5]

输出:

10 loops, best of 3: 47.2 ms per loop

通过在 47 毫秒内重新缩放dist5,列表理解的表现令人钦佩。让我们把这比作创建一个名为scale的定制通用函数。

scale = np.frompyfunc(lambda x, min, max: (x - min) / (max - min), 3, 1)

我们使用np.frompyfunc()函数,它接受一个可调用函数、输入数和输出数作为它的参数。在这种情况下,可调用的是 lambda 函数形式的重定标方程。如果你不熟悉 lambda 函数,你可以把它们想象成一行未命名的函数。我们的 lambda 函数有三个参数,xminmax。这三个参数是调用np.frompyfunc()时指定的三个输入。同样值得注意的是,minmax是从dist5计算的标量,而x代表dist5中的每个值。现在,让我们计算minmax并调用scale函数:

min = np.min(dist5)
max = np.max(dist5)
%timeit scale(dist5, min, max).astype(float)

输出:

10 loops, best of 3: 20.4 ms per loop

如你所见,与列表理解相比,自定义通用函数需要一半的时间来完成。

结论

我们研究了两种归一化技术——残差提取和最小-最大重新缩放。残差提取可以被认为是移动一个分布,使其平均值为 0。最小-最大重新缩放可以被认为是移动和压缩分布以适应 0 和 1 之间的范围。残差提取对于比较均值不同但形状相似的分布很有用。最小-最大重新缩放对于比较不同比例或不同形状的分布很有用。

当分布用 NumPy 数组表示时,这两种规范化技术都可以用 NumPy 有效地执行。NumPy 数组上的标量操作既快又易读。当需要对数组进行更复杂的操作时,可以使用通用函数来高效地执行操作。

规范化与标准化

原文:https://towardsdatascience.com/normalization-vs-standardization-cb8fe15082eb?source=collection_archive---------13-----------------------

主题客栈Unsplash 拍摄的照片

两种最重要的特征缩放技术

在机器学习中,一个模型将和你用来训练该模型的数据一样好(或一样坏)。由于各种原因,不同特征的大小影响不同的机器学习模型。

例如,考虑一个包含年龄和收入两个特征的数据集。这里的年龄范围是从 0 到 100,而收入范围是从 0 到一个很大的数目,大多数都高于 100。收入比年龄大 1000 倍左右。所以,这两个特征在非常不同的范围内。当我们做进一步的分析时,比如多元线性回归,归因收入会由于其更大的值而内在地影响结果。但这并不一定意味着它作为一个预测指标更重要。因此,应缩放所有要素的范围,以便每个要素对最终距离的贡献大致成比例。

为此,使用特征缩放是必不可少的。

在本文中,我们将讨论什么是特性缩放,为什么是特性缩放,实现特性缩放的技术,它的有用性,以及使用这些技术实现特性缩放的 python 片段。

讨论的流程如下,

  • 特征缩放
  • 正常化
  • 标准化
  • 履行
  • 什么时候用什么?

特征缩放

要素缩放是一种将数据集中数值列的值更改为使用通用比例的技术,不会扭曲值范围的差异或丢失信息。

为什么要使用特征缩放?

  1. 使用要素缩放比不使用要素缩放时,梯度下降收敛得更快。
  2. 许多分类器(如 KNN,K-means)通过欧几里得距离计算两点之间的距离。如果其中一个要素的值范围很大,则距离将由该特定要素决定。因此,应缩放要素的范围,使每个要素对最终距离的贡献大致成比例。

但是,并非每个数据集都需要进行要素缩放。仅当特性具有不同范围时才需要。

这可以通过两种广泛使用的技术来实现。

  1. 正常化
  2. 标准化

正常化

归一化(也称为最小-最大归一化)是一种缩放技术,当应用该技术时,特征将被重新缩放,从而数据将落入范围【0,1】

每个特征的归一化形式可以计算如下:

归一化的数学公式

这里“x”是原始值,“x `”是标准化值。

标准化

标准化(也称为 Z 值归一化)是一种缩放技术,当应用该技术时,要素将被重新缩放,从而使其具有标准正态分布的属性,具有平均值、 μ=0 和标准偏差、σ= 1;其中 μ 是平均值,而 σ 是平均值的标准偏差。

样本的标准分(也称z)计算如下:

标准化的数学公式

这将缩放特征,使其范围在[-1,1]* 之间*

履行

现在让我们使用一个简单的 python 代码来实现这些技术。

我们将使用的数据集是来自 Kaggle 的葡萄酒分类器数据。

* [## 葡萄酒品种分类

测试不同算法的伟大实践

www.kaggle.com](https://www.kaggle.com/brynja/wineuci)

关于数据集:

这个数据集是对意大利同一地区的三种不同品种的葡萄酒进行化学分析的结果。这项分析确定了三种葡萄酒中 13 种成分的含量。

import pandas as pd
wine_data = pd.read_csv("wine_data.csv",usecols=[0,1,2])

使用 pandas 导入 pandas 并将 CSV 格式(逗号分隔值)的数据读取到数据框中。

wine_data.head()

输出:

压头的输出()

Head()返回数据中的前五个元素。

现在,让我们来详细研究一下每个专栏/功能。

import seaborn as sns
sns.boxplot(x='Alcohol', data=wine_data)

输出:

在这里,我们可以看到特性酒精值的范围是 11-15

wine_data['Alcohol'].describe()

输出:

describe()的输出

我们可以清楚地看到各种统计函数值,最小值约为 11.03,最大值约为 14.83

sns.boxplot(x='Malic', data=wine_data)

输出:

这里我们可以看到苹果的特性值在 1-6 的范围内,很少有异常值。

wine_data['Malic'].describe()

输出:

观察结果:

  • 特性酒精范围在[11,15]之间
  • 特征苹果范围在[0.5,6]
  • 当我们执行考虑距离的机器学习算法(如 KNN)时,模型将偏向于特征,酒精。因此,特征缩放对于该数据集是必要的。

现在让我们执行规范化和标准化。并比较结果。*

应用规范化

现在,让我们对每个特性进行标准化,并观察变化。

*from sklearn.preprocessing import MinMaxScaler*

使用最小最大缩放器可以实现标准化。**

*minmax_scale = MinMaxScaler().fit(wine_data[['Alcohol', 'Malic']])
df_minmax = minmax_scale.transform(wine_data[['Alcohol', 'Malic']])*

对特征、酒精苹果应用归一化

*print('Min-value after normalization:\nAlcohol={:.2f}, Malic acid={:.2f}'
      .format(df_minmax[:,0].min(), df_minmax[:,1].min()))
print('\nMax-value after normalization:\nAlcohol={:.2f}, Malic acid={:.2f}'
      .format(df_minmax[:,0].max(), df_minmax[:,1].max()))*

输出:

*Min-value after normalization:
Alcohol=0.00, Malic acid=0.00

Max-value after normalization:
Alcohol=1.00, Malic acid=1.00*

应用标准化

现在让我们进行标准化

*from sklearn.preprocessing import StandardScaler*

使用 StandardScaler( ) 可以实现标准化

*std_scale = StandardScaler().fit(wine_data[['Alcohol', 'Malic']])
df_std = std_scale.transform(wine_data[['Alcohol', 'Malic']])*

在特征上应用标准化,酒精苹果**

*print('Mean after standardization:\nAlcohol={:.2f}, Malic acid={:.2f}'
      .format(df_std[:,0].mean(), df_std[:,1].mean()))*

输出:

*Mean after standardization:
Alcohol=-0.00, Malic acid=0.00*

比较结果

现在让我们一起来理解这个结果。

*import matplotlib.pyplot as plt
fig, ax = plt.subplots(3, figsize=(6,14))for a,d,l in zip(range(len(ax)),
               (wine_data[['Alcohol', 'Malic']].values, df_std, df_minmax),
               ('Input scale',
                'Standardized ',
                'min-max scaled [min=0, max=1]')
                ):
    for i,c in zip(range(1,4), ('red', 'blue', 'green')):
        ax[a].scatter(d[wine_data['Class'].values == i, 0],
                  d[wine_data['Class'].values == i, 1],
                  alpha=0.5,
                  color=c,
                  label='Class %s' %i
                  )

    ax[a].set_title(l)
    ax[a].set_xlabel('Alcohol')
    ax[a].set_ylabel('Malic Acid')
    ax[a].legend(loc='upper left')
    ax[a].grid()plt.tight_layout()plt.show()*

输出:

原始数据、标准化数据、标准化数据的散点图

观察结果:

  • 原始数据中,特征酒精位于【11,15】,特征苹果位于【0,6】
  • 归一化数据中,特征酒精位于[0,1],特征苹果酸位于[0,1]
  • 标准化数据中,特征酒精苹果酸以 0 为中心

什么时候用什么?

“规范化还是标准化?” —这个问题没有明显的答案:真的取决于应用。

例如,在聚类分析中,标准化可能特别重要,以便根据某些距离度量来比较要素之间的相似性。另一个突出的例子是主成分分析,我们通常更喜欢标准化而不是规范化,因为我们对最大化方差的成分感兴趣。

但是,这并不意味着规范化一点用都没有!一个流行的应用是图像处理,其中像素强度必须被归一化以适合某个范围(例如,RGB 颜色范围为 0 到 255)。此外,典型的神经网络算法需要 0-1 范围内的数据。

谢谢你的阅读。我也将在未来写更多初学者友好的帖子。请在媒体上关注我,以便了解他们。我欢迎反馈,可以通过 Twitter ramya_vidiyala 和 LinkedIn RamyaVidiyala 联系我。快乐学习!

解释了规范化与标准化

原文:https://towardsdatascience.com/normalization-vs-standardization-explained-209e84d0f81e?source=collection_archive---------3-----------------------

不要互换使用它们!

马克·弗莱彻·布朗在 Unsplash 上的照片

术语规范化和标准化在统计学和数据科学中被大量使用。我们有时会互换使用它们。人们通常会混淆这两个术语。但是这两者之间有一个微妙的区别。这就是面试官迈出第一步的地方。你完了。在本文中,我将尽可能用简单的语言解释什么是规范化和标准化,而不使用太多的技术术语。它们在现实生活中的应用使用实例,以及它们之间的区别。所以请耐心听我说,这五分钟是值得的。

什么是正常化?

这是一种缩放技术方法,其中数据点被移动和重新缩放,以便它们最终在 0 到 1 的范围内。它也被称为最小-最大缩放

计算标准化分数的公式:

X new =(X—X min)/(X max—X min)

这里,Xmax 和 Xmin 分别是特征的最大值和最小值。

如果 X = Xmin 那么 Xnew =0

因为分子会变成 Xmin–Xmin,也就是 0 而已。

如果 X = Xmax 那么 Xnew =1

在这种情况下,分子和分母都相等,并相互抵消,得到 Xnew =1 的值。

太复杂了吧?让我们举一个的例子并把它清除掉。

在 CAT(IIM 商学院为选拔印度顶级商学院而进行的能力倾向测试)中,收到的申请太多了。所以他们不能同时对所有的考生进行考试,因此考试是轮流进行的,甚至是在不同的日子进行。不同班次,试卷设置不同。虽然问题的设置方式是每个班次的难度保持不变,但是仍然有可能班次的难度发生变化。所以这对得到一套难题的考生来说是不公平的。为了对所有候选人公平,候选人的分数被归一化。

假设考试分两班进行A 班B 班,A 班的问题相对于 B 班的问题相对容易。因为 A 班的问题相对容易,所以 A 班考生在 300 分中的最高分是 280 分,最低分是 80 分,而 B 班考生的最高分和最低分分别是 250 分和 50 分。

所以我们不能比较在 A 班得了 150 分的候选人和在 b 班得了 150 分的候选人。

因此我们将分数标准化

在班次 A 中获得 150 分的候选人的标准化分数将按如下方式计算

为了简单起见,让我们把它命名为 Xa

Xa =150-Xmin/(Xmin-Xmax)

Xmax = 280

Xmin = 80

把我们得到的这些值

xa = 150–80/(280–80)

Xa =0.35

在 B 班中获得 150 分的候选人的标准化分数将为

为了简单起见,让我们把它命名为 Xb

Xb=150-Xmin/(Xmin-Xmax)

Xmax = 250

Xmin = 50

把我们得到的这些值

XB = 150–50/(250–50)

Xb =0.5

这里我们可以看到 Xb>Xa

CAT 考试的总分=300 分

如果你想在 300 分中进行比较

Xa *300 =105

预算外*300 = 150

我想现在理解什么是正常化以及我们为什么需要它会更清楚。

好吧,让我们跳到第二个

什么是标准化?

标准化是另一种缩放方法,其中值以平均值为中心,具有单位标准偏差。这意味着如果我们计算标准分数的平均值和标准差,它将分别为 0 和 1。

标准化值的公式:

在哪里,

=给定分布的平均值

σ =给定分布的标准偏差

这个 Z 值称为标准分数,它代表特定观察值高于或低于平均值的标准偏差数。

即,如果 Z=2,这意味着观察值高于平均值两个标准偏差。

如果我们绘制这些标准分数,它将是一个均值为 0 的正态分布,标准差等于 1。

https://365 data science . com/WP-content/uploads/2018/10/image4-9 . jpg

均值= 0 且σ =1 的标准差也称为标准正态分布,用 N(0,1)表示。

变得太专业了,不是吗?

为了更好的理解,我们来解决一个的例子

让我们假设你和你的朋友在不同的大学学习,那里的评分系统是不同的。你在一次测验中得了 85 分。这个班的平均成绩是 75 分,标准差是 5。你的朋友得了 615 分,班级的平均成绩是 600 分,标准差是 50。你将如何评价谁表现得更好?由于 85 级不能和 615 级相比。

标准化的作用来了,因为它允许我们用不同的指标直接比较分数,并对它们进行陈述。

你的 Z 值= 85–75/5 = 2

这意味着你比平均成绩高出 2 个标准差。

你朋友的 Z 值= 615–600/50 = 0.3

意味着你比平均成绩高出 0.3 个标准差。

通过查看标准分数,你可以清楚地说你比他或她在班上表现得好得多。

那不是很容易吗?我答应过你。

现在一个大问题出现了

规范化和标准化哪个更好?

这取决于你使用的数据类型。

当我们的数据不符合正态分布时,规范化优于标准化。它在那些不假设任何数据分布的机器学习算法中很有用,如 k-最近邻和神经网络。

当我们的数据服从正态分布时,标准化很好用。它可以用在机器学习算法中,其中我们对数据的分布进行假设,如线性回归等

需要注意的是,与标准化不同,标准化没有边界范围,即 0 到 1。

它也不受我们数据中最大值和最小值的影响,所以如果我们的数据包含异常值,那就好办了。

最后的话:

我希望您对规范化和标准化有了很好的了解。如果你喜欢我的工作,那么请欣赏我张贴更多与统计和数据科学相关的好内容。请在社交媒体平台上分享。

规范化与标准化,哪个更好

原文:https://towardsdatascience.com/normalization-vs-standardization-which-one-is-better-f29e043a57eb?source=collection_archive---------14-----------------------

在本教程中,让我们看看哪一个是最好的特征工程技术。

图片来源于作者(塔努·南达·帕布)

众所周知特征工程是一个将原始数据转换成数据集的问题。有各种各样的特征工程技术可用。两种最广泛使用且最容易混淆的特征工程技术是:

  • 正常化
  • 标准化

今天,在这个美好的白天或夜晚,我们将探索这两种技术,并了解数据分析师在解决数据科学问题时做出的一些常见假设。此外,本教程的全部代码可以在下面我的 GitHub 库中找到

[## 塔努-北帕布/Python

github.com](https://github.com/Tanu-N-Prabhu/Python/blob/master/Normalization_vs_Standardization.ipynb)

正常化

理论

规范化是将数字特征转换为标准范围值的过程。值的范围可以是[-1,1]或[0,1]。例如,假设我们有一个数据集,包含两个名为“年龄和“体重的特征,如下所示:

图片来源于作者(塔努·南达·帕布)

假设名为“年龄的特征的实际范围是 5100。我们可以通过从“年龄”列的每个值中减去 5 ,然后将结果除以95(100–5),从而将这些值归一化到 [0,1] 的范围内。为了让你的大脑清楚,我们可以把上面的内容写成一个公式。

图片鸣谢 安德烈·布尔科夫的百页机器学习书

其中 min^(j)max^(j) 是数据集中特征 j 的最小值和最大值。****

履行

现在你知道了它背后的理论,让我们看看如何把它投入生产。通常有两种方法来实现它:传统的老式手工方法和另一种使用**sklearn preprocessing**库。今天我们就借助sklearn库来进行归一化。

使用 sklearn 预处理-规格化器

在将“年龄”和“体重”值直接提供给该方法之前,我们需要将这些数据帧转换成一个numpy数组。为此,我们可以使用如下所示的to_numpy()方法:

**# Storing the columns Age values into X and Weight as Y**X = df['Age']
y = df['Weight']
X = X.to_numpy()
y = y.to_numpy()

上述步骤非常重要,因为fit()transform()方法都只对数组有效。

from **sklearn.preprocessing** import **Normalizer**normalizer = **Normalizer**().**fit**([X])
normalizer.**transform**([X])

图片来源于作者(塔努·南达·帕布)

normalizer = **Normalizer**().**fit**([y])
normalizer.**transform**([y])

图片来源于作者(塔努·南达·帕布)

如上所示,两个数组的值都在范围【0,1】内。关于该库的更多细节可以在下面找到:

[## 6.3.预处理数据-sci kit-学习 0.22.2 文档

sklearn.preprocessing 包提供了几个常用的实用函数和转换器类来改变 raw…

scikit-learn.org](https://scikit-learn.org/stable/modules/preprocessing.html#preprocessing-normalization)

我们应该在什么时候对数据进行规范化?

虽然规范化不是强制性或必需的(必须做的事情)。有两种方法可以帮助你

  • 标准化数据将提高学习速度。这将提高构建(训练)和测试数据的速度。试试看!!
  • 它将避免数字溢出。真正的意思是,标准化将确保我们的输入大致在一个相对较小的范围内。这将避免问题,因为计算机通常在处理非常小或非常大的数字时会有问题。

标准化

理论

标准化或 z 值标准化最小-最大缩放是一种重新调整数据集值的技术,使其具有标准正态分布的属性,其中 μ = 0(平均值-要素的平均值)和 σ = 1(平均值的标准偏差)。这可以写成:

图片鸣谢 安德烈·布尔科夫的百页机器学习书

履行

现在实现标准化的方法很多,就像规范化一样,我们可以使用sklearn库,使用StandardScalar方法,如下所示:

from **sklearn.preprocessing** import **StandardScaler**sc = **StandardScaler**()
sc.**fit_transform**([X])
sc.**transform**([X])sc.**fit_transform**([y])
sc.**transform**([y])

你可以从下面阅读更多关于图书馆的信息:

[## 6.3.预处理数据-sci kit-学习 0.22.2 文档

sklearn.preprocessing 包提供了几个常用的实用函数和转换器类来改变 raw…

scikit-learn.org](https://scikit-learn.org/stable/modules/preprocessing.html#standardization-or-mean-removal-and-variance-scaling)

z 分数标准化

同样,我们可以用熊猫meanstd来做必要的事情

**# Calculating the mean and standard deviation**df = (df - df.**mean**())/df.**std**()
print(df)

图片来源于作者(塔努·南达·帕布)

最小-最大缩放比例

在这里,我们可以用熊猫minmax来做必要的事情

**# Calculating the minimum and the maximum** df = (df-df.**min**())/(df.**max**()-df.**min**())
print(df)

图片来源于作者(塔努·南达·帕布)

通常, Z 分数归一化是首选,因为最小-最大缩放容易导致过拟合

什么时候实际使用标准化和规范化?

以上问题没有一个答案。如果你有一个小数据集并且有足够的时间,那么你可以尝试上述两种技术并选择最好的一种。以下是你可以遵循的经验法则:

  • 你可以在无监督学习算法上使用标准化。在这种情况下,标准化比规范化更有利。
  • 如果你在数据中看到一个钟形曲线,那么标准化更可取。为此,您必须绘制您的数据。
  • 如果你的数据集有极高的低值 ( 异常值),那么标准化更可取,因为通常情况下,标准化会这些值压缩到一个小范围

在除了上述情况之外的任何其他情况下,一个人的规范化保持良好。如果你有足够的时间,再次尝试这两种特征工程技术。

好了,你们已经到了教程的结尾。我希望你们今天学到了一些东西。我使用了名为教材作为参考(第 5 章)来编写本教程。你可以看一下。如果你们对本教程有任何疑问,可以在下面的评论栏里找到。我会尽量尽快回答。在那之前注意安全,再见。下次见。欲了解更多关于的更新,请使用来读写更多的 python 笔记本。****

** [## 数据化

创建作品集上传 Jupyter 笔记本用您的数据讲述故事*创建免费作品集探索笔记本…

www . data fed . world](http://www.datafied.world/)**

标准化贴现累积收益

原文:https://towardsdatascience.com/normalized-discounted-cumulative-gain-37e6f75090e9?source=collection_archive---------2-----------------------

一种评估推荐引擎的指标

Graham Ruttan 在 Unsplash 上拍摄的照片

你还记得曾经和你聊得很愉快的人忘记你名字的尴尬时刻吗?在这个时代,我们有了新的标准,新的期望。当期望没有实现时,感觉就在不远处被问到“我在哪里见过你?”上周和你在酒吧呆了一晚上的那个女人/男人,尴尬!—其实我并不去酒吧,但你明白我的意思。我们正处于个性化的时代,个性化的内容正到处涌现——网飞、Youtube、亚马逊等等。用户需要个性化的内容,企业寻求满足用户的需求。

近年来,许多企业已经采用机器学习来开发有效的推荐系统,以帮助个性化用户体验。就像生活中的所有事情一样,这一壮举伴随着它的挑战。评估推荐引擎的影响是推荐引擎的开发阶段或增强阶段的主要挑战。虽然我们可以肯定推荐系统所带来的积极影响,但为了有效地与利益相关者沟通,或者为了将来我们想增强我们的系统,我们非常需要量化这种影响。

经过一番啰嗦,我在此向大家介绍… 归一化贴现累计收益 (NDCG)。

衡量排名质量的一种方法,通常用于衡量 web 搜索引擎算法或相关应用程序的有效性。

如果我们要相应地理解 Nd CG 指标,我们必须首先理解 CG(累积收益)和 DCG(贴现累积收益),以及理解我们在使用 DCG 及其相关指标时所做的两个假设:

  1. 高度相关的文档在搜索引擎结果列表中出现得越早越有用。
  2. 高度相关的文档比不太相关的文档更有用,不太相关的文档比不相关的文档更有用

(来源:维基百科)

累积增益

如果每个推荐都有一个相关的分级相关性分数,那么 CG 就是搜索结果列表中所有结果的分级相关性值的总和——参见图 1,我们可以用数学方法来表达它。

图 1:累积增益数学表达式

特定排名位置p的累积增益,其中rel_i是位置i的结果的分级相关性。为了用 Python 演示这一点,我们必须首先让变量setA成为搜索查询响应的分级相关性分数,从而每个分级相关性分数与一个文档相关联。

setA = [3, 1, 2, 3, 2, 0]
print(sum(setA))11

CG 的问题在于,在确定结果集的有用性时,它没有考虑结果集的排名。换句话说,如果我们对setA返回的分级相关性分数进行重新排序,我们将无法更好地了解结果集的有用性,因为 CG 将保持不变。有关示例,请参见下面的代码单元格。

setB = sorted(setA, reverse=True)
print(f"setA: {setA}\tCG setA: {cg_a}\nsetB: {setB}\tCG setB: {sum(setB)}")setA: [3, 1, 2, 3, 2, 0]	CG setA: 11
setB: [3, 3, 2, 2, 1, 0]	CG setB: 11

setB显然返回了比setA更有用的集合,但是 CG 测量表明它们返回的结果一样好。

贴现累积收益

为了克服这一点,我们引入了 DCG。DCG 通过降低与结果位置成对数比例的分级相关性值来惩罚在搜索中出现较低的高度相关的文档—参见图 2。

图 2:贴现累积收益数学表达式

下面我们创建了一个名为discountedCumulativeGain的函数来计算setAsetB的 DCG。如果这是一个有效的测量,setB应该比setA有更高的 DCG,因为它的结果更有用。

import numpy as np 

def discountedCumulativeGain(result):
    dcg = []
    for idx, val in enumerate(result): 
        numerator = 2**val - 1
        # add 2 because python 0-index
        denominator =  np.log2(idx + 2) 
        score = numerator/denominator
        dcg.append(score)
    return sum(dcg)print(f"DCG setA: {discountedCumulativeGain(setA)}\nDCG setB: {discountedCumulativeGain(setB)}")DCG setA: 13.306224081788834
DCG setB: 14.595390756454924

setB的 DCG 高于setA,这符合我们的直觉,即setBsetA返回更多有用的结果。

标准化贴现累积收益

当我们想要比较搜索引擎从一个查询到下一个查询的性能时,DCG 出现了一个问题,因为搜索结果列表的长度会根据所提供的查询而变化。因此,通过对查询中选择的值p的每个位置的累积增益进行归一化,我们得到 NDCG。我们通过按照相对相关性对语料库中的所有相关文档进行排序来实现这一点,通过位置p产生最大可能的 DCG(也称为理想的折扣累积收益)——参见图 3。

图 3:归一化贴现累积收益数学表达式;REL_p 表示语料库中直到位置 p 的相关文档的列表(按照相关性排序)

为了在 python 中执行这一度量,我们创建了函数normalizedDiscountedCumulativeGain来帮助实现这一功能。

def normalizedDiscountedCumulativeGain(result, sorted_result): 
    dcg = discountedCumulativeGain(result)
    idcg = discountedCumulativeGain(sorted_result)
    ndcg = dcg / idcg
    return ndcgprint(f"DCG setA: {normalizedDiscountedCumulativeGain(setA, setB)}\nDCG setB: {normalizedDiscountedCumulativeGain(setB, setB)}")DCG setA: 0.9116730277265138
DCG setB: 1.0

比率将始终在[0,1]的范围内,1 是满分,这意味着 DCG 与 IDCG 相同。因此,可以对所有查询的 NDCG 值进行平均,以获得推荐系统排序算法的平均性能的度量。

NDCG 的局限性

(来源:维基百科)

  1. NDCG 不会对搜索结果中的错误文档进行处罚
  2. 不惩罚结果中丢失的文档
  3. 可能不适合衡量可能经常有几个同样好的结果的查询的性能

包裹

我们在使用 NDCG 时面临的主要困难是,当只有部分相关反馈可用时,我们经常不知道结果的理想排序。然而,NDCG 已被证明是评估各种问题排名质量的有效指标,例如个性化网络搜索挑战AirBnB 新用户预订挑战个性化 Expedia 酒店搜索——ICDM 2013等等。

谢谢你读到这篇文章的结尾。如果你想和我联系,我在 LinkedIn 上很容易找到。

[## Kurtis Pykes -人工智能作家-走向数据科学| LinkedIn

在世界上最大的职业社区 LinkedIn 上查看 Kurtis Pykes 的个人资料。Kurtis 有一个工作列在他们的…

www.linkedin.com](https://www.linkedin.com/in/kurtispykes/)

归一化单细胞 RNA 测序数据——缺陷和建议

原文:https://towardsdatascience.com/normalizing-single-cell-rna-sequencing-data-pitfalls-and-recommendations-19d0cb4fc43d?source=collection_archive---------17-----------------------

斯文·米克在 Unsplash 上的照片

单细胞 RNA 测序(scRNA-seq)项目的目标通常是识别亚群和差异基因表达分析。为了避免“维数灾难”,高度可变基因(hvg)被用于聚类分析。几项研究表明,hvg 的选择对用于原始计数矩阵归一化的方法的选择很敏感。

为什么要正常化?

原始读数不能直接用于比较细胞间的基因表达,因为它们被技术和“无趣的”生物变异所混淆。有 QC 步骤和其他方法可用于过滤和回归不感兴趣的生物变异。虽然 PCR 扩增偏倚通常通过使用独特的分子标识符(umi)来处理,但需要标准化来消除其他技术变异的影响,如测序深度、细胞裂解和逆转录效率的差异。

标准化过程的主要目标是消除技术效应的影响,保留真正的生物异质性。在标准化良好的数据集中,基因的方差应该与细胞的基因丰度和测序深度无关。“真正”差异表达的基因应该在细胞类型之间表现出高的差异,而看家基因应该表现出低的差异。

因此,标准化是一个关键的预处理步骤,它极大地影响了 scRNA 分析的下游应用。不幸的是,scRNA 数据集通常使用从批量 RNA 测序方法继承的方法进行标准化,正如我们将很快看到的那样,由于这些数据集的技术变异和固有复杂性的性质,这是不合适的。在这篇博文中,我们将看到在 scRNA-seq 分析的背景下,全局比例方法的局限性。我们还将讨论最近引入的 SCNorm 和 SCTransform 归一化方法的潜力,这些方法是专门为单细胞分析量身定制的。

全局缩放方法

传统上,使用 RPKM(每千碱基百万的阅读数)、FPKM(每千碱基百万的片段数)或 TPM(每百万的转录数)方法将细胞间的原始表达计数标准化为测序深度。要了解它们是如何工作的,请观看这个视频。虽然这些方法对样品内标准化很有效,但它们被广泛认为不适合样品间的差异表达分析。例如,考虑一种情况,其中两种基因 A 和 B 的表达在两种条件-对照和处理-之间进行比较。基因 A 在两种条件下表达水平相同,而基因 B 在处理过的细胞中表达水平高 2 倍。TPM 标准化将绝对表达转化为相对表达,因此,人们可能会得出基因 A 差异表达的结论,尽管这种效应只是基因 A 与基因 b 比较的结果。

TPM 规范化不适用于差异表达分析。

开发了样品间标准化的替代方法;TMM(M 值的修整平均值)和 DESeq 最受欢迎。这两种策略遵循相同的动机:通过标准化细胞间感兴趣的数量,同时假设大多数基因没有差异表达,将细胞特异性测量带到一个共同的尺度上。基于非差异表达基因通过这些方法计算的全局比例因子被应用于样本(每个样本一个)。然后,使用相同的因子对样本细胞中的所有基因进行缩放。这些方法在批量 RNA-seq 中表现出优异的性能,但是由于大量的零表达值,它们在单细胞设置中受到损害。此外,这些方法假设样品中所有细胞的基本 RNA 含量是恒定的,并且单一比例因子可以应用于所有基因。因此,基于全局比例因子的标准化策略在典型的零膨胀和高度异质性的 scRNA 数据集上表现不佳。

基因群基础方法

为了解决全局缩放方法的固有问题,最近引入了两种有趣的归一化方法-SCnorm (2017)和 SCTransform (Seurat package v3,2019)。

SCnorm

SCnorm 是在 Bioconductor 上可用的 R 包。对于每个基因,SCnorm 通过分位数回归估计基因表达对测序深度的依赖性。然后将具有相似相关性的基因分组,并使用第二个分位数回归来估计每组的比例因子。最后,使用组特异性比例因子对每个基因组的测序深度进行调整,以产生标准化的表达估计值。

a:原始计数对序列深度,B:归一化的全局比例因子对序列深度,C:单个细胞数据集中 3 个基因的标准计数对序列深度,编辑自 Bacher 等人

上图显示了单个细胞数据集中三个基因的计数深度关系。图 A 为未标准化或原始表达计数。很明显,基于全局比例因子的方法(图 B)与图 c 中的 SCnorm 相比,在标准化方面表现不佳。

SCTransform

SCTransform 是修拉 v3 提供的 R 。该方法使用正则化负二项式模型对 UMI 计数进行建模,以消除测序深度引起的变化。简而言之,该方法首先使用测序深度作为自变量,UMI 计数作为响应或因变量,构建每个基因的广义线性模型(GLM)。然后基于基因表达对参数估计进行正则化(或调整)。使用正则化的参数应用第二轮负二项式回归。该模型的输出(残差)是每个基因的标准化表达水平。

这里的要点是,不是使用一个常数因子来标准化所有基因,而是 SCnormSCTransform 方法都学习基因组特定因子。这些因子分别针对低、中和高表达基因,消除了技术变异的影响,保留了真正的生物异质性。

总结

标准化方法的选择影响高度可变基因的选择,从而影响所有下游的 scRNA 数据分析。将批量 RNA 标准化方法直接应用于 scRNA 数据集是不合适的。值得通过选择 SCNorm 或 SCTransform 规范化方法来更新分析管道,并充分利用最新的技术进步。

NoSQL 数据库——快节奏智能手机世界的解决方案

原文:https://towardsdatascience.com/nosql-databases-the-solution-to-a-fast-paced-smartphone-world-2636251efeb1?source=collection_archive---------32-----------------------

它们是什么以及为什么有用

图像来源

关系数据库是现代技术的基础组成部分。如今它们无处不在,特别是自从 20 世纪 70 年代以来(大喊 IBM!✊).它们无处不在,因为它们非常可靠,一旦你学会如何使用它们的代码,就很容易访问它们。您可以在一个有组织的地方存储、跟踪和分析所有数据。在大多数情况下,关系数据库是一个很好的选择。然而,由于我们生活在互联网和智能手机的时代,有些形式的数据不太适合传统的关系数据库。对于这些情况,我们可以利用一种更新的、不断发展的数据库——NoSQL 数据库。

推特——如果你没有推特,你就不酷。如今每个人都在发微博。事实上,根据 Brandwatch 的数据,每天有五亿条推文被发送。是的。从数字上看,有 5 亿条推文。每天。也就是每秒 6000 条推文!伙计们,这是大量的数据。但是,并不是每条推特都是一样的。有些推文只有一个字符,有些则使用了全部 140 个字符。有些人一年发一次微博,有些人一天一次,有些人一分钟一次。从所有这些中,有各种各样有趣的元数据可以收集和分析——账户名称、转发、评论、喜欢、发送时间、推特用户的位置、提及次数——仅举几例。这种快速的信息存储不太适合传统的数据库。**

但是……为什么呢?为了解释,我将使用一种类型的元数据作为例子——一条推文中的字符数。如果我使用传统的数据库,每个表都必须用一定数量的字符来表示 tweets。例如,“表— 1 个字符”、“表— 2 个字符”、“表— 3 个字符”等。,一直到 140 个字符。如果每条推特都是完全一样的长度,那么也许它可以工作,因为我会有,“推特 1,推特 2,推特 3……”但是,推特和它的推特用户不是这样。此外,一个关系数据库可能会有这样的问题,如果推特用户不止一次地使用同一条推特,它可能会存储同一条推特的多个副本。这会导致冗余,占用宝贵的空间,并可能使查询过程明显变慢。然而,对于 NoSQL 数据库来说,存储 tweet 元数据是最理想的情况。

有不同类型的 NoSQL 数据库,通常分为四类:

  • 键值存储
  • 列存储
  • 图形数据库
  • 文档存储

在这篇文章中,我将主要关注文档存储。一个 文档库 本质上是一个将其记录存储为唯一文档的数据库。流行的文档存储包括 Couchbase 和 MongoDB。它们的长度可以由用户决定,并且每个文档库可以包含多个文档。Tweets 非常适合这种情况——任何 tweet 及其元数据都可以存储为自己的唯一文档,然后这些信息可以嵌入到另一个文档中,该文档可以是发送 tweet 的 twitter 用户的。这就像一个文档…在文档里面…在文档里面(“盗梦空间”参考,仅供参考)。**

图像来源

然后,每个文档包含键值对——类似于熊猫中的字典——值是实际数据。然而,每个文档的键都是唯一的,这提供了难以置信的灵活性,因为键-值对不像传统的关系数据库那样必须使用相同的键。您可以根据需要为任何数据创建任何键。这种灵活性使得不可预测的数据,如 tweets 甚至文本消息,比更严格的关系数据库更容易管理。

然而,有一个重要的警告。随着数据存储灵活性的增加,查询数据的难度也在增加。很可能每个文档——因为每个文档都可以有自己的键——都可以有自己的模式。这意味着,作为数据分析师/科学家,你必须确切地知道你在寻找什么,并且你必须确保存储数据的人很好地保持键名的唯一性。“tweets”和“Tweets”是不同的名称,但是可以存储相同类型的信息。如果你运行一个查询来寻找“tweets”中的所有数据,那么“Tweets”中的所有信息都不会被收集,因为它们的键名是不同的!

我希望这篇文章能够让你对什么是 NoSQL 数据库以及为什么它们有用有所了解。感谢您的阅读!

领英

实时特征工程和 ML 模型的 NoSQL

原文:https://towardsdatascience.com/nosql-for-real-time-feature-engineering-and-ml-models-93d057c0a7b8?source=collection_archive---------29-----------------------

来源

使用流式数据构建用户配置文件

在我数据科学职业生涯的大部分时间里,我使用从数据仓库或湖泊中获取的数据来构建机器学习模型。使用这种方法,您可以通过应用 SQL 命令将几个事件转换成一个用户摘要,从而为每个用户创建一个特征向量。但是,这种方法的一个主要问题是,它是一个批处理操作,如果从应用程序发送的事件需要几分钟或几小时才能在数据存储中显示出来,则可能不包括用户的最新事件。

如果您需要在应用预测模型时使用最近的数据点,则可能有必要构建一个流数据管道,以近乎实时地应用特征工程来构建用户摘要。例如,一个电子商务网站可能希望根据 ML 模型的输出向用户发送一个通知,通知他们将商品添加到购物车中,但不结账。这个用例需要一个模型来使用基于最近 web 会话活动的数据,由于批处理和 ETL 操作引入的延迟,这在数据仓库中可能不可用。对于这种情况,为了提供最新的模型预测以确定是否向用户发送通知,可能有必要基于流数据集逐步建立用户概要。

我是一名为移动游戏发行商工作的数据科学家,我们会遇到类似的场景,我们需要使用最近的会话数据来确定如何为用户提供个性化的体验。我最近一直在探索 NoSQL 数据存储,将其作为一种构建近实时数据产品的方式,这些产品以最小的延迟执行特征工程和模型应用。虽然这篇文章将使用 Python 完成一个示例管道,但是想要亲自动手构建生产级系统的数据科学家应该探索 Java 或 Go,正如我在这里讨论的。在这篇文章中,我将介绍数据科学领域的 NoSQL,介绍使用 Redis 的选项,并演示一个使用 Redis 执行实时特征工程的示例 Flask 应用程序。

NoSQL 数据科学奖

NoSQL 数据存储是关系数据库的一种替代方式,它专注于最小化延迟,同时限制可以执行的操作类型。虽然有很多服务都属于 NoSQL 的概念,但最常见的实现之一是键值数据存储。使用键值存储,您可以以亚毫秒级的延迟从数据存储中保存和检索元素,但不能查询数据存储中的内容。您需要一个键作为保存值的索引,比如用户 ID,并且在检索值时使用相同的键。虽然这组操作对于习惯于使用关系数据库的数据科学家来说似乎是限制性的,但它提供的延迟和吞吐量性能比传统数据库快几个数量级。

数据科学家可能不熟悉这种类型的工作流,在这种工作流中,您可以对数据集执行创建-读取-更新-删除(CRUD)操作,因为使用批处理是很常见的,在批处理中,可以使用 SQL 将事件转换为用户摘要。对于键值数据存储,没有可用于聚集数据集的 SQL 命令,相反,用户概要需要以增量方式构建,其中由系统接收的新数据用于更新用户记录,例如每当用户在电话上打开游戏时递增会话计数。

使用 NoSQL 数据存储使得数据产品能够在接收到新数据时近乎实时地更新用户概要。这意味着,对于每个新数据点,用户的特征向量将只滞后几秒钟,而使用传统的数据仓库工作流时则需要几分钟或几小时。使用这种方法时有一个权衡,即与使用 SQL 数据库时可用的选项相比,您可以使用的功能类型是有限的。例如,在增量更新数据时,您不能计算非重复值或中间值,因为您是在处理单个事件,而不是用户的历史事件。然而,大多数使用实时数据的系统也将包括来自延迟过程的特征,该特征提供更完整的用户简档。例如,对于流数据,不可能计算用户播放的模式的不同数量(除非使用 1-hot 特征编码),但可以有一个批处理过程来计算该值,该值带有附加到特征向量的额外滞后。

当数据科学家需要构建增量更新而非批处理的用户配置文件时,他们应该探索 NoSQL 解决方案。这种工作流的一个常见用例是,当您需要根据最近的会话数据为用户提供个性化的治疗时。例如,先前选择了通知的用户可能更有可能在新游戏中与未来的通知进行交互。移动游戏发行商可以利用该会话数据来为用户提供个性化体验。

为了提供一个具体的例子,我们将使用 Kaggle NHL 数据集来提供一个流数据源,曲棍球运动员的个人资料将根据实时数据源进行增量更新,并通过 web REST 调用来实现。这个示例应用程序的输出将是存储在 Redis 中的用户配置文件,然后可以用于实时应用 ML 模型。我们将关注特征工程步骤而不是模型应用步骤,但是展示了用户简档如何可以用于模型预测。

在这个练习中,我们将使用 Redis 作为我们的 NoSQL 解决方案。虽然 Redis 有类似的替代方案,如 Memcached,但 Redis 是一种跨多种编程语言工作的标准,并在流行的云基础设施上管理实现。Redis 应该被视为一种短暂的缓存,这意味着如果您的用户配置文件需要长期持久性,它可能不是最佳方法。然而,如果你正在构建面向新用户的 ML 模型,这是一个很好的选择。

对于数据科学项目的 NoSQL,通常使用数据存储根据传递给数据产品的实时数据来更新用户配置文件。对于流数据,这个端点可以设置为将数据作为 REST 命令进行处理,或者设置为处理来自 Kinesis 和 Kafka 等工具的数据流。我们将通过一个样例部署来设置一个 REST 端点,该端点使用 Redis 递增地更新用户配置文件。

Redis 部署

有各种不同的选项来设置 Redis 实例,该实例将用于为您的机器学习项目缓存数据。以下是一些可用的不同选项。

  1. 模拟实现:Python 的 fakeredis ,Java 的 jedis-mock
  2. 本地部署:在本地构建和运行,或者使用 Docker
  3. 托管部署:在云中的集群上运行 Redis
  4. 托管部署:AWS elastic cache、GCP Memorystore、 Redis Cloud

当开始使用 Redis 时,使用模拟实现对于学习 Redis 的接口非常有用。此外,模拟实现对于为您的应用程序设置单元测试非常有用。一旦您想了解应用程序的潜在吞吐量,最好直接或通过 Docker 迁移到运行在您机器上的 Redis 的本地实例。这将使您能够测试与 Redis 的连接,并更好地了解应用程序的概要分析。

一旦您希望将系统投入生产,那么您将希望迁移到 Redis 集群,它可以是云平台上的托管解决方案,您负责在机器集群上提供和监控 Redis,或者您可以使用托管解决方案来处理维护集群的所有开销,同时提供相同的 Redis 接口。托管解决方案非常适合在生产应用程序中启动和运行 Redis,但是在为 Redis 选择托管解决方案还是托管解决方案或其他 NoSQL 解决方案时,需要考虑一些因素:

  1. 您的延迟要求是什么?
  2. 你的内存需求是什么?
  3. 您的吞吐量要求是什么?

使用托管解决方案,您可以确保 Redis 集群与您的数据产品位于同一位置,以确保您的服务和 Redis 实例之间的最小延迟。使用 GCP Memorystore,您可以将这两个集群配置为位于同一个可用性区域内,这将导致 Redis 命令的亚毫秒级延迟,但是在使用托管方法时,您将无法配置您的实例。

决定托管还是托管方法的可能因素是群集的预期成本。使用 Memorystore 时,你需要支付每 GB 每小时的费用,并且根据容量有不同的定价等级。读取或写入命令也可能会有变化,这是 AWS 上 DynamoDB 定价的一部分。如果成本看起来合理,那么使用托管选项可能是首选,因为它可以减少您的团队维护集群所需的开发工作量。如果您有较大的内存需求,例如每个区域超过 1TB,那么托管解决方案可能无法扩展到您的使用情形。

在这篇文章中,我们将坚持 Redis 的模拟实现,保留与 Python 编码相关的所有内容,因为 Redis 是一个庞大的主题,读者应该在这篇文章之后更详细地探索它。

Python 中的实时应用程序

为了实时模拟构建特征向量,我们将使用 Kaggle NHL 数据集。这个数据集中的 game_skater_stats.csv 文件提供了球员级别的比赛摘要,比如一场比赛中完成的射门次数、进球次数、助攻次数等。我们将读入该文件,将行过滤到单个播放器,然后遍历事件并将它们发送到 Flask 端点,该端点将更新用户配置文件。发送事件后,我们还将调用端点,使用简单的线性回归模型来获取更新的玩家分数。目标是展示如何设置 Flask 端点来处理流数据集并为实时模型预测服务。这篇文章的完整代码可以在 GitHub 的 Jupyter 笔记本上找到。

[## NHL 游戏数据

游戏、团队、玩家和游戏信息,包括 x、y 坐标

www.kaggle.com](https://www.kaggle.com/martinellis/nhl-game-data)

对于想开始使用 Python 的 Redis 新手读者来说,参考 redis-py 文档以获得关于 Python 接口的更多细节是很有用的。在本文中,我们将使用一个模拟 Redis 服务器来演示基本功能,该服务器实现了该接口的一个子集。要开始使用,请安装以下 Python 库:

pip install pandas
pip install fakeredis
pip install flask

接下来,我们将使用 Redis 运行 CRUD 命令。下面的代码片段展示了如何启动一个进程内 Redis 服务,并使用键12345检索记录。由于我们还没有存储任何记录,print 语句将输出None。代码片段的其余部分显示了如何创建、读取、更新和删除记录。

要在 Redis 中创建一个记录,这是一个键-值条目,我们可以使用set命令,该命令接受键和值参数。您可以将这个键视为 Redis 用来检索值的索引。上面的代码检查记录,如果没有找到记录,则创建一个新的用户配置文件作为字典,并使用球员 ID 作为关键字将对象保存到 Redis。

接下来,我们使用 Redis 中的get命令读取记录,该命令检索保存到数据存储的最新值。如果没有找到记录,则返回值 None。然后,我们使用 json 库将 Redis 返回的字符串值翻译成一个字典。

接下来,我们通过增加 sessions 值来更新用户摘要,然后使用set命令将更新的记录保存到 Redis。如果您多次运行 create、read、update 命令,那么每次运行时您都会看到会话计数更新。

上面显示的最后一个操作是删除操作,可以使用过期或通过删除密钥来执行。delete命令立即从数据存储中删除键-值对,而expire命令将在指定的秒数过后删除该对。使用expire命令是一个常见的用例,因为您可能只需要维护最近更新的数据。

接下来,我们将把 NHL 数据集作为 Pandas 数据帧拉入内存,然后遍历该帧,将行翻译成字典,并将事件发送到我们将要设置的端点。现在,您需要注释掉 post 并获取命令,因为服务器还没有运行。

对于这个例子,我们将数据帧过滤为玩家 ID 等于 8467412 的行,这导致了 213 条记录。一旦我们设置了端点,我们就可以尝试遍历所有的记录来测试端点的性能。

下面的代码片段显示了设置两条路线的示例 Flask 应用程序的代码。/update路线在应用中实施特征工程工作流程,而/score路线使用简单的线性模型实施模型应用。

更新路径使用 CRUD 模式在收到新数据时更新用户配置文件,但它不包括删除或过期步骤。当新的事件被发送到服务器时,应用程序将获取最新的玩家摘要,用新的数据点更新记录,然后保存更新的配置文件。这意味着概要文件会随着数据流向服务器而实时更新,从而最大限度地减少模型管道中的延迟。使用这种方法进行特性工程时需要注意的一点是,与 SQL 相比,只有一部分特性可以使用,因为聚合命令不可用。您可以更新计数器、设置标志、计算平均值,但不能执行计算中值或计算非重复值等操作。

更新路径采用玩家 ID,并根据检索到的特征向量返回一个分数(如果可用)。它从查询字符串中解析玩家 ID,然后获取相应的玩家摘要。此摘要中的值与硬编码线性回归模型的系数相结合,以返回模型预测。结果是一个端点,我们可以调用它来使用最新数据实时获得模型预测。

我们现在有一个模拟服务,展示了如何使用 Redis 作为数据存储来实时执行特性工程和建模应用程序。在实践中,我们将使用 Redis 集群替换模拟 Redis 实现,使用模型存储来应用 ML 模型,使用诸如 gunicorn 之类的 WSGI 服务器运行 Flask 应用程序,并使用 Docker 和 Kubernetes 之类的工具扩展应用程序。将这个工作流投入生产有许多不同的方法,但是我们已经用一个简单的服务演示了核心循环。

结论

当数据科学家需要从批处理工作流转移到流工作流来构建预测模型时,NoSQL 工具非常有用。通过使用 NoSQL 数据存储,工作流中的延迟可以从几分钟或几小时减少到几秒钟,使 ML 模型能够使用最新的输入。虽然数据科学家通常不会接触这些类型的数据存储,但有多种方法可以接触到 Redis 等工具,甚至可以在 Jupyter 笔记本中构建原型服务。

使用 Redis 扩展实时特征工程服务时,会出现各种不同的问题。一个问题是对一个键的并发更新,这可能发生在不同的线程或服务器更新一个概要文件的时候。这可以用检查和设置模式来处理。在模型应用程序方面,也有一些问题,比如模型维护,通常有不同的服务来构建特征向量和应用模型。

Redis 和其他 NoSQL 解决方案只是为数据科学工作流实施实时特征工程的一种方式。另一种方法是使用 Kafka 或 Kinesis 等流系统,以及 Kinesis Analytics 或 Apache Flink 等流处理工具。最好探索不同的方法,以便找到最适合您组织的数据平台和服务的解决方案。

本·韦伯是 Zynga 杰出的数据科学家。我们正在招聘

用 Python 实现云上的 NoSQL

原文:https://towardsdatascience.com/nosql-on-the-cloud-with-python-55a1383752fc?source=collection_archive---------6-----------------------

与 Google Firestore ——(最好的)NoSQL 数据库交流

照片由Unsplash

作为数据科学家、机器学习工程师或开发人员,熟悉云是改变游戏规则的技能之一。

无论我们在哪个领域工作,数据总是关注的焦点,我们的最终用户紧随其后。一个好的基于云的数据库服务将满足这两种需求。

我们将数据卸载到最终用户能够通过任何人都可以使用的界面访问的位置。这个界面可以是一个网络应用——或者是面向更多技术终端用户的 API。

Firestore 是谷歌的云托管 NoSQL 数据库服务。该服务有几个主要优势,即:

  • 灵活的数据存储(NoSQL)
  • 本地库支持大多数流行的语言( Python )
  • 你为免费学习(超越免费层限制需要大量数据)
  • 一切都很简单——我们可以建立一个比煮咖啡还快的数据库
  • 认证(可以)由谷歌处理,我们以最少的工作实现最大的安全性
  • 自动缩放以满足需求
  • 直观的文档,可能是三大云提供商(Azure、AWS、GCP)中最好的

在本文中,我们将设置我们的 Firebase 项目(托管 Firestore 的平台),使用 web-UI 创建一个数据库,并创建一个执行所有基本 Firestore 功能的简单 Python 脚本。它看起来会像这样:

**In Firebase**
> Create a Project
> Initialize Database
> Get Credentials
**In Python**
> Install **gcloud** Libraries (+ venv)
> Authenticate
> Connect to Firestore
> Get
> Create
> Modify
> Delete
> Queries

让我们开始吧。

重火力点

创建项目

幸运的是,谷歌擅长让事情变得简单。进入 Firebase 网站并点击大开始按钮。

我们现在应该看到上面的“欢迎使用 Firebase”页面——创建一个项目,并给它起一个很酷的名字(它应该也与您的项目相关)。

我把它命名为“反重力”。

您应该会看到一个窗口,询问我们是否希望启用 Google Analytics——这完全是您的选择,我们不会使用它,但它也不会花费您任何费用。

我们的项目将初始化,单击继续,我们将进入新项目的项目概述页面。

初始化数据库

为了初始化我们的 Firestore 数据库,我们导航到侧栏并单击开发 > 数据库。在这里,我们将看到上面的“云 Firestore”页面—单击创建数据库

在这里,我们将被询问是以生产模式还是测试模式开始。我们将使用测试模式

接下来,选择您的位置——这是您或您的用户请求数据的地方,所以选择最近的选项!

点击开始收藏添加“地点”收藏和“罗马”文档——这也是真正的旅行建议。

最后,我们可以访问我们的数据库。对于本教程,我们需要一个名为“places”的集合和一个名为“rome”的文档,如上所示——只需点击 Start collection 来添加它们(where_to_go是一个数组)。

移交给 Python

安装依赖项

我们需要 pip 安装firebase_admin包:

pip install firebase-admin

对于 Python 以上的任何版本,当将firebase_admin导入到我们的脚本时,我们都会收到一个语法错误:

如果使用从 3.7 开始的任何版本的 Python,我们将引发一个语法错误

Python 3.7 中添加了async标识符,打破了firebase_admin模块。我们有两个选择:

  1. 修改firebase_admin,用_async (或者你选择的任何关键字)替换async的每一个实例。
  2. 通过虚拟环境(venv)使用 Python 3.6。

选项(1)可能是个坏主意。因此,让我们快速介绍一个使用 Anaconda 的 venv 设置(关于如何在其他环境中使用,请咨询 Google 或我)。

打开 Anaconda 提示符并创建一个新的 venv(我们称之为fire36):

conda create --name fire36 python

启动 venv 并安装firebase_admin组件:

conda activate fire36
pip install firebase_admin

如果您使用 Jupyter 或 Spyder,只需输入jupyter | jupyter lab | spyder就可以使用这个 venv 编写代码。PyCharm 和 VSCode 也可以使用这个 venv。

鉴定

要访问 Firestore,我们需要大量凭证。谷歌再次让这变得简单。

Firebase 控制台中导航到您的项目。

在左上角的“项目概述”旁边,点击齿轮图标并选择项目设置

现在,我们单击“服务帐户”选项卡,在这里可以找到关于使用 Firebase Admin SDK 进行身份验证的说明。

点击生成新的私有密钥以 JSON 文件的形式下载我们的凭证。

现在,我们需要点击生成新的私钥。我们下载该文件,将其重命名为serviceAccountKey.json(或其他名称),并将其存储在 Python 脚本可访问的位置。

serviceAccountKey.json存储在同一个目录中进行测试是可以的——但是保持 JSON 内容的私有性。 Public GitHub repos 是一个可怕的 的地方,为凭据。

在同一个 Firebase Admin SDK 页面上,我们可以将 Python 代码复制并粘贴到脚本的顶部。我们需要做的就是更新到serviceAccountKey.json的路径,并将firestore添加到我们的导入中——我们的脚本应该是这样的:

import firebase_admin
from firebase_admin import credentials, **firestore**cred = credentials.Certificate(**"path/to/serviceAccountKey.json"**)
firebase_admin.initialize_app(cred)

这就是我们认证所需要的一切。现在我们(终于)开始写一些代码了!

连接到 Firestore

我们的联系有三层:

数据库>收藏>文档

db = firestore.client()  # this connects to our Firestore database
collection = db.collection('places')  # opens 'places' collection
doc = collection.document('rome')  # specifies the 'rome' document

我们依次访问每一层——从数据库(反重力-207f8) > 集合(地点)> 文档(罗马)。

每一层都有自己的一套方法,允许我们在数据库、集合或文档级别执行不同的操作。

得到

我们使用 get 方法来检索数据。让我们用这个方法得到我们的rome文档:

doc = collection.document('rome')
res = doc**.get()**.to_dict()
print(res)**[Out]:** {
    'lat': 41.9028, 'long': 12.4964,
    'where_to_go': [
        'villa_borghese',
        'trastevere',
        'vatican_city'
    ]
}

我们还可以对collection执行.get()操作,返回包含其中所有文档的数组。如果我们有两个文档,它看起来会像这样:

docs = collection**.get()**
print(docs)**[Out]:** [
  <google.cloud.firestore_v1.document.DocumentSnapshot object ...>, 
  <google.cloud.firestore_v1.document.DocumentSnapshot object ...>
]

这些文档被存储为 DocumentSnapshot 对象——与我们在使用上面的.document(<doc-id>).get()方法时收到的对象类型相同。和第一个get例子一样——我们可以使用.to_dict()将这些对象转换成字典。

创造

我们在collection上使用.document(<doc-id>).set()方法创建文档。.set()方法获取一个字典,其中包含我们希望存储在新<doc-id>中的所有数据,如下所示:

res = collection.document('barcelona')**.set(**{
    'lat': 41.3851, 'long': 2.1734,
    'weather': 'great',
    'landmarks': [
        'guadí park',
        'gaudí church',
        'gaudí everything'
    ]
}**)**
print(res)**[Out]:** update_time {
    seconds: 1596532394
    nanos: 630200000
}

如果操作成功,我们将在响应中收到update_time

新数据将出现在我们的 Firestore GUI 上。

通过导航回 Firestore 界面,我们可以看到如上所示的新文档数据。

修改

有时,我们需要修改现有的文档,而不是创建一个全新的文档。有几种方法可以做到这一点,这取决于我们想要改变什么。

为了更新完整的键-值对,我们使用update:

res = collection.document('barcelona')**.update(**{
    'weather': 'sun'
}**)**

update 方法允许我们只修改语句中的键值对。

update方法适用于大多数值,但是当我们只想添加或删除数组中的一个条目时,它就没那么有用了。这里我们使用firestore.ArrayUnionfirestore.ArrayRemove方法分别添加和删除单个数组值,如下所示:

collection.document('rome').update({
    'where_to_go': **firestore.ArrayUnion(**['colosseum']**)**
})

我们已经更新了 where_to_go 数组以包含斗兽场

移除vatican_citytrastevere:

collection.document('rome').update({
    'where_to_go': **firestore.ArrayRemove(** ['vatican_city', 'trastevere']
**)**})

去向阵列中移除梵蒂冈城斗兽场后。

删除

其他时候,我们可能需要删除全部文档。我们用delete方法来做这件事:

collection.document('rome')**.delete()**

我们的 Firestore 数据库不再包含罗马文件。

如果我们想删除文档中的单个字段,我们可以像这样使用firestore.DELETE_FIELD:

collection.document('barcelona').update({
    'weather': **firestore.DELETE_FIELD**})

巴塞罗那文档不再包含天气字段。

询问

更进一步,我们可以具体说明我们到底想要什么。

我们的 Firestore 现在包含巴塞罗那、布里斯班、纽约和罗马的条目。

对于这个例子,我们已经向 Firestore 添加了几个全球城市(添加它们的代码是这里是)。

我们将查询欧洲范围内的所有城市——我们将这些城市定义为经度大于 -9.4989 (西方)且小于 33.4299 (东方)的城市。为了简单起见,我们将忽略纬度。

为了查询我们的 Firestore,我们在集合对象上使用了where方法。该方法有三个参数,where(fieldPath, opStr, value):

  • fieldPath —我们的目标区域,在本例中为'long'
  • opStr —比较操作字符串,'=='检查相等性
  • value —我们要比较的价值

我们的查询将返回任何真值。对于我们的示例,我们将找到包含long > 9.4989的文档,我们写为:

collection**.where('long', '>', 9.4989)**.get()

从我们的 long > 9.4989 查询返回的所有文档。

对于这个查询,我们返回barcelonaromebrisbane——但是我们也需要排除欧洲东部的任何东西。我们可以通过添加另一个where方法来做到这一点,如下所示:

collection**.where('long', '>', -9.4989)** \ **.where('long', '<', 33.4299)**.get()

从我们的 long > 9.4989 和 long < 33.4299 查询返回的所有文档。

这就是对谷歌 Firestore 的介绍。对于简单、安全和健壮的基于云的数据库,Firestore 真的很棒。

当然,云计算不仅仅是数据存储。AWS 和 Azure 都很棒,但 GCP Firebase 配置的易用性是其他任何产品无法比拟的。

只需很少的时间,就可以轻松学会构建完整应用程序所需的一切,从前端 UI 到数据存储设置。

如果云对你来说有些陌生,不要犹豫,马上加入——这是一项非常宝贵的技能,不容错过。

如果你有任何建议或者想和我讨论 Firestore——或者开始使用云——请随时在 Twitter 上或者在下面的评论中联系我。

感谢阅读!

有兴趣了解更多的另一面吗?请随意阅读我对 Angular 的介绍——这是一个神奇而简单的前端框架:

[## 如何使用 Angular 部署 TensorFlow Web 应用程序

在角度构建的 web 应用程序中使用 Python 构建的模型

towardsdatascience.com](/how-to-use-angular-to-deploy-tensorflow-web-apps-5675b5a042cc)

不是漏斗!使用 Sankey 代表您的销售过程

原文:https://towardsdatascience.com/not-a-funnel-use-sankey-to-represent-your-sales-process-9621b6578c42?source=collection_archive---------38-----------------------

传统的销售可视化错过了销售过程中正在发生的关键信息。

作者图片

与公司的其他部门(营销、运营、财务)相比,销售仍然不是一个以数据为中心的环境。尤其是当我们考虑 B2B 销售时。改变我们看待销售线索的方式可以大大提高您团队的绩效。

销售漏斗

多年来,销售主管最重要的实践之一是每周回顾销售漏斗。这个漏斗本质上是每个销售过程中的销售线索量,或可能的收入量(以 PV、一次性收入等形式)。这个工具被广泛使用,几乎包含在所有的 CRM 软件中,作为销售模块的一部分。

漏斗的目标是从 10,000 英尺的高度概括钱在哪里,销售团队的工作应该在哪里。问题是这样的:工具只给我们显示了当前状态的截图。跟踪和预测销售是有用的,但是,可视化上的微小变化可以带来巨大的好处。

理论上,销售线索应该从一个阶段进入另一个阶段,然后在某个时候停止前进或以销售结束。事实上,销售线索会前后跳跃,这使得当前的漏斗视图用处不大。在这里,使用桑基图将改善销售团队的概况,并发现过程中可能存在的问题或不正常的趋势。

理想的销售漏斗

让我们从最完美的场景开始。在这种情况下,销售线索从一个阶段平稳地转移到另一个阶段。这非常适合传统的漏斗来显示数据。因此,在这种情况下使用 Sankey 不会为我们提供更多关于销售线索中正在发生的事情的信息或见解。但是,使用桑基图,我们可以直观地获得一个额外的信息,即从一个阶段转移到另一个阶段的销售线索的比例。

作为桑基图的理想销售漏斗(作者图片,源代码此处

您可以在此查看互动桑基

所以,我们的理想世界现在结束了,我们将进入 3 种比任何销售经理都喜欢的更常见的情况,有时它们不容易马上发现。

跳过销售漏斗阶段

许多销售人员不需要完成销售流程成功所需的所有里程碑。因此,对于一些公司来说,销售线索跳级是很常见的。在一个经典的漏斗中,从一周或一月的回顾到另一周或一月的回顾,你看不到变化是怎样的。这是第一个使桑基图成为销售团队的重要补充的功能。
在下面的桑基图中可以看到一个跳过阶段的例子。

当销售流程允许销售线索跳过一些阶段时,使用传统的漏斗表示意味着信息的丢失。(图片作者,源代码此处)

您可以在此查看互动桑基

多输入和分阶段销售漏斗

公司越大,他们的营销组合和销售线索就越广。对于许多公司来说,他们有不同的方法来解决这个问题:为每个营销渠道建立一个单独的漏斗。或者,他们可以在销售线索进入公司后的一个阶段启动销售漏斗。这意味着失去所有以前的历史记录,只显示销售团队关于销售线索起点的绩效。
将两者混合在同一个图表中,可以给出销售和(在某些情况下)营销计划的统一愿景,从而对每个部门起到补充作用。作为一个类似的效果,一个特定的里程碑可能在领导的规模、项目的复杂性或其他区别特征方面有所不同。因此,一个阶段也可以分为两个或更多的子阶段,其中响应时间和其他属性是不同的,没有显示这种效果的经典漏斗将对销售预测产生很大影响。所有这些影响都可以在桑基图中同时显示出来。下图是一个很好的例子,其中销售线索来源于两个不同的渠道(阶段 1),此细分也在阶段 2 和阶段 3 中进行了描述,以便更好地表示每个渠道在各个阶段的权重。此图还显示了这两种销售线索的其余流程是相同的,并且他们共享资源。

一些销售流程涉及到从多个来源获取销售线索,甚至需要根据销售线索将一个阶段分为两个或更多阶段。通常,会使用多个正常漏斗,但使用桑基图,我们可以将所有信息放在一起。(图片作者,源代码此处)

可以在这里查看互动 Sankey

在漏斗上向后移动

漏斗中可能发生的最后一件事是倒退。发生这种情况有不同的原因:流程中的错误、前一阶段的文件丢失,或者仅仅是因为销售流程允许。能够跟踪销售流程逆向移动的数量、金额和渠道将有助于制定可操作的计划,并更好地调整销售和营销策略。
在下图中,我们可以看到所有阶段都有一定比例的销售线索返回到之前的阶段。这种影响增加了工作量和销售线索所需的平均时间。

(图片作者,源代码此处)

点击可以查看互动桑基

最后的话

正如我们所看到的,能够改变一个简单的可视化将大大提高我们从销售数据和流程中获得的洞察力。我们举了几个例子,但通常情况下,不仅仅是其中一种效应会发生,很多效应会同时发生。如果你从事销售或商业智能工作,我邀请你对你的销售过程进行一次全面检查。使用桑基图,检查它是否像你的经典漏斗,你能从中获得什么新的见解。从那里开始改善你的销售流程。

您可以在这里的链接中访问用于创建桑基图的 Jupyter 笔记本:图代码

不是另一个新冠肺炎数据分析!

原文:https://towardsdatascience.com/not-another-covid-19-data-analysis-d7b7df1ddc90?source=collection_archive---------44-----------------------

意见

不,实际上不是。这就是我不打算发表新冠肺炎数据分析/预测的原因…

新冠肺炎确实是眼下的热门话题;新闻上到处都是,这可能是大多数谈话的主题。媒体上涌现出许多数据分析和数据分析文章,展示了一些非常酷的疾病可视化和预测。你可能很高兴知道,这真的不是那些帖子中的另一个,我将解释为什么…

疾控中心Unsplash 拍摄的照片

我是一名婴儿数据科学家,即使这样也有点夸大事实。当然,我对能利用新冠肺炎的数据做些什么很感兴趣,但我也非常清楚自己能力的有限性。我只是最近才开始涉足数据科学,尽管我已经编程 7-8 年了。

我们也处在一个非常有趣和动荡的时代——我毫不怀疑,在未来的几年里,这段时间将成为学校历史课的一部分!然而,这也是我们需要注意身体和精神健康的时候。有这么多关于新冠肺炎的信息,但哪些是准确的呢?我们应该相信什么?所有这些黯淡的预测都是真的吗?

结合这两件事:我缺乏数据科学经验和我们生活中新冠肺炎(错误)信息的饱和,我决定不发表一篇预测死亡人数或传播速度的文章。

不要误解我,我相信数据科学将在社会克服这种以及未来的疾病中发挥重要作用,但是,我不会为此做出重大贡献。

如果这真的是我的目标的话,还有很多其他数据集可以让我练习我的技能。但是发表一篇关于我对新冠肺炎数据分析的文章,我觉得只会产生负面影响。思考两种不同的场景…

  1. 在初步分析中,我没有发现什么新的东西,所以我只是对新冠肺炎已经饱和的黯淡前景做出了贡献,从而影响了心理健康。
  2. 我预测了别人没有的东西(对于我可能生产的简单模型来说,可能性很小),但我不能完全证明这一点,我也不知道这是因为我做错了什么,还是因为我的模型不够好。因此,传播虚假信息或“假新闻”。

是的,新冠肺炎是一个热门话题。

是的,数据科学很可能有助于克服这一点。

但是,这并不是说发表一篇展示婴儿数据科学家研究成果的文章是一件好事。

我的目标是实践我的技能,并有效地交流我的发现,就像许多数据科学家一样。但是,我也觉得我们都对彼此负有责任。我可以使用大量其他数据集来练习这些非常相同的技能,这些数据集对人们来说不太感兴趣,但也不会对他们产生太大的负面影响。或者,如果我积累了足够多的技能,也许我可以产生一些真正的影响,关注世界上其他重要的事情,这些事情正在被忽视或遗忘,而关注的焦点是新冠肺炎。

这就是为什么我要把这项工作的数据预测和公共交流留给那些真正知道自己在做什么的人。

让我们想一想,我们是否真的需要发表更多关于新冠肺炎的文章,或许应该关注世界上其他被遗忘的重要事情。

与 NumPy 一起生成矩阵

原文:https://towardsdatascience.com/not-for-the-data-science-only-generate-matrices-together-with-numpy-d33f03d8875f?source=collection_archive---------18-----------------------

Python 技巧

创建 2d 阵列的 NumPy 函数的综合列表

Anton Vietrov 在 Unsplash 上拍摄的照片

NumPy 位于最初与数据科学相关联的 Python 库中。但是,很明显,它是一种处理高维数组、矩阵和表的通用工具。虽然应用程序的数量太大,无法在一篇文章中描述,但我想关注一个非常有用的特性:2d 数组生成。你可能会想,我们为什么要为此烦恼呢?因此,我会提醒我们在每个项目中产生的数百个微小的操作,而没有注意到它们:默认变量的值生成、单元测试的数据创建、中间结果的准备、转换矩阵、“哑”值,等等..准备这些值需要一些时间,在项目开发结束之前,你会意识到它们的必要性。

1.顺序

你可能会感到惊讶,因为我已经把二维数组作为本文的主题。虽然数组到矩阵的转换非常普遍,所以这是有意义的。让我们来探索一对 NumPy 原生的把戏。

例如,对于序列:

重塑它:

增加维度:

由于我们有将数组转换为矩阵的工具,我们可以将其应用于传统的np.arange()序列发生器,例如:

np.arange(1, 12, 2).reshape(2, 3)

2.随机数

当然,我们不能忽略随机序列,因为它们在测试中被过度使用。Numpy 基于不同的公式提供了大量不同的随机分布。虽然我们将回顾创建随机矩阵的最常见的方法,但所有其他方法也可以类似地使用:

np.random.random([3,3]) —样本来自均匀[0,1)分布的 3x3 矩阵

np.random.randn(3, 3) —3×3 矩阵,样本来自均值为 0、方差为 1 的单变量“正态”(高斯)分布

np.random.randint(0, 2, size=(3, 3)) —3×3 矩阵,随机整数来自[0,2]区间。

3.分布

我们再次使用数组,但是我们不能错过这样重要的函数,它在指定的时间间隔内产生连续的数据分布。

  • np.linspace() —线性分布(等步长)

  • np. logspace() —对数分布

  • np.geomspace() —几何分布(有相等因子)

4.阵列复制

这是填充函数的一个很好的例子,它接受一个数组,并将其复制几次以获得一个矩阵。我们必须设置行数和一行中的重复次数(按照这个顺序)。

5.对角矩阵

对于矩阵的中间运算,我们可能需要对角运算。也是线性代数中的基本元素之一。不足为奇的是,NumPy 为它们的创建提供了几个函数。

  • 来自数组

  • 带 1 的方阵

  • 具有自定义对角线的自定义大小的 1s 矩阵

6.np.zeros()

它创建了一个完全由 0 填充的矩阵。它是变量默认值或哑返回值的完美候选。

您也可以使用np.zeros_like()创建一个自定义大小的 0 矩阵。

7.np.ones()

默认值矩阵的另一个例子,这次用 1 填充。

同样,你可以使用另一个数组作为np.ones_like()的模板。

8.np.full()

前面的函数使用定义的填充值创建矩阵。但是 NumPy 还提供了一个自定义填充的功能。

9.三角形矩阵

线性代数运算的另一个重要元素:矩阵 a 的一半用 0 填充。NumPy 对三角形矩阵有三个主要函数:

  • np.tri() —创建一个下部填充的三角形 1s 矩阵
  • np.tril() —从自定义数组创建一个三角形矩阵,其下半部分被填充
  • np.triu() —从一个自定义数组创建一个三角形矩阵,填充上半部分

10 完全自定义矩阵

NumPy 函数山的顶峰是 np.fromfunction()。它根据用户定义的函数创建一个自定义大小的矩阵。函数应该接受与矩阵维数相等的参数个数,如果需要,还可以接受其他值。生成将从索引(0,0)开始,每个坐标的步长为 1。

你可以在我的 GitHub 上找到一个完整的带有示例的笔记本:

[## 中级/中等 _jupyter_notes

github.com](https://github.com/Midvel/medium_jupyter_notes/blob/master/matrices_generation/generate-matrices.ipynb)

NumPy 库是任何线性代数运算的完美工具。它充满了有趣的功能,可以创造性地使用。你可以自由分享你最喜欢的 NumPy 技巧。

不是千与千寻:在分散注意力的工作环境中记笔记

原文:https://towardsdatascience.com/not-spirited-away-keeping-notes-in-a-distracting-working-environment-af43140e1fb1?source=collection_archive---------63-----------------------

尤利娅·卢卡希娜

数据科学家在动荡的工作环境中保持高效的一些生活窍门。不包括辞职。主要基于 Jupyter,但也支持其他数据科学工具。

我想总结一下我做笔记、写待办事项清单、写工作日记来对抗分心的实验。

我的第一份正经工作发生在一家重视时间追踪的公司。它使用了一个基于 Confluence 的工具——我现在已经忘了它的名字——将项目分解成一系列任务。

在接下来的工作中,我采用了一些方法。他们证明了他们的必要性,因为我们的伞式项目接近最后阶段,整体压力增加。在上线前的最后几天,我们有很多自发的会议。他们让我在进程中离开我的任务,从我被打断的同一点开始并不容易。

没有那么明显的办公室干扰

为什么要费心记笔记,这不是迂腐吗?它与效率和生产力有什么关系,难道不需要更多的时间吗?

让我们想象一个典型的办公室日…

我只想喝杯咖啡。但是因为我们有一个厨房给很多人用,所以总是以不可避免的闲聊结束。我通常是一个内向的人。每一次社交活动都吸引了我并不丰富的社交能力。因此,我花了一些时间来降低我的情绪投入,重新开始工作。

此外,我们有一个非常方便游客的数据科学办公室。门一整天都开着。很多人过来打招呼,谈论晴朗的天气。如此高水平的办公室社交是有代价的。这个代价就是我们的专注。

“恢复”持续了 10 到 15 分钟,然后我才能再次完全集中注意力。一天之内会有很多会谈。

事实上,我们开了很多会。当你知道一个会议将在半小时后召开时,你不可能开始任何需要你全力投入的大事。

朱皮特

因为这些挑战,Jupyter 笔记本成了我的最爱。如果我不得不站起来离开,我会留下完整的数据记录,包括成功的和失败的。我想给你一些见解。

在从我的 Mac 电脑迁移到 iPadPro 后,我暂时从 Jupyter 笔记本转向了谷歌合作研究。它有一个相似的界面。我在 Jupyter 只使用了基本的按钮,它们似乎在 Colab 的同一个地方。

实际上,我想使用 Juno,但是在我阅读了一些操作指南之后,我就不再那么有热情了。我偶然发现了 Colab,现在我在浏览器中使用它。我只需要警告那些处理大量数据的人。你应该检查一下,Colab 处理大量数据的速度有多快。目前,我不会为此做广告。

Microsoft OneNote

由于代码中的注释不是用于进度跟踪的,所以我将笔记保存在不同的工具中。

我没有尝试过很多记笔记的应用程序,但在开始使用 OneNote 后,我不想寻找替代方法。它允许我将笔记组织到文件夹中,并且它提供了许多附件格式。

因为我负责检查在混合迁移期间并行运行的两个平台之间的数据一致性,所以我经常需要在手边准备大量的。CSV 或 Excel 文件。在 OneNote 中,我可以将它们直接插入笔记本。

桌面版也有一种格式样式,可以突出显示我经常直接保存到 OneNote 中的代码块。我最后喜欢的功能是时间戳。我可以看到我什么时候开始任务,什么时候完成任务。可以快速估计每项任务的持续时间。对我和项目经理都有好处。

我的工作日记曾经是这样的:

Microsoft OneNote 屏幕截图

我也滥用 OneNote 作为备份工具。我用我的中间结果保存了多个文件。我总是可以通过访问我的日记回到旧版本。

大量的图标选择,尤其是待办事项图标,有助于在笔记变得过大时突出显示重要内容。

我用来写这篇文章的 iOS 版本错过了时间戳(只有日期)和插入代码块。然而,我喜欢再次使用它,我只能推荐它。

一个用例

把你的一天分成几个任务,然后完成它们!

我想从 OneNote 开始。记笔记训练了我,让我在前一天结束时计划我的一天。这让我在第二天早上节省了时间。白天,我会添加一些临时任务。

那么,让我们从一个例子开始。对于一些说明性的部分——比如代码块——我选择了非常简化的部分,以便为每个读者提供一个共同点。

想象一下,我需要可视化谷歌地理定位位置的实际覆盖范围。它是 Google 定位工具支持的位置及其邮政编码的集合。如果未包含邮政编码,则您无法定制您的活动,也无法将它定位于特定位置。

因此,前一天晚上,我在 OneNote 中记下了以下任务:

您可能已经注意到,我正在数据科学笔记本上工作。我也可以有其他的笔记本。我在工作日记的每个条目的标题前放了一个日历周数。在我们敏捷工作的日子里,这很方便,我们的工作量被分成了两周的 scrum 冲刺。

除了分心,你还可能在任务中遇到问题。如果你记录下你一天中所做的所有工作,你就不会有太大的麻烦去回忆你为什么停止做某事,转而去做其他的事情。

我们无法下载地理定位位置。我将在下一节展示更多的细节。

让我们把一个失败通知放在我们最初想做的任务旁边,并把它删除掉,而不是把它标记为完成。

然后,我们仔细考虑情况,并添加一些我们需要的待办事项,以获得我们想要的数据。第一个做完之后,我们有了一些结果。我们把它们写下来。简而言之,数据的原始路径似乎已经过时,我们必须找到新的路径。由于数据会时不时地被更新,我们必须找到一种通用的方法来获取我们每次需要的相关数据。

我们转到第一个子任务,完成它并在这里放一些中间结果。午餐后,我们可能会思考这些 HTML 片段,并开始 BeautifulSoup 任务来自动化获取实际数据路径的过程。

让我们看看在“后端”发生了什么

在 Jupyter / Google 联合实验室中保持跟踪

从技术角度来看,我的任务是从一个 URL 下载数据。该 URL 以“.”结尾。csv”,这是一个好迹象。尽管如此,当我添加一个简单的检查——一个列表长度——结果看起来有点可笑。整个地球上只有 1713 个邮政编码?那不可能是真的!

因此,我们打印应该包含列名的零线。它抛出了一些在这种情况下毫无意义的东西。如果我们打印下一行,它看起来也没有意义。

我们尝试通过导入 IPython 包,让 Colab notebook 显示完整的输出,但是没有效果。我们把它往下移几格。将输出复制粘贴到 iOS Notes 中,再看一遍。仍然没有线索。

我们发送一个简单的请求并检查响应,结果是一个 404 错误。该页面不存在。

我们可以直接从 BeautifulSoup 包开始,自动解析正确的 URL。但是相反,我们做了一个简单的步骤,缩短网址并打开它。

我们看到的页面在层次结构中比目标页面高一级。我们发现它有不止一条路径。CSV 文件:一个包含退役的位置,一个包含仍在工作的位置。

谷歌地理目标(用户视图)

Google 地理目标(HTML 视图)

因此,我们不仅需要从父网页中解析一个 URL,还需要解析正确的 URL。

我们请求父页面,打印前 1000 个符号,以确保我们得到一些可以开始的数据。输出看起来不错。

找到页面上的所有链接也很好。

然后,我们尝试只获取包含“,”的链接。CSV”部分,但它不工作。我们试验了不同的语法,并把它们都放在那里。如果在这个过程中宣布开会,那么回来就更容易了,而不是开始我们已经拒绝的方法。

例如,一个输出表明我们使用了不可迭代的数据类型。我们检查它是否为真,类型是否为 NoneType。我们得到 yes,并试图把它转换成字符串。它工作了。

我们调整 if 条件,它抛出两个相关的链接。尽管如此,我们只需要一个。因此,我们检查链接文本——这也是按钮标签——并添加一个 if 条件,以便只选择指向最新位置的链接。我们现在可以保存它,并开始今天最初计划的任务:可视化数据。

我们在 OneNote 中将待办事项框标记为已完成!

结论:我们让代码逐渐地、有机地增长,备份每个阶段。

我希望你已经了解了我的进度跟踪方法。在下一节中,我将在更抽象的层次上总结它们。

伟大的八人组

如果你与 Jupyter、Juno、Google 联合实验室研究、Kaggle 或 R Studio 合作,你可以使用这些技巧。对于最后一个,你必须激活降价。

如果你经常在办公室分心,如何避免丢失重要信息?

#1.

我没有把整个代码放在一个单元格中。这些数据块帮助你记录你对数据的操作。在每个块之后是输出部分,您可以在那里显示您的初步结果。

会议一结束,您就可以通过查看输出来快速编写代码并刷新您的记忆。

#2.

我做了很多复制粘贴。如果一部分代码不能正常工作,我不会完全删除它,而是将有问题的部分复制到下一个单元中。然后我一步一步改,一次一改。每次修改后都要复制粘贴。我可以随时回到任何代码单元,制作一个新的副本,调整另一个参数或使用另一个函数,等等。

#3.

我保留那些被证明无效的副本,以便以后能够访问它们的错误信息。为了防止自己忘记已经尝试过的事情。

#4.

我保留了所有的工作副本,以便能够从中选择最好的。

#5.

我在每台笔记本电脑的顶部预留了一个单元格,用于打包导入。对于动态加载到笔记本中的每个新包,我稍后会在顶部添加 import 语句。

如果你只运行其中的一小部分,这有助于保持其他部分的工作。例如,您开始用 pyplot 绘图,然后过一会儿您添加了 seaborn,但是您的 import 语句很快就在笔记本中间的某个地方丢失了。第二天,您回到它那里,只想运行使用这些包的代码行,但是它抛出了一个错误,您不得不寻找一个 import 语句或者专门编写它。最终,你的笔记本中会出现大量重复的语句。

除了 import 语句之外,您在试验过程中不会接触到的所有东西也出现在顶部,例如,禁止科学符号的命令行。

#6.

对于每一个新的试验,我都重新命名用于相同结果的对象。如果我将一些外部数据放入数据帧,每次放入不同的数据,我不会为所有数据帧指定相同的“df”名称。这可能会引起混乱。涉及一个对象的每个新命令,一般命名为,将覆盖前一个对相似对象做了一些转换的命令。如果您以某种方式回到笔记本开头的代码块,您会得到意想不到的结果,因为笔记本会调用最后保存的“df”数据帧。

它仅不适用于图形对象,因为 pyplot show 命令将覆盖当前存储在内存中的任何其他图形。

#7.

在一行的开头加上#进行评论,并留下有意义的注释,将会在将来节省你的宝贵时间。不要再写日记了——只写下简短解释某个函数或方法用法的信息。

如果您完成了代码构建,并希望保存它以供几周后的应用,那么添加散列标记的注释是必不可少的。您可能不乐意在 OneNote 中寻找使用一个包而不使用另一个包的解释。

#8.

在我的笔记本的最终版本中,我将大块与标题分开,以便让它们抓住我的注意力,即使我很紧张,向下滚动得太快而无法阅读代码本身。

一个完美的例子

由于我在上面的例子中没有完全遵循我自己的最佳实践,这里是我用来为另一篇 TDS 文章构建 viz 的笔记本截图:

当然,如果你不能在办公室集中注意力,和你的老板谈谈也是值得的。数据科学家每天应该有几个小时不受干扰地工作。

人工智能世界的显著进步和发展(11 月 9 日)

原文:https://towardsdatascience.com/notable-progress-and-developments-in-the-artificial-intelligence-world-nov-9-54b5cf5fac33?source=collection_archive---------54-----------------------

你应该知道的人工智能世界中相关事件的基本信息。

人工智能的世界发展迅速,新技术每天都在发展,更多专注于人工智能的公司正在涌现。

跟上与机器学习从业者相关的发展和进步可能具有挑战性。

因此,我写了一篇文章,提供了机器学习从业者将特别感兴趣的人工智能领域的事件细节。

NASAUnsplash 上拍摄的照片

Palantir 正在商谈向英国提供援助,以处理其联系和追踪系统

Palantir 是一家在过去一个月一直处于商业新闻头条的公司,这主要是由于曾经的私营公司申请首次公开募股,它已经在美国股票市场成功上市

对于那些不知道的人,Palantir 是一家美国公司,专注于创建高效和有效的数据分析软件和工具。

该公司的创始人之一是彼得·泰尔,他是贝宝和许多其他成功的科技企业的联合创始人。

有报道称,Palantir 和英国政府官员一直在进行谈判,以确定 Palantir 如何帮助英国政府围绕其测试和跟踪计划创建一个更有效的分析系统。

Palantir 对于从以数据为中心的角度与各国合作处理新冠肺炎疫情并不陌生。这家数据分析公司已经与全球多个国家和美国疾病控制和预防中心合作。

可能值得注意的是,英国公共医疗保健系统 NHS(国家医疗服务)已经通过利用其一些数据分析软件获得了 Palantir 的帮助。

点击以下链接了解更多信息。

[## 英国正与 Palantir 就测试和追踪计划进行谈判

英国政府已与美国数据分析公司 Palantir 举行会谈,试图支持其苦苦挣扎的…

www.ft.com](https://www.ft.com/content/6f6575a8-799f-42a4-b1cc-3f7452b2166f) [## 英国正与 Palantir 就新冠肺炎测试与跟踪计划进行谈判

(路透社)-英国政府正在与美国数据分析公司 Palantir Technologies Inc .进行谈判,试图…

uk.reuters.com](https://uk.reuters.com/article/us-health-coronavirus-britain-palantir-idUKKBN27J2HL)

人工智能通过听到你的咳嗽来执行新冠肺炎检测

视觉摘要

麻省理工学院的研究人员开发了一种利用人工智能的新冠肺炎探测方法。

开发的人工智能模型可以从通过手机和网络浏览器捕获的咳嗽音频样本中检测到新冠肺炎。

研究人员报告说,人工智能模型可以拾取指标的微小变化,然后用于检测个体中的新冠肺炎。

研究论文中,这些指标被称为生物标志物。生物标记是肌肉退化、声带变化、情绪变化以及肺部和呼吸系统内的变化。

人工智能模型是神经网络和设计算法的结合,可以拾取生物标志物的微小变化,并从咳嗽样本中准确检测新冠肺炎。

该模型从可用的咳嗽样本中检测新冠肺炎的准确率达到了令人印象深刻的 98.5%。

研究人员希望人工智能模型可以集成到移动应用程序中。在移动应用程序中工作的人工智能模型可以促进在人群中对新冠肺炎的日常监控。

以下资源提供了更多信息:

[## 仅使用咳嗽记录的新冠肺炎人工智能诊断

IEEE Xplore,提供对世界上最高质量的工程和…

ieeexplore.ieee.org](https://ieeexplore.ieee.org/document/9208795) [## 人工智能模型通过手机记录检测无症状新冠肺炎感染…

根据定义,感染新冠肺炎病毒的无症状患者没有可辨别的身体症状

news.mit.edu](https://news.mit.edu/2020/covid-19-cough-cellphone-detection-1029)

英特尔正在通过更多的收购来加强其人工智能部门

英特尔最近收购了两家专注于机器学习的公司,以推动芯片制造公司进入人工智能领域。

英特尔最新收购的两家公司包括 Cnvrg.ioSigOpt

Cnvrg.io 是一家开发软件和工具来帮助数据科学家构建和部署机器学习模型的公司。

SigOpt 专注于通过自动模型优化和开发来优化机器学习模型。

这两家公司似乎互补,无疑将使英特尔成为全球企业人工智能市场份额争夺战中的一支强大力量。

更多信息请点击以下链接:

[## 英特尔将收购 SigOpt 以提升人工智能的生产力和性能|英特尔新闻编辑室

最新消息:今天,英特尔宣布将收购 SigOpt,这是一家总部位于旧金山的领先平台提供商

newsroom.intel.com](https://newsroom.intel.com/news/intel-to-acquire-sigopt-to-scale-ai-productivity-and-performance/#gs.kyc4eu) [## 英特尔已经收购了 Cnvrg.io,这是一个管理、构建和自动化机器学习的平台

英特尔继续收购初创公司,以建立其机器学习和人工智能运营。在最近的行动中,TechCrunch…

techcrunch.com](https://techcrunch.com/2020/11/03/intel-has-acquired-cnvrg-io-a-platform-to-manage-build-and-automate-machine-learning/)

IBM 和辉瑞合作开发可以预测阿尔茨海默病的人工智能模型

IBM 和辉瑞研究部门的合作开发了一种人工智能模型,该模型可以在临床诊断实施之前或个体出现症状之前预测个体阿尔茨海默病的早期发作。

人工智能模型的性能得分为 70%,并通过分析一到两分钟长的口头语音样本来工作。利用自然语言处理技术来分析转录的语音样本。

语音样本数据是通过弗雷明汉心脏研究提供的,该研究包含了超过 5000 个人的健康数据点。

在未来,人工智能模型可以用来帮助降低个体早期患阿尔茨海默病的风险。

更多信息请点击下面的链接。

[## 人工智能能帮助临床医生在阿尔茨海默病发展之前预测它吗?IBM 研究博客

由 IBM 和辉瑞公司开发的人工智能模型已经使用语音测试来帮助预测阿尔茨海默氏症的最终发作…

www.ibm.com](https://www.ibm.com/blogs/research/2020/10/ai-predict-alzheimers/) [## IBM 和辉瑞声称人工智能可以预测阿尔茨海默病的发作,准确率为 71%

辉瑞和 IBM 的研究人员声称已经开发出一种可以预测阿尔茨海默病的机器学习技术…

venturebeat.com](https://venturebeat.com/2020/10/22/ibm-and-pfizer-claim-ai-can-predict-alzheimers-onset-with-71-accuracy/)

结论

随着时间的推移,利用人工智能检测几种疾病正在成为现实。

很快,我们就可以期待临床医生使用人工智能嵌入式软件和硬件来改善威胁生命的疾病的早期检测。

大型科技公司在收购有前途的初创公司方面没有放缓,研究团队之间的合作越来越多,以进一步开发新技术来解决现实世界的问题,特别是关于健康的问题。

下周会有什么发展和进展,我们只能拭目以待。

我希望这篇文章对你有用。

要联系我或找到更多类似本文的内容,请执行以下操作:

  1. 订阅我的 邮件列表 获取每周简讯
  2. 跟我上中型
  3. 通过 LinkedIn 联系我

关于使用 Spark 3.0 保存数据的注意事项

原文:https://towardsdatascience.com/notes-about-saving-data-with-spark-3-0-86ba85ca2b71?source=collection_archive---------10-----------------------

使用 Spark SQL 以文件格式存储数据的不同选项。

Apache Spark 是一个计算引擎,经常在大数据环境中用于数据处理,但它不提供存储,因此在典型情况下,数据处理的输出必须存储在外部存储系统中。Spark SQL 为文件格式(CSV、JSON、text、Parquet、ORC)或 JDBC 等数据源提供了一些连接器。从 2.4 开始也支持 Apache Avro,从 3.0 开始也支持二进制文件。此外,还有几个库允许连接到其他数据源,例如 MongoDB、ElasticSearch 或 DynamoDB 等等。

在本文中,我们将讨论将数据保存为 Apache Parquet 等文件格式时的一些可能性,因为 Spark 和 Parquet 的结合提供了非常好的体验,尤其是对于分析查询。我们将首先解释为什么 Parquet 是 Hadoop 生态系统中如此受欢迎的数据存储格式,然后我们将描述如何使用 Spark 保存数据的不同方法,同时特别关注官方文档中缺少或难以找到的功能。我们要研究的一个重要特性是如何以预先排序的状态保存数据,以便可以利用适当的过滤器跳过数据。

所提供的代码片段使用 Python API,并对照 Spark 3.0 和 2.4 进行了检查。

阿帕奇拼花地板

Apache Parquet 是一种开源文件格式,最初由 Twitter 和 Cloudera 开发。它是一种自描述格式,这意味着它包含带有模式信息的元数据(以及其他信息)。它使用混合模型在磁盘上存储数据,所谓混合,我们的意思是它不是严格面向行的(如 JSON 或 CSV ),也不是严格的列,而是首先将数据垂直划分为所谓的行组,然后将每个行组存储在列表示中。这些行组允许将数据集分成多个文件(每个文件可以有一个或多个行组),这样我们就不会以一个巨大的文件结束,这在大数据环境中尤其重要。

每个行组的列表示也是一个非常重要的特征,因为它允许所谓的列修剪。在分析查询中,我们通常对数据集的所有列都不感兴趣,而是选择几列并对其进行聚合。这种列删减让我们可以跳过所有其他列,只扫描那些在查询中选择的列,因此与必须扫描所有列的面向行的格式相比,它使读取更加高效。列格式的另一个优点是压缩——列中的每个值都具有相同的数据类型,并且这些值甚至可能重复,这可以用于使用各种编码和压缩技术(Parquet 支持的技术)更有效地存储数据。

Parquet 文件支持不同级别的数据跳过,即分区级别和行组级别。因此,数据集可以通过某个(通常是低基数的)键进行分区,这意味着对于该字段的每个不同值,根目录中都会有一个子文件夹,其中包含具有该特定键值的所有记录(每个分区仍可以被划分为多个文件)。分区的用例是在读取时减少数据量,因为当在过滤器中使用分区键时,Spark 将应用分区修剪,它将跳过所有与查询无关的分区(这也支持其他文件格式,如 JSON 或 CSV)。

行-组级别的数据跳过是基于 parquet 元数据的,因为每个 parquet 文件都有一个页脚,该页脚包含关于每个行-组的元数据,并且该元数据包含统计信息,例如行-组中每个列的最小值最大值值。当读取 parquet 文件时,Spark 将首先读取页脚,并使用这些统计信息来检查给定的行组是否可能包含与查询相关的数据。这将非常有用,特别是如果 parquet 文件是按照我们用于过滤的列排序的话。因为,如果文件没有被排序,那么大小值可能分散在所有行组中,因此每个行组都必须被扫描,因为它可能包含一些过滤器满足的行。这里的排序是至关重要的,正如我们将在后面看到的,以排序后的状态保存数据是很重要的。

1.救人()

将 Spark 中的计算输出保存为文件格式的选项之一是使用 save 方法

( 
  df.write
  .mode('overwrite') # or append
  .partitionBy(col_name) # this is optional
  .format('parquet') # this is optional, parquet is default
  .option('path', output_path)
  .save()
)

如您所见,如果您希望在保存数据的文件系统中对数据进行分区,它允许您指定分区列。默认格式是 parquet,所以如果您不指定它,它将被假定。

2.保存表()

如果您使用保存表方法保存数据,将使用数据的数据分析师可能会更加感激,因为这将允许他/她使用

df = spark.table(table_name)

保存表功能也允许使用分桶,其中每个桶也可以(可选地)排序:

( 
  df.write
  .mode('overwrite') # or append
  .partitionBy(col_name) # this is optional
  .bucketBy(n, col_name) # n is number of buckets
  .sortBy(col_name)
  .format('parquet') # this is optional, parquet is default
  .option('path', output_path)
  .saveAsTable(table_name)
)

我们不会在这里深入探讨分桶,但一般来说,这是一种关于如何预混洗数据并将其保存在这种状态下的技术,以便后续查询可以利用它来避免混洗。如果使用 Spark 正确设置了 metastore,这将会起作用,因为关于分桶的信息将保存在这里。这种方法还有其他好处,因为当您稍后调用 ANALYZE TABLE 命令时,metastore 还可以保存关于数据集的其他信息,比如统计数据。 sortBy 只能在 bucketsBy 之后使用,因为要排序的是创建的 bucket。即使表还不存在,两种模式覆盖追加在这里都有效,因为函数会简单地创建它。

3.插入()

如何保存数据的另一种可能性是使用 insertInto 功能。与前一种情况不同,该表必须首先存在,因为如果不存在,您将得到一个错误:analysis exception:Table not found。使用这个函数的语法相当简单

(
  df.write
  .insertInto(table_name)
)

但是有一些需要注意的警告:

  • 您不必指定输出路径。Spark 将在 metastore 中找到该信息。如果您仍然指定路径,它将被忽略。
  • 默认模式是 append ,所以它会简单地将您的数据添加到现有的表中。
  • 数据框架的模式必须与表的模式相匹配。如果数据帧中的列顺序不同于表中的顺序,Spark 将在数据类型不同且无法安全转换时抛出异常。但是如果数据类型没有不匹配,Spark 会以这种错误的顺序将数据插入到表中。因此这是非常危险的,最好确保模式是相同的,例如:
(
  df.select(spark.table(table_name).columns)
  .write
  .insertInto(table_name)
)
  • 如果您的表是分区的或分桶的,您不需要指定这一点(您会得到一个错误),因为 Spark 将从 metastore 中选取该信息。

函数 insertIntosaveAsTable 有一个很大的优势,因为它允许所谓的动态覆盖。此功能允许您覆盖分区表中的特定分区。例如,如果您的表按 year 进行分区,并且您只想更新一个 year,,那么使用 saveAsTable 您将不得不覆盖整个表,但是使用 insertInto,您可以只覆盖这一个分区,因此这将是一个非常便宜的操作,尤其是在有许多大分区的情况下。要使用此功能,您必须设置相应的配置设置:

spark.conf.set("spark.sql.sources.partitionOverwriteMode", "dynamic")(
  df # having data only for specific partitions
  .write
  .insertInto(table_name, overwrite=True)
)

在这里,还是要小心,因为如果将 partitionOverwriteMode 设置为 static (这是默认值),它将覆盖整个表,因此所有其他分区都将变空。动态值确保 Spark 只覆盖数据帧中有数据的分区。

以排序状态保存数据

正如我们上面提到的,有时希望根据某一列以排序状态保存数据,以便在使用该列作为过滤器的分析查询中跳过数据。在 Spark SQL 中,有三个函数用于排序。有 orderBy (或等价的 sort )、 sortWithinPartitions、sortBy。让我们看看它们之间有什么区别,以及如何使用它们:

  1. orderBy —这是一个将调用全局排序的数据帧转换。这将首先运行一个单独的作业,该作业将对数据进行采样,以检查排序列中值的分布。然后,该分布用于创建分区的边界,数据集将被混洗以创建这些分区。这是一个非常昂贵的操作,如果您将数据保存到一个分区表中,并且如果集群上的数据分布与文件系统中的表的最终分布非常不同,则可能会创建许多小文件(例如,如果您按日期排序,并且您的表按国家分区,则 Spark 作业最后阶段的每个任务都可能携带每个国家的数据,因此每个任务都会向每个文件系统分区中写入一个新文件)。
  2. sort within partitions—这也是一个数据帧转换,与前面的情况不同,Spark 不会尝试实现全局排序,而是将每个分区分别排序。所以在这里,您可以使用 repartition() 函数(这也将创建一个 shuffle)在 Spark 集群上分发您所需要的数据,然后调用 sortWithinPartitions 对每个分区进行排序。与前一种方法相比,这种方法的优点是您可以避免拥有大量小文件,并且仍然可以对输出进行排序。
  3. sortBy —如果我们也调用 bucketBy 并使用 saveAsTable 方法进行保存,则可以在data frame writer上调用该函数(在调用 df.write 之后)。它将确保每个存储桶都被排序(一个存储桶可以是一个文件,也可以是多个文件,这取决于写本文时 Spark 集群上的数据分布)。

使用前两个函数有一个大问题,你在文档中找不到(写于 2020 年 10 月)。让我们看一个简单的例子。为了简单起见,我们希望按照对数据进行分区,并按照 user_id 对每个分区进行排序,为了保存,我们使用 saveAsTable() 。如果你只是打电话

(
  df.repartition('year')
  .sortWithinPartitions('user_id')
  .write
  .mode('overwrite')
  .partitionBy('year')
  .option('path', output_path)
  .saveAsTable(table_name)
)

这是行不通的!不会产生任何错误,会保存数据,但订单不会被保留!重点是,当将数据写入文件格式时,Spark 要求这种排序:

(partitionColumns + bucketIdExpression + sortColumns)

这里的 partitionColumns 是我们将数据分区到文件系统所依据的列,bucketingiexpression是从 bucketing 列派生而来的(与我们的查询无关,因为我们在这里没有使用 bucketing),而 sortColumns 是在带有 bucketing 的 sortBy 中使用的列(同样与我们的查询无关)。如果数据是按照这些列(可能还有更多)排序的,那么这个要求将会得到满足,Spark 将会保持这个顺序。但是,如果不满足这个要求,Spark 将会忘记之前的顺序,并在写入数据时根据这个要求再次对数据进行排序。在我们的示例中,所需的排序是( year ),这是分区列,我们在这里没有任何存储桶。然而,这一要求并没有得到满足,因为实际的排序是( user_id ),这是我们对数据进行排序的列,这就是为什么 Spark 不会保留我们的顺序,而是按照 year 列再次对数据进行排序。

required_orering = (year)
actual_ordering = (user_id) ... this doesn't satisfy the requirement

为了实现我们的目标并保存按 user_id 排序的数据(每个分区),我们可以这样做:

(
  df.repartition('year')
  **.sortWithinPartitions('year', 'user_id')**
  .write
  .mode('overwrite')
  .partitionBy('year')
  .option('path', output_path)
  .saveAsTable(table_name)
)

注意现在的区别,我们按照用户 id 对每个分区进行显式排序,但是由于数据将按照进行分区,因此按照该列进行排序并不重要。重要的是,现在 Spark 的要求将得到满足,因此 Spark 将保留我们的顺序并保存按user_id 排序的数据,由于我们按分区,这基本上意味着每个分区将按 user_id 排序,这正是我们想要的。

required_orering = (year)
actual_ordering = (year, user_id) ... this satisfies the requirement

在每个分区排序的位置保存分区数据,将允许使用过滤器进行高效的分析查询,该过滤器将跳过两个级别上的数据—分区级别和行组级别。想象这样一个查询:

(
  spark.table(table_name)
  .filter(col('year') == 2020)
  .filter(col('user_id') == 1)
  .collect()
)

这将首先使用分区过滤器来修剪分区,并且在该单个分区 2020 内,它将检查来自每个行组的镶木地板脚的元数据。基于元数据中的统计数据,Spark 将挑选最小小于等于 1 且最大大于等于 1 的行组,并且只扫描这些行组,因此这将加快查询速度,尤其是在有许多行组可以跳过的情况下。

结论

在本文中,我们描述了如何使用 Spark 将数据保存为文件格式(特别是 Apache Parquet)的三种不同方式,还解释了为什么 Parquet 是如此流行的数据格式,尤其是在分析查询中。我们还指出了一些不太明显的 Spark 特性,比如 insertInto 函数的行为或者如何在排序状态下保存数据。

图论的注记——中心性测度

原文:https://towardsdatascience.com/notes-on-graph-theory-centrality-measurements-e37d2e49550a?source=collection_archive---------10-----------------------

关于不同中心性度量的注记:定义和权衡

作者图片

介绍

中心性测量是分析网络的重要工具,无论是国家道路网络还是电力网络,您都希望确定主要城市,并确定需要维护的关键节点,以消除未来对网络的干扰。所有这些分析都可以使用一些简单的拓扑测量来完成,这些测量根据节点作为大网络的一部分的重要性来评分。

图论:导论

首先,我将通过给出图形抽象的定义和数学表示来介绍图形抽象,因为我们以后会用到它。

图形定义

图表无处不在,它是一个非常适合的工具来呈现数据,其中连接和链接对于我们理解它很重要。就像分子结构呈现出基本原子的集合,这些原子相互连接,形成复杂的结构,在这个集合中每个原子的连接意味着这个分子的用法或特征,事实上,改变其中一个连接可以给你一个完全不同的分子。

这个例子将帮助我们理解一个图的基本结构,这个图是由一堆通过边连接的节点生成的。基础解剖学?是的,但是继续添加这些节点和边,你可以创建一些曾经存在的复杂网络。以脸书为例,节点是用户,边是友谊或追随者。

一个有 5 个节点和 5 条边的图的例子(图片由作者提供)

图形数学演示

如前所述,图表可以发展成为复杂的结构,以脸书社交网络为例。因此,仅仅通过视觉观察很难研究它,因此,我们需要建立数学工具来帮助我们理解或分析我们的图形结构。

我们从作为数学对象的图形定义开始。一个图是由它的一组节点和一组边定义的,所以一个图 G 被定义为:

图表的数学表示(作者提供的图片)

n 表示图中的节点集,E 是边集。我们还将图的范数定义为节点数

邻接矩阵

正如我之前所说的,我们不能仅仅使用图形的几何形状来分析它们,但是我们需要某种工具来封装我们图形中的信息,并且容易对其进行数学分析。

为此,我们将邻接矩阵定义为二进制 2d 数组 n*n,其中 n 表示节点的数量。如果两个节点链接,则每个值可以是 1,否则将是 0。正如你在例子中看到的,无向图(一种图形结构)的邻接矩阵是对称的,我们将在接下来的故事中看到更多。

邻接矩阵示例(图片由作者提供)

图论:中心性测量

现在我们已经建立了关于图的基本概念,我们准备通过给出它们的定义和用法来发现中心性度量。我还将尝试以一种您可以轻松看到何时使用每种措施的方式对它们进行排序。

中心性度量是给予图中每个节点的标量值,以基于假设量化其重要性。

节点度

  • 定义

节点度是基本的中心性度量之一。等于节点邻居的数量。因此,一个节点的邻居越多,它就越是中心的和高度连通的,因此对图有影响。

节点 Ni 的节点度为 1 /节点 Nj 的节点度为 4(图片由作者提供)

  • 节点度是局部的,不是全局的

虽然节点度给了我们一个关于每个节点连通性的概念,但是它是一个局部的度量,并不能展示全局。让我给你举个例子:

这两个节点具有相同的度数(图片由作者提供)

如您所见,这两个节点具有相同数量的邻居,这意味着它们具有相同的节点度,但看看它们的邻居,节点 1 连接到度数较高的节点,因此如果我们基于连通性进行选择,我们肯定会选择它,因此节点度作为一种度量没有考虑邻居连通性这就是为什么我们称之为局部度量。

特征中心性

  • 定义

特征向量中心性测量节点的重要性,同时考虑其邻居,换句话说,它测量节点的度,但更进一步,通过计算其连接(邻居)有多少条链路。它使用邻接矩阵的分解。因此每个节点 I 的特征中心性是具有最大特征值的矩阵特征向量的第 I 个条目。

特征中心性定义(图片由作者提供)

  • 轮毂偏置

我们已经看到,特征中心性是全局的,因为它奖励具有高的和重要的连通性(在数量和质量方面的连接)的节点。但是想象一下添加一个新节点并将其连接到一个 hub 节点。该节点将具有较低的度数,但是具有较高的特征中心性,因为它的邻居是集线器(度数较高的节点)。为了澄清这一点,想象一下你刚到脸书,你开始关注巴拉克·奥巴马或一个受欢迎的人,这并不意味着你在网络中是那么重要。

作者图片

PageRank 中心性

以减少假的或有偏差的中心节点的危险。谷歌创始人拉里·佩奇(Larry Page)和谢尔盖·布林(Sergei Brin)发明了一种新的中心性衡量标准( PageRank ),这种衡量标准使用一种阻尼因子来平抑/减弱中枢连接的影响。

页面等级中心性测量使用阻尼因子来控制邻居对您的节点的影响,同时测量其重要性。(图片由作者提供)

接近中心性

这种类型的中心性根据与其他节点的连接来衡量节点效率。当尝试使用较少的链路向其他节点发送信号时,哪个节点效率更高?为了更好地理解这一点,让我再举一个例子。

想象一下,我们有一个道路网络,城市是你的节点,道路是边。你拥有一家服装公司,你想安装一个新的仓储设施,为所有城市的客户供货。一般来说,你会选择把它放在一个离所有其他城市都近的城市,以减少你的运输成本。

对于这个用例,接近中心性将是选择您的位置的一个很好的度量,因为它测量平均路径长度因此,你的亲密度中心值越高,你的节点离你网络中的其他节点就越近。

亲近中心性公式(作者图片)

中间中心性

在强调最短路径方面,接近接近中心性的度量是中间中心性。它测量我们研究的节点所在的最短路径的百分比因此,具有高介数中心性的节点可能对其他节点之间传递的信息具有相当大的影响。因此它们代表了网络的关键部分,因为移除它们会破坏图中顶点(节点)之间的链接。

外卖点

正如您所看到的,中心性度量为节点提供了一个易于解释的标量分数,还可以帮助您根据重要性和关键程度比较网络中的节点。

另一个要点是,每个中心性度量都有一个背景假设,例如,紧密度和介数中心性将重要性定义为图中信息流的节点效率。其他如特征中心性或度中心性奖励高度连接的节点。所以我给你的建议是,使用一个基于你的研究案例的中心性测量,如果你想更进一步,你可以把它们结合成一个适合你问题需要的一般中心性测量。

最后,如果你正在使用 python,我建议你使用已经实现了这些中心化措施的 Networkx 库,所以花些时间来使用它们。不久我们将看到另一个关于图论的故事。

资源:

没什么特别的——但是 16 个必要的操作让你开始接触熊猫

原文:https://towardsdatascience.com/nothing-fancy-but-16-essential-operations-to-get-you-started-with-pandas-5b0c2f649068?source=collection_archive---------33-----------------------

使用 Pandas 的基本数据处理技能概述

照片由卡伦·艾姆斯利Unsplash 上拍摄

Python 已经成为许多数据科学家和机器学习研究人员的首选编程语言。熊猫图书馆是他们做出这一选择的一个重要的数据处理工具。当然,pandas 库是如此通用,以至于它可以用于几乎所有的初始数据操作,以便为进行统计分析或建立机器学习模型准备好数据。

然而,对于同样的多功能性,开始舒适地使用它可能会令人不知所措。如果你正在纠结如何开始,这篇文章很适合你。本文的目的不是介绍太多而失去要点,而是概述您希望在日常数据处理任务中使用的关键操作。每个关键操作都有一些需要考虑的重要参数。

当然,第一步是安装熊猫,你可以按照这里的说明使用pipconda。在编码环境方面,我推荐 Visual Studio Code,JupyterLab,或者 Google Colab,所有这些都需要很少的努力就可以设置好。当安装完成后,在您首选的编码环境中,您应该能够将 pandas 导入到您的项目中。

import pandas as pd

如果您运行上面的代码没有遇到任何错误,您就可以开始了。

1.读取外部数据

在大多数情况下,我们从外部来源读取数据。如果我们的数据是类似电子表格的格式,下面的函数应该可以满足目的。

*# Read a comma-separated file* df = pd.read_csv(**"the_data.csv"**)*# Read an Excel spreadsheet* df = pd.read_excel(**"the_data.xlsx"**)
  • 应该正确处理标题。默认情况下,读数将假定第一行数据是列名。如果它们没有标题,你必须指定它(如header=None)。
  • 如果你正在读取一个制表符分隔的文件,你可以通过指定制表符作为分隔符来使用read_csv(例如sep=“\t”)。
  • 当你读一个大文件时,读一小部分数据是一个好主意。在这种情况下,您可以设置要读取的行数(例如nrows=1000)。
  • 如果您的数据涉及日期,您可以考虑设置参数使日期正确,例如parse_datesinfer_datetime_format

2.创建系列

在清理数据的过程中,您可能需要自己创建系列。在大多数情况下,您只需传递一个 iterable 来创建一个系列对象。

*# Create a Series from an iterable* integers_s = pd.Series(range(10))# Create a Series from a dictionary object
squares = {x: x*x for x in range(1, 5)}
squares_s = pd.Series(squares)
  • 您可以通过设置name参数为系列对象指定一个名称。如果该名称成为 DataFrame 对象的一部分,它将成为该名称。
  • 如果您发现索引比默认的基于 0 的索引更有用,您也可以将索引分配给系列(例如,设置index参数)。请注意,索引的长度应该与数据的长度相匹配。
  • 如果你从一个字典创建一个系列对象,这些键将成为索引。

3.构建数据框架

通常,您需要使用 Python 内置对象创建 DataFrame 对象,比如列表和字典。下面的代码片段突出了两个常见的使用场景。

*# Create a DataFrame from a dictionary of lists as values* data_dict = {**'a'**: [1, 2, 3], **'b'**: [4, 5, 6], **'c'**: [7, 8, 9]}
data_df0 = pd.DataFrame(data_dict)

*# Create a DataFrame from a list* data_list = [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
data_df1 = pd.DataFrame(data_list, columns=tuple(**'abc'**))
  • 第一个使用了一个字典对象。它的键将成为列名,而它的值将成为相应列的值。
  • 第二个使用了一个列表对象。与前面的方法不同,构造的数据帧将按行使用数据,这意味着每个内部列表将成为创建的数据帧对象的一行。

4.数据帧概述

当我们有了要处理的数据框架时,我们可能想看看 30,000 英尺高度的数据集。您可以使用几种常见的方法,如下所示。

*# Find out how many rows and columns the DataFrame has* df.shape

*# Take a quick peak at the beginning and the end of the data* df.head()
df.tail()*# Get a random sample* df.sample(5)*# Get the information of the dataset* df.info()*# Get the descriptive stats of the numeric values* df.describe()
  • 检查头部和尾部非常重要,尤其是在处理大量数据时,因为您希望确保所有数据都已被完整读取。
  • info()函数将根据数据类型和项目计数给出列的概述。
  • 获取数据的随机样本来检查数据的完整性也很有趣(即sample()函数)。

5.重命名列

您注意到数据的某些列没有太多意义,或者名称太长而无法使用,您想要重命名这些列。

*# Rename columns using mapping* df.rename({**'old_col0'**: **'col0'**, **'old_col1'**: **'col1'**}, axis=1)

*# Rename columns by specifying columns directly* df.rename(columns={**'old_col0'**: **'col0'**, **'old_col1'**: **'col1'**})
  • 如果您只是提供一个映射对象(例如, dict ),那么您需要指定axis=1来重命名列。
  • 或者,您可以显式地将映射对象指定给columns参数。
  • 默认情况下,rename函数将创建一个新的数据帧。如果你想就地重命名数据帧,你需要指定inplace=True

6.排序数据

为了使你的数据更加结构化,你需要对 DataFrame 对象进行排序。

*# Sort data* df.sort_values(by=[**'col0'**, **'col1'**])
  • 默认情况下,sort_values函数将对您的行进行排序(axis=0)。在大多数情况下,我们使用列作为排序关键字。
  • 默认情况下,sort_values函数将创建一个排序后的数据帧对象。要改变它,使用inplace=True
  • 默认情况下,所有排序关键字的排序都基于升序。如果要使用降序,请指定ascending=False。如果您想要混合排序(例如,一些键是升序,一些键是降序),您可以创建一个布尔值列表来匹配键的数量,比如by=[‘col0’, ‘col1’, ‘col2’], ascending=[True, False, True]
  • 原始索引将包含它们的旧数据行。在许多情况下,您需要重新索引。不用直接调用 rese t _index 函数,可以指定ignore_indexTrue,排序完成后会为你重置索引。

7.处理重复

在现实生活的数据集中,包含重复记录是很常见的情况,要么是人为错误,要么是数据库故障。我们希望删除这些重复项,因为它们会在以后导致意想不到的问题。

*# To examine whether there are duplicates using all columns* df.duplicated().any()

*# To examine whether there are duplicates using particular columns* df.duplicated([**'col0'**, **'col1'**]).any()

上述函数将返回一个布尔值,告诉您数据集中是否存在任何重复的记录。要找出重复记录的确切数量,您可以使用sum()函数,利用从duplicated()函数返回的布尔值系列对象(Python 将True视为值 1),如下所示。另外需要注意的是,当参数keep被设置为False时,它会将任何重复标记为True。假设有三条重复记录,当keep=False时,两条记录都会被标记为True(即正在重复)。当keep= “first”keep=“last”时,只有第一条或最后一条记录标记为True

*# To find out the number of duplicates* df.duplicated().sum()
df.duplicated(keep=False).sum()

为了实际查看复制的记录,您需要使用生成的复制的系列对象从原始数据集中选择数据,如下所示。

*# Get the duplicate records* duplicated_indices = df.duplicated([**'col0'**, **'col1'**], keep=False)duplicates = df.loc[duplicated_indices, :].sort_values(by=[**'col0'**, **'col1'**], ignore_index=True)
  • 我们通过将keep参数设置为False来获得所有重复的记录。
  • 为了更好地查看重复记录,您可能希望使用相同的一组键对生成的数据帧进行排序。

一旦您对数据集的重复记录有了一个好的想法,您可以像下面这样删除它们。

*# Drop the duplicate records* df.drop_duplicates([**'col0'**, **'col1'**], keep=**"first"**, inplace=True, ignore_index=True)
  • 默认情况下,保存的记录将是第一个副本。
  • 如果您想就地更新数据帧,您需要指定inplace=True。BTW:许多其他函数都有这个选项,即使不是全部,大多数时候也不会讨论这个问题。
  • sort_values()函数一样,您可能希望通过指定ignore_index参数来重置索引(熊猫 1.0 中的一个新特性)。

8.处理丢失的数据

缺失数据在现实生活的数据集中很常见,这可能是由于测量值不可用或只是人为数据输入错误导致无意义的数据被视为缺失。为了对您的数据集有多少缺失值有一个总体的概念,您已经看到 info()函数告诉我们每一列有多少非空值。我们可以通过更结构化的方式获得关于数据缺失的信息,如下所示。

*# Find out how many missing values for each column* df.isnull().sum()

*# Find out how many missing values for the entire dataset* df.isnull().sum().sum()
  • isnull()函数创建一个与原始数据帧形状相同的数据帧,每个值表示原始值缺失(True)或不缺失(False)。相关的注意事项是,如果您想生成一个指示非空值的数据帧,您可以使用notnull()函数。
  • 如前所述,Python 中的True值在算术上等于 1。sum()函数将为每一列计算这些布尔值的总和(默认情况下,它按列计算总和),这反映了缺失值的数量。

通过对数据集的缺失有所了解,我们通常想要处理它们。可能的解决方案包括删除带有任何缺失值的记录,或者用适用的值填充它们。

*# Drop the rows with any missing values* df.dropna(axis=0, how=**"any"**)

*# Drop the rows without 2 or more non-null values* df.dropna(thresh=2)

*# Drop the columns with all values missing* df.dropna(axis=1, how=**"all"**)
  • 默认情况下,dropna()函数按列工作(即axis=0)。如果指定how=“any”,将会删除任何缺少值的行。
  • 当您设置thresh参数时,它要求行(或当axis=1时的列)具有非缺失值的数量。
  • 与许多其他功能一样,当您设置axis=1时,您正在按列执行操作。在这种情况下,上面的函数调用将删除那些所有值都丢失的列。

除了删除带有缺失值的数据行或列的操作之外,还可以用一些值来填充缺失值,如下所示。

*# Fill missing values with 0 or any other value is applicable* df.fillna(value=0)*# Fill the missing values with customized mapping for columns* df.fillna(value={**"col0"**: 0, **"col1"**: 999})*# Fill missing values with the next valid observation* df.fillna(method=**"bfill"**)
*# Fill missing values with the last valid observation* df.fillna(method=**"ffill"**)
  • 要用指定的值填充缺失的值,您可以将 value 参数设置为所有值的固定值,也可以设置一个 dict 对象,该对象将指示基于每列的填充。
  • 或者,您可以通过使用缺失孔周围的现有观测值来填充缺失值,回填或向前填充。

9.分组描述性统计

当您进行机器学习研究或数据分析时,通常需要对一些分组变量执行特定操作。在这种情况下,我们需要使用groupby()函数。下面的代码片段向您展示了一些适用的常见场景。

*# Get the count by group, a 2 by 2 example* df.groupby([**'col0'**, **'col1'**]).size()

*# Get the mean of all applicable columns by group* df.groupby([**'col0'**]).mean()

*# Get the mean for a particular column* df.groupby([**'col0'**])[**'col1'**].mean()

*# Request multiple descriptive stats* df.groupby([**'col0'**, **'col1'**]).agg({
    **'col2'**: [**'min'**, **'max'**, **'mean'**],
    **'col3'**: [**'nunique'**, **'mean'**]
})
  • 默认情况下,groupby()函数将返回一个 GroupBy 对象。如果你想把它转换成一个数据帧,你可以调用对象上的reset_index()。或者,您可以在groupby() 函数调用中指定as_index=False来直接创建一个数据帧
  • 如果您想知道每组的频率,则size()很有用。
  • agg()功能允许您生成多个描述性统计数据。您可以简单地传递一组函数名,这将应用于所有列。或者,您可以传递一个带有函数的 dict 对象来应用于特定的列。

10.宽到长格式转换

根据数据的收集方式,原始数据集可能是“宽”格式,每一行代表一个具有多个测量值的数据记录(例如,研究中某个主题的不同时间点)。如果我们想要将“宽”格式转换为“长”格式(例如,每个时间点变成一个数据行,因此一个主题有多行),我们可以使用melt()函数,如下所示。

从宽到长的转换

  • melt()函数本质上是“取消透视”一个数据表(我们接下来将讨论透视)。您将id_vars指定为在原始数据集中用作标识符的列。
  • 使用包含值的列设置value_vars参数。默认情况下,这些列将成为融合数据集中var_name列的值。

11.长到宽格式转换

melt()功能相反的操作叫做旋转,我们可以用pivot()功能来实现。假设创建的“宽”格式数据帧被称为df_long。下面的函数向您展示了如何将宽格式转换为长格式——基本上与我们在上一节中所做的过程相反。

从长到宽的转变

除了pivot()函数之外,一个密切相关的函数是pivot_table()函数,它比pivot()函数更通用,允许重复的索引或列(更详细的讨论见此处的)。

12.选择数据

当我们处理一个复杂的数据集时,我们需要根据一些标准为特定的操作选择数据集的一个子集。如果您选择一些列,下面的代码将向您展示如何操作。所选数据将包括所有行。

*# Select a column* df_wide[**'subject'**]

*# Select multiple columns* df_wide[[**'subject'**, **'before_meds'**]]

如果要选择包含所有列的特定行,请执行下列操作。

*# Select rows with a specific condition* df_wide[df_wide[**'subject'**] == 100]

如果你想选择某些行和列,我们应该考虑使用ilocloc方法。这些方法的主要区别在于iloc方法使用基于 0 的索引,而loc方法使用标签。

数据选择

  • 以上几对调用创建了相同的输出。为了清楚起见,只列出了一个输出。
  • 当您将 slice 对象与iloc一起使用时,不包括停止索引,就像常规的 Python slice 对象一样。然而,切片对象在loc方法中包含停止索引。请参见第 15–17 行。
  • 如第 22 行所示,当您使用布尔数组时,您需要使用实际值(使用 values 方法,这将返回底层 numpy 数组)。如果不这样做,您可能会遇到下面的错误:NotImplementedError: iLocation based boolean indexing on an integer type is not available
  • 在选择行方面,loc方法中标签的使用恰好与索引相同,因为索引与索引标签同名。换句话说,iloc将始终根据位置使用基于 0 的索引,而不管索引的数值。

13.使用现有数据的新列(映射和应用)

现有列并不总是以我们想要的格式显示数据。因此,我们经常需要使用现有数据生成新列。这种情况下有两个函数特别有用:map()apply()。我们有太多的方法可以使用它们来创建新的列。例如,apply()函数可以有一个更复杂的映射函数,它可以创建多个列。我将向您展示两个最常用的案例,并遵循以下经验法则。让我们的目标保持简单——只需用任一用例创建一个列。

  • 如果您的数据转换只涉及一列,只需对该列使用map()函数(本质上,它是一个系列对象)。
  • 如果您的数据转换涉及多列,请使用apply()功能。

映射并应用

  • 在这两种情况下,我都使用了 lambda 函数。但是,您可以使用常规函数。还可以为map()函数提供一个 dict 对象,它将基于键-值对将旧值映射到新值,其中键是旧值,值是新值。
  • 对于apply()函数,当我们创建一个新列时,我们需要指定axis=1,因为我们是按行访问数据的。
  • 对于 apply()函数,所示的例子是为了演示的目的,因为我可以使用原来的列做一个更简单的算术减法,如下所示:df_wide[‘change’] = df_wide[‘before_meds’] —df_wide[‘after_meds’]

14.连接和合并

当我们有多个数据集时,有必要不时地将它们放在一起。有两种常见的情况。第一种情况是当您有相似形状的数据集,或者共享相同的索引或者相同的列时,您可以考虑直接连接它们。下面的代码向您展示了一些可能的连接。

*# When the data have the same columns, concatenate them vertically* dfs_a = [df0a, df1a, df2a]
pd.concat(dfs_a, axis=0)

*# When the data have the same index, concatenate them horizontally* dfs_b = [df0b, df1b, df2b]
pd.concat(dfs_b, axis=1)
  • 默认情况下,串联执行“外部”连接,这意味着如果有任何不重叠的索引或列,它们都将被保留。换句话说,这就像创建两个集合的并集。
  • 另一件要记住的事情是,如果您需要连接多个数据帧对象,建议您创建一个列表来存储这些对象,并且如果您按顺序执行连接,通过避免生成中间数据帧对象,只执行一次连接。
  • 如果您想重置串联数据帧的索引,您可以设置ignore_index=True参数。

另一种情况是合并具有一个或两个重叠标识符的数据集。例如,一个数据帧有身份证号、姓名和性别,另一个有身份证号和交易记录。您可以使用 id 号列合并它们。下面的代码向您展示了如何合并它们。

*# Merge DataFrames that have the same merging keys* df_a0 = pd.DataFrame(dict(), columns=[**'id'**, **'name'**, **'gender'**])
df_b0 = pd.DataFrame(dict(), columns=[**'id'**, **'name'**, **'transaction'**])
merged0 = df_a0.merge(df_b0, how=**"inner"**, on=[**"id"**, **"name"**])

*# Merge DataFrames that have different merging keys* df_a1 = pd.DataFrame(dict(), columns=[**'id_a'**, **'name'**, **'gender'**])
df_b1 = pd.DataFrame(dict(), columns=[**'id_b'**, **'transaction'**])
merged1 = df_a1.merge(df_b1, how=**"outer"**, left_on=**"id_a"**, right_on=**"id_b"**)
  • 当两个 DataFrame 对象共享相同的一个或多个键时,可以使用on参数简单地指定它们(一个或多个都可以)。
  • 当它们有不同的名称时,您可以指定哪个用于左数据帧和哪个用于右数据帧
  • 默认情况下,合并将使用内部联接方法。当您希望有其他连接方法(例如,left、right、outer)时,您可以为how参数设置适当的值。

15.删除列

虽然您可以通过重命名数据帧中的所有列而不产生任何冲突,但有时您可能希望删除一些列以保持数据集的整洁。在这种情况下,你应该使用drop()功能。

*# Drop the unneeded columns* df.drop([**'col0'**, **'col1'**], axis=1)
  • 默认情况下,drop()函数使用标签来引用列或索引,因此您可能希望确保标签包含在 DataFrame 对象中。
  • 要删除索引,您可以使用axis=0。如果您删除列,我发现它们更常见,您可以使用axis=1
  • 同样,该操作创建了一个数据帧对象,如果您喜欢更改原始的数据帧,您可以指定inplace=True

16.写入外部文件

当您希望与合作者或队友交流数据时,您需要将 DataFrame 对象写入外部文件。在大多数情况下,逗号分隔的文件应该可以满足要求。

*# Write to a csv file, which will keep the index* df.to_csv(**"filename.csv"**)

*# Write to a csv file without the index* df.to_csv(**"filename.csv"**, index=False)

*# Write to a csv file without the header* df.to_csv(**"filename.csv"**, header=False)
  • 默认情况下,生成的文件将保留索引。您需要指定index=False来从输出中删除索引。
  • 默认情况下,生成的文件将保留标题(例如,列名)。您需要指定header=False来移除标题。

结论

在本文中,我们回顾了一些基本操作,您会发现它们对您开始使用 pandas 库很有用。正如文章标题所示,这些技术并不打算以一种奇特的方式处理数据。相反,它们都是允许你以你想要的方式处理数据的基本技术。稍后,您可能会找到更好的方法来完成一些操作。

用 Python 通知

原文:https://towardsdatascience.com/notify-with-python-41b77d51657e?source=collection_archive---------11-----------------------

使用 Python 构建的电子邮件通知让生活更轻松

西蒙·米加杰在 Unsplash上的照片

在 Python 中工作,我经常运行数据处理、传输和模型训练脚本。现在,对于任何合理程度的复杂性和/或大数据,这都需要一些时间。

虽然在等待这些处理过程完成的时候,我们经常都有一些其他的工作要做,但有时我们并没有。

为此,我整理了一组专门为这个问题构建的 Python 脚本。我使用这些脚本向我的手机发送流程更新、可视化和完成通知。

所以,当我们偶尔有自由的时候。我们可以享受它们,而不用担心模型的进展。

我们需要什么

好的,我们需要问的第一件事是— 我们需要知道什么?

当然,这取决于你正在做的工作。对我来说,我有三个主要的处理任务可能会占用时间:

  • 模型训练
  • 数据处理和/或传输
  • 财务建模

对于其中的每一个,当然都有不同的信息需要我们了解。让我们来看一个例子。

模特培训

每 n 个时期更新,必须包括关键指标。例如,训练集和验证集的损失和准确性。

完成通知(当然)。为此,我喜欢包括:

  • 预测输出,用于文本生成,生成的文本(或其样本)——用于图像生成,一个(希望)酷的可视化。
  • 培训期间关键指标的可视化(同样,培训和验证集的损失和准确性)
  • 其他不太重要但仍然有用的信息,如本地模型目录、培训时间、模型架构等

让我们以训练神经网络来再现给定的艺术风格为例。

对于这一点,我们希望看到;从模型生成的图像、损失和精度图、当前训练时间和模型名称。

在这种情况下,每隔 100 个时期,就会发送一封包含上述所有内容的电子邮件。这是其中一封电子邮件:

数据处理和传输

这一个稍微不那么迷人,但是就消耗的时间而言,遥遥领先。

我们将使用 Python 向 SQL Server 批量上传数据的例子(对于我们这些没有BULK INSERT的人)。

在上传脚本的末尾,我们包含了一条简单的消息,通知我们上传完成。

如果偶尔抛出错误,我们还可以添加一个 try-except 子句来捕获错误,并将其添加到一个列表中,以包含在我们的更新和/或完成电子邮件中。

金融建模

在金融建模的情况下,我运行的一切实际上都相当快,所以我只能在这里给你提供一个“示例”用例。

我们将使用现金流建模工具的例子。实际上,这个过程不超过 10-20 秒,但是现在让我们假设我们是华尔街的热门 quants,处理几百万(而不是几百)贷款。

在这封电子邮件中,我们可能希望包含对所分析的投资组合的高层次总结。我们可以随机选择一些贷款并可视化给定时间段内的关键价值——给我们一个小样本来交叉检查模型性能是意料之中的。

代码

上述所有功能都来自一个名为notify.py的脚本。

我们将在示例代码中使用 Outlook。然而,将它翻译给其他提供者是非常容易的,我们将在最后快速介绍这一点。

这里我们需要两个 Python 库,emailsmtplib

  • [**email**](https://docs.python.org/3/library/email.html) —用于管理电子邮件信息。这样,我们将设置电子邮件本身,包括主题、正文和附件。
  • [**smtplib**](https://docs.python.org/3/library/smtplib.html) —处理 SMTP 连接。简单邮件传输协议(SMTP)是大多数电子邮件系统使用的协议,允许通过互联网发送邮件。'

哑剧

消息本身是使用来自email模块的MIMEMultipart对象构建的。我们还使用了三个 MIME 子类,我们将它们attachMIMEMultipart对象:

  • MIMEText —这将包含电子邮件“有效载荷”,即电子邮件正文中的文本。
  • MIMEImage —很容易猜到,这是用来在我们的电子邮件中包含图像的。
  • MIMEApplication —用于 MIME 消息应用对象。对我们来说,这些是文件附件。

除了这些子类,还有其他参数,比如MimeMultipart中的Subject值。所有这些一起给了我们下面的结构。

让我们看看如何将这些放在一起。

这个脚本在很大程度上相当简单。在顶部,我们有我们的导入——这是我们之前讨论过的 MIME 部分,以及 Python 的os库。

接下来定义一个名为message的函数。这允许我们用不同的参数调用函数,并轻松地构建电子邮件消息对象。例如,我们可以编写一封包含多个图像和附件的电子邮件,如下所示:

email_msg = message(
    text="Model processing complete, please see attached data.",
    img=['accuracy.png', 'loss.png'],
    attachments=['data_in.csv', 'data_out.csv']
)

首先我们初始化MIMEMultipart对象,将其赋给msg

然后我们使用'Subject'键设置邮件主题。

attach方法允许我们向MIMEMultipart对象添加不同的 MIME 子类。这样我们就可以使用MIMEText子类来添加邮件正文。

对于图像img和附件attachment,我们可以什么都不传递,传递一个文件路径,或者传递一个文件路径列表。

这是通过首先检查参数是否是None来处理的,如果是,我们通过。否则,我们检查给定的数据类型,如果它不是一个list,我们把它变成一个——这允许我们使用下面的for循环来迭代我们的项目。

此时,我们使用MIMEImageMIMEApplication子类来分别附加我们的图像和文件。对于这两种情况,我们都使用os.basename从给定的文件路径中检索文件名,我们将其作为附件名。

简单邮件传输协议

现在我们已经建立了电子邮件对象,我们需要发送它。

这就是smtplib模块的用武之地。代码也很简单,除了一个例外。

因为我们直接与不同的电子邮件提供商及其各自的服务器打交道,所以我们需要不同的 SMTP 地址。幸运的是,这个真的很好找。

在谷歌中输入“outlook SMTP”。甚至不用点击页面,我们就能得到服务器地址smtp-mail.outlook.com和端口号587

当用smtplib.SMTP 初始化SMTP对象时,我们使用这两种方法——在send函数的开头附近。

smtp.ehlo()smtp.starttls()都是 SMTP 命令。ehlo(扩展 Hello)本质上是问候服务器。starttls通知服务器我们将使用加密传输级安全(TLS)连接进行通信。你可以在这里了解更多关于 SMTP 命令的信息。

之后,我们只需从文件中读取我们的电子邮件和密码,分别存储在emailpwd中。

然后我们用smtp.login登录 SMTP 服务器,用smtp.sendmail发送邮件。

我总是将通知发送给自己,但在自动报告的情况下(或出于任何其他原因),您可能希望将电子邮件发送到其他地方。为此,更改destination_address : smtp.sendmail(email, ***destination_address***, msg.as_string)

最后,我们终止会话并关闭与smtp.quit的连接。

所有这些都放在一个 try-except 语句中。在网络连接暂时中断的情况下,我们将无法连接到服务器。导致了socket.gaierror

实现这个 try-except 语句可以防止程序在网络连接中断时中断。你如何处理这种情况可能会有所不同,这取决于这封邮件的重要性。

对我来说,我用它来更新 ML 模型训练和完成数据传输。如果一封电子邮件没有被发送出去,那也没关系。因此,这种简单、被动的连接丢失处理是合适的。

把它放在一起

现在我们已经编写了代码的两个部分,我们可以发送电子邮件,只需:

# build a message object
msg = message(text="See attached!", img='important.png',
              attachment='data.csv')send(msg)  # send the email (defaults to Outlook)

杰森·法莱特 指出,使用 Gmail 的人可能需要“允许访问不太安全的应用程序”。这样做的步骤可以在 这个堆栈溢出问题中找到

这就是使用 Python 实现电子邮件通知和/或自动化的全部内容。感谢emailsmptlib库,这是一个非常简单的设置过程。

通用电子邮件提供商服务器地址和 TLS 端口。如果你有什么要补充的,请告诉我!

对于任何耗费大量时间的处理或培训任务,进度更新和完成通知通常是真正的解放。

我希望这篇文章对你们中的一些人有用,一如既往,如果你有任何问题或建议,请告诉我!

感谢阅读!

我还写了其他“快速修复”文章,让我们的 Python 生活变得更简单,看看这篇关于 Excel 和 Python 集成的文章:

[## Excel 到 Python

为 Python 工具构建前端 Excel 工作簿

towardsdatascience.com](/excel-to-python-79b01638f2d9)

网络容量规划的新方法

原文:https://towardsdatascience.com/novel-method-for-network-capacity-planning-7993ef263e07?source=collection_archive---------26-----------------------

介绍

一种增强网络容量测量的方法,该方法基于客户在网络上的数据使用与使用近实时大数据架构的客户的位置变化之间的相关性。

在此分析中,我将使用一个模拟热流的模型,并以类似的方式用数学方法表示网络。

此外,我们将通过在偏微分方程和不同来源之间的概率统计相关性建模。

最后,我们将浏览大数据堆栈,在那里我们可以实施该模型并将其可视化。

为什么/好处

很难主动检测网络流量,也很难将其映射到消费者行为。

因此,在这个模型中,我们需要克服 3 个问题:

主动减少网络上的数据流量拥塞,这将改善客户体验和网络的净推广分数。

通过主动检测故障,减少因数据网络问题导致的客户流失,因为这始终是客户退出网络的主要原因之一。

我们需要有一个不同的视角,从商业消费者的角度来规划网络整改。

用例模拟

在这种情况下,我将通过一个非常简单的网络快照模拟,让一群客户使用数据。

网络的一部分看起来会像这样

图 1:在第一个例子中,在时间 T 5,小区 1 有 70MBPs 带宽的活跃用户,而小区 2 完全免费。

在一个时间增量之后,一些用户将移动到其他邻居节点,占用一部分带宽

图 2:在第二个例子中,在时间 T++时,一些活跃用户已经移动到小区 2,带走了一部分带宽

因此,添加一个新的邻居节点并使用部分带宽移动一些客户的模拟将是这样的。

图 3:然后在下一步中,这些用户的一部分移动到其他新的小区,占用部分带宽。

因此,一般来说,在时间 T 有许多节点,我们需要对具有最大流量的小区采取行动,这是总客户和已用带宽的一个因素。

一般来说,通量是单位时间单位面积的能量流的表示,在我们的情况下,通量是单位时间内用户数量和带宽的函数。

所以,我们要经历的最后一个等式。推导过程看起来像这样:一个偏微分方程,对于具有表中定义的最大差分电势“U”的单元,在时间 t 得到建议 R。

所以,这就是汞金属的扩散方式,它在液态移动中扩散,网络数据就像水银一样珍贵。

这里我们开始进行方程推导。

方法总结:

每个客户进行数据 CDR(呼叫详细记录)并离开该小区到另一个相邻小区的概率方法。

概率基于客户使用的历史频率,如语音、短信和移动到相邻小区。

定义网络流量和决定容量建议的模型是基于传热模型的模拟计算的

基于类比的小区流量计算是小区的最小利用率,加上所有来自其他小区的传入数据流量,减去任何到其他小区的传出数据流量。

为了模型的准确性,模型中使用的一些属性可能会被丢弃

在这一步,我们必须回到热流在两个表面之间的工作原理。

然后,当网络流在单元之间移动时,我们将其与网络上的情况进行类比

因此,我们在这里有一些符号和变量,我们需要映射的类比,将有以下定义。

然后流动的偏微分方程将在这些步骤中完成

一般的定义会是这样的

然后,我将 V 定义为包 P 和顾客 C 的函数

然后,通过替换交通流量方程中的所有变量,得到三维距离 d

这里的面积是两个小区之间的两个覆盖区域的最小值,常数 K 将是在小区 1 和 2 之间随时间移动的用户数量对小区 1 上出现的最小用户数量的积分

最后,两个细胞之间的流动看起来像这样

类似地映射到小区之间的距离 x,y 的第三维的 M 变量是健康监控检查,其示出了网络节点相对于时间的健康,将时间 t 处的 M 变量作为小区 1 监控和小区 2 监控之间的差的梯度。

这就是我们如何在两个单元之间映射等式,那么如果我们有多个节点,那么成本函数将像这样分布。

符号为 21 的 u 表示从 cell2 到 cell1 的流量,依此类推。

现在,一般来说,我们可以得到如下 3 个像元之间的等式,其中 Q 为网络常数,它映射到变量定义表中定义的整个网络的成本函数的最小值。

现在扩展到 N 个单元格,我们可以将流量求和如下。

那么问答在这里,我们需要对哪个细胞采取行动,它就是通量(流量)最大的细胞。

所以最终方程会是这样的。

那么,构建该模型所需的网络资源和流量设计示例是什么呢?我们需要一些网络资源和网络核心数据上的客户行为样本,这些样本将被移动到基础设施的不同逻辑层,如下所示:

我们如何在没有关联的来源之间进行事件关联?

现在让我们来看看如何在两个未链接的源之间进行事件关联

我们将使用 DAG(有向无环图)概率方法。

更详细地说,概率计算可以用这个例子的公式来完成

并深入研究开发集群如何实现该模型。

这是 4 个节点,每个节点将提供以下详细服务。

最后,这是大数据开发集群存储体系结构

结论

因此,在这种方法中,我们设计了一个数学模型,它几乎是线性的,可以使用非链接源之间的相关性来主动分析网络行为,并且我们依赖于一个大数据堆栈。

热传递模型的类比是使用相同方法的入口,以使用相同的方法设计其他成本函数。

实现中的所有微分方程都可以在微批处理中的窗口功能方法中进行,或者以流的方式在移动窗口中进行。

关于我

我是一名独立的分析工程师,在该领域拥有丰富的经验。你可以在这里查看我的 LinkedIn,了解更多关于我和我的证书的信息。https://www.linkedin.com/in/ahmedshaaban90

posted @ 2024-10-14 11:49  绝不原创的飞龙  阅读(383)  评论(0)    收藏  举报