Gensim庫的使用——Word2vec模型(二)訓練自己的模型與訓練引數

訓練自己的Word2vec模型

為了能夠訓練自己的Word2vec模型,你需要有一些資料,這裡用Lee Evaluation 語料庫來進行訓練。

這個語料庫足夠小(一共300條資料),而且可以完全載入進記憶體當中,但是!在實際的應用中你往往不能夠直接載入很大的語料庫進記憶體,所以首先來實現一個迭代器來逐列的讀取檔案:

1
2
3
4
5
6
7
8
9
from gensim.test.utils import datapath
from gensim import utils
class MyCorpus:
    def __iter__(self):
        corpus_path = datapath('lee_background.cor')
        for line in open(corpus_path):
            #對讀取的句子進行簡單的處理
            yield utils.simple_preprocess(line)
sentences = MyCorpus()

這裡的sentences就是得到了一個經過簡單處理的句子組成的串列,當然,你可以在for迴圈裡面進行自己的處理。

接下來可以進行訓練,那麼需要引入gensim.model來做

1
2
import gensim.models
model = gensim.models.Word2Vec(sentences=sentences)

恭喜你,現在已經擁有了一個訓練好的模型

不信?來我們來試一下,先看一下能不能得到「king」的向量

1
2
vec_king = model.wv['king']
print(vec_king)

你將得到一個向量:

[-0.02358022 -0.01961599 -0.00139271 -0.05510962 0.00294285 -0.00853481 -0.05957844 -0.04168227 -0.00846175 -0.02649316 0.01622383 0.01140004
0.00060386 -0.02601025 0.02205477 -0.02732388 0.01936879 0.047723 -0.06851483 -0.02320203 -0.00837262 -0.03829869 -0.00307029 -0.00264714
0.02370911 -0.05599895 -0.05200971 0.00733679 -0.00020037 0.02888935 0.02459002 0.01178179 -0.03889398 0.00082152 -0.01142673 -0.01249802
-0.0460892 -0.05402889 -0.01610627 0.05480611 0.00929705 0.05078919 -0.10389426 -0.078765 0.04261794 0.03915099 0.02897199 -0.04528579
-0.00610147 -0.06752459 -0.01624303 -0.00028024 0.0536734 -0.00837825 0.04030742 -0.05145243 0.03172397 0.05080702 0.0358872 -0.04948008
-0.01018649 -0.04389209 -0.01549766 0.00885961 -0.00399141 0.004901 0.02601369 0.04642579 -0.03019009 0.02526439 0.00062573 0.04625718
-0.04111696 -0.05535169 0.00018219 -0.03083905 0.05379871 -0.04979923-0.01030279 -0.05733781 0.01102394 -0.01693691 0.00895766 0.03222418-0.01516426 0.01628239 -0.03296118 0.01790296 -0.02671471 -0.08221665
0.01137402 -0.02240016 0.02553035 -0.05492717 -0.02355297 0.00911765-0.0913882 -0.00732729 0.02453462 -0.00781731]

不要誤會,這裡我為了方便顯示進行了分行,但是實際上這個向量是一個1行100列的向量,可以看出來,模型的預設向量長度是100,因為我們沒有特別指定維度。

接下來,我們再試試別的,我們來看一下詞典裡面都有什麼,就列印一下前十個好了:

1
2
3
4
for index, word in enumerate(model.wv.index2word):
    if index == 10:
        break
    print(f"word #{index}/{len(model.wv.index2word)} is {word}")

注意!這裡官方教學有錯誤,現在這麼寫才是對的,得到的結果如下:

word #0/1750 is the
word #1/1750 is to
word #2/1750 is of
word #3/1750 is in
word #4/1750 is and
word #5/1750 is he
word #6/1750 is is
word #7/1750 is for
word #8/1750 is on
word #9/1750 is said

儲存與載入模型

既然你相信你已經訓練好了模型,那麼你可以把它儲存起來,方便以後的時候直接使用,就不再需要花時間去在訓練模型了,因為訓練模型很花時間。

那麼,怎麼去儲存模型呢?

官方教學里是這樣做的,這裡用到了tempfile庫,這個庫是用來生成臨時檔案和臨時目錄的,你可以列印一下看看路徑:

1
2
3
4
5
import tempfile
with tempfile.NamedTemporaryFile(prefix='gensim-model-',delete=False) as tmp:
    temporary_filepath = tmp.name
    print(temporary_filepath)
    model.save(temporary_filepath)

C:UsersADMINI~1AppDataLocalTempgensim-model-wohv4_tq

這樣就可以把模型儲存到相應的目錄下了,這裡我也不是很能理解為什麼要用tempfile來做,但是我覺得在平時的使用中,只需要在save的引數裡面傳入檔案的路徑就可以儲存,例如說:

1
model.save('./myModel')

可以看到,在當前目錄資料夾下面就有了這樣一個檔案:

那麼如何去載入這個模型?再來舉個範例:

1
new_model = gensim.models.Word2Vec.load('./myModel')

此外,還可以使用原始的C工具的文字以及二進位制格式來載入模型:

1
2
3
model = gensim.models.KeyedVectors.load_word2vec_format('/tmp/vectors.txt', binary=False)
# using gzipped/bz2 input works too, no need to unzip
model = gensim.models.KeyedVectors.load_word2vec_format('/tmp/vectors.bin.gz', binary=True)

訓練引數

接下來介紹一些訓練模型的引數

min_count(default = 5)

min_count這個引數是用來修建內部的字典的,是不是不好理解,舉個範例來說,在實際的應用中,一個大型的語料庫裡面存在只出現一兩次的單詞,這些單詞可能是沒有意義甚至是拼寫錯誤的單詞,對於這種單詞最好忽略,那麼你可以透過設定模型的min_count引數來指定字典中存在的詞至少要在語料庫裡面出現多少次:

1
model = gensim.models.Word2Vec(sentences, min_count=10)

vector_size(default = 100)

vector_size這個引數是用來指定模型將單詞對映到向量的維數,還記得我們之前的範例么,它的預設值是100,更大的尺寸需要有更多的訓練資料的支援,一般可以從幾十到幾百不等,在論文裡面往往都是設定為300

1
model = gensim.models.Word2Vec(sentences, vector_size=200)

workers(default = 3)

workers是模型用來進行訓練並行化的一個引數,來加快訓練的速度!

1
model = gensim.models.Word2Vec(sentences, workers=4)

注意!workers引數衹有在安裝了Cython以後才有用,如果沒有安裝的話,你只能使用一個核心!(似乎在Anaconda裡面已經有了?反正我這裡有)

儲存

在模型的核心中,word2vec模型的引數是以Numpy array的形式進行儲存的,每個矩陣都是辭彙表的大小(#vocabulary)乘以向量的大小(#vector_size),其中的元素是float型別的(單精度 4個位元組)

在RAM中儲存了3個這麼大的矩陣(似乎這個矩陣的數量正在減少),所以舉個範例來說,如果說有100000個不重複的單詞,並且要求向量的大小為200維,那麼佔用的儲存空間就是:

100,000*200*4*3 bytes = ~229MB

除了儲存模型的引數以外,還要有一些額外的記憶體來儲存辭彙表樹(通常只需要幾兆位元組)