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 倍左右。