用 TF 2.0 迁移学习
站在巨人的肩膀上
Photo by Scott Blake on Unsplash
迁移学习是这样一个过程:采用一个已在相似域的数据集上训练过的模型,然后通过添加层来扩展该模型,以根据您的数据进行预测。
已训练的模型(称为预训练模型)存在于 TensorFlow 库中。这些人通常在 Imagenet 大规模视觉识别挑战(Imagenet)可用的图像上接受训练。该挑战赛提供了 120 万张图片,可分为 1000 个类别。
预训练模型的主要优势在于,它们是在这些图像上使用我们通常无法获得或购买成本过高的硬件进行训练的。这些模型通常有一个最终层,将输出分成 1000 个不同的类别。
在迁移学习中,你要做的是选择一个模型,然后冻结权重。然后向模型中添加新的层,并训练权重,直到收敛。
TensorFlow 中有各种预训练的模型,如 VGG,我们将利用这些模型。让我们从安装 TF 2.0 和导入必要的库开始。
Install TensorFlow 2.0
接下来,我们需要为我们的图像和模型定义一些常量。这些细节包括我们在最终图层中想要的类的数量,以及颜色通道的数量和图像的尺寸。
我们现在准备创建我们的基础模型,这是没有最终层的预训练模型。我们将可训练值设置为 false,以防止在训练期间更新权重。
打印基础模型将显示架构。然后,我们可以继续向基础模型添加新层。我们可以为此使用函数式 API。
就这样,我们有了一个可以用来训练的模型。不要忘记,您需要通过创建一个生成器来将您的图像转换成正确的格式,以便进行培训。我喜欢用 Python 处理文件名列表(文件)和它们所属的类(类别)。有了这两个列表,下面的代码将创建您的生成器。
Image input pipeline
然后,您可以继续编译和训练您的模型。
然后,您可以检查培训的结果,并进行修改以进行改进。你应该改变steps_per_epoch
和epochs
。您应该选择您的优化器并配置学习率。您可能还想携带我们的数据增强功能,使您的训练数据更加可靠。
练习愉快。
使用 Python 的 Matplotlib 将灰度图像转换为 RGB
了解图像数据结构,同时为计算机视觉和深度学习管道添加两个维度
R, G, & B — Arabic numeral ‘3’
数据预处理对于计算机视觉应用至关重要,将灰度图像正确转换为当前深度学习框架所期望的 RGB 格式是一项必不可少的技术。那是什么意思?
理解彩色图像结构
大多数彩色照片由三个互锁的数组组成,每个数组负责红色、绿色或蓝色值(因此是 RGB ),每个数组中的整数值代表一个像素值。同时,黑白或灰度照片只有一个通道,从一个阵列中读取。
使用 matplotlib 库,我们来看一幅彩色(RGB)图像:
img = plt.imread('whales/547b59eec.jpg')
plt.imshow(img)
print(img.shape)
(525, 1050, 3)
matplotlib.plot.shape 调用的输出告诉我们,图像的高度为 525 像素,宽度为 1050 像素,有三个这样大小的数组(通道)。
A whale image, from a recent kaggle competition
img
对象是<类‘numpy . ndarray’>,所以让我们看看每一层的形状和值:
#values
print(img[524][1049][2])
198print(img[524][1049])
[155 177 198]print(img[524])
[[ 68 107 140]
[ 76 115 148]
[ 76 115 148]
[ 75 114 147]
...
[171 196 216]
[171 193 214]
[171 193 214]
[155 177 198]]
好了,上面的打印命令告诉我们这个由 1050 列(宽)和 525 行(高)组成的图像是什么?
首先,我们看最后一个像素的值,在最后一列的最后一行和最后一个通道:198。这告诉我们该文件很可能使用 0 到 255 之间的值。
接下来,我们查看所有三个通道中该像素的值:[155,177,198]。这些是该像素的红色、绿色和蓝色值。
为了好玩,我们可以跨所有层和所有行查看最后一行的值。
了解灰度图像结构
灰度图像只有一个通道!就是这样!
问题是
引用 Pytorch 文档:所有预训练的模型都期望输入图像以相同的方式标准化,即小批量的 3 通道 RGB 形状图像(3 x H x W)…
因此,试图通过许多依赖于从标准商品模型(如 Resnet18 或-34)进行转移学习的计算机视觉/深度学习管道来摄取灰度将导致各种错误。
解决方案
给灰度添加两个额外的通道!有很多方法可以做到这一点,所以我的方法如下:将第一层复制到一个新的 3D 阵列的新层中,从而生成一个彩色图像(黑白的,所以它仍然是 B&W)。
我将使用来自阿拉伯手写数字数据集的一个正方形图像作为例子。形状为(28, 28)
,确认为单通道图像。
matplotlib defaults grayscales as above
因为我想把它输入到一个基于 Resnet34 的模型中,所以我需要三个通道。
显而易见(但不太正确)的方法是添加两个相同大小的零数组:
dim = np.zeros((28,28))R = np.stack((O,dim, dim), axis=2)
O
是我们最初的阵列。我们可以很容易地将两个相同形状的零阵列相加,但我们将得到一个红色为主的图像:
three channels, all values in channel 1
哎呦!我们希望在所有渠道中填充相同的值。不过,在此之前,让我们看看,如果我们将原始数组滚动通过每种非完全 RGB 的可能性,会发生什么:
R, G, B
RG, RB, GB
好了,这是 RGB:
Finally!
仅此而已。
也
附加代码在我的 github 上:www.github.com/matthewarthur。我的 LinkedIn 是 https://www.linkedin.com/in/matt-a-8208aaa/的。打个招呼。
笔记
[1]https://pytorch.org/docs/stable/torchvision/models.html
[2]https://www . cs . Virginia . edu/~ Vicente/recognition/notebooks/image _ processing _ lab . html
[3]numpy 中的索引在这里详细介绍:https://docs . scipy . org/doc/numpy-1 . 10 . 0/user/basics . Indexing . html
变形金刚——你需要的只是关注
通过自我注意和位置编码改进 Seq2Seq 建模的方法
在之前的帖子中,我们讨论了基于注意力的 seq2seq 模型以及它们诞生背后的逻辑。计划是创建一个差不多的 PyTorch 实现故事,但是结果是,PyTorch 文档提供了一个极好的过程这里。所以在这里,我开始我计划中的下一个项目——变压器——,它的工作原理是自我关注。
让我们对基于注意力的模型做一个两行的回顾。它的主要思想是,它接受一个输入序列和与之相关的所有隐藏状态,在输出的每个实例中,它决定输入的哪一部分是有用的,并随后基于此决定输出。通过在编码器和解码器中使用 RNNs 或 LSTMs 中的任一个来捕获顺序性质。
在注意力是你所需要的全部论文中,作者已经表明,这种顺序性质可以通过仅使用注意力机制来捕捉——而不使用 LSTMs 或 RNNs。
在这篇文章中,我们将遵循与上一篇文章相似的结构,从黑盒开始,慢慢地一个接一个地理解每个组件,从而增加整个架构的清晰度。学完本课程后,您将会很好地掌握变压器网络的每个组件,以及它们如何帮助您获得想要的结果。
先修课程:关于注意力网络和其他基于编解码器的模型的基础知识。神经网络和标准化技术。
变压器黑匣子:
Seq2Seq Model
让我们首先了解注意力模型和变压器模型之间的基本异同。两者都旨在使用编码器-解码器方法实现相同的结果。编码器将原始输入序列转换成隐藏状态向量形式的潜在表示。解码器试图使用这个潜在表示来预测输出序列。但是基于 RNN 的方法有一个固有的缺陷。由于顺序计算的基本限制,不可能并行化网络,这使得难以在长序列上训练。这反过来限制了训练时可以使用的批量大小。这已经被变形金刚缓解了,我们很快就会知道怎么做。所以让我们开始吧。
(我想指出,这篇文章有一点额外的阅读和较少的图片,但我会确保阅读尽可能简单。)
背景
transformer 架构继续使用编码器-解码器框架,这是原始注意力网络的一部分——给定一个输入序列,基于上下文创建它的编码,并将基于上下文的编码解码为输出序列。
除了不能并行化的问题之外,致力于改进的另一个重要原因是基于注意力的模型会无意中给序列中更靠近位置的元素更高的权重。虽然这在理解句子各部分的语法结构的意义上可能是有意义的,但是很难找到句子中相距很远的单词之间的关系。
变压器架构
像上一篇文章一样,我们将逐步达到自我关注模型,从基本架构开始,慢慢达到完整的转换器。
如所见,它遵循编码器-解码器设计,同时用自关注层替换 LSTMs,并且使用位置编码来识别顺序性质。需要记住的重要一点是,所有这些组件都是由全连接(FC)层构成的。由于整个架构都是 FC 层,因此很容易将其并行化。
因此,我们现在有以下疑问:
- 输入序列是如何设计的?
- 使用位置编码是如何处理顺序性质的?
- 什么是自我关注?
- 什么是图层规范化?
- 前馈神经网络的设计是怎样的?
- 自我注意层和被掩盖的自我注意层有什么区别?
- Enc-Dec 关注层是什么?
随着我们对每个问题的澄清,这个模型将变得更加清晰。
输入序列
给定一系列记号 x1 、 x2 、 x3 、 … ,输入序列对应于这些记号中的每一个的嵌入。这种嵌入可以像一键编码一样简单。例如,在句子的情况下, x1 、 x2 、 x3 、 … 将对应于句子中的单词。输入的 seq 可以是这些单词中每一个的一键 enc。
位置编码
由于这种新的编码器-解码器架构中没有解释数据顺序性质的组件,因此我们需要注入一些关于序列中令牌的相对或绝对位置的信息。这是位置编码模块的任务。
忽略数学公式,给定标记 x 在位置 i 的嵌入,第I位置的位置编码被添加到该嵌入中。这种位置的注入是这样完成的,使得每个位置编码都不同于任何其他的位置编码。位置 enc 的每个维度对应于一个正弦波长,最终 enc 是这些正弦波在第个点的值。
自我关注
正如《你所需要的只是关注》一书的作者所描述的那样,
这一层的目的是根据序列中的所有其他单词对一个单词进行编码。它将一个单词的编码与另一个单词的编码进行比较,并给出一个新的编码。完成这项工作的方法有点复杂,我将尽量把它分解开来。
给定一个嵌入 x ,它从中学习三个独立的更小的嵌入——查询、键和值。它们有相同的维数。我所说的学习是指在训练阶段、*、 *Wq、Wk、和 Wv 矩阵是基于反向传播的损失来学习的。 x 与这三个矩阵相乘得到查询、键和值嵌入。
为了理解这些术语,让我们把这些词看作有生命的实体。每个单词都想知道其他每个单词对它的重视程度,然后创建一个更好的自身版本来代表这种重视程度。
假设 x1 想知道它相对于 x2 的值。所以就要’查询 ’ x2 。 x2 将以其自身的“关键字”的形式提供答案,然后通过与查询进行点积,该答案可用于获得表示其对 x1 的重视程度的分数。因为两者大小相同,所以这将是一个单一的数字。这一步将对每个单词执行。
现在, x1 将获取所有这些分数并执行 softmax,以确保分数有界,同时还确保分数之间的相对差异得以保持。(还有将 softmax 之前的分数除以 d_model 的平方根的步骤——嵌入维度——以确保在 d_model 是大数的情况下分数太大的情况下梯度稳定。)
这个评分和 softmax 任务由每个单词对照所有其他单词来执行。上图描绘了整个解释的画面,现在会更容易理解。
x1 现在将使用该分数和相应单词的“值”来获得其自身相对于该单词的新值。如果单词与 x1 不相关,那么分数将会很小,并且相应的值将会作为该分数的一个因子而减少,并且类似地,重要单词将会得到其值的分数支持。
最后,字 x1 将通过对接收到的值求和来为自己创建新的值*。这将是这个词的新嵌入。*
但是自我关注层比这要复杂一点。transformer 架构为这一层增加了多头关注。一旦这个概念清晰了,我们将会更接近最终的变压器设计。
多头注意力
使用相同的原始 x1 、 x2 等来学习多个这样的查询、关键字和值集合*。嵌入。自关注步骤分别在每个集合上执行,新嵌入v’1、v’2等。为每个集合创建。然后将这些连接起来,并与另一个学习矩阵 Z (其被联合训练)相乘,这将这些多个嵌入减少为针对x’1、x’2等的单个嵌入。这就是为什么这被称为多头注意力,每个 v '代表自我注意力模型的一个头。*
这种设计的直观原因是每个头在不同的上下文中查看原始嵌入,因为每个 Q、K、V 矩阵在开始时被随机初始化,然后基于训练期间反向传播的损失被修改。因此最终的嵌入是在同时考虑各种上下文的情况下学习的。
因此,在自我关注这一节的最后,我们看到自我关注层将位置注入的原始嵌入形式作为输入,并输出更多的上下文感知嵌入。这样,我们就解决了上述问题中最困难的部分。
图层规范化
Normalization Techniques[2]
图层归一化的关键特征是它对所有特征的输入进行归一化,不同于批量归一化,批量归一化对所有特征进行归一化。批量定额的缺陷在于它对批量大小施加了一个下限。在层规范中,统计数据是跨每个特征计算的,并且独立于其他示例。实验证明,它的性能更好。**
在变形金刚中,层标准化是通过残差完成的,允许它保留来自前一层的某种形式的信息。
前馈神经网络
每个编码器和解码器模块包含一个前馈神经网络。它由两个线性层组成,其间有一个 relu 激活。它被分别且相同地应用于每个位置。因此,它的输入是一组嵌入x’1*、x’2等等。并且输出是另一组嵌入 x’'1 、 x’'2 等。映射到整个语言共有的另一个潜在空间。*
这样,网络的编码器端就应该清楚了。现在,我们只剩下两个问题,我们开始时的问题——掩盖的自我注意和编码注意。
伪装的自我关注
在任何位置,一个词可能既依赖于它前面的词,也依赖于它后面的词。在《我看见 ______ 在追一只老鼠》中。我们会直观地填写 cat,因为这是最有可能的一个。因此,在对一个单词进行编码时,它需要知道整个句子中的所有内容。这就是为什么在自我关注层中,查询是用所有单词对所有单词进行的。但是在解码时,当试图预测句子中的下一个单词时(这就是为什么我们对解码器输入使用移位的输入序列),逻辑上,它不应该知道在我们试图预测的单词之后出现的单词是什么。因此,所有这些嵌入都通过乘以 0 来屏蔽,使它们中的任何值都变成 0,并且仅基于使用它之前的单词创建的嵌入来进行预测。
这种屏蔽与输出嵌入偏移一个位置的事实相结合,确保了位置 I 的预测只能依赖于小于 I 的位置处的已知输出。
编码器-解码器注意
如果你仔细观察上面的网络,来自编码器模块的输入来自这一层的编码器。在此之前,解码器已经使用了从先前的预测中可以获得的任何信息,并且学习了那些单词的新嵌入。在这一层,它使用编码器来更好地理解上下文和原始序列中的完整句子。它是怎么做到的?
解码器利用原始序列中单词的编码嵌入来查询所有现有单词,这些单词携带位置信息以及上下文信息。新的嵌入现在被注入该信息,并且输出序列现在基于该信息被预测。
至此,我们已经弄清楚了 transformer 架构,但是还有一个部分我还没有指定。
编码器-解码器堆栈
这是我们到目前为止拥有的变压器的架构。我们需要注意的是,编码器的输出是原始嵌入的改进版本。因此,我们应该能够通过添加更多来进一步改进它。这是变压器网络最终设计中要考虑的一点。
最初的架构有 4 个这样的编码器和解码器。只有最终编码器的输出被用作解码器输入。
结论
我们从变压器的基本设计开始,在单个编码器和解码器集中包含不同的层。然后,我们了解了每一层如何工作的细节。在此期间,我们还讨论了自我关注层的多头架构。一旦编码器和解码器都清楚了,我们就进入架构的最后一部分,编码器-解码器堆栈。
这就完成了变压器架构的详细设计。我希望这有所有的细节,需要理解完整的图片。基于变换器的网络的最普遍的例子之一是用于自然语言处理任务的 BERT 模型。
我还没有涉及网络的训练和预测细节,因为这将需要另一个完整的帖子,这对我来说很容易是更有趣和复杂的部分。在下一篇文章中,我将讲述我们如何使用变形金刚来处理图像和无监督学习的任务。
我希望你觉得这很有用并且容易理解。如果有任何更正或任何形式的反馈,我希望收到您的来信。请在这里评论,让我知道或发电子邮件给我@ catchpranay@gmail.com
参考资料:
[1]瓦斯瓦尼、阿希什等人,“你所需要的只是注意力。”(2017),神经信息处理系统进展。2017.
[2]吴,庾信,,何。“分组规范化。”(2018),《欧洲计算机视觉会议论文集(ECCV)* 。2018.*
* [## 第 1 天和第 2 天:注意— Seq2Seq 型号
序列对序列(abrv。Seq2Seq)模型是深度学习模型,已经在一些任务中取得了很大的成功,比如…
medium.com](https://medium.com/@catchpranay/day-1-2-attention-seq2seq-models-65df3f49e263) [## 翻译与序列到序列网络和注意力- PyTorch 教程 1.1.0…
类似于字符级 RNN 教程中使用的字符编码,我们将用一个…
pytorch.org](https://pytorch.org/tutorials/intermediate/seq2seq_translation_tutorial.html) [## 什么是变压器?
机器学习中的变压器和序列对序列学习介绍
medium.com](https://medium.com/inside-machine-learning/what-is-a-transformer-d07dd1fbec04) [## 图示的变压器
讨论:黑客新闻(65 分,4 条评论),Reddit r/MachineLearning (29 分,3 条评论)翻译…
jalammar.github.io](https://jalammar.github.io/illustrated-transformer/) [## 深度学习中的规范化方法综述
深度学习中的规范化一直是热门话题。获得正确的标准化可能是…
mlexplained.com](https://mlexplained.com/2018/11/30/an-overview-of-normalization-methods-in-deep-learning/)*
Transformer-XL 解释:将 Transformer 和 RNNs 结合成一个最先进的语言模型
“Transformer-XL:固定长度上下文之外的注意力语言模型”摘要
语言建模已经成为一种重要的 NLP 技术,这要归功于它能够应用于各种 NLP 任务,例如机器翻译和主题分类。今天,有两种主要的语言建模架构——递归神经网络(RNNs)和转换器。前者逐个处理输入的单词或字符,以了解它们之间的关系,而后者接收一段标记,并使用注意机制立即了解它们之间的依赖关系。
尽管这两种体系结构都取得了令人印象深刻的成就,但它们的主要限制是捕获长期依赖,例如,使用文档开头的重要单词来预测后续部分中的单词。谷歌和卡耐基梅隆大学的一篇新论文“Transformer-XL :固定长度上下文之外的专注语言模型”结合了这两种方法。新模型在输入数据的每个片段上使用转换器的注意力模块,并使用递归机制来学习连续片段之间的依赖性。
Transformer-XL 在多种语言建模数据集上实现了最先进的(SOTA)结果,如 enwik8(单词级)和 text8(字符级),同时在推理过程中明显快于之前的 SOTA Transformer 架构(300x-1800x)。
背景——变形金刚
一种流行的语言建模方法是递归神经网络(RNNs),因为它们可以很好地捕捉单词之间的依赖关系,特别是在使用像 LSTM 这样的模块时。然而,由于消失梯度,rnn 往往很慢,并且它们学习长期依赖性的能力仍然有限。
2017 年发明的变形金刚,引入了一种新方法——注意力模块。注意力模块不是一个接一个地处理令牌,而是接收一段令牌,并使用三个学习到的权重矩阵(查询、关键字和值)一次性学习所有令牌之间的依赖关系,这三个权重矩阵形成了注意力头。Transformer 网络由多个层组成,每个层都有几个注意力头(和附加层),用于学习令牌之间的不同关系。
与许多 NLP 模型一样,输入标记首先被嵌入到向量中。由于注意力模块中的并发处理,该模型还需要添加关于标记顺序的信息,这一步骤称为位置编码,有助于网络了解它们的位置。一般来说,这个步骤是用正弦函数完成的,该函数根据令牌的位置生成一个矢量,而不需要任何学习参数。
An example of a single Attention Head on a single token (E1). Its output is calculated using its Query vector, and the Key and Value vectors of all tokens (In the chart we show only one additional token E2) — The Query and the Key define the weight of each token, and the output is the weighted sum of all Value vectors.
注意:关于变形金刚的深入评论可以在 Jay Alammar 伟大的博客文章中找到。
虽然最初的转换器用于机器翻译(带有编码器-解码器机制), Al-Rfou 等人提出了一种语言建模的架构。它的目标是根据其先前的字符预测一个段中的字符,例如,它使用 X1 … Xn-1 预测字符 Xn ,而右边的下一个字符被屏蔽(见下图)。这种 64 层的变压器模型限于 512 个字符的相对较短的输入,因此它将输入分割成段,并分别从每个段中学习。为了在评估中处理较长的输入,它通过在每一步中将输入移动一位来一次预测一个字符。
Training and Evaluation of the vanilla Transformer language model. Source: Transformer-XL
在流行的基准测试(enwik8 和 text8)中,该模型优于 RNN 模型,但是,它仍然有两个缺点:
- 有限的上下文相关性-字符之间的最大相关性距离受限于输入的长度。例如,模型不能“使用”几个句子前出现的一个单词。
- 上下文分段—对于长度超过 512 个字符的文本,该长度的每个片段都是从头开始单独训练的。因此,对于每个片段的第一个标记以及片段之间,根本不存在上下文(依赖性)。这导致低效的训练,并可能影响模型性能。
Transformer-XL 的工作原理
Transformer-XL 在很大程度上依赖于 vanilla Transformer (Al-Rfou 等人),但引入了两种创新技术——递归机制和相对位置编码——来克服 vanilla 的缺点。相对于普通转换器的另一个优点是,它可以用于单词级和字符级语言建模。
重现机制
重现机制的目标是通过使用来自先前分段的信息来实现长期依赖性。与普通版本类似,Transformer-XL 处理第一段标记,但保留隐藏层的输出。当处理下面的段时,每个隐藏层接收两个输入:
- 该段的前一个隐藏层的输出,如普通版本(下图中的灰色箭头)。
- 前一段(绿色箭头)中的前一个隐藏层的输出,允许模型创建长期依赖关系。
从技术上讲,这两个输入被连接起来,然后用于计算当前段(的当前层的当前头)的键和值矩阵。这种添加为网络提供了关于每个令牌的权重(重要性)的更多信息,但是它没有改变值矩阵。
Training and Evaluation of the Transformer-XL language model. Source: Transformer-XL
通过以相同的方式(在 GPU 存储器的限制下)使用来自几个先前段的信息,甚至仅在评估期间,可以扩展该概念以包含更长的依赖性。
递归机制的另一个优点是其评估速度——在每一步中,它可以前进整个段(而不是像普通版本中那样前进一个令牌),并使用先前段的数据来预测当前段令牌。
相对位置编码
递归机制也带来了新的挑战—原始的位置编码分别处理每个段,因此,来自不同段的令牌具有相同的位置编码。例如,第一段和第二段的第一个标记将具有相同的编码,尽管它们的位置和重要性不同(来自第一段的标记可能较低)。这种混淆可能会错误地影响网络。
相反,本文提出了一种新的位置编码,它是每个注意模块的一部分,而不是仅在第一层之前对位置进行编码,并且基于标记之间的相对距离而不是它们的绝对位置。从技术上来说,它扩展了注意力头部得分(Qi ⋅ Kj)的简单相乘,以包括四个部分:
- 内容权重-原始分数,当然没有添加原始位置编码。
- 相对于当前内容的位置偏差(Qi)。它使用类似的正弦函数来接收记号之间的距离(例如 i-j ,而不是当前记号的绝对位置。
- 学习的全局内容偏差-该模型添加了调整其他令牌内容(Kj)的重要性的学习向量。
- 学习的全局偏差-另一个学习的向量,其仅基于记号之间的距离来调整重要性(例如,最后的先前单词可能比先前段落中的单词更重要)。
结果
作者比较了该模型在单词级和字符级数据集上的性能,并将其与其他著名模型(RNNs 和 Transformers)进行了比较。Transformer-XL 在几个不同的数据集基准上取得了最先进的(SOTA)结果:
- 在大型词级数据集 WikiText-103 上,18 层 Transformer-XL (257M 参数)达到了 18.3 的困惑度,而之前的 SOTABaevski&Auli达到了 20.5。
- 在字符级数据集 enwik8 上,12 层 Transformer-XL 达到了每字符 1.06 位(bpc),与之前由 Al-Rfou 等人使用六倍多参数的 SOTA 结果相似。24 层 Transformer-XL 实现了 0.99 bpc 的新 SOTA。
- 有趣的是,该模型还在只有短期依存关系的数据集上实现了 SOTA 结果-10 亿个单词只有单个句子-以及在小数据集- Penn Treebank 只有 100 万个令牌。这表明该模型在这些情况下也可能是有效的。
在下面的图表中可以看到递归机制和相对位置编码的好处。它比较了不同上下文长度(注意头中使用的先前标记的数量)的无重现或新编码的困惑分数。完整的 Transformer-XL 明显优于其他产品,并且能够利用更长期的依赖性。此外,它还能够捕获比 RNN 更长的依赖关系(长 80%)。
Transformer-XL ablation study. Source: Transformer-XL
最后,如前所述,该模型在推理过程中也比普通的转换器快得多,尤其是对于较长的上下文。例如,对于长度为 800 个字符的上下文,速度提高了 363 倍,对于长度为 3,800 个字符的上下文,速度提高了 1,874 倍。
实施细节
该模型是开源的,并且在 TensorFlow 和 PyTorch 中均实现(包括预训练的模型)。没有指定每个数据集的训练持续时间。
结论
Transformer-XL 展示了几种不同数据集(大/小、字符/单词等)上语言建模的最新结果。它结合了深度学习的两个突出概念——重现和注意力——允许该模型学习长期依赖关系,并可能对需要这种能力的深度学习的其他领域有效,如音频分析(例如每秒 16k 样本的语音数据)。
该模型尚未在情感分析或问题回答等 NLP 任务上进行测试,与其他基于 Transformer 的模型(如 BERT )相比,这种强语言模型的优势是什么仍然是一个开放的问题。
关注深度学习最新研究,订阅我的简讯 LyrnAI
变压器如何工作
Open AI 和 DeepMind 使用的神经网络
如果你喜欢这篇文章,并想了解机器学习算法是如何工作的,它们是如何产生的,它们将走向何方,我推荐以下内容:
[## 让事物思考:人工智能和深度学习如何为我们使用的产品提供动力
这是显而易见的,但大多数时候却很难看到。人们说‘这和你脸上的鼻子一样明显。’…
www.holloway.com](https://www.holloway.com/g/making-things-think)
变压器是一种越来越受欢迎的神经网络架构。变形金刚最近被 OpenAI 用于他们的语言模型,最近也被 DeepMind 用于阿尔法星——他们击败顶级职业星际玩家的程序。
变形金刚是为了解决 序列转导或神经机器翻译的问题而开发的。这意味着将输入序列转换成输出序列的任何任务。这包括语音识别、文本到语音转换等…
Sequence transduction. The input is represented in green, the model is represented in blue, and the output is represented in purple. GIF from 3
对于执行序列转导的模型来说,有某种记忆是必要的。例如,假设我们将下面的句子翻译成另一种语言(法语):
“变形金刚”是一支日本[[硬核朋克]]乐队。该乐队成立于 1968 年,正值日本音乐史上的鼎盛时期
在本例中,第二句中的单词“the band”指的是第一句中介绍的乐队“The Transformers”。当你读到第二句中的乐队时,你知道它指的是“变形金刚”乐队。这对翻译可能很重要。有很多例子,有些句子中的词引用了前面句子中的词。
为了翻译这样的句子,模型需要找出这种依赖和联系。由于递归神经网络(RNNs)和卷积神经网络(CNN)的特性,它们已经被用来处理这个问题。让我们回顾一下这两种架构及其缺点。
递归神经网络
递归神经网络中有环路,允许信息持续存在。
The input is represented as x_t
**在上图中,我们看到神经网络的一部分, **A,处理一些输入 x_t 和输出 h_t,一个循环允许信息从一个步骤传递到下一个步骤。
这些循环可以用不同的方式来思考。一个递归神经网络可以被认为是同一个网络的多个副本,一个,每个网络传递一个信息给下一个。考虑一下如果我们展开循环会发生什么:
An unrolled recurrent neural network
这种链状性质表明,递归神经网络与序列和列表明显相关。这样,如果我们想要翻译一些文本,我们可以将每个输入设置为该文本中的单词。递归神经网络将前面单词的信息传递给下一个可以使用和处理该信息的网络。
下图显示了序列到序列模型通常如何使用递归神经网络工作。每个单词被单独处理,通过将隐藏状态传递给解码阶段来生成结果句子,然后解码阶段生成输出。
GIF from 3
长期依赖的问题
考虑一个语言模型,它试图根据前面的单词预测下一个单词。如果我们试图预测句子“天空中的云”的下一个单词,我们不需要进一步的上下文。很明显,下一个词将会是天空。****
在这种情况下,相关信息和需要的地方之间的差异很小,RNNs 可以学习使用过去的信息,并找出这个句子的下一个单词是什么。
Image from 6
但是有些情况下我们需要更多的上下文。比如说你在试着预测课文的最后一个单词:“我在法国长大…我说得很流利…”。最近的信息表明,下一个单词可能是一种语言,但如果我们想缩小哪种语言的范围,我们需要法国的上下文,那是在文本的更后面。
Image from 6
当相关信息和需要信息的点之间的差距变得非常大时,rnn 变得非常无效。这是因为信息是在每一步传递的,链越长,信息就越有可能沿着链丢失。
理论上,RNNs 可以学习这种长期依赖性。在实践中,他们似乎不学他们。LSTM,一种特殊类型的 RNN,试图解决这种问题。
长短期记忆(LSTM)
当安排一天的日程时,我们会优先安排我们的约会。如果有什么重要的事情,我们可以取消一些会议,把重要的事情放在一边。
RNNs 不会这么做的。每当它添加新信息时,它通过应用一个函数来完全转换现有信息。整个信息都被修改,没有考虑什么重要什么不重要。
LSTMs 通过乘法和加法对信息进行小的修改。在 LSTMs 中,信息通过一种称为单元状态的机制流动。通过这种方式,LSTMs 可以选择性地记住或忘记重要的和不那么重要的事情。
在内部,LSTM 看起来如下:
Image from 6
每个单元将输入 x_t (在句子到句子翻译的情况下是一个单词)、前一个单元状态和前一个单元的输出** 作为输入。它处理这些输入,并基于它们生成新的细胞状态和输出。我不会详细讨论每个细胞的结构。如果你想了解每个细胞是如何工作的,我推荐克里斯托弗的博文:**
**[## 了解 LSTM 网络——colah 的博客
这些循环使得循环神经网络看起来有点神秘。然而,如果你想得更多一点,事实证明…
colah.github.io](http://colah.github.io/posts/2015-08-Understanding-LSTMs/)**
利用单元状态,在翻译时,句子中对于翻译单词来说重要的信息可以从一个单词传递到另一个单词。
LSTMs 的问题是
通常发生在 rnn 上的同样的问题也会发生在 lstm 上,也就是说,当句子太长时,lstm 仍然做得不太好。其原因是,保持远离当前正在处理的单词的单词的上下文的概率随着离它的距离而指数下降。
这意味着当句子很长时,模型经常会忘记序列中远处位置的内容。RNNs 和 LSTMs 的另一个问题是很难并行处理句子,因为你必须一个字一个字地处理。不仅如此,也没有长期和短期依赖关系的模型。总之,LSTMs 和 RNNs 存在 3 个问题:
- 顺序计算抑制了并行化
- 没有长短期依赖关系的显式建模
- 位置之间的“距离”是线性的
注意力
为了解决其中的一些问题,研究人员创造了一种关注特定单词的技术。
翻译句子时,我会特别注意我正在翻译的单词。当我转录一段录音时,我会仔细听我主动写下的片段。如果你让我描述我正坐的房间,我会一边描述一边扫视周围的物体。
神经网络可以使用 注意力 实现同样的行为,专注于它们被给予的信息子集的一部分。例如,一个 RNN 可以参与另一个 RNN 的输出。在每一个时间步,它聚焦于另一个 RNN 的不同位置。
为了解决这些问题,注意力是一种在神经网络中使用的技术。对于 RNNs 来说,每个单词都有一个相应的隐藏状态,并一直传递到解码阶段,而不是仅以隐藏状态对整个句子进行编码。然后,在 RNN 的每一步使用隐藏状态进行解码。下面的 gif 展示了这是如何发生的。
The green step is called the encoding stage and the purple step is the decoding stage. GIF from3
其背后的想法是,一个句子中的每个单词都可能有相关的信息。所以为了解码精确,它需要考虑输入的每个单词,使用注意力。****
为了在序列转导中引起对 RNNs 的注意,我们将编码和解码分成两个主要步骤。一步用绿色的表示,另一步用紫色的表示。绿色的步骤被称为编码阶段**,紫色的步骤是解码阶段。******
GIF from 3
绿色部分负责从输入中创建隐藏状态。我们不是像使用 attention 之前那样只将一个隐藏状态传递给解码器,而是将句子的每个“单词”生成的所有隐藏状态传递给解码阶段。每个隐藏状态在解码阶段使用,以计算出网络应该注意的地方。
例如,当将句子“**Je suisétudiant”**翻译成英语时,要求解码步骤在翻译时查看不同的单词。
This gif shows how the weight that is given to each hidden state when translating the sentence “Je suis étudiant” to English. The darker the color is, the more weight is associated to each word. GIF from 3
例如,当你翻译句子“1992 年 8 月欧洲经济区协议”从法语到英语,以及对每个输入的重视程度。
Translating the sentence “L’accord sur la zone économique européenne a été signé en août 1992.” to English. Image from 3
但是我们讨论过的一些问题,仍然没有通过使用注意力的 RNNs 得到解决。例如,并行处理输入(单词)是不可能的。对于大型文本语料库,这增加了翻译文本所花费的时间。
卷积神经网络
卷积神经网络有助于解决这些问题。有了他们,我们可以
- 并行化很简单(每层)
- 利用本地依赖性
- 位置之间的距离是对数的
一些最流行的用于序列转导的神经网络 Wavenet 和 Bytenet 是卷积神经网络。
Wavenet, model is a Convolutional Neural Network (CNN). Image from 10
卷积神经网络可以并行工作的原因是输入的每个单词可以同时处理,而不一定依赖于要翻译的前面的单词。不仅如此,对于一个 CNN 来说,输出单词与任何输入之间的“距离”依次为【log(N)——也就是从输出到输入生成的树的高度大小(你可以在上面的 GIF 上看到。这比一个 RNN 的输出和一个输入的距离要好得多,后者的数量级为T5【N。
问题是,卷积神经网络不一定有助于解决翻译句子时的依赖问题。这就是为什么变形金刚被创造出来,它们是两个 CNN 与关注的结合。
变形金刚(电影名)
为了解决并行化问题,Transformers 试图通过使用卷积神经网络和**注意力模型来解决问题。**注意力提高了模型从一个序列转换到另一个序列的速度。
我们来看看变压器是怎么工作的。Transformer 是一个利用注意力来提升速度的模型。更具体地说,它使用了自我关注。
The Transformer. Image from 4
从内部来看,Transformer 的体系结构与前面的模型类似。但是转换器由六个编码器和六个解码器组成。
Image from 4
每个编码器都非常相似。所有编码器都具有相同的架构。解码器共享相同的属性,即它们彼此也非常相似。每个编码器包括两层:自关注和一个前馈神经网络。
Image from 4
编码器的输入首先流经自关注层。它帮助编码器在对特定单词进行编码时查看输入句子中的其他单词。解码器有这两层,但在它们之间有一个注意力层,帮助解码器关注输入句子的相关部分。
Image from 4
自我关注
**注:**此部分来自 Jay Allamar 博客文章
让我们开始看看各种向量/张量,以及它们如何在这些组件之间流动,以将训练模型的输入转化为输出。正如 NLP 应用程序中的一般情况一样,我们首先使用嵌入算法将每个输入单词转换成一个向量。
Image taken from 4
每个单词被嵌入到大小为 512 的向量中。我们将用这些简单的盒子来表示这些向量。
嵌入只发生在最底层的编码器中。所有编码器共有的抽象是它们接收每个大小为 512 的向量列表。
在底部的编码器中,这将是单词嵌入,但在其他编码器中,这将是直接在下面的编码器的输出。在我们的输入序列中嵌入单词后,它们中的每一个都流经编码器的两层中的每一层。
Image from 4
在这里,我们开始看到转换器的一个关键属性,即每个位置的字在编码器中通过自己的路径流动。在自我关注层,这些路径之间存在依赖关系。然而,前馈层没有这些依赖性,因此各种路径可以在流经前馈层时并行执行。
接下来,我们将把这个例子换成一个更短的句子,看看编码器的每个子层发生了什么。
自我关注
让我们首先看看如何使用向量来计算自我注意力,然后继续看看它实际上是如何实现的——使用矩阵。
Figuring out relation of words within a sentence and giving the right attention to it. Image from 8
计算自我注意力的第一步是从编码器的每个输入向量中创建三个向量(在这种情况下,是每个单词的嵌入)。因此,对于每个单词,我们创建一个查询向量、一个键向量和一个值向量。这些向量是通过将嵌入乘以我们在训练过程中训练的三个矩阵而创建的。
请注意,这些新向量的维数小于嵌入向量。它们的维数是 64,而嵌入和编码器输入/输出向量的维数是 512。它们不一定要更小,这是一种架构选择,以使多头注意力的计算(大部分)保持不变。
Image taken from 4
将 x1 乘以 WQ 权重矩阵产生 q1,即与该单词相关联的“查询”向量。我们最终创建了输入句子中每个单词的“查询”、“键”和“值”投影。
什么是“查询”、“键”和“值”向量?
它们是对计算和思考注意力有用的抽象概念。一旦你开始阅读下面的注意力是如何计算的,你就会知道你所需要知道的关于这些向量所扮演的角色。
计算自我关注度的第二步是计算一个分数。假设我们在计算这个例子中第一个词“思考”的自我关注度。我们需要将输入句子中的每个单词与这个单词进行比较。分数决定了当我们在某个位置对一个单词进行编码时,对输入句子的其他部分的关注程度。
分数是通过查询向量与我们正在评分的相应单词的关键向量的点积来计算的。因此,如果我们正在处理位置#1 的单词的自我注意,第一个分数将是 q1 和 k1 的点积。第二个分数是 q1 和 k2 的点积。
Image from 4
第三和第四步是将分数除以 8(文中使用的关键向量的维数的平方根— 64。这导致具有更稳定的梯度。这里可能有其他可能的值,但这是默认值),然后通过 softmax 操作传递结果。Softmax 将分数标准化,因此它们都是正数,加起来等于 1。
Image from 4
这个 softmax 分数决定了每个单词在这个位置将被表达多少。显然,在这个位置的单词将具有最高的 softmax 分数,但是有时关注与当前单词相关的另一个单词是有用的。
第五步是将每个值向量乘以 softmax 分数(准备将它们相加)。这里的直觉是保持我们想要关注的单词的值不变,并淹没不相关的单词(例如,通过将它们乘以像 0.001 这样的小数字)。
第六步是对加权值向量求和。这就在这个位置产生了自我关注层的输出(针对第一个单词)。
Image from 4
自我关注的计算到此结束。得到的向量是我们可以发送给前馈神经网络的向量。然而,在实际实现中,这种计算是以矩阵形式进行的,以便更快地处理。现在让我们来看看,我们已经看到了单词级别的计算的直觉。
多头注意力
变形金刚基本就是这样工作的。还有一些其他细节使它们工作得更好。例如,变形金刚不是只在一个维度上关注彼此,而是使用了多头关注的概念。
其背后的想法是,每当你翻译一个单词时,你可能会根据你所提问题的类型对每个单词给予不同的关注。下图显示了这意味着什么。例如,每当你在翻译“我踢了球”这句话中的“kicked”时,你可能会问“谁踢了”。根据不同的答案,这个词的另一种语言的翻译会有所不同。或者问其他问题,比如“做了什么?”等等…
Images from 8
位置编码
转换器的另一个重要步骤是在对每个单词进行编码时添加位置编码。编码每个单词的位置是相关的,因为每个单词的位置与翻译相关。
概观
我概述了变压器是如何工作的,以及为什么这是用于序列转导的技术。如果你想深入了解这个模型的工作原理及其所有的细微差别,我推荐下面的帖子、文章和视频,我把它们作为总结这个技术的基础
- 递归神经网络的不合理有效性
- 了解 LSTM 网络
- 可视化神经机器翻译模型
- 图示变压器
- 变压器——你只需要关注
- 带注释的变压器
- 注意力是你所需要的全部注意力神经网络模型
- 生成模型的自我关注
- OpenAI GPT-2:通过可视化理解语言生成
- WaveNet:原始音频的生成模型
递归转换 BigQuery JSON API 响应
从字段/值行嵌套构建键值对
La Sagrada Familia, Barcelona, by Paolo Nicolello.
跟我一起说:“嵌套的 JSON 很难用!”。我说的对吗?当然可以!既然我们已经说清楚了,我只想说我完全相信 JSON。它是合乎逻辑的,是通用的,大多数语言都用它来创建快速访问的散列映射风格的数据结构。所有人的胜利!
直到你筑巢。
一群相信嵌套 JSON 的好处的人和那些相信扁平 JSON 是他们选择 API 有效负载幸福的圣杯的人。这场无声的战斗如此激烈,以至于许多扁平化技术充斥着黑客的宝库,如 递归方式 和 非递归方式 等方法。
递归地飞越巢穴
看过电影盗梦空间?这是个好东西。时间线中的时间线。当一切恢复时,你会看到事情是如何组合在一起的。以类似的方式,递归在代码中占用的空间很小,但是可以处理巨大的计算(理解为“嵌套”)复杂性。
好了,够了,让我们开始吧!
BigQuery 的查询 API 返回 JSON
这是 Google BigQuery 在执行查询后的 API 响应示例:
BigQuery’s query API result looks like this
该模式向您展示了数据是如何构造的,并且各行用字段的**“f”和值的“v”来表示哪些值适合该模式。**
现在,看起来像这样的 JSON 不是更容易阅读和操作吗?
Transformed BigQuery result into something more manageable
如果你同意,那么你会得到很好的照顾。
解决方案
下面是进行这种转换的 node.js 代码。请随意使用它,根据您的需求进行调整,通常会让您的生活更简单,让您的数据更快乐。该功能的界面是:
convertBQToMySQLResults(schema, rows)
您可以像这样传递 BigQuery 结果:
// apiResponse is the payload you receive from a BigQuery query API // responseconvertBQToMySQLResults(apiResponse.schema.fields, apiResponse.rows)
JsFiddle 演示
下面是一个 JsFiddle 代码演示:
概括起来
JSON 的很多转换都存在。递归解决方案不是最容易调试的,但是它们有最简单的代码足迹。用调试器单步调试代码是以“慢动作”方式查看此类算法的首选方式。本文提供了一种将源自 Google BigQuery 的复杂嵌套 JSON 简化为您可以自己操作和使用的东西的方法。试试吧!快乐转换!
为机器学习预测中的可用性转换分类数据
使用邮政编码、纬度和经度的快速示例
凯文·维拉斯科&亚历克斯·什罗普郡
给定华盛顿州金县 2014 年至 2015 年(【https://www.kaggle.com/harlfoxem/housesalesprediction】T2)的房屋销售数据集,我们的任务是创建一个模型来准确预测房屋销售价格。经过最初的数据探索和清理,我们发现了大量描述房屋质量的有用信息,但没有多少关于位置的有用信息。
Aerial photo of Seattle by Thatcher Kelley
为什么位置对我们的数据集很重要
我们都听说过被过度使用的短语“位置,位置,位置”作为房地产市场评估的中心主题。人们普遍认为这是决定一个人应该住在哪里的最重要的因素。价格和位置往往与买家密切相关。任何房屋的条件、价格和大小都可能改变。唯一不变的是房子的位置。
以我们数据集的邮政编码特征为例:
在其当前形式中,在“邮政编码”列中有 70 个唯一的分类值,机器学习模型无法提取每个邮政编码中包含的任何有用信息来评估与价格的关系。在每一个类别中都存在一个有意义的房地产因素的独特选择,如公园、学校、咖啡馆、商店、杂货店、公共交通和主要道路。所有这些都是主要因素,可以表明西雅图的沃灵福社区与亚基马山谷中部的住宅之间的内在差异。揭示邮政编码在价格方面的内在品质对于纳入我们的价格预测模型非常重要,因此我们必须适应以保持类别的力量。
快速浏览一下上面的信息,很明显我们需要设计新的功能来理解邮政编码,以及经度和纬度!
转换和理解分类数据
我们以独特的方式正确应用纬度和经度信息的方法包括创建一个功能来测量到贝尔维尤和西雅图这两个主要经济中心的距离,以便改进我们的价格预测。我们没有通过创建一个数学函数来重新发明轮子,而是决定通过下图所示的哈弗辛公式来计算距离:
Example of the Haversine function
哈弗辛模块(https://pypi.org/project/haversine/)为我们节省了大量时间。Haversine 接受两个纬度和经度元组,并计算特定单元中两个地理点之间的地理距离。我们假设房价与西雅图市中心和贝尔维尤市中心地区之间存在显著关系,选择这两个地区是因为它们是该地区最大的就业中心&和经济活动中心。我们认为缩短通勤时间和方便获取大城市的资源通常会增加需求,从而提高价格。
对于这个公式,我们需要转换每栋房子的坐标。给定单独列中的纬度和经度,我们应用 zip 函数创建一个新的坐标元组列:
利用数据集中每个家庭的单点,以及两个参考点,哈弗辛公式的所有变量都被创建。事实证明,将函数直接应用到现有数据框架的新列中是很棘手的。为了创建一个指示距离的新列,我们必须从列表数据类型创建一个 Pandas 系列,然后将其添加到现有的 Dataframe 中。
最后,我们创建了另一个列,它选择两点之间的最小距离作为“距离震中”列的输入。这一步对于获取这两个城市的邻近信息非常重要,以确保我们对到经济中心的最短距离的解释为我们的模型解释做好准备。
对于邮政编码,我们实现了 one hot encoding pd.get_dummies()方法,通过该方法,分类变量被转换成可以提供给 ML 算法的形式,以便更准确地预测价格。就我们的数据而言,我们希望获得邮政编码的一个类别,并将其转换为二进制 yes[1],这一行是该邮政编码的成员,或者 no[0],它不是。邮政编码的庞大数量起初似乎令人担忧,给我们的数据框架增加了许多列:
但是,通过将 zipcode 特性转换为包含二进制信息的多个列,我们就可以将它作为训练模型的一个特性。为了正确解释我们的模型将为所有列生成的系数,我们首先必须在 pd.get_dummies()方法之后选择一个不同的邮政编码来删除冗余信息。换句话说,我们删除了一个邮政编码列,因为每隔一个邮政编码列出现零表示该行是我们删除的邮政编码的一个成员。该信息是剩余的 n-1 列的二进制形式所固有的。我们选择放弃 98103 的邮政编码,它包括沃灵福德、格林莱克、菲尼岭、格林伍德和弗里蒙特地区。我们选择这个邮政编码是因为它代表了西雅图市中心的一个热门区域,我们希望它能被更广泛的西雅图观众理解为一个价格基准。我们想选择一个既不是比尔·盖茨的邮政编码,也不是更接近相反极端的邮政编码的邮政编码,这样很多其他邮政编码的房屋价格就会高于或低于 98103。最重要的是,整个过程确保了我们得到的系数可以用 98103 个邻域来解释。
我们模型改进工作的结果
经过仔细的数据清理和特征工程,我们的模型包含 10 个预测因子,包括一个初始的“距离西雅图”预测因子。在通过 statsmodels 的普通最小二乘线性回归模型运行数据集后,我们的汇总输出得出了相当不错的 R 平方(一种快速、简便的初始评估模型质量的方法):
Initial OLS Results
在 0.735,我们的情况还不错,但还有改进的空间。意识到 R 平方作为模型质量度量的局限性,为了说明基本模型迭代之前和之后的场景,它可以发挥作用。也就是说,在整合了我们的“距离震中的距离”功能(整合了距离经济中心西雅图市中心和贝尔维尤市中心的距离)后:
adding distance_from_epicenter
令人尊敬的进步!最后,通过使用 one-hot 编码将格式混乱的邮政编码类别转换为有用的数字格式:
adding zipcode
有了这样一个显著的推动,并且取决于业务案例的潜在上下文,我们可能准备好部署我们的预测器或者引入新数据、设计新特性,或者简单地继续在现有数据集内迭代。我们的模型现在得出调整后的 R 平方为 0.876。换句话说,我们的线性模型可以解释 86.7%的响应变量变化。
最后的想法
回顾原始数据集和所提供的信息,最初看起来非常少的关于位置的可操作信息实际上包含了强大的分类邮政编码数据和可转换的纬度和经度数据,一旦每个数据的潜力被释放出来,它们就会对我们的机器学习算法产生巨大的改进。“位置,位置,位置”这句古老的格言在理解一个住宅的市场价格时,似乎仍然具有真正的力量。从这里开始,可以考虑时间、更大的地理界限和来自其他需求影响模式的数据等变量,特别是当房地产/物业技术领域的高增长公司进入分析军备竞赛以成为最有知识的公司时。我知道你们是好人,但我们是为你们而来的。
如需了解项目详情、我们最准确的价格预测代码以及相关幻灯片,请查看我们的 GitHub repos:
亚历克斯·什罗普希尔:
[## as 6140/king county wa _ home _ price _ predictor
通过在 GitHub 上创建一个帐户,为 as 6140/kingcountyWA _ home _ price _ predictor 开发做出贡献。
github.com](https://github.com/as6140/kingcountyWA_home_price_predictor)
凯文·维拉斯科:
[## kevinthedou/DSC-1-final-project-Seattle-ds-career-040119
通过在 GitHub 上创建一个帐户,为 kevinthedou/DSC-1-final-project-Seattle-ds-career-040119 开发做贡献。
github.com](https://github.com/kevintheduu/dsc-1-final-project-seattle-ds-career-040119)
在 Linkedin 上保持联系!
凯文:https://www.linkedin.com/in/kevinrexisvelasco/
亚历克斯:https://www.linkedin.com/in/alexshropshire/
用深度学习翻译肯尼亚手语
Chart showing the Kenyan Sign Language Alphabet
2016 年 7 月,我遇到了 Hudson——一位才华横溢的聋人开发者,他刚刚开发了一款应用,向他的聋人社区教授性健康。我们成了忠实的朋友。从那以后,我的聋人朋友和熟人圈子越来越大。
我甚至有了一个标志名。在聋人社区,从一个独特的特征中给某人分配一个符号比每次用手指拼写他们的名字更容易。但有一个问题,很长一段时间,我无法与这个日益壮大的聋人朋友和熟人圈子很好地沟通,因为我没有学过手语。
与哈德逊和他同样失聪的共同创始人阿尔弗雷德的对话,首先由他们为会议指定的手语翻译进行调解。Hudson 的应用程序和 Sophie bot 是由同一个项目资助的,所以我们有很多这样的项目。
我们的对话变成了在我们每个人的手机笔记或信息应用程序上输入文本。在几次会议和活动中,我让他无法专心听他的翻译,这是我的过错。很快,我们就制定了一个我们都能理解的粗略的手势清单。这些在聋人群体中被称为“乡村手语”。
从那以后,与聋人群体的互动才开始增加。去年 5 月,在微软的 Build 大会上,在一个特别的主题演讲队列边上,一群失聪的开发人员加入了我们,我要求介绍我自己并展示我的签名。幸运的是他们有一个翻译,他帮了忙。去年六月,在肯尼亚海岸的一次活动后,Hudson 让我跟着去参加他朋友的选美比赛。她是选美皇后,也是个聋子。后来我们都出去喝酒了,但我不能完全参与谈话。我只知道如何用手指拼写“GIF ”,我的手语名字,以及如何说“嗨”。
去年 10 月,在我帮助组织的一次会议上,肯尼亚 Droidcon,我们有两个聋人开发者参加,他们带来了两个手语翻译。很明显,宇宙希望我学习手语。
我很自豪地说,我现在可以流利地用手指拼写肯尼亚手语字母,并且我有意每天学一个单词。
我知道这种学习曲线并不是每个人都想与失聪的朋友、家人、同事和熟人更好地交流的解决方案。我们可以利用人工智能技术给我们带来的进步来建立一个工具,让这变得更容易。去年年底,才华横溢的开发人员 Hudson 发布了一个应用程序来教听力正常的人手语,这让我对合适的工具有了直觉。
如果我们能建立一个图像分类器手语翻译器会怎么样?如果我们可以建立一个端到端的手语翻译模型,仅仅使用人们手语的照片,会怎么样?本博客对此进行了调查。
肯尼亚手语翻译的图像分类器
让我们回顾一下我们的目标。我们正试图建立一个应用程序,它使用图像分类器来识别手语,不仅通过看手指的照片,还通过现实生活中的网络摄像头或手机摄像头。这样,我们的应用程序将像人眼一样工作。
这是一个循序渐进的指南,解释了我解决问题的过程。
数据收集和数据标注
Kaggle 数据集
我的第一反应是去 Kaggle 看看是否有数据集存在。
我找到了一个,但都是白色的手指,这是我手指的样子
Physics Gangster sign
哎呦。这可能是行不通的。这是许多数据科学数据集的常见问题。例如,《黑豹》中的角色和演员会得到像这样的面部识别记分卡:
Wakanda Foreeeva!!!
许多研究人员和现在的政治家都指出了数据集的这些固有偏见,这可能导致在这些数据集上训练的模型和算法的偏见。
回到我们的 Kaggle 发现——更糟糕的是,数据集使用的是美国手语。
图像已经矢量化和扁平化,以消除 RGB 层。它不适合我的问题案例。我想要一个端到端的模型,像真实世界的数据一样拍摄半个身体的图像,而不是必须建立一个对象检测层来检测手。
众包深度学习数据集
第二个本能是在我的社交媒体账户上发帖,让我的朋友发送他们用不同字母签名的图片。要么是我的网络圈子里没有人像我一样不热衷于手语,要么是我没有发挥我自认为的那么大的影响力。
自己构建数据集
我不得不自己去工作,自己收集数据。给我拍照,用不同的衬衫和背景签署整个 KSL 字母表。当我每个字母有十张照片时,我不断地在每张照片上添加微小的变换,直到我有了 100 多张照片。快点。
给我的数据集加标签是最简单的部分。把每一个字母放在它自己的目录中,目录的名字会被选作标签
```~/data~/data/A/A (1).jpg~/data/A/A (2).jpg...~/data/Z/Z (1).jpg~/data/Z/Z (2).jpg```
我已经将数据作为 floydhub 数据集上传到这里
选择神经网络
和往常一样,数据集创建和数据标记过程比我预期的要长得多。但是现在我有了一个合适的数据集,是时候开始考虑我可能用于这个项目的神经网络架构和深度学习框架了。
这个社区在快速人工智能和 ResNet 上很大,但我学习了 tensorflow 和 Keras 学习曲线,并在其上加倍下注。
卷积网络是计算机视觉问题的首选网络,但从头训练一个需要大量的数据和时间。所以让我们停止在 keras code labs 上这样做。
我们可以重新训练已经预先训练好的 CNN 的最后一层来进行我们的图像分类。我选择两个预训练的卷积神经网络。Inception,更大、更慢但精度更高的卷积神经网络和 Mobilenets,一种更轻、更快、精度更低的神经网络,旨在运行在移动电话上。
我作为一名移动开发者的背景让我本能地尝试首先开发移动产品。对我来说,我有两个模型的经验,甚至有来自早期“热狗,不是热狗”代码实验室的预定义脚本
预定义的脚本不仅仅是训练模型。他们有代码自动下载预训练重量的计算图表。编写用于评估和调试模型的 tensorboard 摘要日志,将训练好的模型输出为冻结的计算图形。
最后,他们还对我的训练数据进行预处理,对图像进行矢量化,并将矢量值存储在一个文本文件中,该文件的目录结构与训练数据类似。这在用调整的超参数重新训练模型时节省了大量时间。
脚本是由 tensorflow 团队编写的,该团队随后激发了他们的“tensor flow for poets code lab
训练模特
tensorflow 团队精心编写的预定义脚本的额外好处是,我们只需使用适当的超参数运行脚本。对于这个代码实验室,我们将在 floydhub 上进行训练。
使用超参数运行样本
开始
我们对初始模型做同样的事情
首先,我们在本地环境中初始化一个 floydhub 项目:
```bashfloyd init iamukasa/ksl_translator```
然后我们训练这个模型:
```bashfloyd run — env tensorflow-1.9 \ — follow \ — data iamukasa/datasets/ksl/1: data \“python retrain.py — model_dir ./inception — image_dir=/data”```
移动网络
```bashfloyd init iamukasa/ksl_translator_mobilenets```
然后我们训练这个模型
```bashfloyd run — env tensorflow-1.9 \ — follow \ — data iamukasa/datasets/ksl/1:data \“python retrain.py — bottleneck_dir= [path to bottleneck directory] — how_many_training_steps= [number of trainnig steps you want] — output_graph= [path and name of file you want to save .pb file] — output_labels= [ path and name of file you want to save as a .txt file] — image_dir=data”```
为了解释不同的超参数,与 mobilenets 脚本相比,inception 脚本在脚本中定义了更多的默认值。一旦一切都设置好了,瓶颈代码已经如上所示运行,您应该会在终端上看到这样的输出。
*评估我们训练好的模型
预定义的脚本写得非常好,它们会自动在 tensorboard 上写 tensorboard 摘要。您只需在 floydhub 作业仪表板上点击一个按钮,即可直观显示训练迭代的准确性和损失。Floydhub 会生成一个指向您的 tensorboard 摘要的链接:
对于 AI 开发人员来说,没有什么比这两个绘制的图形更令人满意的了,每次训练迭代的准确度趋向于 1,而损失(熵)趋向于 0。这是你做事正确的第一个标志。
有两个不同颜色的图,橙色的是用我们用来训练模型的数据评估损失和准确性的图,蓝色的是用没有用来训练模型的数据评估模型的图。
你可以在 floydhub 这里重现同样的结果
调试我们的模型
1500 次迭代之后,Inception 模型交付了 99.6 %的最终准确性总结。一个非常高的精确度,我怀疑这个模型确实过拟合了。
这是当人工智能模型从你的训练数据中学习得太好时,它不能推广到现实世界的数据。今天,我将保持特定模型不变,并根据现场演示的不同数据进行改进。
企业家所说的 MVP,用更好的现实生活数据不断改进。
初始阶段最终总结:
然而,mobilenets 的实现提出了一个不同的挑战。与初始模型相同的超参数交付了 100%的最终准确性总结
该模型明显过拟合,并且在迭代 22 时过早过拟合
在这种情况下,大多数人工智能研究人员会提高数据质量,引入更多的变异。引入一个丢弃层,每当模型过拟合时,就删除一半的突触。
在那个时候,这两种选择对我来说都不可行,所以我做了一些我不鼓励你做的事情。我用更少的迭代重新训练了模型。
而不是让我的训练迭代达到 100%准确的总结。
黑客攻击后的最终总结
部署到现实世界
如果我不把模型放在现实生活的用例中,所有这些工作和准确性都将是浪费。我开始使用分类器来翻译来自我的网络摄像头的直播。
将图像标签 python 脚本重写为模块化方法,简单地从我的网络摄像头获取一个帧对象到一张照片,并返回预测和预测的置信度得分。下一步是以编程方式从我的前置摄像头流式传输一张实时照片,并将每一帧作为一个帧对象,这样我就可以在模型中运行它进行预测。然后在屏幕上显示预测和置信度得分。
如果你用的是我的 GitHub repo,下面是运行的代码:
import tensorflow as tfimport cv2import base64import timecap = cv2.VideoCapture(-1)count =0if cap.isOpened():rval,frame=cap.read()else :rval=False# Loads label file, strips off carriage returnlabel_lines = [line.rstrip() for linein tf.gfile.GFile("inception/output_labels.txt")]# Unpersists graph from filef = tf.gfile.FastGFile("inception/output_graph.pb", 'rb')graph_def = tf.GraphDef()graph_def.ParseFromString(f.read())_ = tf.import_graph_def(graph_def, name='')with tf.Session() as sess:while True:cv2.imshow("Inception Classifier", frame)# true or false for ret if the capture is there or notret, frame = cap.read() # read frame from the ]buffer= cv2.imencode('.jpg',frame)[1].tostring()image_data=buffer# Feed the image_data as input to the graph and get first predictionsoftmax_tensor = sess.graph.get_tensor_by_name('final_result:0')predictions = sess.run(softmax_tensor,{'DecodeJpeg/contents:0': image_data})# Sort to show labels of first prediction in order of confidencetop_k = predictions[0].argsort()[-1:][::-1]for node_id in top_k:human_string = label_lines[node_id]score = predictions[0][node_id]#Only add label to feed if confidence is more than 40 %if score > 0.4:text_color = (255, 0, 0)cv2.putText(frame, s, (33, 455),cv2.QT_FONT_NORMAL, 1.0, text_color, thickness=2)name_of_file="frames/"+str(human_string)+str(score)+".jpg"cv2.imwrite(name_of_file,frame)print(name_of_file)count= count+1key = cv2.waitKey(20)if key == 27:breakcv2.destroyWindow("Inception Classifier")
结果是这样的:
Signing letter D
Signing the letter O
我将帧保存在一个目录中,以实时改进我的数据集,并最终使模型变得更好。很快我就有了足够的数据,mobilenets 实现并没有溢出。
然而这还不是结束。接下来的步骤
这个项目只是触及了所能实现的表面。
- 部署到 Android :部署到 Android 应用程序有两种途径,第一种选择是将 tflite 应用程序添加到应用程序的源代码中,就像这个 tensorflow 示例应用程序或使用本教程中的 Firebase ML 工具包。你可以在这里测试我的 Firebase ML 工具包实现。我们可以将获得的图形文件转换为 tensorflow lite 文件,并将其部署在 android 应用程序上。为此,运行以下命令
```bash
toco \ — input_file= [path to .pb file] \ — output*_file=output/output_*graph.tflite \ — input*_format=TENSORFLOW_*GRAPHDEF \ — output_format=TFLITE \ — input_shape=1,224,224,3 \ — input_array=input \ — output*_array=final_*result \ — inference_type=FLOAT \ — input*_data_*type=FLOAT\ — allow*_custom_*ops```
- 扩展到视频:我看到这正在扩展到肯尼亚手语词的 gif,并利用视频字幕应用程序的收益。简单地说,视频是一系列照片,我们可以将一层冻结的卷积网络和一层 LSTM 层结合起来,从三帧视频中解读手语词。其灵感来自于 Fchollet 的 TensorFlow 开发峰会演示
直到下次:
政府 AI 的透明度
给机器学习的黑盒子照一盏灯会保护我们吗?
Photo by Kyle Glenn on Unsplash
为什么我们希望政府 ML 透明?
媒体和公众有一种感觉,透明度是确保机器学习的潜在危害不会发生的理想方式。但这在现实中是什么样的呢?
思考机器学习和人工智能在政府手中的潜在危害或担忧,会让人想起奥威尔的《1984 年的 T1》或斯皮尔伯格的《T2 的少数派报告 T3》。
我相信这是因为人类对有人以任何准确度预测我们将做什么的想法感到不舒服。我认为,当一个对我们有权力根据这些预测做出决定的实体(比如政府)做出这种决定时,这种不安会明显加剧。
我在之前写过关于潜在影响和危害的文章,但在其他文章和在线社区中也可以找到大量的故事和担忧。
什么是政府透明度?
透明是自由民主的标志。这是因为政府数据、政府决策和政府规则的透明度为公民和非政府组织质疑政府提供了一些必要的工具。它还赋予这些组织权力,作为对政府的制衡,建立游说和接触当选立法机构所需的知识基础,以改变现有法律或颁布新法律。
在美国,政府决策和规则制定的透明度不仅体现在第五和第十四修正案中,还体现在其他几项立法中。第五条和第十四条修正案一般规定了政府决策的正当程序,尤其是那些影响个人公民自由的决策。
美国还通过了阳光政府法案、信息自由法案、行政程序法和文书工作减少法案。这些法案结合起来向公众提供有关政府推理、决策和内部程序的重要信息。
然而,透明度是有限的。法律学者已经表明,法院会篡改这些法律,在做出决定或实施项目时,不能完全理解政府机构的内部运作。例如,《信息自由法》有九项豁免,政府机构可以排除或拒绝所要求的信息。这些可以有相当宽泛的解释。
但是,尽管这些法律为政府提供了广泛的豁免和警告,从某些信息的发布,仍然有机制来在许多问题上进行三角测量。
对机器学习透明度的错误乐观
在欧盟通过并实施《通用数据保护条例》(GDPR)后,通过对机器学习透明度的讨论,也出现了一种新的代理感。然而,正如学者所指出的,“解释权”的承诺过于乐观,原因有几个。
首先,有人担心政府将无法提供必要的服务水平,以允许关于每个 ML 预测实例的个人信息。
此外,这些算法将完全由政府机构控制的想法在世界范围内仍是一个公开的问题,因为许多政府机构依赖私营公司提供这些技能和技术。
第二,正如我们在 GDPR 所看到的——也很可能在其他法规中得到考虑——公民的个人同意可以免除数据处理器参与透明度的责任。
在私营部门,这被证明是近乎荒谬的控制手段。在公共部门,这还有待研究,但当个人知道政府将使用这些信息并对有影响的决策负责时,这可能会沿着私人路线或有所不同。
然而,人们担心,在没有对条款进行深入审查的情况下,便利会促使大多数个人同意,这种担心是真实的,我们可以预计,这在政府决策中也是无效的。
第三,我们知道机器学习并不总是能被个体公民所理解。这要么是因为公民通常不具备理解所需的知识和技能水平,要么是因为模型本身的性质不符合设计者和实践者的解释能力。
严格透明的替代方案
**有用的解释。**在一些研究中,出现了如何让机器学习对个人“可解释”的想法。如 Edwards 和 Veale 所述,有两种方法,以主题为中心的解释(SCE)或以模型为中心的解释(MCE)。
在 MCE 中,需要向个人解释经过训练的机器学习模型。这需要对输入、训练数据、参数和模型类型有深刻的理解。它还要求能够解释模型如何对单个预测进行排序和决策。这在团体层面上可能是有用的,但在个人层面上很难描述。
此外,MCE 可能需要机器学习算法、训练和测试数据以及输出的完整发布和透明。这将危及公司的私权,但也可能将游戏引入系统…在这种情况下,基本上抵消了机器学习的潜在好处。
另一方面,常设专家委员会可以帮助个人了解他们的情况将如何影响对他们作出的决定或产出,而不必打开“黑箱”。这也可以为他们提供了解他们的行为如何对他们的未来产生积极和消极影响的方法,并证明他们更好地理解关于未来的决策和机构。
SCE 的一个例子是信用评级公司允许用户操纵个人情况(工作、拖欠账户数量、家庭规模等)。)并查看基于这些变化的假设输出。
合理的解释。 另一种选择涉及通过合理的解释而不是鱼缸透明度来实现政府洗钱计划的透明度。鱼缸透明度是一个概念,类似于目前的“解释权”的理想,即政府在洗钱过程中所做的一切都将供公众消费和审查。
在一个合理的解释中,政府机构只需要提供 ML 模型背后的输入、输出和理论来描述它是如何设计的以及它的目标是什么。例如,它可以简单到解释数据输入以及观察犯罪行为和预测未来犯罪的目的。
这与目前美国政府法规的一些实例没有什么不同。在这些情况下,政府机构需要解释他们将如何作出裁决,他们的因果关系理论,考虑的因素,决定的法律标准,以及在这些决定中使用的推理。标准不是他们总是正确的,而是他们为公众提供了关于他们推理的深入信息。
政府问责制。 Cintron 和 Pasquale 提出了一个审计政府 ML 算法的流程,以帮助确保它们不包含对其目的和决策不可接受的偏差。
这种独立审计将通过提供第三方审查来确认合理解释的完整性。
它也可以作为一种机制和最大似然算法的储存库,可以防止担心或指控政府机构在没有公开通知的情况下修改甚至替换最大似然程序。
在公民诉讼或立法监督的情况下,可以将审计的算法与当前在特定情况下部署或使用的算法进行比较,以确认没有重大变化。
总之,公众对政府使用 ML 的谨慎或恐惧并不是没有根据的。但目前正在讨论的呼吁完全透明的提议,不太可能缓解或对这些担忧提供有意义的制衡。
与典型意义上的透明度不同,我同意一些研究人员的观点,他们试图确定政府洗钱项目中有意义的透明度类型,这将允许在政府裁决中采用和实施,但也不会限制政府的正当程序和监督。
允许政府对 ML 项目进行公告和审查,既不会提出不可实现的要求,也不会在第一步就降低其使用 ML 的能力。
考虑 SCE 可以为公民提供一个实际的方法来理解 ML 模型是如何对他们做出决策的,以及他们可以采取什么行动来影响未来的决策。
提供一个独立审计的平台可以建立在这些步骤上,以提供对洗钱项目的额外信任,并确保宪法规定的正当程序和监督。
我们应该仔细思考传统透明度和“解释权”背后的理念,作为减轻政府洗钱担忧的可行机制。
陷阱 DS 项目:当心“容易”的细分项目
99%的可能性你还没准备好
TL;dr:依赖于一大堆其他东西的无界的、范围很小的项目和你想象的一样有趣。
今天的某个地方,世界上有人在对一位数据科学家说这句话的某个版本:“我们有很多客户行为数据,让我们将它们聚集到一些有用的细分市场,看看我们可以从哪里了解我们的业务,这有多难?”
剧透:很难,非常难,看似很难。大多数系统还没准备好。
And you’re on the boat
在我十多年的创业生涯中,我自己或在不同人的指导下,已经开始了不少于 3 个这样的项目。他们都没有好的结局,基本上只有一个原因——我们没有准备好。
分段听起来很容易
https://dilbert.com/strip/2000-11-13
在所有的机器学习算法中,聚类算法是最容易理解和实现的。像 k-means 这样的东西听起来很容易应用,大体上你只需要…
- 将活动数据放入算法中
- 串
- 对照现实观察输出
- 迭代?
- 利润!!!
除了,不。不是真的。
“把数据扔进算法中”?真的吗?
当“把 X 扔进 Y”这个词被四处传播时,警钟应该总是响起。数据几乎从来没有处于可以被“扔”到任何地方的状态。一旦你开始弄清楚你在隐喻性地到处扔什么数据,这个阶段就可以扼杀你的项目。
首先是“你有数据吗”这个基本问题。仅仅因为你一直在收集东西到数据库中,并不能使它对机器学习有用。如果您在持续记录关键事件方面有所懈怠,或者拥有大量有偏见的样本,或者出于成本原因而丢弃数据,那么您将不得不重新考虑所有这些决策。
—但是我有数据,以前甚至有人提到过数据仓库的事情?
很可能您有事务性数据,并且数据存储已经针对 OLTP 工作负载进行了优化,这是许多生产系统的自然状态。但是分析通常会问一些从侧面看数据的问题。这就是为什么在大约 15-20 年前“数据挖掘”成为行业热点时,“数据仓库”成为一个大话题。
Remember when “data mining” was a thing?
现在,如果您碰巧在某个地方有一个漂亮、干净、维护的数据仓库,其中有精选的度量标准和精心布局的数据立方体,那么您实际上就处于一个集群项目的相当好的开始位置。
我真的没见过多少员工少于 100 人的创业公司有这些东西。它们是需要维护的复杂系统,尤其是在其他系统发展和新数据产生的时候。大多数创业公司没有足够的资金来进行这种程度的分析。
—我实际上有数据,所以我可以正确地使用它?
让我们假设您已经有了一些可以使用的、有组织的、相对来说没有错误的数据。我们准备好了,对吗?
没那么快!!
接下来,您需要进行某种形式的特征生成/选择。虽然算法本身并不关心你是否加入了随机数,但作为分析师和最终用户,你是关心的。除非你喜欢虚假相关性,否则你必须对什么特征重要,什么不重要有所了解(如果你愿意,可以称之为假设)。你有必要的领域知识来做出这种有根据的猜测吗?有人知道吗?
因此,你至少需要了解你的业务的一些基本驱动因素,或者知道什么与你所寻求的成功相关。这意味着你需要对谁是你的客户,他们通常做什么做基础研究,即使只是在高层次上。
让我们用一些具体的例子来巩固这一点
假设你认为用户浏览页面的顺序对于区分用户未来的行为很重要。一个序列有多长很重要?因为存储/处理无限长的序列是$$$。
那么多次会话的行为呢,你有会话吗?与其他用户的行为是否有足够的重叠,让你拥有有用的熵?你从哪里剪掉长尾?
他们是否使用优惠券,或通过平面广告链接注册,或在第一天购买了 5 个小工具呢?也许是他们的原籍国,或者他们是否有信用卡记录,或者他们的个人资料?所有这些东西都被正确地装备了吗,在时间和空间上与用户适当地联系起来了吗?
—等等,我正要用所有的东西!为什么我不能现在就走?
因为两个大问题,各种形式的信息泄露,现有数据泄露了你的输出。想象一下,你发现有个人销售电话的用户很可能使用免费试用…因为销售团队为了“节省空间”而错误地从 CRM 中删除了旧的不成功的线索。或者你的系统中有一个“当前付费客户”标志(非常常见),所以如果你盲目地包括它,相对于没有这个标志的人来说,这将是一个很好的收入预测。
另一个原因是你想要使用的所有数据很可能不是普遍兼容和一致的。所有数据都有一致的用户密钥吗?有些字段表示当前的当前状态,有些字段表示时间上的历史状态,还有一些隐含的状态(例如“’”用户在离开默认状态之前不会在此设置字段中获得一行,因为默认状态是假定的)。仅仅因为它的存在并不意味着它值得一起讲述一个关于世界的一致的故事。
好吧,所以我只是看看田地,打扫一下,这能有多难?
当然,所以你去写查询来收集数据,然后你马上开始发现错误,这些数字并不完全一致,所以你必须弄清楚那里发生了什么并修复它们,对吗?然后你会努力去修复各种系统,也许会实现新的系统来取代坏的系统。突然,这个为期两周的“有趣”项目进入了第三个月。
由于这些特性中有许多不是聚类算法可用的格式,所以您会希望将它们存放在某个地方。也许那里有一个临时表,这里有一个聚集表。然后,您会希望随着时间的推移跟踪这些信息,如果这些信息都在一个系统中就好了…等等,这听起来开始像一个数据仓库(另一个梦想破灭的项目,但是我离题了)…
串
这个过程中最简单的部分
如果你设法达到这一步,这一部分通常不会太糟糕。确定您的特定集群包所采用的数据的确切格式通常是一件痛苦的事情,因为有 1500 万种方法来创建和存储“距离矩阵”,每个人都认为他们的格式是不言自明的,并不真正需要文档…
但除此之外,只要按下按钮!
“眼球簇对抗现实”
因为这是一个定义明确的问题,对吗?
假设您对 5 个集群运行 k-means 尝试。我们不确定 5 是否是正确的集群数量,除了我们从空气中提取的数字,我们盲目地进入这个项目,但我们有人类,我们可以检查看看“感觉”有多正确,对吗?
这在实践中如何运作?我们转储行的例子,并试图得出一些押韵或理由。我们的希望是,我们看着集群,它以一种不明确的方式有点“有意义”。本质上,你必须看看机器的分类,看看你过度创造的人类大脑是否能想出一个可信的解释来命名这个集群。
但是没有真正的保证你能找到对你有用的东西。不清楚这一大堆数据点是有用的一组还是我们选择的特征的哑工件。即使集群代表了一种“真实的现象”,我们也可能无法充分理解它并广泛使用它。在任何这种模棱两可的情况下,你会想知道你是应该继续你的发现,还是放弃它,再试一次。
哦,对了,我是不是忘了提到,根据您使用的聚类方法和您的数据属性,可能会有关于在多次运行和一段时间内聚类的稳定性的问题?
重复
——因为第一次做起来很有趣,我们想再做几次,直到我们觉得做对了为止
帕尔塔伊。(顺便说一句,到现在过了几个月才走到这一步?)
利润?
如果你幸运的话。
整个聚类练习的最终目标是 1)了解关于用户的新的有趣的事情,或者 2)将新发现的组应用到其他事情上,这在以后会很有用。现在(大概)您已经有了一组集群用户,您会想要尝试做这些事情。希望它们能起作用,并开启各种洞见和神奇的独角兽。
那么是不是没有希望了?!?
有一些!
先做一些定性的作业
请注意,当您验证这些任意的无监督聚类时,您实际上是在使用您自己的数据心理模型作为参考点?如果你不能对是什么组成了一个集群有一个一致的理解,那么这个集群就不会感觉“正确”。既然你无论如何都需要这个作为参考点,先做!
然后你会对你要寻找的集群数量有一些先验的假设,以及对什么潜在特征对模型有影响有一个更好的认识。所有这些都会对你的模型有所帮助你甚至会发现这个作业已经足够好了*,甚至可能没有必要去做数据挖掘。*
尽可能的限制自己的范围!
关键是要认识到,你想要使用的数据越多,涉及的痛苦就越多,直到一切都变得不可能。
安全生存的方法是非常严格地控制范围。这意味着你应该有
- 一个非常确定和简短的列表列出了用户应该聚集起来反对的因素,假设是被鼓励的!
- 你的数据收集系统提前调试好了
- 您的数据访问/移动/管道基础设施处于可管理状态(您能否获得所有数据并将其复制到需要处理的地方?)
- 如果所有这些基本要素都不具备,他们会有强烈的抵制意愿
知道什么时候该停下来推回去
开放式问题会耗费你愿意投入的时间,所以如果你发现你做的数据工程工作比集群工作多,你应该重新评估整个项目。
数据工程部分可能实际上是你应该做的推动公司前进的必要工作,但是把所有这些工作放在一个单独的数据人员的权限下的“做集群项目”的保护伞下是错误的。这个工作量应该是使用不同资源并与管理层讨论的严肃工作。
重要的是,在你对事情投入太多之前,先往后推。
穿越欧洲旅行(以一种书呆子的方式)
通过使用 python 库抓取谷歌航班来创建最佳旅行路线
作为一个旅行爱好者,我明年的目标是尽可能多地旅行。我对目的地不是很挑剔;然而,我确实有一些限制。首先,我只能在周末旅行,因为我从周一到周五都在办公室工作。第二,我想用最少的预算尽可能多地游览不同的城市。第三,我不想在飞机上花太多时间。那么让我们来看看如何自动找到一个最优的旅行路线。
考虑到我的灵活性和局限性,我尝试了许多航班搜索工具,最终我选择了 https://www.google.com/flights 的 T2。在这里,您可以选择一个出发城市,将目的地留空以探索各种选项。您还可以选择灵活的旅行日期,例如,在未来 6 个月内的所有周末旅行,只需点击几下鼠标:
Google flights is flexible but not what I’m looking for
然而,我发现他们对周末的定义毫无用处。例如,参见上面的截图。你可以看到 4 月 2 日周四飞往布拉格的航班谢谢你,谷歌,给了我这个便宜的选择,但我周五必须去办公室*。同样,它为其他城市提供了一些其他选择,周六晚上出发,周日早上返回,如果你只是对了解机场感兴趣那就太好了。*
所以,谷歌,伴随着巨大的灵活性而来的是巨大的责任,你对周末旅行的假设是错误的。
好吧,让我们给谷歌更少的灵活性。让我们告诉谷歌,我想在 2019 年 12 月 13 日至 15 日的周末去欧洲任何地方旅行,从阿姆斯特丹往返,周五在 hs 的 18.00 和 24.00 之间出发,周日在 hs 的 16.00 和 24.00 之间返回。这是该搜索的链接:
在该 URL 中,AMS 指的是阿姆斯特丹,您也可以在那里看到我们选择的日期和时间限制。
URL 中的搜索逻辑非常简单:
*[https://www.google.com/flights?hl=en#flt={city_code}..{departure_date}*.{city_code}.{return_date};c:EUR;e:1;dt:{takeoff_after}-{takeoff_until}*{return_after}-{return_until};ls:1w;p:{max_budget}.0.EUR;px:1;sd:1;er:296254327.-269199219.671078146.490175781;t:e](https://www.google.com/flights?hl=en#flt=/m/0k3p..{departure_date}*./m/0k3p.{return_date};c:EUR;e:1;dt:{takeoff_after}-{takeoff_until}*{return_after}-{return_until};ls:1w;p:{max_budget}00.2.EUR;px:1;sd:1;er:296254327.-269199219.671078146.490175781;t:e)*
其中城市 _ 代码为 IATA 机场代码,出发 _ 日期和返回 _ 日期格式为yyyy-mm-DD**;起飞 _ 之后,起飞 _ 直到,返回 _ 之后,和返回 _ 直到格式为HHMM;而 max_budget 格式是一个整数,以欧元为单位定义最高价格。 er 参数定义了寻找目的地的区域。您可以使用缩放功能,将这些数字更改为您感兴趣的任何区域。
按照这个简单的 URL 逻辑,我创建了一个 python 库,它可以扫描 Google 航班并将行程保存在一个 CSV 文件中。您可以在此回购中找到代码:
您可以下载它,导入库,然后通过用 CSV 文件名创建 GoogleFlights 对象来调用它。然后,您可以通过调用 createDataWorldwide 方法扫描任何地方的所有目的地,如下所示:
*gs = GoogleFlights(csv_filename)
gs.createDataWorldwide(travel_lenght_list,start_period,end_period,steps_days,takeoff_after,takeoff_until,return_after,return_until,nr_passengers)*
createDataWorldwide 方法的参数如下。travel _ length _ list是一个数组,包含您要扫描的住宿天数,例如,[2,3]将扫描包含 2 晚和 3 晚的旅行。 start_period 是开始扫描的第一个出发日期;因此,如果您想扫描周六出发、周日返回的所有往返航班,请确保 start_period 是周六,并且travel _ length _ list*=[1]。 end_period 是扫描的最后一个出发日期;对我来说,是 2020 年 12 月的任何一天。参数 steps_days 是扫描出发日期之间的间隔天数;因此,如果 steps_days =7,它将扫描每周出发的航班,如果 steps_days =1,它将扫描每天出发的航班。我使用起飞 _ 之后和起飞 _ 直到只扫描 18 小时后出发的行程。因为我想周五下班后去旅游。同样,我使用 return_after 和 return_until 扫描 17 小时后返回阿姆斯特丹的航班。因为我想在周日早上花些时间在城里逛逛。最后可以用 nr_passengers 指定乘客数量。*
如果你没有任何限制,并且想去野外,你可以设置 travel _ length _ list =2,3,7,start _ period= ’ 2020–01–01 ',end _ period= ’ 2020–12–31 ', steps_days =1, takeoff_after ='000 ',take off _ out 这将扫描 2020 年任何日期从阿姆斯特丹出发、持续 2、3 或 7 晚的所有往返航班。
F 还是我的用例,我用我的 python 库刮出了 2020 年每个周末从阿姆斯特丹到任何目的地的所有往返,价格低于 300 欧元的 2 位乘客。
我对周末的定义是 18 小时后的星期五。17 小时后周日返回,但可以很容易地更改。这是我如何使用库来实现我想要的:
*gs.createDataWorldwide([2],'2019-12-06','2020-12-01',7,takeoff_after='1800',return_after='1700',nr_passengers=2)*
它会创建一个 CSV 文件。该文件的一个小示例如下所示:
目前还没有 2020 年 11 月和 12 月的选项,所以我找到的最后一个周末的航班是 2020 年 10 月 16 日。
现在我可以称这个方法为 optimum_weekends,来寻找 2020 年最低预算的旅行路线。
*gs.optimum_weekends(duration_max,from_start,allow_max_city_duplicates)*
参数 duration_max 过滤掉超过*x*
小时的航班。我选择了 duration_max =7,因为我不想飞行超过 7 个小时。参数 from_start 指定旅程的开始日期。参数allow _ max _ city _ duplicates过滤掉具有超过*x*
个重复目的地的路线。该方法通过为 2020 年所有周末的每个日期选择目的地的排列,创建了数千条可能的路线。输出是对于扫描的行程具有最低可能预算的路线。输出如下所示:
Itinerary of weekend trips for 2020
我需要在 2020 年每个周末旅行(不包括 11 月和 12 月)的总预算是 7670 欧元,2 名乘客,从阿姆斯特丹来回。我将在 42 个周末了解 26 个不同的城市。我也不需要在工作中请假。
实际上,我对多次访问同一个城市不感兴趣,所以让我们删除重复的城市,让我们保留最便宜的选项。
Itinerary of weekend trips for 2020 to unique destinations
我需要为 2020 年 2 名乘客游览 26 个不同城市的优化预算旅行路线的总预算是 5061 欧元。
我期待人们使用该工具,根据不同的限制或改进建议,提出其他优化策略。在我的头顶上,人们可以使用该工具找到 2020 年前往特定目的地的最便宜的日期;或者调查航班价格是否在一天之内、一周之内或随着 IP 国家发生变化;或者发现票价错误。天空不是极限,是目标:)。
创建伦敦的现代旅游地图
我设计了一张个性化的伦敦地图,显示了我在 10 分钟、20 分钟、30 分钟等时间内使用公共交通工具可以走多远…)分钟。它看起来是这样的:
Map of London showing how far you can travel using public transport from my house in Ealing. Interactive map here. Can you guess where the tube stops are?
更好的是,代码可以在世界任何地方使用,也可以行走。以下是我有幸居住过的另外三个大城市的个性化地图:
Travel time areas for 10, 20, 30, and 45 minutes travel around where I lived in Montreal, Manchester, and Edinburgh, using any public transport available.
该过程
在一个慵懒的周日早晨,我偶然发现了一系列美丽的历史地图。这些被称为等时线地图,代表了制图员对你在不同时期能走多远的估计。我最喜欢的是巴塞洛缪的从伦敦到世界各地的等时距离图。
John G. Bartholomew’s isochronic map [1]. Look how inaccessible South America, Africa, and Australia are.
虽然这些很有趣,但我们应该有所保留。我怀疑巴塞洛缪先生是否广泛研究过波兰的火车时刻表。但是这些天我们做有高度准确的旅行时间预测。那么,对于世界上我最喜欢的城市来说,真正的等时地图会是什么样的呢?
我发现伦敦特别有趣的地方是,从我住在伦敦西部的地方,我可以很快到达主要的博物馆,并进入伦敦金融城(伦敦内一平方英里的区域)。但是去伦敦东南部旅行是一场噩梦(大约 1.5 小时),比从爱丁堡到格拉斯哥的旅程还要长。
到代码上…
代码
为了创建个性化地图,我们需要选择一组要分析的点,检索这些点的旅行时间,通过绘制外壳将这些点分组到边界中,并在地图上绘制这些点。
当创建一个点的点阵时,我始终专注于使用 NumPy 来利用它的矢量化,以及比 Python 列表更高效的计算。我创建了两个选项:
- 以原点为中心的局部网格,具有定义的点间距和点数
- 一个全球格网,取一个区域的最小和最大纬度和经度进行搜索,以及格网分割的次数
接下来,我必须生成旅行的实际时间。有许多选项可以做到这一点,但我决定使用谷歌距离矩阵 API 。这将返回往返目的地的距离和时间。我查看的其他选项包括 Google 方向 API (它也返回方向,这对于这个应用程序是不必要的),以及 MapQuest 方向 API 。
Screenshot of my Google Developer Console
你可以通过谷歌开发者控制台访问超过 24 个谷歌 API 的套件。我发现设置 API 非常直观,虽然这些 API 是付费的,但你可以在 12 个月的试用期内获得 300 美元的免费积分,我发现这对我的项目来说绰绰有余。确保您对结果进行了筛选,这样您就不需要多次调用同一个区域的 API 了!
# Storing my latitudes, longitudes, and travel times from the API
pickle.dump([lats, lngs, travel_times], open(pickle_path, 'wb'))
我在使用这个 API 时发现了一些有趣的怪癖,包括:
- 您发送给 API 的查询字符串可能太长,在这种情况下,您需要使用折线编码对其进行编码。
- 每个请求只能发送 100 个元素(1 个起点,100 个目的地),所以我使用
chunked_latitudes = np.split(latitudes, len(latitudes)//chunk_size)
分块我的 NumPy 数组。 - 它意外超时,所以我每 5000 个请求就暂停一次代码。
有了一组数据点,我就必须想出如何根据旅行时间将它们连接到不同的区域。这并不是一项简单的任务。我的第一个想法是把外面的点连接起来,这就是所谓的凸包。然而这不是我想要的。我想要的是进入角落和缝隙,在数据中找到“峡湾”。这种实现称为凹面外壳。
The unique convex hull for the set of points on the left, and a concave hull for these points on the right [3].
凹面外壳是不唯一的,你可以通过选择最近邻的数量来决定你希望你的凹面外壳在点周围有多少包裹。我使用了 J. P. Figueira 写的一个很棒的实现,我使用了这个实现。
凹面外壳实现没有处理的是点的孤岛。这些是地图上最有趣的部分。特别是,地铁和公共汽车周围的区域是可以到达的,而地理位置更近的区域则不可以。这是我真正好奇的:伦敦有哪些离我比较近,但又隐藏起来的地方?
Points I can access within 30 minutes from my home in London. Are there 7, 8, or 9 islands?
我对机器学习很感兴趣,所以我开始尝试实现两种无监督的机器学习方法:K-means 聚类和高斯混合方法(GMMs)。然而两者都有问题。
K-means 聚类在聚类中心周围绘制一个恒定的半径,这并没有考虑到点是如何在纵向上更加分散的。
A K-means clustering for the points with 7 clusters. It’s terrible. Code thanks to Python: Data Science Handbook by J. VanderPlas
GMM 通过绘制任意对齐的椭圆来分组集群岛,从而解决了这个问题。然而,我发现这些省略号仍然是病态的。这并不奇怪,因为 GMM 主要是一种密度估计方法。事实上,我寻找的是一种没有聚类中心的聚类方法,它只是根据成对的距离对点进行分组。
经过一番搜索(并试图自己编写算法),我意识到我需要的是 DBSCAN 。Sci-kit learn 有一个易于使用的实现,但是有讨论这个实现是否是一个有效的。
The code to implement Sci-kit learn’s DBSCAN
在这一切当中,我发现 J .范德普拉斯的书非常有助于理解这些方法以及为什么它们不适合我的问题。这是一个很好的教训,在尝试重新发明轮子之前,要先寻找存在的东西,并且思考简单而不是复杂的方法。
这个问题的最后一步是把数据放到地图上。有相当多的地图库可用,包括允许你将数据直接放到谷歌地图上的库。然而,我一直在寻找的是绘制多边形的能力,事实证明,叶子库可以为 OpenStreetMap 做到这一点。
Folium 是一个直观的库,因为它遵循与 Matplotlib 相似的编码风格,让您创建一个地图对象,并将子对象作为点或多边形的层添加到其中。此外,它们被创建为交互式 html 页面,您可以放大和缩小,或者选择和取消选择图层。
Adding island-clusters of points onto the map
我们还可以将它用于哪些有趣的应用?
伦敦在繁忙的地区有一组标志,显示你可以在 5 或 15 分钟内到达哪里,但它们是相当不准确的圆圈。精确的版本呢?
Photo I took of a sign in London at Charing Cross station left. Map with the sign’s five minute walking radius in red, with the true five minute walking distance in black right. No more trying to walk into the Thames.
我尚未探索的想法:
- 查看伦敦哪些地区的交通状况较差,尤其是到“文化中心”的交通状况,并调查可达性和贫困指数之间的相关性。
- 这种个性化地图是如何在 24 小时内演变的,尤其是自从引入夜视管以来。
完成后不久,我在网上找到了两家这样做的公司。不幸的是,其中一个只允许你在付费前进行两次搜索,另一个有国家限制。由于他们画出的形状和他们找到的岛屿是不同的,我将联系他们来找出他们的方法是如何比较的。
你还能在哪里使用这个代码?你可以用它来找到一个合适的住处,离你的工作地点、健身房或其他地方都很近。
请随意使用我的 GitHub 代码(适当地),或者有任何疑问或想法联系我。
参考
[1] J. G. Bartholomew,I 社会距离图 (1904 年),通过大卫·拉姆齐地图收集获得。
[2] 波兰在 1795 年至 1918 年间甚至还不存在。
[3] E .罗森、e .扬松和 m .布伦丁,实现一种快速有效的凹壳算法 (2014)。
[4]奥莱,https://www.oalley.net/
[5]旅行时间地图,https://app.traveltimeplatform.com/
使用 Python 在区块链生态系统中旅行
Aggregate Market Caps of all Coins
全球有超过 2500 个活跃的区块链项目,每个项目都有自己独特的统计特征,我们很少看到对整个加密市场的顶级分析,因为清理和收集时间序列太耗时了。
在零售方面,我们没有一套清晰的功能来收集、清理和探索定制区块链生态系统投资组合所需的关键数据。接下来的博文将为更深入的量化方法打下坚实的基础,这些方法与使用数据科学和量化策略的基于投资组合的波动性、聚类、预测和日志回报等相关。我们现在可以通过 CrytpoCompare 用他们优秀的 API 来聚集和交换特定的交易数据——对散户投资者是免费的。
这篇文章将介绍长时间序列的并行下载,加速比是 8 倍(取决于您机器上的内核数量),我将探索每个可用符号的其他实用统计数据( ticker )。本帖将探讨利用以太坊等协议(即平台)的令牌的性质,以及基于 ERC20 等的令牌。我们将会看到,目前区块链市场的市值为 150,404,143,218 美元(1500 亿美元),仍然只是其他替代市场的一小部分。
首先,您需要在本地机器上下载 Anaconda,并在一个环境中用 Python 3.5+设置一个 conda,然后启动一个 Jupyter 笔记本来运行 chunks 下面的代码。更好的是,如果你还没有尝试过,在 Google Collab 中免费运行下面的代码。
接下来,我们将找出每个协议的令牌项目的数量。
Counts of Tokens per Protocol
- 这里注意,以太坊协议下有 1700+ ERC20 个令牌。WAVES 和 NEO 分别以 53 个和 25 个令牌紧随其后。然后,我们将创建一个树形图来可视化不同协议分组之间的比例。
Token Ratios among Platforms with >1 Coin
我们可以清楚地看到,基于以太坊 ERC20 的项目与市场上所有其他区块链协议相比存在很大的不相称性。这些项目帮助推动了 2017 年底至今的 ICO 市场。
当第一次为这篇文章构建代码时,我试图下载所有列出的 3500+资产,我将在这里为那些在连接所有 crytpo 聚合价格方面有困难的人提供代码。然后,我们将继续在一个并行例程中下载所有历史资产。
Wall time: 5min 17s!! for 150 series!!
现在,我们将绘制显示前 150 个资产的图表,其中颜色编码的条块表示相应项目中的一个或多个令牌。
请注意,左边的高市值项目通常有一个以上来自其根协议的相关令牌。然后,我们将在一个并行化的例程中深入研究所有可用的令牌/协议——这将大大加快我们的处理时间。
创建一个二元图来显示项目从 2014 年到 2018 年的启动时间,按市值排序。
在这里,我用 CryptoCompare 上可用的价格数据绘制了所有 2600 种资产。其他 1000 多项资产要么是前 ico 资产,要么目前没有收集每个符号的汇总交易数据。值得注意的是,在 2017 年 5 月和 2017 年 10 月/2018 年有许多新项目上线的平台期。一些市值较高的项目根据其发布日期增长非常快,而其他类似发布日期的项目却没有增长。接下来,我们将看看大市值 ERC20 令牌在此分布中的位置。
这里的图显示了所有 29 个方案的颜色编码。因为 ERC20s 统治着当前的生态系统,我们看到它们在右边的黄色部分。它们的市值较低,主要是从 2017 年底加密市场的峰值释放到市场上的。这种选择的爆炸可能是密码市场如此迅速衰落的一个重要原因,因为如此多的资本开始分散到许多代币产品中。
在 TechCrunch 最近的一篇文章中,我们看到了“2018 年迄今已有 1000 个项目失败”。然而,截至 2019 年 1 月 30 日,仍有 2633 个活动项目。为了客观地看待问题,福布斯报道仅在 2017 年就提供了 800 个 ico。
以下是 2014 年以来 50 个项目及其各自价格的随机样本。这些资产都是高度正相关的。用上面的并行代码证明给自己看。
我们将使用 Python 中的 Bokeh 模块从 StackOverflow 改编的 gist 中提取一些代码。它非常适合使用 D3 探索多个时间序列——具有缩放功能和基于悬停的信息。
同样,我们将按市值查看顶级资产。
波动性呢??我们将在以后的文章中探讨这个问题。
现在我们想从 CryptoCompare 并行拉入循环补给,并将其与我们原来的 stats 合并,原来的 stats 只包括最大补给。前者是目前被广泛接受的衡量数字资产市值的方法。关于更适合区块链估值的未来和预期测量方法的更深入的讨论,请看经济学的这篇精彩文章。另一个受欢迎的网站 Coinmarketcap.com 用流通供应量来计算市值。
现在合并统计数据,以便按协议探索聚合市场资本
现在,让我们按每个硬币的市值来绘制市值图。我们看到比特币(BTC)、Ripple (XRP)和以太坊(ETH)仍在市场份额上占据主导地位。之后,我们将展示协议生态系统中所有令牌的市场价值。
Market Cap Shares of Aggregate per Coin
接下来,我们显示了基于 marketcap 分组的协议的 marketcap。现在,基于 ERC20 的令牌开始挤占空间。CryptoCompare 似乎有一些令牌在 marketcap 计算中存在异常值。我希望他们尽快修复这些错误,这些错误在下面的代码中被过滤掉了,例如:
“比特 CNY”、“BTF”、“NPC”、“MTN”、“圆点”、“I0C”、“阿米什”、“WBTC*”、“蜂巢”、“OCC”、“SHND”(它们似乎在市值计算中反映不准确)
按协议市场份额分组,瑞士联邦理工学院现在仅次于 BTC。
Source: https://giphy.com/explore/bravocado
感谢您花时间一起探索区块链的生态系统。期待回答您的任何问题。上述代码在一段时间内应该是完全可复制的。如果您对使用上述数据的帖子有任何建议,请分享您的想法。
穿越图形计算和数据库领域
您对图形技术世界的一站式介绍。
Photo courtesy: Neo4j
该博客最初发表于亚特兰蒂斯 数据刊物 人类。
图形是优雅而强大的数据结构,可以在不同规模的多个行业和组织中找到应用。本文旨在向数据人员介绍图形数据库和图形技术领域,并揭开它们的神秘面纱。
注 :我最近有幸在意大利的PyCon X演讲。这个演讲,就像它的名字一样,和这篇文章有着共同的目标。如果你喜欢这种视觉媒体,可以在这里随意观看。
为什么要关心图形?
- 图表是数据的优雅表示,适合各种用例。作为一个数据人,了解它们可以帮助你评估它们对你的问题陈述的效用。
- 从十九世纪开始,图论就作为一个学术领域存在了,从柯尼斯堡桥问题开始。你可以利用大量相关的工作和理论。突出的用例包括最短路径问题、链接预测和 PageRank 。
The Königsberg bridge problem from the 1800s. Photo courtesy: Wikipedia
什么是图?
图是一组顶点(节点、实体)和边(关系)。
传统上,数据以表格格式表示。图表以一种更接近我们心智模型的方式来表示数据。
图形技术怎么样?
图形技术指的是允许用户利用图形数据结构的软件。
Graph tech 软件可以是数据库,如 Neo4j 或 AWS Neptune ,处理框架,如 Apache Giraph 或 Apache Spark 的 GraphX ,或可视化工具,如 Cytoscape 。
让我们比较一下图表数据格式和表格数据结构。
多年来,表格已经成为我们表示数据的事实上的格式。尽管表格模型很有用,但它有局限性,因为它处理的是行和列,而不是真实世界中的实体。逻辑和业务模型从技术模型中分离出来,这就产生了对中介的需求。
这里有一个例子。它涉及到印度 DTC(德里运输公司)的一些 GTFS (通用公交馈电规范)公交数据。
最初由谷歌推出,GTFS 定义了公共交通时刻表和相关地理信息的标准格式。我们用 GTFS 做旅行计划。这些数据由一系列文件组成,比如路线、站点和站点时间,它描绘了德里的公共汽车交通状况。
为了执行有意义的分析,您要么必须在查询/读取时连接各种表,要么以重复的非规范化格式存储它们,这很快就会变得混乱。
连接是一项开销很大的操作。如果您以前处理过关系数据库,您就会知道这样的操作会如何增加您的成本。
处理 GTFS 数据的一个更好的方法是将其存储为图表。通过这样做,我们可以利用健壮的图算法来寻找最短路径和连接组件。图表在视觉上也有很大的不同。
可以用 SQL 做图吗?
鉴于我们对基于 SQL 的解决方案的熟悉,我们可能倾向于在忠于它们的同时解决这个问题,而不是选择图形技术。但这可能会导致一个痛苦的世界。
请看以下摘自 Martin Kleppmann 和 O’Reilly Media 的 设计数据密集型应用 的节选,它为 graph tech 提供了一个强有力的案例。
An excerpt from Designing Data-Intensive Applications on comparing Cypher with SQL
在左上角,您可以看到我们的数据模型。它显示了一对夫妇 Lucy 和 Alain 的信息,以及他们的地理位置。你可以注意到不同国家之间的区域结构和粒度存在差异。
如果我们决定不使用图形数据库会怎么样?
就用基于 SQL 的解决方案比如 Postgres?
虽然我们可以创建一些表——顶点和边——但是 SQL 并不是为查询图形而设计的。
一个创建从美国移民到欧洲的人的列表的查询,显示在上图的右侧,可能需要 50 多行。
如果我们选择基于图形的本地解决方案,我们的数据模型将保持不变。
我们可以使用一种图形查询语言,比如 Cypher,只需几行代码就可以获得相同的信息。
可读性很重要。
- 禅宗之蟒
为什么这些年来图形技术变得越来越流行?
有几个因素导致了 graph tech 今天的地位。这是过去几十年图形技术发展的时间表。
语义网
我们的故事始于 2001 年的语义网。
WWW 发明者蒂姆·伯纳斯·李和他的合著者在《科学美国人》的一篇文章中创造了这个词,它被建模为网络的延伸。语义泛指对意义的研究。
语义网标准旨在用一个物联网取代网页。一个关键的概念是将实体表示为三元组,即主体-客体-谓词,即节点和关系。
尽管语义网还没有完全实现,但它对图形技术的发展做出了巨大的贡献。
A representation of semantic web. Photo courtesy: Wikipedia
开源生态系统
从 2000 年代末开始,一个庞大的图形技术开源生态系统——包括数据库、处理(OLAP/OLTP)和可视化软件——已经形成并继续增长。
还有几种查询语言(Cypher,Gremlin)和抽象层(GraphQL)。
最近,已经开始努力提出一个通用的图形查询标准, GQL 。目标是让 GQL 成为所有基于图形的系统的统一标准,类似于 SQL 对于表格数据系统的意义。
标准化对任何技术来说都是一个好兆头。因此,GQL 的努力是一大积极因素。
托管云服务
Graph tech 将受益于各种大小厂商提供的托管服务。这些产品包括 AWS Neptune 和 Tigergraph cloud 等。这与上一个关于开源生态系统的观点相联系,并从中受益。
AWS Neptune is an example of a managed cloud database.
Photo courtesy: ZDNet
野外的图表
这一部分可以合理地包含一整篇文章,甚至一系列文章。
现在,我将强调一些用例。这些概述了广泛的问题陈述,可以使用图表来解决。
这里一个共同的主题是关系的重要性。
- 知识图谱(KGs) :许多组织如谷歌和美国宇航局利用知识图谱来改善服务和内部效率。KG 以图形格式存储关于域或组织的信息。在数据点之间的关系变得越来越重要的时代,这是一个高度相关的概念。
- 数据民主化和发现:数据民主化意味着允许最终用户,包括非专业人员,能够在没有任何外部帮助的情况下访问和分析数据。阅读这篇关于 Airbnb 如何在图形数据库的帮助下在他们的组织内部实现同样功能的精彩报道。
- 调查性新闻:巴拿马论文背后的 ICIJ (国际调查记者联盟)团队使用图形数据模型有效地探索数据。即使是非技术用户也能够处理视觉上丰富的图形数据。
其他值得注意的用例包括数据治理和合规性( Apache Atlas )、推荐( Pinterest 、亚马逊)和社交网络(脸书)。
与数据相关的技术挑战是什么?
这些挑战可以分为两个主要方面:
1.发展中的生态系统和缺乏共识/标准
无论是选择存储和处理图形数据的工具,还是选择合适的查询语言,决策都可能变得令人不知所措。但是进展很快。为发展 GQL 所做的努力就是一个很好的例子。
2.将数据转换成图形格式
将数据转换为图表格式的过程可能涉及大量的处理和清理工作。它还会导致重复数据删除或记录链接。杂乱的数据让这种转变更加痛苦。
我们在 Atlan 的数据团队在数据民主化和发现方面投入巨大——这是我们构建知识图表平台的主要动机。一个好的平台所提供的抽象将会消除上面提到的挑战。
你应该使用图形数据库吗?
我的建议是:知道你的目的。
你应该根据你的问题陈述仔细评估 graph tech 的效用。一些相关的包括欺诈检测、推荐引擎和法规遵从性。
有些情况下,graph tech 可能不是最合适的,例如简单的 CRUD 应用程序或定期执行数据批量扫描的系统。
最后的话
我希望能够让您相信,在数据关系是首要公民的世界里,图表会一直存在。
别等了。继续前进,穿越图表的土地!
Travis CI for R —高级指南
在 Travis CI 中构建 R 项目的持续集成,包括代码覆盖、[pkgdown](https://github.com/r-lib/pkgdown)
文档、osx 和多个 R 版本
Photo by Guilherme Cunha on Unsplash
Travis CI 是构建 R 包的常用工具。在我看来,在持续集成中使用 R 是最好的平台。一些下载量最大的 R 包就是在这个平台上构建的。例如测试、 magick 或 covr 。我也在这个平台上构建了我的包 RTest 。在安装过程中,我遇到了一些麻烦。在这本指南中,我将与你分享我获得的知识。
目录
- 来自“构建 R 项目”的基础知识
- 修改 R CMD 版本
- 多种操作系统
- 使用用户界面运行脚本
- 代码覆盖率
- 构建并部署一个 pkgdown 页面到 github 页面
- ImageMagick 和 Travis CI
- 延伸阅读
“构建 R 项目”的基础知识
Travis CI 的文章“构建一个 R 项目”告诉您一些基本知识。它允许为 R 包或 R 项目建立一个构建。主要的收获来自这个. travis.yml 文件。
# Use R language
language: r#Define multiple R-versions, one from bioconductor
r:
- oldrel
- release
- devel
- bioc-devel# Set one of you dependencies from github
r_github_packages: r-lib/testthat# Set one of your dependencies from CRAN
r_packages: RTest# set a Linux system dependency
apt_packages:
- libxml2-dev
教程向你解释你应该把你的类型语言设置成 R. 你可以使用不同的 **R 版本。**这些 R 版本是:
[旧版本,发布,开发,生物开发,生物发布]
此外,你可以通过r_github_packages
从 github 加载任何包。或者你可以通过r_packages
从起重机处拿到任何包裹。可以使用标准的 yml 格式创建多个包的列表:
r_packages:
- RTest
- testthat
如果你有 Linux 依赖,这需要被提及。RTest 包使用 XML 测试用例。需要的 XML Linux 库是libxml2
。可以通过以下方式添加:
apt_packages:
- libxml2-dev
您已经完成了基本操作。如果您的存储库中有这个. travis.yml 文件,它将使用R CMD build
和R CMD check
来检查您的项目。
修改 R CMD 命令
为了建立我的项目,我想把它建得像克兰一样。因此,我需要更改包检查的脚本。因此我补充道:
script:
- R CMD build . --compact-vignettes=gs+qpdf
- R CMD check *tar.gz --as-cran
在这个脚本中,你可以改变R CMD build
或R CMD check
参数。关于R CMD
的参数列表,请参见 RStudio 的本教程。
要运行晕影压缩,请通过以下方式获得gs+qpdf
:
addons:
apt:
update: true
packages:
- libgs-dev
- qpdf
- ghostscript
多重操作系统
Travis CI 目前提供两种不同的操作系统(2019 年 1 月)。那些是 macOS 和 Linux。测试的标准方式是 Linux。对于我的项目 RTest,我也需要在 macOS 中进行测试。要在两个操作系统中进行测试,请使用 Travis CI 的matrix
参数。
matrix
参数允许为某些构建调整某些参数。为了在 Linux 和 macOS 中拥有完全相同的版本,我使用了以下结构:
matrix:
include:
- r: release
script:
- R CMD build . --compact-vignettes=gs+qpdf
- R CMD check *tar.gz --as-cran
- r: release
os: osx
osx_image: xcode7.3
before_install:
- sudo tlmgr install framed titling
script:
- R CMD build . --compact-vignettes=gs+qpdf
- R CMD check *tar.gz --as-cran
matrix
函数将构建分成不同的操作系统。对于 macOS,我使用了 xcode7.3 图像,因为它是由 rOpenSCI 提出的。这个版本额外的一点是,它接近目前的 CRAN macOS 版本。正如你所看到的,你应该安装乳胶包framed
和titling
来创建插图。
使用用户界面运行脚本
我的包 RTest 使用 Tcl/Tk 用户界面。为了测试这样的用户界面,您需要分别在 Linux 和 macOS 中启用用户界面。Travis CI 为 Linux 提供了xvfb
包。对于 macOS,您需要用homebrew
重新安装xquartz
和tcl-tk
。
Linux 的用户界面
要在 Linux 中启用用户界面,请安装xvfb
。
addons:
apt:
update: true
packages:
- x11proto-xf86vidmode-dev
- xvfb
- libxxf86vm-dev
您可以在用户界面中运行所有的 R 脚本,方法是在R
命令前使用xvfb-run
命令。
script:
- R CMD build . --compact-vignettes=gs+qpdf
- xvfb-run R CMD check *tar.gz --as-cran
macOS 的用户界面
对于 macOS 来说,用户界面的安装更加困难。您需要将xquart
和tcl-tk
添加到xcode7.3
中提供的图像中。
before_install:
- brew update
- brew cask reinstall xquartz
- brew install tcl-tk --with-tk
- brew link --overwrite --force tcl-tk; brew unlink tcl-tk
要使用 xquartz,macOS 下没有xvfb-run
命令。在 github 的一期中,我发现了一个解决方案,仍然可以让用户界面与xquartz
一起工作。
before_script:
- "export DISPLAY=:99.0"
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then ( sudo Xvfb :99 -ac -screen 0 1024x768x8; echo ok ) & fi
在运行 R 会话可以使用的任何 R 脚本之前,创建一个显示。导出DISPLAY
变量很重要。该变量由 tcktk R 包读取。
在 macOS 中,你不需要修改脚本
script:
- R CMD build . --compact-vignettes=gs+qpdf
- R CMD check *tar.gz --as-cran
插件
有关用户界面的更多信息,您可以阅读以下两个 github 问题:
代码覆盖率
对于代码覆盖率,我建议使用一个特定版本的构建。我决定用 Linux + r-release 来测试代码覆盖率。首先,我将 covr 包添加到我的构建脚本中:
r_github_packages:
- r-lib/covr
其次,我想使用 covr 测试我的包。这可以在 Travis 中使用after_success
步骤完成。为了在这个步骤中使用 covr ,你需要定义你的包 tarball 将如何命名。您可以将这一点直接写入您的脚本。更好的方法是将其写入 you .travis.yml 文件的env
部分。您的 tarball 的名称将始终是*package name+" _ “+package version+” . tar . gz "。在您的描述文件中,您定义了 PackageName 和 PackageVersion。我使用 CODECOV 来存储我的覆盖测试的结果。*
env:
- PKG_TARBALL=RTest_1.2.3.1000.tar.gzafter_success:
- tar -C .. -xf $PKG_TARBALL
- xvfb-run Rscript -e 'covr::codecov(type=c("tests", "vignettes", "examples"))'
我在我的包中使用的设置包括了我所有的例子、插图和测试的代码覆盖率。要部署代码覆盖率的结果,您必须定义全局变量CODECOV_TOKEN
。令牌可以在https://codecov.io/gh/<owner>/<repo>/settings
下找到。你可以把它秘密地插入你的崔维斯电脑里。在https://travis-ci.org/<owner>/<repo>/settings
内添加代币。环境变量部分为您秘密存储变量。
要使用工作服而不是代码罩,使用covr::coveralls
功能并在您的环境中定义一个COVERALLS_TOKEN
。
构建并部署一个 pkgdown 页面到 github 页面
构建一个 pkgdown 页面对于记录您的代码非常有用。在我的 github 存储库中,我还托管了我的包 RTest 的 pkgdown 页面。你可以在这里找到页面:https://zappingseb.github.io/RTest/index.html
为了允许部署到 github 页面,我在 https://github.com///设置中激活了这个特性。你必须使用 gh-pages 分公司。如果您没有这样的分支,您需要创建它。
在. travis.yml 中,首先安装 pkgdown。
r_github_packages:
- r-lib/pkgdown
你将不得不从你的包 tarball 建立页面。必须定义包 tarball 的名称。请参见章节代码覆盖率了解如何做到这一点。拆开 tarball 的包装后,您应该在rm -rf <PackageName>.Rcheck
之前删除检查包装时留下的任何内容。
after_success:
- tar -C .. -xf $PKG_TARBALL
- rm -rf RTest.Rcheck
- Rscript -e 'pkgdown::build_site()'
Rscript
将在docs
文件夹中生成网站。该文件夹必须部署在 github 页面上。
登录 github 后,首先进入https://github.com/settings/tokens。在那里,您必须创建一个具有public_repo
或repo
范围的令牌。现在将这个令牌存储在您的 Travis CI 构建中。因此转到https://travis-ci.org/<owner>/<repo>/settings
并将其存储为名为GITHUB_TOKEN
的全局变量。现在,将使用以下脚本在每个成功的构建上部署网站:
deploy:
- provider: pages
skip-cleanup: true
github-token: $GITHUB_TOKEN
keep-history: false
local-dir: docs
on:
branch: master
有关部署页面的更多信息,您可以查看第页的 Travis CI 指南。
ImageMagick 和 Travis CI
在 travis-ci 社区中,有一个关于如何在 travis-ci 上安装magick
包的问题。答案很简单。您需要拥有 ImageMagick 的所有系统依赖项。通过以下方式为 Linux 安装这些软件:
addons:
apt:
update: true
sources:
- sourceline: 'ppa:opencpu/imagemagick'
- sourceline: 'ppa:ubuntugis/ppa'
packages:
- libmagick++-dev
- librsvg2-dev
- libwebp-dev
- libpoppler-cpp-dev
- libtesseract-dev
- libleptonica-dev
- tesseract-ocr-eng
- r-cran-rgdal
- libfftw3-dev
- cargo
这也适用于我的 macOS。
亲爱的读者:写我在持续集成方面的工作总是令人愉快的。感谢你一直读到这篇文章的结尾。如果你喜欢这篇文章,你可以在 中 或者在github上为它鼓掌。如有评论,请在此处或在我的LinkedIn个人资料http://linkedin.com/in/zappingseb.上留言
进一步阅读
在推特上搜索钓鱼信息
Source: JNL — Troll of Nordic folklore turning to stone in the daylight
虚假信息是民主的最大威胁之一。假新闻、钓鱼和其他政治和社会颠覆性内容困扰着社会。社交媒体巨头在促成和培养这种行为方面发挥了作用。一些人甚至出现在美国国会和欧盟议会面前,承诺采取更多措施应对社交媒体上的虚假信息和仇恨言论的挑战。这些承诺中的一些已经花了将近一年时间,而 T2 仍然受到限制。
因此,当有机会在谷歌云平台(GCP)上创建一个生产机器学习(ML)系统的演示时,我欣然接受了创建一个 trolling tweet 检测器的机会。该演示要求在 GCP 上建立一个完整的项目结构,该结构将生成并部署一个定制的 ML 估计器到云 ML 引擎。
我本可以选择更“商业”的东西。然而,虚假信息识别的用例激励着我。虚假信息和仇恨言论的危害是真实的,我想在这个话题上发表自己的看法,尽管只是一小步。
在这篇文章中,我将重点关注特定于这个 trollish tweet 检测器的数据集和模型开发,在后续文章中,我将讨论使用 MLFlow 跟踪模型性能,以及使用 GCP 部署模型。之前,我写过关于 ProductionML 框架的文章,它在更广泛的架构层次上涵盖了这个主题,并呼吁在数据科学家和数据工程师之间架起一座桥梁。
在钓鱼数据集上进行训练和测试
收集数据
我使用的数据集是由 FiveThirtyEight 在他们的故事 中分享的推文集合,为什么我们要分享 300 万条俄罗斯巨魔推文 。
这就是 FiveThirtyEight 要说的:
FiveThirtyEight 于 2018 年 7 月 25 日从克莱姆森大学研究人员 传播学副教授达伦·林维尔 和经济学副教授 帕特里克·沃伦 处获得数据。他们在一个名为 Social Studio 的工具上使用定制搜索收集数据,该工具归 Salesforce 所有,并由克莱姆森的 社交媒体收听中心 签约使用…
…他的 目录 包含了近 300 万条推文的数据,这些推文是从连接到互联网研究机构、俄罗斯“巨魔工厂”和司法部于 2018 年 2 月提交的一份起诉书 中的一名被告 中发送的,作为特别顾问罗伯特·穆勒俄罗斯调查的一部分。这个数据库中的推文是在 2012 年 2 月至 2018 年 5 月之间发送的,其中绝大多数是在 2015 年至 2017 年发布的。
数据集是存储在 GitHub 存储库中的一系列 CSV 文件。我将它们下载到我的本地机器上,并使用 Python 的 Pandas 库将每个数据帧结合在一起。此时,我已经在一个统一的结构中拥有了完整的数据集,然后我将它存储在 BigQuery 中,再次使用 Pandas。
import os
import pandas as pd# Union
paths = [os.path.join("../data", x) for x in os.listdir("../data")]
cols = pd.read_csv(paths[0]).columns
df = pd.DataFrame(columns=cols) # roughly 3+ million recordsfor path in paths:
df_tmp = pd.read_csv(path)
df = pd.concat([df, df_tmp])# Store in BigQuery
df.to_gbq(
destination_table="dataset.table_name"
, project_id=project_id
, chunksize=None
, verbose=None
, reauth=False
, if_exists='fail'
, private_key=None
, auth_local_webserver=False
, table_schema=table_schema
)
我在下游使用的关键特性是account_category
和content
字段。然而,获得完整的数据集,然后通过 BigQuery 视图,根据需要进行转换,以确保您可以在将来需要时利用更多功能,这始终是一种好的做法。视图,如果您不知道,就不要创建新表——不会存储任何新内容,也不会产生新的存储成本。简单地说,视图是保存到需要时的查询。
阶级不平衡
在阅读了关于数据集的文档并做了初步的探索性数据分析(EDA)后,我得出结论,需要解决一些与类不平衡相关的挑战。
首先,在account_category
下有八个等级或类别。所有这些都来自被怀疑或确认与互联网研究机构(IRA)有关的句柄,因此没有一个是非巨魔,而是与 IRA 有关的各种类型的巨魔。
以下是这些类以及与每个类相关的一些内容示例:
RightTroll
- “我们有一位在任的民主党参议员因腐败接受审判,而你几乎没有听到主流媒体的一点声音。”~ @nedryun
- Marshawn Lynch 穿着反特朗普的衬衫参加比赛。从他下垂的裤子来看,衬衫上应该写着林奇对贝尔特
- 倒下的海军水手的女儿提供了强大的颂歌抗议独白,燃烧她的 NFL 包装工齿轮。#抵制 NFL
- 刚刚消息:特朗普总统将总统杯高尔夫锦标赛奖杯献给佛罗里达州、德克萨斯州和波多黎各的人民。
- 一万九千尊重我们的国歌!#StandForOurAnthem🇺🇸
非英语
- Причина #67 Мутко: «Зенит-Арене» для адаптации к ЧМ потребуется 1,5–2 млрд рублей
- Причина #70 Житель Самары умер в очереди в поликлинике
- Причина #74 Президентский советник предложил ограничить Интернет, как в Китае
- Причина #75 Казаков благословили на защиту интернет-пространства
- Причина #77 В Кстово полицейские сломали женщине лицевую кость, когда та отказалась показать грудь
恐惧使者
- #食物中毒不是玩笑!#沃尔玛#科奇农场
- 感谢上帝,我几天前吃的#火鸡很好吃。#科赫农场
- 我很容易受伤,我只是不表现出来。你可以伤害别人却不自知。
- 金和坎耶的婚礼
- 谁的妆最差,别告诉我,魔镜
LeftTroll
-
blacklivesmatter # BLM # equality # equal rights
- @big_gun_in_utah 所以?如果你交更多的税,你就有更多的权利?“这就是它的工作原理,”
- @犹他州的 big_gun_in_utah 有人吗?
- 黑人学生迫使大学放弃私人监狱 2500 万美元#blacktwitter
- 种族主义的缅因州州长在“毒品问题”上#种族主义渣滓#白痴
未知
- 我的牙医让他的助手吸(我嘴里的水),但我以为他在跟我说话,所以我吸了他的手指。我很羞愧
- 48.“我不吃水牛”
- 新闻史上最伟大的台词
- 从没在这么短的时间内见过这么多的面部表情
- 我不敢相信奶牛是整个宇宙中最可爱、最完美的动物:-)不
HashtagGamer
- 本周由@googlygirl98 主持的@GooglyTags 是# ItWasJustThatOneTime
- 总统自己政党的参议员花在询问总统可能行为不端的情况上的时间似乎异常多。
- #今天将变得伟大因为我选择不在乎任何人说什么或做什么!!这是我的生活,我为自己而活。
- 说真的,如果塞申斯追求色情,特朗普将永远失去动画纳粹
- #今天会很棒,因为我有酒
新闻提要
- 阿尔伯克基男子因试图出售偷来的枪支零件被捕
- 阿尔伯克基口袋妖怪 Go 玩家在这里停留和回馈
- 英国女王伊丽莎白二世因“重感冒”错过了教堂
- 新任联合国秘书长敦促新年决议:“把和平放在第一位”
- 中国表示将在 2017 年底停止象牙贸易
商业
- APA 风格研究论文写作指南
- 为什么教室过敏最严重
- 下周别来上课了,我要生病了。史上最伟大的大学教授
- 脸书的 15 个白痴被叫了出来
幸运的是,我的一个同事一直在挖掘推文——其中许多来自经过验证的 Twitter 账户。所以,我从那些经过验证的账户中提取了推文,并用它们作为非钓鱼者的代理。“已验证”成为 account_category 中的第九个类别。
我们遇到的与类相关的第二个挑战是数据集作为一个整体是不平衡的。每节课的内容量差异很大;有几门课的音量低得令人痛苦。
为了快速有效地处理这个问题,我们做了两件事:
- 删除了非常低的账户类别-非英语、散布谣言者和未知
- 开发了 train_test_split.py 来拆分和平衡我们的数据集
数据集的平衡通过以下 BigQuery 视图解决:
SELECT * FROM (SELECT * FROM (SELECT account_category, content FROM `project_id.ira_russian_troll_tweets.trans_source_unioned_with_verified_view` WHERE account_category = 'Verified' ORDER BY rand() LIMIT 90000)UNION ALLSELECT * FROM (SELECT account_category, content FROM `project_id.ira_russian_troll_tweets.trans_source_unioned_with_verified_view` WHERE account_category = 'Commercial' ORDER BY rand() LIMIT 90000)UNION ALLSELECT * FROM (SELECT account_category, content FROM `project_id.ira_russian_troll_tweets.trans_source_unioned_with_verified_view` WHERE account_category = 'LeftTroll' ORDER BY rand() LIMIT 90000)UNION ALLSELECT * FROM (SELECT account_category, content FROM `project_id.ira_russian_troll_tweets.trans_source_unioned_with_verified_view` WHERE account_category = 'RightTroll' ORDER BY rand() LIMIT 90000)UNION ALLSELECT * FROM (SELECT account_category, content FROM `project_id.ira_russian_troll_tweets.trans_source_unioned_with_verified_view` WHERE account_category = 'HashtagGamer' ORDER BY rand() LIMIT 90000)UNION ALLSELECT * FROM (SELECT account_category, content FROM `project_id.ira_russian_troll_tweets.trans_source_unioned_with_verified_view` WHERE account_category = 'NewsFeed' ORDER BY rand() LIMIT 90000))ORDER BY rand()
train_test_split.py 脚本用于创建该视图。此外,该脚本使用 trans_balanced_view(即 transform 中的 trans)来开发一个数据帧,随后将其拆分为 train 和 test 表。
训练-测试划分为 80/20——80%的数据用于训练,20%用于测试。在训练和测试子数据集中,跨“帐户类别”的数据分布应该保持相等。
ML 管道
sci kit-学习管道
对于机器学习模型,我选择使用 Scikit-learn。我做出这个选择很大程度上是出于重用我已经开发的东西的愿望——如果你只想证明汽车是向前行驶的,那么再造轮子又有什么意义呢?
对于那些不知道的人,Scikit-learn 中的管道允许特征提取器(例如计数或 TF-IDF 矢量器)和 ML 估计器的耦合。换句话说,我能够将矢量器(一种将文本转换为有意义的数字数组的方法)与决策树分类器(一种非常简单的预测目标特征类别的学习方法)连接起来。这帮助我自动化了每次运行所需的数据建模。此外,这允许我使用整个文本(例如一条 tweet)作为输入,而不是整个文本的矢量形式。
虽然将特征提取器与监督学习模型链接在一起相对简单,但它有效地展示了如何以简洁的方式从原始数据输入到预测。
pipeline = Pipeline(
[
("vectorizer", vectorizers[vectorizer])
,(model, models[model][0])
]
)grid_search_cv = GridSearchCV(
estimator=pipline
, param_grid=models[model][1]
, scoring=None
, fit_params=None
, n_jobs=1
, iid=True
, refit=True
, cv=2
, verbose=0
, pre_dispatch='2*n_jobs'
, error_score='raise'
)
网格搜索
任何好的 ML 系统的一个关键方面是超参数调整。通过这种方法,不仅可以选择最佳的统计模型,还可以选择最佳的特征提取器(至少在 Scikit-Learn 中)。
在这个项目中,我选择了使用 Gridsearch,这是公认的非常暴力的方法。也就是说,Gridsearch 很容易理解并被广泛使用。它基于所有允许的参数评估模型的所有排列的性能。
请参见下面的示例,了解如何限制或扩展我为 Gridsearch 提供的参数选项(如矢量器 __ngram_range 或‘DTC _ model _ _ criteria’)。
vectorizer_params = {
"vectorizer__ngram_range": [(1,1), (2,2)]
, "vectorizer__stop_words": [None]
}count_vectorizer = CountVectorizer()
tfidf_vectorizer = TfidfVectorizer()vectorizers = {
"count_vectorizer": count_vectorizer
, "tfidf_vectorizer": tfidf_vectorizer
}# Statistical Model
splitter = ['best', 'random']
min_impurity_decrease = [0.0, 0.8]
max_leaf_nodes = [None, 5]
min_samples_leaf = [1, 5]
min_samples_split = [2, 5]
min_weight_fraction_leaf = [0.0, 0.50]
criterion = ['entropy', 'gini']
random_state = [None, 42]
max_features = [None, 'auto']
max_depth = [None, 5]
class_weight = [None]dtc_param = {
'dtc_model__splitter': splitter
, 'dtc_model__min_impurity_decrease': min_impurity_decrease
, 'dtc_model__max_leaf_nodes': max_leaf_nodes
, 'dtc_model__min_samples_leaf': min_samples_leaf
, 'dtc_model__min_samples_split': min_samples_split
, 'dtc_model__min_weight_fraction_leaf': min_weight_fraction_leaf
, 'dtc_model__criterion': criterion #
, 'dtc_model__random_state': random_state
, 'dtc_model__max_features': max_features
, 'dtc_model__max_depth': max_depth
, 'dtc_model__class_weight': class_weight
}for key in vectorizer_params.keys():
dtc_param[key] = vectorizer_params[key]
从上面的代码中,我向参数字典中添加了矢量器和 ML 模型参数。这允许我们使用作为特征提取的一部分的参数来调整我们的估计器,这可能对估计器的最佳性能有重大影响。
现状核实
重要的是退一步。正如你所看到的,这是一个模型的基础,可以检测一个给定的推文可能属于哪个类别;训练数据集中过去推文的相似词汇和词频有助于建立一个模型,将新推文与该类别或类别相关联。
使用词汇的频率作为特征意味着这个模型仅限于照亮与过去的推文相似的推文。因此,产生的 ML 模型肯定需要与其他模型一起使用来识别单个的巨魔。结合预测其他方面的模型,如病毒范围、辱骂性语言或仇恨图像,可以帮助识别个体巨魔。
研究人员和社交媒体公司正在研究的策略中可以看到这种混合方法。在一项名为自动处理虚假信息的研究中,欧洲议会研究服务(EPRS)详细说明了导致虚假信息传播的因素,并探索了处理虚假信息的可能技术方法。我做的这个小项目很可能符合第 3.2 节中描述的工作。检测计算放大和假账 (p33)。
如果你对跟踪和解决虚假信息的话题以及更广泛的内容监控话题感兴趣,以下内容可能值得一读:
下一步是什么?
好,我有一个模型。那又怎样!
一个 ML 模型不是生活在一个静态的环境中。这个项目就是一个完美的例子。政治和文化的变化。人们在推特上谈论的变化。必须对模型进行再培训,使其准确、相关、可持续和负责任。
那么,如果我把这个模型投入生产,会是什么样子呢?我们如何快速再培训?我们如何跟踪模型性能以确保寿命?我们如何部署到最终用户可以通过 API 访问的源?
我将在下一篇文章中解决这些问题。敬请关注。
喜欢你读的吗?在 Medium 或 LinkedIn 上关注我。
本文原载于 Servian:云和数据专业人士
根据你的自然语言处理任务不同对待否定停用词
否定词(not,nor,never)在 NLTK,spacy 和 sklearn 中都被认为是停用词,但我们应该根据 NLP 任务的不同给予不同的注意
Photo by Jose Aragones on Unsplash
最近我在做一个关系抽取(RE)项目。但是我注意到一些流行的 NLP 工具,NLTK,spacy 和 sklearn,都把否定词当做停用词。如果我将这些否定词作为停用词删除,这将对检测两个实体之间的真实关系产生不良影响。所以我写这篇文章是为了那些遇到同样问题的人。
什么是停用词?
在计算中, 停用词 是在处理自然语言数据(文本)之前或之后过滤掉的词。停用词通常是语言中最常见的词。
我们可以看到这个定义是从统计学的角度来看的。但是在某些自然语言处理任务中,对于否定词的识别是有限的。
为什么要区别对待否定词?
在 RE 任务中,两个实体之间的【SDP】最短依赖路径,被证明可以有效地提取出识别两个实体之间关系的最重要信息。
下面是我从论文中选取的一个例子:修剪后的依赖树上的图卷积改进了关系提取。
在这个例子中,SDP 是['he', 'relative', 'Cane', 'Mike']
。预测关系为per:other_family
。但真正的标签是no_relation
。因为not
不在 SDP 中,not
表示he
和Cane Mike
之间没有关系。
我们可以看到not
是一个重要的上下文词,它直接影响对两个实体之间关系的判断。我们不能只删除not
作为正常的停用词。
如何看待不同 NLP 任务中的否定词?
这取决于我们想要解决什么样的 NLP 任务。如果你的项目很小,你只需要统计功能,像词袋,tf-idf,你可以删除否定词作为停用词。
如果你的 NLP 任务是与上下文相关的,例如,情感分析,我们应该保留否定词。我建议根据 NLP 任务定制一个停用词列表。Twitter 否定语料库就是一个例子。本文中给出了对该方法的解释
如果你的 NLP 任务是高度上下文相关的,我推荐使用 ELMo、ULMFiT、BERT、XLNet 等上下文相关模型。在这种模型中,所有停用词都被保留以提供足够的上下文信息。
查看我的其他帖子 中等 同 一分类查看 !
GitHub:bramble Xu LinkedIn:徐亮 博客:bramble Xu
参考
- 如何用 spaCy 和 StanfordNLP 找到最短依赖路径
- 修剪后的依赖树上的图形卷积改进了关系提取
- Twitter 情感分析的否定范围检测
- https://data science . stack exchange . com/questions/15765/NLP-why-is-not-a-stop-word
数据科学中的树
在简单的决策树中导航,引导/打包,最终形成随机森林模型
机器学习中最容易解释的模型之一是 CART(分类和回归树),俗称决策树。在这篇文章中,我希望给出一个决策树的概述,一些围绕决策树的基本概念,最后是随机森林。内容如下
- 理解决策树
- 纯洁
- 自举和打包
- 随机森林
我们走吧!
决策树
Basic structure of a Decision Tree (Source: cway-quan)
在机器学习宇宙中,树实际上是真实树的颠倒版本。假设我们有一个由特征‘X’和目标‘Y’组成的数据集。决策树所做的是在 X 中寻找模式,并基于这些模式将数据集分割成更小的子集。
在上面略加简化的图像中想象这些分裂。这是一份工作是否被接受的问题。“X”包含“通勤时间”、“薪水”、“免费咖啡”等特征。
基于“X”中的模式,该树被分成分支,直到它到达到达“Y”的纯答案的点。在我们的场景中,被接受的工作机会必须提供超过 50k 的薪水,通勤时间< 1hr and free coffee. In this manner the tree reaches the last leaf which is a pure decision about ‘Y’.
决策树中的纯度
决策树根据节点的纯度进行分裂。这种纯度是基于“Y”的分布来测量的。如果我们的“Y”是连续的,我们的问题是一个回归问题,节点是基于 MSE(均方误差)分裂的。如果“Y”是离散的,我们的模型正在处理一个分类问题,需要不同的纯度测量。
在分类案例中,广泛使用的衡量标准是基尼系数。基尼系数的公式如下:
Source: General Assembly DSI curriculum (Authors:David Yerrington, Matt Brems)
当决定在给定的节点上进行哪个分裂时,它挑选从父节点到子节点的基尼不纯度下降最大的分裂。
自举和打包
要理解 bootstrapping 和 bagging,第一步是理解为什么首先需要它们。它基本上是试图模仿“群体的智慧”原则,即多个模型的综合结果优于单个模型的结果。下面这张由 Lorna Yen 拍摄的图片给出了一个关于系鞋带的好主意。
(Author: Lorna yen, Source)
如上所示的自举只是对数据进行随机采样,并进行替换。Bagging 只是在这些样本中的每一个上构建决策树并获得总体预测的过程。概括来说,装袋包括以下步骤:
- 从大小为 n 的原始数据,用替换引导 k 个大小为 n 的样本
- 在每个引导样本上构建一个决策树。
- 通过所有采油树传递测试数据,并开发一个综合预测
Bagging 因此也被称为自举聚合。
随机森林模型
仔细观察下面的图片,你会对随机森林有一个基本的直觉。
Source: globalsoftwaresupport.com, (link)
bagging 的一个基本障碍是各个决策树高度相关,因为所有的树都使用相同的特征。所以我们模型的预测受到方差问题的困扰。要了解更多关于方差或偏差的信息,您可以阅读此链接。去相关我们的模型是一个解决方案,这正是随机森林所做的。
随机森林在 bagging 中遵循类似的步骤,除了它们在学习过程中的每个分裂处使用特征的随机子集。这减轻了装袋中的差异问题,并且通常产生更好的结果。这种有效而简单的方法使随机森林成为广泛实施的机器学习模型。
奖金
用于在 sklearn 中导入解释的三个分类模型的代码。
#Import for decision trees
**from** **sklearn.tree** **import** DecisionTreeClassifier#Import for bagging
**from** **sklearn.ensemble** **import** BaggingClassifier#Import for random Forests
**from** **sklearn.ensemble** **import** RandomForestClassifier
本周热门人工智能项目 44-19
关注我,这样你就不会错过伟大的人工智能项目。
这里有几个你可能会感兴趣的链接:
- [Labeling and Data Engineering for Conversational AI and Analytics](https://www.humanfirst.ai/)- [Data Science for Business Leaders](https://imp.i115008.net/c/2402645/880006/11298) [Course]- [Intro to Machine Learning with PyTorch](https://imp.i115008.net/c/2402645/788201/11298) [Course]- [Become a Growth Product Manager](https://imp.i115008.net/c/2402645/803127/11298) [Course]- [Deep Learning (Adaptive Computation and ML series)](https://amzn.to/3ncTG7D) [Ebook]- [Free skill tests for Data Scientists & Machine Learning Engineers](https://aigents.co/skills)
上面的一些链接是附属链接,如果你通过它们进行购买,我会赚取佣金。请记住,我链接课程是因为它们的质量,而不是因为我从你的购买中获得的佣金。
你只看系数
yolact 是一个简单的、完全卷积的实时实例分割模型,其任务是检测和描绘图像中出现的每个不同的感兴趣对象。这是用于显著更快(比任何以前的竞争方法)实例分割的开源代码。
细流
Streamlit 让你用看似简单的 Python 脚本为你的机器学习项目创建应用。它支持热重新加载,因此当您编辑和保存文件时,您的应用程序会实时更新。不需要弄乱 HTTP 请求、HTML、JavaScript 等。你所需要的只是你最喜欢的编辑器和浏览器。
Streamlit 演示项目让你浏览整个 Udacity 自动驾驶汽车数据集并实时运行推理。
PyTorch 示例
数据-科学-ipython-笔记本
数据科学 Python 笔记本深度学习(TensorFlow,Theano,Caffe,Keras),scikit-learn,Kaggle,大数据(Spark,Hadoop MapReduce,HDFS),matplotlib,pandas,NumPy,SciPy,Python essentials,AWS,各种命令行。
pwnagotchi
不同于像大多数基于强化学习的人工智能那样仅仅玩超级马里奥或雅达利游戏, Pwnagotchi 随着时间的推移调整其参数,以便在你暴露的环境中更好地控制 WiFi。更具体地说,Pwnagotchi 正在使用一个带有 MLP 特征提取器的 LSTM 作为其针对 A2C 代理的策略网络。如果你对 A2C 不熟悉,这里有一个非常好的介绍性解释(以漫画的形式!)Pwnagotchi 如何学习背后的基本原则。
在你走之前
在 Twitter 上关注我,在那里我定期发布关于数据科学和机器学习的消息。
Photo by Courtney Hedger on Unsplash