一、介绍
Word2Vec是NLP领域的最新突破。Tomas Mikolov是捷克计算机科学家,目前是CIIRC(捷克信息学,机器人和控制论研究所)的研究员,是word2vec研究和实施的主要贡献者之一。词嵌入是解决NLP中许多问题不可或缺的一部分。它们描绘了人类如何向机器理解语言。您可以将它们想象为文本的矢量化表示形式。Word2Vec是一种生成词嵌入的常用方法,具有多种应用,例如文本相似性,推荐系统,情感分析等。
二、什么是词嵌入?
在我们进入word2vec之前,让我们了解什么是单词嵌入。了解这一点很重要,因为word2vec的总体结果和输出将是与通过算法传递的每个唯一单词相关联的嵌入。
词嵌入是一种将单个单词转换为单词的数字表示(向量)的技术。其中每个单词映射到一个向量,然后以类似于神经网络的方式学习该向量。向量试图捕捉该词相对于整个文本的各种特征。这些特征可以包括单词的语义关系、定义、上下文等。使用这些数字表示形式,您可以做很多事情,例如识别单词之间的相似性或相似性。
显然,这些是机器学习各个方面的不可或缺的输入。机器无法处理原始形式的文本,因此将文本转换为嵌入将允许用户将嵌入提供给经典的机器学习模型。最简单的嵌入是文本数据的一次热编码,其中每个向量将映射到一个类别。
For example: have = [1, 0, 0, 0, 0, 0, ... 0] a = [0, 1, 0, 0, 0, 0, ... 0] good = [0, 0, 1, 0, 0, 0, ... 0] day = [0, 0, 0, 1, 0, 0, ... 0] ...
但是,像这样的简单嵌入存在多种限制,因为它们不能捕获单词的特征,并且根据语料库的大小,它们可能非常大。
三、Word2Vec 架构
Word2Vec的有效性来自于它能够将相似单词的向量组合在一起。给定足够大的数据集,Word2Vec可以根据单词在文本中的出现对单词的含义进行强有力的估计。这些估计值产生与语料库中其他单词的单词关联。例如,像“国王”和“女王”这样的词会非常相似。在对词嵌入进行代数运算时,您可以找到词相似性的近似值。例如,“国王”的二维嵌入向量 - “男人”的二维嵌入向量+“女人”的二维嵌入向量产生了一个非常接近“女王”嵌入向量的向量。请注意,以下值是任意选择的。
King - Man + Woman = Queen [5,3] - [2,1] + [3, 2] = [6,4]
你可以看到国王和王后这两个词在位置上彼此接近。(图片由作者提供)
有两种主要的架构可以带来word2vec的成功。skip-gram 和 CBOW 架构。
四、CBOW(连续词袋)
这种架构与前馈神经网络非常相似。此模型体系结构实质上是尝试从上下文单词列表中预测目标单词。这个模型背后的直觉很简单:给定一个短语,我们将选择我们的目标词是“a”,我们的上下文词是[“有”,“很棒”,“日”]。该模型将要做的是采用上下文词的分布式表示来尝试预测目标词。"Have a great day"
CBOW建筑。图像取自向量空间中单词表示的有效估计
五、连续跳克模型
skip-gram 模型是一个简单的神经网络,其中包含一个经过训练的隐藏层,以预测当输入单词存在时给定单词存在的概率。直观地,您可以想象 skip-gram 模型与 CBOW 模型相反。在此体系结构中,它将当前单词作为输入,并尝试准确预测当前单词之前和之后的单词。该模型本质上是尝试学习和预测指定输入词周围的上下文词。基于评估该模型准确性的实验,发现在大范围的词向量下,预测质量有所提高,但也增加了计算复杂性。该过程可以直观地描述,如下所示。
为跳克模型生成训练数据的示例。窗口大小为 3。图片由作者提供
如上所示,给定一些文本语料库,在某个滚动窗口中选择一个目标单词。训练数据由该目标单词和窗口中所有其他单词的成对组合组成。这是神经网络的结果训练数据。一旦模型被训练,我们基本上可以产生一个单词是给定目标的上下文单词的概率。下图显示了 skip-gram 模型的神经网络体系结构。
Skip-Gram 模型体系结构(图片由作者提供)
语料库可以表示为大小为 N 的向量,其中 N 中的每个元素对应于语料库中的一个单词。在训练过程中,我们有一对目标词和上下文词,输入数组在除目标词之外的所有元素中都将为 0。目标字将等于 1。隐藏层将学习每个单词的嵌入表示,产生 d 维嵌入空间。输出层是具有softmax激活功能的密集层。输出层基本上将产生与输入大小相同的向量,向量中的每个元素将包含一个概率。此概率表示语料库中目标词和关联词之间的相似性。
有关这两种模型的更详细概述,我强烈建议阅读此处概述这些结果的原始论文。
实现
我将展示如何使用word2vec生成词嵌入,并使用这些嵌入来查找相似的单词并通过PCA可视化嵌入。
数据
出于本教程的目的,我们将使用莎士比亚数据集。你可以在这里找到我用于本教程的文件,它包括莎士比亚为他的戏剧写的所有台词。
要求
<span style="background-color:#f2f2f2"><span style="color:#292929">nltk==3.6.1
node2vec==0.4.3
pandas==1.2.4
matplotlib==3.3.4
gensim==4.0.1
scikit-learn=0.24.1</span></span>
注意: 由于我们正在使用 NLTK,因此您可能需要下载以下语料库才能使用本教程的其余部分。这可以通过以下命令轻松完成:
import nltk
nltk.download('stopwords')
nltk.download('punkt')
import pandas as pd
import nltk
import string
import matplotlib.pyplot as plt
from nltk.corpus import stopwords
from nltk import word_tokenize
from gensim.models import Word2Vec as w2v
from sklearn.decomposition import PCA
# constants
PATH = 'data/shakespeare.txt'
sw = stopwords.words('english')
plt.style.use('ggplot')
# nltk.download('punkt')
# nltk.download('stopwords')
# import data
lines = []
with open(PATH, 'r') as f:
for l in f:
lines.append(l)
注意:将变量更改为您正在使用的数据的路径。PATH
预处理数据
# remove new lines
lines = [line.rstrip('\n') for line in lines]
# make all characters lower
lines = [line.lower() for line in lines]
# remove punctuations from each line
lines = [line.translate(str.maketrans('', '', string.punctuation)) for line in lines]
# tokenize
lines = [word_tokenize(line) for line in lines]
def remove_stopwords(lines, sw = sw):
'''
The purpose of this function is to remove stopwords from a given array of
lines.
params:
lines (Array / List) : The list of lines you want to remove the stopwords from
sw (Set) : The set of stopwords you want to remove
example:
lines = remove_stopwords(lines = lines, sw = sw)
'''
res = []
for line in lines:
original = line
line = [w for w in line if w not in sw]
if len(line) < 1:
line = original
res.append(line)
return res
filtered_lines = remove_stopwords(lines = lines, sw = sw)
停用词过滤说明
- 请注意,从这些行中删除的停用词是现代词汇。应用程序和数据对于清理单词所需的预处理策略类型具有高度重要性。
- 在我们的场景中,像“你”或“你自己”这样的词会出现在停用词中并从行中删除,但是由于这是莎士比亚的文本数据,因此不会使用这些类型的词。相反,删除“你”或“你自己”可能是有用的。保持对这些类型的微型更改的热衷,因为它们会对好模型与差模型的性能产生巨大差异。
- 出于此示例的目的,我不会在识别来自不同世纪的停用词时进行极端细节,但请注意您应该这样做。
嵌入
w = w2v(
filtered_lines,
min_count=3,
sg = 1,
window=7
)
print(w.wv.most_similar('thou'))
emb_df = (
pd.DataFrame(
[w.wv.get_vector(str(n)) for n in w.wv.key_to_index],
index = w.wv.key_to_index
)
)
print(emb_df.shape)
emb_df.head()
嵌入上的 PCA
pca = PCA(n_components=2, random_state=7)
pca_mdl = pca.fit_transform(emb_df)
emb_df_PCA = (
pd.DataFrame(
pca_mdl,
columns=['x','y'],
index = emb_df.index
)
)
plt.clf()
fig = plt.figure(figsize=(6,4))
plt.scatter(
x = emb_df_PCA['x'],
y = emb_df_PCA['y'],
s = 0.4,
color = 'maroon',
alpha = 0.5
)
plt.xlabel('PCA-1')
plt.ylabel('PCA-2')
plt.title('PCA Visualization')
plt.plot()
Tensorflow为word2vec模型做了一个非常漂亮,直观和用户友好的表示。我强烈建议您探索它,因为它允许您与word2vec的结果进行交互。
结束语
词嵌入是解决NLP中许多问题的重要组成部分,它描述了人类如何向机器理解语言。给定一个大型文本语料库,word2vec 生成一个与语料库中每个单词关联的嵌入向量。这些嵌入的结构使得具有相似特征的单词彼此非常接近。CBOW(连续词袋)和skip-gram模型是与word2vec相关的两个主要架构。给定一个输入单词,skip-gram 将尝试预测输入上下文中的单词,而 CBOW 模型将采用各种单词并尝试预测缺失的单词。