В сетях обработки и классификации изображений общей задачей является свертка или взаимная корреляция входных изображений с некоторыми фиксированными фильтрами. Например, в сверточных нейронных сетях (CNN) это чрезвычайно распространенная операция. Я сократил общую задачу версии до этого:
Дано : серия из N изображений [N, H, W, D, ...] и набор K фильтров [K, H, W, D, ...]
Return : ndarray, который представляет m-мерную взаимную корреляцию (xcorr) изображения N_i с фильтром K_j для каждого N_i в N и K_j в K
В настоящее время , я использую scipy.spatial.cdist для пользовательской функции, которая представляет максимум xcorr двух m-dim изображений, а именно scipy.signal.correlate. Код выглядит примерно так:
from scipy.spatial.distance import cdist
from scipy.signal import correlate
def xcorr(u,v):
'''unfortunately, cdist only takes 2D arrays, so need to do this'''
u = np.reshape(u, [96,96,3])
v = np.reshape(v, [96,96,3])
return np.max(correlate(u,v,mode='same',method='fft'))
batch_images = np.random.random([500,96,96,3])
my_filters = np.random.random([1000,96,96,3])
# unfortunately, cdist only takes 2D arrays, so need to do this
batch_vec = np.reshape(batch_images, [-1,np.prod(batch_images.shape[1:])])
filt_vec = np.reshape(my_filters, [-1,np.prod(my_filters.shape[1:])])
answer = cdist(batch_vec, filt_vec, xcorr)
Метод работает, и приятно, что cdist автоматически распараллеливается между потоками, но на самом деле он довольно медленный. Я предполагаю, что это связано с рядом причин, включая неоптимальное использование кэша между потоками (например, оставить один фильтр фиксированным в кэше, пока вы фильтруете все изображения, или наоборот), операция изменения формы внутри xcorr и т. Д.
Есть ли у сообщества идеи, как это ускорить? Я понимаю, что в моем примере xcorr берет максимум за взаимную корреляцию между обоими изображениями, но это был только пример, который был пригоден для работы с cdist. В идеале вы могли бы выполнить эту пакетную операцию и использовать какую-то другую функцию (или ни одной), чтобы получить желаемый результат. Идеальные решения могут обрабатывать (R, G, B, D, ...) данные.
Любая / вся помощь приветствуется, включая, но не ограничиваясь этим, упаковку C, хотя решения Python / numpy предпочтительнее. Я видел некоторые посты, связанные с нотацией einsum, но я не очень знаком с этим, поэтому любая помощь будет оценена. Я приветствую решения с тензорным потоком, ЕСЛИ они могут получить тот же ответ (с разумной точностью), что и соответствующая медленная версия с нолью.