CoolFace
Modelpublic

OpenTransformer/binary-transformers

sourceHugging Facemitupdated 8mo agoView on Hugging Face
1likes
bit_trainer.py200 linesDownload Raw Back to root
1#!/usr/bin/env python32"""3BIT-LEVEL TRANSFORMER - The Ultimate Zero-Overhead Model4Vocab = 2 (just 0 and 1)5No tokenization. No bytes. Pure binary.6 7Each byte becomes 8 tokens (bits).8Model learns ALL structure from raw bits.9"""10 11import sys12import math13import time14import torch15import torch.nn as nn16import torch.nn.functional as F17from collections import deque18 19DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")20torch.backends.cuda.matmul.allow_tf32 = True21 22# BIT-LEVEL CONFIG - ABSOLUTE UNIT23CONFIG = {24    "d": 768,        # GPT-2 small size25    "layers": 12,    # DEEP for bit pattern learning26    "heads": 12,27    "vocab": 2,      # JUST 0 AND 1!28    "ctx": 4096,     # 512 bytes of context29}30 31LR = 3e-4           # learning rate32UPDATE_EVERY = 2048  # bits between updates (256 bytes worth) - BIGGER BATCHES33PRINT_EVERY = 100000   # bits34 35class BitAttention(nn.Module):36    def __init__(self, d, h):37        super().__init__()38        self.h, self.dk = h, d // h39        self.qkv = nn.Linear(d, 3 * d, bias=False)40        self.proj = nn.Linear(d, d, bias=False)41        42    def forward(self, x, mask=None):43        B, N, D = x.shape44        qkv = self.qkv(x).view(B, N, 3, self.h, self.dk).permute(2, 0, 3, 1, 4)45        q, k, v = qkv[0], qkv[1], qkv[2]46        att = (q @ k.transpose(-1, -2)) / math.sqrt(self.dk)47        if mask is not None:48            att = att + mask49        return self.proj((F.softmax(att, -1) @ v).transpose(1, 2).reshape(B, N, D))50 51class BitBlock(nn.Module):52    def __init__(self, d, h):53        super().__init__()54        self.ln1, self.ln2 = nn.LayerNorm(d), nn.LayerNorm(d)55        self.attn = BitAttention(d, h)56        self.ff = nn.Sequential(nn.Linear(d, 4*d), nn.GELU(), nn.Linear(4*d, d))57        58    def forward(self, x, mask):59        x = x + self.attn(self.ln1(x), mask)60        return x + self.ff(self.ln2(x))61 62class BitTransformer(nn.Module):63    """Transformer with vocab=2 (just 0 and 1)"""64    def __init__(self, cfg):65        super().__init__()66        d, L, h = cfg["d"], cfg["layers"], cfg["heads"]67        self.emb = nn.Embedding(2, d)  # ONLY 2 EMBEDDINGS!68        self.blocks = nn.ModuleList([BitBlock(d, h) for _ in range(L)])69        self.ln = nn.LayerNorm(d)70        self.head = nn.Linear(d, 2, bias=False)  # predict 0 or 171        72    def forward(self, x):73        B, N = x.shape74        mask = torch.triu(torch.ones(N, N, device=x.device), 1) * -1e975        h = self.emb(x)76        for block in self.blocks:77            h = block(h, mask)78        return self.head(self.ln(h))79    80    def count_params(self):81        return sum(p.numel() for p in self.parameters())82 83def byte_to_bits(byte_val):84    """Convert byte to 8 bits (MSB first)"""85    return [(byte_val >> (7 - i)) & 1 for i in range(8)]86 87def bits_to_byte(bits):88    """Convert 8 bits back to byte"""89    val = 090    for i, b in enumerate(bits[:8]):91        val |= (b << (7 - i))92    return val93 94class BitTrainer:95    def __init__(self, model, lr=LR):96        self.model = model.to(DEVICE)97        self.opt = torch.optim.AdamW(model.parameters(), lr=lr)98        self.ctx_size = CONFIG["ctx"]99        self.buffer = deque(maxlen=self.ctx_size + 1)100        101        self.bits_seen = 0102        self.bytes_seen = 0103        self.total_loss = 0.0104        self.updates = 0105        self.start_time = time.time()106        107    def ingest_byte(self, byte_val):108        """Convert byte to 8 bits and absorb"""109        bits = byte_to_bits(byte_val)110        for bit in bits:111            self.buffer.append(bit)112            self.bits_seen += 1113            114            if len(self.buffer) >= UPDATE_EVERY + 1 and self.bits_seen % UPDATE_EVERY == 0:115                self._update()116        117        self.bytes_seen += 1118        119        if self.bits_seen % PRINT_EVERY == 0:120            self._print_stats()121            122        if self.bytes_seen % 500000 == 0 and self.bytes_seen > 0:123            self._save()124    125    def _update(self):126        bits = list(self.buffer)127        x = torch.tensor(bits[:-1], device=DEVICE, dtype=torch.long).unsqueeze(0)128        y = torch.tensor(bits[1:], device=DEVICE, dtype=torch.long).unsqueeze(0)129        130        self.model.train()131        logits = self.model(x)132        loss = F.cross_entropy(133            logits[:, -UPDATE_EVERY:].reshape(-1, 2),134            y[:, -UPDATE_EVERY:].reshape(-1)135        )136        137        self.opt.zero_grad()138        loss.backward()139        torch.nn.utils.clip_grad_norm_(self.model.parameters(), 1.0)140        self.opt.step()141        142        self.total_loss += loss.item()143        self.updates += 1144    145    def _print_stats(self):146        elapsed = time.time() - self.start_time147        bits_per_sec = self.bits_seen / elapsed if elapsed > 0 else 0148        bytes_per_sec = self.bytes_seen / elapsed if elapsed > 0 else 0149        avg_loss = self.total_loss / max(1, self.updates)150        151        # For bits: random is 1.0 (coin flip), lower = learning152        # Entropy in bits per bit153        entropy = avg_loss / math.log(2)154        compression = (1.0 - entropy) * 100  # % compression vs random155        156        print(f"[{elapsed:.0f}s] {self.bytes_seen/1000:.1f}KB | {bytes_per_sec/1000:.1f} KB/s | "157              f"loss={avg_loss:.4f} | entropy={entropy:.3f} bit/bit | "158              f"compression={compression:.1f}%", flush=True)159    160    def _save(self):161        avg_loss = self.total_loss / max(1, self.updates)162        kb = self.bytes_seen // 1000163        ckpt = {164            "model": self.model.state_dict(),165            "bits": self.bits_seen,166            "bytes": self.bytes_seen,167            "loss": avg_loss,168        }169        torch.save(ckpt, f"/workspace/bit_ckpt_{kb}kb.pt")170        print(f"[SAVED] bit_ckpt_{kb}kb.pt", flush=True)171 172def main():173    print(f"BIT-LEVEL TRANSFORMER - Vocab = 2 (just 0 and 1)", flush=True)174    print(f"Config: {CONFIG}", flush=True)175    print(f"Device: {DEVICE}", flush=True)176    177    model = BitTransformer(CONFIG)178    params = model.count_params()179    print(f"Parameters: {params:,} ({params/1e6:.2f}M)", flush=True)180    print(f"Vocab: 2 (literally just 0 and 1)", flush=True)181    print(f"Each byte = 8 bit tokens", flush=True)182    183    trainer = BitTrainer(model)184    185    print(f"Listening for bytes (FAST batch mode)...", flush=True)186    187    # Read in large chunks for speed188    CHUNK_SIZE = 8192  # 8KB chunks = 65536 bits189    while True:190        chunk = sys.stdin.buffer.read(CHUNK_SIZE)191        if not chunk:192            break193        for byte in chunk:194            trainer.ingest_byte(byte)195    196    print(f"Stream ended. Total: {trainer.bytes_seen:,} bytes = {trainer.bits_seen:,} bits", flush=True)197 198if __name__ == "__main__":199    main()200