Как бороться с «TypeError» из-за формы ввода (None, 1024, 1024, 4) при реализации собственного пула? - PullRequest
0 голосов
/ 29 марта 2020

Я наивно пытался реализовать свои собственные функции объединения и отмены, так что индексы сохраняются при объединении, чтобы сопоставить значения с индексами при отмене. Вот код.

from keras.layers import Input, Layer
from keras.models import Model
from keras.layers.convolutional import Conv2D
import keras.backend as K

class MaxPool2DWithIndices(Layer):
    def __init__(self, filter_size=(2,2), strides=(2,2), padding='valid', **kwargs):
        super(MaxPool2DWithIndices, self).__init__(**kwargs)
        self.filter_size = filter_size
        self.strides = strides
        self.padding = padding

    def __call__(self, inputs):
        '''
        inputs: (n, H, W, d), ie batch of n inputs of size (H, W, d)
        '''
        print (inputs.shape)
        inputs_shape = inputs.shape #K.array(inputs.shape)
        pooled_H = (inputs_shape[1]-self.filter_size[0])//self.strides[0]+1
        pooled_W = (inputs_shape[2]-self.filter_size[1])//self.strides[1]+1
        #if type(inputs_shape[0]) is not int: inputs_shape[0] = 1
        mpooled = np.zeros((inputs_shape[0], pooled_H, pooled_W, inputs_shape[3]))
        indices = np.zeros((inputs_shape[0], pooled_H, pooled_W, inputs_shape[3]))
        for n in range(0, inputs_shape[0], 2): # for each example
            for i in range(0, inputs_shape[1], 2):
                for j in range(0, inputs_shape[2], 2):
                    for k in range(inputs_shape[3]):
                        mpooled[n, i//2, j//2, k] = np.max(inputs[n, i:i+2, j:j+2, k])
                        indices[n, i//2, j//2, k] = np.argmax(inputs[n, i:i+2, j:j+2, k])
        return [mpooled, indices]

class MaxUnPool2DWithIndices(Layer):
    def __init__(self, filter_size=(2,2), strides=(2,2), padding='valid'):
        super(MaxUnPool2DWithIndices, self).__init__(**kwargs)
        self.indices = indices
        self.filter_size = filter_size
        self.strides = strides
        self.padding = padding

    def __call__(self, inputs, indices):
        '''
        inputs: (n, H, W, d), ie batch of n inputs of size (H, W, d)
        '''
        inputs_shape = inputs.shape #K.array(inputs.shape)
        unpooled_H = (inputs_shape[1]-1)*self.strides[0]+self.filter_size[0]
        unpooled_W = (inputs_shape[2]-1)*self.strides[1]+self.filter_size[1]
        #if type(inputs_shape[0]) is not int: inputs_shape[0] = 1
        max_unpooled = np.zeros((inputs_shape[0], unpooled_H, unpooled_W, inputs_shape[3]))
        for n in range(inputs_shape[0]): # for each example
            for i in range(0, unpooled_H, 2):
                for j in range(0, unpooled_W, 2):
                    for k in range(inputs_shape[2]):
                        if self.indices[n, i//2, j//2, k] == 0:
                            max_unpooled[n, i+0, j+0, k] = inputs[n, i//2, j//2, k]
                        elif self.indices[n, i//2, j//2, k] == 1:
                            max_unpooled[n, i+0, j+1, k] = inputs[n, i//2, j//2, k]
                        elif self.indices[n, i//2, j//2, k] == 2:
                            max_unpooled[n, i+1, j+0, k] = inputs[n, i//2, j//2, k]
                        else: # it is 3
                            max_unpooled[n, i+1, j+1, k] = inputs[n, i//2, j//2, k]
        return max_unpooled

Пусть приведенная ниже модель будет примером для воспроизведения ошибки:

input_layer = Input(shape=(1024, 1024, 1))

encoded_out = Conv2D(4, (3, 3), activation='relu', padding="same")(input_layer)
encoded_out, indices1 = MaxPool2DWithIndices(filter_size=(2,2), strides=(2,2), padding='valid')(encoded_out)

decoded_out = MaxUnPool2DWithIndices(filter_size=(2,2), strides=(2,2), padding='valid')(encoded_out, indices1)
decoded_out = Conv2D(4, (3, 3), activation='relu', padding="same")(decoded_out)

model = Model(input_layer, decoded_out)

Приведенный выше код выводит следующее с ошибкой:

(None, 1024, 1024, 4)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-77-5a2cf359f3ac> in <module>
      2 
      3 encoded_out = Conv2D(4, (3, 3), activation='relu', padding="same")(input_layer)
----> 4 encoded_out, indices1 = MaxPool2DWithIndices(filter_size=(2,2), strides=(2,2), padding='valid')(encoded_out)
      5 
      6 decoded_out = MaxUnPool2DWithIndices(filter_size=(2,2), strides=(2,2), padding='valid')(encoded_out, indices1)

<ipython-input-76-8a54043c249e> in __call__(self, inputs)
     20         pooled_W = (inputs_shape[2]-self.filter_size[1])//self.strides[1]+1
     21         #if type(inputs_shape[0]) is not int: inputs_shape[0] = 1
---> 22         mpooled = np.zeros((inputs_shape[0], pooled_H, pooled_W, inputs_shape[3]))
     23         indices = np.zeros((inputs_shape[0], pooled_H, pooled_W, inputs_shape[3]))
     24         for n in range(0, inputs_shape[0], 2): # for each example

TypeError: 'NoneType' object cannot be interpreted as an integer

Это, конечно, из-за того, что размер партии неизвестен заранее. Как мне решить эту проблему?

1 Ответ

0 голосов
/ 11 апреля 2020

Для функций __call__ требовались некоторые условия if-else для работы со случаями, такими как input.shape = (None, H, W, d) или input.shape = (None, None, None, d). Решено!

...