Sense2vec with spaCy and Gensim
如果你在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|VERB
, serve|NOUN
, serve|ADJ
等标签信息中搜寻相关单词。由于serve|VERB
是最常见的标签信息,该模型将返回这个结果。但是如果你输入 serve|NOUN
,你将得到完全不一样的结果,因为 serve|NOUN
和网球之间的关系非常紧密,而动词形式则表示其他含义。
我们采用了基于频率的方法来区分大小写的情况。如果你的查询命令是小写单词且没有标签信息,我们将假设它是不区分大小写的,同时寻找最常见的标签和单词。如果你的查询命令中包含大写字母或者标签信息,我们将假设你的查询命令是区分大小写的。
原文链接:https://spacy.io/blog/sense2vec-with-spacy
原文作者:MATTHEW HONNIBAL
译者:Fibears
Sense2vec with spaCy and Gensim的更多相关文章
- 使用Python中的NLTK和spaCy删除停用词与文本标准化
概述 了解如何在Python中删除停用词与文本标准化,这些是自然语言处理的基本技术 探索不同的方法来删除停用词,以及讨论文本标准化技术,如词干化(stemming)和词形还原(lemmatizatio ...
- 使用Gensim库对文本进行词袋、TF-IDF和n-gram方法向量化处理
Gensim库简介 机器学习算法需要使用向量化后的数据进行预测,对于文本数据来说,因为算法执行的是关于矩形的数学运算,这意味着我们必须将字符串转换为向量.从数学的角度看,向量是具有大小和方向的几何对象 ...
- NLP︱词向量经验总结(功能作用、高维可视化、R语言实现、大规模语料、延伸拓展)
R语言由于效率问题,实现自然语言处理的分析会受到一定的影响,如何提高效率以及提升词向量的精度是在当前软件环境下,比较需要解决的问题. 笔者认为还存在的问题有: 1.如何在R语言环境下,大规模语料提高运 ...
- python常用20库
python核心库和统计 简述 1. Requests.最着名的http库由kenneth reitz编写.这是每个python开发人员必备的. 2. Scrapy.如果您参与webscraping, ...
- 20个最有用的Python数据科学库
核心库与统计 1. NumPy(提交:17911,贡献者:641) 一般我们会将科学领域的库作为清单打头,NumPy 是该领域的主要软件库之一.它旨在处理大型的多维数组和矩阵,并提供了很多高级的数学函 ...
- NLTK vs SKLearn vs Gensim vs TextBlob vs spaCy
Generally, NLTK is used primarily for general NLP tasks (tokenization, POS tagging, parsing, etc.) S ...
- doc2vec使用说明(二)gensim工具包 LabeledSentence
欢迎交流,转载请注明出处. 本文介绍gensim工具包中,带标签(一个或者多个)的文档的doc2vec 的向量表示. 应用场景: 当每个文档不仅可以由文本信息表示,还有别的其他标签信息时,比如,在商品 ...
- Gensim LDA主题模型实验
本文利用gensim进行LDA主题模型实验,第一部分是基于前文的wiki语料,第二部分是基于Sogou新闻语料. 1. 基于wiki语料的LDA实验 上一文得到了wiki纯文本已分词语料 wiki.z ...
- doc2vec使用说明(一)gensim工具包TaggedLineDocument
gensim 是处理文本的很强大的工具包,基于python环境下: 1.gensim可以做什么? 它可以完成的任务,参加gensim 主页API中给出的介绍,链接如下: http://radimreh ...
随机推荐
- erlang 小程序:整数序列,搜索和为正的最长子序列
近期学习了一下erlang, 编了个小程序 算法例如以下: 把參数分为三个 当前位置的前子序列(Save)(比方 -5, 1,2,-1, _, ... ) 当前位置为_时, 前子序列就是 1,2,-1 ...
- 修改 百度地图 infowindow 默认样式
1.百度 api 没有 提供可以修改 infowindow 默认样式的 方法. 如需修改,需要 自定义 替换 默认样式. demo.html <!DOCTYPE html> <htm ...
- __del__删除方法
class dog: def __del__(self): print("删除机制被调用了...") dog1 = dog() del dog1 #在这里是先删除掉了,所以就去上面 ...
- 1.新手上路:Windows下,配置Qt环境
个人体会: 我最初只是想看看C++除了"黑窗口"之外,怎么才能做一些"更好看的东西".之后在网上看到有人推荐Qt,就看了一下官网(https://www.qt. ...
- Rest Api(转载)
来源:http://www.cnblogs.com/springyangwc/archive/2012/01/18/2325784.html 概述 REST 从资源的角度来观察整个网络,分布在各处的资 ...
- (Vue)vue模板语法
Vue.js 使用了基于 HTML 的模版语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据.Vue.js 的核心是一个允许你采用简洁的模板语法来声明式的将数据渲染进 DOM 的系统. ...
- 模式匹配之sift--- sift图像特征提取与匹配算法代码
sift,The Scale Invariant Feature Transform ,尺度不变特征变换,是检测图像中具有唯一性.对图像平移.旋转.缩放.甚至仿射变换(如从不同角度拍摄图片)保持不变性 ...
- cocos2d-x lua 中使用protobuf并对http进行处理
cocos2d-x lua 中使用protobuf并对http进行处理 本文介绍 cocos2d-x lua 中使用http 和 基于cocos2d-x 对lua http的封装(部分ok) 本博客链 ...
- Collection of Boot Sector Formats for ISO 9660 Images
http://bazaar.launchpad.net/~libburnia-team/libisofs/scdbackup/view/head:/doc/boot_sectors.txt Colle ...
- cocos2d-js 运行动画
1.添加动画缓存 //添加动画缓存 cc.spriteFrameCache.addSpriteFrames(res.bug_plist); this.spriteSheet = new cc.Spri ...