|
Download README.md from Debarun12/ScratchLM-95M: direct link, hf CLI and curl.
- Browser
- Download file 5.52 kB
-
https://huggingface.co/Debarun12/ScratchLM-95M/resolve/main/README.md
- Command line
-
hf download hf://Debarun12/ScratchLM-95M/README.md
-
curl -L -o README.md https://huggingface.co/Debarun12/ScratchLM-95M/resolve/main/README.md
5.52 kB
| license: apache-2.0 | |
| # ScratchLM-95M | |
| A 95-million-parameter transformer language model built **entirely from scratch** in PyTorch β no pretrained weights, no `from_pretrained`. Trained on WikiText-103 and fine-tuned for question answering using two-stage LoRA. | |
| > Beats GPT-3 Small (PPL 26.0) on WikiText-103 with 30% fewer parameters. | |
| --- | |
| ## Model Details | |
| | Property | Value | | |
| |---|---| | |
| | **Parameters** | ~95M (88.7M base + embedding table) | | |
| | **Architecture** | 12-layer causal transformer | | |
| | **Position Encoding** | RoPE (Rotary Position Embedding) | | |
| | **FFN Activation** | SwiGLU | | |
| | **Attention** | Causal + Flash Attention fallback | | |
| | **Context Length** | 512 tokens | | |
| | **Tokenizer** | GPT-2 BPE (vocab size 50,257) | | |
| | **Framework** | PyTorch (from scratch) | | |
| | **Base Pretraining** | WikiText-103 | | |
| | **Fine-tuning Method** | Two-stage LoRA (R128 β R64) | | |
| | **Trainable Params (LoRA)** | ~1.6M (1.8% of base) | | |
| --- | |
| ## Model Configuration | |
| ```python | |
| VOCAB_SIZE = 50257 # GPT-2 tokenizer | |
| MAX_SEQ_LEN = 512 # Context window | |
| EMBED_DIM = 512 # Model dimension | |
| NUM_HEADS = 8 # Attention heads | |
| NUM_LAYERS = 12 # Transformer blocks | |
| D_FF = 2730 # SwiGLU intermediate dim | |
| DROPOUT = 0.1 | |
| ``` | |
| --- | |
| ## Performance | |
| | Checkpoint | PPL | | |
| |---|---| | |
| | Base model (WikiText-103, Epoch 17) | 24.40 | | |
| | GPT-3 Small (reference) | 26.0 | | |
| | Stage 1 LoRA β R128, Ξ±=256, Epoch 7 | 21.48 | | |
| | **Stage 2 LoRA β R64, Ξ±=128, Epoch 2** | **20.83** | | |
| - **Total PPL improvement:** 3.57 points (24.40 β 20.83) | |
| - **Train/Val gap:** 0.1216 (healthy, no overfitting) | |
| - **Fine-tune hardware:** Single RTX 5050 (8.5GB VRAM), ~6 hours | |
| --- | |
| ## Training Details | |
| ### Base Pretraining (V3) | |
| | Hyperparameter | Value | | |
| |---|---| | |
| | Dataset | WikiText-103 | | |
| | Effective batch size | 32 (8 Γ 4 grad accum) | | |
| | Learning rate | 2e-4 (cosine decay) | | |
| | Warmup steps | 800 | | |
| | Optimizer | AdamW (Ξ²1=0.9, Ξ²2=0.95) | | |
| | Gradient clipping | 0.8 | | |
| | Best checkpoint | Epoch 17 | | |
| ### Fine-Tuning (Two-Stage LoRA) | |
| Full fine-tuning (all 95M params) caused catastrophic forgetting β PPL rose from 24.40 to 35+. LoRA was adopted to freeze 99% of weights. | |
| **LoRA config:** | |
| ```python | |
| LORA_R = 32 # Final rank | |
| LORA_ALPHA = 64 # Scaling factor (2Γ rank) | |
| LORA_DROPOUT = 0.05 | |
| # Target modules: qkv_proj, out_proj | |
| ``` | |
| **Two-stage strategy:** | |
| - **Stage 1** β LoRA R=128, Ξ±=256 β best PPL 21.48 at Epoch 7 | |
| - **Stage 2** β Merge Stage 1 weights into base, restart with LoRA R=64, Ξ±=128 β best PPL **20.83** at Epoch 2 | |
| Weight merge equation: | |
| ```python | |
| W_merged = W_base + (B @ A) * (alpha / rank) | |
| ``` | |
| ### Dataset Engineering | |
| 355k clean QA pairs from three sources, after rejecting 460k noisy alternatives: | |
| | Source | Pairs | Notes | | |
| |---|---|---| | |
| | FreebaseQA / TriviaQA | 205k | Factual pairs | | |
| | ELI5 (cleaned) | 90k | Reddit markdown stripped | | |
| | SciQ | 60k | Science explanations | | |
| Cleaning steps: regex removal of filler phrases (`"the correct answer is..."`), Reddit markdown stripping, deduplication, length filtering (20β80 word answers), proper punctuation enforcement. ~22,000 entries removed. | |
| --- | |
| ## Usage | |
| ```python | |
| from transformers import AutoTokenizer, AutoModelForCausalLM | |
| import torch | |
| tokenizer = AutoTokenizer.from_pretrained("Debarun12/ScratchLM-95M") | |
| model = AutoModelForCausalLM.from_pretrained("Debarun12/ScratchLM-95M") | |
| model.eval() | |
| prompt = "What is the official language of Brazil?" | |
| inputs = tokenizer(prompt, return_tensors="pt") | |
| with torch.no_grad(): | |
| output = model.generate( | |
| **inputs, | |
| max_new_tokens=100, | |
| repetition_penalty=3.0, | |
| do_sample=False | |
| ) | |
| print(tokenizer.decode(output[0], skip_special_tokens=True)) | |
| # β "The official language is Portuguese, used in national and international contexts." | |
| ``` | |
| > **Note:** A repetition penalty of 3.0 (window 128 tokens) is strongly recommended β it is required to suppress repetition loops at this model scale. | |
| --- | |
| ## Limitations | |
| - Hallucinates facts for questions outside training data coverage (e.g., precise dates, counts) | |
| - Struggles with exact numerical facts | |
| - 95M parameter size caps final PPL around 20β22 without architectural scaling | |
| - Context window limited to 512 tokens | |
| --- | |
| ## Key Engineering Decisions | |
| **Why RoPE?** Superior relative position awareness over learned absolute embeddings; no position table to overfit. Same choice as LLaMA, Mistral, and Gemma. | |
| **Why SwiGLU?** Gated linear unit consistently outperforms GELU in practice; requires 3 linear layers (w1, w2, w3). | |
| **Why LoRA over full fine-tune?** Full fine-tune destroyed base knowledge (PPL 24.40 β 35+) due to domain shift between long encyclopedia text and short factual QA. LoRA preserves base weights while adapting ~1.8% of parameters. | |
| **Why two-stage LoRA?** Stage 1 (R128) showed widening train/val gap at Epoch 7. Merging and restarting with lower rank (R64) gave a fresh second stage without continued overfitting. | |
| --- | |
| ## Citation | |
| If you use this model or find this work helpful, please cite: | |
| ```bibtex | |
| @misc{scratchlm95m, | |
| author = {Debarun Das}, | |
| title = {ScratchLM-95M: A 95M Parameter Language Model Built From Scratch}, | |
| year = {2025}, | |
| publisher = {HuggingFace}, | |
| url = {https://huggingface.co/Debarun12/ScratchLM-95M} | |
| } | |
| ``` | |
| --- | |
| ## Author | |
| **Debarun Das** | |
| - GitHub: [github.com/Debarun12](https://github.com/Debarun12) | |
| - HuggingFace: [huggingface.co/Debarun12](https://huggingface.co/Debarun12) |