上一篇《使用Diffusers调用civitai中的checkpoint及LoRA》使用了Diffusers的脚本将C站(civitai)的checkpoint及LoRA转化成Diffusers可以识别的格式,然后供Diffusers使用。
lora方面,上篇的方法有这样几个问题:
本文提供的解决方案运行良好且快速, 虽然它需要对 LoRA alpha 权重进行额外管理, 我们需要创建一个变量来记住当前的 LoRA 权重α。因为加载 LoRA 代码只是添加将 LoRA 中的 A 和 B 矩阵放在一起。
然后与主检查点模型权重 W 合并。
要删除 LoRA 权重, 我们需要负 -α 来删除 LoRA 权重, 或重新创建pipeline。
使用 LoRA 的另一种方法是修改执行模块转发过程的代码, 并在计算文本嵌入和注意力分数期间引入 LoRA 权重。
这就是Diffusers在v0.20.0之前的LoraLoaderMixin的LoRA加载方法。这种方法的好处是没有更新模型权重, 我们可以轻松重置 LoRA 并提供一个新的α来定义 LoRA 权重。但这种方式由于和越南大佬做的sd-webui的方式不同,导致使用Diffusers的很多困扰。
在Diffusers v0.20.0之后,这些问题部分性的解决了。就是说,我们可以使用Diffusers将checkpoint模型与LoRA一起加载,并获得使用sd-webui生成完全相同的结果.
先来看看diffusers docs中推荐的方式。https://huggingface.co/docs/diffusers/v0.20.0/en/training/lora。
import torch
from diffusers import StableDiffusionPipeline
pipe = StableDiffusionPipeline.from_pretrained(
"emilianJR/chilloutmix_NiPrunedFp32Fix",
torch_dtype = torch.float16,
safety_checker = None
)
pipe = pipe.to("cuda")
lora_path = "<path/to/lora.safetensors>"
pipe.load_lora_weights(lora_path)
seed = int.from_bytes(os.urandom(2), "big")
generator = torch.Generator("cuda").manual_seed(seed)
image = pipe(
prompt="(masterpiece),(best quality),(ultra-detailed),1boy, full body, chibi, yellow, outdoors, beret",
negative_prompt="(low quality:1.3), (worst quality:1.3)",
width=512,
height=768,
guidance_scale=9,
num_inference_steps=30,
generator=generator
).images[0]
output_path = f"/tmp/out-{seed}.png"
image.save(output_path)
只需一行代码: pipe.load_lora_weights(lora_path) ,就可以完成lora模型的加载。如果需要加载多个lora,多次调用pipe.load_lora_weights(lora_path) 即可。
备注:
<path/to/lora.safetensors>是将C站的LoRA下载下来的*.safetensors放在本地硬盘的具体路径和文件名;
emilianJR/chilloutmix_NiPrunedFp32Fix来自图片中红色方框中的内容,无需手动下载。
如果希望下载一次后使用本地缓存,则可以加入cache_dir参数。如下示例:
import torch
from diffusers import StableDiffusionPipeline
pipe = StableDiffusionPipeline.from_pretrained(
"emilianJR/chilloutmix_NiPrunedFp32Fix"
, torch_dtype = torch.float16
, safety_checker = None
, cache_dir="diffusers-cache"
).to("cuda")
lora_path = "<path/to/lora.safetensors>"
pipe.load_lora_weights(lora_path)
要重置 LoRA, 只需调用函数 unload_lora_weights 即可:
pipe.unload_lora_weights()
这里我们可以发现一个问题,就是我们在sd-webui中,可以设置lora的权重,比如我们在prompt中加入:<lora:myLora:0.5>。但这里是不支持的。怎么办呢?Andrew Zhu提供了一段代码来解决这个问题:
pipe.unload_lora_weights()
lora_path = "<path/to/lora.safetensors>"
lora_w = 0.5
pipe._lora_scale = lora_w
state_dict, network_alphas = pipe.lora_state_dict(
lora_path
)
for key in network_alphas:
network_alphas[key] = network_alphas[key] * lora_w
#network_alpha = network_alpha * lora_w
pipe.load_lora_into_unet(
state_dict = state_dict
, network_alphas = network_alphas
, unet = pipe.unet
)
pipe.load_lora_into_text_encoder(
state_dict = state_dict
, network_alphas = network_alphas
, text_encoder = pipe.text_encoder
)
我们看看这个提示词在两边的效果对比:
(masterpiece),(best quality),(ultra-detailed),1boy, full body, chibi, yellow, outdoors, beret<lora:blindbox_v1_mix:0.5>
Negative prompt: (low quality:1.3), (worst quality:1.3)
Steps: 30, Sampler: Euler, CFG scale: 9, Seed: 1875473241, Size: 512x768, Model hash: fc2511737a, Model: chilloutmix_NiPrunedFp32Fix, Lora hashes: "blindbox_v1_mix: ee3fbe5a8576", Version: v1.3.2
能看出有区别吗?
本文介绍了Diffusers对Lora支持的最新进展。通过Diffusers v0.20.0的更新,我们可以通过Diffusers获得与sd-webui相同的效果,便于不同框架之间的效果对比。当然,目前依然有若干问题需要解决:
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。