📜  使用 Keras 的着色自动编码器

📅  最后修改于: 2022-05-13 01:55:21.366000             🧑  作者: Mango

使用 Keras 的着色自动编码器

本文给出了一个Autoencoders的实际用例,即灰度图像的着色。我们将使用 Keras 对自动编码器进行编码。

众所周知,自动编码器有两个主要运算符:

在 Autoencoder 的设计过程中,正确选择潜在维度非常重要。好像是
除了输入维度,Autoencoder 更倾向于记忆输入。我们将使用 CNN 实现编码器部分,并将 Conv2DTranspose 用于自动编码器的解码器部分。

为了简单起见,我们将使用CIFAR100 数据集,它在 Keras 数据集中很容易获得
该数据集包含50k个形状为32 * 32 * 3的彩色图像用于训练,以及10k 个相同形状的彩色图像用于测试目的。
代码:导入所有库
import numpy as np
import matplotlib.pyplot as plt
import os
  
from keras.layers import Dense, Input, Conv2D, Conv2DTranspose, Flatten, Reshape
from keras.models import Model
from keras.callbacks import ReduceLROnPlateau, ModelCheckpoint
from keras.datasets import cifar100
from keras import backend as K

由于数据集仅包含彩色图像,因此出于我们任务的目的,我们需要将其更改为灰度。因此,我们为此定义了一个函数。
代码:将RGB图像转换为灰度的函数

def rgb_2_gray(image):
    return np.dot(image[..., :3], [0.299, 0.587, 0.114])

代码:加载数据集

(x_train, _), (x_test, _) = cifar100.load_data()

为了使模型有效地学习,最好将图像转换为浮点数。我们还需要标准化这些值,使它们位于0 和 1之间。这样做是为了在反向传播期间,梯度不会失控。

代码:规范化数据

x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.
  
x_train_gray = x_train_gray.astype('float32') / 255.
x_test_gray = x_test_gray.astype('float32') / 255.

深度学习模型的性能非常依赖于超参数集(包括层数、每层过滤器的数量、批量大小等)。因此,一个好的超参数选择是一项必不可少的技能。为了获得最佳结果,我们需要尝试使用一组不同的方法。在这里,我们使用这些超参数集,
代码:超参数

input_shape = (rows, cols, 1)
batch_size = 32
kernel_size = 3
latent_dim = 256
layer_filters = [64, 128, 256]

对于着色任务,输入是灰度图像。灰度图像只有 1 个通道,而彩色图像有 3 个通道,即红色、绿色、蓝色。我们使用来自 Keras 库的 Input 来获取(rows, cols, 1)形状的输入。
编码器是由 3 个卷积层组成的堆栈,过滤器数量不断增加,然后是一个具有256个单元的密集层,用于生成潜在向量。

代码:编码器

inputs = Input(shape = input_shape)
x = inputs
for filters in layer_filters:
  x = Conv2D(filters = filters,
           kernel_size = kernel_size,
           strides = 2,
           activation ='relu',
           padding ='same')(x)
  
shape = K.int_shape(x)
x = Flatten()(x)
latent = Dense(latent_dim, name ='latent_vector')(x)
encoder = Model(inputs, latent, name ='encoder')

自动编码器的解码器部分尝试解压缩潜在向量以便输入。在我们的例子中,解码器的输入是一个形状层(None, 256) 。它遵循三个 DeConvolutional 层的堆栈,每层中的滤波器数量递减。我们确保最后一层,在这种情况下,应该是形状(None, 32, 32, 3) 。通道数应为 3,以便在反向传播期间将重建与图像的 ground truth 进行比较。
编码器和解码器应该是两者的镜像不是强制性的。

代码:解码器

latent_inputs = Input(shape =(latent_dim, ), name ='decoder_input')
x = Dense(shape[1]*shape[2]*shape[3])(latent_inputs)
x = Reshape((shape[1], shape[2], shape[3]))(x)
# stack of Conv2DTranspose(256)-Conv2DTranspose(128)-
# Conv2DTranspose(64)
for filters in layer_filters[::-1]:
  x = Conv2DTranspose(filters = filters,
                      kernel_size = kernel_size,
                      strides = 2,
                      activation ='relu',
                      padding ='same')(x)
outputs = Conv2DTranspose(filters = channels,
                          kernel_size = kernel_size,
                          activation ='sigmoid',
                          padding ='same',
                          name ='decoder_output')(x)
decoder = Model(latent_inputs, outputs, name ='decoder')

最后,我们定义模型,命名为自动编码器,它接受输入,然后将其传递给编码器,然后将其传递给解码器。

autoencoder = Model(inputs, decoder(encoder(inputs)),
                    name ='autoencoder')

我们现在通过将整个数据分割成批大小 = batch_size的批次来训练自动编码器模型,持续30 个 epochs 。这里要注意的重要一点是,如果我们检查拟合函数,我们会发现,模型的输入是灰度图像数据集,相应的彩色图像作为标签。验证集也会发生类似的事情。
通常,对于分类任务,我们将图像作为输入提供给模型,并将它们各自的类别作为标签给出。在训练期间,我们通过测量模型将图像分类到作为标签给出的各自类别的程度来比较模型的性能。但是,对于这个任务,我们提供彩色图像作为标签,因为我们希望模型在 w 向其提供灰度图像时提供 RGB 图像作为输出。
如果验证损失没有减少太多,我们还使用回调来降低学习率。

autoencoder.fit(x_train_gray,
                x_train,
                validation_data =(x_test_gray, x_test),
                epochs = 30,
                batch_size = batch_size,
                callbacks = callbacks)

代码:结果和分析

测试图像的真实情况

前 100 个测试图像的基本事实

灰度输入

自动编码器的灰度输入

彩色输出

自动编码器的彩色输出

自动编码器在着色工作中具有可接受的性能。它正确地预测了天空是蓝色的,黑猩猩有不同深浅的棕色,树叶是绿色等。但它也做了一些错误的预测,比如向日葵有一些灰色阴影,橙色没有预测颜色,蘑菇是暗的而不是微红的等。