<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>DSP LOG</title>
	<atom:link href="https://dsplog.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://dsplog.com</link>
	<description>Signal Processing</description>
	<lastBuildDate>Sat, 04 Jul 2026 07:03:13 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>
	<item>
		<title>Positional Encoding in Transformers</title>
		<link>https://dsplog.com/2026/07/04/positional-encoding-in-transformers/</link>
					<comments>https://dsplog.com/2026/07/04/positional-encoding-in-transformers/#respond</comments>
		
		<dc:creator><![CDATA[Krishna Sankar]]></dc:creator>
		<pubDate>Sat, 04 Jul 2026 07:03:02 +0000</pubDate>
				<category><![CDATA[Machine Learning]]></category>
		<category><![CDATA[ALiBi]]></category>
		<category><![CDATA[Positional Encoding]]></category>
		<category><![CDATA[RoPE]]></category>
		<category><![CDATA[YaRN]]></category>
		<guid isPermaLink="false">https://dsplog.com/?p=2877</guid>

					<description><![CDATA[<p>In the seminal paper Attention is All you Need (Vaswani et al 2017), the authors proposed Transformer architecture where all tokens in sequence can be processed in parallel. As the architecture process all tokens simultaneously, the concept of positional embeddings to encode the sequence information is needed. In this post, we cover few positional encoding &#8230; <a href="https://dsplog.com/2026/07/04/positional-encoding-in-transformers/" class="more-link">Continue reading<span class="screen-reader-text"> "Positional Encoding in Transformers"</span></a></p>
<p>The post <a rel="nofollow" href="https://dsplog.com/2026/07/04/positional-encoding-in-transformers/">Positional Encoding in Transformers</a> appeared first on <a rel="nofollow" href="https://dsplog.com">DSP LOG</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">In the seminal paper <strong><a href="https://arxiv.org/abs/2309.00071" target="_blank" rel="noopener">Attention is All you Need</a> </strong>(Vaswani et al 2017), the authors proposed <strong>Transformer</strong> architecture where all tokens in sequence can be processed in parallel. As the architecture <strong>process all tokens simultaneously</strong>, the concept of <strong>positional embeddings</strong> to <strong>encode the sequence information</strong> is needed.  In this post, we cover few positional encoding techniques and techniques for extending the pre-trained context length. </p>



<ol class="wp-block-list">
<li><a href="#Sinusoidal_Positional_Encoding_Vaswani_et_al_2017" data-type="internal" data-id="#Sinusoidal_Positional_Encoding_Vaswani_et_al_2017">Sinusoidal Positional Encoding</a> (Vaswani et al 2017)</li>



<li><a href="#RoPE_–_Rotary_Positional_Encoding_Su_et_al_2021" data-type="internal" data-id="#RoPE_–_Rotary_Positional_Encoding_Su_et_al_2021">RoPE – Rotary Positional Encoding </a>(Su et al., 2021)</li>



<li><a href="#ALiBi_–_Attention_with_Linear_Biases_Ofir_Press_et_al_2021" data-type="internal" data-id="#ALiBi_–_Attention_with_Linear_Biases_Ofir_Press_et_al_2021">ALiBi – Attention with Linear Biases</a>, Ofir Press et al 2021</li>



<li>Extending pre-trained context window
<ul class="wp-block-list">
<li><a href="#Position_Interpolation_Chen_et_al_2023" data-type="internal" data-id="#Position_Interpolation_Chen_et_al_2023">Position Interpolation </a>(Chen et al 2023)</li>



<li><a href="#NTK_aware_scaling_bloc97_2023" data-type="internal" data-id="#NTK_aware_scaling_bloc97_2023">NTK aware scaling</a> (block97 2023)</li>



<li><a href="#YaRN_–_Yet_Another_RoPE_extensioN_method_Peng_et_al_2023" data-type="internal" data-id="#YaRN_–_Yet_Another_RoPE_extensioN_method_Peng_et_al_2023">YaRN – Yet Another RoPE extensioN method</a> (Peng et al 2023)</li>
</ul>
</li>
</ol>



<span id="more-2877"></span>



<h1 class="wp-block-heading">Sinusoidal Positional Encoding (Vaswani et al., 2017)</h1>



<p class="wp-block-paragraph">Prior to <strong>transformer</strong> architecture proposed in the paper Attention Is All You Need&#8221; (Vaswani et al., 2017), sequence modelling tasks such as language translation were handled using <strong>recurrent neural networks</strong> (<strong>RNNs</strong>) and recurrent variants such as <strong>LSTMs</strong>. In recurrent architectures, tokens are processed <strong>sequentially</strong>, one after another.</p>



<p class="wp-block-paragraph">For a sequence of <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?N" alt=""> tokens <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\[t_0, t_1, ... t_{N-1}\]
" alt="">, the the hidden state evolves as,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
h_n = f(h_{n-1},x_n)
" alt="">



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">where, </p>



<ul class="wp-block-list">
<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?x_n" alt=""> is the embedding of token at position <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?n" alt=""></li>



<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?h_n" alt=""> is the hidden state after processing token <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?n" alt=""></li>
</ul>



<p class="wp-block-paragraph">Since tokens are processed <strong>sequentially</strong>, the order is naturally embedded into the computation. However, sequential processing <strong>prevents parallel implementation</strong> during training because a token at position <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?n" alt=""> cannot be processed until the previous <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?n-1" alt=""> tokens has been consumed.</p>



<h2 class="wp-block-heading">Transformer architecture</h2>



<p class="wp-block-paragraph">In <strong>Transformer architecture</strong> all tokens in sequence can be processed in <strong>parallel</strong>. To <strong>encode the sequence information</strong>, a <strong>positional encoding vector</strong> defined using <strong>sinusodial basis functions </strong>is defined for each element in the sequence. </p>



<p class="wp-block-paragraph">In the following sections, we will go over the positional encoding scheme followed by attention scheme. In the attention layer, the interactions between the tokens (with the injected position embeddings) is used to understand the intuitions behind the definition of the positional encoding. </p>



<h3 class="wp-block-heading">Positional Encoding</h3>



<p class="wp-block-paragraph"> Each token is mapped into an embedding vector of dimension <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?D" alt=""> as,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}
E_n = 
\begin{bmatrix} 
e_{n,0} \\ 
e_{n,1} \\ 
e_{n,2} \\ 
e_{n,3} \\ 
\vdots \\ 
e_{n,D-1} 
\end{bmatrix}^T
\end{array}
" alt="">



<p class="wp-block-paragraph">Stacking all the all the embedding vectors for the sequence of length <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?N" alt="">,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}
\mathbf{E} = 
\begin{bmatrix} 
E_0^T \\ 
E_1^T \\ 
E_2^T \\ 
\vdots \\ 
E_{N-1}^T
\end{bmatrix}^T 
\quad \in \R^{N \times D}
\end{array}
" alt="">



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">The position embedding <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?P_n" alt=""> at token position <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?n" alt=""> is defined as :</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}
P_n = \begin{bmatrix} 
\sin(\omega_0 n) \\ 
\cos(\omega_0 n) \\ 
\sin(\omega_1 n) \\ 
\cos(\omega_1 n) \\ 
\vdots \\ 
\sin(\omega_{\frac{D}{2}-1} n) \\
\cos(\omega_{\frac{D}{2}-1} n) 
\end{bmatrix}^T

\end{array}, \quad \omega_i = \frac{1}{10000^{\frac{2i}{D}}}

" alt="">



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">Positional embedding can be visualized as <strong>even &amp; odd dimensions</strong> having <strong>sine/cosine </strong>terms and with multiple frequencies across the dimension <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?D" alt="">,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
PE_{pos,2i} = \sin\(\frac{pos}{10000^{\frac{2i}{D}}}\) \\
PE_{pos,2i+1} = \cos\(\frac{pos}{10000^{\frac{2i}{D}}\)

" alt="">



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">Stacking all the all the positional encoding vectors for the sequence of length <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?N" alt=""> ,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}
\mathbf{P} = 
\begin{bmatrix} 
P_0^T \\ 
P_1^T \\ 
P_2^T \\ 
\vdots \\ 
P_{N-1}^T
\end{bmatrix}^T 
\quad \in \R^{N \times D}
\end{array}
" alt="">



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">To encode the sequence information, <strong>postitional embeddings</strong> are <strong>added</strong> into the token embeddings. </p>



<p class="wp-block-paragraph">The <strong>combined input matrix</strong> capturing the sequence of token embedding and position encoding is defined as,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\mathbf{X} = \mathbf{E} + \mathbf{P},\quad \in \R^{N \times D}

" alt="">



<p class="wp-block-paragraph"></p>



<h3 class="wp-block-heading">Self-attention layer</h3>



<p class="wp-block-paragraph">The transformer architecture models interactions between all tokens using the <strong>self-attention mechanism</strong>. The combined input matrix <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{X}" alt="">containing token embeddings and positional encoding is projected into three learned representations called <strong>query</strong>, <strong>key</strong> and <strong>value</strong> as,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\mathbf{Q}=\mathbf{X}\mathbf{W}^{Q} \\
\mathbf{K}=\mathbf{X}\mathbf{W}^{K} \\
\mathbf{V}=\mathbf{X}\mathbf{W}^{V}


" alt="">



<p class="wp-block-paragraph">where, the learned matrices <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{W}^{Q}" alt="">, <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{W}^{K}" alt=""> and <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{W}^{V}" alt=""> project the token embeddings into different representation spaces.</p>



<p class="wp-block-paragraph">Broadly,</p>



<ul class="wp-block-list">
<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{Q}" alt=""> (<strong>query</strong>) captures what information a token is searching for</li>



<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{K}" alt=""> (<strong>key</strong>) captures what information a token contains</li>



<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{V}" alt=""> (<strong>value</strong>) contains the information passed forward to the next layer</li>
</ul>



<p class="wp-block-paragraph">The interaction between every pair of tokens is computed through the query-key similarity matrix,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\mathbf{S}
=
\mathbf{Q}\mathbf{K}^{T}
" alt="">



<p class="wp-block-paragraph">where the element <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?S_{i,j}" alt=""> measures how strongly token <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?i" alt=""> attends to token <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?j" alt="">,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
S_{i,j}
=
Q_iK_j^T
" alt="">



<p class="wp-block-paragraph">The interaction score is normalized by the key dimension and converted into attention weights using <strong>softmax</strong> <sup>(refer post<a href="https://dsplog.com/2025/06/22/gradients-for-multi-class-classification-with-softmax/#Softmax_layer"> Gradients for multi class classification with Softmax</a>)</sup>,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\mathbf{A}
=
\mathrm{softmax}
\left(
\frac{
\mathbf{Q}\mathbf{K}^{T}
}
{\sqrt{D_h}}
\right)
" alt="">



<p class="wp-block-paragraph">The output of the attention layer is computed as,</p>



<p class="wp-block-paragraph"></p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\mathbf{Y}
=
\mathrm{softmax}
\left(
\frac{
\mathbf{Q}\mathbf{K}^{T}
}
{\sqrt{D_h}}
\right)
\mathbf{V}
" alt="">



<p class="wp-block-paragraph">Each token representation is updated by <strong>aggregating information</strong> from all other tokens in the sequence.</p>



<h3 class="wp-block-heading">Multi-head attention</h3>



<p class="wp-block-paragraph">Instead of using a single attention computation, transformer architecture employs <strong>multiple attention heads</strong>, where each head learns different relationships between tokens.</p>



<p class="wp-block-paragraph">For attention head <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?h" alt="">, the query, key and value projections are computed as,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\mathbf{Q}_h = \mathbf{X}\mathbf{W}_h^Q \\
\mathbf{K}_h = \mathbf{X}\mathbf{W}_h^K \\
\mathbf{V}_h = \mathbf{X}\mathbf{W}_h^V

" alt="">



<p class="wp-block-paragraph">Each head independently computes self-attention as,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\mathbf{Y}_h
=
\mathrm{softmax}
\left(
\frac{
\mathbf{Q}_h
\mathbf{K}_h^T
}
{\sqrt{D_h}}
\right)
\mathbf{V}_h
" alt="">



<p class="wp-block-paragraph">The outputs of all heads are concatenated and projected as,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\mathbf{Y}
=
\mathrm{Concat}
(
\mathbf{Y}_1,
\mathbf{Y}_2,
\cdots,
\mathbf{Y}_H
)
\mathbf{W}^{O}
" alt="">



<p class="wp-block-paragraph">where <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?H" alt=""> denotes the number of attention heads.</p>



<p class="wp-block-paragraph">Using multiple attention heads enables the model to simultaneously learn different relationships such as local context, long-range dependencies, syntax and semantics.</p>



<h3 class="wp-block-heading">Stacking multiple transformer layers</h3>



<p class="wp-block-paragraph">The <strong>first</strong> layer takes the position encoded token embeddings as input,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\mathbf{X}^{(0)}
=
\mathbf{E}
+
\mathbf{P}
" alt="">



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">The transformer architecture consists of <strong>multiple stacked attention layers</strong>. The output of one layer is passed as the input to the next layer, progressively refining the token representations.</p>



<p class="wp-block-paragraph">If the input to layer <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?l" alt=""> is <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{X}^{(l)}" alt="">, then the output of the transformer block is defined as,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\mathbf{X}^{(l+1)}
=
f^{(l)}
\left(
\mathbf{X}^{(l)}
\right)
" alt="">



<p class="wp-block-paragraph">where <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?f^{(l)}(\cdot)" alt=""> denotes the transformer block consisting of </p>



<ul class="wp-block-list">
<li><strong>multi-head self-attention</strong>, </li>



<li><strong>feed-forward network</strong>, </li>



<li><strong>residual connections</strong> <sup>(refer paper <a href="https://arxiv.org/pdf/1512.03385" target="_blank" rel="noopener">Deep Residual Learning for Image Recognition</a>, He et al 2015)</sup> and</li>



<li><strong>layer normalization</strong> <sup>(refer paper <a href="https://arxiv.org/pdf/1607.06450" target="_blank" rel="noopener">Layer Normalization</a>, Lei Ba et al 2016)</sup></li>



<li></li>
</ul>



<p class="wp-block-paragraph">Expanding the operations,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{lll}

\mathbf{Z}^{(l)}
&#038; = &#038;
\mathrm{LayerNorm}
\left(
\mathbf{X}^{(l)}
+
\mathrm{MHA}
\left(
\mathbf{X}^{(l)}
\right)
\right)
\\
\\

\mathbf{X}^{(l+1)}
&#038; = &#038;
\mathrm{LayerNorm}
\left(
\mathbf{Z}^{(l)}
+
\mathrm{FFN}
\left(
\mathbf{Z}^{(l)}
\right)
\right)

\end{array}
" alt="">



<p class="wp-block-paragraph">where,</p>



<ul class="wp-block-list">
<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathrm{MHA}(\cdot)" alt=""> denotes the multi-head attention operation</li>



<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathrm{FFN}(\cdot)" alt=""> denotes the position-wise feed-forward network (see </li>



<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathrm{LayerNorm}(\cdot)" alt=""> denotes layer normalization</li>
</ul>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">After <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?L" alt=""> stacked transformer layers, the final representation becomes,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\mathbf{X}^{(L)}
=
f^{(L-1)} \Big( f^{(L-2)} ( \cdots  f^{(0)} ( \mathbf{X}^{(0)} )) \Big)
" alt="">



<p class="wp-block-paragraph"></p>



<h2 class="wp-block-heading">Parameters in Sinusoidal Positional Encoding</h2>



<p class="wp-block-paragraph">In the additive sinusoidal Positional encoding described in the previous section, authors makes several key design choices, namely </p>



<ul class="wp-block-list">
<li>sinusoidal basis functions </li>



<li>Exponentially spaced frequencies</li>



<li>Emperically chosen base frequency</li>
</ul>



<p class="wp-block-paragraph">In the rest of the section, let us explore the intuitions and rationale behind some of the choices. </p>



<h3 class="wp-block-heading">Need for sinusoidal basis function </h3>



<p class="wp-block-paragraph">To understand the rationale <strong>for sine and cosine terms</strong> in positional embedding, let us consider the input to the attention block for a token at <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?n+k" alt="">,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
X_{n+k} = E_{n+k} + P_{n+k}
" alt="">



<p class="wp-block-paragraph">In the attention layer, the <strong>interaction</strong> between two tokens at position <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?n" alt=""> and <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?n+k" alt=""> is computed as,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
$$\text{Score} = (X_n W^Q) \cdot (X_{n+k} W^K)^T$$" alt="">



<p class="wp-block-paragraph">Assuming that the terms <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?W^Q" alt=""> and <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?W^K" alt="">are identity matrices, the score can be approximated as, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{lll}
\text{Score} 
&#038; = &#038; (X_n W^Q) \cdot (X_{n+k} W^K)^T \\
&#038; \approx &#038; (X_n) \cdot (X_{n+k} )^T\\
&#038; \approx &#038; (E_n + P_n) \cdot (E_{n+k} + P_{n+k} )^T \\
&#038; \approx &#038; 
\underbrace{E_n\cdot E_{n+k}^T}_{\text{content}} 
+ 
\underbrace{E_n\cdot P_{n+k}^T + P_n\cdot E_{n+k}^T}_{\text{content position}}
+ 
\underbrace{P_n\cdot P_{n+k}^T}_{\text{position} }

\end{array}
" alt="">



<p class="wp-block-paragraph">Taking the position interaction term, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{lll}
P_nP_{n+k}^T 
&#038;=&#038;
\begin{bmatrix} 
\sin(\omega_0 n) \\ 
\cos(\omega_0 n) \\ 
\sin(\omega_1 n) \\ 
\cos(\omega_1 n) \\ 
\vdots \\ 
\sin(\omega_{\frac{D}{2}-1} n) \\
\cos(\omega_{\frac{D}{2}-1} n) 
\end{bmatrix}^T 

\begin{bmatrix} 
\sin(\omega_0 (n+k)) \\ 
\cos(\omega_0 (n+k)) \\ 
\sin(\omega_1 (n+k)) \\ 
\cos(\omega_1 (n+k)) \\ 
\vdots \\ 
\sin(\omega_{\frac{D}{2}-1} (n+k)) \\
\cos(\omega_{\frac{D}{2}-1} (n+k)) 
\end{bmatrix}


\\
&#038; = &#038;  
\sin(\omega_0 n)\sin(\omega_0 (n+k)) +  
\cos(\omega_0 n) \cos(\omega_0 (n+k)) + \\
&#038;&#038;
\sin(\omega_1 n)\sin(\omega_1 (n+k)) +  
\cos(\omega_1 n) \cos(\omega_1 (n+k)) +  \cdots
\\
&#038;&#038;
\sin(\omega_{\frac{D}{2}-1} n)\sin(\omega_{\frac{D}{2}-1} (n+k)) +  
\cos(\omega_{\frac{D}{2}-1} n) \cos(\omega_{\frac{D}{2}-1} (n+k))  \\



\end{array}
" alt="">



<p class="wp-block-paragraph">Applying the trignometric identity,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\sin(A)\sin(B) + \cos(A)\cos(B) =\cos(A-B), \\
\begin{array}{lll}
\sin(\omega_0 n)\sin(\omega_0 {n+k}) +  
\cos(\omega_0 n) \cos(\omega_0 {n+k})
&#038; = &#038;  \cos(\omega_0 n - \omega_0 ({n+k})) \\
&#038; = &#038; \cos(-\omega_0 k) \\
&#038; = &#038; \cos(\omega_0 k) \\
\end{array}
"
alt="">



<p class="wp-block-paragraph">the position interaction term simplifies to</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{lll}
P_nP_{n+k}^T 
&#038; = &#038; \cos(\omega_0k) + \cos(\omega_1k) + \cdots + \cos(\omega_{\frac{D}{2}-1}k) \\
&#038; = &#038; \sum_{i=0}^{\frac{D}{2}-1}\cos(\omega_ik)


\end{array}
" alt="">



<p class="wp-block-paragraph">The<strong> position interaction term</strong> depends <strong>only on the relative distance</strong> between the tokens <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?k" alt="">.</p>



<p class="wp-block-paragraph">The choice of using sine and cosine terms in the position encoding, leverages the sinusoidal identity <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\sin(A)\sin(B) + \cos(A)\cos(B) =\cos(A-B)" alt=""> makes the position interaction term <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?P_nP_{n+k}^T" alt=""> to a <strong>decaying function</strong> which depends only on the <strong>relative distance</strong> <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?k" alt=""> between tokens.</p>



<h3 class="wp-block-heading">Normalized positional encoding terms</h3>



<p class="wp-block-paragraph">Let us define the normalized position interaction terms as</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{lll}
R(k) &#038; = &#038; \frac{2}{D}\(P_nP_{n+k}^T\) 
&#038; = &#038; \frac{2}{D}\sum_{i=0}^{\frac{D}{2}-1}\cos(\omega_ik)


\end{array}
" alt="">



<p class="wp-block-paragraph">Plot of the normalized positional encoding terms</p>



<figure class="wp-block-image size-full"><a href="https://dsplog.com/db-install/wp-content/uploads/2026/04/image-1.png"><img fetchpriority="high" decoding="async" width="773" height="371" src="https://dsplog.com/db-install/wp-content/uploads/2026/04/image-1.png" alt="" class="wp-image-2966" srcset="https://dsplog.com/db-install/wp-content/uploads/2026/04/image-1.png 773w, https://dsplog.com/db-install/wp-content/uploads/2026/04/image-1-300x144.png 300w, https://dsplog.com/db-install/wp-content/uploads/2026/04/image-1-768x369.png 768w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px" /></a></figure>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">code @ <a href="https://github.com/dsplog/dsplog.com/blob/main/code/positional_encoding/autocorrelation_positional_encoding.ipynb" target="_blank" rel="noreferrer noopener">positional_encoding/autocorrelation_positional_encoding.ipynb</a></p>



<iframe src="https://nbviewer.org/github/dsplog/dsplog.com/blob/main/code/positional_encoding/autocorrelation_positional_encoding.ipynb?flush_cache=false" width="100%" height="600"></iframe>



<p class="wp-block-paragraph">Can see that <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?R(k)" alt="">, which captures the <strong>relative positional similarity</strong> (autocorrelation of positional encoding), exhibits an <strong>overall decaying envelope</strong> as the distance increases due to multiple frequency components being <strong>out of phase</strong>. The overall decaying trend indirectly encodes information about the relative distance between tokens.</p>



<h3 class="wp-block-heading">Need for multiple frequencies</h3>



<p class="wp-block-paragraph">In the position encoding, multiple frequencies are chosen for various dimension as </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{lll}
PE_{n,2i} &#038; = &#038; \sin\(w_i n\) \\
PE_{n,2i+1} &#038; = &#038; \cos\(w_i n\) \\
\end{array}

" alt="">



<p class="wp-block-paragraph">where, the frequencies are spaced exponentially as</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi? \omega_i = \frac{1}{10000^{\frac{2i}{D}}} " alt="">



<p class="wp-block-paragraph">If only a <strong>single frequency </strong>is chosen, the relative position encoding term becomes <strong>periodic</strong>. This means different relative distance can produce identical positional similarities which <strong>causes ambiguity</strong>. Plotting the normalised positional similarity term for different number of frequency counts, can see that :</p>



<ul class="wp-block-list">
<li>with few frequencies (low D) : stronger oscillations</li>



<li>with more frequencies (higher D) : smoother decay</li>
</ul>



<figure class="wp-block-image size-full"><a href="https://dsplog.com/db-install/wp-content/uploads/2026/04/image.png"><img decoding="async" width="778" height="383" src="https://dsplog.com/db-install/wp-content/uploads/2026/04/image.png" alt="" class="wp-image-2960" srcset="https://dsplog.com/db-install/wp-content/uploads/2026/04/image.png 778w, https://dsplog.com/db-install/wp-content/uploads/2026/04/image-300x148.png 300w, https://dsplog.com/db-install/wp-content/uploads/2026/04/image-768x378.png 768w" sizes="(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px" /></a></figure>



<p class="wp-block-paragraph">Summarising, by combining multiple frequencies, the broad intuition is : </p>



<ul class="wp-block-list">
<li><strong>high frequencies</strong> capture <strong>local relative distances</strong></li>



<li><strong>low frequencies</strong> capture the <strong>long range distances</strong></li>
</ul>



<p class="wp-block-paragraph">Together, they increase the probability of each relative distance having a unique signature enabling the model to distinguish near by and far away tokens. </p>



<p class="wp-block-paragraph">code @ <a href="https://github.com/dsplog/dsplog.com/blob/main/code/positional_encoding/multiple_frequencies_positional_encoding.ipynb">positional_encoding/multiple_frequencies_positional_encoding.ipynb</a></p>



<iframe loading="lazy" src="https://nbviewer.org/github/dsplog/dsplog.com/blob/main/code/positional_encoding/multiple_frequencies_positional_encoding.ipynb?flush_cache=false" width="100%" height="600"></iframe>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">Thus, the use of <strong>multiple exponentially</strong> spaced frequencies allows the model to encode position as a <strong>combination of signals at different scales</strong>, enabling robust representation of both <strong>local and global structure</strong>.</p>



<h3 class="wp-block-heading">The choice of the constant 10,000</h3>



<p class="wp-block-paragraph">The choice of <strong>10,000 </strong>as the base in the <strong>geometric progression of frequencies</strong> was an empirical engineering decision.</p>



<p class="wp-block-paragraph">The positional encoding uses frequencies</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\omega_i=\frac{1}{10000^{\frac{2i}{D}}}" alt="">



<p class="wp-block-paragraph">which span from high-frequency components (short wavelengths) to low-frequency components (long wavelengths).</p>



<p class="wp-block-paragraph"><strong>a) At</strong> <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?i=0" alt=""> <strong>(shortest wavelength):</strong></p>



<p class="wp-block-paragraph">The angular frequency is <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\omega_0=1" alt="">, giving a wavelength of</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\lambda_0=\frac{2\pi}{\omega_0}=2\pi\approx 6.28" alt="">



<p class="wp-block-paragraph">This <strong>short wavelength changes rapidly across nearby positions</strong>, helping the model distinguish tokens that are close to each other.</p>



<p class="wp-block-paragraph"><strong>b) At</strong> <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?i=\frac{D}{2}-1" alt=""> <strong>(longest wavelength):</strong></p>



<p class="wp-block-paragraph">The angular frequency is approximately</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\omega_{\frac{D}{2}-1}\approx\frac{1}{10000}" alt="">



<p class="wp-block-paragraph">giving a wavelength of</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\lambda_{\frac{D}{2}-1}\approx 2\pi\cdot 10000" alt="">



<p class="wp-block-paragraph">This<strong> long wavelength varies slowly across position</strong>s, helping the model encode coarse distinctions between tokens that are far apart.</p>



<p class="wp-block-paragraph">Thus, the choice of 10,000 creates a spectrum of frequencies that provides both local positional resolution and long-range positional awareness.</p>



<p class="wp-block-paragraph">The plot of autocorrelation of positional encoding for different base frequencies of 1000, 10000 (default) and 100000 is below. </p>



<figure class="wp-block-image size-full"><a href="https://dsplog.com/db-install/wp-content/uploads/2026/05/image.png"><img loading="lazy" decoding="async" width="849" height="414" src="https://dsplog.com/db-install/wp-content/uploads/2026/05/image.png" alt="" class="wp-image-2970" srcset="https://dsplog.com/db-install/wp-content/uploads/2026/05/image.png 849w, https://dsplog.com/db-install/wp-content/uploads/2026/05/image-300x146.png 300w, https://dsplog.com/db-install/wp-content/uploads/2026/05/image-768x375.png 768w" sizes="auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px" /></a></figure>



<p class="wp-block-paragraph">Based on the <strong>autocorrelation plot</strong>, handwaving explanation for the choice of the base frequency, and on hindsight that typical sequence lengths around the 2017 ish were around <strong>512 tokens</strong>,</p>



<ul class="wp-block-list">
<li>With a base of <strong>1000</strong>, the relative positional similarity decays more rapidly, dropping below about <strong>0.2</strong> at a relative distance near <strong>100 tokens</strong>. </li>



<li>With a base of <strong>10,000</strong>, the decay is slower, and the same similarity threshold is reached only around <strong>600 tokens</strong>. </li>



<li>When the base is increased further to <strong>100,000</strong>, the decay becomes even slower, but the lower slope reduces the separation of tokens which are close by.</li>
</ul>



<p class="wp-block-paragraph">So, a base of <strong>10,000</strong> appears to be a practical compromise between distinguishing <strong>nearby tokens and retaining information across the full training context</strong>.</p>



<p class="wp-block-paragraph">Code @ <a href="https://github.com/dsplog/dsplog.com/blob/main/code/positional_encoding/base_frequency_positional_encoding.ipynb">positional_encoding/base_frequency_positional_encoding.ipynb</a></p>



<iframe loading="lazy" src="https://nbviewer.org/github/dsplog/dsplog.com/blob/main/code/positional_encoding/base_frequency_positional_encoding.ipynb?flush_cache=false" width="100%" height="600"></iframe>



<p class="wp-block-paragraph"></p>



<h1 class="wp-block-heading">RoPE &#8211; Rotary Positional Encoding (Su et al., 2021)</h1>



<p class="wp-block-paragraph">In the paper <a href="RoFormer: Enhanced Transformer with Rotary Position Embedding">RoFormer: Enhanced Transformer with Rotary Position Embedding</a>&#8220;Su et. al 2021, the authors proposed a <strong>multiplicative approach</strong> for <strong>positional encoding i</strong>nstead of the <strong>additive approach </strong>for sinusoidal positional encoding.</p>



<p class="wp-block-paragraph">The token embedding be of dimension <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?D" alt="">, and defined as : <br></p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}
E_n = 
\begin{bmatrix} 
e_{n,0} \\ 
e_{n,1} \\ 
e_{n,2} \\ 
e_{n,3} \\ 
\vdots \\ 
e_{n,D-1} 
\end{bmatrix}
\end{array}
" alt="">



<p class="wp-block-paragraph">The token embedding at position <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?n" alt=""> is grouped into <strong>adjacent dimension pairs</strong>, i.e . <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?(e_{n,2i},e_{n,2i+1})" alt="">. The token embedding at position <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?n" alt=""> is first projected into query and key representations using learned projection matrices <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?W^Q" alt=""> and <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?W^K" alt="">.</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
Q_n = W^Q E_n \\
K_n = W^K E_n
" alt="">



<p class="wp-block-paragraph">The query and key vectors are then grouped into adjacent dimension pairs, i.e., <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?(q_{n,2i},q_{n,2i+1})" alt=""> and <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?(k_{n,2i},k_{n,2i+1})" alt=""> . </p>



<p class="wp-block-paragraph">The rotation matrix for the <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?i^{th}" alt=""> pair is defined as</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}
R_i(n) =  
\begin{bmatrix}
\cos(\omega_in) &#038; -\sin(\omega_in)\\
\sin(\omega_in) &#038; \cos(\omega_in)\\
\end{bmatrix}
\end{array}
" alt="">



<p class="wp-block-paragraph">where, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\omega_i = \frac{1}{10000^{\frac{2i}{D}}}
" alt="">



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">The <strong>complete rotation matrix</strong> for positional encoding is formed by stacking these 2&#215;2 rotation blocks across the diagonal, where each 2×2 block rotates a pair of embedding dimensions with a <strong>different angular frequency</strong>.</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
R_n =
\mathrm{diag}\left(
R_0(n), R_1(n), \cdots, R_{\frac{D}{2}-1}(n)
\right)" alt="">



<p class="wp-block-paragraph">The rotary positional encoding is then applied to the query and key vectors as, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\tilde{Q}_n = R_n Q_n \\
\tilde{K}_n = R_n K_n

" alt="">



<p class="wp-block-paragraph">Expanding the matrices for <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\tilde{Q}_n " alt=""> ,</p>



<p class="wp-block-paragraph"></p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{lll}

\tilde{Q}_n 
&amp; = &amp; R_n\cdot Q_n \\
\\

&amp; = &amp; \begin{bmatrix}

\cos(\omega_0 n) &amp; -\sin(\omega_0 n) &amp; 0 &amp; 0 &amp; \cdots &amp; 0 &amp; 0 \\
\sin(\omega_0 n) &amp; \cos(\omega_0 n)  &amp; 0 &amp; 0 &amp; \cdots &amp; 0 &amp; 0 \\

0 &amp; 0 &amp;
\cos(\omega_1 n) &amp; -\sin(\omega_1 n) &amp; \cdots &amp; 0 &amp; 0 \\

0 &amp; 0 &amp;
\sin(\omega_1 n) &amp; \cos(\omega_1 n) &amp; \cdots &amp; 0 &amp; 0 \\

\vdots &amp; \vdots &amp; \vdots &amp; \vdots &amp; \ddots &amp; \vdots &amp; \vdots \\

0 &amp; 0 &amp; 0 &amp; 0 &amp; \cdots &amp;
\cos(\omega_{\frac{D}{2}-1} n) &amp;
-\sin(\omega_{\frac{D}{2}-1} n) \\

0 &amp; 0 &amp; 0 &amp; 0 &amp; \cdots &amp;
\sin(\omega_{\frac{D}{2}-1} n) &amp;
\cos(\omega_{\frac{D}{2}-1} n)

\end{bmatrix}

\begin{bmatrix}

q_{n,0} \\
q_{n,1} \\
q_{n,2} \\
q_{n,3} \\
\vdots \\
q_{n,D-2} \\
q_{n,D-1}

\end{bmatrix}

\\
\\

&amp; = &amp;

\begin{bmatrix}

q_{n,0}\cos(\omega_0 n)-q_{n,1}\sin(\omega_0 n)
\\

q_{n,0}\sin(\omega_0 n)+q_{n,1}\cos(\omega_0 n)
\\

q_{n,2}\cos(\omega_1 n)-q_{n,3}\sin(\omega_1 n)
\\

q_{n,2}\sin(\omega_1 n)+q_{n,3}\cos(\omega_1 n)
\\

\vdots
\\

q_{n,D-2}\cos(\omega_{\frac{D}{2}-1} n)
-
q_{n,D-1}\sin(\omega_{\frac{D}{2}-1} n)
\\

q_{n,D-2}\sin(\omega_{\frac{D}{2}-1} n)
+
q_{n,D-1}\cos(\omega_{\frac{D}{2}-1} n)

\end{bmatrix}

\end{array}
" alt="">



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">Similarly, the rotated query and key vectors for the token at position <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?n+k" alt=""> are defined as</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\tilde{Q}_{n+k} = R_{n+k} Q_{n+k} \\
\tilde{K}_{n+k} = R_{n+k} K_{n+k}

" alt="">



<p class="wp-block-paragraph">Note :</p>



<p class="wp-block-paragraph">Unlike<strong> sinusoidal positional encoding</strong>, which is added <strong>once to the input embeddings</strong>, RoPE is <strong>applied inside the self-attention block</strong> by rotating the query and key vectors. Since each transformer layer contains a self-attention block, the <strong>rotation operation is applied at every attention laye</strong>r of the transformer architecture.</p>



<h2 class="wp-block-heading">Interaction terms</h2>



<p class="wp-block-paragraph">In the attention layer, the <strong>interaction between two tokens</strong> at position <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?n" alt=""> and <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?n+k" alt=""> is computed as </p>



<p class="wp-block-paragraph"><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\tilde{Q}n
\tilde{K}^{T}_{n+k} = (R_nQ_n)
(R_{n+k}K^T_{n+k})" alt=""> .</p>



<p class="wp-block-paragraph">For intuition, assuming that the terms <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?W^Q" alt=""> and <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?W^K" alt="">are identity matrices. Then the query and key terms simplify to </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
Q_n \approx E_n \\
K_n \approx E_n
"
alt="">



<p class="wp-block-paragraph">With this assumption, the <strong>score is approximated</strong> as,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\text{Score}
\approx
(R_nE_n)
(R_{n+k}E_{n+k})^T

" alt="">



<p class="wp-block-paragraph">Expanding the terms,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{lll}

\mathrm{Score}

\\

&amp; = &amp;

\begin{bmatrix}

e_{n,0}\cos(\omega_0 n)-e_{n,1}\sin(\omega_0 n)
\\

e_{n,0}\sin(\omega_0 n)+e_{n,1}\cos(\omega_0 n)
\\

e_{n,2}\cos(\omega_1 n)-e_{n,3}\sin(\omega_1 n)
\\

e_{n,2}\sin(\omega_1 n)+e_{n,3}\cos(\omega_1 n)
\\

\vdots
\\

e_{n,D-2}\cos(\omega_{\frac{D}{2}-1} n)
-
e_{n,D-1}\sin(\omega_{\frac{D}{2}-1} n)
\\

e_{n,D-2}\sin(\omega_{\frac{D}{2}-1} n)
+
e_{n,D-1}\cos(\omega_{\frac{D}{2}-1} n)

\end{bmatrix}^{T}

\begin{bmatrix}

e_{n+k,0}\cos(\omega_0 (n+k))
-
e_{n+k,1}\sin(\omega_0 (n+k))
\\

e_{n+k,0}\sin(\omega_0 (n+k))
+
e_{n+k,1}\cos(\omega_0 (n+k))
\\

e_{n+k,2}\cos(\omega_1 (n+k))
-
e_{n+k,3}\sin(\omega_1 (n+k))
\\

e_{n+k,2}\sin(\omega_1 (n+k))
+
e_{n+k,3}\cos(\omega_1 (n+k))
\\

\vdots
\\

e_{n+k,D-2}\cos(\omega_{\frac{D}{2}-1}(n+k))
-
e_{n+k,D-1}\sin(\omega_{\frac{D}{2}-1}(n+k))
\\

e_{n+k,D-2}\sin(\omega_{\frac{D}{2}-1}(n+k))
+
e_{n+k,D-1}\cos(\omega_{\frac{D}{2}-1}(n+k))

\end{bmatrix}

\end{array}
" alt="">



<p class="wp-block-paragraph">Let us find the score consider onlying the first frequency pair <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\omega_0" alt="">,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{lll}

Score_0
&#038; = &#038;

\Big(
e_{n,0}\cos(\omega_0 n)
-
e_{n,1}\sin(\omega_0 n)
\Big)

\Big(
e_{n+k,0}\cos(\omega_0(n+k))
-
e_{n+k,1}\sin(\omega_0(n+k))
\Big)
\\
\\

&#038;&#038;+

\Big(
e_{n,0}\sin(\omega_0 n)
+
e_{n,1}\cos(\omega_0 n)
\Big)

\Big(
e_{n+k,0}\sin(\omega_0(n+k))
+
e_{n+k,1}\cos(\omega_0(n+k))
\Big)

\end{array}
" alt="">



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">Expanding the multiplication terms,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{lll}

\mathrm{Score}_0

&#038; = &#038;

e_{n,0}e_{n+k,0}
\cos(\omega_0 n)
\cos(\omega_0(n+k))

\\
&#038;&#038;

-
e_{n,0}e_{n+k,1}
\cos(\omega_0 n)
\sin(\omega_0(n+k))

\\
&#038;&#038;

-
e_{n,1}e_{n+k,0}
\sin(\omega_0 n)
\cos(\omega_0(n+k))

\\
&#038;&#038;

+
e_{n,1}e_{n+k,1}
\sin(\omega_0 n)
\sin(\omega_0(n+k))

\\
&#038;&#038;

+
e_{n,0}e_{n+k,0}
\sin(\omega_0 n)
\sin(\omega_0(n+k))

\\
&#038;&#038;

+
e_{n,1}e_{n+k,0}
\cos(\omega_0 n)
\sin(\omega_0(n+k))

\\
&#038;&#038;

+
e_{n,0}e_{n+k,1}
\sin(\omega_0 n)
\cos(\omega_0(n+k))

\\
&#038;&#038;

+
e_{n,1}e_{n+k,1}
\cos(\omega_0 n)
\cos(\omega_0(n+k))

\end{array}
" alt="">



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">Grouping common terms, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{lll}

Score_0
&#038; = &#038;

e_{n,0}e_{n+k,0}
\Big[
\cos(\omega_0 n)
\cos(\omega_0(n+k))
+
\sin(\omega_0 n)
\sin(\omega_0(n+k))
\Big]
\\
\\

&#038;&#038;+

e_{n,1}e_{n+k,1}
\Big[
\sin(\omega_0 n)
\sin(\omega_0(n+k))
+
\cos(\omega_0 n)
\cos(\omega_0(n+k))
\Big]
\\
\\

&#038;&#038;+

\Big(
e_{n,1}e_{n+k,0}
-
e_{n,0}e_{n+k,1}
\Big)

\Big[
\sin(\omega_0 n)
\cos(\omega_0(n+k))
-
\cos(\omega_0 n)
\sin(\omega_0(n+k))
\Big]

\end{array}
" alt="">



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">Applying the trigonometric identities,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\cos(A)\cos(B)+\sin(A)\sin(B)=\cos(A-B) \\
\sin(A)\cos(B)-\cos(A)\sin(B)=\sin(A-B)

" alt="">



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">the interaction term corresponding to the frequency <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\omega_0" alt=""> becomes</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{lll}

Score_0
&#038; = &#038;

e_{n,0}e_{n+k,0}
\cos\Big(
\omega_0 n
-
\omega_0(n+k)
\Big)
\\
\\

&#038;&#038;+

e_{n,1}e_{n+k,1}
\cos\Big(
\omega_0 n
-
\omega_0(n+k)
\Big)
\\
\\

&#038;&#038;+

\Big(
e_{n,1}e_{n+k,0}
-
e_{n,0}e_{n+k,1}
\Big)

\sin\Big(
\omega_0 n
-
\omega_0(n+k)
\Big)
\\

&#038;=&#038;
e_{n,0}e_{n+k,0}
\cos(-\omega_0 k)
\\
\\

&#038;&#038;+

e_{n,1}e_{n+k,1}
\cos(-\omega_0 k)
\\
\\

&#038;&#038;+

\Big(
e_{n,1}e_{n+k,0}
-
e_{n,0}e_{n+k,1}
\Big)

\sin(-\omega_0 k)

\end{array}
" alt="">



<p class="wp-block-paragraph">Since <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\cos(-x) = \cos(x)" alt=""> and <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\sin(-x) = -\sin(x)" alt="">, the term simplifies to  </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{lll}

Score_0
&#038; = &#038;

\Big(e_{n,0}e_{n+k,0}
+
e_{n,1}e_{n+k,1}
\Big)
\cos(\omega_0 k)
\\
\\

&#038;&#038;

\Big(
e_{n,0}e_{n+k,1}
-

e_{n,1}e_{n+k,0}
\Big)

\sin(\omega_0 k)

\end{array}
" alt="">



<p class="wp-block-paragraph">Notice the key result that <strong>sine and cosine terms depend only on <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi? k" alt=""></strong>, and hence the interaction term depends only on the <strong>relative distance</strong>.</p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">Extending for all frequencies, for the frequency pair <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\omega_i" alt="">, the interaction term becomes</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{lll}

Score_i
&#038; = &#038;

\Big(
e_{n,2i}e_{n+k,2i}
+
e_{n,2i+1}e_{n+k,2i+1}
\Big)
\cos(\omega_i k)
\\
\\

&#038;&#038;+

\Big(
e_{n,2i}e_{n+k,2i+1}
-
e_{n,2i+1}e_{n+k,2i}
\Big)
\sin(\omega_i k)

\end{array}
" alt="">



<p class="wp-block-paragraph">Summing across all frequency pairs, the overall interaction score becomes</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{lll}

\mathrm{Score}
&#038; = &#038;
X_n^T X_{n+k}
\\
\\

&#038; = &#038;
\sum_{i=0}^{\frac{D}{2}-1}
Score_i
\\
\\

&#038; = &#038;
\sum_{i=0}^{\frac{D}{2}-1}
\Big[
\Big(
e_{n,2i}e_{n+k,2i}
+
e_{n,2i+1}e_{n+k,2i+1}
\Big)
\cos(\omega_i k)
\\
\\

&#038;&#038;\qquad +

\Big(
e_{n,2i}e_{n+k,2i+1}
-
e_{n,2i+1}e_{n+k,2i}
\Big)
\sin(\omega_i k)

\Big]

\end{array}
" alt="">



<p class="wp-block-paragraph">Similar to the <strong>additive positional encoding </strong>defined earlier, the <strong>interaction term </strong>in<strong> multiplicative positional encoding</strong> defined in <strong>RoPE</strong> also depends only on the <strong>relative distance </strong>between tokens <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?k" alt="">.</p>



<p class="wp-block-paragraph">However, <strong>unlike additive sinusoidal positional</strong> encoding, multiplicative positional encoding in <strong>RoPE does not </strong>introduce<strong> token-position cross interaction terms</strong> such as <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?E_n\cdot P_{n+k}^T, \ P_n\cdot E_{n+k}^T" alt=""> . </p>



<p class="wp-block-paragraph"></p>



<h2 class="wp-block-heading">Complex Number Interpretation</h2>



<p class="wp-block-paragraph">The <strong>derivation</strong> for rotary positional encoding using explicit matrix multiplication can be expressed <strong>compactly</strong> using<strong> complex numbers</strong>.  The token embedding at position <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?n" alt=""> is grouped into <strong>adjacent dimension pairs</strong>, i.e. <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?(e_{n,2i},e_{n,2i+1})" alt="">, where each pair can be represented as a <strong>complex number</strong></p>



<p class="wp-block-paragraph"></p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
e'_{n,i}
=
e_{n,2i}
+
j\,e_{n,2i+1}
" alt="">



<p class="wp-block-paragraph">where,</p>



<p class="wp-block-paragraph"><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?j=\sqrt{-1}" alt=""> is the imaginary unit.</p>



<p class="wp-block-paragraph">The <strong>rotary positional encoding</strong> is applied as a <strong>complex phase rotation</strong>,</p>



<p class="wp-block-paragraph"></p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
R_i(n) =  \exp^{j\cdot \omega_in} = \cos(\omega_in) + j\cdot \sin(\omega_in)
" alt=""/>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">Thus, the rotated embedding becomes,</p>



<p class="wp-block-paragraph"></p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{lll}
x'_{n,i}
&#038; = &#038; e'_{n,i} \cdot R_i(n)\\
&#038; = &#038; (e_{n,2i} + j e_{n,2i+1}) \Big( \cos(\omega_i n) + j\sin(\omega_i n) \Big)
\end{array}
" alt="">



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">Expanding the multiplication terms,</p>



<p class="wp-block-paragraph"></p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{lll}
x'_{n,i}&#038; = &#038;
e_{n,2i}\cos(\omega_i n) + je_{n,2i}\sin(\omega_i n)\\ &#038;&#038;
+j  e_{n,2i+1}\cos(\omega_i n) + j^2 e_{n,2i+1}\sin(\omega_i n)
\end{array}
" alt="">



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">Since <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?j^2=-1" alt="">,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{lll}
x'_{n,i} &#038; = &#038;
\Big( e_{n,2i}\cos(\omega_i n) - e_{n,2i+1}\sin(\omega_i n) \Big) \\
&#038;&#038;+
j \Big( e_{n,2i}\sin(\omega_i n) + e_{n,2i+1}\cos(\omega_i n) \Big)

\end{array}
" alt="">



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">Comparing the <strong>real and imaginary components</strong>, we observe that this is <strong>identical</strong> to the math derived earlier. </p>



<p class="wp-block-paragraph"></p>



<h3 class="wp-block-heading">Interaction terms</h3>



<p class="wp-block-paragraph">In the attention layer, the <strong>interaction</strong> between two rotated token embeddings at positions <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?n" alt=""> and <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?n+k" alt=""> can be written using <strong>complex number</strong> representation.</p>



<p class="wp-block-paragraph">For simplicity, assuming the query and key projection matrices are identity matrices, the rotated embedding pair at frequency <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\omega_i" alt=""> is expressed as</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{lll}
x'_{n,i}
&#038; = &#038;
e'_{n,i} e^{j\omega_i n}
\\
\\

x'_{n+k,i} &#038; = &#038; e'_{n+k,i}  e^{j\omega_i (n+k)}

\end{array}
" alt="">



<p class="wp-block-paragraph">The interaction score is computed using the <strong>complex conjugate</strong> of the <strong>second</strong> term and taking the <strong>real</strong>-valued component of the <strong>output</strong>,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{lll}
\mathrm{Score}_i
&#038; = &#038;
\mathrm{Re}
\Big(x'_{n,i} (x'_{n+k,i})^{*} \Big)
\\
\\
&#038; = &#038;
\mathrm{Re}
\Big(
e'_{n,i}
e^{j\omega_i n}
\Big(
e'_{n+k,i}
e^{j\omega_i(n+k)}
\Big)^*
\Big)

\end{array}
" alt="">



<p class="wp-block-paragraph">with,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\Big( e^{j\omega_i(n+k)} \Big)^* = e^{-j\omega_i(n+k)}
" alt="">



<p class="wp-block-paragraph">the interaction term becomes</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{lll}
\mathrm{Score}_i
&#038; = &#038;
\mathrm{Re} \Big(e'_{n,i}(e'_{n+k,i})^* e^{j\omega_i n} e^{-j\omega_i(n+k)}\Big)
\\
\\
&#038; = &#038;
\mathrm{Re}\Big(e'_{n,i}(e'_{n+k,i})^*e^{-j\omega_i k}\Big)

\end{array}
" alt="">



<p class="wp-block-paragraph">The absolute token position <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?n" alt=""> cancels out, leaving only the relative token distance <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?k" alt="">. </p>



<h3 class="wp-block-heading">Normalized Positional Encoding</h3>



<p class="wp-block-paragraph">Let us define the embedding interaction term as,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?

e'_{n,i}(e'_{n+k,i})^* = A_ie^{j\phi_i}

" alt="">



<p class="wp-block-paragraph">where, </p>



<ul class="wp-block-list">
<li> <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?A_i" alt=""> is the embedding similarity magnitude </li>



<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\phi_i" alt=""> is the embedding dependent phase difference</li>
</ul>



<p class="wp-block-paragraph">To isolate the positional component independent of the token embedding, consider </p>



<ul class="wp-block-list">
<li>embedding interactions are normalized i.e.<img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?A_i \approx 1" alt=""> </li>



<li>embedding interaction phase effects are not there i.e.  <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\phi_i \approx 0" alt=""></li>
</ul>



<p class="wp-block-paragraph">With this the score simplifies to, </p>



<p class="wp-block-paragraph"></p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{lll}
\mathrm{Score}_i
&#038; = &#038;
\mathrm{Re}\Big(e'_{n,i}(e'_{n+k,i})^*e^{-j\omega_i k}\Big)  \\
&#038; = &#038;  \mathrm{Re}\Big(A_ie^{j\phi_i}e^{-j\omega_i k}\Big) \\
&#038; = &#038;  \mathrm{Re}\Big(e^{-j\omega_i k}\Big) \\
&#038; = &#038; \cos(\omega_i k)


\end{array}

" alt="">



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">Then the normalized positional encoding over all the dimensions is, </p>



<p class="wp-block-paragraph"></p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{lll}
R(k) &#038; = &#038; \frac{2}{D}\(P_nP_{n+k}^T\) 
&#038; = &#038; \frac{2}{D}\sum_{i=0}^{\frac{D}{2}-1}\cos(\omega_ik)


\end{array}
" alt="">



<p class="wp-block-paragraph">This is identical to the sinusoidal positional encoding defined earlier. </p>



<h1 class="wp-block-heading">ALiBi &#8211; Attention with Linear Biases, Ofir Press et al 2021</h1>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">In the paper <strong>&#8220;<a href="https://arxiv.org/abs/2108.12409" target="_blank" rel="noopener">Train Short, Test Long: Attention with Linear Biases Enables Input Length Extrapolation</a>, Ofir Press et al 2021&#8243;</strong>, authors note that both <strong>additive sinusoidal positional encoding</strong> and <strong>multiplicative rotary positional encoding (RoPE)</strong> degrade when <strong>evaluated on sequence lengths significantly longer</strong> than those seen during training. <br><br>They also note that <strong>RoPE extrapolates</strong> better than <strong>additive</strong> sinusoidal positional encoding, with potential reasons being : </p>



<ul class="wp-block-list">
<li>rotary positional encoding injects positional information in every layer and not just the initial one as in additive sinusoidal positional encoding</li>



<li>rotary positional encoding is done only on queries (<img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?Q" alt="">) and keys (<img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?K" alt="">) and not to values (<img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?V" alt="">)</li>
</ul>



<p class="wp-block-paragraph">With this <strong>intuition</strong>, authors proposed <strong>Attention with Linear Bias</strong> (<strong>ALiBi</strong>), where a <strong>static non learned bias</strong> is applied to the query key dot product prior to softmax computation.</p>



<h2 class="wp-block-heading">Equations</h2>



<p class="wp-block-paragraph">Consider a sequence of length (<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?L" alt="">). In standard self-attention, the attention score between a query at position (<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?i" alt="">) and a key at position (<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?j" alt="">) is computed as</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\mathrm{softmax(\frac{q_iK^T}{\sqrt{d_k}})
" alt="">



<p class="wp-block-paragraph">where,</p>



<ul class="wp-block-list">
<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?q_i \in \mathbb{R}^{1 \times d_k}" alt=""> is the query at position <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?i" alt="">,</li>



<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?K \in \mathbb{R}^{L \times d_k}" alt="">, and with causal language modelling the first i keys with <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?1 \le i \le L" alt=""> and</li>



<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?d_k" alt=""> is the head dimension</li>
</ul>



<p class="wp-block-paragraph">ALiBi modifies the attention score directly by adding a <strong>position-dependent linear bias</strong> . The modified attention score becomes,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\mathrm softmax(\frac{q_iK^T}{\sqrt{d_k}}
+
m\cdot[-(i-1), \cdots, -2, -1, 0])

" alt="">



<p class="wp-block-paragraph">where, </p>



<ul class="wp-block-list">
<li> <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?m" alt=""> is head specific scalar fixed before training. </li>
</ul>



<ul class="wp-block-list">
<li>for a model with <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?n" alt=""> attention heads, the set of slope is geometrically spaced and starts at  <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?2^{-\frac{8h}{n}}" alt="">.</li>
</ul>



<p class="wp-block-paragraph">The ALiBi paper focused on the <strong>auto-regressive causal language models</strong>, where a query at position <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?i" alt=""> can only attend to the first <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?i" alt=""> keys. Under this causal constraint, the bias term between a query at position <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?i" alt=""> and a key at position <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?j" alt=""> is calculated linearly based on their directed distance:</p>



<p align="center">
<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\text{Bias}(i, j) = -m \cdot (i - j) \qquad \text{where } j \le i" alt="Causal ALiBi Bias Function">
</p>



<p class="wp-block-paragraph">This creates a <strong>lower triangular bias matrix</strong>, with the diagonal elements receive a penalty of 0, and the penalty grows increasingly negative as the key moves further back into the past tokens.</p>



<p class="wp-block-paragraph">This<strong> relative position information</strong> is injected at e<strong>very attention operation across layers </strong>by adding a position dependent bias.</p>



<p class="wp-block-paragraph">toy implementation @ <a href="https://github.com/dsplog/dsplog.com/blob/main/code/positional_encoding/alibi_causal_positional_encoding.ipynb" target="_blank" rel="noreferrer noopener">positional_encoding/alibi_causal_positional_encoding.ipynb</a></p>



<iframe loading="lazy" src="https://nbviewer.org/github/dsplog/dsplog.com/blob/main/code/positional_encoding/alibi_causal_positional_encoding.ipynb?flush_cache=false" width="100%" height="600"></iframe>



<h1 class="wp-block-heading">Extending pre-trained context window</h1>



<p class="wp-block-paragraph">Multiple approaches for extending the pre-trained context length to a higher number has emerged in literature. In the rest of the sections, we cover three approaches &#8211; scaling the token position index, scaling by a frequency dependent factor and a scheme which combines the above approaches. </p>



<h2 class="wp-block-heading">Position Interpolation (Chen et al 2023)</h2>



<p class="wp-block-paragraph">In the paper <strong><em><a href="https://arxiv.org/abs/2306.15595" target="_blank" rel="noopener">Extending Context Window of Large Language Models via Position Interpolation</a></em>, Chen et al 2023</strong>, proposes an approach to<strong> extend the context </strong>window of <strong>RoPE based LLMs</strong> which was trained for typically ~2048 tokens to around 32768 tokens (<strong>16x</strong>).</p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">With <strong>RoPE</strong>, the rotation factor for token at position <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?n" alt=""> along the <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?i" alt=""> the dimension is,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
R_i(n) =  \exp^{j\cdot \omega_in} = \cos(\omega_in) + j\cdot \sin(\omega_in)
" alt="">



<p class="wp-block-paragraph">where, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\omega_i = \frac{1}{10000^{\frac{2i}{D}}}
" alt="">



<p class="wp-block-paragraph">With <strong>Position Interpolation</strong>, the rotation factor for token position <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?n" alt=""> is <strong>scaled</strong> by a factor <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?s=L^'/L" alt="">, to become</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
R^'_i(n) =  \exp^{j\cdot \omega_in\frac{L}{L^'}} = \cos(\omega_in\frac{L}{L^'}) + j\cdot \sin(\omega_in\frac{L}{L^'})
" alt="">



<p class="wp-block-paragraph">where, </p>



<ul class="wp-block-list">
<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?L" alt=""> is the context length for which the model is trained</li>



<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?L^'" alt=""> is the desired context length</li>
</ul>



<p class="wp-block-paragraph"></p>



<h2 class="wp-block-heading">NTK aware scaling (bloc97, 2023)</h2>



<p class="wp-block-paragraph">In the <strong>reddit post</strong> <a href="https://www.reddit.com/r/LocalLLaMA/comments/14lz7j5/ntkaware_scaled_rope_allows_llama_models_to_have/" data-type="link" data-id="https://www.reddit.com/r/LocalLLaMA/comments/14lz7j5/ntkaware_scaled_rope_allows_llama_models_to_have/" target="_blank" rel="noreferrer noopener"><sup>(link here)</sup></a> author <a href="https://www.reddit.com/user/bloc97/" target="_blank" rel="noreferrer noopener">bloc97</a> proposed an <strong>alternate</strong> way to extend to longer context lengths of RoPE based Large Language Models (LLMs). The key intuition comes from <strong>Neural Tangent Kernel (NTK) </strong>perspective of neural networks which suggested that <strong>neural networks are more sensitive</strong> to <strong>distortions</strong> in <strong>high</strong> frequencies than <strong>low</strong> frequency ones.</p>



<p class="wp-block-paragraph">So instead of <strong>uniformly compressing all frequencies</strong> as in <strong>Positional Interpolation (PI)</strong>, NTK aware scaling applies a <strong>frequency dependent scaling</strong>. </p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">This is achieved by by introducing a <strong>frequency dependent</strong> scaling where <strong>highest</strong> frequency dimension <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?i=0" alt=""> is <strong>preserved</strong>, and <strong>progressively</strong> scaling lower frequencies, till reaching the scaling factor <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{1}{s}" alt=""> for the <strong>lowest frequency</strong> <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?i=\frac{D}{2}-1" alt="">.</p>



<h3 class="wp-block-heading">Equations</h3>



<p class="wp-block-paragraph">The base frequency in RoPE is defined as, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\omega_i = \frac{1}{10000^{\frac{2i}{D}}} =10000^{\frac{-2i}{D}}
" alt="">



<p class="wp-block-paragraph">To scale the context window by factor <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?s" alt=""> , the base <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?b=10000" alt=""> is modified as, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
b^'=10000\cdot s^{\frac{D}{D-2}}
" alt="">



<p class="wp-block-paragraph">Substituting, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array} {lll}
\omega_{i,NTK} 
&amp; = &amp; \left(10000\cdot s^{\frac{D}{D-2}}\right)^{\frac{-2i}{D}} \\
&amp; = &amp; {10000}^{\frac{-2i}{D}}\cdot s^{\frac{-2i}{D-2}} \\
&amp; = &amp; \omega_is^{\frac{-2i}{D-2}}
\end{array}
" alt="">



<p class="wp-block-paragraph">For highest frequency (<img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?i=0" alt="">), the scale modifier is <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?s^0=1" alt="">, preserving the high frequency local positional context. </p>



<p class="wp-block-paragraph">For the lowest frequency (<img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?i=\frac{D}{2}-1" alt="">), the scale factor is<img decoding="async" align="abs middle" src="https://dsplog.com/cgi-bin/mimetex.cgi? s^{-\frac{2(\frac{D}{2}-1)}{D-2} = s^{-1}" alt="">, scaling the lowest frequency by the desired scaling factor <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{1}{s}" alt="">. </p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">toy implementation @ </p>



<p class="wp-block-paragraph"><a href="https://github.com/dsplog/dsplog.com/blob/main/code/positional_encoding/pi_ntk_aware_scaling.ipynb" target="_blank" rel="noreferrer noopener">positional_encoding/pi_ntk_aware_scaling.ipynb </a></p>



<iframe loading="lazy" src="https://nbviewer.org/github/dsplog/dsplog.com/blob/main/code/positional_encoding/pi_ntk_aware_scaling.ipynb?flush_cache=false" width="100%" height="600"></iframe>



<h2 class="wp-block-heading">YaRN &#8211; Yet Another RoPE extensioN method (Peng et al 2023)</h2>



<p class="wp-block-paragraph">In the paper <strong><a href="YaRN: Efficient Context Window Extension of Large Language Models">YaRN: Efficient Context Window Extension of Large Language Models</a>, Peng et al 2023</strong>, authors noted the following limitations :</p>



<ul class="wp-block-list">
<li>As the <strong>Position Interpolation</strong> scales all dimensions (frequencies) by equally by a factor <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?s" alt="">, it <strong>alters</strong> the <strong>high frequency</strong> components of RoPE</li>



<li>The <strong>NTK</strong> aware scaling <strong>alleviated</strong> this to <strong>large</strong> extend by scaling high frequencies less and low frequencies more. However, identifying the optimal base frequency has to be found emperically and increasing the difficulty and cost for a fine tuned model.</li>
</ul>



<p class="wp-block-paragraph">To address this, authors proposed<strong> NTK by parts</strong> approach described below</p>



<h3 class="wp-block-heading">NTK by parts</h3>



<p class="wp-block-paragraph">Let the wavelength at dimension <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?d" alt=""> is defined as,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\lambda_d = \frac{2\pi}{\theta_d} \\ \\
\text{where, }\\
\theta_d = b^{-2d/D} \\
b = 10000
" alt="">



<p class="wp-block-paragraph">Authors observe that, <strong>dimensions</strong> where the <strong>wavelength is longer</strong> than the <strong>maximum context length </strong>seen during <strong>pre-training</strong> captures the absolute positional information. However, for the <strong>dimensions</strong> where <strong>wavelength is short</strong>, it typically captures the <strong>relative positional information</strong>.</p>



<h4 class="wp-block-heading">Equations</h4>



<p class="wp-block-paragraph">Defining the ratio between pre-trained context length <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?L" alt=""> and wavelength <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\lambda_d" alt=""> at dimension <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?d" alt=""> as,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
r(d) = \frac{L}{\lambda_d} = \frac{L}{2\pi 
 b^{\frac{2d}{D}}
" alt="">



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">Based on the ratio, the following constraints are defined : </p>



<ol class="wp-block-list">
<li>Do <strong>not interpolate</strong> for the dimensions whose wavelength <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\lambda_d" alt=""> is <strong>smaller</strong> than the pre trained context length <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?L" alt=""> i.e. <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?L \gt \lambda_d, \quad r(d) \gt 1" alt=""></li>



<li>Do the <strong>interpolation</strong> for the dimensions whose wavelength <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\lambda_d" alt=""> <strong>bigger</strong> than the pre trained context length <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?L" alt=""> i.e <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?L \lt \lambda_d, \quad r(d) \lt 1" alt=""></li>



<li>For the dimensions in between,  have a bit of both </li>
</ol>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">Capturing this in equations,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
h(\theta_d) = \left(1-\gamma(r_d)\right)\frac{\theta_d}{s} + \gamma(r_d)\theta_d
" alt="">



<p class="wp-block-paragraph">where, </p>



<ul class="wp-block-list">
<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?s=L^'/L" alt=""> is the <strong>scale factor</strong> to <strong>increase</strong> the <strong>context length</strong> from pre-trained length <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?L" alt=""> to <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?L^'" alt=""></li>



<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\gamma(\cdot)" alt=""> is a ramp function defined as</li>
</ul>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\gamma(r) = 
\begin{cases}
0, &#038; \text{if } r \lt \alpha \\ 
1, &#038; \text{if } r \gt \beta \\ 
\frac{r - \alpha}{\beta - \alpha}, &#038; \text{otherwise.}
\end{cases}
" alt="">



<ul class="wp-block-list">
<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha, \quad \beta" alt="">  are thresholds to be tuned. </li>
</ul>



<p class="wp-block-paragraph">In the paper, authors proposed <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha=1, \quad \beta=32" alt=""> on the Llama family of models. </p>



<p class="wp-block-paragraph">Pluggin in numbers, </p>



<p class="wp-block-paragraph">for a pre-trained context length of <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?L=2048" alt=""> and scaling to by <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?s=16" alt=""> i.e. to extend the context length to<img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?L^'=32768" alt="">.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Ratio <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?r=L/\lambda_d" alt=""></th><th>Wavelength <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\lambda_d" alt=""> (for <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?L=2048" alt="">)</th><th>Remark</th></tr></thead><tbody><tr><td>
<img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?r\le1" alt="">
</td><td>
<img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\lambda_d\ge2048" alt="">
</td><td><b>Interpolation</b></td></tr><tr><td>
<img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?1<r<32" alt="">
</td><td>
<img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?64<\lambda_d<2048" alt="">
</td><td><b>Linear transition</b></td></tr><tr><td><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?r\ge32" alt=""> (<img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\beta" alt="">)</td><td>
<img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\lambda_d\le64" alt="">
</td><td><b>No interpolation</b>. </td></tr></tbody></table></figure>



<p class="wp-block-paragraph">toy implementation @ </p>



<p class="wp-block-paragraph"><a href="https://github.com/dsplog/dsplog.com/blob/main/code/positional_encoding/yarn_scaling.ipynb" target="_blank" rel="noreferrer noopener">positional_encoding/yarn_scaling.ipynb</a></p>



<a href="https://colab.research.google.com/github/dsplog/dsplog.com/blob/main/code/positional_encoding/yarn_scaling.ipynb" target="_blank" rel="noopener">
  <img decoding="async" src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open In Colab"/>
</a>



<h3 class="wp-block-heading">Attention scaling</h3>



<p class="wp-block-paragraph">In addition to the frequency scaling methods described above, authors propose that <strong>scaling the attention</strong> helps lower the perplexity of the model.</p>



<p class="wp-block-paragraph">The scaled attention is defined as, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\text{softmax}\left(\frac{\mathbf{q}_m^T\mathbf{k}_n}{t\sqrt{D}}\right)
" alt="">



<p class="wp-block-paragraph">where, </p>



<ul class="wp-block-list">
<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\sqrt{\frac{1}{t}} = 0.1\times\ln(s) + 1
" alt=""> </li>



<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?s=L^'/L" alt=""> is the scale factor to increase the context length from pre-trained length <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?L" alt=""> to <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?L^'" alt=""></li>
</ul>



<p class="wp-block-paragraph">The equation for temperature scaling is found by <strong>fitting</strong> <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\sqrt{\frac{1}{t}}" alt=""> at the l<strong>owest perplexity</strong> against different values of <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?s" alt="">.</p>



<h1 class="wp-block-heading">Summary</h1>



<p class="wp-block-paragraph">This post covers the following : </p>



<ul class="wp-block-list">
<li>the transformer positional encodings from <strong>additive sinusoidal vectors</strong> to <strong>multiplicative rotary matrices (RoPE)</strong> and <strong>static linear attention biases (ALiBi)</strong>. </li>



<li>Focuses on how their mathematical interactions capture relative token distance.</li>



<li>Discuss the context-extension methods like <strong>Position Interpolation</strong>, <strong>NTK-Aware Scaling</strong>, and <strong>YaRN</strong> .</li>



<li>Code snippets for each of the scheme is provided. </li>
</ul>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph"></p>
<p>The post <a rel="nofollow" href="https://dsplog.com/2026/07/04/positional-encoding-in-transformers/">Positional Encoding in Transformers</a> appeared first on <a rel="nofollow" href="https://dsplog.com">DSP LOG</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://dsplog.com/2026/07/04/positional-encoding-in-transformers/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Loss functions for handling class imbalance</title>
		<link>https://dsplog.com/2026/03/05/loss-functions-for-handling-class-imbalance/</link>
					<comments>https://dsplog.com/2026/03/05/loss-functions-for-handling-class-imbalance/#respond</comments>
		
		<dc:creator><![CDATA[Krishna Sankar]]></dc:creator>
		<pubDate>Thu, 05 Mar 2026 01:05:23 +0000</pubDate>
				<category><![CDATA[Machine Learning]]></category>
		<category><![CDATA[Assymetric loss]]></category>
		<category><![CDATA[Class Balanced Loss]]></category>
		<category><![CDATA[Focal Loss]]></category>
		<category><![CDATA[Logit Adjusted Loss]]></category>
		<category><![CDATA[Weighted Cross Entropy]]></category>
		<guid isPermaLink="false">https://dsplog.com/?p=2720</guid>

					<description><![CDATA[<p>For handling class imbalance, multiple stratetgies have emerged. Post covers Weighted Cross Entropy, Focal Loss, Assymetric Loss, Class Balanced Loss and Logit Adjusted Loss. </p>
<p>The post <a rel="nofollow" href="https://dsplog.com/2026/03/05/loss-functions-for-handling-class-imbalance/">Loss functions for handling class imbalance</a> appeared first on <a rel="nofollow" href="https://dsplog.com">DSP LOG</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Most of real world datasets have <strong>class imbalance</strong>, where a &#8220;<strong>majority</strong>&#8221; class dwarfs the &#8220;<strong>minority</strong>&#8221; samples. Typical examples are &#8211; identifying rare pathologies in medical diagnosis or flagging anomalous transactions to detect fraud or detecting sparse foreground objects from vast background objects in computer vision to name a few.</p>



<p class="wp-block-paragraph">The machine learning models we have discussed &#8211; <strong>binary classification</strong> <sup>(refer post <a href="https://dsplog.com/2025/05/17/gradients-for-binary-classification/">Gradients for Binary Classification with Sigmoid</a>)</sup> or <strong>multiclass classification</strong> <sup>(refer post <a href="https://dsplog.com/2025/06/22/gradients-for-multi-class-classification-with-softmax/">Gradients for multi class classification with Softmax</a>)</sup> needs tweaks to <strong>learn</strong> from these imbalanced datasets. Without these adjustments, the models can &#8220;<strong>cheat</strong>&#8221; by favouring the <strong>majority class</strong> and can report a <strong>pseudo high accuracy</strong> though the class specific accuracy is low.</p>



<p class="wp-block-paragraph">Different strategies have emerged over the years, and in this article we are covering the approaches listed below.</p>



<ol class="wp-block-list">
<li><strong>Weighted cross entropy</strong>
<ul class="wp-block-list">
<li>Foundational baseline, where a <strong>class-specific weight factor</strong> to the standard cross-entropy loss to weight the loss based on <strong>frequency</strong> of the class. </li>
</ul>
</li>



<li><strong><a href="https://arxiv.org/abs/1708.02002" target="_blank" rel="noreferrer noopener">Focal Loss for Dense Object Detection</a>,</strong> Lin et al. (2017)
<ul class="wp-block-list">
<li>Propose a <strong>modulating</strong> factor <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?(1-p_t) ^\gamma" alt=""> to the cross-entropy loss to <strong>down-weight</strong> easy/frequent examples which indirectly forces the model to focus on hard/rare examples</li>
</ul>
</li>



<li><strong><a href="https://arxiv.org/abs/2009.14119" target="_blank" rel="noreferrer noopener">Asymmetric Loss for Multi-Label Classification</a>, </strong>Ridnik et al. (2021)
<ul class="wp-block-list">
<li>Extended the intuition of Focal Loss by having <strong>independent</strong> <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\gamma" alt=""> hyper-parameter for positive and negative samples. This allows for more aggressive &#8220;pushing&#8221; of easy/frequent examples while preserving the gradient signal for hard/rare samples.</li>



<li>Additionally, authors introduces a <strong>probability margin</strong> that explicitly zeros out the loss from easy/frequent  samples. </li>
</ul>
</li>



<li><strong><a href="https://arxiv.org/abs/1901.05555" target="_blank" rel="noreferrer noopener">Class-Balanced Loss Based on Effective Number of Samples</a>, </strong>Cui et al. (CVPR 2019)
<ul class="wp-block-list">
<li>Based on the intuition that there are <strong>similarities among the samples</strong>, authors propose a framework to capture the <strong>diminishing  benefit</strong> when more datasamples are added to a class.</li>
</ul>
</li>



<li><strong><a href="https://arxiv.org/abs/2007.07314" target="_blank" rel="noreferrer noopener">Long-tail Learning via Logit Adjustment</a>, </strong>Menon et al. (ICLR 2021)
<ul class="wp-block-list">
<li>Based on the foundations from <strong>Bayes Rule</strong>, authors propose that adding a <strong>class dependent offset based on the prior probabilities</strong> help the model learn to <strong>minimise the balanced error rate</strong> (the average of error rates for each class) instead of minimising global error rate. </li>
</ul>
</li>
</ol>



<span id="more-2720"></span>



<h2 class="wp-block-heading">Weighted Cross Entropy</h2>



<p class="wp-block-paragraph">Standard Cross Entropy treats all classes equally, which becomes problematic when your dataset contains 1,000s of easy background examples but only 100s of rare foreground objects. In such cases, the majority class dominates the loss and biases the model. <strong>Weighted Cross Entropy (WCE)</strong> addresses this by assigning a static weight to each class, manually boosting the importance of rare samples.</p>



<h3 class="wp-block-heading">Binary weighted Cross Entropy</h3>



<p class="wp-block-paragraph">For binary classification, a weighting factor <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha \in [0, 1]" alt=""> to the standard BCE formula is used the scale the loss.</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
BCE_W(y, p) = -[\alpha \cdot y \log(p) + (1 - \alpha) \cdot (1 - y) \log(1 - p)]
" alt="Weighted Binary Cross Entropy Formula"/>



<p class="wp-block-paragraph">where <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha" alt=""> is typically set to the <strong>inverse of the class frequency</strong>. </p>



<p class="wp-block-paragraph">By setting a high <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha" alt=""> for the rare class (e.g., 0.9 for the 100 foreground samples) and a low weight for the frequent class (0.1 for the 1,000 background samples), ensures that the rare foreground objects provide a <strong>sufficient gradient</strong> signal during training.</p>



<h3 class="wp-block-heading">Multiclass Weighted Cross Entropy</h3>



<p class="wp-block-paragraph">In the multiclass case with <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?K" alt="" align="absmiddle"> classes, the loss for a single example where <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?c" alt="" align="absmiddle"> is the ground-truth label is defined as:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi? CE_W(p) = -\alpha_c \log(p_c) " alt="Multiclass Weighted Cross Entropy Formula"/>



<p class="wp-block-paragraph">Where <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha_c" alt="" align="absmiddle"> is a fixed weight assigned to class <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?c" alt="" align="absmiddle">, typically calculated using the <strong>Inverse Class Frequency</strong>:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi? \alpha_c = \frac{N}{K \cdot n_c}\\
\text{where, } \\
N \text{ is the total number of samples} " alt="Inverse Class Frequency formula"/>



<p class="wp-block-paragraph">Weighted versions of cross entropy loss is natively supported in PyTorch library as :</p>



<ul class="wp-block-list">
<li><strong>torch.nn.BCEWithLogitsLoss</strong> <sup>(<a href="https://docs.pytorch.org/docs/stable/generated/torch.nn.BCEWithLogitsLoss.html" target="_blank" rel="noopener">refer</a>)</sup> : using the argument <strong>pos_weight</strong> for the binary classification</li>



<li><strong>torch.nn.CrossEntropyLoss</strong> <sup>(<a href="https://docs.pytorch.org/docs/stable/generated/torch.nn.CrossEntropyLoss.html" target="_blank" rel="noopener">refer</a>)</sup> : using the argument <strong>weight</strong> for multiclass classification.</li>
</ul>



<p class="wp-block-paragraph">Toy example computing the loss using the manually vs PyTorch implementation @ <a href="https://github.com/dsplog/dsplog.com/blob/main/code/loss_functions_for_class_imbalance/weighted_cross_entropy.ipynb">loss_functions_for_class_imbalance/weighted_cross_entropy.ipynb</a></p>



<iframe loading="lazy" src="https://nbviewer.org/github/dsplog/dsplog.com/blob/main/code/loss_functions_for_class_imbalance/weighted_cross_entropy.ipynb?flush_cache=false" width="100%" height="600"></iframe>



<h2 class="wp-block-heading">Focal Loss (Lin et al  2017)</h2>



<p class="wp-block-paragraph">In the paper <strong><a href="https://arxiv.org/abs/1708.02002" target="_blank" rel="noreferrer noopener">Focal Loss for Dense Object Detection</a> </strong>Lin et al. (2017) , authors propose an extension to standard Cross Entropy loss to <strong>focus training on hard/rare examples</strong>. The key intuition is that by adding a probability-dependent modulating factor to the loss, the contribution of <strong>easy/frequent examples</strong> (where the estimated probability is close to the truth) is down-weighted. This indirectly forces the training to focus specifically on the hard/rare examples.</p>



<p class="wp-block-paragraph">Focal loss is defined as : </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
FL(y,p) = -[(1-p)^\gamma y  \log(p) +  p^\gamma (1-y)\log(1-p) ]
" alt="">



<p class="wp-block-paragraph">where, </p>



<ul class="wp-block-list">
<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?y\in\{0,1\}" alt=""> represent the ground truth labels and</li>



<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?p\in\[0,1]" alt="">  is the estimated probabilities</li>



<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\gamma" alt=""> is a hyperparameter to control the modulating factor</li>
</ul>



<p class="wp-block-paragraph">Note  : The standard cross entropy loss for binary classification is</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
CE(y,p) = -[y\log(p) + (1-y)\log(1-p) ]
" alt="">



<h3 class="wp-block-heading">Gradients in standard Cross Entropy Loss</h3>



<p class="wp-block-paragraph">To understand how Focal Loss works, the gradient i.e. the derivative with respect to the model&#8217;s output logits, <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?z" alt=""> is explored. The model outputs a real number <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?{z}" alt=""> number, which is converted to a probability <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?p\in\[0,1]" alt=""> using the sigmoid function <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\sigma(z)" alt="">. <br><br>Using the <strong>chain rule from calculus</strong>&nbsp;<a href="https://en.wikipedia.org/wiki/Chain_rule#Intuitive_explanation" target="_blank" rel="noopener"><sup>(refer wiki entry on Chain Rule)</sup></a>, then the gradient of loss with respect <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?{z}" alt=""> <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial {L}}{\partial z}" alt=""> is found as &#8211; gradient of loss with respect to probabilty <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial {L}}{\partial p}" alt=""> multiplied with gradient of probability with respect to parameter <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial p}{\partial z}" alt=""> i.e.</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial {L}}{\partial \mathbf{z}} = \frac{\partial {L}}{\partial p} \cdot \frac{\partial p}{\partial z} 
" alt="">



<p class="wp-block-paragraph">For standard <strong>Cross Entropy</strong> loss, as derived in the post on <a href="https://dsplog.com/2025/05/17/gradients-for-binary-classification/#Gradients_with_Binary_Cross_Entropy_BCE_Loss" target="_blank" rel="noreferrer noopener">Gradients for Binary Classification with Sigmoid</a>, gradient is, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}
\frac{\partial {CE}}{\partial {p}} &#038; = &#038; -\left[\frac{y}{p} - \frac{1-y}{1-p} \right]  \\
\frac{\partial {p}}{\partial {z}} &#038; = &#038; p(1-p)  \\
\\
\text{then, }
\\

\frac{\partial {CE}}{\partial {z}} 
&#038; = &#038; \frac{\partial {CE}}{\partial {p}} \cdot   \frac{\partial {p}}{\partial {z}} \\
&#038;=&#038; -\left[\frac{y}{p} - \frac{1-y}{1-p} \right] \cdot p(1-p) \\
&#038;=&#038;-\left[y(1-p) - (1-y)p \right]  \\
&#038;=&#038;p-y


\end{array}
" alt="">



<p class="wp-block-paragraph">The <strong>gradient is linear</strong> and depends only on the error &#8211; this means an &#8220;easy/frequent&#8221; example (where the error is small, e.g., 0.1) when <strong>summed over large number of of easy examples</strong> still contributes to the loss and can <strong>overwhelm</strong> the training.</p>



<h3 class="wp-block-heading">Gradients in Focal Loss</h3>



<p class="wp-block-paragraph">For computing the gradients with focal loss, let us define the <strong>ground truth labels</strong> <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?y\in\{0,1\}" alt="">and the model&#8217;s <strong>estimated probability</strong> <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?p\in\[0,1]" alt=""> as : </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi? p_t = \begin{cases} p &#038; \text{if } 
y = 1 \\ 1 - p 
&#038; 
 \text{otherwise} \end{cases} " alt="Definition of pt">



<p class="wp-block-paragraph">where,</p>



<ul class="wp-block-list">
<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?y=0" alt=""> background class with 1000&#8217;s of easy/frequent examples</li>



<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?y=1" alt=""> foreground class with 100&#8217;s of hard/rare examples</li>
</ul>



<p class="wp-block-paragraph">Taking the case of <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?y=1" alt="">, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}
\frac{\partial {FL}}{\partial p_t} 
&#038; = &#038; -(1-p_t)^\gamma \cdot \frac{\partial }{\partial p_t}\log(p_t) - \log(p_t) \frac{\partial  }{\partial p_t}(1-p_t)^\gamma \\

&#038; = &#038; -(1-p_t)^\gamma \cdot \frac{1}{(p_t)} + \gamma (1-p_t)^{\gamma-1}\log(p_t) \\


\end{array}
" alt="">



<p class="wp-block-paragraph">Multiplying with <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial {p_t}}{\partial {z}}  =  p_t(1-p_t) " alt=""> ,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}

\frac{\partial {FL}}{\partial {z}} 
&#038; = &#038; \frac{\partial {FL}}{\partial {p_t}} \cdot   \frac{\partial {p_t}}{\partial {z}} \\

&#038; = &#038; \[-(1-p_t)^\gamma \cdot \frac{1}{(p_t)} + \gamma (1-p_t)^{\gamma-1}\log(p_t) \] \cdot p_t(1-p_t) \\

&#038; = &#038; \[-(1-p_t)^{\gamma+1} + \gamma p_t(1-p_t)^{\gamma}\log(p_t) \] \\
&#038; = &#038; (1-p_t)^{\gamma}\[-(1-p_t) + \gamma p_t\log(p_t) \] \\
&#038; = &#038; \underbrace{(1-p_t)^{\gamma}}_{\text{scaling term}}\[\underbrace{(p_t-1)}_{\text{CE term}} + \underbrace{\gamma p_t\log(p_t)}_{\text{focal term}} \] 




\end{array}
" alt="">



<p class="wp-block-paragraph">Sweeping the value of <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?p" alt=""> from 0 to 1 for <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\gamma=2" alt="">, the behaviour of the individual terms are as shown in the plot below. </p>



<div class="wp-block-cover"><span aria-hidden="true" class="wp-block-cover__background has-background-dim"></span><div class="wp-block-cover__inner-container is-layout-flow wp-block-cover-is-layout-flow">
<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<figure class="wp-block-gallery aligncenter has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-full is-style-default"><a href="https://dsplog.com/db-install/wp-content/uploads/2026/01/image-2.png"><img loading="lazy" decoding="async" width="711" height="536" data-id="2733" src="https://dsplog.com/db-install/wp-content/uploads/2026/01/image-2.png" alt="" class="wp-image-2733" srcset="https://dsplog.com/db-install/wp-content/uploads/2026/01/image-2.png 711w, https://dsplog.com/db-install/wp-content/uploads/2026/01/image-2-300x226.png 300w" sizes="auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px" /></a></figure>
</figure>
</div></div>
</div></div>



<p class="wp-block-paragraph">code @<strong> <a href="https://github.com/dsplog/dsplog.com/blob/main/code/loss_functions_for_class_imbalance/focal_loss_terms.py" target="_blank" rel="noreferrer noopener">focal_loss_terms.py</a></strong></p>



<p class="wp-block-paragraph">The model learns easy/frequent examples much faster and <strong><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?p" alt=""> is close to the ground truth <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?y" alt=""></strong>, which means <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?p_t\rightarrow 1" alt="">. As <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?p_t" alt=""> approaches 1, the scaling term <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?(1-p_t) ^\gamma" alt=""> effectively <strong>silences the gradient.</strong></p>



<p class="wp-block-paragraph">Plugging in numbers, when the model is estimating <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?p_t \approx 0.99" alt=""> for the frequent examples, the throttle becomes <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?(1-0.99)^2 \approx 0.0001" alt=""> and the gradient from these examples is effectively silenced.</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}
\frac{\partial FL}{\partial z} &#038; \approx &#038;(1-p_t)^\gamma (p - y)
\end{array}
" alt="">



<p class="wp-block-paragraph">Thus the term <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?(1-p_t) ^\gamma" alt=""> acts as a <strong>throttle</strong> for <strong>easy/frequent examples</strong>.</p>



<p class="wp-block-paragraph"></p>



<h3 class="wp-block-heading">The Weighting Factor $\alpha$</h3>



<p class="wp-block-paragraph">With the focusing parameter <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\gamma" alt=""> down-weighting easy/frequent examples, the choosing <strong>class weights</strong> <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha" alt=""> parameter using <strong>inverse of class frequency</strong> is not preferred. To understand the intuitions, let us define <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha_t" alt=""> as below :</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi? 
\alpha_t = 
\begin{cases} \alpha &amp; \text{if } 
y = 1 \text{ (foreground)} \\ 
1 - \alpha &amp; \text{if } y = 0 \text{ (background)}
\end{cases} " alt="Definition of alpha_t" />



<p class="wp-block-paragraph">The <strong>Focal Loss</strong> including <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha_t" alt=""> is :</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi? FL(p_t) = -\alpha_t (1-p_t)^\gamma \log(p_t) " alt="Alpha Balanced Focal Loss"/>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">When we go with <strong>inverse of class frequency</strong>, typically values of <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha" alt=""> is : </p>



<ul class="wp-block-list">
<li>high <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha" alt=""> (around 0.9) for <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?y=1" alt=""> (hard/rare foreground class) and </li>



<li>low <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha" alt=""> (around 0.1) for <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?y=0" alt=""> (easy/frequent background class)</li>
</ul>



<p class="wp-block-paragraph">With the Focal Loss, the focusing term <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?(1-p_t)^\gamma" alt=""> aggressively down-weights the easy examples and the accumulated loss from the background class drops drastically. Then with high <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha" alt=""> the <strong>hard/rare foreground</strong> class with only 100s of examples will now<strong> dominate the gradient and can cause instability</strong>.</p>



<p class="wp-block-paragraph">Therefore, as <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\gamma" alt=""> <strong>is increased</strong>, <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha" alt=""> should be <strong>decreased</strong>. In the paper, for <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\gamma=2" alt="">, the authors found the best balance was actually <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha=0.25" alt=""> for the foreground class <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?y=1" alt="">.</p>



<h3 class="wp-block-heading">Extension to Multiclass Focal Loss</h3>



<p class="wp-block-paragraph">While the binary case uses a single probability <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?p" alt="">, the multiclass classification involve <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?C" alt=""> distinct classes. In the <strong>multiclass</strong> setting, the model outputs a <strong>vector of logits</strong>, which are transformed into probabilities using the <strong>Softmax</strong> function. The estimated probability for <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?l^{th}" alt=""> class is :</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi? 
P_{l} = \frac{e^{z_{l}}}{\sum_{j=1}^{C} e^{z_{j}}}"/>



<p class="wp-block-paragraph">The Multiclass Focal Loss for a single example for <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?l^{th}" alt=""> ground truth class  is,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi? 
FL_{\text{multi class}} = -\alpha_{l} (1 - P_{l})^\gamma \log(P_{l})
"/>



<p class="wp-block-paragraph">Typically <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\gamma=2" alt=""> is chosen as a scalar, and the weights factor <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha_{l}" alt=""> is defined as a class dependent vector.  </p>



<p class="wp-block-paragraph">Choosing <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha_{l}=0.25" alt=""> for the rare classes and <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha_{l}=0.75" alt=""> for the frequent classes seems to be choice which can be arrived at using hyper parameter tuning. Though it is counter intuitive to give higher <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha" alt=""> for frequent classes, it helps to prevent their contribution from being completely <strong>throttled</strong> by the  <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?(1-p_t)^\gamma" alt=""> term. </p>



<p class="wp-block-paragraph">Toy example showing implementation of Focal Loss for binary and multi-class classification @ <a href="https://github.com/dsplog/dsplog.com/blob/main/code/loss_functions_for_class_imbalance/focal_loss_binary_multiclass.ipynb"><strong>loss_functions_for_class_imbalance/focal_loss_binary_multiclass.ipynb</strong></a></p>



<iframe loading="lazy" src="https://nbviewer.org/github/dsplog/dsplog.com/blob/main/code/loss_functions_for_class_imbalance/focal_loss_binary_multiclass.ipynb?flush_cache=false" width="100%" height="600"></iframe>



<h2 class="wp-block-heading">Assymetric Loss (2021)</h2>



<p class="wp-block-paragraph">In the focal loss definition, the <strong>same <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\gamma" alt=""> is used for both background class</strong> with high count of easy examples and<strong> rare foreground class</strong>. If a higher <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\gamma" alt=""> is used to throttle the gradients of easy background classes, then this also affects when the model is learning the hard foreground classes.</p>



<p class="wp-block-paragraph">In the paper, <a href="https://arxiv.org/abs/2009.14119" target="_blank" rel="noopener"><strong>Asymmetric Loss for Multi-Label Classification</strong></a>, Ridnik et al. (2021). authors proposed to <strong>decouple</strong> the <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\gamma" alt=""> for <strong>foreground and background classes</strong>.</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?

L = \begin{cases} 
-(1-p)^{(\gamma_+)} \log(p) &#038; \text{if } y=1 \quad \text{(hard/rare foreground class)}\\ 
-p^{(\gamma_-)} \log(1-p) &#038; \text{if } y=0 \quad \text{(easy/frequent background class)}
\end{cases}
" alt=""/>



<p class="wp-block-paragraph">To give <strong>emphasis to the contribution of positive samples</strong>, <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\gamma_- \gt \gamma_+" alt=""> . </p>



<p class="wp-block-paragraph">The typical values can be <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\gamma_+ =0" alt=""> so that the hard/low count positive samples behave similar to standard cross entropy loss and <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\gamma_- =2" alt=""> to throttle gradients for easy/high count background classes.</p>



<p class="wp-block-paragraph">Authors further propose <strong>adding a margin</strong> on the probability of easy backround classes by probability shifting which <strong>discards them when the probability is below a threshold</strong>.</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
p_m= \max(p-m,0)
" alt=""/>



<p class="wp-block-paragraph">with <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?m" alt=""> as a hyperparameter and a typical value being <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?m=0.2" alt="">. <br></p>



<p class="wp-block-paragraph">Combining both, the <strong>Assymetric Loss </strong>is defined as,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?

ASL = \begin{cases} 
-(1-p)^{(\gamma_+)} \log(p) &#038; \text{if } y=1 \quad \text{(hard/rare foreground class)}\\ 
-p_m^{(\gamma_-)} \log(1-p_m) &#038; \text{if } y=0 \quad \text{(easy/frequent background class)}
\end{cases}
" alt=""/>



<p class="wp-block-paragraph">Toy implementation of assymetric loss @ <a href="https://github.com/dsplog/dsplog.com/blob/main/code/loss_functions_for_class_imbalance/assymetric_loss.ipynb"><strong>loss_functions_for_class_imbalance/assymetric_loss.ipynb</strong></a></p>



<iframe loading="lazy" src="https://nbviewer.org/github/dsplog/dsplog.com/blob/main/code/loss_functions_for_class_imbalance/assymetric_loss.ipynb?flush_cache=false" width="100%" height="600"></iframe>



<h2 class="wp-block-heading">Class-Balanced Loss (Yin Cui et al 2019)</h2>



<p class="wp-block-paragraph">In the paper <strong><a href="https://arxiv.org/abs/1901.05555" target="_blank" rel="noreferrer noopener">Class-Balanced Loss Based on Effective Number of Samples</a>, </strong>Cui et al. , authors argue that there will be <strong>similarities among the samples</strong> and as the number of samples increase, the probability that this sample is <strong>covered</strong> in the existing samples increases. Based on this intuition, authors propose a framework to capture the <strong>diminishing  benefit</strong> when more datasamples are added to a class.</p>



<h3 class="wp-block-heading">Derivation</h3>



<p class="wp-block-paragraph">Let us denote the effective number of samples as <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?E_n" alt="">, and the total volume of this space as <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?N" alt="">. Consider the case where we have <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?n-1" alt=""> examples and is going to sample the <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?n^{th}" alt=""> example. The probability that the newly sampled example to be overlapped with the previous samples is,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?p=\frac{E_{n-1}}{N}" alt=""/>



<p class="wp-block-paragraph"><strong>Expected volume</strong> with the <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?n^{th}" alt=""> example is,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}E_n 
&#038; = &#038; pE_{n-1} + (1-p)(E_{n-1}+1) \\
&#038; = &#038; pE_{n-1} + E_{n-1}+1 -pE_{n-1} - p \\
&#038; = &#038; E_{n-1} + 1-p\\
\quad \text{substituting for } p, \\ 
&#038; = &#038; E_{n-1} + 1- \frac{E_{n-1}}{N} \\
&#038; = &#038; \frac{NE_{n-1} + N - E_{n-1}}{N} \\
&#038; = &#038; 1 + \frac{N-1}{N}E_{n-1}  \\
&#038; = &#038; 1 + \beta E_{n-1}, \quad \text{where, } \beta =  \frac {N-1}{N}



\end{array}
" alt=""/>



<p class="wp-block-paragraph">To solve for <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?E_n" alt="">, re-writing as a <strong>geometric series</strong>,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{llll}
n=1, &#038; E_1 &#038; =&#038;  1\\
n=2, &#038; E_2 &#038;= &#038; 1+\beta E_1 = 1+\beta \\
n=3, &#038; E_3 &#038;= &#038; 1+\beta E_2 = 1+\beta(1+\beta) = 1+ \beta + \beta^2 \\
n=4, &#038; E_4 &#038;= &#038; 1+\beta E_3 = 1+\beta(1+\beta+\beta^2) = 1+ \beta + \beta^2 + \beta^3 \\
\vdots

\end{array}
" alt=""/>



<p class="wp-block-paragraph">For the general <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?E_n" alt=""> can be written as</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{llllll}
E_n &#038; = &#038; \sum_{j=1}^{n} \beta^{j-1} &#038; = &#038; 1 + \beta + \beta^2 + \cdots + \beta^{n-1}

\end{array}
" alt=""/>



<p class="wp-block-paragraph">Solving for <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?E_n" alt="">, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{llllll}
E_n - \beta E_n &#038; = &#038; (1 + \beta + \beta^2 + \cdots + \beta^{n-1}) - \beta(1 + \beta + \beta^2 + \cdots + \beta^{n-1}) \\
&#038; = &#038; 1-\beta^n \\
\text{solving, }\\
(1-\beta)E_n &#038; = &#038; 1-\beta^n \\
E_n &#038; = &#038; (1-\beta^n)/(1-\beta)

\end{array}
" alt=""/>



<p class="wp-block-paragraph"><strong>Note</strong> :  </p>



<ul class="wp-block-list">
<li>When <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\beta=0" alt="">, the effective number of samples <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?E_n=1" alt=""> indicating that there is <strong>no benefit</strong> in adding more samples.</li>



<li>When <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\beta\rightarrow 1" alt="">, the expected number of samples <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?E_n=n" alt="">, indicating that each sample is treated <strong>unique</strong>.</li>
</ul>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}
\lim_{\beta \to 1}E_n  
&#038; = &#038; \lim_{\beta \to 1}\frac{(1-\beta^n)}{(1-\beta)} \\
\text{using L' Hospitals rule, } \\
&#038;  = &#038; \frac{-n\beta^{n-1}}{-1} 
&#038; = &#038; n

\end{array}
" alt=""/>



<p class="wp-block-paragraph">In the paper authors explore <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\beta" alt=""> as a <strong>hyper-parameter</strong> and report that in long tailed CIFAR-10 (Imbalance Factor = 50) dataset, the best is <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\beta=0.9999" alt=""> . In this dataset, the <strong>most frequent class has 5000</strong> images, while the <strong>rarest class has 100</strong> images. With <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\beta=0.9999" alt="">, the effective number of samples for the frequent and rarest class is</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}
E_{100} = \frac{1-\beta^{100}}{1-\beta} = 99.5 \\
E_{5000} = \frac{1-\beta^{5000}}{1-\beta} = 3934.85 \\
\end{array}
" alt=""/>



<p class="wp-block-paragraph"></p>



<figure class="wp-block-table aligncenter"><table class="has-fixed-layout"><thead><tr><td><strong>Weighting Scheme</strong></td><td><strong>β Value</strong></td><td><strong>Majority En​</strong></td><td><strong>Minority En​</strong></td><td><strong>Ratio (Maj/Min)</strong></td></tr></thead><tbody><tr><td><strong>Inverse Frequency</strong></td><td><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\beta\rightarrow 1" alt=""></td><td>5000</td><td>100</td><td><strong>50.0 : 1</strong></td></tr><tr><td><strong>Class-Balanced</strong></td><td><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\beta=0.9999" alt=""></td><td>3934.85</td><td>99.5</td><td><strong>39.5 : 1</strong></td></tr><tr><td><strong>Class-Balanced</strong></td><td><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\beta=0.999" alt=""></td><td>993</td><td>95.3</td><td><strong>10.4 : 1</strong></td></tr><tr><td><strong>No Weighting</strong></td><td><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\beta=0" alt=""></td><td>1</td><td>1</td><td><strong>1.0 : 1</strong></td></tr></tbody></table><figcaption class="wp-element-caption">Table : Relative ratio of Effective samples in CIFAR long tail (imbalance factor=50) dataset</figcaption></figure>



<p class="wp-block-paragraph">Though the weight ratio between frequent class and small class is 50:1, by<strong> choosing a lower</strong> <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\beta" alt="">, we assume <strong>higher redundancy</strong> in the dataset and give lesser weightage to the sample count of majority class.</p>



<h3 class="wp-block-heading">Applying to loss</h3>



<p class="wp-block-paragraph">To balance the loss, for each class <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?i" alt=""> which has <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?n_i" alt="">samples, a weighting factor <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha_i" alt=""> that is that is <strong>inversely proportional</strong> to the effective number of samples for each class is found out, i.e</p>



<p class="wp-block-paragraph"><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha_i \propto 1/E_{n}_i" alt=""> . </p>



<p class="wp-block-paragraph">To make the total loss roughly in the same scale when applying <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha_i" alt="">, a normalization factor to scale the sum of <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha_i" alt=""> to the class count <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?C" alt=""> i.e.  </p>



<p class="wp-block-paragraph"><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\sum_{i=1}^C\alpha_i = C" alt=""> <br></p>



<p class="wp-block-paragraph">With this definition, </p>



<p class="wp-block-paragraph">a) the <strong>class balanced softmax loss</strong> is,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}
\mathcal{L}_{\text{CB CE}}(\mathbf{y}, \mathbf{p}) 
&#038; = &#038; - \sum_{i=1}^{C} \alpha_iy_i \log(p_i) \\
&#038; = &#038; - \sum_{i=1}^{C} \(\frac{1-\beta}{1-\beta^{n_i}}\)y_i\log(p_i)
\end{array}
" alt=""/>



<p class="wp-block-paragraph">b) <strong>class balanced focal loss </strong>is,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array} {lll}

\mathcal{L}_{\text{CB FL}}(\mathbf{y}, \mathbf{p}) 
&#038; = &#038; -\sum_{i=1}^{C}  \alpha_i(1-p_i)^\gamma y_i\log(p_i) \\ 
&#038; = &#038; - \sum_{i=1}^{C} \(\frac{1-\beta}{1-\beta^{n_i}}\)(1-p_i)^\gamma y_i\log(p_i)
\end{array}
" alt=""/>



<p class="wp-block-paragraph"><strong>Class-Balanced Loss</strong> as a <strong>specific weighting strategy</strong> for standard loss functions and it provides a mathematically grounded way to calculate the weight <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha_i" alt=""> capturing the &#8220;<strong>effective number of samples</strong>&#8220;</p>



<p class="wp-block-paragraph">Code to find the class balanced weights @ <a href="https://github.com/dsplog/dsplog.com/blob/main/code/loss_functions_for_class_imbalance/class_balanced_weights.ipynb"><strong>loss_functions_for_class_imbalance/class_balanced_weights.ipynb</strong></a></p>



<iframe loading="lazy" src="https://nbviewer.org/github/dsplog/dsplog.com/blob/main/code/loss_functions_for_class_imbalance/class_balanced_weights.ipynb?flush_cache=false" width="100%" height="600"></iframe>



<h2 class="wp-block-heading">Logit Adjustment (Menon et al 2021)</h2>



<p class="wp-block-paragraph">In the paper <strong><a href="https://arxiv.org/abs/2007.07314" target="_blank" rel="noreferrer noopener">Long-tail Learning via Logit Adjustment</a>, </strong>Menon et al. (ICLR 2021), authors argue that for scenarios with heavy class imbalance, the <strong>average misclassification error is not a suitable metric</strong>.</p>



<h3 class="wp-block-heading">Average Classification error in Multiclass classification </h3>



<p class="wp-block-paragraph">Consider that <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{x}" alt=""> is an <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi? n" alt=""> dimensional input feature vector <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\[x_1, x_2, \cdots, x_n\]" alt=""> and the model is trained on a multiclass classification task to learn the probability of <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?L" alt=""> classes.</p>



<p class="wp-block-paragraph">The model <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?f_y(x)" alt=""> outputs a vector<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{z}%20\in%20\mathbb{R}^{L%20\times%201}" alt=""> which captures the <strong>logarithm of the probability (aka logit) </strong>for each class. The scores are converted into <strong>probabilities</strong> using <strong>SoftMax</strong> function. For the class <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?k" alt="">, the estimated probability is,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array} {lll}
P(y_k|\mathbf{x}) = \frac{\exp(f_{y_k}(\mathbf{x}))}{\sum_{i=1}^L\exp(f_{y_i}(\mathbf{x}))}
\end{array}
" alt=""/>



<p class="wp-block-paragraph">Taking logarithm, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array} {lll}
\ln(P(y_k|\mathbf{x})) 
&#038; = &#038; \ln\(\frac{\exp(f_{y_k}(\mathbf{x}))}{\sum_{i=1}^L\exp(f_{y_i}(\mathbf{x}))}\) \\
&#038; = &#038; \ln(\exp(f_{y_k}(\mathbf{x}))) - \ln\(\sum_{i=1}^L\exp(f_{y_i}(\mathbf{x}))\) \\
&#038; = &#038; f_{y_k}(\mathbf{x}) -  C

\end{array}
" alt=""/>



<p class="wp-block-paragraph">where, constant <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?C=\ln\(\sum_{i=1}^L\exp(f_{y_i}(\mathbf{x}))\)" alt="">. <br><br>The training loop to estimate the probability of the true class <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?k" alt=""> given the input <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{x}" alt="">, <strong>minimizes the negative log likelihood</strong> i.e.</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array} {lll}
L(y,f(\mathbf{x})) &#038; = &#038; -\ln(P(y_k|\mathbf{x})) \\ 
&#038;=&#038; -\ln \(\frac{\exp(f_{y_k}(\mathbf{x}))}{\sum_{i=1}^L\exp(f_{y_i}(\mathbf{x}))}\) \\
&#038;=&#038;-f_{y_k}(\mathbf{x}) + \ln \(\sum_{i=1}^L\exp(f_{y_i}(\mathbf{x}))\) \\
&#038;=&#038;-f_{y_k}(\mathbf{x}) + \ln \(\exp(f_{y_k}(\mathbf{x})) + \sum_{i=1,i \ne k}^L\exp(f_{y_i}(\mathbf{x}))\)\\
&#038;=&#038;-f_{y_k}(\mathbf{x}) + \ln \(\exp(f_{y_k}(\mathbf{x})) \(1 + \frac{\sum_{i=1,i \ne k}^L\exp(f_{y_i}(x))}{\exp(f_{y_k}(x))}\)\) \\
&#038;=&#038;-f_{y_k}(\mathbf{x}) + f_{y_k}(\mathbf{x})  + \ln \(1 + \frac{\sum_{i=1,i \ne k}^L\exp(f_{y_i}(\mathbf{x}))}{\exp(f_{y_k}(\mathbf{x}))}\) \\
&#038;=&#038; \ln \(1 + \sum_{i=1,i \ne k}^L\frac{\exp(f_{y_i}(\mathbf{x}))}{\exp(f_{y_k}(\mathbf{x}))}\) \\
&#038;=&#038; \ln \(1 + \sum_{i=1,i \ne k}^L\exp(f_{y_i}(\mathbf{x})-f_{y_k}(\mathbf{x}))\)


\end{array}
" alt=""/>



<p class="wp-block-paragraph">From the above equation, we can see that  &#8211; when the <strong>logit corresponding to true class</strong><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?f_{y_k}(x)" alt=""> is <strong>much greater</strong> than the <strong>logit corresponding to incorrect class</strong> <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?f_{y_i}(x)" alt=""> i.e. <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?f_{y_k}(x) \gg f_{y_i}(x)" alt="">, the exponential term <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\exp(f_{y_i}(x) - f_{y_k}(x)) \rightarrow 0" alt=""> and the <strong>loss tends to 0</strong>.</p>



<p class="wp-block-paragraph">To understand how the <strong>class imbalance affects the loss</strong>, the term <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?f_{y_i}(\mathbf{x}) - f_{y_k}(\mathbf{x})" alt=""> can be expanded using <strong>Bayes rule</strong> <sup>(<a href="https://en.wikipedia.org/wiki/Bayes%27_theorem" target="_blank" rel="noopener">refer wiki entry</a>)</sup> as,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array} {lll}
f_{y_i}(\mathbf{x}) - f_{y_k}(\mathbf{x}) 
&#038; = &#038; \ln(P(y_i|\mathbf{x})) - \ln(P(y_k|\mathbf{x}))  \\ 
&#038; = &#038; \ln\(\frac{P(y_i|\mathbf{x})}{P(y_k|\mathbf{x})}\)  \\ 
\text{using Bayes rule, }\\
&#038; = &#038; \ln\(\frac{\frac{P(\mathbf{x}|y_i)P(y_i)}{P(\mathbf{x})}}{\frac{P(\mathbf{x}|y_k)P(y_k)}{P(\mathbf{x})}}\) \\

&#038; = &#038; \ln\(\frac{P(\mathbf{x}|y_i)P(y_i)}{P(\mathbf{x}|y)P(y_k)}\) \\
&#038; = &#038; \underbrace{\ln\(\frac{P(\mathbf{x}|y_i)}{P(\mathbf{x}|y_k)}\)}_{\text{likelihood}} + \underbrace{\ln\(\frac{P(y_i)}{P(y_k)}\)}_{\text{class frequency}\\



\end{array}
" alt=""/>



<p class="wp-block-paragraph">If the <strong>classes are balanced,</strong> then the <strong>class frequency term <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\ln\(\frac{P(y_i)}{P(y_k)}\)" alt=""> tends to 0</strong> and does not contribute to the loss. However, when there is <strong>class imbalance</strong>, for example with with the <strong>class <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?k" alt=""> being rare</strong>, then the term <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\ln\(\frac{P(y_i)}{P(y_k)}\)" alt=""> is a <strong>large positive number contributing to the loss</strong>. </p>



<p class="wp-block-paragraph">To minimize the loss, instead of doing the &#8220;hard work&#8221; of learning discriminative features in the likelihood term <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\ln(\frac{P(\mathbf{x}|y_i)}{P(\mathbf{x}|y_k)})" alt="">, the model can &#8220;<strong>cheat</strong>&#8221; by biasing its predictions toward the majority class <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?y_i" alt="">.</p>



<p class="wp-block-paragraph">Thus we can see that a model which <strong>minimizes the average misclassification error </strong>has its learning affected by the prior probabilities i.e. <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?P(y|\mathbf{x}) \propto P(\mathbf{x}|y)P(y)" alt="">.</p>



<h3 class="wp-block-heading">Logit Adjustment for Balanced Error rate</h3>



<p class="wp-block-paragraph">For a model to <strong>minimize the balanced error rate</strong> i.e. <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?P^{\text{bal}}(y|\mathbf{x}) \propto \frac{1}{L} P(\mathbf{x}|y)" alt="">, the loss should depend only on the likelihood <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi? P(\mathbf{x}|y)" alt=""> and <strong>not be affected by the prior probabilities </strong><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?P(y)" alt="">.</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array} {lll}

E_{bal} = \frac{1}{L}\sum_{i=1}^{L}P(\hat{y} \ne y_i | y_i)
\end{array}
" alt=""/>



<p class="wp-block-paragraph">This is can be done by <strong>dividing the posterior probabilities </strong><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?P(y|\mathbf{x})" alt=""> by the <strong>prior probabilities</strong>. This is equivalent to <strong>subtraction of the log prior</strong> for each class i.e <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi? \ln(P(y_i))" alt=""> from the model <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?f_y(x)" alt=""> output capturing the<strong> log probabilities</strong> <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{z}%20\in%20\mathbb{R}^{L%20\times%201}" alt="">. </p>



<p class="wp-block-paragraph">Defining <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\pi_i=P(y_i)" alt=""> as the probability of each class <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?i" alt="">, the adjusted logit for each class is, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?z_i^{\text{adj}} = f_{y_i}(\mathbf{x}) - \tau\ln (\pi_i)" alt=""/>



<p class="wp-block-paragraph">where, <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\tau" alt=""> is a hyperparameter to tune. </p>



<ul class="wp-block-list">
<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\tau=1" alt=""> : Theoretically aligns the model to <strong>minimize the balanced error rate</strong>, typically chosen value.</li>



<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?0 \lt \tau \lt 1" alt=""> : Provides a <strong>partial correction</strong>, useful for balancing overall accuracy and per-class recall in noisy datasets</li>



<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\tau \gt 1" alt=""> : <strong>Over-corrects for minority classes</strong>, pushing decision boundaries further to prioritize rare class recall</li>



<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\tau=0" alt="">: Disables the adjustment, reverting the model to standard cross entropy loss.</li>
</ul>



<p class="wp-block-paragraph">The <strong>loss function with adjusting the logits</strong> is ,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array} {lll}
L_{\text{logit adj} }
&#038; = &#038; -\ln \left( \frac{e^{f_{y_k}(\mathbf{x}) - \tau \ln(\pi_k)}}{\sum_{i=1}^L e^{f_{y_i}(\mathbf{x}) - \tau \ln \pi_i}} \right) \\
&#038; = &#038; -(f_{y_k}(\mathbf{x}) - \tau \ln (\pi_k)) + \ln \left( \sum_{i=1}^L e^{f_{y_i}(\mathbf{x}) - \tau \ln (\pi_i)} \right)
\end{array}
" alt="Logit Adjusted Loss Formula"/>



<p class="wp-block-paragraph">Incorporating <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi? \ln(\pi_i)" alt=""> into the training loss, enforces a <strong>class-dependent margin</strong>. This forces the model to &#8220;<strong>work harder</strong>&#8221; on minority classes by requiring a higher logit score for a rare class to achieve the same loss as a majority class.</p>



<p class="wp-block-paragraph">During <strong>inference</strong>, the adjustment is typically <strong>removed</strong> to use the raw learned likelihoods, resulting in a model that has learned to treat each class with equal importance regardless of its original frequency in the training set.</p>



<p class="wp-block-paragraph">Example code with logit adjusted loss @ <a href="https://github.com/dsplog/dsplog.com/blob/main/code/loss_functions_for_class_imbalance/logit_adjusted_loss.ipynb"><strong>loss_functions_for_class_imbalance/logit_adjusted_loss.ipynb</strong></a></p>



<iframe loading="lazy" src="https://nbviewer.org/github/dsplog/dsplog.com/blob/main/code/loss_functions_for_class_imbalance/logit_adjusted_loss.ipynb?flush_cache=false" width="100%" height="600"></iframe>



<h2 class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">This article covers : </p>



<p class="wp-block-paragraph"><strong>Evolution:</strong> How we move beyond standard Cross Entropy to specialized loss functions like <strong>Focal Loss</strong> and <strong>Asymmetric Loss</strong> to handle extreme class imbalance.</p>



<p class="wp-block-paragraph"><strong>Math:</strong> Detailed derivations of the gradients for <strong>Focal Loss</strong> and a Bayesian decomposition of <strong>Logit Adjustment</strong> to show how models &#8220;cheat&#8221; using prior probabilities.</p>



<p class="wp-block-paragraph"><strong>Intuition:</strong> A look at the <strong>Effective Number of Samples</strong> framework, capturing the diminishing returns of adding more data to a majority class.</p>



<p class="wp-block-paragraph"><strong>Code:</strong> Complete Python and PyTorch implementations, including toy examples and notebooks comparing manual derivations against library-standard functions.</p>
<p>The post <a rel="nofollow" href="https://dsplog.com/2026/03/05/loss-functions-for-handling-class-imbalance/">Loss functions for handling class imbalance</a> appeared first on <a rel="nofollow" href="https://dsplog.com">DSP LOG</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://dsplog.com/2026/03/05/loss-functions-for-handling-class-imbalance/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Word Embeddings using neural networks</title>
		<link>https://dsplog.com/2025/12/27/word-embeddings-using-neural-networks/</link>
					<comments>https://dsplog.com/2025/12/27/word-embeddings-using-neural-networks/#respond</comments>
		
		<dc:creator><![CDATA[Krishna Sankar]]></dc:creator>
		<pubDate>Sat, 27 Dec 2025 15:12:18 +0000</pubDate>
				<category><![CDATA[Machine Learning]]></category>
		<category><![CDATA[CBOW]]></category>
		<category><![CDATA[Embeddings]]></category>
		<category><![CDATA[GLoVE]]></category>
		<category><![CDATA[Hierarchical SoftMax]]></category>
		<category><![CDATA[NCE]]></category>
		<category><![CDATA[Negative Sampling]]></category>
		<category><![CDATA[Noise Contrastive Estimation]]></category>
		<guid isPermaLink="false">https://dsplog.com/?p=2252</guid>

					<description><![CDATA[<p>The post covers various neural network based word embedding models. Starting from the Neural Probabilistic Language Model from Bengio et al 2003, then reduction of complexity using Hierarchical softmax and Noise Contrastive Estimation. Further works like CBoW, GlOVe, Skip Gram and Negative Sampling which helped to train on much higher data. </p>
<p>The post <a rel="nofollow" href="https://dsplog.com/2025/12/27/word-embeddings-using-neural-networks/">Word Embeddings using neural networks</a> appeared first on <a rel="nofollow" href="https://dsplog.com">DSP LOG</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">In machine learning, converting the input data <strong>(text, images, or time series)</strong> —into a <strong>vector</strong> format (also known as <strong>embeddings</strong>) forms a key building block for enabling downstream tasks. This article explores in detail the architecture of some of the <strong>neural network</strong> based <strong>word embedding models</strong> in the literature.</p>



<p class="wp-block-paragraph">Papers referred : </p>



<ol class="wp-block-list">
<li><em><a href="https://www.jmlr.org/papers/volume3/bengio03a/bengio03a.pdf" target="_blank" rel="noreferrer noopener">Neural Probabilistic Language Model</a>,</em> Bengio et al 2003 
<ul class="wp-block-list">
<li>proposed a <strong>neural network </strong>architecture to <strong>jointly learn word feature vector</strong> and <strong>probability of words in a sequence</strong>.</li>
</ul>
</li>



<li><em><a href="https://proceedings.mlr.press/r5/morin05a/morin05a.pdf" target="_blank" rel="noreferrer noopener">Hierarchical Probabilistic Neural Network Language Model</a></em>, <em>Morin &amp; Bengio (2005)</em>
<ul class="wp-block-list">
<li>given the <strong>softmax</strong> layer for finding the <strong>probability scales with vocabulary</strong>, proposed a <strong>hierarchical</strong> version of <strong>softmax</strong> to reduce the complexity from <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?O(|V|)" alt=""> to <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?O(\log_2|V|)" alt="">.</li>
</ul>
</li>



<li><em><a href="https://www.jmlr.org/papers/volume13/gutmann12a/gutmann12a.pdf" target="_blank" rel="noreferrer noopener">Noise-Contrastive Estimation of Unnormalized Statistical Models, with Applications to Natural Image Statistics</a></em>, Gutmann et al 2012,
<ul class="wp-block-list">
<li>Instead of directly estimating the data distribution, noise contrastive estimation estimates the probability of a sample being from the <strong>data versus from a known noise distribution</strong>. </li>



<li>This approach was extended to <strong>neural language models</strong> in the paper <em><a href="https://arxiv.org/abs/1206.6426" target="_blank" rel="noreferrer noopener">A fast and simple algorithm for training neural probabilistic language models</a> A Mnih et al, 2012</em>.</li>
</ul>
</li>



<li><em><a href="https://arxiv.org/abs/1301.3781" target="_blank" rel="noreferrer noopener">Efficient Estimation of Word Representations in Vector Space</a></em>, Mikolov et al 2013. 
<ul class="wp-block-list">
<li>proposed <strong>simpler neural architectures</strong> with the intuition that simpler models enable training on much larger corpus of data.</li>



<li><strong>Continuous Bag of Words</strong> (CBOW) to predict the center word given the context, <strong>Skip Gram </strong>to predict surrounding words given center word was introduced. </li>
</ul>
</li>



<li><a href="https://arxiv.org/abs/1310.4546" target="_blank" rel="noreferrer noopener">Distributed Representations of Words and Phrases and their Compositionality,</a> Mikolov et al 2013
<ul class="wp-block-list">
<li> speedup provided by sub sampling of frequent words helps to improve the accuracy of the less-frequent words</li>



<li>simplified variant of<strong> Noise Contrastive estimation</strong> called <strong>Negative Sampling</strong></li>
</ul>
</li>



<li><a href="https://nlp.stanford.edu/pubs/glove.pdf" target="_blank" rel="noreferrer noopener">GloVe: Global Vectors for Word Representation,</a> Pennington et al 2014
<ul class="wp-block-list">
<li>propose that <strong>ratio of co-occurrence probabilities</strong> capture semantic information better than co-occurance probabilities.</li>
</ul>
</li>
</ol>



<span id="more-2252"></span>



<p class="wp-block-paragraph">In this post we will cover the key aspects proposed in the above papers with supporting python code. </p>






<h2 class="wp-block-heading">Neural Probabilistic Language Model (Bengio et al, 2003) </h2>



<p class="wp-block-paragraph">Reference : <a style="font-style: italic;" href="https://www.jmlr.org/papers/volume3/bengio03a/bengio03a.pdf" target="_blank" rel="noreferrer noopener">Neural Probabilistic Language Model</a><i>,</i> Bengio et al 2003 </p>



<p class="wp-block-paragraph">The probability of sequence of <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{T}" alt=""> words <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?w_1^T = \left(w_1, w_2, \ldots, w_T\right)
" alt="" align="absmiddle"> can be expressed as conditional probability of sequence of previous words, i.e</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\hat{P}(w_1^T) = \prod_{t=1}^T \hat{P}\big(w_t \,|\, w_1^{t-1}\big)

" alt="">



<p class="wp-block-paragraph">For example, consider a sequence of 4 words, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?w_1^T = (w_1, w_2, w_3, w_4) = (\text{the}, \text{cat}, \text{sat}, \text{down})" alt="">



<p class="wp-block-paragraph">Then, by the chain rule of probability:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\hat{P}(w_1^4) = \begin{array}{l}
\hat{P}(w_1) \times \\
\hat{P}(w_2 \,|\, w_1) \times \\
\hat{P}(w_3 \,|\, w_1, w_2) \times \\
\hat{P}(w_4 \,|\, w_1, w_2, w_3)
\end{array}" alt="">



<p class="wp-block-paragraph">Substituting the actual words:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\hat{P}(\text{the cat sat down}) = \begin{array}{l}
\hat{P}(\text{the}) \times \\
\hat{P}(\text{cat} \,|\, \text{the}) \times \\
\hat{P}(\text{sat} \,|\, \text{the}, \text{cat}) \times \\
\hat{P}(\text{down} \,|\, \text{the}, \text{cat}, \text{sat})
\end{array}" alt="">



<p class="wp-block-paragraph">For a long word sequence, instead of conditioning on all previous words, it is common to approximate the probability by conditioning only on the last <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?n-1" alt=""> words. That is:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\hat{P}(w_t \mid w_1^{t-1}) \approx \hat{P}(w_t \mid w_{t-n+1}^{t-1})" alt="">



<h3 class="wp-block-heading">Neural network Architecture</h3>



<p class="wp-block-paragraph">The neural probabilistic language model builds on the <strong>n-gram approximation </strong>and proposes a way to</p>



<ul class="wp-block-list">
<li><strong>Jointly</strong> learn <strong>word feature vector</strong> (each word in the vocabulary has a feature vector — a real-valued vector in <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbb{R}^k" alt="">) and</li>



<li>Learn the <strong>probability of the sequence of words</strong> in terms of sequence of word feature vectors</li>
</ul>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">The objective is to learn a model that predicts the probability of the next word given the previous <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?n-1" alt=""> words, i.e.</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?f(w_t, \ldots, w_{t-n+1}) = \hat{P}(w_t \mid w_1^{t-1})" alt="">



<p class="wp-block-paragraph">The model is subject to the following constraints:</p>



<ul class="wp-block-list">
<li>For any sequence of words, the model outputs a <strong>non-zero</strong> probability, i.e. <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?f(\dots) &gt; 0" alt="" align="absmiddle"></li>



<li>The <strong>sum of probabilities</strong> over all possible next words <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?w_i" alt="" align="absmiddle"> in the vocabulary <strong>equals 1</strong>, i.e. <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\sum_{i=1}^{|V|} f(w_i, w_{t-1}, \ldots, w_{t-n+1}) = 1" alt="" align="absmiddle"></li>
</ul>



<p class="wp-block-paragraph">where <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?|V|" alt="" align="absmiddle"> is the vocabulary size, and <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?i" alt="" align="absmiddle"> indexes over all possible words in the vocabulary.</p>



<p class="wp-block-paragraph"><strong>Note : </strong></p>



<ul class="wp-block-list">
<li><strong>Non-zero probability:</strong> Ensures that the model never completely rules out any word as a possible next word, allowing it to adapt to all possible word sequences and avoid zero-probability issues during training.</li>
</ul>



<ul class="wp-block-list">
<li><strong>Probabilities sum to one:</strong> Guarantees that <em>f</em> defines a valid probability distribution over the vocabulary for the next word, so the total probability of all possible next words is exactly 1.</li>
</ul>



<p class="wp-block-paragraph">The estimation of the function <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?f(w_t, \ldots, w_{t-n+1}) = \hat{P}(w_t \mid w_1^{t-1})" alt="" align="absmiddle"> is done as follows : </p>



<ul class="wp-block-list">
<li>for any word <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?w_i" alt="" align="absmiddle"> in the vocabulary <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?|V|" alt="" align="absmiddle">, lookup a real vector  <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?C(w_i) \in \mathbb{R}^m" alt="" align="absmiddle"></li>



<li>a function <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?g" alt="" align="absmiddle"> maps an input sequence of feature vectors for words in the context, <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\big(C(w_{t-n+1}), \ldots, C(w_{t-1})\big)" alt="" align="absmiddle"> to a conditional probability distribution over words in <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?V" alt="" align="absmiddle"> for the next word <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?w_t" alt="" align="absmiddle">
</li>
</ul>



<h3 class="wp-block-heading">Model</h3>



<p class="wp-block-paragraph">The neural network model can be expressed as:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?y = b + W \cdot x + U \cdot \tanh(d + H \cdot x)" alt="">



<p class="wp-block-paragraph">where:</p>



<ul class="wp-block-list">
<li><strong><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?x" alt="" align="absmiddle"></strong> is the concatenated input feature vector of the previous <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?n-1" alt="" align="absmiddle"> words, with dimension <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\big[(n-1) \cdot m \times 1\big]" alt="" align="absmiddle">.</li>



<li><strong><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?H" alt="" align="absmiddle"></strong> is a weight matrix of size <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\big[h \times (n-1) \cdot m\big]" alt="" align="absmiddle">, which transforms the input <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?x" alt="" align="absmiddle"> into the hidden layer space.</li>



<li><strong><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?d" alt="" align="absmiddle"></strong> is a bias vector for the hidden layer, of dimension <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\big[h \times 1\big]" alt="" align="absmiddle">.</li>



<li><strong><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?U" alt="" align="absmiddle"></strong> is a weight matrix of size <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\big[|V| \times h\big]" alt="" align="absmiddle"> that maps the hidden layer activations to the output layer, where <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?|V|" alt="" align="absmiddle"> is the vocabulary size.</li>



<li><strong><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?W" alt="" align="absmiddle"></strong> is a weight matrix of size <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\big[|V| \times (n-1) \cdot m\big]" alt="" align="absmiddle"> that connects the input <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?x" alt="" align="absmiddle"> directly to the output layer.</li>



<li><strong><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?b" alt=""></strong> is the bias vector for the output layer, of dimension <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\big[|V| \times 1\big]" alt="" align="absmiddle">.</li>



<li><strong><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?y" alt="" align="absmiddle"></strong> is the output vector containing the unnormalized log-probabilities (scores) for each word in the vocabulary, of dimension <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\big[|V|%20\times%201\big]" alt="" align="absmiddle">.</li>
</ul>



<p class="wp-block-paragraph">Using <strong>softmax</strong> to convert the output vector <strong><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?y" alt=""></strong>into a <strong>probability distribution</strong> over the vocabulary,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?f(w_t, \ldots, w_{t-n+1}) = \hat{P}(w_t \mid w_{t-n+1}^{t-1})=\hat{P}(w_t \mid w_{t-1}, \ldots, w_{t-n+1}) = a(w_t)= \frac{e^{y_{w_t}}}{\sum_i e^{y_{w_i}}" alt="">



<p class="wp-block-paragraph">Using <strong>softmax</strong> layer ensures the constraints defined earlier:</p>



<ul class="wp-block-list">
<li>All probabilities are <strong>positive</strong>, satisfying the <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?f &gt; 0" alt=""> constraint.</li>



<li>The probabilities <strong>sum to one</strong> across all possible next words, satisfying the normalization constraint <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\sum_i f = 1" alt="">.</li>
</ul>



<p class="wp-block-paragraph"><strong>Loss function</strong></p>



<p class="wp-block-paragraph">The <strong>maximum likelihood</strong> estimate for selecting the target word <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?w_t" alt=""> over all the words in vocabulary <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?|V|" alt=""> is equivalent to <strong>minimising the negative log likelihood</strong>,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathcal{L_{\text{NLL}}} = -\sum_{i=1}^{k} \log a(w_t),

" alt=""/>



<p class="wp-block-paragraph">where,</p>



<p class="wp-block-paragraph"><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?k" alt=""> is multiple word sequence examples</p>



<p class="wp-block-paragraph">As can be seen in the section on <a href="https://dsplog.com/2025/06/22/gradients-for-multi-class-classification-with-softmax/#Loss_for_multi-class_classification">Loss for Multiclass classification <sup>(refer post on Gradients for Multiclass classification with SoftMax)</sup></a>, the <strong>negative log likelihood</strong> is indeed the <strong>Categorical Cross Entropy Loss</strong>.</p>



<h3 class="wp-block-heading">Python code</h3>



<p class="wp-block-paragraph">The training of a <strong>Neural Probabilistic Language Model</strong> in PyTorch involves a few key components, each corresponding to the mathematical elements discussed earlier:</p>



<ul class="wp-block-list">
<li><strong><a href="https://pytorch.org/docs/stable/generated/torch.nn.Embedding.html" target="_blank" rel="noopener">torch.nn.Embedding</a></strong> — implements the <em><strong>word feature vector lookup</strong></em> function <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?C(w_i)" alt="">. Each word index in the vocabulary maps to a dense vector in <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbb{R}^m" alt="">.</li>



<li><strong><a href="https://pytorch.org/docs/stable/generated/torch.nn.Linear.html" target="_blank" rel="noopener">torch.nn.Linear</a></strong> — implements the<strong> fully-connected </strong>(dense) layers, corresponding to the transformation matrices <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?W" alt="">, <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?U" alt="">.</li>



<li><a href="https://pytorch.org/docs/stable/generated/torch.nn.Parameter.html" target="_blank" rel="noopener"><code><strong>torch.nn.Parameter</strong></code></a> &#8211; the parameters <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?d" alt=""> and <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?b" alt=""> are explicitly created.</li>



<li><strong><a href="https://pytorch.org/docs/stable/generated/torch.nn.functional.log_softmax.html" target="_blank" rel="noopener">torch.nn.functional.log_softmax</a></strong> — applies the <em><strong>SoftMax</strong></em> in <strong>log space </strong>to obtain <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\log \hat{P}(w_t \mid w_{t-n+1}^{t-1})" alt=""> while maintaining numerical stability.</li>



<li><strong><a href="https://pytorch.org/docs/stable/generated/torch.nn.NLLLoss.html" target="_blank" rel="noopener">torch.nn.NLLLoss</a></strong> — implements the<strong> <em>Negative Log Likelihood Loss</em></strong>, which directly minimises <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?-\log \hat{P}(w_t \mid w_{t-n+1}^{t-1})" alt=""> for the correct target word index.</li>
</ul>



<p class="wp-block-paragraph">These functions, combined with an optimizer such as <a href="https://pytorch.org/docs/stable/generated/torch.optim.SGD.html" target="_blank" rel="noopener">torch.optim.SGD</a> or <a href="https://pytorch.org/docs/stable/generated/torch.optim.Adam.html" target="_blank" rel="noopener">torch.optim.Adam</a>, form the complete training loop for the model.</p>



<p class="wp-block-paragraph"><strong>code @ <a href="https://github.com/dsplog/dsplog.com/blob/main/code/word_embeddings/neural_probabilistic_language_model.ipynb" target="_blank" rel="noreferrer noopener">word_embeddings/neural_probabilistic_language_model.ipynb</a><br></strong>The training loop implementing the model for a simple toy example of 20 sentences shows that the model is doing reasonable in predicting the probability of next word. </p>



<iframe loading="lazy" src="https://nbviewer.org/github/dsplog/dsplog.com/blob/main/code/word_embeddings/neural_probabilistic_language_model.ipynb?flush_cache=false" width="100%" height="600"></iframe>



<h2 class="wp-block-heading">Hierarchical Softmax (<em>Morin &amp; Bengio 2005</em>)</h2>



<p class="wp-block-paragraph">Reference : <em><a href="https://proceedings.mlr.press/r5/morin05a/morin05a.pdf" target="_blank" rel="noreferrer noopener">Hierarchical Probabilistic Neural Network Language Model</a></em>, <em>Morin &amp; Bengio (2005)</em></p>



<p class="wp-block-paragraph">As computing of the probability of all tokens using SoftMax scales with vocabulary size <strong><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?|V|" alt=""></strong> , in the paper <em>Hierarchical Probabilistic Neural Network Language Model</em>, <em>Morin &amp; Bengio (2005)</em> proposed an approach to reduce the complexity from <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?O(|V|)" alt=""> to <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?O(\log_2|V|)" alt="">.</p>



<p class="wp-block-paragraph">Based on the intuition shared in the paper <em><a href="https://arxiv.org/abs/cs/0108006" target="_blank" rel="noreferrer noopener">Classes for Fast Maximum Entropy Training</a>, J Goodman 2001</em>, to compute <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?P(Y=y|X=x)">, instead of directly computing the probability of the target word <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?y"> given the context words <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?x">, we decompose it hierarchically as product of :</p>



<ul class="wp-block-list">
<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?P(C=c(y)|X=x)">   : probability of <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?y"> in class <strong><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?C=c(y)" alt=""></strong> given context <strong><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?X=x" alt=""></strong> </li>



<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?P(Y|C=c(y),X=x)">   : probability of word <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?Y=y" alt="">, given <strong><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?y" alt=""></strong> is in class <strong><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?c(y)" alt=""></strong> AND context <strong><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?X=x" alt=""></strong> </li>
</ul>



<p class="wp-block-paragraph">i.e</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?P(Y=y|X=x)%20=%20P(C=c(y)|X=x)\,P(Y=y|C=c(y),X=x)" alt="P(Y=y|X=x)=P(C=c(y)|X=x)\cdot P(Y=y|C=c(y),X=x)">



<p class="wp-block-paragraph">where, </p>



<ul class="wp-block-list">
<li><strong><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?y" alt="y"></strong> : the target word we want to predict (e.g., “dog”).</li>



<li><strong><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?x" alt="x"></strong> : the context (the surrounding words or features used to predict the next word, e.g., “the big”).</li>



<li><strong><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?c(y)" alt="c(y)"></strong> : the cluster/class that the target word <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?y" alt="y"> belongs to (e.g., <em>dog</em> → Noun class).</li>
</ul>



<p class="wp-block-paragraph"></p>



<h3 class="wp-block-heading">Derivation</h3>



<p class="wp-block-paragraph">To derive the the decomposition of <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?P(Y=y|X=x)" align="absmiddle">, let us introduce a class variable <strong><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?C=c(y)" alt="c(y)" align="absmiddle">, </strong>i.e. the word <strong><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?y" alt="y" align="absmiddle"></strong> belongs to the class <strong><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?c(y)" alt="c(y)" align="absmiddle"></strong>. </p>



<p class="wp-block-paragraph">Then the probability of <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?P(Y=y|X=x)"> can be written as the sum of <strong><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?y" alt="y"></strong> is in the class or not</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}
P(Y=y\mid X=x)  
&#038;=&#038; P\big(Y=y,\,C=c(y)\mid X=x\big) + {P\big(Y=y,\,C\neq c(y)\mid X=x\big)}
\end{array}" alt="">



<p class="wp-block-paragraph">Since each word <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?Y=y" alt="y" align="absmiddle"> belongs to exactly one class, the term <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?P(Y,\,C\ne c(y)|X=x)" align="absmiddle"> is zero.</p>



<p class="wp-block-paragraph">Hence,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}
P(Y=y\mid X=x)  
&#038;=&#038; P\big(Y=y,\,C=c(y)\mid X=x\big) + \underbrace{P\big(Y=y,\,C\neq c(y)\mid X=x\big)}_{=\,0} \\
&#038;=&#038; P\big(Y=y,\,C=c(y)\mid X=x\big)
\end{array}" alt="">



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">The term <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?P(Y=y,\,C = c(y)|X=x)"> can be expanded using the <strong>chain rule of conditional probabilities</strong> as follows:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}
P\big(Y{=}y,\,C{=}c(y)\mid X{=}x\big)
&#038;= \frac{P\big(Y{=}y,\,C{=}c(y),\,X{=}x\big)}{P(X{=}x)} \\
&#038;= \frac{P\big(C{=}c(y),\,X{=}x\big)\cdot \;P\big(Y{=}y\mid C{=}c(y),\,X{=}x\big)}{P(X{=}x)} \\
&#038;= P\big(C{=}c(y),\,X{=}x\big)\frac{\;P\big(Y{=}y\mid C{=}c(y),\,X{=}x\big)}{P(X{=}x)} \\

&#038;= P\big(C{=}c(y)\mid X{=}x\big)\cdot P(X{=}x)\frac{\;P\big(Y{=}y\mid C{=}c(y),\,X{=}x\big)}{P(X{=}x)}\\
&#038;= P\big(C{=}c(y)\mid X{=}x\big)\;P\big(Y{=}y\mid C{=}c(y),\,X{=}x\big).
\end{array}" alt="">



<p class="wp-block-paragraph">Summarizing,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?P(Y=y|X=x)%20=%20P(C=c(y)|X=x)\,P(Y=y|C=c(y),X=x)" alt="P(Y=y|X=x)=P(C=c(y)|X=x)P(Y=y|C=c(y),X=x)">



<p class="wp-block-paragraph">Thus, computing <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?P(Y=y|X=x)"> reduces to first predicting the <strong>class <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?c(y)"> given the context <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?x"></strong> and then <strong>predicting the word <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?y"> within that class conditioned on <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?x"></strong>.</p>



<p class="wp-block-paragraph"><strong>Complexity</strong></p>



<p class="wp-block-paragraph">With this approach, instead of computing probability over the entire vocabulary <strong><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?|V|" alt="|V|" align="absmiddle"></strong>, this is broken down to  computing the probability over the classes, and then computing the probability over the words within the chosen class. <br><br>Taking the example shared in the paper, assuming that <strong><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?|V|" alt="|V|" align="absmiddle"></strong> is 10000 words, and we break it down into 100 classes, with each class having 100 words. Then the computations needed are:</p>



<ul class="wp-block-list">
<li>Finding probability over 100 classes</li>



<li>Finding probability over 100 words in the chosen class</li>
</ul>



<p class="wp-block-paragraph">This reduces the computation to ~200 probability calculations instead of 10000 in the flat structure. Equivalently, the complexity reduces from <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?|V|" alt="|V|" align="absmiddle"> to <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\sqrt{|V|}" alt="\sqrt{|V|}" align="absmiddle"> operations.</p>



<p class="wp-block-paragraph"></p>



<h3 class="wp-block-heading">Binary Tree</h3>



<p class="wp-block-paragraph">An alternative to class-based grouping is to arrange the vocabulary words as the <strong>leaves</strong> of a <strong>binary tree</strong>. Each internal node corresponds to a binary decision (left or right child), and each <strong>leaf</strong> corresponds to <strong>one word</strong> in the vocabulary. This hierarchical arrangement reduces the search complexity from <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?O(|V|)" alt=""> to <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?O(\log_2|V|)" alt="">, making it efficient for large vocabularies.</p>



<p class="wp-block-paragraph">For constructing the binary tree, multiple approaches are possible :</p>



<ul class="wp-block-list">
<li><strong>Perfect binary tree</strong>
<ul class="wp-block-list">
<li><span style="background-color: rgba(0, 0, 0, 0.2); color: initial;">Requires the leaves to be a power of 2 (for eg, 2, 4, 8, 16 etc). </span></li>



<li><span style="color: initial;">If </span><strong style="color: initial;"><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?|V|" alt="|V|"></strong><span style="color: initial; background-color: rgba(0, 0, 0, 0.2);"> is not a power of 2, some leaves will remain unused</span></li>



<li><span style="color: initial;">To reach every word, it takes the same path length i.e </span><img decoding="async" style="color: initial;" src="https://dsplog.com/cgi-bin/mimetex.cgi?\lceil \log_2{|V|} \rceil" alt="ceil(log2(|V|))" align="absmiddle"><span style="color: initial;">.</span></li>



<li>Average depth:<span style="color: initial;"> exactly </span><img decoding="async" style="color: initial;" src="https://dsplog.com/cgi-bin/mimetex.cgi?\log_2{|V|}" alt="log2(|V|)" align="absmiddle"><span style="color: initial;"> since all leaves are at the same level.</span></li>
</ul>
</li>



<li><strong>Balanced binary tree</strong>
<ul class="wp-block-list">
<li><span style="color: initial;">Tries to keep the left and right subtrees of equal size.</span></li>



<li><span style="color: initial;">When the vocabulary is not a power of 2, leaf depths differ by at most 1.</span></li>



<li><span style="color: initial;">No empty leaves; every leaf corresponds to a word.</span></li>



<li>Average depth:<span style="color: initial;"> approximately </span><img decoding="async" style="color: initial;" src="https://dsplog.com/cgi-bin/mimetex.cgi?\log_2{|V|}" alt="log2(|V|)" align="absmiddle"><span style="color: initial;">, often slightly smaller because some leaves are shallower.</span></li>
</ul>
</li>



<li><strong>Word frequency based tree</strong>
<ul class="wp-block-list">
<li><span style="color: initial;">Constructed using a Huffman coding structure, frequent words are placed closer to the root node while rare words are deeper.</span></li>



<li><span style="color: initial;">This minimises the average number of binary decisions required to reach a word.</span></li>



<li>Average depth:<span style="color: initial;"> depends on the frequency distribution; it is minimised and typically much smaller than </span><img decoding="async" style="color: initial;" src="https://dsplog.com/cgi-bin/mimetex.cgi?\log_2{|V|}" alt="log2(|V|)" align="absmiddle"><span style="color: initial;"> for natural language vocabularies (due to Zipf’s law).</span></li>
</ul>
</li>
</ul>



<p class="wp-block-paragraph">For a toy corpus of 12 words, construction of the binary tree with the above approaches is shown below. <strong>code @ <a href="https://github.com/dsplog/dsplog.com/blob/main/code/word_embeddings/binary_tree.ipynb" target="_blank" rel="noreferrer noopener">word_embeddings/binary_tree.ipynb</a></strong><br></p>



<iframe loading="lazy" src="https://nbviewer.org/github/dsplog/dsplog.com/blob/main/code/word_embeddings/binary_tree.ipynb?flush_cache=false" width="100%" height="600"></iframe>



<h3 class="wp-block-heading">Model</h3>



<p class="wp-block-paragraph">The probability of the next word given the context <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?w_{t-1},...,w_{t-n+1}" alt="probability formula"> can be written as:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}
P(v|w_{t-1},...,w_{t-n+1})
&#038;=&#038;\prod_{j=1}^{p}P(b_j(v)|b_1(v),...,b_{j-1}(v),w_{t-1},...,w_{t-n+1})  \\
\end{array}
" alt="probability formula">



<p class="wp-block-paragraph">where, </p>



<ul class="wp-block-list">
<li>each word <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?v" alt="" align="absmiddle"> is represented by a <strong>bit vector</strong> <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?(b_1(v),b_2(v),...,b_p(v))" alt="(b1(v), b2(v), ..., bp(v))" align="absmiddle"></li>



<li>the path <em>p</em> depends on the position of the word in the binary tree.</li>
</ul>



<p class="wp-block-paragraph">For example, if each word is represented by 4 bits, then the probability of predicting the next word given the context <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?w_{t-1},...,w_{t-n+1}" align="absmiddle"> becomes:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll} P(v|w_{t-1},...,w_{t-n+1}) &#038;=&#038;P(b_1(v)|w_{t-1},...,w_{t-n+1}) \\ &#038;\times&#038;P(b_2(v)|b_1(v),w_{t-1},...,w_{t-n+1}) \\ &#038;\times&#038;P(b_3(v)|b_1(v),b_2(v),w_{t-1},...,w_{t-n+1}) \\ &#038;\times&#038;P(b_4(v)|b_1(v),b_2(v),b_3(v),w_{t-1},...,w_{t-n+1}) \end{array}" alt="4-bit chain rule example">



<p class="wp-block-paragraph">Taking log on both sides converts the product into a summation:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll} \log P(v|w_{t-1},...,w_{t-n+1}) &#038;=&#038;\log P(b_1(v)|w_{t-1},...,w_{t-n+1}) \\ &#038;+&#038;\log P(b_2(v)|b_1(v),w_{t-1},...,w_{t-n+1}) \\ &#038;+&#038;\log P(b_3(v)|b_1(v),b_2(v),w_{t-1},...,w_{t-n+1}) \\ &#038;+&#038;\log P(b_4(v)|b_1(v),b_2(v),b_3(v),w_{t-1},...,w_{t-n+1}) \end{array}" alt="log form 4 bit">



<p class="wp-block-paragraph">In general, for a word represented with <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?p"> bits:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\log P(v|w_{t-1},...,w_{t-n+1})=\sum_{j=1}^{p}\log P(b_j(v)|b_1(v),...,b_{j-1}(v),w_{t-1},...,w_{t-n+1})" alt="general log form">



<p class="wp-block-paragraph">The bit vector corresponds to the <strong>path</strong> (left or right at each nodes) starting from the root node to the leaf node (the word). Each internal node outputs a probability of going right (<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?b=1" alt="" align="absmiddle"> ). For the true label <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?b \in [0,1]" alt="" align="absmiddle">, the binary cross-entropy loss at that node is:</p>



<p class="wp-block-paragraph"><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?L_{node}=-\big[b\cdot\log(p)+(1-b)\cdot\log(1-p)\big]" alt="binary cross entropy"></p>



<p class="wp-block-paragraph">The total loss for predicting <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?v" alt=""> is the sum of the node losses along the path:</p>



<p class="wp-block-paragraph"><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?L(v)=-\sum_{j=1}^{p}\big[b_j(v)\log(p_j)+(1-b_j(v))\log(1-p_j)\big]" alt="word loss"></p>



<p class="wp-block-paragraph">where </p>



<ul class="wp-block-list">
<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?p_j" alt="pj" align="absmiddle"> is the predicted probability at the <em>j-th</em> node along the path. </li>



<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?b_j(v)" alt="bj" align="absmiddle"> denotes the binary choice (0 or 1) at the <em>j-th</em> internal node along the path to word <em><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?v" alt="" align="absmiddle"></em>.</li>
</ul>



<p class="wp-block-paragraph">This is equivalent to the negative log-likelihood of the full word probability.</p>



<p class="wp-block-paragraph"><strong>Binary Node Predictor</strong></p>



<p class="wp-block-paragraph">Each internal node of the binary tree acts as a logistic classifier that decides left vs right, based on both the <em>(n−1)-gram context</em> and the <em>node embedding</em>. The conditional probability of taking the binary decision <em><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?b=1" alt=""></em> at a node, given the past context, is modelled as:</p>



<p class="wp-block-paragraph"><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?P(b=1|\;node, w_{t-1},...,w_{t-n+1})=\sigma(\alpha_{node}+\beta' \tanh(c+Wx+UN_{node}))" alt="probability equation"></p>



<p class="wp-block-paragraph">where, </p>



<ul class="wp-block-list">
<li>the sigmoid function is <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\sigma(y)=\frac{1}{1+e^{-y}}" alt="sigmoid function">.</li>



<li>for any word <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?w_i" alt=""> in the vocabulary <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?|V|" alt="">, lookup a real vector <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?C(w_i) \in \mathbb{R}^m" alt=""></li>



<li><strong><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?x" alt="x"></strong> : concatenation of the previous (n−1) word embeddings, <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?x \in \mathbb{R}^{(n-1)\cdot m \times 1}" alt=""></li>



<li><strong><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha_{node}" alt="alpha node"></strong> : bias term specific to the node, <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha_{node} \in \mathbb{R}" alt="scalar"></li>



<li><strong><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\beta" alt="beta"></strong> : projection vector applied after hidden nonlinearity, <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\beta \in \mathbb{R}^{h \times 1}" alt="beta in R^h"></li>



<li><strong><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?c" alt="c"></strong> : bias for hidden layer, <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?c \in \mathbb{R}^{h}" alt="c in R^{h \times 1}"></li>



<li><strong><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?W" alt="W"></strong> : weight matrix projecting context to hidden space, <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?W \in \mathbb{R}^{h \times (n-1)\cdot m}" alt="W in R^(h x (n-1)m)"></li>



<li><strong><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?U" alt="U"></strong> : weight matrix projecting node embedding, <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?U \in \mathbb{R}^{h \times d_{node}}" alt="U in R^(h x d_node)"></li>



<li><strong><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?N_{node}" alt="N node"></strong> : embedding vector for the current node, <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?N_{node} \in \mathbb{R}^{d_{node} \times 1}" alt="N_node in R^(d_node)"></li>
</ul>



<p class="wp-block-paragraph">The matrices <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?W" alt="">, <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?U" alt="">, <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\beta" alt=""> (projection vector) and the bias <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?c" alt=""> are <strong>common parameters</strong> shared across all nodes. </p>



<p class="wp-block-paragraph">Each internal node has its own <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha_{node}" alt=""> (scalar bias), and <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?N_{node}" alt=""> (node embedding). These take care of the decision boundary at each internal node.</p>



<h3 class="wp-block-heading">Python code &#8211; Naive implementation using for-loops</h3>



<p class="wp-block-paragraph">For the toy corpus, naive implementation of hierarchical softmax using for-looops is provided.</p>



<ol class="wp-block-list">
<li>Defined a toy corpus of 20 sentences which has around 42 words. </li>



<li>Training example is constructed as 3 context words and the corresponding target word </li>



<li>Constructed a balanced binary tree, which has 41 internal nodes</li>



<li>Model defined with the binary node predictor for each of the nodes
<ul class="wp-block-list">
<li>The parameters <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?W" alt="">, <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?U" alt="">, <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\beta" alt=""> (projection vector) and the bias <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?c" alt=""> are shared across all nodes.</li>



<li>Each internal node has its own <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha_{node}" alt=""> and <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?N_{node}" alt=""> parameter</li>
</ul>
</li>



<li>For each target word in the training example, the path to the leaf node via the tree is known</li>



<li>Using the binary decision at each path, the loss for each example is computed </li>



<li>The loss is back propagated to find the parameters which minimizes the loss</li>
</ol>



<p class="wp-block-paragraph">Using the trained model, for finding the probabilities for top-k words given the context words,</p>



<ul class="wp-block-list">
<li>For each word in the vocabulary find the path to its leaf node</li>



<li>Starting from the root node, find the probability at each node</li>



<li>Based on the known decision (right vs left) at each node, use either  <em>p</em> for going right OR (1-p) for going left</li>



<li>The joint probability is the product of probabilities at each node. </li>



<li>For numerical stability (loss of accuracy when many small probabilities are multiplied), log of probabilities is found and then summed</li>



<li>On the final log probability is exponentiated to get back in probability (optional)</li>



<li>Then the top-k candidate words are printed </li>
</ul>



<p class="wp-block-paragraph"><strong>code @ <a href="https://github.com/dsplog/dsplog.com/blob/main/code/word_embeddings/hierarchical_probabilistic_neural_language_model.ipynb" target="_blank" rel="noreferrer noopener">word_embeddings/hierarchical_probabilistic_neural_language_model.ipynb</a><br></strong></p>



<iframe loading="lazy" src="https://nbviewer.org/github/dsplog/dsplog.com/blob/main/code/word_embeddings/hierarchical_probabilistic_neural_language_model.ipynb?flush_cache=false" width="100%" height="600"></iframe>



<h3 class="wp-block-heading">Python code &#8211; Vectorized implementation</h3>



<p class="wp-block-paragraph">As one can imagine, using the for loops significantly slows down the training. To form a vectorized implementation, the following was done.</p>



<ol class="wp-block-list">
<li><strong>Path preparation</strong>
<ul class="wp-block-list">
<li>Assign a unique id to every internal node in the binary tree.</li>



<li>Precompute for each word:
<ul class="wp-block-list">
<li>sequence of node-ids on the path to its leaf,</li>



<li>binary decision targets at each node.</li>
</ul>
</li>



<li>Pad all paths to a fixed length <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?p_{pad}"> using a dummy (UNK) node id. Build a mask to ignore padded positions.</li>



<li></li>
</ul>
</li>



<li><strong>Parameter lookup</strong>
<ul class="wp-block-list">
<li>Use <code>torch.nn.Embedding</code> to fetch node-specific parameters <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha_{nodes}"> (biases) and <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?N_{nodes}"> (embeddings).</li>



<li>Shapes:
<ul class="wp-block-list">
<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?N_{nodes} \in \mathbb{R}^{n_{batch}\times p_{pad}\times d_{node}}"></li>



<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha_{nodes} \in \mathbb{R}^{n_{batch}\times p_{pad}}"></li>



<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?x \in \mathbb{R}^{n_{batch}\times (n-1)\cdot m}"></li>
</ul>
</li>
</ul>
</li>



<li><strong>Forward pass (vectorized)</strong>
<ul class="wp-block-list">
<li>Context projection: <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?Wx \in \mathbb{R}^{n_{batch}\times h}"> and bias <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?c \in \mathbb{R}^{h}">.</li>



<li>Node projection: <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?UN_{nodes} \in \mathbb{R}^{n_{batch}\times p_{pad}\times h}"> using <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?U \in \mathbb{R}^{h\times d_{node}}">.</li>



<li>Broadcast: <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?c+Wx+UN_{nodes} \in \mathbb{R}^{n_{batch}\times p_{pad}\times h}">.</li>



<li>Nonlinearity : <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?H=\tanh(c+Wx+UN_{nodes})">.</li>



<li>Projection: <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?logits=\alpha_{nodes}+(H\cdot\beta) \in \mathbb{R}^{n_{batch}\times p_{pad}}"> with <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\beta \in \mathbb{R}^{h\times 1}">.</li>



<li>Probabilities: <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?p=\sigma(logits) \in \mathbb{R}^{n_{batch}\times p_{pad}}">.</li>
</ul>
</li>



<li><strong>Loss and masking</strong>
<ul class="wp-block-list">
<li>Binary cross-entropy is computed between <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?p"> and the decision targets, with mask applied to ignore padded nodes:
<ul class="wp-block-list">
<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?loss_i=\sum_{j}mask_{ij}\cdot BCE(p_{ij},target_{ij})"></li>



<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?loss=\frac{1}{n_{batch}}\sum_i loss_i"></li>
</ul>
</li>
</ul>
</li>
</ol>



<p class="wp-block-paragraph">Notes : </p>



<ul class="wp-block-list">
<li>Compute <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?Wx+c"> once per batch and broadcast, instead of recomputing per path.</li>



<li>UNK node parameters are trainable but excluded from loss using the mask.</li>
</ul>



<p class="wp-block-paragraph"><strong>code @ <a href="https://github.com/dsplog/dsplog.com/blob/main/code/word_embeddings/vectorized_hierarchical_probabilistic_neural_language_model.ipynb" target="_blank" rel="noreferrer noopener">word_embeddings/vectorized_hierarchical_probabilistic_neural_language_model.ipynb</a></strong></p>



<iframe loading="lazy" src="https://nbviewer.org/github/dsplog/dsplog.com/blob/main/code/word_embeddings/vectorized_hierarchical_probabilistic_neural_language_model.ipynb?flush_cache=false" width="100%" height="600"></iframe>



<p class="wp-block-paragraph"></p>



<h2 class="wp-block-heading">Noise contrastive estimation (Gutmann et al 2012, Mnih et al 2012)</h2>



<p class="wp-block-paragraph">As computing of the probability using SoftMax scales with vocabulary size <strong><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?|V|" alt=""></strong>, in the paper <em><a href="https://www.jmlr.org/papers/volume13/gutmann12a/gutmann12a.pdf" target="_blank" rel="noreferrer noopener">Noise-Contrastive Estimation of Unnormalized Statistical Models, with Applications to Natural Image Statistics</a></em>, Gutmann et al 2012, provided an approach called <strong>Noise Contrastive Estimation (NCE)</strong>. Instead of directly estimating the data distribution, <strong>NCE estimates the probability of a sample being from the data versus from a known noise distribution</strong>. By learning the ratio between the data and noise distributions, and knowing the noise distribution, the data distribution can be inferred.</p>



<p class="wp-block-paragraph">This approach was extended to <strong>neural language models</strong> in the paper <em><a href="https://arxiv.org/abs/1206.6426" target="_blank" rel="noreferrer noopener">A fast and simple algorithm for training neural probabilistic language models</a> A Mnih et al, 2012</em>.</p>



<h3 class="wp-block-heading">Model</h3>



<p class="wp-block-paragraph">In <strong>Neural Probabilistic Language model</strong>, the estimation of the probability of the words using <strong>SoftMax</strong> computation is,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{llll}
\hat{P}(w_t \mid w_{t-1}, \ldots, w_{t-n+1}) = \hat{P}(w_t \mid h) &#038; = &#038;  \frac{\exp({y_{w_t}})}{\sum_i \exp\left(y_{w_i}\right)} \\

&#038; = &#038; \frac{\exp({s_\theta(w_t,h)})}{\sum_i \exp\left(s_\theta(w_i,h\)\right)}\\

\end{array}
" alt="">



<p class="wp-block-paragraph">where, </p>



<ul class="wp-block-list">
<li>context words is <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?h = \left[w_{t-1}, \ldots, w_{t-n+1}\right]" align="absmiddle"></li>



<li>term in numerator <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?y_{w_t}=s_\theta(w_t,h)" align="absmiddle"> is estimated using a neural model with parameters <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\theta" align="absmiddle"> for the target word <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?w_t" align="absmiddle"> using the context words <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?h" align="absmiddle"></li>



<li>term in denominator is sum over all the words in the vocabulary i.e. <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\sum_i e^{y_{w_i}}=\sum_i e^{s_\theta(w_i,h)}" align="absmiddle"></li>
</ul>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">Let us define a set <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{W} = \left\{w_1, w_2, \cdots, w_{T_x+T_n}\right\}" alt="" align="absmiddle">, which is the union of two sets <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\left{\mathbf{X},\ \mathbf{N}\right}" align="absmiddle">, where</p>



<ul class="wp-block-list">
<li>the class label <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?C_t=1 \quad : \quad w_t  \in \mathbf{X}" align="absmiddle"> when the word is from the true target word distribution</li>



<li>the class label <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?C_t=0 \quad : \quad w_t \in \mathbf{N}" align="absmiddle"> when the word is NOT from the true target word distribution</li>



<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?T_x"> is the number of <strong>true (data) samples</strong> in the batch (or dataset)</li>



<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?T_n"> is the the number of <strong>noise samples</strong> generated for contrast</li>
</ul>



<p class="wp-block-paragraph">The formulation is, </p>



<ul class="wp-block-list">
<li>for each true (data) sample <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\left(h,w^+\right)" alt="" align="absmiddle"> will draw <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?k" alt="" align="absmiddle"> noise samples <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\left(w_1^-, w_2^-, \cdots, w_k^-\right)" alt="" align="absmiddle">  from <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?P_n" alt="" align="absmiddle"></li>



<li>the model has to learn a binary classification where the sample <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?w" align="absmiddle"> is from the <strong>true distribution </strong><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?C_t=1" align="absmiddle"> or from the <strong>noise distribution</strong> <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?C_t=0" align="absmiddle"></li>
</ul>



<p class="wp-block-paragraph">Further, instead of computing the <strong>denominator term for normalzing to probabilities</strong>, learn it as a context dependent normalizing term, i.e.</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{llll}

\hat{P}(w_t \mid h) = P_{\theta}(w \mid h) = &#038; \frac{\exp({s_\theta(w,h)})}{\mathbf{Z}_\theta(h)}
\quad, \text{where } \mathbf{Z}_\theta(h)=\sum_i \exp\left(s_\theta(w_i,h\)
\\

\end{array}
" alt="">



<p class="wp-block-paragraph">The probability of sample coming from the true distribution given the context <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?h"> can be written as , </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?P_{\theta}(w|h)=P(w|C_t=1)" alt="">



<p class="wp-block-paragraph">Similarly, the probability of the word in noise distribution is,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?P_{n}(w)=P(w|C_t=0)" alt="">



<p class="wp-block-paragraph">Further, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lr} 
P(C_t=1)&#038; = &#038;\frac{T_x}{T_x+T_n} \\
P(C_t=0)&#038; = &#038;\frac{T_n}{T_x+T_n}\\
k = \frac{P(C_t=0)}{P(C_t=1)} &#038; = \frac{T_n}{T_x}
\end{array}">



<p class="wp-block-paragraph"><p>Since <strong>NCE</strong> reframes the problem as a <strong>binary classification task</strong> (distinguishing true data from noise), the class labels <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?C_t"> are modelled as <strong>independent Bernoulli variables</strong>. Consequently, the <strong>conditional log likelihood</strong> is the sum of the binary cross-entropy terms: </p></p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{llll}

\mathbf{L} (\theta) &#038; = &#038; \sum_{t=1}^{T_x+T_n} \left[C_t\log ( P(C_t=1|w)) + (1-C_t)\log(P(C_t=0|w)) \right]\\
&#038; = &#038; \sum_{t=1}^{T_x} \log (P(C_t=1|w)) + \sum_{t=1}^{T_n} \log(P(C_t=0|w)) \\
\end{array}, 
\\
\\
" alt="">



<p class="wp-block-paragraph">For a single true target word  <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?w"> and its corresponding <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?k"> noise samples </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{llll}
\mathcal{L}_t (\theta)
&#038; = &#038; \log (P(C_t=1|w)) + \sum_{j=1}^{k} \log(P(C_t=0|w)) \\
\end{array} 
\\
\\
" alt="">



<p class="wp-block-paragraph">To evaluate this loss, need to express <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?P(C_t=1|w)"> in terms of model parameters. Using Bayes Rule, the probability that the class is true <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?C_t=1"> given the context <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?h"> and target word <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?w"> is,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}
P(C_t=1|w) &#038; = &#038; \frac{P(w|C_t=1)P(C_t=1)}{P(w)}\\
&#038; = &#038; \frac{P(w|C_t=1)P(C_t=1)}{P(w|C_t=1)P(C_t=1) + P(w|C_t=0)P(C_t=0)}\\
&#038; = &#038; \frac{P(w|C_t=1)}{P(w|C_t=1) + P(w|C_t=0)\frac{P(C_t=0)}{P(C_t=1)}}\\
&#038; = &#038; \frac{P_{\theta}(w|h)}{P_{\theta}(w|h) + kP_n(w)}\\
&#038; = &#038; \frac{1}{1 + \frac{k\cdot P_n(w)}{P_{\theta}(w|h)}}\\
&#038; = &#038;  \frac{1}{1 + \frac{k P_n(w)}{\left(\frac{\exp({s_\theta(w,h)})}{\mathbf{Z}_\theta(h)}\right)}} \\
&#038; = &#038;  \frac{1}{1 + \frac{k P_n(w)\mathbf{Z}_\theta(h)}{\exp({s_\theta(w,h)})}} \\
\end{array} 


\quad \text{,where } P_{\theta}(w \mid h) =  \frac{\exp({s_\theta(w,h)})}{\mathbf{Z}_\theta(h)}
" alt="">



<p class="wp-block-paragraph">This gives the general probability for any word <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?w">. When calculating the loss for a true target word, we substitute <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?w=w^+"> to get the positive sample probability</p>



<p class="wp-block-paragraph">Converting to sigmoid form which is used in logistic regression, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}
P(C_t=1|w^+)     
&#038; = &#038;  \frac{1}{1 + \frac{k P_n(w^+)\mathbf{Z}_\theta(h)}{\exp({s_\theta(w^+,h)})}} 
&#038; = &#038; \frac{1}{1+\frac{1}{z^+}} 
&#038; = &#038;  \frac{1}{1+\exp(\log(1/z^+))}  
&#038; = &#038; \frac{1}{1+\exp(-\log(z^+))} \\
&#038; = &#038; \sigma( \log(z^+))\\
\end{array}

\\
\\
\text{where, }\\
\begin{array}{llll}

z^+ &#038; = &#038;\frac{\exp({s_\theta(w^+,h)}) }{k P_n(w^+)\mathbf{Z}_\theta(h)} \\

\log(z^+) &#038; = &#038; \log\left(\frac{\exp({s_\theta(w^+,h)}) }{k P_n(w)\mathbf{Z}_\theta(h)} \right) \\
&#038; = &#038; \log \left(\exp({s_\theta(w^+,h)} ) \right) - \log(k P_n(w^+)) - \log (\mathbf{Z}_\theta(h)) \\
&#038; = &#038; \left[ s_\theta(w^+,h) - \log(k P_n(w^+)) - \log (\mathbf{Z}_\theta(h))\right]

\end{array} 

" alt="">



<p class="wp-block-paragraph">Similarly, for the target word from noise distribution i.e. the probability that the class is noise <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?C_t=0"> given the context <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?h"> and target word <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?w"> is,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}
P(C_t=0|w) &#038; = &#038; \frac{P(w|C_t=0)P(C_t=0)}{P(w)}\\\\
&#038; = &#038; \frac{P(w|C_t=0)P(C_t=0)}{P(w|C_t=1)P(C_t=1) + P(w|C_t=0)P(C_t=0)}\\\\
&#038; = &#038; \frac{P(w|C_t=0)P(C_t=0)/P(C_t=1)}{P(w|C_t=1) + P(w|C_t=0)\dfrac{P(C_t=0)}{P(C_t=1)}}\\\\
&#038; = &#038; \frac{k\,P_n(w)}{P_{\theta}(w|h) + k\,P_n(w)}\\\\
&#038; = &#038; \frac{1}{1 + \dfrac{P_{\theta}(w|h)}{k\,P_n(w)}}\\\\
&#038; = &#038; \frac{1}{1 + \dfrac{\exp\!\big(s_\theta(w,h)\big)}{k\,P_n(w)\,\mathbf{Z}_\theta(h)}}\\\\
\end{array}
\quad,\ \text{where } P_{\theta}(w \mid h) =  \frac{\exp\!\big(s_\theta(w,h)\big)}{\mathbf{Z}_\theta(h)}
" alt="">



<p class="wp-block-paragraph">This gives the general probability for any word <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?w">. When calculating the loss for a noise target word, we substitute <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?w=w^-"> to get the noise sample probability</p>



<p class="wp-block-paragraph">Converting to sigmoid form which is used in logistic regression, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}
P(C_t=0|w^-) &#038; = &#038; \frac{1}{1 + \dfrac{\exp\!\big(s_\theta(w^-,h)\big)}{k\,P_n(w^-)\,\mathbf{Z}_\theta(h)}}
&#038; = &#038; \frac{1}{1+\frac{1}{z^-}} 
&#038; = &#038; \frac{1}{1+\exp(\log(1/z^-))}  
&#038; = &#038; \frac{1}{1+\exp(-\log(z^-))} \\
&#038; = &#038;  \sigma( \log(z^-))
\end{array}

\\
\text{where, } \\
\begin{array}{llll}

z^- &#038; = &#038; \frac{k P_n(w^-)\mathbf{Z}_\theta(h)}{\exp({s_\theta(w^-,h)}) }  \\
\log(z^-) &#038; = &#038; \log\left(\frac{k P_n(w^-)\mathbf{Z}_\theta(h)}{\exp({s_\theta(w^-,h)}) } \right) \\
&#038; = &#038;   \log(k P_n(w^-)) + \log (\mathbf{Z}_\theta(h)) -\log \left(\exp({s_\theta(w^-,h)})\right) \\
&#038; = &#038;  -\left[s_\theta(w^-,h)  -\log(k P_n(w^-)) - \log (\mathbf{Z}_\theta(h))  \right]

\end{array}

" alt="">



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">Plugging in the terms to the log likelihood for a single example,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{llll}

\mathbf{L}_t (\theta) 
&#038; = &#038; \log (P(C_t=1|w)) + \sum_{j=1}^{k} \log(P(C_t=0|w)) \\
&#038; = &#038; \log (\sigma( \log(z^+))) + \sum_{j=1}^{k} \log(\sigma( \log(z^-))) \\
&#038; = &#038;\log (\sigma(\left[ s_\theta(w^+,h) - \log(k P_n(w^+)) - \log (\mathbf{Z}_\theta(h))\right])) +\\
&#038;&#038; \sum_{j=1}^{k} \log(\sigma(-\left[s_\theta(w^-,h)  -\log(k P_n(w^-)) - \log (\mathbf{Z}_\theta(h))  \right] )) \\
 

\end{array}, 
\\
\\
" alt="">



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">To obtain the objective function for the entire dataset, sum the log-likelihoods over all true training examples <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?t=1 \dots T_x">. For each training example at step <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?t">, we have a specific context <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?h_t">, a true target word <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?w_t">, and a fresh set of <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?k"> noise samples.</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{llll}

\mathbf{L}(\theta) &#038;=&#038;
\sum_{t=1}^{T_x} \mathcal{L}_t (\theta) \\
\ &#038; = &#038; \sum_{t=1}^{T_x} \left[ \log (P(C_t=1|w_t)) + \sum_{j=1}^{k} \log(P(C_t=0|w_{t,j}^-)) \right] 


\end{array} " alt=""/>



<p class="wp-block-paragraph">The final loss function <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{J}(\theta)" align="absmiddle"> that we minimize is the negative log-likelihood over the full dataset:</p>



<figure class="wp-block-image"><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{llll} \mathbf{J}(\theta) &amp; = &amp; - \sum_{t=1}^{T_x} \left( \log \left[ \sigma \left( s_\theta(w_t,h_t) - \log(k P_n(w_t)) - \log (\mathbf{Z}_\theta(h_t)) \right) \right] + \sum_{j=1}^{k} \log \left[ \sigma \left( \log(k P_n(w_{t,j}^-)) + \log (\mathbf{Z}_\theta(h_t)) - s_\theta(w_{t,j}^-,h_t) \right) \right] \right) \end{array} " alt=""/></figure>



<p class="wp-block-paragraph"><strong>Note : <br></strong>In the paper, <em>A fast and simple algorithm for training neural probabilistic language models A Mnih et al, 2012</em>, authors mention that approximating the learning of context dependent normalizing factor to 1 <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{Z}_\theta(h) \approx 1" alt=""> did not affect the performance of downstream tasks.</p>



<p class="wp-block-paragraph"></p>



<h3 class="wp-block-heading">Noise Distribution</h3>



<p class="wp-block-paragraph">The noise distribution <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?P_n(w)" alt="" align="absmiddle"> is typically chosen proportional to the unigram frequency of words in the corpus:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?P_n(w)=\frac{\text{count}(w)}{\sum_v \text{count}(v)}">



<p class="wp-block-paragraph">Often a smoothed unigram distribution improves results:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?P_n(w)\propto \text{count}(w)^{3/4}">



<p class="wp-block-paragraph"></p>



<h3 class="wp-block-heading">Python code</h3>



<p class="wp-block-paragraph">For the toy vocabulary, the code for Neural Probabilistic Language Model, Bengio et al, with the SoftMax head replaced with with Noise Contrastive Estimation (NCE).</p>



<p class="wp-block-paragraph"><strong>The code @ <a href="https://github.com/dsplog/dsplog.com/blob/main/code/word_embeddings/nplm_with_noise_contrastive_estimation.ipynb" target="_blank" rel="noreferrer noopener">word_embeddings/nplm_with_noise_contrastive_estimation.ipynb</a></strong></p>



<iframe loading="lazy" src="https://nbviewer.org/github/dsplog/dsplog.com/blob/main/code/word_embeddings/nplm_with_noise_contrastive_estimation.ipynb?flush_cache=false" width="100%" height="600"></iframe>



<p class="wp-block-paragraph"></p>



<h2 class="wp-block-heading">Word2Vec papers (Mikolov et al, 2013)</h2>



<p class="wp-block-paragraph">In the paper,&nbsp;<em><a href="https://arxiv.org/abs/1301.3781" target="_blank" rel="noreferrer noopener">Efficient Estimation of Word Representations in Vector Space</a></em>, Mikolov et al 2013. proposed architectures to reduce the computation complexity in learning word embeddings , with the intuition that simpler models enable training on much larger corpus of data.</p>



<p class="wp-block-paragraph">Two architectures where proposed. </p>



<h3 class="wp-block-heading">Continuous Bag of Words (CBOW) Model</h3>



<p class="wp-block-paragraph">When comparing with <em>Neural Probabilistic Language Model,</em> Bengio et al 2003, the following simplifications are proposed. </p>



<ul class="wp-block-list">
<li><strong>order of context words is ignored</strong>
<ul class="wp-block-list">
<li>instead of concatenating embedding of previous words, averaging the word embeddings of surrounding words is proposed</li>



<li>this approach is called &#8220;<strong>bag-of-words</strong>&#8221; as the order is not taken into consideration</li>
</ul>
</li>



<li><strong>no non linear hidden layer</strong>
<ul class="wp-block-list">
<li>the model uses a shared projection layer</li>
</ul>
</li>
</ul>



<p class="wp-block-paragraph">Additionally, the in the model context including future words too. </p>



<p class="wp-block-paragraph"><strong>Equations</strong></p>



<p class="wp-block-paragraph">The neural network output is :</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?z=Ux">



<p class="wp-block-paragraph">where:</p>



<ul class="wp-block-list">
<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?U%20\in%20\mathbb{R}^{|V|%20\times%20m}" alt="">&nbsp;is the<strong>&nbsp;output weight matrix</strong>, mapping from hidden dimension&nbsp;<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?m" alt="">&nbsp;to vocabulary size&nbsp;<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?|V|" alt=""></li>



<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?x%20\in%20\mathbb{R}^{m%20\times%201}" alt="x in R^{m x 1}">&nbsp;is the&nbsp;<strong>averaged context embeddings</strong>.</li>
</ul>



<p class="wp-block-paragraph">The averaged context embedding vector&nbsp;<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?x%20\in%20\mathbb{R}^{m%20\times%201}" alt="x in R^{m x 1}">&nbsp;is computed as:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?x%20=%20\frac{1}{2n}%20\sum_{-n%20\le%20i%20\le%20n,%20i%20\ne%200}%20C({w_i})" alt="x averaging formula"/>



<p class="wp-block-paragraph">where,</p>



<ul class="wp-block-list">
<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?C%20\in%20\mathbb{R}^{|V|%20\times%20m}" alt="C in R^{|V| x m}">is the&nbsp;<strong>input embedding matrix</strong></li>



<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?C(w_i)%20\in%20\mathbb{R}^{m%20\times%201}" alt="">is the&nbsp;<strong>embedding of the&nbsp;<em>i</em>-th context word</strong>, and</li>



<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?n" alt="">&nbsp;is the number of words to the&nbsp;<strong>left or right&nbsp;</strong>of the target word, giving a total context size of <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?2n" alt="2n"></li>
</ul>



<p class="wp-block-paragraph">The&nbsp;<strong>probability distribution</strong>&nbsp;over the vocabulary is obtained using the&nbsp;<strong>softmax</strong>&nbsp;function:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?a(w_t)%20=%20\frac{e^{z_{w_t}}}{\sum_{i=1}^{|V|}%20e^{z_{w_i}}}" alt="softmax"/>



<p class="wp-block-paragraph">where:</p>



<ul class="wp-block-list">
<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?a(w_t)" alt="">&nbsp;is the predicted probability of word&nbsp;<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?w_t" alt="">&nbsp;being the target word.</li>
</ul>



<ul class="wp-block-list">
<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?z_{w_t}" alt="">&nbsp;is the score for word&nbsp;<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?w_t" alt="">&nbsp;from the output layer.</li>



<li>The denominator sums the exponentiated scores over all vocabulary entries.</li>
</ul>



<p class="wp-block-paragraph"></p>



<h3 class="wp-block-heading">Continuous Skip-gram Model </h3>



<p class="wp-block-paragraph">The Skip-gram model, tries to predict <strong>context words given the current target word</strong>. The main idea is that each word is trained to predict the words surrounding it within a context window of size <em>n</em>.</p>



<ul class="wp-block-list">
<li><strong>Input:</strong> one-hot encoding of the target word <em>w<sub>t</sub></em></li>



<li><strong>Output:</strong> probability distribution over vocabulary for each context word</li>



<li><strong>No non-linear hidden layer:</strong> uses a shared projection matrix (linear)</li>
</ul>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">Given a target word <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?w_t" alt="w_t">, the model tries to predict each surrounding context word <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?w_{t+i}" alt="w_{t+i}"> for <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?-n \le i \le n, i \ne 0" alt="">. The training goal is to maximize the probability of all context words around each target word:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{ll}
J&#038;=&#038;\frac{1}{T} \sum_{t=1}^{T} \sum_{-n \le i \le n, i \ne 0} \log p(w_{t+i} | w_t) \\
\text{where, } \\
&#038;T&#038;\text{ total words in vocabulary} 
\end{array}


">



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph"><strong>Equations</strong></p>



<p class="wp-block-paragraph">The output score, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?z_i = Ux ">



<p class="wp-block-paragraph">where, </p>



<ul class="wp-block-list">
<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?x=C({w_t})" alt="" align="absmiddle">, where <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?x%20\in%20\mathbb{R}^{m%20\times%201}" alt="x in R^{m x 1}"> is the embedding vector for the word <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?w_t" alt="w_t">  </li>



<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?C%20\in%20\mathbb{R}^{|V|%20\times%20m}" alt="C in R^{|V| x m}">is the&nbsp;<strong>input embedding matrix</strong></li>



<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?U \in \mathbb{R}^{|V| \times m}"> is the output embedding matrix and</li>



<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?z_i \in \mathbb{R}^{|V| \times 1}"> </li>
</ul>



<p class="wp-block-paragraph">The scores <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?z_i"> are computed for each context word, and the probability of all the context word is maximized.  </p>



<p class="wp-block-paragraph">For either CBOW or  Skipgram, both <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?C" alt="C"> and <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?U" alt="U"> are trainable. After training, either one (or their average) is used as the word embedding.</p>



<p class="wp-block-paragraph">Naive way for finding the probability is using SoftMax, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
p(w_o|w_t)=\frac{\exp(z_{w_o})}{\sum_{k=1}^{|V|}\exp(z_k)}
">



<p class="wp-block-paragraph">where, </p>



<ul class="wp-block-list">
<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?w_o"> is the output word </li>



<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?z_{w_o}"> is score for output word</li>



<li>denominator = normalizing constant over vocabulary</li>
</ul>



<p class="wp-block-paragraph">For finding the probability, hierarchical softmax is proposed in the paper.</p>



<h3 class="wp-block-heading">Negative Sampling</h3>



<p class="wp-block-paragraph">In the paper, <a href="https://arxiv.org/abs/1310.4546" target="_blank" rel="noreferrer noopener">Distributed Representations of Words and Phrases and their Compositionality</a>, Mikolov et al 2013 introduced two concepts:</p>



<ul class="wp-block-list">
<li>the speedup provided by sub sampling of frequent words helps to improve the accuracy of the less-frequent words</li>



<li>simplified variant of Noise Contrastive estimation called Negative Sampling</li>
</ul>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">The key intuition in Negative Sampling is that noise contrastive loss defined had terms to normalize the score to approximate the probabilities. However, to learn word embeddings the probabilities are not needed and the terms </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\log(k P_n(w^+)),\quad \log (\mathbf{Z}_\theta(h)), \quad \log(k P_n(w^-))" alt="">



<p class="wp-block-paragraph">can be ignored. <br></p>



<p class="wp-block-paragraph">With this simplification, the negative sampling loss is,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{llll}


\mathbf{L}_{ns} (\theta) &#038; = &#038;\log (\sigma(\left[ s_\theta(w^+,h) \right])) +
 \sum_{t=1}^{k} \log(\sigma(-\left[s_\theta(w^-,h)   \right] )) \\

\end{array}
\\
\\
" alt="">



<p class="wp-block-paragraph"></p>



<h3 class="wp-block-heading">Python code</h3>



<p class="wp-block-paragraph">For the toy vocabulary, finding word vectors with </p>



<p class="wp-block-paragraph">a) Continuous Bag of words (CBOW) with negative sampling</p>



<p class="wp-block-paragraph"><strong>The code @ <a href="https://github.com/dsplog/dsplog.com/blob/main/code/word_embeddings/cbow_negative_sampling%20copy.ipynb" target="_blank" rel="noreferrer noopener">word_embeddings/cbow_negative_sampling copy.ipynb</a></strong></p>



<iframe loading="lazy" src="https://nbviewer.org/github/dsplog/dsplog.com/blob/main/code/word_embeddings/cbow_negative_sampling%20copy.ipynb?flush_cache=false" width="100%" height="600"></iframe>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">b) Skip Graph with Negative Sampling </p>



<p class="wp-block-paragraph"><strong>The code @ <a href="https://github.com/dsplog/dsplog.com/blob/main/code/word_embeddings/skip_gram_negative_sampling.ipynb" target="_blank" rel="noreferrer noopener">word_embeddings/skip_gram_negative_sampling.ipynb</a></strong></p>



<iframe loading="lazy" src="https://nbviewer.org/github/dsplog/dsplog.com/blob/main/code/word_embeddings/skip_gram_negative_sampling.ipynb?flush_cache=false" width="100%" height="600"></iframe>



<p class="wp-block-paragraph"><br></p>



<h2 class="wp-block-heading">GloVe Embeddings ( Penning et al 2014)</h2>



<p class="wp-block-paragraph">In the paper <a href="https://nlp.stanford.edu/pubs/glove.pdf" target="_blank" rel="noreferrer noopener">GloVe: Global Vectors for Word Representation</a>, Penning et al 2014, authors propose that <strong>ratio of co-occurrence probabilities</strong> capture semantic information better than co-occurance probabilities.</p>



<p class="wp-block-paragraph">Let, </p>



<ul class="wp-block-list">
<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{X}"> be matrix of the word co-occurance counts</li>



<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?X_{ij}" align="absmiddle"> be the number of times word <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?j"> occur in context of word <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?i">.</li>



<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?X_{i}=\sum_kX_{ik}" align="absmiddle"> be the number of times any word appear in the context of word <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?i"></li>



<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?P_{ij}=P(j|i)=\frac{X_{ij}}{{X_i}}"> be the probability that word <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?j"> occur in context of word <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?i">.</li>
</ul>



<p class="wp-block-paragraph">Authors show that on the 6 billion token corpus dataset, </p>



<img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{llllll}
P(solid|ice)&#038;=&#038;1.9 \times 10^{-4} &#038;
P(gas|ice)&#038;=&#038;6.6\times 10^{-5} &#038;
P(water|ice)&#038;=&#038;3.0\times 10^{-3} \\

P(solid|steam)&#038;=&#038;2.2 \times 10^{-5} &#038;
P(gas|steam)&#038;=&#038;7.8\times 10^{-4} &#038;
P(water|steam)&#038;=&#038;2.2\times 10^{-3} \\

\end{array}
">



<p class="wp-block-paragraph">Taking the ratio of co-occurance probabilities,</p>



<img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{llllll}
\frac{P(solid|ice)}{P(solid|steam)} &#038;=&#038; 8.9 \\ \\ 
\frac{P(gas|ice)}{P(gas|steam)} &#038;=&#038;8.5\times 10^{-2} \\ \\
\frac{P(water|ice)}{P(water|steam)}&#038;=&#038;1.36 \\


\end{array}
">



<p class="wp-block-paragraph">The ratios indicate that, </p>



<ul class="wp-block-list">
<li><em>solid</em> and <em>ice</em> has a higher relationship than with <em>steam</em>.</li>



<li><em>gas</em> and <em>ice</em> is far less likely to co-occur than with <em>steam</em></li>



<li><em>water</em> is related to both <em>ice</em> and <em>steam</em> in similar proportions</li>
</ul>



<h3 class="wp-block-heading">Model </h3>



<p class="wp-block-paragraph">To capture this <strong>ratio</strong> relationship in a vector space, the authors search for a function <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?F"> that satisfies:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi? F(w_i, w_j, \tilde{w}_k) = \frac{P(k|i)}{P(k|j)} = \frac{P_{ik}}{P_{jk}}" alt=""/>



<p class="wp-block-paragraph">where </p>



<ul class="wp-block-list">
<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?k"> is context word</li>



<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?i,j"> are target words</li>



<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?w \in \mathbb{R}^d"> are the word vectors and </li>



<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\tilde{w} \in \mathbb{R}^d"> are separate context vectors.</li>
</ul>



<p class="wp-block-paragraph">Authors enforce that the relationship should be <strong>linear (vector difference)</strong> and the result should be a <strong>scalar (dot product)</strong>, leading to :</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi? F((w_i - w_j)^T \tilde{w}_k) = \frac{P_{ik}}{P_{jk}}" alt=""/>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">To satisfy that, authors propose choosing function <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?F=\exp()"> so that the dot product of vector difference can be written as ratio of probabilities, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{lll}
F((w_i - w_j)^T \tilde{w}_k)  &#038; = &#038; \frac{F(w_i^T \tilde{w}_k)}{F(w_j^T \tilde{w}_k)} \\
&#038;=&#038;\frac{P_{ik}}{P_{jk}}
\end{array}


" alt=""/>



<p class="wp-block-paragraph">With this choice, for a <strong>single word-context pair</strong> estimates the co-occurence probabilities,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi? F(w_i^T \tilde{w}_k) = \exp((w_i^T \tilde{w}_k)) = P_{ik} = \frac{X_{ik}}{X_i}" alt=""/>



<p class="wp-block-paragraph">Taking logarithm, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{lll}
w_i^T \tilde{w}_k = \log(P_{ik}) &#038; = &#038; \log(X_{ik}) - \log(X_i)
\end{array}

"alt=""/>



<p class="wp-block-paragraph"><strong>Note :</strong></p>



<p class="wp-block-paragraph">The model capturing the relation between two words <strong>should not change</strong> even if the <strong>words are swapped</strong>. Even though the co-occurrence counts are identical (<img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?X_{ik} = X_{ki}">), because the total counts of words are not equal (<img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?X_{i} \ne X_{k}">) , the <strong>conditional probability is not symmetric</strong> (<img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?P_{ik} \ne P_{ki}">).</p>



<p class="wp-block-paragraph">The above equation is not symmetric if we swap target word <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?i"> and context word <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?k"> as the row-dependent term <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\log(X_{i})"> has to be handled. </p>



<p class="wp-block-paragraph">To make it symmetric, the authors absorb <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\log(X_{i})"> into a learnable bias term <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?b_{i}"> and then adds a corresponding bias <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\tilde{b}_{k}"> for the context word. This ensures the model is fully symmetric i.e.</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{lll}
w_i^T \tilde{w}_k + b_i + \tilde{b}_k =  \log(X_{ik}) 
\end{array}

"alt=""/>



<p class="wp-block-paragraph">The loss function then becomes , </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{lll}
J = \sum_{i=1}^{V}\sum_{k=1}^{V}\left[w^T_i \tilde{w}_k + b_i + \tilde{b}_k -  \log(X_{ik}) \right]^2
\end{array}

"alt=""/>



<p class="wp-block-paragraph">The key aspect in the above simplification is that, by<strong> training for the pairs of words</strong> to minimize the above loss will <strong>indirectly</strong> ensure that the <strong>dot product </strong>of<strong> vector difference of target words </strong>with<strong> context word </strong>will arrive at the<strong> ratio of probabilities</strong>.</p>



<p class="wp-block-paragraph"><strong>Weighted Least Squares</strong></p>



<p class="wp-block-paragraph">The above loss function weighs all <strong>co-occurances equally</strong>. Authors noted that rare co-occurances are noisy and around 75-95% of the co-occurance is zeros, and proposed adding a <strong>weighting function</strong> to least squares loss proposed above.</p>



<p class="wp-block-paragraph">The weighting function is chosen to obey the following : </p>



<ol class="wp-block-list">
<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?f(0)=0"> (to handle the zero co-occurance counts)</li>



<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?f(x)"> should be non-decreasing so that rare co-occurance are given less weight</li>



<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?f(x)"> should be relatively small for large values of <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?x"> so that frequent co-occurrences are not over-weighted</li>
</ol>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
f(x) =  \left\{
\begin{array}{ll}
(x/x_{max})^{\alpha} &#038; \text{if } x \le x_{max}  \\
1 &#038; \text{otherwise}
\end{array}
\right.
" alt=""/>



<p class="wp-block-paragraph">The parameters <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha = 3/4"> and <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?x_{max} = 100"> are chosen empirically.</p>



<p class="wp-block-paragraph">Then the Weighted Least Squares loss function becomes, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{lll}
J = \sum_{i=1}^{V}\sum_{k=1}^{V}f(X_{ik})\left[w^T_i \tilde{w}_k + b_i + \tilde{b}_k -  \log(X_{ik}) \right]^2
\end{array}

"alt=""/>



<h3 class="wp-block-heading">Python code</h3>



<p class="wp-block-paragraph"><strong>The code @ <a href="https://github.com/dsplog/dsplog.com/blob/main/code/word_embeddings/glove_word_embedding.ipynb" target="_blank" rel="noreferrer noopener">word_embeddings/glove_word_embedding.ipynb</a></strong></p>



<iframe loading="lazy" src="https://nbviewer.org/github/dsplog/dsplog.com/blob/main/code/word_embeddings/glove_word_embedding.ipynb?flush_cache=false" width="100%" height="600"></iframe>



<h2 class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">This article covers</p>



<p class="wp-block-paragraph"><strong>Evolution:</strong> How we moved from Bengio&#8217;s NPLM (2003) to efficient architectures like Word2Vec and GloVe.</p>



<p class="wp-block-paragraph"><strong>Math:</strong> Detailed derivations of <strong>Hierarchical Softmax</strong> (using binary trees) and <strong>Noise Contrastive Estimation</strong> (differentiating data from noise).</p>



<p class="wp-block-paragraph"><strong>Architectures:</strong> A deep look at CBOW, Skip-Gram, and the intuition behind Negative Sampling.</p>



<p class="wp-block-paragraph"><strong>Code:</strong> Complete Python implementations for every model discussed, including vectorized implementations for efficiency.</p>



<p class="wp-block-paragraph"><strong>Acknowledgment </strong> </p>



<p class="wp-block-paragraph">In addition to the primary papers listed above, this post draws inspiration from the excellent overview in the post <strong><a href="https://lilianweng.github.io/posts/2017-10-15-word-embedding/" target="_blank" rel="noreferrer noopener">Learning word embedding</a>, Weng, Lilian 2017</strong>. Credit also goes to the recent Large Language Models <a href="https://gemini.google.com/" target="_blank" rel="noopener"><strong>Gemini</strong></a> and <a href="https://chatgpt.com/" target="_blank" rel="noopener"><strong>ChatGPT</strong></a> which helped to bounce thoughts and refine the drafts.</p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph"></p>
<p>The post <a rel="nofollow" href="https://dsplog.com/2025/12/27/word-embeddings-using-neural-networks/">Word Embeddings using neural networks</a> appeared first on <a rel="nofollow" href="https://dsplog.com">DSP LOG</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://dsplog.com/2025/12/27/word-embeddings-using-neural-networks/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Gradients for multi class classification with Softmax</title>
		<link>https://dsplog.com/2025/06/22/gradients-for-multi-class-classification-with-softmax/</link>
					<comments>https://dsplog.com/2025/06/22/gradients-for-multi-class-classification-with-softmax/#comments</comments>
		
		<dc:creator><![CDATA[Krishna Sankar]]></dc:creator>
		<pubDate>Sun, 22 Jun 2025 08:53:17 +0000</pubDate>
				<category><![CDATA[Machine Learning]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[Categorical Cross Entropy]]></category>
		<category><![CDATA[Linear]]></category>
		<category><![CDATA[Maximum Likelihood]]></category>
		<category><![CDATA[ML]]></category>
		<category><![CDATA[Softmax]]></category>
		<guid isPermaLink="false">https://dsplog.com/?p=2231</guid>

					<description><![CDATA[<p>In a multi class classification problem, the output (also called the label or class) takes a finite set of discrete values . In this post, system model for a multi class classification with a linear layer followed by softmax layer is defined. The softmax function transforms the output of a linear layer into values lying &#8230; <a href="https://dsplog.com/2025/06/22/gradients-for-multi-class-classification-with-softmax/" class="more-link">Continue reading<span class="screen-reader-text"> "Gradients for multi class classification with Softmax"</span></a></p>
<p>The post <a rel="nofollow" href="https://dsplog.com/2025/06/22/gradients-for-multi-class-classification-with-softmax/">Gradients for multi class classification with Softmax</a> appeared first on <a rel="nofollow" href="https://dsplog.com">DSP LOG</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">In a <strong>multi class classification</strong> problem, the output (also called the <strong>label</strong> or <strong>class</strong>) takes a finite set of <strong>discrete values</strong> <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?y \in \{1, 2, \ldots, k\}" alt="">. In this post, <strong>system model</strong> for a multi class classification with a <strong>linear layer</strong> followed by <strong>softmax layer</strong> is defined. The <strong>softmax function</strong> transforms the output of a <strong>linear layer </strong> into values lying between 0 and 1, which can be interpreted as <strong>probability scores</strong>.</p>



<p class="wp-block-paragraph">Next, the <strong>loss function</strong> using <strong>categorical cross entropy</strong> is explained and  derive the <strong>gradients</strong> for model parameters using the <strong>chain rule</strong>. The <strong>analytically computed gradients</strong> are then compared with those obtained from the deep learning framework <strong>PyTorch</strong>. Finally, we implement a <strong>training loop</strong> using <strong>gradient descent</strong> for a toy multi-class classification task with <strong>2D Gaussian-distributed data</strong>. </p>



<span id="more-2231"></span>






<p class="wp-block-paragraph">As always, contents from <a href="https://cs229.stanford.edu/main_notes.pdf" target="_blank" rel="noreferrer noopener">CS229 Lecture Notes</a> and the notations used in the course <a href="https://youtube.com/playlist?list=PLkDaE6sCZn6Ec-XTbcX1uRg2_u4xOEky0&amp;si=_3Xs1piNOfQ847gd" target="_blank" rel="noopener">Deep Learning Specialization C1W1L01</a> from Dr Andrew Ng forms key references.</p>



<h2 class="wp-block-heading">Model</h2>



<p class="wp-block-paragraph">Let us take an example of estimating <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?y \in \{1, 2, \ldots, k\}" alt=""> based on feature vector <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{x}" alt=""> having <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?n" alt=""> features i.e. <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{x} \in \mathbb{R}^{n \times 1}" alt=""> and there are <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?m" alt=""> examples.</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{tabular}{|c|c|c|c|c|}
\hline&amp;{example^1}&amp;{example^2}&amp;\ldots&amp;{example^m}\\
\hline{feature_1}&amp;{x_1}^{1}&amp;{x_1}^{2}&amp;\ldots&amp;{x_1}^{m}\\
\hline{feature_2}&amp;{x_2}^{1}&amp;{x_2}^{2}&amp;\ldots&amp;{x_2}^{m}\\
\hline&amp;\vdots&amp;\vdots&amp;\ldots&amp;\vdots\\
\hline{feature_n}&amp;{x_n}^{1}&amp;{x_n}^{2}&amp;\ldots&amp;{x_n}^{m}&amp;\\
\hline{output}&amp;{y}^{1}&amp;{y}^{2}&amp;\ldots&amp;{y}^{m}\end{tabular}
" alt="">



<h3 class="wp-block-heading">Linear Layer</h3>



<p class="wp-block-paragraph">Let us <strong>assume</strong> that the variable <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?{z}" alt="">is defined as <strong>linear function</strong> of <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{x}" alt="">. For a single training example, this can be written as :</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{align*}
\mathbf{z} &#038;= \mathbf{W} \mathbf{x} + \mathbf{b} \\
\end{align*}" alt="">



<p class="wp-block-paragraph">where, </p>



<ul class="wp-block-list">
<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{z} = 
\begin{bmatrix}
z_1 \\
z_2 \\
\vdots \\
z_k
\end{bmatrix}" alt=""> is the vector of size <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?k \times 1" alt=""> i.e. <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{z} \in \mathbb{R}^{k \times 1}" alt="">,</li>



<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{W} = 
\begin{bmatrix}
w_{11} &amp; w_{12} &amp; \cdots &amp; w_{1n} \\
w_{21} &amp; w_{22} &amp; \cdots &amp; w_{2n} \\
\vdots &amp; \vdots &amp; \ddots &amp; \vdots \\
w_{k1} &amp; w_{k2} &amp; \cdots &amp; w_{kn}
\end{bmatrix}" alt=""> is the <strong>parameter matrix</strong> of size <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?k \times n" alt=""> i.e. <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{W} \in \mathbb{R}^{k \times n}" alt="">,  </li>



<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{x} = 
\begin{bmatrix}
x_1 \\
x_2 \\
\vdots \\
x_n
\end{bmatrix} " alt=""> is the feature vector of size <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?n \times 1" alt=""> i.e. <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{x} \in \mathbb{R}^{n \times 1}" alt=""> and</li>



<li><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{b} = 
\begin{bmatrix}
b_1 \\
b_2 \\
\vdots \\
b_k
\end{bmatrix} " alt=""> is the <strong>parameter vector</strong> of size <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?k \times 1" alt=""> i.e. <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{b} \in \mathbb{R}^{k \times 1}" alt=""></li>
</ul>



<p class="wp-block-paragraph">Note : </p>



<p class="wp-block-paragraph">This is the definition of <strong>Linear layer</strong> in <strong>PyTorch</strong><sup> <a href="https://docs.pytorch.org/docs/stable/generated/torch.nn.Linear.html" target="_blank" rel="noopener">(refer entry on Linear layer)</a></sup>. This is alternatively called as <strong>Dense</strong> <strong>Layer</strong> in <strong>Tensorflow</strong> <a href="https://www.tensorflow.org/api_docs/python/tf/keras/layers/Dense" target="_blank" rel="noopener"><sup>(refer entry on Dense)</sup></a> and as <strong>Fully Connected layer</strong> in deep learning literature.</p>



<h3 class="wp-block-heading">Softmax layer</h3>



<p class="wp-block-paragraph">To map the<strong> real valued vector</strong> <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{z} \in \mathbb{R}^{k \times 1}" alt=""> to a<strong> probability vector </strong><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{a} \in \mathbb{R}^{k \times 1}" alt=""> with elements of <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{a}" alt=""><strong>summing up to 1</strong>, we use the <strong>softmax function</strong> <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi? \mathbf{S}(\cdot)" alt=""> <sup><a href="https://en.wikipedia.org/wiki/Softmax_function" target="_blank" rel="noopener">(refer wiki entry on SoftMax)</a> </sup>. <strong>Softmax</strong> function is defined as,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{a}=\mathbf{S}(\mathbf{z}) = 
\begin{bmatrix}
\frac{e^{z_1}}{\sum_{j=1}^{k} e^{z_j}} \\
\frac{e^{z_2}}{\sum_{j=1}^{k} e^{z_j}} \\
\vdots \\
\frac{e^{z_k}}{\sum_{j=1}^{k} e^{z_j}}
\end{bmatrix}, 


\quad \in \mathbb{R}^{k \times 1}" alt="">



<p class="wp-block-paragraph">Equivalently, this can be written as,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{a} = 

\begin{bmatrix}
a_1 \\
a_2 \\
\vdots \\
a_k
\end{bmatrix}, \quad \in \mathbb{R}^{k \times 1}" alt=""/>



<p class="wp-block-paragraph">where, each <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?a_i" alt=""> represents the normalized exponential of the corresponding <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?z_i" alt="">. This ensures that</p>



<ul class="wp-block-list">
<li>each element <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?a_i" alt=""> lies in the <strong>range [0,1</strong>] i.e. <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?0 \leq a_i \leq 1" alt=""></li>



<li><strong>sum</strong> of all the elements <strong>add upto 1</strong>, i.e. <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\sum_{i=1}^k a_i = 1" alt="">.</li>
</ul>



<p class="wp-block-paragraph">This makes <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{a}" alt=""> interpretable as a probability distribution over the <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?k" alt=""> classes.</p>



<h2 class="wp-block-heading">Derivatives</h2>



<h3 class="wp-block-heading">Derivative of Softmax layer</h3>



<p class="wp-block-paragraph">To compute the <strong>derivative of the softmax output</strong> <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{a} = \mathbf{S}(\mathbf{z})" alt=""> with respect to its input <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{z}" alt="">, we need to find the <strong>Jacobian matrix</strong> <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial \mathbf{a}}{\partial \mathbf{z}} \in \mathbb{R}^{k \times k}" alt="">. The <strong>Jacobian</strong> contains<strong> all partial derivatives </strong>of each output component <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?{a_i}" alt=""> with respect to each input component <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?z_j " alt="">. </p>



<p class="wp-block-paragraph">To find the derivative for all cases, let us split into two scenarios i.e.</p>



<ul class="wp-block-list">
<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}\frac{\partial a_i}{\partial z_j}&amp;  \text{where, } i = j \\  \end{array}" alt=""></li>



<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}\frac{\partial a_i}{\partial z_j}&amp;  \text{where, } i \ne j \\  \end{array}" alt=""> </li>
</ul>



<h4 class="wp-block-heading">Derivative for case <em>i=j</em></h4>



<p class="wp-block-paragraph">Using the product rule of derivatives, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{align*}

\frac{\partial a_i}{\partial z_i} 
&#038;= \frac{\partial}{\partial z_i} \left( e^{z_i} \cdot \frac{1}{\sum_{j=1}^{k} e^{z_j}} \right) \\
&#038;= \frac{\partial }{\partial z_i}\left(e^{z_i}\right) \cdot \frac{1}{\sum_{j=1}^{k} e^{z_j}} 
+ e^{z_i} \cdot \frac{\partial}{\partial z_i} \left( \frac{1}{\sum_{j=1}^{k} e^{z_j}} \right) \\
&#038;= e^{z_i} \cdot \frac{1}{\sum_{j=1}^{k} e^{z_j}} 
- e^{z_i} \cdot \frac{e^{z_i}}{\left( \sum_{j=1}^{k} e^{z_j} \right)^2} \\
&#038;= \frac{e^{z_i}}{\sum_{j=1}^{k} e^{z_j}} 
- \frac{(e^{z_i})^2}{\left( \sum_{j=1}^{k} e^{z_j} \right)^2} \\
&#038;= a_i - a_i^2 \\
&#038;= a_i(1 - a_i)
\end{align*}

" alt=""/>



<h4 class="wp-block-heading">Derivative for case <em>i ≠ j</em></h4>



<p class="wp-block-paragraph"></p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{align*}
\frac{\partial a_i}{\partial z_j} 
&#038;= \frac{\partial}{\partial z_j} \left( e^{z_i} \cdot \frac{1}{\sum_{l=1}^{k} e^{z_l}} \right) \\
&#038;= \frac{\partial }{\partial z_j} \left(e^{z_i}\right)\cdot \frac{1}{\sum_{l=1}^{k} e^{z_l}} 
+ e^{z_i} \cdot \frac{\partial}{\partial z_j} \left( \frac{1}{\sum_{l=1}^{k} e^{z_l}} \right) \\
&#038;= 0 \cdot \frac{1}{\sum_{l=1}^{k} e^{z_l}} 
- e^{z_i} \cdot \frac{e^{z_j}}{\left( \sum_{l=1}^{k} e^{z_l} \right)^2} \\
&#038;= - \frac{e^{z_i} \cdot e^{z_j}}{\left( \sum_{l=1}^{k} e^{z_l} \right)^2} \\
&#038;= - a_i \cdot a_j
\end{align*}

" alt=""/>



<h4 class="wp-block-heading">Final output (matrix form)</h4>



<p class="wp-block-paragraph">Based on the above derivations, the derivative is defined as :</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial a_i}{\partial z_j} = \begin{cases} a_i (1 - a_i), &amp; \text{if } i = j \\ - a_i a_j, &amp; \text{if } i \ne j \end{cases}" alt=""/>



<p class="wp-block-paragraph">In matrix form, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial \mathbf{a}}{\partial \mathbf{z}} =
\begin{bmatrix}
a_1(1 - a_1) &#038; -a_1 a_2 &#038; -a_1 a_3 &#038; \cdots &#038; -a_1 a_k \\
-a_2 a_1 &#038; a_2(1 - a_2) &#038; -a_2 a_3 &#038; \cdots &#038; -a_2 a_k \\
-a_3 a_1 &#038; -a_3 a_2 &#038; a_3(1 - a_3) &#038; \cdots &#038; -a_3 a_k \\
\vdots &#038; \vdots &#038; \vdots &#038; \ddots &#038; \vdots \\
-a_k a_1 &#038; -a_k a_2 &#038; -a_k a_3 &#038; \cdots &#038; a_k(1 - a_k)
\end{bmatrix}, \quad \in \mathbb{R}^{k \times k}

" alt=""/>



<h4 class="wp-block-heading">Code</h4>



<p class="wp-block-paragraph">Python code comparing the derivative of softmax using the derivation above vs computed by PyTorch autograd function below. </p>



<iframe loading="lazy" src="https://nbviewer.org/github/dsplog/dsplog.com/blob/main/code/gradients_multiclass_classification/gradients_cross_entropy_loss.ipynb?flush_cache=false" width="100%" height="600"></iframe>



<h3 class="wp-block-heading">Derivative of Linear layer</h3>



<p class="wp-block-paragraph">To find the derivative of the linear layer <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{align*}
\mathbf{z} &amp;= \mathbf{W} \mathbf{x} + \mathbf{b} \\
\end{align*}" alt="">, with respect to parameters <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{W}" alt=""> and <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{b}" alt="">, we must compute two partial derivatives:</p>



<ul class="wp-block-list">
<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial \mathbf{z}}{\partial \mathbf{W}}" alt="\frac{\partial \mathbf{z}}{\partial \mathbf{W}}"> – how the output changes with respect to the weight matrix.<br>  </li>



<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial \mathbf{z}}{\partial \mathbf{b}}" alt="\frac{\partial \mathbf{z}}{\partial \mathbf{b}}"> – how the output changes with respect to the bias vector.<br>  </li>
</ul>



<p class="wp-block-paragraph"></p>



<h4 class="wp-block-heading">Derivative of Weights</h4>



<p class="wp-block-paragraph">To compute the derivative <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial \mathbf{z}}{\partial \mathbf{W}}">, we evaluate how each weight parameter <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?W_{ij}"> affects each output dimension <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?z_i">.  The <i><strong>i</strong></i>-th component of <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{z}" alt="\mathbf{z}"> is:</p>



<p class="wp-block-paragraph">
<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?z_i = \sum_{j=1}^{n} W_{ij} x_j + b_i" alt="">.
</p>



<p class="wp-block-paragraph">The partial derivative of <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?z_i" alt="z_i"> with respect to <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?W_{ij}" alt="W_{ij}"> is :</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial z_i}{\partial W_{ij}} = x_j
" alt=""/>



<p class="wp-block-paragraph">where, </p>



<ul class="wp-block-list">
<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?i \in \{1, 2, \dots, k\}" alt=""> index over the output vector <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{z} \in \mathbb{R}^{k \times 1}" alt=""></li>



<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?j \in \{1, 2, \dots, n\}" alt=""> indexes the elements of the input vector <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{x} \in \mathbb{R}^{n \times 1}" alt=""></li>
</ul>



<p class="wp-block-paragraph">Since each output <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?z_i"> depends only on the weights in i-th row <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{W}_{i,:}">, the <strong>Jacobian</strong> simplifies to a matrix where each row is <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{x}^\top" alt="">. This can be represented as</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial z_i}{\partial \mathbf{W}_{i,:}} = \mathbf{x}^\top \in \mathbb{R}^{1 \times n}

" alt=""/>



<p class="wp-block-paragraph">For all the rows of <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{W}" alt="">, the derivative is </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial \mathbf{z}}{\partial \mathbf{W}} = 
\begin{bmatrix}
\mathbf{x}^\top \\
\mathbf{x}^\top \\
\vdots \\
\mathbf{x}^\top
\end{bmatrix}
\in \mathbb{R}^{k \times n}
\quad \text{(each row is } \mathbf{x}^\top \text{)}
" alt=""/>



<p class="wp-block-paragraph"></p>



<h4 class="wp-block-heading">Derivative of Bias</h4>



<p class="wp-block-paragraph">The bias vector <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{b} \in \mathbb{R}^{k \times 1}" alt=""> is added element-wise to the output of the linear transformation <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{W}\mathbf{x}">. That is, each output component <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?z_i"> is given by:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?z_i = \sum_{j=1}^{n} W_{ij} x_j + b_i" alt=""/>



<p class="wp-block-paragraph">So the partial derivative of <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?z_i" alt=""> with respect to <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?b_j" alt=""> is:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial z_i}{\partial b_j} = \begin{cases} 1 &#038; \text{if } i = j \\ 0 &#038; \text{if } i \ne j \end{cases} " alt=""/>



<p class="wp-block-paragraph">This implies that the Jacobian matrix of <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{z}"> with respect to <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{b}"> is an identity matrix:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial \mathbf{z}}{\partial \mathbf{b}} = \mathbf{I}_k \in \mathbb{R}^{k \times k}" alt=""/>



<p class="wp-block-paragraph">This tells us that the bias only affects its corresponding output component (i.e., <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?b_j" alt=""> only affects <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?z_j" alt="">).</p>



<p class="wp-block-paragraph"></p>



<h2 class="wp-block-heading">Loss for multi-class classification</h2>



<h3 class="wp-block-heading">Maximum Likelihood Estimate</h3>



<p class="wp-block-paragraph">The <strong>likelihood</strong> of observing the true class c, given input <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{x}" alt="">, under the model is:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?P(y = c \mid \mathbf{x}) = a_c
" alt=""/>



<p class="wp-block-paragraph">The <strong>log-likelihood</strong> over a dataset with <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?m" alt=""> examples is:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\log \mathcal{L} = \sum_{i=1}^{m} \log a^i_c

" alt=""/>



<p class="wp-block-paragraph">where, </p>



<p class="wp-block-paragraph"><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?a^i_c" alt=""> is the model&#8217;s predicted probability for the correct class <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?c" alt=""> for the i-th example.</p>



<p class="wp-block-paragraph"><strong>Maximizing</strong> this log-likelihood is equivalent to <strong>minimizing</strong> the <strong>negative log-likelihood</strong>:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathcal{L_{\text{NLL}}} = -\sum_{i=1}^{m} \log a^i_c

" alt=""/>



<h3 class="wp-block-heading">Connecting to Cross Entropy Loss</h3>



<p class="wp-block-paragraph">To map the ground truth class label <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?y \in \{1, 2, \ldots, k\}" alt=""> to be represented as a target vector <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{y} \in \mathbb{R}^{k \times 1}" alt="">, a common choice is the <strong>one-hot encoding</strong> scheme, where the true class is indicated by a <strong>1</strong> in the corresponding position and <strong>0</strong> elsewhere.  For example, suppose we have <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?k = 3" alt="k=3"> classes, and the correct label is class 2, i.e., <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?y = 2" alt="y = 2">, then the one-hot encoded vector <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{y}" alt="\mathbf{y}"> becomes :</p>



<p class="wp-block-paragraph"><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{y} = \begin{bmatrix} 0 \\ 1 \\ 0  \end{bmatrix}" alt="\mathbf{y} = [0, 1, 0]^T"></p>



<h4 class="wp-block-heading">Cross Entropy</h4>



<p class="wp-block-paragraph">To compare the model’s predicted probability vector <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{a}" alt="\mathbf{a}"> with the one-hot encoded true label <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{y}" alt="\mathbf{y}">, we use a metric called <strong>cross-entropy</strong> <a href="https://en.wikipedia.org/wiki/Cross-entropy" target="_blank" rel="noopener"><sup>(refer wiki entry on Cross Entropy)</sup></a>.  The cross-entropy of the distribution&nbsp;<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{q}" alt="\mathbf{y}">&nbsp;relative to a distribution<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{p}" alt="\mathbf{p}"> over a given set is defined as follows:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?H(p, q) = -\operatorname{E}_p[\log q]
" alt=""/>



<p class="wp-block-paragraph">where, </p>



<p class="wp-block-paragraph"><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\operatorname{E}_p[\cdot]" alt=""> is the&nbsp;<a href="https://en.wikipedia.org/wiki/Expected_value" target="_blank" rel="noopener">expected value</a>&nbsp;operator with respect to the distribution&nbsp;<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{p}" alt="\mathbf{y}">.</p>



<p class="wp-block-paragraph">For&nbsp;<a href="https://en.wikipedia.org/wiki/Discrete_random_variable" target="_blank" rel="noopener">discrete</a>&nbsp;probability distributions <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{p}" alt="\mathbf{p}">and&nbsp;<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{q}" alt="\mathbf{y}">&nbsp;with <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathcal{X}" alt="">set of all possible outcomes or classes.</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?H(p,q) = -\sum_{x \in \mathcal{X}} p(x) \log q(x)
" alt=""/>



<h4 class="wp-block-heading">Cross Entropy Loss</h4>



<p class="wp-block-paragraph">In the context of training classification models, we use the <strong>cross-entropy loss</strong> as a cost function to minimize. For a single training example, to evaluate how well the <strong>predicted probability vector </strong><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{a} \in \mathbb{R}^{k \times 1}" alt=""> matches the ground truth vector <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{y} \in \mathbb{R}^{k \times 1}" alt="">, the <strong>cross-entropy loss</strong> is defined as:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathcal{L}_{\text{CE}}(\mathbf{y}, \mathbf{a}) = - \sum_{k=1}^{k} y_i \log(a_i)
" alt=""/>



<p class="wp-block-paragraph">where, </p>



<ul class="wp-block-list">
<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?y_i" alt=""> is the true probability of class <code><em>i</em></code>  and</li>



<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?a_i" alt=""> is the predicted probability for class <code>i</code>.</li>
</ul>



<p class="wp-block-paragraph">The loss encourages the model to assign <strong>higher probability to the correct class</strong> which <strong>indirectly lowers </strong>the probabilities to the<strong> incorrect classes</strong>. The <strong>smaller the cross-entropy loss</strong>, the <strong>closer the predicted probabilities</strong> are to the true labels.</p>



<p class="wp-block-paragraph">Loss across all <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?m" alt="">examples is, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathcal{L}_{\text{CE}}(\mathbf{y}, \mathbf{a}) = -\sum_{i=1}^{m} \sum_{j=1}^{k} y^i_j \log(a^i_j)
" alt=""/>



<p class="wp-block-paragraph">When <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?y^i_c
" alt=""> is <strong>one-hot coded</strong>, as only the <strong>correct class is non-zero</strong>, the equation reduces to</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathcal{L}_{\text{CE}}(\mathbf{y}, \mathbf{a}) = -\sum_{i=1}^{m} \log(a^i_c)
" alt=""/>



<p class="wp-block-paragraph">We can see that this <strong>cross entropy loss </strong>is same as the <strong>maximum likelihood</strong> estimate derived earlier. </p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">Note : </p>



<ul class="wp-block-list">
<li>Function for cross entropy loss  is available in PyTorch library as <code>torch.nn.CrossEntropyLoss</code><span style="font-size: revert; color: initial;"> </span><a style="font-size: revert;" href="https://docs.pytorch.org/docs/stable/generated/torch.nn.CrossEntropyLoss.html" target="_blank" rel="noreferrer noopener"><sup>(refer entry on CELoss in PyTorch)</sup></a><span style="font-size: revert; color: initial;">.</span>  </li>



<li>In the <code>torch.nn.CrossEntropyLoss</code> definition, we only need to provide the output of the linear layer <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{z} \in \mathbb{R}^{k \times 1}" alt=""> (called <strong>logits</strong>) and the <strong>class indices</strong> <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?y \in \{1, 2, \ldots, k\}" alt=""> as an integer. The softmax and logarithm of probabilities are computed internally, so we do not need to apply softmax before passing logits to this function.</li>
</ul>



<h2 class="wp-block-heading">Gradients with Cross Entropy (CE) Loss</h2>



<p class="wp-block-paragraph">The system model for binary classification involves multiple steps: </p>



<ul class="wp-block-list">
<li>firstly, the vector <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{z}" alt="">is defined as <strong>linear function</strong> of <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{x}" alt=""> using parameters <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{W}" alt=""> and <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{b}" alt="">,</li>



<li>then <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{z}" alt=""> gets transformed into a <strong>estimated probability</strong> score <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{a}" alt=""> using <strong>softmax function</strong>.</li>



<li>lastly, using the<strong> true label </strong><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?y \in \{0, 1, \ldots k\}" alt=""> and estimated probability score <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{a}" alt="">,<strong>  cross entropy</strong> loss <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathcal{L}_{\text{CE}}" alt=""> is computed</li>
</ul>



<p class="wp-block-paragraph">For performing gradient descent of the parameters, the goal is to the find the gradients of the loss <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathcal{L}_{\text{CE}}" alt=""> w.r.t to the parameters <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{W}" alt=""> and <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{b}" alt="">. To find the gradients, we go in the reverse order i.e.</p>



<ul class="wp-block-list">
<li>first, gradients of the loss <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathcal{L}_{\text{CE}}" alt=""> w.r.t to the estimated probability score <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{a}" alt="">, <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial \mathcal{L}}{\partial \mathbf{a}}"> is computed.</li>



<li>then gradients of the probability score <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{a}" alt=""> w.r.t to the output of linear function <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{z}" alt="">  is multiplied with the gradients of loss with respect to <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{a}" alt="">  i.e. <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial \mathcal{L}}{\partial \mathbf{z}} = \frac{\partial \mathcal{L}}{\partial a} \cdot \frac{\partial a}{\partial z}"></li>



<li>lastly, to find the gradients of output of linear function <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{z}" alt=""> w.r.t to parameters <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{W}" alt=""> and <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{b}" alt="">, the product of all the individual gradients is used. This is written as,</li>
</ul>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial \mathcal{L}}{\partial \mathbf{w}} = \frac{\partial \mathcal{L}}{\partial a} \cdot \frac{\partial a}{\partial z} \cdot \frac{\partial z}{\partial \mathbf{w}}
" alt="">



<p class="wp-block-paragraph">The steps described, calculating gradients in the reverse order from the loss back to the parameters<strong> </strong>is an application of the<strong> chain rule from calculus</strong> <a href="https://en.wikipedia.org/wiki/Chain_rule#Intuitive_explanation" target="_blank" rel="noopener"><sup>(refer wiki entry on Chain Rule)</sup></a>. This method is the foundation of <strong>back propagation</strong> used in training models <a href="https://en.wikipedia.org/wiki/Backpropagation" target="_blank" rel="noopener"><sup>(refer wiki entry on Backpropagation)</sup></a>.</p>



<h3 class="wp-block-heading">Gradients of Loss with respect to Probability (dL/da)</h3>



<p class="wp-block-paragraph">As defined earlier, for a <strong>multi-class classification</strong> setting, the <strong>cross-entropy loss</strong> is given by:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathcal{L} = - \sum_{i=1}^{k} y_i \log a_i" alt="">



<p class="wp-block-paragraph">Derivative of <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathcal{L}" alt=""> w.r.t  <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?a_i" alt=""> is, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial \mathcal{L}}{\partial a_i} = - \frac{y_i}{a_i}" alt="">



<p class="wp-block-paragraph">So, the gradient is large if the predicted probability <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?a_i" alt=""> is small for the correct class — this penalises the model for incorrect predictions, which is desired during training. The vectorized form of the loss gradient w.r.t. the probability vector <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{a}" alt=""> is:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial \mathcal{L}}{\partial \mathbf{a}} =
\begin{bmatrix}
-\dfrac{y_1}{a_1} \\
-\dfrac{y_2}{a_2} \\
\vdots \\
-\dfrac{y_k}{a_k}
\end{bmatrix}, \quad  \in \mathbb{R}^{k \times 1}
" alt="">



<p class="wp-block-paragraph">Equivalently,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial \mathcal{L}}{\partial \mathbf{a}} =
\frac{\mathbf{y}}{\mathbf{a}}, \quad \in \mathbb{R}^{k \times 1}
" alt="">



<p class="wp-block-paragraph"></p>



<h3 class="wp-block-heading">Gradients of Loss with respect to z (dL/dz)</h3>



<p class="wp-block-paragraph">Using chain rule, to the find the gradient of loss with respect to <strong>z</strong> i.e. <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial \mathcal{L}}{\partial \mathbf{z}}"> , we multiply the derivative of softmax output <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial \mathbf{a}}{\partial \mathbf{z}}"> which is a <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?k \times k"> matrix with <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial \mathcal{L}}{\partial \mathbf{a}}"> which is of dimension <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?k \times 1"> ,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}\frac{\partial \mathcal{L}}{\partial \mathbf{z}} &#038; = &#038;  \frac{\partial \mathbf{a}}{\partial \mathbf{z}} \cdot  \frac{\partial \mathcal{L}}{\partial \mathbf{a}}  \\
&#038;= &#038; \begin{bmatrix} a_1(1 - a_1) &#038; -a_1 a_2 &#038; -a_1 a_3 &#038; \cdots &#038; -a_1 a_k \\ -a_2 a_1 &#038; a_2(1 - a_2) &#038; -a_2 a_3 &#038; \cdots &#038; -a_2 a_k \\ -a_3 a_1 &#038; -a_3 a_2 &#038; a_3(1 - a_3) &#038; \cdots &#038; -a_3 a_k \\ \vdots &#038; \vdots &#038; \vdots &#038; \ddots &#038; \vdots \\ -a_k a_1 &#038; -a_k a_2 &#038; -a_k a_3 &#038; \cdots &#038; a_k(1 - a_k) \end{bmatrix}\begin{bmatrix}
-\dfrac{y_1}{a_1} \\
-\dfrac{y_2}{a_2} \\
\vdots \\
-\dfrac{y_k}{a_k}
\end{bmatrix} \\

\\
&#038;=&#038; \begin{bmatrix}a_1(1 - a_1)\left(-\frac{y_1}{a_1}\right) 
+ (-a_1 a_2)\left(-\frac{y_2}{a_2}\right)
+ (-a_1 a_3)\left(-\frac{y_3}{a_3}\right)
+ \cdots 
+ (-a_1 a_k)\left(-\frac{y_k}{a_k}\right) \\
(-a_2 a_1)\left(-\frac{y_1}{a_1}\right)
+ a_2(1 - a_2)\left(-\frac{y_2}{a_2}\right)
+ (-a_2 a_3)\left(-\frac{y_3}{a_3}\right)
+ \cdots 
+ (-a_2 a_k)\left(-\frac{y_k}{a_k}\right) \\
\vdots\\
(-a_k a_1)\left(-\frac{y_1}{a_1}\right)
+ (-a_k a_2)\left(-\frac{y_2}{a_2}\right)
+ (-a_k a_3)\left(-\frac{y_3}{a_3}\right)

+ \cdots 

+ a_k(1 - a_k)\left(-\frac{y_k}{a_k}\right) \\

\end{bmatrix} 
\\
&#038;=&#038;
\begin{bmatrix}
-y_1(1 - a_1) + a_1y_2 + a_1y_3 + \dots + a_1y_k\\
a_2y_1  -y_2(1 - a_2) + a_2y_3 + \dots + a_2y_k\\
\vdots\\
a_ky_1 + a_ky_2 + a_ky_3\dots  -y_k(1 - a_k) \\
\end{bmatrix}

\\
&#038;=&#038;
\begin{bmatrix}
-y_1 + a_1\cdot\left(y_1 + y_2 + y_3 + \dots + y_k\right)\\
-y_2 + a_2\cdot\left(y_1 + y_2 + y_3 + \dots + y_k\right)\\
\vdots\\
-y_k + a_k\cdot\left(y_1 + y_2 + y_3 + \dots + y_k\right)
\end{bmatrix}

\text{, note : }y_1 + y_2 + y_3 + \dots + y_k=1 \\

&#038;=&#038;
\begin{bmatrix}
a_1-y_1 \\
a_2-y_2 \\
\vdots\\
a_k-y_k \\
\end{bmatrix} \in \mathbb{R}^{k \times 1}



\end{array}"/>



<p class="wp-block-paragraph">In vectorized form, can be represented as </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial \mathcal{L}}{\partial \mathbf{z}} = \mathbf{a} - \mathbf{y}, \quad \in \mathbb{R}^{k \times 1} " alt="">



<p class="wp-block-paragraph"></p>



<h3 class="wp-block-heading">Gradients of loss with respect to Parameters (dL/dW, dL/db)</h3>



<h4 class="wp-block-heading">Gradients of Weights (W)</h4>



<p class="wp-block-paragraph">Based on the chain rule, to find the gradient of loss with respect to parameter , we multiply each row of the <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial \mathcal{L}}{\partial \mathbf{z_i}}"> with the corresponding row from <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial z_i}{\partial \mathbf{W}_{i,:}} = \mathbf{x}^\top" alt=""> </p>



<p class="wp-block-paragraph"></p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}
\frac{\partial \mathcal{L}}{\partial \mathbf{W}} 
&#038;= &#038; \frac{\partial \mathcal{L}}{\partial \mathbf{z}} \cdot \frac{\partial \mathbf{z}}{\partial \mathbf{W}}\\

&#038;=&#038;
\begin{bmatrix}
(a_1-y_1) \cdot \mathbf{x}^\top \\
(a_2-y_2)  \cdot \mathbf{x}^\top  \\
\vdots\\
(a_k-y_k)  \cdot \mathbf{x}^\top \\
\end{bmatrix} 
\\

&#038;=&#038;
\begin{bmatrix}
(a_1-y_1) \\
(a_2-y_2) \\
\vdots\\
(a_k-y_k) \\
\end{bmatrix}  \mathbf{x}^\top \\

&#038;=&#038;
\begin{bmatrix}
(a_1-y_1) \\
(a_2-y_2) \\
\vdots\\
(a_k-y_k) \\
\end{bmatrix} \cdot 
\begin{bmatrix}
x_1 &#038; x_2 &#038; \cdots &#038; x_n
\end{bmatrix} \\

&#038; = &#038; 
\begin{bmatrix}
(a_1 - y_1) \cdot x_1 &#038; (a_1 - y_1) \cdot x_2 &#038; \cdots &#038; (a_1 - y_1) \cdot x_n \\
(a_2 - y_2) \cdot x_1 &#038; (a_2 - y_2) \cdot x_2 &#038; \cdots &#038; (a_2 - y_2) \cdot x_n \\
\vdots &#038; \vdots &#038; \ddots &#038; \vdots \\
(a_k - y_k) \cdot x_1 &#038; (a_k - y_k) \cdot x_2 &#038; \cdots &#038; (a_k - y_k) \cdot x_n
\end{bmatrix} \in \mathbb{R}^{k \times n} 

\end{array} 

" alt="">



<p class="wp-block-paragraph">This is equivalent to the outer product, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial \mathcal{L}}{\partial \mathbf{W}} = (\mathbf{a} - \mathbf{y}) \mathbf{x}^\top, \quad \in \mathbb{R}^{k \times n}" alt="">



<p class="wp-block-paragraph"></p>



<h4 class="wp-block-heading">Gradients of bias (b)</h4>



<p class="wp-block-paragraph">Recall the linear transformation: <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{z} = \mathbf{W} \mathbf{x} + \mathbf{b}" alt="">. The gradients are:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}\frac{\partial \mathcal{L}}{\partial \mathbf{b}} &#038; = &#038; \frac{\partial \mathcal{L}}{\partial \mathbf{z}} \cdot \frac{\partial \mathbf{z}}{\partial \mathbf{b}} \\

&#038;=&#038;(\mathbf{a} - \mathbf{y}) \mathbf{I}_k \\

&#038;=&#038;(\mathbf{a} - \mathbf{y}) 
\end{array} "  alt="">



<p class="wp-block-paragraph"></p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi? \quad \frac{\partial \mathcal{L}}{\partial \mathbf{b}} = \mathbf{a} - \mathbf{y}" alt="">



<p class="wp-block-paragraph">The intuition from above equations is :</p>



<p class="wp-block-paragraph">if the <strong>estimated probability <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{a}" alt=""> is close to the true value <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{y}" alt=""></strong> then the gradient is <strong>small</strong>, and the update to the parameters is also correspondingly <strong>smaller</strong>. If you recall, the gradients for <strong>binary classification</strong> <sup>(refer post on <a href="https://dsplog.com/2025/05/17/gradients-for-binary-classification/"> Gradients for Binary Classification with Sigmoid</a>)</sup>,  <strong>linear regression</strong> <sup>(refer post on <a href="https://dsplog.com/2025/05/01/gradients-for-linear-regression/#Gradients" target="_blank" rel="noreferrer noopener">Gradients for Linear Regression</a>)</sup> follows a similar intuitive explanation.</p>



<p class="wp-block-paragraph">These gradients are then used in the optimizer (e.g., SGD) to update parameters and reduce the loss.</p>



<h2 class="wp-block-heading">Vectorised operations (with m examples)</h2>



<p class="wp-block-paragraph">The <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?m" alt="">training examples each having <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?n" alt=""> features is represented as, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{X} = \begin{bmatrix}
x_{1}^1 &#038; x_{1}^2 &#038; \dots &#038; x_{1}^m \\
x_{2}^1 &#038; x_{2}^2 &#038; \dots &#038; x_{2}^m \\
\vdots &#038; \vdots &#038; \ddots &#038; \vdots \\
x_{n}^1 &#038; x_{n}^2 &#038; \dots &#038; x_{n}^m
\end{bmatrix}, \quad \mathbf{X} \in \mathbb{R}^{n \times m}
" alt="">



<p class="wp-block-paragraph">The output, which is a probability matrix across <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?k" alt=""> classes for each of the <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?m" alt=""> examples, is:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{Y} = \begin{bmatrix}
y_1^1 &#038; y_1^2 &#038; \dots &#038; y_1^m \\
y_2^1 &#038; y_2^2 &#038; \dots &#038; y_2^m \\
\vdots &#038; \vdots &#038; \ddots &#038; \vdots \\
y_k^1 &#038; y_k^2 &#038; \dots &#038; y_k^m
\end{bmatrix}, \quad \mathbf{Y} \in \mathbb{R}^{k \times m}
" alt="">



<p class="wp-block-paragraph">The linear transformation before applying the activation function (e.g., softmax) is given by:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{Z} = \mathbf{W} \mathbf{X} + \mathbf{b}, \quad  \in \mathbb{R}^{k \times m} 
" alt="">



<p class="wp-block-paragraph">where,  the parameters</p>



<ul class="wp-block-list">
<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{W} \in \mathbb{R}^{k \times n}" alt=""> and</li>



<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{b} \in \mathbb{R}^{k \times 1}" alt=""></li>
</ul>



<p class="wp-block-paragraph">The softmax activation is applied column-wise to the matrix <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{Z}"> to obtain the probability outputs:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi? 
\mathbf{A}_{:,j} = \mathrm{softmax}(\mathbf{Z}_{:,j}) = \frac{\exp(\mathbf{Z}_{:,j})}{\sum_{i=1}^{k} \exp(Z_{i,j})}, \quad \text{for } j = 1, 2, \dots, m
" alt="">



<p class="wp-block-paragraph">In matrix form, this is written as, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{A} = \begin{bmatrix}
a_1^1 &#038; a_1^2 &#038; \dots &#038; a_1^m \\
a_2^1 &#038; a_2^2 &#038; \dots &#038; a_2^m \\
\vdots &#038; \vdots &#038; \ddots &#038; \vdots \\
a_k^1 &#038; a_k^2 &#038; \dots &#038; a_k^m
\end{bmatrix}, \quad \mathbf{A} \in \mathbb{R}^{k \times m}
" alt="">



<p class="wp-block-paragraph">The cross-entropy loss compares the predicted probabilities <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{A}"> with the ground truth one-hot encoded labels <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{Y} \in \mathbb{R}^{k \times m}">:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
L = -\frac{1}{m} \sum_{j=1}^{m} \sum_{i=1}^{k} Y_{i,j} \log A_{i,j}
" alt="">



<p class="wp-block-paragraph">The derivative of the cross-entropy loss with softmax activation, with respect to the input <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{Z}"> (logits), simplifies to:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\frac{\partial L}{\partial \mathbf{Z}} = \mathbf{A} - \mathbf{Y},  \quad \in \mathbb{R}^{k \times m}
" alt="">



<p class="wp-block-paragraph">The gradient of the loss with respect to the weight matrix <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{W}"> is:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\frac{\partial L}{\partial \mathbf{W}} = \frac{1}{m} (\mathbf{A} - \mathbf{Y}) \mathbf{X}^\top, \in \mathbb{R}^{k \times n} 
" alt="">



<p class="wp-block-paragraph">
As the input matrix <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{X}"> has shape <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?n \times m">, the inner product 
<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
(\mathbf{A} - \mathbf{Y}) \mathbf{X}^\top
"> results in a matrix of shape 
<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?k \times n">. This captures the total gradient of the loss over all <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?m"> examples.
Averaging over the examples is done by multiplying with <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{1}{m}">.
</p>



<p class="wp-block-paragraph">The gradient of the loss with respect to the bias vector <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{b}"> is computed by summing the gradient over all <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?m"> examples using a row vector of ones:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\frac{\partial L}{\partial \mathbf{b}} = \frac{1}{m} (\mathbf{A} - \mathbf{Y}) \mathbf{1}_{m \times 1}, \quad \in \mathbb{R}^{k \times 1}
" alt="">



<p class="wp-block-paragraph">
Here, <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{A} - \mathbf{Y} \in \mathbb{R}^{k \times m}"> and 
<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{1}_{m \times 1}"> sums the gradients across all <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?m"> examples. 
The result is a <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?k \times 1"> vector, which matches the shape of <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{b}">.
</p>



<h3 class="wp-block-heading">Code (gradients)</h3>



<p class="wp-block-paragraph">Example code comparing the gradients computed using the derivation with autograd from PyTorch. </p>



<iframe loading="lazy" src="https://nbviewer.org/github/dsplog/dsplog.com/blob/main/code/gradients_multiclass_classification/gradients_cross_entropy_loss.ipynb?flush_cache=false" width="100%" height="600"></iframe>



<h2 class="wp-block-heading">Training for toy example with 3 classes</h2>



<p class="wp-block-paragraph">Below is an example of training a multi class classifier based on the model and gradient descent.&nbsp;<strong>Synthetic training</strong>&nbsp;data data is generated from two&nbsp;<strong>independent Gaussian random variables&nbsp;</strong>with zero mean and unit variance. Mean is shifted by <strong>(-2,-2), (+2,+2 ), (-2,+2 )&nbsp;</strong>corresponding to<strong>&nbsp;class 0</strong>,&nbsp;<strong>class 1, class 2</strong>&nbsp;respectively.</p>



<p class="wp-block-paragraph">The training loop is done using the&nbsp;<strong>numerically computed gradients&nbsp;</strong>and using the&nbsp;<code><strong>torch.autograd</strong></code>&nbsp;provided by&nbsp;<strong>PyTorch</strong>, and can see that both are numerically very close.</p>



<iframe loading="lazy" src="https://nbviewer.org/github/dsplog/dsplog.com/blob/main/code/gradients_multiclass_classification/training_multiclass_classification.ipynb?flush_cache=false" width="100%" height="600"></iframe>



<h2 class="wp-block-heading">Training with Label Smoothing</h2>



<p class="wp-block-paragraph">In the previous section, we derived the gradients for multi-class classification using <strong>one-hot encoded targets</strong>. In the paper <em>&#8220;Rethinking the Inception Architecture for Computer Vision&#8221;</em> by Szegedy et al. (2016) <a href="https://arxiv.org/abs/1512.00567" target="_blank" rel="noopener"><sup>(arXiv:1512.00567)</sup></a>, the idea of <strong>label smoothing</strong> was introduced. The key observation is that one-hot targets, which drives the predicted probability for the correct class toward 1 and ignore the other classes in the loss function, encourage models to become <strong>overconfident</strong>.</p>



<p class="wp-block-paragraph">Label smoothing combats this by replacing the <strong>hard 1</strong> in the true class with a <strong>slightly lower value</strong>, such as <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
(1 - \varepsilon)" alt="">, and distributing the remaining <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\varepsilon" alt=""> <strong>equally among the other classes</strong>. So, instead of teaching the model that <strong>one class is <em>absolutely</em> correct</strong>, we teach it that <strong>one class is <em>very likely</em> correct</strong> — allowing for some uncertainty.</p>



<p class="wp-block-paragraph">For a classification problem with  <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?K" alt=""> classes and smoothing parameter <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\varepsilon" alt=""> , the smoothed label vector becomes:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\mathbf{y}_{\text{smooth}} = (1 - \varepsilon) \cdot \mathbf{y}_{\text{one-hot}} + \frac{\varepsilon}{K}
" alt="">



<p class="wp-block-paragraph">For an example with <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?K" alt="">=4 classes,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}
\mathbf{y}_{\text{one-hot}} &#038; = &#038; [0, 0, 1, 0] \\

\mathbf{y}_{\text{smooth}} &#038; = &#038; \left[ \frac{\varepsilon}{K}, \frac{\varepsilon}{K}, 1 - \varepsilon, \frac{\varepsilon}{K} \right] \quad \text{where } K = 4
\end{array}
" alt="">



<p class="wp-block-paragraph">Even though we modify the target labels using label smoothing, the <strong>sum of the smoothed probabilities still adds up to 1</strong>. Because of this, the <strong>gradient derivations from the previous section remain valid</strong>. </p>



<h3 class="wp-block-heading">Training code</h3>



<p class="wp-block-paragraph">For the toy training example earlier, we compare the training with smoothed labels vs one-hot coded. In  PyTorch function <code>torch.nn.CrossEntropyLoss</code><span style="font-size: revert; color: initial;"> </span><a style="font-size: revert;" href="https://docs.pytorch.org/docs/stable/generated/torch.nn.CrossEntropyLoss.html" target="_blank" rel="noreferrer noopener"><sup>(refer entry on CELoss in PyTorch)</sup></a> has an optional argument <strong><code>label_smoothing</code></strong>  which implements the label smoothing as defined earlier. </p>



<iframe loading="lazy" src="https://nbviewer.org/github/dsplog/dsplog.com/blob/main/code/gradients_multiclass_classification/training_label_smoothing.ipynb?flush_cache=false" width="100%" height="600"></iframe>



<p class="wp-block-paragraph">In the training results on the toy example we can see that the <strong>loss is higher</strong> for the training<strong> </strong>with<strong> label smoothing</strong> and correspondingly <strong>misclassification rate </strong>is also<strong> slightly higher</strong>.</p>



<p class="wp-block-paragraph">However, label smoothing has been shown to <strong>improve generalization </strong>in larger models trained on complex datasets. The concept was first introduced in <em><strong>Rethinking the Inception Architecture for Computer Vision</strong></em> <a class="" href="https://arxiv.org/abs/1512.00567" target="_blank" rel="noopener">(Szegedy et al., 2016)</a>, and was later used in the foundational paper <em><strong>Attention is All You Need</strong></em> <a class="" href="https://arxiv.org/abs/1706.03762" target="_blank" rel="noopener">(Vaswani et al., 2017)</a>. A broader study, <strong><em>When Does Label Smoothing Help?</em> </strong><a class="" href="https://arxiv.org/abs/1906.02629" target="_blank" rel="noopener">(Müller et al., 2019)</a>, analyzed its effectiveness in large models like <strong>ResNets</strong> and <strong>Transformers</strong>.</p>



<h2 class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">The post covers the following key aspects</p>



<ul class="wp-block-list">
<li><strong>System model </strong>for <strong>multi class classification</strong> with <strong>linear layer</strong> and <strong>softmax</strong></li>



<li><strong>Loss function&nbsp;</strong>based on<strong> categorical cross entropy</strong> and showing that this is <strong>Maximum Likelihood Estimate</strong></li>



<li>Computation of the&nbsp;<strong>gradient</strong>&nbsp;based on&nbsp;<strong>chain rule of derivatives</strong></li>



<li><strong>Vectorized Operations</strong>&nbsp;for batch of examples which implements  computations using efficient matrix and vector math.</li>



<li><strong>Training loop</strong>&nbsp;for the classification using both manual and PyTorch based gradients</li>



<li>Explains the concept of <strong>label smoothing </strong>and implements a training loop for explaining the concept</li>
</ul>



<p class="wp-block-paragraph">Have any questions or feedback? Feel free to drop your feedback in the comments section. <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /> </p>
<p>The post <a rel="nofollow" href="https://dsplog.com/2025/06/22/gradients-for-multi-class-classification-with-softmax/">Gradients for multi class classification with Softmax</a> appeared first on <a rel="nofollow" href="https://dsplog.com">DSP LOG</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://dsplog.com/2025/06/22/gradients-for-multi-class-classification-with-softmax/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Gradients for Binary Classification with Sigmoid</title>
		<link>https://dsplog.com/2025/05/17/gradients-for-binary-classification/</link>
					<comments>https://dsplog.com/2025/05/17/gradients-for-binary-classification/#comments</comments>
		
		<dc:creator><![CDATA[Krishna Sankar]]></dc:creator>
		<pubDate>Sat, 17 May 2025 13:05:07 +0000</pubDate>
				<category><![CDATA[Machine Learning]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[Binary Classification]]></category>
		<category><![CDATA[Binary Cross Entropy]]></category>
		<category><![CDATA[Maximum Likelihood]]></category>
		<category><![CDATA[ML]]></category>
		<category><![CDATA[Sigmoid]]></category>
		<guid isPermaLink="false">https://dsplog.com/?p=2162</guid>

					<description><![CDATA[<p>In a classification problem, the output (also called the label or class) takes a small number of discrete values rather than continuous values. For a simple binary classification problem, where output takes only two discrete values : 0 or 1, the sigmoid function can be used to transform the output of a linear regression model &#8230; <a href="https://dsplog.com/2025/05/17/gradients-for-binary-classification/" class="more-link">Continue reading<span class="screen-reader-text"> "Gradients for Binary Classification with Sigmoid"</span></a></p>
<p>The post <a rel="nofollow" href="https://dsplog.com/2025/05/17/gradients-for-binary-classification/">Gradients for Binary Classification with Sigmoid</a> appeared first on <a rel="nofollow" href="https://dsplog.com">DSP LOG</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">In a <strong>classification</strong> problem, the output (also called the <strong>label</strong> or <strong>class</strong>) takes a small number of <strong>discrete values</strong> rather than continuous values. For a simple <strong>binary classification</strong> problem, where output takes only <strong>two discrete </strong>values : 0 or 1, the <strong>sigmoid function</strong> can be used to transform the output of a <strong>linear regression</strong> model into a value between 0 and 1, squashing the continuous prediction into a <strong>probability</strong>-like score. This score can then be interpreted as the <strong>likelihood</strong> of the output being class 1, with a <strong>threshold</strong> (commonly 0.5) used to decide between class 0 and class 1.</p>



<p class="wp-block-paragraph">In this post, the intuition for <strong>loss function</strong> for <strong>binary classification</strong> based on <strong>Maximum Likelihood Estimate (MLE)</strong> is explained. We then derive the <strong>gradients</strong> for model parameters using the <strong>chain rule</strong>. Gradients computed&nbsp;<strong>analytically</strong>&nbsp;are compared against gradients computed using deep learning framework&nbsp;<strong>PyTorch</strong>. Further, <strong>training loop</strong> using&nbsp;<strong>gradient descent</strong>&nbsp;for a binary classification problem having two dimensional Gaussian distributed data is implemented.</p>



<span id="more-2162"></span>






<p class="wp-block-paragraph">As always, contents from <a href="https://cs229.stanford.edu/main_notes.pdf" target="_blank" rel="noreferrer noopener">CS229 Lecture Notes</a> and the notations used in the course <a href="https://youtube.com/playlist?list=PLkDaE6sCZn6Ec-XTbcX1uRg2_u4xOEky0&amp;si=_3Xs1piNOfQ847gd" target="_blank" rel="noopener">Deep Learning Specialization C1W1L01</a> from Dr Andrew Ng forms key references.</p>



<h2 class="wp-block-heading">Model</h2>



<p class="wp-block-paragraph">Let us take an example of estimating <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?y \in \{0, 1\}" alt=""> based on feature vector <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{x}" alt=""> having <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?n" alt=""> features i.e. <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{x} \in \mathbb{R}^n" alt="">.</p>



<p class="wp-block-paragraph">There are <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?m" alt=""> examples.</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{tabular}{|c|c|c|c|c|}
\hline&amp;{example^1}&amp;{example^2}&amp;\ldots&amp;{example^m}\\
\hline{feature_1}&amp;{x_1}^{1}&amp;{x_1}^{2}&amp;\ldots&amp;{x_1}^{m}\\
\hline{feature_2}&amp;{x_2}^{1}&amp;{x_2}^{2}&amp;\ldots&amp;{x_2}^{m}\\
\hline&amp;\vdots&amp;\vdots&amp;\ldots&amp;\vdots\\
\hline{feature_n}&amp;{x_n}^{1}&amp;{x_n}^{2}&amp;\ldots&amp;{x_n}^{m}&amp;\\
\hline{output}&amp;{y}^{1}&amp;{y}^{2}&amp;\ldots&amp;{y}^{m}\end{tabular}
" alt="">



<p class="wp-block-paragraph">Let us <strong>assume</strong> that the variable <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?{z}" alt="">is defined as <strong>linear function</strong> of <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{x}" alt="">. Then <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?{z}" alt=""> gets transformed into a probability score <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?a" alt=""> using <strong>sigmoid function</strong>. For a single training example, this can be written as :</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}{z}^1&#038;=&#038;w_1{x_1}^1+w_2{x_2}^1+\dots+w_n{x_n}^1+b\\&#038;=&#038;\mathbf{w^T}\mathbf{x}^1+b\end{array}" alt="">



<p class="wp-block-paragraph">where, </p>



<ul class="wp-block-list">
<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{w}" alt=""> is the feature vector of size <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?n" alt=""> i.e. <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{w} \in \mathbb{R}^n" alt="">and</li>



<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?b" alt=""> is a scalar</li>
</ul>



<p class="wp-block-paragraph">To convert the real number <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?{z}" alt=""> to a number <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?a" alt="">lying between 0 and 1, let us define</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{equation}
a^1 = \sigma(z^1) = \frac{1}{1 + \exp(-z^1)} = \frac{1}{1 + \exp\left(-(\mathbf{w^T} \mathbf{x}^1 + b)\right)}
\end{equation}" alt="">



<p class="wp-block-paragraph">where,  <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\sigma(z)" alt=""> is the sigmoid function <a href="https://en.wikipedia.org/wiki/Sigmoid_function" target="_blank" rel="noopener"><sup>(refer wiki entry on sigmoid function</sup>)</a></p>



<h2 class="wp-block-heading">Sigmoid function and its derivative</h2>



<p class="wp-block-paragraph">Sigmoid function which has a smooth S-shaped mathematical function is defined as:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{equation}
\sigma(z) = \frac{1}{1 + \exp(-z)}
\end{equation}" alt="">



<p class="wp-block-paragraph">which has the properties</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\textbf{Output range: } (0, 1)\\
\text{As } z \to -\infty, \quad \sigma(z) \to 0 \\
\text{As } z \to +\infty, \quad \sigma(z) \to 1  \\
\text{Symmetric around } z = 0: \quad \sigma(0) = 0.5
" alt="">



<p class="wp-block-paragraph">The derivative of sigmoid <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\sigma'(z)" alt=""> is, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{rcll}
\sigma'(z) &#038; = &#038; \dfrac{d}{dz} \left( \dfrac{1}{1 + e^{-z}} \right) \\
&#038; = &#038; -1 \cdot \left(1 + e^{-z} \right)^{-2} \cdot \dfrac{d}{dz}(1 + e^{-z}) \\
&#038; = &#038; - \dfrac{1}{(1 + e^{-z})^2} \cdot (-e^{-z}) \\
&#038; = &#038; \dfrac{e^{-z}}{(1 + e^{-z})^2} \\
&#038; = &#038; \left( \dfrac{1}{1 + e^{-z}} \right) \left( \dfrac{e^{-z}}{1 + e^{-z}} \right) \\
&#038; = &#038; \sigma(z)\left(1 - \sigma(z)\right)
\end{array}" alt="">



<iframe loading="lazy" src="https://nbviewer.org/github/dsplog/dsplog.com/blob/main/code/gradients_binary_classification/sigmoid_and_derivative.ipynb?flush_cache=false" width="100%" height="600"></iframe>



<p class="wp-block-paragraph">From the plots of derivative of sigmoid, two key observations :</p>



<ul class="wp-block-list">
<li><strong>Vanishing gradients</strong> : for very large or very small <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?{z}" alt="">, the derivative approaches 0 causing gradients to vanish during back propagation — this slows or stalls learning in deep networks.</li>



<li><strong>Low Maximum Gradient</strong> : the maximum value of derivative is 0.25, which caps the gradient flow, making it harder for deep layers to effectively update their weights</li>
</ul>



<p class="wp-block-paragraph">As mentioned in the article<a href="https://karpathy.medium.com/yes-you-should-understand-backprop-e2f06eab496b" target="_blank" rel="noopener"> Yes you should understand backprop by Andrej Karpathy</a>, these aspects have to be kept in mind when using <strong>sigmoid</strong> for training <strong>deeper neural networks</strong>.<br></p>



<h2 class="wp-block-heading">Loss function for binary classification</h2>



<h3 class="wp-block-heading">Maximum Likelihood Estimation </h3>



<p class="wp-block-paragraph">Let us assume that the probability of output being 1, given input <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{x}" alt=""> and parameters <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{w}" alt="">, <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?b" alt=""> is, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?P(y = 1 \mid \mathbf{x}, \mathbf{w}, b) = a = \sigma(z) = \frac{1}{1 + e^{-(\mathbf{w^T} \mathbf{x}+b)}}
" alt="">



<p class="wp-block-paragraph">Then, for the binary classification, the probability of output being 0 is,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?P(y = 0 \mid \mathbf{x},\mathbf{w}, b) = 1-a 
" alt="">



<p class="wp-block-paragraph">Since <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?y" alt=""> can either be 0 or 1, we can compactly write the <strong>likelihood</strong> as:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?P(y^i|x^i,\mathbf{w}, b) = (a^i)^{y^i}  (1-a^i)^{(1-y^i)} 
" alt="">



<p class="wp-block-paragraph">The <strong>likelihood function</strong> is the probability of the actual label <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?y \in \{0, 1\}" alt="">given the prediction <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?a" alt="">. When the multiple independent training examples are <strong>independently and identically distributed (i.i.d.)</strong>, the total likelihood for the dataset is the <strong>product of the likelihoods</strong> for each example. With this assumption, for <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?m" alt=""> training examples, the likelihood for the parameters <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{w}" alt=""> and <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?b" alt=""> is,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathcal{L}(w, b) = \prod_{i=1}^{m} P(y_i \mid x_i, \mathbf{w},b)
 = \prod_{i=1}^{m} (a^i)^{y^i}  (1-a^i)^{(1-y^i)} 
" alt="">



<h3 class="wp-block-heading">Log Likelihood</h3>



<p class="wp-block-paragraph">To avoid the<strong> product of many small numbers</strong>, we take the <strong>natural logarithm</strong> of the<strong> likelihood function</strong>. The <strong>log-likelihood </strong>for the entire dataset is the sum of the log-likelihoods for each example:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}
\log \mathcal{L}(w, b) &#038;=&#038; \log \prod_{i=1}^{m} P(y_i \mid x_i, \mathbf{w},b)\\ 
&#038;=&#038; \sum_{i=1}^{m} \log P(y_i \mid x_i, \mathbf{w},b) \\
&#038;=&#038; \sum_{i=1}^{m} \log \left[(a^i)^{y^i}  (1-a^i)^{(1-y^i)} \right] \\
&#038;=&#038; \sum_{i=1}^{m} \left[ y^{i} \log a^{i} + (1 - y^{i}) \log(1 - a^{i}) \right]
\end{array}
 
" alt="">



<h3 class="wp-block-heading">Negative Log Likelihood</h3>



<p class="wp-block-paragraph">Since <strong>optimizers</strong> like gradient descent are designed to <strong>minimize</strong> functions, we<strong> minimize the negative log-likelihood</strong> instead of<strong> maximizing the log-likelihood</strong>. </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}
\text{neg } \log \mathcal{L}(w, b) 
&#038;=&#038; -\sum_{i=1}^{m} \left[ y^{i} \log a^{i} + (1 - y^{i}) \log(1 - a^{i}) \right]
\end{array}
 
" alt="">



<h3 class="wp-block-heading">Averaging the Loss</h3>



<p class="wp-block-paragraph">Averaging the loss ensures that the total loss remains on the <strong>same scale</strong>, regardless of the size of the training dataset. This is important because it allows the use of a <strong>fixed learning rate</strong> across different dataset sizes, leading to more stable and consistent optimization behaviour.</p>



<p class="wp-block-paragraph">The <strong>averaged negative log-likelihood</strong> is defined as:</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}
\text{neg } \log \mathcal{L}_{\text{avg}}(w, b) 
&#038;=&#038; -\frac{1}{m}\sum_{i=1}^{m} \left[ y^{i} \log a^{i} + (1 - y^{i}) \log(1 - a^{i}) \right]
\end{array}
 
" alt="">



<p class="wp-block-paragraph">This expression is known as the <strong>Binary Cross-Entropy (BCE) Loss</strong>, which is widely used in <strong>binary classification</strong> tasks. This function is available in PyTorch library as <code>torch.nn.BCELoss</code> <a href="https://docs.pytorch.org/docs/stable/generated/torch.nn.BCELoss.html" target="_blank" rel="noopener"><sup>(refer entry on BECLoss in PyTorch)</sup></a>.</p>



<h2 class="wp-block-heading">Gradients with Binary Cross Entropy (BCE) Loss</h2>



<p class="wp-block-paragraph">The system model for binary classification involves multiple steps: </p>



<ul class="wp-block-list">
<li>firstly, the variable <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?{z}" alt="">is defined as <strong>linear function</strong> of <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{x}" alt=""> using parameters <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{w}" alt="">, <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?b" alt="">.</li>



<li>then <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?{z}" alt=""> gets transformed into a <strong>estimated probability</strong> score <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?a" alt=""> using <strong>sigmoid function</strong>. </li>



<li>lastly, use the<strong> true label </strong><img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?y \in \{0, 1\}" alt=""> and estimated probability score <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?a" alt="">,<strong> binary cross entropy</strong> loss <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathcal{L}" alt=""> is computed</li>
</ul>



<p class="wp-block-paragraph">For performing gradient descent of the parameters, the goal is to the find the gradients of the loss <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathcal{L}" alt=""> w.r.t to the parameters <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{w}" alt=""> and <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?b" alt="">.  To find the gradients, we go in the reverse order i.e.</p>



<ul class="wp-block-list">
<li>firstly, gradients of the loss <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathcal{L}" alt=""> w.r.t to the estimated probability score <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?a" alt=""></li>



<li>then gradients of the probability score <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?a" alt=""> w.r.t to the output of linear function <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?{z}" alt=""></li>



<li>lastly, gradients of output of linear function <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?{z}" alt=""> w.r.t to parameters  <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{w}" alt="">, <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?b" alt=""></li>
</ul>



<p class="wp-block-paragraph">Then the product of all the individual gradients from the gradients of loss w.r.t to the parameters. This is written as,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial \mathcal{L}}{\partial \mathbf{w}} = \frac{\partial \mathcal{L}}{\partial a} \cdot \frac{\partial a}{\partial z} \cdot \frac{\partial z}{\partial \mathbf{w}}
" alt="">



<p class="wp-block-paragraph">The steps described, calculating gradients in the reverse order from the loss back to the parameters<strong> </strong>is an application of the<strong> chain rule from calculus</strong> <a href="https://en.wikipedia.org/wiki/Chain_rule#Intuitive_explanation" target="_blank" rel="noopener"><sup>(refer wiki entry on Chain Rule)</sup></a>. This method is the foundation of <strong>backpropagation</strong> used in training models <a href="https://en.wikipedia.org/wiki/Backpropagation" target="_blank" rel="noopener"><sup>(refer wiki entry on Backpropagation)</sup></a>.</p>



<h3 class="wp-block-heading">Deriving the gradients</h3>



<p class="wp-block-paragraph">For simplicity, take a single example and computing gradients step by step, </p>



<h4 class="wp-block-heading">Step1 : Gradients of loss w.r.t to probability score </h4>



<p class="wp-block-paragraph">With the loss <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathcal{L} = \left[ y^{1} \log a^{1} + (1 - y^{1}) \log(1 - a^{1})\right]" alt="">, then the derivative of loss w.r.t to sigmoid output <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?a" alt=""> is,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial \mathcal{L}}{\partial a} = \frac{y^1}{a^1} - \frac{1-y^1}{1-a^1}
" alt="">



<h4 class="wp-block-heading">Step2 : Gradients of probability score w.r.t to output of linear function</h4>



<p class="wp-block-paragraph">With <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?a^1 =\sigma(z^1)" alt=""> as the output of sigmoid function, the derivative is </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial a}{\partial z} = \sigma(z^1)(1-\sigma(z^1))= a^1(1-a^1)
" alt="">



<h4 class="wp-block-heading">Step3 : Gradients of output of linear function w.r.t to parameters</h4>



<p class="wp-block-paragraph">With <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}{z}^1&amp;=&amp;w_1{x_1}^1+w_2{x_2}^1+\dots+w_n{x_n}^1+b&amp;=&amp;\mathbf{w^T}\mathbf{x}^1+b\end{array} " alt="">, the derivative is, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial z}{\partial \mathbf{w}}  = [x_1^1, x_2^1, \dots, x_n^1] = \mathbf{x^1}
" alt="">



<p class="wp-block-paragraph">Similarly,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial z}{\partial b}  = 1
" alt="">



<h4 class="wp-block-heading">Gradients of loss w.r.t to parameters </h4>



<p class="wp-block-paragraph">Taking the product of the gradients from all the steps,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{align*}
\frac{\partial \mathcal{L}}{\partial w} 
&#038;= \frac{\partial \mathcal{L}}{\partial a} \cdot \frac{\partial a}{\partial z} \cdot \frac{\partial z}{\partial \mathbf{w}} \\
&#038;= -\left( \frac{y^1}{a^1} - \frac{1 - y^1}{1 - a^1} \right)  \cdot a^1(1 - a^1) \cdot \mathbf{x^1} \\
&#038;= \left( -y^1(1 - a^1) + (1 - y^1)a^1 \right) \cdot \mathbf{x^1} \\
&#038;= \left( -y^1 + y^1a^1 + a^1 - a^1y^1 \right) \cdot \mathbf{x^1} \\
&#038;= (a^1 - y^1) \cdot \mathbf{x^1} \\
\end{align*}
" 
alt="">



<p class="wp-block-paragraph">Similarly, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{align*}
\frac{\partial \mathcal{L}}{\partial b} 
&#038;= \frac{\partial \mathcal{L}}{\partial a} \cdot \frac{\partial a}{\partial z} \cdot \frac{\partial z}{\partial \mathbf{b}} \\
&#038;= -\left( \frac{y^1}{a^1} - \frac{1 - y^1}{1 - a^1} \right)  \cdot a^1(1 - a^1)  \\
&#038;= \left( -y^1(1 - a^1) + (1 - y^1)a^1 \right)   \\
&#038;= \left( -y^1 + y^1a^1 + a^1 - a^1y^1 \right)  \\
&#038;= (a^1 - y^1) \\
\end{align*}
" 
alt="">



<p class="wp-block-paragraph">The intuition from above equations is :</p>



<p class="wp-block-paragraph">if the <strong>estimated probability <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?{a}=\sigma(z) = \sigma(\mathbf{w^T}\mathbf{x}+b)" alt=""> is close to the true value <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?y" alt=""></strong> then the gradient is <strong>small</strong>, and the update to the parameters is also correspondingly <strong>smaller</strong>. If you recall, the gradients for linear regression <sup>(refer post on <a href="https://dsplog.com/2025/05/01/gradients-for-linear-regression/#Gradients" target="_blank" rel="noreferrer noopener">Gradients for Linear Regression</a>)</sup> follows a similar intuitive explanation.</p>



<p class="wp-block-paragraph"><strong>Note : </strong>With <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?m" alt=""> training examples the loss is averaged, and this becomes :</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}\frac{\partial%20L}{\partial%20w_n}&#038;=&#038;\frac{1}{m}\sum_{i=1}^m\(a^i-y^i\){x_n}^i\end{array}" alt="">



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}\frac{\partial%20L}{\partial%20b}&#038;=&#038;\frac{1}{m}\sum_{i=1}^m\(a^i-y^i\)\end{array}" alt="">



<h3 class="wp-block-heading">Vectorised operations</h3>



<p class="wp-block-paragraph">The <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?m" alt="">training examples each having <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?n" alt=""> features is represented as, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{X} = \begin{bmatrix}
x_{1}^1 &#038; x_{1}^2 &#038; \dots &#038; x_{1}^m \\
x_{2}^1 &#038; x_{2}^2 &#038; \dots &#038; x_{2}^m \\
\vdots &#038; \vdots &#038; \ddots &#038; \vdots \\
x_{n}^1 &#038; x_{n}^2 &#038; \dots &#038; x_{n}^m
\end{bmatrix}, \quad \mathbf{X} \in \mathbb{R}^{n \times m}
" alt="">



<p class="wp-block-paragraph">The output is,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{y} = \begin{bmatrix}
y^1 &#038; y^2 &#038; \dots &#038; y^m \end{bmatrix}, \quad \mathbf{y} \in \mathbb{R}^{1 \times m}
" alt="">



<p class="wp-block-paragraph">The parameters <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{w}" alt=""> and <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?b" alt=""> represented as,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{w} = \begin{bmatrix} w_1 \\ w_2 \\ \vdots \\ w_n \end{bmatrix}, \quad \mathbf{w} \in \mathbb{R}^{n \times 1}
" alt="">



<p class="wp-block-paragraph"><img decoding="async" style="font-size: revert; color: initial;" src="https://dsplog.com/cgi-bin/mimetex.cgi?b\in \mathbb{R}^{1 \times 1}
" alt=""></p>



<p class="wp-block-paragraph">where, </p>



<ul class="wp-block-list">
<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{w}" alt=""> is the feature vector of size <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?n" alt=""> i.e. <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{w} \in \mathbb{R}^n" alt="">and</li>



<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?b" alt=""> is a scalar</li>
</ul>



<p class="wp-block-paragraph">The output <img decoding="async" align="absmiddle" src="https://dsplog.com/cgi-bin/mimetex.cgi?a" alt=""> is,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}\mathbf{a}&#038; = &#038; \sigma(\mathbf{z}) = \sigma( \mathbf{w^T}\mathbf{X} +b) &#038;=&#038;\begin{bmatrix}
a^1 &#038; a^2 &#038; \dots &#038; a^m \end{bmatrix}, \quad \mathbf{a} \in \mathbb{R}^{1 \times m}\end{array}
" alt="">



<p class="wp-block-paragraph">Gradients, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?d\mathbf{w} = \begin{bmatrix}
\frac{\partial \mathbf{L}}{\partial w_1} \\ \frac{\partial \mathbf{L}}{\partial w_2} \\ \vdots \\ \frac{\partial \mathbf{L}}{\partial w_n} \end{bmatrix}, \quad d\mathbf{w} \in \mathbb{R}^{n \times 1}
" alt="">



<p class="wp-block-paragraph"><br>The gradient w.r.t to <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{w}" alt=""> can be represented in matrix operations as,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}d\mathbf{w} &#038;=&#038; \frac{1}{m}\begin{bmatrix}
x_{1}^1 &#038; x_{1}^2 &#038; \dots &#038; x_{1}^m \\
x_{2}^1 &#038; x_{2}^2 &#038; \dots &#038; x_{2}^m \\
\vdots &#038; \vdots &#038; \ddots &#038; \vdots \\
x_{n}^1 &#038; x_{n}^2 &#038; \dots &#038; x_{n}^m
\end{bmatrix}\begin{bmatrix}a^1-y^1\\a^2-y^2\\\vdots\\a^m-y^m\end{bmatrix}\\
&#038;=&#038;\frac{1}{m}\mathbf{X}(\mathbf{a}-\mathbf{y})^T\end{array}
" alt="">



<p class="wp-block-paragraph">Similarly, for the bias term</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}\frac{\partial L}{\partial b}=d\mathbf{b} &#038;=&#038; \frac{1}{m}\underbrac{\begin{bmatrix}
1 &#038; 1 &#038; \dots &#038; 1 \\
\end{bmatrix}}_{1\times m}\begin{bmatrix}a^1-y^1\\a^2-y^2\\\vdots\\a^m-y^m\end{bmatrix}\\
&#038;=&#038;\frac{1}{m}\sum_i^m(a^i-y^i)\end{array}
" alt="">



<h3 class="wp-block-heading">Gradients computed numerically vs PyTorch</h3>



<iframe loading="lazy" src="https://nbviewer.org/github/dsplog/dsplog.com/blob/main/code/gradients_binary_classification/gradients_binary_cross_entropy_loss.ipynb?flush_cache=false" width="100%" height="600"></iframe>



<h2 class="wp-block-heading">Training &#8211; Binary Classification</h2>



<p class="wp-block-paragraph">Below is an example of training a binary classifier based on the model and gradient descent. <strong>Synthetic training</strong> data data is generated from two <strong>independent Gaussian random variables </strong>with zero mean and unit variance. Mean is shifted on <strong>half the samples by (-2,-2) </strong>and the<strong> remaining half by (+2,+2 ) </strong>corresponding to<strong> class 0</strong> and <strong>class 1</strong> respectively.</p>



<p class="wp-block-paragraph">The training loop is done using the <strong>numerically computed gradients </strong>and using the <code><strong>torch.autograd</strong></code> provided by <strong>PyTorch</strong>, and can see that both are numerically very close.</p>



<iframe loading="lazy" src="https://nbviewer.org/github/dsplog/dsplog.com/blob/main/code/gradients_binary_classification/training_loop_binary_classification.ipynb?flush_cache=false" width="100%" height="600"></iframe>



<p class="wp-block-paragraph">The <strong>estimated probability score</strong> indicates the <strong>likelihood</strong> that the given input corresponds to one of the classes. As can be seen in the plot <strong>Predicted Probability for Each Input</strong>, inputs<strong> close to center point</strong> (0,0) have a <strong>probability close to 0.5</strong>, and as we move <strong>away from the center</strong> the probabilities tend to be <strong>closer to either 0 or 1</strong>.</p>



<p class="wp-block-paragraph">To convert this probability into a <strong>class label</strong>, a <strong>decision threshold</strong> needs to be applied. In this example, as can be seen in the plot of <strong>Classification Error vs Threshold</strong>, the t<strong>hreshold of 0.5 is corresponding to the lowest error rate</strong>.</p>



<p class="wp-block-paragraph">However, there are other scenarios where the <strong>threshold of 0.5 can be inappropriate</strong> &#8211; like dealing with <strong>imbalanced</strong> datasets, <strong>skewed class </strong>distribution etc. These require adjusting the threshold for better performance.</p>



<h2 class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">The post covers the following key aspects</p>



<ul class="wp-block-list">
<li><strong>Loss function </strong>based on<strong> Maximum Likelihood Estimate </strong></li>



<li>Computation of the <strong>gradient</strong> based on <strong>chain rule of derivates</strong></li>



<li><strong>Vectorized Operations</strong> Implements all computations using efficient matrix and vector math.</li>



<li><strong>Training loop</strong> for the binary classification using both manual and PyTorch based gradients</li>
</ul>



<p class="wp-block-paragraph">Have any questions or feedback on the gradient computation techniques? Feel free to drop your feedback in the comments section. <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p>The post <a rel="nofollow" href="https://dsplog.com/2025/05/17/gradients-for-binary-classification/">Gradients for Binary Classification with Sigmoid</a> appeared first on <a rel="nofollow" href="https://dsplog.com">DSP LOG</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://dsplog.com/2025/05/17/gradients-for-binary-classification/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Gradients for linear regression</title>
		<link>https://dsplog.com/2025/05/01/gradients-for-linear-regression/</link>
					<comments>https://dsplog.com/2025/05/01/gradients-for-linear-regression/#comments</comments>
		
		<dc:creator><![CDATA[Krishna Sankar]]></dc:creator>
		<pubDate>Thu, 01 May 2025 06:02:13 +0000</pubDate>
				<category><![CDATA[Machine Learning]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[Gradient]]></category>
		<category><![CDATA[MAE]]></category>
		<category><![CDATA[ML]]></category>
		<category><![CDATA[MSE]]></category>
		<category><![CDATA[PyTorch]]></category>
		<guid isPermaLink="false">https://dsplog.com/?p=2019</guid>

					<description><![CDATA[<p>Understanding gradients is essential in machine learning, as they indicate the direction and rate of change in the loss function with respect to model parameters. This post covers the gradients for the vanilla Linear Regression case taking two loss functions Mean Square Error (MSE) and Mean Absolute Error (MAE) as examples. The gradients computed analytically &#8230; <a href="https://dsplog.com/2025/05/01/gradients-for-linear-regression/" class="more-link">Continue reading<span class="screen-reader-text"> "Gradients for linear regression"</span></a></p>
<p>The post <a rel="nofollow" href="https://dsplog.com/2025/05/01/gradients-for-linear-regression/">Gradients for linear regression</a> appeared first on <a rel="nofollow" href="https://dsplog.com">DSP LOG</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Understanding  <strong>gradients</strong> is essential in <strong>machine learning,</strong> as they indicate the <strong>direction</strong> and <strong>rate of change</strong> in the loss function with respect to model parameters.  This post covers the gradients for the vanilla <strong>Linear Regression </strong>case taking two loss functions <strong>Mean Square Error (MSE)</strong> and <strong>Mean Absolute Error (MAE)</strong>  as examples. </p>



<p class="wp-block-paragraph">The gradients computed <strong>analytically</strong> are compared against gradient computed using deep learning framework <strong>PyTorch</strong>. Further, using the gradients, training loop using <strong>gradient descent</strong> is implemented for the simplest example of <strong>fitting a straight line</strong>.</p>



<p class="wp-block-paragraph">As always, contents from <a href="https://cs229.stanford.edu/main_notes.pdf" target="_blank" rel="noreferrer noopener">CS229 Lecture Notes</a> and the notations used in the course <a href="https://youtube.com/playlist?list=PLkDaE6sCZn6Ec-XTbcX1uRg2_u4xOEky0&amp;si=_3Xs1piNOfQ847gd" target="_blank" rel="noopener">Deep Learning Specialization C1W1L01</a> from Dr Andrew Ng forms key references.</p>



<span id="more-2019"></span>






<h2 class="wp-block-heading">Model</h2>



<p class="wp-block-paragraph">Let us take an example of estimating <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?y" alt=""> based on feature vector <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{x}" alt=""> having <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?n" alt=""> features i.e. <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{x} \in \mathbb{R}^n" alt="">.</p>



<p class="wp-block-paragraph">There are <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?m" alt=""> examples.</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{tabular}{|c|c|c|c|c|}
\hline&amp;{example^1}&amp;{example^2}&amp;\ldots&amp;{example^m}\\
\hline{feature_1}&amp;{x_1}^{1}&amp;{x_1}^{2}&amp;\ldots&amp;{x_1}^{m}\\
\hline{feature_2}&amp;{x_2}^{1}&amp;{x_2}^{2}&amp;\ldots&amp;{x_2}^{m}\\
\hline&amp;\vdots&amp;\vdots&amp;\ldots&amp;\vdots\\
\hline{feature_n}&amp;{x_n}^{1}&amp;{x_n}^{2}&amp;\ldots&amp;{x_n}^{m}&amp;\\
\hline{output}&amp;{y}^{1}&amp;{y}^{2}&amp;\ldots&amp;{y}^{m}\end{tabular}
" alt="">



<p class="wp-block-paragraph"><strong>Assume</strong> that the estimate <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?{z}" alt="">is as <strong>linear function</strong> of <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{x}" alt="">. </p>



<p class="wp-block-paragraph">For a single training example, this can be written as : </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}{z}^1&#038;=&#038;w_1{x_1}^1+w_2{x_2}^1+\dots+w_n{x_n}^1+b\\&#038;=&#038;\mathbf{w^T}\mathbf{x}^1+b\end{array}" alt="">



<p class="wp-block-paragraph">where, </p>



<ul class="wp-block-list">
<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{w}" alt=""> is the feature vector of size <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?n" alt=""> i.e. <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{w} \in \mathbb{R}^n" alt="">and</li>



<li><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?b" alt=""> is a scalar</li>
</ul>



<h2 class="wp-block-heading">Least Mean Squares</h2>



<p class="wp-block-paragraph">To find the parameters <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{w}" alt=""> and <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?b" alt="">, based on <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?m" alt=""> training examples, need to formalise a metric to quantify the &#8220;<strong>closeness</strong>&#8221; of the estimate <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?{z}" alt=""> to the true value <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?y" alt="">. As an arbitrary choice, let us define a metric <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?L" alt=""> based on the <strong>mean square error (MSE)</strong> as,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}L&#038;=&#038;\frac{1}{m}\sum_{i=1}^{i}\({z}^i-y^i\)^2\\&#038;=&#038;\frac{1}{m}\sum_{i=1}^{m}\(\mathbf{w^T}\mathbf{x}^i+b -y^i\)^2\end{array}" alt="">



<p class="wp-block-paragraph">Goal is to find the parameters <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{w}" alt=""> and <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?b" alt=""> which <strong>minimizes</strong> the metric <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?L" alt="">. This can be considered as <strong>ordinary least squares</strong> (<sup><a href="https://en.wikipedia.org/wiki/Ordinary_least_squares" target="_blank" rel="noopener">wiki entry on ordinary least squares</a></sup>) model.</p>



<p class="wp-block-paragraph">To find the value of parameters <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{w}" alt=""> and <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?b" alt=""> which <strong>minimises</strong> the metric <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?L" alt="">, let us try <strong>gradient descent </strong>method where we </p>



<p class="wp-block-paragraph">i) start with <strong>initial random</strong> values of parameters and </p>



<p class="wp-block-paragraph">ii) <strong>repeatedly update </strong>parameters simultaneously for all values of <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{w}" alt=""> and <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?b" alt=""></p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\textbf{till convergence:} \quad 
\begin{cases}
\mathbf{w} := \mathbf{w} - \alpha \dfrac{\partial L}{\partial \mathbf{w}} \\
b := b - \alpha \dfrac{\partial L}{\partial b}
\end{cases}
" alt="">



<p class="wp-block-paragraph">where,</p>



<p class="wp-block-paragraph"><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\alpha" alt=""> is the learning rate, </p>



<p class="wp-block-paragraph"><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial L}{\partial \mathbf{w}" alt=""> and <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{\partial L}{\partial b" alt=""> are the partial derivatives of the loss metric <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?L" alt=""> over parameters <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{w}" alt=""> and <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?b" alt=""> respectively.</p>



<p class="wp-block-paragraph">The intuition is, <em>to take repeated steps in the <strong>opposite direction</strong> of the&nbsp;<a href="https://en.wikipedia.org/wiki/Gradient" target="_blank" rel="noopener">gradient</a>&nbsp;(or approximate gradient) of the function at the current point, because this is the direction of <strong>steepest descent</strong></em> <sup><a href="https://en.wikipedia.org/wiki/Gradient_descent" target="_blank" rel="noopener">Wiki Article on gradient descent</a></sup>.</p>



<h3 class="wp-block-heading">Gradients</h3>



<p class="wp-block-paragraph">In this formulation, we need to find the derivative of a scalar i.e. loss <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?L" alt=""> over the a vector of <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?n+1" alt=""> parameters of <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{w}" alt=""> and <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?b" alt="">. </p>



<p class="wp-block-paragraph">For easier understanding, can define the derivative over each parameter as below,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lcl}w_1&#038;:=&#038;w_1-\alpha\frac{\partial%20L}{\partial%20w_1}\\w_2&#038;:=&#038;w_2-\alpha\frac{\partial%20L}{\partial%20w_2}\\&#038;\vdots&#038;\\w_n&#038;:=&#038;w_n-\alpha\frac{\partial%20L}{\partial%20w_n}\\b&#038;:=&#038;b-\alpha\frac{\partial%20L}{\partial%20b}\end{array}" alt="">



<p class="wp-block-paragraph">Further, taking only one training example, the loss is</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}L&#038;=&#038;(\mathbf{w^T}\mathbf{x^1}+b -y^1\)^2\\&#038;=&#038;(w_1x_1^1 + w_2x_2_^1 + \dots + w_nx_n^1 + b - y^1)^2\\&#038;=&#038;(z^1-y^1)^2\end{array}" alt="">



<p class="wp-block-paragraph">Taking the derivative w.r.t to first parameter <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?w_1" alt=""></p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}\frac{\partial%20L}{\partial%20w_1}&#038;=&#038;\frac{\partial%20}{\partial%20w_1}(w_1{x_1}^1%20+%20w_2{x_2}_^1%20+%20\dots%20+%20w_n{x_n}^1%20+%20b%20-%20y^1)^2\\&#038;=&#038;2(w_1{x_1}^1%20+%20w_2{x_2}_^1%20+%20\dots%20+%20w_n{x_n}^1%20+%20b%20-%20y^1)\frac{\partial}{\partial%20w_1}(w_1{x_1}^1%20+%20w_2{x_2}_^1%20+%20\dots%20+%20w_n{x_n}^1%20+%20b%20-%20y^1)\\&#038;=&#038;2(w_1{x_1}^1%20+%20w_2{x_2}_^1%20+%20\dots%20+%20w_n{x_n}^1%20+%20b%20-%20y^1){x_1}^1\\&#038;=&#038;2(\mathbf{w^T}\mathbf{x^1}+b-y^1){x_1}^1\\&#038;=&#038;2(z^1-{y^1}){x_1}^1\end{array}" alt="">



<p class="wp-block-paragraph">Similarly, for the <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?n^{th}" alt=""> parameter of <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{w}" alt="">, the gradient is</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}\frac{\partial%20L}{\partial%20w_n}&#038;=&#038;2(\mathbf{w^T}\mathbf{x^1}+b-y^1){x_n}^1=&#038;2(z^1-y^1){x_n}^1\end{array}" alt="">



<p class="wp-block-paragraph">For the bias parameter <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?b" alt="">, the gradient is</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}\frac{\partial%20L}{\partial%20b}&#038;=&#038;2(\mathbf{w^T}\mathbf{x^1}+b-y^1)=2(z^1-y^1)\end{array}" alt="">



<p class="wp-block-paragraph">The intuition from above equations is : </p>



<p class="wp-block-paragraph">if the <strong>estimate <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?{z}=\mathbf{w^T}\mathbf{x}+b" alt=""> is close to the true value <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?y" alt=""></strong> then the gradient is <strong>small</strong>, and the update to the parameters is also correspondingly <strong>smaller</strong>.</p>



<p class="wp-block-paragraph">With <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?m" alt=""> training examples the loss is averaged, and this becomes :</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}\frac{\partial%20L}{\partial%20w_n}&#038;=&#038;\frac{2}{m}\sum_{i=1}^m(\mathbf{w^T}\mathbf{x^i}+b-y^i){x_n}^i&#038;=&#038;\frac{2}{m}\sum_{i=1}^m\(z^i-y^i\){x_n}^i\end{array}" alt="">



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}\frac{\partial%20L}{\partial%20b}&#038;=&#038;\frac{2}{m}\sum_{i=1}^m(\mathbf{w^T}\mathbf{x^i}+b-y^i)&#038;=&#038;\frac{2}{m}\sum_{i=1}^m\(z^i-y^i\)\end{array}" alt="">



<h3 class="wp-block-heading">Vectorised operations</h3>



<p class="wp-block-paragraph">Vectorised operations allow CPUs/GPUs to do SIMD (Single Instruction Multiple Data<sup><a href="https://en.wikipedia.org/wiki/Single_instruction,_multiple_data" target="_blank" rel="noopener">(Refer Wiki)</a></sup>) processing, making it much faster than using for-loops.</p>



<h4 class="wp-block-heading">Inputs &amp; Outputs</h4>



<p class="wp-block-paragraph">In the current example, this translates to the parameters <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{w}" alt="">  and <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?b" alt=""> represented as, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{w} = \begin{bmatrix} w_1 \\ w_2 \\ \vdots \\ w_n \end{bmatrix}, \quad \mathbf{w} \in \mathbb{R}^{n \times 1}
" alt="">



<p class="wp-block-paragraph"><img decoding="async" style="font-size: revert; color: initial;" src="https://dsplog.com/cgi-bin/mimetex.cgi?b\in \mathbb{R}^{1 \times 1}
" alt=""></p>



<p class="wp-block-paragraph">respectively. </p>



<p class="wp-block-paragraph">The <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?m" alt="">training examples of  <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?n" alt=""> features is represented as </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{X} = \begin{bmatrix}
x_{1}^1 &#038; x_{1}^2 &#038; \dots &#038; x_{1}^m \\
x_{2}^1 &#038; x_{2}^2 &#038; \dots &#038; x_{2}^m \\
\vdots &#038; \vdots &#038; \ddots &#038; \vdots \\
x_{n}^1 &#038; x_{n}^2 &#038; \dots &#038; x_{n}^m
\end{bmatrix}, \quad \mathbf{X} \in \mathbb{R}^{n \times m}
" alt="">



<p class="wp-block-paragraph"></p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{y} = \begin{bmatrix}
y^1 &#038; y^2 &#038; \dots &#038; y^m \end{bmatrix}, \quad \mathbf{y} \in \mathbb{R}^{1 \times m}
" alt="">



<p class="wp-block-paragraph">The output</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}\mathbf{z}&#038; = &#038; \quad \mathbf{w^T}\mathbf{X} +b \\&#038;=&#038;\begin{bmatrix}
z^1 &#038; z^2 &#038; \dots &#038; z^m \end{bmatrix}, \quad \mathbf{z} \in \mathbb{R}^{1 \times m}\end{array}
" alt="">



<p class="wp-block-paragraph"><br></p>



<h4 class="wp-block-heading">Gradients</h4>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?d\mathbf{w} = \begin{bmatrix}
\frac{\partial \mathbf{L}}{\partial w_1} \\ \frac{\partial \mathbf{L}}{\partial w_2} \\ \vdots \\ \frac{\partial \mathbf{L}}{\partial w_n} \end{bmatrix}, \quad d\mathbf{w} \in \mathbb{R}^{n \times 1}
" alt="">



<p class="wp-block-paragraph"><br>The gradient w.r.t to <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{w}" alt=""> can be represented in matrix operations as,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}d\mathbf{w} &#038;=&#038; \frac{2}{m}\begin{bmatrix}
x_{1}^1 &#038; x_{1}^2 &#038; \dots &#038; x_{1}^m \\
x_{2}^1 &#038; x_{2}^2 &#038; \dots &#038; x_{2}^m \\
\vdots &#038; \vdots &#038; \ddots &#038; \vdots \\
x_{n}^1 &#038; x_{n}^2 &#038; \dots &#038; x_{n}^m
\end{bmatrix}\begin{bmatrix}z^1-y^1\\z^2-y^2\\\vdots\\z^m-y^m\end{bmatrix}\\
&#038;=&#038;\frac{2}{m}\mathbf{X}(\mathbf{z}-\mathbf{y})^T\end{array}
" alt="">



<p class="wp-block-paragraph"><br></p>



<p class="wp-block-paragraph">Similarly, for the bias term</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}\frac{\partial L}{\partial b}=d\mathbf{b} &#038;=&#038; \frac{2}{m}\underbrac{\begin{bmatrix}
1 &#038; 1 &#038; \dots &#038; 1 \\
\end{bmatrix}}_{1\times m}\begin{bmatrix}z^1-y^1\\z^2-y^2\\\vdots\\z^m-y^m\end{bmatrix}\\
&#038;=&#038;\frac{2}{m}\sum_i^m(z^i-y^i)\end{array}
" alt="">



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph"></p>



<h3 class="wp-block-heading">Training </h3>



<h4 class="wp-block-heading">Training loop &#8211; using the derivatives</h4>



<p class="wp-block-paragraph">The code for linear regression using the gradients descent defined in the previous section. </p>



<iframe loading="lazy" src="https://nbviewer.org/github/dsplog/dsplog.com/blob/main/code/linear_regression/linear_regression.ipynb?flush_cache=false" width="100%" height="600"></iframe>



<h4 class="wp-block-heading">Computing Gradients </h4>



<h5 class="wp-block-heading">Using PyTorch</h5>



<p class="wp-block-paragraph">For the simple linear regression example, it is relatively straight forward to derive the gradients and perform the training loop. When the function for estimation involves multiple stages/layers a.k.a <strong>deep learning</strong><sup> <a href="https://en.wikipedia.org/wiki/Deep_learning" target="_blank" rel="noopener">(refer wiki)</a></sup>, it becomes harder to derive the gradients.</p>



<p class="wp-block-paragraph">Popular deep learning frameworks like <a href="https://pytorch.org/" target="_blank" rel="noopener">Pytorch</a> provides tools for automatic differentiation ( <code>torch.autograd</code> <sup><a href="https://pytorch.org/tutorials/beginner/basics/autogradqs_tutorial.html" target="_blank" rel="noopener">refer pytorch entry on autograd</a> </sup>) to find the gradients of each parameter based on the loss function. </p>



<h5 class="wp-block-heading">Numerical approximation (finite difference method)</h5>



<p class="wp-block-paragraph">To verify the gradients, derivatives can be computed numerically using using finite difference<sup> <a href="https://en.wikipedia.org/wiki/Finite_difference" target="_blank" rel="noopener">(refer wiki entry  on finite difference)</a></sup> method i.e. </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?f'(x) = \lim_{\varepsilon \to 0} \displaystyle \frac{f(x+\varepsilon) - f(x - \varepsilon)}{2\varepsilon}
" alt="">



<p class="wp-block-paragraph">where, </p>



<p class="wp-block-paragraph"><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?f'(x)" alt=""> is the true derivative of function  <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?f(x)" alt=""> and </p>



<p class="wp-block-paragraph"><img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\varepsilon" alt=""> is a small constant.</p>



<h5 class="wp-block-heading">Example &#8211; Analytic vs PyTorch vs Numerical Approximation</h5>



<p class="wp-block-paragraph">For the toy example below, can see that the gradients computed by Analytically vs PyTorch vs numerical approximation using finite difference methods are matching. </p>



<iframe loading="lazy" src="https://nbviewer.org/github/dsplog/dsplog.com/blob/main/code/linear_regression/gradients_analytic_vs_finite_difference_vs_pytorch.ipynb?flush_cache=false" width="100%" height="600"></iframe>



<p class="wp-block-paragraph"></p>



<h4 class="wp-block-heading">Training Loop &#8211; using PyTorch</h4>



<p class="wp-block-paragraph">Key aspects in the code for implementing the training loop using PyTorch :</p>



<ul class="wp-block-list">
<li>the variables are defined as torch tensors <a href="https://pytorch.org/tutorials/beginner/basics/tensorqs_tutorial.html" target="_blank" rel="noopener"><sup>refer pytorch article on tensors</sup></a>. 
<ul class="wp-block-list">
<li>Tensors are similar to numpy ndarrays, with capabilities to use GPU/hardware accelerators, optimized for automatic differentiation etc</li>
</ul>
</li>



<li>defining the parameters needing gradient computation. 
<ul class="wp-block-list">
<li>the parameters <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{w}" alt=""> and <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?b" alt=""> which needs gradient computation are initialised with <code>requires_grad=True</code></li>
</ul>
</li>



<li>computing the gradient
<ul class="wp-block-list">
<li>the call <code>loss.backward()</code> is used to compute the gradients for the parameters <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{w}" alt=""> and <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?b" alt="">. </li>



<li>this makes the gradient values available in <code>w.grad()</code>  and <code>b.grad()</code> respectively</li>
</ul>
</li>



<li>updating the paramaeters
<ul class="wp-block-list">
<li>as gradient tracking is unnecessary during parameter updates, they are performed within <code>torch.no_grad():</code> context</li>
</ul>
</li>



<li>zeroing gradients between calls 
<ul class="wp-block-list">
<li>PyTorch accumulates gradients by default during each backward pass i.e. each <code>loss.backward()</code> call</li>



<li>so, performing <code>w.grad.zero_()</code> and <code>b.grad.zero_()</code> is needed to clear previous gradients. </li>
</ul>
</li>
</ul>



<p class="wp-block-paragraph"></p>



<iframe loading="lazy" src="https://nbviewer.org/github/dsplog/dsplog.com/blob/main/code/linear_regression/linear_regression_pytorch.ipynb?flush_cache=false" width="100%" height="600"></iframe>



<p class="wp-block-paragraph">As would expect, both the training loop approaches converges to similar values for parameters  <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{w}" alt=""> and <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?b" alt="">. </p>



<h2 class="wp-block-heading">Mean Absolute Error</h2>



<p class="wp-block-paragraph">Another popular metric to quantify the &#8220;<strong>closeness</strong>&#8221; of the estimate <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?{z}" alt=""> to the true value <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?y" alt=""> is <strong>Mean Absolute Error</strong> (MAE). In the cases where there are outliers in the data, <strong>Mean Absolute Error (MAE)</strong> is preferred over <strong>Mean Squared Error (MSE)</strong> as <strong>MAE</strong> penalizes errors linearly rather than quadratically.<br><br>Formally,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
\begin{array}{lll}
L_{\text{mae}} &#038;=&#038; \frac{1}{m} \sum_{i=1}^{m} \left| z^i - y^i \right| \\
               &#038;=&#038; \frac{1}{m} \sum_{i=1}^{m} \left| \mathbf{w}^T \mathbf{x}^i + b - y^i \right|
\end{array}
" alt="">



<p class="wp-block-paragraph">For computing the gradient for the loss from <strong>Mean Absolute Error,</strong> need to find the gradient of <strong>absolute</strong> function.</p>



<h3 class="wp-block-heading">Gradient &#8211; Absolute function</h3>



<p class="wp-block-paragraph">The absolute value of function is defined as, </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?
|x|%20=%20\begin{cases}%20x,%20&#038;%20\text{if%20}%20x%20\geq%200%20\\%20-x,%20&#038;%20\text{if%20}%20x%20%3C%200%20\end{cases}
" alt="">



<p class="wp-block-paragraph">The derivative is </p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{d}{dx}|x|=\begin{cases}
+1&#038;\text{if}x\gt0\\
-1&#038;\text{if}x\lt0\\
\text{undefined}&#038;\text{if}x=0
\end{cases}
" alt="">



<p class="wp-block-paragraph">This can be compactly written as,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\frac{d}{dx}|x| = \mathrm{sign}(x), \quad \text{for } x \ne 0
" alt="">



<p class="wp-block-paragraph">The absolute function is non-differentiable at point at <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?x=0" alt="">, where the function has a <strong>sharp corner</strong>.</p>



<p class="wp-block-paragraph">The concept of<em> <strong>subderivative</strong> (or <strong>subgradient</strong>) </em>generalises the <em>derivative to a convex functions which are not differentiable</em> <sup><a href="https://en.wikipedia.org/wiki/Subderivative" target="_blank" rel="noopener">(refer wiki entry on Subderivative)</a> </sup>. With this definition, subderivative at <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?x=0" alt=""> lies in the interval <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?[ -1, 1] " alt=""> .</p>



<p class="wp-block-paragraph">Using the concept of <strong>Symmetric derivative</strong> <a href="https://en.wikipedia.org/wiki/Symmetric_derivative#The_absolute_value_function" target="_blank" rel="noopener"><sup>(refer wiki entry on symmetric derivative)</sup></a>, the subderivtive at <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?x=0" alt=""> can be chosen as <strong>0</strong>.</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{llll}f_s(0) &#038;= \lim_{h \to 0} \frac{f(0 + h) - f(0 - h)}{2h} = \lim_{h \to 0} \frac{f(h) - f(-h)}{2h} \\
&#038;= \lim_{h \to 0} \frac{|h| - |-h|}{2h} \\
&#038;= \lim_{h \to 0} \frac{|h| - |h|}{2h} \\
&#038;= \lim_{h \to 0} \frac{0}{2h} = 0.
\end{array}
" alt="">



<p class="wp-block-paragraph">In practice, deep learning frameworks (like PyTorch, TensorFlow) and numerical methods like NumPy define <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\text{sign}(0) = 0" alt="">. This is the <strong>subgradient</strong>, and it works fine in optimization.</p>



<iframe loading="lazy" src="https://nbviewer.org/github/dsplog/dsplog.com/blob/main/code/linear_regression/gradients_absolute_function.ipynb?flush_cache=false" width="100%" height="600"></iframe>



<h3 class="wp-block-heading">Training  </h3>



<h4 class="wp-block-heading">Deriving the Gradients </h4>



<p class="wp-block-paragraph">For a single training example, for the <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?n^{th}" alt=""> parameter of <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{w}" alt="">, the gradient is</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}\frac{\partial%20L}{\partial%20w_n}&#038;=&#038;\frac{\partial%20}{\partial%20w_n}|w_1{x_1}^1%20+%20w_2{x_2}_^1%20+%20\dots%20+%20w_n{x_n}^1%20+%20b%20-%20y^1|\\&#038;=&#038;\mathrm{sign}(w_1{x_1}^1%20+%20w_2{x_2}_^1%20+%20\dots%20+%20w_n{x_n}^1%20+%20b%20-%20y^1)\frac{\partial%20L}{\partial%20w_n}(w_1{x_1}^1%20+%20w_2{x_2}_^1%20+%20\dots%20+%20w_n{x_n}^1%20+%20b%20-%20y^1)\\&#038;=&#038;\mathrm{sign}(w_1{x_1}^1%20+%20w_2{x_2}_^1%20+%20\dots%20+%20w_n{x_n}^1%20+%20b%20-%20y^1){x_n}^1\\&#038;=&#038;\mathrm{sign}(\mathbf{w^T}\mathbf{x^1}+b-y^1){x_n}^1\\&#038;=&#038;\mathrm{sign}(z^1-{y^1}){x_n}^1\end{array}" alt="">



<p class="wp-block-paragraph">Similarly for the bias term,</p>



<img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\begin{array}{lll}\frac{\partial%20L}{\partial%20b}&#038;=&#038;\mathrm{sign}(\mathbf{w^T}\mathbf{x^1}+b-y^1)=\mathrm{sign}(z^1-y^1)\end{array}" alt="">



<h4 class="wp-block-heading">Training Loop &#8211; using derivatives and PyTorch</h4>



<p class="wp-block-paragraph">For the same example, the code for training the linear regression using <strong>Mean Absolute Error </strong>as the <strong>Loss function</strong>.</p>



<iframe loading="lazy" src="https://nbviewer.org/github/dsplog/dsplog.com/blob/main/code/linear_regression/linear_regression_mean_abs_error.ipynb?flush_cache=false" width="100%" height="600"></iframe>



<p class="wp-block-paragraph">Can see that both the training loops for <strong>Mean Absolute Error (MAE)</strong> using <strong>PyTorch</strong> and Analaytic approaches converges to the same parameters <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?\mathbf{w}" alt=""> and <img decoding="async" src="https://dsplog.com/cgi-bin/mimetex.cgi?b" alt="">. </p>



<h2 class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">The post covers the following key aspects </p>



<ul class="wp-block-list">
<li><strong>Gradient Basics:</strong> How to deriving the gradients for loss functions Mean Square Error and Mean Absolute Error</li>



<li><strong>Efficient Computation:</strong> Use of vectorized operations and PyTorch autograd</li>



<li><strong>Gradient Computation:</strong> Analytical, numerical (finite difference), and PyTorch comparison</li>



<li><strong>Training Loops:</strong> Implementing updates using both manual and PyTorch-based gradients</li>
</ul>



<p class="wp-block-paragraph">Have any questions or feedback on the gradient computation techniques? Feel free to drop your feedback in the comments section. <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /> </p>
<p>The post <a rel="nofollow" href="https://dsplog.com/2025/05/01/gradients-for-linear-regression/">Gradients for linear regression</a> appeared first on <a rel="nofollow" href="https://dsplog.com">DSP LOG</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://dsplog.com/2025/05/01/gradients-for-linear-regression/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Migrated to Amazon EC2 instance (from shared hosting)</title>
		<link>https://dsplog.com/2013/03/11/migrated-to-amazon-ec2-from-shared-hosting/</link>
					<comments>https://dsplog.com/2013/03/11/migrated-to-amazon-ec2-from-shared-hosting/#respond</comments>
		
		<dc:creator><![CDATA[Krishna Sankar]]></dc:creator>
		<pubDate>Mon, 11 Mar 2013 01:20:38 +0000</pubDate>
				<category><![CDATA[News]]></category>
		<category><![CDATA[amazon]]></category>
		<category><![CDATA[ec2]]></category>
		<guid isPermaLink="false">http://www.dsplog.com/?p=1961</guid>

					<description><![CDATA[<p>Being not too happy with the speed of the shared hosting, decided to move the blog to an Amazon Elastic Compute Cloud (Amazon EC2) instance.  Given this is a baby step, picked up a micro instance running an Ubuntu server and installed Apache web server, MySQL, PHP . After doing a bit of tweaking with this new &#8230; <a href="https://dsplog.com/2013/03/11/migrated-to-amazon-ec2-from-shared-hosting/" class="more-link">Continue reading<span class="screen-reader-text"> "Migrated to Amazon EC2 instance (from shared hosting)"</span></a></p>
<p>The post <a rel="nofollow" href="https://dsplog.com/2013/03/11/migrated-to-amazon-ec2-from-shared-hosting/">Migrated to Amazon EC2 instance (from shared hosting)</a> appeared first on <a rel="nofollow" href="https://dsplog.com">DSP LOG</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Being not too happy with the speed of the shared hosting, decided to move the blog to an <a title="Amazon Elastic Compute Cloud" href="http://aws.amazon.com/ec2/" target="_blank" rel="noopener">Amazon Elastic Compute Cloud (Amazon EC2)</a> instance.  Given this is a baby step, picked up a micro instance running an Ubuntu server and installed <a title="Apache web server" href="http://en.wikipedia.org/wiki/Apache_HTTP_Server" target="_blank" rel="noopener">Apache web server</a>, <a title="wiki entry on MySQL" href="http://en.wikipedia.org/wiki/MySQL" target="_blank" rel="noopener">MySQL</a>, <a title="wiki entry on PHP" href="http://en.wikipedia.org/wiki/PHP" target="_blank" rel="noopener">PHP</a> . After doing a bit of tweaking with this new instance, imported the SQL database and other files from the shared hosting and pointed the A name record to the new IP address. This switch happened over this weekend.</p>
<p>One particular issue which I faced was frequent crashing of MySQL due to memory limitations. Followed few online instructions to improve the situation and the current configuration seems to be holding up (but this is a cause of worry &#8211; need to figure the right solution).</p>
<p>Anyhow, hope you like the decreased page load time! <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p><strong>Some helpful links from the web:</strong></p>
<p><strong></strong>a) <a title="How to install WordPress on Amazon EC2" href="http://iampuneet.com/wordpress-amazon-ec2/" target="_blank" rel="noopener">How to install WordPress on Amazone EC2</a></p>
<p>b) <a title="Move WordPress site from shared hosting to Amazon EC2" href="http://blog.lopau.com/move-wordpress-site-from-shared-hosting-to-amazon-ec2/" target="_blank" rel="noopener">Move WordPress site from shared hosting to Amazon EC2</a></p>
<p>c) <a title="DIY: Enable CGI on your Apache server" href="http://www.techrepublic.com/blog/doityourself-it-guy/diy-enable-cgi-on-your-apache-server/1066" target="_blank" rel="noopener">DIY: Enable CGI on your Apache server</a></p>
<p>d) <a title="Import MySQL Dumpfile, SQL Datafile Into My Database" href="http://www.cyberciti.biz/faq/import-mysql-dumpfile-sql-datafile-into-my-database/" target="_blank" rel="noopener">Import MySQL Dumpfile, SQL Datafile Into My Database</a></p>
<p>e) <a title="Making WordPress Stable on EC2-Micro" href="http://www.frameloss.org/2011/11/04/making-wordpress-stable-on-ec2-micro/" target="_blank" rel="noopener">Making WordPress Stable on EC2-Micro</a></p>
<p>f) <a title="http://www.lavluda.com/2007/07/15/how-to-enable-mod_rewrite-in-apache22-debian/" href="how to enable mod_rewrite in apache2.2 (debian/ubuntu)" target="_blank">how to enable mod_rewrite in apache2.2 (debian/ubuntu)</a></p>
<p>The post <a rel="nofollow" href="https://dsplog.com/2013/03/11/migrated-to-amazon-ec2-from-shared-hosting/">Migrated to Amazon EC2 instance (from shared hosting)</a> appeared first on <a rel="nofollow" href="https://dsplog.com">DSP LOG</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://dsplog.com/2013/03/11/migrated-to-amazon-ec2-from-shared-hosting/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
