NLP 利器 Gensim 中 word2vec 模型的訓練損失計算,和對比基準的選擇
本文為系列文章之一,前面的幾篇請點擊鏈接:
NLP 利器 gensim 庫基本特性介紹和安裝方式
NLP 利器 Gensim 庫的使用之 Word2Vec 模型案例演示
NLP 利器 Gensim 來訓練自己的 word2vec 詞向量模型
NLP 利器 Gensim 來訓練 word2vec 詞向量模型的參數設置
NLP 利器 Gensim 中 word2vec 模型的記憶體需求,和模型評估方式
NLP 利器 Gensim 中 word2vec 模型的恢復訓練:載入存儲模型並繼續訓練
一、訓練損失計算
通過設置 compute_loss 可以設定是否計算 loss,然後訓練的時候就會自動計算 loss 了。
計算完成的 loss 被存儲在 running_training_loss 這一屬性中。
我們可以通過 get_latest_training_loss 方法獲取。
# instantiating and training the Word2Vec model
model_with_loss = gensim.models.Word2Vec(
sentences,
min_count=1,
compute_loss=True,
hs=0,
sg=1,
seed=42
)
# getting the training loss value
training_loss = model_with_loss.get_latest_training_loss()
print(training_loss)
運行結果:
1371947.25
參數說明:
- sg ({0**, 1}**, optional) – 訓練演算法: 1 是 skip-gram; 否則是 CBOW。
- hs ({0**, 1}**, optional) – 1:使用分級 softmax,0:使用負取樣。
- seed (int*,* optional) – 隨機數生成器的種子。
二、比較基準
我們可以運行一些比較基準,看訓練時候損失計算程式碼產生的影響。
用以下兩個數據集作為比較基準:
- Lee Background 語料
- Text8 語料(為了看不同語料大小的影響,會對前 1MB,10MB,50MB,以及整個語料數據進行評估)
import io
import os
import gensim.models.word2vec
import gensim.downloader as api
import smart_open
def head(path, size):
with smart_open.open(path) as fin:
return io.StringIO(fin.read(size))
def generate_input_data():
lee_path = datapath('lee_background.cor')
ls = gensim.models.word2vec.LineSentence(lee_path)
ls.name = '25kB'
yield ls
text8_path = api.load('text8').fn
labels = ('1MB', '10MB', '50MB', '100MB')
sizes = (1024 ** 2, 10 * 1024 ** 2, 50 * 1024 ** 2, 100 * 1024 ** 2)
for l, s in zip(labels, sizes):
ls = gensim.models.word2vec.LineSentence(head(text8_path, s))
ls.name = l
yield ls
input_data = list(generate_input_data())
我們可以對比一下訓練時間的差別,使用不同的輸入數據和訓練參數設置。
對於每種組合,我們重複測試幾次,以獲得測試持續時間的平均值和標準偏差。
import logging
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
# Temporarily reduce logging verbosity
logging.root.level = logging.ERROR
import time
import numpy as np
import pandas as pd
train_time_values = []
seed_val = 42
sg_values = [0, 1]
hs_values = [0, 1]
fast = True
if fast:
input_data_subset = input_data[:3]
else:
input_data_subset = input_data
for data in input_data_subset:
for sg_val in sg_values:
for hs_val in hs_values:
for loss_flag in [True, False]:
time_taken_list = []
for i in range(3):
start_time = time.time()
w2v_model = gensim.models.Word2Vec(
data,
compute_loss=loss_flag,
sg=sg_val,
hs=hs_val,
seed=seed_val,
)
time_taken_list.append(time.time() - start_time)
time_taken_list = np.array(time_taken_list)
time_mean = np.mean(time_taken_list)
time_std = np.std(time_taken_list)
model_result = {
'train_data': data.name,
'compute_loss': loss_flag,
'sg': sg_val,
'hs': hs_val,
'train_time_mean': time_mean,
'train_time_std': time_std,
}
print("Word2vec model #%i: %s" % (len(train_time_values), model_result))
train_time_values.append(model_result)
train_times_table = pd.DataFrame(train_time_values)
train_times_table = train_times_table.sort_values(
by=['train_data', 'sg', 'hs', 'compute_loss'],
ascending=[False, False, True, False],
)
print(train_times_table)
測試結果:
train_data compute_loss sg hs train_time_mean train_time_std
4 25kB True 1 0 0.454762 0.012580
5 25kB False 1 0 0.439228 0.008768
6 25kB True 1 1 0.951644 0.085889
7 25kB False 1 1 0.951292 0.039065
0 25kB True 0 0 0.240479 0.005060
1 25kB False 0 0 0.250178 0.005493
2 25kB True 0 1 0.405198 0.009490
3 25kB False 0 1 0.408087 0.038706
12 1MB True 1 0 1.655859 0.113092
13 1MB False 1 0 1.680051 0.189026
14 1MB True 1 1 3.492107 0.428911
15 1MB False 1 1 3.093424 0.147582
8 1MB True 0 0 0.619222 0.037100
9 1MB False 0 0 0.705076 0.028860
10 1MB True 0 1 1.168661 0.011428
11 1MB False 0 1 1.058264 0.020380
20 10MB True 1 0 24.787724 1.964204
21 10MB False 1 0 21.996642 0.341242
22 10MB True 1 1 43.136896 1.458909
23 10MB False 1 1 46.764473 3.284557
16 10MB True 0 0 8.531959 0.376124
17 10MB False 0 0 8.237493 0.313006
18 10MB True 0 1 16.261160 0.557908
19 10MB False 0 1 17.740904 1.768709
總結:
- 語料越大,訓練時間越長(顯然):10 倍語料,對應 13~15 倍訓練時間。
- 計算 loss:影響不大。
- 訓練演算法 sg:skip-gram(1)是 CBOW(0)訓練時間的 2.5 ~3 倍左右。
- hs:使用分級 softmax(1)是採用負取樣(0)訓練時間的 1.8~2 倍左右。