Q-TensorFormer / experiments /run_baseline.py
Premchandyadav369
Transform Q-TensorFormer into an Information-Value Adaptive Resource Allocation Architecture
eaeea8f
Raw History Blame Contribute Delete
4.16 kB
"""
Experiment Runner: Baselines Comparison.
Compares:
- Dense Baseline Transformer
- Static TT-compressed Transformer (fixed rank 4)
- Quantized Baseline (INT8 / INT4 simulation)
- Dynamic Depth (Layer skipping)
- Adaptive Q-TensorFormer
"""
import sys
import os
import time
import math
import json
import argparse
from pathlib import Path
# Add project root
sys.path.insert(0, str(Path(__file__).parent.parent))
import torch
from src.config import ModelConfig
from src.models import QTensorFormer, DenseBaseline
from src.data import load_synthetic_data, load_wikitext2
from src.hardware_cost_model import HardwareCostModel
def evaluate_ppl(model, data_loader, device="cpu", max_batches=20):
model.eval()
model.to(device)
total_loss, total_tokens = 0.0, 0
with torch.no_grad():
for i, (inp, tgt) in enumerate(data_loader):
if i >= max_batches:
break
inp, tgt = inp.to(device), tgt.to(device)
logits = model(inp)
loss = torch.nn.functional.cross_entropy(
logits.reshape(-1, logits.size(-1)),
tgt.reshape(-1),
ignore_index=0,
reduction="sum",
)
total_loss += loss.item()
total_tokens += inp.numel()
avg = total_loss / max(1, total_tokens)
return math.exp(min(avg, 20.0))
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--d-model", type=int, default=128)
parser.add_argument("--n-layers", type=int, default=2)
parser.add_argument("--vocab-size", type=int, default=1000)
parser.add_argument("--seq-len", type=int, default=32)
parser.add_argument("--device", type=str, default="cpu")
parser.add_argument("--output", type=str, default="outputs/baseline_results.json")
args = parser.parse_args()
os.makedirs(os.path.dirname(args.output) or ".", exist_ok=True)
device = torch.device(args.device)
print("=" * 65)
print("EXPERIMENT: Standardized Baseline Comparison")
print("=" * 65)
loader = load_synthetic_data(vocab_size=args.vocab_size, seq_len=args.seq_len, n_samples=500, batch_size=16)
hw = HardwareCostModel()
cfg = ModelConfig(
vocab_size=args.vocab_size,
d_model=args.d_model,
n_layers=args.n_layers,
max_seq_len=args.seq_len,
tt_rank=8,
use_quantum=True,
)
models = {
"Dense Baseline": DenseBaseline(cfg),
"Static TT (r=4)": QTensorFormer(cfg, preset="QTF_CLASSICAL_ONLY"),
"Dynamic Depth": QTensorFormer(cfg, preset="QTF_LATENCY"),
"Q-TensorFormer (Full)": QTensorFormer(cfg, preset="QTF_FULL"),
"Q-TensorFormer (Balanced)": QTensorFormer(cfg, preset="QTF_BALANCED"),
}
results = []
for name, model in models.items():
if name == "Static TT (r=4)":
for b in model.blocks:
b.set_rank(4)
model.to(device)
total_p = model.total_params
meas = hw.profile_execution(model, batch_size=1, seq_len=args.seq_len, n_repeats=5, device=device)
ppl = evaluate_ppl(model, loader, device=device, max_batches=10)
record = {
"model": name,
"params": total_p,
"latency_p50_ms": meas.latency_ms,
"ttft_ms": meas.ttft_ms,
"tpot_ms": meas.tpot_ms,
"throughput_tokens_sec": meas.throughput_tokens_sec,
"traffic_bytes_per_token": meas.memory_traffic_bytes_per_token,
"peak_memory_mb": meas.peak_memory_mb,
"joules_per_token": meas.joules_per_token,
"energy_level": meas.energy_level,
"perplexity": round(ppl, 2),
"classification": "MEASURED",
"hardware": meas.device_name,
}
results.append(record)
print(f"{name:<26} | Params: {total_p:>8,} | Lat: {meas.latency_ms:>6.2f}ms | J/tok: {meas.joules_per_token*1e6:>6.2f}uJ | PPL: {ppl:>6.2f}")
with open(args.output, "w") as f:
json.dump(results, f, indent=2)
print(f"\nResults saved to {args.output}")
if __name__ == "__main__":
main()