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