Как реализовать одномерную сверточную нейронную сеть с остаточными соединениями и пакетной нормализацией в Керасе? - PullRequest
0 голосов
/ 24 сентября 2018

Я пытаюсь разработать сверточную нейронную сеть 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 и заполнением = одинаковыми, без применения MaxPooling1D.Любые изменения в этих параметрах приводят к несоответствию размера тензора и невозможности компиляции со следующей ошибкой:

ValueError: Operands could not be broadcast together with shapes (70, 64) (70, 128)

Кто-нибудь знает, как исправить это несоответствие размера и заставить его работать?

Кроме того, если вход имеет более одного канала (или функции), несоответствие еще хуже!Есть ли способ справиться с более чем одним каналом?

1 Ответ

0 голосов
/ 26 сентября 2018

Проблема несоответствия формы тензора должна возникать в слое add([y, shortcut]).Из-за того, что вы используете слой MaxPooling1D, это сокращает ваши временные шаги по умолчанию вдвое, и вы можете изменить его, используя параметр pool_size.С другой стороны, ваша остаточная часть не сокращает временные шаги на ту же величину.Вы должны применить stride=2 с padding='same' перед добавлением shortcut и y в любой из слоев Conv1D (желательно последний).

Для справки, вы можете проверить код Resnet здесь Keras-приложения-GitHub

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...