AIGC实战 - 使用变分自编码器生成面部图像

AIGC实战 - 使用变分自编码器生成面部图像

    • 0. 前言
    • 1. 数据集分析
    • 2. 训练变分自编码器
      • 2.1 变分自编码器架构
      • 2.2 变分自编码器分析
    • 3. 生成新的面部图像
    • 4. 潜空间算术
    • 5. 人脸变换
    • 小结
    • 系列链接

0. 前言

在自编码器和变分自编码器上,我们都仅使用具有两个维度的潜空间。这有助于我们可视化自编码器和变分自编码器的内部工作原理,并理解自编码器和变分自编码潜空间分布的区别。在本节中,我们将使用更复杂的数据集,并了解增加潜空间的维度时,变分自编码器的图像生成效果。

1. 数据集分析

接下来,我们将使用 CelebFaces Attributes (CelebA) 数据集训练一个新的变分自编码器 (Variational Autoencoder, VAE)。CelebA 数据集包含了 200,000 多张人脸部彩色图像,每张图像都标注了各种标签(例如戴帽子、微笑等):

数据集示例

当然,训练 VAE 时并不需要这些标签,但当我们探索如何在多维潜空间中捕获这些特征时,这些标签将会派上用场。VAE 训练完成后,我们就可以从潜空间中采样,生成新的面部图像。
CelebA 数据集可以在 Kaggle 网站中获取,下载完成后,将图像和相关元数据保存到本地的 ./data 文件夹中。

# 加载数据
train_data = image_dataset_from_directory(
    "data/img_align_celeba",
    label_mode=None,
    color_mode="rgb",
    image_size=(IMAGE_SIZE, IMAGE_SIZE),
    batch_size=BATCH_SIZE,
    shuffle=True,
    seed=42,
    interpolation="bilinear",
)

使用 Keras 函数 image_dataset_from_directory 能够创建一个指向存储图像目录的 TensorFlow 数据集。用于在需要时(例如在训练期间)将图像批量读入内存,以便处理大型数据集,而不必担心要将整个数据集装入内存中导致内存不足的情况。同时还将图像调整为 64 × 64 大小,并在像素值之间进行插值处理。
原始数据值范围在 [0, 255] 之间,表示像素强度,我们需要将其重新缩放到范围 [0, 1]

# 数据预处理
def preprocess(img):
    img = tf.cast(img, "float32") / 255.0
    return img

2. 训练变分自编码器

2.1 变分自编码器架构

面部生成变分自编码模型的网络架构与 Fashion-MNIST 架构类似,仅有以下细微区别:

  • 输入数据为三通道 (RGB) 图像,而不是仅有一个通道的灰度图像灰度,因此需要将解码器的最后一个转置卷积层的通道数更改为 3
  • 使用一个具有 200 个维度的潜空间,而不是仅仅只有 2 个,由于面部图像比 Fashion-MNIST 图像复杂得多,因此需要增加潜空间的维度,以便网络可以从图像中编码出丰富的细节
  • 在每个卷积层之后都使用批归一化层,以稳定训练,尽管每批数据的运行时间较长,但达到相同损失所需的批大小大幅减少
  • KL 散度的权重因子增加到 2,000,权重因子是一个可调整的超参数,我们可以使用不同值以获得最佳效果

编码器和解码器的完整架构如下图所示:

编码器

解码器

在经过大约五个 epoch 的训练之后,变分自编码器已经能够生成新的面部图像。

2.2 变分自编码器分析

接下来,我们查看重建的脸部样本。下图中顶行展示了原始图像,底行显示了它们通过编码器和解码器处理后的重建图像。

重建图像效果

可以看到,VAE 成功地捕捉到了每张脸的关键特征,例如头部的角度、发型、表情等等。虽然仍然缺少一些细节,但是构建变分自编码器的目标并不是实现完美的重建损失,我们的目标是从潜空间中采样,生成新的面部图像。
为此,我们必须检查潜空间中的点的分布是否与多元标准正态分布大致相同。由于我们无法同时查看所有维度,因此只能分别检查隐空间的每个维度的分布。如果我们发现有任何维度与标准正态分布显著不同,那么我们可能需要减小重建损失权重系数,以增加 KL 散度对损失值的影响。
下图展示了潜空间中的前 50 个维度,可以看到,没有任何分布明显不同于标准正态分布,所以我们可以继续进行下一步,生成新的面部图像。

潜空间

3. 生成新的面部图像

使用以下代码生成新的面部图像:

grid_width, grid_height = (10, 3)
# 从一个具有 200 个维度的标准多元正态分布中随机采样 30 个点
z_sample = np.random.normal(size=(grid_width * grid_height, Z_DIM))
# 解码采样点
reconstructions = decoder.predict(z_sample)
# 绘制解码后得到的图像
fig = plt.figure(figsize=(18, 5))
fig.subplots_adjust(hspace=0.4, wspace=0.4)
for i in range(grid_width * grid_height):
    ax = fig.add_subplot(grid_height, grid_width, i + 1)
    ax.axis("off")
    ax.imshow(reconstructions[i, :, :])
plt.show()

输出结果如下图所示:

生成新图像

可以看到,VAE 能够将我们从标准正态分布中采样的一组点转化为逼真的人脸图像。尽管这些图像并不完美,但这是我们首次尝试生成模型的真正潜力。接下来,我们学习如何利用潜空间对生成的图像执行操作。

4. 潜空间算术

将图像映射到低维潜空间的一个好处在于,我们可以针对潜空间中对向量执行算术运算,当这个向量解码回原始图像域时,就能观察到其对应的视觉效果。
例如,假设我们想给一个看起来很悲伤的人物图像添加一个微笑表情。为此,我们首先需要找到潜空间中指向增加微笑表情方向的向量。将这个向量与原始图像在潜空间中的编码相加,将会得到一个新的点,解码后就能够得到一个在原始图像基础上带有微笑表情的新图像。
因此,关键是找到微笑向量。CelebA 数据集中的每个图像都带有属性标签,其中就包括微小 (Smiling)。如果我们计算具有 “Smiling” 属性的编码图像在潜在空间中的平均位置,并减去没有 “Smiling” 属性的编码图像的平均位置,就可以得到指向 “Smiling” 方向的向量。
从概念上讲,可以通过以下方式在潜在空间中执行向量算术运算,其中 alpha 是一个确定要添加或减去多少特征向量的因子:
z _ n e w = z + a l p h a ∗ f e a t u r e _ v e c t o r z\_new = z + alpha * feature\_vector z_new=z+alphafeature_vector
下图展示了几个编码到潜空间中的图像。接下来,通过添加或减去某个向量(例如 “Smiling”,“Black_Hair”,“Eyeglasses”,“Young”,“Male”,“Blond_Hair”),就可以获得不同版本的图像,而且这些图像只改变了相关的特征。

潜空间算术

需要注意的是,尽管我们在潜空间中将点移动了相当大的距离,但图像的核心特征仍然基本保持不变,只有我们想要操控的那个特征发生了变化。这说明了变分自编码器具备捕捉和调整图像的高级特征的能力。

5. 人脸变换

类似的,我们可以在两张人脸之间进行形态变换,将一张面孔图像变成另一张。假设潜空间中有两个代表两张图像的点 AB,如果从点 A 开始沿着直线走向点 B,在解码过程中遇到每个点,都可以看作是从起始面孔逐渐变换到结束面孔的过渡。从数学上讲,可以通过以下方程描述这一直线的遍历过程:
z _ n e w = z _ A ∗ ( 1 − a l p h a ) + z _ B ∗ a l p h a z\_new = z\_A * (1- alpha) + z\_B * alpha z_new=z_A(1alpha)+z_Balpha
其中,alpha 是介于 01 之间的值,用于确定我们从点 A 沿着直线前进的距离。
下图展示了实际的变换过程。我们选择两个图像,将它们编码到潜空间,然后在它们之间的直线上,以固定间隔对两点之间的所有点进行解码。

人脸变换

可以看到,即使同时需要改变多个特征(例如去掉眼镜、改变发色、性别),变分自编码器也能够平滑地实现这种过渡。这表明变分自编码器的潜空间的确是一个连续的空间,遍历和探索该空间可以生成各种不同的人脸图像。

小结

在本节中,我们将变分自编码器应用于人脸生成问题,并了解如何解码来自标准正态分布的样本点以生成新的人脸。此外,通过在潜空间内执行向量运算,我们可以实现一些新奇的效果,如人脸形态变换和特征操作。

系列链接

AIGC实战——生成模型简介
AIGC实战——深度学习 (Deep Learning, DL)
AIGC实战——卷积神经网络(Convolutional Neural Network, CNN)
AIGC实战——自编码器(Autoencoder)
AIGC实战——变分自编码器(Variational Autoencoder, VAE)

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

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

相关文章

【算法挨揍日记】day28——413. 等差数列划分、978. 最长湍流子数组

413. 等差数列划分 413. 等差数列划分 题目描述: 如果一个数列 至少有三个元素 ,并且任意两个相邻元素之差相同,则称该数列为等差数列。 例如,[1,3,5,7,9]、[7,7,7,7] 和 [3,-1,-5,-9] 都是等差数列。 给你一个整数数组 nums…

性能测试学习——项目环境搭建和Jmete学习二

项目环境搭建、Jmeter学习二 环境的部署虚拟机的安装虚拟机中添加项目操作步骤 使用环境的注意事项Jmeter的安装和简单使用Jemter的使用的进阶Jemter元件 Jmeter属性执行顺序和作用域作用域以自定义用户变量和用户参数(前置处理器)为例如何解决用户变量和线程组同级时&#xff…

Node.js之TCP(net)

Hi I’m Shendi Node.js之TCP(net) 最近使用Nodejs编写程序,需要用到自己编写的分布式工具,于是需要将Java版的用NodeJs重新写一遍,需要使用到TCP通信,于是在这里记录下Node.js TCP 的使用方法 依赖 需要使…

c语言-输入输出详解

文章目录 格式化输入输出占位符printfscanf 字符串输入输出puts&#xff08;&#xff09;gets&#xff08;&#xff09; 字符输入输出putchar&#xff08;&#xff09;getchar&#xff08;&#xff09; 区别 格式化输入输出 输入输出的库函数的头文件&#xff1a; #include<…

动态规划专项---最长上升子序列模型

文章目录 怪盗基德的滑翔翼登山合唱队形友好城市最大上升子序列和拦截导弹导弹防御系统最长公共上升子序列 一、怪盗基德的滑翔翼OJ链接 本题思路:本题是上升子序列模型中比较简单的模型&#xff0c;分别是从前往后和从后往前走一遍LIS即可。 #include <bits/stdc.h>co…

Linux——编译器gcc/g++、调试器gdb以及自动化构建工具makefilemake详解

编译器—gcc/g、调试器—gdb以及自动化构建工具—makefile&&make 文章目录 编译器—gcc/g、调试器—gdb以及自动化构建工具—makefile&&make1. 编译器——gcc/g1.1 生成可执行文件与修改默认可执行文件1.2 程序的翻译过程以及对应的gcc选项1.2.1 预处理 gcc -E…

边缘计算是如何为元宇宙提供动力的?

构建元宇宙虚拟世界并不简单&#xff0c;也并不便宜&#xff0c;但是还是有许多大型公司正在转移大量资源来开发他们的元宇宙业务&#xff0c;当然大部分企业注意力都围绕着 VR 耳机、AR 眼镜、触觉手套和其他沉浸式虚拟现实体验所需的可穿戴硬件。虽然这种沉浸式的体验是最终结…

【Django使用】django经验md文档10大模块。第4期:Django数据库增删改查

Django的主要目的是简便、快速的开发数据库驱动的网站。它强调代码复用&#xff0c;多个组件可以很方便的以"插件"形式服务于整个框架&#xff0c;Django有许多功能强大的第三方插件&#xff0c;你甚至可以很方便的开发出自己的工具包。这使得Django具有很强的可扩展…

WSL 2 更改默认安装的 Linux 发行版

目录 什么是 WSL 2&#xff1f;更改默认安装的 Linux 发行版更改发行版的 WSL 版本 什么是 WSL 2&#xff1f; WSL 2 是适用于 Linux 的 Windows 子系统体系结构的一个新版本&#xff0c;它支持适用于 Linux 的 Windows 子系统在 Windows 上运行 ELF64 Linux 二进制文件。 它的…

nn.KLDivLoss,nn.CrossEntropyLoss,nn.MSELoss,Focal_Loss

KL loss&#xff1a;https://blog.csdn.net/qq_50001789/article/details/128974654 https://pytorch.org/docs/stable/nn.html 1. nn.L1Loss 1.1 公式 L1Loss: 计算预测 x和 目标y之间的平均绝对值误差MAE, 即L1损失&#xff1a; l o s s 1 n ∑ i 1 , . . . n ∣ x i…

leetcode算法之分治-快排

目录 1.颜色分类2.排序数组3.数组中的第k个最大元素4.最小的k个数 1.颜色分类 颜色分类 class Solution { public:void sortColors(vector<int>& nums) {int n nums.size();int left -1,rightn,i0;while(i<right){if(nums[i] 0) swap(nums[left],nums[i]);e…

Spring的后处理器

目录 引言 BeanFactoryPostProcessor 注意 BeanPostProcessor 引言 Spring的后处理器是spring对外开发的重要扩展点&#xff0c;允许我们介入到Bean的整个实例化流程来&#xff0c;以达到动态注册BeanDefintion&#xff0c;动态修改BeanDefintion&#xff0c;以及动态修改Be…

【Android】使用Retrofit2发送异步网络请求的简单案例

添加网络权限到AndroidManifest.xml清单文件 为了让你的Android应用程序能够使用互联网进行通信&#xff0c;你需要在AndroidManifest.xml文件中添加网络权限声明。<uses-permission android:name"android.permission.INTERNET"/> 这个权限应该添加到 Android…

laravel-admin导出excel全部,表中无id列导出失败

laravel-admin导出excel时&#xff0c;导出全部数据&#xff0c;但是表中没有id字段&#xff0c;然后就无法导出excel&#xff1b; 就直接显示 一开始我也很着急&#xff0c;弄了半天还是不行&#xff0c;然后重写还是有问题 最后发现底层代码排序是按照id排序的orderBy(id, a…

音视频技术在手机上的应用与挑战

// 编者按&#xff1a;随着手机相机功能日益强大&#xff0c;4k&#xff0c;8k&#xff0c;各类特色短视频的拍摄&#xff0c;编辑、播放需求日益增长&#xff0c;短视频应用的火爆也对当前的手机音视频技术提出了更高的要求&#xff0c;如何更好地提高用户体验成为了行业共同…

Android 13 - Media框架(14)- OpenMax(二)

这一节我们将来解析 media.codec 这个 HIDL service 究竟提供了什么服务&#xff0c;服务是如何启动的。 1、main 函数 我们先来看 frameworks/av/services/mediacodec/main_codecservice.cpp&#xff1a; int main(int argc __unused, char** argv) {strcpy(argv[0], "…

微服务 Spring Cloud 7,Nacos配置中心的Pull原理,附源码

目录 一、本地配置二、配置中心1、以Nacos为例&#xff1a;2、Pull模式3、也可以通过Nacos实现注册中心 三、配置中心提供了哪些功能四、如何操作配置中心1、配置注册2、配置反注册3、配置查看4、配置变更订阅 五、主流的微服务注册中心有哪些&#xff0c;如何选择&#xff1f;…

76基于matlab的免疫算法求解配送中心选址问题,根据配送地址确定最佳配送中心地址位置。

基于matlab的免疫算法求解配送中心选址问题&#xff0c;根据配送地址确定最佳配送中心地址位置。数据可更换自己的&#xff0c;程序已调通&#xff0c;可直接运行。 76matlab免疫算法配送中心选址 (xiaohongshu.com)

常见Web安全

一.Web安全概述 以下是百度百科对于web安全的解释&#xff1a; Web安全&#xff0c;计算机术语&#xff0c;随着Web2.0、社交网络、微博等等一系列新型的互联网产品的诞生&#xff0c;基于Web环境的互联网应用越来越广泛&#xff0c;企业信息化的过程中各种应用都架设在Web平台…

SpringCloud总结

注&#xff1a;本文并不涉及具体功能是怎么实现的&#xff0c;而只是微服务技术栈的整体总结和理解。 目录 一.基础概念--认识微服务 1.单体架构 2.分布式架构 3.微服务 4.SpringCloud 二.服务的拆分原则 三.RestTemplate--实现不同服务之间的通信与远程调用 四.Eurek…