ostris commited on
Commit
f425156
·
verified ·
1 Parent(s): 8a432f7

Update weights for 2x1 to latest step

Browse files
Files changed (3) hide show
  1. README.md +16 -16
  2. assets/compare_2x1.svg +0 -0
  3. primal_vae_2x1.safetensors +2 -2
README.md CHANGED
@@ -84,10 +84,10 @@ A diffusion model is trained against Gaussian noise, so the latent should look l
84
  KL term and a scaling factor someone measures after the fact, I put the statistics directly in the loss on the
85
  encoder output.
86
 
87
- - **Moment loss** (both): `mean^2 + (std - 1)^2`, weight 0.1. On `2x1` the mean and std are pooled over the
88
- batch. On `2x2` they are per image and per channel, so every single image comes out mean 0 / std 1 in each
89
- channel, not just the dataset on average.
90
- - **Gaussian order-statistic loss** (`2x2`): sort the latent values of each image and channel and MSE them
91
  against the expected order statistics of a standard normal of the same size (Blom's approximation). This
92
  pins the whole distribution shape, not just the first two moments, so a flat gray image still encodes to
93
  something that looks like noise instead of a constant.
@@ -109,15 +109,15 @@ PSNR on these three 512 px images (dB):
109
  | image | Primal 2x1 | Flux.1 VAE | Primal 2x2 | Flux.2 VAE |
110
  |---|---|---|---|---|
111
  | img01 (people, studio) | 32.1 | 35.7 | 37.5 | 37.2 |
112
- | img02 (picnic, foliage) | 22.2 | 24.2 | 27.1 | 26.5 |
113
- | img03 (UI screenshot) | 21.0 | 24.7 | 27.4 | 25.9 |
114
 
115
  The 2x2 matches or beats the Flux.2 VAE here at the same information budget (both are 32 values per 8×8 pixel
116
  block). Three images and PSNR alone are not a benchmark, and a KL VAE pays a reconstruction tax for its posterior
117
  noise that a deterministic one does not. The 2x1 trails the Flux.1 VAE on textured content. One channel at 2x
118
- is a 12:1 reduction with no slack, and it has about a third of the training steps of the 2x2. Its per-image
119
- latent std also drifts (0.9 to 1.4 here) because its moment loss was batch pooled. The per-image normalization
120
- on the 2x2 holds std within a few percent of 1.
121
 
122
  ## Training
123
 
@@ -135,13 +135,13 @@ The tricks that should make the latent space easier to diffuse:
135
  - **Noise-perturbed decode.** On 20% of steps the decoder gets `z + sigma * noise`, `sigma` drawn per image
136
  from `U(0, 0.5)`, and still has to reconstruct the clean image. The decoder learns to tolerate diffusion
137
  model error and the latent gets smooth: nearby codes decode to nearby images.
138
- - **Solid colors** (`2x2`): 5% of images are swapped for a random flat color. Flat regions are the hard case
139
- for a per-image normalized latent.
140
- - **Critic** (`2x1`): a frozen SigLIP2 NaFlex ViT gives patch features from layers 4, 8 and 12 of the real and
141
- reconstructed image at native resolution. Small spectral-normalized conv heads on those features train with
142
- a hinge loss plus R1, and the decoder gets the generator term at weight 0.1, ramped in over the first 1000
143
- steps. It sharpens the texture that MAE and LPIPS leave soft. The 2x2 was trained without a critic, it
144
- seemed to converge fine without one.
145
 
146
  Every step is one encode and one decode. On a flip/rotate step the transformed pair replaces the clean pair
147
  instead of adding a second decoder pass.
 
84
  KL term and a scaling factor someone measures after the fact, I put the statistics directly in the loss on the
85
  encoder output.
86
 
87
+ - **Moment loss**: `mean^2 + (std - 1)^2`, weight 0.1, taken per image and per channel, so every single image
88
+ comes out mean 0 / std 1 in each channel, not just the dataset on average. The 2x1 spent its first 53k steps
89
+ with this pooled over the batch and switched to per image for the last 9k.
90
+ - **Gaussian order-statistic loss**: sort the latent values of each image and channel and MSE them
91
  against the expected order statistics of a standard normal of the same size (Blom's approximation). This
92
  pins the whole distribution shape, not just the first two moments, so a flat gray image still encodes to
93
  something that looks like noise instead of a constant.
 
109
  | image | Primal 2x1 | Flux.1 VAE | Primal 2x2 | Flux.2 VAE |
110
  |---|---|---|---|---|
111
  | img01 (people, studio) | 32.1 | 35.7 | 37.5 | 37.2 |
112
+ | img02 (picnic, foliage) | 22.0 | 24.2 | 27.1 | 26.5 |
113
+ | img03 (UI screenshot) | 21.3 | 24.7 | 27.4 | 25.9 |
114
 
115
  The 2x2 matches or beats the Flux.2 VAE here at the same information budget (both are 32 values per 8×8 pixel
116
  block). Three images and PSNR alone are not a benchmark, and a KL VAE pays a reconstruction tax for its posterior
117
  noise that a deterministic one does not. The 2x1 trails the Flux.1 VAE on textured content. One channel at 2x
118
+ is a 12:1 reduction with no slack, and it has well under half the training steps of the 2x2 (62k vs 147k). Its
119
+ per-image latent std still drifts (1.07 to 1.21 here) because it only got the per-image normalization for its
120
+ last 9k steps. The 2x2, trained with it throughout, holds std within a few percent of 1.
121
 
122
  ## Training
123
 
 
135
  - **Noise-perturbed decode.** On 20% of steps the decoder gets `z + sigma * noise`, `sigma` drawn per image
136
  from `U(0, 0.5)`, and still has to reconstruct the clean image. The decoder learns to tolerate diffusion
137
  model error and the latent gets smooth: nearby codes decode to nearby images.
138
+ - **Solid colors**: 5% of images are swapped for a random flat color. Flat regions are the hard case for a
139
+ per-image normalized latent.
140
+ - **Critic** (`2x1` only, last 9k steps): a frozen SigLIP2 NaFlex ViT gives patch features from layers 4, 8
141
+ and 12 of the real and reconstructed image at native resolution. Small spectral-normalized conv heads on
142
+ those features train with a hinge loss plus R1, and the decoder gets the generator term at weight 0.1,
143
+ ramped in over the first 1000 steps. It sharpens the texture that MAE and LPIPS leave soft. The 2x2 was
144
+ trained without a critic, it seemed to converge fine without one.
145
 
146
  Every step is one encode and one decode. On a flip/rotate step the transformed pair replaces the clean pair
147
  instead of adding a second decoder pass.
assets/compare_2x1.svg CHANGED
primal_vae_2x1.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:9cf37dd0ff80edde481ee2cae858107a71855e6ed5fb495aa095a09b33b9189a
3
- size 321415508
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b035c96861e3d36ed0a5308e89535ba19c26846d98c358a3907949ff8d1776f3
3
+ size 321415516