扩散模型从原理到实战 入门

diffusion-models-class-CN/unit1/README_CN.md at main · darcula1993/diffusion-models-class-CN · GitHub

你可以使用命令行来通过此令牌登录 (huggingface-cli login) 或者运行以下单元来登录:

from huggingface_hub import notebook_loginnotebook_login()

 https://huggingface.co/settings/tokens

在上面的网站中

获取令牌登录

 直接调包的例子

导入将要使用的库,并定义一些方便函数,稍后将会在 Notebook 中使用这些函数:

import numpy as np
import torch
import torch.nn.functional as F
from matplotlib import pyplot as plt
from PIL import Imagedef show_images(x):"""Given a batch of images x, make a grid and convert to PIL"""x = x * 0.5 + 0.5  # Map from (-1, 1) back to (0, 1)grid = torchvision.utils.make_grid(x)grid_im = grid.detach().cpu().permute(1, 2, 0).clip(0, 1) * 255grid_im = Image.fromarray(np.array(grid_im).astype(np.uint8))return grid_imdef make_grid(images, size=64):"""Given a list of PIL images, stack them together into a line for easy viewing"""output_im = Image.new("RGB", (size * len(images), size))for i, im in enumerate(images):output_im.paste(im.resize((size, size)), (i * size, 0))return output_im# Mac users may need device = 'mps' (untested)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

加载管道

from diffusers import StableDiffusionPipeline# Check out https://huggingface.co/sd-dreambooth-library for loads of models from the community
model_id = "sd-dreambooth-library/mr-potato-head"# Load the pipeline
pipe = StableDiffusionPipeline.from_pretrained(model_id, torch_dtype=torch.float16).to(device
)

管道加载完成后,我们可以使用以下命令生成图像:

# prompt = "an abstract oil painting of sks mr potato head by picasso"
prompt = "A dancing elephant"
image = pipe(prompt, num_inference_steps=50, guidance_scale=7.5).images[0]
image

 Diffusers 的核心 API 被分为三个主要部分:

  1. 管道: 从高层出发设计的多种类函数,旨在以易部署的方式,能够做到快速通过主流预训练好的扩散模型来生成样本。
  2. 模型: 训练新的扩散模型时用到的主流网络架构,e.g. UNet.
  3. 管理器 (or 调度器): 在 推理 中使用多种不同的技巧来从噪声中生成图像,同时也可以生成在 训练 中所需的带噪图像。

能够生成小蝴蝶图片的管道。

from diffusers import DDPMPipeline# Load the butterfly pipeline
butterfly_pipeline = DDPMPipeline.from_pretrained("johnowhitaker/ddpm-butterflies-32px"
# ).to(device)
).to("cuda")# Create 8 images
images = butterfly_pipeline(batch_size=8).images# View the result
make_grid(images)

下面这里会是最终的结果: 

自己构建管道

下载一个训练数据集

在这个例子中,我们会用到一个来自 Hugging Face Hub 的图像集。具体来说,是个 1000 张蝴蝶图像收藏集. 这是个非常小的数据集,我们这里也同时包含了已被注释的内容指向一些规模更大的选择。如果你想使用你自己的图像收藏,你也可以使用这里被注释掉的示例代码,从一个指定的文件夹来装载图片。

# %pip install -qq -U datasets
import torchvision
from datasets import load_dataset
from torchvision import transforms
import torchdataset = load_dataset("huggan/smithsonian_butterflies_subset", split="train")# Or load images from a local folder
# dataset = load_dataset("imagefolder", data_dir="path/to/folder")# We'll train on 32-pixel square images, but you can try larger sizes too
image_size = 32
# You can lower your batch size if you're running out of GPU memory
batch_size = 64# Define data augmentations
preprocess = transforms.Compose([transforms.Resize((image_size, image_size)),  # Resizetransforms.RandomHorizontalFlip(),  # Randomly flip (data augmentation)transforms.ToTensor(),  # Convert to tensor (0, 1)transforms.Normalize([0.5], [0.5]),  # Map to (-1, 1)]
)def transform(examples):images = [preprocess(image.convert("RGB")) for image in examples["image"]]return {"images": images}dataset.set_transform(transform)# Create a dataloader from the dataset to serve up the transformed images in batches
train_dataloader = torch.utils.data.DataLoader(dataset, batch_size=batch_size, shuffle=True
)

我们可以从中取出一批图像数据来看一看他们是什么样子:

xb = next(iter(train_dataloader))["images"].to("cuda")[:8]
print("X shape:", xb.shape)
show_images(xb).resize((8 * 64, 64), resample=Image.NEAREST)

定义管理器

我们的训练计划是,取出这些输入图片然后对它们增添噪声,在这之后把带噪的图片送入模型。在推理阶段,我们将用模型的预测值来不断迭代去除这些噪点。在diffusers中,这两个步骤都是由 管理器(调度器) 来处理的。

噪声管理器决定在不同的迭代周期时分别加入多少噪声。我们可以这样创建一个管理器,是取自于训练并能取样 'DDPM' 的默认配置。 (基于此篇论文 "Denoising Diffusion Probabalistic Models":

from diffusers import DDPMSchedulernoise_scheduler = DDPMScheduler(num_train_timesteps=1000)

DDPM 论文这样来描述一个损坏过程,为每一个 ' 迭代周期 '(timestep) 增添一点少量的噪声。设在某个迭代周期有 xt−1, 我们可以得到它的下一个版本 xt (比之前更多一点点噪声):

这就是说,我们取 xt−1, 给他一个 的系数,然后加上带有 βt 系数的噪声。 这里 β 是根据一些管理器来为每一个 t 设定的,来决定每一个迭代周期中添加多少噪声。 现在,我们不想把这个推演进行 500 次来得到 x500,所以我们用另一个公式来根据给出的 x0 计算得到任意 t 时刻的 xt:

数学符号看起来总是很可怕!好在有管理器来为我们完成这些运算。我们可以画出 α¯t−−√ (标记为sqrt_alpha_prod) 和 (1−α¯t)−−−−−−−√ (标记为sqrt_one_minus_alpha_prod) 来看一下输入 (x) 与噪声是如何在不同迭代周期中量化和叠加的:

plt.plot(noise_scheduler.alphas_cumprod.cpu() ** 0.5, label=r"${\sqrt{\bar{\alpha}_t}}$")
plt.plot((1 - noise_scheduler.alphas_cumprod.cpu()) ** 0.5, label=r"$\sqrt{(1 - \bar{\alpha}_t)}$")
plt.legend(fontsize="x-large");

噪声越来越大

不论你选择了哪一个管理器 (调度器),我们现在都可以使用noise_scheduler.add_noise功能来添加不同程度的噪声,就像这样:

timesteps = torch.linspace(0, 999, 8).long().to(device)
noise = torch.randn_like(xb)
noisy_xb = noise_scheduler.add_noise(xb, noise, timesteps)
print("Noisy X shape", noisy_xb.shape)
show_images(noisy_xb).resize((8 * 64, 64), resample=Image.NEAREST)

定义模型

大多数扩散模型使用的模型结构都是一些 [U-net] 的变形 (https://arxiv.org/abs/1505.04597) 也是我们在这里会用到的结构。

概括来说:

  • 输入模型中的图片经过几个由 ResNetLayer 构成的层,其中每层都使图片尺寸减半。
  • 之后在经过同样数量的层把图片升采样。
  • 其中还有对特征在相同位置的上、下采样层残差连接模块。

模型一个关键特征既是,输出图片尺寸与输入图片相同,这正是我们这里需要的。

Diffusers 为我们提供了一个易用的UNet2DModel类,用来在 PyTorch 创建所需要的结构。

我们来使用 U-net 为我们生成目标大小的图片吧。 注意这里down_block_types对应下采样模块 (上图中绿色部分), 而up_block_types对应上采样模块 (上图中红色部分):

from diffusers import UNet2DModel# Create a model
model = UNet2DModel(sample_size=image_size,  # the target image resolutionin_channels=3,  # the number of input channels, 3 for RGB imagesout_channels=3,  # the number of output channelslayers_per_block=2,  # how many ResNet layers to use per UNet blockblock_out_channels=(64, 128, 128, 256),  # More channels -> more parametersdown_block_types=("DownBlock2D",  # a regular ResNet downsampling block"DownBlock2D","AttnDownBlock2D",  # a ResNet downsampling block with spatial self-attention"AttnDownBlock2D",),up_block_types=("AttnUpBlock2D","AttnUpBlock2D",  # a ResNet upsampling block with spatial self-attention"UpBlock2D","UpBlock2D",  # a regular ResNet upsampling block),
)
model.to(device);

当在处理更高分辨率的输入时,你可能想用更多层的下、上采样模块,让注意力层只聚焦在最低分辨率(最底)层来减少内存消耗。我们在之后会讨论该如何实验来找到最适用与你手头场景的配置方法。

我们可以通过输入一批数据和随机的迭代周期数来看输出是否与输入尺寸相同:

with torch.no_grad():model_prediction = model(noisy_xb, timesteps).sample
model_prediction.shape

创建训练循环

终于可以训练了!下面这是 PyTorch 中经典的优化迭代循环,在这里一批一批的送入数据然后通过优化器来一步步更新模型参数 - 在这个样例中我们使用学习率为 0.0004 的 AdamW 优化器。

对于每一批的数据,我们要

  • 随机取样几个迭代周期
  • 根据预设为数据加入噪声
  • 把带噪数据送入模型
  • 使用 MSE 作为损失函数来比较目标结果与模型预测结果(在这里是加入噪声的场景)
  • 通过loss.backward ()optimizer.step ()来更新模型参数

在这个过程中我们记录 Loss 值用来后续的绘图。

NB: 这段代码大概需 10 分钟来运行 - 你也可以跳过以下两块操作直接使用预训练好的模型。供你选择,你可以探索下通过缩小模型层中的通道数会对运行速度有多少提升。

# Set the noise scheduler
noise_scheduler = DDPMScheduler(num_train_timesteps=1000, beta_schedule="squaredcos_cap_v2"
)# Training loop
optimizer = torch.optim.AdamW(model.parameters(), lr=4e-4)losses = []for epoch in range(30):for step, batch in enumerate(train_dataloader):clean_images = batch["images"].to(device)# Sample noise to add to the imagesnoise = torch.randn(clean_images.shape).to(clean_images.device)bs = clean_images.shape[0]# Sample a random timestep for each imagetimesteps = torch.randint(0, noise_scheduler.num_train_timesteps, (bs,), device=clean_images.device).long()# Add noise to the clean images according to the noise magnitude at each timestepnoisy_images = noise_scheduler.add_noise(clean_images, noise, timesteps)# Get the model predictionnoise_pred = model(noisy_images, timesteps, return_dict=False)[0]# Calculate the lossloss = F.mse_loss(noise_pred, noise)loss.backward(loss)losses.append(loss.item())# Update the model parameters with the optimizeroptimizer.step()optimizer.zero_grad()if (epoch + 1) % 5 == 0:loss_last_epoch = sum(losses[-len(train_dataloader) :]) / len(train_dataloader)print(f"Epoch:{epoch+1}, loss: {loss_last_epoch}")

绘制 loss 曲线,我们能看到模型在一开始快速的收敛,接下来以一个较慢的速度持续优化(我们用右边 log 坐标轴的视图可以看的更清楚):

fig, axs = plt.subplots(1, 2, figsize=(12, 4))
axs[0].plot(losses)
axs[1].plot(np.log(losses))
plt.show()

生成图像

方法 1:建立一个管道:
from diffusers import DDPMPipelineimage_pipe = DDPMPipeline(unet=model, scheduler=noise_scheduler)
pipeline_output = image_pipe()
pipeline_output.images[0]

我们可以在本地文件夹这样保存一个管道:

image_pipe.save_pretrained("my_pipeline")

检查文件夹的内容:

!ls my_pipeline/

方法 2:写一个取样循环

从随机噪声开始,遍历管理器的迭代周期来看从最嘈杂直到最微小的噪声变化,基于模型的预测一步步减少一些噪声:

# Random starting point (8 random images):
sample = torch.randn(8, 3, 32, 32).to(device)for i, t in enumerate(noise_scheduler.timesteps):# Get model predwith torch.no_grad():residual = model(sample, t).sample# Update sample with stepsample = noise_scheduler.step(residual, t, sample).prev_sampleshow_images(sample)

 把你的模型 Push 到 Hub

在上面的例子中我们把管道保存在了本地。把模型 push 到 hub 上,我们会需要建立模型和相应文件的仓库名。我们根据你的选择(模型 ID)来决定仓库的名字(大胆的去替换掉model_name吧;需要包含你的用户名,get_full_repo_name ()会帮你做到):

from huggingface_hub import get_full_repo_namemodel_name = "zhzhzhzhzhz-butterflies-32"
hub_model_id = get_full_repo_name(model_name)
hub_model_id

然后,在 🤗 Hub 上创建模型仓库并 push 它吧:

from huggingface_hub import HfApi, create_repocreate_repo(hub_model_id)
api = HfApi()
api.upload_folder(folder_path="my_pipeline/scheduler", path_in_repo="", repo_id=hub_model_id
)
api.upload_folder(folder_path="my_pipeline/unet", path_in_repo="", repo_id=hub_model_id)
api.upload_file(path_or_fileobj="my_pipeline/model_index.json",path_in_repo="model_index.json",repo_id=hub_model_id,
)

最后一件事是创建一个超棒的模型卡,如此,我们的蝴蝶生成器可以轻松的在 Hub 上被找到(请在描述中随意发挥!):

from huggingface_hub import ModelCardcontent = f"""
---
license: mit
tags:
- pytorch
- diffusers
- unconditional-image-generation
- diffusion-models-class
---# Model Card for Unit 1 of the [Diffusion Models Class 🧨](https://github.com/huggingface/diffusion-models-class)This model is a diffusion model for unconditional image generation of cute 🦋.## Usage```python
from diffusers import DDPMPipelinepipeline = DDPMPipeline.from_pretrained('{hub_model_id}')
image = pipeline().images[0]
image
```
"""card = ModelCard(content)
card.push_to_hub(hub_model_id)

现在模型已经在 Hub 上了,你可以这样从任何地方使用DDPMPipelinefrom_pretrained ()方法来下来它:

from diffusers import DDPMPipelinehub_model_id = "https://huggingface.co/zhzhzhzhzhz/zhzhzhzhzhz-butterflies-32"image_pipe = DDPMPipeline.from_pretrained(hub_model_id)
pipeline_output = image_pipe()
pipeline_output.images[0]

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

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

相关文章

阅读《先进引信技术的发展与展望》识别和控制部分_笔记

基本信息 题名:先进引信技术的发展与展望 作者: 张合;戴可人 发表时间:2023-07-20 可装定、可探测、可处理、可控制是灵巧引信设计的四项基本能力。与之对应,先进引信的基础研究涵盖了信息交联技术、末端探测技术、目标识别技术…

07-Making a Bar Chart with D3.js and SVG

课程链接 Curran的课程,通过 D3.js 的 scaleLinear, max, scaleBand, axisLeft, axisBottom,根据 .csv 文件生成一个横向柱状图。 【注】如果想造csv数据,可以使用通义千问,关于LinearScale与BandScale不懂的地方也可以在通义千…

Fakelocation Server服务器/专业版 ubuntu

前言:需要Ubuntu系统 Fakelocation开源文件系统需求 Ubuntu | Fakelocation | 任务一 任务一 更新Ubuntu(安装下载不再赘述) sudo -i # 提权 sudo apt update # 更新软件包列表 sudo apt upgrade # 升级已安装的软…

从搭建uni-app+vue3工程开始

技术栈 uni-app、vue3、typescript、vite、sass、uview-plus、pinia 一、项目搭建 1、创建以 typescript 开发的工程 npx degit dcloudio/uni-preset-vue#vite-ts my-vue3-project2、安装sass npm install -D sass// 安装sass-loader,注意需要版本10,…

SMMU软件指南操作之流(stream)安全性和流标识

安全之安全(security)博客目录导读 目录 1、流安全性 2、流标识 2.1 什么是 StreamID? 2.2 SubstreamID 的作用 1、流安全性 SMMUv3 架构在没有实现 RME 设备分配的情况下,支持两种可选的安全状态,这由 SMMU_S_IDR1.SECURE_IMPL 报告。如果实现了 RME 设备分配,则通过…

Android仿前端分页组件pagination

仿前端pagination Android仿前端分页组件pagination 最近Android原生有个需求就是做个分页组件,不用上拉加载,因为数据量太大用户喜欢前端的方式,UI主要是拼凑比较简单,主要补充了一些判断越界和数据不全的细节,记录方…

贴代码框架PasteForm特性介绍之query,linkquery

简介 PasteForm是贴代码推出的 “新一代CRUD” ,基于ABPvNext,目的是通过对Dto的特性的标注,从而实现管理端的统一UI,借助于配套的PasteBuilder代码生成器,你可以快速的为自己的项目构建后台管理端!目前管…

深入理解下oracle 11g block组成

深层次说,oracle数据库的最少组成单位应该是块,一般默认情况下,oracle数据库的块大小是8kb,其中存储着我们平常所需的数据。我们在使用过程中,难免会疑问道:“oracle数据块中到底是怎样组成的,平…

万有引力定律和库仑定律:自然的对称诗篇

万有引力定律和库仑定律:自然的对称诗篇 在宇宙深邃的知识长河中,万有引力定律和库仑定律恰似两颗璀璨的明珠,闪耀着人类智慧与自然奥秘的光辉。 十七世纪,牛顿在对天体运行的深邃思索中,拨开重重迷雾,发现…

win10局域网加密共享设置

1、创建共享账户 我的电脑右键选择管理 选择本地用户和组 -> 用户 双击用户 在空白区域右键,新建用户 然后创建用户 点击创建后 2、设置网络 右下角网络右键

.NET6 WebApi第1讲:VSCode开发.NET项目、区别.NET5框架【两个框架启动流程详解】

一、使用VSCode开发.NET项目 1、创建文件夹,使用VSCode打开 2、安装扩展工具 1>C# 2>安装NuGet包管理工具,外部dll包依靠它来加载 法1》:NuGet Gallery,注意要启动科学的工具 法2》NuGet Package Manager GUl&#xff0c…

准备阶段 Profiler性能分析工具的使用(一)

Unity 性能分析器 (Unity Profiler) 性能分析器记录应用程序性能的多个方面并显示相关信息。使用此信息可以做出有关应用程序中可能需要优化的事项的明智决策,并确认所做的优化是否产生预期结果。 默认情况下,性能分析器记录并保留游戏的最后 300 帧&a…

【强化学习的数学原理】第03课-贝尔曼最优公式-笔记

学习资料:bilibili 西湖大学赵世钰老师的【强化学习的数学原理】课程。链接:强化学习的数学原理 西湖大学 赵世钰 文章目录 一、例子:如何改进策略?二、最优策略和公式推导三、公式求解以及最优性四、最优策略的有趣性质五、本节课…

24小时自动监控,自动录制直播蓝光视频!支持抖音等热门直播软件

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 工具特点📒📝 使用🎈 获取方式 🎈⚓️ 相关链接 ⚓️📖 介绍 📖 对于许多直播爱好者和内容创作者而言,错过心爱的直播或难以搜集视频素材始终是一个难题。今天,给大家分享的这款工具可以轻松解决这个问题,它拥有…

【LSTM实战】跨越千年,赋诗成文:用LSTM重现唐诗的韵律与情感

本文将介绍如何使用LSTM训练一个能够创作诗歌的模型。为了训练出效果优秀的模型,我整理了来自网络的4万首诗歌数据集。我们的模型可以直接使用预先训练好的参数,这意味着您无需从头开始训练,即可在自己的电脑上体验AI作诗的乐趣。我已经为您准…

【Swift】运算符

文章目录 术语赋值运算符算数运算符基本四则算术运算符求余运算符一元负号运算符一元正号运算符 比较运算符三元运算符空合运算符区间运算符闭区间运算符半开区间运算符单侧区间运算符 逻辑运算符逻辑非运算符逻辑与运算符逻辑或运算符逻辑运算符组合计算 位运算符运算符优先级…

微信小程序技术架构图

一、视图层1.WXML&#xff08;WeiXin Markup Language&#xff09; 这是微信小程序的标记语言&#xff0c;类似于 HTML。它用于构建小程序的页面结构。例如&#xff0c;通过标签来定义各种视图元素&#xff0c;如<view>&#xff08;类似于 HTML 中的<div>&#xff…

【AI最前线】DP双像素sensor相关的AI算法全集:深度估计、图像去模糊去雨去雾恢复、图像重建、自动对焦

Dual Pixel 简介 双像素是成像系统的感光元器件中单帧同时生成的图像&#xff1a;通过双像素可以实现&#xff1a;深度估计、图像去模糊去雨去雾恢复、图像重建 成像原理来源如上&#xff0c;也有遮罩等方式的pd生成&#xff0c;如图双像素视图可以看到光圈的不同一半&#x…

Python 版本的 2024详细代码

2048游戏的Python实现 概述&#xff1a; 2048是一款流行的单人益智游戏&#xff0c;玩家通过滑动数字瓷砖来合并相同的数字&#xff0c;目标是合成2048这个数字。本文将介绍如何使用Python和Pygame库实现2048游戏的基本功能&#xff0c;包括游戏逻辑、界面绘制和用户交互。 主…

socket连接封装

效果&#xff1a; class websocketMessage {constructor(params) {this.params params; // 传入的参数this.socket null;this.lockReconnect false; // 重连的锁this.socketTimer null; // 心跳this.lockTimer null; // 重连this.timeout 3000; // 发送消息this.callbac…