使用gensim训练Doc2Vec时迭代打乱句子报错:AttributeError
解决Doc2Vec训练中的AttributeError问题
嘿,我来帮你搞定这个报错!先拆解一下错误根源:
AttributeError: 'TaggedLineSentence' object has no attribute 'sentences'
问题很清晰:你调用sentences_perm()的时候,self.sentences这个属性还没被初始化。看你的TaggedLineSentence类代码,self.sentences只有在调用to_array()方法时才会被创建,但你的训练代码里从来没调用过to_array(),直接就用了sentences_perm(),自然就找不到这个属性了。
下面给你两种修复方案,按需选择:
方案1:提前初始化self.sentences(简单直接)
在训练代码里,创建sentences对象后,先调用一次to_array(),把所有句子加载到内存中初始化属性:
def train(): doc_files = [f for f in os.listdir('./data/') if f.endswith('.csv')] sources = {} for doc in doc_files: doc2 = os.path.join('./data',doc) sources[doc2] = doc.replace('.csv','') sentences = TaggedLineSentence(sources) sentences.to_array() # 关键:提前初始化self.sentences属性 model = gensim.models.Doc2Vec(size=300, min_count=2, alpha=0.025, min_alpha=0.025) model.build_vocab(sentences) # 后续训练代码保持不变...
这种方法操作简单,但如果你的数据集很大,把所有句子都加载到内存可能会带来不小的资源压力。
方案2:修改sentences_perm方法(更高效,推荐)
直接让sentences_perm()从类的迭代器生成句子列表,不需要依赖self.sentences属性,既省内存又避免了属性未初始化的问题:
class TaggedLineSentence(object): # 其他方法保持不变,仅修改sentences_perm def sentences_perm(self): # 直接通过类的__iter__方法生成所有句子的列表 all_sentences = list(self) random.shuffle(all_sentences) return all_sentences
修改后,你不需要再调用to_array(),训练代码可以保持原样,大数据集下的内存压力也会小很多。
额外提醒:影响模型效果的小坑
你的clean_line()方法里用了list(set(dlist).difference(stopword_set)),这会彻底打乱词的顺序——而Word2Vec/Doc2Vec模型是依赖词序来学习语义关系的,词序丢失会严重影响最终模型效果!建议改成列表推导式过滤停用词,保留原始词序:
def clean_line(line): new_str = unicode(line, errors='replace').lower() # encoding issues dlist = tokenizer.tokenize(new_str) # 保留词序,仅过滤停用词 dlist = [word for word in dlist if word not in stopword_set] new_line = ' '.join(dlist) return new_line
内容的提问来源于stack exchange,提问作者Santino
相关产品推荐
相关产品推荐

