【问题标题】:How build Doc2Vec model by useing an 'iterable' object如何使用“可迭代”对象构建 Doc2Vec 模型
【发布时间】:2017-02-24 01:52:43
【问题描述】:

由于我在this page 中提出的问题,我的代码内存不足。然后,我编写了第二个代码以获得可迭代的alldocs,而不是全内存alldocs。我根据this page的解释更改了我的代码。我不熟悉流概念,无法解决我遇到的错误。

此代码读取给定路径的所有文件夹的所有文件。每个文件的上下文由两行文件名及其上下文组成。例如:

clueweb09-en0010-07-00000

鸽子 gif 剪贴画鸽子剪贴画图片图像 hiox 免费鸟类印度 web 图标剪贴画添加偶然发现

clueweb09-en0010-07-00001

google 书签 yahoo 书签 php 脚本 java 脚本 jsp 脚本 授权脚本 html 教程 css 教程

第一个代码:

# coding: utf-8
 import string
 import nltk
 import nltk.tokenize 
 from nltk.corpus import stopwords
 import re
 import os, sys 

 import MySQLRepository

 from gensim import utils
 from gensim.models.doc2vec import Doc2Vec
 import gensim.models.doc2vec
 from gensim.models.doc2vec import LabeledSentence
 from boto.emr.emrobject import KeyValue


 def readAllFiles(path):
    dirs = os.listdir( path )
    for file in dirs:
        if os.path.isfile(path+"/"+file):
           prepareDoc2VecSetting(path+'/'+file)
       else:
           pf=path+"/"+file
           readAllFiles(pf)      

def prepareDoc2VecSetting (fname):
    mapDocName_Id=[]
    keyValues=set()
   with open(fname) as alldata:
        a= alldata.readlines()
        end=len(a)
        label=0
        tokens=[]
        for i in range(0,end):
            if a[i].startswith('clueweb09-en00'):
               mapDocName_Id.insert(label,a[i])
               label=label+1
               alldocs.append(LabeledSentence(tokens[:],[label]))
               keyValues |= set(tokens)
               tokens=[]
           else:
               tokens=tokens+a[i].split()  

   mydb.insertkeyValueData(keyValues) 

   mydb.insertDocId(mapDocName_Id)


   mydb=MySQLRepository.MySQLRepository()

  alldocs = [] 
  pth='/home/flr/Desktop/newInput/tokens'
  readAllFiles(ipth)

  model = Doc2Vec(alldocs, size = 300, window = 5, min_count = 2, workers = 4)
  model.save(pth+'/my_model.doc2vec')

第二个代码:(我没有考虑与DB​​相关的部分)

import gensim
import os


from gensim.models.doc2vec import Doc2Vec
import gensim.models.doc2vec
from gensim.models.doc2vec import LabeledSentence



class prepareAllDocs(object):

    def __init__(self, top_dir):
        self.top_dir = top_dir

    def __iter__(self):
    mapDocName_Id=[]
    label=1
    for root, dirs, files in os.walk(top_directory):
        for fname in files:
            print fname
            inputs=[]
            tokens=[]
            with open(os.path.join(root, fname)) as f:
                for i, line in enumerate(f):          
                    if line.startswith('clueweb09-en00'):
                        mapDocName_Id.append(line)
                        if tokens:
                            yield LabeledSentence(tokens[:],[label])
                            label+=1
                            tokens=[]
                    else:
                        tokens=tokens+line.split()
                yield LabeledSentence(tokens[:],[label])

pth='/home/flashkar/Desktop/newInput/tokens/'
allDocs = prepareAllDocs('/home/flashkar/Desktop/newInput/tokens/')
for doc in allDocs:
    model = Doc2Vec(allDocs, size = 300, window = 5, min_count = 2, workers = 4)
model.save(pth+'/my_model.doc2vec')

这是错误:

Traceback(最近一次调用最后一次):文件 “/home/flashkar/git/doc2vec_annoy/Doc2Vec_Annoy/KNN/testiterator.py”, 第 44 行,在 model = Doc2Vec(allDocs, size = 300, window = 5, min_count = 2, >workers = 4) 文件 “/home/flashkar/anaconda/lib/python2.7/site->packages/gensim/models/doc2vec.py”, 第 618 行,在 init 中 self.build_vocab(documents, trim_rule=trim_rule) 文件 >"/home/flashkar/anaconda/lib/python2.7/site->packages/gensim/models/word2vec.py", 第 523 行,在 build_vocab self.scan_vocab(sentences, progress_per=progress_per, >trim_rule=trim_rule) # 初始调查文件 “/home/flashkar/anaconda/lib/python2.7/site->packages/gensim/models/doc2vec.py”, 第 655 行,在 scan_vocab 中 对于document_no,枚举中的文档(文档):文件>“/home/flashkar/git/doc2vec_annoy/Doc2Vec_Annoy/KNN/testiterator.py”, 第 40 行,在 iter 中 yield LabeledSentence(tokens[:],tpl1) IndexError: list index out of range

【问题讨论】:

  • 您的“第二个代码”在正确的轨道上,但是:(1)您仍然将每个 line 附加到 mapDocName_Id - 因此将所有内容都放入一个内存列表中; (2) tokens 在你测试它的地方不可能是非空的,因为它只是在每次循环迭代之前设置为 [] - 所以你永远不会产生任何东西; (3) 您现在将一个元组传递给 LabeledSentence,而不是它期望的两个列表; (4) 你不需要自己循环alldocs,当它正常工作时,你只需将alldocs 传递给Doc2Vec 一次。

标签: python iterator gensim doc2vec


【解决方案1】:

您正在使用生成器函数,因为您不想存储所有文档,但您仍将所有文档存储在 alldocs 中。你可以yield LabeledSentence(tokens[:], tpl[1]]))

目前正在发生的事情是您正在附加到一个列表并返回该列表。这就是您收到 AttributeError 的原因。此外,在每次迭代中,您都附加到列表中,这意味着在每次迭代中,i,您将返回 i 和 i 之前的所有文档!

【讨论】:

  • 我更新了我的代码,但我得到了新的错误。另外,你能解释一下你答案的第二部分吗?我听不懂。
  • 我认为你应该首先尝试调试你的代码,然后当你真的遇到一个特定的问题时来解决这个问题。为了给您指明正确的方向,您应该在 prepareAllDocs 中将 iter_document 与 iter 合并以使事情变得更简单。您还应该在 Python 中检查 enumerate,这样您就不需要使用 readlines() 读取所有数据,也不必在 iter_document 中增加标签。
  • 我尝试调试,但我能找到问题所在。你的意思是我逐行阅读而不是 readlines() 为什么?
  • 我无法使用 enumerate 因为每个文件的标签与以下代码中的索引不一样for index, line in enumerate(fname):
  • 对,我错过了,但你仍然可以使用它,这样你就不必一直索引 a。
猜你喜欢
  • 2019-10-15
  • 2023-03-25
  • 1970-01-01
  • 1970-01-01
  • 2012-08-10
  • 2012-05-10
  • 2015-11-28
  • 2020-08-14
  • 1970-01-01
相关资源
最近更新 更多