天天看點

基于gensim實作word2vec模型(附案例實戰)

作者:勇敢的小江程式員

什麼是word2vec?

Word2Vec是google在2013年推出的一個NLP工具,它的特點是能夠将單詞轉化為向量來表示,這樣詞與詞之間就可以定量的去度量他們之間的關系,挖掘詞之間的聯系。用詞向量來表示詞并不是Word2Vec的首創,在很久之前就出現了。最早的詞向量采用One-Hot編碼,又稱為一位有效編碼,每個詞向量次元大小為整個詞彙表的大小,對于每個具體的詞彙表中的詞,将對應的位置置為1。比如我們有下面的5個詞組成的詞彙表:

基于gensim實作word2vec模型(附案例實戰)

采用One-Hot編碼方式來表示詞向量非常簡單,但缺點也是顯而易見的,一方面我們實際使用的詞彙表很大,經常是百萬級以上,這麼高維的資料處理起來會消耗大量的計算資源與時間。另一方面,One-Hot編碼中所有詞向量之間彼此正交,沒有展現詞與詞之間的相似關系。

Distributed representation可以解決One-Hot編碼存在的問題,它的思路是通過訓練,将原來One-Hot編碼的每個詞都映射到一個較短的詞向量上來,而這個較短的詞向量的次元可以由我們自己在訓練時根據任務需要來自己指定。

下圖是采用Distributed representation的一個例子,我們将詞彙表裡的詞用"Royalty","Masculinity", "Femininity"和"Age"4個次元來表示,King這個詞對應的詞向量可能是(0.99,0.99,0.05,0.7)。當然在實際情況中,我們并不能對詞向量的每個次元做一個很好的解釋。

基于gensim實作word2vec模型(附案例實戰)

Word2Vec的原理

Word2Vec 的訓練模型本質上是隻具有一個隐含層的神經元網絡(如下圖)。

它的輸入是采用One-Hot編碼的詞彙表向量,它的輸出也是One-Hot編碼的詞彙表向量。使用所有的樣本,訓練這個神經元網絡,等到收斂之後,從輸入層到隐含層的那些權重,便是每一個詞的采用Distributed Representation的詞向量。比如,上圖中單詞的Word embedding後的向量便是矩陣 Wv x N 的第i行的轉置。這樣我們就把原本維數為V的詞向量變成了維數為N的詞向量(N遠小于V),并且詞向量間保留了一定的相關關系。

gensim實作word2vec模型(實戰)

本次實戰案例選取的資料集是四大名著中的三國演義。

首先使用jieba進行中文分詞,

基于gensim實作word2vec模型(附案例實戰)

分詞之後使用gensim庫中的word2vec構模組化

基于gensim實作word2vec模型(附案例實戰)

從結果中我們看出,與孔明相關性最高的是玄德、雲長、孟獲,也符合小說中的角色關系。

接着我們将模型可視化,

import numpy as np

from sklearn.decomposition import PCA

# 将詞向量投影到二維空間

rawWordVec = []

word2ind = {}

for i, w in enumerate(model.wv.index_to_key):

rawWordVec.append(model.wv[w]) # 詞向量

word2ind[w] = i # {詞語:序号}

rawWordVec = np.array(rawWordVec)

X_reduced = PCA(n_components=2).fit_transform(rawWordVec) # PCA降2維

import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei'] #解決中文顯示

plt.rcParams['axes.unicode_minus'] = False #解決符号無法顯示

# 繪制星空圖

# 繪制所有單詞向量的二維空間投影

fig = plt.figure(figsize = (15, 10))

ax = fig.gca()

ax.set_facecolor('white')

ax.plot(X_reduced[:, 0], X_reduced[:, 1], '.', markersize = 1, alpha = 0.3, color = 'black')

# 繪制幾個特殊單詞的向量

words = ['孫權', '劉備', '曹操', '周瑜', '諸葛亮', '司馬懿','漢獻帝']

for w in words:

if w in word2ind:

ind = word2ind[w]

xy = X_reduced[ind]

plt.plot(xy[0], xy[1], '.', alpha =1, color = 'orange',markersize=10)

plt.text(xy[0], xy[1], w, alpha = 1, color = 'red')

基于gensim實作word2vec模型(附案例實戰)

最後,我們還可以做個類比關系實驗,

比如,孔明是玄德的軍師,那麼曹操的軍師是誰呢?

基于gensim實作word2vec模型(附案例實戰)
基于gensim實作word2vec模型(附案例實戰)

繼續閱讀