Керас: Размеры должны быть равны - PullRequest
0 голосов
/ 07 ноября 2018

Я проводил некоторую классификацию с керасом, когда встретил эту ошибку:

InvalidArgumentError: Dimensions must be equal, but are 256 and 8 for 'dense_185/MatMul' (op: 'MatMul') with input shapes: [?,256], [8,300].

Это удивило меня, потому что размерность входа в плотную равна 1.

Это последовательная модель с несколькими пользовательскими слоями. Я понятия не имею, почему 8 появляется в ошибке плотного слоя.

class Residual(Layer):
    def __init__(self,input_shape,**kwargs):
        super(Residual, self).__init__(**kwargs)
        self.input_shapes = input_shape

    def call(self, x):
        print(np.shape(x)) #    (?, 128, 8) 
        first_layer =   Conv1D(256, 4, activation='relu', input_shape = self.input_shapes)(x)
        print(np.shape(first_layer))     (?, 125, 256)
        x =             Conv1D(256, 4, activation='relu')(first_layer)
        print(np.shape(x)) (?, 122, 256) 
        x =             Conv1D(256, 4, activation='relu')(x)
        print(np.shape(x)) (?, 119, 256)
        x =             ZeroPadding1D(padding=3)(x)
        residual =      Add()([x, first_layer])
        x = Activation("relu")(residual)
        return x

class Pooling(Layer):
    def __init__(self,**kwargs):
        super(Pooling, self).__init__(**kwargs)

    def call(self, x):
        first_layer =   GlobalMaxPooling1D(data_format='channels_last')(x)
        second_layer =  GlobalAveragePooling1D(data_format='channels_last')(x)
        pooling =      Add()([first_layer, second_layer])
        print(np.shape(pooling)) (?, 256)
        return pooling

model = Sequential()
model.add(Residual(input_shape=(128,8)))
model.add(Pooling())
model.add(Dense(300, activation='relu'))
model.add(Dense(150, activation='relu'))
model.add(Dense(10, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer=keras.optimizers.Adadelta(), metrics=['accuracy'])
model.fit(np.array(dataset_data), dataset_target, epochs=1000, validation_split=0.1, verbose=1, batch_size=8)

Размеры:

(1000, 128, 8) - вход (1000 аудио, 8 функций, 128 секв. Длины)

(1000, 10) - цель (1000 аудио, 10 классов)

1 Ответ

0 голосов
/ 09 ноября 2018

Я думаю, что требуется два редактирования:

  1. Добавить InputLayer в качестве входа для данных
  2. Определите метод compute_output_shape как минимум для слоя Pooling ( ссылка ). Если этот метод не определен, слой Dense не может определить, какая форма ввода для него, я думаю, и затем завершается неудачей.

Также есть незначительное редактирование - поскольку модель имеет InputLayer, вам не нужно больше input_shape kwarg в слое Residual.

class Residual(Layer):
    def __init__(self, **kwargs):  # remove input shape
        super(Residual, self).__init__(**kwargs)

    def call(self, x):
        print(np.shape(x))
        first_layer = Conv1D(256, 4, activation='relu')(x)
        print(np.shape(first_layer))    
        x = Conv1D(256, 4, activation='relu')(first_layer)
        print(np.shape(x)) 
        x = Conv1D(256, 4, activation='relu')(x)
        print(np.shape(x)) 
        x = ZeroPadding1D(padding=3)(x)
        residual = Add()([x, first_layer])
        x = Activation("relu")(residual)
        return x


class Pooling(Layer):
    def __init__(self, **kwargs):
        super(Pooling, self).__init__(**kwargs)

    def call(self, x):
        # !!! I build model without data_format argument - my version of keras
        # doesn't support it !!!
        first_layer = GlobalMaxPooling1D(data_format='channels_last')(x)  
        second_layer = GlobalAveragePooling1D(data_format='channels_last')(x)
        pooling = Add()([first_layer, second_layer])
        print(np.shape(pooling)) 
        self.output_dim = int(np.shape(pooling)[-1])  # save output shape
        return pooling

    def compute_output_shape(self, input_shape):
        # compute output shape here
        return (input_shape[0], self.output_dim)  

Инициализация модели:

model = Sequential()
model.add(InputLayer((128,8)))
model.add(Residual())
model.add(Pooling())
model.add(Dense(300, activation='relu'))
model.add(Dense(150, activation='relu'))
model.add(Dense(10, activation='softmax'))
model.compile(loss='categorical_crossentropy', 
              optimizer=keras.optimizers.Adadelta(), 
              metrics=['accuracy'])

Out:
(?, 128, 8)
(?, 125, 256)
(?, 122, 256)
(?, 119, 256)
(?, 256)

Сводная информация о модели (не знаю, почему в Residual и Pooling не отображаются параметры have. Я предполагаю, что для этого класса требуется дополнительный метод для подсчета внутренних параметров):

model.summary()
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
residual_10 (Residual)       (None, 128, 8)            0         
_________________________________________________________________
pooling_8 (Pooling)          (None, 256)               0         
_________________________________________________________________
dense_15 (Dense)             (None, 300)               77100     
_________________________________________________________________
dense_16 (Dense)             (None, 150)               45150     
_________________________________________________________________
dense_17 (Dense)             (None, 10)                1510      
=================================================================
Total params: 123,760
Trainable params: 123,760
Non-trainable params: 0
_________________________________________________________________

Создание поддельных данных и проверка процесса обучения:

dataset_data = np.random.randn(1000, 128, 8)
dataset_target = np.zeros((1000, 10))
dataset_target[:, 0] = 1
model.fit(np.array(dataset_data), dataset_target, epochs=1000,
          validation_split=0.1, verbose=1, batch_size=8)
Train on 900 samples, validate on 100 samples
Epoch 1/1000
900/900 [==============================] - 2s 2ms/step - loss: 0.0235 - acc: 0.9911 - val_loss: 9.4426e-05 - val_acc: 1.0000
Epoch 2/1000
900/900 [==============================] - 1s 1ms/step - loss: 4.2552e-05 - acc: 1.0000 - val_loss: 1.7458e-05 - val_acc: 1.0000
Epoch 3/1000
900/900 [==============================] - 1s 1ms/step - loss: 1.1342e-05 - acc: 1.0000 - val_loss: 7.3141e-06 - val_acc: 1.0000
... and so on

Похоже, это работает.

...