CoolFace
Modelpublic

Girinath11/recursive-language-model-198m

sourceHugging Facemitupdated 6mo agoView on Hugging Face
13likes111downloads
Model Card

Mixture of Recursion Language Model — 198M (Adaptive Computation)

198M parameter language model Built from scratch on a single T4 GPU — no pretrained base, no fine-tuning. Novel self-supervised perplexity-guided adaptive computation via Mixture of Recursion (MoR).


Novel Architecture: Mixture of Recursion (MoR)

Traditional transformers apply the same depth to every input — simple and complex sentences both go through all N layers. This wastes compute on easy inputs and under-processes hard ones.

MoR fixes this with self-supervised perplexity-guided routing:

High PPL (>50)   → Model struggling  → 5 recursive steps
Mid PPL (20–50)  → Uncertain         → 3 recursive steps  
Low PPL (<20)    → Model confident   → 1 recursive step

No manual labels needed — the router learns difficulty directly from the model's own perplexity signal during training.

Key Components

ComponentDescriptionParams
Token EmbeddingGPT-2 BPE vocab (50,260) + special tokens~39M
Base Transformer16 layers, RoPE, pre-norm, NaN-safe attention~149M
Perplexity Router2-layer MLP (768→384→3), self-supervised~1.2M
Recursive LayerShared transformer block, reused 1/3/5×~7M
Total~198M

NaN-Safe FP16 Training

Standard -inf masking causes NaN during fp16 mixed-precision training. MoR uses -1e4 masking + pre-softmax clamping — completely stable:

python
scores = scores.clamp(min=-1e4, max=1e4)
attn   = F.softmax(scores, dim=-1)
attn   = torch.nan_to_num(attn, nan=0.0)

Result: 0 NaN batches across all 150K training steps.


Performance — Honest Evaluation

Training Val Set (in-distribution)

Evaluated on 2,000 held-out samples from the same conversational distribution as training data (HH-RLHF + UltraChat + Alpaca-GPT4):

EpochTrain LossVal LossVal PPL
14.50813.079821.75
23.30682.732615.37

Fresh Test Set (out-of-distribution)

Evaluated on 500 fresh HH-RLHF test samples (never seen during training). GPT-2 Medium evaluated on identical samples for fair comparison:

ModelParamsPPL (fresh test)Notes
GPT-2 Medium345M26.89OpenAI baseline
MoR 198M198M43.21This model
Honest note: MoR scores higher PPL on the fresh test set than GPT-2 Medium. The 15.37 val PPL was measured on in-distribution data — the model shows signs of overfitting to the training distribution. The architecture is novel and the routing mechanism works correctly, but the model needs more diverse training data and longer training to generalize better. The val PPL (15.37) should not be directly compared to GPT-2 Medium's standard benchmark PPL — they are measured on different datasets.

What the Results Actually Show

Architecture works   — training is stable, loss decreases
Router works         — 0 NaN batches, routing signals valid
Novel contribution   — perplexity-based self-supervised routing
Generalization gap  — val PPL 15.37 vs test PPL 43.21
More data needed    — 150K samples is small for this model size

Quick Start

bash
pip install transformers torch
python
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

model = AutoModelForCausalLM.from_pretrained(
    "Girinath11/recursive-language-model-198m",
    trust_remote_code=True
)
tokenizer = AutoTokenizer.from_pretrained(
    "Girinath11/recursive-language-model-198m",
    trust_remote_code=True
)

device = "cuda" if torch.cuda.is_available() else "cpu"
model  = model.to(device).eval()

Chat Format (required)

The model was trained with a specific chat format — always use this:

python
def chat(question, max_new_tokens=150, temperature=0.7, top_p=0.9):
    prompt = f"<|user|>\n{question}\n<|assistant|>\n"

    inputs = tokenizer(
        prompt,
        return_tensors="pt",
        add_special_tokens=False
    ).to(device)

    with torch.no_grad():
        outputs = model.generate(
            inputs["input_ids"],
            max_new_tokens = max_new_tokens,
            temperature    = temperature,
            top_p          = top_p,
            do_sample      = True,
        )

    full = tokenizer.decode(outputs[0], skip_special_tokens=True)
    return full.split("<|assistant|>")[-1].strip() \
           if "<|assistant|>" in full else full

print(chat("What is machine learning?"))
print(chat("Explain neural networks simply"))

Training Details

Dataset — 150K Conversational Samples

DatasetSamples%Description
Anthropic HH-RLHF80,00053%Helpful & harmless human feedback
UltraChat50,00033%GPT-4 multi-turn dialogues
Alpaca-GPT420,00014%Instruction following
Validation2,000Held-out (same distribution)

Training Config

GPU            : NVIDIA Tesla T4 (15.6 GB VRAM)
Platform       : Kaggle (single GPU)
Epochs         : 2
Total steps    : 150,000
Training time  : ~9h 12m

Batch size     : 2
Grad accum     : 32  (effective batch = 64)
Max seq len    : 512
Learning rate  : 1e-4
LR schedule    : Linear warmup + Cosine decay
Warmup steps   : 500
Optimizer      : AdamW (β=0.9, 0.95, ε=1e-8)
Weight decay   : 0.01
Grad clip      : 1.0
Mixed precision: FP16 (AMP)

Loss:
  Total = LM loss + 0.1 × Router loss

Technical Innovation

Self-Supervised Perplexity Routing

python
# During training — no manual labels needed!
sample_ppl = exp(per_sample_ce_loss)

if sample_ppl < 20:   pseudo_label = 0  # simple
elif sample_ppl < 50: pseudo_label = 1  # medium
else:                 pseudo_label = 2  # complex

router_loss = CrossEntropyLoss(router_logits, pseudo_label)
total_loss  = lm_loss + 0.1 * router_loss

Why it works:

  • Router learns difficulty FROM the model's own performance
  • As training progresses, more samples become "simple" — natural curriculum
  • No annotation cost, no bias from human difficulty ratings

What I Learned / What to Improve Next

This model is my first from-scratch LLM — I learned a lot:

What worked:
  NaN-safe attention masking (-1e4)
  Self-supervised routing signal
  Stable FP16 training (0 NaN batches)
  Perplexity drops meaningfully across epochs

What needs improvement:
  More diverse training data (150K is small)
  Longer training (2 epochs not enough)
  Stronger regularization to prevent overfitting
  Better evaluation on neutral benchmarks from day 1

Limitations

  • Context window: 512 tokens max
  • English only: Not suitable for other languages
  • Small training set: 150K samples — commercial models use 100B+
  • Generalization: Shows overfitting to training distribution
  • Repetition: May loop in very long generations (>200 tokens)
  • Factual accuracy: May hallucinate — do not use for facts

Intended Use

Use caseSuitable?
Research on adaptive computationYes
Learning how LLMs are built from scratchYes
Prototyping conversational AIWith caveats
Production chatbotsNo
Medical / legal / financial adviceNo
Factual question answeringNo

Citation

bibtex
@misc{girinath2026mor,
  author       = {Girinath V},
  title        = {Mixture of Recursion: Self-Supervised Perplexity-Guided
                  Adaptive Computation for Language Models},
  year         = {2026},
  publisher    = {Hugging Face},
  howpublished = {\url{https://huggingface.co/Girinath11/recursive-language-model-198m}},
  note         = {198M parameter LM trained from scratch with adaptive
                  recursive computation via perplexity-based routing}
}

Acknowledgments

  • Anthropic — HH-RLHF dataset
  • Tsinghua University — UltraChat dataset
  • Vicgalle — Alpaca-GPT4 dataset
  • HuggingFace — Transformers library
  • Kaggle — Free GPU access

Model status : Research / Educational use Last updated : March 2026 License : MIT