Text-to-Image
Diffusers
stable-diffusion
stable-diffusion-diffusers
lora
Eval Results (legacy)
whosouravsharma's picture
Point scripts at checkpoints/ prefix
d6f5ba0 verified
Raw History Blame Contribute Delete
4.4 kB
# /// script
# requires-python = ">=3.10"
# dependencies = [
# "torch",
# "diffusers>=0.31",
# "transformers>=4.44",
# "peft>=0.13",
# "huggingface_hub>=0.24",
# "pillow",
# ]
# ///
"""Stage 3 of training: render the held-out eval prompts from a checkpoint.
# baseline, before training - run this FIRST
hf jobs uv run --flavor a10g-small --timeout 1h --secrets HF_TOKEN \\
-e CHECKPOINT=base training/sample_job.py
# any checkpoint afterwards
hf jobs uv run --flavor a10g-small --timeout 1h --secrets HF_TOKEN \\
-e CHECKPOINT=checkpoint-2000 training/sample_job.py
Validation loss on a diffusion fine-tune correlates weakly with how the
output actually looks, so it cannot be the only signal. This renders the 50
prompts in eval_prompts.json - drawn from validation groups, so the model has
never trained on them - at a fixed seed, and pushes a contact sheet to the
model repo.
Run CHECKPOINT=base before training starts. Without a baseline you cannot
tell improvement from drift.
"""
import json
import os
from pathlib import Path
import torch
from diffusers import StableDiffusionPipeline
from huggingface_hub import HfApi, hf_hub_download
from PIL import Image
DATASET_REPO = "whosouravsharma/text-to-image-diffusiondb-2M"
DATASET_REVISION = os.environ.get("DATASET_REVISION", "v2-clean")
MODEL_REPO = os.environ.get("MODEL_REPO", "whosouravsharma/diffusiondb-sd15-lora")
BASE_MODEL = "runwayml/stable-diffusion-v1-5"
# "base" renders vanilla SD 1.5 with no adapter - the comparison baseline.
CHECKPOINT = os.environ.get("CHECKPOINT", "base")
CHECKPOINT_DIR = "checkpoints"
STEPS = int(os.environ.get("STEPS", 30))
GUIDANCE = float(os.environ.get("GUIDANCE", 7.5))
SEED = int(os.environ.get("SEED", 42))
COLUMNS = 5
THUMB = 320
def contact_sheet(images: list[Image.Image]) -> Image.Image:
rows = (len(images) + COLUMNS - 1) // COLUMNS
sheet = Image.new("RGB", (COLUMNS * THUMB, rows * THUMB), (18, 18, 22))
for index, image in enumerate(images):
sheet.paste(
image.resize((THUMB, THUMB), Image.LANCZOS),
((index % COLUMNS) * THUMB, (index // COLUMNS) * THUMB),
)
return sheet
def main() -> None:
if not torch.cuda.is_available():
raise SystemExit("No GPU. Run this on a GPU flavor, e.g. a10g-small.")
prompts = json.loads(Path(hf_hub_download(
DATASET_REPO, "eval_prompts.json", repo_type="dataset",
revision=DATASET_REVISION,
)).read_text())
print(f"{len(prompts)} eval prompts from {DATASET_REPO}@{DATASET_REVISION}")
pipeline = StableDiffusionPipeline.from_pretrained(
BASE_MODEL, torch_dtype=torch.float16, safety_checker=None,
).to("cuda")
pipeline.set_progress_bar_config(disable=True)
if CHECKPOINT != "base":
print(f"Loading LoRA {CHECKPOINT} ...")
pipeline.load_lora_weights(
MODEL_REPO, weight_name="pytorch_lora_weights.safetensors",
subfolder=f"{CHECKPOINT_DIR}/{CHECKPOINT}",
)
images = []
for index, prompt in enumerate(prompts):
# Same seed per prompt index across checkpoints, so differences come
# from the weights rather than from the noise.
generator = torch.Generator("cuda").manual_seed(SEED + index)
images.append(pipeline(
prompt, num_inference_steps=STEPS,
guidance_scale=GUIDANCE, generator=generator,
).images[0])
if (index + 1) % 10 == 0:
print(f" {index + 1}/{len(prompts)}", flush=True)
out = Path("samples") / CHECKPOINT
out.mkdir(parents=True, exist_ok=True)
for index, image in enumerate(images):
image.save(out / f"{index:03}.png")
contact_sheet(images).save(out / "grid.jpg", quality=92)
(out / "prompts.json").write_text(json.dumps(
{"checkpoint": CHECKPOINT, "steps": STEPS, "guidance": GUIDANCE,
"seed": SEED, "prompts": prompts}, indent=2))
# MODEL_REPO is created ahead of time, with its card, rather than by the job.
api = HfApi()
api.upload_folder(
folder_path=str(out), path_in_repo=f"samples/{CHECKPOINT}",
repo_id=MODEL_REPO, repo_type="model",
commit_message=f"Eval samples for {CHECKPOINT}",
)
print(f"\nPushed to https://huggingface.co/{MODEL_REPO}"
f"/tree/main/samples/{CHECKPOINT}")
if __name__ == "__main__":
main()