TowardsDataScience 博客中文翻译 2019(五百一十四)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

定义在图上的各向异性、动态、谱和多尺度滤波器

原文:https://towardsdatascience.com/tutorial-on-graph-neural-networks-for-computer-vision-and-beyond-part-2-be6d71d70f49?source=collection_archive---------12-----------------------

作为“计算机视觉图形神经网络教程”的一部分

我将通过使用 Python 和 PyTorch 提取关键思想并解释里程碑方法背后的简单直觉,来概述重要的图形神经网络工作。本帖继续 我的教程第一部分

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Graph of Graph Neural Network (GNN) and related works. Some other important works and edges are not shown to avoid further clutter. For example, there is a large body of works on dynamic graphs that deserve a separate overview. Best viewed on a very wide screen in color.

20 多年的图形神经网络

在上面的“图神经网络(GNN)的图及相关著作”中,我补充了我最近一年接触到的关于图的论文。在该图中,两个作品之间的有向边表示一篇论文基于另一篇论文(尽管没有必要引用它),作品的颜色表示:

  • 红色— 光谱方法(需要拉普拉斯图的特征分解,这将在下面解释)
  • 绿色—在空间域中工作的方法(不需要拉普拉斯图的特征分解)
  • 蓝色—相当于光谱方法,但不需要特征分解(因此,实际上是空间方法)
  • 黑色——是 GNNs 的补充方法,与 GNN 本身的选择无关(例如,集中注意力)。

请注意,为了避免混乱,其他一些重要的作品和边缘没有显示出来,只有一小部分作品,用粗体框突出显示的将在本文中介绍。声明:我仍然在那里找到了挤压我们自己最近作品的空间😊。

大多数重要的方法都包含在这个非详尽的作品列表中:

使用神经网络对图进行分类的第一项工作似乎是由亚历桑德罗·斯佩尔杜蒂和安东尼娜·斯塔丽塔在发表的一篇 1997 关于“用于结构分类的监督神经网络”的论文。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

A figure from (Sperduti & Starita, 1997), which is strikingly similar to what we are doing now, after more than 20 years.

斯珀杜蒂&斯塔里塔,1997 :“到目前为止,神经网络已经被用于对非结构化模式和序列进行分类。然而,标准的神经网络和统计方法通常被认为在处理复杂结构时是不够的,因为它们是基于特征的方法。”

自 1997 年以来,关于从图中学习的大量工作已经在如此多的不同方向上增长,如果没有一些智能的自动化系统,很难保持跟踪。我相信我们正在使用基于神经网络的方法(基于我的教程第一部分*】*中的 中解释的公式(2)】,或者神经网络和其他方法的某种组合。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Graph neural layer’s formula (2) from the first part of my tutorial that we will also need in this part. Keep in mind, that if we need to compute a specific loss for the output features or if we need to stack these layers, we apply some activation like ReLU or Softmax.

回顾一下我们在第一部分中使用的符号,我们有一些无向图 GN 节点。该图中的每个节点都有一个 C 维特征向量,所有节点的特征都表示为一个 N × C 维矩阵 X⁽ˡ⁾.在一个典型的图网络中,比如 GCN ( Kipf & Welling,ICLR,2017 ),我们将这些特征 X⁽ˡ⁾ 馈送到一个具有 C × F 维可训练权重 W⁽ˡ⁾ 的图神经层,这样该层的输出就是一个 N × F 矩阵𝓐是一个 N × N 矩阵,其中条目𝓐 ᵢⱼ 指示节点 i 是否连接到节点 j 的相邻节点。这个矩阵被称为邻接矩阵。我使用𝓐而不是普通的 A 来强调这个矩阵可以被规范化以促进深层网络中的特征传播。出于本教程的目的,我们可以假设𝓐= A ,即矩阵乘积𝓐 X⁽ˡ⁾ 的第 i 至第t51】行将包含节点 i 邻居的特征的总和。**

在本部分教程的剩余部分,我将简要解释概览图中用粗体框显示的我选择的作品。我推荐布朗斯坦等人的评论进行更全面和正式的分析。

请注意,尽管我在下面深入研究了光谱图卷积的一些技术细节,但最近的许多作品(如徐等人的 GIN,2019 )都是在没有光谱卷积的情况下建立的,并在一些任务中显示出很好的结果。然而,了解谱卷积的工作原理仍然有助于理解和避免其他方法的潜在问题。

1。光谱图卷积

布鲁纳等人,2014,ICLR 2014

我在我的另一篇文章中详细解释了谱图卷积。

为了这部分教程的目的,我在这里简单总结一下。谱图卷积的正式定义与信号/图像处理中的卷积定理非常相似,可以写成:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Spectral graph convolution, where ⊙ means element-wise multiplication.

其中 V 为特征向量,λ图拉普拉斯 L 的特征值,通过特征分解可以找到:l=vλvᵀ;w_ 光谱滤光片。在本教程中,我将假设“对称归一化拉普拉斯算子”。它是基于图的邻接矩阵 A 上的唯一来计算的,这可以用几行 Python 代码来完成,如下所示:

**# Computing the graph Laplacian
# A is an adjacency matrix** import numpy as npN = A.shape[0] **# number of nodes in a graph**
D = np.sum(A, 0) **# node degrees**
D_hat = np.diag((D + 1e-5)**(-0.5)) **# normalized node degrees**
L = np.identity(N) — np.dot(D_hat, A).dot(D_hat) **# Laplacian**

这里,我们假设 A 是对称的,即 A = A ᵀ,并且我们的图是无向图,否则节点度不是明确定义的,并且必须做出一些假设来计算拉普拉斯算子。在计算机视觉和机器学习的背景下,图形拉普拉斯定义了如果我们以公式(2)的形式堆叠几个图形神经层,节点特征将如何更新。

所以,给定图的拉普拉斯 L ,节点特征 X 和过滤器 W _spectral,在 Python 图上的谱卷积看起来非常简单:

**# Spectral convolution on graphs
# X is an *N×1 matrix of 1-dimensional node features*** **# L** **is an** ***N******×N* graph Laplacian computed above
# W_spectral are** ***N******×******F weights (filters) that we want to train*** from scipy.sparse.linalg import eigsh **# assumes *L* to be symmetric***Λ**,V* = eigsh(L,k=20,which=’SM’) **#** **eigen-decomposition (i.e. find *Λ******,V)***
X_hat = V.T.dot(X) **# *20*****×*****1* node features in the "spectral" domain**
W_hat = V.T.dot(W_spectral)  **# 20×*F* filters in the** **"spectral" domain**
Y = V.dot(X_hat * W_hat)  **# *N******×******F* result of convolution**

其中我们假设我们的节点特征 X⁽ˡ⁾ 是一维的,例如 m 像素,但是它可以扩展到 C 维的情况:我们将只需要对每个通道重复这个卷积,然后像在信号/图像卷积中一样对 C 求和。

公式(3)本质上与使用傅立叶变换的规则网格上的信号的频谱卷积相同,因此为机器学习产生了一些问题:

  1. 可训练权重(滤波器)的维数取决于图中节点的数量;
  2. W_ 光谱也取决于图结构中编码的特征向量 V.

这些问题阻碍了扩展到具有可变结构的大型图形的数据集。

为了解决第一个问题,布鲁纳等人提出在谱域对滤波器进行平滑,根据谱理论使滤波器在空间域更加局部化。其思想是,您可以将公式(3)中的滤波器 W_ 频谱表示为𝐾预定义函数(如样条函数)的和,并且我们学习这个和的 WN 值,而不是学习这个和的 K 系数 α :

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

We can approximate our N dimensional filter*W_*spectral as a finite sum of K functions f, such as splines shown below. So, instead of learning N values of *W_*spectral, we can learn K coefficients (alpha) of those functions; it becomes efficient when K << N.

虽然 fk 的维数确实取决于节点 N 的数量,但是这些函数是固定的,所以我们不学习它们。我们唯一知道的是系数 α ,因此 W_ 光谱不再依赖于 N 。为了使我们在公式(4)中的近似合理,我们希望 K < < N 将可训练参数的数量从 N 减少到 K ,更重要的是,使其独立于 N ,以便我们的 GNN 可以消化任何大小的图。

虽然解决了第一个问题,但是这种平滑方法没有解决第二个问题。

2。切比雪夫卷积

Defferrard 等人,NeurIPS,2016 年

上面的频谱卷积及其平滑版本的主要缺点是,它仍然需要对一个 N × N 维拉普拉斯图 L 进行本征分解,这产生了两个主要问题:

  1. 🙁特征分解的复杂度是巨大的,O( N )。此外,在大图的情况下,在 RAM 中以密集格式保持图拉普拉斯是不可行的。一种解决方案是使用稀疏矩阵,并用 Python 中的scipy.sparse.linalg.eigs找到特征向量。此外,您可以在具有大量 RAM 和 CPU 内核的专用服务器上预处理所有训练图。在很多应用中,你的测试图也可以提前预处理,但是如果你不断有新的大图涌入,特征分解会让你难过。
  2. 🙁另一个问题是,你训练的模型最终与图的特征向量 V 密切相关。如果您的训练图和测试图具有非常不同的结构(节点和边的数量),这可能是一个大问题。否则,如果所有的图形都非常相似,问题就不大了。此外,如果您在频域中使用一些平滑滤波器,如上面讨论的样条,那么您的滤波器将变得更加局部化,适应新图形的问题似乎更加不明显。然而,这些模型仍然非常有限。

那么,切比雪夫图卷积和这些有什么关系呢?

原来它同时解决了**两个问题!**😃

也就是说,它避免了计算昂贵的特征分解,并且滤波器不再“附着”于特征向量(然而它们仍然是特征值λ)的函数)。此外,它有一个非常有用的参数,通常表示为 K ,具有与我们上面的公式(4)中的 K 相似的直觉,确定滤波器的局部性。非正式地:对于 K =1,我们只将节点特性 X⁽ˡ⁾ 提供给我们的 gnn 对于 K =2,我们馈 X⁽ˡ⁾ 和𝓐x⁽ˡ⁾;对于 K=3,我们馈x⁽ˡ⁾𝓐x⁽ˡ⁾和𝓐x⁽ˡ⁾;对于更大的 K 以此类推(我希望你已经注意到这个模式)。更准确正式的定义见 Defferrard et al. 和下面我的代码,加上额外的分析在( Knyazev et al .,NeurIPS-W,2018 )中给出。

由于邻接矩阵的幂属性,当我们执行𝓐 X⁽ˡ⁾ 时,我们实际上对 2 跳邻居进行平均(或求和,取决于𝓐如何归一化),并且类似地,对𝓐 ⁿX⁽ˡ⁾ 中的任何 n 进行平均,如下图所示,其中我们对 n 跳邻居进行平均。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Chebyshev convolution for K=3 for node 1 (dark blue). Circled nodes denote the nodes affecting feature representation of node 1. The [,] operator denotes concatenation over the feature dimension. W⁽ˡ⁾ are 3C×F dimensional weights.**

注意,为了满足切比雪夫基的正交性,𝓐 假设图中没有回路,因此在矩阵乘积𝓐 X⁽ˡ⁾ 的每 i 行中,我们将具有节点 i 的邻居的特征,但是没有节点 i 本身的特征。节点 i 的特征将作为矩阵 X⁽ˡ⁾.单独输入

如果 K 等于节点数 N ,则切比雪夫卷积非常接近于频谱卷积,因此滤波器的感受域将是整个图形。但是,正如卷积网络的情况一样,由于我已经讨论过的一些原因,我们不希望滤波器与输入图像一样大,因此在实践中, K 取合理的小值。

根据我的经验,这是最强大的 gnn 之一,在非常广泛的图形任务中取得了很好的结果。主要的缺点是在向前/向后传递中必须循环遍历 K (因为切比雪夫多项式是递归的,所以不可能并行化它们),这会降低模型的速度。

与上面讨论的样条一样,我们不是训练滤波器,而是训练切比雪夫多项式的系数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Chebyshev basis used to approximate convolution in the spectral domain.

要生成切比雪夫基,可以使用以下 Python 代码:

****# Set K to some integer > 0, like 4 or 5 in our plots above
# Set n_points to a number of points on a curve (we set to 100)** import numpy as npx = np.linspace(-1, 1, n_points)
T = np.zeros((K, len(x)))
T[0,:] = 1
T[1,:] = x
for n in range(1, K-1):
    T[n+1, :] = 2*x*T[n, :] - T[n-1, :] **# recursive computation**   
return T**

生成样条和切比雪夫基的完整代码在我的 github repo 中。

为了说明切比雪夫滤波器在不规则网格上的表现,我再次遵循布鲁纳等人的实验,从 MNIST 网格中随机抽取 400 个点,其方式与我展示拉普拉斯图的特征向量的方式相同。我在从这 400 个位置采样的 MNIST 图像上训练了一个切比雪夫图卷积模型(相同的不规则网格用于所有图像),下面显示了一个用于 K =1 和 K =20 的过滤器。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

A single Chebyshev filter (K=3 on the left and K=20 on the right) trained on MNIST and applied at different locations (shown as a red pixel) on a irregular grid with 400 points. Compared to filters of standard ConvNets, GNN filters have different shapes depending on the node at which they are applied, because each node has a different neighborhood structure.

3。GCN

Kipf &韦林,ICLR,2017

您可能已经注意到,如果增加切比雪夫卷积的 K ,可训练参数的总数就会增加。例如,对于 K =2,我们的权重 W⁽ˡ⁾ 将是 2 C × F 而不是仅仅 C × F 。这是因为我们将特征x⁽ˡ⁾t16】t17】和𝓐 X⁽ˡ⁾ 连接成一个单一的 N ×2 C 矩阵。更多的训练参数意味着模型比更难训练,需要标注更多的数据进行训练。图表数据集通常非常小。在计算机视觉中,MNIST 被认为是一个很小的数据集,因为图像只有 28×28 维,只有 60k 个训练图像,而在图网络中,MNIST 是相当大的,因为每个图将有 N =784 个节点,60k 是大量的训练图。与计算机视觉任务相比,许多图形数据集只有大约 20-100 个节点和 200-1000 个训练样本。这些图可以表示某些小分子,标记化学/生物数据通常比标记图像更昂贵。因此,训练切比雪夫卷积模型可能导致训练集的严重过拟合(即,模型将具有接近 0 的训练损失,但将具有较大的验证或测试误差)。所以, Kipf & Welling 的 GCN 本质上是将节点特征x⁽ˡ⁾t36】t37】和𝓐 X⁽ˡ⁾ 的矩阵“合并”成一个单独的 N × C 矩阵。结果,与具有 K =2 的切比雪夫卷积相比,该模型需要训练的参数少了两倍,但具有 1 跳的相同感受野。主要的技巧是通过将一个单位矩阵 I 添加到𝓐 中,并以特定的方式对其进行规范化,从而将“自循环”添加到您的图中,因此现在在矩阵乘积的每一行I**x⁽ˡ⁾中,我们将拥有节点 i、 的邻居的特征,以及节点 i.特征

这个模型似乎是一个标准的基线选择,非常适合许多应用程序,因为它的轻量级、良好的性能和对较大图形的可伸缩性。

3.1.GCN vs 切比雪夫层

GCN 卷积和切比雪夫卷积的区别如下图所示。

上面的代码遵循与我的教程 的第一部分 中相同的结构,在那里我比较了经典的 NN 和 GNN。GCN 和切比雪夫卷积中的一个主要步骤是重新标度图拉普拉斯 L 的计算。进行这种重新调整是为了使特征值在[-1,1]的范围内,以便于训练(这在实践中可能不是非常重要的步骤,因为权重可以在训练期间适应)。在 GCN,如上所述,在计算拉普拉斯算子之前,通过添加单位矩阵将自循环添加到图中。这两种方法的主要区别在于,在切比雪夫卷积中,我们递归地遍历 K 来捕获 K 跳邻域中的特征。我们可以将这样的 GCN 或切比雪夫层与非线性交错堆叠起来,构建一个图形神经网络。

现在,让我礼貌地打断一下😃我们的频谱讨论并给出了另外两种令人兴奋的方法背后的大致想法:边缘条件滤波器,由 Simonovsky & Komodakis,CVPR,2017 和莫奈,由 Monti 等人,CVPR,2017 ,它们共享一些类似的概念。

4。边缘调节的滤波器

西蒙诺夫斯基&CVPR 科莫达基斯,2017

如你所知,在 ConvNets 中,我们通过优化一些损失来学习权重(过滤器),如交叉熵。同样,我们在 GNNs 中学习 W⁽ˡ⁾。想象一下,你有另一个网络来预测这些权重,而不是学习这些权重。因此,在训练过程中,我们学习辅助网络的权重,它以一幅图像或一个图形作为输入,并返回权重 W⁽ˡ⁾ (他们工作中的θ)作为输出。该想法基于动态滤波器网络 ( Brabandere 等人,NIPS,2016 ),其中“动态”意味着滤波器 W⁽ˡ⁾ 将根据输入而不同,这与标准模型相反,在标准模型中,滤波器在训练后是固定的(或静态的)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Using an auxiliary “filter generating network” Fˡ to predict edge-specific weights Θ for the main network. Xˡ⁻¹ are input node features and Xˡ are output features. The figure shows a single iteration of “dynamic convolution” for node 1 (in yellow). Standard GNNs typically would simply average (or sum) features of node 1 neighbors (nodes 2, 3, 4, 5) , which would correspond to having an isotropic filter (Θ would be a constant vector). In contrast, this model has anisotropic filters, because it predicts different edge values between node 1 and all it’s neighbors based on edge labels L, so that features Xˡ(1) are computed as a weighted average of neighbors’ features. Figure from (Simonovsky & Komodakis, CVPR, 2017).

这是一种非常普遍的卷积形式,除了图像之外,还可以很容易地应用于图形或点云,正如他们在 CVPR 的论文中所做的那样,并获得了出色的结果。然而,没有“免费的午餐”,训练这样的模型相当具有挑战性,因为常规的网格约束现在已经放松,解决方案的范围急剧增加。这对于具有许多边的较大图形或较深层中的卷积来说尤其如此,这些图形通常具有数百个通道(特征数量, C) ,因此您可能最终会为每个输入总共生成数千个数字!在这方面,标准 ConvNets 非常好,因为我们没有浪费模型的能力来训练预测这些权重,而是直接强制要求滤波器对所有输入都应该相同。但是,这种先验使 ConvNets 受到限制,我们不能直接将它们应用于图形或点云。因此,一如既往,在特定任务中,灵活性和性能之间会有一些权衡。

当应用于图像时,如 MNIST,边缘条件模型可以学习预测各向异性滤波器——对方向敏感的滤波器,如边缘检测器。与我的教程 的第一部分 中讨论的高斯滤波器相比,这些滤波器能够更好地捕捉图像中的某些模式,例如数字中的笔画。**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Convolutional filters learned on MNIST sampled in low (left) and high (right) resolutions. Figure from (Simonovsky & Komodakis, CVPR, 2017).

我想再强调一次,每当我们有一个带有辅助网络的复杂模型时,在某种意义上它就变成了一个先有鸡还是先有蛋的问题。为了解决这个问题,其中一个网络(辅助网络或主网络)应该接收到非常强的信号,这样它就可以隐式地监控另一个网络。在我们的 BMVC 论文中,类似于Simonovsky&Komodakis的工作,我们在生成边的网络上应用了额外的约束来促进训练。我将在后面的帖子中详细描述我们的工作。

5。莫奈

蒙蒂等人,CVPR,2017 年

MoNet 不同于本文中讨论的其他作品,因为它假定具有节点坐标的概念,因此更适合于几何任务,如 3D 网格分析或图像/视频推理。它有点类似于 Simonovsky & Komodakis 的边缘条件滤波器,因为它们也引入了预测权重的辅助可学习函数𝐷(𝑤、𝜃 ,ρ 。不同的是,这些权重取决于节点极坐标(角度𝜃和半径ρ);并且该函数的可训练参数𝑤被约束为高斯分布的均值和方差,从而我们不是学习 N × N 矩阵,而是仅学习与图大小 N 无关的固定大小的向量(均值和方差)。就标准 ConvNets 而言,对于每个滤波器来说,只学习 2 个值(高斯分布的平均值和方差)是相同的,而不是分别学习 3×3、5×5 或 11×11 维滤波器的 9、25 或 121 个值。这种参数化将极大地减少 ConvNet 中的参数数量,但滤波器捕捉图像特征的能力非常有限。****

Monti 等人训练高斯的𝐽均值和方差,转换节点坐标的过程类似于将它们拟合到高斯混合模型。如果我们希望我们的过滤器足够全局,那么这个模型的训练计算量相当大,但它可能是视觉任务的一个很好的选择(参见我们的 BMVC 论文进行比较),但在非视觉任务上,它往往比简单的 GCN 差( Knyazev 等人,NeurIPS-W,2018 )。由于函数 D 依赖于坐标,生成的滤波器也是各向异性的,并且具有如下图所示的定向和拉长的高斯形状。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Filters trained with MoNet in polar coordinates 𝜃 and ρ. Each ellipse corresponds to a slice of a Gaussian at some fixed level. The idea is that if the coordinates of the i-th node are close to the middle of the j-th Gaussian, then the generated weight at index (i,j) will have a value close to 1.

*****Pseudo-code of the MoNet layer using PyTorch*****# assume X to be input *N***×***C* node features**
**# coord are *N*×*N*×*2* node coordinate differences between all pairs of nodes (node degrees for non-geometric tasks)
# coord can be viewed as angular and radial edges between nodes**1\. Generate *J* Gaussian-shaped filters based on coordinates of nodes    using some trainable function D
   weights = D(coord)  # weights: *J*×*N*×*N*
2\. Multiply node features X by these weights
   X = torch.bmm(weights, X.expand(J, N, C))  # X: *J*×*N*×*C*
3\. Project features by a learnable linear transformation
   X = fc(X.permute(1, 2, 0).view(N, J*C))  # X: *N*×*F* 4\. Feed X to the next layer**

结论

尽管讨论了很长时间,我们只是触及了皮毛。图形神经网络的应用正在扩展,远远超出了典型的图形推理任务,如分子分类。不同图形神经层的数量增长非常快,类似于几年前卷积网络的情况,因此很难跟踪它们。在这一点上,py torch Geometric(PyG)——一个从图表中学习的好工具箱——经常用新颖的图层和技巧填充它的集合。

鸣谢:本教程的很大一部分是我在 SRI International 实习期间在 穆罕默德·阿梅尔 ( 主页 )和我的博士导师格拉汉姆·泰勒( 主页 )的指导下编写的。我也感谢Carolyn Augusta的有用反馈。

GithubLinkedInTwitter 上找我。我的主页

如果你想在你的论文中引用这篇博文,请使用:
@ misc
{ Knyazev 2019 Tutorial,
title = {用于计算机视觉及超越的图形神经网络教程},
author={Knyazev,Boris and Taylor,Graham W and Amer,Mohamed R},
year={2019}
}
**

变分图自动编码器教程

原文:https://towardsdatascience.com/tutorial-on-variational-graph-auto-encoders-da9333281129?source=collection_archive---------4-----------------------

图适用于许多现实世界的数据集,如社会网络、引用网络、化学图等。对图结构数据日益增长的兴趣增加了对图神经网络的研究。

变分自动编码器体现了变分贝叶斯方法在深度学习中的成功,并激发了广泛的研究。变分图自动编码器(VGAE)将 VAE 的思想应用于图结构数据,显著提高了在大量引用网络数据集(如 Cora 和 Citesser)上的预测性能。

我在网上搜了一下,还没有看到关于 VGAE 的详细教程。在这篇文章中,我将简单地谈谈传统的自动编码器和变化的自动编码器。此外,我将讨论将 VAE 应用于图结构数据(VGAE)的想法。

传统自动编码器

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 1: The architecture of the traditional autoencoder

传统的自动编码器是包含编码器和解码器的神经网络。编码器将数据点 X 作为输入,并将其转换为低维表示(嵌入) Z 。解码器采用低维表示 Z 并返回原始输入 X-hat 的重构,看起来像输入 X 。嵌入的质量决定输出的质量 X-hat 。然而,编码器不可能编码所有的信息,因为嵌入的维数比输入的维数低。因此,如果嵌入从输入中捕获更多的信息,输出将具有更好的性能。

编码器和解码器的架构

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 2: Traditional autoencoder for MNIST dataset

让我们看一个例子。图 2 显示了一个自动编码器的例子,它将 MNIST 图像作为输入。MNIST 数据集包含灰度图像,每个图像的形状为 28 x 28 像素。编码器获取该图像并将其转换为低维嵌入 Z 。解码器采用嵌入 Z 并返回重构的输入图像,该图像是自动编码器的输出。

损失函数

自动编码器的损失函数测量重建期间的信息损失。我们希望最小化重建损失,以使 X-hat 更接近 X 。我们经常使用均方误差作为损失函数,

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其测量 X-hatX 的接近程度。

为什么我们要将输入转换为低维嵌入?

让我们以图像为例。有几种方法可以使用图像的低维嵌入。与存储图像的像素强度相比,存储图像的低维嵌入可以节省存储空间。存储图像的低维嵌入也可以节省计算能力,因为输入维度更低。

靠近图像嵌入的点也是嵌入空间中的图像嵌入,这是使自动编码器嵌入有用的另一个原因。例如,如果您修改 MNIST 影像的像素强度,您将得到一个看起来不像 MNIST 数据集中的影像的噪声影像。但是,如果您对 MNIST 图像的嵌入进行少量修改,然后对修改后的嵌入进行解码,您仍然可以得到看起来像 MNIST 图像的东西。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 3: Modify the pixel intensities of an MNIST image

图 3 显示了修改 MNIST 图像的像素强度的例子。在每个像素的强度中添加一些随机噪声后,输出的是一幅噪声图像,看起来不像 MNIST 数据集中的图像。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 4: Modify the embedding of MNIST image by a small amount

图 4 显示了一个修改 MNIST 图像的嵌入的例子。少量修改嵌入与嵌入空间的小位移是一样的。从图 4 中我们可以看到,在嵌入 Z 中每个元素加 4 后,输出图像 X2 帽仍然与原始输出 X1 帽非常相似。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 5: An example of plotting MNIST data on embedding space

我们也可以把这些低维嵌入标绘到 n-d 坐标上。图 5 显示了在嵌入空间上绘制 MNIST 数据的例子。嵌入空间上的每个点代表一个输入数据。这种可视化很方便,因为它可以系统地组织坐标中的所有输入数据。

低维嵌入也可以用于下游的机器学习任务。我们可以使用预先计算的嵌入来解决另一个机器学习问题,即分类问题。我们可以对这些嵌入而不是原始输入进行分类。我们还可以在迁移学习或半监督学习中使用嵌入,这可能会给我们带来比原始输入更好的结果。

可变自动编码器

为什么我们需要可变的自动编码器?

变分自动编码器的最大优势之一是 VAE 可以从原始源数据集生成新数据。相比之下,传统的自动编码器只能生成与原始输入相似的图像。假设你想建一个长满灌木的花园。每一株灌木都需要与众不同,这样你的花园才会看起来真实。你肯定不能自己画每一棵灌木,一个更聪明的方法是使用自动编码器自动生成新的灌木。

主要思想

变分自动编码器的主要思想是将输入 X 嵌入到一个分布中,而不是一个点中。然后随机样本 Z 取自分布,而不是直接从编码器产生。

编码器和解码器的架构

VAE 的编码器通常写成 qφ(z|x) ,它取一个数据点 X 并产生一个分布。该分布通常被参数化为多元高斯分布。因此,编码器预测高斯分布的平均值和标准偏差。低维嵌入 Z 从此分布中采样。解码器是一个变分近似, pθ(x|z) ,它采用一个嵌入 Z 并产生输出 X-hat

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 6: An example of a variational autoencoder

损失函数

VAE 的损失函数有两部分。损失函数的第一部分称为变分下界,它衡量网络重构数据的好坏。如果重建数据 X 与原始数据差别很大,那么重建损失将会很高。损失函数的第二部分作为正则项工作。它是近似值与真实后验值( p(z) )的 KL 散度,它衡量输出分布( qφ(z|x) )与 p(z) 的匹配程度。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

摘要

VAE 的想法可以用下图来概括:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 7: The architecture of the variational autoencoder

编码器将数据点 X 作为输入,并生成μ和 logσ作为输出。我们使用 logσ而不是σ的原因是σ是非负的,因此我们将需要一个额外的激活函数。但是 logσ可能是正的,也可能是负的。在我们得到μ和 logσ之后,我们试图让μ和 logσ都接近 0,也就是说μ接近 0,σ接近 1。因此,最终分布将接近于 N(0,1) 。最后,我们想通过 z = μ + σ * ε 由μ和σ生成嵌入 Z ,其中ε ~ N(0,1) 。这被称为重新参数化技巧。现在有了潜在变量 Z ,我们可以通过解码器生成我们的输出 X-hat

变分图自动编码器

介绍

我们希望构建一个变分图自动编码器,将 VAE 的思想应用于图结构数据。我们希望我们的变分图自动编码器能够生成新的图形或关于图形的推理。然而,我们不能直接应用 VAE 的思想,因为图结构的数据是不规则的。每个图都有不同大小的无序节点,图中的每个节点都有不同数量的邻居,所以我们不能再直接使用卷积了。让我们弄清楚如何以神经网络可以理解的方式来表示图形。

邻接矩阵

我们使用一个邻接矩阵 A 来表示输入图。通常我们假设邻接矩阵是二进制的。第 i 行和第 j 列的值 1 表示顶点 i 和顶点 j 之间有一条边。行 m 和列 n 的值 0 表示顶点 m 和顶点 n 之间没有边。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 8: An example of the adjacency matrix

图 8 显示了当输入图是有向和无向时邻接矩阵的例子。在图的左侧,当图是无向图时,邻接矩阵是对称的。顶点 0 和顶点 1 是相连的,所以 A[0,1] = 1A[1,0] = 1 。当图是有向图时,右边的邻接矩阵是不对称的。顶点 0 指向顶点 1,意味着顶点 1 聚合了来自顶点 0 的信息,所以 A[1,0] = 1

特征矩阵

我们使用特征矩阵 X 来表示输入图中每个节点的特征。特征矩阵 X 的行 i 代表顶点 i 的特征嵌入。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 9: An example of the feature matrix

图 9 显示了特征矩阵的一个例子。每个节点 i 都有自己的特征矩阵 X_i ,我们可以将它们组合在一起得到整个图的特征矩阵 X ,其中每一行 i 代表节点 i 的特征矩阵。

编码器和解码器的架构

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 10: The architecture of the variational graph autoencoder

VGAE 的编码器(推理模型)由图卷积网络 ( GCNs )组成。它以邻接矩阵 A 和特征矩阵 X 作为输入,生成潜变量 Z 作为输出。第一 GCN 层生成低维特征矩阵。它被定义为

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

A-tilde 是对称归一化邻接矩阵。

第二 GCN 层产生μ和 logσ,其中

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在如果我们把两层 GCN 的数学结合在一起,我们得到

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从而产生μ和 logσ。

然后我们可以使用参数化技巧计算出 Z

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其中ε ~ N(0,1)。

解码器(生成模型)由潜在变量 Z 之间的内积定义。我们解码器的输出是一个重构的邻接矩阵 A-hat ,其定义为

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其中σ()是逻辑 sigmoid 函数。

总之,编码器表示为

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

并且解码器被表示为

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

损失函数

变分图自动编码器的损失函数和以前几乎一样。第一部分是输入邻接矩阵和重构邻接矩阵之间的重构损失。更具体地说,它是目标(A)和输出(A’)逻辑之间的二元交叉熵。第二部分是 q (Z | X,A)p(Z) 之间的 KL-散度,其中 p(Z) = N(0,1) 。它测量我们的 q (Z | X,A)p(Z) 的匹配程度。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用内积解码器的优势

在我们得到潜变量 Z 之后,我们要想办法学习潜变量中每一行的相似度(因为一行代表一个顶点)来生成输出邻接矩阵。内积可以计算两个向量的余弦相似性,这在我们需要一个对向量大小不变的距离度量时很有用。因此,通过对潜在变量 ZZ^T 应用内积,我们可以学习 Z 内部每个节点的相似度来预测我们的邻接矩阵。

链路预测实验

变分图自动编码器论文中,作者还创建了一个传统的图自动编码器模型(GAE)作为 VGAE 模型的对比。GAE 模型有一个单 GCN 层作为编码器,直接生成潜变量 Z ,还有一个内积解码器,和 VGAE 模型一样。作者在三个数据集(Cora、citeser 和 Pubmed)上测试了这两个模型,VGAE 模型在 Cora 和 citeser 数据集上都获得了更高的预测性能。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结论

在这篇文章中,你已经学习了传统自动编码器、变分自动编码器的基本思想,以及如何将 VAE 的思想应用于图结构数据。

图结构数据在当今各个领域发挥着越来越重要的作用。我相信在不久的将来,图结构数据分析将成为机器学习中最受欢迎的主题之一。

参考

[1] 自动编码变分贝叶斯

[2] 变分图自动编码器

[3] 图形自动编码器 TensorFlow 实现

[4] 变分自动编码器教程

[5] 库尔贝克-莱布勒散度

教程:使用深度学习和 CNN 制作手势识别模型

原文:https://towardsdatascience.com/tutorial-using-deep-learning-and-cnns-to-make-a-hand-gesture-recognition-model-371770b63a51?source=collection_archive---------1-----------------------

首先,这是包含代码的 Github 库。该项目采用 Jupyter 笔记本的形式,可以上传到谷歌合作实验室,在没有环境问题的情况下工作。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

机器学习对于各种现实生活中的问题非常有用。它通常用于分类、识别、检测和预测等任务。此外,自动化使用数据的流程非常有效。基本思想是使用数据生成一个能够返回输出的模型。这个输出可以用新的输入给出正确的答案,或者产生对已知数据的预测。

这个项目的目标是训练一个机器学习算法,能够对不同手势的图像进行分类,例如拳头、手掌、拇指和其他手势。例如,这个特殊的分类问题对手势导航很有用。我将使用的方法是借助基于 Tensorflow 和 Keras 的卷积神经网络进行深度学习。

深度学习是更广泛的机器学习方法家族的一部分。它基于处理输入数据的图层的使用,从这些图层中提取要素并生成数学模型。这个“模型”的创建将在下一次会议中更加清晰。在这个特定的项目中,我们的目标是对手势的不同图像进行分类,这意味着计算机必须“学习”每个手势的特征,并对它们进行正确分类。例如,如果给定一个做竖起大拇指手势的手的图像,模型的输出需要是“手在做竖起大拇指的手势”。我们开始吧。

加载数据

这个项目使用了 Kaggle 上的手势识别数据库(引用如下)。它包含了 20000 张不同手和手势的图片。在数据集中呈现了 10 个不同的人的总共 10 个手势。女被试 5 人,男被试 5 人。
这些图像是使用 Leap Motion 手部跟踪设备拍摄的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Table 1 — Classification used for every hand gesture.

有了这些,我们必须准备图像来训练算法。我们必须将所有图像加载到一个名为 X 的数组中,并将所有标签加载到另一个名为 y 的数组中。

X = [] # Image data
y = [] # Labels# Loops through imagepaths to load images and labels into arrays
for path in imagepaths:
  img = cv2.imread(path) # Reads image and returns np.array
  img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # Converts into the corret colorspace (GRAY)
  img = cv2.resize(img, (320, 120)) # Reduce image size so training can be faster
  X.append(img)

  # Processing label in image path
  category = path.split("/")[3]
  label = int(category.split("_")[0][1]) # We need to convert 10_down to 00_down, or else it crashes
  y.append(label)# Turn X and y into np.array to speed up train_test_split
X = np.array(X, dtype="uint8")
X = X.reshape(len(imagepaths), 120, 320, 1) # Needed to reshape so CNN knows it's different images
y = np.array(y)print("Images loaded: ", len(X))
print("Labels loaded: ", len(y))

Scipy 的 train_test_split 允许我们将数据分成一个训练集和一个测试集。训练集将用于构建我们的模型。然后,测试数据将被用来检验我们的预测是否正确。使用了一个 random_state 种子,因此我们的结果的随机性可以被重现。该函数将随机播放它正在使用的图像,以最大限度地减少训练损失。

# Percentage of images that we want to use for testing. 
# The rest is used for training.
ts = 0.3X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=ts, random_state=42)

创建模型

为了简化这里构建的模型,我们将使用线性回归的概念。通过使用线性回归,我们可以创建一个简单的模型,并使用等式 y = ax + b 来表示它。
ab (分别是斜率和截距)是我们试图寻找的参数。通过寻找最佳参数,对于任何给定的 x 值,我们可以预测 y 。这是相同的想法,但更复杂,使用卷积神经网络。

卷积神经网络(ConvNet/CNN)是一种深度学习算法,可以接受输入图像,为图像中的各个方面/对象分配重要性(可学习的权重和偏差),并能够区分彼此。与其他分类算法相比,ConvNet 中所需的预处理要低得多。虽然在原始方法中,过滤器是手工设计的,但是经过足够的训练,CNN 有能力学习这些过滤器/特征。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 1 — Example of Convolutional Neural Network.

从图 1 和想象我们讲过的线性回归模型方程,我们可以想象输入层是 x ,输出层是 y 。隐藏层因模型而异,但它们用于“学习”模型的参数。每一个都有不同的功能,但他们致力于获得最佳的“斜率和截距”。

# Construction of model
model = Sequential()
model.add(Conv2D(32, (5, 5), activation='relu', input_shape=(120, 320, 1))) 
model.add(MaxPooling2D((2, 2)))
model.add(Conv2D(64, (3, 3), activation='relu')) 
model.add(MaxPooling2D((2, 2)))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D((2, 2)))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dense(10, activation='softmax'))# Configures the model for training
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])# Trains the model for a given number of epochs (iterations on a dataset) and validates it.
model.fit(X_train, y_train, epochs=5, batch_size=64, verbose=2, validation_data=(X_test, y_test))

CNN 将一系列过滤器应用于图像的原始像素数据,以提取和学习更高级别的特征,然后模型可以使用这些特征进行分类。CNN 包含三个组件:

  • 卷积层,将指定数量的卷积滤镜应用于图像。对于每个子区域,图层执行一组数学运算,以在输出要素地图中生成单个值。然后,卷积层通常对输出应用 ReLU 激活函数,以将非线性引入模型。
  • 池层,对卷积层提取的图像数据进行下采样,以降低特征图的维度,从而减少处理时间。最大池算法是一种常用的池算法,它提取特征地图的子区域(例如,2x2 像素的分块),保留其最大值,并丢弃所有其他值。
  • 密集(完全连接)图层,对卷积图层提取的要素执行分类,并由汇集图层进行缩减采样。在密集层中,该层中的每个节点都连接到前一层中的每个节点。

测试模型

既然我们已经编译和训练了模型,我们需要检查它是否是好的。首先,我们运行“model.evaluate”来测试准确性。然后,我们进行预测,并绘制出带有预测标签和真实标签的图像,以检查一切。这样,我们就可以看到我们的算法是如何工作的。稍后,我们制作一个混淆矩阵,这是一个特定的表格布局,允许可视化算法的性能。

test_loss, test_acc = model.evaluate(X_test, y_test)print('Test accuracy: {:2.2f}%'.format(test_acc*100))

6000/6000[= = = = = = = = = = = = = = = = = = = =]—39s 6 ms/步

测试准确率:99.98%

predictions = model.predict(X_test) # Make predictions towards the test sety_pred = np.argmax(predictions, axis=1) # Transform predictions into 1-D array with label number# H = Horizontal
# V = Verticalpd.DataFrame(confusion_matrix(y_test, y_pred), 
             columns=["Predicted Thumb Down", "Predicted Palm (H)", "Predicted L", "Predicted Fist (H)", "Predicted Fist (V)", "Predicted Thumbs up", "Predicted Index", "Predicted OK", "Predicted Palm (V)", "Predicted C"],
             index=["Actual Thumb Down", "Actual Palm (H)", "Actual L", "Actual Fist (H)", "Actual Fist (V)", "Actual Thumbs up", "Actual Index", "Actual OK", "Actual Palm (V)", "Actual C"])

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 3 — Confusion matrix showing the predicted outcomes and the actual image label.

结论

基于上一节中给出的结果,我们可以得出结论,我们的算法基于深度学习模型以足够的置信度(> 95%)成功地对不同的手势图像进行了分类。

我们模型的准确性直接受到我们问题的几个方面的影响。呈现的手势相当清晰,图像清晰,没有背景。此外,存在合理数量的图像,这使得我们的模型更加健壮。缺点是,对于不同的问题,我们可能需要更多的数据来将我们的模型参数推向更好的方向。此外,鉴于其抽象性,深度学习模型很难解释。然而,通过使用这种方法,开始解决实际问题变得更加容易,因为我们不必考虑特征工程。这意味着我们不需要用边缘或斑点检测器预处理图像来提取重要特征;CNN 为我们做的。此外,它可以相对容易地适应新问题,通常表现良好。

如上所述,解决该问题的另一种方法是使用特征工程,例如二值化阈值(检查手的区域)、圆检测和其他方法来检测图像上的独特特征。然而,有了 CNN 的方法,我们就不用担心这些了。

有疑问吗?欢迎在Github 资源库上发送问题/议题!

信用

T.Mantecón,C.R. del Blanco,F. Jaureguizar,N. García,“使用 Leap Motion Controller 提供的红外图像进行手势识别”,Int。糖膏剂智能视觉系统的先进概念,ACIVS 2016,意大利莱切,第 47–57 页,2016 年 10 月 24–27 日。(doi:10.1007/978–3–319–48680–2 _ 5)

适合初学者的 Tweepy

原文:https://towardsdatascience.com/tweepy-for-beginners-24baf21f2c25?source=collection_archive---------8-----------------------

使用 Twitter 的 API 建立你自己的数据集

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

建立你的投资组合的一个好方法是自然语言处理项目,但是像每个项目一样,第一步是获取数据。Twitter 可以成为文本数据的巨大资源;它有一个 API,凭证很容易获得,并且有许多 python 库可以帮助调用 Twitter 的 API。

总的来说,这些资源很棒,但它们有一些容易引起头痛的怪癖,本文将帮助您导航该过程并避免这些头痛,请将它视为您的赛前扑热息痛!

第一步:获得你的证书

**给自己注册一个账户:**Twitter 用户账户是拥有“开发者”账户的必要条件,所以要么注册一个新账户,要么登录一个现有账户。

**申请开发者账号:**前往https://developer.twitter.com申请开发者账号。如果出现提示,请选择个人或个人帐户,而不是企业帐户。当提交一个预期用途时,确保你的答案是足够描述性的,而不是一些垃圾或现成的复制粘贴语句。

创建 app:https://developer.twitter.com/en/apps注册 app。对于必填的网站字段,您可以放置一个占位符。设置完成后,转到“令牌和密钥”以生成访问令牌和密码。连同消费者 API 密钥(已经生成),这些是我们用来与 Twitter API 通信的凭证。

步骤 2:安装 Tweepy

有几个库可用于与 Twitter 的 API 交互,我更喜欢 Tweepy ,它进行可靠的调用,非常适合处理超过 140 个字符的推文。

只需将pip install tweepy写入您的终端。

您可能需要的其他几个库(取决于您想做什么)是 json、pandas、time 和 datetime。稍后我们会看到更多关于这些的内容。

第三步:快速测试运行

API 凭证,检查。Tweepy 安装完毕,检查完毕。时间来看看它是否工作,粘贴下面的代码在一个笔记本上,在你自己的键 sub(注意错别字!)然后跑。

嘣!您刚刚进行了第一次 Twitter API 调用。你现在应该会看到你的账户主页时间线上的一系列推文(你的账户关注的每个人的推文)。它看起来会像这样:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Tweepy text output

够简单了吧?不对。我们可能会看到一些数据,但在目前的格式下,这些数据不是很有用,一些推文已经被截断,我们只有来自我们已经关注的账户的数据。如果我们想要构建一个结构化的数据集来进行分析,我们必须更深入地研究 API 调用输出…戴上安全帽!

步骤 4:检查 tweets json

在一个新的单元格中键入并执行public_tweets[0]来查看与第一条 tweet 相关的 json,享受输出。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

A messy output, hard to make sense off

这不是我们处理数据的方法,试几分钟,你就会重读几行,然后马上让自己头疼。

如果你以前尝试过抓取,你可能使用过 pprint (漂亮的打印)以一种更可读的方式格式化数据。不幸的是,pretty print 在这里不能帮助我们,因为 public_tweets[0]不是一个基本的 python 数据类型,它的类型是 tweepy.models.Status,并且 pprint 模块不兼容。

我们需要使 tweepy 的输出更具可读性,这样我们就可以知道需要编写什么代码来提取我们想要的数据。我们可以这样做:

现在,您将看到一些更有条理的东西:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

A clean output, a lot easier to parse

有了这个视图,我们可以慢慢地浏览字典和列表,以确定哪些信息是可用的,以及访问这些信息需要哪些键。

步骤 5:解析出数据

如果您只是想要 tweet 上的原始数据(文本、id、用户 id),访问这些信息相对容易和可靠,正如我们已经看到的,当使用 home timeline API 调用时,我们可以使用status.text访问 tweet 的文本。

根据你项目的性质和你需要的数据,你需要选择合适的 API 调用来收集它。本文的其余部分将重点介绍如何使用 user_timeline 调用,该调用(对于一个标准帐户)可以检索一个用户的多达 3200 条最新推文(只要配置文件没有被锁定)。

这就是 Tweepy 变得有点麻烦的地方。API 调用返回的 json 结构根据 tweet 的特征而变化(想想常规 tweet、retweet 或 quote tweet)。不是提供一致的格式(如果没有信息可用,则键指向空列表),有些键只在有数据指向时才出现。

克服这一点的简单方法是满足于主要的推文信息,但是如果你关心转发和引用,那么你的数据将是不完整的。如果我们想要构建一个丰富的数据集,我们需要使用 try 和 except 语句来处理这种不一致性。

收集数据的一个好方法是构建一个可以进行 API 调用并一次性解析数据的类。它可能看起来像这样:

关于这段代码的几点说明:

  • 无论 tweet 类型如何,挖掘的字典中没有 try 语句的所有内容都是可访问的。
  • tweet_mode = 'extended'将文本索引替换为 full_text,并防止长度超过 140 个字符的主要推文被截断。不幸的是,转发仍然被截断,我们可以使用.retweeted_status.full_text访问完整的转发文本,这里我们放入一个 try 语句,因为它只在推文是真正的转发时出现。
  • 位置数据包含坐标、城市和国家,这取决于您想要什么,您需要进一步解析它,但这很容易。
  • result_limit 和 max_pages 相乘得到调用的 tweets 数。
  • 转发和引用推文包括在你的 3200 条推文中,无论你是否收集它们(关闭此设置不会获得更多主推文)。
  • 如果你在使用这个类打电话时没有提供用户名,你将会从独一无二的 wint 中抓取推文,欢迎你!

请务必花时间对照我们之前制作的结构化 json 输出版本和两个附加输出(每种 tweet 类型一个,常规、转发和引用)来查看这段代码。通过这样做,你将更好地理解数据是如何被访问的,并准备好为不同的调用创建你自己的类,或者修改这个类来收集额外的数据。

第六步:选择一个项目,确定你想要的数据

这可能是你的第一步,甚至可能是你读到这篇文章的原因。在这里你可能不需要太多帮助,但是一些建议不会有坏处。

在开始一个项目之前,找出是否有任何可用的现有资源。像每一个原始数据科学家一样,我带着分析政客的推文的意图选择了 Tweepy,通过快速的谷歌搜索,我找到了每一个拥有推特账户的英国国会议员的推特账号列表,这让我省去了很多繁重的工作。

明确你的目标,如果是学习,确保你关注其他项目,这有利于激励,获得想法,如果你陷入困境,可以帮助你指出正确的方向。如果原创是你的目标,再次,看看其他项目,你最好的想法可能是对现有项目的补充,拥抱开源哲学。

一旦你确定了你想收集谁的 tweets,就把所有的句柄收集到一个字符串列表中(不要在每个 Twitter 用户名前加上@符号)。

步骤 7:收集数据!

通过导入所需的库来启动会话:

复制该类的代码,代入您自己的 API 凭据。

实例化您的 miner,记住默认的 tweets collected 设置为 20,您可以在实例化时更改它(调用时指定的页面数量,即调用收集的 result_limit 的倍数):

现在,您已经准备好打电话,并以您可以使用的格式收集数据。要拨打电话:

现在你知道了。有了 3200 条 wint tweets 的数据框架,你离理解生命的意义就差一点点了!

最后要记住的是 API 调用是有限制的,对于一个标准用户来说,这是每 15 分钟 900 个请求。不要担心,一条 tweet 不是一个请求,但是可能很难知道你什么时候要过去。要同时拨打多个电话,请尝试以下方法:

开始在没有睡眠计时器的情况下打电话,然后如果你得到一个与你的通话限制有关的错误,就试试睡眠计时器和计数器 if 语句(每 25 次通话启动一次计时器),直到你得到对你有用的东西。

最后,注意 all_tweets 数据帧的索引对于每个句柄都是重复的。为了使它对所有的推文都是唯一的,需要重新设置索引。

就这些了!你现在已经准备好以一种可用的格式收集大量的推文了。狩猎愉快!

通过圆圈和用户交互实现 Tweets 数据可视化

原文:https://towardsdatascience.com/tweets-data-visualization-with-circles-and-user-interaction-485cad7ff248?source=collection_archive---------19-----------------------

如何利用 circles 和 Matplotlib 从一组 tweets 中创建有趣、漂亮且“可探索”的可视化

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by: https://m.yourshot.nationalgeographic.com/photos/8981395/

在这里,我们将讨论如何利用圆圈从一组推文中创建一个有趣的、美丽的、可探索的可视化。这个想法是,每个圆圈将对应一条推文,我们将组织所有的圆圈,以便它将成为数据可视化的一个有趣的静态图像。此外,可视化可以设计为我们可以通过点击静态图像上的相应圆圈来浏览推文。我们将会看到,我们实际上可以做到这一点,甚至不改变静态图像的一部分。这里讨论的实现将使用 Matplotlib 来完成。

模型

一个圆圈将被用来代表一条推文。圆圈的颜色透明度将反映该推文的转发数量(也可能是喜欢的数量,取决于你的兴趣)。颜色较深的圆圈代表转发量较高的推文。透明度高的圆圈是转发次数少的推文。在数据集中的所有推文中,肯定有一条推文的转发次数最高,这条推文将由一个没有透明度的圆圈表示。因此,只有转发量最高的推文才会是彩色的,没有透明度。数据集中的所有其他推文将会更加透明。

到目前为止,我们只为可视化添加了一个度量:转发的数量(或喜欢的数量)。但是我们可以利用圆的另一个属性,那就是大小(半径)。那么尺寸代表什么呢?有很多选择…但是让我们选一个。默认情况下,所有圆圈的半径都是 1,但如果一条推文的赞数多于转发数,那么我们会将圆圈的半径设置为 2。通过这种方式,我们的眼睛可以很容易地区分哪些推文的点赞数多于转发数。

现在我们应该如何组织圈子?我们可以只是分散图中的圆圈,但这看起来很乱,圆圈可能会相互重叠。我们可以将圆放在散点图中(x 轴和 y 轴代表两个额外的测量值),但是圆也可以相互重叠。所以,我们想要的是没有两个圆互相重叠。这需要我们自己写算法。对于我们的例子,我们将使用一种类似于圆形装箱算法的算法(一般 &具体 )。圆的位置将是随机的,但是居中,并且将尽可能地紧凑。

以下是一个样本非常少的示例(为简单起见):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Visualization with small samples (5 tweets for each account)

上图是使用小样本(5 条推文)的可视化示例,这些样本来自 Sadiq Khan(伦敦市长)、Donald Trump(美国总统)、Prabowo Subianto(印度尼西亚总统候选人)和佐科·维多多(印度尼西亚总统)的推特账户。汗和特朗普的推文收集于 2018 年 11 月 25 日,普拉博沃和佐科维的推文收集于 2018 年 11 月 22 日。我们可以很容易地看到,唐纳德·特朗普的推特比其他人有更多的反应。只有一条推文的转发量超过了点赞量,它来自萨迪克·汗。以下是两条推文的快照(一条来自特朗普,另一条来自萨迪克·汗):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

The number of retweets and likes on the image are already updated. (this image is captured on 1 Feb 2019)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

At the time of collection, the number of likes is 0 and the number of retweets is 38. The tweet was retweeted by Sadiq Khan. (this image is captured on 1 Feb 2019)

Sadiq Khan 和 Prabowo Subianto 的 5 条推文并不出名,因为圆圈的颜色非常接近白色(非常透明)。

用于可视化的数据集由 tweet 对象组成,每个 tweet 对象由类tweepy.models.Status表示(在 Tweepy 包中有更多关于这个的信息)。该类存储了许多信息,如 tweet 文本、发布时间、作者信息、转发次数、喜欢次数等。

算法和数学

在本节中,我们将讨论算法及其背后的数学原理。为了在绘图中显示一个圆,我们可以使用[matplotlib.patches.Circle](https://matplotlib.org/api/_as_gen/matplotlib.patches.Circle.html)类。我们可以创建该类的一个实例,然后我们可以通过将该圆补片(实例)添加到轴上来绘制圆。例如,下面的代码将绘制一个蓝色的圆圈:

from matplotlib.patches import Circlea_circle = Circle(xy = (0, 0), radius = 1, color = "blue") #a blue circle with center at (0,0) and radius 1fig, ax = plt.subplots()
ax.axis('square')
ax.add_patch(a_circle)fig.show()

我们也可以用另一种方式设置蓝色,使用带有透明编号的 RGB 颜色序列:

blue_color = (0, 0, 1, 1) #edit the 4th number to change the transparency 
a_circle = Circle(xy = (0, 0), radius = 1, color = blue_color)

现在,我们的数据可视化将不仅仅是绘制圆圈,还将尽可能整齐地组织它们。我们不希望两个圆互相碰撞,但是如何使用 Matplotlib 实现呢?要回答这个问题,让我们分析一下圈子的一些行为。这是两个“几乎”相互重叠的相邻圆的图像:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Two circles tangent to each other

上图是两个圆相互接触的情况。注意,我们还从图像中得到了一个小小的数学洞见: 当两个圆相互接触时,它们的半径之和等于两个圆心之间的距离 *。*这是回答撞圆问题的关键。你可以继续自己解决问题。这并不难,让我给个提示:想象另外两种情况(两个圆互相重叠,两个圆不互相接触)

到目前为止,我们应该已经知道如何绘制圆,以及如何设计图形以使两个圆不会发生碰撞。我们需要考虑的下一个概念是“*圆圈的位置分布”。*我们需要分配(或打包)所有的圆圈,这样就不会有两个圆圈碰撞,但是圆圈之间不应该有很大的间隙。这部分比较棘手,这里有一个显而易见的算法(但是比较耗时):

  1. 创建一个圆心随机的圆
  2. 然后检查该圆与所有其他绘制圆的“碰撞”状态
  3. 如果发现一个碰撞,那么用另一个随机中心改变圆心,然后从上面的步骤 2 重新开始。如果没有发现碰撞,画圆。

我们讨论的可视化不采用上述算法。它从这条 中取长补短。我们的算法看起来与我们排序的方式相似。例如,假设地板上有 10 个重叠的圆(由一张纸制成),它们都位于非常靠近点 P 的位置。为了像圆圈打包一样组织它们,我们可以滑动与另一个圆圈重叠的每个圆圈(滑动是这样的,两个圆圈互相排斥,位移很小)。经过多次重复后,所有的圆圈都将装满 P 大约在包装的中心。这个算法看起来更生动,它使上面明显的“3 步”算法看起来非常僵硬。

此外,为了使我们的数据可视化更有趣,我们可以添加交互式元素。可视化可以设计成这样,我们有两个图形,一个用于圆圈(主要数据 viz),另一个显示关于一条 tweet 的更详细的信息(文本)。更具体地说:如果我们点击一个圆圈,那么关于相应推文的一些信息(文本、转发次数、喜欢次数和发布日期)将出现在第二张图中。这可以通过使用 Matplotlib 的特性[fig.canvas.mpl_connect](https://matplotlib.org/users/event_handling.html)函数来完成。

增加互动性:点击发布信息

在绘制和打包所有的圆后,我们可以让每个圆像一个按钮一样工作。为了实现这一点,我们可以包含来自函数fig.canvas.mpl_connect.的帮助。该函数可以接受两个参数,第一个参数是对应于交互类型的字符串(在我们的例子中,它必须是"button_press_event"),第二个参数是当该类型的事件被触发时将被调用的函数。示例:

fig.canvas.mpl_connect('button_press_event', on_click)

上面的代码行将为图形fig添加交互性,但仅限于按钮按下事件(如果您想要另一种类型的交互:对于图形上的鼠标移动,使用"motion_notify_event")。第二个参数中的函数必须设计成有一个名为event.的输入。在我们的例子中,我们将把函数命名为on_click.

现在,我们必须设计函数on_click,使我们每次在主图中选择并点击一个圆,另一个图就会显示该圆对应的 tweet 的一些细节。信息的呈现必须设计得简洁。以下是当前用于可视化的一个示例:

### fig2 is the figure for the tweet informationfig2, ax2 = plt.subplots()ax2.set_xlim([0, 50])
ax2.set_ylim([0, 50])
ax2.tick_params(colors = (0,0,0,0))def on_click(event):
    ax2.cla()
    x = event.xdata
    y = event.ydata
    print(x,y)
    for i in scattered:
       if abs(x-i.center[0]) <= i.radius:
           if lower_circle(x, i.radius, i.center) <= y <= upper_circle(x, i.radius, i.center):
               try:
                   text = i.tweet.full_text
               except:
                   text = i.tweet.text

               ax2.text(25, 35, i.tweet.created_at, fontproperties = helv, \
                        ha = 'center', va = 'center', color = 'black')
               ax2.text(25, 33, squeeze_text(text), fontproperties = helv, \
                        color = "white", ha = 'center', va = 'top', \
                        bbox = {'boxstyle': 'round', 'ec': "black", 'fc': "gray"}) ax2.text(25, 17, i.tweet.author.name + " (@{})".format(i.tweet.author.screen_name), \
                        fontproperties = helv, ha = 'center', va = 'center', color = "black") ax2.text(25, 15, "Retweet: {}, Likes: {}".format(i.tweet.retweet_count, i.tweet.favorite_count), \
                        fontproperties = helv, ha = 'center', va = 'center', color = "black") fig2.show()
               break
    print("done")fig.canvas.mpl_connect('button_press_event', on_click)

scattered是包含许多CircleObj 对象的列表。CircleObj是用户定义的类,继承自 Matplotlib 的Circle类。这是设计的一瞥:

class CircleObj(Circle):

    def __init__(self, tweet, value, label, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.value = value
        self.label = label
        self.tweet = tweet def collide(self, circles):
        colliding = []
        [colliding.append(i) for i in circles if (dist(self.center, i.center) < self.radius + i.radius)]
        return colliding

    #other methods

代码有circles,它是一个全局变量,是所有CircleObj对象的列表,它们的顺序在scattered列表中被随机化。self.tweet属性由tweepy.models.Status.用于 tweet 对象,collide方法旨在返回所有与self冲突的CircleObj对象。这里没有给出用上一节描述的算法分发和打包圆的完整代码。但是很明显…它包含一个代码块,该代码块反复更新圆的位置,直到它们都没有重叠。

当条件:abs(x-i.center[0]) <= i.radiuslower_circle(x, i.radius, i.center) <= y <= upper_circle(x, i.radius, i.center)都为真时,tweet 信息将以文本形式绘制。lower_circleupper_circle是圆方程的函数(给定x,它们将返回圆曲线上的点的 y 值(【T5,y】)。

当我们在图上的任何地方按下鼠标按钮时,总是会触发on_click功能,但是当我们在绘制的圆圈内单击时,它只会绘制 tweet 信息。以下是绘制信息的示例:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注意,该字体不是 Matplotlib 中的默认字体。您可以通过实现matplotlib.font_manager.来了解如何在 Matplotlib 中使用新字体。另外,请注意,还有另一个用户定义的函数来修饰圆形边界框内的 tweet 文本,即squeeze_text。它使文本每行最多 7 个单词,最多 8 行/行。

大型数据集的结果

使用 400 条 tweets 的实现通常需要大约 400-500 次检查所有圆圈的迭代,一次迭代通常需要半秒钟。如果 tweets 的数量更大,那么完成一次迭代所需的时间会更长。在第一次迭代时:所有的圆都非常接近原点,点(0,0),与它的最大偏差为 0.01 半径。然后,对于之后的每一次迭代,我们通过应用排斥运动,对每两个重叠的圆中的每一个进行非常小的扫动,两个圆相互推开,而不必在一个步骤中使它们成为非重叠的圆。在本节中,我们将查看数据可视化的两个示例结果:

  • 第一个例子是使用 1000 条推文的数据集。500 条推文来自印尼 CNN,另外 500 条来自 Metro TV。两者均于 2018 年 11 月 21 日采集。结果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

500 tweets from CNN Indonesia and 500 tweets from Metro TV. There are two green circles with quite strong color.

从这个结果我们可以得出一些结论:

—与所有其他推文相比,印度尼西亚 CNN 的 2 条推文(2 个绿色圆圈)的转发量非常高。似乎没有任何来自地铁电视台的推文像这些推文一样受欢迎。

——我们不能说有更多转发>喜欢的推文,或者其他

虽然从静态图像中没有太多的见解,但我们可以通过简单地点击圆圈来清楚地进行探索。而且可视化也挺好看的。

好吧,我们的第一次数据分析并不令人满意。接下来,如果我们使用包含 4 个不同账户的数据集,事情会变得更有趣。

  • 第二个例子是使用来自四位政治家的 400 条推文的数据集:萨迪克汗先生、川普先生、普拉博沃先生和佐科·维多多先生(各 100 条推文)。萨迪克先生和特朗普先生的推文是在 2018 年 11 月 25 日收集的,而普拉博沃先生和佐科维先生的推文是在 2018 年 11 月 22 日收集的。对于第二个示例,我们还将看到一个展示用户交互的视频:

除了视频,这里是静态图像(*与视频中的略有不同:两者提供相同的信息,但由于不同的计算,它们在定位上有所不同)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

400 tweets from 4 politicians. Trump’s tweets appear to be more popular than all the others, with quite a large gap.

我不会写一些关于上述可视化的结论,但有一点很清楚,与其他 3 位政治家相比,特朗普的推文非常受欢迎。此外,突出的推文通常是有争议的,这里有一些例子:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结束语

我们已经看到,像圆形这样简单的形状可以用来在数据可视化中表示推文。我们还可以使可视化具有交互性(尽管仍然非常简单)。使用 Matplotlib 实现并不困难。

这种可视化方法可以扩展:

  • 可视化也可以用图形来建模:圆或 tweets 可以用顶点来表示,圆的邻接可以用边来表示。邻接也可以被设计成具有意义(当前的邻接不使用邻接来给出信息)。此外,圆的位置可以表示一个或多个测量值。没有意义的留下一个圈位置是一种浪费。
  • 一个简单的扩展:我们可以将喜欢的数量附加到圆的半径上,从而将喜欢的数量包含到可视化中。请注意,我们不需要确切的数字来显示在主视图中,因为我们只需单击一个圆圈,然后 tweet 信息就会出现在另一个图中。以下是一个示例结果(使用每个账户的 50 条推文):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Visualization that includes the number of likes (represented by the size of the circle)

这个文笔离专家级还很远。有更多类型的复杂数据和数学可视化可以提供更多的见解和更多的应用。我欣赏建设性的意见。

*(完整代码预计将在 Github 上提供)

扭转图——来自推特行为的数据可视化(Art)

原文:https://towardsdatascience.com/twiring-diagrams-data-visualization-art-from-tweeting-behaviour-38601aa2b2c6?source=collection_archive---------20-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

https://twiring.appspot.com/

twining来自 Twitter+Wiring——因为这些图看起来像“接线”图。而且,扭动是为了 害羞或狡猾地瞥一眼 这正是这种可视化形式的功能。

灵感

我的灵感来自于吉姆·瓦兰丁汉姆的句子图画(最初灵感来自于斯蒂芬妮·波萨维克的句子图画艺术),我想为用户的推特行为做一个类似的可视化。我的一些旧项目着眼于生成 Twitter 自我网络,然后通过算法从推文中提取和描述主题,所以这有点像混搭。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Posavec’s original Sentence Drawings

波萨维克的画句子的概念相当简单:你画一条相对相当于句子长度(字数)的线,右转,画一条对应下一句话的线,以此类推。这导致视觉在遇到连续的短句时变得拥挤,在出现长句时变得开阔。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Posavec’s original Legend and Basic Structure

扭曲

Twiring 采用上述句子绘图的基本结构,将句子替换为来自用户的 tweet 并执行概念上的扭曲:一行的长度代表自上次 tweet 以来的时间差,而不是 tweet 的字数。句子绘制的空间性成为一种可视化用户推特行为时间维度的方式。除了这个主开关之外,我还添加了一些其他可视化代码,以便在绘图上添加更多信息。

我还在绘图的背景中添加了一些圆圈,以表明一条推文的受欢迎程度。

此外,我还加入了搜索功能(基本的字符串匹配)来过滤图片上的线条/推文——我认为这很酷,因为你可以看到哪些术语何时出现,并缩小特定术语周围的推文行为。

可视化摘要

  • 每条线都是一条推文
  • 基本结构:在每条线的末端,你做一个右转然后开始画下一条线
  • 在内有+的黑框是最早的推文,空的黑框是最近的推文
  • 一行的长度是相对于从用户最后一次发推起有多长时间了
  • 每行的颜色是推文被分组的主题
  • 每一行的粗细与其主题有多密切的关系
  • 点击任何一个图例项将会切换它们在图上的可见性
  • 搜索栏(键入并按回车键)也可以用于过滤,基于你的输入与 tweet 中的文本的非常基本的比较
  • 回复和不回复按钮可以分别切换推文。(注意:回复自己不被视为“回复”)
  • 在每条线的开头画出了圆圈,表示基于 RTs 和喜欢的 tweet 的受欢迎程度(相对而言)
  • 将鼠标悬停在一行上会显示该推文的更多细节
  • 可以使用右边的工具栏平移、缩放和保存该图

笔记

我将它作为一个 web 应用程序托管,供您使用和播放——请注意,主题建模和收集推文可能需要一些时间(0-3 分钟)。

主题建模有一些随机性,因此刷新将重新计算它们,您将丢失当前配置。

我最多只分析了 1000 条最近的推文。

我还会过滤掉少于 50 个字符的 RTs/赞或推文。

出于可伸缩性/速度的原因,主题建模本身是简单的、轻量级的和未经过滤的(不使用词性标注或 NLP 来预处理文本)。

我不存储任何人的推文,我只要求 twitter 认证的只读权限。

链接:https://twiring.appspot.com/

示例用法

  • 直观感受你在发推之间休息了多长时间
  • 搜索一个特定的术语,看看它是如何/何时出现在你的历史中的
  • 以同样的方式分析其他用户的推文
  • 立即看到热门推文脱颖而出,并找出任何模式
  • 等等等等

Twitter——或者我的机器人和你的机器人说话的地方

原文:https://towardsdatascience.com/twitter-3478a68d5875?source=collection_archive---------16-----------------------

PYTHON DIY 终极指南——构建 TWITTER 机器人

阅读我如何用 Python 构建了一个 Twitter 机器人来运行一个有问题的实验。包括所有代码和详细的解释。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image by Jonny Lindner from Pixabay

摘要

在这个故事中,我将详细解释我如何构建一个 Twitter 机器人,它利用人类的一些基本情感来产生追随者。这种事每天都发生在我们所有人身上。我认为说明它是多么容易是至关重要的。我将分享一些有趣的经历,并在 Twitter 上展示 bot 感染的证据。

文章的后半部分深入描述了机器人的代码和功能。当前的生产代码可在 Github 上获得。我在 AWS 上运行 bot,并通过无服务器框架部署它。它甚至没有使用每月 AWS 免费层的 5%。所以试试吧。

如果这篇文章会让我的推特账户被封禁,我不会感到惊讶。但是嘿,尤洛!

动机

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Patrick Fore on Unsplash

大约六周前,我开始在媒体上写作。我想写一些文章,帮助人们接触 Python,并且,总的来说,拓宽他们的技能。原因是我的一些团队成员想学习 Python,我想这可能会有协同作用。当我开始时,我对自己说,我会这样做两个月,看看会有什么结果。如果出现最坏的情况,我会有一些结构良好的文章,可以用来教 Python。我确信,几乎每个人都可以从了解 Python 中受益。

我写了第一篇关于群体的文章。我没有研究人们是否关心这个话题。坦白说,我不在乎。我不知道如何恰当地编排媒体文章的格式,甚至不知道你最初可以包含图片。我只是想开始,这是我最近做了一些工作的一个主题。

观众人数少得可笑,大约每天只有 30 次浏览。然后这篇文章出现在专栏数据科学编程中,不久之后,出版物更好的编程发布了它。观众人数直线上升。至少按照我当时的标准。

当你从未见过建筑时,即使是一层楼的房子看起来也像一座大房子

我每天被浏览 150 次。感觉很好。那一刻,我设定了一个雄心勃勃的目标。我想写一篇在 30 天内有 100,000 浏览量的文章。实际上是一个任意的数字,但是明确和雄心勃勃的目标有助于不失去焦点。我对自己说,我每周至少要发表一篇文章。我在晚上写作,晚上 9 点到 11 点,周末也写作。有时候很有挑战性,但是我一直坚持。

第二篇文章在观看人数方面要好得多。 走向数据科学 发现了这个故事,因为我热爱这个出版物,所以我毫不犹豫地在那里发表。也许这个话题更贴切一点。谁知道呢。没关系。我正朝着正确的方向前进。

推特

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Nicholas Green on Unsplash

介绍 Twitter!我的第三篇文章是第二篇文章的后续。它包括了某种程度上先进的可视化。我在一个星期五的晚上发表了它,我知道它并不完美,但我没有时间早点完成它。毕竟,我必须达到我的目标。然后奇怪的事情发生了。我的观众人数爆炸了。仅在周日,这篇文章就获得了 4000 次浏览。我大吃一惊。我必须了解这一点,所以我开始寻找潜在的原因。经过一番挖掘,我发现了这个:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Kirk Borne had tweeted a link to my third article

我没有想到 Twitter 是一个合适的媒体作品分销渠道,但不可否认它的影响。我想,如果柯克能做到这一点,我当然也能做到。因此,我重新启用了自己创建的账户,关注唐纳德·特朗普(Donald Trump),偶尔开怀大笑。只有一个问题,这个账号有精确的零关注者。

我开始在推特上发帖,喜欢推文,转发,关注人。天啊,这太累了。我很快意识到,Twitter 就像一个疯狂的集市,每个人都通过扩音器以疯狂的频率不断脱口而出他们的想法和观点。我从事营销工作,对 Twitter 上的推荐活跃度做了一些研究,这简直太疯狂了。一些消息来源暗示每天多达 20 个帖子,其他人甚至更多。我没数过,但我想柯克大概是每天 200 个左右。

这样手动做了一天左右,我烦得要命。我决定我需要一种不同的方法。事实上,我的追随者增加了一个,这无助于我的动力。

十二岁

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Safar Safarov on Unsplash

我在 Twitter 上的活动是令人麻木的重复。从柯克的所作所为来看,他也不像是在阅读他发布的所有内容。每当一件事被反复做的时候,它通常是自动化的首选。我找到了用于访问 Twitter API 的 Python 库 tweepy 。文档看起来很干净,代码维护得很好。我想试试这个。

资格证书

设置身份验证和获取凭证非常简单:

  1. 前往 Twitter 开发者页面
  2. 使用您的 Twitter 帐户登录
  3. 创建一个应用程序并获取凭证(在密钥和令牌下,见红色圆圈)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Steps to create a Twitter app

机器人的结构

我在 Jupyter 笔记本上用一个简单的 API 调用测试了凭证,一切看起来都很好。现在是时候让它更上一层楼了。我的机器人应该做两件事:

  • 产生追随者
  • 广告媒体文章

产生追随者

从几年前的一次 Instagram 机器人实验中,我知道了实现我第一个目标的确切方法。这相对来说是不道德的,因为它迎合了人们渴望被喜欢和被认可的心理。这是最假的了。不过话说回来,这是 Twitter。另外,我认为有必要谈谈这些做法。展示它们是如何工作的至关重要。关键是要表明它们每天都在以更大的规模被使用。

工作方式—给予员工认可和关注:

  1. 与用户互动(点赞、转发、评论他们的推文并关注他们)
  2. 等待和观察
  3. 看着他们跟着你回来
  4. 再等一段时间,然后放开他们

所以抛开所有的道德因素,让我们把这个编码起来。

①与用户互动

在我的项目中,我倾向于使用配置模块作为配置设置的抽象层。

bots.config

配置如下所示:

production.yml

然后,我们可以设置一个模块来提供 Twitter API,如下所示:

bots.twitter_api

下面这段代码包含交互逻辑。

bot.fetchfollow

我们从两个全大写的变量开始,COMMENTSHASHTAG_SETS这两个变量稍后会被引用,给定内容和名称,用法是相当明显的。COMMENTS列表保存了一些通用的正面评论,HASHTAG_SETS保存了一个用于搜索的不同标签组合的列表。

主要功能是fetchfollow,它执行以下操作:

  • 使用从HASHTAG_SETS设置的随机标签来搜索推文。
  • 获得这些推文背后的独特用户。根据关注者的数量(越少越好)、关注者与关注者的比率(越低越好)和帐户的年龄(越新越好)对用户进行评分,并根据分数对他们进行排序,最高(即最有可能再次关注)在前,最低在后。
  • 从 s3 中获取following_history,该文件包含用户被关注的日期(以及后来被取消关注的日期)。
  • 从最高分到最低分与不在following_history中的用户互动(每次最多 10 分,我们毕竟不想触发机器人警报)。互动意味着给包含我们标签的用户推文打分,然后随机点赞、评论和转发
  • 将用户添加到following_history并更新到 s3。毕竟,我们不想再跟着他们了。

②等待观察

这个阶段比较搞笑。这个阶段是你把你的机器人放到野外并观察结果的时候。有时带着娱乐,有时带着困惑。当我试验 Instagram 机器人的时候,我很快发现 Instagram 上有相当多的色情内容。但那是以后的事了。

在部署了第一个版本的 Twitter 机器人之后,我学到了三件事:

我不得不调整我搜索推文的方式,因为我最初只搜索 Python。

Snakes are scary

我不得不调整机器人运行的频率,使其行为不那么确定。这个机器人的第一个版本很快就被屏蔽了,因为我像喝了一杯能量饮料后冰河时代的松鼠一样被机枪评论和传播。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

The first app got restricted to read access only after having commented a little too much

然而,这一次创建一个新的应用程序并采取更加谨慎的方法是相当容易的。

ⓒ:推特上有很多机器人。我得到了回应,“嘿,谢谢你关注我。检查我正在使用的这个伟大的服务: https://xxxbots。 xx”相当经常。向他们致敬。他们运用了一种聪明的病毒式营销方法。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Bots responding to my bot and the list goes on

③看着他们跟着你回来

在过去的四周里,我的 Twitter 账户已经积累了大约 600 名粉丝,除了偶尔在中型帖子列表中添加一个新条目之外,我什么也没做。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

④等待一段时间,然后放开他们

因为你不想让你关注的人数过多,所以你必须时不时地取消关注以保持平衡。

bots.unfollow

unfollow 函数在执行时,获取之前上传的following_history,并按照日期升序对所有未被取消关注的进行排序。对于第一个一到三个用户,它将调用destroy_friendship(调用 unfollow)。如果你问我,我觉得这个名字很合适。它将更新following_history,然后准备好被再次调用。

广告媒体文章

这一部分是直截了当的,它的道德性肯定没有那么多问题。

bots.post

这个脚本从参考列表中随机发布了一篇文章。参考列表如下所示:

Sample posts

部署

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by elCarito on Unsplash

我使用无服务器框架,利用 Lambda 函数和预定义的时间表(在 serverless.yml 中指定)将机器人部署到 AWS

serverless.yml

安装非常简单,但是解释无服务器将是另一篇文章。更新机器人需要我对脚本做一些修改,然后运行serverless deploy

结束语

我会让这个机器人多运行一段时间,这样阅读这篇文章的人就可以有一个实时参考。不过,我最终会关闭它。

如果你想聊天,请在 LinkedIn 上连接!我很乐意和你谈谈,或者回答你可能有的任何问题。

看看我在 Medium 上写的其他文章,如果你喜欢这篇文章,请留下一两个掌声。

面向数据科学家的 Twitter 机器人

原文:https://towardsdatascience.com/twitter-bot-for-data-scientists-8f4242c4d876?source=collection_archive---------12-----------------------

有没有想过如何创建你的@Getvideobot @threadreaderapp 之类的东西

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by AbsolutVision on Unsplash

Twitter 是使用最广泛的社交平台之一。它被个人和组织使用。对于那些其信息(数据)驱动其生活和工作的人来说,它是一个巨大的信息库。

twitter API 的存在为平台上共享和提供的信息提供了无限的创造性访问,因此,不同的 twitter bot 被创建用于不同的目的,它帮助 twitter 成为一个更好的平台。

这些机器人的使用不仅仅使 twitter 平台变得有趣,它还可以作为数据科学家众包数据的一种手段。

在本文中,我们将学习如何为您的数据科学项目创建不同的 twitter bot 来众包数据,例如如何:

  1. 通过监控特定关键字下载图像和视频。
  2. 通过在推文中引用来下载媒体数据。
  3. 收集被监控用户的推文。
  4. 将 twitter 线程展开到文本文件中。
  5. 在 aws s3 中存储数据集合。

这些不同的过程可以帮助众包数据,不仅用于 NLP,还用于计算机视觉(因为大多数人认为 twitter 最适合收集自然语言处理的数据)。

在本文中,我将假设您拥有 Twitter API 认证证书,并且知道如何使用 Tweepy。如果没有,请查看下面的参考资料,了解如何获得 twitter API 证书以及如何安装 tweepy,并获得一些关于它的介绍。但是我建议您先阅读这篇文章,只是为了获得应用程序视图,然后再回到参考资料。

如果您有 twitter API 凭证,那么要做的第一件事就是创建一个配置文件,用 twitter API 设置您的身份验证。

调用该函数有助于检查身份验证是否有效。您可以直接用 api 密钥替换os.getenv(),或者将 api 密钥存储在您的environment中。wait_on_rate_limitwait_on_rate_limit_notify帮助 tweepy 等待,并在超过速率限制时打印出一条消息。

通过监控特定关键字下载媒体数据

数据收集是每个数据驱动项目的基础。收集的数据类型取决于正在进行的项目类型。例如,对于一个计算机视觉项目,它需要图像或视频。Twitter 可以作为一个平台,以不同的方式收集这些数据。其中一种方法是监控与项目所需数据类型相关的一组特定关键字。

比方说,你想策划或收集涉及特朗普的数据,可以创建一个 twitter 机器人来始终收听提到特朗普的每条推文。

监控机器人是使用 tweepy 接口的 Twitter Stream service api 创建的。这有助于机器人在 Twitter 平台上持续收听不同的推文。Monitor 类继承自tweepy.StreamListener,它包含两个方法;on_status这有助于传入推文,并对传入的推文做我们想做的任何事情,并且on_error提供了可操作点,以防在on_status过程中遇到错误。

on_status传入的 tweet 包含了每条 tweet 的 JSON 属性。因为在这个例子中我们需要媒体数据。tweet 的 json 元素包含将被称为entities的内容,实体包含媒体文件和 tweet 中嵌入的 url。例如

{u'hashtags': [{u'indices': [0, 12], u'text': u'NeurIPS2019'}],
 u'media': [{u'display_url': u'pic.twitter.com/GjpvEte86u',
   u'expanded_url': u'https://twitter.com/doomie/status/1206025007261876226/photo/1',
   u'features': {u'large': {u'faces': []},
    u'medium': {u'faces': []},
    u'orig': {u'faces': []},
    u'small': {u'faces': []}},
   u'id': 1206024997262618626,
   u'id_str': u'1206024997262618626',
   u'indices': [278, 301],
   u'media_url': u'http://pbs.twimg.com/media/ELypWGAUcAIpNTu.jpg',
   u'media_url_https': u'https://pbs.twimg.com/media/ELypWGAUcAIpNTu.jpg',
   u'sizes': {u'large': {u'h': 1536, u'resize': u'fit', u'w': 2048},
    u'medium': {u'h': 900, u'resize': u'fit', u'w': 1200},
    u'small': {u'h': 510, u'resize': u'fit', u'w': 680},
    u'thumb': {u'h': 150, u'resize': u'crop', u'w': 150}},
   u'type': u'photo',
   u'url': u'https://t.co/GjpvEte86u'}],
 u'symbols': [],
 u'urls': [],
 u'user_mentions': []}

tweet.entities包含该键和值项。因为我们需要媒体文件。对于图像文件,media_url将用于下载 tweet 中的图像。对于推文中上传的视频,将使用expanded_url下载;对于通过 url 嵌入的视频,如 youtube 视频。将从urls中提取,但是在这个 tweet 中,它不包含 URL,这就是为什么数组是空的。但是对于包含 url 的 tweet

{ ....
  u'urls': [{...,u'expanded_url':'youtube.com?...}]

因此,在urls[0]['expanded_url']中通过解析下载视频。

已经创建了各种 python 库或模块来简化图像和视频的下载。为了下载图像,使用了一个名为 wget 的 python 包。对于 youtube 视频下载,使用 pytube ,对于 twitter 视频,使用 twitter_dl 。所有这些库都是很棒的库,它们使得构建这个项目更加容易。但是对于 twitter-dl 和 pytube,由于我遇到的错误,我对它们做了一些修改,但是我认为新的更新应该可以解决这个问题。所以如果你遇到任何错误,你可以检查我的 github 下载它们。

为了下载这些媒体文件,我们将这些库合并成一个文件

现在我们可以将它与 Monitor.py 结合起来,开始下载媒体文件

当被推文引用时下载媒体文件

有时,我们可以让其他人在 twitter 上帮助我们众包数据,而不是试图监控一个特定的关键词。这种方法包括让人们在包含你想要的数据的推特下引用你的推特名字。这一过程与监控过程类似,只是我们不会使用流式 api,并且它不会监听所有推文,除了您在中提到的那条推文。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

refrenced to a tweet.

提及功能利用api.mention,获取你被提及的所有 tweet。为了防止api.Cursor获取你被提到的所有推文,从你加入 twitter 开始,我们使用since_id。以确保它不断获取你被提到的新推文。首先,我们得到你最后一次提到的 tweet 的 id。

tweety = []
for tweet in tweepy.Cursor(api.mentions_timeline).items():
    if len(tweety) > 1:
        break
    else:
        tweety.append(tweet)

因为推文是基于新创建的推文获取的。我们只需要这个,然后我们索引tweety来获得 tweet 的 id。

tweety[0].idoutput[]:
1208298926627074049

在上述代码面板的mention()中,我们使用了max(tweet.id,new_since_id) ,因为对于每个新的 tweet,id 总是大于它之前的 tweet id。也就是说,新的推文 id 高于旧的推文 id。

不要忘记,收集的tweet不仅仅是文本,还有 json 元素,包含 tweet 属性。对于这个机器人,你会通过评论区被引用到一条推文。你想要的主要内容在用户通过评论引用你的推文中。所以用户在回复一条推文。

在 tweet json 元素中,可以提取用户回复的 tweet 的 id。我们把这个 id 叫做in_reply_to_status_id。当用户没有回复推文时,id 通常是None。为了创建 bot,我们首先检查回复状态 id 是否不是 None,然后我们处理 tweet。然后我们从状态 id 中获取 tweet,使用

status_id = tweet.in_reply_to_status_id                                   tweet_u = api.get_status(status_id,tweet_mode='extended')

然后,您现在可以打印出推文中包含的文本。

在这个基本过程之后,如果需要媒体文件,剩下的过程类似于 Monitor bot 的过程。对于上面的代码,我们可以将文本存储在数据库中。创建另一个名为 popular know hasUnrollthread的机器人仍然需要这样一个过程,这将在本文结束之前讨论。

下载媒体数据

收集被监控用户的推文

可以创建一个 Twitter bot 来始终跟踪来自特定用户集的 twitter feeds,这可以帮助管理数据以创建基于特定数据的语言模型,并用于各种 NLP 数据分析。回顾一下最初创建的特定于 Monitor 的关键字 bot,但是在这个过程中,我们使用用户 id 来订阅用户,而不是订阅关键字。

在代码中,我指定了用户 id,这个用户 id 可以通过;例如

api.get_user("[@_mytwtbot](http://twitter.com/_mytwtbot)").id #specify the user screen name you want//1138739106031308800

因此,你将总是第一个获得这个用户创建的推文。

将 Twitter 线程展开成文本文件

你在 twitter 上听说过展开的线程机器人,它总是创建一个 pdf 格式的线程。我们将创造这样的机会。这也有助于为您的数据科学项目收集数据。这个过程仍然与提及机器人相同。它利用回复状态 id,并使用一个recursive函数来获取一个线程中的所有 tweets。

存储 AWS s3 中收集的数据

既然我们已经有了不同的方法来收集数据,我们需要能够存储它们。如果您没有在线存储服务,Aws s3 提供了一种快速简便的在线存储媒体文件的方法。

首先,安装 aws sdk,它是通过 python 库 boto3 提供的

pip install boto3

然后,为了让 boto3 工作并连接到您的 aws 资源,您需要通过创建一个iam用户权限来获得 aws 凭证,然后可以将凭证存储在您的计算机主目录中

touch ~/.aws/credentials

然后在凭证中,我们存储必要的信息

[default]
aws_access_key_id = YOUR_ACCESS_KEY_ID
aws_secret_access_key = YOUR_SECRET_ACCESS_KEY

现在获取访问密钥;

首先,访问 aws 控制台并进入 iam 资源

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Step by step process of creating iam on aws.

按照图片从左到右的排列顺序在 aws 上设置 iam。完成后,你可以下载如上图所示的 csv 文件,复制其中的凭证并粘贴到~/.aws/credentials

完成后,我们继续在 aws S3 创建一个存储桶。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

点击create bucket创建一个存储桶来存储您的文件。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

然后指定名称,你想要的地区,然后点击create,这样你的桶就创建好了。

既然创建了 bucket,我们就可以使用 boto3 调用它:

import boto3s3 = boto3.client("s3")
s3.upload_file(path,"bucket_name","name_to_store_file")

这是我们将用来在 s3 上存储文件的基本函数。upload_file 方法接受要上传的文件的路径,例如*/home/documents/bot/video . MP4*,而bucket_name是您创建的 bucket 的名称,那么第三个参数是您想要在 s3 上存储文件的名称。

因此,只要对我们的download_t.py稍加修改,我们就可以将文件保存在 aws s3 上

文件上传后,可以通过点击存储桶进行查看

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

aws s3 scrrenshot.

现在一切都设置好了,我们现在可以创建 docker 映像,然后部署到 aws。查看下面的参考资料,了解如何部署到 aws。

但是,在您从 reference 链接中学习了如何部署到 aws 之后,只需添加一点东西,即 aws 凭证和环境变量

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

from realpython.com

此外,为了能够将媒体文件保存到 aws s3

-e aws_access_key_id="sjbkjgkjhfyfyjfyjyfj" \
-e aws_secret_access_key="1124knlkhk45nklhl" \
fav-retweet-bot

现在,作为一名数据科学家,我们已经学会了从 twitter 上收集数据并创建一个机器人的方法。看看这个,了解如何使用深度学习创建 twitter 机器人。

github 下载包含代码的回购协议

参考

这篇文章很大程度上依赖于来自 realpython.com的某个团队的工作查看这里学习如何生成 twitter api 以及如何部署到 aws。

使用 Python 的 Twitter 数据收集教程

原文:https://towardsdatascience.com/twitter-data-collection-tutorial-using-python-3267d7cfa93e?source=collection_archive---------0-----------------------

“没有数据,你只是另一个有观点的人”——w·爱德华兹·戴明

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Carlos Muza on Unsplash

在过去的一年里,我在 Twitter 上变得更加活跃,随着互动次数的增加,我需要回答一些基本问题,比如:

  • 我的追随者来自哪里?
  • 我的推文平均有多少赞?
  • 我关注的客户分布情况如何?

所以我认为这可能是一个有趣的编程练习。但是在我进行任何分析之前,我们需要收集所需的数据。

在本教程中,我们将学习如何使用 Twitter 的 API 和一些 Python 库来收集 Twitter 数据。我们将介绍如何设置开发环境、连接 Twitter 的 API 以及收集数据。

对于“只给我看代码”的人来说,这是笔记本:

[## 谷歌联合实验室

编辑描述

colab.research.google.com](https://colab.research.google.com/drive/1cwefy0vNKHjW_XUZeyvKvc0U-no3gKGt#scrollTo=EaGv0ePkydNz)

工具和 Python 库

这是我们将使用的工具清单

  • 用于开发环境的 Google Colab
  • Google Drive 存储数据

它们是免费的,只需一个基本的谷歌账户,将有助于让事情变得简单。

至于 Python 库,下面是我们需要的

  • tweepy 用于使用 Python 访问 Twitter API。
  • google.colab 将 Google Drive 链接到 colab 笔记本
  • json 用于加载和保存json文件
  • csv 用于加载和保存csv文件
  • 日期时间用于处理日期数据
  • 时间为定时代码执行

我们将导入我们需要的所有库,如下所示

**# Import all needed libraries**import tweepy                   **# Python wrapper around Twitter API**
from google.colab import drive  **# to mount Drive to Colab notebook**
import json
import csv
from datetime import date
from datetime import datetime
import time

将 Google Drive 连接到 Colab

要将 Google Drive *(存储数据的地方)连接到 Colab 笔记本(处理数据的地方)*运行以下命令。

**# Connect Google Drive to Colab** drive.mount('/content/gdrive')**# Create a variable to store the data path on your drive** path = './gdrive/My Drive/path/to/data'

执行上面的代码块将提示您跟随一个 URL 来验证您的帐户,并允许 Google Drive 和 Colab 之间的数据流。只需点击提示,当硬盘安装成功时,您将在笔记本中收到一条消息。

向 Twitter 的 API 认证

首先,申请一个开发者账号访问 API。对于本教程来说,标准 API 已经足够了。它们是免费的,但是有一些限制,我们将在本教程中学习如何解决。

设置好您的开发者账户后,点击右上角的用户名打开下拉菜单,然后点击*“应用”,创建一个将使用 API 的应用,如下所示。然后选择“创建应用”*,并填写表格。出于本教程的目的,使用 Google Colab 笔记本的 URL 作为应用程序的 URL。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Select “Apps” from the top right corner once you log into your developer account

现在您已经创建了一个开发人员帐户和一个应用程序,您应该有一组连接到 Twitter API 的密钥。具体来说,你会有一个

  • API 密钥
  • API 密钥
  • 访问令牌
  • 访问令牌秘密

这些可以直接插入到您的代码中,或者从外部文件加载以连接到 Twitter API,如下所示。

**# Load Twitter API secrets from an external JSON file** secrets = json.loads(open(path + 'secrets.json').read())
api_key = secrets['api_key']
api_secret_key = secrets['api_secret_key']
access_token = secrets['access_token']
access_token_secret = secrets['access_token_secret']**# Connect to Twitter API using the secrets** auth = tweepy.OAuthHandler(api_key, api_secret_key)
auth.set_access_token(access_token, access_token_secret)
api = tweepy.API(auth)

Twitter 数据收集

概观

我们将创建函数来收集

  • Tweets: 这也包括转发,以及作为 Tweet 对象收集的回复。
  • **关注者:**作为用户对象收集的所有关注者信息。
  • **关注:*我关注的所有账户的信息(又名好友)*收集为用户对象
  • **今日统计:**当日跟随者及跟随者统计。

此外,我们将创建两个助手函数来简化我们的工作

  • 保存 JSON: 将收集到的数据保存在 Google Drive 上的json文件中
  • **速率限制处理:**管理免费版本附带的 Twitter API 限制,主要是 15 分钟内允许的 API 调用数量。

助手功能

保存 JSON

**# Helper function to save data into a JSON file
# file_name: the file name of the data on Google Drive
# file_content: the data you want to save**def save_json(file_name, file_content):
  with open(path + file_name, 'w', encoding='utf-8') as f:
    json.dump(file_content, f, ensure_ascii=False, indent=4)

费率限额处理

**# Helper function to handle twitter API rate limit**def limit_handled(cursor, list_name):
  while True:
    try:
      yield cursor.next() **# Catch Twitter API rate limit exception and wait for 15 minutes**
    except tweepy.RateLimitError:
      print("\nData points in list = {}".format(len(list_name))))
      print('Hit Twitter API rate limit.')
      for i in range(3, 0, -1):
        print("Wait for {} mins.".format(i * 5))
        time.sleep(5 * 60) **# Catch any other Twitter API exceptions**
    except tweepy.error.TweepError:
      print('\nCaught TweepError exception' )

为了解开这段代码,让我们从定义什么是光标开始。下面是来自 Tweepy 文档的介绍:

我们在 Twitter API 开发中大量使用分页。遍历时间表、用户列表、直接消息等。为了执行分页,我们必须为每个请求提供一个 page/cursor 参数。这里的问题是这需要大量的 boiler plate 代码来管理分页循环。为了使分页更容易,需要更少的代码,Tweepy 有了光标对象。

我的解释是,Cursor 对象是 Tweepy 管理和传递跨多页数据的方式,就像您最喜欢的书的内容分布在多页上一样。

记住这一点,上面的函数首先请求下一个数据指针(或页面)。如果在过去 15 分钟内收集的数据量超过了 API 限制,就会引发一个tweepy.RateLimitError异常,在这种情况下,代码将等待 15 分钟。最后一个异常是为了捕捉执行过程中可能出现的任何其他tweepy.error.TweepError,比如 Twitter API 的连接错误。

数据收集功能

推文

我们将重用 Github 上稍加修改的实现

**# Helper function to get all tweets of a specified user
# NOTE:This method only allows access to the most recent 3200 tweets
# Source:** [**https://gist.github.com/yanofsky/5436496**](https://gist.github.com/yanofsky/5436496)def get_all_tweets(screen_name): **# initialize a list to hold all the Tweets**
  alltweets = [] **# make initial request for most recent tweets 
  # (200 is the maximum allowed count)** new_tweets = api.user_timeline(screen_name = screen_name,count=200) **# save most recent tweets**
  alltweets.extend(new_tweets) **# save the id of the oldest tweet less one to avoid duplication**
  oldest = alltweets[-1].id - 1 **# keep grabbing tweets until there are no tweets left**
  while len(new_tweets) > 0:
    print("getting tweets before %s" % (oldest)) **# all subsequent requests use the max_id param to prevent
    # duplicates**
    new_tweets = api.user_timeline(screen_name = screen_name,count=200,max_id=oldest) **# save most recent tweets**
    alltweets.extend(new_tweets) **# update the id of the oldest tweet less one**
    oldest = alltweets[-1].id - 1
    print("...%s tweets downloaded so far" % (len(alltweets)))
 **### END OF WHILE LOOP ###** **# transform the tweepy tweets into a 2D array that will 
  # populate the csv** outtweets = [[tweet.id_str, tweet.created_at, tweet.text, tweet.favorite_count,tweet.in_reply_to_screen_name, tweet.retweeted] for tweet in alltweets] **#** **write the csv**
  with open(path + '%s_tweets.csv' % screen_name, 'w') as f:
    writer = csv.writer(f)
    writer.writerow(["id","created_at","text","likes","in reply to","retweeted"])
    writer.writerows(outtweets)
  pass

上面的代码块基本上由两部分组成:一个 while 循环用于收集列表中的所有 tweet,以及一些命令用于将 tweet 保存到一个csv文件中。

在我们解释 while 循环中发生了什么之前,让我们先了解一下使用的两个关键方法

  • api.user_timeline([,count][,max_id])返回指定用户最近的推文。count参数指定了我们希望一次检索的推文数量,最多 200 条。max_id参数告诉该方法只返回 ID 小于(即早于)或等于指定 ID 的 tweets。
  • list.extend(*iterable*)*iterable* 中的所有项目添加到列表中,不像append只将单个元素添加到列表的末尾。

现在,让我们分析一下 while 循环中发生了什么

  1. 这里有三个变量:alltweets是一个存储所有收集的 tweet 的列表,new_tweets是一个存储最新一批收集的 tweet 的列表,因为我们一次只能检索 200 条 tweet,而oldest存储我们迄今检索的最早的 tweet 的 ID,所以下一批检索的 tweet 在它之前。
  2. 变量在循环开始前被初始化。注意,如果指定的用户没有任何 tweets,new_tweets将为空,循环将不会执行。
  3. 在每次迭代中,检索在oldest之前发布的 200 条推文的新列表,并将其添加到alltweets
  4. while 循环将继续迭代,直到在oldest之前没有找到 tweet,或者达到 3200 条 tweet 的限制。

现在,为了将 tweet 数据写入一个csv文件,我们首先从每条 tweet 中提取我们关心的信息。这是通过使用一个列表理解来完成的,在这个列表中,我们将 tweet ID、文本和赞数等信息捕获到一个名为outtweets的新列表中。最后,我们打开一个CSV文件,首先用我们的表的标题名写一行,然后在下面的行中写outtweets中的所有数据。

追随者

**# Function to save follower objects in a JSON file.**def get_followers():
 **# Create a list to store follower data** followers_list = [] **# For-loop to iterate over tweepy cursors** cursor = tweepy.Cursor(api.followers, count=200).pages()for i, page in enumerate(limit_handled(cursor, followers_list)):  
    print("\r"+"Loading"+ i % 5 *".", end='')

    **# Add latest batch of follower data to the list**
    followers_list += page

 **# Extract the follower information**
  followers_list = [x._json for x in followers_list] **# Save the data in a JSON file**
  save_json('followers_data.json', followers_list)

如您所见,我们使用了上面创建的助手函数。此外,tweepy.Cursor(api.followers, count=200).pages()创建一个 Cursor 对象,一次返回 200 个关注者的数据。我们现在可以将这个光标和followers_list一起传递给我们的limited_handled函数。注意,检索到的用户对象包含两个键_api_json,因此我们只需使用 List comprehension [x._json for x in followers_list]提取我们关心的数据。

跟随

**# Function to save friend objects in a JSON file.**def get_friends():
 **# Create a list to store friends data** friends_list = [] **# For-loop to iterate over tweepy cursors** cursor = tweepy.Cursor(api.friends, count=200).pages()for i, page in enumerate(limit_handled(cursor, friends_list)):  
    print("\r"+"Loading"+ i % 5 *".", end='')

    **# Add latest batch of friend data to the list**
    friends_list += page

 **# Extract the friends information**
  friends_list = [x._json for x in friends_list] **# Save the data in a JSON file**
  save_json('friends_data.json', friends_list)

您可以看到,这与我们的get_followers()函数完全一样,只是我们使用api.friends来定义我们的光标对象,因此我们可以检索我们所关注的用户的数据。

今天的统计数据

**# Function to save daily follower and following counts in a JSON file**def todays_stats(dict_name): **# Get my account information**
  info = api.me() **# Get follower and following counts**
  followers_cnt = info.followers_count  
  following_cnt = info.friends_count **# Get today's date**
  today = date.today()
  d = today.strftime("%b %d, %Y") **# Save today's stats only if they haven't been collected before**
  if d not in dict_name:
    dict_name[d] = {"followers":followers_cnt, "following":following_cnt}
    save_json("follower_history.json", dict_name)
  else:
    print('Today\'s stats already exist')

api.me()返回认证用户的信息,在本例中是我。从那里,收集追随者和以下计数是简单的。我指定的日期格式%b %d, %Y将以类似于*2019 年 11 月 11 日、*的格式返回日期。有许多格式可供选择。

结束语

我希望你喜欢这篇介绍 Twitter 数据收集的教程。写这篇文章对澄清我对自己代码的理解很有帮助。例如,我更好地理解了 tweepy 光标对象。这让我想起了那句名言

如果你想学什么,就去教它

我一直在寻找提高写作的方法,所以如果你有任何反馈或想法,请随时分享。感谢阅读!

Twitter Pulse Checker:Twitter 上用于数据科学的交互式 Colab 笔记本

原文:https://towardsdatascience.com/twitter-pulse-checker-an-interactive-colab-notebook-for-data-sciencing-on-twitter-76a27ec8526f?source=collection_archive---------14-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

What’s popping in Seattle? Original background image: http://clipart-library.com/clipart/2099977.htm

想用 Twitter 数据进行奇特的数据科学研究吗?

我创建了一个交互式的 Google Colab,它可以带你浏览一个选定主题的端到端趋势分析。

Colab 是一个很棒的(也很少被使用的)工具,它的表单功能可以让你创建一个很棒的类似于应用程序的 UX 体验,同时提供了深入挖掘底层代码的选项。

我在笔记本中使用西雅图作为我的例子,但是它被设置用于任何主题。你可以搜集 twitter 数据,解析标签(NER),进行情感分析,用情节和文字云将所有好东西可视化。

要直接进入实验室,请点击这里:https://lnkd.in/ghKzQV4

概观

这是一种快速而肮脏的方式来了解 Twitter 上与特定主题相关的趋势。对于我的用例,我关注的是西雅图市,但是您可以很容易地将它应用于任何主题。

笔记本中的代码执行以下操作:

*抓取与你感兴趣的话题相关的推文。
*从文本中提取相关标签(NER:命名实体识别)。
*对这些推文进行情感分析。
*以互动的形式提供了一些可视化效果,以获得正在发生的事情的“脉搏”。

我们使用 Tweepy 收集 Twitter 数据,使用 Flair 进行 NER /情绪分析。我们使用 Seaborn 进行可视化,所有这一切都是可能的,因为有了精彩、免费和快速(使用 GPU)的 Google Colab。

关于 NER 的一点信息

这是从文本中提取标签的过程。

所以,举个例句:‘乔治·华盛顿去了华盛顿’。NER 将允许我们提取标签,如“乔治华盛顿的人”和“华盛顿(州)”的位置。它是 NLP 中最常见和最有用的应用之一,使用它,我们可以从推文中提取标签并对它们进行分析。

关于情感分析的一点看法

最常见的是,这是一个判断某个文本是正面还是负面的过程。更普遍的是,你可以把它应用到你选择的任何标签上(垃圾邮件/非垃圾邮件等等。).

因此,“我讨厌这部电影”将被归类为负面陈述,而“我喜欢这部电影”将被归类为正面陈述。同样,这是一个非常有用的应用程序,因为它让我们能够了解人们对某些事情的看法(Twitter 话题、电影评论等)。

要了解这些应用程序的更多信息,请查看 Flair Github 主页和教程:https://github.com/zalandoresearch/flair

使用

你显然需要一个谷歌账户才能使用 Colab。您可以通过点击顶部的“在操场上打开”选项来编辑笔记本。我建议在继续之前,将它作为你自己的副本保存在你的 Google Drive 中。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Open in Playground mode and then Save in your drive

**快速提示:**运行单元格的快捷方式是按键盘上的 SHIFT+ENTER。这是很方便的,因为你要穿过很多单元格。

你也应该去笔记本电脑设置,并确保选择了 GPU,因为只有一个 CPU 的刮/分析会变得非常慢。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

GPU should be selected

你需要 Twitter API 密匙(当然还有一个 Twitter 账户)来实现这个功能。在这里报名就能拿到:【https://developer.twitter.com/en/apps

一旦有了 API 密钥和 API 秘密密钥,就可以将这些凭证输入到身份验证单元中,并运行整个笔记本。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Enter your Twitter API Keys here

获取数据

一旦通过认证,您就可以开始刮!输入您感兴趣的搜索词和要推送的推文。我们每 15 分钟最多可以使用 API 抓取 45,000 条推文,因此滑块允许您选择这个限制。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

您可以选择是否要过滤掉转发。我选择过滤掉它们,专注于原始推文。

一旦我们收集了推文,我们就把它们加载到熊猫的数据框架中。在这里,我们做一些切片和切块,为一些视觉效果做好准备。

NER 和情感分析

我们使用 NER 提取相关标签:人、组织、位置等。

因为 Flair 不具备处理标签的能力,所以我们为它们创建了一个自定义标签。

最后,我们创建了一个数据框架,其中我们将所有标签按照它们的流行度、喜欢、回复、转发指标进行分组。

我们还计算这些标签的平均极性(情感得分)。

视觉化!

我们为最受欢迎的、喜欢的、回复的、转发的标签创建一些基本的情节。我们也用感情来切割这个。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

What’s hot in Seattle today?

该单元格设置为允许您按标签过滤。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们可以选中 Filter_TAG 框,然后选择我们想要度量的标记。然后,我们简单地重新运行单元以获得刷新的图。

词云

我承认我花了太多的时间来设置背景蒙版,但是它看起来很酷!

你可以选择你所选择的面具(如果你喜欢马或者出于某种原因做马的分析,就选一匹马…)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我选择了西雅图,并用这个掩码生成了一个单词云(如顶部的第一幅图所示)。

希望这能给你的数据项目一个好的开始。Colab 设置为以最少的输入运行,但是如果您想深入研究并根据您的需要定制它,代码就在那里。这就是笔记本的魅力。

你可以从这里开始玩笔记本:【https://lnkd.in/ghKzQV4】T4

使用 NLTK、Python 的 Twitter 情感分析

原文:https://towardsdatascience.com/twitter-sentiment-analysis-classification-using-nltk-python-fa912578614c?source=collection_archive---------2-----------------------

自然语言处理(NLP)是机器学习的一个独特子集,它关注现实生活中的非结构化数据。尽管计算机不能识别和处理字符串输入,但是 NLTK、TextBlob 和许多其他库找到了一种用数学方法处理字符串的方法。Twitter 是一个平台,大多数人在这里表达他们对当前环境的感受。作为人类,我们可以猜测一个句子的情绪是积极的还是消极的。同样,在本文中,我将向您展示如何使用 python 和 NLP 库来训练和开发一个简单的 Twitter 情感分析监督学习模型。

让我们从导入这个项目所需的库开始。

由于这是一个监督学习任务,我们得到了一个由标有“1”或“0”的推文组成的训练数据集和一个没有标签的测试数据集。训练和测试数据集可以在这里找到。

  • 标签“0”:积极情绪
  • 标签“1”:消极情绪

现在我们用熊猫来读数据。

train_tweets = pd.read_csv('train_tweets.csv')
test_tweets = pd.read_csv('test_tweets.csv')

探索性数据分析

无论在哪个领域,对机器学习问题进行数据分析都是必要的。让我们做一些分析,以获得一些见解。

sns.barplot('label','length',data = train_tweets,palette='PRGn')

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

sns.countplot(x= 'label',data = train_tweets)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

上面两张图告诉我们,给定的数据是不平衡的,只有很少数量的“1”标签,推文的长度在分类中没有起主要作用。处理不平衡数据是一个单独的部分,我们将尝试为现有的数据集生成一个最佳模型。

数据预处理和特征工程

给定的数据集由非常多的非结构化 tweets 组成,应该对其进行预处理以建立 NLP 模型。在这个项目中,我们尝试了以下预处理原始数据的技术。但是预处理技术不受限制。

  • 删除标点符号。
  • 删除常用词(停用词)。
  • 文字规范化。

标点符号在 NLP 中总是一个干扰,特别是标签和“@”在 tweets 中扮演主要角色。TextBlob 从句子中提取单词的功能可以在最佳水平上删除标点符号。遗漏的标点符号和其他不常见的符号将在即将到来的预处理技术中删除。

在 NLP 任务中,停用词(最常见的词,例如:is,are,have)在学习中没有意义,因为它们与情感没有联系。因此,去除它们既节省了计算能力,又提高了模型的准确性。

所有不常见的符号和数值都被删除,并返回一个包含单词的纯列表,如上所示。但是我们仍然会遇到同一个词的多种表达。(例如:play,plays,played,playing)尽管单词不同,但它们给我们带来的意思和正常单词“play”一样。所以我们需要做词汇规范化的方法来解决这个问题。NLTK 内置的 WordNetLemmatizer 就做到了这一点。

现在我们已经完成了我们的文本预处理部分,我们将进入矢量化和模型选择。

矢量化和模型选择

在让我们的数据训练之前,我们必须用数字表示预处理过的数据。自然语言处理中比较著名的单词矢量化技术有:CountVectorization 和 Tf-IDF 变换。让我们深入了解一下这些矢量化技术的理论背景。

计数矢量化生成一个代表文档中所有单词的稀疏矩阵。计数矢量化的演示如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Demonstration of Count Vectorization

  • Tf(d,t) (术语频率)定义为术语 t 在文档 d 中的出现次数。
  • Idf(t) (频率的逆文档)定义为 log(D/t),其中 D:文档总数,t:带项的文档数。

Tf-Idf transformer 做的是返回 TfIdf 的乘积,也就是该项的 Tf-Idf 权重。

因此,我们现在已经将我们的 sting 数据矢量化为数值,以便将其输入到机器学习算法中。我们选择朴素贝叶斯分类器进行二进制分类,因为它是 NLP 中最常用的算法。此外,我们使用 scikit-learn 内置的机器学习流水线技术来预定义算法的工作流程。这节省了大量时间和计算能力。

模型验证

因为我们决定选择自然语言处理技术,所以在应用于测试数据集之前,我们必须用现有的训练数据集来验证它。我们将使用传统的 train_test_split 技术来分割测试大小为 0.2 的训练数据集,并让我们的管道模型在分割的数据集上得到验证。一旦我们对验证的准确性感到满意,我们就可以将获得的模型应用于测试数据集。使用 scikit-learn、混淆矩阵和分类报告的内置功能来测量准确度。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Output of the above code

对于我们的简单管道模型,获得了 0.93837 的精度。请注意,通过使用 GridSearchCV 和其他预处理技术调整参数,有机会提高这种准确性。

希望这篇文章给你一个用 NLTK 和 Python 进行情感分析的基本概念。此处提供了该项目的完整笔记本

下面是一些有用的链接,可以帮助我们开始使用我们在这个项目中使用的自然语言处理库:

使用 fastText 的 Twitter 情感分析

原文:https://towardsdatascience.com/twitter-sentiment-analysis-using-fasttext-9ccd04465597?source=collection_archive---------6-----------------------

在这篇博客中,我们将使用一个快速文本库来分析各种推文的情绪,该库易于使用和快速训练。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Twitter sentiment analysis

什么是 fastText?

FastText 是由脸书人工智能开发的自然语言处理库。这是一个开源、免费、轻量级的库,允许用户学习文本表示和文本分类器。它在标准的通用硬件上工作。模型可以缩小尺寸,甚至适合移动设备。

为什么选择 fastText?

深度神经网络模型的主要缺点是它们需要大量的时间来训练和测试。在这里,fastText 有一个优势,因为它只需要很少的时间来训练,并且可以在我们的家用电脑上高速训练。

根据 fastText 上的脸书人工智能博客的说法,这个库的准确性与深度神经网络相当,并且只需要很少的时间来训练。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

comparison between fastText and other deep learning based models

现在,我们知道了 fastText 以及我们为什么使用它,我们将看到如何使用这个库进行情感分析。

获取数据集

我们将使用 betsentiment.com 的上可用的数据集。推文有四个标签,分别是正值、负值、中性和混合型。我们会忽略所有带有混合标签的推文。

我们将使用团队 tweet 数据集作为训练集,而球员数据集作为验证集。

清洗数据集

正如我们所知,在训练任何模型之前,我们需要清理数据,在这里也是如此。

我们将根据这些规则清理推文:

  1. 移除所有标签,因为标签不会影响情绪。
  2. 删除提及,因为它们在情感分析中也不重要。
  3. 将任何表情符号替换为它们所代表的文本,作为表情符号或表情符号在代表一种情绪方面发挥着重要作用。
  4. 用完整的形式代替收缩。
  5. 删除推文中出现的任何 URL,因为它们在情感分析中并不重要。
  6. 删除标点符号。
  7. 修复拼写错误的单词(非常基础,因为这是一个非常耗时的步骤)。
  8. 将所有内容转换为小写。
  9. 删除 HTML 标签(如果有)。

清理推文的规则:

我们将清理这条推文

tweet = '<html> bayer leverkusen goalkeeeeper bernd leno will not be #going to napoli. his agent uli ferber to bild: "I can confirm that there were negotiations with napoli, which we have broken off. napoli is not an option." Atletico madrid and Arsenal are the other strong rumours. #b04 #afc </html>'

删除 HTML 标签

有时 twitter 响应包含 HTML 标签,我们需要删除它。

为此,我们将使用[Beautifulsoup](https://www.crummy.com/software/BeautifulSoup/bs4/doc/)

如果没有 HTML 标签,那么它将返回相同的文本。

tweet = BeautifulSoup(tweet).get_text()#output
'bayer leverkusen goalkeeeeper bernd leno will not be #going to napoli. his agent uli ferber to bild: "I can confirm that there were negotiations with napoli, which we have broken off. napoli is not an option." Atletico madrid and Arsenal are the other strong rumours. #b04 #afc'

我们将使用正则表达式来匹配要删除或要替换的表达式。为此,将使用[re](https://docs.python.org/3/library/re.html)

移除标签

Regex @[A-Za-z0-9]+代表提及次数,#[A-Za-z0-9]+代表标签。我们将用空格替换匹配这个正则表达式的每个单词。

tweet = ' '.join(re.sub("(@[A-Za-z0-9]+)|(#[A-Za-z0-9]+)", " ", tweet).split())#output
'bayer leverkusen goalkeeeeper bernd leno will not be to napoli. his agent uli ferber to bild: "I can confirm that there were negotiations with napoli, which we have broken off. napoli is not an option." Atletico madrid and Arsenal are the other strong rumours.'

删除 URL

Regex \w+:\/\/\S+匹配所有以 http://或 https://开头并用空格替换的 URL。

tweet = ' '.join(re.sub("(\w+:\/\/\S+)", " ", tweet).split())#output
'bayer leverkusen goalkeeeeper bernd leno will not be to napoli. his agent uli ferber to bild: "I can confirm that there were negotiations with napoli, which we have broken off. napoli is not an option." Atletico madrid and Arsenal are the other strong rumours.'

删除标点符号

用空格替换所有标点符号,如.,!?:;-=

tweet = ' '.join(re.sub("[\.\,\!\?\:\;\-\=]", " ", tweet).split())#output 
'bayer leverkusen goalkeeeeper bernd leno will not be napoli his agent uli ferber to bild "I can confirm that there were negotiations with napoli which we have broken off napoli is not an option " Atletico madrid and Arsenal are the other strong rumours'

小写字母盘

为了避免大小写敏感问题

tweet = tweet.lower()#output
'bayer leverkusen goalkeeeeper bernd leno will not be napoli his agent uli ferber to bild "i can confirm that there were negotiations with napoli which we have broken off napoli is not an option " atletico madrid and arsenal are the other strong rumours'

替换收缩

去掉缩写,翻译成合适的俚语。没有通用的列表来代替缩写,所以我们为了自己的目的制作了这个列表。

CONTRACTIONS = {"mayn't":"may not", "may've":"may have",......}tweet = tweet.replace("’","'")
words = tweet.split()
reformed = [CONTRACTIONS[word] if word in CONTRACTIONS else word for word in words]
tweet = " ".join(reformed)#input
'I mayn’t like you.'#output
'I may not like you.'

修复拼写错误的单词

在这里,我们实际上并没有构建任何复杂的函数来纠正拼写错误的单词,而只是检查每个字符在每个单词中出现的次数是否不超过 2 次。这是一个非常基本的拼写错误检查。

tweet = ''.join(''.join(s)[:2] for _, s in itertools.groupby(tweet))#output
'bayer leverkusen goalkeeper bernd leno will not be napoli his agent uli ferber to bild "i can confirm that there were negotiations with napoli which we have broken off napoli is not an option " atletico madrid and arsenal are the other strong rumours'

替换表情符号或表情符号

由于表情符号和表情符号在表达情感方面发挥着重要作用,我们需要用它们在简单英语中所代表的表达方式来取代它们。

对于表情符号,我们将使用emoji包,对于表情符号,我们将建立自己的字典。

SMILEYS = {":‑(":"sad", ":‑)":"smiley", ....}words = tweet.split()
reformed = [SMILEY[word] if word in SMILEY else word for word in words]
tweet = " ".join(reformed)#input 
'I am :-('#output
'I am sad' 

表情符号

表情包返回给定表情的值为:flushed_face:,所以我们需要从给定的输出中删除:

tweet = emoji.demojize(tweet)
tweet = tweet.replace(":"," ")
tweet = ' '.join(tweet.split())#input
'He is 😳'#output
'He is flushed_face'

所以,我们已经清理了我们的数据。

为什么不用 NLTK 停用词?

清除数据时,删除停用词是一种有效的方法。它去掉了所有无关紧要的词,通常是每个句子中最常用的词。获取 NLTK 库中存在的所有停用词

from nltk.corpus import stopwords
stop_words = stopwords.words('english')
print(stop_words)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

NLTK stop words

我们可以看到,如果使用 NLTK 停用词,那么所有的负面缩写都将被移除,这在情感分析中起着重要的作用。

格式化数据集

需要格式化 fastText 监督学习所需的数据。

FastText 假设标签是以字符串__label__为前缀的单词。

fastText 模型的输入应该如下所示

__label__NEUTRAL _d i 'm just fine i have your fanbase angry over
__label__POSITIVE what a weekend of football results & hearts

我们可以使用以下方式格式化数据

def transform_instance(row):
    cur_row = []
    #Prefix the index-ed label with __label__
    label = "__label__" + row[4]  
    cur_row.append(label)
    cur_row.extend(nltk.word_tokenize(tweet_cleaning_for_sentiment_analysis(row[2].lower())))
    return cur_rowdef preprocess(input_file, output_file):
    i=0
    with open(output_file, 'w') as csvoutfile:
        csv_writer = csv.writer(csvoutfile, delimiter=' ', lineterminator='\n')
        with open(input_file, 'r', newline='', encoding='latin1') as csvinfile: # encoding='latin1'
            csv_reader = csv.reader(csvinfile, delimiter=',', quotechar='"')
            for row in csv_reader:
                if row[4]!="MIXED" and row[4].upper() in ['POSITIVE','NEGATIVE','NEUTRAL'] and row[2]!='':
                    row_output = transform_instance(row)
                    csv_writer.writerow(row_output )
                    # print(row_output)
                i=i+1
                if i%10000 ==0:
                    print(i)

这里,我们忽略标签不是Positive, Negative and neutral的推文。

nltk.[word_tokenize](https://www.nltk.org/api/nltk.tokenize.html#nltk.tokenize.punkt.PunktLanguageVars.word_tokenize)()将字符串转换成独立的单词。

nltk.word_tokenize('hello world!')#output
['hello', 'world', '!']

对数据集进行上采样

在我们的数据集中,数据并没有被平均划分到不同的标签中。它包含中性标签中大约 72%的数据。因此,我们可以看到,我们的模型往往会被大班淹没,而忽略小班。

import pandas as pd
import seaborn as snsdf = pd.read_csv('betsentiment-EN-tweets-sentiment-teams.csv',encoding='latin1')df['sentiment'].value_counts(normalize=True)*100

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

percentage of tweets for each labels

sns.countplot(x="sentiment", data=df)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

countplot for sentiment labels

由于中性类由数据集的大部分组成,该模型将始终尝试预测中性标签,因为它将保证 72%的准确性。为了防止这种情况,我们需要每个标签有相同数量的推文。我们可以通过向 minor 类添加新的 tweets 来实现这一点。向少数族裔标签添加新推文的过程被称为上采样。

我们将通过一次又一次地重复给定标签中的 tweet 来实现上采样,直到每个标签中 tweet 的数量相等。

def upsampling(input_file, output_file, ratio_upsampling=1):
    # Create a file with equal number of tweets for each label
    #    input_file: path to file
    #    output_file: path to the output file
    #    ratio_upsampling: ratio of each minority classes vs majority one. 1 mean there will be as much of each class than there is for the majority class 

    i=0
    counts = {}
    dict_data_by_label = {}# GET LABEL LIST AND GET DATA PER LABEL
    with open(input_file, 'r', newline='') as csvinfile: 
        csv_reader = csv.reader(csvinfile, delimiter=',', quotechar='"')
        for row in csv_reader:
            counts[row[0].split()[0]] = counts.get(row[0].split()[0], 0) + 1
            if not row[0].split()[0] in dict_data_by_label:
                dict_data_by_label[row[0].split()[0]]=[row[0]]
            else:
                dict_data_by_label[row[0].split()[0]].append(row[0])
            i=i+1
            if i%10000 ==0:
                print("read" + str(i))# FIND MAJORITY CLASS
    majority_class=""
    count_majority_class=0
    for item in dict_data_by_label:
        if len(dict_data_by_label[item])>count_majority_class:
            majority_class= item
            count_majority_class=len(dict_data_by_label[item])  

    # UPSAMPLE MINORITY CLASS
    data_upsampled=[]
    for item in dict_data_by_label:
        data_upsampled.extend(dict_data_by_label[item])
        if item != majority_class:
            items_added=0
            items_to_add = count_majority_class - len(dict_data_by_label[item])
            while items_added<items_to_add:
                data_upsampled.extend(dict_data_by_label[item][:max(0,min(items_to_add-items_added,len(dict_data_by_label[item])))])
                items_added = items_added + max(0,min(items_to_add-items_added,len(dict_data_by_label[item])))# WRITE ALL
    i=0with open(output_file, 'w') as txtoutfile:
        for row in data_upsampled:
            txtoutfile.write(row+ '\n' )
            i=i+1
            if i%10000 ==0:
                print("writer" + str(i))

至于重复推文,一次又一次,可能会导致我们的模型过度适应我们的数据集,但由于我们的数据集很大,这不是一个问题。

培养

尝试用 git 克隆安装 fastText,而不是使用 pip。

我们将使用监督训练法。

hyper_params = {"lr": 0.01,
                "epoch": 20,
                "wordNgrams": 2,
                "dim": 20}     

        print(str(datetime.datetime.now()) + ' START=>' + str(hyper_params) )# Train the model.
        model = fastText.train_supervised(input=training_data_path, **hyper_params)
        print("Model trained with the hyperparameter \n {}".format(hyper_params))

lr代表learning rateepoch代表number of epochwordNgrams代表max length of word Ngramdim代表size of word vectors

train_supervised是用于使用监督学习来训练模型的函数。

评价

我们需要评估这个模型以确定它的准确性。

model_acc_training_set = model.test(training_data_path)
model_acc_validation_set = model.test(validation_data_path)

# DISPLAY ACCURACY OF TRAINED MODEL
text_line = str(hyper_params) + ",accuracy:" + str(model_acc_training_set[1])  + ",validation:" + str(model_acc_validation_set[1]) + '\n' print(text_line)

我们将在训练和验证数据集上评估我们的模型。

test返回模型的精度和召回率,而不是精度。但是在我们的例子中,两个值几乎相同,所以我们只使用精度。

总的来说,该模型对训练数据给出了 97.5%的准确度,对验证数据给出了 79.7%的准确度。

预测

我们将预测传递给我们训练好的模型的文本的情感。

model.predict(['why not'],k=3)
model.predict(['this player is so bad'],k=1)

predict让我们预测传递的字符串的情感,而k代表返回的带有置信度得分的标签的数量。

量化模型

量化有助于我们降低模型的规模。

model.quantize(input=training_data_path, qnorm=True, retrain=True, cutoff=100000)

保存模型

我们可以保存训练好的模型,然后随时使用,而不是每次都训练它。

model.save_model(os.path.join(model_path,model_name + ".ftz"))

结论

我们学习如何清理数据,并将其传递给训练模型来预测推文的情绪。我们还学习使用 fastText 实现情感分析模型。

利用 Python 的 matplotlib 可视化空间数据

原文:https://towardsdatascience.com/two-dimensional-histograms-and-three-variable-scatterplots-making-map-like-visualisations-in-7f413955747?source=collection_archive---------14-----------------------

在 matplotlib 中制作类似地图的可视化效果

为什么要对空间数据使用 matplotlib?

作为预测房价项目的一部分,我收到了一个来自美国华盛顿州金县的大型房屋数据集。该数据集包含大量与房屋相关的数据,包括一年内售出的每栋房屋的经度和纬度。因为纬度和经度都是连续的数字数据,所以在多元线性回归模型中,这些是潜在有用的特征。然而,甚至在项目进行到那个阶段之前,在数据集中看到纬度和经度就表明您也可以看到令人兴奋的空间数据制图世界。

确实存在一些免费或低价的基于 GUI 的电子表格程序,具有半功能地图功能——从笨重的 Excel Power Map,到有限的 Google My Maps,再到可悲的即将停产的 Google Fusion Tables。然而,只需几行代码,您就可以使用 Python 更快地创建信息丰富的类似地图的可视化效果,并且有更多的定制选项。你甚至不需要专门的地理空间分析库的知识就可以做到这一点——只要你的数据集中有纬度和经度,你就可以使用每个人都喜欢的绘图伙伴 matplotlib 来可视化它。

二维直方图

直方图是可视化数据集中变量分布的一种很好的方式,它显示数据集中位于特定值范围或区间的条目数量。下面的代码为 King County ('kc ')数据集中的纬度和经度生成简单的(一维)直方图:

import matplotlib.pyplot as pltfig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))fig.suptitle(‘Distributions of latitude and longitude in the King County housing dataset’, fontsize=16)ax1.hist(kc.lat)ax1.set_xlabel(‘Latitude’, fontsize=13)ax1.set_ylabel(‘Frequency’, fontsize=13)ax2.hist(kc.long)ax2.set_xlabel(‘Longitude’, fontsize=13)ax2.set_ylabel(‘Frequency’, fontsize=13);

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这些很好地显示了每个变量的分布,但是它们并没有给你一种地理上的感觉。我们想要的是一张地图。幸运的是,我们可以用二维直方图来实现这一点。这实质上是将沿 x 轴(经度)的直方图与沿 y 轴(纬度)的直方图相结合。不再是条的宽度(即一维),它们现在基本上是一个网格(即二维的正方形)。我们可以添加一个带有plt.colorbar()的颜色条,帮助我们将它可视化为一种热图:

plt.figure(figsize = (10,8))plt.hist2d(kc.long, kc.lat, bins=150, cmap=’hot’)plt.colorbar().set_label(‘Number of properties’)plt.xlabel(‘Longitude’, fontsize=14)plt.ylabel(‘Latitude’, fontsize=14)plt.title(‘Number of properties in each area of King County, Washington’, fontsize=17)plt.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果你仔细观察,稍微眯着眼睛,你可以分辨出国王郡的形状,西雅图在左上方,还有普吉特湾的形状。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Map of King County, Washington, USA. Source: Google Maps

三变量散点图

使用 matplotlib 绘制空间数据的另一种方法是使用散点图。散点图将两个变量之间的关系可视化,一个在 x 轴上,一个在 y 轴上,通过在 x 和 y 变量的值上绘制每个数据点的点。Matplotlib 允许我们更进一步,使用第三个变量根据第三个变量的数据点值来改变每个点的颜色(或形状,或大小)。

King County 数据库包含每栋房屋的销售价格和每栋房屋的居住面积等信息。从上面的 2D 直方图中可以清楚地看到,在西雅图及其周边地区发现了许多房产,但是数据集也包括了远离城市的房产。地段大小可能以非随机方式变化,城市中的地段较小,乡村中的地段较大。因此,比较同类产品的更好方法是比较每平方英尺的价格。

在该散点图中,绘制了经度和纬度,并根据每平方英尺的价格对各点进行了着色,从而生成了一张地图,显示了每个地区的价格:

plt.figure(figsize = (10,8))plt.scatter(kc.long, kc.lat ,c=kc.price_per_sqft, cmap = ‘hot’, s=1)plt.colorbar().set_label(‘Price per square foot ($)’, fontsize=14)plt.xlabel(‘Longitude’, fontsize=14)plt.ylabel(‘Latitude’, fontsize=14)plt.title(‘House prices in King County, Washington’, fontsize=17)plt.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

毫不奇怪,最昂贵的房产(以每平方英尺的价格计算)位于贝尔维尤和麦地那——科技亿万富翁比尔·盖茨和杰夫·贝索斯的家,以及美国一些最昂贵的邮政编码。

这就是我们使用 matplotlib 创建类似地图的可视化的两种方法。下次当您发现自己拥有包含纬度和经度的数据集时,为什么不尝试一下呢!

两个基本的熊猫附加产品

原文:https://towardsdatascience.com/two-essential-pandas-add-ons-499c1c9b65de?source=collection_archive---------3-----------------------

这两个必备的用户界面将帮助你提高你的熊猫技能

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Python 数据分析库(Pandas)是 Python 事实上的分析工具。如此强大的分析库居然可以开源免费使用,这还是让我很惊讶。

但它并不完美…

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Yes Pandas does have some shortcomings

我对这个库有一些不满,尤其是在执行简单的过滤和旋转时。在某些情况下,用户界面确实可以加速分析。对于探索和过滤数据的直观方式来说,没有什么比“拖放”更好的了,而这不是 Pandas 允许你做的事情。令人欣慰的是,有两个图书馆解决了这些问题,并与熊猫完美地合作。

Pivottable.js ,交互式数据透视表和图表

Pandas 中的数据透视表非常强大,但它并不适合快速简单的数据浏览。事实上,事情会很快变得非常复杂:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Pandas pivot tables can leave you scratching your head. Credit https://pbpython.com

谢天谢地,有一个奇妙的交互式数据透视表和绘图插件,****。它可以用 4 行代码安装和运行:

!pip install pivottablejs
from pivottablejs import pivot_uipivot_ui(df,outfile_path=’pivottablejs.html’)
HTML(‘pivottablejs.html’)

这给了你一个交互式的 HTML 数据透视图。这可以在笔记本中显示,也可以在浏览器中以 HTML 文件的形式打开(这样可以方便地与他人共享):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

pivottable.js allows for interactive pivoting and charting of a Pandas dataframe

QGrid :快速的交互式表格

厌倦了看熊猫数据框的第一行和最后 5 行?您是否经常希望能够快速过滤并查看您的数据发生了什么?Pandas 使用 lociloc 提供了有用的过滤功能,然而,数据透视表同样会变得非常复杂,使用这些索引功能的语句也是如此。

QGrid 允许你这样做,甚至更多。一些关键特征是:

  • 过滤和排序数据帧
  • 在不降低性能的情况下滚动大型数据帧(超过 100 万行)
  • 直接通过用户界面编辑数据框中的单元格
  • 返回应用了过滤器/排序/编辑的新数据帧
  • 兼容 Jupyter 笔记本和 JupyterLab

通过 pip 或 Conda 安装非常简单:

pip install qgrid
jupyter nbextension enable --py --sys-prefix qgridimport qgrid# only required if you have not enabled the ipywidgets nbextension yet
jupyter nbextension enable --py --sys-prefix widgetsnbextension#to show a df simply use the below:
qgrid.show_grid(df)

要了解什么是可能的,请参见 QGrid Github 页面上的以下演示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Visit https://github.com/quantopian/qgrid for more information on QGrid

仅此而已。希望这两个工具将有助于加快您在 Python 中的数据分析。

如果你知道任何其他的熊猫用户界面库,请在下面的评论中告诉人们。

有抱负的数据科学家的两项重要技能

原文:https://towardsdatascience.com/two-important-skills-for-an-aspiring-data-scientist-acdcb44a5c3a?source=collection_archive---------31-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Austin Distel on Unsplash

这就像生命中的另一天。

我当时正在为一家基于互联网的公司解决一个回归问题。

我加倍努力查找该领域的文献,试图找出还可以做些什么来提高性能。

尽我所能。

这就是我很多天来试图解决的问题。

他联系我问:哎,你工作怎么样?有进展吗?

我回答说:是的,我提高了性能。平均绝对误差已经降低到 10。

他:嗯…?梅。那是什么,伙计?解释一下。

Me:预测值和实际值之间的绝对差值的平均值。

他:用人类的语言和我说话,伙计。我不明白这一切。

然后,在尝试了很多之后,我写了一份对 MAE 的直观解释并发给了他。

他明白了,但还是有问题。

他:好的,听起来很酷!我明白了,但我们不会像这样向客户解释。并不是每个人都会这样理解。我想让你报道一些其他的,任何人都能一口气看懂的东西。

我:好的,我会尽快回复你。

敲响了警钟。

有些事情需要弄清楚,需要从这次事件中吸取教训。

你明白了吗?

是的,它传达了你从数据中得出的见解,这样每个人都能理解。

看,不是每个人都来自技术和数学背景。他们一点也不在乎。他们不关心你的 15 层深层神经网络。重要的是:你有没有给这张桌子增加价值,如果有,用简单的英语向我们解释。

几乎所有的生意都是为了拥有更多的顾客,赚更多的钱。这就是你的工作。所以,你需要坐下来,找出你试图解决的业务核心问题是什么。它将如何帮助企业。然后你只需要用这些术语来解释。

我给你一个建议。

训练你的移情肌肉,站在另一个人的立场上,想象那个人,然后试着解释你的见解。

看,你知道所有的数学概念并运用它们来解决问题是很好的。但是,如果你不能帮助企业做出决策或赚更多的钱,那就没有任何意义。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Source

这也是数据可视化有很大帮助的地方。数据可视化不是画那些花哨的图,数据可视化的唯一目的是用视觉传达你的见解。

项目开始前

作为初学者,我们大多习惯于从 kaggle 或一些随机课程中挑选一个问题,然后解决它。我们事先知道所有的细节,这是回归问题,这是你最后得到的数据集,现在你必须解决它。

但大多数时候事情并不是这样。当你工作时,你会遇到一个商业问题,然后你必须找出并映射到一个机器学习问题。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Business Problem -> ML Problem

快速 **举例:**假设你在 Quora 工作,有人告诉你一个问题存在大量重复条目,使得平台难以使用。你能想办法解决这个问题吗?

这就是商业问题。现在你已经彻底明白了,机器学习是否能有所帮助,如果是的话,那么,把它映射到一个机器学习问题上。

你可以使用 NLP 技术或基于深度学习的解决方案来找出给定的两段文本是否重复。如果是,删除其中一个,如果不是,保留两个。

不仅止于此。你还需要计算出你要用来评估你的模型的误差度量。误差度量的选择将指导您的模型开发之旅。

外卖:

  • 学会使用数据可视化和简单的英语有效地交流你的结果。
  • 甚至在开始一个项目之前,学会将商业问题映射成机器学习问题。

如果你发现它对你有任何帮助,一定要帮我传播这个消息,并关注我以获得更多这样的文章。和平与力量。

一枚硬币的两面:杰瑞米·霍华德的 fast.ai vs 吴恩达的 deeplearning.ai

原文:https://towardsdatascience.com/two-sides-of-the-same-coin-fast-ai-vs-deeplearning-ai-b67e9ec32133?source=collection_archive---------10-----------------------

如何不通过同时参加 fast.ai 和 deeplearning.ai 课程来“过度适应”你的人工智能学习

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Which One to Take? WHY NOT BOTH!

数据科学和人工智能可能是目前科技领域最热门的话题,这是理所当然的。在应用层面和研究领域都有巨大的突破。这是一种祝福,也是一种诅咒,至少对于想要进入这一领域的学生和爱好者来说是这样。有太多的算法要学习,太多的编码/工程技能要磨练,太多的新论文要跟上,即使你觉得你已经掌握了这门艺术

旅程漫长,学习曲线陡峭,冲突真实存在,但潜力如此之大,人们仍然蜂拥而至。好的一面是,我们也有很棒的教育者和指导者致力于减轻痛苦,让这个过程少一点苛刻,多一点乐趣。我们将探索其中最伟大的两个,并分享一种潜在的有效方法,以帮助您更快乐地在数据科学的海洋中畅游。

人工智能学习“耗尽”

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Toa Heftiba on Unsplash

如果你列出一个人要成为一名“好的”数据科学家或机器学习工程师需要学习的东西,那可能会长得吓人:

**数学:**线性代数,微积分,统计学,算法,…

编码: Python,R,SQL/NoSQL,Hadoop,Spark,Tensorflow/PyTorch,Keras,Numpy,Pandas,OpenCV,数据可视化…

**算法:**线性回归、逻辑回归、支持向量机、PCA、异常检测、协同过滤、神经网络、CNN、RNN、K-Means、NLP、深度学习、强化学习、AutoML、…

**工程:**命令行,云平台(AWS,GCP,Asure),DevOps,部署,NGINX/Apache,Docker…

对于一个刚刚进入这个领域的人来说,这份名单很容易让人晕头转向。然而,它仍然只是触及表面。有些人制定了一个雄心勃勃的计划,并投入其中。一些人失去了动力,感觉完全淹没在水下,出口看不见了。哪里出了问题?

你“过度适应”了自己

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

From Andrew Ng’s Machine Learning course

对于了解一点机器学习的人来说,verfitting 是一个非常熟悉的想法。这基本上意味着你的算法学习了“太多”的数据,把自己埋进了数据集的小细节中,错过了大画面。想一想,有时当我们学习一件事情时,我们太投入了,以至于忘记了我们为什么要学习它,以及它将如何融入大局。我称之为“过度适应”你自己的学习。这种情况经常发生在有学术背景的人身上。数学博士倾向于确保在继续下一个之前所有的定理都被完全理解。这对学习数学很有帮助。对理论有深刻的理解会给你很大的直觉和信心。它将使您能够看到未经培训的人不容易看到的模式和问题,但数据科学要求更多。

抛开理论不谈,这其中也有实用的部分。一个恰当应用的算法,加上高效的代码、精心调整的超参数和精心设计的流水线,通常会取得不错的结果,但光有算法是不够的。过于深入地钻研理论,你可能会错过学习的实践部分。同样重要的是,积累如何实施所学知识和处理现实生活中的复杂问题的经验。如何解决这个问题?进入 deeplearning.ai 和 fast.ai 课程。

Deeplearning.ai 和 Fast.ai

已经开发了很多课程来帮助人们完成学习过程。其中,Deeplearning.ai 和 fast.ai 是两个独特的,它们有自己的方法,可以给我们一些关于学习数据科学的潜在有效方法的见解。

deeplearning.ai

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

deeplearning.ai 是由吴恩达开发的付费课程。和他的其他课程一样,它以精心设计的学习曲线、平静流畅的教学风格、充满挑战而又有趣的作业而闻名。它被公认为是一门不会出错的深度学习课程。它从基础理论开始,并逐步发展到如何将所有部分结合起来解决现实生活中的问题。这也被称为“自下而上”的方法。

fast.ai

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

fast.ai 由杰瑞米·霍华德雷切尔·托马斯推出,作为一门免费课程,教授有基本编码经验的人最先进的深度学习技术。在没有太多基础理论解释的情况下,使用很少几行代码,fast.ai 的学生能够在自己的领域内快速取得惊人的成果。(在完成 fast.ai 课程的第一课后,我构建了一个达到 96%准确率的中国书法风格分类器部署在云上。)它首先教你如何解决现实世界的问题,然后越来越深入地探究事物是如何工作的以及为什么工作。这也被称为“自上而下”的方法。

哪一个是最好的方法?都是!

那么‘自下而上’和‘自上而下’,哪个更好?我们应该走哪一条?答案是双双

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Maarten Deckers on Unsplash

看,这两门课程相辅相成。假设你从吴恩达的 deeplearning.ai 课程开始,你将自己埋进了无尽的公式和理论中,你获得了很多直觉,但是经过几周的学习,你仍然没有什么可以展示给你的朋友,也不太确定你什么时候可以应用你新获得的知识。你对机器学习基础的研究回报越来越少。你的大脑变慢了,你开始觉得无聊。现在是开始上一两课 fast.ai 课程的最佳时机。在强大的 fast.ai 库和几行代码的帮助下,你将能够构建令人印象深刻的模型来解决现实生活中的问题,甚至击败一些最先进的论文和竞赛。这将给你的大脑一种完全不同的刺激,给你的心更多的信心和激情去更深入地探究为什么一切都在运转。一旦你建立了几个项目,让你的朋友们惊叹不已,你就会更有动力去学习更多的基础知识,然后你就可以回到 deeplearning.ai 课程,并在那里继续学习。这两个过程互相推动,你可以只是冲洗和重复,直到你完成这两个。

这就形成了一个完美的学习圈。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Dan Freeman on Unsplash

以这种方式选修两门课程的最大好处是,一旦你完成了两门课程,你就会做好充分的准备。从 fast.ai 课程到向潜在雇主展示,你有大量的项目,你也对一切如何运作有深刻的了解,甚至发表过一两篇论文来展示你的发现。你现在是一名全面发展的数据科学家。多酷啊。

欢迎任何反馈或建设性的批评。你可以在 Twitter 上找到我,也可以在我的博客网站 wayofnumbers.com T2 找到我。

关于手工标注数据的两个故事——它仍然有效

原文:https://towardsdatascience.com/two-stories-about-labeling-data-by-hand-it-still-works-fec167d74ac7?source=collection_archive---------21-----------------------

当然,这是一个屁股痛,有自己的问题,但人类的大脑仍然是惊人的

我知道。手动标注数据可能会非常乏味,让人麻木。这是你能得到的最迷人、最性感的机器学习工作。作为超级聪明的数据科学家,我们难道不应该超越这种经常强加给实习生、研究生或机械土耳其人的苦差事吗?

事实上,不是。在很多情况下,我认为它比许多涉及无监督学习方法的替代方法更少痛苦(也更快)。它还会产生非常重要的特定领域见解,我认为一名优秀的数据科学家绝对需要在他们选择的行业中保持高效。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

https://xkcd.com/2173/

也许是因为十年前我作为数据分析师在这个行业崭露头角,艰难地拼凑出自己的见解。或者可能是因为我的社会科学背景,手动编码回答是我们定量工具箱中非常重要的工具。尽管如此,我不是唯一相信这一点的人。

总的来说,我发现手动分类数据是最有用的,当你陷入这样一种情况时,你需要:1)作为研究人员学习理解数据集/问题空间,2)提出一个分类系统。

在这种情况下,很难制造一个开箱即用的自动化系统。当然,有一些无人监管的方法,你可以尝试各种形式的聚类,然后进行分类,但是当你自己不熟悉问题空间时,你得到的聚类是否有效和可用并不完全明显。既然事实上没有地面真理可言,你也可以在你的头脑和你的分类器中,潜进你自己去建立一些地面真理的表象。

人类的分类器会错吗?绝对的。有无意识(或有意识)的偏见?你打赌。错过重要功能?当然了。但对于我平时操作的应用来说,这些都不重要。我们需要足够好的东西来开始,来建立一个测试用例。一旦事情被引导,我们可以看到事情如何执行并检查问题。

这里有两个 2010 年代早期的说明性故事,当时技术是不同的(但并不完全不同)。

技术提示:我通篇交替使用动词“编码”和“标签”。只是习惯。

故事#1,在黑客马拉松上给一些企业分类

2012 年,我参加了某种形式的数据黑客马拉松,我相信是由 Data Kind 的人与各种政府机构和非营利组织合作举办的。我们分成几个小组,每个小组都有一些需要数据帮助的问题,我们都尽力在几个小时内提供帮助。输出可以是一个模型,或者一个方法,或者任何有用的东西。

对于我的团队,我们与纽约的一家代理机构合作,我忘了是哪家了。我们的任务基本上可以归结为企业的大型 csv 文件和他们拥有的专业许可证(香烟零售商、台球室、讨债、路边咖啡馆、一般供应商等)。这些企业也有他们的注册地址和建筑类型,是否有与该网站相关的餐馆执照或酒类执照,以及其他一些细节。我们的目标是了解企业和执照是如何结合在一起的,这样如果一家企业碰巧丢失了执照(比如说,一家没有执照的酒吧),就可以标记出来。

我的四五人团队(我觉得?我忘记了一些细节,但有旧数据文件的副本要查看)有许多超级聪明的人,数据科学界的一些名人。首先,他们拿出 R(一种我还不知道的语言),并开始研究如何摄取我们拥有的各种 CSV 文件,以便他们可以运行各种分析(相似性计算等)。

潜入水中

看到他们在工作中有编码的一面,我继续做我通常做的事情,努力通过原始数据获得对事物的感觉,试图让自己在这方面有用。因为我们最终想要的是一种不使用现有的业务分类代码,根据业务实体拥有的许可证对其进行独立分类的方法,所以我有一种预感,我们必须找到一种方法,用我们不应该使用的标签之外的非常非常少的数据对这些业务实体进行分类(因为我们试图预测它以找到差异)。

另一种方法是做一个两步分类系统,我们将 1)把许可证分组在一起,希望企业的属性能够自然地聚类,然后 2)利用聚类并使用它们来形成一个分类器,可以捕获没有正确许可证的企业。这两者都不能保证商业/许可证集群会以任何合理的方式真正形成。只有大约 10k 个许可证(一个给定的企业可能有多个许可证和行),可能会有太多的干扰。

当我浏览这些企业并试图猜测它们是什么时,奇怪的是,我发现这出奇的容易。我会查看该实体的名称,并会不断地看到类似“弗雷德自助洗衣店”或“阳光咖啡馆”的东西。我意识到虽然没有严格的要求,但人们经常以他们从事的业务来命名他们的商业实体。几乎没有人会开一家名为“玛丽咖啡有限责任公司”的汽车商店。如果没有人坐下来通读大量数据,我们永远不会发现这一点。

我最终做的是编辑一个关键词列表,我觉得这些关键词是某类业务的高度指示,例如:“汽车”、“熟食店”、“Duane”(Duane Reade 连锁药店)、“超市”等…然后,我们分析了哪些许可证与这些词相关联。例如,卷烟零售许可证常常与名称中带有“熟食店”的企业联系在一起,也与“食品”和“市场”联系在一起,偶尔还会与“汽车”联系在一起。下表显示了我们发现的一些关联。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

The number of business entities w/ a word in its name (top row) vs business licenses associated (down the left)

到这一步时,我们的时间有点紧,但我们本质上构建的是一个系统,它可以接受一个企业名称,并生成它可能拥有的许可证列表。它不会对所有东西进行分类,但它是一种比其他可用功能(如地址、建筑类型(两个家庭与电梯合作公寓等)、零售面积)更强大的将企业聚集在一起的方式。

有了这个初始分类,我们就可以试验其他特征,看看是否有任何有意义的聚类,因为我们已经半手工标记了数以千计的企业。这是我们(相当)坚定的基础事实,允许我们利用数据集的其余部分。

可悲的是,数据黑客马拉松很快就结束了,我不知道这个模型发生了什么,不管它是否被使用过。但希望它能帮助某人更接近目标。

故事#2,为 Meetup 创建一些组类别

我不记得这个项目是什么时候出现的了,但是大概是在 Meetup 第一次尝试在直接关键词搜索之外进行群体发现的时候,大概是 2012 年左右吧?自从我帮助建立这个系统以来,他们的分类已经发生了很大的变化,所以我确信这与现有的系统没有任何关系,在这里谈论应该是安全的。

作为背景,在 2011 年之前,Meetup 群组最初有多达 15 个“主题**”**与之相关联。这些影响了当你的组被宣布时什么用户会得到通知,你可以用它来浏览组。疯狂的是,主题是完全自由形式的用户字符串,由组组织者创建。有一些轻微的监管,以防止人们使用顽皮的词语,但除此之外,你可以自由地写下像“摄影”这样的单个单词或像“晚上拍奶酪汉堡的照片”这样的完整句子。

问题是,虽然大多数类型的小组通常都有一个主导主题,就像大多数摄影小组使用“摄影”一样,但并不是所有的小组都这样做。这在“全职妈妈”组和“全职爸爸”组中最为突出,这两个组本质上都是育儿组,但一个组可能只选择一个。

好吧,如果我们要有一个更好的方法来找到群体,就需要有一种方法通过某种类别来组织群体。我们需要将 1-15 个主题标签提取到 1 个(也许 2 个)类别中。这些类别应该是什么?虽然新创建的组无论如何都要经过人工审核,并且可以在那里进行人工分类,但是我们如何处理大约 10 万个现有的组呢?

盲目地来看这个问题,你可能会试图分析和 k-means 聚类所有的主题字符串,基于什么组使用它们。因为我们知道我们希望 K 是一个“可管理的数字”(低于 30 岁),所以它可能会起作用。这可能需要一些调整和反复试验,但听起来可行。

这个计划

我没有采用 k-means 方法,而是走了一个不同的方向。凭直觉工作(深入研究 Meetup 的内部数据 2-3 年),我有一种感觉,“最常用的主题可能已经足够有信息了”,这意味着我可以忽略主题的超长尾巴。

因此,我转而抛弃了所有与超过一定数量的群组相关联的主题(超过 50 个群组或者类似的,我忘了)。这产生了一个大约 1800 个主题的列表,相比之下,一个巨大的列表包含超过 15k 个主题字符串。

在那之后,我和我的犯罪定性研究伙伴谈了谈,我们分开了数据集,然后坐下来用手对主题进行分类。就像编码自由形式的调查回答一样,我们创建了我们认为合适的类别,并努力通过。

创建映射后,我创建了一个非常简单的算法来给一个组分配一个类别,1 个分类主题=一个类别的 1 票,投票最多的类别就是该组的类别。仅用这种简单的算法,我们就覆盖了大约 85-90%的现有群体。对一组随机样本进行的抽样检查显示,这些类别总体上相当准确(我忘记了细节,但与人类的一致性达到了 90%左右)。

我们如何处理无法以这种方式分类的~ 10–15k 组?我们为它制作了一个简单的网络工具,并要求客户支持团队中的每个人在他们轮班的安静时间里对它进行整理。对所有东西进行分类并不需要很长时间,可能需要 1-2 周的时间。

接下来,我们使用相同的算法来建议类别应该是什么,但是支持团队无论如何都会在审查新组的 TOS/质量时检查并更改它。

我确信他们现在使用的系统和我很久以前帮助建立的系统是不同的。当前类别似乎修复了我们在 v1 中发现的一些问题。例如,我们最初的遗憾之一是某些类别“太大”,太多的商业/创业/企业家/投资团体都被归为“商业”一类。我们应该回去平衡事情,但是我们选择不这样做,因为我们不确定类别在那个时候会如何被使用。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Meetup’s current categories (2019), about half of which weren’t ones I put together almost a decade ago

所以卷起你的袖子

想试试吗?这里有一些快速提示。

建立一个良好的编码环境。贴标签的行为应该让你进入一个流程,在那里你可以快速制作出准确的标签。当你最大限度地减少点击链接或眼睛在屏幕上跳来跳去的摩擦时,你就帮助最大限度地减少了引入非受迫性错误的精神疲劳。然后,当你感到疲劳时,确保经常休息(我喜欢吃零食)。

如果你有多个编码员,确保每个人都同意用相似的方式编码(更正式的说法是你有一本编码书),经常交流,检查你的工作。对于更严格的东西,确保你做了健全的交叉检查,并检查了评分者之间的可靠性

最后,想办法把工作分散开来。在团队环境中,编程更有趣。我们可以就奇怪的例子交换笑话,或者在飞行中讨论奇怪的边缘案例。另外,有另一个人和你一起工作有助于集中注意力。

但是,这不会扩展!

当然,如果你有 5000 万件事情要编码,你不会手工去做所有的事情。但是从 500 个到 5000 个,甚至到 15000 个标记条目将使你制作的任何分类器表现得更好。然后,您应该能够比以前更有信心地扩大规模。

希望我的小故事能让你相信,手动标注数据这种完全不性感、时常令人头脑麻木和痛苦的工作是你工具箱中的一个超级有用的工具。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值