稳定扩散模型的隐空间探索

news2024/11/26 16:46:39

生成图像模型学习视觉世界的“潜在流形”:每个点映射到图像的低维向量空间。 从流形上的这样一个点回到可显示的图像称为“解码”—在稳定扩散模型中,这是由“解码器”模型处理的。

在线工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 

这种潜在的图像流形是连续的和可插值的,这意味着:

  • 在流形上稍微移动只会稍微改变相应的图像(连续性)。
  • 对于流形上的任意两点 A 和 B(即任意两个图像),可以通过一条路径从 A 移动到 B,其中每个中间点也在流形上(即也是有效图像)。 中间点被称为两个起始图像之间的“插值”。

不过,稳定扩散不仅仅是一个图像模型,它也是一个自然语言模型。 它有两个潜在空间:训练期间使用的编码器学习的图像表示空间,以及使用预训练和训练时微调相结合学习的提示隐空间(latent space)。

隐空间探索是对隐空间中的点进行采样并逐渐改变潜在表示的过程。 其最常见的应用是生成动画,其中每个采样点都被馈送到解码器并作为最终动画中的帧存储。 对于高质量的潜在表示,这会产生连贯的动画。 这些动画可以提供对潜在空间特征图的洞察,并最终可以改进训练过程。 下面显示了这样一个 GIF:

在本指南中,我们将展示如何利用 KerasCV 中的 Stable Diffusion API 通过 Stable Diffusion 的视觉潜在流形以及文本编码器的潜在流形执行提示插值和循环行走。

首先,我们导入 KerasCV 并使用教程使用稳定扩散生成图像中讨论的优化加载稳定扩散模型。 请注意,如果你使用 M1 Mac GPU 运行,则不应启用混合精度。

!pip install keras-cv --upgrade --quiet
import keras_cv
from tensorflow import keras
import matplotlib.pyplot as plt
import tensorflow as tf
import numpy as np
import math
from PIL import Image

# Enable mixed precision
# (only do this if you have a recent NVIDIA GPU)
keras.mixed_precision.set_global_policy("mixed_float16")

# Instantiate the Stable Diffusion model
model = keras_cv.models.StableDiffusion(jit_compile=True)

1、在文本提示之间插值

在稳定扩散中,文本提示首先被编码为向量,并且该编码用于指导扩散过程。 因空间编码向量的形状为 77x768(非常大!),当我们为稳定扩散提供文本提示时,我们仅从潜在流形上的一个这样的点生成图像。

为了探索更多这样的流形,我们可以在两个文本编码之间进行插值,并在这些插值点生成图像:

prompt_1 = "A watercolor painting of a Golden Retriever at the beach"
prompt_2 = "A still life DSLR photo of a bowl of fruit"
interpolation_steps = 5

encoding_1 = tf.squeeze(model.encode_text(prompt_1))
encoding_2 = tf.squeeze(model.encode_text(prompt_2))

interpolated_encodings = tf.linspace(encoding_1, encoding_2, interpolation_steps)

# Show the size of the latent manifold
print(f"Encoding shape: {encoding_1.shape}")

输出结果如下:

Encoding shape: (77, 768)

一旦我们插入了编码,我们就可以从每个点生成图像。 请注意,为了保持结果图像之间的稳定性,我们保持图像之间的扩散噪声恒定:

seed = 12345
noise = tf.random.normal((512 // 8, 512 // 8, 4), seed=seed)

images = model.generate_image(
    interpolated_encodings,
    batch_size=interpolation_steps,
    diffusion_noise=noise,
)

输出结果如下:

25/25 [==============================] - 50s 340ms/step

现在我们已经生成了一些插值图像,让我们来看看它们!

在本教程中,我们将把图像序列导出为 gif,以便可以在一些时间上下文中轻松查看它们。 对于第一个和最后一个图像在概念上不匹配的图像序列,我们用橡皮筋固定 gif。

如果在 Colab 中运行,可以通过运行以下命令查看自己的 GIF:

from IPython.display import Image as IImage
IImage("doggo-and-fruit-5.gif")
def export_as_gif(filename, images, frames_per_second=10, rubber_band=False):
    if rubber_band:
        images += images[2:-1][::-1]
    images[0].save(
        filename,
        save_all=True,
        append_images=images[1:],
        duration=1000 // frames_per_second,
        loop=0,
    )


export_as_gif(
    "doggo-and-fruit-5.gif",
    [Image.fromarray(img) for img in images],
    frames_per_second=2,
    rubber_band=True,
)

结果可能看起来令人惊讶。 一般来说,提示之间的插值会产生连贯的图像,并且通常会展示两个提示内容之间渐进的概念转变。 这表明了高质量的表示空间,它密切反映了视觉世界的自然结构。

为了最好地形象化这一点,我们应该使用数百个步骤进行更细粒度的插值。 为了保持较小的批量大小(这样我们就不会 OOM 我们的 GPU),这需要手动批处理我们的插值编码。

interpolation_steps = 150
batch_size = 3
batches = interpolation_steps // batch_size

interpolated_encodings = tf.linspace(encoding_1, encoding_2, interpolation_steps)
batched_encodings = tf.split(interpolated_encodings, batches)

images = []
for batch in range(batches):
    images += [
        Image.fromarray(img)
        for img in model.generate_image(
            batched_encodings[batch],
            batch_size=batch_size,
            num_steps=25,
            diffusion_noise=noise,
        )
    ]

export_as_gif("doggo-and-fruit-150.gif", images, rubber_band=True)

结果如下:

生成的 gif 显示了两个提示之间更清晰、更连贯的转变。 尝试一些你自己的提示并进行实验!

我们甚至可以将这一概念扩展到多个图像。 例如,我们可以在四个提示之间进行插值:

prompt_1 = "A watercolor painting of a Golden Retriever at the beach"
prompt_2 = "A still life DSLR photo of a bowl of fruit"
prompt_3 = "The eiffel tower in the style of starry night"
prompt_4 = "An architectural sketch of a skyscraper"

interpolation_steps = 6
batch_size = 3
batches = (interpolation_steps**2) // batch_size

encoding_1 = tf.squeeze(model.encode_text(prompt_1))
encoding_2 = tf.squeeze(model.encode_text(prompt_2))
encoding_3 = tf.squeeze(model.encode_text(prompt_3))
encoding_4 = tf.squeeze(model.encode_text(prompt_4))

interpolated_encodings = tf.linspace(
    tf.linspace(encoding_1, encoding_2, interpolation_steps),
    tf.linspace(encoding_3, encoding_4, interpolation_steps),
    interpolation_steps,
)
interpolated_encodings = tf.reshape(
    interpolated_encodings, (interpolation_steps**2, 77, 768)
)
batched_encodings = tf.split(interpolated_encodings, batches)

images = []
for batch in range(batches):
    images.append(
        model.generate_image(
            batched_encodings[batch],
            batch_size=batch_size,
            diffusion_noise=noise,
        )
    )


def plot_grid(
    images,
    path,
    grid_size,
    scale=2,
):
    fig = plt.figure(figsize=(grid_size * scale, grid_size * scale))
    fig.tight_layout()
    plt.subplots_adjust(wspace=0, hspace=0)
    plt.margins(x=0, y=0)
    plt.axis("off")
    images = images.astype(int)
    for row in range(grid_size):
        for col in range(grid_size):
            index = row * grid_size + col
            plt.subplot(grid_size, grid_size, index + 1)
            plt.imshow(images[index].astype("uint8"))
            plt.axis("off")
            plt.margins(x=0, y=0)
    plt.savefig(
        fname=path,
        pad_inches=0,
        bbox_inches="tight",
        transparent=False,
        dpi=60,
    )


images = np.concatenate(images)
plot_grid(images, "4-way-interpolation.jpg", interpolation_steps)

结果如下:

我们还可以通过删除diffusion_noise参数来进行插值,同时允许扩散噪声变化:

images = []
for batch in range(batches):
    images.append(model.generate_image(batched_encodings[batch], batch_size=batch_size))

images = np.concatenate(images)
plot_grid(images, "4-way-interpolation-varying-noise.jpg", interpolation_steps)

结果如下:

接下来—我们去探索隐空间吧!

2、围绕文本提示探索

我们的下一个实验将从特定提示产生的点开始绕潜在流形探索一圈。

walk_steps = 150
batch_size = 3
batches = walk_steps // batch_size
step_size = 0.005

encoding = tf.squeeze(
    model.encode_text("The Eiffel Tower in the style of starry night")
)
# Note that (77, 768) is the shape of the text encoding.
delta = tf.ones_like(encoding) * step_size

walked_encodings = []
for step_index in range(walk_steps):
    walked_encodings.append(encoding)
    encoding += delta
walked_encodings = tf.stack(walked_encodings)
batched_encodings = tf.split(walked_encodings, batches)

images = []
for batch in range(batches):
    images += [
        Image.fromarray(img)
        for img in model.generate_image(
            batched_encodings[batch],
            batch_size=batch_size,
            num_steps=25,
            diffusion_noise=noise,
        )
    ]

export_as_gif("eiffel-tower-starry-night.gif", images, rubber_band=True)

结果如下:

也许并不奇怪,距离编码器的潜在流形太远会产生看起来不连贯的图像。 通过设置自己的提示并调整 step_size 来增加或减少行走的幅度,亲自尝试一下。 请注意,当步长变大时,通常会进入产生极其嘈杂图像的区域。

3、在扩散噪声空间中循环探索

我们的最后一个实验是坚持一个提示,并探索扩散模型可以根据该提示生成的各种图像。 我们通过控制用于传播扩散过程的噪声来做到这一点。

我们创建两个噪声分量 x 和 y,并从 0 到 2π 行走,对 x 分量的余弦和 y 分量的正弦求和以产生噪声。 使用这种方法,我们结束时会到达与我们开始时相同的噪声输入,因此我们得到了“可循环”的结果!

prompt = "An oil paintings of cows in a field next to a windmill in Holland"
encoding = tf.squeeze(model.encode_text(prompt))
walk_steps = 150
batch_size = 3
batches = walk_steps // batch_size

walk_noise_x = tf.random.normal(noise.shape, dtype=tf.float64)
walk_noise_y = tf.random.normal(noise.shape, dtype=tf.float64)

walk_scale_x = tf.cos(tf.linspace(0, 2, walk_steps) * math.pi)
walk_scale_y = tf.sin(tf.linspace(0, 2, walk_steps) * math.pi)
noise_x = tf.tensordot(walk_scale_x, walk_noise_x, axes=0)
noise_y = tf.tensordot(walk_scale_y, walk_noise_y, axes=0)
noise = tf.add(noise_x, noise_y)
batched_noise = tf.split(noise, batches)

images = []
for batch in range(batches):
    images += [
        Image.fromarray(img)
        for img in model.generate_image(
            encoding,
            batch_size=batch_size,
            num_steps=25,
            diffusion_noise=batched_noise[batch],
        )
    ]

export_as_gif("cows.gif", images)

结果如下:

尝试使用自己的提示和不同的 unconditional_guidance_scale 值!

4、结束语

稳定扩散提供的不仅仅是单一文本到图像的生成。 探索文本编码器的潜在流形和扩散模型的噪声空间是体验该模型强大功能的两种有趣方式,KerasCV 让这一切变得简单!


原文链接;稳定扩散隐空间探索 - BimAnt

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

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

相关文章

Linux多线程基本概念

目录 ​编辑 1.什么是进程,线程,并发,并行 优点 缺点 什么资源是线程应该私有的呢 为什么线程切换成本更低呢 3.线程控制 pthread_create lpthread选项 makefile 代码实现 ps -aL 什么是LWP 轻量级进程ID与进程ID之间的区别 LWP与pthr…

【腾讯云云上实验室】用向量数据库—实践相亲社交应用

快速入口 👉向量数据库_大模型知识库_向量数据存储_向量数据检索- 腾讯云 (tencent.com) 文章目录 前言1. 向量数据库概念及原理1.1 向量数据库概念1.2 向量数据库核心原理1.3 向量数据库优缺点1.4 向量数据库与传统数据库的区别 2. 腾讯云向量数据库的基本特性及优…

虹科方案 | 如何破解CAN与车载以太网之间数据传输和协议转换的难题?

导读:在车辆网络时代,数据传输和协议转换在通信领域中扮演着至关重要的角色。它们不仅能够实现车辆内部系统之间的互联互通,还支持车辆与外部网络进行通信,从而为驾驶者带来更智能、便捷的驾驶体验。本文将介绍CAN总线与车载以太网…

【JAVA届的一代神】——Spring框架体系及Spring IOC思想【面试常问!】

文章目录 Spring简介Spring体系结构SpringIOC控制反转思想自定义对象容器Spring实现IOCSpring容器类型容器接口容器实现类 对象的创建方式使用构造方法使用工厂类的方法使用工厂类的静态方法 对象的创建策略对象的销毁时机生命周期方法获取Bean对象的方式通过id/name获取通过类…

眼精星票证识别系统操作教程与技巧

眼精星票证识别系统是一款高效、准确的票证识别工具,可以帮助用户快速将各种票证识别成结构化数据,并支持批量合并导出Excel。该系统的使用非常简单,只需要按照以下步骤进行操作即可: 1. 下载并安装眼精星票证识别系统 来百度AP…

SSM图书捐赠网站系统开发mysql数据库web结构java编程计算机网页源码eclipse项目

一、源码特点 SSM 图书捐赠网站系统是一套完善的信息系统,结合springMVC框架完成本系统,对理解JSP java编程开发语言有帮助系统采用SSM框架(MVC模式开发),系统具有完整的源代码和数据库 ,系统主要采用B/…

深入理解 Docker 核心原理:Namespace、Cgroups 和 Rootfs

来自:探索云原生 https://www.lixueduan.com 原文:https://www.lixueduan.com/posts/docker/03-container-core/ 通过这篇文章你可以了解到 Docker 容器的核心实现原理,包括 Namespace、Cgroups、Rootfs 等三个核心功能。 后续文章会演示如…

k8s中安装consul集群

一、准备知识 headless services一般结合StatefulSet来部署有状态的应用,比如kafka集群,mysql集群,zk集群等,也包括本文要部署的consul集群。 0、consul集群 consul集群的分布式协议算法采用的是raft协议,这意味着必…

UI彩虹外链网盘系统整站源码/PHP网盘与外链分享程序/整站+模版文件

源码简介: 全新UI彩虹外链网盘系统源码,它是PHP网盘与外链分享程序,提供了整站模版文件,前后端美化模板。 彩虹外链网盘美化模板是一款专为PHP网盘和外链分享程序设计的模板。它具备多种功能,包括支持所有格式文件的…

记录本地与服务器之间数据传输方法(上传、下载文件)

文章目录 一、使用scp命令实现参数说明示例说明 二、使用工具实现windows系统苹果系统如有启发,可点赞收藏哟~ 一、使用scp命令实现 scp 是 secure copy (安全复制)的缩写, scp 是基于 ssh 登陆进行安全的远程文件拷贝命令。相当于 cp 命令 …

ChatGPT进阶:提示工程的神秘面纱与实战指南

文章目录 一、提示工程的概念与原理二、提示工程的实践方法三、提示工程的挑战与展望四、实战案例分析总结《ChatGPT进阶:提示工程入门》内容简介作者简介陈颢鹏:李子菡: 目录获取方式 在人工智能领域,对话系统已经成为了一个热门…

数智赋能 锦江汽车携手苏州金龙打造高质量盛会服务

作为一家老牌客运公司,成立于1956年的上海锦江汽车服务有限公司(以下简称锦江汽车),拥有1200多辆大巴和5000多辆轿车,是上海乃至长三角地区规模最大的专业旅游客运公司。面对客运市场的持续萎缩,锦江汽车坚…

不用再羡慕“SpaceX“ 民营星际荣耀打造国产可回收火箭双曲线二号

大家好,我是极智视界,欢迎关注我的公众号,获取我的更多前沿科技分享 邀您加入我的知识星球「极智视界」,星球内有超多好玩的项目实战源码和资源下载,链接:https://t.zsxq.com/0aiNxERDq 大家似乎习惯了对马…

PDF不小心关闭没保存?这4个方法教你拯救文件!

“我刚刚在查看一个PDF文件,但是一不小心我就把它关闭了,而且我还忘记保存了。这可怎么办呢?PDF不小心关闭没保存应该怎么解决呢?还有办法恢复吗?” PDF文档是我们日常工作和学习中常用的文件格式,但有时候…

QQ录屏保存到哪了?教你快速找到保存位置

qq录屏是许多用户常用的屏幕录制工具,可是一旦录制结束,许多人不清楚如何找到和管理录制的视频文件。那么,您知道qq录屏保存到哪了吗?本文将深入研究qq录制视频功能,以帮助您了解如何存储和管理这些重要的录制视频文件…

【Android Gradle】之一小时 Gradle及 wrapper 入门

😄作者简介: 小曾同学.com,一个致力于测试开发的博主⛽️,主要职责:测试开发、CI/CD 如果文章知识点有错误的地方,还请大家指正,让我们一起学习,一起进步。 😊 座右铭:不…

【算法萌新闯力扣】:合并两个有序链表

力扣题目:合并两个有序链表 开篇 今天是备战蓝桥杯的第24天及算法村开营第2天。根据算法村的讲义,来刷链表的相关题目。今天要分享的是合并两个有序链表。 题目链接: 21.合并两个有序链表 题目描述 代码思路 通过创建一个新链表,然后遍历…

DEM分析

一、实验名称: DEM分析 二、实验目的: 通过本实验练习,掌握DEM的建立与应用基本方法。 三、实验内容和要求: 实验内容: 利用ARCGIS软件相关分析工具及实验数据,创建DEM,并计算相应坡度的区…

Android 单元测试初体验

Android 单元测试初体验 前言一、单元测试是什么?二、简单使用1.依赖2.单元测试代码简单模版及解释 总结 前言 当初在学校学安卓的时候,老师敢教学进度,翻到单元测试这一章节的时候提了两句,没有把单元测试当重点讲,只…

文章解读与仿真程序复现思路——电力自动化设备EI\CSCD\北大核心《考虑碳排放分摊的综合能源服务商交易策略》

这篇文章的标题表明它将讨论一个关于综合能源服务商交易策略的主题,而在这个策略中,特别考虑了碳排放分摊的因素。以下是对标题中各关键词的解读: 综合能源服务商: 这指的是在能源领域提供多种服务的企业或组织,可能涵…