Diffusers(https://huggingface.co/docs/diffusers/index)是一个先进的预训练扩散模型库,用于生成图像、音频甚至分子的三维结构。它提供了人工智能推理和训练领域易于使用且高度可定制的模块化工具箱。
虽然Stable Diffusion WebUI同样在生成高质量图像方面非常强大,但数据科学家和机器学习工程师通常需要更多的控制权。Diffusers库则满足了这一需求,允许用户在Python中根据特定需求自定义模型和提示来生成图像。它主要适用于HuggingFace上托管的模型,但对于在C站上支持Stable Diffusion WebUI的模型,需要一些特定的技巧。
本文主要陈述了如何使用Diffusers调用civitai中的sd扩散性模型中的checkpoint及lora。
服务器购买
建议购买腾讯云云服务器新加坡区域的GPU服务器。详细的购买流程可以看我之前的文章。
环境安装
代码语言:shell复制yum install -y git
adduser sd (创建账户sd)
passwd sd (创建密码)
usermod -aG wheel sd (增加sudo权限)
su - sd (切换为sd用户)
git clone https://github.com/huggingface/diffusers.git
wget https://repo.anaconda.com/archive/Anaconda3-2023.03-Linux-x86_64.sh
sh Anaconda3-2023.03-Linux-x86_64.sh
安装完成后执行 “bash”命令,重新载入bash终端,确保conda命令可用。
代码语言:shell复制conda create -n sd python=3.10.6
pip install diffusers
pip install transformers
pip install torch
pip install matplotlib
pip install numpy
pip install omegaconf
pip install accelerate
mkdir model
cd model
checkpoint和lora格式转换
将大模型 dreamlikePhotoreal20_dreamlikePhotoreal20.safetensors 和lora airfryer.safetensors(此lora是我训练的一个lora) 上传到sd用户的~/model目录中。
在~/model目录中,命令行执行如下命令,将stable diffussion的checkpoint模型转化为可以在diffusers中可以使用的模型。
代码语言:shell复制python ~/diffusers/scripts/convert_original_stable_diffusion_to_diffusers.py --checkpoint_path dreamlikePhotoreal20_dreamlikePhotoreal20.safetensors --dump_path dreamlikePhotoreal20/ --from_safetensors
其中,
--checkpoint_path 将要转换的检查点的路径。
--original_config_file 原始架构对应的YAML配置文件。
--num_in_channels 输入通道的数量。如果为None,将自动推断输入通道的数量。
--scheduler_type 要使用的调度器类型。应为'pndm','lms','ddim','euler','euler-ancestral','dpm'之一。
--pipeline_type 管道类型。其中之一为'FrozenOpenCLIPEmbedder','FrozenCLIPEmbedder','PaintByExample'。如果为None,将自动推断管道类型。
--image_size 模型训练时使用的图像尺寸。对于Stable Diffusion v1.X和Stable Siffusion v2 Base,请使用512。对于Stable Diffusion v2,请使用768。
--prediction_type 模型训练时使用的预测类型。对于Stable Diffusion v1.X和Stable Diffusion v2 Base,请使用'epsilon'。对于Stable Diffusion v2,请使用'v_prediction'。
--extract_ema 仅适用于同时具有EMA和非EMA权重的检查点。是否提取EMA权重。默认为False。添加--extract_ema以提取EMA权重。EMA权重通常用于生成更高质量的图像进行推理。非EMA权重通常用于继续微调。
--upcast_attention 注意力计算是否应始终进行上转换。在运行稳定扩散2.1时,这是必需的。
--from_safetensors 如果--checkpoint_path以safetensors格式,则使用safetensors加载检查点,而不是PyTorch。
--to_safetensors 是否将管道存储为safetensors格式。
--dump_path 输出模型的路径。
--device 要使用的设备(例如cpu,cuda:0,cuda:1等)。
--stable_unclip 如果这是一个稳定的unCLIP模型,请设置。其中之一为'txt2img'或'img2img'。
--stable_unclip_prior 如果这是一个稳定的unCLIP txt2img模型,请设置。选择要使用的先验。如果--stable_unclip设置为txt2img,默认选择karlo先验(https://huggingface.co/kakaobrain/karlo-v1-alpha/tree/main/prior)。
--clip_stats_path clip统计文件的路径。仅在稳定unclip模型的配置指定model.params.noise_aug_config.params.clip_stats_path时需要。
--controlnet 如果这是一个controlnet检查点,请设置标志。
--half 以半精度保存权重。
--vae_path 设置为路径、hub ID,以避免再次转换已转换的vae。
--pipeline_class_name 指定管道类名。
详见: https://github.com/huggingface/diffusers/blob/main/scripts/convert_original_stable_diffusion_to_diffusers.py
完成checkpoint模型的转化后,我们可能还需要依赖lora,做lora的转化。
代码语言:shell复制python ~/diffusers/scripts/convert_lora_safetensor_to_diffusers.py --base_model_path dreamlike-art/dreamlike-photoreal-2.0 --checkpoint_path ./airfryer.safetensors --dump_path ./airfryer
其中,
--base_model_path 基于diffusers格式的基础模型的路径。
--checkpoint_path 要转换的检查点的路径。
--dump_path 输出模型的路径。
--lora_prefix_unet safetensors中UNet权重的前缀。
--lora_prefix_text_encoder safetensors中文本编码器权重的前缀。
--alpha W = W0 alpha * deltaW 中的合并比例。
--to_safetensors 是否将管道存储为safetensors格式。
--device 要使用的设备(例如cpu,cuda:0,cuda:1等)。
详见: https://github.com/huggingface/diffusers/blob/main/scripts/convert_lora_safetensor_to_diffusers.py
这里需要说明一下,--alpha是一个很关键的参数,缺省是0.75,这个值设置得过大就容易过拟合。
这里给出我的例子。
alpha为0.75的情况
alpha为1.5的情况
alpha为0.5的情况
使用Diffusers和checkpoint及lora推理生成图片
使用以下代码片段完成推理
代码语言:python代码运行次数:0复制from diffusers import (
StableDiffusionPipeline,
PNDMScheduler,
LMSDiscreteScheduler,
DDIMScheduler,
EulerDiscreteScheduler,
EulerAncestralDiscreteScheduler,
DPMSolverMultistepScheduler,
UniPCMultistepScheduler,
)
def make_scheduler(name, config):
return {
"PNDM": PNDMScheduler.from_config(config),
"KLMS": LMSDiscreteScheduler.from_config(config),
"DDIM": DDIMScheduler.from_config(config),
"K_EULER": EulerDiscreteScheduler.from_config(config),
"K_EULER_ANCESTRAL": EulerAncestralDiscreteScheduler.from_config(config),
"DPMSolverMultistep": DPMSolverMultistepScheduler.from_config(config),
"UniPCM": UniPCMultistepScheduler.from_config(config),
}[name]
model_id = "./airfryer";
pipe = StableDiffusionPipeline.from_pretrained(
model_id,
torch_dtype=torch.float16,
safety_checker=None,
cache_dir="diffusers-cache",
local_files_only=False).to("cuda");
generator = torch.Generator("cuda").manual_seed(seed)
pipe.scheduler = make_scheduler(scheduler, self.pipe.scheduler.config)
seed = 9527
generator = torch.Generator("cuda").manual_seed(seed)
# generate image
output = pipe(
prompt="",
negative_prompt="",
guidance_scale=guidance_scale,
num_inference_steps=num_inference_steps,
generator=generator,
eta=0.5
)
for i, sample in enumerate(output.images):
output_path = f"/tmp/out-{seed}-{i}.png"
sample.save(output_path)