Model Card for creative-graphic-design/pixel-vae-crello¶
This package ports the image encoder and decoder from CanvasVAE, the ICCV 2021 vector-document VAE, into a 🤗transformers-style package. Its MobileNetV2 encoder maps 256 × 256 RGBA previews to the 256-dimensional posterior mean used by CanvasVAE document records. The package is a separate workspace member so it can be converted, serialized, and parity-checked independently before the document model consumes it.
CPU parity passed on one deterministic, untrained TensorFlow state copied to PyTorch: all 17 held-out metrics met their frozen per-metric limits, and state mapping, decode, and encoder save/load checks passed. This verifies conversion only; no trained-checkpoint or embedding-quality result is claimed. See TRAINING.md for the evidence and EMBEDDING_CONTRACT.md for the shared Crello input and output contract.
Model Details¶
Model Description¶
PixelVAE receives four-channel RGBA values at their original 256 × 256 size. A MobileNetV2 encoder produces posterior mean and log-variance vectors with 256 dimensions; PixelVAEEncoder.encode exports the posterior mean without sampling. The decoder produces 16 categorical logits for each RGBA channel after removing the lowest four bits of source pixels. Its objective combines alpha-masked RGB reconstruction loss, alpha reconstruction loss, a KL term weighted by 100, and L2 regularization on the variational heads.
- Developed by: Kota Yamaguchi.
- Shared by: creative-graphic-design.
- Model type: content-aware; task: evaluation; conditioning: evaluation.
- Language(s) (NLP): not applicable.
- License: Apache-2.0.
Model Sources¶
- Repository: CanvasVAE source, pinned at
bc1e2072ba3a253f1b099e8b0c604f6051e787dafor conversion and parity. - Paper: CanvasVAE, ICCV 2021.
- Released weights: none; the conversion script can convert an original TensorFlow checkpoint or a deterministic untrained initialization.
Supported Checkpoints¶
| Checkpoint | Hub ID | Status |
|---|---|---|
| Crello v1 | creative-graphic-design/pixel-vae-crello |
not-published |
No trained checkpoint is included or published. The seed-0 untrained conversion is only a deterministic parity fixture and is not suitable for semantic retrieval or design decisions.
Uses¶
Direct Use¶
Use PixelVAEEncoder to reproduce original posterior-mean image embeddings or to supply those embeddings to a compatible CanvasVAE document pipeline. The document encoder accepts every element's PNG bytes, regardless of element type. PixelVAE training examples use the original three-type filter (imageElement, maskElement, and svgElement).
Downstream Use¶
CanvasVAE may consume embeddings in the order recorded by its document manifest. Use the shared embedding contract for exact PNG decoding, ID ownership, output dtype, and row ordering.
Out-of-Scope Use¶
The seed-0 untrained encoder does not provide meaningful visual similarity, semantic understanding, or a quality-ranked embedding space. The package does not render vector documents or clear Crello designs for redistribution.
Bias, Risks, and Limitations¶
This port targets the original 256 × 256 RGBA path and rejects other dimensions instead of resizing them. The crello-dataset-v1.zip archive and all derived embeddings remain private. Crello design previews may contain third-party artwork; do not redistribute the archive, previews, or embeddings.
Recommendations¶
Use an encoder converted from a trained original checkpoint for research applications, preserve the original document element order, and evaluate downstream behavior on the intended data. CPU agreement on an untrained state verifies the conversion path, not trained embedding quality.
How to Get Started with the Model¶
Install the package directly from this repository. laygen is included because PixelVAE uses the shared vendor-path helper during conversion.
pip install \
"laygen @ git+https://github.com/creative-graphic-design/design-generators.git#subdirectory=lib/laygen" \
"pixel-vae @ git+https://github.com/creative-graphic-design/design-generators.git#subdirectory=models/pixel-vae"
For conversion and CPU reproduction, clone the repository and follow REPRODUCING.md. The commands there save an encoder under .cache/pixel-vae/converted/encoder.
git clone https://github.com/creative-graphic-design/design-generators.git
cd design-generators
uv sync --package pixel-vae
uv run --package pixel-vae python
from io import BytesIO
import torch
from PIL import Image
from pixel_vae import PixelVAEEncoder, PixelVAEImageProcessor
stream = BytesIO()
Image.new("RGBA", (256, 256)).save(stream, format="PNG")
# After Hub publication: from_pretrained("creative-graphic-design/pixel-vae-crello")
encoder = PixelVAEEncoder.from_pretrained(".cache/pixel-vae/converted/encoder").eval()
inputs = PixelVAEImageProcessor()(stream.getvalue())
with torch.inference_mode():
embedding = encoder.encode(inputs.pixel_values)
print(embedding.shape, embedding.dtype)
Captured output will be added after running the example against the converted CPU checkpoint.
Training Details¶
Training Data¶
| Dataset | Dataset ID | Notes |
|---|---|---|
| Crello | cyberagent/crello |
Original-code parity uses a private v1 archive; the archive and derived embeddings stay private. |
Original-code parity uses crello-dataset-v1.zip, 2,989,732,284 bytes with SHA-256 f6cab2d0c4d888f5082e3b19cfa841c6f483cecdfcbc02a30bc87bd3393cf91e. Keep the archive and derived embeddings private.
Training Procedure¶
This package does not include a package-local training loop or a trained checkpoint. It supports checkpoint conversion and CPU parity; GPU training, full-run evaluation, and S5 are out of scope.
Preprocessing¶
Decode every document-stage image_bytes PNG to RGBA at its original 256 × 256 dimensions, then map byte values to float32 [0, 1]. The encoder consumes all element types for document construction. Original PixelVAE training records select only imageElement, maskElement, and svgElement.
Training Hyperparameters¶
- Training regime: not retrained; the original configuration uses batch size 64, 250 epochs, Adam at 1e-4, KL weight 100, and L2 weight 1e-6.
Evaluation¶
Testing Data, Factors & Metrics¶
Testing Data¶
CPU parity starts with a report-only diagnostic, then uses three fixed, distinct canonical train input pairs for calibration and the canonical test inputs for a fresh held-out check. The full archive audit checks PNG validity and dimensions by element type without writing image data into the repository.
Factors¶
The source and package receive identical PNG bytes decoded to RGBA uint8 values, scaled to float32 [0, 1], and transposed to channels-first order for PyTorch. The test records the source commit, TensorFlow version, seed, encoder-state digest, and stable input IDs.
Metrics¶
Compare maximum absolute error for posterior means, posterior log variances, decoder logits, reconstruction/KL/total loss, gradients, Keras Adam moments, updated parameters, and a three-step short trace. Calibration uses three independent CPU processes on distinct train image groups and freezes max(L, ceil2(1.5 × max)) per metric, rounding upward to two significant figures while preserving the per-metric floor L from parity-limit-floors.json. The held-out run uses a fresh normal-mode CPU process; image decode and structural S0/S4 gates require exact equality.
Parity Results¶
The CPU acceptance passed against one deterministic, untrained TensorFlow state copied to PyTorch. All 17 held-out metrics met their frozen per-metric limits; state mapping and exact decode checks passed. The example limit below illustrates the metric-specific thresholds; PARITY_PROTOCOL.md lists every frozen limit alongside the original worker-run held-out maximum absolute error.
| Check | Cases | Criterion | Result |
|---|---|---|---|
| S0 state mapping | 1 untrained TensorFlow state; all mapped variables | exact config, one-to-one keys, and bitwise transformed tensors | pass; all checks exact |
| S1 forward and losses | 6 held-out metrics | each metric within its frozen absolute bound; posterior mean atol=1.4e-10 |
pass; 6/6 metrics |
| S2 gradients and optimizer | 6 held-out metrics | each metric within its frozen absolute bound | pass; 6/6 metrics |
| S3 three-step trace | 4 held-out metrics | each metric within its frozen absolute bound | pass; 4/4 metrics |
| S4 archive, decode, and serialization | 23,361 documents; 5 element types; 1 encoder round trip; 1 held-out metric | all archive PNGs valid at 256 × 256; exact RGBA decode and round trip; metric within frozen bound | pass; full audit and exact checks; 1/1 metric |
Reproducibility¶
Reproduce agreement with the original TensorFlow implementation using REPRODUCING.md, which covers the pinned source, private Crello archive, three-run CPU calibration, held-out validation, conversion, and local loading. No trained-checkpoint reproduction is claimed.
Technical Specifications¶
Model Architecture and Objective¶
The encoder uses Keras MobileNetV2 topology with a four-channel first convolution, global average pooling, and two dense variational heads. The decoder projects 256 latent values to an 8 × 8 × 32 grid, applies five transposed-convolution upsampling layers and one output convolution, then reshapes logits to [batch, 256, 256, 4, 16].
Compute Infrastructure¶
Hardware¶
The only verified runtime in this package is CPU; GPU training and S5 evaluation have no result and are not claimed.
Software¶
The model uses PyTorch and 🤗transformers. Conversion and source comparison require TensorFlow CPU 2.15.1. See the package pyproject.toml for workspace dependencies.
Citation¶
@inproceedings{yamaguchi2021canvasvae,
title={CanvasVAE: Learning to Generate Vector Graphic Documents},
author={Yamaguchi, Kota},
booktitle={Proceedings of the IEEE/CVF International Conference on Computer Vision},
year={2021}
}
API Reference¶
Transformers-style PixelVAE model package.
PixelVAEConfig ¶
Bases: PretrainedConfig
Configuration for the 256 × 256 RGBA MobileNetV2 VAE.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
latent_dim
|
int
|
Dimension of each posterior vector. |
256
|
quantize_factor
|
int
|
Number of low bits removed from each target channel. |
4
|
kl_weight
|
float
|
Multiplier on the mean KL divergence. |
100.0
|
l2_weight
|
float
|
L2 coefficient for the two variational-head dense layers. |
1e-06
|
batch_norm_epsilon
|
float
|
Variance epsilon used by batch normalization. |
0.001
|
backbone_batch_norm_momentum
|
float
|
Moving-average momentum in MobileNetV2. |
0.999
|
decoder_batch_norm_momentum
|
float
|
Moving-average momentum in the decoder. |
0.99
|
**kwargs
|
str | int | float | bool | None
|
Extra Transformers configuration fields. |
{}
|
Examples:
>>> PixelVAEConfig().latent_dim
256
Source code in models/pixel-vae/src/pixel_vae/configuration_pixel_vae.py
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | |
__init__ ¶
__init__(
*,
latent_dim: int = 256,
quantize_factor: int = 4,
kl_weight: float = 100.0,
l2_weight: float = 1e-06,
batch_norm_epsilon: float = 0.001,
backbone_batch_norm_momentum: float = 0.999,
decoder_batch_norm_momentum: float = 0.99,
**kwargs: str | int | float | bool | None,
) -> None
Initialize the configuration with the production model defaults.
Source code in models/pixel-vae/src/pixel_vae/configuration_pixel_vae.py
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | |
PixelVAEImageProcessor ¶
Bases: BaseImageProcessor
Decode PNG bytes to unmodified 256 × 256 RGBA model inputs.
Examples:
>>> from io import BytesIO
>>> from PIL import Image
>>> stream = BytesIO()
>>> Image.new("RGBA", (256, 256)).save(stream, format="PNG")
>>> batch = PixelVAEImageProcessor()(stream.getvalue())
>>> tuple(batch.pixel_values.shape)
(1, 4, 256, 256)
Source code in models/pixel-vae/src/pixel_vae/image_processing_pixel_vae.py
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | |
__init__ ¶
__init__(**kwargs: str | int | float | bool | None) -> None
Initialize the processor without adding transform settings.
Source code in models/pixel-vae/src/pixel_vae/image_processing_pixel_vae.py
35 36 37 | |
preprocess ¶
preprocess(
images: bytes | Sequence[bytes],
*,
return_tensors: Literal["pt"] = "pt",
) -> BatchFeature
Decode PNG bytes and scale the exact RGBA pixels to [0, 1].
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
images
|
bytes | Sequence[bytes]
|
One PNG byte string or a sequence of PNG byte strings. |
required |
return_tensors
|
Literal['pt']
|
Tensor framework. Only |
'pt'
|
Returns:
| Type | Description |
|---|---|
BatchFeature
|
A batch feature with float32 |
Raises:
| Type | Description |
|---|---|
ValueError
|
If a PNG is malformed, is not 256 × 256, or another tensor framework is requested. |
Source code in models/pixel-vae/src/pixel_vae/image_processing_pixel_vae.py
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | |
PixelVAEEncoder ¶
Bases: PreTrainedModel
MobileNetV2 encoder that exports posterior-mean embeddings.
Source code in models/pixel-vae/src/pixel_vae/modeling_pixel_vae.py
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 | |
__init__ ¶
__init__(config: PixelVAEConfig) -> None
Create the feature extractor and posterior heads.
Source code in models/pixel-vae/src/pixel_vae/modeling_pixel_vae.py
259 260 261 262 263 264 265 266 267 | |
forward ¶
forward(
pixel_values: Float[Tensor, "batch 4 256 256"],
) -> PixelVAEEncoderOutput
Return posterior mean and log variance without sampling.
Source code in models/pixel-vae/src/pixel_vae/modeling_pixel_vae.py
269 270 271 272 273 274 275 276 277 278 | |
encode ¶
encode(
pixel_values: Float[Tensor, "batch 4 256 256"],
) -> Float[torch.Tensor, "batch latent"]
Return the float32 posterior mean used by Crello documents.
Source code in models/pixel-vae/src/pixel_vae/modeling_pixel_vae.py
280 281 282 283 284 285 286 | |
PixelVAEEncoderOutput
dataclass
¶
Bases: ModelOutput
Posterior statistics emitted by :class:PixelVAEEncoder.
Source code in models/pixel-vae/src/pixel_vae/modeling_pixel_vae.py
32 33 34 35 36 37 | |
PixelVAEModel ¶
Bases: PreTrainedModel
Transformers model implementing the RGBA PixelVAE objective.
Source code in models/pixel-vae/src/pixel_vae/modeling_pixel_vae.py
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 | |
__init__ ¶
__init__(config: PixelVAEConfig) -> None
Create the posterior encoder and autoregressive image decoder.
Source code in models/pixel-vae/src/pixel_vae/modeling_pixel_vae.py
371 372 373 374 375 376 | |
encode ¶
encode(
pixel_values: Float[Tensor, "batch 4 256 256"],
) -> Float[torch.Tensor, "batch latent"]
Export the encoder posterior mean without sampling.
Source code in models/pixel-vae/src/pixel_vae/modeling_pixel_vae.py
378 379 380 381 382 | |
forward ¶
forward(
pixel_values: Float[Tensor, "batch 4 256 256"],
*,
sample: bool | None = None,
epsilon: Float[Tensor, "batch latent"] | None = None,
) -> PixelVAEOutput
Compute logits and the source reconstruction, KL, and L2 losses.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pixel_values
|
Float[Tensor, 'batch 4 256 256']
|
Float32 RGBA images scaled to |
required |
sample
|
bool | None
|
Whether to sample the posterior; defaults to module mode. |
None
|
epsilon
|
Float[Tensor, 'batch latent'] | None
|
Optional fixed standard-normal noise for deterministic runs. |
None
|
Returns:
| Type | Description |
|---|---|
PixelVAEOutput
|
Decoder logits, posterior statistics, latent vectors, and losses. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If image dimensions or sampling-noise shape are invalid. |
TypeError
|
If inputs are not float32 tensors. |
Examples:
>>> model = PixelVAEModel(PixelVAEConfig(latent_dim=8)).eval()
>>> image = torch.zeros(1, 4, 256, 256)
>>> model(image).posterior_mean.shape
torch.Size([1, 8])
Source code in models/pixel-vae/src/pixel_vae/modeling_pixel_vae.py
384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 | |
PixelVAEOutput
dataclass
¶
Bases: ModelOutput
Reconstruction, posterior statistics, and losses from PixelVAE.
Source code in models/pixel-vae/src/pixel_vae/modeling_pixel_vae.py
40 41 42 43 44 45 46 47 48 49 50 | |
pixelvae_reconstruction_loss ¶
pixelvae_reconstruction_loss(
pixel_values: Float[Tensor, "batch 4 256 256"],
logits: Float[
Tensor, "batch height width channels levels"
],
quantize_factor: int = 4,
) -> Float[torch.Tensor, ""]
Compute the original alpha-masked RGB and unmasked alpha loss.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pixel_values
|
Float[Tensor, 'batch 4 256 256']
|
Float32 RGBA images scaled from source bytes. |
required |
logits
|
Float[Tensor, 'batch height width channels levels']
|
Per-channel categorical logits. |
required |
quantize_factor
|
int
|
Number of low source bits removed before CE. |
4
|
Returns:
| Type | Description |
|---|---|
Float[Tensor, '']
|
Reconstruction loss summed over rows and averaged over batch, columns, |
Float[Tensor, '']
|
and channels. |
Source code in models/pixel-vae/src/pixel_vae/modeling_pixel_vae.py
472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 | |
options: show_submodules: true