Как выполнить операцию максимального пула над массивом трехмерной свертки? - PullRequest
1 голос
/ 25 мая 2019

Я строю сверточную нейронную сеть с numpy, и я не уверен, что моя обработка пула 3D (HxWxD) входного изображения правильная.

В качестве примера, у меня есть изображение в форме (12x12x3), я сворачиваю его в (6x6x3) и хочу выполнить максимальное объединение таким образом, чтобы получить изображение (3x3x3). Для этого я выбираю размер фильтра (2x2) и шаг 2.

output_size = int((conv.shape[0]-F)/S + 1)
pool = np.zeros((output_size,output_volume,3)) # pool array
for k in range(conv.shape[-1]): # loop over conv depth
    i_stride = 0 
    for i in range(output_size): 
        j_stride = 0
        for j in range(output_size):
            pool[i,j,k] = np.amax(conv[i_stride:i_stride+F,
                                                j_stride:j_stride+F,k],0)
            j_stride+=S 
        i_stride+=S

Для первого канала моего массива свертки conv[:,:,0] я получаю следующее . Сравнивая это с первым каналом массива max pooling pool[:,:,0] , я получаю . С первого взгляда я могу сказать, что операция объединения не правильная, conv[0:2,0:2,0] (в основном серый), безусловно, не pool[0,0,0] (черный), можно ожидать, что это будет один из оттенков серого. Поэтому я убежден, что здесь что-то определенно не так Либо мой цикл for, либо два сравнения, которые я провожу, отключены.

Если кто-то может помочь мне лучше понять операцию объединения над массивом с 3 измерениями, это определенно поможет.

1 Ответ

0 голосов
/ 25 мая 2019

Максимальное объединение дает ту же глубину, что и вход. Имея это в виду, мы можем сосредоточиться на одном срезе (по глубине) входного конв. Для одного среза с произвольным индексом у вас есть простое изображение с размерами NxN. Вы определили размер фильтра 2 и шаг 2. Максимальное объединение в пул не делает ничего, кроме итерации по входному изображению и получения максимума по текущему «подизображению».

import numpy as np

F = 2
S = 2
conv = np.array(
    [
        [
            [[.5, .1], [.1, .0], [.2, .7], [.1, .3], [.0, .1], [.3, .8]],
            [[.0, .9], [.5, .7], [.3, .1], [.9, .2], [.8, .7], [.1, .9]],
            [[.1, .8], [.1, .2], [.6, .2], [.0, .3], [.1, .3], [.0, .8]],
            [[.0, .6], [.6, .4], [.2, .8], [.6, .8], [.9, .1], [.3, .1]],
            [[.3, .9], [.7, .6], [.7, .6], [.5, .4], [.7, .2], [.8, .1]],
            [[.1, .8], [.9, .3], [.2, .7], [.8, .4], [.0, .5], [.8, .0]]
        ],
        [
            [[.1, .2], [.1, .0], [.5, .3], [.0, .4], [.0, .5], [.0, .6]],
            [[.3, .6], [.6, .4], [.1, .2], [.6, .2], [.2, .3], [.2, .4]],
            [[.2, .1], [.4, .2], [.0, .4], [.5, .6], [.7, .6], [.7, .2]],
            [[.0, .7], [.5, .3], [.4, .0], [.4, .6], [.2, .2], [.2, .7]],
            [[.0, .5], [.3, .0], [.3, .8], [.3, .2], [.6, .3], [.5, .2]],
            [[.6, .2], [.2, .5], [.5, .4], [.1, .0], [.2, .6], [.1, .8]]
        ]
    ])

number_of_images, image_height, image_width, image_depth = conv.shape
output_height = (image_height - F) // S + 1
output_width = (image_width - F) // S + 1

pool = np.zeros((number_of_images, output_height, output_width, image_depth))
for k in range(number_of_images):
    for i in range(output_height):
        for j in range(output_width):
            pool[k, i, j, :] = np.max(conv[k, i*S:i*S+F, j*S:j*S+F, :])

print(pool[0, :, :, 0])
[[0.9 0.9 0.9]
 [0.8 0.8 0.9]
 [0.9 0.8 0.8]]
print(pool[0, :, :, 1])
[[0.9 0.9 0.9]
 [0.8 0.8 0.9]
 [0.9 0.8 0.8]]
print(pool[1, :, :, 0])
[[0.6 0.6 0.6]
 [0.7 0.6 0.7]
 [0.6 0.8 0.8]]
print(pool[1, :, :, 1])
[[0.6 0.6 0.6]
 [0.7 0.6 0.7]
 [0.6 0.8 0.8]]

Мне не понятно, почему вы используете транспонирование строки max для одного элемента в пуле.

...