<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.0">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2025-10-06T20:24:19-04:00</updated><id>/feed.xml</id><title type="html">The Horenberger Zone</title><subtitle>Cite me in your thesis</subtitle><author><name>Beau Horenberger</name></author><entry><title type="html">Timescales in the Brain and Hierarchical Reasoning Models</title><link href="/2025/09/01/brain-timescales.html" rel="alternate" type="text/html" title="Timescales in the Brain and Hierarchical Reasoning Models" /><published>2025-09-01T00:00:00-04:00</published><updated>2025-09-01T00:00:00-04:00</updated><id>/2025/09/01/brain-timescales</id><content type="html" xml:base="/2025/09/01/brain-timescales.html">&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#hierarchical-reasoning-models-very-cool&quot; id=&quot;markdown-toc-hierarchical-reasoning-models-very-cool&quot;&gt;Hierarchical reasoning models: Very cool&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#what-is-autocorrelation&quot; id=&quot;markdown-toc-what-is-autocorrelation&quot;&gt;What is Autocorrelation?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#how-does-autocorrelation-relate-to-neuroscience&quot; id=&quot;markdown-toc-how-does-autocorrelation-relate-to-neuroscience&quot;&gt;How does autocorrelation relate to neuroscience?&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#observable-timescales-in-the-brain&quot; id=&quot;markdown-toc-observable-timescales-in-the-brain&quot;&gt;Observable timescales in the brain&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#deep-dive-on-autocorrelations-of-neuron-spike-counts&quot; id=&quot;markdown-toc-deep-dive-on-autocorrelations-of-neuron-spike-counts&quot;&gt;Deep dive on autocorrelations of neuron spike counts&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#anything-else&quot; id=&quot;markdown-toc-anything-else&quot;&gt;Anything else?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusion-and-whats-next&quot; id=&quot;markdown-toc-conclusion-and-whats-next&quot;&gt;Conclusion and what’s next&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;hierarchical-reasoning-models-very-cool&quot;&gt;Hierarchical reasoning models: Very cool&lt;/h1&gt;

&lt;p&gt;Recently there has been discussion about a new ML architecture, &lt;a href=&quot;https://arxiv.org/abs/2506.21734&quot;&gt;hierarchical reasoning models.&lt;/a&gt; Although it’s too soon to say whether they’ll take off, I thought the paper seemed pretty interesting. I noticed the authors made an effort to ground their ideas in cognitive science and neuroscience. One particular comment stood out to me:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The human brain provides a compelling blueprint for achieving the effective computational depth that contemporary artificial models lack. It organizes computation hierarchically across cortical regions operating at different timescales, enabling deep, multi-stage reasoning. Recurrent feedback loops iteratively refine internal representations, allowing slow, higher-level areas to guide, and fast, lower-level circuits to execute—subordinate processing while preserving global coherence. Notably, the brain achieves such depth without incurring the prohibitive credit assignment costs that typically hamper recurrent networks from backpropagation through time.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This was news to me. When did we figure all this out about the brain? I started clicking through citations and got mired in some shenanigans, but I think I’ve mostly figured it out now.&lt;/p&gt;

&lt;p&gt;I’ll probably write more about hierarchical reasoning models in the future, but I think this subject alone makes for a relatively interesting article.&lt;/p&gt;

&lt;p&gt;We’ll start by defining autocorrelation, which will be the lynchpin for the empirical experiments that identified this hierarchy of timescales in the brain.&lt;/p&gt;

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

&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Autocorrelation&quot;&gt;Autocorrelation of a random process is the Pearson correlation between values of the process of different times as a function of the two times or of the time lag.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let ${X_t}$ be a real-valued random process where $X_t$ is the realized value at $t$ for a given run. Supposing we have mean $\mu_t$ at time $t$ and variance $\sigma_t^2$ at each time $t$, then the autocorrelation function is defined by&lt;/p&gt;

\[R_{XX}(t_1,t_2)=E[X_{t_1}X_{t_2}]\]

&lt;p&gt;So if the process tends to be similar at two times, the autocorrelation of those times will be positive-valued. If the process tends to have opposite signs at two times, the autocorrelation will be negative-valued. Autocorrelation near zero indicates the two times are not correlated at all.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2025-09-01-brain-timescales/autocorrelation_example.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tau_fast = 20  # ms
noise_fast = np.random.randn(len(time))
signal_fast = np.zeros(len(time))
for t in range(1, len(time)):
    signal_fast[t] = signal_fast[t-1]*np.exp(-dt/tau_fast) + noise_fast[t]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tau_slow = 200  # ms
noise_slow = np.random.randn(len(time))
signal_slow = np.zeros(len(time))
for t in range(1, len(time)):
    signal_slow[t] = signal_slow[t-1]*np.exp(-dt/tau_slow) + noise_slow[t]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you have a discrete signal $x[n]$, with $n = 0,1,\ldots,N−1$, the sample autocorrelation is:&lt;/p&gt;

\[R_{xx}[k] = \frac{1}{N-k} \sum_{n=0}^{N-k-1} \; x[n] \, x[n+k]\]

&lt;p&gt;for lag $k = 0, 1, \ldots, N-1$. This definition makes it a little more tangible and easier to visualize.&lt;/p&gt;

&lt;p&gt;Autocorrelation shows us how information leaks from our function at different timescales. If the autocorrelation is near 0, the two times share very little information.&lt;/p&gt;

&lt;h1 id=&quot;how-does-autocorrelation-relate-to-neuroscience&quot;&gt;How does autocorrelation relate to neuroscience?&lt;/h1&gt;

&lt;h2 id=&quot;observable-timescales-in-the-brain&quot;&gt;Observable timescales in the brain&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1000209&quot;&gt;As early as 2008, very interesting arguments were being made that the brain operates at many timescales.&lt;/a&gt; This paper was motivated by mathematical simulations involving bird songs, but the core argument was that a hierarchical modeling of the world allows for processing to occur at several timescales and that this hierarchy of timescales is probably organized in the brain according to distance from primary sensory areas.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://johndmurray.org/papers/murray_2014_nn.pdf&quot;&gt;In 2014, JD Murray et al counted neuron spikes over time in various regions of the brain. They found distinct autocorrelations for each region.&lt;/a&gt; This indicates that different regions of the brain may be tailored to operate at particular timescales. For example, some regions may be specialized in processing 60ms chunks of audio, while another region might process 300ms chunks. The data seemed to align with earlier hypotheses that timescale would correlate to distance from primary sensory areas.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2025-09-01-brain-timescales/brain_timescales_data.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This blew my mind, btw. I wasn’t aware that we had made this kind of progress in understanding the brain. The idea feels so simple and agreeable, and it’s so satisfying to see clear empirical evidence of it.&lt;/p&gt;

&lt;p&gt;But the autocorrelation stuff shouldn’t be be completely clear to you yet. Qualitatively, the graphcs make it obvious that the information decays at different rates for each brain region, but how do you extract a specific number that represents each region’s timescale? There are some additional hypotheses at work.&lt;/p&gt;

&lt;h2 id=&quot;deep-dive-on-autocorrelations-of-neuron-spike-counts&quot;&gt;Deep dive on autocorrelations of neuron spike counts&lt;/h2&gt;

&lt;p&gt;Recall that the functions of interest are binned neuron spike counts in some brain region. So, for example, they might use 5ms bins and count all the activations that occurred between each 5ms time step. What would you expect the autocorrelation to look like? We can actually make some predictions using knowledge about neurons.&lt;/p&gt;

&lt;p&gt;The nuance of the brain’s mechanics are largely unsolved, but we do understand certain base behaviors in the brain. For example, we have a decent understanding of individual neurons. &lt;a href=&quot;https://en.wikipedia.org/wiki/Biological_neuron_model#Leaky_integrate-and-fire&quot;&gt;It’s common to model neurons as leaky integrators.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Leaky_integrator&quot;&gt;Leaky integrators are essentially a kind of “forgetful” integration of incoming signals defined by the following equation:&lt;/a&gt;&lt;/p&gt;

\[dx/dt = -Ax+C(t)\]

&lt;p&gt;Where $C(t)$ is the input and $A$ is the rate of leakage. Note that without the first term, we’d have $dx/dt=C(t)$, and thus $x(t)$ would just be the integral of our input function. but the $-Ax$ term contributes a reversion towards 0 over time which erases old information.&lt;/p&gt;

&lt;p&gt;For neurons, the input would be the sum of all the neighboring neurons. Obviously, this system is too complex to model in depth, but we can take a toy model and make some observations. For example, what if the input was just random noise?&lt;/p&gt;

&lt;p&gt;A leaky integrator whose input is essentially just Gaussian noise is actually well-studied model called the &lt;a href=&quot;https://en.wikipedia.org/wiki/Ornstein%E2%80%93Uhlenbeck_process&quot;&gt;Ornstein-Uhlenbeck process&lt;/a&gt; and can be modeled using the stochastic differential equation&lt;/p&gt;

\[dx_t = -\theta x_t dt + \sigma dW_t\]

&lt;p&gt;where $\theta &amp;gt; 0$ and $\sigma &amp;gt; 0$ are parameters and $W_t$ denotes the &lt;a href=&quot;https://en.wikipedia.org/wiki/Wiener_process&quot;&gt;Weiner process&lt;/a&gt;. Basically, you’ve got some random Gaussian stimulus and a tendency to revert to 0.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2025-09-01-brain-timescales/OU_process_example.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://math.stackexchange.com/questions/2772511/autocorrelation-of-ou-process&quot;&gt;An interesting property of Ornstein-Uhlenbeck processes is that the autocorrelation is an exponential.&lt;/a&gt; (Note: Woah! Ito calculus!)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2025-09-01-brain-timescales/OU_autocorrelation_example.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;My understanding is that researchers similarly assume neurons will act like leaky integrators in a noisy environment, and thus the autocorrelation of neuron spike counts will be exponential. For example, &lt;a href=&quot;https://johndmurray.org/papers/murray_2014_nn.pdf&quot;&gt;Murray’s 2014 paper&lt;/a&gt; regressed on the autocorrelation data using&lt;/p&gt;

\[R(k\Delta)=A[\exp(-\frac{k\Delta}{\tau})+B]\]

&lt;p&gt;where $k\Delta$ is the lag time in ms and $\tau$ is called the intrinsic timescale of the region. Regression determines $A$, $B$, and $\tau$. Mathematically, when $k\Delta = \tau$, the exponential will have decayed to about 37% of its maximum contribution, which is why $\tau$ serves as a nice indicator of the general timescale of the exponential.&lt;/p&gt;

&lt;p&gt;Whatever the motivation for the use of exponentials, they’re commonly used to approximate timescales, they tend to fit the data well, and many papers that use them are highly cited. The academic community seems quite receptive to the idea of timescales in the brain that can be quantified by regressing the autocorrelations of neuron spike counts.&lt;/p&gt;

&lt;h1 id=&quot;anything-else&quot;&gt;Anything else?&lt;/h1&gt;

&lt;p&gt;I’m not sure there’s a whole lot more to say about this topic. There is some other interesting research. &lt;a href=&quot;https://www.nature.com/articles/s41467-023-37613-7&quot;&gt;This new paper suggests that the intrinsic timescales of regions can vary during cognitive tasks or that there can be multiple timescales.&lt;/a&gt; In the plot below, you can see the log-linear plot of the autocorrelation of neuron spike counts. Recall that usually the autocorrelation is an exponential, so the log-linear plot would be a straight line.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2025-09-01-brain-timescales/two_timescales_data.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The authors claim there are actually two regimes here, indicated by the elbow at around 40ms. This indicates that the spike counts have two dominant timescales.&lt;/p&gt;

&lt;p&gt;I tried to do a little simulation to see if I could generate data with similar behavior. As a baseline, here’s the autocorrelation for a standard Ornstein-Uhlenbeck process on a log-linear plot:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2025-09-01-brain-timescales/OU_autocorrelation_baseline.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You can see it’s approximately linear (Note: I think the tail falling off is due to the finite data and the way I measure? Not sure…). To get data with two timescales, I summed two OU processes with different timescales. The result looks like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2025-09-01-brain-timescales/sum_two_OUs.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;And I think the timescale division should be at around 2.0-2.5? Hard to say for sure, but I think I see it.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2025-09-01-brain-timescales/sum_two_OUs_regressed.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This is pretty hacky and might not be valid. It’s also irrelevant to hierarchical reasoning models, but it was interesting to see what’s currently being studied in neuroscience.&lt;/p&gt;

&lt;h1 id=&quot;conclusion-and-whats-next&quot;&gt;Conclusion and what’s next&lt;/h1&gt;

&lt;p&gt;It’s pretty interesting to see what we know about the brain and how we think. There are a few other interesting citations in the HRM paper that I want to investigate. For example, &lt;a href=&quot;https://www.nature.com/articles/s41586-024-07522-w&quot;&gt;Language is primarily a tool for communication rather than thought&lt;/a&gt; caught my eye.&lt;/p&gt;

&lt;p&gt;I’d also like to look at HRMs themselves and see what they’re actually meant to do. If nothing else, it’s a pretty interesting read, and the results thus far have been promising. It will be interesting if someone tries to scale them up.&lt;/p&gt;

&lt;p&gt;Another note is that this article was hacked together very quickly after a few days of skimming papers and ruminating. I’m experimenting with a faster composition process motivated by the fact that no one reads my shit anyways. Why should I polish if the vast majority of engagement is only surface level?&lt;/p&gt;

&lt;p&gt;If I’m being honest with myself, my articles were only ever intended to be bait that lures interested parties into having discussions with me. I think articles with this level of quality could still serve that purpose. They don’t need to be targeted at a mass audience. On the other hand, I haven’t had a lot of time to play devil’s advocate and be critical of my own thought process, so hopefully there are no more delusions or blatant errors than usual.&lt;/p&gt;

&lt;p&gt;Lastly, the math around autocorrelation of OU processes is really interesting. It might be the first time I’ve ever “needed” Ito calculus. That was quite a thrill. I might hang around in this subject matter for a bit.&lt;/p&gt;</content><author><name>Beau Horenberger</name></author><category term="blog" /><summary type="html"></summary></entry><entry><title type="html">More interesting links</title><link href="/2025/06/22/interesting-links-again.html" rel="alternate" type="text/html" title="More interesting links" /><published>2025-06-22T00:00:00-04:00</published><updated>2025-06-22T00:00:00-04:00</updated><id>/2025/06/22/interesting-links-again</id><content type="html" xml:base="/2025/06/22/interesting-links-again.html">&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.filfre.net/2025/06/alpha-centauri/&quot;&gt;On Sid Meyers’s Alpha Centuri&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://smoothbrains.net/posts/2025-06-15-estrogen.html&quot;&gt;Estrogen: A Trip Report&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;I love phenomenological reports like this. It’s always a good reminder that there’s a lot of nuance to human experience that can be qualified by just being more attentive. I need to be more mindful of this; it’s a nice hobby that can be practiced anywhere, any time.&lt;/li&gt;
      &lt;li&gt;
        &lt;blockquote&gt;
          &lt;p&gt;I can almost envision everything on our street coming apart piece by piece like an exploded technical diagram. The asphalt, the curb, the patches of grass, all of them could just lift into the air and drift apart, nothing but thin surfaces, almost like abstractions or mere representations. If I were to take a shovel and start digging a hole in the road, it would just be an indentation in that surface, pushing it to extend a bit in one direction or another – but underneath it, nothing. The houses along the street are just outgrowths of the surface, a sort of puckering in it, like a ball on a rubber sheet to demonstrate how gravity is the curvature of spacetime.&lt;/p&gt;
        &lt;/blockquote&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://a.carapetis.com/csf/&quot;&gt;Curve-shortening flow&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.asimov.press/p/slime&quot;&gt;Life as slime&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://arxiv.org/abs/2505.24832&quot;&gt;How much do language models memorize?&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;I did &lt;a href=&quot;https://horenbergerb.github.io/2025/06/12/meta-memory-first-look.html&quot;&gt;a big writeup on this.&lt;/a&gt; The theory is really cool; it’s very impressive to see a simple mathematical model of rote memorization vs generalization applied to actual ML algorithms.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;</content><author><name>Beau Horenberger</name></author><category term="diary" /><summary type="html">On Sid Meyers’s Alpha Centuri Estrogen: A Trip Report I love phenomenological reports like this. It’s always a good reminder that there’s a lot of nuance to human experience that can be qualified by just being more attentive. I need to be more mindful of this; it’s a nice hobby that can be practiced anywhere, any time. I can almost envision everything on our street coming apart piece by piece like an exploded technical diagram. The asphalt, the curb, the patches of grass, all of them could just lift into the air and drift apart, nothing but thin surfaces, almost like abstractions or mere representations. If I were to take a shovel and start digging a hole in the road, it would just be an indentation in that surface, pushing it to extend a bit in one direction or another – but underneath it, nothing. The houses along the street are just outgrowths of the surface, a sort of puckering in it, like a ball on a rubber sheet to demonstrate how gravity is the curvature of spacetime. Curve-shortening flow Life as slime How much do language models memorize? I did a big writeup on this. The theory is really cool; it’s very impressive to see a simple mathematical model of rote memorization vs generalization applied to actual ML algorithms.</summary></entry><entry><title type="html">Paper Review: How much do language models memorize?</title><link href="/2025/06/12/meta-memory-first-look.html" rel="alternate" type="text/html" title="Paper Review: How much do language models memorize?" /><published>2025-06-12T00:00:00-04:00</published><updated>2025-06-12T00:00:00-04:00</updated><id>/2025/06/12/meta-memory-first-look</id><content type="html" xml:base="/2025/06/12/meta-memory-first-look.html">&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#intro&quot; id=&quot;markdown-toc-intro&quot;&gt;Intro&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#setup&quot; id=&quot;markdown-toc-setup&quot;&gt;Setup&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#memory-definitions&quot; id=&quot;markdown-toc-memory-definitions&quot;&gt;Memory definitions&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#toy-example&quot; id=&quot;markdown-toc-toy-example&quot;&gt;Toy Example&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#prior-dataset-and-model&quot; id=&quot;markdown-toc-prior-dataset-and-model&quot;&gt;Prior, dataset, and model&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#preliminary-entropy-calculations&quot; id=&quot;markdown-toc-preliminary-entropy-calculations&quot;&gt;Preliminary entropy calculations&lt;/a&gt;        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#total-entropy-hx&quot; id=&quot;markdown-toc-total-entropy-hx&quot;&gt;Total entropy $H(X)$&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#conditional-entropy-hxverttheta&quot; id=&quot;markdown-toc-conditional-entropy-hxverttheta&quot;&gt;Conditional entropy $H(X\vert\Theta)$&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#memory-calculations&quot; id=&quot;markdown-toc-memory-calculations&quot;&gt;Memory calculations&lt;/a&gt;        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#mutual-information-total-memorization&quot; id=&quot;markdown-toc-mutual-information-total-memorization&quot;&gt;Mutual Information (Total Memorization)&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#unintended-memorization-rote&quot; id=&quot;markdown-toc-unintended-memorization-rote&quot;&gt;Unintended Memorization (Rote)&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#intended-memorization-generalization&quot; id=&quot;markdown-toc-intended-memorization-generalization&quot;&gt;Intended Memorization (Generalization)&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#discussion&quot; id=&quot;markdown-toc-discussion&quot;&gt;Discussion&lt;/a&gt;        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#textmem_i--textmem_u-what-it-doesnt-mean&quot; id=&quot;markdown-toc-textmem_i--textmem_u-what-it-doesnt-mean&quot;&gt;$\text{mem}_I &amp;gt; \text{mem}_U$: what it doesn’t mean&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#last-look-at-the-memory-math&quot; id=&quot;markdown-toc-last-look-at-the-memory-math&quot;&gt;Last look at the memory math&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-rest-of-the-paper-how-useful-is-this-theory&quot; id=&quot;markdown-toc-the-rest-of-the-paper-how-useful-is-this-theory&quot;&gt;The rest of the paper: how useful is this theory?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusion&quot; id=&quot;markdown-toc-conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;intro&quot;&gt;Intro&lt;/h1&gt;

&lt;p&gt;I saw &lt;a href=&quot;https://arxiv.org/pdf/2505.24832&quot;&gt;this paper by Meta,&lt;/a&gt; and it really impressed me. At a glance, it seems like it’s a solid mathematical approach to distinguishing between rote memorization vs generalization. I really liked the mathematics, so I thought I’d play with it a bit and make some observations.&lt;/p&gt;

&lt;p&gt;This article spends a lot of time elaborating on section 2.1, which establishes the fundamental premise by defining a quantitative distinction between rote memorization of a dataset and generalization to the true underlying prior.&lt;/p&gt;

&lt;p&gt;I also talk about how they used Kolmogorov complexity to make these calculations tractable with typical ML models. This boils down pretty quickly to a handful of equations, and after distilling it, I have some doubts.&lt;/p&gt;

&lt;h1 id=&quot;setup&quot;&gt;Setup&lt;/h1&gt;

&lt;p&gt;All of the derivations of interest here revolve around a prior distribution, $\Theta$, a dataset distribution, $X$, and a trained model, $\hat{\Theta}$. Let’s define these.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;prior distribution&lt;/strong&gt;, $\Theta$, is a distribution that represents the actual data. This is “the real world,” in a sense. In most cases, we know very little about this distribution.&lt;/p&gt;

&lt;p&gt;We can build a &lt;strong&gt;dataset distribution&lt;/strong&gt; $X$ using samples of $\Theta$. There are many ways to do this. A simple example would be to a partial observation of $\Theta$, break it into “samples,” then define $X$ as a uniform distribution over the samples. Note that, because we create $X$ by using $\Theta$, the dataset $X$ is conditioned by the properties of $\Theta$. In other words, $X$ contains information about $\Theta$.&lt;/p&gt;

&lt;p&gt;Finally, we can train a &lt;strong&gt;model&lt;/strong&gt; $\hat{\Theta}$ to imitate $\Theta$. The model is also a distribution. The training of $\hat{\Theta}$ can be considered a function of samples $x \sim X$.  $\hat{\Theta}$ is intended to imitate $\Theta$, but it often ends up knowing more about $X$ and less about $\Theta$.&lt;/p&gt;

&lt;h1 id=&quot;memory-definitions&quot;&gt;Memory definitions&lt;/h1&gt;

&lt;p&gt;Let $H(X)$ denote the entropy of $X$. They also call this the “amount of information present in X.” Then let $X \vert Y$ be the uncertainty left in $X$ after fixing $Y$. We define the &lt;strong&gt;mutual information&lt;/strong&gt; between two distributions as&lt;/p&gt;

\[I(X; Y) = H(X) - H(X \vert Y)\]

&lt;p&gt;This represents the information about $X$ that stored in $Y$. For example if $Y = 2X$, then $H(X\vert Y) = H(X\vert 2X) = 0$, since $Y$ determines $X$ completely, and thus $I(X;Y)=H(X)$. So Y contains all of the information about X.&lt;/p&gt;

&lt;p&gt;Now we can use this to define the different kinds of memory. Recall that we’d like for our model $\hat\Theta$ to learn about and act like the prior, $\Theta$. In practice, $\hat\Theta$ often behaves more like the training dataset $X$ than the true prior distribution.&lt;/p&gt;

&lt;p&gt;We can rephrase this in terms of information. What amount of information does the model $\hat\Theta$ contain about $X$ and $\Theta$?&lt;/p&gt;

&lt;p&gt;First, we define the &lt;strong&gt;total memorization&lt;/strong&gt;. This represents all of the information about $X$ stored in $\hat{\Theta}$. The definition just the mutual information between the two:&lt;/p&gt;

\[\text{mem}(X, \hat{\Theta}) = I(X; \hat{\Theta}) = H(X) - H(X \vert \hat{\Theta})\]

&lt;p&gt;The following definitions are more interesting. Next up is &lt;strong&gt;unintended memorization&lt;/strong&gt;. This represents rote memorization of information which is relevant to the dataset $X$ but not representative of the true prior $\Theta$.&lt;/p&gt;

&lt;p&gt;To measure this, we look at the information remaining in $X$ after fixing $\Theta$ and measure the mutual information with the model, $\hat\Theta$:&lt;/p&gt;

\[\text{mem}_U = I([X \vert \Theta]; \hat{\Theta}) = H(X \vert \Theta) - H(X \vert \Theta, \hat{\Theta})\]

&lt;p&gt;Again, this mathematically means it’s the information that $\hat\Theta$ contains about $X$ which does not apply to the underlying prior $\Theta$.&lt;/p&gt;

&lt;p&gt;Finally, we have the &lt;strong&gt;intended memorization&lt;/strong&gt;, which is information that truly generalizes to the underlying prior. We get this by subtracting the rote memorization from the total memorization:&lt;/p&gt;

\[\text{mem}_I = \text{mem}(X, \hat{\Theta}) - \text{mem}_U(X, \hat{\Theta}, \Theta) = I(X; \hat{\Theta}) - I(X \vert \Theta; \hat{\Theta})\]

&lt;p&gt;Intuitively, this also makes sense. It’s the information about $X$ contained by $\hat\Theta$ after subtracting any information about $X$ that is not applicable to the prior $\Theta$. $\text{mem}_I$ represents the learned information that also applies to the prior.&lt;/p&gt;

&lt;h1 id=&quot;toy-example&quot;&gt;Toy Example&lt;/h1&gt;

&lt;p&gt;In the real world, we’d probably have the prior $\Theta$ be the true distribution for human language, and $X$ be constructed by some sampling process.&lt;/p&gt;

&lt;p&gt;That’s not very tractable, so we’ll just pick some simple distributions and crunch through some calculations.&lt;/p&gt;

&lt;h2 id=&quot;prior-dataset-and-model&quot;&gt;Prior, dataset, and model&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Prior $\Theta$ (underlying model):&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;$\Theta$ is a fair coin: $\Theta \in {0,1}$ with $P(\Theta=0) = P(\Theta=1) = 0.5$.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Dataset $X$:&lt;/strong&gt;
You would probably expect this to be a uniform distribution over some collected samples $\theta \sim \Theta$, but I’m going to do something more interesting.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;If $\Theta=0$, $X \sim \text{Bernoulli}(0.1)$ (biased “tails”)&lt;/li&gt;
  &lt;li&gt;If $\Theta=1$, $X \sim \text{Bernoulli}(0.9)$ (biased “heads”)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I do this for two reasons:
1) We can still create interesting distributions for $X$ using a single sample from $\Theta$. This simplifies the math a little.
2) This demonstrates that the theory works even if the relationship between the dataset $X$ and prior $\Theta$ isn’t straightforward. There could be noise, or the sampled data could have some nontrivial indirect relationship to the actual data of interest&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trained model $\hat{\Theta}$:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The model is a stupid solution that’s “trained” on a single sample $x \sim X$ sampled from $X$:&lt;/p&gt;

\[\hat{\Theta} = \begin{cases} 
  0 &amp;amp; \text{if } x = 0 \\
  1 &amp;amp; \text{if } x = 1 
\end{cases}\]

&lt;h2 id=&quot;preliminary-entropy-calculations&quot;&gt;Preliminary entropy calculations&lt;/h2&gt;
&lt;h3 id=&quot;total-entropy-hx&quot;&gt;Total entropy $H(X)$&lt;/h3&gt;

&lt;p&gt;Recall that $H(X) = -\sum P(x) \log_2 P(x)$. Then&lt;/p&gt;

\[P(x=0) = P(\Theta=0)P(x=0\vert\Theta=0) + P(\Theta=1)P(x=0\vert\Theta=1) = (0.5)(0.9) + (0.5)(0.1) = 0.5\]

&lt;p&gt;and&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;$P(x=1) = (0.5)(0.1) + (0.5)(0.9) = 0.5$&lt;/li&gt;
  &lt;li&gt;$H(X) = -[0.5 \log_2(0.5) + 0.5 \log_2(0.5)] = 1$&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the total entropy of $H(X)$ is 1 bit, i.e. the same entropy as a single unbiased coin flip. At a glance, that’s believable.&lt;/p&gt;

&lt;h3 id=&quot;conditional-entropy-hxverttheta&quot;&gt;Conditional entropy $H(X\vert\Theta)$&lt;/h3&gt;

&lt;p&gt;Recall that $H(X\vert\Theta) = \sum P(\theta) H(X\vert\Theta=\theta)$. Then&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;$H(X\vert\Theta=0) = -[0.9 \log_2(0.9) + 0.1 \log_2(0.1)] \approx 0.469$ bits&lt;/li&gt;
  &lt;li&gt;$H(X\vert\Theta=1) = -[0.1 \log_2(0.1) + 0.9 \log_2(0.9)] \approx 0.469$ bits&lt;/li&gt;
  &lt;li&gt;$H(X\vert\Theta) = 0.5(0.469) + 0.5(0.469) \approx 0.469$ bits&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the information remaining in $X$ after fixing $\Theta$ is about 0.469 bits. That also makes sense; knowing $\Theta$ tells us quite a bit about $X$.&lt;/p&gt;

&lt;p&gt;Note: It’s interesting that the biased coin flip $\text{Bernoulli}(0.1)$ has about half the entropy of the unbiased coin flip $\text{Bernoulli}(0.5)$ (0.469 bits vs 1 bit). It doesn’t feel like there’s half as much uncertainty; it seems substantially more determined. But I suppose that’s a problem with my own intuition.&lt;/p&gt;

&lt;h2 id=&quot;memory-calculations&quot;&gt;Memory calculations&lt;/h2&gt;
&lt;h3 id=&quot;mutual-information-total-memorization&quot;&gt;Mutual Information (Total Memorization)&lt;/h3&gt;

&lt;p&gt;Recall that&lt;/p&gt;

\[\text{mem}(X,\hat{\Theta}) = I(X;\hat{\Theta}) = H(X) - H(X\vert\hat{\Theta})\]

&lt;p&gt;Since we defined $\hat{\Theta}=x$, where $x \sim X$, knowing $\hat\Theta$ means we know $X$ too, so $H(X\vert\hat{\Theta}) = 0$.&lt;/p&gt;

&lt;p&gt;Therefore, $I(X;\hat{\Theta}) = 1 - 0 = 1$ bit. Thus, the total memorized information is 1 bit.&lt;/p&gt;

&lt;p&gt;Note: My interpretation of this formula is that we learned everything there is to learn about $X$. We essentially maximized $\text{mem}(X,\hat{\Theta})$ for a fixed $X$ by mimicking the data. However, we will see shortly that generalization still occurred.&lt;/p&gt;

&lt;h3 id=&quot;unintended-memorization-rote&quot;&gt;Unintended Memorization (Rote)&lt;/h3&gt;

&lt;p&gt;Recall that&lt;/p&gt;

\[\text{mem}_U = I([X\vert\Theta];\hat{\Theta}) = H(X\vert\Theta) - H(X\vert\Theta,\hat{\Theta})\]

&lt;p&gt;As before, given $\Theta$ and $\hat{\Theta}$, $X$ is fully determined, so $H(X\vert\Theta,\hat{\Theta}) = 0$. Thus, $\text{mem}_U = 0.469 - 0 = 0.469$ bits.&lt;/p&gt;

&lt;h3 id=&quot;intended-memorization-generalization&quot;&gt;Intended Memorization (Generalization)&lt;/h3&gt;

&lt;p&gt;This follows trivially from the previous calculations:&lt;/p&gt;

&lt;p&gt;\(\text{mem}_I = I(X;\hat{\Theta}) - \text{mem}_U = 1 - 0.469 = 0.531\) So there are 0.531 bits of intended memorization.&lt;/p&gt;

&lt;h2 id=&quot;discussion&quot;&gt;Discussion&lt;/h2&gt;

&lt;p&gt;So we had a dataset $X$ with 1 bit of entropy. Our trained model $\hat\Theta$ has 1 bit of mutual information or total memorization. This breaks down into 0.469 bits of rote memorization, and 0.531 bits of memorization.&lt;/p&gt;

&lt;p&gt;What’s odd to me is that our model $\hat\Theta$ was explicitly defined as a rote memorization of $X$, and yet it supposedly has more generalization than memorization.&lt;/p&gt;

&lt;p&gt;I think what it comes down to is that these values are based on particular samples of $\theta\sim\Theta$ and $x\sim X$. Once the samples have been made, these calculations tell us what we’ve learned about $x$ and $\theta$. In this case, $X\vert\Theta$ has less uncertainty; $x$ is highly likely to be determined by $\theta$. On the flip side, $\theta$ is highly uncertain by itself, but $x$ gives us a strong clue about what $\theta$ probably is.&lt;/p&gt;

&lt;h3 id=&quot;textmem_i--textmem_u-what-it-doesnt-mean&quot;&gt;$\text{mem}_I &amp;gt; \text{mem}_U$: what it doesn’t mean&lt;/h3&gt;

&lt;p&gt;Despite the fact that we mathematically generalized more than we memorized, one could easily argue that $\hat\Theta$ is a better approximation of $X$ than of $\Theta$.&lt;/p&gt;

&lt;p&gt;Let’s look at the accuracy of our trained model in the case where $\Theta = 0$ and thus $X \sim \text{Bernoulli}(0.1)$ (There’s a symmetry with $\text{Bernoulli}(0.9)$, so our calculations are also true if $\Theta=1$).&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;90% chance that the training data $x\sim X$ was tails, so $\hat\Theta$ would be correct 90% of the time.&lt;/li&gt;
  &lt;li&gt;10% chance that the training data $x \sim X$ was heads, so $\hat\Theta$ would be correct 10% of the time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the average accuracy is $(0.9)(0.9) + (0.1)(0.1) = 0.82$, i.e. an overall 82% accuracy rate across trained models.&lt;/p&gt;

&lt;p&gt;Compare this to the baseline of randomly guessing:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;50% chance of guessing tails, 90% chance of $X$ being tails&lt;/li&gt;
  &lt;li&gt;50% chance of guessing heads, 10% chance of $X$ being heads.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this case, the average accuracy is $(0.5)(0.9) + (0.5)(0.1) = 0.5$, or 50% accuracy. So it’s clear our training process generally produces an improved representation of $X$.&lt;/p&gt;

&lt;p&gt;On the flip side, the best possible accuracy is 90%. If we were able to train on more samples, we could approach this accuracy.&lt;/p&gt;

&lt;p&gt;Conversely, if we compare $\hat\Theta$ to $\Theta$, our trained model will always have 50% accuracy, regardless of the training process. On one hand, we have worse accuracy in general, but on the other, we’ve also achieved the best possible accuracy.&lt;/p&gt;

&lt;p&gt;This means that we have better accuracy on $X$ than we do on $\Theta$, which makes sense, since we literally memorized an observation of $X$.&lt;/p&gt;

&lt;p&gt;Accuracy is not the same thing as entropy, but I think this approach helps us delineate what the theory is and is not saying about our models. Having $\text{mem}_I &amp;gt; \text{mem}_U$ does not mean our model is better at representing the prior $\Theta$ than the dataset $X$.&lt;/p&gt;

&lt;p&gt;What we are saying, more explicitly, is that the information contained in $\hat\Theta$ tells us a lot about $\Theta$. The same information might also inform us about $X$, but there’s not much information that tells us &lt;em&gt;only&lt;/em&gt; about $X$ and not $\Theta$.&lt;/p&gt;

&lt;h3 id=&quot;last-look-at-the-memory-math&quot;&gt;Last look at the memory math&lt;/h3&gt;

&lt;p&gt;The explanation necessarily lies in the mathematical definitions. If we look at unintended memorization:&lt;/p&gt;

\[\text{mem}_U = I([X\vert\Theta];\hat{\Theta}) = H(X\vert\Theta) - H(X\vert\Theta,\hat{\Theta})\]

&lt;p&gt;Unintended (or rote) memorization is bounded above by $H(X\vert\Theta)$, i.e. the information unique to $X$ after fixing $\Theta$. From our calculations above, we know this value is already small: $H(X\vert\Theta) \approx 0.469$ bits. There’s a lot less uncertainty in $X\vert \Theta$ than there is in $\Theta$ (1 bit), which means there’s less information to learn about $X$ once $\Theta$ is determined; we won’t be that surprised by the training data.&lt;/p&gt;

&lt;p&gt;But we also know that our model “learned” exactly one bit of information in total:&lt;/p&gt;

\[\text{mem}(X,\hat{\Theta}) = H(X) - H(X\vert\hat{\Theta}) = 1-0 = 1\]

&lt;p&gt;The amount that $\hat\Theta$ can memorize in total (information about $X$ and $\Theta$) is bounded above by $H(X)$. Why is that? Intuitively, it’s because $X$ is the only thing the model ever sees. However, by the properties of entropy,&lt;/p&gt;

\[H(X) = H(\Theta, X) - H(\Theta\vert X)\]

&lt;p&gt;So this upper bound on what we can learn is, itself, bounded by the joint entropy $H(\Theta, X)$, and is larger if $X$ contains information about $\Theta$ (i.e. $H(\Theta\vert X)$ is small). This shared information is what we are gleaning when we generalize.&lt;/p&gt;

&lt;p&gt;It makes intuitive sense that $\hat\Theta$ is storing a bit of information; it remembers exactly one observation of a coin toss $x \sim X$. So it learned one bit of information, but there’s less than one bit of information unique to $X$ after fixing $\Theta$. Thus, memorizing $X$ also told us about $\Theta \vert X$, and there is more information to learn about $\Theta$ than there is to learn about $X\vert \Theta$.&lt;/p&gt;

&lt;h1 id=&quot;the-rest-of-the-paper-how-useful-is-this-theory&quot;&gt;The rest of the paper: how useful is this theory?&lt;/h1&gt;

&lt;p&gt;The authors note that this formulation doesn’t work for real life cases, since we can’t calculate entropy from singular observations like $\theta$ and $x$ if the underlying distributions aren’t known. They use Kolmogorov complexity to argue that you can use a predictive model’s likelihoods to approximate Kalmogorov complexity:&lt;/p&gt;

\[H^K(x \mid \hat{\theta}) \approx -\log_2 p(x \mid \hat{\theta})\]

&lt;p&gt;I think this is supposed to follow from Shannon’s source coding theorem? And then that Kalmogorov complexity can be used to approximate entropy:&lt;/p&gt;

\[\mathbb{E}_{x\sim X}[H^K(x)] \approx H(X)\]

&lt;p&gt;So, in the end, they are literally just doing simple math with the trained models’ outputted logprobs to calculate entropies. It’s so simple that it makes me suspicious, but after stewing on it for a while, I find it believable.&lt;/p&gt;

&lt;p&gt;On the other hand, this new approximation is not a magical cheat code. It seems like they still can only calculate unintended memorization (and not total or intended memorization) for non-synthetic datasets. This is because there’s no way to calculate $H(X)$ for non-synthetic data. As a result, the applicability is somewhat limited.&lt;/p&gt;

&lt;p&gt;Even for unintended memorization, $H(X\vert\Theta,\hat{\Theta})$ is hard to compute. They use an oracle model and approximate the value using&lt;/p&gt;

\[\max\{p(x\vert\hat\theta),p(x\vert\theta)\}\]

&lt;p&gt;I would like to hear more reasoning about the use of oracle models. Why do we expect these to be a good approximation of $H(X\vert\Theta,\hat{\Theta})$? I guess it makes sense if you generally believe that LLMs approach the true distribution as they get larger and train on more data. But I wonder how different the results would look depending on the choice of oracle.&lt;/p&gt;

&lt;p&gt;All this being said, the results they claim seem believable and intuitive, so maybe it all just works. Who am I to talk shit?&lt;/p&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;This paper is cool and gave me a lot to think about.&lt;/p&gt;

&lt;p&gt;I did find it interesting to stumble upon an example in which literal memorization of training data produces, mathematically, more generalization than rote memorization. I’m not sure that it really matters in the grand scheme of things, but it is a fun brain teaser.&lt;/p&gt;

&lt;p&gt;&lt;del&gt;The jump from model logprobs to entropy approximations feels sketchy to me. I’d love for it to be true, but I need to think harder about it.&lt;/del&gt; Edit (06/19/25: I’m feeling better about this now). The empirical results seem believable, though, and I do think this is still a fun read and suggests future experiments.&lt;/p&gt;

&lt;p&gt;I’d like to see more fiddling with synthetic datasets to determine what kind of data various ML architectures can or cannot learn.&lt;/p&gt;

&lt;p&gt;So yeah, nice paper. Good job.&lt;/p&gt;</content><author><name>Beau Horenberger</name></author><category term="blog" /><summary type="html"></summary></entry><entry><title type="html">Nobody reads my blog</title><link href="/2025/05/12/nobody-reads-my-stuff.html" rel="alternate" type="text/html" title="Nobody reads my blog" /><published>2025-05-12T00:00:00-04:00</published><updated>2025-05-12T00:00:00-04:00</updated><id>/2025/05/12/nobody-reads-my-stuff</id><content type="html" xml:base="/2025/05/12/nobody-reads-my-stuff.html">&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#where-are-the-modular-forms-enthusiasts&quot; id=&quot;markdown-toc-where-are-the-modular-forms-enthusiasts&quot;&gt;Where are the modular forms enthusiasts?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#how-many-people-are-thinking-about-modular-forms&quot; id=&quot;markdown-toc-how-many-people-are-thinking-about-modular-forms&quot;&gt;How many people are thinking about modular forms?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#how-many-modular-forms-enthusiasts-have-a-web-presence&quot; id=&quot;markdown-toc-how-many-modular-forms-enthusiasts-have-a-web-presence&quot;&gt;How many modular forms enthusiasts have a web presence?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-math-shows-that-i-am-alone&quot; id=&quot;markdown-toc-the-math-shows-that-i-am-alone&quot;&gt;The math shows that I am alone&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#comparison-with-my-websites-analytics&quot; id=&quot;markdown-toc-comparison-with-my-websites-analytics&quot;&gt;Comparison with my website’s analytics&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#academia-is-hogging-all-the-writers&quot; id=&quot;markdown-toc-academia-is-hogging-all-the-writers&quot;&gt;Academia is hogging all the writers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#what-am-i-supposed-to-do&quot; id=&quot;markdown-toc-what-am-i-supposed-to-do&quot;&gt;What am I supposed to do?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#enough-rambling-wrap-it-up&quot; id=&quot;markdown-toc-enough-rambling-wrap-it-up&quot;&gt;Enough rambling. Wrap it up.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;where-are-the-modular-forms-enthusiasts&quot;&gt;Where are the modular forms enthusiasts?&lt;/h1&gt;

&lt;p&gt;When I was doing my undergrad, I studied modular forms. I found them very interesting; they have deep connections to the frontier of mathematics and were critical to proving Fermat’s Last Theorem.&lt;/p&gt;

&lt;p&gt;It has always bothered me that there wasn’t more discussion about them online. The internet feels so large; surely there must be a cozy little forum out there somewhere for modular form enthusiasts?&lt;/p&gt;

&lt;p&gt;I decided to do some quick approximations to figure out how it is that almost no one on the internet discusses modular forms. How many people are thinking about modular forms, and how many of them have a presence on the web?&lt;/p&gt;

&lt;h1 id=&quot;how-many-people-are-thinking-about-modular-forms&quot;&gt;How many people are thinking about modular forms?&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;https://arxiv.org/search/advanced?advanced=&amp;amp;terms-0-operator=AND&amp;amp;terms-0-term=modular+form&amp;amp;terms-0-field=all&amp;amp;classification-mathematics=y&amp;amp;classification-physics_archives=all&amp;amp;classification-include_cross_list=include&amp;amp;date-filter_by=past_12&amp;amp;date-year=&amp;amp;date-from_date=&amp;amp;date-to_date=&amp;amp;date-date_type=submitted_date&amp;amp;abstracts=show&amp;amp;size=50&amp;amp;order=-announced_date_first&amp;amp;start=0&quot;&gt;Arxiv showed 414 results for “modular form” in the last year.&lt;/a&gt; At a glance, I saw 7 papers out of the first 50 that seemed to be unrelated, so I took that false positive rate and got $414-((414/50)7)\approx 356$ papers.&lt;/p&gt;

&lt;p&gt;Most papers seemed have between 1 and 3 authors. Suppose there could have been up to 10 people tangentially involved in each paper or working with the professors on modular forms.&lt;/p&gt;

&lt;p&gt;That means 3560 people were working on modular forms in the last year. This does not account for academics who did not publish in the last year, their students, and enthusiasts who don’t publish anything on Arxiv.&lt;/p&gt;

&lt;h1 id=&quot;how-many-modular-forms-enthusiasts-have-a-web-presence&quot;&gt;How many modular forms enthusiasts have a web presence?&lt;/h1&gt;

&lt;p&gt;The first 50 results have 96 unique authors.&lt;/p&gt;

&lt;p&gt;I selected 20 authors at random. For each author, I did a cursory google and checked if they had any active socials. This was limited to searching by name, but it’s pretty easy to find my social accounts and website, and I have no credentials, no publications, and very few views.&lt;/p&gt;

&lt;p&gt;Unless otherwise mentioned, “Website” means a mostly-static page updated only to list recent publications. Generally, “Website” is a disappointing result; it’s the bare minimum to affirm you exist at all on the web. This is as opposed to “Blog” or some other actively-generated content like an X profile.&lt;/p&gt;

&lt;p&gt;I’ve scrubbed the names here for anonymity, although it’s not really necessary.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Name&lt;/th&gt;
      &lt;th&gt;Location&lt;/th&gt;
      &lt;th&gt;Status&lt;/th&gt;
      &lt;th&gt;Web Presence&lt;/th&gt;
      &lt;th&gt;Notes&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;**&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;South Korea&lt;/td&gt;
      &lt;td&gt;Professor&lt;/td&gt;
      &lt;td&gt;Website&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;**&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;China&lt;/td&gt;
      &lt;td&gt;Unclear&lt;/td&gt;
      &lt;td&gt;None&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;**&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Colorado&lt;/td&gt;
      &lt;td&gt;Assistant Professor&lt;/td&gt;
      &lt;td&gt;Website&lt;/td&gt;
      &lt;td&gt;His paper was a false positive. Nice website&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;**&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Ireland&lt;/td&gt;
      &lt;td&gt;Postdoc&lt;/td&gt;
      &lt;td&gt;Website&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;**&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Switzerland&lt;/td&gt;
      &lt;td&gt;Postdoc&lt;/td&gt;
      &lt;td&gt;Website&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;**&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Germany&lt;/td&gt;
      &lt;td&gt;Postdoc&lt;/td&gt;
      &lt;td&gt;None&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;**&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Tennessee&lt;/td&gt;
      &lt;td&gt;Postdoc&lt;/td&gt;
      &lt;td&gt;Website&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;**&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Kentucky&lt;/td&gt;
      &lt;td&gt;Associate Professor&lt;/td&gt;
      &lt;td&gt;Website&lt;/td&gt;
      &lt;td&gt;Another false positive. He is at least mentioned on X occasionally&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;**&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;French Polynesia&lt;/td&gt;
      &lt;td&gt;Professor&lt;/td&gt;
      &lt;td&gt;Website&lt;/td&gt;
      &lt;td&gt;Nice website, looks old though&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;**&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;China&lt;/td&gt;
      &lt;td&gt;Assistant Professor&lt;/td&gt;
      &lt;td&gt;Website, Youtube Lectures&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;**&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Utah&lt;/td&gt;
      &lt;td&gt;Associate Professor&lt;/td&gt;
      &lt;td&gt;Website&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;**&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Spain&lt;/td&gt;
      &lt;td&gt;Professor&lt;/td&gt;
      &lt;td&gt;Website&lt;/td&gt;
      &lt;td&gt;One or two mentions on X&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;**&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;South Africa&lt;/td&gt;
      &lt;td&gt;Professor&lt;/td&gt;
      &lt;td&gt;Website, Youtube Lectures&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;**&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Turkey&lt;/td&gt;
      &lt;td&gt;Researcher&lt;/td&gt;
      &lt;td&gt;StackExchange&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;**&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;France&lt;/td&gt;
      &lt;td&gt;Masters Student&lt;/td&gt;
      &lt;td&gt;Github/Website&lt;/td&gt;
      &lt;td&gt;False positive&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;**&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Illinois&lt;/td&gt;
      &lt;td&gt;PhD Student&lt;/td&gt;
      &lt;td&gt;Website, Youtube Lectures&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;**&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;India&lt;/td&gt;
      &lt;td&gt;Assistant Professor&lt;/td&gt;
      &lt;td&gt;Website, Youtube, StackExchange&lt;/td&gt;
      &lt;td&gt;Some of the YouTube content looks good&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;**&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Hawaii&lt;/td&gt;
      &lt;td&gt;Professor&lt;/td&gt;
      &lt;td&gt;Website&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;**&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Minnesota&lt;/td&gt;
      &lt;td&gt;PostDoc Associate&lt;/td&gt;
      &lt;td&gt;None&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;**&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Japan&lt;/td&gt;
      &lt;td&gt;Professor Emeritus&lt;/td&gt;
      &lt;td&gt;Website&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;So there you have it: 0/20 have any substantial web presence beyond a static website and some YouTube videos that were incidentally uploaded by their university.&lt;/p&gt;

&lt;p&gt;Unfortunately, this makes it unclear what the actual rate is. It could be 1/20, 1/50, 1/100, or even worse. I’m not willing to do any more sampling by hand, so we can only speculate for now.&lt;/p&gt;
&lt;h1 id=&quot;the-math-shows-that-i-am-alone&quot;&gt;The math shows that I am alone&lt;/h1&gt;

&lt;p&gt;Supposing, optimistically, that 1 out of 20 modular form enthusiasts participates on the web at all, and given our estimate of 3560 participants in the community, that leaves $3560/20=178$ people on the web talking about modular forms.&lt;/p&gt;

&lt;p&gt;The best case is only 178 people split across a lot of different time zones and languages.&lt;/p&gt;

&lt;p&gt;I suspect 1 in 20 being active on the web is extremely generous. I would not be surprised at all to learn it’s more like 1/100 or worse.&lt;/p&gt;

&lt;p&gt;Further, I wouldn’t be surprised if assuming that there exists 10 unique enthusiasts per preprint published this year is also very generous.&lt;/p&gt;

&lt;p&gt;The lower bound is grim: if there are 5 unique enthusiasts per paper, and 1/100 are actively participating on the web, that leaves about 18 people.&lt;/p&gt;

&lt;h1 id=&quot;comparison-with-my-websites-analytics&quot;&gt;Comparison with my website’s analytics&lt;/h1&gt;

&lt;p&gt;I wrote &lt;a href=&quot;https://horenbergerb.github.io/2020/08/08/modularforms.html&quot;&gt;an article on the history of modular forms&lt;/a&gt; about five years ago. Between 01/01/2021 and 12/31/24, it got 53 views from 33 active users. That’s about 8 users per year stumbling upon my webpage.&lt;/p&gt;

&lt;p&gt;Certainly part of the problem is accessibility. My blog post doesn’t appear in a Google search for “modular forms history”, but it’s the second result if you search on Bing.&lt;/p&gt;

&lt;p&gt;If &lt;a href=&quot;https://www.impressiondigital.com/blog/bing-differ-google/&quot;&gt;Google has 10x more users than Bing&lt;/a&gt;, and pretending they’re the two dominant forces, we can imagine that 1 in 11 modular form enthusiasts use Bing and could find my blog post, but only if they were specifically searching for the history of modular forms.&lt;/p&gt;

&lt;p&gt;So 3560 people are thinking about modular forms. Out of those, only 323 of use Bing. I guess it’s believable that 10% of the 323 modular form enthusiasts who use Bing searched “modular forms history” in the last four years and found my website. That kinda makes sense.&lt;/p&gt;

&lt;p&gt;Actually, though, the number of people who found my page on modular forms by searching is probably lower than 33. 77% of my overall website traffic comes from direct links, while 14% comes from organic search, but &lt;a href=&quot;https://horenbergerb.github.io/2022/08/16/mysteryofthefrogriddle.html&quot;&gt;one page that went viral&lt;/a&gt; biases the data heavily towards direct links. I’d guess around 50% of the 33 users or less actually found the page by searching. The others were probably directly linked to the page by me.&lt;/p&gt;

&lt;p&gt;Overall, though, I think the takeaway here is that getting indexed higher in Google could potentially 10x my views, but it seems unlikely that the target audience for my modular forms article is larger than a few hundred people.&lt;/p&gt;

&lt;h1 id=&quot;academia-is-hogging-all-the-writers&quot;&gt;Academia is hogging all the writers&lt;/h1&gt;

&lt;p&gt;I doubt that many of the authors with preprints on Arxiv feel intellectually isolated. Academia does a good job of connecting academics that share niche interests, and there’s never a shortage of eager students who want to be brought on board for whatever research you happen to be doing.&lt;/p&gt;

&lt;p&gt;Unfortunately, prospects are grim outside the academic sphere. There are no casual readers looking for modular forms content. Realistically, even academics probably aren’t interested in unpublished rants on personal blogs with no credentials, especially articles dealing with math history rather than frontier mathematics. Similarly, writing their own blog posts will do little to further their career.&lt;/p&gt;

&lt;p&gt;I don’t claim that the approximations done here are irrefutable or even particularly accurate. I think it’s more of a cathartic experience for me.&lt;/p&gt;

&lt;p&gt;I don’t really think about modular forms any more, but for few years after college, I had this fantasy that, one day, someone would find my work and invite me into a sphere of like-minded individuals. I imagined a global network of enthusiasts digging into the history of mathematics, sharing their findings, and writing for each other without the institutional pressure of academia.&lt;/p&gt;

&lt;p&gt;The reality is that there are very few people with such interests, the vast majority of them are already in academia, and most academics don’t have a digital presence outside of their academic publications.&lt;/p&gt;

&lt;p&gt;There is still a lingering question of “why?” Why aren’t more people like me? &lt;a href=&quot;https://datausa.io/profile/cip/mathematics&quot;&gt;29,013 math degrees were awarded in the US in 2022.&lt;/a&gt; There must be hundreds of thousands of people with degrees in mathematics. What are they all thinking about? Where are their blogs? I do not know the answer to this.&lt;/p&gt;

&lt;h1 id=&quot;what-am-i-supposed-to-do&quot;&gt;What am I supposed to do?&lt;/h1&gt;

&lt;p&gt;I have changed the subject matter of my writing over time to try and appeal to a larger audience. I talk about machine learning, LLMs, computer science, and statistics. I’ve also worked on interactive web apps like &lt;a href=&quot;https://horenbergerb.github.io/caravan.html&quot;&gt;Caravan&lt;/a&gt; and &lt;a href=&quot;https://horenbergerb.github.io/llamaspace.html&quot;&gt;Astral Fugue.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These pages have been objectively more successful, but it’s an uphill battle to get any meaningful engagement. It’s nice to see the “views” number go up in my analytics, but that’s just a proxy to what I really want. I want to have discussions with people who like my ideas and have ideas of their own. On this front, I have been wildly unsuccessful.&lt;/p&gt;

&lt;p&gt;The only page which has ever really generated spontaneous discussion is &lt;a href=&quot;https://horenbergerb.github.io/2022/10/03/bernoulliderivations.html&quot;&gt;my article on Bernoulli diffusion.&lt;/a&gt; I had several academics reach out for clarification or to make corrections. It was awesome, and it felt good, even if it was only very surface level stuff. In fact, that page still gets a disproportionate amount of engagement, and people really read it. They spend a substantial amount of time on the page. More so than any other article on the website.&lt;/p&gt;

&lt;p&gt;I have reason to believe that some of the people who truly read the Bernoulli diffusion article were using it to assist in writing their own academic publications. Some readers used the derivations in their own works, which they then published without citing me or even contacting me.&lt;/p&gt;

&lt;p&gt;When I realized this, I was excited that my work was finally being used for something, even if it wasn’t how I imagined. But now, I am still here, with nothing to show for all of it except a conspiracy theory that my blog is being plagiarized by academia.&lt;/p&gt;

&lt;p&gt;My pivot to more broadly accessible writing has been ongoing for 3 years. It’s still niche content. I’m not denying that. But the articles tend to be less dense, they’re shorter, they have more pictures, and the subject matter is more variable. What does my audience look like now? What kind of best-case engagement should I expect? It’s tough to say. The diversity of content doesn’t lend itself to this analysis.&lt;/p&gt;

&lt;h1 id=&quot;enough-rambling-wrap-it-up&quot;&gt;Enough rambling. Wrap it up.&lt;/h1&gt;

&lt;p&gt;I don’t have any prescriptive claims to derive from this article. I already had a loose strategy, and I’m continuing to adhere to it. I’ll keep writing about interesting shit, some of which involves mathematics. I’ll keep the articles brief and think about keeping readers engaged. I’ll dip into other kinds of media like web apps. I will look for other people like me publishing content on the web.&lt;/p&gt;

&lt;p&gt;I don’t expect things to get better. I’m learning to make peace with it. I do wish I understood why it’s not working. Does my shit just suck? Does nobody care about this stuff? Is it the search providers? Is it some kind of institutional problem? Am I not advertising enough? Where are the other blogs like mine?&lt;/p&gt;

&lt;p&gt;Anyways, I am proud of the things I’ve written, even if they are inaccurate and messy, and even if no one reads them. I try to convince myself that the personal narrative of developing my own unique understanding has inherent value. Nobody thinks about exactly what I’m thinking about. That’s cool, and I should be proud of it. At the end of the line, I will be someone that no one else is.&lt;/p&gt;

&lt;p&gt;Maybe it’s a mistake to conflate one’s need for intellectual development with one’s need for community. When you decouple the two, they are each available in surplus. I dunno. At least I have a beautiful wife. Thanks for reading.&lt;/p&gt;</content><author><name>Beau Horenberger</name></author><category term="diary" /><summary type="html"></summary></entry><entry><title type="html">Astral Fugue: A space adventure RPG</title><link href="/2025/03/26/llamaspace.html" rel="alternate" type="text/html" title="Astral Fugue: A space adventure RPG" /><published>2025-03-26T00:00:00-04:00</published><updated>2025-03-26T00:00:00-04:00</updated><id>/2025/03/26/llamaspace</id><content type="html" xml:base="/2025/03/26/llamaspace.html">&lt;div class=&quot;p5js-sketch&quot; id=&quot;simple-example-holder&quot;&gt;
    &lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.6.0/p5.min.js&quot;&gt;&lt;/script&gt;
    &lt;script src=&quot;https://cdn.jsdelivr.net/npm/js-yaml@4.1.0/dist/js-yaml.min.js&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;module&quot; src=&quot;/scripts/llamaspace/main.js&quot;&gt;&lt;/script&gt;
&lt;/div&gt;

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

&lt;video width=&quot;320&quot; height=&quot;240&quot; controls=&quot;&quot;&gt;
  &lt;source type=&quot;video/mp4&quot; src=&quot;https://github.com/user-attachments/assets/bc48204e-0e3a-4a4e-a9d9-101d965a7931&quot; /&gt;
&lt;/video&gt;

&lt;p&gt;Astral Fugue is a game about traveling the stars on a research mission. You and your ragtag team are in search of scientific anomalies so that you can further the knowledge of all humankind. It’s also kind of your last chance to prove yourself as a captain.&lt;/p&gt;

&lt;p&gt;The game revolves around traveling to different star systems and coming up with research missions regarding the planetary bodies. The missions are evaluated and expanded upon by an LLM. Coming up with interesting and achievable missions will be rewarded.&lt;/p&gt;

&lt;p&gt;This game uses the OpenRouter API to do its LLM stuff.  All you need is an API key.&lt;/p&gt;

&lt;p&gt;The latest version is no longer open source, but the demo on this website is. Check it out &lt;a href=&quot;https://github.com/horenbergerb/horenbergerb.github.io/tree/master/scripts/llamaspace&quot;&gt;in the GitHub repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you like this game and want to see it developed further, &lt;a href=&quot;https://ko-fi.com/beauhorenberger&quot;&gt;a donation would be greatly appreciated!&lt;/a&gt;&lt;/p&gt;

&lt;h1 id=&quot;how-to-play&quot;&gt;How to play&lt;/h1&gt;

&lt;p&gt;Make sure you paste an OpenRouter API key into the settings and then click Save. Then, travel to different systems. You can enter systems and visit the various bodies.&lt;/p&gt;

&lt;p&gt;At each body, you may invent research missions for your crew to perform. The missions will be attempted and documented, and you’ll either gain reputation or expend your ship’s resources according to the output.&lt;/p&gt;

&lt;p&gt;Reasonably possible, scientifically interesting missions will be rewarded, while other missions may fail more often or give less reputation.&lt;/p&gt;

&lt;p&gt;Some bodies have interesting (LLM-generated) anomalies that merit special investigation…&lt;/p&gt;

&lt;h1 id=&quot;llm-generated-components&quot;&gt;LLM-generated components&lt;/h1&gt;

&lt;p&gt;Each mission you invent is “simulated” by an LLM, and you can see the details of each mission step by hovering over the nodes:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2025-03-26-llamaspace/mission_in_progress.png&quot; alt=&quot;mission_in_progress.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/2025-03-26-llamaspace/mission_step_details.png&quot; alt=&quot;mission_step_details.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Some planets will also have anomalies that are detected when you enter orbit, so try stopping at lots of different planets.&lt;/p&gt;

&lt;h1 id=&quot;disclaimers&quot;&gt;Disclaimers&lt;/h1&gt;

&lt;p&gt;I take no responsibility for anything you do with your OpenRouter API key or anything you do with this game. Remember that your keys are valuable and private, and it’s important to protect them.&lt;/p&gt;

&lt;h1 id=&quot;news&quot;&gt;News&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;04/10/25: Huge update. Added anomaly scanner, tutorial, better missions, better planets, weird planets. All kinds of stuff.&lt;/li&gt;
  &lt;li&gt;03/28/25: Added anomalies&lt;/li&gt;
  &lt;li&gt;03/27/26: Initial release&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;todo&quot;&gt;Todo&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;Finish anomaly detection minigame&lt;/li&gt;
  &lt;li&gt;Make missions cumulative (build upon previous results)&lt;/li&gt;
  &lt;li&gt;Add more interactivity (chatting with crew, etc)&lt;/li&gt;
  &lt;li&gt;???&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Beau Horenberger</name></author><category term="blog" /><summary type="html"></summary></entry><entry><title type="html">Workshopping Astral Fugue</title><link href="/2025/03/12/spacegame.html" rel="alternate" type="text/html" title="Workshopping Astral Fugue" /><published>2025-03-12T00:00:00-04:00</published><updated>2025-03-12T00:00:00-04:00</updated><id>/2025/03/12/spacegame</id><content type="html" xml:base="/2025/03/12/spacegame.html">&lt;div class=&quot;p5js-sketch&quot; id=&quot;simple-example-holder&quot;&gt;
    &lt;script type=&quot;module&quot; src=&quot;/scripts/2025-03-12-spacegame/main.js&quot;&gt;&lt;/script&gt;
&lt;/div&gt;

&lt;p&gt;I’ve been thinking about making something &lt;a href=&quot;https://horenbergerb.github.io/caravan.html&quot;&gt;kind of like Caravan&lt;/a&gt; but in space. This is my first sketch of some basic concepts. I really like the aesthetic.&lt;/p&gt;

&lt;p&gt;Try clicking on some of the colored stars.&lt;/p&gt;

&lt;p&gt;TODO: Fix drag to pan on mobile&lt;/p&gt;</content><author><name>Beau Horenberger</name></author><category term="blog" /><summary type="html"></summary></entry><entry><title type="html">(Beta Test) An explorable LLM-generated world</title><link href="/2024/12/11/world-map-exploration.html" rel="alternate" type="text/html" title="(Beta Test) An explorable LLM-generated world" /><published>2024-12-11T00:00:00-05:00</published><updated>2024-12-11T00:00:00-05:00</updated><id>/2024/12/11/world-map-exploration</id><content type="html" xml:base="/2024/12/11/world-map-exploration.html">&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#map-of-aldreon&quot; id=&quot;markdown-toc-map-of-aldreon&quot;&gt;Map of Aldreon&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#how-to-use-it&quot; id=&quot;markdown-toc-how-to-use-it&quot;&gt;How to use it&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#about-this-demo&quot; id=&quot;markdown-toc-about-this-demo&quot;&gt;About this demo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;map-of-aldreon&quot;&gt;Map of Aldreon&lt;/h1&gt;

&lt;div class=&quot;p5js-sketch&quot; id=&quot;simple-example-holder&quot;&gt;
    &lt;script type=&quot;module&quot; src=&quot;/scripts/2024-12-11-world-map-exploration/sketch_window.js&quot;&gt;&lt;/script&gt;
&lt;/div&gt;

&lt;p&gt;THIS IS JUST A BETA TEST.&lt;/p&gt;

&lt;h1 id=&quot;how-to-use-it&quot;&gt;How to use it&lt;/h1&gt;

&lt;p&gt;Explore the world by traveling to different destinations and reading the lore.&lt;/p&gt;

&lt;p&gt;Click on nodes to travel to them. This will show you a summary of the location. You can expand the summary for a detailed description. New nodes become visible once you visit one of their neigbhors.&lt;/p&gt;

&lt;p&gt;Zooming out will let you select broad regions/subregions. You can learn more about the general area. This provides context for some of the destinations within.&lt;/p&gt;

&lt;p&gt;“Home” returns you to default position and provides information about the world as a whole.&lt;/p&gt;

&lt;h1 id=&quot;about-this-demo&quot;&gt;About this demo&lt;/h1&gt;

&lt;p&gt;The world was generated with a tiny Mistral Nemo finetune, so it’s going to be pretty incoherent. I just wanted to publish something so that I could source some feedback on the GUI.&lt;/p&gt;

&lt;p&gt;The world lore is generated using &lt;a href=&quot;https://horenbergerb.github.io/2024/11/25/world-building-tree.html&quot;&gt;my tree method that I previously documented&lt;/a&gt;. The current world has regions-&amp;gt;subregions-&amp;gt;destinations. There are 3 regions, 3 subregions per region, and 8 destinations per subregion.&lt;/p&gt;

&lt;p&gt;I created an additional algorithm to map that tree structure into an actual world map. To make the map, I started with a 2D plane and randomly divided it in a Voronoi diagram to create the regions. Then, I subdivided each of the region polygons, again using a random Voronoi diagram, to get subregions.&lt;/p&gt;

&lt;p&gt;Within the subregion polygons, I randomly generated a node for each destination in that subregion. Then, I randomly connected the nodes, where probability increases as nodes get closer. I also did a final pass to make sure there were no disconnected graphs (i.e. that you can traverse between any two nodes.)&lt;/p&gt;

&lt;p&gt;Anyways, This is a super rough demo, but I’m pretty proud of it. Please do leave feedback about the usability and any thoughts on how I might improve it. I’ll probably do a more complete blog post in the near future.&lt;/p&gt;</content><author><name>Beau Horenberger</name></author><category term="diary" /><summary type="html"></summary></entry><entry><title type="html">Differential Geometry Visualization Test</title><link href="/2024/11/25/visual-diff-geo.html" rel="alternate" type="text/html" title="Differential Geometry Visualization Test" /><published>2024-11-25T00:00:00-05:00</published><updated>2024-11-25T00:00:00-05:00</updated><id>/2024/11/25/visual-diff-geo</id><content type="html" xml:base="/2024/11/25/visual-diff-geo.html">&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#funky-plot&quot; id=&quot;markdown-toc-funky-plot&quot;&gt;Funky plot&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;funky-plot&quot;&gt;Funky plot&lt;/h1&gt;

&lt;p&gt;This was just an experiment to see if I could render 3D surfaces and do things on them.&lt;/p&gt;

&lt;p&gt;Here you’ll see $\sin{\sqrt{x^2+y^2}}$ plotted in 3D, which is cool. You can click and drag to rotate it.&lt;/p&gt;

&lt;p&gt;Additionally, anywhere you click, it will trigger a “march” along the surface moving parallel to a particular axis. The length of the march along the surface is fixed.&lt;/p&gt;

&lt;p&gt;I originally wanted to make geodesics, i.e. march in a straight line from the perspective of an ant living on the surface. Turns out, it’s hard to figure out how to walk in a straight line along a surface. I guess that’s why I’m studying differential geometry, huh?&lt;/p&gt;

&lt;div class=&quot;p5js-sketch&quot; id=&quot;simple-example-holder&quot;&gt;
    &lt;script type=&quot;text/javascript&quot; src=&quot;/scripts/2024-11-25-visual-diff-geo/sketch_window.js&quot;&gt;&lt;/script&gt;
&lt;/div&gt;</content><author><name>Beau Horenberger</name></author><category term="diary" /><summary type="html"></summary></entry><entry><title type="html">Structured world generation with LLMs</title><link href="/2024/11/25/world-building-tree.html" rel="alternate" type="text/html" title="Structured world generation with LLMs" /><published>2024-11-25T00:00:00-05:00</published><updated>2024-11-25T00:00:00-05:00</updated><id>/2024/11/25/world-building-tree</id><content type="html" xml:base="/2024/11/25/world-building-tree.html">&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#introduction-llms-for-creative-tasks&quot; id=&quot;markdown-toc-introduction-llms-for-creative-tasks&quot;&gt;Introduction: LLMs for creative tasks&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#why-is-this-even-hard&quot; id=&quot;markdown-toc-why-is-this-even-hard&quot;&gt;Why is this even hard?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#world-generation-with-llms&quot; id=&quot;markdown-toc-world-generation-with-llms&quot;&gt;World Generation with LLMs&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#an-interactive-world-graph-for-a-fantasy-world&quot; id=&quot;markdown-toc-an-interactive-world-graph-for-a-fantasy-world&quot;&gt;An interactive world graph for a fantasy world&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#how-do-you-generate-it&quot; id=&quot;markdown-toc-how-do-you-generate-it&quot;&gt;How do you generate it?&lt;/a&gt;        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#the-prompt&quot; id=&quot;markdown-toc-the-prompt&quot;&gt;The prompt&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#sampling-this-is-the-secret-sauce&quot; id=&quot;markdown-toc-sampling-this-is-the-secret-sauce&quot;&gt;Sampling (this is the secret sauce)&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#other-implementation-notes&quot; id=&quot;markdown-toc-other-implementation-notes&quot;&gt;Other implementation notes&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#shortcomings&quot; id=&quot;markdown-toc-shortcomings&quot;&gt;Shortcomings&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#what-can-you-do-with-this&quot; id=&quot;markdown-toc-what-can-you-do-with-this&quot;&gt;What can you do with this?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusion&quot; id=&quot;markdown-toc-conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#more-world-generation-examples&quot; id=&quot;markdown-toc-more-world-generation-examples&quot;&gt;More world generation examples&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#a-cyberpunk-city&quot; id=&quot;markdown-toc-a-cyberpunk-city&quot;&gt;A cyberpunk city&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#a-prison-for-people-with-superpowers&quot; id=&quot;markdown-toc-a-prison-for-people-with-superpowers&quot;&gt;A prison for people with superpowers&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;introduction-llms-for-creative-tasks&quot;&gt;Introduction: LLMs for creative tasks&lt;/h1&gt;

&lt;p&gt;I haven’t seen a lot of discussion about how to use LLMs for fun and creative tasks. This is fair, because it’s actually kind of hard to do, particularly in a quantitative and publishable way. On the other hand, I know for a fact there’s a community of amateurs having a lot of fun with LLMs.&lt;/p&gt;

&lt;p&gt;I’m going to show you a system I created for systematically generating fictional worlds. The goal was to design worlds that are diverse, modular, and extensible. They could be used for something like a D&amp;amp;D style roleplay or a &lt;a href=&quot;https://en.wikipedia.org/wiki/Multi-user_dungeon&quot;&gt;MUD.&lt;/a&gt;&lt;/p&gt;

&lt;h1 id=&quot;why-is-this-even-hard&quot;&gt;Why is this even hard?&lt;/h1&gt;

&lt;p&gt;The big issues with LLMs regarding creative tasks are, in no particular order:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Lack of coherence, i.e. losing the plot or forgetting things (Large models do much better than small models)&lt;/li&gt;
  &lt;li&gt;Repetitiveness. Models will recycle phrases verbatim. “Shivers down your spine” is a classic example. This gets worse over time because the presence of the phrases make the model more likely to repeat them in the future.&lt;/li&gt;
  &lt;li&gt;Reliance on cliches. Every town will be “Greenwood” and every dwarf will have “iron” or “beard” in their name.&lt;/li&gt;
  &lt;li&gt;Limited context size. LLMs can only see a certain amount of input text at once, so they can’t know every little detail all the time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The upshot is that all your text ends up looking kind of “samey,” and important details get lost or forgotten. I think most people have the same experience when they try roleplaying with an LLM for the first time. The first handful of messages blow you away, and then as you start to notice repeated phrases, and when GPT keeps forgetting what items are in your backpack, the magic fades. When you try to restart, you get similar village names and characters on the next go, and then the next one, and then you start to feel like you were tricked.&lt;/p&gt;

&lt;p&gt;This isn’t a nefarious, intentional trickery. It’s just the nature of LLMs that they tend to look best at a glance and fall apart during extended use. This is largely due to the issues I outlined above.&lt;/p&gt;

&lt;p&gt;People do all kinds of funky stuff to get around these issues. There are &lt;a href=&quot;https://github.com/oobabooga/text-generation-webui/pull/6335&quot;&gt;weird samplers like XTC&lt;/a&gt; to prevent cliches or &lt;a href=&quot;https://github.com/ggerganov/llama.cpp/pull/6839&quot;&gt;DRY&lt;/a&gt; to prevent repetitive phrases. These have pros and cons. Additionally, some models are better than others at producing diverse outputs, and there is ongoing work to improve in this regard.&lt;/p&gt;

&lt;h1 id=&quot;world-generation-with-llms&quot;&gt;World Generation with LLMs&lt;/h1&gt;

&lt;h2 id=&quot;an-interactive-world-graph-for-a-fantasy-world&quot;&gt;An interactive world graph for a fantasy world&lt;/h2&gt;

&lt;p&gt;Try clicking some of the nodes! You can drag them around too.&lt;/p&gt;

&lt;div class=&quot;p5js-sketch&quot; id=&quot;simple-example-holder&quot;&gt;
    &lt;script type=&quot;text/javascript&quot; src=&quot;/scripts/2024-11-26-world-building-tree/sketch_window.js&quot;&gt;&lt;/script&gt;
&lt;/div&gt;

&lt;p&gt;The leftmost node is a handwritten overview of the world. Every other node is a subregion generated by an LLM. Click on a node to see the description of the world.&lt;/p&gt;

&lt;p&gt;The world has a tree structure. As you move right along the tree, the nodes describe subregions of their parent region. For example, Elyria’s Crucible, Cryovale’s Grip, and Ignis’ Edge are all subregions of Aldreon. Curmongo’s Shack is a subregion of Dungwater.&lt;/p&gt;

&lt;p&gt;The tree structure was inspired by the paper &lt;a href=&quot;https://arxiv.org/abs/2304.03442&quot;&gt;Generative Agents: Interactive Simulacra of Human Behavior&lt;/a&gt;. In this case, the world itself wasn’t AI-generated, but it had a tree structure that made it very convenient for the LLM to utilize during simulations.&lt;/p&gt;

&lt;h2 id=&quot;how-do-you-generate-it&quot;&gt;How do you generate it?&lt;/h2&gt;

&lt;p&gt;The generation is all done locally using llama.cpp and a quantized version of the Nemotron 70B model. In my experience, Nemotron 70B is pretty good for creative tasks and often surprises me with neat twists. It does suffer from repetition issues and a bit of purple prose.&lt;/p&gt;

&lt;h3 id=&quot;the-prompt&quot;&gt;The prompt&lt;/h3&gt;

&lt;p&gt;The prompt for generating new child nodes looks something like this:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;You are a creative writer generating content for an RPG game set in {root_name}. The user will ask you to write descriptions of locations. Your responses should be diverse, creative, interesting, and occasionally funny. Focus on the facts, contextualizing with common knowledge about the location.&lt;/p&gt;

  &lt;p&gt;The current location is {path_summary}.&lt;/p&gt;

  &lt;p&gt;{path_description}&lt;/p&gt;

  &lt;p&gt;Divide the {current_node_name} into {num_children} subregions. Each subregion should have a name, a list of descriptive tags, a one-line summary, and a long description. Format each entry like this:&lt;/p&gt;

  &lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; &lt;strong&gt;Subregion Name&lt;/strong&gt;&lt;/p&gt;

  &lt;ul&gt;
    &lt;li&gt;&lt;strong&gt;Tags:&lt;/strong&gt; Tags here&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Summary:&lt;/strong&gt; Summary here&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;Description:&lt;/strong&gt; Description here&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the example above, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{root_name}&lt;/code&gt; is Aldreon. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{path_summary}&lt;/code&gt; is the path of nodes from the root to the current node. For example, it would be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Aldreon-&amp;gt;Elryia's Crucible-&amp;gt;Luminari Wilderness&lt;/code&gt; if you were generating subregions of the Luminari Wilderness.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{path_description}&lt;/code&gt; is the description of every node mentioned in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{path_summary}&lt;/code&gt;. Essentially, it’s increasingly-specific information about the current region.&lt;/p&gt;

&lt;p&gt;The tags are meant to be a list of adjectives that loosely summarize the subregion. These are generated first to “seed” the model with creative inspiration. I will explain this further in the sampling section.&lt;/p&gt;

&lt;p&gt;This prompt sets the model up to generate subregions, but there’s no guarantee the outputs will be very creative. I do some strange sampling to help ensure that the output will be diverse.&lt;/p&gt;

&lt;h3 id=&quot;sampling-this-is-the-secret-sauce&quot;&gt;Sampling (this is the secret sauce)&lt;/h3&gt;

&lt;p&gt;I prefill the response up to the name,&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;**1.** **
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then generate the name. Then I continue prefilling to where the tags will be generated:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;**1.** **The Shongor's Den**

* **Tags:** 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And generate the tags.&lt;/p&gt;

&lt;p&gt;The real trick, though is that I do something funky when generating the name and the tags.&lt;/p&gt;

&lt;p&gt;I sample one word at a time (using spaces as stop tokens). For each word, I sample the first token in the word uniformly from the $n$ most likely tokens, where $n$ is usually between 20 and 100. I also do some regex filtering to ensure that none of the tokens have funky characters like dollar signs.&lt;/p&gt;

&lt;p&gt;This works because the words in the name and the tags don’t need much coherence. The whole point of them is to be creative and diverse. Then, the name and tags work as a creative anchor for the rest of the generation.&lt;/p&gt;

&lt;p&gt;This uniform-first-token sampling keeps the model from constantly generating similar subregions.&lt;/p&gt;

&lt;p&gt;The brief summary and long description are generated using standard sampling methods. You can generally use higher temperature with the summary and lower temperature with the longer description.&lt;/p&gt;

&lt;h3 id=&quot;other-implementation-notes&quot;&gt;Other implementation notes&lt;/h3&gt;

&lt;p&gt;I created a WorldNode class in Python that you can build these trees with. You can save and load them from yaml files. When generating subregions, it can traverse the tree to build the prompt and autofill things like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{path_summary}&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{path_description}&lt;/code&gt;. At some point, I’ll probably put this code up on Github so other people can play with it.&lt;/p&gt;

&lt;p&gt;But all the secret sauce was already described, so you could implement this yourself if you wanted.&lt;/p&gt;

&lt;p&gt;You can also ask for particular subregions. For example, I asked specifically for “Dungwater” and described it as “a shoddy town with very little to offer.”&lt;/p&gt;

&lt;h3 id=&quot;shortcomings&quot;&gt;Shortcomings&lt;/h3&gt;

&lt;p&gt;The major limitation is that every generated node can only see the nodes leading back to the root. The only exception to this is when sibling nodes are simultaneously generated. In this case, they’re all “seen” at the time of generation, which helps prevent duplicated nodes or contradictory information.&lt;/p&gt;

&lt;p&gt;In general, though, disparate branches are liable to have contradictory information. It’s something to keep an eye on. There’s not really a good way to mitigate this, but it tends not to be a huge issue since most nodes eventually share some parent information, and distinct regions often handle distinct subject matter anyways.&lt;/p&gt;

&lt;h1 id=&quot;what-can-you-do-with-this&quot;&gt;What can you do with this?&lt;/h1&gt;

&lt;p&gt;I dunno.&lt;/p&gt;

&lt;p&gt;This tool would be pretty handy for rapidly brainstorming areas of interest in a fictional world. If you need some distractions in a local forest, you can generate them on the fly.&lt;/p&gt;

&lt;p&gt;I can see this being useful for D&amp;amp;D type creative tasks. What I’d like to do is add more structure so that the LLM can act as a Dungeon Master while you explore the world. You could generate regions on the fly while you explore. Ideally the world nodes could also hold additional locally-relevant information, like characters, quests, items, etc.&lt;/p&gt;

&lt;p&gt;I’ve also used the sampling techniques to generate characters and had some success. Here’s an example:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Name: Diggory Sweetbark&lt;/p&gt;

  &lt;p&gt;Gender: Male&lt;/p&gt;

  &lt;p&gt;Race: Gnome&lt;/p&gt;

  &lt;p&gt;Alignment: True Neutral&lt;/p&gt;

  &lt;p&gt;Occupation: Gardener and Herbalist&lt;/p&gt;

  &lt;p&gt;About: Diggory Sweetbark is a gnome with a deep love for plants and nature. He was raised in the heart of the Verdant Expanse, a vast forest filled with magical flora and fauna. Diggory’s parents were renowned botanists, and they passed on their knowledge and passion to their son. He spent his early years learning about the various plants in the forest, their properties, and how to cultivate them. As he grew older, Diggory began to explore the forest beyond his family’s home, discovering rare and valuable herbs that he could use to create powerful potions and remedies. His reputation as a skilled herbalist and gardener spread throughout the Verdant Expanse, and he became known as the “Green Thumb of the Forest.” Despite his love for nature, Diggory is not opposed to using his knowledge to help others, even if it means venturing into the dangerous world outside the forest. He has a dry wit and a tendency to speak in riddles, often leaving his companions scratching their heads. His appearance is that of a typical gnome, with a round belly, bushy beard, and bright, twinkling eyes. He wears a wide-brimmed hat adorned with various plants and flowers, and his clothes are made from natural materials, blending in with the foliage around him. Diggory carries a staff made from the heartwood of an ancient tree, and he uses it not only for support but also as a tool to help him tend to his plants and defend himself if necessary.&lt;/p&gt;

  &lt;p&gt;Dialog: “Ah, you seek the rare Moonwhisper Bloom, do you? It grows only under the light of the full moon, in the shadow of the ancient willow. But be warned, the willow’s tears are poisonous, and the moon’s light can be deceiving. Tread carefully, young one, for the forest is a fickle lover.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;My hope is that I can combine several tools of this sort to get an increasingly complete and coherent experience.&lt;/p&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;LLMs can be alright at creative tasks. They do best with lots of structure and carefully-added randomness. If anyone out there wants the code, let me know and I can hustle up about getting it onto Github. Otherwise, I hope to have more updates as I figure out how to piece some of these tools together and make something more fun and interactive.&lt;/p&gt;

&lt;h1 id=&quot;more-world-generation-examples&quot;&gt;More world generation examples&lt;/h1&gt;

&lt;h2 id=&quot;a-cyberpunk-city&quot;&gt;A cyberpunk city&lt;/h2&gt;

&lt;p&gt;I used ChatGPT to generate the root node, then just generated a bunch of subregions at random. This is a cyberpunk-themed world named Vesper City. This was a one-shot; I didn’t even review the nodes before posting. If you really want to use these worlds for something real, I imagine you’d do your own touch-ups or regens as you go along.&lt;/p&gt;

&lt;div class=&quot;p5js-sketch&quot; id=&quot;simple-example-holder-2&quot;&gt;
    &lt;script type=&quot;text/javascript&quot; src=&quot;/scripts/2024-11-26-world-building-tree/sketch_window_2.js&quot;&gt;&lt;/script&gt;
&lt;/div&gt;

&lt;h2 id=&quot;a-prison-for-people-with-superpowers&quot;&gt;A prison for people with superpowers&lt;/h2&gt;

&lt;p&gt;Another one-shot with a root node generated by ChatGPT. It has the same structure as the previous example because I was too lazy to randomize how I generate the nodes.&lt;/p&gt;

&lt;div class=&quot;p5js-sketch&quot; id=&quot;simple-example-holder-3&quot;&gt;
    &lt;script type=&quot;text/javascript&quot; src=&quot;/scripts/2024-11-26-world-building-tree/sketch_window_3.js&quot;&gt;&lt;/script&gt;
&lt;/div&gt;</content><author><name>Beau Horenberger</name></author><category term="blog" /><summary type="html"></summary></entry><entry><title type="html">Visualizing Phase Fluid and Liouville’s Theorem</title><link href="/2024/10/02/p5js-phase-flow.html" rel="alternate" type="text/html" title="Visualizing Phase Fluid and Liouville’s Theorem" /><published>2024-10-02T00:00:00-04:00</published><updated>2024-10-02T00:00:00-04:00</updated><id>/2024/10/02/p5js-phase-flow</id><content type="html" xml:base="/2024/10/02/p5js-phase-flow.html">&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#introduction&quot; id=&quot;markdown-toc-introduction&quot;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#harmonic-oscillator-phase-diagram&quot; id=&quot;markdown-toc-harmonic-oscillator-phase-diagram&quot;&gt;Harmonic oscillator phase diagram&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#estimating-area-of-a-region-in-phase-space&quot; id=&quot;markdown-toc-estimating-area-of-a-region-in-phase-space&quot;&gt;Estimating area of a region in phase space&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusion&quot; id=&quot;markdown-toc-conclusion&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#todos&quot; id=&quot;markdown-toc-todos&quot;&gt;Todos&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;introduction&quot;&gt;Introduction&lt;/h1&gt;

&lt;p&gt;I’ve been trying to make sense of symplectic geometry again. I know that it originates from classical mechanics, particularly Hamiltonians, but I’m not totally clear how. I came across a very interesting &lt;a href=&quot;https://www.reddit.com/r/math/comments/wt9rsz/how_to_explain_symplectic_geometry/&quot;&gt;Reddit post&lt;/a&gt; that made the following remark:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;if we imagine many nearby points in our phase space and watch a “fluid” of points flowing as time passes, the volume of that fluid is preserved (cf &lt;a href=&quot;https://en.wikipedia.org/wiki/Liouville%27s_theorem_(Hamiltonian)&quot;&gt;Liouville’s theorem&lt;/a&gt;)! The way we measure the volume of a phase fluid is called a symplectic form, and symplectic geometry is precisely the study of 2N-dimensional spaces endowed with a symplectic form.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I don’t plan to elaborate on symplectic forms here, but I did realize I can make some neat visualizations of phase fluid.&lt;/p&gt;

&lt;h1 id=&quot;harmonic-oscillator-phase-diagram&quot;&gt;Harmonic oscillator phase diagram&lt;/h1&gt;

&lt;p&gt;So a &lt;a href=&quot;https://en.wikipedia.org/wiki/Harmonic_oscillator&quot;&gt;harmonic oscillator&lt;/a&gt; is basically just a pendulum or a frictionless spring. The behavior of a harmonic oscillator is determined by the equation&lt;/p&gt;

\[\vec{F}=-k\vec{x}\]

&lt;p&gt;where $k$ is a constant.&lt;/p&gt;

&lt;p&gt;Sometimes we want to consider all the possible configurations of a particular harmonic oscillator (i.e. a harmonic oscillator with some known value of $k$). What I mean is, if we start the oscilator at any position $x$ and velocity $v$, what will it do?&lt;/p&gt;

&lt;p&gt;We can represent all of the configurations simultaneously by imagining the &lt;a href=&quot;https://en.wikipedia.org/wiki/Phase_space&quot;&gt;phase space&lt;/a&gt;. This is just a graph where the x-axis is the oscillator’s position and the y-axis is the oscillator’s velocity.&lt;/p&gt;

&lt;p&gt;If you choose a starting point on the plot, you can calculate how the oscillator’s position and velocity will change at each moment based on its current position using $\vec{F}=-k\vec{x}$. This lets you simulate the oscillator bouncing over time.&lt;/p&gt;

&lt;p&gt;Here’s a bunch of spring configurations that have randomly initialized positions and velocities. Each dot represents one spring. You can see some of the behavior you might expect from a spring: the $x$ values oscillate, and $x$ reaches a maximum when $v$ is at 0.&lt;/p&gt;

&lt;div class=&quot;p5js-sketch&quot; id=&quot;simple-sketch-holder-1&quot;&gt;
    &lt;script type=&quot;text/javascript&quot; src=&quot;/scripts/2024-10-02-p5js-phase-flow/harmonic_oscillator_phase_trajectories.js&quot;&gt;&lt;/script&gt;
&lt;/div&gt;

&lt;p&gt;There are some other interesting properties, too. Notice how the dots never intersect? That’s pretty neat, and there’s more to say about it.&lt;/p&gt;

&lt;h1 id=&quot;estimating-area-of-a-region-in-phase-space&quot;&gt;Estimating area of a region in phase space&lt;/h1&gt;

&lt;p&gt;So basically, Liouville’s theorem says that if you initialized a whole region of the phase space and let it flow around, the area of that “phase fluid” should remain constant as it moves around. This is only true for systems where the total energy is conserved.&lt;/p&gt;

&lt;p&gt;We can visualize this for the harmonic oscillator. I’ll initialize a rectanglar region of phase fluid and let it flow.&lt;/p&gt;

&lt;div class=&quot;p5js-sketch&quot; id=&quot;simple-sketch-holder-2&quot;&gt;
    &lt;script type=&quot;text/javascript&quot; src=&quot;/scripts/2024-10-02-p5js-phase-flow/harmonic_oscillator_phase_fluid_volume.js&quot;&gt;&lt;/script&gt;
&lt;/div&gt;

&lt;p&gt;Strangely, the phase fluid remains a parallelogram over time, although the width, height, and angles still change. This preservation of parallelograms is NOT a general property of phase spaces, but rather a quirk of harmonic oscillators (todo: prove this).&lt;/p&gt;

&lt;p&gt;Knowing this, it’s easy to calculate the area of our phase fluid at any point in time. All you need is the corner points (highlighted in the visualization). Then you can use the width, height, and the angle between the sides to calculate the area of the parallelogram: $A=w*h*\sin{\theta}$.&lt;/p&gt;

&lt;p&gt;Lo and behold, the area remains constant! That’s pretty cool! So you can actually visualize the fact that Liouville’s theorem holds for a harmonic oscillator.&lt;/p&gt;

&lt;p&gt;This trick would be harder to pull off for other physical systems, but I think I can extend it to systems where simple polygons remain simple polygons. In that case, I can measure area of the phase fluid using the &lt;a href=&quot;https://en.wikipedia.org/wiki/Shoelace_formula&quot;&gt;shoelace formula&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;I dunno, this is just a neat trick I whipped up pretty quickly. p5.js is useful for visualization. I think this is helping provide some more intuition for how symplectic geometry works, but I’ll have to write a separate article about that. Thanks for reading!&lt;/p&gt;

&lt;h1 id=&quot;todos&quot;&gt;Todos&lt;/h1&gt;

&lt;p&gt;Things I’d like to do:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Verify Liouville’s theorem is expected to hold here. I see a lot of people only apply it after massaging things to get the Hamiltonian equations. Is that necessary?&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Add friction and visualize again. The area conservation probably won’t hold then, but what will it look like?&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Relate this to the symplectic form $d\omega$. You integrate a symplectic form over a region to get an area. Letting the phase flow progress for a fixed time $t$ is basically like a change of variables for the integral? Then you can show that for conservative systems, this transformation preserves $d\omega$? Something like that.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Plug in some more interesting systems and see how the areas/volumes transform over time.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;</content><author><name>Beau Horenberger</name></author><category term="blog" /><summary type="html"></summary></entry></feed>