Ни один скупи не пропускает суммирование каналов. Причина, по которой вы получаете вывод (3, 5, 5)
, заключается в том, что ndimage.convolve
дополняет входной массив по всем осям, а затем выполняет свертку в «одинаковом» режиме (т. Е. Выход имеет ту же форму, что и вход, с центром по отношению к вывод «полного» режима корреляции). См. scipy.signal.convolve для более подробной информации о режимах.
Для ввода формы (3 ,5, 5)
и фильтра w0
формы (3, 3, 3)
, ввод дополнен, что приводит к массив (7, 9, 9)
. См. Ниже (для простоты я использую постоянное заполнение нулями):
a = np.array([[[2, 0, 2, 2, 2],
[1, 1, 0, 2, 0],
[0, 0, 1, 2, 2],
[2, 2, 2, 0, 0],
[1, 0, 1, 2, 0]],
[[1, 2, 1, 0, 1],
[0, 2, 0, 0, 1],
[0, 0, 2, 2, 1],
[2, 0, 1, 0, 2],
[0, 1, 2, 2, 2]],
[[0, 0, 2, 2, 2],
[0, 1, 2, 1, 0],
[0, 0, 0, 2, 0],
[0, 2, 0, 0, 2],
[0, 0, 2, 2, 1]]])
w0 = np.array([[[0, 1, -1],
[1, -1, 0],
[0, 0, 0]],
[[1, 0, 0],
[0, -1, 1],
[1, 0, 1]],
[[ 1, -1, 0],
[-1, 0, -1],
[-1, 0, 1]]])
k = w0.shape[0]
a_p = np.pad(a, k-1)
array([[[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0]],
[[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0]],
[[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 2, 0, 2, 2, 2, 0, 0],
[0, 0, 1, 1, 0, 2, 0, 0, 0],
[0, 0, 0, 0, 1, 2, 2, 0, 0],
[0, 0, 2, 2, 2, 0, 0, 0, 0],
[0, 0, 1, 0, 1, 2, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0]],
[[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 2, 1, 0, 1, 0, 0],
[0, 0, 0, 2, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 2, 2, 1, 0, 0],
[0, 0, 2, 0, 1, 0, 2, 0, 0],
[0, 0, 0, 1, 2, 2, 2, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0]],
[[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 2, 2, 2, 0, 0],
[0, 0, 0, 1, 2, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 2, 0, 0, 0],
[0, 0, 0, 2, 0, 0, 2, 0, 0],
[0, 0, 0, 0, 2, 2, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0]],
[[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0]],
[[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0]]])
Прежде чем продолжить, обратите внимание, что на изображении из cs231n выполняется корреляция, а не свертка, поэтому нам нужно перевернуть w0
или вместо этого используйте корреляционную функцию (я сделаю первое).
Затем свертка выполняется путем скольжения вдоль первого измерения (ось-0), т. е. (перевернутый) w0
сворачивается с a_p[0:3]
, затем с a_p[1:4]
, затем с a_p[2:5]
, затем с a_p[3:6]
и, наконец, с a_p[4:7]
, каждый из которых приводит к массиву (1, 7, 7)
из-за суммирования по каналам. Затем они складываются вместе, в результате чего получается массив (5, 7, 7)
. Чтобы показать это, я использую scipy.signal.convolve
, который позволяет использовать режим full
:
out = scipy.signal.convolve(a, np.flip(w0), mode='full')
array([[[ 2, 0, 0, 2, 0, -2, -2],
[-1, 1, -5, -1, -4, -4, -2],
[-1, -3, 2, -3, 1, -4, 0],
[ 2, 1, -1, -3, -7, 0, -2],
[-1, -2, -4, -1, -4, -2, 2],
[-1, -2, -2, -2, 1, -2, 0],
[ 0, -1, 1, -1, -1, 2, 0]],
[[ 3, 2, 4, 0, 4, 2, 1],
[ 2, -1, 1, -1, -1, 0, -2],
[ 1, -3, 3, 5, 2, 1, 3],
[ 4, 2, 1, 4, 0, -3, -2],
[ 1, 1, 1, -1, -1, 3, -1],
[ 1, -4, 3, -1, -3, -4, 0],
[ 0, 0, 0, -1, 1, 2, 2]],
[[ 1, 2, 4, 4, 2, -2, -1],
[ 1, 2, 1, -3, -4, -4, 1],
[-2, 2, -3, 3, 1, 2, 4],
[ 1, 2, 5, -6, 6, -2, 3],
[ 2, -5, 4, 1, 5, 4, 0],
[-2, 0, 0, 1, -3, -4, 3],
[-1, 1, -1, -2, 4, 3, 3]],
[[ 0, 0, 2, 2, 4, 2, 2],
[ 0, 0, 3, 3, 3, -2, 1],
[-1, 0, 0, 4, 0, 4, 3],
[ 0, 0, 2, 3, 1, 3, 3],
[ 0, 0, 0, 1, 7, 1, 3],
[-2, 2, 0, 2, -3, 1, 4],
[ 0, -1, -1, 0, 2, 4, 1]],
[[ 0, 0, 0, 0, 0, 0, 0],
[ 0, 0, 0, -2, 0, 0, 2],
[ 0, 0, -3, -1, 1, 3, 0],
[ 0, -1, -1, 1, -1, 2, 0],
[ 0, 0, -2, 0, 2, -2, 2],
[ 0, -2, 2, -2, -2, 3, 1],
[ 0, 0, -2, 0, 1, 1, 0]]])
Чтобы перейти в "тот же" режим ndimage.convolve
, нам нужно отцентрировать out
:
out = out[1:-1, 1:-1, 1:-1]
array([[[-1, 1, -1, -1, 0],
[-3, 3, 5, 2, 1],
[ 2, 1, 4, 0, -3],
[ 1, 1, -1, -1, 3],
[-4, 3, -1, -3, -4]],
[[ 2, 1, -3, -4, -4],
[ 2, -3, 3, 1, 2],
[ 2, 5, -6, 6, -2],
[-5, 4, 1, 5, 4],
[ 0, 0, 1, -3, -4]],
[[ 0, 3, 3, 3, -2],
[ 0, 0, 4, 0, 4],
[ 0, 2, 3, 1, 3],
[ 0, 0, 1, 7, 1],
[ 2, 0, 2, -3, 1]]])
Это именно то, что вы получите, если вы запустите scipy.ndimage.convolve(a, np.flip(w0), mode='constant', cval=0)
. Наконец, чтобы получить желаемый результат, нам нужно игнорировать элементы, которые полагались на заполнение по первому измерению (т.е. оставить только среднюю часть выхода), также использовать шаги s=2
(то есть out[1][::s, ::s]
) и, наконец, добавить смещение b = 1
:
out[1][::s, ::s] + b
array([[ 3, -2, -3],
[ 3, -5, -1],
[ 1, 2, -3]])
Все в одной строке:
scipy.ndimage.convolve(a, np.flip(w0), mode='constant', cval=0)[1][::2, ::2] + b
# or using scipy.signal.convolve
# scipy.signal.convolve(a, np.flip(w0), 'full')[2][1:-1,1:-1][::2, ::2] + b
# or
# scipy.signal.convolve(a, np.flip(w0), 'same')[1][::2, ::2] + b