訓練自己的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
除了儲存模型的引數以外,還要有一些額外的記憶體來儲存辭彙表樹(通常只需要幾兆位元組)