TobiasLogic commited on
Commit
6c311ad
·
verified ·
1 Parent(s): dc5c0f9

Publish PixelModel v6: MMDiT + REPA, 150k steps, FID 23.62 at cfg 3.0

Browse files
.gitattributes CHANGED
@@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ examples.png filter=lfs diff=lfs merge=lfs -text
37
+ model.png filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,192 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ pipeline_tag: text-to-image
4
+ language:
5
+ - en
6
+ tags:
7
+ - text-to-image
8
+ - diffusion
9
+ - rectified-flow
10
+ - mmdit
11
+ - tiny
12
+ - custom-code
13
+ ---
14
+
15
+ # PixelModel v6 🖼️
16
+
17
+ <img src="examples.png" alt="Two 256px images generated by PixelModel v6: a lighthouse on a cliff at sunset, and a cup of coffee on a wooden table" style="width: 100%; max-width: 600px;">
18
+
19
+ *"a lighthouse on a cliff at sunset" / "a cup of coffee on a wooden table", cfg 4.0, single draw each, not
20
+ cherry-picked from multiple seeds*
21
+
22
+ PixelModel v6 is a 155,090,448 parameter text-to-image diffusion transformer. It generates 256x256
23
+ images in 50 sampling steps and it trained in about 55 hours across two A100s.
24
+
25
+ Where [v5](https://huggingface.co/bench-labs/PixelModel-v5) changed the data and kept v4's
26
+ architecture byte for byte, v6 changes the architecture and keeps v5's data. v5's own README ended
27
+ with a diagnosis: the model had learned appearance thoroughly and topology poorly, and topology is
28
+ what capacity buys. This is that bet.
29
+
30
+ ## What actually changed
31
+
32
+ Six real architecture changes, not one, which is a departure from this line's usual practice of
33
+ isolating a single variable per release. Each change has independent literature support; the
34
+ combination does not, and that is worth being upfront about rather than implying six papers'
35
+ results simply add up.
36
+
37
+ **Joint attention instead of cross-attention.** v4 and v5 read text through cross-attention, the way
38
+ PixArt-alpha does it. v6 concatenates image and text tokens into one sequence and runs joint
39
+ self-attention over both, the way SD3's MMDiT does it, so text tokens can attend to image tokens and
40
+ not just the reverse.
41
+
42
+ **T5 instead of CLIP-only conditioning.** The joint stream is built from `google/flan-t5-base`
43
+ hidden states rather than CLIP token embeddings. CLIP's pooled vector is kept, but only for the
44
+ global adaLN conditioning signal. T5 conditioning is the specific change PixArt-alpha, DeepFloyd IF,
45
+ and SD3 all made for prompt adherence, and v5's README named exactly this failure mode: prompts
46
+ asking for one object in an empty scene often returned the scene without the object.
47
+
48
+ **2D RoPE instead of additive sincos position embeddings.** Image tokens get axial rotary position
49
+ encoding, text tokens get standard 1D rotary encoding. This is also what makes a future higher
50
+ resolution fine-tune cheap: RoPE carries no learned parameters, so a checkpoint trained at 256px can
51
+ extend to a larger token grid without retraining or interpolating a position embedding table.
52
+
53
+ **QK-norm and SwiGLU.** RMSNorm on queries and keys before attention, and a SwiGLU MLP in place of
54
+ GELU. Both are standard modern stabilizers, included because a bigger model trains less forgivingly
55
+ than a 40M one.
56
+
57
+ **REPA.** An auxiliary loss projecting mid-stack image token hidden states to align with frozen
58
+ DINOv2-small features of the same image, cosine similarity, weight scheduled to peak early and decay
59
+ to exactly zero by step 105,000. This is the one item on this list without solid precedent at this
60
+ scale: the original REPA paper is class-conditional ImageNet at 675M parameters, and v5's own
61
+ planning notes flagged that transfer to text-conditional generation at a fraction of that size as
62
+ genuinely unverified. The decay schedule follows the follow-up finding that the alignment loss helps
63
+ early and can hurt if left on too long.
64
+
65
+ **More capacity.** dim 512, depth 16, heads 8: 155.1M trainable, versus v5's 40M. Still well short of
66
+ SD1.5's 860M UNet or SDXL's 2.6B, but the largest this line has been.
67
+
68
+ <img src="pixelmodel-v6-params.png" alt="Trainable backbone size by version, v4 and v5 at 40M, v6 at 155.1M" style="width: 100%; max-width: 700px;">
69
+
70
+ The frozen VAE also moved from `sd-vae-ft-mse` to `madebyollin/sdxl-vae-fp16-fix`, a drop-in upgrade
71
+ at the same latent shape.
72
+
73
+ ## Training
74
+
75
+ <img src="pixelmodel-v6-loss.png" alt="Training loss, diffusion and REPA components, over 150,000 steps" style="width: 100%; max-width: 860px;">
76
+
77
+ 150,000 steps at batch 192 on the same 2,986,571 image CC12M-recaptioned set v5 used, about 9.7
78
+ epochs. AdamW at 2e-4, cosine decay after a 1,500 step warmup, EMA at 0.9999, 10% caption dropout,
79
+ gradient checkpointing throughout. The REPA loss ran at peak weight for the first 40% of training,
80
+ decayed linearly through the next 30%, and sat at exactly zero for the final 30%, both to follow the
81
+ early-stopping finding above and because computing DINOv2 targets costs real throughput: the run held
82
+ 0.86 steps/s while REPA was active and 1.39 steps/s once it turned off.
83
+
84
+ <img src="pixelmodel-v6-val.png" alt="Held-out validation loss falling monotonically from 0.938 to 0.798" style="width: 100%; max-width: 860px;">
85
+
86
+ Held-out loss on a fixed 4,096-pair split, evaluated every 2,000 steps, fell without interruption
87
+ from 0.938 to 0.798 across the entire run. No overfitting turn-up at any point, same clean shape v5
88
+ reported.
89
+
90
+ This run was not a clean single continuous job. It moved between two rented A100s partway through
91
+ (a direct box-to-box transfer once the economics of a cheaper card made sense, verified byte-identical
92
+ by checksum before the first box was released), and survived two host-level outages on the vast.ai
93
+ side, both recovered from the last saved checkpoint. Total lost progress across both interruptions
94
+ was under a thousand steps out of 150,000. Worth stating plainly rather than pretending the run was
95
+ tidier than it was.
96
+
97
+ ## Results
98
+
99
+ Measured on 5,000 MS-COCO val2014 images at 256 center crop, `torchmetrics` FID at 2048 features and
100
+ `torchmetrics` CLIPScore with `openai/clip-vit-base-patch32`. Identical protocol to v4 and v5.
101
+
102
+ | | FID ↓ | CLIP ↑ |
103
+ |---|---|---|
104
+ | PixelModel v4 | 39.54 | 28.04 |
105
+ | PixelModel v5 | 34.06 | 29.27 |
106
+ | **PixelModel v6, cfg 3.0** | **23.62** | 30.43 |
107
+ | real photographs | n/a | 30.05 |
108
+
109
+ v6 beats v5's best FID by over 10 points at every guidance scale tested, not just at one cherry-picked
110
+ value. Full sweep, same 5,000 image set and 50 sampling steps throughout:
111
+
112
+ | cfg | FID ↓ | CLIP ↑ |
113
+ |---|---|---|
114
+ | 2.0 | 25.65 | 29.65 |
115
+ | **3.0** | **23.62** | 30.43 |
116
+ | 4.0 | 23.77 | 30.81 |
117
+ | 5.0 | 24.42 | 31.06 |
118
+ | 6.0 | 25.10 | 31.12 |
119
+ | 7.0 | 26.26 | 31.16 |
120
+ | 8.0 | 26.87 | 31.17 |
121
+
122
+ FID bottoms at cfg 3.0 and rises steadily past it, the usual guidance tradeoff: more weight on the
123
+ text condition pulls generations away from the real-image manifold even as it pulls them closer to
124
+ the prompt. cfg 3.0 is the reported default. Worth flagging rather than celebrating: CLIP score
125
+ crosses the real-photograph baseline (30.05) starting around cfg 4.0 and keeps climbing to 31.17.
126
+ That is not v6 out-photographing real photographs, it is high guidance making generations more
127
+ literal about the prompt than an actual photo ever is, which CLIP score rewards and FID does not. Use
128
+ FID, not CLIP, to pick a guidance scale.
129
+
130
+ ## What it does well and what it does not
131
+
132
+ Judged across several hundred samples during training, not just the checkpoint above.
133
+
134
+ It is good at material, light, and increasingly at structure that v5 could not hold: food, faces of
135
+ common animals, latte foam texture, boat masts and sails, neon-lit streets. Where v5's README singled
136
+ out faces and animal heads as a weak point, v6 renders recognizable dog and fox faces reliably by the
137
+ back half of training, something no earlier version in this line managed.
138
+
139
+ It is still uneven on rare subjects. Across many samples of the same fox prompt, output quality
140
+ varied far more than for common subjects like coffee or strawberries, which is a direct read on
141
+ training data frequency in CC12M rather than a model defect: the architecture change did not fix data
142
+ scarcity, it just makes better use of what is there.
143
+
144
+ A watermark and ghost-text artifact shows up intermittently, most often on the lighthouse and boat
145
+ prompts: faint illegible text-like marks bled in from CC12M's watermarked stock photography, the same
146
+ failure family v5 documented for actual text rendering. It did not fully train out by step 150,000.
147
+
148
+ ## Specification
149
+
150
+ | | |
151
+ |---|---|
152
+ | trainable parameters | 155,090,448 |
153
+ | frozen VAE, `sdxl-vae-fp16-fix` | 83,653,863 |
154
+ | frozen text encoder, CLIP ViT-B/32 | 63,165,952 |
155
+ | frozen text encoder, T5-base | 109,628,544 |
156
+ | **combined total** | **411,538,807** |
157
+ | architecture | MMDiT, dim 512, depth 16, heads 8, patch 2 |
158
+ | tokens | 256 image (16x16 over a 32x32x4 latent) + 32 text |
159
+ | objective | rectified flow, target `x1 - x0`, logit-normal timesteps |
160
+ | conditioning | joint attention on T5 tokens, plus adaLN-zero from CLIP pooled + timestep |
161
+ | resolution | 256x256 |
162
+ | sampling | 50 steps, cfg 3.0 default (23.62 FID); see cfg sweep above for the tradeoff |
163
+
164
+ All parameter counts above are the released backbone. Training also carried a small REPA projection
165
+ head (459,648 params, 155,550,096 total while training) that only ever fed the auxiliary alignment
166
+ loss; it has no role in sampling and is dropped from the published weights.
167
+
168
+ ## Usage
169
+
170
+ ```bash
171
+ python main.py "a bowl of ramen with a soft boiled egg" --out ramen.png --cfg 3.0 --steps 50
172
+ ```
173
+
174
+ As with every model in this line the weights are also stored as a PNG. `model.png` is not a picture
175
+ of the network, it is the network, with each parameter packed across the red and green channels of
176
+ one pixel.
177
+
178
+ ## Files
179
+
180
+ | file | contents |
181
+ |---|---|
182
+ | `model.safetensors` | the trainable MMDiT backbone only, fp32. VAE, CLIP, and T5 load fresh from their own HF repos at inference time, same convention as v4 and v5 despite what their READMEs said |
183
+ | `model.png` | the same backbone weights as an image, fp16, packed via `png_codec.py`. Verified bit-exact against `model.safetensors` (rounded to fp16) before upload |
184
+ | `model_png.json` | manifest `png_codec.py` needs to decode `model.png` back into a state dict |
185
+ | `png_codec.py` | the PNG weight codec, encode and decode |
186
+ | `dit_v6.py` | the model |
187
+ | `train_v6.py` | training loop, REPA schedule, held-out split |
188
+ | `prep_v6.py` | streams CC12M-recaptioned, encodes latents, caches tokens |
189
+ | `build_eval_set.py` | builds the 5,000 image COCO val2014 eval set |
190
+ | `eval_v6.py` | FID / CLIPScore protocol and cfg sweep |
191
+ | `preview.py` | quick sampling CLI for spot checks |
192
+ | `main.py` | inference |
build_eval_set.py ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import io
5
+ import json
6
+ import os
7
+ import random
8
+ import zipfile
9
+ from concurrent.futures import ThreadPoolExecutor
10
+
11
+ import numpy as np
12
+ import requests
13
+ from PIL import Image
14
+
15
+ ANN_URL = "http://images.cocodataset.org/annotations/annotations_trainval2014.zip"
16
+
17
+ def csr(img, size):
18
+ img = img.convert("RGB")
19
+ w, h = img.size
20
+ s = min(w, h)
21
+ l, t = (w - s) // 2, (h - s) // 2
22
+ return np.asarray(img.crop((l, t, l + s, t + s)).resize((size, size), Image.BICUBIC), dtype=np.uint8)
23
+
24
+ def fetch_one(item, size):
25
+ url, cap = item
26
+ for _ in range(3):
27
+ try:
28
+ r = requests.get(url, timeout=15)
29
+ if r.status_code == 200:
30
+ return csr(Image.open(io.BytesIO(r.content)), size), cap
31
+ except Exception:
32
+ pass
33
+ return None
34
+
35
+ def main():
36
+ ap = argparse.ArgumentParser()
37
+ ap.add_argument("--work", default="/root/v6cache")
38
+ ap.add_argument("--n", type=int, default=5000)
39
+ ap.add_argument("--size", type=int, default=256)
40
+ ap.add_argument("--seed", type=int, default=0)
41
+ ap.add_argument("--workers", type=int, default=48)
42
+ args = ap.parse_args()
43
+ os.makedirs(args.work, exist_ok=True)
44
+
45
+ out_path = os.path.join(args.work, "eval_256.npz")
46
+ if os.path.exists(out_path):
47
+ print(f"[eval-set] already exists at {out_path}", flush=True)
48
+ return
49
+
50
+ ann_path = os.path.join(args.work, "captions_val2014.json")
51
+ if not os.path.exists(ann_path):
52
+ print("[eval-set] downloading annotations", flush=True)
53
+ z = os.path.join(args.work, "ann.zip")
54
+ with requests.get(ANN_URL, stream=True, timeout=120) as r:
55
+ with open(z, "wb") as f:
56
+ for chunk in r.iter_content(1 << 20):
57
+ f.write(chunk)
58
+ with zipfile.ZipFile(z) as zf:
59
+ with zf.open("annotations/captions_val2014.json") as src, open(ann_path, "wb") as dst:
60
+ dst.write(src.read())
61
+ os.remove(z)
62
+
63
+ ann = json.load(open(ann_path))
64
+ url_by_id = {im["id"]: im["coco_url"] for im in ann["images"]}
65
+ cap_by_id = {}
66
+ for a in ann["annotations"]:
67
+ cap_by_id.setdefault(a["image_id"], a["caption"])
68
+ items = [(url_by_id[i], cap_by_id[i]) for i in cap_by_id if i in url_by_id]
69
+ random.Random(args.seed).shuffle(items)
70
+ print(f"[eval-set] {len(items)} val2014 pairs available, target {args.n}", flush=True)
71
+
72
+ imgs, caps = [], []
73
+ pool = ThreadPoolExecutor(max_workers=args.workers)
74
+ idx, batch = 0, 64
75
+ while len(imgs) < args.n and idx < len(items):
76
+ chunk = items[idx:idx + batch]
77
+ idx += batch
78
+ results = [r for r in pool.map(lambda it: fetch_one(it, args.size), chunk) if r is not None]
79
+ for a, c in results:
80
+ imgs.append(a); caps.append(c)
81
+ if idx % (batch * 20) == 0:
82
+ print(f"[eval-set] {len(imgs)}/{args.n}", flush=True)
83
+
84
+ imgs = np.stack(imgs[:args.n])
85
+ caps = np.array(caps[:args.n], dtype=object)
86
+ np.savez(out_path, images=imgs, captions=caps)
87
+ print(f"[eval-set] DONE {imgs.shape} -> {out_path}", flush=True)
88
+
89
+ if __name__ == "__main__":
90
+ main()
config.json ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architecture": "latent-mmdit",
3
+ "objective": "rectified-flow",
4
+ "dit": {
5
+ "dim": 512,
6
+ "depth": 16,
7
+ "heads": 8,
8
+ "patch": 2,
9
+ "latent_ch": 4,
10
+ "latent_size": 32,
11
+ "mlp_hidden": 1408,
12
+ "t5_len": 32
13
+ },
14
+ "vae": "madebyollin/sdxl-vae-fp16-fix",
15
+ "text_encoders": {
16
+ "joint_stream": "google/flan-t5-base",
17
+ "global_conditioning": "openai/clip-vit-base-patch32"
18
+ },
19
+ "max_tokens": {
20
+ "t5": 32,
21
+ "clip": 40
22
+ },
23
+ "trainable_parameters": 155090448,
24
+ "total_parameters_incl_frozen": 411538807,
25
+ "sampling": {
26
+ "steps": 50,
27
+ "cfg": 3.0
28
+ },
29
+ "training": {
30
+ "steps": 150000,
31
+ "batch": 192,
32
+ "dataset": "undefined443/cc12m-wds-coco-recaptioned, 2986571 images",
33
+ "final_val_loss": 0.7982857534661889
34
+ },
35
+ "eval": {
36
+ "fid": 23.62,
37
+ "clip_score": 30.43,
38
+ "cfg_sweep": [
39
+ {"cfg": 2.0, "fid": 25.65, "clip_score": 29.65},
40
+ {"cfg": 3.0, "fid": 23.62, "clip_score": 30.43},
41
+ {"cfg": 4.0, "fid": 23.77, "clip_score": 30.81},
42
+ {"cfg": 5.0, "fid": 24.42, "clip_score": 31.06},
43
+ {"cfg": 6.0, "fid": 25.10, "clip_score": 31.12},
44
+ {"cfg": 7.0, "fid": 26.26, "clip_score": 31.16},
45
+ {"cfg": 8.0, "fid": 26.87, "clip_score": 31.17}
46
+ ],
47
+ "n": 5000,
48
+ "dataset": "MS-COCO val2014, 256 center crop",
49
+ "protocol": "torchmetrics FrechetInceptionDistance + CLIPScore (openai/clip-vit-base-patch32)"
50
+ }
51
+ }
dit_v6.py ADDED
@@ -0,0 +1,233 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import math
4
+ import torch
5
+ import torch.nn as nn
6
+ import torch.nn.functional as F
7
+ import torch.utils.checkpoint
8
+
9
+ def modulate(x, shift, scale):
10
+ return x * (1 + scale.unsqueeze(1)) + shift.unsqueeze(1)
11
+
12
+ def timestep_embedding(t, dim, max_period=10000):
13
+ half = dim // 2
14
+ freqs = torch.exp(-math.log(max_period) * torch.arange(half, device=t.device) / half)
15
+ args = t[:, None].float() * freqs[None]
16
+ emb = torch.cat([torch.cos(args), torch.sin(args)], dim=-1)
17
+ if dim % 2:
18
+ emb = torch.cat([emb, torch.zeros_like(emb[:, :1])], dim=-1)
19
+ return emb
20
+
21
+ def rope_freqs(positions, dim, base=10000.0):
22
+ inv_freq = 1.0 / (base ** (torch.arange(0, dim, 2).float() / dim))
23
+ return torch.outer(positions.float(), inv_freq)
24
+
25
+ def rope_cos_sin(freqs):
26
+ emb = torch.cat([freqs, freqs], dim=-1)
27
+ return emb.cos(), emb.sin()
28
+
29
+ def rotate_half(x):
30
+ x1, x2 = x.chunk(2, dim=-1)
31
+ return torch.cat([-x2, x1], dim=-1)
32
+
33
+ def apply_rope(x, cos, sin):
34
+ return x * cos + rotate_half(x) * sin
35
+
36
+ def apply_rope_2d(x, row_cos, row_sin, col_cos, col_sin):
37
+ x1, x2 = x.chunk(2, dim=-1)
38
+ x1 = apply_rope(x1, row_cos, row_sin)
39
+ x2 = apply_rope(x2, col_cos, col_sin)
40
+ return torch.cat([x1, x2], dim=-1)
41
+
42
+ class RMSNormHead(nn.Module):
43
+ def __init__(self, head_dim, eps=1e-6):
44
+ super().__init__()
45
+ self.weight = nn.Parameter(torch.ones(head_dim))
46
+ self.eps = eps
47
+
48
+ def forward(self, x):
49
+ n = x.pow(2).mean(-1, keepdim=True).add(self.eps).rsqrt()
50
+ return x * n * self.weight
51
+
52
+ class SwiGLU(nn.Module):
53
+ def __init__(self, dim, hidden):
54
+ super().__init__()
55
+ self.gate = nn.Linear(dim, hidden)
56
+ self.up = nn.Linear(dim, hidden)
57
+ self.down = nn.Linear(hidden, dim)
58
+
59
+ def forward(self, x):
60
+ return self.down(F.silu(self.gate(x)) * self.up(x))
61
+
62
+ class JointBlock(nn.Module):
63
+ def __init__(self, dim, heads, mlp_hidden):
64
+ super().__init__()
65
+ self.heads = heads
66
+ self.head_dim = dim // heads
67
+ self.norm1_img = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)
68
+ self.norm1_txt = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)
69
+ self.qkv_img = nn.Linear(dim, 3 * dim)
70
+ self.qkv_txt = nn.Linear(dim, 3 * dim)
71
+ self.qn_img = RMSNormHead(self.head_dim)
72
+ self.kn_img = RMSNormHead(self.head_dim)
73
+ self.qn_txt = RMSNormHead(self.head_dim)
74
+ self.kn_txt = RMSNormHead(self.head_dim)
75
+ self.proj_img = nn.Linear(dim, dim)
76
+ self.proj_txt = nn.Linear(dim, dim)
77
+ self.norm2_img = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)
78
+ self.norm2_txt = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)
79
+ self.mlp_img = SwiGLU(dim, mlp_hidden)
80
+ self.mlp_txt = SwiGLU(dim, mlp_hidden)
81
+ self.ada_img = nn.Sequential(nn.SiLU(), nn.Linear(dim, 6 * dim))
82
+ self.ada_txt = nn.Sequential(nn.SiLU(), nn.Linear(dim, 6 * dim))
83
+
84
+ def forward(self, img, txt, c, rope_img, rope_txt, key_valid):
85
+ s1i, sc1i, g1i, s2i, sc2i, g2i = self.ada_img(c).chunk(6, dim=-1)
86
+ s1t, sc1t, g1t, s2t, sc2t, g2t = self.ada_txt(c).chunk(6, dim=-1)
87
+
88
+ xi = modulate(self.norm1_img(img), s1i, sc1i)
89
+ xt = modulate(self.norm1_txt(txt), s1t, sc1t)
90
+
91
+ B, Ni, C = xi.shape
92
+ Nt = xt.shape[1]
93
+ H, D = self.heads, self.head_dim
94
+
95
+ qi, ki, vi = self.qkv_img(xi).reshape(B, Ni, 3, H, D).permute(2, 0, 3, 1, 4)
96
+ qt, kt, vt = self.qkv_txt(xt).reshape(B, Nt, 3, H, D).permute(2, 0, 3, 1, 4)
97
+
98
+ qi, ki = self.qn_img(qi), self.kn_img(ki)
99
+ qt, kt = self.qn_txt(qt), self.kn_txt(kt)
100
+
101
+ row_cos, row_sin, col_cos, col_sin = rope_img
102
+ qi = apply_rope_2d(qi, row_cos, row_sin, col_cos, col_sin)
103
+ ki = apply_rope_2d(ki, row_cos, row_sin, col_cos, col_sin)
104
+
105
+ t_cos, t_sin = rope_txt
106
+ qt = apply_rope(qt, t_cos, t_sin)
107
+ kt = apply_rope(kt, t_cos, t_sin)
108
+
109
+ q = torch.cat([qi, qt], dim=2)
110
+ k = torch.cat([ki, kt], dim=2)
111
+ v = torch.cat([vi, vt], dim=2)
112
+
113
+ mask = key_valid[:, None, None, :]
114
+ o = F.scaled_dot_product_attention(q, k, v, attn_mask=mask)
115
+ o = o.transpose(1, 2).reshape(B, Ni + Nt, C)
116
+ oi, ot = o[:, :Ni], o[:, Ni:]
117
+
118
+ img = img + g1i.unsqueeze(1) * self.proj_img(oi)
119
+ txt = txt + g1t.unsqueeze(1) * self.proj_txt(ot)
120
+
121
+ img = img + g2i.unsqueeze(1) * self.mlp_img(modulate(self.norm2_img(img), s2i, sc2i))
122
+ txt = txt + g2t.unsqueeze(1) * self.mlp_txt(modulate(self.norm2_txt(txt), s2t, sc2t))
123
+ return img, txt
124
+
125
+ class MMDiT(nn.Module):
126
+ def __init__(self, latent_ch=4, latent_size=32, patch=2, dim=512, depth=16, heads=8,
127
+ t5_dim=768, clip_dim=512, t5_len=32, mlp_hidden=1408,
128
+ repa_dim=384, repa_layer=8):
129
+ super().__init__()
130
+ self.latent_ch = latent_ch
131
+ self.latent_size = latent_size
132
+ self.patch = patch
133
+ self.grid = latent_size // patch
134
+ self.patch_dim = latent_ch * patch * patch
135
+ self.dim = dim
136
+ self.depth = depth
137
+ self.heads = heads
138
+ self.head_dim = dim // heads
139
+ self.t5_len = t5_len
140
+ self.repa_layer = repa_layer
141
+
142
+ self.x_embed = nn.Linear(self.patch_dim, dim)
143
+ self.t_mlp = nn.Sequential(nn.Linear(dim, dim), nn.SiLU(), nn.Linear(dim, dim))
144
+ self.clip_proj = nn.Linear(clip_dim, dim)
145
+ self.t5_proj = nn.Linear(t5_dim, dim)
146
+
147
+ self.blocks = nn.ModuleList([JointBlock(dim, heads, mlp_hidden) for _ in range(depth)])
148
+
149
+ self.norm_out = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)
150
+ self.ada_out = nn.Sequential(nn.SiLU(), nn.Linear(dim, 2 * dim))
151
+ self.head = nn.Linear(dim, self.patch_dim)
152
+
153
+ self.repa_head = nn.Sequential(nn.Linear(dim, dim), nn.GELU(approximate="tanh"), nn.Linear(dim, repa_dim))
154
+
155
+ hd2 = self.head_dim // 2
156
+ rows = torch.arange(self.grid).repeat_interleave(self.grid)
157
+ cols = torch.arange(self.grid).repeat(self.grid)
158
+ row_cos, row_sin = rope_cos_sin(rope_freqs(rows, hd2))
159
+ col_cos, col_sin = rope_cos_sin(rope_freqs(cols, hd2))
160
+ self.register_buffer("row_cos", row_cos, persistent=False)
161
+ self.register_buffer("row_sin", row_sin, persistent=False)
162
+ self.register_buffer("col_cos", col_cos, persistent=False)
163
+ self.register_buffer("col_sin", col_sin, persistent=False)
164
+ t_cos, t_sin = rope_cos_sin(rope_freqs(torch.arange(t5_len), self.head_dim))
165
+ self.register_buffer("t_cos", t_cos, persistent=False)
166
+ self.register_buffer("t_sin", t_sin, persistent=False)
167
+
168
+ self._init()
169
+
170
+ def _init(self):
171
+ for m in self.modules():
172
+ if isinstance(m, nn.Linear):
173
+ nn.init.xavier_uniform_(m.weight)
174
+ if m.bias is not None:
175
+ nn.init.zeros_(m.bias)
176
+ for b in self.blocks:
177
+ nn.init.zeros_(b.ada_img[-1].weight); nn.init.zeros_(b.ada_img[-1].bias)
178
+ nn.init.zeros_(b.ada_txt[-1].weight); nn.init.zeros_(b.ada_txt[-1].bias)
179
+ nn.init.zeros_(self.ada_out[-1].weight); nn.init.zeros_(self.ada_out[-1].bias)
180
+ nn.init.zeros_(self.head.weight); nn.init.zeros_(self.head.bias)
181
+
182
+ def patchify(self, x):
183
+ B, C, H, W = x.shape
184
+ p = self.patch
185
+ x = x.reshape(B, C, H // p, p, W // p, p)
186
+ x = x.permute(0, 2, 4, 1, 3, 5).reshape(B, (H // p) * (W // p), C * p * p)
187
+ return x
188
+
189
+ def unpatchify(self, x):
190
+ B, N, _ = x.shape
191
+ p = self.patch
192
+ g = self.grid
193
+ C = self.latent_ch
194
+ x = x.reshape(B, g, g, C, p, p).permute(0, 3, 1, 4, 2, 5)
195
+ return x.reshape(B, C, g * p, g * p)
196
+
197
+ def forward(self, x, t, t5_seq, t5_mask, clip_pool, return_repa=False, use_checkpoint=False):
198
+ B = x.shape[0]
199
+ img = self.x_embed(self.patchify(x))
200
+ txt = self.t5_proj(t5_seq)
201
+ c = self.t_mlp(timestep_embedding(t, self.dim)) + self.clip_proj(clip_pool)
202
+
203
+ key_valid = torch.cat([
204
+ torch.ones(B, img.shape[1], dtype=torch.bool, device=x.device),
205
+ t5_mask.bool(),
206
+ ], dim=1)
207
+
208
+ rope_img = (self.row_cos, self.row_sin, self.col_cos, self.col_sin)
209
+ rope_txt = (self.t_cos, self.t_sin)
210
+
211
+ repa_hidden = None
212
+ for i, blk in enumerate(self.blocks):
213
+ if use_checkpoint and self.training:
214
+ img, txt = torch.utils.checkpoint.checkpoint(
215
+ blk, img, txt, c, rope_img, rope_txt, key_valid, use_reentrant=False)
216
+ else:
217
+ img, txt = blk(img, txt, c, rope_img, rope_txt, key_valid)
218
+ if return_repa and i == self.repa_layer:
219
+ repa_hidden = img
220
+
221
+ shift, scale = self.ada_out(c).chunk(2, dim=-1)
222
+ img = modulate(self.norm_out(img), shift, scale)
223
+ out = self.unpatchify(self.head(img))
224
+
225
+ if return_repa:
226
+ return out, self.repa_head(repa_hidden)
227
+ return out
228
+
229
+ def num_params(self):
230
+ return sum(p.numel() for p in self.parameters())
231
+
232
+ def num_backbone_params(self):
233
+ return sum(p.numel() for n, p in self.named_parameters() if not n.startswith("repa_head"))
eval_v6.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import json
5
+ import os
6
+
7
+ import numpy as np
8
+ import torch
9
+ from PIL import Image
10
+ from diffusers import AutoencoderKL
11
+ from transformers import CLIPModel, CLIPTextModel, CLIPTokenizer, T5EncoderModel, T5TokenizerFast
12
+
13
+ from dit_v6 import MMDiT
14
+
15
+ def patch_clip_score():
16
+ def get_image_features(self, pixel_values, **kw):
17
+ pooled = self.vision_model(pixel_values=pixel_values).pooler_output
18
+ return self.visual_projection(pooled)
19
+
20
+ def get_text_features(self, input_ids=None, attention_mask=None, **kw):
21
+ pooled = self.text_model(input_ids=input_ids, attention_mask=attention_mask).pooler_output
22
+ return self.text_projection(pooled)
23
+
24
+ CLIPModel.get_image_features = get_image_features
25
+ CLIPModel.get_text_features = get_text_features
26
+
27
+ @torch.no_grad()
28
+ def sample(model, seq, mask, pool, null_seq, null_mask, null_pool, steps, cfg, dev):
29
+ B = seq.shape[0]
30
+ x = torch.randn(B, 4, 32, 32, device=dev)
31
+ ns, nm, npo = null_seq.expand(B, -1, -1), null_mask.expand(B, -1), null_pool.expand(B, -1)
32
+ dt = 1.0 / steps
33
+ for i in range(steps):
34
+ t = torch.full((B,), i * dt, device=dev)
35
+ with torch.autocast("cuda", dtype=torch.bfloat16):
36
+ vc = model(x, t, seq, mask, pool)
37
+ vu = model(x, t, ns, nm, npo)
38
+ x = x + (vu + cfg * (vc - vu)).float() * dt
39
+ return x
40
+
41
+ @torch.no_grad()
42
+ def main():
43
+ ap = argparse.ArgumentParser()
44
+ ap.add_argument("--work", default="/root/v6cache")
45
+ ap.add_argument("--ckpt", default="/root/runs/pm6/best.pt")
46
+ ap.add_argument("--vae", default="madebyollin/sdxl-vae-fp16-fix")
47
+ ap.add_argument("--clip", default="openai/clip-vit-base-patch32")
48
+ ap.add_argument("--t5", default="google/flan-t5-base")
49
+ ap.add_argument("--n", type=int, default=5000)
50
+ ap.add_argument("--batch", type=int, default=50)
51
+ ap.add_argument("--steps", type=int, default=50)
52
+ ap.add_argument("--cfg", type=float, nargs="+", default=[5.0])
53
+ ap.add_argument("--t5-len", type=int, default=32)
54
+ ap.add_argument("--clip-len", type=int, default=40)
55
+ ap.add_argument("--out", default="/root/runs/pm6/eval_results.jsonl")
56
+ ap.add_argument("--preview", default="")
57
+ args = ap.parse_args()
58
+ dev = "cuda"
59
+
60
+ ck = torch.load(args.ckpt, map_location=dev)
61
+ c = ck["cfg"]
62
+ model = MMDiT(dim=c["dim"], depth=c["depth"], heads=c["heads"], mlp_hidden=c["mlp_hidden"],
63
+ t5_len=c["t5_len"]).to(dev).eval()
64
+ model.load_state_dict(ck["ema"])
65
+ print(f"[eval] loaded {args.ckpt} step {ck['step']} params {model.num_params():,}", flush=True)
66
+
67
+ vae = AutoencoderKL.from_pretrained(args.vae).to(dev).half().eval()
68
+ vae_scale = vae.config.scaling_factor
69
+ t5_tok = T5TokenizerFast.from_pretrained(args.t5)
70
+ t5 = T5EncoderModel.from_pretrained(args.t5).to(dev).eval()
71
+ clip_tok = CLIPTokenizer.from_pretrained(args.clip)
72
+ clip_txt = CLIPTextModel.from_pretrained(args.clip).to(dev).eval()
73
+
74
+ def enc(strings):
75
+ te = t5_tok(strings, padding="max_length", max_length=args.t5_len, truncation=True, return_tensors="pt").to(dev)
76
+ seq = t5(input_ids=te["input_ids"], attention_mask=te["attention_mask"]).last_hidden_state.float()
77
+ ce = clip_tok(strings, padding="max_length", max_length=args.clip_len, truncation=True,
78
+ return_tensors="pt").to(dev)
79
+ pool = clip_txt(input_ids=ce["input_ids"]).pooler_output.float()
80
+ return seq, te["attention_mask"].float(), pool
81
+
82
+ null_seq, null_mask, null_pool = enc([""])
83
+
84
+ d = np.load(os.path.join(args.work, "eval_256.npz"), allow_pickle=True)
85
+ real = d["images"][:args.n]
86
+ caps = [str(x) for x in d["captions"][:args.n]]
87
+ n = len(caps)
88
+
89
+ patch_clip_score()
90
+ from torchmetrics.image.fid import FrechetInceptionDistance
91
+ from torchmetrics.multimodal.clip_score import CLIPScore
92
+
93
+ results = []
94
+ for cfg_val in args.cfg:
95
+ fid = FrechetInceptionDistance(feature=2048, normalize=True).to(dev)
96
+ clip_metric = CLIPScore(model_name_or_path=args.clip).to(dev)
97
+ for i in range(0, n, args.batch):
98
+ rb = torch.from_numpy(real[i:i + args.batch].astype(np.float32) / 255.0).permute(0, 3, 1, 2).to(dev)
99
+ fid.update(rb, real=True)
100
+
101
+ preview_imgs = []
102
+ for i in range(0, n, args.batch):
103
+ cb = caps[i:i + args.batch]
104
+ seq, mask, pool = enc(cb)
105
+ z = sample(model, seq, mask, pool, null_seq, null_mask, null_pool, args.steps, cfg_val, dev)
106
+ img = vae.decode((z / vae_scale).half()).sample.float()
107
+ img = (img.clamp(-1, 1) + 1) / 2
108
+ fid.update(img, real=False)
109
+ clip_metric.update((img * 255).to(torch.uint8), cb)
110
+ if args.preview and cfg_val == args.cfg[0] and len(preview_imgs) < 12:
111
+ for j in range(min(len(cb), 12 - len(preview_imgs))):
112
+ a = (img[j].permute(1, 2, 0).cpu().numpy() * 255).astype(np.uint8)
113
+ preview_imgs.append((a, cb[j]))
114
+ if i % (args.batch * 10) == 0:
115
+ print(f"[eval] cfg={cfg_val} generated {i}/{n}", flush=True)
116
+
117
+ fid_v = float(fid.compute().item())
118
+ clip_v = float(clip_metric.compute().item())
119
+ res = {"n": n, "fid": round(fid_v, 2), "clip_score": round(clip_v, 2), "steps": args.steps,
120
+ "cfg": cfg_val, "render_res": 256, "fid_size": 256, "clip_model": args.clip, "step": ck["step"]}
121
+ results.append(res)
122
+ print(f"[eval] cfg={cfg_val} FID={fid_v:.2f} CLIP={clip_v:.2f} (n={n}, steps={args.steps})", flush=True)
123
+
124
+ with open(args.out, "a") as f:
125
+ f.write(json.dumps(res) + "\n")
126
+
127
+ if args.preview and cfg_val == args.cfg[0] and preview_imgs:
128
+ cell, pad = 256, 8
129
+ cols = 4
130
+ rows = (len(preview_imgs) + cols - 1) // cols
131
+ sheet = Image.new("RGB", (cols * cell + (cols + 1) * pad, rows * cell + (rows + 1) * pad), (245, 246, 248))
132
+ for k, (a, cap) in enumerate(preview_imgs):
133
+ r, cc = divmod(k, cols)
134
+ sheet.paste(Image.fromarray(a), (pad + cc * (cell + pad), pad + r * (cell + pad)))
135
+ sheet.save(args.preview)
136
+ print(f"[eval] wrote preview {args.preview}", flush=True)
137
+
138
+ print(json.dumps(results, indent=2))
139
+
140
+ if __name__ == "__main__":
141
+ main()
examples.png ADDED

Git LFS Details

  • SHA256: b77c024d728cddb4292b6340e5fdb7e6e756a549662cc46ac6733e6632b1faab
  • Pointer size: 131 Bytes
  • Size of remote file: 139 kB
main.py ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import json
5
+ import os
6
+
7
+ import numpy as np
8
+ import torch
9
+ from PIL import Image
10
+ from safetensors.torch import load_file
11
+ from diffusers import AutoencoderKL
12
+ from transformers import CLIPTextModel, CLIPTokenizer, T5EncoderModel, T5TokenizerFast
13
+
14
+ from dit_v6 import MMDiT
15
+
16
+ @torch.no_grad()
17
+ def sample(model, seq, mask, pool, null_seq, null_mask, null_pool, steps, cfg, dev):
18
+ B = seq.shape[0]
19
+ x = torch.randn(B, 4, 32, 32, device=dev)
20
+ ns, nm, npo = null_seq.expand(B, -1, -1), null_mask.expand(B, -1), null_pool.expand(B, -1)
21
+ dt = 1.0 / steps
22
+ for i in range(steps):
23
+ t = torch.full((B,), i * dt, device=dev)
24
+ with torch.autocast("cuda", dtype=torch.bfloat16):
25
+ vc = model(x, t, seq, mask, pool)
26
+ vu = model(x, t, ns, nm, npo)
27
+ x = x + (vu + cfg * (vc - vu)).float() * dt
28
+ return x
29
+
30
+ @torch.no_grad()
31
+ def main():
32
+ ap = argparse.ArgumentParser()
33
+ ap.add_argument("prompt")
34
+ ap.add_argument("--out", default="out.png")
35
+ ap.add_argument("--cfg", type=float, default=5.0)
36
+ ap.add_argument("--steps", type=int, default=50)
37
+ ap.add_argument("--device", default="cuda" if torch.cuda.is_available() else "cpu")
38
+ ap.add_argument("--safetensors", default="model.safetensors")
39
+ ap.add_argument("--config", default="config.json")
40
+ ap.add_argument("--vae", default="madebyollin/sdxl-vae-fp16-fix")
41
+ ap.add_argument("--clip", default="openai/clip-vit-base-patch32")
42
+ ap.add_argument("--t5", default="google/flan-t5-base")
43
+ ap.add_argument("--t5-len", type=int, default=32)
44
+ ap.add_argument("--clip-len", type=int, default=40)
45
+ args = ap.parse_args()
46
+ dev = args.device
47
+
48
+ d = json.load(open(args.config))["dit"] if os.path.exists(args.config) else \
49
+ {"dim": 512, "depth": 16, "heads": 8, "mlp_hidden": 1408, "t5_len": 32}
50
+ model = MMDiT(dim=d["dim"], depth=d["depth"], heads=d["heads"], mlp_hidden=d["mlp_hidden"],
51
+ t5_len=d["t5_len"]).to(dev).eval()
52
+ model.load_state_dict(load_file(args.safetensors))
53
+
54
+ vae = AutoencoderKL.from_pretrained(args.vae).to(dev).half().eval()
55
+ vae_scale = vae.config.scaling_factor
56
+ t5_tok = T5TokenizerFast.from_pretrained(args.t5)
57
+ t5 = T5EncoderModel.from_pretrained(args.t5).to(dev).eval()
58
+ clip_tok = CLIPTokenizer.from_pretrained(args.clip)
59
+ clip_txt = CLIPTextModel.from_pretrained(args.clip).to(dev).eval()
60
+
61
+ def enc(strings):
62
+ te = t5_tok(strings, padding="max_length", max_length=args.t5_len, truncation=True,
63
+ return_tensors="pt").to(dev)
64
+ seq = t5(input_ids=te["input_ids"], attention_mask=te["attention_mask"]).last_hidden_state.float()
65
+ ce = clip_tok(strings, padding="max_length", max_length=args.clip_len, truncation=True,
66
+ return_tensors="pt").to(dev)
67
+ pool = clip_txt(input_ids=ce["input_ids"]).pooler_output.float()
68
+ return seq, te["attention_mask"].float(), pool
69
+
70
+ seq, mask, pool = enc([args.prompt])
71
+ null_seq, null_mask, null_pool = enc([""])
72
+ z = sample(model, seq, mask, pool, null_seq, null_mask, null_pool, args.steps, args.cfg, dev)
73
+ img = vae.decode((z / vae_scale).half()).sample.float()
74
+ img = ((img.clamp(-1, 1) + 1) / 2)[0].permute(1, 2, 0).cpu().numpy()
75
+ Image.fromarray((img * 255).round().astype(np.uint8)).save(args.out)
76
+ print(f'[main] "{args.prompt}" -> {args.out} (cfg {args.cfg}, {args.steps} steps)')
77
+
78
+ if __name__ == "__main__":
79
+ main()
model.png ADDED

Git LFS Details

  • SHA256: 9c6fc996dd7cbed00f34fa262651a4d9b566e51a2417501a28193efeca888da9
  • Pointer size: 134 Bytes
  • Size of remote file: 344 MB
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b23bb35fdb7da8a17ddd9346f5b7434be874abf7f4ff40bac38d2e5c81774444
3
+ size 620406232
model_png.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"cfg": {"dim": 512, "depth": 16, "heads": 8, "mlp_hidden": 1408, "t5_len": 32}, "params": [{"name": "x_embed.weight", "shape": [512, 16], "numel": 8192}, {"name": "x_embed.bias", "shape": [512], "numel": 512}, {"name": "t_mlp.0.weight", "shape": [512, 512], "numel": 262144}, {"name": "t_mlp.0.bias", "shape": [512], "numel": 512}, {"name": "t_mlp.2.weight", "shape": [512, 512], "numel": 262144}, {"name": "t_mlp.2.bias", "shape": [512], "numel": 512}, {"name": "clip_proj.weight", "shape": [512, 512], "numel": 262144}, {"name": "clip_proj.bias", "shape": [512], "numel": 512}, {"name": "t5_proj.weight", "shape": [512, 768], "numel": 393216}, {"name": "t5_proj.bias", "shape": [512], "numel": 512}, {"name": "blocks.0.qkv_img.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.0.qkv_img.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.0.qkv_txt.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.0.qkv_txt.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.0.qn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.0.kn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.0.qn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.0.kn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.0.proj_img.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.0.proj_img.bias", "shape": [512], "numel": 512}, {"name": "blocks.0.proj_txt.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.0.proj_txt.bias", "shape": [512], "numel": 512}, {"name": "blocks.0.mlp_img.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.0.mlp_img.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.0.mlp_img.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.0.mlp_img.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.0.mlp_img.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.0.mlp_img.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.0.mlp_txt.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.0.mlp_txt.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.0.mlp_txt.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.0.mlp_txt.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.0.mlp_txt.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.0.mlp_txt.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.0.ada_img.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.0.ada_img.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.0.ada_txt.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.0.ada_txt.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.1.qkv_img.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.1.qkv_img.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.1.qkv_txt.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.1.qkv_txt.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.1.qn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.1.kn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.1.qn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.1.kn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.1.proj_img.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.1.proj_img.bias", "shape": [512], "numel": 512}, {"name": "blocks.1.proj_txt.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.1.proj_txt.bias", "shape": [512], "numel": 512}, {"name": "blocks.1.mlp_img.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.1.mlp_img.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.1.mlp_img.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.1.mlp_img.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.1.mlp_img.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.1.mlp_img.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.1.mlp_txt.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.1.mlp_txt.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.1.mlp_txt.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.1.mlp_txt.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.1.mlp_txt.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.1.mlp_txt.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.1.ada_img.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.1.ada_img.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.1.ada_txt.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.1.ada_txt.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.2.qkv_img.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.2.qkv_img.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.2.qkv_txt.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.2.qkv_txt.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.2.qn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.2.kn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.2.qn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.2.kn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.2.proj_img.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.2.proj_img.bias", "shape": [512], "numel": 512}, {"name": "blocks.2.proj_txt.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.2.proj_txt.bias", "shape": [512], "numel": 512}, {"name": "blocks.2.mlp_img.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.2.mlp_img.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.2.mlp_img.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.2.mlp_img.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.2.mlp_img.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.2.mlp_img.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.2.mlp_txt.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.2.mlp_txt.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.2.mlp_txt.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.2.mlp_txt.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.2.mlp_txt.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.2.mlp_txt.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.2.ada_img.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.2.ada_img.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.2.ada_txt.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.2.ada_txt.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.3.qkv_img.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.3.qkv_img.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.3.qkv_txt.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.3.qkv_txt.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.3.qn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.3.kn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.3.qn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.3.kn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.3.proj_img.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.3.proj_img.bias", "shape": [512], "numel": 512}, {"name": "blocks.3.proj_txt.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.3.proj_txt.bias", "shape": [512], "numel": 512}, {"name": "blocks.3.mlp_img.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.3.mlp_img.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.3.mlp_img.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.3.mlp_img.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.3.mlp_img.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.3.mlp_img.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.3.mlp_txt.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.3.mlp_txt.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.3.mlp_txt.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.3.mlp_txt.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.3.mlp_txt.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.3.mlp_txt.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.3.ada_img.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.3.ada_img.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.3.ada_txt.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.3.ada_txt.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.4.qkv_img.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.4.qkv_img.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.4.qkv_txt.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.4.qkv_txt.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.4.qn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.4.kn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.4.qn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.4.kn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.4.proj_img.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.4.proj_img.bias", "shape": [512], "numel": 512}, {"name": "blocks.4.proj_txt.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.4.proj_txt.bias", "shape": [512], "numel": 512}, {"name": "blocks.4.mlp_img.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.4.mlp_img.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.4.mlp_img.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.4.mlp_img.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.4.mlp_img.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.4.mlp_img.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.4.mlp_txt.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.4.mlp_txt.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.4.mlp_txt.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.4.mlp_txt.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.4.mlp_txt.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.4.mlp_txt.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.4.ada_img.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.4.ada_img.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.4.ada_txt.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.4.ada_txt.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.5.qkv_img.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.5.qkv_img.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.5.qkv_txt.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.5.qkv_txt.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.5.qn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.5.kn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.5.qn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.5.kn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.5.proj_img.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.5.proj_img.bias", "shape": [512], "numel": 512}, {"name": "blocks.5.proj_txt.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.5.proj_txt.bias", "shape": [512], "numel": 512}, {"name": "blocks.5.mlp_img.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.5.mlp_img.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.5.mlp_img.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.5.mlp_img.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.5.mlp_img.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.5.mlp_img.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.5.mlp_txt.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.5.mlp_txt.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.5.mlp_txt.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.5.mlp_txt.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.5.mlp_txt.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.5.mlp_txt.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.5.ada_img.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.5.ada_img.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.5.ada_txt.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.5.ada_txt.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.6.qkv_img.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.6.qkv_img.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.6.qkv_txt.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.6.qkv_txt.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.6.qn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.6.kn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.6.qn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.6.kn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.6.proj_img.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.6.proj_img.bias", "shape": [512], "numel": 512}, {"name": "blocks.6.proj_txt.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.6.proj_txt.bias", "shape": [512], "numel": 512}, {"name": "blocks.6.mlp_img.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.6.mlp_img.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.6.mlp_img.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.6.mlp_img.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.6.mlp_img.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.6.mlp_img.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.6.mlp_txt.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.6.mlp_txt.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.6.mlp_txt.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.6.mlp_txt.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.6.mlp_txt.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.6.mlp_txt.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.6.ada_img.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.6.ada_img.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.6.ada_txt.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.6.ada_txt.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.7.qkv_img.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.7.qkv_img.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.7.qkv_txt.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.7.qkv_txt.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.7.qn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.7.kn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.7.qn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.7.kn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.7.proj_img.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.7.proj_img.bias", "shape": [512], "numel": 512}, {"name": "blocks.7.proj_txt.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.7.proj_txt.bias", "shape": [512], "numel": 512}, {"name": "blocks.7.mlp_img.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.7.mlp_img.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.7.mlp_img.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.7.mlp_img.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.7.mlp_img.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.7.mlp_img.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.7.mlp_txt.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.7.mlp_txt.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.7.mlp_txt.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.7.mlp_txt.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.7.mlp_txt.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.7.mlp_txt.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.7.ada_img.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.7.ada_img.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.7.ada_txt.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.7.ada_txt.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.8.qkv_img.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.8.qkv_img.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.8.qkv_txt.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.8.qkv_txt.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.8.qn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.8.kn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.8.qn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.8.kn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.8.proj_img.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.8.proj_img.bias", "shape": [512], "numel": 512}, {"name": "blocks.8.proj_txt.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.8.proj_txt.bias", "shape": [512], "numel": 512}, {"name": "blocks.8.mlp_img.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.8.mlp_img.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.8.mlp_img.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.8.mlp_img.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.8.mlp_img.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.8.mlp_img.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.8.mlp_txt.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.8.mlp_txt.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.8.mlp_txt.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.8.mlp_txt.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.8.mlp_txt.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.8.mlp_txt.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.8.ada_img.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.8.ada_img.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.8.ada_txt.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.8.ada_txt.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.9.qkv_img.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.9.qkv_img.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.9.qkv_txt.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.9.qkv_txt.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.9.qn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.9.kn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.9.qn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.9.kn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.9.proj_img.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.9.proj_img.bias", "shape": [512], "numel": 512}, {"name": "blocks.9.proj_txt.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.9.proj_txt.bias", "shape": [512], "numel": 512}, {"name": "blocks.9.mlp_img.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.9.mlp_img.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.9.mlp_img.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.9.mlp_img.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.9.mlp_img.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.9.mlp_img.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.9.mlp_txt.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.9.mlp_txt.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.9.mlp_txt.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.9.mlp_txt.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.9.mlp_txt.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.9.mlp_txt.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.9.ada_img.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.9.ada_img.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.9.ada_txt.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.9.ada_txt.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.10.qkv_img.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.10.qkv_img.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.10.qkv_txt.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.10.qkv_txt.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.10.qn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.10.kn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.10.qn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.10.kn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.10.proj_img.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.10.proj_img.bias", "shape": [512], "numel": 512}, {"name": "blocks.10.proj_txt.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.10.proj_txt.bias", "shape": [512], "numel": 512}, {"name": "blocks.10.mlp_img.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.10.mlp_img.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.10.mlp_img.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.10.mlp_img.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.10.mlp_img.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.10.mlp_img.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.10.mlp_txt.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.10.mlp_txt.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.10.mlp_txt.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.10.mlp_txt.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.10.mlp_txt.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.10.mlp_txt.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.10.ada_img.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.10.ada_img.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.10.ada_txt.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.10.ada_txt.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.11.qkv_img.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.11.qkv_img.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.11.qkv_txt.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.11.qkv_txt.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.11.qn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.11.kn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.11.qn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.11.kn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.11.proj_img.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.11.proj_img.bias", "shape": [512], "numel": 512}, {"name": "blocks.11.proj_txt.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.11.proj_txt.bias", "shape": [512], "numel": 512}, {"name": "blocks.11.mlp_img.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.11.mlp_img.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.11.mlp_img.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.11.mlp_img.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.11.mlp_img.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.11.mlp_img.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.11.mlp_txt.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.11.mlp_txt.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.11.mlp_txt.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.11.mlp_txt.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.11.mlp_txt.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.11.mlp_txt.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.11.ada_img.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.11.ada_img.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.11.ada_txt.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.11.ada_txt.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.12.qkv_img.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.12.qkv_img.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.12.qkv_txt.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.12.qkv_txt.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.12.qn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.12.kn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.12.qn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.12.kn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.12.proj_img.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.12.proj_img.bias", "shape": [512], "numel": 512}, {"name": "blocks.12.proj_txt.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.12.proj_txt.bias", "shape": [512], "numel": 512}, {"name": "blocks.12.mlp_img.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.12.mlp_img.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.12.mlp_img.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.12.mlp_img.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.12.mlp_img.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.12.mlp_img.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.12.mlp_txt.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.12.mlp_txt.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.12.mlp_txt.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.12.mlp_txt.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.12.mlp_txt.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.12.mlp_txt.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.12.ada_img.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.12.ada_img.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.12.ada_txt.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.12.ada_txt.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.13.qkv_img.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.13.qkv_img.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.13.qkv_txt.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.13.qkv_txt.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.13.qn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.13.kn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.13.qn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.13.kn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.13.proj_img.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.13.proj_img.bias", "shape": [512], "numel": 512}, {"name": "blocks.13.proj_txt.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.13.proj_txt.bias", "shape": [512], "numel": 512}, {"name": "blocks.13.mlp_img.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.13.mlp_img.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.13.mlp_img.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.13.mlp_img.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.13.mlp_img.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.13.mlp_img.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.13.mlp_txt.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.13.mlp_txt.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.13.mlp_txt.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.13.mlp_txt.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.13.mlp_txt.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.13.mlp_txt.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.13.ada_img.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.13.ada_img.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.13.ada_txt.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.13.ada_txt.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.14.qkv_img.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.14.qkv_img.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.14.qkv_txt.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.14.qkv_txt.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.14.qn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.14.kn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.14.qn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.14.kn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.14.proj_img.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.14.proj_img.bias", "shape": [512], "numel": 512}, {"name": "blocks.14.proj_txt.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.14.proj_txt.bias", "shape": [512], "numel": 512}, {"name": "blocks.14.mlp_img.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.14.mlp_img.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.14.mlp_img.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.14.mlp_img.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.14.mlp_img.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.14.mlp_img.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.14.mlp_txt.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.14.mlp_txt.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.14.mlp_txt.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.14.mlp_txt.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.14.mlp_txt.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.14.mlp_txt.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.14.ada_img.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.14.ada_img.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.14.ada_txt.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.14.ada_txt.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.15.qkv_img.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.15.qkv_img.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.15.qkv_txt.weight", "shape": [1536, 512], "numel": 786432}, {"name": "blocks.15.qkv_txt.bias", "shape": [1536], "numel": 1536}, {"name": "blocks.15.qn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.15.kn_img.weight", "shape": [64], "numel": 64}, {"name": "blocks.15.qn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.15.kn_txt.weight", "shape": [64], "numel": 64}, {"name": "blocks.15.proj_img.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.15.proj_img.bias", "shape": [512], "numel": 512}, {"name": "blocks.15.proj_txt.weight", "shape": [512, 512], "numel": 262144}, {"name": "blocks.15.proj_txt.bias", "shape": [512], "numel": 512}, {"name": "blocks.15.mlp_img.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.15.mlp_img.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.15.mlp_img.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.15.mlp_img.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.15.mlp_img.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.15.mlp_img.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.15.mlp_txt.gate.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.15.mlp_txt.gate.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.15.mlp_txt.up.weight", "shape": [1408, 512], "numel": 720896}, {"name": "blocks.15.mlp_txt.up.bias", "shape": [1408], "numel": 1408}, {"name": "blocks.15.mlp_txt.down.weight", "shape": [512, 1408], "numel": 720896}, {"name": "blocks.15.mlp_txt.down.bias", "shape": [512], "numel": 512}, {"name": "blocks.15.ada_img.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.15.ada_img.1.bias", "shape": [3072], "numel": 3072}, {"name": "blocks.15.ada_txt.1.weight", "shape": [3072, 512], "numel": 1572864}, {"name": "blocks.15.ada_txt.1.bias", "shape": [3072], "numel": 3072}, {"name": "ada_out.1.weight", "shape": [1024, 512], "numel": 524288}, {"name": "ada_out.1.bias", "shape": [1024], "numel": 1024}, {"name": "head.weight", "shape": [16, 512], "numel": 8192}, {"name": "head.bias", "shape": [16], "numel": 16}], "total_parameters": 155090448, "side": 12454, "dtype": "float16", "channels": "R=hi,G=lo,B=unused"}
pixelmodel-v6-loss.png ADDED
pixelmodel-v6-params.png ADDED
pixelmodel-v6-val.png ADDED
png_codec.py ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+ import argparse, json, math
3
+ import numpy as np
4
+ import torch
5
+ from PIL import Image
6
+ from dit_v6 import MMDiT
7
+
8
+ def encode(ckpt, png_path, cfg_path, which="ema"):
9
+ ck = torch.load(ckpt, map_location="cpu")
10
+ c = ck["cfg"]
11
+ model = MMDiT(dim=c["dim"], depth=c["depth"], heads=c["heads"], mlp_hidden=c["mlp_hidden"], t5_len=c["t5_len"])
12
+ model.load_state_dict(ck[which])
13
+ parts, manifest = [], []
14
+ for name, p in model.named_parameters():
15
+ a = p.detach().to(torch.float16).contiguous().view(-1).numpy()
16
+ parts.append(a)
17
+ manifest.append({"name": name, "shape": list(p.shape), "numel": int(a.size)})
18
+ flat = np.concatenate(parts)
19
+ N = flat.size
20
+ side = math.ceil(math.sqrt(N))
21
+ u16 = flat.view(np.uint16)
22
+ img = np.zeros((side * side, 3), dtype=np.uint8)
23
+ img[:N, 0] = (u16 >> 8).astype(np.uint8)
24
+ img[:N, 1] = (u16 & 0xFF).astype(np.uint8)
25
+ Image.fromarray(img.reshape(side, side, 3), "RGB").save(png_path)
26
+ total = sum(m["numel"] for m in manifest)
27
+ with open(cfg_path, "w") as f:
28
+ json.dump({"cfg": c, "params": manifest, "total_parameters": total,
29
+ "side": side, "dtype": "float16", "channels": "R=hi,G=lo,B=unused"}, f)
30
+ import os
31
+ mb = os.path.getsize(png_path) / 1e6
32
+ print(f"[png] encoded {total:,} params -> {side}x{side} PNG ({mb:.1f} MB)", flush=True)
33
+ return total, side
34
+
35
+ def load_model_png(png_path, cfg_path, device="cpu"):
36
+ meta = json.load(open(cfg_path))
37
+ c = meta["cfg"]
38
+ model = MMDiT(dim=c["dim"], depth=c["depth"], heads=c["heads"], mlp_hidden=c["mlp_hidden"], t5_len=c["t5_len"])
39
+ arr = np.asarray(Image.open(png_path).convert("RGB")).reshape(-1, 3)
40
+ total = meta["total_parameters"]
41
+ hi = arr[:total, 0].astype(np.uint16)
42
+ lo = arr[:total, 1].astype(np.uint16)
43
+ flat = ((hi << 8) | lo).astype(np.uint16).view(np.float16)
44
+ sd = dict(model.named_parameters())
45
+ off = 0
46
+ with torch.no_grad():
47
+ for m in meta["params"]:
48
+ n = m["numel"]
49
+ chunk = flat[off:off + n].astype(np.float16)
50
+ t = torch.from_numpy(chunk.copy()).view(*m["shape"]).to(torch.float32)
51
+ sd[m["name"]].copy_(t)
52
+ off += n
53
+ return model.to(device).eval()
54
+
55
+ def decode_and_verify(png_path, cfg_path, ckpt=None, which="ema"):
56
+ model = load_model_png(png_path, cfg_path)
57
+ print(f"[png] decoded -> MMDiT with {sum(p.numel() for p in model.parameters()):,} params", flush=True)
58
+ if ckpt:
59
+ ck = torch.load(ckpt, map_location="cpu")
60
+ c = ck["cfg"]
61
+ ref = MMDiT(dim=c["dim"], depth=c["depth"], heads=c["heads"], mlp_hidden=c["mlp_hidden"], t5_len=c["t5_len"])
62
+ ref.load_state_dict(ck[which])
63
+ maxdiff = 0.0
64
+ for (n1, p1), (n2, p2) in zip(model.named_parameters(), ref.named_parameters()):
65
+ maxdiff = max(maxdiff, (p1.float() - p2.half().float()).abs().max().item())
66
+ print(f"[png] max |decoded - original(fp16)| = {maxdiff:.2e} (0 == lossless)", flush=True)
67
+ return model
68
+
69
+ if __name__ == "__main__":
70
+ ap = argparse.ArgumentParser()
71
+ ap.add_argument("mode", choices=["encode", "decode"])
72
+ ap.add_argument("--ckpt", default="ckpt/final.pt")
73
+ ap.add_argument("--png", default="model.png")
74
+ ap.add_argument("--config", default="model_png.json")
75
+ ap.add_argument("--which", default="ema")
76
+ args = ap.parse_args()
77
+ if args.mode == "encode":
78
+ encode(args.ckpt, args.png, args.config, args.which)
79
+ else:
80
+ decode_and_verify(args.png, args.config, args.ckpt, args.which)
prep_v6.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import io
5
+ import os
6
+ import tarfile
7
+ import time
8
+ from concurrent.futures import ThreadPoolExecutor
9
+
10
+ import numpy as np
11
+ import torch
12
+ from PIL import Image
13
+ from diffusers import AutoencoderKL
14
+ from transformers import CLIPTokenizer, T5TokenizerFast
15
+ from huggingface_hub import hf_hub_download
16
+
17
+ REPO = "undefined443/cc12m-wds-coco-recaptioned"
18
+
19
+ def csr(img, size):
20
+ img = img.convert("RGB")
21
+ w, h = img.size
22
+ s = min(w, h)
23
+ l, t = (w - s) // 2, (h - s) // 2
24
+ return np.asarray(img.crop((l, t, l + s, t + s)).resize((size, size), Image.BICUBIC), dtype=np.uint8)
25
+
26
+ def load_shard_items(tar_path, size):
27
+ t = tarfile.open(tar_path)
28
+ raw = {}
29
+ for m in t.getmembers():
30
+ if not m.isfile():
31
+ continue
32
+ key, ext = m.name.rsplit(".", 1)
33
+ raw.setdefault(key, {})[ext] = t.extractfile(m).read()
34
+ t.close()
35
+
36
+ def proc(kv):
37
+ _, d = kv
38
+ if "jpg" not in d or "txt" not in d:
39
+ return None
40
+ try:
41
+ arr = csr(Image.open(io.BytesIO(d["jpg"])), size)
42
+ cap = d["txt"].decode("utf-8", "ignore").strip()
43
+ if not cap:
44
+ return None
45
+ return arr, cap
46
+ except Exception:
47
+ return None
48
+
49
+ results = []
50
+ with ThreadPoolExecutor(max_workers=32) as pool:
51
+ for r in pool.map(proc, raw.items()):
52
+ if r is not None:
53
+ results.append(r)
54
+ return results
55
+
56
+ @torch.no_grad()
57
+ def main():
58
+ ap = argparse.ArgumentParser()
59
+ ap.add_argument("--out", default="/root/v6cache/shards")
60
+ ap.add_argument("--tmp", default="/root/v6cache/tars")
61
+ ap.add_argument("--size", type=int, default=256)
62
+ ap.add_argument("--t5-len", type=int, default=32)
63
+ ap.add_argument("--clip-len", type=int, default=40)
64
+ ap.add_argument("--batch", type=int, default=128)
65
+ ap.add_argument("--vae", default="madebyollin/sdxl-vae-fp16-fix")
66
+ ap.add_argument("--clip", default="openai/clip-vit-base-patch32")
67
+ ap.add_argument("--t5", default="google/flan-t5-base")
68
+ ap.add_argument("--start", type=int, default=0)
69
+ ap.add_argument("--end", type=int, default=598)
70
+ ap.add_argument("--prefetch", type=int, default=2)
71
+ args = ap.parse_args()
72
+ os.makedirs(args.out, exist_ok=True)
73
+ os.makedirs(args.tmp, exist_ok=True)
74
+ dev = "cuda"
75
+
76
+ vae = AutoencoderKL.from_pretrained(args.vae).to(dev).half().eval()
77
+ scale = vae.config.scaling_factor
78
+ print(f"[prep] vae={args.vae} scaling_factor={scale}", flush=True)
79
+ clip_tok = CLIPTokenizer.from_pretrained(args.clip)
80
+ t5_tok = T5TokenizerFast.from_pretrained(args.t5)
81
+
82
+ shard_names = [f"cc12m-coco-{i:04d}.tar" for i in range(args.start, args.end)]
83
+
84
+ def fetch(name):
85
+ return hf_hub_download(REPO, name, repo_type="dataset", local_dir=args.tmp)
86
+
87
+ fpool = ThreadPoolExecutor(max_workers=args.prefetch)
88
+ futures = {}
89
+ def ensure_fetch(idx):
90
+ if idx < len(shard_names) and idx not in futures:
91
+ futures[idx] = fpool.submit(fetch, shard_names[idx])
92
+
93
+ for k in range(args.prefetch):
94
+ ensure_fetch(k)
95
+
96
+ t0 = time.time()
97
+ total = 0
98
+ for i, name in enumerate(shard_names):
99
+ out_path = f"{args.out}/shard_{args.start+i:04d}.npz"
100
+ if os.path.exists(out_path):
101
+ total += np.load(out_path)["latents"].shape[0]
102
+ futures.pop(i, None)
103
+ ensure_fetch(i + args.prefetch)
104
+ continue
105
+
106
+ tar_path = futures.pop(i).result()
107
+ ensure_fetch(i + args.prefetch)
108
+
109
+ items = load_shard_items(tar_path, args.size)
110
+ os.remove(tar_path)
111
+ if not items:
112
+ print(f"[prep] shard {args.start+i:04d} EMPTY, skipping", flush=True)
113
+ continue
114
+ imgs = [a for a, c in items]
115
+ caps = [c for a, c in items]
116
+
117
+ lat_chunks = []
118
+ for j in range(0, len(imgs), args.batch):
119
+ chunk = np.stack(imgs[j:j + args.batch]).astype(np.float32) / 127.5 - 1.0
120
+ x = torch.from_numpy(chunk).permute(0, 3, 1, 2).to(dev).half()
121
+ z = vae.encode(x).latent_dist.mean * scale
122
+ lat_chunks.append(z.cpu().numpy().astype(np.float16))
123
+ latents = np.concatenate(lat_chunks)
124
+
125
+ t5o = t5_tok(caps, padding="max_length", max_length=args.t5_len, truncation=True, return_tensors="np")
126
+ clip_ids = clip_tok(caps, padding="max_length", max_length=args.clip_len, truncation=True,
127
+ return_tensors="np")["input_ids"]
128
+
129
+ np.savez(out_path, latents=latents,
130
+ t5_ids=t5o["input_ids"].astype(np.int32),
131
+ t5_mask=t5o["attention_mask"].astype(np.int8),
132
+ clip_ids=clip_ids.astype(np.int64))
133
+ total += len(imgs)
134
+ el = time.time() - t0
135
+ print(f"[prep] shard {args.start+i:04d} +{len(imgs)} total={total} "
136
+ f"({total/el:.1f} img/s, {el/3600:.2f}h elapsed)", flush=True)
137
+
138
+ print(f"[prep] DONE total={total}", flush=True)
139
+
140
+ if __name__ == "__main__":
141
+ main()
preview.py ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import numpy as np
5
+ import torch
6
+ from PIL import Image
7
+ from diffusers import AutoencoderKL
8
+ from transformers import CLIPTextModel, CLIPTokenizer, T5EncoderModel, T5TokenizerFast
9
+
10
+ from dit_v6 import MMDiT
11
+
12
+ PROMPTS = [
13
+ "a bowl of ramen with a soft boiled egg",
14
+ "a red fox sitting in a snowy forest",
15
+ "a lighthouse on a cliff at sunset",
16
+ "a wooden cabin in the mountains",
17
+ "a cup of coffee on a wooden table",
18
+ "a golden retriever running on a beach",
19
+ "a city street at night with neon signs",
20
+ "a bowl of fresh strawberries",
21
+ "a sailboat on a calm lake",
22
+ ]
23
+
24
+ @torch.no_grad()
25
+ def sample(model, seq, mask, pool, null_seq, null_mask, null_pool, steps, cfg, dev):
26
+ B = seq.shape[0]
27
+ x = torch.randn(B, 4, 32, 32, device=dev)
28
+ ns, nm, npo = null_seq.expand(B, -1, -1), null_mask.expand(B, -1), null_pool.expand(B, -1)
29
+ dt = 1.0 / steps
30
+ for i in range(steps):
31
+ t = torch.full((B,), i * dt, device=dev)
32
+ with torch.autocast("cuda", dtype=torch.bfloat16):
33
+ vc = model(x, t, seq, mask, pool)
34
+ vu = model(x, t, ns, nm, npo)
35
+ x = x + (vu + cfg * (vc - vu)).float() * dt
36
+ return x
37
+
38
+ @torch.no_grad()
39
+ def main():
40
+ ap = argparse.ArgumentParser()
41
+ ap.add_argument("--ckpt", default="/root/runs/pm6/best.pt")
42
+ ap.add_argument("--vae", default="madebyollin/sdxl-vae-fp16-fix")
43
+ ap.add_argument("--clip", default="openai/clip-vit-base-patch32")
44
+ ap.add_argument("--t5", default="google/flan-t5-base")
45
+ ap.add_argument("--steps", type=int, default=50)
46
+ ap.add_argument("--cfg", type=float, default=5.0)
47
+ ap.add_argument("--t5-len", type=int, default=32)
48
+ ap.add_argument("--clip-len", type=int, default=40)
49
+ ap.add_argument("--out", default="/root/preview.png")
50
+ args = ap.parse_args()
51
+ dev = "cuda"
52
+
53
+ ck = torch.load(args.ckpt, map_location=dev)
54
+ c = ck["cfg"]
55
+ model = MMDiT(dim=c["dim"], depth=c["depth"], heads=c["heads"], mlp_hidden=c["mlp_hidden"],
56
+ t5_len=c["t5_len"]).to(dev).eval()
57
+ model.load_state_dict(ck["ema"])
58
+ print(f"[preview] loaded {args.ckpt} step {ck['step']}", flush=True)
59
+
60
+ vae = AutoencoderKL.from_pretrained(args.vae).to(dev).half().eval()
61
+ vae_scale = vae.config.scaling_factor
62
+ t5_tok = T5TokenizerFast.from_pretrained(args.t5)
63
+ t5 = T5EncoderModel.from_pretrained(args.t5).to(dev).eval()
64
+ clip_tok = CLIPTokenizer.from_pretrained(args.clip)
65
+ clip_txt = CLIPTextModel.from_pretrained(args.clip).to(dev).eval()
66
+
67
+ def enc(strings):
68
+ te = t5_tok(strings, padding="max_length", max_length=args.t5_len, truncation=True,
69
+ return_tensors="pt").to(dev)
70
+ seq = t5(input_ids=te["input_ids"], attention_mask=te["attention_mask"]).last_hidden_state.float()
71
+ ce = clip_tok(strings, padding="max_length", max_length=args.clip_len, truncation=True,
72
+ return_tensors="pt").to(dev)
73
+ pool = clip_txt(input_ids=ce["input_ids"]).pooler_output.float()
74
+ return seq, te["attention_mask"].float(), pool
75
+
76
+ null_seq, null_mask, null_pool = enc([""])
77
+
78
+ cell, pad, cols = 256, 8, 3
79
+ rows = (len(PROMPTS) + cols - 1) // cols
80
+ sheet = Image.new("RGB", (cols * cell + (cols + 1) * pad, rows * cell + (rows + 1) * pad), (245, 246, 248))
81
+
82
+ for i, prompt in enumerate(PROMPTS):
83
+ seq, mask, pool = enc([prompt])
84
+ z = sample(model, seq, mask, pool, null_seq, null_mask, null_pool, args.steps, args.cfg, dev)
85
+ img = vae.decode((z / vae_scale).half()).sample.float()
86
+ img = ((img.clamp(-1, 1) + 1) / 2)[0].permute(1, 2, 0).cpu().numpy()
87
+ a = (img * 255).round().astype(np.uint8)
88
+ r, cc = divmod(i, cols)
89
+ sheet.paste(Image.fromarray(a), (pad + cc * (cell + pad), pad + r * (cell + pad)))
90
+ print(f"[preview] {i+1}/{len(PROMPTS)}: {prompt}", flush=True)
91
+
92
+ sheet.save(args.out)
93
+ print(f"[preview] wrote {args.out}", flush=True)
94
+
95
+ if __name__ == "__main__":
96
+ main()
publish_v6.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from huggingface_hub import HfApi
3
+
4
+ tok = os.environ["HF_TOKEN"]
5
+ api = HfApi(token=tok)
6
+ url = api.upload_folder(
7
+ repo_id="bench-labs/PixelModel-v6",
8
+ repo_type="model",
9
+ folder_path="/root/pm6release",
10
+ ignore_patterns=["__pycache__/*", "*.pyc"],
11
+ commit_message="Publish PixelModel v6: MMDiT + REPA, 150k steps, FID 23.62 at cfg 3.0",
12
+ )
13
+ print("done:", url)
train_v6.py ADDED
@@ -0,0 +1,286 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import copy
5
+ import glob
6
+ import json
7
+ import math
8
+ import os
9
+ import time
10
+
11
+ import numpy as np
12
+ import torch
13
+ import torch.nn.functional as F
14
+ from diffusers import AutoencoderKL
15
+ from transformers import AutoModel, CLIPTextModel, CLIPTokenizer, T5EncoderModel, T5TokenizerFast
16
+
17
+ from dit_v6 import MMDiT
18
+
19
+ IMAGENET_MEAN = torch.tensor([0.485, 0.456, 0.406]).view(1, 3, 1, 1)
20
+ IMAGENET_STD = torch.tensor([0.229, 0.224, 0.225]).view(1, 3, 1, 1)
21
+
22
+ def build_cache(shards_dir, cache):
23
+ shards = sorted(glob.glob(f"{shards_dir}/shard_*.npz"))
24
+ if not shards:
25
+ raise SystemExit(f"no shards in {shards_dir}")
26
+ lat, t5i, t5m, ci = [], [], [], []
27
+ for i, s in enumerate(shards):
28
+ z = np.load(s)
29
+ lat.append(z["latents"]); t5i.append(z["t5_ids"]); t5m.append(z["t5_mask"]); ci.append(z["clip_ids"])
30
+ if (i + 1) % 50 == 0:
31
+ print(f" loaded {i+1}/{len(shards)} shards", flush=True)
32
+ lat = np.concatenate(lat); t5i = np.concatenate(t5i); t5m = np.concatenate(t5m); ci = np.concatenate(ci)
33
+ np.save(f"{cache}_lat.npy", lat)
34
+ np.save(f"{cache}_t5ids.npy", t5i)
35
+ np.save(f"{cache}_t5mask.npy", t5m)
36
+ np.save(f"{cache}_clipids.npy", ci)
37
+ return lat, t5i, t5m, ci
38
+
39
+ def repa_weight_at(step, total, warm_frac=0.40, zero_frac=0.70, peak=0.5):
40
+ p = step / total
41
+ if p < warm_frac:
42
+ return peak
43
+ if p < zero_frac:
44
+ return peak * (1 - (p - warm_frac) / (zero_frac - warm_frac))
45
+ return 0.0
46
+
47
+ def main():
48
+ ap = argparse.ArgumentParser()
49
+ ap.add_argument("--shards", default="/root/v6cache/shards")
50
+ ap.add_argument("--cache", default="/root/v6cache/cache")
51
+ ap.add_argument("--out", default="/root/runs/pm6")
52
+ ap.add_argument("--steps", type=int, default=150000)
53
+ ap.add_argument("--batch", type=int, default=192)
54
+ ap.add_argument("--lr", type=float, default=2e-4)
55
+ ap.add_argument("--warmup", type=int, default=1500)
56
+ ap.add_argument("--dim", type=int, default=512)
57
+ ap.add_argument("--depth", type=int, default=16)
58
+ ap.add_argument("--heads", type=int, default=8)
59
+ ap.add_argument("--mlp-hidden", type=int, default=1408)
60
+ ap.add_argument("--t5-len", type=int, default=32)
61
+ ap.add_argument("--repa-layer", type=int, default=8)
62
+ ap.add_argument("--repa-peak", type=float, default=0.5)
63
+ ap.add_argument("--repa-batch", type=int, default=48)
64
+ ap.add_argument("--cfg-dropout", type=float, default=0.1)
65
+ ap.add_argument("--ema", type=float, default=0.9999)
66
+ ap.add_argument("--val-size", type=int, default=4096)
67
+ ap.add_argument("--val-every", type=int, default=2000)
68
+ ap.add_argument("--log-every", type=int, default=200)
69
+ ap.add_argument("--save-every", type=int, default=5000)
70
+ ap.add_argument("--vae", default="madebyollin/sdxl-vae-fp16-fix")
71
+ ap.add_argument("--clip", default="openai/clip-vit-base-patch32")
72
+ ap.add_argument("--t5", default="google/flan-t5-base")
73
+ ap.add_argument("--dinov2", default="facebook/dinov2-small")
74
+ ap.add_argument("--resume", default="")
75
+ ap.add_argument("--seed", type=int, default=0)
76
+ ap.add_argument("--grad-ckpt", action="store_true")
77
+ args = ap.parse_args()
78
+
79
+ dev = "cuda"
80
+ os.makedirs(args.out, exist_ok=True)
81
+ torch.manual_seed(args.seed)
82
+ torch.backends.cuda.matmul.allow_tf32 = True
83
+ torch.backends.cudnn.allow_tf32 = True
84
+
85
+ if os.path.exists(f"{args.cache}_lat.npy"):
86
+ lat = np.load(f"{args.cache}_lat.npy", mmap_mode="r")
87
+ t5i = np.load(f"{args.cache}_t5ids.npy")
88
+ t5m = np.load(f"{args.cache}_t5mask.npy")
89
+ ci = np.load(f"{args.cache}_clipids.npy")
90
+ else:
91
+ lat, t5i, t5m, ci = build_cache(args.shards, args.cache)
92
+
93
+ N = len(lat)
94
+ perm = np.random.RandomState(args.seed).permutation(N)
95
+ val_i = np.sort(perm[:args.val_size])
96
+ tr_i = perm[args.val_size:]
97
+ print(f"[data] {N} pairs, {len(tr_i)} train, {len(val_i)} val", flush=True)
98
+
99
+ vae = AutoencoderKL.from_pretrained(args.vae).to(dev).half().eval()
100
+ vae_scale = vae.config.scaling_factor
101
+ for p in vae.parameters():
102
+ p.requires_grad_(False)
103
+
104
+ clip_txt = CLIPTextModel.from_pretrained(args.clip).to(dev).eval()
105
+ for p in clip_txt.parameters():
106
+ p.requires_grad_(False)
107
+
108
+ t5 = T5EncoderModel.from_pretrained(args.t5).to(dev).eval()
109
+ for p in t5.parameters():
110
+ p.requires_grad_(False)
111
+
112
+ dinov2 = AutoModel.from_pretrained(args.dinov2).to(dev).eval()
113
+ for p in dinov2.parameters():
114
+ p.requires_grad_(False)
115
+ imagenet_mean = IMAGENET_MEAN.to(dev)
116
+ imagenet_std = IMAGENET_STD.to(dev)
117
+
118
+ @torch.no_grad()
119
+ def encode_text(t5_ids, t5_mask, clip_ids):
120
+ t5_out = t5(input_ids=t5_ids, attention_mask=t5_mask).last_hidden_state.float()
121
+ clip_pool = clip_txt(input_ids=clip_ids).pooler_output.float()
122
+ return t5_out, clip_pool
123
+
124
+ @torch.no_grad()
125
+ def dino_features(x1_latent):
126
+ px = vae.decode((x1_latent / vae_scale).to(vae.dtype)).sample.float()
127
+ px = (px.clamp(-1, 1) + 1) / 2
128
+ px = F.interpolate(px, size=(224, 224), mode="bilinear", align_corners=False)
129
+ px = (px - imagenet_mean) / imagenet_std
130
+ out = dinov2(pixel_values=px.to(dinov2.dtype)).last_hidden_state
131
+ return out[:, 1:, :].float()
132
+
133
+ t5_tok = T5TokenizerFast.from_pretrained(args.t5)
134
+ clip_tok = CLIPTokenizer.from_pretrained(args.clip)
135
+ null_t5_enc = t5_tok([""], padding="max_length", max_length=args.t5_len, truncation=True, return_tensors="pt")
136
+ null_t5_ids = null_t5_enc["input_ids"].to(dev)
137
+ null_t5_mask = null_t5_enc["attention_mask"].to(dev)
138
+ null_clip_ids = clip_tok([""], padding="max_length", max_length=ci.shape[1], truncation=True,
139
+ return_tensors="pt")["input_ids"].to(dev)
140
+ null_t5_seq, null_clip_pool = encode_text(null_t5_ids, null_t5_mask, null_clip_ids)
141
+
142
+ t5i_t = torch.from_numpy(t5i.astype(np.int64))
143
+ t5m_t = torch.from_numpy(t5m.astype(np.int64))
144
+ ci_t = torch.from_numpy(ci.astype(np.int64))
145
+
146
+ vlat = torch.from_numpy(np.asarray(lat[val_i])).float()
147
+ vg = torch.Generator(device=dev).manual_seed(1234)
148
+ vx1 = vlat.to(dev)
149
+ vx0 = torch.randn(vx1.shape, device=dev, generator=vg)
150
+ vt = torch.sigmoid(torch.randn(vx1.shape[0], device=dev, generator=vg))
151
+ with torch.no_grad():
152
+ vseq, vmask, vpool = [], [], []
153
+ for i in range(0, len(val_i), 256):
154
+ s, p = encode_text(t5i_t[val_i[i:i+256]].to(dev), t5m_t[val_i[i:i+256]].to(dev), ci_t[val_i[i:i+256]].to(dev))
155
+ vseq.append(s); vmask.append(t5m_t[val_i[i:i+256]].to(dev)); vpool.append(p)
156
+ vseq = torch.cat(vseq); vmask = torch.cat(vmask); vpool = torch.cat(vpool)
157
+
158
+ model = MMDiT(dim=args.dim, depth=args.depth, heads=args.heads, mlp_hidden=args.mlp_hidden,
159
+ t5_len=args.t5_len).to(dev)
160
+ ema = copy.deepcopy(model).eval()
161
+ for p in ema.parameters():
162
+ p.requires_grad_(False)
163
+ opt = torch.optim.AdamW(model.parameters(), lr=args.lr, betas=(0.9, 0.99), weight_decay=0.0)
164
+ print(f"[model] {model.num_params()/1e6:.2f}M trainable, {model.num_backbone_params()/1e6:.2f}M backbone", flush=True)
165
+
166
+ start, best = 0, float("inf")
167
+ if args.resume and os.path.exists(args.resume):
168
+ ck = torch.load(args.resume, map_location=dev)
169
+ model.load_state_dict(ck["model"]); ema.load_state_dict(ck["ema"])
170
+ opt.load_state_dict(ck["opt"]); start = ck["step"] + 1; best = ck.get("best", best)
171
+ print(f"[resume] from step {start}", flush=True)
172
+
173
+ def lr_at(s):
174
+ if s < args.warmup:
175
+ return args.lr * (s + 1) / args.warmup
176
+ p = (s - args.warmup) / max(1, args.steps - args.warmup)
177
+ return args.lr * (0.1 + 0.9 * 0.5 * (1 + math.cos(math.pi * min(1.0, p))))
178
+
179
+ @torch.no_grad()
180
+ def val_loss():
181
+ tot, n = 0.0, 0
182
+ for j in range(0, vx1.shape[0], args.batch):
183
+ sl = slice(j, j + args.batch)
184
+ m = vx1[sl].shape[0]
185
+ tb = vt[sl].view(-1, 1, 1, 1)
186
+ xt = (1 - tb) * vx0[sl] + tb * vx1[sl]
187
+ with torch.autocast("cuda", dtype=torch.bfloat16):
188
+ v = ema(xt, vt[sl], vseq[sl], vmask[sl], vpool[sl])
189
+ tot += F.mse_loss(v.float(), vx1[sl] - vx0[sl]).item() * m
190
+ n += m
191
+ return tot / n
192
+
193
+ logf = open(f"{args.out}/log.jsonl", "a")
194
+ gen = torch.Generator(device=dev).manual_seed(args.seed)
195
+ run, run_diff, run_repa = 0.0, 0.0, 0.0
196
+ t0 = time.time()
197
+ for step in range(start, args.steps):
198
+ i = tr_i[np.random.randint(0, len(tr_i), args.batch)]
199
+ i_sorted = np.sort(i)
200
+ x1 = torch.from_numpy(np.asarray(lat[i_sorted])).to(dev).float()
201
+ t5_ids_b = t5i_t[i_sorted].to(dev)
202
+ t5_mask_b = t5m_t[i_sorted].to(dev)
203
+ clip_ids_b = ci_t[i_sorted].to(dev)
204
+ seq, pool = encode_text(t5_ids_b, t5_mask_b, clip_ids_b)
205
+ mask = t5_mask_b
206
+
207
+ drop = torch.rand(x1.shape[0], device=dev, generator=gen) < args.cfg_dropout
208
+ seq = torch.where(drop[:, None, None], null_t5_seq, seq)
209
+ mask = torch.where(drop[:, None], null_t5_mask, mask)
210
+ pool = torch.where(drop[:, None], null_clip_pool, pool)
211
+
212
+ x0 = torch.randn(x1.shape, device=dev, generator=gen)
213
+ t = torch.sigmoid(torch.randn(x1.shape[0], device=dev, generator=gen))
214
+ tb = t.view(-1, 1, 1, 1)
215
+ xt = (1 - tb) * x0 + tb * x1
216
+ target = x1 - x0
217
+
218
+ rw = repa_weight_at(step, args.steps, peak=args.repa_peak)
219
+
220
+ for g in opt.param_groups:
221
+ g["lr"] = lr_at(step)
222
+
223
+ with torch.autocast("cuda", dtype=torch.bfloat16):
224
+ if rw > 0:
225
+ v, repa_pred = model(xt, t, seq, mask, pool, return_repa=True, use_checkpoint=args.grad_ckpt)
226
+ else:
227
+ v = model(xt, t, seq, mask, pool, use_checkpoint=args.grad_ckpt)
228
+ loss_diff = F.mse_loss(v.float(), target)
229
+ if rw > 0:
230
+ rb = min(args.repa_batch, x1.shape[0])
231
+ with torch.no_grad():
232
+ dino_tgt = dino_features(x1[:rb])
233
+ loss_repa = 1.0 - F.cosine_similarity(repa_pred[:rb].float(), dino_tgt, dim=-1).mean()
234
+ loss = loss_diff + rw * loss_repa
235
+ else:
236
+ loss_repa = torch.zeros((), device=dev)
237
+ loss = loss_diff
238
+
239
+ opt.zero_grad(set_to_none=True)
240
+ loss.backward()
241
+ gn = torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)
242
+ opt.step()
243
+ d = args.ema if step > args.warmup else 0.0
244
+ with torch.no_grad():
245
+ for pe, pm in zip(ema.parameters(), model.parameters()):
246
+ pe.mul_(d).add_(pm.detach(), alpha=1 - d)
247
+ for be, bm in zip(ema.buffers(), model.buffers()):
248
+ be.copy_(bm)
249
+
250
+ run += loss.item(); run_diff += loss_diff.item(); run_repa += loss_repa.item()
251
+ if (step + 1) % args.log_every == 0:
252
+ el = time.time() - t0
253
+ sps = args.log_every / el
254
+ print(f"[s{step+1:06d}] loss={run/args.log_every:.4f} diff={run_diff/args.log_every:.4f} "
255
+ f"repa={run_repa/args.log_every:.4f} rw={rw:.3f} lr={lr_at(step):.2e} gnorm={gn:.2f} "
256
+ f"{sps:.2f} steps/s eta={(args.steps-step-1)/sps/3600:.1f}h", flush=True)
257
+ logf.write(json.dumps({"step": step + 1, "loss": run/args.log_every, "loss_diff": run_diff/args.log_every,
258
+ "loss_repa": run_repa/args.log_every, "repa_weight": rw,
259
+ "steps_per_s": sps}) + "\n"); logf.flush()
260
+ run, run_diff, run_repa, t0 = 0.0, 0.0, 0.0, time.time()
261
+
262
+ if (step + 1) % args.val_every == 0 or step + 1 == args.steps:
263
+ vl = val_loss()
264
+ tag = ""
265
+ if vl < best:
266
+ best = vl
267
+ torch.save({"ema": ema.state_dict(), "step": step, "val": vl,
268
+ "cfg": {"dim": args.dim, "depth": args.depth, "heads": args.heads,
269
+ "mlp_hidden": args.mlp_hidden, "t5_len": args.t5_len}},
270
+ f"{args.out}/best.pt")
271
+ tag = " *best*"
272
+ print(f"[s{step+1:06d}] val_loss={vl:.5f}{tag}", flush=True)
273
+ logf.write(json.dumps({"step": step + 1, "val_loss": vl}) + "\n"); logf.flush()
274
+ t0 = time.time()
275
+
276
+ if (step + 1) % args.save_every == 0 or step + 1 == args.steps:
277
+ torch.save({"model": model.state_dict(), "ema": ema.state_dict(), "opt": opt.state_dict(),
278
+ "step": step, "best": best,
279
+ "cfg": {"dim": args.dim, "depth": args.depth, "heads": args.heads,
280
+ "mlp_hidden": args.mlp_hidden, "t5_len": args.t5_len}},
281
+ f"{args.out}/latest.pt")
282
+
283
+ print("TRAINDONE best_val", best, flush=True)
284
+
285
+ if __name__ == "__main__":
286
+ main()