Нужна помощь в оптимизации расчетов энтропии движущегося окна - PullRequest
1 голос
/ 11 июля 2019

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

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

Мне бы очень хотелось иметь возможность запускать эту операцию параллельно, но не получается заставить работать pool.apply(), возможно ли запустить ее параллельно?

Вот мой рабочий код:

def get_entropy_of_block(data):
    value,counts = np.unique(data, return_counts=True)
    entropy_of_block = entropy(value, counts)
    if np.isnan(entropy_of_block):
        entropy_of_block = 0
    return entropy_of_block


def output_entropy_versions(mask, window = 5):    
        mask = np.pad(mask, (0,window - 2), 'edge')
        blocks = view_as_windows(mask, (window,window,window),step=1)
        entropy_mask = np.zeros(shape=(blocks.shape[0], blocks.shape[1], blocks.shape[2]))
        for x in range(blocks.shape[0]):
            print(x)
            for y in range(blocks.shape[1]):
                for z in range(blocks.shape[2]):
                    entropy_mask[x,y,z] = get_entropy_of_block(blocks[x,y,z,:,:])
        return entropy_mask

А вот и параллельная попытка

def output_entropy_versions_parallel(mask, window = 5):    

        mask = np.pad(mask, (0,window - 2), 'edge')
        blocks = view_as_windows(mask, (window,window,window),step=1)
        entropy_mask = np.zeros(shape=(blocks.shape[0], blocks.shape[1], blocks.shape[2]))
        for x in range(blocks.shape[0]):
            print(x)
            for y in range(blocks.shape[1]):
                    res = [pool.apply(get_entropy_of_block, args = (blocks[x,y,z,:,:])) for z in range(blocks.shape[2])]
                    entropy_mask[x,y,:] = res
        return entropy_mask

Запустив это, я получаю следующее:


<ipython-input-10-8c3d4ca9d313> in output_entropy_versions(mask, window)
     24                 print(x)
     25                 for y in range(blocks.shape[1]):
---> 26                         res = [pool.apply(get_entropy_of_block, args = (blocks[x,y,z,:,:])) for z in range(blocks.shape[2])]
     27                         entropy_mask[x,y,:] = res
     28             return entropy_mask

> <ipython-input-10-8c3d4ca9d313> in get_entropy_of_block(data)
     10 def get_entropy_of_block(data):
     11         value,counts = np.unique(data, return_counts=True)
---> 12         entropy_of_block = entropy(value, counts)
     13         if np.isnan(entropy_of_block):
     14             entropy_of_block = 0

E:\Anaconda\lib\site-packages\scipy\stats\_distn_infrastructure.py in entropy(pk, qk, base)
   2505     """
   2506     pk = asarray(pk)
-> 2507     pk = 1.0*pk / np.sum(pk, axis=0)
   2508     if qk is None:
   2509         vec = entr(pk)

TypeError: unsupported operand type(s) for *: 'float' and 'generator'

...