AIGC实战——自编码器(Autoencoder)

AIGC实战——自编码器

    • 0. 前言
    • 1. 自编码器原理
    • 2. 数据集与模型分析
      • 2.1 Fashion-MNIST 数据集
      • 2.2 自编码器架构
    • 3. 去噪自编码器
      • 3.1 编码器
      • 3.2 解码器
      • 3.3 连接编码器和解码器
      • 3.4 训练自编码器
      • 3.5 重建图像
    • 4. 可视化潜空间
    • 5. 生成新图像
    • 小结
    • 系列链接

0. 前言

自编码器 (Autoencoder) 是一种无监督学习的神经网络模型,用于学习输入数据的低维表示。它由编码器和解码器两部分组成,通过将输入数据压缩到潜空间表示(编码),然后将其重构为与原始输入尽可能相似的形式(解码)。在本节中,我们将使用 Keras 构建一个标准的自编码器,以理解自编码器的工作原理。

1. 自编码器原理

自编码器的目标是最小化输入与重构输出之间的重构误差,通过这个过程来学习数据中的有用特征。在训练过程中,自编码器首先将输入数据传递给编码器 (Encoder),编码器将数据映射到低维的潜空间表示(也称嵌入,或编码)。然后,解码器 (Decoder) 接收编码后的表示,并尝试将其重构为原始输入,以最小化重构误差。

自编码器

自编码器是一个被训练来执行编码和解码任务的神经网络,使得这个过程的输出尽可能接近原始输入。自编码器可以用作生成模型,因为我们可以解码我们想要的潜空间中的任何点(即使那些不是原始输入的嵌入),以产生一个新颖的输出结果。

2. 数据集与模型分析

2.1 Fashion-MNIST 数据集

在本节中,我们将使用 Fashion-MNIST 数据集,其包含了 10 个类别的 70,000 张灰度图像,每个类别有 7,000 张图像,这些类别分别对应于不同类型的服装和鞋子,包括T恤、裤子、套衫、连衣裙、外套、凉鞋、运动鞋、手提包、踝靴和运动衫。每张图像的大小为 28 x 28 像素,像素值介于 0255 之间,表示图像中每个像素的灰度级别,下图展示了数据集中的一些示例图像。

Fashion-MNIST 数据集

Fashion-MNIST 数据集已经预置在 TensorFlow 库中,可以使用以下代码下载:

from tensorflow.keras import datasets
(x_train, y_train), (x_test, y_test) = datasets.fashion_mnist.load_data()

数据集中,每张图像都为 28 × 28 的灰度图像(像素值介于 0255 之间),需要进行预处理,以确保将像素值缩放置 01 之间。我们还将每个图像填充为 32 × 32,以便能够更加方便的通过神经网络操作张量形状:

def preprocess(imgs):
    """
    图像预处理
    """
    imgs = imgs.astype("float32") / 255.0
    imgs = np.pad(imgs, ((0, 0), (2, 2), (2, 2)), constant_values=0.0)
    imgs = np.expand_dims(imgs, -1)
    return imgs

接下来,我们需要了解自编码器的整体结构,以便使用 Keras 进行实现。

2.2 自编码器架构

自编码器是一个由两部分组成的神经网络:

  • 编码器网络:将高维输入数据(如图像)压缩成低维嵌入向量
  • 解码器网络:将给定的嵌入向量解压缩还原回原始域(如解还原回图像)

自编码器网络架构如下图所示,输入图像被编码为嵌入向量 z,然后再解码回原始像素空间。

自编码器

通过编码器和解码器之后,自编码器被训练用于重构图像。之所以要重构已经存在的图像集合,是因为自编码器中的嵌入空间(也称为潜空间)具有重要作用,在该空间中进行抽样可以用于生成新的图像。
嵌入 (z) 是将原始图像压缩成低维潜空间的表示,这是因为通过选择潜空间中的任意点,我们可以通过解码器生成新图像,因为解码器已经学习到如何将潜空间的点转换成可行的图像。
在我们构建的神经网络中,将图像嵌入到一个二维潜空间中。这有助于我们可视化潜空间,方便的在二维空间中绘制点。实际应用中,为了能够捕捉图像中更多的细微特征差别,自编码器的潜空间通常会有多个维度。

3. 去噪自编码器

自编码器可用于清除图像中的噪声,因为编码器能够学习到潜空间中的随机噪声位置对于重构原始图像是无用的。对于去噪任务而言,二维潜空间无法从输入中编码足够的相关信息。但相应的,如果我们想将自编码器用作生成模型,一味地增加潜空间的维度很快会产生其它问题。

3.1 编码器

在自编码器中,编码器的作用是将输入图像映射到潜空间中的嵌入向量,我们所构建的编码器架构如下图所示:

编码器架构

首先创建一个用于接收图像的输入层,并将其依次通过三个 Conv2D 层,每一层捕捉越来越高级的特征。在卷积层中,使用步幅为 2,将每个层的输出大小减半,同时增加通道数。最后一个卷积层展平后连接到一个包含2个单元(表示二维潜空间)的全连接层:

# 编码器
# 定义编码器的输入层(图像)
encoder_input = layers.Input(
    shape=(IMAGE_SIZE, IMAGE_SIZE, CHANNELS), name="encoder_input"
)
# 依次堆叠 Conv2D 层
x = layers.Conv2D(32, (3, 3), strides=2, activation="relu", padding="same")(
    encoder_input
)
x = layers.Conv2D(64, (3, 3), strides=2, activation="relu", padding="same")(x)
x = layers.Conv2D(128, (3, 3), strides=2, activation="relu", padding="same")(x)
shape_before_flattening = K.int_shape(x)[1:]
# 将最后一个卷积层展平为一个向量
x = layers.Flatten()(x)
# 使用全连接层将此向量连接到 2D 嵌入
encoder_output = layers.Dense(EMBEDDING_DIM, name="encoder_output")(x)
# 定义编码器的 Keras 模型,该模型接受一个输入图像并将其编码成一个 2D 嵌入向量
encoder = models.Model(encoder_input, encoder_output)
print(encoder.summary())

可以调整卷积层和过滤器的数量,以了解架构对模型参数的总数、模型性能和模型运行时间的了解。

3.2 解码器

解码器是编码器的镜像,其使用转置卷积替代卷积层,解码器网络架构如下所示:

解码器

需要注意的是,解码器不一定必须和编码器使用同样的架构,它可以是任何形式,只要解码器最后一层的输出与编码器的输人大小相同即可,因为损失函数会逐像素比较输入图像与重建结果。

转置卷积层
标准的卷积层可以通过将 strides 设置为 2,在两个维度(高度和宽度)上将输入张量的大小减半。
转置卷积层 (Convolutional Transpose Layers) 的原理与标准卷积层相同(在图像上滑动滤波器),但不同之处在于将 strides 设置为 2 会使输入张量在两个维度上的大小加倍。
在转置卷积层中,strides 参数决定了在图像中像素之间的填充零的数量,如下图所示,一个 3 × 3 × 1 的滤波器(灰色)在一个 3 × 3 × 1 的图像(蓝色)上滑动,strides 设置为 2,将得到一个 6 × 6 × 1 的输出张量(绿色)。

转置卷积

Keras 中,可以使用 Conv2DTranspose 层对张量执行转置卷积操作。通过堆叠转置卷积层,可以以步幅为 2 的速度逐渐扩展每个层的大小,直到将嵌入还原为原始图像尺寸 32 × 32

# 解码器
# 定义解码器的输入(嵌入向量)
decoder_input = layers.Input(shape=(EMBEDDING_DIM,), name="decoder_input")
# 将输入连接到一个全连接层
x = layers.Dense(np.prod(shape_before_flattening))(decoder_input)
# 将向量形状调整为一个可以作为第一个 Conv2DTranspose 层输入的张量
x = layers.Reshape(shape_before_flattening)(x)
# 逐层堆叠 Conv2DTranspose 层
x = layers.Conv2DTranspose(
    128, (3, 3), strides=2, activation="relu", padding="same"
)(x)
x = layers.Conv2DTranspose(
    64, (3, 3), strides=2, activation="relu", padding="same"
)(x)
x = layers.Conv2DTranspose(
    32, (3, 3), strides=2, activation="relu", padding="same"
)(x)
decoder_output = layers.Conv2D(
    CHANNELS,
    (3, 3),
    strides=1,
    activation="sigmoid",
    padding="same",
    name="decoder_output",
)(x)
# 定义解码器的 Keras 模型,将潜空间中的嵌入解码为原始图像域
decoder = models.Model(decoder_input, decoder_output)
print(decoder.summary())

3.3 连接编码器和解码器

为了同时训练编码器和解码器,需要定义一个模型,表示图像通过编码器后再通过解码器转换回图像的流程。

# 自编码器
autoencoder = models.Model(
    encoder_input, decoder(encoder_output)
)
print(autoencoder.summary())

以上代码定义完整的自编码器的 Keras 模型,该模型接收图像输入,通过编码器传递,再传回到解码器中,生成原始图像的重建图像。

# 编译自编码器
autoencoder.compile(optimizer="adam", loss="binary_crossentropy")

定义了模型后,只需要使用损失函数和优化器对其进行编译,损失函数通常选择原始图像与重建图像各个像素之间的均方根误差 (Root Mean Squared Error, RMSE) 或二元交叉熵。

选择损失函数
优化 RMSE 损失意味着生成的输出将在平均像素值周围对称分布(因为过高或过低的估计都会受到相同的惩罚)。
另一方面,二元交叉熵损失是非对称的,相比 RMSE,二元交叉熵会更重地惩罚极端错误。例如,如果真实像素值较高(比如 0.7),则生成像素值为 0.8 的惩罚要大于生成像素值为 0.6 的惩罚;如果真实像素值较低(比如 0.3),则生成像素值为 0.2 的惩罚要大于生成像素值为 0.4 的惩罚。
因此,二元交叉熵损失相比 RMSE 损失会产生稍微模糊一些的图像(二元交叉熵倾向于将预测推向 0.5),而 RMSE 则可能会导致明显的像素化边缘。在进行充分尝试后,我们可以选择适合实际问题的最佳选择。

3.4 训练自编码器

接下来,我们将原始图像作为输入和输出训练自编码器:

autoencoder.fit(
    x_train,
    x_train,
    epochs=EPOCHS,
    batch_size=BATCH_SIZE,
    shuffle=True,
    validation_data=(x_test, x_test),
)

自编码器训练完成后,我们需要检查的是它是否能够准确地重建输入图像。

3.5 重建图像

将测试集中的图像通过自编码器进行传递,并将输出与原始图像进行比较来测试重建图像的能力:

n_to_predict = 5000
example_images = x_test[:n_to_predict]
example_labels = y_test[:n_to_predict]

predictions = autoencoder.predict(example_images)

在这里插入图片描述

在上图中,可以看到示例原始图像(顶部行),编码后的 2D 向量以及解码后的重建图像(底部行)。重建效果并不完美,解码过程中仍然有一些原始图像的细节没有被捕捉到。这是因为将每个图像缩减为二维嵌入向量,自然会丢失一些信息。

4. 可视化潜空间

接下来,我们继续研究编码器如何在潜在空间中表示图像。可以通过将测试集传递给编码器并绘制结果嵌入来可视化图像在潜在空间中的嵌入:

# 编码样本图像
embeddings = encoder.predict(example_images)
print(embeddings[:10])
# 在2D空间可视化潜向量
figsize = 8
plt.figure(figsize=(figsize, figsize))
plt.scatter(embeddings[:, 0], embeddings[:, 1], c="black", alpha=0.5, s=3)
plt.show()

在生成的散点图中,每个点表示一个已被嵌入到潜在空间中的图像。
为了更好地理解潜空间的结构,我们可以利用 Fashion-MNIST 数据集中附带的标签(描述了每个图像中物品的类型)。根据相应图像的标签为每个点着色,在结果图像中,可以看到,尽管在训练过程中从未向模型展示过服装标签,但自编码器自然地将外观相似的物品分组到潜空间的相邻部分。

潜空间

5. 生成新图像

通过在潜在空间中采样一些点,并使用解码器将其转换回像素空间来生成新的图像:

mins, maxs = np.min(embeddings, axis=0), np.max(embeddings, axis=0)
# 在潜空间中采样点
grid_width, grid_height = (6, 3)
sample = np.random.uniform(
    mins, maxs, size=(grid_width * grid_height, EMBEDDING_DIM)
)
# 解码采样点
reconstructions = decoder.predict(sample)

生成图像示例如下图所示,图中同时显示了它们在潜空间中的嵌入。

生成新图像

每个蓝色点对应图示右侧的一个图像,其嵌入向量显示在生成图像下方,可以看到生成的不同图像具有不同的逼真程度。通过观察潜空间中点的整体分布,可以得到如下结论:

  • 有些物品类别在一个非常小的区域内表示,而有一些则在一个更大的区域内表示
  • 分布关于点 (0, 0) 不对称,也没有上下界。例如,正y轴值的点要远多于负值的点,甚至一些点的y轴值超过 8
  • 彩色图像之间存在较大的间隙,自编码器无法确保将间隙处的点解码成合理的图像

上述现象使得从潜空间中进行采样变得相当具有挑战性。将潜空间与解码后的网格点图像叠加在一起,我们就可以开始理解为什么解码器并不总是能够生成令人满意的图像。

潜空间与解码后的网格点图像叠加

首先,可以看到,如果在一个有界空间中均匀地选择点,更有可能采样出解码后像一个包 (ID 8) 而不是一个踝靴 (ID 9) 的嵌入向量,因为潜空间中包(橙色)所占据的区域比踝靴(红色)要大。
其次,我们无法提前预知如何在潜空间中选择随机点,因为这些点的分布是未定义的。从技术上讲,我们可以在二维平面中选择任何点,这使得从潜空间中进行采样成为一个问题。
最后,在潜空间中存在一些没有任何原始图像编码的空白区域。例如,在区域边缘有大片的白色空间,自编码器没有强制确保这些点可以解码出可识别的图像,因为在训练集中很少有图像能够被编码到这里。
即使中心点也可能无法解码为完好的图像。这是因为自编码器并没有强制要求空间连续。例如,即使点 (-1,-1) 能够解码为一个令人满意的凉鞋图像,但没有机制确保点 (-1.1,-1.1) 也能够生成一个令人满意的凉鞋图像。
在二维空间中,自编码器只有少数几个维度可以使用,所以必须将图像分组压缩在一起,导致图像分组之间的空间相对较小。当我们在潜空间中使用更多维度来生成更复杂的图像(如人脸)时,这个问题会变得更加明显。如果我们让自编码器自由使用潜空间来编码图像,那么相似点之间就会有出现巨大的空白,因为自编码器中没有相应机制确保在这些空白空间生成合理的图像。

小结

自编码器通常由两部分组成:编码器和解码器。编码器将输入数据转化为低维编码表示,而解码器则将这个编码表示转化回原始数据的表示。在训练过程中,自编码器试图最小化重构误差,即输入数据与解码器输出之间的误差。通过使用这种方式,自编码器可以学习到数据的压缩表示,并且保留了数据的主要特征信息。利用自编码器可以利用潜空间向量生成新图像,但仍存在诸多问题,无法确保潜空间中的所有点均可以生成逼真图像。

系列链接

AIGC实战——生成模型简介
AIGC实战——深度学习 (Deep Learning, DL)
AIGC实战——卷积神经网络(Convolutional Neural Network, CNN)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/138673.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux常用的解压命令

笑小枫的专属目录 整啥幺蛾子Linux tar命令tar命令的参数范例 Linux unzip命令语法参数 整啥幺蛾子 今天在linux解压一个文件,顺手就来tar -zxvf xxxx ,哦吼,爆竿了,套他猴子的。 好吧,承认 .gz文件解压多了&#xff…

基于springboot实现结合疫情情况的婚恋系统【项目源码】计算机毕业设计

基于springboot实现结合疫情情况的婚恋系统演示 SpringBoot框架 SpringBoot是一个全新开源的轻量级框架。基于Spring4.0设计,其不仅继承了Spring框架原来有的优秀特性,而且还通过简化配置文件来进一步简化了Spring应用的整个搭建以及开发过程。另外在原…

电脑一直IP地址错误无法上网怎么办?

电脑出现IP地址错误,就将无法正常上网,那么,电脑一直IP地址错误无法上网怎么办呢?下面我们就一起来了解一下。 方法1. 确认是否禁用本地连接 你需要先确定是否禁用了本地网络连接,如果发现禁用,则将其启用…

理事长走进统信软件,深度探讨社区发展规划 | 理事长走进系列

10 月 19 日,龙蜥社区“理事长走进理事单位系列交流会”活动第二期开展,本期走进龙蜥社区副理事长单位——统信软件,会议共出席 17 人。会上回顾了统信软件过去在龙蜥社区的贡献和投入,并共同对未来的合作计划和诉求进行了深度讨论…

解决任务栏卡死

近期许多Win10用户反映在开机进入系统后遇到了任务栏卡顿、无法正常使用的问题,虽然桌面能够正常操作,但任务栏问题依然影响了用户的使用体验。 对“Windows资源管理器”进行重启 你可以尝试按下“CtrlAltDel”快捷键,打开“任务管理器”&a…

Android Studio 代码上传gitLab

1、项目忽略文件 2选择要上传的项目 3、添加 首次提交需要输入url 最后在push

通过流量分析查看业务系统运行和访问情况

在当今数字化时代,应用程序的运行和访问情况对于企业和组织来说至关重要。无论是在线销售平台、移动应用还是企业内部系统,应用的性能和可用性直接影响着用户体验、业务流程以及组织效率。因此,对应用的运行和访问情况进行全面分析和评估&…

使用阿里云服务器学习Docker

首先我这里选择的系统服务器是CentOS 7.9 64位 因为centos系统里面的安装指令是:yum,而非apt-get. yum install docker -y试着建立一个容器: docker run -d -p 80:80 httpd启动docker的守护进程: sudo systemctl start docker 查看Docke…

Linux常用的压缩命令

笑小枫的专属目录 少整花活,直接干货Linux gzip命令语法功能参数 Linux zip命令语法参数 少整花活,直接干货 本文的来源就是因为上篇文章Linux常用的解压命令,解压整了,顺手整理了一波压缩命令。 Linux gzip命令 减少文件大小有…

包装类、自动装箱、自动拆箱是什么?有哪些注意点?

1、包装类 Java中的数据类型总体上分为基本数据类型和引用数据类型。引用类型的数据可以通过对象的属性和方法来进行操作,但对于基本数据类型的数据,我们能不能像操作对象那样来操作呢?为了实现这个目标,Java为8种基本数据类型分…

axios1.5取消请求,中断请求的方法

给input的onchange绑定事件 引入axios,使用axios.CancelToken.source()创建标记 实例中,把cancelToken的值填上

群晖NAS:内网穿透、异地组网 frp

群晖NAS:内网穿透、异地组网 星空-远程访问(推荐高速) https://ip4.ink/ cpolar极点云(简单易用) https://www.cpolar.com/ 内网穿透矿神教程 https://imnks.com/4406.html 1、公网最好了,IPV4参考&…

在VM ware上安装ESXI,并ESXI上安装centos系统

在VM ware上安装ESXI,并ESXI上安装centos系统 文章目录 在VM ware上安装ESXI,并ESXI上安装centos系统1.ESXI8.0镜像下载:1.1. 下载ESXI镜像: 2.下载镜像后安装ESXI虚拟机2.1.创建虚拟机 3.开启ESXI的虚拟机开启安装ESXI操作系统4.…

深度学习 大数据 股票预测系统 - python lstm 计算机竞赛

文章目录 0 前言1 课题意义1.1 股票预测主流方法 2 什么是LSTM2.1 循环神经网络2.1 LSTM诞生 2 如何用LSTM做股票预测2.1 算法构建流程2.2 部分代码 3 实现效果3.1 数据3.2 预测结果项目运行展示开发环境数据获取 最后 0 前言 🔥 优质竞赛项目系列,今天…

SSL证书对于SEO优化的重要性

SEO是指通过优化网站的内容、结构和技术元素以提升其在搜索引擎结果页上的排名的过程。其中一个经常被忽视但对SEO效果产生深远影响的因素就是SSL证书。 SSL证书是一种数字证书,用于加密网站流量并验证网站身份。它有助于保护用户的敏感数据,并在访问者和…

【算法练习Day47】两个字符串的删除操作编辑距离

​📝个人主页:Sherry的成长之路 🏠学习社区:Sherry的成长之路(个人社区) 📖专栏链接:练题 🎯长路漫漫浩浩,万事皆有期待 文章目录 两个字符串的删除操作编辑距…

一款好用的jpeg分析软件 JPEGsnoop

最近解码器解码jpeg的时候出了问题,为了追踪问题,找到了这款免费好用的jpeg分析软件- JPEGsnoop。 顶礼膜拜。 贴上链接地址: https://github.com/ImpulseAdventure/JPEGsnoop/releases 上面已经有编译好的win10 exe了 下载后解压&#x…

个微协议开发/微信个人号二次开发/ipad协议/api接口

E云管家,是完整的第三方服务平台,并基于IPAD协议8.0.37开发出的最新个微API服务框架。 你可以 通过API 实现 个性化微信功能 (例云发单助手、社群小助手、客服系统、机器人等),用来自动管理微信消息。用户仅可一次对接…

解锁海外网红营销的潜力:关于KOC合作的7大建议

随着社交媒体的崛起,海外网红营销已成为全球各行业的主要趋势之一。传统的广告渠道逐渐被社交媒体平台和网红吸引了大量的广告投放,因此企业需要不断创新,以吸引受众并保持竞争力。其中,KOC合作是一个备受关注的策略,它…

运行程序报错 system/bin/linker: No such file or direct

使用CLion写了一个测试程序, cmake 编译完成后 , ./test 运行程序报错system/bin/linker: No such file or direct 解决 修改编译链接工具链 重新编译后运行正常