glove中文詞向量_NLP.TM | GloVe模型的原理和實現
技術標籤:glove中文詞向量
在進行自然語言處理中,需要對文章的中的語義進行分析,於是迫切需要一些模型去描述詞彙的含義,很多人可能都知道word2vector演算法,誠然,word2vector是一個非常優秀的演算法,並且被廣泛運用,為人們熟知,然而,從結果的優劣性來看,其實word2vector並非唯一的優秀方案,斯坦福大學提出的GloVe就是其中之一。今天我來為大家介紹一下GloVe模型,但是重點,還是放在實現上。
原論文: http://www. eecs.wsu.edu/~sji/class es/DL16/CNN-text/glove.pdf
簡單地說一下原理
這裡的原理我主要參考了兩篇部落格,感謝兩位優秀的博主。
理解GloVe模型(+總結): https:// blog.csdn.net/u01466501 3/article/details/79642083
GloVe模型: https://www. cnblogs.com/Weirping/p/ 7999979.html
前者會比較通俗,後者則比較深刻。
共現關係
和word2vector不同,GloVe更傾向於進行分析前後語境之間的共現關係,通過共現關係抽象出詞向量。
所謂的共現,共同出現,其實就是看一個詞有沒有在另一個詞的附近出現,所謂的附近,其實就是一個移動視窗的概念,定義視窗的半徑(從中心詞到邊緣的距離)後,看看方圓多少範圍內出現詞的個數,就是共現,現在看看例子。
假設語料庫就只有下面一行:
i love you but you love him i am sad
設半徑為2,於是移動視窗的滑動就有下面的形式:
以視窗5為例,此處就可以認為,love分別和but, you, him, i共同出現了一次,通過這種方式去計數,就能知道任意兩個詞之間的共現關係(一般是可逆的),構成共現矩陣X,一般地,X是一個對稱矩陣。
詞向量的產生
首先,模型的損失函式長這樣的:
vi和vj是詞彙i和j的詞向量,bi和bj是常數項,f是特定的權重函式,N是詞彙表大小。
這個損失函式怎麼來的,我覺得上面的第一個連結講的非常清楚,看的時候注意一個核心,就是考慮兩個詞彙的共現關係與詞向量之間的關係(對映)儘可能接近,於是就構造了上面的損失函式。
GloVe的Python實現
在pypi裡面看到了很多GloVe的包,但是很多都有坑,我直接說一個我自己已經走通的包mittens。
下載方式還是比較簡單的, pip install mittens
基本沒什麼問題,想要去看看原始碼的話,在這裡:
https:// github.com/roamanalytic s/mittens
一般而言GloVe按照計算共現矩陣和GloVe訓練兩大模組,而mittens裡面其實只提供了後者,前者還是需要自己寫,這是我寫的部分內容,給大家詳細講講(複雜度啥的基本沒做什麼優化,歡迎提出一些意見)。
共現矩陣的計算
將之前事先說明一下,現在讀進來的資料,即程式碼中的“data”變數,每行不是對應的單詞或者短語,而是已經對應在詞典中的該短語的index(自己構建詞典,一般設定為0-(N-1),N為詞典中詞語的個數),尤其在後面的cooccurrence的統計,即如果句子陣列中的第i個詞語是詞典中的第j個詞,則句子向量中第i個位置就是數字j,這種方式對cooccurrence的統計非常方便。
# 構建空的詞表
coWindow = 3 # 共現視窗大小(半徑)
tableSize = 1000 # 共現矩陣維度
cooccurrence = np.zeros((tableSize, tableSize), "int64" )
首先是資料初始化,這裡不詳細說資料載入了,但是共現矩陣當然是需要初始化的(np是numpy別忘了)。
# 開始統計
flag = 0
for item in data:
itemInt = [int(x) for x in item]
for core in range(1, len(item)):
if core <= coWindow + 1:
# 左視窗不足
window = itemInt[1:core + coWindow + 1]
coreIndex = core - 1
cooccurrence = countCOOC(cooccurrence, window, coreIndex)
elif core >= len(item) - 1 - coWindow:
# 右視窗不足
window = itemInt[core - coWindow:(len(item))]
coreIndex = coWindow
cooccurrence = countCOOC(cooccurrence, window, coreIndex)
else:
# 左右均沒有問題
window = itemInt[core - coWindow:core + coWindow + 1]
coreIndex = coWindow
cooccurrence = countCOOC(cooccurrence, window, coreIndex)
flag = flag + 1
if flag % 1000 == 0:
endTime = datetime.datetime.now()
print("已經計算了%s條資料,用時%s" % (flag, endTime - startTime))
這一塊裡面主要是為了設定移動視窗來進行挪動識別,具體統計移動視窗內部的共現,是在countCOOC函式裡面做的。
def countCOOC(cooccurrence, window, coreIndex):
# cooccurrence:當前共現矩陣
# window:當前移動視窗陣列
# coreIndex:當前移動視窗陣列中的視窗中心位置
for index in range(len(window)):
if index == coreIndex:
continue
else:
cooccurrence[window[coreIndex]][window[index]] = cooccurrence[window[coreIndex]][window[index]] + 1
return cooccurrence
countCOOC用來當前移動視窗的共現,一個一個計數即可。
GloVe的訓練
# 包的引入
from mittens import GloVe
# 初始化模型
vecLength=100 # 矩陣長度
max_iter=100000 # 最大迭代次數
display_progress=1000 # 每次展示
glove_model = GloVe(n=vecLength, max_iter=max_iter, display_progress=display_progress)
# 模型訓練與結果輸出
embeddings = glove_model.fit(coocMatric)
引入包之後,配置相應的引數,然後可以開始訓練,訓練完的返回值embeddings就是得到的詞向量詞典,通過詞向量詞典,就能夠將每篇文字的每一個單詞轉化為詞向量,從而進行進一步分析。
小結
GloVe終於寫完了,不知道大家覺得怎麼樣,關於原理寫的人相對比較多,也理解的比我好我就不再解釋了,而程式碼這塊,網上寫的不多,所以我寫得詳細一些,這也是我把結果寫出來的核心程式碼,有什麼問題我來回答,歡迎通過下面的聯絡方式聯絡我。