<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Machine Learning on kenji.blog</title><link>http://kenji.blog/en/categories/machine-learning/</link><description>Recent content in Machine Learning on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>en</language><copyright>kenjinote</copyright><lastBuildDate>Fri, 11 Sep 2026 22:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/en/categories/machine-learning/index.xml" rel="self" type="application/rss+xml"/><item><title>【For Beginners】 Deciphering the Mathematical Structure of the Transformer Model</title><link>http://kenji.blog/en/p/transformer-mathematical-structure/</link><pubDate>Fri, 11 Sep 2026 22:00:00 +0900</pubDate><guid>http://kenji.blog/en/p/transformer-mathematical-structure/</guid><description>&lt;img src="http://kenji.blog/p/transformer-mathematical-structure/img/eyecatch.jpg" alt="Featured image of post 【For Beginners】 Deciphering the Mathematical Structure of the Transformer Model" />&lt;h1 id="introduction-why-learn-the-mathematics-of-transformers">Introduction: Why Learn the Mathematics of Transformers?
&lt;/h1>&lt;p>It is no exaggeration to say that the &amp;ldquo;Transformer&amp;rdquo; is the architecture that rewrote the history of modern Natural Language Processing (NLP) and AI as a whole. First proposed in the 2017 paper &amp;ldquo;Attention Is All You Need&amp;rdquo; by Google researchers, this model serves as the heart of Large Language Models (LLMs) that are currently taking the world by storm, such as OpenAI&amp;rsquo;s GPT series (the foundational technology of ChatGPT), Google&amp;rsquo;s BERT, and Anthropic&amp;rsquo;s Claude.&lt;/p>
&lt;p>However, while qualitative explanations like &amp;ldquo;understanding context using Attention mechanisms&amp;rdquo; are commonly seen regarding how Transformers work, surprisingly few resources dive deep into the &lt;strong>mathematical structure&lt;/strong> behind it for beginners. To truly understand how AI processes &amp;ldquo;words&amp;rdquo; as &amp;ldquo;mathematical formulas&amp;rdquo; and generates incredibly natural sentences, deciphering its mathematical mechanisms is essential.&lt;/p>
&lt;p>This article is aimed at those with a basic understanding of mathematics and programming (those who grasp high school-level concepts of matrices and derivatives). It thoroughly and clearly uncovers the mathematical structures of the Transformer&amp;rsquo;s core components: the &amp;ldquo;Self-Attention mechanism,&amp;rdquo; the &amp;ldquo;Query-Key-Value (Q/K/V) model,&amp;rdquo; &amp;ldquo;normalization using the Softmax function,&amp;rdquo; and &amp;ldquo;Positional Encoding.&amp;rdquo;&lt;/p>
&lt;p>You might be overwhelmed by the list of mathematical formulas, but each calculation has a clear &amp;ldquo;meaning.&amp;rdquo; By the time you finish reading this article, you should understand that the Transformer is not just a magical black box, but an exquisitely designed crystallization of mathematics and statistics.&lt;/p>
&lt;hr>
&lt;h1 id="1-limitations-of-conventional-methods-and-the-innovativeness-of-the-transformer">1. Limitations of Conventional Methods and the Innovativeness of the Transformer
&lt;/h1>&lt;p>Before the advent of the Transformer, the mainstream of natural language processing was Recurrent Neural Networks (RNNs) and their derivative, LSTM (Long Short-Term Memory). RNNs are designed to process time-series data, reading sentences sequentially from the beginning, word by word.&lt;/p>
&lt;p>However, RNNs had two fatal weaknesses:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Difficulty in learning long-term dependencies&lt;/strong>: As sentences get longer, the information of the words inputted at the beginning fades by the time it reaches the end (the vanishing gradient problem).&lt;/li>
&lt;li>&lt;strong>Inability to compute in parallel&lt;/strong>: Because words must be processed sequentially, large-scale parallel computation using GPUs is difficult, requiring an enormous amount of time for training.&lt;/li>
&lt;/ol>
&lt;p>The Transformer caused a paradigm shift by completely discarding the RNN structure and grasping context using only &amp;ldquo;Attention.&amp;rdquo; This allowed for no loss of information no matter how long the sequence is, and made it possible to maximize GPU performance by parallelizing computations.&lt;/p>
&lt;hr>
&lt;h1 id="2-overall-architecture-of-the-transformer">2. Overall Architecture of the Transformer
&lt;/h1>&lt;p>First, let&amp;rsquo;s take a bird&amp;rsquo;s-eye view of the overall Transformer architecture. The Transformer is broadly composed of two blocks: the &amp;ldquo;Encoder&amp;rdquo; and the &amp;ldquo;Decoder.&amp;rdquo; Taking a translation task as an example, the Encoder converts the input language (e.g., English) into mathematical vector representations, and the Decoder generates the output language (e.g., Japanese) based on those vector representations.&lt;/p>
&lt;p>The following diagram is a simplified internal structure of the Encoder block.&lt;/p>
&lt;div class="mermaid">graph TD
A["Input Tokens"] --> B["Input Embedding"]
B --> C["Positional Encoding"]
C --> D["Multi-Head Self-Attention"]
D --> E["Add &amp; Layer Normalization"]
E --> F["Feed Forward Network"]
F --> G["Add &amp; Layer Normalization"]
G --> H["Output to Next Layer"]
C -.->|"Residual Connection"| E
E -.->|"Residual Connection"| G&lt;/div>
&lt;p>From here, let&amp;rsquo;s look step by step at the mathematical operations being performed in each component.&lt;/p>
&lt;hr>
&lt;h1 id="3-word-vectorization-and-positional-encoding">3. Word Vectorization and Positional Encoding
&lt;/h1>&lt;p>Computers cannot understand text as it is. The inputted text is first divided into units called &amp;ldquo;Tokens,&amp;rdquo; and each is converted into a fixed-length vector. This is &lt;strong>Input Embedding&lt;/strong>.&lt;/p>
&lt;h2 id="31-mathematics-of-input-embedding">3.1 Mathematics of Input Embedding
&lt;/h2>&lt;p>Let the size of the vocabulary be $V$, and the dimensionality of the embedding vector be $d_{model}$ (in the original paper, $d_{model} = 512$). Each word $w_i$ is converted into a vector $x_i \in \mathbb{R}^{d_{model}}$ using the embedding matrix $W_E \in \mathbb{R}^{V \times d_{model}}$.&lt;/p>
$$ x_i = W_E \cdot \text{one\_hot}(w_i) $$
&lt;p>As a result, the entire sentence is represented as a matrix $X \in \mathbb{R}^{N \times d_{model}}$ (where $N$ is the length of the sentence).&lt;/p>
&lt;h2 id="32-the-need-for-positional-encoding-and-its-formulas">3.2 The Need for Positional Encoding and its Formulas
&lt;/h2>&lt;p>Unlike RNNs, the Transformer does not process words sequentially but processes all words in parallel simultaneously. This is a significant advantage in terms of computational speed, but at the same time, it causes the problem that &lt;strong>important information of &amp;ldquo;word order&amp;rdquo; is lost&lt;/strong>. For example, &amp;ldquo;A dog bites a man&amp;rdquo; and &amp;ldquo;A man bites a dog&amp;rdquo; have the exact same set of input words, but their meanings are completely different.&lt;/p>
&lt;p>&lt;strong>Positional Encoding&lt;/strong> was devised to provide this word order information to the model.
The Positional Encoding $PE$ for the $i$-th dimension of a word at position $pos$ is calculated using the following trigonometric functions:&lt;/p>
$$ PE_{(pos, 2i)} = \sin\left(\frac{pos}{10000^{2i/d_{model}}}\right) $$
$$ PE_{(pos, 2i+1)} = \cos\left(\frac{pos}{10000^{2i/d_{model}}}\right) $$
&lt;p>Here, $pos$ is the position of the word ($0, 1, 2, \dots, N-1$), and $i$ is the index of the vector&amp;rsquo;s dimension ($0, 1, \dots, d_{model}/2 - 1$).&lt;/p>
&lt;h3 id="why-use-sine-and-cosine">Why Use Sine and Cosine?
&lt;/h3>&lt;p>At first glance, it looks like a very complex and strange mathematical formula, but there is a profound mathematical reason for this. By using trigonometric functions, the model can easily learn not only the &lt;strong>&amp;ldquo;absolute position&amp;rdquo; but also the difference in &amp;ldquo;relative position&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;p>Recall the addition theorems of trigonometric functions learned in high school math:
&lt;/p>
$$ \sin(\alpha + \beta) = \sin\alpha \cos\beta + \cos\alpha \sin\beta $$
$$ \cos(\alpha + \beta) = \cos\alpha \cos\beta - \sin\alpha \sin\beta $$
&lt;p>The Positional Encoding of a position $pos + k$, which is offset by $k$ from a certain position $pos$, can be expressed as a linear combination of the Positional Encoding of position $pos$. In other words, using a matrix $M_k$, it can be written as follows:&lt;/p>
$$ PE_{pos+k} = M_k \cdot PE_{pos} $$
&lt;p>This allows the Attention mechanism to easily recognize the relative distance, or &amp;ldquo;how far apart&amp;rdquo; words are, through dot product calculations. Another advantage is that by combining multiple sine and cosine waves of different wavelengths, a unique position vector can be generated no matter how long the sentence is.&lt;/p>
&lt;p>The final input matrix $X_{input}$ is the sum of the word embedding vectors and this positional encoding.&lt;/p>
$$ X_{input} = X + PE $$
&lt;hr>
&lt;h1 id="4-the-profound-mathematics-of-self-attention">4. The Profound Mathematics of Self-Attention
&lt;/h1>&lt;p>We will finally step into the &lt;strong>Self-Attention&lt;/strong> mechanism, the most critical component of the Transformer. The purpose of Self-Attention is &amp;ldquo;to calculate the degree of relevance between all words in a sentence and update the vector of each word into a richer representation that takes context into account.&amp;rdquo;&lt;/p>
&lt;p>Here, an analogy of a &amp;ldquo;search system&amp;rdquo; is used.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Query (Q)&lt;/strong>: The query (search term). &amp;ldquo;What information am I looking for right now?&amp;rdquo;&lt;/li>
&lt;li>&lt;strong>Key (K)&lt;/strong>: The key (heading). &amp;ldquo;What information do I have?&amp;rdquo;&lt;/li>
&lt;li>&lt;strong>Value (V)&lt;/strong>: The value (entity). &amp;ldquo;What information do I actually provide?&amp;rdquo;&lt;/li>
&lt;/ul>
&lt;h2 id="41-generation-of-matrices-q-k-v">4.1 Generation of Matrices $Q, K, V$
&lt;/h2>&lt;p>For the input matrix $X \in \mathbb{R}^{N \times d_{model}}$ (we ignore batch size here for simplicity), we calculate the query $Q$, key $K$, and value $V$ by multiplying it with learnable weight matrices $W^Q, W^K, W^V \in \mathbb{R}^{d_{model} \times d_k}$. (Usually $d_k = d_v = d_{model} / h$)&lt;/p>
$$ Q = X W^Q $$
$$ K = X W^K $$
$$ V = X W^V $$
&lt;p>Here, $Q, K, V$ are all matrices in $\mathbb{R}^{N \times d_k}$.&lt;/p>
&lt;h2 id="42-calculation-of-attention-scores-dot-product">4.2 Calculation of Attention Scores (Dot Product)
&lt;/h2>&lt;p>To measure how much each word&amp;rsquo;s Query is related to the Keys of all other words, we calculate the &lt;strong>dot product&lt;/strong> of the vectors. Written as a matrix operation, it looks like this:&lt;/p>
$$ \text{Scores} = Q K^T $$
&lt;p>Each element $s_{ij}$ of the matrix $\text{Scores} \in \mathbb{R}^{N \times N}$ obtained by this calculation represents the dot product of the $i$-th word&amp;rsquo;s Query and the $j$-th word&amp;rsquo;s Key, that is, the &amp;ldquo;strength of relevance&amp;rdquo;.&lt;/p>
&lt;h2 id="43-scaling-scale">4.3 Scaling (Scale)
&lt;/h2>&lt;p>There is one problem with calculating scores via dot products. As the dimensionality $d_k$ of the vectors becomes larger, the values of the dot product can become extremely large or small.&lt;/p>
&lt;p>Let&amp;rsquo;s prove this mathematically.
Assume that each element $q$ of the query and $k$ of the key follows an independent standard normal distribution: $q \sim \mathcal{N}(0, 1)$ and $k \sim \mathcal{N}(0, 1)$.
We find the mean and variance of the dot product $q \cdot k = \sum_{i=1}^{d_k} q_i k_i$.
Mean: $\mathbb{E}[q_i k_i] = \mathbb{E}[q_i] \mathbb{E}[k_i] = 0 \times 0 = 0$, so the mean of the sum is also $0$.
Variance: The variance of $q_i k_i$ is, from independence, $\text{Var}(q_i k_i) = \mathbb{E}[(q_i k_i)^2] - (\mathbb{E}[q_i k_i])^2 = 1 \times 1 - 0 = 1$.
Therefore, the variance of the entire dot product is equal to the number of dimensions $d_k$.&lt;/p>
$$ \text{Var}(q \cdot k) = d_k $$
&lt;p>When the variance becomes large, in the Softmax function applied subsequently, the gradients for values other than the maximum become extremely small, leading to &amp;ldquo;vanishing gradients&amp;rdquo;, and learning stops progressing.
To prevent this, the scores are divided (scaled) by $\sqrt{d_k}$ so that the variance is constantly kept at $1$.&lt;/p>
$$ \text{Scaled Scores} = \frac{Q K^T}{\sqrt{d_k}} $$
&lt;h2 id="44-probabilization-by-softmax-function">4.4 Probabilization by Softmax Function
&lt;/h2>&lt;p>To convert the obtained scores into a probability distribution (weights) that sums to $1$, the &lt;strong>Softmax function&lt;/strong> is applied row by row.&lt;/p>
$$ a_{ij} = \text{softmax}(s_i)_j = \frac{\exp(s_{ij} / \sqrt{d_k})}{\sum_{m=1}^N \exp(s_{im} / \sqrt{d_k})} $$
&lt;p>The matrix $A \in \mathbb{R}^{N \times N}$ is called the Attention Weight matrix. Looking at each row $i$ of this matrix, it expresses &amp;ldquo;how much attention should be paid to other words $j$ in order to understand word $i$&amp;rdquo; as a value between 0 and 1.&lt;/p>
&lt;h2 id="45-weighted-sum-of-value">4.5 Weighted Sum of Value
&lt;/h2>&lt;p>Finally, using the obtained Attention Weight matrix $A$, we calculate the weighted sum of the Value matrix $V$.&lt;/p>
$$ \text{Output} = A V = \text{softmax}\left(\frac{Q K^T}{\sqrt{d_k}}\right) V $$
&lt;p>The matrix $Z \in \mathbb{R}^{N \times d_v}$ output by this operation is a collection of &amp;ldquo;word vector representations updated to account for context&amp;rdquo;.
This is the complete picture of the &lt;strong>Scaled Dot-Product Attention&lt;/strong> defined in the paper.&lt;/p>
&lt;hr>
&lt;h1 id="5-multi-head-attention">5. Multi-Head Attention
&lt;/h1>&lt;p>A single Attention calculation (single-head) might only capture context from one perspective (for example, &amp;ldquo;grammatical relationships&amp;rdquo;). Therefore, to simultaneously capture the diverse semantic and syntactic relationships of language (such as &amp;ldquo;subject and predicate&amp;rdquo; or &amp;ldquo;pronouns and their referents&amp;rdquo;), &lt;strong>Multi-Head Attention&lt;/strong> was introduced.&lt;/p>
&lt;p>The generation of $Q, K, V$ and Attention calculation described earlier are performed in parallel $h$ times (the number of heads. In the original paper, $h=8$).&lt;/p>
$$ \text{head}_i = \text{Attention}(X W_i^Q, X W_i^K, X W_i^V) $$
&lt;p>Here, $W_i^Q, W_i^K, W_i^V \in \mathbb{R}^{d_{model} \times d_k}$ are learnable weight matrices dedicated to the $i$-th head.&lt;/p>
&lt;p>The results output from each head, $\text{head}_i \in \mathbb{R}^{N \times d_v}$, are concatenated horizontally.&lt;/p>
$$ \text{Concat}(\text{head}_1, \dots, \text{head}_h) \in \mathbb{R}^{N \times (h \cdot d_v)} $$
&lt;p>Usually, it is set such that $h \cdot d_v = d_{model}$, so the concatenated dimension returns to the original $d_{model}$. Finally, this matrix is multiplied by a weight matrix $W^O \in \mathbb{R}^{d_{model} \times d_{model}}$ to obtain the final output.&lt;/p>
$$ \text{MultiHead}(Q, K, V) = \text{Concat}(\text{head}_1, \dots, \text{head}_h) W^O $$
&lt;div class="mermaid">graph TD
X["Input X"] --> Q1["Q1"]
X --> K1["K1"]
X --> V1["V1"]
Q1 &amp; K1 &amp; V1 --> H1["Head 1"]
X --> Q2["Q2"]
X --> K2["K2"]
X --> V2["V2"]
Q2 &amp; K2 &amp; V2 --> H2["Head 2"]
X --> QN["..."]
X --> KN["..."]
X --> VN["..."]
QN &amp; KN &amp; VN --> HN["Head h"]
H1 &amp; H2 &amp; HN --> C["Concatenate"]
C --> WO["Multiply by WO"]
WO --> OUT["Multi-Head Output"]&lt;/div>
&lt;hr>
&lt;h1 id="6-feed-forward-neural-network-ffn">6. Feed-Forward Neural Network (FFN)
&lt;/h1>&lt;p>The output of Multi-Head Attention is next inputted into the &lt;strong>Position-wise Feed-Forward Network (FFN)&lt;/strong>.
This is a two-layer fully connected neural network applied &amp;ldquo;independently to each position (word)&amp;rdquo; in the sequence.&lt;/p>
&lt;p>Expressed as a formula, it is as follows:&lt;/p>
$$ \text{FFN}(x) = \max(0, x W_1 + b_1) W_2 + b_2 $$
&lt;p>Here, $\max(0, z)$ represents the ReLU (Rectified Linear Unit) activation function (recently, GELU or SwiGLU are also often used in modern models).&lt;/p>
&lt;p>The role of this network is extremely important. While the Attention mechanism learns &amp;ldquo;relationships between words (spatial/sequential relationships)&amp;rdquo;, the FFN is responsible for &amp;ldquo;non-linear feature transformation of each word vector itself&amp;rdquo;.
Usually, the dimension is temporarily expanded greatly by the weights of the first layer $W_1$ (for example, expanding by 4 times from $d_{model}=512$ to $d_{ff}=2048$), and after performing complex calculations in the feature space, it is returned to the original dimension by the weights of the second layer $W_2$. Through this &amp;ldquo;expansion and contraction of dimensions&amp;rdquo;, the expressive power of the model is dramatically enhanced.&lt;/p>
&lt;hr>
&lt;h1 id="7-residual-connection-and-layer-normalization">7. Residual Connection and Layer Normalization
&lt;/h1>&lt;p>In deep learning, as the layers of a network become deeper, problems arise where gradients vanish or explode during training, making it impossible to learn properly. To prevent this, &lt;strong>Residual Connections&lt;/strong> and &lt;strong>Layer Normalization&lt;/strong> are placed around each sublayer (Attention and FFN) of the Transformer.&lt;/p>
&lt;p>Written mathematically, the output of the sublayer is processed as follows:&lt;/p>
$$ \text{Output} = \text{LayerNorm}(x + \text{Sublayer}(x)) $$
&lt;h2 id="71-residual-connection-x--textsublayerx">7.1 Residual Connection ($x + \text{Sublayer}(x)$)
&lt;/h2>&lt;p>The input $x$ is directly added to the output of the sublayer. By doing this, gradients can propagate directly to shallower layers through shortcuts during backpropagation, stabilizing learning even when the layers are deepened.&lt;/p>
&lt;h2 id="72-mathematics-of-layer-normalization">7.2 Mathematics of Layer Normalization
&lt;/h2>&lt;p>Layer Normalization is a technique that calculates the mean and variance along the feature dimension direction to normalize data. For an input with batch size $B$, sequence length $N$, and dimensionality $d_{model}$, normalization is performed on a single word vector $x \in \mathbb{R}^{d_{model}}$.&lt;/p>
&lt;p>Calculate the mean $\mu$ and variance $\sigma^2$:
&lt;/p>
$$ \mu = \frac{1}{d_{model}} \sum_{i=1}^{d_{model}} x_i $$
$$ \sigma^2 = \frac{1}{d_{model}} \sum_{i=1}^{d_{model}} (x_i - \mu)^2 $$
&lt;p>Then, obtain the normalized output $\hat{x}$:
&lt;/p>
$$ \text{LN}(x) = \frac{x - \mu}{\sqrt{\sigma^2 + \epsilon}} \odot \gamma + \beta $$
&lt;p>
(where $\epsilon$ is a small constant to prevent division by zero, and $\gamma, \beta$ are learnable scale and shift parameters)&lt;/p>
&lt;p>The reason for adopting Layer Normalization instead of Batch Normalization is that when processing sequential data of variable length, like sentences, batch-wise statistics tend to become unstable. Thanks to Layer Normalization, the Transformer is capable of stable learning independent of batch size.&lt;/p>
&lt;hr>
&lt;h1 id="8-decoder-specific-structures-masked-attention-and-cross-attention">8. Decoder-Specific Structures: Masked Attention and Cross-Attention
&lt;/h1>&lt;p>The structure explained so far is for the Encoder. In the Decoder block that generates text, the structure is slightly different.&lt;/p>
&lt;h2 id="81-masked-multi-head-attention">8.1 Masked Multi-Head Attention
&lt;/h2>&lt;p>The role of the Decoder is &amp;ldquo;to predict the next word from past words&amp;rdquo;. Therefore, &amp;ldquo;looking ahead at future words&amp;rdquo; during training would be cheating. The mathematical operation to prevent this is &lt;strong>Masking&lt;/strong>.&lt;/p>
&lt;p>To the score matrix $Q K^T$, we add a mask matrix $M$ that sets extremely small values close to $-\infty$ for the upper triangular part (corresponding to future information).&lt;/p>
$$ M_{ij} = \begin{cases} 0 &amp; (i \le j) \\ -\infty &amp; (i > j) \end{cases} $$
$$ \text{Masked Attention}(Q, K, V) = \text{softmax}\left(\frac{Q K^T + M}{\sqrt{d_k}}\right) V $$
&lt;p>When calculating the Softmax function, since $\exp(-\infty) = 0$, the Attention Weight for future words becomes exactly $0$. This enables autoregressive generation while preserving causality.&lt;/p>
&lt;h2 id="82-encoder-decoder-cross-attention">8.2 Encoder-Decoder Cross-Attention
&lt;/h2>&lt;p>The second sublayer of the Decoder is &lt;strong>Cross-Attention&lt;/strong>, which references the output from the Encoder.
Here, $Q$ is generated from the previous decoder layer, while $K$ and $V$ are generated from the output of the final encoder layer.&lt;/p>
$$ Q_{decoder} = X_{dec} W^Q $$
$$ K_{encoder} = X_{enc} W^K $$
$$ V_{encoder} = X_{enc} W^V $$
&lt;p>Through this calculation, in tasks like translation, the model can learn &amp;ldquo;which parts of the original foreign language sentence the currently translating word is strongly related to&amp;rdquo;.&lt;/p>
&lt;hr>
&lt;h1 id="9-computational-complexity-and-mathematics-of-modern-optimization">9. Computational Complexity and Mathematics of Modern Optimization
&lt;/h1>&lt;p>The Transformer is a brilliant model, but it also has &amp;ldquo;weaknesses&amp;rdquo; due to its mathematical structure.
Consider the computational complexity of Self-Attention. Calculating the score matrix $Q K^T$ involves multiplying an $(N \times d_k)$ matrix with a $(d_k \times N)$ matrix, so its computational complexity is &lt;strong>$O(N^2 \cdot d_{model})$&lt;/strong>.&lt;/p>
&lt;p>In other words, &lt;strong>the computational complexity and memory usage increase quadratically with respect to the sequence length $N$&lt;/strong>.
This is not a problem when sentences are short, but if you try to input an enormous context like a whole book into an LLM, $N$ reaches tens to hundreds of thousands, and conventional Attention calculations will immediately exhaust GPU memory.&lt;/p>
&lt;p>To break this curse of $O(N^2)$, various optimizations from mathematical and hardware approaches have been proposed in recent years.
A representative example is &lt;strong>FlashAttention&lt;/strong>. FlashAttention is an algorithm that divides the Attention calculation into tiles (Tiling) to minimize data transfer (memory access) between GPU memory hierarchies (SRAM and HBM). Even though mathematically it outputs exactly the same result as standard Attention (Exact Attention), it achieves dramatic speedups and memory reduction through hardware-level optimization, enabling the realization of long-context models like GPT-4.&lt;/p>
&lt;p>In addition, research on Sparse Attention and Linear Attention, which approximate the computational complexity to $O(N \log N)$ or $O(N)$, is also actively being conducted.&lt;/p>
&lt;hr>
&lt;h1 id="10-implementation-concept-pytorch-style-pseudocode">10. Implementation Concept (PyTorch-style Pseudocode)
&lt;/h1>&lt;p>When translating the mathematical structures up to this point into actual programming code (Python / PyTorch), you&amp;rsquo;ll see that it can be written surprisingly simply. Here is the pseudocode for the core part of Self-Attention.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">torch&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">torch.nn.functional&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">F&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">math&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">scaled_dot_product_attention&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">q&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">k&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">v&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">mask&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">None&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Shape of q, k, v: [batch_size, num_heads, seq_length, d_k]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">d_k&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">q&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">size&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 1. Score calculation via dot product: Q * K^T&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Transpose the last two dimensions to calculate matrix multiplication&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">scores&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">matmul&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">q&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">k&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">transpose&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 2. Scaling&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">scores&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">scores&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="n">math&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sqrt&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">d_k&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 3. Masking (for Masked Attention)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">mask&lt;/span> &lt;span class="ow">is&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="kc">None&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">scores&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">scores&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">masked_fill&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">mask&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="mf">1e9&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 4. Probabilization by Softmax&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">attention_weights&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">F&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">softmax&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">scores&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">dim&lt;/span>&lt;span class="o">=-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># 5. Multiplication with Value matrix&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">output&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">torch&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">matmul&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">attention_weights&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">v&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">output&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">attention_weights&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>You can intuitively see that $Q K^T / \sqrt{d_k}$ expressed mathematically is implemented as &lt;code>torch.matmul(q, k.transpose(-2, -1)) / math.sqrt(d_k)&lt;/code>. The fact that mathematical theories can be realized in just a few lines of code with the help of advanced optimization libraries is a highly fascinating aspect of deep learning.&lt;/p>
&lt;hr>
&lt;h1 id="conclusion-the-shape-of-intelligence-seen-through-mathematical-formulas">Conclusion: The Shape of &amp;ldquo;Intelligence&amp;rdquo; Seen Through Mathematical Formulas
&lt;/h1>&lt;p>In this article, we have deciphered the deep mathematical structures of the Transformer model.&lt;/p>
&lt;p>Embedding maps words into a multi-dimensional vector space, Positional Encoding represents position information through the composition of triangular waves, and the Self-Attention mechanism is a matrix dot product calculation born from an information retrieval analogy. Each of these components is merely an accumulation of fundamental mathematics such as linear algebra, calculus, and probability statistics.&lt;/p>
&lt;p>However, when these simple matrix operations are layered over and over, learning patterns from massive datasets through billions or hundreds of billions of parameters, a &amp;ldquo;shape of intelligence&amp;rdquo; emerges—one that seems to understand our &amp;ldquo;words&amp;rdquo;, perform logical reasoning, and sometimes generate creative ideas.&lt;/p>
&lt;p>As the provocative title &amp;ldquo;Attention Is All You Need&amp;rdquo; suggests, the beauty of this architecture, which discards complex recurrent or convolutional processing and specializes purely in calculating &amp;ldquo;attention (relevance)&amp;rdquo;, lies exactly in its mathematical simplicity.&lt;/p>
&lt;p>While there is a possibility that new architectures surpassing the Transformer (such as Mamba, a State Space Model) may appear in the future, the mathematical framework of &amp;ldquo;context understanding through Attention&amp;rdquo; built by the Transformer will surely be etched in the history of AI forever.&lt;/p>
&lt;p>If you have the opportunity to use LLMs like ChatGPT or Claude in the future, imagine the trillions of $Q K^T$ matrix multiplications being calculated per second in the background, with the Softmax function spitting out probabilities. Your resolution regarding the technology will increase, and you should find the world of AI even more fascinating.&lt;/p>
&lt;h3 id="references">References
&lt;/h3>&lt;ul>
&lt;li>Vaswani, A., et al. (2017). &amp;ldquo;Attention Is All You Need.&amp;rdquo; &lt;em>Advances in Neural Information Processing Systems&lt;/em>.&lt;/li>
&lt;li>Alammar, J. (2018). &amp;ldquo;The Illustrated Transformer.&amp;rdquo;&lt;/li>
&lt;/ul>
&lt;hr>
&lt;p>&lt;em>This article was written as a guide for those learning the mathematical foundations of natural language processing and AI. If you have any questions or discussions, please let us know in the comments!&lt;/em>&lt;/p></description></item><item><title>An Explanation of How llama.cpp Quantization Technology (GGUF) Works</title><link>http://kenji.blog/en/p/llama-cpp-quantization-gguf/</link><pubDate>Fri, 11 Sep 2026 00:00:00 +0900</pubDate><guid>http://kenji.blog/en/p/llama-cpp-quantization-gguf/</guid><description>&lt;img src="http://kenji.blog/p/llama-cpp-quantization-gguf/img/eyecatch.jpg" alt="Featured image of post An Explanation of How llama.cpp Quantization Technology (GGUF) Works" />&lt;h2 id="1-introduction-why-do-llms-need-quantization">1. Introduction: Why Do LLMs Need Quantization?
&lt;/h2>&lt;p>The recent evolution of Large Language Models (LLMs) has been remarkable, but behind the scenes, serious problems of &amp;ldquo;exhaustion of computational resources&amp;rdquo; and &amp;ldquo;memory bandwidth bottlenecks&amp;rdquo; have emerged. For example, if a 70B (70 billion) parameter model like Llama 3 is loaded into memory in standard 16-bit floating-point (FP16), the parameters alone consume about 140GB of VRAM/RAM. When the context during inference (KV cache) is added to this, it will not run unless multiple high-end GPUs for data centers (such as NVIDIA A100 80GB or H100 80GB) are clustered together.&lt;/p>
&lt;p>To save individual developers and edge devices (like MacBooks and standard gaming PCs) wanting to run LLMs, &lt;strong>llama.cpp&lt;/strong> and its core &lt;strong>Quantization&lt;/strong> technology appeared as a savior. In particular, the &lt;strong>GGUF (GPT-Generated Unified Format)&lt;/strong> file format and the advanced block-wise quantization algorithm called &lt;strong>k-quants&lt;/strong> are revolutionary methods that compress the model size to a fraction while minimizing the degradation of model accuracy (Perplexity).&lt;/p>
&lt;p>This article thoroughly explains the mathematical background of quantization in llama.cpp, its differences from the GGML format, the detailed structure of the GGUF format, and the internal mechanisms of k-quants.&lt;/p>
&lt;hr>
&lt;h2 id="2-mathematical-foundations-of-quantization">2. Mathematical Foundations of Quantization
&lt;/h2>&lt;p>Quantization in the context of LLMs refers to the operation of mapping continuous values (or high-precision floating-point numbers) to discrete values with a smaller number of bits (INT8, INT4, INT3, etc.).&lt;/p>
&lt;h3 id="21-basic-formulas-of-linear-quantization">2.1. Basic Formulas of Linear Quantization
&lt;/h3>&lt;p>The simplest approach is linear quantization (Min-Max quantization). Let $W$ be the original high-precision weight tensor, and $W_q$ be the quantized integer tensor.&lt;/p>
$$ W_q = \text{round}\left( \frac{W}{S} \right) + Z $$
&lt;p>Here,&lt;/p>
&lt;ul>
&lt;li>$S$ is the &lt;strong>Scale Factor&lt;/strong>, which determines the step size (resolution) of the quantization.&lt;/li>
&lt;li>$Z$ is the &lt;strong>Zero-point&lt;/strong>, which is a bias value used to shift what integer value the real number $0.0$ corresponds to after quantization.&lt;/li>
&lt;li>$\text{round}(\cdot)$ is a function that rounds to the nearest integer.&lt;/li>
&lt;/ul>
&lt;p>By dequantization, the approximate real weights $\tilde{W}$ are restored during inference.&lt;/p>
$$ \tilde{W} = S \times (W_q - Z) $$
&lt;h3 id="22-symmetric-quantization-vs-asymmetric-quantization">2.2. Symmetric Quantization vs. Asymmetric Quantization
&lt;/h3>&lt;p>Depending on the treatment of the zero-point $Z$, it is broadly divided into two methods.&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>Asymmetric Quantization&lt;/strong>
It maps using the minimum value $W_{\min}$ and the maximum value $W_{\max}$ of the data.
&lt;/p>
$$ S = \frac{W_{\max} - W_{\min}}{2^b - 1}, \quad Z = \text{round}\left(-\frac{W_{\min}}{S}\right) $$
&lt;p>
Here $b$ is the number of quantization bits (e.g., for 4 bits, $2^4-1 = 15$). Because it is necessary to hold $Z$, the computation and memory overhead slightly increase.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Symmetric Quantization&lt;/strong>
It uses the maximum absolute value of the data and maps around zero ($Z=0$).
&lt;/p>
$$ S = \frac{\max(|W_{\max}|, |W_{\min}|)}{2^{b-1} - 1}, \quad Z = 0 $$
&lt;p>
Early quantization in llama.cpp (like the legacy Q4_0) adopted symmetric quantization, and since there is no $Z$ term, it has the advantage of significantly speeding up dot product calculations with SIMD instructions.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="3-the-evolution-from-ggml-to-gguf-and-file-structure">3. The Evolution from GGML to GGUF and File Structure
&lt;/h2>&lt;p>When talking about llama.cpp, the tensor math library &lt;strong>GGML&lt;/strong> written in C++, and its derived file format &lt;strong>GGUF&lt;/strong>, are indispensable.&lt;/p>
&lt;h3 id="31-issues-with-ggml">3.1. Issues with GGML
&lt;/h3>&lt;p>Early llama.cpp used the &lt;code>ggml&lt;/code> format (and variants like &lt;code>ggjt&lt;/code>). However, these had the following problems:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Lack of extensibility:&lt;/strong> Magic numbers and hyperparameters were hardcoded in fixed lengths and a fixed order, causing breaking changes every time a new model architecture (e.g., Llama, Falcon, Mixtral, etc.) or a new tokenizer was added.&lt;/li>
&lt;li>&lt;strong>Loss of backward compatibility:&lt;/strong> The format was frequently updated, leading to many situations where old model files could not be read by the latest llama.cpp.&lt;/li>
&lt;/ul>
&lt;h3 id="32-the-birth-of-the-gguf-format">3.2. The Birth of the GGUF Format
&lt;/h3>&lt;p>&lt;strong>GGUF&lt;/strong>, introduced in August 2023, is a highly versatile format designed to solve these problems. Its most significant feature is the adoption of a &lt;strong>Key-Value-based metadata structure&lt;/strong>.&lt;/p>
&lt;p>The Mermaid diagram below abstracts the file structure of GGUF.&lt;/p>
&lt;div class="mermaid">graph TD
A["GGUF File"] --> B["Header (Magic, Version)"]
A --> C["Metadata (Key-Value Pairs)"]
A --> D["Tensor Info (Name, Shape, Offset)"]
A --> E["Tensor Data (Binary payload)"]
C --> C1["general.architecture: llama"]
C --> C2["llama.context_length: 4096"]
C --> C3["tokenizer.ggml.tokens: [...]"]
E --> E1["Layer 0 Weights"]
E --> E2["Layer 1 Weights"]
E --> E3["..."]&lt;/div>
&lt;p>&lt;strong>Main Advantages of GGUF:&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Flexibility:&lt;/strong> All model hyperparameters, RoPE (Rotary Positional Embedding) settings, tokenizer vocabulary data, etc., are stored as named Key-Value pairs. Unknown keys are ignored, making it easy to add new features.&lt;/li>
&lt;li>&lt;strong>Endian-independent:&lt;/strong> GGUF adopts little-endian by default, but it explicitly holds a flag, making it safely portable across different architectures.&lt;/li>
&lt;li>&lt;strong>Optimized for mmap (Memory Mapping):&lt;/strong> Tensor data is aligned (padded) to specific boundaries and can be mapped directly from the disk into the memory space using the OS&amp;rsquo;s &lt;code>mmap()&lt;/code> system call. As a result, the initialization time for loading the model becomes virtually zero.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="4-the-depths-of-k-quants-advanced-block-wise-quantization">4. The Depths of k-quants: Advanced Block-wise Quantization
&lt;/h2>&lt;p>The true value of the GGUF format lies in the mechanism called &lt;strong>k-quants (K-quantization)&lt;/strong>, which is responsible for compressing model weights.&lt;/p>
&lt;p>Normally, the weights of a neural network take a shape close to a normal distribution when looking at the entire layer, but Outliers exist locally. If the weights of an entire layer are quantized with a uniform scale factor $S$, the information of small weights will be completely lost due to being dragged by outliers.&lt;/p>
&lt;p>To prevent this, llama.cpp performs &lt;strong>Block-wise Quantization&lt;/strong>. The weight tensor is divided into small blocks (e.g., 32 elements or 256 elements), and each block is given its own unique scale factor (and zero-point).&lt;/p>
&lt;h3 id="41-limitations-of-legacy-quantization-q4_0-q4_1">4.1. Limitations of Legacy Quantization (Q4_0, Q4_1)
&lt;/h3>&lt;p>The early &lt;code>Q4_0&lt;/code> treated 32 FP16 weights as one block and shared one FP16 scale factor.&lt;/p>
&lt;ul>
&lt;li>Block size: 32&lt;/li>
&lt;li>Memory: 1 scale (16-bit) + 32 4-bit weights (128-bit) = 144-bit&lt;/li>
&lt;li>Effective bits per weight (bpw): $144 / 32 = 4.5$ bpw&lt;/li>
&lt;/ul>
&lt;p>Even this was excellent enough, but the limits of accuracy and compression ratio became apparent. Thus, &lt;strong>k-quants&lt;/strong> emerged, featuring a more complex and sophisticated hierarchical structure.&lt;/p>
&lt;h3 id="42-hierarchical-structure-of-super-blocks-and-sub-blocks-example-of-q4_k_m">4.2. Hierarchical Structure of Super-blocks and Sub-blocks (Example of Q4_K_M)
&lt;/h3>&lt;p>k-quants has a hierarchical structure consisting of large &amp;ldquo;Super-blocks&amp;rdquo; and small &amp;ldquo;Sub-blocks&amp;rdquo; contained within them. This allows the metadata itself (such as scale values) to be quantized, maintaining accuracy while reducing bpw to the absolute limit.&lt;/p>
&lt;p>Let&amp;rsquo;s look at the structure of &lt;strong>Q4_K_M&lt;/strong>, which is the most popular configuration. Q4_K_M uses a super-block of 256 elements.&lt;/p>
&lt;div class="mermaid">graph TD
A["Super-block (256 weights)"] --> B["Scale metadata (FP16/INT8)"]
A --> C["Sub-block 0 (32 weights, 4-bit)"]
A --> D["Sub-block 1 (32 weights, 4-bit)"]
A --> E["..."]
A --> F["Sub-block 7 (32 weights, 4-bit)"]
B --> B1["Super-scale (FP16)"]
B --> B2["Sub-scales (8 x 6-bit)"]
B --> B3["Sub-mins (8 x 6-bit)"]&lt;/div>
&lt;p>The actual structure in C++ (GGML) is defined conceptually as follows:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Conceptual structure of block_q4_K in llama.cpp
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="cp">#define QK_K 256
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">struct&lt;/span> &lt;span class="nc">block_q4_K&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">uint8_t&lt;/span> &lt;span class="n">d&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">];&lt;/span> &lt;span class="c1">// Super-scale for the entire super-block (e.g., FP16 x 2)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">uint8_t&lt;/span> &lt;span class="n">scales&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">12&lt;/span>&lt;span class="p">];&lt;/span> &lt;span class="c1">// Packed data of 6-bit scales and 6-bit minimums (zero-points) for 8 sub-blocks (32 elements each)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">uint8_t&lt;/span> &lt;span class="n">qs&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">QK_K&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">];&lt;/span> &lt;span class="c1">// Weight data quantized in 4-bit (256 elements / 2 = 128 bytes)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>Mathematical Dequantization Process:&lt;/strong>&lt;/p>
&lt;p>The approximate real value $\tilde{W}_{i, j}$ of element $j$ ($0 \le j &lt; 32$) within sub-block $i$ ($0 \le i &lt; 8$) is calculated as follows:&lt;/p>
$$ \tilde{W}_{i, j} = S_{\text{super}} \times s_i \times (w_{i, j} - m_i) $$
&lt;ul>
&lt;li>$S_{\text{super}}$: Floating-point scale for the entire super-block&lt;/li>
&lt;li>$s_i$: 6-bit scale quantized for sub-block $i$&lt;/li>
&lt;li>$m_i$: 6-bit minimum (zero-point) quantized for sub-block $i$&lt;/li>
&lt;li>$w_{i, j}$: 4-bit quantized weight ($0 \dots 15$)&lt;/li>
&lt;/ul>
&lt;p>This hierarchical structure drastically reduces the memory footprint occupied by the scale factors themselves while maintaining adaptability to outliers. Q4_K_M achieves around &lt;strong>4.8 bpw&lt;/strong> overall.&lt;/p>
&lt;h3 id="43-diverse-k-quants-options">4.3. Diverse k-quants Options
&lt;/h3>&lt;p>llama.cpp provides a number of variations depending on the purpose. The suffixes after &amp;ldquo;K&amp;rdquo; (S, M, L) represent the relative size.&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:left">Format&lt;/th>
&lt;th style="text-align:center">BPW (Bits per Weight)&lt;/th>
&lt;th style="text-align:left">Overview and Features&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Q2_K&lt;/strong>&lt;/td>
&lt;td style="text-align:center">2.5～3.3&lt;/td>
&lt;td style="text-align:left">Extreme compression. Accuracy drops significantly, but meant for environments with extremely low VRAM.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Q3_K_M&lt;/strong>&lt;/td>
&lt;td style="text-align:center">3.3&lt;/td>
&lt;td style="text-align:left">Standard for 3-bit quantization. It degrades more than Q4 but often stays within acceptable limits.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Q4_K_M&lt;/strong>&lt;/td>
&lt;td style="text-align:center">4.8&lt;/td>
&lt;td style="text-align:left">&lt;strong>Recommended sweet spot&lt;/strong>. Achieves both a halving of model size and maintenance of accuracy.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Q5_K_M&lt;/strong>&lt;/td>
&lt;td style="text-align:center">5.5&lt;/td>
&lt;td style="text-align:left">When higher accuracy is required. Positioned halfway between Q4 and FP16.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Q6_K&lt;/strong>&lt;/td>
&lt;td style="text-align:center">6.6&lt;/td>
&lt;td style="text-align:left">Maintains Perplexity almost equivalent to FP16, but the file size is relatively large.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Q8_0&lt;/strong>&lt;/td>
&lt;td style="text-align:center">8.5&lt;/td>
&lt;td style="text-align:left">Equivalent to INT8. Mainly used for intermediate tensors for computation during inference, or only in the final layer.&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;ul>
&lt;li>Note: The actual BPW is averaged over the entire model, as Mixed Quantization is performed depending on the model&amp;rsquo;s tensors (for example, whether it is a Q/K/V projection in Attention, or FFN weights). Optimizations such as quantizing important tensors with Q6 and others with Q4 are performed internally.&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="5-performance-optimization-during-inference-simd-and-cuda-architectures">5. Performance Optimization During Inference: SIMD and CUDA Architectures
&lt;/h2>&lt;p>Merely loading a GGUF model into memory does not speed up inference. The majority of LLM inference is &amp;ldquo;Matrix Multiplication&amp;rdquo; (Matrix-Vector Multiplication, abbreviated as GEMV, or Matrix-Matrix, GEMM). The key is how to speed up the multiply-accumulate operations between quantized weights and activations (input data) held in FP16 (or FP32).&lt;/p>
&lt;h3 id="51-utilizing-simd-instructions-in-cpu-environments">5.1. Utilizing SIMD Instructions in CPU Environments
&lt;/h3>&lt;p>The reason llama.cpp boasts tremendous speed in CPU inference lies in &lt;strong>SIMD (Single Instruction, Multiple Data)&lt;/strong> optimization at the assembly level.
For example, it fully utilizes the &lt;strong>AVX2&lt;/strong> or &lt;strong>AVX-512&lt;/strong> instruction sets on Intel/AMD CPUs, and &lt;strong>ARM NEON&lt;/strong> on Apple Silicon.&lt;/p>
&lt;p>During inference, it does not bother to revert (dequantize) $W_q$ to FP32 before multiplying.
The activation side is also dynamically quantized in blocks (Dynamic Quantization, typically to INT8), and integer operations of &lt;strong>INT8 $\times$ INT4&lt;/strong> are computed at once using special SIMD dot-product instructions (e.g., &lt;code>vdpaddd&lt;/code> or &lt;code>_mm256_madd_epi16&lt;/code>). By converting it back to FP32 in the final accumulator and multiplying by the scale factor, it achieves incredible throughput.&lt;/p>
&lt;h3 id="52-offloading-in-gpu-environments-cublas--cuda">5.2. Offloading in GPU Environments (cuBLAS / CUDA)
&lt;/h3>&lt;p>Recent versions of llama.cpp have strong support for NVIDIA GPUs (CUBLAS / CUDA) as well as CPUs.
It is possible to offload some or all layers of a GGUF file to VRAM (using the &lt;code>--n-gpu-layers&lt;/code> option).&lt;/p>
&lt;div class="mermaid">sequenceDiagram
participant User
participant CPU_RAM as CPU &amp; RAM (mmap)
participant VRAM as GPU VRAM
participant Compute as Tensor Cores
User->>CPU_RAM: Load GGUF (mmap)
CPU_RAM->>VRAM: Offload Layers (e.g. 30/32 layers)
Note over CPU_RAM, VRAM: Data remains quantized in VRAM
User->>Compute: Forward Pass (Input Tokens)
Compute->>VRAM: Fetch Quantized Weights
Compute->>Compute: Dequantize to FP16 on-the-fly in SRAM
Compute->>Compute: Matrix Multiplication (cuBLAS / Custom Kernels)
Compute->>User: Output Logits&lt;/div>
&lt;p>When computing on a GPU, the Memory Bandwidth of VRAM becomes the biggest bottleneck. Because the weights are compressed with k-quants, the amount of data transferred from VRAM to the GPU&amp;rsquo;s compute units (SM: Streaming Multiprocessors or Tensor Cores) is reduced to 1/3 to 1/4. The moment the weights reach the compute units, they are dequantized to FP16 on-the-fly, and matrix multiplication is executed ultra-fast using Tensor Cores.
In other words, quantization is performed &lt;strong>not to &amp;ldquo;reduce the amount of computation,&amp;rdquo; but to &amp;ldquo;reduce the amount of memory transfer&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;hr>
&lt;h2 id="6-specific-examples-of-memory-usage-vs-performance-trade-offs">6. Specific Examples of Memory Usage vs. Performance Trade-offs
&lt;/h2>&lt;p>Here, let&amp;rsquo;s look at the required specifications for each quantization level of GGUF, taking the Llama 3 8B model as an example. (The numbers are rough estimates.)&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:left">Model / Quantization&lt;/th>
&lt;th style="text-align:left">File Size&lt;/th>
&lt;th style="text-align:left">Required VRAM/RAM&lt;/th>
&lt;th style="text-align:left">Inference Speed (Est.)&lt;/th>
&lt;th style="text-align:left">Perplexity Degradation&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Llama-3-8B (FP16)&lt;/strong>&lt;/td>
&lt;td style="text-align:left">Approx. 16 GB&lt;/td>
&lt;td style="text-align:left">18 GB or more&lt;/td>
&lt;td style="text-align:left">Baseline&lt;/td>
&lt;td style="text-align:left">None (Base)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Llama-3-8B (Q8_0)&lt;/strong>&lt;/td>
&lt;td style="text-align:left">Approx. 8.5 GB&lt;/td>
&lt;td style="text-align:left">10 GB or more&lt;/td>
&lt;td style="text-align:left">Fast&lt;/td>
&lt;td style="text-align:left">Near zero&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Llama-3-8B (Q6_K)&lt;/strong>&lt;/td>
&lt;td style="text-align:left">Approx. 6.6 GB&lt;/td>
&lt;td style="text-align:left">8 GB or more&lt;/td>
&lt;td style="text-align:left">Very Fast&lt;/td>
&lt;td style="text-align:left">Minimal&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Llama-3-8B (Q4_K_M)&lt;/strong>&lt;/td>
&lt;td style="text-align:left">Approx. 4.9 GB&lt;/td>
&lt;td style="text-align:left">6.5 GB or more&lt;/td>
&lt;td style="text-align:left">Fastest / Optimal&lt;/td>
&lt;td style="text-align:left">Acceptable / Slight&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Llama-3-8B (Q3_K_M)&lt;/strong>&lt;/td>
&lt;td style="text-align:left">Approx. 3.9 GB&lt;/td>
&lt;td style="text-align:left">5.5 GB or more&lt;/td>
&lt;td style="text-align:left">Fastest&lt;/td>
&lt;td style="text-align:left">Somewhat noticeable&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Llama-3-8B (Q2_K)&lt;/strong>&lt;/td>
&lt;td style="text-align:left">Approx. 3.0 GB&lt;/td>
&lt;td style="text-align:left">4.5 GB or more&lt;/td>
&lt;td style="text-align:left">Fast&lt;/td>
&lt;td style="text-align:left">Obvious degradation&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>Important Note (Impact of KV Cache):&lt;/strong>
In LLM inference, as the context length (number of prompt tokens) becomes longer, not only the model weights but also the memory consumption of the &lt;strong>KV Cache&lt;/strong>, which stores past Attention states, increases explosively.
For example, if the context is 8192 tokens, the KV cache alone consumes several GBs. Therefore, in actual operation, it is necessary to secure a margin (Headroom) of &lt;code>Model File Size + Approx. 1.5GB to 3GB&lt;/code>. The reason Q4_K_M is recommended is because it perfectly strikes a balance, safely running on standard GPUs with 8GB VRAM (like RTX 3060 / 4060) even with this KV cache reserved.&lt;/p>
&lt;p>In recent versions of llama.cpp, a &lt;strong>feature to quantize the KV cache itself to Q8_0 or Q4_0&lt;/strong> has also been added, and continuous efforts are being made to further extend the context length.&lt;/p>
&lt;hr>
&lt;h2 id="7-conclusion">7. Conclusion
&lt;/h2>&lt;p>In this article, we delved deep into and explained the internal structure of the GGUF format and k-quants quantization technology, which are the heart of llama.cpp.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Flexibility of GGUF:&lt;/strong> With a Key-Value-based metadata structure, it has built a robust ecosystem capable of following the rapid evolution of LLMs (the emergence of new model architectures) without breaking changes.&lt;/li>
&lt;li>&lt;strong>Extreme Compression with k-quants:&lt;/strong> By managing hierarchical scale factors with super-blocks and sub-blocks, it achieved incredible compression of an average of 4.8 bits per weight (Q4_K_M) while preserving outlier information.&lt;/li>
&lt;li>&lt;strong>Elimination of Memory Bandwidth Bottleneck:&lt;/strong> Through advanced kernel implementations in SIMD and CUDA, performing computations while dequantizing on-the-fly reduces VRAM transfer volumes and dramatically improves inference speed.&lt;/li>
&lt;/ol>
&lt;p>The technological prowess of llama.cpp, which advances the democratization of AI, is no exaggeration to call one of the peaks of modern software engineering, transcending the boundaries of a mere tool. By understanding the quantization algorithms and the mechanics of the GGUF format, you will be able to choose the most suitable model for your environment and perform performance tuning more accurately.&lt;/p>
&lt;h3 id="reference-links">Reference Links
&lt;/h3>&lt;ul>
&lt;li>&lt;a class="link" href="https://github.com/ggerganov/llama.cpp" target="_blank" rel="noopener"
>llama.cpp GitHub Repository&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://github.com/ggerganov/ggml/blob/master/docs/gguf.md" target="_blank" rel="noopener"
>GGUF Format Specification&lt;/a>&lt;/li>
&lt;li>&lt;a class="link" href="https://github.com/ggerganov/llama.cpp/pull/1684" target="_blank" rel="noopener"
>K-quants Implementation PR&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>(End)&lt;/p></description></item></channel></rss>