Автоэнкодер CNN с неквадратичными входными формами

#tensorflow #keras #conv-neural-network #autoencoder

Вопрос:

Я реализовал автоэнкодер CNN, который не имеет входных данных квадратной формы. Я немного сбит с толку. Обязательно ли иметь ввод в квадратной форме для автоэнкодеров ? Каждое из 2D — изображений имеет форму 800×20. Я ввел данные в соответствии с формой. Но почему-то формы не совпадают при построении модели. Я поделился кодом модели и сообщением об ошибке ниже. Нужна ваша экспертная консультация. Спасибо.

 x = Input(shape=(800, 20,1)) 

# Encoder
conv1_1 = Conv2D(16, (3, 3), activation='relu', padding='same')(x)
pool1 = MaxPooling2D((2, 2), padding='same')(conv1_1)
conv1_2 = Conv2D(8, (3, 3), activation='relu', padding='same')(pool1)
pool2 = MaxPooling2D((2, 2), padding='same')(conv1_2)
conv1_3 = Conv2D(8, (3, 3), activation='relu', padding='same')(pool2)
h = MaxPooling2D((2, 2), padding='same')(conv1_3)

# Decoder
conv2_1 = Conv2D(8, (3, 3), activation='relu', padding='same')(h)
up1 = UpSampling2D((2, 2))(conv2_1)
conv2_2 = Conv2D(8, (3, 3), activation='relu', padding='same')(up1)
up2 = UpSampling2D((2, 2))(conv2_2)
conv2_3 = Conv2D(16, (3, 3), activation='relu', padding='same')(up2)
up3 = UpSampling2D((2, 2))(conv2_3)
r = Conv2D(1, (3, 3), activation='sigmoid', padding='same')(up3)

model = Model(inputs=x, outputs=r)
model.compile(optimizer='adadelta', loss='binary_crossentropy', metrics=['accuracy'])

results = model.fit(x_train, x_train, epochs = 500, batch_size=16,validation_data= (x_test, x_test))
 

Вот ошибка:

     ValueError: logits and labels must have the same shape ((16, 800, 24, 1) vs (16, 800, 20, 1))
 

Комментарии:

1. Не могли бы вы также поделиться полученным сообщением об ошибке? Как правило, автокодеры работают также с входами «неквадратичной» формы

2. Пожалуйста, не показывайте код/ошибки в виде изображений, включите текст в сам вопрос. И вы должны включить свой вызов model.fit.

3. @Dr. Snoopy Я обновил сообщение и добавил ошибку и подгонку. Пожалуйста, взгляните сейчас.

4. Что такое y_train здесь? Предполагается, что автокодеры восстанавливают входные данные, поэтому вы не предоставляете дополнительные метки для задачи.

5. @Доктор Снупи Спасибо, что выяснил это. Но все равно я получаю ту же ошибку после замены y_train на x_train. Я обновил код ошибки. Пожалуйста, взгляните.

Ответ №1:

Как показывает трассировка ошибок, проблема, с которой вы сталкиваетесь при попытке работать с этим автоэнкодером, заключается в том, что модель ожидает, что форма ввода будет (?, 800, 20, 1) , но форма вывода будет (?, 796, 20, 1) . В то время как он получает каждое входное и выходное изображение в виде

(800, 20, 1) . (Проверьте форму ввода и вывода сводки вашей модели!)

Мои Рекомендации —

  1. Я исправил padding = 'same' и перенастроил формы так, чтобы форма входного тензора и выход были одинаковыми. Проверьте размеры ядра, которые я изменил, чтобы получить выходную форму по мере необходимости.
  2. Кроме того, для многоуровневой архитектуры кодера-декодера conv (такой как автоматический кодер) рекомендуется преобразовать пространственную информацию в карты объектов/фильтры/каналы с последующими слоями. Прямо сейчас вы начинаете с 8 фильтров, затем переходите к 4 в кодере. Это должно быть больше похоже 4->8->16 . Проверьте эту диаграмму для ссылки на интуицию.

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

С учетом приведенных выше рекомендаций я внес здесь изменения.

 x = Input(shape=(800, 20,1)) 

# Encoder
conv1_1 = Conv2D(4, (3, 3), activation='relu', padding='same')(x)
pool1 = MaxPooling2D((2, 2), padding='same')(conv1_1)
conv1_2 = Conv2D(8, (3, 3), activation='relu', padding='same')(pool1)
pool2 = MaxPooling2D((2, 2), padding='same')(conv1_2)
conv1_3 = Conv2D(16, (3, 3), activation='relu', padding='same')(pool2)
h = MaxPooling2D((2, 1), padding='same')(conv1_3) #<------

# # Decoder

conv2_1 = Conv2D(16, (3, 3), activation='relu', padding='same')(h)
up1 = UpSampling2D((2, 2))(conv2_1)
conv2_2 = Conv2D(8, (3, 3), activation='relu', padding='same')(up1)
up2 = UpSampling2D((2, 2))(conv2_2)
conv2_3 = Conv2D(4, (3, 3), activation='sigmoid', padding='same')(up2) #<--- ADD PADDING HERE
up3 = UpSampling2D((2, 1))(conv2_3)
r = Conv2D(1, (3, 3), activation='sigmoid', padding='same')(up3)

model = Model(inputs=x, outputs=r)
model.compile(optimizer='adadelta', loss='binary_crossentropy', metrics=['accuracy'])
model.summary()
 
 Model: "model_13"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_16 (InputLayer)        [(None, 800, 20, 1)]      0         
_________________________________________________________________
conv2d_101 (Conv2D)          (None, 800, 20, 4)        40        
_________________________________________________________________
max_pooling2d_45 (MaxPooling (None, 400, 10, 4)        0         
_________________________________________________________________
conv2d_102 (Conv2D)          (None, 400, 10, 8)        296       
_________________________________________________________________
max_pooling2d_46 (MaxPooling (None, 200, 5, 8)         0         
_________________________________________________________________
conv2d_103 (Conv2D)          (None, 200, 5, 16)        1168      
_________________________________________________________________
max_pooling2d_47 (MaxPooling (None, 100, 5, 16)        0         
_________________________________________________________________
conv2d_104 (Conv2D)          (None, 100, 5, 16)        2320      
_________________________________________________________________
up_sampling2d_43 (UpSampling (None, 200, 10, 16)       0         
_________________________________________________________________
conv2d_105 (Conv2D)          (None, 200, 10, 8)        1160      
_________________________________________________________________
up_sampling2d_44 (UpSampling (None, 400, 20, 8)        0         
_________________________________________________________________
conv2d_106 (Conv2D)          (None, 400, 20, 4)        292       
_________________________________________________________________
up_sampling2d_45 (UpSampling (None, 800, 20, 4)        0         
_________________________________________________________________
conv2d_107 (Conv2D)          (None, 800, 20, 1)        37        
=================================================================
Total params: 5,313
Trainable params: 5,313
Non-trainable params: 0
_________________________________________________________________
 

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

 x_train = np.random.random((16,800,20,1))

model.fit(x_train, x_train, epochs=2)
 
 Epoch 1/2
1/1 [==============================] - 0s 180ms/step - loss: 0.7526 - accuracy: 0.0000e 00
Epoch 2/2
1/1 [==============================] - 0s 189ms/step - loss: 0.7526 - accuracy: 0.0000e 00
<tensorflow.python.keras.callbacks.History at 0x7fa85a9896d0>
 

Комментарии:

1. Спасибо за ваш подробный ответ. Я изменил свою модель в соответствии с вашим предложением, и она работает только в течение одной эпохи, а затем снова та же ошибка. Ошибка значения: логины и метки должны иметь одинаковую форму ((Нет, 800, 20, 1) против (Нет, 3))

2. можете ли вы распечатать форму изображений X_train и y_train? Я думаю, что это связано с вашими формами данных для обучения. Я могу запускать эпохи для случайно сгенерированных данных

3. Кроме того, в validation = (x_test, y_test) , измените его на (x_test, x_test)

4. добавил к ответу свою эпоху. вы можете видеть, что он работает для фигуры (16, 800,20,1) как x_train

5. Это сработало после изменения validation = (x_test, x_test). Спасибо Акшай 🙂