|
| 1 | +# Pre-Process (Rotation Preprocessing) |
| 2 | + |
| 3 | +Rotation preprocessing applies SpinQuant/OstQuant-style rotation matrices to model weights |
| 4 | +before quantization, reducing quantization error. This is particularly effective for |
| 5 | +low-bit quantization (e.g., 3-bit). |
| 6 | + |
| 7 | +## Overview |
| 8 | + |
| 9 | +The rotation preprocessing pipeline: |
| 10 | + |
| 11 | +1. **Trains** rotation/scaling matrices using calibration data with an RTN quantization proxy |
| 12 | +2. **Absorbs** the learned matrices into model weights (fuses LayerNorms, rotates projections) |
| 13 | +3. **Registers** online Hadamard hooks on `down_proj` layers for inference correctness |
| 14 | +4. **Saves** the rotated model as a standard Hugging Face model directory |
| 15 | + |
| 16 | +The saved model can then be quantized with any quantizer (GPTQ, RTN, etc.) using the |
| 17 | +standard `Runner` pipeline. |
| 18 | + |
| 19 | +## Quick Start |
| 20 | + |
| 21 | +```python |
| 22 | +from onecomp import ModelConfig, Runner, GPTQ, prepare_rotated_model, setup_logger |
| 23 | + |
| 24 | +setup_logger() |
| 25 | + |
| 26 | +# Step 1: Rotation preprocessing |
| 27 | +model_config = ModelConfig(model_id="meta-llama/Llama-2-7b-hf", device="cuda:0") |
| 28 | + |
| 29 | +rotated_config = prepare_rotated_model( |
| 30 | + model_config=model_config, |
| 31 | + save_directory="./rotated_model", |
| 32 | + wbits=4, |
| 33 | + groupsize=128, |
| 34 | +) |
| 35 | + |
| 36 | +# Step 2: Quantize (wbits/groupsize/sym must match Step 1) |
| 37 | +gptq = GPTQ(wbits=4, groupsize=128) |
| 38 | +runner = Runner(model_config=rotated_config, quantizer=gptq) |
| 39 | +runner.run() |
| 40 | +``` |
| 41 | + |
| 42 | +## Supported Architectures |
| 43 | + |
| 44 | +| Architecture | Status | |
| 45 | +|-------------|--------| |
| 46 | +| Llama | Supported | |
| 47 | +| Qwen3 | Supported | |
| 48 | + |
| 49 | +## Key Parameters |
| 50 | + |
| 51 | +| Parameter | Description | Default | |
| 52 | +|-----------|-------------|---------| |
| 53 | +| `rotation` | Apply rotation matrices (R1, R2) | `True` | |
| 54 | +| `scaling` | Apply scaling diagonals (S_*) | `False` | |
| 55 | +| `enable_training` | Train rotation matrices (vs. random init) | `True` | |
| 56 | +| `wbits` | RTN proxy bit-width (must match quantizer) | `4` | |
| 57 | +| `groupsize` | RTN proxy group size (must match quantizer) | `-1` | |
| 58 | +| `sym` | RTN proxy symmetric quantization | `False` | |
| 59 | +| `fp32_had` | Use FP32 for online Hadamard transform | `False` | |
| 60 | +| `seed` | Seed for rotation init and calibration data | `0` | |
| 61 | + |
| 62 | +!!! warning "Parameter matching" |
| 63 | + The `wbits`, `groupsize`, and `sym` parameters **must match** the quantizer |
| 64 | + used in Step 2. Mismatched values will degrade quantization quality because |
| 65 | + the rotation matrices were optimized for different quantization settings. |
| 66 | + |
| 67 | +## Save and Load |
| 68 | + |
| 69 | +Rotation-preprocessed quantized models support the standard save/load API: |
| 70 | + |
| 71 | +```python |
| 72 | +# Save |
| 73 | +runner.save_quantized_model("./quantized_model") |
| 74 | + |
| 75 | +# Load (Hadamard hooks are auto-registered) |
| 76 | +from onecomp import load_quantized_model |
| 77 | +model, tokenizer = load_quantized_model("./quantized_model") |
| 78 | +``` |
| 79 | + |
| 80 | +The saved `config.json` includes `"rotated": true` and `"fp32_had": false`, |
| 81 | +which `load_quantized_model()` uses to automatically register the required |
| 82 | +Hadamard hooks on `down_proj` layers. |
| 83 | + |
| 84 | +## Limitations |
| 85 | + |
| 86 | +- **vLLM inference is not supported.** vLLM kernels do not apply the online Hadamard |
| 87 | + transform required by rotation-preprocessed models. |
| 88 | +- Only Llama and Qwen3 architectures are currently supported. |
| 89 | + |
| 90 | +## API Reference |
| 91 | + |
| 92 | +See [Pre-Process API](../api/pre_process.md) for full parameter documentation. |
0 commit comments