当前位置: 首页 > news >正文

diffusers库学习--pipeline,模型,调度器的基础使用

pipeline,模型,调度器的基础使用

⚙️ 1. 基础设置

首先,我们从 diffuserstorch 和其他工具库中导入所有必要的组件,并设置好在 GPU 上运行的设备。

from diffusers import DiffusionPipeline
from diffusers import EulerDiscreteScheduler
from diffusers import AutoModel
from diffusers import UNet2DModel
from diffusers import DDPMScheduler
import torch
from tqdm.auto import tqdm
import PIL.Image
import numpy as npdevice="cuda" if torch.cuda.is_available() else "cpu"

🚀 Demo 1: 高度封装的 Pipeline 用法

这是生成图像最简单、最直接的方式。DiffusionPipeline (扩散管道) 为我们封装了所有复杂的步骤。

核心概念: 使用 DiffusionPipeline.from_pretrained() 来加载一个像 Stable Diffusion 一样配置齐全的“开箱即用”模型。之后,只需要提供一个提示词 (Prompt) 来调用这个 pipeline 对象就可以生成图像。

def demo1(): # 测试SD1.5默认管道设置pipeline=DiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5",torch_dtype=torch.float16,use_safetensors=True) # 模型id ,精度,是否用safetensorspipeline.to(device)image1=pipeline(prompt="A cute cat",num_inference_steps=25,guidance_scale=7.5,negative_prompt="").images[0]image1.save("./test_cat.png")

🔄 Demo 2: 更换调度器 (Scheduler)

Pipeline 是模块化的。你可以轻松地替换其中的组件,例如“调度器”,来改变去噪过程的行为和效果。

核心概念: 加载 pipeline 后,可以直接替换它的 .scheduler 属性。EulerDiscreteScheduler.from_config(pipeline.scheduler.config) 这个用法非常巧妙,它能方便地创建一个新的调度器,并让它继承旧调度器的所有配置。

def demo2():# 更换调度器pipeline=DiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5",torch_dtype=torch.float16,use_safetensors=True) # 模型id ,精度,是否用safetensorspipeline.scheduler=EulerDiscreteScheduler.from_config(pipeline.scheduler.config)pipeline.to(device)image1=pipeline(prompt="A cute cat",num_inference_step=25,guidance_scale=7.5,negative_prompt="").images[0]image1.save("./test_cat2.png")

🧩 Demo 3: 使用独立的 U-Net 模型

除了使用完整的 pipeline,我们也可以只和独立的组件打交道。扩散模型最核心的组件就是 U-Net,它负责预测噪声。

核心概念: 直接从仓库加载一个模型,比如 UNet2DModel。要使用它,你必须手动创建一个输入(一个随机噪声张量),并提供一个特定的 timestep (时间步)。模型的输出就是在该时间步预测出的噪声。

def demo3(): # AutoModel的使用和 UNet2DModel 模型repo_id="google/ddpm-cat-256"model1=AutoModel.from_pretrained(repo_id,use_safetensors=True).to(device)noise_sample=torch.randn(1,model1.config.in_channels,model1.config.sample_size,model1.config.sample_size).to(device)# 有了噪声图像然后就是推理了,推理还需要一个时间步with torch.no_grad():# 直接把时间步和噪声图像传给模型降噪noisy_residual = model1(sample=noise_sample, timestep=2).sample print(noisy_residual)

🧠 Demo 4: 理解调度器的作用

调度器是指导整个去噪过程的“大脑”。它利用模型的输出来计算出图像在上一个时间步的状态。

核心概念: scheduler.step() 方法是调度器的核心。它接收 model_output (模型预测的噪声)、当前的 timestep (时间步) 和当前的 sample (样本,即 x_t),然后计算出 prev_sample (上一步的样本,即 x_{t-1}). 这个过程为我们展示了去噪过程中的一个独立的、精确控制的步骤。

def demo4(): # 调度器repo_id="google/ddpm-cat-256"model1=AutoModel.from_pretrained(repo_id,use_safetensors=True).to(device)noise_sample=torch.randn(1,model1.config.in_channels,model1.config.sample_size,model1.config.sample_size).to(device)with torch.no_grad():noisy_residual = model1(sample=noise_sample, timestep=2).sample scheduler=DDPMScheduler.from_config(repo_id)less_noise_sample=scheduler.step(model_output=noisy_residual,timestep=2,sample=noise_sample).prev_sample

📜 Demo 5: 完整的“从零开始”推理循环

通过在一个循环中结合 U-Net 模型和调度器,我们可以从零开始复现 pipeline 内部的完整逻辑。这给了我们最大程度的控制权。

核心概念: 一个完整的推理过程,就是一个不断重复“预测噪声”和“时间步回退”的循环。

具体流程如下:

  1. 加载 U-Net 模型和一个兼容的调度器。
  2. 使用 scheduler.set_timesteps() 告诉调度器你想要进行多少步推理。
  3. 创建一个正确尺寸的初始随机噪声张量。
  4. 使用 for 循环遍历 scheduler.timesteps 数组。在每次循环中:
    a. 用 U-Net 模型根据当前样本预测噪声。
    b. 用 scheduler.step() 计算出上一个时间步的样本。
    c. 用上一步的结果更新当前样本,为下一次循环做准备。
  5. 循环结束后,将最终的张量结果转换为可以查看和保存的图像。
def demo5():# 综合练习,进行一个完整推理repo_id="google/ddpm-cat-256"model=UNet2DModel.from_pretrained(repo_id,use_safetensors=True).to(device)scheduler=DDPMScheduler.from_config(repo_id)# 关键:设置推理步数num_inference_steps = 40scheduler.set_timesteps(num_inference_steps)# 创建初始的随机噪声sample_size = model.config.sample_sizesample = torch.randn(1,model.config.in_channels,model.config.sample_size,model.config.sample_size).to(device)# 使用tqdm来显示进度条for t in tqdm(scheduler.timesteps):with torch.no_grad():# 1. 预测噪声noisy_residual = model(sample, t).sample# 2. 计算上一步的样本sample = scheduler.step(noisy_residual, t, sample).prev_sample# 循环结束后,将最终的样本转换为图像image_processed = sample.cpu().permute(0, 2, 3, 1)image_processed = (image_processed + 1.0) * 127.5image_processed = image_processed.numpy().astype(np.uint8)image_pil = PIL.Image.fromarray(image_processed[0])# 保存最终的图像image_pil.save("cat_after_40_steps.png")
http://www.lryc.cn/news/621160.html

相关文章:

  • Docker exec进入容器命令的入门教程
  • 使用正则表达式 \s+ 作为分隔符处理字符串
  • 【cmake】编译cpp文件,安装MinGW
  • Python 进阶详解:正则表达式与 JSON —— 文本处理与数据交换的核心技能
  • K8s-持久化存储
  • 第1节:多模态大模型入门(多模态大模型基础教程)
  • 安装 Nginx
  • Spring Boot + Redis + 布隆过滤器防止缓存穿透
  • UML函数原型中constraint的含义,有啥用?
  • 读《精益数据分析》:移情(Empathy)—— 验证真实需求,避免伪需求陷阱
  • 加密货币交易所开发:如何打造安全、高并发的数字资产交易平台?
  • 7、C 语言数组进阶知识点总结
  • 分布式事务、锁、链路追踪
  • Mybatis学习笔记(九)
  • C#WPF实战出真汁01--搭建项目三层架构
  • 计算机视觉第一课opencv(二)保姆级教
  • 【CLR via C#(第3版)阅读笔记】类型基础
  • (论文速读)DiffusionDet - 扩散模型在目标检测中的开创性应用
  • 【C#】跨平台创建你的WinForms窗体应用(WindowsUbuntu)
  • 从零开始的云计算生活——第四十三天,激流勇进,kubernetes模块之Pod资源对象
  • Ansible企业级实战
  • 设计模式(2)
  • sql的关键字 limit 和offset
  • 第16届蓝桥杯C++中高级选拔赛(STEMA)2024年10月20日真题
  • Ansys FreeFlow入门:对搅拌罐进行建模
  • pull request是啥意思
  • Serverless 架构核心解析与应用实践
  • 第三十一天(系统io)
  • 如何让手机访问本地服务器部署的网页?无公网IP内网主机应用,自定义外网地址,给任意网设备访问
  • 从0-1学习Java(三)快速了解字符串、数组、“==“与equals比较