LoRA de imagem: treinar style/character em 30 min
- ⬜🎛️ ControlNet: condicionamento espacial preciso(Diffusion Models & Geração Multimodal)
Recomendamos completar os pré-requisitos antes de seguir, mas nada te impede de continuar.
Por que LoRA é a forma certa de personalizar diffusion
Antes de LoRA, personalizar SD significava treinar Dreambooth completo (atualiza todos os pesos do U-Net) — 24+ GB VRAM, checkpoints de 4-7 GB cada, lento para iterar. A entrada do LoRA (Hu et al. 2021, primeiro em NLP; portado para SD por kohya_ss em 2022) virou o jogo: arquivos de 50-200 MB, treino em GPU de consumidor, e composáveis (vários LoRAs ativos ao mesmo tempo).
A premissa empírica: os gradientes da fine-tuning vivem num subespaço de baixa dimensão. Ou seja, ΔW aprendido é "naturalmente low-rank". LoRA explora essa observação para reduzir parâmetros sem perder capacidade.
Ferramentas — qual escolher
| Tool | Foco | UX | Suporte | Quando usar |
|---|---|---|---|---|
| kohya_ss | Geral (SD 1.5, SDXL, SD3, Flux) | GUI Gradio + CLI | ★★★★★ | Padrão de fato; máxima customização |
| OneTrainer | SD 1.5, SDXL, Flux | GUI desktop limpa | ★★★★ | Iniciantes em LoRA SDXL |
| ai-toolkit (Ostris) | Flux principalmente | CLI + YAML config | ★★★★ | Estado da arte para Flux LoRAs |
| SimpleTuner (bghira) | SDXL, SD3, Flux, Pixart | CLI + config | ★★★★ | Pesquisa, multi-aspect ratio |
| Replicate / Civitai trainer | SDXL principalmente | Web UI hospedado | ★★★ | Sem GPU local; rápido |
| Diffusers train_dreambooth_lora.py | Geral, baixo nível | Script Python | ★★★ | Integração custom em pipeline |
Recomendação prática 2024-25: ai-toolkit do Ostris para Flux; kohya_ss para SDXL/SD3; Replicate se não tem GPU.
Dataset: o que importa de verdade
O erro mais comum de iniciante: 100 screenshots todas tiradas do mesmo jogo/personagem, mesma iluminação, mesma pose. O LoRA aprende isso (e só isso). Resultado: gera o personagem só naquela cenário específico. Diversidade do dataset é o que permite generalização.
Captioning automático: WD14 / BLIP / Florence-2
Escrever captions à mão para 30 imagens dói. Por sorte existem auto-captioners maduros:
| Captioner | Tipo de output | Quando usar |
|---|---|---|
| WD14 Tagger (SmilingWolf) | Booru tags ("1girl, blue_eyes, sitting") | Anime/illustrations; SD 1.5 anime LoRAs |
| BLIP-2 (Salesforce) | Frase natural ("a girl with blue eyes sitting on a chair") | Estilo realistic; SDXL e Flux |
| Florence-2 (Microsoft) | Densa, multi-task (caption + bboxes + OCR) | Estado da arte 2024; flex |
| JoyCaption (fancyfeast) | Captions detalhadas otimizadas para Flux | Flux LoRAs — qualidade superior |
| LLaVA-Next / Cogvlm | Caption muito detalhado via VLM | Quando você quer captions ricas mas é lento |
# Exemplo: WD14 + trigger word injection
from PIL import Image
from wd14_tagger import WD14Tagger # pseudocode
tagger = WD14Tagger("SmilingWolf/wd-v1-4-swinv2-tagger-v2")
trigger = "ohwx_character"
for img_path in glob("./dataset/*.png"):
img = Image.open(img_path)
tags = tagger.predict(img, threshold=0.35) # ["1girl", "blue_eyes", ...]
# Trigger word PRIMEIRO, sempre
caption = f"{trigger}, " + ", ".join(tags)
with open(img_path.replace(".png", ".txt"), "w") as f:
f.write(caption)Trigger word: invente algo único (ex: "ohwx", "myxch", "zxc7"). Use sempre — durante training e na inferência. Sem trigger word, o LoRA pode "vazar" no modelo base (qualquer mulher vira seu personagem).
Config de treino: o que cada parâmetro faz
# Exemplo de config para LoRA de personagem em Flux Dev
job: extension
config:
name: "myx_character_flux_v1"
process:
- type: 'sd_trainer'
training_folder: "output"
device: cuda:0
trigger_word: "myxch"
network:
type: "lora"
linear: 32 # rank — capacity da adaptação
linear_alpha: 32 # alpha — ganho efetivo (α/r = 1.0)
save:
dtype: float16
save_every: 500 # checkpoint periódico
max_step_saves_to_keep: 4
datasets:
- folder_path: "./dataset"
caption_ext: "txt"
caption_dropout_rate: 0.05 # 5% dos steps sem caption — regulariza
shuffle_tokens: false
resolution: [1024]
train:
batch_size: 1
steps: 2500 # ~2500 para 20 imgs; ajustar para tamanho dataset
gradient_accumulation_steps: 1
train_unet: true
train_text_encoder: false # economiza VRAM; geralmente OK
gradient_checkpointing: true # troca tempo por VRAM
noise_scheduler: "flowmatch" # Flux usa rectified flow
optimizer: "adamw8bit"
lr: 1e-4 # típico: 1e-4 a 5e-4 para Flux
ema_config:
use_ema: true
ema_decay: 0.99
dtype: bf16
model:
name_or_path: "black-forest-labs/FLUX.1-dev"
is_flux: true
quantize: true # NF4 quant para caber em 24GB
sample:
sampler: "flowmatch"
sample_every: 250
width: 1024
height: 1024
prompts:
- "myxch character standing in a forest, cinematic lighting"
- "myxch character portrait, neutral background"
- "myxch character riding a bike in a city"Lendo a curva de loss (e o que ela NÃO diz)
Lei fundamental do LoRA training: sample, sample, sample. Configure com 4-6 prompts de validação fixos (com e sem trigger word, em poses/contextos diferentes do dataset). A curva de loss é um indicador secundário.
Qual premissa empírica justifica adaptar o modelo por matrizes de posto baixo em vez de atualizar todos os pesos?
Variantes avançadas: DoRA, LoKr, LoHa
| Método | Ideia | Quando usar |
|---|---|---|
| LoRA (Hu 2021) | ΔW = A·B (rank-r) | Padrão; sempre uma boa baseline |
| DoRA (Liu 2024) | Decompõe ΔW em magnitude + direção; treina ambos separadamente. Liu et al. ICML 2024 | Mais expressivo que LoRA para mesmo rank; ~10-20% melhor em benchmarks |
| LoHa (Yeh et al. 2023) | Hadamard product de duas LoRAs — mais capacity | Quando rank baixo não basta mas você quer params controlados |
| LoKr | Kronecker product — alta capacity, poucos params | Estilos complexos com poucas imagens |
| LyCORIS | Família que engloba LoHa, LoKr, etc. + algoritmos novos | kohya_ss tem suporte nativo |
Inferência: como usar o LoRA gerado
from diffusers import FluxPipeline
import torch
pipe = FluxPipeline.from_pretrained(
"black-forest-labs/FLUX.1-dev",
torch_dtype=torch.bfloat16,
).to("cuda")
# Carrega LoRA treinado
pipe.load_lora_weights("./output/myx_character_flux_v1/myx_character_flux_v1.safetensors")
pipe.fuse_lora(lora_scale=0.8) # 0..1.5; 0.8-1.0 típico
img = pipe(
prompt="myxch character in a snowy mountain, cinematic, 35mm film",
num_inference_steps=28,
guidance_scale=3.5, # Flux usa CFG baixo
width=1024, height=1024,
).images[0]
img.save("test.png")
# Opcional: combinar múltiplos LoRAs
pipe.load_lora_weights("./style_anime.safetensors", adapter_name="style")
pipe.set_adapters(["myx_character_flux_v1", "style"], adapter_weights=[1.0, 0.6])Decisão: LoRA vs Dreambooth vs Textual Inversion
📋 Você quer personalizar um modelo de imagem para um personagem específico
Tem o melhor trade-off: qualidade próxima a Dreambooth full, arquivos pequenos (~150 MB), treinável em consumer GPU, composable com outros LoRAs. Estado da arte da comunidade desde 2022.
Alt: Dreambooth full
Alt: Checkpoint 4-7 GB, mais VRAM no treino, não composable, raramente melhor que LoRA bem feito
Alt: Textual Inversion
Alt: Só treina embedding (5 KB) — limitado em capacidade; ok para conceitos simples, ruim para personagens detalhados
Alt: ControlNet
Alt: Não personaliza identidade; condiciona estrutura. Use junto, não no lugar
Alt: IP-Adapter
Alt: Subject reference leve, mas menos consistente que LoRA dedicado
Perguntas que sobram
❓ Treinei um LoRA em SDXL — funciona em SD3 ou Flux?
❓ Por que recomendam não treinar o text encoder em LoRA de Flux?
❓ Qual a melhor GPU para treinar Flux LoRA em casa?
❓ Como precificar treino na nuvem (Replicate / RunPod)?
Papers e tools
Próximo: ComfyUI como engenharia de workflow — JSON versionável, custom nodes em Python, API server e ComfyUI Deploy para produção. Sai do "clica e arrasta" e entra em automação real.
Perguntas frequentes
❓ Quantas imagens preciso para treinar um estilo?
❓ Por que o modelo treinado ignora o prompt?
❓ Legenda das imagens de treino importa?
Fixando
Qual é o erro de conjunto de dados mais comum, e o que ele produz?
Por que a curva de perda é considerada indicador secundário nesse tipo de treino?
Terminou de ler?
Marcar como concluído registra o XP, mantém sua sequência e coloca 3 cartas deste módulo na fila de revisão espaçada.
Próximos passos sugeridos
Temas deste módulo
Discussão
Carregando comentários…