gensim生成词向量并获取词向量矩阵

word2vec是目前比较通用的训练词向量的工具,使用Gensim模块,可以使词向量的训练变的简单,但是调用gensim.models的word2vec模块使用skip-gram或CBOW完成词向量训练之后,如何获取词向量中的词汇表以及对应的词向量矩阵呢。本文以一个小例子进行演示。

1. 导入相关包

主要用到了jieba和gensim包,可以使用命令行pip3 install gensim或下载gensim包的方式,具体不述。

import jieba
from gensim.models import Word2Vec

1. 加载语料并清洗

为了方便演示,本文直接定义了一个语料,并使用jieba进行分词操作。

#  停用词
stopword_list = []
with open('./stopwords.txt', 'r+', encoding='utf8') as f:
    for word in f.readlines():
        if len(word)>0 and word != '\n\t':
            stopword_list.append(word)
            
# 语料
content = [
"长江是中国第一大河,干流全长6397公里(以沱沱河为源),一般称6300公里。流域总面积一百八十余万平方公里,年平均入海水量约九千六百余亿立方米。以干流长度和入海水量论,长江均居世界第三位。",
"黄河,中国古代也称河,发源于中华人民共和国青海省巴颜喀拉山脉,流经青海、四川、甘肃、宁夏、内蒙古、陕西、山西、河南、山东9个省区,最后于山东省东营垦利县注入渤海。干流河道全长5464千米,仅次于长江,为中国第二长河。黄河还是世界第五长河。",
"黄河,是中华民族的母亲河。作为中华文明的发祥地,维系炎黄子孙的血脉.是中华民族民族精神与民族情感的象征。",
"黄河被称为中华文明的母亲河。公元前2000多年华夏族在黄河领域的中原地区形成、繁衍。",
"在兰州的“黄河第一桥”内蒙古托克托县河口镇以上的黄河河段为黄河上游。",
"黄河上游根据河道特性的不同,又可分为河源段、峡谷段和冲积平原三部分。 ",
"黄河,是中华民族的母亲河。"
]

# 分词
seg = [jieba.lcut(text) for text in content]

# 清洗
content_clean = []
for t in seg:
    text_clean = []
    for i in t:
        if len(i)>1 and i != '\t\n': 
            if not i.isdigit():
                if i.strip() not in stopword_list:
                    text_clean.append(i.strip())
    content_clean.append(text_clean)

最后的content_clean为一个list,具体为:
批注 2020-05-13 155509.png

3. 使用gensim训练词向量

## 用gensim训练词向量模型

model = Word2Vec(content_clean, sg=1, size=100, window=5, min_count=2, negative=1, 
                 sample=0.001, workers=4)
'''
sg=1 是 skip-gram 算法,对低频词敏感;默认 sg=0 为 CBOW 算法。
size 是输出词向量的维数,值太小会导致词映射因为冲突而影响结果,值太大则会耗内存并使算法计算变慢,一般值取为100到200之间。
window 是句子中当前词与目标词之间的最大距离,3表示在目标词前看3-b 个词,后面看 b 个词(b 在0-3之间随机)。
min_count 是对词进行过滤,频率小于 min-count 的单词则会被忽视,默认值为5。
negative 和 sample 可根据训练结果进行微调,sample 表示更高频率的词被随机下采样到所设置的阈值,默认值为 1e-3。
hs=1 表示层级 softmax 将会被使用,默认 hs=0 且 negative 不为0,则负采样将会被选择使用。
'''


# 训练后的模型model可以保存,备用
model.save('./word2vec')   #保存
model = Word2Vec.load('word2vec')   #加载model

代码中model是一个训练好的词向量模型,里面包含许多内容,可以获取词汇表和对应的词向量。

## 获取词汇
words = model.wv.index2word
print(words)                 # 长度18

# ['黄河', '长江', '中国', '干流', '中华民族', '母亲河', '第一', '全长',
#    '公里', '入海', '水量', '世界', '内蒙古', '河道', '长河', '中华文明', '民族', '上游']


## 获取对应词向量
vectors = model.wv.vectors
print(vectors)    # 18*100   100为设置的size,即词向量维度

#[[ 1.2898202e-03 -3.4580764e-03  3.4779524e-03 ... -3.6768757e-03
#   2.6582647e-03 -3.7408734e-03]
# [ 2.9404070e-03  3.9611240e-03 -2.1796243e-03 ...  2.3843886e-03
#  -4.3357350e-03 -3.3540600e-03]
# [ 4.9255025e-03  1.4151304e-03 -8.7503344e-04 ...  4.2551141e-03
#  -2.9053804e-03  3.6766860e-03]
# ...
# [ 1.9452259e-03  4.8658932e-03 -2.3852135e-03 ... -2.7566685e-03
#   4.9943980e-03 -3.9313175e-03]
# [ 5.2972522e-04  4.8273476e-03 -3.0694890e-03 ...  4.2261067e-03
#   9.7657423e-05  4.4411011e-03]
# [-2.2659900e-03  1.5058877e-03 -4.7887382e-03 ...  2.4552434e-03
#   4.4189487e-04  5.9008709e-04]]


## 根据指定词获取该词的向量
vec = model.wv['长江']
print(vec)

#[ 2.9404070e-03  3.9611240e-03 -2.1796243e-03  3.5846021e-03
# -8.5443829e-04 -1.5641276e-03 -1.6966875e-03 -4.6902820e-03
# -4.3645203e-03 -1.8363699e-03 -3.9727231e-03  4.7817207e-03
# -1.3380363e-03 -2.6813489e-03  4.1867769e-03  3.4822649e-03
# -3.9391480e-03 -2.3266519e-03  1.4906399e-03 -7.4510416e-04
# ...


## 判断词之间的相似度
print(model.similarity('黄河','黄河'))   #1.0
print(model.similarity('黄河','长江'))   #-0.08
print(model.similarity('黄河','中国'))   #0.14


## 预测与'黄河'和'母亲河'最相似,而与长江不接近的词
print(model.most_similar(positive=['黄河','母亲河'], negative=['长江']))

#[('长河', 0.10036612302064896), ('世界', 0.065335713326931), 
# ('民族', 0.05369586870074272), ('中华民族', 0.03456304967403412), 
# ('入海', 0.00084715336561203), ('公里', -0.007249757647514343), 
# ('第一', -0.0175853930413723), ('内蒙古', -0.0281079038977623), 
# ('干流', -0.02939787693321705), ('上游', -0.029546111822128296)]
#__main__:1: DeprecationWarning: Call to deprecated `most_similar` 
#(Method will be removed in 4.0.0, use self.wv.most_similar() instead).