Это прямая реализация такого рода keras
-подобной (?) Свертки.Это может быть трудно понять новичкам, потому что он использует множество приемов вещания и быстрого продвижения.
from numpy.lib.stride_tricks import as_strided
def conv2d(a, b):
a = as_strided(a,(len(a),a.shape[1]-len(b)+1,a.shape[2]-b.shape[1]+1,len(b),b.shape[1],a.shape[3]),a.strides[:3]+a.strides[1:])
return np.einsum('abcijk,ijkd', a, b[::-1,::-1])
Кстати: если вы делаете свертку с очень большим ядром, используйте вместо этого алгоритм на основе Фурье.
РЕДАКТИРОВАТЬ: [::-1,::-1]
следует удалить в случае, если свертка не включает в себя сначала перевернуть ядро (как в tensorflow
).
РЕДАКТИРОВАТЬ: np.tensordot(a, b, axes=3)
работает намного лучше, чем np.einsum("abcijk,ijkd", a, b)
, и настоятельно рекомендуется.Итак, функция становится:
from numpy.lib.stride_tricks import as_strided
def conv2d(a, b):
Hout = a.shape[1] - b.shape[0] + 1
Wout = a.shape[2] - b.shape[1] + 1
a = as_strided(a, (a.shape[0], Hout, Wout, b.shape[0], b.shape[1], a.shape[3]), a.strides[:3] + a.strides[1:])
return np.tensordot(a, b, axes=3)