Как реализовать одномерную сверточную нейронную сеть с остаточными соединениями и пакетной нормализацией в Keras?
Я пытаюсь разработать 1D сверточную нейронную сеть с остаточными связями и нормализацией партии, основанную на статье " Обнаружение аритмии на уровне кардиолога с помощью сверточных нейронных сетей, используя керасы". Это код до сих пор:
# define model
x = Input(shape=(time_steps, n_features))
# First Conv / BN / ReLU layer
y = Conv1D(filters=n_filters, kernel_size=n_kernel, strides=n_strides, padding='same')(x)
y = BatchNormalization()(y)
y = ReLU()(y)
shortcut = MaxPooling1D(pool_size = n_pool)(y)
# First Residual block
y = Conv1D(filters=n_filters, kernel_size=n_kernel, strides=n_strides, padding='same')(y)
y = BatchNormalization()(y)
y = ReLU()(y)
y = Dropout(rate=drop_rate)(y)
y = Conv1D(filters=n_filters, kernel_size=n_kernel, strides=n_strides, padding='same')(y)
# Add Residual (shortcut)
y = add([shortcut, y])
# Repeated Residual blocks
for k in range (2,3): # smaller network for testing
shortcut = MaxPooling1D(pool_size = n_pool)(y)
y = BatchNormalization()(y)
y = ReLU()(y)
y = Dropout(rate=drop_rate)(y)
y = Conv1D(filters=n_filters * k, kernel_size=n_kernel, strides=n_strides, padding='same')(y)
y = BatchNormalization()(y)
y = ReLU()(y)
y = Dropout(rate=drop_rate)(y)
y = Conv1D(filters=n_filters * k, kernel_size=n_kernel, strides=n_strides, padding='same')(y)
y = add([shortcut, y])
z = BatchNormalization()(y)
z = ReLU()(z)
z = Flatten()(z)
z = Dense(64, activation='relu')(z)
predictions = Dense(classes, activation='softmax')(z)
model = Model(inputs=x, outputs=predictions)
# Compiling
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['categorical_accuracy'])
# Fitting
model.fit(train_x, train_y, epochs=n_epochs, batch_size=n_batch)
И это график упрощенной модели того, что я пытаюсь построить.
Модель, описанная в статье, использует возрастающее количество фильтров:
Сеть состоит из 16 остаточных блоков с 2 сверточными слоями на блок. Все сверточные слои имеют длину фильтра 16 и имеют фильтры 64k, где k начинается с 1 и увеличивается с каждым 4-м остаточным блоком. Каждый альтернативный остаточный блок выполняет выборку своих входных данных с коэффициентом 2, таким образом, исходный входной сигнал в конечном итоге субдискретизируется с коэффициентом 2^8. Когда остаточный блок выполняет выборку входных данных, соответствующие соединения быстрого доступа также производят выборку своих входных данных, используя операцию "Максимальное объединение" с тем же коэффициентом выборки.
Но я могу заставить его работать, только если я использую одинаковое количество фильтров в каждом слое Conv1D, с k=1, шагами = 1 и padding= одинаково, без применения MaxPooling1D. Любые изменения в этих параметрах приводят к несоответствию размера тензора и невозможности компиляции со следующей ошибкой:
ValueError: Operands could not be broadcast together with shapes (70, 64) (70, 128)
У кого-нибудь есть идеи, как исправить это несоответствие размера и заставить его работать?
Кроме того, если на входе имеется более одного канала (или функций), несоответствие еще хуже! Есть ли способ справиться с более чем одним каналом?
1 ответ
Проблема несоответствия формы тензора должна происходить в add([y, shortcut])
слой. Из-за того, что вы используете слой MaxPooling1D, это сокращает ваши временные шаги по умолчанию вдвое, и вы можете изменить его, используя pool_size
параметр. С другой стороны, ваша остаточная часть не сокращает временные шаги на ту же величину. Вы должны подать заявку stride=2
с padding='same'
перед добавлением shortcut
а также y
в любом из слоев Conv1D (предпочтительно последний).
Для справки вы можете проверить код Resnet здесь Keras -Applications-Github