3.2.2词向量(Word2Vec)技术
词袋法是以每个词汇为特征,向量化表示一个文本;并且提供了几种特征量化的技术,如CountVectorizer和TfidfVectorizer。词袋法可以视作对文本向量化的表示技术,通过这项技术可以对文本之间在内容的相似性进行一定程序的度量。但是对于如下两段文本,词袋法技术似乎对计算他们的相似度表现的无能为力。
The cat is walking in the bedroom.
A dog was running across the kitchen.
尽管从语义上讲,这两段文本所描述的场景极为相似;但是,从词袋法表示来看,这两段文本唯一相同的词汇是the,找不到任何语义层面的联系。
而我们进一步学习到通过自然语言处理包,可以借助更加复杂的自然语言处理技术对文本进行分析。这使得我们不仅能够对词汇的具体词性进行标注,甚至可以对句子进行解构。然而,即便我们能够使用NLTK中的词性标注技术对上述文本进行分析,找出对应词汇在词性方面的相似性,也无法针对具体词汇之间的含义是否相似进行度量。
因此,为了寻找词汇之间的相似度关系,我们视图也将词汇的表示向量化。
这样就可以通过计算表示词汇的向量之间的相似度,来度量词汇之间的含义是否相似。而为了学习到这样的词向量表示,Yoshua教授等人Google研究员Mikolow等人分别从神经网络模型的角度提出了自己的框架。
![](https://img.haomeiwen.com/i1289421/dbbc6be8ec4e1ebd.png)
以输入一句英文为例:The cat is walking in the bedroom。如果我们需要这句话中所有上下文为数量为4的连续词汇片段,那么就有 The cat is walking、cat is walking in、is walking in the 以及 walking in the bedroom 这样4个片段。从语言模型角度上来讲,每个连续词汇片段的最后一个单词是什么,都是受前面三个词汇制约。因此,这就形成了一个根据前面三个单词,预测最后一个单词的监督学习系统。
如果用神经网络框架来描述,上图就代表一个监督模型的神经网络,当上下文数量为n的时候,这里的模型就是用前n-1个词语,也就是w(t-1) … w(t-n+1),来预测第t个词语w(t)。在神经网络中,用于计算的都是这些词的向量表示,如C(w(t-1)) 就是词语 w(t-1) 的向量表示。
这里C(w(t-1))其实就是词向量,但不是最终的词向量,最终结果还需要多轮迭代计算。其实这些词向量就是神经网络里的参数,生成词向量的过程就是一个参数更新的过程。
注意:对于初学者来说这里有个坑,考虑一个问题:词向量不是我们最终得到的吗?那我们如何得到最初输入的每个词对应的词向量C(w(t-1))、C(w(t-2))、、、C(w(t-n+1))?以下是我查阅资料后自己的理解:
在上图中存在一个系数矩阵C(是一个NM的矩阵),其中N是词典的长度,M是词向量的维度。最底层的输入其实是词语的one-hot形式,one-hot也可以看成 1N的矩阵 ,与这个系数矩阵C(NM, M是word2vec词向量维数)相乘之后就可以得到1M的向量,这个向量就是这个词对应的词向量了。
从本质上来看,词语w转化为词向量C(w),就是根据词 w 的one-hot 形式,通过矩阵相乘,从系数矩阵C中取出一行。
还需注意的是,这个系数矩阵C,就是神经网络的参数,最初是随机的,随着训练的进行不断被更新。
用20类新闻文本进行词向量训练
from sklearn.datasets import fetch_20newsgroups
news=fetch_20newsgroups(subset='all')
X,y=news.data,news.target
from bs4 import BeautifulSoup
import nltk,re
#定义一个函数名为news_to_sentences讲每条新闻中的句子逐一剥离出来,并返回一个句子的列表
def news_to_sentences(news):
news_text=BeautifulSoup(news).get_text()
tokenizer=nltk.data.load('tokenizers/punkt/english.pickle')
raw_sentences=tokenizer.tokenize(news_text)
sentences=[]
for sent in raw_sentences:
sentences.append(re.sub('[^a-zA-Z]',' ',sent.lower().strip()).split())
return sentences
sentences=[]
![](https://img.haomeiwen.com/i1289421/af6cc08c97562f51.jpeg)
#将长篇新闻文本中的句子剥离出来,用于训练
for x in X:
sentences+=news_to_sentences(x)
from gensim.models import word2vec
#配置词向量的维度
num_features=300
#保证被考虑的词汇的频度
min_word_count=20
#设定并行化训练使用CPU计算核心的数量,多核可用
num_workers=2
#定义训练词向量的上下文窗口大小
context=5
downsampling=1e-3#1e-3第一个是数字1,不是字母l
from gensim.models import word2vec
#训练词向量模型
model=word2vec.Word2Vec(sentences,workers=num_workers,\
size=num_features,min_count=min_word_count,\
window=context,sample=downsampling)
#这个设定代表当前训练好的词向量为最终版,也可以加快模型的训练速度
model.init_sims(replace=True)
#利用训练好的模型,寻找训练文本中与morning最相关的10个词汇
model.most_similar('morning')
[('afternoon', 0.7969172596931458),
('weekend', 0.764119565486908),
('evening', 0.7500736117362976),
('saturday', 0.7279693484306335),
('night', 0.7039743661880493),
('friday', 0.6897615790367126),
('newspaper', 0.6688321828842163),
('summer', 0.6671631932258606),
('sunday', 0.6512582898139954),
('week', 0.6438664793968201)]
#利用训练好的模型,寻找训练文本中与email最相关的10个词汇
model.most_similar('email')
[('mail', 0.7358647584915161),
('contact', 0.6991280913352966),
('mailed', 0.6708669066429138),
('replies', 0.6512271165847778),
('address', 0.630152702331543),
('send', 0.6236768364906311),
('archie', 0.6234195828437805),
('listserv', 0.6213445067405701),
('request', 0.6204395890235901),
('sas', 0.6121519804000854)]
结果表明,在不使用语言学词典的前提下,词向量技术仍然可以借助上下文信息找到词汇之间的相似性。这一技术不仅大量专业人士的作业时间,而且也可以作为一个基础模型应用到更加复杂的自然语言处理任务中。
最后需要指出的是,词向量的训练结果很大程度上受所提供的文本影响。换言之,这些词向量绝不是固定的;您可以灵活运用这个模型,训练不同文本内部独有的词向量。