ij commited on
Commit
aca0f1d
·
verified ·
1 Parent(s): 4e5fb00

Release Anima Style Embedding v2

Browse files
.gitattributes CHANGED
@@ -37,3 +37,8 @@ assets/generalization_and_gallery_size.png filter=lfs diff=lfs merge=lfs -text
37
  assets/learned_vs_frozen_baseline.png filter=lfs diff=lfs merge=lfs -text
38
  assets/reference_count_curve.png filter=lfs diff=lfs merge=lfs -text
39
  assets/training_validation_curves.png filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
37
  assets/learned_vs_frozen_baseline.png filter=lfs diff=lfs merge=lfs -text
38
  assets/reference_count_curve.png filter=lfs diff=lfs merge=lfs -text
39
  assets/training_validation_curves.png filter=lfs diff=lfs merge=lfs -text
40
+ assets/architecture_imagegen_v1.png filter=lfs diff=lfs merge=lfs -text
41
+ assets/domain_reference_count_imagegen_v1.png filter=lfs diff=lfs merge=lfs -text
42
+ assets/factor_control_imagegen_v1.png filter=lfs diff=lfs merge=lfs -text
43
+ assets/hero_shared_axis_imagegen_v1.png filter=lfs diff=lfs merge=lfs -text
44
+ assets/set_retrieval_matrix_imagegen_v1.png filter=lfs diff=lfs merge=lfs -text
README.md CHANGED
@@ -1,88 +1,140 @@
1
  ---
2
- library_name: pytorch
3
- pipeline_tag: feature-extraction
4
  license: other
5
  license_name: circlestone-labs-non-commercial-license
6
- license_link: LICENSE.md
7
- base_model:
8
- - circlestone-labs/Anima
9
- - timm/vit_so400m_patch16_siglip_gap_512.v2_webli
10
  tags:
11
  - anime
 
12
  - style-embedding
13
  - image-retrieval
14
  - reference-image
15
- - siglip2
 
16
  - anima
17
- - pytorch
18
  ---
19
 
20
- # Anima Style Embedding v1.0
21
 
22
- **A multi-reference style encoder for person-centric anime and illustration images.**
23
 
24
- Anima Style Embedding converts one to eight reference images into a normalized 512-dimensional style vector. It combines multi-level SigLIP2 features from the full image and face with internal Anima features, then grounds the result across the complete reference set. The embedding is designed for open-set style retrieval and reference-driven style transfer systems rather than a fixed bank of known artists.
25
 
26
- | Model size | References | Embedding | Modalities |
27
- |---:|---:|---:|---|
28
- | 17.49M parameters | 18 images | 512-D, L2-normalized | Full image + face + Anima internals |
29
 
30
- ![Learned encoder versus frozen backbone](assets/learned_vs_frozen_baseline.png)
31
 
32
  ## Highlights
33
 
34
- - **Open-set style representation:** unseen artists can be embedded directly from reference images.
35
- - **Native multi-reference grounding:** Reference Consensus Re-reading lets each image be interpreted in the context of the complete 1–8 image set.
36
- - **Full-image and face awareness:** the encoder combines global composition and rendering cues with face-specific style information.
37
- - **Anima-aware features:** three internal Anima blocks complement SigLIP2 visual features with representations aligned to the target generator.
38
- - **Strong retrieval gains:** unseen synthetic-style MRR improves from 32.0% with the frozen SigLIP2 Full+Face baseline to 60.8% with the learned encoder on the 4,500-way validation gallery.
 
39
 
40
  ## Performance
41
 
42
- Retrieval uses cosine similarity between normalized query embeddings and five-image style prototypes.
 
 
 
 
 
 
 
 
 
 
 
 
43
 
44
- ### 4,500-way validation unseen identities
 
 
 
 
45
 
46
- The unseen subset contains 500 identities retrieved against a gallery of 4,500 styles.
47
 
48
- | Source | Top-1 | Top-5 | MRR |
49
- |---|---:|---:|---:|
50
- | Synthetic | 51.8% | 71.7% | 60.8% |
51
- | Human | 56.4% | 75.3% | 65.0% |
 
52
 
53
- ### 500-way sealed test unseen identities
54
 
55
- | Source | Top-1 | Top-5 | MRR |
56
- |---|---:|---:|---:|
57
- | Synthetic | 73.8% | 90.3% | 81.1% |
58
- | Human | 76.1% | 92.0% | 83.0% |
59
 
60
- The sealed test uses a smaller gallery than validation, so its absolute scores should be read independently.
61
 
62
- ![Generalization and gallery-size sensitivity](assets/generalization_and_gallery_size.png)
63
 
64
- ### Reference count
 
 
 
 
 
65
 
66
- More references consistently improve human-style grounding. Synthetic K=5 uses the locked controlled/matched/cross-content protocol and is shown separately from the generic K diagnostics.
67
 
68
- ![Reference count evaluation](assets/reference_count_curve.png)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
 
70
  ## Architecture
71
 
72
- The encoder projects full-image, face, and Anima tokens into a shared 512-wide space and reads them with four eight-head mixer blocks. Functional Style Factorization introduces four auxiliary style queries during training. Reference Consensus Re-reading computes a consensus across the reference set, re-reads every image under that context, and forms an agreement-weighted prototype.
 
 
73
 
74
- | Input | Shape per batch |
 
 
 
 
 
 
 
 
 
 
75
  |---|---|
76
- | Full-image SigLIP2 features | `[B, R, 30, 1152]` |
77
- | Face SigLIP2 features | `[B, R, 30, 1152]` |
78
- | Face validity mask | `[B, R]` |
79
- | Anima internal features | `[B, R, 3, 4096]` |
80
- | Reference mask | `[B, R]` |
81
 
82
- SigLIP2 features use [`timm/vit_so400m_patch16_siglip_gap_512.v2_webli`](https://huggingface.co/timm/vit_so400m_patch16_siglip_gap_512.v2_webli) at 512×512 and three backbone depths. Anima features use 768×768 inputs and blocks 8, 18, and 26 at sigma 0.1.
83
 
84
  ## Quick start
85
 
 
 
86
  ```python
87
  import json
88
 
@@ -90,59 +142,99 @@ import torch
90
  from huggingface_hub import hf_hub_download
91
  from safetensors.torch import load_file
92
 
93
- from modeling_anima_style_embedding import UnifiedStyleEncoder
94
 
95
  repo_id = "Baragi-AI/Anima-Style-Embedding"
96
- config = json.load(open(hf_hub_download(repo_id, "config.json"), encoding="utf-8"))
97
- cfg = config["architecture"]
98
-
99
- encoder = UnifiedStyleEncoder(
100
- width=cfg["width"],
101
- blocks=cfg["blocks"],
102
- heads=cfg["heads"],
103
- embedding_dim=cfg["embedding_dim"],
104
- dropout=cfg["dropout"],
105
- use_anima=True,
106
- reference_grounding=cfg["reference_grounding"],
107
- functional_factors=cfg["functional_factors"],
108
- )
109
- encoder.load_state_dict(
110
- load_file(hf_hub_download(repo_id, "model.safetensors")),
111
- strict=True,
112
- )
113
  encoder.eval()
114
- ```
115
 
116
- ```python
117
  with torch.inference_mode():
118
- style_embedding, per_image_embeddings = encoder(
119
- full_features,
120
- reference_mask,
121
- face_features=face_features,
122
- face_mask=face_mask,
123
- anima_features=anima_features,
 
 
 
124
  )
125
 
126
- assert style_embedding.shape == (full_features.shape[0], 512)
 
 
 
 
127
  ```
128
 
129
- `modeling_anima_style_embedding.py` contains the matching encoder definition. The checkpoint expects precomputed SigLIP2 and Anima features; RGB and Anima feature extraction are supplied by downstream integrations.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
 
131
- ## Training
 
 
 
 
132
 
133
- The model was trained on 320,000 person-centric style records: 160,000 Anima-generated images and 160,000 human-created illustrations across 8,000 training identities. Synthetic and human examples are mixed within each batch. Training uses four RTX 5090 GPUs, BF16 DistributedDataParallel, 16-way episodes, two queries per prototype, variable 1–8 image support, global negatives, and weak hard-negative sampling. The 4,500-step checkpoint produced the best full-validation score.
134
 
135
- ![Training dynamics](assets/training_validation_curves.png)
136
 
137
- The training record is available in [Weights & Biases](https://wandb.ai/1wndrla17-kyung-hee-university/anima-style-embedding/runs/5c9ae843a14f46529fe9aaa604a78d3b). Machine-readable evaluation results are included under `metrics/`.
 
 
 
 
 
 
 
 
 
138
 
139
  ## Applications
140
 
141
  - reference-driven style transfer for Anima;
142
- - artist-style retrieval and clustering;
143
- - aggregation of multiple references into a single style prototype;
144
- - open-set style recognition for previously unseen artists;
145
- - similarity scoring and reference-set curation.
 
 
 
 
 
 
 
 
 
 
 
 
 
146
 
147
  ## Files
148
 
@@ -151,29 +243,28 @@ The training record is available in [Weights & Biases](https://wandb.ai/1wndrla1
151
  | `model.safetensors` | Encoder weights |
152
  | `config.json` | Architecture and feature contract |
153
  | `modeling_anima_style_embedding.py` | PyTorch model definition |
154
- | `metrics/` | Training curves and retrieval results |
 
 
155
  | `SHA256SUMS.json` | Release checksums |
156
-
157
- ## Limitations
158
-
159
- - The model is optimized for person-centric anime and illustration images; other domains are not evaluated.
160
- - Retrieval metrics measure representation quality, not generated-image fidelity.
161
- - Style and artist-associated content preferences are not completely disentangled.
162
- - Anima features must follow the documented model, block, resolution, and sigma configuration.
163
 
164
  ## License
165
 
166
- The model weights are distributed under the [CircleStone Labs Non-Commercial License v1.2](LICENSE.md). Commercial or production use requires appropriate authorization from CircleStone Labs.
167
 
168
- The original source code supplied with this release is available under the [Apache License 2.0](CODE_LICENSE). Third-party components remain subject to their respective licenses; attribution details are listed in [NOTICE](NOTICE) and [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
169
 
170
- Built on NVIDIA Cosmos.
171
 
172
  ## Citation
173
 
174
  ```bibtex
175
- @misc{baragi2026animastyleembedding,
176
- title = {Anima Style Embedding v1.0},
177
  author = {{Baragi AI}},
178
  year = {2026},
179
  howpublished = {Hugging Face model repository},
 
1
  ---
 
 
2
  license: other
3
  license_name: circlestone-labs-non-commercial-license
4
+ license_link: https://huggingface.co/circlestone-labs/Anima/blob/main/LICENSE.md
5
+ library_name: pytorch
6
+ pipeline_tag: feature-extraction
7
+ base_model: circlestone-labs/Anima
8
  tags:
9
  - anime
10
+ - illustration
11
  - style-embedding
12
  - image-retrieval
13
  - reference-image
14
+ - multi-reference
15
+ - dinov3
16
  - anima
17
+ - controllable-generation
18
  ---
19
 
20
+ # Anima Style Embedding v2
21
 
22
+ A multi-reference shared-axis style encoder for anime and illustration images.
23
 
24
+ Anima Style Embedding v2 converts one to eight reference images into a normalized 1,024-dimensional embedding and a controllable style memory for Anima. It preserves spatial VAE evidence, adds DINOv3 visual context and Anima-aware descriptors, and represents Line, Color, Texture, and Layout as overlapping memberships on one 256-axis style field.
25
 
26
+ | Model size | References | Embedding | Shared axes | Reference signals |
27
+ |---|---:|---:|---:|---|
28
+ | 51,991,809 parameters | 1-8 images | 1,024-D, L2-normalized | 256 | VAE + DINOv3-S+ + Anima |
29
 
30
+ ![Anima Style Embedding v2 overview: 91.2% Top-1 and 97.4% Top-5 for a disjoint four-image Gallery and two-image Probe evaluation.](assets/hero_shared_axis_imagegen_v1.png)
31
 
32
  ## Highlights
33
 
34
+ - **Style-disjoint evaluation:** retrieval is measured on 1,000 unseen style identities with separate Gallery and Probe image sets.
35
+ - **Native multi-reference reasoning:** the encoder compares one to eight references before producing the style representation.
36
+ - **One shared style field:** Line, Color, Texture, and Layout are overlapping memberships, not independent encoders.
37
+ - **Controllable routing:** Auto, Assisted, and Manual modes support per-image factor weights plus a separate Face weight.
38
+ - **Anima-ready memory:** the same shared axes produce the retrieval embedding and the style memory used by the native transfer path.
39
+ - **Position-free Layout evidence:** phase-free spatial-power statistics capture composition-like tendencies without copying absolute object coordinates.
40
 
41
  ## Performance
42
 
43
+ ### Disjoint set-to-set retrieval
44
+
45
+ Gallery and Probe embeddings are built from different images of the same style. The primary protocol uses cosine similarity, three fixed seeds, and a 1,000-style validation gallery. The sealed test split was not used for checkpoint selection or for the reported v2 results.
46
+
47
+ The headline condition uses a four-image Gallery and a two-image Probe:
48
+
49
+ | Top-1 | Top-5 |
50
+ |---:|---:|
51
+ | **91.23%** | **97.40%** |
52
+
53
+ ![Top-1 and Top-5 retrieval matrices for Gallery sets of 2, 4, and 8 images and Probe sets of 1, 2, 4, and 8 images.](assets/set_retrieval_matrix_imagegen_v1.png)
54
+
55
+ Top-1:
56
 
57
+ | Gallery \ Probe | 1 | 2 | 4 | 8 |
58
+ |---|---:|---:|---:|---:|
59
+ | 2 references | 67.07% | 81.93% | 89.90% | 93.97% |
60
+ | 4 references | 77.17% | 91.23% | 96.60% | 98.47% |
61
+ | 8 references | 83.27% | 95.07% | 98.83% | 99.83% |
62
 
63
+ Top-5:
64
 
65
+ | Gallery \ Probe | 1 | 2 | 4 | 8 |
66
+ |---|---:|---:|---:|---:|
67
+ | 2 references | 84.73% | 93.27% | 96.97% | 98.23% |
68
+ | 4 references | 91.23% | 97.40% | 99.27% | 99.70% |
69
+ | 8 references | 94.03% | 98.60% | 99.80% | 100.00% |
70
 
71
+ Machine-readable Overall, Synthetic, and Human results are included in [`metrics/evaluation-set-matrix.json`](metrics/evaluation-set-matrix.json).
72
 
73
+ ### Reference count and domain behavior
 
 
 
74
 
75
+ Human references have greater within-style variation when only one Probe image is available. With a two-image Gallery, the Synthetic/Human Top-1 gap narrows from 6.2 points at Probe-1 to 0.8 point at Probe-8.
76
 
77
+ ![Synthetic and Human Top-1 retrieval improve as the disjoint Probe reference set grows from one to eight images.](assets/domain_reference_count_imagegen_v1.png)
78
 
79
+ | Probe references | Synthetic Top-1 | Human Top-1 |
80
+ |---:|---:|---:|
81
+ | 1 | 69.20% | 63.00% |
82
+ | 2 | 83.27% | 79.73% |
83
+ | 4 | 90.73% | 88.47% |
84
+ | 8 | 93.80% | 93.00% |
85
 
86
+ ## Factor control and routing
87
 
88
+ Factor behavior is evaluated on 4,096 interventions from held-out transform families.
89
+
90
+ ![Held-out intervention accuracy, selective factor response, shared-axis overlap, and multi-reference routing results.](assets/factor_control_imagegen_v1.png)
91
+
92
+ | Factor | Classification accuracy | Target / non-target response |
93
+ |---|---:|---:|
94
+ | Line | 88.48% | 1.761x |
95
+ | Color | 64.16% | 1.406x |
96
+ | Texture | 94.04% | 2.393x |
97
+ | Layout | 91.70% | 1.970x |
98
+
99
+ | Control metric | Result |
100
+ |---|---:|
101
+ | Balanced factor accuracy | 84.60% |
102
+ | Strong > weak ordering | 98.83% of 2,048 pairs |
103
+ | Median factor-outlier suppression | 3.643x |
104
+ | Auto routing error reduction vs. uniform | 19.80% |
105
+ | Axes materially shared by all four factors | 82 |
106
+ | Effective rank | 248.35 / 256 |
107
+
108
+ Attribute reconstruction reduces error by 31.2% relative to a train-mean predictor. Removing a factor membership raises its corresponding attribute error, confirming that the memberships are used by the prediction path rather than serving only as labels.
109
 
110
  ## Architecture
111
 
112
+ ![Architecture from one to eight full and face references through VAE, DINOv3, and Anima signals into a shared 256-axis field, routing, a 1,024-D embedding, and Anima style memory.](assets/architecture_imagegen_v1.png)
113
+
114
+ The production encoder has one spatial field and one aligned dictionary:
115
 
116
+ 1. A convolutional stem preserves full-image and face VAE spatial fields.
117
+ 2. Each spatial token is projected into the same 256-axis dictionary.
118
+ 3. Per-axis moments and translation-invariant power statistics retain persistent and composition-like style evidence.
119
+ 4. DINOv3 and Anima projections add visual and generator-aware context to the aligned axes.
120
+ 5. A relation Transformer compares references before estimating per-axis reliability.
121
+ 6. Overlapping memberships expose Line, Color, Texture, and Layout views without splitting the representation into branches.
122
+ 7. The mixed axes produce both a normalized retrieval embedding and style memory for Anima conditioning.
123
+
124
+ ### Routing modes
125
+
126
+ | Mode | Behavior |
127
  |---|---|
128
+ | Auto | Uses learned per-reference, per-axis reliability. |
129
+ | Assisted | Multiplies learned reliability by user-provided factor and Face weights. |
130
+ | Manual | Uses user weights directly to choose factor suppliers. |
 
 
131
 
132
+ Weights normalize across references, so adding references does not automatically increase style strength. A zero Manual factor weight produces zero output contribution and zero gradient on that reference-factor path. Face controls face-token routing and is not treated as a fifth factor branch.
133
 
134
  ## Quick start
135
 
136
+ The v2 checkpoint expects precomputed features. Raw-RGB VAE, DINOv3-S+, and Anima descriptor extraction is not bundled in this release candidate.
137
+
138
  ```python
139
  import json
140
 
 
142
  from huggingface_hub import hf_hub_download
143
  from safetensors.torch import load_file
144
 
145
+ from modeling_anima_style_embedding import SharedAxisStyleEncoder
146
 
147
  repo_id = "Baragi-AI/Anima-Style-Embedding"
148
+ config_path = hf_hub_download(repo_id, "config.json")
149
+ weights_path = hf_hub_download(repo_id, "model.safetensors")
150
+
151
+ with open(config_path, encoding="utf-8") as file:
152
+ config = json.load(file)
153
+
154
+ encoder = SharedAxisStyleEncoder(**config["architecture"])
155
+ encoder.load_state_dict(load_file(weights_path), strict=True)
 
 
 
 
 
 
 
 
 
156
  encoder.eval()
 
157
 
 
158
  with torch.inference_mode():
159
+ output = encoder(
160
+ full_latents=full_latents,
161
+ face_latents=face_latents,
162
+ dino=dino_features,
163
+ anima=anima_features,
164
+ reference_valid=reference_valid,
165
+ face_valid=face_valid,
166
+ user_weights=user_weights,
167
+ mode="assisted",
168
  )
169
 
170
+ style_embedding = output["embedding"]
171
+ style_memory = output["style_memory"]
172
+ factor_coordinates = output["factor_coordinates"]
173
+
174
+ assert style_embedding.shape == (full_latents.shape[0], 1024)
175
  ```
176
 
177
+ ### Input contract
178
+
179
+ | Input | Shape | Notes |
180
+ |---|---|---|
181
+ | Full VAE latents | `[B, R, 16, H, W]` | Spatial full-image evidence |
182
+ | Face VAE latents | `[B, R, 16, Hf, Wf]` | Optional, masked by `face_valid` |
183
+ | DINOv3 full+face summary | `[B, R, 6912]` | Cached DINOv3-S+ context |
184
+ | Anima descriptors | `[B, R, 3, 4096]` | Three internal Anima blocks |
185
+ | Reference validity | `[B, R]` | At least one valid reference per sample |
186
+ | User weights | `[B, R, 5]` | Line, Color, Texture, Layout, Face |
187
+
188
+ ## Training data and split policy
189
+
190
+ The base corpus contains 500,000 images:
191
+
192
+ - 250,000 Anima-generated images from 5,000 Synthetic style identities;
193
+ - 250,000 human-created illustrations from 5,000 Human style identities.
194
+
195
+ Synthetic and Human identities remain separate even when artist names overlap. The split is identity-disjoint:
196
 
197
+ | Split | Images | Style identities | Use |
198
+ |---|---:|---:|---|
199
+ | Train | 400,000 | 8,000 | Optimization and training-only statistics |
200
+ | Validation | 50,000 | 1,000 | Checkpoint selection and reported v2 metrics |
201
+ | Test | 50,000 | 1,000 | Sealed and unused |
202
 
203
+ Factor training additionally uses 108,096 controlled intervention images. Training and validation intervention families are disjoint.
204
 
205
+ ## Development findings
206
 
207
+ The final structure follows several measured corrections:
208
+
209
+ - Global pooling and repeated low-dimensional compression removed local line and texture evidence. The accepted path preserves the VAE spatial field.
210
+ - Independent factor branches duplicated capacity and forced artificial separation. Overlapping memberships on one dictionary retained shared evidence.
211
+ - An earlier dense-coordinate implementation broke coordinate identity between training and production gating. Aligned per-axis pooling made coordinate `k` refer to the same axis everywhere.
212
+ - FiLM improved retrieval, but updating it during factor tuning reduced retrieval. Retrieval-trained FiLM is kept and frozen during later stages.
213
+ - Layout needed phase-free radial and directional power statistics. These improved Layout prediction without encoding absolute object locations.
214
+ - Fixed validation panels, atomic checkpoints, domain-balanced episodes, and median per-record routing metrics prevented evaluation artifacts from selecting a model.
215
+
216
+ See [`RESEARCH_REPORT.md`](RESEARCH_REPORT.md) for the full architecture, training stages, failed approaches, and acceptance evidence.
217
 
218
  ## Applications
219
 
220
  - reference-driven style transfer for Anima;
221
+ - open-set style retrieval and clustering;
222
+ - multi-reference style prototype construction;
223
+ - per-reference Line, Color, Texture, Layout, and Face control;
224
+ - reference-set curation and similarity scoring;
225
+ - research on shared and controllable style representations.
226
+
227
+ ## Limitations
228
+
229
+ - Retrieval and intervention metrics measure representation behavior, not generated-image fidelity.
230
+ - Raw-RGB feature extraction is not bundled in this release candidate.
231
+ - The sealed test split remains unused, so v2 does not claim sealed-test performance.
232
+ - Color intervention selectivity is weaker than Line, Texture, and Layout.
233
+ - Layout attribute causality is positive but weaker than the other attribute memberships.
234
+ - Human single-reference retrieval remains harder than Synthetic retrieval.
235
+ - Line, Color, Texture, and Layout are useful controls, not a complete or perfectly disentangled theory of style.
236
+ - The model is optimized for anime and illustration images and has not been evaluated as a general photographic style encoder.
237
+ - The embedding must not be used as evidence of authorship or identity.
238
 
239
  ## Files
240
 
 
243
  | `model.safetensors` | Encoder weights |
244
  | `config.json` | Architecture and feature contract |
245
  | `modeling_anima_style_embedding.py` | PyTorch model definition |
246
+ | `metrics/` | Retrieval, factor, attribute, and routing evaluations |
247
+ | `assets/` | Model-card figures |
248
+ | `RESEARCH_REPORT.md` | Detailed research and implementation report |
249
  | `SHA256SUMS.json` | Release checksums |
250
+ | `LICENSE.md` | CircleStone Labs Non-Commercial License v1.2 |
251
+ | `CODE_LICENSE/` | License for original release code |
252
+ | `NOTICE` | Required attribution notice |
253
+ | `THIRD_PARTY_NOTICES.md` | Third-party licenses and attribution |
 
 
 
254
 
255
  ## License
256
 
257
+ The model weights are a derivative of [circlestone-labs/Anima](https://huggingface.co/circlestone-labs/Anima) and are distributed under the [CircleStone Labs Non-Commercial License v1.2](https://huggingface.co/circlestone-labs/Anima/blob/main/LICENSE.md).
258
 
259
+ The license permits the model and its derivatives only for the non-commercial purposes defined by that license. Commercial or production use requires authorization from CircleStone Labs. The upstream license separately permits use of model outputs, subject to its terms and applicable law.
260
 
261
+ Original Baragi AI release code is provided under the Apache License 2.0. Third-party components remain under their respective licenses and are listed in `NOTICE` and `THIRD_PARTY_NOTICES.md`.
262
 
263
  ## Citation
264
 
265
  ```bibtex
266
+ @misc{baragi2026animastyleembeddingv2,
267
+ title = {Anima Style Embedding v2},
268
  author = {{Baragi AI}},
269
  year = {2026},
270
  howpublished = {Hugging Face model repository},
RESEARCH_REPORT.md ADDED
@@ -0,0 +1,275 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Anima Style Embedding v2: Research Report
2
+
3
+ ## Executive summary
4
+
5
+ Anima Style Embedding v2 is a 52.0M-parameter, multi-reference style encoder for anime and illustration images. It maps one to eight reference images into a normalized 1,024-dimensional embedding and, at the same time, exposes a controllable shared style space for Line, Color, Texture, Layout, and Face-aware routing.
6
+
7
+ The production checkpoint uses three complementary signals:
8
+
9
+ - spatial Anima VAE latents, which retain local line, texture, and layout evidence;
10
+ - DINOv3-S+ descriptors, which supply robust visual context;
11
+ - three cached Anima internal descriptors, which align the representation with the target generator.
12
+
13
+ All signals enter one aligned 256-axis style dictionary. Line, Color, Texture, and Layout are learned as overlapping memberships on that dictionary rather than independent branches. This preserves a common style representation while allowing factor-specific reference weighting and intervention training.
14
+
15
+ The accepted Stage 4 checkpoint was selected on style-disjoint validation only. The sealed 1,000-style test split was not opened.
16
+
17
+ ## Released checkpoint
18
+
19
+ | Item | Value |
20
+ |---|---|
21
+ | Architecture | `shared_axis_v3` |
22
+ | Parameters | 51,991,809 |
23
+ | Embedding | 1,024-D, L2-normalized |
24
+ | Shared style axes | 256 |
25
+ | Reference images | 1–8 |
26
+ | Spatial resolution mode | `s12` |
27
+ | Set reasoning | 2 layers, 8 heads |
28
+ | Inputs | VAE full/face, DINOv3 full/face, Anima descriptors |
29
+ | Factor controls | Line, Color, Texture, Layout |
30
+ | Face control | Per-reference face weight |
31
+ | Checkpoint SHA-256 | `79f1b467fa9fdb855c38ae91015371851ad574ca7a73c24b586b68701c37af14` |
32
+
33
+ The release contains the encoder weights only. Optimizer state and private training metadata are not part of the public model.
34
+
35
+ ## Data and split policy
36
+
37
+ The base corpus contains 500,000 images:
38
+
39
+ - 250,000 Anima-generated images from 5,000 synthetic style identities;
40
+ - 250,000 human-created illustrations from 5,000 human style identities.
41
+
42
+ Synthetic and human identities remain distinct even when their artist names overlap. The split is identity-disjoint:
43
+
44
+ | Split | Records | Style identities | Use |
45
+ |---|---:|---:|---|
46
+ | Train | 400,000 | 8,000 | optimization and normalization statistics |
47
+ | Validation | 50,000 | 1,000 | checkpoint selection and reported v2 metrics |
48
+ | Test | 50,000 | 1,000 | sealed; not used for v2 selection or reporting |
49
+
50
+ Factor learning additionally uses 108,096 controlled intervention images. Training and validation use disjoint intervention families so that evaluation measures factor response rather than memorization of an image transform.
51
+
52
+ ## Architecture
53
+
54
+ ### Shared spatial field
55
+
56
+ The encoder does not globally pool the VAE latent before style reasoning. A convolutional stem preserves a spatial field, and every spatial token is projected into the same 256-axis dictionary. Per-axis mean and log-standard-deviation statistics capture persistent appearance, while translation-invariant power statistics capture low- and mid-frequency energy, anisotropy, and diagonal structure without copying absolute object positions.
57
+
58
+ ### Context alignment
59
+
60
+ DINOv3 and Anima descriptors condition the same aligned axes. The accepted model keeps the retrieval-trained FiLM transformation fixed during later intervention and routing stages because updating FiLM caused a measurable retrieval conflict. DINOv3 and Anima relation projections still provide per-reference context for set reasoning.
61
+
62
+ ### Overlapping factor memberships
63
+
64
+ Line, Color, Texture, and Layout are sigmoid memberships over the shared dictionary. An axis may contribute to several factors. This is deliberate: line rendering, texture, and color handling are correlated in real styles, and forcing four disjoint branches discarded useful shared evidence.
65
+
66
+ The accepted checkpoint retains:
67
+
68
+ - 82 axes with material membership in every factor;
69
+ - minimum factor coverage of 0.11045;
70
+ - effective rank 248.35 out of 256.
71
+
72
+ The decomposition is therefore controllable but not assumed to be complete. Style evidence outside the four named factors remains in the shared representation.
73
+
74
+ ### Multi-reference routing
75
+
76
+ A relation Transformer compares all references before estimating per-axis reliability. The routing contract supports:
77
+
78
+ - **Auto:** the model selects reliable references per axis;
79
+ - **Assisted:** automatic reliability is multiplied by user-provided per-image factor weights;
80
+ - **Manual:** user weights directly choose factor suppliers.
81
+
82
+ Reference weights are normalized, so adding references does not automatically increase style strength. A zero user weight produces exactly zero contribution and zero gradient for that reference-factor path. Face weights control face-token routing without being added as a fifth factor coordinate.
83
+
84
+ ## Evaluation protocol
85
+
86
+ The primary retrieval evaluation uses disjoint gallery and probe image sets:
87
+
88
+ - gallery references: 2, 4, or 8 images per style;
89
+ - probe references: 1, 2, 4, or 8 images per style;
90
+ - cosine similarity between L2-normalized set embeddings;
91
+ - three fixed seeds: 20260724, 20260725, and 20260726;
92
+ - Overall: 1,000-way retrieval;
93
+ - Synthetic and Human: 500-way retrieval each.
94
+
95
+ This protocol is stricter and more representative than comparing one image with another image from the same artist. It measures whether a small probe set can retrieve a style prototype built from a separate gallery set.
96
+
97
+ ### Overall set-to-set retrieval
98
+
99
+ Top-1:
100
+
101
+ | Gallery \ Probe | 1 | 2 | 4 | 8 |
102
+ |---|---:|---:|---:|---:|
103
+ | 2 references | 67.07% | 81.93% | 89.90% | 93.97% |
104
+ | 4 references | 77.17% | 91.23% | 96.60% | 98.47% |
105
+ | 8 references | 83.27% | 95.07% | 98.83% | 99.83% |
106
+
107
+ Top-5:
108
+
109
+ | Gallery \ Probe | 1 | 2 | 4 | 8 |
110
+ |---|---:|---:|---:|---:|
111
+ | 2 references | 84.73% | 93.27% | 96.97% | 98.23% |
112
+ | 4 references | 91.23% | 97.40% | 99.27% | 99.70% |
113
+ | 8 references | 94.03% | 98.60% | 99.80% | 100.00% |
114
+
115
+ The complete Overall, Synthetic, and Human matrices are included with the release. Every primary Top-1 and Top-5 cell remains within two percentage points of the accepted translation-invariant Stage 2 teacher. The worst deltas were -1.00 percentage point Overall, -1.40 Synthetic, and -1.27 Human.
116
+
117
+ ### Single-query regression panel
118
+
119
+ The secondary diagnostic compares one query image with style sets containing 1, 2, 4, or 8 references.
120
+
121
+ | Domain | Metric | 1 | 2 | 4 | 8 |
122
+ |---|---|---:|---:|---:|---:|
123
+ | Overall | Top-1 | 50.47% | 67.20% | 77.63% | 82.20% |
124
+ | Overall | Top-5 | 72.70% | 83.50% | 90.03% | 93.40% |
125
+ | Synthetic | Top-1 | 56.20% | 69.33% | 80.60% | 85.93% |
126
+ | Synthetic | Top-5 | 76.07% | 86.93% | 92.80% | 94.33% |
127
+ | Human | Top-1 | 48.33% | 63.60% | 74.93% | 79.80% |
128
+ | Human | Top-5 | 70.00% | 80.40% | 88.40% | 91.93% |
129
+
130
+ Synthetic Top-1 at two references regressed by 2.20 percentage points from its Stage 2 teacher. It is retained as a disclosed secondary limitation; the primary disjoint set-to-set matrix passed its preservation gate.
131
+
132
+ ## Factor and routing evaluation
133
+
134
+ Evaluation uses 4,096 interventions from families that were never used for training.
135
+
136
+ | Metric | Result |
137
+ |---|---:|
138
+ | Balanced factor accuracy | 84.60% |
139
+ | Median target/non-target response ratio | 1.862× |
140
+ | Level-response correlation | 0.260 |
141
+ | Strong > weak ordering | 98.83% of 2,048 pairs |
142
+
143
+ Factor-specific results:
144
+
145
+ | Factor | Classification accuracy | Target/non-target response |
146
+ |---|---:|---:|
147
+ | Line | 88.48% | 1.761× |
148
+ | Color | 64.16% | 1.406× |
149
+ | Texture | 94.04% | 2.393× |
150
+ | Layout | 91.70% | 1.970× |
151
+
152
+ Color is the weakest controlled factor and does not meet the earlier 1.5× response target. The release should not be interpreted as perfect factor disentanglement.
153
+
154
+ Attribute reconstruction is evaluated against a train-mean predictor:
155
+
156
+ | Metric | Result |
157
+ |---|---:|
158
+ | Model error | 0.23806 |
159
+ | Mean-predictor error | 0.34610 |
160
+ | Relative error | 0.68785 |
161
+ | Error reduction | 31.2% |
162
+
163
+ Removing each factor's membership raises its corresponding attribute error by 2.033× for Line, 2.431× for Color, 1.433× for Texture, and 1.118× for Layout. The factors are therefore causally used, although Layout remains the least selective attribute subspace.
164
+
165
+ Routing evaluation shows:
166
+
167
+ - 3.643× median per-record suppression of a factor-outlier reference;
168
+ - 4.557× ratio of mean target and non-target suppression;
169
+ - 19.80% lower coordinate error for Auto routing than uniform averaging.
170
+
171
+ ## Training stages
172
+
173
+ ### Stage 1 — global style retrieval
174
+
175
+ The model first learned an open-set global style embedding with style-disjoint validation, balanced Synthetic/Human episodes, variable reference counts, supervised contrastive learning, set-query consistency, Sub-center ArcFace, and variance/covariance regularization. DINO-only and DINO+Anima candidates were matched at equal steps; the Anima-aware model gained 11.2 percentage points in Top-5@1 by step 1,000.
176
+
177
+ ### Stage 2 — aligned factor representation
178
+
179
+ Attribute reconstruction and membership-causality objectives were added while preserving retrieval. A coordinate-identity defect in the first implementation was corrected by making production dictionary index `k` identical to factor coordinate `k`. The accepted aligned model then learned soft overlapping memberships and translation-invariant spatial-power statistics.
180
+
181
+ ### Stage 3 — intervention response
182
+
183
+ Controlled transforms trained locality, strength ordering, non-target preservation, and global identity preservation. Membership logits use a separate high learning rate and zero weight decay; a prior optimizer wiring error had accidentally assigned them the 1e-4 context learning rate.
184
+
185
+ ### Stage 4 — routing and continual preservation
186
+
187
+ Stage 4 alternated clean retrieval, attribute reconstruction, intervention replay, factor-outlier routing, and weak/strong replay. Similarity-distribution distillation from the frozen Stage 2 teacher limited forgetting. Memberships were frozen because joint membership updates reduced shared coverage without improving control. The selected step-2,000 checkpoint passed the corrected robust routing and retrieval gates.
188
+
189
+ ## What failed and what was learned
190
+
191
+ ### Excessive compression loses style evidence
192
+
193
+ Early plans normalized multiple backbones into a small common vector and then tokenized that vector again. This discarded local line and texture evidence. The production path retains the VAE spatial field and uses a larger aligned axis space.
194
+
195
+ ### Separate factor branches were the wrong abstraction
196
+
197
+ Independent Line, Color, Texture, and Layout branches encouraged artificial separation and duplicated representation capacity. Overlapping memberships on one dictionary preserve shared evidence while still allowing factor-specific control.
198
+
199
+ ### Reconstruction and intervention are different jobs
200
+
201
+ The first attribute probe accepted no reconstruction coordinates because it required one descriptor to be both reconstructable and selectively changed by every intervention. Reconstruction now defines interpretable axes; intervention deltas guide direction, strength, and locality.
202
+
203
+ ### Some handcrafted descriptors were misleading
204
+
205
+ Contour turning-angle features and layout contour-shape statistics were removed after poor held-out behavior. Blur/sharpen was removed from the Line intervention family because it behaved primarily as Texture. Descriptor groups are retained only when they improve held-out prediction.
206
+
207
+ ### Coordinate identity must be literal
208
+
209
+ The most consequential defect mixed dense projected coordinates while production gating used raw dictionary indices. A coordinate named `k` did not refer to the same style axis in training and inference. Aligned per-axis pooling fixed the contract and made factor controls load-bearing.
210
+
211
+ ### Factor separation was not a loss-coefficient problem
212
+
213
+ Absolute locality hinges, relative locality, and diversity coefficient screens could not overcome the coordinate defect or nearly identical memberships. The useful changes were structural: aligned coordinates, a real membership learning rate, and translation-invariant spatial statistics.
214
+
215
+ ### FiLM is useful for retrieval but unstable during intervention tuning
216
+
217
+ Removing FiLM significantly reduced retrieval. Updating it during intervention training also reduced retrieval. The accepted design keeps the retrieval-trained DINO/Anima FiLM path and freezes it during Stages 2–4.
218
+
219
+ ### Layout needed phase-free spatial evidence
220
+
221
+ Mean and variance were insufficient for composition-like style. Low/mid radial power, anisotropy, and diagonal energy improved Layout error and causality without encoding absolute object positions. The implementation derives its frequency basis from the actual field resolution after an early 12×12 assumption failed on 8×8 face fields.
222
+
223
+ ### Evaluation infrastructure can invalidate a good run
224
+
225
+ Several non-model failures were corrected:
226
+
227
+ - validation panels now replay a fixed seed rather than advancing the sampler epoch;
228
+ - checkpoints use atomic replacement to avoid incomplete ZIP files;
229
+ - hard-negative episodes are domain-balanced;
230
+ - W&B run IDs and resume policies are explicit;
231
+ - routing logs distinguish ratio-of-means from the robust median per-record ratio;
232
+ - Stage 4 uses source-relative membership coverage instead of an obsolete absolute threshold.
233
+
234
+ ### Artist-tag escaping was valid data
235
+
236
+ Backslashes before parentheses in Anima artist tags were initially suspected to be corruption. They are required to represent literal parentheses in ComfyUI syntax. Cache repair was limited to genuinely invalid escaping.
237
+
238
+ ## Strengths
239
+
240
+ - Strong retrieval from one reference and near-saturated retrieval from larger disjoint sets.
241
+ - Native 1–8 reference reasoning rather than post-hoc mean pooling.
242
+ - One representation shared by retrieval, factor control, routing, and future style transfer.
243
+ - Explicit per-image Line, Color, Texture, Layout, and Face control.
244
+ - Translation-invariant layout evidence that avoids copying absolute object locations.
245
+ - Validation on unseen style identities and unseen intervention families.
246
+ - Exact-zero Manual routing contract suitable for production controls.
247
+ - Synthetic and Human domains are reported separately.
248
+
249
+ ## Limitations
250
+
251
+ - Metrics measure representation and control behavior, not generated-image fidelity.
252
+ - The v2 release expects precomputed VAE, DINOv3, and Anima features; raw-RGB extraction is not bundled yet.
253
+ - The sealed test split remains unused, so v2 does not claim test-set performance.
254
+ - Color intervention separation is weaker than Line, Texture, and Layout.
255
+ - Layout membership causality is positive but comparatively weak.
256
+ - Human single-reference retrieval remains harder than Synthetic retrieval.
257
+ - The four named factors are useful controls, not a complete or perfectly disentangled theory of style.
258
+ - The model is optimized for anime and illustration images and has not been evaluated as a general photographic style encoder.
259
+
260
+ ## Intended use
261
+
262
+ The encoder is intended for:
263
+
264
+ - reference-driven Anima style transfer;
265
+ - open-set style retrieval and clustering;
266
+ - multi-reference style prototype construction;
267
+ - reference-set curation and similarity scoring;
268
+ - research on controllable style representations.
269
+
270
+ It is not a raw-image end-to-end product and should not be presented as evidence of authorship or identity.
271
+
272
+ ## Licensing
273
+
274
+ The public weights are a derivative of Anima and are distributed under the CircleStone Labs Non-Commercial License v1.2. Commercial or production use of the model requires appropriate authorization from CircleStone Labs. Original release code is provided under Apache License 2.0; third-party components retain their own licenses. Generated-image licensing is governed separately by the upstream Anima terms and the user's generation workflow.
275
+
SHA256SUMS.json CHANGED
@@ -1,9 +1,21 @@
1
  {
2
- "model.safetensors": "6cdf126152927f6e31dc856a8d10b8decee3bb20ce4c0ca449206db65d4633ec",
3
- "config.json": "7323cbf6061896453a88cd0f6302831b96278a52eb8b0b3c1500d84552a1e68f",
4
- "README.md": "3f5dff8ec693b6ae1587640983237b78a480bda94ffafd7087e15696cf55bb05",
5
- "LICENSE.md": "0457e82ca9056fb71de47af655407fbddf135db22025bfcc6c540c21e0071c43",
6
  "CODE_LICENSE": "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4",
 
7
  "NOTICE": "cc26915cc81a0c84c8d18294cb2a949454be5e17c509468c660008313cd0d59c",
8
- "THIRD_PARTY_NOTICES.md": "82e8d6cfd59dd247a64beca52e45eba909737416316578dcd22273f1662cbb78"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  }
 
1
  {
 
 
 
 
2
  "CODE_LICENSE": "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4",
3
+ "LICENSE.md": "0457e82ca9056fb71de47af655407fbddf135db22025bfcc6c540c21e0071c43",
4
  "NOTICE": "cc26915cc81a0c84c8d18294cb2a949454be5e17c509468c660008313cd0d59c",
5
+ "README.md": "07f16322497e0db68a130b5a3bf34a8e4feeee048942d7965327d9cacd76e98e",
6
+ "RESEARCH_REPORT.md": "2f6227ea78ab2851100052c34fb01f6499df0ae58aa9e799f0fecf27fdb1437b",
7
+ "THIRD_PARTY_NOTICES.md": "82e8d6cfd59dd247a64beca52e45eba909737416316578dcd22273f1662cbb78",
8
+ "__pycache__/modeling_anima_style_embedding.cpython-312.pyc": "a9fe32ff6aedd2c1be7f270caac2d2e9a94c6aef010d3a50388658f2c33a348b",
9
+ "assets/architecture_imagegen_v1.png": "8a99fe93f3974982b1d027a0a539ebba254b86a106f2a5f12475f90348c2aa05",
10
+ "assets/domain_reference_count_imagegen_v1.png": "c8258d4cdfb3d84967618605d75eab88e4d30a25c616cc10f0a0d51901260215",
11
+ "assets/factor_control_imagegen_v1.png": "0749a35eace0425dca0f4df8ee0550b64d911822a64700a8292aa87767cf8b67",
12
+ "assets/hero_shared_axis_imagegen_v1.png": "71810febfa8ce6683c4baff372d5854683b0266bb6d038d283698c8505ee360b",
13
+ "assets/set_retrieval_matrix_imagegen_v1.png": "a20f34d8cc0a3e19b5f72383347f09a70602bb10498cdbe5913744fe0ac5caf1",
14
+ "config.json": "7c2d00fa1b659f96c12044a3096a1ecb033395412e18f092f008d4889ce5dd18",
15
+ "metrics/evaluation-set-matrix.json": "dfbca1e313632a33644115b110330959036a01ed8cf92c137f7c2c8b8ea84d04",
16
+ "metrics/evaluation-single-query-3panel.json": "d35f42b065880857f2aac0e638d25bb211005d97317e2b86c996e3de982f6443",
17
+ "metrics/evaluation.json": "caacdb2cd8b4bc303b8ba5cc54799521b479b5d27a64fe9ff791a720fd6e04de",
18
+ "model.safetensors": "c7f38c64babe6a1dd711f7819654640b40102d6e73ae45cd2675dc84cda03453",
19
+ "modeling_anima_style_embedding.py": "bd20df4437a051abec62e9ad7d59ae242965cf39671b8e3984972457f2e39811",
20
+ "requirements.txt": "ac92c134bacf839bdd98dc18526d4dba2c1ce0e07c0a1b3f129b5a96ae4bfc70"
21
  }
__pycache__/modeling_anima_style_embedding.cpython-312.pyc ADDED
Binary file (26.6 kB). View file
 
assets/{generalization_and_gallery_size.png → architecture_imagegen_v1.png} RENAMED
File without changes
assets/{learned_vs_frozen_baseline.png → domain_reference_count_imagegen_v1.png} RENAMED
File without changes
assets/{reference_count_curve.png → factor_control_imagegen_v1.png} RENAMED
File without changes
assets/{training_validation_curves.png → hero_shared_axis_imagegen_v1.png} RENAMED
File without changes
assets/set_retrieval_matrix_imagegen_v1.png ADDED

Git LFS Details

  • SHA256: a20f34d8cc0a3e19b5f72383347f09a70602bb10498cdbe5913744fe0ac5caf1
  • Pointer size: 132 Bytes
  • Size of remote file: 1.53 MB
config.json CHANGED
@@ -1,75 +1,44 @@
1
  {
2
- "model_type": "anima_style_embedding",
3
- "version": "1.0",
 
 
4
  "architecture": {
5
- "width": 512,
6
- "blocks": 4,
7
- "heads": 8,
8
- "embedding_dim": 512,
9
- "dropout": 0.1,
10
- "reference_grounding": true,
11
- "functional_factors": true,
12
- "reference_count": [
13
- 1,
14
- 8
15
- ],
16
- "trainable_parameters": 17488353
17
  },
18
- "inputs": {
19
- "siglip2_full": {
20
- "shape": [
21
- 30,
22
- 1152
23
- ],
24
- "dtype": "bfloat16"
25
- },
26
- "siglip2_face": {
27
- "shape": [
28
- 30,
29
- 1152
30
- ],
31
- "dtype": "bfloat16",
32
- "optional": true
33
- },
34
- "anima": {
35
- "shape": [
36
- 3,
37
- 4096
38
- ],
39
- "dtype": "bfloat16"
40
- }
41
- },
42
- "vision_backbone": {
43
- "repo_id": "timm/vit_so400m_patch16_siglip_gap_512.v2_webli",
44
- "image_size": 512,
45
- "layer_fractions": [
46
- 0.25,
47
- 0.55,
48
- 1.0
49
- ],
50
- "pool_sizes": [
51
- 2,
52
- 4,
53
- 2
54
  ]
55
  },
56
- "anima_features": {
57
- "image_size": 768,
58
- "blocks": [
59
- 8,
60
- 18,
61
- 26
62
- ],
63
- "sigma": 0.1,
64
- "noise_seed": 20260715
65
- },
66
- "training": {
67
- "checkpoint_step": 4500,
68
- "face_dropout": 0.3,
69
- "query_count": 2,
70
- "optimizer": "AdamW(fused)",
71
- "scheduler": "cosine_with_linear_warmup",
72
- "learning_rate": 0.0001,
73
- "packed_manifest_sha256": "c1267b9fd45c6e0d222b91d6ae2291b36b763277cc39cbc32484874ffeae9b32"
74
- }
75
  }
 
1
  {
2
+ "model_type": "anima_style_embedding_v2",
3
+ "architectures": [
4
+ "SharedAxisStyleEncoder"
5
+ ],
6
  "architecture": {
7
+ "dino_dim": 6912,
8
+ "style_dim": 1024,
9
+ "axis_count": 256,
10
+ "embedding_dim": 1024,
11
+ "anima_dim": 12288,
12
+ "resolution": "s12",
13
+ "set_layers": 2,
14
+ "set_heads": 8,
15
+ "direct_context_axes": true,
16
+ "axis_aligned": true,
17
+ "disable_token_film": false,
18
+ "translation_invariant_stats": true
19
  },
20
+ "feature_contract": {
21
+ "full_latents": "[B,R,16,H,W]",
22
+ "face_latents": "[B,R,16,Hf,Wf]",
23
+ "dino": "[B,R,6912]",
24
+ "anima": "[B,R,3,4096]",
25
+ "reference_valid": "[B,R]",
26
+ "face_valid": "[B,R]",
27
+ "user_weights": "[B,R,5]",
28
+ "factor_order": [
29
+ "line",
30
+ "color",
31
+ "texture",
32
+ "layout",
33
+ "face"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  ]
35
  },
36
+ "routing_modes": [
37
+ "auto",
38
+ "assisted",
39
+ "manual"
40
+ ],
41
+ "parameter_count": 51991809,
42
+ "source_checkpoint_sha256": "79f1b467fa9fdb855c38ae91015371851ad574ca7a73c24b586b68701c37af14",
43
+ "validation_split": "style-disjoint validation; sealed test unused"
 
 
 
 
 
 
 
 
 
 
 
44
  }
metrics/evaluation-set-matrix.json ADDED
@@ -0,0 +1,341 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "checkpoint": "/workspace/anima-style/runs/shared-axis-stage4-routing-focused/candidate-step2000.pt",
3
+ "domains": {
4
+ "human": {
5
+ "mean": {
6
+ "top1_gallery_r2_probe_r1": 0.6299999952316284,
7
+ "top1_gallery_r2_probe_r2": 0.7973333398501078,
8
+ "top1_gallery_r2_probe_r4": 0.8846666614214579,
9
+ "top1_gallery_r2_probe_r8": 0.9299999872843424,
10
+ "top1_gallery_r4_probe_r1": 0.7333333293596903,
11
+ "top1_gallery_r4_probe_r2": 0.8933333357175192,
12
+ "top1_gallery_r4_probe_r4": 0.9646666844685873,
13
+ "top1_gallery_r4_probe_r8": 0.9853333234786987,
14
+ "top1_gallery_r8_probe_r1": 0.8106666604677836,
15
+ "top1_gallery_r8_probe_r2": 0.9386666417121887,
16
+ "top1_gallery_r8_probe_r4": 0.9913333257039388,
17
+ "top1_gallery_r8_probe_r8": 0.9980000058809916,
18
+ "top5_gallery_r2_probe_r1": 0.8146666685740153,
19
+ "top5_gallery_r2_probe_r2": 0.9213333129882812,
20
+ "top5_gallery_r2_probe_r4": 0.9646666844685873,
21
+ "top5_gallery_r2_probe_r8": 0.9799999992052714,
22
+ "top5_gallery_r4_probe_r1": 0.8926666577657064,
23
+ "top5_gallery_r4_probe_r2": 0.972000002861023,
24
+ "top5_gallery_r4_probe_r4": 0.990666667620341,
25
+ "top5_gallery_r4_probe_r8": 0.9973333477973938,
26
+ "top5_gallery_r8_probe_r1": 0.9273333350817362,
27
+ "top5_gallery_r8_probe_r2": 0.984666665395101,
28
+ "top5_gallery_r8_probe_r4": 0.9973333477973938,
29
+ "top5_gallery_r8_probe_r8": 1.0
30
+ },
31
+ "panels": [
32
+ {
33
+ "seed": 20260724,
34
+ "top1_gallery_r2_probe_r1": 0.6539999842643738,
35
+ "top1_gallery_r2_probe_r2": 0.8259999752044678,
36
+ "top1_gallery_r2_probe_r4": 0.8939999938011169,
37
+ "top1_gallery_r2_probe_r8": 0.9340000152587891,
38
+ "top1_gallery_r4_probe_r1": 0.7540000081062317,
39
+ "top1_gallery_r4_probe_r2": 0.8939999938011169,
40
+ "top1_gallery_r4_probe_r4": 0.9620000123977661,
41
+ "top1_gallery_r4_probe_r8": 0.9819999933242798,
42
+ "top1_gallery_r8_probe_r1": 0.8199999928474426,
43
+ "top1_gallery_r8_probe_r2": 0.9279999732971191,
44
+ "top1_gallery_r8_probe_r4": 0.9900000095367432,
45
+ "top1_gallery_r8_probe_r8": 0.9959999918937683,
46
+ "top5_gallery_r2_probe_r1": 0.8379999995231628,
47
+ "top5_gallery_r2_probe_r2": 0.9279999732971191,
48
+ "top5_gallery_r2_probe_r4": 0.9660000205039978,
49
+ "top5_gallery_r2_probe_r8": 0.9819999933242798,
50
+ "top5_gallery_r4_probe_r1": 0.9179999828338623,
51
+ "top5_gallery_r4_probe_r2": 0.9700000286102295,
52
+ "top5_gallery_r4_probe_r4": 0.9879999756813049,
53
+ "top5_gallery_r4_probe_r8": 0.9940000176429749,
54
+ "top5_gallery_r8_probe_r1": 0.9259999990463257,
55
+ "top5_gallery_r8_probe_r2": 0.9779999852180481,
56
+ "top5_gallery_r8_probe_r4": 0.9980000257492065,
57
+ "top5_gallery_r8_probe_r8": 1.0
58
+ },
59
+ {
60
+ "seed": 20260725,
61
+ "top1_gallery_r2_probe_r1": 0.6320000290870667,
62
+ "top1_gallery_r2_probe_r2": 0.8040000200271606,
63
+ "top1_gallery_r2_probe_r4": 0.8859999775886536,
64
+ "top1_gallery_r2_probe_r8": 0.9419999718666077,
65
+ "top1_gallery_r4_probe_r1": 0.7059999704360962,
66
+ "top1_gallery_r4_probe_r2": 0.9020000100135803,
67
+ "top1_gallery_r4_probe_r4": 0.9660000205039978,
68
+ "top1_gallery_r4_probe_r8": 0.9860000014305115,
69
+ "top1_gallery_r8_probe_r1": 0.8199999928474426,
70
+ "top1_gallery_r8_probe_r2": 0.9419999718666077,
71
+ "top1_gallery_r8_probe_r4": 0.9879999756813049,
72
+ "top1_gallery_r8_probe_r8": 1.0,
73
+ "top5_gallery_r2_probe_r1": 0.8119999766349792,
74
+ "top5_gallery_r2_probe_r2": 0.921999990940094,
75
+ "top5_gallery_r2_probe_r4": 0.9620000123977661,
76
+ "top5_gallery_r2_probe_r8": 0.9800000190734863,
77
+ "top5_gallery_r4_probe_r1": 0.8920000195503235,
78
+ "top5_gallery_r4_probe_r2": 0.972000002861023,
79
+ "top5_gallery_r4_probe_r4": 0.9900000095367432,
80
+ "top5_gallery_r4_probe_r8": 1.0,
81
+ "top5_gallery_r8_probe_r1": 0.9359999895095825,
82
+ "top5_gallery_r8_probe_r2": 0.9900000095367432,
83
+ "top5_gallery_r8_probe_r4": 0.9959999918937683,
84
+ "top5_gallery_r8_probe_r8": 1.0
85
+ },
86
+ {
87
+ "seed": 20260726,
88
+ "top1_gallery_r2_probe_r1": 0.6039999723434448,
89
+ "top1_gallery_r2_probe_r2": 0.7620000243186951,
90
+ "top1_gallery_r2_probe_r4": 0.8740000128746033,
91
+ "top1_gallery_r2_probe_r8": 0.9139999747276306,
92
+ "top1_gallery_r4_probe_r1": 0.7400000095367432,
93
+ "top1_gallery_r4_probe_r2": 0.8840000033378601,
94
+ "top1_gallery_r4_probe_r4": 0.9660000205039978,
95
+ "top1_gallery_r4_probe_r8": 0.9879999756813049,
96
+ "top1_gallery_r8_probe_r1": 0.7919999957084656,
97
+ "top1_gallery_r8_probe_r2": 0.9459999799728394,
98
+ "top1_gallery_r8_probe_r4": 0.9959999918937683,
99
+ "top1_gallery_r8_probe_r8": 0.9980000257492065,
100
+ "top5_gallery_r2_probe_r1": 0.7940000295639038,
101
+ "top5_gallery_r2_probe_r2": 0.9139999747276306,
102
+ "top5_gallery_r2_probe_r4": 0.9660000205039978,
103
+ "top5_gallery_r2_probe_r8": 0.9779999852180481,
104
+ "top5_gallery_r4_probe_r1": 0.8679999709129333,
105
+ "top5_gallery_r4_probe_r2": 0.9739999771118164,
106
+ "top5_gallery_r4_probe_r4": 0.9940000176429749,
107
+ "top5_gallery_r4_probe_r8": 0.9980000257492065,
108
+ "top5_gallery_r8_probe_r1": 0.9200000166893005,
109
+ "top5_gallery_r8_probe_r2": 0.9860000014305115,
110
+ "top5_gallery_r8_probe_r4": 0.9980000257492065,
111
+ "top5_gallery_r8_probe_r8": 1.0
112
+ }
113
+ ],
114
+ "styles": 500
115
+ },
116
+ "overall": {
117
+ "mean": {
118
+ "top1_gallery_r2_probe_r1": 0.6706666747728983,
119
+ "top1_gallery_r2_probe_r2": 0.8193333347638448,
120
+ "top1_gallery_r2_probe_r4": 0.8990000089009603,
121
+ "top1_gallery_r2_probe_r8": 0.9396666685740153,
122
+ "top1_gallery_r4_probe_r1": 0.7716666658719381,
123
+ "top1_gallery_r4_probe_r2": 0.9123333295186361,
124
+ "top1_gallery_r4_probe_r4": 0.9660000006357828,
125
+ "top1_gallery_r4_probe_r8": 0.984666665395101,
126
+ "top1_gallery_r8_probe_r1": 0.8326666553815206,
127
+ "top1_gallery_r8_probe_r2": 0.9506666660308838,
128
+ "top1_gallery_r8_probe_r4": 0.9883333245913187,
129
+ "top1_gallery_r8_probe_r8": 0.9983333349227905,
130
+ "top5_gallery_r2_probe_r1": 0.8473333517710367,
131
+ "top5_gallery_r2_probe_r2": 0.9326666593551636,
132
+ "top5_gallery_r2_probe_r4": 0.9696666598320007,
133
+ "top5_gallery_r2_probe_r8": 0.9823333422342936,
134
+ "top5_gallery_r4_probe_r1": 0.9123333295186361,
135
+ "top5_gallery_r4_probe_r2": 0.9740000168482462,
136
+ "top5_gallery_r4_probe_r4": 0.9926666617393494,
137
+ "top5_gallery_r4_probe_r8": 0.996999979019165,
138
+ "top5_gallery_r8_probe_r1": 0.940333346525828,
139
+ "top5_gallery_r8_probe_r2": 0.9860000014305115,
140
+ "top5_gallery_r8_probe_r4": 0.9980000058809916,
141
+ "top5_gallery_r8_probe_r8": 1.0
142
+ },
143
+ "panels": [
144
+ {
145
+ "seed": 20260724,
146
+ "top1_gallery_r2_probe_r1": 0.6859999895095825,
147
+ "top1_gallery_r2_probe_r2": 0.828000009059906,
148
+ "top1_gallery_r2_probe_r4": 0.8980000019073486,
149
+ "top1_gallery_r2_probe_r8": 0.9409999847412109,
150
+ "top1_gallery_r4_probe_r1": 0.777999997138977,
151
+ "top1_gallery_r4_probe_r2": 0.9169999957084656,
152
+ "top1_gallery_r4_probe_r4": 0.9620000123977661,
153
+ "top1_gallery_r4_probe_r8": 0.9829999804496765,
154
+ "top1_gallery_r8_probe_r1": 0.8389999866485596,
155
+ "top1_gallery_r8_probe_r2": 0.9440000057220459,
156
+ "top1_gallery_r8_probe_r4": 0.9869999885559082,
157
+ "top1_gallery_r8_probe_r8": 0.996999979019165,
158
+ "top5_gallery_r2_probe_r1": 0.8640000224113464,
159
+ "top5_gallery_r2_probe_r2": 0.9390000104904175,
160
+ "top5_gallery_r2_probe_r4": 0.9729999899864197,
161
+ "top5_gallery_r2_probe_r8": 0.984000027179718,
162
+ "top5_gallery_r4_probe_r1": 0.9259999990463257,
163
+ "top5_gallery_r4_probe_r2": 0.9760000109672546,
164
+ "top5_gallery_r4_probe_r4": 0.9929999709129333,
165
+ "top5_gallery_r4_probe_r8": 0.996999979019165,
166
+ "top5_gallery_r8_probe_r1": 0.9380000233650208,
167
+ "top5_gallery_r8_probe_r2": 0.9860000014305115,
168
+ "top5_gallery_r8_probe_r4": 0.9990000128746033,
169
+ "top5_gallery_r8_probe_r8": 1.0
170
+ },
171
+ {
172
+ "seed": 20260725,
173
+ "top1_gallery_r2_probe_r1": 0.675000011920929,
174
+ "top1_gallery_r2_probe_r2": 0.8270000219345093,
175
+ "top1_gallery_r2_probe_r4": 0.906000018119812,
176
+ "top1_gallery_r2_probe_r8": 0.9440000057220459,
177
+ "top1_gallery_r4_probe_r1": 0.7689999938011169,
178
+ "top1_gallery_r4_probe_r2": 0.9150000214576721,
179
+ "top1_gallery_r4_probe_r4": 0.9679999947547913,
180
+ "top1_gallery_r4_probe_r8": 0.9860000014305115,
181
+ "top1_gallery_r8_probe_r1": 0.8349999785423279,
182
+ "top1_gallery_r8_probe_r2": 0.9509999752044678,
183
+ "top1_gallery_r8_probe_r4": 0.9860000014305115,
184
+ "top1_gallery_r8_probe_r8": 1.0,
185
+ "top5_gallery_r2_probe_r1": 0.8510000109672546,
186
+ "top5_gallery_r2_probe_r2": 0.9359999895095825,
187
+ "top5_gallery_r2_probe_r4": 0.968999981880188,
188
+ "top5_gallery_r2_probe_r8": 0.984000027179718,
189
+ "top5_gallery_r4_probe_r1": 0.9139999747276306,
190
+ "top5_gallery_r4_probe_r2": 0.9700000286102295,
191
+ "top5_gallery_r4_probe_r4": 0.9909999966621399,
192
+ "top5_gallery_r4_probe_r8": 0.996999979019165,
193
+ "top5_gallery_r8_probe_r1": 0.9449999928474426,
194
+ "top5_gallery_r8_probe_r2": 0.984000027179718,
195
+ "top5_gallery_r8_probe_r4": 0.9959999918937683,
196
+ "top5_gallery_r8_probe_r8": 1.0
197
+ },
198
+ {
199
+ "seed": 20260726,
200
+ "top1_gallery_r2_probe_r1": 0.6510000228881836,
201
+ "top1_gallery_r2_probe_r2": 0.8029999732971191,
202
+ "top1_gallery_r2_probe_r4": 0.8930000066757202,
203
+ "top1_gallery_r2_probe_r8": 0.9340000152587891,
204
+ "top1_gallery_r4_probe_r1": 0.7680000066757202,
205
+ "top1_gallery_r4_probe_r2": 0.9049999713897705,
206
+ "top1_gallery_r4_probe_r4": 0.9679999947547913,
207
+ "top1_gallery_r4_probe_r8": 0.9850000143051147,
208
+ "top1_gallery_r8_probe_r1": 0.8240000009536743,
209
+ "top1_gallery_r8_probe_r2": 0.9570000171661377,
210
+ "top1_gallery_r8_probe_r4": 0.9919999837875366,
211
+ "top1_gallery_r8_probe_r8": 0.9980000257492065,
212
+ "top5_gallery_r2_probe_r1": 0.8270000219345093,
213
+ "top5_gallery_r2_probe_r2": 0.9229999780654907,
214
+ "top5_gallery_r2_probe_r4": 0.9670000076293945,
215
+ "top5_gallery_r2_probe_r8": 0.9789999723434448,
216
+ "top5_gallery_r4_probe_r1": 0.8970000147819519,
217
+ "top5_gallery_r4_probe_r2": 0.9760000109672546,
218
+ "top5_gallery_r4_probe_r4": 0.9940000176429749,
219
+ "top5_gallery_r4_probe_r8": 0.996999979019165,
220
+ "top5_gallery_r8_probe_r1": 0.9380000233650208,
221
+ "top5_gallery_r8_probe_r2": 0.9879999756813049,
222
+ "top5_gallery_r8_probe_r4": 0.9990000128746033,
223
+ "top5_gallery_r8_probe_r8": 1.0
224
+ }
225
+ ],
226
+ "styles": 1000
227
+ },
228
+ "synthetic": {
229
+ "mean": {
230
+ "top1_gallery_r2_probe_r1": 0.6919999917348226,
231
+ "top1_gallery_r2_probe_r2": 0.8326666752497355,
232
+ "top1_gallery_r2_probe_r4": 0.9073333342870077,
233
+ "top1_gallery_r2_probe_r8": 0.9380000034968058,
234
+ "top1_gallery_r4_probe_r1": 0.7846666574478149,
235
+ "top1_gallery_r4_probe_r2": 0.9153333306312561,
236
+ "top1_gallery_r4_probe_r4": 0.9699999888737997,
237
+ "top1_gallery_r4_probe_r8": 0.9859999815622965,
238
+ "top1_gallery_r8_probe_r1": 0.8306666612625122,
239
+ "top1_gallery_r8_probe_r2": 0.9586666623751322,
240
+ "top1_gallery_r8_probe_r4": 0.990666667620341,
241
+ "top1_gallery_r8_probe_r8": 0.9973333477973938,
242
+ "top5_gallery_r2_probe_r1": 0.8686666687329611,
243
+ "top5_gallery_r2_probe_r2": 0.9419999917348226,
244
+ "top5_gallery_r2_probe_r4": 0.9773333271344503,
245
+ "top5_gallery_r2_probe_r8": 0.9899999896685282,
246
+ "top5_gallery_r4_probe_r1": 0.9153333107630411,
247
+ "top5_gallery_r4_probe_r2": 0.9760000109672546,
248
+ "top5_gallery_r4_probe_r4": 0.9933333396911621,
249
+ "top5_gallery_r4_probe_r8": 0.9980000058809916,
250
+ "top5_gallery_r8_probe_r1": 0.9386666814486185,
251
+ "top5_gallery_r8_probe_r2": 0.9893333315849304,
252
+ "top5_gallery_r8_probe_r4": 0.9986666838328043,
253
+ "top5_gallery_r8_probe_r8": 1.0
254
+ },
255
+ "panels": [
256
+ {
257
+ "seed": 20260724,
258
+ "top1_gallery_r2_probe_r1": 0.6840000152587891,
259
+ "top1_gallery_r2_probe_r2": 0.8320000171661377,
260
+ "top1_gallery_r2_probe_r4": 0.9139999747276306,
261
+ "top1_gallery_r2_probe_r8": 0.9319999814033508,
262
+ "top1_gallery_r4_probe_r1": 0.7879999876022339,
263
+ "top1_gallery_r4_probe_r2": 0.921999990940094,
264
+ "top1_gallery_r4_probe_r4": 0.9779999852180481,
265
+ "top1_gallery_r4_probe_r8": 0.9879999756813049,
266
+ "top1_gallery_r8_probe_r1": 0.8299999833106995,
267
+ "top1_gallery_r8_probe_r2": 0.9639999866485596,
268
+ "top1_gallery_r8_probe_r4": 0.9940000176429749,
269
+ "top1_gallery_r8_probe_r8": 0.9959999918937683,
270
+ "top5_gallery_r2_probe_r1": 0.8820000290870667,
271
+ "top5_gallery_r2_probe_r2": 0.9559999704360962,
272
+ "top5_gallery_r2_probe_r4": 0.9760000109672546,
273
+ "top5_gallery_r2_probe_r8": 0.9879999756813049,
274
+ "top5_gallery_r4_probe_r1": 0.9319999814033508,
275
+ "top5_gallery_r4_probe_r2": 0.9819999933242798,
276
+ "top5_gallery_r4_probe_r4": 0.9959999918937683,
277
+ "top5_gallery_r4_probe_r8": 1.0,
278
+ "top5_gallery_r8_probe_r1": 0.9440000057220459,
279
+ "top5_gallery_r8_probe_r2": 0.9919999837875366,
280
+ "top5_gallery_r8_probe_r4": 0.9980000257492065,
281
+ "top5_gallery_r8_probe_r8": 1.0
282
+ },
283
+ {
284
+ "seed": 20260725,
285
+ "top1_gallery_r2_probe_r1": 0.7059999704360962,
286
+ "top1_gallery_r2_probe_r2": 0.8320000171661377,
287
+ "top1_gallery_r2_probe_r4": 0.9020000100135803,
288
+ "top1_gallery_r2_probe_r8": 0.9440000057220459,
289
+ "top1_gallery_r4_probe_r1": 0.7799999713897705,
290
+ "top1_gallery_r4_probe_r2": 0.9100000262260437,
291
+ "top1_gallery_r4_probe_r4": 0.9679999947547913,
292
+ "top1_gallery_r4_probe_r8": 0.9879999756813049,
293
+ "top1_gallery_r8_probe_r1": 0.8399999737739563,
294
+ "top1_gallery_r8_probe_r2": 0.9660000205039978,
295
+ "top1_gallery_r8_probe_r4": 0.9900000095367432,
296
+ "top1_gallery_r8_probe_r8": 0.9980000257492065,
297
+ "top5_gallery_r2_probe_r1": 0.8560000061988831,
298
+ "top5_gallery_r2_probe_r2": 0.9399999976158142,
299
+ "top5_gallery_r2_probe_r4": 0.9739999771118164,
300
+ "top5_gallery_r2_probe_r8": 0.9900000095367432,
301
+ "top5_gallery_r4_probe_r1": 0.9139999747276306,
302
+ "top5_gallery_r4_probe_r2": 0.9760000109672546,
303
+ "top5_gallery_r4_probe_r4": 0.9940000176429749,
304
+ "top5_gallery_r4_probe_r8": 1.0,
305
+ "top5_gallery_r8_probe_r1": 0.9380000233650208,
306
+ "top5_gallery_r8_probe_r2": 0.9919999837875366,
307
+ "top5_gallery_r8_probe_r4": 1.0,
308
+ "top5_gallery_r8_probe_r8": 1.0
309
+ },
310
+ {
311
+ "seed": 20260726,
312
+ "top1_gallery_r2_probe_r1": 0.6859999895095825,
313
+ "top1_gallery_r2_probe_r2": 0.8339999914169312,
314
+ "top1_gallery_r2_probe_r4": 0.906000018119812,
315
+ "top1_gallery_r2_probe_r8": 0.9380000233650208,
316
+ "top1_gallery_r4_probe_r1": 0.7860000133514404,
317
+ "top1_gallery_r4_probe_r2": 0.9139999747276306,
318
+ "top1_gallery_r4_probe_r4": 0.9639999866485596,
319
+ "top1_gallery_r4_probe_r8": 0.9819999933242798,
320
+ "top1_gallery_r8_probe_r1": 0.8220000267028809,
321
+ "top1_gallery_r8_probe_r2": 0.9459999799728394,
322
+ "top1_gallery_r8_probe_r4": 0.9879999756813049,
323
+ "top1_gallery_r8_probe_r8": 0.9980000257492065,
324
+ "top5_gallery_r2_probe_r1": 0.8679999709129333,
325
+ "top5_gallery_r2_probe_r2": 0.9300000071525574,
326
+ "top5_gallery_r2_probe_r4": 0.9819999933242798,
327
+ "top5_gallery_r2_probe_r8": 0.9919999837875366,
328
+ "top5_gallery_r4_probe_r1": 0.8999999761581421,
329
+ "top5_gallery_r4_probe_r2": 0.9700000286102295,
330
+ "top5_gallery_r4_probe_r4": 0.9900000095367432,
331
+ "top5_gallery_r4_probe_r8": 0.9940000176429749,
332
+ "top5_gallery_r8_probe_r1": 0.9340000152587891,
333
+ "top5_gallery_r8_probe_r2": 0.984000027179718,
334
+ "top5_gallery_r8_probe_r4": 0.9980000257492065,
335
+ "top5_gallery_r8_probe_r8": 1.0
336
+ }
337
+ ],
338
+ "styles": 500
339
+ }
340
+ }
341
+ }
metrics/evaluation-single-query-3panel.json ADDED
@@ -0,0 +1,243 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "candidates": {
3
+ "direct256": {
4
+ "anima_features": true,
5
+ "checkpoint": "/workspace/anima-style/runs/shared-axis-stage4-routing-focused/candidate-step2000.pt",
6
+ "domains": {
7
+ "human": {
8
+ "mean": {
9
+ "axis_effective_rank": 248.3503875732422,
10
+ "axis_max_offdiag_cosine": 0.3716677725315094,
11
+ "top1_r1": 0.4833333194255829,
12
+ "top1_r2": 0.6359999974568685,
13
+ "top1_r4": 0.7493333419164022,
14
+ "top1_r8": 0.7980000178019205,
15
+ "top5_r1": 0.699999988079071,
16
+ "top5_r2": 0.8040000001589457,
17
+ "top5_r4": 0.8840000033378601,
18
+ "top5_r8": 0.9193333387374878
19
+ },
20
+ "panels": [
21
+ {
22
+ "axis_effective_rank": 248.3503875732422,
23
+ "axis_max_offdiag_cosine": 0.3716677725315094,
24
+ "seed": 20260724,
25
+ "top1_r1": 0.46399998664855957,
26
+ "top1_r2": 0.6359999775886536,
27
+ "top1_r4": 0.7440000176429749,
28
+ "top1_r8": 0.7900000214576721,
29
+ "top5_r1": 0.7139999866485596,
30
+ "top5_r2": 0.8159999847412109,
31
+ "top5_r4": 0.8920000195503235,
32
+ "top5_r8": 0.9240000247955322
33
+ },
34
+ {
35
+ "axis_effective_rank": 248.3503875732422,
36
+ "axis_max_offdiag_cosine": 0.3716677725315094,
37
+ "seed": 20260725,
38
+ "top1_r1": 0.48399999737739563,
39
+ "top1_r2": 0.6399999856948853,
40
+ "top1_r4": 0.7459999918937683,
41
+ "top1_r8": 0.7960000038146973,
42
+ "top5_r1": 0.6959999799728394,
43
+ "top5_r2": 0.7900000214576721,
44
+ "top5_r4": 0.8840000033378601,
45
+ "top5_r8": 0.921999990940094
46
+ },
47
+ {
48
+ "axis_effective_rank": 248.3503875732422,
49
+ "axis_max_offdiag_cosine": 0.3716677725315094,
50
+ "seed": 20260726,
51
+ "top1_r1": 0.5019999742507935,
52
+ "top1_r2": 0.6320000290870667,
53
+ "top1_r4": 0.7580000162124634,
54
+ "top1_r8": 0.8080000281333923,
55
+ "top5_r1": 0.6899999976158142,
56
+ "top5_r2": 0.8059999942779541,
57
+ "top5_r4": 0.8759999871253967,
58
+ "top5_r8": 0.9120000004768372
59
+ }
60
+ ],
61
+ "records": 25000,
62
+ "std": {
63
+ "axis_effective_rank": 0.0,
64
+ "axis_max_offdiag_cosine": 0.0,
65
+ "top1_r1": 0.015520590819103444,
66
+ "top1_r2": 0.003265968608957246,
67
+ "top1_r4": 0.006182416289578324,
68
+ "top1_r8": 0.007483319318916783,
69
+ "top5_r1": 0.010198036315239446,
70
+ "top5_r2": 0.010708236862135389,
71
+ "top5_r4": 0.006531985884842726,
72
+ "top5_r8": 0.005249344174247969
73
+ },
74
+ "styles": 500
75
+ },
76
+ "overall": {
77
+ "mean": {
78
+ "axis_effective_rank": 248.3503875732422,
79
+ "axis_max_offdiag_cosine": 0.3716677725315094,
80
+ "top1_r1": 0.5046666661898295,
81
+ "top1_r2": 0.671999990940094,
82
+ "top1_r4": 0.7763333320617676,
83
+ "top1_r8": 0.8220000068346659,
84
+ "top5_r1": 0.7269999980926514,
85
+ "top5_r2": 0.8349999984105428,
86
+ "top5_r4": 0.9003333250681559,
87
+ "top5_r8": 0.9339999953905741
88
+ },
89
+ "panels": [
90
+ {
91
+ "axis_effective_rank": 248.3503875732422,
92
+ "axis_max_offdiag_cosine": 0.3716677725315094,
93
+ "seed": 20260724,
94
+ "top1_r1": 0.4860000014305115,
95
+ "top1_r2": 0.6639999747276306,
96
+ "top1_r4": 0.7739999890327454,
97
+ "top1_r8": 0.8109999895095825,
98
+ "top5_r1": 0.7409999966621399,
99
+ "top5_r2": 0.8389999866485596,
100
+ "top5_r4": 0.8989999890327454,
101
+ "top5_r8": 0.9309999942779541
102
+ },
103
+ {
104
+ "axis_effective_rank": 248.3503875732422,
105
+ "axis_max_offdiag_cosine": 0.3716677725315094,
106
+ "seed": 20260725,
107
+ "top1_r1": 0.5130000114440918,
108
+ "top1_r2": 0.6779999732971191,
109
+ "top1_r4": 0.7739999890327454,
110
+ "top1_r8": 0.8220000267028809,
111
+ "top5_r1": 0.7250000238418579,
112
+ "top5_r2": 0.828000009059906,
113
+ "top5_r4": 0.8989999890327454,
114
+ "top5_r8": 0.9369999766349792
115
+ },
116
+ {
117
+ "axis_effective_rank": 248.3503875732422,
118
+ "axis_max_offdiag_cosine": 0.3716677725315094,
119
+ "seed": 20260726,
120
+ "top1_r1": 0.5149999856948853,
121
+ "top1_r2": 0.6740000247955322,
122
+ "top1_r4": 0.781000018119812,
123
+ "top1_r8": 0.8330000042915344,
124
+ "top5_r1": 0.7149999737739563,
125
+ "top5_r2": 0.8379999995231628,
126
+ "top5_r4": 0.902999997138977,
127
+ "top5_r8": 0.9340000152587891
128
+ }
129
+ ],
130
+ "records": 50000,
131
+ "std": {
132
+ "axis_effective_rank": 0.0,
133
+ "axis_max_offdiag_cosine": 0.0,
134
+ "top1_r1": 0.013224554288104472,
135
+ "top1_r2": 0.005887845760751241,
136
+ "top1_r4": 0.0032998453573119375,
137
+ "top1_r8": 0.008981468424922569,
138
+ "top5_r1": 0.010708259127091117,
139
+ "top5_r2": 0.004966546871788705,
140
+ "top5_r4": 0.0018856219044783918,
141
+ "top5_r8": 0.0024494825401091443
142
+ },
143
+ "styles": 1000
144
+ },
145
+ "synthetic": {
146
+ "mean": {
147
+ "axis_effective_rank": 248.3503875732422,
148
+ "axis_max_offdiag_cosine": 0.3716677725315094,
149
+ "top1_r1": 0.5619999965031942,
150
+ "top1_r2": 0.6933333476384481,
151
+ "top1_r4": 0.8059999942779541,
152
+ "top1_r8": 0.859333316485087,
153
+ "top5_r1": 0.7606666684150696,
154
+ "top5_r2": 0.8693333268165588,
155
+ "top5_r4": 0.9279999931653341,
156
+ "top5_r8": 0.9433333476384481
157
+ },
158
+ "panels": [
159
+ {
160
+ "axis_effective_rank": 248.3503875732422,
161
+ "axis_max_offdiag_cosine": 0.3716677725315094,
162
+ "seed": 20260724,
163
+ "top1_r1": 0.5640000104904175,
164
+ "top1_r2": 0.6980000138282776,
165
+ "top1_r4": 0.7979999780654907,
166
+ "top1_r8": 0.8619999885559082,
167
+ "top5_r1": 0.7540000081062317,
168
+ "top5_r2": 0.871999979019165,
169
+ "top5_r4": 0.9279999732971191,
170
+ "top5_r8": 0.9380000233650208
171
+ },
172
+ {
173
+ "axis_effective_rank": 248.3503875732422,
174
+ "axis_max_offdiag_cosine": 0.3716677725315094,
175
+ "seed": 20260725,
176
+ "top1_r1": 0.5479999780654907,
177
+ "top1_r2": 0.6460000276565552,
178
+ "top1_r4": 0.8040000200271606,
179
+ "top1_r8": 0.843999981880188,
180
+ "top5_r1": 0.7599999904632568,
181
+ "top5_r2": 0.8619999885559082,
182
+ "top5_r4": 0.9300000071525574,
183
+ "top5_r8": 0.9440000057220459
184
+ },
185
+ {
186
+ "axis_effective_rank": 248.3503875732422,
187
+ "axis_max_offdiag_cosine": 0.3716677725315094,
188
+ "seed": 20260726,
189
+ "top1_r1": 0.5740000009536743,
190
+ "top1_r2": 0.7360000014305115,
191
+ "top1_r4": 0.8159999847412109,
192
+ "top1_r8": 0.871999979019165,
193
+ "top5_r1": 0.7680000066757202,
194
+ "top5_r2": 0.8740000128746033,
195
+ "top5_r4": 0.9259999990463257,
196
+ "top5_r8": 0.9480000138282776
197
+ }
198
+ ],
199
+ "records": 25000,
200
+ "std": {
201
+ "axis_effective_rank": 0.0,
202
+ "axis_max_offdiag_cosine": 0.0,
203
+ "top1_r1": 0.010708262837900284,
204
+ "top1_r2": 0.0368902168587073,
205
+ "top1_r4": 0.007483314008929943,
206
+ "top1_r8": 0.011585430934170549,
207
+ "top5_r1": 0.005734883585275591,
208
+ "top5_r2": 0.005249344174247969,
209
+ "top5_r4": 0.0016329964712711142,
210
+ "top5_r8": 0.0041096047714775565
211
+ },
212
+ "styles": 500
213
+ }
214
+ },
215
+ "human_minus_synthetic": {
216
+ "top1_r1": -0.07866667707761132,
217
+ "top1_r2": -0.05733335018157959,
218
+ "top1_r4": -0.056666652361551884,
219
+ "top1_r8": -0.061333298683166504,
220
+ "top5_r8": -0.024000008900960323
221
+ },
222
+ "resolution": "s12",
223
+ "step": 2000
224
+ }
225
+ },
226
+ "contract": {
227
+ "nested_reference_prefix": true,
228
+ "reference_counts": [
229
+ 1,
230
+ 2,
231
+ 4,
232
+ 8
233
+ ],
234
+ "same_target_across_reference_counts": true,
235
+ "seeds": [
236
+ 20260724,
237
+ 20260725,
238
+ 20260726
239
+ ],
240
+ "split": "validation",
241
+ "test_used": false
242
+ }
243
+ }
metrics/evaluation.json ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "attribute/attribute_error": 0.23806460597734524,
3
+ "attribute/attribute_error/human/color": 0.2041477712397719,
4
+ "attribute/attribute_error/human/layout": 0.3487045900660114,
5
+ "attribute/attribute_error/human/line": 0.2568663033834128,
6
+ "attribute/attribute_error/human/texture": 0.306499986136275,
7
+ "attribute/attribute_error/overall/color": 0.17828673733810343,
8
+ "attribute/attribute_error/overall/layout": 0.29342790455345175,
9
+ "attribute/attribute_error/overall/line": 0.21477947311496154,
10
+ "attribute/attribute_error/overall/texture": 0.27130544221554836,
11
+ "attribute/attribute_error/synthetic/color": 0.1525209903662535,
12
+ "attribute/attribute_error/synthetic/layout": 0.2381604293611011,
13
+ "attribute/attribute_error/synthetic/line": 0.17284771567126797,
14
+ "attribute/attribute_error/synthetic/texture": 0.23624006975823775,
15
+ "attribute/attribute_ratio": 0.6878512990755349,
16
+ "attribute/factor_std": 0.01133992150425911,
17
+ "attribute/mean_predictor_error": 0.3460989407118975,
18
+ "attribute/mean_predictor_error/human/color": 0.42768885221590647,
19
+ "attribute/mean_predictor_error/human/layout": 0.4193881548407108,
20
+ "attribute/mean_predictor_error/human/line": 0.43766723310491573,
21
+ "attribute/mean_predictor_error/human/texture": 0.42246386204507497,
22
+ "attribute/mean_predictor_error/overall/color": 0.3307754093894214,
23
+ "attribute/mean_predictor_error/overall/layout": 0.33926805037765684,
24
+ "attribute/mean_predictor_error/overall/line": 0.359268975772589,
25
+ "attribute/mean_predictor_error/overall/texture": 0.3572357347621366,
26
+ "attribute/mean_predictor_error/synthetic/color": 0.23421905634921739,
27
+ "attribute/mean_predictor_error/synthetic/layout": 0.25916127857816873,
28
+ "attribute/mean_predictor_error/synthetic/line": 0.28115958259758983,
29
+ "attribute/mean_predictor_error/synthetic/texture": 0.2922470102932322,
30
+ "attribute/membership_ablation_error/human/color": 0.4833354100328614,
31
+ "attribute/membership_ablation_error/human/layout": 0.3872401288902689,
32
+ "attribute/membership_ablation_error/human/line": 0.4958906247126295,
33
+ "attribute/membership_ablation_error/human/texture": 0.43578456714301117,
34
+ "attribute/membership_ablation_error/overall/color": 0.43335724416979005,
35
+ "attribute/membership_ablation_error/overall/layout": 0.3280958065628183,
36
+ "attribute/membership_ablation_error/overall/line": 0.4365888942086092,
37
+ "attribute/membership_ablation_error/overall/texture": 0.3886331248763336,
38
+ "attribute/membership_ablation_error/synthetic/color": 0.3835632295569392,
39
+ "attribute/membership_ablation_error/synthetic/layout": 0.26896133447411424,
40
+ "attribute/membership_ablation_error/synthetic/line": 0.37750567111737304,
41
+ "attribute/membership_ablation_error/synthetic/texture": 0.3416547381412804,
42
+ "attribute/membership_ablation_ratio/color": 2.430675722939336,
43
+ "attribute/membership_ablation_ratio/layout": 1.118147938459109,
44
+ "attribute/membership_ablation_ratio/line": 2.0327310048615463,
45
+ "attribute/membership_ablation_ratio/texture": 1.4324560602347596,
46
+ "attribute/membership_coverage_min": 0.11045104265213013,
47
+ "attribute/membership_mean": 0.2886149287223816,
48
+ "attribute/membership_overlap_axes": 82,
49
+ "attribute/membership_pair_difference": 0.38394951820373535,
50
+ "attribute/membership_within_factor_std": 0.34480148553848267,
51
+ "attribute/records": 4096,
52
+ "intervention/exact_strength_pairs": 2048,
53
+ "intervention/factor_accuracy/color": 0.6416015625,
54
+ "intervention/factor_accuracy/layout": 0.9169921875,
55
+ "intervention/factor_accuracy/line": 0.884765625,
56
+ "intervention/factor_accuracy/texture": 0.9404296875,
57
+ "intervention/factor_balanced_accuracy": 0.845947265625,
58
+ "intervention/factor_ratio/color": 1.405653715133667,
59
+ "intervention/factor_ratio/layout": 1.9703501462936401,
60
+ "intervention/factor_ratio/line": 1.7611885070800781,
61
+ "intervention/factor_ratio/texture": 2.39322829246521,
62
+ "intervention/family_accuracy/channel_mixer": 0.6416015625,
63
+ "intervention/family_accuracy/edge_overlay": 0.884765625,
64
+ "intervention/family_accuracy/median_speckle": 0.9404296875,
65
+ "intervention/family_accuracy/shear": 0.9169921875,
66
+ "intervention/level_response_correlation": 0.26010704040527344,
67
+ "intervention/loss/attribute_delta": 0.13530989782884717,
68
+ "intervention/loss/diversity": 0.3046875,
69
+ "intervention/loss/identity": 0.20753358397632837,
70
+ "intervention/loss/locality": 1.076119126752019,
71
+ "intervention/loss/preservation": 0.0003530628382577561,
72
+ "intervention/records": 4096,
73
+ "intervention/strong_gt_weak_exact": 0.98828125,
74
+ "intervention/target_non_target_ratio_median": 1.861896276473999,
75
+ "retrieval/axis_effective_rank": 248.3503875732422,
76
+ "retrieval/axis_max_offdiag_cosine": 0.3716677725315094,
77
+ "retrieval/top1_r1": 0.48500001430511475,
78
+ "retrieval/top1_r2": 0.6629999876022339,
79
+ "retrieval/top1_r4": 0.7739999890327454,
80
+ "retrieval/top1_r8": 0.8119999766349792,
81
+ "retrieval/top5_r1": 0.7409999966621399,
82
+ "retrieval/top5_r2": 0.8389999866485596,
83
+ "retrieval/top5_r4": 0.8960000276565552,
84
+ "retrieval/top5_r8": 0.9309999942779541,
85
+ "routing/auto_coordinate_error": 0.00034273043274879456,
86
+ "routing/auto_improvement": 0.19799659329327857,
87
+ "routing/non_target_attention_drop": 0.008984970860183239,
88
+ "routing/routing": 0.012377707287669182,
89
+ "routing/suppression_ratio_mean": 4.55674592245753,
90
+ "routing/suppression_ratio_median": 3.6429529190063477,
91
+ "routing/target_attention_drop": 0.0409422293305397,
92
+ "routing/uniform_coordinate_error": 0.00042734286398626864,
93
+ "set_retrieval/top1_gallery_r2_probe_r1": 0.6859999895095825,
94
+ "set_retrieval/top1_gallery_r2_probe_r2": 0.828000009059906,
95
+ "set_retrieval/top1_gallery_r2_probe_r4": 0.8980000019073486,
96
+ "set_retrieval/top1_gallery_r2_probe_r8": 0.9409999847412109,
97
+ "set_retrieval/top1_gallery_r4_probe_r1": 0.777999997138977,
98
+ "set_retrieval/top1_gallery_r4_probe_r2": 0.9169999957084656,
99
+ "set_retrieval/top1_gallery_r4_probe_r4": 0.9620000123977661,
100
+ "set_retrieval/top1_gallery_r4_probe_r8": 0.9829999804496765,
101
+ "set_retrieval/top1_gallery_r8_probe_r1": 0.8389999866485596,
102
+ "set_retrieval/top1_gallery_r8_probe_r2": 0.9440000057220459,
103
+ "set_retrieval/top1_gallery_r8_probe_r4": 0.9869999885559082,
104
+ "set_retrieval/top1_gallery_r8_probe_r8": 0.996999979019165,
105
+ "set_retrieval/top5_gallery_r2_probe_r1": 0.8640000224113464,
106
+ "set_retrieval/top5_gallery_r2_probe_r2": 0.9390000104904175,
107
+ "set_retrieval/top5_gallery_r2_probe_r4": 0.9729999899864197,
108
+ "set_retrieval/top5_gallery_r2_probe_r8": 0.984000027179718,
109
+ "set_retrieval/top5_gallery_r4_probe_r1": 0.9259999990463257,
110
+ "set_retrieval/top5_gallery_r4_probe_r2": 0.9760000109672546,
111
+ "set_retrieval/top5_gallery_r4_probe_r4": 0.9929999709129333,
112
+ "set_retrieval/top5_gallery_r4_probe_r8": 0.996999979019165,
113
+ "set_retrieval/top5_gallery_r8_probe_r1": 0.9380000233650208,
114
+ "set_retrieval/top5_gallery_r8_probe_r2": 0.9860000014305115,
115
+ "set_retrieval/top5_gallery_r8_probe_r4": 0.9990000128746033,
116
+ "set_retrieval/top5_gallery_r8_probe_r8": 1.0
117
+ }
metrics/model_card_metrics.json DELETED
@@ -1,169 +0,0 @@
1
- {
2
- "selected_checkpoint": {
3
- "checkpoint": "/workspace/runs/style_embedding_combined_lr1e4_clip10_5k/best.pt",
4
- "checkpoint_sha256": "16345685b72c9bb018833ea9d42d18ebdaafa585b2a2eb136f267006c1de5663",
5
- "step": 4500,
6
- "validation_checkpoint_score": 0.6301507651805878
7
- },
8
- "validation_k5": {
9
- "synthetic": {
10
- "styles": 4500.0,
11
- "queries": 22500.0,
12
- "top1": 0.5625777840614319,
13
- "top5": 0.7585333585739136,
14
- "mrr": 0.6518997550010681,
15
- "margin": -0.006614952813833952,
16
- "positive_cosine": 0.7365614771842957,
17
- "hardest_negative_cosine": 0.7431764006614685,
18
- "verification_auroc": 0.5534452199935913,
19
- "embedding_std": 0.04349411278963089,
20
- "embedding_effective_rank": 24.163583755493164,
21
- "seen_queries": 20000.0,
22
- "seen_top1": 0.5681999921798706,
23
- "seen_top5": 0.7637499570846558,
24
- "seen_mrr": 0.6573799848556519,
25
- "seen_margin": -0.004584707319736481,
26
- "unseen_queries": 2500.0,
27
- "unseen_top1": 0.5175999999046326,
28
- "unseen_top5": 0.7167999744415283,
29
- "unseen_mrr": 0.6080579161643982,
30
- "unseen_margin": -0.02285691164433956,
31
- "matched_queries": 4500.0,
32
- "matched_top1": 0.48955556750297546,
33
- "matched_top5": 0.6902222037315369,
34
- "matched_mrr": 0.5840909481048584,
35
- "matched_margin": -0.030851511284708977,
36
- "cross_queries": 18000.0,
37
- "cross_top1": 0.5808333158493042,
38
- "cross_top5": 0.7756111025810242,
39
- "cross_mrr": 0.6688519716262817,
40
- "cross_margin": -0.0005558129050768912
41
- },
42
- "human": {
43
- "styles": 4500.0,
44
- "queries": 22500.0,
45
- "top1": 0.6493777632713318,
46
- "top5": 0.8219555616378784,
47
- "mrr": 0.7280733585357666,
48
- "margin": 0.022814957424998283,
49
- "positive_cosine": 0.7811680436134338,
50
- "hardest_negative_cosine": 0.7583531141281128,
51
- "verification_auroc": 0.6369090676307678,
52
- "embedding_std": 0.043804656714200974,
53
- "embedding_effective_rank": 27.383806228637695,
54
- "seen_queries": 20000.0,
55
- "seen_top1": 0.660099983215332,
56
- "seen_top5": 0.830549955368042,
57
- "seen_mrr": 0.7378283143043518,
58
- "seen_margin": 0.026178810745477676,
59
- "unseen_queries": 2500.0,
60
- "unseen_top1": 0.5636000037193298,
61
- "unseen_top5": 0.7531999945640564,
62
- "unseen_mrr": 0.6500336527824402,
63
- "unseen_margin": -0.004095893818885088
64
- }
65
- },
66
- "sealed_test_k5": {
67
- "synthetic": {
68
- "styles": 500.0,
69
- "queries": 2500.0,
70
- "top1": 0.7375999689102173,
71
- "top5": 0.9031999707221985,
72
- "mrr": 0.8114251494407654,
73
- "margin": 0.06940444558858871,
74
- "positive_cosine": 0.7258960008621216,
75
- "hardest_negative_cosine": 0.6564915776252747,
76
- "verification_auroc": 0.7113653421401978,
77
- "embedding_std": 0.04344247281551361,
78
- "embedding_effective_rank": 23.896039962768555,
79
- "unseen_queries": 2500.0,
80
- "unseen_top1": 0.7375999689102173,
81
- "unseen_top5": 0.9031999707221985,
82
- "unseen_mrr": 0.8114251494407654,
83
- "unseen_margin": 0.06940444558858871,
84
- "matched_queries": 500.0,
85
- "matched_top1": 0.6600000262260437,
86
- "matched_top5": 0.8520000576972961,
87
- "matched_mrr": 0.748103678226471,
88
- "matched_margin": 0.045967720448970795,
89
- "cross_queries": 2000.0,
90
- "cross_top1": 0.7570000290870667,
91
- "cross_top5": 0.9160000681877136,
92
- "cross_mrr": 0.8272556662559509,
93
- "cross_margin": 0.0752636268734932
94
- },
95
- "human": {
96
- "styles": 500.0,
97
- "queries": 2500.0,
98
- "top1": 0.761199951171875,
99
- "top5": 0.9199999570846558,
100
- "mrr": 0.830402135848999,
101
- "margin": 0.08207859843969345,
102
- "positive_cosine": 0.7568042874336243,
103
- "hardest_negative_cosine": 0.6747256517410278,
104
- "verification_auroc": 0.7453367114067078,
105
- "embedding_std": 0.04376835376024246,
106
- "embedding_effective_rank": 26.91031265258789,
107
- "unseen_queries": 2500.0,
108
- "unseen_top1": 0.761199951171875,
109
- "unseen_top5": 0.9199999570846558,
110
- "unseen_mrr": 0.830402135848999,
111
- "unseen_margin": 0.08207859843969345
112
- }
113
- },
114
- "frozen_full_face_validation_k5": {
115
- "synthetic": {
116
- "styles": 4500.0,
117
- "queries": 22500.0,
118
- "top1": 0.2617333233356476,
119
- "top5": 0.3952000141143799,
120
- "mrr": 0.3287946879863739,
121
- "margin": -0.058847684413194656,
122
- "positive_cosine": 0.3081073760986328,
123
- "hardest_negative_cosine": 0.36695507168769836,
124
- "verification_auroc": 0.3488680124282837,
125
- "seen_queries": 20000.0,
126
- "seen_top1": 0.2628999948501587,
127
- "seen_top5": 0.3959999978542328,
128
- "seen_mrr": 0.3298960030078888,
129
- "seen_margin": -0.0586077980697155,
130
- "unseen_queries": 2500.0,
131
- "unseen_top1": 0.2523999810218811,
132
- "unseen_top5": 0.3887999951839447,
133
- "unseen_mrr": 0.31998398900032043,
134
- "unseen_margin": -0.06076674535870552,
135
- "matched_queries": 4500.0,
136
- "matched_top1": 0.10533333569765091,
137
- "matched_top5": 0.1851111203432083,
138
- "matched_mrr": 0.14898858964443207,
139
- "matched_margin": -0.11573364585638046,
140
- "cross_queries": 18000.0,
141
- "cross_top1": 0.3008333444595337,
142
- "cross_top5": 0.4477222263813019,
143
- "cross_mrr": 0.37374621629714966,
144
- "cross_margin": -0.04462619498372078
145
- },
146
- "human": {
147
- "styles": 4500.0,
148
- "queries": 22500.0,
149
- "top1": 0.43657779693603516,
150
- "top5": 0.5786222219467163,
151
- "mrr": 0.5056873559951782,
152
- "margin": -0.029125619679689407,
153
- "positive_cosine": 0.4710022509098053,
154
- "hardest_negative_cosine": 0.5001279711723328,
155
- "verification_auroc": 0.4406580626964569,
156
- "seen_queries": 20000.0,
157
- "seen_top1": 0.4320499897003174,
158
- "seen_top5": 0.5762999653816223,
159
- "seen_mrr": 0.5021449327468872,
160
- "seen_margin": -0.030033092945814133,
161
- "unseen_queries": 2500.0,
162
- "unseen_top1": 0.47279998660087585,
163
- "unseen_top5": 0.5971999764442444,
164
- "unseen_mrr": 0.5340264439582825,
165
- "unseen_margin": -0.021865803748369217
166
- }
167
- },
168
- "protocol_note": "Synthetic K=5 uses the locked five-controlled support, one matched and four cross-content query protocol. Other K values use deterministic generic record ordering."
169
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
metrics/retrieval_metrics.csv DELETED
@@ -1,21 +0,0 @@
1
- split,source,k,styles,queries,top1,top5,mrr,margin,seen_top1,seen_top5,seen_mrr,unseen_top1,unseen_top5,unseen_mrr,matched_mrr,cross_mrr,verification_auroc,embedding_effective_rank
2
- validation,synthetic,1,4500.0,40500.0,0.25738272070884705,0.4447901248931885,0.3484785854816437,-0.13694550096988678,0.26072221994400024,0.448972225189209,0.35212650895118713,0.23066666722297668,0.4113333523273468,0.3192950487136841,,,0.2625024914741516,24.163583755493164
3
- validation,synthetic,2,4500.0,36000.0,0.38269445300102234,0.5837222337722778,0.479046106338501,-0.0735325887799263,0.3878125250339508,0.5885000228881836,0.48388049006462097,0.34175002574920654,0.5455000400543213,0.4403711259365082,,,0.3855718970298767,24.163583755493164
4
- validation,synthetic,4,4500.0,27000.0,0.4913703501224518,0.6868888735771179,0.5827372670173645,-0.032036565244197845,0.4964166581630707,0.6924583315849304,0.5878510475158691,0.45100000500679016,0.6423333287239075,0.5418276190757751,,,0.4890711009502411,24.163583755493164
5
- validation,synthetic,5,4500.0,22500.0,0.5625777840614319,0.7585333585739136,0.6518997550010681,-0.006614952813833952,0.5681999921798706,0.7637499570846558,0.6573799848556519,0.5175999999046326,0.7167999744415283,0.6080579161643982,0.5840909481048584,0.6688519716262817,0.5534452199935913,24.163583755493164
6
- validation,synthetic,8,4500.0,9000.0,0.5631111264228821,0.7501111030578613,0.6487501263618469,-0.006703122518956661,0.5692500472068787,0.7573750615119934,0.6548616290092468,0.5139999985694885,0.6920000314712524,0.5998580455780029,,,0.557915985584259,24.163583755493164
7
- validation,human,1,4500.0,40500.0,0.37967902421951294,0.5846666693687439,0.47633036971092224,-0.07382111996412277,0.3872777819633484,0.5945833325386047,0.48492416739463806,0.31888890266418457,0.5053333640098572,0.40757980942726135,,,0.38891345262527466,27.383806228637695
8
- validation,human,2,4500.0,36000.0,0.5184444785118103,0.7187777757644653,0.6118195652961731,-0.018171189352869987,0.5287187695503235,0.729593813419342,0.6219512224197388,0.4362500309944153,0.6322500109672546,0.5307666063308716,,,0.516968846321106,27.383806228637695
9
- validation,human,4,4500.0,27000.0,0.6229629516601562,0.8089629411697388,0.7071906924247742,0.01628497801721096,0.6336249709129333,0.8175833225250244,0.7167206406593323,0.5376666784286499,0.7400000095367432,0.6309514045715332,,,0.6160270571708679,27.383806228637695
10
- validation,human,5,4500.0,22500.0,0.6493777632713318,0.8219555616378784,0.7280733585357666,0.022814957424998283,0.660099983215332,0.830549955368042,0.7378283143043518,0.5636000037193298,0.7531999945640564,0.6500336527824402,,,0.6369090676307678,27.383806228637695
11
- validation,human,8,4500.0,9000.0,0.6846666932106018,0.8516666889190674,0.7596060037612915,0.03352390229701996,0.6943750381469727,0.85875004529953,0.7680479884147644,0.6070000529289246,0.7950000166893005,0.6920705437660217,,,0.6696112155914307,27.383806228637695
12
- test,synthetic,1,500.0,4500.0,0.41688889265060425,0.6495555639266968,0.5274384617805481,-0.07223178446292877,,,,0.41688889265060425,0.6495555639266968,0.5274384617805481,,,0.41443032026290894,23.896039962768555
13
- test,synthetic,2,500.0,4000.0,0.5692500472068787,0.7830000519752502,0.6672611236572266,0.00026985956355929375,,,,0.5692500472068787,0.7830000519752502,0.6672611236572266,,,0.557541012763977,23.896039962768555
14
- test,synthetic,4,500.0,3000.0,0.6786666512489319,0.8600000143051147,0.7601169943809509,0.04286628216505051,,,,0.6786666512489319,0.8600000143051147,0.7601169943809509,,,0.6542216539382935,23.896039962768555
15
- test,synthetic,5,500.0,2500.0,0.7375999689102173,0.9031999707221985,0.8114251494407654,0.06940444558858871,,,,0.7375999689102173,0.9031999707221985,0.8114251494407654,0.748103678226471,0.8272556662559509,0.7113653421401978,23.896039962768555
16
- test,synthetic,8,500.0,1000.0,0.7070000171661377,0.8790000677108765,0.7862902879714966,0.06344308704137802,,,,0.7070000171661377,0.8790000677108765,0.7862902879714966,,,0.7011929750442505,23.896039962768555
17
- test,human,1,500.0,4500.0,0.5155555605888367,0.7431111335754395,0.6204044222831726,-0.0215375367552042,,,,0.5155555605888367,0.7431111335754395,0.6204044222831726,,,0.5082485675811768,26.91031265258789
18
- test,human,2,500.0,4000.0,0.6565000414848328,0.8540000319480896,0.7454702258110046,0.03674145042896271,,,,0.6565000414848328,0.8540000319480896,0.7454702258110046,,,0.6430025100708008,26.91031265258789
19
- test,human,4,500.0,3000.0,0.737666666507721,0.9136666655540466,0.8140823245048523,0.07469645887613297,,,,0.737666666507721,0.9136666655540466,0.8140823245048523,,,0.726514458656311,26.91031265258789
20
- test,human,5,500.0,2500.0,0.761199951171875,0.9199999570846558,0.830402135848999,0.08207859843969345,,,,0.761199951171875,0.9199999570846558,0.830402135848999,,,0.7453367114067078,26.91031265258789
21
- test,human,8,500.0,1000.0,0.7820000648498535,0.9250000715255737,0.8470030426979065,0.08853543549776077,,,,0.7820000648498535,0.9250000715255737,0.8470030426979065,,,0.7604439854621887,26.91031265258789
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
metrics/test_k_curve.json DELETED
@@ -1,204 +0,0 @@
1
- {
2
- "synthetic": {
3
- "k1": {
4
- "styles": 500.0,
5
- "queries": 4500.0,
6
- "top1": 0.41688889265060425,
7
- "top5": 0.6495555639266968,
8
- "mrr": 0.5274384617805481,
9
- "margin": -0.07223178446292877,
10
- "positive_cosine": 0.5964593291282654,
11
- "hardest_negative_cosine": 0.668691098690033,
12
- "verification_auroc": 0.41443032026290894,
13
- "embedding_std": 0.04344247281551361,
14
- "embedding_effective_rank": 23.896039962768555,
15
- "unseen_queries": 4500.0,
16
- "unseen_top1": 0.41688889265060425,
17
- "unseen_top5": 0.6495555639266968,
18
- "unseen_mrr": 0.5274384617805481,
19
- "unseen_margin": -0.07223178446292877
20
- },
21
- "k2": {
22
- "styles": 500.0,
23
- "queries": 4000.0,
24
- "top1": 0.5692500472068787,
25
- "top5": 0.7830000519752502,
26
- "mrr": 0.6672611236572266,
27
- "margin": 0.00026985956355929375,
28
- "positive_cosine": 0.6695296764373779,
29
- "hardest_negative_cosine": 0.6692599058151245,
30
- "verification_auroc": 0.557541012763977,
31
- "embedding_std": 0.04344247281551361,
32
- "embedding_effective_rank": 23.896039962768555,
33
- "unseen_queries": 4000.0,
34
- "unseen_top1": 0.5692500472068787,
35
- "unseen_top5": 0.7830000519752502,
36
- "unseen_mrr": 0.6672611236572266,
37
- "unseen_margin": 0.00026985956355929375
38
- },
39
- "k4": {
40
- "styles": 500.0,
41
- "queries": 3000.0,
42
- "top1": 0.6786666512489319,
43
- "top5": 0.8600000143051147,
44
- "mrr": 0.7601169943809509,
45
- "margin": 0.04286628216505051,
46
- "positive_cosine": 0.7160320281982422,
47
- "hardest_negative_cosine": 0.6731657981872559,
48
- "verification_auroc": 0.6542216539382935,
49
- "embedding_std": 0.04344247281551361,
50
- "embedding_effective_rank": 23.896039962768555,
51
- "unseen_queries": 3000.0,
52
- "unseen_top1": 0.6786666512489319,
53
- "unseen_top5": 0.8600000143051147,
54
- "unseen_mrr": 0.7601169943809509,
55
- "unseen_margin": 0.04286628216505051
56
- },
57
- "k5": {
58
- "styles": 500.0,
59
- "queries": 2500.0,
60
- "top1": 0.7375999689102173,
61
- "top5": 0.9031999707221985,
62
- "mrr": 0.8114251494407654,
63
- "margin": 0.06940444558858871,
64
- "positive_cosine": 0.7258960008621216,
65
- "hardest_negative_cosine": 0.6564915776252747,
66
- "verification_auroc": 0.7113653421401978,
67
- "embedding_std": 0.04344247281551361,
68
- "embedding_effective_rank": 23.896039962768555,
69
- "unseen_queries": 2500.0,
70
- "unseen_top1": 0.7375999689102173,
71
- "unseen_top5": 0.9031999707221985,
72
- "unseen_mrr": 0.8114251494407654,
73
- "unseen_margin": 0.06940444558858871,
74
- "matched_queries": 500.0,
75
- "matched_top1": 0.6600000262260437,
76
- "matched_top5": 0.8520000576972961,
77
- "matched_mrr": 0.748103678226471,
78
- "matched_margin": 0.045967720448970795,
79
- "cross_queries": 2000.0,
80
- "cross_top1": 0.7570000290870667,
81
- "cross_top5": 0.9160000681877136,
82
- "cross_mrr": 0.8272556662559509,
83
- "cross_margin": 0.0752636268734932
84
- },
85
- "k8": {
86
- "styles": 500.0,
87
- "queries": 1000.0,
88
- "top1": 0.7070000171661377,
89
- "top5": 0.8790000677108765,
90
- "mrr": 0.7862902879714966,
91
- "margin": 0.06344308704137802,
92
- "positive_cosine": 0.739560604095459,
93
- "hardest_negative_cosine": 0.676117479801178,
94
- "verification_auroc": 0.7011929750442505,
95
- "embedding_std": 0.04344247281551361,
96
- "embedding_effective_rank": 23.896039962768555,
97
- "unseen_queries": 1000.0,
98
- "unseen_top1": 0.7070000171661377,
99
- "unseen_top5": 0.8790000677108765,
100
- "unseen_mrr": 0.7862902879714966,
101
- "unseen_margin": 0.06344308704137802
102
- }
103
- },
104
- "human": {
105
- "k1": {
106
- "styles": 500.0,
107
- "queries": 4500.0,
108
- "top1": 0.5155555605888367,
109
- "top5": 0.7431111335754395,
110
- "mrr": 0.6204044222831726,
111
- "margin": -0.0215375367552042,
112
- "positive_cosine": 0.6388872861862183,
113
- "hardest_negative_cosine": 0.6604248285293579,
114
- "verification_auroc": 0.5082485675811768,
115
- "embedding_std": 0.04376835376024246,
116
- "embedding_effective_rank": 26.91031265258789,
117
- "unseen_queries": 4500.0,
118
- "unseen_top1": 0.5155555605888367,
119
- "unseen_top5": 0.7431111335754395,
120
- "unseen_mrr": 0.6204044222831726,
121
- "unseen_margin": -0.0215375367552042
122
- },
123
- "k2": {
124
- "styles": 500.0,
125
- "queries": 4000.0,
126
- "top1": 0.6565000414848328,
127
- "top5": 0.8540000319480896,
128
- "mrr": 0.7454702258110046,
129
- "margin": 0.03674145042896271,
130
- "positive_cosine": 0.7047365307807922,
131
- "hardest_negative_cosine": 0.6679950952529907,
132
- "verification_auroc": 0.6430025100708008,
133
- "embedding_std": 0.04376835376024246,
134
- "embedding_effective_rank": 26.91031265258789,
135
- "unseen_queries": 4000.0,
136
- "unseen_top1": 0.6565000414848328,
137
- "unseen_top5": 0.8540000319480896,
138
- "unseen_mrr": 0.7454702258110046,
139
- "unseen_margin": 0.03674145042896271
140
- },
141
- "k4": {
142
- "styles": 500.0,
143
- "queries": 3000.0,
144
- "top1": 0.737666666507721,
145
- "top5": 0.9136666655540466,
146
- "mrr": 0.8140823245048523,
147
- "margin": 0.07469645887613297,
148
- "positive_cosine": 0.7484809756278992,
149
- "hardest_negative_cosine": 0.6737845540046692,
150
- "verification_auroc": 0.726514458656311,
151
- "embedding_std": 0.04376835376024246,
152
- "embedding_effective_rank": 26.91031265258789,
153
- "unseen_queries": 3000.0,
154
- "unseen_top1": 0.737666666507721,
155
- "unseen_top5": 0.9136666655540466,
156
- "unseen_mrr": 0.8140823245048523,
157
- "unseen_margin": 0.07469645887613297
158
- },
159
- "k5": {
160
- "styles": 500.0,
161
- "queries": 2500.0,
162
- "top1": 0.761199951171875,
163
- "top5": 0.9199999570846558,
164
- "mrr": 0.830402135848999,
165
- "margin": 0.08207859843969345,
166
- "positive_cosine": 0.7568042874336243,
167
- "hardest_negative_cosine": 0.6747256517410278,
168
- "verification_auroc": 0.7453367114067078,
169
- "embedding_std": 0.04376835376024246,
170
- "embedding_effective_rank": 26.91031265258789,
171
- "unseen_queries": 2500.0,
172
- "unseen_top1": 0.761199951171875,
173
- "unseen_top5": 0.9199999570846558,
174
- "unseen_mrr": 0.830402135848999,
175
- "unseen_margin": 0.08207859843969345
176
- },
177
- "k8": {
178
- "styles": 500.0,
179
- "queries": 1000.0,
180
- "top1": 0.7820000648498535,
181
- "top5": 0.9250000715255737,
182
- "mrr": 0.8470030426979065,
183
- "margin": 0.08853543549776077,
184
- "positive_cosine": 0.7681199312210083,
185
- "hardest_negative_cosine": 0.6795844435691833,
186
- "verification_auroc": 0.7604439854621887,
187
- "embedding_std": 0.04376835376024246,
188
- "embedding_effective_rank": 26.91031265258789,
189
- "unseen_queries": 1000.0,
190
- "unseen_top1": 0.7820000648498535,
191
- "unseen_top5": 0.9250000715255737,
192
- "unseen_mrr": 0.8470030426979065,
193
- "unseen_margin": 0.08853543549776077
194
- }
195
- },
196
- "checkpoint_score": 0.8209136426448822,
197
- "checkpoint_config": {
198
- "packed_manifest_sha256": "c1267b9fd45c6e0d222b91d6ae2291b36b763277cc39cbc32484874ffeae9b32",
199
- "use_anima": true,
200
- "face_dropout": 0.3,
201
- "episode_pairs": 8,
202
- "seed": 20260719
203
- }
204
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
metrics/training_metrics.jsonl DELETED
The diff for this file is too large to render. See raw diff
 
metrics/validation_k_curve.json DELETED
@@ -1,254 +0,0 @@
1
- {
2
- "synthetic": {
3
- "k1": {
4
- "styles": 4500.0,
5
- "queries": 40500.0,
6
- "top1": 0.25738272070884705,
7
- "top5": 0.4447901248931885,
8
- "mrr": 0.3484785854816437,
9
- "margin": -0.13694550096988678,
10
- "positive_cosine": 0.6166356205940247,
11
- "hardest_negative_cosine": 0.7535811066627502,
12
- "verification_auroc": 0.2625024914741516,
13
- "embedding_std": 0.04349411278963089,
14
- "embedding_effective_rank": 24.163583755493164,
15
- "seen_queries": 36000.0,
16
- "seen_top1": 0.26072221994400024,
17
- "seen_top5": 0.448972225189209,
18
- "seen_mrr": 0.35212650895118713,
19
- "seen_margin": -0.13477584719657898,
20
- "unseen_queries": 4500.0,
21
- "unseen_top1": 0.23066666722297668,
22
- "unseen_top5": 0.4113333523273468,
23
- "unseen_mrr": 0.3192950487136841,
24
- "unseen_margin": -0.15430252254009247
25
- },
26
- "k2": {
27
- "styles": 4500.0,
28
- "queries": 36000.0,
29
- "top1": 0.38269445300102234,
30
- "top5": 0.5837222337722778,
31
- "mrr": 0.479046106338501,
32
- "margin": -0.0735325887799263,
33
- "positive_cosine": 0.6810839176177979,
34
- "hardest_negative_cosine": 0.7546165585517883,
35
- "verification_auroc": 0.3855718970298767,
36
- "embedding_std": 0.04349411278963089,
37
- "embedding_effective_rank": 24.163583755493164,
38
- "seen_queries": 32000.0,
39
- "seen_top1": 0.3878125250339508,
40
- "seen_top5": 0.5885000228881836,
41
- "seen_mrr": 0.48388049006462097,
42
- "seen_margin": -0.07155531644821167,
43
- "unseen_queries": 4000.0,
44
- "unseen_top1": 0.34175002574920654,
45
- "unseen_top5": 0.5455000400543213,
46
- "unseen_mrr": 0.4403711259365082,
47
- "unseen_margin": -0.08935073763132095
48
- },
49
- "k4": {
50
- "styles": 4500.0,
51
- "queries": 27000.0,
52
- "top1": 0.4913703501224518,
53
- "top5": 0.6868888735771179,
54
- "mrr": 0.5827372670173645,
55
- "margin": -0.032036565244197845,
56
- "positive_cosine": 0.7242447733879089,
57
- "hardest_negative_cosine": 0.756281316280365,
58
- "verification_auroc": 0.4890711009502411,
59
- "embedding_std": 0.04349411278963089,
60
- "embedding_effective_rank": 24.163583755493164,
61
- "seen_queries": 24000.0,
62
- "seen_top1": 0.4964166581630707,
63
- "seen_top5": 0.6924583315849304,
64
- "seen_mrr": 0.5878510475158691,
65
- "seen_margin": -0.030110228806734085,
66
- "unseen_queries": 3000.0,
67
- "unseen_top1": 0.45100000500679016,
68
- "unseen_top5": 0.6423333287239075,
69
- "unseen_mrr": 0.5418276190757751,
70
- "unseen_margin": -0.047447264194488525
71
- },
72
- "k5": {
73
- "styles": 4500.0,
74
- "queries": 22500.0,
75
- "top1": 0.5625777840614319,
76
- "top5": 0.7585333585739136,
77
- "mrr": 0.6518997550010681,
78
- "margin": -0.006614952813833952,
79
- "positive_cosine": 0.7365614771842957,
80
- "hardest_negative_cosine": 0.7431764006614685,
81
- "verification_auroc": 0.5534452199935913,
82
- "embedding_std": 0.04349411278963089,
83
- "embedding_effective_rank": 24.163583755493164,
84
- "seen_queries": 20000.0,
85
- "seen_top1": 0.5681999921798706,
86
- "seen_top5": 0.7637499570846558,
87
- "seen_mrr": 0.6573799848556519,
88
- "seen_margin": -0.004584707319736481,
89
- "unseen_queries": 2500.0,
90
- "unseen_top1": 0.5175999999046326,
91
- "unseen_top5": 0.7167999744415283,
92
- "unseen_mrr": 0.6080579161643982,
93
- "unseen_margin": -0.02285691164433956,
94
- "matched_queries": 4500.0,
95
- "matched_top1": 0.48955556750297546,
96
- "matched_top5": 0.6902222037315369,
97
- "matched_mrr": 0.5840909481048584,
98
- "matched_margin": -0.030851511284708977,
99
- "cross_queries": 18000.0,
100
- "cross_top1": 0.5808333158493042,
101
- "cross_top5": 0.7756111025810242,
102
- "cross_mrr": 0.6688519716262817,
103
- "cross_margin": -0.0005558129050768912
104
- },
105
- "k8": {
106
- "styles": 4500.0,
107
- "queries": 9000.0,
108
- "top1": 0.5631111264228821,
109
- "top5": 0.7501111030578613,
110
- "mrr": 0.6487501263618469,
111
- "margin": -0.006703122518956661,
112
- "positive_cosine": 0.7508071660995483,
113
- "hardest_negative_cosine": 0.7575103044509888,
114
- "verification_auroc": 0.557915985584259,
115
- "embedding_std": 0.04349411278963089,
116
- "embedding_effective_rank": 24.163583755493164,
117
- "seen_queries": 8000.0,
118
- "seen_top1": 0.5692500472068787,
119
- "seen_top5": 0.7573750615119934,
120
- "seen_mrr": 0.6548616290092468,
121
- "seen_margin": -0.004510539583861828,
122
- "unseen_queries": 1000.0,
123
- "unseen_top1": 0.5139999985694885,
124
- "unseen_top5": 0.6920000314712524,
125
- "unseen_mrr": 0.5998580455780029,
126
- "unseen_margin": -0.024243783205747604
127
- }
128
- },
129
- "human": {
130
- "k1": {
131
- "styles": 4500.0,
132
- "queries": 40500.0,
133
- "top1": 0.37967902421951294,
134
- "top5": 0.5846666693687439,
135
- "mrr": 0.47633036971092224,
136
- "margin": -0.07382111996412277,
137
- "positive_cosine": 0.6724859476089478,
138
- "hardest_negative_cosine": 0.7463070750236511,
139
- "verification_auroc": 0.38891345262527466,
140
- "embedding_std": 0.043804656714200974,
141
- "embedding_effective_rank": 27.383806228637695,
142
- "seen_queries": 36000.0,
143
- "seen_top1": 0.3872777819633484,
144
- "seen_top5": 0.5945833325386047,
145
- "seen_mrr": 0.48492416739463806,
146
- "seen_margin": -0.06964229047298431,
147
- "unseen_queries": 4500.0,
148
- "unseen_top1": 0.31888890266418457,
149
- "unseen_top5": 0.5053333640098572,
150
- "unseen_mrr": 0.40757980942726135,
151
- "unseen_margin": -0.10725177824497223
152
- },
153
- "k2": {
154
- "styles": 4500.0,
155
- "queries": 36000.0,
156
- "top1": 0.5184444785118103,
157
- "top5": 0.7187777757644653,
158
- "mrr": 0.6118195652961731,
159
- "margin": -0.018171189352869987,
160
- "positive_cosine": 0.7339839339256287,
161
- "hardest_negative_cosine": 0.7521551847457886,
162
- "verification_auroc": 0.516968846321106,
163
- "embedding_std": 0.043804656714200974,
164
- "embedding_effective_rank": 27.383806228637695,
165
- "seen_queries": 32000.0,
166
- "seen_top1": 0.5287187695503235,
167
- "seen_top5": 0.729593813419342,
168
- "seen_mrr": 0.6219512224197388,
169
- "seen_margin": -0.014534689486026764,
170
- "unseen_queries": 4000.0,
171
- "unseen_top1": 0.4362500309944153,
172
- "unseen_top5": 0.6322500109672546,
173
- "unseen_mrr": 0.5307666063308716,
174
- "unseen_margin": -0.04726320877671242
175
- },
176
- "k4": {
177
- "styles": 4500.0,
178
- "queries": 27000.0,
179
- "top1": 0.6229629516601562,
180
- "top5": 0.8089629411697388,
181
- "mrr": 0.7071906924247742,
182
- "margin": 0.01628497801721096,
183
- "positive_cosine": 0.7733137607574463,
184
- "hardest_negative_cosine": 0.7570288181304932,
185
- "verification_auroc": 0.6160270571708679,
186
- "embedding_std": 0.043804656714200974,
187
- "embedding_effective_rank": 27.383806228637695,
188
- "seen_queries": 24000.0,
189
- "seen_top1": 0.6336249709129333,
190
- "seen_top5": 0.8175833225250244,
191
- "seen_mrr": 0.7167206406593323,
192
- "seen_margin": 0.019602350890636444,
193
- "unseen_queries": 3000.0,
194
- "unseen_top1": 0.5376666784286499,
195
- "unseen_top5": 0.7400000095367432,
196
- "unseen_mrr": 0.6309514045715332,
197
- "unseen_margin": -0.01025400310754776
198
- },
199
- "k5": {
200
- "styles": 4500.0,
201
- "queries": 22500.0,
202
- "top1": 0.6493777632713318,
203
- "top5": 0.8219555616378784,
204
- "mrr": 0.7280733585357666,
205
- "margin": 0.022814957424998283,
206
- "positive_cosine": 0.7811680436134338,
207
- "hardest_negative_cosine": 0.7583531141281128,
208
- "verification_auroc": 0.6369090676307678,
209
- "embedding_std": 0.043804656714200974,
210
- "embedding_effective_rank": 27.383806228637695,
211
- "seen_queries": 20000.0,
212
- "seen_top1": 0.660099983215332,
213
- "seen_top5": 0.830549955368042,
214
- "seen_mrr": 0.7378283143043518,
215
- "seen_margin": 0.026178810745477676,
216
- "unseen_queries": 2500.0,
217
- "unseen_top1": 0.5636000037193298,
218
- "unseen_top5": 0.7531999945640564,
219
- "unseen_mrr": 0.6500336527824402,
220
- "unseen_margin": -0.004095893818885088
221
- },
222
- "k8": {
223
- "styles": 4500.0,
224
- "queries": 9000.0,
225
- "top1": 0.6846666932106018,
226
- "top5": 0.8516666889190674,
227
- "mrr": 0.7596060037612915,
228
- "margin": 0.03352390229701996,
229
- "positive_cosine": 0.793936014175415,
230
- "hardest_negative_cosine": 0.7604120373725891,
231
- "verification_auroc": 0.6696112155914307,
232
- "embedding_std": 0.043804656714200974,
233
- "embedding_effective_rank": 27.383806228637695,
234
- "seen_queries": 8000.0,
235
- "seen_top1": 0.6943750381469727,
236
- "seen_top5": 0.85875004529953,
237
- "seen_mrr": 0.7680479884147644,
238
- "seen_margin": 0.03656964749097824,
239
- "unseen_queries": 1000.0,
240
- "unseen_top1": 0.6070000529289246,
241
- "unseen_top5": 0.7950000166893005,
242
- "unseen_mrr": 0.6920705437660217,
243
- "unseen_margin": 0.009157972410321236
244
- }
245
- },
246
- "checkpoint_score": 0.6290457844734192,
247
- "checkpoint_config": {
248
- "packed_manifest_sha256": "c1267b9fd45c6e0d222b91d6ae2291b36b763277cc39cbc32484874ffeae9b32",
249
- "use_anima": true,
250
- "face_dropout": 0.3,
251
- "episode_pairs": 8,
252
- "seed": 20260719
253
- }
254
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
model.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:6cdf126152927f6e31dc856a8d10b8decee3bb20ce4c0ca449206db65d4633ec
3
- size 69962484
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c7f38c64babe6a1dd711f7819654640b40102d6e73ae45cd2675dc84cda03453
3
+ size 207972492
modeling_anima_style_embedding.py CHANGED
@@ -1,341 +1,441 @@
1
  from __future__ import annotations
2
 
3
- import math
4
 
5
  import torch
6
- from torch import Tensor, nn
7
- from torch.nn import functional as F
8
 
9
 
10
- def masked_mean_prototype(per_image: Tensor, mask: Tensor) -> Tensor:
11
- if per_image.ndim != 3 or mask.shape != per_image.shape[:2]:
12
- raise ValueError("expected per_image [batch,references,width] and matching mask")
13
- mask = mask.to(device=per_image.device, dtype=torch.bool)
14
- counts = mask.sum(dim=1)
15
- if torch.any(counts < 1) or torch.any(counts > 8):
16
- raise ValueError("each reference set must contain 1-8 images")
17
- weights = mask.unsqueeze(-1).to(per_image.dtype)
18
- mean = (per_image * weights).sum(dim=1) / counts.unsqueeze(-1)
19
- return F.normalize(mean, dim=-1)
20
 
21
 
22
- class StyleMixerBlock(nn.Module):
23
- def __init__(self, width: int, heads: int, dropout: float = 0.0) -> None:
 
 
24
  super().__init__()
25
- self.query_norm = nn.LayerNorm(width)
26
- self.token_norm = nn.LayerNorm(width)
27
- self.attention = nn.MultiheadAttention(width, heads, batch_first=True)
28
- self.attention_dropout = nn.Dropout(dropout)
29
- self.output_norm = nn.LayerNorm(width)
30
- self.mlp = nn.Sequential(
31
- nn.Linear(width, 4 * width),
32
- nn.GELU(),
33
- nn.Dropout(dropout),
34
- nn.Linear(4 * width, width),
35
- nn.Dropout(dropout),
36
- )
37
 
38
- def forward(self, query: Tensor, tokens: Tensor, token_mask: Tensor) -> Tensor:
39
- value, _ = self.attention(
40
- self.query_norm(query),
41
- self.token_norm(tokens),
42
- self.token_norm(tokens),
43
- key_padding_mask=~token_mask,
44
- need_weights=False,
45
- )
46
- query = query + self.attention_dropout(value)
47
- return query + self.mlp(self.output_norm(query))
48
 
49
 
50
- class UnifiedStyleEncoder(nn.Module):
51
- """Encode cached full/face vision tokens and optional Anima descriptors."""
52
 
53
  def __init__(
54
  self,
55
- *,
56
- external_dim: int = 1152,
57
- external_tokens: int = 30,
58
- anima_dim: int = 4096,
59
- anima_tokens: int = 3,
60
- width: int = 384,
61
- blocks: int = 2,
62
- heads: int = 6,
63
- embedding_dim: int = 512,
64
- use_anima: bool = True,
65
- dropout: float = 0.0,
66
- reference_grounding: bool = False,
67
- functional_factors: bool = False,
68
  ) -> None:
69
  super().__init__()
70
- if (
71
- blocks < 1
72
- or width % heads
73
- or (reference_grounding and embedding_dim % heads)
74
- or not 0.0 <= dropout < 1.0
75
- ):
76
- raise ValueError("blocks must be positive and width must be divisible by heads")
77
- if functional_factors and embedding_dim != 512:
78
- raise ValueError("functional factorization currently requires a 512-D embedding")
79
- self.external_tokens = external_tokens
80
- self.anima_tokens = anima_tokens if use_anima else 0
81
- self.external_projector = nn.Sequential(
82
- nn.LayerNorm(external_dim),
83
- nn.Linear(external_dim, width),
 
 
 
 
 
 
 
 
 
 
 
84
  )
85
- self.anima_projector = (
86
- nn.Sequential(nn.LayerNorm(anima_dim), nn.Linear(anima_dim, width))
87
- if use_anima
88
- else None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  )
90
- self.full_positions = nn.Parameter(torch.randn(external_tokens, width) * 0.02)
91
- self.face_positions = nn.Parameter(torch.randn(external_tokens, width) * 0.02)
92
- self.anima_positions = (
93
- nn.Parameter(torch.randn(anima_tokens, width) * 0.02) if use_anima else None
94
  )
95
- self.reference_grounding = reference_grounding
96
- self.functional_factors = functional_factors
97
- query_count = 5 if functional_factors else 1
98
- self.style_query = nn.Parameter(torch.randn(1, query_count, width) * 0.02)
99
- self.blocks = nn.ModuleList(
100
- [StyleMixerBlock(width, heads, dropout) for _ in range(blocks)]
101
  )
102
- if functional_factors:
103
- self.factor_output = nn.Sequential(nn.LayerNorm(width), nn.Linear(width, 96))
104
- self.shared_output = nn.Sequential(nn.LayerNorm(width), nn.Linear(width, 128))
105
- self.output = nn.Sequential(nn.LayerNorm(512), nn.Linear(512, embedding_dim))
106
- self.factor_decoders = nn.ModuleList([nn.Linear(96, external_dim) for _ in range(4)])
107
- else:
108
- self.output = nn.Sequential(nn.LayerNorm(width), nn.Linear(width, embedding_dim))
109
- if reference_grounding:
110
- self.consensus_query = nn.Parameter(torch.randn(1, 1, embedding_dim) * 0.02)
111
- self.consensus_attention = nn.MultiheadAttention(
112
- embedding_dim, heads, batch_first=True, dropout=dropout
113
- )
114
- self.consensus_condition = nn.Linear(embedding_dim, width)
115
- self.consensus_gamma = nn.Parameter(torch.tensor(-2.9444))
116
-
117
- def _read_tokens(
118
- self, tokens: Tensor, token_mask: Tensor, conditioning: Tensor | None = None
119
- ) -> tuple[Tensor, Tensor | None]:
120
- query = self.style_query.expand(tokens.shape[0], -1, -1)
121
- if conditioning is not None:
122
- query = query + self.consensus_condition(conditioning)[:, None]
123
- for block in self.blocks:
124
- query = block(query, tokens, token_mask)
125
- if self.functional_factors:
126
- factors = F.normalize(self.factor_output(query[:, :4]), dim=-1)
127
- shared = self.shared_output(query[:, 4])
128
- embedding = self.output(torch.cat((factors.flatten(1), shared), dim=-1))
129
- return F.normalize(embedding, dim=-1), factors
130
- return F.normalize(self.output(query[:, 0]), dim=-1), None
131
-
132
- def encode_images(
133
- self,
134
- full_features: Tensor,
135
- *,
136
- face_features: Tensor | None = None,
137
- face_mask: Tensor | None = None,
138
- anima_features: Tensor | None = None,
139
- conditioning: Tensor | None = None,
140
- ) -> Tensor:
141
- """Encode independent images without padding them into reference sets."""
142
-
143
- if full_features.ndim != 3 or full_features.shape[1] != self.external_tokens:
144
- raise ValueError("full_features must have shape [images,external_tokens,width]")
145
- images = full_features.shape[0]
146
- full = self.external_projector(full_features) + self.full_positions
147
- tokens = [full]
148
- masks = [torch.ones(full.shape[:2], dtype=torch.bool, device=full.device)]
149
-
150
- if face_features is not None:
151
- if face_features.shape != full_features.shape:
152
- raise ValueError("face_features must match full_features")
153
- if face_mask is None or face_mask.shape != (images,):
154
- raise ValueError("face_mask is required and must contain one value per image")
155
- face = self.external_projector(face_features)
156
- tokens.append(face + self.face_positions)
157
- masks.append(face_mask[:, None].to(torch.bool).expand(-1, self.external_tokens))
158
-
159
- if self.anima_projector is not None:
160
- expected = (images, self.anima_tokens)
161
- if anima_features is None or anima_features.shape[:2] != expected:
162
- raise ValueError("anima_features are required by this encoder configuration")
163
- anima = self.anima_projector(anima_features)
164
- tokens.append(anima + self.anima_positions)
165
- masks.append(torch.ones(anima.shape[:2], dtype=torch.bool, device=anima.device))
166
-
167
- token_tensor = torch.cat(tokens, dim=1)
168
- token_mask = torch.cat(masks, dim=1)
169
- return self._read_tokens(token_tensor, token_mask, conditioning)[0]
170
-
171
- def encode_images_with_factors(
172
- self,
173
- full_features: Tensor,
174
- *,
175
- face_features: Tensor | None = None,
176
- face_mask: Tensor | None = None,
177
- anima_features: Tensor | None = None,
178
- conditioning: Tensor | None = None,
179
- ) -> tuple[Tensor, Tensor | None]:
180
- if full_features.ndim != 3 or full_features.shape[1] != self.external_tokens:
181
- raise ValueError("full_features must have shape [images,external_tokens,width]")
182
- images = full_features.shape[0]
183
- full = self.external_projector(full_features) + self.full_positions
184
- tokens = [full]
185
- masks = [torch.ones(full.shape[:2], dtype=torch.bool, device=full.device)]
186
- if face_features is not None:
187
- if face_features.shape != full_features.shape:
188
- raise ValueError("face_features must match full_features")
189
- if face_mask is None or face_mask.shape != (images,):
190
- raise ValueError("face_mask is required and must contain one value per image")
191
- tokens.append(self.external_projector(face_features) + self.face_positions)
192
- masks.append(face_mask[:, None].to(torch.bool).expand(-1, self.external_tokens))
193
- if self.anima_projector is not None:
194
- if anima_features is None or anima_features.shape[:2] != (images, self.anima_tokens):
195
- raise ValueError("anima_features are required by this encoder configuration")
196
- tokens.append(self.anima_projector(anima_features) + self.anima_positions)
197
- masks.append(torch.ones(anima_features.shape[:2], dtype=torch.bool, device=full.device))
198
- return self._read_tokens(torch.cat(tokens, dim=1), torch.cat(masks, dim=1), conditioning)
199
-
200
- def encode_reference_sets(
201
- self,
202
- full_features: Tensor,
203
- reference_mask: Tensor,
204
- *,
205
- face_features: Tensor | None = None,
206
- face_mask: Tensor | None = None,
207
- anima_features: Tensor | None = None,
208
- ) -> tuple[Tensor, Tensor, Tensor | None]:
209
- batch, references = full_features.shape[:2]
210
- flat_face = None if face_features is None else face_features.flatten(0, 1)
211
- flat_face_mask = None if face_mask is None else face_mask.flatten()
212
- flat_anima = None if anima_features is None else anima_features.flatten(0, 1)
213
- per_image, factors = self.encode_images_with_factors(
214
- full_features.flatten(0, 1),
215
- face_features=flat_face,
216
- face_mask=flat_face_mask,
217
- anima_features=flat_anima,
218
  )
219
- per_image = per_image.reshape(batch, references, -1)
220
- factors = None if factors is None else factors.reshape(batch, references, 4, -1)
221
- base = masked_mean_prototype(per_image, reference_mask)
222
- if not self.reference_grounding:
223
- return base, per_image, factors
224
- consensus, _ = self.consensus_attention(
225
- self.consensus_query.expand(batch, -1, -1),
226
- per_image,
227
- per_image,
228
- key_padding_mask=~reference_mask,
229
- need_weights=False,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
  )
231
- consensus = F.normalize(consensus[:, 0], dim=-1)
232
- reread, factors = self.encode_images_with_factors(
233
- full_features.flatten(0, 1),
234
- face_features=flat_face,
235
- face_mask=flat_face_mask,
236
- anima_features=flat_anima,
237
- conditioning=consensus[:, None].expand(-1, references, -1).reshape(batch * references, -1),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
238
  )
239
- reread = reread.reshape(batch, references, -1)
240
- factors = None if factors is None else factors.reshape(batch, references, 4, -1)
241
- agreement = F.cosine_similarity(reread, consensus[:, None], dim=-1)
242
- centered = agreement - (
243
- (agreement * reference_mask).sum(1, keepdim=True)
244
- / reference_mask.sum(1, keepdim=True).clamp_min(1)
 
 
 
 
 
 
 
 
 
 
 
 
 
245
  )
246
- weights = (1.0 + 0.25 * torch.tanh(4.0 * centered)) * reference_mask
247
- grounded = F.normalize((reread * weights[..., None]).sum(1) / weights.sum(1, keepdim=True), dim=-1)
248
- gamma = torch.sigmoid(self.consensus_gamma)
249
- return F.normalize(base + gamma * (grounded - base), dim=-1), reread, factors
250
-
251
- def functional_response_loss(self, factor_codes: Tensor, full_features: Tensor) -> Tensor:
252
- """Reconstruct artist response after removing a shared prompt/seed cell mean."""
253
- if not self.functional_factors:
254
- return full_features.new_zeros(())
255
- groups = ((2, 3, 4, 5), (0, 6, 24), tuple(range(8, 24)), (1, 7, 25))
256
- losses = []
257
- for index, token_indices in enumerate(groups):
258
- teacher = full_features[..., list(token_indices), :].float().mean(dim=-2)
259
- teacher = F.normalize(teacher - teacher.mean(dim=1, keepdim=True), dim=-1)
260
- prediction = F.normalize(self.factor_decoders[index](factor_codes[..., index, :]).float(), dim=-1)
261
- losses.append((1.0 - F.cosine_similarity(prediction, teacher, dim=-1)).mean())
262
- return torch.stack(losses).mean()
263
 
264
  def forward(
265
  self,
266
- full_features: Tensor,
267
- reference_mask: Tensor,
268
- *,
269
- face_features: Tensor | None = None,
270
- face_mask: Tensor | None = None,
271
- anima_features: Tensor | None = None,
272
- ) -> tuple[Tensor, Tensor]:
273
- if full_features.ndim != 4 or full_features.shape[2] != self.external_tokens:
274
- raise ValueError("full_features must have shape [batch,references,external_tokens,width]")
275
- batch, references = full_features.shape[:2]
276
- if reference_mask.shape != (batch, references):
277
- raise ValueError("reference_mask shape does not match full_features")
278
-
279
- prototype, per_image, _ = self.encode_reference_sets(
280
- full_features,
281
- reference_mask,
282
- face_features=face_features,
283
- face_mask=face_mask,
284
- anima_features=anima_features,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
285
  )
286
- return prototype, per_image
 
 
 
 
 
 
 
 
287
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
288
 
289
- class AngularPrototypeLoss(nn.Module):
290
- """Episode prototype softmax with an optional ArcFace-style positive margin."""
 
 
 
 
 
 
291
 
292
- def __init__(
293
- self, initial_scale: float = 10.0, initial_bias: float | None = None
294
- ) -> None:
295
- super().__init__()
296
- if initial_scale <= 0:
297
- raise ValueError("initial_scale must be positive")
298
- self.raw_scale = nn.Parameter(torch.tensor(math.log(math.expm1(initial_scale))))
299
- # initial_bias remains accepted for feasibility-script compatibility. A
300
- # common softmax bias is a no-op and is not a trainable production parameter.
 
301
 
302
- def forward(
303
- self,
304
- queries: Tensor,
305
- prototypes: Tensor,
306
- targets: Tensor,
307
- *,
308
- margin: float = 0.0,
309
- ) -> tuple[Tensor, Tensor]:
310
- if queries.ndim < 2 or prototypes.ndim != queries.ndim:
311
- raise ValueError("queries and prototypes must have matching [episode,...,width] ranks")
312
- if queries.shape[:-2] != prototypes.shape[:-2] or queries.shape[-1] != prototypes.shape[-1]:
313
- raise ValueError("queries and prototypes must have matching episode axes and widths")
314
- if targets.shape != queries.shape[:-1]:
315
- raise ValueError("targets must contain one class index per query")
316
- # Autocast can round a near-perfect BF16 cosine to exactly one. ArcFace's
317
- # sqrt(1-cos��) derivative is then singular, so margin math and CE stay FP32.
318
- cosine = (
319
- F.normalize(queries, dim=-1)
320
- @ F.normalize(prototypes, dim=-1).transpose(-1, -2)
321
- ).float()
322
- loss_cosine = cosine
323
- if margin:
324
- if not 0.0 <= margin < math.pi / 2:
325
- raise ValueError("margin must be in [0, pi/2)")
326
- positive = cosine.gather(-1, targets.unsqueeze(-1)).clamp(-1 + 1e-6, 1 - 1e-6)
327
- positive_margin = positive * math.cos(margin) - torch.sqrt(1 - positive.square()) * math.sin(margin)
328
- loss_cosine = cosine.scatter(-1, targets.unsqueeze(-1), positive_margin)
329
- scale = F.softplus(self.raw_scale).clamp_max(100.0)
330
- loss_logits = scale * loss_cosine
331
- metric_logits = scale * cosine
332
- return (
333
- F.cross_entropy(loss_logits.flatten(0, -2), targets.flatten()),
334
- metric_logits,
335
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
336
 
337
 
338
- def subset_consistency_loss(first: Tensor, second: Tensor) -> Tensor:
339
- if first.shape != second.shape or first.ndim != 2:
340
- raise ValueError("subset prototypes must have equal [batch,width] shapes")
341
- return (1.0 - F.cosine_similarity(first, second, dim=-1)).mean()
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  from __future__ import annotations
2
 
3
+ from math import isqrt
4
 
5
  import torch
6
+ from torch import nn
7
+ import torch.nn.functional as F
8
 
9
 
10
+ FACTOR_NAMES = ("line", "color", "texture", "layout")
 
 
 
 
 
 
 
 
 
11
 
12
 
13
+ class ValueOnlyResampler(nn.Module):
14
+ """Position-free, bias-free resampling whose output is zero for zero values."""
15
+
16
+ def __init__(self, width: int, tokens: int = 144, heads: int = 8) -> None:
17
  super().__init__()
18
+ if width % heads:
19
+ raise ValueError("width must be divisible by heads")
20
+ self.heads = heads
21
+ self.head_dim = width // heads
22
+ self.queries = nn.Parameter(torch.empty(tokens, width))
23
+ self.q_proj = nn.Linear(width, width, bias=False)
24
+ self.k_proj = nn.Linear(width, width, bias=False)
25
+ self.v_proj = nn.Linear(width, width, bias=False)
26
+ self.out_proj = nn.Linear(width, width, bias=False)
27
+ nn.init.normal_(self.queries, std=width**-0.5)
 
 
28
 
29
+ def forward(self, values: torch.Tensor) -> torch.Tensor:
30
+ batch, source_tokens, width = values.shape
31
+ target_tokens = self.queries.shape[0]
32
+ queries = self.queries.unsqueeze(0).expand(batch, -1, -1)
33
+ q = self.q_proj(queries).view(batch, target_tokens, self.heads, self.head_dim).transpose(1, 2)
34
+ k = self.k_proj(values).view(batch, source_tokens, self.heads, self.head_dim).transpose(1, 2)
35
+ v = self.v_proj(values).view(batch, source_tokens, self.heads, self.head_dim).transpose(1, 2)
36
+ result = F.scaled_dot_product_attention(q, k, v)
37
+ return self.out_proj(result.transpose(1, 2).reshape(batch, target_tokens, width))
 
38
 
39
 
40
+ class SharedAxisStyleEncoder(nn.Module):
41
+ """One VAE field and one shared axis space for embedding, routing, and transfer."""
42
 
43
  def __init__(
44
  self,
45
+ dino_dim: int,
46
+ style_dim: int = 1024,
47
+ axis_count: int = 256,
48
+ embedding_dim: int = 1024,
49
+ anima_dim: int = 0,
50
+ resolution: str = "s12",
51
+ set_layers: int = 2,
52
+ set_heads: int = 8,
53
+ direct_context_axes: bool = False,
54
+ axis_aligned: bool = False,
55
+ disable_token_film: bool = False,
56
+ translation_invariant_stats: bool = False,
 
57
  ) -> None:
58
  super().__init__()
59
+ if resolution not in {"s12", "s24r"}:
60
+ raise ValueError(f"unknown spatial resolution: {resolution}")
61
+ if axis_count % set_heads:
62
+ raise ValueError("axis_count must be divisible by set_heads")
63
+ self.resolution = resolution
64
+ self.style_dim = style_dim
65
+ self.axis_count = axis_count
66
+ self.embedding_dim = embedding_dim
67
+ self.set_layers = set_layers
68
+ self.set_heads = set_heads
69
+ self.direct_context_axes = direct_context_axes
70
+ self.axis_aligned = axis_aligned
71
+ self.disable_token_film = disable_token_film
72
+ self.translation_invariant_stats = translation_invariant_stats
73
+ if disable_token_film and not axis_aligned:
74
+ raise ValueError("disable_token_film requires axis_aligned=True")
75
+ if translation_invariant_stats and not axis_aligned:
76
+ raise ValueError("translation-invariant statistics require axis_aligned=True")
77
+ last_stride = 2 if resolution == "s12" else 1
78
+ self.stem = nn.Sequential(
79
+ nn.Conv2d(16, 256, 3, stride=2, padding=1),
80
+ nn.GELU(),
81
+ nn.Conv2d(256, 512, 3, stride=2, padding=1),
82
+ nn.GELU(),
83
+ nn.Conv2d(512, style_dim, 3, stride=last_stride, padding=1),
84
  )
85
+ self.token_norm = nn.LayerNorm(style_dim, elementwise_affine=False)
86
+ self.dino_norm = nn.LayerNorm(dino_dim)
87
+ self.dino_film = nn.Linear(dino_dim, 2 * style_dim, bias=False)
88
+ self.dino_relation = nn.Linear(dino_dim, axis_count, bias=False)
89
+ nn.init.zeros_(self.dino_film.weight)
90
+
91
+ self.axis_dictionary = nn.Parameter(torch.empty(style_dim, axis_count))
92
+ nn.init.orthogonal_(self.axis_dictionary)
93
+ self.membership_logits = nn.Parameter(torch.zeros(len(FACTOR_NAMES), axis_count))
94
+ self.moment_projection = nn.Linear(2 * axis_count, axis_count, bias=False)
95
+ relation_layer = nn.TransformerEncoderLayer(
96
+ axis_count,
97
+ nhead=set_heads,
98
+ dim_feedforward=2 * axis_count,
99
+ dropout=0.0,
100
+ activation="gelu",
101
+ batch_first=True,
102
+ norm_first=True,
103
  )
104
+ self.relation_encoder = nn.TransformerEncoder(
105
+ relation_layer,
106
+ set_layers,
107
+ enable_nested_tensor=False,
108
  )
109
+ self.axis_reliability = nn.Linear(axis_count, axis_count)
110
+ self.face_reliability = nn.Linear(axis_count, 1)
111
+ self.embedding_head = nn.Sequential(
112
+ nn.LayerNorm(axis_count),
113
+ nn.Linear(axis_count, embedding_dim),
 
114
  )
115
+ self.resampler = (
116
+ ValueOnlyResampler(style_dim, tokens=144, heads=set_heads)
117
+ if resolution == "s24r"
118
+ else None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  )
120
+ # Construct optional modality modules last so matched runs share identical common initialization.
121
+ self.anima_norm = nn.LayerNorm(anima_dim) if anima_dim else None
122
+ self.anima_film = nn.Linear(anima_dim, 2 * style_dim, bias=False) if anima_dim else None
123
+ self.anima_relation = nn.Linear(anima_dim, axis_count, bias=False) if anima_dim else None
124
+ if self.anima_film is not None:
125
+ nn.init.zeros_(self.anima_film.weight)
126
+ if axis_aligned:
127
+ self.axis_moment_weights = nn.Parameter(torch.empty(axis_count, 2))
128
+ nn.init.normal_(self.axis_moment_weights, std=axis_count**-0.5)
129
+ if translation_invariant_stats:
130
+ self.axis_power_weights = nn.Parameter(torch.zeros(axis_count, 4))
131
+
132
+ def model_config(self) -> dict[str, int | str | bool]:
133
+ return {
134
+ "style_dim": self.style_dim,
135
+ "axis_count": self.axis_count,
136
+ "embedding_dim": self.embedding_dim,
137
+ "anima_dim": self.anima_norm.normalized_shape[0] if self.anima_norm is not None else 0,
138
+ "resolution": self.resolution,
139
+ "set_layers": self.set_layers,
140
+ "set_heads": self.set_heads,
141
+ "direct_context_axes": self.direct_context_axes,
142
+ "axis_aligned": self.axis_aligned,
143
+ "disable_token_film": self.disable_token_film,
144
+ "translation_invariant_stats": self.translation_invariant_stats,
145
+ }
146
+
147
+ def _field(
148
+ self,
149
+ latent: torch.Tensor,
150
+ scale: torch.Tensor,
151
+ shift: torch.Tensor,
152
+ axis_shift: torch.Tensor | None = None,
153
+ ) -> tuple[torch.Tensor, torch.Tensor]:
154
+ batch, references = latent.shape[:2]
155
+ field = self.stem(latent.flatten(0, 1).float())
156
+ field = field.flatten(2).transpose(1, 2).reshape(batch, references, -1, field.shape[1])
157
+ field = self.token_norm(field)
158
+ field = field * (1 + scale.unsqueeze(2)) + shift.unsqueeze(2)
159
+ axes = torch.einsum("brnd,dk->brnk", field, self.axis_dictionary.to(field.dtype))
160
+ if axis_shift is not None:
161
+ axes = axes + axis_shift.unsqueeze(2)
162
+ return field, axes
163
+
164
+ def _moments(self, axes: torch.Tensor) -> torch.Tensor:
165
+ mean = axes.mean(dim=2)
166
+ log_std = torch.log(axes.std(dim=2, unbiased=False).clamp_min(1e-6))
167
+ if self.axis_aligned:
168
+ coordinates = (
169
+ torch.stack((mean, log_std), dim=-1)
170
+ * self.axis_moment_weights.to(mean.dtype)
171
+ ).sum(-1)
172
+ if self.translation_invariant_stats:
173
+ power = self._power_statistics(axes).to(mean.dtype)
174
+ coordinates = coordinates + (
175
+ power * self.axis_power_weights.to(mean.dtype)
176
+ ).sum(-1)
177
+ return coordinates
178
+ moments = torch.cat((mean, log_std), dim=-1)
179
+ return self.moment_projection(moments)
180
+
181
+ def _power_statistics(self, axes: torch.Tensor) -> torch.Tensor:
182
+ """Phase-free radial and directional power for each aligned spatial axis."""
183
+ side = isqrt(axes.shape[2])
184
+ if side * side != axes.shape[2]:
185
+ raise ValueError(f"unexpected spatial token count: {axes.shape[2]}")
186
+ fy = torch.fft.fftfreq(side, device=axes.device)[:, None]
187
+ fx = torch.fft.rfftfreq(side, device=axes.device)[None, :]
188
+ radius2 = fy.square() + fx.square()
189
+ radius = radius2.sqrt()
190
+ basis = torch.stack((
191
+ ((radius > 0) & (radius <= 0.25)).float(),
192
+ ((radius > 0.25) & (radius <= 0.5)).float(),
193
+ (fx.square() - fy.square()) / radius2.clamp_min(1e-12),
194
+ 4 * fx.square() * fy.square() / radius2.square().clamp_min(1e-12),
195
+ ))
196
+ rfft_weight = torch.ones(side // 2 + 1, device=axes.device)
197
+ rfft_weight[1:-1] = 2
198
+ maps = axes.float().permute(0, 1, 3, 2).reshape(
199
+ *axes.shape[:2],
200
+ axes.shape[-1],
201
+ side,
202
+ side,
203
  )
204
+ maps = maps - maps.mean(dim=(-2, -1), keepdim=True)
205
+ power = torch.fft.rfft2(maps, norm="ortho").abs().square()
206
+ power = power * rfft_weight[None, None, None, None, :]
207
+ power = power / power.sum(dim=(-2, -1), keepdim=True).clamp_min(1e-12)
208
+ return torch.einsum("brkhw,phw->brkp", power, basis)
209
+
210
+ def factor_coordinates(self, axis_coordinates: torch.Tensor) -> torch.Tensor:
211
+ """Apply overlapping factor memberships without creating factor branches."""
212
+ memberships = torch.sigmoid(self.membership_logits).to(axis_coordinates.dtype)
213
+ return axis_coordinates.unsqueeze(-2) * memberships
214
+
215
+ def encode_vae_axes(self, latents: torch.Tensor) -> torch.Tensor:
216
+ """Encode VAE latents without DINO/Anima context for the frozen transfer teacher."""
217
+ if latents.ndim != 5 or latents.shape[2] != 16:
218
+ raise ValueError(f"expected latents [B,R,16,H,W], got {tuple(latents.shape)}")
219
+ batch, references = latents.shape[:2]
220
+ zeros = torch.zeros(
221
+ batch,
222
+ references,
223
+ self.axis_dictionary.shape[0],
224
+ device=latents.device,
225
+ dtype=latents.dtype,
226
  )
227
+ _, axes = self._field(latents, zeros, zeros)
228
+ return self._moments(axes)
229
+
230
+ def _user_axis_gate(self, user_weights: torch.Tensor) -> torch.Tensor:
231
+ memberships = torch.sigmoid(self.membership_logits)
232
+ factors = user_weights[..., : len(FACTOR_NAMES)].unsqueeze(-1)
233
+ return 1 - torch.prod(1 - factors * memberships[None, None], dim=-2)
234
+
235
+ def _controlled_tokens(
236
+ self,
237
+ axes: torch.Tensor,
238
+ beta: torch.Tensor,
239
+ view_gate: torch.Tensor,
240
+ ) -> torch.Tensor:
241
+ gated = axes * beta.unsqueeze(2) * view_gate[:, :, None, None]
242
+ tokens = torch.einsum(
243
+ "brnk,dk->brnd",
244
+ gated,
245
+ self.axis_dictionary.to(gated.dtype),
246
  )
247
+ if self.resampler is not None:
248
+ batch, references, token_count, width = tokens.shape
249
+ tokens = self.resampler(tokens.reshape(batch * references, token_count, width))
250
+ tokens = tokens.reshape(batch, references, -1, width)
251
+ return tokens
252
+
253
+ def soft_orthogonality_loss(self) -> torch.Tensor:
254
+ dictionary = F.normalize(self.axis_dictionary, dim=0)
255
+ gram = dictionary.T @ dictionary
256
+ return (gram - torch.eye(gram.shape[0], device=gram.device, dtype=gram.dtype)).square().mean()
 
 
 
 
 
 
 
257
 
258
  def forward(
259
  self,
260
+ full_latents: torch.Tensor,
261
+ dino: torch.Tensor,
262
+ reference_valid: torch.Tensor,
263
+ face_latents: torch.Tensor | None = None,
264
+ face_valid: torch.Tensor | None = None,
265
+ user_weights: torch.Tensor | None = None,
266
+ mode: str = "auto",
267
+ overall_style_gain: float | torch.Tensor = 1.0,
268
+ build_memory: bool = True,
269
+ anima: torch.Tensor | None = None,
270
+ ) -> dict[str, torch.Tensor]:
271
+ if full_latents.ndim != 5 or full_latents.shape[2] != 16:
272
+ raise ValueError(f"expected full latents [B,R,16,H,W], got {tuple(full_latents.shape)}")
273
+ if not reference_valid.any(dim=1).all():
274
+ raise ValueError("every sample needs at least one valid reference")
275
+ if mode not in {"auto", "assisted", "manual"}:
276
+ raise ValueError(f"unknown routing mode: {mode}")
277
+
278
+ batch, references = full_latents.shape[:2]
279
+ if user_weights is None:
280
+ user_weights = torch.ones(
281
+ batch,
282
+ references,
283
+ len(FACTOR_NAMES) + 1,
284
+ device=full_latents.device,
285
+ dtype=full_latents.dtype,
286
+ )
287
+ context = self.dino_norm(dino.float())
288
+ scale, shift = self.dino_film(context).chunk(2, dim=-1)
289
+ relation_context = self.dino_relation(context)
290
+ if self.anima_norm is not None:
291
+ if anima is None:
292
+ raise ValueError("Anima features are required when anima_dim is configured")
293
+ anima_context = self.anima_norm(anima.float().flatten(start_dim=2))
294
+ anima_scale, anima_shift = self.anima_film(anima_context).chunk(2, dim=-1)
295
+ scale = scale + anima_scale
296
+ shift = shift + anima_shift
297
+ relation_context = relation_context + self.anima_relation(anima_context)
298
+ elif anima is not None:
299
+ raise ValueError("Anima features were provided but anima_dim=0")
300
+ if self.disable_token_film:
301
+ scale = torch.zeros_like(scale)
302
+ shift = torch.zeros_like(shift)
303
+ axis_shift = (
304
+ relation_context
305
+ if self.axis_aligned and self.direct_context_axes
306
+ else None
307
  )
308
+ full_field, full_axes = self._field(
309
+ full_latents,
310
+ scale,
311
+ shift,
312
+ axis_shift,
313
+ )
314
+ full_coordinates = self._moments(full_axes)
315
+ if self.direct_context_axes and not self.axis_aligned:
316
+ full_coordinates = full_coordinates + relation_context
317
 
318
+ if face_latents is None:
319
+ face_valid = torch.zeros_like(reference_valid)
320
+ face_axes = None
321
+ face_coordinates = torch.zeros_like(full_coordinates)
322
+ else:
323
+ if face_valid is None:
324
+ raise ValueError("face_valid is required with face_latents")
325
+ _, face_axes = self._field(
326
+ face_latents,
327
+ scale,
328
+ shift,
329
+ axis_shift,
330
+ )
331
+ face_coordinates = self._moments(face_axes)
332
 
333
+ preliminary = (
334
+ full_coordinates
335
+ + face_coordinates * face_valid.unsqueeze(-1)
336
+ + (0 if self.direct_context_axes else relation_context)
337
+ )
338
+ contextual = self.relation_encoder(preliminary, src_key_padding_mask=~reference_valid)
339
+ reliability = torch.sigmoid(self.axis_reliability(contextual))
340
+ predicted_face = torch.sigmoid(self.face_reliability(contextual).squeeze(-1))
341
 
342
+ if mode == "auto":
343
+ face_weight = predicted_face
344
+ elif mode == "assisted":
345
+ face_weight = predicted_face * user_weights[..., -1]
346
+ else:
347
+ face_weight = user_weights[..., -1]
348
+ face_weight = face_weight * face_valid * reference_valid
349
+ coordinates = (
350
+ full_coordinates + face_weight.unsqueeze(-1) * face_coordinates
351
+ ) / (1 + face_weight.unsqueeze(-1))
352
 
353
+ axis_gate = self._user_axis_gate(user_weights.float())
354
+ valid = reference_valid.unsqueeze(-1).to(axis_gate.dtype)
355
+ if mode == "auto":
356
+ weights = reliability * valid
357
+ gamma = torch.ones(batch, self.axis_dictionary.shape[1], device=weights.device, dtype=weights.dtype)
358
+ elif mode == "assisted":
359
+ weights = reliability * axis_gate * valid
360
+ gamma = axis_gate.amax(dim=1)
361
+ else:
362
+ weights = axis_gate * valid
363
+ gamma = axis_gate.amax(dim=1)
364
+
365
+ denominator = weights.sum(dim=1, keepdim=True)
366
+ alpha = torch.where(
367
+ denominator > 0,
368
+ weights / denominator.clamp_min(torch.finfo(weights.dtype).tiny),
369
+ torch.zeros_like(weights),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
370
  )
371
+ beta = alpha * gamma.unsqueeze(1)
372
+ mixed = gamma * torch.einsum("brk,brk->bk", alpha, coordinates)
373
+
374
+ gain = torch.as_tensor(overall_style_gain, device=mixed.device, dtype=mixed.dtype)
375
+ while gain.ndim < mixed.ndim:
376
+ gain = gain.unsqueeze(-1)
377
+ mixed = mixed * gain
378
+ beta = beta * gain.unsqueeze(1) if gain.ndim == 2 else beta * gain
379
+
380
+ pre_embedding = self.embedding_head(mixed)
381
+ output = {
382
+ "embedding": F.normalize(pre_embedding, dim=-1),
383
+ "pre_embedding": pre_embedding,
384
+ "style_present": mixed.ne(0).any(dim=-1),
385
+ "reference_axis_coordinates": coordinates,
386
+ "axis_coordinates": mixed,
387
+ "axis_reliability": reliability,
388
+ "axis_weights": weights,
389
+ "axis_alpha": alpha,
390
+ "axis_gamma": gamma,
391
+ "factor_memberships": torch.sigmoid(self.membership_logits),
392
+ "reference_factor_coordinates": self.factor_coordinates(coordinates),
393
+ "factor_coordinates": self.factor_coordinates(mixed),
394
+ "face_weight": face_weight,
395
+ }
396
+ if build_memory:
397
+ full_tokens = self._controlled_tokens(
398
+ full_axes,
399
+ beta,
400
+ reference_valid.to(beta.dtype),
401
+ )
402
+ memories = [full_tokens.flatten(1, 2)]
403
+ memory_masks = [
404
+ reference_valid[:, :, None].expand(-1, -1, full_tokens.shape[2]).flatten(1)
405
+ ]
406
+ if face_axes is not None:
407
+ face_tokens = self._controlled_tokens(face_axes, beta, face_weight)
408
+ memories.append(face_tokens.flatten(1, 2))
409
+ memory_masks.append(
410
+ (reference_valid & face_valid)[:, :, None]
411
+ .expand(-1, -1, face_tokens.shape[2])
412
+ .flatten(1)
413
+ )
414
+ output.update({
415
+ "style_memory": torch.cat(memories, dim=1),
416
+ "style_memory_valid": torch.cat(memory_masks, dim=1),
417
+ "style_condition": torch.einsum(
418
+ "bk,dk->bd",
419
+ mixed,
420
+ self.axis_dictionary.to(mixed.dtype),
421
+ ),
422
+ })
423
+ return output
424
 
425
 
426
+ def load_shared_axis_state(
427
+ model: SharedAxisStyleEncoder,
428
+ state: dict[str, torch.Tensor],
429
+ ) -> None:
430
+ """Load a checkpoint, deriving aligned per-axis moments from a legacy dense head."""
431
+ state = dict(state)
432
+ if model.axis_aligned and "axis_moment_weights" not in state:
433
+ dense = state["moment_projection.weight"]
434
+ axes = model.axis_count
435
+ state["axis_moment_weights"] = torch.stack((
436
+ dense.diagonal(),
437
+ dense[:, axes:].diagonal(),
438
+ ), dim=-1)
439
+ if model.translation_invariant_stats and "axis_power_weights" not in state:
440
+ state["axis_power_weights"] = torch.zeros_like(model.axis_power_weights)
441
+ model.load_state_dict(state)
requirements.txt CHANGED
@@ -1,3 +1,3 @@
1
- torch>=2.4
2
- safetensors>=0.4
3
- huggingface_hub>=0.28
 
1
+ torch>=2.5
2
+ safetensors>=0.4.5
3
+ huggingface_hub>=0.27