<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Algorithms on Hunter Heidenreich | Senior AI Research Scientist</title><link>https://hunterheidenreich.com/tags/algorithms/</link><description>Recent content in Algorithms on Hunter Heidenreich | Senior AI Research Scientist</description><image><title>Hunter Heidenreich | Senior AI Research Scientist</title><url>https://hunterheidenreich.com/img/avatar.webp</url><link>https://hunterheidenreich.com/img/avatar.webp</link></image><generator>Hugo -- 0.163.3</generator><language>en-US</language><copyright>2026 Hunter Heidenreich</copyright><lastBuildDate>Sun, 28 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://hunterheidenreich.com/tags/algorithms/index.xml" rel="self" type="application/rss+xml"/><item><title>Surge: Fastest Open-Source Chemical Graph Generator</title><link>https://hunterheidenreich.com/notes/chemistry/molecular-design/chemical-space/surge-chemical-graph-generator/</link><pubDate>Sat, 11 Apr 2026 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/chemistry/molecular-design/chemical-space/surge-chemical-graph-generator/</guid><description>McKay et al. present Surge, an open-source constitutional isomer generator that outperforms MOLGEN by orders of magnitude in speed.</description><content:encoded><![CDATA[<h2 id="a-three-stage-canonical-generation-path">A Three-Stage Canonical Generation Path</h2>
<p>Surge is an open-source constitutional isomer generator that enumerates all possible molecular structures for a given molecular formula. It is built on the nauty package for <a href="https://en.wikipedia.org/wiki/Graph_automorphism">graph automorphism</a> computation and uses a three-stage canonical generation path method that decomposes the enumeration problem into progressively refined graph operations. Surge outperforms the previous state-of-the-art (MOLGEN 5.0) by orders of magnitude in speed while running in under 5 MB of RAM regardless of molecule size.</p>
<h2 id="motivation-the-need-for-fast-open-structure-generators">Motivation: The Need for Fast, Open Structure Generators</h2>
<p>Chemical structure generators are essential for <a href="https://en.wikipedia.org/wiki/Computer-assisted_structure_elucidation">computer-assisted structure elucidation</a> (CASE), virtual library creation, and chemical space enumeration (e.g., <a href="/notes/chemistry/datasets/gdb-17/">GDB-17</a>&rsquo;s 166.4 billion molecules). MOLGEN had been the gold standard for decades but is closed-source. The previous best open-source alternative, MAYGEN, was roughly 3x slower than MOLGEN. Reymond&rsquo;s lab used an in-house nauty-based generator for GDB-17 but did not release it publicly. Surge fills this gap as a fast, open-source, and extensible alternative.</p>
<h2 id="the-three-stage-algorithm">The Three-Stage Algorithm</h2>
<p>Given a molecular formula (e.g., $\text{C}_9\text{H}_{18}\text{N}_2\text{O}_4$), Surge proceeds through three stages:</p>
<p><strong>Stage 1 (geng): Simple graph generation.</strong> Computes all connected simple graphs with the appropriate number of non-hydrogen atoms and edges, subject to maximum degree constraints from the molecular formula. These graphs represent molecular topologies without atom types or bond orders. For Lysopine ($\text{C}_9\text{H}_{18}\text{N}_2\text{O}_4$), this produces 534,493 graphs in 1.3 seconds.</p>
<p><strong>Stage 2 (vcolg): Vertex coloring (atom assignment).</strong> Assigns element types (C, N, O, S, etc.) to vertices in all distinct ways, using the automorphism group of each simple graph to avoid generating equivalent assignments. Given a fixed ordering of elements (e.g., $\text{C} &lt; \text{O} &lt; \text{S}$), element assignments are represented as lists $L$ and compared lexicographically. Exactly one representative from each equivalence class is selected by computing the canonical (lexicographically maximal) list:</p>
<p>$$
\text{canon}(L) = \max\{\gamma(L) \mid \gamma \in \text{Aut}(G)\}
$$</p>
<p>A list $L$ is accepted if and only if $\text{canon}(L) = L$, i.e., no automorphism produces a lexicographically larger list. For Lysopine, this expands to 3.0 billion vertex-labeled graphs in 90 seconds.</p>
<p><strong>Stage 3 (multig): Edge multiplicity (bond orders).</strong> Assigns bond multiplicities (single, double, triple) to edges, again using automorphism group factorization to avoid duplicates. For Lysopine, this produces 6.0 billion completed molecules in an additional 100 seconds.</p>
<h2 id="efficient-automorphism-handling-via-group-factorization">Efficient Automorphism Handling via Group Factorization</h2>
<p>The key algorithmic innovation is the factorization of the automorphism group:</p>
<p>$$
\text{Aut}(G) = NM = \{\gamma\delta \mid \gamma \in N,; \delta \in M\}
$$</p>
<p>where $M$ is the &ldquo;minor subgroup&rdquo; generated by transpositions of leaves sharing a common neighbor (&ldquo;flowers&rdquo;), and $N$ is a complete set of coset representatives computed by nauty. A flower is a maximal set of degree-1 vertices (leaves) with the same neighbor. The minor subgroup $M$ is normal in $\text{Aut}(G)$, making the factorization well-defined.</p>
<p><strong>Theorem.</strong> A list $L$ satisfies $L = \text{canon}(L)$ if and only if $L = \max\{\delta(L) \mid \delta \in M\}$ and $L = \max\{\gamma(L) \mid \gamma \in N\}$.</p>
<p>This factorization enables efficient canonicity testing. Maximality under $M$ reduces to enforcing decreasing element order within each flower (simple inequality constraints during recursive assignment). Maximality under $N$ requires explicit testing against the $N$ generators, but $N$ is trivial (identity only) 58% of the time in Stage 2 and 98% of the time in Stage 3.</p>
<h2 id="benchmark-results">Benchmark Results</h2>
<p>Benchmarked against MOLGEN 5.0 on 30 natural product molecular formulas from the COCONUT database on a compute-optimized c2-standard-4 Google Cloud VM, Surge achieves 7-22 million molecules per second with a memory footprint of at most 5 MB regardless of molecule size. Representative results:</p>
<table>
	<thead>
			<tr>
					<th>Formula</th>
					<th>Isomers</th>
					<th>Surge (s)</th>
					<th>MOLGEN (s)</th>
					<th>Speedup</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>$\text{C}_{10}\text{H}_{16}\text{O}_5$</td>
					<td>1.1B</td>
					<td>69</td>
					<td>5,146</td>
					<td>75x</td>
			</tr>
			<tr>
					<td>$\text{C}_9\text{H}_{18}\text{N}_2\text{O}_4$</td>
					<td>6.0B</td>
					<td>289</td>
					<td>27,250</td>
					<td>94x</td>
			</tr>
			<tr>
					<td>$\text{C}_{11}\text{H}_{12}\text{O}_4$</td>
					<td>31.6B</td>
					<td>2,179</td>
					<td>181,725</td>
					<td>83x</td>
			</tr>
			<tr>
					<td>$\text{C}_{10}\text{H}_{13}\text{NO}_5$</td>
					<td>552B</td>
					<td>54,372</td>
					<td>6,325,646</td>
					<td>116x</td>
			</tr>
			<tr>
					<td>$\text{C}_{10}\text{H}_{10}\text{N}_2\text{O}_3$</td>
					<td>1.5T</td>
					<td>83,186</td>
					<td>8,292,585</td>
					<td>100x</td>
			</tr>
			<tr>
					<td>$\text{C}_9\text{H}_{12}\text{N}_2\text{O}_5$</td>
					<td>1.8T</td>
					<td>180,727</td>
					<td>13,983,652</td>
					<td>77x</td>
			</tr>
	</tbody>
</table>
<p>MOLGEN hit its built-in limit of $2^{31} - 1$ structures for most formulas; reported times were linearly extrapolated. Both generators were instructed to generate but not output structures. MOLGEN was run with <code>-noaromaticity</code> for fair comparison since Surge v1.0 lacks aromaticity detection.</p>
<p>Surge supports output in both <a href="https://en.wikipedia.org/wiki/Chemical_table_file">SDfile</a> and <a href="/notes/chemistry/molecular-representations/notations/smiles/">SMILES</a> formats. SMILES output is produced efficiently by constructing a template for each simple graph at Stage 1, so that only atom types and bond multiplicities must be filled in before output.</p>
<p>Surge also supports built-in filters applied during generation (more efficient than post-hoc filtering):</p>
<ul>
<li><code>-p0:1</code>: at most one cycle of length 5</li>
<li><code>-P</code>: the molecule must be planar</li>
<li><code>-B5</code>: no atom has two double bonds and otherwise only hydrogen neighbors</li>
<li><code>-B9</code>: no atom lies on more than one cycle of length 3 or 4</li>
</ul>
<p>These filter options are inspired by corresponding features in MOLGEN. Surge&rsquo;s open-source design also supports a plugin mechanism: users can write small code snippets to insert custom filters into any of the three stages, enabling efficient pruning of the generation tree.</p>
<h2 id="limitations">Limitations</h2>
<ul>
<li>Version 1.0 does not perform <a href="https://en.wikipedia.org/wiki/H%C3%BCckel%27s_rule">Hückel aromaticity</a> detection, so it generates duplicate <a href="https://en.wikipedia.org/wiki/Aromaticity">Kekulé structures</a> for aromatic rings that are graph-theoretically distinct</li>
<li>Benchmarking against MOLGEN required disabling MOLGEN&rsquo;s aromaticity detection (<code>-noaromaticity</code>) for fair comparison</li>
<li>Written in C (from the nauty suite), which limits accessibility compared to Python-based tools, though this is also the source of its speed</li>
</ul>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<table>
	<thead>
			<tr>
					<th>Artifact</th>
					<th>Type</th>
					<th>License</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><a href="https://github.com/structuregenerator/surge">Surge on GitHub</a></td>
					<td>Code</td>
					<td>Apache 2.0</td>
					<td>Official C implementation from the nauty suite</td>
			</tr>
			<tr>
					<td><a href="https://structuregenerator.github.io">Surge project page</a></td>
					<td>Other</td>
					<td>Apache 2.0</td>
					<td>Project homepage with documentation and binaries</td>
			</tr>
	</tbody>
</table>
<ul>
<li><strong>Status</strong>: Highly Reproducible. Source code, build instructions, and benchmark formulas are all publicly available.</li>
<li><strong>Hardware</strong>: Benchmarks used a compute-optimized c2-standard-4 Google Cloud VM. Surge runs in at most 5 MB of RAM regardless of molecule size.</li>
<li><strong>Build</strong>: Standard Unix Configure/Make scheme producing a standalone command-line executable. Written in portable C from the nauty suite.</li>
<li><strong>Dependencies</strong>: Requires the nauty package (bundled).</li>
</ul>
<h2 id="paper-information">Paper Information</h2>
<ul>
<li><strong>Published</strong>: Journal of Cheminformatics, Volume 14, Article 24, April 23, 2022</li>
<li><strong>Preprint</strong>: ChemRxiv, December 7, 2021</li>
<li><strong>License</strong>: Apache 2.0 (software), Open Access (paper)</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@article</span>{mckay2022surge,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>=<span style="color:#e6db74">{Surge: a fast open-source chemical graph generator}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>=<span style="color:#e6db74">{McKay, Brendan D. and Yirik, Mehmet Aziz and Steinbeck, Christoph}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">journal</span>=<span style="color:#e6db74">{Journal of Cheminformatics}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">volume</span>=<span style="color:#e6db74">{14}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">number</span>=<span style="color:#e6db74">{1}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span>=<span style="color:#e6db74">{24}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span>=<span style="color:#e6db74">{2022}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">publisher</span>=<span style="color:#e6db74">{BioMed Central}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">doi</span>=<span style="color:#e6db74">{10.1186/s13321-022-00604-9}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Liquid-S4: Input-Dependent State-Space Models</title><link>https://hunterheidenreich.com/notes/machine-learning/model-architectures/liquid-s4-state-space-models/</link><pubDate>Tue, 07 Apr 2026 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/machine-learning/model-architectures/liquid-s4-state-space-models/</guid><description>Liquid-S4 combines liquid time-constant networks with structured state-space models, adding input-dependent kernels for long-range sequence modeling.</description><content:encoded><![CDATA[<h2 id="a-method-for-input-adaptive-sequence-modeling">A Method for Input-Adaptive Sequence Modeling</h2>
<p>This is a <strong>Method</strong> paper that introduces Liquid-S4, a new state-space model combining the structured state-space framework (S4) with liquid time-constant (LTC) networks. The primary contribution is an input-dependent state transition mechanism that allows the model to adapt its dynamics based on incoming inputs, while retaining the efficient convolutional kernel computation of S4.</p>
<h2 id="scaling-liquid-networks-to-long-sequences">Scaling Liquid Networks to Long Sequences</h2>
<p>Liquid time-constant (LTC) networks are continuous-time neural networks with input-dependent state transitions, giving them strong generalization and causal modeling properties. However, LTCs rely on ODE solvers that limit their scalability to long sequences. Structured state-space models (S4) solve this scalability problem through HiPPO initialization, diagonal plus low-rank (DPLR) parameterization, and efficient Cauchy kernel computation in the frequency domain, but they use fixed (input-independent) state transitions.</p>
<p>The key question this paper addresses: can the expressivity of LTC networks be combined with the efficiency and scalability of S4 to improve long-range sequence modeling?</p>
<h2 id="the-liquid-kernel-input-dependent-convolutions">The Liquid Kernel: Input-Dependent Convolutions</h2>
<p>The core innovation is a linearized LTC state-space model that replaces the standard SSM dynamics:</p>
<p>$$\dot{x}(t) = \mathbf{A}x(t) + \mathbf{B}u(t)$$</p>
<p>with an input-dependent formulation:</p>
<p>$$\dot{x}(t) = \left[\mathbf{A} + \mathbf{B}u(t)\right]x(t) + \mathbf{B}u(t)$$</p>
<p>where $u(t)$ now modulates the state transition matrix itself. After discretization via the <a href="https://en.wikipedia.org/wiki/Bilinear_transform">bilinear transform</a>, the recurrence becomes:</p>
<p>$$x_{k} = \left(\overline{\mathbf{A}} + \overline{\mathbf{B}}u_{k}\right)x_{k-1} + \overline{\mathbf{B}}u_{k}$$</p>
<p>Unrolling this recurrence reveals that the output $y_{k}$ decomposes into two parts:</p>
<p>$$y = \overline{\mathbf{K}} * u + \overline{\mathbf{K}}_{\text{liquid}} * u_{\text{correlations}}$$</p>
<p>The first term is the standard S4 convolutional kernel $\overline{\mathbf{K}}$, mapping individual input time steps independently. The second term is a new &ldquo;liquid kernel&rdquo; $\overline{\mathbf{K}}_{\text{liquid}}$ that operates on <a href="https://en.wikipedia.org/wiki/Autocorrelation">auto-correlation</a> terms of the input signal (products $u_{i}u_{j}$, $u_{i}u_{j}u_{k}$, etc., up to a chosen order $\mathcal{P}$).</p>
<p><strong>Proposition 1</strong> shows that each liquid kernel of order $p$ can be computed from the precomputed S4 kernel via a <a href="https://en.wikipedia.org/wiki/Hadamard_product_(matrices)">Hadamard product</a> with $\overline{\mathbf{B}}^{p-1}$ followed by an anti-diagonal transformation (flip):</p>
<p>$$\overline{\mathbf{K}}_{\text{liquid}=p} = \left[\overline{\mathbf{K}}_{(L-\tilde{L},L)} \odot \overline{\mathbf{B}}_{(L-\tilde{L},L)}^{p-1}\right] * \mathbf{J}_{\tilde{L}}$$</p>
<p>This is the KB (Kernel $\times$ B) mode. The authors also propose a simplified PB (Powers of B) mode that sets the transition matrix $\overline{\mathbf{A}}$ to identity for the correlation terms:</p>
<p>$$\overline{\mathbf{K}}_{\text{liquid}=p} = \overline{\mathbf{C}} \odot \overline{\mathbf{B}}^{p-1}$$</p>
<p>The PB kernel is cheaper to compute and performs equally well or better in practice.</p>
<p>The computational complexity is $\tilde{\mathcal{O}}(N + L + p_{\text{max}}\tilde{L})$, where $N$ is the state size, $L$ the sequence length, $p_{\text{max}}$ the maximum liquid order, and $\tilde{L}$ the liquid kernel length (typically two orders of magnitude smaller than $L$).</p>
<h2 id="benchmarks-across-long-range-sequence-tasks">Benchmarks Across Long-Range Sequence Tasks</h2>
<p>Liquid-S4 is evaluated on four benchmark suites with the PB kernel using the S4-LegS (scaled <a href="https://en.wikipedia.org/wiki/Legendre_polynomials">Legendre</a>) parameterization.</p>
<h3 id="long-range-arena-lra">Long Range Arena (LRA)</h3>
<p>The LRA benchmark contains six tasks with sequence lengths from 1K to 16K. Liquid-S4 achieves state-of-the-art on all six tasks with an average accuracy of 87.32%:</p>
<table>
	<thead>
			<tr>
					<th>Task</th>
					<th>Input Length</th>
					<th>Liquid-S4</th>
					<th>S4-LegS</th>
					<th>Improvement</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>ListOps</td>
					<td>2048</td>
					<td>62.75%</td>
					<td>59.60%</td>
					<td>+3.15%</td>
			</tr>
			<tr>
					<td>Text (IMDB)</td>
					<td>2048</td>
					<td>89.02%</td>
					<td>86.82%</td>
					<td>+2.20%</td>
			</tr>
			<tr>
					<td>Retrieval (AAN)</td>
					<td>4000</td>
					<td>91.20%</td>
					<td>90.90%</td>
					<td>+0.30%</td>
			</tr>
			<tr>
					<td>Image (CIFAR)</td>
					<td>1024</td>
					<td>89.50%</td>
					<td>88.65%</td>
					<td>+0.85%</td>
			</tr>
			<tr>
					<td>Pathfinder</td>
					<td>1024</td>
					<td>94.80%</td>
					<td>94.20%</td>
					<td>+0.60%</td>
			</tr>
			<tr>
					<td>Path-X</td>
					<td>16384</td>
					<td>96.66%</td>
					<td>96.35%</td>
					<td>+0.31%</td>
			</tr>
			<tr>
					<td><strong>Average</strong></td>
					<td></td>
					<td><strong>87.32%</strong></td>
					<td><strong>86.09%</strong></td>
					<td><strong>+1.23%</strong></td>
			</tr>
	</tbody>
</table>
<p>Liquid orders $p$ range from 2 to 6 across tasks.</p>
<h3 id="bidmc-vital-signs">BIDMC Vital Signs</h3>
<p>On medical time-series regression (heart rate, respiratory rate, <a href="https://en.wikipedia.org/wiki/Oxygen_saturation_(medicine)">SpO2</a> prediction from length-4000 biomarker signals):</p>
<table>
	<thead>
			<tr>
					<th>Task</th>
					<th>Liquid-S4 (RMSE)</th>
					<th>S4-LegS (RMSE)</th>
					<th>Improvement</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Heart Rate</td>
					<td>0.303</td>
					<td>0.332</td>
					<td>8.7%</td>
			</tr>
			<tr>
					<td>Respiratory Rate</td>
					<td>0.158</td>
					<td>0.247</td>
					<td>36.0%</td>
			</tr>
			<tr>
					<td>SpO2</td>
					<td>0.066</td>
					<td>0.090</td>
					<td>26.7%</td>
			</tr>
	</tbody>
</table>
<h3 id="sequential-cifar-scifar">Sequential CIFAR (sCIFAR)</h3>
<p>Liquid-S4 with $p=3$ achieves 92.02% accuracy on 1-D pixel-level image classification, improving over S4-LegS (91.80%).</p>
<h3 id="speech-commands-full-35-labels">Speech Commands (Full 35 Labels)</h3>
<p>On the raw 16kHz speech recognition task, Liquid-S4 achieves 96.78% accuracy with only 224K parameters, a 30% reduction compared to S4&rsquo;s 307K. On the zero-shot 8kHz experiment, performance drops to 90.00% (vs. 91.32% for S4-LegS), which the authors attribute to the liquid kernel&rsquo;s sensitivity to input covariance structure at different sampling rates.</p>
<h2 id="consistent-improvements-with-smaller-models">Consistent Improvements with Smaller Models</h2>
<p>Liquid-S4 achieves state-of-the-art performance on every benchmark evaluated: all six LRA tasks (87.32% average), all three BIDMC vital signs tasks, sCIFAR, and full Speech Commands recognition. The gains are particularly large on tasks where input correlation structure matters (ListOps +3.15%, IMDB +2.20%, respiratory rate RMSE improvement of 36%).</p>
<p>A practical advantage is that Liquid-S4 works well with smaller state sizes (as low as 7 units for some tasks), reducing parameter counts. The PB kernel is recommended over KB for its simplicity and competitive performance. Higher liquid orders ($p$) consistently improve performance, though $p=3$ is recommended as a default.</p>
<p>Limitations include degraded performance in zero-shot frequency transfer (8kHz Speech Commands), suggesting the liquid kernel&rsquo;s input covariance terms may not generalize well across sampling rate changes. The paper also does not compare against non-SSM approaches beyond the LRA benchmark. The causal (unidirectional) configuration works better than bidirectional for Liquid-S4, which may limit applicability to tasks that benefit from bidirectional context.</p>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<p><strong>Classification: Partially Reproducible.</strong> Code and all benchmark datasets are publicly available, with complete hyperparameters documented. No pre-trained weights are released and hardware requirements are not specified.</p>
<h3 id="artifacts">Artifacts</h3>
<table>
	<thead>
			<tr>
					<th>Artifact</th>
					<th>Type</th>
					<th>License</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><a href="https://github.com/raminmh/liquid-s4">raminmh/liquid-s4</a></td>
					<td>Code</td>
					<td>Apache-2.0</td>
					<td>Official PyTorch implementation; fork of the S4 repo with KB and PB kernels added</td>
			</tr>
	</tbody>
</table>
<h3 id="data">Data</h3>
<table>
	<thead>
			<tr>
					<th>Purpose</th>
					<th>Dataset</th>
					<th>Size</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Evaluation</td>
					<td>Long Range Arena (LRA)</td>
					<td>6 tasks, 1K-16K seq length</td>
					<td>ListOps, IMDB, AAN, CIFAR, Pathfinder, Path-X</td>
			</tr>
			<tr>
					<td>Evaluation</td>
					<td>BIDMC Vital Signs</td>
					<td>4000-length biomarker signals</td>
					<td>Heart rate, respiratory rate, SpO2</td>
			</tr>
			<tr>
					<td>Evaluation</td>
					<td>sCIFAR</td>
					<td>1024-length flattened images</td>
					<td>10-class classification</td>
			</tr>
			<tr>
					<td>Evaluation</td>
					<td>Speech Commands</td>
					<td>16kHz raw audio, 35 labels</td>
					<td>Full dataset with zero-shot 8kHz test</td>
			</tr>
	</tbody>
</table>
<h3 id="algorithms">Algorithms</h3>
<p>The Liquid-S4 kernel computation builds on the S4 kernel pipeline:</p>
<ol>
<li>Initialize $\mathbf{A}$ with HiPPO (scaled Legendre) matrix in DPLR form</li>
<li>Compute S4 kernel $\overline{\mathbf{K}}$ via Cauchy kernel and iFFT</li>
<li>For each liquid order $p \in {2, \ldots, \mathcal{P}}$, compute $\overline{\mathbf{K}}_{\text{liquid}=p}$ using either KB or PB mode</li>
<li>Convolve $\overline{\mathbf{K}}_{\text{liquid}}$ with input correlation vector $u_{\text{correlations}}$</li>
</ol>
<p>The PB kernel mode is used in all reported experiments. The PyKeops package is used for large tensor computations.</p>
<h3 id="models">Models</h3>
<table>
	<thead>
			<tr>
					<th>Task</th>
					<th>Depth</th>
					<th>Features</th>
					<th>State Size</th>
					<th>Norm</th>
					<th>LR</th>
					<th>Epochs</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>ListOps</td>
					<td>9</td>
					<td>128</td>
					<td>7</td>
					<td>BN</td>
					<td>0.002</td>
					<td>30</td>
			</tr>
			<tr>
					<td>IMDB</td>
					<td>4</td>
					<td>128</td>
					<td>7</td>
					<td>BN</td>
					<td>0.003</td>
					<td>50</td>
			</tr>
			<tr>
					<td>AAN</td>
					<td>6</td>
					<td>256</td>
					<td>64</td>
					<td>BN</td>
					<td>0.005</td>
					<td>20</td>
			</tr>
			<tr>
					<td>CIFAR (LRA)</td>
					<td>6</td>
					<td>512</td>
					<td>512</td>
					<td>LN</td>
					<td>0.01</td>
					<td>200</td>
			</tr>
			<tr>
					<td>Pathfinder</td>
					<td>6</td>
					<td>256</td>
					<td>64</td>
					<td>BN</td>
					<td>0.0004</td>
					<td>200</td>
			</tr>
			<tr>
					<td>Path-X</td>
					<td>6</td>
					<td>320</td>
					<td>64</td>
					<td>BN</td>
					<td>0.001</td>
					<td>60</td>
			</tr>
			<tr>
					<td>Speech Commands</td>
					<td>6</td>
					<td>128</td>
					<td>7</td>
					<td>BN</td>
					<td>0.008</td>
					<td>50</td>
			</tr>
			<tr>
					<td>BIDMC (HR)</td>
					<td>6</td>
					<td>128</td>
					<td>256</td>
					<td>LN</td>
					<td>0.005</td>
					<td>500</td>
			</tr>
			<tr>
					<td>BIDMC (RR)</td>
					<td>6</td>
					<td>128</td>
					<td>256</td>
					<td>LN</td>
					<td>0.01</td>
					<td>500</td>
			</tr>
			<tr>
					<td>BIDMC (SpO2)</td>
					<td>6</td>
					<td>128</td>
					<td>256</td>
					<td>LN</td>
					<td>0.01</td>
					<td>500</td>
			</tr>
			<tr>
					<td>sCIFAR</td>
					<td>6</td>
					<td>512</td>
					<td>512</td>
					<td>LN</td>
					<td>0.01</td>
					<td>200</td>
			</tr>
	</tbody>
</table>
<p>Liquid-S4 generally requires smaller learning rates than S4/S4D. $\Delta t_{\text{max}} = 0.2$ for all experiments; $\Delta t_{\text{min}} \propto 1/\text{seq_length}$.</p>
<h3 id="evaluation">Evaluation</h3>
<p>All results report validation accuracy (except BIDMC, which reports test RMSE). Experiments use 2-3 random seeds with standard deviations reported.</p>
<h3 id="hardware">Hardware</h3>
<p>Not specified in the paper.</p>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Hasani, R., Lechner, M., Wang, T.-H., Chahine, M., Amini, A., &amp; Rus, D. (2022). Liquid Structural State-Space Models. <em>arXiv preprint arXiv:2209.12951</em>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@misc</span>{hasani2022liquid,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>=<span style="color:#e6db74">{Liquid Structural State-Space Models}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>=<span style="color:#e6db74">{Hasani, Ramin and Lechner, Mathias and Wang, Tsun-Hsuan and Chahine, Makram and Amini, Alexander and Rus, Daniela}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span>=<span style="color:#e6db74">{2022}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">eprint</span>=<span style="color:#e6db74">{2209.12951}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">archiveprefix</span>=<span style="color:#e6db74">{arXiv}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">primaryclass</span>=<span style="color:#e6db74">{cs.LG}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Lagrangian Neural Networks for Physics</title><link>https://hunterheidenreich.com/notes/machine-learning/model-architectures/lagrangian-neural-networks/</link><pubDate>Tue, 07 Apr 2026 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/machine-learning/model-architectures/lagrangian-neural-networks/</guid><description>LNNs parameterize arbitrary Lagrangians with neural networks, learning energy-conserving dynamics without requiring canonical coordinates.</description><content:encoded><![CDATA[<h2 id="a-method-for-learning-arbitrary-lagrangians">A Method for Learning Arbitrary Lagrangians</h2>
<p>This is a <strong>Method</strong> paper that introduces Lagrangian Neural Networks (LNNs), a neural network architecture that parameterizes arbitrary Lagrangians to learn energy-conserving dynamics from data. The key contribution is showing that neural networks can learn Lagrangian functions directly, and that the Euler-Lagrange equation can be solved numerically using automatic differentiation to produce physically consistent dynamics. The approach is strictly more general than prior methods: it does not require canonical coordinates (unlike Hamiltonian Neural Networks) and does not restrict the functional form of kinetic energy (unlike Deep Lagrangian Networks).</p>
<h2 id="why-standard-neural-networks-fail-at-conservation-laws">Why Standard Neural Networks Fail at Conservation Laws</h2>
<p>Neural networks struggle to learn fundamental symmetries and conservation laws from data. A standard neural network trained on trajectories of a <a href="https://en.wikipedia.org/wiki/Double_pendulum">double pendulum</a> will gradually dissipate energy over long rollouts, producing physically implausible behavior. This happens because unconstrained function approximators have no inductive bias toward conservation.</p>
<p>Hamiltonian Neural Networks (HNNs) addressed this by learning a Hamiltonian function, which automatically enforces energy conservation. However, the <a href="https://en.wikipedia.org/wiki/Hamiltonian_mechanics">Hamiltonian formalism</a> requires inputs in <a href="https://en.wikipedia.org/wiki/Canonical_coordinates">canonical coordinates</a> $(q, p)$ satisfying strict <a href="https://en.wikipedia.org/wiki/Poisson_bracket">Poisson bracket</a> relations:</p>
<p>$$
p_i \equiv \frac{\partial \mathcal{L}}{\partial \dot{q}_i} \quad \Longleftrightarrow \quad {q_i, q_j} = 0, \quad {p_i, p_j} = 0, \quad {q_i, p_j} = \delta_{ij}
$$</p>
<p>In many real-world settings, the canonical momenta are unknown or difficult to compute. For example, in special relativity the canonical momentum $\dot{q}(1 - \dot{q}^2)^{-3/2}$ is a complex nonlinear function of velocity. Deep Lagrangian Networks (DeLaNs) partially addressed this by learning Lagrangians, but they assumed kinetic energy takes the rigid-body form $T = \dot{q}^T M \dot{q}$, which excludes relativistic and other non-standard systems.</p>
<h2 id="solving-euler-lagrange-for-a-black-box-lagrangian">Solving Euler-Lagrange for a Black-Box Lagrangian</h2>
<p>The core innovation of LNNs is a method for computing accelerations from a neural network that represents an arbitrary Lagrangian $\mathcal{L}(q, \dot{q})$. Starting from the <a href="https://en.wikipedia.org/wiki/Euler%E2%80%93Lagrange_equation">Euler-Lagrange equation</a>:</p>
<p>$$
\frac{d}{dt} \nabla_{\dot{q}} \mathcal{L} = \nabla_{q} \mathcal{L}
$$</p>
<p>The authors expand the time derivative using the chain rule, yielding:</p>
<p>$$
\left(\nabla_{\dot{q}} \nabla_{\dot{q}}^{\top} \mathcal{L}\right) \ddot{q} + \left(\nabla_{q} \nabla_{\dot{q}}^{\top} \mathcal{L}\right) \dot{q} = \nabla_{q} \mathcal{L}
$$</p>
<p>Solving for the accelerations gives:</p>
<p>$$
\ddot{q} = \left(\nabla_{\dot{q}} \nabla_{\dot{q}}^{\top} \mathcal{L}\right)^{-1} \left[ \nabla_{q} \mathcal{L} - \left(\nabla_{q} \nabla_{\dot{q}}^{\top} \mathcal{L}\right) \dot{q} \right]
$$</p>
<p>This requires computing the Hessian of the neural network with respect to $\dot{q}$ and then inverting it (using a pseudoinverse for numerical stability). JAX&rsquo;s automatic differentiation makes this feasible in just a few lines of code, despite the seemingly complex chain of second-order derivatives. The matrix inverse scales as $\mathcal{O}(d^3)$ with the number of coordinates $d$.</p>
<p>A critical implementation detail is the choice of activation function. Since the method takes second-order derivatives of the network, ReLU is unsuitable (its second derivative is zero everywhere). After a hyperparameter search over ReLU$^2$, ReLU$^3$, tanh, sigmoid, and softplus, the authors found <a href="https://en.wikipedia.org/wiki/Softplus">softplus</a> performed best.</p>
<p>The authors also developed a custom initialization scheme, using symbolic regression to find initialization variances that maintain well-conditioned gradients through the Hessian computation:</p>
<p>$$
\sigma = \frac{1}{\sqrt{n}} \begin{cases} 2.2 &amp; \text{First layer} \\ 0.58i &amp; \text{Hidden layer } i \\ n &amp; \text{Output layer} \end{cases}
$$</p>
<h2 id="extension-to-graphs-and-continuous-systems">Extension to Graphs and Continuous Systems</h2>
<p>LNNs extend naturally to graph-structured and continuous systems via Lagrangian <a href="/notes/machine-learning/model-architectures/relational-inductive-biases-deep-learning-graph-networks/">Graph Networks</a>. For a system with $n$ gridpoints, the total Lagrangian is decomposed into local densities:</p>
<p>$$
\mathcal{L} = \sum_{i=1}^{n} \mathcal{L}_i, \quad \text{where} \quad \mathcal{L}_i = \mathcal{L}_{\text{density}}\left({\phi_j, \dot{\phi}_j}_{j \in \mathcal{I}_i}\right)
$$</p>
<p>Here $\mathcal{I}_i$ defines the neighborhood of node $i$ (e.g., ${i-1, i, i+1}$ for a 1D grid). The Lagrangian density is modeled as an MLP. The resulting Hessian matrix is sparse, with non-zero entries only at &ldquo;neighbor of neighbor&rdquo; positions, enabling efficient computation: in 1D, only 5 forward-over-backward autodiff passes are needed, and the tridiagonal inverse runs in linear time.</p>
<h2 id="experiments-double-pendulum-relativity-and-waves">Experiments: Double Pendulum, Relativity, and Waves</h2>
<p>All models used 4-layer MLPs with 500 hidden units, softplus activations, a decaying learning rate starting at $10^{-3}$, and batch size 32.</p>
<h3 id="double-pendulum">Double Pendulum</h3>
<p>The LNN and baseline achieved similar instantaneous acceleration losses ($7.3$ vs. $7.4 \times 10^{-2}$). The key difference appeared in long-term energy conservation: averaged over 40 random initial conditions with 100 time steps, the mean energy discrepancy was 8% of max potential energy for the baseline but only 0.4% for the LNN.</p>
<h3 id="relativistic-particle">Relativistic Particle</h3>
<p>For a particle with Lagrangian $\mathcal{L} = ((1 - \dot{q}^2)^{-1/2} - 1) + gq$, the canonical momenta $\dot{q}(1 - \dot{q}^2)^{-3/2}$ are non-trivial. An HNN trained on non-canonical coordinates $(q, \dot{q})$ failed to learn the dynamics. The LNN succeeded using the same non-canonical coordinates, matching the performance of an HNN given the correct canonical coordinates.</p>
<h3 id="1d-wave-equation">1D Wave Equation</h3>
<p>The Lagrangian Graph Network learned the wave equation dynamics ($\ddot{\phi} = \frac{\partial^2 \phi}{\partial x^2}$ with $c = 1$) on a 100-gridpoint domain with periodic boundary conditions. The network learned the Lagrangian density corresponding to the continuum form $\mathcal{L} = \int (\dot{\phi}^2 - (\partial \phi / \partial x)^2) dx$, accurately modeling wave propagation and conserving energy across the material.</p>
<table>
	<thead>
			<tr>
					<th>Experiment</th>
					<th>Model</th>
					<th>Energy Error (% of max PE)</th>
					<th>Canonical Coords Required</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Double Pendulum</td>
					<td>Baseline</td>
					<td>8%</td>
					<td>N/A</td>
			</tr>
			<tr>
					<td>Double Pendulum</td>
					<td>LNN</td>
					<td>0.4%</td>
					<td>No</td>
			</tr>
			<tr>
					<td>Relativistic Particle</td>
					<td>HNN (non-canonical)</td>
					<td>Failed</td>
					<td>Yes</td>
			</tr>
			<tr>
					<td>Relativistic Particle</td>
					<td>HNN (canonical)</td>
					<td>Succeeded</td>
					<td>Yes</td>
			</tr>
			<tr>
					<td>Relativistic Particle</td>
					<td>LNN</td>
					<td>Succeeded</td>
					<td>No</td>
			</tr>
			<tr>
					<td>1D Wave Equation</td>
					<td>LGN</td>
					<td>Energy conserved</td>
					<td>No</td>
			</tr>
	</tbody>
</table>
<h2 id="findings-and-comparison-to-prior-approaches">Findings and Comparison to Prior Approaches</h2>
<p>LNNs combine several desirable properties that no single prior method offers:</p>
<table>
	<thead>
			<tr>
					<th>Property</th>
					<th>Neural Net</th>
					<th>Neural ODE</th>
					<th>HNN</th>
					<th>DeLaN</th>
					<th>LNN</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Models dynamical systems</td>
					<td>Yes</td>
					<td>Yes</td>
					<td>Yes</td>
					<td>Yes</td>
					<td>Yes</td>
			</tr>
			<tr>
					<td>Learns differential equations</td>
					<td></td>
					<td>Yes</td>
					<td>Yes</td>
					<td>Yes</td>
					<td>Yes</td>
			</tr>
			<tr>
					<td>Learns exact conservation laws</td>
					<td></td>
					<td></td>
					<td>Yes</td>
					<td>Yes</td>
					<td>Yes</td>
			</tr>
			<tr>
					<td>Learns from arbitrary coordinates</td>
					<td>Yes</td>
					<td>Yes</td>
					<td></td>
					<td>Yes</td>
					<td>Yes</td>
			</tr>
			<tr>
					<td>Learns arbitrary Lagrangians</td>
					<td></td>
					<td></td>
					<td></td>
					<td></td>
					<td>Yes</td>
			</tr>
	</tbody>
</table>
<p>The main limitation is computational cost: the Hessian computation and inversion scale as $\mathcal{O}(d^3)$ in the number of coordinates. The Lagrangian Graph Network partially mitigates this for spatially extended systems through the sparsity of the resulting Hessian. The method also assumes access to state derivatives ($\dot{q}$) during training, which may not always be directly available from observations.</p>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="data">Data</h3>
<table>
	<thead>
			<tr>
					<th>Purpose</th>
					<th>Dataset</th>
					<th>Size</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Training</td>
					<td>Double pendulum</td>
					<td>600,000 random initial conditions</td>
					<td>Simulated with masses and lengths set to 1</td>
			</tr>
			<tr>
					<td>Training</td>
					<td>Relativistic particle</td>
					<td>Random initial conditions and $g$ values</td>
					<td>$c = 1$, mass = 1, uniform potential</td>
			</tr>
			<tr>
					<td>Training</td>
					<td>1D wave equation</td>
					<td>100 gridpoints</td>
					<td>Periodic boundary conditions, $c = 1$</td>
			</tr>
	</tbody>
</table>
<h3 id="algorithms">Algorithms</h3>
<ul>
<li>Forward model: Euler-Lagrange equation solved via Equation 6 using JAX autodiff</li>
<li>Pseudoinverse used for Hessian inversion to handle potential singular matrices</li>
<li>Custom initialization scheme (Equation 16) derived via symbolic regression with eureqa</li>
<li>Softplus activation selected via hyperparameter search</li>
</ul>
<h3 id="models">Models</h3>
<ul>
<li>4-layer MLP with 500 hidden units for all experiments</li>
<li>Softplus activation function</li>
<li>Code: <a href="https://github.com/MilesCranmer/lagrangian_nns">github.com/MilesCranmer/lagrangian_nns</a> (Apache-2.0)</li>
</ul>
<h3 id="evaluation">Evaluation</h3>
<table>
	<thead>
			<tr>
					<th>Metric</th>
					<th>LNN</th>
					<th>Baseline</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Acceleration loss (double pendulum)</td>
					<td>$7.3 \times 10^{-2}$</td>
					<td>$7.4 \times 10^{-2}$</td>
					<td>Similar short-term accuracy</td>
			</tr>
			<tr>
					<td>Energy error (double pendulum)</td>
					<td>0.4%</td>
					<td>8%</td>
					<td>Percentage of max potential energy</td>
			</tr>
	</tbody>
</table>
<h3 id="hardware">Hardware</h3>
<p>Not specified in the paper. JAX-based implementation supports CPU and GPU execution.</p>
<hr>
<p><strong>Reproducibility Status</strong>: Highly Reproducible</p>
<h2 id="artifacts">Artifacts</h2>
<table>
	<thead>
			<tr>
					<th>Artifact</th>
					<th>Type</th>
					<th>License</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><a href="https://github.com/MilesCranmer/lagrangian_nns">lagrangian_nns</a></td>
					<td>Code</td>
					<td>Apache-2.0</td>
					<td>Official JAX implementation with notebooks for all experiments</td>
			</tr>
			<tr>
					<td>Training data</td>
					<td>Dataset</td>
					<td>N/A</td>
					<td>Generated procedurally; simulation code included in repository</td>
			</tr>
			<tr>
					<td>Trained models</td>
					<td>Model</td>
					<td>N/A</td>
					<td>Not provided</td>
			</tr>
	</tbody>
</table>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Cranmer, M., Greydanus, S., Hoyer, S., Battaglia, P., Spergel, D., &amp; Ho, S. (2020). Lagrangian Neural Networks. <em>ICLR 2020 Workshop on Integration of Deep Neural Models and Differential Equations</em>. arXiv: <a href="https://arxiv.org/abs/2003.04630">2003.04630</a></p>
<p><strong>Publication</strong>: ICLR 2020 Workshop on Integration of Deep Neural Models and Differential Equations</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@misc</span>{cranmer2020lagrangian,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>=<span style="color:#e6db74">{Lagrangian Neural Networks}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>=<span style="color:#e6db74">{Cranmer, Miles and Greydanus, Sam and Hoyer, Stephan and Battaglia, Peter and Spergel, David and Ho, Shirley}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span>=<span style="color:#e6db74">{2020}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">eprint</span>=<span style="color:#e6db74">{2003.04630}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">archiveprefix</span>=<span style="color:#e6db74">{arXiv}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">primaryclass</span>=<span style="color:#e6db74">{cs.LG}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>STONED: Training-Free Molecular Design with SELFIES</title><link>https://hunterheidenreich.com/notes/chemistry/molecular-design/generation/search-based/stoned-selfies-chemical-space-exploration/</link><pubDate>Wed, 25 Mar 2026 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/chemistry/molecular-design/generation/search-based/stoned-selfies-chemical-space-exploration/</guid><description>STONED uses string mutations in the SELFIES representation for training-free molecular generation, interpolation, and chemical space exploration.</description><content:encoded><![CDATA[<h2 id="a-training-free-algorithm-for-molecular-generation">A Training-Free Algorithm for Molecular Generation</h2>
<p>This is a <strong>Method</strong> paper that introduces STONED (Superfast Traversal, Optimization, Novelty, Exploration and Discovery), a suite of algorithms for molecular generation and chemical space exploration. STONED operates entirely through string manipulations on the <a href="/notes/chemistry/molecular-representations/notations/selfies/">SELFIES</a> molecular representation, avoiding the need for deep learning models, training data, or GPU resources. The key claim is that simple character-level mutations and interpolations in SELFIES can achieve results competitive with state-of-the-art deep generative models on standard benchmarks.</p>
<h2 id="why-deep-generative-models-may-be-overkill">Why Deep Generative Models May Be Overkill</h2>
<p>Deep generative models (VAEs, GANs, RNNs, reinforcement learning) have become popular for <a href="/notes/chemistry/molecular-design/generation/evaluation/inverse-molecular-design-ml-review/">inverse molecular design</a>, but they come with practical costs: large training datasets, expensive GPU compute, and long training times. Fragile representations like <a href="/notes/chemistry/molecular-representations/notations/smiles/">SMILES</a> compound the problem, since large portions of a latent space can map to invalid molecules. Even with the introduction of SELFIES (a 100% valid string representation), prior work still embedded it within neural network architectures.</p>
<p>The authors argue that for tasks like local chemical space exploration and molecular interpolation, the guarantees of SELFIES alone may be sufficient. Because every SELFIES string maps to a valid molecule, random character mutations always produce valid structures. This observation eliminates the need for learned generation procedures entirely.</p>
<h2 id="core-innovation-selfies-string-mutations-as-molecular-operators">Core Innovation: SELFIES String Mutations as Molecular Operators</h2>
<p>STONED relies on four key techniques built on SELFIES string manipulations:</p>
<p><strong>1. Random character mutations.</strong> A point mutation in SELFIES (character replacement, deletion, or addition) always yields a valid molecule. The position of mutations serves as a hyperparameter controlling exploration vs. exploitation: terminal character mutations preserve more structural similarity to the seed, while random mutations explore more broadly.</p>
<p><strong>2. Multiple SMILES orderings.</strong> A single molecule has many valid SMILES strings, each mapping to a different SELFIES. By generating 50,000 SMILES orderings and converting to SELFIES before mutation, the diversity of generated structures increases substantially.</p>
<p><strong>3. Deterministic interpolation.</strong> Given two SELFIES strings (padded to equal length), characters at equivalent positions can be successively replaced from the start molecule to the target molecule. Every intermediate string is a valid molecule. A chemical path is extracted by keeping only those intermediates that increase fingerprint similarity to the target.</p>
<p><strong>4. Fingerprint-based filtering.</strong> Since edit distance in SELFIES does not reflect molecular similarity, STONED uses fingerprint comparisons (ECFP4, FCFP4, atom-pair) to enforce structural similarity constraints.</p>
<p>The authors also propose a revised joint molecular similarity metric for evaluating median molecules. Given $n$ reference molecules $M = {m_1, m_2, \ldots, m_n}$, the joint similarity of a candidate molecule $m$ is:</p>
<p>$$
F(m) = \frac{1}{n} \sum_{i=1}^{n} \text{sim}(m_i, m) - \left[\max_{i} \text{sim}(m_i, m) - \min_{i} \text{sim}(m_i, m)\right]
$$</p>
<p>This penalizes candidates that are similar to only a subset of references, unlike the geometric mean metric used in GuacaMol which can yield high scores even with lopsided similarities.</p>
<h2 id="experimental-setup-and-applications">Experimental Setup and Applications</h2>
<h3 id="local-chemical-subspace-formation">Local chemical subspace formation</h3>
<p>Starting from a single seed molecule (<a href="https://en.wikipedia.org/wiki/Aripiprazole">aripiprazole</a>, albuterol, mestranol, or <a href="https://en.wikipedia.org/wiki/Celecoxib">celecoxib</a>), the algorithm generates 50,000 SMILES orderings and performs 1-5 point mutations per ordering, producing 250,000 candidate strings. Unique valid molecules are filtered by fingerprint similarity thresholds.</p>
<table>
	<thead>
			<tr>
					<th>Starting structure</th>
					<th>Fingerprint</th>
					<th>Molecules at $\delta &gt; 0.75$</th>
					<th>Molecules at $\delta &gt; 0.60$</th>
					<th>Molecules at $\delta &gt; 0.40$</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Aripiprazole (SELFIES, random)</td>
					<td>ECFP4</td>
					<td>513 (0.25%)</td>
					<td>4,206 (2.15%)</td>
					<td>34,416 (17.66%)</td>
			</tr>
			<tr>
					<td>Albuterol (SELFIES, random)</td>
					<td>FCFP4</td>
					<td>587 (0.32%)</td>
					<td>4,156 (2.33%)</td>
					<td>16,977 (9.35%)</td>
			</tr>
			<tr>
					<td>Mestranol (SELFIES, random)</td>
					<td>AP</td>
					<td>478 (0.22%)</td>
					<td>4,079 (1.90%)</td>
					<td>45,594 (21.66%)</td>
			</tr>
			<tr>
					<td>Celecoxib (SELFIES, random)</td>
					<td>ECFP4</td>
					<td>198 (0.10%)</td>
					<td>1,925 (1.00%)</td>
					<td>18,045 (9.44%)</td>
			</tr>
			<tr>
					<td>Celecoxib (SELFIES, terminal 10%)</td>
					<td>ECFP4</td>
					<td>864 (2.02%)</td>
					<td>9,407 (21.99%)</td>
					<td>34,187 (79.91%)</td>
			</tr>
	</tbody>
</table>
<p>Key finding: restricting mutations to terminal characters yields a 20x increase in high-similarity molecules compared to random positions. Compared to SMILES mutations (0.30% valid) and <a href="/notes/chemistry/molecular-representations/notations/deepsmiles-adaptation-for-ml/">DeepSMILES</a> (1.44% valid), SELFIES mutations are all valid by construction.</p>
<p>A two-step expansion (mutating all unique first-round neighbors) produced over 17 million unique molecules, with 120,000 having similarity greater than 0.4 to celecoxib.</p>
<h3 id="chemical-path-formation-and-drug-design">Chemical path formation and drug design</h3>
<p>Deterministic SELFIES interpolation between <a href="https://en.wikipedia.org/wiki/Tadalafil">tadalafil</a> and <a href="https://en.wikipedia.org/wiki/Sildenafil">sildenafil</a> generated paths where <a href="https://en.wikipedia.org/wiki/Partition_coefficient">logP</a> and QED values varied smoothly. A more challenging application docked intermediates between <a href="https://en.wikipedia.org/wiki/Dihydroergotamine">dihydroergotamine</a> (<a href="https://en.wikipedia.org/wiki/5-HT1B_receptor">5-HT1B</a> binder) and prinomastat (<a href="https://en.wikipedia.org/wiki/CYP2D6">CYP2D6</a> binder), finding molecules with non-trivial binding affinity to both proteins without any optimization routine.</p>
<h3 id="median-molecules-for-photovoltaics">Median molecules for photovoltaics</h3>
<p>Using 100 triplets from the Harvard Clean Energy (HCE) dataset, each with one molecule optimized for high LUMO energy, one for high dipole moment, and one for high <a href="https://en.wikipedia.org/wiki/HOMO_and_LUMO">HOMO-LUMO gap</a>, generalized chemical paths produced median molecules. These were evaluated with GFN2-xTB semiempirical calculations. The generated medians matched or exceeded the best molecules available in the HCE database in both structural similarity and target properties.</p>
<h3 id="guacamol-benchmarks">GuacaMol benchmarks</h3>
<p>Without any training, STONED achieved an overall <a href="/notes/chemistry/molecular-design/generation/evaluation/guacamol-benchmarking-de-novo-molecular-design/">GuacaMol</a> score of 14.70, competitive with several deep generative models. The approach simply identifies the single best molecule in the benchmark&rsquo;s training set and generates its local chemical subspace. 38% of the top-100 molecules from each benchmark passed compound quality filters, comparable to <a href="/notes/chemistry/molecular-design/generation/search-based/graph-based-genetic-algorithm-chemical-space/">Graph GA</a> and SMILES GA.</p>
<h2 id="results-summary-and-limitations">Results Summary and Limitations</h2>
<p>STONED demonstrates that SELFIES string mutations can match or approach deep generative models on standard molecular design benchmarks while being orders of magnitude faster and requiring no training. The most expensive benchmark (aripiprazole subspace) completed in 500 seconds on a laptop CPU.</p>
<p>The method comparison table from the paper highlights STONED&rsquo;s unique position:</p>
<table>
	<thead>
			<tr>
					<th>Feature</th>
					<th>Expert Systems</th>
					<th>VAE</th>
					<th>GAN</th>
					<th>RL</th>
					<th>STONED</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Expert rule-free</td>
					<td>No</td>
					<td>Yes</td>
					<td>Yes</td>
					<td>Yes</td>
					<td>Yes</td>
			</tr>
			<tr>
					<td>Structure coverage</td>
					<td>Partial</td>
					<td>Partial</td>
					<td>Partial</td>
					<td>Partial</td>
					<td>Yes</td>
			</tr>
			<tr>
					<td>Interpolatability</td>
					<td>No</td>
					<td>Yes</td>
					<td>Yes</td>
					<td>No</td>
					<td>Yes</td>
			</tr>
			<tr>
					<td>Property-based navigation</td>
					<td>Partial</td>
					<td>Yes</td>
					<td>Yes</td>
					<td>Yes</td>
					<td>Partial</td>
			</tr>
			<tr>
					<td>Training-free</td>
					<td>Yes</td>
					<td>No</td>
					<td>No</td>
					<td>No</td>
					<td>Yes</td>
			</tr>
			<tr>
					<td>Data independence</td>
					<td>Yes</td>
					<td>No</td>
					<td>No</td>
					<td>No</td>
					<td>Yes</td>
			</tr>
	</tbody>
</table>
<p><strong>Limitations acknowledged by the authors:</strong></p>
<ul>
<li>STONED lacks property-based navigation (gradient-guided optimization toward specific property targets). It can only do stochastic property optimization when wrapped in a genetic algorithm.</li>
<li>The success rate of mutations leading to structurally similar molecules is relatively low (0.1-2% at high similarity thresholds), though speed compensates.</li>
<li>Chemical paths can contain molecules with unstable functional groups or <a href="https://en.wikipedia.org/wiki/Tautomer">tautomerization</a> issues, requiring post-hoc filtering with domain-specific rules.</li>
<li>Fingerprint similarity does not capture all aspects of chemical similarity (3D geometry, reactivity, synthesizability).</li>
<li>The penalized logP and QED benchmarks used by GuacaMol do not represent the full complexity of practical molecular design.</li>
</ul>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="data">Data</h3>
<table>
	<thead>
			<tr>
					<th>Purpose</th>
					<th>Dataset</th>
					<th>Size</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Photovoltaics</td>
					<td>Harvard Clean Energy (HCE) database</td>
					<td>~2.3M molecules</td>
					<td>Used for median molecule triplet experiments</td>
			</tr>
			<tr>
					<td>Benchmarking</td>
					<td>GuacaMol benchmark suite</td>
					<td>Varies per task</td>
					<td>Standard benchmarks for generative molecular design</td>
			</tr>
			<tr>
					<td>Comparison</td>
					<td>ChEMBL (SCScore &lt;= 2.5 subset)</td>
					<td>Fragment database</td>
					<td>Used for CReM comparison experiments</td>
			</tr>
	</tbody>
</table>
<h3 id="algorithms">Algorithms</h3>
<ul>
<li><strong>Local subspace formation</strong>: 50,000 SMILES orderings per seed molecule, 1-5 SELFIES point mutations each, totaling 250,000 candidates per experiment.</li>
<li><strong>Chemical paths</strong>: Deterministic character-by-character interpolation between padded SELFIES strings, with monotonic fingerprint similarity filtering.</li>
<li><strong>Median molecules</strong>: Generalized paths between 3+ reference molecules using 10,000 paths per triplet with randomized SMILES orderings.</li>
<li><strong>Docking</strong>: <a href="/notes/chemistry/molecular-design/generation/evaluation/smina-docking-benchmark/">SMINA</a> with crystal structures from PDB (4IAQ for 5-HT1B, 3QM4 for CYP2D6). Top-5 binding poses averaged.</li>
<li><strong>Quantum chemistry</strong>: GFN2-xTB for dipole moments, LUMO energies, and HOMO-LUMO gaps.</li>
</ul>
<h3 id="evaluation">Evaluation</h3>
<table>
	<thead>
			<tr>
					<th>Metric</th>
					<th>Value</th>
					<th>Baseline</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>GuacaMol overall score</td>
					<td>14.70</td>
					<td>Varies by model</td>
					<td>Competitive with deep generative models</td>
			</tr>
			<tr>
					<td>Quality filter pass rate</td>
					<td>38%</td>
					<td>Graph GA/SMILES GA comparable</td>
					<td>Top-100 molecules per benchmark</td>
			</tr>
			<tr>
					<td>Celecoxib neighbors ($\delta &gt; 0.75$)</td>
					<td>198-864</td>
					<td>CReM: 239</td>
					<td>Depends on mutation position strategy</td>
			</tr>
	</tbody>
</table>
<h3 id="hardware">Hardware</h3>
<p>All experiments run on a laptop with Intel i7-8750H CPU at 2.20 GHz. No GPU required. Most expensive single experiment (aripiprazole subspace) completed in 500 seconds.</p>
<h3 id="artifacts">Artifacts</h3>
<table>
	<thead>
			<tr>
					<th>Artifact</th>
					<th>Type</th>
					<th>License</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><a href="https://github.com/aspuru-guzik-group/stoned-selfies">stoned-selfies</a></td>
					<td>Code</td>
					<td>Not specified</td>
					<td>Official implementation of STONED algorithms</td>
			</tr>
	</tbody>
</table>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Nigam, A. K., Pollice, R., Krenn, M., dos Passos Gomes, G., &amp; Aspuru-Guzik, A. (2021). Beyond generative models: superfast traversal, optimization, novelty, exploration and discovery (STONED) algorithm for molecules using SELFIES. <em>Chemical Science</em>, 12(20), 7079-7090. <a href="https://doi.org/10.1039/d1sc00231g">https://doi.org/10.1039/d1sc00231g</a></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@article</span>{nigam2021stoned,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>=<span style="color:#e6db74">{Beyond generative models: superfast traversal, optimization, novelty, exploration and discovery ({STONED}) algorithm for molecules using {SELFIES}}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>=<span style="color:#e6db74">{Nigam, AkshatKumar and Pollice, Robert and Krenn, Mario and dos Passos Gomes, Gabriel and Aspuru-Guzik, Al{\&#39;a}n}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">journal</span>=<span style="color:#e6db74">{Chemical Science}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">volume</span>=<span style="color:#e6db74">{12}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">number</span>=<span style="color:#e6db74">{20}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span>=<span style="color:#e6db74">{7079--7090}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span>=<span style="color:#e6db74">{2021}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">publisher</span>=<span style="color:#e6db74">{Royal Society of Chemistry}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">doi</span>=<span style="color:#e6db74">{10.1039/d1sc00231g}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Graph-Based GA and MCTS Generative Model for Molecules</title><link>https://hunterheidenreich.com/notes/chemistry/molecular-design/generation/search-based/graph-based-genetic-algorithm-chemical-space/</link><pubDate>Wed, 25 Mar 2026 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/chemistry/molecular-design/generation/search-based/graph-based-genetic-algorithm-chemical-space/</guid><description>Jensen introduces a graph-based genetic algorithm and generative model with MCTS that outperforms ML methods for penalized logP optimization.</description><content:encoded><![CDATA[<h2 id="a-graph-based-approach-to-molecular-optimization">A Graph-Based Approach to Molecular Optimization</h2>
<p>This is a <strong>Method</strong> paper that introduces two graph-based approaches for exploring chemical space: a genetic algorithm (GB-GA) and a generative model combined with <a href="https://en.wikipedia.org/wiki/Monte_Carlo_tree_search">Monte Carlo tree search</a> (GB-GM-MCTS). The primary contribution is demonstrating that these non-ML, graph-based methods can match or exceed the performance of contemporary ML-based generative models for molecular property optimization, while being several orders of magnitude faster. The paper provides open-source implementations built on the RDKit cheminformatics package. The two approaches explore <a href="https://en.wikipedia.org/wiki/Chemical_space">chemical space</a> using direct graph manipulations rather than string-based representations like <a href="/notes/chemistry/molecular-representations/notations/smiles/">SMILES</a>.</p>
<h2 id="why-compare-simple-baselines-to-ml-generative-models">Why Compare Simple Baselines to ML Generative Models?</h2>
<p>By 2018, several ML-based generative models for molecules had been published, including VAEs, RNNs, and graph convolutional policy networks. However, these models were rarely compared against traditional optimization approaches such as genetic algorithms. Jensen identifies this gap explicitly: while ML generative model performance had been impressive, the lack of comparison to simpler baselines made it difficult to assess whether the complexity of ML approaches was justified.</p>
<p>A practical barrier to such comparisons was the absence of free, open-source GA implementations for molecular optimization (the existing ACSESS algorithm required proprietary OpenEye toolkits). This paper fills that gap by providing RDKit-based implementations of both the GB-GA and GB-GM-MCTS.</p>
<h2 id="graph-based-crossovers-mutations-and-monte-carlo-tree-search">Graph-Based Crossovers, Mutations, and Monte Carlo Tree Search</h2>
<h3 id="gb-ga-crossovers-and-mutations-on-molecular-graphs">GB-GA: Crossovers and Mutations on Molecular Graphs</h3>
<p>The GB-GA operates directly on molecular graph representations (not string representations like SMILES). It combines ideas from Brown et al. (2004) and the ACSESS algorithm of Virshup et al. (2013).</p>
<p><strong>Crossovers</strong> can occur at two types of positions with equal probability:</p>
<ul>
<li>Non-ring bonds: a molecule is cut at a non-ring bond, and fragments from two parent molecules are recombined</li>
<li>Ring bonds: adjacent bonds or bonds separated by one bond are cut, and fragments are mated using single or double bonds</li>
</ul>
<p><strong>Mutations</strong> include seven operation types, each with specified probabilities:</p>
<ul>
<li>Append atom (15%): adds an atom with a single, double, or triple bond</li>
<li>Insert atom (15%): inserts an atom into an existing bond</li>
<li>Delete atom (14%): removes an atom, reconnecting neighbors</li>
<li>Change atom type (14%): swaps element identity (C, N, O, F, S, Cl, Br)</li>
<li>Change bond order (14%): toggles between single, double, and triple bonds</li>
<li>Delete ring bond (14%): opens a ring</li>
<li>Add ring bond (14%): closes a new ring</li>
</ul>
<p>Molecules with macrocycles (seven or more atoms), allene centers in rings, fewer than five heavy atoms, incorrect valences, or more non-H atoms than the target size are discarded. The target size is sampled from a normal distribution with mean 39.15 and standard deviation 3.50 non-H atoms, calibrated to match the molecules found by Yang et al. (2017).</p>
<h3 id="gb-gm-mcts-a-probabilistic-growth-model-with-tree-search">GB-GM-MCTS: A Probabilistic Growth Model with Tree Search</h3>
<p>The GB-GM grows molecules one atom at a time, with the choice of bond order and atom type determined probabilistically from a bonding analysis of a reference dataset (the first 1000 molecules from ZINC). Since 63% of atoms in the reference set are ring atoms, ring-creation or ring-insertion mutations are chosen 63% of the time.</p>
<p>The generative model is combined with a <a href="https://en.wikipedia.org/wiki/Monte_Carlo_tree_search">Monte Carlo tree search</a> where:</p>
<ul>
<li>Each node corresponds to an atom addition step</li>
<li>Leaf parallelization uses a maximum of 25 leaf nodes</li>
<li>The exploration factor is $1 / \sqrt{2}$</li>
<li>Rollout terminates if the molecule exceeds the target size</li>
<li>The reward function returns 1 if the predicted $J(\mathbf{m})$ value exceeds the largest value found so far, and 0 otherwise</li>
</ul>
<h3 id="the-penalized-logp-objective">The Penalized logP Objective</h3>
<p>Both methods optimize the penalized logP score $J(\mathbf{m})$:</p>
<p>$$
J(\mathbf{m}) = \log P(\mathbf{m}) - \text{SA}(\mathbf{m}) - \text{RingPenalty}(\mathbf{m})
$$</p>
<p>where $\log P(\mathbf{m})$ is the <a href="https://en.wikipedia.org/wiki/Partition_coefficient">octanol-water partition coefficient</a> predicted by RDKit, $\text{SA}(\mathbf{m})$ is a synthetic accessibility score, and $\text{RingPenalty}(\mathbf{m})$ penalizes unrealistically large rings by reducing the score by $\text{RingSize} - 6$ for each oversized ring. Each property is normalized to zero mean and unit standard deviation across the ZINC dataset.</p>
<h2 id="experimental-setup-and-comparisons-to-ml-methods">Experimental Setup and Comparisons to ML Methods</h2>
<h3 id="gb-ga-experiments">GB-GA Experiments</h3>
<p>Ten GA simulations were performed with a population size of 20 over 50 generations (1000 $J(\mathbf{m})$ evaluations per run). The initial mating pool was 20 random molecules from the first 1000 molecules in ZINC. Two mutation rates were tested: 50% and 1%.</p>
<h3 id="gb-gm-mcts-experiments">GB-GM-MCTS Experiments</h3>
<p>Ten simulations used ethane as a seed molecule with 1000 tree traversals per run. Additional experiments used 5000 traversals and an adjusted probability of generating $\text{C}=\text{C}-\text{C}$ ring patterns (increased from 62% to 80%).</p>
<h3 id="baselines">Baselines</h3>
<p>Results were compared to those compiled by Yang et al. (2017):</p>
<ul>
<li>ChemTS (RNN + MCTS)</li>
<li>RNN with and without Bayesian optimization</li>
<li><a href="/notes/chemistry/molecular-design/generation/latent-space/automatic-chemical-design-vae/">Continuous VAE (CVAE)</a></li>
<li><a href="/notes/chemistry/molecular-design/generation/latent-space/grammar-variational-autoencoder/">Grammar VAE (GVAE)</a></li>
<li>Graph convolutional policy network (GCPN, from You et al. 2018)</li>
</ul>
<h3 id="key-results">Key Results</h3>
<table>
	<thead>
			<tr>
					<th>Method</th>
					<th>Average $J(\mathbf{m})$</th>
					<th>Molecules Evaluated</th>
					<th>CPU Time</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>GB-GA (50% mutation)</td>
					<td>6.8 +/- 0.7</td>
					<td>1000</td>
					<td>30 seconds</td>
			</tr>
			<tr>
					<td>GB-GA (1% mutation)</td>
					<td>7.4 +/- 0.9</td>
					<td>1000</td>
					<td>30 seconds</td>
			</tr>
			<tr>
					<td>GB-GM-MCTS (62%)</td>
					<td>2.6 +/- 0.6</td>
					<td>1000</td>
					<td>90 seconds</td>
			</tr>
			<tr>
					<td>GB-GM-MCTS (80%)</td>
					<td>3.4 +/- 0.6</td>
					<td>1000</td>
					<td>90 seconds</td>
			</tr>
			<tr>
					<td>GB-GM-MCTS (80%)</td>
					<td>4.3 +/- 0.6</td>
					<td>5000</td>
					<td>9 minutes</td>
			</tr>
			<tr>
					<td>ChemTS</td>
					<td>4.9 +/- 0.5</td>
					<td>~5000</td>
					<td>2 hours</td>
			</tr>
			<tr>
					<td>ChemTS</td>
					<td>5.6 +/- 0.5</td>
					<td>~20000</td>
					<td>8 hours</td>
			</tr>
			<tr>
					<td>RNN + BO</td>
					<td>4.5 +/- 0.2</td>
					<td>~4000</td>
					<td>8 hours</td>
			</tr>
			<tr>
					<td>Only RNN</td>
					<td>4.8 +/- 0.2</td>
					<td>~20000</td>
					<td>8 hours</td>
			</tr>
			<tr>
					<td>CVAE + BO</td>
					<td>0.0 +/- 0.9</td>
					<td>~100</td>
					<td>8 hours</td>
			</tr>
			<tr>
					<td>GVAE + BO</td>
					<td>0.2 +/- 1.3</td>
					<td>~1000</td>
					<td>8 hours</td>
			</tr>
	</tbody>
</table>
<p>The GB-GA with 1% mutation rate achieved an average maximum $J(\mathbf{m})$ of 7.4, which is 1.8 units higher than the best ML result (ChemTS at 5.6) while using 20x fewer evaluations and completing in 30 seconds versus 8 hours. The two highest-scoring individual molecules found by GB-GA had $J(\mathbf{m})$ scores of 8.8 and 8.5, exceeding the 7.8-8.0 range found by the GCPN approach. These molecules bore little resemblance to the initial mating pool (<a href="https://en.wikipedia.org/wiki/Jaccard_index">Tanimoto similarities</a> of 0.27 and 0.12 to the most similar ZINC molecules), indicating that the GA traversed a large distance in chemical space in just 50 generations.</p>
<p>The GB-GM-MCTS performed below ChemTS at equal evaluations (4.3 vs. 4.9 at 5000 evaluations) but was several orders of magnitude faster (9 minutes vs. 2 hours). The MCTS approach tended to extract the dominant hydrophobic structural motif (benzene rings) from the training set, making it more dependent on training set composition than the GA.</p>
<h2 id="simple-methods-set-a-high-bar-for-molecular-optimization">Simple Methods Set a High Bar for Molecular Optimization</h2>
<p>The central finding is that a simple graph-based genetic algorithm outperforms all tested ML-based generative models on penalized logP optimization, both in terms of solution quality and computational efficiency. The GB-GA achieves higher $J(\mathbf{m})$ scores with 1000 evaluations in 30 seconds than ML methods achieve with 20,000 evaluations over 8 hours.</p>
<p>Several additional observations emerge:</p>
<ol>
<li><strong>Chemical space traversal</strong>: The GB-GA can reach high-scoring molecules that are structurally distant from the starting population, with Tanimoto similarity as low as 0.12 to the nearest ZINC molecule.</li>
<li><strong>Mutation rate matters</strong>: A 1% mutation rate outperformed a 50% rate (7.4 vs. 6.8), suggesting that preserving more parental structure during crossover is beneficial for this objective.</li>
<li><strong>Training set dependence</strong>: The GB-GM-MCTS is more sensitive to training set composition than the GA. Its preference for benzene-ring-containing molecules (the dominant ZINC motif) limits its ability to discover alternative structural solutions like the long aliphatic chains favored by the GA.</li>
<li><strong>Generalizability caveat</strong>: Jensen explicitly notes that these comparisons cover only one property (penalized logP) and that similar comparisons for other properties are needed before drawing general conclusions.</li>
</ol>
<p>The paper&rsquo;s influence has been substantial: it helped establish the expectation that new molecular generative models should be benchmarked against genetic algorithm baselines, a position subsequently reinforced by Brown et al. (2019) in <a href="/notes/chemistry/molecular-design/generation/evaluation/guacamol-benchmarking-de-novo-molecular-design/">GuacaMol</a> and by <a href="/notes/chemistry/molecular-design/generation/search-based/genetic-algorithms-molecule-generation-baselines/">Tripp and Hernandez-Lobato (2023)</a>.</p>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="data">Data</h3>
<table>
	<thead>
			<tr>
					<th>Purpose</th>
					<th>Dataset</th>
					<th>Size</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Initial mating pool / reference set</td>
					<td><a href="/notes/chemistry/datasets/zinc-22/">ZINC</a> (subset)</td>
					<td>First 1000 molecules</td>
					<td>Same subset used in previous studies (Gomez-Bombarelli et al., Yang et al.)</td>
			</tr>
			<tr>
					<td>Target molecule size</td>
					<td>Derived from Yang et al. results</td>
					<td>20 molecules</td>
					<td>Mean 39.15, SD 3.50 non-H atoms</td>
			</tr>
	</tbody>
</table>
<h3 id="algorithms">Algorithms</h3>
<ul>
<li><strong>GB-GA</strong>: Population size 20, 50 generations, mutation rates of 1% and 50% tested. Crossovers at ring and non-ring bonds with equal probability. Seven mutation types with specified probabilities. Molecules selected from mating pool based on normalized logP scores.</li>
<li><strong>GB-GM</strong>: Atom-by-atom growth using probabilistic rules derived from ZINC bonding analysis. Ring creation probability 63% (matching ZINC), with 80% variant also tested. Seed molecule: ethane.</li>
<li><strong>MCTS</strong>: Modified from haroldsultan/MCTS Python implementation. Leaf parallelization with max 25 leaf nodes. Exploration factor $1/\sqrt{2}$. Binary reward function (1 if new best, 0 otherwise).</li>
<li><strong>Property calculation</strong>: logP, SA score, and ring penalty all computed via RDKit. Each property normalized to zero mean and unit standard deviation across ZINC.</li>
</ul>
<h3 id="models">Models</h3>
<p>No neural network models are used. The GB-GA and GB-GM are purely algorithmic approaches parameterized by bonding statistics from the ZINC dataset.</p>
<h3 id="evaluation">Evaluation</h3>
<table>
	<thead>
			<tr>
					<th>Metric</th>
					<th>GB-GA (1%)</th>
					<th>Best ML (ChemTS)</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Average max $J(\mathbf{m})$</td>
					<td>7.4 +/- 0.9</td>
					<td>5.6 +/- 0.5</td>
					<td>Over 10 runs</td>
			</tr>
			<tr>
					<td>Single best $J(\mathbf{m})$</td>
					<td>8.8</td>
					<td>~8.0 (GCPN)</td>
					<td>GB-GA vs. You et al.</td>
			</tr>
			<tr>
					<td>Evaluations per run</td>
					<td>1000</td>
					<td>~20,000</td>
					<td>20x fewer for GB-GA</td>
			</tr>
			<tr>
					<td>CPU time per run</td>
					<td>30 seconds</td>
					<td>8 hours</td>
					<td>~960x faster</td>
			</tr>
	</tbody>
</table>
<h3 id="hardware">Hardware</h3>
<p>All GB-GA and GB-GM experiments were run on a laptop. No GPU required. The GB-GA completes in 30 seconds per run and the GB-GM-MCTS in 90 seconds (1000 traversals) to 9 minutes (5000 traversals).</p>
<h3 id="artifacts">Artifacts</h3>
<table>
	<thead>
			<tr>
					<th>Artifact</th>
					<th>Type</th>
					<th>License</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><a href="https://github.com/jensengroup/GB-GA/tree/v0.0">GB-GA (v0.0)</a></td>
					<td>Code</td>
					<td>Not specified</td>
					<td>Graph-based genetic algorithm, RDKit dependency only</td>
			</tr>
			<tr>
					<td><a href="https://github.com/jensengroup/GB-GM/tree/v0.0">GB-GM (v0.0)</a></td>
					<td>Code</td>
					<td>Not specified</td>
					<td>Graph-based generative model + MCTS, RDKit dependency only</td>
			</tr>
	</tbody>
</table>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Jensen, J. H. (2019). A graph-based genetic algorithm and generative model/Monte Carlo tree search for the exploration of chemical space. <em>Chemical Science</em>, 10(12), 3567-3572. <a href="https://doi.org/10.1039/c8sc05372c">https://doi.org/10.1039/c8sc05372c</a></p>
<p><strong>Publication</strong>: Chemical Science (Royal Society of Chemistry), 2019</p>
<p><strong>Additional Resources</strong>:</p>
<ul>
<li><a href="https://github.com/jensengroup/GB-GA">GB-GA Code (GitHub)</a></li>
<li><a href="https://github.com/jensengroup/GB-GM">GB-GM Code (GitHub)</a></li>
</ul>
<h2 id="citation">Citation</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@article</span>{jensen2019graph,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>=<span style="color:#e6db74">{A graph-based genetic algorithm and generative model/Monte Carlo tree search for the exploration of chemical space}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>=<span style="color:#e6db74">{Jensen, Jan H.}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">journal</span>=<span style="color:#e6db74">{Chemical Science}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">volume</span>=<span style="color:#e6db74">{10}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">number</span>=<span style="color:#e6db74">{12}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span>=<span style="color:#e6db74">{3567--3572}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span>=<span style="color:#e6db74">{2019}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">publisher</span>=<span style="color:#e6db74">{Royal Society of Chemistry}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">doi</span>=<span style="color:#e6db74">{10.1039/c8sc05372c}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Genetic Algorithms as Baselines for Molecule Generation</title><link>https://hunterheidenreich.com/notes/chemistry/molecular-design/generation/search-based/genetic-algorithms-molecule-generation-baselines/</link><pubDate>Mon, 23 Mar 2026 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/chemistry/molecular-design/generation/search-based/genetic-algorithms-molecule-generation-baselines/</guid><description>Genetic algorithms outperform many deep learning methods for molecule generation. Tripp and Hernández-Lobato propose the GA criterion.</description><content:encoded><![CDATA[<h2 id="a-position-paper-on-molecular-generation-baselines">A Position Paper on Molecular Generation Baselines</h2>
<p>This is a <strong>Position</strong> paper that argues genetic algorithms (GAs) are underused and underappreciated as baselines in the molecular generation community. The primary contribution is empirical evidence that a simple GA implementation (MOL_GA) matches or outperforms many sophisticated deep learning methods on standard benchmarks. The authors propose the &ldquo;GA criterion&rdquo; as a minimum bar for evaluating new molecular generation algorithms.</p>
<h2 id="why-molecular-generation-may-be-easier-than-assumed">Why Molecular Generation May Be Easier Than Assumed</h2>
<p>Drug discovery is fundamentally a molecular generation task, and many machine learning methods have been proposed for it (Du et al., 2022). The problem has many variants, from unconditional generation of novel molecules to directed optimization of specific molecular properties.</p>
<p>The authors observe that generating valid molecules is, in some respects, straightforward. The rules governing molecular validity are well-defined bond constraints that can be checked using standard cheminformatics software like <a href="https://en.wikipedia.org/wiki/RDKit">RDKit</a>. This means new molecules can be generated simply by adding, removing, or substituting fragments of known molecules. When applied iteratively, this is exactly what a genetic algorithm does. Despite this, many papers in the field propose complex deep learning methods without adequately comparing to simple GA baselines.</p>
<h2 id="the-ga-criterion-for-evaluating-new-methods">The GA Criterion for Evaluating New Methods</h2>
<p>The core proposal is the <strong>GA criterion</strong>: new methods in molecular generation should offer some clear advantage over genetic algorithms. This advantage can be:</p>
<ul>
<li><strong>Empirical</strong>: outperforming GAs on relevant benchmarks</li>
<li><strong>Conceptual</strong>: identifying and overcoming a specific limitation of randomly modifying known molecules</li>
</ul>
<p>The authors argue that the current state of molecular generation research reflects poor empirical practices, where comprehensive baseline evaluation is treated as optional rather than essential.</p>
<h2 id="genetic-algorithm-framework-and-benchmark-experiments">Genetic Algorithm Framework and Benchmark Experiments</h2>
<h3 id="how-genetic-algorithms-work-for-molecules">How Genetic Algorithms Work for Molecules</h3>
<p>GAs operate through the following iterative procedure:</p>
<ol>
<li>Start with an initial population $P$ of molecules</li>
<li>Sample a subset $S \subseteq P$ from the population (possibly biased toward better molecules)</li>
<li>Generate new molecules $N$ from $S$ via mutation and crossover operations</li>
<li>Select a new population $P&rsquo;$ from $P \cup N$ (e.g., keep the highest-scoring molecules)</li>
<li>Set $P \leftarrow P&rsquo;$ and repeat from step 2</li>
</ol>
<p>The MOL_GA implementation uses:</p>
<ul>
<li><strong>Quantile-based sampling</strong> (step 2): molecules are sampled from the top quantiles of the population using a log-uniform distribution over quantile thresholds:</li>
</ul>
<p>$$
u \sim \mathcal{U}[-3, 0], \quad \epsilon = 10^{u}
$$</p>
<p>A molecule is drawn uniformly from the top $\epsilon$ fraction of the population.</p>
<ul>
<li><strong>Mutation and crossover</strong> (step 3): graph-based operations from <a href="/notes/chemistry/molecular-design/generation/search-based/graph-based-genetic-algorithm-chemical-space/">Jensen (2019)</a>, as implemented in the <a href="/notes/chemistry/molecular-design/generation/evaluation/guacamol-benchmarking-de-novo-molecular-design/">GuacaMol benchmark (Brown et al., 2019)</a></li>
<li><strong>Greedy population selection</strong> (step 4): molecules with the highest scores are retained</li>
</ul>
<h3 id="unconditional-generation-on-zinc-250k">Unconditional Generation on ZINC 250K</h3>
<p>The first experiment evaluates unconditional molecule generation, where the task is to produce novel, valid, and unique molecules distinct from a reference set (ZINC 250K). Success is measured by validity, novelty (at 10,000 generated molecules), and uniqueness.</p>
<table>
	<thead>
			<tr>
					<th>Method</th>
					<th>Paper</th>
					<th>Validity</th>
					<th>Novelty@10k</th>
					<th>Uniqueness</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>JT-VAE</td>
					<td>Jin et al. (2018)</td>
					<td>99.8%</td>
					<td>100%</td>
					<td>100%</td>
			</tr>
			<tr>
					<td>GCPN</td>
					<td>You et al. (2018)</td>
					<td>100%</td>
					<td>100%</td>
					<td>99.97%</td>
			</tr>
			<tr>
					<td><a href="/notes/chemistry/molecular-design/generation/rl-tuned/molecularrnn-graph-generation-optimized-properties/">MolecularRNN</a></td>
					<td>Popova et al. (2019)</td>
					<td>100%</td>
					<td>100%</td>
					<td>99.89%</td>
			</tr>
			<tr>
					<td>Graph NVP</td>
					<td>Madhawa et al. (2019)</td>
					<td>100%</td>
					<td>100%</td>
					<td>94.80%</td>
			</tr>
			<tr>
					<td>Graph AF</td>
					<td>Shi et al. (2020)</td>
					<td>100%</td>
					<td>100%</td>
					<td>99.10%</td>
			</tr>
			<tr>
					<td>MoFlow</td>
					<td>Zang and Wang (2020)</td>
					<td>100%</td>
					<td>100%</td>
					<td>99.99%</td>
			</tr>
			<tr>
					<td>GraphCNF</td>
					<td>Lippe and Gavves (2020)</td>
					<td>96.35%</td>
					<td>99.98%</td>
					<td>99.98%</td>
			</tr>
			<tr>
					<td>Graph DF</td>
					<td>Luo et al. (2021)</td>
					<td>100%</td>
					<td>100%</td>
					<td>99.16%</td>
			</tr>
			<tr>
					<td>ModFlow</td>
					<td>Verma et al. (2022)</td>
					<td>98.1%</td>
					<td>100%</td>
					<td>99.3%</td>
			</tr>
			<tr>
					<td>GraphEBM</td>
					<td>Liu et al. (2021)</td>
					<td>99.96%</td>
					<td>100%</td>
					<td>98.79%</td>
			</tr>
			<tr>
					<td>AddCarbon</td>
					<td>Renz et al. (2019)</td>
					<td>100%</td>
					<td>99.94%</td>
					<td>99.86%</td>
			</tr>
			<tr>
					<td>MOL_GA</td>
					<td>(this paper)</td>
					<td>99.76%</td>
					<td>99.94%</td>
					<td>98.60%</td>
			</tr>
	</tbody>
</table>
<p>All methods perform near 100% on all metrics, demonstrating that unconditional molecule generation is not a particularly discriminative benchmark. The authors note that generation speed (molecules per second) is an important missing dimension from these comparisons, where simple methods like GAs have a clear advantage.</p>
<h3 id="molecule-optimization-on-the-pmo-benchmark">Molecule Optimization on the PMO Benchmark</h3>
<p>The second experiment evaluates directed molecule optimization on the <a href="/notes/chemistry/molecular-design/generation/evaluation/pmo-sample-efficient-molecular-optimization/">Practical Molecular Optimization (PMO) benchmark (Gao et al., 2022)</a>, which measures the ability to find molecules optimizing a scalar objective function $f: \mathcal{M} \mapsto \mathbb{R}$ with a budget of 10,000 evaluations.</p>
<p>A key insight is that previous GA implementations in PMO used large generation sizes ($\approx 100$), which limits the number of improvement iterations. The authors set the generation size to 5, allowing approximately 2,000 iterations of improvement within the same evaluation budget.</p>
<table>
	<thead>
			<tr>
					<th>Task</th>
					<th><a href="/notes/chemistry/molecular-design/generation/rl-tuned/reinvent-deep-rl-molecular-design/">REINVENT</a></th>
					<th>Graph GA</th>
					<th>MOL_GA</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>albuterol_similarity</td>
					<td>0.882 +/- 0.006</td>
					<td>0.838 +/- 0.016</td>
					<td><strong>0.896 +/- 0.035</strong></td>
			</tr>
			<tr>
					<td>amlodipine_mpo</td>
					<td>0.635 +/- 0.035</td>
					<td>0.661 +/- 0.020</td>
					<td><strong>0.688 +/- 0.039</strong></td>
			</tr>
			<tr>
					<td>celecoxib_rediscovery</td>
					<td><strong>0.713 +/- 0.067</strong></td>
					<td>0.630 +/- 0.097</td>
					<td>0.567 +/- 0.083</td>
			</tr>
			<tr>
					<td>drd2</td>
					<td>0.945 +/- 0.007</td>
					<td><strong>0.964 +/- 0.012</strong></td>
					<td>0.936 +/- 0.016</td>
			</tr>
			<tr>
					<td>fexofenadine_mpo</td>
					<td>0.784 +/- 0.006</td>
					<td>0.760 +/- 0.011</td>
					<td><strong>0.825 +/- 0.019</strong></td>
			</tr>
			<tr>
					<td>isomers_c9h10n2o2pf2cl</td>
					<td>0.642 +/- 0.054</td>
					<td>0.719 +/- 0.047</td>
					<td><strong>0.865 +/- 0.012</strong></td>
			</tr>
			<tr>
					<td>sitagliptin_mpo</td>
					<td>0.021 +/- 0.003</td>
					<td>0.433 +/- 0.075</td>
					<td><strong>0.582 +/- 0.040</strong></td>
			</tr>
			<tr>
					<td>zaleplon_mpo</td>
					<td>0.358 +/- 0.062</td>
					<td>0.346 +/- 0.032</td>
					<td><strong>0.519 +/- 0.029</strong></td>
			</tr>
			<tr>
					<td><strong>Sum (23 tasks)</strong></td>
					<td>14.196</td>
					<td>13.751</td>
					<td><strong>14.708</strong></td>
			</tr>
			<tr>
					<td><strong>Rank</strong></td>
					<td>2</td>
					<td>3</td>
					<td><strong>1</strong></td>
			</tr>
	</tbody>
</table>
<p>MOL_GA achieves the highest aggregate score across all 23 PMO tasks, outperforming both the previous best GA (Graph GA) and the previous best overall method (REINVENT). The authors attribute this partly to the tuning of the baselines in PMO rather than MOL_GA being an especially strong method, since MOL_GA is essentially the same algorithm as Graph GA with different hyperparameters.</p>
<h2 id="implications-for-molecular-generation-research">Implications for Molecular Generation Research</h2>
<p>The key findings and arguments are:</p>
<ol>
<li>
<p><strong>GAs match or outperform deep learning methods</strong> on standard molecular generation benchmarks, both for unconditional generation and directed optimization.</p>
</li>
<li>
<p><strong>Hyperparameter choices matter significantly</strong>: MOL_GA&rsquo;s strong performance on PMO comes partly from using a smaller generation size (5 vs. ~100), which allows more iterations of refinement within the same evaluation budget.</p>
</li>
<li>
<p><strong>The GA criterion should be enforced in peer review</strong>: new molecular generation methods should demonstrate a clear advantage over GAs, whether empirical or conceptual.</p>
</li>
<li>
<p><strong>Deep learning methods may implicitly do what GAs do explicitly</strong>: many generative models are trained on datasets of known molecules, so the novel molecules they produce may simply be variants of their training data. The authors consider this an important direction for future investigation.</p>
</li>
<li>
<p><strong>Poor empirical practices are widespread</strong>: the paper argues that many experiments in molecule generation are conducted with an explicit desired outcome (that the novel algorithm is the best), leading to inadequate baseline comparisons.</p>
</li>
</ol>
<p>The authors are careful to note that this result should not be interpreted as GAs being exceptional algorithms. Rather, it is an indication that more complex methods have made surprisingly little progress beyond what simple heuristic search can achieve.</p>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="data">Data</h3>
<table>
	<thead>
			<tr>
					<th>Purpose</th>
					<th>Dataset</th>
					<th>Size</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Unconditional generation</td>
					<td>ZINC 250K</td>
					<td>250,000 molecules</td>
					<td>Reference set for novelty evaluation</td>
			</tr>
			<tr>
					<td>Directed optimization</td>
					<td>PMO benchmark</td>
					<td>23 tasks</td>
					<td>10,000 evaluation budget per task</td>
			</tr>
	</tbody>
</table>
<h3 id="algorithms">Algorithms</h3>
<ul>
<li><strong>GA implementation</strong>: MOL_GA package, using graph-based mutation and crossover from Jensen (2019) via the GuacaMol implementation</li>
<li><strong>Generation size</strong>: 5 molecules per iteration (allowing ~2,000 iterations with 10,000 evaluations)</li>
<li><strong>Population selection</strong>: Greedy (highest-scoring molecules retained)</li>
<li><strong>Sampling</strong>: Quantile-based with log-uniform distribution over quantile thresholds</li>
</ul>
<h3 id="evaluation">Evaluation</h3>
<table>
	<thead>
			<tr>
					<th>Metric</th>
					<th>Benchmark</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Validity, Novelty@10k, Uniqueness</td>
					<td>ZINC 250K unconditional</td>
					<td>Calculated using <a href="/notes/chemistry/molecular-design/generation/evaluation/molecular-sets-moses/">MOSES package</a></td>
			</tr>
			<tr>
					<td>AUC top-10 scores</td>
					<td>PMO benchmark</td>
					<td>23 optimization tasks with 10,000 evaluation budget</td>
			</tr>
	</tbody>
</table>
<h3 id="hardware">Hardware</h3>
<p>The paper does not specify hardware requirements. Given that GAs are computationally lightweight compared to deep learning methods, standard CPU hardware is likely sufficient.</p>
<h3 id="artifacts">Artifacts</h3>
<table>
	<thead>
			<tr>
					<th>Artifact</th>
					<th>Type</th>
					<th>License</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><a href="https://github.com/AustinT/mol_ga">MOL_GA</a></td>
					<td>Code</td>
					<td>MIT</td>
					<td>Python package for molecular genetic algorithms</td>
			</tr>
			<tr>
					<td><a href="https://pypi.org/project/mol-ga/">MOL_GA on PyPI</a></td>
					<td>Code</td>
					<td>MIT</td>
					<td>pip-installable package</td>
			</tr>
	</tbody>
</table>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Tripp, A., &amp; Hernández-Lobato, J. M. (2023). Genetic algorithms are strong baselines for molecule generation. <em>arXiv preprint arXiv:2310.09267</em>. <a href="https://arxiv.org/abs/2310.09267">https://arxiv.org/abs/2310.09267</a></p>
<p><strong>Publication</strong>: arXiv preprint, 2023</p>
<p><strong>Additional Resources</strong>:</p>
<ul>
<li><a href="https://github.com/AustinT/mol_ga">MOL_GA Python Package (GitHub)</a></li>
<li><a href="https://pypi.org/project/mol-ga/">MOL_GA on PyPI</a></li>
</ul>
<h2 id="citation">Citation</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@article</span>{tripp2023genetic,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>=<span style="color:#e6db74">{Genetic algorithms are strong baselines for molecule generation}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>=<span style="color:#e6db74">{Tripp, Austin and Hern{\&#39;a}ndez-Lobato, Jos{\&#39;e} Miguel}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">journal</span>=<span style="color:#e6db74">{arXiv preprint arXiv:2310.09267}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span>=<span style="color:#e6db74">{2023}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Kabsch-Horn Cookbook: Differentiable Alignment</title><link>https://hunterheidenreich.com/projects/kabsch-horn-cookbook/</link><pubDate>Fri, 20 Mar 2026 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/projects/kabsch-horn-cookbook/</guid><description>Differentiable Kabsch (SVD) and Horn (quaternion) alignment for NumPy, PyTorch, JAX, TensorFlow, and MLX with gradient-safe SVD.</description><content:encoded><![CDATA[<h2 id="overview">Overview</h2>
<p>Aligning two sets of corresponding points, finding the optimal rotation (and optionally translation and scale) that maps one onto the other, is a fundamental operation across scientific computing. It appears in molecular dynamics (superimposing protein conformations), robotics (sensor registration), and computer vision (shape matching). The two dominant algorithm families are the Kabsch (SVD-based) method and the Horn (quaternion-based) method.</p>
<p>The <strong>Kabsch-Horn Cookbook</strong> is a Python library that implements both algorithm families across five numerical frameworks: NumPy, PyTorch, JAX, TensorFlow, and MLX. Every backend shares the same API, supports N-dimensional point sets, per-point weights, and arbitrary batch dimensions. The PyTorch, JAX, TensorFlow, and MLX backends are fully differentiable, with custom autograd rules that bypass the numerically unstable gradient of the standard SVD near degenerate singular values.</p>
<h2 id="features">Features</h2>
<h3 id="algorithms">Algorithms</h3>
<ul>
<li><strong>Kabsch</strong>: SVD-based optimal rotation for rigid alignment</li>
<li><strong>Kabsch-Umeyama</strong>: Kabsch with an additional optimal scaling factor $c$, solving $Q \approx cRP + t$</li>
<li><strong>Horn</strong>: Quaternion-based optimal rotation via the eigendecomposition of a $4 \times 4$ key matrix</li>
<li><strong>Horn + Scale</strong>: Horn&rsquo;s method extended with optimal isotropic scaling</li>
<li><strong>RMSD Wrappers</strong>: Convenience functions that return RMSD directly alongside the alignment parameters</li>
</ul>
<h3 id="framework-support">Framework Support</h3>
<table>
	<thead>
			<tr>
					<th>Framework</th>
					<th style="text-align: center">Differentiable</th>
					<th style="text-align: center">Compile/JIT</th>
					<th>Versions</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>NumPy</td>
					<td style="text-align: center"></td>
					<td style="text-align: center"></td>
					<td>1.24+</td>
			</tr>
			<tr>
					<td>PyTorch</td>
					<td style="text-align: center">Yes</td>
					<td style="text-align: center"><code>torch.compile</code></td>
					<td>2.0+</td>
			</tr>
			<tr>
					<td>JAX</td>
					<td style="text-align: center">Yes</td>
					<td style="text-align: center"><code>jax.jit</code></td>
					<td>0.4+</td>
			</tr>
			<tr>
					<td>TensorFlow</td>
					<td style="text-align: center">Yes</td>
					<td style="text-align: center"></td>
					<td>2.13+</td>
			</tr>
			<tr>
					<td>MLX</td>
					<td style="text-align: center">Yes</td>
					<td style="text-align: center"></td>
					<td>0.1+</td>
			</tr>
	</tbody>
</table>
<p><code>torch.compile</code> and <code>jax.jit</code> are the tested compile/JIT paths. MLX supports 3D inputs only; the Kabsch (SVD) path is N-dimensional on the other four backends.</p>
<h3 id="numerical-robustness">Numerical Robustness</h3>
<p>Standard SVD and eigendecomposition backward passes produce <code>NaN</code> gradients when singular values collide or are near-zero. The library provides custom autograd primitives to handle these cases:</p>
<ul>
<li><strong>SafeSVD</strong> (PyTorch, JAX, TF, MLX): Custom backward pass that clamps the singular value gap, preventing division-by-zero in the gradient</li>
<li><strong>SafeEigh</strong> (PyTorch, JAX, TF, MLX): Analogous safe backward for the symmetric eigendecomposition used in Horn&rsquo;s method</li>
<li><strong>Per-point weights</strong>: Weighted centroids and weighted cross-covariance for mass-weighted or confidence-weighted alignment</li>
<li><strong>Batch dimensions</strong>: All functions broadcast over leading batch dimensions without explicit loops</li>
<li><strong>Mixed-dtype promotion</strong>: Inputs are promoted to a common floating-point dtype automatically</li>
</ul>
<h3 id="testing">Testing</h3>
<p>The test suite uses Hypothesis-based property testing across 13 modules covering:</p>
<ul>
<li>Round-trip correctness (align then compare)</li>
<li>Gradient finiteness and correctness (finite-difference checks)</li>
<li>Reflection handling (proper vs. improper rotations)</li>
<li>Weighted alignment consistency</li>
<li>Batch broadcasting</li>
<li>4 differentiable backends $\times$ 4 precisions (float32, float64, and where supported, float16, bfloat16)</li>
</ul>
<h2 id="usage">Usage</h2>
<p>This is a reference cookbook, so you can copy the framework folder you need from <code>src/kabsch_horn/&lt;framework&gt;/</code> directly into your project (the code has no runtime dependencies beyond the framework itself). To depend on it instead, install a pinned version from GitHub:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>pip install <span style="color:#e6db74">&#34;git+https://github.com/hunter-heidenreich/Kabsch-Cookbook.git@v0.4.1&#34;</span>
</span></span></code></pre></div><p>Basic alignment with NumPy:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">import</span> numpy <span style="color:#66d9ef">as</span> np
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> kabsch_horn <span style="color:#f92672">import</span> numpy <span style="color:#66d9ef">as</span> kh
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Two sets of corresponding 3D points</span>
</span></span><span style="display:flex;"><span>P <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>random<span style="color:#f92672">.</span>randn(<span style="color:#ae81ff">100</span>, <span style="color:#ae81ff">3</span>)
</span></span><span style="display:flex;"><span>R_true <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>linalg<span style="color:#f92672">.</span>qr(np<span style="color:#f92672">.</span>random<span style="color:#f92672">.</span>randn(<span style="color:#ae81ff">3</span>, <span style="color:#ae81ff">3</span>))[<span style="color:#ae81ff">0</span>]  <span style="color:#75715e"># random rotation matrix</span>
</span></span><span style="display:flex;"><span>Q <span style="color:#f92672">=</span> (P <span style="color:#f92672">@</span> R_true<span style="color:#f92672">.</span>T) <span style="color:#f92672">+</span> np<span style="color:#f92672">.</span>random<span style="color:#f92672">.</span>randn(<span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">3</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>R, t, rmsd <span style="color:#f92672">=</span> kh<span style="color:#f92672">.</span>kabsch(P, Q)
</span></span><span style="display:flex;"><span>aligned <span style="color:#f92672">=</span> P <span style="color:#f92672">@</span> R<span style="color:#f92672">.</span>T <span style="color:#f92672">+</span> t
</span></span></code></pre></div><p>RMSD loss for training in PyTorch:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">import</span> torch
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> kabsch_horn <span style="color:#f92672">import</span> pytorch <span style="color:#66d9ef">as</span> kh
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>pred_coords <span style="color:#f92672">=</span> model(input_features)   <span style="color:#75715e"># (B, N, 3), requires_grad=True</span>
</span></span><span style="display:flex;"><span>target_coords <span style="color:#f92672">=</span> batch[<span style="color:#e6db74">&#34;target&#34;</span>]       <span style="color:#75715e"># (B, N, 3)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>rmsd <span style="color:#f92672">=</span> kh<span style="color:#f92672">.</span>kabsch_rmsd(pred_coords, target_coords)  <span style="color:#75715e"># (B,)</span>
</span></span><span style="display:flex;"><span>loss <span style="color:#f92672">=</span> rmsd<span style="color:#f92672">.</span>mean()
</span></span><span style="display:flex;"><span>loss<span style="color:#f92672">.</span>backward()  <span style="color:#75715e"># safe gradients via SafeSVD</span>
</span></span></code></pre></div><p>For the full API reference and additional examples, see the <a href="https://hunter-heidenreich.github.io/Kabsch-Cookbook/">documentation site</a>.</p>
<h2 id="results">Results</h2>
<h3 id="gradient-stability">Gradient Stability</h3>
<p>The standard SVD backward pass computes terms of the form $\frac{1}{\sigma_i^2 - \sigma_j^2}$, which diverges when two singular values are close. In molecular alignment this happens frequently: planar molecules, symmetric structures, and noisy coordinates can all produce near-degenerate singular values. The SafeSVD primitive floors the magnitude of that denominator at the dtype&rsquo;s machine epsilon (<code>finfo(dtype).eps</code>), producing finite (if slightly biased) gradients in these edge cases. Property-based tests confirm that gradients remain finite across thousands of random rotations, scales, and noise levels for all four differentiable backends.</p>
<h3 id="framework-parity">Framework Parity</h3>
<p>All five backends produce numerically equivalent results (up to floating-point tolerance) on the same inputs. The shared API means switching from NumPy prototyping to PyTorch training requires changing only the import path.</p>
<h2 id="related-work">Related Work</h2>
<p>This project builds on the foundational alignment algorithms described in these papers:</p>
<ul>
<li><a href="/notes/computational-biology/kabsch-algorithm/">Kabsch (1976)</a>: the original SVD-based rotation alignment</li>
<li><a href="/notes/computational-biology/arun-svd-point-fitting/">Arun et al. (1987)</a>: SVD formulation for 3D point set fitting</li>
<li><a href="/notes/computational-biology/horn-absolute-orientation/">Horn (1987)</a>: quaternion-based closed-form absolute orientation</li>
<li><a href="/notes/computational-biology/horn-orthonormal-matrices/">Horn et al. (1988)</a>: orthonormal matrix (polar decomposition) approach</li>
<li><a href="/notes/computational-biology/umeyama-similarity-transformation/">Umeyama (1991)</a>: extension to include optimal scaling</li>
</ul>
<p>For a detailed walkthrough of the Kabsch algorithm with code examples, see the companion blog post: <a href="/posts/kabsch-algorithm/">The Kabsch Algorithm</a>.</p>
]]></content:encoded></item><item><title>Umeyama's Method: Corrected SVD for Point Alignment</title><link>https://hunterheidenreich.com/notes/computational-biology/umeyama-similarity-transformation/</link><pubDate>Mon, 16 Mar 2026 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/computational-biology/umeyama-similarity-transformation/</guid><description>Umeyama (1991) fixes the SVD-based point set alignment method to always produce proper rotations, jointly solving for rotation, translation, and scale.</description><content:encoded><![CDATA[<h2 id="fixing-the-reflection-problem-in-svd-based-alignment">Fixing the Reflection Problem in SVD-Based Alignment</h2>
<p>This <strong>Method</strong> paper addresses a specific failure mode in prior SVD-based solutions to the point set registration problem. Both <a href="/notes/computational-biology/arun-svd-point-fitting/">Arun et al. (1987)</a> and <a href="/notes/computational-biology/horn-orthonormal-matrices/">Horn, Hilden, and Negahdaripour (1988)</a> presented SVD-based methods for finding the optimal rotation between two point patterns. (Note: this is a different paper from <a href="/notes/computational-biology/horn-absolute-orientation/">Horn&rsquo;s 1987 quaternion method</a>, which does not suffer from this issue.) These SVD-based methods can produce a reflection ($\det(R) = -1$) instead of a proper rotation when the data is severely corrupted. Umeyama provides a corrected formulation that always yields a proper rotation matrix.</p>
<h2 id="the-similarity-transformation-problem">The Similarity Transformation Problem</h2>
<p>Given two point sets ${\mathbf{x}_i}$ and ${\mathbf{y}_i}$ ($i = 1, \ldots, n$) in $m$-dimensional space, find the similarity transformation parameters (rotation $R$, translation $\mathbf{t}$, and scale $c$) minimizing the mean squared error:</p>
<p>$$
e^2(R, \mathbf{t}, c) = \frac{1}{n} \sum_{i=1}^{n} \lVert \mathbf{y}_i - (cR\mathbf{x}_i + \mathbf{t}) \rVert^2
$$</p>
<p>This generalizes the <a href="/notes/computational-biology/kabsch-algorithm/">Kabsch problem</a> (rotation only) and the <a href="/notes/computational-biology/horn-absolute-orientation/">absolute orientation problem</a> (rotation + translation + scale) to arbitrary dimensions $m$.</p>
<h2 id="the-core-lemma-corrected-svd-rotation">The Core Lemma: Corrected SVD Rotation</h2>
<p>The key contribution is a lemma for finding the rotation $R$ minimizing $\lVert A - RB \rVert^2$. Given the SVD of $AB^T = UDV^T$ (with $d_1 \geq d_2 \geq \cdots \geq d_m \geq 0$), define the correction matrix:</p>
<p>$$
S = \begin{cases} I &amp; \text{if } \det(AB^T) \geq 0 \\ \operatorname{diag}(1, 1, \ldots, 1, -1) &amp; \text{if } \det(AB^T) &lt; 0 \end{cases}
$$</p>
<p>The minimum value is:</p>
<p>$$
\min_{R} \lVert A - RB \rVert^2 = \lVert A \rVert^2 + \lVert B \rVert^2 - 2\operatorname{tr}(DS)
$$</p>
<p>When $\operatorname{rank}(AB^T) \geq m - 1$, the optimal rotation is uniquely determined as:</p>
<p>$$
R = USV^T
$$</p>
<p>The critical insight is that when $\det(AB^T) = 0$ (i.e., $\operatorname{rank}(AB^T) = m - 1$), the matrix $S$ must instead be chosen based on $\det(U)\det(V)$:</p>
<p>$$
S = \begin{cases} I &amp; \text{if } \det(U)\det(V) = 1 \\ \operatorname{diag}(1, 1, \ldots, 1, -1) &amp; \text{if } \det(U)\det(V) = -1 \end{cases}
$$</p>
<p>This handles the degenerate case where the sign of $\det(AB^T)$ is unreliable.</p>
<h2 id="complete-similarity-transformation-solution">Complete Similarity Transformation Solution</h2>
<p>Umeyama derives the full solution using centered coordinates and the covariance matrix $\Sigma_{xy} = \frac{1}{n} \sum_i (\mathbf{y}_i - \boldsymbol{\mu}_y)(\mathbf{x}_i - \boldsymbol{\mu}_x)^T$.</p>
<p>Given the SVD $\Sigma_{xy} = UDV^T$:</p>
<p><strong>Rotation</strong>:</p>
<p>$$
R = USV^T
$$</p>
<p><strong>Scale</strong>:</p>
<p>$$
c = \frac{1}{\sigma_x^2} \operatorname{tr}(DS)
$$</p>
<p><strong>Translation</strong>:</p>
<p>$$
\mathbf{t} = \boldsymbol{\mu}_y - cR\boldsymbol{\mu}_x
$$</p>
<p><strong>Minimum error</strong>:</p>
<p>$$
\varepsilon^2 = \sigma_y^2 - \frac{\operatorname{tr}(DS)^2}{\sigma_x^2}
$$</p>
<p>where $\sigma_x^2$ and $\sigma_y^2$ are the variances of the respective point sets around their centroids.</p>
<h2 id="why-prior-methods-fail">Why Prior Methods Fail</h2>
<p>The methods of Arun et al. and Horn et al. use $R = UV^T$ directly from the SVD. This works when $\det(UV^T) = 1$ (proper rotation). When $\det(UV^T) = -1$, these methods either produce a reflection or apply an ad hoc correction (flipping the sign of the last column of $U$). Umeyama shows that the correct fix depends on $\det(\Sigma_{xy})$:</p>
<ul>
<li>If $\det(\Sigma_{xy}) \geq 0$: set $S = I$, so $R = UV^T$</li>
<li>If $\det(\Sigma_{xy}) &lt; 0$: set $S = \operatorname{diag}(1, \ldots, 1, -1)$, flipping the last singular value&rsquo;s contribution</li>
</ul>
<p>This distinction matters because corrupted data can make $\det(UV^T) = -1$ even when the true transformation is a proper rotation. Simply flipping a column of $U$ does not always yield the correct least-squares solution.</p>
<h2 id="generality">Generality</h2>
<p>The formulation works for any dimension $m$, covering both 2D and 3D registration problems. The proof uses Lagrange multipliers with explicit enforcement of both orthogonality ($R^T R = I$) and the proper rotation constraint ($\det(R) = 1$), which prior methods enforced only partially.</p>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Umeyama, S. (1991). Least-squares estimation of transformation parameters between two point patterns. <em>IEEE Transactions on Pattern Analysis and Machine Intelligence</em>, 13(4), 376-380. <a href="https://doi.org/10.1109/34.88573">https://doi.org/10.1109/34.88573</a></p>
<p><strong>Publication</strong>: IEEE TPAMI, 1991</p>
<p><strong>Additional Resources</strong>:</p>
<ul>
<li><a href="/posts/kabsch-algorithm/">Kabsch Algorithm: NumPy, PyTorch, TensorFlow, and JAX</a> (tutorial with implementations including the Kabsch-Umeyama scaling extension)</li>
<li><a href="/projects/kabsch-horn-cookbook/">Kabsch-Horn Cookbook</a> (a differentiable, gradient-safe implementation of Kabsch, Horn, and Umeyama alignment across NumPy, PyTorch, JAX, TensorFlow, and MLX)</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@article</span>{umeyama1991least,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>=<span style="color:#e6db74">{Least-squares estimation of transformation parameters between two point patterns}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>=<span style="color:#e6db74">{Umeyama, Shinji}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">journal</span>=<span style="color:#e6db74">{IEEE Transactions on Pattern Analysis and Machine Intelligence}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">volume</span>=<span style="color:#e6db74">{13}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">number</span>=<span style="color:#e6db74">{4}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span>=<span style="color:#e6db74">{376--380}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span>=<span style="color:#e6db74">{1991}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">publisher</span>=<span style="color:#e6db74">{IEEE}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">doi</span>=<span style="color:#e6db74">{10.1109/34.88573}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Horn et al.: Absolute Orientation Using Orthonormal Matrices</title><link>https://hunterheidenreich.com/notes/computational-biology/horn-orthonormal-matrices/</link><pubDate>Mon, 16 Mar 2026 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/computational-biology/horn-orthonormal-matrices/</guid><description>Horn, Hilden, and Negahdaripour (1988) solve absolute orientation using matrix square roots, providing an orthonormal matrix alternative to quaternions.</description><content:encoded><![CDATA[<h2 id="a-matrix-based-companion-to-the-quaternion-method">A Matrix-Based Companion to the Quaternion Method</h2>
<p>This <strong>Method</strong> paper presents a closed-form solution to the absolute orientation problem using $3 \times 3$ orthonormal matrices directly, complementing <a href="/notes/computational-biology/horn-absolute-orientation/">Horn&rsquo;s earlier quaternion-based solution</a> (1987). The authors note that while quaternions are more elegant, orthonormal matrices are more widely used in photogrammetry, graphics, and robotics. The solution relies on the polar decomposition of the cross-covariance matrix via its matrix square root.</p>
<p>The paper also compares two approaches: (1) directly finding the best-fit orthonormal matrix (the main result), and (2) finding an unconstrained best-fit linear transformation and then projecting it onto the nearest orthonormal matrix. These give different results, and only the first approach has the desired symmetry property.</p>
<h2 id="the-rotation-via-polar-decomposition">The Rotation via Polar Decomposition</h2>
<p>As in the quaternion paper, the problem reduces to finding the orthonormal matrix $R$ maximizing $\operatorname{Tr}(R^T M)$, where $M = \sum_{i=1}^{n} \mathbf{r}&rsquo;_{r,i} (\mathbf{r}&rsquo;_{l,i})^T$ is the cross-covariance matrix of the centered point sets.</p>
<p>The key insight is the polar decomposition: any matrix $M$ can be written as:</p>
<p>$$
M = U S
$$</p>
<p>where $U$ is orthonormal and $S = (M^T M)^{1/2}$ is positive semidefinite. When $M$ is nonsingular:</p>
<p>$$
U = M (M^T M)^{-1/2}
$$</p>
<p>The matrix square root $(M^T M)^{1/2}$ is computed via eigendecomposition. If $M^T M$ has eigenvalues $\lambda_1, \lambda_2, \lambda_3$ and eigenvectors $\hat{\mathbf{u}}_1, \hat{\mathbf{u}}_2, \hat{\mathbf{u}}_3$:</p>
<p>$$
(M^T M)^{1/2} = \sqrt{\lambda_1} , \hat{\mathbf{u}}_1 \hat{\mathbf{u}}_1^T + \sqrt{\lambda_2} , \hat{\mathbf{u}}_2 \hat{\mathbf{u}}_2^T + \sqrt{\lambda_3} , \hat{\mathbf{u}}_3 \hat{\mathbf{u}}_3^T
$$</p>
<p>The sign of $\det(U)$ equals the sign of $\det(M)$, so $U$ is a proper rotation when $\det(M) &gt; 0$ and a reflection when $\det(M) &lt; 0$.</p>
<h2 id="handling-the-coplanar-case">Handling the Coplanar Case</h2>
<p>When one set of measurements is coplanar, $M$ is singular ($\operatorname{rank}(M) = 2$) and one eigenvalue of $M^T M$ is zero. The matrix square root still exists (positive semidefinite rather than positive definite), but $S$ is no longer invertible.</p>
<p>In this case, $U$ is determined only for two of its three columns. The third column (corresponding to the zero eigenvalue) is fixed by the orthonormality constraint, with a sign ambiguity resolved by requiring $\det(U) = +1$ (proper rotation).</p>
<h2 id="the-nearest-orthonormal-matrix-alternative-approach">The Nearest Orthonormal Matrix (Alternative Approach)</h2>
<p>The paper also derives a closed-form solution for finding the orthonormal matrix nearest to an arbitrary matrix $A$ (minimizing $\lVert A - R \rVert^2$). This uses the same polar decomposition machinery: if $A = U_A S_A$, then $U_A$ is the nearest orthonormal matrix.</p>
<p>This approach (find unconstrained best-fit transform, then project to nearest orthonormal matrix) was used by some earlier methods. Horn et al. show it gives a different result from the direct least-squares solution and lacks the symmetry property: the inverse transformation from right-to-left is generally not the exact inverse of the left-to-right solution.</p>
<h2 id="relationship-to-other-methods">Relationship to Other Methods</h2>
<table>
	<thead>
			<tr>
					<th>Method</th>
					<th>Rotation representation</th>
					<th>Core computation</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><a href="/notes/computational-biology/kabsch-algorithm/">Kabsch (1976)</a></td>
					<td>Orthogonal matrix</td>
					<td>Eigendecomposition of $\tilde{R}R$ ($3 \times 3$)</td>
			</tr>
			<tr>
					<td><a href="/notes/computational-biology/horn-absolute-orientation/">Horn (1987)</a></td>
					<td>Unit quaternion</td>
					<td>Eigenvector of $N$ ($4 \times 4$)</td>
			</tr>
			<tr>
					<td>Horn et al. (1988)</td>
					<td>Orthonormal matrix</td>
					<td>Square root of $M^T M$ ($3 \times 3$)</td>
			</tr>
			<tr>
					<td><a href="/notes/computational-biology/arun-svd-point-fitting/">Arun et al. (1987)</a></td>
					<td>Orthonormal matrix</td>
					<td>SVD of $H$ ($3 \times 3$)</td>
			</tr>
	</tbody>
</table>
<p>The polar decomposition approach (this paper) and the SVD approach (<a href="/notes/computational-biology/arun-svd-point-fitting/">Arun et al.</a>) are closely related: the SVD $M = U \Lambda V^T$ gives the polar decomposition as $M = (UV^T)(V \Lambda V^T)$ where $UV^T$ is the orthonormal factor and $V \Lambda V^T$ is the positive semidefinite factor. Both methods can produce reflections under noisy data, which <a href="/notes/computational-biology/umeyama-similarity-transformation/">Umeyama (1991)</a> later addressed.</p>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Horn, B. K. P., Hilden, H. M., &amp; Negahdaripour, S. (1988). Closed-form solution of absolute orientation using orthonormal matrices. <em>Journal of the Optical Society of America A</em>, 5(7), 1127-1135. <a href="https://doi.org/10.1364/josaa.5.001127">https://doi.org/10.1364/josaa.5.001127</a></p>
<p><strong>Publication</strong>: Journal of the Optical Society of America A, 1988</p>
<p><strong>Additional Resources</strong>:</p>
<ul>
<li><a href="/posts/kabsch-algorithm/">Kabsch Algorithm: NumPy, PyTorch, TensorFlow, and JAX</a> (tutorial with differentiable implementations)</li>
<li><a href="/projects/kabsch-horn-cookbook/">Kabsch-Horn Cookbook</a> (a differentiable, gradient-safe implementation of Kabsch, Horn, and Umeyama alignment across NumPy, PyTorch, JAX, TensorFlow, and MLX)</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@article</span>{horn1988closed,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>=<span style="color:#e6db74">{Closed-form solution of absolute orientation using orthonormal matrices}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>=<span style="color:#e6db74">{Horn, Berthold K. P. and Hilden, Hugh M. and Negahdaripour, Shahriar}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">journal</span>=<span style="color:#e6db74">{Journal of the Optical Society of America A}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">volume</span>=<span style="color:#e6db74">{5}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">number</span>=<span style="color:#e6db74">{7}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span>=<span style="color:#e6db74">{1127--1135}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span>=<span style="color:#e6db74">{1988}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">publisher</span>=<span style="color:#e6db74">{Optica Publishing Group}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">doi</span>=<span style="color:#e6db74">{10.1364/josaa.5.001127}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Arun et al.: SVD-Based Least-Squares Fitting of 3D Points</title><link>https://hunterheidenreich.com/notes/computational-biology/arun-svd-point-fitting/</link><pubDate>Mon, 16 Mar 2026 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/computational-biology/arun-svd-point-fitting/</guid><description>Arun, Huang, and Blostein (1987) introduce an SVD-based algorithm for least-squares rotation and translation between two 3D point sets.</description><content:encoded><![CDATA[<h2 id="svd-for-3d-point-set-registration">SVD for 3D Point Set Registration</h2>
<p>This <strong>Method</strong> paper presents a concise algorithm for finding the least-squares rotation and translation between two 3D point sets using the singular value decomposition (SVD) of a $3 \times 3$ cross-covariance matrix. The approach is closely related to the earlier <a href="/notes/computational-biology/kabsch-algorithm/">Kabsch algorithm</a> (1976), which used eigendecomposition, and was developed independently of <a href="/notes/computational-biology/horn-absolute-orientation/">Horn&rsquo;s quaternion method</a> (1987). The paper also identifies a reflection degeneracy that <a href="/notes/computational-biology/umeyama-similarity-transformation/">Umeyama</a> later provided a complete fix for.</p>
<h2 id="problem-formulation">Problem Formulation</h2>
<p>Given two 3D point sets ${p_i}$ and ${p&rsquo;_i}$ ($i = 1, \ldots, N$) related by:</p>
<p>$$
p&rsquo;_i = R p_i + T + N_i
$$</p>
<p>where $R$ is a rotation matrix, $T$ is a translation vector, and $N_i$ is noise, find $\hat{R}$ and $\hat{T}$ minimizing:</p>
<p>$$
\Sigma^2 = \sum_{i=1}^{N} \lVert p&rsquo;_i - (R p_i + T) \rVert^2
$$</p>
<h2 id="decoupling-translation-and-rotation">Decoupling Translation and Rotation</h2>
<p>The translation is eliminated by centering both point sets at their centroids $p$ and $p&rsquo;$. Defining centered coordinates $q_i = p_i - p$ and $q&rsquo;_i = p&rsquo;_i - p&rsquo;$, the problem reduces to:</p>
<p>$$
\Sigma^2 = \sum_{i=1}^{N} \lVert q&rsquo;_i - R q_i \rVert^2
$$</p>
<p>Once $\hat{R}$ is found, the translation follows as $\hat{T} = p&rsquo; - \hat{R} p$.</p>
<h2 id="the-svd-algorithm">The SVD Algorithm</h2>
<p>The algorithm proceeds in five steps:</p>
<ol>
<li>Center both point sets by subtracting centroids</li>
<li>Compute the $3 \times 3$ cross-covariance matrix: $H = \sum_{i=1}^{N} q_i q&rsquo;^t_i$</li>
<li>Compute the SVD: $H = U \Lambda V^t$</li>
<li>Form the candidate rotation: $X = V U^t$</li>
<li>Check $\det(X)$: if $+1$, then $\hat{R} = X$; if $-1$, the result is a reflection</li>
</ol>
<p>The key insight is that minimizing $\Sigma^2$ is equivalent to maximizing $\operatorname{Trace}(RH)$. Using a lemma based on the Cauchy-Schwarz inequality, Arun et al. show that $X = VU^t$ maximizes this trace over all orthonormal matrices.</p>
<h2 id="the-reflection-problem">The Reflection Problem</h2>
<p>When $\det(VU^t) = -1$, the SVD produces a reflection rather than a proper rotation. Arun et al. analyze three cases:</p>
<p><strong>Noiseless, non-coplanar points</strong>: The SVD always gives a proper rotation ($\det = +1$). No issue arises.</p>
<p><strong>Coplanar points</strong> (including $N = 3$): One singular value of $H$ is zero. Both a rotation and a reflection achieve $\Sigma^2 = 0$. The fix is to flip the sign of the column of $V$ corresponding to the zero singular value:</p>
<p>$$
V&rsquo; = [v_1, v_2, -v_3], \quad X&rsquo; = V&rsquo; U^t
$$</p>
<p><strong>Noisy, non-coplanar points with $\det = -1$</strong>: The paper acknowledges this case cannot be handled by the algorithm. The reflection genuinely minimizes $\Sigma^2$ over all orthonormal matrices, meaning no rotation achieves a lower error. The authors suggest this only occurs with very large noise and recommend RANSAC-like approaches.</p>
<p>This last case is precisely what <a href="/notes/computational-biology/umeyama-similarity-transformation/">Umeyama (1991)</a> later resolved with a corrected formulation using a sign matrix $S$ conditioned on $\det(\Sigma_{xy})$.</p>
<h2 id="computational-comparison">Computational Comparison</h2>
<p>The paper includes VAX 11/780 benchmarks comparing three methods:</p>
<table>
	<thead>
			<tr>
					<th>Points</th>
					<th>SVD (ms)</th>
					<th>Quaternion (ms)</th>
					<th>Iterative (ms)</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>3</td>
					<td>54.6</td>
					<td>26.6</td>
					<td>126.8</td>
			</tr>
			<tr>
					<td>11</td>
					<td>37.0</td>
					<td>41.0</td>
					<td>105.2</td>
			</tr>
			<tr>
					<td>30</td>
					<td>44.2</td>
					<td>48.3</td>
					<td>111.0</td>
			</tr>
	</tbody>
</table>
<p>The SVD and quaternion methods have comparable speed, both significantly faster than the iterative approach. SVD becomes faster than quaternion for larger point sets since its core computation operates on a $3 \times 3$ matrix regardless of $N$.</p>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Arun, K. S., Huang, T. S., &amp; Blostein, S. D. (1987). Least-Squares Fitting of Two 3-D Point Sets. <em>IEEE Transactions on Pattern Analysis and Machine Intelligence</em>, PAMI-9(5), 698-700. <a href="https://doi.org/10.1109/TPAMI.1987.4767965">https://doi.org/10.1109/TPAMI.1987.4767965</a></p>
<p><strong>Publication</strong>: IEEE TPAMI, 1987</p>
<p><strong>Additional Resources</strong>:</p>
<ul>
<li><a href="/posts/kabsch-algorithm/">Kabsch Algorithm: NumPy, PyTorch, TensorFlow, and JAX</a> (tutorial with differentiable implementations)</li>
<li><a href="/projects/kabsch-horn-cookbook/">Kabsch-Horn Cookbook</a> (a differentiable, gradient-safe implementation of Kabsch, Horn, and Umeyama alignment across NumPy, PyTorch, JAX, TensorFlow, and MLX)</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@article</span>{arun1987least,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>=<span style="color:#e6db74">{Least-Squares Fitting of Two 3-D Point Sets}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>=<span style="color:#e6db74">{Arun, K. S. and Huang, T. S. and Blostein, S. D.}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">journal</span>=<span style="color:#e6db74">{IEEE Transactions on Pattern Analysis and Machine Intelligence}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">volume</span>=<span style="color:#e6db74">{PAMI-9}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">number</span>=<span style="color:#e6db74">{5}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span>=<span style="color:#e6db74">{698--700}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span>=<span style="color:#e6db74">{1987}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">publisher</span>=<span style="color:#e6db74">{IEEE}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">doi</span>=<span style="color:#e6db74">{10.1109/TPAMI.1987.4767965}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Latent Diffusion Models for High-Res Image Synthesis</title><link>https://hunterheidenreich.com/notes/machine-learning/generative-models/latent-diffusion-models/</link><pubDate>Sun, 15 Mar 2026 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/machine-learning/generative-models/latent-diffusion-models/</guid><description>Latent Diffusion Models train diffusion in a compressed latent space, enabling high-res image synthesis with cross-attention conditioning at reduced compute.</description><content:encoded><![CDATA[<h2 id="what-kind-of-paper-is-this">What kind of paper is this?</h2>
<p>This is a <strong>Method</strong> paper. It introduces Latent Diffusion Models (LDMs), which train denoising diffusion models in the latent space of pretrained autoencoders rather than directly in pixel space. The key insight is that separating perceptual compression from generative learning enables high-resolution image synthesis at a fraction of the computational cost of pixel-based diffusion. The paper also introduces a cross-attention conditioning mechanism for flexible multi-modal generation.</p>
<h2 id="computational-cost-of-pixel-space-diffusion">Computational Cost of Pixel-Space Diffusion</h2>
<p>Training diffusion models directly in pixel space is computationally expensive (150 to 1000 V100 GPU-days for leading models at the time) because the model must process high-dimensional RGB data at every denoising step. Much of this compute is spent modeling imperceptible high-frequency details. The authors observe that learning can be split into two stages: a perceptual compression stage that removes high-frequency detail, and a semantic compression stage where the generative model learns the conceptual composition. Prior two-stage approaches (VQGAN, DALL-E) relied on aggressive compression and autoregressive modeling in discrete latent spaces, trading off reconstruction quality for tractability.</p>
<h2 id="core-innovation-diffusion-in-latent-space">Core Innovation: Diffusion in Latent Space</h2>
<p>LDMs decompose image synthesis into two phases:</p>
<p><strong>Phase 1: Perceptual Compression.</strong> A pretrained autoencoder (encoder $\mathcal{E}$, decoder $\mathcal{D}$) maps images $x \in \mathbb{R}^{H \times W \times 3}$ to a lower-dimensional latent representation $z = \mathcal{E}(x) \in \mathbb{R}^{h \times w \times c}$ with spatial downsampling factor $f = H/h$. The autoencoder is trained with a perceptual loss (matching deep features from a pretrained VGG network) and a patch-based adversarial objective, with either KL or VQ regularization on the latent space.</p>
<p><strong>Phase 2: Latent Diffusion.</strong> A standard denoising diffusion model operates in this latent space. The training objective becomes:</p>
<p>$$L_{\text{LDM}} := \mathbb{E}_{\mathcal{E}(x), \epsilon \sim \mathcal{N}(0,1), t} \left[ \left| \epsilon - \epsilon_\theta(z_t, t) \right|_2^2 \right]$$</p>
<p>where $z_t$ is the noised latent at timestep $t$, and $\epsilon_\theta$ is a time-conditional UNet.</p>
<p><strong>Cross-Attention Conditioning.</strong> To enable conditioning on text, semantic maps, or other modalities, the authors introduce cross-attention layers into the UNet. A domain-specific encoder $\tau_\theta$ maps conditioning input $y$ to an intermediate representation $\tau_\theta(y) \in \mathbb{R}^{M \times d_\tau}$, which interacts with the UNet features via:</p>
<p>$$Q = W_Q^{(i)} \cdot \varphi_i(z_t), \quad K = W_K^{(i)} \cdot \tau_\theta(y), \quad V = W_V^{(i)} \cdot \tau_\theta(y)$$</p>
<p>The conditional objective then becomes:</p>
<p>$$L_{\text{LDM}} := \mathbb{E}_{\mathcal{E}(x), y, \epsilon \sim \mathcal{N}(0,1), t} \left[ \left| \epsilon - \epsilon_\theta(z_t, t, \tau_\theta(y)) \right|_2^2 \right]$$</p>
<p>Both $\tau_\theta$ and $\epsilon_\theta$ are optimized jointly.</p>
<h2 id="experimental-setup-and-results">Experimental Setup and Results</h2>
<p>The authors evaluate across multiple tasks and datasets:</p>
<p><strong>Perceptual compression tradeoffs.</strong> Downsampling factors $f \in {1, 2, 4, 8, 16, 32}$ are compared on ImageNet class-conditional generation. LDM-1 (pixel-based) trains slowly; LDM-32 loses too much information. LDM-4 and LDM-8 achieve the best balance, with LDM-8 outperforming pixel-based diffusion by 38 FID points after 2M training steps on a single A100.</p>
<p><strong>Unconditional image synthesis</strong> on CelebA-HQ 256, FFHQ 256, LSUN Churches/Bedrooms 256: LDM-4 achieves FID 5.11 on CelebA-HQ (state of the art at the time), outperforming LSGM, GANs, and other likelihood-based models. On LSUN-Bedrooms, LDM-4 achieves FID 2.95, close to ADM (1.90) with half the parameters and roughly 4x less training compute (see Appendix E.3.5).</p>
<p><strong>Text-to-image synthesis</strong> on MS-COCO: A 1.45B parameter LDM-KL-8 model trained on LAION-400M achieves FID 12.63 with classifier-free guidance (a technique that amplifies the conditioning signal at the cost of diversity, by interpolating between conditional and unconditional predictions) at scale s=1.5, on par with GLIDE (FID 12.24, 6B params) and Make-A-Scene (FID 11.84, 4B params) with substantially fewer parameters.</p>
<p><strong>Class-conditional ImageNet 256:</strong> LDM-4-G achieves FID 3.60, IS 247.67, outperforming ADM-G (FID 4.59) with fewer parameters and less compute.</p>
<p><strong>Super-resolution:</strong> LDM-4 (big) achieves FID 2.4 on ImageNet 64-to-256 upscaling (validation split), outperforming SR3 in FID.</p>
<p><strong>Inpainting</strong> on Places: LDM-4 (big, w/ ft) achieves FID 1.50, setting a new state of the art on image inpainting.</p>
<h2 id="key-findings-and-limitations">Key Findings and Limitations</h2>
<ul>
<li>LDM-4 and LDM-8 offer the best tradeoff between perceptual compression and generation quality.</li>
<li>The autoencoder only needs to be trained once and can be reused across different diffusion models and tasks.</li>
<li>Cross-attention conditioning generalizes to text, semantic layouts, and bounding boxes without architecture changes.</li>
<li>Convolutional sampling enables generation at resolutions higher than the training resolution (up to 1024x1024).</li>
<li>Sequential sampling remains slower than GANs. The autoencoder reconstruction can become a bottleneck for tasks requiring pixel-level precision.</li>
</ul>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="data">Data</h3>
<table>
	<thead>
			<tr>
					<th>Purpose</th>
					<th>Dataset</th>
					<th>Size</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Unconditional</td>
					<td>CelebA-HQ, FFHQ, LSUN</td>
					<td>256x256</td>
					<td>Standard benchmarks</td>
			</tr>
			<tr>
					<td>Class-conditional</td>
					<td>ImageNet</td>
					<td>256x256</td>
					<td>1000 classes</td>
			</tr>
			<tr>
					<td>Text-to-image</td>
					<td>LAION-400M</td>
					<td>256x256</td>
					<td>400M image-text pairs</td>
			</tr>
			<tr>
					<td>Inpainting</td>
					<td>Places</td>
					<td>256x256, 512x512</td>
					<td>Following LaMa protocol</td>
			</tr>
			<tr>
					<td>Super-resolution</td>
					<td>ImageNet</td>
					<td>64 to 256</td>
					<td>Following SR3 pipeline</td>
			</tr>
	</tbody>
</table>
<h3 id="algorithms">Algorithms</h3>
<ul>
<li><strong>Autoencoder regularization</strong>: KL-reg (KL penalty toward standard normal, weighted by ~$10^{-6}$) or VQ-reg (vector quantization layer on the latent space with a learned codebook)</li>
<li><strong>Diffusion</strong>: Standard DDPM denoising with reweighted objective</li>
<li><strong>Sampling</strong>: DDIM sampler with configurable steps (100 to 500 depending on task)</li>
<li><strong>Guidance</strong>: Classifier-free diffusion guidance with scale $s$ (1.5 for class-conditional and text-to-image quantitative evaluation; 10.0 for qualitative text-to-image samples)</li>
</ul>
<h3 id="models">Models</h3>
<ul>
<li><strong>Autoencoder</strong>: Based on VQGAN architecture with perceptual + adversarial loss</li>
<li><strong>UNet backbone</strong>: Time-conditional with cross-attention layers at multiple resolutions</li>
<li><strong>Text encoder</strong>: BERT-tokenizer with transformer $\tau_\theta$ for LAION text-to-image model</li>
<li><strong>LDM-4-G</strong>: 400M parameters, $f=4$ downsampling</li>
<li><strong>LDM-KL-8 (text)</strong>: 1.45B parameters, $f=8$ downsampling, KL-regularized</li>
</ul>
<h3 id="evaluation">Evaluation</h3>
<table>
	<thead>
			<tr>
					<th>Metric</th>
					<th>Task</th>
					<th>Best Value</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>FID</td>
					<td>CelebA-HQ unconditional</td>
					<td>5.11</td>
					<td>500 DDIM steps</td>
			</tr>
			<tr>
					<td>FID</td>
					<td>ImageNet class-conditional</td>
					<td>3.60</td>
					<td>LDM-4-G, cfg s=1.5</td>
			</tr>
			<tr>
					<td>FID</td>
					<td>MS-COCO text-to-image</td>
					<td>12.63</td>
					<td>LDM-KL-8-G, 250 steps, cfg s=1.5</td>
			</tr>
			<tr>
					<td>FID</td>
					<td>Places inpainting</td>
					<td>1.50</td>
					<td>LDM-4 big, w/ ft</td>
			</tr>
			<tr>
					<td>FID</td>
					<td>ImageNet 4x super-resolution</td>
					<td>2.4</td>
					<td>LDM-4 big, 100 steps</td>
			</tr>
	</tbody>
</table>
<h3 id="hardware">Hardware</h3>
<ul>
<li>Perceptual compression tradeoff experiments: single NVIDIA A100</li>
<li>Inpainting model trained on eight V100</li>
<li>Training at least 2.7x faster than pixel-based diffusion at equal parameters</li>
</ul>
<h3 id="artifacts">Artifacts</h3>
<table>
	<thead>
			<tr>
					<th>Artifact</th>
					<th>Type</th>
					<th>License</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><a href="https://github.com/CompVis/latent-diffusion">CompVis/latent-diffusion</a></td>
					<td>Code</td>
					<td>MIT</td>
					<td>Official implementation with pretrained models</td>
			</tr>
	</tbody>
</table>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Rombach, R., Blattmann, A., Lorenz, D., Esser, P., &amp; Ommer, B. (2022). High-Resolution Image Synthesis with Latent Diffusion Models. <em>CVPR 2022</em>. <a href="https://arxiv.org/abs/2112.10752">https://arxiv.org/abs/2112.10752</a></p>
<p><strong>Publication</strong>: CVPR 2022</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@inproceedings</span>{rombach2022highresolution,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>     = <span style="color:#e6db74">{High-Resolution Image Synthesis with Latent Diffusion Models}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>    = <span style="color:#e6db74">{Rombach, Robin and Blattmann, Andreas and Lorenz, Dominik and Esser, Patrick and Ommer, Bj{\&#34;o}rn}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">booktitle</span> = <span style="color:#e6db74">{Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span>     = <span style="color:#e6db74">{10684--10695}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span>      = <span style="color:#e6db74">{2022}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><strong>Additional Resources</strong>:</p>
<ul>
<li><a href="https://github.com/CompVis/latent-diffusion">GitHub Repository</a></li>
<li><a href="/notes/machine-learning/generative-models/score-based-generative-modeling-sde/">Score-Based Generative Modeling with SDEs</a></li>
</ul>
]]></content:encoded></item><item><title>Kabsch Algorithm: Optimal Rotation for Point Set Alignment</title><link>https://hunterheidenreich.com/notes/computational-biology/kabsch-algorithm/</link><pubDate>Sun, 15 Mar 2026 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/computational-biology/kabsch-algorithm/</guid><description>Kabsch (1976) derives a closed-form solution for the optimal rotation aligning two weighted vector sets by minimizing squared deviations.</description><content:encoded><![CDATA[<h2 id="a-closed-form-solution-for-optimal-rotation">A Closed-Form Solution for Optimal Rotation</h2>
<p>This short communication presents a <strong>Method</strong> paper: a direct, analytical solution to a constrained optimization problem. Given two sets of vectors, Kabsch derives the orthogonal matrix (rotation) that best superimposes one set onto the other by minimizing a weighted sum of squared deviations. Prior approaches either solved an unconstrained problem and factorized the result (Diamond, 1976) or used iterative methods (McLachlan, 1972). Kabsch shows that a direct, non-iterative solution exists despite the non-linear nature of the orthogonality constraint.</p>
<h2 id="the-superposition-problem">The Superposition Problem</h2>
<p>The core problem arises frequently in crystallography and structural biology: given two sets of corresponding points (e.g., atomic coordinates from a known structure and experimentally measured coordinates), find the rigid rotation that best aligns them. Translations can be removed by centering both point sets at the origin, leaving only the rotational component.</p>
<p>Formally, given vector sets $\mathbf{x}_n$ and $\mathbf{y}_n$ ($n = 1, 2, \ldots, N$) with weights $w_n$, find the orthogonal matrix $\mathsf{U}$ minimizing:</p>
<p>$$
E = \frac{1}{2} \sum_{n} w_n (\mathsf{U} \mathbf{x}_n - \mathbf{y}_n)^2
$$</p>
<p>subject to orthogonality: $\tilde{\mathsf{U}} \mathsf{U} = \mathsf{I}$.</p>
<h2 id="derivation-via-lagrange-multipliers">Derivation via Lagrange Multipliers</h2>
<p>Kabsch introduces a symmetric matrix $\mathsf{L}$ of Lagrange multipliers to enforce orthogonality, forming the Lagrangian:</p>
<p>$$
G = E + \frac{1}{2} \sum_{i,j} l_{ij} \left( \sum_{k} u_{ki} u_{kj} - \delta_{ij} \right)
$$</p>
<p>Setting $\partial G / \partial u_{ij} = 0$ and defining two key matrices:</p>
<p>$$
r_{ij} = \sum_{n} w_n , y_{ni} , x_{nj} \qquad s_{ij} = \sum_{n} w_n , x_{ni} , x_{nj}
$$</p>
<p>where $\mathsf{R} = (r_{ij})$ is the weighted cross-covariance matrix and $\mathsf{S} = (s_{ij})$ is the weighted auto-covariance matrix, the stationarity condition becomes:</p>
<p>$$
\mathsf{U} \cdot (\mathsf{S} + \mathsf{L}) = \mathsf{R}
$$</p>
<h2 id="eigendecomposition-solution">Eigendecomposition Solution</h2>
<p>The key insight is that multiplying both sides by their transposes eliminates the unknown $\mathsf{U}$:</p>
<p>$$
(\mathsf{S} + \mathsf{L})(\mathsf{S} + \mathsf{L}) = \tilde{\mathsf{R}} \mathsf{R}
$$</p>
<p>Since $\tilde{\mathsf{R}} \mathsf{R}$ is symmetric positive definite, it has positive eigenvalues $\mu_k$ and eigenvectors $\mathbf{a}_k$. The matrix $\mathsf{S} + \mathsf{L}$ shares the same eigenvectors with eigenvalues $\sqrt{\mu_k}$.</p>
<p>From the eigenvectors $\mathbf{a}_k$, a second set of unit vectors $\mathbf{b}_k$ is defined:</p>
<p>$$
\mathbf{b}_k = \frac{1}{\sqrt{\mu_k}} \mathsf{R} , \mathbf{a}_k
$$</p>
<p>The optimal rotation matrix is then constructed directly:</p>
<p>$$
u_{ij} = \sum_{k} b_{ki} , a_{kj}
$$</p>
<h2 id="handling-degeneracies-and-generalizations">Handling Degeneracies and Generalizations</h2>
<p>Kabsch addresses two extensions:</p>
<ol>
<li>
<p><strong>Planar point sets</strong>: When all vectors lie in a plane, one eigenvalue of $\tilde{\mathsf{R}} \mathsf{R}$ is zero. The missing eigenvectors are recovered via cross products: $\mathbf{a}_3 = \mathbf{a}_1 \times \mathbf{a}_2$ and $\mathbf{b}_3 = \mathbf{b}_1 \times \mathbf{b}_2$.</p>
</li>
<li>
<p><strong>General metric constraints</strong>: The orthogonality constraint $\tilde{\mathsf{U}} \mathsf{U} = \mathsf{I}$ can be replaced by $\tilde{\mathsf{U}} \mathsf{U} = \mathsf{M}$ for any symmetric positive definite $\mathsf{M}$. By finding any specific solution $\mathsf{B}$ and transforming the input vectors as $\mathbf{x}&rsquo;_n = \mathsf{B} \mathbf{x}_n$, the problem reduces back to the standard orthogonal case.</p>
</li>
</ol>
<p>The method generalizes naturally to vector spaces of arbitrary dimension.</p>
<h2 id="legacy-and-impact">Legacy and Impact</h2>
<p>This two-page communication became one of the most cited papers in structural biology. The &ldquo;Kabsch algorithm&rdquo; (or &ldquo;Kabsch rotation&rdquo;) is the standard method for computing the root-mean-square deviation (RMSD) between two molecular structures after optimal superposition. It underpins structure comparison tools across crystallography, NMR spectroscopy, cryo-EM, and computational chemistry.</p>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Kabsch, W. (1976). A solution for the best rotation to relate two sets of vectors. <em>Acta Crystallographica Section A</em>, 32(5), 922-923. <a href="https://doi.org/10.1107/s0567739476001873">https://doi.org/10.1107/s0567739476001873</a></p>
<p><strong>Publication</strong>: Acta Crystallographica Section A, 1976</p>
<p><strong>Additional Resources</strong>:</p>
<ul>
<li><a href="/posts/kabsch-algorithm/">Kabsch Algorithm: NumPy, PyTorch, TensorFlow, and JAX</a> (tutorial with differentiable implementations)</li>
<li><a href="/projects/kabsch-horn-cookbook/">Kabsch-Horn Cookbook</a> (a differentiable, gradient-safe implementation of Kabsch, Horn, and Umeyama alignment across NumPy, PyTorch, JAX, TensorFlow, and MLX)</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@article</span>{kabsch1976solution,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>=<span style="color:#e6db74">{A solution for the best rotation to relate two sets of vectors}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>=<span style="color:#e6db74">{Kabsch, Wolfgang}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">journal</span>=<span style="color:#e6db74">{Acta Crystallographica Section A: Crystal Physics, Diffraction, Theoretical and General Crystallography}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">volume</span>=<span style="color:#e6db74">{32}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">number</span>=<span style="color:#e6db74">{5}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span>=<span style="color:#e6db74">{922--923}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span>=<span style="color:#e6db74">{1976}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">publisher</span>=<span style="color:#e6db74">{International Union of Crystallography}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">doi</span>=<span style="color:#e6db74">{10.1107/s0567739476001873}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Horn's Method: Absolute Orientation via Unit Quaternions</title><link>https://hunterheidenreich.com/notes/computational-biology/horn-absolute-orientation/</link><pubDate>Sun, 15 Mar 2026 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/computational-biology/horn-absolute-orientation/</guid><description>Horn (1987) presents a closed-form quaternion solution for absolute orientation, finding optimal rotation, translation, and scale between two point sets.</description><content:encoded><![CDATA[<h2 id="a-quaternion-approach-to-point-set-registration">A Quaternion Approach to Point Set Registration</h2>
<p>This <strong>Method</strong> paper presents a closed-form solution to the absolute orientation problem: given corresponding points measured in two different coordinate systems, find the optimal rotation, translation, and scale that maps one set onto the other. While the <a href="/notes/computational-biology/kabsch-algorithm/">Kabsch algorithm</a> (1976) solved the rotation subproblem via eigendecomposition of $\tilde{\mathsf{R}}\mathsf{R}$, Horn&rsquo;s approach uses unit quaternions to represent rotation, reducing the problem to finding the eigenvector of a $4 \times 4$ symmetric matrix associated with its largest eigenvalue.</p>
<h2 id="the-absolute-orientation-problem">The Absolute Orientation Problem</h2>
<p>Given $n$ point pairs ${\mathbf{r}_{l,i}}$ and ${\mathbf{r}_{r,i}}$ measured in &ldquo;left&rdquo; and &ldquo;right&rdquo; coordinate systems, find the transformation:</p>
<p>$$
\mathbf{r}_r = s , R(\mathbf{r}_l) + \mathbf{r}_0
$$</p>
<p>where $s$ is a scale factor, $R$ is a rotation, and $\mathbf{r}_0$ is a translation, minimizing the sum of squared residual errors:</p>
<p>$$
\sum_{i=1}^{n} \lVert \mathbf{r}_{r,i} - s , R(\mathbf{r}_{l,i}) - \mathbf{r}_0 \rVert^2
$$</p>
<p>Prior methods either used iterative numerical procedures or selectively discarded constraints (e.g., Thompson&rsquo;s and Schut&rsquo;s three-point methods). Horn derives a direct solution that uses all available information from all points simultaneously.</p>
<h2 id="decoupling-translation-scale-and-rotation">Decoupling Translation, Scale, and Rotation</h2>
<p>Horn shows that the three components of the transformation can be solved sequentially.</p>
<p><strong>Translation</strong>: After centering both point sets at their centroids ($\bar{\mathbf{r}}_l$ and $\bar{\mathbf{r}}_r$), the optimal translation is:</p>
<p>$$
\mathbf{r}_0 = \bar{\mathbf{r}}_r - s , R(\bar{\mathbf{r}}_l)
$$</p>
<p><strong>Scale</strong>: Horn derives three formulations (asymmetric left, asymmetric right, and symmetric). The symmetric version, which ensures the inverse transformation yields the reciprocal scale, is:</p>
<p>$$
s = \left( \frac{\sum_{i=1}^{n} \lVert \mathbf{r}&rsquo;_{r,i} \rVert^2}{\sum_{i=1}^{n} \lVert \mathbf{r}&rsquo;_{l,i} \rVert^2} \right)^{1/2}
$$</p>
<p>the ratio of root-mean-square deviations from the respective centroids.</p>
<p><strong>Rotation</strong>: After removing translation and scale, the remaining problem is to find the rotation $R$ that maximizes:</p>
<p>$$
\sum_{i=1}^{n} \mathbf{r}&rsquo;_{r,i} \cdot R(\mathbf{r}&rsquo;_{l,i})
$$</p>
<h2 id="the-quaternion-eigenvector-solution">The Quaternion Eigenvector Solution</h2>
<p>Horn represents rotation using unit quaternions $\dot{q} = q_0 + i q_x + j q_y + k q_z$ with $\lVert \dot{q} \rVert = 1$. A rotation acts on a vector (represented as a purely imaginary quaternion $\dot{r}$) via the composite product:</p>
<p>$$
\dot{r}&rsquo; = \dot{q} , \dot{r} , \dot{q}^*
$$</p>
<p>Using the $4 \times 4$ matrix representations of quaternion products, the objective function becomes a quadratic form:</p>
<p>$$
\dot{q}^T N \dot{q}
$$</p>
<p>where $N$ is a real symmetric $4 \times 4$ matrix whose elements are combinations of the sums of products $S_{xx}, S_{xy}, \ldots, S_{zz}$ from the $3 \times 3$ cross-covariance matrix $M = \sum_i \mathbf{r}&rsquo;_{l,i} \mathbf{r}&rsquo;^T_{r,i}$:</p>
<p>$$
N = \begin{bmatrix} (S_{xx} + S_{yy} + S_{zz}) &amp; S_{yz} - S_{zy} &amp; S_{zx} - S_{xz} &amp; S_{xy} - S_{yx} \\ S_{yz} - S_{zy} &amp; (S_{xx} - S_{yy} - S_{zz}) &amp; S_{xy} + S_{yx} &amp; S_{zx} + S_{xz} \\ S_{zx} - S_{xz} &amp; S_{xy} + S_{yx} &amp; (-S_{xx} + S_{yy} - S_{zz}) &amp; S_{yz} + S_{zy} \\ S_{xy} - S_{yx} &amp; S_{zx} + S_{xz} &amp; S_{yz} + S_{zy} &amp; (-S_{xx} - S_{yy} + S_{zz}) \end{bmatrix}
$$</p>
<p>The trace of $N$ is always zero. The unit quaternion maximizing $\dot{q}^T N \dot{q}$ is the eigenvector corresponding to the most positive eigenvalue of $N$.</p>
<h2 id="the-characteristic-polynomial">The Characteristic Polynomial</h2>
<p>The eigenvalues satisfy a quartic $\lambda^4 + c_3 \lambda^3 + c_2 \lambda^2 + c_1 \lambda + c_0 = 0$ where:</p>
<ul>
<li>$c_3 = 0$ (trace of $N$ is zero, so the four roots sum to zero)</li>
<li>$c_2 = -2 \operatorname{Tr}(M^T M)$ (always negative, guaranteeing both positive and negative roots)</li>
<li>$c_1 = -8 \det(M)$</li>
<li>$c_0 = \det(N)$</li>
</ul>
<p>When points are coplanar (including the common case of exactly three points), $\det(M) = 0$, so $c_1 = 0$ and the quartic reduces to a biquadratic solvable in closed form.</p>
<h2 id="coplanar-points-and-the-three-point-case">Coplanar Points and the Three-Point Case</h2>
<p>For coplanar measurements, the quartic simplifies to $\lambda^4 + c_2 \lambda^2 + c_0 = 0$, yielding:</p>
<p>$$
\lambda_m = \left[ \frac{1}{2} \left( (c_2^2 - 4c_0)^{1/2} - c_2 \right) \right]^{1/2}
$$</p>
<p>Horn also provides a geometric interpretation for the coplanar case: first rotate one plane into the other (about their line of intersection), then solve a 2D least-squares rotation within the shared plane.</p>
<h2 id="comparison-with-the-kabsch-algorithm">Comparison with the Kabsch Algorithm</h2>
<p>Both methods solve the same underlying optimization problem but approach it differently:</p>
<table>
	<thead>
			<tr>
					<th>Aspect</th>
					<th>Kabsch (1976)</th>
					<th>Horn (1987)</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Rotation representation</td>
					<td>Orthogonal matrix</td>
					<td>Unit quaternion</td>
			</tr>
			<tr>
					<td>Core computation</td>
					<td>SVD or eigendecomposition of $\tilde{R}R$ ($3 \times 3$)</td>
					<td>Eigenvector of $N$ ($4 \times 4$)</td>
			</tr>
			<tr>
					<td>Scale estimation</td>
					<td>Not addressed</td>
					<td>Three formulations (including symmetric)</td>
			</tr>
			<tr>
					<td>Constraint enforcement</td>
					<td>Lagrange multipliers</td>
					<td>Unit quaternion norm</td>
			</tr>
			<tr>
					<td>Symmetry guarantee</td>
					<td>Not addressed</td>
					<td>Proven for symmetric scale</td>
			</tr>
			<tr>
					<td>Degenerate cases</td>
					<td>Cross-product fallback</td>
					<td>Biquadratic closed form</td>
			</tr>
	</tbody>
</table>
<p>Horn emphasizes a symmetry property: the inverse transformation should yield exactly the inverse parameters. This holds automatically for the quaternion rotation but requires a specific (symmetric) choice of scale formula.</p>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Horn, B. K. P. (1987). Closed-form solution of absolute orientation using unit quaternions. <em>Journal of the Optical Society of America A</em>, 4(4), 629-642. <a href="https://doi.org/10.1364/JOSAA.4.000629">https://doi.org/10.1364/JOSAA.4.000629</a></p>
<p><strong>Publication</strong>: Journal of the Optical Society of America A, 1987</p>
<p><strong>Additional Resources</strong>:</p>
<ul>
<li><a href="/posts/kabsch-algorithm/">Kabsch Algorithm: NumPy, PyTorch, TensorFlow, and JAX</a> (tutorial with differentiable implementations of the related SVD-based method)</li>
<li><a href="/projects/kabsch-horn-cookbook/">Kabsch-Horn Cookbook</a> (a differentiable, gradient-safe implementation of Kabsch, Horn, and Umeyama alignment across NumPy, PyTorch, JAX, TensorFlow, and MLX)</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@article</span>{horn1987closed,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>=<span style="color:#e6db74">{Closed-form solution of absolute orientation using unit quaternions}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>=<span style="color:#e6db74">{Horn, Berthold K. P.}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">journal</span>=<span style="color:#e6db74">{Journal of the Optical Society of America A}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">volume</span>=<span style="color:#e6db74">{4}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">number</span>=<span style="color:#e6db74">{4}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span>=<span style="color:#e6db74">{629--642}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span>=<span style="color:#e6db74">{1987}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">publisher</span>=<span style="color:#e6db74">{Optica Publishing Group}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">doi</span>=<span style="color:#e6db74">{10.1364/josaa.4.000629}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>GraphReco: Probabilistic Structure Recognition (2026)</title><link>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/rule-based/graphreco-2026/</link><pubDate>Sun, 15 Mar 2026 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/rule-based/graphreco-2026/</guid><description>GraphReco is a rule-based OCSR system using Markov networks for probabilistic atom/bond ambiguity resolution during graph assembly.</description><content:encoded><![CDATA[<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Wang, H., Yu, Y., &amp; Liu, J.-C. (2026). GraphReco: Probabilistic Structure Recognition for Chemical Molecules. <em>ChemistryOpen</em>, e202500537. <a href="https://doi.org/10.1002/open.202500537">https://doi.org/10.1002/open.202500537</a></p>
<p><strong>Publication</strong>: ChemistryOpen 2026 (Open Access)</p>
<h2 id="a-rule-based-ocsr-system-with-probabilistic-graph-assembly">A Rule-Based OCSR System with Probabilistic Graph Assembly</h2>
<p>GraphReco tackles a challenge that is rarely addressed explicitly in rule-based OCSR: the ambiguity that arises during graph assembly when lower-level component extraction results are imprecise. Small deviations in bond endpoint locations, false positive detections, and spatial proximity between elements all create uncertainty about which atoms and bonds should be connected, merged, or discarded.</p>
<p>The system introduces two main contributions:</p>
<ol>
<li><strong>Fragment Merging (FM) line detection</strong>: An adaptive three-stage algorithm for precise bond line identification across images of variable resolution</li>
<li><strong>Probabilistic ambiguity resolution</strong>: A Markov network that infers the most likely existence and merging state of atom and bond candidates</li>
</ol>
<h2 id="three-stage-pipeline">Three-Stage Pipeline</h2>
<p>GraphReco follows a three-stage workflow:</p>
<ol>
<li>
<p><strong>Component Extraction</strong>: Detects circles (aromatic bonds), bond lines (via the FM algorithm), and chemical symbols (via Tesseract OCR). Includes detection of solid wedge, dashed wedge, dashed line, and wavy bond styles. A semi-open-loop correction step resolves cases where symbols are misclassified as bonds and vice versa.</p>
</li>
<li>
<p><strong>Atom and Bond Ambiguity Resolution</strong>: Creates atom and bond candidates from detected components, builds a Markov network to infer their most probable states, and resolves candidates through existence and merging decisions.</p>
</li>
<li>
<p><strong>Graph Reconstruction</strong>: Assembles resolved atoms and bonds into a molecule graph, selects the largest connected component, and exports as MDL Molfile.</p>
</li>
</ol>
<h2 id="fragment-merging-line-detection">Fragment Merging Line Detection</h2>
<p>Classical Line Hough Transform (LHT) struggles with chemical structure images because bond lines suffer from pixelization, and algorithm parameters that work for one image resolution fail at others. The FM algorithm addresses this with three stages:</p>
<ol>
<li>
<p><strong>Fragment extraction</strong>: Apply LHT with high-resolution parameters (resolution $r = 2$, resolution $\theta = 2°$) to detect fine line fragments. Walk along detected theoretical lines to find actual black pixels and group them by connectivity.</p>
</li>
<li>
<p><strong>Fragment grouping</strong>: Pair fragments that share similar angles, are close in the perpendicular direction, and are either overlapping or connected by a path of black pixels.</p>
</li>
<li>
<p><strong>Fragment merging</strong>: Merge grouped fragments into single line segments using the two border pixels farthest from the centroid.</p>
</li>
</ol>
<p>The FM algorithm effectively handles the tradeoff that plagues standard LHT: coarse parameters miss short lines and produce overlaps, while fine parameters return many fragments shorter than actual bonds.</p>
<h2 id="probabilistic-ambiguity-resolution-via-markov-network">Probabilistic Ambiguity Resolution via Markov Network</h2>
<p>After component extraction, GraphReco creates atom and bond candidates rather than directly assembling the graph. Each bond endpoint generates an atom candidate with a circular bounding area of radius:</p>
<p>$$r_b = \min(l_{\text{bond}}, l_{\text{med}}) / 4$$</p>
<p>where $l_{\text{bond}}$ is the bond length and $l_{\text{med}}$ is the median bond length.</p>
<p>A Markov network is constructed with four types of nodes:</p>
<ul>
<li><strong>Atom nodes</strong>: Boolean existence variables for each atom candidate</li>
<li><strong>Bond nodes</strong>: Boolean existence variables for each bond candidate</li>
<li><strong>Atom merge nodes</strong>: Boolean variables for pairs of overlapping atom candidates</li>
<li><strong>Bond merge nodes</strong>: Boolean variables for pairs of nearby bond candidates</li>
</ul>
<p>Potential functions encode rules about when candidates should exist or merge, with merging likelihood between two bond-ending atom candidates defined as a piecewise function of center distance $d$:</p>
<p>$$P(a_1, a_2) = \begin{cases} 0.9, &amp; \text{if } d \leq Q \\ 0.7 - 0.4(d - Q)/(R - Q), &amp; \text{if } Q &lt; d \leq R \\ 0.1, &amp; \text{if } d &gt; R \end{cases}$$</p>
<p>where $Q = \max(r_1, r_2)$ and $R = \min(1.5Q, r_1 + r_2)$. MAP inference determines the final state of all candidates.</p>
<h2 id="evaluation-results">Evaluation Results</h2>
<p>GraphReco is evaluated on USPTO benchmarks with InChI string comparison (stereochemistry removed):</p>
<table>
	<thead>
			<tr>
					<th>System</th>
					<th>USPTO-10K</th>
					<th>USPTO-10K-Abb</th>
					<th>USPTO</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><strong>GraphReco</strong></td>
					<td><strong>94.2</strong></td>
					<td><strong>86.7</strong></td>
					<td>89.9</td>
			</tr>
			<tr>
					<td>MolVec 0.9.7</td>
					<td>92.4</td>
					<td>70.3</td>
					<td>89.1</td>
			</tr>
			<tr>
					<td>Imago 2.0</td>
					<td>89.9</td>
					<td>63.0</td>
					<td>89.4</td>
			</tr>
			<tr>
					<td>OSRA 2.1</td>
					<td>89.7</td>
					<td>63.9</td>
					<td>89.3</td>
			</tr>
			<tr>
					<td>MolGrapher</td>
					<td>93.3</td>
					<td>82.8</td>
					<td><strong>91.5</strong></td>
			</tr>
			<tr>
					<td>Img2Mol</td>
					<td>35.4</td>
					<td>13.8</td>
					<td>25.2</td>
			</tr>
	</tbody>
</table>
<p>GraphReco outperforms all rule-based systems and most ML systems, with a particularly large margin on USPTO-10K-Abb (abbreviation-heavy molecules). MolGrapher achieves slightly higher accuracy on the USPTO dataset.</p>
<h3 id="robustness-on-perturbed-images">Robustness on Perturbed Images</h3>
<p>On USPTO-perturbed (rotation and shearing applied), rule-based methods degrade substantially:</p>
<table>
	<thead>
			<tr>
					<th>System</th>
					<th>USPTO-perturbed</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>MolGrapher</td>
					<td><strong>86.7</strong></td>
			</tr>
			<tr>
					<td>Img2Mol</td>
					<td>42.3</td>
			</tr>
			<tr>
					<td><strong>GraphReco</strong></td>
					<td>40.6</td>
			</tr>
			<tr>
					<td>MolVec 0.9.7</td>
					<td>30.7</td>
			</tr>
			<tr>
					<td>OSRA 2.1</td>
					<td>6.4</td>
			</tr>
			<tr>
					<td>Imago 2.0</td>
					<td>5.1</td>
			</tr>
	</tbody>
</table>
<p>GraphReco performs better than other rule-based systems on perturbed inputs (40.6% vs. under 31%) thanks to its probabilistic assembly, but still falls far behind MolGrapher (86.7%), demonstrating the robustness advantage of learned approaches.</p>
<h2 id="ablation-study">Ablation Study</h2>
<p>Each component contributes substantially to overall performance on USPTO-10K:</p>
<table>
	<thead>
			<tr>
					<th>Configuration</th>
					<th>USPTO-10K</th>
					<th>USPTO-10K-Abb</th>
					<th>USPTO</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Full system</td>
					<td>94.2</td>
					<td>86.7</td>
					<td>89.9</td>
			</tr>
			<tr>
					<td>Without FM line detection</td>
					<td>2.9</td>
					<td>5.5</td>
					<td>4.8</td>
			</tr>
			<tr>
					<td>Without atom candidates</td>
					<td>9.8</td>
					<td>0.4</td>
					<td>5.0</td>
			</tr>
			<tr>
					<td>Without bond candidates</td>
					<td>79.1</td>
					<td>75.8</td>
					<td>75.0</td>
			</tr>
			<tr>
					<td>Without Markov network</td>
					<td>88.2</td>
					<td>81.4</td>
					<td>84.2</td>
			</tr>
	</tbody>
</table>
<p>The FM algorithm and atom candidate mechanism are both critical (accuracy drops below 10% without either). Bond candidates provide a moderate improvement (~15 percentage points), and the Markov network adds ~6 points over hard-threshold alternatives.</p>
<h2 id="limitations">Limitations</h2>
<ul>
<li>Deterministic expert rules limit robustness on perturbed or noisy images, as evidenced by the large accuracy gap with MolGrapher on USPTO-perturbed</li>
<li>The system relies on Tesseract OCR for symbol recognition, which may struggle with unusual fonts or degraded image quality</li>
<li>Only handles single 2D molecule structures per image</li>
<li>Stereochemistry is removed during evaluation, so performance on stereo-bond recognition is not assessed</li>
</ul>
<h2 id="reproducibility">Reproducibility</h2>
<p>GraphReco is implemented in Python and relies on Tesseract OCR, OpenCV, and RDKit. The authors provide an online demo for testing but have not released the source code or a public repository.</p>
<table>
	<thead>
			<tr>
					<th>Artifact</th>
					<th>Type</th>
					<th>License</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Online Demo</td>
					<td>Other</td>
					<td>Unknown</td>
					<td>Google Cloud Run deployment (no longer available)</td>
			</tr>
	</tbody>
</table>
<p><strong>Missing components for full reproduction:</strong></p>
<ul>
<li>Source code is not publicly available</li>
<li>No pre-built package or installable library</li>
<li>Hyperparameters for Markov network potential functions are given in the paper (Equations 8-11), but full implementation details are not released</li>
</ul>
<p><strong>Hardware/compute requirements:</strong> Not specified in the paper. The system uses classical computer vision (Hough transforms, thinning) and probabilistic inference (Markov networks), so GPU hardware is likely not required.</p>
]]></content:encoded></item><item><title>D3PM: Discrete Denoising Diffusion Probabilistic Models</title><link>https://hunterheidenreich.com/notes/machine-learning/generative-models/discrete-diffusion-models/</link><pubDate>Sun, 15 Mar 2026 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/machine-learning/generative-models/discrete-diffusion-models/</guid><description>D3PMs extend diffusion models to discrete data with structured transition matrices, connecting diffusion to masked language models.</description><content:encoded><![CDATA[<h2 id="what-kind-of-paper-is-this">What kind of paper is this?</h2>
<p>This is a <strong>Method</strong> paper. It extends denoising diffusion probabilistic models (DDPMs) from continuous to discrete state-spaces by introducing structured Markov transition matrices for the corruption process. The paper unifies several corruption strategies, draws a formal connection between absorbing-state diffusion and masked language models, and demonstrates competitive results on both image and text generation.</p>
<h2 id="diffusion-beyond-continuous-spaces">Diffusion Beyond Continuous Spaces</h2>
<p>Standard DDPMs operate in continuous state-spaces (e.g., pixel values treated as real numbers) and use Gaussian noise for corruption. Many important data types are inherently discrete: text (tokens from a vocabulary), quantized images (discrete pixel values), molecular structures, and segmentation maps. Prior work by Hoogeboom et al. extended binary diffusion to multinomial diffusion with uniform transition probabilities, but this limits the structure of the corruption process. D3PMs generalize this by allowing arbitrary transition matrices that encode domain-specific inductive biases.</p>
<h2 id="core-innovation-structured-transition-matrices">Core Innovation: Structured Transition Matrices</h2>
<p>D3PMs define a forward corruption process over discrete variables $\mathbf{x} \in {1, \ldots, K}^D$ using transition matrices $\mathbf{Q}_t \in \mathbb{R}^{K \times K}$:</p>
<p>$$q(\mathbf{x}_t | \mathbf{x}_{t-1}) = \text{Cat}(\mathbf{x}_t; \mathbf{p} = \mathbf{x}_{t-1} \mathbf{Q}_t)$$</p>
<p>where $\mathbf{x}_{t-1}$ is a one-hot row vector. The cumulative transition after $t$ steps is $\overline{\mathbf{Q}}_t = \mathbf{Q}_1 \mathbf{Q}_2 \cdots \mathbf{Q}_t$, giving:</p>
<p>$$q(\mathbf{x}_t | \mathbf{x}_0) = \text{Cat}(\mathbf{x}_t; \mathbf{p} = \mathbf{x}_0 \overline{\mathbf{Q}}_t)$$</p>
<p>The paper explores several transition matrix designs:</p>
<p><strong>Uniform diffusion:</strong> $[\mathbf{Q}_t]_{ij} = (1 - \beta_t) \mathbf{1}_{i=j} + \beta_t / K$. Transitions with equal probability to any state. Stationary distribution is uniform.</p>
<p><strong>Absorbing state:</strong> In absorbing-state diffusion, each non-mask token transitions to the mask state with probability $\beta_t$ per step, while tokens already at the mask state remain there:</p>
<p>$[\mathbf{Q}_t]_{ij} = (1-\beta_t)\mathbf{1}_{i=j\neq m} + \beta_t \mathbf{1}_{j=m} + \mathbf{1}_{i=j=m}$. Each token transitions to a designated absorbing state $m$ (e.g., [MASK] for text, gray pixel for images) with probability $\beta_t$. This establishes a direct connection to masked language models like BERT.</p>
<p><strong>Discretized Gaussian:</strong> Transition probabilities decay as a function of the distance $|i-j|$ between states, mimicking Gaussian diffusion on ordinal data like pixel values.</p>
<p><strong>Embedding-based nearest neighbor:</strong> For text, transitions are weighted by proximity in a pretrained word embedding space, so corruption preferentially swaps words with semantically similar ones.</p>
<p><strong>Training objective.</strong> The reverse process $p_\theta(\mathbf{x}_{t-1} | \mathbf{x}_t)$ is parameterized by predicting $\tilde{p}_\theta(\tilde{\mathbf{x}}_0 | \mathbf{x}_t)$ and computing the posterior:</p>
<p>$$p_\theta(\mathbf{x}_{t-1} | \mathbf{x}_t) \propto \sum_{\tilde{\mathbf{x}}_0} q(\mathbf{x}_{t-1} | \mathbf{x}_t, \tilde{\mathbf{x}}_0) , \tilde{p}_\theta(\tilde{\mathbf{x}}_0 | \mathbf{x}_t)$$</p>
<p>The loss combines the variational lower bound (VLB) with an auxiliary cross-entropy loss $L_\lambda$:</p>
<p>$$L = L_{\text{VLB}} + \lambda , L_{\text{CE}}$$</p>
<p>where $L_{\text{CE}}$ is a reweighted cross-entropy loss on the $\mathbf{x}_0$ prediction that stabilizes training and improves sample quality. The VLB decomposes into per-timestep KL divergences between the true and predicted reverse transitions.</p>
<h2 id="experiments-and-results">Experiments and Results</h2>
<p><strong>Image generation (CIFAR-10):</strong></p>
<table>
	<thead>
			<tr>
					<th>Model</th>
					<th>Loss</th>
					<th>IS</th>
					<th>FID</th>
					<th>NLL (bpd)</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>D3PM uniform</td>
					<td>$L_{\text{VLB}}$</td>
					<td>5.99</td>
					<td>51.27</td>
					<td>5.08</td>
			</tr>
			<tr>
					<td>D3PM absorbing</td>
					<td>$L_\lambda$ ($\lambda{=}0.001$)</td>
					<td>6.78</td>
					<td>30.97</td>
					<td>4.40</td>
			</tr>
			<tr>
					<td>D3PM Gauss</td>
					<td>$L_{\text{VLB}}$</td>
					<td>7.75</td>
					<td>15.30</td>
					<td>3.97</td>
			</tr>
			<tr>
					<td>D3PM Gauss</td>
					<td>$L_\lambda$ ($\lambda{=}0.001$)</td>
					<td>8.54</td>
					<td>8.34</td>
					<td>3.98</td>
			</tr>
			<tr>
					<td>D3PM Gauss + logistic</td>
					<td>$L_\lambda$ ($\lambda{=}0.001$)</td>
					<td>8.56</td>
					<td>7.34</td>
					<td>3.44</td>
			</tr>
			<tr>
					<td>DDPM $L_{\text{simple}}$ (continuous)</td>
					<td>&ndash;</td>
					<td>9.46</td>
					<td>3.17</td>
					<td>3.75</td>
			</tr>
	</tbody>
</table>
<p>The best discrete D3PM variant is D3PM Gauss + logistic, which achieves FID 7.34 and NLL 3.44 bpd using the combined $L_\lambda$ loss with a truncated logistic parameterization. The truncated logistic parameterization replaces the standard softmax output with a discretized logistic distribution over pixel values, assigning probability mass to each discrete bin based on a continuous logistic CDF. This provides a smoother output distribution that better captures the ordinal structure of pixel intensities. This variant exceeds the continuous DDPM in log-likelihood (3.44 vs. 3.75 bpd) while approaching its sample quality (FID 7.34 vs. 3.17).</p>
<p><strong>Text generation (text8, character-level, 1000 steps):</strong></p>
<table>
	<thead>
			<tr>
					<th>Model</th>
					<th>bpc</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>D3PM absorbing ($L_\lambda$)</td>
					<td>1.45</td>
			</tr>
			<tr>
					<td>D3PM NN ($L_{\text{VLB}}$)</td>
					<td>1.59</td>
			</tr>
			<tr>
					<td>D3PM uniform</td>
					<td>1.61</td>
			</tr>
			<tr>
					<td>Discrete Flow (Tran et al.)</td>
					<td>1.23</td>
			</tr>
	</tbody>
</table>
<p>Among the D3PM variants and baselines evaluated, D3PM absorbing achieves the best bpc on text8 apart from Discrete Flow (Tran et al., 2019). On LM1B (sentencepiece vocabulary of 8192 tokens), D3PM absorbing achieves a perplexity of 76.9 at 1000 steps, compared to 137.9 for D3PM uniform and 43.6 for a comparable autoregressive transformer, demonstrating that discrete diffusion scales to large vocabularies.</p>
<p><strong>Ablation findings:</strong></p>
<ul>
<li>The auxiliary cross-entropy loss $L_\lambda$ is critical: for D3PM Gauss, it improves FID from 15.30 ($L_{\text{VLB}}$) to 8.34 ($L_\lambda$, $\lambda{=}0.001$). Adding the truncated logistic parameterization further improves FID to 7.34.</li>
<li>Discretized Gaussian transitions outperform both uniform and absorbing-state transitions on CIFAR-10 across all metrics.</li>
<li>For text, the absorbing-state (mask) model outperforms uniform and nearest-neighbor models. Nearest-neighbor diffusion provides only marginal improvement over uniform, a surprising negative result.</li>
<li>The $\mathbf{x}_0$-parameterization ensures the learned reverse distribution has the correct sparsity pattern dictated by the transition matrix $\mathbf{Q}_t$.</li>
</ul>
<h2 id="findings-and-limitations">Findings and Limitations</h2>
<ul>
<li>The choice of transition matrix is an important design decision that encodes domain-specific inductive biases. Discretized Gaussian transitions work best for ordinal image data; absorbing-state transitions work best for text.</li>
<li>D3PMs formally unify diffusion models and masked language models: absorbing-state diffusion with a [MASK] token is equivalent to a reweighted BERT-style training objective.</li>
<li>The combined VLB + auxiliary loss ($L_\lambda$) achieves better density estimation (3.44 bpd) than continuous DDPMs (3.75 bpd) while producing competitive samples.</li>
<li>Sample quality (best FID 7.34 for D3PM Gauss + logistic) still lags behind continuous-space DDPMs (FID 3.17) on CIFAR-10, though the gap narrows with structured transitions and the auxiliary loss.</li>
<li>Scaling to very large numbers of categories $K$ requires special techniques (low-rank corruption or matrix exponentials) to manage the $O(K^2 T)$ memory cost of storing transition matrices.</li>
</ul>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="data">Data</h3>
<table>
	<thead>
			<tr>
					<th>Purpose</th>
					<th>Dataset</th>
					<th>Size</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Image generation</td>
					<td>CIFAR-10</td>
					<td>32x32, 256 categories</td>
					<td>Quantized to 256 ordinal values per channel</td>
			</tr>
			<tr>
					<td>Text generation</td>
					<td>text8</td>
					<td>Character-level</td>
					<td>27 character vocabulary, sequences of length 256</td>
			</tr>
			<tr>
					<td>Text generation</td>
					<td>LM1B</td>
					<td>Word-level</td>
					<td>Sentencepiece vocabulary of 8192 tokens, sequence length 128</td>
			</tr>
	</tbody>
</table>
<h3 id="algorithms">Algorithms</h3>
<ul>
<li><strong>Noise schedules</strong>: Linear schedule for D3PM Gauss, cosine schedule for D3PM uniform, and a novel mutual information schedule for absorbing and nearest-neighbor models</li>
<li><strong>Reverse parameterization</strong>: $\mathbf{x}_0$-parameterization with posterior computation via Bayes&rsquo; rule</li>
<li><strong>Loss</strong>: $L_{\text{VLB}} + \lambda L_{\text{CE}}$ with $\lambda = 0.001$ for images and $\lambda = 0.01$ for text absorbing models</li>
<li><strong>Scaling</strong>: Low-rank corruption (absorbing, uniform) scales as $O(r^2 T)$; matrix exponentials for nearest-neighbor transitions</li>
</ul>
<h3 id="models">Models</h3>
<ul>
<li><strong>Image models</strong>: Modified U-Net architecture from Ho et al. (2020) adapted for categorical output via softmax over $K$ classes</li>
<li><strong>Text models</strong>: 12-layer <a href="/notes/natural-language-processing/language-models/t5-text-to-text-transfer-transformer/">T5</a>-style transformer encoder with 70M parameters (12 heads, MLP dim 3072, QKV dim 768)</li>
<li><strong>Timesteps</strong>: $T = 1000$ for both images and text, though text models can be evaluated with fewer steps (e.g., 256 or 20)</li>
</ul>
<h3 id="evaluation">Evaluation</h3>
<table>
	<thead>
			<tr>
					<th>Metric</th>
					<th>Dataset</th>
					<th>Best D3PM</th>
					<th>Continuous DDPM</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>FID</td>
					<td>CIFAR-10</td>
					<td>7.34 (Gauss + logistic)</td>
					<td>3.17</td>
			</tr>
			<tr>
					<td>NLL (bpd)</td>
					<td>CIFAR-10</td>
					<td>3.44 (Gauss + logistic)</td>
					<td>3.75</td>
			</tr>
			<tr>
					<td>BPC</td>
					<td>text8 (char)</td>
					<td>1.45 (absorbing, $L_\lambda$)</td>
					<td>N/A</td>
			</tr>
			<tr>
					<td>Perplexity</td>
					<td>LM1B</td>
					<td>76.9 (absorbing)</td>
					<td>N/A</td>
			</tr>
	</tbody>
</table>
<h3 id="hardware">Hardware</h3>
<ul>
<li>All models trained for 1M steps with batch size 512 on TPUv2 or TPUv3</li>
<li>Text models: 12-layer transformer encoder (T5 architecture), 70M parameters</li>
<li>Image models: Modified U-Net architecture from Ho et al. (2020)</li>
</ul>
<h3 id="artifacts">Artifacts</h3>
<table>
	<thead>
			<tr>
					<th>Artifact</th>
					<th>Type</th>
					<th>License</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><a href="https://github.com/google-research/google-research/tree/master/d3pm">google-research/d3pm</a></td>
					<td>Code</td>
					<td>Apache-2.0</td>
					<td>Official JAX/Flax implementation for image and text experiments</td>
			</tr>
	</tbody>
</table>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Austin, J., Johnson, D. D., Ho, J., Tarlow, D., &amp; van den Berg, R. (2021). Structured Denoising Diffusion Models in Discrete State-Spaces. <em>NeurIPS 2021</em>. <a href="https://arxiv.org/abs/2107.03006">https://arxiv.org/abs/2107.03006</a></p>
<p><strong>Publication</strong>: NeurIPS 2021</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@inproceedings</span>{austin2021structured,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>     = <span style="color:#e6db74">{Structured Denoising Diffusion Models in Discrete State-Spaces}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>    = <span style="color:#e6db74">{Austin, Jacob and Johnson, Daniel D. and Ho, Jonathan and Tarlow, Daniel and van den Berg, Rianne}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">booktitle</span> = <span style="color:#e6db74">{Advances in Neural Information Processing Systems}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">volume</span>    = <span style="color:#e6db74">{34}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span>      = <span style="color:#e6db74">{2021}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><strong>Additional Resources</strong>:</p>
<ul>
<li><a href="/notes/machine-learning/generative-models/score-based-generative-modeling-sde/">Score-Based Generative Modeling with SDEs</a></li>
</ul>
]]></content:encoded></item><item><title>Consistency Models: Fast One-Step Diffusion Generation</title><link>https://hunterheidenreich.com/notes/machine-learning/generative-models/consistency-models/</link><pubDate>Sun, 15 Mar 2026 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/machine-learning/generative-models/consistency-models/</guid><description>Consistency models enable one-step generation by learning to map any point on a diffusion ODE trajectory to its origin, achieving FID 3.55 on CIFAR-10.</description><content:encoded><![CDATA[<h2 id="what-kind-of-paper-is-this">What kind of paper is this?</h2>
<p>This is a <strong>Method</strong> paper. It proposes consistency models, a new class of generative models designed for fast one-step (or few-step) generation. The models can be trained either by distilling pretrained diffusion models (consistency distillation) or as standalone generative models from scratch (consistency training). The paper provides theoretical analysis of both training modes and achieves FID 3.55 on CIFAR-10 for single-step non-adversarial generation (state of the art at the time of publication).</p>
<h2 id="the-slow-sampling-problem-in-diffusion">The Slow Sampling Problem in Diffusion</h2>
<p>Diffusion models produce high-quality samples but require iterating through many denoising steps (often tens to hundreds), making generation slow compared to GANs or VAEs. Previous approaches to speed up sampling include faster ODE/SDE solvers (DDIM, DPM-Solver) and progressive distillation. These either still require multiple steps or depend on a complex multi-stage distillation pipeline. The goal is a model that can generate high-quality samples in a single forward pass while optionally allowing more steps for better quality.</p>
<h2 id="core-innovation-the-self-consistency-property">Core Innovation: The Self-Consistency Property</h2>
<p>The key idea builds on the Probability Flow (PF) ODE from the score-based SDE framework. The PF ODE describes a deterministic trajectory that converts noise into data, governed by the learned score function. For the VE-SDE parameterization used by EDM (Karras et al., 2022), this takes the form:</p>
<p>$$\frac{d\mathbf{x}_t}{dt} = -t , s_\phi(\mathbf{x}_t, t)$$</p>
<p>where $s_\phi$ is a pretrained score model, a <strong>consistency function</strong> $f(\mathbf{x}_t, t)$ maps any point on an ODE trajectory to the trajectory&rsquo;s origin $\mathbf{x}_\epsilon$. The defining property is self-consistency:</p>
<p>$$f(\mathbf{x}_t, t) = f(\mathbf{x}_{t&rsquo;}, t&rsquo;) \quad \text{for all } t, t&rsquo; \in [\epsilon, T]$$</p>
<p>for any points $\mathbf{x}_t$ and $\mathbf{x}_{t&rsquo;}$ on the same PF ODE trajectory.</p>
<p><strong>Parameterization.</strong> The model enforces the boundary condition $f(\mathbf{x}_\epsilon, \epsilon) = \mathbf{x}_\epsilon$ using skip connections:</p>
<p>$$f_\theta(\mathbf{x}, t) = c_{\text{skip}}(t) , \mathbf{x} + c_{\text{out}}(t) , F_\theta(\mathbf{x}, t)$$</p>
<p>where $c_{\text{skip}}(\epsilon) = 1$ and $c_{\text{out}}(\epsilon) = 0$, ensuring the boundary condition is satisfied by construction.</p>
<p><strong>Consistency Distillation (CD).</strong> Given a pretrained diffusion model, CD trains a consistency model by enforcing self-consistency between adjacent timesteps:</p>
<p>$$\mathcal{L}_{\text{CD}}^N(\theta, \theta^-; \phi) = \mathbb{E}\left[\lambda(t_n) , d!\left(f_\theta(\mathbf{x}_{t_{n+1}}, t_{n+1}), , f_{\theta^-}(\hat{\mathbf{x}}_{t_n}^\phi, t_n)\right)\right]$$</p>
<p>where $\hat{\mathbf{x}}_{t_n}^\phi$ is obtained by running one step of the ODE solver using the pretrained score model, $\theta^-$ is an exponential moving average (EMA) of $\theta$, and $d(\cdot, \cdot)$ is a distance metric. The use of a target network $\theta^-$ (updated via EMA) parallels techniques from deep Q-learning and momentum contrastive learning.</p>
<p><strong>Consistency Training (CT).</strong> CT eliminates the need for a pretrained diffusion model. It replaces the ODE solver step with a score estimate derived from the denoising score matching identity:</p>
<p>$$\nabla_{\mathbf{x}_t} \log p_t(\mathbf{x}_t) = \mathbb{E}\left[\frac{\mathbf{x} - \mathbf{x}_t}{t^2} ,\middle|, \mathbf{x}_t\right]$$</p>
<p>Because this identity lets us estimate the score from noisy data alone (without a pretrained model), we can compute the ODE update directly from training samples. This allows training directly on data pairs $(\mathbf{x}, \mathbf{x} + t\mathbf{z})$ where $\mathbf{z} \sim \mathcal{N}(0, I)$.</p>
<p><strong>Theoretical guarantee.</strong> If CD achieves zero loss, the consistency model error is bounded by $O((\Delta t)^p)$ where $\Delta t$ is the maximum timestep gap and $p$ is the order of the ODE solver.</p>
<h2 id="experiments-and-benchmarks">Experiments and Benchmarks</h2>
<p><strong>Datasets:</strong> CIFAR-10 (32x32), ImageNet 64x64, LSUN Bedroom 256x256, LSUN Cat 256x256.</p>
<p><strong>Architecture:</strong> All models use the NCSN++/EDM architecture. CD distills from pretrained EDM models.</p>
<p><strong>Key results for consistency distillation (CD):</strong></p>
<table>
	<thead>
			<tr>
					<th>Dataset</th>
					<th>Steps</th>
					<th>FID</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>CIFAR-10</td>
					<td>1</td>
					<td>3.55</td>
			</tr>
			<tr>
					<td>CIFAR-10</td>
					<td>2</td>
					<td>2.93</td>
			</tr>
			<tr>
					<td>ImageNet 64x64</td>
					<td>1</td>
					<td>6.20</td>
			</tr>
			<tr>
					<td>ImageNet 64x64</td>
					<td>2</td>
					<td>4.70</td>
			</tr>
			<tr>
					<td>LSUN Bedroom 256</td>
					<td>1</td>
					<td>7.80</td>
			</tr>
			<tr>
					<td>LSUN Bedroom 256</td>
					<td>2</td>
					<td>5.22</td>
			</tr>
			<tr>
					<td>LSUN Cat 256</td>
					<td>1</td>
					<td>11.0</td>
			</tr>
			<tr>
					<td>LSUN Cat 256</td>
					<td>2</td>
					<td>8.84</td>
			</tr>
	</tbody>
</table>
<p>CD outperforms progressive distillation (PD) across all datasets and sampling steps, with the exception of single-step generation on Bedroom 256x256 where CD with $\ell_2$ slightly underperforms PD with $\ell_2$.</p>
<p><strong>Key results for consistency training (CT):</strong></p>
<table>
	<thead>
			<tr>
					<th>Dataset</th>
					<th>Steps</th>
					<th>FID</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>CIFAR-10</td>
					<td>1</td>
					<td>8.70</td>
			</tr>
			<tr>
					<td>CIFAR-10</td>
					<td>2</td>
					<td>5.83</td>
			</tr>
			<tr>
					<td>ImageNet 64x64</td>
					<td>1</td>
					<td>13.0</td>
			</tr>
			<tr>
					<td>ImageNet 64x64</td>
					<td>2</td>
					<td>11.1</td>
			</tr>
			<tr>
					<td>LSUN Bedroom 256</td>
					<td>1</td>
					<td>16.0</td>
			</tr>
			<tr>
					<td>LSUN Cat 256</td>
					<td>1</td>
					<td>20.7</td>
			</tr>
	</tbody>
</table>
<p>CT outperforms existing single-step non-adversarial models (VAEs, normalizing flows), e.g., improving over DC-VAE&rsquo;s FID of 17.90 on CIFAR-10. Samples from CT share structural similarity with EDM samples from the same initial noise, suggesting CT does not suffer from mode collapse.</p>
<p><strong>Zero-shot editing:</strong> Consistency models support colorization, super-resolution, inpainting, stroke-guided generation, interpolation, and denoising at test time without task-specific training, by modifying the multi-step sampling algorithm.</p>
<h2 id="findings-and-limitations">Findings and Limitations</h2>
<ul>
<li>Consistency distillation achieves state-of-the-art FID for one-step generation (3.55 on CIFAR-10, 6.20 on ImageNet 64x64).</li>
<li>Multi-step sampling provides a smooth quality-compute tradeoff: more steps yield better FID.</li>
<li>CT produces competitive results without any pretrained diffusion model, making consistency models a standalone generative model family.</li>
<li>The LPIPS distance metric $d(\cdot, \cdot)$ generally outperforms $\ell_1$ and $\ell_2$ for training consistency models.</li>
<li>At higher resolutions (LSUN 256x256), the gap between CD/CT and full EDM sampling widens.</li>
<li>CT currently underperforms CD, suggesting room for improvement in the standalone training paradigm.</li>
</ul>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="data">Data</h3>
<table>
	<thead>
			<tr>
					<th>Purpose</th>
					<th>Dataset</th>
					<th>Size</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Primary benchmark</td>
					<td>CIFAR-10</td>
					<td>32x32, 50K train</td>
					<td>FID on 50K samples</td>
			</tr>
			<tr>
					<td>Scaling benchmark</td>
					<td>ImageNet 64x64</td>
					<td>64x64, 1.28M</td>
					<td>Unconditional generation</td>
			</tr>
			<tr>
					<td>High-res benchmark</td>
					<td>LSUN Bedroom, Cat</td>
					<td>256x256</td>
					<td>Unconditional generation</td>
			</tr>
	</tbody>
</table>
<h3 id="algorithms">Algorithms</h3>
<ul>
<li><strong>ODE solver for CD</strong>: Euler and Heun (2nd order) solvers on the empirical PF ODE</li>
<li><strong>EMA for target network</strong>: Decay rate $\mu$ scheduled as a function of training step</li>
<li><strong>Schedule functions</strong>: $N$ (number of discretization steps) and $\mu$ (EMA rate) increase over training following specific schedules (see Appendix C of the paper)</li>
<li><strong>Distance metric</strong>: LPIPS performs best; $\ell_2$ and $\ell_1$ also evaluated</li>
</ul>
<h3 id="models">Models</h3>
<ul>
<li><strong>Architecture</strong>: NCSN++/EDM architecture from Karras et al. (2022)</li>
<li><strong>CD teacher</strong>: Pretrained EDM models</li>
<li><strong>Parameterization</strong>: Skip-connection formulation with $c_{\text{skip}}(t)$ and $c_{\text{out}}(t)$ from EDM</li>
</ul>
<h3 id="evaluation">Evaluation</h3>
<table>
	<thead>
			<tr>
					<th>Metric</th>
					<th>Dataset</th>
					<th>CD 1-step</th>
					<th>CT 1-step</th>
					<th>EDM (full)</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>FID</td>
					<td>CIFAR-10</td>
					<td>3.55</td>
					<td>8.70</td>
					<td>2.04</td>
			</tr>
			<tr>
					<td>FID</td>
					<td>ImageNet 64</td>
					<td>6.20</td>
					<td>13.0</td>
					<td>2.44</td>
			</tr>
			<tr>
					<td>FID</td>
					<td>LSUN Bedroom</td>
					<td>7.80</td>
					<td>16.0</td>
					<td>3.57</td>
			</tr>
			<tr>
					<td>FID</td>
					<td>LSUN Cat</td>
					<td>11.0</td>
					<td>20.7</td>
					<td>6.69</td>
			</tr>
	</tbody>
</table>
<h3 id="hardware">Hardware</h3>
<ul>
<li>Training details follow EDM conventions</li>
<li>CD and CT use the same batch sizes and learning rate schedules as EDM training</li>
</ul>
<h3 id="artifacts">Artifacts</h3>
<table>
	<thead>
			<tr>
					<th>Artifact</th>
					<th>Type</th>
					<th>License</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><a href="https://github.com/openai/consistency_models">openai/consistency_models</a></td>
					<td>Code</td>
					<td>MIT</td>
					<td>Official implementation with pretrained checkpoints</td>
			</tr>
	</tbody>
</table>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Song, Y., Dhariwal, P., Chen, M., &amp; Sutskever, I. (2023). Consistency Models. <em>ICML 2023</em>. <a href="https://arxiv.org/abs/2303.01469">https://arxiv.org/abs/2303.01469</a></p>
<p><strong>Publication</strong>: ICML 2023</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@inproceedings</span>{song2023consistency,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>     = <span style="color:#e6db74">{Consistency Models}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>    = <span style="color:#e6db74">{Song, Yang and Dhariwal, Prafulla and Chen, Mark and Sutskever, Ilya}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">booktitle</span> = <span style="color:#e6db74">{International Conference on Machine Learning}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">volume</span>    = <span style="color:#e6db74">{202}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span>      = <span style="color:#e6db74">{2023}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">url</span>       = <span style="color:#e6db74">{https://arxiv.org/abs/2303.01469}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><strong>Additional Resources</strong>:</p>
<ul>
<li><a href="https://github.com/openai/consistency_models">GitHub Repository</a></li>
<li><a href="/notes/machine-learning/generative-models/score-based-generative-modeling-sde/">Score-Based Generative Modeling with SDEs</a></li>
</ul>
]]></content:encoded></item><item><title>The Quarks of Attention: Building Blocks of Attention</title><link>https://hunterheidenreich.com/notes/machine-learning/model-architectures/quarks-of-attention/</link><pubDate>Sat, 14 Mar 2026 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/machine-learning/model-architectures/quarks-of-attention/</guid><description>Baldi and Vershynin's 2023 theoretical analysis decomposing attention into fundamental building blocks and proving capacity bounds for attentional circuits.</description><content:encoded><![CDATA[<h2 id="what-kind-of-paper-is-this">What kind of paper is this?</h2>
<p>This is a <strong>theory paper</strong> that takes a reductionist approach to attention mechanisms. It classifies all possible fundamental building blocks of attention (&ldquo;quarks&rdquo;) within a formal neural network framework, then proves capacity theorems for circuits built from these primitives using linear and polynomial threshold gates.</p>
<h2 id="why-decompose-attention-into-primitives">Why decompose attention into primitives?</h2>
<p>Descriptions of attention in deep learning often seem complex and obscure the underlying neural architecture. Despite the widespread use of attention in transformers and beyond, there has been little formal theory about the computational nature and capacity of attention mechanisms. Baldi and Vershynin address this by identifying the smallest building blocks and rigorously analyzing what they can compute.</p>
<h2 id="the-standard-model-and-its-extensions">The Standard Model and its extensions</h2>
<p>The paper defines the &ldquo;Standard Model&rdquo; (SM) as the class of all neural networks built from McCulloch-Pitt neurons: directed weighted graphs where neuron $i$ computes $O_i = f_i(S_i)$ with activation $S_i = \sum_j w_{ij} O_j$. The SM already has universal approximation properties, so extensions should be evaluated on efficiency (circuit size, depth, learning), not on what functions can be represented.</p>
<p>Three variable types exist in the SM: activations ($S$), outputs ($O$), and synaptic weights ($w$). Cross these with two mechanisms (addition, multiplication) and the constraint that attending signals originate from neuronal outputs, and you get six possible attention primitives.</p>
<h2 id="the-six-quarks-reduced-to-three">The six quarks, reduced to three</h2>
<table>
	<thead>
			<tr>
					<th></th>
					<th>$S$ (activation)</th>
					<th>$O$ (output)</th>
					<th>$w$ (synapse)</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><strong>Addition</strong></td>
					<td>Multiplexing (in SM)</td>
					<td>Additive output (in SM)</td>
					<td>Additive synaptic</td>
			</tr>
			<tr>
					<td><strong>Multiplication</strong></td>
					<td>Activation gating</td>
					<td><strong>Output gating</strong></td>
					<td><strong>Synaptic gating</strong></td>
			</tr>
	</tbody>
</table>
<p>The paper shows these reduce to three cases worth studying:</p>
<h3 id="multiplexing-additive-activation-attention">Multiplexing (additive activation attention)</h3>
<p>The attending signal $S_2$ is added to the normal activation $S_1$, producing $O_i = f_i(S_1 + S_2)$. With sigmoid or threshold activations, a large negative $S_2$ forces the output to zero regardless of $S_1$, suppressing unattended stimuli. This mechanism lives entirely within the SM and plays a central role in proving capacity lower bounds.</p>
<h3 id="output-gating">Output gating</h3>
<p>Neuron $j$ multiplies the output of neuron $i$, producing $O_i O_j$. This quadratic term is new to the SM. The gated signal $O_i O_j$ propagates to all downstream neurons of $i$. When $O_j \approx 0$, the attended neuron is silenced; when $O_j$ is large, it is enhanced.</p>
<h3 id="synaptic-gating">Synaptic gating</h3>
<p>Neuron $j$ multiplies a synaptic weight $w_{ki}$, creating a dynamic weight $w_{ki} O_j$. This produces the same local term $w_{ki} O_i O_j$ at neuron $k$ as output gating, but affects only the single downstream connection rather than all of neuron $i$&rsquo;s outputs. Synaptic gating is a fast weight mechanism: the attending network dynamically changes the program executed by the attended network.</p>
<h2 id="transformers-are-built-entirely-from-gating">Transformers are built entirely from gating</h2>
<p>The paper shows that transformer encoder modules decompose into:</p>
<ol>
<li><strong>Output gating</strong> ($mn^2$ operations): computing all $n^2$ pairwise dot products of $Q$ and $K$ vectors, each requiring $m$ element-wise multiplications</li>
<li><strong>Softmax</strong>: a standard SM extension</li>
<li><strong>Synaptic gating</strong> ($n^2$ operations): weighting $V$ vectors by the softmax outputs to form convex combinations</li>
</ol>
<p>The entire attention mechanism uses $O(mn^2)$ gating operations. The permutation invariance of transformers follows directly from the weight sharing across input positions.</p>
<h2 id="relationship-to-polynomial-neural-networks">Relationship to polynomial neural networks</h2>
<p>Gating is a special case of polynomial activation. A neuron with full quadratic activation over $n$ inputs has the form $S_i = \sum_{jk} w_{ijk} O_j O_k$, requiring $O(n^2)$ three-way synaptic weights for all possible pairs. Gating introduces only one new quadratic term per operation. The same gating concepts can also be applied to more complex units with polynomial activations of degree $d$, where one polynomial threshold unit gates the output or synapse of another.</p>
<h2 id="functional-properties-of-gating">Functional properties of gating</h2>
<p>Several examples illustrate what gating enables:</p>
<ul>
<li><strong>Shaping activation functions</strong>: When a unit with activation function $f$ is output-gated by a unit with activation function $g$ (both having the same inputs), the result is $f(S)g(S) = fg(S)$. This changes the effective activation function from $f$ to $fg$. For instance, a linear unit gated by a $(0,1)$ threshold function produces the ReLU activation.</li>
<li><strong>XOR without hidden layers</strong>: The XOR function cannot be computed by a single linear threshold gate. However, gating the OR function by the NAND function (both implementable by single linear threshold gates) produces XOR in a shallow network with no hidden layers.</li>
<li><strong>Universal approximation</strong>: Every continuous function on a compact set can be approximated to arbitrary precision by a shallow attention network of linear units gated by linear threshold gates (Theorem 4.3).</li>
</ul>
<h2 id="attention-as-sparse-quadratic-terms">Attention as sparse quadratic terms</h2>
<p>Both output and synaptic gating introduce quadratic terms of the form $w_{ki} O_i O_j$. A neuron with full quadratic activation over $n$ inputs would require $O(n^2)$ parameters. Gating introduces only one new quadratic term per operation. This is the key insight: attention mechanisms gain some of the expressiveness of quadratic activations while avoiding the combinatorial parameter explosion.</p>
<h2 id="capacity-results">Capacity results</h2>
<p>Using cardinal capacity (the base-2 logarithm of the number of distinct Boolean functions a class of circuits can implement), the paper proves bounds for attentional circuits with linear and polynomial threshold gates:</p>
<ul>
<li><strong>Single unit with output gating</strong>: a gated pair of linear threshold gates on $n$ inputs has capacity $2n^2(1 + o(1))$, compared to $n^2(1 + o(1))$ for a single gate (Theorem 6.1). This represents a doubling of capacity with a doubling of parameters (from $n$ to $2n$), a sign of efficiency.</li>
<li><strong>Multiplexing technique</strong>: additive activation attention enables a &ldquo;multiplexing&rdquo; proof strategy where one unit in a layer is selected as a function of the attending units while driving remaining units to saturation. This is the key tool for proving lower bounds.</li>
<li><strong>Attention layers</strong>: extending to layers of $m$ gated units with $n$ inputs, the capacity is $2mn^2(1 + o(1))$ for output gating (Theorem 7.1), confirming that gating approximately doubles the capacity relative to ungated layers.</li>
<li><strong>Depth reduction</strong>: gating operations available as physical primitives in a neural network can reduce the depth required for certain basic circuits.</li>
</ul>
<h2 id="limitations-and-future-work">Limitations and future work</h2>
<p>The authors note several open directions:</p>
<ul>
<li>The capacity estimates for some configurations (e.g., single-weight synaptic gating in Proposition 6.9) have gaps between the lower and upper bounds that remain to be tightened.</li>
<li>The analysis uses Boolean neurons (linear and polynomial threshold gates) as approximations. Extending results to other activation functions (sigmoid, ReLU) is left for future work.</li>
<li>The paper focuses on single layers and pairs of units. Capacity analysis for deeper attention architectures with multiple stacked layers is not addressed.</li>
<li>The theory treats attention on the time scale of individual inputs. The paper briefly notes that fast synaptic mechanisms operating on different time scales raise interesting architectural questions but does not develop this direction.</li>
</ul>
<h2 id="reproducibility">Reproducibility</h2>
<p>This is a purely theoretical paper with no associated code, datasets, or pretrained models. All results are mathematical theorems and proofs that can be verified from the paper itself. The paper is freely available on arXiv under a CC BY-NC-ND 4.0 license.</p>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Baldi, P. &amp; Vershynin, R. (2023). The quarks of attention: Structure and capacity of neural attention building blocks. <em>Artificial Intelligence</em>, 319, 103901.</p>
<p><strong>Publication</strong>: Artificial Intelligence 2023</p>
<p><strong>Additional Resources</strong>:</p>
<ul>
<li><a href="https://www.sciencedirect.com/science/article/pii/S0004370223000474">Journal (ScienceDirect)</a></li>
<li><a href="https://arxiv.org/abs/2202.08371">arXiv</a></li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@article</span>{baldi2023quarks,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>=<span style="color:#e6db74">{The quarks of attention: Structure and capacity of neural attention building blocks}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>=<span style="color:#e6db74">{Baldi, Pierre and Vershynin, Roman}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">journal</span>=<span style="color:#e6db74">{Artificial Intelligence}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">volume</span>=<span style="color:#e6db74">{319}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span>=<span style="color:#e6db74">{103901}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span>=<span style="color:#e6db74">{2023}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">doi</span>=<span style="color:#e6db74">{10.1016/j.artint.2023.103901}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Spherical CNNs: Rotation-Equivariant Networks on the Sphere</title><link>https://hunterheidenreich.com/notes/machine-learning/geometric-deep-learning/spherical-cnns/</link><pubDate>Sat, 14 Mar 2026 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/machine-learning/geometric-deep-learning/spherical-cnns/</guid><description>Cohen et al. introduce rotation-equivariant spherical CNNs that define cross-correlation on SO(3), computed via generalized FFT from harmonic analysis.</description><content:encoded><![CDATA[<h2 id="what-kind-of-paper-is-this">What kind of paper is this?</h2>
<p>This is a <strong>method paper</strong> that introduces the theory and implementation of convolutional neural networks on the sphere. The key contribution is defining spherical cross-correlation that is SO(3)-equivariant and can be computed efficiently using generalized Fast Fourier Transforms from non-commutative harmonic analysis.</p>
<h2 id="why-planar-convolutions-fail-on-spherical-data">Why planar convolutions fail on spherical data</h2>
<p>Many problems require analyzing spherical signals: omnidirectional vision for robots and autonomous vehicles, molecular regression, and global weather modeling. A naive approach of projecting spherical data to a plane introduces space-varying distortions that break translational weight sharing. Rotating a spherical signal cannot be emulated by translating its planar projection.</p>
<p>The fundamental issue is geometric: patterns on a plane move via translations, but patterns on a sphere move via 3D rotations. A spherical CNN should detect patterns regardless of how they are rotated over the sphere. The relevant symmetry group is SO(3) (the group of all 3D rotations).</p>
<h2 id="spherical-cross-correlation-and-the-so3-output-space">Spherical cross-correlation and the SO(3) output space</h2>
<p>The paper defines spherical cross-correlation by replacing filter translations with rotations. For spherical signals $f$ on $S^2$ (the unit sphere) and filter $\psi$, the correlation is:</p>
<p>$$\lbrack\psi \star f\rbrack(R) = \langle L_R \psi, f \rangle = \int_{S^2} \sum_{k=1}^{K} \psi_k(R^{-1}x) f_k(x) , dx$$</p>
<p>where $L_R$ is the rotation operator $\lbrack L_R f\rbrack(x) = f(R^{-1}x)$.</p>
<p>A crucial subtlety: whereas the space of moves for the plane (2D translations) is isomorphic to the plane itself, the space of moves for the sphere (3D rotations) is SO(3), a different three-dimensional manifold. The output of a spherical correlation is therefore a function on SO(3), not on $S^2$. This means subsequent layers must use SO(3) correlation:</p>
<p>$$\lbrack\psi \star f\rbrack(R) = \int_{\text{SO}(3)} \sum_{k=1}^{K} \psi_k(R^{-1}Q) f_k(Q) , dQ$$</p>
<h3 id="equivariance-proof">Equivariance proof</h3>
<p>Equivariance follows from the unitarity of $L_R$ in a single line:</p>
<p>$$\lbrack\psi \star \lbrack L_Q f\rbrack\rbrack(R) = \langle L_R \psi, L_Q f \rangle = \langle L_{Q^{-1}R} \psi, f \rangle = \lbrack\psi \star f\rbrack(Q^{-1}R) = \lbrack L_Q\lbrack\psi \star f\rbrack\rbrack(R)$$</p>
<p>This holds for both $S^2$ and SO(3) correlation.</p>
<h2 id="efficient-computation-via-generalized-fft">Efficient computation via generalized FFT</h2>
<p>A naive SO(3) correlation is $O(n^6)$. The paper addresses this using the generalized Fourier transform (GFT) from non-commutative harmonic analysis.</p>
<p>The GFT projects functions onto orthogonal basis functions: spherical harmonics $Y_m^l(x)$ for $S^2$, and Wigner D-functions $D_{mn}^l(R)$ for SO(3). Both satisfy generalized Fourier theorems:</p>
<ul>
<li><strong>SO(3) convolution theorem</strong>: $\widehat{\psi \star f} = \hat{f} \cdot \hat{\psi}^\dagger$ (matrix multiplication of block Fourier coefficients)</li>
<li><strong>$S^2$ convolution theorem</strong>: $\widehat{\psi \star f}^l = \hat{f}^l \cdot \hat{\psi}^{l\dagger}$ (outer product of $S^2$ Fourier coefficient vectors)</li>
</ul>
<p>The SO(3) FFT works in two steps: (1) standard 2D FFT over the $\alpha$ and $\gamma$ Euler angles, then (2) linear contraction of the $\beta$ axis with precomputed Wigner-d function samples, implemented as a custom GPU kernel.</p>
<h2 id="experiments">Experiments</h2>
<h3 id="equivariance-error">Equivariance error</h3>
<p>Since the theory applies to continuous functions but the implementation is discretized, the authors rigorously measure equivariance error. The approximation error grows with resolution and depth but stays manageable for practical bandwidths. With ReLU activations, the error is higher but stays flat across layers, indicating the error comes from feature map rotation (exact only for bandlimited functions) rather than accumulating through the network.</p>
<h3 id="spherical-mnist">Spherical MNIST</h3>
<p>MNIST digits projected onto the sphere, tested in non-rotated (NR) and rotated (R) settings with ~165K parameters per model:</p>
<table>
	<thead>
			<tr>
					<th>Train / Test</th>
					<th>Planar CNN</th>
					<th>Spherical CNN</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>NR / NR</td>
					<td>99%</td>
					<td>91%</td>
			</tr>
			<tr>
					<td>R / R</td>
					<td>45%</td>
					<td>91%</td>
			</tr>
			<tr>
					<td>NR / R</td>
					<td>9%</td>
					<td>85%</td>
			</tr>
	</tbody>
</table>
<p>The planar CNN collapses to chance when trained on non-rotated data and tested on rotated data. The spherical CNN maintains strong performance across all settings.</p>
<h3 id="3d-shape-recognition-shrec17">3D shape recognition (SHREC17)</h3>
<p>3D meshes projected onto an enclosing sphere via ray casting. For each point on the sphere, a ray is cast toward the origin, collecting three types of information from the intersection: ray length and cos/sin of the surface angle. The same three channels are computed for the convex hull, giving 6 channels total. The network (~1.4M parameters) placed 2nd on recall, mAP, and NDCG, and 3rd on precision and F1 in the SHREC17 competition, competing against methods with highly task-specialized architectures.</p>
<h3 id="molecular-atomization-energy-qm7">Molecular atomization energy (QM7)</h3>
<p>Molecules represented as spherical potential functions around each atom (generalizing the Coulomb matrix). A deep ResNet-style $S^2$CNN with DeepSets-style permutation-invariant aggregation over atoms achieved 8.47 RMSE, outperforming all kernel-based approaches and sorted Coulomb matrix methods.</p>
<h2 id="discussion-and-future-directions">Discussion and future directions</h2>
<p>The authors highlight several avenues for future work. For volumetric tasks like 3D model recognition, extending beyond SO(3) to the roto-translation group SE(3) could improve results. They also note that a Steerable CNN for the sphere would enable analysis of vector fields (e.g., global wind directions). Omnidirectional vision is mentioned as a compelling application as 360-degree sensors become more prevalent.</p>
<h2 id="reproducibility">Reproducibility</h2>
<p>The official PyTorch implementation is publicly available. The code does not support recent PyTorch versions due to changes in the FFT interface.</p>
<table>
	<thead>
			<tr>
					<th>Artifact</th>
					<th>Type</th>
					<th>License</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><a href="https://github.com/jonkhler/s2cnn">s2cnn</a></td>
					<td>Code</td>
					<td>MIT</td>
					<td>Official PyTorch implementation (deprecated for modern PyTorch)</td>
			</tr>
	</tbody>
</table>
<p>Hardware requirements from the paper: the SHREC17 model uses 8GB GPU memory at batch size 16 and takes 50 hours to train. The QM7 model uses 7GB at batch size 20 and takes 3 hours to train. Datasets used (Spherical MNIST, SHREC17, QM7) are all publicly available.</p>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Cohen, T. S., Geiger, M., Köhler, J., &amp; Welling, M. (2018). Spherical CNNs. <em>International Conference on Learning Representations</em>. <a href="https://arxiv.org/abs/1801.10130">https://arxiv.org/abs/1801.10130</a></p>
<p><strong>Publication</strong>: ICLR 2018</p>
<p><strong>Additional Resources</strong>:</p>
<ul>
<li><a href="https://openreview.net/forum?id=Hkbd5xZRb">OpenReview</a></li>
<li><a href="https://arxiv.org/abs/1801.10130">arXiv</a></li>
<li><a href="https://github.com/jonkhler/s2cnn">GitHub</a></li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@inproceedings</span>{cohen2018spherical,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>=<span style="color:#e6db74">{Spherical {CNNs}}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>=<span style="color:#e6db74">{Cohen, Taco S. and Geiger, Mario and K{\&#34;o}hler, Jonas and Welling, Max}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">booktitle</span>=<span style="color:#e6db74">{International Conference on Learning Representations}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span>=<span style="color:#e6db74">{2018}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>SE(3)-Transformers: Equivariant Attention for 3D Data</title><link>https://hunterheidenreich.com/notes/machine-learning/geometric-deep-learning/se3-transformers/</link><pubDate>Sat, 14 Mar 2026 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/machine-learning/geometric-deep-learning/se3-transformers/</guid><description>Fuchs et al. combine self-attention with SE(3)-equivariance for 3D point clouds using invariant attention weights and equivariant value messages.</description><content:encoded><![CDATA[<h2 id="what-kind-of-paper-is-this">What kind of paper is this?</h2>
<p>This is a <strong>method paper</strong> that introduces the SE(3)-Transformer, a self-attention mechanism for 3D point clouds and graphs that is equivariant under continuous 3D rotations and translations. It builds on tensor field networks (TFNs) by adding data-dependent attention weights, resolving a known expressiveness limitation of equivariant convolutions.</p>
<h2 id="why-equivariant-attention-for-point-clouds">Why equivariant attention for point clouds?</h2>
<p>Point cloud data appears in 3D object scans, molecular structures, and particle simulations. Two properties are essential: handling varying numbers of irregularly sampled points, and invariance to global changes in pose (rotations and translations).</p>
<p>Self-attention handles variable-size inputs naturally and has proven effective across many domains. Tensor field networks provide SE(3)-equivariant convolutions but suffer from a key limitation: their filter kernels are decomposed into learnable radial functions and fixed angular components (spherical harmonics). The angular dependence is completely constrained by the equivariance condition, leaving no learnable degrees of freedom in the angular direction. This has been identified in the literature as severely limiting performance.</p>
<p>The SE(3)-Transformer resolves this by introducing data-dependent attention weights that modulate the angular profile of the kernels while maintaining equivariance.</p>
<h2 id="architecture-invariant-attention-meets-equivariant-values">Architecture: invariant attention meets equivariant values</h2>
<p>The core layer combines three components:</p>
<p>$$\mathbf{f}_{\text{out},i}^{\ell} = \underbrace{\mathbf{W}_V^{\ell\ell} \mathbf{f}_{\text{in},i}^{\ell}}_{\text{self-interaction}} + \sum_{k \geq 0} \sum_{j \in \mathcal{N}_i \setminus i} \underbrace{\alpha_{ij}}_{\text{attention}} \underbrace{\mathbf{W}_V^{\ell k}(\mathbf{x}_j - \mathbf{x}_i) \mathbf{f}_{\text{in},j}^k}_{\text{value message}}$$</p>
<h3 id="invariant-attention-weights">Invariant attention weights</h3>
<p>The attention weights use dot-product attention between equivariant queries and keys:</p>
<p>$$\alpha_{ij} = \frac{\exp(\mathbf{q}_i^\top \mathbf{k}_{ij})}{\sum_{j&rsquo; \in \mathcal{N}_i \setminus i} \exp(\mathbf{q}_i^\top \mathbf{k}_{ij&rsquo;})}$$</p>
<p>Both $\mathbf{q}_i$ and $\mathbf{k}_{ij}$ are constructed using TFN-type linear embeddings, making them SE(3)-equivariant. Their inner product is invariant because SO(3) representations are orthogonal: $\mathbf{q}^\top \mathbf{S}_g^\top \mathbf{S}_g \mathbf{k} = \mathbf{q}^\top \mathbf{k}$.</p>
<h3 id="equivariant-value-messages">Equivariant value messages</h3>
<p>The value messages use the same TFN kernel structure as tensor field networks: weight kernels $\mathbf{W}_V^{\ell k}(\mathbf{x})$ decomposed into learnable radial functions and Clebsch-Gordan/spherical harmonic angular components. Features are typed by irreducible representation degree $\ell$ (the independent matrix blocks into which SO(3) group actions decompose): type-0 vectors are rotation-invariant scalars, type-1 vectors transform as 3D vectors, and so on.</p>
<h3 id="angular-modulation">Angular modulation</h3>
<p>The attention weights $\alpha_{ij}$ multiply the value messages, creating data-dependent kernels $\alpha_{ij} \mathbf{W}_V^{\ell k}(\mathbf{x})$. This effectively modulates the angular profile of the fixed spherical harmonic components, adding learnable angular degrees of freedom while preserving equivariance. The authors describe this as one of the first examples of a nonlinear equivariant layer.</p>
<h3 id="attentive-self-interaction">Attentive self-interaction</h3>
<p>The paper also introduces attentive self-interaction as an alternative to the standard linear self-interaction (analogous to 1x1 convolutions). Instead of fixed learned weights across all points, the weights are generated by an MLP operating on invariant inner products of the input features:</p>
<p>$$w_{i,c&rsquo;c}^{\ell\ell} = \text{MLP}\left(\bigoplus_{c,c&rsquo;} \mathbf{f}_{\text{in},i,c&rsquo;}^{\ell\top} \mathbf{f}_{\text{in},i,c}^{\ell}\right)$$</p>
<h2 id="experiments">Experiments</h2>
<h3 id="n-body-particle-simulation">N-body particle simulation</h3>
<p>Five charged particles carrying positive or negative charges, exerting repulsive or attractive forces on each other. The task is predicting positions and velocities 500 timesteps ahead. The SE(3)-Transformer achieves 0.0076 MSE on position (vs. 0.0139 for Set Transformer and 0.0151 for TFN), with equivariance error on the order of $10^{-7}$, confirming exact equivariance up to numerical precision.</p>
<h3 id="scanobjectnn-real-world-3d-object-classification">ScanObjectNN (real-world 3D object classification)</h3>
<p>2902 real-world scanned objects across 15 categories. This task is only SO(2)-invariant (gravity axis matters), so the authors provide the z-component as an additional scalar input. With only 128 input points, the SE(3)-Transformer+z achieves 85.0% accuracy, competitive with methods using 1024 points and task-specific architectures. The model learns to ignore the symmetry-breaking z-input when trained on rotation-augmented data.</p>
<h3 id="qm9-molecular-property-regression"><a href="/notes/chemistry/datasets/qm9/">QM9</a> molecular property regression</h3>
<p>134k molecules with up to 29 atoms, predicting 6 quantum chemical properties. The SE(3)-Transformer achieves competitive results against other equivariant models (TFN, Cormorant), with improvements over TFN on all six targets. Across all three experiments, the SE(3)-Transformer outperforms both a non-equivariant attention baseline (Set Transformer) and equivariant models without attention (TFN).</p>
<h3 id="practical-contributions">Practical contributions</h3>
<p>The paper includes a PyTorch spherical harmonics implementation that is 10x faster than Scipy on CPU and 100-1000x faster on GPU. For a ScanObjectNN model, this yields roughly 22x speedup of the forward pass compared to the lie-learn library, directly addressing a major bottleneck of TFN-based architectures.</p>
<h2 id="conclusions-and-limitations">Conclusions and limitations</h2>
<p>Adding attention to a roto-translation-equivariant model consistently led to higher accuracy and increased training stability across all three experiments. For large neighbourhoods, attention proved essential for model convergence. The equivariance constraints also improved performance compared to conventional (non-equivariant) attention in all experiments.</p>
<p>The authors note that the SE(3)-Transformer is inherently suited for classification and regression on molecular data and discuss applications in drug research, including early-stage suitability classification of molecules for inhibiting viral reproductive cycles.</p>
<h2 id="reproducibility">Reproducibility</h2>
<table>
	<thead>
			<tr>
					<th>Artifact</th>
					<th>Type</th>
					<th>License</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><a href="https://github.com/FabianFuchsML/se3-transformer-public">se3-transformer-public</a></td>
					<td>Code</td>
					<td>MIT</td>
					<td>Official PyTorch + DGL implementation</td>
			</tr>
	</tbody>
</table>
<p>The repository includes code for N-body simulations and QM9 experiments. Hyperparameters and architecture details are provided in the paper&rsquo;s appendix (4 equivariant layers, representation degrees, channels per degree, learning rates, batch sizes). Hardware requirements are not explicitly stated in the paper.</p>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Fuchs, F. B., Worrall, D. E., Fischer, V., &amp; Welling, M. (2020). SE(3)-Transformers: 3D Roto-Translation Equivariant Attention Networks. <em>Advances in Neural Information Processing Systems</em>, 33. <a href="https://arxiv.org/abs/2006.10503">https://arxiv.org/abs/2006.10503</a></p>
<p><strong>Publication</strong>: NeurIPS 2020</p>
<p><strong>Additional Resources</strong>:</p>
<ul>
<li><a href="https://arxiv.org/abs/2006.10503">arXiv</a></li>
<li><a href="https://github.com/FabianFuchsML/se3-transformer-public">GitHub</a></li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@inproceedings</span>{fuchs2020se3,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>=<span style="color:#e6db74">{{SE(3)-Transformers}: 3D Roto-Translation Equivariant Attention Networks}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>=<span style="color:#e6db74">{Fuchs, Fabian B. and Worrall, Daniel E. and Fischer, Volker and Welling, Max}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">booktitle</span>=<span style="color:#e6db74">{Advances in Neural Information Processing Systems}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">volume</span>=<span style="color:#e6db74">{33}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span>=<span style="color:#e6db74">{2020}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Relational Inductive Biases in Deep Learning (2018)</title><link>https://hunterheidenreich.com/notes/machine-learning/model-architectures/relational-inductive-biases-deep-learning-graph-networks/</link><pubDate>Sat, 14 Mar 2026 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/machine-learning/model-architectures/relational-inductive-biases-deep-learning-graph-networks/</guid><description>Battaglia et al.'s 2018 paper unifying graph neural network variants under a general graph network framework and analyzing relational inductive biases.</description><content:encoded><![CDATA[<h2 id="what-kind-of-paper-is-this">What kind of paper is this?</h2>
<p>This is a <strong>systematization paper</strong> that is part position paper, part review, and part unification. It argues that combinatorial generalization, the ability to construct new inferences from known building blocks, is a top priority for AI. It frames relational inductive biases as the key design principle connecting standard deep learning architectures, presents the graph network (GN) as a general framework subsuming prior graph neural network variants, and advocates for combining structured approaches with deep learning rather than choosing between them.</p>
<h2 id="the-case-for-relational-inductive-biases">The case for relational inductive biases</h2>
<p>Human intelligence relies on representing the world as compositions of entities, relations, and rules. We understand complex systems by decomposing them into parts and their interactions. Modern deep learning&rsquo;s &ldquo;end-to-end&rdquo; philosophy minimizes structural assumptions, relying on data and compute to learn representations from scratch. The paper argues this approach struggles with combinatorial generalization: generalizing beyond one&rsquo;s experiences by composing known elements in new ways.</p>
<p>The authors reject the false dichotomy between &ldquo;hand-engineering&rdquo; and &ldquo;end-to-end&rdquo; learning. Just as biology uses both nature and nurture, they advocate for architectures that bake in useful structural assumptions (inductive biases) while still learning flexibly from data.</p>
<h2 id="inductive-biases-across-standard-architectures">Inductive biases across standard architectures</h2>
<p>The paper provides a systematic analysis of how existing architectures encode relational structure:</p>
<p><strong>Fully connected networks (MLPs)</strong>: The weakest relational inductive bias. All input units can interact with all others, with no reuse of parameters. No assumptions about the structure of the input.</p>
<p><strong>Convolutional networks (CNNs)</strong>: Encode locality (nearby elements interact) and translation invariance (the same local function is applied everywhere). The entities are individual units or grid elements (e.g., pixels), the relations are defined by the grid neighborhood, and the rule (convolution kernel) is shared across all positions.</p>
<p><strong>Recurrent networks (RNNs)</strong>: Encode sequential structure and temporal invariance. The entities are time steps, each step relates to the previous one through a shared transition function. This imposes a Markovian bias (the future depends on the present state, not the full history directly).</p>
<p><strong>Sets and self-attention</strong>: Permutation invariant architectures impose no ordering on entities. Self-attention (as in Transformers) allows all pairwise interactions but with no structural prior on which interactions matter.</p>
<p>Each architecture can be understood as making specific commitments about what the entities are, what the relations between them are, and what rules govern their interactions.</p>
<h2 id="the-graph-network-framework">The graph network framework</h2>
<p>The paper defines a general &ldquo;graph network&rdquo; (GN) block that operates on graphs with attributes on nodes, edges, and the global graph level. A GN block performs three update steps and three aggregation steps:</p>
<ol>
<li><strong>Edge update</strong>: For each edge, compute updated edge attributes using the current edge attributes, the sender node attributes, the receiver node attributes, and the global attributes</li>
<li><strong>Node update</strong>: For each node, aggregate incoming updated edge attributes, then compute updated node attributes using the aggregated edges, current node attributes, and global attributes</li>
<li><strong>Global update</strong>: Aggregate all updated edge and node attributes, then compute updated global attributes</li>
</ol>
<p>Each update function is learned (typically a small neural network), and each aggregation function must be permutation invariant (typically sum, mean, or max).</p>
<p>This framework generalizes prior work:</p>
<ul>
<li><strong>Message Passing Neural Networks</strong> (Gilmer et al., 2017): edge and node updates with a readout function but no explicit global attribute in message passing</li>
<li><strong>Non-local Neural Networks</strong> (Wang et al., 2018): attention-weighted edge interactions</li>
<li><strong>Interaction Networks</strong> (Battaglia et al., 2016): physics-inspired message passing</li>
<li><strong>Relation Networks</strong> (Santoro et al., 2017): a simple neural network module for relational reasoning</li>
<li><strong>Discovering objects and their relations</strong> (Raposo et al., 2017): discovering objects and their relations from entangled scene representations</li>
<li><strong>Deep Sets</strong> (Zaheer et al., 2017): node-only aggregation without edge structure</li>
<li><strong>CommNet, Structure2Vec, GGNNs</strong>, and others</li>
</ul>
<p>The paper shows how each prior approach corresponds to a specific configuration of which GN components are used and how they are connected.</p>
<h2 id="design-principles-for-graph-networks">Design principles for graph networks</h2>
<p>The paper identifies several key design choices:</p>
<p><strong>Flexible representations</strong>: GN blocks can output graphs with different structure than their input (e.g., predicting edge existence), enabling tasks like link prediction, clustering, or property regression.</p>
<p><strong>Configurable within-block structure</strong>: The internal update and aggregation functions can be swapped freely. The framework separates what is computed (the relational structure) from how it is computed (the function approximators).</p>
<p><strong>Composable multi-block architectures</strong>: GN blocks can be stacked, sharing or not sharing weights across layers. They can be composed with other architectures (e.g., an encoder-GN-decoder pattern) or arranged in recurrent configurations.</p>
<p><strong>Combinatorial generalization</strong>: Because GN blocks share functions across edges and nodes, they can generalize to graphs of different sizes and topologies than those seen during training. A GN trained on small graphs can, in principle, be applied to larger ones.</p>
<h2 id="connections-to-broader-ai-themes">Connections to broader AI themes</h2>
<p>The paper frames graph networks as supporting:</p>
<ul>
<li><strong>Relational reasoning</strong>: Learning about entities and their interactions</li>
<li><strong>Combinatorial generalization</strong>: Applying learned rules to novel combinations</li>
<li><strong>Structured prediction</strong>: Producing complex, structured outputs including graphs and sequences</li>
<li><strong>Interpretable representations</strong>: Graph structure provides a natural vocabulary for understanding what the model has learned</li>
</ul>
<p>The authors also discuss connections to classical AI (logic, planning, causal reasoning) and argue that graph networks provide a bridge between the flexibility of deep learning and the compositionality of symbolic approaches.</p>
<h2 id="limitations-and-open-questions">Limitations and open questions</h2>
<p>The paper identifies several limitations of graph networks:</p>
<ul>
<li><strong>Graph isomorphism</strong>: Learned message-passing cannot be guaranteed to discriminate between certain non-isomorphic graphs. Kondor et al. (2018) suggested that covariance, rather than invariance to permutations, may be preferable.</li>
<li><strong>Expressivity limits of graphs</strong>: Notions like recursion, control flow, and conditional iteration are not straightforward to represent with graphs. Programs and more &ldquo;computer-like&rdquo; processing may offer greater representational and computational expressivity for these concepts.</li>
<li><strong>Where do graphs come from?</strong>: Converting raw sensory data (images, text) into graph-structured representations remains an open problem. Fully connected graphs between spatial or linguistic entities are a common workaround but may not reflect the true underlying structure.</li>
<li><strong>Adaptive graph structure</strong>: How to modify graph topology during computation (e.g., splitting a node when an object fractures, or adding/removing edges based on contact) is an active research direction.</li>
</ul>
<h2 id="reproducibility">Reproducibility</h2>
<p>The authors released an open-source software library for building graph networks in TensorFlow/Sonnet, including demos for shortest-path finding, sorting, and physical prediction tasks.</p>
<table>
	<thead>
			<tr>
					<th>Artifact</th>
					<th>Type</th>
					<th>License</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><a href="https://github.com/deepmind/graph_nets">Graph Nets library</a></td>
					<td>Code</td>
					<td>Apache 2.0</td>
					<td>Official TensorFlow/Sonnet implementation with demos</td>
			</tr>
	</tbody>
</table>
<p>This is a position/systematization paper rather than an empirical one, so reproducibility pertains to the accompanying library rather than experimental results. The library and demos are publicly available, making the framework highly accessible.</p>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Battaglia, P. W., Hamrick, J. B., Bapst, V., Sanchez-Gonzalez, A., Zambaldi, V., Malinowski, M., &hellip; &amp; Pascanu, R. (2018). Relational inductive biases, deep learning, and graph networks. <em>arXiv preprint arXiv:1806.01261</em>.</p>
<p><strong>Publication</strong>: arXiv 2018</p>
<p><strong>Additional Resources</strong>:</p>
<ul>
<li><a href="https://arxiv.org/abs/1806.01261">arXiv</a></li>
<li><a href="https://github.com/deepmind/graph_nets">Graph Nets library (GitHub)</a></li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@article</span>{battaglia2018relational,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>=<span style="color:#e6db74">{Relational inductive biases, deep learning, and graph networks}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>=<span style="color:#e6db74">{Battaglia, Peter W. and Hamrick, Jessica B. and Bapst, Victor and Sanchez-Gonzalez, Alvaro and Zambaldi, Vinicius and Malinowski, Mateusz and Tacchetti, Andrea and Raposo, David and Santoro, Adam and Faulkner, Ryan and others}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">journal</span>=<span style="color:#e6db74">{arXiv preprint arXiv:1806.01261}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span>=<span style="color:#e6db74">{2018}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Can Recurrent Neural Networks Warp Time? (ICLR 2018)</title><link>https://hunterheidenreich.com/notes/machine-learning/model-architectures/can-recurrent-neural-networks-warp-time/</link><pubDate>Sat, 14 Mar 2026 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/machine-learning/model-architectures/can-recurrent-neural-networks-warp-time/</guid><description>Tallec and Ollivier's ICLR 2018 paper deriving gating mechanisms in RNNs from time warping invariance and proposing chrono initialization for LSTMs.</description><content:encoded><![CDATA[<h2 id="what-kind-of-paper-is-this">What kind of paper is this?</h2>
<p>This is a <strong>theory paper</strong> that provides a principled derivation of gating mechanisms in recurrent neural networks from an axiom of invariance to time transformations. The theoretical insights also yield a practical contribution: the <strong>chrono initialization</strong> for LSTM gate biases.</p>
<h2 id="why-time-warping-invariance-matters-for-recurrent-models">Why time warping invariance matters for recurrent models</h2>
<p>Standard recurrent neural networks are highly sensitive to changes in the time scale of their input data. Inserting a fixed number of blank steps between elements of an input sequence can make an otherwise easy task impossible for a vanilla RNN to learn. This fragility arises because the class of functions representable by an ordinary RNN is not closed under time rescaling.</p>
<p>The vanishing gradient problem compounds this issue: learning long-term dependencies requires gradient signals to persist across many time steps, but stability of the dynamical system causes these signals to decay exponentially. Prior solutions include gating mechanisms (LSTMs, GRUs) introduced on engineering grounds, and orthogonal weight constraints that limit representational power and make forgetting difficult.</p>
<p>Tallec and Ollivier ask a clean theoretical question: what structural properties must a recurrent model have to be invariant to arbitrary time transformations in its input?</p>
<h2 id="deriving-gates-from-time-warping-invariance">Deriving gates from time warping invariance</h2>
<p>The core insight starts from the continuous-time formulation of a basic RNN:</p>
<p>$$\frac{\mathrm{d}h(t)}{\mathrm{d}t} = \tanh(W_x x(t) + W_h h(t) + b) - h(t)$$</p>
<p>Applying a time warping $t \gets c(t)$ (any increasing differentiable function) to the input data $x(c(t))$ transforms this equation into:</p>
<p>$$\frac{\mathrm{d}h(t)}{\mathrm{d}t} = \frac{\mathrm{d}c(t)}{\mathrm{d}t} \tanh(W_x x(t) + W_h h(t) + b) - \frac{\mathrm{d}c(t)}{\mathrm{d}t} h(t)$$</p>
<p>The derivative $\frac{\mathrm{d}c(t)}{\mathrm{d}t}$ of the time warping appears as a multiplicative factor. For the model class to represent this equation for any time warping, a learnable function $g(t)$ must replace the unknown derivative:</p>
<p>$$\frac{\mathrm{d}h(t)}{\mathrm{d}t} = g(t) \tanh(W_x x(t) + W_h h(t) + b) - g(t) h(t)$$</p>
<p>Discretizing with a Taylor expansion ($\delta t = 1$) yields:</p>
<p>$$h_{t+1} = g_t \tanh(W_x x_t + W_h h_t + b) + (1 - g_t) h_t$$</p>
<p>This is a gated recurrent network with input gate $g_t$ and forget gate $(1 - g_t)$, where $g_t$ is computed by a sigmoid function of the inputs. The value $1/g(t_0)$ represents the local forgetting time of the network at time $t_0$.</p>
<h3 id="the-special-case-of-linear-time-rescaling">The special case of linear time rescaling</h3>
<p>For the simpler case of a constant time rescaling $c(t) = \alpha t$, the same derivation produces a leaky RNN:</p>
<p>$$h_{t+1} = \alpha \tanh(W_x x_t + W_h h_t + b) + (1 - \alpha) h_t$$</p>
<p>Leaky RNNs are invariant to global time rescalings but fail with variable warpings. Full gating (where $g_t$ depends on the input) is required for invariance to general time warpings.</p>
<h3 id="per-unit-gates-and-the-connection-to-lstms">Per-unit gates and the connection to LSTMs</h3>
<p>Extending to per-unit gates $g_t^i$ allows different units to operate at different characteristic timescales:</p>
<p>$$h_{t+1}^i = g_t^i \tanh(W_x^i x_t + W_h^i h_t + b^i) + (1 - g_t^i) h_t^i$$</p>
<p>This closely resembles the LSTM cell update equation, where $(1 - g_t^i)$ corresponds to the forget gate $f_t$ and $g_t^i$ corresponds to the input gate $i_t$. The derivation naturally ties these two gates (they sum to 1), a constraint that has been used successfully in practice.</p>
<h2 id="chrono-initialization-for-gate-biases">Chrono initialization for gate biases</h2>
<p>The theoretical framework provides a principled initialization strategy. If the sequential data has temporal dependencies in a range $[T_{\text{min}}, T_{\text{max}}]$, then gate values $g$ should lie in $[1/T_{\text{max}}, 1/T_{\text{min}}]$. Since gate values center around $\sigma(b_g)$ when inputs are centered, the biases should be initialized as:</p>
<p>$$b_g \sim -\log(\mathcal{U}([T_{\text{min}}, T_{\text{max}}]) - 1)$$</p>
<p>For LSTMs specifically, the <strong>chrono initialization</strong> sets:</p>
<p>$$b_f \sim \log(\mathcal{U}([1, T_{\text{max}} - 1]))$$
$$b_i = -b_f$$</p>
<p>where $T_{\text{max}}$ is the expected range of long-term dependencies. This contrasts with the standard practice of setting forget gate biases to 1 or 2.</p>
<h2 id="experimental-validation">Experimental validation</h2>
<h3 id="time-warping-robustness">Time warping robustness</h3>
<p>On a character recall task with artificially warped sequences, three architectures are compared (64 units each):</p>
<ul>
<li><strong>Vanilla RNNs</strong> fail with even moderate warping coefficients</li>
<li><strong>Leaky RNNs</strong> perfectly solve uniform warpings but fail with variable warpings</li>
<li><strong>Gated RNNs</strong> achieve perfect performance under both uniform and variable warpings for all tested warping factors</li>
</ul>
<p>This directly validates the theory: leaky RNNs handle constant time rescalings, but only gated models handle general time warpings.</p>
<h3 id="synthetic-tasks-copy-and-adding">Synthetic tasks (copy and adding)</h3>
<p>Using 128-unit LSTMs:</p>
<ul>
<li><strong>Copy task</strong> ($T = 500, 2000$): Chrono initialization converges to the solution while standard initialization plateaus at the memoryless baseline</li>
<li><strong>Variable copy</strong> ($T = 500, 1000$): Chrono matches standard for smaller $T$ but outperforms for $T = 1000$</li>
<li><strong>Adding task</strong> ($T = 200, 750$): Chrono converges significantly faster, approximately 7x faster for $T = 750$</li>
</ul>
<h3 id="real-world-tasks">Real-world tasks</h3>
<ul>
<li><strong>Permuted MNIST</strong> (512-unit LSTM): Chrono achieves 96.3% vs. 95.4% for standard initialization</li>
<li><strong>Character-level text8</strong> (2000-unit LSTM): Slight improvement (1.37 vs. 1.38 bits-per-character)</li>
<li><strong>Word-level Penn Treebank</strong> (10-layer RHN): Comparable results to the baseline (65.4 test perplexity)</li>
</ul>
<p>Short-term dependency tasks show minimal differences, consistent with the theory that chrono initialization primarily helps when long-term dependencies dominate.</p>
<h2 id="limitations">Limitations</h2>
<p>The continuous-to-discrete time correspondence relies on a Taylor expansion with step size $\delta t = 1$. This approximation holds when the derivative of the time warping is not too large ($g_t \lesssim 1$). Discrete-time gated models are therefore invariant to time warpings that stretch time (such as interspersing data with blanks or introducing long-term dependencies), but they cannot handle warpings that compress events faster than the model&rsquo;s time step. Additionally, the chrono initialization requires specifying $T_{\text{max}}$, the expected range of long-term dependencies, which may not be known in advance.</p>
<h2 id="reproducibility">Reproducibility</h2>
<p><strong>Status: Partially Reproducible.</strong></p>
<p>The paper describes all hyperparameters, architectures, and training procedures in sufficient detail to reproduce the experiments. The synthetic tasks (copy, adding, time warping) follow standard setups from prior work with clearly specified parameters. The real-world experiments (permuted MNIST, text8, Penn Treebank) use established benchmarks with referenced codebases (the text8 setup reuses code from Cooijmans et al. 2016).</p>
<p>The chrono initialization itself requires minimal implementation effort: it only changes the bias initialization of gate units, with no modifications to the model architecture or training procedure.</p>
<p>No official code repository is provided by the authors. No pre-trained models or datasets beyond standard benchmarks are released.</p>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Tallec, C. &amp; Ollivier, Y. (2018). Can recurrent neural networks warp time? <em>International Conference on Learning Representations (ICLR 2018)</em>.</p>
<p><strong>Publication</strong>: ICLR 2018</p>
<p><strong>Additional Resources</strong>:</p>
<ul>
<li><a href="https://openreview.net/forum?id=SJcKhk-Ab">OpenReview</a></li>
<li><a href="https://arxiv.org/abs/1804.11188">arXiv</a></li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@inproceedings</span>{tallec2018can,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>=<span style="color:#e6db74">{Can recurrent neural networks warp time?}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>=<span style="color:#e6db74">{Tallec, Corentin and Ollivier, Yann}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">booktitle</span>=<span style="color:#e6db74">{International Conference on Learning Representations}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span>=<span style="color:#e6db74">{2018}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>ChemDFM-R: Chemical Reasoning LLM with Atomized Knowledge</title><link>https://hunterheidenreich.com/notes/chemistry/llm-applications/chemdfm-r/</link><pubDate>Fri, 26 Dec 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/chemistry/llm-applications/chemdfm-r/</guid><description>A 14B-parameter chemical reasoning LLM enhanced with atomized functional group knowledge and mix-sourced distillation strategy.</description><content:encoded><![CDATA[<h2 id="method-and-resource-contributions">Method and Resource Contributions</h2>
<p>This is primarily a <strong>Method</strong> paper with significant <strong>Resource</strong> contributions.</p>
<ul>
<li><strong>Methodological Basis</strong>: The paper introduces a training pipeline (&ldquo;mix-sourced distillation&rdquo;) and domain-specific reinforcement learning to improve reasoning capabilities in chemical LLMs. It validates the approach through ablation studies across training stages.</li>
<li><strong>Resource Contribution</strong>: The authors constructed <strong>ChemFG</strong>, a 101 billion-token corpus annotated with &ldquo;atomized&rdquo; knowledge regarding functional groups and reaction centers.</li>
</ul>
<h2 id="bridging-the-chemical-reasoning-gap">Bridging the Chemical Reasoning Gap</h2>
<p>Current chemical LLMs struggle to reason logically for two main reasons:</p>
<ol>
<li><strong>Shallow Domain Understanding</strong>: Models generally learn molecule-level properties directly, bypassing the intermediate &ldquo;atomized&rdquo; characteristics (e.g., <a href="https://en.wikipedia.org/wiki/Functional_group">functional groups</a>) that ultimately dictate chemical behavior.</li>
<li><strong>Specialized Reasoning Logic</strong>: Chemical logic differs fundamentally from math or code. Distilling reasoning from general teacher models like DeepSeek-R1 frequently fails because the teachers lack the domain intuition required to generate valid chemical rationales.</li>
</ol>
<h2 id="atomized-knowledge-and-mixed-source-distillation">Atomized Knowledge and Mixed-Source Distillation</h2>
<p>The authors introduce three structural innovations to solve the reasoning gap:</p>
<ol>
<li><strong>Atomized Knowledge Enhancement (ChemFG)</strong>: A toolkit was built leveraging SMARTS notations to identify functional group changes during reactions. A critique of this approach is that it relies heavily on 2D cheminformatics abstractions, potentially missing deeper 3D stereochemical interactions.</li>
<li><strong>Mix-Sourced Distillation</strong>: General models (DeepSeek-R1/o3-mini) are fed &ldquo;pseudo-reasoning&rdquo; prompts that include ground truth answers and functional group data. While this forces the teacher to generate high-quality rationales for the student to learn, it introduces a layer of hindsight bias into the generated reasoning chains. During inference, the student model lacks both the pre-calculated functional group metadata and the ground truth, forcing it to bridge an artificially steep generalization gap.</li>
<li><strong>Chemical Reinforcement Learning</strong>: The intermediate model undergoes domain-specific reinforcement learning. The RL details are described in the paper&rsquo;s Appendix D, with the authors citing the open-source DAPO (Decoupled Clip and Dynamic Sampling Policy Optimization) framework. The optimization relies on rule-based rewards (format adherence and canonicalized <a href="/notes/chemistry/molecular-representations/notations/smiles/">SMILES</a> accuracy) across a variety of chemical tasks.</li>
</ol>
<h2 id="benchmark-evaluation-and-ablation-studies">Benchmark Evaluation and Ablation Studies</h2>
<p>The model was evaluated on comprehensive chemical benchmarks: <strong>SciKnowEval</strong> (19 tasks) and <strong><a href="/notes/chemistry/llm-applications/chemeval-multilevel-chemical-evaluation/">ChemEval</a></strong> (36 tasks).</p>
<ul>
<li><strong>Baselines</strong>: Compared against similarly sized open models (Qwen2.5-14B-Instruct, Qwen3-14B), domain models (<a href="/notes/chemistry/llm-applications/chemllm-chemical-large-language-model/">ChemLLM</a>, MolInst), and frontier models (GPT-4o, DeepSeek-R1).</li>
<li><strong>Ablation</strong>: Evaluated across training stages (Base → ChemDFM-I → ChemDFM-R) to measure the specific impact of the instruction tuning versus the reasoning stages.</li>
<li><strong>Qualitative Analysis</strong>: The paper includes case studies demonstrating the model&rsquo;s step-by-step chemical reasoning and its potential for human-AI collaboration (Sections 4.2 and 4.3).</li>
</ul>
<h2 id="performance-outcomes-and-numerical-limitations">Performance Outcomes and Numerical Limitations</h2>
<ul>
<li><strong>Performance vs. Baselines</strong>: ChemDFM-R outperforms similarly sized open models and domain models on molecule-centric and reaction-centric tasks, and surpasses the much larger DeepSeek-R1 on ChemEval (0.78 vs. 0.58 overall). It shows competitive results relative to o4-mini, though o4-mini leads on SciKnowEval (0.74 vs. 0.70).</li>
<li><strong>Reasoning Interactivity</strong>: The model generates readable rationales that allow users to catch structural errors or identify reaction mechanisms accurately. Section 4.3 of the paper demonstrates human-AI collaboration scenarios.</li>
<li><strong>Quantitative Limitations</strong>: The model struggles with tasks involving numerical prediction and calculation (e.g., yield extraction, molecular property calculation). The paper notes that all molecule-centric and reaction-centric tasks where ChemDFM-R falls short of Qwen2.5-14B-Instruct involve numerical reasoning.</li>
</ul>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="data">Data</h3>
<p>The training data is constructed in three phases:</p>
<p><strong>1. Domain Pre-training (ChemFG)</strong>:</p>
<ul>
<li><strong>Size</strong>: 101 billion tokens</li>
<li><strong>Composition</strong>:
<ul>
<li>12M literature documents (79B tokens)</li>
<li>30M molecules from PubChem/PubChemQC</li>
<li>7M reactions from USPTO-FULL</li>
</ul>
</li>
<li><strong>Augmentation</strong>: SMILES augmentation (10x) using R-SMILES</li>
<li><strong>Atomized Features</strong>: Annotated with a custom &ldquo;Functional Group Identification Toolkit&rdquo; that identifies 241 functional group types and tracks changes in reaction centers. <em>Note: Data and toolkit are partially reproduced; while the toolkit (<a href="https://github.com/OpenDFM/ChemFG-Tool">ChemFG-Tool</a>) was open-sourced on GitHub, the 101 billion-token ChemFG dataset itself has not been publicly released.</em></li>
</ul>
<p><strong>2. Instruction Tuning</strong>:</p>
<ul>
<li><strong>Sources</strong>: Molecule-centric (<a href="https://en.wikipedia.org/wiki/PubChem">PubChem</a>, <a href="/notes/chemistry/molecular-design/property-prediction/moleculenet-benchmark-molecular-ml/">MoleculeNet</a>), Reaction-centric (USPTO), and Knowledge-centric (Exams, Literature QA) tasks</li>
<li><strong>Mixing</strong>: Mixed with general instruction data in a 1:2 ratio</li>
</ul>
<p><strong>3. Distillation Dataset</strong>:</p>
<ul>
<li><strong>Sources</strong>:
<ul>
<li>~70% ChemDFM-R instruction data</li>
<li>~22% constructed pseudo-reasoning (functional group descriptions)</li>
<li>~8% teacher rationales (from DeepSeek-R1/o3-mini)</li>
</ul>
</li>
<li><strong>Mixing</strong>: Mixed with general data (including AM-Deepseek-R1-Distill-1.4M) in a 1:2 ratio</li>
</ul>
<h3 id="algorithms">Algorithms</h3>
<p><strong>Functional Group Identification</strong>:</p>
<ul>
<li>Extends the <code>thermo</code> library&rsquo;s SMARTS list</li>
<li>For reactions, identifies &ldquo;reacting functional groups&rdquo; by finding reactants containing atoms involved in bond changes (reaction centers) that do not appear in the product</li>
</ul>
<p><strong>Mix-Sourced Distillation</strong>:</p>
<ul>
<li>Teacher models (DeepSeek-R1, o3-mini) are prompted with Question + Ground Truth + Functional Group Info to generate high-quality &ldquo;Thoughts&rdquo;</li>
<li>These rationales are distilled into the student model using a supervised fine-tuning loss across target tokens $y_t$:
$$ \mathcal{L}_{\text{SFT}} = - \sum_{t=1}^T \log P_\theta(y_t \mid x, y_{&lt;t}) $$</li>
</ul>
<p><strong>Reinforcement Learning</strong>:</p>
<ul>
<li><strong>Algorithm</strong>: The paper cites DAPO (Decoupled Clip and Dynamic Sampling Policy Optimization) as the RL framework; full details are in Appendix D of the paper. <em>Note: While the underlying DAPO framework is open-source, the specific chemistry-oriented RL pipeline and environment used for ChemDFM-R has not been publicly released.</em></li>
<li><strong>Hyperparameters</strong> (from paper appendix): Learning rate <code>5e-7</code>, rollout batch size <code>512</code>, training batch size <code>128</code></li>
<li><strong>Rewards</strong>: The reward system applies rule-based constraints focusing on physical form and chemical validity. The total reward $R(y, y^*)$ for a generated response $y$ given target $y^*$ combines a format adherence reward ($R_{\text{format}}$) and an accuracy reward ($R_{\text{acc}}$) evaluated on canonicalized SMILES:
$$ R(y, y^*) = R_{\text{format}}(y) + R_{\text{acc}}(\text{canonicalize}(y), \text{canonicalize}(y^*)) $$</li>
</ul>
<h3 id="models">Models</h3>
<ul>
<li><strong>Base Model</strong>: Qwen2.5-14B</li>
<li><strong>ChemDFM-I</strong>: Result of instruction tuning the domain-pretrained model for 2 epochs</li>
<li><strong>ChemDFM-R</strong>: Result of applying mix-sourced distillation (1 epoch) followed by RL on ChemDFM-I. <em>Note: Model weights are publicly available on <a href="https://huggingface.co/OpenDFM/ChemDFM-R-14B">Hugging Face</a>.</em></li>
</ul>
<h3 id="hardware">Hardware</h3>
<p>Hardware and training time details are described in the paper&rsquo;s appendices, which are not available in the extracted text. The details below are reported from the paper but could not be independently cross-verified against the main text:</p>
<ul>
<li><strong>Compute</strong>: NVIDIA A800 Tensor Core GPUs</li>
<li><strong>Training Time</strong>: 30,840 GPU hours total (Domain Pretraining: 24,728 hours; Instruction Tuning: 3,785 hours; Distillation: 2,059 hours; Reinforcement Learning: 268 hours)</li>
</ul>
<h3 id="evaluation">Evaluation</h3>
<p><strong>Benchmarks</strong>:</p>
<ul>
<li><strong>SciKnowEval</strong>: 19 tasks (text-centric, molecule-centric, reaction-centric)</li>
<li><strong>ChemEval</strong>: 36 tasks, categorized similarly</li>
</ul>
<p><strong>Key Metrics</strong>: Accuracy, F1 Score, BLEU score (with PRS normalization for ChemEval)</p>
<table>
	<thead>
			<tr>
					<th>Model</th>
					<th>SciKnowEval (all)</th>
					<th>ChemEval* (all)</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Qwen2.5-14B-Instruct</td>
					<td>0.61</td>
					<td>0.57</td>
					<td>General-domain baseline</td>
			</tr>
			<tr>
					<td>ChemDFM-I</td>
					<td>0.69</td>
					<td>0.72</td>
					<td>After domain pretraining + instruction tuning</td>
			</tr>
			<tr>
					<td>ChemDFM-R</td>
					<td><strong>0.70</strong></td>
					<td><strong>0.78</strong></td>
					<td>After distillation + RL</td>
			</tr>
			<tr>
					<td>DeepSeek-R1</td>
					<td>0.62</td>
					<td>0.58</td>
					<td>General-domain reasoning model</td>
			</tr>
			<tr>
					<td>o4-mini</td>
					<td><strong>0.74</strong></td>
					<td>0.69</td>
					<td>Frontier reasoning model</td>
			</tr>
	</tbody>
</table>
<h3 id="artifacts">Artifacts</h3>
<table>
	<thead>
			<tr>
					<th>Artifact</th>
					<th>Type</th>
					<th>License</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><a href="https://huggingface.co/OpenDFM/ChemDFM-R-14B">ChemDFM-R-14B</a></td>
					<td>Model</td>
					<td>AGPL-3.0</td>
					<td>Final reasoning model weights on Hugging Face</td>
			</tr>
			<tr>
					<td><a href="https://github.com/OpenDFM/ChemFG-Tool">ChemFG-Tool</a></td>
					<td>Code</td>
					<td>Apache-2.0</td>
					<td>Functional group identification toolkit (241 groups)</td>
			</tr>
	</tbody>
</table>
<p><strong>Missing components</strong>: The 101B-token ChemFG pretraining dataset is not publicly released. The chemistry-oriented RL pipeline and training code are not open-sourced. The instruction tuning and distillation datasets are not available.</p>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Zhao, Z., Chen, B., Wan, Z., Chen, L., Lin, X., Yu, S., Zhang, S., Ma, D., Zhu, Z., Zhang, D., Wang, H., Dai, Z., Wen, L., Chen, X., &amp; Yu, K. (2025). ChemDFM-R: A Chemical Reasoning LLM Enhanced with Atomized Chemical Knowledge. <em>arXiv preprint arXiv:2507.21990</em>. <a href="https://doi.org/10.48550/arXiv.2507.21990">https://doi.org/10.48550/arXiv.2507.21990</a></p>
<p><strong>Publication</strong>: arXiv 2025</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@misc</span>{zhao2025chemdfmr,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>=<span style="color:#e6db74">{ChemDFM-R: A Chemical Reasoning LLM Enhanced with Atomized Chemical Knowledge}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>=<span style="color:#e6db74">{Zihan Zhao and Bo Chen and Ziping Wan and Lu Chen and Xuanze Lin and Shiyang Yu and Situo Zhang and Da Ma and Zichen Zhu and Danyang Zhang and Huayang Wang and Zhongyang Dai and Liyang Wen and Xin Chen and Kai Yu}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span>=<span style="color:#e6db74">{2025}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">eprint</span>=<span style="color:#e6db74">{2507.21990}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">archivePrefix</span>=<span style="color:#e6db74">{arXiv}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">primaryClass</span>=<span style="color:#e6db74">{cs.CE}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">url</span>=<span style="color:#e6db74">{https://arxiv.org/abs/2507.21990}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Score-Based Generative Modeling with SDEs (Song 2021)</title><link>https://hunterheidenreich.com/notes/machine-learning/generative-models/score-based-generative-modeling-sde/</link><pubDate>Sun, 21 Dec 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/machine-learning/generative-models/score-based-generative-modeling-sde/</guid><description>Unified SDE framework for score-based generative models, introducing Predictor-Corrector samplers and setting CIFAR-10 records with FID 2.20 and 2.99 bits/dim.</description><content:encoded><![CDATA[<h2 id="what-kind-of-paper-is-this">What kind of paper is this?</h2>
<p>This is primarily a <strong>Method</strong> paper. It proposes a unified framework that generalizes previous discrete score-based models (SMLD and DDPM) into continuous-time Stochastic Differential Equations (SDEs). The paper introduces algorithms for sampling (Predictor-Corrector) and likelihood computation (Probability Flow ODE), validated by setting new records on CIFAR-10 (FID 2.20, IS 9.89 at the time of publication). It also contains elements of <strong>Systematization</strong> by showing how existing methods are special cases of this broader framework.</p>
<h2 id="what-is-the-motivation">What is the motivation?</h2>
<p>Prior successful generative models, specifically Score Matching with Langevin Dynamics (SMLD) and Denoising Diffusion Probabilistic Models (DDPM), operate by sequentially corrupting data with slowly increasing noise and learning to reverse the process. Both methods treat the noise scales as a finite set of discrete steps. The authors aim to generalize this to a continuum of noise scales by modeling the diffusion process as a Stochastic Differential Equation (SDE). This continuous formulation enables:</p>
<ul>
<li><strong>Flexible sampling:</strong> Use of general-purpose SDE solvers.</li>
<li><strong>Exact likelihood computation:</strong> Via connection to Neural ODEs.</li>
<li><strong>Controllable generation:</strong> Solving inverse problems (inpainting, colorization) without retraining.</li>
</ul>
<h2 id="what-is-the-novelty-here">What is the novelty here?</h2>
<p>The core novelty is the <strong>SDE framework</strong> for score-based generative modeling:</p>
<ul>
<li><strong>Continuous Generalization:</strong> Proving that SMLD and DDPM noise perturbations correspond to discretizations of Variance Exploding (VE) SDEs and Variance Preserving (VP) SDEs, respectively.</li>
<li><strong>Reverse-Time SDE:</strong> Leveraging Anderson&rsquo;s result (Anderson, 1982: a result on time-reversal of diffusion processes showing that the reverse is also a diffusion, with the forward drift reversed and a correction term involving the score of the marginal density) that the reverse of a diffusion process is also a diffusion process, governed by the score (gradient of log density).</li>
<li><strong>Predictor-Corrector (PC) Samplers:</strong> A hybrid sampling strategy where a numerical SDE solver (Predictor) estimates the next step, and a score-based MCMC approach (Corrector) corrects the marginal distribution.</li>
<li><strong>Probability Flow ODE:</strong> Deriving a deterministic ODE that shares the same marginal densities as the SDE, enabling near-exact likelihood computation (accuracy is limited by both numerical ODE solver discretization and variance of the unbiased Hutchinson trace estimator) and latent space manipulation.</li>
<li><strong>Sub-VP SDE:</strong> A new SDE class proposed to improve likelihoods by bounding variance tighter than the VP SDE.</li>
</ul>
<h2 id="what-experiments-were-performed">What experiments were performed?</h2>
<p>The authors validated the framework on standard image benchmarks:</p>
<ul>
<li><strong>Datasets:</strong> CIFAR-10 (32x32), CelebA (64x64), LSUN (Bedroom, Church), and CelebA-HQ (256x256 and 1024x1024).</li>
<li><strong>Ablation Studies:</strong> Comparing samplers (Ancestral vs. Reverse Diffusion vs. Probability Flow vs. PC) and SDE types (VE, VP, sub-VP).</li>
<li><strong>Architecture Search:</strong> Exploring improvements like FIR up/downsampling, rescaling skip connections, and increasing depth (leading to NCSN++ and DDPM++ architectures).</li>
<li><strong>Likelihood Evaluation:</strong> Computing Negative Log-Likelihood (NLL) in bits/dim using the Probability Flow ODE.</li>
<li><strong>Inverse Problems:</strong> Testing class-conditional generation, inpainting, and colorization using the conditional reverse-time SDE.</li>
</ul>
<h2 id="what-outcomesconclusions">What outcomes/conclusions?</h2>
<ul>
<li><strong>Record Performance:</strong> The <strong>NCSN++ cont. (deep, VE)</strong> model achieved an Inception Score of 9.89 and FID of 2.20 on CIFAR-10 (as of ICLR 2021).</li>
<li><strong>High-Fidelity Generation:</strong> First score-based model to generate 1024x1024 images (CelebA-HQ).</li>
<li><strong>Competitive Likelihoods:</strong> The <strong>DDPM++ cont. (deep, sub-VP)</strong> model achieved 2.99 bits/dim on uniformly dequantized CIFAR-10, a record at the time.</li>
<li><strong>Sampling Efficiency:</strong> PC samplers consistently outperformed predictor-only methods (like standard ancestral sampling) for the same computational cost.</li>
<li><strong>Controllable Generation:</strong> Successful application to inpainting and colorization using a single unconditional model.</li>
<li><strong>Limitations:</strong> Sampling remains slower than GANs on the same datasets. The breadth of available samplers introduces many hyperparameters (SDE type, predictor, corrector, signal-to-noise ratio, number of steps) that require tuning.</li>
</ul>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="data">Data</h3>
<ul>
<li><strong>CIFAR-10</strong>: Used for main benchmarking (FID, Inception Score, NLL).</li>
<li><strong>CelebA-HQ</strong>: Used for high-resolution experiments at 256x256 and 1024x1024.</li>
<li><strong>LSUN</strong>: Bedroom and Church Outdoor categories (256x256) used for sampler comparison and controllable generation (inpainting, colorization).</li>
<li><strong>Preprocessing</strong>: CIFAR-10 images are 32x32; CelebA pre-processed to 64x64 following Song &amp; Ermon (2020). Data is typically scaled to $[0, 1]$ or standardized depending on the specific SDE config.</li>
</ul>
<h3 id="algorithms">Algorithms</h3>
<p><strong>Forward SDEs</strong>:</p>
<p>Here $dw$ denotes a Wiener process increment (a small, independent Gaussian noise burst at each timestep).</p>
<ul>
<li><strong>VE SDE (Variance Exploding)</strong>: $dx = \sqrt{\frac{d[\sigma^2(t)]}{dt}} dw$. Corresponds to SMLD. Used with $\sigma_{\min}=0.01$ and $\sigma_{\max}$ chosen via heuristics.</li>
<li><strong>VP SDE (Variance Preserving)</strong>: $dx = -\frac{1}{2}\beta(t)x dt + \sqrt{\beta(t)} dw$. Corresponds to DDPM.</li>
<li><strong>Sub-VP SDE</strong>: $dx = -\frac{1}{2}\beta(t)x dt + \sqrt{\beta(t)(1 - e^{-2\int_0^t \beta(s)ds})} dw$. Bounded variance, good for likelihoods.</li>
</ul>
<p><strong>Reverse-Time SDE Solver (Predictor)</strong>:</p>
<ul>
<li>Discretized via <strong>Reverse Diffusion Sampling</strong>, which matches the forward discretization.</li>
<li><strong>Euler-Maruyama</strong> solver used for continuously-trained models.</li>
</ul>
<p><strong>Corrector Algorithm</strong>:</p>
<ul>
<li><strong>Langevin MCMC</strong>: Applies annealed Langevin dynamics: adds noise and takes a score-guided gradient step to correct the marginal distribution at each timestep.</li>
<li><strong>PC Sampling</strong>: Alternates between one step of the Predictor and one step of the Corrector.</li>
<li><strong>Signal-to-Noise Ratio ($r$)</strong>: A hyperparameter for the corrector step size. Tuned values: $r \approx 0.16$ for VE SDEs on CIFAR-10.</li>
</ul>
<h3 id="models">Models</h3>
<ul>
<li><strong>NCSN++</strong>: Optimized architecture for VE SDEs. Key features:
<ul>
<li>4 residual blocks per resolution.</li>
<li>BigGAN-type residual blocks.</li>
<li>Rescaling skip connections by $1/\sqrt{2}$.</li>
<li>FIR (Finite Impulse Response) up/downsampling.</li>
<li>&ldquo;Residual&rdquo; progressive architecture for input, no progressive growing for output.</li>
</ul>
</li>
<li><strong>DDPM++</strong>: Optimized architecture for VP/sub-VP SDEs. Similar to NCSN++ but without FIR upsampling and no progressive growing.</li>
<li><strong>Deep Variants</strong>: &ldquo;cont. (deep)&rdquo; models double the depth (from 4 to 8 blocks per resolution) for the best reported results.</li>
<li><strong>Conditioning</strong>: Time $t$ is conditioned via random Fourier feature embeddings (scale 16) for continuous models.</li>
</ul>
<h3 id="evaluation">Evaluation</h3>
<p><strong>Metrics</strong>:</p>
<ul>
<li><strong>FID (Fréchet Inception Distance)</strong>: Computed on 50k samples.</li>
<li><strong>Inception Score</strong>: Reported for CIFAR-10.</li>
<li><strong>NLL (Negative Log-Likelihood)</strong>: Reported in bits/dim on uniformly dequantized data using the Probability Flow ODE.</li>
</ul>
<p><strong>Denoising</strong>: A single denoising step using Tweedie&rsquo;s formula is applied at the end of sampling to remove residual noise, which significantly improves FID.</p>
<h3 id="hardware">Hardware</h3>
<p><strong>Training</strong>:</p>
<ul>
<li>Batch size: 128 for CIFAR-10, 64 for LSUN, 8 for high-res CelebA-HQ.</li>
<li>Iterations: Discrete-objective models trained for 1.3M iterations during architecture exploration. Continuous-objective models (cont.) trained for 0.95M iterations. High-res CelebA-HQ (1024x1024) trained for approximately 2.4M iterations.</li>
<li><strong>EMA</strong>: Exponential Moving Average rate of 0.999 used for VE models, 0.9999 for VP models.</li>
</ul>
<h3 id="artifacts">Artifacts</h3>
<table>
	<thead>
			<tr>
					<th>Artifact</th>
					<th>Type</th>
					<th>License</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><a href="https://github.com/yang-song/score_sde">yang-song/score_sde</a></td>
					<td>Code</td>
					<td>Apache-2.0</td>
					<td>Official JAX and PyTorch implementation with pretrained checkpoints</td>
			</tr>
	</tbody>
</table>
<p>All datasets used (CIFAR-10, CelebA-HQ, LSUN) are publicly available. Pretrained model checkpoints for CIFAR-10, CelebA-HQ, and FFHQ are provided in the repository. Specific hardware requirements (GPU type, training time) are not detailed in the paper.</p>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Song, Y., Sohl-Dickstein, J., Kingma, D. P., Kumar, A., Ermon, S., &amp; Poole, B. (2021). Score-Based Generative Modeling through Stochastic Differential Equations. <em>ICLR 2021</em>. <a href="https://arxiv.org/abs/2011.13456">https://arxiv.org/abs/2011.13456</a></p>
<p><strong>Publication</strong>: ICLR 2021</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@inproceedings</span>{song2021scorebased,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>     = <span style="color:#e6db74">{Score-Based Generative Modeling through Stochastic Differential Equations}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>    = <span style="color:#e6db74">{Song, Yang and Sohl-Dickstein, Jascha and Kingma, Diederik P and Kumar, Abhishek and Ermon, Stefano and Poole, Ben}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">booktitle</span> = <span style="color:#e6db74">{International Conference on Learning Representations}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span>      = <span style="color:#e6db74">{2021}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">url</span>       = <span style="color:#e6db74">{https://openreview.net/forum?id=PxTIG12RRHS}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><strong>Additional Resources</strong>:</p>
<ul>
<li><a href="https://github.com/yang-song/score_sde">GitHub Repository</a></li>
<li><a href="/notes/machine-learning/generative-models/score-matching-denoising-autoencoders/">Score Matching and Denoising Autoencoders</a></li>
</ul>
]]></content:encoded></item><item><title>Score Matching and Denoising Autoencoders: A Connection</title><link>https://hunterheidenreich.com/notes/machine-learning/generative-models/score-matching-denoising-autoencoders/</link><pubDate>Sun, 21 Dec 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/machine-learning/generative-models/score-matching-denoising-autoencoders/</guid><description>Theoretical paper proving the equivalence between training Denoising Autoencoders and performing Score Matching on a Parzen density estimator.</description><content:encoded><![CDATA[<h2 id="what-kind-of-paper-is-this">What kind of paper is this?</h2>
<p>This is a <strong>Theory Paper</strong>.</p>
<p>Its primary contribution is a formal mathematical derivation connecting two previously distinct techniques: Score Matching (SM) and Denoising Autoencoders (DAE). It provides the &ldquo;why&rdquo; behind the empirical success of DAEs by grounding them in the probabilistic framework of energy-based models. It relies on proofs and equivalence relations (e.g., $J_{ESMq_{\sigma}} \sim J_{DSMq_{\sigma}}$).</p>
<h2 id="what-is-the-motivation">What is the motivation?</h2>
<p>The paper bridges a gap between two successful but disconnected approaches in unsupervised learning:</p>
<ol>
<li><strong>Denoising Autoencoders (DAE):</strong> Empirically successful for pre-training deep networks. They previously lacked a clear probabilistic interpretation.</li>
<li><strong>Score Matching (SM):</strong> A theoretically sound method for estimating unnormalized density models that avoids the partition function problem but requires computing expensive second derivatives.</li>
</ol>
<p>By connecting them, the authors aim to define a proper probabilistic model for DAEs (allowing sampling/ranking) and find a simpler way to apply score matching that avoids second derivatives.</p>
<h2 id="what-is-the-novelty-here">What is the novelty here?</h2>
<p>The core novelty is the <strong>Denoising Score Matching (DSM)</strong> framework and the proof of its equivalence to DAEs. Key contributions include:</p>
<ul>
<li><strong>Equivalence Proof:</strong> Showing that training a DAE with Gaussian noise is equivalent to matching the score of a model against a non-parametric Parzen density estimator of the data.</li>
<li><strong>Denoising Score Matching ($J_{DSM}$):</strong> A new objective that learns a score function by trying to denoise corrupted samples. This avoids the explicit second derivatives required by standard Implicit Score Matching ($J_{ISM}$).</li>
<li><strong>Explicit Energy Function:</strong> Deriving the specific energy function $E(x;\theta)$ that corresponds to the standard sigmoid DAE architecture.</li>
<li><strong>Justification for Tied Weights:</strong> Providing a theoretical justification for tying encoder and decoder weights, which arises naturally from differentiating the energy function.</li>
</ul>
<h2 id="what-experiments-were-performed">What experiments were performed?</h2>
<p>The validation in this theoretical paper is purely mathematical and focuses on formal proofs:</p>
<ul>
<li><strong>Derivation of Equivalence:</strong> The paper formally proves the chain of equivalences:
$$J_{ISMq_{\sigma}} \sim J_{ESMq_{\sigma}} \sim J_{DSMq_{\sigma}} \sim J_{DAE\sigma}$$
where $q_{\sigma}$ is the Parzen density estimate.</li>
<li><strong>Appendix Proof:</strong> A detailed proof is provided to show that Explicit Score Matching ($J_{ESM}$) on the Parzen density is equivalent to the proposed Denoising Score Matching ($J_{DSM}$) objective.</li>
</ul>
<h2 id="what-outcomesconclusions">What outcomes/conclusions?</h2>
<ul>
<li><strong>Theoretical Unification:</strong> DAE training is formally equivalent to Score Matching on a smoothed data distribution ($q_{\sigma}$).</li>
<li><strong>New Training Objective:</strong> The $J_{DSM}$ objective offers a computationally efficient way to perform score matching (no Hessian required) by using a denoising objective.</li>
<li><strong>Probabilistic Interpretation:</strong> DAEs can now be understood as Energy-Based Models (EBMs), allowing for operations like sampling (via Hybrid Monte Carlo) and likelihood ranking, which were previously ill-defined for standard autoencoders.</li>
<li><strong>Regularization Insight:</strong> The smoothing kernel width $\sigma$ in the Parzen estimator corresponds to the noise level in the DAE. This suggests that DAEs are learning a regularized version of the score, which may explain their robustness.</li>
<li><strong>Connection to Regularized Score Matching:</strong> The paper notes that Kingma and LeCun (2010) independently proposed a regularized score matching criterion $J_{ISMreg}$ derived by approximating $J_{ISMq_{\sigma}}$. The four $q_{\sigma}$-based objectives in this work (including the DAE objective) can be seen as approximation-free forms of regularized score matching, with the additional advantage that $J_{DSMq_{\sigma}}$ does not require second derivatives.</li>
</ul>
<hr>
<h2 id="key-concepts-explained">Key Concepts Explained</h2>
<h3 id="1-score-and-score-matching">1. &ldquo;Score&rdquo; and &ldquo;Score Matching&rdquo;</h3>
<p><strong>What does &ldquo;score&rdquo; actually mean?</strong></p>
<p>In this paper (and probabilistic modeling generally), the <strong>score</strong> is the gradient of the log-density with respect to the <em>data vector</em> $x$.</p>
<ul>
<li><strong>Definition:</strong> $\psi(x) = \nabla_x \log p(x)$.</li>
<li><strong>Intuition:</strong> It is a vector field pointing in the direction of highest probability increase. Crucially, calculating the score avoids the intractable partition function $Z$, because $\nabla_x \log p(x) = \nabla_x \log \tilde{p}(x) - \nabla_x \log Z = \nabla_x \log \tilde{p}(x)$. The constant $Z$ vanishes upon differentiation.</li>
</ul>
<p><strong>What is Score Matching?</strong></p>
<p>Score Matching is a training objective for unnormalized models. It minimizes the squared Euclidean distance between the model&rsquo;s score $\psi(x;\theta)$ and the data&rsquo;s true score $\nabla_x \log q(x)$.</p>
<h3 id="2-the-parzen-density-estimator">2. The Parzen Density Estimator</h3>
<p><strong>What is it?</strong></p>
<p>It is a non-parametric method for estimating a probability density function from finite data. It places a smooth kernel (here, a Gaussian) centered at every data point in the training set $D_n$.</p>
<ul>
<li><strong>Formula:</strong> $q_{\sigma}(\tilde{x}) = \frac{1}{n} \sum_{t=1}^n \mathcal{N}(\tilde{x}; x^{(t)}, \sigma^2 I)$.</li>
</ul>
<p><strong>Why smooth the data?</strong></p>
<ol>
<li>
<p><strong>To define the score:</strong> The empirical data distribution is a set of Dirac deltas (spikes). The gradient (score) of a Dirac delta is undefined. Smoothing creates a differentiable surface, allowing a valid target score $\nabla_{\tilde{x}} \log q_{\sigma}(\tilde{x})$ to be computed.</p>
</li>
<li>
<p><strong>To model corruption:</strong> The Parzen estimator with Gaussian kernels mathematically models the process of taking a clean data point $x$ and adding Gaussian noise - the exact procedure used in Denoising Autoencoders.</p>
</li>
</ol>
<h3 id="3-why-avoiding-second-derivatives-matters">3. Why avoiding second derivatives matters</h3>
<p>Standard <strong>Implicit Score Matching (ISM)</strong> eliminates the need for the unknown data score, but introduces a new cost: it requires computing the trace of the Hessian (the sum of second partial derivatives) of the log-density.</p>
<ul>
<li><strong>The Cost:</strong> For high-dimensional data (like images) and deep networks, computing second derivatives of the log-density is computationally expensive.</li>
<li>This paper shows that <strong>Denoising Score Matching (DSM)</strong> allows you to bypass Hessian computation entirely. By using the Parzen target, the objective simplifies to matching a first-order vector, making it scalable to deep neural networks.</li>
</ul>
<h3 id="4-the-equivalence-chain---why-each-step">4. The equivalence chain - why each step?</h3>
<p>The chain $J_{ISMq_{\sigma}} \sim J_{ESMq_{\sigma}} \sim J_{DSMq_{\sigma}} \sim J_{DAE\sigma}$ connects the concepts.</p>
<ul>
<li>
<p><strong>$J_{ISMq_{\sigma}} \sim J_{ESMq_{\sigma}}$ (Implicit $\to$ Explicit):</strong>
<strong>Why:</strong> Integration by parts. This is Hyvärinen&rsquo;s original proof (2005): integration by parts moves the derivative from $\psi$ onto the data density $q$, producing a term involving $q$&rsquo;s gradient (the score). The boundary term vanishes because $q_{\sigma}$ decays to zero at infinity (Hyvärinen&rsquo;s 2005 regularity condition for Implicit Score Matching). The result allows replacing the unknown data score with a computable term involving only the model&rsquo;s score and its Jacobian.</p>
</li>
<li>
<p><strong>$J_{ESMq_{\sigma}} \sim J_{DSMq_{\sigma}}$ (Explicit $\to$ Denoising):</strong>
<strong>Why:</strong> The explicit score of the Parzen density is known. When $x$ is perturbed to $\tilde{x}$ by Gaussian noise $\epsilon \sim \mathcal{N}(0, \sigma^2 I)$, the gradient of the log-density pointing back to the mean is exactly $\frac{1}{\sigma^2}(x - \tilde{x})$. Minimizing the error against the true score becomes minimizing the error against this restoration vector.</p>
</li>
<li>
<p><strong>$J_{DSMq_{\sigma}} \sim J_{DAE\sigma}$ (Denoising $\to$ Autoencoder):</strong>
<strong>Why:</strong> Algebraic substitution. If you define the model&rsquo;s score $\psi(\tilde{x};\theta)$ to be proportional to the reconstruction error ($\propto x^r - \tilde{x}$), the score matching loss $J_{DSM}$ becomes proportional to the standard autoencoder squared loss $|x^r - x|^2$.</p>
</li>
</ul>
<h3 id="5-energy-based-models-ebms-connection">5. Energy-Based Models (EBMs) connection</h3>
<p><strong>What is an EBM?</strong></p>
<p>An EBM defines a probability distribution via an energy function $E(x;\theta)$, where $p(x;\theta) \propto e^{-E(x;\theta)}$.</p>
<p><strong>Why standard autoencoders lack probabilistic interpretation:</strong></p>
<p>A standard autoencoder acts as a deterministic map $x \to x^r$, providing a reconstruction error. It lacks a normalization constant or a defined density function to support sampling or probability queries.</p>
<p><strong>What does this enable?</strong></p>
<p>By proving the equivalence, the DAE is formally defined as an EBM. This enables:</p>
<ol>
<li><strong>Sampling:</strong> Using MCMC methods (like Hybrid Monte Carlo) to generate new data from the DAE.</li>
<li><strong>Ranking:</strong> Calculating the energy of inputs to determine which are more &ldquo;likely&rdquo; or &ldquo;normal&rdquo; (useful for anomaly detection).</li>
</ol>
<h3 id="6-the-specific-energy-function-form">6. The specific energy function form</h3>
<p>The function is:</p>
<p>$$E(x; W, b, c) = - \frac{1}{\sigma^2} \left( \langle c, x \rangle - \frac{1}{2}|x|^2 + \sum_{j=1}^{d_h} \text{softplus}(\langle W_j, x \rangle + b_j) \right)$$</p>
<p><strong>Why does it have that specific form?</strong></p>
<p>It was derived via integration to ensure its derivative matches the DAE architecture. The authors worked backward from the DAE&rsquo;s reconstruction function (sigmoid + linear) to find the scalar field that generates it.</p>
<p><strong>Where does the quadratic term come from?</strong></p>
<p>The score (negative energy gradient) needs to look like $\psi(x) \propto c - x + W^T\text{sigmoid}(Wx + b)$.</p>
<ul>
<li>The term $-x$ in the score arises because $\nabla_x(-\frac{1}{2}|x|^2) = -x$. Including $-\frac{1}{2}|x|^2$ inside the energy&rsquo;s numerator produces this linear term after differentiation.</li>
</ul>
<p><strong>How does differentiating it recover the DAE reconstruction?</strong></p>
<ul>
<li>$\nabla_x \sum_j \text{softplus}(\langle W_j, x \rangle + b_j) = W^T \sigma(Wx + b)$ (The encoder part).</li>
<li>$\nabla_x \langle c, x \rangle = c$ (The bias).</li>
<li>$\nabla_x (-\frac{1}{2}|x|^2) = -x$ (The input subtraction).</li>
<li>Result: $-\nabla_x E \propto c + W^T h - x = x^r - x$.</li>
</ul>
<h3 id="7-tied-weights-justification">7. &ldquo;Tied weights&rdquo; justification</h3>
<p><strong>What does it mean for weights to be &ldquo;tied&rdquo;?</strong></p>
<p>The decoder matrix is the transpose of the encoder matrix ($W^T$).</p>
<p><strong>Why is this theoretically justified?</strong></p>
<p>Because the reconstruction function is interpreted as the <strong>gradient</strong> of an energy function. A vector field can only be the gradient of a scalar field if its Jacobian is symmetric.</p>
<ul>
<li>In the DAE energy derivative, the encoder contributes $W^T \sigma(Wx + b)$. If the decoder used a separate matrix $U$, the resulting vector field would not be a valid gradient of any scalar energy function (unless $U = W^T$).</li>
<li>Therefore, for a DAE to correspond to a valid probabilistic Energy-Based Model, the weights <em>must</em> be tied.</li>
</ul>
<p><strong>The necessity of tied weights:</strong></p>
<p>Within this parametrization, tied weights are a mathematical necessity: a separate decoder matrix $U \neq W^T$ would make the reconstruction function an invalid gradient of any scalar energy, breaking the EBM correspondence.</p>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<p>Since this is a theoretical paper, the &ldquo;reproducibility&rdquo; lies in the mathematical formulations derived.</p>
<h3 id="data">Data</h3>
<ul>
<li><strong>Input Data ($D_n$):</strong> The theory assumes a set of training examples $D_n = {x^{(1)}, &hellip;, x^{(n)}}$ drawn from an unknown true pdf $q(x)$.</li>
<li><strong>Parzen Density Estimate ($q_{\sigma}$):</strong> The theoretical targets are derived from a kernel-smoothed empirical distribution:
$$q_{\sigma}(\tilde{x}) = \frac{1}{n} \sum_{t=1}^n q_{\sigma}(\tilde{x}|x^{(t)})$$
where the kernel is an isotropic Gaussian of variance $\sigma^2$.</li>
</ul>
<h3 id="algorithms">Algorithms</h3>
<p><strong>1. Denoising Score Matching (DSM) Objective</strong></p>
<p>The paper proposes this objective as a tractable alternative to standard score matching. It minimizes the distance between the model score and the gradient of the log-noise density:</p>
<p>$$J_{DSMq_{\sigma}}(\theta) = \mathbb{E}_{q_{\sigma}(x,\tilde{x})} \left[ \frac{1}{2} \left| \psi(\tilde{x};\theta) - \frac{\partial \log q_{\sigma}(\tilde{x}|x)}{\partial \tilde{x}} \right|^2 \right]$$</p>
<p>For Gaussian noise, the target score is simply $\frac{1}{\sigma^2}(x - \tilde{x})$.</p>
<p><strong>2. Equivalence Chain</strong></p>
<p>The central result connects four objectives:</p>
<p>$$J_{ISMq_{\sigma}} \sim J_{ESMq_{\sigma}} \sim J_{DSMq_{\sigma}} \sim J_{DAE\sigma}$$</p>
<p>This implies optimizing the DAE reconstruction error is minimizing a score matching objective.</p>
<h3 id="models">Models</h3>
<p><strong>1. The Denoising Autoencoder (DAE)</strong></p>
<ul>
<li><strong>Corruption:</strong> Additive isotropic Gaussian noise $\tilde{x} = x + \epsilon, \epsilon \sim \mathcal{N}(0, \sigma^2 I)$.</li>
<li><strong>Encoder:</strong> $h = \text{sigmoid}(W\tilde{x} + b)$.</li>
<li><strong>Decoder:</strong> $x^r = W^T h + c$ (Tied weights $W$).</li>
<li><strong>Loss:</strong> Squared reconstruction error $|x^r - x|^2$. (The equivalence with DSM introduces a $\frac{1}{2\sigma^4}$ scaling factor.)</li>
</ul>
<p><strong>2. The Corresponding Energy Function</strong></p>
<p>To make the DAE equivalent to Score Matching, the underlying Energy-Based Model $p(x;\theta) \propto e^{-E(x;\theta)}$ must have the following energy function:</p>
<p>$$E(x; W, b, c) = - \frac{1}{\sigma^2} \left( \langle c, x \rangle - \frac{1}{2}|x|^2 + \sum_{j=1}^{d_h} \text{softplus}(\langle W_j, x \rangle + b_j) \right)$$</p>
<p>Note the scaling by $1/\sigma^2$ and the quadratic term $|x|^2$.</p>
<h3 id="evaluation">Evaluation</h3>
<ul>
<li><strong>Metric:</strong> Theoretical Equivalence ($\sim$).</li>
<li><strong>Condition:</strong> The equivalence holds provided $\sigma &gt; 0$ and the density $q_{\sigma}$ is differentiable and vanishes at infinity (Hyvärinen&rsquo;s 2005 regularity condition for Implicit Score Matching).</li>
</ul>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Vincent, P. (2011). A Connection Between Score Matching and Denoising Autoencoders. <em>Neural Computation</em>, 23(7), 1661-1674. <a href="https://doi.org/10.1162/NECO_a_00142">https://doi.org/10.1162/NECO_a_00142</a></p>
<p><strong>Publication</strong>: Neural Computation 2011</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@article</span>{vincentConnectionScoreMatching2011,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span> = <span style="color:#e6db74">{A {{Connection Between Score Matching}} and {{Denoising Autoencoders}}}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span> = <span style="color:#e6db74">{Vincent, Pascal}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span> = <span style="color:#ae81ff">2011</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">month</span> = jul,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">journal</span> = <span style="color:#e6db74">{Neural Computation}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">volume</span> = <span style="color:#e6db74">{23}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">number</span> = <span style="color:#e6db74">{7}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span> = <span style="color:#e6db74">{1661--1674}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">doi</span> = <span style="color:#e6db74">{10.1162/NECO_a_00142}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><strong>Additional Resources</strong>:</p>
<ul>
<li><a href="https://www.iro.umontreal.ca/~vincentp/Publications/smdae_techreport.pdf">Official PDF</a></li>
</ul>
]]></content:encoded></item><item><title>Rectified Flow: Learning to Generate and Transfer Data</title><link>https://hunterheidenreich.com/notes/machine-learning/generative-models/rectified-flow/</link><pubDate>Sun, 21 Dec 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/machine-learning/generative-models/rectified-flow/</guid><description>A unified ODE-based framework for generative modeling and domain transfer that learns straight paths for fast 1-step generation.</description><content:encoded><![CDATA[<h2 id="what-kind-of-paper-is-this">What kind of paper is this?</h2>
<p>This is primarily a <strong>Method</strong> paper, with a significant <strong>Theory</strong> component.</p>
<ul>
<li><strong>Method</strong>: It proposes &ldquo;Rectified Flow,&rdquo; a novel generative framework that learns ordinary differential equations (ODEs) to transport distributions via straight paths. It introduces the &ldquo;Reflow&rdquo; algorithm to iteratively straighten these paths.</li>
<li><strong>Theory</strong>: It provides rigorous proofs connecting the method to Optimal Transport, showing that the rectification process yields a coupling with non-increasing convex transport costs and that recursive reflow reduces the curvature of trajectories.</li>
</ul>
<h2 id="what-is-the-motivation">What is the motivation?</h2>
<p>The work addresses two main challenges in unsupervised learning: generative modeling (generating data from noise) and domain transfer (mapping between two observed distributions).</p>
<ul>
<li><strong>Inefficiency of ODE/SDE Models</strong>: Continuous-time models (like Score-based Generative Models and DDPMs) require simulating diffusions over many steps, resulting in high computational costs during inference.</li>
<li><strong>Complexity of GANs</strong>: GANs provide fast (one-step) generation alongside challenges with training instability and mode collapse.</li>
<li><strong>Disconnection</strong>: Generative modeling and domain transfer are often treated as separate tasks requiring different techniques.</li>
</ul>
<p>The authors aim to unify these tasks into a single &ldquo;transport mapping&rdquo; problem while bridging the gap between high-quality continuous models and fast one-step models.</p>
<h2 id="what-is-the-novelty-here">What is the novelty here?</h2>
<p>The core novelty is the <strong>Rectified Flow</strong> framework and the <strong>Reflow</strong> procedure.</p>
<ul>
<li><strong>Straight-Line ODEs</strong>: Rectified Flow learns an ODE drift $v$ to follow the straight line connecting data pairs $(X_0, X_1)$, providing an alternative to diffusion models that rely on stochastic paths or specific forward processes. This is achieved via a simple least-squares optimization problem.</li>
<li><strong>Reflow (Iterative Straightening)</strong>: The authors introduce a recursive training procedure where a new flow is trained on the data pairs $(Z_0, Z_1)$ generated by the previous flow. Theoretical analysis shows this reduces the &ldquo;transport cost&rdquo; and straightens the trajectories, allowing for accurate 1-step simulation (effectively converting the ODE into a one-step model).</li>
<li><strong>Unified Framework</strong>: The method uses the exact same algorithm for generation ($\pi_0$ is Gaussian) and domain transfer ($\pi_0$ is a source dataset), removing the need for adversarial losses or cycle-consistency constraints.</li>
</ul>
<h2 id="what-experiments-were-performed">What experiments were performed?</h2>
<p>The authors validated the method across image generation, translation, and domain adaptation tasks.</p>
<ul>
<li><strong>Unconditioned Image Generation</strong>:
<ul>
<li><strong>Dataset</strong>: CIFAR-10 ($32\times32$).</li>
<li><strong>Baselines</strong>: Compared against GANs (StyleGAN2, TDPM), Diffusion/SDE Models (VP SDE, sub-VP SDE, VE SDE), ODE methods (VP ODE, sub-VP ODE, VE ODE), and distilled methods (DDIM Distillation).</li>
<li><strong>High-Res</strong>: Validated on LSUN Bedroom/Church, CelebA-HQ, and AFHQ ($256\times256$).</li>
</ul>
</li>
<li><strong>Image-to-Image Translation</strong>:
<ul>
<li><strong>Datasets</strong>: AFHQ (Cat $\leftrightarrow$ Dog/Wild), MetFace $\leftrightarrow$ CelebA-HQ.</li>
<li><strong>Setup</strong>: Transferring styles while preserving semantic identity (using a classifier-based feature mapping metric).</li>
</ul>
</li>
<li><strong>Domain Adaptation</strong>:
<ul>
<li><strong>Datasets</strong>: DomainNet, Office-Home.</li>
<li><strong>Metric</strong>: Classification accuracy on the transferred testing data.</li>
</ul>
</li>
</ul>
<h2 id="what-outcomesconclusions">What outcomes/conclusions?</h2>
<ul>
<li><strong>Superior 1-Step Generation</strong>: On CIFAR-10 with a single Euler step (as of ICLR 2023), the distilled 2-Rectified Flow achieved an FID of <strong>4.85</strong>, beating the best one-step U-Net model TDPM (FID 8.91, a truncated diffusion model using a GAN). The distilled 3-Rectified Flow reached a Recall of <strong>0.51</strong>, beating the GAN baseline StyleGAN2+ADA (Recall 0.49).</li>
<li><strong>Straightening Effect</strong>: The &ldquo;Reflow&rdquo; procedure was empirically shown to reduce the &ldquo;straightness&rdquo; error and transport costs, validating the theoretical claims. &ldquo;Straightness&rdquo; is measured as $S(Z) = \mathbb{E}[\int_0^1 |\dot{Z}_t - (Z_1 - Z_0)|^2, dt]$ (zero means perfectly straight); &ldquo;transport cost&rdquo; is $\mathbb{E}[c(Z_1 - Z_0)]$ for a convex cost $c$, and Reflow reduces this for all convex costs.</li>
<li><strong>High-Quality Transfer</strong>: The model successfully performed image translation (e.g., Cat to Wild Animal) without paired data or cycle-consistency losses.</li>
<li><strong>Strong Full-Simulation Results</strong>: With RK45 adaptive ODE solving, 1-Rectified Flow achieves FID 2.58 and Recall 0.57 on CIFAR-10 (Table 1a), the best among ODE methods and comparable to fully simulated SDEs (VP SDE: FID 2.55).</li>
<li><strong>Fast Simulation</strong>: The method allows for extremely coarse time discretization (e.g., $N=1$) without significant quality loss after reflow, effectively solving the slow inference speed of standard ODE models.</li>
<li><strong>Domain Adaptation</strong>: On Office-Home, Rectified Flow achieves 69.2% accuracy, outperforming Deep CORAL (68.7%) and other baselines. On DomainNet, it achieves 41.4%, comparable to Deep CORAL (41.5%) and MLDG (41.2%).</li>
</ul>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="data">Data</h3>
<p>The paper utilizes several standard computer vision benchmarks.</p>
<table>
	<thead>
			<tr>
					<th>Purpose</th>
					<th>Dataset</th>
					<th>Size/Resolution</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Generation</td>
					<td><strong>CIFAR-10</strong></td>
					<td>32x32</td>
					<td>Standard split</td>
			</tr>
			<tr>
					<td>Generation</td>
					<td><strong>LSUN</strong> (Bedroom, Church)</td>
					<td>256x256</td>
					<td>High-res evaluation</td>
			</tr>
			<tr>
					<td>Generation</td>
					<td><strong>CelebA-HQ</strong></td>
					<td>256x256</td>
					<td>High-res evaluation</td>
			</tr>
			<tr>
					<td>Gen/Transfer</td>
					<td><strong>AFHQ</strong> (Cat, Dog, Wild)</td>
					<td>512x512</td>
					<td>256x256 for generation, 512x512 for transfer</td>
			</tr>
			<tr>
					<td>Transfer</td>
					<td><strong>MetFace</strong></td>
					<td>1024x1024</td>
					<td>Resized to 512x512 for experiments</td>
			</tr>
			<tr>
					<td>Adaptation</td>
					<td><strong>DomainNet</strong></td>
					<td>Mixed</td>
					<td>345 categories, 6 domains</td>
			</tr>
			<tr>
					<td>Adaptation</td>
					<td><strong>Office-Home</strong></td>
					<td>Mixed</td>
					<td>65 categories, 4 domains</td>
			</tr>
	</tbody>
</table>
<h3 id="algorithms">Algorithms</h3>
<ul>
<li>
<p><strong>Objective Function</strong>:
The drift $v(Z_t, t)$ is trained by minimizing a least-squares regression objective:
$$\min_{v} \int_{0}^{1} \mathbb{E}[|(X_1 - X_0) - v(X_t, t)|^2] dt$$
where $X_t = tX_1 + (1-t)X_0$ is the linear interpolation.</p>
</li>
<li>
<p><strong>Reflow Procedure</strong>:
Iteratively updates the flow. Let $Z^k$ be the $k$-th rectified flow.</p>
<ol>
<li>Generate 4 million data pairs $(Z_0^k, Z_1^k)$ by simulating the current flow.</li>
<li>Fine-tune the $i$-rectified flow model for 300,000 steps on these pairs to obtain the $(i+1)$-rectified flow.</li>
</ol>
</li>
<li>
<p><strong>Distillation</strong>:
For 1-step distillation ($k=1$), the L2 loss is replaced with LPIPS perceptual similarity, which empirically yields better image quality. For multi-step distillation, training samples $t$ from ${0, 1/k, \ldots, (k-1)/k}$ rather than the full $[0, 1]$ interval.</p>
</li>
<li>
<p><strong>ODE Solver</strong>:</p>
<ul>
<li>Training: Analytical linear interpolation.</li>
<li>Inference: Euler method (constant step size $1/N$) or RK45 (adaptive).</li>
</ul>
</li>
</ul>
<h3 id="models">Models</h3>
<ul>
<li>
<p><strong>Architecture</strong>:</p>
<ul>
<li>Uses the <strong>DDPM++ U-Net</strong> architecture (from Song et al., 2020) across experiments. Implementation is modified from the open-source code of Song et al.</li>
</ul>
</li>
<li>
<p><strong>Optimization</strong>:</p>
<ul>
<li><strong>Optimizer</strong>: Adam (CIFAR-10) or AdamW (Transfer/Adaptation).</li>
<li><strong>Hyperparameters</strong>:
<ul>
<li>LR: $2 \times 10^{-4}$ (CIFAR), Grid search for transfer.</li>
<li>EMA: 0.999999 (CIFAR), 0.9999 (Transfer).</li>
<li>Batch Size: 4 (Transfer), 16 (Domain Adaptation).</li>
<li>Dropout: 0.15 (CIFAR), 0.1 (Transfer).</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="evaluation">Evaluation</h3>
<table>
	<thead>
			<tr>
					<th>Metric</th>
					<th>Value (CIFAR-10, N=1)</th>
					<th>Baseline (Best 1-step)</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><strong>FID</strong></td>
					<td><strong>4.85</strong> (2-Rectified + Distill)</td>
					<td>8.91 (TDPM)</td>
					<td>Lower is better</td>
			</tr>
			<tr>
					<td><strong>Recall</strong></td>
					<td><strong>0.51</strong> (3-Rectified + Distill)</td>
					<td>0.49 (StyleGAN2+ADA)</td>
					<td>Higher is better</td>
			</tr>
	</tbody>
</table>
<h3 id="hardware">Hardware</h3>
<p>The paper does not specify GPU models or training times. The DDPM++ U-Net architecture used in the experiments typically requires multi-GPU setups for training on high-resolution datasets.</p>
<h3 id="artifacts">Artifacts</h3>
<table>
	<thead>
			<tr>
					<th>Artifact</th>
					<th>Type</th>
					<th>License</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><a href="https://github.com/gnobitab/RectifiedFlow">RectifiedFlow (GitHub)</a></td>
					<td>Code</td>
					<td>Unknown</td>
					<td>Official PyTorch implementation with CIFAR-10 and high-res training code, plus pre-trained checkpoints</td>
			</tr>
	</tbody>
</table>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Liu, X., Gong, C., &amp; Liu, Q. (2023). Flow Straight and Fast: Learning to Generate and Transfer Data with Rectified Flow. <em>International Conference on Learning Representations (ICLR)</em>. <a href="https://openreview.net/forum?id=XVjTT1nw5z">https://openreview.net/forum?id=XVjTT1nw5z</a></p>
<p><strong>Publication</strong>: ICLR 2023</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@inproceedings</span>{liuFlowStraightFast2023,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span> = <span style="color:#e6db74">{Flow {{Straight}} and {{Fast}}: {{Learning}} to {{Generate}} and {{Transfer Data}} with {{Rectified Flow}}}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">booktitle</span> = <span style="color:#e6db74">{International Conference on Learning Representations}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span> = <span style="color:#e6db74">{Liu, Xingchao and Gong, Chengyue and Liu, Qiang}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span> = <span style="color:#ae81ff">2023</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">url</span> = <span style="color:#e6db74">{https://openreview.net/forum?id=XVjTT1nw5z}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><strong>Additional Resources</strong>:</p>
<ul>
<li><a href="https://github.com/gnobitab/RectifiedFlow">Official Code Repository</a></li>
<li><a href="https://openreview.net/forum?id=XVjTT1nw5z">OpenReview Page</a></li>
</ul>
]]></content:encoded></item><item><title>Neural ODEs: Continuous-Depth Deep Learning Models</title><link>https://hunterheidenreich.com/notes/machine-learning/generative-models/neural-odes/</link><pubDate>Sun, 21 Dec 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/machine-learning/generative-models/neural-odes/</guid><description>Introduces ODE-Nets, a continuous-depth neural network model parameterized by ODEs, enabling constant memory backpropagation and adaptive computation.</description><content:encoded><![CDATA[<blockquote>
<p><strong>Key Prerequisites</strong>: Before diving in, note that for the ODE solver to guarantee a unique solution, the neural network $f(h(t), t, \theta)$ parameterizing the dynamics must be <a href="https://en.wikipedia.org/wiki/Lipschitz_continuity">Lipschitz continuous</a>. This ensures the <a href="https://en.wikipedia.org/wiki/Picard%E2%80%93Lindel%C3%B6f_theorem">Picard-Lindelöf theorem</a> holds, preventing trajectories from crossing and guaranteeing a well-defined backward pass.</p>
</blockquote>
<h2 id="what-kind-of-paper-is-this">What kind of paper is this?</h2>
<p>This is primarily a <strong>Method</strong> paper, with a strong secondary <strong>Theory</strong> component.</p>
<ul>
<li><strong>Method</strong>: It proposes a novel family of deep neural network models where the derivative of the hidden state is parameterized by a neural network. It provides specific algorithms (Algorithm 1) for training these models scalably.</li>
<li><strong>Theory</strong>: It derives the adjoint sensitivity method for backpropagating through black-box ODE solvers and proves the &ldquo;Instantaneous Change of Variables&rdquo; theorem (Theorem 1) for continuous normalizing flows.</li>
</ul>
<h2 id="what-is-the-motivation">What is the motivation?</h2>
<p>The authors aim to address limitations in discrete deep learning architectures:</p>
<ul>
<li><strong>Discrete vs. Continuous</strong>: Existing models like Residual Networks build transformations by composing discrete steps, which can be seen as an Euler discretization of a continuous transformation. The authors investigate the limit as step sizes go to zero.</li>
<li><strong>Memory Efficiency</strong>: Backpropagating through deep discrete networks requires storing intermediate activations, leading to linear memory cost in terms of depth, which is a major bottleneck.</li>
<li><strong>Irregular Data</strong>: Recurrent Neural Networks (RNNs) struggle with data arriving at arbitrary times, typically requiring discretization into fixed bins.</li>
<li><strong>Normalizing Flow Costs</strong>: Standard normalizing flows have a bottleneck in computing the determinant of the Jacobian, which is computationally expensive ($O(D^3)$).</li>
</ul>
<h2 id="what-is-the-novelty-here">What is the novelty here?</h2>
<p>The core contribution is the <strong>Neural ODE</strong> formulation:
$$\frac{dh(t)}{dt} = f(h(t), t, \theta)$$
where the output is computed using a black-box differential equation solver.</p>
<p>Key technical innovations include:</p>
<ol>
<li><strong>Adjoint Sensitivity Method for Backprop</strong>: The authors treat the solver as a black box and compute gradients by solving a second, augmented ODE backwards in time. This allows for <strong>constant memory cost</strong> regardless of depth.</li>
<li><strong>Adaptive Computation</strong>: The model uses modern ODE solvers that adapt evaluation steps based on error tolerance, allowing the model to trade precision for speed explicitly.</li>
<li><strong>Continuous Normalizing Flows (CNF)</strong>: By moving to continuous time, the change of variables formula simplifies from a log-determinant (cubic cost) to a trace operation (linear cost), enabling scalable generative modeling.</li>
<li><strong>Latent ODEs</strong>: A generative time-series model that represents time-series as latent trajectories determined by a local initial state and global shared dynamics, handling irregular sampling naturally.</li>
</ol>
<h2 id="what-experiments-were-performed">What experiments were performed?</h2>
<p>The authors validated the method across three distinct domains:</p>
<ol>
<li><strong>Supervised Learning (MNIST)</strong>:
<ul>
<li>Compared <strong>ODE-Net</strong> against a standard <strong>ResNet</strong> and a Runge-Kutta network (<strong>RK-Net</strong>).</li>
<li>Measured test error, parameter count, and memory usage.</li>
<li>Analyzed the trade-off between numerical precision (tolerance) and speed (NFE).</li>
</ul>
</li>
<li><strong>Continuous Normalizing Flows (Generative)</strong>:
<ul>
<li>Compared CNF against standard Normalizing Flows (NF) on density matching and maximum likelihood estimation tasks using toy 2D datasets (Two Circles, Two Moons, and other target distributions).</li>
<li>Evaluated training loss (KL divergence) and maximum likelihood estimation.</li>
</ul>
</li>
<li><strong>Time-Series Modeling (Latent ODE)</strong>:
<ul>
<li>Tested on a dataset of bi-directional spirals with irregular timestamps and Gaussian noise.</li>
<li>Compared Latent ODEs against an RNN baseline on predictive RMSE. A second RNN variant with time-difference concatenation was also trained.</li>
</ul>
</li>
</ol>
<h2 id="what-outcomesconclusions">What outcomes/conclusions?</h2>
<ul>
<li><strong>Efficiency</strong>: ODE-Nets achieved roughly equivalent accuracy to ResNets on MNIST (0.42% vs 0.41% error) but with <strong>constant memory cost</strong> ($O(1)$) compared to ResNet&rsquo;s linear cost ($O(L)$).</li>
<li><strong>Adaptive Depth</strong>: The number of function evaluations (NFE) in ODE-Nets increases with training epoch, suggesting the model adapts its complexity as it learns. The backward pass NFE is roughly half the forward pass NFE, indicating that the adjoint method is also more computationally efficient than direct backpropagation through the integrator.</li>
<li><strong>Generative Performance</strong>: Continuous Normalizing Flows (CNF) achieved lower KL divergence loss than standard Normalizing Flows (NF), trained with only 10,000 iterations (Adam) compared to 500,000 iterations (RMSprop) for NF. Note that the two models used different optimizers, so the comparison is not fully controlled. CNF can also expand capacity by increasing width ($M$) without architectural constraints.</li>
<li><strong>Irregular Time-Series</strong>: Latent ODEs significantly outperformed RNNs across all observation counts on irregular spiral data. The advantage is most pronounced with sparse observations (0.1642 vs 0.3937 RMSE at 30 obs), and the model learns interpretable latent trajectories that switch direction smoothly.</li>
</ul>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="data">Data</h3>
<ul>
<li><strong>MNIST</strong>: Standard handwritten digit dataset used for supervised learning benchmarks.</li>
<li><strong>Toy 2D Densities</strong>: &ldquo;Two Circles&rdquo; and &ldquo;Two Moons&rdquo; distributions used for visualizing normalizing flows.</li>
<li><strong>Bi-directional Spirals</strong>: A generated dataset of 1,000 2D spirals (half clockwise, half counter-clockwise). Each spiral is sampled at 100 equally-spaced timesteps with added Gaussian noise. For training, each spiral is then subsampled without replacement to $n \in {30, 50, 100}$ irregularly-spaced observations, simulating realistic missing data.</li>
</ul>
<h3 id="algorithms">Algorithms</h3>
<p><strong>1. Adjoint Sensitivity Method (Backpropagation)</strong></p>
<p>To optimize the parameters of the ODE-Net, the authors use the adjoint sensitivity method to compute gradients. Standard backpropagation would require storing the activations at every step of the ODE solver, incurring a high memory cost that scales linearly with the number of steps.</p>
<p>Instead, this method treats the ODE solver as a &ldquo;black box&rdquo; and computes gradients by solving a second, <strong>augmented ODE</strong> backwards in time from the final state $t_1$ to the initial state $t_0$.</p>
<p>The augmented state contains three components that are solved simultaneously:</p>
<ol>
<li><strong>The State</strong>: The original hidden state $z(t)$, which is reconstructed backwards.</li>
<li><strong>The Adjoint</strong>: The sensitivity of the loss with respect to the state, $a(t) = \partial L / \partial z(t)$.</li>
<li><strong>The Gradient</strong>: The accumulating gradients with respect to parameters, $\partial L / \partial \theta$.</li>
</ol>
<p>The dynamics of this augmented system are defined as:
$$\frac{d}{dt}\begin{bmatrix} z(t) \ a(t) \ \partial L/\partial \theta \end{bmatrix} = \begin{bmatrix} f(z(t), t, \theta) \ -a(t)^T \frac{\partial f}{\partial z} \ -a(t)^T \frac{\partial f}{\partial \theta} \end{bmatrix}$$</p>
<p>Using this approach, the vector-Jacobian products (e.g., $a(t)^T \frac{\partial f}{\partial z}$) are evaluated efficiently using automatic differentiation.</p>
<blockquote>
<p><strong>Why:</strong> Reconstructing $z(t)$ backwards avoids storing the forward pass, enabling <strong>constant memory cost</strong> ($O(1)$) regardless of depth.</p>
<p><strong>Origin:</strong> Adapted from Pontryagin&rsquo;s maximum principle (1962) for optimal control.</p>
</blockquote>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">import</span> torch
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> torch.nn <span style="color:#66d9ef">as</span> nn
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> torchdiffeq <span style="color:#f92672">import</span> odeint_adjoint
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ODEFunc</span>(nn<span style="color:#f92672">.</span>Module):
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">__init__</span>(self, dim):
</span></span><span style="display:flex;"><span>        super(ODEFunc, self)<span style="color:#f92672">.</span><span style="color:#a6e22e">__init__</span>()
</span></span><span style="display:flex;"><span>        self<span style="color:#f92672">.</span>net <span style="color:#f92672">=</span> nn<span style="color:#f92672">.</span>Sequential(
</span></span><span style="display:flex;"><span>            nn<span style="color:#f92672">.</span>Linear(dim, <span style="color:#ae81ff">50</span>),
</span></span><span style="display:flex;"><span>            nn<span style="color:#f92672">.</span>Tanh(),
</span></span><span style="display:flex;"><span>            nn<span style="color:#f92672">.</span>Linear(<span style="color:#ae81ff">50</span>, dim),
</span></span><span style="display:flex;"><span>        )
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">forward</span>(self, t, y):
</span></span><span style="display:flex;"><span>        <span style="color:#75715e"># Defines dy/dt = f(y, t)</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> self<span style="color:#f92672">.</span>net(y)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Usage with adjoint method for O(1) memory backprop</span>
</span></span><span style="display:flex;"><span>func <span style="color:#f92672">=</span> ODEFunc(dim<span style="color:#f92672">=</span><span style="color:#ae81ff">2</span>)
</span></span><span style="display:flex;"><span>y0 <span style="color:#f92672">=</span> torch<span style="color:#f92672">.</span>tensor([[<span style="color:#ae81ff">1.</span>, <span style="color:#ae81ff">0.</span>]]) <span style="color:#75715e"># Initial state</span>
</span></span><span style="display:flex;"><span>t <span style="color:#f92672">=</span> torch<span style="color:#f92672">.</span>linspace(<span style="color:#ae81ff">0.</span>, <span style="color:#ae81ff">1.</span>, <span style="color:#ae81ff">10</span>) <span style="color:#75715e"># Time points to solve for</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># &#39;odeint_adjoint&#39; automatically handles the augmented state backward pass</span>
</span></span><span style="display:flex;"><span>out <span style="color:#f92672">=</span> odeint_adjoint(func, y0, t, method<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;dopri5&#39;</span>)
</span></span></code></pre></div><p><strong>2. Instantaneous Change of Variables (CNF)</strong></p>
<p>For generative modeling, the authors introduce <strong>Continuous Normalizing Flows (CNF)</strong>. In discrete normalizing flows, the probability density of a transformed variable is calculated using the change of variables theorem, which requires computing the log-determinant of the Jacobian: $\log p(z_1) = \log p(z_0) - \log |\det \frac{\partial z_1}{\partial z_0}|$. This operation is computationally expensive ($O(D^3)$) and often restricts model architectures to ensure the Jacobian is easy to compute (e.g., triangular).</p>
<p>Moving to continuous time simplifies this requirement. The paper proves that if the transformation is defined by an ODE, the change in log-probability follows a differential equation determined by the <strong>trace</strong> of the Jacobian:
$$\frac{\partial \log p(z(t))}{\partial t} = -\text{tr}\left( \frac{\partial f}{\partial z(t)} \right)$$</p>
<p>The total change in log-density is obtained by integrating this value over time.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">get_trace</span>(y, f):
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Computes trace of Jacobian df/dy.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    For high dimensions, use Hutchinson&#39;s trace estimator (approximate).
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    tr <span style="color:#f92672">=</span> <span style="color:#ae81ff">0.</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> i <span style="color:#f92672">in</span> range(y<span style="color:#f92672">.</span>size(<span style="color:#ae81ff">1</span>)):
</span></span><span style="display:flex;"><span>        <span style="color:#75715e"># Gradients of f&#39;s i-th component w.r.t y&#39;s i-th component</span>
</span></span><span style="display:flex;"><span>        tr <span style="color:#f92672">+=</span> torch<span style="color:#f92672">.</span>autograd<span style="color:#f92672">.</span>grad(f[:, i]<span style="color:#f92672">.</span>sum(), y, create_graph<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>)[<span style="color:#ae81ff">0</span>][:, i]
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> tr
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># In the ODE function:</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># d(log_p)/dt = -trace(df/dy)</span>
</span></span></code></pre></div><blockquote>
<p><strong>Why:</strong> The trace operator has <strong>linear cost</strong> ($O(D)$), whereas the determinant has cubic cost ($O(D^3)$). This allows for unrestricted, &ldquo;wide&rdquo; architectures that are automatically bijective.</p>
<p><strong>Origin:</strong> This is the &ldquo;Instantaneous Change of Variables&rdquo; theorem (Theorem 1), derived in Appendix A of the paper.</p>
</blockquote>
<h3 id="models">Models</h3>
<p><strong>ODE-Net (MNIST Classification)</strong>:</p>
<ul>
<li><strong>Input</strong>: Downsamples input twice.</li>
<li><strong>Core</strong>: 6 standard residual blocks replaced by a single <strong>ODESolve</strong> module.</li>
<li><strong>Output</strong>: Global average pooling + Fully connected layer.</li>
<li><strong>Solver</strong>: Implicit Adams method.</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">ODEBlock</span>(nn<span style="color:#f92672">.</span>Module):
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">__init__</span>(self, odefunc):
</span></span><span style="display:flex;"><span>        super(ODEBlock, self)<span style="color:#f92672">.</span><span style="color:#a6e22e">__init__</span>()
</span></span><span style="display:flex;"><span>        self<span style="color:#f92672">.</span>odefunc <span style="color:#f92672">=</span> odefunc
</span></span><span style="display:flex;"><span>        self<span style="color:#f92672">.</span>integration_time <span style="color:#f92672">=</span> torch<span style="color:#f92672">.</span>tensor([<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">1</span>])<span style="color:#f92672">.</span>float()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">forward</span>(self, x):
</span></span><span style="display:flex;"><span>        self<span style="color:#f92672">.</span>integration_time <span style="color:#f92672">=</span> self<span style="color:#f92672">.</span>integration_time<span style="color:#f92672">.</span>type_as(x)
</span></span><span style="display:flex;"><span>        <span style="color:#75715e"># Returns [x(t0), x(t1)]; we only want final state x(t1)</span>
</span></span><span style="display:flex;"><span>        out <span style="color:#f92672">=</span> odeint_adjoint(self<span style="color:#f92672">.</span>odefunc, x, self<span style="color:#f92672">.</span>integration_time)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> out[<span style="color:#ae81ff">1</span>]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># ResNet-like architecture with ODE block</span>
</span></span><span style="display:flex;"><span>model <span style="color:#f92672">=</span> nn<span style="color:#f92672">.</span>Sequential(
</span></span><span style="display:flex;"><span>    nn<span style="color:#f92672">.</span>Conv2d(<span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">64</span>, <span style="color:#ae81ff">3</span>, <span style="color:#ae81ff">1</span>),
</span></span><span style="display:flex;"><span>    nn<span style="color:#f92672">.</span>ReLU(inplace<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>),
</span></span><span style="display:flex;"><span>    ODEBlock(ODEFunc(<span style="color:#ae81ff">64</span>)), <span style="color:#75715e"># Continuous-depth layer replacement</span>
</span></span><span style="display:flex;"><span>    nn<span style="color:#f92672">.</span>BatchNorm2d(<span style="color:#ae81ff">64</span>),
</span></span><span style="display:flex;"><span>    nn<span style="color:#f92672">.</span>AdaptiveAvgPool2d((<span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">1</span>)),
</span></span><span style="display:flex;"><span>    nn<span style="color:#f92672">.</span>Flatten(),
</span></span><span style="display:flex;"><span>    nn<span style="color:#f92672">.</span>Linear(<span style="color:#ae81ff">64</span>, <span style="color:#ae81ff">10</span>)
</span></span><span style="display:flex;"><span>)
</span></span></code></pre></div><p><strong>Latent ODE (Time-Series)</strong>:</p>
<ul>
<li><strong>Encoder</strong>: RNN with 25 hidden units processing data backwards to produce $q(z_0|x)$. It runs backwards so the final RNN state summarizes the entire sequence at $t_0$, parameterizing the initial latent state $z_0$ for the forward-running ODE.</li>
<li><strong>Latent Space</strong>: 4-dimensional latent state $z_0$.</li>
<li><strong>Dynamics ($f$)</strong>: Neural network with one hidden layer of 20 units.</li>
<li><strong>Decoder</strong>: Neural network with one hidden layer of 20 units computing $p(x_{t_i}|z_{t_i})$.</li>
<li><strong>Likelihood</strong>: Gaussian log-likelihood for the spiral reconstruction task. The paper also describes an optional Poisson process likelihood $\lambda(z(t))$ for event-time data (e.g., medical records), but this is not used in the spiral experiment.</li>
</ul>
<h3 id="evaluation">Evaluation</h3>
<table>
	<thead>
			<tr>
					<th>Experiment</th>
					<th>Metric</th>
					<th>Baseline (ResNet/RNN)</th>
					<th>ODE Model</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>MNIST</td>
					<td>Test Error</td>
					<td>0.41%</td>
					<td>0.42%</td>
			</tr>
			<tr>
					<td>MNIST</td>
					<td>Parameters</td>
					<td>0.60 M</td>
					<td>0.22 M</td>
			</tr>
			<tr>
					<td>MNIST</td>
					<td>Memory</td>
					<td>$O(L)$</td>
					<td>$O(1)$</td>
			</tr>
			<tr>
					<td>Spirals (30 obs)</td>
					<td>RMSE</td>
					<td>0.3937</td>
					<td><strong>0.1642</strong></td>
			</tr>
			<tr>
					<td>Spirals (50 obs)</td>
					<td>RMSE</td>
					<td>0.3202</td>
					<td><strong>0.1502</strong></td>
			</tr>
			<tr>
					<td>Spirals (100 obs)</td>
					<td>RMSE</td>
					<td>0.1813</td>
					<td><strong>0.1346</strong></td>
			</tr>
	</tbody>
</table>
<h3 id="hardware">Hardware</h3>
<ul>
<li><strong>Implementation</strong>: Hidden state dynamics evaluated on GPU using <strong>TensorFlow</strong>.</li>
<li><strong>Solvers</strong>: Fortran ODE solvers (LSODE, VODE) from <code>scipy.integrate</code> were used for the actual integration.</li>
<li><strong>Note</strong>: While the original paper used TensorFlow/Scipy, the authors later released <code>torchdiffeq</code> (PyTorch), which has become the standard implementation for this architecture. The code samples above reflect this modern standard.</li>
<li><strong>Interface</strong>: Python&rsquo;s <code>autograd</code> framework bridged the TensorFlow dynamics and Scipy solvers.</li>
</ul>
<h3 id="limitations">Limitations</h3>
<p>The paper identifies several practical limitations of Neural ODEs:</p>
<ul>
<li><strong>Minibatching</strong>: Batching requires concatenating states of each batch element into a combined ODE of dimension $D \times K$. Controlling error on all batch elements together can require more evaluations than solving each system individually, though in practice this overhead was not substantial.</li>
<li><strong>Tolerance tuning</strong>: Users must choose error tolerances for both the forward and reverse passes. The paper used 1.5e-8 for sequence modeling, 1e-3 for classification, and 1e-5 for density estimation.</li>
<li><strong>Backward trajectory reconstruction</strong>: Running the dynamics backwards to reconstruct the forward state trajectory can introduce extra numerical error if the reconstructed trajectory diverges from the original. Checkpointing (storing intermediate states) can address this, though the authors did not find it necessary in practice.</li>
<li><strong>Uniqueness requirements</strong>: The neural network $f$ must be Lipschitz continuous (e.g., using tanh or ReLU activations with finite weights) to guarantee a unique solution via Picard&rsquo;s existence theorem.</li>
</ul>
<h3 id="artifacts">Artifacts</h3>
<table>
	<thead>
			<tr>
					<th>Artifact</th>
					<th>Type</th>
					<th>License</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><a href="https://github.com/rtqichen/torchdiffeq">torchdiffeq</a></td>
					<td>Code</td>
					<td>MIT</td>
					<td>Official PyTorch implementation with GPU-based ODE solvers</td>
			</tr>
	</tbody>
</table>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Chen, R. T. Q., Rubanova, Y., Bettencourt, J., &amp; Duvenaud, D. (2018). Neural ordinary differential equations. <em>Proceedings of the 32nd International Conference on Neural Information Processing Systems</em>, 6572-6583.</p>
<p><strong>Publication</strong>: NeurIPS 2018</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@inproceedings</span>{chen2018neural,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>=<span style="color:#e6db74">{Neural ordinary differential equations}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>=<span style="color:#e6db74">{Chen, Ricky T. Q. and Rubanova, Yulia and Bettencourt, Jesse and Duvenaud, David}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">booktitle</span>=<span style="color:#e6db74">{Proceedings of the 32nd International Conference on Neural Information Processing Systems}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span>=<span style="color:#e6db74">{6572--6583}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span>=<span style="color:#e6db74">{2018}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><strong>Additional Resources</strong>:</p>
<ul>
<li><a href="https://github.com/rtqichen/torchdiffeq">Official PyTorch Implementation</a></li>
</ul>
]]></content:encoded></item><item><title>Flow Matching for Generative Modeling: Scalable CNFs</title><link>https://hunterheidenreich.com/notes/machine-learning/generative-models/flow-matching-for-generative-modeling/</link><pubDate>Sun, 21 Dec 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/machine-learning/generative-models/flow-matching-for-generative-modeling/</guid><description>A simulation-free framework for training Continuous Normalizing Flows using Conditional Flow Matching and Optimal Transport paths.</description><content:encoded><![CDATA[<h2 id="what-kind-of-paper-is-this">What kind of paper is this?</h2>
<p>This is primarily a <strong>Method</strong> paper, as it introduces &ldquo;Flow Matching&rdquo; (FM), a novel simulation-free paradigm for training Continuous Normalizing Flows (CNFs) at scale. It is supported by a strong <strong>Theory</strong> basis, providing formal theorems that allow the intractable marginal vector field regression to be solved via a tractable conditional objective. It also touches on <strong>Systematization</strong> by showing that existing diffusion paths are specific instances of the proposed Gaussian probability path framework.</p>
<h2 id="what-is-the-motivation">What is the motivation?</h2>
<p>The paper aims to overcome the scaling limitations of Continuous Normalizing Flows (CNFs).</p>
<ul>
<li><strong>Problem</strong>: Standard Maximum Likelihood training for CNFs requires expensive numerical ODE simulations during training, which scales poorly. Existing simulation-free methods often involve intractable integrals or result in biased gradients.</li>
<li><strong>Gap</strong>: Diffusion models scale well, yet they are restricted to specific, curved probability paths (e.g., VP, VE) that can result in slow sampling and long training times.</li>
<li><strong>Goal</strong>: To develop an efficient, simulation-free training method for CNFs that supports arbitrary probability paths, specifically allowing for straighter, more efficient trajectories like those from Optimal Transport.</li>
</ul>
<h2 id="what-is-the-novelty-here">What is the novelty here?</h2>
<p>The core novelty is <strong>Flow Matching (FM)</strong> and specifically the <strong>Conditional Flow Matching (CFM)</strong> objective.</p>
<ul>
<li><strong>Direct Vector Field Regression</strong>: The model regresses a target vector field $u_t$ that generates a desired probability path $p_t$.</li>
<li><strong>Conditional Flow Matching (CFM)</strong>: The authors prove that regressing the vector field of <em>conditional</em> paths (e.g., $p_t(x|x_1)$ given a single data point) yields the same gradients as regressing the intractable marginal vector field. This bypasses the need to know the marginal score or vector field.</li>
<li><strong>Optimal Transport Paths</strong>: The framework enables the use of <strong>Optimal Transport (OT)</strong> displacement interpolation for probability paths. OT paths are straight lines with constant speed, leading to faster training and easier sampling.</li>
</ul>
<p><strong>Concurrent work note</strong>: Rectified Flow (Liu et al., 2023) and Stochastic Interpolants (Albergo &amp; Vanden-Eijnden, 2023) were published concurrently at ICLR 2023 with structurally similar contributions under different names. All three independently propose simulation-free training of continuous flows via direct vector field regression; the differences lie in the specific interpolation schemes, theoretical framing, and experimental focus.</p>
<h2 id="what-experiments-were-performed">What experiments were performed?</h2>
<ul>
<li><strong>Domains</strong>: 2D Checkerboard data, CIFAR-10, and ImageNet at resolutions $32 \times 32$, $64 \times 64$, and $128 \times 128$.</li>
<li><strong>Task</strong>: Unconditional generative modeling (density estimation and sample quality) and conditional super-resolution ($64 \times 64 \to 256 \times 256$).</li>
<li><strong>Baselines</strong>: Compared against Diffusion-based methods on the same architecture (U-Net): DDPM, Score Matching (SM), and ScoreFlow.</li>
<li><strong>Ablations</strong>: Specifically compared <strong>FM with Diffusion paths</strong> vs. <strong>FM with Optimal Transport (OT) paths</strong> to isolate the benefit of the training objective vs. the path choice.</li>
</ul>
<h2 id="what-outcomesconclusions">What outcomes/conclusions?</h2>
<ul>
<li><strong>Outperforms diffusion baselines</strong>: FM-OT consistently outperforms all diffusion-based methods (DDPM, Score Matching, ScoreFlow) in both Likelihood (NLL) and Sample Quality (FID) across CIFAR-10 and ImageNet, using the same U-Net architecture and training budget. Selected rows from Table 1 (NLL in bits per dimension, BPD; lower is better for all three metrics; &ldquo;FM w/ OT&rdquo; and &ldquo;FM w/ Diffusion&rdquo; refer to FM trained with OT paths and Diffusion paths respectively):</li>
</ul>
<table>
	<thead>
			<tr>
					<th>Dataset</th>
					<th>Method</th>
					<th>NLL (BPD) ↓</th>
					<th>FID ↓</th>
					<th>NFE ↓</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>CIFAR-10</td>
					<td>DDPM</td>
					<td>3.12</td>
					<td>7.48</td>
					<td>274</td>
			</tr>
			<tr>
					<td>CIFAR-10</td>
					<td>FM w/ OT</td>
					<td><strong>2.99</strong></td>
					<td><strong>6.35</strong></td>
					<td><strong>142</strong></td>
			</tr>
			<tr>
					<td>ImageNet 64×64</td>
					<td>ScoreFlow</td>
					<td>3.36</td>
					<td>24.95</td>
					<td>601</td>
			</tr>
			<tr>
					<td>ImageNet 64×64</td>
					<td>FM w/ OT</td>
					<td><strong>3.31</strong></td>
					<td><strong>14.45</strong></td>
					<td><strong>138</strong></td>
			</tr>
	</tbody>
</table>
<ul>
<li><strong>Training stability</strong>: FM with diffusion paths (FM w/ Diffusion) is itself a more stable alternative to diffusion training than DDPM and Score Matching, as shown by training curves in the paper (Figure 5), even before switching to OT paths. The OT path then provides further gains.</li>
<li><strong>Sampling speed</strong>: The straight trajectories of OT paths allow accurate sampling with significantly fewer function evaluations (NFE) compared to diffusion paths.</li>
<li><strong>Generality</strong>: Diffusion is a specific instance of Gaussian probability paths within FM. OT paths are a better-optimized alternative available within the same framework.</li>
<li><strong>Downstream adoption</strong>: Flow matching has been adopted beyond image generation. <a href="/notes/computational-biology/dynamicflow/">DynamicFlow</a> uses it as the generative backbone for simultaneously generating ligand molecules and transforming protein pockets, extending flow matching to structure-based drug design.</li>
</ul>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="data">Data</h3>
<ul>
<li><strong>Datasets</strong>: CIFAR-10, ImageNet ($32 \times 32$, $64 \times 64$, $128 \times 128$).</li>
<li><strong>Preprocessing</strong>:
<ul>
<li>Images are center-cropped and resized.</li>
<li>For $32 \times 32$ and $64 \times 64$, the preprocessing follows Chrabaszcz et al. (2017).</li>
<li>Data is transformed via $\varphi(y) = 2^7(y+1)$ mapping $[-1, 1]$ pixel values to $[0, 256]$ for BPD computation.</li>
</ul>
</li>
</ul>
<h3 id="algorithms">Algorithms</h3>
<p><strong>1. Conditional Flow Matching (CFM) Objective</strong></p>
<p>The practical training objective used is the CFM loss, which bypasses intractable marginalization:</p>
<p>$$\mathcal{L}_{CFM}(\theta) = \mathbb{E}_{t, q(x_1), p(x_0)} | v_t(\psi_t(x_0)) - u_t(\psi_t(x_0) | x_1) |^2$$</p>
<p>Where $t \sim \mathcal{U}[0,1]$, $x_1 \sim q(x_1)$ (data), and $x_0 \sim p(x_0)$ (noise).</p>
<p><strong>2. Optimal Transport (OT) Probability Path</strong></p>
<p>The authors recommend the OT path for efficiency.</p>
<ul>
<li><strong>Mean/Std Schedule</strong>: $\mu_t(x) = t x_1$ and $\sigma_t(x) = 1 - (1 - \sigma_{min})t$.</li>
<li><strong>Conditional Flow Map</strong>: $\psi_t(x) = (1 - (1 - \sigma_{min})t)x + t x_1$.</li>
<li><strong>Target Vector Field</strong>: The closed-form regression target for OT is:
$$u_t(x|x_1) = \frac{x_1 - (1 - \sigma_{min})x}{1 - (1 - \sigma_{min})t}$$</li>
</ul>
<p><strong>3. Sampling</strong></p>
<p>Sampling is performed by solving the ODE $\frac{d}{dt}\phi_t(x) = v_t(\phi_t(x))$ from $t=0$ to $t=1$ using the learned vector field $v_t$.</p>
<ul>
<li><strong>Solver</strong>: <code>dopri5</code> (adaptive) is used for robust evaluation. Fixed-step solvers (Euler, Midpoint) are used for low-NFE efficiency tests.</li>
</ul>
<h3 id="models">Models</h3>
<ul>
<li><strong>Architecture</strong>: U-Net architecture from Dhariwal &amp; Nichol (2021) is used for all image experiments.</li>
<li><strong>Toy Data</strong>: 5-layer MLP with 512 neurons.</li>
<li><strong>Hyperparameters</strong>:
<ul>
<li>Optimizer: Adam ($\beta_1=0.9, \beta_2=0.999$, weight decay=0.0).</li>
<li>Learning Rate: Polynomial decay or constant (see Table 3 in paper).</li>
<li>$\sigma_{min}$: Set to a small value (e.g., $1e-5$).</li>
</ul>
</li>
</ul>
<h3 id="evaluation">Evaluation</h3>
<ul>
<li><strong>Metrics</strong>:
<ul>
<li><strong>NLL (BPD)</strong>: Computed using the continuous change of variables formula, estimated via the Hutchinson trace estimator to bypass $O(d^3)$ divergence computation.</li>
<li><strong>FID</strong>: Frechet Inception Distance for sample quality.</li>
<li><strong>NFE</strong>: Number of Function Evaluations required by the solver.</li>
</ul>
</li>
<li><strong>Likelihood Computation</strong>: Requires solving an augmented ODE to track the log-density change:
$$\frac{d}{dt} \begin{bmatrix} \phi_t(x) \ f(t) \end{bmatrix} = \begin{bmatrix} v_t(\phi_t(x)) \ -\text{div}(v_t(\phi_t(x))) \end{bmatrix}$$</li>
</ul>
<h3 id="hardware">Hardware</h3>
<ul>
<li><strong>CIFAR-10</strong>: 2 GPUs.</li>
<li><strong>ImageNet-32</strong>: 4 GPUs.</li>
<li><strong>ImageNet-64</strong>: 16 GPUs.</li>
<li><strong>ImageNet-128</strong>: 32 GPUs.</li>
<li><strong>Precision</strong>: Full 32-bit for CIFAR/IM-32; 16-bit mixed precision for IM-64/128.</li>
</ul>
<h3 id="artifacts">Artifacts</h3>
<table>
	<thead>
			<tr>
					<th>Artifact</th>
					<th>Type</th>
					<th>License</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><a href="https://github.com/facebookresearch/flow_matching">flow_matching (PyTorch library)</a></td>
					<td>Code</td>
					<td>CC BY-NC 4.0</td>
					<td>Later official library from Meta; not the original experiment code</td>
			</tr>
	</tbody>
</table>
<p>The paper does not release the original training code or model weights used in the experiments. The <code>facebookresearch/flow_matching</code> library was released later as a general-purpose PyTorch implementation of flow matching algorithms. Standard benchmark datasets (CIFAR-10, ImageNet) are publicly available.</p>
<hr>
<h2 id="theoretical-notes-why-cfm-works">Theoretical Notes: Why CFM Works</h2>
<p>The paper relies on three key theorems to make training tractable.</p>
<p><strong>Theorem 1 (Marginal Generation)</strong>:</p>
<p>Marginalizing conditional vector fields $u_t(x|x_1)$ yields the correct marginal vector field $u_t(x)$ that generates the marginal probability path $p_t(x)$.</p>
<p>$$u_t(x) = \int u_t(x|x_1) \frac{p_t(x|x_1)q(x_1)}{p_t(x)} dx_1$$</p>
<blockquote>
<p><strong>Understanding the Proof:</strong></p>
<p>To understand why this theorem holds, we have to look at the <strong>Continuity Equation</strong>, which is the fundamental partial differential equation (PDE) that links a probability density path $p_t$ to a vector field $u_t$.</p>
<p>A vector field $u_t$ is said to &ldquo;generate&rdquo; a probability path $p_t$ if and only if they satisfy the continuity equation:</p>
<p>$$\frac{\partial p_t(x)}{\partial t} + \nabla \cdot (p_t(x) u_t(x)) = 0$$</p>
<p>The proof of Theorem 1 relies on substituting the definitions of the marginal path and vector field into this equation to see if they balance out.</p>
<p><strong>Step-by-Step Proof:</strong></p>
<ol>
<li>
<p><strong>Start with the time derivative of the marginal path</strong>: We begin by differentiating the marginal probability path $p_t(x)$ with respect to time. By definition, the marginal path is the integral of the conditional paths over the data distribution:
$$\frac{\partial p_t(x)}{\partial t} = \frac{\partial}{\partial t} \int p_t(x|x_1) q(x_1) dx_1$$</p>
</li>
<li>
<p><strong>Swap derivative and integral</strong>: Assuming standard regularity conditions (Leibniz Rule), we can move the time derivative inside the integral:
$$\frac{\partial p_t(x)}{\partial t} = \int \frac{\partial p_t(x|x_1)}{\partial t} q(x_1) dx_1$$</p>
</li>
<li>
<p><strong>Apply the Conditional Continuity Equation</strong>: This is the critical step. We know that the conditional vector field $u_t(x|x_1)$ generates the conditional path $p_t(x|x_1)$. Therefore, for every single sample $x_1$, the pair satisfies the continuity equation:
$$\frac{\partial p_t(x|x_1)}{\partial t} = -\nabla \cdot (p_t(x|x_1) u_t(x|x_1))$$</p>
<p>Substituting this into our integral gives:
$$\frac{\partial p_t(x)}{\partial t} = -\int \nabla \cdot (p_t(x|x_1) u_t(x|x_1)) q(x_1) dx_1$$</p>
</li>
<li>
<p><strong>Pull the Divergence out</strong>: Since the divergence operator ($\nabla \cdot$) acts on $x$ and the integral is over $x_1$, we can pull the divergence operator outside the integral (by linearity):
$$\frac{\partial p_t(x)}{\partial t} = -\nabla \cdot \left( \int p_t(x|x_1) u_t(x|x_1) q(x_1) dx_1 \right)$$</p>
</li>
<li>
<p><strong>Match with the Marginal Vector Field Definition</strong>: Now, look at the term inside the parentheses. The paper defines the marginal vector field $u_t(x)$ specifically to make this term simpler. Rearranging the definition of $u_t(x)$ provided in the theorem:
$$p_t(x) u_t(x) = \int p_t(x|x_1) u_t(x|x_1) q(x_1) dx_1$$</p>
<p>Substitute $p_t(x) u_t(x)$ back into our equation from Step 4:
$$\frac{\partial p_t(x)}{\partial t} = -\nabla \cdot (p_t(x) u_t(x))$$</p>
</li>
</ol>
<p><strong>Conclusion</strong>: We have just shown that $\frac{\partial p_t(x)}{\partial t} + \nabla \cdot (p_t(x) u_t(x)) = 0$. This is exactly the continuity equation. Because the marginal path and the aggregated marginal vector field satisfy this equation, the vector field is proven to generate the path.</p>
</blockquote>
<p><strong>Theorem 2 (Gradient Equivalence)</strong>:</p>
<p>The intractable Flow Matching objective $\mathcal{L}_{FM}$ (which requires $u_t(x)$) has the <strong>same gradients</strong> as the tractable Conditional Flow Matching objective $\mathcal{L}_{CFM}$.</p>
<p>$$\nabla_\theta \mathcal{L}_{FM}(\theta) = \nabla_\theta \mathcal{L}_{CFM}(\theta)$$</p>
<p>This allows the model to learn the marginal vector field by only seeing conditional sample paths.</p>
<blockquote>
<p><strong>Understanding the Proof:</strong></p>
<p>The reason Theorem 2 holds is that the &ldquo;Conditional Flow Matching&rdquo; (CFM) objective is essentially an unbiased estimator of the &ldquo;Flow Matching&rdquo; (FM) objective (up to a constant). When we average over all the conditional data points $x_1$, the &ldquo;cross-term&rdquo; in the loss function aligns perfectly with the marginal vector field.</p>
<p><strong>1. Expand the Loss Functions</strong></p>
<p>First, let&rsquo;s look at the squared error in both objectives. Recall that $v_t$ is our neural network (parameterized by $\theta$), $u_t$ is the intractable marginal target, and $u_t(x|x_1)$ is the tractable conditional target.</p>
<p>Expanding the squared norms:</p>
<ul>
<li>
<p><strong>FM Objective</strong>:
$$\mathcal{L}_{FM}(\theta) = \mathbb{E}_{t, p_t(x)} \left[ |v_t(x)|^2 - 2v_t(x) \cdot u_t(x) + |u_t(x)|^2 \right]$$</p>
</li>
<li>
<p><strong>CFM Objective</strong>:
$$\mathcal{L}_{CFM}(\theta) = \mathbb{E}_{t, q(x_1), p_t(x|x_1)} \left[ |v_t(x)|^2 - 2v_t(x) \cdot u_t(x|x_1) + |u_t(x|x_1)|^2 \right]$$</p>
</li>
</ul>
<p><strong>Key Insight</strong>: When we take the gradient $\nabla_\theta$, the last term in both equations disappears because the targets ($u_t$) are independent of the network weights $\theta$. We only need to show that the expectations of the first two terms match.</p>
<p><strong>2. Matching the First Term ($|v_t(x)|^2$)</strong></p>
<p>This part is straightforward. The expectation of $|v_t(x)|^2$ is the same in both cases because of how the marginal density $p_t(x)$ is defined.</p>
<ul>
<li><strong>FM</strong>: averages over $p_t(x)$.</li>
<li><strong>CFM</strong>: averages over $p_t(x|x_1)q(x_1)$.</li>
</ul>
<p>Since $p_t(x) = \int p_t(x|x_1) q(x_1) dx_1$ (by definition), averaging over the joint distribution is mathematically identical to averaging over the marginal $p_t(x)$.</p>
<p><strong>3. Matching the Cross Term (The &ldquo;Trick&rdquo;)</strong></p>
<p>This is the critical part of the proof. We need to show that the interaction between the network and the marginal field equals the interaction between the network and the conditional field.</p>
<p><strong>The Goal</strong>: Show $\mathbb{E}_{t, p_t(x)} [v_t(x) \cdot u_t(x)] = \mathbb{E}_{t, q(x_1), p_t(x|x_1)} [v_t(x) \cdot u_t(x|x_1)]$.</p>
<p><strong>The Proof</strong>:</p>
<ol>
<li>
<p>Start with the <strong>FM cross-term</strong> (marginal):
$$\mathbb{E}_{t, p_t(x)} [v_t(x) \cdot u_t(x)]$$</p>
</li>
<li>
<p>Substitute the definition of the marginal vector field $u_t(x)$ derived in <strong>Theorem 1</strong>:
$$u_t(x) = \int u_t(x|x_1) \frac{p_t(x|x_1) q(x_1)}{p_t(x)} dx_1$$</p>
</li>
<li>
<p>Plug this into the integral. The $p_t(x)$ terms cancel:
$$\mathbb{E}_{t, p_t(x)} [v_t(x) \cdot u_t(x)] = \int_t \int_x p_t(x) v_t(x) \cdot \left[ \int_{x_1} u_t(x|x_1) \frac{p_t(x|x_1) q(x_1)}{p_t(x)} dx_1 \right] dx$$</p>
</li>
<li>
<p>This simplifies to:
$$= \int_t \int_x \int_{x_1} v_t(x) \cdot u_t(x|x_1) p_t(x|x_1) q(x_1) dx_1 dx dt$$</p>
</li>
<li>
<p>This is exactly the definition of the expectation in the <strong>CFM objective</strong>:
$$= \mathbb{E}_{t, q(x_1), p_t(x|x_1)} [v_t(x) \cdot u_t(x|x_1)]$$</p>
</li>
</ol>
<p><strong>Conclusion</strong>: Because the expectations of all terms involving $\theta$ are identical, the gradients must be identical.</p>
<p>Intuitively, this works like <strong>Denoising Score Matching</strong> or <strong>Stochastic Gradient Descent</strong>: even though each individual conditional vector field $u_t(x|x_1)$ points to a specific data point $x_1$ (which may differ from the true marginal direction), the <em>average</em> of all these pulls equals the true marginal vector field $u_t(x)$.</p>
</blockquote>
<p><strong>Theorem 3 (Gaussian Conditional VFs)</strong>:</p>
<p>For any Gaussian probability path $p_t(x|x_1) = \mathcal{N}(x | \mu_t(x_1), \sigma_t(x_1)^2 I)$, the unique vector field generating it is available in closed form:</p>
<p>$$u_t(x|x_1) = \frac{\sigma&rsquo;_t(x_1)}{\sigma_t(x_1)}(x - \mu_t(x_1)) + \mu&rsquo;_t(x_1)$$</p>
<p>This theorem allows explicitly defining targets for both Diffusion (curved) and Optimal Transport (straight) paths.</p>
<blockquote>
<p><strong>Understanding the Proof:</strong></p>
<p>The derivation of Theorem 3 comes from the direct relationship between a flow map $\psi_t$ and its generating vector field. Because we chose a specific, simple path (Gaussian), we can invert the flow map to find the vector field in closed form.</p>
<p><strong>1. Define the Flow Map $\psi_t$</strong></p>
<p>We start by defining the conditional probability path as a Gaussian:</p>
<p>$$p_t(x|x_1) = \mathcal{N}(x | \mu_t(x_1), \sigma_t(x_1)^2 I)$$</p>
<p>The simplest way to &ldquo;push&rdquo; a standard normal distribution (noise) $p_0 = \mathcal{N}(0, I)$ to this Gaussian is using an affine transformation (scaling and shifting). We define the flow map $\psi_t$ as:</p>
<p>$$\psi_t(x_0) = \sigma_t(x_1) x_0 + \mu_t(x_1)$$</p>
<p>This map takes a noise sample $x_0$ and transforms it into a sample $x$ at time $t$.</p>
<p><strong>2. The Definition of a Generating Vector Field</strong></p>
<p>By definition, a vector field $u_t$ generates a flow $\psi_t$ if the vector field describes the instantaneous velocity of the flow at any point. Mathematically:</p>
<p>$$u_t(\psi_t(x_0)) = \frac{d}{dt}\psi_t(x_0)$$</p>
<p>Let $x = \psi_t(x_0)$ be the position of the particle at time $t$. We want to find $u_t(x)$.</p>
<p><strong>3. Invert the Flow Map</strong></p>
<p>To find $u_t(x)$, we must express the equation in terms of $x$ rather than $x_0$. Since our flow map is a simple affine transformation (multiply and add), it is easily invertible (assuming $\sigma_t(x_1) \neq 0$):</p>
<p>$$x_0 = \frac{x - \mu_t(x_1)}{\sigma_t(x_1)}$$</p>
<p>We will call this inverse map $\psi_t^{-1}(x)$.</p>
<p><strong>4. Differentiate the Flow Map</strong></p>
<p>Now we calculate the left side of our definition equation (velocity): $\frac{d}{dt}\psi_t(x_0)$.</p>
<p>Taking the time derivative of $\psi_t(x_0) = \sigma_t(x_1) x_0 + \mu_t(x_1)$:</p>
<p>$$\frac{d}{dt}\psi_t(x_0) = \sigma&rsquo;_t(x_1) x_0 + \mu&rsquo;_t(x_1)$$</p>
<p>(Note: $\sigma&rsquo;_t$ and $\mu&rsquo;_t$ denote time derivatives).</p>
<p><strong>5. Substitute and Solve</strong></p>
<p>Now we combine everything. We know $u_t(\psi_t(x_0)) = \frac{d}{dt}\psi_t(x_0)$.</p>
<p>Substitute the result from Step 4 into this equation:</p>
<p>$$u_t(\psi_t(x_0)) = \sigma&rsquo;_t(x_1) x_0 + \mu&rsquo;_t(x_1)$$</p>
<p>This expresses the vector field in terms of the initial point $x_0$. We must express it in terms of the current point $x$. So, we plug in the inverse formula for $x_0$ derived in Step 3:</p>
<p>$$u_t(x|x_1) = \sigma&rsquo;_t(x_1) \frac{x - \mu_t(x_1)}{\sigma_t(x_1)} + \mu&rsquo;_t(x_1)$$</p>
<p>Rearranging terms gives the final closed form:</p>
<p>$$u_t(x|x_1) = \frac{\sigma&rsquo;_t(x_1)}{\sigma_t(x_1)}(x - \mu_t(x_1)) + \mu&rsquo;_t(x_1)$$</p>
<p><strong>Why is this useful?</strong></p>
<p>This formula means that as long as you can define a mean schedule $\mu_t(x_1)$ and a standard deviation schedule $\sigma_t(x_1)$ (which is easy to do for both Diffusion and Optimal Transport), you immediately get the exact vector field target $u_t(x|x_1)$ needed to train your neural network, bypassing complex ODE solving or score matching approximations.</p>
</blockquote>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Lipman, Y., Chen, R. T. Q., Ben-Hamu, H., Nickel, M., &amp; Le, M. (2023). Flow Matching for Generative Modeling. <em>International Conference on Learning Representations (ICLR)</em>.</p>
<p><strong>Publication</strong>: ICLR 2023</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@inproceedings</span>{lipmanFlowMatchingGenerative2023,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span> = <span style="color:#e6db74">{Flow Matching for Generative Modeling}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span> = <span style="color:#e6db74">{Lipman, Yaron and Chen, Ricky T. Q. and Ben-Hamu, Heli and Nickel, Maximilian and Le, Matt}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">booktitle</span> = <span style="color:#e6db74">{International Conference on Learning Representations}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span> = <span style="color:#e6db74">{2023}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><strong>Additional Resources</strong>:</p>
<ul>
<li><a href="https://arxiv.org/abs/2210.02747">ArXiv</a></li>
</ul>
]]></content:encoded></item><item><title>Building Normalizing Flows with Stochastic Interpolants</title><link>https://hunterheidenreich.com/notes/machine-learning/generative-models/stochastic-interpolants/</link><pubDate>Sun, 21 Dec 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/machine-learning/generative-models/stochastic-interpolants/</guid><description>A continuous-time normalizing flow using stochastic interpolants and quadratic loss to bypass costly ODE backpropagation.</description><content:encoded><![CDATA[<h2 id="what-kind-of-paper-is-this">What kind of paper is this?</h2>
<p>This is primarily a <strong>Method</strong> paper, with significant <strong>Theory</strong> contributions.</p>
<p>The authors propose a specific algorithm (&ldquo;InterFlow&rdquo;) for constructing generative models based on continuous-time normalizing flows. The work is characterized by the derivation of a new training objective (a simple quadratic loss) that bypasses the computational bottlenecks of previous methods. It includes prominent baseline comparisons against continuous flow methods (FFJORD, OT-Flow) and diffusion models. The theoretical component establishes the validity of the interpolant density satisfying the continuity equation (a conservation law governing how probability mass flows) and bounds the Wasserstein-2 distance (a measure of transport cost between distributions, penalizing squared displacement) of the transport.</p>
<h2 id="what-is-the-motivation">What is the motivation?</h2>
<p>The primary motivation is to overcome the computational inefficiency of training Continuous Normalizing Flows (CNFs) using Maximum Likelihood Estimation (MLE). Standard CNF training requires backpropagating through numerical ODE solvers, which is costly and limits scalability.</p>
<p>Additionally, while score-based diffusion models (SDEs) have achieved high sample quality, they theoretically require infinite time integration and rely on specific noise schedules. The authors aim to establish a method that works strictly with Probability Flow ODEs on finite time intervals, retaining the flexibility to connect arbitrary densities without the complexity of SDEs or the cost of standard ODE adjoint methods.</p>
<h2 id="what-is-the-novelty-here">What is the novelty here?</h2>
<p>The core novelty is the <strong>Stochastic Interpolant</strong> framework:</p>
<ul>
<li><strong>Explicit Interpolant Construction</strong>: The method defines a time-dependent interpolant $x_t = I_t(x_0, x_1)$ (e.g., trigonometric interpolation) that connects samples from the base density $\rho_0$ and target $\rho_1$.</li>
<li><strong>Simulation-Free Training</strong>: The velocity field $v_t(x)$ of the probability flow is learned by minimizing a simple quadratic objective: $G(\hat{v}) = \mathbb{E}[|\hat{v}_t(x_t)|^2 - 2\partial_t x_t \cdot \hat{v}_t(x_t)]$. Because $\partial_t I_t$ is known analytically from the interpolant definition, the expectation can be estimated by sampling $(x_0, x_1, t)$ directly. This avoids ODE integration during training (ODE integration is still required at inference).</li>
<li><strong>Decoupling Path and Optimization</strong>: The choice of path (interpolant) is separated from the optimization of the velocity field. MLE methods couple the path and objective.</li>
<li><strong>Connection to Score-Based Models</strong>: The authors show that for Gaussian base densities and trigonometric interpolants, the learned velocity field is explicitly related to the score function $\nabla \log \rho_t$, providing a theoretical bridge between CNFs and diffusion models.</li>
</ul>
<h2 id="what-experiments-were-performed">What experiments were performed?</h2>
<p>The authors performed validation across synthetic, tabular, and image domains:</p>
<ul>
<li><strong>2D Density Estimation</strong>: Benchmarked on &ldquo;Checkerboard&rdquo;, &ldquo;8 Gaussians&rdquo;, and anisotropic curved densities to visualize mode coverage and transport smoothness.</li>
<li><strong>High-Dimensional Tabular Data</strong>: Evaluated on standard benchmarks (POWER, GAS, HEPMASS, MINIBOONE, BSDS300) comparing Negative Log Likelihood (NLL) against FFJORD, OT-Flow, and others.</li>
<li><strong>Image Generation</strong>: Trained models on CIFAR-10 ($32 \times 32$), ImageNet ($32 \times 32$), and Oxford Flowers ($128 \times 128$) to test scalability.</li>
<li><strong>Ablations</strong>: Investigated optimizing the interpolant path itself (e.g., learning Fourier coefficients for the path) to approach optimal transport and minimize path length.</li>
</ul>
<h2 id="what-outcomesconclusions">What outcomes/conclusions?</h2>
<ul>
<li><strong>Performance</strong>: The method matches or supersedes conventional ODE flows (like FFJORD) in terms of NLL while being significantly cheaper to train.</li>
<li><strong>Efficiency</strong>: The training cost per epoch is constant (simulation-free), whereas MLE-based ODE methods see growing costs as the dynamics become more complex.</li>
<li><strong>Scalability</strong>: The method successfully scales to $128 \times 128$ resolution on a single GPU, a resolution that prior ab-initio ODE flows had not demonstrated.</li>
<li><strong>Flexibility</strong>: The framework can connect <em>any</em> two arbitrary densities (e.g., connecting two different complex 2D distributions) without needing one to be Gaussian.</li>
<li><strong>Optimal Transport</strong>: For a fixed interpolant, minimizing $G(\hat{v})$ over the velocity field recovers the velocity for that specific path. Additionally optimizing over the interpolant family yields a solution to the Benamou-Brenier optimal transport problem.</li>
<li><strong>Limitations</strong>: The authors acknowledge that image FID scores trail dedicated diffusion models, noting that InterFlow was not optimized with standard training tricks such as exponential moving averages, truncation, or learning rate warm-ups. The framework&rsquo;s sample quality could likely improve with these additions.</li>
</ul>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="data">Data</h3>
<ul>
<li><strong>Tabular Datasets</strong>: POWER (6D), GAS (8D), HEPMASS (21D), MINIBOONE (43D), BSDS300 (63D).
<ul>
<li>Training points range from ~30k (MINIBOONE) to ~1.6M (POWER).</li>
</ul>
</li>
<li><strong>Image Datasets</strong>:
<ul>
<li>CIFAR-10 ($32 \times 32$, 50k training points).</li>
<li>ImageNet ($32 \times 32$, ~1.28M training points).</li>
<li>Oxford Flowers ($128 \times 128$, ~315k training points).</li>
</ul>
</li>
<li><strong>Time Sampling</strong>: Time $t$ is sampled from a Beta distribution during training (reweighting) to focus learning near the target.</li>
</ul>
<h3 id="algorithms">Algorithms</h3>
<ul>
<li><strong>Interpolant</strong>: The primary interpolant used is trigonometric: $I_t(x_0, x_1) = \cos(\frac{\pi t}{2})x_0 + \sin(\frac{\pi t}{2})x_1$.
<ul>
<li>Alternative linear interpolant: $I_t = a_t x_0 + b_t x_1$.</li>
</ul>
</li>
<li><strong>Loss Function</strong>:
$$G(\hat{v}) = \mathbb{E}_{t, x_0, x_1}[|\hat{v}_t(x_t)|^2 - 2\partial_t I_t(x_0, x_1) \cdot \hat{v}_t(x_t)]$$
<ul>
<li>The expectation is amenable to empirical estimation using batches of $x_0, x_1, t$.</li>
</ul>
</li>
<li><strong>Sampling</strong>: Numerical integration using Dormand-Prince (Runge-Kutta 4/5).</li>
<li><strong>Optimization</strong>: SGD/Adam variants used for optimization.</li>
</ul>
<h3 id="models">Models</h3>
<ul>
<li><strong>Tabular Architectures</strong>:
<ul>
<li>Feed-forward networks with 4-5 hidden layers.</li>
<li>Hidden widths: 512 (POWER, GAS, HEPMASS, MINIBOONE) or 1024 (BSDS300).</li>
<li>Activation: ReLU (general) or ELU (BSDS300).</li>
</ul>
</li>
<li><strong>Image Architectures</strong>:
<ul>
<li>U-Net based on the DDPM implementation.</li>
<li>Dimensions: 256 hidden dimension.</li>
<li>Sinusoidal time embeddings used.</li>
</ul>
</li>
</ul>
<h3 id="evaluation">Evaluation</h3>
<ul>
<li><strong>Metrics</strong>: Negative Log Likelihood (NLL) in nats (tabular) or bits per dim (images), Frechet Inception Distance (FID) for images.</li>
<li><strong>Baselines</strong>: FFJORD, Glow, Real NVP, OT-Flow, ScoreFlow, DDPM.</li>
</ul>
<p><strong>Tabular NLL</strong> (nats, lower is better; Table 2 Left):</p>
<table>
	<thead>
			<tr>
					<th>Method</th>
					<th>POWER</th>
					<th>GAS</th>
					<th>HEPMASS</th>
					<th>MINIBOONE</th>
					<th>BSDS300</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>MADE</td>
					<td>3.08</td>
					<td>-3.56</td>
					<td>20.98</td>
					<td>15.59</td>
					<td>-148.85</td>
			</tr>
			<tr>
					<td>Real NVP</td>
					<td>-0.17</td>
					<td>-8.33</td>
					<td>18.71</td>
					<td>13.55</td>
					<td>-153.28</td>
			</tr>
			<tr>
					<td>Glow</td>
					<td>-0.17</td>
					<td>-8.15</td>
					<td>18.92</td>
					<td>11.35</td>
					<td>-155.07</td>
			</tr>
			<tr>
					<td>CPF</td>
					<td>-0.52</td>
					<td>-10.36</td>
					<td>16.93</td>
					<td>10.58</td>
					<td>-154.99</td>
			</tr>
			<tr>
					<td>NSP</td>
					<td>-0.64</td>
					<td>-13.09</td>
					<td>14.75</td>
					<td>9.67</td>
					<td>-157.54</td>
			</tr>
			<tr>
					<td>FFJORD</td>
					<td>-0.46</td>
					<td>-8.59</td>
					<td>14.92</td>
					<td>10.43</td>
					<td>-157.40</td>
			</tr>
			<tr>
					<td>OT-Flow</td>
					<td>-0.30</td>
					<td>-9.20</td>
					<td>17.32</td>
					<td>10.55</td>
					<td>-154.20</td>
			</tr>
			<tr>
					<td><strong>Ours</strong></td>
					<td><strong>-0.57</strong></td>
					<td><strong>-12.35</strong></td>
					<td><strong>14.85</strong></td>
					<td><strong>10.42</strong></td>
					<td><strong>-156.22</strong></td>
			</tr>
	</tbody>
</table>
<p><strong>Image Generation NLL and FID</strong> (Table 2 Right; NLL in bits per dim, lower is better):</p>
<table>
	<thead>
			<tr>
					<th>Method</th>
					<th>CIFAR-10 NLL</th>
					<th>CIFAR-10 FID</th>
					<th>ImageNet-32 NLL</th>
					<th>ImageNet-32 FID</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>FFJORD</td>
					<td>3.40</td>
					<td>-</td>
					<td>-</td>
					<td>-</td>
			</tr>
			<tr>
					<td>Glow</td>
					<td>3.35</td>
					<td>-</td>
					<td>4.09</td>
					<td>-</td>
			</tr>
			<tr>
					<td>DDPM</td>
					<td>≤3.75</td>
					<td>3.17</td>
					<td>-</td>
					<td>-</td>
			</tr>
			<tr>
					<td>DDPM++ (Song et al., 2021)</td>
					<td>≤3.37</td>
					<td>2.90</td>
					<td>-</td>
					<td>-</td>
			</tr>
			<tr>
					<td>ScoreSDE (Song et al., 2021)</td>
					<td>2.99</td>
					<td>2.92</td>
					<td>-</td>
					<td>-</td>
			</tr>
			<tr>
					<td>VDM</td>
					<td>≤2.65</td>
					<td>7.41</td>
					<td>≤3.72</td>
					<td>-</td>
			</tr>
			<tr>
					<td>Soft Truncation</td>
					<td>2.88</td>
					<td>3.45</td>
					<td>3.85</td>
					<td>8.42</td>
			</tr>
			<tr>
					<td>ScoreFlow</td>
					<td>2.81</td>
					<td>5.40</td>
					<td>3.76</td>
					<td>10.18</td>
			</tr>
			<tr>
					<td><strong>Ours</strong></td>
					<td><strong>2.99</strong></td>
					<td><strong>10.27</strong></td>
					<td><strong>3.48</strong></td>
					<td><strong>8.49</strong></td>
			</tr>
	</tbody>
</table>
<p>Note: DDPM++ is from Song et al. (2021), the same work as ScoreSDE (it is the architecture optimized for VP/sub-VP SDEs). InterFlow matches ScoreSDE on CIFAR-10 NLL (2.99 bits per dim) while being simulation-free. FID is weaker than dedicated image models (10.27 vs 2.92 for ScoreSDE), reflecting the paper&rsquo;s primary focus on tractable likelihood rather than sample quality.</p>
<h3 id="hardware">Hardware</h3>
<ul>
<li><strong>Compute</strong>: All models were trained on a single NVIDIA A100 GPU.</li>
<li><strong>Training Time</strong>:
<ul>
<li>Tabular: $10^5$ steps.</li>
<li>Images: $1.5 \times 10^5$ to $6 \times 10^5$ steps.</li>
<li>Speedup: Demonstrated ~400x speedup compared to FFJORD on MiniBooNE dataset.</li>
</ul>
</li>
</ul>
<h3 id="artifacts">Artifacts</h3>
<table>
	<thead>
			<tr>
					<th>Artifact</th>
					<th>Type</th>
					<th>License</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>lucidrains/denoising-diffusion-pytorch (link defunct)</td>
					<td>Code</td>
					<td>MIT</td>
					<td>Base U-Net architecture used for image experiments; original GitHub account no longer available</td>
			</tr>
	</tbody>
</table>
<p>No official code release accompanies this paper. All tabular datasets (POWER, GAS, HEPMASS, MINIBOONE, BSDS300) are publicly available from prior work. CIFAR-10 and ImageNet are standard public benchmarks. Oxford Flowers 102 is also publicly available. Hyperparameters and architectures are fully specified in Tables 3 and 4 of the paper.</p>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Albergo, M. S., &amp; Vanden-Eijnden, E. (2023). Building Normalizing Flows with Stochastic Interpolants. <em>The Eleventh International Conference on Learning Representations</em>.</p>
<p><strong>Publication</strong>: ICLR 2023</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@inproceedings</span>{albergoBuildingNormalizingFlows2022,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span> = <span style="color:#e6db74">{Building {{Normalizing Flows}} with {{Stochastic Interpolants}}}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">booktitle</span> = <span style="color:#e6db74">{The {{Eleventh International Conference}} on {{Learning Representations}}}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span> = <span style="color:#e6db74">{Albergo, Michael Samuel and {Vanden-Eijnden}, Eric}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span> = <span style="color:#ae81ff">2023</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">url</span> = <span style="color:#e6db74">{https://openreview.net/forum?id=li7qeBbCR1t}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><strong>Additional Resources</strong>:</p>
<ul>
<li><a href="https://openreview.net/forum?id=li7qeBbCR1t">OpenReview</a></li>
<li><a href="https://arxiv.org/abs/2209.15571">arXiv</a></li>
</ul>
]]></content:encoded></item><item><title>A Convexity Principle for Interacting Gases (McCann 1997)</title><link>https://hunterheidenreich.com/notes/machine-learning/generative-models/convexity-principle-interacting-gases/</link><pubDate>Sun, 21 Dec 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/machine-learning/generative-models/convexity-principle-interacting-gases/</guid><description>Introduces displacement interpolation to prove ground state uniqueness via optimal transport, with mathematical tools later used in generative modeling.</description><content:encoded><![CDATA[<h2 id="what-kind-of-paper-is-this">What kind of paper is this?</h2>
<p>This is a <a href="/notes/research-methods/ai-physical-sciences-paper-taxonomy/">Theory</a> paper. It relies entirely on formal mathematical derivation to establish existence and uniqueness properties for energy functionals. It introduces a new mathematical structure (displacement interpolation) to analyze the geometry of probability measures.</p>
<h2 id="what-is-the-motivation">What is the motivation?</h2>
<p>The paper addresses the uniqueness of stationary configurations (ground states) for a gas model where particles interact via attractive forces while resisting compression.</p>
<p>The total energy functional $E(\rho)$ includes an interaction term $G(\rho)$ that lacks convexity under standard linear interpolation ($(1-t)\rho + t\rho&rsquo;$), making it difficult to prove that a unique minimizer exists. Standard convexity tools and rearrangement inequalities are also insufficient for cases without specific symmetries (like spherical symmetry) or when convexity of the potential fails.</p>
<h2 id="what-is-the-novelty-here">What is the novelty here?</h2>
<p>The core novelty is the introduction of <strong>Displacement Interpolation</strong>.</p>
<ul>
<li><strong>New Interpolant</strong>: The paper defines an interpolant $\rho_t$ by moving mass along the gradient of a convex potential $\psi$ (transport map).</li>
<li><strong>Displacement Convexity</strong>: It proves that the internal energy $U(\rho)$ and potential energy $G(\rho)$ become convex functions of $t$ along this displacement path. This is a property specific to displacement interpolation.</li>
<li><strong>Generalization</strong>: This framework generalizes the classical <strong>Brunn-Minkowski inequality</strong> from sets to measures.</li>
</ul>
<h3 id="theoretical-framework">Theoretical Framework</h3>
<h4 id="mathematical-setup">Mathematical Setup</h4>
<p><strong>Probability Measures</strong></p>
<p>The gas state is represented by absolutely continuous probability measures $\rho \in \mathcal{P}_{ac}(\mathbb{R}^d)$ with finite second moments.</p>
<p><strong>Energy Functional</strong></p>
<p>The gas model is defined by the total energy functional $E(\rho)$:
$$E(\rho) := \underbrace{\int_{\mathbb{R}^d} A(\rho(x))dx}_{\text{Internal Energy } U(\rho)} + \underbrace{\frac{1}{2} \iint d\rho(x)V(x-y)d\rho(y)}_{\text{Potential Energy } G(\rho)}$$</p>
<h4 id="key-construction-displacement-interpolation">Key Construction: Displacement Interpolation</h4>
<p>The core theoretical tool is the construction of the interpolant $\rho_t$ between two probability measures $\rho$ and $\rho&rsquo;$:</p>
<ol>
<li><strong>Transport Map</strong>: By Brenier&rsquo;s theorem, there exists a convex function $\psi$ such that $\nabla\psi_{\#}\rho = \rho&rsquo;$ (push-forward).</li>
<li><strong>Interpolation</strong>: The interpolant at time $t \in [0,1]$ is defined as the push-forward of $\rho$ under the linear interpolation of the identity and the transport map:
$$\rho_t := [(1-t)\text{id} + t\nabla\psi]_{\#}\rho$$</li>
</ol>
<p>This is the &ldquo;displacement interpolation&rdquo; where mass moves along straight lines from initial to final positions.</p>
<h4 id="assumptions-for-uniqueness">Assumptions for Uniqueness</h4>
<p>The main existence and uniqueness theorem (Theorem 3.1) requires one condition on the interaction potential, two conditions on the equation of state, and one regularity condition:</p>
<ol>
<li><strong>Interaction</strong>: $V(x)$ is strictly convex.</li>
<li><strong>(P1) Equation of State</strong>: $P(\rho) / \rho^{(d-1)/d}$ is non-decreasing. This is equivalent to convexity of $U$ under mass-preserving dilations, and is satisfied by polytropic gases $P(\rho) = \rho^q$ with $q &gt; 1$.</li>
<li><strong>(P2) Growth Condition</strong>: $P(\rho) \cdot \rho^{-2}$ is not integrable at $\infty$. This ensures the energy minimizer has no singular part with respect to Lebesgue measure.</li>
<li><strong>Regularity</strong>: $\rho \in \mathcal{P}_{ac}(\mathbb{R}^d)$ (absolutely continuous probability measures).</li>
</ol>
<h4 id="main-results">Main Results</h4>
<p><strong>Theorem 2.2</strong> (Displacement Convexity of Internal Energy): Under condition (A1) (that $\lambda^d A(\lambda^{-d})$ is convex non-increasing on $(0, \infty)$ with $A(0) = 0$, ensuring internal energy decreases as the gas dilates), the internal energy $U(\rho)$ is convex along displacement interpolation paths. Strict convexity follows unless $\nabla^2\psi(x) = I$ holds $\rho$-a.e., i.e., $\rho&rsquo;$ is a translate of $\rho$.</p>
<p><strong>Theorem 3.1</strong> (Existence and Uniqueness of Ground State): For any equation of state satisfying (P1) and (P2) with a strictly convex interaction potential $V$, the total energy $E(\rho)$ attains a unique minimizer up to translation. The minimizer can be taken to be even, meaning $\rho_g(x) = \rho_g(-x)$.</p>
<p><strong>Theorem 3.3</strong> (Uniqueness for Spherically Symmetric Potentials): When the strict convexity of $V(x)$ is relaxed to spherical symmetry (with $V$ not constant), uniqueness up to translation still holds provided (P1) holds strictly. This extends the main result to cases like Coulomb-type interactions.</p>
<p><strong>Lemma 3.2</strong>: A decomposition lemma for convex functions. Let $\psi$ and $\phi$ be convex on $\mathbb{R}^d$, and let $\Omega \subset \mathbb{R}^d$ be an open convex set on which both are finite. Suppose $\phi$ is differentiable on $\Omega$ with a locally Lipschitz gradient. If their Aleksandrov second derivatives agree almost everywhere on $\Omega$, then $\psi - \phi$ is convex on $\Omega$. This underpins the proof of Theorem 3.3.</p>
<h2 id="what-experiments-were-performed">What experiments were performed?</h2>
<p>The validation consists entirely of rigorous mathematical proofs:</p>
<ul>
<li><strong>Convexity Proofs</strong>: Deriving inequalities to show $E(\rho_t) \le (1-t)E(\rho) + tE(\rho&rsquo;)$.</li>
<li><strong>Existence/Uniqueness</strong>: Using the new convexity principle to prove that the energy minimizer is unique up to translation.</li>
</ul>
<h2 id="what-outcomesconclusions">What outcomes/conclusions?</h2>
<ul>
<li><strong>Uniqueness of Ground State</strong>: For equations of state satisfying specific monotonicity conditions (e.g., polytropic gases), the energy minimizing state is unique up to translation.</li>
<li><strong>Brunn-Minkowski Extension</strong>: The internal energy convexity implies the Brunn-Minkowski inequality as a special case ($A(\rho) = -\rho^{(d-1)/d}$).</li>
<li><strong>Norm Concavity</strong>: The functional $|\rho_t|_q^{-p/d}$ is shown to be concave along the interpolation path for conjugate $p, q$ with $q \geq (d-1)/d$.</li>
</ul>
<h3 id="relevance-to-machine-learning">Relevance to Machine Learning</h3>
<p>This 1997 paper establishes the mathematical foundations of displacement convexity in optimal transport theory, which underpins several modern generative modeling techniques. The displacement interpolation framework introduced here is used in:</p>
<ul>
<li><strong>Flow Matching</strong>: Uses optimal transport probability paths (straight-line interpolations with constant speed) to generate samples. See the <a href="../flow-matching-for-generative-modeling/">Flow Matching note</a> for details on how OT paths differ from diffusion paths.</li>
<li><strong>Wasserstein GANs</strong>: Use the Wasserstein distance (optimal transport metric) for training stability.</li>
<li><strong>Continuous Normalizing Flows</strong>: Use OT-inspired transport maps for probability density transformation.</li>
</ul>
<p>McCann&rsquo;s convexity principle proves that energy functionals become convex along displacement paths, a mathematical structure that underpins the geometry used in flow matching and optimal transport-based generative modeling.</p>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: McCann, R. J. (1997). A Convexity Principle for Interacting Gases. <em>Advances in Mathematics</em>, 128(1), 153-179. <a href="https://doi.org/10.1006/aima.1997.1634">https://doi.org/10.1006/aima.1997.1634</a></p>
<p><strong>Publication</strong>: Advances in Mathematics 1997</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@article</span>{mccannConvexityPrincipleInteracting1997,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span> = <span style="color:#e6db74">{A {{Convexity Principle}} for {{Interacting Gases}}}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span> = <span style="color:#e6db74">{McCann, Robert J.}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span> = <span style="color:#ae81ff">1997</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">month</span> = jun,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">journal</span> = <span style="color:#e6db74">{Advances in Mathematics}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">volume</span> = <span style="color:#e6db74">{128}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">number</span> = <span style="color:#e6db74">{1}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span> = <span style="color:#e6db74">{153--179}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">issn</span> = <span style="color:#e6db74">{00018708}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">doi</span> = <span style="color:#e6db74">{10.1006/aima.1997.1634}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">urldate</span> = <span style="color:#e6db74">{2025-12-21}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>DynamicFlow: Integrating Protein Dynamics into Drug Design</title><link>https://hunterheidenreich.com/notes/computational-biology/dynamicflow/</link><pubDate>Sat, 20 Dec 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/computational-biology/dynamicflow/</guid><description>Flow matching model that co-generates ligands and flexible protein pockets, addressing rigid-receptor limitations in structure-based drug design.</description><content:encoded><![CDATA[<h2 id="what-kind-of-paper-is-this">What kind of paper is this?</h2>
<p>This is primarily a <strong>Methodological Paper</strong> ($\Psi_{\text{Method}}$) with a strong <strong>Resource</strong> ($\Psi_{\text{Resource}}$) component.</p>
<ul>
<li><strong>Method</strong>: It proposes <strong>DynamicFlow</strong>, a novel multiscale architecture combining atom-level SE(3)-equivariant GNNs (SE(3) is the special Euclidean group in 3D: the set of all 3D rotations and translations, and equivariance means predictions transform consistently under those symmetries) and residue-level Transformers within a <a href="/notes/machine-learning/generative-models/flow-matching-for-generative-modeling/">flow matching</a> framework to model the joint distribution of ligand generation and protein conformational change.</li>
<li><strong>Resource</strong>: It curates a significant dataset derived from MISATO, pairing AlphaFold2-predicted apo structures with multiple MD-simulated holo states, specifically filtered for flow matching tasks.</li>
</ul>
<h2 id="what-is-the-motivation">What is the motivation?</h2>
<p>Traditional Structure-Based Drug Design (SBDD) methods typically assume the protein target is rigid, which limits their applicability because proteins are dynamic and undergo conformational changes (induced fit) upon ligand binding.</p>
<ul>
<li><strong>Biological Reality</strong>: Proteins exist as ensembles of states; binding often involves transitions from &ldquo;apo&rdquo; (unbound) to &ldquo;holo&rdquo; (bound) <a href="/posts/geom-conformer-generation-dataset/">conformational changes</a>, sometimes revealing cryptic pockets.</li>
<li><strong>Computational Bottleneck</strong>: <a href="/notes/chemistry/molecular-simulation/">Molecular Dynamics (MD)</a> simulates these changes but incurs high computational costs due to energy barriers.</li>
<li><strong>Gap</strong>: <a href="/notes/machine-learning/generative-models/">Existing generative models</a> for SBDD mostly condition on a fixed pocket structure, ignoring the co-adaptation of the protein and ligand.</li>
</ul>
<h2 id="what-is-the-novelty-here">What is the novelty here?</h2>
<p>The core novelty is the <strong>simultaneous modeling of ligand generation and protein conformational dynamics</strong> using a unified flow matching framework.</p>
<ul>
<li><strong>DynamicFlow Architecture</strong>: A multiscale model that treats the protein as both full-atom (for interaction) and residue-level frames (for large-scale dynamics), utilizing separate flow matching objectives for backbone frames, side-chain torsions, and ligand atoms.</li>
<li><strong>Stochastic Flow (SDE)</strong>: Introduction of a <a href="/notes/machine-learning/generative-models/score-based-generative-modeling-sde/">stochastic variant</a> (DynamicFlow-SDE) that improves robustness and diversity compared to the deterministic ODE flow.</li>
<li><strong>Coupled Generation</strong>: The model learns to transport the <em>apo</em> pocket distribution to the <em>holo</em> pocket distribution while simultaneously denoising the ligand, advancing beyond rigid pocket docking methods.</li>
</ul>
<h2 id="what-experiments-were-performed">What experiments were performed?</h2>
<p>The authors validated the method on a curated dataset of 5,692 protein-ligand complexes.</p>
<ul>
<li><strong>Baselines</strong>: Compared against rigid-pocket SBDD methods: Pocket2Mol, TargetDiff, and IPDiff (adapted as TargetDiff* and IPDiff* for fair comparison of atom numbers). Also compared against conformation sampling baselines (Str2Str).</li>
<li><strong>Metrics</strong>:
<ul>
<li><strong>Ligand Quality</strong>: Vina Score (binding affinity), QED (drug-likeness), SA (synthesizability), Lipinski&rsquo;s rule of 5.</li>
<li><strong>Pocket Quality</strong>: RMSD between generated and ground-truth holo pockets, Cover Ratio (percentage of holo states successfully retrieved), and Pocket Volume distributions.</li>
<li><strong>Interaction</strong>: Protein-Ligand Interaction Profiler (PLIP) to measure specific non-covalent interactions.</li>
</ul>
</li>
<li><strong>Ablations</strong>: Tested the impact of the interaction loss, residue-level Transformer, and SDE vs. ODE formulations.</li>
</ul>
<h2 id="what-outcomesconclusions">What outcomes/conclusions?</h2>
<ul>
<li><strong>Improved Affinity</strong>: DynamicFlow-SDE achieved the best (lowest) Vina scores ($-7.65$) compared to baselines like TargetDiff ($-5.09$) and Pocket2Mol ($-5.50$). Note that Vina scores are a computational proxy and do not directly predict experimental binding affinity. Moreover, Vina score optimization is gameable: molecules can achieve strong computed binding energies while remaining synthetically inaccessible. QED and SA scores, which assess drug-likeness and synthesizability respectively, were reported but were not primary optimization targets in the paper, which limits the strength of this affinity claim.</li>
<li><strong>Realistic Dynamics</strong>: The model successfully generated holo-like pocket conformations with volume distributions and interaction profiles closer to ground-truth MD simulations than the initial apo structures.</li>
<li><strong>Enhancing Rigid Methods</strong>: Holo pockets generated by DynamicFlow served as better inputs for rigid-SBDD baselines (e.g., TargetDiff improved from $-5.09$ to $-9.00$ and IPDiff improved from $-7.55$ to $-11.04$ when using &ldquo;Our Pocket&rdquo;), suggesting the method can act as a &ldquo;pocket refiner&rdquo;.</li>
<li><strong>ODE vs. SDE Trade-off</strong>: The deterministic ODE variant achieves better pocket RMSD, while the stochastic SDE variant achieves better Cover Ratio (diversity of holo states captured) and binding affinity. Neither dominates uniformly.</li>
<li><strong>Conformation Sampling Baseline</strong>: Str2Str, a dedicated conformation sampling baseline, performed worse than simply perturbing the apo structure with noise. One interpretation is that this highlights the difficulty of the apo-to-holo prediction task; another is that Str2Str was not designed specifically for apo-to-holo prediction, making it a limited test of its capabilities.</li>
</ul>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="data">Data</h3>
<p>The dataset is derived from <strong>MISATO</strong>, which contains MD trajectories for PDBbind complexes.</p>
<table>
	<thead>
			<tr>
					<th>Purpose</th>
					<th>Dataset</th>
					<th>Size</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><strong>Training/Test</strong></td>
					<td>Curated MISATO</td>
					<td>5,692 complexes</td>
					<td>Filtered for valid MD (<a href="/posts/kabsch-algorithm/">RMSD</a> $&lt; 3\text{\AA}$), clustered to remove redundancy. Contains 46,235 holo-ligand conformations total.</td>
			</tr>
			<tr>
					<td><strong>Apo Structures</strong></td>
					<td>AlphaFold2</td>
					<td>N/A</td>
					<td>Apo structures were obtained by mapping PDB IDs to UniProt and retrieving AlphaFold2 predictions, then aligning to MISATO structures.</td>
			</tr>
			<tr>
					<td><strong>Splits</strong></td>
					<td>Standard</td>
					<td>50 test complexes</td>
					<td>50 complexes with no overlap with the training set selected for testing. Note: 50 is a small held-out set; results should be interpreted cautiously.</td>
			</tr>
	</tbody>
</table>
<p><strong>Preprocessing</strong>:</p>
<ul>
<li><strong>Clustering</strong>: Holo-ligand conformations clustered with RMSD threshold $1.0\text{\AA}$; top 10 clusters kept per complex.</li>
<li><strong>Pocket Definition</strong>: Residues within $7\text{\AA}$ of the ligand.</li>
<li><strong>Alignment</strong>: AlphaFold predicted structures (apo) aligned to MISATO holo structures using sequence alignment (Smith-Waterman) to identify pocket residues.</li>
</ul>
<h3 id="algorithms">Algorithms</h3>
<p><strong>Flow Matching Framework</strong>:</p>
<ul>
<li><strong>Continuous Variables</strong> (Pocket translation/rotation/torsions, Ligand positions): Modeled using <strong>Conditional Flow Matching (CFM)</strong>.
<ul>
<li><em>Prior</em>: Apo state for pocket; Normal distribution for ligand positions.</li>
<li><em>Target</em>: Holo state from MD; Ground truth ligand.</li>
<li><em>Interpolant</em>: Linear interpolation for Euclidean variables; Geodesic for rotations ($SO(3)$, the rotation-only subgroup of SE(3) containing all 3D rotations but not translations); Wrapped linear interpolation for torsions (Torus).</li>
</ul>
</li>
<li><strong>Discrete Variables</strong> (Ligand atom/bond types): Modeled using <strong>Discrete Flow Matching</strong> based on Continuous-Time Markov Chains (CTMC).
<ul>
<li><em>Rate Matrix</em>: Interpolates between mask token and data distribution.</li>
</ul>
</li>
<li><strong>Loss Function</strong>: Weighted sum of 7 losses:
<ol>
<li>Translation CFM (Eq 5)</li>
<li>Rotation CFM (Eq 7)</li>
<li>Torsion CFM (Eq 11)</li>
<li>Ligand Position CFM</li>
<li>Ligand Atom Type CTMC (Eq 14)</li>
<li>Ligand Bond Type CTMC</li>
<li><strong>Interaction Loss</strong> (Eq 18): Explicitly penalizes deviations in pairwise distances between protein and ligand atoms for pairs $\leq 3.5\text{\AA}$.</li>
</ol>
</li>
</ul>
<h3 id="models">Models</h3>
<p><strong>Architecture</strong>: <strong>DynamicFlow</strong> is a multiscale model with 15.9M parameters.</p>
<ol>
<li><strong>Atom-Level SE(3)-Equivariant GNN</strong>:
<ul>
<li><em>Input</em>: Complex graph (k-NN) and Ligand graph (fully connected).</li>
<li><em>Layers</em>: 6 EGNN blocks modified to maintain node and edge hidden states.</li>
<li><em>Function</em>: Updates ligand positions and predicts ligand atom/bond types.</li>
</ul>
</li>
<li><strong>Residue-Level Transformer</strong>:
<ul>
<li><em>Input</em>: Aggregated atom features from the GNN + Residue frames/torsions.</li>
<li><em>Layers</em>: 4 Transformer blocks with <strong>Invariant Point Attention (IPA)</strong>.</li>
<li><em>Function</em>: Updates protein residue frames (translation/rotation) and predicts side-chain torsions.</li>
</ul>
</li>
</ol>
<h3 id="evaluation">Evaluation</h3>
<p><strong>Metrics</strong>:</p>
<ul>
<li><strong>Vina Score</strong>: <code>vina_minimize</code> mode used for binding affinity.</li>
<li><strong>RMSD</strong>: Minimum RMSD between generated pocket and ground-truth holo conformations.</li>
<li><strong>Cover Ratio</strong>: % of ground-truth holo conformations covered by at least one generated sample (threshold $1.42\text{\AA}$).</li>
<li><strong>POVME 3</strong>: For pocket volume calculation.</li>
</ul>
<h3 id="hardware">Hardware</h3>
<ul>
<li><strong>Inference Benchmark</strong>: 1x Tesla V100-SXM2-32GB.</li>
<li><strong>Speed</strong>: Generates 10 ligands in ~35-36 seconds (100 NFE), significantly faster than diffusion baselines like Pocket2Mol (980s) or TargetDiff (156s).</li>
</ul>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Zhou, X., Xiao, Y., Lin, H., He, X., Guan, J., Wang, Y., Liu, Q., Zhou, F., Wang, L., &amp; Ma, J. (2025). Integrating Protein Dynamics into Structure-Based Drug Design via Full-Atom Stochastic Flows. <em>International Conference on Learning Representations (ICLR)</em>. <a href="https://arxiv.org/abs/2503.03989">https://arxiv.org/abs/2503.03989</a></p>
<p><strong>Publication</strong>: ICLR 2025</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@inproceedings</span>{zhouIntegratingProteinDynamics2025,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span> = <span style="color:#e6db74">{Integrating Protein Dynamics into Structure-Based Drug Design via Full-Atom Stochastic Flows}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span> = <span style="color:#e6db74">{Zhou, Xiangxin and Xiao, Yi and Lin, Haowei and He, Xinheng and Guan, Jiaqi and Wang, Yang and Liu, Qiang and Zhou, Feng and Wang, Liang and Ma, Jianzhu}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">booktitle</span> = <span style="color:#e6db74">{International Conference on Learning Representations}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span> = <span style="color:#e6db74">{2025}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">url</span> = <span style="color:#e6db74">{https://arxiv.org/abs/2503.03989}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><strong>Additional Resources</strong>:</p>
<ul>
<li><a href="https://arxiv.org/abs/2503.03989">arXiv Page</a></li>
<li>Code: no public repository available at time of writing</li>
</ul>
]]></content:encoded></item><item><title>Unified Framework for Handwritten Chemical Expressions</title><link>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/online-recognition/chang-unified-framework-2009/</link><pubDate>Wed, 17 Dec 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/online-recognition/chang-unified-framework-2009/</guid><description>A 2009 unified framework for inorganic/organic chemical handwriting recognition using graph search and statistical symbol grouping.</description><content:encoded><![CDATA[<h2 id="addressing-the-complexity-of-handwritten-organic-chemistry">Addressing the Complexity of Handwritten Organic Chemistry</h2>
<p>This is a <strong>Methodological Paper</strong> ($\Psi_{\text{Method}}$) from Microsoft Research Asia that addresses the challenge of recognizing complex 2D organic chemistry structures. By 2009, math expression recognition had seen significant commercial progress, but chemical expression recognition remained less developed.</p>
<p>The specific gap addressed is the geometric complexity of organic formulas. While inorganic formulas typically follow a linear, equation-like structure, organic formulas present complex 2D diagrammatic structures with various bond types and rings. Existing work often relied on strong assumptions (like single-stroke symbols) or failed to handle arbitrary compounds. There was a clear need for a unified solution capable of handling both inorganic and organic domains consistently.</p>
<h2 id="the-chemical-expression-structure-graph-cesg">The Chemical Expression Structure Graph (CESG)</h2>
<p>The core innovation is a unified statistical framework that processes inorganic and organic expressions within the same pipeline. Key technical novelties include:</p>
<ol>
<li><strong>Unified Bond Modeling</strong>: Bonds are treated as special symbols. The framework detects &ldquo;extended bond symbols&rdquo; (multi-stroke bonds) and splits them into single, double, or triple bonds using corner detection for consistent processing.</li>
<li><strong>Chemical Expression Structure Graph (CESG)</strong>: A defined graph representation for generic chemical expressions where nodes represent symbols and edges represent bonds or spatial relations.</li>
<li><strong>Non-Symbol Modeling</strong>: During the symbol grouping phase, the system explicitly models &ldquo;invalid groups&rdquo; to reduce over-grouping errors.</li>
<li><strong>Global Graph Search</strong>: Structure analysis is formulated as finding the optimal CESG by searching over a Weighted Direction Graph ($G_{WD}$).</li>
</ol>
<h2 id="graph-search-and-statistical-validation">Graph Search and Statistical Validation</h2>
<p>The authors validated the framework on a proprietary database of 35,932 handwritten chemical expressions collected from 300 writers.</p>
<ul>
<li><strong>Setup</strong>: The data was split into roughly 26,000 training and 6,400 testing samples.</li>
<li><strong>Metric</strong>: Recognition accuracy was measured strictly by expression (all symbols and the complete structure must be correct).</li>
<li><strong>Ablations</strong>: The team evaluated the performance contribution of symbol grouping, structure analysis, and full semantic verification.</li>
</ul>
<h2 id="recognition-accuracy-and-outcomes">Recognition Accuracy and Outcomes</h2>
<p>The full framework achieved a Top-1 accuracy of 75.4% and a Top-5 accuracy of 83.1%.</p>
<ul>
<li><strong>Component Contribution</strong>: Structure analysis is the primary bottleneck. Adding it drops the theoretical &ldquo;perfect grouping&rdquo; performance from 85.9% to 74.1% (Top-1) due to structural errors.</li>
<li><strong>Semantic Verification</strong>: Checking valence and grammar improved relative accuracy by 1.7%.</li>
</ul>
<p>The unified framework effectively handles the variance in 2D space for chemical expressions, demonstrating that delayed decision-making (keeping top-N candidates) improves robustness.</p>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="artifacts">Artifacts</h3>
<table>
	<thead>
			<tr>
					<th style="text-align: left">Artifact</th>
					<th style="text-align: left">Type</th>
					<th style="text-align: left">License</th>
					<th style="text-align: left">Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td style="text-align: left">N/A</td>
					<td style="text-align: left">N/A</td>
					<td style="text-align: left">N/A</td>
					<td style="text-align: left">No public artifacts (code, data, models) were released by the authors.</td>
			</tr>
	</tbody>
</table>
<h3 id="data">Data</h3>
<p>The study used a private Microsoft Research Asia dataset, making direct reproduction difficult.</p>
<table>
	<thead>
			<tr>
					<th>Purpose</th>
					<th>Dataset</th>
					<th>Size</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Total</td>
					<td>Proprietary MSRA DB</td>
					<td>35,932 expressions</td>
					<td>Written by 300 people</td>
			</tr>
			<tr>
					<td>Training</td>
					<td>Subset</td>
					<td>25,934 expressions</td>
					<td></td>
			</tr>
			<tr>
					<td>Testing</td>
					<td>Subset</td>
					<td>6,398 expressions</td>
					<td></td>
			</tr>
	</tbody>
</table>
<ul>
<li><strong>Content</strong>: 2,000 unique expressions from high school/college textbooks.</li>
<li><strong>Composition</strong>: ~25% of samples are organic expressions.</li>
<li><strong>Vocabulary</strong>: 163 symbol classes (elements, digits, <code>+</code>, <code>↑</code>, <code>%</code>, bonds, etc.).</li>
</ul>
<h3 id="algorithms">Algorithms</h3>
<p><strong>1. Symbol Grouping (Dynamic Programming)</strong></p>
<ul>
<li>Objective: Find the optimal symbol sequence $G_{max}$ maximizing the posterior probability given the ink strokes:
$$ G_{max} = \arg\max_{G} P(G | \text{Ink}) $$</li>
<li><strong>Non-symbol modeling</strong>: Iteratively trained models on &ldquo;incorrect grouping results&rdquo; to learn to reject invalid strokes.</li>
<li><strong>Inter-group modeling</strong>: Uses Gaussian Mixture Models (GMM) to model spatial relations ($R_j$) between groups.</li>
</ul>
<p><strong>2. Bond Processing</strong></p>
<ul>
<li><strong>Extended Bond Symbol</strong>: Recognizes connected strokes (e.g., a messy double bond written in one stroke) as a single &ldquo;extended&rdquo; symbol.</li>
<li><strong>Splitting</strong>: Uses <strong>Curvature Scale Space (CSS)</strong> corner detection to split extended symbols into primitive lines.</li>
<li><strong>Classification</strong>: A Neural Network verifies if the split lines form valid single, double, or triple bonds.</li>
</ul>
<p><strong>3. Structure Analysis (Graph Search)</strong></p>
<ul>
<li><strong>Graph Construction</strong>: Builds a Weighted Direction Graph ($G_{WD}$) where nodes are symbol candidates and edges are potential relationships ($E_{c}, E_{nc}, E_{peer}, E_{sub}$).</li>
<li><strong>Edge Weights</strong>: Calculated as the product of observation, spatial, and contextual probabilities:
$$ W(S, O, R) = P(O|S) \times P(\text{Spatial}|R) \times P(\text{Context}|S, R) $$
<ul>
<li>Spatial probability uses rectangular control regions and distance functions.</li>
<li>Contextual probability uses statistical co-occurrence (e.g., &lsquo;C&rsquo; often appears with &lsquo;H&rsquo;).</li>
</ul>
</li>
<li><strong>Search</strong>: Breadth-first search with pruning to find the top-N optimal CESGs.</li>
</ul>
<h3 id="models">Models</h3>
<ul>
<li><strong>Symbol Recognition</strong>: Implementation details not specified, but likely HMM or NN based on the era. Bond verification explicitly uses a <strong>Neural Network</strong>.</li>
<li><strong>Spatial Models</strong>: <strong>Gaussian Mixture Models (GMM)</strong> are used to model the 9 spatial relations (e.g., Left-super, Above, Subscript).</li>
<li><strong>Semantic Model</strong>: A <strong>Context-Free Grammar (CFG)</strong> parser is used for final verification (e.g., ensuring digits aren&rsquo;t reactants).</li>
</ul>
<h3 id="evaluation">Evaluation</h3>
<p>Evaluation is performed using &ldquo;Expression-level accuracy&rdquo;.</p>
<table>
	<thead>
			<tr>
					<th>Metric</th>
					<th>Value (Top-1)</th>
					<th>Value (Top-5)</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Full Framework</td>
					<td>75.4%</td>
					<td>83.1%</td>
					<td></td>
			</tr>
			<tr>
					<td>Without Semantics</td>
					<td>74.1%</td>
					<td>83.0%</td>
					<td></td>
			</tr>
			<tr>
					<td>Grouping Only</td>
					<td>85.9%</td>
					<td>95.6%</td>
					<td>Theoretical max if structure analysis was perfect</td>
			</tr>
	</tbody>
</table>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Chang, M., Han, S., &amp; Zhang, D. (2009). A Unified Framework for Recognizing Handwritten Chemical Expressions. <em>2009 10th International Conference on Document Analysis and Recognition</em>, 1345&ndash;1349. <a href="https://doi.org/10.1109/ICDAR.2009.64">https://doi.org/10.1109/ICDAR.2009.64</a></p>
<p><strong>Publication</strong>: ICDAR 2009</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@inproceedings</span>{changUnifiedFrameworkRecognizing2009,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span> = <span style="color:#e6db74">{A {{Unified Framework}} for {{Recognizing Handwritten Chemical Expressions}}}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">booktitle</span> = <span style="color:#e6db74">{2009 10th {{International Conference}} on {{Document Analysis}} and {{Recognition}}}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span> = <span style="color:#e6db74">{Chang, Ming and Han, Shi and Zhang, Dongmei}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span> = <span style="color:#ae81ff">2009</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">volume</span> = <span style="color:#e6db74">{3}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span> = <span style="color:#e6db74">{1345--1349}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">publisher</span> = <span style="color:#e6db74">{IEEE}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">address</span> = <span style="color:#e6db74">{Barcelona, Spain}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">doi</span> = <span style="color:#e6db74">{10.1109/ICDAR.2009.64}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>SVM-HMM Online Classifier for Chemical Symbols</title><link>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/online-recognition/zhang-svm-hmm-2010/</link><pubDate>Wed, 17 Dec 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/online-recognition/zhang-svm-hmm-2010/</guid><description>A dual-stage classifier combining SVM and HMM to recognize online handwritten chemical symbols, introducing a reordering algorithm for organic rings.</description><content:encoded><![CDATA[<h2 id="contribution-double-stage-classification-method">Contribution: Double-Stage Classification Method</h2>
<p><strong>Method</strong>.
This paper is a methodological contribution that proposes a novel &ldquo;double-stage classifier&rdquo; architecture. It fits the taxonomy by introducing a specific algorithmic pipeline (SVM rough classification followed by HMM fine classification) and a novel pre-processing algorithm (Point Sequence Reordering) to solve technical limitations in recognizing organic ring structures. The contribution is validated through ablation studies (comparing SVM kernels and HMM state/Gaussian counts) and performance benchmarks.</p>
<h2 id="motivation-recognizing-complex-organic-ring-structures">Motivation: Recognizing Complex Organic Ring Structures</h2>
<p>The primary motivation is the complexity of recognizing handwritten chemical symbols, specifically the distinction between <strong>Organic Ring Structures (ORS)</strong> and <strong>Non-Ring Structures (NRS)</strong>. Existing single-stage classifiers are unreliable for ORS because these symbols have arbitrary writing styles, variable stroke numbers, and inconsistent stroke orders due to their 2D hexagonal structure. A robust system is needed to handle this uncertainty and achieve high accuracy.</p>
<h2 id="core-innovation-point-sequence-reordering-psr">Core Innovation: Point Sequence Reordering (PSR)</h2>
<p>The authors introduce two main novelties:</p>
<ol>
<li><strong>Double-Stage Architecture</strong>: A hybrid system where an SVM (using RBF kernel) first roughly classifies inputs as either ORS or NRS, followed by specialized HMMs for fine-grained recognition.</li>
<li><strong>Point Sequence Reordering (PSR) Algorithm</strong>: A stroke-order independent algorithm designed specifically for ORS. It reorders the point sequence of a symbol based on a counter-clockwise scan from the centroid, effectively eliminating the uncertainty caused by variations in stroke number and writing order.</li>
</ol>
<h2 id="methodology--experimental-design">Methodology &amp; Experimental Design</h2>
<p>The authors collected a custom dataset and performed sequential optimizations:</p>
<ul>
<li><strong>SVM Optimization</strong>: Compared Polynomial, RBF, and Sigmoid kernels to find the best rough classifier.</li>
<li><strong>HMM Optimization</strong>: Tested multiple combinations of states (4, 6, 8) and Gaussians (3, 4, 6, 8, 9, 12) to maximize fine classification accuracy.</li>
<li><strong>PSR Validation</strong>: Conducted an ablation study comparing HMM accuracy on ORS symbols &ldquo;Before PSR&rdquo; vs &ldquo;After PSR&rdquo; to quantify the algorithm&rsquo;s impact.</li>
</ul>
<h2 id="results--final-conclusions">Results &amp; Final Conclusions</h2>
<ul>
<li><strong>Architecture Performance</strong>: The RBF-based SVM achieved 99.88% accuracy in differentiating ORS from NRS.</li>
<li><strong>HMM Configuration</strong>: The optimal HMM topology was found to be 8-states and 12-Gaussians for both symbol types.</li>
<li><strong>PSR Impact</strong>: The PSR algorithm improved ORS recognition. Top-1 accuracy shifted from <strong>49.84% (Before PSR)</strong> to <strong>98.36% (After PSR)</strong>.</li>
<li><strong>Overall Accuracy</strong>: The final integrated system achieved a Top-1 accuracy of <strong>93.10%</strong> and Top-3 accuracy of <strong>98.08%</strong> on the test set.</li>
</ul>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="data">Data</h3>
<p>The study defined 101 chemical symbols split into two categories.</p>
<table>
	<thead>
			<tr>
					<th>Category</th>
					<th>Count</th>
					<th>Content</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><strong>NRS</strong> (Non-Ring)</td>
					<td>63</td>
					<td>Digits 0-9, 44 letters, 9 operators</td>
					<td>Operators include +, -, =, $\rightarrow$, etc.</td>
			</tr>
			<tr>
					<td><strong>ORS</strong> (Organic Ring)</td>
					<td>38</td>
					<td>2D hexagonal structures</td>
					<td>Benzene rings, cyclohexane, etc.</td>
			</tr>
	</tbody>
</table>
<ul>
<li><strong>Collection</strong>: 12,322 total samples (122 per symbol) collected from 20 writers (teachers and students).</li>
<li><strong>Split</strong>: 9,090 training samples and 3,232 test samples.</li>
<li><strong>Constraints</strong>: Three specifications were used: normal, standard, and freestyle.</li>
</ul>
<h3 id="algorithms">Algorithms</h3>
<p><strong>1. SVM Feature Extraction (Rough Classification)</strong>
The input strokes are scaled, and a 58-dimensional feature vector is calculated:</p>
<ul>
<li><strong>Mesh ($4 \times 4$)</strong>: Ratio of points in 16 grids (16 features).</li>
<li><strong>Outline</strong>: Normalized scan distance from 4 edges with 5 scan lines each (20 features).</li>
<li><strong>Projection</strong>: Point density in 5 bins per edge (20 features).</li>
<li><strong>Aspect Ratio</strong>: Height/Width ratios (2 features).</li>
</ul>
<p><strong>2. Point Sequence Reordering (PSR)</strong>
Used strictly for ORS preprocessing:</p>
<ol>
<li>Calculate the centroid $(x_c, y_c)$ of the symbol.</li>
<li>Initialize a scan line at angle $\theta = 0$.</li>
<li>Traverse points; if a point $p_i = (x_i, y_i)$ satisfies the distance threshold to the scan line, add it to the reordered list. Distance $d_i$ is calculated as:
$$ d_i = |(y_i - y_c)\cos(\theta) - (x_i - x_c)\sin(\theta)| $$</li>
<li>Increment $\theta$ by $\Delta\theta$ and repeat until a full circle ($2\pi$) is completed.</li>
</ol>
<h3 id="models">Models</h3>
<ul>
<li><strong>SVM (Stage 1)</strong>: RBF Kernel was selected as optimal with parameters $C=512$ and $\gamma=0.5$.</li>
<li><strong>HMM (Stage 2)</strong>: Left-right continuous HMM trained via Baum-Welch algorithm. The topology is one model per symbol using <strong>8 states and 12 Gaussians</strong>.</li>
</ul>
<h3 id="evaluation">Evaluation</h3>
<p>Metrics reported are Top-1, Top-2, and Top-3 accuracy on the held-out test set.</p>
<table>
	<thead>
			<tr>
					<th>Metric</th>
					<th>NRS Accuracy</th>
					<th>ORS Accuracy</th>
					<th>Overall Test Accuracy</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><strong>Top-1</strong></td>
					<td>91.91%</td>
					<td>97.53%</td>
					<td>93.10%</td>
			</tr>
			<tr>
					<td><strong>Top-3</strong></td>
					<td>99.12%</td>
					<td>99.34%</td>
					<td>98.08%</td>
			</tr>
	</tbody>
</table>
<h3 id="hardware">Hardware</h3>
<ul>
<li><strong>Device</strong>: HP Pavilion tx1000 Tablet PC.</li>
<li><strong>Processor</strong>: 2.00GHz CPU.</li>
</ul>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Zhang, Y., Shi, G., &amp; Wang, K. (2010). A SVM-HMM Based Online Classifier for Handwritten Chemical Symbols. <em>2010 International Conference on Pattern Recognition</em>, 1888&ndash;1891. <a href="https://doi.org/10.1109/ICPR.2010.465">https://doi.org/10.1109/ICPR.2010.465</a></p>
<p><strong>Publication</strong>: ICPR 2010</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@inproceedings</span>{zhang2010svm,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span> = <span style="color:#e6db74">{A SVM-HMM Based Online Classifier for Handwritten Chemical Symbols}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">booktitle</span> = <span style="color:#e6db74">{2010 International Conference on Pattern Recognition}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span> = <span style="color:#e6db74">{Zhang, Yang and Shi, Guangshun and Wang, Kai}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span> = <span style="color:#e6db74">{2010}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span> = <span style="color:#e6db74">{1888--1891}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">publisher</span> = <span style="color:#e6db74">{IEEE}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">doi</span> = <span style="color:#e6db74">{10.1109/ICPR.2010.465}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Online Handwritten Chemical Formula Structure Analysis</title><link>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/online-recognition/wang-online-handwritten-2009/</link><pubDate>Wed, 17 Dec 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/online-recognition/wang-online-handwritten-2009/</guid><description>A hierarchical grammar-based approach for recognizing and analyzing online handwritten chemical formulas in mobile education contexts.</description><content:encoded><![CDATA[<h2 id="hierarchical-grammatical-framework-contribution">Hierarchical Grammatical Framework Contribution</h2>
<p>This is a <strong>Method</strong> paper. It proposes a novel architectural framework for processing chemical formulas by decomposing them into three hierarchical levels (Formula, Molecule, Text). The contribution is defined by a specific set of formal grammatical rules and parsing algorithms used to construct a &ldquo;grammar spanning tree&rdquo; and &ldquo;molecule spanning graph&rdquo; from online handwritten strokes.</p>
<h2 id="motivation-for-online-formula-recognition">Motivation for Online Formula Recognition</h2>
<p>The primary motivation is the application of mobile computing in chemistry education, where precise comprehension of casual, <em>online</em> handwritten formulas is a significant challenge.</p>
<ul>
<li><strong>2D Complexity</strong>: Unlike 1D text, chemical formulas utilize complex 2D spatial relationships that convey specific chemical meaning (e.g., bonds, rings).</li>
<li><strong>Format Limitations</strong>: Existing storage formats like CML (Chemical Markup Language) or MDL MOLFILE do not natively record the layout or abbreviated information necessary for recognizing handwritten input.</li>
<li><strong>Online Gap</strong>: Previous research focused heavily on <em>offline</em> (image-based) recognition, lacking solutions for <em>online</em> (stroke-based) handwritten chemical formulas (OHCF).</li>
</ul>
<h2 id="core-novelty-in-three-level-grammatical-analysis">Core Novelty in Three-Level Grammatical Analysis</h2>
<p>The core novelty is the <strong>Three-Level Grammatical Analysis</strong> approach:</p>
<ol>
<li><strong>Formula Level (1D)</strong>: Treats the reaction equation as a linear sequence of components (Reactants, Products, Separators), parsed via a context-free grammar to build a spanning tree.</li>
<li><strong>Molecule Level (2D)</strong>: Treats molecules as graphs where &ldquo;text groups&rdquo; are vertices and &ldquo;bonds&rdquo; are edges. It introduces specific handling for &ldquo;hidden Carbon dots&rdquo; (intersections of bonds without text).</li>
<li><strong>Text Level (1D)</strong>: Analyzes the internal structure of text groups (atoms, subscripts).</li>
</ol>
<p>Unique to this approach is the <strong>formal definition of the chemical grammar</strong> as a 5-tuple $G=(T,N,P,M,S)$ and the generation of an <strong>Adjacency Matrix</strong> directly from the handwritten sketch to represent chemical connectivity.</p>
<h2 id="experimental-validation-on-handwritten-strokes">Experimental Validation on Handwritten Strokes</h2>
<p>The authors validated their model using a custom dataset of online handwritten formulas.</p>
<ul>
<li><strong>Data Source</strong>: 25 formulas were randomly selected from a larger pool of 1,250 samples.</li>
<li><strong>Scope</strong>: The test set included 484 total symbols, comprising generators, separators, text symbols, rings, and various bond types.</li>
<li><strong>Granular Validation</strong>: The system was tested at multiple distinct stages:
<ul>
<li>Key Symbol Extraction (Formula Level)</li>
<li>Text Localization (Molecule Level)</li>
<li>Bond End Grouping (Molecule Level)</li>
<li>Text Recognition (Text Level)</li>
</ul>
</li>
</ul>
<h2 id="downstream-impact-and-parsing-accuracy">Downstream Impact and Parsing Accuracy</h2>
<p>The system achieved high accuracy across all sub-tasks, demonstrating that the hierarchical grammar approach is effective for both inorganic and organic formulas.</p>
<ul>
<li><strong>Formula Level</strong>: 98.3% accuracy for Key Symbols; 100% for State-assisted symbols.</li>
<li><strong>Molecule Level</strong>: 98.8% accuracy for Bond End Grouping; 100% for Free End-Text connection detection.</li>
<li><strong>Text Recognition</strong>: 98.7% accuracy (Top-3) using HMMs.</li>
<li><strong>Impact</strong>: The method successfully preserves the writer&rsquo;s &ldquo;online information&rdquo; (habits/intentions) while converting the handwritten input into standard formats suitable for visual editing or data retrieval.</li>
</ul>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<p>To replicate this work, one would need to implement the specific grammatical production rules and the geometric thresholds defined for bond analysis.</p>
<h3 id="data">Data</h3>
<table>
	<thead>
			<tr>
					<th>Purpose</th>
					<th>Dataset</th>
					<th>Size</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><strong>Training</strong></td>
					<td>Symbol HMMs</td>
					<td>5,670 samples</td>
					<td>Used to train the text recognition module</td>
			</tr>
			<tr>
					<td><strong>Testing</strong></td>
					<td>Text Recognition</td>
					<td>2,016 samples</td>
					<td>Test set for character HMMs</td>
			</tr>
			<tr>
					<td><strong>Testing</strong></td>
					<td>Formula Analysis</td>
					<td>25 formulas</td>
					<td>Random subset of 1,250 collected samples; contains 484 symbols</td>
			</tr>
	</tbody>
</table>
<h3 id="algorithms">Algorithms</h3>
<p><strong>1. Formula Level Parsing</strong></p>
<ul>
<li><strong>HBL Analysis</strong>: Identify the &ldquo;Horizontal Baseline&rdquo; (HBL) containing the most symbols to locate key operators (e.g., $+$, $\rightarrow$).</li>
<li><strong>Grammar</strong>: Use the productions defined in Figure 4. Example rules include:
<ul>
<li>$Reaction ::= ReactantList \ Generator \ ProductList$</li>
<li>$Reactant ::= BalancingNum \ Molecule \ IonicCharacter$</li>
</ul>
</li>
</ul>
<p><strong>2. Molecule Level Analysis (Bond Grouping)</strong></p>
<ul>
<li><strong>Endpoint Classification</strong>: Points are classified as <em>free ends</em>, <em>junctions</em> (3+ bonds), or <em>connections</em> (2 bonds).</li>
<li><strong>Grouping Equation</strong>: An endpoint $(x_k, y_k)$ belongs to Group A based on distance thresholding:
$$
\begin{aligned}
Include(x_0, y_0) = \begin{cases} 1, &amp; d_0 &lt; t \cdot \max d_x + \partial \\ 0, &amp; \text{else} \end{cases}
\end{aligned}
$$
Where $d_k$ is the Euclidean distance to the group center $(x_a, y_a)$.</li>
</ul>
<p><strong>3. Connection Detection</strong></p>
<ul>
<li><strong>Text-Bond Connection</strong>: A text group is connected to a bond if the free end falls within a bounding box expanded by thresholds $t_W$ and $t_H$:
$$
\begin{aligned}
Con(x,y) = \begin{cases} 1, &amp; \min x - t_W &lt; x &lt; \max x + t_W \text{ AND } \min y - t_H &lt; y &lt; \max y + t_H \\ 0, &amp; \text{else} \end{cases}
\end{aligned}
$$</li>
</ul>
<h3 id="models">Models</h3>
<ul>
<li><strong>Text Recognition</strong>: Hidden Markov Models (HMM) are used for recognizing individual text symbols.</li>
<li><strong>Grammar</strong>: Context-Free Grammar (CFG) designed with ambiguity elimination to ensure a single valid parse tree for any valid formula.</li>
</ul>
<h3 id="evaluation">Evaluation</h3>
<p>Performance is measured by recognition accuracy at specific processing stages:</p>
<table>
	<thead>
			<tr>
					<th>Metric</th>
					<th>Task</th>
					<th>Value</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Accuracy</td>
					<td>F1 (Key Symbol Extraction)</td>
					<td>98.3%</td>
					<td>Formula Level</td>
			</tr>
			<tr>
					<td>Accuracy</td>
					<td>F2 (State-assisted Symbol)</td>
					<td>100%</td>
					<td>Formula Level</td>
			</tr>
			<tr>
					<td>Accuracy</td>
					<td>M2 (Bond End Grouping)</td>
					<td>98.8%</td>
					<td>Molecule Level</td>
			</tr>
			<tr>
					<td>Accuracy</td>
					<td>M3 (Free End-Text Conn)</td>
					<td>100%</td>
					<td>Molecule Level</td>
			</tr>
			<tr>
					<td>Accuracy</td>
					<td>T1 (Text Recognition)</td>
					<td>98.7%</td>
					<td>Top-3 Accuracy</td>
			</tr>
	</tbody>
</table>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Wang, X., Shi, G., &amp; Yang, J. (2009). The Understanding and Structure Analyzing for Online Handwritten Chemical Formulas. <em>2009 10th International Conference on Document Analysis and Recognition</em>, 1056&ndash;1060. <a href="https://doi.org/10.1109/ICDAR.2009.70">https://doi.org/10.1109/ICDAR.2009.70</a></p>
<p><strong>Publication</strong>: ICDAR 2009</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@inproceedings</span>{wangUnderstandingStructureAnalyzing2009,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span> = <span style="color:#e6db74">{The {{Understanding}} and {{Structure Analyzing}} for {{Online Handwritten Chemical Formulas}}}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">booktitle</span> = <span style="color:#e6db74">{2009 10th {{International Conference}} on {{Document Analysis}} and {{Recognition}}}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span> = <span style="color:#e6db74">{Wang, Xin and Shi, Guangshun and Yang, Jufeng}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span> = <span style="color:#e6db74">{2009}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span> = <span style="color:#e6db74">{1056--1060}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">publisher</span> = <span style="color:#e6db74">{IEEE}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">address</span> = <span style="color:#e6db74">{Barcelona, Spain}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">doi</span> = <span style="color:#e6db74">{10.1109/ICDAR.2009.70}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">isbn</span> = <span style="color:#e6db74">{978-1-4244-4500-4}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">langid</span> = <span style="color:#e6db74">{english}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Chemical Structure Reconstruction with chemoCR (2011)</title><link>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/benchmarks/chemocr-trec-2011/</link><pubDate>Tue, 16 Dec 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/benchmarks/chemocr-trec-2011/</guid><description>A hybrid system combining pattern recognition and rule-based expert systems to reconstruct chemical structures from bitmap images.</description><content:encoded><![CDATA[<h2 id="contribution-the-chemocr-architecture">Contribution: The chemoCR Architecture</h2>
<p><strong>Methodological Paper ($\Psi_{\text{Method}}$)</strong></p>
<p>This paper focuses entirely on the architecture and workflow of the <strong>chemoCR</strong> system. It proposes specific algorithmic innovations (texture-based vectorization, graph constraint exploration) and defines a comprehensive pipeline for converting raster images into semantic chemical graphs. The primary contribution is the system design and its operational efficacy.</p>
<h2 id="motivation-digitizing-image-locked-chemical-structures">Motivation: Digitizing Image-Locked Chemical Structures</h2>
<p>Chemical structures are the preferred language of chemistry, yet they are frequently locked in non-machine-readable formats (bitmap images like GIF, BMP) within patents and journals.</p>
<ul>
<li><strong>The Problem:</strong> Once published as images, chemical structure information is &ldquo;dead&rdquo; to analysis software.</li>
<li><strong>The Gap:</strong> Manual reconstruction is slow and error-prone. Existing tools struggled with the diversity of drawing styles (e.g., varying line thickness, font types, and non-standard bond representations).</li>
<li><strong>The Goal:</strong> To automate the conversion of these depictions into connection tables (SDF/MOL files) to make the data accessible for computational chemistry applications.</li>
</ul>
<h2 id="core-innovation-rule-based-semantic-object-identification">Core Innovation: Rule-Based Semantic Object Identification</h2>
<p>The system is based on a &ldquo;Semantic Entity&rdquo; approach that identifies chemically significant objects (chiral bonds, superatoms, reaction arrows) from structural formula depictions. Key technical innovations include:</p>
<ol>
<li><strong>Texture-based Vectorization:</strong> A new algorithm that computes local directions to vectorize lines, robust against varying drawing styles.</li>
<li><strong>Expert System Integration:</strong> A graph constraint exploration algorithm that applies an XML-based rule set to classify geometric primitives into chemical classes such as <code>BOND</code>, <code>DOUBLEBOND</code>, <code>TRIPLEBOND</code>, <code>BONDSET</code>, <code>DOTTED CHIRAL</code>, <code>STRINGASSOCIATION</code>, <code>DOT</code>, <code>RADICAL</code>, <code>REACTION</code>, <code>REACTION ARROW</code>, <code>REACTION PLUS</code>, <code>CHARGE</code>, and <code>UNKNOWN</code>.</li>
<li><strong>Validation Scoring:</strong> A built-in validation module that tests valences, bond lengths and angles, typical atom types, and fragments to assign a confidence score (0 to 1) to the reconstruction.</li>
</ol>
<h2 id="experiments-the-trec-2011-image-to-structure-task">Experiments: The TREC 2011 Image-to-Structure Task</h2>
<p>The system was evaluated as part of the <strong>TREC 2011 Image-to-Structure (I2S) Task</strong>.</p>
<ul>
<li><strong>Dataset:</strong> 1,000 unique chemical structure images provided by USPTO.</li>
<li><strong>Configuration:</strong> The authors used chemoCR v0.93 in batch mode with a single pre-configured parameter set (&ldquo;Houben-Weyl&rdquo;), originally developed for the Houben-Weyl book series of organic chemistry reactions published by Thieme.</li>
<li><strong>Process:</strong> The workflow included image binarization, connected component analysis, OCR for atom labels, and final molecule assembly.</li>
<li><strong>Metric:</strong> Perfect match recall against ground-truth MOL files.</li>
</ul>
<h2 id="results-and-conclusions-expert-systems-vs-dirty-data">Results and Conclusions: Expert Systems vs. &ldquo;Dirty&rdquo; Data</h2>
<ul>
<li><strong>Performance:</strong> The system achieved a <strong>perfect match for 656 out of 1,000 structures (65.6%)</strong>.</li>
<li><strong>Error Analysis:</strong> Failures were primarily attributed to &ldquo;unclear semantics&rdquo; in drawing styles, such as:
<ul>
<li>Overlapping objects (e.g., atom labels clashing with bonds).</li>
<li>Ambiguous primitives (dots interpreted as both radicals and chiral centers).</li>
<li>Markush structures (variable groups), which were excluded from the I2S task definition. A prototype for Markush detection existed but was not used.</li>
</ul>
</li>
<li><strong>Limitations:</strong> The vectorizer cannot recognize curves and circles, only straight lines. Aromatic ring detection (via a heuristic that looks for a large &ldquo;O&rdquo; character in the center of a ring system) was switched off for the I2S task. The system maintained 12 different parameter sets for various drawing styles, and selecting the correct set was critical.</li>
<li><strong>Impact:</strong> Demonstrated that rule-based expert systems combined with standard pattern recognition could handle high-quality datasets effectively, though non-standard drawing styles remain a challenge.</li>
</ul>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="data">Data</h3>
<p>The paper relies on the TREC 2011 I2S dataset, comprising images extracted from USPTO patents.</p>
<table>
	<thead>
			<tr>
					<th>Purpose</th>
					<th>Dataset</th>
					<th>Size</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Evaluation</td>
					<td>TREC 2011 I2S</td>
					<td>1,000 images</td>
					<td>Binarized bitmaps from USPTO patents.</td>
			</tr>
			<tr>
					<td>Training</td>
					<td>Internal Training Set</td>
					<td>Unknown</td>
					<td>Used to optimize parameter sets (e.g., &ldquo;Houben-Weyl&rdquo; set).</td>
			</tr>
	</tbody>
</table>
<h3 id="algorithms">Algorithms</h3>
<p>The paper describes three main workflow phases (preprocessing, semantic entity recognition, and molecule reconstruction plus validation), organized into four pipeline sections:</p>
<ol>
<li>
<p><strong>Preprocessing:</strong></p>
<ul>
<li><em>Vaporizer Unit:</em> Erases parts of the image that are presumably not structure diagrams (e.g., text or other human-readable information), isolating the chemical depictions.</li>
<li><em>Connected Components:</em> Groups all foreground pixels that are 8-connected into components.</li>
<li><em>Text Tagging and OCR:</em> Identifies components that map to text areas and converts bitmap letters into characters.</li>
</ul>
</li>
<li>
<p><strong>Vectorization:</strong></p>
<ul>
<li><em>Algorithm:</em> <strong>Compute Local Directions</strong>. It analyzes segment clusters to detect ascending, descending, horizontal, and vertical trends in pixel data, converting them into vectors.</li>
<li><em>Feature:</em> Explicitly handles &ldquo;thick chirals&rdquo; (wedges) by computing orientation.</li>
</ul>
</li>
<li>
<p><strong>Reconstruction (Expert System):</strong></p>
<ul>
<li><em>Core Logic:</em> <strong>Graph Constraint Exploration</strong>. It visits connected components and evaluates them against an XML Rule Set.</li>
<li><em>Classification:</em> Objects are tagged with chemical keywords (e.g., <code>BONDSET</code> for ring systems and chains, <code>STRINGASSOCIATION</code> for atom labels, <code>DOTTED CHIRAL</code> for chiral bonds).</li>
<li><em>Rules:</em> Configurable via <code>chemoCRSettings.xml</code>. The successful rule with the highest priority value defines the annotation for each component.</li>
</ul>
</li>
<li>
<p><strong>Assembly &amp; Validation:</strong></p>
<ul>
<li>Combines classified vectors and OCR text into a semantic graph.</li>
<li><em>Superatoms:</em> Matches text groups against a loaded superatom database (e.g., &ldquo;COOH&rdquo;, &ldquo;Boc&rdquo;).</li>
<li><em>Validation:</em> Calculates a score (0-1) based on chemical feasibility (valences, bond lengths and angles, typical atom types, and fragments).</li>
</ul>
</li>
</ol>
<h3 id="models">Models</h3>
<p>The system is primarily rule-based but utilizes machine learning components for specific sub-tasks:</p>
<ul>
<li><strong>OCR:</strong> A trainable OCR module using supervised machine learning to recognize atom labels ($H, C, N, O$). The specific classifier is not detailed in the paper.</li>
<li><strong>Rule Base:</strong> An XML file containing the expert system logic. This is the &ldquo;model&rdquo; for structural interpretation.</li>
</ul>
<h3 id="evaluation">Evaluation</h3>
<p>Evaluation was performed strictly within the context of the TREC competition.</p>
<table>
	<thead>
			<tr>
					<th>Metric</th>
					<th>Value</th>
					<th>Baseline</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Recall (Perfect Match)</td>
					<td>656 / 1000</td>
					<td>N/A</td>
					<td>Strict structural identity required.</td>
			</tr>
	</tbody>
</table>
<h3 id="hardware">Hardware</h3>
<ul>
<li><strong>Software Stack:</strong> Platform-independent JAVA libraries.</li>
<li><strong>Compute:</strong> Batch mode processing supported; specific hardware requirements (CPU/RAM) were not disclosed.</li>
</ul>
<h3 id="artifacts">Artifacts</h3>
<table>
	<thead>
			<tr>
					<th>Artifact</th>
					<th>Type</th>
					<th>License</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>chemoCR (Fraunhofer SCAI)</td>
					<td>Software</td>
					<td>Unknown</td>
					<td>Project page defunct; tool was proprietary</td>
			</tr>
			<tr>
					<td><a href="https://trec.nist.gov/pubs/trec20/papers/chemoCR.chem.update.pdf">TREC 2011 Proceedings Paper</a></td>
					<td>Paper</td>
					<td>Public</td>
					<td>Official NIST proceedings</td>
			</tr>
	</tbody>
</table>
<p>No source code was publicly released. The chemoCR system was a proprietary tool from Fraunhofer SCAI. The TREC 2011 I2S dataset was distributed to competition participants and is not independently hosted.</p>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Zimmermann, M. (2011). Chemical Structure Reconstruction with chemoCR. <em>TREC 2011 Proceedings</em>.</p>
<p><strong>Publication</strong>: Text REtrieval Conference (TREC) 2011</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@inproceedings</span>{zimmermannChemicalStructureReconstruction2011,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span> = <span style="color:#e6db74">{Chemical Structure Reconstruction with {{chemoCR}}}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">booktitle</span> = <span style="color:#e6db74">{Text {{REtrieval Conference}} ({{TREC}}) 2011}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span> = <span style="color:#e6db74">{Zimmermann, Marc}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span> = <span style="color:#e6db74">{2011}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">langid</span> = <span style="color:#e6db74">{english}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Structural Analysis of Handwritten Chemical Formulas</title><link>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/hand-drawn/ramel-handwritten-1999/</link><pubDate>Mon, 15 Dec 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/hand-drawn/ramel-handwritten-1999/</guid><description>A 1999 methodology for recognizing handwritten chemical structures using a structural graph representation and recursive specialists.</description><content:encoded><![CDATA[<h2 id="contribution-structural-approach-to-document-analysis">Contribution: Structural Approach to Document Analysis</h2>
<p><strong>Method</strong>.
This paper proposes a system architecture for document analysis. It introduces a specific pipeline (Global Perception followed by Incremental Extraction) and validates this strategy with recognition rates on specific tasks. The core contribution is the shift from bitmap-based processing to a <strong>structural graph representation</strong> of graphical primitives.</p>
<h2 id="motivation-overcoming-bitmap-limitations-in-freehand-drawings">Motivation: Overcoming Bitmap Limitations in Freehand Drawings</h2>
<ul>
<li><strong>Complexity of Freehand</strong>: Freehand drawings contain fluctuating lines and noise that make standard vectorization techniques difficult to apply directly.</li>
<li><strong>Limitation of Bitmap Analysis</strong>: Most existing systems at the time attempted to interpret the document by working directly on the static bitmap image throughout the process.</li>
<li><strong>Need for Context</strong>: Interpretation requires a dynamic resource that can evolve as knowledge is extracted (e.g., recognizing a polygon changes the context for its neighbors).</li>
</ul>
<h2 id="novelty-dynamic-structural-graphs-and-recursive-specialists">Novelty: Dynamic Structural Graphs and Recursive Specialists</h2>
<p>The authors propose a <strong>Structural Representation</strong> as the unique resource for interpretation.</p>
<ul>
<li><strong>Quadrilateral Primitives</strong>: The system builds Quadrilaterals (pairs of vectors) to represent thin shapes, which are robust to handwriting fluctuations.</li>
<li><strong>Structural Graph</strong>: These primitives are organized into a graph where arcs represent geometric relationships (T-junctions, L-junctions, parallels).</li>
<li><strong>Specialist Agents</strong>: Interpretation is driven by independent modules (specialists) that browse this graph recursively to identify high-level chemical entities like rings (polygons) or chains.</li>
</ul>
<h2 id="experimental-setup-and-outcomes">Experimental Setup and Outcomes</h2>
<ul>
<li><strong>Validation Set</strong>: The system was tested on 20 handwritten off-line documents containing chemical formulas at 300 dpi resolution.</li>
<li><strong>Text Database</strong>: A separate base of 328 models was used for the text recognition component.</li>
<li><strong>High Graphical Accuracy</strong>: The system achieved a $\approx 97%$ recognition rate for graphical parts (chemical elements like rings and bonds).</li>
<li><strong>Text Recognition</strong>: The text recognition module achieved a $\approx 93%$ success rate.</li>
<li><strong>Robustness</strong>: The structural graph approach successfully handled multiple liaisons, polygons, chains and allowed for the progressive construction of a solution consistent with the context.</li>
</ul>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="data">Data</h3>
<table>
	<thead>
			<tr>
					<th>Purpose</th>
					<th>Dataset</th>
					<th>Size</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Evaluation</td>
					<td>Handwritten Documents</td>
					<td>20 docs</td>
					<td>Off-line documents at 300 dpi</td>
			</tr>
			<tr>
					<td>Training</td>
					<td>Character Models</td>
					<td>328 models</td>
					<td>Used for the Pattern Matching text recognition base</td>
			</tr>
	</tbody>
</table>
<h3 id="algorithms">Algorithms</h3>
<p>The interpretation process is divided into two distinct phases:</p>
<p><strong>1. Global Perception (Graph Construction)</strong></p>
<ul>
<li><strong>Vectorization</strong>: Contour tracking produces a chain of vectors, which are simplified via iterative polygonal approximation until fusion stabilizes (2-5 iterations).</li>
<li><strong>Quadrilateral Formation</strong>: Vectors are paired to form quadrilaterals based on Euclidean distance and &ldquo;empirical&rdquo; alignment criteria.</li>
<li><strong>Graph Generation</strong>: Quadrilaterals become nodes. Arcs are created based on &ldquo;zones of influence&rdquo; and classified into 5 types: T-junction, Intersection (X), Parallel (//), L-junction, and Successive (S).</li>
<li><strong>Redraw Heuristic</strong>: A pre-processing step transforms T, X, and S junctions into L or // relations, as chemical drawings primarily consist of L-junctions and parallels.</li>
</ul>
<p><strong>2. Specialists (Interpretation)</strong></p>
<ul>
<li><strong>Liaison Specialist</strong>: Scans the graph for // arcs or quadrilaterals with free extremities to identify bonds.</li>
<li><strong>Polygon/Chain Specialist</strong>: Uses recursive <code>look-left</code> and <code>look-right</code> procedures. If a search returns to the start node after $n$ steps, a polygon is detected.</li>
<li><strong>Text Localization</strong>: Clusters &ldquo;short&rdquo; quadrilaterals by physical proximity into &ldquo;focus zones&rdquo;. Zones are classified as text/non-text based on connected components.</li>
</ul>
<h3 id="models">Models</h3>
<p><strong>Text Recognition Hybrid</strong>:</p>
<ol>
<li><strong>Normalization &amp; Pattern Matching</strong>: A classic method using the database of 328 models.</li>
<li><strong>Structural Rule Base</strong>: Uses &ldquo;significant&rdquo; quadrilaterals (length $\ge 1/3$ of zone dimension) to verify characters. A rule base defines the expected count of horizontal, vertical, right-diagonal, and left-diagonal lines for each character.</li>
</ol>
<h3 id="evaluation">Evaluation</h3>
<table>
	<thead>
			<tr>
					<th>Metric</th>
					<th>Value</th>
					<th>Baseline</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Graphical Element Recognition</td>
					<td>~97%</td>
					<td>N/A</td>
					<td>Evaluated on 20 documents (Fig. 7 examples)</td>
			</tr>
			<tr>
					<td>Text Recognition</td>
					<td>~93%</td>
					<td>N/A</td>
					<td>Evaluated on 20 documents</td>
			</tr>
	</tbody>
</table>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Ramel, J.-Y., Boissier, G., &amp; Emptoz, H. (1999). Automatic Reading of Handwritten Chemical Formulas from a Structural Representation of the Image. <em>Proceedings of the Fifth International Conference on Document Analysis and Recognition (ICDAR &lsquo;99)</em>, 83-86. <a href="https://doi.org/10.1109/ICDAR.1999.791730">https://doi.org/10.1109/ICDAR.1999.791730</a></p>
<p><strong>Publication</strong>: ICDAR 1999</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@inproceedings</span>{ramelAutomaticReadingHandwritten1999,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span> = <span style="color:#e6db74">{Automatic Reading of Handwritten Chemical Formulas from a Structural Representation of the Image}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">booktitle</span> = <span style="color:#e6db74">{Proceedings of the {{Fifth International Conference}} on {{Document Analysis}} and {{Recognition}}. {{ICDAR}} &#39;99 ({{Cat}}. {{No}}.{{PR00318}})}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span> = <span style="color:#e6db74">{Ramel, J.-Y. and Boissier, G. and Emptoz, H.}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span> = <span style="color:#ae81ff">1999</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span> = <span style="color:#e6db74">{83--86}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">publisher</span> = <span style="color:#e6db74">{IEEE}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">address</span> = <span style="color:#e6db74">{Bangalore, India}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">doi</span> = <span style="color:#e6db74">{10.1109/ICDAR.1999.791730}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">isbn</span> = <span style="color:#e6db74">{978-0-7695-0318-9}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Imago: Open-Source Chemical Structure Recognition (2011)</title><link>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/benchmarks/imago-trec-2011/</link><pubDate>Mon, 15 Dec 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/benchmarks/imago-trec-2011/</guid><description>Open-source C++ toolkit for extracting 2D chemical structures from scientific literature using heuristic image processing methods.</description><content:encoded><![CDATA[<h2 id="paper-contribution-and-resource-utility">Paper Contribution and Resource Utility</h2>
<p>This is primarily a <strong>Resource ($\Psi_{\text{Resource}}$)</strong> paper, with a secondary <strong>Method ($\Psi_{\text{Method}}$)</strong> component.</p>
<p><strong>Resource:</strong> The paper&rsquo;s main contribution is the release of the &ldquo;Imago&rdquo; open-source toolkit. It emphasizes infrastructure utility: cross-platform C++ implementation, a core written from scratch without third-party code, and the inclusion of both GUI and command-line tools.</p>
<p><strong>Method:</strong> It provides a detailed description of the recognition pipeline (filtering, segmentation, vectorization) to document the resource.</p>
<h2 id="motivation-the-deep-web-of-chemical-structures">Motivation: The Deep Web of Chemical Structures</h2>
<p>Chemical databases (like PubChem or PubMed) allow text and substructure searches, but a vast amount of chemical data remains &ldquo;locked&rdquo; in the images of scientific articles and patents. This is described as a &ldquo;Deep Web indexing problem&rdquo;. To bridge this gap, the authors identify a need for efficient, accurate, and portable algorithms to convert 2D raster images of molecules into graph representations suitable for indexing and search.</p>
<h2 id="core-innovation-a-dependency-free-c-architecture">Core Innovation: A Dependency-Free C++ Architecture</h2>
<p>The novelty lies in the <strong>open-source, dependency-free implementation</strong>.</p>
<p><strong>Portability:</strong> The core of the toolkit is written from scratch in modern C++ without third-party libraries, specifically targeting portability to mobile devices and various platforms.</p>
<p><strong>Integration:</strong> It combines optical character recognition (OCR) with specific chemical heuristics (like identifying stereochemistry and abbreviations) into a single usable workflow.</p>
<h2 id="methodology-and-experimental-validation-at-trec-chem">Methodology and Experimental Validation at TREC-CHEM</h2>
<p>The paper describes the algorithm used in Imago and reflects on its participation in the <strong>Image2Structure task at TREC-CHEM 2011</strong>. No quantitative results are reported; the &ldquo;Discussion&rdquo; section instead reflects on qualitative performance issues observed during the task, such as handling low resolution, noise, and connected atom labels.</p>
<h2 id="outcomes-limitations-and-future-directions">Outcomes, Limitations, and Future Directions</h2>
<p><strong>Release:</strong> The authors successfully released Imago under the GPLv3 license, including an API for developers. The toolkit outputs recognized structures in MDL Molfile format.</p>
<p><strong>Limitations Identified:</strong> The straightforward pipeline fails when images have low resolution (atom labels merge with bonds), high noise, or tight character spacing (symbols rendered without space pixels between them). Additionally, when few symbols are present, the average bond length estimate can have large error, causing atom symbols to be misidentified as bond chains.</p>
<p><strong>Future Directions:</strong> The authors propose moving from a linear pipeline to an &ldquo;optimization procedure&rdquo; that maximizes a confidence score, using probabilistic mapping of image primitives to chemical entities. They also argue that recognition programs should output a confidence score to enable automatic batch processing (only images with low confidence need manual review). They suggest a multi-pass workflow where each iteration adjusts parameters to improve the confidence level, and they note the additional challenge of separating molecule images from text in real articles and patents.</p>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="data">Data</h3>
<p>The paper does not specify a training dataset for the core logic (which appears heuristic-based), but references testing context:</p>
<ul>
<li><strong>Domain:</strong> Images from scientific articles and patents.</li>
<li><strong>Validation:</strong> TREC-CHEM 2011 Image2Structure task data.</li>
<li><strong>Databases:</strong> Mentions PubMed and PubChem as context for the type of data being indexed.</li>
</ul>
<h3 id="algorithms">Algorithms</h3>
<p>The recognition pipeline follows a strict linear sequence:</p>
<ol>
<li>
<p><strong>Preprocessing:</strong></p>
<ul>
<li><strong>Binarization:</strong> Threshold-based.</li>
<li><strong>Supersegmentation:</strong> Locates the chemical structure using a $15 \times 15$ window neighbor search.</li>
<li><strong>Filtering:</strong> Removes single-down stereo bonds (dashed triangles) early to prevent incorrect recognition of the small line segments during classification.</li>
</ul>
</li>
<li>
<p><strong>Separation (Symbols vs. Graphics):</strong></p>
<ul>
<li><strong>Heuristic:</strong> Estimates &ldquo;capital letter height&rdquo;.</li>
<li><strong>Criteria:</strong> Groups segments by height and aspect ratio range $[\text{MinSymRatio}, \text{MaxSymRatio}]$.</li>
</ul>
</li>
<li>
<p><strong>Skeleton Construction (Vectorization):</strong></p>
<ul>
<li><strong>Thinning:</strong> Uses neighborhood maps to reduce lines to 1-pixel thickness.</li>
<li><strong>De-crossing:</strong> Each black pixel with more than 2 black pixels in its 8-neighborhood becomes white, isolating polylines.</li>
<li><strong>Smoothing:</strong> Uses the <strong>Douglas-Peucker algorithm</strong>.</li>
<li><strong>Graph Adjustment:</strong> Merges close vertices and detects bond orders based on parallel edges.</li>
</ul>
</li>
<li>
<p><strong>Symbol Recognition:</strong></p>
<ul>
<li><strong>Grouping:</strong> Uses a <strong>Relative Neighborhood Graph</strong> to group characters into superatoms/labels.</li>
<li><strong>OCR:</strong> Classification based on <strong>Fourier descriptors</strong> of outer/inner contours.</li>
</ul>
</li>
<li>
<p><strong>Chemical Expansion:</strong></p>
<ul>
<li><strong>Abbreviation:</strong> Expands common groups (e.g., Ph, COOH) stored as SMILES notation, using the <strong>Indigo toolkit</strong> for 2D coordinate generation of the expanded structures.</li>
</ul>
</li>
</ol>
<h3 id="models">Models</h3>
<ul>
<li><strong>Type:</strong> Heuristic-based computer vision pipeline; no learned deep learning weights mentioned.</li>
<li><strong>Stereo Recognition:</strong>
<ul>
<li><strong>Single Down:</strong> Identified as $k \ge 3$ parallel equidistant lines.</li>
<li><strong>Single Up:</strong> Identified by checking if a bond was a solid triangle before thinning.</li>
</ul>
</li>
</ul>
<h3 id="evaluation">Evaluation</h3>
<ul>
<li><strong>Metrics:</strong> None quantitatively reported in the text; discussion focuses on qualitative failure modes (low resolution, noise).</li>
</ul>
<h3 id="artifacts">Artifacts</h3>
<table>
	<thead>
			<tr>
					<th>Artifact</th>
					<th>Type</th>
					<th>License</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><a href="https://github.com/epam/Imago">Imago GitHub Repository</a></td>
					<td>Code</td>
					<td>Apache-2.0 (current); GPLv3 (as published)</td>
					<td>Official C++ implementation</td>
			</tr>
			<tr>
					<td><a href="https://lifescience.opensource.epam.com/imago/">Imago Project Page</a></td>
					<td>Other</td>
					<td>N/A</td>
					<td>Documentation and downloads</td>
			</tr>
	</tbody>
</table>
<h3 id="hardware">Hardware</h3>
<ul>
<li><strong>Requirements:</strong> Designed to be lightweight and portable (mobile-device capable), written in C++. No specific GPU/TPU requirements.</li>
</ul>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Smolov, V., Zentsev, F., &amp; Rybalkin, M. (2011). Imago: Open-Source Toolkit for 2D Chemical Structure Image Recognition. <em>TREC-CHEM 2011</em>.</p>
<p><strong>Publication</strong>: TREC-CHEM 2011</p>
<p><strong>Additional Resources</strong>:</p>
<ul>
<li><a href="https://trec.nist.gov/pubs/trec20/t20.proceedings.html">TREC-CHEM 2011 Proceedings</a></li>
<li><a href="https://lifescience.opensource.epam.com/imago/">Project Website</a></li>
<li><a href="https://github.com/epam/Imago">GitHub Repository</a></li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@techreport</span>{smolovImagoOpenSourceToolkit2011,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span> = <span style="color:#e6db74">{Imago: {{Open-Source Toolkit}} for {{2D Chemical Structure Image Recognition}}}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span> = <span style="color:#e6db74">{Smolov, Viktor and Zentsev, Fedor and Rybalkin, Mikhail}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span> = <span style="color:#e6db74">{2011}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">institution</span> = <span style="color:#e6db74">{{GGA Software Services LLC}}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">note</span> = <span style="color:#e6db74">{TREC-CHEM 2011}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>CLiDE Pro: Optical Chemical Structure Recognition Tool</title><link>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/rule-based/clide-pro-2009/</link><pubDate>Mon, 15 Dec 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/rule-based/clide-pro-2009/</guid><description>A methodological paper presenting CLiDE Pro, an OCSR system for reconstructing chemical graphs from images with ~90% accuracy.</description><content:encoded><![CDATA[<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Valko, A. T., &amp; Johnson, A. P. (2009). CLiDE Pro: The Latest Generation of CLiDE, a Tool for Optical Chemical Structure Recognition. <em>Journal of Chemical Information and Modeling</em>, 49(4), 780-787. <a href="https://doi.org/10.1021/ci800449t">https://doi.org/10.1021/ci800449t</a></p>
<p><strong>Publication</strong>: Journal of Chemical Information and Modeling 2009</p>
<h2 id="contribution-robust-algorithmic-pipeline-for-ocsr">Contribution: Robust Algorithmic Pipeline for OCSR</h2>
<p>This is primarily a <strong>Method ($\Psi_{\text{Method}}$)</strong> paper, as it proposes a specific algorithmic architecture (CLiDE Pro) for converting raster images of chemical structures into connection tables. It details the procedural steps for segmentation, vectorization, and graph reconstruction.</p>
<p>It also has a secondary <strong>Resource ($\Psi_{\text{Resource}}$)</strong> contribution, as the authors compile and release a validation set of 454 real-world images to serve as a community benchmark for OCSR systems.</p>
<h2 id="motivation-bridging-the-gap-between-legacy-document-images-and-machine-readable-chemistry">Motivation: Bridging the Gap Between Legacy Document Images and Machine-Readable Chemistry</h2>
<p>While modern chemical drawing software captures structural information explicitly, the vast majority of legacy and current chemical literature (journals, patents, reports) exists as images or PDF documents. These images are human-readable but lack the semantic &ldquo;connection table&rdquo; data required for chemical databases and software. Manual redrawing is time-consuming and error-prone. Therefore, there is a critical need for efficient Optical Chemical Structure Recognition (OCSR) systems to automate this extraction.</p>
<h2 id="novelty-integrated-document-segmentation-and-ambiguity-resolution-heuristics">Novelty: Integrated Document Segmentation and Ambiguity Resolution Heuristics</h2>
<p>CLiDE Pro introduces several algorithmic improvements over its predecessor (CLiDE) and contemporary tools:</p>
<ul>
<li><strong>Integrated Document Segmentation</strong>: Unlike page-oriented systems, it processes whole documents to link information across pages.</li>
<li><strong>Robust &ldquo;Difficult Feature&rdquo; Handling</strong>: It implements specific heuristic rules to resolve ambiguities in crossing bonds (bridged structures), which are often misinterpreted as carbon atoms in other systems.</li>
<li><strong>Generic Structure Interpretation</strong>: It includes a module to parse &ldquo;generic&rdquo; (Markush) structures by matching R-group labels in the diagram with text-based definitions found in the document.</li>
<li><strong>Ambiguity Resolution</strong>: It uses context-aware rules to distinguish between geometrically similar features, such as vertical lines representing bonds vs. the letter &rsquo;l&rsquo; in &lsquo;Cl&rsquo;.</li>
</ul>
<h2 id="methodology-and-benchmarking-on-real-world-data">Methodology and Benchmarking on Real-World Data</h2>
<p>The authors conducted a systematic validation on a dataset of <strong>454 images</strong> containing <strong>519 structure diagrams</strong>.</p>
<ul>
<li><strong>Source Material</strong>: Images were extracted from published materials (journals, patents), ensuring &ldquo;real artifacts&rdquo; like noise and scanning distortions were present.</li>
<li><strong>Automation</strong>: The test was fully automated without human intervention.</li>
<li><strong>Metrics</strong>: The primary metric was the &ldquo;success rate,&rdquo; defined as the correct reconstruction of the molecule&rsquo;s connection table. They also performed fine-grained error analysis on specific features (e.g., atom labels, dashed bonds, wavy bonds).</li>
</ul>
<h2 id="results-high-topological-accuracy-and-persistent-ocr-challenges">Results: High Topological Accuracy and Persistent OCR Challenges</h2>
<ul>
<li><strong>High Accuracy</strong>: The system achieved a <strong>89.79%</strong> retrieval rate (466/519 molecules correctly reconstructed).</li>
<li><strong>Robustness on Primitives</strong>: Solid straight bonds were recognized with 99.92% accuracy.</li>
<li><strong>Key Failure Modes</strong>: The majority of errors (58 cases) occurred in atom label construction, specifically when labels touched nearby bonds or other artifacts, causing OCR failures.</li>
<li><strong>Impact</strong>: The study demonstrated that handling &ldquo;difficult&rdquo; drawing features like crossing bonds and bridged structures significantly reduces topological errors. The authors released the test set to encourage standardized benchmarking in the OCSR field.</li>
</ul>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="data">Data</h3>
<p>The authors utilized a custom dataset designed to reflect real-world noise.</p>
<table>
	<thead>
			<tr>
					<th>Purpose</th>
					<th>Dataset</th>
					<th>Size</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Evaluation</td>
					<td>CLiDE Pro Validation Set</td>
					<td>454 images (519 structures)</td>
					<td>Extracted from scanned journals and PDFs. Includes noise/artifacts. Available in Supporting Information.</td>
			</tr>
	</tbody>
</table>
<h3 id="algorithms">Algorithms</h3>
<p>The CLiDE Pro pipeline consists of five distinct phases. To replicate this system, one would need to implement:</p>
<ol>
<li>
<p><strong>Image Binarization</strong>:</p>
<ul>
<li>Input images are binarized using a threshold-based technique to separate foreground (molecule) from background.</li>
<li><strong>Connected Component Analysis (CCA)</strong>: A non-recursive scan identifies connected components (CCs) and generates interpixel contours (using N, S, E, W directions).</li>
</ul>
</li>
<li>
<p><strong>Document Segmentation</strong>:</p>
<ul>
<li><strong>Layout Analysis</strong>: Uses a bottom-up approach building a tree structure. It treats CCs as graph vertices and distances as edges.</li>
<li><strong>Clustering</strong>: A minimal-cost spanning tree (Kruskal&rsquo;s algorithm) groups CCs into words, lines, and blocks.</li>
<li><strong>Classification</strong>: CCs are classified (Character, Dash, Line, Graphics, Noise) based on size thresholds derived from statistical image analysis.</li>
</ul>
</li>
<li>
<p><strong>Vectorization</strong>:</p>
<ul>
<li><strong>Contour Approximation</strong>: Uses a method similar to <strong>Sklansky and Gonzalez</strong> to approximate contours into polygons.</li>
<li><strong>Vector Formation</strong>: Long polygon sides become straight lines; short consecutive sides become curves. Opposing borders of a line are matched to define the bond vector.</li>
<li><strong>Wavy Bonds</strong>: Detected by finding groups of short vectors lying on a straight line.</li>
<li><strong>Dashed Bonds</strong>: Detected using the <strong>Hough transform</strong> to find collinear or parallel dashes.</li>
</ul>
</li>
<li>
<p><strong>Atom Label Construction</strong>:</p>
<ul>
<li><strong>OCR</strong>: An OCR engine (filtering + topological analysis) interprets characters.</li>
<li><strong>Grouping</strong>: Characters are grouped into words based on horizontal and vertical proximity (for vertical labels).</li>
<li><strong>Superatom Lookup</strong>: Labels are matched against a database of elements, functional groups, and R-groups. Unknown linear formulas (e.g., $\text{CH}_2\text{CH}_2\text{OH}$) are parsed.</li>
</ul>
</li>
<li>
<p><strong>Graph Reconstruction</strong>:</p>
<ul>
<li><strong>Connection Logic</strong>: Bond endpoints are joined to atoms if they are within a distance threshold and &ldquo;point toward&rdquo; the label.</li>
<li><strong>Implicit Carbons</strong>: Unconnected bond ends are joined if close; parallel bonds merge into double/triple bonds.</li>
<li><strong>Crossing Bonds</strong>: Rules check proximity, length, and ring membership to determine if crossing lines are valid atoms or 3D visual artifacts.</li>
</ul>
</li>
<li>
<p><strong>Generic Structure Interpretation</strong>:</p>
<ul>
<li><strong>Text Mining</strong>: A lexical/syntactic analyzer extracts R-group definitions (e.g., &ldquo;R = Me or H&rdquo;) from text blocks.</li>
<li><strong>Matching</strong>: The system attempts to match R-group labels in the diagram with the parsed text definitions.</li>
</ul>
</li>
</ol>
<h3 id="models">Models</h3>
<ul>
<li><strong>OCR Engine</strong>: The system relies on a customized OCR engine capable of handling rotation and chemical symbols, though the specific architecture (neural vs. feature-based) is not detailed beyond &ldquo;topological and geometrical feature analysis&rdquo;.</li>
<li><strong>Superatom Database</strong>: A lookup table containing elements, common functional groups, and R-group labels.</li>
</ul>
<h3 id="evaluation">Evaluation</h3>
<p>The evaluation focused on the topological correctness of the output.</p>
<table>
	<thead>
			<tr>
					<th>Metric</th>
					<th>Value</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><strong>Total Success Rate</strong></td>
					<td>89.79%</td>
					<td>466/519 structures perfectly reconstructed.</td>
			</tr>
			<tr>
					<td><strong>Atom Label Accuracy</strong></td>
					<td>98.54%</td>
					<td>3923/3981 labels correct. Main error source: labels touching bonds.</td>
			</tr>
			<tr>
					<td><strong>Solid Bond Accuracy</strong></td>
					<td>&gt;99.9%</td>
					<td>16061/16074 solid bonds correct.</td>
			</tr>
			<tr>
					<td><strong>Dashed Bond Accuracy</strong></td>
					<td>98.37%</td>
					<td>303/308 dashed bonds correct.</td>
			</tr>
	</tbody>
</table>
<h3 id="hardware">Hardware</h3>
<ul>
<li><strong>Requirements</strong>: Unspecified; described as efficient.</li>
<li><strong>Performance</strong>: The system processed the complex Palytoxin structure &ldquo;within a few seconds&rdquo;. This implies low computational overhead suitable for standard desktop hardware of the 2009 era.</li>
</ul>
<hr>
<h2 id="citation">Citation</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@article</span>{valkoCLiDEProLatest2009,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span> = <span style="color:#e6db74">{CLiDE Pro: The Latest Generation of CLiDE, a Tool for Optical Chemical Structure Recognition}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span> = <span style="color:#e6db74">{Valko, Aniko T. and Johnson, A. Peter}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">journal</span> = <span style="color:#e6db74">{Journal of Chemical Information and Modeling}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">volume</span> = <span style="color:#e6db74">{49}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">number</span> = <span style="color:#e6db74">{4}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span> = <span style="color:#e6db74">{780--787}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span> = <span style="color:#e6db74">{2009}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">doi</span> = <span style="color:#e6db74">{10.1021/ci800449t}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>ChemInk: Real-Time Recognition for Chemical Drawings</title><link>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/online-recognition/chemink-2011/</link><pubDate>Mon, 15 Dec 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/online-recognition/chemink-2011/</guid><description>A sketch recognition framework for chemical diagrams using a joint CRF model to combine multi-level visual features for real-time interpretation.</description><content:encoded><![CDATA[<h2 id="contribution-real-time-sketch-recognition-method">Contribution: Real-Time Sketch Recognition Method</h2>
<p>This is a <strong>Method</strong> paper. It proposes a novel architectural framework for sketch recognition that integrates visual features at three distinct levels (inkpoints, segments, symbols) into a single probabilistic model. The rhetorical structure centers on the proposal of this new architecture, the introduction of a specific &ldquo;trainable corner detector&rdquo; algorithm, and the validation of these methods against existing benchmarks and alternative toolsets (ChemDraw).</p>
<h2 id="motivation-bridging-the-gap-between-sketching-and-cad">Motivation: Bridging the Gap Between Sketching and CAD</h2>
<p>The primary motivation is to bridge the gap between the natural, efficient process of drawing chemical diagrams by hand and the cumbersome &ldquo;point-click-and-drag&rdquo; interactions required by CAD tools like ChemDraw. While chemists prefer sketching for communication, existing digital tools do not offer the same speed or ease of use. The goal is to build an intelligent system that understands freehand sketches in real-time, converting them into structured data suitable for analysis or search.</p>
<h2 id="core-innovation-hierarchical-joint-crf-model">Core Innovation: Hierarchical Joint CRF Model</h2>
<p>The core novelty lies in the <strong>hierarchical joint model</strong>. Unlike previous approaches that might treat stroke segmentation and symbol recognition as separate, isolated steps, ChemInk uses a <strong>Conditional Random Field (CRF)</strong> to jointly model dependencies across three levels:</p>
<ol>
<li><strong>Inkpoints</strong>: Local visual appearance.</li>
<li><strong>Segments</strong>: Stroke fragments separated by corners.</li>
<li><strong>Candidates</strong>: Potential symbol groupings.</li>
</ol>
<p>Additionally, the paper introduces a <strong>trainable corner detector</strong> that learns domain-specific corner definitions from data.</p>
<h2 id="experimental-design-and-baselines">Experimental Design and Baselines</h2>
<p>The authors conducted two primary evaluations:</p>
<ol>
<li><strong>Off-line Accuracy Evaluation</strong>:
<ul>
<li><strong>Dataset</strong>: 12 real-world organic compounds drawn by 10 participants.</li>
<li><strong>Metric</strong>: Recognition accuracy (Recall and Precision).</li>
<li><strong>Baseline</strong>: Comparison against their own previous work (O&amp;D 2009) and ablations (with/without context).</li>
</ul>
</li>
<li><strong>On-line User Study</strong>:
<ul>
<li><strong>Task</strong>: 9 participants (chemistry students) drew 5 diagrams using both ChemInk (Tablet PC) and ChemDraw (Mouse/Keyboard).</li>
<li><strong>Metric</strong>: Time to completion and subjective user ratings (speed/ease of use).</li>
</ul>
</li>
</ol>
<h2 id="results-accuracy-and-user-study-outcomes">Results: Accuracy and User Study Outcomes</h2>
<ul>
<li><strong>Accuracy</strong>: The system achieved <strong>97.4% symbol recognition accuracy</strong>, slightly outperforming the best prior result (97.1%). The trainable corner detector achieved <strong>99.91% recall</strong>.</li>
<li><strong>Speed</strong>: Users were <strong>twice as fast</strong> using ChemInk (avg. 36s) compared to ChemDraw (avg. 79s).</li>
<li><strong>Usability</strong>: Participants rated ChemInk significantly higher for speed (6.3 vs 4.5) and ease of use (6.3 vs 4.7) on a 7-point scale.</li>
<li><strong>Conclusion</strong>: Sketch recognition is a viable, superior alternative to standard CAD tools for authoring chemical diagrams.</li>
</ul>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="data">Data</h3>
<ul>
<li><strong>Training/Test Data</strong>: 12 real-world organic compounds (e.g., Aspirin, Penicillin) drawn by 10 participants (organic chemistry familiar).</li>
<li><strong>Evaluation Split</strong>: User-independent cross-validation (training on 9 users, testing on 1).</li>
<li><strong>Input</strong>: Raw digital ink (strokes) collected on a Tablet PC.</li>
</ul>
<h3 id="algorithms">Algorithms</h3>
<p><strong>1. Corner Detection (Trainable)</strong></p>
<ul>
<li><strong>Method</strong>: Iterative vertex elimination.</li>
<li><strong>Cost Function</strong>: $cost(p_{i}) = \sqrt{mse(s_{i}; p_{i-1}, p_{i+1})} \cdot dist(p_{i}; p_{i-1}, p_{i+1})$</li>
<li><strong>Procedure</strong>: Repeatedly remove the vertex with the lowest cost until the classifier (trained on features like cost, diagonal length, ink density) predicts the remaining vertices are corners.</li>
</ul>
<p><strong>2. Feature Extraction</strong></p>
<ul>
<li><strong>Inkpoints</strong>: Sampled at regular intervals. Features = $10 \times 10$ pixel orientation filters (0, 45, 90, 135 degrees) at two scales ($L/2$, $L$), smoothed and downsampled to $5 \times 5$. Total 400 features.</li>
<li><strong>Segments</strong>: Similar image features centered at segment midpoint, plus geometric features (length, ink density).</li>
<li><strong>Candidates</strong>: 5 feature images ($20 \times 20$) including an &ldquo;endpoint&rdquo; image, stretched to normalize aspect ratio.</li>
<li><strong>Dimensionality Reduction</strong>: PCA used to compress feature images to 256 components.</li>
</ul>
<p><strong>3. Structure Generation</strong></p>
<ul>
<li><strong>Clustering</strong>: Agglomerative clustering with a complete-link metric to connect symbols.</li>
<li><strong>Threshold</strong>: Stop clustering at distance $0.4L$.</li>
</ul>
<h3 id="models">Models</h3>
<p><strong>Conditional Random Field (CRF)</strong></p>
<ul>
<li><strong>Structure</strong>: 3-level hierarchy (Inkpoints $V_p$, Segments $V_s$, Candidates $V_c$).</li>
<li><strong>Nodes</strong>:
<ul>
<li>$V_p, V_s$ labels: &ldquo;bond&rdquo;, &ldquo;hash&rdquo;, &ldquo;wedge&rdquo;, &ldquo;text&rdquo;.</li>
<li>$V_c$ labels: specific candidate interpretations.</li>
</ul>
</li>
<li><strong>Edges/Potentials</strong>:
<ul>
<li><strong>Entity-Feature</strong>: $\phi(y, x)$ (Linear classifier).</li>
<li><strong>Consistency</strong>: $\psi(y_i, y_j)$ (Hard constraint: child must match parent label).</li>
<li><strong>Spatial Context</strong>: $\psi_{ss}(y_i, y_j)$ (Pairwise geometric relationships between segments: angle, distance).</li>
<li><strong>Overlap</strong>: Prevents conflicting candidates from sharing segments.</li>
</ul>
</li>
<li><strong>Inference</strong>: Loopy Belief Propagation (up to 100 iterations).</li>
<li><strong>Training</strong>: Maximum Likelihood via gradient ascent (L-BFGS).</li>
</ul>
<h3 id="evaluation">Evaluation</h3>
<ul>
<li><strong>Primary Metric</strong>: Accuracy (Recall/Precision) of symbol detection.</li>
<li><strong>Comparison</strong>: Compared against Ouyang &amp; Davis 2009 (previous SOTA).</li>
<li><strong>Speed Metric</strong>: Wall-clock time for diagram creation (ChemInk vs. ChemDraw).</li>
</ul>
<h3 id="hardware">Hardware</h3>
<ul>
<li><strong>Processor</strong>: 3.7 GHz processor (single thread) for base benchmarking (approx. 1 sec/sketch).</li>
<li><strong>Deployment</strong>: Validated on 1.8 GHz Tablet PCs using multi-core parallelization for real-time feedback.</li>
</ul>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Ouyang, T. Y., &amp; Davis, R. (2011). ChemInk: A Natural Real-Time Recognition System for Chemical Drawings. <em>Proceedings of the 16th International Conference on Intelligent User Interfaces</em>, 267&ndash;276. <a href="https://doi.org/10.1145/1943403.1943444">https://doi.org/10.1145/1943403.1943444</a></p>
<p><strong>Publication</strong>: IUI &lsquo;11</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@inproceedings</span>{ouyangChemInkNaturalRealtime2011,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span> = <span style="color:#e6db74">{ChemInk: A Natural Real-Time Recognition System for Chemical Drawings}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">shorttitle</span> = <span style="color:#e6db74">{ChemInk}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">booktitle</span> = <span style="color:#e6db74">{Proceedings of the 16th International Conference on Intelligent User Interfaces}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span> = <span style="color:#e6db74">{Ouyang, Tom Y. and Davis, Randall}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span> = <span style="color:#e6db74">{2011}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">month</span> = feb,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span> = <span style="color:#e6db74">{267--276}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">publisher</span> = <span style="color:#e6db74">{ACM}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">address</span> = <span style="color:#e6db74">{Palo Alto, CA, USA}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">doi</span> = <span style="color:#e6db74">{10.1145/1943403.1943444}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">isbn</span> = <span style="color:#e6db74">{978-1-4503-0419-1}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">url</span> = <span style="color:#e6db74">{http://hdl.handle.net/1721.1/78898}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Second-Order Langevin Equation for Field Simulations</title><link>https://hunterheidenreich.com/notes/chemistry/molecular-simulation/classical-methods/second-order-langevin-1987/</link><pubDate>Sun, 14 Dec 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/chemistry/molecular-simulation/classical-methods/second-order-langevin-1987/</guid><description>Hyperbolic Algorithm adds second-order derivatives to Langevin dynamics, reducing systematic errors to O(ε²) for lattice field simulations.</description><content:encoded><![CDATA[<h2 id="contribution-and-paper-type">Contribution and Paper Type</h2>
<p>This is a <strong>Methodological Paper</strong> ($\Psi_{\text{Method}}$). It proposes a novel stochastic algorithm, the Hyperbolic Algorithm (HA), and validates its superior efficiency against the existing Langevin Algorithm (LA) through formal error analysis and numerical simulation. It contains significant theoretical derivation (Liouville dynamics) that serves primarily to justify the algorithmic performance claims.</p>
<h2 id="motivation-and-gaps-in-prior-work">Motivation and Gaps in Prior Work</h2>
<p>The standard Langevin Algorithm (LA) for numerical simulation of Euclidean field theories suffers from efficiency bottlenecks. The simplest Euler-discretization of the LA introduces systematic errors of $O(\epsilon)$ (where $\epsilon$ is the step size). To maintain accuracy, $\epsilon$ must be kept small, which increases the sweep-sweep correlation time (autocorrelation time), making simulations computationally expensive.</p>
<h2 id="core-novelty-second-order-dynamics">Core Novelty: Second-Order Dynamics</h2>
<p>The core contribution is the introduction of a <strong>second-order derivative in fictitious time</strong> to the stochastic equation. This converts the parabolic Langevin equation into a hyperbolic equation:</p>
<p>$$
\begin{aligned}
\frac{\partial^{2}\phi}{\partial t^{2}}+\gamma\frac{\partial\phi}{\partial t}=-\frac{\partial S}{\partial\phi}+\eta
\end{aligned}
$$</p>
<h3 id="equation-comparison">Equation Comparison</h3>
<p>The key difference from the standard (first-order) Langevin equation:</p>
<table>
	<thead>
			<tr>
					<th style="text-align: left">Equation Type</th>
					<th style="text-align: left">Formula</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td style="text-align: left"><strong>Hyperbolic (Second Order)</strong></td>
					<td style="text-align: left">$$\frac{\partial^{2}\phi}{\partial t^{2}}+\gamma\frac{\partial\phi}{\partial t}=-\frac{\partial S}{\partial\phi}+\eta$$</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong>Langevin (First Order)</strong></td>
					<td style="text-align: left">$$\frac{\partial\phi}{\partial t}=-\frac{\partial S}{\partial\phi}+\eta$$</td>
			</tr>
	</tbody>
</table>
<p>The standard Langevin equation corresponds to the overdamped limit where the acceleration term is absent. Physically, the Hyperbolic equation can be viewed as microcanonical equations of motion with an added friction term.</p>
<h3 id="key-innovations">Key Innovations</h3>
<ul>
<li><strong>Higher Order Accuracy</strong>: The simplest discretization of this equation leads to systematic errors of only $O(\epsilon^2)$ compared to $O(\epsilon)$ for LA.</li>
<li><strong>Tunable Damping</strong>: The addition of the damping parameter $\gamma$ allows tuning to minimize autocorrelation tails.</li>
<li><strong>Uniform Evolution</strong>: The method evolves structures of different wavelengths more uniformly than LA due to the specific dissipation structure.</li>
</ul>
<h2 id="methodology-and-experiments">Methodology and Experiments</h2>
<p>The author validated the method using the <strong>XY Model</strong> on 2D lattices.</p>
<ul>
<li><strong>System</strong>: Euclidean action $S = -\sum_{x,\mu} \cos(\theta_{x+\mu} - \theta_x)$.</li>
<li><strong>Setup</strong>:
<ul>
<li>Lattice sizes: $15^2$ (helical boundary conditions) and $30^2$.</li>
<li>$\beta$ range: 0.9 to 1.2 (crossing the critical point $\approx 1.0$).</li>
<li>Run length: &gt;100,000 updates in equilibrium.</li>
</ul>
</li>
<li><strong>Metrics</strong>:
<ul>
<li><strong>Autocorrelation time ($\tau$)</strong>: Defined as the number of updates for the time-correlation function to drop to 10% of its initial value.</li>
<li><strong>Systematic Error</strong>: Measured via deviation of average action from Monte Carlo values.</li>
</ul>
</li>
</ul>
<h2 id="results-and-conclusions">Results and Conclusions</h2>
<ul>
<li><strong>Efficiency</strong>: The Hyperbolic Algorithm (HA) is far more efficient. For equal systematic errors, sweep-sweep correlation times are significantly lower than LA.</li>
<li><strong>Error Scaling</strong>: Numerical results confirmed that HA step size $\epsilon_H = 0.1$ yields systematic errors comparable to LA step size $\epsilon_L \approx 0.008$ ($O(\epsilon^2)$ vs $O(\epsilon)$ scaling).</li>
<li><strong>Speedup</strong>: In the disordered phase, HA is roughly $\epsilon_H / \epsilon_L$ times faster (approximately a factor of 12.5 for $\epsilon_H = 0.1$, $\epsilon_L = 0.008$). In the ordered phase, efficiency gains increase with distance scale, reaching factors of 20 or more for long-range correlations.</li>
<li><strong>Optimal Damping</strong>: For the XY model, the optimal damping parameter was found to be $\gamma \approx 0.4$.</li>
</ul>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="algorithms">Algorithms</h3>
<p><strong>1. The Hyperbolic Algorithm (HA)</strong></p>
<p>The discretized update equations for scalar fields are:</p>
<p>$$
\begin{aligned}
\pi_{t+\epsilon} - \pi_{t} &amp;= -\epsilon\gamma\pi_{t} - \epsilon\frac{\partial S}{\partial\phi_{t}} + \sqrt{2\epsilon\gamma/\beta}\xi_{t} \\
\phi_{t+\epsilon} - \phi_{t} &amp;= \epsilon\pi_{t+\epsilon}
\end{aligned}
$$</p>
<ul>
<li><strong>Variables</strong>: $\phi$ is the field, $\pi$ is the conjugate momentum ($\dot{\phi}$).</li>
<li><strong>Parameters</strong>: $\epsilon$ (step size), $\gamma$ (damping constant).</li>
<li><strong>Noise</strong>: $\xi$ is Gaussian noise with $\langle\xi_x \xi_y\rangle = \delta_{x,y}$.</li>
<li><strong>Storage</strong>: Requires storing both $\phi$ and $\pi$ vectors.</li>
</ul>
<p><strong>2. Non-Abelian Generalization</strong></p>
<p>For Lie group elements $U$ with generators $T^a$:</p>
<p>$$
\begin{aligned}
\pi_{t+\epsilon}^a - \pi_{t}^a &amp;= -\epsilon\gamma\pi_{t}^a - \epsilon\delta^a S[U_t] + \sqrt{2\epsilon\gamma/\beta}\xi_{t}^a \\
U_{t+\epsilon} &amp;= e^{i\epsilon\pi_{t+\epsilon}^a T^a} U_t
\end{aligned}
$$</p>
<h3 id="theoretical-proof-of-oepsilon2-accuracy">Theoretical Proof of $O(\epsilon^2)$ Accuracy</h3>
<p>The derivation relies on the generalized Liouville equation for the probability distribution $P[\phi, \pi; t]$.</p>
<ol>
<li><strong>Transition Probability</strong>: The transition $W$ for one iteration is defined.</li>
<li><strong>Effective Liouville Operator</strong>: The evolution is written as $P(t+\epsilon) = \exp(\epsilon L_{\text{eff}}) P(t)$.</li>
<li><strong>Baker-Hausdorff Expansion</strong>: Using normal ordering of operators, the equilibrium distribution $P_{\text{eq}}$ is derived through $O(\epsilon^2)$:</li>
</ol>
<p>$$
\begin{aligned}
P_{\text{eq}} &amp;= \exp\left\lbrace-\frac{1}{2}\beta_{1}\sum_{x}\pi_{x}^{2} - \beta S[\phi] + \frac{1}{2}\epsilon\beta\sum_{x}\pi_{x}S_{x} + \epsilon^{2}G + O(\epsilon^3)\right\rbrace
\end{aligned}
$$</p>
<p>where $\beta_1 = \beta\left(1 - \frac{1}{2}\epsilon\gamma\right)$.</p>
<ol start="4">
<li><strong>Effective Action</strong>: Integrating out $\pi$ yields the effective action for $\phi$:</li>
</ol>
<p>$$
\begin{aligned}
S_{\text{eff}}[\phi] &amp;= S[\phi] - \frac{1}{8}\epsilon^2 \sum_x S_x^2 + \dots
\end{aligned}
$$</p>
<p>The absence of $O(\epsilon)$ terms proves the higher-order accuracy.</p>
<h3 id="evaluation">Evaluation</h3>
<ul>
<li><strong>Model</strong>: XY Model (2D)</li>
<li><strong>Hamiltonian</strong>: $H = \frac{1}{2}\sum \pi^2 + S[\phi]$ where $S = -\sum \cos(\Delta \theta)$.</li>
<li><strong>Observables</strong>:
<ul>
<li>$\Gamma_n = \cos(\theta_{m+n} - \theta_m)$ (averaged over lattice $m$).</li>
</ul>
</li>
<li><strong>Comparisons</strong>:
<ul>
<li><strong>LA Step</strong>: $\epsilon_L \approx 0.005 - 0.02$.</li>
<li><strong>HA Step</strong>: $\epsilon_H \approx 0.1 - 0.2$.</li>
<li><strong>Equivalence</strong>: $\epsilon_H = 0.1$ matches error of $\epsilon_L \approx 0.008$.</li>
</ul>
</li>
</ul>
<hr>
<h2 id="terminology-note">Terminology Note</h2>
<p>The naming conventions in this paper differ from those commonly used in molecular dynamics (MD). The following table provides a cross-field mapping:</p>
<table>
	<thead>
			<tr>
					<th style="text-align: left">Concept</th>
					<th style="text-align: left"><strong>Field Theory (This Paper)</strong></th>
					<th style="text-align: left"><strong>Molecular Dynamics</strong></th>
					<th style="text-align: left"><strong>Mathematics</strong></th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td style="text-align: left"><strong>Equation 1</strong></td>
					<td style="text-align: left">&ldquo;Langevin Equation&rdquo;</td>
					<td style="text-align: left">Brownian Dynamics (BD)</td>
					<td style="text-align: left">Overdamped Langevin</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong>Equation 2</strong></td>
					<td style="text-align: left">&ldquo;Hyperbolic Equation&rdquo;</td>
					<td style="text-align: left">Langevin Dynamics (LD)</td>
					<td style="text-align: left">Underdamped Langevin</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong>Integrator 1</strong></td>
					<td style="text-align: left">Euler Discretization</td>
					<td style="text-align: left">Euler Integrator</td>
					<td style="text-align: left">Euler-Maruyama</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong>Integrator 2</strong></td>
					<td style="text-align: left">Hyperbolic Algorithm (HA)</td>
					<td style="text-align: left">Velocity Verlet / Leapfrog</td>
					<td style="text-align: left">Quasi-Symplectic Splitting</td>
			</tr>
	</tbody>
</table>
<p><strong>Key insight</strong>: The paper&rsquo;s &ldquo;Hyperbolic Algorithm&rdquo; is mathematically equivalent to Langevin Dynamics with a Leapfrog/Verlet integrator, commonly used in MD. The baseline &ldquo;Langevin Algorithm&rdquo; corresponds to Brownian Dynamics. The term &ldquo;Langevin equation&rdquo; is overloaded: field theorists often use it for overdamped dynamics (no inertia), while chemists assume it includes momentum ($F=ma$).</p>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Horowitz, A. M. (1987). The Second Order Langevin Equation and Numerical Simulations. <em>Nuclear Physics B</em>, 280, 510-522. <a href="https://doi.org/10.1016/0550-3213(87)90159-3">https://doi.org/10.1016/0550-3213(87)90159-3</a></p>
<p><strong>Publication</strong>: Nuclear Physics B 1987</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@article</span>{horowitzSecondOrderLangevin1987,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span> = <span style="color:#e6db74">{The Second Order {{Langevin}} Equation and Numerical Simulations}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span> = <span style="color:#e6db74">{Horowitz, Alan M.}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span> = <span style="color:#ae81ff">1987</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">month</span> = jan,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">journal</span> = <span style="color:#e6db74">{Nuclear Physics B}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">volume</span> = <span style="color:#e6db74">{280}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span> = <span style="color:#e6db74">{510--522}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">issn</span> = <span style="color:#e6db74">{05503213}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">doi</span> = <span style="color:#e6db74">{10.1016/0550-3213(87)90159-3}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Reconstruction of Chemical Molecules from Images</title><link>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/rule-based/algorri-reconstruction-2007/</link><pubDate>Sun, 14 Dec 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/rule-based/algorri-reconstruction-2007/</guid><description>A 5-module system converting raster images of chemical structures into machine-readable SDF files with custom vectorization.</description><content:encoded><![CDATA[<h2 id="methodological-basis">Methodological Basis</h2>
<p>This paper is a clear methodological contribution describing a novel system architecture. It proposes a five-stage pipeline to solve a specific engineering problem: converting rasterized chemical images into structured chemical files (SDF). The authors validate the method by benchmarking it against a commercial product (CLIDE) and analyzing performance across multiple databases.</p>
<h2 id="the-inaccessibility-of-raster-chemical-images">The Inaccessibility of Raster Chemical Images</h2>
<ul>
<li><strong>Data Inaccessibility</strong>: A massive amount of chemical knowledge (scientific articles, patents) exists only as raster images, rendering it inaccessible to computational analysis.</li>
<li><strong>Inefficiency of Manual Entry</strong>: Manual replication of molecules into CAD programs is the standard but unscalable solution for extracting this information.</li>
<li><strong>Limitations of Existing Tools</strong>: Previous academic and commercial attempts (early 90s systems like CLIDE) had faded or remained limited in robustness, leaving the problem &ldquo;wide open&rdquo;.</li>
</ul>
<h2 id="topology-preserving-chemical-vectorization">Topology-Preserving Chemical Vectorization</h2>
<p>The core novelty is the <strong>topology-preserving vectorization</strong> strategy designed specifically for chemical graphs.</p>
<ul>
<li><strong>Graph-Centric Vectorizer</strong>: This system prioritizes graph characteristics over the pixel precision of traditional CAD vectorizers, ensuring one line in the image becomes exactly one vector, regardless of line width or vertex thickness.</li>
<li><strong>Chemical Knowledge Module</strong>: The inclusion of a final validation step that applies chemical rules (valence, charge) to detect and potentially correct reconstruction errors.</li>
<li><strong>Hybrid Recognition</strong>: The separation of the pipeline into a &ldquo;Body&rdquo; path (vectorizer for bonds) and an &ldquo;OCR&rdquo; path (SVM for atomic symbols), which are re-integrated in a reconstruction phase.</li>
</ul>
<h2 id="validating-reconstruction-accuracy">Validating Reconstruction Accuracy</h2>
<p>The authors performed a quantitative validation using <strong>ground-truth SDF files</strong> to verify reconstruction accuracy. The success rate metric evaluated whether the reconstructed graph perfectly matched the true SDF:</p>
<p>$$ \text{Accuracy} = \frac{\text{Correctly Reconstructed SDFs}}{\text{Total Images Evaluated}} $$</p>
<ul>
<li><strong>Baselines</strong>: The system was benchmarked against the commercial software <strong>CLIDE</strong> on &ldquo;Database 1&rdquo;.</li>
<li><strong>Datasets</strong>: Three distinct databases were used:
<ul>
<li><strong>Database 1</strong>: 100 images (varied fonts/line widths).</li>
<li><strong>Database 2</strong>: 100 images.</li>
<li><strong>Database 3</strong>: 7,604 images (large-scale test).</li>
</ul>
</li>
</ul>
<h2 id="system-performance-and-scalability">System Performance and Scalability</h2>
<ul>
<li><strong>Superior Performance</strong>: On Database 1, the proposed system correctly reconstructed <strong>97%</strong> of images, whereas the commercial CLIDE system only reconstructed <strong>25%</strong> (after parameter tuning).</li>
<li><strong>Scalability</strong>: The system maintained reasonable performance on the large dataset (Database 3), achieving <strong>67%</strong> accuracy.</li>
<li><strong>Robustness</strong>: The system can handle varying fonts and line widths via parameterization.</li>
<li><strong>Future Work</strong>: The authors plan to implement a feedback loop where the Chemical Knowledge Module can send error signals back to earlier modules to correct inconsistencies.</li>
</ul>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<p><strong>Reproducibility Status</strong>: Closed / Not Reproducible (Paywalled paper, no public code or data).</p>
<h3 id="data">Data</h3>
<p>The paper utilizes three databases for validation. The authors note that for these images, the correct SDF files were already available, allowing for direct automated checking.</p>
<table>
	<thead>
			<tr>
					<th>Purpose</th>
					<th>Dataset</th>
					<th>Size</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Evaluation</td>
					<td>Database 1</td>
					<td>100 Images</td>
					<td>Varied line widths, fonts, symbols; used for CLIDE comparison.</td>
			</tr>
			<tr>
					<td>Evaluation</td>
					<td>Database 2</td>
					<td>100 Images</td>
					<td>General chemical database.</td>
			</tr>
			<tr>
					<td>Evaluation</td>
					<td>Database 3</td>
					<td>7,604 Images</td>
					<td>Large-scale database.</td>
			</tr>
	</tbody>
</table>
<h3 id="algorithms">Algorithms</h3>
<p>The system is composed of five distinct modules executed in sequence:</p>
<p><strong>1. Binarization &amp; Segmentation</strong></p>
<ul>
<li><strong>Preprocessing</strong>: Removal of anti-aliasing effects followed by <strong>adaptive histogram binarization</strong>.</li>
<li><strong>Connected Components</strong>: A non-recursive raster-scan algorithm identifies connected Run-Length Encoded (RLE) segments.</li>
</ul>
<p><strong>2. Optical Character Recognition (OCR)</strong></p>
<ul>
<li><strong>Feature Extraction</strong>: Uses functions similar to <strong>Zernike moments</strong> and a <strong>wavelet transform strategy</strong>.</li>
<li><strong>Classification</strong>: Identifies isolated characters/symbols and separates them from the molecular &ldquo;body&rdquo;.</li>
</ul>
<p><strong>3. Vectorizer</strong></p>
<ul>
<li><strong>Logic</strong>: Assigns local directions to RLE segments based on neighbors, then groups segments with similar local direction patterns.</li>
<li><strong>Constraint</strong>: Enforces a 1-to-1 mapping between visual lines and graph vectors to prevent spurious small vectors at thick joints.</li>
</ul>
<p><strong>4. Reconstruction (Heuristics)</strong></p>
<p>This module annotates vectors with chemical significance:</p>
<ul>
<li><strong>Chiral Bonds (Wedges)</strong>: Identified by registering vectors against original pixel density. If a vector corresponds to a thick geometric form (triangle/rectangle), it is labeled chiral.</li>
<li><strong>Dotted Chiral Bonds</strong>: Identified by clustering isolated vectors (no neighbors) using <strong>quadtree clustering</strong> on geometric centers. Coherent parallel clusters are fused into a single bond.</li>
<li><strong>Double/Triple Bonds</strong>: Detected by checking for parallel vectors within a <strong>Region of Interest (ROI)</strong> defined as the vector&rsquo;s bounding box <strong>dilated by a factor of 2</strong>.</li>
<li><strong>Superatoms</strong>: OCR results are clustered by dilating bounding boxes; overlapping boxes are grouped into names (e.g., &ldquo;COOH&rdquo;).</li>
</ul>
<p><strong>5. Chemical Knowledge</strong></p>
<p>Validates the generated graph against rules for valences and charges. If valid, an SDF file is generated.</p>
<h3 id="models">Models</h3>
<ul>
<li><strong>SVM (Support Vector Machine)</strong>: Used within the OCR module to classify connected components as characters or symbols. It is trained to be tolerant to rotation and font variations.</li>
</ul>
<h3 id="evaluation">Evaluation</h3>
<p>The primary metric is binary success rate per molecule (perfect reconstruction of the SDF).</p>
<table>
	<thead>
			<tr>
					<th>Metric</th>
					<th>Value (DB1)</th>
					<th>Value (DB3)</th>
					<th>Baseline (CLIDE on DB1)</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Correct Reconstruction</td>
					<td><strong>97%</strong></td>
					<td>67%</td>
					<td>25%</td>
					<td>CLIDE required significant parameter tuning to reach 25%.</td>
			</tr>
	</tbody>
</table>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Algorri, M.-E., Zimmermann, M., Friedrich, C. M., Akle, S., &amp; Hofmann-Apitius, M. (2007). Reconstruction of Chemical Molecules from Images. <em>Proceedings of the 29th Annual International Conference of the IEEE EMBS</em>, 4609-4612. <a href="https://doi.org/10.1109/IEMBS.2007.4353366">https://doi.org/10.1109/IEMBS.2007.4353366</a></p>
<p><strong>Publication venue</strong>: IEEE EMBS 2007</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@inproceedings</span>{algorriReconstructionChemicalMolecules2007,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span> = <span style="color:#e6db74">{Reconstruction of {{Chemical Molecules}} from {{Images}}}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">booktitle</span> = <span style="color:#e6db74">{Proceedings of the 29th Annual International Conference of the IEEE EMBS}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span> = <span style="color:#e6db74">{Algorri, Maria-Elena and Zimmermann, Marc and Friedrich, Christoph M. and Akle, Santiago and {Hofmann-Apitius}, Martin}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span> = <span style="color:#e6db74">{2007}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span> = <span style="color:#e6db74">{4609--4612}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">publisher</span> = <span style="color:#e6db74">{IEEE}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">doi</span> = <span style="color:#e6db74">{10.1109/IEMBS.2007.4353366}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Optical Recognition of Chemical Graphics</title><link>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/rule-based/casey-ocsr-1993/</link><pubDate>Sun, 14 Dec 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/rule-based/casey-ocsr-1993/</guid><description>A 1993 prototype system for converting scanned chemical diagrams into connection tables using vectorization and heuristic-based structure recognition.</description><content:encoded><![CDATA[<h2 id="contribution-early-ocsr-pipeline-methodology">Contribution: Early OCSR Pipeline Methodology</h2>
<p><strong>Method</strong>. This paper proposes a novel architectural pipeline for the automatic recognition of chemical structure diagrams. It defines a specific sequence of algorithmic steps, including diagram separation, vectorization, segmentation, and structural analysis, which converts pixel data into a semantic chemical representation (MDL Molfile).</p>
<h2 id="motivation-digitizing-legacy-chemical-data">Motivation: Digitizing Legacy Chemical Data</h2>
<p><strong>Problem</strong>: In 1993, vast databases of chemical information existed, but the entry of graphical data was significantly less advanced than the facilities for manipulating it.</p>
<p><strong>Gap</strong>: Creating digital chemical structures required trained operators to manually redraw diagrams that already existed in printed journals and catalogs, leading to a costly duplication of effort.</p>
<p><strong>Goal</strong>: To automate the creation of coded representations (connection tables) directly from optically scanned diagrams on printed pages.</p>
<h2 id="novelty-general-document-analysis-integrated-with-chemical-rules">Novelty: General Document Analysis Integrated with Chemical Rules</h2>
<p><strong>Pipeline Approach</strong>: The authors present a complete end-to-end system that integrates general document analysis with domain-specific chemical rules.</p>
<p><strong>Convex Bounding Separation</strong>: A novel use of &ldquo;bounding polygons&rdquo; defined by 8 fixed-direction bands to distinguish diagram components from text with linear computational cost.</p>
<p><strong>Vector-Based Segmentation</strong>: The system uses the output of a vectorizer (GIFTS) to classify diagram elements. It relies on the observation that vectorizers approximate characters with sets of short vectors to distinguish them from bonds.</p>
<h2 id="methodology-and-system-evaluation">Methodology and System Evaluation</h2>
<p><strong>System Implementation</strong>: The algorithm was implemented in &lsquo;C&rsquo; on IBM PS/2 personal computers running OS/2 Presentation Manager.</p>
<p><strong>Input Specification</strong>: The system was tested on documents scanned at 300 dpi using an IBM 3119 scanner.</p>
<p><strong>Qualitative Evaluation</strong>: The authors evaluated the system on &ldquo;typical scanned structures&rdquo; and &ldquo;simple planar diagrams&rdquo;. Large-scale quantitative benchmarking was not conducted in this work.</p>
<h2 id="results-performance-and-limitations">Results, Performance, and Limitations</h2>
<p><strong>Performance</strong>: The prototype processes a typical structure (after extraction) in less than one minute.</p>
<p><strong>Accuracy</strong>: It is reported to be accurate for simple planar diagrams.</p>
<p><strong>Output Format</strong>: The system successfully generates MDL Molfiles that interface with standard chemistry software like REACCS, MACCS, and modeling tools.</p>
<p><strong>Limitations</strong>: The system struggles with broken lines, characters touching bond structures, and requires manual intervention for complex errors.</p>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<p><strong>Status:</strong> Closed (Historical). As an early prototype from 1993, no source code, datasets, or digital models were publicly released. Reproducing this exact system would require recreating the pipeline from the described heuristics and sourcing vintage OCR software.</p>
<h3 id="artifacts">Artifacts</h3>
<table>
	<thead>
			<tr>
					<th style="text-align: left">Artifact</th>
					<th style="text-align: left">Type</th>
					<th style="text-align: left">License</th>
					<th style="text-align: left">Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td style="text-align: left"><em>None available</em></td>
					<td style="text-align: left">N/A</td>
					<td style="text-align: left">N/A</td>
					<td style="text-align: left">No digital artifacts were released with this 1993 publication.</td>
			</tr>
	</tbody>
</table>
<h3 id="data">Data</h3>
<p>The paper does not release a dataset but specifies the input requirements for the system.</p>
<table>
	<thead>
			<tr>
					<th>Purpose</th>
					<th>Dataset</th>
					<th>Size</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Input</td>
					<td>Scanned Documents</td>
					<td>N/A</td>
					<td>Black ink on white paper; scanned at 300 dpi bi-level.</td>
			</tr>
	</tbody>
</table>
<h3 id="algorithms">Algorithms</h3>
<p>The paper relies on a pipeline of specific heuristics and geometric rules.</p>
<p><strong>1. Diagram Separation (Region Growing)</strong></p>
<ul>
<li><strong>Bounding Polygons</strong>: Uses convex polygons defined by pairs of parallel sides in 8 fixed directions. This approximation improves distance estimation compared to bounding rectangles.</li>
<li><strong>Seed Detection</strong>: Finds a connected component with bounding dimension $D &gt; d_{\text{max char size}}$.</li>
<li><strong>Aggregation</strong>: Iteratively searches for neighboring components within a specific distance threshold $d_t$ (where $d_t$ is smaller than the whitespace margin) and merges them into the bounding polygon.</li>
</ul>
<p><strong>2. Vectorization &amp; Segmentation</strong></p>
<ul>
<li><strong>Vectorization</strong>: Uses the GIFTS system (IBM Tokyo) to fit lines to pixels.</li>
<li><strong>Classification Heuristics</strong>:
<ul>
<li><strong>Ratio Test</strong>: If the ratio of a group&rsquo;s dimension to the full diagram dimension is below a threshold $\tau$, it is classified as a <strong>Symbol</strong>:
$$ \frac{D_{\text{group}}}{D_{\text{diagram}}} &lt; \tau $$</li>
<li><strong>Context Rule</strong>: Small vector groups near letters are classified as <strong>Characters</strong> (handles &rsquo;l&rsquo; in &lsquo;Cl&rsquo;).</li>
<li><strong>Circle Rule</strong>: A group is a <strong>Circle</strong> (aromatic ring) if it contains $N \ge 8$ vectors in a roughly circular arrangement.</li>
<li><strong>Default</strong>: Otherwise, classified as <strong>Bond Structure</strong>.</li>
</ul>
</li>
</ul>
<p><strong>3. Cleanup &amp; Structure Recognition</strong></p>
<ul>
<li><strong>Short Vector Removal</strong>: Vectors shorter than a fraction of the median line length $L_{\text{median}}$ are shrunk to their midpoint (fixing broken junctions).</li>
<li><strong>Vertex Merging</strong>: If two vectors meet at an angle $\theta &lt; 35^{\circ}$, the vertex is removed (fixing single lines broken into two).</li>
<li><strong>Aromatic Processing</strong>: If a circle is detected, the system identifies the 6 closest atoms and adds double bonds to every second bond in the ring.</li>
</ul>
<h3 id="models">Models</h3>
<p><strong>OCR</strong>:</p>
<ul>
<li>The system uses a feature-based, single-font OCR engine.</li>
<li>It assumes non-serif, plain styles typical of drafting standards.</li>
<li>Character images are normalized for size before recognition.</li>
</ul>
<h3 id="hardware">Hardware</h3>
<ul>
<li><strong>Scanner</strong>: IBM 3119 (300 dpi).</li>
<li><strong>Compute</strong>: IBM PS/2 series running OS/2.</li>
</ul>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Casey, R., et al. (1993). Optical Recognition of Chemical Graphics. <em>Proceedings of 2nd International Conference on Document Analysis and Recognition (ICDAR &lsquo;93)</em>, 627-631. <a href="https://doi.org/10.1109/ICDAR.1993.395658">https://doi.org/10.1109/ICDAR.1993.395658</a></p>
<p><strong>Publication</strong>: ICDAR 1993</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@inproceedings</span>{caseyOpticalRecognitionChemical1993,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span> = <span style="color:#e6db74">{Optical Recognition of Chemical Graphics}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">booktitle</span> = <span style="color:#e6db74">{Proceedings of 2nd {{International Conference}} on {{Document Analysis}} and {{Recognition}} ({{ICDAR}} &#39;93)}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span> = <span style="color:#e6db74">{Casey, R. and Boyer, S. and Healey, P. and Miller, A. and Oudot, B. and Zilles, K.}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span> = <span style="color:#ae81ff">1993</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span> = <span style="color:#e6db74">{627--631}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">publisher</span> = <span style="color:#e6db74">{IEEE Comput. Soc. Press}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">address</span> = <span style="color:#e6db74">{Tsukuba Science City, Japan}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">doi</span> = <span style="color:#e6db74">{10.1109/ICDAR.1993.395658}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Mixture Density Networks: Modeling Multimodal Distributions</title><link>https://hunterheidenreich.com/notes/machine-learning/generative-models/mixture-density-networks/</link><pubDate>Sun, 14 Dec 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/machine-learning/generative-models/mixture-density-networks/</guid><description>A 1994 technical report introducing Mixture Density Networks (MDNs) to model arbitrary conditional probability distributions using neural networks.</description><content:encoded><![CDATA[<h2 id="what-kind-of-paper-is-this">What kind of paper is this?</h2>
<p>This is a <strong>Method</strong> paper.</p>
<p>It identifies a specific failure mode in existing neural network methodologies (least-squares regression on multi-valued inverse problems) and proposes a novel architecture (combining MLPs with Mixture Models) to solve it. It derives the mathematical framework for training this architecture via standard back-propagation and validates it against the established baseline.</p>
<h2 id="what-is-the-motivation">What is the motivation?</h2>
<p>Standard neural networks trained with sum-of-squares (MSE) or cross-entropy error functions approximate the <strong>conditional average</strong> of the target data, $\langle t|x \rangle$.</p>
<p>While optimal for single-valued functions or classification, this produces completely erroneous results for <strong>inverse problems</strong> where the mapping is multi-valued (one input has multiple valid outputs). For example, in robot inverse kinematics, &ldquo;elbow-up&rdquo; and &ldquo;elbow-down&rdquo; configurations can achieve the same hand position. An MSE-trained network will average these two valid angles, resulting in an invalid configuration (the paper shows this produces end-effector positions at the outer boundary of the accessible region, corresponding to $\theta_2 = \pi$).</p>















<figure class="post-figure center ">
    <img src="/img/notes/single-gaussian-mse-prediction.webp"
         alt="Single Gaussian MSE prediction averaging multimodal distribution"
         title="Single Gaussian MSE prediction averaging multimodal distribution"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">MSE-trained networks predict the mean, which averages across modes and produces invalid outputs for inverse problems.</figcaption>
    
</figure>

<h2 id="what-is-the-novelty-here">What is the novelty here?</h2>
<p>The introduction of the <strong>Mixture Density Network (MDN)</strong>.</p>
<p>The neural network predicts the <strong>parameters</strong> (mixing coefficients, means, and variances) of a kernel mixture distribution (typically Gaussian).</p>















<figure class="post-figure center ">
    <img src="/img/notes/gaussian-mixture-mdn-prediction.webp"
         alt="Gaussian mixture model prediction capturing multimodal distribution"
         title="Gaussian mixture model prediction capturing multimodal distribution"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">MDNs predict mixture parameters to capture the full conditional probability density, representing all modes.</figcaption>
    
</figure>

<p>Key technical contributions include:</p>
<ol>
<li><strong>Architecture</strong>: Mapping network outputs to mixture parameters using specific activation functions to satisfy constraints (Softmax for priors $\alpha$, Exponential for variances $\sigma$).</li>
<li><strong>Training</strong>: Deriving the error function as the negative log-likelihood of the mixture model.</li>
<li><strong>Optimization</strong>: Deriving the exact derivatives (gradients) of the error with respect to network outputs, allowing the mixture model parameters to be learned via standard back-propagation.</li>
</ol>
<h2 id="what-experiments-were-performed">What experiments were performed?</h2>
<p>Bishop validated the method on two tasks, comparing an MDN against a standard MLP trained with least-squares:</p>
<ol>
<li><strong>Toy Inverse Problem</strong>: A sinusoidal mapping $x = t + 0.3\sin(2\pi t) + \epsilon$. The forward problem ($t \to x$) is single-valued, but the inverse ($x \to t$) is multi-valued.</li>
<li><strong>Robot Kinematics</strong>: A 2-link robot arm simulation. The task is to map end-effector Cartesian coordinates $(x_1, x_2)$ back to joint angles $(\theta_1, \theta_2)$.</li>
</ol>
<h2 id="what-outcomesconclusions">What outcomes/conclusions?</h2>
<ul>
<li><strong>Toy Problem</strong>: The standard least-squares network failed completely, drawing a smooth curve through the average of the multiple branches, which did not correspond to valid data. The MDN correctly modeled the tri-modal density and discontinuous jumps in the most probable solution.</li>
<li><strong>Robot Kinematics</strong>: The MDN reduced the RMS positioning error by an order of magnitude compared to the standard network (0.0053 vs 0.0578).</li>
<li><strong>Generality</strong>: The paper concludes that MDNs provide a complete description of the conditional probability density, allowing users to calculate any statistic (mean, mode, variance) needed for the application.</li>
</ul>
<h2 id="extracting-predictions">Extracting Predictions</h2>
<p>Once trained, the MDN outputs a full conditional density $p(t|x)$, from which several useful statistics can be derived:</p>
<ul>
<li><strong>Conditional mean</strong>: $\langle t|x \rangle = \sum_i \alpha_i(x) \mu_i(x)$, equivalent to the standard least-squares network output.</li>
<li><strong>Conditional variance</strong>: $s^2(x) = \sum_i \alpha_i(x) { \sigma_i(x)^2 + | \mu_i(x) - \sum_j \alpha_j(x) \mu_j(x) |^2 }$, which is input-dependent (more general than the constant-variance least-squares assumption).</li>
<li><strong>Most probable branch</strong>: Select the kernel $i$ with the largest mixing coefficient $\alpha_i(x)$, then use its center $\mu_i$ as the prediction. This yields a discontinuous but accurate mapping for multi-valued problems.</li>
</ul>
<h2 id="limitations">Limitations</h2>
<ul>
<li><strong>Model order selection</strong>: The number of mixture components $m$ must be chosen in advance. The paper acknowledges this as an open problem and suggests cross-validation or Bayesian model comparison as potential approaches.</li>
<li><strong>Computational overhead</strong>: The number of network outputs grows as $(c + 2) \times m$, where $c$ is the target dimensionality. For high-dimensional targets or many kernels, this can become significant.</li>
<li><strong>Isotropic kernels</strong>: The paper uses a single variance parameter $\sigma_i$ per kernel (shared across target dimensions), which assumes isotropic covariance. The paper notes this can be generalized to full covariance matrices at the cost of additional parameters.</li>
</ul>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="data">Data</h3>
<p><strong>1. Toy Inverse Problem</strong></p>
<ul>
<li><strong>Function</strong>: $x = t + 0.3\sin(2\pi t) + \epsilon$</li>
<li><strong>Noise</strong>: $\epsilon \sim U(-0.1, 0.1)$</li>
<li><strong>Sampling</strong>: 1,000 points generated by sampling $t$ at equal intervals in range $(0, 1)$.</li>
<li><strong>Task</strong>: Inverse mapping (predict $t$ given $x$).</li>
</ul>
<p><strong>2. Robot Kinematics</strong></p>
<ul>
<li><strong>System</strong>: 2-link arm with lengths $L_1=0.8, L_2=0.2$.</li>
<li><strong>Forward Kinematics</strong>:
<ul>
<li>$x_1 = L_1 \cos(\theta_1) - L_2 \cos(\theta_1 + \theta_2)$</li>
<li>$x_2 = L_1 \sin(\theta_1) - L_2 \sin(\theta_1 + \theta_2)$</li>
</ul>
</li>
<li><strong>Constraints</strong>: $\theta_1 \in (0.3, 1.2)$, $\theta_2 \in (\pi/2, 3\pi/2)$.</li>
<li><strong>Dataset</strong>: 1,000 training points, 1,000 test points.</li>
</ul>
<h3 id="algorithms">Algorithms</h3>
<p><strong>Mixture Model Definition</strong></p>
<p>The conditional density is defined as:</p>
<p>$$p(t|x) = \sum_{i=1}^{m} \alpha_i(x) \phi_i(t|x)$$</p>
<p>Where kernels $\phi_i$ are Gaussians with centers $\mu_i(x)$ and variances $\sigma_i(x)$.</p>
<p><strong>Network Output Mappings</strong></p>
<p>If the network produces raw outputs $z$, they are mapped to parameters as follows to satisfy probability constraints:</p>
<ul>
<li><strong>Mixing Coefficients ($\alpha$)</strong>: Softmax. $\alpha_i = \frac{\exp(z_i^\alpha)}{\sum_j \exp(z_j^\alpha)}$</li>
<li><strong>Variances ($\sigma$)</strong>: Exponential. $\sigma_i = \exp(z_i^\sigma)$</li>
<li><strong>Means ($\mu$)</strong>: Linear/Identity. $\mu_{ik} = z_{ik}^\mu$</li>
</ul>
<p><strong>Loss Function</strong></p>
<p>Negative Log Likelihood:</p>
<p>$$E^q = - \ln \left{ \sum_{i=1}^{m} \alpha_i(x^q) \phi_i(t^q|x^q) \right}$$</p>
<h3 id="models">Models</h3>
<p><strong>1. Toy Problem Configuration</strong></p>
<ul>
<li><strong>Structure</strong>: MLP with 1 input ($x$), 1 hidden layer.</li>
<li><strong>Hidden Units</strong>: 20 units (tanh activation).</li>
<li><strong>Outputs</strong>: 9 units.
<ul>
<li>$m=3$ Gaussian kernels.</li>
<li>Parameters per kernel: 1 $\alpha$, 1 $\sigma$, 1 $\mu$. Total = $3 \times 3 = 9$.</li>
</ul>
</li>
<li><strong>Training</strong>: 1,000 cycles of BFGS.</li>
</ul>
<p><strong>2. Robot Kinematics Configuration (Least-Squares Baseline)</strong></p>
<ul>
<li><strong>Structure</strong>: MLP with 2 inputs ($x_1, x_2$), 2 linear outputs ($\theta_1, \theta_2$).</li>
<li><strong>Hidden Units</strong>: Best result with 20 units (tanh activation), tested with 5, 10, 15, 20, 25, 30.</li>
<li><strong>Training</strong>: 3,000 cycles of BFGS.</li>
</ul>
<p><strong>3. Robot Kinematics Configuration (MDN)</strong></p>
<ul>
<li><strong>Structure</strong>: MLP with 2 inputs ($x_1, x_2$).</li>
<li><strong>Hidden Units</strong>: 10 units (tanh activation).</li>
<li><strong>Outputs</strong>: 8 units.
<ul>
<li>$m=2$ Gaussian kernels.</li>
<li>Target dimension $c=2$ (predicting $\theta_1, \theta_2$).</li>
<li>Parameters per kernel: 1 $\alpha$ + 1 $\sigma$ (common variance) + 2 $\mu$ (means for $\theta_1, \theta_2$).</li>
<li>Total = $2 \times (1 + 1 + 2) = 8$.</li>
</ul>
</li>
</ul>
<h3 id="evaluation">Evaluation</h3>
<p><strong>Metric</strong>: RMS Euclidean distance between the desired end-effector position and the achieved position (calculated by plugging predicted angles back into forward kinematics).</p>
<table>
	<thead>
			<tr>
					<th>Model</th>
					<th>Hidden Units</th>
					<th>Kernels</th>
					<th>RMS Error</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Least Squares</td>
					<td>20</td>
					<td>N/A</td>
					<td>0.0578</td>
			</tr>
			<tr>
					<td>MDN</td>
					<td>10</td>
					<td>2</td>
					<td>0.0053</td>
			</tr>
	</tbody>
</table>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Bishop, C. M. (1994). Mixture Density Networks. <em>Neural Computing Research Group Report: NCRG/94/004</em>, Aston University.</p>
<p><strong>Publication</strong>: Neural Computing Research Group Technical Report 1994</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@techreport</span>{bishopMixtureDensityNetworks1994,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span> = <span style="color:#e6db74">{Mixture {{Density Networks}}}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span> = <span style="color:#e6db74">{Bishop, Christopher M.}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span> = <span style="color:#ae81ff">1994</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">month</span> = feb,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">number</span> = <span style="color:#e6db74">{NCRG/94/004}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">institution</span> = <span style="color:#e6db74">{Aston University}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Graph Perception for Chemical Structure OCR</title><link>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/rule-based/contreras-ocr-1990/</link><pubDate>Sun, 14 Dec 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/rule-based/contreras-ocr-1990/</guid><description>A 1990 methodological paper presenting an early OCR system for digitizing chemical structure images into connectivity tables using C and Prolog.</description><content:encoded><![CDATA[<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Contreras, M. L., Allendes, C., Alvarez, L. T., &amp; Rozas, R. (1990). Computational perception and recognition of digitized molecular structures. <em>Journal of Chemical Information and Computer Sciences</em>, 30(3), 302-307. <a href="https://doi.org/10.1021/ci00067a014">https://doi.org/10.1021/ci00067a014</a></p>
<p><strong>Publication</strong>: Journal of Chemical Information and Computer Sciences, 1990</p>
<h2 id="contribution-graph-perception-and-character-recognition">Contribution: Graph Perception and Character Recognition</h2>
<p>This is a <strong>Methodological Paper ($\Psi_{\text{Method}}$)</strong>.</p>
<p>It proposes a specific algorithmic pipeline (&ldquo;graph perception and character recognition&rdquo;) to solve the technical problem of converting pixelated images of molecules into machine-readable connectivity tables. The dominant contribution is the novel set of algorithms (contour search, circular inspection, matrix parametrization).</p>
<h2 id="motivation-automating-chemical-database-entry">Motivation: Automating Chemical Database Entry</h2>
<p>The primary motivation is to automate the input of chemical structures into databases.</p>
<ul>
<li><strong>Problem</strong>: Manual input of structures (especially large ones with stereochemistry) is time-consuming and prone to human error.</li>
<li><strong>Gap</strong>: Existing methods required significant human intervention. The authors created a system that handles the &ldquo;graph/skeleton&rdquo; and the &ldquo;alphanumeric characters&rdquo; effectively to speed up entry into systems like ARIUSA or CAD tools.</li>
</ul>
<h2 id="algorithmic-novelty-circular-inspection-processing">Algorithmic Novelty: Circular Inspection Processing</h2>
<p>The paper introduces a unified &ldquo;capture-to-recognition&rdquo; system written in C that handles both type-printed and hand-printed structures. Key novelties include:</p>
<ul>
<li><strong>Circular Inspection Algorithm</strong>: A specific technique for detecting internal rings and multiple bonds by sweeping a radius of 0.3 bond lengths around atoms.</li>
<li><strong>Hybrid Recognition</strong>: Combining &ldquo;graph perception&rdquo; (vectorizing the lines) with &ldquo;character recognition&rdquo; (OCR for atom labels) in a single pipeline.</li>
<li><strong>Matrix Parametrization for OCR</strong>: A feature extraction method that assigns hexadecimal IDs to character matrices based on pixel gradients and &ldquo;semibytes&rdquo;.</li>
</ul>
<h2 id="methodology-validation-via-custom-structure-dataset">Methodology: Validation via Custom Structure Dataset</h2>
<p>The authors validated the system by digitizing and recognizing a set of test structures:</p>
<ul>
<li><strong>Dataset</strong>: 200 type-printed structures and 50 hand-printed structures.</li>
<li><strong>Metric</strong>: &ldquo;Reliability&rdquo; percentage (correct recognition of the connectivity table).</li>
<li><strong>Speed Comparison</strong>: Measured processing time against a &ldquo;qualified person&rdquo; performing manual input for an average 20-atom molecule.</li>
</ul>
<h2 id="results-speed-and-file-size-efficiency">Results: Speed and File Size Efficiency</h2>
<ul>
<li><strong>Accuracy</strong>: The system achieved <strong>94% reliability</strong> for both type- and hand-printed graphs.</li>
<li><strong>Character Recognition</strong>: Isolated character recognition achieved <strong>&gt;99% reliability</strong>.</li>
<li><strong>Speed</strong>: The system was <strong>3-5 times faster</strong> than manual human input.</li>
<li><strong>Efficiency</strong>: The storage required for a recognized molecule (e.g., $C_{19}H_{31}N$) was significantly smaller (4.1 kb) than the raw image bitmap.</li>
</ul>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="data">Data</h3>
<p>The paper does not use a standard external dataset but rather a custom set of structures for validation.</p>
<table>
	<thead>
			<tr>
					<th style="text-align: left">Purpose</th>
					<th style="text-align: left">Dataset</th>
					<th style="text-align: left">Size</th>
					<th style="text-align: left">Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td style="text-align: left"><strong>Validation</strong></td>
					<td style="text-align: left">Type-printed structures</td>
					<td style="text-align: left">200 images</td>
					<td style="text-align: left">Used to test reliability</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong>Validation</strong></td>
					<td style="text-align: left">Hand-printed structures</td>
					<td style="text-align: left">50 images</td>
					<td style="text-align: left">&ldquo;Straight enough&rdquo; drawings required</td>
			</tr>
	</tbody>
</table>
<h3 id="algorithms">Algorithms</h3>
<p>The paper details three specific algorithmic components crucial for replication:</p>
<ol>
<li>
<p><strong>Graph Perception (Contour Search)</strong>:</p>
<ul>
<li><strong>Sweep</strong>: Left-to-right horizontal sweep to find the first pixel.</li>
<li><strong>Contour Follow</strong>: Counter-clockwise algorithm used to trace borders.</li>
<li><strong>Vertex Detection</strong>: A vertex is flagged if the linear trajectory deflection angle is $&gt;18^\circ$.</li>
<li><strong>Atom Localization</strong>: Two or more vertices in a small space indicate an atom position.</li>
</ul>
</li>
<li>
<p><strong>Circular Inspection (Branching/Rings)</strong>:</p>
<ul>
<li><strong>Radius</strong>: A circle is inspected around each atom with $r = 0.3 \times \text{single bond length}$.</li>
<li><strong>Branch Detection</strong>: &ldquo;Unknown border pixels&rdquo; found on this circle trigger new contour searches to find attached bonds or rings.</li>
</ul>
</li>
<li>
<p><strong>Character Recognition (Matrix Feature Extraction)</strong>:</p>
<ul>
<li><strong>Separation</strong>: Characters are separated into isolated matrices and &ldquo;relocated&rdquo; to the top-left corner.</li>
<li><strong>Parametrization</strong>: The matrix is divided into zones. A &ldquo;semibyte&rdquo; (4-bit code) is generated by checking for pixel density in specific directions.</li>
<li><strong>ID Assignment</strong>: Matrices are assigned a Hex ID (e.g., <code>8</code>, <code>1</code>, <code>0</code>, <code>6</code>) based on these semibytes.</li>
<li><strong>Differentiation</strong>: Secondary parameters (concavities, vertical lines) resolve conflicts (e.g., between &lsquo;b&rsquo; and &lsquo;h&rsquo;).</li>
</ul>
</li>
</ol>
<h3 id="models">Models</h3>
<p>The system does not use learned weights (neural networks). It relies on <strong>rule-based topological recognition</strong>.</p>
<ul>
<li><strong>Representation</strong>: The final output is a Prolog data structure converted into a connectivity table.</li>
<li><strong>Atom Recognition</strong>: Terminal atoms are identified by linear projection; if no pixels are found, it defaults to Carbon.</li>
</ul>
<h3 id="hardware">Hardware</h3>
<p>The performance metrics reflect 1990s hardware, useful for historical context or low-resource reimplementation.</p>
<ul>
<li><strong>Capture</strong>: PC-AT microcomputer with HP-Scanjet.</li>
<li><strong>Processing</strong>: MicroVax II (8 MB real memory, 159 MB hard disc) running Ultrix-32.</li>
<li><strong>Memory Usage</strong>: A $300 \times 300$ dpi image required ~175 kb; a recognized graph required ~1.6 kb.</li>
<li><strong>Time</strong>: Processing time per molecule was 0.7 - 1.0 minutes.</li>
</ul>
<hr>
<h2 id="citation">Citation</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@article</span>{contrerasComputationalPerceptionRecognition1990,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span> = <span style="color:#e6db74">{Computational Perception and Recognition of Digitized Molecular Structures}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span> = <span style="color:#e6db74">{Contreras, M. Leonor and Allendes, Carlos and Alvarez, L. Tomas and Rozas, Roberto}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span> = <span style="color:#ae81ff">1990</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">month</span> = aug,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">journal</span> = <span style="color:#e6db74">{Journal of Chemical Information and Computer Sciences}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">volume</span> = <span style="color:#e6db74">{30}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">number</span> = <span style="color:#e6db74">{3}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span> = <span style="color:#e6db74">{302--307}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">issn</span> = <span style="color:#e6db74">{0095-2338, 1520-5142}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">doi</span> = <span style="color:#e6db74">{10.1021/ci00067a014}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Dynamical Corrections to TST for Surface Diffusion</title><link>https://hunterheidenreich.com/notes/chemistry/molecular-simulation/surface-science/self-diffusion-lj-fcc111-1989/</link><pubDate>Sun, 14 Dec 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/chemistry/molecular-simulation/surface-science/self-diffusion-lj-fcc111-1989/</guid><description>Application of dynamical corrections formalism to TST for LJ surface diffusion, revealing bounce-back recrossings at low T.</description><content:encoded><![CDATA[<h2 id="bridging-md-and-tst-for-surface-diffusion">Bridging MD and TST for Surface Diffusion</h2>
<p>This is primarily a <strong>Methodological Paper</strong> with a secondary contribution in <strong>Discovery</strong>.</p>
<p>The authors&rsquo; primary goal is to demonstrate the validity of the &ldquo;dynamical corrections formalism&rdquo; for calculating diffusion constants. They validate this by reproducing Molecular Dynamics (MD) results at high temperatures and then extending the method into low-temperature regimes where MD is infeasible.</p>
<p>By applying this method, they uncover a specific physical phenomenon, &ldquo;bounce-back recrossings&rdquo;, that causes a dip in the diffusion coefficient at low temperatures, a detail previously unobserved.</p>
<h2 id="timescale-limits-in-molecular-dynamics">Timescale Limits in Molecular Dynamics</h2>
<p>The authors aim to solve the timescale problem in simulating surface diffusion.</p>
<p><strong>Limit of MD</strong>: Molecular Dynamics (MD) is effective at high temperatures but becomes computationally infeasible at low temperatures because the time between diffusive hops increases drastically.</p>
<p><strong>Limit of TST</strong>: Standard Transition State Theory (TST) can handle long timescales but assumes all barrier crossings are successful, ignoring correlated dynamical events like immediate recrossings or multiple jumps.</p>
<p><strong>Goal</strong>: They seek to apply a formalism that corrects TST using short-time trajectory data, allowing for accurate calculation of diffusion constants across the entire temperature range.</p>
<h2 id="the-bounce-back-mechanism">The Bounce-Back Mechanism</h2>
<p>The core novelty is the rigorous application of the dynamical corrections formalism to a multi-site system (fcc/hcp sites) to characterize non-Arrhenius behavior at low temperatures.</p>
<p><strong>Unified Approach</strong>: They demonstrate that this method works for all temperatures, bridging the gap between the &ldquo;rare-event regime&rdquo; and the high-temperature regime dominated by fluid-like motion.</p>
<p><strong>Bounce-back Mechanism</strong>: They identify a specific &ldquo;dip&rdquo; in the dynamical correction factor ($f_d &lt; 1$) at low temperatures ($T \approx 0.038$), attributed to trajectories where the adatom collides with a substrate atom on the far side of the binding site and immediately recrosses the dividing surface.</p>
<h2 id="simulating-the-lennard-jones-fcc111-surface">Simulating the Lennard-Jones fcc(111) Surface</h2>
<p>The authors performed computational experiments on a Lennard-Jones fcc(111) surface cluster.</p>
<p><strong>System Setup</strong>: A single adatom on a 3-layer substrate (30 atoms/layer) with periodic boundary conditions.</p>
<p><strong>Baselines</strong>: They compared their high-temperature results against standard Molecular Dynamics simulations to validate the method.</p>
<p><strong>Ablation of Substrate Freedom</strong>: They ran a control experiment with a 6-layer substrate (top 3 free, 800 trajectories) to confirm the bounce-back effect persisted independently of the fixed deep layers, obtaining $D/D^{TST} = 0.75 \pm 0.06$, consistent with the original result.</p>
<p><strong>Trajectory Analysis</strong>: They analyzed the angular distribution of initial momenta to characterize the specific geometry of the bounce-back trajectories. Bounce-back trajectories were more strongly peaked at $\phi = 90°$ (perpendicular to the TST gate), confirming the effect arises from interaction with the substrate atom directly across the binding site.</p>
<p><strong>Temperature Range</strong>: The full calculation spanned $0.013 \leq T \leq 0.383$ in reduced units, bridging the rare-event regime and the high-temperature fluid-like regime.</p>
<h2 id="resolving-non-arrhenius-behavior">Resolving Non-Arrhenius Behavior</h2>
<p><strong>Arrhenius Behavior of TST</strong>: The uncorrected TST diffusion constant ($D^{TST}$) followed a near-perfect Arrhenius law, with a linear least-squares fit of $\ln(D^{TST}) = -1.8 - 0.30/T$.</p>
<p><strong>High-Temperature Correction</strong>: At high T, the dynamical correction factor $D/D^{TST} &gt; 1$, indicating correlated multiple forward jumps (long flights).</p>
<p><strong>Low-Temperature Dip</strong>: At low T, $D/D^{TST} &lt; 1$ for $T = 0.013, 0.026, 0.038, 0.051$ (minimum at $T = 0.038$), caused by the bounce-back mechanism.</p>
<p><strong>Validation</strong>: The method successfully reproduced high-T literature values while providing access to low-T dynamics inaccessible to direct MD.</p>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="data">Data</h3>
<p>The paper does not use external datasets but generates simulation data based on the Lennard-Jones potential.</p>
<table>
	<thead>
			<tr>
					<th>Type</th>
					<th>Parameter</th>
					<th>Value</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><strong>Potential</strong></td>
					<td>$\epsilon, \sigma$</td>
					<td>1.0 (Reduced units)</td>
					<td>Standard Lennard-Jones 6-12</td>
			</tr>
			<tr>
					<td><strong>Cutoff</strong></td>
					<td>Spline</td>
					<td>$r_1=1.5\sigma, r_2=2.5\sigma$</td>
					<td>5th-order spline smooths potential to 0 at $r_2$</td>
			</tr>
			<tr>
					<td><strong>Geometry</strong></td>
					<td>Lattice Constant</td>
					<td>$a_0 = 1.549$</td>
					<td>Minimum energy for this potential</td>
			</tr>
			<tr>
					<td><strong>Cluster</strong></td>
					<td>Size</td>
					<td>3 layers, 30 atoms/layer</td>
					<td>Periodic boundary conditions parallel to surface</td>
			</tr>
	</tbody>
</table>
<h3 id="algorithms">Algorithms</h3>
<p>The diffusion constant $D$ is calculated as $D = D^{TST} \times (D/D^{TST})$.</p>
<p><strong>1. TST Rate Calculation ($D^{TST}$)</strong></p>
<ul>
<li><strong>Method</strong>: Monte Carlo integration of the flux through the dividing surface.</li>
<li><strong>Technique</strong>: Calculate free energy difference between the entire binding site and the TST dividing region.</li>
<li><strong>Dividing Surface</strong>: Defined geometrically with respect to equilibrium substrate positions (honeycomb boundaries around fcc/hcp sites).</li>
</ul>
<p><strong>2. Dynamical Correction Factor ($D/D^{TST}$)</strong></p>
<p>The method relies on evaluating the dynamical correction factor $f_d$, initialized via a Metropolis walk restricted to the TST boundary region, computed as:</p>
<p>$$
\begin{aligned}
f_d(i\rightarrow j) = \frac{2}{N}\sum_{I=1}^{N}\eta_{ij}(I)
\end{aligned}
$$</p>
<ul>
<li><strong>Initialization</strong>:
<ul>
<li><strong>Position</strong>: Sampled via Metropolis walk restricted to the TST boundary region.</li>
<li><strong>Momentum</strong>: Maxwellian distribution for parallel components; Maxwellian-flux distribution for normal component.</li>
<li><strong>Symmetry</strong>: Trajectories entering hcp sites are generated by reversing momenta of those entering fcc sites.</li>
</ul>
</li>
<li><strong>Integration</strong>:
<ul>
<li><strong>Integrator</strong>: Adams-Bashforth-Moulton predictor-corrector formulas of orders 1 through 12.</li>
<li><strong>Duration</strong>: Integrated until time $t &gt; \tau_{corr}$ (approximately $\tau_{corr} \approx 13$ reduced time units).</li>
<li><strong>Sample Size</strong>: 1400 trajectories per temperature point (700 initially entering each type of site).</li>
</ul>
</li>
</ul>
<h3 id="models">Models</h3>
<ul>
<li><strong>System</strong>: Single component Lennard-Jones solid (Argon-like).</li>
<li><strong>Adsorbate</strong>: Single adatom on fcc(111) surface.</li>
<li><strong>Substrate Flexibility</strong>: Adatom plus top layer atoms are free to move. Layers 2 and 3 are fixed. (Validation run used 6 layers with top 3 free).</li>
</ul>
<h3 id="evaluation">Evaluation</h3>
<p>The primary metric is the Diffusion Constant $D$, analyzed via the Dynamical Correction Factor.</p>
<table>
	<thead>
			<tr>
					<th>Metric</th>
					<th>Value</th>
					<th>Baseline</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><strong>Slope ($E_a$)</strong></td>
					<td>0.30</td>
					<td>0.303 fcc / 0.316 hcp (Newton-Raphson)</td>
					<td>TST slope in good agreement with static barrier height.</td>
			</tr>
			<tr>
					<td><strong>$D/D^{TST}$ (Low T)</strong></td>
					<td>$0.82 \pm 0.04$</td>
					<td>1.0 (TST)</td>
					<td>At $T=0.038$. Indicates 18% reduction due to recrossing.</td>
			</tr>
			<tr>
					<td><strong>$D/D^{TST}$ (High T)</strong></td>
					<td>$&gt; 1.0$</td>
					<td>MD Literature</td>
					<td>Increases with T due to multiple jumps.</td>
			</tr>
	</tbody>
</table>
<h3 id="hardware">Hardware</h3>
<p>Specific hardware configurations (e.g., node architectures, supercomputers) or training times were not specified in the original publication, which is typical for 1989 literature. Modern open-source MD engines (e.g., LAMMPS, ASE) could perform identical Lennard-Jones molecular dynamics integrations in negligible time on any consumer workstation.</p>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Cohen, J. M., &amp; Voter, A. F. (1989). Self-diffusion on the Lennard-Jones fcc(111) surface: Effects of temperature on dynamical corrections. <em>The Journal of Chemical Physics</em>, 91(8), 5082-5086. <a href="https://doi.org/10.1063/1.457599">https://doi.org/10.1063/1.457599</a></p>
<p><strong>Publication</strong>: The Journal of Chemical Physics 1989</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@article</span>{cohenSelfDiffusionLennard1989,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span> = <span style="color:#e6db74">{Self-diffusion on the {{Lennard}}-{{Jones}} Fcc(111) Surface: {{Effects}} of Temperature on Dynamical Corrections}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">shorttitle</span> = <span style="color:#e6db74">{Self-diffusion on the {{Lennard}}-{{Jones}} Fcc(111) Surface}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span> = <span style="color:#e6db74">{Cohen, J. M. and Voter, A. F.}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span> = <span style="color:#e6db74">{1989}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">month</span> = oct,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">journal</span> = <span style="color:#e6db74">{The Journal of Chemical Physics}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">volume</span> = <span style="color:#e6db74">{91}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">number</span> = <span style="color:#e6db74">{8}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span> = <span style="color:#e6db74">{5082--5086}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">issn</span> = <span style="color:#e6db74">{0021-9606, 1089-7690}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">doi</span> = <span style="color:#e6db74">{10.1063/1.457599}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">langid</span> = <span style="color:#e6db74">{english}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Chemical Machine Vision</title><link>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/rule-based/chemical-machine-vision/</link><pubDate>Sun, 14 Dec 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/rule-based/chemical-machine-vision/</guid><description>Machine vision approach using Gabor wavelets and Kohonen networks to classify chemical raster images and extract structural metadata.</description><content:encoded><![CDATA[<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Gkoutos, G. V., Rzepa, H., Clark, R. M., Adjei, O., &amp; Johal, H. (2003). Chemical Machine Vision: Automated Extraction of Chemical Metadata from Raster Images. <em>Journal of Chemical Information and Computer Sciences</em>, 43(5), 1342-1355. <a href="https://doi.org/10.1021/ci034017n">https://doi.org/10.1021/ci034017n</a></p>
<p><strong>Publication</strong>: J. Chem. Inf. Comput. Sci. 2003</p>
<h2 id="paper-classification-methodological-approach">Paper Classification: Methodological Approach</h2>
<p>This is a <strong>Method</strong> paper. It proposes a novel architectural pipeline applying &ldquo;machine vision&rdquo; techniques (Gabor wavelets and Kohonen networks) to the problem of identifying chemical diagrams in low-resolution raster images. The paper focuses on the &ldquo;how&rdquo; (the algorithm and its parameters) and validates the method through quantitative experiments optimizing feature vectors and masks.</p>
<h2 id="motivation-extracting-legacy-chemical-data">Motivation: Extracting Legacy Chemical Data</h2>
<p>The primary motivation is to unlock the &ldquo;large amount of data&rdquo; trapped in legacy raster images (GIF, JPEG) on the Web that lack semantic metadata.</p>
<ul>
<li><strong>Legacy Data Problem</strong>: Most chemical structural information on the Web is embedded in raster images, not machine-readable formats like Molfiles.</li>
<li><strong>Limitations of Existing Tools</strong>: Previous tools like Kekule and CLiDE acted as &ldquo;Chemical OCR,&rdquo; attempting to reconstruct exact atom-bond connections. This required high-resolution images (&gt;300 dpi) and human intervention, making them unsuitable for automated Web crawling of low-resolution (72-96 dpi) images.</li>
<li><strong>Goal</strong>: To create a low-cost, automated tool for a &ldquo;robot-based Internet resource discovery tool&rdquo; that can classify images (e.g., &ldquo;is this a molecule?&rdquo;).</li>
</ul>
<h2 id="core-innovation-texture-recognition-over-structural-ocr">Core Innovation: Texture Recognition over Structural OCR</h2>
<p>The core novelty is the shift from &ldquo;Optical Character Recognition&rdquo; (exact reconstruction) to <strong>&ldquo;Texture Recognition&rdquo;</strong> (classification).</p>
<ul>
<li><strong>Texture-Based Approach</strong>: The authors treat chemical diagrams as textures. They use <strong>Gabor wavelets</strong> to extract texture features. <strong>Crucially, this system does not recognize specific chemical structures</strong> (i.e., atom-bond connectivity tables, <a href="/notes/chemistry/molecular-representations/notations/smiles/">SMILES</a>, or Molfiles). It only classifies images into broad categories.</li>
<li><strong>Incremental Learning</strong>: The system uses a <strong>Kohonen Self-Organizing Feature Map (KSOFM)</strong> combined with Class Boundary Analysis (CBA). This allows for &ldquo;incremental learning,&rdquo; where new classes (e.g., aromatic vs. non-aromatic) can be added without retraining the entire system.</li>
<li><strong>Optimization for Chemistry</strong>: The authors identify specific parameters (frequency channels, mask sizes) that are optimal for the &ldquo;texture&rdquo; of chemical diagrams.</li>
<li><strong>Integration with ChemDig</strong>: The method was designed to feed into ChemDig, a robot-based index engine for automated web crawling and metadata generation.</li>
</ul>
<h2 id="experimental-setup-parameter-optimization">Experimental Setup: Parameter Optimization</h2>
<p>The authors performed optimization and validation experiments using a dataset of <strong>300 images</strong> divided into three classes: Ring Systems, Non-Ring Systems, and Non-Chemistry (textures, biological figures, etc.).</p>
<ol>
<li><strong>Parameter Optimization</strong>: They systematically varied hyperparameters to find the optimal configuration:
<ul>
<li><strong>Feature Vector Size</strong>: Tested sizes from 100 to 4000 elements.</li>
<li><strong>Energy Mask Size</strong>: Tested windows from $3 \times 3$ to $15 \times 15$ pixels.</li>
<li><strong>Frequency Channels</strong>: Tested seven spatial frequencies ($\sqrt{2}$ to $64\sqrt{2}$).</li>
</ul>
</li>
<li><strong>Classification Performance</strong>: Evaluated the system&rsquo;s ability to classify unseen test images using a 50:50 training/test split.</li>
<li><strong>Comparison</strong>: Qualitatively compared the approach against vectorization tools (Autotrace, CR2V).</li>
</ol>
<h2 id="results-robust-classification-of-low-resolution-images">Results: Robust Classification of Low-Resolution Images</h2>
<ul>
<li><strong>Optimal Configuration</strong>: The system performed best with a feature vector size of ~1500 elements, a $9 \x9$ energy mask, and frequency channel $4\sqrt{2}$.</li>
<li><strong>High Accuracy</strong>: Achieved a recognition rate of <strong>91%</strong> with a 50:50 training/test split, and up to <strong>92%</strong> with a 70:30 split.</li>
<li><strong>Robustness</strong>: The system successfully distinguished between chemical and non-chemical images (zero false negatives for chemical images).</li>
<li><strong>Limitations</strong>: Misclassifications occurred between &ldquo;ring&rdquo; and &ldquo;non-ring&rdquo; systems when structures had similar visual &ldquo;textures&rdquo; (e.g., similar density or layout).</li>
<li><strong>Impact</strong>: The method is viable for automating metadata generation (e.g., <code>alt</code> tags) for web crawlers, functioning as a coarse-grained filter before more expensive processing.</li>
</ul>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="data">Data</h3>
<p>The study used a custom dataset of raster images collected from the Web.</p>
<table>
	<thead>
			<tr>
					<th>Purpose</th>
					<th>Dataset</th>
					<th>Size</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Training/Eval</td>
					<td><strong>Custom Web Dataset</strong></td>
					<td>300 images</td>
					<td>Split into 3 classes: Ring Systems, Non-Ring Systems, Non-Chemistry.</td>
			</tr>
			<tr>
					<td>Resolution</td>
					<td><strong>Low-Res Web Images</strong></td>
					<td>72-96 dpi</td>
					<td>Deliberately chosen to mimic Web conditions where OCR fails.</td>
			</tr>
			<tr>
					<td>Format</td>
					<td><strong>Raster</strong></td>
					<td>GIF, JPEG</td>
					<td>Typical web formats.</td>
			</tr>
	</tbody>
</table>
<h3 id="algorithms">Algorithms</h3>
<p>The core pipeline consists of a <strong>Gabor Transform Unit</strong> followed by a <strong>Training/Classification Unit</strong>.</p>
<ul>
<li><strong>Gabor Wavelets</strong>: Used for feature extraction. The 2D Gabor wavelet equation is:
$$h(x,y)=\exp\left{-\frac{1}{2}\left[\frac{x^{2}}{\sigma_{x}^{2}}+\frac{y^{2}}{\sigma_{y}^{2}}\right]\right}\cos(2\pi\mu_{\sigma}x+\phi)$$
<ul>
<li><strong>Bank Structure</strong>: 28 filters total (4 orientations $\times$ 7 radial frequencies).</li>
<li><strong>Orientations</strong>: $0^{\circ}, 45^{\circ}, 90^{\circ}, 135^{\circ}$.</li>
<li><strong>Frequencies</strong>: 1 octave apart, specifically $1\sqrt{2}, \dots, 64\sqrt{2}$.</li>
<li><strong>Selected Frequency</strong>: $4\sqrt{2}$ was found to be optimal for chemistry.</li>
</ul>
</li>
<li><strong>Preprocessing</strong>:
<ul>
<li><strong>Buffer Mounting</strong>: Images are mounted in a buffer (set to 0) to handle edge artifacts.</li>
<li><strong>Look-Up-Tables (LUT/LUF)</strong>: A binary Look-Up-Frame (LUF) indicates Regions of Interest (ROI) to avoid computing empty space; values are stored in a Look-Up-Table (LUT) to prevent re-computation of overlapping windows.</li>
</ul>
</li>
<li><strong>Feature Extraction</strong>:
<ul>
<li><strong>Non-linear Thresholding</strong>: $\psi(t) = \tanh(\alpha t)$ with $\alpha = 0.25$.</li>
<li><strong>Energy Function</strong>: Calculated as average absolute deviation from the mean using a window $W_{xy}$.
$$e_{k}(x,y)=\frac{1}{M^{2}}\sum_{(a,b)\in W_{xy}}|\psi(r_{k}(a,b))|$$</li>
<li><strong>Optimal Window</strong>: $9 \times 9$ pixels.</li>
</ul>
</li>
</ul>
<h3 id="models">Models</h3>
<p>The classification model relies on competitive learning.</p>
<ul>
<li><strong>Architecture</strong>: <strong>Kohonen Self-Organizing Feature Map (KSOFM)</strong>.</li>
<li><strong>Training</strong>:
<ul>
<li><strong>Learning Rate</strong>: Starts at 1.0, decreases to 0.1.</li>
<li><strong>Class Boundary Analysis (CBA)</strong>: Computes the centroid (mean) and variance of each cluster. The variance defines the class boundary.</li>
</ul>
</li>
<li><strong>Classification Metric</strong>: <strong>Euclidean Distance Norm</strong>. An unknown vector is classified based on the shortest distance to a cluster center, provided it falls within the variance boundary.
$$D_{ij}=||x_{i}-x_{j}||$$</li>
</ul>
<h3 id="evaluation">Evaluation</h3>
<p>Performance was measured using recognition rate ($R_s$) and misclassification error ($E_s$).</p>
<table>
	<thead>
			<tr>
					<th>Metric</th>
					<th>Value</th>
					<th>Baseline</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Recognition Rate</td>
					<td><strong>91%</strong></td>
					<td>N/A</td>
					<td>Achieved with 50:50 split. 92% with 70:30 split.</td>
			</tr>
			<tr>
					<td>Feature Size</td>
					<td><strong>~1500</strong></td>
					<td>4000</td>
					<td>Reducing vector size from 4000 to 1500 maintained ~80% accuracy while improving speed.</td>
			</tr>
	</tbody>
</table>
<hr>
<h2 id="citation">Citation</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@article</span>{gkoutosChemicalMachineVision2003,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span> = <span style="color:#e6db74">{Chemical {{Machine Vision}}: {{Automated Extraction}} of {{Chemical Metadata}} from {{Raster Images}}}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">shorttitle</span> = <span style="color:#e6db74">{Chemical {{Machine Vision}}}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span> = <span style="color:#e6db74">{Gkoutos, Georgios V. and Rzepa, Henry and Clark, Richard M. and Adjei, Osei and Johal, Harpal}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span> = <span style="color:#ae81ff">2003</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">month</span> = sep,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">journal</span> = <span style="color:#e6db74">{Journal of Chemical Information and Computer Sciences}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">volume</span> = <span style="color:#e6db74">{43}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">number</span> = <span style="color:#e6db74">{5}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span> = <span style="color:#e6db74">{1342--1355}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">issn</span> = <span style="color:#e6db74">{0095-2338}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">doi</span> = <span style="color:#e6db74">{10.1021/ci034017n}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">urldate</span> = <span style="color:#e6db74">{2025-12-15}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">langid</span> = <span style="color:#e6db74">{english}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Chemical Literature Data Extraction: The CLiDE Project</title><link>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/rule-based/clide-1993/</link><pubDate>Sun, 14 Dec 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/rule-based/clide-1993/</guid><description>Seminal OCSR system converting scanned chemical diagrams into connection tables via primitive recognition and semantic interpretation.</description><content:encoded><![CDATA[<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Ibison, P., Jacquot, M., Kam, F., Neville, A. G., Simpson, R. W., Tonnelier, C., Venczel, T., &amp; Johnson, A. P. (1993). Chemical Literature Data Extraction: The CLiDE Project. <em>Journal of Chemical Information and Computer Sciences</em>, 33(3), 338-344. <a href="https://doi.org/10.1021/ci00013a010">https://doi.org/10.1021/ci00013a010</a></p>
<p><strong>Publication</strong>: J. Chem. Inf. Comput. Sci. 1993</p>
<h2 id="contribution-and-taxonomy">Contribution and Taxonomy</h2>
<p><strong>Classification: Method ($\Psi_{\text{Method}}$)</strong></p>
<p>This methodological paper proposes a novel software architecture for Optical Chemical Structure Recognition (OCSR). It details specific algorithms for image segmentation, vectorization, and chemical interpretation, validated through the successful extraction of complex structures from literature.</p>
<h2 id="motivation-automating-literature-extraction">Motivation: Automating Literature Extraction</h2>
<p>The manual creation of chemical reaction databases is a time-consuming and expensive process requiring trained chemists to abstract information from literature. While commercial tools existed for interpreting isolated scanned structures (like Kekulé), there was a lack of systems capable of processing whole pages of journals (including embedded text, reaction schemes, and structures) without significant human intervention.</p>
<h2 id="core-innovation-a-three-phase-hybrid-architecture">Core Innovation: A Three-Phase Hybrid Architecture</h2>
<p>CLiDE introduces a comprehensive <strong>three-phase architecture</strong> (Recognition, Grouping, Interpretation) that integrates computer vision with chemical knowledge. Key novelties include:</p>
<ul>
<li><strong>Context-Aware Interpretation:</strong> The use of an extendable <strong>superatom database</strong> to resolve ambiguities in chemical text (e.g., expanding &ldquo;OAc&rdquo; or &ldquo;Me&rdquo; into connection tables).</li>
<li><strong>Hybrid Primitive Detection:</strong> A combination of contour coding for solid lines and a modified Hough transform specifically tuned for detecting dashed chemical bonds.</li>
<li><strong>Semantic Re-construction:</strong> A scoring system for bond-atom association that considers both distance and vector direction to handle poorly drawn structures.</li>
</ul>
<h2 id="methodology-and-experimental-validation">Methodology and Experimental Validation</h2>
<p>The authors validated the system on a set of &ldquo;difficult cases&rdquo; selected to test specific capabilities. These included:</p>
<ul>
<li><strong>Crossing Bonds:</strong> Structures where bonds intersect without a central atom (Fig. 9d, 9e).</li>
<li><strong>Stereochemistry:</strong> Identification of wedged, dashed, and wavy bonds.</li>
<li><strong>Generic Structures:</strong> Parsing generic text blocks (e.g., $R^1 = Me$) and performing substitutions.</li>
<li><strong>Accuracy Estimation:</strong> The authors report an approximate 90% recognition rate for distinct characters in literature scans.</li>
</ul>
<h2 id="results-and-structural-reconstruction">Results and Structural Reconstruction</h2>
<p>The system successfully generates connection tables (exported as MOLfiles or ChemDraw files) from scanned bitmaps. It effectively distinguishes between graphical primitives (wedges, lines) and text, accurately reconstructing stereochemistry and resolving superatom synonyms (e.g., converting &ldquo;MeO&rdquo; to &ldquo;OMe&rdquo;). The authors conclude that while character recognition depends heavily on image quality, the graphic primitive recognition is robust for lines above a threshold length.</p>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="data">Data</h3>
<ul>
<li><strong>Input Format:</strong> Binary bitmaps scanned from journal pages.</li>
<li><strong>Resolution:</strong> 300 dpi (generating ~1 MB per page).</li>
<li><strong>Superatom Database:</strong> A lookup table containing ~200 entries. Each entry includes:
<ul>
<li><strong>Valency/Charge:</strong> Explicit constraints (e.g., &ldquo;HO&rdquo; takes 1 bond, &ldquo;CO2&rdquo; takes 2).</li>
<li><strong>Bonding Index:</strong> Specifies which letter in the string serves as the attachment point (e.g., letter 2 for &ldquo;HO&rdquo;, letters 1 and 2 for &ldquo;CO2&rdquo;).</li>
<li><strong>Sub-Connection Table:</strong> The internal atomic representation of the group.</li>
</ul>
</li>
</ul>
<h3 id="algorithms">Algorithms</h3>
<p><strong>1. Primitive Recognition (Vectorization)</strong></p>
<ul>
<li><strong>Contour Coding:</strong> Uses the <strong>Ahronovitz-Bertier-Habib</strong> method to generate interpixel contours (directions N, S, E, W) for connected components.</li>
<li><strong>Polygonal Approximation:</strong> A method similar to <strong>Sklansky and Gonzalez</strong> breaks contours into &ldquo;fractions&rdquo;.
<ul>
<li><em>Rule:</em> Long sides are &ldquo;straight fractions&rdquo;; consecutive short sides are &ldquo;curved fractions&rdquo;.</li>
<li><em>Reconstruction:</em> Parallel fractions are paired to form bond borders. If a border is split (due to noise or crossing lines), the system attempts to merge collinear segments.</li>
</ul>
</li>
<li><strong>Dash Detection:</strong> A <strong>modified Hough transform</strong> is applied to small connected components. It requires at least <strong>three collinear dashes</strong> to classify a sequence as a dashed bond.</li>
</ul>
<p><strong>2. Interpretation Rules</strong></p>
<ul>
<li><strong>Bond-Atom Association:</strong>
<ul>
<li><em>Candidate Selection:</em> The system identifies $m$ closest bonds for a superatom requiring $n$ connections ($m \ge n$).</li>
<li><em>Scoring Function:</em> Connections are selected based on minimizing <strong>perpendicular distance</strong> (alignment).</li>
</ul>
</li>
<li><strong>Crossing Bonds:</strong> Resolved using rules based on <strong>proximity, length, collinearity, and ring membership</strong> to distinguish actual crossings from central carbon atoms.</li>
</ul>
<h3 id="models">Models</h3>
<ul>
<li><strong>OCR:</strong> A neural network trained on alphanumeric characters.
<ul>
<li><strong>Input Representation:</strong> Density matrices derived from character bitmaps.</li>
<li><strong>Post-processing:</strong> Unrecognized characters are flagged for manual correction.</li>
</ul>
</li>
</ul>
<h3 id="hardware">Hardware</h3>
<ul>
<li><strong>Platform:</strong> SUN SPARC workstation.</li>
<li><strong>Scanner:</strong> Agfa Focus S 800GS.</li>
<li><strong>Implementation Language:</strong> C++.</li>
</ul>
<hr>
<h2 id="citation">Citation</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@article</span>{ibisonChemicalLiteratureData1993,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span> = <span style="color:#e6db74">{Chemical Literature Data Extraction: {{The CLiDE Project}}}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">shorttitle</span> = <span style="color:#e6db74">{Chemical Literature Data Extraction}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span> = <span style="color:#e6db74">{Ibison, P. and Jacquot, M. and Kam, F. and Neville, A. G. and Simpson, R. W. and Tonnelier, C. and Venczel, T. and Johnson, A. P.}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span> = <span style="color:#ae81ff">1993</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">month</span> = may,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">journal</span> = <span style="color:#e6db74">{Journal of Chemical Information and Computer Sciences}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">volume</span> = <span style="color:#e6db74">{33}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">number</span> = <span style="color:#e6db74">{3}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span> = <span style="color:#e6db74">{338--344}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">issn</span> = <span style="color:#e6db74">{0095-2338, 1520-5142}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">doi</span> = <span style="color:#e6db74">{10.1021/ci00013a010}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Automatic Recognition of Chemical Images</title><link>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/rule-based/algorri-chemical-image-recognition-2007/</link><pubDate>Sun, 14 Dec 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/rule-based/algorri-chemical-image-recognition-2007/</guid><description>A rule-based system for extracting chemical structure information from raster images, validated against commercial baselines.</description><content:encoded><![CDATA[<h2 id="contribution-rule-based-image-mining-architecture">Contribution: Rule-Based Image Mining Architecture</h2>
<p><strong>$\Psi_{\text{Method}}$ (Methodological Basis)</strong></p>
<p>This is a methodological paper describing a system architecture for <strong>image mining</strong> in the chemical domain. It focuses on the engineering challenge of converting rasterized depictions of molecules into computer-readable SDF files. The paper details the algorithmic pipeline and validates it through quantitative benchmarking against a commercial alternative.</p>
<h2 id="motivation-digitizing-chemical-literature">Motivation: Digitizing Chemical Literature</h2>
<ul>
<li><strong>Loss of Information</strong>: Chemical software creates images. The chemical significance is lost when published in scientific literature, making the data &ldquo;dead&rdquo; to computers.</li>
<li><strong>Gap in Technology</strong>: Image mining lags behind advances in text mining. Existing commercial solutions (like CLIDE) faded away or remained limited.</li>
<li><strong>Scale of Problem</strong>: The colossal production of chemical documents requires automated tools to exploit this information at large scale.</li>
</ul>
<h2 id="core-innovation-graph-preserving-vectorization">Core Innovation: Graph-Preserving Vectorization</h2>
<ul>
<li><strong>Graph-Preserving Vectorization</strong>: The system uses a custom vectorizer designed to preserve the &ldquo;graph characteristics&rdquo; of chemical diagrams (1 vector = 1 line), which avoids creating spurious vectors at thick joints. It aims to generate a mathematical graph, $G = (V, E)$, mapped geometrically to the image lines.</li>
<li><strong>Chemical Knowledge Integration</strong>: A distinct module validates the reconstructed graph against chemical rules (valences, charges) to ensure the output is chemically valid.</li>
<li><strong>Hybrid Processing</strong>: The system splits the image into &ldquo;connected components&rdquo; for an OCR path (text/symbols) and a &ldquo;body&rdquo; path (bonds), reassembling them later.</li>
</ul>
<h2 id="methodology--experiments-benchmark-validation">Methodology &amp; Experiments: Benchmark Validation</h2>
<p>The authors performed a quantitative validation using <strong>three different databases</strong> where ground-truth SDF files were available. They also compared their system against the commercial tool <strong>CLIDE</strong> (Chemical Literature Data Extraction).</p>
<ul>
<li><strong>Database 1</strong>: 100 images (varied line widths/fonts)</li>
<li><strong>Database 2</strong>: 100 images</li>
<li><strong>Database 3</strong>: 7,604 images (large-scale batch processing)</li>
</ul>
<h2 id="results--conclusions-superior-accuracy-over-baselines">Results &amp; Conclusions: Superior Accuracy over Baselines</h2>
<ul>
<li><strong>High Accuracy</strong>: The system achieved <strong>94%</strong> correct reconstruction on Database 1 and <strong>77%</strong> on Database 2. Accuracy was measured as correct recovery of identical geometry and connections.</li>
</ul>
<p>$$ \text{Acc} = \frac{\text{Correct Images}}{\text{Total Images}} $$</p>
<ul>
<li><strong>Baseline Superiority</strong>: The commercial tool CLIDE only successfully reconstructed ~50% of images in Database 1 (compared to the authors&rsquo; 94%).</li>
<li><strong>Scalability</strong>: On the large dataset (Database 3), the system achieved <strong>67%</strong> accuracy in batch mode.</li>
<li><strong>Robustness</strong>: The authors state the system uses a handful of parameters and works robustly across different image types. CLIDE lacked flexibility and required manual intervention.</li>
</ul>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<p><strong>Reproducibility Status</strong>: Closed / Not Formally Reproducible. As is common with applied research from this era, the source code, training models (SVM), and specific datasets used for benchmarking do not appear to be publicly maintained or available.</p>
<h3 id="artifacts">Artifacts</h3>
<table>
	<thead>
			<tr>
					<th style="text-align: left">Artifact</th>
					<th style="text-align: left">Type</th>
					<th style="text-align: left">License</th>
					<th style="text-align: left">Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td style="text-align: left"><em>None available</em></td>
					<td style="text-align: left">N/A</td>
					<td style="text-align: left">Unknown</td>
					<td style="text-align: left">No public code, models, or datasets were released with this 2007 publication.</td>
			</tr>
	</tbody>
</table>
<h3 id="data">Data</h3>
<table>
	<thead>
			<tr>
					<th>Purpose</th>
					<th>Dataset</th>
					<th>Size</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Evaluation</td>
					<td>Database 1</td>
					<td>100 Images</td>
					<td>Used for comparison with CLIDE; 94% success rate</td>
			</tr>
			<tr>
					<td>Evaluation</td>
					<td>Database 2</td>
					<td>100 Images</td>
					<td>77% success rate</td>
			</tr>
			<tr>
					<td>Evaluation</td>
					<td>Database 3</td>
					<td>7,604 Images</td>
					<td>Large-scale test; 67% success rate</td>
			</tr>
	</tbody>
</table>
<h3 id="algorithms">Algorithms</h3>
<p>The paper outlines a 5-module pipeline:</p>
<ol>
<li><strong>Pre-processing</strong>: Adaptive histogram binarization and non-recursive connected component labeling using RLE segments.</li>
<li><strong>OCR</strong>: A &ldquo;chemically oriented OCR&rdquo; using wavelet functions for feature extraction and a <strong>Support Vector Machine (SVM)</strong> for classification. It distinguishes characters from molecular structure.</li>
<li><strong>Vectorizer</strong>: Assigns local directions to RLE segments and groups them into patterns. Crucially, it enforces a one-to-one mapping between image lines and graph vectors.</li>
<li><strong>Reconstruction</strong>: A rule-based module that annotates vectors:
<ul>
<li><strong>Stereochemistry</strong>: Registers vectors against original pixels; thick geometric forms (triangles) become chiral wedges.</li>
<li><strong>Dotted Bonds</strong>: Identifies isolated vectors and clusters them using <strong>quadtree clustering</strong>.</li>
<li><strong>Multi-bonds</strong>: Identifies parallel vectors within a dilated bounding box (factor of 2).</li>
</ul>
</li>
<li><strong>Chemical Knowledge</strong>: Validates the graph valences and properties before exporting SDF.</li>
</ol>
<h3 id="models">Models</h3>
<ul>
<li><strong>SVM</strong>: Used in the OCR module to classify text/symbols. It supports dynamic training to correct classification mistakes.</li>
</ul>
<h3 id="evaluation">Evaluation</h3>
<p>The primary metric is the percentage of correctly reconstructed images (generating a valid, matching SDF file).</p>
<table>
	<thead>
			<tr>
					<th>Metric</th>
					<th>System Value (DB1)</th>
					<th>Baseline (CLIDE)</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Reconstruction Accuracy</td>
					<td><strong>94%</strong></td>
					<td>~50%</td>
					<td>CLIDE noted as unsuitable for batch processing</td>
			</tr>
	</tbody>
</table>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Algorri, M.-E., Zimmermann, M., &amp; Hofmann-Apitius, M. (2007). Automatic Recognition of Chemical Images. <em>Eighth Mexican International Conference on Current Trends in Computer Science</em>, 41-46. <a href="https://doi.org/10.1109/ENC.2007.25">https://doi.org/10.1109/ENC.2007.25</a></p>
<p><strong>Publication</strong>: ENC 2007 (IEEE Computer Society)</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@inproceedings</span>{algorriAutomaticRecognitionChemical2007,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span> = <span style="color:#e6db74">{Automatic {{Recognition}} of {{Chemical Images}}}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">booktitle</span> = <span style="color:#e6db74">{Eighth {{Mexican International Conference}} on {{Current Trends}} in {{Computer Science}} ({{ENC}} 2007)}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span> = <span style="color:#e6db74">{Algorri, Maria-Elena and Zimmermann, Marc and {Hofmann-Apitius}, Martin}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span> = <span style="color:#e6db74">{2007}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span> = <span style="color:#e6db74">{41--46}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">publisher</span> = <span style="color:#e6db74">{IEEE}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">doi</span> = <span style="color:#e6db74">{10.1109/ENC.2007.25}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Mixfile &amp; MInChI: Machine-Readable Mixture Formats</title><link>https://hunterheidenreich.com/notes/chemistry/molecular-representations/notations/mixfile-minchi/</link><pubDate>Sun, 12 Oct 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/chemistry/molecular-representations/notations/mixfile-minchi/</guid><description>Mixfile and MInChI provide the first standardized, machine-readable formats for representing chemical mixtures.</description><content:encoded><![CDATA[<h2 id="a-standardized-resource-for-chemical-mixtures">A Standardized Resource for Chemical Mixtures</h2>
<p>This is a <strong>Resource</strong> paper that introduces two complementary standards for representing chemical mixtures: the detailed <strong>Mixfile</strong> format for comprehensive mixture descriptions and the compact <strong>MInChI</strong> (Mixtures InChI) specification for canonical mixture identifiers.</p>
<h2 id="the-missing-format-for-complex-formulations">The Missing Format for Complex Formulations</h2>
<p>There is a fundamental gap in chemical informatics: current standards excel at representing pure individual molecules (SMILES, InChI, Molfile), but a corresponding standard for multi-component mixtures remains an open challenge. This is a major problem because real-world chemistry predominantly involves complex mixtures.</p>
<p>Everyday chemical work frequently involves:</p>
<ul>
<li>Reagents with specified purity (e.g., &ldquo;$\geq$ 97% pure&rdquo;)</li>
<li>Solutions and formulations</li>
<li>Complex mixtures like &ldquo;hexanes&rdquo; (which contains multiple isomers)</li>
<li>Drug formulations with active ingredients and excipients</li>
</ul>
<p>Without a machine-readable standard, chemists are forced to describe these mixtures in plain text that software cannot parse or analyze systematically. This creates barriers for automated safety analysis, inventory management, and data sharing.</p>
<h2 id="dual-design-comprehensive-mixfiles-and-canonical-minchis">Dual Design: Comprehensive Mixfiles and Canonical MInChIs</h2>
<p>The authors propose a two-part solution:</p>
<ol>
<li><strong>Mixfile</strong>: A detailed, hierarchical JSON format that captures the complete composition of a mixture</li>
<li><strong>MInChI</strong>: A compact, canonical string identifier derived from Mixfile data</li>
</ol>
<p>This dual approach provides both comprehensive description (Mixfile) and simple identification (MInChI), similar to having both a detailed recipe and a short name for a dish.</p>
<h3 id="what-makes-a-good-mixture-format">What Makes a Good Mixture Format?</h3>
<p>The authors identify three essential properties any mixture format must capture:</p>
<ol>
<li><strong>Compound</strong>: What molecules are present?</li>
<li><strong>Quantity</strong>: How much of each component?</li>
<li><strong>Hierarchy</strong>: How are components organized (e.g., mixtures-of-mixtures)?</li>
</ol>
<p>The hierarchical aspect is crucial. Consider &ldquo;hexanes&rdquo;: it is a named mixture containing specific proportions of n-hexane, 2-methylpentane, 3-methylpentane, etc. A mixture format needs to represent both the individual isomers and the fact that they are grouped under the umbrella term &ldquo;hexanes.&rdquo;</p>
<h3 id="mixfile-format-details">Mixfile Format Details</h3>
<p>Mixfile uses JSON as its foundation, making it both human-readable and easy to parse in modern programming languages. The core structure is a hierarchical tree where each component can contain:</p>
<ul>
<li><strong>name</strong>: Component identifier</li>
<li><strong>molfile/smiles/inchi/formula</strong>: Molecular structure (molfile is the primary source of truth)</li>
<li><strong>quantity/units/relation/ratio</strong>: Concentration data with optional relation operators</li>
<li><strong>contents</strong>: Array of sub-components for hierarchical mixtures</li>
<li><strong>identifiers</strong>: Database IDs or URLs for additional information</li>
</ul>
<h4 id="simple-example">Simple Example</h4>
<p>A basic Mixfile might look like:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;mixfileVersion&#34;</span>: <span style="color:#ae81ff">0.01</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;name&#34;</span>: <span style="color:#e6db74">&#34;Acetone, ≥99%&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;contents&#34;</span>: [
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;name&#34;</span>: <span style="color:#e6db74">&#34;acetone&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;smiles&#34;</span>: <span style="color:#e6db74">&#34;CC(=O)C&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;quantity&#34;</span>: <span style="color:#ae81ff">99</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;units&#34;</span>: <span style="color:#e6db74">&#34;%&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;relation&#34;</span>: <span style="color:#e6db74">&#34;&gt;=&#34;</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  ]
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Note that the paper specifies distinct fields for molecular structures: <code>molfile</code> (the primary source of truth), <code>smiles</code>, <code>inchi</code>, and <code>formula</code>. Concentration data uses separate <code>quantity</code>, <code>units</code>, and <code>relation</code> fields.</p>
<h4 id="complex-example-mixture-of-mixtures">Complex Example: Mixture-of-Mixtures</h4>
<p>For something like &ldquo;ethyl acetate dissolved in hexanes,&rdquo; the structure would be:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;mixfileVersion&#34;</span>: <span style="color:#ae81ff">0.01</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;name&#34;</span>: <span style="color:#e6db74">&#34;Ethyl acetate in hexanes&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;contents&#34;</span>: [
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;name&#34;</span>: <span style="color:#e6db74">&#34;ethyl acetate&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;smiles&#34;</span>: <span style="color:#e6db74">&#34;CCOC(=O)C&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;quantity&#34;</span>: <span style="color:#ae81ff">10</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;units&#34;</span>: <span style="color:#e6db74">&#34;%&#34;</span>
</span></span><span style="display:flex;"><span>    },
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;name&#34;</span>: <span style="color:#e6db74">&#34;hexanes&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&#34;contents&#34;</span>: [
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">&#34;name&#34;</span>: <span style="color:#e6db74">&#34;n-hexane&#34;</span>,
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">&#34;smiles&#34;</span>: <span style="color:#e6db74">&#34;CCCCCC&#34;</span>,
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">&#34;quantity&#34;</span>: <span style="color:#ae81ff">60</span>,
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">&#34;units&#34;</span>: <span style="color:#e6db74">&#34;%&#34;</span>
</span></span><span style="display:flex;"><span>        },
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">&#34;name&#34;</span>: <span style="color:#e6db74">&#34;2-methylpentane&#34;</span>,
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">&#34;smiles&#34;</span>: <span style="color:#e6db74">&#34;CC(C)CCC&#34;</span>,
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">&#34;quantity&#34;</span>: <span style="color:#ae81ff">25</span>,
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">&#34;units&#34;</span>: <span style="color:#e6db74">&#34;%&#34;</span>
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>      ]
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  ]
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This hierarchical structure captures the &ldquo;recipe&rdquo; of complex mixtures while remaining machine-readable.</p>
<h3 id="minchi-canonical-mixture-identifiers">MInChI: Canonical Mixture Identifiers</h3>
<p>While Mixfiles provide comprehensive descriptions, simple identifiers are also needed for database storage and searching. This is where MInChI comes in.</p>
<p>A MInChI string is structured as:</p>
<pre><code>MInChI=0.00.1S/&lt;components&gt;/n&lt;indexing&gt;/g&lt;concentration&gt;
</code></pre>
<ul>
<li><strong>Header</strong>: Version information (<code>0.00.1S</code> in the paper&rsquo;s specification)</li>
<li><strong>Components</strong>: Standard InChI for each unique molecule, sorted alphabetically <em>by the InChI strings themselves</em>, then concatenated with <code>&amp;</code></li>
<li><strong>Indexing</strong> (prefixed with <code>/n</code>): Hierarchical structure using curly braces <code>{}</code> for branches and <code>&amp;</code> for adjacent nodes; uses 1-based integer indices referring to the sorted InChI list</li>
<li><strong>Concentration</strong> (prefixed with <code>/g</code>): Quantitative information for each component, with units converted to canonical codes</li>
</ul>
<h4 id="why-this-matters">Why This Matters</h4>
<p>MInChI strings enable simple database searches:</p>
<ul>
<li>Check if a specific component appears in any mixture</li>
<li>Compare different formulations of the same product</li>
<li>Identify similar mixtures based on string similarity</li>
</ul>
<h2 id="validating-the-standard-through-practical-tooling">Validating the Standard Through Practical Tooling</h2>
<p>The paper demonstrates the format&rsquo;s capabilities through several practical applications and a proof-of-concept implementation:</p>
<h3 id="text-extraction-algorithm">Text Extraction Algorithm</h3>
<p>The authors demonstrate a proof-of-concept algorithm that uses regular expressions and chemical name recognition to parse plain-text mixture descriptions into structured Mixfile data. The algorithm:</p>
<ol>
<li>Applies regex rules to remove filler words and extract concentrations</li>
<li>Looks up cleaned names against a custom chemical database</li>
<li>Falls back to OPSIN for SMILES generation from chemical names</li>
<li>Generates 2D coordinates for molecular structures</li>
</ol>
<h3 id="graphical-editor">Graphical Editor</h3>
<p>An open-source editor provides:</p>
<ul>
<li>Tree-based interface for building and editing hierarchical structures</li>
<li>Chemical structure sketching and editing</li>
<li>Database lookup (e.g., PubChem integration)</li>
<li>Automatic MInChI generation</li>
<li>Import/export capabilities</li>
</ul>
<h3 id="example-use-cases">Example Use Cases</h3>
<p>The paper validates the format through real-world applications:</p>
<ul>
<li><strong>Safety compliance</strong>: Automated hazard assessment based on concentration-dependent properties (e.g., solid osmium tetroxide vs. 1% aqueous solution)</li>
<li><strong>Inventory management</strong>: Precise, searchable laboratory records</li>
<li><strong>Data extraction</strong>: Parsing vendor catalogs and safety data sheets</li>
</ul>
<h2 id="outcomes-and-future-extensibility">Outcomes and Future Extensibility</h2>
<p>The work successfully establishes the first standardized, machine-readable formats for chemical mixtures. Key achievements:</p>
<ul>
<li><strong>Comprehensive representation</strong>: Mixfile captures component identity, quantity, and hierarchy</li>
<li><strong>Canonical identification</strong>: MInChI provides compact, searchable identifiers</li>
<li><strong>Practical tooling</strong>: Open-source editor and text extraction demonstrate feasibility</li>
<li><strong>Real-world validation</strong>: Format handles diverse use cases from safety to inventory</li>
</ul>
<h3 id="limitations-and-future-directions">Limitations and Future Directions</h3>
<p>The authors acknowledge areas for improvement:</p>
<ul>
<li><strong>Machine learning improvements</strong>: Better text extraction using modern NLP techniques</li>
<li><strong>Extended coverage</strong>: Support for polymers, complex formulations, analytical results</li>
<li><strong>Community adoption</strong>: Integration with existing chemical databases and software</li>
</ul>
<p>The hierarchical design makes Mixfile suitable for both &ldquo;recipe&rdquo; descriptions (how to make something) and analytical results (what was found). This flexibility should help drive adoption across different use cases in chemistry and materials science.</p>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="open-source-tooling--data">Open Source Tooling &amp; Data</h3>
<p>While the central repository focusing on validating and establishing the MInChI standard is <a href="https://github.com/IUPAC/MInChI">github.com/IUPAC/MInChI</a>, the tools and datasets actually used to develop the paper&rsquo;s proofs-of-concept are hosted elsewhere:</p>
<ul>
<li><strong>Graphical Editor &amp; App codebase</strong>: The Electron application and Mixfile handling codebase (<code>console.js</code>) can be found at <a href="https://github.com/cdd/mixtures">github.com/cdd/mixtures</a>.</li>
<li><strong>Text Extraction Data</strong>: The several thousand extracted mixture records generated through the text extraction method can be accessed inside the <code>cdd/mixtures</code> repository under <a href="https://github.com/cdd/mixtures/tree/master/reference"><code>reference/gathering.zip</code></a>.</li>
</ul>
<h3 id="artifacts">Artifacts</h3>
<table>
	<thead>
			<tr>
					<th style="text-align: left">Artifact</th>
					<th style="text-align: left">Type</th>
					<th style="text-align: left">License</th>
					<th style="text-align: left">Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td style="text-align: left"><a href="https://github.com/IUPAC/MInChI">IUPAC/MInChI</a></td>
					<td style="text-align: left">Code / Data</td>
					<td style="text-align: left">Unknown</td>
					<td style="text-align: left">Validation test suite with ~150 mixture JSON files</td>
			</tr>
			<tr>
					<td style="text-align: left"><a href="https://github.com/cdd/mixtures">cdd/mixtures</a></td>
					<td style="text-align: left">Code / Data</td>
					<td style="text-align: left">GPL-3.0</td>
					<td style="text-align: left">Electron-based Mixfile editor, CLI tools, and reference mixture corpus</td>
			</tr>
	</tbody>
</table>
<p>The paper was funded by NIH Grant 1R43TR002528-01. No specific hardware requirements are needed, as this is a format specification with lightweight tooling.</p>
<h3 id="algorithms">Algorithms</h3>
<p>This section provides the specific algorithmic logic, schema definitions, and standardization rules needed to replicate the Mixfile parser or MInChI generator.</p>
<h4 id="the-strict-mixfile-json-schema">The Strict Mixfile JSON Schema</h4>
<p>To implement the format, a parser must recognize these specific fields:</p>
<p><strong>Root Structure</strong>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;mixfileVersion&#34;</span>: <span style="color:#ae81ff">0.01</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;header&#34;</span>: {},
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;contents&#34;</span>: []
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><strong>Component Fields</strong>:</p>
<ul>
<li><code>name</code>: string (required if no structure is provided)</li>
<li><code>molfile</code>: string (the primary source of truth for molecular structure)</li>
<li><code>smiles</code>, <code>inchi</code>, <code>formula</code>: derived/transient fields for convenience</li>
<li><code>quantity</code>: number OR <code>[min, max]</code> array for ranges</li>
<li><code>units</code>: string (must map to supported ontology)</li>
<li><code>relation</code>: string (e.g., <code>&quot;&gt;&quot;</code>, <code>&quot;~&quot;</code>, <code>&quot;&gt;=&quot;</code>)</li>
<li><code>ratio</code>: array of two numbers <code>[numerator, denominator]</code></li>
<li><code>identifiers</code>: database assignments (e.g., CASRN, PubChem)</li>
<li><code>links</code>: URLs relevant to the component</li>
<li><code>contents</code>: recursive array for hierarchical mixtures</li>
</ul>
<h4 id="minchi-generation-algorithm">MInChI Generation Algorithm</h4>
<p>To generate <code>MInChI=0.00.1S/...</code>, the software must follow these steps:</p>
<ol>
<li>
<p><strong>Component Layer</strong>:</p>
<ul>
<li>Calculate standard <a href="/notes/chemistry/molecular-representations/notations/inchi-2013/">InChI</a> for all structures in the mixture</li>
<li>Sort distinct InChIs alphabetically by the InChI string itself</li>
<li>Join with <code>&amp;</code> to form the structure layer</li>
</ul>
</li>
<li>
<p><strong>Hierarchy &amp; Concentration Layers</strong>:</p>
<ul>
<li>Traverse the Mixfile tree recursively</li>
<li><strong>Indexing</strong>: Use integer indices (1-based) referring to the sorted InChI list</li>
<li><strong>Grouping</strong>: Use <code>{}</code> to denote hierarchy branches and <code>&amp;</code> to separate nodes at the same level</li>
<li><strong>Concentration</strong>: Convert all quantities to canonical unit codes and apply scaling factors</li>
</ul>
</li>
</ol>
<h4 id="unit-standardization-table">Unit Standardization Table</h4>
<p>Replication requires mapping input units to canonical MInChI codes. The full table from the paper (Table 1) includes:</p>
<table>
	<thead>
			<tr>
					<th style="text-align: left">Input Unit</th>
					<th style="text-align: left">MInChI Code</th>
					<th style="text-align: left">Scale Factor</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td style="text-align: left">%</td>
					<td style="text-align: left">pp</td>
					<td style="text-align: left">1</td>
			</tr>
			<tr>
					<td style="text-align: left">w/v%</td>
					<td style="text-align: left">wv</td>
					<td style="text-align: left">0.01</td>
			</tr>
			<tr>
					<td style="text-align: left">w/w%</td>
					<td style="text-align: left">wf</td>
					<td style="text-align: left">0.01</td>
			</tr>
			<tr>
					<td style="text-align: left">v/v%</td>
					<td style="text-align: left">vf</td>
					<td style="text-align: left">0.01</td>
			</tr>
			<tr>
					<td style="text-align: left">mol/mol%</td>
					<td style="text-align: left">mf</td>
					<td style="text-align: left">0.01</td>
			</tr>
			<tr>
					<td style="text-align: left">mol/L (M)</td>
					<td style="text-align: left">mr</td>
					<td style="text-align: left">1</td>
			</tr>
			<tr>
					<td style="text-align: left">mmol/L</td>
					<td style="text-align: left">mr</td>
					<td style="text-align: left">$10^{-3}$</td>
			</tr>
			<tr>
					<td style="text-align: left">g/L</td>
					<td style="text-align: left">wv</td>
					<td style="text-align: left">$10^{-3}$</td>
			</tr>
			<tr>
					<td style="text-align: left">mol/kg</td>
					<td style="text-align: left">mb</td>
					<td style="text-align: left">1</td>
			</tr>
			<tr>
					<td style="text-align: left">ratio</td>
					<td style="text-align: left">vp</td>
					<td style="text-align: left">1</td>
			</tr>
	</tbody>
</table>
<h4 id="text-extraction-logic">Text Extraction Logic</h4>
<p>The paper defines a recursive procedure for parsing plain-text mixture descriptions:</p>
<ol>
<li><strong>Input</strong>: Raw text string (e.g., &ldquo;2 M acetone in water&rdquo;)</li>
<li><strong>Rule Application</strong>: Apply RegEx rules in order:
<ul>
<li><em>Remove</em>: Delete common filler words (&ldquo;solution&rdquo;, &ldquo;in&rdquo;)</li>
<li><em>Replace</em>: Substitute known variations</li>
<li><em>Concentration</em>: Extract quantities like &ldquo;2 M&rdquo;, &ldquo;97%&rdquo;</li>
<li><em>Branch</em>: Split phrases like &ldquo;A in B&rdquo; into sub-nodes</li>
</ul>
</li>
<li><strong>Lookup</strong>: Check cleaned name against a custom table (handles cases like &ldquo;xylenes&rdquo; or specific structures)</li>
<li><strong>OPSIN</strong>: If no lookup match, send to the OPSIN tool to generate SMILES from the chemical name</li>
<li><strong>Embed</strong>: If structure found, generate 2D coordinates (Molfile) via RDKit</li>
</ol>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Clark, A. M., McEwen, L. R., Gedeck, P., &amp; Bunin, B. A. (2019). Capturing mixture composition: an open machine-readable format for representing mixed substances. <em>Journal of Cheminformatics</em>, <em>11</em>(1), 33. <a href="https://doi.org/10.1186/s13321-019-0357-4">https://doi.org/10.1186/s13321-019-0357-4</a></p>
<p><strong>Publication</strong>: Journal of Cheminformatics (2019)</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@article</span>{clark2019capturing,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>=<span style="color:#e6db74">{Capturing mixture composition: an open machine-readable format for representing mixed substances}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>=<span style="color:#e6db74">{Clark, Alex M and McEwen, Leah R and Gedeck, Peter and Bunin, Barry A}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">journal</span>=<span style="color:#e6db74">{Journal of cheminformatics}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">volume</span>=<span style="color:#e6db74">{11}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">number</span>=<span style="color:#e6db74">{1}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span>=<span style="color:#e6db74">{33}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span>=<span style="color:#e6db74">{2019}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">publisher</span>=<span style="color:#e6db74">{BioMed Central}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><strong>Additional Resources</strong>:</p>
<ul>
<li><a href="https://github.com/IUPAC/MInChI">Official MInChI GitHub repository</a></li>
</ul>
]]></content:encoded></item><item><title>MolRec: Rule-Based OCSR System at TREC 2011 Benchmark</title><link>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/benchmarks/molrec_at_trec/</link><pubDate>Sat, 11 Oct 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/benchmarks/molrec_at_trec/</guid><description>Rule-based system for optical chemical structure recognition using vectorization and geometric analysis, achieving 95% accuracy on TREC 2011.</description><content:encoded><![CDATA[<h2 id="contribution-rule-based-ocsr-system">Contribution: Rule-Based OCSR System</h2>
<p>This is a <strong>Method</strong> paper that presents and validates MolRec, a rule-based system for Optical Chemical Structure Recognition (OCSR). While the paper emphasizes performance analysis on the TREC 2011 benchmark, the core contribution is the system architecture itself: a multi-stage pipeline using vectorization, geometric rule-based analysis, and graph construction to convert chemical diagram images into machine-readable MOL files.</p>
<h2 id="motivation-robust-conversion-of-chemical-diagrams">Motivation: Robust Conversion of Chemical Diagrams</h2>
<p>Chemical molecular diagrams are ubiquitous in scientific documents across chemistry and life sciences. Converting these static raster images into machine-readable formats (like MOL files) that encode precise spatial and connectivity information is important for cheminformatics applications such as database indexing, similarity searching, and automated literature mining.</p>
<p>While pixel-based pattern matching approaches exist, they struggle with variations in drawing style, image quality, and diagram complexity. An approach that can handle the geometric and topological diversity of real-world chemical diagrams is needed.</p>
<h2 id="novelty-vectorization-and-geometric-rules">Novelty: Vectorization and Geometric Rules</h2>
<p>MolRec uses a <strong>vectorization and geometric rule-based pipeline</strong>. Key technical innovations include:</p>
<p><strong>Disk-Growing Heuristic for Wedge Bonds</strong>: A novel dynamic algorithm to distinguish wedge bonds from bold lines. A disk with radius greater than the average line width is placed inside the connected component and grown to the largest size that still covers only foreground pixels. The disk is then walked in the direction that allows it to continue growing. When it can grow no more, the base of the triangle (stereo-center) has been located, identifying the wedge orientation.</p>
<p><strong>Joint Breaking Strategy</strong>: Explicitly breaking all connected joints in the vectorization stage to avoid combinatorial connection complexity. This allows uniform treatment of all line segment connections regardless of junction complexity.</p>
<p><strong>Superatom Dictionary Mining</strong>: The system mines MOL files from the OSRA dataset to build a comprehensive superatom dictionary (e.g., &ldquo;Ph&rdquo;, &ldquo;COOH&rdquo;), supplemented by the Marvin abbreviation collection.</p>
<p><strong>Comprehensive Failure Analysis</strong>: Unlike most OCSR papers that report only aggregate accuracy, this work provides a detailed categorization of all 55 failures, identifying 61 specific error reasons and their root causes.</p>
<h2 id="methodology-and-trec-2011-experiments">Methodology and TREC 2011 Experiments</h2>
<p><strong>Benchmark</strong>: The system was evaluated on the <strong>TREC 2011 Chemical Track</strong> test set consisting of 1,000 molecular diagram images. The authors performed two independent runs with slightly different internal parameter settings to assess reproducibility.</p>
<p><strong>Evaluation Metric</strong>: Correct recall of chemical structures. Output MOL files were compared semantically to ground truth using <strong>OpenBabel</strong>, which ignores syntactically different but chemically equivalent representations.</p>
<p><strong>Failure Analysis</strong>: Across both runs, 55 unique diagrams were misrecognized (50 in run 1, 51 in run 2, with significant overlap). The authors manually examined all 55 and categorized them, identifying 61 specific reasons for mis-recognition. This analysis provides insight into systematic limitations of the rule-based approach.</p>
<h2 id="results-and-top-failure-modes">Results and Top Failure Modes</h2>
<p><strong>High Accuracy</strong>: MolRec achieved a <strong>95% correct recovery rate</strong> on the TREC 2011 benchmark:</p>
<ul>
<li>Run 1: 950/1000 structures correctly recognized (95.0%)</li>
<li>Run 2: 949/1000 structures correctly recognized (94.9%)</li>
</ul>
<p>The near-identical results across runs with slightly different internal parameters show stability of the rule-based approach.</p>
<p><strong>Top Failure Modes</strong> (from detailed analysis of 55 unique misrecognized diagrams, yielding 61 total error reasons):</p>
<ul>
<li><strong>Dashed wedge bond misidentification (15 cases)</strong>: Most common failure. Short dashes at the narrow end were interpreted as a separate dashed bond while longer dashes were treated as a dashed wedge or dashed bold bond, splitting one bond into two with a spurious node.</li>
<li><strong>Incorrect stereochemistry (10 cases)</strong>: Heuristics guessed wrong 3D orientations for ambiguous bold/dashed bonds where syntax alone is insufficient.</li>
<li><strong>Touching components (6 cases)</strong>: Characters touching bonds, letters touching symbols, or ink bleed between close parallel lines caused segmentation failures.</li>
<li><strong>Incorrect character grouping (5 cases)</strong>: Characters too close together for reliable separation.</li>
<li><strong>Solid circles without 3D hydrogen bond (5 cases)</strong>: MolRec correctly interprets solid circles as implying a hydrogen atom via a solid wedge bond, but some solution MOL files in the test set omit this bond, causing a mismatch.</li>
<li><strong>Diagram caption confusion (5 cases)</strong>: Captions appearing within images are mistakenly parsed as part of the molecular structure.</li>
<li><strong>Unrecognised syntax (5 cases)</strong>: User annotations, unusual notations (e.g., wavy line crossing a dashed wedge), and repetition structures.</li>
<li><strong>Broken characters (3 cases)</strong>: Degraded or partial characters without recovery mechanisms.</li>
<li><strong>Connectivity of superatoms (3 cases)</strong>: Ambiguous permutation of connection points for multi-bonded superatoms.</li>
<li><strong>Problematic bridge bonds (3 cases)</strong>: Extreme perspective or angles outside MolRec&rsquo;s thresholds.</li>
<li><strong>Unhandled bond type (1 case)</strong>: A dashed dative bond not previously encountered.</li>
</ul>
<p><strong>System Strengths</strong>:</p>
<ul>
<li>Douglas-Peucker line simplification proves faster and more robust than Hough transforms across different drawing styles</li>
<li>Disk-growing wedge bond detection effectively distinguishes 3D orientations in most cases</li>
<li>Mining MOL files for superatom dictionary captures real-world chemical abbreviation usage patterns</li>
</ul>
<p><strong>Fundamental Limitations Revealed</strong>:</p>
<ul>
<li><strong>Brittleness</strong>: Small variations in drawing style or image quality can cause cascading failures</li>
<li><strong>Stereochemistry ambiguity</strong>: Even humans disagree on ambiguous cases; automated resolution based purely on syntax is inherently limited</li>
<li><strong>Segmentation dependence</strong>: Most failures trace back to incorrect separation of text, bonds, and graphical elements</li>
<li><strong>No error recovery</strong>: Early-stage mistakes propagate through the pipeline with no mechanism for correction</li>
</ul>
<p><strong>Test Set Quality Issues</strong>: The paper also highlights several cases where the TREC 2011 ground truth itself was questionable. Some solution MOL files omitted stereo bond information for solid circle notations, dative (polar) bonds were inconsistently interpreted as either double bonds or single bonds across the training and test sets, and one diagram contained over-connected carbon atoms (5 bonds without the required positive charge indication) that the solution MOL file did not flag.</p>
<p>The systematic error analysis reveals what 95% accuracy means in practice. The failure modes highlight scalability challenges for rule-based systems when applied to diverse real-world documents with noise, artifacts, and non-standard conventions.</p>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="data">Data</h3>
<table>
	<thead>
			<tr>
					<th>Purpose</th>
					<th>Dataset</th>
					<th>Size</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Dictionary Mining</td>
					<td>OSRA Dataset</td>
					<td>Unknown</td>
					<td>Mined to create superatom dictionary for abbreviations like &ldquo;Ph&rdquo;, &ldquo;COOH&rdquo;</td>
			</tr>
			<tr>
					<td>Dictionary</td>
					<td>Marvin Collection</td>
					<td>N/A</td>
					<td>Integrated Marvin abbreviation group collection for additional superatoms</td>
			</tr>
			<tr>
					<td>Evaluation</td>
					<td>TREC 2011 Test Set</td>
					<td>1,000 images</td>
					<td>Standard benchmark for Text REtrieval Conference Chemical Track</td>
			</tr>
	</tbody>
</table>
<h3 id="algorithms">Algorithms</h3>
<p>The MolRec pipeline consists of sequential image processing and graph construction stages:</p>
<p><strong>1. Preprocessing</strong></p>
<ul>
<li><strong>Binarization</strong>: Input image converted to binary</li>
<li><strong>Connected Component Labeling</strong>: Identifies distinct graphical elements</li>
<li><strong>OCR</strong>: Simple metric space-based engine identifies characters (letters $L$, digits $N$, symbols $S$)</li>
<li><strong>Character Grouping</strong>: Spatial proximity and type-based heuristics group characters:
<ul>
<li>Horizontal: Letter-Letter, Digit-Digit, Letter-Symbol</li>
<li>Vertical: Letter-Letter only</li>
<li>Diagonal: Letter-Digit, Letter-Charge</li>
</ul>
</li>
</ul>
<p><strong>2. Vectorization (Line Finding)</strong></p>
<ul>
<li><strong>Image Thinning</strong>: Reduce lines to unit width</li>
<li><strong>Douglas-Peucker Algorithm</strong>: Simplify polylines into straight line segments</li>
<li><strong>Joint Breaking</strong>: Explicitly split lines at junctions where $&gt;2$ segments meet, avoiding combinatorial connection complexity</li>
</ul>
<p><strong>3. Bond Recognition Rules</strong></p>
<p>After erasing text from the image, remaining line segments are analyzed:</p>
<ul>
<li><strong>Double/Triple Bonds</strong>: Cluster segments with same slope within threshold distance</li>
<li><strong>Dashed Bonds</strong>: Identify repeated short segments of similar length with collinear center points</li>
<li><strong>Wedge/Bold Bonds</strong>: Dynamic disk algorithm:
<ul>
<li>Place disk with radius $&gt;$ average line width inside component</li>
<li>Grow disk to maximum size to locate triangle base (stereo-center)</li>
<li>&ldquo;Walk&rdquo; disk to find narrow end, distinguishing wedge orientation</li>
</ul>
</li>
<li><strong>Wavy Bonds</strong>: Identify sawtooth pattern polylines after thinning</li>
<li><strong>Implicit Nodes</strong>: Split longer segments at points where parallel shorter segments terminate (carbon atoms in chains)</li>
</ul>
<p><strong>4. Graph Construction</strong></p>
<ul>
<li><strong>Node Formation</strong>: Group line segment endpoints by distance threshold</li>
<li><strong>Disambiguation</strong>: Logic separates lowercase &ldquo;l&rdquo;, uppercase &ldquo;I&rdquo;, digit &ldquo;1&rdquo;, and vertical bonds</li>
<li><strong>Superatom Expansion</strong>: Replace abbreviations with full structures using mined dictionary</li>
<li><strong>Stereochemistry Resolution</strong>: Heuristics based on neighbor counts determine direction for ambiguous bold/dashed bonds (known limitation)</li>
</ul>
<p><strong>5. MOL File Generation</strong></p>
<ul>
<li>Final graph structure converted to standard MOL file format</li>
</ul>
<h3 id="evaluation">Evaluation</h3>
<table>
	<thead>
			<tr>
					<th>Metric</th>
					<th>Run 1</th>
					<th>Run 2</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Correct Recall</td>
					<td>950/1000</td>
					<td>949/1000</td>
					<td>Slightly different internal parameters between runs</td>
			</tr>
			<tr>
					<td>Accuracy</td>
					<td>95.0%</td>
					<td>94.9%</td>
					<td>Semantic comparison using OpenBabel</td>
			</tr>
	</tbody>
</table>
<p><strong>Comparison Method</strong>: OpenBabel converts graphs to MOL files and compares them semantically to ground truth, ignoring syntactic variations that don&rsquo;t affect chemical meaning.</p>
<p><strong>Failure Categorization</strong>: 55 unique misrecognized diagrams analyzed across both runs, identifying 61 specific error reasons across 11 categories including dashed wedge bond misidentification (15), incorrect stereochemistry (10), touching components (6), incorrect character grouping (5), solid circles (5), diagram caption confusion (5), unrecognised syntax (5), broken characters (3), superatom connectivity (3), problematic bridge bonds (3), and unhandled bond type (1).</p>
<h3 id="artifacts">Artifacts</h3>
<table>
	<thead>
			<tr>
					<th>Artifact</th>
					<th>Type</th>
					<th>License</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><a href="https://openbabel.org/">Open Babel</a></td>
					<td>Code</td>
					<td>GPL-2.0</td>
					<td>Used for semantic MOL file comparison</td>
			</tr>
			<tr>
					<td><a href="https://sourceforge.net/projects/osra/">OSRA</a></td>
					<td>Code</td>
					<td>GPL-2.0</td>
					<td>Source of superatom dictionary data (MOL files mined)</td>
			</tr>
			<tr>
					<td>TREC 2011 Chemical Track</td>
					<td>Dataset</td>
					<td>Unknown</td>
					<td>1,000 molecular diagram images (available via NIST)</td>
			</tr>
	</tbody>
</table>
<p><strong>Reproducibility Status</strong>: Partially Reproducible. The MolRec source code is not publicly available. The evaluation dataset (TREC 2011) is accessible through NIST, and the tools used for comparison (OpenBabel) are open source. However, full reproduction of MolRec&rsquo;s pipeline would require reimplementation from the paper&rsquo;s descriptions.</p>
<h3 id="hardware">Hardware</h3>
<ul>
<li><strong>Compute Details</strong>: Not explicitly specified in the paper</li>
<li><strong>Performance Note</strong>: Vectorization approach noted as &ldquo;proven to be fast&rdquo; compared to Hough transform alternatives</li>
</ul>
<h3 id="references">References</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@inproceedings</span>{sadawiPerformanceMolRecTREC2011,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span> = <span style="color:#e6db74">{Performance of {{MolRec}} at {{TREC}} 2011 {{Overview}} and {{Analysis}} of {{Results}}}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">booktitle</span> = <span style="color:#e6db74">{Proceedings of the 20th {{Text REtrieval Conference}}}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span> = <span style="color:#e6db74">{Sadawi, Noureddin M. and Sexton, Alan P. and Sorge, Volker}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span> = <span style="color:#e6db74">{2011}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">langid</span> = <span style="color:#e6db74">{english}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Sadawi, N. M., Sexton, A. P., &amp; Sorge, V. (2011). Performance of MolRec at TREC 2011 Overview and Analysis of Results. <em>Proceedings of the 20th Text REtrieval Conference</em>. <a href="https://trec.nist.gov/pubs/trec20/papers/UoB.chem.update.pdf">https://trec.nist.gov/pubs/trec20/papers/UoB.chem.update.pdf</a></p>
<p><strong>Publication</strong>: TREC 2011</p>
<p><strong>Additional Resources</strong>:</p>
<ul>
<li><a href="https://openbabel.org/">Open Babel</a> - Used for semantic MOL file comparison</li>
<li><a href="https://sourceforge.net/projects/osra/">OSRA Project</a> - Source of superatom dictionary data</li>
</ul>
]]></content:encoded></item><item><title>ChemInfty: Chemical Structure Recognition in Patent Images</title><link>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/rule-based/cheminfty/</link><pubDate>Sat, 04 Oct 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/chemistry/optical-structure-recognition/rule-based/cheminfty/</guid><description>Fujiyoshi et al.'s segment-based approach for recognizing chemical structures in challenging Japanese patent images with touching characters and broken lines.</description><content:encoded><![CDATA[<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Fujiyoshi, A., Nakagawa, K., &amp; Suzuki, M. (2011). Robust Method of Segmentation and Recognition of Chemical Structure Images in ChemInfty. <em>Pre-Proceedings of the 9th IAPR International Workshop on Graphics Recognition, GREC.</em></p>
<p><strong>Publication</strong>: GREC 2011 (Graphics Recognition Workshop)</p>
<p><strong>Additional Resources</strong>:</p>
<ul>
<li><a href="https://www.sciaccess.net/en/InftyReader/">InftyReader Project</a></li>
</ul>
<h2 id="contribution-segment-based-ocsr-method">Contribution: Segment-Based OCSR Method</h2>
<p>This is a <strong>method paper</strong> that introduces ChemInfty, a rule-based system for Optical Chemical Structure Recognition (OCSR) specifically designed to handle the challenging, low-quality images found in Japanese patent applications.</p>
<h2 id="motivation-the-challenge-of-degraded-patent-images">Motivation: The Challenge of Degraded Patent Images</h2>
<p>The motivation is straightforward: Japanese patent applications contain a massive amount of chemical knowledge, but the images are remarkably poor quality. Unlike the relatively clean molecular diagrams in scientific papers, patent images suffer from multiple problems that break conventional OCSR systems.</p>
<p>The authors quantified these issues in a sample of 200 patent images and found that 22% contained touching characters (where atom labels merge together), 19.5% had characters touching bond lines, and 8.5% had broken lines. These are not edge cases; they are pervasive enough to cripple existing recognition tools. Established systems like CLIDE, ChemReader, and OSRA struggle significantly with line-touching characters and broken lines, leading to recognition failures.</p>
<p>The challenge is compounded by the sheer diversity of creation methods. Some structures are drawn with sophisticated molecular editors, others with basic paint programs, and some are even handwritten. This means there&rsquo;s no standardization in fonts, character sizes, or line thickness. Add in the effects of scanning and faxing, and you have images with significant noise, distortion, and degradation.</p>
<p>The goal of ChemInfty is to build a system robust enough to handle these messy real-world conditions and make Japanese patent chemistry computer-searchable.</p>
<h2 id="core-innovation-segment-decomposition-and-dynamic-programming">Core Innovation: Segment Decomposition and Dynamic Programming</h2>
<p>The novelty lies in a segment-based decomposition approach that separates the recognition problem into manageable pieces before attempting to classify them. The key insight is that traditional OCR fails on these images because characters and lines are physically merged. You cannot recognize a character if you cannot cleanly separate it from the surrounding bonds first.</p>
<p>ChemInfty&rsquo;s approach has several distinctive elements:</p>
<ol>
<li>
<p><strong>Line and Curve Segmentation</strong>: The system first decomposes the image into smaller line and curve segments. The decomposition happens at natural breakpoints&mdash;crossings, sharp bends, and other locations where touching is likely to occur. This creates a set of primitive elements that can be recombined in different ways.</p>
</li>
<li>
<p><strong>Linear Order Assumption for Scalability</strong>: To make the dynamic programming approach computationally tractable and avoid combinatorial explosion, the system assumes that segments to be combined are adjacent when sorted in one of four directional orderings ($\perp, \setminus, \triangle, \rightarrow$). This constraint dramatically reduces the search space while still capturing the natural spatial relationships in chemical diagrams.</p>
</li>
<li>
<p><strong>Dynamic Programming for Segment Combination</strong>: Once the image is decomposed, the system faces a combinatorial problem: which segments should be grouped together to form characters, and which should be classified as bonds? The authors use dynamic programming to efficiently search for the &ldquo;most suitable combination&rdquo; of segments. This optimization finds the configuration that maximizes the likelihood of valid chemical structure elements.</p>
</li>
<li>
<p><strong>Two-Pass OCR Strategy</strong>: ChemInfty integrates with InftyReader, a powerful OCR engine. The system uses OCR twice in the pipeline:</p>
<ul>
<li><strong>First pass</strong>: High-confidence character recognition removes obvious atom labels early, simplifying the remaining image</li>
<li><strong>Second pass</strong>: After the segment-based method identifies and reconstructs difficult character regions, OCR is applied again to the cleaned-up character image</li>
</ul>
<p>This two-stage approach handles both easy and hard cases effectively: simple characters are recognized immediately, while complex cases get special treatment.</p>
</li>
<li>
<p><strong>Image Thinning for Structure Analysis</strong>: Before segmentation, the system thins the remaining graphical elements (after removing high-confidence characters) to skeleton lines. This thinning operation reveals the underlying topological structure&mdash;crossings, bends, and endpoints&mdash;making it easier to detect where segments should be divided.</p>
</li>
<li>
<p><strong>Proximity-Based Grouping</strong>: After identifying potential character segments, the system groups nearby segments together. This spatial clustering ensures that parts of the same character that were separated by bonds get recombined correctly.</p>
</li>
</ol>
<h2 id="methodology-real-world-patent-evaluation">Methodology: Real-World Patent Evaluation</h2>
<p>The evaluation focused on demonstrating that ChemInfty could handle real-world patent images at scale:</p>
<ol>
<li>
<p><strong>Large-Scale Patent Dataset</strong>: The system was tested on chemical structure images from Japanese patent applications published in 2008. This represents a realistic deployment scenario with all the messiness of actual documents.</p>
</li>
<li>
<p><strong>Touching Character Separation</strong>: The authors specifically measured the system&rsquo;s ability to separate characters from bonds when they were touching. Success was defined as cleanly extracting the character region so that OCR could recognize it.</p>
</li>
<li>
<p><strong>Recognition Accuracy by Object Type</strong>: Performance was broken down by element type (characters, line segments, solid wedges, and hashed wedges). This granular analysis revealed which components were easier or harder for the system to handle.</p>
</li>
<li>
<p><strong>End-to-End Performance</strong>: The overall recognition ratio was calculated across all object types to establish the system&rsquo;s practical utility for automated patent processing.</p>
</li>
</ol>
<h2 id="results-and-conclusions">Results and Conclusions</h2>
<ul>
<li>
<p><strong>Effective Separation for Line-Touching Characters</strong>: The segment-based method successfully separated 63.5% of characters that were touching bond lines. This is a substantial improvement over standard OCR, which typically fails completely on such cases. The authors note that when image quality is reasonable, the separation method works well.</p>
</li>
<li>
<p><strong>Strong Overall Character Recognition</strong>: Character recognition achieved 85.86% accuracy, which is respectable given the poor quality of the input images. Combined with the 90.73% accuracy for line segments, this demonstrates the system can reliably reconstruct the core molecular structure.</p>
</li>
<li>
<p><strong>Weak Performance on Wedges</strong>: The system struggled significantly with stereochemistry notation. Solid wedges were correctly recognized only 52.54% of the time, and hashed wedges fared even worse at 23.63%. This is a critical limitation since stereochemistry is often essential for understanding molecular properties.</p>
</li>
<li>
<p><strong>Image Quality Dependency</strong>: The authors acknowledge that the method&rsquo;s effectiveness is ultimately limited by image quality. When images are severely degraded (blurred to the point where even humans struggle to distinguish characters from noise), the segmentation approach cannot reliably separate touching elements.</p>
</li>
<li>
<p><strong>Overall System Performance</strong>: The combined recognition ratio of 86.58% for all objects indicates that ChemInfty is a working system but not yet production-ready. The authors conclude that further refinement is necessary, particularly for wedge recognition and handling extremely low-quality images.</p>
</li>
</ul>
<p>The work establishes that segment-based decomposition with dynamic programming is a viable approach for handling the specific challenges of patent image OCSR. The two-pass OCR strategy and the use of image thinning to reveal structure are practical engineering solutions that improve robustness. However, the results also highlight that rule-based methods are fundamentally limited by image quality. There is only so much you can do with algorithmic cleverness when the input is severely degraded. This limitation would motivate later work on deep learning approaches that can learn robust feature representations from large datasets.</p>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="technical-paradigm">Technical Paradigm</h3>
<p><strong>This is a pre-deep learning (2011) classical computer vision paper.</strong> The system uses rule-based methods and traditional OCR engines, not neural networks.</p>
<h3 id="models">Models</h3>
<ul>
<li><strong>InftyReader</strong>: A mathematical OCR engine used for the initial high-confidence character recognition pass. This is a pre-existing external tool.</li>
<li><strong>DEF-based OCR</strong>: A standard OCR engine based on Directional Element Features (DEF). These are manually engineered statistical features (histograms of edge directions), not learned neural network features.</li>
</ul>
<h3 id="algorithms">Algorithms</h3>
<p>The paper details a multi-step recognition pipeline:</p>
<ol>
<li><strong>Preprocessing</strong>: Binarization and smoothing</li>
<li><strong>Initial Character Removal</strong>: High-confidence characters are recognized by the InftyReader OCR engine and removed from the image to simplify segmentation</li>
<li><strong>Skeletonization</strong>: Thinning using <strong>Hilditch&rsquo;s algorithm</strong> to skeletonize graphical elements, revealing topological structure (crossings, bends, endpoints)</li>
<li><strong>Feature Point Detection</strong>:
<ul>
<li><strong>Crossing points</strong>: Direct detection on skeleton</li>
<li><strong>Bending points</strong>: Detected using the <strong>Hough transformation</strong></li>
</ul>
</li>
<li><strong>Dynamic Programming Search</strong>:
<ul>
<li><strong>Input</strong>: Set of line/curve segments $S$</li>
<li><strong>Procedure</strong>: Sort segments in 4 directions ($\perp, \setminus, \triangle, \rightarrow$). For each direction, use DP to find the grouping that minimizes a heuristic score</li>
<li><strong>Complexity</strong>: $O(n^2)$ where $n$ is the number of segments</li>
<li><strong>Scoring</strong>: Uses a function <code>Measure(S')</code> that returns a score (0-100) indicating if a subset of segments forms a valid character or bond</li>
</ul>
</li>
</ol>
<p>The scoring function <code>Measure(S')</code> used in the dynamic programming algorithm is never mathematically defined in the paper, limiting replicability.</p>
<h3 id="data">Data</h3>
<p><strong>Evaluation Dataset</strong>: Chemical structure images from Japanese patent applications published in 2008. The complete 2008 dataset contains 229,969 total images.</p>
<table>
	<thead>
			<tr>
					<th>Purpose</th>
					<th>Dataset</th>
					<th>Size</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Evaluation</td>
					<td>Japanese Published Patent Applications (2008)</td>
					<td>1,599 images</td>
					<td>Contains 229,969 total images for the year. Format: TIFF, 200-400 dpi.</td>
			</tr>
			<tr>
					<td>Analysis</td>
					<td>Random subset for frequency analysis</td>
					<td>200 images</td>
					<td>Used to estimate frequency of touching/broken characters (found in ~20% of images).</td>
			</tr>
	</tbody>
</table>
<p><strong>No Training Set</strong>: The system is rule-based and uses pre-built OCR engines, so no model training was performed.</p>
<h3 id="evaluation">Evaluation</h3>
<p><strong>Primary Metric</strong>: Recognition ratio (percentage of correctly recognized objects)</p>
<table>
	<thead>
			<tr>
					<th>Metric</th>
					<th>Value</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Line-touching Separation</td>
					<td>63.5%</td>
					<td>Success rate for separating text glued to lines</td>
			</tr>
			<tr>
					<td>Character Recognition</td>
					<td>85.86%</td>
					<td>For all character sizes</td>
			</tr>
			<tr>
					<td>Line segments</td>
					<td>90.73%</td>
					<td>Standard bond recognition</td>
			</tr>
			<tr>
					<td>Solid Wedge Recognition</td>
					<td>52.54%</td>
					<td>Low performance noted as area for improvement</td>
			</tr>
			<tr>
					<td>Hashed Wedges</td>
					<td>23.63%</td>
					<td>Poorest performing element type</td>
			</tr>
			<tr>
					<td>Overall</td>
					<td>86.58%</td>
					<td>Combined across all object types</td>
			</tr>
	</tbody>
</table>
<p><strong>Total Objects Evaluated</strong>: 742,287 objects (characters, line segments, solid wedges, hashed wedges) extracted from the patent images.</p>
<h3 id="hardware">Hardware</h3>
<p>Not reported. Computational cost was not a primary concern for this classical CV system.</p>
<h3 id="replicability">Replicability</h3>
<p><strong>Low.</strong> The paper does not provide sufficient detail for full replication:</p>
<ul>
<li>The scoring function <code>Measure(S')</code> used in the dynamic programming algorithm is never mathematically defined</li>
<li>Dependency on the proprietary/specialized InftyReader engine</li>
<li>No pseudocode provided for the segment decomposition heuristics</li>
</ul>
<h3 id="notes-on-wedge-recognition">Notes on Wedge Recognition</h3>
<p>The system&rsquo;s poor performance on solid wedges (52.54%) and hashed wedges (23.63%) reflects a fundamental challenge for classical thinning algorithms. Wedge bonds are dense triangular regions that indicate 3D stereochemistry. When skeletonized using algorithms like Hilditch&rsquo;s method, these &ldquo;blob&rdquo; shapes often distort into unrecognizable patterns, unlike the clean thin lines that represent regular bonds.</p>
<hr>
<h2 id="citation">Citation</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@article</span>{fujiyoshiRobustMethodSegmentation2011,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span> = <span style="color:#e6db74">{Robust {{Method}} of {{Segmentation}} and {{Recognition}} of {{Chemical Structure Images}} in {{ChemInfty}}}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span> = <span style="color:#e6db74">{Fujiyoshi, Akio and Nakagawa, Koji and Suzuki, Masakazu}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span> = <span style="color:#ae81ff">2011</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">journal</span> = <span style="color:#e6db74">{Pre-proceedings of the 9th IAPR international workshop on graphics recognition, GREC}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">langid</span> = <span style="color:#e6db74">{english}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>The Number of Isomeric Hydrocarbons of the Methane Series</title><link>https://hunterheidenreich.com/notes/chemistry/molecular-representations/notations/number-of-isomeric-hydrocarbons/</link><pubDate>Mon, 08 Sep 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/chemistry/molecular-representations/notations/number-of-isomeric-hydrocarbons/</guid><description>Henze and Blair's 1931 JACS paper deriving exact recursive formulas for counting constitutional alkane isomers.</description><content:encoded><![CDATA[<h2 id="a-theoretical-foundation-for-mathematical-chemistry">A Theoretical Foundation for Mathematical Chemistry</h2>
<p>This is a foundational <strong>theoretical paper</strong> in mathematical chemistry and chemical graph theory. It derives <strong>exact mathematical laws</strong> governing molecular topology. The paper also serves as a <strong>benchmark resource</strong>, establishing the first systematic isomer counts that corrected historical errors and whose recursive method remains the basis for modern molecular enumeration.</p>
<h2 id="historical-motivation-and-the-failure-of-centric-trees">Historical Motivation and the Failure of Centric Trees</h2>
<p>The primary motivation was the lack of a rigorous mathematical relationship between carbon content ($N$) and isomer count.</p>
<ul>
<li><strong>Previous failures</strong>: Earlier attempts by <a href="https://doi.org/10.1002/cber.187500801227">Cayley (1875)</a> (as cited by Henze and Blair, referring to the Berichte der deutschen chemischen Gesellschaft summary) and <a href="https://doi.org/10.1002/cber.187500802191">Schiff (1875)</a> used &ldquo;centric&rdquo; and &ldquo;bicentric&rdquo; symmetry tree methods that broke down as carbon content increased, producing incorrect counts as early as $N = 12$. Subsequent efforts by Tiemann (1893), Delannoy (1894), Losanitsch (1897), Goldberg (1898), and Trautz (1924), as cited in the paper, each improved on specific aspects but none achieved general accuracy beyond moderate carbon content.</li>
<li><strong>The theoretical gap</strong>: All prior formulas depended on exhaustively identifying centers of symmetry, meaning they required additional correction terms for each increase in $N$ and could not reliably predict counts for larger molecules like $C_{40}$.</li>
</ul>
<p>This work aimed to develop a theoretically sound, generalizable method that could be extended to any number of carbons.</p>
<h2 id="core-innovation-recursive-enumeration-of-graphs">Core Innovation: Recursive Enumeration of Graphs</h2>
<p>The core novelty is the proof that the count of hydrocarbons is a recursive function of the count of alkyl radicals (alcohols) of size $N/2$ or smaller. The authors rely on a preliminary calculation of the total number of isomeric alcohols (the methanol series) to make this hydrocarbon enumeration possible. By defining $T_k$ as the exact number of possible isomeric alkyl radicals strictly containing $k$ carbon atoms, graph enumeration transforms into a mathematical recurrence.</p>
<p>To rigorously prevent double-counting when functionally identical branches connect to a central carbon, Henze and Blair applied combinations with substitution. Because the chemical branches are unordered topologically, connecting $x$ branches of identical structural size $k$ results in combinations with repetition:</p>
<p>$$ \binom{T_k + x - 1}{x} $$</p>
<p>For example, if a Group B central carbon is bonded to three identical sub-branches of length $k$, the combinatoric volume for that precise topological partition resolves to:</p>
<p>$$ \frac{T_k (T_k + 1)(T_k + 2)}{6} $$</p>
<p>Summing these constrained combinatorial partitions across all valid branch sizes (governed by the Even/Odd bisection rules) yields the exact isomer count for $N$ without overestimating due to symmetric permutations.</p>
<p><strong>The Symmetry Constraints</strong>: The paper rigorously divides the problem space to prevent double-counting:</p>
<ul>
<li><strong>Group A (Centrosymmetric)</strong>: Hydrocarbons that can be bisected into two smaller alkyl radicals.
<ul>
<li><em>Even $N$</em>: Split into two radicals of size $N/2$.</li>
<li><em>Odd $N$</em>: Split into sizes $(N+1)/2$ and $(N-1)/2$.</li>
</ul>
</li>
<li><strong>Group B (Asymmetric)</strong>: Hydrocarbons whose graphic formula cannot be symmetrically bisected. They contain exactly one central carbon atom attached to 3 or 4 branches. To prevent double-counting, Henze and Blair established strict maximum branch sizes:
<ul>
<li><em>Even $N$</em>: No branch can be larger than $(N/2 - 1)$ carbons.</li>
<li><em>Odd $N$</em>: No branch can be larger than $(N-3)/2$ carbons.</li>
<li><em>The Combinatorial Partitioning</em>: They further subdivided these 3-branch and 4-branch molecules into distinct mathematical cases based on whether the branches were structurally identical or unique, applying distinct combinatorial formulas to each scenario.</li>
</ul>
</li>
</ul>















<figure class="post-figure center ">
    <img src="/img/notes/hexane-and-its-six-isomers-by-even-and-odd-decomposition.webp"
         alt="The five structural isomers of hexane classified into Group A and Group B based on their decomposition"
         title="The five structural isomers of hexane classified into Group A and Group B based on their decomposition"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">The five isomers of hexane ($C_6$) classified by Henze and Blair&rsquo;s symmetry scheme. Group A molecules (top row) can be bisected along a bond (highlighted in red) into two $C_3$ alkyl radicals. Group B molecules (bottom row) have a central carbon atom (red circle) with 3-4 branches, preventing symmetric bisection.</figcaption>
    
</figure>

<p>This classification is the key insight that enables the recursive formulas. By exhaustively partitioning hydrocarbons into these mutually exclusive groups, the authors could derive separate combinatorial expressions for each and sum them without double-counting.</p>
<p>For each structural class, combinatorial formulas are derived that depend on the number of isomeric alcohols ($T_k$) where $k &lt; N$. This transforms the problem of counting large molecular graphs into a recurrence relation based on the counts of smaller, simpler sub-graphs.</p>
<h2 id="validation-via-exhaustive-hand-enumeration">Validation via Exhaustive Hand-Enumeration</h2>
<p>The experiments were computational and enumerative:</p>
<ol>
<li><strong>Derivation of the recursion formulas</strong>: The main effort was the mathematical derivation of the set of equations for each structural class of hydrocarbon.</li>
<li><strong>Calculation</strong>: They applied their formulas to calculate the number of isomers for alkanes up to $N=40$, reaching over $6.2 \times 10^{13}$ isomers. This was far beyond what was previously possible.</li>
<li><strong>Validation by exhaustive enumeration</strong>: To prove the correctness of their theory, the authors manually drew and counted all possible structural formulas for the undecanes ($C_{11}$), dodecanes ($C_{12}$), tridecanes ($C_{13}$), and tetradecanes ($C_{14}$). This brute-force check confirmed their calculated numbers and corrected long-standing errors in the literature.
<ul>
<li><em>Key correction</em>: The manual enumeration proved that the count for tetradecane ($C_{14}$) is <strong>1,858</strong>, correcting erroneous values previously published by <a href="https://doi.org/10.1002/cber.189703002144" title="Die Isomerie-Arten bei den Homologen der Paraffin-Reihe">Losanitsch (1897)</a>, whose results for $C_{12}$ and $C_{14}$ the paper identifies as incorrect.</li>
</ul>
</li>
</ol>
<h2 id="benchmark-outcomes-and-scaling-limits">Benchmark Outcomes and Scaling Limits</h2>
<ul>
<li><strong>The Constitutional Limit</strong>: The paper establishes the mathematical ground truth for organic molecular graphs by strictly counting <em>constitutional</em> (structural) isomers. The derivation completely excludes 3D stereoisomerism (enantiomers and diastereomers). For modern geometric deep learning applications (e.g., generating 3D conformers), Henze and Blair&rsquo;s scaling sequence serves as a lower bound, representing a severe underestimation of the true number of spatial configurations feasible within chemical space.</li>
<li><strong>Theoretical outcome</strong>: The paper proves that the problem&rsquo;s inherent complexity requires a recursive approach.</li>
<li><strong>Benchmark resource</strong>: The authors published a table of isomer counts up to $C_{40}$ (Table II), correcting historical errors and establishing the first systematic enumeration across this range. Later computational verification revealed that the paper&rsquo;s hand-calculated values are exact through at least $C_{14}$ (confirmed by exhaustive enumeration) but accumulate minor arithmetic errors beyond that range (e.g., at $C_{40}$). The recursive method itself is exact and remains the basis for the accepted values in <a href="https://oeis.org/A000602">OEIS A000602</a>.</li>
</ul>















<figure class="post-figure center ">
    <img src="/img/notes/number-of-isomeric-hydrocarbons-of-the-methane-series.webp"
         alt="Log-scale plot showing exponential growth of alkane isomer counts from C1 to C40"
         title="Log-scale plot showing exponential growth of alkane isomer counts from C1 to C40"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">The number of structural isomers grows super-exponentially with carbon content, reaching over 62 trillion for C₄₀. This plot, derived from Henze and Blair&rsquo;s Table II, illustrates the combinatorial explosion that makes direct enumeration intractable for larger molecules.</figcaption>
    
</figure>

<p>The plot above illustrates the staggering growth rate. Methane ($C_1$) through propane ($C_3$) each have exactly one isomer. Beyond this, the count accelerates rapidly: 75 isomers at $C_{10}$, nearly 37 million at $C_{25}$, and over 4 billion at $C_{30}$. By $C_{40}$, the count exceeds $6.2 \times 10^{13}$ (the paper&rsquo;s hand-calculated Table II reports 62,491,178,805,831, while the modern OEIS-verified value is 62,481,801,147,341). This super-exponential scaling demonstrates why brute-force enumeration becomes impossible and why the recursive approach was essential.</p>
<ul>
<li><strong>Foundational impact</strong>: This work established the mathematical framework that would later evolve into modern chemical graph theory and computational chemistry approaches for molecular enumeration. In the context of AI for molecular generation, this is an early form of <strong>expressivity analysis</strong>, defining the size of the chemical space that generative models must learn to cover.</li>
</ul>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<ul>
<li>
<p><strong>Algorithms</strong>: The exact mathematical recursive formulas and combinatorial partitioning logic are fully provided in the text, allowing for programmatic implementation.</p>
</li>
<li>
<p><strong>Evaluation</strong>: The authors scientifically validated their recursive formulas through exhaustive manual hand-enumeration (brute-force drawing of structural formulas) up to $C_{14}$ to establish absolute correctness.</p>
</li>
<li>
<p><strong>Data</strong>: The paper&rsquo;s Table II provides isomer counts up to $C_{40}$. These hand-calculated values are exact through at least $C_{14}$ (validated by exhaustive enumeration) but accumulate minor arithmetic errors beyond that range. The corrected integer sequence is maintained in the On-Line Encyclopedia of Integer Sequences (OEIS) as <a href="https://oeis.org/A000602">A000602</a>.</p>
</li>
<li>
<p><strong>Code</strong>: The OEIS page provides Mathematica and Maple implementations. The following pure Python implementation uses the OEIS generating functions (which formalize Henze and Blair&rsquo;s recursive method) to compute the corrected isomer counts up to any arbitrary $N$:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">compute_alkane_isomers</span>(max_n: int) <span style="color:#f92672">-&gt;</span> list[int]:
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Computes the number of alkane structural isomers C_nH_{2n+2}
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    up to max_n using the generating functions from OEIS A000602.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> max_n <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span>: <span style="color:#66d9ef">return</span> [<span style="color:#ae81ff">1</span>]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Helper: multiply two polynomials (cap at degree max_n)</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">poly_mul</span>(a: list[int], b: list[int]) <span style="color:#f92672">-&gt;</span> list[int]:
</span></span><span style="display:flex;"><span>        res <span style="color:#f92672">=</span> [<span style="color:#ae81ff">0</span>] <span style="color:#f92672">*</span> (max_n <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">for</span> i, v_a <span style="color:#f92672">in</span> enumerate(a):
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">for</span> j, v_b <span style="color:#f92672">in</span> enumerate(b):
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">if</span> i <span style="color:#f92672">+</span> j <span style="color:#f92672">&lt;=</span> max_n: res[i <span style="color:#f92672">+</span> j] <span style="color:#f92672">+=</span> v_a <span style="color:#f92672">*</span> v_b
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">else</span>: <span style="color:#66d9ef">break</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> res
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Helper: evaluate P(x^k) by spacing out terms</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">poly_pow</span>(a: list[int], k: int) <span style="color:#f92672">-&gt;</span> list[int]:
</span></span><span style="display:flex;"><span>        res <span style="color:#f92672">=</span> [<span style="color:#ae81ff">0</span>] <span style="color:#f92672">*</span> (max_n <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">for</span> i, v <span style="color:#f92672">in</span> enumerate(a):
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> i <span style="color:#f92672">*</span> k <span style="color:#f92672">&lt;=</span> max_n: res[i <span style="color:#f92672">*</span> k] <span style="color:#f92672">=</span> v
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">else</span>: <span style="color:#66d9ef">break</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> res
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># T represents the alkyl radicals (OEIS A000598), T[0] = 1</span>
</span></span><span style="display:flex;"><span>    T <span style="color:#f92672">=</span> [<span style="color:#ae81ff">0</span>] <span style="color:#f92672">*</span> (max_n <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>    T[<span style="color:#ae81ff">0</span>] <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Iteratively build coefficients of T</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># We only need to compute the (n-1)-th degree terms at step n</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> n <span style="color:#f92672">in</span> range(<span style="color:#ae81ff">1</span>, max_n <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span>):
</span></span><span style="display:flex;"><span>        <span style="color:#75715e"># Extract previously calculated slices</span>
</span></span><span style="display:flex;"><span>        t_prev <span style="color:#f92672">=</span> T[:n]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e"># T(x^2) and T(x^3) terms up to n-1</span>
</span></span><span style="display:flex;"><span>        t2_term <span style="color:#f92672">=</span> T[(n <span style="color:#f92672">-</span> <span style="color:#ae81ff">1</span>) <span style="color:#f92672">//</span> <span style="color:#ae81ff">2</span>] <span style="color:#66d9ef">if</span> (n <span style="color:#f92672">-</span> <span style="color:#ae81ff">1</span>) <span style="color:#f92672">%</span> <span style="color:#ae81ff">2</span> <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span> <span style="color:#66d9ef">else</span> <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>        t3_term <span style="color:#f92672">=</span> T[(n <span style="color:#f92672">-</span> <span style="color:#ae81ff">1</span>) <span style="color:#f92672">//</span> <span style="color:#ae81ff">3</span>] <span style="color:#66d9ef">if</span> (n <span style="color:#f92672">-</span> <span style="color:#ae81ff">1</span>) <span style="color:#f92672">%</span> <span style="color:#ae81ff">3</span> <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span> <span style="color:#66d9ef">else</span> <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e"># T(x)^2 and T(x)^3 terms up to n-1</span>
</span></span><span style="display:flex;"><span>        t_squared_n_1 <span style="color:#f92672">=</span> sum(t_prev[i] <span style="color:#f92672">*</span> t_prev[n <span style="color:#f92672">-</span> <span style="color:#ae81ff">1</span> <span style="color:#f92672">-</span> i] <span style="color:#66d9ef">for</span> i <span style="color:#f92672">in</span> range(n))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        t_cubed_n_1 <span style="color:#f92672">=</span> sum(
</span></span><span style="display:flex;"><span>            T[i] <span style="color:#f92672">*</span> T[j] <span style="color:#f92672">*</span> T[n <span style="color:#f92672">-</span> <span style="color:#ae81ff">1</span> <span style="color:#f92672">-</span> i <span style="color:#f92672">-</span> j]
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">for</span> i <span style="color:#f92672">in</span> range(n)
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">for</span> j <span style="color:#f92672">in</span> range(n <span style="color:#f92672">-</span> i)
</span></span><span style="display:flex;"><span>        )
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e"># T(x) * T(x^2) term up to n-1</span>
</span></span><span style="display:flex;"><span>        t_t2_n_1 <span style="color:#f92672">=</span> sum(
</span></span><span style="display:flex;"><span>            T[i] <span style="color:#f92672">*</span> T[j]
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">for</span> i <span style="color:#f92672">in</span> range(n)
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">for</span> j <span style="color:#f92672">in</span> range((n <span style="color:#f92672">-</span> <span style="color:#ae81ff">1</span> <span style="color:#f92672">-</span> i) <span style="color:#f92672">//</span> <span style="color:#ae81ff">2</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> i <span style="color:#f92672">+</span> <span style="color:#ae81ff">2</span><span style="color:#f92672">*</span>j <span style="color:#f92672">==</span> n <span style="color:#f92672">-</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>        )
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        T[n] <span style="color:#f92672">=</span> (t_cubed_n_1 <span style="color:#f92672">+</span> <span style="color:#ae81ff">3</span> <span style="color:#f92672">*</span> t_t2_n_1 <span style="color:#f92672">+</span> <span style="color:#ae81ff">2</span> <span style="color:#f92672">*</span> t3_term) <span style="color:#f92672">//</span> <span style="color:#ae81ff">6</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Calculate Alkanes (OEIS A000602) from fully populated T</span>
</span></span><span style="display:flex;"><span>    T2 <span style="color:#f92672">=</span> poly_pow(T, <span style="color:#ae81ff">2</span>)
</span></span><span style="display:flex;"><span>    T3 <span style="color:#f92672">=</span> poly_pow(T, <span style="color:#ae81ff">3</span>)
</span></span><span style="display:flex;"><span>    T4 <span style="color:#f92672">=</span> poly_pow(T, <span style="color:#ae81ff">4</span>)
</span></span><span style="display:flex;"><span>    T_squared <span style="color:#f92672">=</span> poly_mul(T, T)
</span></span><span style="display:flex;"><span>    T_cubed <span style="color:#f92672">=</span> poly_mul(T_squared, T)
</span></span><span style="display:flex;"><span>    T_fourth <span style="color:#f92672">=</span> poly_mul(T_cubed, T)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    term2 <span style="color:#f92672">=</span> [(T_squared[i] <span style="color:#f92672">-</span> T2[i]) <span style="color:#f92672">//</span> <span style="color:#ae81ff">2</span> <span style="color:#66d9ef">for</span> i <span style="color:#f92672">in</span> range(max_n <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span>)]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    term3_inner <span style="color:#f92672">=</span> [
</span></span><span style="display:flex;"><span>        T_fourth[i]
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">+</span> <span style="color:#ae81ff">6</span> <span style="color:#f92672">*</span> poly_mul(T_squared, T2)[i]
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">+</span> <span style="color:#ae81ff">8</span> <span style="color:#f92672">*</span> poly_mul(T, T3)[i]
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">+</span> <span style="color:#ae81ff">3</span> <span style="color:#f92672">*</span> poly_mul(T2, T2)[i]
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">+</span> <span style="color:#ae81ff">6</span> <span style="color:#f92672">*</span> T4[i]
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">for</span> i <span style="color:#f92672">in</span> range(max_n <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>    ]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    alkanes <span style="color:#f92672">=</span> [<span style="color:#ae81ff">1</span>] <span style="color:#f92672">+</span> [<span style="color:#ae81ff">0</span>] <span style="color:#f92672">*</span> max_n
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> n <span style="color:#f92672">in</span> range(<span style="color:#ae81ff">1</span>, max_n <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span>):
</span></span><span style="display:flex;"><span>        alkanes[n] <span style="color:#f92672">=</span> T[n] <span style="color:#f92672">-</span> term2[n] <span style="color:#f92672">+</span> term3_inner[n <span style="color:#f92672">-</span> <span style="color:#ae81ff">1</span>] <span style="color:#f92672">//</span> <span style="color:#ae81ff">24</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> alkanes
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Calculate and verify</span>
</span></span><span style="display:flex;"><span>isomers <span style="color:#f92672">=</span> compute_alkane_isomers(<span style="color:#ae81ff">40</span>)
</span></span><span style="display:flex;"><span>print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;C_14 isomers: </span><span style="color:#e6db74">{</span>isomers[<span style="color:#ae81ff">14</span>]<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>)   <span style="color:#75715e"># Output: 1858</span>
</span></span><span style="display:flex;"><span>print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;C_40 isomers: </span><span style="color:#e6db74">{</span>isomers[<span style="color:#ae81ff">40</span>]<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>)   <span style="color:#75715e"># Output: 62481801147341</span>
</span></span></code></pre></div></li>
<li>
<p><strong>Hardware</strong>: Derived analytically and enumerated manually by the authors in 1931 without computational hardware.</p>
</li>
</ul>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Henze, H. R., &amp; Blair, C. M. (1931). The number of isomeric hydrocarbons of the methane series. <em>Journal of the American Chemical Society</em>, 53(8), 3077-3085. <a href="https://doi.org/10.1021/ja01359a034">https://doi.org/10.1021/ja01359a034</a></p>
<p><strong>Publication</strong>: Journal of the American Chemical Society (JACS) 1931</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@article</span>{henze1931number,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>=<span style="color:#e6db74">{The number of isomeric hydrocarbons of the methane series}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>=<span style="color:#e6db74">{Henze, Henry R and Blair, Charles M}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">journal</span>=<span style="color:#e6db74">{Journal of the American Chemical Society}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">volume</span>=<span style="color:#e6db74">{53}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">number</span>=<span style="color:#e6db74">{8}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span>=<span style="color:#e6db74">{3077--3085}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span>=<span style="color:#e6db74">{1931}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">publisher</span>=<span style="color:#e6db74">{ACS Publications}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>How to Fold Graciously: Levinthal's Paradox (1969)</title><link>https://hunterheidenreich.com/notes/computational-biology/fold-graciously/</link><pubDate>Mon, 08 Sep 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/computational-biology/fold-graciously/</guid><description>A perspective paper defining the Grand Challenge of protein folding: distinguishing kinetic pathways from thermodynamic endpoints.</description><content:encoded><![CDATA[<h2 id="what-kind-of-paper-is-this">What kind of paper is this?</h2>
<p>This is technically a transcription of a conference talk, not a paper Levinthal wrote himself. The proceedings page credits &ldquo;Notes by: A. Rawitch, Retranscribed: B. Krantz&rdquo;, meaning what we have is a third-party record of an oral presentation Levinthal gave at the 1969 Mössbauer Spectroscopy in Biological Systems meeting at Allerton House, Illinois. This explains the informal, conversational register and the attached Q&amp;A discussion.</p>
<p>In terms of contribution type, it functions as a <strong>Position</strong> paper (with Theory and Discovery elements):</p>
<ul>
<li><strong>Position</strong>: Defines a &ldquo;Grand Challenge&rdquo; and argues for a conceptual shift in how we view biomolecular assembly</li>
<li><strong>Theory</strong>: Uses formal combinatorial arguments to establish the bounds of the search space ($10^{300}$ configurations)</li>
<li><strong>Discovery</strong>: Uses experimental data on alkaline phosphatase to validate the kinetic hypothesis</li>
</ul>
<h2 id="what-is-the-motivation">What is the motivation?</h2>
<p><strong>The Central Question</strong>: How does a protein choose one unique structure out of a hyper-astronomical number of possibilities in a biological timeframe (seconds)?</p>
<p>Levinthal provides a &ldquo;back-of-the-envelope&rdquo; derivation to define the problem scope:</p>
<ol>
<li><strong>Degrees of Freedom:</strong> A generic, unrestricted protein with 2,000 atoms would possess ~6,000 degrees of freedom. However, physical constraints (specifically the planar peptide bond) reduce this significantly. For a 150-amino acid protein, these constraints lower the complexity to ~450 degrees of freedom (300 rotations, 150 bond angles).</li>
<li><strong>The Combinatorial Explosion:</strong> Even with conservative estimates, this results in $10^{300}$ possible conformations.</li>
<li><strong>The Time Constraint:</strong> Since proteins fold in seconds, Levinthal argues they can sample at most <strong>$10^8$ conformations</strong> (&ldquo;postulating a minimum time from one conformation to another&rdquo;) before stabilizing. Against $10^{300}$ possibilities, this search effectively covers 0% of the space, proving the impossibility of random search.</li>
</ol>
<blockquote>
<p><strong>The Insight:</strong> The existence of folded proteins proves the <strong>impossibility of random global search</strong>. The system <em>must</em> be guided.</p>
</blockquote>
<h2 id="what-is-the-novelty-here">What is the novelty here?</h2>
<p><strong>Core Contribution</strong>: Levinthal reframes folding from a thermodynamic problem (seeking the absolute global minimum) to a <strong>Kinetic Control</strong> problem. He argues the native state is a &ldquo;metastable&rdquo; energy well found quickly by a specific pathway, which can differ from the system&rsquo;s lowest possible energy state.</p>
<h3 id="the-pathway-dependence-hypothesis">The Pathway Dependence Hypothesis</h3>
<p>The key insights of kinetic control:</p>
<ul>
<li><strong>Nucleation:</strong> The process is &ldquo;speeded and guided by the rapid formation of local interactions&rdquo;</li>
<li><strong>Pathway Constraints:</strong> Local amino acid sequences form stable interactions and serve as nucleation points in the folding process, restricting the conformational search space</li>
<li><strong>The &ldquo;Metastable&rdquo; State:</strong> The final structure represents a &ldquo;metastable state&rdquo; in a sufficiently deep energy well that is <em>kinetically accessible</em> via the folding pathway, independent of the global energy minimum. Think of a ball that rolls into a valley on the side of a hill and stays there: it is not in the lowest valley on the entire landscape, but it is stable enough that it never escapes.</li>
</ul>















<figure class="post-figure center ">
    <img src="/img/notes/folding-funnel.webp"
         alt="The protein folding energy landscape funnel, showing many unfolded states at high energy converging through multiple pathways to the native folded state at the bottom of the funnel"
         title="The protein folding energy landscape funnel, showing many unfolded states at high energy converging through multiple pathways to the native folded state at the bottom of the funnel"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">The Energy Landscape Funnel: The modern resolution to Levinthal&rsquo;s Paradox. While Levinthal envisioned a single guided pathway, the &lsquo;funnel&rsquo; model (Wolynes, Dill) shows that many different pathways can lead to the same native state basin. The roughness of the funnel surface represents local energy minima (kinetic traps) that can slow folding.</figcaption>
    
</figure>

<h2 id="what-experiments-were-performed">What experiments were performed?</h2>
<p>To support the pathway hypothesis, Levinthal cites work on <strong>Alkaline Phosphatase</strong> (MW ~40,000), utilizing its property as a dimer of two identical subunits:</p>
<ul>
<li><strong>Renaturation Window:</strong> The wild-type enzyme refolds optimally at 37°C. However, mutants were isolated that only produce active enzyme (and renature) at temperatures <em>below</em> 37°C.</li>
<li><strong>Stability vs. Formation:</strong> Crucially, once folded, both the wild-type and mutant enzymes are stable up to 90°C.</li>
<li><strong>The Rate-Limiting Step:</strong> Levinthal notes that the rate-limiting step for activity is the <strong>formation of the dimer</strong> from monomers. This proves that the <em>order of assembly</em> (kinetic pathway) dictates the final structure, distinct from the final structure&rsquo;s thermodynamic stability.</li>
</ul>
<p>The talk concluded with a short motion picture Levinthal showed live, illustrating polypeptide synthesis and &ldquo;the process of then forming a desired interaction via the most favored energy path as displayed on the computer controlled oscilloscope.&rdquo;</p>
<p>The Q&amp;A discussion following the talk includes one exchange directly relevant to the folding argument: when asked whether a protein is ever truly unfolded (devoid of all secondary and tertiary structure), Levinthal answered that both physical measurements and synthetic polypeptide work suggest yes. The other exchanges concerned the tangent formula for x-ray crystallographic phase refinement and whether computed structures had been tested for thermal perturbations.</p>
<h2 id="what-outcomesconclusions">What outcomes/conclusions?</h2>
<h3 id="key-finding">Key Finding</h3>
<p>The mutant experiments serve as the &ldquo;smoking gun&rdquo;: a protein seeking a global thermodynamic minimum would fold spontaneously at any temperature where the final state is stable (up to 90°C). The fact that mutants require specific lower temperatures for <em>formation</em> (while remaining stable at high temperatures once formed) proves that the <strong>kinetic pathway</strong> determines the outcome alongside the thermodynamic endpoint.</p>
<h3 id="broader-implications">Broader Implications</h3>
<p>Levinthal explicitly asks: &ldquo;Is a unique folding necessary for any random 150-amino acid sequence?&rdquo; and answers &ldquo;Probably not.&rdquo; He supports this by noting the difficulty many researchers face in attempting to crystallize proteins, suggesting that not all sequences produce stably folded structures.</p>
<p>He concludes by connecting these computational models to <strong>Mössbauer spectroscopy</strong>, suggesting that these computational studies may help in understanding how small perturbations of polypeptide structures affect the Mössbauer nucleus (a reminder of the specific conference context where this perspective was delivered).</p>
<h3 id="connection-to-modern-work">Connection to Modern Work</h3>
<p>Levinthal&rsquo;s arguments remain relevant context for modern computational protein folding:</p>
<ul>
<li><strong>Early computational visualization:</strong> Levinthal used computer-controlled oscilloscopes and vector matrix multiplications to build and display 3D polypeptide structures, and showed a motion picture of forming a desired interaction via the most favored energy path. This was an early instance of computational molecular visualization.</li>
<li><strong>Local interactions and folding pathways:</strong> The hypothesis that &ldquo;local interactions&rdquo; serve as nucleation points that guide folding remains central to how modern structure prediction methods (e.g., AlphaFold) model residue-residue interactions.</li>
<li><strong>The paradox&rsquo;s lasting influence:</strong> The impossibility of random conformational search that Levinthal articulated continues to motivate approaches that exploit the structure of the energy landscape rather than exhaustive enumeration.</li>
<li><strong>Sequence-structure relationship:</strong> Levinthal&rsquo;s suggestion that not every random amino acid sequence would fold uniquely foreshadows the modern challenge of inverse folding (protein design), where the goal is to find sequences within the subset that does fold to a target structure.</li>
</ul>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Levinthal, C. (1969). How to Fold Graciously. In <em>Mössbauer Spectroscopy in Biological Systems: Proceedings of a meeting held at Allerton House, Monticello, Illinois</em> (pp. 22-24). University of Illinois Press.</p>
<p><strong>Publication</strong>: Mössbauer Spectroscopy in Biological Systems Proceedings, 1969</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@inproceedings</span>{levinthal1969fold,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>=<span style="color:#e6db74">{How to fold graciously}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>=<span style="color:#e6db74">{Levinthal, Cyrus}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">booktitle</span>=<span style="color:#e6db74">{M{\&#34;o}ssbauer spectroscopy in biological systems}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span>=<span style="color:#e6db74">{22--24}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span>=<span style="color:#e6db74">{1969}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">publisher</span>=<span style="color:#e6db74">{University of Illinois Press}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">url</span>=<span style="color:#e6db74">{https://faculty.cc.gatech.edu/~turk/bio_sim/articles/proteins_levinthal_1969.pdf}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><strong>Additional Resources</strong>:</p>
<ul>
<li><a href="https://en.wikipedia.org/wiki/Levinthal%27s_paradox">Levinthal&rsquo;s Paradox (Wikipedia)</a></li>
</ul>
]]></content:encoded></item><item><title>Communication in the Presence of Noise: Shannon's 1949 Paper</title><link>https://hunterheidenreich.com/notes/machine-learning/model-architectures/communication-in-the-presence-of-noise/</link><pubDate>Mon, 08 Sep 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/machine-learning/model-architectures/communication-in-the-presence-of-noise/</guid><description>Shannon's 1949 foundational paper establishing information theory, channel capacity, and the sampling theorem for communication systems.</description><content:encoded><![CDATA[<h2 id="what-kind-of-paper-is-this">What kind of paper is this?</h2>
<p>This is a foundational <strong>Theory</strong> paper. It establishes the mathematical framework for modern information theory and defines the ultimate physical limits of communication for an entire system, from the information source to the final destination.</p>
<h2 id="what-is-the-motivation">What is the motivation?</h2>
<p>The central motivation was to develop a general theory of communication that could quantify information and determine the maximum rate at which it can be transmitted reliably over a noisy channel. Prior to this work, communication system design was largely empirical. Shannon sought to create a mathematical foundation to understand the trade-offs between key parameters like bandwidth, power, and noise, independent of any specific hardware or modulation scheme. To frame this, he conceptualized a general communication system as consisting of five essential elements: an information source, a transmitter, a channel, a receiver, and a destination.</p>
<h2 id="what-is-the-novelty-here">What is the novelty here?</h2>
<p>The novelty is a complete, end-to-end mathematical theory of communication built upon several key concepts and theorems:</p>
<ol>
<li><strong>Geometric Representation of Signals</strong>: Shannon introduced the idea of representing signals as points in a high-dimensional vector space. A signal of duration $T$ and bandwidth $W$ is uniquely specified by $2TW$ numbers (its samples), which are treated as coordinates in a $2TW$-dimensional space. This transformed problems in communication into problems of high-dimensional geometry. In this representation, signal energy corresponds to squared distance from the origin, and noise introduces a &ldquo;sphere of uncertainty&rdquo; around each transmitted point.</li>
</ol>















<figure class="post-figure center ">
    <img src="/img/notes/geometric-interpretation-of-signals-as-spheres.webp"
         alt="Sphere packing illustration showing the geometric interpretation of channel capacity. A large dashed circle represents the total signal space with radius proportional to the square root of P&#43;N. Inside are multiple smaller blue circles (uncertainty spheres) with radius proportional to the square root of N, each centered on a distinct message point."
         title="Sphere packing illustration showing the geometric interpretation of channel capacity. A large dashed circle represents the total signal space with radius proportional to the square root of P&#43;N. Inside are multiple smaller blue circles (uncertainty spheres) with radius proportional to the square root of N, each centered on a distinct message point."
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption"><strong>Sphere Packing and Channel Capacity</strong>: Each transmitted message corresponds to a point in high-dimensional signal space. Noise creates an &lsquo;uncertainty sphere&rsquo; of radius $\sqrt{N}$ around each point. The channel capacity equals how many non-overlapping uncertainty spheres can be packed into the total signal sphere of radius $\sqrt{P+N}$.</figcaption>
    
</figure>

<ol start="2">
<li>
<p><strong>Theorem 1 (The Sampling Theorem)</strong>: The paper provides an explicit statement and proof that a signal containing no frequencies higher than $W$ is perfectly determined by its samples taken at a rate of $2W$ samples per second (i.e., spaced $1/2W$ seconds apart). Shannon credits Nyquist for pointing out the fundamental importance of the time interval $1/2W$ seconds in connection with telegraphy, and names this the &ldquo;Nyquist interval&rdquo; corresponding to the band $W$. This theorem is the theoretical bedrock of all modern digital signal processing.</p>
</li>
<li>
<p><strong>Theorem 2 (Channel Capacity for AWGN)</strong>: This is the paper&rsquo;s most celebrated result, now known as the <strong>Shannon-Hartley theorem</strong> (a name assigned retrospectively, not used in the paper itself). It provides an exact formula for the capacity $C$ (the maximum rate of error-free communication) of a channel with bandwidth $W$, signal power $P$, and additive white Gaussian noise of power $N$:
$$ C = W \log_2 \left(1 + \frac{P}{N}\right) $$
It proves that for any transmission rate below $C$, a coding scheme exists that can achieve an arbitrarily low error frequency.</p>
<p><strong>Random Coding Proof Technique</strong>: Shannon&rsquo;s proof employs a <strong>random coding argument</strong>: he proved that if you choose signal points at random from the sphere of radius $\sqrt{2TWP}$, the average error frequency vanishes for any transmission rate below capacity. This non-constructive proof (meaning it establishes that good codes must exist without constructing any specific one) established that &ldquo;good&rdquo; codes exist almost everywhere in the signal space, even if we don&rsquo;t know how to build them efficiently. The random coding argument became a fundamental tool in information theory, shifting the focus from building specific codes to proving existence and understanding fundamental limits.</p>
</li>
</ol>















<figure class="post-figure center ">
    <img src="/img/notes/shannons-ideal-capacity-curve-and-sampling-theorem.webp"
         alt="Two plots illustrating Shannon&#39;s key theorems: (Left) The ideal capacity curve showing bits per cycle vs SNR in dB, with an example operating point at 10dB. (Right) The sampling theorem demonstrating how a continuous signal is perfectly captured by samples taken at the Nyquist rate of 2W."
         title="Two plots illustrating Shannon&#39;s key theorems: (Left) The ideal capacity curve showing bits per cycle vs SNR in dB, with an example operating point at 10dB. (Right) The sampling theorem demonstrating how a continuous signal is perfectly captured by samples taken at the Nyquist rate of 2W."
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption"><strong>Left</strong>: Shannon&rsquo;s ideal capacity curve, showing how channel capacity (in bits per cycle) increases logarithmically with signal-to-noise ratio. <strong>Right</strong>: The sampling theorem in action, where a band-limited continuous signal is fully determined by discrete samples taken at twice its maximum frequency.</figcaption>
    
</figure>

<ol start="4">
<li>
<p><strong>Theorem 3 (Channel Capacity for Arbitrary Noise)</strong>: Shannon generalized the capacity concept to channels with any type of noise. Entropy power is defined as $N_1 = \frac{1}{2\pi e} e^{2h(X)}$, where $h(X)$ is the differential entropy of the noise distribution (the continuous analog of discrete entropy $H$: where $H$ counts the average bits per symbol from a discrete source, $h(X)$ measures the same unpredictability for continuous-valued random variables); it quantifies how spread out a distribution is in an information-theoretic sense, with Gaussian noise having the highest entropy power for a given variance. He showed that the capacity for a channel with arbitrary noise of power $N$ is bounded by the noise&rsquo;s <strong>entropy power</strong> $N_1$. Shannon proved that <strong>white Gaussian noise is the worst possible type of noise</strong> for any given noise power. Because the Gaussian distribution maximizes entropy for a given variance, the entropy power $N_1$ of any noise with power $N$ satisfies $N_1 \leq N$, with equality only for the Gaussian case. Since channel capacity decreases as entropy power increases, Gaussian noise achieves the highest $N_1$ (equal to $N$) and therefore imposes the lowest capacity bound. This means a system designed to handle white Gaussian noise will perform at least as well against any other noise type of the same power.</p>
<p><strong>Arbitrary Gaussian Noise and the Water-Filling Principle</strong>: Shannon extended his analysis to Gaussian noise with a non-flat power spectrum $N(f)$, using the calculus of variations (a technique for optimizing over functions rather than fixed variables) to find the power allocation $P(f)$ that maximizes capacity. He proved that optimal capacity is achieved when the sum $P(f) + N(f)$ is constant across the utilized frequency band. This leads to what is now known as the &ldquo;water-filling&rdquo; principle: allocate more signal power to quieter frequency bands, and allocate zero power to any band where noise exceeds the constant threshold. This provides the foundation for modern adaptive power allocation across frequency bands.</p>
</li>
</ol>















<figure class="post-figure center ">
    <img src="/img/notes/the-water-filling-principle.webp"
         alt="The water-filling principle for optimal power allocation. Gray area shows noise power N(f) varying across frequencies, orange area shows signal power P(f) allocated to fill up to a constant level lambda, such that P(f) &#43; N(f) equals a constant."
         title="The water-filling principle for optimal power allocation. Gray area shows noise power N(f) varying across frequencies, orange area shows signal power P(f) allocated to fill up to a constant level lambda, such that P(f) &#43; N(f) equals a constant."
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption"><strong>The Water-Filling Principle</strong>: The condition $P(f) + N(f) = \lambda$ is Shannon&rsquo;s derivation; &lsquo;water-filling&rsquo; is the modern retrospective label for it. When noise power varies across frequencies, optimal capacity is achieved by allocating more signal power to &lsquo;quieter&rsquo; frequency bands. Like filling a container with water, power is poured in until the total (signal + noise) reaches a constant level $\lambda$. Frequencies with noise above this threshold receive no power at all.</figcaption>
    
</figure>

<ol start="5">
<li>
<p><strong>Theorem 4 (now known as the Source Coding Theorem)</strong>: This theorem addresses the information source itself. It proves that it&rsquo;s possible to encode messages from a discrete source into binary digits such that the average number of bits per source symbol approaches the source&rsquo;s <strong>entropy</strong>, $H$. This establishes entropy as the fundamental limit of data compression.</p>
</li>
<li>
<p><strong>Theorem 5 (Information Rate for Continuous Sources)</strong>: For continuous (analog) signals, Shannon introduced a concept foundational to rate-distortion theory. He defined the rate $R$ at which a continuous source generates information relative to a specific fidelity criterion (i.e., a tolerable amount of error, $N_1$, in the reproduction). This provides an early theoretical foundation for what later became rate-distortion theory.</p>
</li>
</ol>
<h2 id="what-experiments-were-performed">What experiments were performed?</h2>
<p>The paper is primarily theoretical, with &ldquo;experiments&rdquo; consisting of rigorous <strong>mathematical derivations and proofs</strong>. The channel capacity theorem, for instance, is proven using a geometric sphere-packing argument in the high-dimensional signal space.</p>
<p>However, Shannon does include a quantitative <strong>theoretical benchmark against existing 1949 technology</strong>. He plots his theoretical &ldquo;Ideal Curve&rdquo; against calculated limits of Pulse Code Modulation (PCM) and Pulse Position Modulation (PPM) systems in Figure 6. The PCM points were calculated from formulas in another paper, and the PPM points were from unpublished calculations by B. McMillan. This comparison reveals that the entire series of plotted points for these contemporary systems operated approximately <strong>8 dB</strong> below the ideal power limit over most of the practical range. Interestingly, PPM systems approached to within <strong>3 dB</strong> of the ideal curve specifically at very small $P/N$ ratios, highlighting that different modulation schemes are optimal for different regimes (PCM for high SNR, PPM for power-limited scenarios).</p>
<h2 id="what-outcomesconclusions">What outcomes/conclusions?</h2>
<p>The primary outcome was a complete, unified theory that quantifies both information itself (entropy) and the ability of a channel to transmit it (capacity).</p>
<ul>
<li>
<p><strong>Decoupling of Source and Channel</strong>: A key conclusion is that the problem of communication can be split into two distinct parts: encoding sequences of message symbols into sequences of binary digits (where the average digits per symbol approaches the entropy $H$), and then mapping these binary digits into a particular signal function of long duration to combat noise. A source can be transmitted reliably if and only if its rate $R$ (or entropy $H$) is less than the channel capacity $C$.</p>
</li>
<li>
<p><strong>The Limit is on Rate</strong>: A central conclusion is that noise in a channel imposes a maximum <strong>rate</strong> of transmission. Below this rate, error-free communication is theoretically possible.</p>
</li>
<li>
<p><strong>The Threshold Effect and Topological Necessity</strong>: To approach capacity, one must map a lower-dimensional message space into the high-dimensional signal space efficiently, winding through the available signal sphere to fill its volume (as illustrated with the efficient mapping in Fig. 4 of the paper). This complex mapping creates a sharp <strong>threshold effect</strong>: below a certain noise level, recovery is essentially perfect; above it, the system fails catastrophically because the &ldquo;uncertainty spheres&rdquo; around signal points begin to overlap. Shannon provides a topological explanation for why this threshold is unavoidable: it is not possible to map a region of higher dimensionality into a region of lower dimensionality continuously. To compress bandwidth (reducing the number of dimensions in signal space), the mapping from message space to signal space must necessarily be discontinuous. This required discontinuity creates vulnerable points where a small noise perturbation can cause the received signal to &ldquo;jump&rdquo; to an entirely different interpretation. The threshold is an inevitable consequence of dimensional reduction.</p>
</li>
<li>
<p><strong>The Exchange Relation</strong>: Shannon explicitly states that the key parameters $T$ (time), $W$ (bandwidth), $P$ (power), and $N$ (noise) can be &ldquo;altered at will&rdquo; without changing the total information transmitted, provided $TW \log(1 + P/N)$ is held constant. This exchangeability enables trade-offs such as using more bandwidth to compensate for lower power.</p>
</li>
<li>
<p><strong>Characteristics of an Ideal System</strong>: The theory implies that to approach the channel capacity limit, one must use very complex and long codes. An ideal system exhibits five key properties: (1) the transmission rate approaches $C$, (2) the error probability approaches zero, (3) the transmitted signal&rsquo;s statistical properties approach those of white noise, (4) the threshold effect becomes very sharp (errors increase rapidly if noise exceeds the designed value), and (5) <strong>the required delay increases indefinitely</strong>. This final constraint is a crucial practical limitation: achieving near-capacity performance requires encoding over increasingly long message blocks, introducing latency that may be unacceptable for real-time applications.</p>
</li>
</ul>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="algorithms">Algorithms</h3>
<p>The paper introduces the theoretical foundation for the <strong>water-filling algorithm</strong> for optimal power allocation across frequency bands with varying noise levels. The mathematical condition derived is that $P(f) + N(f)$ must be constant across the utilized frequency band.</p>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Shannon, C. E. (1949). Communication in the Presence of Noise. <em>Proceedings of the IRE</em>, 37(1), 10-21. <a href="https://doi.org/10.1109/JRPROC.1949.232969">https://doi.org/10.1109/JRPROC.1949.232969</a></p>
<p><strong>Publication</strong>: Proceedings of the IRE, 1949</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@article</span>{shannon1949communication,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>=<span style="color:#e6db74">{Shannon, C. E.}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">journal</span>=<span style="color:#e6db74">{Proceedings of the IRE}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>=<span style="color:#e6db74">{Communication in the Presence of Noise}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span>=<span style="color:#e6db74">{1949}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">volume</span>=<span style="color:#e6db74">{37}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">number</span>=<span style="color:#e6db74">{1}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span>=<span style="color:#e6db74">{10-21}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">doi</span>=<span style="color:#e6db74">{10.1109/JRPROC.1949.232969}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Exponential Random Numbers: Two Classic Algorithms</title><link>https://hunterheidenreich.com/posts/random-number-tricks/</link><pubDate>Sun, 31 Aug 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/posts/random-number-tricks/</guid><description>Compare inverse transform sampling and von Neumann's rejection method for exponential random numbers with Python implementations and performance.</description><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2>
<p>In the early days of computing, generating random numbers was a significant computational challenge. In a landmark 1951 paper, mathematician John von Neumann detailed various &ldquo;cooking recipes&rdquo; for producing and using random numbers on machines like the ENIAC. While much of the paper focuses on generating <em>uniform</em> random digits, he also described ingenious methods for generating numbers from more complex, non-uniform probability distributions.</p>
<p>One of the most fundamental needs in scientific simulation (from modeling radioactive decay to calculating particle free-paths in molecular dynamics) is sampling from an <strong>exponential distribution</strong> with probability density function:</p>
<p>$$f(x) = e^{-x} \quad \text{for } x \ge 0$$</p>
<p>Today&rsquo;s standard approach is elegant and direct, but it requires computing a natural logarithm (a computationally expensive operation on early hardware). To sidestep this limitation, von Neumann described a fascinating alternative that uses only basic comparisons, resembling what he called &ldquo;a well known game of chance Twenty-One, or Black Jack.&rdquo;</p>
<p>In this post, we&rsquo;ll explore both methods: the modern inverse transform approach and von Neumann&rsquo;s ingenious comparison-based algorithm. We&rsquo;ll implement them in Python, verify their correctness, and compare their performance, empirically testing the trade-offs von Neumann identified nearly 75 years ago.</p>
<hr>
<h2 id="method-1-the-standard-approach-inverse-transform-sampling">Method 1: The Standard Approach (Inverse Transform Sampling)</h2>
<p>The most common method for sampling from a given distribution is <strong>inverse transform sampling</strong>. This method relies on a fundamental principle: if you have a uniform random variable $U$ on the interval (0, 1), you can transform it into a random variable $X$ with any desired cumulative distribution function (CDF) $F(x)$ by applying:</p>
<p>$$X = F^{-1}(U)$$</p>
<p>For the exponential distribution, the CDF is $F(x) = 1 - e^{-x}$. To find the inverse, we set $U = 1 - e^{-X}$ and solve for $X$:</p>
<p>$$
\begin{align}
e^{-X} &amp;= 1 - U \
-X &amp;= \ln(1 - U) \
X &amp;= -\ln(1 - U)
\end{align}
$$</p>
<p>Here&rsquo;s a useful simplification: since $U$ is uniformly distributed on (0, 1), the quantity $(1 - U)$ is also uniformly distributed on (0, 1). Therefore, we can use the simpler formula:</p>
<p>$$X = -\ln(U)$$</p>
<p>This gives us an efficient method for generating exponentially distributed numbers, provided the logarithm function is computationally accessible.</p>
<h3 id="python-implementation">Python Implementation</h3>
<p>Here&rsquo;s a straightforward implementation using NumPy:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">import</span> numpy <span style="color:#66d9ef">as</span> np
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">exponential_inverse_transform</span>(n_samples<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span>):
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Generate samples from an exponential distribution using inverse transform sampling.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Args:
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        n_samples (int): Number of samples to generate.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Returns:
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        np.ndarray: Array of exponentially distributed samples.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Generate uniform random numbers</span>
</span></span><span style="display:flex;"><span>    U <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>random<span style="color:#f92672">.</span>rand(n_samples)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Apply the inverse transform</span>
</span></span><span style="display:flex;"><span>    X <span style="color:#f92672">=</span> <span style="color:#f92672">-</span>np<span style="color:#f92672">.</span>log(U)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> X
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Generate 100,000 samples for testing</span>
</span></span><span style="display:flex;"><span>n_samples <span style="color:#f92672">=</span> <span style="color:#ae81ff">100000</span>
</span></span><span style="display:flex;"><span>inverse_samples <span style="color:#f92672">=</span> exponential_inverse_transform(n_samples)
</span></span></code></pre></div><hr>
<h2 id="method-2-von-neumanns-ingenious-trick-rejection-sampling">Method 2: Von Neumann&rsquo;s Ingenious Trick (Rejection Sampling)</h2>
<p>Von Neumann proposed a clever alternative that avoids transcendental functions entirely. His procedure, which he noted &ldquo;resembles a well known game of chance Twenty-One, or Black Jack,&rdquo; generates sequences of uniform random numbers and accepts or rejects them based on simple comparison rules.</p>
<p>The algorithm works as follows to generate a single exponential sample $X$:</p>
<ol>
<li>
<p><strong>Initialize</strong>: Start with an integer offset <code>k = 0</code>, which will form the integer part of the final result.</p>
</li>
<li>
<p><strong>Generate a trial sequence</strong>:</p>
<ul>
<li>Generate uniform random numbers $Y_1, Y_2, Y_3, \ldots$ from (0, 1)</li>
<li>Find the smallest integer <code>n</code> such that the sequence is no longer strictly decreasing</li>
<li>That is, find <code>n</code> where $Y_1 &gt; Y_2 &gt; \cdots &gt; Y_n$ but $Y_n \leq Y_{n+1}$</li>
</ul>
</li>
<li>
<p><strong>Accept or reject</strong>:</p>
<ul>
<li>If <code>n</code> is <strong>odd</strong>: Accept the trial. Return $X = Y_1 + k$ and terminate.</li>
<li>If <code>n</code> is <strong>even</strong>: Reject the trial. Increment <code>k</code> by 1 and start a new trial.</li>
</ul>
</li>
</ol>
<p>This process is guaranteed to terminate and produces samples that follow the exponential distribution exactly. As von Neumann elegantly put it, the machine has &ldquo;in effect computed a logarithm by performing only discriminations on the relative magnitude of numbers.&rdquo;</p>
<h3 id="python-implementation-1">Python Implementation</h3>
<p>This implementation requires more careful state management due to the nested trial structure:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">import</span> numpy <span style="color:#66d9ef">as</span> np
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">exponential_von_neumann</span>(n_samples<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span>):
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Generate samples from an exponential distribution using von Neumann&#39;s
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    comparison-based rejection sampling method.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Args:
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        n_samples (int): Number of samples to generate.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Returns:
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">        tuple[np.ndarray, float]: Array of samples and average uniform draws per sample.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    samples <span style="color:#f92672">=</span> []
</span></span><span style="display:flex;"><span>    total_uniform_draws <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> _ <span style="color:#f92672">in</span> range(n_samples):
</span></span><span style="display:flex;"><span>        k <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>  <span style="color:#75715e"># Integer offset</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">while</span> <span style="color:#66d9ef">True</span>:  <span style="color:#75715e"># Trial loop</span>
</span></span><span style="display:flex;"><span>            <span style="color:#75715e"># Generate decreasing sequence</span>
</span></span><span style="display:flex;"><span>            y_prev <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>random<span style="color:#f92672">.</span>rand()
</span></span><span style="display:flex;"><span>            total_uniform_draws <span style="color:#f92672">+=</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>            y1 <span style="color:#f92672">=</span> y_prev  <span style="color:#75715e"># Store first value</span>
</span></span><span style="display:flex;"><span>            n <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            <span style="color:#75715e"># Find length of decreasing sequence</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">while</span> <span style="color:#66d9ef">True</span>:
</span></span><span style="display:flex;"><span>                y_curr <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>random<span style="color:#f92672">.</span>rand()
</span></span><span style="display:flex;"><span>                total_uniform_draws <span style="color:#f92672">+=</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">if</span> y_prev <span style="color:#f92672">&lt;=</span> y_curr:
</span></span><span style="display:flex;"><span>                    <span style="color:#66d9ef">break</span>  <span style="color:#75715e"># Sequence no longer decreasing</span>
</span></span><span style="display:flex;"><span>                y_prev <span style="color:#f92672">=</span> y_curr
</span></span><span style="display:flex;"><span>                n <span style="color:#f92672">+=</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            <span style="color:#75715e"># Accept if n is odd, reject if even</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> n <span style="color:#f92672">%</span> <span style="color:#ae81ff">2</span> <span style="color:#f92672">==</span> <span style="color:#ae81ff">1</span>:  <span style="color:#75715e"># Accept</span>
</span></span><span style="display:flex;"><span>                samples<span style="color:#f92672">.</span>append(y1 <span style="color:#f92672">+</span> k)
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">break</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">else</span>:  <span style="color:#75715e"># Reject</span>
</span></span><span style="display:flex;"><span>                k <span style="color:#f92672">+=</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    avg_draws <span style="color:#f92672">=</span> total_uniform_draws <span style="color:#f92672">/</span> n_samples
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> np<span style="color:#f92672">.</span>array(samples), avg_draws
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Generate samples using von Neumann&#39;s method</span>
</span></span><span style="display:flex;"><span>von_neumann_samples, avg_draws <span style="color:#f92672">=</span> exponential_von_neumann(n_samples)
</span></span><span style="display:flex;"><span>print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Von Neumann method used </span><span style="color:#e6db74">{</span>avg_draws<span style="color:#e6db74">:</span><span style="color:#e6db74">.2f</span><span style="color:#e6db74">}</span><span style="color:#e6db74"> uniform draws per sample on average.&#34;</span>)
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-console" data-lang="console"><span style="display:flex;"><span>Von Neumann method used 4.30 uniform draws per sample on average.
</span></span></code></pre></div><p>The algorithm requires approximately <strong>4.3</strong> uniform draws per exponential sample, matching the theoretical value $e^2/(e-1) = 4.30$.</p>
<hr>
<h2 id="verification-and-comparison">Verification and Comparison</h2>
<p>The critical test: do both methods actually produce the same distribution? And how do their performance characteristics compare?</p>
<h3 id="visual-verification">Visual Verification</h3>
<p>Let&rsquo;s plot histograms of samples from both methods alongside the theoretical probability density function $f(x) = e^{-x}$:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">import</span> matplotlib.pyplot <span style="color:#66d9ef">as</span> plt
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> seaborn <span style="color:#66d9ef">as</span> sns
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Configure plot aesthetics</span>
</span></span><span style="display:flex;"><span>sns<span style="color:#f92672">.</span>set_style(<span style="color:#e6db74">&#34;whitegrid&#34;</span>)
</span></span><span style="display:flex;"><span>plt<span style="color:#f92672">.</span>figure(figsize<span style="color:#f92672">=</span>(<span style="color:#ae81ff">12</span>, <span style="color:#ae81ff">7</span>))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Plot histograms for both methods</span>
</span></span><span style="display:flex;"><span>plt<span style="color:#f92672">.</span>hist(inverse_samples, bins<span style="color:#f92672">=</span><span style="color:#ae81ff">50</span>, density<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>, alpha<span style="color:#f92672">=</span><span style="color:#ae81ff">0.7</span>,
</span></span><span style="display:flex;"><span>         label<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;Inverse Transform&#39;</span>, color<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;skyblue&#39;</span>)
</span></span><span style="display:flex;"><span>plt<span style="color:#f92672">.</span>hist(von_neumann_samples, bins<span style="color:#f92672">=</span><span style="color:#ae81ff">50</span>, density<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>, alpha<span style="color:#f92672">=</span><span style="color:#ae81ff">0.7</span>,
</span></span><span style="display:flex;"><span>         label<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;Von Neumann&#39;s Method&#34;</span>, color<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;lightcoral&#39;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Overlay theoretical PDF</span>
</span></span><span style="display:flex;"><span>x <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>linspace(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">8</span>, <span style="color:#ae81ff">400</span>)
</span></span><span style="display:flex;"><span>pdf <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>exp(<span style="color:#f92672">-</span>x)
</span></span><span style="display:flex;"><span>plt<span style="color:#f92672">.</span>plot(x, pdf, <span style="color:#e6db74">&#39;r-&#39;</span>, linewidth<span style="color:#f92672">=</span><span style="color:#ae81ff">2</span>, label<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;Theoretical PDF ($e^{-x}$)&#39;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>plt<span style="color:#f92672">.</span>title(<span style="color:#e6db74">&#39;Exponential Sampling Methods vs. Theoretical Distribution&#39;</span>, fontsize<span style="color:#f92672">=</span><span style="color:#ae81ff">16</span>)
</span></span><span style="display:flex;"><span>plt<span style="color:#f92672">.</span>xlabel(<span style="color:#e6db74">&#39;x&#39;</span>, fontsize<span style="color:#f92672">=</span><span style="color:#ae81ff">12</span>)
</span></span><span style="display:flex;"><span>plt<span style="color:#f92672">.</span>ylabel(<span style="color:#e6db74">&#39;Density&#39;</span>, fontsize<span style="color:#f92672">=</span><span style="color:#ae81ff">12</span>)
</span></span><span style="display:flex;"><span>plt<span style="color:#f92672">.</span>legend()
</span></span><span style="display:flex;"><span>plt<span style="color:#f92672">.</span>xlim(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">8</span>)
</span></span><span style="display:flex;"><span>plt<span style="color:#f92672">.</span>tight_layout()
</span></span><span style="display:flex;"><span>plt<span style="color:#f92672">.</span>show()
</span></span></code></pre></div>














<figure class="post-figure center ">
    <img src="/img/exponential_random_gens.webp"
         alt="Comparison of exponential sampling methods showing histograms from both inverse transform and von Neumann methods overlaid with the theoretical exponential distribution"
         title="Comparison of exponential sampling methods showing histograms from both inverse transform and von Neumann methods overlaid with the theoretical exponential distribution"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">Both sampling methods reproduce the exponential distribution $f(x) = e^{-x}$</figcaption>
    
</figure>

<p>The visualization confirms that both methods accurately reproduce the target exponential distribution. The empirical histograms match the theoretical curve, confirming both algorithms sample the target distribution.</p>
<h3 id="performance-analysis">Performance Analysis</h3>
<p>Mathematical elegance often diverges from computational efficiency. Von Neumann himself observed that on the ENIAC, it was actually &ldquo;slightly quicker to use a truncated power series for log(1-T)&rdquo; than to perform all the comparisons his method required.</p>
<p>Let&rsquo;s benchmark both approaches in a modern Python environment:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">import</span> time
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Benchmark inverse transform method</span>
</span></span><span style="display:flex;"><span>start_time <span style="color:#f92672">=</span> time<span style="color:#f92672">.</span>time()
</span></span><span style="display:flex;"><span>_ <span style="color:#f92672">=</span> exponential_inverse_transform(n_samples)
</span></span><span style="display:flex;"><span>inverse_time <span style="color:#f92672">=</span> time<span style="color:#f92672">.</span>time() <span style="color:#f92672">-</span> start_time
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Benchmark von Neumann method</span>
</span></span><span style="display:flex;"><span>start_time <span style="color:#f92672">=</span> time<span style="color:#f92672">.</span>time()
</span></span><span style="display:flex;"><span>_ <span style="color:#f92672">=</span> exponential_von_neumann(n_samples)
</span></span><span style="display:flex;"><span>vn_time <span style="color:#f92672">=</span> time<span style="color:#f92672">.</span>time() <span style="color:#f92672">-</span> start_time
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Inverse Transform:  </span><span style="color:#e6db74">{</span>inverse_time<span style="color:#e6db74">:</span><span style="color:#e6db74">.4f</span><span style="color:#e6db74">}</span><span style="color:#e6db74"> seconds&#34;</span>)
</span></span><span style="display:flex;"><span>print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Von Neumann Method: </span><span style="color:#e6db74">{</span>vn_time<span style="color:#e6db74">:</span><span style="color:#e6db74">.4f</span><span style="color:#e6db74">}</span><span style="color:#e6db74"> seconds&#34;</span>)
</span></span><span style="display:flex;"><span>print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#34;Speedup factor: </span><span style="color:#e6db74">{</span>vn_time <span style="color:#f92672">/</span> inverse_time<span style="color:#e6db74">:</span><span style="color:#e6db74">.1f</span><span style="color:#e6db74">}</span><span style="color:#e6db74">x&#34;</span>)
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-console" data-lang="console"><span style="display:flex;"><span>Inverse Transform:  0.0018 seconds
</span></span><span style="display:flex;"><span>Von Neumann Method: 0.1860 seconds
</span></span><span style="display:flex;"><span>Speedup factor: 103.3x
</span></span></code></pre></div><p>The gap is large. The vectorized NumPy implementation of inverse transform sampling, leveraging a highly optimized C-backed logarithm function, outperforms the Python-looped von Neumann implementation by more than two orders of magnitude. While a vectorized or JIT-compiled version of von Neumann&rsquo;s method would close this gap by removing Python interpreter overhead, the inverse transform remains the practical winner on modern hardware with fast floating-point units. This confirms von Neumann&rsquo;s prescient observation: the &ldquo;theoretically elegant&rdquo; method avoiding transcendental functions often yields to direct computation.</p>
<h2 id="conclusion">Conclusion</h2>
<p>This exploration offers a window into the ingenuity of early computational mathematics. Von Neumann&rsquo;s comparison-based algorithm demonstrates remarkable mathematical creativity (showing how to &ldquo;compute a logarithm&rdquo; using only basic machine operations). Our implementation reproduces the algorithm, producing samples whose histogram and moments match the exponential distribution.</p>
<p>The performance comparison validates von Neumann&rsquo;s own pragmatic assessment. His rejection sampling method is intellectually elegant and historically significant. The direct logarithmic approach proves far more efficient on both early and modern hardware. It serves as a timeless reminder in scientific computing: theoretical beauty often diverges from computational practicality.</p>
<p>The enduring value of von Neumann&rsquo;s work lies in the fundamental insight that creative mathematical thinking can circumvent apparent computational limitations. Understanding alternative methods deepens our appreciation for the rich landscape of algorithmic possibilities, even when the direct approach proves superior.</p>
]]></content:encoded></item><item><title>Efficient DFT Hamiltonian Prediction via Adaptive Sparsity</title><link>https://hunterheidenreich.com/notes/chemistry/molecular-simulation/ml-potentials/efficient-dft-hamiltonian-predicton-sphnet/</link><pubDate>Sat, 23 Aug 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/chemistry/molecular-simulation/ml-potentials/efficient-dft-hamiltonian-predicton-sphnet/</guid><description>Luo et al. introduce SPHNet, using adaptive sparsity to achieve up to 7x speedup in SE(3)-equivariant Hamiltonian prediction.</description><content:encoded><![CDATA[<h2 id="core-innovation-adaptive-sparsity-in-se3-networks">Core Innovation: Adaptive Sparsity in SE(3) Networks</h2>
<p>This is a <strong>methodological paper</strong> introducing a novel architecture and training curriculum to solve efficiency bottlenecks in Geometric Deep Learning. It directly tackles the primary computational bottleneck in modern SE(3)-equivariant graph neural networks (the tensor product operation) and proposes a generalizable solution through adaptive network sparsification.</p>
<h2 id="the-computational-bottleneck-in-dft-hamiltonian-prediction">The Computational Bottleneck in DFT Hamiltonian Prediction</h2>
<p>SE(3)-equivariant networks are accurate but unscalable for DFT Hamiltonian prediction due to two key bottlenecks:</p>
<ul>
<li><strong>Atom Scaling</strong>: Tensor Product (TP) operations grow quadratically with atoms ($N^2$).</li>
<li><strong>Basis Set Scaling</strong>: Computational complexity grows with the sixth power of the angular momentum order ($L^6$). Larger basis sets (e.g., def2-TZVP) require higher orders ($L=6$), making them prohibitively slow.</li>
</ul>
<p>Existing SE(3)-equivariant models cannot handle large molecules (40-100 atoms) with high-quality basis sets, limiting their practical applicability in computational chemistry.</p>
<h2 id="sphnet-architecture-and-the-three-phase-sparsity-scheduler">SPHNet Architecture and the Three-Phase Sparsity Scheduler</h2>
<p><strong>SPHNet</strong> introduces <strong>Adaptive Sparsity</strong> to prune redundant computations at two levels:</p>
<ol>
<li><strong>Sparse Pair Gate</strong>: Learns which atom pairs to include in message passing, adapting the interaction graph based on importance.</li>
<li><strong>Sparse TP Gate</strong>: Filters which spherical harmonic triplets $(l_1, l_2, l_3)$ are computed in tensor product operations, pruning higher-order combinations that contribute less to accuracy.</li>
<li><strong>Three-Phase Sparsity Scheduler</strong>: A training curriculum (Random → Adaptive → Fixed) that enables stable convergence to high-performing sparse subnetworks.</li>
</ol>
<p>Key insight: The Sparse Pair Gate learns to preserve long-range interactions (16-25 Angstrom) at higher rates than short-range ones. Short-range pairs are abundant and easier to learn, while rare long-range interactions require more samples for accurate representation, making them more critical to retain.</p>
<h2 id="benchmarks-and-ablation-studies">Benchmarks and Ablation Studies</h2>
<p>The authors evaluated SPHNet on three datasets (MD17, QH9, and PubChemQH) with varying molecule sizes and basis set complexities. Baselines include SchNOrb, PhiSNet, QHNet, and WANet. SchNOrb and PhiSNet results are limited to MD17, as those models are designed for trajectory datasets. WANet was not open-sourced, so only partial metrics from its paper are reported.</p>
<h3 id="evaluation-metrics">Evaluation Metrics</h3>
<ul>
<li><strong>Hamiltonian MAE ($H$)</strong>: Mean absolute error between predicted and DFT-computed Hamiltonian matrices, in Hartrees ($E_h$)</li>
<li><strong>Occupied Orbital Energy MAE ($\epsilon$)</strong>: Mean absolute error of all occupied molecular orbital energies derived from the predicted Hamiltonian</li>
<li><strong>Orbital Coefficient Similarity ($\psi$)</strong>: Cosine similarity of occupied molecular orbital coefficients between predicted and reference wavefunctions</li>
</ul>
<h3 id="ablation-studies">Ablation Studies</h3>
<p><strong>Sparse Gates</strong> (on PubChemQH):</p>
<table>
	<thead>
			<tr>
					<th>Configuration</th>
					<th>$H$ [$10^{-6} E_h$] $\downarrow$</th>
					<th>Memory [GB] $\downarrow$</th>
					<th>Speedup $\uparrow$</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Both gates</td>
					<td>97.31</td>
					<td>5.62</td>
					<td>7.09x</td>
			</tr>
			<tr>
					<td>Pair Gate only</td>
					<td>87.70</td>
					<td>6.98</td>
					<td>2.73x</td>
			</tr>
			<tr>
					<td>TP Gate only</td>
					<td>94.31</td>
					<td>8.04</td>
					<td>3.98x</td>
			</tr>
			<tr>
					<td>Neither gate</td>
					<td>86.35</td>
					<td>10.91</td>
					<td>1.73x</td>
			</tr>
	</tbody>
</table>
<p>The Sparse Pair Gate contributes a 78% speedup with 30% memory reduction. The Sparse TP Gate (pruning 70% of combinations) yields a 160% speedup. Both gates together achieve the highest speedup, though accuracy slightly decreases compared to no gating.</p>
<p><strong>Three-Phase Scheduler</strong>: Removing the random phase causes convergence to local optima ($112.68 \pm 10.75$ vs $97.31 \pm 0.52$). Removing the adaptive phase increases variance and lowers accuracy ($122.79 \pm 19.02$). Removing the fixed phase has minimal accuracy impact but reduces speedup from 7.09x to 5.45x due to dynamic graph overhead.</p>
<p><strong>Sparsity Rate</strong>: The critical sparsity threshold scales with system complexity: 30% for MD17 (small molecules), 40% for QH9 (medium), and 70% for PubChemQH (large). Beyond the threshold, MAE increases sharply. Computational cost decreases approximately linearly with sparsity rate.</p>
<h3 id="transferability-to-other-models">Transferability to Other Models</h3>
<p>To demonstrate the speedup is architecture-agnostic, the authors applied the Sparse Pair Gate and Sparse TP Gate to the QHNet baseline on PubChemQH:</p>
<table>
	<thead>
			<tr>
					<th>Configuration</th>
					<th>$H$ [$10^{-6} E_h$] $\downarrow$</th>
					<th>Memory [GB] $\downarrow$</th>
					<th>Speedup $\uparrow$</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>QHNet baseline</td>
					<td>123.74</td>
					<td>22.50</td>
					<td>1.00x</td>
			</tr>
			<tr>
					<td>+ TP Gate</td>
					<td>128.16</td>
					<td>12.68</td>
					<td>2.04x</td>
			</tr>
			<tr>
					<td>+ Pair Gate</td>
					<td>126.27</td>
					<td>10.07</td>
					<td>1.66x</td>
			</tr>
			<tr>
					<td>+ Both gates</td>
					<td>128.89</td>
					<td>8.46</td>
					<td>3.30x</td>
			</tr>
	</tbody>
</table>
<p>The gates reduced QHNet&rsquo;s memory by 62% and improved speed by 3.3x with modest accuracy trade-off, confirming the gates are portable modules applicable to other SE(3)-equivariant architectures.</p>
<h2 id="performance-results">Performance Results</h2>
<h3 id="qh9-134k-molecules-leq-20-atoms">QH9 (134k molecules, $\leq$ 20 atoms)</h3>
<p>SPHNet achieves 3.3x to 4.0x speedup over QHNet across all four QH9 splits, with improved Hamiltonian MAE and orbital energy MAE. Memory drops to 0.23 GB/sample (33% of QHNet&rsquo;s 0.70 GB). On the stable-iid split, Hamiltonian MAE improves from 76.31 to 45.48 ($10^{-6} E_h$).</p>
<h3 id="pubchemqh-50k-molecules-40-100-atoms">PubChemQH (50k molecules, 40-100 atoms)</h3>
<table>
	<thead>
			<tr>
					<th>Model</th>
					<th>$H$ [$10^{-6} E_h$] $\downarrow$</th>
					<th>$\epsilon$ [$E_h$] $\downarrow$</th>
					<th>$\psi$ [$10^{-2}$] $\uparrow$</th>
					<th>Memory [GB] $\downarrow$</th>
					<th>Speedup $\uparrow$</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>QHNet</td>
					<td>123.74</td>
					<td>3.33</td>
					<td>2.32</td>
					<td>22.5</td>
					<td>1.0x</td>
			</tr>
			<tr>
					<td>WANet</td>
					<td>99.98</td>
					<td><strong>1.17</strong></td>
					<td><strong>3.13</strong></td>
					<td>15.0</td>
					<td>2.4x</td>
			</tr>
			<tr>
					<td>SPHNet</td>
					<td><strong>97.31</strong></td>
					<td>2.16</td>
					<td>2.97</td>
					<td><strong>5.62</strong></td>
					<td><strong>7.1x</strong></td>
			</tr>
	</tbody>
</table>
<p>SPHNet achieves the best Hamiltonian MAE and efficiency, though WANet outperforms on orbital energy MAE and coefficient similarity. The higher speedup on PubChemQH (vs QH9) reflects greater computational redundancy in larger systems with higher-order basis sets ($L_{max} = 6$ for def2-TZVP vs $L_{max} = 4$ for def2-SVP).</p>
<h3 id="md17-small-molecule-trajectories">MD17 (Small Molecule Trajectories)</h3>
<p>SPHNet achieves accuracy comparable to QHNet and PhiSNet on four MD17 molecules (water, ethanol, malondialdehyde, uracil; 3-12 atoms). MD17 represents a simpler task where baseline models already perform well, leaving limited room for improvement. For water (3 atoms), the number of interaction combinations is inherently small, limiting the benefit of adaptive sparsification.</p>
<h3 id="scaling-limit">Scaling Limit</h3>
<p>SPHNet can train on systems with approximately 3000 atomic orbitals on a single A6000 GPU; the QHNet baseline runs out of memory at approximately 1800 orbitals. Memory consumption scales more favorably as molecule size increases.</p>
<h3 id="key-findings">Key Findings</h3>
<ul>
<li><strong>Adaptive sparsity scales with system complexity</strong>: The method is most effective for large systems where redundancy is high. For small molecules (e.g., water with only 3 atoms), every interaction is critical, so pruning hurts accuracy and yields negligible speedup.</li>
<li><strong>Long-range pair preservation</strong>: The Sparse Pair Gate selects long-range pairs (16-25 Angstrom) at higher rates than short-range ones. Short-range pairs are numerous and easier to learn, while rare long-range interactions are harder to represent and thus more critical to retain.</li>
<li><strong>Generalizable components</strong>: The sparsification techniques are portable modules, demonstrated by successful integration into QHNet with 3.3x speedup.</li>
<li><strong>Architecture ablation</strong>: Removing one Vectorial Node Interaction block or Spherical Node Interaction block significantly hurts accuracy, confirming the importance of the progressive order-increase design. Removing one Pair Construction block has less impact, suggesting room for further speedup.</li>
</ul>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="artifacts">Artifacts</h3>
<table>
	<thead>
			<tr>
					<th>Artifact</th>
					<th>Type</th>
					<th>License</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><a href="https://github.com/microsoft/SPHNet">SPHNet (GitHub)</a></td>
					<td>Code</td>
					<td>MIT</td>
					<td>Official implementation; archived by Microsoft (Dec 2025), read-only</td>
			</tr>
			<tr>
					<td><a href="https://huggingface.co/datasets/EperLuo/PubChemQH">PubChemQH (Hugging Face)</a></td>
					<td>Dataset</td>
					<td>MIT</td>
					<td>50k molecules, 40-100 atoms, def2-TZVP basis</td>
			</tr>
	</tbody>
</table>
<p>No pre-trained model weights are provided. MD17 and QH9 are publicly available community datasets. Training requires 4x NVIDIA A100 (80GB) GPUs; benchmarking uses a single NVIDIA RTX A6000 (46GB).</p>
<h3 id="data">Data</h3>
<p>The experiments evaluated SPHNet on three datasets with different molecular sizes and basis set complexities. All datasets use DFT calculations as ground truth, with MD17 using the PBE exchange-correlation functional and QH9/PubChemQH using B3LYP.</p>
<table>
	<thead>
			<tr>
					<th>Dataset</th>
					<th>Molecules</th>
					<th>Molecule Size</th>
					<th>Basis Set</th>
					<th>$L_{max}$</th>
					<th>Functional</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>MD17</td>
					<td>4 systems</td>
					<td>3-12 atoms (water, ethanol, malondialdehyde, uracil)</td>
					<td>def2-SVP</td>
					<td>4</td>
					<td>PBE</td>
			</tr>
			<tr>
					<td>QH9</td>
					<td>134k</td>
					<td>$\leq$ 20 atoms (Stable/Dynamic splits)</td>
					<td>def2-SVP</td>
					<td>4</td>
					<td>B3LYP</td>
			</tr>
			<tr>
					<td>PubChemQH</td>
					<td>50k</td>
					<td>40-100 atoms</td>
					<td>def2-TZVP</td>
					<td>6</td>
					<td>B3LYP</td>
			</tr>
	</tbody>
</table>
<p><strong>Data Availability</strong>:</p>
<ul>
<li><strong>MD17 &amp; QH9</strong>: Publicly available</li>
<li><strong>PubChemQH</strong>: Publicly available on Hugging Face (<a href="https://huggingface.co/datasets/EperLuo/PubChemQH">EperLuo/PubChemQH</a>)</li>
</ul>
<h3 id="algorithms">Algorithms</h3>
<p><strong>Loss Function</strong>:</p>
<p>The model learns the <strong>residual</strong> $\Delta H$:</p>
<p>$$
\begin{aligned}
\Delta H &amp;= H_{\text{ref}} - H_{\text{init}} \\
\mathcal{L} &amp;= \text{MAE}(H_{\text{ref}}, H_{\text{pred}}) + \text{MSE}(H_{\text{ref}}, H_{\text{pred}})
\end{aligned}
$$</p>
<p>where $H_{\text{init}}$ is a computationally inexpensive initial guess computed via PySCF.</p>
<p><strong>Hyperparameters</strong>:</p>
<table>
	<thead>
			<tr>
					<th>Parameter</th>
					<th>PubChemQH</th>
					<th>QH9</th>
					<th>MD17</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Batch Size</td>
					<td>8</td>
					<td>32</td>
					<td>10 (uracil: 5)</td>
			</tr>
			<tr>
					<td>Training Steps</td>
					<td>300k</td>
					<td>260k</td>
					<td>200k</td>
			</tr>
			<tr>
					<td>Warmup Steps</td>
					<td>1k</td>
					<td>1k</td>
					<td>1k</td>
			</tr>
			<tr>
					<td>Learning Rate</td>
					<td>1e-3</td>
					<td>1e-3</td>
					<td>5e-4</td>
			</tr>
			<tr>
					<td>Sparsity Rate</td>
					<td>0.7</td>
					<td>0.4</td>
					<td>0.1-0.3</td>
			</tr>
			<tr>
					<td>TSS Epoch $t$</td>
					<td>3</td>
					<td>3</td>
					<td>3</td>
			</tr>
	</tbody>
</table>
<p><strong>Sparse Pair Gate</strong>: Adapts the interaction graph. It concatenates zero-order features and inner products of atom pairs, then passes them through a linear layer $F_p$ with sigmoid activation to learn a weight $W_p^{ij}$ for every pair. Pairs are kept only if selected by the scheduler ($U_p^{TSS}$). The overhead comes primarily from the linear layer $F_p$.</p>
<p><strong>Sparse TP Gate</strong>: Filters triplets $(l_1, l_2, l_3)$ inside the TP operation. Higher-order combinations are more likely to be pruned. Complexity: $\mathcal{O}(L^3)$.</p>
<p><strong>Three-Phase Sparsity Scheduler</strong>: Training curriculum designed to optimize the sparse gates effectively:</p>
<ul>
<li><strong>Phase 1 (Random)</strong>: Random selection ($1-k$ probability) to ensure unbiased weight updates. Complexity: $\mathcal{O}(|U|)$.</li>
<li><strong>Phase 2 (Adaptive)</strong>: Selects top $(1-k)$ percent based on learned magnitude. Complexity: $\mathcal{O}(|U|\log|U|)$.</li>
<li><strong>Phase 3 (Fixed)</strong>: Freezes the connectivity mask for maximum inference speed. No overhead.</li>
</ul>
<p><strong>Weight Initialization</strong>: Learnable sparsity weights ($W$) initialized as all-ones vector.</p>
<h3 id="models">Models</h3>
<p>The model predicts the Hamiltonian matrix $H$ from atomic numbers $Z$ and coordinates $r$.</p>
<p><strong>Inputs</strong>: Atomic numbers ($Z$) and 3D coordinates.</p>
<p><strong>Backbone Structure</strong>:</p>
<ol>
<li><strong>Vectorial Node Interaction (x4)</strong>: Uses long-short range message passing. Extracts vectorial representations ($l=1$) without high-order TPs to save cost.</li>
<li><strong>Spherical Node Interaction (x2)</strong>: Projects features to high-order spherical harmonics (up to $L_{max}$). The first block increases the maximum order from 0 to $L_{max}$ without the Sparse Pair Gate; the second block applies the <strong>Sparse Pair Gate</strong> to filter node pairs.</li>
<li><strong>Pair Construction Block (x2)</strong>: Splits into <strong>Diagonal</strong> (self-interaction) and <strong>Non-Diagonal</strong> (cross-interaction) blocks. Both use the <strong>Sparse TP Gate</strong> to prune cross-order combinations $(l_1, l_2, l_3)$. The Non-Diagonal blocks also use the <strong>Sparse Pair Gate</strong> to filter atom pairs. The two Pair Construction blocks receive representations from the two Spherical Node Interaction blocks respectively, and their outputs are summed.</li>
<li><strong>Expansion Block</strong>: Reconstructs the full Hamiltonian matrix from the sparse irreducible representations, exploiting symmetry ($H_{ji} = H_{ij}^T$) to halve computations.</li>
</ol>
<h3 id="hardware">Hardware</h3>
<ul>
<li><strong>Training</strong>: 4x NVIDIA A100 (80GB)</li>
<li><strong>Benchmarking</strong>: Single NVIDIA RTX A6000 (46GB)</li>
</ul>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Luo, E., Wei, X., Huang, L., Li, Y., Yang, H., Xia, Z., Wang, Z., Liu, C., Shao, B., &amp; Zhang, J. (2025). Efficient and Scalable Density Functional Theory Hamiltonian Prediction through Adaptive Sparsity. <em>Proceedings of the 42nd International Conference on Machine Learning</em>, PMLR 267:41368&ndash;41390.</p>
<p><strong>Publication</strong>: ICML 2025</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@inproceedings</span>{luo2025efficient,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>=<span style="color:#e6db74">{Efficient and Scalable Density Functional Theory Hamiltonian Prediction through Adaptive Sparsity}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>=<span style="color:#e6db74">{Luo, Erpai and Wei, Xinran and Huang, Lin and Li, Yunyang and Yang, Han and Xia, Zaishuo and Wang, Zun and Liu, Chang and Shao, Bin and Zhang, Jia}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">booktitle</span>=<span style="color:#e6db74">{Proceedings of the 42nd International Conference on Machine Learning}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span>=<span style="color:#e6db74">{41368--41390}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span>=<span style="color:#e6db74">{2025}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">volume</span>=<span style="color:#e6db74">{267}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">series</span>=<span style="color:#e6db74">{Proceedings of Machine Learning Research}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">publisher</span>=<span style="color:#e6db74">{PMLR}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><strong>Additional Resources</strong>:</p>
<ul>
<li><a href="https://icml.cc/virtual/2025/poster/45656">ICML 2025 poster page</a></li>
<li><a href="https://openreview.net/forum?id=K3lykWhXON">OpenReview forum</a></li>
<li><a href="https://openreview.net/pdf?id=K3lykWhXON">PDF on OpenReview</a></li>
<li><a href="https://github.com/microsoft/SPHNet">GitHub Repository</a> <em>(Note: The official repository was archived by Microsoft in December 2025. It is available for reference but no longer actively maintained.)</em></li>
</ul>
]]></content:encoded></item><item><title>Umbrella Sampling: Monte Carlo Free-Energy Estimation</title><link>https://hunterheidenreich.com/notes/chemistry/molecular-simulation/classical-methods/umbrella-sampling/</link><pubDate>Thu, 21 Aug 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/chemistry/molecular-simulation/classical-methods/umbrella-sampling/</guid><description>Torrie and Valleau's 1977 paper introducing Umbrella Sampling, an importance sampling technique for Monte Carlo free-energy calculations.</description><content:encoded><![CDATA[<h2 id="a-methodological-shift-in-monte-carlo-simulations">A Methodological Shift in Monte Carlo Simulations</h2>
<p>This is a <strong>Method</strong> paper that introduces a novel computational technique for Monte Carlo simulations. It presents Umbrella Sampling, an importance sampling approach that uses non-physical distributions to calculate free energy differences in molecular systems.</p>
<h2 id="the-sampling-gap-in-phase-transitions">The Sampling Gap in Phase Transitions</h2>
<p>The paper addresses the failure of conventional Boltzmann-weighted Monte Carlo to estimate free energy differences.</p>
<ul>
<li><strong>The Problem</strong>: Free energy depends on the integral of configurations that are rare in the reference system. In a standard simulation, the relevant probability density $f_0(\Delta U^*)$ is too small to be sampled accurately by conventional Boltzmann-weighted Monte Carlo.</li>
<li><strong>Phase Transitions</strong>: Conventional &ldquo;thermodynamic integration&rdquo; fails near phase transitions because it requires a path of integration where ensemble averages can be reliably measured, which is difficult in unstable regions.</li>
</ul>
<h2 id="bridging-states-with-non-physical-distributions">Bridging States with Non-Physical Distributions</h2>
<p>The authors introduce a non-physical distribution $\pi(q^N)$ to bridge the gap between a reference system (0) and a system of interest (1).</p>
<ul>
<li><strong>Arbitrary Weights</strong>: They generate a Markov chain with a limiting distribution $\pi(q^N)$ that differs from the Boltzmann distribution of either system. This distribution is written as $\pi(q&rsquo;^N) = w(q&rsquo;^N) \exp(-U_0(q&rsquo;^N)/kT_0) / Z$, where $w(q^N) = W(\Delta U^*)$ is a weighting function chosen to favor configurations with values of $\Delta U^*$ important to the free-energy integral.</li>
<li><strong>Reweighting Formula</strong>: The unbiased average of any property $\theta$ is recovered via the ratio of biased averages:</li>
</ul>
<p>$$\langle\theta\rangle_{0}=\frac{\langle\theta/w\rangle_{w}}{\langle1/w\rangle_{w}}$$</p>
<ul>
<li><strong>Overlap</strong>: The method allows sampling a range of $\Delta U^*$ up to <strong>three times</strong> that of a conventional Monte Carlo experiment, enabling accurate determination of values of $f_0(\Delta U^*)$ as small as $10^{-8}$. If a single weight function cannot span the entire gap, additional overlapping umbrella-sampling experiments are carried out with different weighting functions exploring successively overlapping ranges of $\Delta U^*$.</li>
</ul>
<h2 id="validation-on-lennard-jones-fluids">Validation on Lennard-Jones Fluids</h2>
<p>The authors validated Umbrella Sampling using Monte Carlo simulations of model fluids.</p>
<h3 id="experimental-setup">Experimental Setup</h3>
<ul>
<li><strong>System Specifications</strong>: The study used a <strong>Lennard-Jones (LJ)</strong> fluid and an <strong>inverse-12 &ldquo;soft-sphere&rdquo;</strong> fluid.</li>
<li><strong>System Size</strong>: Simulations were primarily performed with <strong>$N=32$ particles</strong>, with some validation runs at <strong>$N=108$ particles</strong> to check for size dependence.</li>
<li><strong>State Points</strong>: Calculations covered a wide range of densities ($N\sigma^3/V = 0.50$ to $0.85$) and temperatures ($kT/\epsilon = 0.7$ to $2.8$), including the gas-liquid coexistence region.</li>
</ul>
<h3 id="baselines">Baselines</h3>
<ul>
<li><strong>Baselines</strong>: Results were compared to thermodynamic integration data from <strong>Hansen</strong>, <strong>Levesque</strong>, and <strong>Verlet</strong>.</li>
<li><strong>Quantitative Success</strong>:
<ul>
<li><strong>Agreement</strong>: The free energy estimates agreed with pressure integration results to within statistical uncertainties (e.g., at $kT/\epsilon=1.35$, Umbrella Sampling gave -3.236 vs. Conventional -3.25).</li>
<li><strong>Precision</strong>: Free energy differences were obtained with high precision ($\pm 0.005 NkT$ for $N=108$).</li>
<li><strong>Efficiency</strong>: A single umbrella run could replace the &ldquo;numerous runs&rdquo; required for conventional $1/T$ integrations.</li>
</ul>
</li>
</ul>
<h2 id="temperature-scaling-via-reweighting">Temperature Scaling via Reweighting</h2>
<p>When the reference system has the same internal energy function as the system of interest (i.e., the same fluid at a different temperature), the free-energy expression simplifies to:</p>
<p>$$\frac{A(T)}{kT} = \frac{A(T_0)}{kT_0} - \ln \int f_0(U) \exp\left[-U\left(\frac{1}{kT} - \frac{1}{kT_0}\right)\right] dU$$</p>
<p>This is especially useful because a single determination of $f_0(U)$ over a wide energy range gives the free energy over a whole range of temperatures simultaneously. For 32 Lennard-Jones particles, only two umbrella-sampling experiments are needed to span the temperature range from the triple point ($kT/\epsilon = 0.7$) to twice the critical temperature ($kT/\epsilon = 2.8$). For 108 particles, four experiments suffice.</p>
<h2 id="mapping-the-liquid-gas-free-energy-surface">Mapping the Liquid-Gas Free Energy Surface</h2>
<ul>
<li><strong>Methodological Utility</strong>: The method successfully mapped the free energy of the LJ fluid across the liquid-gas transition, a region where conventional methods face convergence problems.</li>
<li><strong>N-Dependence</strong>: Comparison between $N=32$ and $N=108$ showed no statistically significant size dependence for free energy differences, suggesting small systems are sufficient for these estimates.</li>
<li><strong>Comparison with Gosling-Singer Method</strong>: The paper contrasts its results with free energies derived from Gosling and Singer&rsquo;s entropy estimation technique, finding discrepancies as large as $0.4N\epsilon$ (a 20% error in the nonideal entropy), equivalent to overestimating the configurational integral of a 108-particle system by a factor of $10^{16}$.</li>
<li><strong>Generality</strong>: While demonstrated on energy ($U$), the authors note the weighting function $w$ can be any function of the coordinates, generalizing the technique beyond simple free energy differences.</li>
</ul>
<h2 id="reproducibility">Reproducibility</h2>
<p>This 1977 paper predates modern code-sharing practices, and no source code or data files are publicly available. However, the paper provides sufficient algorithmic detail for reimplementation:</p>
<ul>
<li><strong>Constructing $W$</strong>: The paper does not derive $W$ analytically. It uses a <strong>trial-and-error procedure</strong>: start with a short Boltzmann-weighted experiment, then broaden the distribution in stages through short test runs, adjusting weights to flatten the probability density $f_w(\Delta U^*)$. The paper acknowledges this requires &ldquo;interaction between the trial computer results and human judgment.&rdquo;</li>
<li><strong>Specific Weights</strong>: Table I provides the exact numerical weights used for the 32-particle soft-sphere experiment at $N\sigma^3/V = 0.85$, $kT/\epsilon = 2.74$, with values spanning from $W=1{,}500{,}000$ at the lowest energies down to $W=1.0$ at the center and back up to $W=16.0$ at the highest energies.</li>
<li><strong>Potentials</strong>: The Lennard-Jones and inverse-twelve potentials are fully specified (Eqs. 8 and 9).</li>
<li><strong>State Points</strong>: Densities and temperatures are enumerated in Tables II and III.</li>
<li><strong>Block Averaging</strong>: Errors were estimated by treating sequences of $m$ steps as independent samples, where $m$ is determined by increasing block size until no systematic trends can be detected in either the average or the standard deviation of the mean.</li>
</ul>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Torrie, G. M., &amp; Valleau, J. P. (1977). Nonphysical sampling distributions in Monte Carlo free-energy estimation: Umbrella sampling. <em>Journal of Computational Physics</em>, 23(2), 187-199. <a href="https://doi.org/10.1016/0021-9991(77)90121-8">https://doi.org/10.1016/0021-9991(77)90121-8</a></p>
<p><strong>Publication</strong>: Journal of Computational Physics, 1977</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@article</span>{torrie1977nonphysical,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>=<span style="color:#e6db74">{Nonphysical sampling distributions in Monte Carlo free-energy estimation: Umbrella sampling}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>=<span style="color:#e6db74">{Torrie, Glenn M and Valleau, John P}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">journal</span>=<span style="color:#e6db74">{Journal of Computational Physics}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">volume</span>=<span style="color:#e6db74">{23}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">number</span>=<span style="color:#e6db74">{2}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span>=<span style="color:#e6db74">{187--199}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span>=<span style="color:#e6db74">{1977}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">publisher</span>=<span style="color:#e6db74">{Elsevier}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">doi</span>=<span style="color:#e6db74">{10.1016/0021-9991(77)90121-8}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>Vectorized Word2Vec in Pure PyTorch</title><link>https://hunterheidenreich.com/projects/modern-word2vec/</link><pubDate>Sat, 16 Aug 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/projects/modern-word2vec/</guid><description>A from-scratch PyTorch Word2Vec implementation with vectorized Hierarchical Softmax, Negative Sampling, and torch.compile support.</description><content:encoded><![CDATA[<h2 id="overview">Overview</h2>
<p>Word2Vec is often treated as a &ldquo;solved problem&rdquo; or a black box inside libraries like Gensim. This project deconstructs the algorithm to treat it as a <strong>systems engineering challenge</strong>.</p>
<p>I built a ground-up, typed, and compiled PyTorch implementation that bridges the gap between the original C code&rsquo;s efficiency and modern GPU acceleration. The core innovation lies in <strong>&ldquo;tensorizing the tree&rdquo;</strong>, converting the pointer-chasing logic of Hierarchical Softmax into dense, vectorized operations compatible with <code>torch.compile</code>.</p>
<h2 id="features">Features</h2>
<h3 id="1-vectorized-hierarchical-softmax">1. Vectorized Hierarchical Softmax</h3>
<p>Classically, Hierarchical Softmax involves traversing a binary Huffman tree. While efficient on a CPU, this approach creates divergent execution paths on GPUs.</p>
<ul>
<li><strong>The Solution:</strong> I implemented a &ldquo;pre-computed path&rdquo; strategy. The tree traversal for every vocabulary word is flattened into fixed-size tensors (<code>word_path_indices</code>, <code>word_codes_tensor</code>) padded to the maximum depth.</li>
<li><strong>The Result:</strong> The forward pass becomes a massive, masked batch dot-product against internal node embeddings, allowing the GPU to crunch the probability tree without branching logic.</li>
</ul>
<h3 id="2-infinite-streaming--sliding-windows">2. Infinite Streaming &amp; Sliding Windows</h3>
<p>To handle datasets larger than RAM (e.g., Wikipedia/CommonCrawl), I built a custom <code>IterableDataset</code> that performs a true single-pass read.</p>
<ul>
<li><strong>Efficient Windowing:</strong> It uses a <code>collections.deque</code> buffer to slide over the token stream, generating training pairs only when a new token enters the center context.</li>
<li><strong>Zipfian Subsampling:</strong> Implemented a probabilistic rejection sampling layer that downsamples frequent words (like &ldquo;the&rdquo; or &ldquo;of&rdquo;) on-the-fly, strictly adhering to the original Mikolov et al. paper&rsquo;s distribution.</li>
</ul>
<h3 id="3-modern-tooling">3. Modern Tooling</h3>
<p>This project uses a strict &ldquo;software 2.0&rdquo; stack:</p>
<ul>
<li><strong>Dependency Management</strong>: Built with <code>uv</code> for deterministic, fast environment resolution.</li>
<li><strong>Compilation</strong>: Fully compatible with <code>torch.compile</code> (PyTorch 2.0+), allowing for graph fusion of the custom loss functions.</li>
</ul>
<h2 id="usage">Usage</h2>
<p>The library installs from source (clone the repo, then <code>pip install -e .</code>) and exposes a typed Python API (<code>SkipGramModel</code>, <code>CBOWModel</code>, <code>Trainer</code>, <code>Word2VecDataset</code>) alongside <code>word2vec-train</code> and <code>word2vec-query</code> CLIs, with GPU acceleration. Trained embeddings export to <code>.npy</code> for use with Gensim or other tooling.</p>
<h2 id="results">Results</h2>
<ul>
<li><strong>Correct embeddings</strong>: the produced vectors pass qualitative semantic-similarity checks (e.g., analogical reasoning), confirming the tensorized tree produces the same geometry as sequential traversal.</li>
<li><strong>Branch-free GPU execution</strong>: the batched Huffman-tree path turns hierarchical-softmax tree traversal into dense, masked tensor operations, removing the divergent branching that slows naive implementations on GPUs.</li>
<li><strong>Runs on larger-than-RAM corpora</strong>: the streaming <code>IterableDataset</code> with Zipfian subsampling processes Wikipedia/CommonCrawl-scale text in a single pass without loading the corpus into memory.</li>
<li><strong><code>torch.compile</code>-compatible</strong>: the custom loss functions are written to fuse under <code>torch.compile</code> (PyTorch 2.0+).</li>
</ul>
<h2 id="related-work">Related Work</h2>
<p>This project connects to related NLP work on this site:</p>
<ul>
<li><a href="/posts/intro-to-word-embeddings/">An Introduction to Word Embeddings</a>: conceptual background on the representations this library produces</li>
<li><a href="/research/word-company-vicinity/">Word Company Vicinity</a>: research applying word vector semantics to company names</li>
<li><a href="/research/semantic-network-induction/">Semantic Network Induction</a>: research on inducing semantic graphs from embedding spaces</li>
</ul>
]]></content:encoded></item><item><title>3D Steerable CNNs: Rotationally Equivariant Features</title><link>https://hunterheidenreich.com/notes/machine-learning/geometric-deep-learning/3d-steerable-cnns/</link><pubDate>Thu, 16 Jan 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/machine-learning/geometric-deep-learning/3d-steerable-cnns/</guid><description>Weiler et al.'s NeurIPS 2018 paper introducing SE(3)-equivariant CNNs for volumetric data using group theory and spherical harmonics.</description><content:encoded><![CDATA[<h2 id="what-kind-of-paper-is-this">What kind of paper is this?</h2>
<p>This is a <strong>method paper</strong> that introduces a novel neural network architecture, the 3D Steerable CNN. It provides a comprehensive theoretical derivation for the architecture grounded in group representation theory and demonstrates its practical application.</p>
<h2 id="what-is-the-motivation">What is the motivation?</h2>
<p>The work is motivated by the prevalence of <strong>symmetry</strong> in problems from the natural sciences. Standard 3D CNNs lack inherent equivariance to 3D rotations, a fundamental symmetry governed by the SE(3) group in many scientific datasets like molecular or protein structures. Building this symmetry directly into the model architecture as an <strong>inductive bias</strong> is expected to yield more data-efficient, generalizable, and physically meaningful models.</p>















<figure class="post-figure center ">
    <img src="/img/notes/3d-cnn-versus-3d-steerable-cnn.webp"
         alt="Comparison of standard 3D CNN versus 3D Steerable CNN for handling rotational symmetry. Panel A shows how standard CNNs produce distorted outputs when inputs are rotated, requiring data augmentation. Panel B shows how Steerable CNNs use spherical harmonic kernel bases to produce equivariant geometric field outputs that transform predictably under rotation."
         title="Comparison of standard 3D CNN versus 3D Steerable CNN for handling rotational symmetry. Panel A shows how standard CNNs produce distorted outputs when inputs are rotated, requiring data augmentation. Panel B shows how Steerable CNNs use spherical harmonic kernel bases to produce equivariant geometric field outputs that transform predictably under rotation."
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">Standard 3D CNNs (Panel A) produce inconsistent feature maps when inputs are rotated, requiring expensive data augmentation. 3D Steerable CNNs (Panel B) use analytically-derived spherical harmonic kernels to produce geometric field outputs that transform equivariantly under rotation.</figcaption>
    
</figure>

<h2 id="what-is-the-novelty-here">What is the novelty here?</h2>
<p>The core novelty is the rigorous and practical construction of a CNN architecture that is equivariant to 3D rigid body motions (SE(3) group). The key contributions are:</p>
<ul>
<li><strong>Geometric Feature Representation</strong>: Features are modeled as geometric <strong>fields</strong> (collections of scalars, vectors, and higher-order tensors) defined over $\mathbb{R}^{3}$. Each type of feature transforms according to an <strong>irreducible representation (irrep)</strong> of the rotation group SO(3).</li>
<li><strong>General Equivariant Convolution</strong>: The paper proves that the most general form of an SE(3)-equivariant linear map between these fields is a convolution with a <strong>rotation-steerable kernel</strong>.</li>
<li><strong>Analytical Kernel Basis</strong>: The main theoretical breakthrough is the analytical derivation of a complete basis for these steerable kernels. They solve the kernel&rsquo;s equivariance constraint, $\kappa(rx) = D^{j}(r)\kappa(x)D^{l}(r)^{-1}$, showing the solutions are functions whose angular components are <strong>spherical harmonics</strong>. The network&rsquo;s kernels are then parameterized as a learnable linear combination of these pre-computed basis functions, making the implementation a minor modification to standard 3D convolutions.</li>
</ul>















<figure class="post-figure center ">
    <img src="/img/notes/spherical-harmonics.webp"
         alt="Spherical harmonics visualization showing the angular basis functions organized by degree l (rows) and order m (columns). Row 0 shows the single s-type orbital (l=0), row 1 shows three p-type orbitals (l=1), row 2 shows five d-type orbitals (l=2), and row 3 shows seven f-type orbitals (l=3)."
         title="Spherical harmonics visualization showing the angular basis functions organized by degree l (rows) and order m (columns). Row 0 shows the single s-type orbital (l=0), row 1 shows three p-type orbitals (l=1), row 2 shows five d-type orbitals (l=2), and row 3 shows seven f-type orbitals (l=3)."
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">Spherical harmonics $Y_l^m$ organized by degree $l$ (rows) and order $m$ (columns). These functions form the angular basis for steerable kernels: $l=0$ (scalar), $l=1$ (vector/p-orbital), $l=2$ (rank-2 tensor/d-orbital), $l=3$ (rank-3 tensor/f-orbital). Each degree $l$ has $2l+1$ components.</figcaption>
    
</figure>

<ul>
<li><strong>Equivariant Nonlinearity</strong>: A novel <strong>gated nonlinearity</strong> is proposed for non-scalar features. It preserves equivariance by multiplying a feature field by a separately computed, learned scalar field (the gate).</li>
</ul>
<h2 id="what-experiments-were-performed">What experiments were performed?</h2>
<p>The model&rsquo;s performance was evaluated on a series of tasks with inherent rotational symmetry:</p>
<ol>
<li><strong>Tetris Classification</strong>: A toy problem to empirically validate the model&rsquo;s rotational equivariance by training on aligned blocks and testing on randomly rotated ones.</li>
<li><strong>SHREC17 3D Model Classification</strong>: A benchmark for classifying complex 3D shapes that are arbitrarily rotated.</li>
<li><strong>Amino Acid Propensity Prediction</strong>: A scientific application to predict amino acid types from their 3D atomic environments.</li>
<li><strong>CATH Protein Structure Classification</strong>: A challenging task on a new dataset introduced by the authors, requiring classification of global protein architecture, a problem with full SE(3) invariance.</li>
</ol>
<h2 id="what-outcomesconclusions">What outcomes/conclusions?</h2>
<p>The 3D Steerable CNN demonstrated clear advantages due to its built-in equivariance:</p>
<ul>
<li>It was empirically confirmed to be <strong>rotationally equivariant</strong>, achieving $99 \pm 2%$ test accuracy on the rotated Tetris dataset (averaged over 17 runs), compared to a standard 3D CNN&rsquo;s $27 \pm 7%$ accuracy.</li>
<li>On the amino acid prediction task the model achieves 0.58 accuracy, compared to 0.50 (regular-grid) and 0.56 (concentric-grid) baselines, using roughly half the parameters. On SHREC17 it reaches a total score (micro + macro mAP) of 1.11, compared to 1.13 for the leading contemporary system.</li>
<li>On the CATH protein classification task, it <strong>outperformed a deep 3D CNN baseline</strong> while using ~110x fewer parameters. This performance gap widened as the training data was reduced, highlighting the model&rsquo;s superior <strong>data efficiency</strong>.</li>
</ul>
<p>The paper concludes that 3D Steerable CNNs provide a universal and effective framework for incorporating SE(3) symmetry into deep learning models, leading to improved accuracy and efficiency for tasks involving volumetric data, particularly in scientific domains.</p>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="data">Data</h3>
<ul>
<li><strong>Input Format</strong>: All inputs must be voxelized. Point clouds require voxelization before use.
<ul>
<li><strong>Proteins (CATH)</strong>: $50^3$ grid, 0.2 nm voxel size. Simplified to $C_\alpha$ atoms only; Gaussian density placed at each atom position.</li>
<li><strong>3D Objects (SHREC17)</strong>: $64^3$ voxel grids.</li>
<li><strong>Tetris</strong>: $36^3$ input grid.</li>
</ul>
</li>
<li><strong>Splitting Strategy</strong>: CATH used a 10-fold split (7 train, 1 val, 2 test) strictly separated by &ldquo;superfamily&rdquo; level to prevent data leakage (&lt;40% sequence identity).</li>
</ul>
<h3 id="models">Models</h3>
<p><strong>Kernel Basis Construction</strong>:</p>
<ul>
<li>Constructed from <strong>Spherical Harmonics</strong> multiplied by <strong>Gaussian Radial Shells</strong>: $\exp\left(-\frac{1}{2}(|x|-m)^{2}/\sigma^{2}\right)$</li>
<li><strong>Anti-aliasing</strong>: A radially dependent angular frequency cutoff ($J_{\max}$) is applied to prevent aliasing near the origin.</li>
</ul>
<p><strong>Normalization</strong>: Uses <strong>Equivariant Batch Norm</strong>. Non-scalar fields are normalized by the average of their norms.</p>
<p><strong>Downsampling</strong>: Standard strided convolution breaks equivariance. The architecture uses <strong>low-pass filtering</strong> (Gaussian blur) before downsampling to maintain equivariance.</p>
<p><strong>Exact Architecture Configurations</strong>:</p>
<p><strong>Tetris Architecture</strong> (4 layers):</p>
<table>
	<thead>
			<tr>
					<th>Layer</th>
					<th>Field Types</th>
					<th>Spatial Size</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Input</td>
					<td>1 scalar</td>
					<td>$36^3$</td>
			</tr>
			<tr>
					<td>Layer 1</td>
					<td>4 scalars, 4 vectors ($l=1$), 4 tensors ($l=2$), 1 tensor ($l=3$)</td>
					<td>$40^3$</td>
			</tr>
			<tr>
					<td>Layer 2</td>
					<td>16 scalars, 16 vectors, 16 tensors ($l=2$)</td>
					<td>$22^3$ (stride 2)</td>
			</tr>
			<tr>
					<td>Layer 3</td>
					<td>32 scalars, 16 vectors, 16 tensors ($l=2$)</td>
					<td>$13^3$ (stride 2)</td>
			</tr>
			<tr>
					<td>Layer 4</td>
					<td>128 scalars</td>
					<td>$17^3$</td>
			</tr>
			<tr>
					<td>Output</td>
					<td>8 scalars (global average pool)</td>
					<td>$1$</td>
			</tr>
	</tbody>
</table>
<p><strong>SHREC17 Architecture</strong> (8 layers):</p>
<table>
	<thead>
			<tr>
					<th>Layers</th>
					<th>Field Types</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>1-2</td>
					<td>8 scalars, 4 vectors, 2 tensors ($l=2$)</td>
			</tr>
			<tr>
					<td>3-4</td>
					<td>16 scalars, 8 vectors, 4 tensors</td>
			</tr>
			<tr>
					<td>5-7</td>
					<td>32 scalars, 16 vectors, 8 tensors</td>
			</tr>
			<tr>
					<td>8</td>
					<td>512 scalars</td>
			</tr>
			<tr>
					<td>Output</td>
					<td>55 scalars (classes)</td>
			</tr>
	</tbody>
</table>
<p><strong>CATH Architecture</strong> (ResNet34-inspired):</p>
<p>Block progression: <code>(2,2,2,2)</code>, <code>(4,4,4,4)</code>, <code>(8,8,8,8)</code>, <code>(16,16,16,16)</code></p>
<p>Notation: <code>(a,b,c,d)</code> = $a$ scalars ($l=0$), $b$ vectors ($l=1$), $c$ rank-2 tensors ($l=2$), $d$ rank-3 tensors ($l=3$).</p>
<h3 id="algorithms">Algorithms</h3>
<p><strong>Parameter Counts</strong>:</p>
<table>
	<thead>
			<tr>
					<th>Task</th>
					<th>Model</th>
					<th>Parameters</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>CATH</td>
					<td>3D Steerable CNN</td>
					<td>143,560</td>
			</tr>
			<tr>
					<td>CATH</td>
					<td>Baseline (ResNet34-style)</td>
					<td>15,878,764</td>
			</tr>
			<tr>
					<td>Amino Acid</td>
					<td>3D Steerable CNN</td>
					<td>~32,600,000</td>
			</tr>
			<tr>
					<td>Amino Acid</td>
					<td>Regular grid baseline</td>
					<td>~61,100,000</td>
			</tr>
			<tr>
					<td>Amino Acid</td>
					<td>Concentric grid baseline</td>
					<td>~75,300,000</td>
			</tr>
	</tbody>
</table>
<p>Note: The concentric grid baseline groups voxels by distance from the molecular center, reflecting that atomic interactions are primarily distance-dependent (Torng, W., &amp; Altman, R. B. (2017). 3D deep convolutional neural networks for amino acid environment similarity analysis. <em>BMC Bioinformatics</em>, 18, 302). Amino acid parameter counts are rounded figures as reported in the paper.</p>
<p><strong>Hyperparameters &amp; Training</strong>:</p>
<table>
	<thead>
			<tr>
					<th>Parameter</th>
					<th>Value</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><strong>Optimizer</strong></td>
					<td>Adam</td>
			</tr>
			<tr>
					<td><strong>LR Scheduler</strong></td>
					<td>Exponential decay (0.94/epoch) after 40 epoch burn-in</td>
			</tr>
			<tr>
					<td><strong>Dropout</strong> (CATH)</td>
					<td>0.1 (Capsule-wide convolutional dropout)</td>
			</tr>
			<tr>
					<td><strong>Weight Decay</strong> (CATH)</td>
					<td>L1 &amp; L2 regularization: $10^{-8.5}$</td>
			</tr>
	</tbody>
</table>
<p><strong>Mathematical Formulations for Equivariance</strong>:</p>
<p>Standard operations like Batch Normalization and ReLU break rotational equivariance. The paper derives equivariant alternatives:</p>
<p><strong>Equivariant Batch Normalization</strong>:</p>
<p>Standard BN subtracts a mean, which introduces a preferred direction and breaks symmetry. <strong>Norm-based normalization</strong> scales feature fields by the average of their squared norms to preserve symmetry:</p>
<p>$$f_{i}(x) \mapsto f_{i}(x) \left( \frac{1}{|B|} \sum_{j \in B} \frac{1}{V} \int dx |f_{j}(x)|^{2} + \epsilon \right)^{-1/2}$$</p>
<p>This scales vector lengths to unit variance on average while avoiding mean subtraction, preserving directional information and symmetry.</p>
<p><strong>Equivariant Nonlinearities</strong>:</p>
<p>Applying ReLU to vector components independently breaks equivariance (this depends on the coordinate frame). Two approaches:</p>
<ol>
<li>
<p><strong>Norm Nonlinearity</strong> (geometric shrinking): Acts on magnitude, preserves direction. Shrinks vectors shorter than learned bias $\beta$ to zero:
$$f(x) \mapsto \text{ReLU}(|f(x)| - \beta) \frac{f(x)}{|f(x)|}$$
<em>Note: Found to converge slowly; omitted from final models.</em></p>
</li>
<li>
<p><strong>Gated Nonlinearity</strong> (used in practice): A separate scalar field $s(x)$ passes through sigmoid to create a gate $\sigma(s(x))$, which multiplies the geometric field:
$$f_{\text{out}}(x) = f_{\text{in}}(x) \cdot \sigma(s(x))$$
<em>Architecture implication: Requires extra scalar channels ($l=0$) specifically for gating higher-order channels ($l&gt;0$).</em></p>
</li>
</ol>
<p><strong>Voxelization Details</strong>:</p>
<p>For CATH protein inputs, Gaussian density is placed at each atom position with standard deviation equal to <strong>half the voxel width</strong> ($0.5 \times 0.2\text{ nm} = 0.1\text{ nm}$).</p>
<h3 id="evaluation">Evaluation</h3>
<table>
	<thead>
			<tr>
					<th>Task</th>
					<th>Metric</th>
					<th>Steerable CNN</th>
					<th>Baseline</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Tetris (rotated test)</td>
					<td>Accuracy</td>
					<td>$99 \pm 2%$</td>
					<td>$27 \pm 7%$ (standard 3D CNN)</td>
			</tr>
			<tr>
					<td>Amino Acid Propensity</td>
					<td>Accuracy</td>
					<td><strong>0.58</strong> (32.6M params)</td>
					<td>0.50 (regular grid, 61.1M params); 0.56 (concentric grid, 75.3M params)</td>
			</tr>
			<tr>
					<td>SHREC17</td>
					<td>micro + macro mAP (higher is better)</td>
					<td>1.11</td>
					<td>1.13 (SOTA)</td>
			</tr>
			<tr>
					<td>CATH</td>
					<td>Accuracy</td>
					<td>Higher across all training set sizes (see Figure 4; not reported as a single value) (143,560 params)</td>
					<td>Deep 3D CNN (15,878,764 params; ~110x more)</td>
			</tr>
	</tbody>
</table>
<p>Note: On SHREC17, the total score is micro mAP + macro mAP combined (higher is better). From Table 4 in the supplementary material: Steerable CNN micro mAP = 0.661, macro mAP = 0.449, total = 1.11. On CATH, the steerable CNN outperformed the baseline with ~110x fewer parameters, a gap that widened as training data was reduced.</p>
<h2 id="historical-context-from-peer-reviews">Historical Context (From Peer Reviews)</h2>
<p>The NeurIPS peer reviews reveal important context about the paper&rsquo;s structure and claims:</p>
<ul>
<li>
<p><strong>Evolution of Experiments</strong>: The <strong>SHREC17</strong> experiment and the <strong>arbitrary rotation</strong> test in Tetris were added during the rebuttal phase to address reviewer concerns about the lack of standard computer vision benchmarks. This explains why SHREC17 feels somewhat disconnected from the paper&rsquo;s &ldquo;AI for Science&rdquo; narrative.</p>
</li>
<li>
<p><strong>Continuous vs. Discrete Rotations</strong>: The Tetris experiment validates equivariance to <strong>continuous</strong> ($SO(3)$) rotations alongside discrete 90-degree turns. This distinction is crucial and separates Steerable CNNs from earlier Group CNNs that handled discrete rotation groups exclusively.</p>
</li>
<li>
<p><strong>Terminology Warning</strong>: The use of terms like &ldquo;fiber&rdquo; and &ldquo;induced representation&rdquo; was critiqued by reviewers as being denser than necessary and inconsistent with related work (e.g., Tensor Field Networks). If you find Section 3 difficult, this is a known barrier of this paper. Focus on the resulting kernel constraints.</p>
</li>
<li>
<p><strong>Parameter Efficiency Quantified</strong>: Reviewers highlighted that the main practical win is <strong>parameter efficiency</strong>. Standard 3D CNNs hit diminishing returns around $10^7$ parameters, while Steerable CNNs achieve better results with ~110x fewer parameters ($10^5$).</p>
</li>
</ul>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
			<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube-nocookie.com/embed/ENLJACPHSEA?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
		</div>

<h2 id="artifacts">Artifacts</h2>
<table>
	<thead>
			<tr>
					<th>Artifact</th>
					<th>Type</th>
					<th>License</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><a href="https://github.com/mariogeiger/se3cnn">se3cnn (GitHub)</a></td>
					<td>Code</td>
					<td>MIT</td>
					<td>Original implementation; superseded by <a href="https://github.com/e3nn/e3nn">e3nn</a> for point cloud applications</td>
			</tr>
			<tr>
					<td><a href="https://github.com/wouterboomsma/cath_datasets">CATH Datasets (GitHub)</a></td>
					<td>Dataset</td>
					<td>CC-BY-4.0</td>
					<td>Protein structure classification dataset introduced in this paper</td>
			</tr>
	</tbody>
</table>
<p>Pre-trained model weights are not publicly released. Hardware and compute requirements are not specified in the paper.</p>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Weiler, M., Geiger, M., Welling, M., Boomsma, W., &amp; Cohen, T. S. (2018). 3D steerable CNNs: Learning rotationally equivariant features in volumetric data. <em>Advances in Neural Information Processing Systems</em>, 31. <a href="https://proceedings.neurips.cc/paper/2018/hash/488e4104520c6aab692863cc1dba45af-Abstract.html">https://proceedings.neurips.cc/paper/2018/hash/488e4104520c6aab692863cc1dba45af-Abstract.html</a></p>
<p><strong>Publication</strong>: NeurIPS 2018</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@inproceedings</span>{weiler20183d,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>=<span style="color:#e6db74">{3D Steerable CNNs: Learning Rotationally Equivariant Features in Volumetric Data}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>=<span style="color:#e6db74">{Weiler, Maurice and Geiger, Mario and Welling, Max and Boomsma, Wouter and Cohen, Taco S}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">booktitle</span>=<span style="color:#e6db74">{Advances in Neural Information Processing Systems}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">volume</span>=<span style="color:#e6db74">{31}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span>=<span style="color:#e6db74">{2018}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><strong>Additional Resources</strong>:</p>
<ul>
<li><a href="https://github.com/mariogeiger/se3cnn">GitHub Repository</a></li>
<li><a href="https://www.youtube.com/watch?v=ENLJACPHSEA">YouTube Video</a></li>
<li><a href="https://github.com/wouterboomsma/cath_datasets">CATH Dataset</a></li>
</ul>
]]></content:encoded></item><item><title>Kabsch Algorithm: NumPy, PyTorch, TensorFlow, and JAX</title><link>https://hunterheidenreich.com/posts/kabsch-algorithm/</link><pubDate>Tue, 03 Oct 2023 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/posts/kabsch-algorithm/</guid><description>Learn about the Kabsch algorithm for optimal point alignment with implementations in NumPy, PyTorch, TensorFlow, and JAX for ML applications.</description><content:encoded><![CDATA[<h2 id="what-is-the-kabsch-algorithm">What is the Kabsch Algorithm?</h2>
<p>In computer vision or scientific computing, a common problem frequently arises: given two sets of points, what is the optimal rigid body transformation for their alignment? The Kabsch algorithm provides a nice solution.</p>















<figure class="post-figure center ">
    <img src="/img/scientific-computing/kabsch-alignment-before-and-after.webp"
         alt="Visualization of two point sets before and after Kabsch alignment"
         title="Visualization of two point sets before and after Kabsch alignment"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">The Kabsch algorithm optimally rotates and translates the blue points to align with the red points.</figcaption>
    
</figure>

<p>What are some concrete situations where this crops up?</p>
<ul>
<li><strong>Molecular Dynamics</strong>: Your points are a set of atoms (with physically relevant types), and you want to compare two molecular conformations. Are they the same structure with minor noise or rotation? Or are they different conformations, like a different folding of a protein? This is especially helpful when applying generative models to chemical structures. For example, if you are building a <a href="/notes/chemistry/molecular-simulation/ml-potentials/denoise-vae/">3D Molecular VAE</a> in PyTorch or working with <a href="/notes/machine-learning/generative-models/flow-matching-for-generative-modeling/">Flow Matching models</a>, Kabsch alignment ensures your generative loss function remains rotationally invariant.</li>
<li><strong>Computer Vision</strong>: You have two point clouds from 3D scans of an object taken from different angles. You want to align them to reconstruct the full shape. Or perhaps you&rsquo;re generating 3D shapes from 2D images and need to compare the generated shape to a ground truth scan. Anytime a 3D system is represented as a point cloud, the Kabsch algorithm can help with alignment.</li>
</ul>
<p>Of course, existing libraries implement this algorithm. However, often I find it beneficial to implement algorithms from scratch to build intuition. Furthermore, modern machine learning applications require automatic differentiation, so we will implement the algorithm in PyTorch, TensorFlow, and JAX.</p>
<p>Below, we&rsquo;ll cover the math behind the Kabsch algorithm (and its scaling variant, the <strong>Kabsch-Umeyama</strong> algorithm) and provide complete, differentiable implementations in <strong>NumPy</strong>, <strong>PyTorch</strong>, <strong>TensorFlow</strong>, and <strong>JAX</strong>, demonstrating both single-pair and batched computations for ML applications.</p>
<h2 id="the-math">The Math</h2>















<figure class="post-figure center ">
    <img src="/img/scientific-computing/kabsch-algorithm-basic-animation.webp"
         alt="Animation showing the iterative steps of centroid alignment and rotation"
         title="Animation showing the iterative steps of centroid alignment and rotation"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">Visualizing the alignment process: first centering the datasets, then finding the optimal rotation.</figcaption>
    
</figure>

<p>Let&rsquo;s say we have two sets of paired points,
$P={\mathbf{p}_i} \in \mathbb{R}^{N \times D}$ and $Q={\mathbf{q}_i} \in \mathbb{R}^{N \times D}$, for $i = 1, \dots, N$
(where $D$ is the dimensionality and $N$ is the number of points).
We want to find a translation vector $\mathbf{t}$ and rotation matrix $R$ to transform $P$ to align with $Q$.</p>
<p>The optimization problem is:</p>
<p>$$
\min_{\mathbf{t}, \ R} \mathcal{L}(\mathbf{t}, R) = \frac{1}{2} \sum_{i=1}^N | \mathbf{q}_i - (R\mathbf{p}_i + \mathbf{t}) |^2
$$</p>
<p>where $\mathbf{t}^\ast \in \mathbb{R}^D$ and $R^\ast \in \mathbb{R}^{D \times D}$ are the optimal translation and rotation.</p>
<p>Often we use a weighted version with weights $w_i$ (e.g., atomic masses in molecular dynamics):</p>
<p>$$
\min_{\mathbf{t}, \ R} \mathcal{L}(\mathbf{t}, R) = \frac{1}{2} \sum_{i=1}^N w_i | \mathbf{q}_i - (R\mathbf{p}_i + \mathbf{t}) |^2
$$</p>
<h3 id="the-translation">The Translation</h3>
<p>The translation and rotation are coupled, but they separate cleanly once we work in centroid-centered coordinates. Compute the centroids (averages) of both point sets:</p>
<p>$$
\bar{\mathbf{p}} = \frac{1}{N} \sum_{i=1}^N \mathbf{p}_i \quad \text{and} \quad \bar{\mathbf{q}} = \frac{1}{N} \sum_{i=1}^N \mathbf{q}_i
$$</p>
<p>For any fixed rotation $R$, the translation that minimizes $\mathcal{L}$ is found by setting $\partial \mathcal{L} / \partial \mathbf{t} = 0$. It maps the rotated source centroid onto the target centroid:</p>
<p>$$
\mathbf{t} = \bar{\mathbf{q}} - R\bar{\mathbf{p}}
$$</p>
<p>A tempting shortcut is to write $\mathbf{t} = \bar{\mathbf{q}} - \bar{\mathbf{p}}$, but that is only correct when $R = I$. In general the translation depends on the rotation, so we compute it <em>after</em> solving for $R$. Substituting this optimal $\mathbf{t}$ back into the objective cancels the centroids and leaves a rotation-only problem in the centered coordinates $\mathbf{p}_i^\prime = \mathbf{p}_i - \bar{\mathbf{p}}$ and $\mathbf{q}_i^\prime = \mathbf{q}_i - \bar{\mathbf{q}}$:</p>
<p>$$
\mathcal{L}(R) = \frac{1}{2} \sum_{i=1}^N | \mathbf{q}_i^\prime - R\mathbf{p}_i^\prime |^2
$$</p>
<p>which is what the next section solves.</p>
<h3 id="the-rotation-matrix">The Rotation Matrix</h3>
<p>We now minimize $\mathcal{L}(R)$ over rotations, using the centered points $\mathbf{p}_i^\prime$ and $\mathbf{q}_i^\prime$ from above. Compute the cross-covariance matrix between the centered sets:</p>
<p>$$
C = P^{\prime T} Q^\prime = \sum_{i=1}^N \mathbf{p}_i^{\prime T} \mathbf{q}_i^{\prime} \in \mathbb{R}^{D \times D}
$$</p>
<p>This is a fairly lightweight operation since $D$ is typically small (e.g., 3 for 3D points), even if $N$ is large.</p>
<p>With $C$ in hand, we want to compute its Singular Value Decomposition (SVD):</p>
<p>$$
C = U \Sigma V^T
$$</p>
<p>This operation is computationally expensive. It scales cubically with $D$ (i.e., $O(D^3)$).
However, since we&rsquo;re often interested in cases where $D$ is small (e.g., 2D or 3D points), this is manageable.</p>
<p>Next, we check for improper rotations (i.e., reflections) and correct for them where necessary:</p>
<p>$$
d = \text{sign}(\det(V U^T))
$$</p>
<p>If $d = -1$, we need to flip the last column of $V$ in the final rotation matrix.</p>
<p>Let $B = \text{diag}(1, 1, d)$.
The optimal rotation matrix comes out:</p>
<p>$$
R^\ast = V B U^T
$$</p>
<h3 id="summary">Summary</h3>
<p>In a nutshell, the Kabsch algorithm boils down to:</p>
<ol>
<li>Compute centroids of $P$ and $Q$ ($\bar{\mathbf{p}}$ and $\bar{\mathbf{q}}$)</li>
<li>Center both point sets by subtracting centroids: $P^\prime$ and $Q^\prime$</li>
<li>Compute cross-covariance matrix $C = P^{\prime T} Q^\prime$</li>
<li>Compute SVD: $C = U \Sigma V^T$ (<em>expensive step</em>)</li>
<li>Compute $d = \text{sign}(\det(V U^T))$ and $B = \text{diag}(1, 1, d)$</li>
<li>Optimal rotation: $R^\ast = V B U^T$</li>
<li>Optimal translation (using the rotation from step 6): $\mathbf{t}^\ast = \bar{\mathbf{q}} - R^\ast\bar{\mathbf{p}}$</li>
</ol>
<p>The resulting root-mean-square deviation (RMSD) between aligned point sets is</p>
<p>$$
\text{RMSD} = \sqrt{\frac{1}{N} \sum_{i=1}^N | \mathbf{q}_i - (R^\ast\mathbf{p}_i + \mathbf{t}^\ast) |^2}
$$</p>















<figure class="post-figure center ">
    <img src="/img/scientific-computing/kabsch-algorithm-visualized-rmsd.webp"
         alt="Diagram illustrating Root Mean Square Deviation (RMSD) distances"
         title="Diagram illustrating Root Mean Square Deviation (RMSD) distances"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">RMSD measures the average distance between the aligned points.</figcaption>
    
</figure>

<p>which is frequently used as a measure of similarity between molecular structures or as a metric in loss functions for ML applications.</p>
<h3 id="the-kabsch-umeyama-algorithm-scaling">The Kabsch-Umeyama Algorithm (Scaling)</h3>
<p>While the standard Kabsch algorithm solves for optimal rotation and translation, the <strong>Kabsch-Umeyama algorithm</strong> extends this by also finding an optimal <strong>scaling factor</strong> $c$. This is essential when aligning structures of different scales, such as a 3D scan versus a ground truth model.</p>
<p><em>(Note: This is sometimes searched for as the &ldquo;Absch-Umeyama algorithm&rdquo; due to typos, but the correct attribution is to Shinji Umeyama based on Wolfgang Kabsch&rsquo;s work.)</em></p>
<p>The method estimates the transformation $\mathbf{q}_i \approx c R \mathbf{p}_i + \mathbf{t}$. The optimal scale is the trace of the (reflection-corrected) singular values of the cross-covariance divided by the variance of the source points about their centroid. See the <a href="/notes/computational-biology/umeyama-similarity-transformation/">Umeyama paper notes</a> for the full derivation.</p>
<p><strong>A Note on SVD and Automatic Differentiation</strong></p>
<p>While modern frameworks allow us to backpropagate through the Singular Value Decomposition (SVD), it comes with a known stability issue: if the cross-covariance matrix has identical (degenerate) singular values (which can occur if the point clouds are perfectly aligned or have certain symmetries), the gradient of the SVD approaches infinity, causing <code>NaN</code> values during backpropagation. If you plan to use this algorithm as a loss function for a neural network, it is often necessary to add a tiny epsilon to the matrix before computing the SVD, or to utilize an SVD gradient patch. The <a href="/projects/kabsch-horn-cookbook/">Kabsch-Horn Cookbook</a> library provides a SafeSVD primitive that floors the singular-value-gap denominator at machine epsilon in the backward pass, producing finite gradients at degenerate inputs across PyTorch, JAX, TensorFlow, and MLX.</p>
<h2 id="implementation">Implementation</h2>
<p>Let&rsquo;s implement the algorithm in different frameworks. Note that for simplicity, the following implementations cover the <strong>unweighted</strong> Kabsch algorithm. If your application (like molecular dynamics) requires weights (e.g., atomic masses), the <a href="/projects/kabsch-horn-cookbook/">Kabsch-Horn Cookbook</a> library provides per-point weighted alignment out of the box.</p>
<h3 id="numpy">NumPy</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">import</span> numpy <span style="color:#66d9ef">as</span> np
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">kabsch_numpy</span>(P, Q):
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Computes the optimal rotation and translation to align two sets of points (P -&gt; Q),
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    and their RMSD.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    :param P: A Nx3 matrix of points
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    :param Q: A Nx3 matrix of points
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    :return: A tuple containing the optimal rotation matrix, the optimal
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">             translation vector, and the RMSD.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">assert</span> P<span style="color:#f92672">.</span>shape <span style="color:#f92672">==</span> Q<span style="color:#f92672">.</span>shape, <span style="color:#e6db74">&#34;Matrix dimensions must match&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Compute centroids</span>
</span></span><span style="display:flex;"><span>    centroid_P <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>mean(P, axis<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>    centroid_Q <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>mean(Q, axis<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Center the points</span>
</span></span><span style="display:flex;"><span>    p <span style="color:#f92672">=</span> P <span style="color:#f92672">-</span> centroid_P
</span></span><span style="display:flex;"><span>    q <span style="color:#f92672">=</span> Q <span style="color:#f92672">-</span> centroid_Q
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Compute the covariance matrix</span>
</span></span><span style="display:flex;"><span>    H <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>dot(p<span style="color:#f92672">.</span>T, q)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># SVD</span>
</span></span><span style="display:flex;"><span>    U, S, Vt <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>linalg<span style="color:#f92672">.</span>svd(H)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Validate right-handed coordinate system</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> np<span style="color:#f92672">.</span>linalg<span style="color:#f92672">.</span>det(np<span style="color:#f92672">.</span>dot(Vt<span style="color:#f92672">.</span>T, U<span style="color:#f92672">.</span>T)) <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">0.0</span>:
</span></span><span style="display:flex;"><span>        Vt[<span style="color:#f92672">-</span><span style="color:#ae81ff">1</span>, :] <span style="color:#f92672">*=</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">1.0</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Optimal rotation</span>
</span></span><span style="display:flex;"><span>    R <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>dot(Vt<span style="color:#f92672">.</span>T, U<span style="color:#f92672">.</span>T)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Optimal translation (depends on R, so computed after it)</span>
</span></span><span style="display:flex;"><span>    t <span style="color:#f92672">=</span> centroid_Q <span style="color:#f92672">-</span> np<span style="color:#f92672">.</span>dot(R, centroid_P)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># RMSD</span>
</span></span><span style="display:flex;"><span>    rmsd <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>sqrt(np<span style="color:#f92672">.</span>sum(np<span style="color:#f92672">.</span>square(np<span style="color:#f92672">.</span>dot(p, R<span style="color:#f92672">.</span>T) <span style="color:#f92672">-</span> q)) <span style="color:#f92672">/</span> P<span style="color:#f92672">.</span>shape[<span style="color:#ae81ff">0</span>])
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> R, t, rmsd
</span></span></code></pre></div><p>Here&rsquo;s a quick test to verify correctness:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">test_numpy</span>():
</span></span><span style="display:flex;"><span>    np<span style="color:#f92672">.</span>random<span style="color:#f92672">.</span>seed(<span style="color:#ae81ff">12345</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    P <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>random<span style="color:#f92672">.</span>randn(<span style="color:#ae81ff">100</span>, <span style="color:#ae81ff">3</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    alpha <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>random<span style="color:#f92672">.</span>rand() <span style="color:#f92672">*</span> <span style="color:#ae81ff">2</span> <span style="color:#f92672">*</span> np<span style="color:#f92672">.</span>pi
</span></span><span style="display:flex;"><span>    R <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>array([[np<span style="color:#f92672">.</span>cos(alpha), <span style="color:#f92672">-</span>np<span style="color:#f92672">.</span>sin(alpha), <span style="color:#ae81ff">0</span>],
</span></span><span style="display:flex;"><span>                    [np<span style="color:#f92672">.</span>sin(alpha), np<span style="color:#f92672">.</span>cos(alpha), <span style="color:#ae81ff">0</span>],
</span></span><span style="display:flex;"><span>                    [<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">1</span>]])
</span></span><span style="display:flex;"><span>    t <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>random<span style="color:#f92672">.</span>randn(<span style="color:#ae81ff">3</span>) <span style="color:#f92672">*</span> <span style="color:#ae81ff">10</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    Q <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>dot(P, R<span style="color:#f92672">.</span>T) <span style="color:#f92672">+</span> t
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    R_opt, t_opt, rmsd <span style="color:#f92672">=</span> kabsch_numpy(P, Q)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    print(<span style="color:#e6db74">&#39;RMSD: </span><span style="color:#e6db74">{}</span><span style="color:#e6db74">&#39;</span><span style="color:#f92672">.</span>format(rmsd))
</span></span><span style="display:flex;"><span>    print(<span style="color:#e6db74">&#39;R:</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">{}</span><span style="color:#e6db74">&#39;</span><span style="color:#f92672">.</span>format(R))
</span></span><span style="display:flex;"><span>    print(<span style="color:#e6db74">&#39;R_opt:</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">{}</span><span style="color:#e6db74">&#39;</span><span style="color:#f92672">.</span>format(R_opt))
</span></span><span style="display:flex;"><span>    print(<span style="color:#e6db74">&#39;t:</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">{}</span><span style="color:#e6db74">&#39;</span><span style="color:#f92672">.</span>format(t))
</span></span><span style="display:flex;"><span>    print(<span style="color:#e6db74">&#39;t_opt:</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">{}</span><span style="color:#e6db74">&#39;</span><span style="color:#f92672">.</span>format(t_opt))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    l2_t <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>linalg<span style="color:#f92672">.</span>norm(t <span style="color:#f92672">-</span> t_opt)
</span></span><span style="display:flex;"><span>    l2_R <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>linalg<span style="color:#f92672">.</span>norm(R <span style="color:#f92672">-</span> R_opt)
</span></span><span style="display:flex;"><span>    print(<span style="color:#e6db74">&#39;l2_t: </span><span style="color:#e6db74">{}</span><span style="color:#e6db74">&#39;</span><span style="color:#f92672">.</span>format(l2_t))
</span></span><span style="display:flex;"><span>    print(<span style="color:#e6db74">&#39;l2_R: </span><span style="color:#e6db74">{}</span><span style="color:#e6db74">&#39;</span><span style="color:#f92672">.</span>format(l2_R))
</span></span></code></pre></div><p>Running this test shows the algorithm correctly recovers the rotation and translation:</p>
<pre><code>RMSD: 3.2111501877699246e-15
R:
[[-0.8475392 -0.5307328  0.       ]
 [ 0.5307328 -0.8475392  0.       ]
 [ 0.         0.         1.       ]]
R_opt:
[[-8.47539198e-01 -5.30732803e-01 -2.95434260e-16]
 [ 5.30732803e-01 -8.47539198e-01  2.92859649e-16]
 [ 0.00000000e+00 -2.77555756e-16  1.00000000e+00]]
t:
[ 5.99726796  1.50078468 -3.34633977]
t_opt:
[ 5.99726796  1.50078468 -3.34633977]
l2_t: 2.7012892057857038e-15
l2_R: 8.028174304721057e-16
</code></pre>
<p>Both the rotation and the translation are recovered to within floating-point precision (the residuals <code>l2_t</code> and <code>l2_R</code> are on the order of <code>1e-15</code>).</p>
<p>For batch processing:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">kabsch_numpy_batched</span>(P, Q):
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Computes the optimal rotation and translation to align two sets of points (P -&gt; Q),
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    and their RMSD.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    :param P: A BxNx3 matrix of points
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    :param Q: A BxNx3 matrix of points
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    :return: A tuple containing the optimal rotation matrix, the optimal
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">             translation vector, and the RMSD.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">assert</span> P<span style="color:#f92672">.</span>shape <span style="color:#f92672">==</span> Q<span style="color:#f92672">.</span>shape, <span style="color:#e6db74">&#34;Matrix dimensions must match&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Compute centroids</span>
</span></span><span style="display:flex;"><span>    centroid_P <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>mean(P, axis<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span>, keepdims<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>)  <span style="color:#75715e"># Bx1x3</span>
</span></span><span style="display:flex;"><span>    centroid_Q <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>mean(Q, axis<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span>, keepdims<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>)  <span style="color:#75715e"># Bx1x3</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Center the points</span>
</span></span><span style="display:flex;"><span>    p <span style="color:#f92672">=</span> P <span style="color:#f92672">-</span> centroid_P  <span style="color:#75715e"># BxNx3</span>
</span></span><span style="display:flex;"><span>    q <span style="color:#f92672">=</span> Q <span style="color:#f92672">-</span> centroid_Q  <span style="color:#75715e"># BxNx3</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Compute the covariance matrix</span>
</span></span><span style="display:flex;"><span>    H <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>matmul(p<span style="color:#f92672">.</span>transpose(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">1</span>), q)  <span style="color:#75715e"># Bx3x3</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># SVD</span>
</span></span><span style="display:flex;"><span>    U, S, Vt <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>linalg<span style="color:#f92672">.</span>svd(H)  <span style="color:#75715e"># Bx3x3</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Validate right-handed coordinate system</span>
</span></span><span style="display:flex;"><span>    d <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>linalg<span style="color:#f92672">.</span>det(np<span style="color:#f92672">.</span>matmul(Vt<span style="color:#f92672">.</span>transpose(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">1</span>), U<span style="color:#f92672">.</span>transpose(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">1</span>)))
</span></span><span style="display:flex;"><span>    flip <span style="color:#f92672">=</span> d <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">0.0</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> flip<span style="color:#f92672">.</span>any():
</span></span><span style="display:flex;"><span>        Vt[flip, <span style="color:#f92672">-</span><span style="color:#ae81ff">1</span>, :] <span style="color:#f92672">*=</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">1.0</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Optimal rotation</span>
</span></span><span style="display:flex;"><span>    R <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>matmul(Vt<span style="color:#f92672">.</span>transpose(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">1</span>), U<span style="color:#f92672">.</span>transpose(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">1</span>))  <span style="color:#75715e"># Bx3x3</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Optimal translation (depends on R, so computed after it)</span>
</span></span><span style="display:flex;"><span>    t <span style="color:#f92672">=</span> centroid_Q<span style="color:#f92672">.</span>squeeze(<span style="color:#ae81ff">1</span>) <span style="color:#f92672">-</span> np<span style="color:#f92672">.</span>matmul(centroid_P, R<span style="color:#f92672">.</span>transpose(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">1</span>))<span style="color:#f92672">.</span>squeeze(<span style="color:#ae81ff">1</span>)  <span style="color:#75715e"># Bx3</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># RMSD</span>
</span></span><span style="display:flex;"><span>    rmsd <span style="color:#f92672">=</span> np<span style="color:#f92672">.</span>sqrt(np<span style="color:#f92672">.</span>sum(np<span style="color:#f92672">.</span>square(np<span style="color:#f92672">.</span>matmul(p, R<span style="color:#f92672">.</span>transpose(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">1</span>)) <span style="color:#f92672">-</span> q), axis<span style="color:#f92672">=</span>(<span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">2</span>)) <span style="color:#f92672">/</span> P<span style="color:#f92672">.</span>shape[<span style="color:#ae81ff">1</span>])
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> R, t, rmsd
</span></span></code></pre></div><h3 id="pytorch">PyTorch</h3>


<p><details >
  <summary markdown="span">📝 Important Update (February 15, 2026)</summary>
  <strong>Bug Fix Notice:</strong> The PyTorch implementation has been updated to use the &ldquo;B-matrix&rdquo; broadcasting approach. This eliminates in-place tensor modification (which breaks <code>autograd</code>) and data-dependent control flow (which breaks <code>torch.compile</code> and <code>torch.vmap</code>).
</details></p>

<p>The PyTorch implementation now uses broadcasting to ensure differentiability:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">import</span> torch
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">kabsch_torch</span>(P, Q):
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Computes the optimal rotation and translation to align two sets of points (P -&gt; Q),
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    and their RMSD.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    :param P: A Nx3 matrix of points
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    :param Q: A Nx3 matrix of points
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    :return: A tuple containing the optimal rotation matrix, the optimal
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">             translation vector, and the RMSD.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">assert</span> P<span style="color:#f92672">.</span>shape <span style="color:#f92672">==</span> Q<span style="color:#f92672">.</span>shape, <span style="color:#e6db74">&#34;Matrix dimensions must match&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Compute centroids</span>
</span></span><span style="display:flex;"><span>    centroid_P <span style="color:#f92672">=</span> torch<span style="color:#f92672">.</span>mean(P, dim<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>    centroid_Q <span style="color:#f92672">=</span> torch<span style="color:#f92672">.</span>mean(Q, dim<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Center the points</span>
</span></span><span style="display:flex;"><span>    p <span style="color:#f92672">=</span> P <span style="color:#f92672">-</span> centroid_P
</span></span><span style="display:flex;"><span>    q <span style="color:#f92672">=</span> Q <span style="color:#f92672">-</span> centroid_Q
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Compute the covariance matrix</span>
</span></span><span style="display:flex;"><span>    H <span style="color:#f92672">=</span> torch<span style="color:#f92672">.</span>matmul(p<span style="color:#f92672">.</span>transpose(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">1</span>), q)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># SVD</span>
</span></span><span style="display:flex;"><span>    U, S, Vt <span style="color:#f92672">=</span> torch<span style="color:#f92672">.</span>linalg<span style="color:#f92672">.</span>svd(H)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># 1. Calculate determinant</span>
</span></span><span style="display:flex;"><span>    d <span style="color:#f92672">=</span> torch<span style="color:#f92672">.</span>det(torch<span style="color:#f92672">.</span>matmul(Vt<span style="color:#f92672">.</span>transpose(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">1</span>), U<span style="color:#f92672">.</span>transpose(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">1</span>)))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># 2. Build diagonal B tensor without in-place mutation</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># We use stack to preserve gradients and graph connections</span>
</span></span><span style="display:flex;"><span>    B_diag <span style="color:#f92672">=</span> torch<span style="color:#f92672">.</span>stack([torch<span style="color:#f92672">.</span>tensor(<span style="color:#ae81ff">1.0</span>, device<span style="color:#f92672">=</span>d<span style="color:#f92672">.</span>device, dtype<span style="color:#f92672">=</span>d<span style="color:#f92672">.</span>dtype),
</span></span><span style="display:flex;"><span>                          torch<span style="color:#f92672">.</span>tensor(<span style="color:#ae81ff">1.0</span>, device<span style="color:#f92672">=</span>d<span style="color:#f92672">.</span>device, dtype<span style="color:#f92672">=</span>d<span style="color:#f92672">.</span>dtype),
</span></span><span style="display:flex;"><span>                          torch<span style="color:#f92672">.</span>sign(d)])
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># 3. Scale columns of Vt.T via broadcasting, then multiply by U^T</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Vt.T: (3, 3). B_diag: (3) -&gt; B_diag[None, :]: (1, 3)</span>
</span></span><span style="display:flex;"><span>    R <span style="color:#f92672">=</span> torch<span style="color:#f92672">.</span>matmul(Vt<span style="color:#f92672">.</span>transpose(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">1</span>) <span style="color:#f92672">*</span> B_diag[<span style="color:#66d9ef">None</span>, :], U<span style="color:#f92672">.</span>transpose(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">1</span>))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Optimal translation (depends on R, so computed after it)</span>
</span></span><span style="display:flex;"><span>    t <span style="color:#f92672">=</span> centroid_Q <span style="color:#f92672">-</span> centroid_P <span style="color:#f92672">@</span> R<span style="color:#f92672">.</span>transpose(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># RMSD</span>
</span></span><span style="display:flex;"><span>    rmsd <span style="color:#f92672">=</span> torch<span style="color:#f92672">.</span>sqrt(torch<span style="color:#f92672">.</span>sum(torch<span style="color:#f92672">.</span>square(torch<span style="color:#f92672">.</span>matmul(p, R<span style="color:#f92672">.</span>transpose(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">1</span>)) <span style="color:#f92672">-</span> q)) <span style="color:#f92672">/</span> P<span style="color:#f92672">.</span>shape[<span style="color:#ae81ff">0</span>])
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> R, t, rmsd
</span></span></code></pre></div><p>And our batched version:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">kabsch_torch_batched</span>(P, Q):
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Computes the optimal rotation and translation to align two sets of points (P -&gt; Q),
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    and their RMSD, in a batched manner.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    :param P: A BxNx3 matrix of points
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    :param Q: A BxNx3 matrix of points
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    :return: A tuple containing the optimal rotation matrix, the optimal
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">             translation vector, and the RMSD.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">assert</span> P<span style="color:#f92672">.</span>shape <span style="color:#f92672">==</span> Q<span style="color:#f92672">.</span>shape, <span style="color:#e6db74">&#34;Matrix dimensions must match&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Compute centroids</span>
</span></span><span style="display:flex;"><span>    centroid_P <span style="color:#f92672">=</span> torch<span style="color:#f92672">.</span>mean(P, dim<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span>, keepdims<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>)  <span style="color:#75715e"># Bx1x3</span>
</span></span><span style="display:flex;"><span>    centroid_Q <span style="color:#f92672">=</span> torch<span style="color:#f92672">.</span>mean(Q, dim<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span>, keepdims<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>)  <span style="color:#75715e"># Bx1x3</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Center the points</span>
</span></span><span style="display:flex;"><span>    p <span style="color:#f92672">=</span> P <span style="color:#f92672">-</span> centroid_P  <span style="color:#75715e"># BxNx3</span>
</span></span><span style="display:flex;"><span>    q <span style="color:#f92672">=</span> Q <span style="color:#f92672">-</span> centroid_Q  <span style="color:#75715e"># BxNx3</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Compute the covariance matrix</span>
</span></span><span style="display:flex;"><span>    H <span style="color:#f92672">=</span> torch<span style="color:#f92672">.</span>matmul(p<span style="color:#f92672">.</span>transpose(<span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">2</span>), q)  <span style="color:#75715e"># Bx3x3</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># SVD</span>
</span></span><span style="display:flex;"><span>    U, S, Vt <span style="color:#f92672">=</span> torch<span style="color:#f92672">.</span>linalg<span style="color:#f92672">.</span>svd(H)  <span style="color:#75715e"># Bx3x3</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># 1. Calculate batched determinant</span>
</span></span><span style="display:flex;"><span>    d <span style="color:#f92672">=</span> torch<span style="color:#f92672">.</span>det(torch<span style="color:#f92672">.</span>matmul(Vt<span style="color:#f92672">.</span>transpose(<span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">2</span>), U<span style="color:#f92672">.</span>transpose(<span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">2</span>)))  <span style="color:#75715e"># B</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># 2. Build batched B_diag without in-place mutation or control flow</span>
</span></span><span style="display:flex;"><span>    ones <span style="color:#f92672">=</span> torch<span style="color:#f92672">.</span>ones_like(d)
</span></span><span style="display:flex;"><span>    B_diag <span style="color:#f92672">=</span> torch<span style="color:#f92672">.</span>stack([ones, ones, torch<span style="color:#f92672">.</span>sign(d)], dim<span style="color:#f92672">=-</span><span style="color:#ae81ff">1</span>) <span style="color:#75715e"># Bx3</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># 3. Scale columns of Vt.T and multiply</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Vt.T: (B, 3, 3). B_diag: (B, 3). B_diag[:, None, :]: (B, 1, 3).</span>
</span></span><span style="display:flex;"><span>    R <span style="color:#f92672">=</span> torch<span style="color:#f92672">.</span>matmul(Vt<span style="color:#f92672">.</span>transpose(<span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">2</span>) <span style="color:#f92672">*</span> B_diag[:, <span style="color:#66d9ef">None</span>, :], U<span style="color:#f92672">.</span>transpose(<span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">2</span>))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Optimal translation (depends on R, so computed after it)</span>
</span></span><span style="display:flex;"><span>    t <span style="color:#f92672">=</span> centroid_Q<span style="color:#f92672">.</span>squeeze(<span style="color:#ae81ff">1</span>) <span style="color:#f92672">-</span> torch<span style="color:#f92672">.</span>matmul(centroid_P, R<span style="color:#f92672">.</span>transpose(<span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">2</span>))<span style="color:#f92672">.</span>squeeze(<span style="color:#ae81ff">1</span>)  <span style="color:#75715e"># Bx3</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># RMSD</span>
</span></span><span style="display:flex;"><span>    rmsd <span style="color:#f92672">=</span> torch<span style="color:#f92672">.</span>sqrt(torch<span style="color:#f92672">.</span>sum(torch<span style="color:#f92672">.</span>square(torch<span style="color:#f92672">.</span>matmul(p, R<span style="color:#f92672">.</span>transpose(<span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">2</span>)) <span style="color:#f92672">-</span> q), dim<span style="color:#f92672">=</span>(<span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">2</span>)) <span style="color:#f92672">/</span> P<span style="color:#f92672">.</span>shape[<span style="color:#ae81ff">1</span>])
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> R, t, rmsd
</span></span></code></pre></div><h3 id="tensorflow">TensorFlow</h3>
<p>The TensorFlow implementation returns <code>S</code>, <code>U</code>, and <code>V</code> directly. To handle immutability and potential compilation (e.g., via <code>@tf.function</code>), we avoid explicit conditional branching by constructing a correction matrix $B$ and broadcasting it.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">import</span> tensorflow <span style="color:#66d9ef">as</span> tf
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">kabsch_tensorflow</span>(P, Q):
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Computes the optimal rotation and translation to align two sets of points (P -&gt; Q),
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    and their RMSD.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    :param P: A Nx3 matrix of points
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    :param Q: A Nx3 matrix of points
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    :return: A tuple containing the optimal rotation matrix, the optimal
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">             translation vector, and the RMSD.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    P <span style="color:#f92672">=</span> tf<span style="color:#f92672">.</span>convert_to_tensor(P, dtype<span style="color:#f92672">=</span>tf<span style="color:#f92672">.</span>float32)
</span></span><span style="display:flex;"><span>    Q <span style="color:#f92672">=</span> tf<span style="color:#f92672">.</span>convert_to_tensor(Q, dtype<span style="color:#f92672">=</span>tf<span style="color:#f92672">.</span>float32)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">assert</span> P<span style="color:#f92672">.</span>shape <span style="color:#f92672">==</span> Q<span style="color:#f92672">.</span>shape, <span style="color:#e6db74">&#34;Matrix dimensions must match&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Compute centroids</span>
</span></span><span style="display:flex;"><span>    centroid_P <span style="color:#f92672">=</span> tf<span style="color:#f92672">.</span>reduce_mean(P, axis<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>    centroid_Q <span style="color:#f92672">=</span> tf<span style="color:#f92672">.</span>reduce_mean(Q, axis<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Center the points</span>
</span></span><span style="display:flex;"><span>    p <span style="color:#f92672">=</span> P <span style="color:#f92672">-</span> centroid_P
</span></span><span style="display:flex;"><span>    q <span style="color:#f92672">=</span> Q <span style="color:#f92672">-</span> centroid_Q
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Compute the covariance matrix</span>
</span></span><span style="display:flex;"><span>    H <span style="color:#f92672">=</span> tf<span style="color:#f92672">.</span>matmul(tf<span style="color:#f92672">.</span>transpose(p), q)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># SVD</span>
</span></span><span style="display:flex;"><span>    S, U, V <span style="color:#f92672">=</span> tf<span style="color:#f92672">.</span>linalg<span style="color:#f92672">.</span>svd(H)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># 1. Calculate determinant</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Note: V in TF SVD is V, not V^T.</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># R = V * U^T. Det(R) = Det(V * U^T)</span>
</span></span><span style="display:flex;"><span>    d <span style="color:#f92672">=</span> tf<span style="color:#f92672">.</span>linalg<span style="color:#f92672">.</span>det(tf<span style="color:#f92672">.</span>matmul(V, tf<span style="color:#f92672">.</span>transpose(U)))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># 2. Build diagonal B tensor: [1.0, 1.0, sign(d)]</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Use static shape 3 if possible, or infer from D. Assuming D=3 here.</span>
</span></span><span style="display:flex;"><span>    B_diag <span style="color:#f92672">=</span> tf<span style="color:#f92672">.</span>stack([<span style="color:#ae81ff">1.0</span>, <span style="color:#ae81ff">1.0</span>, tf<span style="color:#f92672">.</span>sign(d)])
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># 3. Scale columns of V via broadcasting (V * B_diag), then multiply by U^T</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># V is DxD, B_diag is D. V * B_diag[None, :] multiplies each column j by B_diag[j]</span>
</span></span><span style="display:flex;"><span>    R <span style="color:#f92672">=</span> tf<span style="color:#f92672">.</span>matmul(V <span style="color:#f92672">*</span> B_diag[<span style="color:#66d9ef">None</span>, :], tf<span style="color:#f92672">.</span>transpose(U))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Optimal translation (depends on R, so computed after it)</span>
</span></span><span style="display:flex;"><span>    t <span style="color:#f92672">=</span> centroid_Q <span style="color:#f92672">-</span> tf<span style="color:#f92672">.</span>linalg<span style="color:#f92672">.</span>matvec(R, centroid_P)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># RMSD</span>
</span></span><span style="display:flex;"><span>    rmsd <span style="color:#f92672">=</span> tf<span style="color:#f92672">.</span>sqrt(tf<span style="color:#f92672">.</span>reduce_sum(tf<span style="color:#f92672">.</span>square(tf<span style="color:#f92672">.</span>matmul(p, tf<span style="color:#f92672">.</span>transpose(R)) <span style="color:#f92672">-</span> q)) <span style="color:#f92672">/</span> P<span style="color:#f92672">.</span>shape[<span style="color:#ae81ff">0</span>])
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> R, t, rmsd
</span></span></code></pre></div><p>and a batched version:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">kabsch_tensorflow_batched</span>(P, Q):
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Computes the optimal rotation and translation to align two sets of points (P -&gt; Q),
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    and their RMSD.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    :param P: A Nx3 matrix of points
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    :param Q: A Nx3 matrix of points
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    :return: A tuple containing the optimal rotation matrix, the optimal
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">             translation vector, and the RMSD.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    P <span style="color:#f92672">=</span> tf<span style="color:#f92672">.</span>convert_to_tensor(P, dtype<span style="color:#f92672">=</span>tf<span style="color:#f92672">.</span>float32)
</span></span><span style="display:flex;"><span>    Q <span style="color:#f92672">=</span> tf<span style="color:#f92672">.</span>convert_to_tensor(Q, dtype<span style="color:#f92672">=</span>tf<span style="color:#f92672">.</span>float32)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">assert</span> P<span style="color:#f92672">.</span>shape <span style="color:#f92672">==</span> Q<span style="color:#f92672">.</span>shape, <span style="color:#e6db74">&#34;Matrix dimensions must match&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Compute centroids</span>
</span></span><span style="display:flex;"><span>    centroid_P <span style="color:#f92672">=</span> tf<span style="color:#f92672">.</span>reduce_mean(P, axis<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span>, keepdims<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>)
</span></span><span style="display:flex;"><span>    centroid_Q <span style="color:#f92672">=</span> tf<span style="color:#f92672">.</span>reduce_mean(Q, axis<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span>, keepdims<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Center the points</span>
</span></span><span style="display:flex;"><span>    p <span style="color:#f92672">=</span> P <span style="color:#f92672">-</span> centroid_P
</span></span><span style="display:flex;"><span>    q <span style="color:#f92672">=</span> Q <span style="color:#f92672">-</span> centroid_Q
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Compute the covariance matrix</span>
</span></span><span style="display:flex;"><span>    H <span style="color:#f92672">=</span> tf<span style="color:#f92672">.</span>matmul(tf<span style="color:#f92672">.</span>transpose(p, perm<span style="color:#f92672">=</span>[<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">1</span>]), q)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># SVD</span>
</span></span><span style="display:flex;"><span>    S, U, V <span style="color:#f92672">=</span> tf<span style="color:#f92672">.</span>linalg<span style="color:#f92672">.</span>svd(H)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># 1. Calculate batched determinant</span>
</span></span><span style="display:flex;"><span>    d <span style="color:#f92672">=</span> tf<span style="color:#f92672">.</span>linalg<span style="color:#f92672">.</span>det(tf<span style="color:#f92672">.</span>matmul(V, tf<span style="color:#f92672">.</span>transpose(U, perm<span style="color:#f92672">=</span>[<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">1</span>])))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># 2. Build batched B_diag: shape (B, 3)</span>
</span></span><span style="display:flex;"><span>    ones <span style="color:#f92672">=</span> tf<span style="color:#f92672">.</span>ones_like(d)
</span></span><span style="display:flex;"><span>    B_diag <span style="color:#f92672">=</span> tf<span style="color:#f92672">.</span>stack([ones, ones, tf<span style="color:#f92672">.</span>sign(d)], axis<span style="color:#f92672">=-</span><span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># 3. Scale columns of V (Broadcasting adds the middle dimension)</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># V: (B, 3, 3), B_diag: (B, 3) -&gt; B_diag[:, None, :]: (B, 1, 3)</span>
</span></span><span style="display:flex;"><span>    R <span style="color:#f92672">=</span> tf<span style="color:#f92672">.</span>matmul(V <span style="color:#f92672">*</span> B_diag[:, <span style="color:#66d9ef">None</span>, :], tf<span style="color:#f92672">.</span>transpose(U, perm<span style="color:#f92672">=</span>[<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">1</span>]))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Optimal translation (depends on R, so computed after it)</span>
</span></span><span style="display:flex;"><span>    t <span style="color:#f92672">=</span> tf<span style="color:#f92672">.</span>squeeze(centroid_Q, axis<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span>) <span style="color:#f92672">-</span> tf<span style="color:#f92672">.</span>linalg<span style="color:#f92672">.</span>matvec(R, tf<span style="color:#f92672">.</span>squeeze(centroid_P, axis<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span>))  <span style="color:#75715e"># Bx3</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># RMSD</span>
</span></span><span style="display:flex;"><span>    rmsd <span style="color:#f92672">=</span> tf<span style="color:#f92672">.</span>sqrt(tf<span style="color:#f92672">.</span>reduce_sum(tf<span style="color:#f92672">.</span>square(tf<span style="color:#f92672">.</span>matmul(p, tf<span style="color:#f92672">.</span>transpose(R, perm<span style="color:#f92672">=</span>[<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">1</span>])) <span style="color:#f92672">-</span> q), axis<span style="color:#f92672">=</span>(<span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">2</span>)) <span style="color:#f92672">/</span> P<span style="color:#f92672">.</span>shape[<span style="color:#ae81ff">1</span>])
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> R, t, rmsd
</span></span></code></pre></div><h3 id="jax">JAX</h3>
<p>The JAX implementation closely mirrors NumPy, replacing <code>np</code> with <code>jnp</code>. However, we again avoid <code>if</code> statements and in-place assignment (which JAX disallows) by using the broadcasting B-matrix approach.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">import</span> jax.numpy <span style="color:#66d9ef">as</span> jnp
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">kabsch_jax</span>(P, Q):
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Computes the optimal rotation and translation to align two sets of points (P -&gt; Q),
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    and their RMSD.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    :param P: A Nx3 matrix of points
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    :param Q: A Nx3 matrix of points
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    :return: A tuple containing the optimal rotation matrix, the optimal
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">             translation vector, and the RMSD.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    P <span style="color:#f92672">=</span> jnp<span style="color:#f92672">.</span>array(P)
</span></span><span style="display:flex;"><span>    Q <span style="color:#f92672">=</span> jnp<span style="color:#f92672">.</span>array(Q)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">assert</span> P<span style="color:#f92672">.</span>shape <span style="color:#f92672">==</span> Q<span style="color:#f92672">.</span>shape, <span style="color:#e6db74">&#34;Matrix dimensions must match&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Compute centroids</span>
</span></span><span style="display:flex;"><span>    centroid_P <span style="color:#f92672">=</span> jnp<span style="color:#f92672">.</span>mean(P, axis<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>    centroid_Q <span style="color:#f92672">=</span> jnp<span style="color:#f92672">.</span>mean(Q, axis<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Center the points</span>
</span></span><span style="display:flex;"><span>    p <span style="color:#f92672">=</span> P <span style="color:#f92672">-</span> centroid_P
</span></span><span style="display:flex;"><span>    q <span style="color:#f92672">=</span> Q <span style="color:#f92672">-</span> centroid_Q
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Compute the covariance matrix</span>
</span></span><span style="display:flex;"><span>    H <span style="color:#f92672">=</span> jnp<span style="color:#f92672">.</span>dot(p<span style="color:#f92672">.</span>T, q)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># SVD</span>
</span></span><span style="display:flex;"><span>    U, S, Vt <span style="color:#f92672">=</span> jnp<span style="color:#f92672">.</span>linalg<span style="color:#f92672">.</span>svd(H)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># 1. Calculate determinant</span>
</span></span><span style="display:flex;"><span>    d <span style="color:#f92672">=</span> jnp<span style="color:#f92672">.</span>linalg<span style="color:#f92672">.</span>det(jnp<span style="color:#f92672">.</span>dot(Vt<span style="color:#f92672">.</span>T, U<span style="color:#f92672">.</span>T))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># 2. Build diagonal B array</span>
</span></span><span style="display:flex;"><span>    B_diag <span style="color:#f92672">=</span> jnp<span style="color:#f92672">.</span>array([<span style="color:#ae81ff">1.0</span>, <span style="color:#ae81ff">1.0</span>, jnp<span style="color:#f92672">.</span>sign(d)])
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># 3. Scale columns of Vt.T and multiply by U.T</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Vt.T is V.</span>
</span></span><span style="display:flex;"><span>    R <span style="color:#f92672">=</span> jnp<span style="color:#f92672">.</span>dot(Vt<span style="color:#f92672">.</span>T <span style="color:#f92672">*</span> B_diag[<span style="color:#66d9ef">None</span>, :], U<span style="color:#f92672">.</span>T)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Optimal translation (depends on R, so computed after it)</span>
</span></span><span style="display:flex;"><span>    t <span style="color:#f92672">=</span> centroid_Q <span style="color:#f92672">-</span> jnp<span style="color:#f92672">.</span>dot(R, centroid_P)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># RMSD</span>
</span></span><span style="display:flex;"><span>    rmsd <span style="color:#f92672">=</span> jnp<span style="color:#f92672">.</span>sqrt(jnp<span style="color:#f92672">.</span>sum(jnp<span style="color:#f92672">.</span>square(jnp<span style="color:#f92672">.</span>dot(p, R<span style="color:#f92672">.</span>T) <span style="color:#f92672">-</span> q)) <span style="color:#f92672">/</span> P<span style="color:#f92672">.</span>shape[<span style="color:#ae81ff">0</span>])
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> R, t, rmsd
</span></span></code></pre></div><p>and batched:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">kabsch_jax_batched</span>(P, Q):
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Computes the optimal rotation and translation to align two sets of points (P -&gt; Q),
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    and their RMSD.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    :param P: A BxNx3 matrix of points
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    :param Q: A BxNx3 matrix of points
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    :return: A tuple containing the optimal rotation matrix, the optimal
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">             translation vector, and the RMSD.
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    &#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    P <span style="color:#f92672">=</span> jnp<span style="color:#f92672">.</span>array(P)
</span></span><span style="display:flex;"><span>    Q <span style="color:#f92672">=</span> jnp<span style="color:#f92672">.</span>array(Q)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">assert</span> P<span style="color:#f92672">.</span>shape <span style="color:#f92672">==</span> Q<span style="color:#f92672">.</span>shape, <span style="color:#e6db74">&#34;Matrix dimensions must match&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Compute centroids</span>
</span></span><span style="display:flex;"><span>    centroid_P <span style="color:#f92672">=</span> jnp<span style="color:#f92672">.</span>mean(P, axis<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span>, keepdims<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>)  <span style="color:#75715e"># Bx1x3</span>
</span></span><span style="display:flex;"><span>    centroid_Q <span style="color:#f92672">=</span> jnp<span style="color:#f92672">.</span>mean(Q, axis<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span>, keepdims<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>)  <span style="color:#75715e"># Bx1x3</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Center the points</span>
</span></span><span style="display:flex;"><span>    p <span style="color:#f92672">=</span> P <span style="color:#f92672">-</span> centroid_P  <span style="color:#75715e"># BxNx3</span>
</span></span><span style="display:flex;"><span>    q <span style="color:#f92672">=</span> Q <span style="color:#f92672">-</span> centroid_Q  <span style="color:#75715e"># BxNx3</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Compute the covariance matrix</span>
</span></span><span style="display:flex;"><span>    H <span style="color:#f92672">=</span> jnp<span style="color:#f92672">.</span>matmul(p<span style="color:#f92672">.</span>transpose(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">1</span>), q)  <span style="color:#75715e"># Bx3x3</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># SVD</span>
</span></span><span style="display:flex;"><span>    U, S, Vt <span style="color:#f92672">=</span> jnp<span style="color:#f92672">.</span>linalg<span style="color:#f92672">.</span>svd(H)  <span style="color:#75715e"># Bx3x3</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># 1. Calculate batched determinant</span>
</span></span><span style="display:flex;"><span>    d <span style="color:#f92672">=</span> jnp<span style="color:#f92672">.</span>linalg<span style="color:#f92672">.</span>det(jnp<span style="color:#f92672">.</span>matmul(Vt<span style="color:#f92672">.</span>transpose(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">1</span>), U<span style="color:#f92672">.</span>transpose(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">1</span>)))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># 2. Build batched B_diag</span>
</span></span><span style="display:flex;"><span>    ones <span style="color:#f92672">=</span> jnp<span style="color:#f92672">.</span>ones_like(d)
</span></span><span style="display:flex;"><span>    B_diag <span style="color:#f92672">=</span> jnp<span style="color:#f92672">.</span>stack([ones, ones, jnp<span style="color:#f92672">.</span>sign(d)], axis<span style="color:#f92672">=-</span><span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># 3. Scale columns of Vt.T and multiply by U.T</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Vt.T: (B, 3, 3). B_diag: (B, 3).</span>
</span></span><span style="display:flex;"><span>    R <span style="color:#f92672">=</span> jnp<span style="color:#f92672">.</span>matmul(Vt<span style="color:#f92672">.</span>transpose(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">1</span>) <span style="color:#f92672">*</span> B_diag[:, <span style="color:#66d9ef">None</span>, :], U<span style="color:#f92672">.</span>transpose(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">1</span>))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Optimal translation (depends on R, so computed after it)</span>
</span></span><span style="display:flex;"><span>    t <span style="color:#f92672">=</span> centroid_Q<span style="color:#f92672">.</span>squeeze(<span style="color:#ae81ff">1</span>) <span style="color:#f92672">-</span> jnp<span style="color:#f92672">.</span>matmul(centroid_P, R<span style="color:#f92672">.</span>transpose(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">1</span>))<span style="color:#f92672">.</span>squeeze(<span style="color:#ae81ff">1</span>)  <span style="color:#75715e"># Bx3</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># RMSD</span>
</span></span><span style="display:flex;"><span>    rmsd <span style="color:#f92672">=</span> jnp<span style="color:#f92672">.</span>sqrt(jnp<span style="color:#f92672">.</span>sum(jnp<span style="color:#f92672">.</span>square(jnp<span style="color:#f92672">.</span>matmul(p, R<span style="color:#f92672">.</span>transpose(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">1</span>)) <span style="color:#f92672">-</span> q), axis<span style="color:#f92672">=</span>(<span style="color:#ae81ff">1</span>, <span style="color:#ae81ff">2</span>)) <span style="color:#f92672">/</span> P<span style="color:#f92672">.</span>shape[<span style="color:#ae81ff">1</span>])
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> R, t, rmsd
</span></span></code></pre></div>














<figure class="post-figure center ">
    <img src="/img/scientific-computing/kabsch-animated-protein-conformational-alignment-analysis.webp"
         alt="Animation of a protein structure being aligned using the Kabsch algorithm"
         title="Animation of a protein structure being aligned using the Kabsch algorithm"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">Real-world application: Aligning protein conformations to analyze structural changes.</figcaption>
    
</figure>

<h2 id="extensions">Extensions</h2>
<p>The Kabsch algorithm has several important extensions that go beyond the formulation dealt with here:</p>
<ul>
<li><strong>Quaternion Form</strong>: The algorithm can be reformulated using quaternions for better numerical stability, particularly useful in applications requiring high precision.</li>
<li><strong>Iterative Versions</strong>: More robust variants that handle noise better and have improved scaling properties for large point sets. This also can be advantageous for setups with limited computational resources.</li>
<li><strong>Weighted Kabsch</strong>: Extensions that incorporate point weights (e.g., atomic masses in molecular dynamics). While SciPy provides a <a href="https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.transform.Rotation.align_vectors.html#scipy.spatial.transform.Rotation.align_vectors">weighted version</a>, it lacks batch processing capabilities.</li>
<li><strong>The Umeyama Algorithm</strong>: If your point sets are rotated, translated, and scaled differently, the Umeyama algorithm is the direct extension of Kabsch. It solves the same optimization problem but introduces a scaling factor $c$, finding the optimal alignment for $Q \approx c R P + t$.</li>
</ul>
<p>Several of these extensions are implemented in the <a href="/projects/kabsch-horn-cookbook/">Kabsch-Horn Cookbook</a> library, which provides differentiable Kabsch, Horn, and Umeyama alignment across NumPy, PyTorch, JAX, TensorFlow, and MLX.</p>
<h2 id="further-reading">Further Reading</h2>
<ul>
<li><a href="https://en.wikipedia.org/wiki/Kabsch_algorithm">Wikipedia, Kabsch Algorithm</a></li>
<li><a href="https://zalo.github.io/blog/kabsch/">Zalo on Kabsch</a>: An interactive shape matching demo.</li>
</ul>
<h3 id="original-papers">Original Papers</h3>
<ul>
<li><strong>[Kabsch 1976]</strong> Kabsch, W. (1976). &ldquo;A solution for the best rotation to relate two sets of vectors.&rdquo; <em>Acta Crystallographica Section A</em>, 32(5), 922-923. <a href="https://doi.org/10.1107/S0567739476001873">DOI: 10.1107/S0567739476001873</a>
<em>The original paper: a closed-form, non-iterative optimal-rotation solution derived via Lagrange multipliers and eigendecomposition of $\tilde{R}R$ (the SVD reformulation came later; see Arun et al. 1987).</em> See also: <a href="/notes/computational-biology/kabsch-algorithm/">paper notes</a>.</li>
<li><strong>[Kabsch 1978]</strong> Kabsch, W. (1978). &ldquo;A discussion of the solution for the best rotation to relate two sets of vectors.&rdquo; <em>Acta Crystallographica Section A</em>, 34(5), 827-828. <a href="https://doi.org/10.1107/S0567739478001680">DOI: 10.1107/S0567739478001680</a>
<em>The follow-up paper correcting for improper rotations (reflections).</em></li>
<li><strong>[Arun et al. 1987]</strong> Arun, K. S., Huang, T. S., &amp; Blostein, S. D. (1987). &ldquo;Least-Squares Fitting of Two 3-D Point Sets.&rdquo; <em>IEEE Transactions on Pattern Analysis and Machine Intelligence</em>, PAMI-9(5), 698-700. <a href="https://doi.org/10.1109/TPAMI.1987.4767965">DOI: 10.1109/TPAMI.1987.4767965</a>
<em>The first SVD-based formulation for 3D point set alignment.</em> See also: <a href="/notes/computational-biology/arun-svd-point-fitting/">paper notes</a>.</li>
<li><strong>[Horn et al. 1988]</strong> Horn, B. K. P., Hilden, H. M., &amp; Negahdaripour, S. (1988). &ldquo;Closed-form solution of absolute orientation using orthonormal matrices.&rdquo; <em>Journal of the Optical Society of America A</em>, 5(7), 1127-1135. <a href="https://doi.org/10.1364/JOSAA.5.001127">DOI: 10.1364/JOSAA.5.001127</a>
<em>The matrix square root (polar decomposition) approach to the same problem.</em> See also: <a href="/notes/computational-biology/horn-orthonormal-matrices/">paper notes</a>.</li>
<li><strong>[Horn 1987]</strong> Horn, B. K. P. (1987). &ldquo;Closed-form solution of absolute orientation using unit quaternions.&rdquo; <em>Journal of the Optical Society of America A</em>, 4(4), 629-642. <a href="https://doi.org/10.1364/JOSAA.4.000629">DOI: 10.1364/JOSAA.4.000629</a>
<em>An alternative quaternion-based closed-form solution that also handles scale.</em> See also: <a href="/notes/computational-biology/horn-absolute-orientation/">paper notes</a>.</li>
<li><strong>[Umeyama 1991]</strong> Umeyama, S. (1991). &ldquo;Least-squares estimation of transformation parameters between two point patterns.&rdquo; <em>IEEE Transactions on Pattern Analysis and Machine Intelligence</em>, 13(4), 376-380. <a href="https://doi.org/10.1109/34.88573">DOI: 10.1109/34.88573</a>
<em>The extension of the algorithm to include optimal scaling in addition to rotation and translation.</em> See also: <a href="/notes/computational-biology/umeyama-similarity-transformation/">paper notes</a>.</li>
</ul>
]]></content:encoded></item><item><title>IQCRNN: Certified Stability for Neural Networks</title><link>https://hunterheidenreich.com/projects/iqcrnn-pytorch/</link><pubDate>Wed, 11 May 2022 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/projects/iqcrnn-pytorch/</guid><description>PyTorch IQCRNN enforcing stability guarantees on RNNs via Integral Quadratic Constraints and semidefinite programming.</description><content:encoded><![CDATA[<p>This project is a PyTorch re-implementation of <strong>IQCRNN</strong>, a method that enforces strict stability guarantees on Recurrent Neural Networks used in control systems.</p>
<h2 id="overview">Overview</h2>
<p>Standard Reinforcement Learning agents can behave unpredictably in unseen states. This approach forces the agent&rsquo;s weights to satisfy <strong>Integral Quadratic Constraints (IQC)</strong> via a projection step. Effectively, it solves a convex optimization problem (Semidefinite Program) inside the gradient descent loop to ensure the controller never violates Lyapunov stability criteria.</p>
<p>The method bridges classic <strong>Robust Control Theory</strong> (1990s) with <strong>Deep Reinforcement Learning</strong> (2020s), providing mathematical certificates of safety for neural network controllers.</p>
<h2 id="features">Features</h2>
<ul>
<li><strong>Hybrid Optimization:</strong> Interleaved standard Gradient Descent (PyTorch) with Convex Optimization (<code>cvxpy</code> + <code>MOSEK</code>) to project weights onto the &ldquo;safe&rdquo; manifold after each training step.</li>
<li><strong>Complex Constraints:</strong> Implemented the &ldquo;Tilde&rdquo; parametrization from the original paper to convexify the non-convex stability conditions of the RNN dynamics, transforming an intractable problem into a solvable Linear Matrix Inequality (LMI).</li>
<li><strong>Safety-Critical Domains:</strong> Applied the controller across six control systems (cartpole, inverted pendulum, nonlinear pendulum, pendubot, power grid, and vehicle dynamics), including unstable plants where &ldquo;crashing&rdquo; during training is unacceptable.</li>
</ul>
<h2 id="usage">Usage</h2>
<p>The repository includes training scripts for the inverted pendulum and power grid environments, demonstrating the stability guarantees in practice.</p>
<h2 id="results">Results</h2>
<p>This project was a deep dive into the tension between <strong>Safety</strong> and <strong>Speed</strong>.</p>
<ul>
<li><strong>The Bottleneck:</strong> Solving an SDP at every few steps of training is computationally expensive (interior-point SDP solvers scale steeply, roughly $O(n^6)$ in the matrix dimension). While it provided mathematical certificates of safety, it highlighted why these methods haven&rsquo;t yet overtaken standard PPO/SAC in production: the &ldquo;safety tax&rdquo; on training time is steep.</li>
<li><strong>The Lesson:</strong> It taught me that &ldquo;theoretical guarantees&rdquo; often come with &ldquo;engineering fine print.&rdquo; If I were to redo this today, I would look into <strong>differentiable convex optimization layers</strong> (like <code>cvxpylayers</code>) to make the projection end-to-end differentiable.</li>
<li><strong>The &ldquo;Rough Edges&rdquo;:</strong> The codebase has artifacts of its research origins (e.g., the <code>reqs.txt</code> dependency dump). Reading a dense control theory paper (Gu et al., 2021) and implementing the math correctly was the primary focus.</li>
</ul>
<h2 id="citation">Citation</h2>
<p>Credit to the original authors:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@misc</span>{gu2021recurrentneuralnetworkcontrollers,
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">title</span>=<span style="color:#e6db74">{Recurrent Neural Network Controllers Synthesis with Stability Guarantees for Partially Observed Systems}</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">author</span>=<span style="color:#e6db74">{Fangda Gu and He Yin and Laurent El Ghaoui and Murat Arcak and Peter Seiler and Ming Jin}</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">year</span>=<span style="color:#e6db74">{2021}</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">eprint</span>=<span style="color:#e6db74">{2109.03861}</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">archivePrefix</span>=<span style="color:#e6db74">{arXiv}</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">primaryClass</span>=<span style="color:#e6db74">{eess.SY}</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">url</span>=<span style="color:#e6db74">{https://arxiv.org/abs/2109.03861}</span>,
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="related-work">Related Work</h2>
<ul>
<li><a href="/research/deconstructing-recurrence-attention-gating/">Deconstructing Recurrence and Attention Gating</a>: research on recurrent network architectures, providing context for why stability guarantees on RNNs matter</li>
</ul>
]]></content:encoded></item><item><title>Analytical Solution to Word2Vec Softmax &amp; Bias Probing</title><link>https://hunterheidenreich.com/research/word-company-vicinity/</link><pubDate>Sun, 01 May 2022 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/research/word-company-vicinity/</guid><description>Analytical derivation of Word2Vec's softmax objective factorization and a new framework for detecting semantic bias in raw corpora.</description><content:encoded><![CDATA[<h2 id="abstract">Abstract</h2>
<p>While the Skip-Gram with Negative Sampling (SGNS) objective for Word2Vec has famously been shown to factorize a shifted PMI matrix, the implicit matrix factorization of the original <strong>Softmax</strong> objective has remained an open question. In this work, we provide the first known analytical solution to Word2Vec&rsquo;s softmax-optimized skip-gram algorithm.</p>
<p>We use this derivation to introduce the <strong>Independent Frequencies Model (IFM)</strong>, identifying a &ldquo;frequency-ratios property&rdquo; that unifies classical word vector models. This theoretical insight allows us to derive a low-cost, training-free method for measuring semantic bias directly from corpus statistics.</p>
<h2 id="key-contributions">Key Contributions</h2>
<ul>
<li><strong>Analytical Solution</strong>: Proved that the softmax skip-gram objective converges to a factorization of the log-conditional probability matrix, a derivation for Word2Vec&rsquo;s original (unapproximated) objective that prior work had left open.</li>
<li><strong>Independent Frequencies Model (IFM)</strong>: Introduced a dense co-occurrence model computable purely from unigram frequencies to act as a null hypothesis for embedding structures.</li>
<li><strong>Bias Dissonance Metric</strong>: Derived a low-cost, training-free method for measuring semantic bias directly from corpus statistics using the frequency-ratios property.</li>
<li><strong>Data Transparency</strong>: Demonstrated how specific corpora exhibit distinct bias profiles, offering a tool for auditing datasets before training large models.</li>
</ul>
<h2 id="key-theoretical-results">Key Theoretical Results</h2>
<h3 id="1-the-softmax-factorization-theorem">1. The Softmax Factorization Theorem</h3>
<p>We prove that under the log-softmax objective, Word2Vec implicitly converges towards a factorization of the <strong>log-conditional probability matrix</strong> of the co-occurrence model.</p>
<p><strong>Theorem:</strong> For the objective
$\mathcal{L}_{\text{soft}} = - \sum _{t,s} F _{t,s}^m \log \varphi (\vec{u}_t \vec{v}_s)$,
the algorithm converges to:</p>
<p>$$
\vec{u}_{t}\vec{v}_{s}^{T} = \log\frac{F_{t,s}^{m}}{f_{t}^{m}}
$$</p>
<p>where $F_{t,s}^m$ is the co-occurrence count and $f_t^m$ is the marginal frequency. This effectively makes the dot product of the embedding vectors equal to the log-conditional probability of the context word given the target word.</p>
<h3 id="2-the-independent-frequencies-model-ifm">2. The Independent Frequencies Model (IFM)</h3>
<p>To understand the baseline behavior of these models, we introduce the IFM, which models a dense co-occurrence matrix computable purely from unigram frequencies:</p>
<p>$$
\hat{F}_{t,s}^{m} = \frac{2m f_t f_s}{M}
$$</p>
<p>This model acts as a &ldquo;null hypothesis&rdquo; for embedding structures, allowing us to isolate true semantic signals from statistical noise.</p>
<h2 id="methodological-innovation-bias-dissonance">Methodological Innovation: Bias Dissonance</h2>
<p>Leveraging the frequency-ratios property derived from our factorization, we propose a metric called <strong>Dissonance ($\Delta$)</strong> to probe semantic bias in data without training a model.</p>
<p>For an analogy $A:B :: C:D$ (e.g., <em>man:king :: woman:queen</em>), we measure the alignment of their corpus frequency ratios. High dissonance indicates that the corpus statistics do not support the analogy, potentially revealing bias or under-representation.</p>
<p><strong>Intuitive Example:</strong> If a corpus contains the phrase <em>&ldquo;man is king&rdquo;</em> 100 times more often than <em>&ldquo;woman is queen,&rdquo;</em> the frequency ratios are misaligned. A perfect, unbiased analogy would have matching ratios (i.e., <em>man</em> relates to <em>king</em> at the same rate <em>woman</em> relates to <em>queen</em>). Any deviation from this symmetry is captured by our dissonance metric, revealing where the data itself encodes asymmetric associations.</p>
<p>$$
\Delta(x,y|\mathcal{D}) = \left| \log\frac{f_{t}f_{\bar{s}}}{f_{s}f_{\bar{t}}} \right| / \max_{l \in \mathcal{V}} { \log f_l }
$$</p>
<p>By applying this to the <strong>Bigger Analogy Test Set (BATS)</strong>, we demonstrated how specific corpora (like Wikipedia vs. Google Books) exhibit distinct bias profiles regarding geographic and encyclopedic knowledge.</p>
<h2 id="visualizing-statistical-independence">Visualizing Statistical Independence</h2>















<figure class="post-figure center ">
    <img src="/img/word-bias-iqr.webp"
         alt="Plot showing the portion of statistically dependent information decreasing as window size increases, with curves for different corpus sizes and an inset showing power-law decay"
         title="Plot showing the portion of statistically dependent information decreasing as window size increases, with curves for different corpus sizes and an inset showing power-law decay"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">The Information Quality Ratio measuring the portion of co-occurrence information that is statistically dependent, plotted against window size. Colors indicate corpus size from the GUM corpus. The dashed lines show the IFM prediction. The inset reveals the power-law decay rate, demonstrating how linguistic dependencies diminish predictably with context distance.</figcaption>
    
</figure>

<h2 id="impact">Impact</h2>
<p>This work bridges the gap between empirical success and theoretical foundations in NLP by:</p>
<ol>
<li><strong>Solving a fundamental mechanism:</strong> Providing the missing factorization proof for Softmax Word2Vec.</li>
<li><strong>Efficient pre-training (a future direction):</strong> The factorization suggests embedding layers could be &ldquo;warm-started&rdquo; from unigram statistics via the IFM, a direction taken up in the companion <a href="/research/eigennoise-contrastive-prior/">EigenNoise</a> work.</li>
<li><strong>Data Transparency:</strong> Offering a computationally inexpensive tool for auditing datasets for bias before investing resources in training large models.</li>
</ol>
<h2 id="my-contribution">My Contribution</h2>
<p>Jake Williams is the first author and primary driver of this work. He developed the core theory, derived the factorization proofs, designed the dissonance metric, and ran the experiments. My role was supporting: I contributed through critique and refinement during the writing process, but the intellectual heavy lifting belongs to Jake.</p>
<h2 id="citation">Citation</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bibtex" data-lang="bibtex"><span style="display:flex;"><span><span style="color:#a6e22e">@misc</span>{williams2022knowcompanywordslies,
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">title</span>=<span style="color:#e6db74">{To Know by the Company Words Keep and What Else Lies in the Vicinity}</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">author</span>=<span style="color:#e6db74">{Jake Ryland Williams and Hunter Scott Heidenreich}</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">year</span>=<span style="color:#e6db74">{2022}</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">eprint</span>=<span style="color:#e6db74">{2205.00148}</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">archivePrefix</span>=<span style="color:#e6db74">{arXiv}</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">primaryClass</span>=<span style="color:#e6db74">{cs.CL}</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">url</span>=<span style="color:#e6db74">{https://arxiv.org/abs/2205.00148}</span>,
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="related-work">Related Work</h2>
<p>For a complementary analytical approach to word representations, deriving data-free word vector initializations from the same frequency-ratio insights, see <a href="/research/eigennoise-contrastive-prior/">EigenNoise: Data-Free Word Vector Initialization</a>.</p>
]]></content:encoded></item><item><title>5 Axes of Multi-Arm Bandit Problems: A Practical Guide</title><link>https://hunterheidenreich.com/posts/a-roadmap-to-multi-arm-bandit-algorithms/</link><pubDate>Tue, 10 Nov 2020 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/posts/a-roadmap-to-multi-arm-bandit-algorithms/</guid><description>Explore 5 key dimensions of multi-arm bandit problems to help practitioners better navigate the exploration-exploitation tradeoff in ML applications.</description><content:encoded><![CDATA[<h2 id="what-is-a-multi-arm-bandit-problem">What is a Multi-Arm Bandit Problem?</h2>
<p>Multi-arm bandit problems are a fundamental class of sequential decision-making problems in machine learning. They&rsquo;re less complex than a full reinforcement learning problem, but they capture a lot of the essential challenges of learning from interaction.</p>
<p>The name comes from the analogy of a gambler facing multiple slot machines (or &ldquo;one-armed bandits&rdquo;) and trying to figure out which one pays out the most over time. Do you keep playing the machine that&rsquo;s paid out well so far, or try others to see if they&rsquo;re better? This is the exploration-exploitation dilemma at the heart of bandit algorithms.</p>
<p>Bandit algorithms solve this by learning the reward distributions for each arm over time, balancing the need to explore new options with exploiting what they&rsquo;ve learned.</p>















<figure class="post-figure center ">
    <img src="/img/multi-arm-bandits/multi-arm-bandit-conceptual-graphic.webp"
         alt="Illustration of a vintage slot machine with multiple arms, representing the multi-arm bandit problem in machine learning where algorithms must balance exploration and exploitation"
         title="Illustration of a vintage slot machine with multiple arms, representing the multi-arm bandit problem in machine learning where algorithms must balance exploration and exploitation"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">Multi-arm bandit algorithms balance exploration and exploitation</figcaption>
    
</figure>

<p>What I&rsquo;ve found helpful is thinking about any bandit problem along five key dimensions. Asking these five questions helps quickly identify which approaches work best for a given problem:</p>
<div style="display: flex; flex-direction: column; gap: 16px; max-width: 700px; margin: 30px auto; font-family: system-ui, -apple-system, sans-serif;">
  <div style="background-color: #5A9BD5; color: white; padding: 20px 24px; border-radius: 10px; box-shadow: 0 4px 6px rgba(0,0,0,0.05);">
    <h3 style="margin: 0 0 8px 0; font-size: 1.25rem; font-weight: 700; color: white;">1. Action Space</h3>
    <p style="margin: 0; font-size: 1.05rem; line-height: 1.5;"><em>What does the problem action space look like?</em> <br>Consider whether your options are finite vs. infinite, or single vs. combinatorial.</p>
  </div>
  <div style="background-color: #55C3BA; color: white; padding: 20px 24px; border-radius: 10px; box-shadow: 0 4px 6px rgba(0,0,0,0.05);">
    <h3 style="margin: 0 0 8px 0; font-size: 1.25rem; font-weight: 700; color: white;">2. Problem Structure</h3>
    <p style="margin: 0; font-size: 1.05rem; line-height: 1.5;"><em>Is there any structure to the problem?</em> <br>Determine whether choosing certain actions provides information about the expected rewards of other actions.</p>
  </div>
  <div style="background-color: #5CC382; color: white; padding: 20px 24px; border-radius: 10px; box-shadow: 0 4px 6px rgba(0,0,0,0.05);">
    <h3 style="margin: 0 0 8px 0; font-size: 1.25rem; font-weight: 700; color: white;">3. External Information</h3>
    <p style="margin: 0; font-size: 1.05rem; line-height: 1.5;"><em>Is there external information that my learner has access to?</em> <br>Assess the availability of contextual information (like user data or environment state) before an action is chosen.</p>
  </div>
  <div style="background-color: #56B14E; color: white; padding: 20px 24px; border-radius: 10px; box-shadow: 0 4px 6px rgba(0,0,0,0.05);">
    <h3 style="margin: 0 0 8px 0; font-size: 1.25rem; font-weight: 700; color: white;">4. Reward Mechanism</h3>
    <p style="margin: 0; font-size: 1.05rem; line-height: 1.5;"><em>How are rewards generated?</em> <br>Identify if the environment's payouts are stochastic (random but consistent), non-stationary (changing over time), or adversarial.</p>
  </div>
  <div style="background-color: #81B653; color: white; padding: 20px 24px; border-radius: 10px; box-shadow: 0 4px 6px rgba(0,0,0,0.05);">
    <h3 style="margin: 0 0 8px 0; font-size: 1.25rem; font-weight: 700; color: white;">5. Learner Feedback</h3>
    <p style="margin: 0; font-size: 1.05rem; line-height: 1.5;"><em>What kind of feedback does my learner receive each round?</em> <br>Clarify if the feedback loop is strict bandit (only seeing the reward for the chosen arm), full, partial, or semi-bandit feedback.</p>
  </div>
</div>
<p>Jump to <strong><a href="#real-examples">Real Examples</a></strong> to see these dimensions in practice.</p>
<hr>
<h2 id="1-what-can-you-do-action-space">1. What Can You Do? (Action Space)</h2>
<p>The first question is simple: what options do you have? Action spaces are generally categorized along two dimensions: size and complexity.</p>
<p><strong>Finite vs. Infinite (Size)</strong></p>
<ul>
<li><strong>Finite (Discretized):</strong> Most people think of this scenario where the agent chooses between a small number of discrete options. Examples include selecting an arm in a standard 3-arm bandit or testing 5 different website layouts.</li>
<li><strong>Infinite (Continuous):</strong> Sometimes your action has continuous parameters. For example, selecting a bid price anywhere in the range of (0, 1), or adjusting a recommendation algorithm&rsquo;s temperature parameter. This requires different mathematical approaches.</li>
</ul>
<p><strong>Single vs. Combinatorial (Complexity)</strong></p>
<ul>
<li><strong>Single Action:</strong> Selection of exactly 1 action per round (e.g., showing a user <em>one</em> specific ad).</li>
<li><strong>Combinatorial Actions:</strong> Selection of a vector (multiple) of actions simultaneously. For example, selecting a subset of edges in a graph to form a path from node $t$ to node $s$. If you are picking 10 movies to populate a Netflix homepage at once, those selections might interact with one another.</li>
</ul>
<h2 id="2-do-your-choices-tell-you-about-other-choices-problem-structure">2. Do Your Choices Tell You About Other Choices? (Problem Structure)</h2>
<p>This is often overlooked but crucial: does trying option A teach you anything about option B?</p>
<ul>
<li><strong>Independent (Unstructured):</strong> Information gained from one action provides <em>zero insight</em> into the expected reward of other actions. For example, knowing the open rate of an email campaign tells you nothing about the click-through rate of a separate social media post.</li>
<li><strong>Correlated (Structured):</strong> Information gained from one action provides <em>valuable hints</em> about similar actions. If you test a 10% discount and see high conversions, it strongly implies a 15% discount will also perform well, helping you map the underlying demand curve.</li>
</ul>
<h2 id="3-what-extra-information-do-you-have-context">3. What Extra Information Do You Have? (Context)</h2>
<p>Real-world problems rarely happen in isolation. The question is: what additional predictive information might help you make better decisions <em>before</em> you pull the lever?</p>
<p>When you incorporate these state variables, you move from a Standard Bandit to a <strong>Contextual Bandit</strong>. This data usually falls into two buckets:</p>
<ul>
<li><strong>User Context:</strong> State information tied directly to the individual, such as age, location, or past purchase history.</li>
<li><strong>Environmental Context:</strong> State information tied to the surrounding conditions at the exact moment of decision, such as time of day, seasonality, or device type (mobile vs. desktop).</li>
</ul>
<h2 id="4-how-do-rewards-work-reward-mechanism">4. How Do Rewards Work? (Reward Mechanism)</h2>
<p>This dimension is about understanding the nature of the feedback you&rsquo;re getting. Are the rewards predictable, changing over time, or actively working against you?</p>
<blockquote>
<p><strong>Stochastic (Stable but Random)</strong>
Each action corresponds to an IID (Independent and Identically Distributed) reward. The underlying mean rewards do not shift significantly over time.
<em>Example: Clinical trials. A drug has a true underlying effectiveness rate, but individual patients respond with random variation around that mean.</em></p>
</blockquote>
<blockquote>
<p><strong>Non-Stationary (Changing Over Time)</strong>
Reward distributions <em>do</em> shift over time, usually following some underlying rule. This is a realistic relaxation of the stochastic model, but comes at a learning cost.
<em>Example: Stock trading or ad performance. What worked last month might not work today.</em></p>
</blockquote>
<blockquote>
<p><strong>Adversarial (Actively Working Against You)</strong>
An adversary selects the worst-case rewards for your options, often with full knowledge of your learner&rsquo;s policy. Randomization is key to remaining unpredictable.
<em>Example: Cybersecurity defenses. Attackers actively adapt their strategies to exploit your algorithm.</em></p>
</blockquote>
<h2 id="5-how-much-do-you-learn-from-each-decision-feedback">5. How Much Do You Learn From Each Decision? (Feedback)</h2>
<p>The last dimension is about information flow. How much do you learn each time you make a choice?</p>
<table>
	<thead>
			<tr>
					<th style="text-align: left">Feedback Type</th>
					<th style="text-align: left">What You Learn</th>
					<th style="text-align: left">Real-World Example</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td style="text-align: left"><strong>Bandit</strong></td>
					<td style="text-align: left">You only observe the reward for the specific action selected. You have no knowledge of what could have been gained from other options.</td>
					<td style="text-align: left">A literal slot machine payout.</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong>Semi-Bandit</strong></td>
					<td style="text-align: left">Common in combinatorial settings. You see the individual rewards associated with each <em>sub-action</em> you took.</td>
					<td style="text-align: left">Learning exactly which specific edges of a graph &ldquo;dropped&rdquo; or succeeded in a path-finding algorithm.</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong>Full</strong></td>
					<td style="text-align: left">You see all reward signals for <em>every</em> action, including the ones you didn&rsquo;t take.</td>
					<td style="text-align: left">Analyzing historical stock market data where you can see all alternative outcomes.</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong>Partial Monitoring</strong></td>
					<td style="text-align: left">Feedback is <em>not</em> received every round. You are occasionally flying blind.</td>
					<td style="text-align: left"><em>(Note: Because the core feedback loop is broken, this is generally not considered a true bandit problem!)</em></td>
			</tr>
	</tbody>
</table>
<h2 id="real-examples">Real Examples</h2>
<p>If you are trying to figure out which bandit algorithm to use for your project, it helps to map out your problem first. Here is how these five dimensions play out in three common real-world scenarios:</p>
<h3 id="1-e-commerce-recommendations">1. E-commerce Recommendations</h3>















<figure class="post-figure center ">
    <img src="/img/multi-arm-bandits/multi-arm-bandit-for-ecommerce.webp"
         alt="Illustration of a multi-arm bandit algorithm applied to e-commerce recommendations, showing a user interacting with a carousel of product recommendations on a website"
         title="Illustration of a multi-arm bandit algorithm applied to e-commerce recommendations, showing a user interacting with a carousel of product recommendations on a website"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">The algorithm must populate an entire &lsquo;Recommended for You&rsquo; carousel with multiple items simultaneously.</figcaption>
    
</figure>

<ul>
<li><strong>Action Space:</strong> Combinatorial <em>(Pick multiple products to show at once)</em></li>
<li><strong>Problem Structure:</strong> Structured <em>(Similar products perform similarly)</em></li>
<li><strong>Context:</strong> Available <em>(User history, time of day, device type)</em></li>
<li><strong>Reward Mechanism:</strong> Stochastic <em>(Relatively stable underlying user preferences)</em></li>
<li><strong>Feedback:</strong> Bandit <em>(You only see clicks on the specific items you showed)</em></li>
</ul>
<h3 id="2-online-ad-bidding">2. Online Ad Bidding</h3>















<figure class="post-figure center ">
    <img src="/img/multi-arm-bandits/multi-arm-bandit-for-ad-bidding.webp"
         alt="Illustration of a multi-arm bandit algorithm applied to online ad bidding, showing a marketer adjusting bid prices in real-time auctions for ad placements"
         title="Illustration of a multi-arm bandit algorithm applied to online ad bidding, showing a marketer adjusting bid prices in real-time auctions for ad placements"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">The algorithm must learn the optimal price to bid in real-time auctions.</figcaption>
    
</figure>

<ul>
<li><strong>Action Space:</strong> Infinite / Continuous <em>(Bid any amount from 0.01 to 10.00)</em></li>
<li><strong>Problem Structure:</strong> Structured <em>(Similar bid prices yield similar win rates)</em></li>
<li><strong>Context:</strong> Available <em>(User demographics, search terms, ad relevance)</em></li>
<li><strong>Reward Mechanism:</strong> Non-stationary <em>(Market conditions and competitor budgets change constantly)</em></li>
<li><strong>Feedback:</strong> Bandit <em>(You only see the results from your winning bids)</em></li>
</ul>
<h3 id="3-content-personalization">3. Content Personalization</h3>
<p><em>A media site dynamically selects articles or videos based on trending topics and user habits to create a personalized homepage.</em></p>
<ul>
<li><strong>Action Space:</strong> Combinatorial <em>(Select a layout of multiple articles/videos)</em></li>
<li><strong>Problem Structure:</strong> Structured <em>(Content categories and tags have predictable patterns)</em></li>
<li><strong>Context:</strong> Available <em>(User profile, current geographic trends, browsing history)</em></li>
<li><strong>Reward Mechanism:</strong> Non-stationary <em>(User interests and news cycles evolve over time)</em></li>
<li><strong>Feedback:</strong> Partial / Semi-Bandit <em>(You see the performance of the individual content pieces within the selected layout)</em></li>
</ul>
<h2 id="the-algorithm-selection-cheat-sheet">The Algorithm Selection Cheat Sheet</h2>
<p>If you prefer a text breakdown, here is how those steps translate into algorithm choices:</p>
<p><strong>Step 1: What are my options? (Action Space)</strong></p>
<ul>
<li><strong>Few discrete choices?</strong> $\rightarrow$ Start with standard <strong>UCB</strong> (Upper Confidence Bound) or <strong>Thompson Sampling</strong>.</li>
<li><strong>Continuous parameters?</strong> $\rightarrow$ Look into <strong>Gaussian Process</strong> methods.</li>
</ul>
<p><strong>Step 2: Do my choices relate to each other? (Structure)</strong></p>
<ul>
<li><strong>Yes?</strong> $\rightarrow$ Use <strong>Linear Bandits</strong> or kernel methods to share information across arms.</li>
<li><strong>No?</strong> $\rightarrow$ Treat each option completely independently.</li>
</ul>
<p><strong>Step 3: What extra information do I have? (Context)</strong></p>
<ul>
<li><strong>Rich context available?</strong> $\rightarrow$ Use contextual bandits (LinUCB is the standard choice here).</li>
<li><strong>No context?</strong> $\rightarrow$ Stick with standard, context-free approaches.</li>
</ul>
<p><strong>Step 4: How do rewards behave? (Mechanism)</strong></p>
<ul>
<li><strong>Stable?</strong> $\rightarrow$ <strong>UCB</strong> and <strong>Thompson Sampling</strong> are your go-to choices.</li>
<li><strong>Changing over time?</strong> $\rightarrow$ Add forgetting factors (discounting) or use sliding-window variants of standard algorithms.</li>
<li><strong>Actively working against me?</strong> $\rightarrow$ You need adversarial approaches, most notably the <strong>EXP3</strong> algorithm.</li>
</ul>
<p><strong>Step 5: How much do I learn each time? (Feedback)</strong></p>
<ul>
<li><strong>Just my choice?</strong> $\rightarrow$ Standard bandit algorithms.</li>
<li><strong>Everything?</strong> $\rightarrow$ Online gradient descent or multiplicative weights.</li>
<li><strong>Something in between?</strong> $\rightarrow$ Look for specialized algorithms that exploit your specific combinatorial structure.</li>
</ul>
<p>This framework keeps the focus exactly where it needs to be: on what actually matters for the problem at hand.</p>
<h2 id="summary">Summary</h2>
<p>These five questions have helped me navigate bandit problems more systematically:</p>
<ol>
<li><strong>What can you do?</strong> (Action space: few vs many options, single vs multiple choices)</li>
<li><strong>Do choices relate?</strong> (Whether trying one option teaches you about others)</li>
<li><strong>What extra info do you have?</strong> (Context that might improve decisions)</li>
<li><strong>How do rewards work?</strong> (Stable, changing, or adversarial)</li>
<li><strong>How much do you learn?</strong> (Feedback from just your choice vs everything)</li>
</ol>
<p>This framework helps avoid getting overwhelmed by the academic literature and focuses attention on what matters for real problems. Structured problems let you learn faster by sharing information between options, while adversarial settings require completely different approaches.</p>
<h2 id="if-you-want-to-learn-more">If You Want to Learn More</h2>
<ul>
<li><strong><a href="https://tor-lattimore.com/downloads/book/book.pdf">Bandit Algorithms by Lattimore &amp; Szepesvári</a></strong> - The comprehensive textbook (free PDF)</li>
<li><strong><a href="https://arxiv.org/abs/1904.07272">Introduction to Multi-Armed Bandits</a></strong> - Aleksandrs Slivkins&rsquo; survey paper is more accessible</li>
</ul>
<h2 id="get-your-hands-dirty">Get Your Hands Dirty</h2>
<p>Want to see these dimensions in code? I&rsquo;ve implemented the foundational algorithms (Explore-Then-Commit and Follow-The-Leader) in Python. Check out the <strong><a href="https://github.com/hunter-heidenreich/Bandit-Algorithms">Bandit Algorithms Repository</a></strong> to run the simulations yourself.</p>
]]></content:encoded></item><item><title>A Guide to Neuroevolution: NEAT and HyperNEAT</title><link>https://hunterheidenreich.com/posts/neuroevolution-neat-and-hyperneat/</link><pubDate>Wed, 02 Jan 2019 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/posts/neuroevolution-neat-and-hyperneat/</guid><description>Explore the evolution of neural network topologies with NEAT and how HyperNEAT scales this approach using geometric patterns and indirect encoding.</description><content:encoded><![CDATA[<h2 id="automating-neural-architecture-design">Automating Neural Architecture Design</h2>
<p>Designing neural network architectures is typically a manual, iterative process. Researchers experiment with different layer configurations, activation functions, and connection patterns, often guided by intuition and empirical results. Evolution offers an automated alternative to this design process.</p>
<p><a href="https://nn.cs.utexas.edu/downloads/papers/stanley.ec02.pdf">NEAT (NeuroEvolution of Augmenting Topologies)</a>, introduced in 2002, optimizes network weights and evolves the network structure itself, starting from minimal topologies and growing complexity only when beneficial.</p>
<p>NEAT&rsquo;s core innovations solved fundamental problems that had plagued earlier attempts at topology evolution. Its solutions for genetic encoding, structural crossover, and innovation protection remain influential today, especially as neural architecture search and automated ML gain prominence.</p>
<h2 id="the-core-challenges-of-neat">The Core Challenges of NEAT</h2>
<p>Evolving neural network topologies presents several fundamental challenges that NEAT elegantly addressed. Understanding these problems helps explain why NEAT&rsquo;s solutions were so influential.</p>
<h3 id="genetic-encoding-how-to-represent-networks">Genetic Encoding: How to Represent Networks</h3>
<p>Evolutionary algorithms require a genetic representation, a way to encode individuals that enables meaningful selection, mutation, and crossover. For neural networks, this choice is critical.</p>
<p><strong>Direct encoding</strong> explicitly represents each network component. Genes directly correspond to nodes and connections. This approach is intuitive and readable, and it works well for smaller networks.</p>
<p><strong>Indirect encoding</strong> specifies construction rules or processes. These encodings are more compact and can generate highly complex structures from simple rules.</p>
<p>NEAT chose direct encoding with a simple two-part structure: separate gene lists for nodes and connections. This balances simplicity with the flexibility needed for evolutionary operations.</p>















<figure class="post-figure center ">
    <img src="/img/neat_genomes.webp"
         alt="NEAT genome encoding showing node genes and connection genes with innovation numbers"
         title="NEAT genome encoding showing node genes and connection genes with innovation numbers"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">NEAT&rsquo;s direct encoding: node genes (top) and connection genes (bottom) with historical markings</figcaption>
    
</figure>

<p>Connection genes specify the source and target nodes, weight, enabled status, and an innovation number for historical tracking. Input and output nodes are fixed; only hidden nodes evolve.</p>
<h3 id="structural-mutations-growing-complexity">Structural Mutations: Growing Complexity</h3>
<p>NEAT employs two categories of mutations to evolve both weights and structure:</p>
<p><strong>Weight mutations</strong> adjust existing connection strengths using standard perturbation methods, the familiar approach from traditional neuroevolution.</p>
<p><strong>Structural mutations</strong> add new network components:</p>
<ul>
<li><strong>Add connection</strong>: Creates a new link between existing nodes with a random initial weight</li>
<li><strong>Add node</strong>: Splits an existing connection by inserting a new node. The original connection is disabled, while two new connections replace it. One inherits the original weight, the other starts at 1.0</li>
</ul>
<p>This node-splitting approach minimizes disruption. The new node initially acts as an identity function, giving it time to prove useful before natural selection pressure intensifies.</p>
<h3 id="solving-the-competing-conventions-problem">Solving the Competing Conventions Problem</h3>
<p>Performing crossover between networks with different structures presents a fundamental challenge. Consider two networks that solve the same problem using different internal organizations. Naive crossover between them typically produces broken offspring.</p>















<figure class="post-figure center ">
    <img src="/img/competing_conventions.webp"
         alt="Two neural networks performing the same function but with different internal structures"
         title="Two neural networks performing the same function but with different internal structures"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">The competing conventions problem: identical functions, different implementations</figcaption>
    
</figure>

<p>NEAT&rsquo;s solution draws inspiration from biology through <strong>historical markings</strong>. Each structural innovation (adding a node or connection) receives a unique innovation number, a timestamp of when that change first appeared in the population.</p>
<p>During crossover, genes with matching innovation numbers are aligned and combined. This biological concept of homology enables meaningful recombination between networks of different sizes and structures.</p>















<figure class="post-figure center ">
    <img src="/img/neat_crossover.webp"
         alt="Diagram showing how NEAT aligns genes during crossover using innovation numbers"
         title="Diagram showing how NEAT aligns genes during crossover using innovation numbers"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">NEAT crossover using historical markings for gene alignment</figcaption>
    
</figure>

<h3 id="protecting-innovation-through-speciation">Protecting Innovation Through Speciation</h3>
<p>New structural innovations face a harsh reality: they usually perform worse initially. Adding nodes or connections typically decreases performance before optimization can improve the new structure. Without protection, these innovations disappear before realizing their potential.</p>
<p>NEAT addresses this through <strong>speciation</strong>: dividing the population into species based on structural and weight similarity. The historical markings that enable crossover also measure compatibility between individuals.</p>
<p>Crucially, individuals only compete within their species. This gives new structural innovations time to optimize without immediately competing against established, well-tuned networks.</p>
<p><strong>Explicit fitness sharing</strong> enhances this protection: species divide their collective fitness among members, preventing any single species from dominating the population while maintaining diversity for continued exploration.</p>
<h3 id="complexification-starting-minimal">Complexification: Starting Minimal</h3>
<p>NEAT begins with the simplest possible networks (just input and output nodes connected by random weights). No hidden layers exist initially. Complexity emerges only when mutations that add structure prove beneficial.</p>
<p>This complexification approach builds efficient solutions that solve problems with minimal structure. Combined with speciation, it tends to produce highly optimized architectures.</p>
<h2 id="scaling-up-hyperneat">Scaling Up: HyperNEAT</h2>
<p>NEAT evolved networks through direct encoding, where each gene explicitly specifies nodes and connections. Scaling this approach to larger architectures requires a fundamentally different method. Evolving networks with billions of connections like the brain requires indirect encoding.</p>
<p><a href="https://doi.org/10.1162/artl.2009.15.2.15202">HyperNEAT</a> introduces <strong>indirect encoding</strong> through geometric principles. HyperNEAT evolves geometric patterns that generate connections based on spatial relationships. This enables the evolution of large networks with biological regularities: symmetry, repetition, and locality.</p>
<p>The key insight is leveraging Compositional Pattern Producing Networks (CPPNs) to map coordinates to connection weights, exploiting the geometric organization found in natural neural networks.</p>
<h3 id="biological-motivation">Biological Motivation</h3>
<p>The human brain exhibits remarkable organizational principles:</p>
<ul>
<li><strong>Scale</strong>: ~86 billion neurons with ~100 trillion connections</li>
<li><strong>Repetition</strong>: Structural patterns reused across regions</li>
<li><strong>Symmetry</strong>: Mirrored structures like bilateral visual processing</li>
<li><strong>Locality</strong>: Spatial proximity influences connectivity and function</li>
</ul>
<p>HyperNEAT aims to evolve networks that capture these biological regularities, leading to more efficient and interpretable architectures.</p>
<h3 id="compositional-pattern-producing-networks">Compositional Pattern Producing Networks</h3>
<p>CPPNs are the foundation of HyperNEAT&rsquo;s indirect encoding. Think of them as pattern generators that create complex spatial structures from simple coordinate inputs.</p>
<p>DNA exemplifies indirect encoding (roughly 20,000 protein-coding genes specify a brain with trillions of connections). This massive compression ratio suggests that simple rules can generate complex structures through developmental processes.</p>
<p>CPPNs abstract this concept, using compositions of mathematical functions to create patterns in coordinate space. The same genetic program (function composition) can be reused across different locations and scales, just like how developmental genes control pattern formation throughout an organism.</p>















<figure class="post-figure center ">
    <img src="/img/hyperneat_cppns.webp"
         alt="Various symmetric and repetitive patterns created by CPPNs"
         title="Various symmetric and repetitive patterns created by CPPNs"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">Complex patterns generated by CPPNs through function composition</figcaption>
    
</figure>

<h3 id="pattern-generation-through-function-composition">Pattern Generation Through Function Composition</h3>
<p>CPPNs generate patterns by composing simple mathematical functions. Key function types include:</p>
<ul>
<li><strong>Gaussian functions</strong>: Create symmetric patterns and gradients</li>
<li><strong>Trigonometric functions</strong>: Generate periodic/repetitive structures</li>
<li><strong>Linear functions</strong>: Produce gradients and asymmetric patterns</li>
<li><strong>Sigmoid functions</strong>: Create sharp transitions and boundaries</li>
</ul>
<p>By combining these functions, CPPNs can encode complex regularities that would require many explicit rules in direct encoding.</p>
<h3 id="evolution-of-cppns">Evolution of CPPNs</h3>
<p>HyperNEAT uses NEAT to evolve the CPPN structure. This brings several advantages:</p>
<ul>
<li><strong>Complexification</strong>: CPPNs start simple and grow more complex only when beneficial</li>
<li><strong>Historical markings</strong>: Enable proper crossover between different CPPN topologies</li>
<li><strong>Speciation</strong>: Protects innovative CPPN patterns during evolution</li>
</ul>
<p>Additional activation functions beyond standard neural networks are crucial:</p>
<ul>
<li>Gaussian functions for symmetry</li>
<li>Sine/cosine for repetition</li>
<li>Specialized functions for specific geometric patterns</li>
</ul>
<h2 id="the-hyperneat-process">The HyperNEAT Process</h2>
<h3 id="substrates-geometric-organization">Substrates: Geometric Organization</h3>
<p>A <strong>substrate</strong> defines the spatial arrangement of neurons. Substrates embed neurons in geometric space (2D grids, 3D volumes, etc.), providing an alternative to layer-based connectivity rules.</p>
<p>The CPPN maps from coordinates to connection weights:</p>
<p>$$\text{CPPN}(x_1, y_1, x_2, y_2) = w$$</p>
<p>Where $(x_1, y_1)$ and $(x_2, y_2)$ are the coordinates of two neurons, and $w$ determines their connection weight.</p>















<figure class="post-figure center ">
    <img src="/img/hyperneat_cppn_basics.webp"
         alt="Diagram showing CPPN taking four coordinate inputs and outputting connection weight"
         title="Diagram showing CPPN taking four coordinate inputs and outputting connection weight"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">Basic CPPN architecture mapping coordinates to connection weights</figcaption>
    
</figure>

<p>This geometric approach enables several key properties:</p>
<ul>
<li><strong>Locality</strong>: Nearby neurons tend to have similar connectivity patterns</li>
<li><strong>Symmetry</strong>: Patterns can be mirrored across spatial axes</li>
<li><strong>Repetition</strong>: Periodic functions create repeating motifs</li>
<li><strong>Scalability</strong>: The same pattern can be applied at different resolutions</li>
</ul>
<h3 id="emergent-regularities">Emergent Regularities</h3>
<p>The geometric encoding naturally produces the desired biological patterns:</p>
<p><strong>Symmetry</strong> emerges from symmetric functions. A Gaussian centered at the origin creates identical patterns when $(x_1, y_1)$ and $(x_2, y_2)$ are equidistant from the center.</p>
<p><strong>Repetition</strong> arises from periodic functions like sine and cosine. These create repeating connectivity motifs across the substrate.</p>
<p><strong>Locality</strong> results from functions that vary smoothly across space. Nearby coordinates produce similar outputs, leading to local connectivity patterns.</p>
<p><strong>Imperfect regularity</strong> occurs when these patterns are modulated by additional coordinate dependencies, creating biological-like variation within the basic structure.</p>
<h3 id="substrate-configurations">Substrate Configurations</h3>
<p>The choice of substrate geometry critically influences network behavior. Several standard configurations exist:</p>















<figure class="post-figure center ">
    <img src="/img/hyperneat_substrate_configurations.webp"
         alt="Various substrate layouts including grids, 3D arrangements, and circular patterns"
         title="Various substrate layouts including grids, 3D arrangements, and circular patterns"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">Common substrate geometries for different problem types</figcaption>
    
</figure>

<p><strong>2D Grid</strong>: Simple planar arrangement, CPPN takes four coordinates $(x_1, y_1, x_2, y_2)$</p>
<p><strong>3D Volume</strong>: Extends to three dimensions, CPPN becomes six-dimensional $(x_1, y_1, z_1, x_2, y_2, z_2)$</p>
<p><strong>Sandwich</strong>: Input layer connects only to output layer, useful for sensory-motor tasks</p>
<p><strong>Circular</strong>: Radial geometry enables rotation-invariant patterns and cyclic behaviors</p>
<p>The substrate must be chosen before evolution begins, making domain knowledge important for success.</p>
<h3 id="exploiting-input-output-geometry">Exploiting Input-Output Geometry</h3>
<p>HyperNEAT exploits the spatial organization of inputs and outputs. For visual tasks, pixel coordinates provide meaningful geometric information. For control problems, sensor and actuator layouts can guide connectivity patterns.</p>















<figure class="post-figure center ">
    <img src="/img/hyperneat_inputs_outputs.webp"
         alt="Visual representation of how HyperNEAT maps spatial input arrangements to output patterns"
         title="Visual representation of how HyperNEAT maps spatial input arrangements to output patterns"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">Spatial organization of inputs and outputs enables geometric exploitation</figcaption>
    
</figure>

<p>This spatial awareness allows HyperNEAT to:</p>
<ul>
<li>Develop receptive fields similar to biological vision systems</li>
<li>Create locally connected patterns for spatial processing</li>
<li>Generate symmetric motor control patterns</li>
<li>Scale across different input resolutions</li>
</ul>
<h3 id="resolution-independence">Resolution Independence</h3>
<p>A unique advantage of HyperNEAT is <strong>substrate resolution independence</strong>. Networks evolved on low-resolution substrates can be deployed on higher-resolution versions without retraining. The CPPN&rsquo;s coordinate-based mapping scales naturally across different granularities.</p>
<p>This property suggests that evolved patterns capture fundamental spatial relationships, providing a key insight for scalable neural architecture design.</p>
<h2 id="impact-and-future-directions">Impact and Future Directions</h2>
<p>NEAT and HyperNEAT demonstrated that evolution could design neural network topologies and scale them through indirect encoding. The algorithms&rsquo; key insights, exploiting geometry, generating patterns through function composition, and scaling across resolutions, continue to influence modern research.</p>
<p>Extensions like ES-HyperNEAT add even more sophisticated capabilities by evolving the substrate itself. As neural architecture search becomes increasingly important, these principles find new applications in hybrid approaches that combine evolutionary pattern generation with gradient-based optimization.</p>
<p>The emphasis on spatial organization and regularity also connects to contemporary work on geometric deep learning and equivariant networks, suggesting that evolution and hand-design converge on similar organizing principles for building structured, efficient neural architectures.</p>
]]></content:encoded></item><item><title>Breaking Down Machine Learning for the Average Person</title><link>https://hunterheidenreich.com/posts/breaking-down-ml-for-the-average-person/</link><pubDate>Tue, 04 Dec 2018 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/posts/breaking-down-ml-for-the-average-person/</guid><description>Discover how machine learning actually works through three fundamental approaches, explained with everyday examples you already know and use.</description><content:encoded><![CDATA[<h2 id="machine-learning">Machine Learning</h2>
<p>Machine learning is about teaching computer programs to improve at tasks through experience. We show algorithms examples and let them discover patterns in data.</p>
<p>There are three main approaches to machine learning: supervised learning, unsupervised learning, and reinforcement learning. Each works differently and suits different types of problems.</p>















<figure class="post-figure center ">
    <img src="/img/types-of-machine-learning.webp"
         alt="Diagram showing the three main types of machine learning: supervised, unsupervised, and reinforcement learning"
         title="Diagram showing the three main types of machine learning: supervised, unsupervised, and reinforcement learning"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">Three fundamental approaches to machine learning, each suited to different types of problems and data</figcaption>
    
</figure>

<p>Each type addresses different kinds of problems and works with different data requirements.</p>
<h3 id="supervised-learning">Supervised Learning</h3>
<p>Supervised learning works like teaching with examples and answers. You show the algorithm many input-output pairs, and it learns to predict outputs for new inputs it hasn&rsquo;t seen before.</p>
<p>The algorithm learns by comparing its predictions to the correct answers. Over time, it gets better at finding patterns that connect inputs to outputs. Once trained, it can make predictions on new data.</p>
<p>Common examples you encounter:</p>
<ul>
<li><strong>Email Spam Filtering</strong>: Email systems learn to identify spam by training on thousands of emails labeled as spam or legitimate.</li>
<li><strong>Advertisement Targeting</strong>: Algorithms predict which ads you might click based on your browsing history and demographics.</li>
<li><strong>Face Recognition</strong>: Social media platforms use tagged photos to learn who appears in new images.</li>
</ul>
<h3 id="unsupervised-learning">Unsupervised Learning</h3>
<p>Unsupervised learning works without correct answers. Instead, algorithms analyze data to find patterns, group similar items, or discover structure that wasn&rsquo;t obvious before.</p>
<p>This approach is useful because most real-world data doesn&rsquo;t come with labels. Unsupervised algorithms can process large amounts of data to find patterns that might not be obvious to humans.</p>
<p>Examples include:</p>
<ul>
<li><strong>Recommendation Systems</strong>: Netflix and YouTube analyze viewing patterns to suggest content, even without explicit ratings.</li>
<li><strong>Customer Segmentation</strong>: Companies group customers by purchasing behavior for targeted marketing.</li>
<li><strong>Problem Identification</strong>: Tech companies automatically group similar bug reports to identify common issues.</li>
</ul>
<h3 id="reinforcement-learning">Reinforcement Learning</h3>
<p>Reinforcement learning works through trial and error. An algorithm tries different actions in an environment and learns from the consequences, getting rewards for good choices and penalties for poor ones.</p>
<p>This mirrors how many animals learn: through consequences. Good behavior gets rewards, bad behavior gets correction.</p>
<p>Consider an algorithm learning to play Mario:</p>
<ul>
<li><strong>Agent</strong>: The learning algorithm</li>
<li><strong>Environment</strong>: The game world</li>
<li><strong>Actions</strong>: Controller inputs (jump, run, etc.)</li>
<li><strong>State</strong>: Current game screen</li>
<li><strong>Reward</strong>: Points gained or lost</li>
</ul>
<p>The algorithm tries different button combinations, sees what happens, and gradually learns strategies that lead to higher scores.</p>
<p>Real applications include:</p>
<ul>
<li><strong>Game AI</strong>: AlphaGo and similar systems learned to play complex games through self-play.</li>
<li><strong>Robotics</strong>: Factory robots learn assembly processes through trial and error in simulated environments.</li>
<li><strong>Resource Management</strong>: Google uses reinforcement learning to manage data center cooling, reducing energy costs.</li>
</ul>
<h3 id="putting-it-together">Putting It Together</h3>
<p>In practice, these approaches often work together. Many real systems combine different learning methods depending on the problem and available data.</p>
<p>For example:</p>
<ul>
<li>A game AI might use supervised learning to recognize objects and reinforcement learning for strategy</li>
<li>A language model might learn word relationships without supervision, then improve with supervised training</li>
<li>A recommendation system could group users without labels, then use supervised learning to predict preferences</li>
</ul>
<p>These three approaches cover most machine learning applications. Understanding them helps explain how the AI systems we use daily actually work, whether it&rsquo;s email filters, recommendation engines, or game-playing algorithms.</p>
<p>Machine learning is pattern recognition and learning from data, not magic. The more we understand these basics, the better we can work with and build these systems.</p>
]]></content:encoded></item><item><title>Foundations of AI: Knowledge-Based Agents and Logic</title><link>https://hunterheidenreich.com/posts/knowledge-based-agents-and-logic/</link><pubDate>Sat, 01 Dec 2018 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/posts/knowledge-based-agents-and-logic/</guid><description>A look back at classic symbolic AI: how knowledge-based agents use logic, reasoning, and inference to build intelligent behavior.</description><content:encoded><![CDATA[<p><em>Note from 2026: I originally wrote these notes in 2018 while studying for my undergraduate AI final. They cover classic symbolic AI (often called Good Old-Fashioned AI, or GOFAI). Looking back from the current era of Large Language Models (LLMs) and Vision-Language Models (VLMs), it is fascinating to see how these foundational concepts have evolved. The classic &ldquo;knowledge base&rdquo; and &ldquo;Ask/Tell&rdquo; operations conceptually mirror modern Retrieval-Augmented Generation (RAG) systems, and the classic problem of logical &ldquo;grounding&rdquo; is exactly what we tackle today with multimodal visual grounding in models like GutenOCR. I have preserved and merged these notes here as a time capsule of my learning journey.</em></p>
<hr>
<h2 id="the-evolution-of-knowledge-based-systems">The Evolution of Knowledge-Based Systems</h2>
<p>Early AI research focused heavily on knowledge bases and agents that could interact with them, leading to <strong>expert systems</strong>. These systems relied on central knowledge bases to make decisions through &ldquo;if-then&rdquo; reasoning patterns. While some consider expert systems the first major AI breakthrough, others debate whether they truly belong in the AI category.</p>
<p>Knowledge-based agents remain relevant in modern AI. If you&rsquo;ve worked in natural language processing, you&rsquo;ve likely encountered knowledge bases like WordNet. Wikipedia represents another massive knowledge base, encoding semantic relationships between countless entities.</p>
<p>This abundance of knowledge bases raises important questions: How do we build agents that effectively interface with these repositories? How can they update knowledge bases and make decisions based on stored information?</p>
<p>This article explores these questions through a practical introduction to knowledge-based agents, knowledge representation, and logic.</p>
<h2 id="anatomy-of-a-knowledge-based-agent">Anatomy of a Knowledge-Based Agent</h2>
<p>An <strong>agent</strong> is any entity that acts within an environment. In AI, we build <strong>rational agents</strong>. Entities that act sensibly within their environment. In well-understood environments, rational agents choose actions that yield desired outcomes. In uncertain environments, they act to maximize expected positive outcomes.</p>
<p>Consider agents that maintain internal knowledge, reason over that knowledge, and update their understanding through observations and actions. This is the foundation of <strong>knowledge-based agents</strong>.</p>
<h3 id="knowledge-bases-the-foundation">Knowledge Bases: The Foundation</h3>
<p>The core component of any knowledge-based agent is its <strong>knowledge base</strong> (KB): the repository of what the agent knows about the world.</p>
<p>Every KB consists of <strong>sentences</strong>. These are statements written in a <strong>knowledge representation language</strong>. These specialized languages express assertions about the world in formats that enable systematic reasoning.</p>
<p>Knowledge representation languages are designed for systematic representation of world knowledge. This is why we use these specialized languages for agent knowledge bases.</p>
<h4 id="types-of-knowledge-in-a-kb">Types of Knowledge in a KB</h4>
<p><strong>Axioms</strong> are foundational sentences assumed to be true without derivation from other KB content. If you&rsquo;re familiar with mathematics, this concept will feel natural.</p>
<p><strong>Inferred sentences</strong> are derived from existing KB content through logical reasoning. These are systematically derived using reasoning rules that may be built into the knowledge representation language itself.</p>
<h3 id="core-agent-operations">Core Agent Operations</h3>
<p>Knowledge-based agents interact with their KBs through two fundamental operations: <strong>Ask</strong> and <strong>Tell</strong>.</p>
<h4 id="ask-querying-knowledge">Ask: Querying Knowledge</h4>
<p><strong>Ask</strong> is how agents extract information from their KB. When an agent asks a &ldquo;question&rdquo; or queries its KB, it must format the request in the KB&rsquo;s expected format (typically in the knowledge representation language).</p>
<p>The KB responds with sentences that are either:</p>
<ul>
<li>Directly stored in the KB, or</li>
<li>Inferred from existing KB information</li>
</ul>
<p>This guarantees that responses never contradict the KB&rsquo;s knowledge.</p>
<h4 id="tell-adding-knowledge">Tell: Adding Knowledge</h4>
<p><strong>Tell</strong> updates the KB with new information. Agents use this when they:</p>
<ul>
<li>Observe environmental changes</li>
<li>Update the KB with planned or completed actions</li>
<li>Add newly learned facts</li>
</ul>
<p>Like Ask operations, new information must be properly formatted. The KB stores the new sentence and may trigger reasoning and inference processes to derive additional conclusions.</p>
<h3 id="a-generic-knowledge-based-agent-architecture">A Generic Knowledge-Based Agent Architecture</h3>
<p>Here&rsquo;s a high-level view of how a knowledge-based agent operates:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">kb_agent</span>(percept):
</span></span><span style="display:flex;"><span>    Tell(KB, make_percept_sentence(percept, t))
</span></span><span style="display:flex;"><span>    action <span style="color:#f92672">=</span> Ask(KB, make_action_query(t))
</span></span><span style="display:flex;"><span>    Tell(KB, make_action_sentence(action, t))
</span></span><span style="display:flex;"><span>    t <span style="color:#f92672">=</span> t <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> action
</span></span></code></pre></div><p>This function illustrates the agent&rsquo;s reasoning cycle:</p>
<ol>
<li><strong>Perceive</strong>: Convert environmental observations into KB-compatible sentences via <code>make_percept_sentence()</code></li>
<li><strong>Reason</strong>: Query the KB for the appropriate action using <code>make_action_query()</code></li>
<li><strong>Act</strong>: Record the chosen action in the KB through <code>make_action_sentence()</code></li>
<li><strong>Update</strong>: Increment the time step and return the action</li>
</ol>
<p>The helper functions handle the crucial task of translating between the external world and the knowledge representation language. This architecture focuses purely on the reasoning process, the &ldquo;brains&rdquo; of the operation, while abstracting away perception and action execution details.</p>
<h2 id="design-perspectives-for-knowledge-based-agents">Design Perspectives for Knowledge-Based Agents</h2>
<p>Knowledge-based agents can be analyzed and designed from three distinct levels, each addressing different aspects of the system.</p>
<h3 id="knowledge-level-the-strategic-view">Knowledge Level: The Strategic View</h3>
<p>The <strong>knowledge level</strong> represents the highest level of analysis, focusing on:</p>
<ul>
<li><strong>Goals</strong>: What objectives does the agent pursue?</li>
<li><strong>Knowledge scope</strong>: How much does the agent know about its world initially?</li>
</ul>
<p>This level helps us understand the agent&rsquo;s capabilities and limitations from a strategic perspective, independent of implementation details.</p>
<h3 id="logical-level-the-representation-view">Logical Level: The Representation View</h3>
<p>The <strong>logical level</strong> examines how knowledge is represented and reasoned about:</p>
<ul>
<li><strong>Knowledge representation language</strong>: Which language best suits our domain?</li>
<li><strong>Logical framework</strong>: Are we using propositional logic, first-order logic, or something else?</li>
</ul>
<p>Each choice carries trade-offs. Some languages excel at expressing certain types of knowledge but struggle with others. The logical framework determines what kinds of reasoning the agent can perform.</p>
<h3 id="implementation-level-the-technical-view">Implementation Level: The Technical View</h3>
<p>The <strong>implementation level</strong> addresses the concrete technical decisions:</p>
<ul>
<li><strong>Data structures</strong>: How is knowledge stored? (structs, databases, objects, vectors?)</li>
<li><strong>Algorithms</strong>: Which inference procedures are used?</li>
<li><strong>Performance</strong>: How do design choices affect speed and memory usage?</li>
</ul>
<p>These decisions significantly impact the agent&rsquo;s practical performance and scalability.</p>
<h2 id="learning-and-knowledge-acquisition">Learning and Knowledge Acquisition</h2>
<h3 id="declarative-vs-procedural-approaches">Declarative vs. Procedural Approaches</h3>
<p>Knowledge-based agents can be constructed through two primary approaches:</p>
<p><strong>Declarative approach</strong>: Initialize the agent with an empty KB, then systematically Tell it all the knowledge it needs. This explicit knowledge encoding offers transparency and modularity.</p>
<p><strong>Procedural approach</strong>: Write programs that encode knowledge directly into the agent&rsquo;s behavior. This approach can be more efficient but less transparent.</p>
<p>Real-world systems typically benefit from combining both approaches, leveraging the strengths of each method.</p>
<h3 id="incorporating-learning">Incorporating Learning</h3>
<p>Learning enhances knowledge-based agents in several ways:</p>
<p><strong>Perceptual learning</strong>: Agents can learn to combine observations in novel ways, creating new sentences that improve goal achievement. These learned patterns become part of the KB for future reasoning.</p>
<p><strong>Inference optimization</strong>: Learning algorithms can identify efficient reasoning paths within existing KBs, speeding up the inference process.</p>
<p><strong>Knowledge base expansion</strong>: Research continues into generating new connections in existing KBs like WordNet. As semantic webs proliferate online, efficient methods for KB expansion become increasingly valuable.</p>
<p>The integration of learning with knowledge-based reasoning represents an active area of AI research, with promising applications in knowledge graph completion, automated reasoning, and intelligent system adaptation.</p>
<h2 id="the-components-of-logic">The Components of Logic</h2>
<p>Every logical system has three components that create a framework for representing and reasoning about knowledge.</p>
<h3 id="syntax-the-rules-of-formation">Syntax: The Rules of Formation</h3>
<p>Syntax defines how sentences are constructed, the rules that determine if a sentence is well-formed.</p>
<p>Consider English: &ldquo;name Hunter mine is&rdquo; violates syntax rules, while &ldquo;my name is Hunter&rdquo; follows them. In mathematics, &ldquo;1+=2 3&rdquo; breaks syntax, but &ldquo;1+2=3&rdquo; follows it.</p>
<p>Knowledge bases need proper syntax because they&rsquo;re built from collections of sentences.</p>
<h3 id="semantics-the-meaning-behind-sentences">Semantics: The Meaning Behind Sentences</h3>
<p>While syntax governs structure, semantics determines meaning, whether a sentence is true or false in a given context.</p>
<p>The sentence &ldquo;my name is Hunter&rdquo; is true in our context, but &ldquo;my name is Paul&rdquo; would be false. In math, &ldquo;x=5&rdquo; is true only when x actually equals 5.</p>
<p>We use <strong>model</strong> to describe a specific world state where variables have particular values. Different models let us evaluate sentence truth. One model might have x=4, another x=5.</p>
<p>When a sentence is true under a model, the model <strong>satisfies</strong> the sentence. If model₅ has x=5, then model₅ satisfies <code>x=5</code>.</p>
<p>For any sentence A, $M(A)$ represents all models that satisfy A.</p>
<h3 id="entailment-logical-relationships">Entailment: Logical Relationships</h3>
<p><strong>Entailment</strong> enables reasoning. When sentence A entails sentence B (written $A \models B$), B must be true whenever A is true.</p>
<p>More precisely, A entails B if B is true in every model where A is true:</p>
<ul>
<li>A is the <strong>premise</strong></li>
<li>B is the <strong>consequent</strong></li>
<li>B is a necessary consequence of A</li>
</ul>
<p><strong>Example:</strong> <code>x=1</code> entails <code>xy=y</code>. If x equals 1, then xy will always equal y, regardless of y&rsquo;s value.</p>
<p>This helps knowledge bases reason. When we&rsquo;re uncertain about <code>xy=y</code> but add <code>x=1</code> to our KB, entailment lets us assert that <code>xy=y</code> is now true.</p>
<p>To check if a KB entails sentence A, we verify that $M(KB) \subseteq M(A)$, every model satisfying our KB also satisfies A.</p>
<p>When we add sentences to our KB, we need systematic ways to discover newly entailed sentences. <strong>Inference algorithms</strong> do this work.</p>
<h2 id="inference-algorithms-deriving-new-knowledge">Inference Algorithms: Deriving New Knowledge</h2>
<p>Inference algorithms systematically derive new sentences entailed by our knowledge base. These algorithms need two properties to be useful and trustworthy.</p>
<h3 id="soundness-truth-preservation">Soundness: Truth Preservation</h3>
<p>An inference algorithm is <strong>sound</strong> if it only derives sentences actually entailed by the KB. If an algorithm adds unjustified sentences, it is fabricating information, undermining the KB&rsquo;s reliability.</p>
<h3 id="completeness-finding-everything">Completeness: Finding Everything</h3>
<p>A <strong>complete</strong> inference algorithm finds all sentences entailed by the KB, missing no valid conclusions. This ensures we don&rsquo;t overlook important logical consequences.</p>
<p>Achieving both soundness and completeness grows challenging as environments become more complex. Small, bounded models make this manageable. Unbounded environments require sophisticated algorithms that guarantee both properties while maintaining reasonable performance.</p>
<h3 id="grounding-connecting-logic-to-reality">Grounding: Connecting Logic to Reality</h3>
<p>Beyond formal algorithm properties lies a practical concern: <strong>grounding</strong>. Is our knowledge base actually grounded in reality? Does it accurately represent what&rsquo;s true?</p>
<p>Grounding depends on how knowledge enters the system:</p>
<ul>
<li><strong>Sensors</strong>: Agent perceptions are only as accurate as their sensors</li>
<li><strong>Learning algorithms</strong>: Learned sentences are only as reliable as the learning process</li>
</ul>
<p>With accurate sensors and reliable learning, we can trust our KB&rsquo;s grounding. This remains important when deploying knowledge-based systems in real applications.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Logic provides the foundation for knowledge representation in AI systems. Understanding syntax (forming valid sentences), semantics (sentence meaning), entailment (how conclusions follow from premises), and inference algorithms (deriving new knowledge) enables building knowledge-based agents.</p>
<p>The interplay between these components, governed by soundness, completeness, and grounding, determines how effectively our AI systems represent and reason about the world.</p>
]]></content:encoded></item><item><title>Cartesian Genetic Programming in Julia</title><link>https://hunterheidenreich.com/projects/cgp-julia/</link><pubDate>Sun, 18 Nov 2018 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/projects/cgp-julia/</guid><description>A fork of Dennis Wilson's CGP.jl applying Cartesian Genetic Programming to Atari RL tasks; my work was the Atari experiments, not the core framework.</description><content:encoded><![CDATA[<p>Written in 2018, this was an exploration into <strong>Evolutionary Algorithms</strong> applied to Reinforcement Learning tasks (specifically Atari games). It is a fork of <a href="https://github.com/d9w/CGP.jl">d9w/CGP.jl</a> (Dennis Wilson, Apache 2.0); my work centered on the Atari reinforcement-learning experiments rather than the core CGP framework.</p>
<h2 id="overview">Overview</h2>
<p>Standard Cartesian Genetic Programming (CGP) relies heavily on mutation. The upstream library hybridizes CGP with <strong>NEAT (NeuroEvolution of Augmenting Topologies)</strong> concepts to protect topological innovation through speciation.</p>
<p>My goal in forking it was to evolve graph-based programs that could learn Atari control policies using gradient-free optimization.</p>
<h2 id="features">Features</h2>
<p>The upstream framework provides the CGP machinery this project builds on:</p>
<ul>
<li><strong>Graph-based Crossover:</strong> Crossover operators such as <code>subgraph_crossover</code> and <code>aligned_node_crossover</code> that handle the destructive nature of mating graph structures.</li>
<li><strong>Speciation:</strong> A NEAT-inspired compatibility-distance metric (<code>cgpneat.jl</code>) to maintain population diversity and prevent premature convergence.</li>
<li><strong>Active Gene Tracking:</strong> Differentiates between &ldquo;active&rdquo; nodes (those contributing to output) and &ldquo;junk DNA,&rdquo; focusing mutation on phenotypic changes.</li>
</ul>
<p>My own contribution was the <strong>Atari reinforcement-learning layer</strong> on top of this: experiment variants (<code>action_atari.jl</code>, <code>original_atari.jl</code>, <code>manual_atari.jl</code>, <code>play_atari.jl</code>, <code>param_sweep.jl</code>), custom fitness and scoring functions, early-stopping and completion-percentage logging, multithreading and <code>pmap</code> multiprocessing attempts (reverted to single-thread), and config tuning to match a reference paper&rsquo;s hyperparameters.</p>
<h2 id="usage">Usage</h2>
<p>The library provides a Julia API for defining CGP graphs, configuring evolutionary parameters, and running the evolutionary loop against custom environments.</p>
<h2 id="results">Results</h2>
<p>Looking back, this codebase captures a transitional moment where I was moving from scripting to library design.</p>
<ul>
<li><strong>The Ambition:</strong> Getting CGP graphs to learn Atari policies under the mixed-type regime (RGB-array inputs, scalar action outputs) was an ambitious undertaking for my software engineering skills at the time.</li>
<li><strong>The &ldquo;Legacy&rdquo; Code:</strong> The project relies on the now-deprecated Julia v0.6 and uses <code>eval(parse(...))</code> patterns for configuration (a significant performance anti-pattern in modern Julia).</li>
<li><strong>The Lesson:</strong> It taught me the difficulty of designing genetic operators that respect topological constraints, a lesson that informs my current understanding of optimization in structured spaces.</li>
</ul>
]]></content:encoded></item><item><title>FFTW Compiler in Haskell</title><link>https://hunterheidenreich.com/projects/fftw-compiler-haskell/</link><pubDate>Thu, 15 Mar 2018 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/projects/fftw-compiler-haskell/</guid><description>Reverse-engineering the genfft logic to generate optimized C kernels for Fast Fourier Transforms using Haskell metaprogramming.</description><content:encoded><![CDATA[<p>Written during my sophomore year, this project was an attempt to look inside the &ldquo;black box&rdquo; of one of the fastest Fourier transform libraries: <strong>FFTW</strong>.</p>
<h2 id="overview">Overview</h2>
<p>I sought to replicate the logic of FFTW&rsquo;s <code>genfft</code>: a metaprogram that generates straight-line, highly optimized C code. The goal was to understand how abstract algebra (group theory) could be translated into efficient machine code through symbolic manipulation.</p>
<h2 id="features">Features</h2>
<p>This was my first deep dive into <strong>functional metaprogramming</strong> and <strong>compiler theory</strong>:</p>
<ul>
<li><strong>Symbolic AST:</strong> Modeled mathematical operations as a Directed Acyclic Graph (DAG) in Haskell (<code>data Node</code>), separating the <em>definition</em> of the math from its <em>execution</em>.</li>
<li><strong>Algebraic Simplification:</strong> Implemented a symbolic optimization pass that pruned operations at compile-time (e.g., eliminating multiplications by $1$, $0$, or $-1$) before code generation.</li>
<li><strong>Monadic State Management:</strong> Used Haskell&rsquo;s <code>State</code> Monad to manage the graph construction and memoization, ensuring common subexpressions (like reusable cosine factors) were calculated only once.</li>
<li><strong>Code Generation:</strong> The system outputted unrolled, straight-line C code (e.g., <code>fftw4.c</code>), mimicking the &ldquo;codelets&rdquo; used by the actual FFTW library.</li>
</ul>
<h2 id="usage">Usage</h2>
<p>The compiler is run via the command line, taking the desired FFT size as input and outputting the optimized C code.</p>
<h2 id="results">Results</h2>
<p>Looking back, this project represents a pivotal moment where I moved from &ldquo;writing programs&rdquo; to &ldquo;writing tools that write programs.&rdquo;</p>
<ul>
<li><strong>The &ldquo;Magic&rdquo;:</strong> It demystified high-performance computing. I learned that speed often comes from unrolling recursion and managing register pressure at compile time alongside writing fast loops.</li>
<li><strong>The &ldquo;Rough Edges&rdquo;:</strong> The scheduler (coloring nodes Red/Blue for register allocation) was a heuristic approximation of the optimal Aho-Johnson-Ullman algorithm.</li>
<li><strong>Legacy:</strong> The core lesson that domain-specific compilers can outperform hand-tuned generic code remains relevant to my current work in optimizing scientific computing kernels.</li>
</ul>
]]></content:encoded></item><item><title>Term Schedule Optimizer</title><link>https://hunterheidenreich.com/projects/term-schedule-optimizer/</link><pubDate>Wed, 15 Feb 2017 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/projects/term-schedule-optimizer/</guid><description>A constraint satisfaction solver built to generate conflict-free university schedules from web-scraped course data.</description><content:encoded><![CDATA[<p>A Python-based automation tool I wrote as a freshman to solve the &ldquo;Term Master Schedule&rdquo; problem (and used throughout my undergrad from 2016 to 2020).</p>
<h2 id="overview">Overview</h2>
<p>Manually creating a university schedule involves solving a <strong>Constraint Satisfaction Problem (CSP)</strong> with multiple variables:</p>
<ul>
<li><strong>Hard Constraints:</strong> No time overlaps between classes.</li>
<li><strong>Soft Constraints:</strong> Preferences for &ldquo;no 8 AMs,&rdquo; specific lunch breaks, or maximizing free days.</li>
</ul>
<p>The naive approach (manually checking every possible combination) becomes intractable as the number of courses and sections grows.</p>
<h2 id="features">Features</h2>
<p>I built a script that:</p>
<ol>
<li><strong>Scraped Data:</strong> Parsed the Drexel WebTMS (Term Master Schedule) using <code>lxml</code> to build a localized dataset of course availability.</li>
<li><strong>Solved for X:</strong> Implemented a <strong>recursive backtracking algorithm</strong> to generate every valid schedule permutation that satisfied user-defined constraints.</li>
</ol>
<h3 id="the-algorithm">The Algorithm</h3>
<p>The core of this project is a <code>recursive_generator</code> function that implements a valid CSP solver using backtracking. It performs a recursive depth-first search that:</p>
<ol>
<li>Takes a set of variables (courses).</li>
<li>Checks constraints (time overlaps, lunch hours, max classes per day).</li>
<li>Backtracks when a branch fails.</li>
</ol>
<p>It is the same backtracking pattern used in everything from Sudoku solvers to compiler register allocation.</p>
<h2 id="usagegameplay">Usage/Gameplay</h2>
<p>The tool is run via the command line, taking a list of desired courses and outputting valid schedule combinations.</p>
<h2 id="results">Results</h2>
<p>This tool saved me (and several friends) hours of planning time each quarter. While the scraping logic was fragile (dependent on 2017 HTML structures), the core logic (a depth-first search through the state space of possible schedules) remains a fundamental algorithmic pattern.</p>
]]></content:encoded></item></channel></rss>