代码示例 / 生成式深度学习 / 使用 Stable Diffusion 探索潜在空间

使用 Stable Diffusion 探索潜在空间

作者: Ian Stenbit, fchollet, lukewood
创建日期 2022/09/28
最后修改日期 2022/09/28
描述: 探索 Stable Diffusion 的潜在流形。

ⓘ 本示例使用 Keras 3

在 Colab 中查看 GitHub 源代码


概述

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

The Stable Diffusion architecture

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

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

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

潜在空间漫步潜在空间探索是指在潜在空间中采样一个点并逐步更改潜在表示的过程。它最常见的应用是生成动画,其中每个采样点都馈送到解码器并存储为最终动画中的一个帧。对于高质量的潜在表示,这会产生外观连贯的动画。这些动画可以提供对潜在空间特征图的深入了解,并最终导致训练过程的改进。下面显示了这样一个 GIF

Panda to Plane

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

本指南假设读者对 Stable Diffusion 有一个高层次的理解。如果您还没有,您应该从阅读 Stable Diffusion 教程开始。

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

!pip install keras-cv --upgrade --quiet
import keras_cv
import keras
import matplotlib.pyplot as plt
from keras import ops
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)
By using this model checkpoint, you acknowledge that its usage is subject to the terms of the CreativeML Open RAIL-M license at https://raw.githubusercontent.com/CompVis/stable-diffusion/main/LICENSE

在文本提示之间插值

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

为了探索这个流形的更多内容,我们可以插值两个文本编码,并在那些插值点生成图像

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 = ops.squeeze(model.encode_text(prompt_1))
encoding_2 = ops.squeeze(model.encode_text(prompt_2))

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

# Show the size of the latent manifold
print(f"Encoding shape: {encoding_1.shape}")
Downloading data from https://github.com/openai/CLIP/blob/main/clip/bpe_simple_vocab_16e6.txt.gz?raw=true
 1356917/1356917 ━━━━━━━━━━━━━━━━━━━━ 0s 0us/step
Downloading data from https://hugging-face.cn/fchollet/stable-diffusion/resolve/main/kcv_encoder.h5
 492466864/492466864 ━━━━━━━━━━━━━━━━━━━━ 7s 0us/step
Encoding shape: (77, 768)

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

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

images = model.generate_image(
    interpolated_encodings,
    batch_size=interpolation_steps,
    diffusion_noise=noise,
)
Downloading data from https://hugging-face.cn/fchollet/stable-diffusion/resolve/main/kcv_diffusion_model.h5
 3439090152/3439090152 ━━━━━━━━━━━━━━━━━━━━ 26s 0us/step
 50/50 ━━━━━━━━━━━━━━━━━━━━ 173s 311ms/step
Downloading data from https://hugging-face.cn/fchollet/stable-diffusion/resolve/main/kcv_decoder.h5
 198180272/198180272 ━━━━━━━━━━━━━━━━━━━━ 1s 0us/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,
)

Dog to Fruit 5

结果可能看起来令人惊讶。通常,在提示之间插值会产生看起来连贯的图像,并且通常会显示两个提示内容之间的概念逐渐变化。这表明高质量的表示空间,它与视觉世界的自然结构密切对应。

为了最好地可视化这一点,我们应该进行更细粒度的插值,使用数百个步骤。为了保持批量大小较小(以便我们不会超出 GPU 的内存),这需要手动批处理我们的插值编码。

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

interpolated_encodings = ops.linspace(encoding_1, encoding_2, interpolation_steps)
batched_encodings = ops.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)
 25/25 ━━━━━━━━━━━━━━━━━━━━ 77s 204ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 214ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 205ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 208ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 211ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 205ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 215ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 203ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 206ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 212ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 204ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 211ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 206ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 204ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 215ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 204ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 208ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 210ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 203ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 214ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 204ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 205ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 213ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 204ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 211ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 206ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 205ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 216ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 205ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 207ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 209ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 204ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 213ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 205ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 205ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 213ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 203ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 212ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 208ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 205ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 213ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 204ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 208ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 212ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 205ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 213ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 205ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 205ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 214ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 204ms/step

Dog to Fruit 150

生成的 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 = ops.squeeze(model.encode_text(prompt_1))
encoding_2 = ops.squeeze(model.encode_text(prompt_2))
encoding_3 = ops.squeeze(model.encode_text(prompt_3))
encoding_4 = ops.squeeze(model.encode_text(prompt_4))

interpolated_encodings = ops.linspace(
    ops.linspace(encoding_1, encoding_2, interpolation_steps),
    ops.linspace(encoding_3, encoding_4, interpolation_steps),
    interpolation_steps,
)
interpolated_encodings = ops.reshape(
    interpolated_encodings, (interpolation_steps**2, 77, 768)
)
batched_encodings = ops.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, axs = plt.subplots(
        grid_size, grid_size, figsize=(grid_size * scale, grid_size * scale)
    )
    fig.tight_layout()
    plt.subplots_adjust(wspace=0, hspace=0)
    plt.axis("off")
    for ax in axs.flat:
        ax.axis("off")

    images = images.astype(int)
    for i in range(min(grid_size * grid_size, len(images))):
        ax = axs.flat[i]
        ax.imshow(images[i].astype("uint8"))
        ax.axis("off")

    for i in range(len(images), grid_size * grid_size):
        axs.flat[i].axis("off")
        axs.flat[i].remove()

    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)
 50/50 ━━━━━━━━━━━━━━━━━━━━ 10s 209ms/step
 50/50 ━━━━━━━━━━━━━━━━━━━━ 10s 204ms/step
 50/50 ━━━━━━━━━━━━━━━━━━━━ 10s 209ms/step
 50/50 ━━━━━━━━━━━━━━━━━━━━ 11s 210ms/step
 50/50 ━━━━━━━━━━━━━━━━━━━━ 10s 210ms/step
 50/50 ━━━━━━━━━━━━━━━━━━━━ 10s 205ms/step
 50/50 ━━━━━━━━━━━━━━━━━━━━ 11s 210ms/step
 50/50 ━━━━━━━━━━━━━━━━━━━━ 10s 210ms/step
 50/50 ━━━━━━━━━━━━━━━━━━━━ 10s 208ms/step
 50/50 ━━━━━━━━━━━━━━━━━━━━ 10s 205ms/step
 50/50 ━━━━━━━━━━━━━━━━━━━━ 10s 210ms/step
 50/50 ━━━━━━━━━━━━━━━━━━━━ 11s 210ms/step

png

我们还可以在允许扩散噪声变化的同时进行插值,通过删除 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)
 50/50 ━━━━━━━━━━━━━━━━━━━━ 11s 215ms/step
 50/50 ━━━━━━━━━━━━━━━━━━━━ 13s 254ms/step
 50/50 ━━━━━━━━━━━━━━━━━━━━ 12s 235ms/step
 50/50 ━━━━━━━━━━━━━━━━━━━━ 12s 230ms/step
 50/50 ━━━━━━━━━━━━━━━━━━━━ 11s 214ms/step
 50/50 ━━━━━━━━━━━━━━━━━━━━ 10s 210ms/step
 50/50 ━━━━━━━━━━━━━━━━━━━━ 10s 208ms/step
 50/50 ━━━━━━━━━━━━━━━━━━━━ 11s 210ms/step
 50/50 ━━━━━━━━━━━━━━━━━━━━ 10s 209ms/step
 50/50 ━━━━━━━━━━━━━━━━━━━━ 10s 208ms/step
 50/50 ━━━━━━━━━━━━━━━━━━━━ 10s 205ms/step
 50/50 ━━━━━━━━━━━━━━━━━━━━ 11s 213ms/step

png

接下来 - 让我们开始一些漫步!


围绕文本提示漫步

我们的下一个实验将是从特定提示产生的点开始,围绕潜在流形漫步。

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

encoding = ops.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 = ops.ones_like(encoding) * step_size

walked_encodings = []
for step_index in range(walk_steps):
    walked_encodings.append(encoding)
    encoding += delta
walked_encodings = ops.stack(walked_encodings)
batched_encodings = ops.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)
 25/25 ━━━━━━━━━━━━━━━━━━━━ 6s 228ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 205ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 210ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 206ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 204ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 214ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 206ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 208ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 210ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 204ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 214ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 204ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 207ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 214ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 205ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 212ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 209ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 205ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 218ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 206ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 210ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 210ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 206ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 215ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 206ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 207ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 214ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 207ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 213ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 209ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 206ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 218ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 205ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 209ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 210ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 206ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 214ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 206ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 206ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 216ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 206ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 213ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 206ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 205ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 218ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 206ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 210ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 210ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 206ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 217ms/step

Eiffel tower walk gif

也许不足为奇的是,离编码器的潜在流形太远地漫步会产生看起来不连贯的图像。通过设置您自己的提示,并调整 step_size 来增加或减少漫步的幅度,自己尝试一下。请注意,当漫步的幅度变大时,漫步通常会导致产生非常嘈杂的图像的区域。


在单个提示的扩散噪声空间中循环漫步

我们的最后一个实验是坚持一个提示,并探索扩散模型可以从该提示产生的多样化图像。我们通过控制用于播种扩散过程的噪声来实现这一点。

我们创建两个噪声分量 xy,并从 0 到 2π 进行漫步,将 x 分量的余弦和 y 分量的正弦相加来产生噪声。使用这种方法,我们漫步的结尾会到达我们开始漫步的相同噪声输入,因此我们得到了一个“可循环”的结果!

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

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

walk_scale_x = ops.cos(ops.linspace(0, 2, walk_steps) * math.pi)
walk_scale_y = ops.sin(ops.linspace(0, 2, walk_steps) * math.pi)
noise_x = ops.tensordot(walk_scale_x, walk_noise_x, axes=0)
noise_y = ops.tensordot(walk_scale_y, walk_noise_y, axes=0)
noise = ops.add(noise_x, noise_y)
batched_noise = ops.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)
 25/25 ━━━━━━━━━━━━━━━━━━━━ 35s 216ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 205ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 216ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 204ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 210ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 208ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 205ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 215ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 204ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 207ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 214ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 206ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 213ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 207ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 205ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 216ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 206ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 209ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 212ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 205ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 216ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 206ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 209ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 213ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 206ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 212ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 207ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 206ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 218ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 207ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 211ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 210ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 206ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 217ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 204ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 208ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 214ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 206ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 212ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 207ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 206ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 215ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 206ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 212ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 209ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 205ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 216ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 205ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 206ms/step
 25/25 ━━━━━━━━━━━━━━━━━━━━ 5s 214ms/step

Happy Cows

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


结论

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