grinpress ๐๏ธ๐พ
woof woof! hot off the press: tiny inky faces, freshly fetched :3
hiii, welcome to grinpress! it's a smol (33.86M params) text-to-image model, trained totally from scratch with rectified flow right in pixel space ๐พ. you tell it a color, a mood, and a lil word, and it barks back a 128ร128 vintage-newspaper halftone face with your word stamped beside it, all inky and smudgy on old yellowed newsprint. bark! :3
a red smiley face with 'HELLO' next to it
๐ฎ try it live: huggingface.co/spaces/skyuu72/grinpress-demo (ZeroGPU, about 1 s per batch!) ๐พ
made with lots of tail wags by the puppygirl CEO of Quantara (quantara.cv) ๐พ๐
Model ๐ง ๐พ
| part | params | details |
|---|---|---|
| U-Net | 32.23M | levels 128/64/32/16 with channels 64/128/192/256; 2 ResBlocks per level; AdaGN timestep conditioning (sinusoidal embedding into an MLP); self-attention and masked char-level cross-attention at the 32/16 levels and in the mid block |
| Text encoder | 1.63M | ASCII byte tokenizer (max 64 chars, full caption); learned embeddings + sinusoidal positions; 2-layer transformer (d=256); 10% CFG dropout to a learned null sequence |
| Total | 33.86M | see config.json |
Flow: x_t = (1-t)ยทx0 + tยทฮต (t=0 is data, t=1 is noise). The network predicts v = ฮต โ x0 and is
trained with MSE, with t sampled logit-normal. Sampling uses Euler integration from t=1 to t=0 with
classifier-free guidance v = v_u + sยท(v_c โ v_u).
Training ๐๏ธ๐พ
- Data: 50k procedurally generated 128px images (
generate_data.py): aged newsprint, a halftone face in one of 12 colors, a smiley/sad/meh expression, and 1โ8 characters of wood-type/serif text with ink bleed and distressed edges. - Schedule: 60k steps at batch 64. AdamW at lr 2e-4 with 1k warmup steps, then cosine decay. bf16 autocast and EMA (0.9999). The released weights are the EMA weights.
- Hardware: a single A100 on Google Colab, about 7 h wall clock including 2 resumes from checkpoint.
Training progression (watch the pup learn!) :3
Fixed prompts and seeds at each checkpoint. Rows: red smiley 'HELLO', blue sad 'NEWS', green meh 'OK', yellow smiley 'XQ7'.
A fresh sample from the released weights (a pink sad face with 'HEY' next to it, 50 steps, CFG 5) ๐พ:
Every grid, saved every 5k steps, is in samples/. Layout and color settle early, and
later steps mostly sharpen the letterforms; random strings like 'XQ7' are clearly cleaner at 60k.
Prompt format ๐ฆด
a {color} {expression} face with '{text}' next to it
- color: red, orange, yellow, green, teal, blue, navy, purple, pink, brown, gray, cyan
- expression: smiley, sad, meh
- text: 1โ8 ASCII characters (trained mostly on uppercase words and random letters/digits)
sample.py checks the prompt with a regex and gives a helpful error when it doesn't match.
Usage ๐พ
pip install torch numpy pillow opencv-python-headless
python sample.py --prompt "a pink sad face with 'HEY' next to it" \
--checkpoint ema_final_bf16.pt --cfg_scale 5.0 --steps 50 --seed 0 --num_images 4 --out out.png
sample.py loads the ema entry of the checkpoint. Weights: ema_final_bf16.pt (about 68 MB, bf16 EMA; the loader upcasts it) and model.safetensors (the same bf16
EMA tensors, flat keys). woof, pick whichever you like! :3
Python:
import torch
from model import build_model
from sample import sample, parse_prompt
m = build_model().eval()
m.load_state_dict({k: v.float() for k, v in torch.load("ema_final_bf16.pt", map_location="cpu")["ema"].items()})
x = sample(m, parse_prompt("a teal meh face with 'OK' next to it")[3], 128, 50, 5.0, 0, "cpu") # [-1,1]
Or with safetensors (pip install safetensors):
python sample.py --prompt "a navy smiley face with 'WOOF' next to it" --checkpoint model.safetensors --out woof.png
Training from scratch: see smiley_flow_colab.ipynb (it resumes from Drive across disconnects), or
run_pipeline.sh.
Inference speed ๐จ
| setup | 50 steps + CFG (100 forward passes) |
|---|---|
| CPU, 8-thread Xeon, fp32 (measured) | 26.8 s/img (25 steps: 13.3 s); peak RAM about 0.9 GB |
| A100, bf16 (estimate) | about 0.5โ1 s/img at batch 1; about 15โ20 img/s batched |
| L4 (estimate) | about 1โ1.5 s/img; about 6 img/s batched |
| T4 (estimate) | about 1.5โ2.5 s/img; about 3 img/s batched |
A single forward pass is 66.1 GFLOPs at 128px (measured with the torch FLOP counter). The GPU numbers are estimates assuming 30โ35% of peak throughput; they were not measured.
Limitations (she's a good girl, but...) ๐ถ
- Only the fixed procedural domain: one face plus a text string on newsprint. It is not a general-purpose image model.
- Only 1โ8 characters of text and only the 12 trained colors. Prompts outside the template are rejected.
- Letters are occasionally smudged or malformed, especially in long random strings and lowercase text.
- 128px only. The code supports 256px, but these weights were not trained at that size.
License ๐๐พ
MIT. The fonts used to generate the training data are downloaded at runtime under their own OFL/Apache licenses and are not included.
arf arf, thanks for visiting! go make some inky lil faces :3 ๐พ๐๏ธ
- Downloads last month
- 17




