Press "Enter" to skip to content

使用Gensim逐步指南Word2Vec

介绍

几个月前,当我刚开始在Office People工作时,我对语言模型,尤其是Word2Vec产生了兴趣。作为一个使用Python的本地用户,我自然而然地专注于Gensim的Word2Vec实现,并在网上寻找论文和教程。我直接应用并复制了来自多个来源的代码片段,就像任何一个优秀的数据科学家所做的那样。我进一步深入,试图理解我的方法出了什么问题,阅读了Stackoverflow的讨论、Gensim的Google Groups和该库的文档。

使用Gensim逐步指南Word2Vec 四海 第1张

然而,我一直认为创建Word2Vec模型的最重要的方面之一被忽略了。在我的实验过程中,我发现对句子进行词形还原或查找词组/二元组对结果和模型性能有很大的影响。尽管预处理的影响因数据集和应用而异,但我决定在本文中包含数据准备步骤,并与之配合使用绝妙的spaCy库。

其中一些问题让我很烦恼,所以我决定写一篇自己的文章。我不能保证它是完美的或者是实现Word2Vec的最佳方法,但至少比很多其他文章好。

学习目标

  • 了解词嵌入及其在捕捉语义关系中的作用。
  • 使用流行的库如Gensim或TensorFlow实现Word2Vec模型。
  • 使用Word2Vec嵌入度量词语相似度和计算距离。
  • 探索Word2Vec捕捉到的词语类比和语义关系。
  • 在情感分析和机器翻译等各种NLP任务中应用Word2Vec。
  • 学习微调Word2Vec模型以适应特定任务或领域的技巧。
  • 使用子词信息或预训练的嵌入来处理词汇表外的单词。
  • 了解Word2Vec的限制和权衡,如词义消歧和句子级语义。
  • 深入研究诸如子词嵌入和通过Word2Vec进行模型优化等高级主题。

本文作为Data Science Blogathon的一部分发布。

Word2Vec简介

谷歌的一个研究团队在2013年9月和10月之间发表了两篇关于Word2Vec的论文。研究人员还在论文中发布了他们的C实现。Gensim在第一篇论文发表后不久完成了Python实现。

使用Gensim逐步指南Word2Vec 四海 第2张

Word2Vec的基本假设是具有相似上下文的两个词具有相似的含义,因此模型中的向量表示也是相似的。例如,”狗”、”小狗”和”幼犬”经常在相似的上下文中使用,周围的词语也相似,比如”好”、”蓬松”或”可爱”,因此根据Word2Vec,它们具有相似的向量表示。

基于这个假设,Word2Vec可以用于发现数据集中词语之间的关系,计算它们的相似性,或者将这些词语的向量表示作为其他应用(如文本分类或聚类)的输入。

Word2Vec的实现

Word2Vec的思想非常简单。我们假设通过其周围的词语可以推断出一个词的含义。这类似于谚语”告诉我你的朋友,我会告诉你是谁”。下面是Word2Vec的一个实现。

设置环境

python==3.6.3

使用的库:

  • xlrd==1.1.0:
  • spaCy==2.0.12:
  • gensim==3.4.0:
  • scikit-learn==0.19.1:
  • seaborn==0.8:
import re  # 用于预处理
import pandas as pd  # 用于数据处理
from time import time  # 用于计时
from collections import defaultdict  # 用于词频统计

import spacy  # 用于预处理

import logging  # 设置日志以监控gensim
logging.basicConfig(format="%(levelname)s - %(asctime)s: %(message)s", 
                    datefmt= '%H:%M:%S', level=logging.INFO)

数据集

该数据集包含了600多集《辛普森一家》的角色、地点、剧集详情和剧本对话信息,追溯到1989年。可在Kaggle上获取。(约25MB)

预处理

在预处理过程中,我们只保留数据集中的两列:raw_character_text和spoken_words。

  • raw_character_text:说话的角色(用于跟踪预处理步骤)。
  • spoken_words:对话行中的原始文本。

因为我们想要进行自己的预处理,所以不保留normalized_text。

df = pd.read_csv('../input/simpsons_dataset.csv')
df.shape

使用Gensim逐步指南Word2Vec 四海 第3张

df.head()

使用Gensim逐步指南Word2Vec 四海 第4张

缺失值来自剧本中的某个部分,该部分发生了某些情节,但没有对话。“(斯普林菲尔德小学:外景 小学操场 下午)”就是一个例子。

df.isnull().sum()

使用Gensim逐步指南Word2Vec 四海 第5张

清洗

对于每一行对话,我们进行词形还原,去除停用词和非字母字符。

nlp = spacy.load('en', disable=['ner', 'parser']) 

def cleaning(doc):
    # 词形还原和去除停用词
    # doc需要是一个spacy Doc对象
    txt = [token.lemma_ for token in doc if not token.is_stop]



    if len(txt) > 2:
        return ' '.join(txt)

去除非字母字符:

brief_cleaning = (re.sub("[^A-Za-z']+", ' ', str(row)).lower() for row in df['spoken_words'])

使用spaCy的pipe()属性加速清洗过程:

t = time()

txt = [cleaning(doc) for doc in nlp.pipe(brief_cleaning, batch_size=5000,
                   n_threads=-1)]

print('清理完毕所需时间:{}分钟'.format(round((time() - t) / 60, 2)))

使用Gensim逐步指南Word2Vec 四海 第6张

为了去除缺失值和重复值,将结果放入一个DataFrame中:

df_clean = pd.DataFrame({'clean': txt})
df_clean = df_clean.dropna().drop_duplicates()
df_clean.shape

使用Gensim逐步指南Word2Vec 四海 第7张

二元组

二元组是自然语言处理和文本分析中使用的一个概念。它们指的是在一个文本序列中连续出现的两个单词或字符对。通过分析二元组,我们可以了解给定文本中单词或字符之间的关系。

让我们举一个例子句子:“我喜欢冰淇淋”。为了识别该句子中的二元组,我们查看连续的两个单词对:

“我喜欢”

“喜欢冰”

“冰淇淋”

每个二元组代表一个二元组。二元组在各种语言处理任务中都很有用。例如,在语言建模中,我们可以根据前一个单词预测句子中的下一个单词。

二元组可以扩展为更大的序列,称为三元组(连续的三个元素)或n元组(连续的n个单词或字符)。n的选择取决于具体的分析或任务。

使用Gensim Phrases包来自动检测一组句子中的常见短语(二元组)。https://radimrehurek.com/gensim/models/phrases.html

我们主要是为了捕捉像“mr_burns”和“bart_simpson”这样的词语!

from gensim.models.phrases import Phrases, Phraser
sent = [row.split() for row in df_clean['clean']]

以下短语是从句子列表中生成的:

phrases = Phrases(sent, min_count=30, progress_per=10000)

使用Gensim逐步指南Word2Vec 四海 第8张

Phraser()的目标是通过丢弃对二元组检测任务不严格要求的模型状态来减少Phrases()的内存消耗:

bigram = Phraser(phrases)

使用Gensim逐步指南Word2Vec 四海 第9张

根据检测到的二元组对语料进行转换:

sentences = bigram[sent]

最常见的词语

主要是对词形还原、去停用词和添加二元组的有效性进行检查。

word_freq = defaultdict(int)
for sent in sentences:
    for i in sent:
        word_freq[i] += 1
len(word_freq)

使用Gensim逐步指南Word2Vec 四海 第10张

sorted(word_freq, key=word_freq.get, reverse=True)[:10]

使用Gensim逐步指南Word2Vec 四海 第11张

将模型的训练分为3个步骤

为了清晰和监控,我更喜欢将训练分为三个不同的步骤。

  • Word2Vec():
    • 在第一步中,逐个设置模型的参数。
    • 通过不提供参数sentences,有意地使模型未初始化。
  • build_vocab():
    • 通过从句子序列中构建词汇表来初始化模型。
    • 我可以通过日志跟踪进度,更重要的是,通过min_count和sample参数对词语语料的影响。我发现这两个参数,特别是sample,对模型性能有重要影响。显示两者可以更准确和简单地管理它们的影响。
  • .train():
    • 最后,对模型进行训练。
    • 这个页面上的日志大多数是有用的。
import multiprocessing

from gensim.models import Word2Vec

cores = multiprocessing.cpu_count() # 计算计算机的核心数量


w2v_model = Word2Vec(min_count=20,
                     window=2,
                     size=300,
                     sample=6e-5, 
                     alpha=0.03, 
                     min_alpha=0.0007, 
                     negative=20,
                     workers=cores-1)

word2vec的Gensim实现:https://radimrehurek.com/gensim/models/word2vec.html

构建词汇表

Word2Vec要求我们创建词汇表(通过消化所有单词,过滤出唯一单词,并对其进行一些基本计数):

t = time()

w2v_model.build_vocab(sentences, progress_per=10000)

print('建立词汇表的时间:{}分钟'.format(round((time() - t) / 60, 2)))

使用Gensim逐步指南Word2Vec 四海 第12张

词汇表对于在训练或推断过程中将单词编码为索引并查找其对应的词嵌入是至关重要的。它为训练Word2Vec模型奠定了基础,并实现了连续向量空间中的高效词表示。

模型的训练

训练Word2Vec模型涉及将文本数据语料库输入到算法中,并优化模型的参数以学习词嵌入。Word2Vec的训练参数包括各种超参数和设置,它们影响训练过程和生成的词嵌入的质量。以下是一些常用的Word2Vec训练参数:

  • total_examples = int – 句子的数量;
  • epochs = int – 语料库的迭代次数(epochs) – [10, 20, 30]
t = time()

w2v_model.train(sentences, total_examples=w2v_model.corpus_count, epochs=30, report_delay=1)

print('训练模型的时间:{} 分钟'.format(round((time() - t) / 60, 2)))

我们调用init_sims()函数使模型更节省内存,因为我们不打算进一步训练它:

w2v_model.init_sims(replace=True)

使用Gensim逐步指南Word2Vec 四海 第13张

这些参数控制诸如上下文窗口大小、常见词和罕见词之间的权衡、学习率、训练算法以及负采样的负样本数量等方面。调整这些参数可能会影响Word2Vec训练过程的质量、效率和内存需求。

探索模型

一旦训练了Word2Vec模型,您可以探索它以深入了解学到的词嵌入并提取有用的信息。以下是一些探索Word2Vec模型的方法:

最相似的词

在Word2Vec中,您可以根据学到的词嵌入找到与给定词最相似的词。相似性通常使用余弦相似度来计算。以下是使用Word2Vec查找与目标词最相似的词的示例:

让我们看看对于这个节目的主角我们会得到什么:

similar_words = w2v_model.wv.most_similar(positive=["homer"])
for word, similarity in similar_words:
    print(f"{word}: {similarity}")

使用Gensim逐步指南Word2Vec 四海 第14张

请注意,当我们查看与“homer”最相似的词时,并不一定会得到他的家庭成员、个性特征或他最令人难忘的台词。

相比之下,看看二元词组“homer_simpson”返回了什么:

w2v_model.wv.most_similar(positive=["homer_simpson"])

使用Gensim逐步指南Word2Vec 四海 第15张

那现在来看看Marge:

w2v_model.wv.most_similar(positive=["marge"])

使用Gensim逐步指南Word2Vec 四海 第16张

现在我们来检查一下Bart:

w2v_model.wv.most_similar(positive=["bart"])

使用Gensim逐步指南Word2Vec 四海 第17张

看起来有点道理!

相似性

下面是使用Word2Vec找到两个词之间余弦相似度的示例:

示例:计算两个词之间的余弦相似度。

w2v_model.wv.similarity("moe_'s", 'tavern')

使用Gensim逐步指南Word2Vec 四海 第18张

<p谁能忘记Moe's酒馆?巴尼肯定不会忘记。

w2v_model.wv.similarity('maggie', 'baby')

使用Gensim逐步指南Word2Vec 四海 第19张

Maggie确实是辛普森一家中最有名的宝宝!

w2v_model.wv.similarity('bart', 'nelson')

使用Gensim逐步指南Word2Vec 四海 第20张

Bart和Nelson虽然是朋友,但并不亲密,这很合理!

不合群的

在这里,我们要求模型给出不属于列表的单词!

在Jimbo、Milhouse和Kearney中,哪个不是恶霸?

w2v_model.wv.doesnt_match(['jimbo', 'milhouse', 'kearney'])

使用Gensim逐步指南Word2Vec 四海 第21张

如果我们比较Nelson、Bart和Milhouse之间的友谊呢?

w2v_model.wv.doesnt_match(["nelson", "bart", "milhouse"])

使用Gensim逐步指南Word2Vec 四海 第22张

看起来Nelson是不合群的!

最后但并非最不重要的是,霍马和他的两个弟媳之间的关系如何?

w2v_model.wv.doesnt_match(['homer', 'patty', 'selma'])

使用Gensim逐步指南Word2Vec 四海 第23张

该死,他们真的不喜欢你,霍马!

类比差异

哪个词对应于“woman”如同“homer”对应于“marge”?

w2v_model.wv.most_similar(positive=["woman", "homer"], negative=["marge"], topn=3)

使用Gensim逐步指南Word2Vec 四海 第24张

“man”在第一位,看起来没错!

哪个词对应于“woman”如同“Bart”对应于“man”?

w2v_model.wv.most_similar(positive=["woman", "bart"], negative=["man"], topn=3)

使用Gensim逐步指南Word2Vec 四海 第25张

Lisa是Bart的姐姐,她的男性对应!

结论

总之,Word2Vec是自然语言处理领域中广泛使用的算法,通过将词表示为连续向量空间中的密集向量来学习词嵌入。它基于文本语料库中词的共现模式捕捉词之间的语义和句法关系。

Word2Vec通过使用连续词袋模型(CBOW)或Skip-gram模型来工作,这些模型是神经网络架构。Word2Vec生成的词嵌入是单词的密集向量表示,编码了语义和句法信息。它们允许进行诸如单词相似性计算之类的数学运算,并可用作各种自然语言处理任务的特征。

要点

  • Word2Vec学习单词的词嵌入,即单词的密集向量表示。
  • 它分析文本语料库中的共现模式,以捕捉语义关系。
  • 该算法使用具有CBOW或Skip-gram模型的神经网络。
  • 词嵌入使得单词相似性计算成为可能。
  • 它们可以用作各种自然语言处理任务的特征。
  • Word2Vec需要大量的训练语料库以获得准确的嵌入。
  • 它无法捕捉单词的语义消歧。
  • Word2Vec不考虑单词顺序。
  • 未登录词可能会带来挑战。
  • 尽管存在限制,但Word2Vec在自然语言处理中有重要的应用。

虽然Word2Vec是一个强大的算法,但它也有一些限制。它需要大量的训练数据来学习准确的词嵌入。它将每个单词视为一个原子实体,并且无法捕捉单词的语义消歧。未登录词可能会带来挑战,因为它们没有预先存在的嵌入。

Word2Vec在自然语言处理的进步中做出了重要贡献,并且在信息检索、情感分析、机器翻译等任务中仍然是一个有价值的工具。

常见问题和回答

本文中显示的媒体不属于Analytics Vidhya所有,仅由作者自行决定使用。

Leave a Reply

Your email address will not be published. Required fields are marked *