AWQ › The AWQ Algorithm

Michael BrenndoerferJanuary 14, 202612 min read
Language AI HandbookAll chapters
Part 42 of 67Inference Optimization
Chapter 321AWQ › The AWQ Algorithm
Reading section 3 of 11 · The AWQ Algorithm · 12 minSection 3 of 11 · 12 min

Book contents

Section 3 of 11 · 12 min read

AWQ › The AWQ AlgorithmOne section · Sections in this chapter3 / 11 ↓
Reading tools Definitions & inline links

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

AWQ determines optimal per-channel scaling factors by analyzing activation statistics from a small calibration dataset. Unlike GPTQ, which requires solving optimization problems involving Hessian matrices, AWQ relies on straightforward statistical measurements that can be computed efficiently in a single forward pass per calibration sample. The algorithm proceeds through four stages: activation collection, scale computation, weight transformation, and standard quantization.

Think of the overall algorithm as a three-phase engineering process. First, you diagnose the problem by measuring which channels carry the most signal. Second, you design a correction by computing scaling factors that shift quantization resolution toward those necessary channels. Third, you apply the correction by transforming the weights and absorbing the inverse transformation into the preceding layer. Each phase is simple on its own; the insight is in combining them.

Activation Statistics Collection

The first step is running a calibration set through the model and recording activation statistics. This calibration set need not be large; typically a few hundred to a few thousand examples suffice to obtain stable estimates of activation magnitudes. For general-purpose language models, any diverse text corpus gives reliable statistics. For domain-specific models, calibration data from the target domain produces better results.

For each linear layer in the model, we record the average absolute magnitude of each input channel across the calibration examples. Formally, for a layer receiving inputs xj(n)x_j^{(n)} where nn indexes the calibration sample and jj indexes the input channel:

aˉj=1N∑n=1N∣xj(n)∣\bar{a}_j = \frac{1}{N} \sum_{n=1}^{N} \left|x_j^{(n)}\right|

where:

  • aˉj\bar{a}_j: the average activation magnitude for input channel jj, serving as our proxy for channel importance during quantization
  • NN: the total number of calibration samples used to estimate statistics
  • xj(n)x_j^{(n)}: the activation value at channel jj for the nn-th calibration sample
  • ∣xj(n)∣\left|x_j^{(n)}\right|: the absolute magnitude, capturing signal strength regardless of sign (since both positive and negative activations amplify weight errors equally)

Taking the absolute value ensures we capture activation strength regardless of sign. A channel that alternates between large positive and large negative values is just as influential as one that is consistently large positive. Averaging across samples smooths out noise from individual examples and reveals the underlying pattern of which channels consistently carry strong signals across diverse inputs.

The averaging operation is important because any single input might happen to have unusual activation patterns. A question about chemistry might activate different channels than a question about sports. By averaging across many diverse examples, we obtain a stable estimate of each channel's typical importance under the model's actual usage distribution.

Computing Optimal Scaling Factors

Given activation statistics, AWQ computes per-channel scaling factors that balance two competing objectives. The first objective is to protect salient weights: channels with large activations should receive larger scaling factors, expanding the weights to occupy more of the quantization range and thus receive finer resolution. The second objective is to avoid harming other weights: extreme scaling factors can hurt non-salient weights by compressing their share of the quantization range too aggressively, potentially causing larger errors than the uniform quantization they started with.

Finding the right balance requires a formula that increases with activation magnitude but does not grow too aggressively for the highest-activation channels. If the scaling factor is proportional to the raw activation magnitude and one channel has activations ten times larger than the average, that channel would receive a scaling factor ten times larger, which could severely compress the remaining channels. AWQ addresses this by normalizing activation magnitudes and raising them to a fractional power:

sj=(aˉjmax⁡kaˉk)αs_j = \left(\frac{\bar{a}_j}{\max_k \bar{a}_k}\right)^\alpha

where:

  • sjs_j: the calculated scaling factor for input channel jj, which will multiply the weights in column jj of the weight matrix
  • aˉj\bar{a}_j: the average activation magnitude for channel jj, computed over the calibration set
  • max⁡kaˉk\max_k \bar{a}_k: the maximum average activation magnitude across all input channels kk, serving as the normalization reference
  • α\alpha: a hyperparameter in the range [0,1][0, 1] controlling scaling aggressiveness, balancing the protection of salient weights against potential distortion of others

The normalization by max⁡kaˉk\max_k \bar{a}_k ensures that scaling factors lie in the range (0,1](0, 1]. The channel with the largest average activation receives a scaling factor of exactly 1 (unchanged). Every other channel receives a scaling factor strictly less than 1, meaning their weights get compressed relative to the most important channel rather than expanded. This design ensures the overall quantization range does not grow, which would hurt all channels.

The exponent α\alpha gives a smooth tradeoff between the two objectives. When α=0\alpha = 0, the formula yields sj=1s_j = 1 for all channels, and AWQ reduces to standard quantization without any activation-aware adjustment. When α=1\alpha = 1, scaling factors are directly proportional to relative activation magnitudes. This gives maximum differentiation between channels. In practice, α\alpha values between 0.25 and 0.75 work well across different layer types, with the original AWQ paper using per-layer grid search to find optimal values.

Out[5]:
Visualization
Line plot of AWQ scaling factor versus normalized activation magnitude for four alpha values, all curves rising from near zero to 1.0.
AWQ scaling factor as a function of normalized activation magnitude for four values of the exponent alpha (0.25, 0.5, 0.75, 1.0). Higher alpha values assign lower scaling factors to non-maximal activation channels, more aggressively separating them from salient channels near 1.0. In practice, alpha values between 0.25 and 0.75 give the best balance between protecting salient weights and preserving accuracy for the majority of channels.

When α=0\alpha = 0, all scaling factors collapse to 1 (no adjustment), and AWQ reduces to standard quantization without any activation-aware optimization. When α=1\alpha = 1, scaling factors are directly proportional to relative activation magnitudes. This gives maximum differentiation between channels. In practice, α\alpha values between 0.25 and 0.75 work well, with the original AWQ paper using grid search to find optimal values per layer.

The shape of these curves is significant. For low values of alpha, the curve is relatively flat, meaning even channels with quite low activation magnitudes receive nearly the same scaling as high-activation channels. This is a conservative setting that avoids hurting any channel but gives weaker protection for the salient ones. For higher alpha values, the curve bends more sharply, putting higher scaling factors on channels that truly dominate in activation magnitude while sharply reducing protection for mediocre channels.

Weight Transformation and Quantization

With scaling factors computed, AWQ transforms the weights before applying standard quantization. The transformation is straightforward: for each input channel jj, the corresponding column of the weight matrix is multiplied by the scaling factor sjs_j:

w~ij=wij⋅sj\tilde{w}_{ij} = w_{ij} \cdot s_j

where:

  • w~ij\tilde{w}_{ij}: the transformed (scaled) weight that will be fed into the quantization process
  • wijw_{ij}: the original weight parameter from the pretrained model
  • sjs_j: the scaling factor for channel jj, expanding the weight's magnitude to utilize more of the quantization range

This multiplication stretches the weights for high-activation channels (those with sjs_j close to 1) while compressing those for low-activation channels (those with small sjs_j). The resulting weight distribution concentrates the most important weights in a larger portion of the quantization range, where they benefit from finer resolution.

After applying channel scaling, AWQ applies standard group-wise INT4 quantization to the scaled weights. Within each quantization group (typically spanning 128 consecutive weights), the quantizer determines the scale sqs_q and zero point zz that minimize quantization error for the group:

w^ij=round(w~ijsq−z)\hat{w}_{ij} = \text{round}\left(\frac{\tilde{w}_{ij}}{s_q} - z\right)

where:

  • w^ij\hat{w}_{ij}: the integer-quantized weight stored in the 4-bit representation
  • w~ij\tilde{w}_{ij}: the scaled weight being quantized
  • sqs_q: the quantization scale for the weight group, mapping from real values to integers
  • zz: the zero point for asymmetric quantization, letting the integer grid to stand for asymmetric value ranges
  • round(⋅)\text{round}(\cdot): rounding to the nearest integer, which introduces quantization error

The rounding operation is where information is lost, as continuous values are mapped to the nearest point on a discrete grid with only 24=162^4 = 16 representable levels. However, because salient weights have been scaled up relative to the group range, they now occupy proportionally more of those 16 levels and thus suffer less relative error.

During inference, weights are dequantized on-the-fly before use:

w~ijdequant=(w^ij+z)⋅sq\tilde{w}^{\text{dequant}}_{ij} = (\hat{w}_{ij} + z) \cdot s_q

The inverse channel scaling then recovers the effective weight in the original computation space:

wijeff=w~ijdequantsjw^{\text{eff}}_{ij} = \frac{\tilde{w}^{\text{dequant}}_{ij}}{s_j}

The effective quantization error for the original weight is therefore:

Errorij=∣wij−wijeff∣≈Δqsj\text{Error}_{ij} = \left|w_{ij} - w^{\text{eff}}_{ij}\right| \approx \frac{\Delta_q}{s_j}

where:

  • Errorij\text{Error}_{ij}: the effective quantization error in the original, unscaled weight space
  • Δq\Delta_q: the quantization step size for the group (approximately sqs_q), representing the minimum distinguishable difference in weight values
  • sjs_j: the channel scaling factor; larger values reduce the effective error for that channel proportionally

For salient channels where sjs_j is large (close to 1 after normalization by the maximum), the effective error is the base quantization step. For non-salient channels where sjs_j is small, the error is larger, but these errors are multiplied by small activation values during inference and therefore have less impact on the output. The output error for element yiy_i from channel jj is approximately Errorij⋅∣xj∣\text{Error}_{ij} \cdot |x_j|, which equals approximately (Δq/sj)⋅∣xj∣(\Delta_q / s_j) \cdot |x_j|.

The key insight of AWQ is now visible in the math. If sjs_j is designed to be proportional to aˉj\bar{a}_j, then the output error contribution becomes approximately Δq⋅∣aˉj∣/sj≈Δq⋅const\Delta_q \cdot |\bar{a}_j| / s_j \approx \Delta_q \cdot \text{const}. AWQ redistributes quantization precision so that every channel contributes roughly equally to the total output error, rather than high-activation channels dominating the error.

Out[6]:
Visualization
Grouped bar chart showing weighted quantization error for salient and non-salient channels under RTN and AWQ, with RTN showing a large bar for the salient channel that AWQ eliminates.
Comparison of output-weighted quantization error between standard round-to-nearest (RTN) and AWQ across a salient channel and a non-salient channel. RTN produces enormous error on the salient channel because the large activation magnifies even modest quantization noise. AWQ's scaling compresses this error to near zero while keeping the non-salient channel similarly unaffected, showing the targeted precision redistribution at the heart of AWQ.

Grid Search Optimization

While the formula-based scaling gives an excellent starting point, AWQ refines the scaling factors through a lightweight grid search over the exponent α\alpha. The optimal value of α\alpha varies across layers depending on their specific weight and activation distributions. Layers in earlier parts of a network may have very different activation profiles than layers in later parts, and a single global α\alpha would be suboptimal for some.

For each layer, the grid search algorithm evaluates a small number of candidate α\alpha values, typically five to ten evenly spaced values between 0 and 1. For each candidate, it computes the corresponding scaling factors, transforms and quantizes the layer's weights, and evaluates quantization error by running the calibration data through that layer and measuring the mean squared error between the original and quantized outputs:

L(α)=1N∑n=1N∥Wx(n)−W^(α)x(n)∥22\mathcal{L}(\alpha) = \frac{1}{N} \sum_{n=1}^{N} \left\| \mathbf{W}\mathbf{x}^{(n)} - \hat{\mathbf{W}}(\alpha)\mathbf{x}^{(n)} \right\|_2^2

where:

  • L(α)\mathcal{L}(\alpha): the mean squared output error for a given scaling exponent α\alpha
  • NN: the number of calibration samples
  • Wx(n)\mathbf{W}\mathbf{x}^{(n)}: the original layer output for sample nn
  • W^(α)x(n)\hat{\mathbf{W}}(\alpha)\mathbf{x}^{(n)}: the quantized layer output when using scaling factors derived from exponent α\alpha
  • ∥⋅∥22\left\|\cdot\right\|_2^2: the squared Euclidean norm of the output error vector

The algorithm selects the α∗\alpha^* that minimizes L(α)\mathcal{L}(\alpha) and uses the corresponding scaling factors for that layer. This per-layer optimization requires only a handful of forward passes through each layer, making the total additional cost negligible compared to the forward pass through the full model that happens anyway during activation collection.

This per-layer grid search adds minimal computational overhead since we're only searching over a handful of α\alpha values, unlike GPTQ's expensive Hessian computations. The search space is tiny, requiring only a few forward passes through each layer to evaluate the candidates. The resulting layer-specific α\alpha values allow AWQ to adapt to the heterogeneous structure of modern neural networks, where different layers may have very different activation and weight distributions. An attention query projection might benefit from more aggressive scaling than a feed-forward output projection, and the grid search discovers these differences automatically.