Потери не развиваются при использовании пропущенных соединений

Я пытаюсь реализовать этот документ в Keras: https://arxiv.org/pdf/1603.09056.pdf, который использует Conv-Deconv с пропуском соединений для создания сети шумоподавления изображения. Моя сеть работает довольно хорошо, если я создаю симметричные пропускные соединения между соответствующими слоями Conv-Deconv, но если я добавляю соединение между входом и выходом (как в статье), мою сеть невозможно обучить. Это я не понимаю бумагу?

«Однако наша сеть учится аддитивному искажению на входе, поскольку между входом и выходом сети существует пропускная связь».

Вот сеть, описанная в статье:

введите здесь описание изображения

А вот и моя сеть:

input_img = Input(shape=(None,None,3))

############################
####### CONVOLUTIONS #######
############################

c1 = Convolution2D(64, (3, 3))(input_img)
a1 = Activation('relu')(c1)

c2 = Convolution2D(64, (3, 3))(a1)
a2 = Activation('relu')(c2)

c3 = Convolution2D(64, (3, 3))(a2)
a3 = Activation('relu')(c3)

c4 = Convolution2D(64, (3, 3))(a3)
a4 = Activation('relu')(c4)

c5 = Convolution2D(64, (3, 3))(a4)
a5 = Activation('relu')(c5)

############################
###### DECONVOLUTIONS ######
############################

d1 = Conv2DTranspose(64, (3, 3))(a5)
a6 = Activation('relu')(d1)

m1 = add([a4, a6])
a7 = Activation('relu')(m1)

d2 = Conv2DTranspose(64, (3, 3))(a7)
a8 = Activation('relu')(d2)

m2 = add([a3, a8])
a9 = Activation('relu')(m2)

d3 = Conv2DTranspose(64, (3, 3))(a9)
a10 = Activation('relu')(d3)

m3 = add([a2, a10])
a11 = Activation('relu')(m3)

d4 = Conv2DTranspose(64, (3, 3))(a11)
a12 = Activation('relu')(d4) 

m4 = add([a1, a12])
a13 = Activation('relu')(m4)

d5 = Conv2DTranspose(3, (3, 3))(a13)
a14 = Activation('relu')(d5)

m5 = add([input_img, a14]) # Everything goes well without this line
out = Activation('relu')(m5)

model = Model(input_img, out) 
model.compile(optimizer='adam', loss='mse')

Если я тренирую его, вот что я получаю:

Epoch 1/10
31250/31257 [============================>.] - ETA: 0s - loss: 0.0015
Current PSNR: 28.1152534485

31257/31257 [==============================] - 89s - loss: 0.0015 - val_loss: 0.0015
Epoch 2/10
31250/31257 [============================>.] - ETA: 0s - loss: 0.0015
Current PSNR: 28.1152534485

31257/31257 [==============================] - 89s - loss: 0.0015 -  val_loss: 0.0015
Epoch 3/10
31250/31257 [============================>.] - ETA: 0s - loss: 0.0015
Current PSNR: 28.1152534485

31257/31257 [==============================] - 89s - loss: 0.0015 -   val_loss: 0.0015
Epoch 4/10
31250/31257 [============================>.] - ETA: 0s - loss: 0.0015
Current PSNR: 28.1152534485

31257/31257 [==============================] - 89s - loss: 0.0015 - val_loss: 0.0015
Epoch 5/10
31250/31257 [============================>.] - ETA: 0s - loss: 0.0015
Current PSNR: 28.1152534485

Что не так с моей сетью?


person Nathan Hubens    schedule 31.08.2017    source источник
comment
Но ваши потери довольно малы. Почему вы утверждаете, что это не обучение?   -  person Marcin Możejko    schedule 31.08.2017
comment
Потому что потеря не развивается? Разве это не должно быть сведено к минимуму постепенно?   -  person Nathan Hubens    schedule 01.09.2017


Ответы (1)


Активация 'relu' никогда не возвращает отрицательное значение.

Поскольку вы добавляете входные данные к выходным (a14) и вам необходимо «подавить шум» (удалить шум), вполне ожидаемо, что выходные данные (a14) будут содержать как положительные, так и отрицательные< /сильные> значения. (Вы хотите затемнить светлые пятна и осветлить темные пятна).

Из-за этого активация в a14 не может быть 'relu'. Это должно быть что-то как положительное, так и отрицательное, способное достигать диапазона шума. Вероятно, 'tanh' или пользовательская активация. Если ваш ввод идет от 0 до 1, 'tanh', вероятно, будет лучшим вариантом.

(Не уверен насчет предыдущих слоев, возможно, некоторые из них, использующие 'tanh', упростят процесс)


Иногда эти длинные сверточные сети застревают, я тренирую здесь U-сеть, и потребовалось некоторое время, чтобы заставить ее сходиться. Когда он застревает, иногда лучше построить модель заново (инициализация новых весов) и повторить попытку.

Подробнее см. здесь: Как построить мульти- класс сверточной нейронной сети с Keras

person Daniel Möller    schedule 31.08.2017