0

I've been trying to implement a MaxPoolingLayer in numpy. The problem I'm having is that I cannot create an array that contains all the indices of the max Values(which I obviously need for the backward pass). My Idea is to create said array as some sort of binaryMask which i can apply to the dInputArray to get an Array which is set to 0 on all values that did not contribute to the output of the forward pass but set to one to all values which contributed to the output of the forward pass. My Code is here:

import numpy as np

#Quellen https://numpy.org/doc/stable/reference/generated/numpy.mgrid.html
#https://lanstonchu.wordpress.com/2018/09/01/convolutional-neural-network-cnn-backward-propagation-of-the-pooling-layers/

class MaxPooling():
    def __init__(self, *, maxPoolingSize=2):
        self.maxPoolingSize = maxPoolingSize
    
    def forward(self, image):
        self._input = image.shape
        b,h, w  = image.shape
        output = np.zeros((b, h // self.maxPoolingSize, w // self.maxPoolingSize))
        self._maxOutputIndeces = np.copy(output)
        for batch in range(b):
            for y in range(0, h - h % self.maxPoolingSize, self.maxPoolingSize):
                for x in range(0, w - w % self.maxPoolingSize, self.maxPoolingSize):
                    Y, X = y // self.maxPoolingSize, x // self.maxPoolingSize
                    output[batch, Y, X] = np.max(image[batch, y:y+self.maxPoolingSize, x:x+self.maxPoolingSize])
                    self._maxOutputIndeces[batch, Y, X] = np.argmax(image[batch, y:y+self.maxPoolingSize, x:x+self.maxPoolingSize])
        return output
    
    def forwardOptim(self, image):
        """
        Es wird eine Kopie von der shape des Bild angefertigt, welche später im backward Pass verwendet wird.
        Wir "formen" den Image array um, sodass dieser aufgesplitet wird und entlang der Achsen -1, -2 den Imagearray
        in Form von kleinen "subArrays", die die einzelnen Teilausschnitte des Bildes in bezug auf die MaxPooling Operat-
        ion beinhalten.
        """
        self._input = image.shape
        _, y, x = image.shape
        newImage = image[:y - y % self.maxPoolingSize, :x - x % self.maxPoolingSize]
        newImage = newImage.reshape(-1, y // self.maxPoolingSize, self.maxPoolingSize, x // self.maxPoolingSize, self.maxPoolingSize)
        maxValuesImage = newImage.max(axis = (-3, -1))
        self._maxOutputIndeces1 = newImage.argmax(axis = -3)#this line makes me wanna give up
        return maxValuesImage
    
    def backward(self, gradient):
        dInput = np.zeros(self._input)
        b, h, w = self._input
        B, Y, X = np.mgrid[0:b, 0:h - h % self.maxPoolingSize:self.maxPoolingSize, 0:w - w % self.maxPoolingSize:self.maxPoolingSize]
        Y //= self.maxPoolingSize
        X //= self.maxPoolingSize
        maxIndex = np.unravel_index(self._maxOutputIndeces[B,Y, X].astype(int), (b,self.maxPoolingSize, self.maxPoolingSize))
        dInput[maxIndex[0], Y * self.maxPoolingSize + maxIndex[1], X * self.maxPoolingSize + maxIndex[2]] = gradient[B, Y, X]
        return dInput
    
    def backwardOptim(self, gradient):
        raise NotImplementedError

I tried pretty much everything i could think of. So yeah I don't know what to put here apart from my test setup to make it easier for you guys to help me.

if __name__ == "__main__":
    test = np.array([[[1, 2, 3, 4],
                      [5, 6, 7, 8],
                      
                      [1, 2, 3, 4],
                      [5, 6, 7, 8]],
                     
                     [[1, 2, 3, 4],
                      [5, 6, 7, 8],
                      [1, 2, 3, 4],
                      [5, 6, 7, 8]]])
    gradient = np.array([[[1, 2],
                         [1, 2]],
                         [[1, 2],
                          [1, 2]]])
    m = MaxPooling()
    output = m.forwardOptim(test)
    output1 = m.forward(test)
    dInput = m.backward(gradient)
FalkAurel
  • 1
  • 2

0 Answers0