nlp - Gensim 的 word2vec 从 epoch 1 开始有 0 的损失?
问题描述
我正在使用 Gensim 库的 Word2vec 模块来训练词嵌入,数据集是 400k 句子和 100k 唯一词(不是英语)
我正在使用此代码来监控和计算损失:
class MonitorCallback(CallbackAny2Vec):
def __init__(self, test_words):
self._test_words = test_words
def on_epoch_end(self, model):
print("Model loss:", model.get_latest_training_loss()) # print loss
for word in self._test_words: # show wv logic changes
print(model.wv.most_similar(word))
monitor = MonitorCallback(["MyWord"]) # monitor with demo words
w2v_model = gensim.models.word2vec.Word2Vec(size=W2V_SIZE, window=W2V_WINDOW, min_count=W2V_MIN_COUNT , callbacks=[monitor])
w2v_model.build_vocab(tokenized_corpus)
words = w2v_model.wv.vocab.keys()
vocab_size = len(words)
print("Vocab size", vocab_size)
print("[*] Training...")
# Train Word Embeddings
w2v_model.train(tokenized_corpus, total_examples=len(tokenized_corpus), epochs=W2V_EPOCH)
问题是从 epoch 1 开始,loss 为 0,并且被监控词的向量根本没有改变!
[*] Training...
Model loss: 0.0
Model loss: 0.0
Model loss: 0.0
Model loss: 0.0
那么这里有什么问题呢?这是正常的吗?标记化语料库是一个列表列表,类似于 tokenized_corpus[0] = [ "word1" , "word2" , ...]
我用谷歌搜索,似乎一些旧版本的 gensim 在计算损失函数时有问题,但它们是差不多一年前的,现在应该修复了吗?
我也尝试了这个问题的答案中提供的代码,但损失仍然是 0 :
EDIT1:添加compute_loss=True后,损失出现了,但它越来越高,最相似的词和它们的相似度根本没有改变:
Model loss: 2187903.5
Model loss: 3245492.0
Model loss: 4103624.5
Model loss: 4798541.0
Model loss: 5413940.0
Model loss: 5993822.5
Model loss: 6532631.0
Model loss: 7048384.5
Model loss: 7547147.0
解决方案
您的代码的最大问题是您没有使用Word2Vec
切换丢失跟踪所需的初始化参数:compute_loss=True
(参见https://radimrehurek.com/gensim/models/word2vec.html#gensim.models.word2vec.Word2Vec的“参数”部分)
即使有了这个修复,损失报告仍然有很多错误(截至gensim-3.8.3
2020 年 8 月撰写本文时):
- 这不是人们可能期望的每个时期的总数或每个示例的平均值。(因此,如果您需要,作为一种解决方法,您的回调应该记住最后一个值并计算增量,或者将内部计数器重置为
0.0
,每个时期的结束。) - 它在较大的训练运行中肯定会失去精度,最终变得无用。(这对您来说可能不是问题。)
- 由于多线程值覆盖,它可能会丢失一些计数。(这对您来说可能不是一个实际问题,具体取决于您咨询损失值的原因。)
推荐阅读
- javascript - 反应原生 Firestore:使用无效数据调用的函数 addDoc()
- pandas - 用索引名称标记 pandas 标头
- oracle - Oracle:如何将 char(16) 转换为日期
- android - Android QtService 不会在单独的进程上调用像 onCreate 这样的覆盖方法
- javascript - 将提取的值数组处理为 JMeter 中的格式化字符串值
- linux - 在 lua 中检查每月的日期
- makefile - 如何使用 $(info) 打印前导空格
- python - 填充 xarray 数据数组中缺少的索引位置
- python - 如何检查用户是否登录?烧瓶
- javascript - 通过使用JS单击按钮来显示div