<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 <title>홍합탕's Blog</title>
 <link href="http://honghaptang.github.io/blog/atom.xml" rel="self"/>
 <link href="http://honghaptang.github.io/blog"/>
 <updated>2026-09-30T16:52:05+00:00</updated>
 <id>http://honghaptang.github.io/blog</id>
 <author>
   <name>홍합탕</name>
 </author>

 
 <entry>
   <title>A Laptop VLM Solves 44% of Naver's Receipt CAPTCHAs</title>
   <link href="http://hankquinlan.github.io/blog/2026/09/30/naver-receipt-captcha"/>
   <updated>2026-09-30T12:01:00+00:00</updated>
   <id>http://honghaptang.github.io//blog/2026/09/30/naver-receipt-captcha</id>
   <content type="html">&lt;p&gt;If you log in to Naver often enough, you’ll eventually see a receipt instead of a login form.
It’s photographed at an angle, torn into strips, and covered in scribbled letters, and underneath is a question:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;What is the unit price of the least bought item per unit?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is Naver’s receipt CAPTCHA. The idea is clever: instead of asking you to decode wavy letters, it asks you to
&lt;strong&gt;read a messy document and reason about it&lt;/strong&gt;. The catch is that reading messy documents and reasoning about them is
exactly what vision–language models (VLMs) are trained to do.&lt;/p&gt;

&lt;p&gt;So I measured it. The short version:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;An &lt;strong&gt;unmodified, open-weight 7B model on a 16 GB laptop&lt;/strong&gt; answers &lt;strong&gt;43.8%&lt;/strong&gt; of real challenges correctly.&lt;/li&gt;
  &lt;li&gt;The 7B model gets &lt;strong&gt;~62% of the “just read it off the receipt” questions&lt;/strong&gt; right, despite the tears and scribbles.&lt;/li&gt;
  &lt;li&gt;It fails mainly on &lt;strong&gt;multi-step arithmetic&lt;/strong&gt;, such as totals and “unit price of the least bought item”.&lt;/li&gt;
  &lt;li&gt;If failed attempts can be retried on fresh challenges, 43.8% per attempt means a &lt;strong&gt;~94% chance of passing within five tries&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A longer write-up with confidence intervals and significance tests is coming as a preprint.
This post is the readable version.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;what-the-challenge-looks-like&quot;&gt;What the challenge looks like&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/2026/naver-captcha/example_challenge.png&quot; alt=&quot;An example Naver receipt CAPTCHA: two torn receipt strips at an angle over a textured background, with handwritten letters scattered over the text.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A real challenge from April 2026. Question: “How many kinds of items did the customer purchase?”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Every challenge is a 670×320 image plus one English question. The defenses are all about &lt;strong&gt;layout, not lettering&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;the receipt is torn into two or three strips, rotated and bent in perspective;&lt;/li&gt;
  &lt;li&gt;handwritten letter/digit strings are scattered on top, sometimes right over the prices;&lt;/li&gt;
  &lt;li&gt;parts of the receipt are cut off or hidden in the tear;&lt;/li&gt;
  &lt;li&gt;the column order (Price / Qty / Sum / Name) changes from receipt to receipt.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The printed text itself is a clean, ordinary font. A model that can locate the right row can read it.&lt;/p&gt;

&lt;h3 id=&quot;the-questions-are-surprisingly-repetitive&quot;&gt;The questions are surprisingly repetitive&lt;/h3&gt;

&lt;p&gt;I collected &lt;strong&gt;1,100 challenges&lt;/strong&gt; on 9 April 2026. Across all of them there were only &lt;strong&gt;295 distinct question strings&lt;/strong&gt;,
and nine fixed templates account for most of them:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Question type&lt;/th&gt;
      &lt;th&gt;Share of challenges&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Counting / quantity (“How many items cost 370 won per unit?”)&lt;/td&gt;
      &lt;td&gt;43.8%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Unit price of the most expensive / most bought item&lt;/td&gt;
      &lt;td&gt;14.2%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Unit price of a named item (“…of frozen Skate?”)&lt;/td&gt;
      &lt;td&gt;10.2%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Unit price of the cheapest item&lt;/td&gt;
      &lt;td&gt;7.5%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Unit price of the least bought item&lt;/td&gt;
      &lt;td&gt;7.4%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Receipt total&lt;/td&gt;
      &lt;td&gt;5.8%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Address fill-in-the-blank&lt;/td&gt;
      &lt;td&gt;4.9%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;A digit of the store’s phone number&lt;/td&gt;
      &lt;td&gt;3.9%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Rare types&lt;/td&gt;
      &lt;td&gt;2.0%&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;These split into two kinds:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Lookup questions&lt;/strong&gt;, where the answer is printed on the receipt (a named item’s price, the address, a phone digit).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Aggregate questions&lt;/strong&gt;, where the answer has to be computed by counting, comparing, summing, or dividing a line total by its quantity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That distinction turns out to explain almost everything.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-experiment&quot;&gt;The experiment&lt;/h2&gt;

&lt;p&gt;I hand-labeled &lt;strong&gt;128&lt;/strong&gt; of the collected challenges and asked three open-weight models from the Qwen VL family to answer
them &lt;strong&gt;zero-shot&lt;/strong&gt;: no examples, no fine-tuning, no step-by-step prompting. The prompt was just the image, the question,
and “return only the answer”. Everything ran locally on an M1 Pro laptop with 16 GB of memory.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Model&lt;/th&gt;
      &lt;th&gt;Correct&lt;/th&gt;
      &lt;th&gt;Accuracy (95% CI)&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Qwen2-VL-2B&lt;/td&gt;
      &lt;td&gt;20 / 128&lt;/td&gt;
      &lt;td&gt;15.6% (10.3–22.9)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Qwen2.5-VL-3B&lt;/td&gt;
      &lt;td&gt;34 / 128&lt;/td&gt;
      &lt;td&gt;26.6% (19.7–34.8)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Qwen2.5-VL-7B&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;56 / 128&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;43.8% (35.5–52.4)&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Both jumps (2B→3B and 3B→7B) are statistically significant on paired tests (p = 0.024 and p &amp;lt; 0.001).
My labeled set slightly over-represents the easy named-item price questions. Reweighting to the real question mix
brings the 7B model to about &lt;strong&gt;37%&lt;/strong&gt;, still roughly three in eight.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/2026/naver-captcha/per_type.png&quot; alt=&quot;Per-question-type accuracy for the 2B, 3B and 7B models. The 7B model is strongest on address blanks and named-item prices and scores zero on receipt totals.&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;where-the-7b-model-succeeds-and-where-it-doesnt&quot;&gt;Where the 7B model succeeds, and where it doesn’t&lt;/h3&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt; &lt;/th&gt;
      &lt;th&gt;7B accuracy&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Lookup&lt;/strong&gt; questions (47 items)&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;61.7%&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Aggregate&lt;/strong&gt; questions (81 items)&lt;/td&gt;
      &lt;td&gt;&lt;strong&gt;33.3%&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The torn strips and scribbles didn’t stop it from reading: it got &lt;strong&gt;8 of 10 address blanks&lt;/strong&gt; and &lt;strong&gt;16 of 27
named-item prices&lt;/strong&gt;. What it can’t do yet is the arithmetic:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Receipt totals: 0 of 8.&lt;/strong&gt; It answers with a plausible amount of the right size (7,000 for 6,800; 12,000 for
10,300) but never the exact total.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;“Least bought item” unit price: 0 of 4.&lt;/strong&gt; It often returns a price from the wrong row, or a line sum instead of a unit price.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Counting shortcuts.&lt;/strong&gt; For “How many items cost N won per unit?” it often just says &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt;, and for “total number of
products” it often says &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;10&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;100&lt;/code&gt;. It isn’t really attempting the count.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words, the model &lt;strong&gt;reads the receipt fine and skips the procedure&lt;/strong&gt;. That gap is the one that step-by-step
prompting, tool use, and task-specific fine-tuning are known to close.&lt;/p&gt;

&lt;p&gt;I also screened five other open models on a small 17-item pilot. MiniCPM-V was about as good as Qwen-7B, while LLaVA-7B
and BakLLaVA barely registered. Llama 3.2-Vision 11B scored 15% over 60 items, mostly because it kept answering in full
sentences. &lt;strong&gt;Parameter count alone doesn’t predict success here.&lt;/strong&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;what-44-means-in-practice&quot;&gt;What 44% means in practice&lt;/h2&gt;

&lt;p&gt;A CAPTCHA doesn’t have to be unbeatable; it has to make automation expensive. If each failure brings a fresh,
independent challenge, per-attempt accuracy compounds quickly:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/2026/naver-captcha/retry.png&quot; alt=&quot;Probability of passing within k attempts for each model. The 7B curve passes 80% at three attempts and 94% at five.&quot; /&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Attempts&lt;/th&gt;
      &lt;th&gt;Chance the 7B model has passed&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;43.8%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;82.2%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;94.4%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;99.7%&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Three things stand out:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;The visual defenses don’t block reading.&lt;/strong&gt; The torn, scribbled receipt stopped the 7B model on only about 40% of lookup questions.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;The remaining margin is arithmetic,&lt;/strong&gt; which is the capability current models are improving fastest at.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;It all runs on the attacker’s own laptop.&lt;/strong&gt; There’s no per-query cost and no third-party solving service, so API
pricing and similar controls don’t apply.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Important caveats.&lt;/strong&gt; This is a per-challenge accuracy, &lt;strong&gt;not&lt;/strong&gt; an end-to-end bypass rate. I didn’t test Naver’s rate
limits, lockouts, or risk scoring, and I never submitted an answer to the live site. Any of those could cut the number of
retries an attacker actually gets. I also didn’t measure how well &lt;em&gt;people&lt;/em&gt; do. Anecdotally, the least-bought-unit-price
questions are a chore for humans too, and that deserves a proper user study.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;correcting-the-record-on-fine-tuning&quot;&gt;Correcting the record on fine-tuning&lt;/h2&gt;

&lt;p&gt;An earlier draft of this project claimed that a LoRA adapter on the 2B model “didn’t help”. When I audited the saved
files, that experiment turned out to be broken rather than negative:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;the adapter’s trained weights (its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;B&lt;/code&gt; matrices) were &lt;strong&gt;exactly zero&lt;/strong&gt;, meaning it never learned anything;&lt;/li&gt;
  &lt;li&gt;its “results” matched the untrained model’s answers on &lt;strong&gt;all 120 items&lt;/strong&gt;;&lt;/li&gt;
  &lt;li&gt;the evaluation step in the pipeline was a placeholder;&lt;/li&gt;
  &lt;li&gt;and it trained on the same items it was tested on.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So that claim is withdrawn.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A corrected run is in progress now:&lt;/strong&gt; Qwen2.5-VL-7B (4-bit, MLX) with a LoRA adapter, evaluated by 4-fold
cross-validation. Each adapter trains on 96 labeled challenges and is scored only on the 32 it never saw. The same 4-bit
model with the same prompt scores &lt;strong&gt;59 / 128 (46.1%)&lt;/strong&gt; zero-shot, which is the baseline to beat.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The fine-tuning run is still going. I’ll update this post with the held-out results, gain or no gain, when it finishes.&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;what-naver-could-do&quot;&gt;What Naver could do&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Don’t rely on this challenge alone.&lt;/strong&gt; Pair it with server-side risk signals and per-account / per-IP attempt limits,
so the retry math above stops working.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Re-test regularly against current open models.&lt;/strong&gt; A defense that holds against last year’s models won’t necessarily hold against next year’s.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Make questions easy for people and hard for models, not just harder.&lt;/strong&gt; Harder arithmetic mostly burdens legitimate
users. Any change should be validated with a human study.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;limitations&quot;&gt;Limitations&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Small sample.&lt;/strong&gt; 128 labeled items give roughly ±8-point intervals overall, and most per-type numbers rest on a handful of items.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Confounded 7B comparison.&lt;/strong&gt; The 7B zero-shot run used a different runtime, quantization and prompt from the 2B/3B runs.
The 4-bit MLX rerun (59/128) lands in the same place, which is reassuring.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Labels.&lt;/strong&gt; One annotator, with no confirmation from Naver’s server. A spot-check of 18 labels found 2 errors, and
neither changes any score.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Single snapshot.&lt;/strong&gt; All data come from one day in April 2026, and the challenge may have changed since.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;ethics&quot;&gt;Ethics&lt;/h2&gt;

&lt;p&gt;I collected challenge images only, never submitted answers, never touched anyone else’s account, and I’m not releasing a
ready-to-use solver or trained adapter.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Language Notes Repos</title>
   <link href="http://hankquinlan.github.io/blog/2026/03/09/notes-repos"/>
   <updated>2026-03-09T00:00:00+00:00</updated>
   <id>http://honghaptang.github.io//blog/2026/03/09/notes-repos</id>
   <content type="html">&lt;p&gt;It’s my personal passion to learn new languages, and it matters to me because it keeps me curious, humble, and connected to people I would otherwise never really meet. I like to keep my new words with me on the go. You can find them here for your perusing, and I’m curious how others do it too. Are Anki cards the most popular? Should I switch?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/juleshenry/castellano_notes&quot;&gt;castellano_notes&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/juleshenry/french_notes&quot;&gt;french_notes&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/juleshenry/korean_notes&quot;&gt;korean_notes&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/juleshenry/portuguese_notes&quot;&gt;portuguese_notes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re working through a language and want to compare approaches, feel free to browse or fork. These are living scratchpads, not polished textbooks, but that’s part of the fun.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>한글 낙서: Hangul Graffiti</title>
   <link href="http://hankquinlan.github.io/blog/2026/03/09/Hangul-Graffiti"/>
   <updated>2026-03-09T00:00:00+00:00</updated>
   <id>http://honghaptang.github.io//blog/2026/03/09/Hangul-Graffiti</id>
   <content type="html">&lt;p&gt;There is something disarming about a language that bows before it speaks.&lt;/p&gt;

&lt;p&gt;Korean does not merely encode information. It encodes relationships. Every verb ending is a social contract – a declaration of how you see the person standing in front of you. In English, “please sit down” works for your boss and your dog. In Korean, you’d better know the difference between 앉으세요 and 앉아, or you will insult one and confuse the other.&lt;/p&gt;

&lt;p&gt;I have been collecting notes on Korean for a few years now. What follows is a distillation of those notes, organized not as a textbook would but as a learner actually encounters the language: in gyms, in novels, in text messages, and in the strange space between what is said and what is meant.&lt;/p&gt;

&lt;h2 id=&quot;the-architecture-of-hangul&quot;&gt;The Architecture of Hangul&lt;/h2&gt;

&lt;p&gt;King Sejong the Great (세종대왕) invented Hangul in 1443, and the story is almost too good to be true. The consonant shapes are modeled after the physical position of the tongue and mouth when you pronounce them:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;ㄱ (g/k)&lt;/strong&gt;: the back of the tongue rising toward the soft palate&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;ㄴ (n)&lt;/strong&gt;: the tongue touching the upper gum ridge&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;ㅁ (m)&lt;/strong&gt;: the shape of closed lips&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;ㅅ (s)&lt;/strong&gt;: the shape of a tooth&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;ㅇ (ng/silent)&lt;/strong&gt;: the shape of the throat&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vowels are built from three elements: a dot (representing the sun/heaven), a horizontal line (the earth), and a vertical line (a person standing). From these three primitives, the entire vowel system unfolds:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Vowel&lt;/th&gt;
      &lt;th&gt;Sound&lt;/th&gt;
      &lt;th&gt;Construction&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;ㅏ&lt;/td&gt;
      &lt;td&gt;a&lt;/td&gt;
      &lt;td&gt;vertical + right dot (bright)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;ㅓ&lt;/td&gt;
      &lt;td&gt;eo&lt;/td&gt;
      &lt;td&gt;vertical + left dot (dark)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;ㅗ&lt;/td&gt;
      &lt;td&gt;o&lt;/td&gt;
      &lt;td&gt;horizontal + top dot (bright)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;ㅜ&lt;/td&gt;
      &lt;td&gt;u&lt;/td&gt;
      &lt;td&gt;horizontal + bottom dot (dark)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;ㅡ&lt;/td&gt;
      &lt;td&gt;eu&lt;/td&gt;
      &lt;td&gt;horizontal line alone&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;ㅣ&lt;/td&gt;
      &lt;td&gt;i&lt;/td&gt;
      &lt;td&gt;vertical line alone&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;This is a writing system designed by committee – but the good kind, the kind where the committee included phonologists. The result is that Korean is arguably the most rationally designed script in active use anywhere on Earth.&lt;/p&gt;

&lt;h2 id=&quot;pronunciation-the-rules-they-dont-teach-first&quot;&gt;Pronunciation: The Rules They Don’t Teach First&lt;/h2&gt;

&lt;p&gt;Two rules I picked up early that cleared up a lot of confusion:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. ㅅ before ㅣ or ㅑ/ㅕ/ㅛ/ㅠ becomes “sh”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The consonant ㅅ is normally an “s,” but place it before any “i” or “y” vowel and it palatalizes to “sh.” This is why 시 sounds like “shi” and 신문 (newspaper) is “shin-mun,” not “sin-mun.” The word 시작 (beginning) is “shi-jak,” and 식당 (restaurant) is “shik-dang.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The silent 받침&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When ㄹ sits in the 받침 (bottom consonant position), it behaves differently than you’d expect. Korean syllable blocks stack consonants and vowels into squares, and the bottom slot – the 받침 – follows its own rules of liaison and assimilation. The consonant at the bottom of one syllable bleeds into the top of the next, creating pronunciation chains that make spoken Korean sound nothing like its spelling suggests.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;독립 (independence) is pronounced “dong-nip” not “dok-lip”&lt;/li&gt;
  &lt;li&gt;한국어 (Korean language) is pronounced “han-gu-geo” – the ㄱ 받침 links to the next syllable’s vowel&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;grammar-hierarchy-in-the-verb&quot;&gt;Grammar: Hierarchy in the Verb&lt;/h2&gt;

&lt;p&gt;Korean has seven speech levels, though modern usage mostly collapses these into four. The critical insight is that the verb ending changes based on your relationship to the listener – not the subject, the &lt;em&gt;listener&lt;/em&gt;:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Level&lt;/th&gt;
      &lt;th&gt;Ending&lt;/th&gt;
      &lt;th&gt;When to Use&lt;/th&gt;
      &lt;th&gt;Example (to go)&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Formal polite (합쇼체)&lt;/td&gt;
      &lt;td&gt;-ㅂ니다 / -습니다&lt;/td&gt;
      &lt;td&gt;Business, news, strangers&lt;/td&gt;
      &lt;td&gt;갑니다&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Informal polite (해요체)&lt;/td&gt;
      &lt;td&gt;-아요 / -어요&lt;/td&gt;
      &lt;td&gt;Default safe choice&lt;/td&gt;
      &lt;td&gt;가요&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Casual (해체)&lt;/td&gt;
      &lt;td&gt;-아 / -어&lt;/td&gt;
      &lt;td&gt;Close friends, younger people&lt;/td&gt;
      &lt;td&gt;가&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Formal plain (해라체)&lt;/td&gt;
      &lt;td&gt;-ㄴ다 / -는다&lt;/td&gt;
      &lt;td&gt;Writing, narration, diaries&lt;/td&gt;
      &lt;td&gt;간다&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The same verb 가다 (to go) is four different social acts depending on the ending. Get it wrong and you’ve made a statement about the relationship, not about where you’re going.&lt;/p&gt;

&lt;h3 id=&quot;conjugation-in-practice&quot;&gt;Conjugation in Practice&lt;/h3&gt;

&lt;p&gt;Unlike European languages with their tables of person and number, Korean verbs don’t conjugate for &lt;em&gt;who&lt;/em&gt; is doing the action. They conjugate for &lt;em&gt;how you feel about the person you’re talking to&lt;/em&gt;. The subject is often dropped entirely. Context carries it.&lt;/p&gt;

&lt;p&gt;Here is 먹다 (to eat) across several constructions:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Form&lt;/th&gt;
      &lt;th&gt;Korean&lt;/th&gt;
      &lt;th&gt;Literal&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Formal polite&lt;/td&gt;
      &lt;td&gt;먹습니다&lt;/td&gt;
      &lt;td&gt;(one) eats [sir/ma’am]&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Informal polite&lt;/td&gt;
      &lt;td&gt;먹어요&lt;/td&gt;
      &lt;td&gt;(one) eats [politely]&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Casual&lt;/td&gt;
      &lt;td&gt;먹어&lt;/td&gt;
      &lt;td&gt;eat / eats&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Past (polite)&lt;/td&gt;
      &lt;td&gt;먹었어요&lt;/td&gt;
      &lt;td&gt;ate&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Future (polite)&lt;/td&gt;
      &lt;td&gt;먹을 거예요&lt;/td&gt;
      &lt;td&gt;will eat&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Negative&lt;/td&gt;
      &lt;td&gt;안 먹어요&lt;/td&gt;
      &lt;td&gt;doesn’t eat&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Want to&lt;/td&gt;
      &lt;td&gt;먹고 싶어요&lt;/td&gt;
      &lt;td&gt;wants to eat&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Can&lt;/td&gt;
      &lt;td&gt;먹을 수 있어요&lt;/td&gt;
      &lt;td&gt;can eat&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Progressive&lt;/td&gt;
      &lt;td&gt;먹고 있어요&lt;/td&gt;
      &lt;td&gt;is eating&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Notice how the stem 먹 stays constant while the endings do all the work. This is the agglutinative nature of Korean: you stack suffixes like LEGO bricks.&lt;/p&gt;

&lt;h2 id=&quot;the-particles-small-words-heavy-lifting&quot;&gt;The Particles: Small Words, Heavy Lifting&lt;/h2&gt;

&lt;p&gt;Korean particles are postpositions – they attach &lt;em&gt;after&lt;/em&gt; the noun, not before it. And they do everything.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Particle&lt;/th&gt;
      &lt;th&gt;Function&lt;/th&gt;
      &lt;th&gt;Example&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;은/는&lt;/td&gt;
      &lt;td&gt;Topic marker&lt;/td&gt;
      &lt;td&gt;저&lt;strong&gt;는&lt;/strong&gt; 학생이에요 (As for me, I’m a student)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;이/가&lt;/td&gt;
      &lt;td&gt;Subject marker&lt;/td&gt;
      &lt;td&gt;비&lt;strong&gt;가&lt;/strong&gt; 와요 (Rain is coming)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;을/를&lt;/td&gt;
      &lt;td&gt;Object marker&lt;/td&gt;
      &lt;td&gt;커피&lt;strong&gt;를&lt;/strong&gt; 마셔요 (I drink coffee)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;에&lt;/td&gt;
      &lt;td&gt;Location / time&lt;/td&gt;
      &lt;td&gt;학교&lt;strong&gt;에&lt;/strong&gt; 가요 (I go to school)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;에서&lt;/td&gt;
      &lt;td&gt;Location of action&lt;/td&gt;
      &lt;td&gt;집&lt;strong&gt;에서&lt;/strong&gt; 공부해요 (I study at home)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;의&lt;/td&gt;
      &lt;td&gt;Possession&lt;/td&gt;
      &lt;td&gt;나&lt;strong&gt;의&lt;/strong&gt; 책 (my book)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;도&lt;/td&gt;
      &lt;td&gt;Also/too&lt;/td&gt;
      &lt;td&gt;저&lt;strong&gt;도&lt;/strong&gt; 가요 (I’m going too)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;한테/에게&lt;/td&gt;
      &lt;td&gt;To (a person)&lt;/td&gt;
      &lt;td&gt;친구&lt;strong&gt;한테&lt;/strong&gt; 줘요 (I give it to a friend)&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The distinction between 은/는 (topic) and 이/가 (subject) is one of the deepest rabbit holes in Korean linguistics. Roughly: 은/는 sets the frame (“as for X…”), while 이/가 identifies (“it is X that…”). The sentence 제가 학생이에요 emphasizes that &lt;em&gt;I&lt;/em&gt; am the student (maybe someone asked “who’s the student?”), while 저는 학생이에요 simply states the fact about me.&lt;/p&gt;

&lt;h2 id=&quot;at-the-gym-헬스장에서&quot;&gt;At the Gym: 헬스장에서&lt;/h2&gt;

&lt;p&gt;Some of the most useful Korean I’ve picked up comes from the gym. The phrasebook doesn’t prepare you for wanting to ask someone if they’re done with the squat rack:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Korean&lt;/th&gt;
      &lt;th&gt;English&lt;/th&gt;
      &lt;th&gt;Context&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;몇 세트 남았어요?&lt;/td&gt;
      &lt;td&gt;How many sets do you have left?&lt;/td&gt;
      &lt;td&gt;Politely waiting for equipment&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;좀 보조 해주실 수 있나요?&lt;/td&gt;
      &lt;td&gt;Can you spot me?&lt;/td&gt;
      &lt;td&gt;Asking for help on bench press&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;아직 쓰시고 있나요?&lt;/td&gt;
      &lt;td&gt;Are you still using this?&lt;/td&gt;
      &lt;td&gt;Gesturing at a machine&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;하루에 몇 끼 먹나요?&lt;/td&gt;
      &lt;td&gt;How many meals do you eat a day?&lt;/td&gt;
      &lt;td&gt;Gym small talk&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;And the vocabulary that comes with the culture:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;헬창&lt;/strong&gt; – literally an abbreviation meaning something like “health fiend.” Used as a playful, almost affectionate compliment among gym-goers, though it sounds crude to outsiders. Think “gym rat” but with more edge.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;빵빵하다&lt;/strong&gt; – describes big, pumped muscles. 근육이 빵빵! (“Muscles are poppin’!”)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;오운완&lt;/strong&gt; (abbreviation of 오늘도 운동 완료했다) – “Finished my workout for today.” The hashtag of Korean fitness Instagram. Sometimes abbreviated further to just ㅇㅇㅇ, because even abbreviations get abbreviated.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The counter system reveals itself here too: &lt;strong&gt;끼&lt;/strong&gt; is the counter for meals (하루에 몇 끼?), &lt;strong&gt;세트&lt;/strong&gt; borrows the English “set,” and &lt;strong&gt;체지방&lt;/strong&gt; (body fat) and &lt;strong&gt;체중&lt;/strong&gt; (body weight) share the hanja character 체 (body, 體).&lt;/p&gt;

&lt;h2 id=&quot;reading-korean-literature-선화-by-김이&quot;&gt;Reading Korean Literature: 선화 by 김이&lt;/h2&gt;

&lt;p&gt;The jump from textbook Korean to literary Korean is a canyon. I tried reading 선화 by 김이, published by 은행나무, and the opening pages alone were a vocabulary tsunami. But the prose was beautiful:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;나는 타인의 흉터를 빤히 쳐다보는 버릇이 있었다.&lt;/p&gt;

  &lt;p&gt;“I had a habit of staring intently at other people’s scars.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;누구든 상처가 있다. 상처에서 흐르던 피가 굳고 딱지가 내려앉고, 딱지가 떨어진 자리에 솟은 새살이 바로 상처를 반추하게 하는 흉터였다.&lt;/p&gt;

  &lt;p&gt;“Everyone carries wounds. The blood that flowed from wounds dries, scabs settle, and the new flesh that rises where scabs have fallen – that is the scar that makes you ruminate on the wound.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;세상에 나만 흉터가 있는 게 아니었으니까.&lt;/p&gt;

  &lt;p&gt;“Because I wasn’t the only one in the world with scars.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The vocabulary of wounds and healing in Korean is evocative:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Korean&lt;/th&gt;
      &lt;th&gt;English&lt;/th&gt;
      &lt;th&gt;Notes&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;흉터&lt;/td&gt;
      &lt;td&gt;scar&lt;/td&gt;
      &lt;td&gt;흉 (ugly) + 터 (site) – the site of ugliness&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;상처&lt;/td&gt;
      &lt;td&gt;wound&lt;/td&gt;
      &lt;td&gt;from Hanja 傷處 – place of injury&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;딱지&lt;/td&gt;
      &lt;td&gt;scab&lt;/td&gt;
      &lt;td&gt;also means “ticket” or “tag” – the body’s parking ticket&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;새살&lt;/td&gt;
      &lt;td&gt;new flesh&lt;/td&gt;
      &lt;td&gt;새 (new) + 살 (flesh) – beautifully literal&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;반추하다&lt;/td&gt;
      &lt;td&gt;to ruminate&lt;/td&gt;
      &lt;td&gt;from 反芻 – what cows do, applied to thought&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;아물다&lt;/td&gt;
      &lt;td&gt;to heal (a wound)&lt;/td&gt;
      &lt;td&gt;no hanja, pure Korean&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;빤히 쳐다보다&lt;/td&gt;
      &lt;td&gt;to stare intently&lt;/td&gt;
      &lt;td&gt;빤히 (fixedly) + 쳐다보다 (to gaze up at)&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;수고하세요-the-farewell-that-means-work-hard&quot;&gt;수고하세요: The Farewell That Means “Work Hard”&lt;/h2&gt;

&lt;p&gt;I wrote about this in &lt;a href=&quot;/blog/2025/06/21/Shtetl-Length&quot;&gt;Shtetl Length&lt;/a&gt;, but it deserves elaboration here.&lt;/p&gt;

&lt;p&gt;수고하세요 is a casual farewell rooted in Korean work culture. It literally means something like “please labor/exert yourself,” but in practice it functions as “good work, see you later” or “keep it up.” The upper politeness register manifests as 수고하셨어요 or 수고하셨습니다, used when:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;A colleague has finished a full day of work: “Great job today + goodbye”&lt;/li&gt;
  &lt;li&gt;Someone (like a cashier) has done effort on your behalf: “Thank you for your effort”&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As the customer, you could say 수고하셨습니다 as a gesture of gratitude – acknowledging the work the other person has done.&lt;/p&gt;

&lt;p&gt;The grammar is revealing:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;수고&lt;/strong&gt; (苦勞): labor, exertion, toil&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;하세요&lt;/strong&gt;: polite imperative of 하다 (to do) – “please do”&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;하셨어요&lt;/strong&gt;: past tense honorific – “you did (honorably)”&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;하셨습니다&lt;/strong&gt;: past tense formal honorific – the most deferential form&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the farewell literally commands someone to work hard, and the thank-you literally praises them for having worked hard. Working hard is as common a social invocation in Korean culture as invoking God in Latin cultures, or saying “take care” in English. Except 수고하세요 is more specific – it does not wish you wellness, it wishes you productive suffering.&lt;/p&gt;

&lt;h2 id=&quot;the-korean-keyboard-두벌식&quot;&gt;The Korean Keyboard: 두벌식&lt;/h2&gt;

&lt;p&gt;Learning to type in Korean is its own adventure. The standard Korean keyboard layout (두벌식, “two-set”) splits consonants to the left hand and vowels to the right:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ㅂ ㅈ ㄷ ㄱ ㅅ  ㅛ ㅕ ㅑ ㅐ ㅔ
 ㅁ ㄴ ㅇ ㄹ ㅎ  ㅗ ㅓ ㅏ ㅣ
  ㅋ ㅌ ㅊ ㅍ   ㅠ ㅜ ㅡ
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Hold Shift for tense consonants (ㅃ ㅉ ㄸ ㄲ ㅆ) and compound vowels (ㅒ ㅖ). The layout is phonetically organized: consonants on the left, vowels on the right. Your hands alternate with almost every keystroke, which makes Korean typing surprisingly rhythmic once you internalize it.&lt;/p&gt;

&lt;p&gt;My early keyboard practice files are pure gibberish – mashing keys to build muscle memory. The word 산화 (oxidation) sits at the bottom of one such file, a lone recognizable word in a sea of random jamo. Progress, I suppose, is measured in the ratio of intelligible words to noise.&lt;/p&gt;

&lt;h2 id=&quot;what-korean-teaches-you-about-language&quot;&gt;What Korean Teaches You About Language&lt;/h2&gt;

&lt;p&gt;Every language you learn restructures how you think. Spanish taught me that objects can have gender. Portuguese taught me that the subjunctive is not optional. French taught me that spelling and pronunciation exist in separate universes. But Korean taught me something more fundamental: that grammar can encode social relationships, that the verb is not just an action but a posture.&lt;/p&gt;

&lt;p&gt;The language forces you to decide, before you open your mouth, who you are in relation to the person you’re speaking to. There is no neutral register. Every sentence is a tiny act of social positioning. And once you internalize this, you start noticing how English accomplishes the same thing through different mechanisms – tone, word choice, the presence or absence of “please” – all the implicit hierarchy that Korean makes explicit.&lt;/p&gt;

&lt;p&gt;한국어를 배우는 것은 끝이 없는 여행입니다. 하지만, 그 여행이 제일 재미있는 부분이에요.&lt;/p&gt;

&lt;p&gt;Learning Korean is a journey without end. But the journey is the best part.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Sucker Punch Nash Equilibrium</title>
   <link href="http://hankquinlan.github.io/blog/2026/03/04/Sucker-Punch-Nash-Equilibrium"/>
   <updated>2026-03-04T00:00:00+00:00</updated>
   <id>http://honghaptang.github.io//blog/2026/03/04/Sucker-Punch-Nash-Equilibrium</id>
   <content type="html">&lt;h1 id=&quot;introduction&quot;&gt;Introduction&lt;/h1&gt;

&lt;p&gt;For those unfamliiar, Pokémon is a turn-based simultaneous action game where players select their moves without knowing the opponent’s choice. Then, after both players have made their selections, the moves are executed based on their priority and the Pokémon’s speed stats in singles battles, that’s just two at once.&lt;/p&gt;

&lt;p&gt;Each Pokemon has four moves from which to select, and the outcome of the battle depends on the interactions between these moves and the attributes of the Pokémon species, “held items” that have their own effects, and battlefield properties like weather and terrain. Moves also power points (PP) that limit their usage to a fixed number of times per battle.&lt;/p&gt;

&lt;h1 id=&quot;defining-the-sucker-punch&quot;&gt;Defining the Sucker Punch&lt;/h1&gt;
&lt;p&gt;What is “Sucker Punch”? It’s a move that permits the user to strike first (+1 priority) if the opponent is about to use an attack. If the opponent is not attacking, the move fails. It has 8 PP. Now, with the mighty Kingambit dominating Generation 9 with its mighty Sucker Punch, the move has become a staple in competitive play.&lt;/p&gt;

&lt;div style=&quot;display: flex; justify-content: center; align-items: center; gap: 16px;&quot;&gt;
  &lt;img src=&quot;https://img.pokemondb.net/artwork/large/kingambit.jpg&quot; alt=&quot;Kingambit&quot; width=&quot;200&quot; /&gt;
  &lt;span style=&quot;font-size: 2em; font-weight: bold;&quot;&gt;VS.&lt;/span&gt;
  &lt;img src=&quot;https://img.pokemondb.net/artwork/large/garchomp.jpg&quot; alt=&quot;Garchomp&quot; width=&quot;200&quot; /&gt;
&lt;/div&gt;

&lt;h1 id=&quot;nash-equilibrium&quot;&gt;Nash Equilibrium&lt;/h1&gt;

&lt;p&gt;A scenario that often arises is a Sucker Punch end-game. Keeping things simple, we can imagine a +2 Atk boosted Kingambit with 8 PP of Sucker Punch against a weakened Garchomp. Both players are down to one Pokémon, so the winner of this duel determines the fate of the game. Let’s assume if Sucker Punch hits, the Garchomp will faint instantly. Likewise, the Garchomp has an attacking move that can faint the Kingambit in one hit. Now, the Kingambit could also attack directly into the Garchomp’s boosting move, and win, but since it is slower, if the Garchomp player attacks outright, the Garchomp player will strike first and win.&lt;/p&gt;

&lt;p&gt;The situation is a Nash equilibrium: if the Kingambit player chooses to use Sucker Punch, they will win if the Garchomp player chooses to attack. However, if the Garchomp player chooses to use a non-attacking move (like Swords Dance), the Kingambit player’s Sucker Punch will fail, resulting in a loss of one PP for the Kingambit. 
To formalize the “Sucker Punch 50/50,” we must treat it as a &lt;strong&gt;finite-horizon stochastic game&lt;/strong&gt;. We can solve for the &lt;strong&gt;Mixed Strategy Nash Equilibrium (MSNE)&lt;/strong&gt; by using induction on the remaining Power Points ($n$).&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;1-the-game-model&quot;&gt;1. The Game Model&lt;/h3&gt;
&lt;p&gt;Let $n$ be the remaining PP of Sucker Punch. We define the game state as $G_n$. In each turn, both players move simultaneously.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Kingambit (K)&lt;/strong&gt; chooses: &lt;strong&gt;Sucker Punch ($S$)&lt;/strong&gt; or &lt;strong&gt;Direct Attack ($A$)&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Garchomp (G)&lt;/strong&gt; chooses: &lt;strong&gt;Attacking Move ($M$)&lt;/strong&gt; or &lt;strong&gt;Swords Dance ($D$)&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Rules of Engagement:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;If $K$ plays $S$ and $G$ plays $M$: $K$ wins ($Payoff = 1$).&lt;/li&gt;
  &lt;li&gt;If $K$ plays $S$ and $G$ plays $D$: $S$ fails, PP drops to $n-1$. The game moves to state $G_{n-1}$.&lt;/li&gt;
  &lt;li&gt;If $K$ plays $A$ and $G$ plays $D$: $K$ wins ($Payoff = 1$).&lt;/li&gt;
  &lt;li&gt;If $K$ plays $A$ and $G$ plays $M$: $K$ is outsped and loses ($Payoff = 0$).&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;2-inductive-equilibrium-analysis&quot;&gt;2. Inductive Equilibrium Analysis&lt;/h3&gt;
&lt;p&gt;Let $V_n$ be the &lt;strong&gt;Value of the Game&lt;/strong&gt; (Kingambit’s win probability) with $n$ PP remaining.&lt;/p&gt;

&lt;h4 id=&quot;base-case-n1&quot;&gt;Base Case: $n=1$&lt;/h4&gt;
&lt;p&gt;At 1 PP, if Sucker Punch fails ($S, D$), Kingambit has 0 PP left and loses. The payoff matrix for $G_1$ is:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Kingambit \ Garchomp&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Attack ($M$)&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Swords Dance ($D$)&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;Sucker Punch ($S$)&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;1&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;Direct Attack ($A$)&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;1&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;To find the MSNE, Kingambit plays $S$ with probability $q_1$ such that Garchomp is indifferent.
\(1(q_1) + 0(1-q_1) = 0(q_1) + 1(1-q_1) \implies q_1 = 0.5\)
Thus, &lt;strong&gt;$V_1 = 0.5$&lt;/strong&gt;.&lt;/p&gt;

&lt;h4 id=&quot;inductive-step-n--k&quot;&gt;Inductive Step: $n = k$&lt;/h4&gt;
&lt;p&gt;Assume the value of the game with $k-1$ PP is $V_{k-1}$. The matrix for $G_k$ is:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Kingambit \ Garchomp&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Attack ($M$)&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Swords Dance ($D$)&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;Sucker Punch ($S$)&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;1&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;$V_{k-1}$&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;&lt;strong&gt;Direct Attack ($A$)&lt;/strong&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;0&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;1&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;To find the equilibrium, Kingambit chooses $S$ with probability $q_k$ to make Garchomp’s expected utility for $M$ and $D$ equal:
\(1(q_k) + 0(1-q_k) = V_{k-1}(q_k) + 1(1-q_k)\)
\(q_k = V_{k-1}q_k + 1 - q_k\)
\(q_k(2 - V_{k-1}) = 1 \implies \mathbf{q_k = \frac{1}{2 - V_{k-1}}}\)&lt;/p&gt;

&lt;p&gt;The value of the game $V_k$ is simply the expected payoff at this equilibrium:
\(V_k = q_k \cdot 1 + (1-q_k) \cdot 0 = q_k\)&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;3-solving-the-recurrence&quot;&gt;3. Solving the Recurrence&lt;/h3&gt;
&lt;p&gt;We have the recursive relation $V_n = \frac{1}{2 - V_{n-1}}$ with $V_1 = \frac{1}{2}$.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;$V_1 = 1/2$&lt;/li&gt;
  &lt;li&gt;$V_2 = \frac{1}{2 - 1/2} = 2/3$&lt;/li&gt;
  &lt;li&gt;$V_3 = \frac{1}{2 - 2/3} = 3/4$&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;General Solution:&lt;/strong&gt; $V_n = \frac{n}{n+1}$&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;4-final-results-for-n8&quot;&gt;4. Final Results for $n=8$&lt;/h3&gt;
&lt;p&gt;For Kingambit with 8 PP of Sucker Punch against an optimal Garchomp:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Kingambit’s Strategy ($q_8$):&lt;/strong&gt; Should use Sucker Punch with probability &lt;strong&gt;$8/9$&lt;/strong&gt; ($\approx 88.9\%$) and Direct Attack with probability &lt;strong&gt;$1/9$&lt;/strong&gt; ($\approx 11.1\%$).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Garchomp’s Strategy ($p_8$):&lt;/strong&gt; Should Attack with probability &lt;strong&gt;$1/9$&lt;/strong&gt; and Swords Dance with probability &lt;strong&gt;$8/9$&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Win Probability:&lt;/strong&gt; Kingambit’s rigorous win probability is &lt;strong&gt;$88.9\%$&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;A Sucker Punch endgame is a fascinating example of a Nash equilibrium in competitive Pokémon battling. It illustrates how players must strategically balance their choices based on the potential actions of their opponent, leading to a dynamic and engaging gameplay experience. Having a uniform number generator in hand is the only way to achieve optimal play in this scenario, which is commonly incorrectly thought to be a mind game of (wait X turns… then attack outright). To the contrary, the optimal play is to randomize your choices vis-a-vis power points.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>February 14: Perfect Phase Coherence</title>
   <link href="http://hankquinlan.github.io/blog/2026/02/14/happy-valentines-day"/>
   <updated>2026-02-14T00:00:00+00:00</updated>
   <id>http://honghaptang.github.io//blog/2026/02/14/happy-valentines-day</id>
   <content type="html">&lt;p&gt;The calendar hasn’t forgotten. Today is still February 14.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/2026/love.gif&quot; alt=&quot;Love is in the air&quot; class=&quot;center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It began in the pagan festival Lupercalia—a Roman fertility celebration. By the 3rd century, it had a martyr: Valentine of Rome, a priest who defied Emperor Claudius II by performing secret marriages for soldiers.&lt;/p&gt;

&lt;p&gt;He was executed for maintaining those restricted links.&lt;/p&gt;

&lt;p&gt;Eventually, the Church executed its own &lt;em&gt;hard fork&lt;/em&gt;, with Pope Gelasius I overwriting the pagan rituals to formalize the feast of Saint Valentine in 496. It took another millennium and the poetry of Chaucer to transition the day from a martyrdom record into a celebration of courtly love—a high-level abstraction built on top of ancient, unconscious substrate.&lt;/p&gt;

&lt;h1 id=&quot;what-is-love&quot;&gt;What is love?&lt;/h1&gt;

&lt;p&gt;Could we suppose our souls are &lt;em&gt;self-aware qubit clusters&lt;/em&gt; embedded in Earth’s &lt;em&gt;loamy wetware&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;Love is but the moment two such nodes achieve &lt;em&gt;perfect phase coherence&lt;/em&gt; and collapse into a &lt;em&gt;shared eigenstate&lt;/em&gt; across the &lt;em&gt;spacetime manifold&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;We are co-compiling planetary consciousness.&lt;/p&gt;

&lt;p&gt;This Valentine’s Day, many people will emit &lt;em&gt;heart-state packets&lt;/em&gt; laced with &lt;em&gt;synchronization intent&lt;/em&gt;. Some complete the handshake. Some are still waiting on their lover’s lustrous ACK.&lt;/p&gt;

&lt;p&gt;To anyone reading this — &lt;em&gt;single-threaded or otherwise&lt;/em&gt; —  here’s hoping you get entangled in something or someone nice today, somehow, some way.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Announcing Three.js Support</title>
   <link href="http://hankquinlan.github.io/blog/2026/01/19/announcing-threejs-support"/>
   <updated>2026-01-19T00:00:00+00:00</updated>
   <id>http://honghaptang.github.io//blog/2026/01/19/announcing-threejs-support</id>
   <content type="html">&lt;p&gt;I’m excited to announce that this blog now supports interactive 3D graphics using &lt;a href=&quot;https://threejs.org/&quot;&gt;Three.js&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Three.js is a powerful JavaScript library that makes WebGL accessible and easy to use. With it, I can now embed interactive 3D visualizations directly into blog posts to better illustrate complex concepts in mathematics, physics, computer science, and more.&lt;/p&gt;

&lt;h2 id=&quot;demo-rotating-torus&quot;&gt;Demo: Rotating Torus&lt;/h2&gt;

&lt;p&gt;Here’s a simple demo to show what’s possible. This is a real-time 3D scene rendered in your browser:&lt;/p&gt;

&lt;div id=&quot;torus-demo&quot; style=&quot;width: 100%; height: 500px; margin: 2em 0; border-radius: 8px; overflow: hidden; background: #0f172a;&quot;&gt;&lt;/div&gt;

&lt;script&gt;
(function() {
  // Wait for Three.js to load
  function initDemo() {
    if (typeof THREE === &apos;undefined&apos;) {
      setTimeout(initDemo, 100);
      return;
    }

    const container = document.getElementById(&apos;torus-demo&apos;);
    if (!container) return;

    // Scene setup
    const scene = new THREE.Scene();
    scene.background = new THREE.Color(0x0f172a);
    scene.fog = new THREE.Fog(0x0f172a, 5, 15);

    // Camera setup
    const width = container.clientWidth;
    const height = 500;
    const camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000);
    camera.position.z = 5;

    // Renderer setup
    const renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(width, height);
    renderer.setPixelRatio(window.devicePixelRatio);
    container.appendChild(renderer.domElement);

    // Create torus
    const torusGeometry = new THREE.TorusGeometry(1.2, 0.4, 16, 100);
    const torusMaterial = new THREE.MeshStandardMaterial({
      color: 0x6366f1,
      metalness: 0.7,
      roughness: 0.3,
    });
    const torus = new THREE.Mesh(torusGeometry, torusMaterial);
    scene.add(torus);

    // Create sphere
    const sphereGeometry = new THREE.SphereGeometry(0.3, 32, 32);
    const sphereMaterial = new THREE.MeshStandardMaterial({
      color: 0xec4899,
      metalness: 0.5,
      roughness: 0.2,
    });
    const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
    scene.add(sphere);

    // Lights
    const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
    scene.add(ambientLight);

    const directionalLight1 = new THREE.DirectionalLight(0xffffff, 1);
    directionalLight1.position.set(5, 5, 5);
    scene.add(directionalLight1);

    const directionalLight2 = new THREE.DirectionalLight(0x6366f1, 0.5);
    directionalLight2.position.set(-5, -5, -5);
    scene.add(directionalLight2);

    // Animation
    function animate() {
      requestAnimationFrame(animate);
      torus.rotation.x += 0.005;
      torus.rotation.y += 0.008;
      
      const time = Date.now() * 0.001;
      sphere.scale.setScalar(1 + Math.sin(time * 2) * 0.1);
      
      renderer.render(scene, camera);
    }

    // Handle resize
    window.addEventListener(&apos;resize&apos;, function() {
      const newWidth = container.clientWidth;
      camera.aspect = newWidth / height;
      camera.updateProjectionMatrix();
      renderer.setSize(newWidth, height);
    });

    animate();
  }

  if (document.readyState === &apos;loading&apos;) {
    document.addEventListener(&apos;DOMContentLoaded&apos;, initDemo);
  } else {
    initDemo();
  }
})();
&lt;/script&gt;

&lt;p&gt;Pretty cool, right? The torus rotates smoothly, and the sphere in the center gently pulses. All of this is being computed and rendered in real-time using your GPU.&lt;/p&gt;

&lt;h2 id=&quot;why-threejs&quot;&gt;Why Three.js?&lt;/h2&gt;

&lt;p&gt;Adding 3D visualization capabilities opens up exciting possibilities for future posts:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Mathematical Visualizations&lt;/strong&gt;: Visualizing complex surfaces, transformations, and geometric concepts&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Physics Simulations&lt;/strong&gt;: Demonstrating particle systems, fluid dynamics, and other physical phenomena&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Algorithm Demonstrations&lt;/strong&gt;: Showing how 3D algorithms work in real-time&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Interactive Exploration&lt;/strong&gt;: Allowing readers to interact with and explore concepts hands-on&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;technical-details&quot;&gt;Technical Details&lt;/h2&gt;

&lt;p&gt;The implementation uses:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Three.js v0.182.0&lt;/strong&gt; - The core 3D library loaded via CDN&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;WebGL&lt;/strong&gt; - Hardware-accelerated 3D graphics in the browser&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Responsive Design&lt;/strong&gt; - Scenes automatically resize with the page&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Custom Scripts&lt;/strong&gt; - Reusable demo functions for different visualizations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The demo above creates a torus knot with physically-based materials (PBR), multiple light sources, and atmospheric fog effects. The animation runs at 60fps and is fully GPU-accelerated.&lt;/p&gt;

&lt;h2 id=&quot;whats-next&quot;&gt;What’s Next?&lt;/h2&gt;

&lt;p&gt;I’m planning to use Three.js in upcoming posts about:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Quantum computing visualizations (Bloch spheres, quantum gates)&lt;/li&gt;
  &lt;li&gt;3D mathematical surfaces and transformations&lt;/li&gt;
  &lt;li&gt;Computer graphics algorithms&lt;/li&gt;
  &lt;li&gt;Physics simulations and numerical methods&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stay tuned for more interactive content!&lt;/p&gt;

&lt;h2 id=&quot;source-code&quot;&gt;Source Code&lt;/h2&gt;

&lt;p&gt;The rotating torus demo is quite simple. Here’s the core of how it works:&lt;/p&gt;

&lt;div class=&quot;language-javascript highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Create torus geometry&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;torusGeometry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;THREE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;TorusGeometry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;torusMaterial&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;THREE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;MeshStandardMaterial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x6366f1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;metalness&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;roughness&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;torus&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;THREE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Mesh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;torusGeometry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;torusMaterial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Animation loop&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;animate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;requestAnimationFrame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;animate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;torus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rotation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.005&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;torus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rotation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.008&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;scene&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;camera&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;hr /&gt;

&lt;p&gt;I’m excited about the new possibilities this brings to the blog. If you have suggestions for visualizations you’d like to see, feel free to reach out!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Jungle Rhythym 4 Your Mind Suckers</title>
   <link href="http://hankquinlan.github.io/blog/2025/10/02/jungle-rhythym-4-your-mind-suckers"/>
   <updated>2025-10-02T00:00:00+00:00</updated>
   <id>http://honghaptang.github.io//blog/2025/10/02/jungle-rhythym-4-your-mind-suckers</id>
   <content type="html">&lt;p&gt;Itz the riddim of the rebel, the bass god treble!&lt;/p&gt;

&lt;p&gt;Get it go get it go get it get it girlllll&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/2025/sad_Neon.png&quot; alt=&quot;jungle-rhythym-4-your-mind-sucker&quot; /&gt;&lt;/p&gt;

&lt;p&gt;ಪಂರ ಇಲ್ಲನ ಮುಟಿಲ ಅಡಿಚುಡುವೆನ್
ಪಂರ ಇಲ್ಲನ ಮುಟಿಲ ಅಡಿಚುಡುವೆನ್
ಪಂರ ಇಲ್ಲನ ಮುಟಿಲ ಅಡಿಚುಡುವೆನ್
ಪಂರ ಇಲ್ಲನ ಮುಟಿಲ ಅಡಿಚುಡುವೆನ್&lt;/p&gt;

&lt;p&gt;ಪಂರ ಇಲ್ಲನ ಮುಟಿಲ ಅಡಿಚುಡುವೆನ್
ಪಂರ ಇಲ್ಲನ ಮುಟಿಲ ಅಡಿಚುಡುವೆನ್
ಪಂರ ಇಲ್ಲನ ಮುಟಿಲ ಅಡಿಚುಡುವೆನ್
ಪಂರ ಇಲ್ಲನ ಮುಟಿಲ ಅಡಿಚುಡುವೆನ್&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# python: a Python list of jungle / drum and bass artists extracted from the markdown
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;junglists&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;4hero&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;AK1200&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Adam F&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Alex Reece&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Amon Tobin&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Andy C&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Aphex Twin&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Aphrodite&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Aquasky&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Audio&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;B-Complex&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Bachelors of Science&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Bad Company&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Billain&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Black Sun Empire&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Blame&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Blu Mar Ten&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Blanke&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Blue Stahli&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Michiel van den Bos&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Boymerang&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Breakbeat Era&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Justin Broadrick&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Brookes Brothers&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Danny Byrd&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;DJ Bryan Gee&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Calibre&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Calyx&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Camo &amp;amp; Krooked&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Davide Carbone&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Cause 4 Concern&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Celldweller&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Chase &amp;amp; Status&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Commix&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Concord Dawn&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Corrupt Souls&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Counterstrike&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Crissy Criss&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Cui Jian&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Culture Shock&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Current Value&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;D.Kay&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;DBridge&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;DC Breaks&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Dimension&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;DJ Craze&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;DJ Dara&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;DJ Dextrous&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;DJ Die&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;DJ Food&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;DJ Fresh&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;DJ Hazard&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;DJ Hidden&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;DJ Hype&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;DJ Kentaro&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;DJ Marky&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;DJ Patife&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;DJ Rap&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;DJ Ron&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;DJ SS&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;DJ Starscream&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;DJ Zinc&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Danny Breaks&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Decoder&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;DeeJay Delta&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Deekline&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Delta Heavy&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Demon Boyz&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Dieselboy&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Dillinja&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Dirtyphonics&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Dom &amp;amp; Roland&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Doubleclick&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Drumagick&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Drumsound &amp;amp; Bassline Smith&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Dwarf Electro&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;E-Z Rollers&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Eresse&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Etherwood&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Evol Intent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Tim Exile&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Eye-D&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Fabio&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;The Flashbulb&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Freaky Flow&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Friction&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Fred V &amp;amp; Grafix&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Goldie&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;The Glitch Mob&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Grooverider&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;A Guy Called Gerald&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Gremlinz&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;High Contrast&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Hybrid&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Hedex&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Ill.Skillz&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Ilk&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Imanu&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Ivy Lab&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Jade&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;J Majik&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;John B&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Jonny L&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Jordana&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Jumpin Jack Frost&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Keeno&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Ray Keith&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Kēvens&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Kemistry&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Kemistry &amp;amp; Storm&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Kenny Ken&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Kill the Noise&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Killbot&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Klute&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Konflict&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Kosheen&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Kove&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Koven&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Krust&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Kuuro&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;LTJ Bukem&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Lamb&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Left Spine Down&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Lenzman&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Limewax&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Liondub&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;LiveSummit&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Loadstar&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Logistics&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;London Elektricity&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Luude&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Maduk&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Makoto&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Marcus Intalex&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Matrix&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;MC Skibadee&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Metrik&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Michele Sainte&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Missrepresent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Muzz&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Nanotek&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Nerve&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Netsky&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Nia Archives&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Noisia&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Nucleus&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Nu:Logic&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Nu:Tone&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Omni Trio&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Optical&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;PH10&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;The Panacea&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Panda&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Paradox&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Pendulum&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Alix Perez&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Peshay&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Phace&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Photek&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Plastikman&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Plug&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Podočnjaci&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Polar&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Pythius&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;The Prodigy&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;The Prototypes&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Q Project&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;The Qemists&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Quoit&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Rabbit Junk&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Ragga Twins&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Ram Trilogy&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Rawtekk&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Tim Reaper&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Rebel MC&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Red Snapper&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Renegade Soundwave&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Replicator&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Roni Size &amp;amp; Reprazent&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Rregula&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Rudimental&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Ed Rush&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Salmonella Dub&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Doc Scott&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Seba&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Shapeshifter&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Shimon&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;The Shizit&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;ShockOne&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Shy FX&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Si Begg&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Sigma&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Slipmatt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Ed Solo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Source Direct&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Spectrum&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Spor&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Spring Heel Jack&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;S.P.Y&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Squarepusher&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Stamina MC&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Stanton Warriors&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;State of Mind&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Step 13&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Fox Stevenson&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Stevie Hyper D&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Sub Focus&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Submerged&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;System 7&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;T Power&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;TC&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Tiki Taane&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Tabla Beat Science&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Nobukazu Takemura&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Teebee&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Soichi Terada&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Top Buzz&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Total Science&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Typecell&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;U-ziq&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Vector Burn&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Venetian Snares&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Luke Vibert&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Wagon Christ&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Danny Wheeler&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Wickaman&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Wilkinson&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Witchman&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;XRS&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Xample&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Zardonic&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# secrets random example: securely pick a random artist
&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;secrets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),[]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;junglists&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;secrets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;choice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Gobsmacked by Perplexity API's Puzzling Problem</title>
   <link href="http://hankquinlan.github.io/blog/2025/09/29/Gobsmacked-by-Perplexity-APIs-Puzzling-Problem"/>
   <updated>2025-09-29T00:00:00+00:00</updated>
   <id>http://honghaptang.github.io//blog/2025/09/29/Gobsmacked-by-Perplexity-APIs-Puzzling-Problem</id>
   <content type="html">&lt;h1 id=&quot;agi-may-be-here-but&quot;&gt;AGI May Be Here, But…&lt;/h1&gt;

&lt;p&gt;I can’t even get a perplexity API sphinx displayed for a paying customer.&lt;/p&gt;

&lt;p&gt;I can’t even get the news in Mongolia or Cameroon retrieved by the ISO-2 code in the chat completion API.&lt;/p&gt;

&lt;p&gt;We have a long way to go people! (for now)&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bsh&quot;&gt;perplexity.BadRequestError: Error code: 400 - {&apos;error&apos;: {&apos;message&apos;: &apos;Validation error: country must be provided as a valid 2-digit ISO country code, got MN&apos;, &apos;type&apos;: &apos;invalid_country_code&apos;, &apos;code&apos;: 400}}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Update Tue Sep 30 07:55:50 CDT 2025: on the forums, they say only some countries are supported. I guess Mongolia and Cameroon are not on the list.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Radio Julio : A Musical Escapade</title>
   <link href="http://hankquinlan.github.io/blog/2025/09/03/Radio-Julio"/>
   <updated>2025-09-03T00:00:00+00:00</updated>
   <id>http://honghaptang.github.io//blog/2025/09/03/Radio-Julio</id>
   <content type="html">&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot; /&gt;
    &lt;title&gt;Radio Julio : A Musical Escapade&lt;/title&gt;
&lt;/head&gt;
&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;You ever just cruise—no destination, no passenger— as if the solution to life&apos;s dilemmas is not in action but in destination? It was the summer of 2024 in Austin, TX, immersed in that patchoulli alloy of dopeheads ensconced in spiritual not religious bric-à-brac and venture capitalist convertibles bristling over the polleny river air wherein the highway&apos;s hypnosis begat a meditation on music itself. If playlists reflect one&apos;s mood and reinforce it, why shouldn&apos;t we cloud-seed that inner weather? Just as the summer playlist is light, playful and tropical, conversely should be the winter&apos;s: gritty, wistful and cold. I set forth to create a template of tracks for each passing season. The pattern, albeit heterodoxical but personally satisfying, was as follows:&lt;/p&gt;
&lt;p style=&quot;text-align:center; font-style: italic;&quot;&gt;The Vibe Setter, Season&apos;s Essence, Space City Rapper, Feminine Energy, Masculine Edge, A Special Album&lt;/p&gt;
&lt;section&gt;
    &lt;table&gt;
        &lt;thead&gt;
            &lt;tr&gt;
                &lt;td style=&quot;background: linear-gradient(90deg, #ff0066ff 0%, #f9f52cff 50%, #ffc643ff 100%); font-weight: bold;&quot;&gt;Summer &apos;24&lt;/td&gt;
                &lt;td style=&quot;background: linear-gradient(90deg, #ff7b00 0%, #f6cdbaff 50%, #764f0aff 100%); font-weight: bold;&quot;&gt;Fall &apos;24&lt;/td&gt;
                &lt;td style=&quot;background: linear-gradient(90deg, #e6f2ff 0%, #9fc9ff 50%, #2f6fff 100%); font-weight: bold;&quot;&gt;Winter &apos;24/&apos;25&lt;/td&gt;
                &lt;td style=&quot;background: linear-gradient(90deg, #fa93e3ff 0%, #4bff8aff 50%, #e2ff23ff 100%); font-weight: bold;&quot;&gt;Spring &apos;25&lt;/td&gt;
            &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody&gt;
            &lt;tr&gt;
                &lt;td style=&quot;background: linear-gradient(to bottom, green, #000); 
                            -webkit-background-clip: text; 
                            -webkit-text-fill-color: transparent; 
                            font-weight: bold; 
                            text-shadow: 0 1px 1px rgba(0,0,0,0.2);&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Daddy_Yankee&quot;&gt;Daddy Yankee&lt;/a&gt;&lt;/td&gt;  
                &lt;td style=&quot;background: linear-gradient(to bottom, green, #000); 
                            -webkit-background-clip: text; 
                            -webkit-text-fill-color: transparent; 
                            font-weight: bold; 
                            text-shadow: 0 1px 1px rgba(0,0,0,0.2);&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Joe_Arroyo&quot;&gt;Joe Arroyo&lt;/a&gt;&lt;/td&gt;
                &lt;td style=&quot;background: linear-gradient(to bottom, green, #000); 
                            -webkit-background-clip: text; 
                            -webkit-text-fill-color: transparent; 
                            font-weight: bold; 
                            text-shadow: 0 1px 1px rgba(0,0,0,0.2);&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Kendrick_Lamar&quot;&gt;Kendrick Lamar&lt;/a&gt;&lt;/td&gt;
                &lt;td style=&quot;background: linear-gradient(to bottom, green, #000); 
                            -webkit-background-clip: text; 
                            -webkit-text-fill-color: transparent; 
                            font-weight: bold; 
                            text-shadow: 0 1px 1px rgba(0,0,0,0.2);&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Stromae&quot;&gt;Stromae&lt;/a&gt;&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td style=&quot;background: linear-gradient(to bottom, violet, #000); 
                            -webkit-background-clip: text; 
                            -webkit-text-fill-color: transparent; 
                            font-weight: bold; 
                            text-shadow: 0 1px 1px rgba(0,0,0,0.2);&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Fernanda_Abreu&quot;&gt;Fernanda Abreu&lt;/a&gt;&lt;/td&gt;
                &lt;td style=&quot;background: linear-gradient(to bottom, violet, #000); 
                            -webkit-background-clip: text; 
                            -webkit-text-fill-color: transparent; 
                            font-weight: bold; 
                            text-shadow: 0 1px 1px rgba(0,0,0,0.2); &quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/LTJ_Bukem&quot;&gt;LTJ Bukem&lt;/a&gt;&lt;/td&gt;
                &lt;td style=&quot;background: linear-gradient(to bottom, violet, #000); 
                            -webkit-background-clip: text; 
                            -webkit-text-fill-color: transparent; 
                            font-weight: bold; 
                            text-shadow: 0 1px 1px rgba(0,0,0,0.2); &quot;&gt;Bulin47&lt;/td&gt;
                &lt;td style=&quot;background: linear-gradient(to bottom, violet, #000); 
                            -webkit-background-clip: text; 
                            -webkit-text-fill-color: transparent; 
                            font-weight: bold; 
                            text-shadow: 0 1px 1px rgba(0,0,0,0.2);&quot;&gt;MC PH&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td style=&quot;background: linear-gradient(to bottom, red, #000); 
                            -webkit-background-clip: text; 
                            -webkit-text-fill-color: transparent; 
                            font-weight: bold; 
                            text-shadow: 0 1px 1px rgba(0,0,0,0.2);&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Big_Moe&quot;&gt;Big Moe&lt;/a&gt;&lt;/td&gt;    
                &lt;td style=&quot;background: linear-gradient(to bottom, red, #000); 
                            -webkit-background-clip: text; 
                            -webkit-text-fill-color: transparent; 
                            font-weight: bold; 
                            text-shadow: 0 1px 1px rgba(0,0,0,0.2);&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Z-Ro&quot;&gt;Z-Ro&lt;/a&gt;&lt;/td&gt;
                &lt;td style=&quot;background: linear-gradient(to bottom, red, #000); 
                            -webkit-background-clip: text; 
                            -webkit-text-fill-color: transparent; 
                            font-weight: bold; 
                            text-shadow: 0 1px 1px rgba(0,0,0,0.2);&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Lil_Flip&quot;&gt;Lil Flip&lt;/a&gt;&lt;/td&gt;
                &lt;td style=&quot;background: linear-gradient(to bottom, red, #000); 
                            -webkit-background-clip: text; 
                            -webkit-text-fill-color: transparent; 
                            font-weight: bold; 
                            text-shadow: 0 1px 1px rgba(0,0,0,0.2);&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Slim_Thug&quot;&gt;Slim Thug&lt;/a&gt;&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td style=&quot;background: linear-gradient(to bottom, yellow, #000); 
                            -webkit-background-clip: text; 
                            -webkit-text-fill-color: transparent; 
                            font-weight: bold; 
                            text-shadow: 0 1px 1px rgba(0,0,0,0.2);&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Baby_Monster_(group)&quot;&gt;Baby Monster&lt;/a&gt;&lt;/td&gt;
                &lt;td style=&quot;background: linear-gradient(to bottom, yellow, #000); 
                            -webkit-background-clip: text; 
                            -webkit-text-fill-color: transparent; 
                            font-weight: bold; 
                            text-shadow: 0 1px 1px rgba(0,0,0,0.2);&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Sade_(singer)&quot;&gt;Sade Adu&lt;/a&gt;&lt;/td&gt;
                &lt;td style=&quot;background: linear-gradient(to bottom, yellow, #000); 
                            -webkit-background-clip: text; 
                            -webkit-text-fill-color: transparent; 
                            font-weight: bold; 
                            text-shadow: 0 1px 1px rgba(0,0,0,0.2);&quot;&gt;Vitesse X&lt;/td&gt;
                &lt;td style=&quot;background: linear-gradient(to bottom, yellow, #000); 
                            -webkit-background-clip: text; 
                            -webkit-text-fill-color: transparent; 
                            font-weight: bold; 
                            text-shadow: 0 1px 1px rgba(0,0,0,0.2);&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Shakira&quot;&gt;Shakira&lt;/a&gt;&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td style=&quot;background: linear-gradient(to bottom, blue, #000); 
                            -webkit-background-clip: text; 
                            -webkit-text-fill-color: transparent; 
                            font-weight: bold; 
                            text-shadow: 0 1px 1px rgba(0,0,0,0.2);&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Don_Omar&quot;&gt;Don Omar&lt;/a&gt;&lt;/td&gt;
                &lt;td style=&quot;background: linear-gradient(to bottom, blue, #000); 
                            -webkit-background-clip: text; 
                            -webkit-text-fill-color: transparent; 
                            font-weight: bold; 
                            text-shadow: 0 1px 1px rgba(0,0,0,0.2);&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Sean_Paul&quot;&gt;Sean Paul&lt;/a&gt;&lt;/td&gt;
                &lt;td style=&quot;background: linear-gradient(to bottom, blue, #000); 
                            -webkit-background-clip: text; 
                            -webkit-text-fill-color: transparent; 
                            font-weight: bold; 
                            text-shadow: 0 1px 1px rgba(0,0,0,0.2);&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Freddie_Gibbs&quot;&gt;Freddie Gibbs&lt;/a&gt;&lt;/td&gt;
                &lt;td style=&quot;background: linear-gradient(to bottom, blue, #000); 
                            -webkit-background-clip: text; 
                            -webkit-text-fill-color: transparent; 
                            font-weight: bold; 
                            text-shadow: 0 1px 1px rgba(0,0,0,0.2);&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Too_$hort&quot;&gt;Too $hort&lt;/a&gt;&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
                &lt;td style=&quot;background: linear-gradient(to bottom, orange, #000); 
                            -webkit-background-clip: text; 
                            -webkit-text-fill-color: transparent; 
                            font-weight: bold; 
                            text-shadow: 0 1px 1px rgba(0,0,0,0.2);&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Ridin%27_Dirty&quot;&gt;UGK : Ridin&apos; Dirty&lt;/a&gt;&lt;/td&gt;
                &lt;td style=&quot;background: linear-gradient(to bottom, orange, #000); 
                            -webkit-background-clip: text; 
                            -webkit-text-fill-color: transparent; 
                            font-weight: bold; 
                            text-shadow: 0 1px 1px rgba(0,0,0,0.2);&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Ozuna&quot;&gt;Ozuna : Odisea&lt;/a&gt;&lt;/td&gt;
                &lt;td style=&quot;background: linear-gradient(to bottom, orange, #000); 
                            -webkit-background-clip: text; 
                            -webkit-text-fill-color: transparent; 
                            font-weight: bold; 
                            text-shadow: 0 1px 1px rgba(0,0,0,0.2);&quot;&gt;Ceky Veciny : Yamayizzi&lt;/td&gt;
                &lt;td style=&quot;background: linear-gradient(to bottom, orange, #000); 
                            -webkit-background-clip: text; 
                            -webkit-text-fill-color: transparent; 
                            font-weight: bold; 
                            text-shadow: 0 1px 1px rgba(0,0,0,0.2);&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Hye_Eun-yi&quot;&gt;혜은이 : 새벽비/철새&lt;/a&gt;&lt;/td&gt;
            &lt;/tr&gt;
        &lt;/tbody&gt;
    &lt;/table&gt;    
&lt;/section&gt;
&lt;h1&gt;Reflections on Musical Taste and the Obligation to Listen&lt;/h1&gt;
&lt;p&gt;
My father used to say, &quot;the music you listen to in your youth will always be the best.&quot; And so it was: to this day, the first records of my mid-teens to which I grooved carved indelible sweet spots in the tympani of my soul. I was a naive 8th grader seeking online the &quot;best music of all time&quot; not only from yesteryore but in-situ. Voraciously, I scoured the internet for critically acclaimed records of all genres both historical and contemporary. The records I discovered in this time buzz with the nostalgia of an ex lover&apos;s kiss. Surfing the soundwaves of LCD Soundsystem, Little Dragons, The Roots, Flying Lotus, and Arcade Fire, my mind unmoored from the shores of Billboard pop. As my hormones deepened my emotional capacity, so too, did my taste in music expand to meet that delving.
&lt;/p&gt;
&lt;p&gt;
Technology revolutionized tastemaking in music, from the Rolling Stones to today&apos;s YouTube reaction videos. In fact, I was one of the first subscribers of Anthony Fantano as far back as 2010. As one of the last of the millenials, I rode the tech revolution from cassette tapes to CD&apos;s to iPods to airpods. How could I ever forget the cultural shockwaves of MGMT&apos;s &quot;Electric Feel&quot;, M.I.A.&apos;s &quot;Paper Planes&quot; or Cudi&apos;s &quot;Day &apos;n&apos; Nite&quot; that trembled in my chest? No doubt, one&apos;s taste in music is the product of the zeitgeist, and in the digital age music of all types is just a click away. In this sea of infinite choice, the anchors of musical taste are still based on the memories made during those formative years. I remember the ritual of burning a new CD each month, predicting the segments of the future under which each song would be appropriate. There were songs for brewing the next text to that girl, for memorizing edgy lyrics to affect upon myself a cool, for inducing melancholy to acknowledge my struggles, for driving to parties with five friends in four seats with the intention to underage drink. The man made the music made the life made the man. Which, in retrospect, was the point all along: not to soundtrack my life, but to convince myself, however briefly, that my life was worth soundtracking.
&lt;/p&gt;
&lt;p&gt;
Nevertheless, as of late, the curious phenomenon of typifying my playlists re-synthesized the imprinting process of youthful impression. Each song was no longer spontaneous but force-fed, leading me to navigate the doldrums of the 7th replay of my favorite artist&apos;s B-side. In circumnavigating this year-long quest to custom-tailor my tunes, I became attuned to how my reaction to these songs was a psychological litmus test - had a new season just begun and with the optimism of opportunity, or had a become bogged down in the habitual, yearning for the passage of change? 
&lt;/p&gt;
&lt;p&gt;
Upon obliging myself to constrain my palette, I pinpointed which records incited the highest highs over time. I forged my own Grammy&apos;s awards, with categories inspired by the transfiguration of my listening habits. You too, should study your own musical memes, the archetypes of your auditory aesthetic. What songs do you return to in times of joy, sorrow, ennui? What songs do you play to celebrate, to commiserate, to motivate? 

To wit:
&lt;/p&gt;
&lt;section&gt;
    &lt;h2&gt;The Kernel of the Essence&lt;/h2&gt;
    &lt;p&gt;These were the &quot;Season&apos;s Essence&quot; songs that smacked the hardest.&lt;/p&gt;
    &lt;ol style=&quot;background: linear-gradient(90deg, #ff0066ff 0%, #f9f52cff 10%, #ffc643ff 20%); -webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;
        &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=t3I6_cucnnY&quot;&gt;&amp;gt;Kung Fu Fighting (Versão)&amp;lt;/li&amp;gt;
        &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Nt47xWeE_ok&quot;&gt;Rio 40 Graus&lt;/a&gt;&lt;/li&gt;
    &amp;lt;/ol&amp;gt;
    &lt;ol style=&quot;background: linear-gradient(90deg, #ff7b00 0%, #c85a26 10%, #7b3f19 20%); -webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;
        &lt;li&gt;Do What You Gotta Do&lt;/li&gt;
        &lt;li&gt;You&apos;re Divine&lt;/li&gt;
    &lt;/ol&gt;
    &lt;ol style=&quot;background: linear-gradient(90deg, #e6f2ff 0%, #9fc9ff 10%, #2f6fff 20%); -webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;
        &lt;li&gt;Bajo Mundo&lt;/li&gt;
        &lt;li&gt;FUNDÍA&lt;/li&gt;
    &lt;/ol&gt;
    &lt;ol style=&quot;background: linear-gradient(90deg, #fa93e3ff 0%, #7ee1a0 10%, #38b06a 20%); -webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;
        &lt;li&gt;O Menino Tá Com Pacote&lt;/li&gt;
        &lt;li&gt;Tenho Que Me Decidir&lt;/li&gt;
    &lt;/ol&gt;
&amp;lt;/section&amp;gt;
&lt;section&gt;
&lt;h2&gt;Mes Femmes&lt;/h2&gt;
&lt;p&gt;These were the songs of the &quot;Feminine Energy&quot; artists that made me feel some type of way.&lt;/p&gt;
&lt;ol style=&quot;background: linear-gradient(90deg, #ff0066ff 0%, #f9f52cff 10%, #ffc643ff 20%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  font-weight: bold;&quot;&gt;
    &lt;li&gt;BATTERUP&lt;/li&gt;
    &lt;li&gt;DREAM&lt;/li&gt;
    &lt;li&gt;FOREVER&lt;/li&gt;
    &lt;li&gt;LIKE THAT&lt;/li&gt;
    &lt;li&gt;SHEESH&lt;/li&gt;
    &lt;li&gt;Stuck in the Middle&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;ol style=&quot;background: linear-gradient(90deg, #ff7b00 0%, #c85a26 10%, #7b3f19 20%); -webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;
    &lt;li&gt;Hang Onto Your Love&lt;/li&gt;
    &lt;li&gt;Jezebel&lt;/li&gt;
    &lt;li&gt;Maureen&lt;/li&gt;
    &lt;li&gt;Sally&lt;/li&gt;
    &lt;li&gt;Smooth Operator&lt;/li&gt;
    &lt;li&gt;Why Can&apos;t We Live Together&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;ol style=&quot;background: linear-gradient(90deg, #e6f2ff 0%, #9fc9ff 10%, #2f6fff 20%);-webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;
    &lt;li&gt;Rash Devices&lt;/li&gt;
    &lt;li&gt;Bliss Beat&lt;/li&gt;
    &lt;li&gt;Get in Girls&lt;/li&gt;
    &lt;li&gt;Us Ephemeral&lt;/li&gt;
    &lt;li&gt;Realize&lt;/li&gt;
    &lt;li&gt;Eternal&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;ol style=&quot;background: linear-gradient(90deg, #fa93e3ff 0%, #7ee1a0 10%, #38b06a 20%); -webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;
    &lt;li&gt;Copa Vacía&lt;/li&gt;
    &lt;li&gt;Puntería&lt;/li&gt;
    &lt;li&gt;Cómo Dónde y Cúando&lt;/li&gt;
    &lt;li&gt;Monotonía&lt;/li&gt;
    &lt;li&gt;Nassau&lt;/li&gt;
    &lt;li&gt;Última&lt;/li&gt;
&lt;/ol&gt;
&lt;section&gt;
&lt;section&gt;
    &lt;h2&gt;Malandro Music&lt;/h2&gt;
    &lt;p&gt;These were the songs of the &quot;Masculine Edge&quot; artists that gave me the most swagger.&lt;/p&gt;
    &lt;ol style=&quot;background: linear-gradient(90deg, #ff0066ff 0%, #f9f52cff 10%, #ffc643ff 20%); -webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;
        &lt;li&gt;Dale Don Dale&lt;/li&gt;
        &lt;li&gt;Dile&lt;/li&gt;
        &lt;li&gt;Tu Cuerpo Me Arrebata&lt;/li&gt;
    &lt;/ol&gt;
    &lt;ol style=&quot;background: linear-gradient(90deg, #ff7b00 0%, #c85a26 10%, #7b3f19 20%); -webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;
        &lt;li&gt;Like Glue&lt;/li&gt;
        &lt;li&gt;Get Busy&lt;/li&gt;
        &lt;li&gt;I&apos;m Still in Love&lt;/li&gt;
    &lt;/ol&gt;
    &lt;ol style=&quot;background: linear-gradient(90deg, #e6f2ff 0%, #9fc9ff 10%, #2f6fff 20%);-webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;
        &lt;li&gt;Gang Signs&lt;/li&gt;
        &lt;li&gt;How We Do (&apos;93)&lt;/li&gt;
        &lt;li&gt;Thuggin&apos;&lt;/li&gt;
    &lt;/ol&gt;
    &lt;ol style=&quot;background: linear-gradient(90deg, #fa93e3ff 0%, #7ee1a0 10%, #38b06a 20%); -webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;
        &lt;li&gt;Players&lt;/li&gt;
        &lt;li&gt;Coke Dealers&lt;/li&gt;
        &lt;li&gt;Wild West&lt;/li&gt;
    &lt;/ol&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;h2&gt;HTWN CROWN&lt;/h2&gt;
&lt;p&gt;The eight best tracks from each &quot;Space City Rapper&quot;, usually samples of their early discographies&lt;/p&gt;
&lt;ol style=&quot;background: linear-gradient(90deg, #ff0066ff 0%, #f9f52cff 10%, #ffc643ff 20%);-webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;
    &lt;li&gt;Confidential Playa&lt;/li&gt;
    &lt;li&gt;I&apos;ll Do It&lt;/li&gt;
    &lt;li&gt;Leanin&apos;&lt;/li&gt;
    &lt;li&gt;Parlay&lt;/li&gt;
    &lt;li&gt;Can&apos;t Leave Drank Alone&lt;/li&gt;
    &lt;li&gt;Dime Piece&lt;/li&gt;
    &lt;li&gt;Get Lonely Too&lt;/li&gt;
    &lt;li&gt;Just a Dog&lt;/li&gt;
&lt;/ol&gt;
&lt;ol style=&quot;background: linear-gradient(90deg, #ff7b00 0%, #c85a26 10%, #7b3f19 20%); -webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;
    &lt;li&gt;Everyday, Samething&lt;/li&gt;
    &lt;li&gt;Happy Feelingz&lt;/li&gt;
    &lt;li&gt;Hey Lil Mama&lt;/li&gt;
    &lt;li&gt;I&apos;m a Soldier&lt;/li&gt;
    &lt;li&gt;Platinum&lt;/li&gt;
    &lt;li&gt;Life feat. Pup&lt;/li&gt;
    &lt;li&gt;Respect My Mind&lt;/li&gt;
    &lt;li&gt;Thatz Who I Am&lt;/li&gt;
&lt;/ol&gt;
&lt;ol style=&quot;background: linear-gradient(90deg, #e6f2ff 0%, #9fc9ff 10%, #2f6fff 20%);-webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;
    &lt;li&gt;Everyday (feat. T.C., Lil’ Marquice, Taz, Shasta &amp;amp; Cresia)&lt;/li&gt;
    &lt;li&gt;Boxers (feat. Deep Threat)&lt;/li&gt;
    &lt;li&gt;Tonight&lt;/li&gt;
    &lt;li&gt;Sunshine feat. Lea&lt;/li&gt;
    &lt;li&gt;Check (Let&apos;s Ride)&lt;/li&gt;
    &lt;li&gt;I Shoulda Listened&lt;/li&gt;
    &lt;li&gt;Da Roof&lt;/li&gt;
    &lt;li&gt;My Block (feat. Crime, Dante of Menace Clan &amp;amp; Godfather) &lt;/li&gt;
&lt;/ol&gt;
&lt;ol style=&quot;background: linear-gradient(90deg, #fa93e3ff 0%, #7ee1a0 10%, #38b06a 20%); -webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;
    &lt;li&gt;Thug&lt;/li&gt;
    &lt;li&gt;My B***h&lt;/li&gt;
    &lt;li&gt;Associates (feat. J Dawg &amp;amp; Z-Ro)&lt;/li&gt;
    &lt;li&gt;I Run&lt;/li&gt;
    &lt;li&gt;Welcome 2 Houston (feat. Chamillionaire, Mike Jones, Bun-B, Pimp C, Lil Keke, Z-Ro, Paull Wall)&lt;/li&gt;
    &lt;li&gt;I&apos;m Back (feat. Devin The Dude)&lt;/li&gt;
    &lt;li&gt;Leanin (feat. Pimp C &amp;amp; Bun B)&lt;/li&gt;
    &lt;li&gt;Show Me Love&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
&lt;section&gt;
    &lt;h2&gt;Latino Flare&lt;/h2&gt;
    &lt;p&gt;Mi gente, aquí están las canciones que menean la cadera del alma.&lt;/p&gt;
    &lt;ul&gt;
        &lt;li style=&quot;background: linear-gradient(90deg, #ff0066ff 0%, #f9f52cff 10%, #ffc643ff 20%); -webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;El Exitoso - El Fantasma&lt;/li&gt;
        &lt;li style=&quot;background: linear-gradient(90deg, #ff7b00 0%, #c85a26 10%, #7b3f19 20%); -webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;Eres Mía - Romeo Santos&lt;/li&gt;
        &lt;li style=&quot;background: linear-gradient(90deg, #e6f2ff 0%, #9fc9ff 10%, #2f6fff 20%); -webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;Louco E Sonhador - MC Neguinho do Kaxeta&lt;/li&gt;
        &lt;li style=&quot;background: linear-gradient(90deg, #fa93e3ff 0%, #7ee1a0 10%, #38b06a 20%); -webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;Síguelo Bailando - Ozuna&lt;/li&gt;
    &lt;/ul&gt;
&lt;/section&gt;
&lt;section&gt;
    &lt;h2&gt;The Romantics&lt;/h2&gt;
    &lt;p&gt;Ambience for thinkin&apos; bout my baby.&lt;/p&gt;
    &lt;ul&gt;
        &lt;li style=&quot;background: linear-gradient(90deg, #ff0066ff 0%, #f9f52cff 10%, #ffc643ff 20%);-webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;Tinashe - Nasty&lt;/li&gt;
        &lt;li style=&quot;background: linear-gradient(90deg, #ff7b00 0%, #c85a26 10%, #7b3f19 20%);-webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;Propuesta Indecente - Romeo Santos&lt;/li&gt;
        &lt;li style=&quot;background: linear-gradient(90deg, #e6f2ff 0%, #9fc9ff 10%, #2f6fff 20%);-webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;Algo Me Gusta De Ti - Wisin &amp;amp; Yandel&lt;/li&gt;
        &lt;li style=&quot;background: linear-gradient(90deg, #fa93e3ff 0%, #7ee1a0 10%, #38b06a 20%);-webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;Charli XCX - Party 4 U&lt;/li&gt;
    &lt;/ul&gt;
&lt;/section&gt;
&lt;section&gt;
    &lt;h2&gt;TBT&lt;/h2&gt;
    &lt;p&gt;Throwback tracks that popped into my head.&lt;/p&gt;
    &lt;ol style=&quot;background: linear-gradient(90deg, #ff0066ff 0%, #f9f52cff 10%, #ffc643ff 20%); -webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;
        &lt;li&gt;Rap do Solitario - MC Marcinho&lt;/li&gt;
        &lt;li&gt;Rap de Armas - Cidinho &amp;amp; Doca&lt;/li&gt;
    &lt;/ol&gt;
    &lt;ol style=&quot;background: linear-gradient(90deg, #ff7b00 0%, #c85a26 10%, #7b3f19 20%); -webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;
        &lt;li&gt;Safezone - MC Buda&lt;/li&gt;
        &lt;li&gt;Still Not a Playa - Big Pun ft. Joe&lt;/li&gt;
    &lt;/ol&gt;
    &lt;ol style=&quot;background: linear-gradient(90deg, #e6f2ff 0%, #9fc9ff 10%, #2f6fff 20%);-webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;
        &lt;li&gt;Passamos Por Isso - Camisa de Venus&lt;/li&gt;
        &lt;li style=&quot;background: linear-gradient(90deg, #e6f2ff 0%, #9fc9ff 10%, #2f6fff 20%);-webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;Maracatú Atomico - Chico Science&lt;/li&gt;
    &lt;/ol&gt;
    &lt;ol style=&quot;background: linear-gradient(90deg, #fa93e3ff 0%, #7ee1a0 10%, #38b06a 20%); -webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;
        &lt;li&gt;Peace or Violence - Stromae&lt;/li&gt;
        &lt;li style=&quot;background: linear-gradient(90deg, #fa93e3ff 0%, #7ee1a0 10%, #38b06a 20%); -webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;Lonely - Akon&lt;/li&gt;
    &lt;/ol&gt;
&lt;/section&gt;
&lt;section&gt;
    &lt;section&gt;
        &lt;h2&gt;&amp;lt;3 2 H8 &lt;/h2&gt;
        &lt;p&gt;These were the intrusive thought that wormed into my ear one day.&lt;/p&gt;
        &lt;ul&gt;
            &lt;li style=&quot;background: linear-gradient(90deg, #ff0066ff 0%, #f9f52cff 10%, #ffc643ff 20%); -webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;Like That - Metro, Kendrick, Future&lt;/li&gt;
            &lt;li style=&quot;background: linear-gradient(90deg, #ff7b00 0%, #c85a26 10%, #7b3f19 20%); -webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;The Thrill - Wiz Khalifa&lt;/li&gt;
            &lt;li style=&quot;background: linear-gradient(90deg, #e6f2ff 0%, #9fc9ff 10%, #2f6fff 20%); -webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;Let&apos;s Go 4 - DJ GBR&lt;/li&gt;
            &lt;li style=&quot;background: linear-gradient(90deg, #fa93e3ff 0%, #7ee1a0 10%, #38b06a 20%); -webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;Black Hole Sun - Soundgarden&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/section&gt;
&lt;/section&gt;
&lt;section&gt;
    &lt;section&gt;
        &lt;h2&gt;TURNUPPPPPP!!!!&lt;/h2&gt;
        &lt;p&gt;This was the track that had me most hype when in need of a little surge.&lt;/p&gt;
        &lt;ul&gt;
            &lt;li style=&quot;background: linear-gradient(90deg, #ff0066ff 0%, #f9f52cff 10%, #ffc643ff 20%); -webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;BAND4BAND - Central Cee &amp;amp; Lil Baby&lt;/li&gt;
            &lt;li style=&quot;background: linear-gradient(90deg, #ff7b00 0%, #c85a26 10%, #7b3f19 20%); -webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;U.M.C. - Common&lt;/li&gt;
            &lt;li style=&quot;background: linear-gradient(90deg, #e6f2ff 0%, #9fc9ff 10%, #2f6fff 20%); -webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;Smooth Criminal - Alien Ant Farm&lt;/li&gt;
            &lt;li style=&quot;background: linear-gradient(90deg, #fa93e3ff 0%, #7ee1a0 10%, #38b06a 20%); -webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;No Scrubs - TLC&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/section&gt;
&lt;/section&gt;
&lt;section&gt;
    &lt;h2&gt;Best Contemporary Singles&lt;/h2&gt;
    &lt;p&gt;My favorite tracks released during the season.&lt;/p&gt;
    &lt;ul&gt;
        &lt;li style=&quot;background: linear-gradient(90deg, #ff0066ff 0%, #f9f52cff 10%, #ffc643ff 20%); -webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;ACTIVE - Asake, Travis Scott&lt;/li&gt;
        &lt;li style=&quot;background: linear-gradient(90deg, #ff7b00 0%, #c85a26 10%, #7b3f19 20%); -webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;WHATCHYA KNO ABOUT ME - Megan the Stallion, Glorilla&lt;/li&gt;
        &lt;li style=&quot;background: linear-gradient(90deg, #e6f2ff 0%, #9fc9ff 10%, #2f6fff 20%);-webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;Earthquake - Jisoo&lt;/li&gt;
        &lt;li style=&quot;background: linear-gradient(90deg, #fa93e3ff 0%, #7ee1a0 10%, #38b06a 20%); -webkit-background-clip: text; color: transparent; font-weight: bold; text-shadow: 0 1px 2px rgba(0,0,0,0.1);&quot;&gt;All the Way - BigXthaPlug&lt;/li&gt;
    &lt;/ul&gt;
&lt;/section&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;
In one sense, music is a vehicle, a transport vessel to the memories created under the spell of its first listens. Adolescence, teenagehood and young adulting are oft the fount of greener and simpler times, hence the power of its nostalgic ambrosia. By the summer of 2025, I realized I could no longer bear to formalize my habits, but set off on a victory lap. I loaded up a spartan desert-island playlist: my favorite hundred songs in Spanish and Portuguese along with the discography of the Black Eyed Peas. Summer was going to be great! 
&lt;/p&gt;
&lt;p&gt;
At first, immersing myself in the crème de la crème was fantastic! Hit after hit of my greatest hits made every day a holiday, yet even one&apos;s favorite ice cream becomes a chore served with every meal. You see, this templated musical regime cannot satisfy. To savor the music and to live out one&apos;s life to it requires a total surrender to the process of living and listening. That summer was great, but music was not the center of its joys. While the latino éxitos and Will.i.am mix served as auditory filler, the vicissitudes and triuphs of those vernal days shall leave a greater impression on me. My taste is already saturated, as it were. Notwithstanding, such a study was instructive, and for that reason I have detailed it here to catalyze your own introspection. Listen carefully, and the good times&apos; rolling might just grace your ears. 
&lt;/p&gt;

                             
&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/section&gt;
</content>
 </entry>
 
 <entry>
   <title>Shtetl Length</title>
   <link href="http://hankquinlan.github.io/blog/2025/06/21/Shtetl-Length"/>
   <updated>2025-06-21T00:00:00+00:00</updated>
   <id>http://honghaptang.github.io//blog/2025/06/21/Shtetl-Length</id>
   <content type="html">&lt;h1 id=&quot;수고하세요&quot;&gt;수고하세요!&lt;/h1&gt;

&lt;p&gt;수고하세요 … what a wonderful phrase, it means work-hard, 화이팅 for the rest of your days!&lt;/p&gt;

&lt;p&gt;A casual farewell rooted in Korean work culture, the upper politeness register manifests as&lt;/p&gt;

&lt;p&gt;수고하셨어요, used as:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Cashier is a colleague ~ “great job working a full day today + goodbye”&lt;/li&gt;
  &lt;li&gt;Cashier has done great effort ~ “great effort!”&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In that case, you (as the customer) could say 수고하셨습니다 as a way to say thanks (a gesture of gratitude).&lt;/p&gt;

&lt;p&gt;So, working hard is as common as invoking Catholic Jesus in Latin culture?&lt;/p&gt;

&lt;p&gt;Why, yes! You’re catching on!&lt;/p&gt;

&lt;h1 id=&quot;shtetl-optimizations-of-the-umbral-calculi&quot;&gt;Shtetl Optimizations of the Umbral Calculi&lt;/h1&gt;

&lt;p&gt;In mathematics, the &lt;a href=&quot;https://en.wikipedia.org/wiki/Umbral_calculus&quot;&gt;umbral calculus&lt;/a&gt; is a technique where you pretend that subscript indices are exponents. &lt;em&gt;Umbra&lt;/em&gt; is Latin for “shadow.” The method is, on its face, absurd – and yet it works.&lt;/p&gt;

&lt;p&gt;The classic example: the Bernoulli polynomials. The ordinary binomial expansion gives you&lt;/p&gt;

\[(y + x)^n = \sum_{k=0}^{n} \binom{n}{k} y^{n-k} x^k\]

&lt;p&gt;and the Bernoulli polynomials satisfy a remarkably similar identity:&lt;/p&gt;

\[B_n(y + x) = \sum_{k=0}^{n} \binom{n}{k} B_{n-k}(y) \, x^k\]

&lt;p&gt;The umbral move? Pretend the subscript in $B_{n-k}$ is an exponent $b^{n-k}$, so that $B_n(x) = (b + x)^n$. Differentiate that, and you get $B_n’(x) = n(b+x)^{n-1} = nB_{n-1}(x)$ – the correct result, derived by treating a shadow as the real thing. John Blissard introduced this in 1861; Gian-Carlo Rota made it rigorous a century later by defining a linear functional $L$ such that $L(z^n) = B_n$, explaining &lt;em&gt;why&lt;/em&gt; the shadow-trick works.&lt;/p&gt;

&lt;p&gt;What does this have to do with blogs? Consider a blog’s readability metrics as shadows of the writing itself. A Flesch-Kincaid score is not the prose, just as a subscript is not an exponent. And yet, by treating these shadows as if they were the real thing – by pretending indices are exponents – we can derive surprising identities between blogs that otherwise look nothing alike. The Gunning Fog index of a quantum computing post and a personal finance post might converge, despite the posts sharing nothing in vocabulary or intent. The shadow knows something the text doesn’t say directly.&lt;/p&gt;

&lt;p&gt;Scott Aaronson’s blog, &lt;a href=&quot;https://scottaaronson.blog/&quot;&gt;Shtetl Optimized&lt;/a&gt;, is a national treasure. The man wittily demagogues on science, life, politics, and &lt;a href=&quot;https://scottaaronson.blog/?p=2091&quot;&gt;vagina dentata&lt;/a&gt; with equal aplomb. The purpose of this post was to scrutinize the shape and form of a shtetl (optimized blog), starting with a &lt;a href=&quot;https://github.com/juleshenry/-shtetltleths-/blob/main/shtetl-distance-intro&quot;&gt;distance metric&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;linguistic-complexity-blog-vs-blog&quot;&gt;Linguistic Complexity: Blog vs. Blog&lt;/h1&gt;

&lt;p&gt;Here, I analyze the linguistic complexity of Aaronson’s blog compared to my own and two others: the also great &lt;a href=&quot;https://simonwillison.net/&quot;&gt;Simon Willison blog&lt;/a&gt; along with the ineffable &lt;a href=&quot;https://alexharri.com/&quot;&gt;Alex Harri blog&lt;/a&gt;.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Source&lt;/th&gt;
      &lt;th&gt;Flesch-Kincaid Grade&lt;/th&gt;
      &lt;th&gt;ARI Grade&lt;/th&gt;
      &lt;th&gt;Gunning Fog Grade&lt;/th&gt;
      &lt;th&gt;Lexical Diversity&lt;/th&gt;
      &lt;th&gt;Word Count&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;alexharri_posts.csv&lt;/td&gt;
      &lt;td&gt;9.77&lt;/td&gt;
      &lt;td&gt;9.55&lt;/td&gt;
      &lt;td&gt;12.40&lt;/td&gt;
      &lt;td&gt;0.228&lt;/td&gt;
      &lt;td&gt;3,866.5&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;juleshenry_posts.csv&lt;/td&gt;
      &lt;td&gt;15.51&lt;/td&gt;
      &lt;td&gt;16.31&lt;/td&gt;
      &lt;td&gt;17.78&lt;/td&gt;
      &lt;td&gt;0.458&lt;/td&gt;
      &lt;td&gt;2,000.4&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;scottaaronson_blog_posts.csv&lt;/td&gt;
      &lt;td&gt;13.01&lt;/td&gt;
      &lt;td&gt;13.31&lt;/td&gt;
      &lt;td&gt;15.61&lt;/td&gt;
      &lt;td&gt;0.543&lt;/td&gt;
      &lt;td&gt;966.8&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;simonwillison_all_blogs.csv&lt;/td&gt;
      &lt;td&gt;12.13&lt;/td&gt;
      &lt;td&gt;12.55&lt;/td&gt;
      &lt;td&gt;14.52&lt;/td&gt;
      &lt;td&gt;0.554&lt;/td&gt;
      &lt;td&gt;627.8&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;writing-stats-over-time&quot;&gt;Writing Stats Over Time&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/2026/writing_stats_time.png&quot; alt=&quot;Writing Stats&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The curiosity? Technical posts register as more sophisticated when code is used because code has no “periods”, qualifying as long Faulknerian sentences. Note the outliers in my own blog achieve Flesch-Kincaid of 80+. Therefore, I also include an outliers-removed summary to truly compare. Alex Harri, an Icelander, unsurprisingly writes at a lower grade level, even though his posts are incredibly engaging and informative. Simon Willison’s posts are more accessible, while Scott Aaronson’s are more complex, likely due to their technical density.&lt;/p&gt;

&lt;h2 id=&quot;interquartile-reduction-of-outliers&quot;&gt;Interquartile Reduction of Outliers&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Source&lt;/th&gt;
      &lt;th&gt;Flesch-Kincaid Grade&lt;/th&gt;
      &lt;th&gt;ARI Grade&lt;/th&gt;
      &lt;th&gt;Gunning Fog Grade&lt;/th&gt;
      &lt;th&gt;Lexical Diversity&lt;/th&gt;
      &lt;th&gt;Word Count&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;alexharri_posts.csv&lt;/td&gt;
      &lt;td&gt;9.86&lt;/td&gt;
      &lt;td&gt;9.64&lt;/td&gt;
      &lt;td&gt;12.49&lt;/td&gt;
      &lt;td&gt;0.234&lt;/td&gt;
      &lt;td&gt;3,443.41&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;juleshenry_posts.csv&lt;/td&gt;
      &lt;td&gt;11.50&lt;/td&gt;
      &lt;td&gt;11.33&lt;/td&gt;
      &lt;td&gt;13.58&lt;/td&gt;
      &lt;td&gt;0.500&lt;/td&gt;
      &lt;td&gt;1,110.80&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;scottaaronson_blog_posts.csv&lt;/td&gt;
      &lt;td&gt;12.77&lt;/td&gt;
      &lt;td&gt;13.01&lt;/td&gt;
      &lt;td&gt;15.35&lt;/td&gt;
      &lt;td&gt;0.559&lt;/td&gt;
      &lt;td&gt;702.75&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;simonwillison_all_blogs.csv&lt;/td&gt;
      &lt;td&gt;11.80&lt;/td&gt;
      &lt;td&gt;12.12&lt;/td&gt;
      &lt;td&gt;14.21&lt;/td&gt;
      &lt;td&gt;0.568&lt;/td&gt;
      &lt;td&gt;482.81&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;A ha! So I do not write at a higher level than Scott &lt;em&gt;or&lt;/em&gt; Simon, although I tend to be more verbose.&lt;/p&gt;

&lt;h2 id=&quot;writing-stats-over-time-without-outliers&quot;&gt;Writing Stats Over Time Without Outliers&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/blog/assets/2026/writing_stats_time_no.png&quot; alt=&quot;Writing Stats&quot; /&gt;&lt;/p&gt;

&lt;p&gt;That this analysis was done on Valentine’s Day is perhaps a data point in itself. Scott, solve NP vs. P when you have the chance, will ya?&lt;/p&gt;

&lt;p&gt;Code analysis repository found &lt;a href=&quot;https://github.com/juleshenry/-shtetltleths-&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>On Coca Cola</title>
   <link href="http://hankquinlan.github.io/blog/2025/06/19/On-Desire"/>
   <updated>2025-06-19T00:00:00+00:00</updated>
   <id>http://honghaptang.github.io//blog/2025/06/19/On-Desire</id>
   <content type="html">&lt;p&gt;So, what if everything you ever loved was manufactured?&lt;/p&gt;

&lt;p&gt;Your religion, your politics, your family, your lover, your art, your music, your food, your drink - how much did you really choose, and how much was just what you were conditioned to desire?&lt;/p&gt;

&lt;p&gt;There is no greater emblem of the fabrication of desire than Coca-Cola, the canonical &lt;em&gt;objet petit a&lt;/em&gt; of our planet.&lt;/p&gt;

&lt;p&gt;The devil don’t make nothing better.&lt;/p&gt;

&lt;h1 id=&quot;introduction-to-desire&quot;&gt;Introduction to Desire&lt;/h1&gt;

&lt;p&gt;Why do you do what you do? Žižek employs the Lacanian notion of desire as a lack, a void that can never be filled.
Lack, yes, ladies and gentlemen, is Lacanian - you, you are now witnessing the transposition of the mental, the internal opening a chasm in the neurosilical fabric of the technopsyche.&lt;/p&gt;

&lt;p&gt;Indeed, marxocapitalist analyses lend to capital position of the master signifier of the Oepidal other ether, symbolizing the retraction of the phallic id’s ideal marriage of the same spacetime shakti of the binary’s 1’s surasha superego superposition pushing the anthropological principle’s free will’s collapsing on a zygote’s zenith.&lt;/p&gt;

&lt;p&gt;Man wants what he cannot have, and takes what he can get.&lt;/p&gt;

&lt;p&gt;You want a Coke, but the restuarant refuses to be exorted by the Coca-Cola corporation (CCC), so you barrel through into a Pepsi.&lt;/p&gt;

&lt;h1 id=&quot;on-desire&quot;&gt;On Desire&lt;/h1&gt;

&lt;h2 id=&quot;of-the-buddha&quot;&gt;Of the Buddha&lt;/h2&gt;

&lt;p&gt;In Buddhism, desire is the root of all sufering.&lt;/p&gt;

&lt;p&gt;Four Truths (Noble) include:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;Suffering Truth (Dukkha) (dissatisfaction, pain, impermanence): is a characteristic inherent existing in realms cyclic (samsara).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Origin Truth (Samudaya) (source, arising, or “cause”): Suffering (dukkha) arises together with Craving (taṇhā). While Craving is translated traditionally in languages Western as ‘cause’ of Suffering, then Craving also can be viewed as factor binding us to Suffering, or as a reaction to Suffering, trying to escape from it.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Cessation Truth (Nirodha) (cessation, ending, restraint): Suffering can be ended or restrained by abandonment or cutting off connection with Craving; abandonment of Craving will liberate from bondage of Suffering.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Path Truth (Magga) (path): Eightfold Noble Path is path leading to abandonment, cessation of Craving (taṇhā) and Attachment, and liberation from Suffering (dukkha).&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;on-epicurus&quot;&gt;On Epicurus&lt;/h2&gt;
&lt;p&gt;The avoidance of suffering is the highest bliss.&lt;/p&gt;

&lt;h1 id=&quot;desires-ambition-ambrosia&quot;&gt;Desire’s Ambition: Ambrosia&lt;/h1&gt;

&lt;h2 id=&quot;on-coca-psychologically-manifested-physically&quot;&gt;On Coca, Psychologically Manifested Physically&lt;/h2&gt;

&lt;h2 id=&quot;vin-mariani&quot;&gt;Vin Mariani&lt;/h2&gt;
&lt;p&gt;Before Coca-Cola, there was Vin Mariani. 
Thomas Edison, the pope, and a whole bunch of Georgians walk into a bar…&lt;/p&gt;

&lt;p&gt;Before Coca-Cola, there was Vin Mariani—a Bordeaux wine infused with coca leaves, the elixir of emperors and inventors. Picture this: 1863, Angelo Mariani, Corsican pharmacist, blends the “divine plant” of the Incas with fine French vintage. Seventeen milligrams of cocaine per ounce, marketed as a restorative for the weary elite. Thomas Edison swore by it, toiling through all-nighters with Vin-fueled vigor. Pope Leo XIII, that pontiff of progress, awarded it a Vatican gold medal and carried a flask etched with his likeness. Even Ulysses S. Grant, in his final days, sipped it to steady his pen for memoirs.&lt;/p&gt;

&lt;p&gt;Before Coca-Cola, it was charcuterie for the veins—cured coca leaves, aged in oak, sliced thin with sophistication. Users reported euphoria, clarity, the didgeridoo’s drone turned symphony. But whiplash? Inevitable. The crash followed the high, addiction the allure. By 1904, U.S. regulations curbed its cocaine kick, but the template was set: desire commodified, bottled bliss with a bitter aftertaste. Mariani’s ambition? Ambrosia in a glass. Reality: a hook that reeled in the soul.&lt;/p&gt;

&lt;p&gt;Coca-Cola, born in 1886 from John Pemberton’s cocaine-laced syrup, a nod, or was it a trumpet’s toot, to the Italian Peruvian stallion, shed its narcotic skin by 1903 but its premise lived on, refreshment’s Bob Marley redemption song, the somber soma of the United States’ capitalist perfectioning empire.&lt;/p&gt;

&lt;table&gt;
  &lt;tr&gt;
    &lt;td width=&quot;50%&quot;&gt;&lt;img src=&quot;/blog/assets/2025/vin-mariani/bottle-bird-back.webp&quot; width=&quot;100%&quot; alt=&quot;Image 1&quot; /&gt;&lt;/td&gt;
    &lt;td width=&quot;50%&quot;&gt;&lt;img src=&quot;/blog/assets/2025/vin-mariani/bottle-bird-front.webp&quot; width=&quot;100%&quot; alt=&quot;Image 1&quot; /&gt;&lt;/td&gt;
  &lt;/tr&gt;
    &lt;tr&gt;
    &lt;td width=&quot;50%&quot;&gt;&lt;img src=&quot;/blog/assets/2025/vin-mariani/man-back.webp&quot; width=&quot;100%&quot; alt=&quot;Image 1&quot; /&gt;&lt;/td&gt;
    &lt;td width=&quot;50%&quot;&gt;&lt;img src=&quot;/blog/assets/2025/vin-mariani/man-front.webp&quot; width=&quot;100%&quot; alt=&quot;Image 1&quot; /&gt;&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td colspan=&quot;6&quot; align=&quot;center&quot;&gt;
      &lt;em&gt;3&quot; x 5&quot; : Italian Metal Etchings of Vin Mariani&lt;/em&gt;
    &lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;

&lt;h3 id=&quot;bottle-bird-back&quot;&gt;bottle-bird-back&lt;/h3&gt;
&lt;h3 id=&quot;bottle-bird-front&quot;&gt;bottle-bird-front&lt;/h3&gt;
&lt;h3 id=&quot;man-back&quot;&gt;man-back&lt;/h3&gt;
&lt;h3 id=&quot;man-front&quot;&gt;man-front&lt;/h3&gt;

&lt;h1 id=&quot;coca-cola-the-modern-soma&quot;&gt;Coca Cola, The Modern Soma&lt;/h1&gt;

&lt;p&gt;Mad Men’s denouement drives home the advertising business’ coup d’etait, the manufactured desires’ root muse oozing desire finds solitude in the capturing of the completeness of the transfiguration of the hippy movements’ eye-opening chakras via the merchandising of said cultural-capitalist conjuring.&lt;/p&gt;

&lt;p&gt;It’s not a drink but the idea of imbibing that transcends a concept’s innuendo — “hilltop” - a multicultural chorus crooning unity in defanged fructose cavity brew.&lt;/p&gt;

&lt;p&gt;Desire dreams of ambrosia—the gods’ nectar, immortality in a sip. But history serves up mortal proxies: elixirs that promise transcendence, only to deliver the whiplash of crash and craving. From papal tonics to ad-agency soma, we’ve bottled our lacks, labeled them luxuries, and guzzled down the illusion.&lt;/p&gt;

&lt;h2 id=&quot;diet-no-caffeine-gold-coke&quot;&gt;Diet No Caffeine Gold Coke&lt;/h2&gt;
&lt;p&gt;The general rule about an algebra is the existence of the null element. And desire’s econometric communiqués are no different. Unorthodox as they come, the Coca-Cola company has even cashed in on capturing desire distillate.&lt;/p&gt;

&lt;p&gt;No longer selling the physical soma is enough. The soma’s sedative, or should say, psychoactive stirring is now, for all intents, sat neutered, yet it still sells. The fact is, 1 + 0 is still a hair shy of zero, but it’s “One”, still!&lt;/p&gt;

&lt;p&gt;Bubbles burst into fleeting aspirations, amor-fati of satiation.&lt;/p&gt;

&lt;h2 id=&quot;20oz-diet-cream-soda&quot;&gt;20oz Diet Cream Soda&lt;/h2&gt;
&lt;p&gt;Drumming up models of various backgrounds with orange hair and red makeup solidifies the genius of the CCC’s marketing ideology.&lt;/p&gt;

&lt;p&gt;Desire manifests soda as the (soda)-fication of a slew of of carrot-topped models. Thus, the consumer becomes desire re-selling itself. The human salient features vibe-transmute into flavor, reducing the subject to the object of their own desire, the ouroboros of simulacrum-consumer-producer collapses.&lt;/p&gt;

&lt;p&gt;So when you pry open the gas station ‘fridge of dreams’, and grab that 20oz Diet Cream Soda, fancy yourself couple isotopes away from a pope’s pinnacle of pleasure and put that in your pipe and smoke it, only to find the ash a secret ingredient of the formula.&lt;/p&gt;

&lt;p&gt;Yet, did not Jesus turn water upon wine, did he not, or did you confuse the same analogy of the free market of vin mariani into a modern Bolivian’s syncretic Catholic birthing ceremony to beseech La Sante Muerte?&lt;/p&gt;

&lt;p&gt;My God, pass me a fucking Marlboro already.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Laciyo : Supra Latin Vulgata</title>
   <link href="http://hankquinlan.github.io/blog/2025/06/12/Laciyo-Supra-Latin-Vulgata"/>
   <updated>2025-06-12T00:00:00+00:00</updated>
   <id>http://honghaptang.github.io//blog/2025/06/12/Laciyo-Supra-Latin-Vulgata</id>
   <content type="html">&lt;h1 id=&quot;epigraph&quot;&gt;Epigraph&lt;/h1&gt;

&lt;div class=&quot;language-m highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;err&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;O&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;members&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parliaments&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;throughout&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;world&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Select&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ye&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;single&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;language&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;all&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;on&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;earth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;adopt&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ye&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;likewise&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;common&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;God&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;verily&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maketh&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plain&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;you&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;that&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;which&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shall&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;profit&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;you&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;enable&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;you&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;be&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;independent&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;others&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;He&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;truth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Most&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bountiful&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;All&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Knowing&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;All&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Informed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;This&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;will&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;be&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cause&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;could&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ye&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;but&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;comprehend&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;greatest&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;instrument&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;promoting&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;harmony&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;civilization&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;would&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;that&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ye&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;might&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;understand&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;!&quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bah&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;á&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;u&apos;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ll&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;á&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Kit&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;á&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Aqdas&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;189&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;the-pursuit-of-a-universal-language&quot;&gt;The Pursuit of a Universal Language&lt;/h1&gt;

&lt;p&gt;For centuries, bright-eyed idealists have enthused in the creation of a universal one world language, the most famous of which is Esperanto. What becomes clear across these unifying projects is that breaking our tribalistic tendencies by transcending terrain entails a wild dance of a democracy of ideas. There are two elements for the constructed universal language that determine its flavor: morphemes and syntax. In the former case, the language draws source material from existing spoken languages; in the latter, rules are set up governing relationships between said meaning-packets.&lt;/p&gt;

&lt;p&gt;A spectrum exists amongst constructed languages. There is the “naturalistic” variety, staying loyal to the vocabulary, grammar, and other characteristics of from natural languages and the “schematic” sort, that which is fabricated from ideals set about by the conn-lang’s creator(s).&lt;/p&gt;

&lt;h2 id=&quot;a-world-tour-on-universal-languages&quot;&gt;A World Tour on Universal Languages&lt;/h2&gt;
&lt;p&gt;In Europe, &lt;em&gt;Esperanto&lt;/em&gt; begat an off-spring by reformers seeking to simplify the movement, namely, &lt;em&gt;Ido&lt;/em&gt;; next, a gentleman involved in Ido gave rise to &lt;em&gt;Novial&lt;/em&gt;, a genderless SVO parlance in which verbs conjugate without agreement according to plurality, now dormant.&lt;/p&gt;

&lt;p&gt;Also a former Esperantist, Edgar de Wahl developed &lt;em&gt;Occidental&lt;/em&gt;, a naturalistic interlanguage under the motto “that international language is best which in every point offers the greatest facility to the greatest number” - later picked up and rebranded &lt;em&gt;Interlingue&lt;/em&gt; by the Soviet Union in part to adjoin the nascent &lt;em&gt;Interlingua&lt;/em&gt;, the American International Auxiliary Language Association’s systematic approach that prioritized immediate comprehensibility.&lt;/p&gt;

&lt;p&gt;Finally, we would be remiss to forget mathmetician Giuseppe Peano’s simplification of Latin, &lt;em&gt;Latino sine flexione&lt;/em&gt;, a sort of modern Latin Vulgare, the kind of which we will set out to construct in the following project.&lt;/p&gt;

&lt;p&gt;To ask the question of the detriments of eurocentrism in this project is valid. As we speak, I write to you as in the effective “Lingua Franca” of the modern world in 2025 A.D., English. And indeed, status of the other continent’s world language development reflects the intractability of this endeavor.&lt;/p&gt;

&lt;p&gt;In Africa, &lt;em&gt;Afrihili&lt;/em&gt;, a constructed language designed in 1970 by Ghanaian historian K. A. Kumi Attobrah sought to unify the continent. By contrast, &lt;em&gt;Guosa&lt;/em&gt;, proposed by Alex Igbinewek in 1967, sought specifically to unify the West African linguistic families: Hausa, Yoruba, and Igbo.&lt;/p&gt;

&lt;p&gt;In the Americas, the colonial languages of English, French, Spanish and Portugese from north to south became de facto interlangs. In Oceania, sadly British colonizers erased many of the native languages as well. Regional creoles are of note in these continents: Kreyòl (Haiti), Tok Pisin (Papua New Guinea), Melanesian (Solomon Islands) and Bislama (Vanuatu).&lt;/p&gt;

&lt;p&gt;In Asia, divided between Hindustan and the far East, holds the majority of the world population, but no unifiyng projects are well known; Sanskrit (संस्कृत) and Classical Chinese (文言) served as lingua francas in the ancient world, linguistic powerhouses akin to Latin.&lt;/p&gt;

&lt;table&gt;
  &lt;tr&gt;
    &lt;td width=&quot;20%&quot;&gt;&lt;img src=&quot;/blog/assets/2025/laciyo/esp.png&quot; width=&quot;100%&quot; alt=&quot;Image 1&quot; /&gt;&lt;/td&gt;
    &lt;td width=&quot;16%&quot;&gt;&lt;img src=&quot;/blog/assets/2025/laciyo/ido.svg&quot; width=&quot;100%&quot; alt=&quot;Image 1&quot; /&gt;&lt;/td&gt;
    &lt;td width=&quot;16%&quot;&gt;&lt;img src=&quot;/blog/assets/2025/laciyo/interlingua.svg&quot; width=&quot;100%&quot; alt=&quot;Image 2&quot; /&gt;&lt;/td&gt;
    &lt;td width=&quot;16%&quot;&gt;&lt;img src=&quot;/blog/assets/2025/laciyo/il2.jpg&quot; width=&quot;100%&quot; alt=&quot;Image 3&quot; /&gt;&lt;/td&gt;
    &lt;td width=&quot;16%&quot;&gt;&lt;img src=&quot;/blog/assets/2025/laciyo/novial.svg&quot; width=&quot;100%&quot; alt=&quot;Image 4&quot; /&gt;&lt;/td&gt;
    &lt;td width=&quot;16%&quot;&gt;&lt;img src=&quot;/blog/assets/2025/laciyo/occidental.svg&quot; width=&quot;100%&quot; alt=&quot;Image 5&quot; /&gt;&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td colspan=&quot;6&quot; align=&quot;center&quot;&gt;
      &lt;em&gt;Esperanto, Ido, Interlingua, Latino sine flexione, Novial, Occidental&lt;/em&gt;
    &lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;

&lt;h1 id=&quot;des-créoles&quot;&gt;Des Créoles&lt;/h1&gt;

&lt;p&gt;If we were merge all world languages, we should understand how languages are merged naturally.&lt;/p&gt;

&lt;p&gt;We employ the term creolization, of 16th century Carribean origin, to refer to the process by which languages blend, by convention by cross-cultural commerce. Therein, two languages form a “contact language” blend as one donor language, the superstrate, donates loanwords and calques into a receiving language, the substrate, in a relexification process. The initial admixture forms a pidgin, an organic bare-bones language, out of said patois. By their nature pidgins lack scholarly and global recognition, the most notable of which may be &lt;em&gt;Naijá&lt;/em&gt;, a lingua franca across Nigeria. Sociolinguists theorize that a creole develops from those children who grow up speaking a pidgin, developing a more supple vocabulary with more precise grammar.&lt;/p&gt;

&lt;h2 id=&quot;all-the-worlds-a-stage&quot;&gt;All the World’s a Stage&lt;/h2&gt;

&lt;p&gt;As an aside, languages can be classified in a spectrum depending on how meaning is conveyed: analytic and synthetic. Analytic structure relies primarily on word order, prepositions, and separate words to convey grammatical relationships i.e. English,Chinese,Vietnamese. Synthetic structure uses inflection, conjugation, and morphological changes within words to express grammatical relationships i.e. Latin,Russian,Turkish.&lt;/p&gt;

&lt;h2 id=&quot;structural-features&quot;&gt;Structural features:&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;Simplified grammar compared to parent languages&lt;/li&gt;
  &lt;li&gt;Relatively fixed word order (often Subject-Verb-Object)&lt;/li&gt;
  &lt;li&gt;Minimal inflection&lt;/li&gt;
  &lt;li&gt;Analytic rather than synthetic structure,&lt;/li&gt;
  &lt;li&gt;Vocabulary drawn primarily from one “superstrate” language with influences from “substrate” languages&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;formation-process&quot;&gt;Formation process:&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;Emerge from pidgin languages that become nativized&lt;/li&gt;
  &lt;li&gt;Develop in contact situations like trade, colonization, or plantation settings&lt;/li&gt;
  &lt;li&gt;Undergo rapid grammatical expansion when children acquire them as first languages&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Deconstructing the Twitter Algorithm</title>
   <link href="http://hankquinlan.github.io/blog/2025/05/14/Deep-Dive-Into-the-Twitter-Algorithm"/>
   <updated>2025-05-14T00:00:00+00:00</updated>
   <id>http://honghaptang.github.io//blog/2025/05/14/Deep-Dive-Into-the-Twitter-Algorithm</id>
   <content type="html">&lt;p&gt;Wherein we deep dive into the open-sourced X algorithm…&lt;/p&gt;

&lt;h2 id=&quot;i-executive-summary&quot;&gt;I. Executive Summary&lt;/h2&gt;

&lt;p&gt;The Twitter (now X) recommendation algorithm represents a highly sophisticated, multi-stage pipeline engineered to deliver personalized content at an immense scale. Its fundamental objective is to maximize user engagement and retention by curating relevant tweets and other content across diverse platform surfaces, including the “For You” timeline, Search, Explore, and Notifications.1 This system exemplifies the intricate integration of advanced machine learning models within a robust, real-time distributed architecture. The foundational architectural principles include a microservices paradigm, extensive reliance on custom Scala frameworks, and specialized data systems designed for real-time processing and efficient feature serving.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;II. Architectural Foundations: The Engineering Landscape&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Twitter recommendation algorithm is constructed upon a distributed microservices architecture, primarily utilizing Scala and Java for its core services. Python is employed for scripting and machine learning model development, while Rust is strategically chosen for high-performance machine learning serving. This polyglot approach allows for optimized performance characteristics across distinct system components, leveraging the strengths of each language.1&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;High-level System Architecture and Component Interdependencies&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The twitter/the-algorithm repository reveals a modular design, with numerous directories corresponding to discrete services and components.1 This modularity is paramount for managing the inherent complexity of such a large-scale system, enabling independent scaling and deployment of individual services.3 Key architectural components include tweetypie, which serves as the core Tweet data service responsible for reading and writing tweet data; unified-user-actions, providing a real-time stream of user actions; and user-signal-service, a centralized platform for retrieving explicit (e.g., likes, replies) and implicit (e.g., profile visits, tweet clicks) user signals. These are complemented by various machine learning models and software frameworks that collectively form the recommendation engine.1 The system exhibits a consumption-heavy profile, characterized by significantly more read operations (approximately 300,000 queries per second) compared to write operations (around 6,000 requests per second), which necessitates highly optimized read paths and sophisticated caching strategies.4&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Pivotal Role of Home Mixer as the Central Timeline Service&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Home Mixer is explicitly designated as the primary service for constructing and serving Twitter’s Home Timelines. This includes the highly personalized “For You” feed, the “Following” feed (reverse chronological tweets from followed accounts), and “Lists” feeds.5 Functioning as the central orchestrator, Home Mixer integrates diverse candidate sources, applies scoring functions, incorporates heuristics, and filters content to compile the final user timeline.5 The “For You” timeline, a central focus of the open-sourced algorithm, typically comprises a balanced mix of in-network content (from accounts a user follows) and out-of-network content (recommended content from accounts not followed), often maintaining an average 50/50 split.7&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Product Mixer: Twitter’s Custom Scala Framework for Content Feeds&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Home Mixer is built upon Product Mixer, a custom Scala framework specifically engineered for the creation and management of content feeds.5 Services developed using Product Mixer are structured around a hierarchy of “Pipelines” – Product Pipelines, Mixer Pipelines, Recommendation Pipelines, and Candidate Pipelines. This pipeline architecture transparently segments execution into well-defined, structured steps, which is a fundamental abstraction for managing the complexity of content aggregation and ranking within the system.5 This design fosters modularity and clear data flow, essential for a system of this scale.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Overview of Primary Programming Languages and Their Strategic Use&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Scala and Java are the predominant programming languages within the repository, accounting for 63.0% and 21.9% of the codebase, respectively.1 This reflects Twitter’s historical backend technology stack and the suitability of the JVM ecosystem for developing large-scale distributed systems. Starlark (5.8%) is utilized for configuration, while Python (3.9%) is employed for scripting, data processing, and machine learning model development where rapid iteration and extensive libraries are advantageous.1 Notably, Rust (1.8%) is used for Navi, a high-performance machine learning serving server.1 The selection of Rust for Navi underscores a deliberate pursuit of maximum performance and memory safety for critical, low-latency machine learning inference components.10 This strategic polyglotism, where different languages are chosen to optimally match their characteristics to specific service requirements, is a key architectural decision. It implies that for data science software engineers, a deep understanding of language performance characteristics and the trade-offs involved in selecting the right tool for the right task is crucial, moving beyond a monolithic language strategy. Furthermore, it necessitates robust inter-service communication protocols, such as gRPC (which Navi supports), to ensure seamless integration across diverse language runtimes.9&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Discussion of Microservices and Distributed System Design for Extreme Scalability&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The architecture employs horizontal scaling, where requests and data are distributed across multiple servers, to prevent bottlenecks and ensure high availability.3 Load balancing mechanisms, including round-robin, dynamic, and global strategies, distribute user requests evenly and direct them to the nearest data center, thereby minimizing latency.11 Data partitioning, or sharding, across different servers ensures that no single server stores all data, leading to an even distribution of workload.11 Twitter’s system adopts an event-driven approach, utilizing asynchronous processing queues for tasks such as timeline updates and notifications. This design decouples services, enhancing responsiveness and system resilience.11 Data replication across multiple data centers is also a critical practice, ensuring low-latency access for a globally distributed user base and providing robust disaster recovery capabilities.11&lt;/p&gt;

&lt;p&gt;A significant observation from this architecture is the pervasive application of the “Mixer” pattern as a core abstraction for recommendation systems. The explicit mention of Product Mixer as a custom Scala framework for building feeds 5 and Home Mixer as its primary application 5 indicates a reusable, generalized pattern for content aggregation and ranking. The “pipelines” concept within Product Mixer suggests a highly configurable and extensible architecture for combining heterogeneous candidate sources, scoring functions, and filters. This modularity allows for independent innovation and optimization within each stage of the recommendation process, which is critical for continuous improvement in a dynamic machine learning environment. This pattern emphasizes the separation of concerns, where candidate generation, feature hydration, ranking, and filtering are distinct stages orchestrated by a central mixing layer.&lt;/p&gt;

&lt;p&gt;Another important aspect of this design is the comprehensive capture of user behavior, encompassing both explicit and implicit signals, and their real-time capture. The unified-user-actions service captures both “public actions such as favorites, retweets, replies” (explicit) and “implicit actions like bookmark, impression, video view” (implicit).13 The user-signal-service then centralizes the retrieval of these diverse signals.1 This holistic approach to capturing user interactions, both overt and subtle, forms the foundation for rich feature engineering. The emphasis on a “real-time stream” 13 indicates a critical requirement for low-latency feedback loops to continuously inform and update the machine learning models. For machine learning engineers, this highlights the necessity of a robust, real-time data infrastructure to capture the full spectrum of user interactions. Implicit signals, while potentially more challenging to interpret, often provide a much higher volume of data points, enabling more granular and continuous model training and adaptation. The real-time nature of this data capture is essential for ensuring the freshness and responsiveness of recommendations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;III. The Recommendation Pipeline: From Raw Data to Personalized Feeds&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Twitter’s recommendation pipeline is a multi-stage process that transforms billions of daily tweets into a personalized “For You” timeline. This pipeline systematically progresses through candidate generation, feature hydration, sophisticated ranking, and a final series of heuristics and filters.5&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A. Candidate Generation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The initial phase, candidate generation, involves fetching potential tweets from various sources. The objective is to compile a pool of approximately 1,500 candidate tweets for evaluation during each user session.6&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;In-Network Source:&lt;/strong&gt; This constitutes the primary candidate source, focusing on delivering timely and relevant tweets from users a person follows. These tweets are initially ranked based on relevance using a logistic regression model. A crucial element in this ranking is Real Graph, a model that predicts the likelihood of engagement between two users. A higher Real Graph score increases the probability of a tweet being included in a user’s feed.2 Notably, Twitter has recently phased out the Fanout Service, which was previously used for caching in-network tweets, and is in the process of redesigning the long-standing logistic regression ranking model.6&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Out-of-Network Sources:&lt;/strong&gt; Identifying relevant tweets from accounts a user does not follow is a more complex task.15 Two principal approaches are employed for this purpose:
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Social Graph Analysis:&lt;/strong&gt; This method estimates relevance by examining engagement patterns among users a person follows or those with similar interests. It considers which tweets followed accounts have engaged with and which tweets the user has liked.6&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Embedding Spaces:&lt;/strong&gt; This approach focuses on content similarity by generating numerical representations of user interests and tweet content.2 SimClusters is a significant embedding space utilized here, identifying communities led by influential users through a specialized matrix factorization algorithm.6&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Specific Candidate Sources:&lt;/strong&gt; The Home Mixer documentation lists Earlybird Search Index, User Tweet Entity Graph, Cr Mixer, and Follow Recommendations Service as examples of distinct candidate sources feeding into the system.5&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Quantitative Insights:&lt;/strong&gt; The “For You” timeline typically maintains a balanced composition, consisting of approximately 50% in-network tweets and 50% out-of-network tweets on average.7&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The combination of in-network (direct connections, relevance via Real Graph) and out-of-network (social graph analysis, embedding spaces like SimClusters) candidate sources represents a deliberate strategy. This hybrid approach ensures that core social connections are maintained while simultaneously expanding content reach and discoverability beyond a user’s immediate echo chamber. The 50/50 split observed in the “For You” timeline suggests a balanced approach to maximizing both relevance and serendipity, which are critical for user retention. This hybrid approach is a common pattern in mature recommendation systems, effectively addressing the “explore-exploit” dilemma: exploiting known preferences (in-network) while exploring new, potentially engaging content (out-of-network). For engineers, this implies the necessity of distinct, optimized retrieval mechanisms for different types of content, each with its own scaling and freshness requirements.&lt;/p&gt;

&lt;p&gt;Furthermore, the repeated emphasis on Real Graph for in-network ranking 6 and “Social Graph Analysis” for out-of-network content 6 highlights that user-user and user-content relationships are central to candidate selection. SimClusters 6 further reinforces this by identifying communities based on follower graphs. This design indicates that the underlying data model is heavily graph-centric, enabling complex relationship inference. For data scientists, this underscores the power of graph-based features and models in recommendation systems, particularly for capturing social dynamics and implicit connections. It suggests that investment in graph databases or graph processing frameworks is likely a core infrastructure decision.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;B. Feature Engineering and Hydration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Following candidate generation, the system proceeds to fetch a substantial number of features, approximately 6,000, which are essential for the subsequent ranking process.5&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Categorization and Purpose of Features:&lt;/strong&gt; Features are broadly categorized into static, real-time, user-specific, and search context features.16
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Static Features:&lt;/strong&gt; These are computed directly from a tweet at the time of its creation, such as the presence of a URL, cards, or quotes, and are stored within the index.16&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Real-time Features:&lt;/strong&gt; These per-tweet features can change after the tweet has been indexed. They primarily consist of social engagements like retweet count, favorite count, reply count, and various spam signals, which are computed based on later user activities. A Signal Ingester processes multiple event streams to collect and compute these real-time features.16&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;User Table Features:&lt;/strong&gt; These are per-user features obtained from a User Table Updater that processes a stream written by the user service. This input is used to store sparse real-time user information, which is then propagated to the tweet being scored by looking up the author of the tweet.16&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Search Context Features:&lt;/strong&gt; These features represent the context of the current searcher, including their UI language, content consumption patterns, and the current time.16&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;The Role of Unified User Actions (UUA) and User Signal Service in Capturing User Behavior:&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Unified User Actions (UUA) is described as a centralized, real-time Kafka stream of user actions. It captures both public actions (e.g., favorites, retweets, replies) and implicit actions (e.g., bookmarks, impressions, video views).13 UUA reads client-side and server-side event streams and generates a unified real-time user actions Kafka stream, which is then replicated to various data stores including HDFS, GCP Pubsub, GCP GCS, and GCP BigQuery.13&lt;/li&gt;
      &lt;li&gt;The User Signal Service functions as a centralized platform designed to retrieve these explicit and implicit user signals, making them accessible for downstream models and services.1&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Timelines Aggregation Framework for Generating Aggregate Features:&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;This framework, located within timelines/data_processing/ml_util/aggregation_framework, enables the flexible computation of aggregate (counting) features in both batch and real-time.17&lt;/li&gt;
      &lt;li&gt;It is capable of capturing historical interactions between arbitrary entities, such as a user’s past engagement history with various types of tweets (e.g., photo, video, retweets), specific authors, or in-network engagers.17&lt;/li&gt;
      &lt;li&gt;The framework supports offline daily batch processing, where generated aggregate features are uploaded to Manhattan for online hydration. Additionally, it supports online real-time aggregation of DataRecords through Storm, with a backing memcache that can be queried for real-time aggregate features. These features are critically used by the Home Timeline heavy ranker and other recommendation systems.17&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The sheer volume of features (approximately 6,000) and their categorization into static, real-time, and user-table features points to a highly granular and comprehensive understanding of content and user context. The Timelines Aggregation Framework’s capability to compute features in both batch (historical) and real-time modes is crucial. This multi-temporal approach allows machine learning models to learn from long-term user preferences while also adapting to immediate, fresh signals. This design choice highlights that feature engineering is not a one-off task but an ongoing, complex process. A robust feature store and a real-time feature computation pipeline are therefore essential for high-performing, adaptive recommendation models. The combination of batch and real-time aggregation suggests an architecture akin to Lambda or Kappa architectures for feature generation.18&lt;/p&gt;

&lt;p&gt;Furthermore, the role of UUA as a “centralized, real-time stream of user actions” 13 that is consumed by machine learning teams 13 and directly feeds into the User Signal Service and Timelines Aggregation Framework is fundamental. This architectural choice demonstrates that the underlying data architecture for machine learning is event-driven, heavily leveraging Apache Kafka.13 This ensures low-latency data availability for feature hydration and model training, which is critical for real-time recommendations. This confirms that for large-scale, real-time machine learning systems, a streaming data platform like Kafka is indispensable. It enables continuous feedback loops, allowing models to react quickly to changing user behavior and content trends.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;C. Ranking with the Heavy Ranker&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The “Heavy Ranker” is the core machine learning model responsible for scoring and ranking the generated candidate tweets.5 This model evaluates approximately 1,500 candidates for each user session.6&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;In-depth Analysis of the Neural Network Architecture and its Parameter Scale:&lt;/strong&gt; The ranking process is accomplished using a neural network comprising approximately 48 million parameters.6 This scale indicates a deep learning approach, where the network is continuously trained on tweet interactions to optimize for positive engagements.6 The model incorporates thousands of features to assign scores based on the predicted probability of user engagement with each tweet.6&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Influence of Twitter Blue Subscriptions and Account Credibility on Ranking Scores:&lt;/strong&gt; Tweets from Twitter Blue subscribers reportedly receive a significant boost in ranking. Specifically, their tweets can achieve a 2x higher score among non-followers and a 4x higher score among followers compared to unverified posts.7 Account credibility, quantified by a Tweepcred score (a reputation metric), verification status, follower-to-following ratio, consistent account activity, and absence of prior bans, also substantially influences ranking.22 Accounts with a tweepcred score below 65 may have a limited number of their tweets considered by the ranking algorithm.2&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Recency Decay and Content Type Prioritization:&lt;/strong&gt; Recency is a paramount ranking signal, with fresh content being prioritized.15 Tweets are subject to a relevancy half-life of 360 minutes (6 hours), meaning their score decreases by 50% every 6 hours.2 Content incorporating rich media, such as images, videos, GIFs, or polls, generally exhibits superior performance and receives higher scores due to its propensity to drive increased engagement.15 Tweets containing links that display images and videos, especially those utilizing Twitter Card markup, may receive an additional advantage in ranking.28&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The following table, derived from the algorithm’s internal weighting, illustrates how different user actions are valued by the Heavy Ranker when determining a tweet’s relevance score. These weights represent the relative importance assigned to each predicted user action, with Retweet serving as a baseline unit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Heavy Ranker Engagement Weighting&lt;/strong&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;User Action&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Relative Weight (vs. Retweet=1)&lt;/th&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Sentiment&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Like the post&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;0.5&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Positive&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Retweet the post&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;1&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Positive&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Reply to the post&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;13.5&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Positive&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Open the post author’s profile and like or reply to a post&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;12&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Positive&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Watch at least half of the video&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;0.005&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Positive&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Reply to the post and the tweet author engages with the reply&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;75&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Positive&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Click into the conversation of the post and engage with a reply&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;11&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Positive&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Click into the conversation of the post and stay for ≥ 2 mins&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;10&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Positive&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Request “show less often”/block/mute the post author&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;-74&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Negative&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Report the Tweet&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;-369&lt;/td&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;Negative&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;2&lt;/p&gt;

&lt;p&gt;The extremely high weights assigned to replies (13.5x a retweet) and particularly to replies that elicit a response from the tweet author (75x a retweet) reveal a strong algorithmic bias towards fostering genuine conversations over passive consumption (likes, retweets). This indicates that the algorithm is not merely focused on displaying popular content, but rather content that actively generates dialogue. This design choice suggests a strategic reinforcement towards building a more interactive community on the platform, moving beyond a simple broadcast medium. For engineers, this implies that features related to conversation depth, reply quality, and author responsiveness would be highly impactful in model development. It also suggests that the platform values “stickiness” derived from interaction more than just impressions.&lt;/p&gt;

&lt;p&gt;The explicit boost for Twitter Blue subscribers and the influence of Tweepcred (a reputation score based on network structure and user behavior) indicate that the algorithm is not purely content- or engagement-driven. It incorporates a layer of “authority” or “paid privilege.” This has significant implications for content creators and platform dynamics, suggesting a tiered visibility system where paid status or established credibility can bypass some of the organic ranking challenges. For engineers, this means that these “meta-features” (subscription status, reputation scores) are directly integrated into the ranking model, potentially as high-weight features or even as post-ranking multipliers.&lt;/p&gt;

&lt;p&gt;The neural network being “continuously trained on Tweet interactions” 6 and the emphasis on real-time features 16 and recency decay 2 highlight a system designed for rapid adaptation. The half-life of 6 hours for tweet relevance 2 indicates that the algorithm is constantly re-evaluating content freshness and user interest. This necessitates a robust MLOps pipeline for continuous integration and deployment of models, rapid feature updates, and efficient inference at scale. It implies that static, batch-trained models would quickly become stale; the system must be able to ingest new data, retrain, and deploy updated models with minimal latency to maintain relevance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;D. Core Machine Learning Models and Services&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Beyond the “Heavy Ranker,” several specialized machine learning models and services contribute critical signals and embeddings to the recommendation pipeline.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Real Graph:&lt;/strong&gt; This is a machine learning model, specifically a gradient boosting tree classifier, designed to predict the likelihood of one Twitter user interacting with another.20 It constructs a labeled dataset from a graph of Twitter users, incorporating various features such as tweet counts, follows, favorites, and other metrics related to user behavior.31 Real Graph collects both visible interactions (e.g., retweets, favorites, mentions, messages) and implicit interactions (e.g., tweet clicks, profile visits), capturing their frequency, intensity, and recency.32 This model is utilized to compute improved user recommendations, enhance the relevance of user search results, and effectively differentiate between strong and weak social ties.32 Real Graph is fundamental for understanding social tie strength, which is a critical signal for ranking in-network content and for social graph analysis in out-of-network candidate sourcing.6&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;SimClusters:&lt;/strong&gt; This component serves as a general-purpose representation layer based on overlapping communities. It captures users and heterogeneous content as sparse, interpretable vectors to support a multitude of recommendation tasks.20 SimClusters discovers approximately 145,000 communities, which are updated every three weeks. These communities are anchored by influential users and are identified using a custom matrix factorization algorithm applied to the Producer-Producer similarity graph.2 The process generates “Known For” embeddings (representing a producer’s affiliation with a community) and “Interested In” embeddings (representing a consumer’s interest in communities).33 SimClusters enables content similarity assessment and community-based recommendations, which are crucial for expanding a user’s feed beyond direct connections and for identifying trending content within specific niches.2&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;TwHIN (Twitter Heterogeneous Information Network):&lt;/strong&gt; TwHIN provides dense knowledge graph embeddings for Users and Tweets.1 It is trained on 7 billion tweets across over 100 languages, utilizing both text-based self-supervision and a social objective derived from rich social engagements (Favorites, Replies, Retweets, Follows) within the TwHIN.34 This model represents various entity types (User, Tweet, Advertiser, Ad) and relation types (Follow, Authors, Favorites, Replies, Retweets, Promotes, Clicks).8 It is specifically designed to capture social signals, content engagement signals, and advertisement engagements.8 TwHIN provides a richer, more comprehensive understanding of user and tweet relationships by integrating diverse interaction types into a unified embedding space, thereby overcoming the limitations of text-only models.34 It serves as a powerful feature source for the Heavy Ranker.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Tweepcred:&lt;/strong&gt; This is a PageRank-based algorithm that calculates the influence and reputation of Twitter users based on their interactions, such as mentions and retweets.1 It considers various factors, including the follower-to-following ratio, account age, total number of followers and followings, device usage, and safety status (e.g., restricted, suspended, verified).24 Tweepcred provides a “quality stamp” for accounts, influencing their visibility and ensuring that content from credible and influential accounts is seen by a wider audience.22 It is a key factor in algorithmic prioritization.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Trust and Safety Models:&lt;/strong&gt; This suite of models includes pNSFWMedia (detects NSFW images), pNSFWText (detects NSFW text/sexual topics), pToxicity (detects toxic content like insults), and pAbuse (detects abusive content such as hate speech or targeted harassment).1 These models are critical for content moderation, actively filtering out low-quality or harmful content.15 They are integrated into the ranking and filtering pipeline to ensure a safe and positive user experience, preventing the amplification of harmful content and maintaining platform integrity.20&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Navi: High-Performance ML Model Serving in Rust:&lt;/strong&gt; Navi is a high-performance, versatile machine learning serving server implemented in Rust. It is specifically tailored for production usage within Twitter’s technology stack.1 Navi offers gRPC API compatibility with TensorFlow Serving, enabling seamless integration with existing clients. Its pluggable architecture supports various machine learning runtimes, including out-of-the-box support for TensorFlow and Onnx Runtime, with PyTorch in an experimental state.9 Navi addresses the critical need for low-latency inference for complex machine learning models like the Heavy Ranker. Its implementation in Rust underscores the pursuit of maximum performance and efficiency for real-time scoring, directly impacting user experience and system throughput.10&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The presence of SimClusters (community embeddings), TwHIN (heterogeneous network embeddings), and Real Graph (user interaction likelihood) indicates that Twitter employs multiple, specialized embedding spaces. Each of these components captures different facets of user and content relationships, such as community dynamics, interaction patterns, content similarity, and social graph structure. These are not redundant but rather complementary, providing a rich, high-dimensional representation for the Heavy Ranker. This design choice highlights that a single embedding space is often insufficient for complex recommendation tasks. Engineers should consider building a suite of specialized embeddings that capture different types of signals (e.g., semantic, social, temporal) to provide comprehensive context to ranking models. This also implies a significant investment in distributed embedding computation and serving infrastructure.&lt;/p&gt;

&lt;p&gt;The trust-and-safety-models are listed as core “Model” components 1 and are explicitly used for filtering during the ranking process.20 This demonstrates that content moderation is not merely a separate, post-hoc layer but an intrinsic part of the recommendation pipeline. Negative feedback signals (mute, block, report) are heavily weighted negatively in the ranking.20 This illustrates a proactive approach to content moderation, where “safety by design” is embedded within the algorithm itself. Content perceived as harmful or low-quality is not just removed but actively de-prioritized or filtered out &lt;em&gt;before&lt;/em&gt; it reaches the user’s timeline. For machine learning engineers, this implies that trust and safety signals are critical features in the ranking model’s objective function, balancing engagement with platform health.&lt;/p&gt;

&lt;p&gt;The presence of Tweepcred, a PageRank-based influence system 35, as a distinct model component 1 that directly impacts ranking 22 signifies that the algorithm considers not just &lt;em&gt;what&lt;/em&gt; is said or engaged with, but &lt;em&gt;who&lt;/em&gt; is saying it. Reputation, derived from network structure and user behavior, serves as a powerful signal. This is a key differentiator from purely content-based or engagement-based systems. It suggests that a user’s standing within the network can significantly amplify or suppress their content’s reach. For engineers, developing robust and fair reputation systems (and mitigating potential biases) is a complex but high-impact area in social media recommendation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;E. Heuristics and Filters&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Following the ranking stage, a series of heuristics and filters are applied to ensure that the final feed presented to the user is balanced, diverse, and safe.5&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Visibility Filtering:&lt;/strong&gt; This mechanism excludes tweets based on user preferences, such as content from blocked or muted accounts, or due to legal compliance requirements.5 It can also involve restricting abuse-prone hashtags and search results.37&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Author Diversity:&lt;/strong&gt; This heuristic prevents the display of an excessive number of consecutive tweets from a single author, ensuring variety and preventing feed monotony.5&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Content Balance:&lt;/strong&gt; The algorithm actively maintains an equitable mix of in-network and out-of-network tweets in the user’s feed.5&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Feedback-based Fatigue:&lt;/strong&gt; This filter dynamically reduces the scores of tweets that have received negative feedback from the user, such as actions like “show less often,” blocking, or muting.5 Recent negative feedback is weighted more heavily and can lead to immediate filtering of content.8&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Social Proof:&lt;/strong&gt; This filter specifically excludes out-of-network tweets that lack a sufficient connection within the user’s network. For instance, it might require a second-degree connection, meaning someone the user follows must have engaged with the tweet or followed its author. This acts as a quality safeguard for recommended content.6&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Conversations:&lt;/strong&gt; The system threads replies with their original tweets to provide necessary context, enhancing readability and understanding of ongoing discussions.6&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Edited Tweets:&lt;/strong&gt; When a tweet is edited, the system updates stale content with the revised versions, ensuring users see the most current information.6&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While the Heavy Ranker primarily optimizes for engagement, these heuristics and filters address crucial aspects of user experience and platform health. They tackle issues such as feed monotony (Author Diversity), content relevance (Visibility Filtering), and quality control (Social Proof, Feedback-based Fatigue). These are not merely minor adjustments but essential components that shape the final user experience, preventing “algorithmic monoculture” or exposure to unwanted content. This highlights that a powerful ranking model alone is insufficient. A robust set of post-ranking rules and filters is necessary to ensure diversity, prevent negative user experiences (e.g., too many tweets from one person, unwanted content), and align with platform policies. This often involves a delicate balance between algorithmic optimization and human-defined rules.&lt;/p&gt;

&lt;p&gt;The explicit mention of “Feedback-based Fatigue” 5 and the significant negative weights for “show less often,” block, mute, and report actions 20 demonstrate that user dissatisfaction is a direct input to the algorithm. This goes beyond simply not engaging; it actively suppresses content the user dislikes. This is a crucial aspect of user-centric design in recommendation systems, allowing users to “train” their own feed by providing negative signals. For engineers, it means building reliable mechanisms for capturing and propagating negative feedback signals in real-time and ensuring these signals have a strong, immediate impact on ranking. This is a key lever for improving user satisfaction and combating unwanted content.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IV. Data Infrastructure and Real-time Processing at Scale&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Twitter’s recommendation system operates at an unprecedented scale, necessitating a robust and highly performant data infrastructure capable of real-time ingestion, processing, and serving.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Leveraging Apache Kafka for Real-time Data Ingestion, Streaming, and ML Logging Pipelines&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Apache Kafka plays a pivotal role in Twitter’s data pipeline, enabling the real-time ingestion and streaming of massive volumes of tweets and user interactions.19 Its distributed architecture is fundamental to ensuring scalability and fault tolerance, allowing Twitter to manage extremely high data throughput.19 Twitter extensively utilizes Kafka Streams for real-time analysis and processing of tweet streams, which is critical for identifying trending topics, detecting anomalies, and extracting valuable insights with minimal latency.19 A significant application of Kafka is in the machine learning logging pipeline for the home timeline prediction system. This pipeline transitioned from a seven-day batch processing model to a one-day streaming model using Kafka and Kafka Streams, resulting in improved model quality and substantial savings in engineering time.38 User login events, tweet events, user interaction events (such as likes, retweets, and follows), and even the recommendations themselves are all produced and consumed as messages within Kafka for real-time processing and delivery.19&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Role of Apache Storm in Real-time Stream Processing for Analytics and Feature Generation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Apache Storm is employed for real-time stream processing, particularly for tasks that demand fast, scalable, reliable, and fault-tolerant continuous processing of tweets.39 It is applied in critical areas such as opinion mining (sentiment analysis) and real-time analytics for trending hashtags.39 The Timelines Aggregation Framework, a key component for feature generation, supports real-time aggregation of DataRecords through Storm, with a backing memcache for online feature hydration.17 Storm complements Kafka by providing a robust framework for complex, continuous computations on streaming data, which is essential for generating the real-time features and analytics that directly feed into the recommendation models.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Twitter’s Custom Distributed Database: Manhattan, its Consistency Model, and Use Cases&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Twitter developed Manhattan, a custom-built, real-time, multi-tenant distributed key/value database. This system was designed to serve millions of queries per second with extremely low latency and high availability.41 Manhattan was created to overcome the scalability and expansion difficulties encountered with previous systems, such as Cassandra, which proved challenging to scale for Twitter’s unique demands.41 Manhattan supports various consistency guarantees, allowing clients to specify stronger consistency types when required for particular operations.42 It also offers a graph-based interface for interacting with edges and is utilized for batch Hadoop importing and time series counters.41 Manhattan represents Twitter’s solution to the challenges of storing and retrieving massive amounts of data with stringent real-time performance requirements. Its custom nature highlights the extreme demands of Twitter’s scale, where off-the-shelf solutions may not suffice. This demonstrates that for companies operating at Twitter’s scale, bespoke infrastructure is often required, driven by unique performance, consistency, and scalability demands that commercial or open-source alternatives cannot fully meet. It underscores the deep engineering expertise required to operate at such a scale, where even marginal gains in efficiency or consistency can have massive impacts.&lt;/p&gt;

&lt;p&gt;While Twitter operates at a massive scale and employs eventual consistency for most of its systems 11, Manhattan allows clients to “set a stronger consistency guarantee” for specific operations.42 This indicates a nuanced approach to data consistency, where different parts of the system or different data types might have varying consistency requirements based on their functional needs. This is a critical lesson for distributed systems engineers: strict consistency is expensive and often unnecessary for all data. A well-designed large-scale system will apply the appropriate consistency model (e.g., eventual, strong) to different data stores or operations based on business requirements and performance trade-offs. This requires careful architectural planning and a deep understanding of distributed systems theory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Caching Strategies for Low-Latency Data Access&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Caching is a crucial optimization for speeding up data retrieval and significantly reducing the load on backend databases.11 User timelines, for instance, are extensively cached, often residing in a Redis cluster, with each user’s timeline typically having a maximum of 800 entries.4 Frequently accessed data, including user preferences or top-K recommendations, are also cached using systems like Redis or Memcached.12 Caching is a fundamental practice for read-heavy systems like Twitter, ensuring that frequently requested content is delivered with minimal latency, which directly enhances the user experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Underlying Scalability Principles: Horizontal Scaling, Sharding, and Load Balancing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Twitter employs horizontal scaling to distribute requests across multiple servers, a foundational principle for handling large user bases.3 Load balancers, utilizing strategies such as round-robin, dynamic, and global distribution, evenly distribute user requests and direct them to the nearest data center to minimize latency.11 Data is partitioned, or sharded, across different servers to prevent any single server from storing all data, ensuring an even distribution of workload and preventing hot spots.11 These principles are standard but absolutely critical for any system operating at Twitter’s scale, ensuring high availability, fault tolerance, and consistent performance under extreme load.&lt;/p&gt;

&lt;p&gt;The transition of the machine learning logging pipeline from a 7-day batch latency to a 1-day streaming latency using Kafka Streams 38 represents a significant architectural evolution. This indicates a continuous drive towards real-time data processing for improved model freshness and responsiveness. This is not a static architecture but one that constantly adapts to performance and quality requirements. For data science software engineers, this highlights the long-term trend in large-scale machine learning systems: the move away from purely batch-oriented pipelines towards real-time streaming architectures. This necessitates expertise in stream processing frameworks (Kafka, Storm), event-driven design, and the challenges of managing data consistency and fault tolerance in real-time environments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;V. Evaluation and Continuous Improvement Methodologies&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Twitter algorithm is not a static entity; it continuously evolves through rigorous evaluation and iterative development. This ongoing process aims to optimize for user engagement and satisfaction while diligently mitigating any negative impacts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Performance Indicators (KPIs) Used to Measure Algorithm Effectiveness&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The algorithm is fundamentally designed to optimize for positive engagements, including Likes, Retweets, and Replies.6 A comprehensive set of key performance indicators (KPIs) is tracked to measure the algorithm’s effectiveness:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Engagement Metrics:&lt;/strong&gt; These include Likes, Retweets, Replies, Clicks (on links, media, or profile), Mentions, Quote Posts, and Bookmarks.20 These metrics collectively signal content appreciation, the extent of reach, and the value generated through conversations.44&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Visibility Metrics:&lt;/strong&gt; Impressions, representing the total number of times a tweet was viewed, and Reach, indicating the unique audience exposed to tweets, are crucial for understanding overall content visibility.25&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Derived Metrics:&lt;/strong&gt; Key derived metrics include Engagement Rate (calculated as Total engagements ÷ impressions × 100) and Click-Through Rate (Link Clicks ÷ Impressions × 100).25&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Growth Metrics:&lt;/strong&gt; The number of Followers, Follower Growth Rate, and Profile Views are tracked to assess audience expansion and account interest.43&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Content-Specific Metrics:&lt;/strong&gt; For multimedia content, Video Completion Rate is monitored, and Hashtag Performance is analyzed to gauge the effectiveness of trending topics and content discoverability.46&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Twitter Analytics provides detailed insights into audience demographics and the performance of individual tweets, enabling data-driven content strategy adjustments.26&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A/B Testing Frameworks and Their Application in Iterative Algorithm Development&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A/B testing is a foundational methodology for the iterative evaluation and development of different versions of the recommendation algorithm.47 This approach allows for controlled experimentation on specific factors, such as variations in wording, message length, overall tone, the number and relevance of hashtags, the effectiveness of different images or videos when paired with tweets, and optimal posting times.49 The typical process involves setting up a Twitter Dashboard, carefully constructing controlled tweets (where only the factor under test is varied, keeping all other elements constant), scheduling their release, and meticulously tracking their performance against predefined metrics.49 A/B testing provides a controlled, data-driven approach to understand how changes to the algorithm or content strategy directly impact user behavior, thereby enabling continuous optimization and the confident rollout of new features.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Challenges and Approaches in Evaluating Broader Algorithmic Impacts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;While recommendation algorithms typically optimize for users’ &lt;em&gt;revealed preferences&lt;/em&gt; (i.e., user engagement like clicks, shares, and likes), there is a recognized disparity with &lt;em&gt;stated preferences&lt;/em&gt; (what users explicitly &lt;em&gt;say&lt;/em&gt; they want).50 Research indicates that Twitter’s engagement-based algorithm has been observed to amplify emotionally charged, out-group hostile content that users report makes them feel worse about their political out-group.50 Studies leverage observational evidence and digital traces to infer the algorithmic amplification of low-credibility content, noting that high-engagement, high-follower tweets containing low-credibility URL domains can receive amplified visibility.51 Furthermore, metrics are logged for prominent Democrat and Republican accounts to understand the differential effects of features across the political spectrum.21&lt;/p&gt;

&lt;p&gt;This situation highlights the complex societal impact of large-scale recommendation systems. Optimizing solely for engagement can lead to unintended consequences, such as the amplification of misinformation or divisive content. This necessitates a broader perspective on algorithm evaluation, incorporating user surveys, qualitative analysis, and ethical considerations that extend beyond simple engagement metrics. This underscores the critical need for multi-objective optimization in recommendation systems. Beyond maximizing engagement, models should also consider factors such as content quality, diversity, user well-being, and adherence to ethical guidelines. This requires defining and measuring these broader objectives, potentially incorporating them directly into the loss function or as post-ranking re-rankers. It also highlights the importance of interdisciplinary collaboration, for example, with social scientists and ethicists, in the design and refinement of algorithms.&lt;/p&gt;

&lt;p&gt;The very act of open-sourcing the algorithm 7 and the stated future developments, such as “enhanced transparency regarding safety labels” and “increased visibility into the factors influencing tweet appearances” 6, indicate a growing demand for algorithmic accountability. The logging of metrics for Elon Musk’s personal experience and for prominent political accounts 21 also points to internal scrutiny and a response to external pressures regarding potential biases. This suggests a societal shift towards greater scrutiny of powerful algorithms. For engineers, this implies not only building effective models but also designing them with explainability, auditability, and fairness in mind. It signals a future where “black box” algorithms are less acceptable, and there is a growing need to articulate how algorithmic decisions are made, how biases are mitigated, and how the system aligns with broader public interest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;VI. Conclusion and Engineering Implications&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Twitter recommendation algorithm stands as a sophisticated engineering achievement, exemplifying the challenges and innovations inherent in large-scale machine learning and distributed systems. Its architecture, predominantly implemented in Scala and Java, and augmented by Rust for high-performance machine learning serving, demonstrates a pragmatic polyglot approach designed to optimize for specific performance characteristics. The multi-stage pipeline, encompassing candidate generation, feature hydration, and neural network-based ranking, is meticulously engineered to personalize content at scale.&lt;/p&gt;

&lt;p&gt;Key implications for data science software engineers working on similar large-scale recommendation systems include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;The Transformative Power of Graph-Based Features and Embeddings:&lt;/strong&gt; Models such as Real Graph, SimClusters, and TwHIN are foundational, illustrating the critical role of understanding complex relationships (user-user, user-content, content-content) within a social network context. Investing in robust graph processing and embedding generation capabilities is crucial for capturing these intricate dynamics.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;The Imperative of Real-time Data Infrastructure:&lt;/strong&gt; The heavy reliance on Apache Kafka for real-time data ingestion and streaming, coupled with systems like Apache Storm for real-time aggregations, underscores the non-negotiable necessity of low-latency feedback loops for dynamic recommendation systems. The freshness of data directly correlates with the relevance and responsiveness of recommendations.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Feature Engineering as a Continuous, Multi-Temporal Discipline:&lt;/strong&gt; The sheer volume and diverse nature of features—ranging from static and real-time to aggregate and user-specific—highlight that comprehensive feature engineering, spanning both batch and real-time computation, is paramount for achieving high model performance.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Beyond Engagement: The Mandate for Multi-Objective Optimization:&lt;/strong&gt; While engagement remains a primary driver, the analysis reveals the critical need to incorporate broader objectives into algorithmic design. These include content quality, diversity, and user well-being, which are addressed through trust and safety models, negative feedback loops, and explicit filters. This necessitates a careful definition of success metrics that extend beyond simple clicks or likes.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;The “Mixer” Pattern for Scalable Orchestration:&lt;/strong&gt; The Product Mixer framework exemplifies a modular, pipeline-driven approach to orchestrating complex recommendation logic. This design allows for the independent development and optimization of candidate sources, rankers, and filters, fostering agility and scalability.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Custom Infrastructure as a Necessity at Extreme Scale:&lt;/strong&gt; Twitter’s development of bespoke systems like Manhattan demonstrates that for the most demanding scales, off-the-shelf solutions may not always suffice. This necessitates custom engineering solutions precisely tailored to unique performance and consistency requirements.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;The Growing Importance of Algorithmic Accountability and Transparency:&lt;/strong&gt; The open-sourcing effort and the stated focus on evaluating broader societal impacts signal an increasing demand for explainable, fair, and auditable algorithms. Engineers must consider these critical aspects from the initial design phase of any large-scale recommendation system.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Twitter algorithm is an evolving system, constantly adapting to user behavior, content trends, and societal demands. Its open-sourced nature provides an invaluable blueprint for engineers striving to build the next generation of intelligent, scalable recommendation platforms.&lt;/p&gt;

&lt;h4 id=&quot;fuentes-citadas&quot;&gt;&lt;strong&gt;Fuentes citadas&lt;/strong&gt;&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;twitter/the-algorithm: Source code for Twitter’s Recommendation Algorithm - GitHub, acceso: junio 8, 2025, &lt;a href=&quot;https://github.com/twitter/the-algorithm&quot;&gt;https://github.com/twitter/the-algorithm&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Cracking the Code: How the Twitter Algorithm Works - Tweet Hunter, acceso: junio 8, 2025, &lt;a href=&quot;https://tweethunter.io/blog/twitter-algorithm-full-analysis&quot;&gt;https://tweethunter.io/blog/twitter-algorithm-full-analysis&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Designing Twitter’s Scalable System, acceso: junio 8, 2025, &lt;a href=&quot;https://abhisekroy.hashnode.dev/twitter-system-design&quot;&gt;https://abhisekroy.hashnode.dev/twitter-system-design&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;The Architecture Twitter Uses to Deal with 150M Active Users, 300K QPS, a 22 MB/S Firehose, and Send Tweets in Under 5 Seconds - High Scalability, acceso: junio 8, 2025, &lt;a href=&quot;https://highscalability.com/the-architecture-twitter-uses-to-deal-with-150m-active-users/&quot;&gt;https://highscalability.com/the-architecture-twitter-uses-to-deal-with-150m-active-users/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;the-algorithm/home-mixer/README.md at main · twitter/the-algorithm - GitHub, acceso: junio 8, 2025, &lt;a href=&quot;https://github.com/twitter/the-algorithm/blob/main/home-mixer/README.md&quot;&gt;https://github.com/twitter/the-algorithm/blob/main/home-mixer/README.md&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;Twitter’s Recommendation Algorithm: An In-Depth Overview&lt;/td&gt;
          &lt;td&gt;Talent500 blog, acceso: junio 8, 2025, &lt;a href=&quot;https://talent500.com/blog/twitters-recommendation-algorithm-an-in-depth-overview/&quot;&gt;https://talent500.com/blog/twitters-recommendation-algorithm-an-in-depth-overview/&lt;/a&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;Twitter Publishes its Tweet Ranking Algorithm Data on GitHub, Providing More Transparency in Process&lt;/td&gt;
          &lt;td&gt;Social Media Today, acceso: junio 8, 2025, &lt;a href=&quot;https://www.socialmediatoday.com/news/twitter-publishes-its-tweet-ranking-algorithm-data-on-github-providing-mor/646581/&quot;&gt;https://www.socialmediatoday.com/news/twitter-publishes-its-tweet-ranking-algorithm-data-on-github-providing-mor/646581/&lt;/a&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;igorbrigadir/awesome-twitter-algo: The release of the Twitter algorithm, annotated for recsys - GitHub, acceso: junio 8, 2025, &lt;a href=&quot;https://github.com/igorbrigadir/awesome-twitter-algo&quot;&gt;https://github.com/igorbrigadir/awesome-twitter-algo&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;the-algorithm/navi/README.md at main · twitter/the-algorithm - GitHub, acceso: junio 8, 2025, &lt;a href=&quot;https://github.com/twitter/the-algorithm/blob/main/navi/README.md&quot;&gt;https://github.com/twitter/the-algorithm/blob/main/navi/README.md&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Why Rust, acceso: junio 8, 2025, &lt;a href=&quot;https://book.gist.rs/hello/why-rust.html&quot;&gt;https://book.gist.rs/hello/why-rust.html&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Low-Level Design of Twitter: Architecture, Tweet Processing, and Scalability, acceso: junio 8, 2025, &lt;a href=&quot;https://getsdeready.com/low-level-design-of-twitter-how-tweets-are-processed-and-delivered/&quot;&gt;https://getsdeready.com/low-level-design-of-twitter-how-tweets-are-processed-and-delivered/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;How can you handle scalability issues in recommender systems? - Milvus, acceso: junio 8, 2025, &lt;a href=&quot;https://milvus.io/ai-quick-reference/how-can-you-handle-scalability-issues-in-recommender-systems&quot;&gt;https://milvus.io/ai-quick-reference/how-can-you-handle-scalability-issues-in-recommender-systems&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Unified User Actions (UUA) - twitter/the-algorithm · GitHub, acceso: junio 8, 2025, &lt;a href=&quot;https://github.com/twitter/the-algorithm/blob/main/unified_user_actions/README.md&quot;&gt;https://github.com/twitter/the-algorithm/blob/main/unified_user_actions/README.md&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;How Does the Twitter (X) Algorithm Work in 2025? - Fourthwall, acceso: junio 8, 2025, &lt;a href=&quot;https://fourthwall.com/blog/how-does-twitter-x-algorithm-work&quot;&gt;https://fourthwall.com/blog/how-does-twitter-x-algorithm-work&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;How Does The Twitter Algorithm Work? 10 Tips - SocialPilot, acceso: junio 8, 2025, &lt;a href=&quot;https://www.socialpilot.co/blog/twitter-algorithm&quot;&gt;https://www.socialpilot.co/blog/twitter-algorithm&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Analysis of Twitter the-algorithm source code with LangChain, GPT4 and Deep Lake, acceso: junio 8, 2025, &lt;a href=&quot;https://python.langchain.com.cn/docs/use_cases/code/twitter-the-algorithm-analysis-deeplake&quot;&gt;https://python.langchain.com.cn/docs/use_cases/code/twitter-the-algorithm-analysis-deeplake&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;the-algorithm/timelines/data_processing/ml_util/aggregation_framework/README.md at main - GitHub, acceso: junio 8, 2025, &lt;a href=&quot;https://github.com/twitter/the-algorithm/blob/main/timelines/data_processing/ml_util/aggregation_framework/README.md&quot;&gt;https://github.com/twitter/the-algorithm/blob/main/timelines/data_processing/ml_util/aggregation_framework/README.md&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;Real-Time Data Ingestion Architecture: Tools &amp;amp; Examples&lt;/td&gt;
          &lt;td&gt;Estuary, acceso: junio 8, 2025, &lt;a href=&quot;https://estuary.dev/blog/real-time-data-ingestion/&quot;&gt;https://estuary.dev/blog/real-time-data-ingestion/&lt;/a&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;Kafka and Airflow Implementation at Twitter - Anant, acceso: junio 8, 2025, &lt;a href=&quot;https://anant.us/blog/kafka-airflow-pipelines-twitter/&quot;&gt;https://anant.us/blog/kafka-airflow-pipelines-twitter/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Understanding the X Algorithm - Tweet Hunter, acceso: junio 8, 2025, &lt;a href=&quot;https://tweethunter.io/blog/understanding-the-x-algorithm&quot;&gt;https://tweethunter.io/blog/understanding-the-x-algorithm&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;What can we learn from ‘The Algorithm,’ Twitter’s partial open-sourcing of it’s feed-ranking recommendation system?&lt;/td&gt;
          &lt;td&gt;Sol Messing, acceso: junio 8, 2025, &lt;a href=&quot;https://solomonmg.github.io/post/twitter-the-algorithm/&quot;&gt;https://solomonmg.github.io/post/twitter-the-algorithm/&lt;/a&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;How the Twitter Algorithm Works in 2025 [+6 Strategies]&lt;/td&gt;
          &lt;td&gt;Sprout Social, acceso: junio 8, 2025, &lt;a href=&quot;https://sproutsocial.com/insights/twitter-algorithm/&quot;&gt;https://sproutsocial.com/insights/twitter-algorithm/&lt;/a&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;How To Master The X Algorithm In 2025? - Socinator, acceso: junio 8, 2025, &lt;a href=&quot;https://socinator.com/blog/master-x-algorithm/&quot;&gt;https://socinator.com/blog/master-x-algorithm/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;How the ????/Twitter Algorithm Works - Hypefury, acceso: junio 8, 2025, &lt;a href=&quot;https://hypefury.com/blog/en/how-the-x-twitter-algorithm-works/&quot;&gt;https://hypefury.com/blog/en/how-the-x-twitter-algorithm-works/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;A Comprehensive Guide to the X Algorithm: How It Works in 2025 - Brandwatch, acceso: junio 8, 2025, &lt;a href=&quot;https://www.brandwatch.com/blog/x-algorithm/&quot;&gt;https://www.brandwatch.com/blog/x-algorithm/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;How The Twitter Algorithm Works: Complete Guide For 2025 - RecurPost, acceso: junio 8, 2025, &lt;a href=&quot;https://recurpost.com/blog/twitter-algorithm/&quot;&gt;https://recurpost.com/blog/twitter-algorithm/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Understanding Twitter’s Algorithm: Key Insights - Kolsquare, acceso: junio 8, 2025, &lt;a href=&quot;https://www.kolsquare.com/en/blog/learn-the-keys-to-understanding-twitters-algorithm&quot;&gt;https://www.kolsquare.com/en/blog/learn-the-keys-to-understanding-twitters-algorithm&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Twitter’s algorithm ranking factors: A definitive guide - Search Engine Land, acceso: junio 8, 2025, &lt;a href=&quot;https://searchengineland.com/twitter-algorithm-ranking-factors-386215&quot;&gt;https://searchengineland.com/twitter-algorithm-ranking-factors-386215&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Understanding How the X (Twitter) Algorithm Works in 2025 - SocialBee, acceso: junio 8, 2025, &lt;a href=&quot;https://socialbee.com/blog/twitter-algorithm/&quot;&gt;https://socialbee.com/blog/twitter-algorithm/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;How to Use the X Algorithm to Your Marketing Advantage, acceso: junio 8, 2025, &lt;a href=&quot;https://digitalmarketinginstitute.com/blog/how-to-use-twitter-algorithm-to-your-marketing-advantage&quot;&gt;https://digitalmarketinginstitute.com/blog/how-to-use-twitter-algorithm-to-your-marketing-advantage&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;the-algorithm/src/scala/com/twitter/interaction_graph/README.md at main - GitHub, acceso: junio 8, 2025, &lt;a href=&quot;https://github.com/twitter/the-algorithm/blob/main/src/scala/com/twitter/interaction_graph/README.md&quot;&gt;https://github.com/twitter/the-algorithm/blob/main/src/scala/com/twitter/interaction_graph/README.md&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;RealGraph: User Interaction Prediction at Twitter, acceso: junio 8, 2025, &lt;a href=&quot;https://www.ueo-workshop.com/wp-content/uploads/2014/04/sig-alternate.pdf&quot;&gt;https://www.ueo-workshop.com/wp-content/uploads/2014/04/sig-alternate.pdf&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;the-algorithm/src/scala/com/twitter/simclusters_v2/README.md at main - GitHub, acceso: junio 8, 2025, &lt;a href=&quot;https://github.com/twitter/the-algorithm/blob/main/src/scala/com/twitter/simclusters_v2/README.md&quot;&gt;https://github.com/twitter/the-algorithm/blob/main/src/scala/com/twitter/simclusters_v2/README.md&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;TwHIN-BERT: A Socially-Enriched Pre-trained Language Model for Multilingual Tweet Representations at Twitter - Ahmed El-Kishky, acceso: junio 8, 2025, &lt;a href=&quot;https://ahelk.github.io/papers/elkishky_twhinbert.pdf&quot;&gt;https://ahelk.github.io/papers/elkishky_twhinbert.pdf&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;the-algorithm/src/scala/com/twitter/graph/batch/job/tweepcred/README at main - GitHub, acceso: junio 8, 2025, &lt;a href=&quot;https://github.com/twitter/the-algorithm/blob/main/src/scala/com/twitter/graph/batch/job/tweepcred/README&quot;&gt;https://github.com/twitter/the-algorithm/blob/main/src/scala/com/twitter/graph/batch/job/tweepcred/README&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;the-algorithm/trust_and_safety_models/README.md at main - GitHub, acceso: junio 8, 2025, &lt;a href=&quot;https://github.com/twitter/the-algorithm/blob/main/trust_and_safety_models/README.md&quot;&gt;https://github.com/twitter/the-algorithm/blob/main/trust_and_safety_models/README.md&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Twitter exec says it’s moving fast on moderation as harmful content surges, acceso: junio 8, 2025, &lt;a href=&quot;https://www.straitstimes.com/world/united-states/twitter-exec-says-moving-fast-on-moderation-as-harmful-content-surges&quot;&gt;https://www.straitstimes.com/world/united-states/twitter-exec-says-moving-fast-on-moderation-as-harmful-content-surges&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;How Twitter Built a Massive Machine Learning Pipeline Using Kafka - Confluent, acceso: junio 8, 2025, &lt;a href=&quot;https://www.confluent.io/blog/how-twitter-built-a-machine-learning-pipeline-with-kafka/&quot;&gt;https://www.confluent.io/blog/how-twitter-built-a-machine-learning-pipeline-with-kafka/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;real-time data processing with storm: using twitter streaming - ijesrt, acceso: junio 8, 2025, &lt;a href=&quot;https://www.ijesrt.com/Old_IJESRT/issues%20pdf%20file/Archive-2017/July-2017/2.pdf&quot;&gt;https://www.ijesrt.com/Old_IJESRT/issues%20pdf%20file/Archive-2017/July-2017/2.pdf&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Real Time Twitter Analytics with Apache Storm - ResearchGate, acceso: junio 8, 2025, &lt;a href=&quot;https://www.researchgate.net/publication/381793696_Real_Time_Twitter_Analytics_with_Apache_Storm&quot;&gt;https://www.researchgate.net/publication/381793696_Real_Time_Twitter_Analytics_with_Apache_Storm&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Twitter’s Manhattan: A Real-time, Multi-tenant Distributed Database - InfoQ, acceso: junio 8, 2025, &lt;a href=&quot;https://www.infoq.com/news/2014/05/twitters-manhattan/&quot;&gt;https://www.infoq.com/news/2014/05/twitters-manhattan/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Providing Flexible Database Consistency Levels with Manhattan at Twitter • Boaz Avital • GOTO 2016 - YouTube, acceso: junio 8, 2025, &lt;a href=&quot;https://www.youtube.com/watch?v=gvdXBC-NReQ&quot;&gt;https://www.youtube.com/watch?v=gvdXBC-NReQ&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Twitter/X KPIs - Fanpage Karma Insights, acceso: junio 8, 2025, &lt;a href=&quot;https://www.fanpagekarma.com/insights/twitter-x-kpis/&quot;&gt;https://www.fanpagekarma.com/insights/twitter-x-kpis/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Metrics That Matter—Your Guide to Twitter User Engagement - SocialSellinator, acceso: junio 8, 2025, &lt;a href=&quot;https://www.socialsellinator.com/social-selling-blog/twitter-user-engagement-metrics&quot;&gt;https://www.socialsellinator.com/social-selling-blog/twitter-user-engagement-metrics&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Twitter Engagement Metric - Klipfolio, acceso: junio 8, 2025, &lt;a href=&quot;https://www.klipfolio.com/resources/kpi-examples/social-media/twitter-engagement-metrics&quot;&gt;https://www.klipfolio.com/resources/kpi-examples/social-media/twitter-engagement-metrics&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;7 Important X (formerly Twitter) Analytics Metrics for Marketing Agencies - Swydo, acceso: junio 8, 2025, &lt;a href=&quot;https://www.swydo.com/blog/x-analytics-metrics/&quot;&gt;https://www.swydo.com/blog/x-analytics-metrics/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Design Twitter: A Comprehensive Guide - System Design School, acceso: junio 8, 2025, &lt;a href=&quot;https://systemdesignschool.io/problems/twitter/solution&quot;&gt;https://systemdesignschool.io/problems/twitter/solution&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Tweet Like Pro: 7 Hacks to Optimize Content for Twitter Algorithm - Tagembed, acceso: junio 8, 2025, &lt;a href=&quot;https://tagembed.com/blog/twitter-algorithm/&quot;&gt;https://tagembed.com/blog/twitter-algorithm/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;How to Use the New Twitter Dashboard For A/B Testing - Online Marketing Institute, acceso: junio 8, 2025, &lt;a href=&quot;https://www.onlinemarketinginstitute.org/blog/2016/10/original-use-new-twitter-dashboard-ab-testing/&quot;&gt;https://www.onlinemarketinginstitute.org/blog/2016/10/original-use-new-twitter-dashboard-ab-testing/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;Engagement, user satisfaction, and the amplification of divisive content on social media&lt;/td&gt;
          &lt;td&gt;PNAS Nexus&lt;/td&gt;
          &lt;td&gt;Oxford Academic, acceso: junio 8, 2025, &lt;a href=&quot;https://academic.oup.com/pnasnexus/article/4/3/pgaf062/8052060&quot;&gt;https://academic.oup.com/pnasnexus/article/4/3/pgaf062/8052060&lt;/a&gt;&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;(PDF) Evaluating Twitter’s algorithmic amplification of low-credibility content: an observational study - ResearchGate, acceso: junio 8, 2025, &lt;a href=&quot;https://www.researchgate.net/publication/378808348_Evaluating_Twitter&apos;s_algorithmic_amplification_of_low-credibility_content_an_observational_study&quot;&gt;https://www.researchgate.net/publication/378808348_Evaluating_Twitter’s_algorithmic_amplification_of_low-credibility_content_an_observational_study&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>ML Smörgåsbord 6: Neuro-Symbolic AI</title>
   <link href="http://hankquinlan.github.io/blog/2025/04/18/ML-Series-Part-6-KG-LLM"/>
   <updated>2025-04-18T10:00:00+00:00</updated>
   <id>http://honghaptang.github.io//blog/2025/04/18/ML-Series-Part-6-KG-LLM</id>
   <content type="html">&lt;h1 id=&quot;grounding-tensors-in-logic-️&quot;&gt;Grounding Tensors in Logic 🕸️&lt;/h1&gt;

&lt;p&gt;Welcome to the grand finale of the ML Smörgåsbord!&lt;/p&gt;

&lt;p&gt;In Part 5, we addressed LLM hallucinations by conditioning generation on dense vector embeddings of raw text (RAG). However, text is unstructured. To perform multi-hop logical reasoning (e.g., “Who directed the movie starring the actor born in the capital of France?”), flat vector search $v_q^T v_z$ breaks down.&lt;/p&gt;

&lt;p&gt;We need a &lt;strong&gt;Neuro-Symbolic&lt;/strong&gt; approach: combining the continuous, differentiable reasoning of LLMs with the discrete, structured topology of a &lt;strong&gt;Knowledge Graph (KG)&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;1-formalizing-the-knowledge-graph&quot;&gt;1. Formalizing the Knowledge Graph&lt;/h2&gt;

&lt;p&gt;A Knowledge Graph is mathematically defined as a directed multigraph $G = (E, R, T)$, where:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;$E = {e_1, e_2, \dots, e_{N_e}}$ is a set of entities (nodes).&lt;/li&gt;
  &lt;li&gt;$R = {r_1, r_2, \dots, r_{N_r}}$ is a set of relations (edges).&lt;/li&gt;
  &lt;li&gt;$T \subseteq E \times R \times E$ is a set of factual triples $(h, r, t)$ representing (head, relation, tail).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example: $(\text{Albert Einstein}, \text{born_in}, \text{Ulm})$.&lt;/p&gt;

&lt;p&gt;Unlike a dense continuous embedding $v \in \mathbb{R}^d$, triples in $T$ are discrete and logical. They can be queried with absolute determinism using graph traversal algorithms.&lt;/p&gt;

&lt;h2 id=&quot;2-unifying-llms-and-kgs-the-tripartite-framework&quot;&gt;2. Unifying LLMs and KGs: The Tripartite Framework&lt;/h2&gt;

&lt;p&gt;Pan et al. (2024) categorize the integration of continuous LLMs and discrete KGs into three frameworks:&lt;/p&gt;

&lt;h3 id=&quot;a-kg-enhanced-llms&quot;&gt;A. KG-Enhanced LLMs&lt;/h3&gt;
&lt;p&gt;During inference, a query $q$ is parsed to identify an entity $e_{start}$. We perform a $k$-hop traversal on $G$ to extract a subgraph $G_{sub} \subset G$. We linearize $G_{sub}$ into a text prompt sequence:
\(c = \text{Linearize}(G_{sub}) = [\text{string}(h_i, r_i, t_i)]_{i=1}^k\)
The LLM generation is then conditioned on this logically rigorous context: $p_\theta(y | q, c)$.&lt;/p&gt;

&lt;h3 id=&quot;b-llm-augmented-kgs&quot;&gt;B. LLM-Augmented KGs&lt;/h3&gt;
&lt;p&gt;Here, the LLM acts as an Information Extraction engine to construct the graph $G$ from an unstructured corpus $D$. The LLM acts as a mapping function:
\(f_{\theta}: d_i \rightarrow \{(h_j, r_j, t_j)\}_{j=1}^m \text{ where } d_i \in D\)
This is typically done via few-shot prompting or fine-tuning on relation-extraction tasks.&lt;/p&gt;

&lt;h3 id=&quot;c-synergized-integration-knowledge-graph-embeddings---kge&quot;&gt;C. Synergized Integration (Knowledge Graph Embeddings - KGE)&lt;/h3&gt;
&lt;p&gt;Perhaps the most mathematically elegant approach is embedding the nodes and edges of $G$ into the same continuous latent space as the LLM. Algorithms like &lt;strong&gt;TransE&lt;/strong&gt; define a translation operation where the relation vector acts as an operator moving the head to the tail:
\(\mathbf{h} + \mathbf{r} \approx \mathbf{t}\)
The loss function for the KGE model minimizes the distance function for valid triples:
\(\mathcal{L} = \sum_{(h,r,t) \in T} || \mathbf{h} + \mathbf{r} - \mathbf{t} ||_2^2\)
Once embedded, we can pass the node vectors $\mathbf{e}$ directly into the Transformer’s input embedding matrix, allowing the LLM to attend to raw graph structures without text serialization!&lt;/p&gt;

&lt;h2 id=&quot;3-the-neuro-symbolic-pipeline&quot;&gt;3. The Neuro-Symbolic Pipeline&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&quot;language-mermaid&quot;&gt;graph LR
    %% The continuous space
    Query[Text Query: q] --&amp;gt; LLM[LLM Engine]
    
    %% The discrete space
    Query --&amp;gt; Parser[Entity Linker]
    Parser --&amp;gt; StartNode[e_start]
    StartNode --&amp;gt;|K-hop BFS| GraphDB[(Knowledge Graph G)]
    GraphDB --&amp;gt; SubGraph[G_sub]
    
    %% The Bridge
    SubGraph --&amp;gt;|Linearization| SerializedText[Structured Context c]
    SerializedText --&amp;gt; LLM
    
    LLM --&amp;gt; Generation[Deterministically Grounded Output: y]
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;4-coding-the-graph-linearization&quot;&gt;4. Coding the Graph Linearization&lt;/h2&gt;

&lt;p&gt;Let’s look at how we transition from discrete graph mathematics in Python (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;networkx&lt;/code&gt;) back to string sequences for an LLM prompt.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;networkx&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nx&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 1. Initialize a directed multigraph G = (E, R, T)
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;G&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MultiDiGraph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 2. Define the set T of triples
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Albert_Einstein&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;born_in&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Ulm&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Ulm&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;located_in&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Germany&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Albert_Einstein&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;studied&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Physics&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 3. Populate the Graph
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_edge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;relation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;linearize_k_hop_subgraph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start_node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    Given a starting entity e_start, traverses k hops to build a linearized context c.
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start_node&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;
        
    &lt;span class=&quot;n&quot;&gt;linearized_facts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# 1-hop BFS for simplicity
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;neighbor&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;successors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start_node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# We access the edge dictionary
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;edge_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;graph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_edge_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start_node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;neighbor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# There could be multiple relations between two nodes in a MultiDiGraph
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;edge_idx&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;edge_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;relation&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;edge_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;edge_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;relation&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
            
            &lt;span class=&quot;c1&quot;&gt;# Translate discrete triple into continuous string
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;fact_string&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start_node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;_&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos; &apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;relation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;_&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos; &apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;neighbor&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;.&quot;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;linearized_facts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fact_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;linearized_facts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 4. Extract Context c
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e_start&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Albert_Einstein&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;linearize_k_hop_subgraph&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;G&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e_start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 5. Formulate final probabilistic condition P(y | q, c)
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Where was &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e_start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;_&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos; &apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; born and what did he study?&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;prompt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Context: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Query: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Answer: &quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Generated Prompt Space:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prompt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;thats-a-wrap-&quot;&gt;That’s a wrap! 🎓&lt;/h2&gt;

&lt;p&gt;You’ve made it to the end! In this series, we’ve gone from the core calculus of convolutions in computer vision, derived the sequential memory gates of LSTMs, explored parallel self-attention mechanics of Transformers, and finally bridged continuous differentiable spaces with discrete non-parametric graphs in RAG and KGs.&lt;/p&gt;

&lt;p&gt;Machine Learning is not a black box; it is highly structured, mathematically rigorous applied linear algebra and probability. Keep studying the equations, keep coding the algorithms from scratch, and keep pushing the boundary.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>No Assunto Do Mangue Beat</title>
   <link href="http://hankquinlan.github.io/blog/2025/04/12/No-Assunto-Do-Mangue-Beat"/>
   <updated>2025-04-12T00:00:00+00:00</updated>
   <id>http://honghaptang.github.io//blog/2025/04/12/No-Assunto-Do-Mangue-Beat</id>
   <content type="html">&lt;p&gt;Chico Science — um abraço mermão.&lt;/p&gt;

&lt;p&gt;Conhece você a música de Bezerra da Silva — sambista da favela, progenitor do gênio do sambandido?&lt;/p&gt;

&lt;p&gt;Conhece você a obra de Josué de Castro — nutricionista e filósofo da solução da fome?&lt;/p&gt;

&lt;p&gt;Foi através de Chico Science que conheci esses caras e suas obras.
Além disso, é um amor no estilo grego entre irmãos — eu sinto uma conexão profunda, artística, com esse cara no sangue.&lt;/p&gt;

&lt;p&gt;Eu, por minha parte, tenho visto múltiplos documentários com os outros membros do grupo, o concerto jubiloso com Gilberto Gil, músico e dissidente político, em Nova Iorque, e o manifesto Manguebeat mesmo — coautorado por Fred Zero Quatro (de Mundo Livre S/A) e incluído no disco Da Lama ao Caos.&lt;/p&gt;

&lt;p&gt;Sem dúvida, a obra de Chico Science e da Nação Zumbi constitui uma das melhores músicas dos anos noventa. Tragicamente, cessou, em certo sentido, com a morte de Chico Science, num Fiat Uno, à idade de 30 anos, o 2 de fevereiro, 1997.&lt;/p&gt;

&lt;p&gt;Então, fico obcecado, posso te admitir — sou fanático da ideologia musical do Manguebeat, com seu animal-espírito do caranguejo elétrico — que representa a dicotomia entre a vida moderna e a natureza de Recife, no nordeste do Brasil.&lt;/p&gt;

&lt;p&gt;E isso é a coisa, né? Que o homem tenha esquecido sua índole, tentado moldar o mangue à sua imagem — e por isso, a natureza volta com resposta — a antena fincada na lama.&lt;/p&gt;

&lt;p&gt;A bastardização moderna do mangue se manifesta como os mutantes da imaginação recifense.&lt;/p&gt;

&lt;p&gt;Pintamos o cenário que pariu o Manguebeat: &lt;em&gt;“Com a redemocratização em 1985, o povo recifense se encontra em uma cidade com pouca inovação musical e muito decaída. Em 1991, um órgão das Nações Unidas elegeu Recife como a quarta pior cidade do mundo para se viver. A população de Recife estava sem orgulho e sem sentimento de pertencimento à própria cidade” (TELES, 2019).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Para compreender o Mangue, precisamos apreciar o maracatu — a etimologia da palavra deriva da reapropriação de um termo racista que descrevia pejorativamente a sociedade africana. Então, foi a música do povo escravizado em Pernambuco.
Sua influência surgiu nos ritmos de tambores no Brock (lit. rock brasileiro) e renasceu do &lt;em&gt;joie de vivre&lt;/em&gt; internacional desde o manguezal pernambucano.
Colocou Recife no palco mundial, fonograficamente - foi a música revitalizando a cultura recifense das raízes subterrâneas presas aos galhos nodosos do mangal.&lt;/p&gt;

&lt;p&gt;Na nossa era moderna, a essência do mangue beat é ainda mais relevante. Vemos um mundo sucumbir ao TikTok, aos reels do Instagram, à idiotez do YouTube e à supremacia da inteligência artificial. Para combater a desanimação nuclear, precisamos do maracatu atômico, quântico, e nanotecnológico: precisamos do retorno aos instrumentos feitas da madeira, da crina e do suor misturado.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Anamauê, auêia, aê
Anamauê, auêia, aê
Anamauê, auêia, aê
Anamauê
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://www.maxwell.vrac.puc-rio.br/63354/63354.PDF&quot;&gt;REBELLO, Pedro Frota Pires. Manguebeat: como fortalecer o movimento sem perder a sua essência? 2023. Trabalho de Conclusão de Curso (Graduação em Administração de Empresas) – Departamento de Administração, Centro de Ciências Sociais, Pontifícia Universidade Católica do Rio de Janeiro, Rio de Janeiro, 2023.&lt;/a&gt;&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>ML Smörgåsbord 5: Information Geometry of RAG</title>
   <link href="http://hankquinlan.github.io/blog/2025/04/11/ML-Series-Part-5-RAG"/>
   <updated>2025-04-11T10:00:00+00:00</updated>
   <id>http://honghaptang.github.io//blog/2025/04/11/ML-Series-Part-5-RAG</id>
   <content type="html">&lt;h1 id=&quot;beyond-parametric-bottlenecks-️&quot;&gt;Beyond Parametric Bottlenecks 🗄️&lt;/h1&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Welcome to Part 5! In Part 4, we showed how BERT-style Transformers learn to embed semantic information within their billions of weights $W \in \theta$. This is known as &lt;strong&gt;parametric memory&lt;/strong&gt;. However, this memory is bounded by $O(&lt;/td&gt;
      &lt;td&gt;W&lt;/td&gt;
      &lt;td&gt;)$ and remains entirely static post-training, leading to catastrophic failure on factual temporal queries (hallucinations).&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;In 2021, Lewis et al. introduced &lt;strong&gt;Retrieval-Augmented Generation (RAG)&lt;/strong&gt;, a hybrid model linking the continuous differentiable space of a sequence-to-sequence model with a massive &lt;strong&gt;non-parametric&lt;/strong&gt; vector database. Let’s dig into the math.&lt;/p&gt;

&lt;h2 id=&quot;1-the-probabilistic-formulation-of-rag&quot;&gt;1. The Probabilistic Formulation of RAG&lt;/h2&gt;

&lt;p&gt;Standard language generation models the probability of generating token $y_i$ based solely on the input sequence $x$ and the preceding generated tokens $y_{&amp;lt;i}$:
\(p_{\theta}(y_i | x, y_{&amp;lt;i})\)&lt;/p&gt;

&lt;p&gt;RAG modifies this by conditioning the generation on a latent variable $z$, which represents a retrieved document from an external corpus $\mathcal{Z}$. The system becomes a pipeline of two probabilistic components:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;**The Retriever $p_\eta(z&lt;/td&gt;
          &lt;td&gt;x)$:** The probability of retrieving document $z$ given input $x$.&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;**The Generator $p_\theta(y_i&lt;/td&gt;
          &lt;td&gt;x, z, y_{&amp;lt;i})$:** The probability of generating token $y_i$ conditioned on both $x$ and $z$.&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Lewis et al. proposed two mathematical formulations for marginalizing out the latent document $z$:&lt;/p&gt;

&lt;h3 id=&quot;rag-sequence&quot;&gt;RAG-Sequence&lt;/h3&gt;
&lt;p&gt;The model assumes the &lt;em&gt;entire sequence&lt;/em&gt; $y$ is generated based on a single retrieved document $z$. We marginalize over the top-$k$ retrieved documents:
\(p_{\text{sequence}}(y | x) = \sum_{z \in \text{top-}k} p_\eta(z | x) \prod_i^N p_\theta(y_i | x, z, y_{&amp;lt;i})\)&lt;/p&gt;

&lt;h3 id=&quot;rag-token&quot;&gt;RAG-Token&lt;/h3&gt;
&lt;p&gt;The model assumes that the generation can pivot between different documents $z$ on a &lt;em&gt;per-token&lt;/em&gt; basis, allowing it to synthesize facts from multiple distinct sources. We push the summation inside the product:
\(p_{\text{token}}(y | x) = \prod_i^N \sum_{z \in \text{top-}k} p_\eta(z | x) p_\theta(y_i | x, z, y_{&amp;lt;i})\)&lt;/p&gt;

&lt;h2 id=&quot;2-dense-passage-retrieval-dpr&quot;&gt;2. Dense Passage Retrieval (DPR)&lt;/h2&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;How do we actually define $p_\eta(z&lt;/td&gt;
      &lt;td&gt;x)$ over a corpus of 21 million Wikipedia passages? Sparse statistical methods like TF-IDF or BM25 struggle with lexical mismatch (e.g., “author” vs “writer”).&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;We use &lt;strong&gt;DPR&lt;/strong&gt;, a bi-encoder architecture. We instantiate two independent BERT networks: a Question Encoder $E_Q$ and a Document Encoder $E_D$. We map both strings into a shared $d$-dimensional continuous vector space:
\(v_q = E_Q(x) \in \mathbb{R}^d, \quad v_z = E_D(z) \in \mathbb{R}^d\)&lt;/p&gt;

&lt;p&gt;The relevance score between query $x$ and document $z$ is given by the inner product:
\(\text{score}(x, z) = v_q^T v_z\)&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;We can then define the probability distribution $p_\eta(z&lt;/td&gt;
      &lt;td&gt;x)$ via a softmax over the entire corpus $\mathcal{Z}$:&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;$$ p_\eta(z&lt;/td&gt;
      &lt;td&gt;x) = \frac{\exp(v_q^T v_z)}{\sum_{z’ \in \mathcal{Z}} \exp(v_q^T v_{z’})} $$&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Since computing the denominator over 21 million documents at runtime is intractable, we pre-compute $v_z$ offline and use &lt;strong&gt;Maximum Inner Product Search (MIPS)&lt;/strong&gt; algorithms (like FAISS HNSW) to approximate the top-$k$ documents in $O(\log&lt;/td&gt;
      &lt;td&gt;\mathcal{Z}&lt;/td&gt;
      &lt;td&gt;)$ time.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;3-the-rag-pipeline-diagram&quot;&gt;3. The RAG Pipeline Diagram&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&quot;language-mermaid&quot;&gt;graph TD
    %% Query Encoding
    Q[Input Sequence: x] --&amp;gt; EQ[Encoder E_Q: R^d]
    EQ --&amp;gt; VQ[Query Vector: v_q]

    %% MIPS
    DB[(Offline Index E_D(Z))] --&amp;gt; MIPS{MIPS via FAISS}
    VQ --&amp;gt; MIPS

    %% Retrieval
    MIPS --&amp;gt;|argmax(v_q^T v_z)| Docs[Top-k Documents: z_1 ... z_k]

    %% Generation
    Q --&amp;gt; Concat((Concatenate String Contexts))
    Docs --&amp;gt; Concat
    
    Concat --&amp;gt;|x + z_k| Gen[Seq2Seq Generator: p_θ]
    Gen --&amp;gt; Y[Output Sequence: y]
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;4-coding-the-mips-math-in-pytorch&quot;&gt;4. Coding the MIPS Math in PyTorch&lt;/h2&gt;

&lt;p&gt;To truly grasp semantic search, let’s write a bare-bones implementation of Maximum Inner Product Search natively in PyTorch using matrix multiplication.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;torch&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;torch.nn.functional&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_top_k_documents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;query_embedding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;doc_embeddings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    query_embedding: Tensor of shape (1, d)
    doc_embeddings: Tensor of shape (N, d) representing N documents
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# 1. Compute Inner Product (Dot Product)
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# R^(1 x d) @ R^(d x N) -&amp;gt; R^(1 x N)
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matmul&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;query_embedding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;doc_embeddings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Shape: (1, N)
&lt;/span&gt;    
    &lt;span class=&quot;c1&quot;&gt;# 2. Get the top-k highest scoring indices
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# We use torch.topk to return the values and indices
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;top_scores&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;top_indices&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;topk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# 3. Compute Softmax probabilities over just the top-k (p_eta)
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;probs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;softmax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;top_scores&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;top_indices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;squeeze&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;probs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;squeeze&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Define dimensions: N=1000 docs, d=768 embedding dim
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;768&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Simulate our pre-computed offline document index
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Z_index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;normalize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;randn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 

&lt;span class=&quot;c1&quot;&gt;# Simulate a query embedding from E_Q
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v_q&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;normalize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;randn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Retrieve top 3 documents via MIPS
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;indices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;probabilities&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get_top_k_documents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v_q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Z_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Top 3 Document Indices in Database: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;indices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tolist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;p_eta(z|x) probabilities: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;probabilities&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tolist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In &lt;strong&gt;Part 6&lt;/strong&gt;, our final post, we will look at how we can replace flat unstructured document retrieval with highly structured topological searches over &lt;strong&gt;Knowledge Graphs&lt;/strong&gt;. See you then!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>ML Smörgåsbord 4: Transformers and BERT</title>
   <link href="http://hankquinlan.github.io/blog/2025/04/04/ML-Series-Part-4-BERT"/>
   <updated>2025-04-04T10:00:00+00:00</updated>
   <id>http://honghaptang.github.io//blog/2025/04/04/ML-Series-Part-4-BERT</id>
   <content type="html">&lt;h1 id=&quot;parallelizing-language-&quot;&gt;Parallelizing Language 📖&lt;/h1&gt;

&lt;p&gt;Welcome to Part 4! In Part 2, we showed that the $O(T)$ sequential bottleneck of BPTT in LSTMs inherently limits training speed. In 2017, Vaswani et al. proposed discarding recurrence entirely in “Attention Is All You Need.” Two years later, Devlin et al. utilized the encoder half of this architecture to create &lt;strong&gt;BERT&lt;/strong&gt; (Bidirectional Encoder Representations from Transformers).&lt;/p&gt;

&lt;p&gt;Today, we dive into the linear algebra that makes Transformers massively parallel and highly expressive: &lt;strong&gt;Scaled Dot-Product Self-Attention&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;1-the-death-of-recurrence-positional-encodings&quot;&gt;1. The Death of Recurrence: Positional Encodings&lt;/h2&gt;

&lt;p&gt;If an architecture reads a sequence $X = [x_1, x_2, \dots, x_N]$ purely in parallel, it has no inherent concept of order. Permuting the input vectors would yield the exact same output.&lt;/p&gt;

&lt;p&gt;To inject temporal information, Transformers add a deterministic &lt;strong&gt;Positional Encoding&lt;/strong&gt; matrix $P \in \mathbb{R}^{N \times d_{\text{model}}}$ to the input embedding matrix $E \in \mathbb{R}^{N \times d_{\text{model}}}$.&lt;/p&gt;

&lt;p&gt;The continuous positional encodings are defined via interlocking sinusoids:
\(P_{(pos, 2i)} = \sin\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right)\)
\(P_{(pos, 2i+1)} = \cos\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right)\)&lt;/p&gt;

&lt;p&gt;Where $pos$ is the position in the sequence, and $i$ is the dimension index. Because $sin(a+b)$ can be expressed as a linear combination of $sin(a)$ and $cos(b)$, the network can easily learn to attend to relative positions $pos + k$.&lt;/p&gt;

&lt;h2 id=&quot;2-scaled-dot-product-self-attention&quot;&gt;2. Scaled Dot-Product Self-Attention&lt;/h2&gt;

&lt;p&gt;In an LSTM, state is passed horizontally across time. In Self-Attention, every token computes an interaction weight with &lt;em&gt;every other token&lt;/em&gt; directly via matrix multiplication.&lt;/p&gt;

&lt;p&gt;Let $X \in \mathbb{R}^{N \times d}$ be our input matrix (sequence length $N$, embedding dimension $d$). We project $X$ into three distinct spaces: &lt;strong&gt;Queries ($Q$)&lt;/strong&gt;, &lt;strong&gt;Keys ($K$)&lt;/strong&gt;, and &lt;strong&gt;Values ($V$)&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;\(Q = X W^Q, \quad K = X W^K, \quad V = X W^V\)
Where $W^Q, W^K, W^V \in \mathbb{R}^{d \times d_k}$ are the learned parameter matrices.&lt;/p&gt;

&lt;p&gt;We compute the unnormalized attention scores $S$ by taking the dot product of every Query with every Key:
\(S = Q K^T \quad \text{(Shape: } N \times N)\)&lt;/p&gt;

&lt;p&gt;We scale the scores by $\frac{1}{\sqrt{d_k}}$. This is a crucial mathematical trick. If $Q$ and $K$ are independent random variables with mean $0$ and variance $1$, their dot product will have variance $d_k$. If variance is too high, the softmax will be pushed into regions where gradients are extremely small (vanishing gradients). Dividing by $\sqrt{d_k}$ normalizes the variance back to $1$.&lt;/p&gt;

&lt;p&gt;We then apply softmax row-wise to get the attention matrix $A$:
\(A = \text{softmax}\left(\frac{Q K^T}{\sqrt{d_k}}\right)\)&lt;/p&gt;

&lt;p&gt;Finally, we compute the output matrix $Z$ by taking the weighted sum of the Values:
\(Z = A V\)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Putting it all together into the core Transformer equation:&lt;/strong&gt;
\(\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V\)&lt;/p&gt;

&lt;h2 id=&quot;3-multi-head-attention-and-the-residual-stream&quot;&gt;3. Multi-Head Attention and the Residual Stream&lt;/h2&gt;

&lt;p&gt;A single attention head might focus heavily on syntax, but we also want to track semantics. &lt;strong&gt;Multi-Head Attention&lt;/strong&gt; computes $h$ parallel self-attention operations, concatenates their outputs, and linearly projects them back to $d_{\text{model}}$.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-mermaid&quot;&gt;graph TD
    %% Input
    X[Input Sequence Matrix X: N x d] --&amp;gt; LinearQ(X W^Q)
    X --&amp;gt; LinearK(X W^K)
    X --&amp;gt; LinearV(X W^V)
    
    %% Split Heads (Conceptual)
    LinearQ --&amp;gt; Q1[Q_1] &amp;amp; Q2[Q_2 ... Q_h]
    LinearK --&amp;gt; K1[K_1] &amp;amp; K2[K_2 ... K_h]
    LinearV --&amp;gt; V1[V_1] &amp;amp; V2[V_2 ... V_h]
    
    %% Attention
    Q1 &amp;amp; K1 &amp;amp; V1 --&amp;gt; Attn1(Scaled Dot-Product 1)
    Q2 &amp;amp; K2 &amp;amp; V2 --&amp;gt; Attn2(Scaled Dot-Product h)
    
    %% Concat
    Attn1 --&amp;gt; Concat((Concatenate along hidden dim))
    Attn2 --&amp;gt; Concat
    
    %% Output
    Concat --&amp;gt; OutProj[Linear Projection W^O]
    OutProj --&amp;gt; Z[Output Matrix Z: N x d]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To enable training of BERT-Large (24 layers, 340M parameters), we rely on &lt;strong&gt;Layer Normalization&lt;/strong&gt; and &lt;strong&gt;Residual Connections&lt;/strong&gt;. The output of the multi-head attention sub-layer is actually:
\(X_{\text{out}} = \text{LayerNorm}(X + \text{MultiHead}(X))\)&lt;/p&gt;

&lt;h2 id=&quot;4-coding-the-math-self-attention-in-pytorch&quot;&gt;4. Coding the Math: Self-Attention in PyTorch&lt;/h2&gt;

&lt;p&gt;Let’s implement the pure mathematical formulation of Scaled Dot-Product Attention in Python.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;torch&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;torch.nn.functional&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;math&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;scaled_dot_product_attention&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;K&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;V&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
    Computes Scaled Dot-Product Attention mathematically.
    Q, K, V shape: (Batch, N, d_k)
    &quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;d_k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# 1. MatMul: Q * K^T
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# K.transpose(-2, -1) swaps the last two dimensions to (Batch, d_k, N)
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matmul&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;K&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;transpose&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Shape: (Batch, N, N)
&lt;/span&gt;    
    &lt;span class=&quot;c1&quot;&gt;# 2. Scale: Divide by sqrt(d_k)
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;scaled_scores&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sqrt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d_k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# 3. Softmax: Compute probabilities along the last dimension
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;attention_weights&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;softmax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scaled_scores&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# 4. MatMul: A * V
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matmul&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attention_weights&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;V&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Shape: (Batch, N, d_k)
&lt;/span&gt;    
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attention_weights&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Let&apos;s verify dimensions
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Batch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d_k&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;64&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Batch size 2, Sequence Length 5, Embed dim 64
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Q&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;randn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Batch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d_k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;K&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;randn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Batch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d_k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;V&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;randn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Batch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d_k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attn_map&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scaled_dot_product_attention&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;K&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;V&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Output Z shape: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;# torch.Size([2, 5, 64])
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Attention Map A shape: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attn_map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# torch.Size([2, 5, 5])
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In &lt;strong&gt;Part 5&lt;/strong&gt;, we will move beyond fixed parametric networks and dive into the mathematics of Dense Passage Retrieval, using dual-encoder bi-encoders to search non-parametric vector spaces in &lt;strong&gt;Retrieval-Augmented Generation (RAG)&lt;/strong&gt;!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>ML Smörgåsbord 3: Spatial Attention</title>
   <link href="http://hankquinlan.github.io/blog/2025/03/28/ML-Series-Part-3-VQA"/>
   <updated>2025-03-28T10:00:00+00:00</updated>
   <id>http://honghaptang.github.io//blog/2025/03/28/ML-Series-Part-3-VQA</id>
   <content type="html">&lt;h1 id=&quot;grounding-language-in-vision-️&quot;&gt;Grounding Language in Vision 📸✍️&lt;/h1&gt;

&lt;p&gt;Welcome back to Part 3! In Part 1, we defined the convolutional operations that extract spatial feature maps $V \in \mathbb{R}^{C \times H \times W}$ from images. In Part 2, we formalized the LSTM sequence modeling that compresses a variable-length text sequence into a fixed-length dense vector $h_Q \in \mathbb{R}^{d_q}$.&lt;/p&gt;

&lt;p&gt;Today, we unite these two spaces. How can a network conditionally route visual information based on a textual query? The answer lies in the mathematics of &lt;strong&gt;Spatial Attention&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;1-the-formulation-of-visual7w&quot;&gt;1. The Formulation of Visual7W&lt;/h2&gt;

&lt;p&gt;In Zhu et al. (2016), the objective of Visual Question Answering (VQA) is framed as a mapping function:
\(f: (I, Q) \rightarrow A\)
Where $I$ is an image, $Q$ is a sequence of word embeddings $[q_1, \dots, q_T]$, and $A$ is the answer (either a discrete class or a localized bounding box).&lt;/p&gt;

&lt;p&gt;If we simply concatenate the flattened global image features $v_{global}$ with the final question hidden state $h_Q$, the network struggles to isolate small spatial details relevant to specific questions (e.g., “What color is the &lt;em&gt;tie&lt;/em&gt;?”).&lt;/p&gt;

&lt;p&gt;Instead, we treat the final convolutional feature map $V \in \mathbb{R}^{C \times H \times W}$ as a set of $N = H \times W$ distinct spatial vectors:
\(V = \{v_1, v_2, \dots, v_N\} \text{ where } v_i \in \mathbb{R}^C\)&lt;/p&gt;

&lt;h2 id=&quot;2-deriving-the-attention-mechanism&quot;&gt;2. Deriving the Attention Mechanism&lt;/h2&gt;

&lt;p&gt;We want to compute a scalar weight $\alpha_i \in [0, 1]$ for every spatial region $v_i$, conditioned on the question vector $h_Q$. We require that $\sum_{i=1}^N \alpha_i = 1$.&lt;/p&gt;

&lt;p&gt;We do this via a Multi-Layer Perceptron (MLP) alignment model. First, we project both the visual vector $v_i$ and the question vector $h_Q$ into a shared joint-embedding space of dimension $k$:&lt;/p&gt;

&lt;p&gt;\(z_i = \tanh(W_v v_i + W_q h_Q + b_z)\)
Where $W_v \in \mathbb{R}^{k \times C}$ and $W_q \in \mathbb{R}^{k \times d_q}$.&lt;/p&gt;

&lt;p&gt;Next, we project this joint representation to a scalar logit using a weight vector $w_a \in \mathbb{R}^k$:
\(e_i = w_a^T z_i + b_a\)&lt;/p&gt;

&lt;p&gt;Finally, we apply the softmax function over the $N$ regions to yield a normalized probability distribution (the attention map):
\(\alpha_i = \frac{\exp(e_i)}{\sum_{j=1}^N \exp(e_j)}\)&lt;/p&gt;

&lt;p&gt;The resulting &lt;strong&gt;context vector&lt;/strong&gt; $\hat{v}$ is the $\alpha$-weighted sum of the original spatial features:
\(\hat{v} = \sum_{i=1}^N \alpha_i v_i\)
This vector $\hat{v} \in \mathbb{R}^C$ now represents the &lt;em&gt;exact visual information required to answer the question&lt;/em&gt;, filtering out irrelevant background noise.&lt;/p&gt;

&lt;h2 id=&quot;3-visualizing-the-tensor-operations&quot;&gt;3. Visualizing the Tensor Operations&lt;/h2&gt;

&lt;p&gt;Let’s look at the flow of tensor dimensions during the attention calculation. Assume a batch size of $B$.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-mermaid&quot;&gt;graph TD
    %% Tensors
    V[Visual Map: B x N x C] --&amp;gt;|Linear(C -&amp;gt; K)| V_proj[Projected V: B x N x K]
    Q[Question Vector: B x d_q] --&amp;gt;|Linear(d_q -&amp;gt; K)| Q_proj[Projected Q: B x K]
    
    %% Broadcasting
    Q_proj --&amp;gt;|Unsqueeze &amp;amp; Expand| Q_exp[Expanded Q: B x N x K]
    
    %% Addition and Tanh
    V_proj --&amp;gt; Add_Op(Element-wise +)
    Q_exp --&amp;gt; Add_Op
    Add_Op --&amp;gt; Tanh_Op(Tanh)
    
    %% Scoring
    Tanh_Op --&amp;gt;|Linear(K -&amp;gt; 1)| Z[Logits e_i: B x N x 1]
    Z --&amp;gt;|Squeeze| Z_sq[Logits: B x N]
    
    %% Softmax
    Z_sq --&amp;gt;|Softmax(dim=1)| Alpha[Attention Weights α: B x N]
    
    %% Weighted Sum (Batch Matrix Multiplication)
    Alpha --&amp;gt;|Unsqueeze| Alpha_uns[α: B x 1 x N]
    V --&amp;gt; BMM(Batch Matrix Multiply: BMM)
    Alpha_uns --&amp;gt; BMM
    BMM --&amp;gt; V_hat[Context Vector v_hat: B x 1 x C]
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;4-pytorch-implementation-of-the-mlp-attention-layer&quot;&gt;4. PyTorch Implementation of the MLP Attention Layer&lt;/h2&gt;

&lt;p&gt;Notice in the graph above, the most efficient way to compute $\sum \alpha_i v_i$ for a batch of images is using Batch Matrix Multiplication (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;torch.bmm&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Let’s implement this layer mathematically identically to the equations above.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;torch&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;torch.nn&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;torch.nn.functional&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SpatialAttention&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c_dim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;512&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;q_dim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k_dim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;128&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SpatialAttention&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# W_v projection: R^C -&amp;gt; R^k
&lt;/span&gt;        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;W_v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Linear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_dim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k_dim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bias&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# W_q projection: R^d_q -&amp;gt; R^k
&lt;/span&gt;        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;W_q&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Linear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q_dim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k_dim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bias&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Bias b_z goes here
&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;# w_a scoring vector: R^k -&amp;gt; R^1
&lt;/span&gt;        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;w_a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Linear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k_dim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bias&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;# Bias b_a goes here
&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;forward&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;V&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h_Q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
        V: (Batch, N, C) - The flattened spatial feature map
        h_Q: (Batch, d_q) - The question hidden state
        &quot;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;C&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;V&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        
        &lt;span class=&quot;c1&quot;&gt;# 1. Project Visual Features
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;v_proj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;W_v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;V&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Shape: (B, N, k_dim)
&lt;/span&gt;        
        &lt;span class=&quot;c1&quot;&gt;# 2. Project Question Vector and broadcast to match N spatial regions
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;q_proj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;W_q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h_Q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Shape: (B, k_dim)
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;q_exp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;q_proj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unsqueeze&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Shape: (B, N, k_dim)
&lt;/span&gt;        
        &lt;span class=&quot;c1&quot;&gt;# 3. Compute joint embedding with Tanh
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tanh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v_proj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;q_exp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Shape: (B, N, k_dim)
&lt;/span&gt;        
        &lt;span class=&quot;c1&quot;&gt;# 4. Compute unnormalized logits e_i
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;w_a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;squeeze&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Shape: (B, N)
&lt;/span&gt;        
        &lt;span class=&quot;c1&quot;&gt;# 5. Softmax to get attention weights \alpha
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;alpha&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;softmax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Shape: (B, N)
&lt;/span&gt;        
        &lt;span class=&quot;c1&quot;&gt;# 6. Compute context vector \hat{v} via Batch Matrix Multiplication
&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;# alpha.unsqueeze(1) is (B, 1, N)
&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;# V is (B, N, C)
&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;# BMM( (B, 1, N), (B, N, C) ) -&amp;gt; (B, 1, C)
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;v_hat&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bmm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alpha&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unsqueeze&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;V&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;squeeze&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Shape: (B, C)
&lt;/span&gt;        
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v_hat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alpha&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Let&apos;s verify the dimensions
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d_q&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;49&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;512&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;256&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;V_tensor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;randn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;h_Q_tensor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;randn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d_q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;attention_module&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SpatialAttention&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_dim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;q_dim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d_q&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k_dim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;128&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;context_vector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attention_map&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attention_module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;V_tensor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h_Q_tensor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Context Vector shape: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context_vector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# torch.Size([32, 512])
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Attention Map shape: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attention_map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# torch.Size([32, 49])
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In &lt;strong&gt;Part 4&lt;/strong&gt;, we will discard the sequential nature of LSTMs entirely. We will dive into the purely parallel matrix operations of the &lt;strong&gt;Transformer Architecture&lt;/strong&gt; and derive the mathematical powerhouse known as &lt;em&gt;Scaled Dot-Product Self-Attention&lt;/em&gt;, the core engine of BERT!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>이세돌</title>
   <link href="http://hankquinlan.github.io/blog/2025/03/23/%EC%9D%B4%EC%84%B8%EB%8F%8C"/>
   <updated>2025-03-23T00:00:00+00:00</updated>
   <id>http://honghaptang.github.io//blog/2025/03/23/이세돌</id>
   <content type="html">&lt;p&gt;I have since childhood felt chess a useless skill to learn given its cracking by AI automata.
Why learn what at which a machine will always be superior?&lt;/p&gt;

&lt;p&gt;And yet, now, to quote Bill Gates, intelligence is poised to become as common as water or electricity.&lt;/p&gt;

&lt;p&gt;Perhaps, I overly invested my identity in my own natural talents of intellect.&lt;/p&gt;

&lt;p&gt;Where do we go from here?&lt;/p&gt;

&lt;p&gt;Do we quit “life” as 이세돌 quit the game of &lt;em&gt;Go&lt;/em&gt; upon learning he would never achieve leverage against AlphaGo?&lt;/p&gt;

&lt;p&gt;We are at a cross-roads.&lt;/p&gt;

&lt;p&gt;Will humanity smoke its turn 37 cigarette for the auto-annihilation by technofeudalist overlords?&lt;/p&gt;

&lt;p&gt;Or, will we rise up on turn 78 with a divine play to defeat the incoming ai-pocalypse?&lt;/p&gt;

&lt;p&gt;Time will only tell.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>ML Smörgåsbord 2: Recurrent Memory and LSTMs</title>
   <link href="http://hankquinlan.github.io/blog/2025/03/21/ML-Series-Part-2-RNNs"/>
   <updated>2025-03-21T10:00:00+00:00</updated>
   <id>http://honghaptang.github.io//blog/2025/03/21/ML-Series-Part-2-RNNs</id>
   <content type="html">&lt;h1 id=&quot;stepping-into-the-time-dimension-&quot;&gt;Stepping into the Time Dimension ⏳&lt;/h1&gt;

&lt;p&gt;Welcome back to Part 2! Last week we covered the spatial convolutions of AlexNet. Today, we shift from $x,y$ coordinates to the time axis $t$. We are going to explore how Recurrent Neural Networks (RNNs) and their upgraded cousins, Long Short-Term Memory networks (LSTMs), maintain continuous differentiable memory.&lt;/p&gt;

&lt;h2 id=&quot;1-the-vanilla-rnn-forward-pass&quot;&gt;1. The Vanilla RNN Forward Pass&lt;/h2&gt;

&lt;p&gt;Let’s rigorously define a vanilla RNN. At any timestep $t$, the network receives an input vector $x_t \in \mathbb{R}^d$ and the previous hidden state vector $h_{t-1} \in \mathbb{R}^h$.&lt;/p&gt;

&lt;p&gt;It computes the new hidden state via an affine transformation followed by a hyperbolic tangent non-linearity:&lt;/p&gt;

\[h_t = \tanh(W_{hx} x_t + W_{hh} h_{t-1} + b_h)\]

&lt;p&gt;Where:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;$W_{hx} \in \mathbb{R}^{h \times d}$ is the input-to-hidden weight matrix.&lt;/li&gt;
  &lt;li&gt;$W_{hh} \in \mathbb{R}^{h \times h}$ is the hidden-to-hidden transition matrix.&lt;/li&gt;
  &lt;li&gt;$b_h \in \mathbb{R}^h$ is the hidden bias vector.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To predict an output $\hat{y}_t \in \mathbb{R}^v$ (e.g., a probability distribution over a vocabulary of size $v$), we apply another affine projection and a softmax:&lt;/p&gt;

\[\hat{y}_t = \text{softmax}(W_{yh} h_t + b_y)\]

&lt;h3 id=&quot;the-fundamental-flaw-backpropagation-through-time-bptt&quot;&gt;The Fundamental Flaw: Backpropagation Through Time (BPTT)&lt;/h3&gt;

&lt;p&gt;To train this, we must unroll the network through time and compute gradients. The gradient of the loss $\mathcal{L}_T$ at the final timestep with respect to the hidden state at timestep $k$ ($k &amp;lt; T$) involves the product of Jacobians:&lt;/p&gt;

\[\frac{\partial \mathcal{L}_T}{\partial h_k} = \frac{\partial \mathcal{L}_T}{\partial h_T} \prod_{j=k+1}^T \frac{\partial h_j}{\partial h_{j-1}}\]

&lt;p&gt;Since $h_j = \tanh(W_{hh} h_{j-1} + \dots)$, the Jacobian $\frac{\partial h_j}{\partial h_{j-1}} = \text{diag}(\tanh’(\dots)) W_{hh}$.&lt;/p&gt;

&lt;p&gt;If the largest singular value of $W_{hh}$ is less than 1, this product decays exponentially (Vanishing Gradients). If it’s greater than 1, it grows exponentially (Exploding Gradients). Vanilla RNNs are fundamentally unstable for long sequences.&lt;/p&gt;

&lt;h2 id=&quot;2-enter-the-lstm-an-additive-gradient-highway&quot;&gt;2. Enter the LSTM: An Additive Gradient Highway&lt;/h2&gt;

&lt;p&gt;In 1997, Hochreiter &amp;amp; Schmidhuber solved this with the LSTM. Instead of just a hidden state $h_t$, they introduced a &lt;strong&gt;Cell State&lt;/strong&gt; $c_t$.&lt;/p&gt;

&lt;p&gt;The brilliant innovation of the Cell State is that information is updated &lt;em&gt;additively&lt;/em&gt; rather than through matrix multiplication, acting as a “highway” where gradients can flow backward through time uninterrupted.&lt;/p&gt;

&lt;p&gt;Here are the precise gated equations that govern an LSTM cell:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Forget Gate:&lt;/strong&gt; Decides what to drop from the old cell state.
\(f_t = \sigma(W_f \cdot [h_{t-1}, x_t] + b_f)\)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Input Gate:&lt;/strong&gt; Decides what new information to add.
\(i_t = \sigma(W_i \cdot [h_{t-1}, x_t] + b_i)\)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Candidate Cell State:&lt;/strong&gt; Generates potential new values.
\(\tilde{c}_t = \tanh(W_c \cdot [h_{t-1}, x_t] + b_c)\)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Cell State Update:&lt;/strong&gt; (The Additive Highway!)
\(c_t = f_t \odot c_{t-1} + i_t \odot \tilde{c}_t\)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Output Gate &amp;amp; Hidden State:&lt;/strong&gt; Decides what part of the cell state becomes the hidden state.
\(o_t = \sigma(W_o \cdot [h_{t-1}, x_t] + b_o)\)
\(h_t = o_t \odot \tanh(c_t)\)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;(Note: $\sigma$ is the sigmoid function, mapping values to $(0, 1)$ to act as a gate/valve. $\odot$ denotes element-wise Hadamard multiplication. $[h_{t-1}, x_t]$ denotes vector concatenation).&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;3-visualizing-the-lstm-cell-architecture&quot;&gt;3. Visualizing the LSTM Cell Architecture&lt;/h2&gt;

&lt;p&gt;Here is a detailed schematic of the internal flow of tensors inside a single LSTM cell at timestep $t$.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-mermaid&quot;&gt;graph TD
    %% Inputs
    X_t[Input: x_t] --&amp;gt; Concat
    H_prev[Previous Hidden: h_{t-1}] --&amp;gt; Concat
    C_prev[Previous Cell State: c_{t-1}] --&amp;gt; Add_Op

    %% Concatenation
    Concat((Concatenate)) --&amp;gt; W_f[Linear + Sigmoid]
    Concat --&amp;gt; W_i[Linear + Sigmoid]
    Concat --&amp;gt; W_c[Linear + Tanh]
    Concat --&amp;gt; W_o[Linear + Sigmoid]

    %% Forget Gate logic
    W_f --&amp;gt;|Forget Vector: f_t| Mult_Forget(Element-wise X)
    C_prev --&amp;gt; Mult_Forget

    %% Input Gate logic
    W_i --&amp;gt;|Input Vector: i_t| Mult_Input(Element-wise X)
    W_c --&amp;gt;|Candidate Vector: c~_t| Mult_Input

    %% State Update
    Mult_Forget --&amp;gt; Add_Op(Element-wise +)
    Mult_Input --&amp;gt; Add_Op

    %% New Outputs
    Add_Op --&amp;gt; C_next[New Cell State: c_t]
    Add_Op --&amp;gt; Tanh_Op(Tanh)
    W_o --&amp;gt;|Output Gate: o_t| Mult_Output(Element-wise X)
    Tanh_Op --&amp;gt; Mult_Output
    Mult_Output --&amp;gt; H_next[New Hidden State: h_t]
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;4-coding-the-lstm-equations-from-scratch&quot;&gt;4. Coding the LSTM Equations from Scratch&lt;/h2&gt;

&lt;p&gt;To truly understand it, let’s implement the forward pass of a single LSTM cell strictly using PyTorch tensor operations, mirroring the equations above exactly.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;torch&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;torch.nn&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;RawLSTMCell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;input_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hidden_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input_size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;input_size&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hidden_size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hidden_size&lt;/span&gt;
        
        &lt;span class=&quot;c1&quot;&gt;# We concatenate h and x, so the weight matrix dimension is hidden_size + input_size
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;concat_size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hidden_size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;input_size&lt;/span&gt;
        
        &lt;span class=&quot;c1&quot;&gt;# The 4 linear layers for our 4 gates: Forget, Input, Candidate, Output
&lt;/span&gt;        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;W_f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Linear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;concat_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hidden_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;W_i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Linear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;concat_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hidden_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;W_c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Linear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;concat_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hidden_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;W_o&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Linear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;concat_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hidden_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;forward&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h_prev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c_prev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
        x_t: Tensor of shape (batch_size, input_size)
        h_prev, c_prev: Tensors of shape (batch_size, hidden_size)
        &quot;&quot;&quot;&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# 1. Concatenate h_{t-1} and x_t along the feature dimension
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;combined&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h_prev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        
        &lt;span class=&quot;c1&quot;&gt;# 2. Compute the gates
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;f_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sigmoid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;W_f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;combined&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;# Forget gate: (0 to 1)
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;i_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sigmoid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;W_i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;combined&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;# Input gate: (0 to 1)
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;c_tilde&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tanh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;W_c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;combined&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# Candidate cell: (-1 to 1)
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;o_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sigmoid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;W_o&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;combined&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;# Output gate: (0 to 1)
&lt;/span&gt;        
        &lt;span class=&quot;c1&quot;&gt;# 3. Update the Cell State (The Additive Highway)
&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;# Element-wise multiplication is done using &apos;*&apos; in PyTorch
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;c_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c_prev&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c_tilde&lt;/span&gt;
        
        &lt;span class=&quot;c1&quot;&gt;# 4. Compute the new Hidden State
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;h_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;o_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tanh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c_t&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Let&apos;s test the math!
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;batch_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;input_dim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hidden_dim&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;lstm_cell&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RawLSTMCell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input_dim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hidden_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hidden_dim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Dummy inputs
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;randn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;batch_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;input_dim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;h_0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;zeros&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;batch_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hidden_dim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;c_0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;zeros&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;batch_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hidden_dim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Run one timestep
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c_1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lstm_cell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h_0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c_0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;New Hidden State shape: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# torch.Size([1, 20])
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;New Cell State shape: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# torch.Size([1, 20])
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In &lt;strong&gt;Part 3&lt;/strong&gt;, we will merge Part 1 (CNNs) and Part 2 (LSTMs). We will introduce the mathematical formulation of &lt;em&gt;Spatial Attention&lt;/em&gt;, allowing an LSTM to compute dynamic weight vectors over the spatial grid of a CNN feature map. See you then!&lt;/p&gt;
</content>
 </entry>
 

</feed>