45.4% parameter reduction Β· 45.4% storage reduction Β· +14.7% throughput
All experiments on a single RTX 4050 Laptop GPU (6 GB VRAM) Β· ~90β100 min end-to-end
Amrita Vishwa Vidyapeetham Β· Department of AI & Data Science Β· Team D11
| Member | Roll No. | |
|---|---|---|
| Hemanth SN | CB.SC.U4AIE24321 | cb.sc.u4aie24321@cb.students.amrita.edu |
| Mahakisore M | CB.SC.U4AIE24333 | cb.sc.u4aie24333@cb.students.amrita.edu |
| Yashwanth B | CB.SC.U4AIE24360 | cb.sc.u4aie24360@cb.students.amrita.edu |
This project replicates and extends Krony-PT (arXiv:2412.12351), compressing GPT-2 Small (124M parameters) by replacing its Feed-Forward Network (FFN) weight matrices with Kronecker Product Decompositions.
Instead of storing a full weight matrix
where
What we built on top of the paper:
- β Full 6-phase experiment pipeline on WikiText-2 (baseline β compress β normalize β analyze β fine-tune β rank-extend)
- β
Rank-K Kronecker:
$W \approx \sum_{r=1}^K A_r \otimes B_r$ with sweep over ranks 1, 2, 4, 8 - β
Triple-factor Kronecker (
$W \approx A \otimes B \otimes C$ ) extreme compression - β Detailed layer sensitivity analysis β logit difference + perplexity, isolated and cumulative
- β Partial compression experiments (first-6 vs last-6 layers) with fine-tuning
- β Sparse Residual Correction β our novel extension, 47% Frobenius error reduction over the paper
- β DistilGPT-2 benchmarking to situate our results against knowledge distillation
| Metric | Baseline GPT-2 | Rank-1 Compressed | Ξ |
|---|---|---|---|
| Parameters | 124.4M | 67.9M | π» β45.4% |
| Storage | 474.75 MB | 259.19 MB | π» β45.4% |
| Throughput | 406.5 tok/s | 466.1 tok/s | π’ +14.7% |
| Latency | 10.22 ms | 11.47 ms | πΊ +12.3% |
| PPL (no fine-tune) | 59.11 | 50,011 | |
| PPL (6 layers + 5ep FT) | 59.11 | ~100 | β usable range |
Parameter Reduction: 45.4% (124M β 67.9M)
Storage Reduction: 45.4% (474 MB β 259 MB)
Throughput Gain: +14.7% (406 β 466 tok/s)
Latency Overhead: +12.3% (10.2 ms β 11.5 ms)
PPL after partial FT: ~100 (first-6 layers, 5 epochs)
Perplexity without fine-tuning is high by design β Kronecker-factorized weights are a mathematical approximation requiring adaptation. After partial compression + 5 epochs of WikiText-2 fine-tuning, PPL reaches ~100, approaching DistilGPT-2 territory on our compute budget.
GPT-2 Small is a 12-layer decoder-only transformer (768 hidden dim, 12 attention heads). Its parameter budget:
| Component | Shape | Parameters | Share |
|---|---|---|---|
| Token Embedding (wte) | 50,257 Γ 768 | 38,597,376 | 31.0% |
| Position Embedding (wpe) | 1,024 Γ 768 | 786,432 | 0.6% |
| Self-Attention Γ 12 | c_attn + c_proj | 28,311,552 | 22.8% |
| FFN / MLP Γ 12 β compressed | c_fc + c_proj | 56,623,104 | 45.5% |
| LayerNorms + biases | β | ~37,000 | ~0% |
| Total | 124,439,808 | 100% |
Why target only the FFN? The MLP block holds 45.5% of all parameters β the single largest compressible component. Each FFN block transforms:
c_fc : 768 β 3072 (expand by 4Γ)
c_proj : 3072 β 768 (project back)
Compressing both in all 12 layers eliminates 56.6M parameters, reducing the model from 124M to 67.9M.
β οΈ GPT-2 Conv1D quirk: GPT-2 usesConv1Dwhich stores weights as(in_dim, out_dim)β transposed relative to standardnn.Linear. The forward pass requires a permute-based matmul strategy to handle this correctly.
Given
The key insight: rearrange
def kronecker_rank1(W, m1, m2, n1, n2):
# Van Loan rearrangement via block-permutation
W_r = W.reshape(m1, m2, n1, n2).permute(0, 2, 1, 3).reshape(m1*n1, m2*n2)
U, S, Vh = torch.linalg.svd(W_r, full_matrices=False)
A = (U[:, 0] * S[0].sqrt()).reshape(m1, n1)
B = (Vh[0, :] * S[0].sqrt()).reshape(m2, n2)
return A, B
def kronecker_rank_r(W, m1, m2, n1, n2, rank):
W_r = W.reshape(m1, m2, n1, n2).permute(0, 2, 1, 3).reshape(m1*n1, m2*n2)
U, S, Vh = torch.linalg.svd(W_r, full_matrices=False)
A_list, B_list = [], []
for r in range(rank):
A_list.append((U[:, r] * S[r].sqrt()).reshape(m1, n1))
B_list.append((Vh[r, :] * S[r].sqrt()).reshape(m2, n2))
return A_list, B_list| Layer | Original Shape | A shape | B shape | Params: before β after | ||
|---|---|---|---|---|---|---|
c_fc |
3072 Γ 768 | 48, 64 | 12, 64 | (48, 12) | (64, 64) | 2,359,296 β 4,672 |
c_proj |
768 Γ 3072 | 12, 64 | 48, 64 | (12, 48) | (64, 64) | 2,359,296 β 4,672 |
Each layer pair goes from 4.7M parameters to just 9,344 β a 252Γ reduction per layer.
class KronLinear(nn.Module):
"""Drop-in replacement for a GPT-2 Conv1D layer using sum-of-Kronecker-products."""
def __init__(self, A_list, B_list, bias):
super().__init__()
self.A_list = nn.ParameterList([nn.Parameter(A) for A in A_list])
self.B_list = nn.ParameterList([nn.Parameter(B) for B in B_list])
self.bias = nn.Parameter(bias.clone())
def forward(self, x):
out = 0
for A, B in zip(self.A_list, self.B_list):
W = torch.kron(A, B) # Reconstruct weight on the fly
out += torch.matmul(x, W.t()) # Apply linear transform
return out + self.biasdef compress_layer(model, layer_idx, rank=1):
block = model.transformer.h[layer_idx]
# c_fc: 768β3072 (Conv1D stores as (768,3072) β transpose first)
W_fc = block.mlp.c_fc.weight.data.T # β (3072, 768)
A, B = kronecker_rank_r(W_fc, 48, 64, 12, 64, rank)
block.mlp.c_fc = KronLinear(A, B, block.mlp.c_fc.bias.data)
# c_proj: 3072β768 (Conv1D stores as (3072,768) β correct as-is)
W_proj = block.mlp.c_proj.weight.data # (3072, 768)
A, B = kronecker_rank_r(W_proj, 12, 64, 48, 64, rank)
block.mlp.c_proj = KronLinear(A, B, block.mlp.c_proj.bias.data)| Item | Detail |
|---|---|
| Model | GPT-2 Small (gpt2, HuggingFace Transformers 4.57.6) |
| Dataset | WikiText-2 (wikitext-2-raw-v1) |
| Eval | ~500 batches Β· batch_size=16 Β· seq_len=128 |
| Train | 2,000 samples, AdamW (lr=3e-5), AMP mixed precision |
| GPU | NVIDIA RTX 4050 Laptop GPU Β· 6 GB VRAM |
| OS | Windows Β· Miniconda Β· Python 3.x Β· PyTorch |
Load GPT-2 Small and record all reference metrics on WikiText-2 before any modification.
Baseline PPL (WikiText-2): ~59β60
Parameters: 124,439,808
Disk Size: 474.75 MB
Inference Latency: 10.22 ms / batch
Throughput: 406.5 tok/s
Replace c_fc and c_proj in all 12 transformer blocks with KronLinear.
| Metric | Baseline | Rank-1 Compressed | Change |
|---|---|---|---|
| Parameters | 124.4M | 67.9M | β45.4% |
| Disk Size | 474.75 MB | 259.19 MB | β45.4% |
| Latency | 10.22 ms | 11.47 ms | +12.3% |
| Throughput | 406.5 tok/s | 466.1 tok/s | +14.7% |
| PPL (no FT) | 59.11 | 50,011 |
After Kronecker decomposition, the scale of
This is a zero-cost post-processing step β no additional parameters, no training β and consistently improves pre-fine-tuning PPL across all compressed layers.
For each of the 12 transformer layers, compress only that layer (Rank-1, all others remain full precision), then measure:
Relative logit difference vs baseline: $$\mathrm{diff} = \frac{|f_{\text{baseline}}(x) - f_{\text{compressed}}(x)|2}{|f{\text{baseline}}(x)|_2}$$
Perplexity on WikiText-2.
| Layer | Logit Diff | PPL (isolated Rank-1) | Sensitivity |
|---|---|---|---|
| 0 | 0.3034 | 4,825 | π΄ Uniquely sensitive |
| 1 | 0.028 | 62 | π’ Very stable |
| 2β9 | 0.04β0.07 | 62β68 | π’ Stable |
| 10 | 0.2208 | 67 | π‘ Elevated |
| 11 | 0.1573 | 68 | π‘ Elevated |
Layer 0 is uniquely sensitive β it is the first feature transformation after embeddings and carries irreplaceable representational structure. All other layers (1β9) in isolation cause negligible degradation (~2β5 PPL increase). This finding has a direct practical consequence: skipping Layer 0 during compression is a strong heuristic for quality-preserving deployment.
Fig 6. WikiText-2 perplexity heatmap β Layer 0 extreme outlier clearly visible (yellow = high PPL)
Compressing layers 0 through
| Layers Compressed | Logit Diff | PPL |
|---|---|---|
| 1 | ~0.003 | ~62 |
| 4 | ~0.65 | ~8,700 |
| 8 | ~0.72 | ~15,600 |
| 12 (all) | 0.849 | 43,022 |
Kronecker factors from SVD are the best rank-1 approximation to
Config: AdamW (lr=3e-5) Β· mixed precision (AMP) Β· 2,000 WikiText-2 training samples
| Epoch | Avg Loss |
|---|---|
| 1 | 4.70 |
| 2 | 4.28 |
| 3 | 3.93 |
| 4 | 3.62 |
| 5 | 3.31 |
Post-training PPL (all 12 layers, 5ep): 266.6
Compressing only 6 of 12 layers preserves model quality much better β and with 5 epochs of fine-tuning, PPL reaches ~100:
| Model | Params | PPL After Fine-tune |
|---|---|---|
| Original GPT-2 | 124M | 60.27 |
| 12-layer Kronecker + 2ep | 67.9M | 266.6 |
| First-6 layers + 5ep | ~96M | 99.9 β |
| Last-6 layers + 5ep | ~96M | 103.2 β |
| DistilGPT-2 (reference) | 82M | 88.97 |
Captures the top-2 singular value pairs of
| Method | Params | PPL (no FT) | Compression |
|---|---|---|---|
| Baseline GPT-2 | 124M | 60.27 | β |
| Rank-1 Kronecker | 67.9M | 43,022 | 45.4% |
| Rank-2 Kronecker | ~80M | 21,978 | ~35% |
| DistilGPT-2 | 82M | 88.97 | 34% |
| KronyPT-81M (paper) | 81M | 35.75 | 35% |
Rank-2 is 2Γ better as a weight initialization before any fine-tuning β directly confirming Table II of the Krony-PT paper. Each additional rank pair recovers a progressively smaller fraction of the singular value energy, so returns diminish quickly.
Fig 11. Complete Rank-1 vs Rank-2 comparison β PPL before/after FT, parameter count, storage, latency
The supplementary notebook (Extras_Plots.ipynb) runs a complete comparison across two-factor (AxB) and three-factor (AxBxC) Kronecker over ranks 1, 2, 4, 8 on the full WikiText-2 pipeline.
Fig 12. All Kronecker variants achieve the same ~45.4% reduction β differences are purely in quality
| Model | PPL (before FT) |
|---|---|
| Baseline GPT-2 | 60.27 |
| AxB Rank-1 | ~46,162 |
| AxB Rank-2 | ~47,800 |
| AxB Rank-4 | ~43,088 |
| AxBxC | ~5Γ10β· (random init) |
| Metric | AxB (Rank-1) | AxBxC |
|---|---|---|
| Loss (Epoch 1) | 7.95 | 13.82 |
| Loss (Epoch 5) | 6.52 | 8.35 |
| PPL after FT | 1,059 | 3,875 |
| Training time | 529.9s | 552.4s |
Fig 19. Pareto frontier β AxB post-FT variants dominate AxBxC in the parameterβquality tradeoff space
Fig 20. Kronecker compression vs distillation β complete GPT-2 family across training configurations
The rearranged matrix
| Rank | Relative Reconstruction Error |
|---|---|
| 1 | highest |
| 2 | moderate |
| 4 | low |
| 8 | very low |
| Method | Params per layer | Notes |
|---|---|---|
| Original |
2,359,296 | β |
|
|
4,672 | SVD-initialized |
| ~400 | Random B, C β needs heavy FT |
Triple Kronecker achieves ~5,890Γ per-layer parameter reduction at the cost of entirely random initialization for factors B and C.
We proposed and implemented a Sparse Residual Correction not present in the original Krony-PT paper:
where
| Method | Frobenius Error | vs. Paper Method |
|---|---|---|
| Pruning (identity baseline) | 136.62 | β |
| Van Loan SVD + Ξ± (paper method) | 9.1492 | β |
| Our method (SVD + Ξ± + Sparse) | 4.8922 | 47% better β |
def sparse_residual_correction(W, A, B, k_percent=10):
alpha = torch.norm(W, 'fro') / torch.norm(torch.kron(A, B), 'fro')
W_approx = alpha * torch.kron(A, B)
R = W - W_approx # Residual
threshold = torch.quantile(R.abs(), 1 - k_percent/100)
S = R * (R.abs() >= threshold) # Keep top-k% entries
return W_approx + S, alphaRun
python scripts/step2_sparse_residual.pyExpected:SUCCESS: Python proves your method wins!
| Model | Method | Params | WikiText-2 PPL |
|---|---|---|---|
| GPT-2 Small | Baseline | 124M | 59.11 |
| DistilGPT-2 | Knowledge Distillation | 82M | 88.97 |
| KronyPT-81M (paper) | Kronecker + 3ep OpenWebText (A100) | 81M | 35.75 |
| Ours: Rank-1 (no FT) | Kronecker SVD init | 67.9M | 50,011 |
| Ours: Rank-1 + 2ep | Kronecker + WikiText-2 FT | 67.9M | 266.6 |
| Ours: First-6 + 5ep | Partial Kronecker | ~96M | 99.9 |
| Ours: Last-6 + 5ep | Partial Kronecker | ~96M | 103.2 |
On the gap between our PPL (~100) and the paper's (35.75):
KronyPT-81M was trained for 3 full epochs on OpenWebText (~8 billion tokens) on an A100 GPU. Our experiments used 2,000 WikiText-2 samples on an RTX 4050 Laptop (6GB VRAM). The compression architecture is identical. The gap is purely a compute budget difference, not a methodological one.
LLM-Compression-using-Krony-PT/
β
βββ π Documentation/ β Exported PDFs & supporting visuals
β βββ Adaptive Normalization.pdf
β βββ Comparisons.pdf β Benchmark notebook export
β βββ DistilGPT2_Comparison.ipynb
β βββ Final-Plots.pdf β Layer sensitivity notebook export
β βββ GPT2_Kronecker_Compression_Documentation_FIXED (1).ipynb β Main notebook (copy)
β βββ Rank1_vs_Rank2_Comparison.ipynb
β βββ Untitled.pdf
β βββ distilgpt2_comparison.png
β βββ gpt2_exploded_diagram.html
β βββ rank1_vs_rank2_comparison.png
β
βββ π Jupyter/ β All experiment notebooks
β βββ Adaptive Normalization.ipynb β Phase 3: alpha rescaling
β βββ Baseline_GPT2small.ipynb β Phase 1: baseline eval
β βββ Comparisons.ipynb β Parameter / latency / size benchmarks
β βββ Extras_Plots.ipynb β AxB vs AxBxC Β· Rank-R sweep β
β βββ Final-Plots.ipynb β Layer sensitivity plots
β βββ GPT2_Kronecker_Compression_Documentation_FIXED (1).ipynb β Main 6-phase notebook β
β βββ Isolated vs Cumulative Compression.ipynb
β βββ Logit_Score_Calculation_Layer_by-layer.ipynb
β βββ Pre_Training.ipynb β Fine-tuning recovery β
β βββ Rank-2_Compression.ipynb β Phase 6: Rank-2 extension
β βββ Rank1_vs_Rank2_Comparison.ipynb β Rank-1 vs Rank-2 dashboard β
β βββ Retraining Loss.ipynb
β βββ Singular Value Check and A(kron)B(kron)C.ipynb β Triple Kronecker
β βββ Three_Factor_Compression.ipynb
β βββ ... β Additional exploration notebooks
β
βββ π Matlab/ β MATLAB replication & sparse residual
β βββ Basic_Krony_PT.mlx
β βββ Final.mlx
β βββ Krony_PT_Alpha_and_Prunning.mlx β Alpha normalization + pruning baseline
β βββ Krony_PT_Replication.mlx β Full Van Loan replication
β βββ Sparse_Matrix_Method.mlx β Sparse residual verification β
β
βββ π Python/
β βββ π New/ β Current working scripts
β β βββ step2_sparse_residual.py β Sparse Residual 47% improvement demo β
β β βββ compression_agent.py
β β βββ chat_with_gpt2.py
β β βββ test_step1_rearrangement.py β Van Loan math unit test
β βββ π Old/ β Archived earlier versions
β βββ π Visualizations/ β Manim & matplotlib animation scripts
β βββ gpt2_visualization/
β βββ gpt2_research_animation/ β GPT-2 architecture animations
β
βββ π assets/ β All result plots used in this README
β βββ slide_param_inference_results.png
β βββ slide_model_size_results.png
β βββ slide_efficiency_dashboard.png
β βββ slide_layer_sensitivity_logit.png
β βββ slide_layer_heatmaps.png
β βββ slide_ppl_heatmap.png
β βββ slide_ppl_recovery.png
β βββ slide_compression_depth.png
β βββ slide_full_comparison.png
β βββ slide_rank1_vs_rank2.png
β βββ param_comparison.png
β βββ ppl_comparison.png
β βββ rank_vs_ppl.png
β βββ layerwise_sensitivity.png
β βββ cumulative_compression.png
β βββ retraining_loss.png
β βββ ppl_before_after.png
β βββ rank_vs_compression.png
β βββ time_vs_compression.png
β βββ pareto_frontier.png
β
βββ βοΈ .gitignore
βββ π Base_Paper.pdf β Krony-PT reference paper
βββ π MFC_4__Kronecker_Product_.pdf β Course project report
βββ π LICENSE
βββ π README.md
β = primary notebooks to run for reproducing reported results.
To render images on GitHub: Theassets/folder is already at the repo root β all image paths in this README referenceassets/filename.pngand will render automatically.
git clone https://github.com/mahakisore/LLM-Compression-using-Krony-PT
cd LLM-Compression-using-Krony-PTpip install torch transformers datasets einops matplotlib seaborn pandas accelerate
# Or use the included requirements file:
pip install -r Python/requirements.txtpython Python/New/step2_sparse_residual.py
# Expected: SUCCESS: Python proves your method wins!jupyter notebook "Jupyter/GPT2_Kronecker_Compression_Documentation_FIXED (1).ipynb"jupyter notebook Jupyter/Baseline_GPT2small.ipynb # Phase 1: baseline eval
jupyter notebook Jupyter/Comparisons.ipynb # Compression benchmarks
jupyter notebook Jupyter/Pre_Training.ipynb # Fine-tuning recovery
jupyter notebook Jupyter/Rank1_vs_Rank2_Comparison.ipynb # Rank-1 vs Rank-2
jupyter notebook Jupyter/Extras_Plots.ipynb # AxB vs AxBxC full sweep
jupyter notebook "Jupyter/Isolated vs Cumulative Compression.ipynb" # Sensitivity
jupyter notebook "Jupyter/Singular Value Check and A(kron)B(kron)C.ipynb" # Triple Kronecker| Experiment | Notebook | Time |
|---|---|---|
| Baseline PPL eval (~500 batches, WikiText-2) | Baseline_GPT2small.ipynb |
~2 min |
| Rank-1 compression all 12 layers (SVD only) | Comparisons.ipynb |
~15 sec |
| Forward pass latency benchmark (50 runs) | Comparisons.ipynb |
~30 sec |
| Fine-tuning 12-layer model (2ep, 2000 samples) | Pre_Training.ipynb |
~8 min |
| Fine-tuning 6-layer model (5ep, 2000 samples) | Pre_Training.ipynb |
~10 min |
| Layer sensitivity (isolated, 12 models Γ eval) | Final-Plots.ipynb |
~25 min |
| Cumulative sensitivity (13 models Γ eval) | Isolated vs Cumulative Compression.ipynb |
~30 min |
| AxB vs AxBxC rank sweep | Extras_Plots.ipynb |
~20 min |
| Total end-to-end | ~90β100 min |
Tip for reproducibility: Use
%%timeat the top of Jupyter cells, or wrap blocks withimport time; t = time.time(); ...; print(f"{time.time()-t:.1f}s")to log exact timings.
-
45.4% parameter and storage reduction is achieved by replacing all 12 FFN blocks with Rank-1 Kronecker factors β zero changes to attention, embeddings, or layer norms.
-
Throughput improves (+14.7%) despite slight latency overhead (+12.3%), because smaller weight matrices improve GPU memory bandwidth utilization during inference.
-
Perplexity is fully recoverable through fine-tuning. Partial compression (6 of 12 layers) with 5 epochs on WikiText-2 reaches PPL ~100, approaching DistilGPT-2 quality on a fraction of the compute budget.
-
Layer 0 is uniquely sensitive (isolated PPL 4,825 vs 62β68 for all others). Skipping it during compression is a practical heuristic confirmed experimentally.
-
Rank-2 provides 2Γ better pre-FT initialization than Rank-1, with ~18% more parameters β directly validating Table II of the Krony-PT paper.
-
Triple Kronecker (AxBxC) achieves extreme per-layer compression (~400 params vs 2.36M) but is entirely dependent on fine-tuning due to random B, C initialization.
-
Our Sparse Residual Correction reduces Frobenius reconstruction error by 47% over the Van Loan baseline β a novel contribution beyond the paper, verified in MATLAB and Python.
-
The gap to the paper's PPL (35.75 vs ~100) is entirely due to training compute: 8B tokens on an A100 vs 2,000 samples on an RTX 4050. The architecture, decomposition, and training setup are otherwise equivalent.
-
Ayad, M. A. B., MitroviΔ, J., & Granitzer, M. (2025). KronyPT: GPT-2 Compressed with Kronecker Products. FLLM 2025, IEEE. [arXiv:2412.12351]
-
Van Loan, C. F., & Pitsianis, N. (1993). Approximation with Kronecker Products. In Linear Algebra for Large Scale and Real-Time Applications. Springer Netherlands, pp. 293β314.
-
Radford, A., Wu, J., Child, R., Luan, D., Amodei, D., & Sutskever, I. (2019). Language Models are Unsupervised Multitask Learners. OpenAI Blog.
-
Sanh, V., Debut, L., Chaumond, J., & Wolf, T. (2019). DistilBERT, a distilled version of BERT: smaller, faster, cheaper and lighter. [arXiv:1910.01108]
-
Alammar, J. The Illustrated Transformer. https://jalammar.github.io/illustrated-transformer/
-
3Blue1Brown β Neural Networks YouTube series.
Amrita Vishwa Vidyapeetham Β· 22MAT230 β Mathematics for Computing 4 Β· Semester 4 Β· Team D11
Hemanth SN Β Β·Β Mahakisore M Β Β·Β Yashwanth B















