前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用Gensim实现Word2Vec和FastText词嵌入

使用Gensim实现Word2Vec和FastText词嵌入

作者头像
银河1号
发布2019-05-15 17:43:30
1.8K0
发布2019-05-15 17:43:30
举报
文章被收录于专栏:银河系资讯

在自然语言处理(NLP)中,我们经常将词映射到包含数值的向量中,以便机器可以理解它。词嵌入是一种映射,允许具有相似含义的单词具有相似的表示。本文将介绍两种最先进的词嵌入方法,Word2VecFastText以及它们在Gensim中的实现。

传统方法

表示单词的传统方式是单热(one-hot)向量,其本质上是仅具有一个元素为1且其他为0的向量。向量的长度等于语料库中的总唯一词汇(去重后)的大小。通常,这些独特的单词按字母顺序编码。也就是说,你应该希望one-hot向量用于表示以“a”开头的单词,其中“1”的索引较低,而以“z”开头的那些单词,“1”的索引较高。

虽然这种单词表示简单易行,但存在一些问题。首先,你不能推断两个单词之间的任何关系根据他们的one-hot表示。例如,“endure”和“tolerate”这两个词虽然具有相似的含义,但它们的目标“1”彼此相距很远。此外,稀疏性是另一个问题,因为向量中存在许多冗余“0”。这意味着我们浪费了大量的空间。我们需要更好地表达单词以解决这些问题。

Word2Vec

Word2Vec是这些问题的有效解决方案,它利用了目标词的上下文。本质上,我们希望使用周围的单词来表示目标单词,通过神经网络的隐藏层对单词表示进行编码。

有两种类型的Word2Vec,Skip-gram和Continuous Bag of Words(CBOW)。我将在下面的段落中简要描述这两种方法是如何工作的。

Skip-gram

对于skip-gram,输入是目标词,而输出是目标词周围的词。例如,在句子“I have a cute dog”中,输入为“a”,而输出为“I”,“have”,“cute”和“dog”,假设窗口大小为5.所有输入和输出数据都具有相同的维度和一个one-hot编码。网络包含1个隐藏层,其维度等于嵌入大小,小于输入/输出向量大小。在输出层的末端,应用softmax激活函数,以便输出向量的每个元素描述特定单词在上下文中出现的可能性。下图显示了网络结构。

Skip-gram(https://www.analyticsvidhya.com/blog/2017/06/word-embeddings-count-word2veec/)

Skip-gram(https://www.analyticsvidhya.com/blog/2017/06/word-embeddings-count-word2veec/)

通过将该单词的one-hot表示输入网络中之后提取隐藏层,可以获得目标词的词嵌入。

使用skip-gram,表示维度从词汇量大小(V)减小到隐藏层(N)的长度。此外,就描述单词之间的关系而言,向量更“有意义”。通过减去两个相关词而获得的向量有时表达一个有意义的概念,如性别或动词时态,如下图所示(维数减少)。

Visualize Word Vectors(https://www.tensorflow.org/images/linear-relationships.png)

CBOW

连续词袋(CBOW)与skip-gram非常相似,只是它交换输入和输出。我们的想法是,在给定上下文的情况下,我们想知道哪个词最有可能出现在其中。

Skip-gram(https://www.analyticsvidhya.com/blog/2017/06/word-embeddings-count-word2veec/)

CBOW(https://www.analyticsvidhya.com/blog/2017/06/word-embeddings-count-word2veec/)

Skip-gram和CBOW之间最大的区别在于生成单词向量的方式。对于CBOW,将目标的所有示例输入到网络中,并取出提取的隐藏层的平均值。例如,假设我们只有两个句子,“He is a nice guy”和“She is a wise queen”。为了计算单词“a”的词表示,我们需要在神经网络中输入这两个例子,“He is nice guy”和“She is wise queen”并取隐藏层中的值的平均值。Skip-gram仅输入一个且仅一个目标词的one-hot向量作为输入。

据称,Skip-gram在罕见的词汇方面往往做得更好。然而,Skip-gram和CBOW的性能大致相似。

实现

我将向你展示如何使用Gensim,强大的NLP工具包和TED Talk数据集表示词嵌入。

首先,我们使用urllib下载数据集,从文件中提取副标题。

代码语言:javascript
复制
import numpy as np
import os
from random import shuffle
import re
import urllib.request
import zipfile
import lxml.etree
#download the data
        urllib.request.urlretrieve("https://wit3.fbk.eu/get.php?path=XML_releases/xml/ted_en-20160408.zip&filename=ted_en-20160408.zip", filename="ted_en-20160408.zip")
        # extract subtitle
        with zipfile.ZipFile('ted_en-20160408.zip', 'r') as z:
        doc = lxml.etree.parse(z.open('ted_en-20160408.xml', 'r'))
        input_text = '\n'.join(doc.xpath('//content/text()'))

让我们看一下input_text变量的存储,如下图所示。

input_text

input_text

显然,有些冗余信息对我们理解谈话没有帮助,例如括号中描述声音的单词和说话者的姓名。我们用正则表达式去除这些单词。

代码语言:javascript
复制
# remove parenthesis
        input_text_noparens = re.sub(r'\([^)]*\)', '', input_text)
        # store as list of sentences
        sentences_strings_ted = []
 for line in input_text_noparens.split('\n'):
        m = re.match(r'^(?:(?P<precolon>[^:]{,20}):)?(?P<postcolon>.*)$', line)
        sentences_strings_ted.extend(sent for sent in m.groupdict()['postcolon'].split('.') if sent)
        # store as list of lists of words
        sentences_ted = []
 for sent_str in sentences_strings_ted:
        tokens = re.sub(r"[^a-z0-9]+", " ", sent_str.lower()).split()
        sentences_ted.append(tokens)

现在,sentences_ted已被转换为二维数组,每个元素都是一个单词。让我们打印出第一个和第二个元素。

sentences_ted

这是准备输入Gensim中定义的Word2Vec模型的表单。Word2Vec模型可以通过一行轻松训练,如下面的代码所示。

代码语言:javascript
复制
from gensim.models import Word2Vec
model_ted = Word2Vec(sentences=sentences_ted, size=100, window=5, min_count=5, workers=4, sg=0)

· sentences:切分句子的列表。

· size:嵌入向量的维数

· window:你正在查看的上下文单词数

· min_count:告诉模型忽略总计数小于这个数字的单词。

· workers:正在使用的线程数

· sg:是否使用skip-gram或CBOW

现在,让我们尝试哪些词与“man”这个词最相似。

代码语言:javascript
复制
model_ted.wv.most_similar(“man”)

看起来与men/women/kid相关的单词与“man”最相似。

尽管Word2Vec成功处理了one-hot向量引起的问题,但它有一些局限性。最大的挑战是它无法表示未出现在训练数据集中的单词。尽管使用包含更多词汇表的更大训练集,但很少使用的罕见单词永远不能映射到向量。

FastText

FastText是Facebook在2016年提出的Word2Vec的扩展。FastText不是将单个词输入神经网络,而是将词分成几个n-gram(sub-words)。例如,apple这个词的三元组是app,ppl和ple(忽略单词边界的起点和终点)。apple的词嵌入向量将是所有这些n-gram的总和。在训练神经网络之后,我们将根据训练数据集对所有n-gram进行词嵌入。现在可以恰当地表达稀有的单词,因为很可能他们的一些n-gram也出现在其他单词中。我将在下一节中向你展示如何在Gensim中使用FastText。

实现

与Word2Vec类似,我们只需要一行来指定训练词嵌入的模型。

代码语言:javascript
复制
from gensim.models import FastText
model_ted = FastText(sentences_ted, size=100, window=5, min_count=5, workers=4,sg=1)

让我们尝试使用Gastroenteritis这个词,这个词很少使用,也没有出现在训练数据集中。

代码语言:javascript
复制
model_ted.wv.most_similar("Gastroenteritis")

即使训练数据集中不存在Gastroenteritis这个词,它仍然能够确定这个词与某些医学术语密切相关。如果我们在之前定义的Word2Vec中尝试这个,它会弹出错误,因为训练数据集中不存在这样的单词。虽然训练FastText模型需要更长的时间(n-gram的数量>单词的数量),但它比Word2Vec表现更好,并且允许恰当地表示罕见的单词。

结论

你已经了解了Word2Vec和FastText以及使用Gensim工具包实现的内容。如果你有任何问题,请随时在下面发表评论。如果你喜欢这篇文章,请确保你在twitter上关注我,这样你就不会错过任何好的机器学习/深度学习博客文章!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-03-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 银河系1号 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 传统方法
  • Word2Vec
  • Skip-gram
  • CBOW
  • 实现
  • FastText
  • 实现
  • 结论
相关产品与服务
NLP 服务
NLP 服务(Natural Language Process,NLP)深度整合了腾讯内部的 NLP 技术,提供多项智能文本处理和文本生成能力,包括词法分析、相似词召回、词相似度、句子相似度、文本润色、句子纠错、文本补全、句子生成等。满足各行业的文本智能需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档