<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Transformer on XEDCZQ Blog</title><link>https://xedczq.cn/en/tags/transformer/</link><description>Recent content in Transformer on XEDCZQ Blog</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Fri, 05 Jun 2026 23:10:00 +0800</lastBuildDate><atom:link href="https://xedczq.cn/en/tags/transformer/index.xml" rel="self" type="application/rss+xml"/><item><title>Transformer 20-Step Visual Study Notes</title><link>https://xedczq.cn/en/post/transformerexplainer/</link><pubDate>Fri, 05 Jun 2026 23:10:00 +0800</pubDate><guid>https://xedczq.cn/en/post/transformerexplainer/</guid><description>&lt;img src="https://xedczq.cn/img/transformer-explainer/steps/step-03.jpg" alt="Featured image of post Transformer 20-Step Visual Study Notes" /&gt;&lt;h1 id="transformer-20-step-visual-study-notes"&gt;&lt;a href="#transformer-20-step-visual-study-notes" class="header-anchor"&gt;&lt;/a&gt;Transformer 20-Step Visual Study Notes
&lt;/h1&gt;&lt;p&gt;This note is based on the interactive explanation from &lt;a class="link" href="https://poloclub.github.io/transformer-explainer/" target="_blank" rel="noopener"
 &gt;Transformer Explainer&lt;/a&gt;. It follows the site&amp;rsquo;s 20 steps and organizes them into a study note for understanding how GPT-style Transformers perform next-token prediction. The site uses GPT-2 small as the example model and visualizes the full pipeline from input tokens to output probabilities.&lt;/p&gt;
&lt;p&gt;First, remember one sentence: &lt;strong&gt;the core task of GPT-style Transformers is next-token prediction&lt;/strong&gt;. Given the prompt:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Data visualization empowers users to
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The model needs to answer:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;What is the most likely next token?
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To answer this, a Transformer goes through tokenization, embedding, positional encoding, repeated Transformer blocks, self-attention, MLP, logits, probability distribution, sampling strategy, and other steps.&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;All screenshots in this note are taken from &lt;a class="link" href="https://poloclub.github.io/transformer-explainer/" target="_blank" rel="noopener"
 &gt;Transformer Explainer&lt;/a&gt;, developed by the Georgia Tech Polo Club team. They are used here for personal study notes. It is best to read this together with the original interactive site.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="what-is-transformer"&gt;&lt;a href="#what-is-transformer" class="header-anchor"&gt;&lt;/a&gt;What Is Transformer
&lt;/h2&gt;&lt;p&gt;Transformer is the most common foundation architecture for modern large language models. Text-generation models such as GPT, Llama, and Gemini can all be understood as expanded versions of the Transformer architecture.&lt;/p&gt;
&lt;p&gt;Its most important ability is not &amp;ldquo;memorizing answers&amp;rdquo;, but learning language patterns from large amounts of text and then predicting the next token from context at inference time. This prediction is repeated: predict one token, append it to the text, then predict the next one.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Step 1: What is Transformer" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://xedczq.cn/img/transformer-explainer/steps/step-01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Source: Transformer Explainer, &lt;a class="link" href="https://poloclub.github.io/transformer-explainer/" target="_blank" rel="noopener"
 &gt;https://poloclub.github.io/transformer-explainer/&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="how-transformers-work"&gt;&lt;a href="#how-transformers-work" class="header-anchor"&gt;&lt;/a&gt;How Transformers Work
&lt;/h2&gt;&lt;p&gt;When a Transformer generates text, it does not write an entire paragraph at once. It generates step by step. Each step performs the same task: &lt;strong&gt;predict a probability distribution for the next token based on the existing context&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;For example, if the current input is:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Data visualization empowers users to
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The model may assign the highest probability to &lt;code&gt;visualize&lt;/code&gt;, while also assigning relatively high probabilities to tokens such as &lt;code&gt;create&lt;/code&gt;, &lt;code&gt;see&lt;/code&gt;, and &lt;code&gt;make&lt;/code&gt;. The final selected token is also affected by sampling parameters such as temperature, top-k, and top-p.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Step 2: How Transformers Work" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://xedczq.cn/img/transformer-explainer/steps/step-02.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Source: Transformer Explainer&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="transformer-architecture"&gt;&lt;a href="#transformer-architecture" class="header-anchor"&gt;&lt;/a&gt;Transformer Architecture
&lt;/h2&gt;&lt;p&gt;A text-generation Transformer can be divided into three major parts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Embedding&lt;/strong&gt;: converts human-readable text into vectors the model can process.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Transformer Blocks&lt;/strong&gt;: repeatedly refine each token representation, mainly through Self-Attention and MLP.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Output Probabilities&lt;/strong&gt;: converts the final vector into probabilities over all tokens in the vocabulary.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At a high level, the information flow is:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;text input -&amp;gt; token -&amp;gt; embedding -&amp;gt; Transformer Blocks -&amp;gt; logits -&amp;gt; probabilities -&amp;gt; sample next token
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img alt="Step 3: Transformer Architecture" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://xedczq.cn/img/transformer-explainer/steps/step-03.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Source: Transformer Explainer&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="embedding"&gt;&lt;a href="#embedding" class="header-anchor"&gt;&lt;/a&gt;Embedding
&lt;/h2&gt;&lt;p&gt;The model cannot directly understand strings. Embedding converts each token into a sequence of numbers, or a vector. This vector is not manually designed; it is learned during training.&lt;/p&gt;
&lt;p&gt;If two tokens often appear in similar contexts, their embeddings tend to be closer in high-dimensional space. You can think of embedding as an internal &amp;ldquo;semantic coordinate&amp;rdquo; used by the model.&lt;/p&gt;
&lt;p&gt;GPT-2 small has a hidden dimension of 768, so each token is represented as a 768-dimensional vector.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Step 4: Embedding" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://xedczq.cn/img/transformer-explainer/steps/step-04.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Source: Transformer Explainer&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="token-embedding"&gt;&lt;a href="#token-embedding" class="header-anchor"&gt;&lt;/a&gt;Token Embedding
&lt;/h2&gt;&lt;p&gt;Tokenization splits input text into tokens. A token can be a full word or a subword. For example, &lt;code&gt;empowers&lt;/code&gt; in the example is split into &lt;code&gt;em&lt;/code&gt; and &lt;code&gt;powers&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Each token has a unique ID. GPT-2 has a vocabulary size of 50,257, so its token embedding matrix is roughly:&lt;/p&gt;
$$
50257 \times 768
$$&lt;p&gt;After the model gets the token ID, it looks up the corresponding 768-dimensional vector from this large matrix.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Step 5: Token Embedding" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://xedczq.cn/img/transformer-explainer/steps/step-05.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Source: Transformer Explainer&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="positional-encoding"&gt;&lt;a href="#positional-encoding" class="header-anchor"&gt;&lt;/a&gt;Positional Encoding
&lt;/h2&gt;&lt;p&gt;Self-Attention does not naturally know sequence order. If the model only receives a set of token vectors, it does not know which token comes first and which comes later.&lt;/p&gt;
&lt;p&gt;So positional encoding is needed. GPT-2 uses learnable positional embeddings and adds the semantic token vector and the position vector:&lt;/p&gt;
$$
x_i = \text{TokenEmbedding}_i + \text{PositionEmbedding}_i
$$&lt;p&gt;This lets the model know both &amp;ldquo;what this token is&amp;rdquo; and &amp;ldquo;where it is.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Step 6: Positional Encoding" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://xedczq.cn/img/transformer-explainer/steps/step-06.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Source: Transformer Explainer&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="repetitive-transformer-blocks"&gt;&lt;a href="#repetitive-transformer-blocks" class="header-anchor"&gt;&lt;/a&gt;Repetitive Transformer Blocks
&lt;/h2&gt;&lt;p&gt;Embedding is only the input representation, not a fully contextualized semantic representation. The real context modeling happens inside Transformer Blocks.&lt;/p&gt;
&lt;p&gt;GPT-2 small has 12 Transformer Blocks. Each block roughly contains:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Multi-Head Self-Attention: lets tokens exchange information.&lt;/li&gt;
&lt;li&gt;MLP: nonlinearly processes each token representation.&lt;/li&gt;
&lt;li&gt;Residual, LayerNorm, and Dropout: stabilize training and improve generalization.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The meaning of stacking multiple layers is that lower layers tend to capture local and lexical information, while higher layers more easily form complex semantic and task-related representations.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Step 7: Repetitive Transformer Blocks" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://xedczq.cn/img/transformer-explainer/steps/step-07.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Source: Transformer Explainer&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="multi-head-self-attention"&gt;&lt;a href="#multi-head-self-attention" class="header-anchor"&gt;&lt;/a&gt;Multi-Head Self Attention
&lt;/h2&gt;&lt;p&gt;The goal of Self-Attention is to let each token update itself based on context. For example, the token &lt;code&gt;to&lt;/code&gt; has different meanings in different sentences. It needs to &amp;ldquo;look at&amp;rdquo; the previous context &lt;code&gt;Data visualization empowers users&lt;/code&gt; to form a more accurate representation.&lt;/p&gt;
&lt;p&gt;Multi-Head means the model does not use just one attention perspective. It uses multiple heads in parallel. GPT-2 small has 12 attention heads. Different heads can learn different relationships, such as syntactic relations, short-distance collocations, and long-distance semantic dependencies.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Step 8: Multi-Head Self Attention" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://xedczq.cn/img/transformer-explainer/steps/step-08.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Source: Transformer Explainer&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="query-key-value"&gt;&lt;a href="#query-key-value" class="header-anchor"&gt;&lt;/a&gt;Query, Key, Value
&lt;/h2&gt;&lt;p&gt;Self-Attention maps each token&amp;rsquo;s input vector into three vectors:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Query (Q)&lt;/strong&gt;: what information the current token wants to search for.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Key (K)&lt;/strong&gt;: features by which each token can be matched by others.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Value (V)&lt;/strong&gt;: the actual information content to be aggregated and passed along.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;They come from linear transformations:&lt;/p&gt;
$$
Q = XW_Q,\quad K = XW_K,\quad V = XW_V
$$&lt;p&gt;A simple analogy is a search engine:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Query is the search query.&lt;/li&gt;
&lt;li&gt;Key is the page title or index.&lt;/li&gt;
&lt;li&gt;Value is the page content.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The model first computes relevance between Query and Key, then reads Value with weighted aggregation.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Step 9: Query, Key, Value" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://xedczq.cn/img/transformer-explainer/steps/step-09.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Source: Transformer Explainer&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="multi-head"&gt;&lt;a href="#multi-head" class="header-anchor"&gt;&lt;/a&gt;Multi-Head
&lt;/h2&gt;&lt;p&gt;GPT-2 small has an embedding dimension of 768 and 12 attention heads, so each head usually processes:&lt;/p&gt;
$$
768 / 12 = 64
$$&lt;p&gt;The benefit of multi-head attention is learning multiple relationships in parallel. One head may focus on adjacent words, another on subject-verb relationships, and another on more distant semantic hints.&lt;/p&gt;
&lt;p&gt;Multiple heads are not duplicate work; they give the model multiple &amp;ldquo;viewing angles.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Step 10: Multi-head" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://xedczq.cn/img/transformer-explainer/steps/step-10.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Source: Transformer Explainer&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="masked-self-attention"&gt;&lt;a href="#masked-self-attention" class="header-anchor"&gt;&lt;/a&gt;Masked Self Attention
&lt;/h2&gt;&lt;p&gt;GPT-style models generate text from left to right. When predicting the current position, they must not peek at future tokens, so causal mask, also called masked self-attention, is used.&lt;/p&gt;
&lt;p&gt;The core formula is:&lt;/p&gt;
$$
\text{Attention}(Q,K,V)=\text{softmax}\left(\frac{QK^T}{\sqrt{d_k}} + M\right)V
$$&lt;p&gt;Where:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$QK^T$: computes pairwise similarity between tokens.&lt;/li&gt;
&lt;li&gt;$\sqrt{d_k}$: scaling factor that prevents dot products from becoming too large and making softmax too sharp.&lt;/li&gt;
&lt;li&gt;$M$: mask matrix that sets future positions to $-\infty$.&lt;/li&gt;
&lt;li&gt;softmax: turns scores into probabilities.&lt;/li&gt;
&lt;li&gt;multiplying by $V$: aggregates information according to attention weights.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Step 11: Masked Self Attention" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://xedczq.cn/img/transformer-explainer/steps/step-11.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Source: Transformer Explainer&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="attention-output-and-concatenation"&gt;&lt;a href="#attention-output-and-concatenation" class="header-anchor"&gt;&lt;/a&gt;Attention Output and Concatenation
&lt;/h2&gt;&lt;p&gt;Each head outputs a context-enhanced token representation. Since GPT-2 small has 12 heads, it produces 12 sets of results.&lt;/p&gt;
&lt;p&gt;The model then concatenates the outputs from these heads and applies a linear projection back to the original hidden dimension 768:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;head_1, head_2, ..., head_12 -&amp;gt; concat -&amp;gt; linear projection
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The purpose is to let different heads extract information separately, then fuse those perspectives into one unified representation.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Step 12: Attention Output &amp; Concatenation" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://xedczq.cn/img/transformer-explainer/steps/step-12.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Source: Transformer Explainer&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="mlp"&gt;&lt;a href="#mlp" class="header-anchor"&gt;&lt;/a&gt;MLP
&lt;/h2&gt;&lt;p&gt;Attention handles information flow between tokens. MLP processes each token&amp;rsquo;s own representation nonlinearly.&lt;/p&gt;
&lt;p&gt;GPT-2&amp;rsquo;s MLP usually contains two linear transformations with GELU activation in between:&lt;/p&gt;
$$
\text{MLP}(x)=W_2\cdot \text{GELU}(W_1x+b_1)+b_2
$$&lt;p&gt;The first layer expands the dimension from 768 to 3072, and the second layer compresses it back to 768. Expanding the dimension lets the model represent more complex features in a higher-dimensional space.&lt;/p&gt;
&lt;p&gt;Note that MLP does not communicate across tokens like Attention. It processes each token independently.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Step 13: MLP" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://xedczq.cn/img/transformer-explainer/steps/step-13.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Source: Transformer Explainer&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="output-logit"&gt;&lt;a href="#output-logit" class="header-anchor"&gt;&lt;/a&gt;Output Logit
&lt;/h2&gt;&lt;p&gt;After all Transformer Blocks, the model takes the output vector at the last position and uses it to predict the next token.&lt;/p&gt;
&lt;p&gt;This vector goes through the final linear layer and is mapped to the vocabulary size:&lt;/p&gt;
$$
\text{logits}=h_{\text{last}}W_{\text{vocab}}+b
$$&lt;p&gt;GPT-2 has a vocabulary size of 50,257, so logits are a vector of length 50,257. Each number corresponds to the raw score of a candidate token.&lt;/p&gt;
&lt;p&gt;A logit is not a probability. It can be any real number and must go through softmax to become a probability distribution.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Step 14: Output Logit" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://xedczq.cn/img/transformer-explainer/steps/step-14.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Source: Transformer Explainer&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="probabilities"&gt;&lt;a href="#probabilities" class="header-anchor"&gt;&lt;/a&gt;Probabilities
&lt;/h2&gt;&lt;p&gt;Softmax converts logits into probabilities:&lt;/p&gt;
$$
p_i=\frac{e^{z_i}}{\sum_j e^{z_j}}
$$&lt;p&gt;After conversion:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Every token probability is between 0 and 1.&lt;/li&gt;
&lt;li&gt;The probabilities of all tokens sum to 1.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the figure, after the example input, the model considers tokens such as &lt;code&gt;visualize&lt;/code&gt;, &lt;code&gt;create&lt;/code&gt;, &lt;code&gt;see&lt;/code&gt;, and &lt;code&gt;make&lt;/code&gt; to be likely next tokens.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Step 15: Probabilities" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://xedczq.cn/img/transformer-explainer/steps/step-15.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Source: Transformer Explainer&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="temperature"&gt;&lt;a href="#temperature" class="header-anchor"&gt;&lt;/a&gt;Temperature
&lt;/h2&gt;&lt;p&gt;Temperature scales logits before softmax:&lt;/p&gt;
$$
p_i=\frac{\exp(z_i/T)}{\sum_j \exp(z_j/T)}
$$&lt;p&gt;Where $T$ is the temperature:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$T &amp;lt; 1$: the probability distribution becomes sharper. High-score tokens are more likely to be selected, and output is more stable.&lt;/li&gt;
&lt;li&gt;$T = 1$: logits are not additionally adjusted.&lt;/li&gt;
&lt;li&gt;$T &amp;gt; 1$: the probability distribution becomes flatter. Low-probability tokens have more chances to be selected, and output becomes more diverse.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In simple terms, lower temperature is more conservative, while higher temperature is more divergent.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Step 16: Temperature" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://xedczq.cn/img/transformer-explainer/steps/step-16.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Source: Transformer Explainer&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="sampling-strategy"&gt;&lt;a href="#sampling-strategy" class="header-anchor"&gt;&lt;/a&gt;Sampling Strategy
&lt;/h2&gt;&lt;p&gt;After obtaining a probability distribution, the model still needs to decide how to choose the next token. Common strategies include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Greedy Search&lt;/strong&gt;: always choose the highest-probability token. Stable, but can be rigid.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Top-k&lt;/strong&gt;: keep only the k highest-probability tokens, then sample from them.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Top-p&lt;/strong&gt;: keep the smallest token set whose cumulative probability reaches p. Also called nucleus sampling.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Top-k is more like a fixed candidate pool, while top-p is a dynamic candidate pool. In practice, temperature and top-k/top-p are often tuned together.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Step 17: Sampling Strategy" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://xedczq.cn/img/transformer-explainer/steps/step-17.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Source: Transformer Explainer&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="residual-connection"&gt;&lt;a href="#residual-connection" class="header-anchor"&gt;&lt;/a&gt;Residual Connection
&lt;/h2&gt;&lt;p&gt;A residual connection adds a layer&amp;rsquo;s input directly to its output:&lt;/p&gt;
$$
y = x + F(x)
$$&lt;p&gt;Its purpose is to preserve original information and make gradients pass through deep networks more easily. Without residual connections, training becomes harder as the model gets deeper, and information from early layers is more likely to be lost.&lt;/p&gt;
&lt;p&gt;In Transformers, residual connections usually surround both Attention and MLP.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Step 18: Residual Connection" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://xedczq.cn/img/transformer-explainer/steps/step-18.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Source: Transformer Explainer&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="layer-normalization"&gt;&lt;a href="#layer-normalization" class="header-anchor"&gt;&lt;/a&gt;Layer Normalization
&lt;/h2&gt;&lt;p&gt;Layer Normalization normalizes the values inside a token vector, making the mean and variance more stable:&lt;/p&gt;
$$
\text{LayerNorm}(x)=\gamma\frac{x-\mu}{\sqrt{\sigma^2+\epsilon}}+\beta
$$&lt;p&gt;It reduces training instability and makes the input distribution of each layer more controllable. GPT-2 uses a pre-norm style: LayerNorm is applied before entering Attention and MLP.&lt;/p&gt;
&lt;p&gt;Intuitively, LayerNorm is like adjusting the numerical scale to a more suitable range before each key computation.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Step 19: Layer Normalization" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://xedczq.cn/img/transformer-explainer/steps/step-19.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Source: Transformer Explainer&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="dropout"&gt;&lt;a href="#dropout" class="header-anchor"&gt;&lt;/a&gt;Dropout
&lt;/h2&gt;&lt;p&gt;Dropout is a regularization method used during training. It randomly sets part of the connections or activations to zero, preventing the model from over-relying on certain local features.&lt;/p&gt;
&lt;p&gt;The intuition is: during training, do not let the model follow the exact same path every time, forcing it to learn more robust representations.&lt;/p&gt;
&lt;p&gt;Important notes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dropout is mainly used during training.&lt;/li&gt;
&lt;li&gt;Dropout is disabled during inference.&lt;/li&gt;
&lt;li&gt;Many newer large models use less Dropout than early models because their training data is extremely large.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Step 20: Dropout" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://xedczq.cn/img/transformer-explainer/steps/step-20.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Source: Transformer Explainer&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="one-flowchart-summary"&gt;&lt;a href="#one-flowchart-summary" class="header-anchor"&gt;&lt;/a&gt;One Flowchart Summary
&lt;/h2&gt;&lt;p&gt;The inference flow of a GPT-style Transformer can be compressed into this chain:&lt;/p&gt;
&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart LR
 A["Input text"] --&gt; B["Tokenization"]
 B --&gt; C["Token Embedding"]
 C --&gt; D["Positional Encoding"]
 D --&gt; E["Transformer Block x N"]
 E --&gt; F["Multi-Head Self-Attention"]
 F --&gt; G["MLP"]
 G --&gt; H["Final Linear"]
 H --&gt; I["Logits"]
 I --&gt; J["Softmax Probabilities"]
 J --&gt; K["Temperature / Top-k / Top-p"]
 K --&gt; L["Sample next token"]&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id="key-differences-from-rnn"&gt;&lt;a href="#key-differences-from-rnn" class="header-anchor"&gt;&lt;/a&gt;Key Differences from RNN
&lt;/h2&gt;&lt;p&gt;Combining this with the previous RNN note, the difference can be understood like this:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Aspect&lt;/th&gt;
 &lt;th&gt;RNN&lt;/th&gt;
 &lt;th&gt;Transformer&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Information transfer&lt;/td&gt;
 &lt;td&gt;Passed step by step through hidden state&lt;/td&gt;
 &lt;td&gt;Self-Attention lets tokens directly read one another&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Parallelism&lt;/td&gt;
 &lt;td&gt;Strong time-step dependency, hard to parallelize&lt;/td&gt;
 &lt;td&gt;Tokens in the same layer can be computed in parallel&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Long-distance dependency&lt;/td&gt;
 &lt;td&gt;Long path, easy to decay&lt;/td&gt;
 &lt;td&gt;Any positions can directly connect&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Context representation&lt;/td&gt;
 &lt;td&gt;Compressed into hidden state&lt;/td&gt;
 &lt;td&gt;Keeps explicit token representations for the whole context&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Large-model training&lt;/td&gt;
 &lt;td&gt;Less efficient to scale&lt;/td&gt;
 &lt;td&gt;Better suited to large-scale GPU/TPU matrix computation&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;This is why modern LLMs mainly use Transformers: they are not only strong in modeling, but also better engineered for large-scale pretraining.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="sources"&gt;&lt;a href="#sources" class="header-anchor"&gt;&lt;/a&gt;Sources
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://poloclub.github.io/transformer-explainer/" target="_blank" rel="noopener"
 &gt;Transformer Explainer: LLM Transformer Model Visually Explained&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/poloclub/transformer-explainer" target="_blank" rel="noopener"
 &gt;Transformer Explainer GitHub Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://arxiv.org/abs/2408.04619" target="_blank" rel="noopener"
 &gt;Transformer Explainer Paper, arXiv:2408.04619&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Vaswani et al., &lt;a class="link" href="https://arxiv.org/abs/1706.03762" target="_blank" rel="noopener"
 &gt;Attention Is All You Need&lt;/a&gt;, 2017&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>RNN Recurrent Neural Network Study Notes</title><link>https://xedczq.cn/en/post/rnn/</link><pubDate>Thu, 04 Jun 2026 00:00:00 +0800</pubDate><guid>https://xedczq.cn/en/post/rnn/</guid><description>&lt;img src="https://xedczq.cn/img/rnn/diags.jpeg" alt="Featured image of post RNN Recurrent Neural Network Study Notes" /&gt;&lt;h1 id="rnn-recurrent-neural-network-study-notes"&gt;&lt;a href="#rnn-recurrent-neural-network-study-notes" class="header-anchor"&gt;&lt;/a&gt;RNN Recurrent Neural Network Study Notes
&lt;/h1&gt;&lt;p&gt;This note summarizes what I learned from Andrej Karpathy&amp;rsquo;s classic blog post &lt;a class="link" href="https://karpathy.github.io/2015/05/21/rnn-effectiveness/" target="_blank" rel="noopener"
 &gt;The Unreasonable Effectiveness of Recurrent Neural Networks&lt;/a&gt;. The original article was published in 2015 and uses character-level language models to show how RNNs/LSTMs can learn spelling, formatting, structure, local syntax, and even interpretable &amp;ldquo;state memory&amp;rdquo; from raw text.&lt;/p&gt;
&lt;p&gt;The main thread of this note is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Why RNNs are suitable for sequences.&lt;/li&gt;
&lt;li&gt;The core formulas and computation process of RNNs.&lt;/li&gt;
&lt;li&gt;How character-level language models are trained and sampled.&lt;/li&gt;
&lt;li&gt;What the classic experiments in Karpathy&amp;rsquo;s article demonstrate.&lt;/li&gt;
&lt;li&gt;Why RNNs were later replaced by Transformers in mainstream NLP.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="what-problem-rnns-solve"&gt;&lt;a href="#what-problem-rnns-solve" class="header-anchor"&gt;&lt;/a&gt;What Problem RNNs Solve
&lt;/h2&gt;&lt;p&gt;Ordinary feedforward neural networks usually assume that inputs and outputs are fixed-length vectors, such as taking an image as input and outputting a class label. But many real tasks are naturally sequential:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Text: a sentence consists of multiple tokens or characters.&lt;/li&gt;
&lt;li&gt;Speech: audio frames are arranged over time.&lt;/li&gt;
&lt;li&gt;Video: frames are arranged over time.&lt;/li&gt;
&lt;li&gt;Translation: one sentence is converted into another sentence in another language.&lt;/li&gt;
&lt;li&gt;Generation: previously generated content affects what comes next.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The key idea of an RNN is: &lt;strong&gt;when processing the current input, the model does not only look at the current input; it also maintains a hidden state that compresses past context.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="RNN patterns for different sequence tasks" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://xedczq.cn/img/rnn/diags.jpeg"&gt;&lt;/p&gt;
&lt;p&gt;Source: Andrej Karpathy, &lt;a class="link" href="https://karpathy.github.io/2015/05/21/rnn-effectiveness/" target="_blank" rel="noopener"
 &gt;The Unreasonable Effectiveness of Recurrent Neural Networks&lt;/a&gt;. Red represents input, blue represents output, and green represents recurrent state. The diagram shows common modes such as fixed input/output, sequence output, sequence input, sequence-to-sequence, and synchronized sequence input/output.&lt;/p&gt;
&lt;p&gt;You can think of an RNN as a repeatedly called &lt;code&gt;step&lt;/code&gt; function:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;rnn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RNN&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rnn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Each time &lt;code&gt;step(x)&lt;/code&gt; is called, the RNN reads the current input &lt;code&gt;x_t&lt;/code&gt;, combines it with the previous hidden state &lt;code&gt;h_{t-1}&lt;/code&gt;, updates a new hidden state &lt;code&gt;h_t&lt;/code&gt;, and produces the current output &lt;code&gt;y_t&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="core-formula-of-a-vanilla-rnn"&gt;&lt;a href="#core-formula-of-a-vanilla-rnn" class="header-anchor"&gt;&lt;/a&gt;Core Formula of a Vanilla RNN
&lt;/h2&gt;&lt;p&gt;The most basic RNN update is:&lt;/p&gt;
$$
h_t = \tanh(W_{hh}h_{t-1} + W_{xh}x_t + b_h)
$$$$
y_t = W_{hy}h_t + b_y
$$&lt;p&gt;Where:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$x_t$: input at time step $t$&lt;/li&gt;
&lt;li&gt;$h_{t-1}$: hidden state from the previous time step&lt;/li&gt;
&lt;li&gt;$h_t$: hidden state at the current time step&lt;/li&gt;
&lt;li&gt;$W_{xh}$: input-to-hidden weights&lt;/li&gt;
&lt;li&gt;$W_{hh}$: hidden-to-hidden recurrent weights&lt;/li&gt;
&lt;li&gt;$W_{hy}$: hidden-to-output weights&lt;/li&gt;
&lt;li&gt;$\tanh$: nonlinear activation that squashes values into $[-1, 1]$&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In code, it roughly looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RNN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;step&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tanh&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;W_hh&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;W_xh&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;W_hy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The most important thing to understand is the meaning of &lt;code&gt;h&lt;/code&gt;: it is not a hand-written rule, but a &amp;ldquo;context summary&amp;rdquo; learned by the model during training. If the input is text, &lt;code&gt;h&lt;/code&gt; may carry information such as whether the model is inside quotes, inside a URL, whether a bracket is open, or what words have appeared before.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="why-rnns-can-model-context"&gt;&lt;a href="#why-rnns-can-model-context" class="header-anchor"&gt;&lt;/a&gt;Why RNNs Can Model Context
&lt;/h2&gt;&lt;p&gt;Take the string &lt;code&gt;hello&lt;/code&gt; as an example. Suppose the vocabulary only contains the four characters &lt;code&gt;h, e, l, o&lt;/code&gt;. During training, the input and target can be:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Input: h e l l
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Target: e l l o
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice that the target after the first &lt;code&gt;l&lt;/code&gt; is &lt;code&gt;l&lt;/code&gt;, while the target after the second &lt;code&gt;l&lt;/code&gt; is &lt;code&gt;o&lt;/code&gt;. If the model only looks at the current character, both time steps have the same input, so it cannot tell what the next character should be. The RNN must use its hidden state to record &amp;ldquo;what has already been seen.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&lt;img alt="Character-level RNN predicting the next character" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://xedczq.cn/img/rnn/charseq.jpeg"&gt;&lt;/p&gt;
&lt;p&gt;Source: Andrej Karpathy, &lt;a class="link" href="https://karpathy.github.io/2015/05/21/rnn-effectiveness/" target="_blank" rel="noopener"
 &gt;The Unreasonable Effectiveness of Recurrent Neural Networks&lt;/a&gt;. The model reads &lt;code&gt;hell&lt;/code&gt; one character at a time, outputs scores for the next character at each step, and the green targets show the correct characters whose scores should be increased.&lt;/p&gt;
&lt;p&gt;The training objective is usually cross-entropy loss at every time step:&lt;/p&gt;
$$
\mathcal{L} = -\sum_t \log p(x_{t+1}\mid x_{\le t})
$$&lt;p&gt;Where:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$x_{\le t}$ means the context up to and including the current position.&lt;/li&gt;
&lt;li&gt;$p(x_{t+1}\mid x_{\le t})$ means the probability of the next character predicted from historical context.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After training, text generation works as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Give the model a starting character or prompt.&lt;/li&gt;
&lt;li&gt;Get the probability distribution for the next character.&lt;/li&gt;
&lt;li&gt;Sample one character from the distribution.&lt;/li&gt;
&lt;li&gt;Feed the sampled character back into the model.&lt;/li&gt;
&lt;li&gt;Repeat the process.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is the simplest generation loop for a character-level language model.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="bptt-how-rnns-are-trained"&gt;&lt;a href="#bptt-how-rnns-are-trained" class="header-anchor"&gt;&lt;/a&gt;BPTT: How RNNs Are Trained
&lt;/h2&gt;&lt;p&gt;An RNN reuses the same set of parameters at every time step. During training, the recurrent structure is unrolled over time and then backpropagation is applied. This is called &lt;strong&gt;Backpropagation Through Time, BPTT&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;If the sequence is very long, fully unrolling it is expensive. A common approach is &lt;strong&gt;Truncated BPTT&lt;/strong&gt;, where gradients are only propagated back for a fixed number of steps. For example, Karpathy&amp;rsquo;s Paul Graham experiment used truncated BPTT with a length of 100 characters.&lt;/p&gt;
&lt;p&gt;The main difficulty in RNN training comes from long chains of gradients:&lt;/p&gt;
$$
\frac{\partial \mathcal{L}}{\partial h_{t-k}}
$$&lt;p&gt;This gradient must pass through many matrix multiplications and nonlinear functions. When the chain is long, gradients may:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Become smaller and smaller: vanishing gradients, making long-term dependencies hard to learn.&lt;/li&gt;
&lt;li&gt;Become larger and larger: exploding gradients, making training unstable.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is why LSTM and GRU became widely used.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="lstm-a-stronger-recurrent-unit"&gt;&lt;a href="#lstm-a-stronger-recurrent-unit" class="header-anchor"&gt;&lt;/a&gt;LSTM: A Stronger Recurrent Unit
&lt;/h2&gt;&lt;p&gt;The experiments in Karpathy&amp;rsquo;s article actually use LSTM. LSTM is still part of the RNN family, but it uses a more complex hidden-state update with gates, making it easier for the model to keep or forget information.&lt;/p&gt;
&lt;p&gt;Typical LSTM components include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Forget gate: decides how much old information to keep.&lt;/li&gt;
&lt;li&gt;Input gate: decides how much new information to write.&lt;/li&gt;
&lt;li&gt;Output gate: decides how much current state to expose to the output.&lt;/li&gt;
&lt;li&gt;Cell state: provides a more stable information channel.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Intuitively, a Vanilla RNN mixes the old state and the new input at every step and compresses them again, so long-term information is easily overwritten. LSTM gives the model mechanisms for &amp;ldquo;writing, keeping, and reading&amp;rdquo;, making it more suitable for long sequences.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="classic-experiments-in-karpathys-article"&gt;&lt;a href="#classic-experiments-in-karpathys-article" class="header-anchor"&gt;&lt;/a&gt;Classic Experiments in Karpathy&amp;rsquo;s Article
&lt;/h2&gt;&lt;h3 id="learning-structure-from-characters"&gt;&lt;a href="#learning-structure-from-characters" class="header-anchor"&gt;&lt;/a&gt;Learning Structure from Characters
&lt;/h3&gt;&lt;p&gt;The original article shows RNN/LSTM results trained on different kinds of text, including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Paul Graham essays&lt;/li&gt;
&lt;li&gt;Shakespeare plays&lt;/li&gt;
&lt;li&gt;Wikipedia Markdown/XML&lt;/li&gt;
&lt;li&gt;Algebraic geometry LaTeX&lt;/li&gt;
&lt;li&gt;Linux source code&lt;/li&gt;
&lt;li&gt;Baby name lists&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The common point is that the model is not given an explicit dictionary, grammar rules, Markdown rules, XML tree rules, or C language rules. It is only trained to &amp;ldquo;predict the next character.&amp;rdquo; Yet after training, it can generate text that looks like the distribution of the original data.&lt;/p&gt;
&lt;p&gt;This shows that: &lt;strong&gt;next-character prediction looks simple, but it forces the model to learn multi-level structure.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Character level: spelling, spaces, punctuation&lt;/li&gt;
&lt;li&gt;Word level: common words, names, variable names&lt;/li&gt;
&lt;li&gt;Syntax level: quotes, brackets, indentation, tag closure&lt;/li&gt;
&lt;li&gt;Style level: Shakespeare-like dialogue, Wikipedia-like entries, source-code comments&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="capability-evolution-during-training"&gt;&lt;a href="#capability-evolution-during-training" class="header-anchor"&gt;&lt;/a&gt;Capability Evolution During Training
&lt;/h3&gt;&lt;p&gt;Karpathy uses &lt;em&gt;War and Peace&lt;/em&gt; as an example to show how sampled text changes over training iterations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Early stage: almost random characters, but spaces begin to appear.&lt;/li&gt;
&lt;li&gt;Middle stage: short words, periods, quotes, and other local structures appear.&lt;/li&gt;
&lt;li&gt;Later stage: more English-like words, names, and sentence forms appear.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;My understanding is that an RNN does not learn &amp;ldquo;language&amp;rdquo; all at once. It first learns the most local and frequent patterns, then gradually forms longer-range dependencies.&lt;/p&gt;
&lt;h3 id="hidden-units-learn-interpretable-states"&gt;&lt;a href="#hidden-units-learn-interpretable-states" class="header-anchor"&gt;&lt;/a&gt;Hidden Units Learn Interpretable States
&lt;/h3&gt;&lt;p&gt;One of the most classic parts of the article is the visualization of LSTM hidden unit activations. Some neurons activate inside URLs, some activate inside Markdown link contexts such as &lt;code&gt;[[...]]&lt;/code&gt;, and others seem to track quoted regions.&lt;/p&gt;
&lt;p&gt;&lt;img alt="LSTM neuron activation over URL regions" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://xedczq.cn/img/rnn/under1.jpeg"&gt;&lt;/p&gt;
&lt;p&gt;Source: Andrej Karpathy, &lt;a class="link" href="https://karpathy.github.io/2015/05/21/rnn-effectiveness/" target="_blank" rel="noopener"
 &gt;The Unreasonable Effectiveness of Recurrent Neural Networks&lt;/a&gt;. This figure shows a hidden unit that activates strongly in URL regions, suggesting the model may have learned an internal state for &amp;ldquo;currently inside a URL.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&lt;img alt="LSTM neuron activation over Markdown link regions" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://xedczq.cn/img/rnn/under2.jpeg"&gt;&lt;/p&gt;
&lt;p&gt;Source: Andrej Karpathy, &lt;a class="link" href="https://karpathy.github.io/2015/05/21/rnn-effectiveness/" target="_blank" rel="noopener"
 &gt;The Unreasonable Effectiveness of Recurrent Neural Networks&lt;/a&gt;. This figure shows a hidden unit responding to the &lt;code&gt;[[...]]&lt;/code&gt; Markdown environment.&lt;/p&gt;
&lt;p&gt;&lt;img alt="A more compact visualization of neuron activations" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://xedczq.cn/img/rnn/pane1.png"&gt;&lt;/p&gt;
&lt;p&gt;Source: Andrej Karpathy, &lt;a class="link" href="https://karpathy.github.io/2015/05/21/rnn-effectiveness/" target="_blank" rel="noopener"
 &gt;The Unreasonable Effectiveness of Recurrent Neural Networks&lt;/a&gt;. These visualizations show that some hidden units learn state-detection functions that humans can interpret.&lt;/p&gt;
&lt;p&gt;The point is not that every neuron has a clear semantic meaning. Rather, end-to-end training can lead the model to discover intermediate states that are useful for the task. For next-character prediction, knowing whether the model is inside a URL, bracket, or quote genuinely improves prediction accuracy.&lt;/p&gt;
&lt;h3 id="rnns-can-handle-non-traditional-sequential-tasks"&gt;&lt;a href="#rnns-can-handle-non-traditional-sequential-tasks" class="header-anchor"&gt;&lt;/a&gt;RNNs Can Handle Non-Traditional Sequential Tasks
&lt;/h3&gt;&lt;p&gt;Karpathy also mentions that even when the data itself is not a sequence, the processing procedure can be designed as a sequence. For example, a model can move attention step by step to read an image, or generate an image step by step on a canvas.&lt;/p&gt;
&lt;p&gt;&lt;img alt="RNN reading house numbers step by step" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://xedczq.cn/img/rnn/house_read.gif"&gt;&lt;/p&gt;
&lt;p&gt;Source: Andrej Karpathy, &lt;a class="link" href="https://karpathy.github.io/2015/05/21/rnn-effectiveness/" target="_blank" rel="noopener"
 &gt;The Unreasonable Effectiveness of Recurrent Neural Networks&lt;/a&gt;. The experiment on the left is related to Recurrent Models of Visual Attention.&lt;/p&gt;
&lt;p&gt;&lt;img alt="RNN generating house numbers step by step" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://xedczq.cn/img/rnn/house_generate.gif"&gt;&lt;/p&gt;
&lt;p&gt;Source: Andrej Karpathy, &lt;a class="link" href="https://karpathy.github.io/2015/05/21/rnn-effectiveness/" target="_blank" rel="noopener"
 &gt;The Unreasonable Effectiveness of Recurrent Neural Networks&lt;/a&gt;. The experiment on the right is related to DRAW: A Recurrent Neural Network For Image Generation.&lt;/p&gt;
&lt;p&gt;This gives an important perspective: RNNs are not only for &amp;ldquo;processing sequence data&amp;rdquo;; they can also represent &amp;ldquo;a computation process executed in order.&amp;rdquo;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="sampling-temperature-why-generation-changes"&gt;&lt;a href="#sampling-temperature-why-generation-changes" class="header-anchor"&gt;&lt;/a&gt;Sampling Temperature: Why Generation Changes
&lt;/h2&gt;&lt;p&gt;A character-level language model outputs a probability distribution for the next character. During sampling, a temperature value is often used to adjust the distribution:&lt;/p&gt;
$$
p_i = \frac{\exp(z_i / T)}{\sum_j \exp(z_j / T)}
$$&lt;p&gt;Where:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$z_i$ is the logit of the $i$-th character.&lt;/li&gt;
&lt;li&gt;$T$ is the temperature.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The effect of temperature:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$T &amp;lt; 1$: the distribution becomes sharper; the model is more conservative and more likely to repeat high-probability patterns.&lt;/li&gt;
&lt;li&gt;$T = 1$: normal sampling.&lt;/li&gt;
&lt;li&gt;$T &amp;gt; 1$: the distribution becomes flatter; output is more diverse, but errors also increase.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So the &amp;ldquo;creativity&amp;rdquo; and &amp;ldquo;stability&amp;rdquo; of a generative model are often a tradeoff.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="advantages-of-rnns"&gt;&lt;a href="#advantages-of-rnns" class="header-anchor"&gt;&lt;/a&gt;Advantages of RNNs
&lt;/h2&gt;&lt;p&gt;RNN advantages can be summarized as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Naturally suitable for streaming input: when data arrives one time step at a time, an RNN can continuously update its state.&lt;/li&gt;
&lt;li&gt;Parameter sharing: the same &lt;code&gt;step&lt;/code&gt; function is reused for sequences of arbitrary length.&lt;/li&gt;
&lt;li&gt;State compression: the hidden state can summarize past context.&lt;/li&gt;
&lt;li&gt;Simple generation intuition: predict the next token, then feed the output back into the model.&lt;/li&gt;
&lt;li&gt;Still valuable for small models and certain temporal tasks, such as sensor sequences, real-time speech, and low-latency tasks on edge devices.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="limitations-of-rnns"&gt;&lt;a href="#limitations-of-rnns" class="header-anchor"&gt;&lt;/a&gt;Limitations of RNNs
&lt;/h2&gt;&lt;p&gt;The main limitations are also clear.&lt;/p&gt;
&lt;h3 id="sequential-computation-is-hard-to-parallelize"&gt;&lt;a href="#sequential-computation-is-hard-to-parallelize" class="header-anchor"&gt;&lt;/a&gt;Sequential Computation Is Hard to Parallelize
&lt;/h3&gt;&lt;p&gt;An RNN must compute $h_{t-1}$ before it can compute $h_t$. This means the time steps inside one sequence are hard to fully parallelize.&lt;/p&gt;
&lt;p&gt;For short sequences this may not matter much, but in large-scale language model training, both data size and model size are huge. Not being able to fully use GPU/TPU parallelism becomes a core bottleneck.&lt;/p&gt;
&lt;h3 id="long-distance-dependencies-are-difficult"&gt;&lt;a href="#long-distance-dependencies-are-difficult" class="header-anchor"&gt;&lt;/a&gt;Long-Distance Dependencies Are Difficult
&lt;/h3&gt;&lt;p&gt;In theory, the hidden state can carry all historical information. In practice, it is hard for a fixed-length vector to losslessly compress a long context. Earlier information passes through more state updates and is more likely to be overwritten or weakened.&lt;/p&gt;
&lt;p&gt;LSTM/GRU mitigate this issue, but do not completely solve it.&lt;/p&gt;
&lt;h3 id="the-information-path-is-too-long"&gt;&lt;a href="#the-information-path-is-too-long" class="header-anchor"&gt;&lt;/a&gt;The Information Path Is Too Long
&lt;/h3&gt;&lt;p&gt;If the first token needs to affect the 1000th token, the information in an RNN must pass through about 1000 recurrent updates. The longer the path, the harder optimization becomes and the easier information is lost.&lt;/p&gt;
&lt;h3 id="hidden-state-is-a-bottleneck"&gt;&lt;a href="#hidden-state-is-a-bottleneck" class="header-anchor"&gt;&lt;/a&gt;Hidden State Is a Bottleneck
&lt;/h3&gt;&lt;p&gt;RNNs compress the past into one hidden vector. This vector must both store context and participate in the next computation. Karpathy also mentions in the outlook section that RNNs couple representation capacity with per-step computation cost: the larger the hidden state, the more expensive each matrix multiplication becomes.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="why-rnns-were-replaced-by-transformers"&gt;&lt;a href="#why-rnns-were-replaced-by-transformers" class="header-anchor"&gt;&lt;/a&gt;Why RNNs Were Replaced by Transformers
&lt;/h2&gt;&lt;p&gt;Transformers did not replace RNNs because &amp;ldquo;RNNs are completely useless.&amp;rdquo; They replaced them because, for large-scale NLP tasks, Transformers have better engineering properties and modeling scalability.&lt;/p&gt;
&lt;h3 id="transformers-are-easier-to-train-in-parallel"&gt;&lt;a href="#transformers-are-easier-to-train-in-parallel" class="header-anchor"&gt;&lt;/a&gt;Transformers Are Easier to Train in Parallel
&lt;/h3&gt;&lt;p&gt;RNNs recur over time:&lt;/p&gt;
$$
h_t = f(h_{t-1}, x_t)
$$&lt;p&gt;Transformer self-attention can compute relationships among all positions in a sequence within the same layer. During training, token representations in a batch can be heavily matrixized and parallelized.&lt;/p&gt;
&lt;p&gt;This is one of the core motivations of &lt;a class="link" href="https://arxiv.org/abs/1706.03762" target="_blank" rel="noopener"
 &gt;Attention Is All You Need&lt;/a&gt;: remove recurrence and convolution, and build sequence transduction models using attention only, improving parallelization and reducing training time.&lt;/p&gt;
&lt;h3 id="shorter-paths-for-long-distance-dependencies"&gt;&lt;a href="#shorter-paths-for-long-distance-dependencies" class="header-anchor"&gt;&lt;/a&gt;Shorter Paths for Long-Distance Dependencies
&lt;/h3&gt;&lt;p&gt;In an RNN, information between distant tokens must pass through many time steps. Transformer self-attention lets any two positions directly connect within one layer.&lt;/p&gt;
&lt;p&gt;A rough comparison:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Model&lt;/th&gt;
 &lt;th&gt;Information path between distant tokens&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;RNN&lt;/td&gt;
 &lt;td&gt;$O(n)$&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;CNN&lt;/td&gt;
 &lt;td&gt;Depends on convolution depth and receptive field&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Transformer self-attention&lt;/td&gt;
 &lt;td&gt;$O(1)$&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Shorter paths usually make long-distance dependencies easier to learn.&lt;/p&gt;
&lt;h3 id="attention-explicitly-reads-context"&gt;&lt;a href="#attention-explicitly-reads-context" class="header-anchor"&gt;&lt;/a&gt;Attention Explicitly Reads Context
&lt;/h3&gt;&lt;p&gt;RNNs rely on hidden states to compress history, while Transformer attention dynamically reads information from other positions for the current position:&lt;/p&gt;
$$
\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V
$$&lt;p&gt;This allows the model to retrieve information from context according to relevance, instead of relying entirely on a recursively compressed state.&lt;/p&gt;
&lt;h3 id="transformers-fit-large-model-scaling-better"&gt;&lt;a href="#transformers-fit-large-model-scaling-better" class="header-anchor"&gt;&lt;/a&gt;Transformers Fit Large-Model Scaling Better
&lt;/h3&gt;&lt;p&gt;Modern large language models rely on large data, large parameter counts, and large compute. Transformers are matrix-multiplication-heavy and parallel-friendly, which makes them better at using hardware efficiently. RNNs are limited by time-step dependencies and have lower throughput.&lt;/p&gt;
&lt;p&gt;In the era of large-scale pretraining, the advantage of Transformers is not only algorithmic performance, but also hardware efficiency, training stability, ecosystem tooling, and scalability.&lt;/p&gt;
&lt;h3 id="but-rnns-have-not-disappeared-completely"&gt;&lt;a href="#but-rnns-have-not-disappeared-completely" class="header-anchor"&gt;&lt;/a&gt;But RNNs Have Not Disappeared Completely
&lt;/h3&gt;&lt;p&gt;RNNs are still useful in some scenarios:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Streaming inference: input arrives continuously and recomputing the whole context is undesirable.&lt;/li&gt;
&lt;li&gt;Low-latency edge tasks: small models, fixed state, and controllable inference cost.&lt;/li&gt;
&lt;li&gt;Time-series tasks: some sensor or control tasks do not necessarily need full self-attention.&lt;/li&gt;
&lt;li&gt;New architecture research: state-space models, linear attention, and RWKV-like models reuse ideas from recurrence.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So a more accurate statement is: &lt;strong&gt;Transformers replaced traditional RNN/LSTM models in mainstream NLP and large-model training, but the idea of recurrent state continues to exist in many newer architectures.&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="study-summary"&gt;&lt;a href="#study-summary" class="header-anchor"&gt;&lt;/a&gt;Study Summary
&lt;/h2&gt;&lt;p&gt;The core of RNNs is not a complicated formula, but a simple and powerful abstraction: &lt;strong&gt;use the same function repeatedly to process a sequence, and use a hidden state to carry past information.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Karpathy&amp;rsquo;s article is classic because it does not start by stacking theory. Instead, it uses character-level generation experiments to show that if the training objective is general enough, the model will spontaneously learn spelling, formatting, brackets, quotes, URLs, code structure, and other multi-level patterns in order to predict the next character.&lt;/p&gt;
&lt;p&gt;But the recurrent structure of RNNs also creates natural bottlenecks at scale: difficult parallelization, hard optimization of long dependencies, and limited hidden-state compression capacity. Transformers use self-attention to let sequence positions interact directly and greatly improve parallel training, which is why they became the mainstream architecture for modern NLP and large language models.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="sources"&gt;&lt;a href="#sources" class="header-anchor"&gt;&lt;/a&gt;Sources
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Andrej Karpathy, &lt;a class="link" href="https://karpathy.github.io/2015/05/21/rnn-effectiveness/" target="_blank" rel="noopener"
 &gt;The Unreasonable Effectiveness of Recurrent Neural Networks&lt;/a&gt;, 2015-05-21&lt;/li&gt;
&lt;li&gt;Andrej Karpathy, &lt;a class="link" href="https://github.com/karpathy/char-rnn" target="_blank" rel="noopener"
 &gt;char-rnn GitHub repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Andrej Karpathy, &lt;a class="link" href="https://gist.github.com/karpathy/d4dee566867f8291f086" target="_blank" rel="noopener"
 &gt;Minimal character-level language model with a Vanilla Recurrent Neural Network, in Python/numpy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Ashish Vaswani et al., &lt;a class="link" href="https://arxiv.org/abs/1706.03762" target="_blank" rel="noopener"
 &gt;Attention Is All You Need&lt;/a&gt;, 2017&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>