Как сгладить данные разного размера в Keras и использовать их в следующих слоях

Я хотел бы построить CNN, которая может быть матрицей каналов с постоянным количеством строк, но с переменным количеством столбцов. Я начал с этого блога но в какой-то момент он использует слой Flatten. Согласно этой проблеме GitHub, слой Flatten нельзя использовать с не полностью данные, определяемые формой. Я использовал этот ответ для создания CNN следующим образом:

from keras import Input, Model
from keras.layers import Conv2D, MaxPooling2D, Dense, Dropout, Lambda, Activation
from keras.optimizers import SGD
import keras.backend as K

input = Input(shape=(None, 60, 1))
        x = Conv2D(list_of_neurons[0], (3, 3), padding='same', activation='relu')(input)
        x = MaxPooling2D(pool_size=(2, 2))(x) # None x 30

        x = Conv2D(list_of_neurons[1], (3, 3), padding='same', activation='relu')(x)
        x = MaxPooling2D(pool_size=(2, 2))(x) # None x 15

        x = Conv2D(list_of_neurons[2], (3, 3), padding='same', activation='relu')(x)
        x = MaxPooling2D(pool_size=(3, 3))(x) # None x 5

        x = Lambda(lambda k: K.batch_flatten(k))(x)
        x = Dense(list_of_neurons[3])(x)
        x = Activation("relu")(x)
        x = Dropout(dropout)(x)
        output = Dense(1, activation='sigmoid')(x)

        self._model = Model(inputs=input, outputs=output)
        self._model.compile(loss='binary_crossentropy', optimizer='rmsprop', metrics=['accuracy'])
        self._model.summary()

Однако, когда я пытаюсь запустить скрипт, возникает ошибка:

Traceback (most recent call last):
  File "/home/kuba/Dropbox/MGR Jakub Kustra/implementacja/first_cnn.py", line 66, in <module>
    mlp = MLP([60, 60, 120, 120], 0.3)
  File "/home/kuba/Dropbox/MGR Jakub Kustra/implementacja/models.py", line 22, in __init__
    x = Dense(list_of_neurons[3])(x)
  File "/home/kuba/anaconda3/lib/python3.6/site-packages/keras/engine/topology.py", line 576, in __call__
    self.build(input_shapes[0])
  File "/home/kuba/anaconda3/lib/python3.6/site-packages/keras/layers/core.py", line 830, in build
    constraint=self.kernel_constraint)
  File "/home/kuba/anaconda3/lib/python3.6/site-packages/keras/legacy/interfaces.py", line 87, in wrapper
    return func(*args, **kwargs)
  File "/home/kuba/anaconda3/lib/python3.6/site-packages/keras/engine/topology.py", line 397, in add_weight
    weight = K.variable(initializer(shape),
  File "/home/kuba/anaconda3/lib/python3.6/site-packages/keras/initializers.py", line 204, in __call__
    scale /= max(1., float(fan_in + fan_out) / 2)
TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'

Ошибка возникает в этой строке в initializers.py:

def __call__(self, shape, dtype=None):
    fan_in, fan_out = _compute_fans(shape)
    scale = self.scale
    if self.mode == 'fan_in':
        scale /= max(1., fan_in)
    elif self.mode == 'fan_out':
        scale /= max(1., fan_out)
    else:
        scale /= max(1., float(fan_in + fan_out) / 2) # <<<<<<<< HERE
    if self.distribution == 'normal':
        stddev = np.sqrt(scale)
        return K.truncated_normal(shape, 0., stddev,
                                  dtype=dtype, seed=self.seed)
    else:
        limit = np.sqrt(3. * scale)
        return K.random_uniform(shape, -limit, limit,
                                dtype=dtype, seed=self.seed)

переменная fan_in равна None. Я думал, что слой Dense можно кормить данными разного размера. Как я могу преодолеть это?


person Colonder    schedule 13.01.2018    source источник


Ответы (1)


К сожалению, ваш сценарий невозможно реализовать по простой причине: за вашим Flatten следует слой Dense. Для того, чтобы выделить тензор для слоя Dense, почему теперь входная фигура - поскольку распределитель должен выделить матрицу весов формы (input_shape, output_shape). Отсюда ваша ошибка.

Решение, представленное в вопросе, который вы предоставили, решило немного другую задачу. Проблема там была связана с тем, что иногда необходимо указать форму партии, и это проблема, которую batch_flatten стремится решить.

person Marcin Możejko    schedule 14.01.2018
comment
Могу ли я добиться этого другим способом? Например, как описано здесь в разделе Преобразование слоев FC в слои CONV cs231n.github.io/convolutional -сети/#convert - person Colonder; 14.01.2018
comment
Вы можете применить либо GlobalMaxPooling2D, либо GlobalAveragePooling2D вместо Flatten - person Marcin Możejko; 14.01.2018
comment
Честно говоря, раньше я использовал GlobalMaxPooling2D вместо Flatten, но разве тогда я не теряю много информации? - person Colonder; 14.01.2018
comment
С вашим дизайном это может иметь место, поскольку рецептивные поля вашей сети относительно малы. Но любой другой подход потребует сложного дизайна пользовательского слоя. - person Marcin Możejko; 14.01.2018