Reproducing noisy/translucent sprites with the published checkpoint: recipe and diagnostic results
Thank you for releasing Alucard, the dataset, and the training code. We are evaluating it for pixel-art game assets and investigated soft/noisy RGBA outputs using both the upstream API and our local integration. We would appreciate help confirming the expected output for the documented recipe, or identifying a known-good checkpoint/environment.
The main finding: we can reproduce the issue directly with upstream Alucard, and our integration produces identical pixels under matched conditions. Checking earlier weights and several inference variations did not recover clean sprites. This does not establish that a training failure occurred; we may still be missing an environment or training/inference detail.
Minimal reproduction
Upstream code tested: 02d1c60a16142015f7838a6a033da5e6ac9ce4f7. The following uses the model card's wizard recipe and pins the tested weight revision:
from alucard import Alucard
from huggingface_hub import hf_hub_download
import numpy as np
weights = hf_hub_download(
"evilsocket/alucard",
"alucard_model.safetensors",
revision="b8e7602fc8e676d0b0bc0abb11d2cda665c560d8",
)
model = Alucard.from_pretrained(weights, device="cpu")
sprite = model(
"a pixel art wizard sprite",
num_samples=1,
num_steps=20,
cfg_text=5.0,
cfg_ref=2.0,
seed=42,
)
sprite.save("alucard-wizard.png")
alpha = np.asarray(sprite.convert("RGBA"))[..., 3]
print("partial alpha fraction:", ((alpha > 0) & (alpha < 255)).mean())
Observed: a recognizable but fuzzy figure with background texture; all 16,384 pixels have alpha strictly between 0 and 255 (partial alpha fraction: 1.0). We expected a more clearly defined sprite and useful transparent background. Partial alpha alone is not evidence of a broken model; the visual softness, background noise, and weak response to different subjects are the practical concerns.
Original CPU output, without post-processing.
We also checked CUDA on an RTX 5080 (16 GB). The final diagnostic environment was Python 3.11, PyTorch 2.10.0+cu128, OpenCLIP 3.3.0, FP32 inference. CPU and CUDA use different noise streams, so we compare implementations on the same device, rather than expecting identical CPU/GPU pictures.
Checks and comparisons
| Check | Observation |
|---|---|
| Installed weight vs published file | SHA-256 matches; all parameters finite |
| Cached OpenCLIP file vs publisher | SHA-256 matches |
| Upstream API vs our integration, original CPU recipe | Identical pixel arrays |
| Upstream vs locally corrected sampler, original CUDA recipe | Maximum absolute tensor difference 0 |
| Load safetensors directly vs containing directory | Same result |
Previous weights ef54ee9 and d3d7dd1 |
Similar fuzzy figures; no fully transparent/opaque pixels for tested wizard/knight outputs |
Older weight 4e70eb0 |
More noisy detail; no useful visual recovery |
| Text CFG 1, 2, 3, 5, 7; 100 Euler steps at CFG 1/5 | Changes appearance, but no clean recovery |
ViT-B-32-quickgelu vs upstream's ViT-B-32 |
No useful visual recovery |
| Velocity gains 1.05/1.10/1.15/1.25, tapered gain 1.10, 40-step Heun, 100-step Euler + gain 1.10 | Some noise decreases with gain, but detail collapses and prompt failures persist |
The final sampler comparison used four prompts with the same CUDA noise seeded with 42, text CFG 5, no reference: wizard, knight, dragon, and slime. In particular, the model-card dragon prompt produced noisy textures in these tests. No experimental correction was retained as a quality fix.
Visual comparison: four prompts across eight sampler variants
The native RGBA outputs are enlarged with nearest-neighbor scaling and composited over a checkerboard for inspection. Row timings measure a batch of four with precomputed embeddings, after model loading; the first batch includes cold-start overhead. They are not end-to-end CLI timings.
Checksums and exact comparison prompts
- Current weight:
2f502cc676c9fc34009d6c57caa4e782512a2643f436bc16408f477c352ccc2c - Previous
ef54ee9:7653d4dd9f09c725f26aba022325712b6ae2df7877cd97c3e8b79064a3ba88c4 - Previous
d3d7dd1:27dc99d8cffe7757e4a4ccd8af758f22e4aad35687111dfcc47358b16948b486 - OpenCLIP
timm/vit_base_patch32_clip_224.openai,open_clip_model.safetensors:e6d1bd7789aa45192b3bf90570a789b478bae1b74ebcce7eddd908e83a2b7c31
Prompts, in comparison-image column order:
a pixel art wizard spritea pixel art knight sprite, idle posea pixel art dragon enemy spritepixel art, green, small, slime, blob creature, front view
Separate sampler edge cases
While reviewing sample.py, we found two control behaviors worth flagging independently:
- With no reference,
cfg_text < 1takes the non-CFG branch and ignores the requested fractional/zero scale. - With
cfg_text > 1and a supplied reference,cfg_ref == 1drops the reference because the reference branch only runs forcfg_ref > 1.
Applying the documented equation consistently resolves these cases:
v_guided = v_uncond + cfg_text * (v_text - v_uncond)
if ref is not None:
v_guided += cfg_ref * (v_both - v_text)
We verified zero, fractional, unit and amplified scales with a small deterministic test model. Neither edge case explains the original text-only wizard output, and fixing them preserves the original default recipe exactly. We also fixed batch-seed reporting and cancellation/progress in our integration; those are integration changes, not evidence of an upstream quality cause.
Additional diagnostic and training-code observations (not established causes)
We audited 96 real images and their actual CLIP-encoded captions from the current alucard-sprites dataset: three contiguous 32-row windows starting at rows 0, 156250 and 312454. This is a small, nonrandom diagnostic sample, not a general dataset-quality estimate or held-out benchmark.
- The source's velocity objective fits the measurements; changing output interpretation, timestep scale, or embedding scale did not reveal a consistently better interpretation.
- Correct captions helped relative to shuffled captions most at high noise, so conditioning is not completely disconnected. At
t=1, velocity MSE was 0.7032 with correct captions vs 0.7486 shuffled; att=0.5, 0.09628 vs 0.09697. - A least-squares fit suggested multiplicative velocity gains around 1.08β1.11 for
t=0.05β0.9. Direct sampling tests did not validate this as a repair. - The sample included mixed styles/backgrounds and some visibly mismatched or vague captions. Mean partially transparent pixel fraction was approximately 0.48%, versus 100% for the original wizard output. That difference is diagnostic, not a proof of a particular failure.
In the pinned train.py, we noticed possible robustness improvements for a future run:
- An incomplete gradient-accumulation group carries into the next epoch. With the current 312,550-row dataset, batch 64,
drop_last=True, and accumulation 2, there are 4,883 microbatches per epoch; the next epoch's first update then includes three microbatches divided by two. - Scheduler/EMA/global-step advance even if FP16 GradScaler skips the optimizer update; scaler state is not included in saved checkpoints. We did not observe skipped updates in our short benchmark.
- Best-checkpoint selection uses training loss, and changing shuffled-batch RGB previews do not expose alpha defects. Fixed-seed RGBA previews and held-out checks would make comparisons easier.
We do not know whether any of these affected the released weights. The current dataset has 312,550 rows, while the model card describes training on 33K sprites, so the current dataset should not be assumed to be the exact training corpus. The published config also says FP16, whereas the current safetensors tensors are FP32; this may simply be stale metadata.
For context, a short compute-only training benchmark on our RTX 5080 reached about 97 images/s with BF16, batch 16, accumulation 8 and no activation checkpointing. It excluded loading/embedding preparation/validation and used synthetic normalized text embeddings; it measures throughput, not convergence or quality. No retrained checkpoint is being presented as a fix.
Would you be able to share a known-good output and its checkpoint/seed, the intended CLIP version/activation, or a raw-versus-EMA checkpoint comparison? Any recommended baseline would help us distinguish a setup mismatch from limitations of these particular weights. Thanks again for making the project available.
You guys are 100% correct, after the first training attempt i've noticed the outputs being noisy and did not have time to attempt a fix and/or improve the training dataset, apologies for this not being clear in the model card. This is/was an ongoing experiment more than a production ready model.

