如果你在2015年做过文本分析项目,那么你大概率用的是word2vec模型。Sense2vec是基于word2vec的一个新模型,你可以利用它来获取更详细的、与上下文相关的词向量。本文主要介绍该模型的思想以及一些简单的实现。

多义性:word2vec遇到的问题

当人们编写字典和辞典时,我们会列出每个词语的不同含义。在自然语言处理过程中,利用文档的统计信息来定义词典的概念往往非常有效,其中word2vec系列模型是最常见的用于创建词典的模型。给定一个大规模的文本数据,word2vec模型将创建一个用于储存词语含义的词典,其中每行的数值代表一个词语的内在含义。此时要计算词典中两个单词之间的相似度,等价于计算这两行数据之间的相似性。

word2vec模型的问题在于词语的多义性。比如duck这个单词常见的含义有水禽或者下蹲,但对于 word2vec 模型来说,它倾向于将所有概念做归一化平滑处理,得到一个最终的表现形式。Nalisnick & Ravi注意到这个问题,他们认为模型应该考虑到词向量的多义性,这样我们可以更好地构建那些复杂的词向量。我们想要实现的功能是将不同含义的词语赋值成不同的词向量,同时我们也想知道给定上下文情况时,某个词语对应的具体含义。因此,我们需要分析上下文的内容,这正好是spaCy的用武之地。

Sense2vec: 利用 NLP 方法来构建更精确的词向量

sense2vec 模型的思想非常简单,如果要处理duck的多义性问题,我们只需要将两个不同含义的词语赋值成不同的词向量即可,即 duckNduckN 和 duckVduckV。我们一直在尝试实现这个模型,所以当Trask et al公布了其良好的模型试验结果后,我们很容易地认为这个想法是可行的。

我们跟随 Trask 等人的思路,并将部分的语音标签和名字标签纳入词向量中。此外,我们还合并了基本的名词短语和命名实体,从而获取了单一的词向量。虽然当前的模型只是个简单的草案,但是我们非常高兴可以得到这样的结果。沿着该模型的思路我们还可以做很多事情,比如处理多词问题或者单词拆解问题。

下述代码是数据预处理函数,考虑到篇幅问题,我将剩余部分的代码托管在Github

def transform_texts(texts):
# Load the annotation models
nlp = English()
# Stream texts through the models. We accumulate a buffer and release
# the GIL around the parser, for efficient multi-threading.
for doc in nlp.pipe(texts, n_threads=4):
# Iterate over base NPs, e.g. "all their good ideas"
for np in doc.noun_chunks:
# Only keep adjectives and nouns, e.g. "good ideas"
while len(np) > 1 and np[0].dep_ not in ('amod', 'compound'):
np = np[1:]
if len(np) > 1:
# Merge the tokens, e.g. good_ideas
np.merge(np.root.tag_, np.text, np.root.ent_type_)
# Iterate over named entities
for ent in doc.ents:
if len(ent) > 1:
# Merge them into single tokens
ent.merge(ent.root.tag_, ent.text, ent.label_)
token_strings = []
for token in tokens:
text = token.text.replace(' ', '_')
tag = token.ent_type_ or token.pos_
token_strings.append('%s|%s' % (text, tag))
yield ' '.join(token_strings)

虽然需要这些预处理过程,但是我们仍然可以利用该模型进行大规模的建模分析。因为 spaCy 使用 Cython 写的,它允许多线程操作,在四线程环境中该模型每秒可以处理 100,000 个单词。

数据预处理之后,我们可以利用常规的方法来训练词向量,比如原始的 C 语言代码、Gensim或者 GloVe。只要数据集中单词由空格分隔,且句子由换行符分隔开就没有问题。唯一需要注意的地方是该模型不应该试图利用其自身的符号,否则可能会错误地拆分标签信息。

我们利用 Gensim 中的基于负抽样方法的 Skip-Gram 模型来训练词向量,其中频数阀值为10 或 5。模型训练后我们将频数阀值设为50,从而减少模型的运算时间。

案例

当我们利用这些词向量来分析问题时,我们发现了许多有趣的事情,以下是一些简单的说明:

语义合成性

该模型训练出来的词向量可以很好地提取合成词的语义信息,比如该模型知道 fair game 不是一个游戏类型,而 multiplayer game 是一种游戏类型。

>>> model.similarity('fair_game|NOUN', 'game|NOUN')
0.034977455677555599
>>> model.similarity('multiplayer_game|NOUN', 'game|NOUN')
0.54464530644393849

同样地,该模型知道 class action 和 action 之间的相似度很低,而 class action lawsuit 和 lawsuit 之间有很高的相似度:

>>> model.similarity('class_action|NOUN', 'action|NOUN')
0.14957825452335169
>>> model.similarity('class_action_lawsuit|NOUN', 'lawsuit|NOUN')
0.69595765453644187

词语之间的相似性

以下是 Reddit 网上关于川普的词向量信息:

>>> model.most_similar(['Donald_Trump|PERSON'])
(u'Sarah_Palin|PERSON', 0.854670465),
(u'Mitt_Romney|PERSON', 0.8245523572),
(u'Barrack_Obama|PERSON', 0.808201313),
(u'Bill_Clinton|PERSON', 0.8045649529),
(u'Oprah|GPE', 0.8042222261),
(u'Paris_Hilton|ORG', 0.7962667942),
(u'Oprah_Winfrey|PERSON', 0.7941152453),
(u'Stephen_Colbert|PERSON', 0.7926792502),
(u'Herman_Cain|PERSON', 0.7869615555),
(u'Michael_Moore|PERSON', 0.7835546732)]

该模型返回了与‘川普’之间相似度较高的词语,从上述结果中可以看出该模型很好地识别出川普政治家和真人秀明星的身份。我对模型返回的 Michael Moore 非常感兴趣,我怀疑很多人都是他两的粉丝。如果我必须选择出一个异常值的话,那么我会选择 Oprah,该词条和其他词语的相似度较低。

该模型发现 Oprah|GPE 和 Oprah_Winfrey|PERSON 之间的相似度较高,这意味着命名实体识别器还存在一定的问题,具有提升的空间。

word2vec模型可以很好地识别出命名实体,特别是音乐领域的信息。这让我想起我曾经获取推荐音乐的方式:留意经常和我喜欢的乐队一起被提到的歌手。当然现在我们已经拥有更强大的推荐模型,比如观察成千上万人的行为进而得出相应的规律。但是对我来说,该模型在分析乐队相似度时仍存在一些奇怪的问题。

以下是该模型揭示的 Carrot Top 和 Kate Mara 之间潜在的联系:

>>> model.most_similar(['Carrot_Top|PERSON'])
[(u'Kate_Mara|PERSON', 0.5347248911857605),
(u'Andy_Samberg|PERSON', 0.5336876511573792),
(u'Ryan_Gosling|PERSON', 0.5287898182868958),
(u'Emma_Stone|PERSON', 0.5243821740150452),
(u'Charlie_Sheen|PERSON', 0.5209298133850098),
(u'Joseph_Gordon_Levitt|PERSON', 0.5196050405502319),
(u'Jonah_Hill|PERSON', 0.5151286125183105),
(u'Zooey_Deschanel|PERSON', 0.514430582523346),
(u'Gerard_Butler|PERSON', 0.5115377902984619),
(u'Ellen_Page|PERSON', 0.5094753503799438)]

我花了好多时间在思考这个问题,但是并没有得到任何有意义的结果。也许这里面存在更深层次的逻辑关系,我们需要进一步探究才能得到结果。但是当我们往模型中加入更多的数据时,该现象就消失了,就和 Carrot Top 一样。

食品领域

>>> model.most_similar(['onion_rings|NOUN'])
[(u'hashbrowns|NOUN', 0.8040812611579895),
(u'hot_dogs|NOUN', 0.7978234887123108),
(u'chicken_wings|NOUN', 0.793393611907959),
(u'sandwiches|NOUN', 0.7903584241867065),
(u'fries|NOUN', 0.7885469198226929),
(u'tater_tots|NOUN', 0.7821801900863647),
(u'bagels|NOUN', 0.7788236141204834),
(u'chicken_nuggets|NOUN', 0.7787706255912781),
(u'coleslaw|NOUN', 0.7771176099777222),
(u'nachos|NOUN', 0.7755396366119385)]

Reddit 网站上关于食品的一些评论非常有趣,比如 bacon 和 brocoll 之间的相似度非常高:

>>> model.similarity('bacon|NOUN', 'broccoli|NOUN')
0.83276615202851845

此外,模型的结果显示热狗和沙拉之间也非常相似:

>>> model.similarity('hot_dogs|NOUN', 'salad|NOUN')
0.76765100035460465
>>> model.similarity('hot_dogs|NOUN', 'entrails|NOUN')
0.28360725445449464

Using the demo

你可以通过搜索单词或短语来探索相关概念。如果你想要更精确的信息,你可以在查询语句中加入标签信息,比如query phrase|NOUN。如果你没有添加标签信息,那么该模型将会返回关联度最高的单词。标签信息主要由包含了上下文信息的统计模型预测所得。

如果你输入 serve,该模型将从 serve|VERBserve|NOUNserve|ADJ 等标签信息中搜寻相关单词。由于serve|VERB 是最常见的标签信息,该模型将返回这个结果。但是如果你输入 serve|NOUN,你将得到完全不一样的结果,因为 serve|NOUN 和网球之间的关系非常紧密,而动词形式则表示其他含义。

我们采用了基于频率的方法来区分大小写的情况。如果你的查询命令是小写单词且没有标签信息,我们将假设它是不区分大小写的,同时寻找最常见的标签和单词。如果你的查询命令中包含大写字母或者标签信息,我们将假设你的查询命令是区分大小写的。


原文链接:https://spacy.io/blog/sense2vec-with-spacy

原文作者:MATTHEW HONNIBAL

译者:Fibears

Sense2vec with spaCy and Gensim的更多相关文章

  1. 使用Python中的NLTK和spaCy删除停用词与文本标准化

    概述 了解如何在Python中删除停用词与文本标准化,这些是自然语言处理的基本技术 探索不同的方法来删除停用词,以及讨论文本标准化技术,如词干化(stemming)和词形还原(lemmatizatio ...

  2. 使用Gensim库对文本进行词袋、TF-IDF和n-gram方法向量化处理

    Gensim库简介 机器学习算法需要使用向量化后的数据进行预测,对于文本数据来说,因为算法执行的是关于矩形的数学运算,这意味着我们必须将字符串转换为向量.从数学的角度看,向量是具有大小和方向的几何对象 ...

  3. NLP︱词向量经验总结(功能作用、高维可视化、R语言实现、大规模语料、延伸拓展)

    R语言由于效率问题,实现自然语言处理的分析会受到一定的影响,如何提高效率以及提升词向量的精度是在当前软件环境下,比较需要解决的问题. 笔者认为还存在的问题有: 1.如何在R语言环境下,大规模语料提高运 ...

  4. python常用20库

    python核心库和统计 简述 1. Requests.最着名的http库由kenneth reitz编写.这是每个python开发人员必备的. 2. Scrapy.如果您参与webscraping, ...

  5. 20个最有用的Python数据科学库

    核心库与统计 1. NumPy(提交:17911,贡献者:641) 一般我们会将科学领域的库作为清单打头,NumPy 是该领域的主要软件库之一.它旨在处理大型的多维数组和矩阵,并提供了很多高级的数学函 ...

  6. NLTK vs SKLearn vs Gensim vs TextBlob vs spaCy

    Generally, NLTK is used primarily for general NLP tasks (tokenization, POS tagging, parsing, etc.) S ...

  7. doc2vec使用说明(二)gensim工具包 LabeledSentence

    欢迎交流,转载请注明出处. 本文介绍gensim工具包中,带标签(一个或者多个)的文档的doc2vec 的向量表示. 应用场景: 当每个文档不仅可以由文本信息表示,还有别的其他标签信息时,比如,在商品 ...

  8. Gensim LDA主题模型实验

    本文利用gensim进行LDA主题模型实验,第一部分是基于前文的wiki语料,第二部分是基于Sogou新闻语料. 1. 基于wiki语料的LDA实验 上一文得到了wiki纯文本已分词语料 wiki.z ...

  9. doc2vec使用说明(一)gensim工具包TaggedLineDocument

    gensim 是处理文本的很强大的工具包,基于python环境下: 1.gensim可以做什么? 它可以完成的任务,参加gensim 主页API中给出的介绍,链接如下: http://radimreh ...

随机推荐

  1. 设计模式之中介者模式(Mediator)摘录

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程.它们帮助一个系统独立于怎样创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...

  2. 安装odoo 9实录

    安装Ubuntu,省略 下载 odoo源码 使用 git 下载源码 mkdir /opt/openerp/server cd /opt/openerp/server git clone https:/ ...

  3. Libx264 编码错误 Input picture width(320) is greater than stride (0)

    Ffmpeg libx264编码出现 Input picture width(320) is greater than stride (0),问题出在视频格式不正确. libx264 编码要求输入源的 ...

  4. UDIMM、RDIMM、SODIMM以及LRDIMM的区别

    DIMM简介 DIMM(Dual Inline Memory Module,双列直插内存模块)与SIMM(single in-line memory module,单边接触内存模组)相当类似,不同的只 ...

  5. MEMS--微机电系统

    http://baike.baidu.com/view/95221.htm?fromtitle=MEMS&fromid=686299&type=search 微机电系统 编辑   您检 ...

  6. 【转】VMware 11.0 简体中文版|附永久密钥

    VMware 11.0 简体中文版|附永久密钥 昨天,VMware虚拟机11.0 简体中文版正式发布,值得注意的是新版抛弃了32位系统支持,安装包体积大幅减小, 新增Windows 10 技术预览版支 ...

  7. Spring Boot中使用RSocket

    1. 概述 RSocket应用层协议支持 Reactive Streams语义, 例如:用RSocket作为HTTP的一种替代方案.在本教程中, 我们将看到RSocket用在spring boot中, ...

  8. inception安装步骤---自己整理的安装步骤

    inception安装步骤---自己整理的安装步骤2015-09-18 15:51 6185人阅读 评论(1) 收藏 举报 分类: inception相关版权声明:本文为博主原创文章,未经博主允许不得 ...

  9. 根据ip识别地区

    <script src="http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=js"></scri ...

  10. 2016/07/07 wamp中apache2.4.9允许外部访问的配置 重点是版本 版本不同配置效果不同

    wamp安装包中安装好服务器之后只能使用127.0.0.1来访问了,如果我们要设置多个站点或其它像192.168.1.1这种就需要进行一下修改,具体步骤如下.   wamp-apache2.4.9允许 ...