用于情感分析的词嵌入
当对单词应用一键编码时,我们最终得到高维度的稀疏(包含许多零)向量。在大型数据集上,这可能会导致性能问题。此外,独热编码没有考虑单词的语义。所以像飞机和飞机这样的词被认为是两种不同的特征。虽然我们知道它们有非常相似的意思。单词嵌入解决了这两个问题。
单词嵌入是具有低得多的维度的密集向量。其次,词与词之间的语义关系反映在向量的距离和方向上。
我们将使用 Kaggle 上的推特在线感知数据集。该数据集包含大约 15K 条推文,具有 3 种可能的情绪类别(积极、消极和中立)。在我之前的帖子中,我们试图通过对单词进行标记和应用两个分类器来对推文进行分类。让我们看看单词嵌入是否能胜过它。
阅读完本教程后,你将知道如何使用 Keras 的嵌入层计算特定任务的单词嵌入。其次,我们将研究在更大的语料库上训练的单词嵌入是否可以提高我们的模型的准确性。
本教程的结构是:
- 单词嵌入背后的直觉
- 项目设置
- 数据准备
- Keras 及其嵌入层
- 预训练单词嵌入—手套
- 多维度训练词嵌入
单词嵌入背后的直觉
在我们可以在分类器中使用单词之前,我们需要将它们转换成数字。一种方法是简单地将单词映射成整数。另一种方法是一键编码单词。然后,每条 tweet 可以表示为一个向量,其维数等于语料库中的单词(有限的一组)。tweet 中出现的单词在向量中的值为 1。所有其他向量值等于零。
单词嵌入的计算方式不同。每个单词被定位到一个 多维空间 。这个空间中的维度数量由数据科学家选择。您可以尝试不同的维度,看看什么能提供最好的结果。
单词的 向量值表示其在该嵌入空间中的位置 。同义词之间的距离很近,而意思相反的词之间的距离很大。您还可以对向量应用数学运算,这会产生语义上正确的结果。一个典型的例子就是王和女的单词嵌入之和产生了皇后的单词嵌入。
项目设置
让我们从导入这个项目的所有包开始。
import pandas as pd
import numpy as np
import re
import collections
import matplotlib.pyplot as plt
from pathlib import Path
from sklearn.model_selection import train_test_split
from nltk.corpus import stopwords
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences
from keras.utils.np_utils import to_categorical
from sklearn.preprocessing import LabelEncoder
from keras import models
from keras import layers
我们定义了在整个项目中使用的一些参数和路径。大部分都是不言自明的。但是其他的将在代码中进一步解释。
NB_WORDS = 10000 # Parameter indicating the number of words we'll put in the dictionary
VAL_SIZE = 1000 # Size of the validation set
NB_START_EPOCHS = 10 # Number of epochs we usually start to train with
BATCH_SIZE = 512 # Size of the batches used in the mini-batch gradient descent
MAX_LEN = 24 # Maximum number of words in a sequence
GLOVE_DIM = 100 # Number of dimensions of the GloVe word embeddings
root = Path('../')
input_path = root / 'input/'
ouput_path = root / 'output/'
source_path = root / 'source/'
在这段代码中,我们还将使用一些帮助函数进行数据准备、建模和可视化。这里没有显示这些函数定义,以避免博客文章混乱。你可以随时参考 Github 里的笔记本看代码。
数据准备
读取数据和清理
我们读入包含 tweets 的 CSV 文件,并对其索引进行随机排序。之后,我们删除停用词和@提及。分离出 10%的测试集,以根据新数据评估模型。
df = pd.read_csv(input_path / 'Tweets.csv')
df = df.reindex(np.random.permutation(df.index))
df = df[['text', 'airline_sentiment']]
df.text = df.text.apply(remove_stopwords).apply(remove_mentions)
X_train, X_test, y_train, y_test = train_test_split(df.text, df.airline_sentiment, test_size=0.1, random_state=37)
将单词转换成整数
使用 Keras 的 标记器 ,我们将推文转换成整数序列。我们把单词的数量限制在 NB_WORDS 最常用的单词。此外,tweets 被一些过滤器清理,设置为小写,并在空格上分割。
tk = Tokenizer(num_words=NB_WORDS,
filters='!"#$%&()*+,-./:;<=>?@[\]^_`{"}~\t\n',lower=True, split=" ")
tk.fit_on_texts(X_train)
X_train_seq = tk.texts_to_sequences(X_train)
X_test_seq = tk.texts_to_sequences(X_test)
等长序列
每批都需要提供等长的序列。我们用pad _ sequences方法实现了这一点。通过指定***【maxlen】***,序列或用零填充或截断。
X_train_seq_trunc = pad_sequences(X_train_seq, maxlen=MAX_LEN)
X_test_seq_trunc = pad_sequences(X_test_seq, maxlen=MAX_LEN)
编码目标变量
目标类是需要转换成数字向量的字符串。这是通过 Sklearn 的 LabelEncoder 和 Keras 的to _ categorial方法完成的。
le = LabelEncoder()
y_train_le = le.fit_transform(y_train)
y_test_le = le.transform(y_test)
y_train_oh = to_categorical(y_train_le)
y_test_oh = to_categorical(y_test_le)
分离验证集
从训练数据中,我们分离出 10%的验证集用于训练。
X_train_emb, X_valid_emb, y_train_emb, y_valid_emb = train_test_split(X_train_seq_trunc, y_train_oh, test_size=0.1, random_state=37)
建模
Keras 和嵌入层
Keras 提供了一种将每个单词转换成多维向量的便捷方法。这可以用 嵌入 层来完成。它将计算单词嵌入(或使用预先训练的嵌入)并在字典中查找每个单词以找到其矢量表示。这里我们将训练 8 维的单词嵌入。
emb_model = models.Sequential()
emb_model.add(layers.Embedding(NB_WORDS, 8, input_length=MAX_LEN))
emb_model.add(layers.Flatten())
emb_model.add(layers.Dense(3, activation='softmax'))
emb_history = deep_model(emb_model, X_train_emb, y_train_emb, X_valid_emb, y_valid_emb)
我们有大约 74%的验证准确率。推文字数比较低,所以这个结果还是比较不错的。通过比较训练和验证损失,我们看到模型从时期 6 开始过度拟合。
在之前的一篇文章中,我讨论了我们如何避免过度拟合。如果你想深入研究这个话题,你可能想读一下。
当我们在所有数据(包括验证数据,但不包括测试数据)上训练模型并将时期数设置为 6 时,我们得到 78%的测试准确度。这个测试结果相当好,但是让我们看看我们是否可以通过预先训练的单词嵌入来改进。
emb_results = test_model(emb_model, X_train_seq_trunc, y_train_oh, X_test_seq_trunc, y_test_oh, 6)
print('/n')
print('Test accuracy of word embeddings model: {0:.2f}%'.format(emb_results[1]*100))
预训练单词嵌入—手套
因为训练数据不是很大,所以模型可能无法学习用于情感分析的良好嵌入。或者,我们可以加载建立在更大的训练数据上的预训练单词嵌入。
手套数据库包含多个预训练的单词嵌入,以及在推文 上训练的更具体的 嵌入。所以这可能对手头的任务有用。
首先,我们将单词嵌入放在字典中,其中键是单词,值是单词嵌入。
glove_file = 'glove.twitter.27B.' + str(GLOVE_DIM) + 'd.txt'
emb_dict = {}
glove = open(input_path / glove_file)
for line in glove:
values = line.split()
word = values[0]
vector = np.asarray(values[1:], dtype='float32')
emb_dict[word] = vector
glove.close()
通过将手套嵌入加载到字典中,我们可以在航空公司 tweets 的语料库中查找每个单词的嵌入。这些将被存储在一个形状为 NB_WORDS 和 GLOVE_DIM 的矩阵中。如果在手套字典中找不到某个单词,则该单词的单词嵌入值为零。
emb_matrix = np.zeros((NB_WORDS, GLOVE_DIM))
for w, i in tk.word_index.items():
if i < NB_WORDS:
vect = emb_dict.get(w)
if vect is not None:
emb_matrix[i] = vect
else:
break
然后,我们指定模型,就像我们对上面的模型所做的那样。
glove_model = models.Sequential()
glove_model.add(layers.Embedding(NB_WORDS, GLOVE_DIM, input_length=MAX_LEN))
glove_model.add(layers.Flatten())
glove_model.add(layers.Dense(3, activation='softmax'))
在嵌入层(这里是第 0 层)中,我们 将单词的权重 设置为在手套单词嵌入中找到的权重。通过将 可训练 设置为假,我们确保手套单词嵌入不能被改变。之后,我们运行模型。
glove_model.layers[0].set_weights([emb_matrix])
glove_model.layers[0].trainable = False
glove_history = deep_model(glove_model, X_train_emb, y_train_emb, X_valid_emb, y_valid_emb)
在 3 个时期之后,模型过拟合得很快。此外,与在训练数据上训练的嵌入相比,验证准确度较低。
glove_results = test_model(glove_model, X_train_seq_trunc, y_train_oh, X_test_seq_trunc, y_test_oh, 3)
print('/n')
print('Test accuracy of word glove model: {0:.2f}%'.format(glove_results[1]*100))
作为最后一个练习,让我们看看当我们用与手套数据相同的维数训练嵌入时会得到什么结果。
多维度训练单词嵌入
我们将用与手套嵌入相同的维数训练单词嵌入(即 GLOVE_DIM)。
emb_model2 = models.Sequential()
emb_model2.add(layers.Embedding(NB_WORDS, GLOVE_DIM, input_length=MAX_LEN))
emb_model2.add(layers.Flatten())
emb_model2.add(layers.Dense(3, activation='softmax'))
emb_history2 = deep_model(emb_model2, X_train_emb, y_train_emb, X_valid_emb, y_valid_emb)
emb_results2 = test_model(emb_model2, X_train_seq_trunc, y_train_oh, X_test_seq_trunc, y_test_oh, 3)
print('/n')
print('Test accuracy of word embedding model 2: {0:.2f}%'.format(emb_results2[1]*100))
在测试数据上,我们得到了很好的结果,但我们并没有优于使用 CountVectorizer 的 LogisticRegression。所以还是有提升的空间。
结论
最好的结果是利用在可用数据上训练的 100 维单词嵌入来实现的。这甚至超过了在更大的 Twitter 语料库上训练的单词嵌入的使用。
到目前为止,我们只是在展平的嵌入物上加了一个致密层。通过这样做, 我们不考虑 tweet 中单词 之间的关系。这可以用递归神经网络或 1D 卷积网络来实现。但这是未来文章的内容。
单词变形
Smooth image transition (morphing) from a tiger to a human (image courtesy: Google Images)
在这篇文章中,我将描述我如何使用 word2vec 的嵌入和 A*搜索算法在单词之间变形。
为了执行单词变形,我们将定义一个图 G ,其中节点集 N 表示单词,并且有一些非负的权重函数f:n×n→ℝ.给定一个起始字 S 和一个结束字 E ,我们的目标是在图中找到一条路径,该路径最小化由 f 导出的权重之和:
Fig. 1. Optimal path with minimal cost induced by f
通常当人们谈论单词变形时,他们指的是在 S 和 E 之间寻找一条路径,在那里单词之间只有一条边,这样一个可以通过改变一个字母从另一个获得,正如这里可以看到的。在这种情况下,当这种变化存在时, f ( n ₁, n ₂)为 1,否则为∞。
在这篇文章中,我将向你展示如何在语义相似的词之间变形,也就是说 f 将与语义相关。这里有一个例子来说明这两种方法的区别:给定 S = 齿, E = 光,一次改变一个字符的方法可以导致出现
tooth, booth, boots, botts, bitts, bitos, bigos, bigot, bight, light
虽然本文将要定义的语义方法会导致
tooth, retina, X_ray, light
你可以在这里找到完整的代码。
词汇语义学
为了捕捉单词语义,我们将使用预训练的 word2vec 嵌入[1]。对于那些不熟悉该算法的人,这里有一段来自维基百科的摘录:
Word2vec 将大型文本语料库作为其输入,并产生通常具有数百维的向量空间,语料库中的每个唯一单词被分配给该空间中的相应向量。单词向量被定位在向量空间中,使得语料库中共享共同上下文的单词在空间中彼此非常接近。
这意味着图中的每个节点都可以与高维空间中的某个向量相关联(在我们的例子中是 300)。因此,我们可以自然地定义每两个节点之间的距离函数。我们将使用余弦相似度,因为这是在想要对单词嵌入进行语义比较时通常使用的度量。从现在开始,我将重载一个节点符号 n 作为其关联单词的嵌入向量。
为了使用 word2vec 嵌入,我们将从这里下载 Google 的预训练嵌入,并使用gensim
包来访问它们。
选择权重函数
给定余弦相似距离函数,我们可以将我们的 f 函数定义为
Eq. 1. Definition of weight function using cosine similarity
然而,使用这种方法,我们将面临一个问题:最佳路径可能包括具有高权重的边,这将导致语义不相似的连续单词。
为了解决这个问题,我们可以将 f 改为
Eq. 2. Definition of weight function using cosine similarity limited to nearest neighbors
其中邻居 ( n ₁)表示在余弦相似性方面,图中距离 n ₁最近的节点。邻居的数量是可配置的。
A*搜索
现在我们已经定义了我们的图,我们将使用一个众所周知的搜索算法 A* [2]。
在该算法中,每个节点都有一个由两项组成的成本-g(n)+h(n)。
g ( n )是从 S 到 n 的最短路径的代价, h ( n )是估算从 n 到 E 的最短路径的代价的启发式方法。在我们的例子中,启发式函数将是 f 。
搜索算法维护一个叫做开集的数据结构。最初,这个集合包含 S ,在算法的每次迭代中,我们弹出开集中具有最小成本g(n)+h(n)的节点,并将其邻居添加到开集。当具有最小成本的节点是 E 时,算法停止。
这个算法适用于我们选择的任何启发式函数。但是,为了实际找到最佳路径,启发式函数必须是可接受的,这意味着它不能高估真实成本。不幸的是, f 是不可接受的。然而,我们将使用观察结果,即如果向量长度为 1,那么余弦相似性可以通过欧几里德距离上的单调变换来获得。这意味着这两个词在相似度排序方面是可以互换的。欧几里德距离是容许的(你可以用三角形不等式来证明它),所以我们可以用它来代替,通过定义
Eq. 3. Definition of weight function using euclidean distance
总之,我们将标准化单词嵌入,使用欧几里得距离作为寻找语义相似的单词的手段,并使用相同的欧几里得距离来指导搜索过程,以便找到最佳路径。
我选择了邻居 ( n )来包含它的 1000 个最近的节点。然而,为了使搜索更有效,我们可以使用 10 的dilute_factor
来稀释这些:我们选择最近的邻居、第 10 个最近的邻居、第 20 个邻居等等——直到我们有 100 个节点。其背后的直觉是,从某个中间节点到 E 的最佳路径可能经过其最近的邻居。如果它不通过,可能也不会通过第二个邻居,因为第一个和第二个邻居可能几乎相同。所以为了节省一些计算,我们跳过一些最近的邻居。
有趣的部分来了:
结果是:
['tooth', u'retina', u'X_ray', u'light']
['John', u'George', u'Frank_Sinatra', u'Wonderful', u'perfect']
['pillow', u'plastic_bag', u'pickup_truck', u'car']
最后的想法
实现单词变形项目很有趣,但没有在我能想到的任何一对单词上玩这个工具有趣。我鼓励你继续前进,自己玩这个游戏。请在评论中告诉我你发现了哪些有趣和令人惊讶的变形:)
本帖原帖www.anotherdatum.com。
参考
[1]https://papers . nips . cc/paper/5021-distributed-presentations-of-words-and-phrases-and-they-compositivity
【2】https://www . cs . Auckland . AC . NZ/courses/compsci 709s 2 c/resources/Mike . d/astarnilsson . pdf
来自手写文本的单词预测器
r 语言中图像到文字预测器的实现。
我已经很久没有为社区做贡献了。我回来是为了付出我应得的。但在此之前,让我告诉你我一直在做什么。这几个月职业生涯的亮点有两件事。第一,我在三月份的一次数据科学会议上发言(孟买版 WiDS )。第二,我成为了一个开源贡献者,并得到了一个合并到 numpy 包中的 pull 请求。Yayyy!
好吧,让我们从一些机器学习开始。我将简要介绍建模过程,并向您介绍 github repo,它包含实现建模的所有文件和代码。
工作
创建一个模型,从手写文本图像中识别 5 个字母的英语单词。这些单词是使用 EMNIST 数据集的字母创建的,该数据集是一组手写字符数字,转换为 28x28 像素的图像格式和数据集结构,与 MNIST 数据集直接匹配。你可以从[这里](http://What is it? The EMNIST dataset is a set of handwritten character digits derived from the NIST Special Database 19 and converted to a 28x28 pixel image format and dataset structure that directly matches the MNIST dataset)了解详情。
Example Image for Prediction
解决方案
为了解决这个问题,我们将建立两个模型。
- **图像模型:**单词预测器,通过使用多层感知器执行图像识别,它将接收图像并猜测图像中写了什么。
- **文本模型:**这将补充图像模型。该模型的任务是利用隐马尔可夫模型,根据前一个字符给出下一个字符的概率。例如,字母 n 或 a 或 x 后面的 e 的概率是多少。
步伐
请参考此 git 报告,以遵循以下步骤-
字符识别-使用 MLP 从图像中识别单词
github.com](https://github.com/Krithi07/Character_Recognition/blob/master/Code_image_text.R)
1.从 EMNIST 网站下载数据集:
- 向下滚动并点击“Matlab 格式数据集”
- 将会下载一个“Matlab.zip”文件。解压后你会发现 6 个 MS Access 数据集。我们使用“emnist-byclass”数据集来完成此任务,因为它包含所有字符
- 第一次使用“R.matlab”库读取 R 中的数据集
- 加载数据集后,将其保存为 R 格式(Rdata ),以备后用
EMNIST 数据集在训练集中包含 697,932 幅大小为 28 x 28 的标记图像,在测试集中包含 116,323 幅标记图像。图像以灰度表示,其中从 0 到 255 的每个像素值表示其暗度。
测试设置:下载文件em NIST 字。Rdata’ 来自 github repo。该文件包含长度为 5 的 1000 个单词的示例。该测试集是使用 EMNIST 数据集中的字母图像创建的。变量 X 包含单词的图像,变量 y 包含真实单词(标签),变量 y_hat 包含由 2 层神经网络结合 2 阶马尔可夫模型进行的预测。
用于预测的数据集格式:在调用预测函数之前,我们需要获得特定格式的原始输入数据。预测函数采用的输入 X 的大小为 28n×28L,其中 n 是输入样本的数量,L 是单词的长度(例如,对于长度为 5 的 100 个单词,X 的大小为 2800×140)。预测函数在‘Word _ Predictor _ Champ’中定义。R’ 文件。
2.从 github 下载支持文件:
'EMNIST_general_functions。这个文件有帮助函数,允许访问 EMNIST 数据集,计算误差,使用 EMNIST 数据集创建新单词。
‘EMNIST_run。R’- 这是代码执行文件。将 github repo 中的所有文件放在您选择的目录中,并运行’ EMNIST_run。r '文件。这将给出字符准确度和单词准确度来评估模型。
3.构建模型:
‘Code_image_text。R’ 文件有训练图像和文本模型的代码。文件“EMNIST_Model_Champ.h5”和“TEXT_Model_Champ”。“Rdata”是使用该文件中的代码创建的。这两者分别是图像和文本模型。我们来谈谈这里的代码-
安装需求: 我们将使用 tensorflow 构建图像识别的多层神经网络。您只需要这样做一次,以后,只需要从代码中调用库函数()来将需求加载到您的环境中
为图像模型准备数据: 我们下载的 EMNIST 数据已经分别有了训练和测试数据集。使用通用函数文件中定义的 EMNIST_read()函数读取数据。因为数据集中定义的每个字母或数字都是一个标签,而不是一个连续的值,所以让我们也将 y 转换成一个包含 62 个类的分类变量(emnist_byclass 数据集)
建立图像模型: 我们将通过交替密集层和脱落层来建立一个简单的多层神经网络。丢弃层通过丢弃两个密集层之间的指定百分比的连接来帮助模型的一般化。
我们使用了 Adam optimizer 和准确性作为衡量标准来拟合模型。最后,我们以 h5 格式保存模型。“h5”格式用于保存使用 keras 学习的模型,这些模型使用 R 的“保存”命令无法正确保存。
这里的想法是使用神经网络建立一个简单的图像识别模型,该模型将图像像素值作为特征,并将相应的标签作为目标变量。
为文本模型准备数据: 就像我们为构建图像模型做数据准备一样,我们需要为文本分析准备数据集。这里的尝试是训练一个懂英语的模型,这样它就可以补充来自图像的预测。例如“从不”这个词。如果图像模型由于字迹不清楚而将“e”预测为“c ”,则文本模型可以纠正它,因为它知道该语言。文本模型将知道,对于 5 个字母的单词,与“c”的概率相比,“nev”之后的“e”的概率更高
为了实现这一点,我们将采用英语语料库(书面文本的集合),从中构建词汇,然后告诉模型从中学习特征。具体来说,就是在给定前一个字符的情况下,学习下一个字符的概率。
我们在这里编写了一个函数,该函数执行数据清理部分,首先从文本中删除标点符号,过滤 5 个字母的单词,将所有单词转换为小写,提取只有字母(而不是数字)的单词,最后从这个精炼的语料库中只选择唯一的单词。
构建文本模型: 现在我们有了一个预处理过的语料库,我们可以用它来学习语言特征。对于这个任务,我们已经编写了一个隐马尔可夫模型,它基本上使用频率表得到给定 X(i)的 X(i+1)的概率。最后,让我们将这个模型保存为‘Text _ Model _ Champ’。Rdata '文件。
注意:您可以使用任何文本语料库来构建这个模型。通常,模型的性能取决于所提供的训练数据的质量和数量。在 github repo 上,我放了一个例子语料库(War_and_Peace.txt)供大家参考/使用。
4。预测单词:
’ Word_Predictor_Champ '。r’文件包含预测函数,该函数将具有像素值的 2D 阵列 X、图像的学习模型 m:image 和学习的文本模型 m:text 作为输入。该函数返回字符串标签 y 的 1D 数组,其中数组的每个元素都是长度为 l 的字符串
该函数首先将输入图像转换成所需的(nxl,28x28)形状的矩阵形式。然后使用图像模型得到每个字符的概率。使用文本模型获取下一个字符的概率(第一个字符除外)。将这两者的概率结合起来进行最终预测。
Photo by John Jennings on Unsplash
5.模型改进:
这是一个基本的模型,在字符级给出了大约 95%的准确率。以下是一些你可以尝试改进这种模式的想法:
- 使用一个巨大的文本语料库来改进文本模型。你可以使用维基百科语料库来训练一个更好的文本模型。或者,使用网络上预先训练好的模型
- 通过添加更多的隐藏层/隐藏单元来改进 MLP 模型。或者,使用更复杂的图像模型,如 CNN
- 通过编辑 Code_image_text 文件来概括模型。目前,守则有一些限制,如下所述。通过编辑这个文件中的一些硬编码部分,可以使模型更通用。a .仅预测来自 EMNIST 数据集的 28 x 28 像素图像 b .仅预测 5 个字母单词并接受训练 EMNIST_general_functions 文件包含帮助您从 EMNIST 数据集创建单词图像的函数。此功能可用于创建不同的训练/测试集,消除 5 个单词长度的限制
感谢阅读!希望它能帮助你开始字符识别。
如果您有任何问题/建议,请随时在这里发表您的评论,或者通过 LinkedIn / Twitter 与我联系
自然语言处理中的词表示(一)
在这篇博文中,我将讨论自然语言处理(NLP)中单词的表示。它是自然语言处理,尤其是神经网络的基本构件之一。它对深度学习模型的性能有着重要的影响。在博客文章的这一部分,我将描述相对简单的方法及其特点。
字典查找
最简单的方法是在字典中查找单词 ID。这种方法的基本步骤如下。
首先,取语料库,可以是单词、句子或文本的集合。将它们预处理成预期的格式。一种方法是使用词汇化,这是一个将单词转换为其基本形式的过程。例如,给定单词 walk,walking,walks 和walk,它们的引理将是 walk 。然后,将预处理后的词汇保存到文件中,如“vocabulary . txt”。
之后,通过创建单词和 ID 之间的映射来构建查找字典,即词汇表中的每个唯一单词都被分配一个 ID。
因此,将构建一个简单的查找字典,如下所示,从中可以查找单词 id。
Example of sample lookup dictionary.
然后,对于每个给定的单词,通过在字典中查找返回相应的整数表示。如果字典中不存在该单词,则应该返回与词汇外标记相对应的整数。在实践中,通常将词汇外令牌的值设置为字典的大小加 1,即长度(字典)+ 1。
虽然这是一种相对容易的方法,但它也有需要考虑的缺点。通过将标记视为整数,该模型可能会错误地假设自然排序的存在。例如,字典中包含的条目有 *1:“机场”和 2:“飞机”。*具有较大 ID 值的标记可能被深度学习模型认为比具有较小值的标记更重要,这是一个错误的假设。用这种类型的数据训练的模型容易失败。相反,带有序数值的数据如 size measures *1:“小”,2:“中”,3:“大”*适合这种情况。因为数据中有一个自然的顺序。
一键编码
单词表示的第二种方法是一键编码。主要思想是创建一个词汇大小向量,其中除了 1 之外都填充了 0。对于单个单词,只有相应的列用值 1 填充,其余的是零值。编码的记号将由维度为 1 × (N+ 1) 的向量组成,其中 N 是字典的大小,并且对于超出词汇表的记号,额外的 1 被加到 N。让我们看看字典中的单词是如何转换成一键编码的:
正如我们所看到的,对于每个单词,只有对应于单词的列被激活。
这种顺序表示编码的优点是它不会遭受不希望的偏差。然而,其巨大而稀疏的矢量表示需要大量的计算内存。
分布表示
第三种方法是一系列分布式表示。这种方法背后的主要思想是,通常出现在相似上下文中的单词将具有相似的含义。其思想是存储单词-上下文共现矩阵 F ,其中行代表词汇表中的单词,列代表上下文。上下文可以是训练句子上的滑动窗口,甚至是文档。矩阵条目包括频率计数或 tf-idf(术语频率-逆文档频率)得分。这里有一个简单的例子:
波士顿有飞往美国主要城市的航班。
由于恶劣的天气状况,飞往波士顿的航班被取消了。
此外,一些函数 g 可以应用于 F 以降低噪声、平滑频率或降低表示向量的维数。函数 g 可以做简单的变换,比如线性分解,但是也有高级的方法,比如潜在的狄利克雷分配。由于上下文的数量可能非常大,例如文档可能包含数千个句子,这些方法被认为是低效的。
上述方法易于使用,但具有难以训练和需要大内存的缺点。此外,它们不像高级方法那样将单词的意思结合到表示中。在下面的自然语言处理中的单词表示系列中,我将描述更高级的方法。下一个系列可以在 这里找到 。
自然语言处理中的词表示第二部分
在单词表征系列的前一部分( 第一部分 ) 中,我谈到了固定的单词表征,它对单词的语义(意义)和相似性不做任何假设。在这一部分,我将描述一系列的分布式单词表示。主要思想是将单词表示为特征向量。vector 中的每个条目代表单词含义中的一个隐藏特征。它们可以揭示语义或句法依赖性。在下面的例子中,我们看到了 300 维的单词表示。我们可以观察到*‘flight’和‘plane’的向量值与 s 的值相似,它们之间的数值差异很小。这同样适用于‘河’和‘湖’*,因为它们具有密切相关的含义。
因此,它生成有用的属性,如线性关系。一个广为使用的例子是这样的类比:国王对女王就像男人对女人*一样。*国王和王后之间的差异几乎等同于向量空间中男人和女人之间的差异,这导致以下运算有效。
“国王—王后+男人”最接近“女人”
Word2Vec
一个广泛使用的分布式单词表示是 Skip-Gram 模型,它是 Word2Vec 库的一部分。它是由谷歌的托马斯·米科洛夫领导的研究小组创造的。主要思想是通过单词的邻居来表示单词。它试图预测给定单词的所有相邻单词(上下文)。
根据文件,模型的目标定义如下:
Objective function for Skip-Gram model
其中 w 是训练字, c 是上下文的大小。所以它的目标是找到可以预测周围单词的单词表征。
我们可以在我们的数据集上训练 Word2Vec,或者加载预训练的向量。谷歌公布了在谷歌新闻数据集(约 1000 亿字)的一部分上训练的预训练向量。该模型包含 300 万个单词和短语的 300 维向量。这里有这里有。
这些步骤使我们能够使用 Word2Vec 库中预先训练好的向量。
我们可以使用 gensim 加载预训练的单词向量,例如:
预训练向量表示的查找是这样的
手套
分布式单词表示的另一个成员是 Glove,它是全局向量的缩写。虽然 Word2Vec 捕获某些局部上下文窗口,但 GloVe 利用了来自语料库(一个大型文本集合)的单词的总体共现统计。它包括两个重要步骤。首先,构建一个词共现矩阵。对于每个单词,我们计算条件概率,例如对于单词 water P(k|water) ,其中 k 是来自词汇表的单词。如果 k 是流,则 P 的值为高,如果 k 是时尚,则期望值为低,因为它们通常不会同时出现。在完成所有的统计计算后,大矩阵就形成了。然后通过归一化计数和对数平滑来减少高维上下文矩阵,如下所示。
我们还可以使用 gensim 加载预训练的手套向量,这些向量是在维基百科数据上训练的。
我们需要将 GloVe 格式转换为 Word2Vec,以便与 gensim 一起使用,例如:
更多技术细节可以在这里找到。
Glove 和 Word2Vec 都允许对单词进行有用的操作,比如查找语义相似的单词。让我们比较一下最相似单词的结果。
使用 Glove 获得与’ flight '意思相似的单词。
使用 Word2Vec 获得与’航班’意思相似的单词。
正如我们所观察到的,这两个向量的输出并不精确。不同之处在于相似度得分和返回的单词。
在上述方法中,分布式单词表示是一种强大的技术。它没有简单方法的不良特性,并且可能将单词的语义信息合并到它们的表示中。然而,它不能为不在词汇表中的单词产生向量。此外,罕见词的向量表示法学得不够好。在这些情况下,最好使用 FastText 模型,这将在下一部分描述。
词到向量—自然语言处理
自然语言处理为什么很难?
计算机用编程语言与人类交流,这种语言清晰、精确,而且通常是结构化的。但是,自然(人类)语言有很多歧义。有多个意思相同的词(同义词),有多个意思的词(一词多义),其中一些在性质上完全相反(自动反义词),还有当用作名词和动词时表现不同的词。这些词在自然语言的上下文中是有意义的,人类可以很容易地理解和区分,但机器不能。这就是 NLP 成为人工智能中最困难和最有趣的任务之一的原因。
使用自然语言处理可以完成什么?
让计算机“理解”人类语言可以完成几项任务。一个活生生的例子就是我在这篇文章中用来检查拼写和语法的软件。以下是目前使用 NLP 完成的一些任务:
- 拼写和语法检查
- 寻找同义词和反义词
- 从文档、网站解析信息
- 理解句子、文档和查询的含义
- 机器翻译(例如,将文本从英语翻译成德语)
- 回答问题和执行任务(例如安排约会等。)
如何表示文字?
首先,我们需要能够将单词表示为机器学习模型的输入。表示单词的一种数学方法是向量。英语中估计有 1300 万个单词。但其中许多是相关的。从配偶到伴侣,从酒店到汽车旅馆。那么,我们是否希望 1300 万个单词都有独立的向量呢?
不。我们必须寻找一个 N 维向量空间(其中 N << 13 million) that is sufficient to encode all semantics in our language. We need to have a sense of similarity and difference between words. We can exploit concept of vectors and distances between them (Cosine, Euclidean etc. ) to find similarities and differences between words.
我们如何表示单词的意思?
如果我们对英语词汇中的 1300 万个单词(或者更多)使用不同的向量,我们将面临几个问题。首先,我们有一个大的向量,里面有很多“0”和一个“1”(在不同的位置代表不同的单词)。这也被称为**一键编码。**其次,当我们在谷歌中搜索诸如“新泽西州的酒店”等短语时,我们希望返回与新泽西州的“汽车旅馆”、“住宿”和“住宿”相关的结果。如果我们使用一键编码,这些单词没有自然的相似性。理想情况下,我们希望同义词/相似词的点积(因为我们处理的是向量)接近 1。
基于分布相似性的表示:
从一个人交的朋友你就可以知道他说了什么——j·r·弗斯
用非常简单的外行话来说,就拿一个字‘银行’来说吧。这个词有许多含义,其中一个是金融机构,另一个是水边的土地。如果在一个句子中,银行与邻近的词如货币、政府、国库、利率等一起出现。我们可以理解为前者的意思。相反,如果相邻的词是水、海岸、河流、土地等。情况是后者。我们可以利用这个概念来处理多义词和同义词,并使我们的模型能够学习。
Word2Vec
我们如何构建简单、可扩展、快速的训练模型,能够运行数十亿个单词,产生非常好的单词表示?让我们研究一下 Word2Vec 模型来寻找这个问题的答案。
Word2Vec 是一组帮助导出单词与其上下文单词之间关系的模型。让我们看看 Word2Vec 中的两个重要模型:Skip-grams 和 CBOW
跳棋
在 Skip-gram 模型中,我们取一个中心单词和一个**上下文(邻居)**单词的窗口,并且我们尝试为每个中心单词预测出一些窗口大小的上下文单词。因此,我们的模型将定义一个概率分布,即给定一个中心词,一个词在上下文中出现的概率,我们将选择我们的向量表示来最大化该概率。
连续单词包模型(CBOW)
从抽象的角度来说,这与跳格是相反的。在 CBOW 中,我们试图通过对周围单词的向量求和来预测中心单词。
这是关于把单词转换成向量。但是“学习”发生在哪里呢?本质上,我们从单词向量的小的随机初始化开始。我们的预测模型通过最小化损失函数来学习向量。在 Word2vec 中,这是通过前馈神经网络和优化技术(如随机梯度下降)实现的。还存在基于计数的模型,其在我们的语料库中形成单词的共现计数矩阵;我们有一个大矩阵,每行代表“单词”,每列代表“上下文”。“上下文”的数量当然很大,因为它在大小上基本上是组合的。为了克服这个尺寸问题,我们将 SVD 应用于矩阵。这减少了矩阵的维数,保留了最大限度的信息。
总之,将单词转换为深度学习算法可以摄取和处理的向量,有助于更好地理解自然语言。小说家埃尔·多克托罗在他的《比利·巴斯盖特》一书中颇有诗意地表达了这一观点。
就像数字是语言一样,语言中的所有字母都变成了数字,所以每个人都以同样的方式理解它。你失去了字母的声音,不管它们是咔嚓声、砰砰声还是碰上颚的声音,或者发出“哦”或“啊”的声音,以及任何可能被误读或被它的音乐或它放在你脑海中的图片欺骗的声音,所有这些都消失了,连同口音,你有了一种完全新的理解,一种数字语言,一切对每个人来说都变得像墙上的文字一样清晰。所以正如我所说的,阅读数字的时间到了。
面向非 NLP 数据和研究人员的词向量
单词向量代表了在提高我们分析单词、句子和文档之间关系的能力方面的一个重大飞跃。在这样做的过程中,他们通过向机器提供比以前可能使用的传统单词表示更多的单词信息来推进技术。正是单词向量使得语音识别和机器翻译等技术成为可能。关于词向量有很多很好的解释,但在这一篇中,我想让不太熟悉自然语言处理(NLP)的数据和研究人员也能理解这个概念——有关基本 NLP 概念的初级读本,请在这里查看我的帖子:https://data flume . WordPress . com/2017/03/17/intro-NLP-python-spacy/。
什么是词向量?
单词向量只是代表单词意思的数字向量。现在,这还不是很清楚,但我们一会儿会回来。首先,考虑一下为什么单词向量被认为是对传统单词表示的一次飞跃,这是很有用的。
传统的 NLP 方法,如一键编码和词袋模型(即,使用虚拟变量来表示单词在观察结果(例如,句子)中的存在或不存在),虽然对一些机器学习(ML)任务有用,但不能捕获关于单词的含义或上下文的信息。这意味着潜在的关系,如上下文的密切程度,不能在单词集合中被捕获。例如,一键编码不能捕捉简单的关系,例如确定单词“狗”和“猫”都是指经常在家庭宠物的上下文中讨论的动物。这种编码通常为简单的 NLP 任务(例如,电子邮件垃圾分类器)提供了足够的基线,但对于更复杂的任务(如翻译和语音识别)来说,却缺乏复杂性。本质上,传统的自然语言处理方法,比如一键编码,不能捕捉单词集合之间的句法(结构和语义(含义)关系,因此,以一种非常幼稚的方式来表示语言。
相反,单词向量将单词表示为多维连续浮点数,其中语义相似的单词被映射到几何空间中的邻近点。更简单地说, 一个单词向量是一行实数值 (与虚数值相对),其中 每个点捕捉单词含义的一个维度 和 ,其中语义相似的单词具有相似的向量 。这意味着像车轮和发动机这样的词应该和汽车这样的词有相似的词向量(因为它们的意思相似),而香蕉这样的词应该是相当遥远的。换句话说,在相似上下文中使用的单词将被映射到一个近似的向量空间(我们将在下面讨论这些单词向量是如何创建的)。将单词表示为向量的美妙之处在于它们有助于数学运算。例如,我们可以增加和减少向量,这里的典型例子表明,通过使用词向量,我们可以确定:
国王-男人+女人=王后
换句话说,我们可以从代表国王的单词向量中减去一个意思(即男性),添加另一个意思(女性),并显示这个新的单词向量(国王-男人+女人)最接近地映射到代表王后的单词向量。
单词向量中的数字代表单词在维度上的分布权重。在简化的意义上,每个维度代表一个意义,单词在该维度上的数字权重捕捉了它与该意义的关联的紧密程度。因此,单词的 语义被嵌入到向量的维度中。
词向量的简化表示
在图中,我们假设每个维度都有一个明确定义的含义。例如,如果你想象第一个维度代表“动物”的意义或概念,那么每个词在那个维度上的权重代表它与那个概念的密切程度。
这是对单词向量的一个相当大的简化,因为维度并不具有如此明确定义的含义,但这是一个有用且直观的方法来让你理解单词向量维度的概念。
我们可以使用 Python NLP 库 spaCy(在这里查看我的介绍:https://data flume . WordPress . com/2017/03/17/intro-NLP-Python-spaCy/,最近也移植到了 R【https://github.com/kbenoit/spacyr】的上,快速访问一些预先训练好的 300 维单词向量。我们创建一个单词列表,应用 spaCy 的解析器,提取每个单词的向量,将它们堆叠在一起,然后提取两个主要成分用于可视化。
https://gist . github . com/Conor mm/ca 0 CDF 78 fa 7a 91 fdacf 500 ff 4 dff 0645
在这里,我们简单地提取不同动物的向量和可能用来描述其中一些动物的单词。正如开头提到的,单词向量非常强大,因为它们允许我们(和机器)通过在连续的向量空间中表示不同单词来识别它们之间的相似性。你可以在这里看到像“狮子”、“老虎”、“猎豹”和“大象”这样的动物的向量是如何非常接近的。这可能是因为它们经常在类似的背景下被讨论,例如这些动物很大,是野生的,有潜在的危险——事实上,描述性的词“野生”与这组动物非常接近。
相似的单词在向量空间中被映射在一起。注意猫和狗和宠物有多接近,大象、狮子和老虎有多聚在一起,以及描述性的词语是如何聚在一起的。
同样有趣的是,“野生”、“动物园”和“驯养”这三个词是如何相互对应的。这是有道理的,因为它们是经常被用来描述动物的词,但突出了词向量的惊人力量!
词向量从何而来?
此时一个极好的问题是这些维度和权重从何而来?!生成单词向量有两种常见方式:
- 单词/上下文共现的计数
- 给定单词的上下文预测(skip-gram 神经网络模型,例如 word2vec)
*注意:下面我描述了一种生成单词向量的高级 word2vec 方法,但是可以在这里找到计数/共现方法的很好的概述(https://medium . com/ai-society/jkljlj-7d6e 699895 C4)。
生成单词向量的两种方法都建立在 Firth(1957)分布假设的基础上,该假设陈述:
“从一个人交的朋友,你就可以知道他说的是什么”
换句话说,拥有相似语境的单词往往有相似的意思。单词的上下文在实际意义上是指其周围的单词,并且单词向量(通常)是通过预测给定单词的上下文的概率而生成的。换句话说,组成单词向量的权重是通过预测其他单词在上下文中接近给定单词的概率来学习的。这类似于试图填充某个给定输入单词周围的空白。例如,给定输入序列,“蓬松的狗在追猫时吠叫”,单词“狗”和“吠叫”的双窗口(焦点单词之前和之前的两个单词)上下文看起来像:
我不想过多地探究神经网络如何学习单词嵌入的数学细节,因为更有资格这样做的人已经解释了这一点。尤其是这些帖子对我理解单词向量是如何学习的很有帮助:
- 深度学习、NLP 和表示法(http://colah . github . io/posts/2014-07-NLP-RNNs-re presentations/)
- 词向量的惊人力量(https://blog . acolyer . org/2016/04/21/the-amazing-power-of-word-vectors/)
- Word2Vec 教程—跳过 Gram 模型(http://mccormickml . com/2016/04/19/word 2 vec-Tutorial-The-Skip-Gram-Model/)
然而,考虑到它的流行性和实用性,接触一下 word2vec 模型的工作原理是很有用的。word2vec 模型只是一个具有单个隐藏层的神经网络,它被设计为通过估计一个单词与作为输入给出的另一个单词“接近”的概率来重建单词的上下文。
该模型针对语料库中每个单词的单词、上下文配对进行训练,即:
(狗)
(狗,毛茸茸的)
(狗叫)
(狗,作为)
请注意,从技术上讲,这是一个受监督的学习过程,但您不需要带标签的数据—标签(目标/因变量)是从形成焦点单词上下文的单词中生成的。因此,使用窗口函数,模型学习使用单词的上下文。在这个简单的例子中,模型将了解到 fluffy 和barbed在单词 dog 的上下文(由窗口长度定义)中使用。
由 word2vec 模型创建的单词向量的一个迷人之处在于,它们是预测任务的副作用,而不是输出。换句话说,单词向量不是预测的,(预测的是上下文概率), 单词向量是输入 的学习表示,用于预测任务,即预测给定上下文的单词。单词向量是模型学习单词的良好数字表示的尝试,以便最小化其预测的损失(误差)。随着模型的迭代,它调整其神经元的权重,试图最小化其预测的误差,并在这样做的过程中,逐渐完善其对单词的表示。在这样做的过程中,单词的“含义”嵌入了网络隐藏层中每个神经元学习的权重中。
因此,word2vec 模型接受单个单词作为输入(表示为语料库中所有单词中的独热编码),并且该模型试图预测语料库中随机选择的单词位于输入单词附近位置的概率。这意味着对于,每个输入单词都有 n 个输出概率,其中 n 等于语料库的总大小。这里的神奇之处在于,训练过程只包括单词的上下文,而不是语料库中的所有单词。这意味着在我们上面的简单例子中,给定单词“狗”作为输入,“汪汪”将比“猫”具有更高的概率估计,因为它在上下文中更接近,即它是在训练过程中学习的。换句话说,**模型试图预测语料库中的其他单词属于输入单词的上下文的概率。**因此,给定上面的句子(*“毛茸茸的狗在追逐一只猫时吠叫”)*作为输入,模型的运行将如下所示:
注意:这个概念神经网络是 Chris McCormick 博客文章中的图表的密友,链接到上面的
经历这个过程的价值是提取模型隐藏层的神经元已经学习的权重。正是这些权重形成了单词向量,即,如果你有 300 个神经元隐藏层,你将为语料库中的每个单词创建 300 维的单词向量。因此,这个过程的输出是大小为 n- 个输入单词* n 个隐藏层神经元的单词向量映射。
感谢你的阅读,希望你学到了新的东西:)
Word2Vec For Phrases —学习多个单词的嵌入
Photo by Alexandra on Unsplash
如何使用 Word2Vec 在给定的无监督语料库中学习相似术语
说到语义,我们都知道并喜欢著名的 Word2Vec [1]算法,该算法在许多自然语言处理应用中通过分布式语义表示来创建单词嵌入,如 NER、语义分析、文本分类等等。
然而,Word2Vec 算法当前实现的局限性是其单字自然行为。在 Word2Vec 中,我们试图根据上下文预测给定的单词(CBOW),或者根据给定的单词预测周围的上下文(Skip-Gram)。但是如果我们想把“美国航空公司”这个词作为一个整体嵌入进去呢?在这篇文章中,我将解释如何使用无监督的文本语料库为多个单词创建嵌入。如果你熟悉 Word2Vec 算法和单词嵌入,你可以跳过这篇文章的第一部分。
具体来说,我们将涵盖:
- 自然语言处理任务中的词汇表征。
- 分布假设[2]和 Word2Vec 算法。
- 从无监督文本中学习短语。
- 如何提取与给定短语相似的短语?
背景
我现在工作的公司,舒适分析,正在开发文本分析产品,同时专注于金融领域。它帮助企业获得大规模的可操作的见解。最近,我们发布了一个基于弹性搜索的新搜索引擎,以帮助我们的客户获得更精确、更集中的数据视图。在搜索引擎中查看用户的查询后,我们注意到许多客户正在搜索金融术语,而天真地使用查询执行全文搜索是不够的。例如,在用户搜索中出现多次的一个术语是“拐点”。
在 Investopedia 中寻找“拐点”的定义:
“拐点是指导致公司、行业、部门、经济或地缘政治形势发生重大变化的事件,可被视为一个转折点,在此之后,预期会出现具有积极或消极结果的巨大变化”
我们的客户希望看到他们所关注的公司的重大事件,因此,我们需要搜索更多与“拐点”具有相同含义的术语,如“转折点”、“引爆点”等。
从离散符号到连续向量
文字表述
语言中最细粒度的对象是字符,它构成了单词或记号。单词(和字符)是离散的和象征性的。仅仅从单词本身,或者从组成单词的字符来看,是无法分辨出“拉布拉多”和“狗”之间有什么联系的。
包话(鞠躬)
自然语言处理任务中最常见的特征提取是词袋(BOW)方法。在词袋中,我们查看给定语料库中词出现的直方图,而不考虑顺序。通常,我们寻找的不仅仅是一个单词,还包括双字母(“我想要”),三字母(“我想要”),或者一般情况下的 n 字母。标准化每个单词的计数是一种常见的方法,因为文档的长度可能不同(在大多数情况下)。
Normalized BOW.
BOW 表示的一个主要缺点是它是离散的,不能捕捉单词之间的语义关系。
词频—文档逆频(TF-IDF)
BOW 表示法的一个结果是,它为多次出现的单词打分,但其中许多单词没有给出任何有意义的信息,如“to”和“from”。我们希望区分多次出现的单词和出现多次但给出特定文档信息的单词。对船首向量进行加权是一种常见的做法,最常用的加权方法之一是 TF-IDF (Manning 等人,2008)。
TF-IDF weighting formula. There are many variations for TF-IDF, one can read more about it here.
然而,BOW 和 TF-IDF 都不能捕获单词的语义,因为它们以离散的方式表示单词或 n 元语法。
从上下文中学习单词
“告诉我你的朋友是谁,我就知道你是谁。”
分布假说认为出现在相同语境中的单词往往有相似的意思。这是文本语义分析的基础。这个假设背后的想法是,我们可以通过观察单词出现的上下文来学习单词的意思。人们可以很容易地看出“男孩喜欢在外面玩”这句话中的“play”和“The play was fantastic”这句话中的“play”有不同的意思。一般来说,离目标词近的词信息量更大,但在某些情况下,目标词和“远”的词在句子中有很长的依存关系。这些年来,已经开发了许多从上下文学习 word 的方法,其中包括著名的 Word2Vec,因为它在学术界和工业界都非常流行,所以本文将讨论它。
Word2Vec
分布假设是 Word2Vec 背后的主要思想。在 Word2Vec 中,我们有一个大型的无监督语料库,对于语料库中的每个单词,我们试图通过其给定的上下文(CBOW)来预测它,或者试图预测给定特定单词的上下文(Skip-Gram)。Word2Vec 是一个(浅层)神经网络,具有一个隐藏层(维度为 d)和负采样或分层 Softmax 的优化功能(可以阅读这篇论文了解更多详细信息)。在训练阶段,我们遍历语料库中的标记(目标单词)并查看大小为 k 的窗口(目标单词的每一边有 k 个单词,值通常在 2-10 之间)。
Image source
在训练结束时,我们将从网络中获得以下嵌入矩阵:
Emdedding matrix after Word2Vec training
现在,每个单词将不会用一个离散的、稀疏的向量来表示,而是用一个 d 维的连续向量来表示,每个单词的含义将通过它与其他单词的关系来捕捉[5]。这背后的原因是,在训练时间,如果两个目标词共享某个上下文,直观上这两个目标词的网络权重将彼此接近,从而它们的匹配向量也接近。因此,与基于计数的方法(如 BOW 和 TF-IDF)相比,我们获得了语料库中每个词的分布表示。由于分布行为,向量中的特定维度不会给出任何有价值的信息,但是将(分布)向量作为一个整体来看,可以执行许多相似性任务。比如我们得到 V(“国王”)-V(“男人”)+V(“女人”)~= V(“女王”)、V(“巴黎”)-V(“法国”)+V(“西班牙”)~= V(“马德里”)。此外,我们可以在向量之间执行相似性度量,如余弦相似性,并得到单词“总统”的向量将接近“奥巴马”、“特朗普”、“首席执行官”、“主席”等。
如上所述,我们可以使用 Word2Vec 对单词执行许多相似性任务。但是,正如我们上面提到的,我们想对不止一个单词做同样的事情。
从无监督文本中学习短语(搭配提取)
我们可以很容易地用无监督语料库创建二元模型,并将其作为 Word2Vec 的输入。例如,句子“我今天步行去公园”将被转换为“我今天步行去公园”,并且在 Word2Vec 训练短语中,每个双词将被视为单词。这是可行的,但是这种方法存在一些问题:
- 它将只学习二元模型的嵌入和,而这个二元模型中的许多并不真正有意义(例如,“walked_today”),我们将错过单元模型的嵌入,如“walked”和“today”。
- 只处理二元语法会创建一个非常稀疏的语料库。想想上面的句子“我今天去了公园”。假设目标词是“walked_today”,这个词在语料库中不是很常见,我们没有很多上下文示例来学习这个词的代表性向量。
那么,我们如何克服这个问题呢?如果单词的互信息足够强,我们如何只提取有意义的术语,同时保持单词是一元的?一如既往,答案就在问题里面— 互信息。
互信息
两个随机变量 X 和 Y 之间的互信息是 X 和 Y 之间相关性的度量。形式上:
Mutual Information (MI) of random variables X and Y.
在我们的例子中,X 和 Y 表示语料库中的所有二元语法,因此 Y 紧跟在 X 之后。
点态互信息
PMI 是对 y 的 x 的具体事件之间的相关性的度量。例如:x =已走,y =今天。形式上:
PMI of concrete occurrences of x and y.
很容易看出,当两个词 x 和 y 一起出现很多次,但不是单独出现时,PMI(x;y)将具有高值,而如果 x 和 y 完全独立,则它将具有 0 值。
归一化逐点互信息(NPMI)
虽然 PMI 是对 x 和 y 出现的相关性的度量,但我们没有其值的上限[3]。我们需要一个可以在所有二元模型之间进行比较的度量,因此我们可以只选择高于某个阈值的二元模型。我们希望 PMI 度量在完全相关的单词 x 和 y 上具有最大值 1。形式上:
Normalized Pointwise Mutual Information of x and y.
数据驱动的方法
从文本中提取短语的另一种方法是使用下一个公式[4],该公式考虑了单字和双字的计数以及用于防止创建过于罕见的单词的双字的折扣系数。形式上:
Read this article for more details.
提取相似的短语
既然我们有办法从大型无监督语料库中提取有意义的二元语法,我们可以用高于某个阈值的 NPMI 将二元语法替换为一个元语法,例如:“拐点”将被转换为“拐点”。通过将转换后的语料库与二元语法一起使用,并再次运行形成三元语法的过程(使用较低的阈值),可以很容易地创建三元语法。类似地,我们可以用递减的阈值对 n 元文法继续这个过程。
我们的语料库由大约 6000 万个句子组成,总共包含 16 亿个单词。使用数据驱动的方法,我们花了 1 个小时构建二元模型。阈值为 7 且最小术语数为 5 时获得最佳结果。
我们使用评估集来衡量结果,该评估集包含我们想要识别的重要二元模型,如财务术语、人名(主要是 CEO 和 CFO)、城市、国家等。我们使用的度量是一个简单的回忆:从我们提取的二元模型中,评估测试的覆盖率是多少。在这个特定的任务中,我们更关心回忆而不是精度,所以我们允许自己在提取二元模型时使用相对较小的阈值。我们确实考虑到,当降低阈值时,我们的精度可能会变得更差,反过来,我们可能会提取不太有价值的二元模型,但这比在执行查询扩展任务时丢失重要的二元模型要好。
示例代码
以一种记忆高效的方法逐行阅读语料库(我们假设每行包含一个句子):
def get_sentences(input_file_pointer):
while True:
line = input_file_pointer.readline()
if not line:
break
yield line
通过修剪前导空格和尾随空格、小写字母、删除标点符号、删除不必要的字符并将重复的空格减少为一个空格来清理句子(请注意,这并不是真正必要的,因为我们稍后将通过空格字符来标记我们的句子):
import redef clean_sentence(sentence):
sentence = sentence.lower().strip()
sentence = re.sub(r’[^a-z0-9\s]’, '’, sentence)
return re.sub(r’\s{2,}’, ' ', sentence)
用一个简单的空格定界符来标记每一行(有更高级的标记化技术,但是用一个简单的空格来标记给我们很好的结果,并且在实践中效果很好),并删除停用词。去除停用词是任务相关的,在一些 NLP 任务中,保留停用词会产生更好的结果。人们应该评估这两种方法。对于这个任务,我们使用了 Spacy 的停用词集。
from spacy.lang.en.stop_words import STOP_WORDSdef tokenize(sentence):
return [token for token in sentence.split() if token not in STOP_WORDS]
现在,我们已经用一个二维矩阵表示了我们的句子,我们可以构建二元模型了。我们将使用真正推荐用于 NLP 语义任务的 Gensim 库。幸运的是,Genim 有一个短语提取的实现,既有 NPMI,也有上面 Mikolov 等人的数据驱动方法。人们可以很容易地控制超参数,如确定最小术语数、阈值和得分(数据驱动方法的“默认”和 NPMI 的“npmi”)。请注意,这两种方法的值是不同的,需要考虑到这一点。
from gensim.models.phrases import Phrases, Phraserdef build_phrases(sentences):
phrases = Phrases(sentences,
min_count=5,
threshold=7,
progress_per=1000)
return Phraser(phrases)
构建完短语模型后,我们可以轻松地保存它并在以后加载它:
phrases_model.save('phrases_model.txt')phrases_model= Phraser.load('phrases_model.txt')
现在我们有了一个短语模型,我们可以用它来提取给定句子的二元语法:
def sentence_to_bi_grams(phrases_model, sentence):
return ' '.join(phrases_model[sentence])
我们希望基于我们的语料库创建一个新的语料库,将有意义的二元语法连接在一起供以后使用:
def sentences_to_bi_grams(n_grams, input_file_name, output_file_name):
with open(input_file_name, 'r') as input_file_pointer:
with open(output_file_name, 'w+') as out_file:
for sentence in get_sentences(input_file_pointer):
cleaned_sentence = clean_sentence(sentence)
tokenized_sentence = tokenize(cleaned_sentence)
parsed_sentence = sentence_to_bi_grams(n_grams, tokenized_sentence)
out_file.write(parsed_sentence + '\n')
学习相似的短语
在上述短语之后,我们的语料库包含短语,我们可以使用它作为 Word2Vec 训练的输入(可能需要更改超参数),与之前一样。训练短语会将“拐点”视为一个单词,并将学习一个分布式 d 维向量,该向量将接近于“临界点”或“拐点”等术语的向量,这是我们的目标!
在我们的 16 亿单词语料库上,我们花了 1 个小时来构建二元模型,又花了 2 个小时在使用 AWS Sagemaker 服务的具有 16 个 CPU 和 64 个 ram 的机器上训练 Word2Vec(具有批处理 Skip-Gram、300 个维度、10 个时期、k=5 的上下文、5 的负采样、0.01 的学习率和 5 的最小单词计数)。关于如何使用 AWS Sagemaker 服务来训练 Word2Vec 的一个很好的笔记本例子可以在这里找到。
人们也可以使用 Gensim 库来训练 Word2Vec 模型,例如这里的。
例如,当给出术语“拐点”时,我们得到以下相关术语,按照它们来自它们表示的向量和“拐点”向量的余弦相似性分数排序:
"terms": [
{
"term": "inflection",
"score": 0.741
},
{
"term": "tipping_point",
"score": 0.667
},
{
"term": "inflexion_point",
"score": 0.637
},
{
"term": "hit_inflection",
"score": 0.624
},
{
"term": "inflection_points",
"score": 0.606
},
{
"term": "reached_inflection",
"score": 0.583
},
{
"term": "cusp",
"score": 0.567
},
{
"term": "reaching_inflection",
"score": 0.546
},
{
"term": "reached_tipping",
"score": 0.518
},
{
"term": "hitting_inflection",
"score": 0.501
}
]
我们的一些客户希望看到黑色星期五对公司销售的影响,所以当给出术语“黑色星期五”时,我们得到:
"terms": [
{
"term": "cyber_monday",
"score": 0.815
},
{
"term": "thanksgiving_weekend",
"score": 0.679
},
{
"term": "holiday_season",
"score": 0.645
},
{
"term": "thanksgiving_holiday",
"score": 0.643
},
{
"term": "valentine_day",
"score": 0.628
},
{
"term": "mother_day",
"score": 0.628
},
{
"term": "christmas",
"score": 0.627
},
{
"term": "shopping_cyber",
"score": 0.612
},
{
"term": "holiday_shopping",
"score": 0.608
},
{
"term": "holiday",
"score": 0.605
}
]
很酷,不是吗?
结论
在这篇文章中,我们介绍了 NLP 任务中单词表示的不同方法(BOW、TF-IDF 和单词嵌入),学习了如何使用 Word2Vec 从上下文中学习单词表示,了解了如何从给定的语料库中提取有意义的短语(NPMI 和数据驱动方法),以及如何转换给定的语料库,以便使用 Word2Vec 算法为每个提取的术语/单词学习相似的术语/单词。这个过程的结果可以用于下游任务,如信息提取任务中的查询扩展、文档分类、聚类、问答等等。
感谢阅读!
参考
[1] Mikolov,t .,Chen,k .,Corrado,G.S .,& Dean,J. (2013 年)。向量空间中单词表示的有效估计。 CoRR,abs/1301.3781 。
[2]哈里斯,Z. (1954 年)。分配结构。 Word ,10(23):146–162。
[3]布马,G. (2009 年)。搭配抽取中的归一化(逐点)互信息。
[4]t . miko lov,Sutskever,I .,Chen,k .,Corrado,G.S .,& Dean,J. (2013 年)。词和短语的分布式表示及其组合性。辊隙。
[5]戈德堡、赫斯特、刘、张(2017)。自然语言处理的神经网络方法。计算语言学,44 ,193–195。
Word2Vec 遭遇特朗普推文——视觉分析
TL;速度三角形定位法(dead reckoning)
你会发现:
特朗普发推特?真的吗?
我知道,我知道——“又一个对特朗普推文的分析?”,但也许没那么糟糕?“嘿,也许我是第一个做这种类型分析的人?”
“嗯,是的,但这并不意味着它是数据科学——任何人都可以简单地看一看,然后做出结论。”
“…好吧,那么我正在做的 确切地说是 的事情呢?”
你知道,现在我已经花了至少 5 天半的时间来做这件事(大部分时间都是为了让图表看起来足够好,符合我的完美主义者的口味),我觉得有点愚蠢。我甚至找到了一篇很棒的文章,解释了几乎与我相同的分析。不,说真的,看看这里的——太棒了。
…不管怎样。既然我们已经解决了“这已经被做了 5700 万次,而你的分析是垃圾”的问题,我们可以开始了。
Word2Vec 和集群
我真的很喜欢将聚集的想法——因为相似的东西几乎总是在一起,因此可以将它们分组或聚集在一起。
例如,如果一个女人开着 SUV,有孩子,留着标志性的发型,她很可能属于“我能和经理说话吗”这一类。
Can I speak to the manager?
聚类也是数字类别的完美匹配:年龄、薪水、职位等。利用这一点,公司可以识别出高收入——高支出群体,在每一个 YouTube 视频之后用不间断的广告轰炸他们。
但是文本聚类呢?
对你来说,“回头见”后面可能会跟着“鳄鱼”或“一会儿”后面可能会跟着“鳄鱼”,这似乎是显而易见的,但对计算机来说,这种逻辑是荒谬的:“这是一种杀手动物,再见,你说它们相似是什么意思,哔哔 BOOP”(用机器人的声音朗读)。这就是 Word2Vec 算法大放异彩的地方。
跳过几乎每一个细节,该算法所做的是寻找在相似上下文中使用过的单词,并基于此创建它们的相似度。
如果你让计算机根据四年级英语课上使用的单词做出决定,它可能会认为“再见”和“鳄鱼”几乎是相同的短语,但如果你把它带到一个新闻站,它会把“鳄鱼”和“残忍地谋杀了一个小孩”放在一起。
这就是 Word2Vec 的闪光点——你可以用任何你想要的数据来训练它!你可以在你的脸书聊天记录、特朗普推文甚至产品评论中创建词语相似度云,根据上下文,可能会将“假”和“新闻”放在一起。
特朗普会见 Word2Vec
单词相似度云相当简单——单词越接近,它们就越相似。注意,并不是所有的单词都包括在内。是的,科菲也不见了。
Full word cloud. To represent Word2Vec in 2D, I used t-SNE.
太美了。那它是什么呢?嗯,有几件事。首先,如果你花同样多的时间试图绘制一个符合我所有完美主义者需求的图表,你会发现这里有一个轻微的趋势。
注意,左上方有更多的正(黄色)气泡?没错。让我们仔细看看。
这看起来很像感激的声音——我们到处都有像祝贺、美好、感谢、欢迎这样的词。最左边的单词似乎表示欢迎某人(总理梅拉尼娅)加入团队或只是参加白宫会议,并获得荣誉。
在特朗普的推特世界里,感激的反义词是什么?看一看。
这真的让我大笑——看看特朗普认为负面的东西吧!
如果让你选出唐纳德·特朗普最常用的两个单词,会是什么?
I actually had to zoom REALLY close to prevent words from overlapping (that’s how close they were!). This is a representation of how often fake news has been tweeted by Trump.
第二朵云更有趣。我们这里有三件主要的事情——希拉里、俄罗斯和政治迫害,所有这些都在相似的上下文中被提及。看起来,特朗普咆哮时,他也是以类似的方式做的,只是切换了实体。
让我们仔细看看。
这绝对是 Hillaryous(对不起)——和希拉里最接近、最相似的词是什么?当然是歪的。
在“hillary”的左边,朝着*“positive”*的那一边是什么? 正义 *。*在联邦调查局调查希拉里·克林顿的问题上,特朗普似乎一直在要求很多正义——注意“联邦调查局”。它位于“希拉里”云的中央。
但事情变得更有趣了。在“联邦调查局”和“希拉里”的右边,漂浮着“俄罗斯”和“勾结”的云。那是对俄罗斯干涉总统选举的调查!
但是为什么《猎巫》和它如此接近呢?现在,我不是美国人,我不在推特上关注特朗普,也没有花太多时间思考这个问题,但特朗普似乎认为联邦调查局对俄罗斯人的调查与其说是可信的调查,不如说是政治迫害。
谁在这中间?科米。哪个科米?联邦调查局局长科米。
这就是我喜欢这种文本分析方法的原因。一旦你仔细观察云里面的东西,你会发现惊人的关系。
Word2Vec 做出的单词之间关系的复杂程度其实高得不可思议。这不是一个人跟踪特朗普的每一个举动,阅读每一个与特朗普相关的标题——这是一个运行了 30 秒的算法。可能性是如此之大,我完全不知所措,但我会把它留给另一个帖子。
这还不是这一具体分析的全部——例如,有一些群集将诸如*【白色】和【房子】【前进】和【会议】(期待会议)【联合】和【国家】这样的词放在一起。与‘奥巴马医改’相关的一切都与共和党纠缠在一起。【墙】站在【边境】【犯罪】**【非法】*旁边。
我个人最喜欢的是*,,,,,【中国】,,但是下一个最接近的词实际上是,【贸易】,*!
但是不要相信我的话,你自己看看吧!(双击缩小)
特朗普的推文到此为止。
但是这个想法总体上怎么样呢?由于欧盟数据保护法的最新变化,你现在可以下载你在脸书发来的每一封邮件。
你可以在我的 GitHub 上使用我的 JupyterNotebook 来生成同样的图形,就像你的脸书一样。它包含了太多的信息——我可以看到“滑稽”(笑的 DD 类型中的字母 D 的数量)和诅咒语/猴子噪音逐渐消失,并转化为用于描述你情绪的单词,因为这些单词在 x 轴上移动。
在“笑话云”的另一边,你可以看到我变得富有哲理,并使用诸如*、、、【意识到】、*等词语。另一类包含黑色幽默——如果我把它们发布到网上,这些话题会让我丧命。
你还可以发现更多的东西——这绝对值得花时间去做!
我希望你喜欢阅读这篇文章,就像我喜欢创作它一样。
要知道,数据科学将数据转化为知识,我们都知道知识就是 力量 。
Word2Vec(跳格模型):第 1 部分——直觉。
这里的大部分内容来自克里斯的博客。我对它进行了压缩,并做了一些小的改动。
鸣谢:克里斯·麦考密克
http://mccormickml . com/2016/04/19/word 2 vec-tutorial-the-skip-gram-model/
http://mccormickml . com/2017/01/11/word 2 vec-tutorial-part-2-negative-sampling/
该算法有两种版本 CBOW 和 Skip-Gram 。给定一组句子(也称为语料库),该模型循环每个句子的单词,并试图使用当前单词来预测其邻居(其上下文),在这种情况下,该方法被称为“Skip-Gram”,或者它使用这些上下文中的每一个来预测当前单词,在这种情况下,该方法被称为“连续单词包”(CBOW)。每个上下文中的字数限制由一个名为“窗口大小的参数决定。
直觉
skip-gram 神经网络模型的最基本形式实际上非常简单。训练一个只有一个隐藏层的简单神经网络来执行某项任务,但是我们实际上不会将该神经网络用于我们训练它的任务!相反,目标实际上只是学习隐藏层的权重——我们将看到这些权重实际上是我们试图学习的“单词向量”。
我们将训练神经网络做以下事情。给定一个句子中间的特定单词(输入单词),查看附近的单词并随机选择一个。网络会告诉我们,我们词汇表中的每个单词成为我们选择的“邻近单词”的概率。
输出概率将与在我们的输入单词附近找到每个词汇单词的可能性有关。例如,如果你给训练好的网络输入单词“苏维埃”,输出概率对于像“联盟”和“俄罗斯”这样的单词比对于像“西瓜”和“袋鼠”这样不相关的单词要高得多。
我们将通过向神经网络输入在我们的训练文档中找到的单词对来训练它做到这一点。下面的例子展示了我们从句子“敏捷的棕色狐狸跳过懒惰的狗”中提取的一些训练样本(单词对)我在这个例子中使用了一个大小为 2 的小窗口。用蓝色突出显示的单词是输入单词。
我们将把像“蚂蚁”这样的输入单词表示为一个热向量。这个向量将有 10,000 个分量(我们词汇表中的每个单词一个分量),我们将在对应于单词“ants”的位置放置一个“1”,在所有其他位置放置 0。
网络的输出是一个单一的向量(也有 10,000 个分量),它包含我们词汇表中的每个单词,随机选择的邻近单词是该词汇表单词的概率。
这是我们神经网络的架构。
隐层神经元上没有激活函数,但输出神经元使用 softmax。
对于我们的例子,我们将说我们正在学习有 300 个特征的词向量。因此,隐藏层将由一个 10,000 行(词汇表中的每个单词一行)和 300 列(每个隐藏神经元一列)的权重矩阵来表示。
300 个特征是谷歌在谷歌新闻数据集上训练的发布模型中使用的(你可以从这里下载)。特性的数量是一个“超级参数”,您只需根据您的应用进行调整(也就是说,尝试不同的值,看看什么能产生最好的结果)。
如果你看看这个权重矩阵的行,这些实际上将是我们的单词向量!
因此,所有这些的最终目标实际上只是学习这个隐藏的层权重矩阵——当我们完成时,输出层将被丢弃!“蚂蚁”的1 x 300
单词向量然后被馈送到输出层。输出层是 softmax 回归分类器。
具体来说,每个输出神经元都有一个权重向量,它与来自隐藏层的单词向量相乘,然后将函数exp(x)
应用于结果。最后,为了使输出总和为 1,我们将这个结果除以来自所有10,000 个输出节点的结果总和。
下面是计算单词“car”的输出神经元的输出的图示。
如果两个不同的单词有非常相似的“上下文”(即它们周围有可能出现什么单词),那么我们的模型需要为这两个单词输出非常相似的结果。并且网络输出这两个单词的相似上下文预测的一种方式是如果单词向量相似。所以,如果两个单词有相似的上下文,那么我们的网络就有动力为这两个单词学习相似的单词向量!哒哒!
而两个词有相似的上下文是什么意思?我认为你可以预期像“智能”和“聪明”这样的同义词会有非常相似的上下文。或者相关的单词,如“引擎”和“传输”,可能也有相似的上下文。
这也可以为你处理词干——网络可能会为单词“ant”和“ants”学习相似的单词向量,因为它们应该有相似的上下文。
我们需要对基本的跳格模型进行一些额外的修改,这些修改对于实际上使训练可行是很重要的。在这么大的神经网络上运行梯度下降会很慢。更糟糕的是,你需要大量的训练数据来调整这么多权重,避免过度拟合。数百万的权重乘以数十亿的训练样本意味着训练这个模型将会是一头野兽。Word2Vec 的作者在他们的第二篇论文中解决了这些问题。
第二篇论文有三个创新点:
- 将常见的单词对或短语视为模型中的单个“单词”。
- 对常用词进行二次抽样以减少训练样本的数量。
- 使用他们称为“负采样”的技术修改优化目标,这导致每个训练样本只更新模型权重的一小部分。
值得注意的是,子采样频繁词和应用负采样不仅减少了训练过程的计算负担,还提高了结果词向量的质量。
子采样:
像“the”这样的常用词有两个“问题”:
- 在看词对的时候(《狐狸》、《the》)并没有告诉我们太多关于“狐狸”的意思。“the”出现在几乎每个单词的上下文中。
- 我们将有更多的样本(“the”,…)比我们需要学习一个好的“the”向量。
Word2Vec 实现了一个“子采样”方案来解决这个问题。对于我们在训练文本中遇到的每个单词,我们都有可能有效地将其从文本中删除。我们截词的概率和词的频率有关。
如果我们的窗口大小为 10,并且我们从文本中删除了“the”的一个特定实例:
- 当我们训练剩下的单词时,“the”将不会出现在它们的任何上下文窗口中。
- 我们将少 10 个训练样本,其中“the”是输入单词。
注意这两种效应是如何帮助解决上述两个问题的。
负采样:
正如我们上面讨论的,我们的单词词汇量的大小意味着我们的 skip-gram 神经网络有大量的权重,所有这些都将由我们数十亿训练样本中的每一个进行轻微更新!
负采样通过使每个训练样本仅修改一小部分权重而不是所有权重来解决这一问题。它是这样工作的。
当在单词对(“fox”、“quick”)上训练网络时,回想一下,网络的“标签”或“正确输出”是一个热向量。即对于“quick”对应的输出神经元输出 1,对于其他几千个输出神经元的所有输出 0。
对于负采样,我们将随机选择少量的“负”词(假设 5 个)来更新权重。(在这种情况下,“否定”单词是我们希望网络输出 0 的单词)。我们还将更新“正面”单词(在我们当前的例子中是单词“quick”)的权重。
这篇论文说,选择 5-20 个单词对于较小的数据集很有效,对于较大的数据集,你可以只选择 2-5 个单词。
回想一下,我们模型的输出层有一个 300 x 10,000 的权重矩阵。因此,我们将只更新正面词(“quick”)的权重,加上我们希望输出 0 的其他 5 个词的权重。总共有 6 个输出神经元和 1800 个权重值。这只是输出层中 3M 重量的 0.06%!
在隐藏层中,只更新输入单词的权重(无论是否使用负采样都是如此)。
使用“一元分布”选择“负样本”(即,我们将训练输出 0 的 5 个输出单词)。
本质上,选择一个词作为负样本的概率与其频率相关,更频繁的词更有可能被选择作为负样本。
鸣谢:克里斯·麦考密克
http://mccormickml . com/2016/04/19/word 2 vec-tutorial-the-skip-gram-model/
http://mccormickml . com/2017/01/11/word 2 vec-tutorial-part-2-negative-sampling/
Word2Vec(跳格模型):第 2 部分—在 TF 中的实现
Jupyter 笔记本:https://github . com/mchablani/deep-learning/blob/master/embeddings/Skip-Gram _ word 2 vec . ipynb
张量流内置了对 skip-gram word 2 ect 所需的大部分支架的支持,包括嵌入查找和负采样。
tf.nn.embedding_lookup
tf.nn.sampled_softmax_loss
预处理
将输入标记化,并将输入转换为 int 表示。从单词到 int 查找,反之亦然。
二次抽样
经常出现的单词,如“the”、“of”和“for ”,不会为附近的单词提供太多的上下文信息。如果我们丢弃其中一些,我们可以从数据中去除一些噪声,反过来得到更快的训练和更好的表示。这个过程被米科洛夫称为子采样。对于训练集中的每个单词 wi,我们将以如下概率将其丢弃
from collections import Counter
import randomthreshold = 1e-5
word_counts = Counter(int_words)
total_count = len(int_words)
freqs = {word: count/total_count for word, count in word_counts.items()}
p_drop = {word: 1 - np.sqrt(threshold/freqs[word]) for word in word_counts}
train_words = [word for word in int_words if random.random() < (1 - p_drop[word])]
构建图表
inputs = tf.placeholder(tf.int32, [None], name=’inputs’)
labels = tf.placeholder(tf.int32, [None, None], name=’labels’)
注意标签是二维的,如用于负采样的 tf.nn.sampled_softmax_loss 所要求的。
嵌入矩阵的大小为单词数乘以隐藏层中的单元数。因此,如果您有 10,000 个单词和 300 个隐藏单元,矩阵的大小将为 10,000×300。请记住,我们对输入使用了标记化的数据,通常是整数,其中标记的数量就是我们词汇表中的单词数量。
n_vocab = len(int_to_vocab)
n_embedding = 300
embedding = tf.Variable(tf.random_uniform((n_vocab, n_embedding), -1, 1))
embed = tf.nn.embedding_lookup(embedding, inputs)
负采样
我们将更新正确标签的权重,但只有少量不正确的标签。这就是所谓的【负抽样】。Tensorflow 有一个方便的函数可以做到这一点,[tf.nn.sampled_softmax_loss](https://www.tensorflow.org/api_docs/python/tf/nn/sampled_softmax_loss)
。
# Number of negative labels to sample
n_sampled = 100
softmax_w = tf.Variable(tf.truncated_normal((n_vocab, n_embedding))) softmax_b = tf.Variable(tf.zeros(n_vocab), name="softmax_bias")
# Calculate the loss using negative sampling
loss = tf.nn.sampled_softmax_loss(
weights=softmax_w,
biases=softmax_b,
labels=labels,
inputs=embed,
num_sampled=n_sampled,
num_classes=n_vocab)
cost = tf.reduce_mean(loss)
optimizer = tf.train.AdamOptimizer().minimize(cost)
培养
batches = get_batches(train_words, batch_size, window_size)
for x, y in batches:
feed = {inputs: x, labels: np.array(y)[:, None]}
train_loss, _ = sess.run([cost, optimizer], feed_dict=feed)
使用 T-SNE 可视化单词向量
%matplotlib inline
%config InlineBackend.figure_format = 'retina'import matplotlib.pyplot as plt
from sklearn.manifold import TSNEembed_mat = sess.run(embedding)viz_words = 500
tsne = TSNE()
embed_tsne = tsne.fit_transform(embed_mat[:viz_words, :])
fig, ax = plt.subplots(figsize=(14, 14))
for idx in range(viz_words):
plt.scatter(*embed_tsne[idx, :], color='steelblue')
plt.annotate(int_to_vocab[idx], (embed_tsne[idx, 0], embed_tsne[idx, 1]), alpha=0.7)
学分:来自课堂讲稿:https://classroom.udacity.com/nanodegrees/nd101/syllabus
40 行代码的 Wordcloud Web 应用程序
这些天来,r 的成长势头迅猛。鉴于其统计学根源,这种受欢迎程度可能看起来有些奇怪。然而,通过哈德利·韦翰和整个 R 工作室团队的惊人工作,这种情况正在改变。这种新发现的能力的一个例子是能够用少得可笑的代码编写清晰的 web 应用程序。在这篇文章中,我将演示如何使用 R!没有 Javascript,HTML 或 CSS 什么的。
Final project
启动和运行
Simple ‘Hello World’ with R + Shiny
通往 Hello World 的道路很简单。你需要安装 r。对于 Mac 用户来说,最简单的方法是自制。如果没有,你总是可以从曲柄处得到它。你只需在你选择的终端上输入 R 就可以得到一个 R 控制台。
接下来,您需要创建一个名为 app 的文件。r 用下面的代码。我们将要做的一切背后的主要驱动力是一个叫做闪亮的 R 包。这个神奇的包到底是什么?
Shiny 是一个开源的 R 包,它为使用 R 构建 web 应用程序提供了一个优雅而强大的 web 框架。Shiny 帮助您将您的分析转化为交互式 web 应用程序,而不需要 HTML、CSS 或 JavaScript 知识。
一旦你做到了。您可以通过调用 R 并键入以下命令来运行该应用程序:
library(shiny)
shiny::runApp()
很简单,对吧?好吧,这只是开始。
- 闪亮的应用程序会像电子表格一样自动“活”起来。当用户修改输入时,输出会立即改变,不需要重新加载浏览器。
- 闪亮的用户界面可以完全使用 R 构建,也可以直接用 HTML、CSS 和 JavaScript 编写,以获得更大的灵活性。
- 可在任何 R 环境下工作(控制台 R、用于 Windows 或 Mac 的 Rgui、ESS、StatET、RStudio 等。)
- 基于 Twitter Bootstrap 的有吸引力的默认 UI 主题。
- 一个高度可定制的滑块部件,内置动画支持。
- 预构建的输出部件,用于显示 R 对象的绘图、表格和打印输出。
- 使用 websockets 包在 web 浏览器和 R 之间进行快速双向通信。
- 使用反应式编程模型,消除混乱的事件处理代码,因此您可以专注于真正重要的代码。
至此,我们的项目已经启动。下一步是添加侧边栏,滑块和设置我们的主面板。
尽管有些语法是新的,但它相当简单。我们用 fluidPage 定义了我们的页面样式,它允许我们利用 Bootstrap 的网格系统。然后,我们建立我们的侧边栏。接下来,我们设置两个幻灯片输入。这将允许用户在我们的 wordcloud 中更改值,这将立即反映在我们的云中。这种对输入及其后续变化的关注是 Shiny 的核心。这一过程的方法论基础是反应性。
在很大程度上,反应超出了本文的范围,但是我将从 RStudio 的优秀人员那里提供一个快速的概述。
闪亮的 web 框架从根本上说是让从 web 页面连接输入值变得容易,让它们在 R 中对你可用,并且让你的 R 代码的结果作为输出值写回到 web 页面。
input values => R code => output values
由于闪亮的 web 应用程序是交互式的,输入值可以随时更改,输出值需要立即更新以反映这些更改。
Shiny 附带了一个反应式编程库,你可以用它来构建你的应用程序逻辑。通过使用这个库,更改输入值自然会导致 R 代码的正确部分被重新执行,这又会导致任何更改的输出被更新。
我们已经完成了这个应用程序的 UI 所需的所有代码。现在,我们将关注服务器端。如果你是 R 和 Tidyverse 的新手,下面的语法看起来完全陌生,但是请耐心听我说。这比看起来容易。
信不信由你,就是这样。如果你想在本地运行这个,你需要声明你正在使用什么库。你可以在这里 找到这个演练 的最终代码。
本演练绝非详尽无遗。Shiny 提供了很多东西,有一个看似无穷无尽的工具箱。如果你愿意,你可以编写自定义的 HTML 和 CSS。此外,像 ShinyJS 这样的包将会给更有经验的开发者一个机会,通过开发 Javascript 让他们的应用大放异彩。
希望这个简单的概述能揭示使用 R 和 Shiny 是多么的简单和有趣。这对于围绕模型或数据的内部工具来说是非常好的。绝对值得一个周末的黑客会议。你可以在 RStudio 上看到一系列例子来获得一些灵感。
如果你正在寻找一个更深入的教程,由迪安·阿塔利撰写的这个是一个很好的起点!
工作+研究生院:数据科学家的生存指南(第一部分)
“multicolored rock lot” by Oliver Paaske on Unsplash
前进
所以,你决定要做了。
你将继续全职工作,同时攻读某种研究生学位。看起来很简单——你在工作的时候到处看视频讲座,读一些专题书籍,甚至可能完成整个 Coursera 课程。为什么不更上一层楼,在学习的同时获得一个完整的学位呢?此外,随着最近(著名的)在线教育机会的激增,你甚至不需要在你就读的学校附近的任何地方获得学位。现在,做一份全职工作,读一所高质量的研究生院是一个合法的选择,而就在 10 年前,这个选择还根本不存在。
这些是我 23 岁时的想法。我在辛辛那提做数据分析师,意识到如果我想长期从事这一职业,我需要一个定量硕士学位。这听起来很简单,但问题是这个学位对我来说并不像医学或法律学位那样有用。换句话说,我不在一张纸就能让我做一份与我已经在做的工作完全不同的工作的情况下;可以肯定的是,分析领域重视研究生教育,但它是结合经验来评价的,而不是作为一个独立的实体。因此,如果我最终想管理,或者进入数据科学领域,获得研究生学位是我必须要跨过的一条河。
除此之外,没有真正的“最佳”数据科学学位。计算机科学、统计学和运筹学是显而易见的,但没有一个学科能描绘出全貌。同样,对数据结构的深入了解不会帮助您指定回归模型,知道给定的估计量是无偏的也不会帮助您计算出 400GB 表的有效 I/O。要在数据科学领域取得成功,您需要同时在不同程度上培养所有这些领域的技能。你还需要学习他们如何互动,并在现实世界的商业环境中找到应用——在真空中了解事情并不能证明你的薪水是合理的。经过一番思考,我得出的结论是,对我来说,最佳途径就是边工作边上学,我喜欢把这看作是一种现代学徒计划。
2014 年末,我决定努力争取,并申请了德克萨斯 A & M 的统计硕士项目,该项目不仅广受好评,还提供 100%在线完成的选项。我将能够继续我设计和评估现实世界广告活动的工作,同时获得我认为我需要的学位。很简单,对吧?不对。虽然它给我带来了很多好处,但获得这个学位无疑是我所从事的最具挑战性的努力。四年(!)后来,然而,我在我的最后一个学期,并认为自己是一个工作+学校的老将。回想那次旅程,我意识到有很多事情我希望在开始之前就知道,如果没有其他原因,我会对自己将陷入什么样的境地有更好的了解。这本指南是我希望 4 年前就能看到的简明手册——如果你正在考虑边工作边攻读研究生学位,或者已经在这样做了,这是给你的,希望你会觉得有用。
电平设置
本指南是从行业数据科学家的角度撰写的,但也适用于各种职业。这些年来,我学到了一些东西,我将经历同时工作和学校生活方式的一些现实,以及一些最佳实践。然而,在你开始这段旅程之前,你需要对自己诚实,并确定你是否愿意/能够采取必要的步骤来取得成功。这条路并不适合所有人——句号。如果你能完成它,回报是可观的,但是你将不得不放弃很多来达到目的。下一节将会更详细,但这只是一些很难兼顾工作和学校的事情的例子:
追求几个耗费时间的爱好
照顾特别需要的宠物
保持丰富活跃的社交生活(又名:每周去一次酒吧)
花 90%的空闲时间和你的另一半在一起
拥有一栋房子
抚养孩子
我并不是说这些都是不可能实现的,但是平衡正规教育和你目前的所有责任将会迫使你优先考虑。
现实和最佳实践
在这一节中,我将讲述我所经历的一些最引人注目的现实,以及我发现的解决这些现实的最佳实践。
现实一
你的朋友、家人和同事不会理解你正在经历的事情
我还没有为人父母,但是在我的生活中,我在新父母中注意到的一件事是,在他们有了孩子之后,个人关注点发生了相当大的变化(不是开玩笑)。他们以前的爱好和兴趣被放在一边,他们将大部分时间用于承担和管理新的责任。他们也倾向于花更多的时间和其他父母在一起,主要是因为其他现有的父母是周围唯一真正知道他们的生活方式是什么样的人。他们会告诉我意想不到的医生来访,他们睡了两个小时,或者在一个孩子生病后不得不清洗他们的汽车,虽然我可以试图理解这一切是什么样的,但如果不亲身经历,我不可能真正理解。
在较小的程度上,作为一个打工学生,完全相同的情况会降临到你身上。你的朋友不会理解你为什么没有时间去那个快乐时光。你的亲戚不会理解你为什么来的少了。你的另一半不会理解你为什么不能更快地完成作业。除非这些人经历过和你类似的事情,否则准备好进行“期望管理”,让很多人失望。
最佳实践
在可能的范围内,找到一个社区
在过去的几年里,在从事某种教育的同时找到一个社区几乎从来不是问题,因为你通常会亲自去上课。然而,现在我们有了在线教育,并不能保证你将有机会有机地认识和你处境相同的同龄人。这个社区很重要——当事情在期中考试前变得紧张时,知道你不是唯一一个可能在这种情况下挣扎的人,真的很让人放心。这可能是我能建议的最重要的事情——如果你觉得你在单干,你更有可能放弃你的计划。
你需要积极主动地建立联系——大多数班级都有讨论板,你可以在那里张贴问题或帮助其他学生解决自己的问题。我发现我自己对课堂的喜爱与我参与讨论板的程度直接相关;人们非常感谢其他人花时间解决他们的问题,或者至少尝试解决问题。大多数在线课程还会有一个全球讨论论坛——值得贴一张便条,看看是否有其他人住在你所在的区域,是否会对一学期一次的聚会开放。此外,不要犹豫寻找你项目之外的人——工作的学生并不新鲜,你可能有同事或邻居也在攻读学位。
现实二:
你的工作绩效会变得更高
人们追求同时接受教育和就业的原因之一是他们希望他们的学习能让他们在工作中做得更好。这是我发现绝对是这样的事情,但不是每天都这样。在你完成一项特别困难的任务后的第二天,你可能不会有 100%的动力去完成它。类似地,在期中考试的前一天,你可能不会完全“到场”参加任何会议。还有你的工作时间之外的问题——如果你习惯于每周花几个小时关注与你的工作直接相关的技术话题,那将不得不退居二线,除非它也与你的课程直接相关。
然而,也有一些时候,你在学校所做的与你在工作中所做的完全一致,在这些时候,你将提供巨大的价值。比如,我曾经发现自己在学习正规实验设计的同时,还在设置直复广告。我很有信心,我为那个项目想出的测试设计和测量计划比我以前制作的要好得多,并且立即被我的研究所启用。
最佳实践:
不断验证你在做什么
假设你正在学习的材料与你的工作至少有一些关系,那么验证你在学校所做努力的最好方法就是找到机会直接应用它。对我来说,这意味着通过新的视角回顾我以前做过的项目——也许我以前做过的卡方检验作为逻辑回归会更好。这也意味着鼓励自己根据新发现的知识来看待问题——当你每周花 15-20 个小时研究时间序列数据的分析时,你会惊奇地发现在你的工作中自然会有多少时间序列问题。
其他最佳实践和收尾思路将在 第二部分 中讨论。
处理您的仪表板布局?
Photo by Dawid Małecki on Unsplash
以下是让你开始的五个建议
也许创建仪表板的最大障碍是布局。它必须是有用信息和吸引力的正确结合。大多数仪表板都显示在网页上。因此,在创建仪表板时使用网页设计原则是有意义的。
提示 1:你的大脑将物体理解为群体
很多设计师在讨论布局时都会参考格式塔原则。20 世纪 20 年代,德国心理学家描述了人类如何组织视觉信息。这些发现被称为格式塔原理。
这些原则讨论了大脑如何试图理解一组对象——例如页面上的图表。注意下图;你的眼睛受过训练。即使你看到了物体,你的大脑会添加一些额外的信息,你也会看到另一个形状。
当您违反这些原则时,您的用户会感到困惑,不想与您的仪表板交互。设计布局时,考虑用户将如何看到数据对象一起工作。
或许大小和接近度相似的条形图会被视为一个对象,或者被认为是关于同一主题的。
提示 2: F 模式布局支持您的扫描用户
当你看一个网页时,你的眼睛倾向于以一种特定的模式来浏览它。你浏览页面,向下浏览页面,然后在某个时候再次浏览页面。这是一个 F 或 e 的模型。这是一个有趣的科学发现,但这和你的仪表板有什么关系呢?
您可以利用这种模式来提高仪表板的可用性。设计用户期望找到东西的布局。在下面的排列中,控件被放置在页面的顶部,在页面的中央,有更多的控件。是 E 型还是 F 型,对吧?
注意,除了告诉你模式之外,我还使用了单词扫描。当用户第一次访问您的仪表板时,他们很可能不会先阅读所有文本。他们将浏览以了解哪些内容可以搭配在一起,并学习使用仪表板的最快方式。
技巧 3:考虑工具内的交互性
如果数据可视化工具是交互式的(如 SAS Visual Analytics ),或者您打算添加编程来帮助实现交互性,那么请确定如何使用它。用户将如何识别路径或了解更多可用信息。在某些情况下,这是显而易见。页面上可能有下拉列表、按钮或滑块等控件。用户理解这些对象控制其他对象。请仔细考虑这些项目在页面上的位置。
在以下示例中,趋势图表控制其下方的图表。对于趋势图上的每一点,用户都可以点击查看当月的销售额。用户还可以按地区或产品区域进行探索。
想象一下,如果设计中用条形图来控制一切,将会很难使用。很可能如果有人点击了这个栏,它周围的一切都变了,这就没有意义了。
提示 4:我们用传统的方法设计版面——铅笔和纸
你可能有很多布局思路。开始在纸上勾画你的想法。强迫自己想出三种或三种以上的布局。最后,你可能最喜欢你的第一个设计,但是你会从每次迭代中学习。
你很想跳过这一步,但是不要这样做。
这一步迫使你思考测量方法和你想要传达的内容。
这是整理 KPI 和其他指标的时候了。您希望将数据放入逻辑分组和支持这些分组的度量中。
这是应用你的格式塔原则的机会!这也是思考每个指标试图表达什么的时候了。趋势图效果更好还是树形图对用户帮助更大?在纸上尝试一下。
技巧 5:线框帮助你从用户的角度看问题
画完草图后,你可以使用像 MS Visio 这样的工具来绘制线框。线框有助于你的客户(或老板)理解你计划如何展示所有的信息。使用箭头来显示你希望用户如何在各部分之间移动,以及交互的位置。在这个阶段,更容易解决无效的设计,并从最终用户那里获得反馈。
这是一个确定了信息路径的仪表板布局示例。请注意,我的主仪表板会引导用户了解更多信息。对于 KPI 1,重点是产品。高级经理可能只对第 1 页感兴趣,但直线经理可能需要更多信息来了解是什么导致了这种趋势。
该布局帮助用户理解仪表板的显著之处。它通过使用适当的设计技术和深思熟虑的途径来支持数据。
你的外卖
一个功能完善的设计好的仪表盘不是偶然!这是精心规划和遵守适当的网页设计技术的结果。
工作远程备忘单
最近有人问我,您如何确保在远程工作时保持高效工作?这个小抄是我想出来的。
Image Credit: “Author’s Photo” — More on attributions.
远程工作是一件喜忧参半的事情。我不是来讨论它的利弊的。我在这里分发一份有用的小抄。
随着时间的推移,我远程工作的使用案例发生了变化和发展。简而言之,我曾以兼职教授、研究员、数据科学家和独立顾问的身份远程工作。在这篇文章的最后,我进一步阐述了我的用例。
关于语义学的一个注释。
有时远程工作被称为“在家工作”或行话“wfh”在我看来,wfh 是一个误称。远程工作、远程工作或外出工作是我的首选。外出工作是我的最爱。外出工作是最简单也是最具包容性的说法。不是每个远程工作的人都在家工作。
这种区别很重要。我观察到一个大型组织的一个分支机构实施了一个“在家工作”的策略。其他分支机构抱怨说“在家工作”的政策并不是人人都能平等享受的。与此同时,同一组织中的另一个分支机构实施了“离开工作”策略。这两项政策实质上是一样的。在高层管理人员的压力下,他们觉得“在家工作”政策并不顺利,“外出工作”政策保留了下来,而“在家工作”政策结束了。
关于职业精神的一个注解。
从许多角度来看,在办公室环境中,在外工作对员工的要求比在同一家公司工作的同一名员工可能需要的更多。我发现外出工作需要更多的专业精神,更多的交流,更多的奉献,更多的动力,更多的技能,更多的更多。
警告。
外出工作并不能保证提高生产率或员工满意度。生产力和员工满意度最深层的核心驱动力不是工作场所。工作场所很重要,但其他因素更重要。生产率和员工满意度最深层的核心驱动因素是专业精神、沟通、奉献、激励或技能。
也就是说,如果没有相应的专业精神、沟通、奉献、动力和技能,从办公室环境转换到远程环境不会提高生产力或工作满意度。
如果你确实在外地工作,以下策略让我能够利用我的专业精神、沟通、奉献、动力和技能。
设定目标。
我经常设定高而远大的目标。高目标让我保持动力。我写下我的目标。我与家人、朋友、主管和其他同事分享我的目标。我定期回顾目标。如果你需要帮助来写你的目标(专业建议:在网上搜索“智能目标”)。
当我足够幸运地赢得了他人的信任,让他们与我分享他们的目标时,我会查看他们做得如何。当别人为我做同样的事情时,我会很感激。
提前计划一周。
在每周的开始。对我来说,一周的开始是星期天。我花时间(有时一个小时或更多)来计划我的一周。计划我的一周包括列清单,回顾我的日历,调整日历,决定我可以把什么东西搬到车上,这样当我需要它的时候它就在那里。我也打包我的运动包,计划我的饮食。
这一评估确保我在两次承诺之间有足够的旅行时间。这个过程有助于我确保自己不会过度投入——我有时间工作。
提前计划有助于我更有策略。例如,我可能会决定周二上午在市中心的共享办公空间工作是有意义的,因为我和邻居有两个会议。
另一个例子可能是,我在星期四有一个会议,就在城市的另一端。在周日看到这一点有助于我决定是否可以将会议转移到一个更方便的地点。或者我能不能把会议推迟一天。
周日每一分钟的计划时间,我都认为我在一周中节省了 5-10 分钟。
共享您的日历。
与您信任的人以及依赖您的人共享您的日历。因为你没有与同事共享的工作空间,他们无法亲自看到你进出办公室。共享您的日历可以建立信任。
共享您的日历也有助于那些依赖您的人在需要时找到您。我让那些依赖或依赖我的人直接编辑我的日历。节省我们双方的时间,不必协调会议时间。
把你的日历当成日记。
在一天结束的时候,或者一周结束的时候,我会调整我的日历,这样它就能准确地反映出我做了什么。如果一个会议被取消或推迟,我会用显示“取消”或“推迟”的注释编辑它的标题这样我就有了我应该如何度过时间的记录。在它旁边,我将添加一个事件,描述我实际上是如何度过时间的。
在你的日历上记日记再次建立信任并促进透明度。当你需要记录你的工作时,《华尔街日报》会帮你的。
保存实验书籍。
我是科学家。实验室书籍是科学家最好的朋友(对许多科学家来说,实验室书籍是可怕的伙伴)。我把实验书变成了我的朋友。实验书实际上就是你用来记笔记的笔记本。
我用纸质实验书。最近,我用速记本。斯特诺的书很小,很容易写。我为每个重大项目都做了速记本。我在每一页的顶部都注明了日期,这样我就可以回头看笔记,并很容易地与我的日志日历相互参照。
做实验记录有助于你记住你做了什么,怎么做的,为什么做。每当我缺少灵感或动力的时候,我都会回头看看我的实验书。毫无疑问,回顾我的实验书是刷新和更新我的任务清单的最好方法之一。
如果我对下一步缺少想法,实验书会拯救我。
灵感来临时抓住它。
如果是凌晨 3 点,工作的灵感来了,我会起床,走到电脑前,或笔记本前,把想法写下来。我在半夜一次写了好几页。我写了几百行代码。相反,我在半夜重构了数百行代码。
灵感是珍贵的,抓住它。同样,如果我下午 1 点下班回来,灵感不在,我会去散步,重温我的笔记本,或者读一本与我当前项目相关的书。换句话说,我不强求。
打造专属工作空间。
这个建议在关于外出工作的文章中很常见。对我来说,我的建议与许多人认为的外出工作的最大好处(你可以在你喜欢的地方工作)背道而驰。我放弃了在我喜欢的任何地方工作的选择,而选择了一个我可以完成大部分工作的专用工作空间。
对我来说,我的专用工作区必须具备的决定性特征(工具)是一个大白板。如果我可以的话,每一面墙都将是一块巨大的白板。
白板是记笔记、画图表、发展想法、列清单等的地方。这对我很有效,因为我是一个视觉学习者。把我的想法写在白板上让我可以看到这些想法。当我能在一个无界、无限制的空间里看到想法时,我能更清晰地思考。
因此,留出一个专用的工作空间(有一两个你最常用的权威工具)是有益的策略,可以改善你的工作体验。对一些人来说,专用工作空间可以是一个背包。
花时间在新的地方工作。
我建议花时间在新的地方工作。对我来说,我知道我需要一个专用的工作空间。然而,我也受益于探索和寻找新的工作场所。有时那会是一家咖啡店。其他时候,这将是一个共同的工作空间。一些联合工作区是免费使用的(某些条件适用)。
保持专用工作区的整洁。
经常清洁专用工作区。确保文件存档(或扫描并保存在云中)。保持该工作区的表面可见。如果有成堆的纸张、书籍或其他物品,把它们收起来。我发现当工作场所整洁有序时,开始工作会更容易。
把自己的手机分享给大家。
正如我让我的日历对我信任的人和依赖我的人开放一样,我几乎和所有人分享我的手机。当我教书的时候,我把它放在我的教学大纲上。几乎没有人再给我打电话了。但是,拥有我的手机号码可以帮助其他人感受到联系。
通过视频向他人展示自己。
随着电话使用的减少,视频聊天服务的可用性和使用激发了远程通信的复兴。我使用平板电脑、旧手机或备用笔记本电脑来保持一条开放的视频线路,这样可信任的同事可以随时拨打。就好像他们可以在我的办公桌前停下来一样。
自动回复器的广泛使用。
我在电子邮件中大量使用自动回复功能。这有助于其他人知道我在哪里,我在做什么。例如,可能一天就要结束了,现在是晚上 7 点左右。我会在邮件里放一封自动回复邮件,解释:
“嗨,谢谢你的邮件。今天晚上 7 点我离开了我的工作场所。我不在的时候会留意邮件的。如果你现在需要我,请打我的手机(608–555–5555)。否则,我会在明天早上 6 点回到办公室后尽快回复。”
休息一下。
为了避免一直工作…总会有工作的。当你的专用工作空间离你只有几步之遥时,你很容易告诉自己“我会再发一封邮件。”或者,“我会让自己在这个清单上再做两件事。”
为了确保休息,我离开家去吃午饭。午餐时使用健身房。下午三点左右绕着街区散散步。
关于我的用例的更多信息。
我一直在努力扮演多种角色。这意味着我有多个用例。
教学是我最常使用的案例之一。对于多个 semseters,我教过大学生。有时候这些课程是基于教室的,其他的是在线的。教书的时候,我在外面工作,而不是在学校提供给我的办公室里工作。虽然我的专用工作空间在家里,但我逃离家的地方通常是图书馆。
我还在一个涉及进行研究和拓展的岗位上工作。我大约一半的工作是处理数据。我工作的另一半是计划和发表演讲或进行培训。对于这个双重/分离用例,我的雇主提供了一间办公室,但是我主要在办公室之外工作(在图书馆、家里、咖啡店、会议酒店等。).
在研究生院,我创建并经营了一家精品咨询公司(现已关闭)。在这些用例中,我使用了上述大部分策略。
这些策略对我很有用,我希望其他人也会觉得有用。
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
adamrossnelson.medium.com](https://adamrossnelson.medium.com/membership)
感谢阅读
把你的想法和主意发给我。你可以写信只是为了说声嗨。如果你真的需要告诉我是怎么错的,我期待着尽快和你聊天。推特:@ adamrossnelsonLinkedIn:亚当·罗斯·尼尔森在推特和脸书:亚当·罗斯·尼尔森在脸书。
为清晰起见,2020 年 11 月进行了适度的编辑更新。
Apache Spark、Python 和 PySpark 入门
Image Source: www.spark.apache.org
本文是 Apache Spark 单节点安装的快速指南,以及如何使用 Spark python 库 PySpark。
1.环境
- Hadoop 版本:3.1.0
- 阿帕奇卡夫卡版本:1.1.1
- 操作系统:Ubuntu 16.04
- Java 版本:Java 8
2.先决条件
Apache Spark 需要 Java。要确保安装了 Java,首先更新操作系统,然后尝试安装它:
sudo apt-get updatesudo apt-get –y upgradesudo add-apt-repository -y ppa:webupd8team/javasudo apt-get install oracle-java8-installer
3.安装 Apache Spark
3.1.下载并安装 Spark
首先,我们需要为 apache Spark 创建一个目录。
sudo mkdir /opt/spark
然后,我们需要下载 apache spark 二进制包。
**wget “**http://www-eu.apache.org/dist/spark/spark-2.3.1/spark-2.3.1-bin-hadoop2.7.tgz**”**
接下来,我们需要将 apache spark 文件解压缩到/opt/spark 目录中
sudo tar -xzvf spark-2.3.1-bin-hadoop2.7.tgz --directory=/opt/spark -- strip 1
3.2.配置 Apache Spark
当 Spark 启动作业时,它会将其 jar 文件传输到 HDFS,这样任何正在工作的机器都可以使用这些文件。这些文件对于较小的作业来说是一笔很大的开销,所以我把它们打包,复制到 HDFS,并告诉 Spark 它不再需要复制它们了。
jar cv0f ~/spark-libs.jar -C /opt/spark/jars/ .hdfs dfs -mkdir /spark-libshdfs dfs -put ~/spark-libs.jar /spark-libs/
复制文件后,我们必须告诉 spark 忽略从 Spark 默认配置文件中复制 jar 文件:
sudo gedit /opt/spark/conf/spark-defaults.conf
添加以下几行:
spark.master spark://localhost:7077spark.yarn.preserve.staging.files truespark.yarn.archive hdfs:///spark-libs/spark-libs.jar
在本文中,我们将配置 Apache Spark 在单个节点上运行,因此它将只是 localhost:
sudo gedit /opt/spark/conf/slaves
确保它只包含值 localhost
在运行服务之前,我们必须打开。使用 gedit 的 bashrc 文件
sudo gedit ~/.bashrc
并添加以下几行
export SPARK_HOME=/opt/sparkexport SPARK_CONF_DIR=/opt/spark/confexport SPARK_MASTER_HOST=localhost
现在,我们必须运行 Apache Spark 服务:
sudo /opt/spark/sbin/start-master.shsudo /opt/spark/sbin/start-slaves.sh
4.安装 Python
4.1.获取最新的 Python 版本
Ubuntu 16.04 预装了 Python 3 和 Python 2。为了确保我们的版本是最新的,我们必须用 apt-get 更新和升级系统(在先决条件一节中提到):
sudo apt-get updatesudo apt-get -y upgrade
我们可以通过键入以下命令来检查系统中安装的 Python 3 的版本:
python3 –V
它必须返回 python 版本(例如:Python 3.5.2)
4.2.安装 Python 工具
要管理 Python 的软件包,我们必须安装 pip 实用程序:
sudo apt-get install -y python3-pip
还需要安装一些软件包和开发工具,以确保我们的编程环境有一个健壮的设置。
sudo apt-get install build-essential libssl-dev libffi-dev python-dev
4.3.营造环境
我们需要首先安装 venv 模块,它允许我们创建虚拟环境:
sudo apt-get install -y python3-venv
接下来,我们必须为我们的环境创建一个目录
mkdir testenv
现在,我们必须转到这个目录并创建环境(所有环境文件都将创建在一个名为 my_env 的目录中):
cd testenvpython3 -m venv my_env
我们完成了检查使用 ls my_env 创建的环境文件
要使用此环境,您需要激活它:
source my_env/bin/activate
5.使用 PySpark
5.1.配置
首先我们需要打开。bashrc 文件
sudo gedit ~/.bashrc
并添加以下几行:
export PYTHONPATH=/usr/lib/python3.5export PYSPARK_SUBMIT_ARGS=” -- master local[*] pyspark-shell”export PYSPARK_PYTHON=/usr/bin/python3.5
5.2.FindSpark 库
如果我们在机器上安装了 Apache Spark,我们就不需要在开发环境中安装 pyspark 库。我们需要安装 findspark 库,它负责定位随 apache Spark 一起安装的 pyspark 库。
pip3 install findspark
在每个 python 脚本文件中,我们必须添加以下行:
import findsparkfindspark.init()
5.3.PySpark 示例
5.3.1.阅读 HDFS 的作品
下面的脚本将读取存储在 hdfs 中的文件
import findsparkfindspark.init()from pyspark.sql import SparkSessionsparkSession = SparkSession.builder.appName(“example-pyspark-hdfs”).getOrCreate()df_load = sparkSession.read.csv(‘hdfs://localhost:9000/myfiles/myfilename’)df_load.show()
5.3.2.阅读阿帕奇·卡夫卡《消费者》
我们首先必须将 spark-streaming-Kafka-0–8-assembly _ 2.11–2 . 3 . 1 . jar 库添加到我们的 Apache spark jars 目录/opt/spark/jars 中。我们可以从 mvn 存储库下载:
以下代码从 Kafka 主题消费者那里读取消息,并逐行打印出来:
import findsparkfindspark.init()from kafka import KafkaConsumerfrom pyspark import SparkContextfrom pyspark.streaming import StreamingContextfrom pyspark.streaming.kafka import KafkaUtilsKAFKA_TOPIC = ‘KafkaTopicName’KAFKA_BROKERS = ‘localhost:9092’ZOOKEEPER = ‘localhost:2181’sc = SparkContext(‘local[*]’,’test’)ssc = StreamingContext(sc, 60)kafkaStream = KafkaUtils.createStream(ssc, ZOOKEEPER, ‘spark-streaming’, {KAFKA_TOPIC:1})lines = kafkaStream.map(lambda x: x[1])lines.pprint()ssc.start()ssc.awaitTermination()
6.文献学
[1] M. Litwintschik,“Hadoop 3 单节点安装指南”,2018 年 3 月 19 日。【在线】。可用:http://tech . marksblogg . com/Hadoop-3-single-node-install-guide . html【2018 年 6 月 1 日访问】。
[2] L. Tagiaferri,“如何在 Ubuntu 16.04 上安装 Python 3 并设置本地编程环境”,2017 年 12 月 20 日。【在线】。可用:https://www . digital ocean . com/community/tutorials/how-to-install-python-3-and-set-up-a-local-programming-environment-on-Ubuntu-16-04。【2018 年 08 月 01 日接入】。
[3]《Apache Spark 官方文档》,[在线]。可用:https://spark.apache.org/docs/latest/.【2018 年 8 月 5 日访问】。
[4]《堆栈溢出问答》[在线]。可用:https://stackoverflow.com/.【2018 年 6 月 1 日获取】。
[5] A. GUPTA,“PySpark 中数据帧操作的完整指南”,2016 年 10 月 23 日。【在线】。可用:https://www . analyticsvidhya . com/blog/2016/10/spark-data frame-and-operations/。【2018 年 8 月 14 日进入】。
提高不平衡数据集下机器学习模型性能的三项重要技术
这个项目是我最近“机器学习工程师”职位面试技能测试的一部分。我必须在 48 小时内完成这个项目,包括用 latex 写一份 10 页的报告。数据集有三个类,并且高度不平衡。这个项目的主要目标是处理数据不平衡的问题。在下面的小节中,我描述了我用来克服数据不平衡问题的三种技术。
首先,让我们开始熟悉数据集:
**数据集:**训练数据中有三个标签【1,2,3】,使得问题成为多类问题。训练数据集有 17 个特征和 38829 个体数据点。而在测试数据中,有 16 个特征没有标签,有 16641 个数据点。训练数据集非常不平衡。大部分数据属于 1 类(95%),而 2 类和 3 类只有 3.0%和 0.87%的数据。由于数据集没有任何空值,并且已经缩放,所以我没有做任何进一步的处理。由于一些内部原因,我不会分享数据集,但详细的结果和技术。下图显示数据不平衡。
Figure 1: The graph shows the data imbalance in the training dataset. The majority of the data belongs to class-1 (95%), whereas class-2 and class-3 have 3.0% and 0.87% data.
**算法:**经过初步观察,我决定使用随机森林(RF)算法,因为它优于其他算法,如支持向量机、Xgboost、LightGBM 等。RF 是一种 bagging 类型的集成分类器,它使用许多这样的单个树来进行预测。在这个项目中选择 RF 有几个原因:
- RF 对于过拟合是健壮的(因此解决了单一决策树的最显著的缺点之一)。
- 参数化仍然非常直观和简单。
- 随机森林算法在高度不平衡的数据集中有很多成功的使用案例,就像我们在这个项目中所做的那样。
- 我有以前的算法实现经验。
为了找到最佳参数,我使用 scikit-sklearn 实现的 GridSearchCV 对指定的参数值进行了网格搜索。更多细节可以在 Github 上找到。
为了处理数据不平衡问题,我使用了以下三种技术:
A .使用集成交叉验证(CV): 在这个项目中,我使用交叉验证来证明模型的稳健性。整个数据集被分成五个子集。在每个 CV 中,5 个子集中的 4 个用于训练,剩余的集用于验证模型。在每个 CV 中,模型还预测(概率,而不是类别)测试数据。在交叉验证的最后,我们有五个测试预测概率。最后,我对所有类别的预测概率进行平均。该模型的训练表现稳定,在每份简历上的回忆和 f1 分数几乎保持不变。这项技术帮助我在一次 Kaggle 比赛中很好地预测了测试数据,在那次比赛中,我在 5355 名选手中名列前 25 名,也就是前 1%。以下部分代码片段显示了集成交叉验证的实现:
for j, (train_idx, valid_idx) in enumerate(folds):
X_train = X[train_idx]
Y_train = y[train_idx]
X_valid = X[valid_idx]
Y_valid = y[valid_idx]
clf.fit(X_train, Y_train)
valid_pred = clf.predict(X_valid)
recall = recall_score(Y_valid, valid_pred, average='macro')
f1 = f1_score(Y_valid, valid_pred, average='macro')
recall_scores[i][j] = recall
f1_scores[i][j] = f1
train_pred[valid_idx, i] = valid_pred
test_pred[:, test_col] = clf.predict(T)
test_col += 1
## Probabilities
valid_proba = clf.predict_proba(X_valid)
train_proba[valid_idx, :] = valid_proba
test_proba += clf.predict_proba(T)
test_proba /= self.n_splits
**B .设置类权重/重要性:**成本敏感学习是使随机森林更适合从非常不平衡的数据中学习的许多其他方法之一。RF 倾向于偏向多数阶级。因此,对少数类错误分类施加成本惩罚可能是有用的。因为这种技术被证明可以提高模型性能,所以我给少数类分配了较高的权重(即较高的误分类成本)。然后将类别权重合并到 RF 算法中。我根据 class-1 中数据集的数量与数据集中类的数量之间的比率来确定类权重。例如,类-1 和类-3 中数据集的数量之比约为 110,类-1 和类-2 的数量之比约为 26。后来,我在反复试验的基础上稍微修改了这个数字,以提高模型的性能。下面的代码片段显示了不同类权重的实现。
from sklearn.ensemble import RandomForestClassifier
class_weight = dict({1:1.9, 2:35, 3:180})rdf = RandomForestClassifier(bootstrap=True, class_weight=class_weight,
criterion='gini',
max_depth=8, max_features='auto', max_leaf_nodes=None,
min_impurity_decrease=0.0, min_impurity_split=None,
min_samples_leaf=4, min_samples_split=10,
min_weight_fraction_leaf=0.0, n_estimators=300,
oob_score=False,
random_state=random_state,
verbose=0, warm_start=False)
**C .过度预测一个标签比预测不足:**这个技巧是可选的。自从我被要求实现这个技术以来,我就一直在应用它。在我看来,这种方法对提高少数民族学生的成绩很有影响。简而言之,如果模型误分类为类 3,则该技术对模型的惩罚最大,对类 2 的惩罚稍小,对类 1 的惩罚最小。
为了实现这个方法,我改变了每个类的概率阈值。为此,我以递增的顺序为类别 3、类别 2 和类别 1 设置概率(即,类别 3 = 0.25、类别 2 = 0.35、类别 1 = 0.50),以便该模型被强制过度预测类别。这个算法的详细实现可以在这个项目 Github 页面找到。
最终结果:
以下结果显示了上述三种技术如何帮助提高模型性能。
- 集成交叉验证的结果:
2。集成交叉验证+类别权重的结果:
3。集成交叉验证+类别权重+过度预测标签的结果:
结论
最初,过度预测对我来说似乎很棘手。然而,研究这种方法有助于我找到解决这个问题的方法。由于时间限制,我无法专注于模型的微调和功能工程。该模型还有许多进一步改进的空间。比如删除不必要的特性,通过工程增加一些额外的特性。我也试过 LightGBM 和 XgBoost。但是在这么短的时间内,我发现随机森林比其他算法更好。我们可以尝试一些其他的算法,包括神经网络,来改进这个模型。最后,我想说,从这次数据挑战中,我学会了如何以一种组织良好的方式处理不平衡的数据。
非常感谢您的阅读。完整代码可以在 Github 上找到。如果你有任何问题或者这篇文章需要修改,请告诉我。
想在附近找到对机器学习感兴趣的人吗?
我将通过分享关于 xoolooloo 的有趣信息来结束这篇文章。它是一个基于位置的搜索引擎,利用相似和多重兴趣寻找当地人。例如,如果你读了这篇文章,你肯定对数据科学、图论、机器学习感兴趣。因此,你可以在你的地区找到有这些兴趣的人;去看看 www.xoolooloo.com 的
让我们讨论一下
如果你有任何问题,请随意提问。看到错别字、错误,或者有什么建议,请评论。你可以联系我:
Email: sabbers@gmail.com
LinkedIn: [https://www.linkedin.com/in/sabber-ahamed/](https://www.linkedin.com/in/sabber-ahamed/)
Github: [https://github.com/msahamed](https://github.com/msahamed)
Medium: [https://medium.com/@sabber/](https://medium.com/@sabber/)
在机器学习中处理缺失数据
缺失值代表了真实世界数据的混乱。发生这种情况的原因可能有很多,从数据输入过程中的人为错误、不正确的传感器读数,到数据处理流程中的软件错误。
正常的反应是沮丧。丢失数据可能是代码中最常见的错误来源,也是大多数异常处理的原因。如果你试图删除它们,你可能会大幅减少可用的数据量——这可能是机器学习中最糟糕的情况。
尽管如此,在缺失的数据点中通常存在隐藏的模式。这些模式可以为你试图解决的问题提供额外的洞察力。
我们可以像对待音乐中的沉默一样对待数据中的缺失值——从表面上看,它们可能被认为是负面的(没有贡献任何信息),但其中蕴含着巨大的潜力。
方法
注意:我们将使用 Python 和一个 人口普查数据集 (为本教程的目的而修改)
您可能会惊讶地发现有多少种处理缺失数据的方法。这证明了这个问题的重要性,也证明了创造性解决问题的巨大潜力。
你应该做的第一件事是数一数你有多少,并试着想象它们的分布。为了使这一步正常工作,您应该手动检查数据(或者至少是数据的一个子集),以尝试确定它们是如何指定的。可能的变体有:’ NaN ‘,’ NA ‘,’ None ‘,’ ‘,’?‘和其他人。如果你有不同于’ NaN '的东西,你应该通过使用 np.nan 来标准化它们。
import missingno as msno
msno.matrix(census_data)
Missing data visualisation. White fields indicate NA’s
import pandas as pd
census_data.isnull().sum()age 325
workclass 2143
fnlwgt 325
education 325
education.num 325
marital.status 325
occupation 2151
relationship 326
race 326
sex 326
capital.gain 326
capital.loss 326
hours.per.week 326
native.country 906
income 326
dtype: int64
让我们从你能做的最简单的事情开始:移除。如前所述,虽然这是一个快速的解决方案,并且在丢失值的比例相对较低(< 10%)的情况下可能有效,但大多数时候它会使您丢失大量数据。想象一下,仅仅因为某个要素中缺少值,您就不得不放弃整个观察值,即使其余的要素已经完全填充且信息丰富!
import numpy as np
census_data = census_data.replace('np.nan', 0)
第二糟糕的方法是用 0(或-1)替换。虽然这将有助于您运行您的模型,但它可能是极其危险的。这样做的原因是,有时这个值可能会产生误导。想象一个出现负值的回归问题(例如预测温度),在这种情况下,这将成为一个实际的数据点。
既然我们已经解决了这些问题,让我们变得更有创造力。我们可以根据父数据类型来划分缺失值的类型:
数值分析
一个标准且通常非常好的方法是用平均值、中间值或众数替换缺失值。对于数值,你应该选择平均值,如果有一些异常值,试试中值(因为它对异常值不太敏感)。
**from** sklearn.preprocessing **import** Imputer
imputer = Imputer(missing_values=np.nan, strategy='median', axis=0)
census_data[['fnlwgt']] = imputer.fit_transform(census_data[['fnlwgt']])
类别分析
分类值可能有点棘手,所以在编辑后,您一定要注意您的模型性能指标(比较前后)。标准做法是用最常用的条目替换丢失的条目:
census_data['marital.status'].value_counts()Married-civ-spouse 14808
Never-married 10590
Divorced 4406
Separated 1017
Widowed 979
Married-spouse-absent 413
Married-AF-spouse 23
Name: marital.status, dtype: int64def replace_most_common(x):
if pd.isnull(x):
return most_common
else:
return xcensus_data = census_data['marital.status'].map(replace_most_common)
结论
最重要的是,您应该知道从缺失数据中获取更多信息的不同方法,更重要的是,开始将它视为可能的洞察力来源,而不是烦恼!
快乐编码:)
奖励—先进的方法和可视化
理论上,您可以通过拟合回归模型来估算缺失值,例如线性回归或 k 最近邻。这一点的实现留给读者作为示例。
A visual example of kNN.
这里有一些可视化,也可以从奇妙的 missingno 包中获得,它可以帮助你以相关矩阵或树状图的形式揭示关系:
Correlation matrix of missing values. Values which are often missing together can help you solve the problem.
Dendrogram of missing values
处理文本数据—从质量到数量
注意你的语言:有毒评论的挑战
由于互联网上的大量文本数据,文本处理和分析变得越来越普遍。从拼写检查等相对简单的任务到监视网络活动等更加不祥的任务,基本项目是将语言和哲学的特殊性(如意义、内涵和上下文)转换为有意义的数学对象,然后可以输入到 ML 算法中。
让我们揭开这个问题的表面,看看解决这个问题的基本方法。假设我们有一组文档(也称为语料库)要分析。这些文档可以是推文、句子甚至整本书。要将文档转换为向量,一个简单的尝试是对我们的词汇表 V 中的所有单词进行排序,并让文档 d 由向量 v,表示,其中如果 d 包含我们的词汇表中的第 i 到第个单词,则该向量中的第 i 到第个条目为 1,否则为 0。这个过程的一个显而易见的结果是,我们的语料库中的所有文档都由相同大小的向量来表示,即我们的词汇量的大小|V|。**这里的缺点是我们已经失去了所有的语言结构,**这被恰当地称为单词袋模型。我们所获得的是我们词汇表中每个单词的数据特征。重新获得文档局部结构的一种方法是通过添加 ngrams 来扩大我们的词汇量。这些只是被视为一个单元的 n 个连续单词(将我们的词汇单元称为’*记号’*而不是单词更合适),这一变化允许我们考虑频繁共现的单词。
一个小小的改进是跟踪单词在文档中出现的次数,因此我们使用单词在文档中的频率,通常称为术语频率(TF ),而不是上面公式中的 1。现在,一个重要的词可能频繁出现,但频繁出现的词不一定重要;像‘the’和‘of’这样的词很少给出关于文档内容的信息。考虑到这一点,我们将使用与语料库中单词的频率成反比的权重,而不是仅使用单词的 TF 值,这通常被称为逆文档频率(IDF ),通常被认为是
TF 和 IDF 具有相反的趋势,如果该单词在文档中频繁出现,则 TF 值大(根据定义),如果该单词在语料库中的文档中频繁出现,则 IDF 权重低。这就是流行的 TF-IDF 方案的提法。
让我们玩玩这个概念,并将其应用于维基百科评论数据,作为 Kaggle 上 有毒评论分类挑战 的一部分。
这里的数据由维基百科的文本评论组成,其中一些评论被贴上了一个或多个标签——“有毒”、“严重 _ 有毒”、“淫秽”、“威胁”、“侮辱”和“身份 _ 仇恨”。这里我们的文档是单独的评论,目的是学习一些模式,并用零个或多个上述标签来标记一个新的评论。让我们使用 python 中的 sklearn 来看看 TF-IDF 的实际功能。
首先,我们导入数据(名为 test 和 train 的两个 CSV 文件)和一些 python 库:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import stringfrom sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.feature_extraction.text import CountVectorizer,
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
train = pd.read_csv('..\train.csv').fillna(' ')
test = pd.read_csv('..\test.csv').fillna(' ')train_text = train['comment_text']
test_text = test['comment_text']
文本数据通常需要一些清理,但如果我们希望使用上述方案来识别包含侮辱性和有毒语言的评论,这一点更重要。我们不应该将’ F*** ‘和’ F**k '视为不同的词,因为这会混淆我们的 TF 值。尽管有这样的警告,让我们满足于下面的简单函数 str_clean()并清理测试和训练文档集合。
# Replace all elements of punct by white spaces and delete all numbers and a few chosen punctuation import string
from nltk.stem import PorterStemmer
ps = PortStemmer()
def str_clean(text):
punct = '():[]?.,|_^-&><;!"/%'
table = str.maketrans(punct, ' '*len(punct), "0123456789$#'=")
cleaned_comment = []
for word in text.split():
cleaned_comment.extend(word.translate(table).split())
cleaned_comment = [ps.stem(word) for word in
cleaned_comment]
return " ".join(cleaned_comment)
在上面的代码块中,我们用空格替换了一些标点符号,并删除了一些数字和标点符号。最后,我们使用了 nltk 包中的一个特殊的“词干分析器”将一些单词转换成它们的“词根形式”——例如,“哔”、“哔”和“哔”到“哔”。这允许我们忽略单词的某些形式,因为它们本身是不同的单词。
train_text = train_text.map(lambda x: str_clean(x))
test_text = test_text.map(lambda x: str_clean(x))
Scikit-Learn 有一个内置函数 TfidfVectorizer ,它将语料库作为输入,输出文档的 TF-IDF 向量——这正是我们所需要的。我们现在需要做的就是应用 fit_transform 方法来获得所需的矩阵。该函数有多个参数,有助于获得更好的结果;小写和 strip_accents 允许进一步清理原始文本, min_df 和 max_df 允许我们限制哪些单词进入我们的词汇表。控制我们词汇的另一个重要方法是使用 stop_words 参数,该参数允许删除诸如“is”、“at”和“which”之类的单词。
tfidf_vectorizer = TfidfVectorizer(strip_accents='unicode',
analyzer='word', token_pattern=r'\w{1,}', ngram_range=(1, 2),
max_features=10000)train_features = tfidf_vectorizer.fit_transform(train_text)
test_features = tfidf_vectorizer.fit_transform(test_text)
max_features 参数允许将我们的词汇表限制为最频繁出现的特性;它假设最常用的术语是最重要的。我们的另一个选择是使用 sublinear 参数,它返回 1+log(TF ),而不仅仅是 TF。这可以用在这样的情况下,即有理由假设一个比另一个令牌多 n 倍出现的令牌不是重要 n 倍,而是大约重要 log(n)倍。最后,默认情况下应用 IDF 权重。
现在,有了这些特性,我们可以预测测试集中注释的类别标签。这是一个多标签问题,因此标签并不相互排斥。我们将在 sklearn 中使用 logit 来获得循环中每个类的预测。我们将使用三重交叉验证来检查 ROCAUC 分数(本次挑战的评估指标)不会大幅波动。
pred = pd.DataFrame([])
labels = ['toxic', 'severe_toxic', 'obscene', 'threat', 'insult', 'identity_hate']for label in labels:
target = train[label]
classifier = LogisticRegression(solver = 'sag')
cv_scores = cross_val_score(classifier, train_features,
train_target, cv=3, scoring = 'roc_auc')
mean_cv = np.mean(cv_scores) print('CV score for label {} is {}'.format(label,mean_cv))
print('\n') classifier.fit(train_features, train_target)
pred[label]=classifier.predict_proba(test_features)[:, 1]
虽然这是一个非常基本的模型,还有许多参数优化有待执行,但它做得相当好——交叉验证得分约为 0.97。从某种意义上来说,一个评论是否包含侮辱或有毒或可被视为身份仇恨,实际上在很大程度上是由话语本身所捕捉的。我们不需要钻研注释的语法或以更复杂的方式解析它来确定给出哪个标签,所以 TF-IDF 特征提取非常适合这里。
接下来呢?
这里的分析可以从改进的词汇中受益。人们对侮辱和谩骂有着非凡的创造力,我们需要更好的方式来看待同一侮辱或词语的各种形式。也许几个小时的正则表达式工作可以帮助大大提高分数。
并不是所有 IDF 分值大的单词都在区分类别标签。我们可以使用一些特征选择的方法来降低我们正在处理的向量的维数,并使用其他算法来进行预测。在后面的帖子中,我们将考虑一种称为双正态比例(BNS)的特征选择方法,该方法将权重添加到术语频率,类似于 IDF 权重,但考虑了文档的实际类别标签,以确定哪个特征对预测有影响。
其他特征可以附加到 TF-IDF 矩阵之外。粗略地看一下评论,看起来被归类为有毒的评论往往有更多的标点符号。像这样的元特征可以从数据中收集。
在任何情况下,为了保持理智和功能,不要涉入太多的有毒评论!
世界精神卫生日数据可视化:退伍军人与精神疾病
10 月 10 日是世界精神卫生日,旨在提高人们对精神卫生问题的认识,加大对精神卫生的支持力度,减少社会对精神疾病的歧视。2017 年心理健康日的主题是工作场所的心理健康。
退伍军人面临风险
虽然许多工作场所都充满压力,而且某些类型的工作或老板比其他人更有可能对心理健康造成损害,但很难想象有任何工作环境比军人所经历的工作环境更容易产生压力。虽然退伍军人管理局系统的医院和门诊诊所为许多美国退伍军人提供服务,但据估计,超过 20%的退伍军人寻求退伍军人管理局系统之外的精神健康治疗,在许多情况下,因为他们住的地方离退伍军人管理局下属的治疗中心不在合理的距离内。此外,那些因收入原因而被开除军籍或不符合退伍军人服务资格的退伍军人无法从退伍军人健康服务机构获得帮助。截至 2017 年 7 月 5 日,退伍军人医疗中心将为退伍军人提供长达 90 天的心理健康紧急情况护理。
退伍军人管理局东北项目评估中心发布了 2015 财年的心理健康统计数据。根据这些数据,2015 年有 1,570,907 名退伍军人在寻求退伍军人健康服务时被诊断患有精神疾病。我已经按州绘制了使用退伍军人健康服务的确诊患有精神疾病的退伍军人的总数。
要探索数据集的其他细节,请访问这个由退伍军人事务部维护的闪亮应用或包含原始数据的 GitHub 存储库。
寻求精神疾病的帮助
如果你或你认识的人现在有自杀倾向,你应该立即拨打 1–800–273–8255 的国家预防自杀生命线,拨打 911 或去医院急诊室。
对于任何痛苦情绪的短期帮助,美国的青少年可以通过给家里发短信 741741 给 24 小时危机短信热线发短信
成人或青少年可以拨打 1-800-273-TALK(8255)联系 24 小时危机中心,或者发短信给 MHA,号码是 741741
T4 精神健康网站可以帮助你在当地找到支持。
退伍军人可以拨打退伍军人危机热线 800–273–8255(按 1),或发短信 838255
感谢您的阅读。
我欢迎反馈——您可以“鼓掌”表示赞同,或者如果您有具体的回应或问题,请在此给我发消息。我也有兴趣听听你想在未来的帖子中涉及哪些主题。用于数据操作和数据可视化的代码可以在我的 GitHub 上找到。
阅读更多关于我的作品jenny-listman.netlify.com。欢迎随时通过 Twitter@ jblistman或LinkedIn联系我。
注意事项:
- 在https://www.va.gov/directory/guide/rpt_fac_list.cfm找到退伍军人事务部所在地的州和邮政编码数据
- 退伍军人事务部报告的原始数据从 Mihir Iyer 的 GitHub 储存库https://github.com/mihiriyer/mental下载
- 使用 R 中的工具处理和绘制数据
TensorFlow 中的世界模型—第 1.0 集— OpenAi 健身房赛车
Creative Common License
代理人能了解他们自己的梦吗?
论文开头的这一句话立刻引起了我的注意。
如果你还没有读过这篇文章,我肯定会推荐它,因为它令人兴奋,而且对理解本文的内容是必要的。
让我们实施它
每当我偶然发现一些有趣的事情时,我总是试图自己去实现它。
据我所知,我是第二个分享本文实现的人。
大卫·福斯特写了一篇非常好的博文,他在博文中一步步解释了他在 Keras 的实施。
然而,最有趣的部分——机器的梦想😴—缺失。
这一系列文章的目标是更深入地阅读 TensorFlow 中的代码,并在阅读过程中学习(与读者一起)。
我不会重新解释这个想法和方法,因为它们已经在最初的论文和作者写的博客中很好地覆盖了。
互动演示:点击屏幕以覆盖代理的决定。我们探索建立生成神经网络模型的…
worldmodels.github.io](https://worldmodels.github.io/)
OpenAi 健身赛车
这个任务的目标是训练一个代理在模拟的轨道上驾驶汽车。代理可以看到一个 96x96 的 RGB 像素网格,以及比赛完成后的最终奖励。
代理可以通过决定转向角度[-1,1]→[左,右],加速和刹车来控制汽车。
代理人如何看待世界🤖
首先要解决的是让代理人有可能以一种有意义的方式看到他们生活的世界。
作者使用变分自动编码器 - VAE -将每一帧的信息压缩成大小为 32 的向量。
(如果你还没看过,可以看看我的另一篇文章用人工神经网络生成数字和声音使用 VAEs。)
Left: What the human sees — Right: What the agent sees (Image created by the author)
获取代码
让我们从克隆我的回购代码开始:
git clone [https://github.com/dariocazzani/World-Models-TensorFlow](https://github.com/dariocazzani/World-Models-TensorFlow)
将所有依赖项(只需按照自述文件和光盘安装到 VAE 文件夹中:
cd [stateless_agent/](https://github.com/dariocazzani/World-Models-TensorFlow/tree/master/stateless_agent)
VAE 的数据
首先要做的是生成数据来训练 VAE,这就是 生成-VAE-data.py 脚本的作用。
在运行它之前,让我们先看看几件事:
如果您有一台带有多个 CPU 的机器,这两行代码将加快整个过程。
这里有一个小技巧来迫使环境将汽车定位在赛道上的任意点:
现在运行:
mkdir -p ../data
python generate-VAE-data.py
所有的数据将被放置在根文件夹下的文件夹 data 中。
自动编码器
作者提供了他们使用的 VAE 的详细描述,因此在 TensorFlow 中对其进行编码非常简单。
该脚本与 VAE 架构的定义一起提供了两个主要功能:
- train_vae() 会加载一个已保存的模型(如果存在)或者从头开始,训练直到损耗低于一个定义的值(我是凭经验挑的)。
- 代理将使用 load_vae() 将每一帧编码成一个嵌入向量。
训练 VAE
要开始训练变分自动编码器,只需运行:
python train_vae.py
并且在另一个终端中
tensorboard --logdir logdir
在我装有 Nvidia Geforce Titan X 的机器上,只需要几分钟就可以完成。
在 tensorboard URL 上打开浏览器,检查自动编码器是否正常工作。
Image created by the author
现在有趣的部分来了:让我们学开车吧!
为了驾驶汽车,代理需要输出 3 个值:
- 转向角
- 加速度值
- 制动值
我假设刹车时加速是没有意义的,所以代理只需输出 2 个参数,这将减少 1/3 的学习参数。
因为动作仅依赖于当前观察,所以参数的数量为:
Embedding_size * 2 + bias = 66
训练使用 CMA-ES 学习 66 个参数。作者说他们使用了 64 种药物,每种药物都在 16 次试验中进行了评估。因为我们还没有解决高级问题(RNN 的状态被输入到控制器中),为了加速训练,我把数字保持得较低。
当我完成完整的解决方案时,这些数字将会改变。
每个代理运行在不同的进程中,他们得到的回报是 12 次尝试的平均值。作者之一大卫·哈在他的博客进化稳定策略中很好地解释了为什么需要多次试验。
最后,运行:
python [train-agents.py](https://github.com/dariocazzani/World-Models-TensorFlow/blob/master/01-VAE/train-agents.py)
Image created by the author
并且等待…
几个小时后…
在我有 16 个 CPU 的机器上,我必须等待几个小时才能得到不错的结果。
差不多 100 代之后,最好的代理平均能拿到~740 的奖励。
Image created by the author
下一步是什么?
特工们的驾驶风格相当古怪。他们对之前发生的事情没有记忆,也没有能力预测采取某种行动后汽车会在哪里。
Image created by the author
在下一篇文章中,我将介绍如何训练 RNN,让它学会每一帧的潜在空间如何随着时间的推移和不同的动作而演变。
敬请关注,请在下面留下评论或提问😊
世界上最小的机器学习项目,将吸引你开始
机器学习火热!互联网上有大量关于机器学习的话题和文章。
大多数初学者仍然在机器学习中消耗大量的内容,而不是自己尝试一个小程序。因为大多数教程用所有的统计、数据清理、线性代数、复杂的数学、学习 python 或 r 淹没了初学者,所以初学者更喜欢消费更多的内容,而不是创造一些东西。初学者需要一个微型的“Hello world”项目来理解这些概念。如果你是一个机器学习爱好者,如果你还没有编写你的第一个机器学习程序,这个教程/项目是为你准备的。
机器学习项目涉及的步骤:
以下是创建定义良好的 ML 项目的步骤:
- 理解并定义问题
- 分析和准备数据
- 应用算法并训练模型
- 预测结果
我们的第一个项目:让我们根据数据科学家多年的工作经验来预测他的工资
学习新平台或工具的最佳方式是端到端地从事机器学习项目,并涵盖关键步骤。从加载数据、清洗数据、汇总数据、评估算法到最后做一些预测。
我们将使用一个简单的训练数据集:
根据工作经验的年数,我们将预测工资
our dataset
为什么这是一个适合初学者解决的问题:
- 这是一个简单的单变量问题(单变量线性回归),我们用美元($)来预测工资
- 属性是数字的,所以你必须弄清楚如何加载和处理数据,而且不需要数据清理或转换
- 数据集只有 2 个属性和 10 行,这意味着它很小,很容易放入内存并易于解释。
所以,花点时间去理解问题陈述。完成每一步。
您可以简单地点击命令,将命令复制并粘贴到您的程序中
看哪!要完成这个项目,您需要在系统中安装带有机器学习库的 python。设置机器学习环境需要 30 分钟。跟随此处的指南。
加载薪金数据集
- 启动 Anaconda navigator 并打开终端
- 键入以下命令启动 python 环境
python
- 让我们确保 python 环境已经启动并正在运行。将下面的命令复制粘贴到终端中,检查它是否正常工作
print("Hello World")
- 很好,让我们开始写我们的第一个程序。首先,导入项目所需的所有库是很重要的。因此,将下面的命令复制粘贴到终端中。(您可以一次复制全部内容)
import pandas
import numpy as np
import matplotlib.pyplot as plt from sklearn.metrics
import accuracy_score
- 现在,让我们加载 salary training 数据集,并将其分配给一个名为“data set”的变量
#Load training dataset
url = "[https://raw.githubusercontent.com/callxpert/datasets/master/data-scientist-salaries.cc](https://raw.githubusercontent.com/callxpert/datasets/master/data-scientist-salaries.cc)"
names = ['Years-experience', 'Salary']
dataset = pandas.read_csv(url, names=names)
汇总数据并进行分析
让我们来看看我们的训练数据集:
- 数据集的维度:使用 shape 属性找出我们的数据集有多少行和列
# shape
print(dataset.shape)
结果:(10,2),这意味着我们的数据集有 10 行 2 列
- 要查看数据集的前 10 行
print(dataset.head(10))
结果:
- 找出数据的统计摘要,包括计数、平均值、最小值和最大值以及一些百分点。
print(dataset.describe())
结果:
可视化数据并执行分析
现在,我们已经加载了库,导入了数据集,并进行了一些数据处理。现在是我们查看数据并理解它的时候了。
- 让我们用曲线图来看看数据集。复制粘贴以下命令,在我们的数据集上绘制一个图形
#visualize
dataset.plot()
plt.show()
如图所示,我们有两个参数。年资和薪资。橙色线表示两者之间的相关性
拆分数据
在机器学习中,我们有两种数据集
- 训练数据集—用于训练我们的模型
- 测试数据集—用于测试我们的模型是否做出准确的预测
由于我们的数据集很小(10 条记录),我们将使用 9 条记录来训练模型,1 条记录来评估模型。复制粘贴下面的命令来准备我们的数据集。
X = dataset[['Years-experience']]
y = dataset['Salary']
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=101)
训练模型
现在我们已经分析了数据,并准备好了我们的训练和测试集。我们将使用下面的命令来训练我们的模型。在这个例子中,我们选择线性回归,因为我们试图预测一个连续的数字(薪水)
from sklearn.linear_model import LinearRegression
model = LinearRegression()
model.fit(X_train,y_train)
测试模型
我们已经有了训练好的模型,现在我们应该开始用它来预测。让我们使用我们的测试数据集来估计我们的模型的准确性
predictions = model.predict(X_test)
print(accuracy_score(y_test,predictions))
我们得到了 1.0,这是我们模型的 100%准确性。这是理想的准确度分数。在生产系统中,任何超过 90%的都被认为是成功的模型
我们也可以用我们自己的输入来测试我们的模型
让我们试试一个有 6.3 年经验的人能赚多少钱
print(model.predict(6.3))
结果:【163000。].我们的模型估计一个有 6.3 年经验的人需要 16.3 万英镑。
恭喜你完成了你的第一个机器学习项目。现在休息一下,去慢跑,或者欣赏一下你渴望已久的网飞秀
摘要
总之,在本教程中,您逐步了解了如何使用 Python 中的第一个机器学习项目来导入、分析和预测
你的下一步
再次浏览这个教程来修正你的理解。列出你的疑问并在网上搜索。激动吗?需要多运动?尝试另一个机器学习项目:
最初发表于【copycoding.com】。机器学习社区