добавление данных в декодер в автоэнкодере во время обучения - PullRequest
0 голосов
/ 14 сентября 2018

Я хочу реализовать автоэнкодер с использованием Keras, и эта структура представляет собой большую сеть, в которой некоторые операции выполняются на выходе автоэнкодера, и затем мы должны рассмотреть две потери. Я прикрепил изображение, которое показывает мою предложенную структуру.ссылка ниже.

структура автоэнкодера

w имеет тот же размер, что и входное изображение, и в этом автоэнкодере я не использую максимальное объединение, поэтому выходные данные каждогоФаза имеет тот же размер, что и входное изображение.Я хочу отправить w и представление скрытого пространства в часть декодера, а затем после добавления шума к выходу декодера попытаться извлечь w, используя третью часть сети.поэтому мне нужно, чтобы моя функция потерь учитывала разницу между входным изображением и отображением скрытого пространства, а также между w и w '.но у меня есть несколько проблем с реализацией.Я не знаю, как я могу добавить w к выходу декодера, из-за использования этой строки "merge_encoded_w = cv2.merge (encoded, w)" выдает ошибку и не работает.Я не уверен, что моя функция потери верна в зависимости от того, что мне нужно или нет? Пожалуйста, помогите мне с этим кодом.Я новичок, и мне трудно найти решение.Я задавал этот вопрос раньше, но никто не помог мне с этим.пожалуйста, направь меня.мой код, как показано ниже:

from keras.models import Sequential
from keras.layers import Input, Dense, Dropout, Activation,UpSampling2D,Conv2D, MaxPooling2D, GaussianNoise
from keras.models import Model
from keras.optimizers import SGD
from keras.datasets import mnist
from keras import regularizers
from keras import backend as K
import keras as k
import numpy as np
import matplotlib.pyplot as plt
import cv2
from time import time
from keras.callbacks import TensorBoard
# Embedding phase
##encoder

w=np.random.random((1, 28,28))
input_img = Input(shape=(28, 28, 1))  # adapt this if using `channels_first` image data format

x = Conv2D(8, (5, 5), activation='relu', padding='same')(input_img)
#x = MaxPooling2D((2, 2), padding='same')(x)
x = Conv2D(4, (3, 3), activation='relu', padding='same')(x)
#x = MaxPooling2D((2, 2), padding='same')(x)
x = Conv2D(2, (3, 3), activation='relu', padding='same')(x)
encoded = Conv2D(1, (3, 3), activation='relu', padding='same')(x)
merge_encoded_w=cv2.merge(encoded,w)
#
#decoder

x = Conv2D(2, (5, 5), activation='relu', padding='same')(merge_encoded_w)
#x = UpSampling2D((2, 2))(x)
x = Conv2D(4, (3, 3), activation='relu', padding='same')(x)
#x = UpSampling2D((2, 2))(x)
x = Conv2D(8, (3, 3), activation='relu',padding='same')(x)
#x = UpSampling2D((2, 2))(x)
decoded = Conv2D(1, (3, 3), activation='sigmoid', padding='same')(x)

#Extraction phase
decodedWithNois=k.layers.GaussianNoise(0.5)(decoded)
x = Conv2D(8, (5, 5), activation='relu', padding='same')(decodedWithNois)
#x = MaxPooling2D((2, 2), padding='same')(x)
x = Conv2D(4, (3, 3), activation='relu', padding='same')(x)
#x = MaxPooling2D((2, 2), padding='same')(x)
final_image_watermark = Conv2D(2, (3, 3), activation='relu', padding='same')(x)


autoencoder = Model([input_img,w], [decoded,final_image_watermark(2)])
encoder=Model(input_img,encoded)
autoencoder.compile(optimizer='adadelta', loss=['mean_squared_error','mean_squared_error'],metrics=['accuracy'])
(x_train, _), (x_test, _) = mnist.load_data()
x_validation=x_train[1:10000,:,:]
x_train=x_train[10001:60000,:,:]
#
x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.
x_validation = x_validation.astype('float32') / 255.
x_train = np.reshape(x_train, (len(x_train), 28, 28, 1))  # adapt this if using `channels_first` image data format
x_test = np.reshape(x_test, (len(x_test), 28, 28, 1))  # adapt this if using `channels_first` image data format
x_validation = np.reshape(x_validation, (len(x_validation), 28, 28, 1))  # adapt this if using `channels_first` image data format
autoencoder.fit(x_train, x_train,
                epochs=5,
                batch_size=128,
                shuffle=True,
                validation_data=(x_validation, x_validation),
                callbacks=[TensorBoard(log_dir='/tmp/autoencoder')])

decoded_imgs = autoencoder.predict(x_test)
encoded_imgs=encoder.predict(x_test)

1 Ответ

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

Для такого рода большой архитектуры я предлагаю вам строить из маленьких кусочков, а затем соединять их вместе. Во-первых, часть кодера. Он получает изображение размером (28,28,1) и возвращает закодированное изображение формы (28,28,1).

from keras.layers import Input, Concatenate, GaussianNoise
from keras.layers import Conv2D
from keras.models import Model

def make_encoder():
    image = Input((28, 28, 1))
    x = Conv2D(8, (5, 5), activation='relu', padding='same')(image)
    x = Conv2D(4, (3, 3), activation='relu', padding='same')(x)
    x = Conv2D(2, (3, 3), activation='relu', padding='same')(x)
    encoded =  Conv2D(1, (3, 3), activation='relu', padding='same')(x)

    return Model(inputs=image, outputs=encoded)
encoder = make_encoder()
encoder.summary()

#_________________________________________________________________
#Layer (type)                 Output Shape              Param #   
#=================================================================
#input_1 (InputLayer)         (None, 28, 28, 1)         0         
#_________________________________________________________________
#conv2d_1 (Conv2D)            (None, 28, 28, 8)         208       
_________________________________________________________________
#conv2d_2 (Conv2D)            (None, 28, 28, 4)         292       
#_________________________________________________________________
#conv2d_3 (Conv2D)            (None, 28, 28, 2)         74        
#_________________________________________________________________
#conv2d_4 (Conv2D)            (None, 28, 28, 1)         19        
#=================================================================
#Total params: 593
#Trainable params: 593
#Non-trainable params: 0
#_________________________________________________________________

Переход формы соответствует теории.
Затем часть декодера получает закодированный слитый с другим массивом shape (28, 28, 2) и, наконец, восстанавливает исходное изображение shape (28, 28, 1).

def make_decoder():
    encoded_merged = Input((28, 28, 2))
    x = Conv2D(2, (5, 5), activation='relu', padding='same')(encoded_merged)
    x = Conv2D(4, (3, 3), activation='relu', padding='same')(x)
    x = Conv2D(8, (3, 3), activation='relu',padding='same')(x)
    decoded = Conv2D(1, (3, 3), activation='sigmoid', padding='same')(x) 

    return Model(inputs=encoded_merged, outputs=decoded)
decoder = make_decoder()
decoder.summary()

#_________________________________________________________________
#Layer (type)                 Output Shape              Param #   
#=================================================================
#input_2 (InputLayer)         (None, 28, 28, 2)         0         
#_________________________________________________________________
#conv2d_5 (Conv2D)            (None, 28, 28, 2)         102       
#_________________________________________________________________
#conv2d_6 (Conv2D)            (None, 28, 28, 4)         76        
#_________________________________________________________________
#conv2d_7 (Conv2D)            (None, 28, 28, 8)         296       
#_________________________________________________________________
#conv2d_8 (Conv2D)            (None, 28, 28, 1)         73        
#=================================================================
#Total params: 547
#Trainable params: 547
#Non-trainable params: 0
#_________________________________________________________________

Затем модель пытается восстановить массив W. Ввод - восстановленное изображение плюс шум (форма (28, 28, 1)).

def make_w_predictor():
    decoded_noise = Input((28, 28, 1))
    x = Conv2D(8, (5, 5), activation='relu', padding='same')(decoded_noise)
    x = Conv2D(4, (3, 3), activation='relu', padding='same')(x)
    pred_w = Conv2D(1, (3, 3), activation='relu', padding='same')(x)  
    # reconsider activation (is W positive?)
    # should be filter=1 to match W
    return Model(inputs=decoded_noise, outputs=pred_w)

w_predictor = make_w_predictor()
w_predictor.summary()

#_________________________________________________________________
#Layer (type)                 Output Shape              Param #   
#=================================================================
#input_3 (InputLayer)         (None, 28, 28, 1)         0         
#_________________________________________________________________
#conv2d_9 (Conv2D)            (None, 28, 28, 8)         208       
#_________________________________________________________________
#conv2d_10 (Conv2D)           (None, 28, 28, 4)         292       
#_________________________________________________________________
#conv2d_11 (Conv2D)           (None, 28, 28, 1)         37        
#=================================================================
#Total params: 537
#Trainable params: 537
#Non-trainable params: 0
#_________________________________________________________________

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

def put_together(encoder, decoder, w_predictor):
    image = Input((28, 28, 1))
    w = Input((28, 28, 1))
    encoded = encoder(image)

    encoded_merged = Concatenate(axis=3)([encoded, w])
    decoded = decoder(encoded_merged)

    decoded_noise = GaussianNoise(0.5)(decoded)
    pred_w = w_predictor(decoded_noise)

    return Model(inputs=[image, w], outputs=[decoded, pred_w])

model = put_together(encoder, decoder, w_predictor)
model.summary()

#__________________________________________________________________________________________________
#Layer (type)                    Output Shape         Param #     Connected to                     
#==================================================================================================
#input_4 (InputLayer)            (None, 28, 28, 1)    0                                            
#__________________________________________________________________________________________________
#model_1 (Model)                 (None, 28, 28, 1)    593         input_4[0][0]                    
#__________________________________________________________________________________________________
#input_5 (InputLayer)            (None, 28, 28, 1)    0                                            
#__________________________________________________________________________________________________
#concatenate_1 (Concatenate)     (None, 28, 28, 2)    0           model_1[1][0]                    
#                                                                 input_5[0][0]                    
#__________________________________________________________________________________________________
#model_2 (Model)                 (None, 28, 28, 1)    547         concatenate_1[0][0]              
#__________________________________________________________________________________________________
#gaussian_noise_1 (GaussianNoise (None, 28, 28, 1)    0           model_2[1][0]                    
#__________________________________________________________________________________________________
#model_3 (Model)                 (None, 28, 28, 1)    537         gaussian_noise_1[0][0]           
#==================================================================================================
#Total params: 1,677
#Trainable params: 1,677
#Non-trainable params: 0
#__________________________________________________________________________________________________

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

import numpy as np

# dummy data
images = np.random.random((1000, 28, 28, 1))
w = np.random.lognormal(size=(1000, 28, 28, 1))

# is accuracy sensible metric for this model?
model.compile(optimizer='adadelta', loss='mse', metrics=['accuracy'])
model.fit([images, w], [images, w], batch_size=64, epochs=5)

РЕДАКТИРОВАТЬ НИЖЕ

У меня есть несколько вопросов о коде, который вы здесь разместили. в предикторе make_w_ вы сказали: «# пересмотреть активацию (W положительный?) # должен быть filter = 1, чтобы соответствовать W», что это значит? W - это массив, содержащий 0 и 1. Что означает «пересмотреть активацию», если я изменю код этой части?

relu Активация возвращает положительные числа в [0, + inf), поэтому это может быть неправильным выбором, если W принимает другой набор значений. Типичный выбор будет следующим.

  • W могут быть положительными и отрицательными числами: «линейная» активация.
  • W в [0, 1]: «сигмовидная» активация.
  • W в [-1, 1]: активация "tanh".
  • W - положительное число: активация "relu".

В исходном коде у вас было:

w=np.random.random((1, 28, 28))

, который принимает значения от 0 до 1. Поэтому я предложил переключиться с «relu» на «sigmoid». Но я не изменил свой пример кода, потому что я не был уверен, что это было задумано.

Вы сказали, что фильтр должен быть 1, это означает изменение (3,3) на (1,1)? Мне очень жаль эти вопросы. но я новичок, и я не могу найти некоторые из них, что вы говорите. не могли бы вы помочь мне и объяснить мне полностью.

Я ссылаюсь на эту строку в оригинальном вопросе:

final_image_watermark = Conv2D(2, (3, 3), activation='relu', padding='same')(x)

Если я правильно понимаю, это определяет W' на прилагаемом изображении, которое должно предсказывать W, а его размер равен (28, 28, 1). Тогда первый аргумент Conv2D должен быть один. В противном случае выходная форма становится (28, 28, 2). Я сделал это изменение в моем примере кода, потому что в противном случае он выдает ошибку несоответствия формы:

pred_w = Conv2D(1, (3, 3), activation='relu', padding='same')(x)

Я думаю, (3, 3) часть, kernel size в керасе, это нормально, как есть.

...