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

news2024/11/19 10:43:11

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)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Alien Skin Exposure2024免费版图片颜色滤镜插件

Alien Skin Exposure一款非常专业的图片后期处理软件,内含500多种照片滤镜。是一款图片后期处理功能非常强大的软件。这款软件可以对图片的后期效果做很好的处理。 打开Alien Skin Exposure软件,会显示下面这个界面,如图1. ExposureX8win-安…

爱奇艺大数据离在线混部

混部作为一种提高资源利用率、降低成本的的方案,被业界普遍认可。爱奇艺在云原生化与降本增效的过程中,成功将大数据离线计算、音视频内容处理等工作负载与在线业务进行了混部,并且取得了阶段性收益。本文重点以大数据为例,介绍从…

图解API设计风格,看一眼就忘不了了!

点击下方“JavaEdge”,选择“设为星标” 第一时间关注技术干货! 免责声明~ 任何文章不要过度深思! 万事万物都经不起审视,因为世上没有同样的成长环境,也没有同样的认知水平,更「没有适用于所有人的解决方案…

反弹Shell

概述 反弹shell(reverse shell)就是控制端监听在某TCP/UDP端口,被控端发起请求到该端口,并将其命令行的输入输出转到控制端。reverse shell与telnet,ssh等标准shell对应,本质上是网络概念的客户端与服务端…

原型网络Prototypical Network的python代码逐行解释,新手小白也可学会!!-----系列7(承接系列6)

文章目录 前言一、原始代码---保存原型点,加载原型点二、代码逐行解释 前言 此部分为原型网络的两个函数,分别为保存原型点函数和加载原型点函数,与之前的系列相承接。 一、原始代码—保存原型点,加载原型点 def save_center(self,path):datas []for …

C/C++ 获取主机网卡MAC地址

MAC地址(Media Access Control address),又称为物理地址或硬件地址,是网络适配器(网卡)在制造时被分配的全球唯一的48位地址。这个地址是数据链路层(OSI模型的第二层)的一部分&#…

端口号大揭秘:网络世界的“门牌号”有多牛?

大家好,今天我们来聊一聊网络中的端口号。如果你以为端口号只是冷冰冰的数字,那你就大错特错了。端口号,这些看似枯燥的数字背后,隐藏着一个个生动的故事。 目录 大家好,今天我们来聊一聊网络中的端口号。如果你以为端…

odoo17前端js框架的演化

odoo17发布了,从界面上看,变化还是很明显的,比16更漂亮了,本来以为源码不会发生太大的变化,结果仔细一瞧,变化也不小。 1、打包好的文件数量和大小发生了变化 打包好的文件从两个变成了一个,在…

适用于全部安卓手机的 5 大免费 Android 数据恢复

您是否面临这样一种情况,即在Android设备上丢失了一些重要文件,但不知道应该选择哪种Android数据恢复来取回它们? 如果您以前从未备份过Android数据,则很难解决问题。 本文将介绍排名前5位的免费Android数据恢复软件。 您可以获…

同花顺,通达信,东方财富股票竞价,早盘板块、概念、题材竞价数据接口

早盘板块、概念、题材竞价数据接口 量化接口地址:https://stockapi.com.cn 通过分析每天早盘的板块竞价,从而判断出今日主力资金的看好方向 地址: https://stockapi.com.cn/v1/base/bkjjzq?tradeDate2023-11-08再结合个股竞价数据筛选出自…

科大讯飞会议笔记本、GoodNotes、E人E本 功能及体验对比

科大讯飞会议笔记本、GoodNotes、E人E本功能及体验对比 【旧文档,怕失传】 通过对科大讯飞会议笔记本、基于iPad的GoodNotes以及E人E本的各项功能指标进行了实际对比,得出了以下结果: 在实际体验中,科大讯飞笔记本在录音方面表…

知道数字孪生发展的四个阶段,你就能明白数字孪生的真正价值了

数字孪生的发展经历了四个阶段。以下是每个阶段的详细描述: 1、数字孪生萌芽期:这个阶段以模型仿真驱动为特征。20世纪80年代以来,CAD、CAE、CAM等计算机建模、模拟仿真技术开始迅猛发展,并在制造业领域广泛应用。该阶段主要通过…

JSP基本表单和Request对象使用例子

表单的jsp&#xff1b; <%page contentType"text/html;charsetgbk" pageEncoding"UTF-8"%> <!DOCTYPE html> <html><head><meta http-equiv"Content-Type" content"text/html; charsetUTF-8"><titl…

2023全球边缘计算大会深圳站-核心PPT资料下载

一、峰会简介 边缘计算&#xff0c;是指在靠近物或数据源头的一侧&#xff0c;采用网络、计算、存储、应用核心能力为一体的开放平台&#xff0c;就近提供最近端服务。其应用程序在边缘侧发起&#xff0c;产生更快的网络服务响应&#xff0c;满足行业在实时业务、应用智能、安…

excel中设置图表图例的位置

例如&#xff0c;在excel中已经做好了一个折线图&#xff1a; 可以看到&#xff0c;默认图例是在图表的右侧&#xff0c;减小了图的横向展示区域。我们可以把图例放到图的上边、或者下边。 双击图表&#xff1a; 鼠标放在图例上方&#xff0c;出现了浮动文字“图例”&#…

代码随想录算法训练营第二十七天|39 组合总和 40 组合总和II 131分割回文串

目录 39 组合总和 40 组合总和II 131分割回文串 39 组合总和 class Solution {List<List<Integer>>res new ArrayList<>();List<Integer>newList new LinkedList<>();public List<List<Integer>> combinationSum(int[] candid…

【算法挨揍日记】day22——面试题 17.16. 按摩师、213. 打家劫舍 II

面试题 17.16. 按摩师 面试题 17.16. 按摩师 题目描述&#xff1a; 一个有名的按摩师会收到源源不断的预约请求&#xff0c;每个预约都可以选择接或不接。在每次预约服务之间要有休息时间&#xff0c;因此她不能接受相邻的预约。给定一个预约请求序列&#xff0c;替按摩师找…

系列七、GC垃圾回收【四大垃圾算法-标记压缩算法】

一、原理 在整理压缩阶段&#xff0c;不再对标记的对象回收&#xff0c;而是通过所有存活对象都向一端移动。可以看到&#xff0c;标记的存活对象将会被整理&#xff0c;按照内存地址依次排列。如此一来&#xff0c;当我们需要给新对象分配内存时&#xff0c;JVM只需要持有一个…

记录-2023/11/18

1. 序列器中可以定义update方法 2. 分页之后前端获取数据的方式要进行改变 JavaScript的switch语法2 situation "a"switch (situation) {case "a":console.log("a")breakcase "b":console.log("b")breakcase "c&quo…

0基础编程教学,编程零基础该学什么,中文编程工具下载

0基础编程教学&#xff0c;编程零基础该学什么&#xff0c;中文编程工具下载 给大家分享一款中文编程工具&#xff0c;零基础轻松学编程&#xff0c;不需英语基础&#xff0c;编程工具可下载。 这款工具不但可以连接部分硬件&#xff0c;而且可以开发大型的软件&#xff0c;象…