BiliSakura commited on
Commit
772b208
Β·
verified Β·
1 Parent(s): 6afe0c8

Upload PixelDiT2-diffusers checkpoints

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
+ PixelDiT2-H-16-256/demo.png filter=lfs diff=lfs merge=lfs -text
37
+ PixelDiT2-H-16-512/demo.png filter=lfs diff=lfs merge=lfs -text
PixelDiT2-H-16-256/demo.png ADDED

Git LFS Details

  • SHA256: d663be8988a8ee80d197bbcffbeff531dcc1b3a1751448e53e8abb2f155d8e5d
  • Pointer size: 131 Bytes
  • Size of remote file: 145 kB
PixelDiT2-H-16-256/encoder/LICENSE.md ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # DINOv3 License
2
+
3
+ *Last Updated: August 19, 2025*
4
+
5
+ **β€œAgreement”** means the terms and conditions for use, reproduction, distribution and modification of the DINO Materials set forth herein.
6
+
7
+ **β€œDINO Materials”** means, collectively, Documentation and the models, software and algorithms, including machine-learning model code, trained model weights, inference-enabling code, training-enabling code, fine-tuning enabling code, and other elements of the foregoing distributed by Meta and made available under this Agreement.
8
+
9
+ **β€œDocumentation”** means the specifications, manuals and documentation accompanying
10
+ DINO Materials distributed by Meta.
11
+
12
+ **β€œLicensee”** or **β€œyou”** means you, or your employer or any other person or entity (if you are entering into this Agreement on such person or entity’s behalf), of the age required under applicable laws, rules or regulations to provide legal consent and that has legal authority to bind your employer or such other person or entity if you are entering in this Agreement on their behalf.
13
+
14
+ **β€œMeta”** or **β€œwe”** means Meta Platforms Ireland Limited (if you are located in or, if you are an entity, your principal place of business is in the EEA or Switzerland) or Meta Platforms, Inc. (if you are located outside of the EEA or Switzerland).
15
+
16
+ **β€œSanctions”** means any economic or trade sanctions or restrictions administered or enforced by the United States (including the Office of Foreign Assets Control of the U.S. Department of the Treasury (β€œOFAC”), the U.S. Department of State and the U.S. Department of Commerce), the United Nations, the European Union, or the United Kingdom.
17
+
18
+ **β€œTrade Controls”** means any of the following: Sanctions and applicable export and import controls.
19
+
20
+ By clicking β€œI Accept” below or by using or distributing any portion or element of the DINO Materials, you agree to be bound by this Agreement.
21
+
22
+ ## 1. License Rights and Redistribution.
23
+
24
+ a. <ins>Grant of Rights</ins>. You are granted a non-exclusive, worldwide, non-transferable and royalty-free limited license under Meta’s intellectual property or other rights owned by Meta embodied in the DINO Materials to use, reproduce, distribute, copy, create derivative works of, and make modifications to the DINO Materials.
25
+
26
+ b. <ins>Redistribution and Use</ins>.
27
+
28
+ i. Distribution of DINO Materials, and any derivative works thereof, are subject to the terms of this Agreement. If you distribute or make the DINO Materials, or any derivative works thereof, available to a third party, you may only do so under the terms of this Agreement and you shall provide a copy of this Agreement with any such DINO Materials.
29
+
30
+ ii. If you submit for publication the results of research you perform on, using, or otherwise in connection with DINO Materials, you must acknowledge the use of DINO Materials in your publication.
31
+
32
+ iii. Your use of the DINO Materials must comply with applicable laws and regulations, including Trade Control Laws and applicable privacy and data protection laws.
33
+
34
+ iv. Your use of the DINO Materials will not involve or encourage others to reverse engineer, decompile or discover the underlying components of the DINO Materials.
35
+
36
+ v. You are not the target of Trade Controls and your use of DINO Materials must comply with Trade Controls. You agree not to use, or permit others to use, DINO Materials for any activities subject to the International Traffic in Arms Regulations (ITAR) or end uses prohibited by Trade Controls, including those related to military or warfare purposes, nuclear industries or applications, espionage, or the development or use of guns or illegal weapons.
37
+
38
+ ## 2. User Support.
39
+
40
+ Your use of the DINO Materials is done at your own discretion; Meta does not process any information nor provide any service in relation to such use. Meta is under no obligation to provide any support services for the DINO Materials. Any support provided is β€œas is”, β€œwith all faults”, and without warranty of any kind.
41
+
42
+ ## 3. Disclaimer of Warranty.
43
+
44
+ UNLESS REQUIRED BY APPLICABLE LAW, THE DINO MATERIALS AND ANY OUTPUT AND RESULTS THEREFROM ARE PROVIDED ON AN β€œAS IS” BASIS, WITHOUT WARRANTIES OF ANY KIND, AND META DISCLAIMS ALL WARRANTIES OF ANY KIND, BOTH EXPRESS AND IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. YOU ARE SOLELY RESPONSIBLE FOR DETERMINING THE APPROPRIATENESS OF USING OR REDISTRIBUTING THE DINO MATERIALS AND ASSUME ANY RISKS ASSOCIATED WITH YOUR USE OF THE DINO MATERIALS AND ANY OUTPUT AND RESULTS.
45
+
46
+ ## 4. Limitation of Liability.
47
+
48
+ IN NO EVENT WILL META OR ITS AFFILIATES BE LIABLE UNDER ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, TORT, NEGLIGENCE, PRODUCTS LIABILITY, OR OTHERWISE, ARISING OUT OF THIS AGREEMENT, FOR ANY LOST PROFITS OR ANY DIRECT OR INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL, EXEMPLARY OR PUNITIVE DAMAGES, EVEN IF META OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF ANY OF THE FOREGOING.
49
+
50
+ ## 5. Intellectual Property.
51
+
52
+ a. Subject to Meta’s ownership of DINO Materials and derivatives made by or for Meta, with respect to any derivative works and modifications of the DINO Materials that are made by you, as between you and Meta, you are and will be the owner of such derivative works and modifications.
53
+
54
+ b. If you institute litigation or other proceedings against Meta or any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the DINO Materials, outputs or results, or any portion of any of the foregoing, constitutes infringement of intellectual property or other rights owned or licensable by you, then any licenses granted to you under this Agreement shall terminate as of the date such litigation or claim is filed or instituted. You will indemnify and hold harmless Meta from and against any claim by any third party arising out of or related to your use or distribution of the DINO Materials.
55
+
56
+ ## 6. Term and Termination.
57
+
58
+ The term of this Agreement will commence upon your acceptance of this Agreement or access to the DINO Materials and will continue in full force and effect until terminated in accordance with the terms and conditions herein. Meta may terminate this Agreement if you are in breach of any term or condition of this Agreement. Upon termination of this Agreement, you shall delete and cease use of the DINO Materials. Sections 3, 4 and 7 shall survive the termination of this Agreement.
59
+
60
+ ## 7. Governing Law and Jurisdiction.
61
+
62
+ This Agreement will be governed and construed under the laws of the State of California without regard to choice of law principles, and the UN Convention on Contracts for the International Sale of Goods does not apply to this Agreement. The courts of California shall have exclusive jurisdiction of any dispute arising out of this Agreement.
63
+
64
+ ## 8. Modifications and Amendments.
65
+
66
+ Meta may modify this Agreement from time to time; provided that they are similar in spirit to the current version of the Agreement, but may differ in detail to address new problems or concerns. All such changes will be effective immediately. Your continued use of the DINO Materials after any modification to this Agreement constitutes your agreement to such modification. Except as provided in this Agreement, no modification or addition to any provision of this Agreement will be binding unless it is in writing and signed by an authorized representative of both you and Meta.
PixelDiT2-H-16-256/encoder/README.md ADDED
@@ -0,0 +1,477 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ extra_gated_fields:
3
+ First Name: text
4
+ Last Name: text
5
+ Date of birth: date_picker
6
+ Country: country
7
+ Affiliation: text
8
+ Job title:
9
+ type: select
10
+ options:
11
+ - Student
12
+ - Research Graduate
13
+ - AI researcher
14
+ - AI developer/engineer
15
+ - Reporter
16
+ - Other
17
+ geo: ip_location
18
+ By clicking Submit below I accept the terms of the license and acknowledge that the information I provide will be collected stored processed and shared in accordance with the Meta Privacy Policy: checkbox
19
+ extra_gated_description: >-
20
+ The information you provide will be collected, stored, processed and shared in
21
+ accordance with the [Meta Privacy
22
+ Policy](https://www.facebook.com/privacy/policy/).
23
+ extra_gated_button_content: Submit
24
+ language:
25
+ - en
26
+ tags:
27
+ - dino
28
+ - dinov3
29
+ - arxiv:2508.10104
30
+ license: other
31
+ license_name: dinov3-license
32
+ license_link: https://ai.meta.com/resources/models-and-libraries/dinov3-license
33
+ base_model: facebook/dinov3-vit7b16-pretrain-lvd1689m
34
+ pipeline_tag: image-feature-extraction
35
+ library_name: transformers
36
+ ---
37
+
38
+ # Model Card for DINOv3
39
+
40
+ DINOv3 is a family of versatile vision foundation models that outperforms the specialized state of the art across a broad range of settings, without fine-tuning. DINOv3 produces high-quality dense features that achieve outstanding performance on various vision tasks, significantly surpassing previous self- and weakly-supervised foundation models.
41
+
42
+ ## Model Details
43
+
44
+ These are Vision Transformer and ConvNeXt models trained following the method described in the DINOv3 paper. 12 models are provided:
45
+
46
+ - 10 models pretrained on web data (LVD-1689M dataset)
47
+ - 1 ViT-7B trained from scratch,
48
+ - 5 ViT-S/S+/B/L/H+ models distilled from the ViT-7B,
49
+ - 4 ConvNeXt-{T/S/B/L} models distilled from the ViT-7B,
50
+ - 2 models pretrained on satellite data (SAT-493M dataset)
51
+ - 1 ViT-7B trained from scratch
52
+ - 1 ViT-L distilled from the ViT-7B
53
+
54
+
55
+ Each Transformer-based model takes an image as input and returns a class token, patch tokens (and register tokens). These models follow a ViT architecture, with a patch size of 16. For a 224x224 image, this results in 1 class token + 4 register tokens + 196 patch tokens = 201 tokens (for DINOv2 with registers this resulted in 1 + 4 + 256 = 261 tokens).
56
+
57
+ The models can accept larger images provided the image shapes are multiples of the patch size (16). If this condition is not verified, the model will crop to the closest smaller multiple of the patch size.
58
+
59
+ ### Model Description
60
+
61
+ - **Developed by:** Meta AI
62
+ - **Model type:** Vision Transformer, ConvNeXt
63
+ - **License:** [DINOv3 License](https://ai.meta.com/resources/models-and-libraries/dinov3-license/)
64
+
65
+ ### Model Sources
66
+
67
+ - **Repository:** [https://github.com/facebookresearch/dinov3](https://github.com/facebookresearch/dinov3)
68
+ - **Paper:** [https://arxiv.org/abs/2508.10104](https://arxiv.org/abs/2508.10104)
69
+
70
+ ## Uses
71
+
72
+ The models are vision backbones providing multi-purpose features for downstream tasks.
73
+
74
+ ### Direct Use
75
+
76
+ The models can be used without fine-tuning, with downstream classifiers as simple as linear layers, to obtain competitive results:
77
+
78
+ - on image classification, using k-NN classifiers on the class token
79
+ - on image classification, with logistic regression classifiers applied on the class token
80
+ - on image classification, with a linear layer applied on the class token and the average of the patch tokens
81
+ - on image retrieval using nearest neighbors
82
+ - on geometric and semantic 3D keypoint correspondances
83
+ - on depth estimation, semantic segmentation, using linear layers
84
+ - on unsupervised object discovery
85
+ - on video segmentation tracking
86
+ - on video classification, using a small 4-layer attentive probe
87
+
88
+ ### Downstream Use
89
+
90
+ While fine-tuning the models can yield some gains, it is recommended to keep this option as a last resort: the frozen features are expected to provide good performance out-of-the-box.
91
+
92
+ ## Bias, Risks, and Limitations
93
+
94
+ Compared to DINOv2 and SEERv2, DINOv3 delivers somewhat consistent performance across income categories on geographical fairness and diversity, although with a notable performance drop in the low-income bucket compared to the highest-income bucket.
95
+
96
+ DINOv3 also achieves relatively good scores across different regions, improving over its predecessor DINOv2. However, a relative difference is still observed between Europe and Africa.
97
+
98
+ ### Recommendations
99
+
100
+ Fine-tuning is expected to increase the biases in the features produced by the model as they will be tuned to the fine-tuning labels.
101
+
102
+ ## How to Get Started with the Model
103
+
104
+ The example below demonstrates how to obtain an image embedding with [Pipeline] or the [AutoModel] class.
105
+
106
+ ```python
107
+ from transformers import pipeline
108
+ from transformers.image_utils import load_image
109
+
110
+ url = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/pipeline-cat-chonk.jpeg"
111
+ image = load_image(url)
112
+
113
+ feature_extractor = pipeline(
114
+ model="facebook/dinov3-vits16-pretrain-lvd1689m",
115
+ task="image-feature-extraction",
116
+ )
117
+ features = feature_extractor(image)
118
+ ```
119
+
120
+ ```python
121
+ import torch
122
+ from transformers import AutoImageProcessor, AutoModel
123
+ from transformers.image_utils import load_image
124
+
125
+ url = "http://images.cocodataset.org/val2017/000000039769.jpg"
126
+ image = load_image(url)
127
+
128
+ pretrained_model_name = "facebook/dinov3-vits16-pretrain-lvd1689m"
129
+ processor = AutoImageProcessor.from_pretrained(pretrained_model_name)
130
+ model = AutoModel.from_pretrained(
131
+ pretrained_model_name,
132
+ device_map="auto",
133
+ )
134
+
135
+ inputs = processor(images=image, return_tensors="pt").to(model.device)
136
+ with torch.inference_mode():
137
+ outputs = model(**inputs)
138
+
139
+ pooled_output = outputs.pooler_output
140
+ print("Pooled output shape:", pooled_output.shape)
141
+ ```
142
+
143
+ ## Training Details
144
+
145
+ ### Training Data
146
+
147
+ - Web dataset (LVD-1689M): a curated dataset of 1,689 millions of images extracted from a large data
148
+ pool of 17 billions web images collected from public posts on Instagram
149
+
150
+ - Satellite dataset (SAT-493M): a dataset of 493 millions of 512x512 images sampled randomly from Maxar RGB ortho-rectified imagery at 0.6 meter resolution
151
+
152
+ ### Training Procedure
153
+
154
+ **Training objective:**
155
+
156
+ - DINO self-distillation loss with multi-crop
157
+ - iBOT masked-image modeling loss
158
+ - KoLeo regularization on [CLS] tokens
159
+ - Gram anchoring
160
+
161
+ - **Training regime:** PyTorch FSDP2 (with bf16 and fp8 matrix multiplications)
162
+
163
+ **Distillation:**
164
+
165
+ - Distillation follows the standard DINOv3 pretraining procedure, except the teacher is a frozen pretrained ViT-7B.
166
+
167
+ ## Evaluation
168
+
169
+ **Results**
170
+
171
+ The reader is referred to the associated paper for details on the evaluation protocols
172
+
173
+ *Results for ViT backbones pretrained (or distilled) on web (LVD-1689M)*
174
+
175
+ <table>
176
+ <tr>
177
+ <th></th>
178
+ <!-- <th></th> -->
179
+ <th colspan="4">Global Tasks</th>
180
+ <th colspan="5">Dense Tasks</th>
181
+ </tr>
182
+ <tr>
183
+ <th>Model</th>
184
+ <!-- <th>Dataset</th> -->
185
+ <th>IN-ReaL</th>
186
+ <th>IN-R</th>
187
+ <th>Obj.Net</th>
188
+ <th>Ox.-H</th>
189
+ <th>ADE20k</th>
190
+ <th>NYU↓</th>
191
+ <th>DAVIS</th>
192
+ <th>NAVI</th>
193
+ <th>SPair</th>
194
+ </tr>
195
+ <tr>
196
+ <td>DINOv3 ViT-S/16</td>
197
+ <!-- <td>LVD-1689M</td> -->
198
+ <td align="right">87.0</td>
199
+ <td align="right">60.4</td>
200
+ <td align="right">50.9</td>
201
+ <td align="right">49.5</td>
202
+ <td align="right">47.0</td>
203
+ <td align="right">0.403</td>
204
+ <td align="right">72.7</td>
205
+ <td align="right">56.3</td>
206
+ <td align="right">50.4</td>
207
+ </tr>
208
+ <tr>
209
+ <td>DINOv3 ViT-S+/16</td>
210
+ <!-- <td>LVD-1689M</td> -->
211
+ <td align="right">88.0</td>
212
+ <td align="right">68.8</td>
213
+ <td align="right">54.6</td>
214
+ <td align="right">50.0</td>
215
+ <td align="right">48.8</td>
216
+ <td align="right">0.399</td>
217
+ <td align="right">75.5</td>
218
+ <td align="right">57.1</td>
219
+ <td align="right">55.2</td>
220
+ </tr>
221
+ <tr>
222
+ <td>DINOv3 ViT-B/16</td>
223
+ <!-- <td>LVD-1689M</td> -->
224
+ <td align="right">89.3</td>
225
+ <td align="right">76.7</td>
226
+ <td align="right">64.1</td>
227
+ <td align="right">58.5</td>
228
+ <td align="right">51.8</td>
229
+ <td align="right">0.373</td>
230
+ <td align="right">77.2</td>
231
+ <td align="right">58.8</td>
232
+ <td align="right">57.2</td>
233
+ </tr>
234
+ <tr>
235
+ <td>DINOv3 ViT-L/16</td>
236
+ <!-- <td>LVD-1689M</td> -->
237
+ <td align="right">90.2</td>
238
+ <td align="right">88.1</td>
239
+ <td align="right">74.8</td>
240
+ <td align="right">63.1</td>
241
+ <td align="right">54.9</td>
242
+ <td align="right">0.352</td>
243
+ <td align="right">79.9</td>
244
+ <td align="right">62.3</td>
245
+ <td align="right">61.3</td>
246
+ </tr>
247
+ <tr>
248
+ <td>DINOv3 ViT-H+/16</td>
249
+ <!-- <td>LVD-1689M</td> -->
250
+ <td align="right">90.3</td>
251
+ <td align="right">90.0</td>
252
+ <td align="right">78.6</td>
253
+ <td align="right">64.5</td>
254
+ <td align="right">54.8</td>
255
+ <td align="right">0.352</td>
256
+ <td align="right">79.3</td>
257
+ <td align="right">63.3</td>
258
+ <td align="right">56.3</td>
259
+ </tr>
260
+ <tr>
261
+ <td>DINOv3 ViT-7B/16</td>
262
+ <!-- <td>LVD-1689M</td> -->
263
+ <td align="right">90.4</td>
264
+ <td align="right">91.1</td>
265
+ <td align="right">91.1</td>
266
+ <td align="right">72.8</td>
267
+ <td align="right">55.9</td>
268
+ <td align="right">0.309</td>
269
+ <td align="right">79.7</td>
270
+ <td align="right">64.4</td>
271
+ <td align="right">58.7</td>
272
+ </tr>
273
+ </table>
274
+
275
+ *Results for ConvNeXt backbones distilled on web (LVD-1689M)*
276
+
277
+ <table>
278
+ <tr>
279
+ <th></th>
280
+ <th colspan="6">Global Tasks</th>
281
+ <th colspan="2">Dense Tasks</th>
282
+ </tr>
283
+ <tr>
284
+ <th>Model</th>
285
+ <th colspan="2">IN-ReaL</th>
286
+ <th colspan="2">IN-R</th>
287
+ <th colspan="2">Obj.Net</th>
288
+ <th>ADE20k</th>
289
+ <th>NYU↓</th>
290
+ </tr>
291
+ <tr>
292
+ <td></th>
293
+ <td>@256px</td>
294
+ <td>@512px</td>
295
+ <td>@256px</td>
296
+ <td>@512px</td>
297
+ <td>@256px</td>
298
+ <td>@512px</td>
299
+ <td colspan="2"></td>
300
+ </tr>
301
+ <tr>
302
+ <td>DINOv3 ConvNeXt Tiny</td>
303
+ <td align="right">86.6</td>
304
+ <td align="right">87.7</td>
305
+ <td align="right">73.7</td>
306
+ <td align="right">74.1</td>
307
+ <td align="right">52.6</td>
308
+ <td align="right">58.7</td>
309
+ <td align="right">42.7</td>
310
+ <td align="right">0.448</td>
311
+ </tr>
312
+ <tr>
313
+ <td>DINOv3 ConvNeXt Small</td>
314
+ <td align="right">87.9</td>
315
+ <td align="right">88.7</td>
316
+ <td align="right">73.7</td>
317
+ <td align="right">74.1</td>
318
+ <td align="right">52.6</td>
319
+ <td align="right">58.7</td>
320
+ <td align="right">44.8</td>
321
+ <td align="right">0.432</td>
322
+ </tr>
323
+ <tr>
324
+ <td>DINOv3 ConvNeXt Base</td>
325
+ <td align="right">88.5</td>
326
+ <td align="right">89.2</td>
327
+ <td align="right">77.2</td>
328
+ <td align="right">78.2</td>
329
+ <td align="right">56.2</td>
330
+ <td align="right">61.3</td>
331
+ <td align="right">46.3</td>
332
+ <td align="right">0.420</td>
333
+ </tr>
334
+ <tr>
335
+ <td>DINOv3 ConvNeXt Large</td>
336
+ <td align="right">88.9</td>
337
+ <td align="right">89.4</td>
338
+ <td align="right">81.3</td>
339
+ <td align="right">82.4</td>
340
+ <td align="right">59.3</td>
341
+ <td align="right">65.2</td>
342
+ <td align="right">47.8</td>
343
+ <td align="right">0.403</td>
344
+ </tr>
345
+ </table>
346
+
347
+ *Results for ViT backbones pretrained (or distilled) on satellite (SAT-493M)*
348
+
349
+ <table>
350
+ <tr>
351
+ <th></th>
352
+ <th colspan="7">(GEO-Bench) Classification</th>
353
+ </tr>
354
+ <tr>
355
+ <th>Model</ht>
356
+ <th>m-BEnet</th>
357
+ <th>m-brick-kiln
358
+ <th>m-eurosat</th>
359
+ <th>m-forestnet</th>
360
+ <th>m-pv4ger</th>
361
+ <th>m-so2sat</th>
362
+ <th>mean</th>
363
+ </tr>
364
+ <tr>
365
+ <td>DINOv3 ViT-L/16</td>
366
+ <td>73.0</td>
367
+ <td>96.5</td>
368
+ <td>94.1</td>
369
+ <td>60.6</td>
370
+ <td>96.0</td>
371
+ <td>57.4</td>
372
+ <td>79.6</td>
373
+ </tr>
374
+ <tr>
375
+ <td>DINOv3 ViT-7B/16</td>
376
+ <td>74.0</td>
377
+ <td>97.2</td>
378
+ <td>94.8</td>
379
+ <td>62.3</td>
380
+ <td>96.1</td>
381
+ <td>62.1</td>
382
+ <td>81.1</td>
383
+ </tr>
384
+ <tr>
385
+ <th></th>
386
+ <th colspan="7">(GEO-Bench) Segmentation</th>
387
+ </tr>
388
+ <tr>
389
+ <th>Model</th>
390
+ <th>m-cashew</th>
391
+ <th>m-chesapeake</th>
392
+ <th>m-NeonTree</th>
393
+ <th>m-nz-cattle</th>
394
+ <th>m-pv4ger-seg</th>
395
+ <th>m-SA-crop</th>
396
+ <th>mean</th>
397
+ </tr>
398
+ <tr>
399
+ <td>DINOv3 ViT-L/16</td>
400
+ <td>94.2</td>
401
+ <td>75.6</td>
402
+ <td>61.8</td>
403
+ <td>83.7</td>
404
+ <td>95.2</td>
405
+ <td>36.8</td>
406
+ <td>74.5</td>
407
+ </tr>
408
+ <tr>
409
+ <td>DINOv3 ViT-7B/16</td>
410
+ <td>94.1</td>
411
+ <td>76.6</td>
412
+ <td>62.6</td>
413
+ <td>83.4</td>
414
+ <td>95.5</td>
415
+ <td>37.6</td>
416
+ <td>75.0</td>
417
+ </tr>
418
+ </table>
419
+
420
+
421
+ ## Environmental Impact
422
+
423
+ - **Hardware Type:** Nvidia H100
424
+ - **Hours used:** 61,440 hours for ViT-7B model training
425
+ - **Cloud Provider:** Private infrastructure
426
+ - **Compute Region:** USA
427
+ - **Carbon Emitted:** 18t CO2eq
428
+
429
+ ## Technical Specifications
430
+
431
+ ### Model Architecture and Objective
432
+
433
+ Vision Transformer models:
434
+
435
+ - ViT-S (21M parameters): patch size 16, embedding dimension 384, 4 register tokens, 6 heads, MLP FFN, RoPE
436
+ - ViT-S+ (29M parameters): patch size 16, embedding dimension 384, 4 register tokens, 6 heads, SwiGLU FFN, RoPE
437
+ - ViT-B (86M parameters): patch size 16, embedding dimension 768, 4 register tokens, 12 heads, MLP FFN, RoPE
438
+ - ViT-L (300M parameters): patch size 16, embedding dimension 1024, 4 register tokens, 16 heads, MLP FFN, RoPE
439
+ - ViT-H+ (840M parameters): patch size 16, embedding dimension 1280, 4 register tokens, 20 heads, SwiGLU FFN, RoPE
440
+ - ViT-7B (6716M parameters): patch size 16, embedding dimension 4096, 4 register tokens, 32 heads, SwiGLU FFN, RoPE
441
+
442
+ ConvNeXt models:
443
+
444
+ - ConvNeXt Tiny (29M parameters)
445
+ - ConvNeXt Small (50M parameters)
446
+ - ConvNeXt Base (89M parameters)
447
+ - ConvNeXt Large (198M parameters)
448
+
449
+ ### Compute Infrastructure
450
+
451
+ #### Hardware
452
+
453
+ Nvidia H100 GPUs
454
+
455
+ #### Software
456
+
457
+ PyTorch 2.7
458
+
459
+ ## More Information
460
+
461
+ See the [blog post](https://ai.meta.com/blog/dinov3-self-supervised-vision-model/) and the associated [website](https://ai.meta.com/dinov3/).
462
+
463
+ ## Citation
464
+
465
+ **BibTeX**
466
+
467
+ ```
468
+ @misc{simeoni2025dinov3,
469
+ title={{DINOv3}},
470
+ author={Sim{\'e}oni, Oriane and Vo, Huy V. and Seitzer, Maximilian and Baldassarre, Federico and Oquab, Maxime and Jose, Cijo and Khalidov, Vasil and Szafraniec, Marc and Yi, Seungeun and Ramamonjisoa, Micha{\"e}l and Massa, Francisco and Haziza, Daniel and Wehrstedt, Luca and Wang, Jianyuan and Darcet, Timoth{\'e}e and Moutakanni, Th{\'e}o and Sentana, Leonel and Roberts, Claire and Vedaldi, Andrea and Tolan, Jamie and Brandt, John and Couprie, Camille and Mairal, Julien and J{\'e}gou, Herv{\'e} and Labatut, Patrick and Bojanowski, Piotr},
471
+ year={2025},
472
+ eprint={2508.10104},
473
+ archivePrefix={arXiv},
474
+ primaryClass={cs.CV},
475
+ url={https://arxiv.org/abs/2508.10104},
476
+ }
477
+ ```
PixelDiT2-H-16-256/encoder/config.json ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "DINOv3ViTModel"
4
+ ],
5
+ "attention_dropout": 0.0,
6
+ "drop_path_rate": 0.0,
7
+ "hidden_act": "gelu",
8
+ "hidden_size": 384,
9
+ "image_size": 224,
10
+ "initializer_range": 0.02,
11
+ "intermediate_size": 1536,
12
+ "key_bias": false,
13
+ "layer_norm_eps": 1e-05,
14
+ "layerscale_value": 1.0,
15
+ "mlp_bias": true,
16
+ "model_type": "dinov3_vit",
17
+ "num_attention_heads": 6,
18
+ "num_channels": 3,
19
+ "num_hidden_layers": 12,
20
+ "num_register_tokens": 4,
21
+ "patch_size": 16,
22
+ "pos_embed_jitter": null,
23
+ "pos_embed_rescale": 2.0,
24
+ "pos_embed_shift": null,
25
+ "proj_bias": true,
26
+ "query_bias": true,
27
+ "rope_theta": 100.0,
28
+ "torch_dtype": "float32",
29
+ "transformers_version": "4.56.0.dev0",
30
+ "use_gated_mlp": false,
31
+ "value_bias": true
32
+ }
PixelDiT2-H-16-256/encoder/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4610ad75edef83e75afdebf162d148dc628045ea6cbb83d67d4708c709c4f91d
3
+ size 86406384
PixelDiT2-H-16-256/encoder/preprocessor_config.json ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "crop_size": null,
3
+ "data_format": "channels_first",
4
+ "default_to_square": true,
5
+ "device": null,
6
+ "disable_grouping": null,
7
+ "do_center_crop": null,
8
+ "do_convert_rgb": null,
9
+ "do_normalize": true,
10
+ "do_rescale": true,
11
+ "do_resize": true,
12
+ "image_mean": [
13
+ 0.485,
14
+ 0.456,
15
+ 0.406
16
+ ],
17
+ "image_processor_type": "DINOv3ViTImageProcessorFast",
18
+ "image_std": [
19
+ 0.229,
20
+ 0.224,
21
+ 0.225
22
+ ],
23
+ "input_data_format": null,
24
+ "resample": 2,
25
+ "rescale_factor": 0.00392156862745098,
26
+ "return_tensors": null,
27
+ "size": {
28
+ "height": 224,
29
+ "width": 224
30
+ }
31
+ }
PixelDiT2-H-16-256/model_index.json ADDED
@@ -0,0 +1,1021 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_class_name": [
3
+ "pipeline",
4
+ "PixelDiT2Pipeline"
5
+ ],
6
+ "_diffusers_version": "0.39.0",
7
+ "encoder": [
8
+ "transformers",
9
+ "DINOv3ViTModel"
10
+ ],
11
+ "scheduler": [
12
+ "scheduling_pixeldit2",
13
+ "PixelDiT2Scheduler"
14
+ ],
15
+ "transformer": [
16
+ "transformer_pixeldit2",
17
+ "PixelDiT2Transformer2DModel"
18
+ ],
19
+ "id2label": {
20
+ "0": "tench, Tinca tinca",
21
+ "1": "goldfish, Carassius auratus",
22
+ "2": "great white shark, white shark, man-eater, man-eating shark, Carcharodon carcharias",
23
+ "3": "tiger shark, Galeocerdo cuvieri",
24
+ "4": "hammerhead, hammerhead shark",
25
+ "5": "electric ray, crampfish, numbfish, torpedo",
26
+ "6": "stingray",
27
+ "7": "cock",
28
+ "8": "hen",
29
+ "9": "ostrich, Struthio camelus",
30
+ "10": "brambling, Fringilla montifringilla",
31
+ "11": "goldfinch, Carduelis carduelis",
32
+ "12": "house finch, linnet, Carpodacus mexicanus",
33
+ "13": "junco, snowbird",
34
+ "14": "indigo bunting, indigo finch, indigo bird, Passerina cyanea",
35
+ "15": "robin, American robin, Turdus migratorius",
36
+ "16": "bulbul",
37
+ "17": "jay",
38
+ "18": "magpie",
39
+ "19": "chickadee",
40
+ "20": "water ouzel, dipper",
41
+ "21": "kite",
42
+ "22": "bald eagle, American eagle, Haliaeetus leucocephalus",
43
+ "23": "vulture",
44
+ "24": "great grey owl, great gray owl, Strix nebulosa",
45
+ "25": "European fire salamander, Salamandra salamandra",
46
+ "26": "common newt, Triturus vulgaris",
47
+ "27": "eft",
48
+ "28": "spotted salamander, Ambystoma maculatum",
49
+ "29": "axolotl, mud puppy, Ambystoma mexicanum",
50
+ "30": "bullfrog, Rana catesbeiana",
51
+ "31": "tree frog, tree-frog",
52
+ "32": "tailed frog, bell toad, ribbed toad, tailed toad, Ascaphus trui",
53
+ "33": "loggerhead, loggerhead turtle, Caretta caretta",
54
+ "34": "leatherback turtle, leatherback, leathery turtle, Dermochelys coriacea",
55
+ "35": "mud turtle",
56
+ "36": "terrapin",
57
+ "37": "box turtle, box tortoise",
58
+ "38": "banded gecko",
59
+ "39": "common iguana, iguana, Iguana iguana",
60
+ "40": "American chameleon, anole, Anolis carolinensis",
61
+ "41": "whiptail, whiptail lizard",
62
+ "42": "agama",
63
+ "43": "frilled lizard, Chlamydosaurus kingi",
64
+ "44": "alligator lizard",
65
+ "45": "Gila monster, Heloderma suspectum",
66
+ "46": "green lizard, Lacerta viridis",
67
+ "47": "African chameleon, Chamaeleo chamaeleon",
68
+ "48": "Komodo dragon, Komodo lizard, dragon lizard, giant lizard, Varanus komodoensis",
69
+ "49": "African crocodile, Nile crocodile, Crocodylus niloticus",
70
+ "50": "American alligator, Alligator mississipiensis",
71
+ "51": "triceratops",
72
+ "52": "thunder snake, worm snake, Carphophis amoenus",
73
+ "53": "ringneck snake, ring-necked snake, ring snake",
74
+ "54": "hognose snake, puff adder, sand viper",
75
+ "55": "green snake, grass snake",
76
+ "56": "king snake, kingsnake",
77
+ "57": "garter snake, grass snake",
78
+ "58": "water snake",
79
+ "59": "vine snake",
80
+ "60": "night snake, Hypsiglena torquata",
81
+ "61": "boa constrictor, Constrictor constrictor",
82
+ "62": "rock python, rock snake, Python sebae",
83
+ "63": "Indian cobra, Naja naja",
84
+ "64": "green mamba",
85
+ "65": "sea snake",
86
+ "66": "horned viper, cerastes, sand viper, horned asp, Cerastes cornutus",
87
+ "67": "diamondback, diamondback rattlesnake, Crotalus adamanteus",
88
+ "68": "sidewinder, horned rattlesnake, Crotalus cerastes",
89
+ "69": "trilobite",
90
+ "70": "harvestman, daddy longlegs, Phalangium opilio",
91
+ "71": "scorpion",
92
+ "72": "black and gold garden spider, Argiope aurantia",
93
+ "73": "barn spider, Araneus cavaticus",
94
+ "74": "garden spider, Aranea diademata",
95
+ "75": "black widow, Latrodectus mactans",
96
+ "76": "tarantula",
97
+ "77": "wolf spider, hunting spider",
98
+ "78": "tick",
99
+ "79": "centipede",
100
+ "80": "black grouse",
101
+ "81": "ptarmigan",
102
+ "82": "ruffed grouse, partridge, Bonasa umbellus",
103
+ "83": "prairie chicken, prairie grouse, prairie fowl",
104
+ "84": "peacock",
105
+ "85": "quail",
106
+ "86": "partridge",
107
+ "87": "African grey, African gray, Psittacus erithacus",
108
+ "88": "macaw",
109
+ "89": "sulphur-crested cockatoo, Kakatoe galerita, Cacatua galerita",
110
+ "90": "lorikeet",
111
+ "91": "coucal",
112
+ "92": "bee eater",
113
+ "93": "hornbill",
114
+ "94": "hummingbird",
115
+ "95": "jacamar",
116
+ "96": "toucan",
117
+ "97": "drake",
118
+ "98": "red-breasted merganser, Mergus serrator",
119
+ "99": "goose",
120
+ "100": "black swan, Cygnus atratus",
121
+ "101": "tusker",
122
+ "102": "echidna, spiny anteater, anteater",
123
+ "103": "platypus, duckbill, duckbilled platypus, duck-billed platypus, Ornithorhynchus anatinus",
124
+ "104": "wallaby, brush kangaroo",
125
+ "105": "koala, koala bear, kangaroo bear, native bear, Phascolarctos cinereus",
126
+ "106": "wombat",
127
+ "107": "jellyfish",
128
+ "108": "sea anemone, anemone",
129
+ "109": "brain coral",
130
+ "110": "flatworm, platyhelminth",
131
+ "111": "nematode, nematode worm, roundworm",
132
+ "112": "conch",
133
+ "113": "snail",
134
+ "114": "slug",
135
+ "115": "sea slug, nudibranch",
136
+ "116": "chiton, coat-of-mail shell, sea cradle, polyplacophore",
137
+ "117": "chambered nautilus, pearly nautilus, nautilus",
138
+ "118": "Dungeness crab, Cancer magister",
139
+ "119": "rock crab, Cancer irroratus",
140
+ "120": "fiddler crab",
141
+ "121": "king crab, Alaska crab, Alaskan king crab, Alaska king crab, Paralithodes camtschatica",
142
+ "122": "American lobster, Northern lobster, Maine lobster, Homarus americanus",
143
+ "123": "spiny lobster, langouste, rock lobster, crawfish, crayfish, sea crawfish",
144
+ "124": "crayfish, crawfish, crawdad, crawdaddy",
145
+ "125": "hermit crab",
146
+ "126": "isopod",
147
+ "127": "white stork, Ciconia ciconia",
148
+ "128": "black stork, Ciconia nigra",
149
+ "129": "spoonbill",
150
+ "130": "flamingo",
151
+ "131": "little blue heron, Egretta caerulea",
152
+ "132": "American egret, great white heron, Egretta albus",
153
+ "133": "bittern",
154
+ "134": "crane",
155
+ "135": "limpkin, Aramus pictus",
156
+ "136": "European gallinule, Porphyrio porphyrio",
157
+ "137": "American coot, marsh hen, mud hen, water hen, Fulica americana",
158
+ "138": "bustard",
159
+ "139": "ruddy turnstone, Arenaria interpres",
160
+ "140": "red-backed sandpiper, dunlin, Erolia alpina",
161
+ "141": "redshank, Tringa totanus",
162
+ "142": "dowitcher",
163
+ "143": "oystercatcher, oyster catcher",
164
+ "144": "pelican",
165
+ "145": "king penguin, Aptenodytes patagonica",
166
+ "146": "albatross, mollymawk",
167
+ "147": "grey whale, gray whale, devilfish, Eschrichtius gibbosus, Eschrichtius robustus",
168
+ "148": "killer whale, killer, orca, grampus, sea wolf, Orcinus orca",
169
+ "149": "dugong, Dugong dugon",
170
+ "150": "sea lion",
171
+ "151": "Chihuahua",
172
+ "152": "Japanese spaniel",
173
+ "153": "Maltese dog, Maltese terrier, Maltese",
174
+ "154": "Pekinese, Pekingese, Peke",
175
+ "155": "Shih-Tzu",
176
+ "156": "Blenheim spaniel",
177
+ "157": "papillon",
178
+ "158": "toy terrier",
179
+ "159": "Rhodesian ridgeback",
180
+ "160": "Afghan hound, Afghan",
181
+ "161": "basset, basset hound",
182
+ "162": "beagle",
183
+ "163": "bloodhound, sleuthhound",
184
+ "164": "bluetick",
185
+ "165": "black-and-tan coonhound",
186
+ "166": "Walker hound, Walker foxhound",
187
+ "167": "English foxhound",
188
+ "168": "redbone",
189
+ "169": "borzoi, Russian wolfhound",
190
+ "170": "Irish wolfhound",
191
+ "171": "Italian greyhound",
192
+ "172": "whippet",
193
+ "173": "Ibizan hound, Ibizan Podenco",
194
+ "174": "Norwegian elkhound, elkhound",
195
+ "175": "otterhound, otter hound",
196
+ "176": "Saluki, gazelle hound",
197
+ "177": "Scottish deerhound, deerhound",
198
+ "178": "Weimaraner",
199
+ "179": "Staffordshire bullterrier, Staffordshire bull terrier",
200
+ "180": "American Staffordshire terrier, Staffordshire terrier, American pit bull terrier, pit bull terrier",
201
+ "181": "Bedlington terrier",
202
+ "182": "Border terrier",
203
+ "183": "Kerry blue terrier",
204
+ "184": "Irish terrier",
205
+ "185": "Norfolk terrier",
206
+ "186": "Norwich terrier",
207
+ "187": "Yorkshire terrier",
208
+ "188": "wire-haired fox terrier",
209
+ "189": "Lakeland terrier",
210
+ "190": "Sealyham terrier, Sealyham",
211
+ "191": "Airedale, Airedale terrier",
212
+ "192": "cairn, cairn terrier",
213
+ "193": "Australian terrier",
214
+ "194": "Dandie Dinmont, Dandie Dinmont terrier",
215
+ "195": "Boston bull, Boston terrier",
216
+ "196": "miniature schnauzer",
217
+ "197": "giant schnauzer",
218
+ "198": "standard schnauzer",
219
+ "199": "Scotch terrier, Scottish terrier, Scottie",
220
+ "200": "Tibetan terrier, chrysanthemum dog",
221
+ "201": "silky terrier, Sydney silky",
222
+ "202": "soft-coated wheaten terrier",
223
+ "203": "West Highland white terrier",
224
+ "204": "Lhasa, Lhasa apso",
225
+ "205": "flat-coated retriever",
226
+ "206": "curly-coated retriever",
227
+ "207": "golden retriever",
228
+ "208": "Labrador retriever",
229
+ "209": "Chesapeake Bay retriever",
230
+ "210": "German short-haired pointer",
231
+ "211": "vizsla, Hungarian pointer",
232
+ "212": "English setter",
233
+ "213": "Irish setter, red setter",
234
+ "214": "Gordon setter",
235
+ "215": "Brittany spaniel",
236
+ "216": "clumber, clumber spaniel",
237
+ "217": "English springer, English springer spaniel",
238
+ "218": "Welsh springer spaniel",
239
+ "219": "cocker spaniel, English cocker spaniel, cocker",
240
+ "220": "Sussex spaniel",
241
+ "221": "Irish water spaniel",
242
+ "222": "kuvasz",
243
+ "223": "schipperke",
244
+ "224": "groenendael",
245
+ "225": "malinois",
246
+ "226": "briard",
247
+ "227": "kelpie",
248
+ "228": "komondor",
249
+ "229": "Old English sheepdog, bobtail",
250
+ "230": "Shetland sheepdog, Shetland sheep dog, Shetland",
251
+ "231": "collie",
252
+ "232": "Border collie",
253
+ "233": "Bouvier des Flandres, Bouviers des Flandres",
254
+ "234": "Rottweiler",
255
+ "235": "German shepherd, German shepherd dog, German police dog, alsatian",
256
+ "236": "Doberman, Doberman pinscher",
257
+ "237": "miniature pinscher",
258
+ "238": "Greater Swiss Mountain dog",
259
+ "239": "Bernese mountain dog",
260
+ "240": "Appenzeller",
261
+ "241": "EntleBucher",
262
+ "242": "boxer",
263
+ "243": "bull mastiff",
264
+ "244": "Tibetan mastiff",
265
+ "245": "French bulldog",
266
+ "246": "Great Dane",
267
+ "247": "Saint Bernard, St Bernard",
268
+ "248": "Eskimo dog, husky",
269
+ "249": "malamute, malemute, Alaskan malamute",
270
+ "250": "Siberian husky",
271
+ "251": "dalmatian, coach dog, carriage dog",
272
+ "252": "affenpinscher, monkey pinscher, monkey dog",
273
+ "253": "basenji",
274
+ "254": "pug, pug-dog",
275
+ "255": "Leonberg",
276
+ "256": "Newfoundland, Newfoundland dog",
277
+ "257": "Great Pyrenees",
278
+ "258": "Samoyed, Samoyede",
279
+ "259": "Pomeranian",
280
+ "260": "chow, chow chow",
281
+ "261": "keeshond",
282
+ "262": "Brabancon griffon",
283
+ "263": "Pembroke, Pembroke Welsh corgi",
284
+ "264": "Cardigan, Cardigan Welsh corgi",
285
+ "265": "toy poodle",
286
+ "266": "miniature poodle",
287
+ "267": "standard poodle",
288
+ "268": "Mexican hairless",
289
+ "269": "timber wolf, grey wolf, gray wolf, Canis lupus",
290
+ "270": "white wolf, Arctic wolf, Canis lupus tundrarum",
291
+ "271": "red wolf, maned wolf, Canis rufus, Canis niger",
292
+ "272": "coyote, prairie wolf, brush wolf, Canis latrans",
293
+ "273": "dingo, warrigal, warragal, Canis dingo",
294
+ "274": "dhole, Cuon alpinus",
295
+ "275": "African hunting dog, hyena dog, Cape hunting dog, Lycaon pictus",
296
+ "276": "hyena, hyaena",
297
+ "277": "red fox, Vulpes vulpes",
298
+ "278": "kit fox, Vulpes macrotis",
299
+ "279": "Arctic fox, white fox, Alopex lagopus",
300
+ "280": "grey fox, gray fox, Urocyon cinereoargenteus",
301
+ "281": "tabby, tabby cat",
302
+ "282": "tiger cat",
303
+ "283": "Persian cat",
304
+ "284": "Siamese cat, Siamese",
305
+ "285": "Egyptian cat",
306
+ "286": "cougar, puma, catamount, mountain lion, painter, panther, Felis concolor",
307
+ "287": "lynx, catamount",
308
+ "288": "leopard, Panthera pardus",
309
+ "289": "snow leopard, ounce, Panthera uncia",
310
+ "290": "jaguar, panther, Panthera onca, Felis onca",
311
+ "291": "lion, king of beasts, Panthera leo",
312
+ "292": "tiger, Panthera tigris",
313
+ "293": "cheetah, chetah, Acinonyx jubatus",
314
+ "294": "brown bear, bruin, Ursus arctos",
315
+ "295": "American black bear, black bear, Ursus americanus, Euarctos americanus",
316
+ "296": "ice bear, polar bear, Ursus Maritimus, Thalarctos maritimus",
317
+ "297": "sloth bear, Melursus ursinus, Ursus ursinus",
318
+ "298": "mongoose",
319
+ "299": "meerkat, mierkat",
320
+ "300": "tiger beetle",
321
+ "301": "ladybug, ladybeetle, lady beetle, ladybird, ladybird beetle",
322
+ "302": "ground beetle, carabid beetle",
323
+ "303": "long-horned beetle, longicorn, longicorn beetle",
324
+ "304": "leaf beetle, chrysomelid",
325
+ "305": "dung beetle",
326
+ "306": "rhinoceros beetle",
327
+ "307": "weevil",
328
+ "308": "fly",
329
+ "309": "bee",
330
+ "310": "ant, emmet, pismire",
331
+ "311": "grasshopper, hopper",
332
+ "312": "cricket",
333
+ "313": "walking stick, walkingstick, stick insect",
334
+ "314": "cockroach, roach",
335
+ "315": "mantis, mantid",
336
+ "316": "cicada, cicala",
337
+ "317": "leafhopper",
338
+ "318": "lacewing, lacewing fly",
339
+ "319": "dragonfly, darning needle, devils darning needle, sewing needle, snake feeder, snake doctor, mosquito hawk, skeeter hawk",
340
+ "320": "damselfly",
341
+ "321": "admiral",
342
+ "322": "ringlet, ringlet butterfly",
343
+ "323": "monarch, monarch butterfly, milkweed butterfly, Danaus plexippus",
344
+ "324": "cabbage butterfly",
345
+ "325": "sulphur butterfly, sulfur butterfly",
346
+ "326": "lycaenid, lycaenid butterfly",
347
+ "327": "starfish, sea star",
348
+ "328": "sea urchin",
349
+ "329": "sea cucumber, holothurian",
350
+ "330": "wood rabbit, cottontail, cottontail rabbit",
351
+ "331": "hare",
352
+ "332": "Angora, Angora rabbit",
353
+ "333": "hamster",
354
+ "334": "porcupine, hedgehog",
355
+ "335": "fox squirrel, eastern fox squirrel, Sciurus niger",
356
+ "336": "marmot",
357
+ "337": "beaver",
358
+ "338": "guinea pig, Cavia cobaya",
359
+ "339": "sorrel",
360
+ "340": "zebra",
361
+ "341": "hog, pig, grunter, squealer, Sus scrofa",
362
+ "342": "wild boar, boar, Sus scrofa",
363
+ "343": "warthog",
364
+ "344": "hippopotamus, hippo, river horse, Hippopotamus amphibius",
365
+ "345": "ox",
366
+ "346": "water buffalo, water ox, Asiatic buffalo, Bubalus bubalis",
367
+ "347": "bison",
368
+ "348": "ram, tup",
369
+ "349": "bighorn, bighorn sheep, cimarron, Rocky Mountain bighorn, Rocky Mountain sheep, Ovis canadensis",
370
+ "350": "ibex, Capra ibex",
371
+ "351": "hartebeest",
372
+ "352": "impala, Aepyceros melampus",
373
+ "353": "gazelle",
374
+ "354": "Arabian camel, dromedary, Camelus dromedarius",
375
+ "355": "llama",
376
+ "356": "weasel",
377
+ "357": "mink",
378
+ "358": "polecat, fitch, foulmart, foumart, Mustela putorius",
379
+ "359": "black-footed ferret, ferret, Mustela nigripes",
380
+ "360": "otter",
381
+ "361": "skunk, polecat, wood pussy",
382
+ "362": "badger",
383
+ "363": "armadillo",
384
+ "364": "three-toed sloth, ai, Bradypus tridactylus",
385
+ "365": "orangutan, orang, orangutang, Pongo pygmaeus",
386
+ "366": "gorilla, Gorilla gorilla",
387
+ "367": "chimpanzee, chimp, Pan troglodytes",
388
+ "368": "gibbon, Hylobates lar",
389
+ "369": "siamang, Hylobates syndactylus, Symphalangus syndactylus",
390
+ "370": "guenon, guenon monkey",
391
+ "371": "patas, hussar monkey, Erythrocebus patas",
392
+ "372": "baboon",
393
+ "373": "macaque",
394
+ "374": "langur",
395
+ "375": "colobus, colobus monkey",
396
+ "376": "proboscis monkey, Nasalis larvatus",
397
+ "377": "marmoset",
398
+ "378": "capuchin, ringtail, Cebus capucinus",
399
+ "379": "howler monkey, howler",
400
+ "380": "titi, titi monkey",
401
+ "381": "spider monkey, Ateles geoffroyi",
402
+ "382": "squirrel monkey, Saimiri sciureus",
403
+ "383": "Madagascar cat, ring-tailed lemur, Lemur catta",
404
+ "384": "indri, indris, Indri indri, Indri brevicaudatus",
405
+ "385": "Indian elephant, Elephas maximus",
406
+ "386": "African elephant, Loxodonta africana",
407
+ "387": "lesser panda, red panda, panda, bear cat, cat bear, Ailurus fulgens",
408
+ "388": "giant panda, panda, panda bear, coon bear, Ailuropoda melanoleuca",
409
+ "389": "barracouta, snoek",
410
+ "390": "eel",
411
+ "391": "coho, cohoe, coho salmon, blue jack, silver salmon, Oncorhynchus kisutch",
412
+ "392": "rock beauty, Holocanthus tricolor",
413
+ "393": "anemone fish",
414
+ "394": "sturgeon",
415
+ "395": "gar, garfish, garpike, billfish, Lepisosteus osseus",
416
+ "396": "lionfish",
417
+ "397": "puffer, pufferfish, blowfish, globefish",
418
+ "398": "abacus",
419
+ "399": "abaya",
420
+ "400": "academic gown, academic robe, judge robe",
421
+ "401": "accordion, piano accordion, squeeze box",
422
+ "402": "acoustic guitar",
423
+ "403": "aircraft carrier, carrier, flattop, attack aircraft carrier",
424
+ "404": "airliner",
425
+ "405": "airship, dirigible",
426
+ "406": "altar",
427
+ "407": "ambulance",
428
+ "408": "amphibian, amphibious vehicle",
429
+ "409": "analog clock",
430
+ "410": "apiary, bee house",
431
+ "411": "apron",
432
+ "412": "ashcan, trash can, garbage can, wastebin, ash bin, ash-bin, ashbin, dustbin, trash barrel, trash bin",
433
+ "413": "assault rifle, assault gun",
434
+ "414": "backpack, back pack, knapsack, packsack, rucksack, haversack",
435
+ "415": "bakery, bakeshop, bakehouse",
436
+ "416": "balance beam, beam",
437
+ "417": "balloon",
438
+ "418": "ballpoint, ballpoint pen, ballpen, Biro",
439
+ "419": "Band Aid",
440
+ "420": "banjo",
441
+ "421": "bannister, banister, balustrade, balusters, handrail",
442
+ "422": "barbell",
443
+ "423": "barber chair",
444
+ "424": "barbershop",
445
+ "425": "barn",
446
+ "426": "barometer",
447
+ "427": "barrel, cask",
448
+ "428": "barrow, garden cart, lawn cart, wheelbarrow",
449
+ "429": "baseball",
450
+ "430": "basketball",
451
+ "431": "bassinet",
452
+ "432": "bassoon",
453
+ "433": "bathing cap, swimming cap",
454
+ "434": "bath towel",
455
+ "435": "bathtub, bathing tub, bath, tub",
456
+ "436": "beach wagon, station wagon, wagon, estate car, beach waggon, station waggon, waggon",
457
+ "437": "beacon, lighthouse, beacon light, pharos",
458
+ "438": "beaker",
459
+ "439": "bearskin, busby, shako",
460
+ "440": "beer bottle",
461
+ "441": "beer glass",
462
+ "442": "bell cote, bell cot",
463
+ "443": "bib",
464
+ "444": "bicycle-built-for-two, tandem bicycle, tandem",
465
+ "445": "bikini, two-piece",
466
+ "446": "binder, ring-binder",
467
+ "447": "binoculars, field glasses, opera glasses",
468
+ "448": "birdhouse",
469
+ "449": "boathouse",
470
+ "450": "bobsled, bobsleigh, bob",
471
+ "451": "bolo tie, bolo, bola tie, bola",
472
+ "452": "bonnet, poke bonnet",
473
+ "453": "bookcase",
474
+ "454": "bookshop, bookstore, bookstall",
475
+ "455": "bottlecap",
476
+ "456": "bow",
477
+ "457": "bow tie, bow-tie, bowtie",
478
+ "458": "brass, memorial tablet, plaque",
479
+ "459": "brassiere, bra, bandeau",
480
+ "460": "breakwater, groin, groyne, mole, bulwark, seawall, jetty",
481
+ "461": "breastplate, aegis, egis",
482
+ "462": "broom",
483
+ "463": "bucket, pail",
484
+ "464": "buckle",
485
+ "465": "bulletproof vest",
486
+ "466": "bullet train, bullet",
487
+ "467": "butcher shop, meat market",
488
+ "468": "cab, hack, taxi, taxicab",
489
+ "469": "caldron, cauldron",
490
+ "470": "candle, taper, wax light",
491
+ "471": "cannon",
492
+ "472": "canoe",
493
+ "473": "can opener, tin opener",
494
+ "474": "cardigan",
495
+ "475": "car mirror",
496
+ "476": "carousel, carrousel, merry-go-round, roundabout, whirligig",
497
+ "477": "carpenters kit, tool kit",
498
+ "478": "carton",
499
+ "479": "car wheel",
500
+ "480": "cash machine, cash dispenser, automated teller machine, automatic teller machine, automated teller, automatic teller, ATM",
501
+ "481": "cassette",
502
+ "482": "cassette player",
503
+ "483": "castle",
504
+ "484": "catamaran",
505
+ "485": "CD player",
506
+ "486": "cello, violoncello",
507
+ "487": "cellular telephone, cellular phone, cellphone, cell, mobile phone",
508
+ "488": "chain",
509
+ "489": "chainlink fence",
510
+ "490": "chain mail, ring mail, mail, chain armor, chain armour, ring armor, ring armour",
511
+ "491": "chain saw, chainsaw",
512
+ "492": "chest",
513
+ "493": "chiffonier, commode",
514
+ "494": "chime, bell, gong",
515
+ "495": "china cabinet, china closet",
516
+ "496": "Christmas stocking",
517
+ "497": "church, church building",
518
+ "498": "cinema, movie theater, movie theatre, movie house, picture palace",
519
+ "499": "cleaver, meat cleaver, chopper",
520
+ "500": "cliff dwelling",
521
+ "501": "cloak",
522
+ "502": "clog, geta, patten, sabot",
523
+ "503": "cocktail shaker",
524
+ "504": "coffee mug",
525
+ "505": "coffeepot",
526
+ "506": "coil, spiral, volute, whorl, helix",
527
+ "507": "combination lock",
528
+ "508": "computer keyboard, keypad",
529
+ "509": "confectionery, confectionary, candy store",
530
+ "510": "container ship, containership, container vessel",
531
+ "511": "convertible",
532
+ "512": "corkscrew, bottle screw",
533
+ "513": "cornet, horn, trumpet, trump",
534
+ "514": "cowboy boot",
535
+ "515": "cowboy hat, ten-gallon hat",
536
+ "516": "cradle",
537
+ "517": "crane",
538
+ "518": "crash helmet",
539
+ "519": "crate",
540
+ "520": "crib, cot",
541
+ "521": "Crock Pot",
542
+ "522": "croquet ball",
543
+ "523": "crutch",
544
+ "524": "cuirass",
545
+ "525": "dam, dike, dyke",
546
+ "526": "desk",
547
+ "527": "desktop computer",
548
+ "528": "dial telephone, dial phone",
549
+ "529": "diaper, nappy, napkin",
550
+ "530": "digital clock",
551
+ "531": "digital watch",
552
+ "532": "dining table, board",
553
+ "533": "dishrag, dishcloth",
554
+ "534": "dishwasher, dish washer, dishwashing machine",
555
+ "535": "disk brake, disc brake",
556
+ "536": "dock, dockage, docking facility",
557
+ "537": "dogsled, dog sled, dog sleigh",
558
+ "538": "dome",
559
+ "539": "doormat, welcome mat",
560
+ "540": "drilling platform, offshore rig",
561
+ "541": "drum, membranophone, tympan",
562
+ "542": "drumstick",
563
+ "543": "dumbbell",
564
+ "544": "Dutch oven",
565
+ "545": "electric fan, blower",
566
+ "546": "electric guitar",
567
+ "547": "electric locomotive",
568
+ "548": "entertainment center",
569
+ "549": "envelope",
570
+ "550": "espresso maker",
571
+ "551": "face powder",
572
+ "552": "feather boa, boa",
573
+ "553": "file, file cabinet, filing cabinet",
574
+ "554": "fireboat",
575
+ "555": "fire engine, fire truck",
576
+ "556": "fire screen, fireguard",
577
+ "557": "flagpole, flagstaff",
578
+ "558": "flute, transverse flute",
579
+ "559": "folding chair",
580
+ "560": "football helmet",
581
+ "561": "forklift",
582
+ "562": "fountain",
583
+ "563": "fountain pen",
584
+ "564": "four-poster",
585
+ "565": "freight car",
586
+ "566": "French horn, horn",
587
+ "567": "frying pan, frypan, skillet",
588
+ "568": "fur coat",
589
+ "569": "garbage truck, dustcart",
590
+ "570": "gasmask, respirator, gas helmet",
591
+ "571": "gas pump, gasoline pump, petrol pump, island dispenser",
592
+ "572": "goblet",
593
+ "573": "go-kart",
594
+ "574": "golf ball",
595
+ "575": "golfcart, golf cart",
596
+ "576": "gondola",
597
+ "577": "gong, tam-tam",
598
+ "578": "gown",
599
+ "579": "grand piano, grand",
600
+ "580": "greenhouse, nursery, glasshouse",
601
+ "581": "grille, radiator grille",
602
+ "582": "grocery store, grocery, food market, market",
603
+ "583": "guillotine",
604
+ "584": "hair slide",
605
+ "585": "hair spray",
606
+ "586": "half track",
607
+ "587": "hammer",
608
+ "588": "hamper",
609
+ "589": "hand blower, blow dryer, blow drier, hair dryer, hair drier",
610
+ "590": "hand-held computer, hand-held microcomputer",
611
+ "591": "handkerchief, hankie, hanky, hankey",
612
+ "592": "hard disc, hard disk, fixed disk",
613
+ "593": "harmonica, mouth organ, harp, mouth harp",
614
+ "594": "harp",
615
+ "595": "harvester, reaper",
616
+ "596": "hatchet",
617
+ "597": "holster",
618
+ "598": "home theater, home theatre",
619
+ "599": "honeycomb",
620
+ "600": "hook, claw",
621
+ "601": "hoopskirt, crinoline",
622
+ "602": "horizontal bar, high bar",
623
+ "603": "horse cart, horse-cart",
624
+ "604": "hourglass",
625
+ "605": "iPod",
626
+ "606": "iron, smoothing iron",
627
+ "607": "jack-o-lantern",
628
+ "608": "jean, blue jean, denim",
629
+ "609": "jeep, landrover",
630
+ "610": "jersey, T-shirt, tee shirt",
631
+ "611": "jigsaw puzzle",
632
+ "612": "jinrikisha, ricksha, rickshaw",
633
+ "613": "joystick",
634
+ "614": "kimono",
635
+ "615": "knee pad",
636
+ "616": "knot",
637
+ "617": "lab coat, laboratory coat",
638
+ "618": "ladle",
639
+ "619": "lampshade, lamp shade",
640
+ "620": "laptop, laptop computer",
641
+ "621": "lawn mower, mower",
642
+ "622": "lens cap, lens cover",
643
+ "623": "letter opener, paper knife, paperknife",
644
+ "624": "library",
645
+ "625": "lifeboat",
646
+ "626": "lighter, light, igniter, ignitor",
647
+ "627": "limousine, limo",
648
+ "628": "liner, ocean liner",
649
+ "629": "lipstick, lip rouge",
650
+ "630": "Loafer",
651
+ "631": "lotion",
652
+ "632": "loudspeaker, speaker, speaker unit, loudspeaker system, speaker system",
653
+ "633": "loupe, jewelers loupe",
654
+ "634": "lumbermill, sawmill",
655
+ "635": "magnetic compass",
656
+ "636": "mailbag, postbag",
657
+ "637": "mailbox, letter box",
658
+ "638": "maillot",
659
+ "639": "maillot, tank suit",
660
+ "640": "manhole cover",
661
+ "641": "maraca",
662
+ "642": "marimba, xylophone",
663
+ "643": "mask",
664
+ "644": "matchstick",
665
+ "645": "maypole",
666
+ "646": "maze, labyrinth",
667
+ "647": "measuring cup",
668
+ "648": "medicine chest, medicine cabinet",
669
+ "649": "megalith, megalithic structure",
670
+ "650": "microphone, mike",
671
+ "651": "microwave, microwave oven",
672
+ "652": "military uniform",
673
+ "653": "milk can",
674
+ "654": "minibus",
675
+ "655": "miniskirt, mini",
676
+ "656": "minivan",
677
+ "657": "missile",
678
+ "658": "mitten",
679
+ "659": "mixing bowl",
680
+ "660": "mobile home, manufactured home",
681
+ "661": "Model T",
682
+ "662": "modem",
683
+ "663": "monastery",
684
+ "664": "monitor",
685
+ "665": "moped",
686
+ "666": "mortar",
687
+ "667": "mortarboard",
688
+ "668": "mosque",
689
+ "669": "mosquito net",
690
+ "670": "motor scooter, scooter",
691
+ "671": "mountain bike, all-terrain bike, off-roader",
692
+ "672": "mountain tent",
693
+ "673": "mouse, computer mouse",
694
+ "674": "mousetrap",
695
+ "675": "moving van",
696
+ "676": "muzzle",
697
+ "677": "nail",
698
+ "678": "neck brace",
699
+ "679": "necklace",
700
+ "680": "nipple",
701
+ "681": "notebook, notebook computer",
702
+ "682": "obelisk",
703
+ "683": "oboe, hautboy, hautbois",
704
+ "684": "ocarina, sweet potato",
705
+ "685": "odometer, hodometer, mileometer, milometer",
706
+ "686": "oil filter",
707
+ "687": "organ, pipe organ",
708
+ "688": "oscilloscope, scope, cathode-ray oscilloscope, CRO",
709
+ "689": "overskirt",
710
+ "690": "oxcart",
711
+ "691": "oxygen mask",
712
+ "692": "packet",
713
+ "693": "paddle, boat paddle",
714
+ "694": "paddlewheel, paddle wheel",
715
+ "695": "padlock",
716
+ "696": "paintbrush",
717
+ "697": "pajama, pyjama, pjs, jammies",
718
+ "698": "palace",
719
+ "699": "panpipe, pandean pipe, syrinx",
720
+ "700": "paper towel",
721
+ "701": "parachute, chute",
722
+ "702": "parallel bars, bars",
723
+ "703": "park bench",
724
+ "704": "parking meter",
725
+ "705": "passenger car, coach, carriage",
726
+ "706": "patio, terrace",
727
+ "707": "pay-phone, pay-station",
728
+ "708": "pedestal, plinth, footstall",
729
+ "709": "pencil box, pencil case",
730
+ "710": "pencil sharpener",
731
+ "711": "perfume, essence",
732
+ "712": "Petri dish",
733
+ "713": "photocopier",
734
+ "714": "pick, plectrum, plectron",
735
+ "715": "pickelhaube",
736
+ "716": "picket fence, paling",
737
+ "717": "pickup, pickup truck",
738
+ "718": "pier",
739
+ "719": "piggy bank, penny bank",
740
+ "720": "pill bottle",
741
+ "721": "pillow",
742
+ "722": "ping-pong ball",
743
+ "723": "pinwheel",
744
+ "724": "pirate, pirate ship",
745
+ "725": "pitcher, ewer",
746
+ "726": "plane, carpenters plane, woodworking plane",
747
+ "727": "planetarium",
748
+ "728": "plastic bag",
749
+ "729": "plate rack",
750
+ "730": "plow, plough",
751
+ "731": "plunger, plumbers helper",
752
+ "732": "Polaroid camera, Polaroid Land camera",
753
+ "733": "pole",
754
+ "734": "police van, police wagon, paddy wagon, patrol wagon, wagon, black Maria",
755
+ "735": "poncho",
756
+ "736": "pool table, billiard table, snooker table",
757
+ "737": "pop bottle, soda bottle",
758
+ "738": "pot, flowerpot",
759
+ "739": "potters wheel",
760
+ "740": "power drill",
761
+ "741": "prayer rug, prayer mat",
762
+ "742": "printer",
763
+ "743": "prison, prison house",
764
+ "744": "projectile, missile",
765
+ "745": "projector",
766
+ "746": "puck, hockey puck",
767
+ "747": "punching bag, punch bag, punching ball, punchball",
768
+ "748": "purse",
769
+ "749": "quill, quill pen",
770
+ "750": "quilt, comforter, comfort, puff",
771
+ "751": "racer, race car, racing car",
772
+ "752": "racket, racquet",
773
+ "753": "radiator",
774
+ "754": "radio, wireless",
775
+ "755": "radio telescope, radio reflector",
776
+ "756": "rain barrel",
777
+ "757": "recreational vehicle, RV, R.V.",
778
+ "758": "reel",
779
+ "759": "reflex camera",
780
+ "760": "refrigerator, icebox",
781
+ "761": "remote control, remote",
782
+ "762": "restaurant, eating house, eating place, eatery",
783
+ "763": "revolver, six-gun, six-shooter",
784
+ "764": "rifle",
785
+ "765": "rocking chair, rocker",
786
+ "766": "rotisserie",
787
+ "767": "rubber eraser, rubber, pencil eraser",
788
+ "768": "rugby ball",
789
+ "769": "rule, ruler",
790
+ "770": "running shoe",
791
+ "771": "safe",
792
+ "772": "safety pin",
793
+ "773": "saltshaker, salt shaker",
794
+ "774": "sandal",
795
+ "775": "sarong",
796
+ "776": "sax, saxophone",
797
+ "777": "scabbard",
798
+ "778": "scale, weighing machine",
799
+ "779": "school bus",
800
+ "780": "schooner",
801
+ "781": "scoreboard",
802
+ "782": "screen, CRT screen",
803
+ "783": "screw",
804
+ "784": "screwdriver",
805
+ "785": "seat belt, seatbelt",
806
+ "786": "sewing machine",
807
+ "787": "shield, buckler",
808
+ "788": "shoe shop, shoe-shop, shoe store",
809
+ "789": "shoji",
810
+ "790": "shopping basket",
811
+ "791": "shopping cart",
812
+ "792": "shovel",
813
+ "793": "shower cap",
814
+ "794": "shower curtain",
815
+ "795": "ski",
816
+ "796": "ski mask",
817
+ "797": "sleeping bag",
818
+ "798": "slide rule, slipstick",
819
+ "799": "sliding door",
820
+ "800": "slot, one-armed bandit",
821
+ "801": "snorkel",
822
+ "802": "snowmobile",
823
+ "803": "snowplow, snowplough",
824
+ "804": "soap dispenser",
825
+ "805": "soccer ball",
826
+ "806": "sock",
827
+ "807": "solar dish, solar collector, solar furnace",
828
+ "808": "sombrero",
829
+ "809": "soup bowl",
830
+ "810": "space bar",
831
+ "811": "space heater",
832
+ "812": "space shuttle",
833
+ "813": "spatula",
834
+ "814": "speedboat",
835
+ "815": "spider web, spiders web",
836
+ "816": "spindle",
837
+ "817": "sports car, sport car",
838
+ "818": "spotlight, spot",
839
+ "819": "stage",
840
+ "820": "steam locomotive",
841
+ "821": "steel arch bridge",
842
+ "822": "steel drum",
843
+ "823": "stethoscope",
844
+ "824": "stole",
845
+ "825": "stone wall",
846
+ "826": "stopwatch, stop watch",
847
+ "827": "stove",
848
+ "828": "strainer",
849
+ "829": "streetcar, tram, tramcar, trolley, trolley car",
850
+ "830": "stretcher",
851
+ "831": "studio couch, day bed",
852
+ "832": "stupa, tope",
853
+ "833": "submarine, pigboat, sub, U-boat",
854
+ "834": "suit, suit of clothes",
855
+ "835": "sundial",
856
+ "836": "sunglass",
857
+ "837": "sunglasses, dark glasses, shades",
858
+ "838": "sunscreen, sunblock, sun blocker",
859
+ "839": "suspension bridge",
860
+ "840": "swab, swob, mop",
861
+ "841": "sweatshirt",
862
+ "842": "swimming trunks, bathing trunks",
863
+ "843": "swing",
864
+ "844": "switch, electric switch, electrical switch",
865
+ "845": "syringe",
866
+ "846": "table lamp",
867
+ "847": "tank, army tank, armored combat vehicle, armoured combat vehicle",
868
+ "848": "tape player",
869
+ "849": "teapot",
870
+ "850": "teddy, teddy bear",
871
+ "851": "television, television system",
872
+ "852": "tennis ball",
873
+ "853": "thatch, thatched roof",
874
+ "854": "theater curtain, theatre curtain",
875
+ "855": "thimble",
876
+ "856": "thresher, thrasher, threshing machine",
877
+ "857": "throne",
878
+ "858": "tile roof",
879
+ "859": "toaster",
880
+ "860": "tobacco shop, tobacconist shop, tobacconist",
881
+ "861": "toilet seat",
882
+ "862": "torch",
883
+ "863": "totem pole",
884
+ "864": "tow truck, tow car, wrecker",
885
+ "865": "toyshop",
886
+ "866": "tractor",
887
+ "867": "trailer truck, tractor trailer, trucking rig, rig, articulated lorry, semi",
888
+ "868": "tray",
889
+ "869": "trench coat",
890
+ "870": "tricycle, trike, velocipede",
891
+ "871": "trimaran",
892
+ "872": "tripod",
893
+ "873": "triumphal arch",
894
+ "874": "trolleybus, trolley coach, trackless trolley",
895
+ "875": "trombone",
896
+ "876": "tub, vat",
897
+ "877": "turnstile",
898
+ "878": "typewriter keyboard",
899
+ "879": "umbrella",
900
+ "880": "unicycle, monocycle",
901
+ "881": "upright, upright piano",
902
+ "882": "vacuum, vacuum cleaner",
903
+ "883": "vase",
904
+ "884": "vault",
905
+ "885": "velvet",
906
+ "886": "vending machine",
907
+ "887": "vestment",
908
+ "888": "viaduct",
909
+ "889": "violin, fiddle",
910
+ "890": "volleyball",
911
+ "891": "waffle iron",
912
+ "892": "wall clock",
913
+ "893": "wallet, billfold, notecase, pocketbook",
914
+ "894": "wardrobe, closet, press",
915
+ "895": "warplane, military plane",
916
+ "896": "washbasin, handbasin, washbowl, lavabo, wash-hand basin",
917
+ "897": "washer, automatic washer, washing machine",
918
+ "898": "water bottle",
919
+ "899": "water jug",
920
+ "900": "water tower",
921
+ "901": "whiskey jug",
922
+ "902": "whistle",
923
+ "903": "wig",
924
+ "904": "window screen",
925
+ "905": "window shade",
926
+ "906": "Windsor tie",
927
+ "907": "wine bottle",
928
+ "908": "wing",
929
+ "909": "wok",
930
+ "910": "wooden spoon",
931
+ "911": "wool, woolen, woollen",
932
+ "912": "worm fence, snake fence, snake-rail fence, Virginia fence",
933
+ "913": "wreck",
934
+ "914": "yawl",
935
+ "915": "yurt",
936
+ "916": "web site, website, internet site, site",
937
+ "917": "comic book",
938
+ "918": "crossword puzzle, crossword",
939
+ "919": "street sign",
940
+ "920": "traffic light, traffic signal, stoplight",
941
+ "921": "book jacket, dust cover, dust jacket, dust wrapper",
942
+ "922": "menu",
943
+ "923": "plate",
944
+ "924": "guacamole",
945
+ "925": "consomme",
946
+ "926": "hot pot, hotpot",
947
+ "927": "trifle",
948
+ "928": "ice cream, icecream",
949
+ "929": "ice lolly, lolly, lollipop, popsicle",
950
+ "930": "French loaf",
951
+ "931": "bagel, beigel",
952
+ "932": "pretzel",
953
+ "933": "cheeseburger",
954
+ "934": "hotdog, hot dog, red hot",
955
+ "935": "mashed potato",
956
+ "936": "head cabbage",
957
+ "937": "broccoli",
958
+ "938": "cauliflower",
959
+ "939": "zucchini, courgette",
960
+ "940": "spaghetti squash",
961
+ "941": "acorn squash",
962
+ "942": "butternut squash",
963
+ "943": "cucumber, cuke",
964
+ "944": "artichoke, globe artichoke",
965
+ "945": "bell pepper",
966
+ "946": "cardoon",
967
+ "947": "mushroom",
968
+ "948": "Granny Smith",
969
+ "949": "strawberry",
970
+ "950": "orange",
971
+ "951": "lemon",
972
+ "952": "fig",
973
+ "953": "pineapple, ananas",
974
+ "954": "banana",
975
+ "955": "jackfruit, jak, jack",
976
+ "956": "custard apple",
977
+ "957": "pomegranate",
978
+ "958": "hay",
979
+ "959": "carbonara",
980
+ "960": "chocolate sauce, chocolate syrup",
981
+ "961": "dough",
982
+ "962": "meat loaf, meatloaf",
983
+ "963": "pizza, pizza pie",
984
+ "964": "potpie",
985
+ "965": "burrito",
986
+ "966": "red wine",
987
+ "967": "espresso",
988
+ "968": "cup",
989
+ "969": "eggnog",
990
+ "970": "alp",
991
+ "971": "bubble",
992
+ "972": "cliff, drop, drop-off",
993
+ "973": "coral reef",
994
+ "974": "geyser",
995
+ "975": "lakeside, lakeshore",
996
+ "976": "promontory, headland, head, foreland",
997
+ "977": "sandbar, sand bar",
998
+ "978": "seashore, coast, seacoast, sea-coast",
999
+ "979": "valley, vale",
1000
+ "980": "volcano",
1001
+ "981": "ballplayer, baseball player",
1002
+ "982": "groom, bridegroom",
1003
+ "983": "scuba diver",
1004
+ "984": "rapeseed",
1005
+ "985": "daisy",
1006
+ "986": "yellow ladys slipper, yellow lady-slipper, Cypripedium calceolus, Cypripedium parviflorum",
1007
+ "987": "corn",
1008
+ "988": "acorn",
1009
+ "989": "hip, rose hip, rosehip",
1010
+ "990": "buckeye, horse chestnut, conker",
1011
+ "991": "coral fungus",
1012
+ "992": "agaric",
1013
+ "993": "gyromitra",
1014
+ "994": "stinkhorn, carrion fungus",
1015
+ "995": "earthstar",
1016
+ "996": "hen-of-the-woods, hen of the woods, Polyporus frondosus, Grifola frondosa",
1017
+ "997": "bolete",
1018
+ "998": "ear, spike, capitulum",
1019
+ "999": "toilet tissue, toilet paper, bathroom tissue"
1020
+ }
1021
+ }
PixelDiT2-H-16-256/pipeline.py ADDED
@@ -0,0 +1,839 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2026 The HuggingFace Team. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import importlib.util
16
+ import inspect
17
+ import json
18
+ import sys
19
+ from pathlib import Path
20
+ from typing import Any, Callable
21
+
22
+ import torch
23
+ from diffusers.callbacks import MultiPipelineCallbacks, PipelineCallback
24
+ from transformers import DINOv3ViTModel
25
+ from diffusers.models.modeling_utils import ModelMixin
26
+ from diffusers.pipelines.pipeline_utils import DiffusionPipeline, ImagePipelineOutput
27
+ from diffusers.schedulers.scheduling_utils import SchedulerMixin
28
+ from diffusers.utils import deprecate, is_torch_xla_available, logging, replace_example_docstring
29
+ from diffusers.utils.torch_utils import randn_tensor
30
+ from PIL import Image
31
+
32
+ if is_torch_xla_available():
33
+ import torch_xla.core.xla_model as xm
34
+
35
+ XLA_AVAILABLE = True
36
+ else:
37
+ XLA_AVAILABLE = False
38
+
39
+ logger = logging.get_logger(__name__)
40
+
41
+ EXAMPLE_DOC_STRING = """
42
+ Examples:
43
+ ```py
44
+ >>> from pathlib import Path
45
+ >>> import torch
46
+ >>> from diffusers import DiffusionPipeline
47
+
48
+ >>> model_dir = Path("pixeldit2-diffusers/PixelDiT2-H-16-256").resolve()
49
+ >>> pipe = DiffusionPipeline.from_pretrained(
50
+ ... str(model_dir),
51
+ ... local_files_only=True,
52
+ ... custom_pipeline=str(model_dir / "pipeline.py"),
53
+ ... trust_remote_code=True,
54
+ ... torch_dtype=torch.bfloat16,
55
+ ... ).to("cuda:0")
56
+
57
+ >>> image = pipe(
58
+ ... class_labels="golden retriever",
59
+ ... num_inference_steps=50,
60
+ ... guidance_scale=2.4,
61
+ ... generator=torch.Generator(device="cuda:0").manual_seed(0),
62
+ ... ).images[0]
63
+ >>> image.save("sample.png")
64
+
65
+ >>> # Hugging Face Hub style model id: UserID/RepoID
66
+ >>> # RepoID is usually like "modelname-diffusers"
67
+ >>> # Example: "BiliSakura/PixelDiT2-diffusers" with subfolder "PixelDiT2-H-16-256"
68
+ ```
69
+ """
70
+
71
+
72
+ class PixelDiT2Pipeline(DiffusionPipeline):
73
+ r"""
74
+ Class-conditional image pipeline for PixelDiT2.
75
+
76
+ PixelDiT2 denoises directly in RGB pixel space (no VAE). The transformer predicts the clean
77
+ image `x0`. [`PixelDiT2Scheduler`] integrates that prediction on `linspace(0, 1, steps + 1)`:
78
+ Heun on every interval except the last, which is Euler. `solver="euler"` uses the same knots
79
+ with one evaluation per interval.
80
+
81
+ Classifier-free guidance mixes a grounded class-conditional forward with an ungrounded null-class
82
+ forward. Guidance is applied only while the flow time is strictly greater than
83
+ `guidance_interval_min` and strictly less than `guidance_interval_max`.
84
+
85
+ The pipeline inherits from [`DiffusionPipeline`]. Check the superclass documentation for the
86
+ generic methods (download, save, device placement, CPU offload).
87
+
88
+ Args:
89
+ transformer ([`ModelMixin`]):
90
+ PixelDiT2 denoiser (`PixelDiT2Transformer2DModel`) that predicts `x0` in pixel space.
91
+ scheduler ([`PixelDiT2Scheduler`]):
92
+ Flow scheduler. The paper setting is Heun, `t_eps=0.05`. Loaded from `scheduler/`.
93
+ encoder (`DINOv3ViTModel`, *optional*):
94
+ Original DINOv3 checkpoint shipped in `encoder/`. The 256px variant includes DINOv3-S/16.
95
+ Sampling uses the mapped copy stored inside the transformer, so this module is not called.
96
+ id2label (`dict[int, str]`, *optional*):
97
+ ImageNet class id to English label mapping. Values may contain comma-separated synonyms.
98
+ Loaded from `model_index.json` when omitted.
99
+
100
+ Sampling defaults are not pipeline config. When `__call__` omits them, they are read from
101
+ `transformer.config`: `default_num_inference_steps`, `guidance_scale`, `guidance_interval_min`,
102
+ `guidance_interval_max`, `noise_scale`, and `t_eps`. Missing transformer entries fall back to
103
+ 50 steps, CFG 2.4 on `(0.125, 0.9)`, `noise_scale` 1.0, and `t_eps` 0.05.
104
+ """
105
+
106
+ _optional_components = ["encoder"]
107
+ _callback_tensor_inputs = ["latents"]
108
+
109
+ def __init__(
110
+ self,
111
+ transformer: ModelMixin,
112
+ scheduler: SchedulerMixin,
113
+ encoder: DINOv3ViTModel | None = None,
114
+ id2label: dict[int, str] | dict[str, str] | None = None,
115
+ ):
116
+ super().__init__()
117
+ if scheduler is None:
118
+ scheduler = self._default_scheduler()
119
+
120
+ self.register_modules(transformer=transformer, scheduler=scheduler, encoder=encoder)
121
+ normalized_labels = self._normalize_id2label(id2label)
122
+ self.register_to_config(id2label={str(key): value for key, value in normalized_labels.items()})
123
+ self._id2label = normalized_labels
124
+ self.labels = self._build_label2id(self._id2label)
125
+ self._labels_loaded_from_model_index = bool(self._id2label)
126
+
127
+ def _sampling_default(self, name: str, fallback: float) -> float:
128
+ r"""
129
+ Read a sampling default from the transformer config.
130
+
131
+ Args:
132
+ name (`str`):
133
+ Key on `transformer.config`, such as `guidance_scale` or `noise_scale`.
134
+ fallback (`float`):
135
+ Value used when the transformer config does not define `name`.
136
+
137
+ Returns:
138
+ `float`: The configured value, or `fallback`.
139
+ """
140
+ value = getattr(self.transformer.config, name, None)
141
+ if value is None:
142
+ return fallback
143
+ return value
144
+
145
+ @staticmethod
146
+ def _default_scheduler() -> SchedulerMixin:
147
+ r"""
148
+ Build [`PixelDiT2Scheduler`] from the variant's scheduler module.
149
+
150
+ Returns:
151
+ [`PixelDiT2Scheduler`]: Heun on the paper linspace, `t_eps=0.05`.
152
+ """
153
+ module_path = Path(__file__).resolve().parent / "scheduler" / "scheduling_pixeldit2.py"
154
+ spec = importlib.util.spec_from_file_location("scheduling_pixeldit2", module_path)
155
+ if spec is None or spec.loader is None:
156
+ raise ImportError(f"Could not load the PixelDiT2 scheduler from {module_path}.")
157
+ module = importlib.util.module_from_spec(spec)
158
+ sys.modules["scheduling_pixeldit2"] = module
159
+ spec.loader.exec_module(module)
160
+ return module.PixelDiT2Scheduler()
161
+
162
+ def _ensure_labels_loaded(self) -> None:
163
+ r"""
164
+ Fill `id2label` from `model_index.json` when the constructor did not receive it.
165
+ """
166
+ if self._labels_loaded_from_model_index:
167
+ return
168
+ loaded = self._read_id2label_from_model_index(getattr(self.config, "_name_or_path", None))
169
+ if loaded:
170
+ self._id2label = loaded
171
+ self.labels = self._build_label2id(self._id2label)
172
+ self._labels_loaded_from_model_index = True
173
+
174
+ @staticmethod
175
+ def _normalize_id2label(id2label: dict[int, str] | dict[str, str] | None) -> dict[int, str]:
176
+ r"""
177
+ Cast label-map keys to integers.
178
+
179
+ Args:
180
+ id2label (`dict`, *optional*):
181
+ Class id to English label. Keys may be strings, which is how JSON stores them.
182
+
183
+ Returns:
184
+ `dict[int, str]`: Integer-keyed map. Empty when `id2label` is missing.
185
+ """
186
+ if not id2label:
187
+ return {}
188
+ return {int(key): value for key, value in id2label.items()}
189
+
190
+ @staticmethod
191
+ def _read_id2label_from_model_index(variant_path: str | None) -> dict[int, str]:
192
+ r"""
193
+ Read `id2label` from a local variant directory.
194
+
195
+ Args:
196
+ variant_path (`str`, *optional*):
197
+ Directory that contains `model_index.json`.
198
+
199
+ Returns:
200
+ `dict[int, str]`: Loaded map, or an empty dict when the file or key is absent.
201
+ """
202
+ if not variant_path:
203
+ return {}
204
+ model_index_path = Path(variant_path).resolve() / "model_index.json"
205
+ if not model_index_path.exists():
206
+ return {}
207
+ raw = json.loads(model_index_path.read_text(encoding="utf-8"))
208
+ id2label = raw.get("id2label")
209
+ if not isinstance(id2label, dict):
210
+ return {}
211
+ return {int(key): value for key, value in id2label.items()}
212
+
213
+ @staticmethod
214
+ def _build_label2id(id2label: dict[int, str]) -> dict[str, int]:
215
+ r"""
216
+ Invert `id2label`, splitting comma-separated synonyms.
217
+
218
+ Args:
219
+ id2label (`dict[int, str]`):
220
+ Class id to one or more English names.
221
+
222
+ Returns:
223
+ `dict[str, int]`: Synonym to class id, sorted by synonym.
224
+ """
225
+ label2id: dict[str, int] = {}
226
+ for class_id, value in id2label.items():
227
+ for synonym in value.split(","):
228
+ synonym = synonym.strip()
229
+ if synonym:
230
+ label2id[synonym] = int(class_id)
231
+ return dict(sorted(label2id.items()))
232
+
233
+ @property
234
+ def id2label(self) -> dict[int, str]:
235
+ r"""
236
+ ImageNet id to English label map.
237
+
238
+ Returns:
239
+ `dict[int, str]`: The map loaded from the constructor or `model_index.json`.
240
+ """
241
+ self._ensure_labels_loaded()
242
+ return self._id2label
243
+
244
+ def get_label_ids(self, label: str | list[str]) -> list[int]:
245
+ r"""
246
+ Map ImageNet English labels to class ids.
247
+
248
+ Args:
249
+ label (`str` or `list[str]`):
250
+ One label or a list of labels. Each string must match a synonym in `id2label`
251
+ after stripping whitespace. Synonyms are the comma-separated pieces of each value.
252
+
253
+ Returns:
254
+ `list[int]`: Class ids in the same order as `label`.
255
+ """
256
+ self._ensure_labels_loaded()
257
+ label2id = self.labels
258
+ if not label2id:
259
+ raise ValueError("No English labels loaded. Ensure `id2label` exists in model_index.json.")
260
+ if isinstance(label, str):
261
+ label = [label]
262
+ missing = [item for item in label if item not in label2id]
263
+ if missing:
264
+ preview = ", ".join(list(label2id.keys())[:8])
265
+ raise ValueError(f"Unknown English label(s): {missing}. Example valid labels: {preview}, ...")
266
+ return [label2id[item] for item in label]
267
+
268
+ def _normalize_class_labels(self, class_labels: int | str | list[int | str]) -> list[int]:
269
+ r"""
270
+ Turn a class-label argument into a list of integer ids.
271
+
272
+ Args:
273
+ class_labels (`int`, `str`, or `list`):
274
+ One id, one English label, or a list of either. A list must not mix types.
275
+
276
+ Returns:
277
+ `list[int]`: One id per requested image.
278
+ """
279
+ if isinstance(class_labels, int):
280
+ return [class_labels]
281
+ if isinstance(class_labels, str):
282
+ return self.get_label_ids(class_labels)
283
+ if len(class_labels) == 0:
284
+ raise ValueError("`class_labels` must contain at least one class id or label.")
285
+ if isinstance(class_labels[0], str):
286
+ if not all(isinstance(item, str) for item in class_labels):
287
+ raise TypeError("`class_labels` must be all strings or all integers.")
288
+ return self.get_label_ids(class_labels)
289
+ if not all(isinstance(item, int) for item in class_labels):
290
+ raise TypeError("`class_labels` must be all strings or all integers.")
291
+ return list(class_labels)
292
+
293
+ def prepare_extra_step_kwargs(
294
+ self,
295
+ generator: torch.Generator | list[torch.Generator] | None,
296
+ eta: float,
297
+ ) -> dict[str, Any]:
298
+ r"""
299
+ Extra arguments forwarded to `scheduler.step`, depending on what that method accepts.
300
+
301
+ Args:
302
+ generator (`torch.Generator` or `list[torch.Generator]`, *optional*):
303
+ Generator passed through when the scheduler step samples noise.
304
+ eta (`float`):
305
+ DDIM eta in `[0, 1]`. Ignored by schedulers whose `step` has no `eta` argument.
306
+
307
+ Returns:
308
+ `dict`: Keyword arguments for `scheduler.step`.
309
+ """
310
+ extra_step_kwargs: dict[str, Any] = {}
311
+ step_params = set(inspect.signature(self.scheduler.step).parameters.keys())
312
+ if "eta" in step_params:
313
+ extra_step_kwargs["eta"] = eta
314
+ if "generator" in step_params:
315
+ extra_step_kwargs["generator"] = generator
316
+ return extra_step_kwargs
317
+
318
+ def check_inputs(
319
+ self,
320
+ class_labels: int | str | list[int | str],
321
+ height: int,
322
+ width: int,
323
+ num_inference_steps: int,
324
+ guidance_scale: float,
325
+ guidance_interval_min: float,
326
+ guidance_interval_max: float,
327
+ noise_scale: float,
328
+ t_eps: float,
329
+ output_type: str,
330
+ callback_steps: int | None = None,
331
+ callback_on_step_end_tensor_inputs: list[str] | None = None,
332
+ ) -> None:
333
+ r"""
334
+ Reject arguments that the denoiser or the sampler cannot run.
335
+
336
+ Args:
337
+ class_labels (`int`, `str`, or `list`):
338
+ Class ids or English labels. A list must be non-empty.
339
+ height (`int`):
340
+ Output height in pixels. Must be positive and divisible by the patch size.
341
+ width (`int`):
342
+ Output width in pixels. Must be positive and divisible by the patch size.
343
+ num_inference_steps (`int`):
344
+ Number of integration intervals. Must be >= 1.
345
+ guidance_scale (`float`):
346
+ CFG scale. Must be finite.
347
+ guidance_interval_min (`float`):
348
+ Exclusive lower flow-time bound of CFG.
349
+ guidance_interval_max (`float`):
350
+ Exclusive upper flow-time bound of CFG. Must be greater than the minimum and at most 1.
351
+ noise_scale (`float`):
352
+ Initial Gaussian scale. Must be positive.
353
+ t_eps (`float`):
354
+ Velocity denominator floor. Must be positive.
355
+ output_type (`str`):
356
+ One of `"pil"`, `"np"`, `"pt"`, `"latent"`.
357
+ callback_steps (`int`, *optional*):
358
+ Deprecated callback period. When set, must be a positive integer.
359
+ callback_on_step_end_tensor_inputs (`list[str]`, *optional*):
360
+ Tensor names the step callback may read. Each name must be in `_callback_tensor_inputs`.
361
+ """
362
+ if isinstance(class_labels, list) and len(class_labels) == 0:
363
+ raise ValueError("`class_labels` must contain at least one class id or label.")
364
+ patch_size = int(self.transformer.config.patch_size)
365
+ if height <= 0 or width <= 0:
366
+ raise ValueError(f"`height` and `width` must be positive, got {(height, width)}.")
367
+ if height % patch_size != 0 or width % patch_size != 0:
368
+ raise ValueError(f"`height` and `width` must be divisible by patch_size={patch_size}. Got {(height, width)}.")
369
+ if num_inference_steps < 1:
370
+ raise ValueError(f"`num_inference_steps` must be >= 1, got {num_inference_steps}.")
371
+ if not torch.isfinite(torch.tensor(guidance_scale)):
372
+ raise ValueError(f"`guidance_scale` must be finite, got {guidance_scale}.")
373
+ if not 0.0 <= guidance_interval_min < guidance_interval_max <= 1.0:
374
+ raise ValueError(
375
+ "Guidance interval must satisfy 0 <= min < max <= 1, got "
376
+ f"[{guidance_interval_min}, {guidance_interval_max}]."
377
+ )
378
+ if noise_scale <= 0:
379
+ raise ValueError(f"`noise_scale` must be positive, got {noise_scale}.")
380
+ if t_eps <= 0:
381
+ raise ValueError(f"`t_eps` must be positive, got {t_eps}.")
382
+ if output_type not in {"pil", "np", "pt", "latent"}:
383
+ raise ValueError(f"Unsupported `output_type` {output_type!r}. Choose from 'pil', 'np', 'pt', 'latent'.")
384
+ if callback_steps is not None and (not isinstance(callback_steps, int) or callback_steps < 1):
385
+ raise ValueError(f"`callback_steps` must be a positive integer, got {callback_steps}.")
386
+ if callback_on_step_end_tensor_inputs is not None:
387
+ unknown = [name for name in callback_on_step_end_tensor_inputs if name not in self._callback_tensor_inputs]
388
+ if unknown:
389
+ raise ValueError(
390
+ f"`callback_on_step_end_tensor_inputs` contains {unknown}, which are not in "
391
+ f"{self._callback_tensor_inputs}."
392
+ )
393
+
394
+ def prepare_latents(
395
+ self,
396
+ batch_size: int,
397
+ num_channels: int,
398
+ height: int,
399
+ width: int,
400
+ dtype: torch.dtype,
401
+ device: torch.device,
402
+ generator: torch.Generator | list[torch.Generator] | None,
403
+ latents: torch.Tensor | None,
404
+ noise_scale: float,
405
+ ) -> torch.Tensor:
406
+ r"""
407
+ Sample the initial pixel-space noise, or validate a tensor the caller already sampled.
408
+
409
+ PixelDiT2 has no VAE, so these "latents" are RGB images. Fresh noise is multiplied by
410
+ `noise_scale`. A provided `latents` tensor is not rescaled.
411
+
412
+ Args:
413
+ batch_size (`int`):
414
+ Number of images.
415
+ num_channels (`int`):
416
+ Channel count. 3 for RGB.
417
+ height (`int`):
418
+ Image height in pixels.
419
+ width (`int`):
420
+ Image width in pixels.
421
+ dtype (`torch.dtype`):
422
+ Dtype of freshly sampled noise. The integration itself is accumulated in float32.
423
+ device (`torch.device`):
424
+ Device of the returned tensor.
425
+ generator (`torch.Generator` or `list[torch.Generator]`, *optional*):
426
+ Per-call RNG. A list must have length `batch_size`.
427
+ latents (`torch.Tensor`, *optional*):
428
+ Starting noise of shape `(batch_size, num_channels, height, width)`.
429
+ noise_scale (`float`):
430
+ Scale applied only when `latents` is `None`.
431
+
432
+ Returns:
433
+ `torch.Tensor`: Starting noise of shape `(batch_size, num_channels, height, width)`.
434
+ """
435
+ shape = (batch_size, num_channels, height, width)
436
+ if isinstance(generator, list) and len(generator) != batch_size:
437
+ raise ValueError(
438
+ f"You passed a list of {len(generator)} generators for a batch of {batch_size}. "
439
+ "The two lengths must match."
440
+ )
441
+ if latents is None:
442
+ latents = randn_tensor(shape, generator=generator, device=device, dtype=dtype)
443
+ latents = latents * float(noise_scale)
444
+ else:
445
+ latents = latents.to(device=device)
446
+ if tuple(latents.shape) != shape:
447
+ raise ValueError(f"`latents` shape {tuple(latents.shape)} does not match the expected {shape}.")
448
+ return latents
449
+
450
+ def _prepare_scheduler(
451
+ self,
452
+ num_inference_steps: int,
453
+ device: torch.device,
454
+ timesteps: list[float] | None,
455
+ sigmas: list[float] | None,
456
+ ) -> torch.Tensor:
457
+ r"""
458
+ Install the paper linspace on `self.scheduler` and return its flow times.
459
+
460
+ [`PixelDiT2Scheduler`] owns the grid. `timesteps` and `sigmas` are rejected. Use
461
+ `solver="euler"` for one model evaluation per interval.
462
+
463
+ Args:
464
+ num_inference_steps (`int`):
465
+ Number of flow-time intervals.
466
+ device (`torch.device`):
467
+ Device of the scheduler tensors.
468
+ timesteps (`list[float]`, *optional*):
469
+ Not used. The scheduler builds `linspace(0, 1, steps + 1)`.
470
+ sigmas (`list[float]`, *optional*):
471
+ Not used. PixelDiT2 integrates flow time, not a sigma schedule.
472
+
473
+ Returns:
474
+ `torch.Tensor`: Flow times at which the denoiser is evaluated, in `[0, 1]`.
475
+ """
476
+ if timesteps is not None or sigmas is not None:
477
+ raise ValueError(
478
+ "PixelDiT2Scheduler builds its own linspace and does not accept custom `timesteps` or "
479
+ '`sigmas`. Use PixelDiT2Scheduler(solver="euler") for one evaluation per step.'
480
+ )
481
+ self.scheduler.set_timesteps(num_inference_steps, device=device)
482
+ return self.scheduler.timesteps
483
+
484
+ def _predict_x0(
485
+ self,
486
+ latents: torch.Tensor,
487
+ flow_time: torch.Tensor,
488
+ class_labels: torch.Tensor,
489
+ skip_grounding: bool,
490
+ ) -> torch.Tensor:
491
+ r"""
492
+ Run the denoiser and return an x0 prediction in float32.
493
+
494
+ Args:
495
+ latents (`torch.Tensor`):
496
+ Current sample `(batch, channels, height, width)`.
497
+ flow_time (`torch.Tensor`):
498
+ Scalar flow time in `[0, 1]`, broadcast inside the denoiser.
499
+ class_labels (`torch.Tensor`):
500
+ Class ids `(batch,)`.
501
+ skip_grounding (`bool`):
502
+ When `True`, skip the DINOv3 encoder. Used for the unconditional branch.
503
+
504
+ Returns:
505
+ `torch.Tensor`: x0 prediction `(batch, channels, height, width)` in float32.
506
+ """
507
+ model_input = latents
508
+ parameter_dtype = self.transformer.dtype
509
+ device_type = model_input.device.type
510
+ use_amp = device_type in {"cuda", "xpu"} and parameter_dtype in (torch.float16, torch.bfloat16)
511
+ if not use_amp:
512
+ model_input = model_input.to(dtype=parameter_dtype)
513
+ timesteps = flow_time.to(device=model_input.device, dtype=parameter_dtype).expand(model_input.shape[0])
514
+ with torch.autocast(device_type if device_type != "mps" else "cpu", dtype=parameter_dtype, enabled=use_amp):
515
+ prediction = self.transformer(
516
+ model_input,
517
+ timestep=timesteps,
518
+ class_labels=class_labels,
519
+ skip_grounding=skip_grounding,
520
+ ).sample
521
+ return prediction.float()
522
+
523
+ def _guided_x0(
524
+ self,
525
+ latents: torch.Tensor,
526
+ flow_time: float,
527
+ class_labels: torch.Tensor,
528
+ class_null: torch.Tensor,
529
+ guidance_scale: float,
530
+ guidance_interval_min: float,
531
+ guidance_interval_max: float,
532
+ ) -> torch.Tensor:
533
+ r"""
534
+ Classifier-free guidance on x0, restricted to the paper's time interval.
535
+
536
+ Outside the interval the scale is 1, which is exactly the conditional prediction, so the
537
+ ungrounded forward is skipped.
538
+
539
+ Args:
540
+ latents (`torch.Tensor`):
541
+ Current sample.
542
+ flow_time (`float`):
543
+ Scalar flow time of this evaluation.
544
+ class_labels (`torch.Tensor`):
545
+ Conditional class ids.
546
+ class_null (`torch.Tensor`):
547
+ Null class ids, one per batch row.
548
+ guidance_scale (`float`):
549
+ CFG scale used inside the interval.
550
+ guidance_interval_min (`float`):
551
+ Exclusive lower bound.
552
+ guidance_interval_max (`float`):
553
+ Exclusive upper bound.
554
+
555
+ Returns:
556
+ `torch.Tensor`: Guided x0, same shape as `latents`, in float32.
557
+ """
558
+ flow = torch.tensor(flow_time, device=latents.device, dtype=torch.float32)
559
+ conditional = self._predict_x0(latents, flow, class_labels, skip_grounding=False)
560
+ inside = guidance_interval_min < flow_time < guidance_interval_max
561
+ if guidance_scale == 1.0 or not inside:
562
+ return conditional
563
+ unconditional = self._predict_x0(latents, flow, class_null, skip_grounding=True)
564
+ return unconditional + guidance_scale * (conditional - unconditional)
565
+
566
+ @property
567
+ def guidance_scale(self) -> float:
568
+ r"""
569
+ Classifier-free guidance scale of the call that is currently running.
570
+
571
+ Returns:
572
+ `float`: The scale set by the active `__call__`.
573
+ """
574
+ return self._guidance_scale
575
+
576
+ @property
577
+ def do_classifier_free_guidance(self) -> bool:
578
+ r"""
579
+ Whether the active call can run an unconditional forward.
580
+
581
+ The unconditional forward is still skipped at timesteps outside the guidance interval.
582
+
583
+ Returns:
584
+ `bool`: True when `guidance_scale > 1`.
585
+ """
586
+ return self._guidance_scale > 1.0
587
+
588
+ @property
589
+ def num_timesteps(self) -> int:
590
+ r"""
591
+ Number of scheduler timesteps in the active call.
592
+
593
+ Returns:
594
+ `int`: Length of the timestep schedule, including Heun's repeated states.
595
+ """
596
+ return self._num_timesteps
597
+
598
+ @property
599
+ def interrupt(self) -> bool:
600
+ r"""
601
+ Whether the active denoising loop should skip remaining steps.
602
+
603
+ Returns:
604
+ `bool`: True after the caller sets `pipeline._interrupt = True`.
605
+ """
606
+ return self._interrupt
607
+
608
+ def _images_from_latents(self, latents: torch.Tensor, output_type: str) -> torch.Tensor | list[Image.Image]:
609
+ r"""
610
+ Convert pixel-space samples to the requested output type.
611
+
612
+ Quantization matches the original sampler: `uint8(clip((x + 1) * 127.5 + 0.5, 0, 255))`.
613
+
614
+ Args:
615
+ latents (`torch.Tensor`):
616
+ Samples of shape `(batch, channels, height, width)` in model range around `[-1, 1]`.
617
+ output_type (`str`):
618
+ `"latent"` returns `latents` unchanged. `"pt"` is float RGB in `[0, 1]` after that
619
+ quantization. `"np"` is `uint8` HWC arrays. `"pil"` is a list of `PIL.Image.Image`.
620
+
621
+ Returns:
622
+ Images in the requested type.
623
+ """
624
+ if output_type == "latent":
625
+ return latents
626
+ images = torch.clamp((latents.float() + 1.0) * 127.5 + 0.5, 0, 255).to(torch.uint8)
627
+ if output_type == "pt":
628
+ return images.float() / 255.0
629
+ arrays = images.permute(0, 2, 3, 1).cpu().numpy()
630
+ if output_type == "np":
631
+ return arrays
632
+ return [Image.fromarray(image) for image in arrays]
633
+
634
+ @torch.no_grad()
635
+ @replace_example_docstring(EXAMPLE_DOC_STRING)
636
+ def __call__(
637
+ self,
638
+ class_labels: int | str | list[int | str],
639
+ height: int | None = None,
640
+ width: int | None = None,
641
+ num_inference_steps: int | None = None,
642
+ timesteps: list[float] | None = None,
643
+ sigmas: list[float] | None = None,
644
+ guidance_scale: float | None = None,
645
+ guidance_interval_min: float | None = None,
646
+ guidance_interval_max: float | None = None,
647
+ noise_scale: float | None = None,
648
+ t_eps: float | None = None,
649
+ eta: float = 0.0,
650
+ generator: torch.Generator | list[torch.Generator] | None = None,
651
+ latents: torch.Tensor | None = None,
652
+ output_type: str = "pil",
653
+ return_dict: bool = True,
654
+ callback_on_step_end: Callable[[int, int, dict], dict] | PipelineCallback | MultiPipelineCallbacks | None = None,
655
+ callback_on_step_end_tensor_inputs: list[str] | None = None,
656
+ **kwargs,
657
+ ) -> ImagePipelineOutput | tuple:
658
+ r"""
659
+ Generate images from ImageNet class labels.
660
+
661
+ Args:
662
+ class_labels (`int`, `str`, or `list`):
663
+ One ImageNet class id, one English label, or a list of either. English labels are
664
+ resolved with [`get_label_ids`]. The list length is the batch size.
665
+ height (`int`, *optional*):
666
+ Image height in pixels. Defaults to `transformer.config.sample_size`. Must be
667
+ divisible by the patch size. Other sizes recompute rotary positions for that grid.
668
+ width (`int`, *optional*):
669
+ Image width in pixels. Defaults to `transformer.config.sample_size`.
670
+ num_inference_steps (`int`, *optional*):
671
+ Denoising intervals. Defaults to `transformer.config.default_num_inference_steps` (50).
672
+ timesteps (`list[float]`, *optional*):
673
+ Not accepted. [`PixelDiT2Scheduler`] builds `linspace(0, 1, steps + 1)`.
674
+ sigmas (`list[float]`, *optional*):
675
+ Not accepted. PixelDiT2 integrates flow time. Use `solver="euler"` for one evaluation per step.
676
+ guidance_scale (`float`, *optional*):
677
+ Classifier-free guidance scale. Defaults to `transformer.config.guidance_scale`.
678
+ Guidance is on when this is greater than 1 and the flow time is inside the interval.
679
+ guidance_interval_min (`float`, *optional*):
680
+ Exclusive lower flow-time bound. Defaults to `transformer.config.guidance_interval_min`.
681
+ guidance_interval_max (`float`, *optional*):
682
+ Exclusive upper flow-time bound. Defaults to `transformer.config.guidance_interval_max`.
683
+ noise_scale (`float`, *optional*):
684
+ Initial noise scale. Defaults to `transformer.config.noise_scale`. Ignored when `latents` is passed.
685
+ t_eps (`float`, *optional*):
686
+ Floor of the velocity denominator `1 - t`. Defaults to `transformer.config.t_eps` (0.05).
687
+ eta (`float`, defaults to 0.0):
688
+ DDIM eta. Ignored by [`PixelDiT2Scheduler`].
689
+ generator (`torch.Generator` or `list[torch.Generator]`, *optional*):
690
+ RNG for the initial noise.
691
+ latents (`torch.Tensor`, *optional*):
692
+ Initial noise `(batch, 3, height, width)`. Not multiplied by `noise_scale`.
693
+ output_type (`str`, defaults to `"pil"`):
694
+ `"pil"`, `"np"`, `"pt"` (float RGB in `[0, 1]`), or `"latent"` (pixels in model range).
695
+ return_dict (`bool`, defaults to `True`):
696
+ Return [`ImagePipelineOutput`] when `True`, otherwise a one-tuple of images.
697
+ callback_on_step_end (`Callable` or `PipelineCallback`, *optional*):
698
+ Called as `callback_on_step_end(pipeline, step, timestep, callback_kwargs)` after each
699
+ scheduler step. Return a dict to replace tensors listed in
700
+ `callback_on_step_end_tensor_inputs`.
701
+ callback_on_step_end_tensor_inputs (`list[str]`, *optional*):
702
+ Tensor names passed to the step callback. Defaults to `["latents"]`.
703
+
704
+ Examples:
705
+
706
+ Returns:
707
+ [`ImagePipelineOutput`] or `tuple`:
708
+ When `return_dict` is `True`, [`ImagePipelineOutput`] with the images. Otherwise a tuple
709
+ whose first element is the images.
710
+ """
711
+ callback = kwargs.pop("callback", None)
712
+ callback_steps = kwargs.pop("callback_steps", None)
713
+ if kwargs:
714
+ raise TypeError(f"Unexpected arguments: {sorted(kwargs)}.")
715
+ if callback_on_step_end_tensor_inputs is None:
716
+ callback_on_step_end_tensor_inputs = ["latents"]
717
+
718
+ if callback is not None:
719
+ deprecate(
720
+ "callback",
721
+ "1.0.0",
722
+ "Passing `callback` as an input argument to `__call__` is deprecated, consider using `callback_on_step_end`",
723
+ )
724
+ if callback_steps is not None:
725
+ deprecate(
726
+ "callback_steps",
727
+ "1.0.0",
728
+ "Passing `callback_steps` as an input argument to `__call__` is deprecated, consider using `callback_on_step_end`",
729
+ )
730
+ if isinstance(callback_on_step_end, (PipelineCallback, MultiPipelineCallbacks)):
731
+ callback_on_step_end_tensor_inputs = callback_on_step_end.tensor_inputs
732
+
733
+ image_size = int(self.transformer.config.sample_size)
734
+ height = image_size if height is None else int(height)
735
+ width = image_size if width is None else int(width)
736
+ if num_inference_steps is None:
737
+ num_inference_steps = int(self._sampling_default("default_num_inference_steps", 50))
738
+ if guidance_scale is None:
739
+ guidance_scale = float(self._sampling_default("guidance_scale", 2.4))
740
+ if guidance_interval_min is None:
741
+ guidance_interval_min = float(self._sampling_default("guidance_interval_min", 0.125))
742
+ if guidance_interval_max is None:
743
+ guidance_interval_max = float(self._sampling_default("guidance_interval_max", 0.9))
744
+ if noise_scale is None:
745
+ noise_scale = float(self._sampling_default("noise_scale", 1.0))
746
+ if t_eps is None:
747
+ t_eps = float(self._sampling_default("t_eps", 0.05))
748
+
749
+ # 1. Check inputs.
750
+ self.check_inputs(
751
+ class_labels,
752
+ height,
753
+ width,
754
+ num_inference_steps,
755
+ guidance_scale,
756
+ guidance_interval_min,
757
+ guidance_interval_max,
758
+ noise_scale,
759
+ t_eps,
760
+ output_type,
761
+ callback_steps,
762
+ callback_on_step_end_tensor_inputs,
763
+ )
764
+
765
+ self._guidance_scale = float(guidance_scale)
766
+ self._interrupt = False
767
+
768
+ # 2. Define call parameters.
769
+ class_label_ids = self._normalize_class_labels(class_labels)
770
+ batch_size = len(class_label_ids)
771
+ device = self._execution_device
772
+ null_class = int(self.transformer.config.num_classes)
773
+ class_labels_t = torch.tensor(class_label_ids, device=device, dtype=torch.long)
774
+ if torch.any(class_labels_t < 0) or torch.any(class_labels_t > null_class):
775
+ raise ValueError(f"Class ids must lie in [0, {null_class}], got {class_label_ids}.")
776
+ class_null = torch.full_like(class_labels_t, null_class)
777
+
778
+ # 3. Encode input condition (class ids are already the condition; nothing else is encoded).
779
+
780
+ # 4. Prepare timesteps.
781
+ scheduled_timesteps = self._prepare_scheduler(num_inference_steps, device, timesteps, sigmas)
782
+
783
+ # 5. Prepare latent variables (pixel-space noise; there is no VAE).
784
+ latents = self.prepare_latents(
785
+ batch_size,
786
+ int(self.transformer.config.in_channels),
787
+ height,
788
+ width,
789
+ torch.float32,
790
+ device,
791
+ generator,
792
+ latents,
793
+ noise_scale,
794
+ ).float()
795
+
796
+ # 6. Prepare extra step kwargs.
797
+ extra_step_kwargs = self.prepare_extra_step_kwargs(generator, eta)
798
+ num_warmup_steps = len(scheduled_timesteps) - num_inference_steps * self.scheduler.order
799
+ self._num_timesteps = len(scheduled_timesteps)
800
+
801
+ # 7. Denoising loop.
802
+ with self.progress_bar(total=num_inference_steps) as progress_bar:
803
+ for i, timestep in enumerate(scheduled_timesteps):
804
+ if self.interrupt:
805
+ continue
806
+
807
+ flow_time = float(timestep.to(dtype=torch.float32).reshape(-1)[0])
808
+ x0 = self._guided_x0(
809
+ latents,
810
+ flow_time,
811
+ class_labels_t,
812
+ class_null,
813
+ self.guidance_scale,
814
+ guidance_interval_min,
815
+ guidance_interval_max,
816
+ )
817
+ latents = self.scheduler.step(
818
+ x0, timestep, latents, t_eps=t_eps, **extra_step_kwargs, return_dict=False
819
+ )[0]
820
+
821
+ if callback_on_step_end is not None:
822
+ callback_kwargs = {key: locals()[key] for key in callback_on_step_end_tensor_inputs}
823
+ callback_outputs = callback_on_step_end(self, i, timestep, callback_kwargs)
824
+ latents = callback_outputs.pop("latents", latents)
825
+
826
+ if i == len(scheduled_timesteps) - 1 or ((i + 1) > num_warmup_steps and (i + 1) % self.scheduler.order == 0):
827
+ progress_bar.update()
828
+ if callback is not None and i % callback_steps == 0:
829
+ callback(i, timestep, latents)
830
+
831
+ if XLA_AVAILABLE:
832
+ xm.mark_step()
833
+
834
+ images = self._images_from_latents(latents, output_type)
835
+ self.maybe_free_model_hooks()
836
+
837
+ if not return_dict:
838
+ return (images,)
839
+ return ImagePipelineOutput(images=images)
PixelDiT2-H-16-256/scheduler/scheduler_config.json ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_class_name": "PixelDiT2Scheduler",
3
+ "_diffusers_version": "0.39.0",
4
+ "num_train_timesteps": 1000,
5
+ "prediction_type": "sample",
6
+ "solver": "heun",
7
+ "t_eps": 0.05
8
+ }
PixelDiT2-H-16-256/scheduler/scheduling_pixeldit2.py ADDED
@@ -0,0 +1,216 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """PixelDiT2 flow scheduler.
2
+
3
+ Time runs from 0 (noise) to 1 (data). The transformer predicts the clean sample x0.
4
+ Velocity is `(x0 - x) / max(1 - t, t_eps)`. Heun is used on every interval except the
5
+ last, which is Euler. This matches `GroundedHeunSampler` rather than the sigma grid
6
+ inside `FlowMatchHeunDiscreteScheduler`.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from dataclasses import dataclass
12
+ from typing import Optional, Union
13
+
14
+ import torch
15
+ from diffusers.configuration_utils import ConfigMixin, register_to_config
16
+ from diffusers.schedulers.scheduling_utils import SchedulerMixin
17
+ from diffusers.utils import BaseOutput
18
+
19
+
20
+ @dataclass
21
+ class PixelDiT2SchedulerOutput(BaseOutput):
22
+ prev_sample: torch.Tensor
23
+
24
+
25
+ class PixelDiT2Scheduler(SchedulerMixin, ConfigMixin):
26
+ """Uniform flow-time scheduler for PixelDiT2.
27
+
28
+ `solver="heun"` evaluates the model twice on each interval except the last.
29
+ `solver="euler"` evaluates it once per interval on the same linspace.
30
+ """
31
+
32
+ config_name = "scheduler_config.json"
33
+ _compatibles: list[str] = []
34
+ order = 2
35
+
36
+ @register_to_config
37
+ def __init__(
38
+ self,
39
+ num_train_timesteps: int = 1000,
40
+ solver: str = "heun",
41
+ prediction_type: str = "sample",
42
+ t_eps: float = 0.05,
43
+ ):
44
+ if solver not in {"heun", "euler"}:
45
+ raise ValueError(f'`solver` must be "heun" or "euler", got {solver}.')
46
+ if prediction_type not in {"sample", "velocity"}:
47
+ raise ValueError(f'`prediction_type` must be "sample" or "velocity", got {prediction_type}.')
48
+ if num_train_timesteps < 1:
49
+ raise ValueError(f"`num_train_timesteps` must be >= 1, got {num_train_timesteps}.")
50
+ if t_eps <= 0:
51
+ raise ValueError(f"`t_eps` must be positive, got {t_eps}.")
52
+
53
+ self.timesteps: Optional[torch.Tensor] = None
54
+ self.schedule: Optional[torch.Tensor] = None
55
+ self.num_inference_steps: Optional[int] = None
56
+ self._step_plan: list[dict] = []
57
+ self._step_index: Optional[int] = None
58
+ self._begin_index: Optional[int] = None
59
+ self._heun_sample: Optional[torch.Tensor] = None
60
+ self._heun_velocity: Optional[torch.Tensor] = None
61
+
62
+ @property
63
+ def init_noise_sigma(self) -> float:
64
+ return 1.0
65
+
66
+ @property
67
+ def step_index(self) -> Optional[int]:
68
+ return self._step_index
69
+
70
+ @property
71
+ def begin_index(self) -> Optional[int]:
72
+ return self._begin_index
73
+
74
+ def set_begin_index(self, begin_index: int = 0) -> None:
75
+ self._begin_index = int(begin_index)
76
+
77
+ def set_timesteps(
78
+ self,
79
+ num_inference_steps: int,
80
+ device: Union[str, torch.device, None] = None,
81
+ **kwargs,
82
+ ) -> None:
83
+ """Install `linspace(0, 1, steps + 1)` and the Heun or Euler step plan.
84
+
85
+ Args:
86
+ num_inference_steps (`int`):
87
+ Number of intervals from noise to data.
88
+ device (`str` or `torch.device`, *optional*):
89
+ Device of `timesteps`.
90
+ """
91
+ if kwargs:
92
+ raise ValueError(f"PixelDiT2Scheduler.set_timesteps does not accept {sorted(kwargs)}.")
93
+ if num_inference_steps < 1:
94
+ raise ValueError(f"`num_inference_steps` must be >= 1, got {num_inference_steps}.")
95
+
96
+ knots = torch.linspace(0.0, 1.0, num_inference_steps + 1, device=device, dtype=torch.float32)
97
+ plan: list[dict] = []
98
+ use_heun = self.config.solver == "heun" and num_inference_steps > 1
99
+ if use_heun:
100
+ for index in range(num_inference_steps - 1):
101
+ current = float(knots[index])
102
+ nxt = float(knots[index + 1])
103
+ plan.append({"kind": "heun_predict", "t_model": current, "t_cur": current, "t_next": nxt})
104
+ plan.append({"kind": "heun_correct", "t_model": nxt, "t_cur": current, "t_next": nxt})
105
+ last = num_inference_steps - 1
106
+ plan.append(
107
+ {
108
+ "kind": "euler",
109
+ "t_model": float(knots[last]),
110
+ "t_cur": float(knots[last]),
111
+ "t_next": float(knots[last + 1]),
112
+ }
113
+ )
114
+ else:
115
+ for index in range(num_inference_steps):
116
+ plan.append(
117
+ {
118
+ "kind": "euler",
119
+ "t_model": float(knots[index]),
120
+ "t_cur": float(knots[index]),
121
+ "t_next": float(knots[index + 1]),
122
+ }
123
+ )
124
+
125
+ self.num_inference_steps = int(num_inference_steps)
126
+ self.schedule = knots
127
+ self._step_plan = plan
128
+ self.timesteps = torch.tensor([item["t_model"] for item in plan], device=device, dtype=torch.float32)
129
+ self.order = 2 if use_heun else 1
130
+ self._step_index = 0 if self._begin_index is None else self._begin_index
131
+ self._heun_sample = None
132
+ self._heun_velocity = None
133
+
134
+ def scale_model_input(self, sample: torch.Tensor, timestep: Union[float, torch.Tensor]) -> torch.Tensor:
135
+ del timestep
136
+ return sample
137
+
138
+ def _velocity(
139
+ self,
140
+ sample: torch.Tensor,
141
+ model_output: torch.Tensor,
142
+ flow_time: float,
143
+ t_eps: float,
144
+ ) -> torch.Tensor:
145
+ if self.config.prediction_type == "velocity":
146
+ return model_output.float()
147
+ denominator = max(1.0 - float(flow_time), float(t_eps))
148
+ return (model_output.float() - sample.float()) / denominator
149
+
150
+ def step(
151
+ self,
152
+ model_output: torch.Tensor,
153
+ timestep: Union[float, torch.Tensor],
154
+ sample: torch.Tensor,
155
+ return_dict: bool = True,
156
+ generator: Optional[Union[torch.Generator, list[torch.Generator]]] = None,
157
+ t_eps: Optional[float] = None,
158
+ ) -> Union[PixelDiT2SchedulerOutput, tuple]:
159
+ """Advance one planned step.
160
+
161
+ Args:
162
+ model_output (`torch.Tensor`):
163
+ x0 prediction when `prediction_type` is `"sample"`.
164
+ timestep (`float` or `torch.Tensor`):
165
+ Flow time at which `model_output` was evaluated. The step plan is the
166
+ source of the update; this value is checked against that plan.
167
+ sample (`torch.Tensor`):
168
+ Current sample. For a Heun corrector this is the predictor state.
169
+ return_dict (`bool`, defaults to `True`):
170
+ Return [`PixelDiT2SchedulerOutput`] when `True`.
171
+ generator (`torch.Generator`, *optional*):
172
+ Unused. The integrator is deterministic.
173
+ t_eps (`float`, *optional*):
174
+ Floor on `1 - t`. Defaults to the scheduler config.
175
+
176
+ Returns:
177
+ [`PixelDiT2SchedulerOutput`] or `tuple`:
178
+ The updated sample in float32.
179
+ """
180
+ del generator
181
+ if not self._step_plan or self._step_index is None:
182
+ raise ValueError("Call `set_timesteps` before `step`.")
183
+ if self._step_index >= len(self._step_plan):
184
+ raise ValueError("PixelDiT2Scheduler has already reached the final timestep.")
185
+
186
+ plan = self._step_plan[self._step_index]
187
+ sample = sample.to(dtype=torch.float32)
188
+ floor = float(self.config.t_eps if t_eps is None else t_eps)
189
+ if floor <= 0:
190
+ raise ValueError(f"`t_eps` must be positive, got {floor}.")
191
+ velocity = self._velocity(sample, model_output, plan["t_model"], floor)
192
+ dt = plan["t_next"] - plan["t_cur"]
193
+
194
+ kind = plan["kind"]
195
+ if kind == "heun_predict":
196
+ self._heun_sample = sample
197
+ self._heun_velocity = velocity
198
+ prev_sample = sample + dt * velocity
199
+ elif kind == "heun_correct":
200
+ if self._heun_sample is None or self._heun_velocity is None:
201
+ raise RuntimeError("Heun corrector was called before its predictor.")
202
+ prev_sample = self._heun_sample + dt * 0.5 * (self._heun_velocity + velocity)
203
+ self._heun_sample = None
204
+ self._heun_velocity = None
205
+ else:
206
+ prev_sample = sample + dt * velocity
207
+ self._heun_sample = None
208
+ self._heun_velocity = None
209
+
210
+ self._step_index += 1
211
+ if not return_dict:
212
+ return (prev_sample,)
213
+ return PixelDiT2SchedulerOutput(prev_sample=prev_sample)
214
+
215
+ def __len__(self) -> int:
216
+ return int(self.config.num_train_timesteps)
PixelDiT2-H-16-256/transformer/config.json ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_class_name": "PixelDiT2Transformer2DModel",
3
+ "_diffusers_version": "0.39.0",
4
+ "attn_dropout": 0.0,
5
+ "default_num_inference_steps": 50,
6
+ "depth": 32,
7
+ "grounding_encoder": "dinov3_vits16",
8
+ "grounding_proj_blocks": 1,
9
+ "grounding_proj_heads": 16,
10
+ "guidance_interval_max": 0.9,
11
+ "guidance_interval_min": 0.125,
12
+ "guidance_scale": 2.4,
13
+ "hidden_size": 1280,
14
+ "in_channels": 3,
15
+ "in_context_len": 32,
16
+ "in_context_start": 8,
17
+ "mlp_hidden_multiple": 0,
18
+ "noise_scale": 1.0,
19
+ "num_classes": 1000,
20
+ "num_heads": 16,
21
+ "patch_size": 16,
22
+ "proj_dropout": 0.2,
23
+ "sample_size": 256,
24
+ "single_silu_cond": false,
25
+ "t_eps": 0.05
26
+ }
PixelDiT2-H-16-256/transformer/diffusion_pytorch_model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a5d43740198ec13c90c0c678701018c7d55c22b6e4d9ee4865143366ab34904d
3
+ size 2015645984
PixelDiT2-H-16-256/transformer/transformer_pixeldit2.py ADDED
@@ -0,0 +1,1094 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2026 The HuggingFace Team. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """PixelDiT2 denoiser as a diffusers transformer.
16
+
17
+ PixelDiT2 predicts the clean image x0 directly in RGB pixel space. A frozen
18
+ DINOv3 encoder grounds every patch token; the unconditional branch of
19
+ classifier-free guidance skips that encoder (`skip_grounding=True`) and uses
20
+ the null class id `num_classes`.
21
+ """
22
+
23
+ from __future__ import annotations
24
+
25
+ import math
26
+ from dataclasses import dataclass
27
+
28
+ import timm
29
+ import torch
30
+ import torch.nn.functional as F
31
+ from diffusers.configuration_utils import ConfigMixin, register_to_config
32
+ from diffusers.models.modeling_outputs import Transformer2DModelOutput
33
+ from diffusers.models.modeling_utils import ModelMixin
34
+ from torch import nn
35
+
36
+
37
+ @dataclass(frozen=True)
38
+ class EncoderSpec:
39
+ r"""
40
+ Frozen grounding encoder used by PixelDiT2.
41
+
42
+ Args:
43
+ timm_name (`str`):
44
+ `timm` model id, including the pretrained tag when one exists.
45
+ feature_dim (`int`):
46
+ Channel count of the encoder patch tokens.
47
+ patch_size (`int`):
48
+ Encoder patch size in pixels.
49
+ """
50
+
51
+ timm_name: str
52
+ feature_dim: int
53
+ patch_size: int
54
+
55
+
56
+ GROUNDING_ENCODERS: dict[str, EncoderSpec] = {
57
+ "dinov3_vits16": EncoderSpec("vit_small_patch16_dinov3_qkvb.lvd1689m", 384, 16),
58
+ "dinov3_vitb16": EncoderSpec("vit_base_patch16_dinov3_qkvb.lvd1689m", 768, 16),
59
+ "dinov3_vitl16": EncoderSpec("vit_large_patch16_dinov3_qkvb.lvd1689m", 1024, 16),
60
+ }
61
+
62
+ IMAGENET_MEAN = (0.485, 0.456, 0.406)
63
+ IMAGENET_STD = (0.229, 0.224, 0.225)
64
+
65
+
66
+ def apply_adaln(hidden_states: torch.Tensor, shift: torch.Tensor, scale: torch.Tensor) -> torch.Tensor:
67
+ r"""
68
+ Apply adaptive layer-norm modulation.
69
+
70
+ Args:
71
+ hidden_states (`torch.Tensor`):
72
+ Token states of shape `(batch, tokens, hidden)`.
73
+ shift (`torch.Tensor`):
74
+ Shift term broadcastable to `hidden_states`.
75
+ scale (`torch.Tensor`):
76
+ Scale term broadcastable to `hidden_states`. The applied factor is `1 + scale`.
77
+
78
+ Returns:
79
+ `torch.Tensor`: Modulated tokens, same shape as `hidden_states`.
80
+ """
81
+ return hidden_states * (1 + scale) + shift
82
+
83
+
84
+ def precompute_freqs_cis_2d(
85
+ dim: int,
86
+ height: int,
87
+ width: int,
88
+ theta: float = 10000.0,
89
+ scale: float = 16.0,
90
+ ) -> torch.Tensor:
91
+ r"""
92
+ Build 2D rotary frequencies for a patch grid.
93
+
94
+ Positions are `linspace(0, scale, length)` on each axis, matching the PixelDiT2 training code.
95
+ A different grid size recomputes the table, which is how non-native resolutions are handled.
96
+
97
+ Args:
98
+ dim (`int`):
99
+ Head dimension. Must be divisible by 4.
100
+ height (`int`):
101
+ Grid height in patches.
102
+ width (`int`):
103
+ Grid width in patches.
104
+ theta (`float`, defaults to 10000.0):
105
+ RoPE base period.
106
+ scale (`float`, defaults to 16.0):
107
+ Coordinate of the last patch on each axis.
108
+
109
+ Returns:
110
+ `torch.Tensor`: Complex frequencies of shape `(height * width, dim / 2)`.
111
+ """
112
+ x_pos = torch.linspace(0, scale, width)
113
+ y_pos = torch.linspace(0, scale, height)
114
+ y_pos, x_pos = torch.meshgrid(y_pos, x_pos, indexing="ij")
115
+ y_pos = y_pos.reshape(-1)
116
+ x_pos = x_pos.reshape(-1)
117
+ freqs = 1.0 / (theta ** (torch.arange(0, dim, 4)[: (dim // 4)].float() / dim))
118
+ x_freqs = torch.outer(x_pos, freqs).float()
119
+ y_freqs = torch.outer(y_pos, freqs).float()
120
+ x_cis = torch.polar(torch.ones_like(x_freqs), x_freqs)
121
+ y_cis = torch.polar(torch.ones_like(y_freqs), y_freqs)
122
+ freqs_cis = torch.cat([x_cis.unsqueeze(dim=-1), y_cis.unsqueeze(dim=-1)], dim=-1)
123
+ return freqs_cis.reshape(height * width, -1)
124
+
125
+
126
+ def apply_rotary_emb(
127
+ query: torch.Tensor,
128
+ key: torch.Tensor,
129
+ freqs_cis: torch.Tensor,
130
+ ) -> tuple[torch.Tensor, torch.Tensor]:
131
+ r"""
132
+ Apply rotary embeddings to query and key.
133
+
134
+ Args:
135
+ query (`torch.Tensor`):
136
+ Queries of shape `(batch, tokens, heads, head_dim)`.
137
+ key (`torch.Tensor`):
138
+ Keys of shape `(batch, tokens, heads, head_dim)`.
139
+ freqs_cis (`torch.Tensor`):
140
+ Complex frequencies of shape `(tokens, head_dim / 2)`.
141
+
142
+ Returns:
143
+ `tuple[torch.Tensor, torch.Tensor]`: Rotated query and key, same shapes as the inputs.
144
+ """
145
+ freqs_cis = freqs_cis[None, :, None, :]
146
+ query_complex = torch.view_as_complex(query.float().reshape(*query.shape[:-1], -1, 2))
147
+ key_complex = torch.view_as_complex(key.float().reshape(*key.shape[:-1], -1, 2))
148
+ query_out = torch.view_as_real(query_complex * freqs_cis).flatten(3)
149
+ key_out = torch.view_as_real(key_complex * freqs_cis).flatten(3)
150
+ return query_out.type_as(query), key_out.type_as(key)
151
+
152
+
153
+ class TimestepConditioner(nn.Module):
154
+ r"""
155
+ Sinusoidal timestep embedding followed by a two-layer MLP.
156
+
157
+ PixelDiT2 uses `max_period=10`, not the more common 10000.
158
+
159
+ Args:
160
+ hidden_size (`int`):
161
+ Width of the MLP output.
162
+ frequency_embedding_size (`int`, defaults to 256):
163
+ Width of the sinusoidal embedding.
164
+ """
165
+
166
+ def __init__(self, hidden_size: int, frequency_embedding_size: int = 256):
167
+ super().__init__()
168
+ self.mlp = nn.Sequential(
169
+ nn.Linear(frequency_embedding_size, hidden_size, bias=True),
170
+ nn.SiLU(),
171
+ nn.Linear(hidden_size, hidden_size, bias=True),
172
+ )
173
+ self.frequency_embedding_size = frequency_embedding_size
174
+
175
+ @staticmethod
176
+ def timestep_embedding(timesteps: torch.Tensor, dim: int, max_period: int = 10) -> torch.Tensor:
177
+ r"""
178
+ Build a sinusoidal embedding of scalar timesteps.
179
+
180
+ Args:
181
+ timesteps (`torch.Tensor`):
182
+ Timesteps of shape `(batch,)`.
183
+ dim (`int`):
184
+ Embedding width.
185
+ max_period (`int`, defaults to 10):
186
+ Maximum period of the sinusoid.
187
+
188
+ Returns:
189
+ `torch.Tensor`: Embeddings of shape `(batch, dim)`.
190
+ """
191
+ half = dim // 2
192
+ freqs = torch.exp(
193
+ -math.log(max_period) * torch.arange(start=0, end=half, dtype=torch.float32, device=timesteps.device) / half
194
+ )
195
+ args = timesteps[..., None].float() * freqs[None, ...]
196
+ embedding = torch.cat([torch.cos(args), torch.sin(args)], dim=-1)
197
+ if dim % 2:
198
+ embedding = torch.cat([embedding, torch.zeros_like(embedding[:, :1])], dim=-1)
199
+ return embedding
200
+
201
+ def forward(self, timesteps: torch.Tensor) -> torch.Tensor:
202
+ r"""
203
+ Embed timesteps.
204
+
205
+ Args:
206
+ timesteps (`torch.Tensor`):
207
+ Flow time `t` of shape `(batch,)`, in `[0, 1]`.
208
+
209
+ Returns:
210
+ `torch.Tensor`: Embeddings of shape `(batch, hidden_size)`.
211
+ """
212
+ timestep_freq = self.timestep_embedding(timesteps, self.frequency_embedding_size)
213
+ mlp_dtype = self.mlp[0].weight.dtype
214
+ if timestep_freq.dtype != mlp_dtype:
215
+ timestep_freq = timestep_freq.to(mlp_dtype)
216
+ return self.mlp(timestep_freq)
217
+
218
+
219
+ class ClassEmbedder(nn.Module):
220
+ r"""
221
+ Embedding table for ImageNet class ids, including the null class.
222
+
223
+ Args:
224
+ num_classes (`int`):
225
+ Number of rows. PixelDiT2 uses `num_classes + 1` so index `num_classes` is unconditional.
226
+ hidden_size (`int`):
227
+ Embedding width.
228
+ """
229
+
230
+ def __init__(self, num_classes: int, hidden_size: int):
231
+ super().__init__()
232
+ self.embedding_table = nn.Embedding(num_classes, hidden_size)
233
+ self.num_classes = num_classes
234
+
235
+ def forward(self, labels: torch.Tensor) -> torch.Tensor:
236
+ r"""
237
+ Look up class embeddings.
238
+
239
+ Args:
240
+ labels (`torch.Tensor`):
241
+ Integer class ids of shape `(batch,)`.
242
+
243
+ Returns:
244
+ `torch.Tensor`: Embeddings of shape `(batch, hidden_size)`.
245
+ """
246
+ return self.embedding_table(labels)
247
+
248
+
249
+ class RMSNorm(nn.Module):
250
+ r"""
251
+ Root-mean-square normalization.
252
+
253
+ Args:
254
+ hidden_size (`int`):
255
+ Channel width.
256
+ eps (`float`, defaults to 1e-6):
257
+ Numerical stability term.
258
+ """
259
+
260
+ def __init__(self, hidden_size: int, eps: float = 1e-6):
261
+ super().__init__()
262
+ self.weight = nn.Parameter(torch.ones(hidden_size))
263
+ self.variance_epsilon = eps
264
+
265
+ def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
266
+ r"""
267
+ Normalize the last dimension.
268
+
269
+ Args:
270
+ hidden_states (`torch.Tensor`):
271
+ Input of shape `(..., hidden_size)`.
272
+
273
+ Returns:
274
+ `torch.Tensor`: Normalized tensor, same shape as the input.
275
+ """
276
+ input_dtype = hidden_states.dtype
277
+ hidden_states = hidden_states.to(torch.float32)
278
+ variance = hidden_states.pow(2).mean(-1, keepdim=True)
279
+ hidden_states = hidden_states * torch.rsqrt(variance + self.variance_epsilon)
280
+ return self.weight * hidden_states.to(input_dtype)
281
+
282
+
283
+ class FeedForward(nn.Module):
284
+ r"""
285
+ SwiGLU feed-forward block.
286
+
287
+ Args:
288
+ dim (`int`):
289
+ Input and output width.
290
+ hidden_dim (`int`):
291
+ Width before the SwiGLU 2/3 reduction. The inner width is `int(2 * hidden_dim / 3)`,
292
+ then rounded up to `hidden_multiple` when that value is positive.
293
+ drop (`float`, defaults to 0.0):
294
+ Dropout on the hidden activation. Disabled by `eval()`.
295
+ hidden_multiple (`int`, defaults to 0):
296
+ Round the inner width up to a multiple of this value. `0` disables rounding.
297
+ The 512px PixelDiT2 checkpoint uses 32.
298
+ """
299
+
300
+ def __init__(self, dim: int, hidden_dim: int, drop: float = 0.0, hidden_multiple: int = 0):
301
+ super().__init__()
302
+ hidden_dim = int(2 * hidden_dim / 3)
303
+ hidden_multiple = int(hidden_multiple)
304
+ if hidden_multiple > 0:
305
+ hidden_dim = ((hidden_dim + hidden_multiple - 1) // hidden_multiple) * hidden_multiple
306
+ self.w1 = nn.Linear(dim, hidden_dim, bias=False)
307
+ self.w3 = nn.Linear(dim, hidden_dim, bias=False)
308
+ self.w2 = nn.Linear(hidden_dim, dim, bias=False)
309
+ self.ffn_dropout = nn.Dropout(drop)
310
+
311
+ def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
312
+ r"""
313
+ Apply SwiGLU.
314
+
315
+ Args:
316
+ hidden_states (`torch.Tensor`):
317
+ Tokens of shape `(..., dim)`.
318
+
319
+ Returns:
320
+ `torch.Tensor`: Tokens of shape `(..., dim)`.
321
+ """
322
+ hidden = F.silu(self.w1(hidden_states)) * self.w3(hidden_states)
323
+ return self.w2(self.ffn_dropout(hidden))
324
+
325
+
326
+ class RotaryAttention(nn.Module):
327
+ r"""
328
+ Multi-head self-attention with QK RMSNorm and 2D rotary embeddings.
329
+
330
+ Args:
331
+ dim (`int`):
332
+ Token width. Must be divisible by `num_heads`.
333
+ num_heads (`int`, defaults to 8):
334
+ Number of attention heads.
335
+ qkv_bias (`bool`, defaults to `False`):
336
+ Whether the fused QKV projection has a bias. PixelDiT2 checkpoints use `False`.
337
+ qk_norm (`bool`, defaults to `True`):
338
+ Apply RMSNorm to query and key per head.
339
+ attn_drop (`float`, defaults to 0.0):
340
+ Attention dropout. The released models use 0.
341
+ proj_drop (`float`, defaults to 0.0):
342
+ Dropout after the output projection.
343
+ """
344
+
345
+ def __init__(
346
+ self,
347
+ dim: int,
348
+ num_heads: int = 8,
349
+ qkv_bias: bool = False,
350
+ qk_norm: bool = True,
351
+ attn_drop: float = 0.0,
352
+ proj_drop: float = 0.0,
353
+ ):
354
+ super().__init__()
355
+ if dim % num_heads != 0:
356
+ raise ValueError(f"dim={dim} must be divisible by num_heads={num_heads}.")
357
+ self.dim = dim
358
+ self.num_heads = num_heads
359
+ self.head_dim = dim // num_heads
360
+ self.qkv = nn.Linear(dim, dim * 3, bias=qkv_bias)
361
+ self.q_norm = RMSNorm(self.head_dim) if qk_norm else nn.Identity()
362
+ self.k_norm = RMSNorm(self.head_dim) if qk_norm else nn.Identity()
363
+ self.attn_drop = nn.Dropout(attn_drop)
364
+ self.proj = nn.Linear(dim, dim)
365
+ self.proj_drop = nn.Dropout(proj_drop)
366
+
367
+ def forward(self, hidden_states: torch.Tensor, pos: torch.Tensor, mask: torch.Tensor | None = None) -> torch.Tensor:
368
+ r"""
369
+ Run self-attention.
370
+
371
+ Args:
372
+ hidden_states (`torch.Tensor`):
373
+ Tokens of shape `(batch, tokens, dim)`.
374
+ pos (`torch.Tensor`):
375
+ Complex RoPE table of shape `(tokens, head_dim / 2)`.
376
+ mask (`torch.Tensor`, *optional*):
377
+ Attention mask forwarded to scaled-dot-product attention. `None` attends to every token.
378
+
379
+ Returns:
380
+ `torch.Tensor`: Tokens of shape `(batch, tokens, dim)`.
381
+ """
382
+ batch, tokens, channels = hidden_states.shape
383
+ qkv = self.qkv(hidden_states).reshape(batch, tokens, 3, self.num_heads, channels // self.num_heads)
384
+ qkv = qkv.permute(2, 0, 1, 3, 4)
385
+ query, key, value = qkv[0], qkv[1], qkv[2]
386
+ query = self.q_norm(query)
387
+ key = self.k_norm(key)
388
+ query, key = apply_rotary_emb(query, key, freqs_cis=pos)
389
+ query = query.view(batch, -1, self.num_heads, channels // self.num_heads).transpose(1, 2)
390
+ key = key.view(batch, -1, self.num_heads, channels // self.num_heads).transpose(1, 2).contiguous()
391
+ value = value.view(batch, -1, self.num_heads, channels // self.num_heads).transpose(1, 2).contiguous()
392
+ # The training forward always uses dropout_p=0 and ignores `attn_drop`.
393
+ hidden_states = F.scaled_dot_product_attention(query, key, value, attn_mask=mask, dropout_p=0.0)
394
+ hidden_states = hidden_states.transpose(1, 2).reshape(batch, tokens, channels)
395
+ hidden_states = self.proj(hidden_states)
396
+ hidden_states = self.proj_drop(hidden_states)
397
+ return hidden_states
398
+
399
+
400
+ class PatchTokenEmbedder(nn.Module):
401
+ r"""
402
+ Linear embedding of flattened pixel patches.
403
+
404
+ Args:
405
+ in_channels (`int`):
406
+ Flattened patch width, `in_channels * patch_size ** 2` at the call site.
407
+ embed_dim (`int`):
408
+ Token width.
409
+ bias (`bool`, defaults to `True`):
410
+ Bias on the linear projection. PixelDiT2 uses `True`.
411
+ """
412
+
413
+ def __init__(self, in_channels: int, embed_dim: int, bias: bool = True):
414
+ super().__init__()
415
+ self.in_channels = in_channels
416
+ self.embed_dim = embed_dim
417
+ self.proj = nn.Linear(in_channels, embed_dim, bias=bias)
418
+ self.norm = nn.Identity()
419
+
420
+ def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
421
+ r"""
422
+ Embed patch tokens.
423
+
424
+ Args:
425
+ hidden_states (`torch.Tensor`):
426
+ Flattened patches of shape `(batch, tokens, in_channels)`.
427
+
428
+ Returns:
429
+ `torch.Tensor`: Tokens of shape `(batch, tokens, embed_dim)`.
430
+ """
431
+ return self.norm(self.proj(hidden_states))
432
+
433
+
434
+ class ModulatedDiTBlock(nn.Module):
435
+ r"""
436
+ AdaLN-Zero transformer block with rotary attention and SwiGLU.
437
+
438
+ Args:
439
+ hidden_size (`int`):
440
+ Token width.
441
+ num_heads (`int`):
442
+ Attention heads.
443
+ mlp_ratio (`float`, defaults to 4.0):
444
+ MLP expansion before the SwiGLU 2/3 reduction.
445
+ attn_drop (`float`, defaults to 0.0):
446
+ Attention dropout.
447
+ proj_drop (`float`, defaults to 0.0):
448
+ Dropout on the attention projection and the MLP.
449
+ mlp_hidden_multiple (`int`, defaults to 0):
450
+ Forwarded to [`FeedForward`].
451
+ """
452
+
453
+ def __init__(
454
+ self,
455
+ hidden_size: int,
456
+ num_heads: int,
457
+ mlp_ratio: float = 4.0,
458
+ attn_drop: float = 0.0,
459
+ proj_drop: float = 0.0,
460
+ mlp_hidden_multiple: int = 0,
461
+ ):
462
+ super().__init__()
463
+ self.norm1 = RMSNorm(hidden_size, eps=1e-6)
464
+ self.attn = RotaryAttention(
465
+ hidden_size,
466
+ num_heads=num_heads,
467
+ qkv_bias=False,
468
+ attn_drop=attn_drop,
469
+ proj_drop=proj_drop,
470
+ )
471
+ self.norm2 = RMSNorm(hidden_size, eps=1e-6)
472
+ self.mlp = FeedForward(
473
+ hidden_size,
474
+ int(hidden_size * mlp_ratio),
475
+ drop=proj_drop,
476
+ hidden_multiple=mlp_hidden_multiple,
477
+ )
478
+ self.adaLN_modulation = nn.Sequential(
479
+ nn.SiLU(),
480
+ nn.Linear(hidden_size, 6 * hidden_size, bias=True),
481
+ )
482
+
483
+ def forward(
484
+ self,
485
+ hidden_states: torch.Tensor,
486
+ conditioning: torch.Tensor,
487
+ pos: torch.Tensor,
488
+ mask: torch.Tensor | None = None,
489
+ ) -> torch.Tensor:
490
+ r"""
491
+ Run one modulated block.
492
+
493
+ Args:
494
+ hidden_states (`torch.Tensor`):
495
+ Tokens of shape `(batch, tokens, hidden)`.
496
+ conditioning (`torch.Tensor`):
497
+ AdaLN conditioning of shape `(batch, tokens, hidden)` or `(batch, 1, hidden)`.
498
+ pos (`torch.Tensor`):
499
+ RoPE table aligned with `tokens`.
500
+ mask (`torch.Tensor`, *optional*):
501
+ Attention mask. `None` uses full attention.
502
+
503
+ Returns:
504
+ `torch.Tensor`: Tokens of shape `(batch, tokens, hidden)`.
505
+ """
506
+ shift_msa, scale_msa, gate_msa, shift_mlp, scale_mlp, gate_mlp = self.adaLN_modulation(conditioning).chunk(6, dim=-1)
507
+ hidden_states = hidden_states + gate_msa * self.attn(
508
+ apply_adaln(self.norm1(hidden_states), shift_msa, scale_msa), pos, mask=mask
509
+ )
510
+ hidden_states = hidden_states + gate_mlp * self.mlp(apply_adaln(self.norm2(hidden_states), shift_mlp, scale_mlp))
511
+ return hidden_states
512
+
513
+
514
+ class PatchFinalLayer(nn.Module):
515
+ r"""
516
+ AdaLN-modulated projection from tokens back to pixel patches.
517
+
518
+ Args:
519
+ hidden_size (`int`):
520
+ Token width.
521
+ patch_size (`int`):
522
+ Spatial patch size.
523
+ out_channels (`int`):
524
+ Image channels, 3 for RGB.
525
+ """
526
+
527
+ def __init__(self, hidden_size: int, patch_size: int, out_channels: int):
528
+ super().__init__()
529
+ self.norm = RMSNorm(hidden_size, eps=1e-6)
530
+ self.linear = nn.Linear(hidden_size, patch_size * patch_size * out_channels, bias=True)
531
+ self.adaLN_modulation = nn.Sequential(
532
+ nn.SiLU(),
533
+ nn.Linear(hidden_size, 2 * hidden_size, bias=True),
534
+ )
535
+
536
+ def forward(self, hidden_states: torch.Tensor, conditioning: torch.Tensor) -> torch.Tensor:
537
+ r"""
538
+ Project tokens to flattened patches.
539
+
540
+ Args:
541
+ hidden_states (`torch.Tensor`):
542
+ Tokens of shape `(batch, patches, hidden)`.
543
+ conditioning (`torch.Tensor`):
544
+ Conditioning of shape `(batch, patches, hidden)`. A 2D tensor is unsqueezed.
545
+
546
+ Returns:
547
+ `torch.Tensor`: Patch pixels of shape `(batch, patches, patch_size ** 2 * out_channels)`.
548
+ """
549
+ shift, scale = self.adaLN_modulation(conditioning).chunk(2, dim=-1)
550
+ if shift.dim() == 2:
551
+ shift = shift.unsqueeze(1)
552
+ scale = scale.unsqueeze(1)
553
+ return self.linear(apply_adaln(self.norm(hidden_states), shift, scale))
554
+
555
+
556
+ class TimestepProjection(nn.Module):
557
+ r"""
558
+ Projects DINOv3 tokens into the denoiser width with timestep modulation.
559
+
560
+ Args:
561
+ in_dim (`int`):
562
+ Encoder feature width.
563
+ out_dim (`int`):
564
+ Denoiser hidden size.
565
+ hidden_size (`int`):
566
+ Width of the internal transformer blocks. PixelDiT2 uses the denoiser width.
567
+ num_blocks (`int`, defaults to 1):
568
+ Number of modulated blocks. Released checkpoints use 1.
569
+ num_heads (`int`, defaults to 16):
570
+ Heads inside those blocks. `hidden_size` must be divisible by this value.
571
+ mlp_ratio (`float`, defaults to 4.0):
572
+ MLP expansion of the internal blocks.
573
+ """
574
+
575
+ def __init__(
576
+ self,
577
+ in_dim: int,
578
+ out_dim: int,
579
+ hidden_size: int,
580
+ num_blocks: int = 1,
581
+ num_heads: int = 16,
582
+ mlp_ratio: float = 4.0,
583
+ ):
584
+ super().__init__()
585
+ if hidden_size % num_heads != 0:
586
+ raise ValueError(f"TimestepProjection hidden_size={hidden_size} must be divisible by num_heads={num_heads}.")
587
+ self.head_dim = hidden_size // num_heads
588
+ self.input_proj = nn.Linear(in_dim, hidden_size, bias=True)
589
+ self.t_embedder = TimestepConditioner(hidden_size)
590
+ self.blocks = nn.ModuleList(
591
+ [ModulatedDiTBlock(hidden_size, num_heads, mlp_ratio=mlp_ratio) for _ in range(num_blocks)]
592
+ )
593
+ self.output_proj = nn.Linear(hidden_size, out_dim, bias=True)
594
+ for block in self.blocks:
595
+ nn.init.zeros_(block.adaLN_modulation[-1].weight)
596
+ nn.init.zeros_(block.adaLN_modulation[-1].bias)
597
+ self._pos_cache: dict[tuple[int, int], torch.Tensor] = {}
598
+
599
+ def fetch_pos(self, height: int, width: int, device: torch.device) -> torch.Tensor:
600
+ r"""
601
+ Return cached RoPE frequencies for a patch grid.
602
+
603
+ Args:
604
+ height (`int`):
605
+ Grid height in patches.
606
+ width (`int`):
607
+ Grid width in patches.
608
+ device (`torch.device`):
609
+ Device of the returned table.
610
+
611
+ Returns:
612
+ `torch.Tensor`: Complex frequencies of shape `(height * width, head_dim / 2)`.
613
+ """
614
+ key = (height, width)
615
+ if key not in self._pos_cache:
616
+ self._pos_cache[key] = precompute_freqs_cis_2d(self.head_dim, height, width)
617
+ return self._pos_cache[key].to(device)
618
+
619
+ def forward(self, tokens: torch.Tensor, timesteps: torch.Tensor, grid_hw: tuple[int, int]) -> torch.Tensor:
620
+ r"""
621
+ Project grounding tokens.
622
+
623
+ Args:
624
+ tokens (`torch.Tensor`):
625
+ Encoder tokens of shape `(batch, patches, in_dim)`.
626
+ timesteps (`torch.Tensor`):
627
+ Flow time of shape `(batch,)`.
628
+ grid_hw (`tuple[int, int]`):
629
+ `(height, width)` of the token grid in patches.
630
+
631
+ Returns:
632
+ `torch.Tensor`: Tokens of shape `(batch, patches, out_dim)`.
633
+ """
634
+ hidden_states = self.input_proj(tokens)
635
+ conditioning = self.t_embedder(timesteps).unsqueeze(1).to(dtype=hidden_states.dtype)
636
+ pos = self.fetch_pos(grid_hw[0], grid_hw[1], hidden_states.device)
637
+ for block in self.blocks:
638
+ hidden_states = block(hidden_states, conditioning, pos)
639
+ return self.output_proj(hidden_states)
640
+
641
+
642
+ class GroundingConditioner(nn.Module):
643
+ r"""
644
+ Frozen DINOv3 encoder plus the trainable projection `P_g`.
645
+
646
+ The encoder is built with `pretrained=False`. Conversion copies either the
647
+ checkpoint's encoder tensors or a `timm` pretrained checkpoint into this module
648
+ so inference does not download weights.
649
+
650
+ Args:
651
+ encoder_name (`str`):
652
+ Key of [`GROUNDING_ENCODERS`], for example `dinov3_vits16`.
653
+ hidden_size (`int`):
654
+ Denoiser width.
655
+ target_patch_size (`int`):
656
+ Denoiser patch size. The encoder grid is resized to this patch grid.
657
+ proj_num_blocks (`int`, defaults to 1):
658
+ Blocks inside the projection.
659
+ proj_num_heads (`int`, defaults to 16):
660
+ Heads inside the projection.
661
+ """
662
+
663
+ def __init__(
664
+ self,
665
+ encoder_name: str,
666
+ hidden_size: int,
667
+ target_patch_size: int,
668
+ proj_num_blocks: int = 1,
669
+ proj_num_heads: int = 16,
670
+ ):
671
+ super().__init__()
672
+ if encoder_name not in GROUNDING_ENCODERS:
673
+ raise ValueError(f"Unknown grounding encoder {encoder_name!r}. Available: {sorted(GROUNDING_ENCODERS)}.")
674
+ self.spec = GROUNDING_ENCODERS[encoder_name]
675
+ self.encoder_name = encoder_name
676
+ self.target_patch_size = int(target_patch_size)
677
+ self.encoder = timm.create_model(self.spec.timm_name, pretrained=False, dynamic_img_size=True)
678
+ self.encoder.requires_grad_(False)
679
+ self.dino_proj = TimestepProjection(
680
+ in_dim=self.spec.feature_dim,
681
+ out_dim=hidden_size,
682
+ hidden_size=hidden_size,
683
+ num_blocks=proj_num_blocks,
684
+ num_heads=proj_num_heads,
685
+ )
686
+ self.register_buffer("image_mean", torch.tensor(IMAGENET_MEAN).view(1, 3, 1, 1), persistent=False)
687
+ self.register_buffer("image_std", torch.tensor(IMAGENET_STD).view(1, 3, 1, 1), persistent=False)
688
+
689
+ def train(self, mode: bool = True) -> "GroundingConditioner":
690
+ r"""
691
+ Keep the frozen encoder in eval mode.
692
+
693
+ Args:
694
+ mode (`bool`, defaults to `True`):
695
+ Whether the projection should train.
696
+
697
+ Returns:
698
+ `GroundingConditioner`: This module.
699
+ """
700
+ super().train(mode)
701
+ self.encoder.eval()
702
+ return self
703
+
704
+ def preprocess(self, hidden_states: torch.Tensor) -> tuple[torch.Tensor, tuple[int, int]]:
705
+ r"""
706
+ Map pixels from `[-1, 1]` to the encoder's ImageNet normalization.
707
+
708
+ Args:
709
+ hidden_states (`torch.Tensor`):
710
+ Images of shape `(batch, 3, height, width)` in model range `[-1, 1]`.
711
+
712
+ Returns:
713
+ `tuple[torch.Tensor, tuple[int, int]]`:
714
+ Normalized encoder input and the denoiser patch grid `(grid_h, grid_w)`.
715
+ """
716
+ height, width = hidden_states.shape[-2:]
717
+ grid_hw = (height // self.target_patch_size, width // self.target_patch_size)
718
+ encoder_hw = (grid_hw[0] * self.spec.patch_size, grid_hw[1] * self.spec.patch_size)
719
+ hidden_states = (hidden_states + 1.0) * 0.5
720
+ hidden_states = (hidden_states - self.image_mean.to(hidden_states.dtype)) / self.image_std.to(hidden_states.dtype)
721
+ if encoder_hw != (height, width):
722
+ hidden_states = F.interpolate(hidden_states, size=encoder_hw, mode="bicubic", align_corners=False)
723
+ return hidden_states, grid_hw
724
+
725
+ def _zero_key_bias(self) -> None:
726
+ """Keep DINOv3 key bias at zero.
727
+
728
+ timm's qkvb attention stores a zero key bias as a non-persistent buffer, so it
729
+ is absent from the checkpoint. `from_pretrained` builds the encoder on the meta
730
+ device and materializes missing buffers as uninitialized memory. A non-zero key
731
+ bias makes attention NaN.
732
+ """
733
+ for module in self.encoder.modules():
734
+ bias = getattr(module, "k_bias", None)
735
+ if isinstance(bias, torch.Tensor) and bias.device.type != "meta":
736
+ bias.zero_()
737
+
738
+ def encode(self, hidden_states: torch.Tensor) -> tuple[torch.Tensor, tuple[int, int]]:
739
+ r"""
740
+ Encode an image into patch tokens aligned with the denoiser grid.
741
+
742
+ Args:
743
+ hidden_states (`torch.Tensor`):
744
+ Images of shape `(batch, 3, height, width)` in `[-1, 1]`.
745
+
746
+ Returns:
747
+ `tuple[torch.Tensor, tuple[int, int]]`:
748
+ Tokens `(batch, grid_h * grid_w, feature_dim)` and the grid size.
749
+ """
750
+ self._zero_key_bias()
751
+ encoder_input, grid_hw = self.preprocess(hidden_states)
752
+ with torch.no_grad():
753
+ features = self.encoder.forward_features(encoder_input)
754
+ prefix = int(getattr(self.encoder, "num_prefix_tokens", 0))
755
+ tokens = features[:, prefix:, :]
756
+ encoder_grid = (
757
+ encoder_input.shape[-2] // self.spec.patch_size,
758
+ encoder_input.shape[-1] // self.spec.patch_size,
759
+ )
760
+ if encoder_grid != grid_hw:
761
+ batch, _, channels = tokens.shape
762
+ tokens = tokens.transpose(1, 2).reshape(batch, channels, *encoder_grid)
763
+ tokens = F.interpolate(tokens, size=grid_hw, mode="bilinear", align_corners=False)
764
+ tokens = tokens.flatten(2).transpose(1, 2)
765
+ return tokens, grid_hw
766
+
767
+ def forward(self, hidden_states: torch.Tensor, timesteps: torch.Tensor) -> torch.Tensor:
768
+ r"""
769
+ Encode and project grounding tokens.
770
+
771
+ Args:
772
+ hidden_states (`torch.Tensor`):
773
+ Images of shape `(batch, 3, height, width)`.
774
+ timesteps (`torch.Tensor`):
775
+ Flow time of shape `(batch,)`.
776
+
777
+ Returns:
778
+ `torch.Tensor`: Grounding of shape `(batch, patches, hidden_size)`.
779
+ """
780
+ tokens, grid_hw = self.encode(hidden_states)
781
+ return self.dino_proj(tokens.to(dtype=self.dino_proj.input_proj.weight.dtype), timesteps, grid_hw)
782
+
783
+
784
+ class PixelDiT2Transformer2DModel(ModelMixin, ConfigMixin):
785
+ r"""
786
+ PixelDiT2 class-conditional denoiser.
787
+
788
+ The module names match the training checkpoint (`t_embedder`, `y_embedder`, `s_embedder`,
789
+ `patch_blocks`, `final_layer`, `dino_conditioner`) so an EMA state dict loads without renaming.
790
+
791
+ Args:
792
+ sample_size (`int`, defaults to 256):
793
+ Native square resolution in pixels. Other multiples of `patch_size` are valid at inference
794
+ because rotary positions are recomputed for the requested grid.
795
+ in_channels (`int`, defaults to 3):
796
+ Image channels.
797
+ patch_size (`int`, defaults to 16):
798
+ Pixel patch size. `height` and `width` must be divisible by this value.
799
+ hidden_size (`int`, defaults to 1280):
800
+ Token width of PixelDiT2-H.
801
+ num_heads (`int`, defaults to 16):
802
+ Attention heads.
803
+ depth (`int`, defaults to 32):
804
+ Number of patch blocks.
805
+ num_classes (`int`, defaults to 1000):
806
+ ImageNet classes. The embedding table has `num_classes + 1` rows; the last row is the null class.
807
+ in_context_len (`int`, defaults to 32):
808
+ Number of in-context class tokens inserted at `in_context_start`.
809
+ in_context_start (`int`, defaults to 8):
810
+ Block index at which the in-context tokens are inserted. Must lie in `[0, depth)`.
811
+ attn_dropout (`float`, defaults to 0.0):
812
+ Attention dropout on the middle half of the blocks.
813
+ proj_dropout (`float`, defaults to 0.2):
814
+ Projection dropout on the middle half of the blocks. Inactive in `eval()`.
815
+ mlp_hidden_multiple (`int`, defaults to 0):
816
+ SwiGLU width rounding. `0` for 256px, `32` for 512px.
817
+ grounding_encoder (`str`, defaults to `"dinov3_vits16"`):
818
+ Frozen encoder key. 256px uses `dinov3_vits16`; 512px uses `dinov3_vitb16`.
819
+ grounding_proj_blocks (`int`, defaults to 1):
820
+ Blocks in the grounding projection.
821
+ grounding_proj_heads (`int`, defaults to 16):
822
+ Heads in the grounding projection.
823
+ single_silu_cond (`bool`, defaults to `False`):
824
+ When `False` (256px), SiLU is applied to the summed condition. When `True` (512px), it is not.
825
+ guidance_scale (`float`, defaults to 2.4):
826
+ Recommended classifier-free guidance scale. Read by the pipeline when the caller omits it.
827
+ guidance_interval_min (`float`, defaults to 0.125):
828
+ Lower flow-time bound of the guidance interval, exclusive.
829
+ guidance_interval_max (`float`, defaults to 0.9):
830
+ Upper flow-time bound of the guidance interval, exclusive.
831
+ noise_scale (`float`, defaults to 1.0):
832
+ Standard deviation of the initial Gaussian. 1.0 at 256px and 2.0 at 512px.
833
+ t_eps (`float`, defaults to 0.05):
834
+ Minimum denominator when converting an x0 prediction into a velocity.
835
+ default_num_inference_steps (`int`, defaults to 50):
836
+ Heun steps used when the pipeline caller omits `num_inference_steps`.
837
+ """
838
+
839
+ @register_to_config
840
+ def __init__(
841
+ self,
842
+ sample_size: int = 256,
843
+ in_channels: int = 3,
844
+ patch_size: int = 16,
845
+ hidden_size: int = 1280,
846
+ num_heads: int = 16,
847
+ depth: int = 32,
848
+ num_classes: int = 1000,
849
+ in_context_len: int = 32,
850
+ in_context_start: int = 8,
851
+ attn_dropout: float = 0.0,
852
+ proj_dropout: float = 0.2,
853
+ mlp_hidden_multiple: int = 0,
854
+ grounding_encoder: str = "dinov3_vits16",
855
+ grounding_proj_blocks: int = 1,
856
+ grounding_proj_heads: int = 16,
857
+ single_silu_cond: bool = False,
858
+ guidance_scale: float = 2.4,
859
+ guidance_interval_min: float = 0.125,
860
+ guidance_interval_max: float = 0.9,
861
+ noise_scale: float = 1.0,
862
+ t_eps: float = 0.05,
863
+ default_num_inference_steps: int = 50,
864
+ ):
865
+ super().__init__()
866
+ if not 0 <= in_context_start < depth:
867
+ raise ValueError(f"in_context_start must be in [0, {depth - 1}], got {in_context_start}.")
868
+ if hidden_size % num_heads != 0:
869
+ raise ValueError(f"hidden_size={hidden_size} must be divisible by num_heads={num_heads}.")
870
+
871
+ self.in_channels = in_channels
872
+ self.out_channels = in_channels
873
+ self.hidden_size = hidden_size
874
+ self.num_heads = num_heads
875
+ self.depth = depth
876
+ self.patch_size = patch_size
877
+ self.num_classes = num_classes
878
+ self.in_context_len = in_context_len
879
+ self.in_context_start = in_context_start
880
+ self.single_silu_cond = single_silu_cond
881
+
882
+ self.t_embedder = TimestepConditioner(hidden_size)
883
+ self.y_embedder = ClassEmbedder(num_classes + 1, hidden_size)
884
+ self.s_embedder = PatchTokenEmbedder(in_channels * patch_size**2, hidden_size, bias=True)
885
+ self.in_context_posemb = nn.Parameter(torch.zeros(1, in_context_len, hidden_size)) if in_context_len > 0 else None
886
+ self.patch_blocks = nn.ModuleList(
887
+ [
888
+ ModulatedDiTBlock(
889
+ hidden_size,
890
+ num_heads,
891
+ attn_drop=attn_dropout if depth // 4 <= i < depth // 4 * 3 else 0.0,
892
+ proj_drop=proj_dropout if depth // 4 <= i < depth // 4 * 3 else 0.0,
893
+ mlp_hidden_multiple=mlp_hidden_multiple,
894
+ )
895
+ for i in range(depth)
896
+ ]
897
+ )
898
+ self.final_layer = PatchFinalLayer(hidden_size, patch_size, self.out_channels)
899
+ self._init_denoiser_weights()
900
+ self.dino_conditioner = GroundingConditioner(
901
+ encoder_name=grounding_encoder,
902
+ hidden_size=hidden_size,
903
+ target_patch_size=patch_size,
904
+ proj_num_blocks=grounding_proj_blocks,
905
+ proj_num_heads=grounding_proj_heads,
906
+ )
907
+ self._pos_cache: dict[tuple[int, int, int], torch.Tensor] = {}
908
+
909
+ def _init_denoiser_weights(self) -> None:
910
+ r"""
911
+ Initialize the trainable denoiser the same way as the training code.
912
+
913
+ The grounding encoder is created afterwards and is not touched here.
914
+ """
915
+ weight = self.s_embedder.proj.weight.data
916
+ nn.init.xavier_uniform_(weight.view([weight.shape[0], -1]))
917
+ nn.init.constant_(self.s_embedder.proj.bias, 0)
918
+ nn.init.normal_(self.y_embedder.embedding_table.weight, std=0.02)
919
+ nn.init.normal_(self.t_embedder.mlp[0].weight, std=0.02)
920
+ nn.init.normal_(self.t_embedder.mlp[2].weight, std=0.02)
921
+ if self.in_context_posemb is not None:
922
+ nn.init.normal_(self.in_context_posemb, std=0.02)
923
+ for block in self.patch_blocks:
924
+ nn.init.zeros_(block.adaLN_modulation[-1].weight)
925
+ nn.init.zeros_(block.adaLN_modulation[-1].bias)
926
+ nn.init.zeros_(self.final_layer.linear.weight)
927
+ nn.init.zeros_(self.final_layer.linear.bias)
928
+ nn.init.zeros_(self.final_layer.adaLN_modulation[-1].weight)
929
+ nn.init.zeros_(self.final_layer.adaLN_modulation[-1].bias)
930
+
931
+ def fetch_pos(self, height: int, width: int, device: torch.device, num_context_tokens: int = 0) -> torch.Tensor:
932
+ r"""
933
+ RoPE table for a patch grid, with an identity prefix when context tokens are present.
934
+
935
+ Args:
936
+ height (`int`):
937
+ Grid height in patches.
938
+ width (`int`):
939
+ Grid width in patches.
940
+ device (`torch.device`):
941
+ Device of the returned table.
942
+ num_context_tokens (`int`, defaults to 0):
943
+ Leading tokens that receive an identity rotation (real part 1, imaginary part 0).
944
+
945
+ Returns:
946
+ `torch.Tensor`: Complex frequencies of shape `(num_context_tokens + height * width, head_dim / 2)`.
947
+ """
948
+ key = (height, width, num_context_tokens)
949
+ if key not in self._pos_cache:
950
+ pos = precompute_freqs_cis_2d(self.hidden_size // self.num_heads, height, width)
951
+ if num_context_tokens > 0:
952
+ identity = torch.ones(num_context_tokens, pos.shape[-1], dtype=pos.dtype)
953
+ pos = torch.cat([identity, pos], dim=0)
954
+ self._pos_cache[key] = pos
955
+ return self._pos_cache[key].to(device)
956
+
957
+ def _grounded_condition(
958
+ self,
959
+ hidden_states: torch.Tensor,
960
+ timesteps: torch.Tensor,
961
+ timestep_embedding: torch.Tensor,
962
+ class_embedding: torch.Tensor,
963
+ ) -> torch.Tensor:
964
+ r"""
965
+ Conditioning used by the class-conditional branch.
966
+
967
+ Args:
968
+ hidden_states (`torch.Tensor`):
969
+ Noisy images `(batch, channels, height, width)`.
970
+ timesteps (`torch.Tensor`):
971
+ Flow time `(batch,)`.
972
+ timestep_embedding (`torch.Tensor`):
973
+ Timestep embedding `(batch, hidden)`.
974
+ class_embedding (`torch.Tensor`):
975
+ Class embedding `(batch, 1, hidden)`.
976
+
977
+ Returns:
978
+ `torch.Tensor`: Per-patch conditioning `(batch, patches, hidden)`.
979
+ """
980
+ grounding = self.dino_conditioner(hidden_states, timesteps)
981
+ conditioning = grounding + timestep_embedding.unsqueeze(1) + class_embedding
982
+ if self.single_silu_cond:
983
+ return conditioning
984
+ return F.silu(conditioning)
985
+
986
+ def _null_condition(
987
+ self,
988
+ timestep_embedding: torch.Tensor,
989
+ class_embedding: torch.Tensor,
990
+ num_patches: int,
991
+ ) -> torch.Tensor:
992
+ r"""
993
+ Conditioning used when grounding is dropped.
994
+
995
+ Args:
996
+ timestep_embedding (`torch.Tensor`):
997
+ Timestep embedding `(batch, hidden)`.
998
+ class_embedding (`torch.Tensor`):
999
+ Class embedding `(batch, 1, hidden)`.
1000
+ num_patches (`int`):
1001
+ Number of spatial patches to broadcast over.
1002
+
1003
+ Returns:
1004
+ `torch.Tensor`: Conditioning `(batch, num_patches, hidden)`.
1005
+ """
1006
+ conditioning = timestep_embedding.unsqueeze(1) + class_embedding
1007
+ if not self.single_silu_cond:
1008
+ conditioning = F.silu(conditioning)
1009
+ return conditioning.expand(-1, num_patches, -1)
1010
+
1011
+ def forward(
1012
+ self,
1013
+ hidden_states: torch.Tensor,
1014
+ timestep: torch.Tensor,
1015
+ class_labels: torch.Tensor,
1016
+ skip_grounding: bool = False,
1017
+ skip_grounding_mask: torch.Tensor | None = None,
1018
+ return_dict: bool = True,
1019
+ ) -> Transformer2DModelOutput | tuple:
1020
+ r"""
1021
+ Predict the clean image x0.
1022
+
1023
+ Args:
1024
+ hidden_states (`torch.Tensor`):
1025
+ Noisy RGB sample of shape `(batch, in_channels, height, width)`, in model range around `[-1, 1]`.
1026
+ `height` and `width` must be divisible by `patch_size`.
1027
+ timestep (`torch.Tensor`):
1028
+ Flow-matching time `t` in `[0, 1]`, shape `(batch,)` or a scalar broadcast to the batch.
1029
+ `t = 0` is noise and `t = 1` is data.
1030
+ class_labels (`torch.Tensor`):
1031
+ Integer ImageNet ids of shape `(batch,)`. The null class is `num_classes`.
1032
+ skip_grounding (`bool`, defaults to `False`):
1033
+ When `True`, do not run the DINOv3 encoder. The unconditional CFG branch sets this.
1034
+ skip_grounding_mask (`torch.Tensor`, *optional*):
1035
+ Boolean mask of shape `(batch,)`. `True` rows use the null grounding condition.
1036
+ Ignored when `skip_grounding` is `True`.
1037
+ return_dict (`bool`, defaults to `True`):
1038
+ Return [`Transformer2DModelOutput`] when `True`, otherwise a one-tuple of the sample.
1039
+
1040
+ Returns:
1041
+ [`Transformer2DModelOutput`] or `tuple`:
1042
+ The x0 prediction of shape `(batch, in_channels, height, width)`.
1043
+ """
1044
+ batch, _, height, width = hidden_states.shape
1045
+ if height % self.patch_size or width % self.patch_size:
1046
+ raise ValueError(
1047
+ f"Input resolution ({height}, {width}) must be divisible by patch_size={self.patch_size}."
1048
+ )
1049
+ timestep = timestep.reshape(batch)
1050
+ class_labels = class_labels.reshape(batch).long()
1051
+ grid_h, grid_w = height // self.patch_size, width // self.patch_size
1052
+ num_patches = grid_h * grid_w
1053
+
1054
+ timestep_embedding = self.t_embedder(timestep)
1055
+ class_embedding = self.y_embedder(class_labels).view(batch, 1, self.hidden_size)
1056
+
1057
+ if skip_grounding:
1058
+ conditioning = self._null_condition(timestep_embedding, class_embedding, num_patches)
1059
+ else:
1060
+ conditioning = self._grounded_condition(hidden_states, timestep, timestep_embedding, class_embedding)
1061
+ if skip_grounding_mask is not None:
1062
+ null_conditioning = self._null_condition(timestep_embedding, class_embedding, num_patches)
1063
+ conditioning = torch.where(skip_grounding_mask.view(batch, 1, 1), null_conditioning, conditioning)
1064
+
1065
+ tokens = self.s_embedder(F.unfold(hidden_states, kernel_size=self.patch_size, stride=self.patch_size).transpose(1, 2))
1066
+ use_context = self.in_context_len > 0
1067
+ pos = self.fetch_pos(grid_h, grid_w, hidden_states.device)
1068
+ pos_with_context = self.fetch_pos(grid_h, grid_w, hidden_states.device, self.in_context_len) if use_context else None
1069
+ if use_context:
1070
+ context_conditioning = conditioning.mean(dim=1, keepdim=True).expand(-1, self.in_context_len, -1)
1071
+ conditioning_extended = torch.cat([context_conditioning, conditioning], dim=1)
1072
+
1073
+ context_inserted = False
1074
+ for index, block in enumerate(self.patch_blocks):
1075
+ if use_context and not context_inserted and index == self.in_context_start:
1076
+ context_tokens = class_embedding.expand(-1, self.in_context_len, -1)
1077
+ tokens = torch.cat([context_tokens + self.in_context_posemb.to(tokens.dtype), tokens], dim=1)
1078
+ context_inserted = True
1079
+ tokens = block(
1080
+ tokens,
1081
+ conditioning_extended if context_inserted else conditioning,
1082
+ pos_with_context if context_inserted else pos,
1083
+ )
1084
+ if context_inserted:
1085
+ tokens = tokens[:, self.in_context_len :, :]
1086
+
1087
+ output = self.final_layer(tokens, conditioning)
1088
+ output = output.view(batch, num_patches, self.patch_size**2, self.out_channels)
1089
+ output = output.permute(0, 3, 2, 1).reshape(batch, self.out_channels * self.patch_size**2, num_patches)
1090
+ output = F.fold(output, (height, width), kernel_size=self.patch_size, stride=self.patch_size)
1091
+
1092
+ if not return_dict:
1093
+ return (output,)
1094
+ return Transformer2DModelOutput(sample=output)
PixelDiT2-H-16-512/demo.png ADDED

Git LFS Details

  • SHA256: 32f21d3c6a5bf6086249e9d6a50d778e7c69270a6f73e5393eb4c9fe08533a66
  • Pointer size: 131 Bytes
  • Size of remote file: 504 kB
PixelDiT2-H-16-512/encoder/LICENSE.md ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # DINOv3 License
2
+
3
+ *Last Updated: August 19, 2025*
4
+
5
+ **β€œAgreement”** means the terms and conditions for use, reproduction, distribution and modification of the DINO Materials set forth herein.
6
+
7
+ **β€œDINO Materials”** means, collectively, Documentation and the models, software and algorithms, including machine-learning model code, trained model weights, inference-enabling code, training-enabling code, fine-tuning enabling code, and other elements of the foregoing distributed by Meta and made available under this Agreement.
8
+
9
+ **β€œDocumentation”** means the specifications, manuals and documentation accompanying
10
+ DINO Materials distributed by Meta.
11
+
12
+ **β€œLicensee”** or **β€œyou”** means you, or your employer or any other person or entity (if you are entering into this Agreement on such person or entity’s behalf), of the age required under applicable laws, rules or regulations to provide legal consent and that has legal authority to bind your employer or such other person or entity if you are entering in this Agreement on their behalf.
13
+
14
+ **β€œMeta”** or **β€œwe”** means Meta Platforms Ireland Limited (if you are located in or, if you are an entity, your principal place of business is in the EEA or Switzerland) or Meta Platforms, Inc. (if you are located outside of the EEA or Switzerland).
15
+
16
+ **β€œSanctions”** means any economic or trade sanctions or restrictions administered or enforced by the United States (including the Office of Foreign Assets Control of the U.S. Department of the Treasury (β€œOFAC”), the U.S. Department of State and the U.S. Department of Commerce), the United Nations, the European Union, or the United Kingdom.
17
+
18
+ **β€œTrade Controls”** means any of the following: Sanctions and applicable export and import controls.
19
+
20
+ By clicking β€œI Accept” below or by using or distributing any portion or element of the DINO Materials, you agree to be bound by this Agreement.
21
+
22
+ ## 1. License Rights and Redistribution.
23
+
24
+ a. <ins>Grant of Rights</ins>. You are granted a non-exclusive, worldwide, non-transferable and royalty-free limited license under Meta’s intellectual property or other rights owned by Meta embodied in the DINO Materials to use, reproduce, distribute, copy, create derivative works of, and make modifications to the DINO Materials.
25
+
26
+ b. <ins>Redistribution and Use</ins>.
27
+
28
+ i. Distribution of DINO Materials, and any derivative works thereof, are subject to the terms of this Agreement. If you distribute or make the DINO Materials, or any derivative works thereof, available to a third party, you may only do so under the terms of this Agreement and you shall provide a copy of this Agreement with any such DINO Materials.
29
+
30
+ ii. If you submit for publication the results of research you perform on, using, or otherwise in connection with DINO Materials, you must acknowledge the use of DINO Materials in your publication.
31
+
32
+ iii. Your use of the DINO Materials must comply with applicable laws and regulations, including Trade Control Laws and applicable privacy and data protection laws.
33
+
34
+ iv. Your use of the DINO Materials will not involve or encourage others to reverse engineer, decompile or discover the underlying components of the DINO Materials.
35
+
36
+ v. You are not the target of Trade Controls and your use of DINO Materials must comply with Trade Controls. You agree not to use, or permit others to use, DINO Materials for any activities subject to the International Traffic in Arms Regulations (ITAR) or end uses prohibited by Trade Controls, including those related to military or warfare purposes, nuclear industries or applications, espionage, or the development or use of guns or illegal weapons.
37
+
38
+ ## 2. User Support.
39
+
40
+ Your use of the DINO Materials is done at your own discretion; Meta does not process any information nor provide any service in relation to such use. Meta is under no obligation to provide any support services for the DINO Materials. Any support provided is β€œas is”, β€œwith all faults”, and without warranty of any kind.
41
+
42
+ ## 3. Disclaimer of Warranty.
43
+
44
+ UNLESS REQUIRED BY APPLICABLE LAW, THE DINO MATERIALS AND ANY OUTPUT AND RESULTS THEREFROM ARE PROVIDED ON AN β€œAS IS” BASIS, WITHOUT WARRANTIES OF ANY KIND, AND META DISCLAIMS ALL WARRANTIES OF ANY KIND, BOTH EXPRESS AND IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. YOU ARE SOLELY RESPONSIBLE FOR DETERMINING THE APPROPRIATENESS OF USING OR REDISTRIBUTING THE DINO MATERIALS AND ASSUME ANY RISKS ASSOCIATED WITH YOUR USE OF THE DINO MATERIALS AND ANY OUTPUT AND RESULTS.
45
+
46
+ ## 4. Limitation of Liability.
47
+
48
+ IN NO EVENT WILL META OR ITS AFFILIATES BE LIABLE UNDER ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, TORT, NEGLIGENCE, PRODUCTS LIABILITY, OR OTHERWISE, ARISING OUT OF THIS AGREEMENT, FOR ANY LOST PROFITS OR ANY DIRECT OR INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL, EXEMPLARY OR PUNITIVE DAMAGES, EVEN IF META OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF ANY OF THE FOREGOING.
49
+
50
+ ## 5. Intellectual Property.
51
+
52
+ a. Subject to Meta’s ownership of DINO Materials and derivatives made by or for Meta, with respect to any derivative works and modifications of the DINO Materials that are made by you, as between you and Meta, you are and will be the owner of such derivative works and modifications.
53
+
54
+ b. If you institute litigation or other proceedings against Meta or any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the DINO Materials, outputs or results, or any portion of any of the foregoing, constitutes infringement of intellectual property or other rights owned or licensable by you, then any licenses granted to you under this Agreement shall terminate as of the date such litigation or claim is filed or instituted. You will indemnify and hold harmless Meta from and against any claim by any third party arising out of or related to your use or distribution of the DINO Materials.
55
+
56
+ ## 6. Term and Termination.
57
+
58
+ The term of this Agreement will commence upon your acceptance of this Agreement or access to the DINO Materials and will continue in full force and effect until terminated in accordance with the terms and conditions herein. Meta may terminate this Agreement if you are in breach of any term or condition of this Agreement. Upon termination of this Agreement, you shall delete and cease use of the DINO Materials. Sections 3, 4 and 7 shall survive the termination of this Agreement.
59
+
60
+ ## 7. Governing Law and Jurisdiction.
61
+
62
+ This Agreement will be governed and construed under the laws of the State of California without regard to choice of law principles, and the UN Convention on Contracts for the International Sale of Goods does not apply to this Agreement. The courts of California shall have exclusive jurisdiction of any dispute arising out of this Agreement.
63
+
64
+ ## 8. Modifications and Amendments.
65
+
66
+ Meta may modify this Agreement from time to time; provided that they are similar in spirit to the current version of the Agreement, but may differ in detail to address new problems or concerns. All such changes will be effective immediately. Your continued use of the DINO Materials after any modification to this Agreement constitutes your agreement to such modification. Except as provided in this Agreement, no modification or addition to any provision of this Agreement will be binding unless it is in writing and signed by an authorized representative of both you and Meta.
PixelDiT2-H-16-512/encoder/README.md ADDED
@@ -0,0 +1,477 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ extra_gated_fields:
3
+ First Name: text
4
+ Last Name: text
5
+ Date of birth: date_picker
6
+ Country: country
7
+ Affiliation: text
8
+ Job title:
9
+ type: select
10
+ options:
11
+ - Student
12
+ - Research Graduate
13
+ - AI researcher
14
+ - AI developer/engineer
15
+ - Reporter
16
+ - Other
17
+ geo: ip_location
18
+ By clicking Submit below I accept the terms of the license and acknowledge that the information I provide will be collected stored processed and shared in accordance with the Meta Privacy Policy: checkbox
19
+ extra_gated_description: >-
20
+ The information you provide will be collected, stored, processed and shared in
21
+ accordance with the [Meta Privacy
22
+ Policy](https://www.facebook.com/privacy/policy/).
23
+ extra_gated_button_content: Submit
24
+ language:
25
+ - en
26
+ tags:
27
+ - dino
28
+ - dinov3
29
+ - arxiv:2508.10104
30
+ license: other
31
+ license_name: dinov3-license
32
+ license_link: https://ai.meta.com/resources/models-and-libraries/dinov3-license
33
+ base_model: facebook/dinov3-vit7b16-pretrain-lvd1689m
34
+ pipeline_tag: image-feature-extraction
35
+ library_name: transformers
36
+ ---
37
+
38
+ # Model Card for DINOv3
39
+
40
+ DINOv3 is a family of versatile vision foundation models that outperforms the specialized state of the art across a broad range of settings, without fine-tuning. DINOv3 produces high-quality dense features that achieve outstanding performance on various vision tasks, significantly surpassing previous self- and weakly-supervised foundation models.
41
+
42
+ ## Model Details
43
+
44
+ These are Vision Transformer and ConvNeXt models trained following the method described in the DINOv3 paper. 12 models are provided:
45
+
46
+ - 10 models pretrained on web data (LVD-1689M dataset)
47
+ - 1 ViT-7B trained from scratch,
48
+ - 5 ViT-S/S+/B/L/H+ models distilled from the ViT-7B,
49
+ - 4 ConvNeXt-{T/S/B/L} models distilled from the ViT-7B,
50
+ - 2 models pretrained on satellite data (SAT-493M dataset)
51
+ - 1 ViT-7B trained from scratch
52
+ - 1 ViT-L distilled from the ViT-7B
53
+
54
+
55
+ Each Transformer-based model takes an image as input and returns a class token, patch tokens (and register tokens). These models follow a ViT architecture, with a patch size of 16. For a 224x224 image, this results in 1 class token + 4 register tokens + 196 patch tokens = 201 tokens (for DINOv2 with registers this resulted in 1 + 4 + 256 = 261 tokens).
56
+
57
+ The models can accept larger images provided the image shapes are multiples of the patch size (16). If this condition is not verified, the model will crop to the closest smaller multiple of the patch size.
58
+
59
+ ### Model Description
60
+
61
+ - **Developed by:** Meta AI
62
+ - **Model type:** Vision Transformer, ConvNeXt
63
+ - **License:** [DINOv3 License](https://ai.meta.com/resources/models-and-libraries/dinov3-license/)
64
+
65
+ ### Model Sources
66
+
67
+ - **Repository:** [https://github.com/facebookresearch/dinov3](https://github.com/facebookresearch/dinov3)
68
+ - **Paper:** [https://arxiv.org/abs/2508.10104](https://arxiv.org/abs/2508.10104)
69
+
70
+ ## Uses
71
+
72
+ The models are vision backbones providing multi-purpose features for downstream tasks.
73
+
74
+ ### Direct Use
75
+
76
+ The models can be used without fine-tuning, with downstream classifiers as simple as linear layers, to obtain competitive results:
77
+
78
+ - on image classification, using k-NN classifiers on the class token
79
+ - on image classification, with logistic regression classifiers applied on the class token
80
+ - on image classification, with a linear layer applied on the class token and the average of the patch tokens
81
+ - on image retrieval using nearest neighbors
82
+ - on geometric and semantic 3D keypoint correspondances
83
+ - on depth estimation, semantic segmentation, using linear layers
84
+ - on unsupervised object discovery
85
+ - on video segmentation tracking
86
+ - on video classification, using a small 4-layer attentive probe
87
+
88
+ ### Downstream Use
89
+
90
+ While fine-tuning the models can yield some gains, it is recommended to keep this option as a last resort: the frozen features are expected to provide good performance out-of-the-box.
91
+
92
+ ## Bias, Risks, and Limitations
93
+
94
+ Compared to DINOv2 and SEERv2, DINOv3 delivers somewhat consistent performance across income categories on geographical fairness and diversity, although with a notable performance drop in the low-income bucket compared to the highest-income bucket.
95
+
96
+ DINOv3 also achieves relatively good scores across different regions, improving over its predecessor DINOv2. However, a relative difference is still observed between Europe and Africa.
97
+
98
+ ### Recommendations
99
+
100
+ Fine-tuning is expected to increase the biases in the features produced by the model as they will be tuned to the fine-tuning labels.
101
+
102
+ ## How to Get Started with the Model
103
+
104
+ The example below demonstrates how to obtain an image embedding with [Pipeline] or the [AutoModel] class.
105
+
106
+ ```python
107
+ from transformers import pipeline
108
+ from transformers.image_utils import load_image
109
+
110
+ url = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/pipeline-cat-chonk.jpeg"
111
+ image = load_image(url)
112
+
113
+ feature_extractor = pipeline(
114
+ model="facebook/dinov3-vitb16-pretrain-lvd1689m",
115
+ task="image-feature-extraction",
116
+ )
117
+ features = feature_extractor(image)
118
+ ```
119
+
120
+ ```python
121
+ import torch
122
+ from transformers import AutoImageProcessor, AutoModel
123
+ from transformers.image_utils import load_image
124
+
125
+ url = "http://images.cocodataset.org/val2017/000000039769.jpg"
126
+ image = load_image(url)
127
+
128
+ pretrained_model_name = "facebook/dinov3-vitb16-pretrain-lvd1689m"
129
+ processor = AutoImageProcessor.from_pretrained(pretrained_model_name)
130
+ model = AutoModel.from_pretrained(
131
+ pretrained_model_name,
132
+ device_map="auto",
133
+ )
134
+
135
+ inputs = processor(images=image, return_tensors="pt").to(model.device)
136
+ with torch.inference_mode():
137
+ outputs = model(**inputs)
138
+
139
+ pooled_output = outputs.pooler_output
140
+ print("Pooled output shape:", pooled_output.shape)
141
+ ```
142
+
143
+ ## Training Details
144
+
145
+ ### Training Data
146
+
147
+ - Web dataset (LVD-1689M): a curated dataset of 1,689 millions of images extracted from a large data
148
+ pool of 17 billions web images collected from public posts on Instagram
149
+
150
+ - Satellite dataset (SAT-493M): a dataset of 493 millions of 512x512 images sampled randomly from Maxar RGB ortho-rectified imagery at 0.6 meter resolution
151
+
152
+ ### Training Procedure
153
+
154
+ **Training objective:**
155
+
156
+ - DINO self-distillation loss with multi-crop
157
+ - iBOT masked-image modeling loss
158
+ - KoLeo regularization on [CLS] tokens
159
+ - Gram anchoring
160
+
161
+ - **Training regime:** PyTorch FSDP2 (with bf16 and fp8 matrix multiplications)
162
+
163
+ **Distillation:**
164
+
165
+ - Distillation follows the standard DINOv3 pretraining procedure, except the teacher is a frozen pretrained ViT-7B.
166
+
167
+ ## Evaluation
168
+
169
+ **Results**
170
+
171
+ The reader is referred to the associated paper for details on the evaluation protocols
172
+
173
+ *Results for ViT backbones pretrained (or distilled) on web (LVD-1689M)*
174
+
175
+ <table>
176
+ <tr>
177
+ <th></th>
178
+ <!-- <th></th> -->
179
+ <th colspan="4">Global Tasks</th>
180
+ <th colspan="5">Dense Tasks</th>
181
+ </tr>
182
+ <tr>
183
+ <th>Model</th>
184
+ <!-- <th>Dataset</th> -->
185
+ <th>IN-ReaL</th>
186
+ <th>IN-R</th>
187
+ <th>Obj.Net</th>
188
+ <th>Ox.-H</th>
189
+ <th>ADE20k</th>
190
+ <th>NYU↓</th>
191
+ <th>DAVIS</th>
192
+ <th>NAVI</th>
193
+ <th>SPair</th>
194
+ </tr>
195
+ <tr>
196
+ <td>DINOv3 ViT-S/16</td>
197
+ <!-- <td>LVD-1689M</td> -->
198
+ <td align="right">87.0</td>
199
+ <td align="right">60.4</td>
200
+ <td align="right">50.9</td>
201
+ <td align="right">49.5</td>
202
+ <td align="right">47.0</td>
203
+ <td align="right">0.403</td>
204
+ <td align="right">72.7</td>
205
+ <td align="right">56.3</td>
206
+ <td align="right">50.4</td>
207
+ </tr>
208
+ <tr>
209
+ <td>DINOv3 ViT-S+/16</td>
210
+ <!-- <td>LVD-1689M</td> -->
211
+ <td align="right">88.0</td>
212
+ <td align="right">68.8</td>
213
+ <td align="right">54.6</td>
214
+ <td align="right">50.0</td>
215
+ <td align="right">48.8</td>
216
+ <td align="right">0.399</td>
217
+ <td align="right">75.5</td>
218
+ <td align="right">57.1</td>
219
+ <td align="right">55.2</td>
220
+ </tr>
221
+ <tr>
222
+ <td>DINOv3 ViT-B/16</td>
223
+ <!-- <td>LVD-1689M</td> -->
224
+ <td align="right">89.3</td>
225
+ <td align="right">76.7</td>
226
+ <td align="right">64.1</td>
227
+ <td align="right">58.5</td>
228
+ <td align="right">51.8</td>
229
+ <td align="right">0.373</td>
230
+ <td align="right">77.2</td>
231
+ <td align="right">58.8</td>
232
+ <td align="right">57.2</td>
233
+ </tr>
234
+ <tr>
235
+ <td>DINOv3 ViT-L/16</td>
236
+ <!-- <td>LVD-1689M</td> -->
237
+ <td align="right">90.2</td>
238
+ <td align="right">88.1</td>
239
+ <td align="right">74.8</td>
240
+ <td align="right">63.1</td>
241
+ <td align="right">54.9</td>
242
+ <td align="right">0.352</td>
243
+ <td align="right">79.9</td>
244
+ <td align="right">62.3</td>
245
+ <td align="right">61.3</td>
246
+ </tr>
247
+ <tr>
248
+ <td>DINOv3 ViT-H+/16</td>
249
+ <!-- <td>LVD-1689M</td> -->
250
+ <td align="right">90.3</td>
251
+ <td align="right">90.0</td>
252
+ <td align="right">78.6</td>
253
+ <td align="right">64.5</td>
254
+ <td align="right">54.8</td>
255
+ <td align="right">0.352</td>
256
+ <td align="right">79.3</td>
257
+ <td align="right">63.3</td>
258
+ <td align="right">56.3</td>
259
+ </tr>
260
+ <tr>
261
+ <td>DINOv3 ViT-7B/16</td>
262
+ <!-- <td>LVD-1689M</td> -->
263
+ <td align="right">90.4</td>
264
+ <td align="right">91.1</td>
265
+ <td align="right">91.1</td>
266
+ <td align="right">72.8</td>
267
+ <td align="right">55.9</td>
268
+ <td align="right">0.309</td>
269
+ <td align="right">79.7</td>
270
+ <td align="right">64.4</td>
271
+ <td align="right">58.7</td>
272
+ </tr>
273
+ </table>
274
+
275
+ *Results for ConvNeXt backbones distilled on web (LVD-1689M)*
276
+
277
+ <table>
278
+ <tr>
279
+ <th></th>
280
+ <th colspan="6">Global Tasks</th>
281
+ <th colspan="2">Dense Tasks</th>
282
+ </tr>
283
+ <tr>
284
+ <th>Model</th>
285
+ <th colspan="2">IN-ReaL</th>
286
+ <th colspan="2">IN-R</th>
287
+ <th colspan="2">Obj.Net</th>
288
+ <th>ADE20k</th>
289
+ <th>NYU↓</th>
290
+ </tr>
291
+ <tr>
292
+ <td></th>
293
+ <td>@256px</td>
294
+ <td>@512px</td>
295
+ <td>@256px</td>
296
+ <td>@512px</td>
297
+ <td>@256px</td>
298
+ <td>@512px</td>
299
+ <td colspan="2"></td>
300
+ </tr>
301
+ <tr>
302
+ <td>DINOv3 ConvNeXt Tiny</td>
303
+ <td align="right">86.6</td>
304
+ <td align="right">87.7</td>
305
+ <td align="right">73.7</td>
306
+ <td align="right">74.1</td>
307
+ <td align="right">52.6</td>
308
+ <td align="right">58.7</td>
309
+ <td align="right">42.7</td>
310
+ <td align="right">0.448</td>
311
+ </tr>
312
+ <tr>
313
+ <td>DINOv3 ConvNeXt Small</td>
314
+ <td align="right">87.9</td>
315
+ <td align="right">88.7</td>
316
+ <td align="right">73.7</td>
317
+ <td align="right">74.1</td>
318
+ <td align="right">52.6</td>
319
+ <td align="right">58.7</td>
320
+ <td align="right">44.8</td>
321
+ <td align="right">0.432</td>
322
+ </tr>
323
+ <tr>
324
+ <td>DINOv3 ConvNeXt Base</td>
325
+ <td align="right">88.5</td>
326
+ <td align="right">89.2</td>
327
+ <td align="right">77.2</td>
328
+ <td align="right">78.2</td>
329
+ <td align="right">56.2</td>
330
+ <td align="right">61.3</td>
331
+ <td align="right">46.3</td>
332
+ <td align="right">0.420</td>
333
+ </tr>
334
+ <tr>
335
+ <td>DINOv3 ConvNeXt Large</td>
336
+ <td align="right">88.9</td>
337
+ <td align="right">89.4</td>
338
+ <td align="right">81.3</td>
339
+ <td align="right">82.4</td>
340
+ <td align="right">59.3</td>
341
+ <td align="right">65.2</td>
342
+ <td align="right">47.8</td>
343
+ <td align="right">0.403</td>
344
+ </tr>
345
+ </table>
346
+
347
+ *Results for ViT backbones pretrained (or distilled) on satellite (SAT-493M)*
348
+
349
+ <table>
350
+ <tr>
351
+ <th></th>
352
+ <th colspan="7">(GEO-Bench) Classification</th>
353
+ </tr>
354
+ <tr>
355
+ <th>Model</ht>
356
+ <th>m-BEnet</th>
357
+ <th>m-brick-kiln
358
+ <th>m-eurosat</th>
359
+ <th>m-forestnet</th>
360
+ <th>m-pv4ger</th>
361
+ <th>m-so2sat</th>
362
+ <th>mean</th>
363
+ </tr>
364
+ <tr>
365
+ <td>DINOv3 ViT-L/16</td>
366
+ <td>73.0</td>
367
+ <td>96.5</td>
368
+ <td>94.1</td>
369
+ <td>60.6</td>
370
+ <td>96.0</td>
371
+ <td>57.4</td>
372
+ <td>79.6</td>
373
+ </tr>
374
+ <tr>
375
+ <td>DINOv3 ViT-7B/16</td>
376
+ <td>74.0</td>
377
+ <td>97.2</td>
378
+ <td>94.8</td>
379
+ <td>62.3</td>
380
+ <td>96.1</td>
381
+ <td>62.1</td>
382
+ <td>81.1</td>
383
+ </tr>
384
+ <tr>
385
+ <th></th>
386
+ <th colspan="7">(GEO-Bench) Segmentation</th>
387
+ </tr>
388
+ <tr>
389
+ <th>Model</th>
390
+ <th>m-cashew</th>
391
+ <th>m-chesapeake</th>
392
+ <th>m-NeonTree</th>
393
+ <th>m-nz-cattle</th>
394
+ <th>m-pv4ger-seg</th>
395
+ <th>m-SA-crop</th>
396
+ <th>mean</th>
397
+ </tr>
398
+ <tr>
399
+ <td>DINOv3 ViT-L/16</td>
400
+ <td>94.2</td>
401
+ <td>75.6</td>
402
+ <td>61.8</td>
403
+ <td>83.7</td>
404
+ <td>95.2</td>
405
+ <td>36.8</td>
406
+ <td>74.5</td>
407
+ </tr>
408
+ <tr>
409
+ <td>DINOv3 ViT-7B/16</td>
410
+ <td>94.1</td>
411
+ <td>76.6</td>
412
+ <td>62.6</td>
413
+ <td>83.4</td>
414
+ <td>95.5</td>
415
+ <td>37.6</td>
416
+ <td>75.0</td>
417
+ </tr>
418
+ </table>
419
+
420
+
421
+ ## Environmental Impact
422
+
423
+ - **Hardware Type:** Nvidia H100
424
+ - **Hours used:** 61,440 hours for ViT-7B model training
425
+ - **Cloud Provider:** Private infrastructure
426
+ - **Compute Region:** USA
427
+ - **Carbon Emitted:** 18t CO2eq
428
+
429
+ ## Technical Specifications
430
+
431
+ ### Model Architecture and Objective
432
+
433
+ Vision Transformer models:
434
+
435
+ - ViT-S (21M parameters): patch size 16, embedding dimension 384, 4 register tokens, 6 heads, MLP FFN, RoPE
436
+ - ViT-S+ (29M parameters): patch size 16, embedding dimension 384, 4 register tokens, 6 heads, SwiGLU FFN, RoPE
437
+ - ViT-B (86M parameters): patch size 16, embedding dimension 768, 4 register tokens, 12 heads, MLP FFN, RoPE
438
+ - ViT-L (300M parameters): patch size 16, embedding dimension 1024, 4 register tokens, 16 heads, MLP FFN, RoPE
439
+ - ViT-H+ (840M parameters): patch size 16, embedding dimension 1280, 4 register tokens, 20 heads, SwiGLU FFN, RoPE
440
+ - ViT-7B (6716M parameters): patch size 16, embedding dimension 4096, 4 register tokens, 32 heads, SwiGLU FFN, RoPE
441
+
442
+ ConvNeXt models:
443
+
444
+ - ConvNeXt Tiny (29M parameters)
445
+ - ConvNeXt Small (50M parameters)
446
+ - ConvNeXt Base (89M parameters)
447
+ - ConvNeXt Large (198M parameters)
448
+
449
+ ### Compute Infrastructure
450
+
451
+ #### Hardware
452
+
453
+ Nvidia H100 GPUs
454
+
455
+ #### Software
456
+
457
+ PyTorch 2.7
458
+
459
+ ## More Information
460
+
461
+ See the [blog post](https://ai.meta.com/blog/dinov3-self-supervised-vision-model/) and the associated [website](https://ai.meta.com/dinov3/).
462
+
463
+ ## Citation
464
+
465
+ **BibTeX**
466
+
467
+ ```
468
+ @misc{simeoni2025dinov3,
469
+ title={{DINOv3}},
470
+ author={Sim{\'e}oni, Oriane and Vo, Huy V. and Seitzer, Maximilian and Baldassarre, Federico and Oquab, Maxime and Jose, Cijo and Khalidov, Vasil and Szafraniec, Marc and Yi, Seungeun and Ramamonjisoa, Micha{\"e}l and Massa, Francisco and Haziza, Daniel and Wehrstedt, Luca and Wang, Jianyuan and Darcet, Timoth{\'e}e and Moutakanni, Th{\'e}o and Sentana, Leonel and Roberts, Claire and Vedaldi, Andrea and Tolan, Jamie and Brandt, John and Couprie, Camille and Mairal, Julien and J{\'e}gou, Herv{\'e} and Labatut, Patrick and Bojanowski, Piotr},
471
+ year={2025},
472
+ eprint={2508.10104},
473
+ archivePrefix={arXiv},
474
+ primaryClass={cs.CV},
475
+ url={https://arxiv.org/abs/2508.10104},
476
+ }
477
+ ```
PixelDiT2-H-16-512/encoder/config.json ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "DINOv3ViTModel"
4
+ ],
5
+ "attention_dropout": 0.0,
6
+ "drop_path_rate": 0.0,
7
+ "hidden_act": "gelu",
8
+ "hidden_size": 768,
9
+ "image_size": 224,
10
+ "initializer_range": 0.02,
11
+ "intermediate_size": 3072,
12
+ "key_bias": false,
13
+ "layer_norm_eps": 1e-05,
14
+ "layerscale_value": 1.0,
15
+ "mlp_bias": true,
16
+ "model_type": "dinov3_vit",
17
+ "num_attention_heads": 12,
18
+ "num_channels": 3,
19
+ "num_hidden_layers": 12,
20
+ "num_register_tokens": 4,
21
+ "patch_size": 16,
22
+ "pos_embed_jitter": null,
23
+ "pos_embed_rescale": 2.0,
24
+ "pos_embed_shift": null,
25
+ "proj_bias": true,
26
+ "query_bias": true,
27
+ "rope_theta": 100.0,
28
+ "torch_dtype": "float32",
29
+ "transformers_version": "4.56.0.dev0",
30
+ "use_gated_mlp": false,
31
+ "value_bias": true
32
+ }
PixelDiT2-H-16-512/encoder/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9a21ac3df0c63839d62612dda6f454d816c25611cc7a52966ed5a5a94921dc8b
3
+ size 342662192
PixelDiT2-H-16-512/encoder/preprocessor_config.json ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "crop_size": null,
3
+ "data_format": "channels_first",
4
+ "default_to_square": true,
5
+ "device": null,
6
+ "disable_grouping": null,
7
+ "do_center_crop": null,
8
+ "do_convert_rgb": null,
9
+ "do_normalize": true,
10
+ "do_rescale": true,
11
+ "do_resize": true,
12
+ "image_mean": [
13
+ 0.485,
14
+ 0.456,
15
+ 0.406
16
+ ],
17
+ "image_processor_type": "DINOv3ViTImageProcessorFast",
18
+ "image_std": [
19
+ 0.229,
20
+ 0.224,
21
+ 0.225
22
+ ],
23
+ "input_data_format": null,
24
+ "resample": 2,
25
+ "rescale_factor": 0.00392156862745098,
26
+ "return_tensors": null,
27
+ "size": {
28
+ "height": 224,
29
+ "width": 224
30
+ }
31
+ }
PixelDiT2-H-16-512/model_index.json ADDED
@@ -0,0 +1,1021 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_class_name": [
3
+ "pipeline",
4
+ "PixelDiT2Pipeline"
5
+ ],
6
+ "_diffusers_version": "0.39.0",
7
+ "encoder": [
8
+ "transformers",
9
+ "DINOv3ViTModel"
10
+ ],
11
+ "scheduler": [
12
+ "scheduling_pixeldit2",
13
+ "PixelDiT2Scheduler"
14
+ ],
15
+ "transformer": [
16
+ "transformer_pixeldit2",
17
+ "PixelDiT2Transformer2DModel"
18
+ ],
19
+ "id2label": {
20
+ "0": "tench, Tinca tinca",
21
+ "1": "goldfish, Carassius auratus",
22
+ "2": "great white shark, white shark, man-eater, man-eating shark, Carcharodon carcharias",
23
+ "3": "tiger shark, Galeocerdo cuvieri",
24
+ "4": "hammerhead, hammerhead shark",
25
+ "5": "electric ray, crampfish, numbfish, torpedo",
26
+ "6": "stingray",
27
+ "7": "cock",
28
+ "8": "hen",
29
+ "9": "ostrich, Struthio camelus",
30
+ "10": "brambling, Fringilla montifringilla",
31
+ "11": "goldfinch, Carduelis carduelis",
32
+ "12": "house finch, linnet, Carpodacus mexicanus",
33
+ "13": "junco, snowbird",
34
+ "14": "indigo bunting, indigo finch, indigo bird, Passerina cyanea",
35
+ "15": "robin, American robin, Turdus migratorius",
36
+ "16": "bulbul",
37
+ "17": "jay",
38
+ "18": "magpie",
39
+ "19": "chickadee",
40
+ "20": "water ouzel, dipper",
41
+ "21": "kite",
42
+ "22": "bald eagle, American eagle, Haliaeetus leucocephalus",
43
+ "23": "vulture",
44
+ "24": "great grey owl, great gray owl, Strix nebulosa",
45
+ "25": "European fire salamander, Salamandra salamandra",
46
+ "26": "common newt, Triturus vulgaris",
47
+ "27": "eft",
48
+ "28": "spotted salamander, Ambystoma maculatum",
49
+ "29": "axolotl, mud puppy, Ambystoma mexicanum",
50
+ "30": "bullfrog, Rana catesbeiana",
51
+ "31": "tree frog, tree-frog",
52
+ "32": "tailed frog, bell toad, ribbed toad, tailed toad, Ascaphus trui",
53
+ "33": "loggerhead, loggerhead turtle, Caretta caretta",
54
+ "34": "leatherback turtle, leatherback, leathery turtle, Dermochelys coriacea",
55
+ "35": "mud turtle",
56
+ "36": "terrapin",
57
+ "37": "box turtle, box tortoise",
58
+ "38": "banded gecko",
59
+ "39": "common iguana, iguana, Iguana iguana",
60
+ "40": "American chameleon, anole, Anolis carolinensis",
61
+ "41": "whiptail, whiptail lizard",
62
+ "42": "agama",
63
+ "43": "frilled lizard, Chlamydosaurus kingi",
64
+ "44": "alligator lizard",
65
+ "45": "Gila monster, Heloderma suspectum",
66
+ "46": "green lizard, Lacerta viridis",
67
+ "47": "African chameleon, Chamaeleo chamaeleon",
68
+ "48": "Komodo dragon, Komodo lizard, dragon lizard, giant lizard, Varanus komodoensis",
69
+ "49": "African crocodile, Nile crocodile, Crocodylus niloticus",
70
+ "50": "American alligator, Alligator mississipiensis",
71
+ "51": "triceratops",
72
+ "52": "thunder snake, worm snake, Carphophis amoenus",
73
+ "53": "ringneck snake, ring-necked snake, ring snake",
74
+ "54": "hognose snake, puff adder, sand viper",
75
+ "55": "green snake, grass snake",
76
+ "56": "king snake, kingsnake",
77
+ "57": "garter snake, grass snake",
78
+ "58": "water snake",
79
+ "59": "vine snake",
80
+ "60": "night snake, Hypsiglena torquata",
81
+ "61": "boa constrictor, Constrictor constrictor",
82
+ "62": "rock python, rock snake, Python sebae",
83
+ "63": "Indian cobra, Naja naja",
84
+ "64": "green mamba",
85
+ "65": "sea snake",
86
+ "66": "horned viper, cerastes, sand viper, horned asp, Cerastes cornutus",
87
+ "67": "diamondback, diamondback rattlesnake, Crotalus adamanteus",
88
+ "68": "sidewinder, horned rattlesnake, Crotalus cerastes",
89
+ "69": "trilobite",
90
+ "70": "harvestman, daddy longlegs, Phalangium opilio",
91
+ "71": "scorpion",
92
+ "72": "black and gold garden spider, Argiope aurantia",
93
+ "73": "barn spider, Araneus cavaticus",
94
+ "74": "garden spider, Aranea diademata",
95
+ "75": "black widow, Latrodectus mactans",
96
+ "76": "tarantula",
97
+ "77": "wolf spider, hunting spider",
98
+ "78": "tick",
99
+ "79": "centipede",
100
+ "80": "black grouse",
101
+ "81": "ptarmigan",
102
+ "82": "ruffed grouse, partridge, Bonasa umbellus",
103
+ "83": "prairie chicken, prairie grouse, prairie fowl",
104
+ "84": "peacock",
105
+ "85": "quail",
106
+ "86": "partridge",
107
+ "87": "African grey, African gray, Psittacus erithacus",
108
+ "88": "macaw",
109
+ "89": "sulphur-crested cockatoo, Kakatoe galerita, Cacatua galerita",
110
+ "90": "lorikeet",
111
+ "91": "coucal",
112
+ "92": "bee eater",
113
+ "93": "hornbill",
114
+ "94": "hummingbird",
115
+ "95": "jacamar",
116
+ "96": "toucan",
117
+ "97": "drake",
118
+ "98": "red-breasted merganser, Mergus serrator",
119
+ "99": "goose",
120
+ "100": "black swan, Cygnus atratus",
121
+ "101": "tusker",
122
+ "102": "echidna, spiny anteater, anteater",
123
+ "103": "platypus, duckbill, duckbilled platypus, duck-billed platypus, Ornithorhynchus anatinus",
124
+ "104": "wallaby, brush kangaroo",
125
+ "105": "koala, koala bear, kangaroo bear, native bear, Phascolarctos cinereus",
126
+ "106": "wombat",
127
+ "107": "jellyfish",
128
+ "108": "sea anemone, anemone",
129
+ "109": "brain coral",
130
+ "110": "flatworm, platyhelminth",
131
+ "111": "nematode, nematode worm, roundworm",
132
+ "112": "conch",
133
+ "113": "snail",
134
+ "114": "slug",
135
+ "115": "sea slug, nudibranch",
136
+ "116": "chiton, coat-of-mail shell, sea cradle, polyplacophore",
137
+ "117": "chambered nautilus, pearly nautilus, nautilus",
138
+ "118": "Dungeness crab, Cancer magister",
139
+ "119": "rock crab, Cancer irroratus",
140
+ "120": "fiddler crab",
141
+ "121": "king crab, Alaska crab, Alaskan king crab, Alaska king crab, Paralithodes camtschatica",
142
+ "122": "American lobster, Northern lobster, Maine lobster, Homarus americanus",
143
+ "123": "spiny lobster, langouste, rock lobster, crawfish, crayfish, sea crawfish",
144
+ "124": "crayfish, crawfish, crawdad, crawdaddy",
145
+ "125": "hermit crab",
146
+ "126": "isopod",
147
+ "127": "white stork, Ciconia ciconia",
148
+ "128": "black stork, Ciconia nigra",
149
+ "129": "spoonbill",
150
+ "130": "flamingo",
151
+ "131": "little blue heron, Egretta caerulea",
152
+ "132": "American egret, great white heron, Egretta albus",
153
+ "133": "bittern",
154
+ "134": "crane",
155
+ "135": "limpkin, Aramus pictus",
156
+ "136": "European gallinule, Porphyrio porphyrio",
157
+ "137": "American coot, marsh hen, mud hen, water hen, Fulica americana",
158
+ "138": "bustard",
159
+ "139": "ruddy turnstone, Arenaria interpres",
160
+ "140": "red-backed sandpiper, dunlin, Erolia alpina",
161
+ "141": "redshank, Tringa totanus",
162
+ "142": "dowitcher",
163
+ "143": "oystercatcher, oyster catcher",
164
+ "144": "pelican",
165
+ "145": "king penguin, Aptenodytes patagonica",
166
+ "146": "albatross, mollymawk",
167
+ "147": "grey whale, gray whale, devilfish, Eschrichtius gibbosus, Eschrichtius robustus",
168
+ "148": "killer whale, killer, orca, grampus, sea wolf, Orcinus orca",
169
+ "149": "dugong, Dugong dugon",
170
+ "150": "sea lion",
171
+ "151": "Chihuahua",
172
+ "152": "Japanese spaniel",
173
+ "153": "Maltese dog, Maltese terrier, Maltese",
174
+ "154": "Pekinese, Pekingese, Peke",
175
+ "155": "Shih-Tzu",
176
+ "156": "Blenheim spaniel",
177
+ "157": "papillon",
178
+ "158": "toy terrier",
179
+ "159": "Rhodesian ridgeback",
180
+ "160": "Afghan hound, Afghan",
181
+ "161": "basset, basset hound",
182
+ "162": "beagle",
183
+ "163": "bloodhound, sleuthhound",
184
+ "164": "bluetick",
185
+ "165": "black-and-tan coonhound",
186
+ "166": "Walker hound, Walker foxhound",
187
+ "167": "English foxhound",
188
+ "168": "redbone",
189
+ "169": "borzoi, Russian wolfhound",
190
+ "170": "Irish wolfhound",
191
+ "171": "Italian greyhound",
192
+ "172": "whippet",
193
+ "173": "Ibizan hound, Ibizan Podenco",
194
+ "174": "Norwegian elkhound, elkhound",
195
+ "175": "otterhound, otter hound",
196
+ "176": "Saluki, gazelle hound",
197
+ "177": "Scottish deerhound, deerhound",
198
+ "178": "Weimaraner",
199
+ "179": "Staffordshire bullterrier, Staffordshire bull terrier",
200
+ "180": "American Staffordshire terrier, Staffordshire terrier, American pit bull terrier, pit bull terrier",
201
+ "181": "Bedlington terrier",
202
+ "182": "Border terrier",
203
+ "183": "Kerry blue terrier",
204
+ "184": "Irish terrier",
205
+ "185": "Norfolk terrier",
206
+ "186": "Norwich terrier",
207
+ "187": "Yorkshire terrier",
208
+ "188": "wire-haired fox terrier",
209
+ "189": "Lakeland terrier",
210
+ "190": "Sealyham terrier, Sealyham",
211
+ "191": "Airedale, Airedale terrier",
212
+ "192": "cairn, cairn terrier",
213
+ "193": "Australian terrier",
214
+ "194": "Dandie Dinmont, Dandie Dinmont terrier",
215
+ "195": "Boston bull, Boston terrier",
216
+ "196": "miniature schnauzer",
217
+ "197": "giant schnauzer",
218
+ "198": "standard schnauzer",
219
+ "199": "Scotch terrier, Scottish terrier, Scottie",
220
+ "200": "Tibetan terrier, chrysanthemum dog",
221
+ "201": "silky terrier, Sydney silky",
222
+ "202": "soft-coated wheaten terrier",
223
+ "203": "West Highland white terrier",
224
+ "204": "Lhasa, Lhasa apso",
225
+ "205": "flat-coated retriever",
226
+ "206": "curly-coated retriever",
227
+ "207": "golden retriever",
228
+ "208": "Labrador retriever",
229
+ "209": "Chesapeake Bay retriever",
230
+ "210": "German short-haired pointer",
231
+ "211": "vizsla, Hungarian pointer",
232
+ "212": "English setter",
233
+ "213": "Irish setter, red setter",
234
+ "214": "Gordon setter",
235
+ "215": "Brittany spaniel",
236
+ "216": "clumber, clumber spaniel",
237
+ "217": "English springer, English springer spaniel",
238
+ "218": "Welsh springer spaniel",
239
+ "219": "cocker spaniel, English cocker spaniel, cocker",
240
+ "220": "Sussex spaniel",
241
+ "221": "Irish water spaniel",
242
+ "222": "kuvasz",
243
+ "223": "schipperke",
244
+ "224": "groenendael",
245
+ "225": "malinois",
246
+ "226": "briard",
247
+ "227": "kelpie",
248
+ "228": "komondor",
249
+ "229": "Old English sheepdog, bobtail",
250
+ "230": "Shetland sheepdog, Shetland sheep dog, Shetland",
251
+ "231": "collie",
252
+ "232": "Border collie",
253
+ "233": "Bouvier des Flandres, Bouviers des Flandres",
254
+ "234": "Rottweiler",
255
+ "235": "German shepherd, German shepherd dog, German police dog, alsatian",
256
+ "236": "Doberman, Doberman pinscher",
257
+ "237": "miniature pinscher",
258
+ "238": "Greater Swiss Mountain dog",
259
+ "239": "Bernese mountain dog",
260
+ "240": "Appenzeller",
261
+ "241": "EntleBucher",
262
+ "242": "boxer",
263
+ "243": "bull mastiff",
264
+ "244": "Tibetan mastiff",
265
+ "245": "French bulldog",
266
+ "246": "Great Dane",
267
+ "247": "Saint Bernard, St Bernard",
268
+ "248": "Eskimo dog, husky",
269
+ "249": "malamute, malemute, Alaskan malamute",
270
+ "250": "Siberian husky",
271
+ "251": "dalmatian, coach dog, carriage dog",
272
+ "252": "affenpinscher, monkey pinscher, monkey dog",
273
+ "253": "basenji",
274
+ "254": "pug, pug-dog",
275
+ "255": "Leonberg",
276
+ "256": "Newfoundland, Newfoundland dog",
277
+ "257": "Great Pyrenees",
278
+ "258": "Samoyed, Samoyede",
279
+ "259": "Pomeranian",
280
+ "260": "chow, chow chow",
281
+ "261": "keeshond",
282
+ "262": "Brabancon griffon",
283
+ "263": "Pembroke, Pembroke Welsh corgi",
284
+ "264": "Cardigan, Cardigan Welsh corgi",
285
+ "265": "toy poodle",
286
+ "266": "miniature poodle",
287
+ "267": "standard poodle",
288
+ "268": "Mexican hairless",
289
+ "269": "timber wolf, grey wolf, gray wolf, Canis lupus",
290
+ "270": "white wolf, Arctic wolf, Canis lupus tundrarum",
291
+ "271": "red wolf, maned wolf, Canis rufus, Canis niger",
292
+ "272": "coyote, prairie wolf, brush wolf, Canis latrans",
293
+ "273": "dingo, warrigal, warragal, Canis dingo",
294
+ "274": "dhole, Cuon alpinus",
295
+ "275": "African hunting dog, hyena dog, Cape hunting dog, Lycaon pictus",
296
+ "276": "hyena, hyaena",
297
+ "277": "red fox, Vulpes vulpes",
298
+ "278": "kit fox, Vulpes macrotis",
299
+ "279": "Arctic fox, white fox, Alopex lagopus",
300
+ "280": "grey fox, gray fox, Urocyon cinereoargenteus",
301
+ "281": "tabby, tabby cat",
302
+ "282": "tiger cat",
303
+ "283": "Persian cat",
304
+ "284": "Siamese cat, Siamese",
305
+ "285": "Egyptian cat",
306
+ "286": "cougar, puma, catamount, mountain lion, painter, panther, Felis concolor",
307
+ "287": "lynx, catamount",
308
+ "288": "leopard, Panthera pardus",
309
+ "289": "snow leopard, ounce, Panthera uncia",
310
+ "290": "jaguar, panther, Panthera onca, Felis onca",
311
+ "291": "lion, king of beasts, Panthera leo",
312
+ "292": "tiger, Panthera tigris",
313
+ "293": "cheetah, chetah, Acinonyx jubatus",
314
+ "294": "brown bear, bruin, Ursus arctos",
315
+ "295": "American black bear, black bear, Ursus americanus, Euarctos americanus",
316
+ "296": "ice bear, polar bear, Ursus Maritimus, Thalarctos maritimus",
317
+ "297": "sloth bear, Melursus ursinus, Ursus ursinus",
318
+ "298": "mongoose",
319
+ "299": "meerkat, mierkat",
320
+ "300": "tiger beetle",
321
+ "301": "ladybug, ladybeetle, lady beetle, ladybird, ladybird beetle",
322
+ "302": "ground beetle, carabid beetle",
323
+ "303": "long-horned beetle, longicorn, longicorn beetle",
324
+ "304": "leaf beetle, chrysomelid",
325
+ "305": "dung beetle",
326
+ "306": "rhinoceros beetle",
327
+ "307": "weevil",
328
+ "308": "fly",
329
+ "309": "bee",
330
+ "310": "ant, emmet, pismire",
331
+ "311": "grasshopper, hopper",
332
+ "312": "cricket",
333
+ "313": "walking stick, walkingstick, stick insect",
334
+ "314": "cockroach, roach",
335
+ "315": "mantis, mantid",
336
+ "316": "cicada, cicala",
337
+ "317": "leafhopper",
338
+ "318": "lacewing, lacewing fly",
339
+ "319": "dragonfly, darning needle, devils darning needle, sewing needle, snake feeder, snake doctor, mosquito hawk, skeeter hawk",
340
+ "320": "damselfly",
341
+ "321": "admiral",
342
+ "322": "ringlet, ringlet butterfly",
343
+ "323": "monarch, monarch butterfly, milkweed butterfly, Danaus plexippus",
344
+ "324": "cabbage butterfly",
345
+ "325": "sulphur butterfly, sulfur butterfly",
346
+ "326": "lycaenid, lycaenid butterfly",
347
+ "327": "starfish, sea star",
348
+ "328": "sea urchin",
349
+ "329": "sea cucumber, holothurian",
350
+ "330": "wood rabbit, cottontail, cottontail rabbit",
351
+ "331": "hare",
352
+ "332": "Angora, Angora rabbit",
353
+ "333": "hamster",
354
+ "334": "porcupine, hedgehog",
355
+ "335": "fox squirrel, eastern fox squirrel, Sciurus niger",
356
+ "336": "marmot",
357
+ "337": "beaver",
358
+ "338": "guinea pig, Cavia cobaya",
359
+ "339": "sorrel",
360
+ "340": "zebra",
361
+ "341": "hog, pig, grunter, squealer, Sus scrofa",
362
+ "342": "wild boar, boar, Sus scrofa",
363
+ "343": "warthog",
364
+ "344": "hippopotamus, hippo, river horse, Hippopotamus amphibius",
365
+ "345": "ox",
366
+ "346": "water buffalo, water ox, Asiatic buffalo, Bubalus bubalis",
367
+ "347": "bison",
368
+ "348": "ram, tup",
369
+ "349": "bighorn, bighorn sheep, cimarron, Rocky Mountain bighorn, Rocky Mountain sheep, Ovis canadensis",
370
+ "350": "ibex, Capra ibex",
371
+ "351": "hartebeest",
372
+ "352": "impala, Aepyceros melampus",
373
+ "353": "gazelle",
374
+ "354": "Arabian camel, dromedary, Camelus dromedarius",
375
+ "355": "llama",
376
+ "356": "weasel",
377
+ "357": "mink",
378
+ "358": "polecat, fitch, foulmart, foumart, Mustela putorius",
379
+ "359": "black-footed ferret, ferret, Mustela nigripes",
380
+ "360": "otter",
381
+ "361": "skunk, polecat, wood pussy",
382
+ "362": "badger",
383
+ "363": "armadillo",
384
+ "364": "three-toed sloth, ai, Bradypus tridactylus",
385
+ "365": "orangutan, orang, orangutang, Pongo pygmaeus",
386
+ "366": "gorilla, Gorilla gorilla",
387
+ "367": "chimpanzee, chimp, Pan troglodytes",
388
+ "368": "gibbon, Hylobates lar",
389
+ "369": "siamang, Hylobates syndactylus, Symphalangus syndactylus",
390
+ "370": "guenon, guenon monkey",
391
+ "371": "patas, hussar monkey, Erythrocebus patas",
392
+ "372": "baboon",
393
+ "373": "macaque",
394
+ "374": "langur",
395
+ "375": "colobus, colobus monkey",
396
+ "376": "proboscis monkey, Nasalis larvatus",
397
+ "377": "marmoset",
398
+ "378": "capuchin, ringtail, Cebus capucinus",
399
+ "379": "howler monkey, howler",
400
+ "380": "titi, titi monkey",
401
+ "381": "spider monkey, Ateles geoffroyi",
402
+ "382": "squirrel monkey, Saimiri sciureus",
403
+ "383": "Madagascar cat, ring-tailed lemur, Lemur catta",
404
+ "384": "indri, indris, Indri indri, Indri brevicaudatus",
405
+ "385": "Indian elephant, Elephas maximus",
406
+ "386": "African elephant, Loxodonta africana",
407
+ "387": "lesser panda, red panda, panda, bear cat, cat bear, Ailurus fulgens",
408
+ "388": "giant panda, panda, panda bear, coon bear, Ailuropoda melanoleuca",
409
+ "389": "barracouta, snoek",
410
+ "390": "eel",
411
+ "391": "coho, cohoe, coho salmon, blue jack, silver salmon, Oncorhynchus kisutch",
412
+ "392": "rock beauty, Holocanthus tricolor",
413
+ "393": "anemone fish",
414
+ "394": "sturgeon",
415
+ "395": "gar, garfish, garpike, billfish, Lepisosteus osseus",
416
+ "396": "lionfish",
417
+ "397": "puffer, pufferfish, blowfish, globefish",
418
+ "398": "abacus",
419
+ "399": "abaya",
420
+ "400": "academic gown, academic robe, judge robe",
421
+ "401": "accordion, piano accordion, squeeze box",
422
+ "402": "acoustic guitar",
423
+ "403": "aircraft carrier, carrier, flattop, attack aircraft carrier",
424
+ "404": "airliner",
425
+ "405": "airship, dirigible",
426
+ "406": "altar",
427
+ "407": "ambulance",
428
+ "408": "amphibian, amphibious vehicle",
429
+ "409": "analog clock",
430
+ "410": "apiary, bee house",
431
+ "411": "apron",
432
+ "412": "ashcan, trash can, garbage can, wastebin, ash bin, ash-bin, ashbin, dustbin, trash barrel, trash bin",
433
+ "413": "assault rifle, assault gun",
434
+ "414": "backpack, back pack, knapsack, packsack, rucksack, haversack",
435
+ "415": "bakery, bakeshop, bakehouse",
436
+ "416": "balance beam, beam",
437
+ "417": "balloon",
438
+ "418": "ballpoint, ballpoint pen, ballpen, Biro",
439
+ "419": "Band Aid",
440
+ "420": "banjo",
441
+ "421": "bannister, banister, balustrade, balusters, handrail",
442
+ "422": "barbell",
443
+ "423": "barber chair",
444
+ "424": "barbershop",
445
+ "425": "barn",
446
+ "426": "barometer",
447
+ "427": "barrel, cask",
448
+ "428": "barrow, garden cart, lawn cart, wheelbarrow",
449
+ "429": "baseball",
450
+ "430": "basketball",
451
+ "431": "bassinet",
452
+ "432": "bassoon",
453
+ "433": "bathing cap, swimming cap",
454
+ "434": "bath towel",
455
+ "435": "bathtub, bathing tub, bath, tub",
456
+ "436": "beach wagon, station wagon, wagon, estate car, beach waggon, station waggon, waggon",
457
+ "437": "beacon, lighthouse, beacon light, pharos",
458
+ "438": "beaker",
459
+ "439": "bearskin, busby, shako",
460
+ "440": "beer bottle",
461
+ "441": "beer glass",
462
+ "442": "bell cote, bell cot",
463
+ "443": "bib",
464
+ "444": "bicycle-built-for-two, tandem bicycle, tandem",
465
+ "445": "bikini, two-piece",
466
+ "446": "binder, ring-binder",
467
+ "447": "binoculars, field glasses, opera glasses",
468
+ "448": "birdhouse",
469
+ "449": "boathouse",
470
+ "450": "bobsled, bobsleigh, bob",
471
+ "451": "bolo tie, bolo, bola tie, bola",
472
+ "452": "bonnet, poke bonnet",
473
+ "453": "bookcase",
474
+ "454": "bookshop, bookstore, bookstall",
475
+ "455": "bottlecap",
476
+ "456": "bow",
477
+ "457": "bow tie, bow-tie, bowtie",
478
+ "458": "brass, memorial tablet, plaque",
479
+ "459": "brassiere, bra, bandeau",
480
+ "460": "breakwater, groin, groyne, mole, bulwark, seawall, jetty",
481
+ "461": "breastplate, aegis, egis",
482
+ "462": "broom",
483
+ "463": "bucket, pail",
484
+ "464": "buckle",
485
+ "465": "bulletproof vest",
486
+ "466": "bullet train, bullet",
487
+ "467": "butcher shop, meat market",
488
+ "468": "cab, hack, taxi, taxicab",
489
+ "469": "caldron, cauldron",
490
+ "470": "candle, taper, wax light",
491
+ "471": "cannon",
492
+ "472": "canoe",
493
+ "473": "can opener, tin opener",
494
+ "474": "cardigan",
495
+ "475": "car mirror",
496
+ "476": "carousel, carrousel, merry-go-round, roundabout, whirligig",
497
+ "477": "carpenters kit, tool kit",
498
+ "478": "carton",
499
+ "479": "car wheel",
500
+ "480": "cash machine, cash dispenser, automated teller machine, automatic teller machine, automated teller, automatic teller, ATM",
501
+ "481": "cassette",
502
+ "482": "cassette player",
503
+ "483": "castle",
504
+ "484": "catamaran",
505
+ "485": "CD player",
506
+ "486": "cello, violoncello",
507
+ "487": "cellular telephone, cellular phone, cellphone, cell, mobile phone",
508
+ "488": "chain",
509
+ "489": "chainlink fence",
510
+ "490": "chain mail, ring mail, mail, chain armor, chain armour, ring armor, ring armour",
511
+ "491": "chain saw, chainsaw",
512
+ "492": "chest",
513
+ "493": "chiffonier, commode",
514
+ "494": "chime, bell, gong",
515
+ "495": "china cabinet, china closet",
516
+ "496": "Christmas stocking",
517
+ "497": "church, church building",
518
+ "498": "cinema, movie theater, movie theatre, movie house, picture palace",
519
+ "499": "cleaver, meat cleaver, chopper",
520
+ "500": "cliff dwelling",
521
+ "501": "cloak",
522
+ "502": "clog, geta, patten, sabot",
523
+ "503": "cocktail shaker",
524
+ "504": "coffee mug",
525
+ "505": "coffeepot",
526
+ "506": "coil, spiral, volute, whorl, helix",
527
+ "507": "combination lock",
528
+ "508": "computer keyboard, keypad",
529
+ "509": "confectionery, confectionary, candy store",
530
+ "510": "container ship, containership, container vessel",
531
+ "511": "convertible",
532
+ "512": "corkscrew, bottle screw",
533
+ "513": "cornet, horn, trumpet, trump",
534
+ "514": "cowboy boot",
535
+ "515": "cowboy hat, ten-gallon hat",
536
+ "516": "cradle",
537
+ "517": "crane",
538
+ "518": "crash helmet",
539
+ "519": "crate",
540
+ "520": "crib, cot",
541
+ "521": "Crock Pot",
542
+ "522": "croquet ball",
543
+ "523": "crutch",
544
+ "524": "cuirass",
545
+ "525": "dam, dike, dyke",
546
+ "526": "desk",
547
+ "527": "desktop computer",
548
+ "528": "dial telephone, dial phone",
549
+ "529": "diaper, nappy, napkin",
550
+ "530": "digital clock",
551
+ "531": "digital watch",
552
+ "532": "dining table, board",
553
+ "533": "dishrag, dishcloth",
554
+ "534": "dishwasher, dish washer, dishwashing machine",
555
+ "535": "disk brake, disc brake",
556
+ "536": "dock, dockage, docking facility",
557
+ "537": "dogsled, dog sled, dog sleigh",
558
+ "538": "dome",
559
+ "539": "doormat, welcome mat",
560
+ "540": "drilling platform, offshore rig",
561
+ "541": "drum, membranophone, tympan",
562
+ "542": "drumstick",
563
+ "543": "dumbbell",
564
+ "544": "Dutch oven",
565
+ "545": "electric fan, blower",
566
+ "546": "electric guitar",
567
+ "547": "electric locomotive",
568
+ "548": "entertainment center",
569
+ "549": "envelope",
570
+ "550": "espresso maker",
571
+ "551": "face powder",
572
+ "552": "feather boa, boa",
573
+ "553": "file, file cabinet, filing cabinet",
574
+ "554": "fireboat",
575
+ "555": "fire engine, fire truck",
576
+ "556": "fire screen, fireguard",
577
+ "557": "flagpole, flagstaff",
578
+ "558": "flute, transverse flute",
579
+ "559": "folding chair",
580
+ "560": "football helmet",
581
+ "561": "forklift",
582
+ "562": "fountain",
583
+ "563": "fountain pen",
584
+ "564": "four-poster",
585
+ "565": "freight car",
586
+ "566": "French horn, horn",
587
+ "567": "frying pan, frypan, skillet",
588
+ "568": "fur coat",
589
+ "569": "garbage truck, dustcart",
590
+ "570": "gasmask, respirator, gas helmet",
591
+ "571": "gas pump, gasoline pump, petrol pump, island dispenser",
592
+ "572": "goblet",
593
+ "573": "go-kart",
594
+ "574": "golf ball",
595
+ "575": "golfcart, golf cart",
596
+ "576": "gondola",
597
+ "577": "gong, tam-tam",
598
+ "578": "gown",
599
+ "579": "grand piano, grand",
600
+ "580": "greenhouse, nursery, glasshouse",
601
+ "581": "grille, radiator grille",
602
+ "582": "grocery store, grocery, food market, market",
603
+ "583": "guillotine",
604
+ "584": "hair slide",
605
+ "585": "hair spray",
606
+ "586": "half track",
607
+ "587": "hammer",
608
+ "588": "hamper",
609
+ "589": "hand blower, blow dryer, blow drier, hair dryer, hair drier",
610
+ "590": "hand-held computer, hand-held microcomputer",
611
+ "591": "handkerchief, hankie, hanky, hankey",
612
+ "592": "hard disc, hard disk, fixed disk",
613
+ "593": "harmonica, mouth organ, harp, mouth harp",
614
+ "594": "harp",
615
+ "595": "harvester, reaper",
616
+ "596": "hatchet",
617
+ "597": "holster",
618
+ "598": "home theater, home theatre",
619
+ "599": "honeycomb",
620
+ "600": "hook, claw",
621
+ "601": "hoopskirt, crinoline",
622
+ "602": "horizontal bar, high bar",
623
+ "603": "horse cart, horse-cart",
624
+ "604": "hourglass",
625
+ "605": "iPod",
626
+ "606": "iron, smoothing iron",
627
+ "607": "jack-o-lantern",
628
+ "608": "jean, blue jean, denim",
629
+ "609": "jeep, landrover",
630
+ "610": "jersey, T-shirt, tee shirt",
631
+ "611": "jigsaw puzzle",
632
+ "612": "jinrikisha, ricksha, rickshaw",
633
+ "613": "joystick",
634
+ "614": "kimono",
635
+ "615": "knee pad",
636
+ "616": "knot",
637
+ "617": "lab coat, laboratory coat",
638
+ "618": "ladle",
639
+ "619": "lampshade, lamp shade",
640
+ "620": "laptop, laptop computer",
641
+ "621": "lawn mower, mower",
642
+ "622": "lens cap, lens cover",
643
+ "623": "letter opener, paper knife, paperknife",
644
+ "624": "library",
645
+ "625": "lifeboat",
646
+ "626": "lighter, light, igniter, ignitor",
647
+ "627": "limousine, limo",
648
+ "628": "liner, ocean liner",
649
+ "629": "lipstick, lip rouge",
650
+ "630": "Loafer",
651
+ "631": "lotion",
652
+ "632": "loudspeaker, speaker, speaker unit, loudspeaker system, speaker system",
653
+ "633": "loupe, jewelers loupe",
654
+ "634": "lumbermill, sawmill",
655
+ "635": "magnetic compass",
656
+ "636": "mailbag, postbag",
657
+ "637": "mailbox, letter box",
658
+ "638": "maillot",
659
+ "639": "maillot, tank suit",
660
+ "640": "manhole cover",
661
+ "641": "maraca",
662
+ "642": "marimba, xylophone",
663
+ "643": "mask",
664
+ "644": "matchstick",
665
+ "645": "maypole",
666
+ "646": "maze, labyrinth",
667
+ "647": "measuring cup",
668
+ "648": "medicine chest, medicine cabinet",
669
+ "649": "megalith, megalithic structure",
670
+ "650": "microphone, mike",
671
+ "651": "microwave, microwave oven",
672
+ "652": "military uniform",
673
+ "653": "milk can",
674
+ "654": "minibus",
675
+ "655": "miniskirt, mini",
676
+ "656": "minivan",
677
+ "657": "missile",
678
+ "658": "mitten",
679
+ "659": "mixing bowl",
680
+ "660": "mobile home, manufactured home",
681
+ "661": "Model T",
682
+ "662": "modem",
683
+ "663": "monastery",
684
+ "664": "monitor",
685
+ "665": "moped",
686
+ "666": "mortar",
687
+ "667": "mortarboard",
688
+ "668": "mosque",
689
+ "669": "mosquito net",
690
+ "670": "motor scooter, scooter",
691
+ "671": "mountain bike, all-terrain bike, off-roader",
692
+ "672": "mountain tent",
693
+ "673": "mouse, computer mouse",
694
+ "674": "mousetrap",
695
+ "675": "moving van",
696
+ "676": "muzzle",
697
+ "677": "nail",
698
+ "678": "neck brace",
699
+ "679": "necklace",
700
+ "680": "nipple",
701
+ "681": "notebook, notebook computer",
702
+ "682": "obelisk",
703
+ "683": "oboe, hautboy, hautbois",
704
+ "684": "ocarina, sweet potato",
705
+ "685": "odometer, hodometer, mileometer, milometer",
706
+ "686": "oil filter",
707
+ "687": "organ, pipe organ",
708
+ "688": "oscilloscope, scope, cathode-ray oscilloscope, CRO",
709
+ "689": "overskirt",
710
+ "690": "oxcart",
711
+ "691": "oxygen mask",
712
+ "692": "packet",
713
+ "693": "paddle, boat paddle",
714
+ "694": "paddlewheel, paddle wheel",
715
+ "695": "padlock",
716
+ "696": "paintbrush",
717
+ "697": "pajama, pyjama, pjs, jammies",
718
+ "698": "palace",
719
+ "699": "panpipe, pandean pipe, syrinx",
720
+ "700": "paper towel",
721
+ "701": "parachute, chute",
722
+ "702": "parallel bars, bars",
723
+ "703": "park bench",
724
+ "704": "parking meter",
725
+ "705": "passenger car, coach, carriage",
726
+ "706": "patio, terrace",
727
+ "707": "pay-phone, pay-station",
728
+ "708": "pedestal, plinth, footstall",
729
+ "709": "pencil box, pencil case",
730
+ "710": "pencil sharpener",
731
+ "711": "perfume, essence",
732
+ "712": "Petri dish",
733
+ "713": "photocopier",
734
+ "714": "pick, plectrum, plectron",
735
+ "715": "pickelhaube",
736
+ "716": "picket fence, paling",
737
+ "717": "pickup, pickup truck",
738
+ "718": "pier",
739
+ "719": "piggy bank, penny bank",
740
+ "720": "pill bottle",
741
+ "721": "pillow",
742
+ "722": "ping-pong ball",
743
+ "723": "pinwheel",
744
+ "724": "pirate, pirate ship",
745
+ "725": "pitcher, ewer",
746
+ "726": "plane, carpenters plane, woodworking plane",
747
+ "727": "planetarium",
748
+ "728": "plastic bag",
749
+ "729": "plate rack",
750
+ "730": "plow, plough",
751
+ "731": "plunger, plumbers helper",
752
+ "732": "Polaroid camera, Polaroid Land camera",
753
+ "733": "pole",
754
+ "734": "police van, police wagon, paddy wagon, patrol wagon, wagon, black Maria",
755
+ "735": "poncho",
756
+ "736": "pool table, billiard table, snooker table",
757
+ "737": "pop bottle, soda bottle",
758
+ "738": "pot, flowerpot",
759
+ "739": "potters wheel",
760
+ "740": "power drill",
761
+ "741": "prayer rug, prayer mat",
762
+ "742": "printer",
763
+ "743": "prison, prison house",
764
+ "744": "projectile, missile",
765
+ "745": "projector",
766
+ "746": "puck, hockey puck",
767
+ "747": "punching bag, punch bag, punching ball, punchball",
768
+ "748": "purse",
769
+ "749": "quill, quill pen",
770
+ "750": "quilt, comforter, comfort, puff",
771
+ "751": "racer, race car, racing car",
772
+ "752": "racket, racquet",
773
+ "753": "radiator",
774
+ "754": "radio, wireless",
775
+ "755": "radio telescope, radio reflector",
776
+ "756": "rain barrel",
777
+ "757": "recreational vehicle, RV, R.V.",
778
+ "758": "reel",
779
+ "759": "reflex camera",
780
+ "760": "refrigerator, icebox",
781
+ "761": "remote control, remote",
782
+ "762": "restaurant, eating house, eating place, eatery",
783
+ "763": "revolver, six-gun, six-shooter",
784
+ "764": "rifle",
785
+ "765": "rocking chair, rocker",
786
+ "766": "rotisserie",
787
+ "767": "rubber eraser, rubber, pencil eraser",
788
+ "768": "rugby ball",
789
+ "769": "rule, ruler",
790
+ "770": "running shoe",
791
+ "771": "safe",
792
+ "772": "safety pin",
793
+ "773": "saltshaker, salt shaker",
794
+ "774": "sandal",
795
+ "775": "sarong",
796
+ "776": "sax, saxophone",
797
+ "777": "scabbard",
798
+ "778": "scale, weighing machine",
799
+ "779": "school bus",
800
+ "780": "schooner",
801
+ "781": "scoreboard",
802
+ "782": "screen, CRT screen",
803
+ "783": "screw",
804
+ "784": "screwdriver",
805
+ "785": "seat belt, seatbelt",
806
+ "786": "sewing machine",
807
+ "787": "shield, buckler",
808
+ "788": "shoe shop, shoe-shop, shoe store",
809
+ "789": "shoji",
810
+ "790": "shopping basket",
811
+ "791": "shopping cart",
812
+ "792": "shovel",
813
+ "793": "shower cap",
814
+ "794": "shower curtain",
815
+ "795": "ski",
816
+ "796": "ski mask",
817
+ "797": "sleeping bag",
818
+ "798": "slide rule, slipstick",
819
+ "799": "sliding door",
820
+ "800": "slot, one-armed bandit",
821
+ "801": "snorkel",
822
+ "802": "snowmobile",
823
+ "803": "snowplow, snowplough",
824
+ "804": "soap dispenser",
825
+ "805": "soccer ball",
826
+ "806": "sock",
827
+ "807": "solar dish, solar collector, solar furnace",
828
+ "808": "sombrero",
829
+ "809": "soup bowl",
830
+ "810": "space bar",
831
+ "811": "space heater",
832
+ "812": "space shuttle",
833
+ "813": "spatula",
834
+ "814": "speedboat",
835
+ "815": "spider web, spiders web",
836
+ "816": "spindle",
837
+ "817": "sports car, sport car",
838
+ "818": "spotlight, spot",
839
+ "819": "stage",
840
+ "820": "steam locomotive",
841
+ "821": "steel arch bridge",
842
+ "822": "steel drum",
843
+ "823": "stethoscope",
844
+ "824": "stole",
845
+ "825": "stone wall",
846
+ "826": "stopwatch, stop watch",
847
+ "827": "stove",
848
+ "828": "strainer",
849
+ "829": "streetcar, tram, tramcar, trolley, trolley car",
850
+ "830": "stretcher",
851
+ "831": "studio couch, day bed",
852
+ "832": "stupa, tope",
853
+ "833": "submarine, pigboat, sub, U-boat",
854
+ "834": "suit, suit of clothes",
855
+ "835": "sundial",
856
+ "836": "sunglass",
857
+ "837": "sunglasses, dark glasses, shades",
858
+ "838": "sunscreen, sunblock, sun blocker",
859
+ "839": "suspension bridge",
860
+ "840": "swab, swob, mop",
861
+ "841": "sweatshirt",
862
+ "842": "swimming trunks, bathing trunks",
863
+ "843": "swing",
864
+ "844": "switch, electric switch, electrical switch",
865
+ "845": "syringe",
866
+ "846": "table lamp",
867
+ "847": "tank, army tank, armored combat vehicle, armoured combat vehicle",
868
+ "848": "tape player",
869
+ "849": "teapot",
870
+ "850": "teddy, teddy bear",
871
+ "851": "television, television system",
872
+ "852": "tennis ball",
873
+ "853": "thatch, thatched roof",
874
+ "854": "theater curtain, theatre curtain",
875
+ "855": "thimble",
876
+ "856": "thresher, thrasher, threshing machine",
877
+ "857": "throne",
878
+ "858": "tile roof",
879
+ "859": "toaster",
880
+ "860": "tobacco shop, tobacconist shop, tobacconist",
881
+ "861": "toilet seat",
882
+ "862": "torch",
883
+ "863": "totem pole",
884
+ "864": "tow truck, tow car, wrecker",
885
+ "865": "toyshop",
886
+ "866": "tractor",
887
+ "867": "trailer truck, tractor trailer, trucking rig, rig, articulated lorry, semi",
888
+ "868": "tray",
889
+ "869": "trench coat",
890
+ "870": "tricycle, trike, velocipede",
891
+ "871": "trimaran",
892
+ "872": "tripod",
893
+ "873": "triumphal arch",
894
+ "874": "trolleybus, trolley coach, trackless trolley",
895
+ "875": "trombone",
896
+ "876": "tub, vat",
897
+ "877": "turnstile",
898
+ "878": "typewriter keyboard",
899
+ "879": "umbrella",
900
+ "880": "unicycle, monocycle",
901
+ "881": "upright, upright piano",
902
+ "882": "vacuum, vacuum cleaner",
903
+ "883": "vase",
904
+ "884": "vault",
905
+ "885": "velvet",
906
+ "886": "vending machine",
907
+ "887": "vestment",
908
+ "888": "viaduct",
909
+ "889": "violin, fiddle",
910
+ "890": "volleyball",
911
+ "891": "waffle iron",
912
+ "892": "wall clock",
913
+ "893": "wallet, billfold, notecase, pocketbook",
914
+ "894": "wardrobe, closet, press",
915
+ "895": "warplane, military plane",
916
+ "896": "washbasin, handbasin, washbowl, lavabo, wash-hand basin",
917
+ "897": "washer, automatic washer, washing machine",
918
+ "898": "water bottle",
919
+ "899": "water jug",
920
+ "900": "water tower",
921
+ "901": "whiskey jug",
922
+ "902": "whistle",
923
+ "903": "wig",
924
+ "904": "window screen",
925
+ "905": "window shade",
926
+ "906": "Windsor tie",
927
+ "907": "wine bottle",
928
+ "908": "wing",
929
+ "909": "wok",
930
+ "910": "wooden spoon",
931
+ "911": "wool, woolen, woollen",
932
+ "912": "worm fence, snake fence, snake-rail fence, Virginia fence",
933
+ "913": "wreck",
934
+ "914": "yawl",
935
+ "915": "yurt",
936
+ "916": "web site, website, internet site, site",
937
+ "917": "comic book",
938
+ "918": "crossword puzzle, crossword",
939
+ "919": "street sign",
940
+ "920": "traffic light, traffic signal, stoplight",
941
+ "921": "book jacket, dust cover, dust jacket, dust wrapper",
942
+ "922": "menu",
943
+ "923": "plate",
944
+ "924": "guacamole",
945
+ "925": "consomme",
946
+ "926": "hot pot, hotpot",
947
+ "927": "trifle",
948
+ "928": "ice cream, icecream",
949
+ "929": "ice lolly, lolly, lollipop, popsicle",
950
+ "930": "French loaf",
951
+ "931": "bagel, beigel",
952
+ "932": "pretzel",
953
+ "933": "cheeseburger",
954
+ "934": "hotdog, hot dog, red hot",
955
+ "935": "mashed potato",
956
+ "936": "head cabbage",
957
+ "937": "broccoli",
958
+ "938": "cauliflower",
959
+ "939": "zucchini, courgette",
960
+ "940": "spaghetti squash",
961
+ "941": "acorn squash",
962
+ "942": "butternut squash",
963
+ "943": "cucumber, cuke",
964
+ "944": "artichoke, globe artichoke",
965
+ "945": "bell pepper",
966
+ "946": "cardoon",
967
+ "947": "mushroom",
968
+ "948": "Granny Smith",
969
+ "949": "strawberry",
970
+ "950": "orange",
971
+ "951": "lemon",
972
+ "952": "fig",
973
+ "953": "pineapple, ananas",
974
+ "954": "banana",
975
+ "955": "jackfruit, jak, jack",
976
+ "956": "custard apple",
977
+ "957": "pomegranate",
978
+ "958": "hay",
979
+ "959": "carbonara",
980
+ "960": "chocolate sauce, chocolate syrup",
981
+ "961": "dough",
982
+ "962": "meat loaf, meatloaf",
983
+ "963": "pizza, pizza pie",
984
+ "964": "potpie",
985
+ "965": "burrito",
986
+ "966": "red wine",
987
+ "967": "espresso",
988
+ "968": "cup",
989
+ "969": "eggnog",
990
+ "970": "alp",
991
+ "971": "bubble",
992
+ "972": "cliff, drop, drop-off",
993
+ "973": "coral reef",
994
+ "974": "geyser",
995
+ "975": "lakeside, lakeshore",
996
+ "976": "promontory, headland, head, foreland",
997
+ "977": "sandbar, sand bar",
998
+ "978": "seashore, coast, seacoast, sea-coast",
999
+ "979": "valley, vale",
1000
+ "980": "volcano",
1001
+ "981": "ballplayer, baseball player",
1002
+ "982": "groom, bridegroom",
1003
+ "983": "scuba diver",
1004
+ "984": "rapeseed",
1005
+ "985": "daisy",
1006
+ "986": "yellow ladys slipper, yellow lady-slipper, Cypripedium calceolus, Cypripedium parviflorum",
1007
+ "987": "corn",
1008
+ "988": "acorn",
1009
+ "989": "hip, rose hip, rosehip",
1010
+ "990": "buckeye, horse chestnut, conker",
1011
+ "991": "coral fungus",
1012
+ "992": "agaric",
1013
+ "993": "gyromitra",
1014
+ "994": "stinkhorn, carrion fungus",
1015
+ "995": "earthstar",
1016
+ "996": "hen-of-the-woods, hen of the woods, Polyporus frondosus, Grifola frondosa",
1017
+ "997": "bolete",
1018
+ "998": "ear, spike, capitulum",
1019
+ "999": "toilet tissue, toilet paper, bathroom tissue"
1020
+ }
1021
+ }
PixelDiT2-H-16-512/pipeline.py ADDED
@@ -0,0 +1,839 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2026 The HuggingFace Team. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import importlib.util
16
+ import inspect
17
+ import json
18
+ import sys
19
+ from pathlib import Path
20
+ from typing import Any, Callable
21
+
22
+ import torch
23
+ from diffusers.callbacks import MultiPipelineCallbacks, PipelineCallback
24
+ from transformers import DINOv3ViTModel
25
+ from diffusers.models.modeling_utils import ModelMixin
26
+ from diffusers.pipelines.pipeline_utils import DiffusionPipeline, ImagePipelineOutput
27
+ from diffusers.schedulers.scheduling_utils import SchedulerMixin
28
+ from diffusers.utils import deprecate, is_torch_xla_available, logging, replace_example_docstring
29
+ from diffusers.utils.torch_utils import randn_tensor
30
+ from PIL import Image
31
+
32
+ if is_torch_xla_available():
33
+ import torch_xla.core.xla_model as xm
34
+
35
+ XLA_AVAILABLE = True
36
+ else:
37
+ XLA_AVAILABLE = False
38
+
39
+ logger = logging.get_logger(__name__)
40
+
41
+ EXAMPLE_DOC_STRING = """
42
+ Examples:
43
+ ```py
44
+ >>> from pathlib import Path
45
+ >>> import torch
46
+ >>> from diffusers import DiffusionPipeline
47
+
48
+ >>> model_dir = Path("pixeldit2-diffusers/PixelDiT2-H-16-256").resolve()
49
+ >>> pipe = DiffusionPipeline.from_pretrained(
50
+ ... str(model_dir),
51
+ ... local_files_only=True,
52
+ ... custom_pipeline=str(model_dir / "pipeline.py"),
53
+ ... trust_remote_code=True,
54
+ ... torch_dtype=torch.bfloat16,
55
+ ... ).to("cuda:0")
56
+
57
+ >>> image = pipe(
58
+ ... class_labels="golden retriever",
59
+ ... num_inference_steps=50,
60
+ ... guidance_scale=2.1,
61
+ ... generator=torch.Generator(device="cuda:0").manual_seed(0),
62
+ ... ).images[0]
63
+ >>> image.save("sample.png")
64
+
65
+ >>> # Hugging Face Hub style model id: UserID/RepoID
66
+ >>> # RepoID is usually like "modelname-diffusers"
67
+ >>> # Example: "BiliSakura/PixelDiT2-diffusers" with subfolder "PixelDiT2-H-16-256"
68
+ ```
69
+ """
70
+
71
+
72
+ class PixelDiT2Pipeline(DiffusionPipeline):
73
+ r"""
74
+ Class-conditional image pipeline for PixelDiT2.
75
+
76
+ PixelDiT2 denoises directly in RGB pixel space (no VAE). The transformer predicts the clean
77
+ image `x0`. [`PixelDiT2Scheduler`] integrates that prediction on `linspace(0, 1, steps + 1)`:
78
+ Heun on every interval except the last, which is Euler. `solver="euler"` uses the same knots
79
+ with one evaluation per interval.
80
+
81
+ Classifier-free guidance mixes a grounded class-conditional forward with an ungrounded null-class
82
+ forward. Guidance is applied only while the flow time is strictly greater than
83
+ `guidance_interval_min` and strictly less than `guidance_interval_max`.
84
+
85
+ The pipeline inherits from [`DiffusionPipeline`]. Check the superclass documentation for the
86
+ generic methods (download, save, device placement, CPU offload).
87
+
88
+ Args:
89
+ transformer ([`ModelMixin`]):
90
+ PixelDiT2 denoiser (`PixelDiT2Transformer2DModel`) that predicts `x0` in pixel space.
91
+ scheduler ([`PixelDiT2Scheduler`]):
92
+ Flow scheduler. The paper setting is Heun, `t_eps=0.05`. Loaded from `scheduler/`.
93
+ encoder (`DINOv3ViTModel`, *optional*):
94
+ Original DINOv3 checkpoint shipped in `encoder/`. The 256px variant includes DINOv3-S/16.
95
+ Sampling uses the mapped copy stored inside the transformer, so this module is not called.
96
+ id2label (`dict[int, str]`, *optional*):
97
+ ImageNet class id to English label mapping. Values may contain comma-separated synonyms.
98
+ Loaded from `model_index.json` when omitted.
99
+
100
+ Sampling defaults are not pipeline config. When `__call__` omits them, they are read from
101
+ `transformer.config`: `default_num_inference_steps`, `guidance_scale`, `guidance_interval_min`,
102
+ `guidance_interval_max`, `noise_scale`, and `t_eps`. Missing transformer entries fall back to
103
+ 50 steps, CFG 2.4 on `(0.125, 0.9)`, `noise_scale` 1.0, and `t_eps` 0.05.
104
+ """
105
+
106
+ _optional_components = ["encoder"]
107
+ _callback_tensor_inputs = ["latents"]
108
+
109
+ def __init__(
110
+ self,
111
+ transformer: ModelMixin,
112
+ scheduler: SchedulerMixin,
113
+ encoder: DINOv3ViTModel | None = None,
114
+ id2label: dict[int, str] | dict[str, str] | None = None,
115
+ ):
116
+ super().__init__()
117
+ if scheduler is None:
118
+ scheduler = self._default_scheduler()
119
+
120
+ self.register_modules(transformer=transformer, scheduler=scheduler, encoder=encoder)
121
+ normalized_labels = self._normalize_id2label(id2label)
122
+ self.register_to_config(id2label={str(key): value for key, value in normalized_labels.items()})
123
+ self._id2label = normalized_labels
124
+ self.labels = self._build_label2id(self._id2label)
125
+ self._labels_loaded_from_model_index = bool(self._id2label)
126
+
127
+ def _sampling_default(self, name: str, fallback: float) -> float:
128
+ r"""
129
+ Read a sampling default from the transformer config.
130
+
131
+ Args:
132
+ name (`str`):
133
+ Key on `transformer.config`, such as `guidance_scale` or `noise_scale`.
134
+ fallback (`float`):
135
+ Value used when the transformer config does not define `name`.
136
+
137
+ Returns:
138
+ `float`: The configured value, or `fallback`.
139
+ """
140
+ value = getattr(self.transformer.config, name, None)
141
+ if value is None:
142
+ return fallback
143
+ return value
144
+
145
+ @staticmethod
146
+ def _default_scheduler() -> SchedulerMixin:
147
+ r"""
148
+ Build [`PixelDiT2Scheduler`] from the variant's scheduler module.
149
+
150
+ Returns:
151
+ [`PixelDiT2Scheduler`]: Heun on the paper linspace, `t_eps=0.05`.
152
+ """
153
+ module_path = Path(__file__).resolve().parent / "scheduler" / "scheduling_pixeldit2.py"
154
+ spec = importlib.util.spec_from_file_location("scheduling_pixeldit2", module_path)
155
+ if spec is None or spec.loader is None:
156
+ raise ImportError(f"Could not load the PixelDiT2 scheduler from {module_path}.")
157
+ module = importlib.util.module_from_spec(spec)
158
+ sys.modules["scheduling_pixeldit2"] = module
159
+ spec.loader.exec_module(module)
160
+ return module.PixelDiT2Scheduler()
161
+
162
+ def _ensure_labels_loaded(self) -> None:
163
+ r"""
164
+ Fill `id2label` from `model_index.json` when the constructor did not receive it.
165
+ """
166
+ if self._labels_loaded_from_model_index:
167
+ return
168
+ loaded = self._read_id2label_from_model_index(getattr(self.config, "_name_or_path", None))
169
+ if loaded:
170
+ self._id2label = loaded
171
+ self.labels = self._build_label2id(self._id2label)
172
+ self._labels_loaded_from_model_index = True
173
+
174
+ @staticmethod
175
+ def _normalize_id2label(id2label: dict[int, str] | dict[str, str] | None) -> dict[int, str]:
176
+ r"""
177
+ Cast label-map keys to integers.
178
+
179
+ Args:
180
+ id2label (`dict`, *optional*):
181
+ Class id to English label. Keys may be strings, which is how JSON stores them.
182
+
183
+ Returns:
184
+ `dict[int, str]`: Integer-keyed map. Empty when `id2label` is missing.
185
+ """
186
+ if not id2label:
187
+ return {}
188
+ return {int(key): value for key, value in id2label.items()}
189
+
190
+ @staticmethod
191
+ def _read_id2label_from_model_index(variant_path: str | None) -> dict[int, str]:
192
+ r"""
193
+ Read `id2label` from a local variant directory.
194
+
195
+ Args:
196
+ variant_path (`str`, *optional*):
197
+ Directory that contains `model_index.json`.
198
+
199
+ Returns:
200
+ `dict[int, str]`: Loaded map, or an empty dict when the file or key is absent.
201
+ """
202
+ if not variant_path:
203
+ return {}
204
+ model_index_path = Path(variant_path).resolve() / "model_index.json"
205
+ if not model_index_path.exists():
206
+ return {}
207
+ raw = json.loads(model_index_path.read_text(encoding="utf-8"))
208
+ id2label = raw.get("id2label")
209
+ if not isinstance(id2label, dict):
210
+ return {}
211
+ return {int(key): value for key, value in id2label.items()}
212
+
213
+ @staticmethod
214
+ def _build_label2id(id2label: dict[int, str]) -> dict[str, int]:
215
+ r"""
216
+ Invert `id2label`, splitting comma-separated synonyms.
217
+
218
+ Args:
219
+ id2label (`dict[int, str]`):
220
+ Class id to one or more English names.
221
+
222
+ Returns:
223
+ `dict[str, int]`: Synonym to class id, sorted by synonym.
224
+ """
225
+ label2id: dict[str, int] = {}
226
+ for class_id, value in id2label.items():
227
+ for synonym in value.split(","):
228
+ synonym = synonym.strip()
229
+ if synonym:
230
+ label2id[synonym] = int(class_id)
231
+ return dict(sorted(label2id.items()))
232
+
233
+ @property
234
+ def id2label(self) -> dict[int, str]:
235
+ r"""
236
+ ImageNet id to English label map.
237
+
238
+ Returns:
239
+ `dict[int, str]`: The map loaded from the constructor or `model_index.json`.
240
+ """
241
+ self._ensure_labels_loaded()
242
+ return self._id2label
243
+
244
+ def get_label_ids(self, label: str | list[str]) -> list[int]:
245
+ r"""
246
+ Map ImageNet English labels to class ids.
247
+
248
+ Args:
249
+ label (`str` or `list[str]`):
250
+ One label or a list of labels. Each string must match a synonym in `id2label`
251
+ after stripping whitespace. Synonyms are the comma-separated pieces of each value.
252
+
253
+ Returns:
254
+ `list[int]`: Class ids in the same order as `label`.
255
+ """
256
+ self._ensure_labels_loaded()
257
+ label2id = self.labels
258
+ if not label2id:
259
+ raise ValueError("No English labels loaded. Ensure `id2label` exists in model_index.json.")
260
+ if isinstance(label, str):
261
+ label = [label]
262
+ missing = [item for item in label if item not in label2id]
263
+ if missing:
264
+ preview = ", ".join(list(label2id.keys())[:8])
265
+ raise ValueError(f"Unknown English label(s): {missing}. Example valid labels: {preview}, ...")
266
+ return [label2id[item] for item in label]
267
+
268
+ def _normalize_class_labels(self, class_labels: int | str | list[int | str]) -> list[int]:
269
+ r"""
270
+ Turn a class-label argument into a list of integer ids.
271
+
272
+ Args:
273
+ class_labels (`int`, `str`, or `list`):
274
+ One id, one English label, or a list of either. A list must not mix types.
275
+
276
+ Returns:
277
+ `list[int]`: One id per requested image.
278
+ """
279
+ if isinstance(class_labels, int):
280
+ return [class_labels]
281
+ if isinstance(class_labels, str):
282
+ return self.get_label_ids(class_labels)
283
+ if len(class_labels) == 0:
284
+ raise ValueError("`class_labels` must contain at least one class id or label.")
285
+ if isinstance(class_labels[0], str):
286
+ if not all(isinstance(item, str) for item in class_labels):
287
+ raise TypeError("`class_labels` must be all strings or all integers.")
288
+ return self.get_label_ids(class_labels)
289
+ if not all(isinstance(item, int) for item in class_labels):
290
+ raise TypeError("`class_labels` must be all strings or all integers.")
291
+ return list(class_labels)
292
+
293
+ def prepare_extra_step_kwargs(
294
+ self,
295
+ generator: torch.Generator | list[torch.Generator] | None,
296
+ eta: float,
297
+ ) -> dict[str, Any]:
298
+ r"""
299
+ Extra arguments forwarded to `scheduler.step`, depending on what that method accepts.
300
+
301
+ Args:
302
+ generator (`torch.Generator` or `list[torch.Generator]`, *optional*):
303
+ Generator passed through when the scheduler step samples noise.
304
+ eta (`float`):
305
+ DDIM eta in `[0, 1]`. Ignored by schedulers whose `step` has no `eta` argument.
306
+
307
+ Returns:
308
+ `dict`: Keyword arguments for `scheduler.step`.
309
+ """
310
+ extra_step_kwargs: dict[str, Any] = {}
311
+ step_params = set(inspect.signature(self.scheduler.step).parameters.keys())
312
+ if "eta" in step_params:
313
+ extra_step_kwargs["eta"] = eta
314
+ if "generator" in step_params:
315
+ extra_step_kwargs["generator"] = generator
316
+ return extra_step_kwargs
317
+
318
+ def check_inputs(
319
+ self,
320
+ class_labels: int | str | list[int | str],
321
+ height: int,
322
+ width: int,
323
+ num_inference_steps: int,
324
+ guidance_scale: float,
325
+ guidance_interval_min: float,
326
+ guidance_interval_max: float,
327
+ noise_scale: float,
328
+ t_eps: float,
329
+ output_type: str,
330
+ callback_steps: int | None = None,
331
+ callback_on_step_end_tensor_inputs: list[str] | None = None,
332
+ ) -> None:
333
+ r"""
334
+ Reject arguments that the denoiser or the sampler cannot run.
335
+
336
+ Args:
337
+ class_labels (`int`, `str`, or `list`):
338
+ Class ids or English labels. A list must be non-empty.
339
+ height (`int`):
340
+ Output height in pixels. Must be positive and divisible by the patch size.
341
+ width (`int`):
342
+ Output width in pixels. Must be positive and divisible by the patch size.
343
+ num_inference_steps (`int`):
344
+ Number of integration intervals. Must be >= 1.
345
+ guidance_scale (`float`):
346
+ CFG scale. Must be finite.
347
+ guidance_interval_min (`float`):
348
+ Exclusive lower flow-time bound of CFG.
349
+ guidance_interval_max (`float`):
350
+ Exclusive upper flow-time bound of CFG. Must be greater than the minimum and at most 1.
351
+ noise_scale (`float`):
352
+ Initial Gaussian scale. Must be positive.
353
+ t_eps (`float`):
354
+ Velocity denominator floor. Must be positive.
355
+ output_type (`str`):
356
+ One of `"pil"`, `"np"`, `"pt"`, `"latent"`.
357
+ callback_steps (`int`, *optional*):
358
+ Deprecated callback period. When set, must be a positive integer.
359
+ callback_on_step_end_tensor_inputs (`list[str]`, *optional*):
360
+ Tensor names the step callback may read. Each name must be in `_callback_tensor_inputs`.
361
+ """
362
+ if isinstance(class_labels, list) and len(class_labels) == 0:
363
+ raise ValueError("`class_labels` must contain at least one class id or label.")
364
+ patch_size = int(self.transformer.config.patch_size)
365
+ if height <= 0 or width <= 0:
366
+ raise ValueError(f"`height` and `width` must be positive, got {(height, width)}.")
367
+ if height % patch_size != 0 or width % patch_size != 0:
368
+ raise ValueError(f"`height` and `width` must be divisible by patch_size={patch_size}. Got {(height, width)}.")
369
+ if num_inference_steps < 1:
370
+ raise ValueError(f"`num_inference_steps` must be >= 1, got {num_inference_steps}.")
371
+ if not torch.isfinite(torch.tensor(guidance_scale)):
372
+ raise ValueError(f"`guidance_scale` must be finite, got {guidance_scale}.")
373
+ if not 0.0 <= guidance_interval_min < guidance_interval_max <= 1.0:
374
+ raise ValueError(
375
+ "Guidance interval must satisfy 0 <= min < max <= 1, got "
376
+ f"[{guidance_interval_min}, {guidance_interval_max}]."
377
+ )
378
+ if noise_scale <= 0:
379
+ raise ValueError(f"`noise_scale` must be positive, got {noise_scale}.")
380
+ if t_eps <= 0:
381
+ raise ValueError(f"`t_eps` must be positive, got {t_eps}.")
382
+ if output_type not in {"pil", "np", "pt", "latent"}:
383
+ raise ValueError(f"Unsupported `output_type` {output_type!r}. Choose from 'pil', 'np', 'pt', 'latent'.")
384
+ if callback_steps is not None and (not isinstance(callback_steps, int) or callback_steps < 1):
385
+ raise ValueError(f"`callback_steps` must be a positive integer, got {callback_steps}.")
386
+ if callback_on_step_end_tensor_inputs is not None:
387
+ unknown = [name for name in callback_on_step_end_tensor_inputs if name not in self._callback_tensor_inputs]
388
+ if unknown:
389
+ raise ValueError(
390
+ f"`callback_on_step_end_tensor_inputs` contains {unknown}, which are not in "
391
+ f"{self._callback_tensor_inputs}."
392
+ )
393
+
394
+ def prepare_latents(
395
+ self,
396
+ batch_size: int,
397
+ num_channels: int,
398
+ height: int,
399
+ width: int,
400
+ dtype: torch.dtype,
401
+ device: torch.device,
402
+ generator: torch.Generator | list[torch.Generator] | None,
403
+ latents: torch.Tensor | None,
404
+ noise_scale: float,
405
+ ) -> torch.Tensor:
406
+ r"""
407
+ Sample the initial pixel-space noise, or validate a tensor the caller already sampled.
408
+
409
+ PixelDiT2 has no VAE, so these "latents" are RGB images. Fresh noise is multiplied by
410
+ `noise_scale`. A provided `latents` tensor is not rescaled.
411
+
412
+ Args:
413
+ batch_size (`int`):
414
+ Number of images.
415
+ num_channels (`int`):
416
+ Channel count. 3 for RGB.
417
+ height (`int`):
418
+ Image height in pixels.
419
+ width (`int`):
420
+ Image width in pixels.
421
+ dtype (`torch.dtype`):
422
+ Dtype of freshly sampled noise. The integration itself is accumulated in float32.
423
+ device (`torch.device`):
424
+ Device of the returned tensor.
425
+ generator (`torch.Generator` or `list[torch.Generator]`, *optional*):
426
+ Per-call RNG. A list must have length `batch_size`.
427
+ latents (`torch.Tensor`, *optional*):
428
+ Starting noise of shape `(batch_size, num_channels, height, width)`.
429
+ noise_scale (`float`):
430
+ Scale applied only when `latents` is `None`.
431
+
432
+ Returns:
433
+ `torch.Tensor`: Starting noise of shape `(batch_size, num_channels, height, width)`.
434
+ """
435
+ shape = (batch_size, num_channels, height, width)
436
+ if isinstance(generator, list) and len(generator) != batch_size:
437
+ raise ValueError(
438
+ f"You passed a list of {len(generator)} generators for a batch of {batch_size}. "
439
+ "The two lengths must match."
440
+ )
441
+ if latents is None:
442
+ latents = randn_tensor(shape, generator=generator, device=device, dtype=dtype)
443
+ latents = latents * float(noise_scale)
444
+ else:
445
+ latents = latents.to(device=device)
446
+ if tuple(latents.shape) != shape:
447
+ raise ValueError(f"`latents` shape {tuple(latents.shape)} does not match the expected {shape}.")
448
+ return latents
449
+
450
+ def _prepare_scheduler(
451
+ self,
452
+ num_inference_steps: int,
453
+ device: torch.device,
454
+ timesteps: list[float] | None,
455
+ sigmas: list[float] | None,
456
+ ) -> torch.Tensor:
457
+ r"""
458
+ Install the paper linspace on `self.scheduler` and return its flow times.
459
+
460
+ [`PixelDiT2Scheduler`] owns the grid. `timesteps` and `sigmas` are rejected. Use
461
+ `solver="euler"` for one model evaluation per interval.
462
+
463
+ Args:
464
+ num_inference_steps (`int`):
465
+ Number of flow-time intervals.
466
+ device (`torch.device`):
467
+ Device of the scheduler tensors.
468
+ timesteps (`list[float]`, *optional*):
469
+ Not used. The scheduler builds `linspace(0, 1, steps + 1)`.
470
+ sigmas (`list[float]`, *optional*):
471
+ Not used. PixelDiT2 integrates flow time, not a sigma schedule.
472
+
473
+ Returns:
474
+ `torch.Tensor`: Flow times at which the denoiser is evaluated, in `[0, 1]`.
475
+ """
476
+ if timesteps is not None or sigmas is not None:
477
+ raise ValueError(
478
+ "PixelDiT2Scheduler builds its own linspace and does not accept custom `timesteps` or "
479
+ '`sigmas`. Use PixelDiT2Scheduler(solver="euler") for one evaluation per step.'
480
+ )
481
+ self.scheduler.set_timesteps(num_inference_steps, device=device)
482
+ return self.scheduler.timesteps
483
+
484
+ def _predict_x0(
485
+ self,
486
+ latents: torch.Tensor,
487
+ flow_time: torch.Tensor,
488
+ class_labels: torch.Tensor,
489
+ skip_grounding: bool,
490
+ ) -> torch.Tensor:
491
+ r"""
492
+ Run the denoiser and return an x0 prediction in float32.
493
+
494
+ Args:
495
+ latents (`torch.Tensor`):
496
+ Current sample `(batch, channels, height, width)`.
497
+ flow_time (`torch.Tensor`):
498
+ Scalar flow time in `[0, 1]`, broadcast inside the denoiser.
499
+ class_labels (`torch.Tensor`):
500
+ Class ids `(batch,)`.
501
+ skip_grounding (`bool`):
502
+ When `True`, skip the DINOv3 encoder. Used for the unconditional branch.
503
+
504
+ Returns:
505
+ `torch.Tensor`: x0 prediction `(batch, channels, height, width)` in float32.
506
+ """
507
+ model_input = latents
508
+ parameter_dtype = self.transformer.dtype
509
+ device_type = model_input.device.type
510
+ use_amp = device_type in {"cuda", "xpu"} and parameter_dtype in (torch.float16, torch.bfloat16)
511
+ if not use_amp:
512
+ model_input = model_input.to(dtype=parameter_dtype)
513
+ timesteps = flow_time.to(device=model_input.device, dtype=parameter_dtype).expand(model_input.shape[0])
514
+ with torch.autocast(device_type if device_type != "mps" else "cpu", dtype=parameter_dtype, enabled=use_amp):
515
+ prediction = self.transformer(
516
+ model_input,
517
+ timestep=timesteps,
518
+ class_labels=class_labels,
519
+ skip_grounding=skip_grounding,
520
+ ).sample
521
+ return prediction.float()
522
+
523
+ def _guided_x0(
524
+ self,
525
+ latents: torch.Tensor,
526
+ flow_time: float,
527
+ class_labels: torch.Tensor,
528
+ class_null: torch.Tensor,
529
+ guidance_scale: float,
530
+ guidance_interval_min: float,
531
+ guidance_interval_max: float,
532
+ ) -> torch.Tensor:
533
+ r"""
534
+ Classifier-free guidance on x0, restricted to the paper's time interval.
535
+
536
+ Outside the interval the scale is 1, which is exactly the conditional prediction, so the
537
+ ungrounded forward is skipped.
538
+
539
+ Args:
540
+ latents (`torch.Tensor`):
541
+ Current sample.
542
+ flow_time (`float`):
543
+ Scalar flow time of this evaluation.
544
+ class_labels (`torch.Tensor`):
545
+ Conditional class ids.
546
+ class_null (`torch.Tensor`):
547
+ Null class ids, one per batch row.
548
+ guidance_scale (`float`):
549
+ CFG scale used inside the interval.
550
+ guidance_interval_min (`float`):
551
+ Exclusive lower bound.
552
+ guidance_interval_max (`float`):
553
+ Exclusive upper bound.
554
+
555
+ Returns:
556
+ `torch.Tensor`: Guided x0, same shape as `latents`, in float32.
557
+ """
558
+ flow = torch.tensor(flow_time, device=latents.device, dtype=torch.float32)
559
+ conditional = self._predict_x0(latents, flow, class_labels, skip_grounding=False)
560
+ inside = guidance_interval_min < flow_time < guidance_interval_max
561
+ if guidance_scale == 1.0 or not inside:
562
+ return conditional
563
+ unconditional = self._predict_x0(latents, flow, class_null, skip_grounding=True)
564
+ return unconditional + guidance_scale * (conditional - unconditional)
565
+
566
+ @property
567
+ def guidance_scale(self) -> float:
568
+ r"""
569
+ Classifier-free guidance scale of the call that is currently running.
570
+
571
+ Returns:
572
+ `float`: The scale set by the active `__call__`.
573
+ """
574
+ return self._guidance_scale
575
+
576
+ @property
577
+ def do_classifier_free_guidance(self) -> bool:
578
+ r"""
579
+ Whether the active call can run an unconditional forward.
580
+
581
+ The unconditional forward is still skipped at timesteps outside the guidance interval.
582
+
583
+ Returns:
584
+ `bool`: True when `guidance_scale > 1`.
585
+ """
586
+ return self._guidance_scale > 1.0
587
+
588
+ @property
589
+ def num_timesteps(self) -> int:
590
+ r"""
591
+ Number of scheduler timesteps in the active call.
592
+
593
+ Returns:
594
+ `int`: Length of the timestep schedule, including Heun's repeated states.
595
+ """
596
+ return self._num_timesteps
597
+
598
+ @property
599
+ def interrupt(self) -> bool:
600
+ r"""
601
+ Whether the active denoising loop should skip remaining steps.
602
+
603
+ Returns:
604
+ `bool`: True after the caller sets `pipeline._interrupt = True`.
605
+ """
606
+ return self._interrupt
607
+
608
+ def _images_from_latents(self, latents: torch.Tensor, output_type: str) -> torch.Tensor | list[Image.Image]:
609
+ r"""
610
+ Convert pixel-space samples to the requested output type.
611
+
612
+ Quantization matches the original sampler: `uint8(clip((x + 1) * 127.5 + 0.5, 0, 255))`.
613
+
614
+ Args:
615
+ latents (`torch.Tensor`):
616
+ Samples of shape `(batch, channels, height, width)` in model range around `[-1, 1]`.
617
+ output_type (`str`):
618
+ `"latent"` returns `latents` unchanged. `"pt"` is float RGB in `[0, 1]` after that
619
+ quantization. `"np"` is `uint8` HWC arrays. `"pil"` is a list of `PIL.Image.Image`.
620
+
621
+ Returns:
622
+ Images in the requested type.
623
+ """
624
+ if output_type == "latent":
625
+ return latents
626
+ images = torch.clamp((latents.float() + 1.0) * 127.5 + 0.5, 0, 255).to(torch.uint8)
627
+ if output_type == "pt":
628
+ return images.float() / 255.0
629
+ arrays = images.permute(0, 2, 3, 1).cpu().numpy()
630
+ if output_type == "np":
631
+ return arrays
632
+ return [Image.fromarray(image) for image in arrays]
633
+
634
+ @torch.no_grad()
635
+ @replace_example_docstring(EXAMPLE_DOC_STRING)
636
+ def __call__(
637
+ self,
638
+ class_labels: int | str | list[int | str],
639
+ height: int | None = None,
640
+ width: int | None = None,
641
+ num_inference_steps: int | None = None,
642
+ timesteps: list[float] | None = None,
643
+ sigmas: list[float] | None = None,
644
+ guidance_scale: float | None = None,
645
+ guidance_interval_min: float | None = None,
646
+ guidance_interval_max: float | None = None,
647
+ noise_scale: float | None = None,
648
+ t_eps: float | None = None,
649
+ eta: float = 0.0,
650
+ generator: torch.Generator | list[torch.Generator] | None = None,
651
+ latents: torch.Tensor | None = None,
652
+ output_type: str = "pil",
653
+ return_dict: bool = True,
654
+ callback_on_step_end: Callable[[int, int, dict], dict] | PipelineCallback | MultiPipelineCallbacks | None = None,
655
+ callback_on_step_end_tensor_inputs: list[str] | None = None,
656
+ **kwargs,
657
+ ) -> ImagePipelineOutput | tuple:
658
+ r"""
659
+ Generate images from ImageNet class labels.
660
+
661
+ Args:
662
+ class_labels (`int`, `str`, or `list`):
663
+ One ImageNet class id, one English label, or a list of either. English labels are
664
+ resolved with [`get_label_ids`]. The list length is the batch size.
665
+ height (`int`, *optional*):
666
+ Image height in pixels. Defaults to `transformer.config.sample_size`. Must be
667
+ divisible by the patch size. Other sizes recompute rotary positions for that grid.
668
+ width (`int`, *optional*):
669
+ Image width in pixels. Defaults to `transformer.config.sample_size`.
670
+ num_inference_steps (`int`, *optional*):
671
+ Denoising intervals. Defaults to `transformer.config.default_num_inference_steps` (50).
672
+ timesteps (`list[float]`, *optional*):
673
+ Not accepted. [`PixelDiT2Scheduler`] builds `linspace(0, 1, steps + 1)`.
674
+ sigmas (`list[float]`, *optional*):
675
+ Not accepted. PixelDiT2 integrates flow time. Use `solver="euler"` for one evaluation per step.
676
+ guidance_scale (`float`, *optional*):
677
+ Classifier-free guidance scale. Defaults to `transformer.config.guidance_scale`.
678
+ Guidance is on when this is greater than 1 and the flow time is inside the interval.
679
+ guidance_interval_min (`float`, *optional*):
680
+ Exclusive lower flow-time bound. Defaults to `transformer.config.guidance_interval_min`.
681
+ guidance_interval_max (`float`, *optional*):
682
+ Exclusive upper flow-time bound. Defaults to `transformer.config.guidance_interval_max`.
683
+ noise_scale (`float`, *optional*):
684
+ Initial noise scale. Defaults to `transformer.config.noise_scale`. Ignored when `latents` is passed.
685
+ t_eps (`float`, *optional*):
686
+ Floor of the velocity denominator `1 - t`. Defaults to `transformer.config.t_eps` (0.05).
687
+ eta (`float`, defaults to 0.0):
688
+ DDIM eta. Ignored by [`PixelDiT2Scheduler`].
689
+ generator (`torch.Generator` or `list[torch.Generator]`, *optional*):
690
+ RNG for the initial noise.
691
+ latents (`torch.Tensor`, *optional*):
692
+ Initial noise `(batch, 3, height, width)`. Not multiplied by `noise_scale`.
693
+ output_type (`str`, defaults to `"pil"`):
694
+ `"pil"`, `"np"`, `"pt"` (float RGB in `[0, 1]`), or `"latent"` (pixels in model range).
695
+ return_dict (`bool`, defaults to `True`):
696
+ Return [`ImagePipelineOutput`] when `True`, otherwise a one-tuple of images.
697
+ callback_on_step_end (`Callable` or `PipelineCallback`, *optional*):
698
+ Called as `callback_on_step_end(pipeline, step, timestep, callback_kwargs)` after each
699
+ scheduler step. Return a dict to replace tensors listed in
700
+ `callback_on_step_end_tensor_inputs`.
701
+ callback_on_step_end_tensor_inputs (`list[str]`, *optional*):
702
+ Tensor names passed to the step callback. Defaults to `["latents"]`.
703
+
704
+ Examples:
705
+
706
+ Returns:
707
+ [`ImagePipelineOutput`] or `tuple`:
708
+ When `return_dict` is `True`, [`ImagePipelineOutput`] with the images. Otherwise a tuple
709
+ whose first element is the images.
710
+ """
711
+ callback = kwargs.pop("callback", None)
712
+ callback_steps = kwargs.pop("callback_steps", None)
713
+ if kwargs:
714
+ raise TypeError(f"Unexpected arguments: {sorted(kwargs)}.")
715
+ if callback_on_step_end_tensor_inputs is None:
716
+ callback_on_step_end_tensor_inputs = ["latents"]
717
+
718
+ if callback is not None:
719
+ deprecate(
720
+ "callback",
721
+ "1.0.0",
722
+ "Passing `callback` as an input argument to `__call__` is deprecated, consider using `callback_on_step_end`",
723
+ )
724
+ if callback_steps is not None:
725
+ deprecate(
726
+ "callback_steps",
727
+ "1.0.0",
728
+ "Passing `callback_steps` as an input argument to `__call__` is deprecated, consider using `callback_on_step_end`",
729
+ )
730
+ if isinstance(callback_on_step_end, (PipelineCallback, MultiPipelineCallbacks)):
731
+ callback_on_step_end_tensor_inputs = callback_on_step_end.tensor_inputs
732
+
733
+ image_size = int(self.transformer.config.sample_size)
734
+ height = image_size if height is None else int(height)
735
+ width = image_size if width is None else int(width)
736
+ if num_inference_steps is None:
737
+ num_inference_steps = int(self._sampling_default("default_num_inference_steps", 50))
738
+ if guidance_scale is None:
739
+ guidance_scale = float(self._sampling_default("guidance_scale", 2.4))
740
+ if guidance_interval_min is None:
741
+ guidance_interval_min = float(self._sampling_default("guidance_interval_min", 0.125))
742
+ if guidance_interval_max is None:
743
+ guidance_interval_max = float(self._sampling_default("guidance_interval_max", 0.9))
744
+ if noise_scale is None:
745
+ noise_scale = float(self._sampling_default("noise_scale", 1.0))
746
+ if t_eps is None:
747
+ t_eps = float(self._sampling_default("t_eps", 0.05))
748
+
749
+ # 1. Check inputs.
750
+ self.check_inputs(
751
+ class_labels,
752
+ height,
753
+ width,
754
+ num_inference_steps,
755
+ guidance_scale,
756
+ guidance_interval_min,
757
+ guidance_interval_max,
758
+ noise_scale,
759
+ t_eps,
760
+ output_type,
761
+ callback_steps,
762
+ callback_on_step_end_tensor_inputs,
763
+ )
764
+
765
+ self._guidance_scale = float(guidance_scale)
766
+ self._interrupt = False
767
+
768
+ # 2. Define call parameters.
769
+ class_label_ids = self._normalize_class_labels(class_labels)
770
+ batch_size = len(class_label_ids)
771
+ device = self._execution_device
772
+ null_class = int(self.transformer.config.num_classes)
773
+ class_labels_t = torch.tensor(class_label_ids, device=device, dtype=torch.long)
774
+ if torch.any(class_labels_t < 0) or torch.any(class_labels_t > null_class):
775
+ raise ValueError(f"Class ids must lie in [0, {null_class}], got {class_label_ids}.")
776
+ class_null = torch.full_like(class_labels_t, null_class)
777
+
778
+ # 3. Encode input condition (class ids are already the condition; nothing else is encoded).
779
+
780
+ # 4. Prepare timesteps.
781
+ scheduled_timesteps = self._prepare_scheduler(num_inference_steps, device, timesteps, sigmas)
782
+
783
+ # 5. Prepare latent variables (pixel-space noise; there is no VAE).
784
+ latents = self.prepare_latents(
785
+ batch_size,
786
+ int(self.transformer.config.in_channels),
787
+ height,
788
+ width,
789
+ torch.float32,
790
+ device,
791
+ generator,
792
+ latents,
793
+ noise_scale,
794
+ ).float()
795
+
796
+ # 6. Prepare extra step kwargs.
797
+ extra_step_kwargs = self.prepare_extra_step_kwargs(generator, eta)
798
+ num_warmup_steps = len(scheduled_timesteps) - num_inference_steps * self.scheduler.order
799
+ self._num_timesteps = len(scheduled_timesteps)
800
+
801
+ # 7. Denoising loop.
802
+ with self.progress_bar(total=num_inference_steps) as progress_bar:
803
+ for i, timestep in enumerate(scheduled_timesteps):
804
+ if self.interrupt:
805
+ continue
806
+
807
+ flow_time = float(timestep.to(dtype=torch.float32).reshape(-1)[0])
808
+ x0 = self._guided_x0(
809
+ latents,
810
+ flow_time,
811
+ class_labels_t,
812
+ class_null,
813
+ self.guidance_scale,
814
+ guidance_interval_min,
815
+ guidance_interval_max,
816
+ )
817
+ latents = self.scheduler.step(
818
+ x0, timestep, latents, t_eps=t_eps, **extra_step_kwargs, return_dict=False
819
+ )[0]
820
+
821
+ if callback_on_step_end is not None:
822
+ callback_kwargs = {key: locals()[key] for key in callback_on_step_end_tensor_inputs}
823
+ callback_outputs = callback_on_step_end(self, i, timestep, callback_kwargs)
824
+ latents = callback_outputs.pop("latents", latents)
825
+
826
+ if i == len(scheduled_timesteps) - 1 or ((i + 1) > num_warmup_steps and (i + 1) % self.scheduler.order == 0):
827
+ progress_bar.update()
828
+ if callback is not None and i % callback_steps == 0:
829
+ callback(i, timestep, latents)
830
+
831
+ if XLA_AVAILABLE:
832
+ xm.mark_step()
833
+
834
+ images = self._images_from_latents(latents, output_type)
835
+ self.maybe_free_model_hooks()
836
+
837
+ if not return_dict:
838
+ return (images,)
839
+ return ImagePipelineOutput(images=images)
PixelDiT2-H-16-512/scheduler/scheduler_config.json ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_class_name": "PixelDiT2Scheduler",
3
+ "_diffusers_version": "0.39.0",
4
+ "num_train_timesteps": 1000,
5
+ "prediction_type": "sample",
6
+ "solver": "heun",
7
+ "t_eps": 0.05
8
+ }
PixelDiT2-H-16-512/scheduler/scheduling_pixeldit2.py ADDED
@@ -0,0 +1,216 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """PixelDiT2 flow scheduler.
2
+
3
+ Time runs from 0 (noise) to 1 (data). The transformer predicts the clean sample x0.
4
+ Velocity is `(x0 - x) / max(1 - t, t_eps)`. Heun is used on every interval except the
5
+ last, which is Euler. This matches `GroundedHeunSampler` rather than the sigma grid
6
+ inside `FlowMatchHeunDiscreteScheduler`.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from dataclasses import dataclass
12
+ from typing import Optional, Union
13
+
14
+ import torch
15
+ from diffusers.configuration_utils import ConfigMixin, register_to_config
16
+ from diffusers.schedulers.scheduling_utils import SchedulerMixin
17
+ from diffusers.utils import BaseOutput
18
+
19
+
20
+ @dataclass
21
+ class PixelDiT2SchedulerOutput(BaseOutput):
22
+ prev_sample: torch.Tensor
23
+
24
+
25
+ class PixelDiT2Scheduler(SchedulerMixin, ConfigMixin):
26
+ """Uniform flow-time scheduler for PixelDiT2.
27
+
28
+ `solver="heun"` evaluates the model twice on each interval except the last.
29
+ `solver="euler"` evaluates it once per interval on the same linspace.
30
+ """
31
+
32
+ config_name = "scheduler_config.json"
33
+ _compatibles: list[str] = []
34
+ order = 2
35
+
36
+ @register_to_config
37
+ def __init__(
38
+ self,
39
+ num_train_timesteps: int = 1000,
40
+ solver: str = "heun",
41
+ prediction_type: str = "sample",
42
+ t_eps: float = 0.05,
43
+ ):
44
+ if solver not in {"heun", "euler"}:
45
+ raise ValueError(f'`solver` must be "heun" or "euler", got {solver}.')
46
+ if prediction_type not in {"sample", "velocity"}:
47
+ raise ValueError(f'`prediction_type` must be "sample" or "velocity", got {prediction_type}.')
48
+ if num_train_timesteps < 1:
49
+ raise ValueError(f"`num_train_timesteps` must be >= 1, got {num_train_timesteps}.")
50
+ if t_eps <= 0:
51
+ raise ValueError(f"`t_eps` must be positive, got {t_eps}.")
52
+
53
+ self.timesteps: Optional[torch.Tensor] = None
54
+ self.schedule: Optional[torch.Tensor] = None
55
+ self.num_inference_steps: Optional[int] = None
56
+ self._step_plan: list[dict] = []
57
+ self._step_index: Optional[int] = None
58
+ self._begin_index: Optional[int] = None
59
+ self._heun_sample: Optional[torch.Tensor] = None
60
+ self._heun_velocity: Optional[torch.Tensor] = None
61
+
62
+ @property
63
+ def init_noise_sigma(self) -> float:
64
+ return 1.0
65
+
66
+ @property
67
+ def step_index(self) -> Optional[int]:
68
+ return self._step_index
69
+
70
+ @property
71
+ def begin_index(self) -> Optional[int]:
72
+ return self._begin_index
73
+
74
+ def set_begin_index(self, begin_index: int = 0) -> None:
75
+ self._begin_index = int(begin_index)
76
+
77
+ def set_timesteps(
78
+ self,
79
+ num_inference_steps: int,
80
+ device: Union[str, torch.device, None] = None,
81
+ **kwargs,
82
+ ) -> None:
83
+ """Install `linspace(0, 1, steps + 1)` and the Heun or Euler step plan.
84
+
85
+ Args:
86
+ num_inference_steps (`int`):
87
+ Number of intervals from noise to data.
88
+ device (`str` or `torch.device`, *optional*):
89
+ Device of `timesteps`.
90
+ """
91
+ if kwargs:
92
+ raise ValueError(f"PixelDiT2Scheduler.set_timesteps does not accept {sorted(kwargs)}.")
93
+ if num_inference_steps < 1:
94
+ raise ValueError(f"`num_inference_steps` must be >= 1, got {num_inference_steps}.")
95
+
96
+ knots = torch.linspace(0.0, 1.0, num_inference_steps + 1, device=device, dtype=torch.float32)
97
+ plan: list[dict] = []
98
+ use_heun = self.config.solver == "heun" and num_inference_steps > 1
99
+ if use_heun:
100
+ for index in range(num_inference_steps - 1):
101
+ current = float(knots[index])
102
+ nxt = float(knots[index + 1])
103
+ plan.append({"kind": "heun_predict", "t_model": current, "t_cur": current, "t_next": nxt})
104
+ plan.append({"kind": "heun_correct", "t_model": nxt, "t_cur": current, "t_next": nxt})
105
+ last = num_inference_steps - 1
106
+ plan.append(
107
+ {
108
+ "kind": "euler",
109
+ "t_model": float(knots[last]),
110
+ "t_cur": float(knots[last]),
111
+ "t_next": float(knots[last + 1]),
112
+ }
113
+ )
114
+ else:
115
+ for index in range(num_inference_steps):
116
+ plan.append(
117
+ {
118
+ "kind": "euler",
119
+ "t_model": float(knots[index]),
120
+ "t_cur": float(knots[index]),
121
+ "t_next": float(knots[index + 1]),
122
+ }
123
+ )
124
+
125
+ self.num_inference_steps = int(num_inference_steps)
126
+ self.schedule = knots
127
+ self._step_plan = plan
128
+ self.timesteps = torch.tensor([item["t_model"] for item in plan], device=device, dtype=torch.float32)
129
+ self.order = 2 if use_heun else 1
130
+ self._step_index = 0 if self._begin_index is None else self._begin_index
131
+ self._heun_sample = None
132
+ self._heun_velocity = None
133
+
134
+ def scale_model_input(self, sample: torch.Tensor, timestep: Union[float, torch.Tensor]) -> torch.Tensor:
135
+ del timestep
136
+ return sample
137
+
138
+ def _velocity(
139
+ self,
140
+ sample: torch.Tensor,
141
+ model_output: torch.Tensor,
142
+ flow_time: float,
143
+ t_eps: float,
144
+ ) -> torch.Tensor:
145
+ if self.config.prediction_type == "velocity":
146
+ return model_output.float()
147
+ denominator = max(1.0 - float(flow_time), float(t_eps))
148
+ return (model_output.float() - sample.float()) / denominator
149
+
150
+ def step(
151
+ self,
152
+ model_output: torch.Tensor,
153
+ timestep: Union[float, torch.Tensor],
154
+ sample: torch.Tensor,
155
+ return_dict: bool = True,
156
+ generator: Optional[Union[torch.Generator, list[torch.Generator]]] = None,
157
+ t_eps: Optional[float] = None,
158
+ ) -> Union[PixelDiT2SchedulerOutput, tuple]:
159
+ """Advance one planned step.
160
+
161
+ Args:
162
+ model_output (`torch.Tensor`):
163
+ x0 prediction when `prediction_type` is `"sample"`.
164
+ timestep (`float` or `torch.Tensor`):
165
+ Flow time at which `model_output` was evaluated. The step plan is the
166
+ source of the update; this value is checked against that plan.
167
+ sample (`torch.Tensor`):
168
+ Current sample. For a Heun corrector this is the predictor state.
169
+ return_dict (`bool`, defaults to `True`):
170
+ Return [`PixelDiT2SchedulerOutput`] when `True`.
171
+ generator (`torch.Generator`, *optional*):
172
+ Unused. The integrator is deterministic.
173
+ t_eps (`float`, *optional*):
174
+ Floor on `1 - t`. Defaults to the scheduler config.
175
+
176
+ Returns:
177
+ [`PixelDiT2SchedulerOutput`] or `tuple`:
178
+ The updated sample in float32.
179
+ """
180
+ del generator
181
+ if not self._step_plan or self._step_index is None:
182
+ raise ValueError("Call `set_timesteps` before `step`.")
183
+ if self._step_index >= len(self._step_plan):
184
+ raise ValueError("PixelDiT2Scheduler has already reached the final timestep.")
185
+
186
+ plan = self._step_plan[self._step_index]
187
+ sample = sample.to(dtype=torch.float32)
188
+ floor = float(self.config.t_eps if t_eps is None else t_eps)
189
+ if floor <= 0:
190
+ raise ValueError(f"`t_eps` must be positive, got {floor}.")
191
+ velocity = self._velocity(sample, model_output, plan["t_model"], floor)
192
+ dt = plan["t_next"] - plan["t_cur"]
193
+
194
+ kind = plan["kind"]
195
+ if kind == "heun_predict":
196
+ self._heun_sample = sample
197
+ self._heun_velocity = velocity
198
+ prev_sample = sample + dt * velocity
199
+ elif kind == "heun_correct":
200
+ if self._heun_sample is None or self._heun_velocity is None:
201
+ raise RuntimeError("Heun corrector was called before its predictor.")
202
+ prev_sample = self._heun_sample + dt * 0.5 * (self._heun_velocity + velocity)
203
+ self._heun_sample = None
204
+ self._heun_velocity = None
205
+ else:
206
+ prev_sample = sample + dt * velocity
207
+ self._heun_sample = None
208
+ self._heun_velocity = None
209
+
210
+ self._step_index += 1
211
+ if not return_dict:
212
+ return (prev_sample,)
213
+ return PixelDiT2SchedulerOutput(prev_sample=prev_sample)
214
+
215
+ def __len__(self) -> int:
216
+ return int(self.config.num_train_timesteps)
PixelDiT2-H-16-512/transformer/config.json ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_class_name": "PixelDiT2Transformer2DModel",
3
+ "_diffusers_version": "0.39.0",
4
+ "attn_dropout": 0.0,
5
+ "default_num_inference_steps": 50,
6
+ "depth": 32,
7
+ "grounding_encoder": "dinov3_vitb16",
8
+ "grounding_proj_blocks": 1,
9
+ "grounding_proj_heads": 16,
10
+ "guidance_interval_max": 0.925,
11
+ "guidance_interval_min": 0.1,
12
+ "guidance_scale": 2.1,
13
+ "hidden_size": 1280,
14
+ "in_channels": 3,
15
+ "in_context_len": 32,
16
+ "in_context_start": 8,
17
+ "mlp_hidden_multiple": 32,
18
+ "noise_scale": 2.0,
19
+ "num_classes": 1000,
20
+ "num_heads": 16,
21
+ "patch_size": 16,
22
+ "proj_dropout": 0.2,
23
+ "sample_size": 512,
24
+ "single_silu_cond": true,
25
+ "t_eps": 0.05
26
+ }
PixelDiT2-H-16-512/transformer/diffusion_pytorch_model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b096606fa532ffda15ebc313a50a42d6e6c2121b8195217942266c457b2b4567
3
+ size 2147459616
PixelDiT2-H-16-512/transformer/transformer_pixeldit2.py ADDED
@@ -0,0 +1,1094 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2026 The HuggingFace Team. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """PixelDiT2 denoiser as a diffusers transformer.
16
+
17
+ PixelDiT2 predicts the clean image x0 directly in RGB pixel space. A frozen
18
+ DINOv3 encoder grounds every patch token; the unconditional branch of
19
+ classifier-free guidance skips that encoder (`skip_grounding=True`) and uses
20
+ the null class id `num_classes`.
21
+ """
22
+
23
+ from __future__ import annotations
24
+
25
+ import math
26
+ from dataclasses import dataclass
27
+
28
+ import timm
29
+ import torch
30
+ import torch.nn.functional as F
31
+ from diffusers.configuration_utils import ConfigMixin, register_to_config
32
+ from diffusers.models.modeling_outputs import Transformer2DModelOutput
33
+ from diffusers.models.modeling_utils import ModelMixin
34
+ from torch import nn
35
+
36
+
37
+ @dataclass(frozen=True)
38
+ class EncoderSpec:
39
+ r"""
40
+ Frozen grounding encoder used by PixelDiT2.
41
+
42
+ Args:
43
+ timm_name (`str`):
44
+ `timm` model id, including the pretrained tag when one exists.
45
+ feature_dim (`int`):
46
+ Channel count of the encoder patch tokens.
47
+ patch_size (`int`):
48
+ Encoder patch size in pixels.
49
+ """
50
+
51
+ timm_name: str
52
+ feature_dim: int
53
+ patch_size: int
54
+
55
+
56
+ GROUNDING_ENCODERS: dict[str, EncoderSpec] = {
57
+ "dinov3_vits16": EncoderSpec("vit_small_patch16_dinov3_qkvb.lvd1689m", 384, 16),
58
+ "dinov3_vitb16": EncoderSpec("vit_base_patch16_dinov3_qkvb.lvd1689m", 768, 16),
59
+ "dinov3_vitl16": EncoderSpec("vit_large_patch16_dinov3_qkvb.lvd1689m", 1024, 16),
60
+ }
61
+
62
+ IMAGENET_MEAN = (0.485, 0.456, 0.406)
63
+ IMAGENET_STD = (0.229, 0.224, 0.225)
64
+
65
+
66
+ def apply_adaln(hidden_states: torch.Tensor, shift: torch.Tensor, scale: torch.Tensor) -> torch.Tensor:
67
+ r"""
68
+ Apply adaptive layer-norm modulation.
69
+
70
+ Args:
71
+ hidden_states (`torch.Tensor`):
72
+ Token states of shape `(batch, tokens, hidden)`.
73
+ shift (`torch.Tensor`):
74
+ Shift term broadcastable to `hidden_states`.
75
+ scale (`torch.Tensor`):
76
+ Scale term broadcastable to `hidden_states`. The applied factor is `1 + scale`.
77
+
78
+ Returns:
79
+ `torch.Tensor`: Modulated tokens, same shape as `hidden_states`.
80
+ """
81
+ return hidden_states * (1 + scale) + shift
82
+
83
+
84
+ def precompute_freqs_cis_2d(
85
+ dim: int,
86
+ height: int,
87
+ width: int,
88
+ theta: float = 10000.0,
89
+ scale: float = 16.0,
90
+ ) -> torch.Tensor:
91
+ r"""
92
+ Build 2D rotary frequencies for a patch grid.
93
+
94
+ Positions are `linspace(0, scale, length)` on each axis, matching the PixelDiT2 training code.
95
+ A different grid size recomputes the table, which is how non-native resolutions are handled.
96
+
97
+ Args:
98
+ dim (`int`):
99
+ Head dimension. Must be divisible by 4.
100
+ height (`int`):
101
+ Grid height in patches.
102
+ width (`int`):
103
+ Grid width in patches.
104
+ theta (`float`, defaults to 10000.0):
105
+ RoPE base period.
106
+ scale (`float`, defaults to 16.0):
107
+ Coordinate of the last patch on each axis.
108
+
109
+ Returns:
110
+ `torch.Tensor`: Complex frequencies of shape `(height * width, dim / 2)`.
111
+ """
112
+ x_pos = torch.linspace(0, scale, width)
113
+ y_pos = torch.linspace(0, scale, height)
114
+ y_pos, x_pos = torch.meshgrid(y_pos, x_pos, indexing="ij")
115
+ y_pos = y_pos.reshape(-1)
116
+ x_pos = x_pos.reshape(-1)
117
+ freqs = 1.0 / (theta ** (torch.arange(0, dim, 4)[: (dim // 4)].float() / dim))
118
+ x_freqs = torch.outer(x_pos, freqs).float()
119
+ y_freqs = torch.outer(y_pos, freqs).float()
120
+ x_cis = torch.polar(torch.ones_like(x_freqs), x_freqs)
121
+ y_cis = torch.polar(torch.ones_like(y_freqs), y_freqs)
122
+ freqs_cis = torch.cat([x_cis.unsqueeze(dim=-1), y_cis.unsqueeze(dim=-1)], dim=-1)
123
+ return freqs_cis.reshape(height * width, -1)
124
+
125
+
126
+ def apply_rotary_emb(
127
+ query: torch.Tensor,
128
+ key: torch.Tensor,
129
+ freqs_cis: torch.Tensor,
130
+ ) -> tuple[torch.Tensor, torch.Tensor]:
131
+ r"""
132
+ Apply rotary embeddings to query and key.
133
+
134
+ Args:
135
+ query (`torch.Tensor`):
136
+ Queries of shape `(batch, tokens, heads, head_dim)`.
137
+ key (`torch.Tensor`):
138
+ Keys of shape `(batch, tokens, heads, head_dim)`.
139
+ freqs_cis (`torch.Tensor`):
140
+ Complex frequencies of shape `(tokens, head_dim / 2)`.
141
+
142
+ Returns:
143
+ `tuple[torch.Tensor, torch.Tensor]`: Rotated query and key, same shapes as the inputs.
144
+ """
145
+ freqs_cis = freqs_cis[None, :, None, :]
146
+ query_complex = torch.view_as_complex(query.float().reshape(*query.shape[:-1], -1, 2))
147
+ key_complex = torch.view_as_complex(key.float().reshape(*key.shape[:-1], -1, 2))
148
+ query_out = torch.view_as_real(query_complex * freqs_cis).flatten(3)
149
+ key_out = torch.view_as_real(key_complex * freqs_cis).flatten(3)
150
+ return query_out.type_as(query), key_out.type_as(key)
151
+
152
+
153
+ class TimestepConditioner(nn.Module):
154
+ r"""
155
+ Sinusoidal timestep embedding followed by a two-layer MLP.
156
+
157
+ PixelDiT2 uses `max_period=10`, not the more common 10000.
158
+
159
+ Args:
160
+ hidden_size (`int`):
161
+ Width of the MLP output.
162
+ frequency_embedding_size (`int`, defaults to 256):
163
+ Width of the sinusoidal embedding.
164
+ """
165
+
166
+ def __init__(self, hidden_size: int, frequency_embedding_size: int = 256):
167
+ super().__init__()
168
+ self.mlp = nn.Sequential(
169
+ nn.Linear(frequency_embedding_size, hidden_size, bias=True),
170
+ nn.SiLU(),
171
+ nn.Linear(hidden_size, hidden_size, bias=True),
172
+ )
173
+ self.frequency_embedding_size = frequency_embedding_size
174
+
175
+ @staticmethod
176
+ def timestep_embedding(timesteps: torch.Tensor, dim: int, max_period: int = 10) -> torch.Tensor:
177
+ r"""
178
+ Build a sinusoidal embedding of scalar timesteps.
179
+
180
+ Args:
181
+ timesteps (`torch.Tensor`):
182
+ Timesteps of shape `(batch,)`.
183
+ dim (`int`):
184
+ Embedding width.
185
+ max_period (`int`, defaults to 10):
186
+ Maximum period of the sinusoid.
187
+
188
+ Returns:
189
+ `torch.Tensor`: Embeddings of shape `(batch, dim)`.
190
+ """
191
+ half = dim // 2
192
+ freqs = torch.exp(
193
+ -math.log(max_period) * torch.arange(start=0, end=half, dtype=torch.float32, device=timesteps.device) / half
194
+ )
195
+ args = timesteps[..., None].float() * freqs[None, ...]
196
+ embedding = torch.cat([torch.cos(args), torch.sin(args)], dim=-1)
197
+ if dim % 2:
198
+ embedding = torch.cat([embedding, torch.zeros_like(embedding[:, :1])], dim=-1)
199
+ return embedding
200
+
201
+ def forward(self, timesteps: torch.Tensor) -> torch.Tensor:
202
+ r"""
203
+ Embed timesteps.
204
+
205
+ Args:
206
+ timesteps (`torch.Tensor`):
207
+ Flow time `t` of shape `(batch,)`, in `[0, 1]`.
208
+
209
+ Returns:
210
+ `torch.Tensor`: Embeddings of shape `(batch, hidden_size)`.
211
+ """
212
+ timestep_freq = self.timestep_embedding(timesteps, self.frequency_embedding_size)
213
+ mlp_dtype = self.mlp[0].weight.dtype
214
+ if timestep_freq.dtype != mlp_dtype:
215
+ timestep_freq = timestep_freq.to(mlp_dtype)
216
+ return self.mlp(timestep_freq)
217
+
218
+
219
+ class ClassEmbedder(nn.Module):
220
+ r"""
221
+ Embedding table for ImageNet class ids, including the null class.
222
+
223
+ Args:
224
+ num_classes (`int`):
225
+ Number of rows. PixelDiT2 uses `num_classes + 1` so index `num_classes` is unconditional.
226
+ hidden_size (`int`):
227
+ Embedding width.
228
+ """
229
+
230
+ def __init__(self, num_classes: int, hidden_size: int):
231
+ super().__init__()
232
+ self.embedding_table = nn.Embedding(num_classes, hidden_size)
233
+ self.num_classes = num_classes
234
+
235
+ def forward(self, labels: torch.Tensor) -> torch.Tensor:
236
+ r"""
237
+ Look up class embeddings.
238
+
239
+ Args:
240
+ labels (`torch.Tensor`):
241
+ Integer class ids of shape `(batch,)`.
242
+
243
+ Returns:
244
+ `torch.Tensor`: Embeddings of shape `(batch, hidden_size)`.
245
+ """
246
+ return self.embedding_table(labels)
247
+
248
+
249
+ class RMSNorm(nn.Module):
250
+ r"""
251
+ Root-mean-square normalization.
252
+
253
+ Args:
254
+ hidden_size (`int`):
255
+ Channel width.
256
+ eps (`float`, defaults to 1e-6):
257
+ Numerical stability term.
258
+ """
259
+
260
+ def __init__(self, hidden_size: int, eps: float = 1e-6):
261
+ super().__init__()
262
+ self.weight = nn.Parameter(torch.ones(hidden_size))
263
+ self.variance_epsilon = eps
264
+
265
+ def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
266
+ r"""
267
+ Normalize the last dimension.
268
+
269
+ Args:
270
+ hidden_states (`torch.Tensor`):
271
+ Input of shape `(..., hidden_size)`.
272
+
273
+ Returns:
274
+ `torch.Tensor`: Normalized tensor, same shape as the input.
275
+ """
276
+ input_dtype = hidden_states.dtype
277
+ hidden_states = hidden_states.to(torch.float32)
278
+ variance = hidden_states.pow(2).mean(-1, keepdim=True)
279
+ hidden_states = hidden_states * torch.rsqrt(variance + self.variance_epsilon)
280
+ return self.weight * hidden_states.to(input_dtype)
281
+
282
+
283
+ class FeedForward(nn.Module):
284
+ r"""
285
+ SwiGLU feed-forward block.
286
+
287
+ Args:
288
+ dim (`int`):
289
+ Input and output width.
290
+ hidden_dim (`int`):
291
+ Width before the SwiGLU 2/3 reduction. The inner width is `int(2 * hidden_dim / 3)`,
292
+ then rounded up to `hidden_multiple` when that value is positive.
293
+ drop (`float`, defaults to 0.0):
294
+ Dropout on the hidden activation. Disabled by `eval()`.
295
+ hidden_multiple (`int`, defaults to 0):
296
+ Round the inner width up to a multiple of this value. `0` disables rounding.
297
+ The 512px PixelDiT2 checkpoint uses 32.
298
+ """
299
+
300
+ def __init__(self, dim: int, hidden_dim: int, drop: float = 0.0, hidden_multiple: int = 0):
301
+ super().__init__()
302
+ hidden_dim = int(2 * hidden_dim / 3)
303
+ hidden_multiple = int(hidden_multiple)
304
+ if hidden_multiple > 0:
305
+ hidden_dim = ((hidden_dim + hidden_multiple - 1) // hidden_multiple) * hidden_multiple
306
+ self.w1 = nn.Linear(dim, hidden_dim, bias=False)
307
+ self.w3 = nn.Linear(dim, hidden_dim, bias=False)
308
+ self.w2 = nn.Linear(hidden_dim, dim, bias=False)
309
+ self.ffn_dropout = nn.Dropout(drop)
310
+
311
+ def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
312
+ r"""
313
+ Apply SwiGLU.
314
+
315
+ Args:
316
+ hidden_states (`torch.Tensor`):
317
+ Tokens of shape `(..., dim)`.
318
+
319
+ Returns:
320
+ `torch.Tensor`: Tokens of shape `(..., dim)`.
321
+ """
322
+ hidden = F.silu(self.w1(hidden_states)) * self.w3(hidden_states)
323
+ return self.w2(self.ffn_dropout(hidden))
324
+
325
+
326
+ class RotaryAttention(nn.Module):
327
+ r"""
328
+ Multi-head self-attention with QK RMSNorm and 2D rotary embeddings.
329
+
330
+ Args:
331
+ dim (`int`):
332
+ Token width. Must be divisible by `num_heads`.
333
+ num_heads (`int`, defaults to 8):
334
+ Number of attention heads.
335
+ qkv_bias (`bool`, defaults to `False`):
336
+ Whether the fused QKV projection has a bias. PixelDiT2 checkpoints use `False`.
337
+ qk_norm (`bool`, defaults to `True`):
338
+ Apply RMSNorm to query and key per head.
339
+ attn_drop (`float`, defaults to 0.0):
340
+ Attention dropout. The released models use 0.
341
+ proj_drop (`float`, defaults to 0.0):
342
+ Dropout after the output projection.
343
+ """
344
+
345
+ def __init__(
346
+ self,
347
+ dim: int,
348
+ num_heads: int = 8,
349
+ qkv_bias: bool = False,
350
+ qk_norm: bool = True,
351
+ attn_drop: float = 0.0,
352
+ proj_drop: float = 0.0,
353
+ ):
354
+ super().__init__()
355
+ if dim % num_heads != 0:
356
+ raise ValueError(f"dim={dim} must be divisible by num_heads={num_heads}.")
357
+ self.dim = dim
358
+ self.num_heads = num_heads
359
+ self.head_dim = dim // num_heads
360
+ self.qkv = nn.Linear(dim, dim * 3, bias=qkv_bias)
361
+ self.q_norm = RMSNorm(self.head_dim) if qk_norm else nn.Identity()
362
+ self.k_norm = RMSNorm(self.head_dim) if qk_norm else nn.Identity()
363
+ self.attn_drop = nn.Dropout(attn_drop)
364
+ self.proj = nn.Linear(dim, dim)
365
+ self.proj_drop = nn.Dropout(proj_drop)
366
+
367
+ def forward(self, hidden_states: torch.Tensor, pos: torch.Tensor, mask: torch.Tensor | None = None) -> torch.Tensor:
368
+ r"""
369
+ Run self-attention.
370
+
371
+ Args:
372
+ hidden_states (`torch.Tensor`):
373
+ Tokens of shape `(batch, tokens, dim)`.
374
+ pos (`torch.Tensor`):
375
+ Complex RoPE table of shape `(tokens, head_dim / 2)`.
376
+ mask (`torch.Tensor`, *optional*):
377
+ Attention mask forwarded to scaled-dot-product attention. `None` attends to every token.
378
+
379
+ Returns:
380
+ `torch.Tensor`: Tokens of shape `(batch, tokens, dim)`.
381
+ """
382
+ batch, tokens, channels = hidden_states.shape
383
+ qkv = self.qkv(hidden_states).reshape(batch, tokens, 3, self.num_heads, channels // self.num_heads)
384
+ qkv = qkv.permute(2, 0, 1, 3, 4)
385
+ query, key, value = qkv[0], qkv[1], qkv[2]
386
+ query = self.q_norm(query)
387
+ key = self.k_norm(key)
388
+ query, key = apply_rotary_emb(query, key, freqs_cis=pos)
389
+ query = query.view(batch, -1, self.num_heads, channels // self.num_heads).transpose(1, 2)
390
+ key = key.view(batch, -1, self.num_heads, channels // self.num_heads).transpose(1, 2).contiguous()
391
+ value = value.view(batch, -1, self.num_heads, channels // self.num_heads).transpose(1, 2).contiguous()
392
+ # The training forward always uses dropout_p=0 and ignores `attn_drop`.
393
+ hidden_states = F.scaled_dot_product_attention(query, key, value, attn_mask=mask, dropout_p=0.0)
394
+ hidden_states = hidden_states.transpose(1, 2).reshape(batch, tokens, channels)
395
+ hidden_states = self.proj(hidden_states)
396
+ hidden_states = self.proj_drop(hidden_states)
397
+ return hidden_states
398
+
399
+
400
+ class PatchTokenEmbedder(nn.Module):
401
+ r"""
402
+ Linear embedding of flattened pixel patches.
403
+
404
+ Args:
405
+ in_channels (`int`):
406
+ Flattened patch width, `in_channels * patch_size ** 2` at the call site.
407
+ embed_dim (`int`):
408
+ Token width.
409
+ bias (`bool`, defaults to `True`):
410
+ Bias on the linear projection. PixelDiT2 uses `True`.
411
+ """
412
+
413
+ def __init__(self, in_channels: int, embed_dim: int, bias: bool = True):
414
+ super().__init__()
415
+ self.in_channels = in_channels
416
+ self.embed_dim = embed_dim
417
+ self.proj = nn.Linear(in_channels, embed_dim, bias=bias)
418
+ self.norm = nn.Identity()
419
+
420
+ def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
421
+ r"""
422
+ Embed patch tokens.
423
+
424
+ Args:
425
+ hidden_states (`torch.Tensor`):
426
+ Flattened patches of shape `(batch, tokens, in_channels)`.
427
+
428
+ Returns:
429
+ `torch.Tensor`: Tokens of shape `(batch, tokens, embed_dim)`.
430
+ """
431
+ return self.norm(self.proj(hidden_states))
432
+
433
+
434
+ class ModulatedDiTBlock(nn.Module):
435
+ r"""
436
+ AdaLN-Zero transformer block with rotary attention and SwiGLU.
437
+
438
+ Args:
439
+ hidden_size (`int`):
440
+ Token width.
441
+ num_heads (`int`):
442
+ Attention heads.
443
+ mlp_ratio (`float`, defaults to 4.0):
444
+ MLP expansion before the SwiGLU 2/3 reduction.
445
+ attn_drop (`float`, defaults to 0.0):
446
+ Attention dropout.
447
+ proj_drop (`float`, defaults to 0.0):
448
+ Dropout on the attention projection and the MLP.
449
+ mlp_hidden_multiple (`int`, defaults to 0):
450
+ Forwarded to [`FeedForward`].
451
+ """
452
+
453
+ def __init__(
454
+ self,
455
+ hidden_size: int,
456
+ num_heads: int,
457
+ mlp_ratio: float = 4.0,
458
+ attn_drop: float = 0.0,
459
+ proj_drop: float = 0.0,
460
+ mlp_hidden_multiple: int = 0,
461
+ ):
462
+ super().__init__()
463
+ self.norm1 = RMSNorm(hidden_size, eps=1e-6)
464
+ self.attn = RotaryAttention(
465
+ hidden_size,
466
+ num_heads=num_heads,
467
+ qkv_bias=False,
468
+ attn_drop=attn_drop,
469
+ proj_drop=proj_drop,
470
+ )
471
+ self.norm2 = RMSNorm(hidden_size, eps=1e-6)
472
+ self.mlp = FeedForward(
473
+ hidden_size,
474
+ int(hidden_size * mlp_ratio),
475
+ drop=proj_drop,
476
+ hidden_multiple=mlp_hidden_multiple,
477
+ )
478
+ self.adaLN_modulation = nn.Sequential(
479
+ nn.SiLU(),
480
+ nn.Linear(hidden_size, 6 * hidden_size, bias=True),
481
+ )
482
+
483
+ def forward(
484
+ self,
485
+ hidden_states: torch.Tensor,
486
+ conditioning: torch.Tensor,
487
+ pos: torch.Tensor,
488
+ mask: torch.Tensor | None = None,
489
+ ) -> torch.Tensor:
490
+ r"""
491
+ Run one modulated block.
492
+
493
+ Args:
494
+ hidden_states (`torch.Tensor`):
495
+ Tokens of shape `(batch, tokens, hidden)`.
496
+ conditioning (`torch.Tensor`):
497
+ AdaLN conditioning of shape `(batch, tokens, hidden)` or `(batch, 1, hidden)`.
498
+ pos (`torch.Tensor`):
499
+ RoPE table aligned with `tokens`.
500
+ mask (`torch.Tensor`, *optional*):
501
+ Attention mask. `None` uses full attention.
502
+
503
+ Returns:
504
+ `torch.Tensor`: Tokens of shape `(batch, tokens, hidden)`.
505
+ """
506
+ shift_msa, scale_msa, gate_msa, shift_mlp, scale_mlp, gate_mlp = self.adaLN_modulation(conditioning).chunk(6, dim=-1)
507
+ hidden_states = hidden_states + gate_msa * self.attn(
508
+ apply_adaln(self.norm1(hidden_states), shift_msa, scale_msa), pos, mask=mask
509
+ )
510
+ hidden_states = hidden_states + gate_mlp * self.mlp(apply_adaln(self.norm2(hidden_states), shift_mlp, scale_mlp))
511
+ return hidden_states
512
+
513
+
514
+ class PatchFinalLayer(nn.Module):
515
+ r"""
516
+ AdaLN-modulated projection from tokens back to pixel patches.
517
+
518
+ Args:
519
+ hidden_size (`int`):
520
+ Token width.
521
+ patch_size (`int`):
522
+ Spatial patch size.
523
+ out_channels (`int`):
524
+ Image channels, 3 for RGB.
525
+ """
526
+
527
+ def __init__(self, hidden_size: int, patch_size: int, out_channels: int):
528
+ super().__init__()
529
+ self.norm = RMSNorm(hidden_size, eps=1e-6)
530
+ self.linear = nn.Linear(hidden_size, patch_size * patch_size * out_channels, bias=True)
531
+ self.adaLN_modulation = nn.Sequential(
532
+ nn.SiLU(),
533
+ nn.Linear(hidden_size, 2 * hidden_size, bias=True),
534
+ )
535
+
536
+ def forward(self, hidden_states: torch.Tensor, conditioning: torch.Tensor) -> torch.Tensor:
537
+ r"""
538
+ Project tokens to flattened patches.
539
+
540
+ Args:
541
+ hidden_states (`torch.Tensor`):
542
+ Tokens of shape `(batch, patches, hidden)`.
543
+ conditioning (`torch.Tensor`):
544
+ Conditioning of shape `(batch, patches, hidden)`. A 2D tensor is unsqueezed.
545
+
546
+ Returns:
547
+ `torch.Tensor`: Patch pixels of shape `(batch, patches, patch_size ** 2 * out_channels)`.
548
+ """
549
+ shift, scale = self.adaLN_modulation(conditioning).chunk(2, dim=-1)
550
+ if shift.dim() == 2:
551
+ shift = shift.unsqueeze(1)
552
+ scale = scale.unsqueeze(1)
553
+ return self.linear(apply_adaln(self.norm(hidden_states), shift, scale))
554
+
555
+
556
+ class TimestepProjection(nn.Module):
557
+ r"""
558
+ Projects DINOv3 tokens into the denoiser width with timestep modulation.
559
+
560
+ Args:
561
+ in_dim (`int`):
562
+ Encoder feature width.
563
+ out_dim (`int`):
564
+ Denoiser hidden size.
565
+ hidden_size (`int`):
566
+ Width of the internal transformer blocks. PixelDiT2 uses the denoiser width.
567
+ num_blocks (`int`, defaults to 1):
568
+ Number of modulated blocks. Released checkpoints use 1.
569
+ num_heads (`int`, defaults to 16):
570
+ Heads inside those blocks. `hidden_size` must be divisible by this value.
571
+ mlp_ratio (`float`, defaults to 4.0):
572
+ MLP expansion of the internal blocks.
573
+ """
574
+
575
+ def __init__(
576
+ self,
577
+ in_dim: int,
578
+ out_dim: int,
579
+ hidden_size: int,
580
+ num_blocks: int = 1,
581
+ num_heads: int = 16,
582
+ mlp_ratio: float = 4.0,
583
+ ):
584
+ super().__init__()
585
+ if hidden_size % num_heads != 0:
586
+ raise ValueError(f"TimestepProjection hidden_size={hidden_size} must be divisible by num_heads={num_heads}.")
587
+ self.head_dim = hidden_size // num_heads
588
+ self.input_proj = nn.Linear(in_dim, hidden_size, bias=True)
589
+ self.t_embedder = TimestepConditioner(hidden_size)
590
+ self.blocks = nn.ModuleList(
591
+ [ModulatedDiTBlock(hidden_size, num_heads, mlp_ratio=mlp_ratio) for _ in range(num_blocks)]
592
+ )
593
+ self.output_proj = nn.Linear(hidden_size, out_dim, bias=True)
594
+ for block in self.blocks:
595
+ nn.init.zeros_(block.adaLN_modulation[-1].weight)
596
+ nn.init.zeros_(block.adaLN_modulation[-1].bias)
597
+ self._pos_cache: dict[tuple[int, int], torch.Tensor] = {}
598
+
599
+ def fetch_pos(self, height: int, width: int, device: torch.device) -> torch.Tensor:
600
+ r"""
601
+ Return cached RoPE frequencies for a patch grid.
602
+
603
+ Args:
604
+ height (`int`):
605
+ Grid height in patches.
606
+ width (`int`):
607
+ Grid width in patches.
608
+ device (`torch.device`):
609
+ Device of the returned table.
610
+
611
+ Returns:
612
+ `torch.Tensor`: Complex frequencies of shape `(height * width, head_dim / 2)`.
613
+ """
614
+ key = (height, width)
615
+ if key not in self._pos_cache:
616
+ self._pos_cache[key] = precompute_freqs_cis_2d(self.head_dim, height, width)
617
+ return self._pos_cache[key].to(device)
618
+
619
+ def forward(self, tokens: torch.Tensor, timesteps: torch.Tensor, grid_hw: tuple[int, int]) -> torch.Tensor:
620
+ r"""
621
+ Project grounding tokens.
622
+
623
+ Args:
624
+ tokens (`torch.Tensor`):
625
+ Encoder tokens of shape `(batch, patches, in_dim)`.
626
+ timesteps (`torch.Tensor`):
627
+ Flow time of shape `(batch,)`.
628
+ grid_hw (`tuple[int, int]`):
629
+ `(height, width)` of the token grid in patches.
630
+
631
+ Returns:
632
+ `torch.Tensor`: Tokens of shape `(batch, patches, out_dim)`.
633
+ """
634
+ hidden_states = self.input_proj(tokens)
635
+ conditioning = self.t_embedder(timesteps).unsqueeze(1).to(dtype=hidden_states.dtype)
636
+ pos = self.fetch_pos(grid_hw[0], grid_hw[1], hidden_states.device)
637
+ for block in self.blocks:
638
+ hidden_states = block(hidden_states, conditioning, pos)
639
+ return self.output_proj(hidden_states)
640
+
641
+
642
+ class GroundingConditioner(nn.Module):
643
+ r"""
644
+ Frozen DINOv3 encoder plus the trainable projection `P_g`.
645
+
646
+ The encoder is built with `pretrained=False`. Conversion copies either the
647
+ checkpoint's encoder tensors or a `timm` pretrained checkpoint into this module
648
+ so inference does not download weights.
649
+
650
+ Args:
651
+ encoder_name (`str`):
652
+ Key of [`GROUNDING_ENCODERS`], for example `dinov3_vits16`.
653
+ hidden_size (`int`):
654
+ Denoiser width.
655
+ target_patch_size (`int`):
656
+ Denoiser patch size. The encoder grid is resized to this patch grid.
657
+ proj_num_blocks (`int`, defaults to 1):
658
+ Blocks inside the projection.
659
+ proj_num_heads (`int`, defaults to 16):
660
+ Heads inside the projection.
661
+ """
662
+
663
+ def __init__(
664
+ self,
665
+ encoder_name: str,
666
+ hidden_size: int,
667
+ target_patch_size: int,
668
+ proj_num_blocks: int = 1,
669
+ proj_num_heads: int = 16,
670
+ ):
671
+ super().__init__()
672
+ if encoder_name not in GROUNDING_ENCODERS:
673
+ raise ValueError(f"Unknown grounding encoder {encoder_name!r}. Available: {sorted(GROUNDING_ENCODERS)}.")
674
+ self.spec = GROUNDING_ENCODERS[encoder_name]
675
+ self.encoder_name = encoder_name
676
+ self.target_patch_size = int(target_patch_size)
677
+ self.encoder = timm.create_model(self.spec.timm_name, pretrained=False, dynamic_img_size=True)
678
+ self.encoder.requires_grad_(False)
679
+ self.dino_proj = TimestepProjection(
680
+ in_dim=self.spec.feature_dim,
681
+ out_dim=hidden_size,
682
+ hidden_size=hidden_size,
683
+ num_blocks=proj_num_blocks,
684
+ num_heads=proj_num_heads,
685
+ )
686
+ self.register_buffer("image_mean", torch.tensor(IMAGENET_MEAN).view(1, 3, 1, 1), persistent=False)
687
+ self.register_buffer("image_std", torch.tensor(IMAGENET_STD).view(1, 3, 1, 1), persistent=False)
688
+
689
+ def train(self, mode: bool = True) -> "GroundingConditioner":
690
+ r"""
691
+ Keep the frozen encoder in eval mode.
692
+
693
+ Args:
694
+ mode (`bool`, defaults to `True`):
695
+ Whether the projection should train.
696
+
697
+ Returns:
698
+ `GroundingConditioner`: This module.
699
+ """
700
+ super().train(mode)
701
+ self.encoder.eval()
702
+ return self
703
+
704
+ def preprocess(self, hidden_states: torch.Tensor) -> tuple[torch.Tensor, tuple[int, int]]:
705
+ r"""
706
+ Map pixels from `[-1, 1]` to the encoder's ImageNet normalization.
707
+
708
+ Args:
709
+ hidden_states (`torch.Tensor`):
710
+ Images of shape `(batch, 3, height, width)` in model range `[-1, 1]`.
711
+
712
+ Returns:
713
+ `tuple[torch.Tensor, tuple[int, int]]`:
714
+ Normalized encoder input and the denoiser patch grid `(grid_h, grid_w)`.
715
+ """
716
+ height, width = hidden_states.shape[-2:]
717
+ grid_hw = (height // self.target_patch_size, width // self.target_patch_size)
718
+ encoder_hw = (grid_hw[0] * self.spec.patch_size, grid_hw[1] * self.spec.patch_size)
719
+ hidden_states = (hidden_states + 1.0) * 0.5
720
+ hidden_states = (hidden_states - self.image_mean.to(hidden_states.dtype)) / self.image_std.to(hidden_states.dtype)
721
+ if encoder_hw != (height, width):
722
+ hidden_states = F.interpolate(hidden_states, size=encoder_hw, mode="bicubic", align_corners=False)
723
+ return hidden_states, grid_hw
724
+
725
+ def _zero_key_bias(self) -> None:
726
+ """Keep DINOv3 key bias at zero.
727
+
728
+ timm's qkvb attention stores a zero key bias as a non-persistent buffer, so it
729
+ is absent from the checkpoint. `from_pretrained` builds the encoder on the meta
730
+ device and materializes missing buffers as uninitialized memory. A non-zero key
731
+ bias makes attention NaN.
732
+ """
733
+ for module in self.encoder.modules():
734
+ bias = getattr(module, "k_bias", None)
735
+ if isinstance(bias, torch.Tensor) and bias.device.type != "meta":
736
+ bias.zero_()
737
+
738
+ def encode(self, hidden_states: torch.Tensor) -> tuple[torch.Tensor, tuple[int, int]]:
739
+ r"""
740
+ Encode an image into patch tokens aligned with the denoiser grid.
741
+
742
+ Args:
743
+ hidden_states (`torch.Tensor`):
744
+ Images of shape `(batch, 3, height, width)` in `[-1, 1]`.
745
+
746
+ Returns:
747
+ `tuple[torch.Tensor, tuple[int, int]]`:
748
+ Tokens `(batch, grid_h * grid_w, feature_dim)` and the grid size.
749
+ """
750
+ self._zero_key_bias()
751
+ encoder_input, grid_hw = self.preprocess(hidden_states)
752
+ with torch.no_grad():
753
+ features = self.encoder.forward_features(encoder_input)
754
+ prefix = int(getattr(self.encoder, "num_prefix_tokens", 0))
755
+ tokens = features[:, prefix:, :]
756
+ encoder_grid = (
757
+ encoder_input.shape[-2] // self.spec.patch_size,
758
+ encoder_input.shape[-1] // self.spec.patch_size,
759
+ )
760
+ if encoder_grid != grid_hw:
761
+ batch, _, channels = tokens.shape
762
+ tokens = tokens.transpose(1, 2).reshape(batch, channels, *encoder_grid)
763
+ tokens = F.interpolate(tokens, size=grid_hw, mode="bilinear", align_corners=False)
764
+ tokens = tokens.flatten(2).transpose(1, 2)
765
+ return tokens, grid_hw
766
+
767
+ def forward(self, hidden_states: torch.Tensor, timesteps: torch.Tensor) -> torch.Tensor:
768
+ r"""
769
+ Encode and project grounding tokens.
770
+
771
+ Args:
772
+ hidden_states (`torch.Tensor`):
773
+ Images of shape `(batch, 3, height, width)`.
774
+ timesteps (`torch.Tensor`):
775
+ Flow time of shape `(batch,)`.
776
+
777
+ Returns:
778
+ `torch.Tensor`: Grounding of shape `(batch, patches, hidden_size)`.
779
+ """
780
+ tokens, grid_hw = self.encode(hidden_states)
781
+ return self.dino_proj(tokens.to(dtype=self.dino_proj.input_proj.weight.dtype), timesteps, grid_hw)
782
+
783
+
784
+ class PixelDiT2Transformer2DModel(ModelMixin, ConfigMixin):
785
+ r"""
786
+ PixelDiT2 class-conditional denoiser.
787
+
788
+ The module names match the training checkpoint (`t_embedder`, `y_embedder`, `s_embedder`,
789
+ `patch_blocks`, `final_layer`, `dino_conditioner`) so an EMA state dict loads without renaming.
790
+
791
+ Args:
792
+ sample_size (`int`, defaults to 256):
793
+ Native square resolution in pixels. Other multiples of `patch_size` are valid at inference
794
+ because rotary positions are recomputed for the requested grid.
795
+ in_channels (`int`, defaults to 3):
796
+ Image channels.
797
+ patch_size (`int`, defaults to 16):
798
+ Pixel patch size. `height` and `width` must be divisible by this value.
799
+ hidden_size (`int`, defaults to 1280):
800
+ Token width of PixelDiT2-H.
801
+ num_heads (`int`, defaults to 16):
802
+ Attention heads.
803
+ depth (`int`, defaults to 32):
804
+ Number of patch blocks.
805
+ num_classes (`int`, defaults to 1000):
806
+ ImageNet classes. The embedding table has `num_classes + 1` rows; the last row is the null class.
807
+ in_context_len (`int`, defaults to 32):
808
+ Number of in-context class tokens inserted at `in_context_start`.
809
+ in_context_start (`int`, defaults to 8):
810
+ Block index at which the in-context tokens are inserted. Must lie in `[0, depth)`.
811
+ attn_dropout (`float`, defaults to 0.0):
812
+ Attention dropout on the middle half of the blocks.
813
+ proj_dropout (`float`, defaults to 0.2):
814
+ Projection dropout on the middle half of the blocks. Inactive in `eval()`.
815
+ mlp_hidden_multiple (`int`, defaults to 0):
816
+ SwiGLU width rounding. `0` for 256px, `32` for 512px.
817
+ grounding_encoder (`str`, defaults to `"dinov3_vits16"`):
818
+ Frozen encoder key. 256px uses `dinov3_vits16`; 512px uses `dinov3_vitb16`.
819
+ grounding_proj_blocks (`int`, defaults to 1):
820
+ Blocks in the grounding projection.
821
+ grounding_proj_heads (`int`, defaults to 16):
822
+ Heads in the grounding projection.
823
+ single_silu_cond (`bool`, defaults to `False`):
824
+ When `False` (256px), SiLU is applied to the summed condition. When `True` (512px), it is not.
825
+ guidance_scale (`float`, defaults to 2.4):
826
+ Recommended classifier-free guidance scale. Read by the pipeline when the caller omits it.
827
+ guidance_interval_min (`float`, defaults to 0.125):
828
+ Lower flow-time bound of the guidance interval, exclusive.
829
+ guidance_interval_max (`float`, defaults to 0.9):
830
+ Upper flow-time bound of the guidance interval, exclusive.
831
+ noise_scale (`float`, defaults to 1.0):
832
+ Standard deviation of the initial Gaussian. 1.0 at 256px and 2.0 at 512px.
833
+ t_eps (`float`, defaults to 0.05):
834
+ Minimum denominator when converting an x0 prediction into a velocity.
835
+ default_num_inference_steps (`int`, defaults to 50):
836
+ Heun steps used when the pipeline caller omits `num_inference_steps`.
837
+ """
838
+
839
+ @register_to_config
840
+ def __init__(
841
+ self,
842
+ sample_size: int = 256,
843
+ in_channels: int = 3,
844
+ patch_size: int = 16,
845
+ hidden_size: int = 1280,
846
+ num_heads: int = 16,
847
+ depth: int = 32,
848
+ num_classes: int = 1000,
849
+ in_context_len: int = 32,
850
+ in_context_start: int = 8,
851
+ attn_dropout: float = 0.0,
852
+ proj_dropout: float = 0.2,
853
+ mlp_hidden_multiple: int = 0,
854
+ grounding_encoder: str = "dinov3_vits16",
855
+ grounding_proj_blocks: int = 1,
856
+ grounding_proj_heads: int = 16,
857
+ single_silu_cond: bool = False,
858
+ guidance_scale: float = 2.4,
859
+ guidance_interval_min: float = 0.125,
860
+ guidance_interval_max: float = 0.9,
861
+ noise_scale: float = 1.0,
862
+ t_eps: float = 0.05,
863
+ default_num_inference_steps: int = 50,
864
+ ):
865
+ super().__init__()
866
+ if not 0 <= in_context_start < depth:
867
+ raise ValueError(f"in_context_start must be in [0, {depth - 1}], got {in_context_start}.")
868
+ if hidden_size % num_heads != 0:
869
+ raise ValueError(f"hidden_size={hidden_size} must be divisible by num_heads={num_heads}.")
870
+
871
+ self.in_channels = in_channels
872
+ self.out_channels = in_channels
873
+ self.hidden_size = hidden_size
874
+ self.num_heads = num_heads
875
+ self.depth = depth
876
+ self.patch_size = patch_size
877
+ self.num_classes = num_classes
878
+ self.in_context_len = in_context_len
879
+ self.in_context_start = in_context_start
880
+ self.single_silu_cond = single_silu_cond
881
+
882
+ self.t_embedder = TimestepConditioner(hidden_size)
883
+ self.y_embedder = ClassEmbedder(num_classes + 1, hidden_size)
884
+ self.s_embedder = PatchTokenEmbedder(in_channels * patch_size**2, hidden_size, bias=True)
885
+ self.in_context_posemb = nn.Parameter(torch.zeros(1, in_context_len, hidden_size)) if in_context_len > 0 else None
886
+ self.patch_blocks = nn.ModuleList(
887
+ [
888
+ ModulatedDiTBlock(
889
+ hidden_size,
890
+ num_heads,
891
+ attn_drop=attn_dropout if depth // 4 <= i < depth // 4 * 3 else 0.0,
892
+ proj_drop=proj_dropout if depth // 4 <= i < depth // 4 * 3 else 0.0,
893
+ mlp_hidden_multiple=mlp_hidden_multiple,
894
+ )
895
+ for i in range(depth)
896
+ ]
897
+ )
898
+ self.final_layer = PatchFinalLayer(hidden_size, patch_size, self.out_channels)
899
+ self._init_denoiser_weights()
900
+ self.dino_conditioner = GroundingConditioner(
901
+ encoder_name=grounding_encoder,
902
+ hidden_size=hidden_size,
903
+ target_patch_size=patch_size,
904
+ proj_num_blocks=grounding_proj_blocks,
905
+ proj_num_heads=grounding_proj_heads,
906
+ )
907
+ self._pos_cache: dict[tuple[int, int, int], torch.Tensor] = {}
908
+
909
+ def _init_denoiser_weights(self) -> None:
910
+ r"""
911
+ Initialize the trainable denoiser the same way as the training code.
912
+
913
+ The grounding encoder is created afterwards and is not touched here.
914
+ """
915
+ weight = self.s_embedder.proj.weight.data
916
+ nn.init.xavier_uniform_(weight.view([weight.shape[0], -1]))
917
+ nn.init.constant_(self.s_embedder.proj.bias, 0)
918
+ nn.init.normal_(self.y_embedder.embedding_table.weight, std=0.02)
919
+ nn.init.normal_(self.t_embedder.mlp[0].weight, std=0.02)
920
+ nn.init.normal_(self.t_embedder.mlp[2].weight, std=0.02)
921
+ if self.in_context_posemb is not None:
922
+ nn.init.normal_(self.in_context_posemb, std=0.02)
923
+ for block in self.patch_blocks:
924
+ nn.init.zeros_(block.adaLN_modulation[-1].weight)
925
+ nn.init.zeros_(block.adaLN_modulation[-1].bias)
926
+ nn.init.zeros_(self.final_layer.linear.weight)
927
+ nn.init.zeros_(self.final_layer.linear.bias)
928
+ nn.init.zeros_(self.final_layer.adaLN_modulation[-1].weight)
929
+ nn.init.zeros_(self.final_layer.adaLN_modulation[-1].bias)
930
+
931
+ def fetch_pos(self, height: int, width: int, device: torch.device, num_context_tokens: int = 0) -> torch.Tensor:
932
+ r"""
933
+ RoPE table for a patch grid, with an identity prefix when context tokens are present.
934
+
935
+ Args:
936
+ height (`int`):
937
+ Grid height in patches.
938
+ width (`int`):
939
+ Grid width in patches.
940
+ device (`torch.device`):
941
+ Device of the returned table.
942
+ num_context_tokens (`int`, defaults to 0):
943
+ Leading tokens that receive an identity rotation (real part 1, imaginary part 0).
944
+
945
+ Returns:
946
+ `torch.Tensor`: Complex frequencies of shape `(num_context_tokens + height * width, head_dim / 2)`.
947
+ """
948
+ key = (height, width, num_context_tokens)
949
+ if key not in self._pos_cache:
950
+ pos = precompute_freqs_cis_2d(self.hidden_size // self.num_heads, height, width)
951
+ if num_context_tokens > 0:
952
+ identity = torch.ones(num_context_tokens, pos.shape[-1], dtype=pos.dtype)
953
+ pos = torch.cat([identity, pos], dim=0)
954
+ self._pos_cache[key] = pos
955
+ return self._pos_cache[key].to(device)
956
+
957
+ def _grounded_condition(
958
+ self,
959
+ hidden_states: torch.Tensor,
960
+ timesteps: torch.Tensor,
961
+ timestep_embedding: torch.Tensor,
962
+ class_embedding: torch.Tensor,
963
+ ) -> torch.Tensor:
964
+ r"""
965
+ Conditioning used by the class-conditional branch.
966
+
967
+ Args:
968
+ hidden_states (`torch.Tensor`):
969
+ Noisy images `(batch, channels, height, width)`.
970
+ timesteps (`torch.Tensor`):
971
+ Flow time `(batch,)`.
972
+ timestep_embedding (`torch.Tensor`):
973
+ Timestep embedding `(batch, hidden)`.
974
+ class_embedding (`torch.Tensor`):
975
+ Class embedding `(batch, 1, hidden)`.
976
+
977
+ Returns:
978
+ `torch.Tensor`: Per-patch conditioning `(batch, patches, hidden)`.
979
+ """
980
+ grounding = self.dino_conditioner(hidden_states, timesteps)
981
+ conditioning = grounding + timestep_embedding.unsqueeze(1) + class_embedding
982
+ if self.single_silu_cond:
983
+ return conditioning
984
+ return F.silu(conditioning)
985
+
986
+ def _null_condition(
987
+ self,
988
+ timestep_embedding: torch.Tensor,
989
+ class_embedding: torch.Tensor,
990
+ num_patches: int,
991
+ ) -> torch.Tensor:
992
+ r"""
993
+ Conditioning used when grounding is dropped.
994
+
995
+ Args:
996
+ timestep_embedding (`torch.Tensor`):
997
+ Timestep embedding `(batch, hidden)`.
998
+ class_embedding (`torch.Tensor`):
999
+ Class embedding `(batch, 1, hidden)`.
1000
+ num_patches (`int`):
1001
+ Number of spatial patches to broadcast over.
1002
+
1003
+ Returns:
1004
+ `torch.Tensor`: Conditioning `(batch, num_patches, hidden)`.
1005
+ """
1006
+ conditioning = timestep_embedding.unsqueeze(1) + class_embedding
1007
+ if not self.single_silu_cond:
1008
+ conditioning = F.silu(conditioning)
1009
+ return conditioning.expand(-1, num_patches, -1)
1010
+
1011
+ def forward(
1012
+ self,
1013
+ hidden_states: torch.Tensor,
1014
+ timestep: torch.Tensor,
1015
+ class_labels: torch.Tensor,
1016
+ skip_grounding: bool = False,
1017
+ skip_grounding_mask: torch.Tensor | None = None,
1018
+ return_dict: bool = True,
1019
+ ) -> Transformer2DModelOutput | tuple:
1020
+ r"""
1021
+ Predict the clean image x0.
1022
+
1023
+ Args:
1024
+ hidden_states (`torch.Tensor`):
1025
+ Noisy RGB sample of shape `(batch, in_channels, height, width)`, in model range around `[-1, 1]`.
1026
+ `height` and `width` must be divisible by `patch_size`.
1027
+ timestep (`torch.Tensor`):
1028
+ Flow-matching time `t` in `[0, 1]`, shape `(batch,)` or a scalar broadcast to the batch.
1029
+ `t = 0` is noise and `t = 1` is data.
1030
+ class_labels (`torch.Tensor`):
1031
+ Integer ImageNet ids of shape `(batch,)`. The null class is `num_classes`.
1032
+ skip_grounding (`bool`, defaults to `False`):
1033
+ When `True`, do not run the DINOv3 encoder. The unconditional CFG branch sets this.
1034
+ skip_grounding_mask (`torch.Tensor`, *optional*):
1035
+ Boolean mask of shape `(batch,)`. `True` rows use the null grounding condition.
1036
+ Ignored when `skip_grounding` is `True`.
1037
+ return_dict (`bool`, defaults to `True`):
1038
+ Return [`Transformer2DModelOutput`] when `True`, otherwise a one-tuple of the sample.
1039
+
1040
+ Returns:
1041
+ [`Transformer2DModelOutput`] or `tuple`:
1042
+ The x0 prediction of shape `(batch, in_channels, height, width)`.
1043
+ """
1044
+ batch, _, height, width = hidden_states.shape
1045
+ if height % self.patch_size or width % self.patch_size:
1046
+ raise ValueError(
1047
+ f"Input resolution ({height}, {width}) must be divisible by patch_size={self.patch_size}."
1048
+ )
1049
+ timestep = timestep.reshape(batch)
1050
+ class_labels = class_labels.reshape(batch).long()
1051
+ grid_h, grid_w = height // self.patch_size, width // self.patch_size
1052
+ num_patches = grid_h * grid_w
1053
+
1054
+ timestep_embedding = self.t_embedder(timestep)
1055
+ class_embedding = self.y_embedder(class_labels).view(batch, 1, self.hidden_size)
1056
+
1057
+ if skip_grounding:
1058
+ conditioning = self._null_condition(timestep_embedding, class_embedding, num_patches)
1059
+ else:
1060
+ conditioning = self._grounded_condition(hidden_states, timestep, timestep_embedding, class_embedding)
1061
+ if skip_grounding_mask is not None:
1062
+ null_conditioning = self._null_condition(timestep_embedding, class_embedding, num_patches)
1063
+ conditioning = torch.where(skip_grounding_mask.view(batch, 1, 1), null_conditioning, conditioning)
1064
+
1065
+ tokens = self.s_embedder(F.unfold(hidden_states, kernel_size=self.patch_size, stride=self.patch_size).transpose(1, 2))
1066
+ use_context = self.in_context_len > 0
1067
+ pos = self.fetch_pos(grid_h, grid_w, hidden_states.device)
1068
+ pos_with_context = self.fetch_pos(grid_h, grid_w, hidden_states.device, self.in_context_len) if use_context else None
1069
+ if use_context:
1070
+ context_conditioning = conditioning.mean(dim=1, keepdim=True).expand(-1, self.in_context_len, -1)
1071
+ conditioning_extended = torch.cat([context_conditioning, conditioning], dim=1)
1072
+
1073
+ context_inserted = False
1074
+ for index, block in enumerate(self.patch_blocks):
1075
+ if use_context and not context_inserted and index == self.in_context_start:
1076
+ context_tokens = class_embedding.expand(-1, self.in_context_len, -1)
1077
+ tokens = torch.cat([context_tokens + self.in_context_posemb.to(tokens.dtype), tokens], dim=1)
1078
+ context_inserted = True
1079
+ tokens = block(
1080
+ tokens,
1081
+ conditioning_extended if context_inserted else conditioning,
1082
+ pos_with_context if context_inserted else pos,
1083
+ )
1084
+ if context_inserted:
1085
+ tokens = tokens[:, self.in_context_len :, :]
1086
+
1087
+ output = self.final_layer(tokens, conditioning)
1088
+ output = output.view(batch, num_patches, self.patch_size**2, self.out_channels)
1089
+ output = output.permute(0, 3, 2, 1).reshape(batch, self.out_channels * self.patch_size**2, num_patches)
1090
+ output = F.fold(output, (height, width), kernel_size=self.patch_size, stride=self.patch_size)
1091
+
1092
+ if not return_dict:
1093
+ return (output,)
1094
+ return Transformer2DModelOutput(sample=output)
README.md ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: other
3
+ license_name: nsclv1
4
+ license_link: https://huggingface.co/nvidia/PixelDiT2-ImageNet
5
+ library_name: diffusers
6
+ tags:
7
+ - diffusers
8
+ - pixeldit2
9
+ - image-generation
10
+ - class-conditional
11
+ - imagenet
12
+ - flow-matching
13
+ - pixel-space
14
+ inference: true
15
+ widget:
16
+ - text: golden retriever
17
+ output:
18
+ url: PixelDiT2-H-16-256/demo.png
19
+ - text: golden retriever
20
+ output:
21
+ url: PixelDiT2-H-16-512/demo.png
22
+ language:
23
+ - en
24
+ ---
25
+
26
+ # BiliSakura/PixelDiT2-diffusers
27
+
28
+ Self-contained PixelDiT2 class-conditional checkpoints for Hugging Face diffusers. PixelDiT2 denoises in RGB pixel space (no VAE). Each variant ships its original DINOv3 checkpoint in `encoder/` and the mapped copy inside the transformer weights, so inference does not download it. 256px uses DINOv3-S/16. 512px uses DINOv3-B/16.
29
+
30
+ This repository is PixelDiT2 only. The earlier PixelDiT family is [BiliSakura/PixelDiT-diffusers](https://huggingface.co/BiliSakura/PixelDiT-diffusers).
31
+
32
+ ## Demo
33
+
34
+ ![PixelDiT2-H/16 256 demo](PixelDiT2-H-16-256/demo.png)
35
+
36
+ Class: *golden retriever* (ImageNet 207). PixelDiT2-H/16 at 256Γ—256, 50 Heun steps, `guidance_scale=2.4`, interval `(0.125, 0.9)`, `noise_scale=1.0`, `torch_dtype=bfloat16`, seed 1, on `cuda:0`.
37
+
38
+ ![PixelDiT2-H/16 512 demo](PixelDiT2-H-16-512/demo.png)
39
+
40
+ Same class at 512Γ—512, 50 Heun steps, `guidance_scale=2.1`, interval `(0.1, 0.925)`, `noise_scale=2.0`, `torch_dtype=bfloat16`, seed 1, on `cuda:0`.
41
+
42
+ ## Available checkpoints
43
+
44
+ | Subfolder | Resolution | Source checkpoint | Encoder | Steps | CFG | CFG interval | Noise scale |
45
+ | --- | --- | --- | --- | ---: | ---: | --- | ---: |
46
+ | [`PixelDiT2-H-16-256/`](PixelDiT2-H-16-256/) | 256Γ—256 | `pixeldit2_h16_in256_ep600.ckpt` | DINOv3-S/16 | 50 | 2.4 | (0.125, 0.9) | 1.0 |
47
+ | [`PixelDiT2-H-16-512/`](PixelDiT2-H-16-512/) | 512Γ—512 | `pixeldit2_h16_in512_ep680.ckpt` | DINOv3-B/16 | 50 | 2.1 | (0.1, 0.925) | 2.0 |
48
+
49
+ Reported ImageNet FID is 1.46 at 256Γ—256 and 1.48 at 512Γ—512 (50k samples, Heun, 50 steps).
50
+
51
+ ## Repo layout
52
+
53
+ ```text
54
+ BiliSakura/PixelDiT2-diffusers/
55
+ β”œβ”€β”€ README.md
56
+ β”œβ”€β”€ .gitattributes
57
+ β”œβ”€β”€ PixelDiT2-H-16-256/
58
+ β”‚ β”œβ”€β”€ pipeline.py
59
+ β”‚ β”œβ”€β”€ model_index.json
60
+ β”‚ β”œβ”€β”€ demo.png
61
+ β”‚ β”œβ”€β”€ encoder/
62
+ β”‚ β”œβ”€β”€ scheduler/scheduling_pixeldit2.py
63
+ β”‚ └── transformer/
64
+ └── PixelDiT2-H-16-512/
65
+ β”œβ”€β”€ pipeline.py
66
+ β”œβ”€β”€ model_index.json
67
+ β”œβ”€β”€ demo.png
68
+ β”œβ”€β”€ encoder/
69
+ β”œβ”€β”€ scheduler/scheduling_pixeldit2.py
70
+ └── transformer/
71
+ ```
72
+
73
+ `scheduler/scheduling_pixeldit2.py` is `PixelDiT2Scheduler`. It integrates flow time from 0 to 1 with Heun, and uses Euler on the last interval. Each variant is self-contained.
74
+
75
+ ## Load from Hugging Face
76
+
77
+ ```python
78
+ import torch
79
+ from diffusers import DiffusionPipeline
80
+
81
+ pipe = DiffusionPipeline.from_pretrained(
82
+ "BiliSakura/PixelDiT2-diffusers",
83
+ subfolder="PixelDiT2-H-16-256",
84
+ custom_pipeline="pipeline.py",
85
+ trust_remote_code=True,
86
+ torch_dtype=torch.bfloat16,
87
+ ).to("cuda:0")
88
+
89
+ generator = torch.Generator(device="cuda:0").manual_seed(1)
90
+ image = pipe(
91
+ class_labels="golden retriever",
92
+ num_inference_steps=50,
93
+ guidance_scale=2.4,
94
+ guidance_interval_min=0.125,
95
+ guidance_interval_max=0.9,
96
+ generator=generator,
97
+ ).images[0]
98
+ image.save("demo.png")
99
+ ```
100
+
101
+ ## Load from a local clone
102
+
103
+ ```python
104
+ from pathlib import Path
105
+ import torch
106
+ from diffusers import DiffusionPipeline
107
+
108
+ model_dir = Path("PixelDiT2-H-16-256").resolve()
109
+ pipe = DiffusionPipeline.from_pretrained(
110
+ str(model_dir),
111
+ local_files_only=True,
112
+ custom_pipeline=str(model_dir / "pipeline.py"),
113
+ trust_remote_code=True,
114
+ torch_dtype=torch.bfloat16,
115
+ ).to("cuda:0")
116
+
117
+ print(pipe.id2label[207])
118
+ print(pipe.get_label_ids("golden retriever"))
119
+
120
+ generator = torch.Generator(device="cuda:0").manual_seed(1)
121
+ image = pipe(class_labels="golden retriever", generator=generator).images[0]
122
+ image.save("demo.png")
123
+ ```
124
+
125
+ Place the model on one GPU with `.to("cuda:0")`. Do not call `enable_model_cpu_offload()`.
126
+
127
+ Point `model_dir` at `PixelDiT2-H-16-512` for the 512px checkpoint. Omitting the sampling arguments uses that folder's config: 50 steps, `guidance_scale=2.1`, interval `(0.1, 0.925)`, `noise_scale=2.0`.
128
+
129
+ `height` and `width` must be divisible by 16. Other sizes recompute rotary positions for that grid. One evaluation per step uses the same linspace: `pipe.scheduler = pipe.scheduler.__class__.from_config(pipe.scheduler.config, solver="euler")`.
130
+
131
+ ## ImageNet class labels
132
+
133
+ `id2label` is in each variant's `model_index.json`.
134
+
135
+ - `pipe.id2label` β€” id to English label
136
+ - `pipe.labels` β€” synonym to id
137
+ - `pipe.get_label_ids("golden retriever")`
138
+ - `pipe(class_labels="golden retriever")` β€” strings resolve automatically
139
+
140
+ ## Citation
141
+
142
+ ```bibtex
143
+ @inproceedings{yu2026pixeldit2,
144
+ title={PixelDiT2: Representation-Grounded Pixel Diffusion Transformers},
145
+ author={Yongsheng Yu and Wei Xiong and Yichen Sheng and Shiqiu Liu and Jiebo Luo},
146
+ booktitle={Conference on Neural Information Processing Systems (NeurIPS)},
147
+ year={2026},
148
+ }
149
+ ```
150
+
151
+ ## License
152
+
153
+ Pipeline code in this repository is Apache-2.0. Converted weights remain under the NVIDIA NSCLv1 non-commercial research license of [nvidia/PixelDiT2-ImageNet](https://huggingface.co/nvidia/PixelDiT2-ImageNet).