Я пытаюсь воссоздать CNN в Keras для классификации данных облака точек. CNN описывается в этой статье.
Сетевой дизайн
Это моя текущая реализация:
inputs = Input(shape=(None, 3))
x = Conv1D(filters=64, kernel_size=1, activation='relu')(inputs)
x = BatchNormalization()(x)
x = Conv1D(filters=64, kernel_size=1, activation='relu')(x)
x = BatchNormalization()(x)
y = Conv1D(filters=64, kernel_size=1, activation='relu')(x)
y = BatchNormalization()(y)
y = Conv1D(filters=128, kernel_size=1, activation='relu')(y)
y = BatchNormalization()(y)
y = Conv1D(filters=2048, kernel_size=1, activation='relu')(y)
y = MaxPooling1D(1)(y)
z = keras.layers.concatenate([x, y], axis=2)
z = Conv1D(filters=512, kernel_size=1, activation='relu')(z)
z = BatchNormalization()(z)
z = Conv1D(filters=512, kernel_size=1, activation='relu')(z)
z = BatchNormalization()(z)
z = Conv1D(filters=512, kernel_size=1, activation='relu')(z)
z = BatchNormalization()(z)
z = Dense(9, activation='softmax')(z)
model = Model(inputs=inputs, outputs=z)
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
Проблема в том, что сеть прогнозирует один и тот же класс для всех входных данных. Это может быть вызвано ошибкой в моей реализации сети, переполнением или недостаточной подготовкой данных. Может кто-то заметить ошибку в моей реализации?
Тот же класс вывода обычно указывает на только что инициализированную сеть, что означает, что учебные веса не загружаются. Произошло ли это во время обучения такое же дело? Однако другая причина может быть плохой предварительной обработкой. Еще одна вещь, которую я заметил, заключается в том, что в документе говорится "1D-полностью сверточная сеть". Ваш плотный слой является сверточным в статье.
Сеть фиксирована, так как она дает ожидаемые прогнозы. Спасибо за помощь!
Основываясь на ответах, я изменил следующие вещи:
Я также добавил параметр training=True
для уровня нормализации партии
Код правильной реализации:
inputs = Input(shape=(None, 3))
x = Conv1D(filters=64, kernel_size=1, input_shape=(None, 4))(inputs)
x = BatchNormalization()(x, training=True)
x = Activation('relu')(x)
x = Conv1D(filters=64, kernel_size=1, use_bias=False)(x)
x = BatchNormalization()(x, training=True)
x = Activation('relu')(x)
y = Conv1D(filters=64, kernel_size=1)(x)
y = BatchNormalization()(y, training=True)
y = Activation('relu')(y)
y = Conv1D(filters=128, kernel_size=1)(y)
y = BatchNormalization()(y, training=True)
y = Activation('relu')(y)
y = Conv1D(filters=2048, kernel_size=1)(y)
y = BatchNormalization()(y, training=True)
y = Activation('relu')(y)
y = MaxPooling1D(1)(y)
z = keras.layers.concatenate([x, y], axis=2)
z = Conv1D(filters=512, kernel_size=1)(z)
z = BatchNormalization()(z, training=True)
z = Activation('relu')(z)
z = Conv1D(filters=512, kernel_size=1)(z)
z = BatchNormalization()(z, training=True)
z = Activation('relu')(z)
z = Conv1D(filters=512, kernel_size=1)(z)
z = BatchNormalization()(z, training=True)
z = Activation('relu')(z)
z = Conv1D(filters=2, kernel_size=1, activation='softmax')(z)
model = Model(inputs=inputs, outputs=z)
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
Я считаю, что ошибка не в реализации. Скорее всего, проблема в том, что у вас недостаточно данных. Кроме того, если сеть прогнозирует один и тот же класс для всех входных данных, это обычно означает, что вам не хватает регуляризации. Попробуйте добавить несколько слоев Dropout
с отсечением от 0.2
до 0.5
и посмотреть, улучшились ли результаты.
Кроме того, я не думаю, что
x = Conv1D(filters=64, kernel_size=1, activation='relu')(inputs)
x = BatchNormalization()(x)
такой же как
x = Conv1D(filters=64, kernel_size=1)(inputs)
x = BatchNormalization()(x)
x = ReLU(x)
и я думаю, что вам нужен последний.
Еще одна вещь для вас - LeakyReLU, поскольку она обычно дает лучшие результаты, чем обычный ReLU.