<<返回python首页 python

《Python 应用案例》

使用Gensim库实现word2vec和fasttext

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

使用Gensim库实现word2vec和fasttext

传统的词向量表示方法

表示单词的传统方式是单热(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/ )通过将该单词的one-hot表示输入网络中之后提取隐藏层,可以获得目标词的词嵌入。使用skip-gram,表示维度从词汇量大小(V)减小到隐藏层(N)的长度。此外,就描述单词之间的关系而言,向量更“有意义”。通过减去两个相关词而获得的向量有时表达一个有意义的概念,如性别或动词时态。

Skip-gram

CBOW

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

cbow

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的性能大致相似。

fasttext

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

gensim中Word2Vec实现

我将向你展示如何使用Gensim,强大的NLP工具包和TED Talk数据集表示词嵌入。首先,我们使用urllib下载数据集,从文件中提取副标题。

安装相应库

!pip3 install gensim -i https://pypi.tuna.tsinghua.edu.cn/simple
!pip3 install lxml -i https://pypi.tuna.tsinghua.edu.cn/simple

导入相应库

import numpy as np
import os
from random import shuffle
import re
import urllib.request
import zipfile
import lxml.etree

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

#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[:20]

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

# 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[:2]

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

#比较耗时
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”这个词最相似。

model_ted.wv.most_similar("man")

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

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

gensim中Fasttext实现

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

from gensim.models import FastText
model_ted = FastText(sentences_ted, size=100, window=5, min_count=5, workers=4,sg=1

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

model_ted.wv.most_similar("Gastroenteritis")

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

总结

你已经了解了Word2Vec和FastText以及使用Gensim工具包实现的内容。

转载自:https://towardsdatascience.com/word-embedding-with-word2vec-and-fasttext-a209c1d3e12c

移动端设备除iPad Pro外,其它移动设备仅能阅读基础的文本文字。
建议使用PC或笔记本电脑,浏览器使用Chrome或FireFox进行浏览,以开启左侧互动实验区来提升学习效率,推荐使用的分辨率为1920x1080或更高。
我们坚信最好的学习是参与其中这一理念,并致力成为中文互联网上体验更好的学练一体的IT技术学习交流平台。
您可加QQ群:575806994,一起学习交流技术,反馈网站使用中遇到问题。
内容、课程、广告等相关合作请扫描右侧二维码添加好友。

狐狸教程 Copyright 2021

进入全屏