diffusers-Understanding models and schedulers

news2024/10/7 8:21:12

https://huggingface.co/docs/diffusers/using-diffusers/write_own_pipelineicon-default.png?t=N7T8https://huggingface.co/docs/diffusers/using-diffusers/write_own_pipelinediffusers有3个模块:diffusion pipelines,noise schedulers,model。这个库很不错,设计思想和mmlab系列的有的一拼,mm系列生成算法在mmagic中,但是不如diffusers丰富,再者几乎所有的新算法的训练和推理都会采用标准的diffusers形式。

给一个标准的diffusers的sd算法的前向加载,配合huggingface hub,遥遥领先了,这是天工巧绘skypaint的文生图算法。

from diffusers import StableDiffusionPipeline

device = 'cuda'
pipe = StableDiffusionPipeline.from_pretrained("path_to_our_model").to(device)

prompts = [
    '机械狗',
    '城堡 大海 夕阳 宫崎骏动画',
    '花落知多少',
    '鸡你太美',
]

for prompt in prompts:
    prompt = 'sai-v1 art, ' + prompt
    image = pipe(prompt).images[0]  
    image.save("%s.jpg" % prompt)

1.pipelines

将必要组件(多个独立训练的model,scheduler,processor)包装在一个端到端的类中。所有的pipelines都是从DiffusionPipeline中构建而来,该类提供加载,下载和保存所有组件的基本功能。pipelines不提供training,UNet2Model和UNet2DConditionModel都是单独训练的。

下面是目前v0.21.0版本支持的pipelines,后续会一直添加的。

例子: 

from diffusers import DDPMPipeline

ddpm = DDPMPipeline.from_pretrained("google/ddpm-cat-256", use_safetensors=True).to("cuda")
image = ddpm(num_inference_steps=25).images[0]
image

在上面的示例中,pipeline中包含UNet2DModel和DDPMScheduler,pipline通过取随机噪声(与所需输出大小相同)并将其多次输入模型来去噪图像。在每个时间步中,模型预测噪声残差,并且scheduler使用它来预测一个更少噪声的图像。pipeline重复此过程,直到达到指定的推理步数。

分别使用model和scheduler去重新创建pipeline,重新来写去噪过程:

1.加载model和scheduler

from diffusers import DDPMScheduler, UNet2DModel

scheduler = DDPMScheduler.from_pretrained("google/ddpm-cat-256")
model = UNet2DModel.from_pretrained("google/ddpm-cat-256", use_safetensors=True).to("cuda")

2.去噪过程的timesteps

scheduler.set_timesteps(50)

3.设置scheduler timesteps会创建一个张量,在其中均匀地分布元素,本例中为50个元素。每个元素对应于模型去噪图像的一个timestep。当稍后创建去噪循环时,将迭代此张量以去噪图像:

scheduler.timesteps
tensor([980, 960, 940, 920, 900, 880, 860, 840, 820, 800, 780, 760, 740, 720,
    700, 680, 660, 640, 620, 600, 580, 560, 540, 520, 500, 480, 460, 440,
    420, 400, 380, 360, 340, 320, 300, 280, 260, 240, 220, 200, 180, 160,
    140, 120, 100,  80,  60,  40,  20,   0])

4.创建一些和输出形状相同的随机噪声

sample_size = model.config.sample_size
noise = torch.randn((1, 3, sample_size, sample_size)).to("cuda")

5.编写一个循环来迭代timesteps。在每个timestep中,模型执行UNet2DModel.forward()操作并返回带噪声的残差。scheduler的step()方法接受带噪声的残差、timestep和输入,然后预测上一个timestep的图像。该输出成为去噪循环中模型的下一个输入,并一直重复,直到达到时间步骤数组的末尾。这就是整个去噪过程。

input = noise

for t in scheduler.timesteps:
    with torch.no_grad():
        noisy_residual = model(input, t).sample
    previous_noisy_sample = scheduler.step(noisy_residual, t, input).prev_sample
    input = previous_noisy_sample

6.最后是将去噪输出转成图像

image = (input / 2 + 0.5).clamp(0, 1).squeeze()
image = (image.permute(1, 2, 0) * 255).round().to(torch.uint8).cpu().numpy()
image = Image.fromarray(image)
image

2.stable diffusion pipeline

stable diffusion是一个文本-图像潜在扩散模型。它被称为潜在扩散模型,是因为它使用图像的较低维度表示而不是实际的像素空间,这使得它更加内存高效。编码器将图像压缩成较小的表示,解码器将压缩表示转换回图像。对于文本到图像的模型,需要一个分词器和一个编码器来生成文本嵌入。从前面的例子中,已经知道需要一个UNet模型和一个调度器。

from PIL import Image
import torch
from transformers import CLIPTextModel, CLIPTokenizer
from diffusers import AutoencoderKL, UNet2DConditionModel, PNDMScheduler

vae = AutoencoderKL.from_pretrained("CompVis/stable-diffusion-v1-4", subfolder="vae", use_safetensors=True)
tokenizer = CLIPTokenizer.from_pretrained("CompVis/stable-diffusion-v1-4", subfolder="tokenizer")
text_encoder = CLIPTextModel.from_pretrained(
    "CompVis/stable-diffusion-v1-4", subfolder="text_encoder", use_safetensors=True
)
unet = UNet2DConditionModel.from_pretrained(
    "CompVis/stable-diffusion-v1-4", subfolder="unet", use_safetensors=True
)

代替默认的PNDMScheduler,使用UniPCMultistepScheduler

from diffusers import UniPCMultistepScheduler

scheduler = UniPCMultistepScheduler.from_pretrained("CompVis/stable-diffusion-v1-4", subfolder="scheduler")

加速推理,scheduler没有可训练权重,在不在gpu上推理无影响。

torch_device = "cuda"
vae.to(torch_device)
text_encoder.to(torch_device)
unet.to(torch_device)

2.1 create text embeddings

对文本进行tokenize以生成embedding,该文本用于调节UNet并将扩散模型引导至类似于属于提示的方向。guidance_scale参数决定了生成图像时应赋予提示多少权重。

prompt = ["a photograph of an astronaut riding a horse"]
height = 512  # default height of Stable Diffusion
width = 512  # default width of Stable Diffusion
num_inference_steps = 25  # Number of denoising steps
guidance_scale = 7.5  # Scale for classifier-free guidance
generator = torch.manual_seed(0)  # Seed generator to create the inital latent noise
batch_size = len(prompt)

对文本进行tokenize,生成文本embedding

text_input = tokenizer(
    prompt, padding="max_length", max_length=tokenizer.model_max_length, truncation=True, return_tensors="pt"
)

with torch.no_grad():
    text_embeddings = text_encoder(text_input.input_ids.to(torch_device))[0]

需要生成unconditional text embeddings,即用于填充标记的嵌入。这些嵌入需要与条件文本嵌入具有相同的形状(batch_size和seq_length)

max_length = text_input.input_ids.shape[-1]
uncond_input = tokenizer([""] * batch_size, padding="max_length", max_length=max_length, return_tensors="pt")
uncond_embeddings = text_encoder(uncond_input.input_ids.to(torch_device))[0]

把unconditional text embeddings和conditional embeddings放在同一个batch中,避免走两次前向:

text_embeddings = torch.cat([uncond_embeddings, text_embeddings])

2.2 create random noise

接下来,生成一些初始的随机噪声作为扩散过程的起点。这是图像的潜在表示,将逐渐去噪。此时,潜在图像的尺寸比最终的图像尺寸要小,但这没关系,因为模型将在后面将其转换为最终的512x512图像尺寸。

高度和宽度除以8,因为vae有3个下采样层。

2 ** (len(vae.config.block_out_channels) - 1) == 8
latents = torch.randn(
    (batch_size, unet.in_channels, height // 8, width // 8),
    generator=generator,
)
latents = latents.to(torch_device)

2.3 denoise the image

首先,通过初始噪声分布以及噪声尺度值sigma对输入进行缩放。这对于改进的调度器(如UniPCMultistepScheduler)是必需的。

latents = latents * scheduler.init_noise_sigma

最后一步是创建去噪循环,逐步将潜在的纯噪声转换为由提示描述的图像。请记住,去噪循环需要完成三件事:

1.设置调度器在去噪过程中使用的timesteps。 2.迭代timesteps。 3.在每个timestep中,调用UNet模型来预测噪声残差,并将其传递给scheduler以计算先前的噪声样本。

from tqdm.auto import tqdm

scheduler.set_timesteps(num_inference_steps)

for t in tqdm(scheduler.timesteps):
    # expand the latents if we are doing classifier-free guidance to avoid doing two forward passes.
    latent_model_input = torch.cat([latents] * 2)

    latent_model_input = scheduler.scale_model_input(latent_model_input, timestep=t)

    # predict the noise residual
    with torch.no_grad():
        noise_pred = unet(latent_model_input, t, encoder_hidden_states=text_embeddings).sample

    # perform guidance
    noise_pred_uncond, noise_pred_text = noise_pred.chunk(2)
    noise_pred = noise_pred_uncond + guidance_scale * (noise_pred_text - noise_pred_uncond)

    # compute the previous noisy sample x_t -> x_t-1
    latents = scheduler.step(noise_pred, t, latents).prev_sample

classifier-free guidance:通过在 UNet 模型中添加分类标签,使得模型在生成图像时可以同时考虑文本嵌入信息和潜在变量。具体地,在每个时间步中,将噪声残差分为无条件部分和有条件部分,其中有条件部分通过加权求和的方式与文本嵌入信息相结合,从而达到有条件的控制效果。这里的加权系数就是指导尺度,用于调节噪声残差对文本嵌入信息的影响。因此,通过这种方式,可以在不使用分类器的情况下,仍然能够结合文本嵌入信息进行有条件的控制。这就是 Classifier-free Guidance 的实现方式之一。latents*2以及后面noise_pred.chunk(2)都是classifier-free guidance的实现。

2.4 decode the image

使用vae将潜在表示解码成图像

# scale and decode the image latents with vae
latents = 1 / 0.18215 * latents
with torch.no_grad():
    image = vae.decode(latents).sample

image = (image / 2 + 0.5).clamp(0, 1).squeeze()
image = (image.permute(1, 2, 0) * 255).to(torch.uint8).cpu().numpy()
images = (image * 255).round().astype("uint8")
image = Image.fromarray(image)
image

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

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

相关文章

AUTOSAR存储篇 - NVRAM Manager(NvM)

文章目录 基础架构指南分层结构存储器硬件抽象的寻址机制例子 基本储存对象NV块RAM块ROM块管理块NV块头 块管理类型块管理类型概述NVRAM块结构NVRAM 块描述符表Native NVRAM 块Redundant NVRAM块Dataset NVRAM块NVRAM管理器API配置类 扫描顺序/优先级机制 通常行为功能要求设计…

项目综合实训,vrrp+bfd,以及策略路由的应用

目录 一. 项目需求 二. Visio设备画图 三. 设备选型 三.vlan规划 四.Ip地址规划 五.实验拓扑图 六.配置过程及结果 项目需求 1.S1作为VLAN10的主网关和根桥,S2作为v…

堆排序 详解+图解

堆排序是一种基于堆数据结构的排序算法,它的基本思想是将待排序序列构造成一个最大堆,然后将堆顶元素和堆底元素交换,再把堆的大小减一,使堆顶元素下沉到合适的位置,重复以上操作,直到整个序列有序。 堆排…

【QT】事件分发器

event事件分发器,用于分发事件,在这里也可以做拦截,返回值boo。如果返回的是true代表拦截处理,不再向下分发。 展示事件拦截 上一段代码:【QT】鼠标常用事件-CSDN博客 代码 // 事件分发器 // 拦截鼠标按下 // QEven…

Unity地面交互效果——2、动态法线贴图实现轨迹效果

Unity引擎动态法线贴图制作球滚动轨迹 大家好,我是阿赵。   之前说了一个使用局部UV采样来实现轨迹的方法。这一篇在之前的基础上,使用法线贴图进行凹凸轨迹的绘制。 一、实现的目标 先来回顾一下,上一篇最终我们已经绘制了一个轨迹的贴图…

第五章 I/O管理 七、设备的分配与回收

目录 一、设备分配时应该考虑的因素 1、设备的固有属性 2、设备分配算法 3、设备分配中的安全性 (1)安全分配方式: 优点: 缺点: (2)不安全分配方式: 优点: 缺点: 4、静态分配 5、动态分配 二、设备分配管理中的数据结…

一个非常实用的Python模块-struct模块

嗨喽~大家好呀,这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 struct模块提供了用于在字节字符串和Python原生数据类型之间转换函数,比如数字和字符串。 该模块作用是完成Python数值和C语言结构体的Python字符串形…

【git】git拉取代码报错,fatal: refusing to merge unrelated histories问题解决

大家好,我是好学的小师弟。今天准备将之前写的代码,拉到新的工程文件夹(仓库)下面,用了pull命令,结果报错了,报错截图如下 $ git pull https://gitee.com/* #仓库地址 fatal: refusing to merge unrelated histor…

自动化测试注意事项

什么是自动化测? 做测试好几年了,真正学习和实践自动化测试一年,自我感觉这一个年中收获许多。一直想动笔写一篇文章分享自动化测试实践中的一些经验。终于决定花点时间来做这件事儿。 首先理清自动化测试的概念,广义上来讲&#…

数据库-扩展语句,约束方式

扩展语句: 例: 自增长: auto_increment:表示该字段可以自增长,默认从一开始,每条记录会自动递增1 复制: 通过like这个语法直接复制ky32的表结构,只能复制表结构,不能复制表里面的…

C语言每日一题(23)兔子的序列

牛客网 BC159 兔子的序列 题目描述 描述 兔子发现了一个数字序列,于是开始研究这个序列。兔子觉得一个序列应该需要有一个命名,命名应该要与这个序列有关。由于兔子十分讨厌完全平方数,所以兔子开创了一个新的命名方式:这个序列…

Linux--文件操作

1.什么是文件 对于文件来说,文件文件内容文件属性;对于文件来说,只有两种操作,对内容的修改和对文件属性的修改,这就是文件的范畴。 对于存放在磁盘上的文件,我们需要通过进程来进行访问,访问文…

数据库 用户管理与授权

数据库的数据管理 DDL: CTEATE DROP ALTER dml:对数据进行管理 update insert into delete truncate dql:查询语询select dcl:权限控制语句grant revoke 数据库用户管理: 创建用户 修改用户的权限 删除用户。 grant要在终端执行。 create user ‘ky32’localhost ide…

紧急:发现NGINX Ingress Controller for Kubernetes中的新安全漏洞

导语 大家好,今天我要向大家紧急报告一则消息:我们在NGINX Ingress Controller for Kubernetes中发现了三个新的安全漏洞!这些漏洞可能被黑客利用,从集群中窃取机密凭据。在本文中,我们将详细介绍这些漏洞的细节&#…

日本it培训就职 日本的IT工作以什么为主?

现在有好多非计算机专业的人转行做赴日程序员,为什么这么一批人要千里迢迢跑到日本去当程序员呢?当然是因为日本程序员缺口大,需要的人才多,而且日本对程序员的要求不像国内要求那么高,比较硬性的要求就是学历至少要在…

PCIe 访问 EP 配置空间,空间映射详解,BDF 计算偏移

访问 EP 的配置空间方法 内存映射IO 访问 内存访问配置空间 前置知识 PCIe 设备的寻址是按照 BDF 即 Bus-Device-Function 来组织的。访问某个设备则需要根据BDF计算偏移地址。 两种不同的内存访问配置空间方法 类 xilinx,基地址 偏移地址访问 // linux-5.10\…

node使用fs模块(三)—— fs模块的其他使用(复制文件、文件的重命名和移动、删除)

文章目录 前言一、fs的复制1.方式一(先读取后写入)2.方式二(流式读取写入)3.两种方式的区别 二、文件的重命名和移动(fs.rename)1. 参数2. 基本使用(文件的重命名)3. 基本使用(文件的移动)4.文件…

13.7性能测试工具(LoadRunner)(简单扫盲)

下载LoadRunner和360极速浏览器 一.为什么选择LoadRunner而不是Jmeter 1.Jmeter没有录制功能. 2.LoadRunner可以设计非常丰富的测试场景. 3.LoadRunner能够产出非常丰富的测试报告. 二.LoadRunner三大组件 1.VUG: 功能: 录制脚本(编写脚本). 2.Controller: 功能: 设计场…

RocketMQ生产者消息发送出去了,消费者一直接收不到怎么办?(Rocket MQ订阅关系一致性)

问题: 使用RocketMQ消息队列,生产者将数据发送出去了,但是生产者一致没接收到(或者是间隔好几分钟,突然接收到一条数据)怎么办?并且通过rocket web控制台查看消息的状态为NOT_ONELINE或者NOT_CONSUME&#…

把Qt6.2.4内置的标签打印了一遍

2023年10月31日&#xff0c;周二晚上 #include <QGridLayout> #include <QPushButton> #include <QLabel> #include <QApplication> #include <QStyle>int main(int argc, char *argv[]) {QApplication a(argc, argv);QWidget widget;widget.set…