Есть ли более эффективный способ добавления строк из большого файла в массив Numpy? - MemoryError

Я пытаюсь использовать этот пакет lda для обработки csv-файла матрицы терминов с 39568 строками и 27519 столбцами, содержащими только счетные / натуральные числа.

Проблема: я получаю MemoryError с моим подходом, чтобы прочитать файл и сохранить его в массиве.

Цель: получить числа из CSV-файла TDM и преобразовать его в массив numpy, чтобы я мог использовать массив numpy в качестве входных данных для lda.

with open("Results/TDM - Matrix Only.csv", 'r') as matrix_file:
    matrix = np.array([[int(value) for value in line.strip().split(',')] for line in matrix_file])

Я также попытался использовать numpy append, vstack и concatenate, и я все еще получаю MemoryError.

Есть ли способ избежать MemoryError?

Редактировать:

Я попытался использовать dtype int32 и int, и это дает мне:

WindowsError: [Ошибка 8] Недостаточно памяти для обработки этой команды

Я также попытался использовать dtype float64, и это дает мне:

OverflowError: не может вписать 'long' в целое число размером с индекс

С этими кодами:

fp = np.memmap("Results/TDM-memmap.txt", dtype='float64', mode='w+', shape=(len(documents), len(vocabulary)))
matrix = np.genfromtxt("Results/TDM.csv", dtype='float64', delimiter=',', skip_header=1)
fp[:] = matrix[:]

а также

with open("Results/TDM.csv", 'r') as tdm_file:
    vocabulary = [value for value in tdm_file.readline().strip().split(',')]
    fp = np.memmap("Results/TDM-memmap.txt", dtype='float64', mode='w+', shape=(len(documents), len(vocabulary)))
    for idx, line in enumerate(tdm_file):
        fp[idx] = np.array(line.strip().split(','))

Другая информация, которая может иметь значение

  • Win10 64bit
  • 8 ГБ ОЗУ (7,9 годно для использования) | достигает пика в 5,5 ГБ из более или менее 3 ГБ (используется около 2 ГБ), прежде чем он сообщает MemoryError
  • Python 2.7.10 [MSC v.1500 32 бит (Intel)]
  • Использование PyCharm Community Edition 5.0.3

1 ответ

Решение

Поскольку ваши слова будут иметь почти все нули, было бы намного эффективнее хранить их в scipy.sparse матрица. Например:

from scipy import sparse
import textmining
import lda

# a small example matrix
tdm = textmining.TermDocumentMatrix()
tdm.add_doc("here's a bunch of words in a sentence")
tdm.add_doc("here's some more words")
tdm.add_doc("and another sentence")
tdm.add_doc("have some more words")

# tdm.sparse is a list of dicts, where each dict contains {word:count} for a single
# document
ndocs = len(tdm.sparse)
nwords = len(tdm.doc_count)
words = tdm.doc_count.keys()

# initialize output sparse matrix
X = sparse.lil_matrix((ndocs, nwords),dtype=int)

# iterate over documents, fill in rows of X
for ii, doc in enumerate(tdm.sparse):
    for word, count in doc.iteritems():
        jj = words.index(word)
        X[ii, jj] = count

X сейчас (ndocs, nwords) scipy.sparse.lil_matrix, а также words список, соответствующий столбцам X:

print(words)
# ['a', 'and', 'another', 'sentence', 'have', 'of', 'some', 'here', 's', 'words', 'in', 'more', 'bunch']

print(X.todense())
# [[2 0 0 1 0 1 0 1 1 1 1 0 1]
#  [0 0 0 0 0 0 1 1 1 1 0 1 0]
#  [0 1 1 1 0 0 0 0 0 0 0 0 0]
#  [0 0 0 0 1 0 1 0 0 1 0 1 0]]

Вы могли бы пройти X прямо к lda.LDA.fit хотя, вероятно, будет быстрее преобразовать его в scipy.sparse.csr_matrix первый:

X = X.tocsr()
model = lda.LDA(n_topics=2, random_state=0, n_iter=100)
model.fit(X)
# INFO:lda:n_documents: 4
# INFO:lda:vocab_size: 13
# INFO:lda:n_words: 21
# INFO:lda:n_topics: 2
# INFO:lda:n_iter: 100
# INFO:lda:<0> log likelihood: -126
# INFO:lda:<10> log likelihood: -102
# INFO:lda:<20> log likelihood: -99
# INFO:lda:<30> log likelihood: -97
# INFO:lda:<40> log likelihood: -100
# INFO:lda:<50> log likelihood: -100
# INFO:lda:<60> log likelihood: -104
# INFO:lda:<70> log likelihood: -108
# INFO:lda:<80> log likelihood: -98
# INFO:lda:<90> log likelihood: -98
# INFO:lda:<99> log likelihood: -99
Другие вопросы по тегам