A 261M-parameter nanochat-architecture GPT with the YatNMN-Softplus MLP (per-neuron bias, softplus-positive bias, learnable epsilon, learnable α). Trained in JAX/Flax on TPU v6e-8 to Chinchilla-optimal token budget on C4, then ported to PyTorch for easy inference via the HuggingFace transformers API.
This is the best-performing 261M model in the ablation series:
1import torch
2from transformers import AutoModelForCausalLM, AutoTokenizer
34model = AutoModelForCausalLM.from_pretrained(5"mlnomad/yatnmn-softplus-d12-chinchilla-261M-pytorch",6 trust_remote_code=True,7 dtype=torch.float32,8).eval()910tokenizer = AutoTokenizer.from_pretrained("mistralai/Mistral-7B-v0.1")1112prompt ="The meaning of life is"13ids = tokenizer(prompt, return_tensors="pt").input_ids
14with torch.no_grad():15 out = model.generate(16 ids, max_new_tokens=50,17 do_sample=True, temperature=0.8, top_p=0.9,18 use_cache=True, pad_token_id=tokenizer.eos_token_id or0,19)20print(tokenizer.decode(out[0], skip_special_tokens=True))
Greedy completion samples:
"The meaning of life is" → the same as life. The meaning of life is the same as life…
"Once upon a time," → the world was a place where people could live and work. The world was a place where people could…
YatNMN-Softplus MLP
Each MLP block uses the YatNMN nonlinearity from nmn>=0.2.29:
y = α · (x · W + softplus(b))² / (||x − W||² + softplus(ε))
with per-neuron biasb of shape (4·n_embd,) = (3072,), scalar learnable epsilon of shape (1,), and scalar learnable α of shape (1,). Both bias and epsilon are passed through softplus to keep them strictly positive. The MLP is then c_proj (Linear → 768) on top of YatNMN's output.
Model details
Parameters
261,133,226
Architecture
Nanochat-style GPT with YatNMN-Softplus MLP (ported from JAX/Flax NNX)
Smear — learnable gate on first 24 dims of token embedding mixes in prev token
Backout — subtract mid-layer residual from late layers
Logit soft-cap: 15 · tanh(logits / 15)
No biases in any Linear
KV cache
The YatGPTForCausalLM class implements a smear-aware KV cache for fast autoregressive generation. KV-cache parity vs full forward is validated at max |Δ| < 3e-5. Pass use_cache=True (the default for .generate()).