2015-07-15 4 views
7

Я просто попытался использовать IncrementalPCA из sklearn.decomposition, но он бросил MemoryError так же, как PCA и RandomizedPCA раньше. Моя проблема в том, что матрица, которую я пытаюсь загрузить, слишком велика, чтобы вписаться в ОЗУ. Сейчас он хранится в базе данных hdf5 в виде набора данных формы ~ (1000000, 1000), поэтому я имею 1.000.000.000 значений float32. Я думал, что IncrementalPCA загружает данные пакетами, но, судя по всему, он пытается загрузить весь набор данных, что не помогает. Как эта библиотека предназначена для использования? Проблема в формате hdf5?Инкрементальный PCA на большие данные

from sklearn.decomposition import IncrementalPCA 
import h5py 

db = h5py.File("db.h5","r") 
data = db["data"] 
IncrementalPCA(n_components=10, batch_size=1).fit(data) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/software/anaconda/2.3.0/lib/python2.7/site-packages/sklearn/decomposition/incremental_pca.py", line 165, in fit 
    X = check_array(X, dtype=np.float) 
    File "/software/anaconda/2.3.0/lib/python2.7/site-packages/sklearn/utils/validation.py", line 337, in check_array 
    array = np.atleast_2d(array) 
    File "/software/anaconda/2.3.0/lib/python2.7/site-packages/numpy/core/shape_base.py", line 99, in atleast_2d 
    ary = asanyarray(ary) 
    File "/software/anaconda/2.3.0/lib/python2.7/site-packages/numpy/core/numeric.py", line 514, in asanyarray 
    return array(a, dtype, copy=False, order=order, subok=True) 
    File "h5py/_objects.pyx", line 54, in h5py._objects.with_phil.wrapper (-------src-dir-------/h5py/_objects.c:2458) 
    File "h5py/_objects.pyx", line 55, in h5py._objects.with_phil.wrapper (-------src-dir-------/h5py/_objects.c:2415) 
    File "/software/anaconda/2.3.0/lib/python2.7/site-packages/h5py/_hl/dataset.py", line 640, in __array__ 
    arr = numpy.empty(self.shape, dtype=self.dtype if dtype is None else dtype) 
MemoryError 

Спасибо за помощь

ответ

14

программы Вы, вероятно, неудача в попытке загрузить весь набор данных в оперативную память. 32 бита на float32 × 1,000,000 × 1000 составляет 3.7 GiB. Это может быть проблемой на машинах с 4-мя ОЗУ. Для того, чтобы проверить, что это на самом деле проблема, попробуйте создать массив только такого размера:

>>> import numpy as np 
>>> np.zeros((1000000, 1000), dtype=np.float32) 

Если вы видите MemoryError, вам необходимо либо больше оперативной памяти, или вам нужно обработать набор данных один кусок за один раз.

С помощью наборов данных h5py мы должны избегать передачи всего набора данных в наши методы и вместо этого передавать фрагменты набора данных. Один за раз.

Как я не данные, позвольте мне начать с создания случайного набора данных одного и того же размера:

import h5py 
import numpy as np 
h5 = h5py.File('rand-1Mx1K.h5', 'w') 
h5.create_dataset('data', shape=(1000000,1000), dtype=np.float32) 
for i in range(1000): 
    h5['data'][i*1000:(i+1)*1000] = np.random.rand(1000, 1000) 
h5.close() 

Это создает хороший 3.8 контрклин файл.

Теперь, если мы находимся в Linux, мы можем ограничить объем памяти доступен в нашей программе:

$ bash 
$ ulimit -m $((1024*1024*2)) 
$ ulimit -m 
2097152 

Теперь, если мы попытаемся запустить свой код, мы получим MemoryError. (нажмите Ctrl-D, чтобы выйти из новой сессии bash и сбросить лимит позже)

Давайте попробуем решить проблему. Мы создадим объект IncrementalPCA и будем называть его метод .partial_fit() много раз, предоставляя каждый фрагмент набора данных каждый раз.

import h5py 
import numpy as np 
from sklearn.decomposition import IncrementalPCA 

h5 = h5py.File('rand-1Mx1K.h5') 
data = h5['data'] # it's ok, the dataset is not fetched to memory yet 

n = data.shape[0] # how many rows we have in the dataset 
chunk_size = 1000 # how many rows we feed to IPCA at a time, the divisor of n 
icpa = IncrementalPCA(n_components=10, batch_size=16) 

for i in range(0, n//chunk_size): 
    ipca.partial_fit(data[i*chunk_size : (i+1)*chunk_size]) 

Это, кажется, работает для меня, и если я смотрю на то top отчеты, распорок распределения памяти ниже 200M.

+0

Хорошо, так что в основном я не должен называть подходящим, но partial_fit несколько раз. Я не видел этот метод, потому что учебник использует подходящий. Знаете ли вы, почему fit имеет параметр batch_size, если он загружает весь набор данных одновременно? – KrawallKurt

+0

Трюк не загружать все данные в память, вероятно, позаботился о библиотеке h5py. Его объект набора данных ('h5 ​​['data']'), похоже, ведет себя как обычный массив numpy, но это не так. 'IncrementalPCA' не знает, что это структура данных на диске, и в какой-то момент читает все строки (' MemoryError'!). Расчет по-прежнему выполняется в партиях 'batch_size'. – sastanin

+1

Это происходит в 'fit()', который [вызывает check_array()] (https://github.com/scikit-learn/scikit-learn/blob/0.16.1/sklearn/decomposition/incremental_pca.py#L165), который должен преобразовывать данные в обычный массив numpy (https://github.com/scikit-learn/scikit-learn/blob/0.16.1/sklearn/utils/validation.py#L268) Вызов 'partial_fit() 'обходит это преобразование. – sastanin

Смежные вопросы