使用Gensim自定义词频训练Doc2Vec时,文档向量dv为空的问题
问题原因
使用build_vocab_from_freq()初始化词汇表时,该方法仅处理词频数据、构建词的词汇表,不会扫描语料中的文档标签,也不会初始化文档向量空间(model.dv)的标签映射关系。而build_vocab()会扫描整个语料,收集所有文档标签,建立标签到向量索引的映射,从而初始化model.dv。
另外,使用corpus_file(SentenceLine格式)训练时,默认每行文档的标签是字符串类型的行号(比如第0行的标签是'0',而非整数0),若用整数标签去取值也会触发“tag不存在”的错误。
解决方案
方案1:手动初始化文档标签映射
在调用build_vocab_from_freq()后,手动为model.dv添加已知的文档标签(0-999的字符串形式),建立标签与向量索引的映射:
import numpy as np # 在build_vocab_from_freq之后执行 # 初始化文档标签列表(字符串类型,对应SentenceLine默认生成的标签) doc_tags = [str(i) for i in range(1000)] # 设置dv的标签映射 model.dv.index_to_key = doc_tags model.dv.key_to_index = {tag: idx for idx, tag in enumerate(doc_tags)} # 初始化文档向量矩阵(大小为1000*300,与model.vector_size一致) model.dv.vectors = np.zeros((len(doc_tags), model.vector_size), dtype=np.float32)
之后再执行model.train(),训练过程中模型会自动将每个文档的向量更新到对应索引位置。
方案2:先扫描语料获取标签再初始化词汇表
如果不想手动指定标签,可以先通过_scan_vocab()扫描语料获取标签,再初始化词汇表:
from gensim.models.doc2vec import _scan_vocab # 先扫描语料,获取文档标签信息 doc_tag_counts, _ = _scan_vocab( corpus_file=train_data, model=model, corpus_count=1000, update=False ) # 初始化dv的标签映射 model.dv.index_to_key = list(doc_tag_counts.keys()) model.dv.key_to_index = {tag: idx for idx, tag in enumerate(model.dv.index_to_key)} model.dv.vectors = np.zeros((len(model.dv.index_to_key), model.vector_size), dtype=np.float32) # 再构建词汇表 model.build_vocab_from_freq(word_freq=tf_idf_vocab, keep_raw_vocab=False, corpus_count=1000, update=False)
这种方式更灵活,适用于标签不是连续数字的场景。
注意事项
- 取值时需使用字符串类型的标签,比如
model.dv['0']而非model.dv[0],与SentenceLine默认生成的标签类型保持一致; - 若需要使用整数标签,可在生成语料时自定义
TaggedDocument,将标签设为整数类型(比如每行文档的标签为[i],i为整数行号)。
内容的提问来源于stack exchange,提问作者LearnToGrow
相关产品推荐
相关产品推荐

