簡體   English   中英

大型數據集的Python內存錯誤

[英]Python memory error for a large data set

我想生成一個“詞袋”矩陣,其中包含文檔中具有相應計數的文檔。 為了做到這一點,我運行下面的代碼來初始化單詞矩陣包。 不幸的是,在我閱讀文檔的行中的x個文檔之后,我收到了內存錯誤。 有沒有更好的方法來做到這一點,以便我可以避免內存錯誤? 請注意,我想處理大量文件〜2.000.000只有8 Gb的RAM。

def __init__(self, paths, words_count, normalize_matrix = False ,trainingset_size = None, validation_set_words_list = None):
    '''
    Open all documents from the given path.
    Initialize the variables needed in order
    to construct the word matrix.

    Parameters
    ----------
    paths: paths to the documents.
    words_count: number of words in the bag of words.
    trainingset_size: the proportion of the data that should be set to the training set.
    validation_set_words_list: the attributes for validation.
    '''

    print '################ Data Processing Started ################'

    self.max_words_matrix = words_count

    print '________________ Reading Docs From File System ________________'
    timer = time()
    for folder in paths:
        self.class_names.append(folder.split('/')[len(folder.split('/'))-1])
        print '____ dataprocessing for category '+folder
        if trainingset_size == None:
            docs = os.listdir(folder)
        elif not trainingset_size == None and validation_set_words_list == None:
            docs = os.listdir(folder)[:int(len(os.listdir(folder))*trainingset_size-1)]
        else:
            docs = os.listdir(folder)[int(len(os.listdir(folder))*trainingset_size+1):]
        count = 1
        length = len(docs)
        for doc in docs:
            if doc.endswith('.txt'):
                d = open(folder+'/'+doc).read()
                # Append a filtered version of the document to the document list.
                self.docs_list.append(self.__filter__(d))
                # Append the name of the document to the list containing document names.
                self.docs_names.append(doc)
                # Increase the class indices counter.
                self.class_indices.append(len(self.class_names)-1)

            print 'Processed '+str(count)+' of '+str(length)+' in category '+folder
            count += 1

你要求的是不可能的。 此外,Python不會自動獲得您期望從BoW獲得的空間優勢。 另外,我認為你首先做的關鍵是錯誤的。 讓我們以相反的順序。


無論你在這條線上做什么:

self.docs_list.append(self.__filter__(d))

......可能是錯的。

您要為每個文檔存儲的所有內容都是計數向量。 為了獲得該計數向量,您需要附加所有單詞的單個dict。 除非__filter__正在修改一個隱藏的字典,並返回一個向量,否則它不會做正確的事情。


BoW模型的主要空間節省來自於不必為每個文檔存儲字符串鍵的副本,以及能夠存儲簡單的int數組而不是花式哈希表。 但是整數對象幾乎和(短)字符串對象一樣大,並且沒有辦法預測或保證何時獲得新的整數或字符串以及對現有的整數或字符串的額外引用。 所以,實際上,你獲得的唯一優勢是1/hash_fullness ; 如果你想要任何其他優點,你需要像array.arraynumpy.ndarray這樣的東西。

例如:

a = np.zeros(len(self.word_dict), dtype='i2')
for word in split_into_words(d):
    try:
        idx = self.word_dict[word]
    except KeyError:
        idx = len(self.word_dict)
        self.word_dict[word] = idx
        np.resize(a, idx+1)
        a[idx] = 1
    else:
        a[idx] += 1
self.doc_vectors.append(a)

但這仍然不夠。 除非您擁有1K個唯一單詞的順序,否則您無法將所有這些計數都放在內存中。

例如,如果你有5000個獨特的單詞,你就有2M陣列,每個陣列都有5000個2字節計數,所以最緊湊的可能表示需要20GB。

由於大多數文檔都沒有大多數單詞,因此使用稀疏數組(或單個2D稀疏數組)可以獲得一些好處,但是只能獲得很多好處。 並且,即使事情恰好以這樣的方式排序以使您獲得絕對完美的RLE壓縮,如果每個文檔的平均唯一字數大約為1K,那么您仍然會耗盡內存。


因此,您根本無法將所有文檔向量存儲在內存中。

如果你可以迭代地處理它們而不是一次性處理它們,那就是明顯的答案。

如果沒有,您將不得不將它們分頁到磁盤(無論是顯式的,還是使用PyTables或數據庫或其他東西)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM