我从官方GitHub仓库中获取了predict_output_word方法,该方法仅适用于使用skip-gram训练的word2vec模型,并尝试通过将所有输入词的索引向量相加并除以输入词索引的np_sum长度来预测中间词。然后,您考虑输出并采用softmax来获取预测词的概率,最后将所有这些概率相加以得到最可能的词。鉴于这种方法在较短句子上的效果非常差,是否有更好的方法来改进以获得更好的词?以下是来自GitHub的代码。
def predict_output_word(model, context_words_list, topn=10):
from numpy import exp, dtype, float32 as REAL, ndarray, empty, sum as np_sum
from gensim import utils, matutils
"""根据给定的上下文词作为输入,报告中心词的概率分布。"""
if not model.negative:
raise RuntimeError("我们目前仅为负采样方案实现了predict_output_word,所以您需要使用negative > 0运行word2vec才能使其工作。")
if not hasattr(model.wv, 'syn0') or not hasattr(model, 'syn1neg'):
raise RuntimeError("未找到预测输出词所需的参数。")
word_vocabs = [model.wv.vocab[w] for w in context_words_list if w in model.wv.vocab]
if not word_vocabs:
warnings.warn("所有输入的上下文词在当前模型中都超出词汇表范围。")
return None
word2_indices = [word.index for word in word_vocabs]
# 求所有索引的和
l1 = np_sum(model.wv.syn0[word2_indices], axis=0)
if word2_indices and model.cbow_mean:
# l1 = l1 / len(word2_indices)
l1 /= len(word2_indices)
prob_values = exp(dot(l1, model.syn1neg.T)) # 传播隐藏层到输出层并使用softmax获取概率
prob_values /= sum(prob_values)
top_indices = matutils.argsort(prob_values, topn=topn, reverse=True)
return [(model.wv.index2word[index1], prob_values[index1]) for index1 in top_indices] # 返回最可能的输出词及其概率
回答:
虽然word2vec算法通过尝试预测词来训练词向量,并且这些词向量可能对其他用途有用,但如果您的真正目标是词预测,那么它不太可能是理想的算法。
大多数word2vec实现甚至没有提供用于单个词预测的特定接口。在gensim中,predict_output_word()
是最近才添加的。它仅适用于某些模式。它在训练期间对window
的处理方式并不完全相同——没有有效的按距离加权。而且,它相当昂贵——基本上是检查模型对每个词的预测,然后报告前N名。(训练期间发生的“预测”是“稀疏的”且效率更高——仅运行足够的模型来推动它在单个示例上表现得更好。)
如果您的真正目标是词预测,您可能会从其他方法中获得更好的结果,包括计算一个大查找表,显示词在彼此附近或其他n-gram附近出现的频率。