1. 程式人生 > >基於Word2Vec的相似度計算(python)

基於Word2Vec的相似度計算(python)

前言

    此篇文章的基礎知識部分總結了一些別人的文章解釋,環境為Windows10下的python3.5版本,需要的包為gensim。程式碼很簡要,不足之處請說明。

一. 背景知識

1.1詞向量

詞向量(word2vec)是一個將單詞轉換成向量形式的工具。可以把對文字內容的處理簡化為向量空間中的向量運算,計算出向量空間上的相似度,來表示文字語義上的相似度。

在自然語言處理(NLP)相關任務中,要將自然語言交給機器學習中的演算法來處理,通常需要首先將語言數學化,因為機器不是人,機器只認數學符號。向量是人把自然界的東西抽象出來交給機器處理的東西,基本上可以說向量是人對機器輸入的主要方式了。

詞向量就是用來將語言中的詞進行數學化的一種方式,顧名思義,詞向量就是把一個詞表示成一個向量。NLP 中最直觀,也是到目前為止最常用的詞表示方法是 One-hot Representation,這種方法把每個詞表示為一個很長的向量。這個向量的維度是詞表大小,其中絕大多數元素為 0,只有一個維度的值為 1,這個維度就代表了當前的詞。 在word2vec中則採用分散式表徵,在向量維數比較大的情況下,每一個詞都可以用元素的分散式權重來表示,因此,向量的每一維都表示一個特徵向量,作用於所有的單詞,而不是簡單的元素和值之間的一一對映。

word2vec中包含了對兩種模型的訓練,C-BOW模型和Gensim模型。在訓練每種模型的時候又分HS和NEG兩種方法。除了google自己的word2vec工具,也有其它各自不同的版本。其中比較好用的是Python Gensim主題模型包中的word2vec,但通過python版本只實現了skip-gram模型,並且只實現了通過分層softmax方法對其訓練,並沒有使用negative sampling。

1.2語言模型

語言模型包括文法語言模型和統計語言模型。一般我們指的是統計語言模型。統計語言模型: 統計語言模型把語言(詞的序列)看作一個隨機事件,並賦予相應的概率來描述其屬於某種語言集合的可能性。給定一個詞彙集合 V,對於一個由 V 中的詞構成的序列S = ⟨w1, · · · , wT ⟩ ∈ Vn,統計語言模型賦予這個序列一個概率P(S),來衡量S 符合自然語言的語法和語義規則的置信度。用一句簡單的話說,語言模型就是計算一個句子的概率大小。常見的統計語言模型有N元文法模型(N-gram Model),最常見的是unigram model、bigram model、trigram model等等。形式化講,統計語言模型的作用是為一個長度為 m 的字串確定一個概率分佈 P(w1; w2; :::; wm),表示其存在的可能性,其中 w1 到 wm 依次表示這段文字中的各個詞。本文所用到的語言模型為skip-gram,skip-gram模型的輸入是一個單詞wIwI,它的輸出是wIwI的上下文wO,1,...,wO,CwO,1,...,wO,C,上下文的視窗大小為CC。

1.3 Gensim模組

本文用python進行預料的訓練,其中用到模組Gensim,是一款開源的第三方Python工具包,用於從原始的非結構化的文字中,無監督地學習到文字隱層的主題向量表達。它支援包括TF-IDF,LSA,LDA,和word2vec在內的多種主題模型演算法,支援流式訓練,並提供了諸如相似度計算,資訊檢索等一些常用任務的API介面。

二. 訓練預料的預處理

練語料的預處理指的是將文件中原始的字元文字轉換成Gensim模型所能理解的稀疏向量的過程。Gensim的word2vec的輸入是句子的序列. 每個句子是一個單詞列表。

通常,我們要處理的原生語料是一堆文件的集合,每一篇文件又是一些原生字元的集合。在交給Gensim的模型訓練之前,我們需要將這些原生字元解析成Gensim能處理的稀疏向量的格式。由於語言和應用的多樣性,Gensim沒有對預處理的介面做出任何強制性的限定。通常,我們需要先對原始的文字進行分詞、去除停用詞等操作,得到每一篇文件的特徵列表。

本文的語料來源為wiki百科,共2M大小,選用Hanlp漢語分詞系統進行文件的分詞,

原始資料分詞後,並去除詞性標註以及停用詞。

得到的使用資料結果如下圖:

  

Hanlp分詞的主要程式碼如下圖:


三. 模型訓練

3.1 程式碼以及引數設定

模型訓練用到了pythpn中的Gensim模組,Gensim只要求輸入按順序提供句子, 並不將這些句子儲存在記憶體, 然後Gensim可以載入一個句子, 處理該句子, 然後載入下一個句子.

 Word2vec有很多可以影響訓練速度和質量的引數:

(1) sg=1是skip-gram演算法,對低頻詞敏感,預設sg=0為CBOW演算法,所以此處設定為1。

(2) min_count是對詞進行過濾,頻率小於min-count的單詞則會被忽視,預設值為5。

(3) size是輸出詞向量的維數,即神經網路的隱藏層的單元數。值太小會導致詞對映因為衝突而影響結果,值太大則會耗記憶體並使演算法計算變慢,大的size需要更多的訓練資料, 但是效果會更好,在本文中設定的size值為300維度。

(4) window是句子中當前詞與目標詞之間的最大距離,即為視窗。本文設定視窗移動的大小為5。

(5) negative和sample可根據訓練結果進行微調,sample表示更高頻率的詞被隨機下采樣到所設定的閾值,預設值為1e-3。

(6) hs=1表示層級softmax將會被使用,預設hs=0且negative不為0,則負取樣將會被選擇使用。

(7) 最後一個主要的引數控制訓練的並行:worker引數只有在安裝了Cython後才有效,由於本文沒有安裝Cython的, 使用的單核。

通過檢視程式執行的日誌記錄,可看到引數設定如下所示:

 

實現程式碼如下:
# -*- coding: utf-8 -*-
import warnings
warnings.filterwarnings(action='ignore', category=UserWarning, module='gensim')
from gensim.models import word2vec
import logging

# 主程式
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
sentences = word2vec.Text8Corpus(u"D:\wiki\語料.txt")  # 載入語料
n_dim=300
 # 訓練skip-gram模型; 
model = word2vec.Word2Vec(sentences, size=n_dim, min_count=5,sg=1) 
# 計算兩個詞的相似度/相關程度
y1 = model.similarity(u"陝西省", u"山西省")
print(y1)
print("--------")
# 尋找對應關係
print(u"計算機-智慧,速度-")
y3 = model.most_similar([u'智慧', u'速度'], [u'計算機'], topn=3)
for item in y3:
    print(item[0], item[1])

3.2儲存和載入模型

儲存、載入模型可以在載入模型之後繼續使用句子來進一步訓練模型。儲存、載入模型的方法如下:

 

3.3實驗

本文進行了兩項實驗,一個是計算兩個詞的相似度/相關程度,另一個是通過給定的詞語序列關係去尋找其它詞語間的對應關係。本文計算了“陝西省”和“山西省”的相關程度,並且給定(計算機-智慧,速度-)這樣的一組關係得到了另一組關係,根據原有預料所訓練的模型,實驗結果如下如所示,可以看出“山西省”和“陝西省”的相似度很高約為0.954,同時通過給定的關係得出(水資源—降水,明顯)這樣一組關係

 

四. 總結

通過本次實驗,瞭解到神經網路在自然語言中的運用,通過將語言數學化,達到計算機可以識別的地步。向量是人把自然界的東西抽象出來交給機器處理的東西,基本上可以說向量是人對機器輸入的主要方式了。在本次試驗中用到word2vct工具來計算相似度和尋找對應關係組,Word2vec包換兩種語言模型一個是詞袋模型另一個是skip-gram模型,但是這裡用python進行程式設計,python版本下只有skip-gram模型,所以本文通過skip-gram來輸出詞語的權重,即300維的詞向量。在輸入資料之前,要對資料進行分詞處理並去除停用詞。模型訓練完畢後,儲存模型以便後續的使用或者完善。此次試驗,加深了我對詞向量的理解和運用,對於計算相似度的方法有了新的認識。