DiffusionModel-latent diffusion,VAE,U-Net,Text-encoder

news2024/11/14 19:34:29

Diffusers
StableDdiffusion

Latent Diffusion

稳定扩散(Stable Diffusion)模型中使用的三个关键组件:自编码器(VAE)、U-Net和文本编码器(Text-encoder)

由于潜在扩散模型的U-Net操作在低维空间上,与像素空间扩散模型相比大大降低了内存和计算要求。例如,稳定扩散中使用的自动编码器具有8的降维因子。这意味着形状为(3,512,512)的图像在潜在空间中变为(3,64,64),这需要的内存减少了64倍。这就是为什么即使在16GB Colab GPU上也能如此迅速地生成512×512大小的图像!

VAE

VAE模型由编码器和解码器两部分组成。编码器用于将图像转换为低维潜在表示,这将作为输入传递给U-Net模型。相反,解码器将潜在表示转换回图像。

在潜在扩散训练过程中,编码器用于获取图像的潜在表示(latent),用于向前扩散过程中逐步增加噪音。在推断过程中,通过反向扩散过程生成的去噪潜在表示将使用VAE解码器转换回图像。在推断过程中,我们只需要VAE解码器。

U-Net

U-Net由编码器部分和解码器部分组成,两者都由ResNet块组成。编码器将图像表示压缩为低分辨率图像表示,解码器将低分辨率图像表示解码回原始更高分辨率图像表示,假定更清晰。具体而言,U-Net输出预测噪声残差,可用于计算预测的去噪图像表示。

为防止U-Net在降采样过程中丢失重要信息,通常在编码器的降采样ResNet和解码器的升采样ResNet之间添加快捷连接(short-cut connections)。此外,稳定扩散U-Net能够通过交叉注意力层将输出条件化为文本嵌入。交叉注意力层通常添加在U-Net的编码器和解码器部分之间,通常在ResNet块之间。

Text-Encoder

文本编码器负责将输入提示(例如"一个骑马的宇航员")转换为U-Net可理解的嵌入空间。它通常是一个简单的基于Transformer的编码器,将一系列输入标记映射到一系列潜在文本嵌入。

受Imagen启发,稳定扩散在训练期间不训练文本编码器,而是简单地使用CLIP已训练好的文本编码器,即CLIPTextModel。

流程

在这里插入图片描述

  • step1:输入:稳定扩散模型接受两个输入

    • 一个是潜在种子(latent seed),用来生成64×64大小的随机潜在图像表示。
    • 另一个是文本提示(text prompt),文本提示通过CLIP的文本编码器转换为77×768大小的文本嵌入,用于指导图像的生成。
  • step2:去噪:U-Net在被条件化于文本嵌入的情况下逐步去噪随机潜在图像表示,U-Net的输出是噪声残差,用于通过调度算法计算去噪随机潜在图像表示。

    • 调度算法:去噪后的输出(噪声残差)用于通过调度算法计算去噪后的潜在图像表示。有多种调度算法可供选择,每种算法都有其优缺点。对于Stable Diffusion,推荐使用以下之一:
      • PNDM调度器(默认使用)
      • K-LMS调度器
      • Heun离散调度器
      • DPM Solver多步调度器,这种调度器能够在较少的步骤中实现高质量,可以尝试使用25步代替默认的50步。
    • 去噪过程:去噪过程大约重复50次,逐步检索更好的潜在图像表示。
  • step3:解码:完成去噪后,潜在图像表示由变分自编码器的解码器部分解码,生成最终的图像。

Code

Stable Diffusion原理详解(附代码实现)
Stable Diffusion原理+代码

HuggingFace&DiffusionPipeline

官网教程
https://huggingface.co/docs/diffusers/main/zh/quicktour
https://huggingface.co/docs/diffusers/main/zh/api/pipelines/overview#diffusers-summary

https://blog.bot-flow.com/diffusers-quicktour/

在这里插入图片描述


#先使用from_pretrained()方法加载模型:

from diffusers import DiffusionPipeline
# 这里会下载模型,由于模型一般比较大,默认下载目录为~/.cache/huggingface,可通过export HF_HOME=指定目录,最好写入~/.bashrc持久化
pipeline = DiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5", use_safetensors=True)

#DiffusionPipeline下载并缓存所有model、tokenization、scheduling组件。
'''pipeline
# StableDiffusionPipeline {
#   "_class_name": "StableDiffusionPipeline",
#   "_diffusers_version": "0.21.4",
#   ...,
#   "scheduler": [
#     "diffusers",
#     "PNDMScheduler"
#   ],
#   ...,
#   "unet": [
#     "diffusers",
#     "UNet2DConditionModel"
#   ],
#   "vae": [
#     "diffusers",
#     "AutoencoderKL"
#   ]
# }'''

现在,可以在pipeline中输入文本提示生成图像

image = pipeline("An image of a squirrel in Picasso style").images[0]
image.save("image_of_squirrel_painting.png")#保存图像

自定义shceduler()

from diffusers import EulerDiscreteScheduler

pipeline = DiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5", use_safetensors=True)
pipeline.scheduler = EulerDiscreteScheduler.from_config(pipeline.scheduler.config)

MODEL
大多数模型采用噪声样本,并在每个时间步预测噪声残差。您可以混合搭配模型来创建其他扩散系统。模型是使用from_pretrained()方法启动的,该方法还会在本地缓存模型权重,因此下次加载模型时速度会更快。

#加载 UNet2DModel,这是一个基本的无条件图像生成模型:
from diffusers import UNet2DModel

repo_id = "google/ddpm-cat-256"
model = UNet2DModel.from_pretrained(repo_id, use_safetensors=True)

model.config#访问模型参数

模型配置(cinfig)是一个冻结字典,这意味着这些参数在模型创建后无法更改。这是有意为之,并确保一开始用于定义模型架构的参数保持不变,而其他参数仍然可以在推理过程中进行调整

  • sample_size:输入样本的高度和宽度尺寸。
  • in_channels:输入样本的输入通道数。
  • down_block_types和up_block_types:用于创建 UNet 架构的下采样和上采样模块的类型。
  • block_out_channels:下采样块的输出通道数;也以相反的顺序用于上采样块的输入通道的数量。
  • layers_per_block:每个 UNet 块中存在的 ResNet 块的数量。

如需使用推理(inferrence),首先需要使用随机高斯噪声创建图像(在计算机视觉领域,图像往往通过一个复杂的多维张量表示,不同的维度代表不同的含义),具体来说,这里张量的shape是batch * channel * width * height。

  • batch:一个批次想生成的图片张数
  • channel:一般为3,RGB色彩空间
  • width: 图像宽
  • height: 图像高
import torch

torch.manual_seed(0)
noisy_sample = torch.randn(1, model.config.in_channels, model.config.sample_size, model.config.sample_size)
#randn函数生成服从标准正态分布(均值为0,方差为1)的随机数

noisy_sample.shape#输出形状

对于推理,将噪声图像(noisy_sample)和时间步长(timestep)传递给模型。时间步长表示输入图像的噪声程度,开始时噪声多,结束时噪声少。这有助于模型确定其在扩散过程中的位置,是更接近起点还是更接近终点。使用样例方法得到模型输出:

with torch.no_grad():
    noisy_residual = model(sample=noisy_sample, timestep=2).sample
    #noisy_residual 对应调度,给定模型输出,调度程序管理从噪声样本到噪声较小的样本

调度程序:与model不同,调度程序没有可训练的权重并且是无参数的

#使用其DDPMScheduler的from_config()
from diffusers import DDPMScheduler

scheduler = DDPMScheduler.from_pretrained(repo_id)
scheduler
  • num_train_timesteps:去噪过程的长度,或者换句话说,将随机高斯噪声处理为数据样本所需的时间步数。
  • beta_schedule:用于推理和训练的噪声计划类型。
  • beta_start和beta_end:噪声表的开始和结束噪声值。

要预测噪声稍低的图像,需要传入:模型输出(noisy residual)、步长(timestep) 和 当前样本(noisy sample)。

less_noisy_sample = scheduler.step(model_output=noisy_residual, timestep=2, sample=noisy_sample).prev_sample
less_noisy_sample.shape
import PIL.Image
import numpy as np

#首先,创建一个函数,对去噪图像进行后处理并将其显示为PIL.Image:

def display_sample(sample, i):
    image_processed = sample.cpu().permute(0, 2, 3, 1)#匹配PIL的格式
    image_processed = (image_processed + 1.0) * 127.5
    image_processed = image_processed.numpy().astype(np.uint8)

    image_pil = PIL.Image.fromarray(image_processed[0])
    display(f"Image at step {i}")
    display(image_pil)

#为了加速去噪过程,请将输入和模型移至 GPU:

model.to("cuda")
noisy_sample = noisy_sample.to("cuda")




现在创建一个去噪循环来预测噪声较小的样本的残差,并使用调度程序计算噪声较小的样本:

# 导入必要的库
import torch
import tqdm

# 假设noisy_sample是之前定义的噪声样本张量
sample = noisy_sample

# 使用tqdm库来显示进度条,遍历调度器scheduler中的所有时间步
for i, t in enumerate(tqdm.tqdm(scheduler.timesteps)):
    # 1. 预测噪声残差
    # 使用torch.no_grad()上下文管理器来禁用梯度计算,这通常在推理或评估阶段使用
    with torch.no_grad():
        # 调用模型的sample方法来获取噪声残差
        # 这里model(sample, t)可能代表模型根据当前样本和时间步预测噪声
        residual = model(sample, t).sample

    # 2. 计算更少噪声的图像,并更新样本为上一个时间步的值
    # scheduler.step方法根据残差、时间步和当前样本来更新样本
    # prev_sample属性保存了更新后的样本
    sample = scheduler.step(residual, t, sample).prev_sample

    # 3. 可选地查看图像
    # 每隔50步检查一次图像,以可视化生成过程
    # 这里display_sample是一个假设的函数,用于显示或保存图像
    if (i + 1) % 50 == 0:
        display_sample(sample, i + 1)

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

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

相关文章

掌握FluentResults:.NET中优雅处理结果与错误

在.NET开发中,结果和错误处理是构建健壯应用程序的关键部分。FluentResults是一个.NET库,它提供了一种优雅的方式来处理操作结果和错误。它允许开发者以声明性和链式调用的方式构建结果对象,使得代码更加清晰和易于维护。本文将介绍FluentRes…

云原生大数据平台KDP,实战疑难问题解答

智领云的KDP(Kubernetes Data Platform)是一款自主研发的容器化云原生大数据平台,它是市场上首个能够完全在Kubernetes上部署的大数据平台。KDP深度整合了云原生架构的优势,解决了传统Hadoop大数据平台在架构限制、部署、运维、运…

ctfshow~菜狗杯 flag一分为二

第一步:解压附件得到miku.png文件 第二步:修改图片高度出现一半的flag 第三步:使用盲水印提取工具得到另一半工具 ctfshow{FirstPRTSecondPrTMikumiku~}

认识systemctl

1: 概述 systemctl命令可以帮助systemd管理和维护所有服务,系统启动完成后,systemctl命令会向systemd发送消息进行服务启动和停止等操作,想知道为什么systemctl命令可以向systemd传递消息吗,其实它是通过一个叫D_Bus(desktop bus)桌面总线的东西实现这一点,它可以并行的处理多…

劝你先别更新!!最新Stable Diffusion WebUI 1.10已来!WebUI终于支持SD3大模型了!你跑起来了么?

你的SD3大模型在SD WebUI1.10.0中跑起来了么? 今天发现Stable Diffusion WebUI于昨日推出了最新SD WebUI1.10.0 版本。令人比较兴奋的是该版本支持了SD3大模型,同时也新增了DDIM CFG采样器。主要更新内容如下: 最新版本地址: 更新…

跨境电商TikTok达人合作策略:驱动口碑传播,助力经济增长

通过与TikTok达人的深度合作,跨境电商不仅能够有效提升品牌曝光度和销售额,还能激发用户的口碑传播,形成强大的“口碑经济”效应。本文Nox聚星将和大家分析这种合作模式如何引发口碑经济效应,并探讨如何通过优化合作策略&#xff…

Python酷库之旅-第三方库Pandas(058)

目录 一、用法精讲 221、pandas.Series.interpolate方法 221-1、语法 221-2、参数 221-3、功能 221-4、返回值 221-5、说明 221-6、用法 221-6-1、数据准备 221-6-2、代码示例 221-6-3、结果输出 222、pandas.Series.isna方法 222-1、语法 222-2、参数 222-3、功…

JAVA的String类的contains方法,Indexof方法不使用KMP算法

今天做力扣的一道题目,在一个字符串中找出字符串的时候,想到了JAVA有一个contains方法,于是我去看了一下源码,发现他就是简单地调用了一下java的indexof方法, 然后我又去看了Indexof的源码,发现他就是简单的…

深入探讨C++编译期多态:提高效率与安全性

目录 一、引言 二、编译期多态技术详解 函数重载(Function Overloading) 运算符重载(Operator Overloading) 模板元编程(Template Metaprogramming) 使用std::enable_if实现条件模板特化 使用if con…

让我们逐行重现 GPT-2:第 1 部分

欢迎来到雲闪世界。Andrej Karpathy 是人工智能 (AI) 领域的顶尖研究人员之一。他是 OpenAI 的创始成员之一,曾领导特斯拉的 AI 部门,目前仍处于 AI 社区的前沿。 在第一部分中,我们重点介绍如何实现 GPT-2 的架构。虽然 GPT-2 于 2018 年由 …

Gradle下载的依赖jar包路径位置

Gradle依赖默认下载路径 Mac系统默认下载路径:C:/Users/(用户名)/.gradle/caches/modules-2/files-2.1 Windows系统默认下载路径:C:\Users(用户名).gradle\caches\modules-2\files-2.1 修改Gradle缓存文件夹路径 1. 配置环境变量 添加变量GRADLE_US…

elementUI,vue,前端判断时间是否有交集(重合)方法

分成三个部分 html※ 具体实现方法methods帮助理解逻辑图:![smallredBook:灵魂画手,业余爱好支持支持](https://i-blog.csdnimg.cn/direct/665950ee60964ef8912ce4f1a98dcc0e.jpeg#pic_center) 简化:由上面的逻辑反推[^1] html &…

与OpenAI合作:期待已久的苹果AI战略

探讨 Apple 和 OpenAI 合作的AI战略 ©作者|CodeDan 来源|神州问学 一.引言 在当今科技发展日新月异的背景下,大型科技公司的合作与联盟日益成为关注焦点。在最近的2024苹果全球开发者大会上,苹果展示了最新苹果系统上搭载的大模型应用…

.net 7和core版 SignalR

.net 7和core版 SignalR代码示例(手把手一起认识Websocket、SignalR) # 白话讲解 刚听到Websocket、SignalR有没有很迷茫,一脸懵逼的那种有没有,都是通信,这俩有什么区别,都是怎么实现的,什么时候该用哪一个, 苦于Websocket、SignalR久已,今天必须整出个一二三来,…

UWA Gears使用指南:轻松掌握应用性能优化

UWA最新发布了无SDK性能分析工具 - UWA Gears。该工具能够实时监测应用的CPU和GPU性能,无需代码改动即可掌握性能动态。此外,Gears还能截取应用的渲染画面进行深度分析,帮助您快速找到性能瓶颈并进行精准优化。 本文为您提供快速上手UWA Gea…

SpringMVC源码解析(二):请求执行流程

SpringMVC源码系列文章 SpringMVC源码解析(一):web容器启动流程 SpringMVC源码解析(二):请求执行流程 目录 前言DispatcherServlet入口一、获取HandlerExcutionChain(包括Handler)1、获取Handler1.1、通过request获取查找路径1.2、通过查找路径获取Han…

昂贵的质量 —— 为什么bug总在发生?

“To err is human” 在过去相当长一段时间内,我都在一个负责项目维护的团队内工作。团队的特殊之处在于,我们从来不开发新功能,而是负责解决每天上报的线上问题。这些 bug 无奇不有,从无法打开页面到数据奇怪丢失,麻…

关于伦敦金出金时间 你需要了解这些

​在伦敦金交易中,有很多基础因素是投资者在交易之前就需要了解的,其中就有伦敦金出金时间的问题。不过我们需要注意的是,伦敦金出金时间可能会有多种不同的含义,下面我们就这个问题进行一下讨论。 首先,伦敦金出金时间…

软件测试必备技能

在软件测试领域,以下是一些必备的技能和能力,可以帮助你成为一名优秀的软件测试工程师: 1. 测试基础知识: 熟悉软件测试的基本概念、原则和流程,包括不同类型的测试(如单元测试、集成测试、系统测试&#…