NLP.TM | GloVe模型及其Python實現


在進行自然語言處理中,需要對文章的中的語義進行分析,於是迫切需要一些模型去描述詞匯的含義,很多人可能都知道word2vector算法,誠然,word2vector是一個非常優秀的算法,並且被廣泛運用,為人們熟知,然而,從結果的優劣性來看,其實word2vector並非唯一的優秀方案,斯坦福大學提出的GloVe就是其中之一。今天我來為大家介紹一下GloVe模型,但是重點,還是放在實現上。

原論文:http://www.eecs.wsu.edu/~sji/classes/DL16/CNN-text/glove.pdf

簡單地說一下原理

這里的原理我主要參考了兩篇博客,感謝兩位優秀的博主。

前者會比較通俗,后者則比較深刻。

共現關系

和word2vector不同,GloVe更傾向於進行分析前后語境之間的共現關系,通過共現關系抽象出詞向量。

所謂的共現,共同出現,其實就是看一個詞有沒有在另一個詞的附近出現,所謂的附近,其實就是一個移動窗口的概念,定義窗口的半徑(從中心詞到邊緣的距離)后,看看方圓多少范圍內出現詞的個數,就是共現,現在看看例子。

假設語料庫就只有下面一行:

i love you but you love him i am sad

設半徑為2,於是移動窗口的滑動就有下面的形式:

以窗口5為例,此處就可以認為,love分別和but, you, him, i共同出現了一次,通過這種方式去計數,就能知道任意兩個詞之間的共現關系(一般是可逆的),構成共現矩陣X,一般地,X是一個對稱矩陣。

詞向量的產生

首先,模型的損失函數長這樣的:

 
image

vi和vj是詞匯i和j的詞向量,bi和bj是常數項,f是特定的權重函數,N是詞匯表大小。

這個損失函數怎么來的,我覺得上面的第一個鏈接講的非常清楚,看的時候注意一個核心,就是考慮兩個詞匯的共現關系與詞向量之間的關系(映射)盡可能接近,於是就構造了上面的損失函數。

GloVe的Python實現

在pypi里面看到了很多GloVe的包,但是很多都有坑,我直接說一個我自己已經走通的包mittens。

下載方式還是比較簡單的, pip install mittens基本沒什么問題,想要去看看源碼的話,在這里:

https://github.com/roamanalytics/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終於寫完了,不知道大家覺得怎么樣,關於原理寫的人相對比較多,也理解的比我好我就不再解釋了,而代碼這塊,網上寫的不多,所以我寫得詳細一些,這也是我把結果寫出來的核心代碼,有什么問題我來回答,歡迎通過下面的聯系方式聯系我。



作者:機智的叉燒
鏈接:https://www.jianshu.com/p/d0cb367752e8
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權並注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM