2014-01-16 4 views
2

У меня есть двумерный массив numpy (raster_data) с размером растра 1 миллион * 1 миллион. Я хочу, чтобы классифицировать, что растр на два класса следующим образом:Ускорьте код в NumPy

class_A = np.where((raster_data >= 5.23) & (raster_data < 8.55),raster_data,np.nan) 
class_B = np.where((raster_data >= 8.55) & (raster_data < 10.0),raster_data,np.nan) 

Однако из-за очень большой размер данных я получаю ошибку памяти. Как я могу по-прежнему классифицировать этот растровый файл так, как я хотел? Я уже пробовал с 16 ГБ оперативной памяти и 64-битным NumPy.

+1

Почему скорость названия, когда проблема является памятью? – cyborg

+2

Массив элементов 1e6 x 1e6 имеет триллион (1e12) предметов. Даже если вы сохранили один бит за элемент, вам понадобится 125 ГБ ** просто для хранения массива 'raster_data' **, с одноточечными поплавками вам потребуется 4 ТБ памяти ... – Jaime

+0

Ответ зависит от того, что вы собираетесь делать делать с классами, сколько элементов в классах (разреженная матрица?) и как вы храните данные. – cyborg

ответ

3

Вы можете попробовать булево индексацию и в месте операции по сохранению памяти:

>>> class_A = raster_data.copy() 
>>> class_B = raster_data.copy() 
>>> mask = raster_data < 5.23 
>>> mask |= raster_data >= 8.55 
>>> class_A[mask] = np.nan 
>>> mask = raster_data < 8.55 
>>> mask |= raster_data >= 10 
>>> class_B[mask] = np.nan 
+0

Нет, «маска» здесь является отрицанием условия в вопросе OP: он выбирает, где хранить значения «raster_data», я ищу, где можно отбрасывать значения с помощью «np.nan». Обратите внимание также, что вместо '&' -в обоих условий, я '' -на их, так как '~ (a & b) == ~ a | ~ B'. – Jaime

0

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

Все зависит от того, что именно вы хотите сделать с этой маской, но посмотрите на pytables; он позволяет эффективно хранить и манипулировать такими крупными массивами.

3

Так вы можете сделать это с помощью pytables. Хотя я надеюсь, что вы терпеливы и у вас много места.

import tables as tb 
import numpy as np 
import time 

f = tb.openFile('humongusFile.h5', 'w') 

n = 100000 
x = f.createCArray(f.root, 'x', tb.Float16Atom(), (n,n), filters=tb.Filters(5, 'blosc')) 



t0 = time.time() 

for i in range(n): 
    x[i] = np.random.random_sample(n)* 10 
x.flush() # dump data to disk 

t1 = time.time() 
print t1 - t0 
print "Done creating test data" 

y1 = f.createCArray(f.root, 'y1', tb.Float16Atom(), (n,n), filters=tb.Filters(5, 'blosc')) 
y2 = f.createCArray(f.root, 'y2', tb.Float16Atom(), (n,n), filters=tb.Filters(5, 'blosc')) 

t2 = time.time() 
print t2 - t1 
print "Done creating output array" 

expr = tb.Expr("where((x >= 5.23) & (x < 8.55), x, 0)") 
expr.setOutput(y1) 

expr2 = tb.Expr("where((x >= 5.23) & (x < 8.55), x, 0)") 
expr2.setOutput(y2) 

t3 = time.time() 
print t3 - t2 
print "Starting evaluating first output" 
expr.eval() 
print "Starting evaluating second output" 
expr2.eval() 
print "Done" 
t4 = time.time() 
print t4 - t3 
+0

Ваша реализация с PyTables действительно хороша, но разве нельзя использовать значение np.nan вместо нуля в вашем выражении? –

+0

@rockpy Я не уверен, поддерживают ли PyTables значения nan. Но вы часто можете просто «определить» значение, которое никогда не должно появляться в ваших данных как нан. – M4rtini

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