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)
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).