Python MemoryError: не может выделять память массива

У меня есть файл CSV объемом 250 МБ, который мне нужно прочитать с ~ 7000 строк и ~ 9000 столбцов. Каждая строка представляет изображение, и каждый столбец представляет собой пиксель (значение шкалы серого 0-255)

Я начал с простого np.loadtxt("data/training_nohead.csv",delimiter=","), но это дало мне ошибку памяти. Я думал, что это странно, поскольку я запускаю 64-битный Python с установленными 8 гигабайтами памяти, и он умер после использования всего около 512 МБ.

С тех пор я пробовал несколько других тактик, в том числе:

  • import fileinput и читайте по одной строке за раз, добавляя их к массиву
  • np.fromstring после чтения во всем файле
  • np.genfromtext
  • Ручное разборчивость файла (поскольку все данные целые, это было довольно легко кодировать)

Каждый метод дал мне тот же результат. MemoryError около 512 МБ. Удивление, если было что-то особенное в 512 МБ, я создал простую тестовую программу, которая заполняла память до тех пор, пока python не разбился:

str = " " * 511000000 # Start at 511 MB
while 1:
    str = str + " " * 1000 # Add 1 KB at a time

Это не сработало до 1 гигабайта. Я также, просто для удовольствия, попробовал: str = " " * 2048000000 (заполнить 2 концерта) - это бег без затруднений. Заполнял ОЗУ и никогда не жаловался. Таким образом, проблема не в общем объеме ОЗУ, которую я могу выделить, но, похоже, сколько TIMES я могу выделить память...

Я google'd бесплодно, пока не нашел это сообщение: Python вышел из памяти на большом CSV файле (numpy)

Я точно скопировал код из ответа:

def iter_loadtxt(filename, delimiter=',', skiprows=0, dtype=float):
    def iter_func():
        with open(filename, 'r') as infile:
            for _ in range(skiprows):
                next(infile)
            for line in infile:
                line = line.rstrip().split(delimiter)
                for item in line:
                    yield dtype(item)
        iter_loadtxt.rowlength = len(line)

    data = np.fromiter(iter_func(), dtype=dtype)
    data = data.reshape((-1, iter_loadtxt.rowlength))
    return data

Вызов iter_loadtxt("data/training_nohead.csv") на этот раз дал немного другую ошибку:

MemoryError: cannot allocate array memory

Ошибка при запуске этой ошибки. Я нашел только один, не очень полезный пост: Ошибка памяти (MemoryError) при создании булевого массива NumPy (Python)

Поскольку я запускаю Python 2.7, это не было моей проблемой. Любая помощь будет оценена.

Ответ 1

С некоторой помощью от @J.F. Себастьян Я разработал следующий ответ:

train = np.empty([7049,9246])
row = 0
for line in open("data/training_nohead.csv")
    train[row] = np.fromstring(line, sep=",")
    row += 1

Конечно, этот ответ предполагал предварительное знание количества строк и столбцов. Если вы не располагаете этой информацией заранее, количество строк всегда занимает некоторое время, чтобы вычислить, поскольку вам нужно прочитать весь файл и подсчитать символы \n. Что-то вроде этого будет достаточно:

num_rows = 0
for line in open("data/training_nohead.csv")
    num_rows += 1

Для количества столбцов, если каждая строка имеет одинаковое количество столбцов, вы можете просто подсчитать первую строку, иначе вам нужно отслеживать максимум.

num_rows = 0
max_cols = 0
for line in open("data/training_nohead.csv")
    num_rows += 1
    tmp = line.split(",")
    if len(tmp) > max_cols:
        max_cols = len(tmp)

Это решение лучше всего подходит для числовых данных, поскольку строка, содержащая запятую, может действительно усложнить ситуацию.