Я пытаюсь построить автоматический кодировщик релейной сети в keras. Основная идея состоит в том, что уровни кодирования имеют зашумленные и чистые версии, а уровни декодирования передают функции из соответствующих зашумленных слоев кодирования и имеют потери восстановления с чистыми уровнями кодирования. Я предпринял попытку, но не знаю, как проверить, правильно ли я ее настроил. У меня также есть несколько c вопросов по моей реализации. Вот сокращенная версия моего автоэнкодера с меньшим количеством слоев:
from tensorflow.keras.layers import Layer
from tensorflow.keras.layers import BatchNormalization
from tensorflow.keras.layers import Conv2D
from tensorflow.keras.layers import Conv2DTranspose
from tensorflow.keras.layers import LeakyReLU
from tensorflow.keras.layers import UpSampling2D
from tensorflow.keras.layers import GaussianNoise
from tensorflow.keras.layers import Input
from tensorflow.keras.layers import Flatten
from tensorflow.keras.models import Model
import tensorflow as tf
class Combine(Layer):
def __init__(self, **kwargs):
super(Combine, self).__init__()
def build(self, input_shape):
input_shape = input_shape[0][1:]
self.w_vertical = self.add_weight(
shape=(input_shape),
initializer="Ones",
trainable=True,
name="vertical"
)
self.w_lateral = self.add_weight(
shape=(input_shape),
initializer="Zeros",
trainable=True,
name="lateral"
)
self.w_product = self.add_weight(
shape=(input_shape),
initializer="Zeros",
trainable=True,
name="product"
)
self.b = self.add_weight(
shape=(input_shape),
initializer="Zeros",
trainable=True,
name="bias"
)
def call(self, inputs):
vertical = tf.math.multiply(inputs[0], self.w_vertical)
lateral = tf.math.multiply(inputs[1], self.w_lateral)
product_inner = tf.math.multiply(inputs[0], inputs[1])
product = tf.math.multiply(product_inner, self.w_product)
combined = self.b+vertical+lateral+product
square_diff = tf.math.squared_difference(combined,inputs[2])
mse = tf.math.reduce_mean(square_diff)
self.add_loss(0.2*mse)
return combined
def build_autoencoder(width=8, height=8, depth=3,filter_number=10, filter_size=3):
# initialize the input shape to be "channels last" along with
# the channels dimension itself
inputShape = (height, width, depth)
chanDim = -1
noise_std = 0.1
# define the input to the encoder
inputs = Input(shape=inputShape)
# create shared layers
l1_conv = Conv2D(filter_number, filter_size, strides=2, padding="same")
l1_batch = BatchNormalization(axis=chanDim)
l1_nonlin = LeakyReLU(alpha=0.2)
#clean layer 1
clean_l1_conv = l1_conv(inputs)
clean_l1_batch = l1_batch(clean_l1_conv)
clean_l1_nonlin = l1_nonlin(clean_l1_batch)
# noisy layer 1
noisy_image = GaussianNoise(noise_std)(inputs)
noisy_l1_conv = l1_conv(noisy_image)
noisy_l1_batch = l1_batch(noisy_l1_conv)
noisy_l1_batch = GaussianNoise(noise_std)(noisy_l1_batch)
noisy_l1_nonlin = l1_nonlin(noisy_l1_batch)
l2_conv = Conv2D(filter_number, filter_size, strides=2, padding="same")
l2_batch = BatchNormalization(axis=chanDim)
l2_nonlin = LeakyReLU(alpha=0.2)
#clean layer 2
clean_l2_conv = l2_conv(clean_l1_nonlin)
clean_l2_batch = l2_batch(clean_l2_conv)
clean_l2_nonlin = l2_nonlin(clean_l2_batch)
# noisy layer 2
noisy_l2_conv = l2_conv(noisy_l1_nonlin)
noisy_l2_batch = l2_batch(noisy_l2_conv)
noisy_l2_batch = GaussianNoise(noise_std)(noisy_l2_batch)
noisy_l2_nonlin = l2_nonlin(noisy_l2_batch)
latent = Flatten()(clean_l2_nonlin)
dec_l2 = UpSampling2D(size=2, interpolation="nearest")(noisy_l2_nonlin)
dec_l2 = Conv2DTranspose(filter_number, filter_size, strides=1, padding="same")(dec_l2)
dec_l2 = BatchNormalization(axis=chanDim)(dec_l2)
dec_l2 = LeakyReLU(alpha=0.2)(dec_l2)
dec_l1 = Combine()([dec_l2, noisy_l1_nonlin, clean_l1_nonlin])
dec_l1 = UpSampling2D(size=2, interpolation="nearest")(dec_l1)
dec_l1 = Conv2DTranspose(filter_number, filter_size, strides=1, padding="same")(dec_l1)
dec_l1 = BatchNormalization(axis=chanDim)(dec_l1)
outputs = Conv2DTranspose(depth, filter_size, activation="sigmoid", padding="same")(dec_l1)
autoencoder = Model(inputs, outputs, name="autoencoder")
# return a 3-tuple of the encoder, decoder, and autoencoder
return autoencoder
autoencoder = build_autoencoder()
autoencoder.compile(loss="mse", optimizer="Adam", metrics=['accuracy'])
autoencoder.summary()
Когда я запускаю свой фрагмент кода выше, я получаю следующее резюме: введите описание изображения здесь
Вопросы:
Разделяют ли мои шумные и чистые слои conv2d веса? (Что и является моим намерением)
Как объединяются потери, которые я добавляю в слой Combine с потерями на выходе, добавленными в compile()
?
Как мне получить доступ к скрытому слою, который не отображается в сводке? Я хочу, чтобы результат последнего «чистого» слоя использовался для последующей задачи.