Ошибка памяти: numpy.genfromtxt()

У меня есть матричный (плавающий) файл размером 50 000x5 000. при использовании x = np.genfromtxt(readFrom, dtype=float) для загрузки файла в память я получаю следующее сообщение об ошибке:

Файл "C:\Python27\lib\site-packages\numpy\lib\npyio.py", строка 1583, в genfromtxt для (i, конвертер) в enumerate(конвертеры)])
MemoryError

Я хочу загрузить весь файл в память, потому что я вычисляю евклидово расстояние между каждым вектором, используя Scipy. dis = scipy.spatial.distance.euclidean(x[row1], x[row2])

Есть ли эффективный способ загрузить в память огромный файл матрицы.

Спасибо.

Update:

Мне удалось решить проблему. Вот мое решение. Я не уверен, эффективно ли это или логически правильно, но у меня работает нормально:

x = open(readFrom, 'r').readlines()
y = np.asarray([np.array(s.split()).astype('float32') for s in x], dtype=np.float32)
....
dis = scipy.spatial.distance.euclidean(y[row1], y[row2])

Пожалуйста, помогите мне улучшить мое решение.


person Maggie    schedule 14.07.2012    source источник
comment
Вычисление расстояния для всех пар векторов займет гораздо больше времени, чем загрузка файла. Перепроверьте, действительно ли вам нужны все пары векторов. Кроме того, вам понадобится как минимум 25 * 10 ^ 7 * 4 = 10 ^ 9 байт, возможно, 2 * 10 ^ 9 байт — последнее было бы невозможно в 32-битной системе.   -  person krlmlr    schedule 14.07.2012
comment
взгляните на stackoverflow.com/q/1896674/1301710   -  person bmu    schedule 14.07.2012


Ответы (2)


В зависимости от вашей ОС и версии Python вполне вероятно, что вы никогда не сможете выделить массив размером 1 ГБ (здесь есть ответ mgilson). Проблема не в том, что вам не хватает памяти, а в том, что вам не хватает непрерывной памяти. Если вы работаете на 32-битной машине (особенно под управлением Windows), добавление памяти не поможет. Переход на 64-битную архитектуру, вероятно, поможет.

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

Если ничего из этого не работает, то вы вынуждены признать, что данные просто не помещаются в памяти. Вам придется обрабатывать его по частям (в этом случае хранение данных в виде массива HDF5 может быть очень полезным).

person Luke    schedule 14.07.2012

На самом деле вы используете 8-байтовые числа с плавающей запятой, поскольку float python соответствует double C (по крайней мере, в большинстве систем):

a=np.arange(10,dtype=float)
print(a.dtype)  #np.float64

Вы должны указать свой тип данных как np.float32. В зависимости от вашей ОС и от того, является ли она 32-битной или 64-битной (и используете ли вы 32-битный Python или 64-битный Python), адресное пространство, доступное для использования numpy, может быть меньше, чем ваши 4 ГБ, что также может быть проблемой здесь .

person mgilson    schedule 14.07.2012
comment
Даже если я использую dtype=np.float32, я получаю ошибку памяти. - person Maggie; 14.07.2012
comment
@Mahin Что произойдет, если вы просто сделаете: >>> a=np.zeros((50000,5000),dtype=np.float32); a=1 вместо np.genfromtxt? - person mgilson; 14.07.2012
comment
@Mahin -- Мой numpy слишком стар, чтобы поддерживать genfromtxt, но, глядя на источник loadtxt (который предположительно эквивалентен, если у вас нет пропущенных значений), однако numpy считывает значения в список (который по крайней мере 4*N*sizeof(pointer)*N байтов). Затем (я думаю) данные снова копируются при построении массива numpy, поскольку ndarrays непрерывны в памяти. Я бы посоветовал вам самостоятельно перебрать файл и упаковать значения (после выделения памяти с помощью np.zeros). Это должно быть относительно легко сделать, поскольку вы знаете размер массива. - person mgilson; 14.07.2012