이 저장소는 AIGC 연구원이 LORA를 몇 줄로 사용할 수있는 가장 간단한 자습서 코드를 제공합니다. 이 핸드북을 사용하면 Huggingface 및 Cititai와 같은 활동적인 커뮤니티의 LORA 모델을 쉽게 플레이 할 수 있습니다.
이제 우리는 Diffusers의 T2i Adapter-diffusers 인 Controlnet-for-Diffusers를 지원합니다.
LORA (Low Rank Adaptation)의 저 순위 적응 (LORA)은 Microsoft가 원래 가중치를 동결시키면서 순위 파괴 행렬의 쌍을 학습함으로써 훈련 가능한 매개 변수의 수를 줄이기 위해 개발되었습니다. LORA는 전체 모델 대신 모델의 "잔류"를 미세 조정하려고 시도합니다.
어디
이 교육 트릭은 대규모 일반 기본 모델에서 맞춤형 모델을 고정시키는 데 매우 유용합니다. 공식 안정 확산의 상단에 다양한 텍스트 대 이미지 모델이 개발되었습니다. 이제 Lora를 사용하면 훨씬 적은 리소스로 자신의 모델을 효율적으로 훈련시킬 수 있습니다.
SAFETENSORS는 포옹 페이스가 방출하는 텐서를 안전하게 보관할 수있는 새로운 간단한 형식입니다. 효율성을 위해 많은 안정적인 확산 모델, 특히 LORA 모델이 Safetensors 형식으로 출시됩니다. Huggingface/Safetensors에서 더 많은 장점을 찾아 PIP 설치를 통해 설치할 수 있습니다.
pip install safetensors이 튜토리얼에서는 미리 훈련 된 LORA를 디퓨저 프레임 워크에로드하거나 삽입하는 것을 보여줍니다. 많은 흥미로운 프로젝트는 Huggingf 우리는 Cloneofsimo/Lora에 의해 훈련 된 Loras를 로딩, 병합 및 보간하는 것에 대해 매우 동기를 부여했습니다. 우리는 주로 디퓨저와 잘 호환되지 않는 SAFETENSORS 형식의 모델을 논의합니다.
전체 모델에는 필요한 모든 모듈 (LORA 층이 있거나없는 기본 모델)이 포함되며, 일반적으로 .ckpt 또는 .safetensors 형식으로 저장됩니다. 우리는 아래에 사용하는 방법을 보여주기 위해 아래 두 가지 예를 제공합니다.
Huggingface의 안정성/안정화 -1.
Civitai의 드림 셰이퍼.
.ckpt 또는 .safetensors 파일 만 다운로드 할 수 있습니다. 디퓨저는 직접로드하는 것을 지원하지 않지만 변환 스크립트를 제공합니다. 먼저 디퓨저를 로컬로 다운로드하십시오.
git clone https://github.com/huggingface/diffusers cd ./diffusers
# assume you have downloaded xxx.safetensors, it will out save_dir in diffusers format.
python ./scripts/convert_original_stable_diffusion_to_diffusers.py --checkpoint_path xxx.safetensors --dump_path save_dir --from_safetensors
# assume you have downloaded xxx.ckpt, it will out save_dir in diffusers format.
python ./scripts/convert_original_stable_diffusion_to_diffusers.py --checkpoint_path xxx.ckpt --dump_path save_dir그런 다음 모델을로드 할 수 있습니다
from diffusers import StableDiffusionPipeline
pipeline = StableDiffusionPipeline.from_pretrained(save_dir,torch_dtype=torch.float32)현재 Diffuser는 LORA (일반적으로 .safetensor 형식)로 부하 가중치를 지원할 수 없습니다. 여기서 우리는 우리의 시도를 공격적인 스타일로 보여줍니다. 우리는 또한 한 가지 예를 제공합니다.
파일 크기는 여분의 LORA 가중치 만 포함되므로 전체 모델보다 훨씬 작습니다. 이 경우 기본 모델을로드해야합니다. 안정 확산 1.5를 기본으로로드하는 것도 괜찮지 만 만족스러운 결과를 얻으려면 제안 된 기본 모델을 다운로드하는 것이 좋습니다.
우리의 방법은 매우 간단합니다. .Safetensor에서 무게를 꺼내고 LORA 중량을 지원하는 체중으로 병합하십시오. .safetensor를 다른 형식으로 변환하지 않으며 대신 기본 모델의 가중치를 업데이트합니다.
우리의 스크립트는 Huggingf 나를 믿으십시오. 정말 간단하고 당신은 그것을 만들 수 있습니다.
# the default mergering ratio is 0.75, you can manually set it
python convert_lora_safetensor_to_diffusers.py우리는이 문제에 대한 디퓨저를위한 PR을 만들었고, 여기서 변환 함수를 더욱 유연하게 날려 버립니다. 기다릴 수없는 경우 직접 확인할 수 있습니다. 곧 디퓨저로 병합 될 것입니다!
Diffusers는 LORA 모델을 훈련시키기 위해 간단한 TRAIN_TEXT_TO_IMAGE_LORA.py를 제공했습니다. 요구 사항을 설치하려면 지침을 따르십시오.
export MODEL_NAME= " CompVis/stable-diffusion-v1-4 "
export DATASET_NAME= " lambdalabs/pokemon-blip-captions "
accelerate launch --mixed_precision= " fp16 " train_text_to_image_lora.py
--pretrained_model_name_or_path= $MODEL_NAME
--dataset_name= $DATASET_NAME --caption_column= " text "
--resolution=512 --random_flip
--train_batch_size=1
--num_train_epochs=100 --checkpointing_steps=5000
--learning_rate=1e-04 --lr_scheduler= " constant " --lr_warmup_steps=0
--seed=42
--output_dir= " sd-pokemon-model-lora "
--validation_prompt= " cute dragon creature " --report_to= " wandb "위의 명령을 사용하여 모델을 훈련 한 후에는 훈련 된 LORA 가중치를로드 한 후 STABLEIFUSIONPIPIPLESE를 사용하여 추론을 수행 할 수 있습니다. 이 경우 SD-Pokemon-Model-Lora 인 LORA 가중치를로드하려면 output_dir를 전달해야합니다.
import torch
from diffusers import StableDiffusionPipeline
model_path = " your_path/sd-model-finetuned-lora-t4 "
pipe = StableDiffusionPipeline.from_pretrained( " CompVis/stable-diffusion-v1-4 " , torch_dtype=torch.float16)
pipe.unet.load_attn_procs(model_path)
pipe.to( " cuda " )
prompt = " A pokemon with green eyes and red legs. "
image = pipe(prompt, num_inference_steps=30, guidance_scale=7.5).images[0]
image.save( " pokemon.png " )현재 Diffusers는 UNET의 Train Lora 만 지원합니다. 우리는 PR을 지원하고 만들었습니다. 필요한 경우 PR에 문의하거나 문제를여십시오.
Colossalai는 이미 Lora를 지원합니다. 우리는 train_dreambooth_colossalai.py 상단에 몇 줄만 수정하면됩니다. 이 예는 Dreambooth를위한 것이지만 이미지 훈련에 정기적으로 텍스트를 쉽게 채택 할 수 있습니다. 생성 된 LORA 중량은 UNET의주의 층에만 해당됩니다. Colossalai는 아직 여러 모델을 지원하지 않으므로 텍스트 인코더를 지원하려면 디퓨저에서 Acceletate 프레임 워크를 사용하십시오.
from diffusers.loaders import AttnProcsLayers
from diffusers.models.cross_attention import LoRACrossAttnProcessor
# attention here! It is necessaray to init unet under ColoInitContext, not just lora layers
with ColoInitContext(device=get_current_device()):
unet = UNet2DConditionModel.from_pretrained(
args.pretrained_model_name_or_path,
subfolder= " unet " ,
revision=args.revision,
low_cpu_mem_usage=False
)
unet.requires_grad_(False)
# Set correct lora layers
lora_attn_procs = {}
for name in unet.attn_processors.keys ():
cross_attention_dim = None if name.endswith( " attn1.processor " ) else unet.config.cross_attention_dim
if name.startswith( " mid_block " ):
hidden_size = unet.config.block_out_channels[-1]
elif name.startswith( " up_blocks " ):
block_id = int(name[len( " up_blocks. " )])
hidden_size = list(reversed(unet.config.block_out_channels))[block_id]
elif name.startswith( " down_blocks " ):
block_id = int(name[len( " down_blocks. " )])
hidden_size = unet.config.block_out_channels[block_id]
lora_attn_procs[name] = LoRACrossAttnProcessor(
hidden_size=hidden_size, cross_attention_dim=cross_attention_dim
)
unet.set_attn_processor(lora_attn_procs)
lora_layers = AttnProcsLayers(unet.attn_processors)
# DDP
unet = gemini_zero_dpp(unet, args.placement)
# config optimizer for colossalai zero, set initial_scale to large value to avoid underflow
optimizer = GeminiAdamOptimizer(unet,
lr=args.learning_rate,
betas=(args.adam_beta1, args.adam_beta2),
weight_decay=args.adam_weight_decay,
eps=args.adam_epsilon,
initial_scale=2 ** 16,
clipping_norm=args.max_grad_norm)여기서 우리는 유일한 것은 Unet의 초기화 방법입니다. 로라 무게 만 절약하려면
torch_unet = get_static_torch_model(unet)
if gpc.get_local_rank(ParallelMode.DATA) == 0:
torch_unet = torch_unet.to(torch.float32)
torch_unet.save_attn_procs(save_path)그런 다음 추론하십시오
from diffusers import StableDiffusionPipeline
import torch
model_path = " sd-model-finetuned-lora "
pipe = StableDiffusionPipeline.from_pretrained( " CompVis/stable-diffusion-v1-4 " , torch_dtype=torch.float16)
pipe.unet.load_attn_procs(model_path)
pipe.to( " cuda " )
prompt = " A pokemon with green eyes and red legs. "
image = pipe(prompt, num_inference_steps=30, guidance_scale=7.5).images[0]
image.save( " pokemon.png " )생성 된 LORA 무게의 크기는 약 3MB 크기에 불과할 수 있습니다. 이것은 기본 설정 때문입니다. 크기를 늘리려면 LORA 레이어의 순위 (낮은 순위 분해의 차원)를 수동으로 설정할 수 있습니다.
lora_attn_procs[name] = LoRACrossAttnProcessor(hidden_size=hidden_size, cross_attention_dim=cross_attention_dim, rank=128)그런 다음 LORA 무게의 크기는 약 100-200MB입니다. LORA 층은 과잉하기 쉽습니다. 일반적으로 말하면, 배치 크기 = 64로 작은 데이터 세트 (1K 이미지 미만)에서 100-2000 단계 만 훈련하는 데 충분해야합니다.
(1) 병합 할 때 LORA의 무게를 수동으로 조정할 수 있습니까?
예, 여기 알파는 로라의 무게입니다. 우리는 유연한 휘파람 기능을 제공하는 디퓨저에 PR을 제출했습니다.
(2) LORA (.Safetensors) 만 지원하는 다른 형식으로 만 변환 할 수 있습니까?
당신은 할 수 있지만 우리는 제안하지 않습니다.이 문제를보십시오. 많은 제한 사항이 있습니다. 예를 들어, 우리의 스크립트는 모든 이름의 이름 지정을 가지고 있기 때문에 모든 .safetensors에 일반화 할 수는 없습니다. 또한, 현재 디퓨저 프레임 워크는 UNET의주의 레이어에 LORA를 추가하는 것을 지원하는 반면, Civitai의 많은 .Safetensors에는 텍스트 인코더와 같은 다른 모듈에 대한 LORA 가중치가 포함되어 있습니다. 그러나 Lora for Text Encoder는 곧 지원해야합니다.
(3) 둘 이상의 LORA 모델을 혼합 할 수 있습니까?
그렇습니다. 유일한 것은 두 번 병합하는 것입니다. 그러나 알파 (로라의 무게)를 조심스럽게 설정하고 알파가 너무 큰 경우 모델이 저하됩니다.
(4)이 프로젝트의 동기는 무엇입니까?
Civitai 플랫폼에는 많은 놀라운 모델이 있지만 대부분의 LORA 가중치는 SAFETENSORS 형식으로 디퓨저 사용자에게는 편리하지 않습니다. 따라서 디퓨저 에서이 로라를 사용할 수 있도록 변환 스크립트를 작성합니다. 우리는 이미 매우 성숙하지만 확산기와 완전히 다른 API를 가지고있는 안정적인 확산-부이의 대상이 아닙니다.