<?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>Embeddings on Hunter Heidenreich | Senior AI Research Scientist</title><link>https://hunterheidenreich.com/tags/embeddings/</link><description>Recent content in Embeddings 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, 02 Aug 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://hunterheidenreich.com/tags/embeddings/index.xml" rel="self" type="application/rss+xml"/><item><title>What Surprised Me About Aligning Pictures of Molecules</title><link>https://hunterheidenreich.com/posts/aligning-pictures-of-molecules/</link><pubDate>Sun, 02 Aug 2026 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/posts/aligning-pictures-of-molecules/</guid><description>Two alignment objectives compared under a frozen and then a trainable vision backbone, a metric that scored a perfect model at chance, and a reversal.</description><content:encoded><![CDATA[<p>The <a href="https://arxiv.org/abs/2510.18900">MIST paper</a> makes a claim I wanted to test from an angle its authors did not take. They show that their model&rsquo;s embedding space organizes chemical concepts along physically meaningful directions. Lipinski&rsquo;s Rule of Five is linearly decodable from frozen activations. Unsupervised projections of the embeddings separate aromatic from anti-aromatic compounds along Hückel&rsquo;s rule, and none of that was labelled during training.</p>
<p>All of that structure is derived from a <a href="/notes/chemistry/molecular-representations/notations/smiles/">SMILES</a> string.</p>
<p>Molecules are also drawn. A structure diagram carries the same topology a chemist reads directly off the page, in a form no language model ever sees. So I wanted to know whether MIST&rsquo;s geometry is reachable from pixels, or whether it is a property of the string.</p>
<p>There are two standard ways to teach one model to land where another one does. You can push negatives apart with a contrastive loss, or you can skip the negatives and regress the target directly. I expected the predictive one to transfer better to real drawings, because a contrastive objective can exploit shortcuts that only exist inside a training batch. I wrote that down before running anything.</p>
<p>It held, then it reversed, and the mechanism I had named for it was wrong in both cases.</p>
<h2 id="what-i-built">What I Built</h2>
<p>One vision tower, one frozen text tower, and a single linear map between them.</p>
<table>
	<thead>
			<tr>
					<th></th>
					<th></th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Vision tower</td>
					<td><a href="https://arxiv.org/abs/2304.07193">DINOv2</a> ViT-S/14 with registers, 21,629,952 parameters, 384-d output</td>
			</tr>
			<tr>
					<td>Text tower</td>
					<td>MIST-28M, frozen throughout, pooled <code>last_hidden_state[:, 0, :]</code>, 512-d output</td>
			</tr>
			<tr>
					<td>Head</td>
					<td>one linear map, 384 to 512, 197,120 parameters</td>
			</tr>
			<tr>
					<td>Training data</td>
					<td>1M PubChem molecules, about 2M <a href="https://github.com/OBrink/RanDepict">RanDepict</a> depictions at 224px</td>
			</tr>
			<tr>
					<td>Schedule</td>
					<td>24 epochs, batch 256</td>
			</tr>
	</tbody>
</table>
<p>Arm A optimizes the <a href="https://arxiv.org/abs/2303.15343">SigLIP</a> sigmoid pairwise loss. Arm B regresses the frozen target in latent space with a smooth-L1 loss and no negatives, which is the <a href="https://arxiv.org/abs/2301.08243">I-JEPA</a> move applied as an alignment head rather than as pretraining. Everything else is held identical: same molecules, same splits, same seed, same schedule, same evaluation, checked by an assertion before any table prints. Every number below is one seed.</p>
<p>Two details in the setup are load-bearing.</p>
<p>The pooling is MIST&rsquo;s own. Their embedding is the last-layer hidden state at the first token, so anything else measures a different space. Loading the checkpoint with <code>AutoModel</code> also attaches a randomly initialized pooler unless you ask it not to, and <code>pooler_output</code> from that pooler returns plausible noise.</p>
<p>The contrastive labels come from molecular identity rather than batch position. Two rows in a batch can be depictions of the same molecule, and treating them as negatives because they sit at different indices would penalize the model for being right. That detail matters more than it looks, and I will come back to it.</p>
<p>This is not an <a href="/posts/what-is-ocsr/">OCSR</a> contribution. Reading a molecule out of a picture is a mature field, and MolScribe, MolGrapher, DECIMER and Img2Mol all do it well. What is here is a controlled experiment about alignment objectives that happens to run on a domain with a real evaluation surface.</p>
<p>That domain has a catch worth stating early, because it shapes which number is the result. The training depictions are rendered from SMILES strings. A picture drawn from a string carries no information the string did not already have, so the in-distribution task is closer to inverting a renderer than to reading chemistry. Transfer to depictions that came from the world is the part that tests something. That is why the out-of-distribution slice is the headline and the in-distribution number is context.</p>
<p>I came to MIST from the tokenizer side. I had published <a href="/research/bpe-unigram-lm-smiles-vocabularies/">a controlled comparison of BPE and Unigram-LM over chemistry SMILES</a> a few weeks earlier, and MIST is a SMILES foundation model whose headline contribution is <a href="/notes/chemistry/molecular-representations/notations/smirk-tokenization-molecular-models/">its own tokenizer</a>. I was reading the paper closely for that reason and stayed for the embedding geometry.</p>
<h3 id="what-i-registered-in-advance">What I Registered In Advance</h3>
<p>Three predictions, committed before any training run existed:</p>
<blockquote>
<ol>
<li>Both arms will be near-ceiling on in-distribution synthetic retrieval, and that number on its own will mean almost nothing.</li>
<li>The arms will separate, if at all, on the WildMol-10k OOD slice and the scaffold-split linear probe. That gap is the result.</li>
<li>Arm B is expected to hold up better OOD, on the reasoning that regressing a fixed target cannot exploit in-batch shortcuts the way a contrastive objective can. This is a guess and is written down so it can be wrong in public.</li>
</ol>
</blockquote>
<p>I also registered what would count as a clean negative and ship as the result: both arms at or near chance on the OOD slice and the probe, with all baselines behaving correctly. That sentence turns out to matter more than the predictions do.</p>
<h3 id="what-had-to-pass-first">What Had To Pass First</h3>
<p>Four gates run before any headline number is believed, because a comparison between two arms says nothing if the harness scoring both of them is broken.</p>
<table>
	<thead>
			<tr>
					<th>gate</th>
					<th>result</th>
					<th>what it rules out</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>oracle retrieval, a perfect predictor</td>
					<td>R@1 = 1.0</td>
					<td>the retrieval harness itself</td>
			</tr>
			<tr>
					<td>MIST against Tanimoto similarity</td>
					<td>r = +0.42</td>
					<td>a target that carries no chemistry</td>
			</tr>
			<tr>
					<td>random-embedding control</td>
					<td>+0.0014 centered cosine</td>
					<td>a metric that leaks</td>
			</tr>
			<tr>
					<td>trivial image-statistics floor</td>
					<td>+0.0924 centered cosine</td>
					<td>mistaking ink for structure</td>
			</tr>
	</tbody>
</table>
<p>The image-statistics floor is the one that earns its keep below. It is what a model scores using nothing but coarse pixel statistics, and any headline has to clear it.</p>
<h2 id="a-perfect-model-scored-zero">A Perfect Model Scored Zero</h2>
<p>Raw cosine against MIST measures almost nothing. Its embeddings occupy a narrow cone, where two unrelated molecules sit at cosine 0.517 and a model that ignores its input entirely and emits the training centroid scores 0.720. So every cosine in this project is centered, and each side is centered by its own training-split mean:</p>
<p>$$ \mathrm{cc} = \cos\left(\hat{\mathbf{u}} - \bar{\hat{\mathbf{u}}}_{\text{train}},\ \mathbf{y} - \bar{\mathbf{y}}_{\text{train}}\right) $$</p>
<p>Chance is zero. Both centroids come from the training split, since centering a held-out set by its own mean leaks that set&rsquo;s geometry into its own score.</p>
<p>The version I shipped first subtracted the target centroid from both sides. That is valid only while the prediction sits at roughly the target&rsquo;s scale. Arm B&rsquo;s smooth-L1 pins it there. Arm A&rsquo;s loss L2-normalizes both sides internally, so it constrains the output norm not at all, and weight decay shrinks it with nothing opposing.</p>
<p>Take an oracle predictor $\hat{\mathbf{u}} = s\mathbf{y}$, whose true cosine is exactly 1 for every $s &gt; 0$:</p>
<table>
	<thead>
			<tr>
					<th>$s$</th>
					<th>$\lVert\hat{\mathbf{u}}\rVert$</th>
					<th>centered by target</th>
					<th>centered by own mean</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>1.00</td>
					<td>22.28</td>
					<td>+1.0000</td>
					<td>+0.9999</td>
			</tr>
			<tr>
					<td>0.50</td>
					<td>11.14</td>
					<td>+0.6100</td>
					<td>+0.9999</td>
			</tr>
			<tr>
					<td>0.10</td>
					<td>2.23</td>
					<td>+0.0453</td>
					<td>+0.9999</td>
			</tr>
			<tr>
					<td>0.045</td>
					<td>1.00</td>
					<td><strong>-0.0103</strong></td>
					<td>+0.9999</td>
			</tr>
	</tbody>
</table>
<p>A perfect model emitting unit-norm vectors scored below chance.</p>
<p>On the real 20K run, that defect scored a working contrastive model at +0.1088, inside noise of the +0.1058 image-statistics floor. Arm A&rsquo;s head was emitting norm 6.35 against MIST&rsquo;s 22.28. Under the corrected metric the same checkpoint scores +0.3052.</p>
<p>The uncomfortable part is what that number was. I had registered, in advance, that both arms landing at the floor with every baseline behaving correctly would be a clean negative and would ship as the result. The defect produced precisely that. Every exit criterion passed.</p>
<p>No test caught it. What caught it was asking what a perfect model would score under this metric, which is a question whose answer is knowable before you ask it.</p>
<p>Registering a prediction stops the goalposts moving once data exists. It does nothing at all about a defect that happens to confirm the prediction, and it makes that case more expensive rather than less, because the incentive to accept a number and stop looking is strongest exactly where you said the number would be.</p>
<p>There was a second defect of the same shape waiting. Had the contrastive labels come from batch position instead of molecular identity, the model would have been penalized for putting two depictions of one molecule in the same place. That depresses contrastive transfer and leaves predictive untouched, because only the contrastive loss reads other rows in the batch, which is prediction 3 arriving as an artifact of the label matrix.</p>
<h2 id="the-data-ran-out">The Data Ran Out</h2>
<p>With the backbone frozen, I fitted a log-linear law to the closed-form ridge ceiling over 1K to 16K molecules. It described that range well, at r = 0.9906. Extrapolated, it said 1M molecules would reach +0.600.</p>















<figure class="post-figure center ">
    <img src="/img/molecular-depiction-alignment/fig5-scaling-law.webp"
         alt="A line chart of ridge ceiling against molecule count on a log axis, with a fitted line extrapolated to one million and a measured point falling well below it"
         title="A line chart of ridge ceiling against molecule count on a log axis, with a fitted line extrapolated to one million and a measured point falling well below it"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption"><strong>The law was accurate where it was fitted and missed by 0.077 a decade and a half out.</strong> Fifty times the molecules bought +0.020 where the extrapolation predicted +0.088. The implied slope falls from 0.0517 to 0.0117 per decade, so another +0.05 would need roughly ten billion molecules.</figcaption>
    
</figure>

<p>Going from 796K to 1.6M depictions bought +0.0002.</p>
<p>The mechanism is in the features rather than the sample. On these images, 54.3% of DINOv2&rsquo;s feature variance is depiction style rather than molecular identity. Two renders of the same molecule sit at cosine 0.857, and two different molecules sit at 0.809, which leaves very little room between &ldquo;same structure&rdquo; and &ldquo;different structure&rdquo; for a linear head to work with.</p>















<figure class="post-figure center ">
    <img src="/img/molecular-depiction-alignment/fig6-style-pair.webp"
         alt="Two renderings of the same molecule side by side, one drawn with bold lines and implicit carbons, the other with thin grey lines and every carbon atom labelled"
         title="Two renderings of the same molecule side by side, one drawn with bold lines and implicit carbons, the other with thin grey lines and every carbon atom labelled"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption"><strong>One molecule, two renders from the training set.</strong> A chemist reads these as identical. Frozen DINOv2 puts same-molecule pairs at cosine 0.857 and different-molecule pairs at 0.809, and 54.3% of its feature variance on this data is drawing style.</figcaption>
    
</figure>

<p>A linear head can reorganize what the backbone encodes. It cannot manufacture what the backbone discarded. That showed up directly in the probes, where alignment helped on the tasks whose property the frozen features already carried and did nothing at all on three of seven.</p>
<p>This is the second prediction I made in advance and missed, and it was the more expensive one, because I had been about to spend on data.</p>
<h2 id="unfreezing-reversed-my-own-prediction">Unfreezing Reversed My Own Prediction</h2>
<p>Letting the backbone move changes the picture. I swept two trainable modes rather than picking one: LoRA at rank 16 on the attention projections of all twelve blocks, and the top four blocks plus the final norm. The top-blocks mode won on every layer, and LoRA was also 1.84x slower per step despite training 16x fewer parameters, because backward cost tracks how deep the pass goes rather than how many parameters update.</p>















<figure class="post-figure center ">
    <img src="/img/molecular-depiction-alignment/fig2-eval-layers.webp"
         alt="Three panels comparing frozen and unfrozen results for in-distribution retrieval, out-of-distribution retrieval, and centered cosine, each on its own scale"
         title="Three panels comparing frozen and unfrozen results for in-distribution retrieval, out-of-distribution retrieval, and centered cosine, each on its own scale"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption"><strong>Each layer moves, and by very different factors.</strong> In-distribution retrieval 9.6x, out-of-distribution 11.1x, centered cosine 1.7x. Distractor difficulty is matched between the two regimes rather than assumed, at median Tanimoto 0.348 against 0.349 in-distribution.</figcaption>
    
</figure>

<p>The out-of-distribution gate is what makes this mean something, and it matters because an earlier lever failed it. Running the backbone at its native 518px instead of 224 improved every synthetic-image metric, several by multiple standard deviations, and moved the real-depiction metric by less than one. That lever was fitting RanDepict&rsquo;s particular ink rather than learning chemistry. Unfreezing does not behave that way.</p>
<p>Then the registered prediction inverted.</p>















<figure class="post-figure center ">
    <img src="/img/molecular-depiction-alignment/fig3-prediction-reversal.webp"
         alt="Two paired slope panels showing retrieval from synthetic to real depictions, with the predictive arm holding flat under a frozen backbone and the contrastive arm winning under an unfrozen one"
         title="Two paired slope panels showing retrieval from synthetic to real depictions, with the predictive arm holding flat under a frozen backbone and the contrastive arm winning under an unfrozen one"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption"><strong>Frozen, the predictive arm holds and the contrastive arm drops 34%. Unfrozen, it inverts.</strong> Contrastive drops 23.3% against predictive&rsquo;s 42.6% and wins out of distribution outright, 0.4555 against 0.2847.</figcaption>
    
</figure>

<p>The ordering was a property of the frozen bottleneck rather than of the objectives. Give the contrastive objective a backbone it can actually shape and it is the one that degrades less.</p>
<p>Had I only run the frozen half, I would have published a confirmed prediction with a mechanism attached, and the mechanism would have been wrong. The number was fine. The explanation underneath it was not, and nothing in the frozen regime could have told me.</p>
<p>Prediction 1 was wrong outright, which is worth recording since I registered it as the boring one. I expected in-distribution retrieval to sit near ceiling and carry no information. It came in at 0.0617 and 0.0310 against a 0.0156 chance floor, which is why it is reported throughout rather than waved off.</p>















<figure class="post-figure center ">
    <img src="/img/molecular-depiction-alignment/fig4-probe-gap-closed.webp"
         alt="A bar chart of seven probe tasks showing the fraction of the DINOv2 to MIST gap closed by the frozen and unfrozen models, with a dashed line at parity"
         title="A bar chart of seven probe tasks showing the fraction of the DINOv2 to MIST gap closed by the frozen and unfrozen models, with a dashed line at parity"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption"><strong>All three of the frozen regime&rsquo;s nulls break.</strong> ESOL, Lipophilicity and Tox21 SR-MMP were the evidence for &lsquo;alignment only reorganizes&rsquo;. A movable backbone can acquire a property the frozen features had discarded.</figcaption>
    
</figure>

<p>On one fixed checkpoint, the aligned image embedding out-probes MIST-direct on 6 of 7 tasks, losing only BBBP. Best-of-eight beats it on 7 of 7, and I am not quoting that as the result because it is selection over eight tries. The honest reading is that MIST bounds MIST-reconstruction rather than every downstream task where vision carries independent signal.</p>
<h2 id="the-fairest-rule-picked-the-worst-checkpoint">The Fairest Rule Picked the Worst Checkpoint</h2>
<p>The two arms have losses on different scales, so selecting each on its own loss would compare two selection procedures rather than two objectives. I selected on centered cosine instead, the one metric both arms are measured by. Neutral by construction.</p>
<p>It chose epoch 1 of 24 for the contrastive arm, in both trainable modes.</p>















<figure class="post-figure center ">
    <img src="/img/molecular-depiction-alignment/fig1-training-curves.webp"
         alt="Validation centered cosine against epoch for all four runs, with the contrastive arm peaking at the first epoch and decaying while the predictive arm climbs"
         title="Validation centered cosine against epoch for all four runs, with the contrastive arm peaking at the first epoch and decaying while the predictive arm climbs"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption"><strong>The contrastive arm&rsquo;s centered cosine peaks almost immediately and decays for the rest of training</strong>, while its own loss falls sevenfold and every other measure improves. In-distribution retrieval at the selected epoch is 0.2265 against 0.5938 at the final one, a factor of 2.6.</figcaption>
    
</figure>

<p>I had written this down on the first day of the project, at the milestone where the two arms first ran side by side:</p>
<blockquote>
<p>Selecting on it hands Arm A its worst retrieval checkpoint. Selecting on retrieval instead would reverse the ranking and would be equally defensible and equally partial.</p>
</blockquote>
<p>And in the same entry, on why I was recording it at all:</p>
<blockquote>
<p>Recording it now, at M3, because it is exactly the kind of thing that gets quietly resolved in whichever direction the first table happened to point.</p>
</blockquote>
<p>I scoped that observation as measured outside the contrastive arm&rsquo;s viable regime, which was correct at the time. At 20K molecules there is no batch size that is both a real contrastive batch and a small fraction of the dataset, so the arm was running at 256 while SigLIP&rsquo;s own calibration assumes 16,384. Rebuilding at 1M fixed that, and the failure happened anyway, in the regime where it counted.</p>
<p>The obvious objection is that the constraint itself was the cause. Holding the learning rate, the schedule and the checkpoint rule identical across two objectives that optimize different things does not make a comparison fair, it handicaps whichever arm does not match the shared choice.</p>
<p>The repair would be to let each arm carry its own schedule, and gradient accumulation is the specific one that was on the table. I did not add it, and I still think that was right. Accumulation enlarges the contrastive arm&rsquo;s negative pool and does nothing for the predictive one, so adding it converts a comparison of objectives into a comparison of training budgets. That is a second bias rather than a smaller one.</p>
<p>What I did not do was change the rule after seeing what it cost. Retrofitting a selection criterion once results exist is the specific thing pre-registration exists to prevent, so both epochs are reported instead.</p>
<p>Three shared choices ended up bending against the contrastive arm, all in the same direction. Weight decay at 0.05 against a scale-invariant loss, which is what produced the metric defect. Batch 256 against a calibration assuming 16,384. A selection metric that measures direction agreement, which is close to what the predictive arm optimizes directly.</p>
<p>It won the layer I had named in advance as the deciding one anyway, 0.4555 against 0.2847. So the measured gap is a floor rather than an estimate.</p>
<h2 id="what-i-would-not-trust-here">What I Would Not Trust Here</h2>
<p>Three things would change a conclusion above, in order of how much.</p>
<p><strong>The probe splits shift in composition.</strong> ESOL&rsquo;s training split is 35% acyclic molecules against 0% of validation and test, and Tox21 is about 32%. Acyclic molecules have no Bemis-Murcko scaffold, so a scaffold split places them all in one group and that group is large enough to land in train. ESOL is the largest probe gain in this post, and it was scored on a held-out set with none of the molecules that make up a third of what it trained on.</p>
<p><strong>One seed, and the sigmas are uneven.</strong> The only repeats in the project are a 5-seed frozen sweep at 20K. Arm A retrieval sigma runs .002 to .005 and BBBP .004 to .011. The retrieval orderings clear that by roughly two orders of magnitude and are safe. Individual probe cells do not clear it, and several rows show test scores above validation, which is what noise on a small scaffold-split test set looks like.</p>
<p><strong>The predictive arm was truncated.</strong> It was still rising at epoch 24 in both modes, and 24 epochs was inherited from the frozen regime where it was enough. Its numbers are a lower bound, which cuts against this post&rsquo;s own conclusion.</p>
<h2 id="conclusion-one-number-cannot-rank-two-objectives">Conclusion: One Number Cannot Rank Two Objectives</h2>
<p>The comparison never resolved to a winner in the way I expected when I started, and the reason is more interesting than a winner would have been. Under a frozen backbone the predictive arm holds up better, and that ordering is a fact about the bottleneck. Under a trainable one the contrastive arm wins out of distribution, and it does so while carrying every shared-procedure handicap.</p>
<p>Three of the four things above were numbers I initially believed. A metric that scored a perfect model below chance, a scaling law that was accurate everywhere I had fitted it, and a selection rule that was neutral by construction. Each looked fine, and each was checkable in advance by asking what a known answer should be.</p>
<p>The one that still bothers me is the metric, because it produced the exact result I had written down as shippable. Pre-registration protected me from moving the goalposts and did nothing about that.</p>
<p><em>Code, weights and data are public. The <a href="https://github.com/hunter-heidenreich/molecular-depiction-alignment">repository</a> carries the full results, the harness gates and the pre-registration verbatim. The two aligned models are on Hugging Face as <a href="https://huggingface.co/hheiden/dinov2-mist-molecular-depiction-contrastive">contrastive</a> and <a href="https://huggingface.co/hheiden/dinov2-mist-molecular-depiction-predictive">predictive</a>, and the <a href="https://huggingface.co/datasets/hheiden/molecular-depiction-pairs-20k">20K depiction set</a> is published so the comparison can be re-run without standing up the rendering environment.</em></p>
]]></content:encoded></item><item><title>Molecular Depiction Alignment: Contrastive vs Predictive</title><link>https://hunterheidenreich.com/projects/molecular-depiction-alignment/</link><pubDate>Sun, 02 Aug 2026 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/projects/molecular-depiction-alignment/</guid><description>A controlled comparison of contrastive and predictive alignment: one vision tower into a frozen chemistry encoder, everything but the objective held identical.</description><content:encoded><![CDATA[<h2 id="overview">Overview</h2>
<p>Two ways to align an image of a molecular structure diagram into the embedding space of a frozen chemistry language model, compared on one data and evaluation stack. A <a href="https://arxiv.org/abs/2304.07193">DINOv2</a> ViT-S/14-reg vision tower, a frozen <a href="https://arxiv.org/abs/2510.18900">MIST-28M</a> text tower, and a 197,120-parameter linear map between them.</p>
<p>Arm A optimizes the SigLIP sigmoid pairwise loss. Arm B regresses the frozen target directly in latent space with no negatives. Everything else is held identical, and an assertion checks that before any comparison table prints.</p>
<p>The comparison is the deliverable. The models are how it was obtained.</p>
<h2 id="results">Results</h2>
<p>Retrieval R@1 against 64-molecule galleries of nearest-Tanimoto distractors, chance 0.0156. Out-of-distribution is WildMol-10k, real depictions extracted from patents and papers, never trained on.</p>
<table>
	<thead>
			<tr>
					<th></th>
					<th>frozen backbone</th>
					<th></th>
					<th>trainable backbone</th>
					<th></th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td></td>
					<td>contrastive</td>
					<td>predictive</td>
					<td>contrastive</td>
					<td>predictive</td>
			</tr>
			<tr>
					<td>in-distribution</td>
					<td>0.0617</td>
					<td>0.0310</td>
					<td><strong>0.5938</strong></td>
					<td>0.4963</td>
			</tr>
			<tr>
					<td>out-of-distribution</td>
					<td>0.0410</td>
					<td>0.0310</td>
					<td><strong>0.4555</strong></td>
					<td>0.2847</td>
			</tr>
			<tr>
					<td>degradation to real</td>
					<td>-34%</td>
					<td>0%</td>
					<td><strong>-23%</strong></td>
					<td>-43%</td>
			</tr>
	</tbody>
</table>
<p>With the backbone frozen, the ceiling is the representation. Fifty times more data moved a closed-form ridge ceiling by +0.020 against +0.088 predicted by a log-linear law fitted at small scale, and 54.3% of DINOv2&rsquo;s feature variance on these images is depiction style rather than molecular identity.</p>
<p>Unfreezing moves retrieval 9.6x in-distribution and 11.1x out of distribution, and the pre-registered prediction reverses: the predictive arm transfers better under a frozen backbone and the contrastive arm wins outright once the backbone can move.</p>
<h2 id="features">Features</h2>
<ul>
<li><strong>Pre-registered predictions</strong>, committed before any training run and quoted verbatim in the results with how each came out. One was wrong outright and one held then reversed.</li>
<li><strong>Four harness gates</strong> run before any headline number is believed: an oracle retrieval control, MIST against Tanimoto similarity, a random-embedding control, and a trivial image-statistics floor.</li>
<li><strong>Seven linear-probe points</strong> across five MoleculeNet datasets, on Bemis-Murcko scaffold splits committed as build artifacts so a probe number is comparable across clones.</li>
<li><strong>An out-of-distribution slice</strong> of real literature depictions, deduplicated against every training set by InChIKey with a positive control confirming the check detects injected leakage.</li>
<li><strong>Open weights and data</strong>, with an export path that verifies the published weights are the same function of pixels as the checkpoint they came from.</li>
</ul>
<h2 id="usage">Usage</h2>
<p>The released weights need <code>timm</code> and <code>torch</code>, and nothing from this repository:</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> timm<span style="color:#f92672">,</span> torch
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>backbone <span style="color:#f92672">=</span> timm<span style="color:#f92672">.</span>create_model(
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;vit_small_patch14_reg4_dinov2.lvd142m&#34;</span>, pretrained<span style="color:#f92672">=</span><span style="color:#66d9ef">False</span>, num_classes<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>, img_size<span style="color:#f92672">=</span><span style="color:#ae81ff">224</span>
</span></span><span style="display:flex;"><span>)
</span></span><span style="display:flex;"><span>backbone<span style="color:#f92672">.</span>load_state_dict(torch<span style="color:#f92672">.</span>load(<span style="color:#e6db74">&#34;backbone.pt&#34;</span>, weights_only<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>))
</span></span><span style="display:flex;"><span>head <span style="color:#f92672">=</span> torch<span style="color:#f92672">.</span>nn<span style="color:#f92672">.</span>Linear(<span style="color:#ae81ff">384</span>, <span style="color:#ae81ff">512</span>)
</span></span><span style="display:flex;"><span>head<span style="color:#f92672">.</span>load_state_dict(torch<span style="color:#f92672">.</span>load(<span style="color:#e6db74">&#34;projection_head.pt&#34;</span>, weights_only<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>))
</span></span><span style="display:flex;"><span>backbone<span style="color:#f92672">.</span>eval(); head<span style="color:#f92672">.</span>eval()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">with</span> torch<span style="color:#f92672">.</span>no_grad():
</span></span><span style="display:flex;"><span>    embedding <span style="color:#f92672">=</span> head(backbone(pixels))   <span style="color:#75715e"># (batch, 512), in MIST space</span>
</span></span></code></pre></div><p>Comparing images to each other works with the above alone. Comparing an image to a molecule additionally needs MIST to embed that molecule.</p>
<p>Weights are on Hugging Face as <a href="https://huggingface.co/hheiden/dinov2-mist-molecular-depiction-contrastive">contrastive</a> and <a href="https://huggingface.co/hheiden/dinov2-mist-molecular-depiction-predictive">predictive</a>, and the <a href="https://huggingface.co/datasets/hheiden/molecular-depiction-pairs-20k">20K depiction set</a> is published so the comparison can be re-run without the rendering environment.</p>
<h2 id="retrospective">Retrospective</h2>
<p>Scoped to a couple of weekends, and complete rather than paused. There is no roadmap.</p>
<p>The parts worth keeping are methodological. A metric defect scored a working model at the pre-registered clean-negative floor with every exit criterion passing, and it was caught by asking what a perfect model would score rather than by a test. The arm-neutral checkpoint selection rule, chosen because it is the one scalar both arms are measured by, selected epoch 1 of 24 for the contrastive arm at a cost of 2.6x on in-distribution retrieval. That was reported rather than fixed, since changing a pre-registered rule after seeing results is what pre-registration exists to prevent.</p>
<p>Every v2 number is one seed. The only repeats in the project are a five-seed frozen sweep, and the retrieval orderings clear that noise floor by roughly two orders of magnitude while individual probe cells do not.</p>
<p>The code is Apache-2.0. The released weights carry research-only terms mirroring MIST&rsquo;s, since they were trained to predict its embeddings.</p>
]]></content:encoded></item><item><title>SpeechT5: Unified Speech-Text Pre-Training Framework</title><link>https://hunterheidenreich.com/notes/natural-language-processing/language-models/speecht5-unified-speech-text-pretraining/</link><pubDate>Sat, 11 Apr 2026 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/natural-language-processing/language-models/speecht5-unified-speech-text-pretraining/</guid><description>SpeechT5 introduces a shared encoder-decoder framework with cross-modal vector quantization for joint speech and text pre-training across six tasks.</description><content:encoded><![CDATA[<h2 id="a-unified-encoder-decoder-for-spoken-language-processing">A Unified Encoder-Decoder for Spoken Language Processing</h2>
<p>SpeechT5 is a <strong>Method</strong> paper that introduces a shared encoder-decoder pre-training framework for spoken language processing. Inspired by <a href="/notes/natural-language-processing/language-models/t5-text-to-text-transfer-transformer/">T5&rsquo;s</a> text-to-text paradigm, SpeechT5 reformulates all spoken language tasks as &ldquo;speech/text to speech/text&rdquo; problems. The framework uses modal-specific pre-nets and post-nets to interface between raw speech or text and a shared Transformer encoder-decoder, enabling a single pre-trained model to handle six downstream tasks: automatic speech recognition (ASR), text-to-speech synthesis (TTS), speech translation (ST), voice conversion (VC), speech enhancement (SE), and speaker identification (SID).</p>
<h2 id="bridging-the-gap-between-speech-and-text-pre-training">Bridging the Gap Between Speech and Text Pre-Training</h2>
<p>Prior speech pre-training work (wav2vec 2.0, HuBERT) suffered from two key limitations. First, these models learned speech representations from unlabeled audio alone, ignoring the complementary information in text data that is critical for cross-modal tasks like ASR and TTS. Second, they relied on encoder-only architectures with task-specific prediction heads, leaving the decoder un-pretrained for sequence-to-sequence generation tasks.</p>
<p>SpeechT5 addresses both gaps by (1) jointly pre-training on unlabeled speech and text data, and (2) using a full encoder-decoder architecture that benefits generation tasks directly. The approach builds on the observation that speech and text, despite their surface differences, share underlying semantic structure that a unified representation can capture.</p>
<h2 id="cross-modal-vector-quantization-for-alignment">Cross-Modal Vector Quantization for Alignment</h2>
<p>The core innovation in SpeechT5 is a cross-modal <a href="https://en.wikipedia.org/wiki/Vector_quantization">vector quantization</a> (VQ) mechanism that aligns speech and text representations into a shared semantic space. The architecture consists of three components:</p>
<p><strong>Shared encoder-decoder backbone.</strong> A Transformer with 12 encoder blocks and 6 decoder blocks (768-dim, 12 heads), using relative position embeddings.</p>
<p><strong>Modal-specific pre/post-nets.</strong> Six specialized networks handle the conversion between raw modalities and the shared representation space:</p>
<ul>
<li>Speech-encoder pre-net: a convolutional feature extractor (from wav2vec 2.0) downsampling raw waveforms</li>
<li>Speech-decoder pre-net: three FC layers with ReLU, processing 80-dimensional log Mel-filterbank features</li>
<li>Speech-decoder post-net: a linear layer predicting Mel features plus five 1D conv layers (256 channels) for residual refinement, with an x-vector speaker embedding concatenated for multi-speaker support</li>
<li>Text pre/post-nets: shared embedding layers mapping between character-level token indices and hidden states (768-dim)</li>
</ul>
<p><strong>Cross-modal vector quantization.</strong> A shared codebook $\mathbf{C}^{K}$ with $K$ learnable embeddings bridges the two modalities. Encoder outputs $\mathbf{u}_i$ are quantized via nearest-neighbor lookup:</p>
<p>$$
\mathbf{c}_i = \arg\min_{j \in [K]} | \mathbf{u}_i - \mathbf{c}_j |_2
$$</p>
<p>A proportion (10%) of contextual representations are randomly replaced with these quantized latent units before being fed to the decoder&rsquo;s cross-attention. This mixing forces the quantizer to capture cross-modal features. A diversity loss encourages full codebook utilization:</p>
<p>$$
\mathcal{L}_d = \frac{1}{K} \sum_{k=1}^{K} p_k \log p_k
$$</p>
<h3 id="pre-training-objectives">Pre-Training Objectives</h3>
<p>SpeechT5 combines three pre-training objectives:</p>
<p><strong>Speech pre-training</strong> uses two tasks. A bidirectional masked prediction loss $\mathcal{L}_{mlm}^{s}$ follows HuBERT&rsquo;s approach, masking 8% of timesteps in 10-step spans and predicting frame-level targets from an acoustic unit discovery model:</p>
<p>$$
\mathcal{L}_{mlm}^{s} = \sum_{n \in \mathcal{M}} \log p(\mathbf{z}_n \mid \hat{\mathbf{H}}, n)
$$</p>
<p>A reconstruction loss $\mathcal{L}_{1}^{s}$ minimizes the $L_1$ distance between predicted and original Mel-filterbank features, plus a binary cross-entropy stop-token loss $\mathcal{L}_{bce}^{s}$.</p>
<p><strong>Text pre-training</strong> uses BART-style denoising, masking 30% of text spans (Poisson $\lambda = 3.5$) and training with maximum likelihood estimation:</p>
<p>$$
\mathcal{L}_{mle}^{t} = \sum_{n=1}^{N^t} \log p(\mathbf{y}_n^t \mid \mathbf{y}_{&lt; n}^t, \hat{\mathbf{X}}^t)
$$</p>
<p>The full pre-training loss combines all components:</p>
<p>$$
\mathcal{L} = \mathcal{L}_{mlm}^{s} + \mathcal{L}_{1}^{s} + \mathcal{L}_{bce}^{s} + \mathcal{L}_{mle}^{t} + \gamma \mathcal{L}_d
$$</p>
<p>where $\gamma = 0.1$.</p>
<h2 id="evaluation-across-six-spoken-language-tasks">Evaluation Across Six Spoken Language Tasks</h2>
<p>SpeechT5 was evaluated on six downstream tasks, each using a different combination of the shared encoder-decoder and task-appropriate pre/post-nets:</p>
<h3 id="automatic-speech-recognition-asr">Automatic Speech Recognition (ASR)</h3>
<p>Fine-tuned on LibriSpeech 100h with joint <a href="https://en.wikipedia.org/wiki/Connectionist_temporal_classification">CTC</a>/attention decoding. The decoding objective maximizes a combination of decoder, CTC, and language model log-probabilities:</p>
<p>$$
\alpha \log P_{Dec} + (1 - \alpha) \log P_{CTC} + \beta \log P_{LM}
$$</p>
<p>where $\alpha = 0.5$ and $\beta = 1.0$ for the 100h setting (beam size 30). Results on the test sets:</p>
<table>
	<thead>
			<tr>
					<th>Model</th>
					<th>LM</th>
					<th>test-clean</th>
					<th>test-other</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>wav2vec 2.0 BASE</td>
					<td>-</td>
					<td>6.1</td>
					<td>13.3</td>
			</tr>
			<tr>
					<td>HuBERT BASE</td>
					<td>-</td>
					<td>5.8</td>
					<td>13.3</td>
			</tr>
			<tr>
					<td><strong>SpeechT5</strong></td>
					<td><strong>-</strong></td>
					<td><strong>4.4</strong></td>
					<td><strong>10.4</strong></td>
			</tr>
			<tr>
					<td>wav2vec 2.0 BASE</td>
					<td>Transf.</td>
					<td>2.6</td>
					<td>6.3</td>
			</tr>
			<tr>
					<td><strong>SpeechT5</strong></td>
					<td><strong>Transf.</strong></td>
					<td><strong>2.4</strong></td>
					<td><strong>5.8</strong></td>
			</tr>
	</tbody>
</table>
<h3 id="text-to-speech-synthesis-tts">Text-to-Speech Synthesis (TTS)</h3>
<p>Fine-tuned on LibriTTS 460h clean sets with HiFi-GAN vocoder:</p>
<table>
	<thead>
			<tr>
					<th>Model</th>
					<th>Naturalness</th>
					<th>MOS</th>
					<th>CMOS</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Ground Truth</td>
					<td>-</td>
					<td>3.87 ± 0.04</td>
					<td>-</td>
			</tr>
			<tr>
					<td>Baseline</td>
					<td>2.76</td>
					<td>3.56 ± 0.05</td>
					<td>0</td>
			</tr>
			<tr>
					<td><strong>SpeechT5</strong></td>
					<td><strong>2.91</strong></td>
					<td><strong>3.65 ± 0.04</strong></td>
					<td><strong>+0.290</strong></td>
			</tr>
	</tbody>
</table>
<h3 id="speech-translation-st">Speech Translation (ST)</h3>
<p>Evaluated on MUST-C English-to-German and English-to-French:</p>
<table>
	<thead>
			<tr>
					<th>Model</th>
					<th>EN-DE</th>
					<th>EN-FR</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Fairseq ST</td>
					<td>22.70</td>
					<td>32.90</td>
			</tr>
			<tr>
					<td>Adapter Tuning</td>
					<td>24.63</td>
					<td>34.98</td>
			</tr>
			<tr>
					<td>Baseline (HuBERT init)</td>
					<td>23.43</td>
					<td>33.76</td>
			</tr>
			<tr>
					<td><strong>SpeechT5</strong></td>
					<td><strong>25.18</strong></td>
					<td><strong>35.30</strong></td>
			</tr>
	</tbody>
</table>
<h3 id="voice-conversion-vc">Voice Conversion (VC)</h3>
<p>Evaluated on CMU Arctic:</p>
<table>
	<thead>
			<tr>
					<th>Model</th>
					<th>WER (bdl→slt)</th>
					<th>MCD (bdl→slt)</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>VTN w/ TTS</td>
					<td>7.6%</td>
					<td>6.33</td>
			</tr>
			<tr>
					<td>Many-to-many VTN</td>
					<td>-</td>
					<td>6.13</td>
			</tr>
			<tr>
					<td><strong>SpeechT5</strong></td>
					<td><strong>7.8%</strong></td>
					<td><strong>5.93</strong></td>
			</tr>
	</tbody>
</table>
<h3 id="speech-enhancement-se">Speech Enhancement (SE)</h3>
<p>On WHAM! dataset, SpeechT5 reduced WER from 76.1% (noisy) to 8.9%, a relative 9% improvement over the baseline&rsquo;s 10.9%.</p>
<h3 id="speaker-identification-sid">Speaker Identification (SID)</h3>
<p>On VoxCeleb1, SpeechT5 achieved 96.49% accuracy, outperforming HuBERT LARGE at 90.33% (from SUPERB) and SpeechNet multi-task at 87.90%.</p>
<h2 id="ablation-study-and-key-findings">Ablation Study and Key Findings</h2>
<p>The ablation study reveals the contribution of each pre-training component:</p>
<table>
	<thead>
			<tr>
					<th>Model</th>
					<th>ASR (clean)</th>
					<th>ASR (other)</th>
					<th>VC (MCD)</th>
					<th>SID (ACC)</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>SpeechT5</td>
					<td>4.4</td>
					<td>10.7</td>
					<td>5.93</td>
					<td>96.49%</td>
			</tr>
			<tr>
					<td>w/o Speech PT</td>
					<td>-</td>
					<td>-</td>
					<td>6.49</td>
					<td>38.61%</td>
			</tr>
			<tr>
					<td>w/o Text PT</td>
					<td>5.4</td>
					<td>12.8</td>
					<td>6.03</td>
					<td>95.60%</td>
			</tr>
			<tr>
					<td>w/o Joint PT</td>
					<td>4.6</td>
					<td>11.3</td>
					<td>6.18</td>
					<td>95.54%</td>
			</tr>
			<tr>
					<td>w/o $\mathcal{L}_{mlm}^{s}$</td>
					<td>7.6</td>
					<td>22.4</td>
					<td>6.29</td>
					<td>90.91%</td>
			</tr>
	</tbody>
</table>
<p>Key findings:</p>
<ol>
<li><strong>Speech pre-training is critical</strong>: without it, ASR fails to converge entirely, and SID accuracy drops to 38.61%.</li>
<li><strong>Text pre-training complements speech</strong>: removing it degrades ASR by ~20% relative, confirming that textual knowledge transfers to speech tasks.</li>
<li><strong>Joint pre-training enables cross-modal transfer</strong>: the vector quantization approach is essential for modality-bridging tasks like ASR.</li>
<li><strong>The masked prediction loss $\mathcal{L}_{mlm}^{s}$ is the most important single component</strong>, responsible for learning strong acoustic features.</li>
</ol>
<p>The authors note limitations in the current scope (English-only, BASE model size) and propose scaling to larger models and multilingual settings as future work.</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>Speech pre-training</td>
					<td>LibriSpeech</td>
					<td>960 hours</td>
					<td>Full training set</td>
			</tr>
			<tr>
					<td>Text pre-training</td>
					<td>LibriSpeech LM text</td>
					<td>400M sentences</td>
					<td>Normalized language model text</td>
			</tr>
			<tr>
					<td>ASR fine-tuning</td>
					<td>LibriSpeech</td>
					<td>100h / 960h subsets</td>
					<td></td>
			</tr>
			<tr>
					<td>TTS fine-tuning</td>
					<td>LibriTTS</td>
					<td>460h clean sets</td>
					<td></td>
			</tr>
			<tr>
					<td>ST fine-tuning</td>
					<td>MUST-C</td>
					<td>EN-DE, EN-FR</td>
					<td></td>
			</tr>
			<tr>
					<td>VC fine-tuning</td>
					<td>CMU Arctic</td>
					<td>4 speakers</td>
					<td>bdl, clb, slt, rms</td>
			</tr>
			<tr>
					<td>SE fine-tuning</td>
					<td>WHAM!</td>
					<td>16 kHz max</td>
					<td>enhance-single task</td>
			</tr>
			<tr>
					<td>SID fine-tuning</td>
					<td>VoxCeleb1</td>
					<td>100k+ utterances</td>
					<td>1,251 speakers</td>
			</tr>
	</tbody>
</table>
<h3 id="algorithms">Algorithms</h3>
<ul>
<li>Optimizer: Adam with warmup (8% of steps) to peak LR $2 \times 10^{-4}$, then linear decay</li>
<li>Speech masking: 8% of timesteps, 10-step spans</li>
<li>Text masking: 30% of spans, Poisson $\lambda = 3.5$</li>
<li>Vector quantization: 2 codebooks × 100 entries = $10^4$ theoretical maximum codes</li>
<li>CTC/attention joint decoding for ASR (beam size 30)</li>
<li>HiFi-GAN vocoder for TTS and SE waveform generation</li>
<li>Parallel WaveGAN vocoder for VC</li>
</ul>
<h3 id="fine-tuning-hyperparameters">Fine-Tuning Hyperparameters</h3>
<table>
	<thead>
			<tr>
					<th>Task</th>
					<th>GPUs</th>
					<th>Steps</th>
					<th>Peak LR</th>
					<th>Batch (per GPU)</th>
					<th>Schedule</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>ASR (100h)</td>
					<td>8×V100</td>
					<td>80k</td>
					<td>6e-5</td>
					<td>256k audio samples</td>
					<td>Warmup 10%, hold 40%, linear decay</td>
			</tr>
			<tr>
					<td>ASR (960h)</td>
					<td>8×V100</td>
					<td>320k</td>
					<td>1.3e-4</td>
					<td>256k audio samples</td>
					<td>Warmup 10%, hold 40%, linear decay</td>
			</tr>
			<tr>
					<td>TTS</td>
					<td>8×V100</td>
					<td>120k</td>
					<td>4e-4</td>
					<td>45k tokens</td>
					<td>Warmup 10k steps, inv. sqrt decay</td>
			</tr>
			<tr>
					<td>ST</td>
					<td>8×V100</td>
					<td>80k</td>
					<td>-</td>
					<td>-</td>
					<td>Warmup 10k steps</td>
			</tr>
			<tr>
					<td>VC</td>
					<td>8×V100</td>
					<td>60k</td>
					<td>1e-4</td>
					<td>20k tokens</td>
					<td>6k warmup, inv. sqrt decay</td>
			</tr>
			<tr>
					<td>SE</td>
					<td>8×V100</td>
					<td>100k</td>
					<td>1e-4</td>
					<td>16k tokens</td>
					<td>10k warmup, inv. sqrt decay</td>
			</tr>
			<tr>
					<td>SID</td>
					<td>8×V100</td>
					<td>60k</td>
					<td>5e-4</td>
					<td>64 segments (3s each)</td>
					<td>Triangular cyclical (1e-8 to 5e-4)</td>
			</tr>
	</tbody>
</table>
<h3 id="models">Models</h3>
<ul>
<li>Encoder: 12 Transformer blocks (768-dim, 3072 FFN, 12 heads)</li>
<li>Decoder: 6 Transformer blocks (same dimensions)</li>
<li>Speech-encoder pre-net: 7 conv blocks (512 channels, strides [5,2,2,2,2,2,2], kernels [10,3,3,3,3,2,2])</li>
<li>Code and pre-trained models available at <a href="https://github.com/microsoft/SpeechT5">github.com/microsoft/SpeechT5</a> (MIT license)</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/microsoft/SpeechT5">microsoft/SpeechT5</a></td>
					<td>Code</td>
					<td>MIT</td>
					<td>Official Fairseq-based implementation</td>
			</tr>
			<tr>
					<td>Pre-trained models (via repo)</td>
					<td>Model</td>
					<td>MIT</td>
					<td>SpeechT5 BASE encoder-decoder checkpoints</td>
			</tr>
			<tr>
					<td><a href="https://www.openslr.org/12">LibriSpeech</a></td>
					<td>Dataset</td>
					<td>CC-BY-4.0</td>
					<td>960h speech pre-training and ASR fine-tuning</td>
			</tr>
			<tr>
					<td><a href="https://www.openslr.org/60">LibriTTS</a></td>
					<td>Dataset</td>
					<td>CC-BY-4.0</td>
					<td>460h TTS fine-tuning</td>
			</tr>
			<tr>
					<td><a href="https://ict.fbk.eu/must-c/">MUST-C</a></td>
					<td>Dataset</td>
					<td>CC-BY-NC-ND-4.0</td>
					<td>Speech translation fine-tuning</td>
			</tr>
			<tr>
					<td><a href="http://www.festvox.org/cmu_arctic/">CMU Arctic</a></td>
					<td>Dataset</td>
					<td>Free</td>
					<td>Voice conversion fine-tuning</td>
			</tr>
			<tr>
					<td><a href="http://wham.whisper.ai/">WHAM!</a></td>
					<td>Dataset</td>
					<td>CC-BY-NC-4.0</td>
					<td>Speech enhancement fine-tuning</td>
			</tr>
			<tr>
					<td><a href="https://www.robots.ox.ac.uk/~vgg/data/voxceleb/vox1.html">VoxCeleb1</a></td>
					<td>Dataset</td>
					<td>CC-BY-SA-4.0</td>
					<td>Speaker identification fine-tuning</td>
			</tr>
	</tbody>
</table>
<h3 id="hardware">Hardware</h3>
<ul>
<li>Pre-training: 32 NVIDIA V100 GPUs</li>
<li>Batch: ~90s speech per GPU + 12k text tokens per GPU, gradient accumulation 2</li>
<li>Pre-training steps: 500k</li>
</ul>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Ao, J., Wang, R., Zhou, L., Wang, C., Ren, S., Wu, Y., Liu, S., Ko, T., Li, Q., Zhang, Y., Wei, Z., Qian, Y., Li, J., &amp; Wei, F. (2022). SpeechT5: Unified-Modal Encoder-Decoder Pre-Training for Spoken Language Processing. <em>Proceedings of the 60th Annual Meeting of the Association for Computational Linguistics (Volume 1: Long Papers)</em>, 5723-5738.</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>{ao2022speecht,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>=<span style="color:#e6db74">{SpeechT5: Unified-Modal Encoder-Decoder Pre-Training for Spoken Language Processing}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>=<span style="color:#e6db74">{Ao, Junyi and Wang, Rui and Zhou, Long and Wang, Chengyi and Ren, Shuo and Wu, Yu and Liu, Shujie and Ko, Tom and Li, Qing and Zhang, Yu and Wei, Zhihua and Qian, Yao and Li, Jinyu and Wei, Furu}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">booktitle</span>=<span style="color:#e6db74">{Proceedings of the 60th Annual Meeting of the Association for Computational Linguistics (Volume 1: Long Papers)}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span>=<span style="color:#e6db74">{5723--5738}</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">doi</span>=<span style="color:#e6db74">{10.18653/v1/2022.acl-long.393}</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div>]]></content:encoded></item><item><title>InstructMol: Multi-Modal Molecular LLM for Drug Discovery</title><link>https://hunterheidenreich.com/notes/chemistry/llm-applications/instructmol/</link><pubDate>Sat, 20 Dec 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/notes/chemistry/llm-applications/instructmol/</guid><description>A multi-modal LLM aligning 2D molecular graphs with text via two-stage instruction tuning for drug discovery tasks.</description><content:encoded><![CDATA[<h2 id="instructmol-framework-overview">InstructMol Framework Overview</h2>
<p><strong>Methodological Paper ($\Psi_{\text{Method}}$)</strong></p>
<p>This work proposes <strong>InstructMol</strong>, a novel multi-modal architecture and training paradigm. It focuses on engineering a system that aligns a pre-trained molecular graph encoder with a general-purpose Large Language Model (LLM). The paper&rsquo;s primary contribution is the <strong>Two-Stage Instruction Tuning</strong> strategy (Alignment Pre-training + Task-Specific Tuning) designed to bridge the modality gap between 2D molecular graphs and natural language.</p>
<h2 id="bridging-specialist-and-generalist-models">Bridging Specialist and Generalist Models</h2>
<p>Current AI approaches in drug discovery typically fall into two categories. Specialist models deliver high accuracy on specific tasks (such as property prediction) but require extensive labeled datasets and lack conversational adaptability. Conversely, generalist LLMs offer strong reasoning and dialogue capabilities but struggle to natively interpret complex structural data, often relying on brittle 1D text representations of molecules like <a href="/notes/chemistry/molecular-representations/notations/smiles/">SMILES</a>.</p>
<p>There is a practical need for a unified &ldquo;Molecular Assistant&rdquo; capable of visually interpreting molecular graphs, reasoning about structure in natural language, and adapting across tasks like synthesis planning and property analysis without training from scratch.</p>
<h2 id="two-stage-modality-alignment">Two-Stage Modality Alignment</h2>
<p>The core novelty lies in the architecture and the <strong>two-stage training pipeline</strong> designed to align differing modalities efficiently:</p>
<ol>
<li><strong>MoleculeSTM Integration</strong>: InstructMol initializes its graph encoder with <strong>MoleculeSTM</strong>, which is already pre-aligned with text via contrastive learning, facilitating easier downstream alignment.</li>
<li><strong>Two-Stage Alignment Strategy</strong>:
<ul>
<li><strong>Stage 1 (Alignment Pre-training)</strong>: Freezes both the LLM and Graph Encoder; trains <em>only</em> a linear projector using a massive dataset of molecule-description pairs to map graph features into the LLM&rsquo;s token space.</li>
<li><strong>Stage 2 (Task-Specific Instruction Tuning)</strong>: Freezes the Graph Encoder; fine-tunes the Projector and the LLM (using <strong>LoRA</strong>) on specific downstream tasks. This allows the model to adapt its reasoning capabilities while preserving the structural understanding gained in Stage 1.</li>
</ul>
</li>
</ol>
<h2 id="task-evaluation-in-drug-discovery">Task Evaluation in Drug Discovery</h2>
<p>The authors evaluated InstructMol across three distinct categories of drug discovery tasks, comparing it against generalist LLMs (Vicuna, LLaMA, <a href="/notes/chemistry/llm-applications/galactica-large-language-model-for-science/">Galactica</a>) and specialist models (<a href="/notes/chemistry/molecular-representations/encoders/chemberta/">ChemBERTa</a>, MolT5):</p>
<ol>
<li><strong>Property Prediction</strong>:
<ul>
<li><em>Regression</em>: Predicting quantum mechanical properties (HOMO, LUMO, Gap) using the <a href="/notes/chemistry/datasets/qm9/">QM9</a> dataset.</li>
<li><em>Classification</em>: Predicting biological activity (BACE, BBBP, HIV) using <a href="/notes/chemistry/molecular-design/property-prediction/moleculenet-benchmark-molecular-ml/">MoleculeNet</a>.</li>
</ul>
</li>
<li><strong>Molecule Description Generation</strong>: Generating natural language descriptions of molecules using the ChEBI-20 dataset.</li>
<li><strong>Chemical Reaction Analysis</strong>:
<ul>
<li><em>Forward Reaction Prediction</em>: Predicting products from reactants.</li>
<li><em>Reagent Prediction</em>: Identifying necessary reagents.</li>
<li><em><a href="https://en.wikipedia.org/wiki/Retrosynthetic_analysis">Retrosynthesis</a></em>: Suggesting reactants for a given product.</li>
</ul>
</li>
</ol>
<p><strong>Ablation Studies</strong> tested the impact of the projector type (Linear vs. MLP), LLM scale (7B vs 13B), and the necessity of the two-stage training approach.</p>
<h2 id="core-findings-and-limitations">Core Findings and Limitations</h2>
<ul>
<li><strong>Improvement Over Baseline Generalists</strong>: InstructMol significantly outperformed generalist LLMs (like LLaMA and Galactica) on all tasks, demonstrating the value of incorporating explicit graph modalities.</li>
<li><strong>Reducing the Gap with Specialists</strong>: While InstructMol brings versatile reasoning capabilities, it still trails highly optimized specialist models (such as Uni-Mol and MolT5) on tasks like molecule description generation. This remaining gap likely stems from its reliance on a relatively small alignment pre-training dataset (~264K PubChem pairs) and the information bottleneck of using a simple linear projector, compared to the millions of structures used to train expert foundational models.</li>
<li><strong>Importance of Alignment</strong>: Ablation studies confirmed that skipping Stage 1 (Alignment Pre-training) degraded performance, proving that a dedicated phase for projecting graph features into text space is crucial.</li>
<li><strong>Limitation</strong>: The model struggles with highly imbalanced datasets (e.g., HIV) and complex reaction mixtures where mapping multiple graph tokens to text becomes ambiguous.</li>
</ul>
<hr>
<h2 id="reproducibility-details">Reproducibility Details</h2>
<h3 id="data">Data</h3>
<p>The training pipeline utilizes distinct datasets for the two stages. <strong>Note:</strong> As of the latest repository update, the finely-processed instruction-tuning datasets (e.g., the filtered ~264K PubChem pairs and instruction-formatted subset pairs) are listed as &ldquo;coming soon&rdquo;, requiring manual recreation for full reproduction.</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>Stage 1</strong> (Alignment)</td>
					<td style="text-align: left"><strong><a href="https://en.wikipedia.org/wiki/PubChem">PubChem</a></strong></td>
					<td style="text-align: left">~264K pairs</td>
					<td style="text-align: left">Molecule-text pairs. Filtered from 330K for invalid descriptions and overlaps with ChEBI-20 test set.</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong>Stage 2</strong> (Prop. Reg.)</td>
					<td style="text-align: left"><strong>QM9</strong></td>
					<td style="text-align: left">362K samples</td>
					<td style="text-align: left">Quantum mechanics properties (HOMO, LUMO, Gap).</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong>Stage 2</strong> (Prop. Class.)</td>
					<td style="text-align: left"><strong>MoleculeNet</strong></td>
					<td style="text-align: left">35K samples</td>
					<td style="text-align: left">BACE, BBBP, HIV datasets. Converted to instruction format (Yes/No answer).</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong>Stage 2</strong> (Generation)</td>
					<td style="text-align: left"><strong>ChEBI-20</strong></td>
					<td style="text-align: left">26.5K samples</td>
					<td style="text-align: left">Molecule description generation.</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong>Stage 2</strong> (Reactions)</td>
					<td style="text-align: left"><strong>USPTO</strong></td>
					<td style="text-align: left">~380K samples</td>
					<td style="text-align: left">Combined datasets for Forward (125K), Retrosynthesis (130K), and Reagent (125K) prediction.</td>
			</tr>
	</tbody>
</table>
<h3 id="algorithms">Algorithms</h3>
<ul>
<li><strong>Two-Stage Training</strong>:
<ol>
<li><strong>Alignment Pre-training</strong>: Updates only the Projector. The objective maximizes the probability of generating the target description token sequence $\mathbf{X}_A$ given the molecule input $\mathbf{X}_M$ and instruction $\mathbf{X}_I$:
$$p(\mathbf{X}_A | \mathbf{X}_M, \mathbf{X}_I) = \prod_{i=1}^L p_\theta(x_i | \mathbf{X}_G \parallel \mathbf{X}_S, \mathbf{X}_I, \mathbf{X}_{A,&lt;i})$$</li>
<li><strong>Instruction Tuning</strong>: Updates Projector + LLM (via LoRA) using standard autoregressive language modeling on task-specific instructions. The objective minimizes the negative log-likelihood of generating the target response $R$ of length $L$:
$$\mathcal{L}(\theta) = -\sum_{i=1}^L \log p(R_i | I, M, R_{&lt;i}; \theta)$$
where $I$ represents the instruction and $M$ is the multi-modal molecular input.</li>
</ol>
</li>
<li><strong>LoRA (Low-Rank Adaptation)</strong>: Applied to the LLM in Stage 2. Rank $r=64$, Scaling $\alpha=16$.</li>
<li><strong>Optimization</strong>: AdamW optimizer. Learning rate starts at 2e-3 (Stage 1) and 8e-5 (Stage 2) with cosine decay. Warm-up ratio 0.03.</li>
</ul>
<h3 id="models">Models</h3>
<p><strong>Note:</strong> The official repository currently lists the final fine-tuned <strong>InstructMol weights</strong> as &ldquo;coming soon.&rdquo; Consequently, one must fine-tune the components using the provided scripts. Base model weights (Vicuna-7B and MoleculeSTM) are publicly available via Hugging Face.</p>
<ul>
<li><strong>Graph Encoder ($f_g$)</strong>:
<ul>
<li>Architecture: Graph Isomorphism Network (GIN) with 5 layers.</li>
<li>Hidden Dimension: 300.</li>
<li>Initialization: <strong>MoleculeSTM</strong> checkpoint (pre-trained via contrastive learning).</li>
<li>Status: <strong>Frozen</strong> during Stage 2.</li>
</ul>
</li>
<li><strong>LLM</strong>:
<ul>
<li>Base: <strong>Vicuna-v1.3-7B</strong>.</li>
<li>Status: Frozen in Stage 1; LoRA fine-tuned in Stage 2.</li>
</ul>
</li>
<li><strong>Projector</strong>:
<ul>
<li>Architecture: Linear Layer.</li>
<li>Function: Maps node-level graph representation $Z_G \in \mathbb{R}^{N \times d}$ to the LLM&rsquo;s word embedding space dimensions.</li>
</ul>
</li>
</ul>
<h3 id="evaluation">Evaluation</h3>
<ul>
<li><strong>Metric Libraries</strong>: RDKit for validity/fingerprints, standard NLP libraries for BLEU/ROUGE.</li>
<li><strong>Reaction Metrics</strong>: Fingerprint <a href="https://en.wikipedia.org/wiki/Jaccard_index">Tanimoto Similarity</a> (FTS), Exact Match, Levenshtein distance, and validity (via RDKit).</li>
<li><strong>Description Metrics</strong>: BLEU-2, BLEU-4, ROUGE-1, ROUGE-2, ROUGE-L, METEOR.</li>
</ul>
<h3 id="hardware">Hardware</h3>
<ul>
<li><strong>Compute</strong>: 4 x NVIDIA RTX A6000 (48GB VRAM).</li>
<li><strong>Training Time</strong>:
<ul>
<li>Stage 1: 5 epochs.</li>
<li>Stage 2: 20-50 epochs (Description Generation), 10 epochs (Properties/Reactions).</li>
</ul>
</li>
<li><strong>Batch Size</strong>: 128 for both stages.</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/IDEA-XL/InstructMol">InstructMol (GitHub)</a></td>
					<td style="text-align: left">Code</td>
					<td style="text-align: left">Apache 2.0 (code), CC BY-NC 4.0 (data)</td>
					<td style="text-align: left">Training/evaluation scripts provided; fine-tuned weights listed as &ldquo;coming soon&rdquo;</td>
			</tr>
			<tr>
					<td style="text-align: left"><a href="https://huggingface.co/lmsys/vicuna-7b-v1.3">Vicuna-7B v1.3</a></td>
					<td style="text-align: left">Model</td>
					<td style="text-align: left">Non-commercial (LLaMA license)</td>
					<td style="text-align: left">Base LLM; must be downloaded separately</td>
			</tr>
			<tr>
					<td style="text-align: left"><a href="https://huggingface.co/chao1224/MoleculeSTM">MoleculeSTM</a></td>
					<td style="text-align: left">Model</td>
					<td style="text-align: left">MIT</td>
					<td style="text-align: left">Pre-trained graph encoder checkpoint</td>
			</tr>
	</tbody>
</table>
<hr>
<h2 id="paper-information">Paper Information</h2>
<p><strong>Citation</strong>: Cao, H., Liu, Z., Lu, X., Yao, Y., &amp; Li, Y. (2025). InstructMol: Multi-Modal Integration for Building a Versatile and Reliable Molecular Assistant in Drug Discovery. <em>Proceedings of the 31st International Conference on Computational Linguistics</em>, 354-379.</p>
<p><strong>Publication</strong>: COLING 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>{caoInstructMolMultiModalIntegration2025,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span> = <span style="color:#e6db74">{{{InstructMol}}: {{Multi-Modal Integration}} for {{Building}} a {{Versatile}} and {{Reliable Molecular Assistant}} in {{Drug Discovery}}}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">shorttitle</span> = <span style="color:#e6db74">{{{InstructMol}}}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">booktitle</span> = <span style="color:#e6db74">{Proceedings of the 31st {{International Conference}} on {{Computational Linguistics}}}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span> = <span style="color:#e6db74">{Cao, He and Liu, Zijing and Lu, Xingyu and Yao, Yuan and Li, Yu}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">editor</span> = <span style="color:#e6db74">{Rambow, Owen and Wanner, Leo and Apidianaki, Marianna and {Al-Khalifa}, Hend and Eugenio, Barbara Di and Schockaert, Steven}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">year</span> = <span style="color:#ae81ff">2025</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">pages</span> = <span style="color:#e6db74">{354--379}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">url</span> = <span style="color:#e6db74">{https://aclanthology.org/2025.coling-main.25/}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">publisher</span> = <span style="color:#e6db74">{Association for Computational Linguistics}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">address</span> = <span style="color:#e6db74">{Abu Dhabi, UAE}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">abstract</span> = <span style="color:#e6db74">{The rapid evolution of artificial intelligence in drug discovery encounters challenges with generalization and extensive training, yet Large Language Models (LLMs) offer promise in reshaping interactions with complex molecular data. Our novel contribution, InstructMol, a multi-modal LLM, effectively aligns molecular structures with natural language via an instruction-tuning approach, utilizing a two-stage training strategy that adeptly combines limited domain-specific data with molecular and textual information. InstructMol showcases substantial performance improvements in drug discovery-related molecular tasks, surpassing leading LLMs and significantly reducing the gap with specialists, thereby establishing a robust foundation for a versatile and dependable drug discovery assistant.}</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/IDEA-XL/InstructMol">Official Repository</a></li>
</ul>
]]></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>Embedding geometry checked qualitatively</strong>: the vectors behave sensibly on semantic-similarity and analogy probes, which is evidence the tensorized tree matches sequential traversal. No analogy-benchmark score is reported.</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>EigenNoise: Data-Free Word Vector Initialization</title><link>https://hunterheidenreich.com/research/eigennoise-contrastive-prior/</link><pubDate>Sun, 01 May 2022 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/research/eigennoise-contrastive-prior/</guid><description>Investigation into EigenNoise, a data-free initialization scheme for word vectors that approaches pre-trained model performance after fine-tuning.</description><content:encoded><![CDATA[<h2 id="abstract">Abstract</h2>
<p>We developed EigenNoise, a method to initialize word vectors using <strong>zero pre-training data</strong>. By deriving a co-occurrence matrix solely from the theoretical harmonic structure of language (Zipf&rsquo;s Law), this project demonstrates that we can mathematically synthesize a &ldquo;warm-start&rdquo; for NLP models. This approach challenges the reliance on massive corpora for initialization and offers a competitive alternative for low-resource environments.</p>
<h2 id="key-contributions">Key Contributions</h2>
<ul>
<li>A <strong>data-free initialization scheme</strong>: word vectors derived from a co-occurrence matrix synthesized from independent (Zipfian) frequency statistics, with no pre-training corpus.</li>
<li>Grounds the construction in the <strong>harmonic statistical structure</strong> of language, so the representation follows from first principles rather than from data.</li>
<li>Evaluates with <strong>Minimum Description Length (MDL)</strong> probing, which measures how much task-relevant information a representation encodes and how compactly, rather than raw accuracy.</li>
<li>After fine-tuning, EigenNoise <strong>approaches</strong> the performance of GloVe (trained on Gigaword) despite seeing <strong>no pre-training text</strong>.</li>
</ul>
<h2 id="technical-implementation">Technical Implementation</h2>
<p>The core insight is that &ldquo;noise&rdquo; in language follows a predictable distribution.</p>
<ol>
<li><strong>Modeling</strong>: We model the &ldquo;null hypothesis&rdquo; of text, how words would co-occur if they were statistically independent but followed Zipfian rank-frequency. This yields a theoretical co-occurrence matrix $\hat{X}$:</li>
</ol>
<p>$$\hat{X}_{ij} = \frac{2mN}{r_i r_j H_N}$$</p>
<p>Where $r_i$ is the rank of word $i$, $N$ is vocabulary size, $m$ is the context window size, and $H_N$ is the $N$-th harmonic number.</p>
<ol start="2">
<li>
<p><strong>Factorization</strong>: We then solve for the word vectors by performing an <strong>eigen-decomposition</strong> on this matrix, extracting the top $d$ components to form the representation space.</p>
</li>
<li>
<p><strong>Probing</strong>: Validated performance using MDL probing on CoNLL-2003 and TweetEval benchmarks.</p>
</li>
</ol>
<h2 id="why-this-matters">Why This Matters</h2>
<p>This research explores how much structure can emerge from frequency statistics alone, with no text exposure at all. The central finding is that EigenNoise vectors, derived purely from Zipf&rsquo;s Law, reach competitive performance with GloVe after fine-tuning. This is evidence that a significant portion of what we call &ldquo;learned linguistic knowledge&rdquo; is a consequence of word frequency distributions, not semantic exposure to real text.</p>
<p>In 2026, small pretrained models are freely available and handle most low-resource initialization needs, so the practical case for data-free initialization is narrower than it was in 2022. The theoretical contribution remains relevant: EigenNoise establishes a clean null hypothesis for what word vectors look like when only frequency information is present. For interpretability researchers trying to disentangle frequency artifacts from genuine semantic content, this baseline has value independent of the initialization use case.</p>
<p>The <strong>MDL probing</strong> methodology applied here also contributes beyond the main result. Unlike task accuracy, MDL measures how much information a representation encodes and how compactly, providing a more principled lens for evaluating representational quality. EigenNoise&rsquo;s co-occurrence prior is grounded directly in the <strong>Independent Frequencies Model (IFM)</strong> introduced in the companion <a href="/research/word-company-vicinity/">Word2Vec factorization paper</a>. Together, the two works form a coherent theoretical line: the IFM characterizes the frequency-driven baseline of embedding space, and EigenNoise operationalizes it as a practical, data-free initialization scheme.</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>{heidenreich2022eigennoisecontrastivepriorwarmstart,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>=<span style="color:#e6db74">{EigenNoise: A Contrastive Prior to Warm-Start Representations}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>=<span style="color:#e6db74">{Hunter Scott Heidenreich and Jake Ryland Williams}</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.04376}</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.04376}</span>,
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="related-work">Related Work</h2>
<p>For the theoretical foundation underlying EigenNoise&rsquo;s null hypothesis, including the first analytical solution to Word2Vec&rsquo;s softmax objective, see <a href="/research/word-company-vicinity/">Analytical Solution to Word2Vec Softmax &amp; Bias Probing</a>.</p>
]]></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,.</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>Data-Driven WordNet Construction from Wiktionary</title><link>https://hunterheidenreich.com/research/semantic-network-induction/</link><pubDate>Fri, 01 Nov 2019 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/research/semantic-network-induction/</guid><description>We introduce an unsupervised algorithm for inducing semantic networks from noisy, crowd-sourced data, producing a resource with over 344,000 linked examples.</description><content:encoded><![CDATA[<h2 id="abstract">Abstract</h2>
<p>We introduce a novel <strong>unsupervised algorithm</strong> for inducing semantic networks from noisy, crowd-sourced data. By framing network construction as a &ldquo;relationship disambiguation&rdquo; task, we process Wiktionary&rsquo;s English entries to build a massive, WordNet-like semantic resource. The resulting network is more than 5x larger than Princeton WordNet and features over <strong>344,000 linked example sentences</strong> (vs. WordNet&rsquo;s 68k). Evaluation on standard word similarity benchmarks demonstrates that our fully data-driven approach yields semantic structures competitive with expert-annotated resources.</p>
<h2 id="key-contributions">Key Contributions</h2>
<ul>
<li><strong>Unsupervised Hierarchy Induction</strong>: We propose a deterministic algorithm to construct a Directed Acyclic Graph (DAG) of senses from pairwise relationships, effectively inducing a semantic hierarchy without human supervision.</li>
<li><strong>A Massive Semantic Resource</strong>: We release a dataset enriched with hundreds of thousands of semantically linked usage examples, serving as a critical resource for tasks like Word Sense Disambiguation (WSD).</li>
<li><strong>Disambiguation Framework</strong>: We model &ldquo;relationship disambiguation&rdquo; using a Laplacian kernel and FastText embeddings to filter noisy user annotations.</li>
<li><strong>Open-Source Infrastructure</strong>: We provide a full pipeline for downloading, parsing, and constructing networks from Wiktionary data.</li>
</ul>
<h2 id="technical-approach">Technical Approach</h2>
<p>The core of our method addresses the noise inherent in crowd-sourced dictionaries. We frame the problem as <strong>Latent Semantic Network Induction</strong>:</p>
<ol>
<li><strong>Relationship Disambiguation</strong>: For every linked pair of words (e.g., <em>go</em> ~ <em>proceed</em>), we define a semantic subspace using their definitions. We utilize <strong>FastText embeddings</strong> and a <strong>Laplacian kernel</strong> to identify which specific definitions participate in the relationship.</li>
<li><strong>Hierarchy Construction</strong>: We apply a custom intersection algorithm that treats more general senses as the &ldquo;overlap&rdquo; between specific definition sets. We formalize this as a set-theoretic &ldquo;hole punching&rdquo; operation, where a general sense $t$ is defined by the intersection of definition sets $\mathbb{D}&rsquo;$, excluding any broader intersections:</li>
</ol>
<p>$$f^{-1}(t) = \left(\bigcap_{\mathbb{D}&rsquo;} D_{u\sim v}\right) \setminus \left(\bigcup_{\mathbb{D} \supset \mathbb{D}&rsquo;} \bigcap_{\mathbb{D}} D_{u\sim v}\right)$$</p>
<h2 id="evaluation--validation">Evaluation &amp; Validation</h2>
<p>The primary achievement is scale: the network is induced over <strong>344,789 linked example usages</strong>, against Princeton WordNet&rsquo;s 68,411 (more than 5x the coverage), built entirely from crowd-sourced data without expert annotation.</p>
<p>Beyond scale, the network holds up semantically. On standard noun-similarity benchmarks (RG-65), the unsupervised network achieves a Spearman rank correlation of $\rho = 0.83$, matching the performance of Explicit Semantic Analysis (ESA) models built on expert-annotated WordNet ($\rho = 0.82$). A fully automated approach over noisy Wiktionary data produces a resource of comparable quality at 5x the scale.</p>
<h2 id="why-this-matters">Why This Matters</h2>
<p>Building high-quality linguistic resources typically requires expensive expert annotation, and Princeton WordNet took decades of lexicographer effort to reach 68,411 linked examples. For ML practitioners, coverage is training signal: a larger network means more supervision for downstream tasks like Word Sense Disambiguation.</p>
<h2 id="related-work">Related Work</h2>
<p>For a theoretical treatment of word semantics from the same collaboration, including the first analytical solution to Word2Vec&rsquo;s softmax objective, see <a href="/research/word-company-vicinity/">Analytical Solution to Word2Vec Softmax &amp; Bias Probing</a>.</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">@inproceedings</span>{heidenreich2019latent,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">title</span>=<span style="color:#e6db74">{Latent semantic network induction in the context of linked example senses}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">author</span>=<span style="color:#e6db74">{Heidenreich, Hunter and Williams, Jake}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">booktitle</span>=<span style="color:#e6db74">{Proceedings of the 5th Workshop on Noisy User-generated Text (W-NUT 2019)}</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">pages</span>=<span style="color:#e6db74">{170--180}</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></span></code></pre></div>]]></content:encoded></item><item><title>Word Embeddings in NLP: An Introduction</title><link>https://hunterheidenreich.com/posts/intro-to-word-embeddings/</link><pubDate>Sun, 05 Aug 2018 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/posts/intro-to-word-embeddings/</guid><description>Learn about word embeddings in NLP: from basic one-hot encoding to contextual models like ELMo. Guide with examples.</description><content:encoded><![CDATA[<h2 id="understanding-word-embeddings">Understanding Word Embeddings</h2>
<p>A word embedding maps words to real-valued vectors:</p>
<p>$$
\text{word} \rightarrow \mathbb{R}^n
$$</p>
<p>where $n$ represents the dimensionality of the embedding space.</p>
<p>The goal is simple: position semantically similar words close together in vector space. This dense representation typically uses hundreds of dimensions, a massive reduction from the millions required by one-hot encoding.</p>
<p>Word embeddings are grounded in <a href="https://en.wikipedia.org/wiki/Distributional_semantics">Zellig Harris&rsquo; distributional hypothesis</a>: words appearing in similar contexts tend to have similar meanings. This forms the foundation of distributional semantics.</p>















<figure class="post-figure center ">
    <img src="/img/distributional_semantics-50.webp"
         alt="Distributional semantics visualization"
         title="Distributional semantics visualization"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">Words embedded in three-dimensional space, organized by semantic similarity</figcaption>
    
</figure>

<p>Different embedding algorithms capture various aspects of this distributional principle. This post explores the main methods for creating word embeddings and their applications in natural language processing.</p>
<p>While modern foundation models and large Vision-Language Models rely on subword tokenizers (like BPE) and Transformer embedding layers, the goal is the same: mapping discrete text to a continuous vector space where math can capture meaning. These foundational techniques build the intuition for the embedding layers in today&rsquo;s models.</p>
<h2 id="why-word-embeddings-matter-in-nlp">Why Word Embeddings Matter in NLP</h2>
<p>Computers require numerical representations to apply machine learning algorithms to text. Word embeddings bridge this gap by converting text into dense vectors that preserve semantic and syntactic relationships.</p>
<p><strong>Key advantages:</strong></p>
<ol>
<li><strong>Dense representation</strong>: Hundreds of dimensions provide a compact alternative to vocabulary-sized sparse vectors.</li>
<li><strong>Semantic preservation</strong>: Similar words cluster together in vector space.</li>
<li><strong>Mathematical operations</strong>: Enable analogical reasoning ($\text{king} - \text{man} + \text{woman} \approx \text{queen}$).</li>
<li><strong>Transfer learning</strong>: Pre-trained embeddings work across multiple tasks and domains.</li>
</ol>
<p>Modern deep learning architectures leverage these properties extensively. The development of universal, pre-trained embeddings was a significant step forward. We can use versatile embeddings that generalize across applications, eliminating the need to train task-specific representations from scratch.</p>
<h2 id="word-embedding-approaches">Word Embedding Approaches</h2>
<h3 id="one-hot-encoding-and-count-vectorization">One-Hot Encoding and Count Vectorization</h3>
<p>One-hot encoding represents the simplest approach to word vectorization. Each word gets a unique dimension in a vocabulary-sized vector, marked with 1 for presence and 0 elsewhere. Count vectorization extends this by counting the occurrences of each word in a document.</p>















<figure class="post-figure center ">
    <img src="/img/word_vector_onehot-50.webp"
         alt="One-hot encoding visualization"
         title="One-hot encoding visualization"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">One-hot encoding creates sparse vectors with single active dimensions</figcaption>
    
</figure>

<p><strong>Characteristics:</strong></p>
<ul>
<li><strong>High dimensionality</strong>: Vector length equals vocabulary size.</li>
<li><strong>Extreme sparsity</strong>: Most dimensions contain zeros.</li>
<li><strong>No relationships</strong>: Treats all words as equally distant.</li>
<li><strong>Computational efficiency</strong>: Simple to implement and understand.</li>
</ul>
<p>While lacking semantic information, count vectorization serves as a foundation for more complex methods. Let&rsquo;s look at a practical implementation using scikit-learn&rsquo;s <code>CountVectorizer</code>.</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">from</span> sklearn.feature_extraction.text <span style="color:#f92672">import</span> CountVectorizer
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Initialize the vectorizer</span>
</span></span><span style="display:flex;"><span>vectorizer <span style="color:#f92672">=</span> CountVectorizer()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Sample text for demonstration</span>
</span></span><span style="display:flex;"><span>sample_text <span style="color:#f92672">=</span> [<span style="color:#e6db74">&#34;One of the most basic ways we can numerically represent words &#34;</span>
</span></span><span style="display:flex;"><span>               <span style="color:#e6db74">&#34;is through the one-hot encoding method (also sometimes called &#34;</span>
</span></span><span style="display:flex;"><span>               <span style="color:#e6db74">&#34;count vectorizing).&#34;</span>]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Fit the vectorizer to our text data</span>
</span></span><span style="display:flex;"><span>vectorizer<span style="color:#f92672">.</span>fit(sample_text)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Examine the vocabulary and word indices</span>
</span></span><span style="display:flex;"><span>print(<span style="color:#e6db74">&#39;Vocabulary:&#39;</span>)
</span></span><span style="display:flex;"><span>print(vectorizer<span style="color:#f92672">.</span>vocabulary_)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Transform text to vectors</span>
</span></span><span style="display:flex;"><span>vector <span style="color:#f92672">=</span> vectorizer<span style="color:#f92672">.</span>transform(sample_text)
</span></span><span style="display:flex;"><span>print(<span style="color:#e6db74">&#39;Full vector:&#39;</span>)
</span></span><span style="display:flex;"><span>print(vector<span style="color:#f92672">.</span>toarray())
</span></span></code></pre></div><p>At scale, count vectorization introduces engineering challenges. With millions of documents, the vocabulary grows large, and the sparse matrices become expensive to store and compute on. In these scaling scenarios, practitioners often turn to the <strong>Hashing Trick</strong> (via <code>HashingVectorizer</code>) to bound the dimensionality, or they move entirely to the dense embeddings discussed later in this post.</p>
<p>We can see count vectorization in action with a real dataset, building a simple text classifier for the <a href="https://www.kaggle.com/datasets/crawford/20-newsgroups">20 Newsgroups dataset</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-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">from</span> sklearn.datasets <span style="color:#f92672">import</span> fetch_20newsgroups
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> sklearn.feature_extraction.text <span style="color:#f92672">import</span> CountVectorizer
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> sklearn.naive_bayes <span style="color:#f92672">import</span> MultinomialNB
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> sklearn <span style="color:#f92672">import</span> metrics
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Load train and test splits, removing metadata for a cleaner signal</span>
</span></span><span style="display:flex;"><span>newsgroups_train <span style="color:#f92672">=</span> fetch_20newsgroups(subset<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;train&#39;</span>,
</span></span><span style="display:flex;"><span>                                      remove<span style="color:#f92672">=</span>(<span style="color:#e6db74">&#39;headers&#39;</span>, <span style="color:#e6db74">&#39;footers&#39;</span>, <span style="color:#e6db74">&#39;quotes&#39;</span>))
</span></span><span style="display:flex;"><span>newsgroups_test <span style="color:#f92672">=</span> fetch_20newsgroups(subset<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;test&#39;</span>,
</span></span><span style="display:flex;"><span>                                     remove<span style="color:#f92672">=</span>(<span style="color:#e6db74">&#39;headers&#39;</span>, <span style="color:#e6db74">&#39;footers&#39;</span>, <span style="color:#e6db74">&#39;quotes&#39;</span>))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Initialize and fit vectorizer on training data</span>
</span></span><span style="display:flex;"><span>vectorizer <span style="color:#f92672">=</span> CountVectorizer()
</span></span><span style="display:flex;"><span>X_train <span style="color:#f92672">=</span> vectorizer<span style="color:#f92672">.</span>fit_transform(newsgroups_train<span style="color:#f92672">.</span>data)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Build and train classifier</span>
</span></span><span style="display:flex;"><span>classifier <span style="color:#f92672">=</span> MultinomialNB(alpha<span style="color:#f92672">=</span><span style="color:#ae81ff">0.01</span>)
</span></span><span style="display:flex;"><span>classifier<span style="color:#f92672">.</span>fit(X_train, newsgroups_train<span style="color:#f92672">.</span>target)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Transform test data and make predictions</span>
</span></span><span style="display:flex;"><span>X_test <span style="color:#f92672">=</span> vectorizer<span style="color:#f92672">.</span>transform(newsgroups_test<span style="color:#f92672">.</span>data)
</span></span><span style="display:flex;"><span>y_pred <span style="color:#f92672">=</span> classifier<span style="color:#f92672">.</span>predict(X_test)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Evaluate performance</span>
</span></span><span style="display:flex;"><span>accuracy <span style="color:#f92672">=</span> metrics<span style="color:#f92672">.</span>accuracy_score(newsgroups_test<span style="color:#f92672">.</span>target, y_pred)
</span></span><span style="display:flex;"><span>print(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#39;Accuracy: </span><span style="color:#e6db74">{</span>accuracy<span style="color:#e6db74">:</span><span style="color:#e6db74">.3f</span><span style="color:#e6db74">}</span><span style="color:#e6db74">&#39;</span>)
</span></span></code></pre></div><p>This provides a solid baseline. To capture actual semantic meaning and reduce dimensionality, we must move beyond simple counting.</p>
<h3 id="tf-idf-term-frequency-inverse-document-frequency">TF-IDF (Term Frequency-Inverse Document Frequency)</h3>
<p><a href="https://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.TfidfVectorizer.html">TF-IDF</a> extends one-hot encoding by weighting terms based on their importance across a document collection. TF-IDF combines:</p>
<ul>
<li><strong>Term Frequency (TF)</strong>: How often a word appears in a document</li>
<li><strong>Inverse Document Frequency (IDF)</strong>: How rare a word is across all documents</li>
</ul>
<p>This weighting scheme reduces the impact of common words (like &ldquo;the&rdquo; or &ldquo;and&rdquo;) while emphasizing distinctive terms that appear frequently in specific documents but rarely elsewhere.</p>
<p><strong>Advantages:</strong></p>
<ul>
<li>Captures document-level importance</li>
<li>Reduces impact of stop words</li>
<li>Effective for information retrieval tasks</li>
</ul>
<p><strong>Limitations:</strong></p>
<ul>
<li>Still high-dimensional and sparse</li>
<li>No semantic relationships between terms</li>
<li>Context-independent representation</li>
</ul>
<h3 id="co-occurrence-matrices">Co-Occurrence Matrices</h3>
<p>Co-occurrence matrices capture word relationships by recording which terms appear together within defined contexts (sentences, paragraphs, or fixed windows). The resulting matrix has dimensions equal to vocabulary size squared, with entries showing co-occurrence frequency.</p>















<figure class="post-figure center ">
    <img src="/img/Word_co-occurrence_network_%28range_3_words%29_-_ENG-50.webp"
         alt="Co-occurrence network visualization"
         title="Co-occurrence network visualization"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">Co-occurrence relationships within a three-word window</figcaption>
    
</figure>

<p><strong>Key properties:</strong></p>
<ul>
<li><strong>Global statistics</strong>: Captures corpus-wide word relationships</li>
<li><strong>Symmetric relationships</strong>: Mutual co-occurrence patterns</li>
<li><strong>Extreme dimensionality</strong>: Vocabulary size squared creates storage challenges</li>
<li><strong>Sparse representation</strong>: Most word pairs never co-occur</li>
</ul>
<p>While computationally expensive to store and process, co-occurrence matrices form the foundation for advanced methods like GloVe that compress this information into dense representations.</p>
<h2 id="neural-network-based-embeddings">Neural Network-Based Embeddings</h2>
<h3 id="neural-probabilistic-language-models">Neural Probabilistic Language Models</h3>
<p><a href="https://www.jmlr.org/papers/volume3/bengio03a/bengio03a.pdf">Neural probabilistic models</a> pioneered the use of neural networks for learning word embeddings. These models learn dense representations as a byproduct of language modeling, predicting the next word in a sequence.</p>















<figure class="post-figure center ">
    <img src="/img/bengio-npm-50.webp"
         alt="Neural probabilistic model diagram"
         title="Neural probabilistic model diagram"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">Architecture of neural probabilistic language models</figcaption>
    
</figure>

<p><strong>Training process:</strong></p>
<ol>
<li>Initialize random dense embeddings for each vocabulary word</li>
<li>Use embeddings as inputs to predict language modeling objectives</li>
<li>Update embeddings through backpropagation based on prediction errors</li>
<li>Resulting embeddings capture patterns useful for the training task</li>
</ol>
<p>This approach demonstrated that task-specific embeddings could be learned jointly with model objectives, establishing the foundation for modern embedding methods.</p>
<h3 id="word2vec">Word2Vec</h3>
<p><a href="https://code.google.com/archive/p/word2vec/">Word2Vec</a> made word embeddings practical at scale by introducing efficient training algorithms for massive corpora. It popularized compelling vector arithmetic properties, enabling analogical reasoning like the famous &ldquo;$\text{king} - \text{man} + \text{woman} \approx \text{queen}$&rdquo; example (a vector-offset regularity first reported by Mikolov, Yih &amp; Zweig (2013) on recurrent-network language-model embeddings).</p>















<figure class="post-figure center ">
    <img src="/img/Word_vector_illustration.webp"
         alt="Word2Vec vector arithmetic visualization"
         title="Word2Vec vector arithmetic visualization"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">Word2Vec demonstrates analogical relationships through vector arithmetic</figcaption>
    
</figure>

<p><strong>Two training architectures:</strong></p>
<h4 id="continuous-bag-of-words-cbow">Continuous Bag-of-Words (CBOW)</h4>
<p>Predicts target words from surrounding context words. Given a window of context words, the model learns to predict the central word.</p>
<h4 id="skip-gram">Skip-Gram</h4>
<p>Predicts context words from target words. Given a central word, the model learns to predict surrounding words within a defined window.</p>
<p><strong>Key advantages:</strong></p>
<ul>
<li><strong>Computational efficiency</strong>: Much faster than neural probabilistic models</li>
<li><strong>Scalable training</strong>: Can process billion-word corpora effectively</li>
<li><strong>Quality embeddings</strong>: Captures semantic and syntactic relationships</li>
<li><strong>Flexible context</strong>: Window size controls topical vs. functional similarity</li>
</ul>
<p>The choice of window size significantly impacts learned relationships. Larger windows capture topical associations, while smaller windows focus on syntactic and functional similarities.</p>
<h3 id="glove-global-vectors">GloVe (Global Vectors)</h3>
<p><a href="https://nlp.stanford.edu/projects/glove/">GloVe</a> combines the best aspects of matrix factorization methods (which capture global corpus statistics) and local context window approaches like Word2Vec. Matrix factorization methods excel at global patterns but struggle with analogical reasoning, while Word2Vec captures local relationships but may miss global structure.</p>
<p><strong>Key innovation:</strong>
GloVe trains on a global word-context co-occurrence matrix, incorporating corpus-wide statistical information while maintaining the analogical reasoning capabilities that made Word2Vec successful.</p>
<p><strong>Advantages over Word2Vec:</strong></p>
<ul>
<li><strong>Global optimization</strong>: Leverages entire corpus statistics</li>
<li><strong>Better performance</strong>: Often outperforms Word2Vec on word similarity and analogy tasks</li>
<li><strong>Stable training</strong>: More consistent convergence due to global objective function</li>
</ul>
<p>The result is embeddings that capture both local syntactic patterns and global semantic relationships more effectively.</p>
<h2 id="contextual-embedding-methods">Contextual Embedding Methods</h2>
<h3 id="fasttext">FastText</h3>
<p><a href="https://github.com/facebookresearch/fastText">FastText</a> addresses a critical limitation of previous methods: handling out-of-vocabulary (OOV) words. By incorporating subword information, FastText can generate meaningful representations for previously unseen words.</p>
<p><strong>Subword approach:</strong></p>
<ul>
<li>Decomposes words into character n-grams (typically 3-6 characters)</li>
<li>Represents words as sums of their component n-grams</li>
<li>Trains using skip-gram objective with negative sampling</li>
</ul>
<p><strong>Key advantages:</strong></p>
<ul>
<li><strong>OOV handling</strong>: Can embed unseen words using known subword components</li>
<li><strong>Morphological awareness</strong>: Captures relationships between related word forms</li>
<li><strong>Multilingual support</strong>: Facebook released pre-trained embeddings for 294 languages</li>
<li><strong>Robust performance</strong>: Particularly effective for morphologically rich languages</li>
</ul>
<p>For example, if the model knows &ldquo;navigate,&rdquo; it can provide meaningful representation for &ldquo;circumnavigate&rdquo; by leveraging shared subword components, even if &ldquo;circumnavigate&rdquo; wasn&rsquo;t in the training data.</p>
<h3 id="poincaré-embeddings">Poincaré Embeddings</h3>
<p><a href="https://radimrehurek.com/gensim/models/poincare.html">Poincaré embeddings</a> introduce a novel approach by learning representations in hyperbolic space. This geometric innovation specifically targets hierarchical relationships in data.</p>
<p><strong>Hyperbolic geometry advantages:</strong></p>
<ul>
<li><strong>Natural hierarchy encoding</strong>: Distance represents similarity, while norm encodes hierarchical level</li>
<li><strong>Efficient representation</strong>: Requires fewer dimensions for hierarchical data</li>
<li><strong>Mathematical elegance</strong>: Leverages properties of hyperbolic space for embedding optimization</li>
</ul>
<p><strong>Applications:</strong>
Particularly effective for data with inherent hierarchical structure, such as:</p>
<ul>
<li>WordNet taxonomies</li>
<li>Organizational charts</li>
<li>Computer network topologies</li>
<li>Knowledge graphs</li>
</ul>
<p>The <a href="https://arxiv.org/abs/1705.08039">original paper</a> demonstrates good efficiency in reproducing WordNet relationships with significantly lower dimensionality compared to traditional embedding methods.</p>
<h2 id="contextual-embeddings">Contextual Embeddings</h2>
<h3 id="elmo-embeddings-from-language-models">ELMo (Embeddings from Language Models)</h3>
<p><a href="https://github.com/allenai/allennlp-models">ELMo</a> represents a paradigm shift toward contextual word representations. ELMo generates dynamic representations based on sentence context, adapting to word usage patterns.</p>
<p><strong>Architecture:</strong></p>
<ul>
<li><strong>Bidirectional LSTM</strong>: Processes text in both forward and backward directions</li>
<li><strong>Character-level input</strong>: Handles OOV words and captures morphological patterns</li>
<li><strong>Multi-layer representations</strong>: Combines different abstraction levels</li>
</ul>
<p><strong>Layer specialization:</strong></p>
<ul>
<li><strong>Lower layers</strong>: Excel at syntactic tasks (POS tagging, parsing)</li>
<li><strong>Higher layers</strong>: Capture semantic relationships (word sense disambiguation)</li>
<li><strong>Combined layers</strong>: Weighted combination achieves good performance</li>
</ul>
<p><strong>Key innovation:</strong>
ELMo embeddings vary by context. The word &ldquo;bank&rdquo; receives different representations in &ldquo;river bank&rdquo; versus &ldquo;financial bank,&rdquo; addressing polysemy directly through contextual awareness.</p>
<p>This approach achieved strong performance across numerous NLP tasks by providing context-sensitive representations that adapt to word usage patterns.</p>
<h3 id="probabilistic-fasttext">Probabilistic FastText</h3>
<p><a href="https://github.com/benathi/multisense-prob-fasttext">Probabilistic FastText</a> addresses polysemy (words with multiple meanings) through probabilistic modeling. Traditional embeddings conflate different word senses into single representations, limiting their precision.</p>
<p><strong>The polysemy problem:</strong>
Consider &ldquo;rock&rdquo; which can mean:</p>
<ul>
<li>Rock music (genre)</li>
<li>A stone (geological object)</li>
<li>Rocking motion (verb)</li>
</ul>
<p>Standard embeddings average these meanings, producing representations that may not capture any sense precisely.</p>
<p><strong>Probabilistic approach:</strong>
Probabilistic FastText represents words as Gaussian mixture models: probability distributions that can capture multiple distinct meanings as separate components.</p>
<p><strong>Advantages:</strong></p>
<ul>
<li><strong>Multi-sense representation</strong>: Each word sense gets its own distribution</li>
<li><strong>Context sensitivity</strong>: Can select appropriate sense based on usage context</li>
<li><strong>Uncertainty quantification</strong>: Probabilistic framework captures embedding confidence</li>
</ul>
<p>This approach provides a more nuanced treatment of lexical ambiguity, particularly valuable for words with distinct, context-dependent meanings.</p>
<h2 id="summary-and-future-directions">Summary and Future Directions</h2>
<p>Word embeddings have evolved from simple one-hot encodings to contextual representations that capture nuanced linguistic relationships. Each approach offers distinct advantages:</p>
<p><strong>Static embeddings</strong> (Word2Vec, GloVe, FastText) provide:</p>
<ul>
<li>Computational efficiency for large-scale applications</li>
<li>Pre-trained models available for numerous languages</li>
<li>Clear analogical reasoning capabilities</li>
<li>Good performance on many downstream tasks</li>
</ul>
<p><strong>Contextual embeddings</strong> (ELMo, BERT, GPT) offer:</p>
<ul>
<li>Dynamic representations based on sentence context</li>
<li>Better handling of polysemy and word sense disambiguation</li>
<li>Strong performance on complex NLP tasks</li>
<li>Ability to capture subtle contextual nuances</li>
</ul>
<p><strong>Choosing the right approach</strong> depends on:</p>
<ul>
<li><strong>Task requirements</strong>: Static embeddings for efficiency, contextual for accuracy</li>
<li><strong>Data availability</strong>: Pre-trained models vs. domain-specific training</li>
<li><strong>Computational constraints</strong>: Static embeddings require less processing power</li>
<li><strong>Language coverage</strong>: Consider availability of pre-trained models for target languages</li>
</ul>
<p>The field continues advancing toward more efficient contextual models, better multilingual representations, and embeddings that capture increasingly complex linguistic phenomena.</p>
<p>For a from-scratch Word2Vec implementation in PyTorch (Skip-gram and CBOW, with hierarchical softmax and negative sampling) that takes these concepts further, see the <a href="/projects/modern-word2vec/">PyTorch Word2Vec project</a>.</p>
]]></content:encoded></item></channel></rss>