Gensim Word2vec获取未登录词向量触发KeyError的解决方法
问题原因
原生Word2Vec模型只会生成训练语料中达到最低词频要求的词语的向量,本身不具备为词汇表外(OOV)词语生成向量的能力。直接通过model.wv[词]的方式访问不存在的词时,就会触发KeyError: Key 'xxx' not present报错。
解决方案
根据需求可以选择不同的处理方案,从避免程序崩溃到直接获取OOV词向量均有成熟实现:
方案1:基础容错(不需要OOV向量场景)
如果不需要为未登录词生成向量,仅需要避免程序因单个词语中断,可以通过存在性判断或异常捕获做兜底处理:
from gensim.models import KeyedVectors import numpy as np model = KeyedVectors.load('nice.model') token = "bla bla bla" # 写法1:先判断词是否在词汇表中 if token in model.wv: token_vector = model.wv[token] else: # 自定义兜底逻辑:比如返回空、返回和向量维度一致的全0向量 token_vector = np.zeros(model.wv.vector_size) # 写法2:直接捕获KeyError异常 try: token_vector = model.wv[token] except KeyError: token_vector = np.zeros(model.wv.vector_size)
注意:如果训练Word2Vec时没有手动加入<UNK>特殊标记并为其生成向量,直接访问model.wv['<UNK>']同样会触发KeyError。
方案2:直接获取未登录词向量
如果需要拿到OOV词语的可用向量,有两种落地成本极低的成熟方案:
- 替换为FastText模型
FastText是gensim原生支持的词向量模型,训练接口、使用方式和Word2Vec几乎完全一致,区别是它会额外学习字符级n-gram的向量表示。对于训练时没见过的词,模型可以通过拆分出的字符片段组合出合理的向量,取词时不会触发KeyError。from gensim.models import FastText # 训练代码和Word2Vec参数通用,仅替换类名即可 # model = FastText(sentences=your_train_corpus, vector_size=100, window=5, min_count=2) # model.save('fasttext.model') # 加载训练好的模型,直接取OOV词向量无报错 model = FastText.load('fasttext.model') token_vector = model.wv['bla bla bla'] - 为现有Word2Vec模型添加OOV兜底向量
如果不想重新训练模型,可以计算现有所有词向量的平均值作为通用未登录词向量,所有不存在的词统一返回该向量:import numpy as np from gensim.models import KeyedVectors model = KeyedVectors.load('nice.model') # 计算全量词向量的均值作为UNK向量 unk_vector = np.mean(model.wv.vectors, axis=0) # 将UNK向量加入模型词汇表 model.wv.add_vectors(['<UNK>'], [unk_vector]) def get_word_vector(token): return model.wv[token] if token in model.wv else model.wv['<UNK>'] # 调用示例 token_vector = get_word_vector('bla bla bla')
补充提示:如果OOV词多为拼写错误导致(比如报错信息里的hmed大概率是Ahmed的拼写遗漏),可以在取向量前增加拼写纠错预处理步骤,能大幅减少无意义的OOV情况。
内容的提问来源于stack exchange,提问作者Ahmed Zeini
相关产品推荐
相关产品推荐

