У моего кода заканчивается память из-за вопроса, который я задал в this page. Затем я написал второй код, чтобы иметь итеративный alldocs
, а не все-в-памяти alldocs
. Я изменил свой код на основе объяснения this page. Я не знаком с концепцией потока, и я не мог решить ошибку, которую я получил.Как построить модель Doc2Vec, используя объект «итерабельный»
Этот код прочитать все файлы всех папок данного path.The контекста каждого файла состоит из имени документа и его контекст в двух lines.For Например:
clueweb09-en0010-07-00000
dove gif clipart pigeon clip art picture image hiox free birds india web icons clipart add stumble upon
clueweb09-en0010-07-00001
google bookmarks yahoo bookmarks php script java script jsp script licensed scripts html tutorials css tutorials
Первый код:
# 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')
Второй код: (я не рассматривал детали, связанные с БД)
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 (most recent call last): File "/home/flashkar/git/doc2vec_annoy/Doc2Vec_Annoy/KNN/testiterator.py", line 44, in model = Doc2Vec(allDocs, size = 300, window = 5, min_count = 2, >workers = 4) File "/home/flashkar/anaconda/lib/python2.7/site->packages/gensim/models/doc2vec.py", line 618, in init self.build_vocab(documents, trim_rule=trim_rule) File >"/home/flashkar/anaconda/lib/python2.7/site->packages/gensim/models/word2vec.py", line 523, in build_vocab self.scan_vocab(sentences, progress_per=progress_per, >trim_rule=trim_rule) # initial survey File "/home/flashkar/anaconda/lib/python2.7/site->packages/gensim/models/doc2vec.py", line 655, in scan_vocab for document_no, document in enumerate(documents): File >"/home/flashkar/git/doc2vec_annoy/Doc2Vec_Annoy/KNN/testiterator.py", line 40, in iter yield LabeledSentence(tokens[:],tpl 1) IndexError: list index out of range
Ваш «второй код» находится на правильном пути, но: (1) вы по-прежнему добавляете каждую строку в 'mapDocName_Id' - таким образом, принося все в один список в памяти; (2) невозможно, чтобы «токены» никогда не были пустыми, где вы его тестировали, потому что перед каждой итерацией цикла он был установлен как '[]', поэтому вы никогда ничего не дадите; (3) теперь вы передаете один кортеж в LabeledSentence, а не в два списка, которые он ожидает; (4) вам не нужно перебирать «alldocs» самостоятельно, когда он работает правильно, вы просто передаете «alldocs» в Doc2Vec один раз. – gojomo