word2vec原理及gensim中word2vec的使用


概述

在NLP中,對於一個詞,我們用一個詞向量來表示,最常見的一個方式是one hot representation,這種詞向量的編碼方式就是用一個很長的向量來表示一個詞,向量的長度為詞典的大小N,向量的分量只有一個1,其他全為0,1的位置對應該詞在詞典中的索引。這種表示方法不需要繁瑣的計算,簡單易得,但是缺點也不少:

  • 我們的詞匯表一般都非常大,比如達到百萬級別,這樣每個詞都用百萬維的向量來表示,簡直是內存的災難。
  • 這樣表示數據,數據非常稀疏,稀疏數據的訓練效率比較低,我們通常需要更多地數據來訓練。
  • 維度很高,很容易造成維數災難。
  • 無法體現出詞之間的關系,比如“面條”和“方便面”顯然有非常緊密的關系,但轉化成向量[1,0,0]和[0,1,0]以后,就看不出兩者有什么關系了,因為這兩個向量相互正交。
  • 這樣的向量其實除了一個位置是1,其余的位置全部都是0,表達的效率不高。

另一個方式是分布式表示(Distributed Representation),基本思想是將每個詞表達成一個固定長度的、稠密、連續的實數短向量,此時向量長度可以自由選擇,與詞典規模無關。與之相對的one-hot encoding向量空間只有一個維度是1,其余都是0。分布式表示最大的優點是具備非常powerful的特征表達能力,比如 n 維向量每維 k 個值,可以表征 \(k^n\) 個概念。向量空間模型(Vector Space Models)可以將字詞轉化為連續值的向量表示,並且其中意思相近的詞將被映射到向量空間中相近的位置。向量空間模型在NLP中主要依賴的假設為Distributional Hypothesis,即在相同語境中出現的詞其語義也相近。向量空間模型可以分為兩類,一類是計數模型,比如LSA;另一類是預測模型(比如Neural Probabilisitc Language Models)。計數模型統計在語料庫中,相鄰出現的詞的頻率,再把這些計數統計結果轉為小而稠密的矩陣;而預測模型則根據一個詞周圍相鄰的詞推測出這個詞,以及它的向量空間。

我們今天要要介紹的word2vec和Bengio在2003年發表的論文A neural probabilistic language model中提出的模型很相似,可以看做是在此基礎上的改進,下圖是Bengio在論文中提出的網絡結構:
image
這篇文章提出的神經網絡語言模型(NNLM,Neural Probabilistic Language Model)采用的是文本分布式表示,即每個詞表示為稠密的實數向量。NNLM模型的目標是構建語言模型:

\[p(w_i|w_1,w_2,...,w_{t-1}) \approx f(w_i, w_{t-1}, ..., w_{t-n+1}) = g(w_i, C(w_{t-n+1}), ..., C(w_{t-1})) \]

詞的分布式表示即word embedding是訓練語言模型的一個附加產物,即圖中的Matrix C。

盡管Bengio 2003年便提出了NNLM,但是由於它的局限性,word embedding真正火起來是google Mikolov 2013年發表的兩篇word2vec的文章 Efficient Estimation of Word Representations in Vector SpaceDistributed Representations of Words and Phrases and their Compositionality,更重要的是發布了簡單好用的word2vec工具包。值得說明的一點是,word2vec是一個獲得word embeding的工具,該工具得到的訓練結果——word embedding,可以很好地度量詞與詞之間的相似性,挖掘詞之間的聯系。里面的模型只是很淺的神經網絡,算不得深度學習算法,除了word2vec之外,我們還有其他的獲得word embeding的方法,如bert等。

下面我們會詳細的介紹word2vec中的兩個主要語言模型:CBOW和Skip-Gram,以及Hierarchical Softmax和Negative Sampling這兩個針對以上兩種模型的具體的優化方法。這兩個方法很好的解決了計算有效性,事實上這兩個方法都沒有嚴格的理論證明,有些trick之處,非常的實用主義。然后我們利用gensim的python版來介紹word2vec的使用。

word2vec原理

CBOW模型和Skip-gram模型是神經概率語言模型的兩種變形形式,下面我們將會一一介紹。

CBOW模型

CBOW(Continuous Bag-of-Words)的意思就是用上下文來預測當前詞,如下圖所示:
image
在上圖中,通過詞\(w_t\)的前后詞\(w_{t-2}\)\(w_{t-1}\)\(w_{t+1}\)\(w_{t+2}\)來預測當前詞\(w_t\)。此處的窗口的大小window為2。

其中,在CBOW模型中包含三層,即輸入層,映射層和輸出層。輸入層是當前詞周圍每個詞對應的詞向量,在映射層將這些詞的詞向量相加求平均,在輸出層求出為當前詞的概率。
:
如何根據一個詞的one-hot編碼,得到它對應的詞向量,可以看下圖所示:
image
在word2vec實際的實現的網絡里,上式中左邊的式子是輸入詞的one-hot編碼和隱藏層參數矩陣的乘積,在做這個乘法時是不會進行矩陣的運算的,而是直接通過輸入值中1的位置索引來尋找隱藏層中的參數矩陣中對應的索引的行。word2vec訓練的目的就是得到這個隱藏層參數矩陣,這個矩陣也可以叫做embeding 矩陣,由於這一步很簡單,我們上面的講解里忽略掉這個隱藏層,輸入層已經是之后詞得到它所對應的詞向量了,當然這個輸入的詞向量也是要求解的參數,下面的Skip-gram模型里面也按照這個設定,不再詳述。

從數學上看,CBOW模型等價於一個詞袋模型的向量乘以一個embedding矩陣,從而得到一個連續的embedding向量。這也是CBOW模型名稱的由來。

Skip-gram模型

而Skip-gram(Continuous Skip-gram)模型則與CBOW模型正好相反,在Skip-gram模型中,是用當前詞來預測上下文,如下圖所示:
image
在上圖中,通過詞\(w_t\)來預測它的前后詞\(w_{t-2}\)\(w_{t-1}\)\(w_{t+1}\)\(w_{t+2}\)。此處的窗口的大小window為2。

這里輸入層是當前詞對應的詞向量,映射層什么也不做,在輸出層求出當前詞上下文窗口中詞的概率。

Skip-gram名稱來源於該模型在訓練時會對上下文環境里的word進行采樣,然后預測我們選到這個附近詞的概率。

gensim中word2vec的使用

首先我們先介紹一下gensim中的word2vec API,官方API介紹如下:

class gensim.models.word2vec.Word2Vec(sentences=None, 
corpus_file=None, vector_size=100, alpha=0.025, 
window=5, min_count=5, max_vocab_size=None, sample=0.001, 
seed=1, workers=3, min_alpha=0.0001, sg=0, hs=0, negative=5, 
ns_exponent=0.75, cbow_mean=1, hashfxn=<built-in function hash>, 
epochs=5, null_word=0, trim_rule=None, sorted_vocab=1, 
batch_words=10000, compute_loss=False, callbacks=(), 
comment=None, max_final_vocab=None)

gensim中,word2vec相關的API都在包gensim.models.word2vec中。和算法有關的參數都在類gensim.models.word2vec.Word2Vec中。算法需要注意的參數有:

  • sentences: 我們要分析的語料,可以是一個列表,或者從文件中遍歷讀出(通過word2vec提供的LineSentence類來讀文件,word2vec.LineSentence(filename))。
  • vector_size: 詞向量的維度,默認值是100。這個維度的取值一般與我們的語料的大小相關,如果是不大的語料,比如小於100M的文本語料,則使用默認值一般就可以了。如果是超大的語料,建議增大維度。
  • window:即詞向量上下文最大距離,window越大,則和某一詞較遠的詞也會產生上下文關系。默認值為5。在實際使用中,可以根據實際的需求來動態調整這個window的大小。如果是小語料則這個值可以設的更小。對於一般的語料這個值推薦在[5,10]之間。
  • sg: 即我們的word2vec兩個模型的選擇了。如果是0, 則是CBOW模型,是1,則是Skip-Gram模型,默認是0,即CBOW模型。
  • hs: 即我們的word2vec兩個解法的選擇了,如果是1, 則是Hierarchical Softmax,是0的話並且負采樣個數negative大於0, 則是Negative Sampling。默認是0Negative Sampling
  • negative:即使用Negative Sampling時負采樣的個數,默認是5。推薦在[3,10]之間。
  • cbow_mean: 僅用於CBOW在做投影的時候,為0,則算法中的\(x_w\)為上下文的詞向量之和,為1則為上下文的詞向量的平均值。在我們的原理篇中,是按照詞向量的平均值來描述的。個人比較喜歡用平均值來表示\(x_w\),默認值也是1,不推薦修改默認值。
  • min_count:需要計算詞向量的最小詞頻。這個值可以去掉一些很生僻的低頻詞,默認是5。如果是小語料,可以調低這個值。
  • iter: 隨機梯度下降法中迭代的最大次數,默認是5。對於大語料,可以增大這個值。
  • alpha: 在隨機梯度下降法中迭代的初始步長。算法原理篇中標記為η,默認是0.025
  • min_alpha: 由於算法支持在迭代的過程中逐漸減小步長,min_alpha給出了最小的迭代步長值。隨機梯度下降中每輪的迭代步長可以由iter,alpha, min_alpha一起得出。這部分由於不是word2vec算法的核心內容,因此在原理篇我們沒有提到。對於大語料,需要對alpha, min_alpha,iter一起調參,來選擇合適的三個值。

常用的導入中文訓練數據的方式,有以下幾種:
使用Python的內置列表,

# 導入gensim庫
from gensim.models import word2vec
# 第一種輸入方式:Python內置列表
sentences = [['第', '一', '個', '句子'], ['第', '二', '個', '句子']]
# 調用函數訓練模型
model = word2vec.Word2Vec(sentences)

sentences是一個列表的列表,它的每個元素是一個句子所構成的列表。
當數據集特別大的時候,使用上述第一種方法就需要消耗特別多的內存,gensim還支持使用迭代生成器的方式輸入,

class MySentences(object):
    def __init__(self, dirname):
        self.dirname = dirname
 
    def __iter__(self):
        for fname in os.listdir(self.dirname):
            for line in open(os.path.join(self.dirname, fname)):
                yield line.split()
 
sentences = MySentences('/some/directory') # 第二種輸入方式:占用內存少的迭代器
model = Word2Vec(sentences)

這個輸入方式會依次打開“/some/directory”文件夾中的每個數據文件,對於每個文件一行一行的讀取數據進模型,這樣就避免了一次性讀入而占用太多內存。注意這里的每個文件里的每一行都是經過分詞的一個句子,單詞之間用空格分隔。

對於一個語料文件,里面的每一行都是經過分詞的一個句子,單詞之間用空格分隔,那么我們還可以使用
sentences = word2vec.LineSentence('corpus.txt')的方式進行讀取,而sentences = word2vec.PathLineSentences(dir_name)則是針對dir_name文件夾下的所有的這樣的文件進行讀取。

from gensim.models import word2vec
#訓練
model = word2vec.Word2Vec(sentences, hs=1,min_count=1,window=3,size=100)
model.save('model')  # 保存模型
model = word2vec.Word2Vec.load('model')  # 加載模型
model.wv['man']# 得到詞的詞向量
#找出某一個詞向量最相近的詞集合
for val in model.wv.similar_by_word("酒店", topn=10):
    print(val[0], val[1])

image
#查看兩個詞的相似性
image

#找出不同類的詞
image

參考

word2vec前世今生
Word2Vec Tutorial - The Skip-Gram Model
word2vec原理(二) 基於Hierarchical Softmax的模型
用深度學習(CNN RNN Attention)解決大規模文本分類問題 - 綜述和實踐
word2vector的原理,結構,訓練過程
Word2vec 入門(skip-gram部分)
源碼解析——word2vec源碼解析


免責聲明!

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



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