← First Pair Library

Eigen Times: A Newspaper in the Eigenbasis of the News

Recurring Archetypes, the Daily Decomposition, and Two Ways to Compute Them

Alexy Khrabrov

2026-10-03

Eigen Times: A Newspaper in the Eigenbasis of the News — Alexy Khrabrov

Abstract

News is mostly recurrence. A war, a scandal in the capital, another bad turn in the Middle East, a central bank surprising the market: the shape repeats while the names, places and pretexts change. Eigen Times is a newspaper that takes this literally. It treats the archive of news as a matrix, extracts its principal directions—the eigen-news, a few dozen recurring archetypes that explain most of the variance—and prints each day as a decomposition: how much of today projects onto each archetype, what is left over, and, for every story, what is the same as always and what is different this time.

This article describes how Eigen Times was built as a complete system: a 1.09-million-article corpus assembled from public archives (the Guardian, 1999→; Wikipedia’s Current events portal, 2002→; Wikinews, 2004–2026); two independent constructions of the eigenbasis, one in term space (the singular value decomposition of a centred term-frequency–inverse-document-frequency (TF-IDF) matrix) and one in embedding space (the eigenvectors of the covariance of sentence embeddings), both rotated into named axes; a story layer that clusters each day’s articles and threads them into episodes; the statistics that turn coordinates into journalism—Hotelling’s T2T^2 for variance-adjusted retained distance, residual energy QQ for discarded squared length, a novelty ratio, per-archetype profiles, precedents; and the newspaper itself, a static site of 10,102 daily issues. We compare the two bases against the human-assigned event categories of the Wikipedia portal, which are never used in fitting, and find that both recover them at similar rates (42.4% and 40.0% section purity) while their matched axes correlate at 0.57–0.75. The entire backend is Rust; the pipeline runs on a laptop.

A second edition, added after the first was published, extends the archive to 16.5 million articles across 175 years by ingesting the New York Times archive (September 1851→) and refits the eigenbasis with day-balanced weights, so that every calendar day since 1851 counts the same. The two editions are served side by side with a switch on every page. On the same human-labelled events the 175-year basis recovers categories as well as the modern one (section purity 0.435 against 0.431) while spreading today’s stories across all sixty axes instead of piling most of them onto one. Fitting it forced the computation to stream: the orientation of axes, the term loadings and the story clustering were rewritten to run in flat memory over a corpus fifteen times larger than the first, and the paper reports how.

1 Introduction

Newspapers are organised by desk—World, Politics, Business—because that is how newsrooms are organised. Readers, however, experience the news as a small repertoire of recurring situations, and much of what a seasoned reader does when reading a headline is to recognise which situation it is and then look for what departs from the template. “Another regional war” is the recognition; “but this time two great powers are on opposite sides, and it is six weeks before an election in one of them” is the reading.

Eigen Times is an attempt to make that reading mechanical, honest and daily. Its thesis is that the space of news articles has low effective dimension: a few dozen directions carry most of the variance of a quarter-century of reporting, and those directions are the archetypes. Once the archetypes are known, a day’s news can be measured rather than merely categorised. Each story becomes a vector; its projection onto the basis says which archetype it instantiates and at what intensity; the part of the vector the basis cannot reproduce measures variation outside those learned directions; and the archetype’s own history—its typical profile, its previous episodes—gives the reader the precedents against which “different this time” can be stated as a number before it is stated as a sentence.

The contributions of this article are:

  1. a precise formulation of the eigen-news as eigenvectors of weighted observation covariance, with the statistics that follow from it (The mathematics);
  2. a public-archive corpus of 1,093,166 dated articles and a story layer over it (The dataset);
  3. two complete implementations of the basis—term-space Latent Semantic Analysis (LSA) and an embedding eigenbasis—with a common naming and rotation layer, and a comparison against human labels (Two algorithms; Evaluation);
  4. the newspaper: a rendering of the decomposition as a daily issue with spectra, archetype badges, delta panels, precedents, archetype pages and a comparison page (The newspaper);
  5. an all-Rust implementation over Parquet with Sail as the query engine, deployed as a static site (Implementation).

The newspaper is running at eigentimes.com; the source is at github.com/alexy/eigentimes. The refinement loop is an implemented research direction whose scheduling remains separate, as described below.

Paper version 0.2.1. This correction defines symbols and operators before use, separates raw and named coordinates and their scales, and makes the scope of matrix identities and refinement bounds explicit. It preserves the reported datasets, fitted models, numerical results, thresholds, citations, and figures. The numerical results and deployment account describe the editions reported in August and September 2026; this patch is not a new corpus evaluation or operations report. The mathematical companion supplies longer prerequisite explanations.

2 Previous work

2.1 Automation in the newsroom

Automated journalism has mostly meant automated writing: templated prose generated from structured data. The Associated Press began publishing computer-written earnings reports with Automated Insights in 2014; the Washington Post’s Heliograf covered the 2016 Olympics and elections; Reuters’ Lynx Insight (2018) and Bloomberg’s Cyborg turned market data into draft stories. Carlson [4] framed the phenomenon as “the robotic reporter” and examined how journalists narrated its arrival; Graefe’s Guide to Automated Journalism [10] surveyed the practice and its limits, chiefly that generation from structured data covers only the small fraction of news that arrives structured. Eigen Times sits on the other side of the newsroom: it does not write stories, it reads them, and what it automates is the editorial act of recognition and comparison.

2.2 Topic detection and tracking

The closest research lineage is Topic Detection and Tracking. The TDT pilot study [1] defined the tasks—segmenting a stream, detecting first stories, tracking known events—that any system reading a news stream must solve, and first-story detection in particular [22] is the ancestor of what this article calls the residual: the part of today that no existing direction explains. Industrial news aggregation, notably the clustering behind Google News [6], solved the daily grouping problem at scale. Eigen Times reuses the TDT decomposition of the stream into stories (a day’s cluster) and episodes (a chain of stories across days), but its unit of recognition is not the event; it is the archetype, a direction that recurs across many events.

2.3 Latent semantic structure of text

Latent Semantic Analysis [8] was the first demonstration that the singular vectors of a term–document matrix are meaningful directions, and it remains the most interpretable: a component is literally a weighted word list. Probabilistic successors—probabilistic Latent Semantic Analysis (pLSA) [13] and Latent Dirichlet Allocation (LDA) [2]—recast the directions as topics; dynamic topic models [3] let topics drift through time, which is the model-side counterpart of the refinement problem in Refinement and identity. Topic models have been applied to news at scale [21], and meme-tracking [19] followed short phrases through the news cycle. Leetaru’s GDELT [18] took the opposite approach and coded the world’s news into a fixed event ontology; its themes and actors are a hand-built basis where Eigen Times wants a learned one.

Sentence embeddings changed what a document vector is. Word vectors [20] made semantic similarity linear; Sentence-BERT [23] produced document vectors in which cosine similarity tracks meaning rather than vocabulary; the BGE family [24] used here is a compact descendant. BERTopic [11] clusters such embeddings and names the clusters with class-based TF-IDF, which is close in spirit to how Eigen Times names its embedding axes (v1: the embedding eigenbasis), except that Eigen Times keeps the axes orthogonal and continuous rather than discrete.

2.4 The matrix toolkit

The numerical ingredients are classical. Varimax rotation [16] makes a factor basis readable without changing the subspace. Hotelling’s T2T^2 [14] and the squared prediction error QQ [15] are the standard pair for monitoring a process against a principal-component model—here, monitoring the news against its own history. Randomized singular value decomposition (SVD) [12] makes the term-space decomposition of a million-row sparse matrix a matter of minutes. The Davis–Kahan theorem [7] bounds how far separated eigendirections can move when the covariance is perturbed; its stability conclusion requires a suitable eigenvalue separation. Archetypal analysis [5] is the non-negative alternative to rotation for producing unipolar axes, and the Kuhn–Munkres assignment [17] matches axes across refinements and across bases.

2.5 The Wikipedia Current Events portal as data

Wikipedia’s Portal:Current events is a curated daily bulletin, one page per day since January 2002, with each event filed under a section such as Armed conflicts and attacks or Politics and elections. It has been used as a source for multi-document summarisation [9]. Eigen Times uses it twice: as a compact, consistent source of events, and—because the sections are human category labels that were never shown to the fitting procedure—as the held-out check that the eigenvectors recover categories people would choose.

3 The mathematics

3.1 Stories, vectors, weights

We use real-valued column vectors for individual observations; a data matrix stores their transposes as rows. The notation ℝd\mathbb R^d specifies dd real coordinates, a superscript ⊤\top denotes transpose, ‖x‖\lVert x\rVert is Euclidean length, and 𝟏\mathbf1 is an all-ones column of the required row count. A matrix’s shape lists rows then columns. The operator diag\mathrm{diag} forms a diagonal matrix, II denotes the identity of the indicated size, and a negative matrix power denotes an inverse on positive retained eigenvalues. Summation indices run over the specified observations or coordinates; bars around a scalar mean absolute value. The mathematical companion develops these prerequisites pictorially.

The newspaper’s unit of presentation is a story: articles from one day grouped as reporting one event. Let ss index a story, τ(s)\tau(s) its publication day, and xs∈ℝdx_s\in\mathbb R^d its embedding-space vector, with d=384d=384 in the deployed embedding system. An embedding is a numerical representation produced by a fixed text model. A story also has a sparse term vector ts∈ℝpt_s\in\mathbb R^p, where p=50,000p=50{,}000 counts vocabulary terms. Term-frequency–inverse-document-frequency (TF-IDF) weights within-document counts by how rare terms are across documents. Story energy, denoted ϵs\epsilon_s, is the number of distinct sources times ln⁡(1+article count)\ln(1+\text{article count}), normalised so its mean over a day’s stories is one; ln\ln is the natural logarithm.

Story energy is a presentation weight, distinct from the weights used to fit the basis. In the deployed fits the observations are articles: let ii index an article, xi∈ℝdx_i\in\mathbb R^d its vector, wi>0w_i>0 its fitting weight, and NN the number of fitted articles up to a specified cutoff day. Let X∈ℝN×dX\in\mathbb R^{N\times d} have rows xi⊤x_i^{\top}, and let W=diag(w1,…,wN)W=\mathrm{diag}(w_1,\ldots,w_N). The first edition uses uniform article weights; the second uses the day-balanced weights defined below. The same covariance formula could also be applied to weighted story rows, but that is not the deployed fitting population.

3.2 The eigen-news

A covariance matrix averages products of centred coordinates. Let ZZ denote total fitting weight, μ∈ℝd\mu\in\mathbb R^d the weighted mean, and Σ∈ℝd×d\Sigma\in\mathbb R^{d\times d} the weighted covariance:

Z=∑i=1Nwi,μ=Z−1∑i=1Nwixi,Z = \sum_{i=1}^N w_i, \qquad \mu = Z^{-1}\sum_{i=1}^N w_i x_i,

Σ=Z−1∑i=1Nwi(xi−μ)(xi−μ)⊤.\Sigma = Z^{-1}\sum_{i=1}^N w_i (x_i-\mu)\left(x_i-\mu\right)^{\top}.

An eigenvector is a direction that multiplication by Σ\Sigma scales without turning; its eigenvalue is that scale, equal here to variance along the unit direction. Let VfullV_{\mathrm{full}} be the d×dd\times d orthonormal eigenvector matrix and Λfull\Lambda_{\mathrm{full}} its diagonal eigenvalue matrix, ordered by decreasing eigenvalue. The full decomposition is Σ=VfullΛfullVfull⊤\Sigma=V_{\mathrm{full}}\Lambda_{\mathrm{full}}V_{\mathrm{full}}^{\top}. Retain kk positive directions in V∈ℝd×kV\in\mathbb R^{d\times k}, with Λ=diag(λ1,…,λk)\Lambda=\mathrm{diag}(\lambda_1,\ldots,\lambda_k). Column vjv_j and value λj\lambda_j refer to retained raw axis jj, for j=1,…,kj=1,\ldots,k. Their weighted combinations form the news subspace. The matrix VΛV⊤V\Lambda V^{\top} is the retained covariance approximation, not generally the full covariance.

The singular value decomposition (SVD) expresses a matrix using orthonormal left and right directions and nonnegative singular values. Let q=min⁡(N,d)q=\min(N,d), the smaller dimension. Define the weighted centred matrix X̃=W1/2(X−𝟏μ⊤)\tilde X=W^{1/2}(X-\mathbf1\mu^{\top}), where W1/2W^{1/2} has square-root weights on its diagonal. In its thin SVD, UU has shape N×qN\times q, SS is a q×qq\times q diagonal matrix of descending singular values, and V*V_* has shape d×qd\times q: X̃=USV*⊤\tilde X=USV_*^{\top}. The first kk columns of V*V_* give VV; let UkU_k contain the corresponding columns of UU and SkS_k the leading diagonal block of SS. Then Λ=Sk2/Z\Lambda=S_k^2/Z. The ordinary coordinate matrix is C=(X−𝟏μ⊤)V=W−1/2UkSkC=(X-\mathbf1\mu^{\top})V=W^{-1/2}U_kS_k, with shape N×kN\times k. Thus UU alone is not the matrix of unweighted article coordinates. The loading columns describe directions; coordinates rank their historical instances.

For component selection, let σ̂2\hat\sigma^2 denote an estimated isotropic noise variance and λ+\lambda_+ the Marchenko–Pastur upper noise edge. The reference expression is λ+=σ̂2(1+(d/N)1/2)2\lambda_+=\hat\sigma^2(1+(d/N)^{1/2})^2. It assumes an idealised independent, equal-weight noise model; weighted and dependent news observations need additional justification before treating it as a calibrated cutoff. An explained-variance curve reports the sum of retained eigenvalues divided by the sum of all eigenvalues. The deployed bases use k=60k=60.

3.3 Orientation and named axes

An eigenvector’s sign is arbitrary, and nearly equal eigenvalues allow large changes of individual directions within almost the same subspace. Two conventions make axes printable. Sign: each vjv_j is oriented so that its coordinate distribution has nonnegative skewness, the third centred moment divided by the cube of its standard deviation. A heavy positive tail then identifies the named pole when skewness is nonzero. Named axes: let R∈ℝk×kR\in\mathbb R^{k\times k} be an orthogonal rotation, satisfying R⊤R=IR^{\top}\,R=I, and V′=VRV'=VR the named directions. Varimax chooses RR to concentrate lexical loadings on individual axes. Projection residuals and full quadratic statistics are computed in the raw basis; displayed coordinates, names, and canons use the named basis.

For embedding-axis naming, let T∈ℝN×pT\in\mathbb R^{N\times p} be the aligned article TF-IDF matrix and t‾∈ℝp\bar t\in\mathbb R^p its unweighted mean term column. Let F=CΛ−1/2F=C\Lambda^{-1/2} be the N×kN\times k matrix of raw coordinates divided by their fitted standard deviations. The inverse square-root power acts on the diagonal eigenvalues. Let fjf_j be column jj of FF, and βj∈ℝp\beta_j\in\mathbb R^p its lexical loading column. The centred cross-product βj=(T−𝟏t‾⊤)⊤fj\beta_j=\left(T-\mathbf1\bar t^{\top}\right)^{\top}\,f_j ranks associated words; stacking these columns gives β∈ℝp×k\beta\in\mathbb R^{p\times k}, whose rotated loadings are βR\beta R. This can print a component as troops · offensive · ceasefire · shelling. The term-space LSA fit instead obtains its lexical loadings directly from the right singular vectors of the term matrix; both constructions then apply varimax. Naming the embedding axes with standardised raw scores while rotating unstandardised article coordinates is a naming heuristic, not an exact attribution of every final coordinate to words.

3.4 Extraction: a story in the basis

Let tt be the issue day and x∈ℝdx\in\mathbb R^d an individual observation vector measured in the selected reference basis. For the term-space model the same algebra uses a TF-IDF column and replaces embedding dimension dd by vocabulary dimension pp. In the proposed chronological refitting protocol that reference is fitted through day t−1t-1; production currently retains fixed fitted versions. Let c∈ℝkc\in\mathbb R^k be raw coordinates, x̂∈ℝd\hat x\in\mathbb R^d their reconstruction, and r∈ℝdr\in\mathbb R^d the residual:

c=V⊤(x−μ),x̂=μ+Vc,r=x−x̂.c = V^{\top}(x-\mu), \qquad \hat{x} = \mu + V c, \qquad r = x - \hat{x}.

Hotelling’s T2T^2 denotes the variance-adjusted retained squared distance; QQ denotes discarded squared length. Let ν\nu be the fraction of centred squared length discarded, defined by the ratio when x≠μx\ne\mu; the implementation returns zero when centred energy is zero:

T2=c⊤Λ−1c,Q=‖r‖2,ν=‖r‖2/‖x−μ‖2.T^{2} = c^{\top}\,\Lambda^{-1}c, \qquad Q = \lVert r\rVert ^{2}, \qquad \nu = \lVert r\rVert ^{2} / \lVert x-\mu\rVert ^{2}.

These equations measure one vector; the article pipeline applies them to individual articles. Story cards store the mean of their member articles’ T2,Q,νT^2,Q,\nu values, which need not equal the nonlinear statistics evaluated at the story’s mean vector. A high T2T^2 represents an unusual intensity or mixture within familiar directions; a high QQ represents variation outside the retained subspace, not proof of a new event. For the named basis define y=R⊤cy=R^{\top}\,c, with entries yjy_j, and let vj′v'_j be column jj of V′V'. Its fitted covariance is R⊤ΛRR^{\top}\,\Lambda R; its diagonal variances are ∑a=1kλaRaj2\sum_{a=1}^k\lambda_aR_{aj}^2, where aa indexes raw axes. They cannot generally be replaced by the raw λj\lambda_j. Dividing named coordinates by their marginal standard deviations does not remove off-diagonal covariance and is not full whitening. Full whitening would rescale and decorrelate all coordinates. The raw T2T^2 above remains distinct from a sum of squared marginally standardised named coordinates.

For printed dominance, apply named coordinates to the story’s mean projected vector. Let sj>0s_j>0 denote named axis jj’s empirical sample standard deviation over the ten years ending at the latest loaded story date, floored at 10−610^{-6} by the implementation. The operator arg⁡max\arg\max returns the index attaining the largest value. Choose the greatest signed standardised coordinate, without absolute values or mean subtraction; all candidates may be negative. The exact decomposition is

x−μ=yjvj′+∑a≠jyava′+r,j=arg⁡maxa=1,…,kya/sa.x - \mu = y_j v'_j + \sum_{a\ne j}y_a v'_a + r, \qquad j=\arg\max_{a=1,\ldots,k} y_a/s_a.

The three terms are the named archetype, its mixture with other retained directions, and the residual. The scale sjs_j is a story-window statistic, distinct from both the raw eigenvalue and the fitted rotated-axis variance.

3.5 Per day, per archetype

Let x‾t∈ℝd\bar x_t\in\mathbb R^d be the energy-weighted mean of stories published on day tt, and et∈ℝke_t\in\mathbb R^k its named-axis spectrum: x‾t=∑s:τ(s)=tϵsxs/∑s:τ(s)=tϵs\bar x_t=\sum_{s:\tau(s)=t}\epsilon_sx_s/\sum_{s:\tau(s)=t}\epsilon_s and et=V′⊤(x‾t−μ)e_t=V'^{\top}(\bar x_t-\mu). The entry et,je_{t,j} is axis jj’s daily coordinate. A zz-score subtracts a reference mean and divides by its positive reference standard deviation. Applying it to daily coordinates using the site’s era statistics marks axes as loud, usual, or silent. In the audited renderer those era moments use the loaded edition’s daily spectra; they are not a separate preceding-days-only fit for each historical issue.

For each archetype jj, its dominant stories define a profile: the mean and standard deviation of every named coordinate over the chosen reference stories. Here σ\sigma in a displayed profile deviation denotes the relevant coordinate’s profile standard deviation, not a raw eigenvalue or an SVD singular value. “Same as always” is the set of strong profile axes a story also carries; “different this time” is a departure by more than 1.5σ1.5\sigma. Cosine similarity is the dot product of two nonzero coordinate vectors divided by their lengths’ product. Precedents are the nearest earlier stories with the same dominant axis, one per episode, by cosine in named-axis coordinates.

4 The dataset

4.1 Sources

Source Articles Span Text Access
The Guardian (Open Platform) 954,274 1999–2026 full body public test key, 720 req/min
Wikipedia Current events 117,720 2002–2026 one-line bulletins with sections MediaWiki API, 31 days per call
Wikinews (English) 21,172 2004–2026 full text 47 MB dump; the site closed in 2026, so the archive is complete
The New York Times (Archive API) 15,407,541 1851–2026 headline and abstract (index abstracts before the 1980s, ledes after) developer key, one month per call, 2,100 months

The first three sources were the fitted corpus of the first edition (1.09 million articles). The New York Times archive—headlines and abstracts for every item the paper indexed since 18 September 1851—was added for the second edition (§Two editions): 2,100 monthly calls, embedded as they arrived at about 550 articles per second on a laptop, for a corpus of 16,500,781 articles over 63,270 days. Its text changes register along the way: until the 1980s the “abstract” is the index’s terse summary (“Commerce Dept repts mfrs sales at record; illus”), with placeholder headlines for untitled items (“Article 8 – No Title”); afterwards it is the lede paragraph, for a decade prefixed with a literal “LEAD:”. Those conventions are cleaned before the text is tokenised for naming (§Two editions), and only for that source. Every source is read by an adapter split into a pure parser, unit-tested on fixtures, and a rate-limited, retrying fetcher; the whole backfill took one afternoon.

Two properties matter more than volume. Length: archetypes recur on scales of months to decades, so the basis needs decades. Consistency: a change in source mix shows up as a fake change in the world, so backfill and live stream must be embedded with the same pinned model and clustered by the same procedure.

4.2 Storage

Raw articles are append-only Parquet in a Hive layout, one file per (source, month), written atomically so that a finished partition is the resume marker for a backfill. Sail—a Spark-compatible engine in Rust—is the query engine over the layout (et sql registers raw/articles as a view with the partition columns), while the numeric pipeline reads the same files directly with arrow-rs. Every derived table (embeddings, coordinates, statistics, stories) is keyed by the model or basis version that produced it, so any day can be re-materialised against any basis.

4.3 Stories and episodes

Single-linkage clustering joins articles connected by any chain of above-threshold pairwise similarities. Per day, articles from all sources are clustered by single-linkage on cosine similarity (0.72 in embedding space; 0.6 in the diffuser LSA space). A story’s representative is the member with the most text from a full-text source, so headlines come from newspapers rather than bulletin lines; a story’s section is the human section of a bulletin member, if any—newspaper desk names are deliberately not used, since only the bulletin sections are event categories. A centroid is the mean of a cluster’s member vectors. A story on day tt continues yesterday’s episode when its centroid agrees with a story of day t−1t-1 at cosine ≥0.9\ge 0.9; episodes are chains, so a 600-day war is one episode, and “episode day 7” on a card means the seventh day of that thread. The deployed story layer has 842,278 stories over 10,102 days; 24 February 2022 yields a 62-article, three-source lead story, “Russia launches attack on Ukraine”, on episode day 7—the thread begins with the build-up.

5 Two algorithms

Both constructions produce the same objects—an orthogonal basis, a rotation to named axes, per-article coordinates, term loadings—and everything downstream (stories, spectra, profiles, precedents, the site) is computed identically for both. They differ in what a document is.

5.1 v0: term-space LSA

Each article is tokenised (lower-cased, common stop words excluded, and Snowball-stemmed to remove word endings), counted into a 50,000-term vocabulary (document frequency between 20 and 30% of the corpus), and encoded as a TF-IDF row. For a present term, let tf>0\mathrm{tf}>0 be its within-article count and idf\mathrm{idf} its inverse-document-frequency weight. Its unnormalised value is (1+ln⁡tf)⋅idf(1+\ln\mathrm{tf})\cdot\mathrm{idf}; absent terms have zero weight. The row is then ℓ2\ell_2-normalised, meaning divided by its Euclidean length. The corpus term matrix TT has 1,093,166 rows and 149.4 million non-zero entries.

Let Ω∈ℝp×ℓ\Omega\in\mathbb R^{p\times\ell} be the random test matrix in randomized SVD, with ℓ=k+20\ell=k+20 trial columns. The algorithm approximates the leading singular directions through such products and subspace iteration, repeated multiplication that sharpens the leading span. In the uniform first edition, column means are subtracted implicitly: (T−𝟏t‾⊤)Ω=TΩ−𝟏(t‾⊤Ω)(T-\mathbf1\bar t^{\top})\Omega=T\Omega-\mathbf1(\bar t^{\top}\,\Omega). This avoids storing a dense centred term matrix. The top 60 singular triplets—paired left and right directions with a singular value—are computed with 20 oversampling columns and two rounds of subspace iteration, deterministic for a seed. The whole fit—two tokenisation passes over 1.6 GB of text, the SVD, the varimax rotation of the 50,000×6050{,}000\times60 loading matrix—runs in about five minutes on a ten-core laptop.

The rotated axes are word lists by construction, and they are strikingly clean. Among the sixty: bank · financial · credit · rate · loan · Barclays; party · Labour · Tory · conservative · leader · election; police · arrest · officer · protest · investigate · suspect · murder; price · rise · market · oil · inflation · rate · FTSE; Trump · Donald · president · Biden · Republican · immigrant; climate · emissions · carbon · global · warming · temperature; Israel · Palestinian · Gaza · Hamas · Netanyahu; flight · airline · passenger · airport · plane · crash; European · Europe · France · Germany · Brussels · euro; court · judge · rule · case · trial · legal; Russian · Russia · Ukraine · Putin · Moscow · Kremlin; covid · case · vaccine · pandemic · lockdown; house · property · home · mortgage · buyer; protest · demonstrator · activist · arrest; Korea · north · south · nuclear · Kim · Pyongyang; Ireland · northern · Irish · IRA · Sinn · Belfast; Brexit · deal · Johnson · Boris · negotiate · referendum; asylum · immigrant · refugee · seeker · migrant · border; prison · sentence · charge · jail · trial · convict; energy · gas · electricity · nuclear · carbon · renewable; attack · bomb · terrorist · terror · security · Islam; Syrian · Syria · Assad · rebel · Turkey · Damascus. The Gaza axis, the Ukraine axis and the Brexit axis are each one archetype with many episodes.

5.2 v1: the embedding eigenbasis

Each article’s headline and first 300 characters are embedded with a pinned local model (bge-small-en-v1.5, 96 tokens (model text units), classification-token (CLS) pooling (using the model’s designated summary-token vector), 384 dimensions, run through the Open Neural Network Exchange (ONNX) Runtime). Embedding is the only expensive step: about 45 documents per second per process, so two shards took roughly four hours for the corpus.

The covariance eigendecomposition is then exact up to numerical solver precision. Let m∈ℝdm\in\mathbb R^d be the weighted first-moment sum ∑iwixi\sum_iw_ix_i, and M∈ℝd×dM\in\mathbb R^{d\times d} the weighted second-moment sum ∑iwixixi⊤\sum_iw_ix_ix_i^{\top}. Together with total weight ZZ, these are sufficient statistics for the mean and covariance: summaries from which both can be reconstructed without retaining all rows. A first pass accumulates (Z,m,M)(Z,m,M)—MM is 384×384384\times384—in parallel over partitions and merges them by addition. With μ=m/Z\mu=m/Z, the identity Σ=M/Z−μμ⊤\Sigma=M/Z-\mu\mu^{\top} gives the covariance. A dense symmetric solver decomposes it in milliseconds; the top 60 eigenvectors carry 55% of the variance. A second pass projects every article, orients each component by skewness, and writes coordinates and (T2,Q,ν)(T^2,Q,\nu) per article. A third pass re-tokenises the corpus with the LSA vocabulary and computes the centred lexical loadings β=(T−𝟏t‾⊤)⊤F\beta=\left(T-\mathbf1\bar t^{\top}\right)^{\top}\,F defined above. A varimax rotation of that 50,000×6050{,}000\times60 matrix gives the naming rotation.

The rotated embedding axes are mostly topical—Trump · president · Republican · Senate · Obama; covid · vaccine · coronavirus · pandemic · hospital; climate · energy · emissions · carbon · fuel; flight · airline · passenger · airport · aircraft; court · judge · sentence · trial · legal; Russian · Russia · Ukraine · Putin · Kremlin · missile; China · Chinese · Beijing · India · Hong Kong; car · vehicle · driver · road · manufacturer; church · pope · Catholic · bishop · Vatican; Ireland · northern · IRA · Belfast · Sinn—but a few are axes of register that no term matrix can see: think · thing · know · seem · want · question · feel (opinion and interview), resign · leave · down · fall · cut · suspend · cancel (the vocabulary of ending), claim · say · statement · deny · reject · ask (contested assertion). Whether these are archetypes or artefacts is an editorial question the comparison page leaves to the reader.

5.3 What the two constructions share and where they differ

Both are eigendecompositions of a centred second-moment matrix; the difference is whether the document is a bag of words or a point in a semantic space. The term basis is interpretable by construction and has no neural embedding model to pin; the embedding residual QQ measures variation outside the retained semantic subspace and can include model artefacts as well as novel content. The embedding basis also clusters stories far better (in LSA space, same-event articles rarely exceed cosine 0.7; in embedding space the 9/11 day collapses into a 34-article lead story at 0.72). Their eigenvalue spectra differ in shape: LSA’s leading singular values decay slowly, and its top axes are broad (markets, party politics), while the embedding covariance concentrates variance in fewer directions. The Evaluation section quantifies the agreement.

6 Refinement and identity

A possible daily refinement maintains the sufficient statistics already defined. Let 𝒞t\mathcal C_t be the set of new fitting observations on day tt, and let subscripts t−1t-1 and tt denote accumulated states before and after their addition. For fixed weights, the updates are Zt=Zt−1+∑i∈𝒞twiZ_t=Z_{t-1}+\sum_{i\in\mathcal C_t}w_i, mt=mt−1+∑i∈𝒞twixim_t=m_{t-1}+\sum_{i\in\mathcal C_t}w_ix_i, and Mt=Mt−1+∑i∈𝒞twixixi⊤M_t=M_{t-1}+\sum_{i\in\mathcal C_t}w_ix_ix_i^{\top}. A fresh eigendecomposition follows—exact up to numerical precision and cheap at d=384d=384. If a later arrival changes a day’s normalising weight, earlier contributions from that day must also be updated.

What is not free is identity: the symmetric eigensolver eigh returns eigenvectors in eigenvalue order with arbitrary sign. Components can swap when eigenvalues cross, and nearly degenerate groups can rotate. “Archetype 18” must therefore be tracked. Kuhn–Munkres assignment chooses the one-to-one matching with greatest total absolute cosine; signs are then chosen so matched dot products are positive. Orthogonal Procrustes aligns a group by the rotation or reflection minimising squared differences between corresponding directions. Warm-starting varimax means beginning its optimisation from the previous rotation. A component with no match above 0.8 is born and announced; one whose eigenvalue falls below the chosen noise edge is retired but kept in the registry so old issues still resolve.

For a conditional stability statement, let θj\theta_j be the acute angle between corresponding unit eigenvectors before and after an update. Let gapj>0\mathrm{gap}_j>0 be the smallest absolute difference between the matched new eigenvalue and any other eigenvalue of the old covariance (excluding the old axis being compared), and let the matrix norm ‖⋅‖2\lVert \cdot\rVert_2 denote the spectral norm, its largest singular value. In an applicable separated-eigenvalue case the theorem gives sin⁡θj≤‖Σt−Σt−1‖2/gapj\sin\theta_j\le\lVert \Sigma_t-\Sigma_{t-1}\rVert_2/\mathrm{gap}_j. The bound does not identify individual axes inside an unresolved eigenvalue cluster.

To state an update bound explicitly, let ηt=(∑i∈𝒞twi)/Zt\eta_t=(\sum_{i\in\mathcal C_t}w_i)/Z_t be the new batch’s fraction of total weight, and let Lt=max⁡i∈𝒞t‖xi−μt−1‖L_t=\max_{i\in\mathcal C_t}\lVert x_i-\mu_{t-1}\rVert be its largest distance from the old mean. For a nonempty batch, weighted covariance updating gives ‖Σt−Σt−1‖2≤ηt(‖Σt−1‖2+Lt2)\lVert \Sigma_t-\Sigma_{t-1}\rVert_2\le\eta_t(\lVert \Sigma_{t-1}\rVert_2+L_t^2). If batch fractions decrease at the rate 1/t1/t, covariance and batch distances remain bounded, and the relevant separation stays positive, the per-update angle is O(1/t)O(1/t): bounded by a constant times 1/t1/t for sufficiently large tt. This conditional shrinking-step bound alone does not prove convergence of the sequence of bases.

Two ordering rules keep such a chronological protocol honest. Measure day tt against the basis through day t−1t-1 before updating its statistics; otherwise today’s observations partly explain themselves. Retain the full historical archive rather than introducing unreported recency weighting. The first edition uses uniform article weights and the second the day-balanced weights below; era statistics serve a different comparison purpose.

Matching, alignment, statistics, and rotation have implementations and tests in et-basis. Their automatic nightly refitting schedule remains future work (Limitations and next steps); the deployed editions measure new articles in fixed bases.

7 Two editions

7.1 Day-balanced weights

The first edition’s basis is the basis of 1999–2026. With the Times archive in place the question is what weight to give 175 years: by article count the modern era dominates (the Guardian alone contributes about as many articles per day as the Times ever did), and by wall-clock time it is fifteen per cent of the record. The second edition takes the second view and weights each article by the inverse of the number of articles published on its day. Let ii index an article, τ(i)\tau(i) its publication day, and n(τ)n(\tau) the number of fitted articles on day τ\tau. For a day with articles,

wi=1/n(τ(i)),∑τ(i)=τwi=1 for every day τ,w_i = 1 / n(\tau(i)), \qquad \sum_{\tau(i) = \tau} w_i = 1 \text{ for every day } \tau,

so that a day in 1887 and a day in 2024 contribute equally to μ\mu and Σ\Sigma (§The mathematics; the covariance formulae are unchanged). For term-space fitting, let t‾w=Z−1T⊤W𝟏∈ℝp\bar t_w=Z^{-1}T^{\top}\,W\mathbf1\in\mathbb R^p be the weighted mean term column. The LSA of the second edition is the SVD of W1/2(T−𝟏t‾w⊤)W^{1/2}(T-\mathbf1\bar t_w^{\top}) with the same weights, so both bases are balanced the same way. This fitted term mean is distinct from the unweighted lexical-naming mean t‾\bar t. The total weight is the number of days with news, 63,270.

7.2 Cleaning the index register

Fitting on the Times exposed a register problem that the modern sources never had. The strongest terms of several rotated axes were titl · articl · page · front · editori · correct · repts: the vocabulary of the newspaper’s own index rather than of events. Three rules, applied only to Times documents before tokenising, remove it: placeholder headlines lose their boilerplate (“Article 8 – No Title” is dropped, “Letter to the Editor 3 – No Title” keeps its kind), the “LEAD:” marker is stripped, and a source-specific stop list drops the index’s annotation words (illus, por, repts, mfrs, page, correction, editorial and the like). The rule lives in one place, et-cli’s terms module, and is shared by the LSA fit, the eigen term loadings and the nightly projection; the embedding axes themselves are untouched by it, since embeddings are computed from the raw text. After the fix the sixty axes of the 175-year basis read as news: quarterly earnings; the presidency; deaths and funerals; Israel and Palestine; sports; the boroughs of New York; the courts; Congress and taxes; banking; corporate appointments; police and crime; war and the military; elections; the performing arts.

7.3 What 175 years changed

We measured the two eigenbases on the same 20,471 Wikipedia events of 2023–2026, whose human sections were never used in fitting. Section purity is the fraction of labelled events whose assigned axis’s majority section matches their own label. For two orthonormal loading matrices in the same embedding space, the singular values of their cross-product are principal cosines: they compare the retained spans independently of individual axis labels. A matched-axis cosine instead compares the paired directions themselves; bars denote its absolute value.

v1 basis (1999–2026) v2 · 175 years
explained variance of the top 60 axes 0.550 0.545
section purity on 2023–2026 events 0.431 0.435
axes that dominate at least one event 58 / 60 60 / 60
largest axis’s share of the events 58% 27%
mean principal cosine between the two 60-dimensional spans 0.875
principal directions with cosine above 0.9 42 / 60
median |cos⁡|\vert\cos\vert of Kuhn–Munkres-matched axes 0.32

The old news did not overwhelm the new. The 175-year basis explains today’s events exactly as well as the modern one and distributes them better: the first edition sends 58 per cent of labelled events to a single armed conflict axis, the second keeps its largest axis to 27 per cent and separates conflict, disasters, law and crime, and elections. The last three rows say how: the spans of the two bases nearly coincide (42 of 60 principal directions agree to within 26°), but the individual axes within that span have rotated, as the Davis–Kahan bound permits when eigenvalue gaps (here of order 10−310^{-3}) are smaller than the perturbation a new weighting introduces. Since the newspaper prints axes, not spans, the two editions are different newspapers of the same news, and the deployed paper carries both: the root edition is the first, /v2 the second, and every page has a masthead switch that shows both editions with the current one marked.

8 The newspaper

The issue of 24 February 2022. Both bases put the Russia–Ukraine axis at ; the lead story is 62 articles from three sources on episode day 7; the eigen precedents are the 2014 Crimea stories.

A day page (Figure 1) opens with the spectrum: for each basis, the axes ranked by their share of the day’s energy, each bar coloured when its zz-score against the era statistics is beyond ±2\pm 2, followed by a Silence line listing archetypes that are usually present and are not. On 24 February 2022 both bases put russian · russia · ukrain · putin at z≈+8z \approx +8; the LSA also flags covid and nation · million · union · strike, the eigenbasis unit · injur · forc · target.

Then the stories, ranked by energy times (1+ν)(1+\nu) so that big and unexplained rises. Each card carries the dominant archetype of each basis as a badge, the human section if a bulletin member had one, the counts of articles and sources, the episode day, T2T^2 and novelty, and then one panel per basis: the top four coordinates as bars; Same as always—the strongest axes of the archetype’s profile that this story also carries; Different this time—the axes on which the story departs from the profile by more than 1.5σ1.5\sigma, with direction and magnitude; and the five closest precedents from distinct episodes, each a link to its day. For the invasion story both panels honestly report nothing beyond 1.5σ of this archetype’s profile—it is a textbook instance of its archetype—while the precedents differ instructively: the LSA finds the same week’s build-up briefings and 26 February 2014 (Crimea, 0.97), the eigenbasis reaches for “Ukraine: what will happen now?” (2 March 2014) and “Ukrainian president: Russian troops have crossed border” (28 August 2014).

The issue of 12 September 2001. The lead story’s LSA panel reads Different this time: flight · airline · passenger · airport, +3.2σ more than usual, and its precedents are the 1999 airport bomb alerts and the 1999 bin Laden rocket raids.

The day after 11 September 2001 (Figure 2) shows the delta panel doing its job. The spectrum lights attack · bomb · terrorist · terror at +2.9+2.9, european at +2.6+2.6 and market at +2.5+2.5; the lead story, 34 articles under the terrorism archetype, is different from that archetype’s profile in one direction—flight · airline · passenger · airport, +3.2σ+3.2\sigma more than usual—and its precedents are “Airports put on alert for bombs” (December 1999), “US bases in Italy on terror alert” (January 2001) and “Bin Laden is suspect in rocket raids” (November 1999).

Below the stories, The Residual lists the day’s stories with the highest ν\nu: the ones the basis explains least, which is where the genuinely new hides.

An archetype page: the eigen axis russian · russia · ukrain · putin, with its term list, energy by year, the distribution of human sections among its stories, and the canon.

An archetype page (Figure 3) shows the axis’s full term list, the number of stories it dominates, its energy by year as a bar per year—the Ukraine axis has spikes in 2014 and from 2022—the distribution of human sections among its stories (1,084 Armed conflicts and attacks, 529 International relations), and the canon: the purest instances over the years, one per episode, by coordinate.

The comparison page: section purity of the two bases and their axes matched by Kuhn–Munkres on the correlation of story coordinates.

The comparison page (Figure 4) is where the two algorithms meet: the number of axes, the number of articles with coordinates, the section purity of each basis, the matched-axis table, and every axis of each basis with its terms, story count and majority section. An all-issues page lists every day since 1 January 1999.

9 Evaluation

9.1 Recovery of human categories

Wikipedia’s bulletins carry a human section per event. The sections were never used to fit either basis. For each basis we define an axis’s majority section as the most common section among the labelled stories it dominates, and section purity as the share of labelled stories whose dominant axis’s majority section is their own. The LSA basis scores 42.4%, the embedding eigenbasis 40.0%. Both are far above chance (the largest section is under a quarter of the labelled stories), and both are limited by the same thing: the sections are eight coarse categories while the axes are sixty fine ones, so an Armed conflicts bulletin about Gaza and one about Ukraine sit on different axes that both have Armed conflicts as majority—counted as hits—while Politics and elections is spread across a dozen political axes whose majority sections differ.

9.2 Agreement between the bases

Correlation here is the covariance of two coordinate series divided by the product of their standard deviations; the table abbreviation “corr” denotes it. Matching the sixty LSA axes to the sixty embedding axes by Kuhn–Munkres on the absolute correlation of story coordinates (a deterministic 100,000-story sample) gives pairs whose correlations run from 0.75 down to about 0.5. The clearest pairs are the ones a reader would draw by hand:

corr v0 · LSA axis v1 · eigen axis
+0.67 russian russia ukrain putin ukrainian moscow russian russia ukrain putin ukrainian moscow
+0.67 parti labour tori conserv leader elect elect parti labour vote minist tori polit
+0.62 court judg rule case trial legal justic court judg case sentenc trial law legal
+0.62 trump donald presid biden republican trump presid donald republican senat
+0.61 climat emiss chang carbon global warm climat energi emiss gas carbon fuel
+0.59 covid case vaccin pandem coronavirus covid vaccin health case coronavirus
+0.59 flight airlin passeng airport plane flight airlin passeng airport plane air
+0.57 european europ franc germani french european europ franc french germani brexit

The negative correlations in the full table are also informative: the LSA’s police · arrest · investigate · murder axis pairs at −0.69-0.69 with the embedding’s world · company · market · develop axis—the two bases agree that crime reporting and business reporting are opposite ends of one direction, and disagree only about which end to name.

9.3 What each basis sees that the other does not

The term basis cannot see register; the embedding basis cannot help seeing it. The embedding basis clusters events far better and gives a meaningful residual; the term basis produces crisper names and needs no model. On the evidence of Recovery of human categories neither dominates, and the deployed paper prints both.

10 Engineering: computing in flat memory

The first edition was fitted on a laptop in an afternoon, and its code held what it needed in memory: every article’s embedding and coordinates for orienting the axes, and the whole document–term matrix, twice, for the term loadings. At 16.5 million articles that design was killed by the operating system in the third pass of et eigen, at about forty gigabytes. The fix was not a bigger machine but a change of shape: every quantity the fit needs is a sum over documents, and sums can be accumulated over partitions and thrown away.

Covariance already was. The total weight ZZ, first-moment column mm, and second-moment matrix MM defined above are sums over article rows: Z=∑iwiZ=\sum_iw_i, m=∑iwixim=\sum_iw_ix_i, and M=∑iwixixi⊤M=\sum_iw_ix_ix_i^{\top}. Each partition accumulates its own contribution, and merging adds corresponding entries.

Orientation used to sort every axis’s coordinate column to decide its sign. For a fixed raw axis jj, let ii index article rows, cijc_{ij} be entry (i,j)(i,j) of the raw coordinate matrix CC, and nn count accumulated rows. Let S1,S2,S3S_1,S_2,S_3 be scalar sums of the first, second, and third powers: S1=∑icijS_1=\sum_i c_{ij}, S2=∑icij2S_2=\sum_i c_{ij}^2, and S3=∑icij3S_3=\sum_i c_{ij}^3. These scalar power sums are distinct from the SVD matrix SS. Let c‾=S1/n\bar c=S_1/n be the mean coordinate and m3m_3 the third central moment, the average cubed deviation from that mean. For n>0n>0 it is

m3=S3/n−3c‾S2/n+2c‾3,c‾=S1/n.m_3 = S_3 / n - 3 \bar{c} \, S_2 / n + 2 \bar{c}^{\,3}, \qquad \bar{c} = S_1 / n.

An axis is flipped when m3<0m_3<0, exactly the rule the batch code applied to the full column (a test checks the two agree on every axis, including the merge of two partial accumulators).

Term loadings use the N×kN\times k standardised raw score matrix FF, the N×pN\times p term matrix TT, and the unweighted term mean t‾∈ℝp\bar t\in\mathbb R^p defined above. Expanding the centred product gives β=(T−𝟏t‾⊤)⊤F=T⊤F−t‾(𝟏⊤F)\beta=\left(T-\mathbf1\bar t^{\top}\right)^{\top}\,F=T^{\top}\,F-\bar t(\mathbf1^{\top}\,F). Let bb index disjoint row blocks, NbN_b their row counts, TbT_b and FbF_b their aligned term and score matrices, and 𝟏b\mathbf1_b a column of NbN_b ones. Since the blocks partition all NN rows,

β=∑bTb⊤Fb−t‾∑b𝟏b⊤Fb,t‾=N−1∑bTb⊤𝟏b.\beta=\sum_b T_b^{\top}\,F_b-\bar t\sum_b\mathbf1_b^{\top}\,F_b,\qquad \bar t=N^{-1}\sum_bT_b^{\top}\,\mathbf1_b.

Each partition therefore tokenises its own articles into a small sparse block TbT_b, projects and standardises its own embeddings into FbF_b, adds Tb⊤FbT_b^{\top}\,F_b (a 50,000×6050{,}000 \times 60 dense matrix, 24 MB), the column sums of TbT_b and the column sums of FbF_b into an accumulator, and is dropped. Blocks may arrive in any order and from any thread; accumulators merge by addition. A property test checks that the block form equals the whole-matrix operator to 10−1210^{-12}. The same pass writes the partition’s coordinates and T2/Q/νT^2/Q/\nu rows, so the whole of et eigen is now three streaming passes—covariance, orientation, measurement—and runs on the 16.5-million-article corpus in ten minutes at 0.3 GB resident.

Stories clustered the archive after loading every vector; a day’s clustering depends only on that day and, for episode threading, on the previous day’s stories, so the pass now runs month by month, carrying yesterday’s stories across the boundary and holding one month of articles at a time.

Two things still do not stream. The randomized SVD of the term matrix needs TT in memory—455 million non-zeros for this corpus, a peak of 31 GB—which a 64 GB laptop affords; block products could remove that requirement too. For example, let ℓ\ell count test columns and let Ψ∈ℝN×ℓ\Psi\in\mathbb R^{N\times\ell} be a dense row-aligned test block; T⊤ΨT^{\top}\,\Psi and the column sums needed for centring both decompose over row partitions. This is the obvious next step. And the site’s in-memory index, which serves any day from memory and finds precedents across the whole archive, holds all 13.4 million stories of the second edition (about 20 GB). That last fact decides where things run: the GitHub runner (7 GB, 14 GB of disk) builds the root edition nightly and never pulls the second edition’s tables; the second edition is maintained from the laptop by a script that pulls the runner’s fresh articles and embeddings, measures them against the fitted bases without refitting, extends the stories, exports the recent issues and deploys them under /v2.

Two failure-mode decisions were made along the way. Partition reads that used to be swallowed into empty results now fail the fit with the partition’s name, and every partition’s articles are checked id-by-id against its embeddings before they are measured, so a stale or partial embedding can no longer silently shift a basis.

pass before after
eigen: orientation all NN vectors and coordinates in memory (≈30 GB) power sums per axis (0 GB)
eigen: term loadings two copies of TT plus FF (≈20 GB) one 50,000×6050{,}000 \times 60 accumulator per thread (24 MB)
stories all NN vectors and metadata (≈25 GB) one month at a time
LSA: randomized SVD TT in memory unchanged (31 GB peak)
site index all stories unchanged (20 GB for 13.4 M stories)

11 Implementation

The system is a Rust workspace of ten crates behind one binary, et:

crate role
et-core domain types: Article, Source, YearMonth, with validating constructors
et-sources archive adapters: pure parsers over fixtures, rate-limited retrying fetchers
et-store Parquet layout, atomic partition writers and readers, a Spark Connect session to Sail
et-embed the pinned embedding model
et-text tokeniser, vocabulary, sparse TF-IDF rows with implicit centring, LSA
et-basis covariance accumulation and eigendecomposition, randomized SVD over a linear-operator trait, varimax by pairwise rotations, Kuhn–Munkres matching, T2/Q/νT^2/Q/\nu
et-stories daily single-linkage clustering, energy, episode threads
et-models persistence of fitted models as long-format Parquet, so Sail can query them
et-site the in-memory index, the statistics, the pages, an axum server with per-IP rate limiting, and the static export
et-cli et backfill · embed · lsa · eigen · stories · serve · export · sql

The code follows a normative style guide inherited from the author’s QueryGraph work: algebraic data types for domain alternatives, a functional core behind an imperative shell, typed errors at library boundaries, tests in sibling files, and fmt/clippy -D warnings/test as gates. Two implementation notes are worth recording. A plane, or Givens, rotation changes only two coordinate axes at once. Kaiser’s varimax method sweeps over pairs, choosing an angle to improve the loading-concentration objective. It is used rather than the SVD-polar fixed-point iteration, which repeatedly recomputes a whole orthogonal rotation from an SVD, because the latter oscillates on symmetric configurations (it bounced between two mirror-image 30° states on a test case) while the pairwise method increases the criterion monotonically. For a sparse input matrix XX and dense block YY with the same row count, the sparse operator computes X⊤YX^{\top}\,Y by per-thread partial accumulation over row chunks, which is what makes randomized SVD on a 149-million-non-zero matrix a matter of seconds per product.

The site loads the whole index of the first edition in about three minutes—1.09 million article records, two 60-dimensional coordinate tables, 842,278 stories, the era statistics and profiles—and serves any day from memory; the second edition’s index (16.5 million records, 13,421,090 stories) loads in about one minute from local disk and holds 20 GB. For deployment it is exported as 10,227 static objects (about 2 GB) to a private S3 bucket behind CloudFront, with an AWS WAF rate-based rule (600 requests per IP per five minutes) as the edge rate limit and a Route 53 zone for the domain.

12 Limitations and next steps

The delta is quantitative only. The design calls for a per-archetype slot schema—belligerents, trigger, external powers, weapons class for a war; office holder, allegation, evidence, stage for a scandal—filled by a language model for today’s story and its precedents and diffed. That layer, and the location of the residual in the story’s own sentences (embedding sentences and taking those most aligned with rr), are designed but not built; the deployed paper says how far a story is from its archetype’s profile, not yet what is different in words. Its honesty is a feature—the invasion of Ukraine reads as a textbook instance of its archetype, which is true of its coordinates—but the reader wants the actors.

Names are term lists. Without a language model the axes are named by their loadings; russian · russia · ukrain · putin is unambiguous, unit · injur · forc · target less so.

The basis is the basis of the sources read. Three Anglophone sources make “a bad turn in the Middle East” an archetype and “a bad turn in the Sahel” a residual. Per-source contributions to each axis should be tracked and printed.

The nightly loop measures but does not yet refit. Both editions are rebuilt every night—the root edition by a GitHub Actions runner, the second from a laptop—by refreshing the sources, embedding and measuring the new articles against the fitted bases, extending the stories and exporting the recent issues. The refinement mathematics is implemented and tested but not scheduled: the colophon reporting drift against its bound, the RSS and Google News adapters, and the Time Machine (any date against any basis version) are the next build.

Register axes. Whether the embedding basis’s opinion, ending and assertion axes are archetypes of news or artefacts of the embedding is unresolved; the comparison page is the instrument for deciding. The 175-year basis adds a variant of the question: obituaries, marriage announcements and letters to the editor are recurring newspaper content and form axes of their own, which a reader of today’s page may or may not want counted as news.

13 Conclusion

Eigen Times reads a quarter-century of news as a matrix and prints each day as coordinates. The archetypes it finds—by two unrelated constructions—are the ones a reader would name, and its statistics give “how is it different this time” a number before a sentence. The system is small: one binary, a laptop, an afternoon of backfill, five minutes for one basis and a few hours for the other. What it lacks is the language layer that turns a 3.2σ3.2\sigma excess on flight · airline · passenger · airport into the sentence a newspaper would print. That is the next issue.

Acknowledgements

The system and this article were built in a single day’s pair-programming session with Claude (Fable 5) in Claude Code, from a one-paragraph brief to the deployed site. The Guardian Open Platform, the Wikimedia Foundation and the Wikinews community made the corpus possible.

References

  1. Allan, J., Carbonell, J., Doddington, G., Yamron, J., & Yang, Y. (1998). Topic Detection and Tracking pilot study: Final report. Proceedings of the DARPA Broadcast News Transcription and Understanding Workshop.
  2. Blei, D. M., Ng, A. Y., & Jordan, M. I. (2003). Latent Dirichlet allocation. Journal of Machine Learning Research, 3, 993–1022.
  3. Blei, D. M., & Lafferty, J. D. (2006). Dynamic topic models. Proceedings of the 23rd International Conference on Machine Learning, 113–120.
  4. Carlson, M. (2015). The robotic reporter: Automated journalism and the redefinition of labor, compositional forms, and journalistic authority. Digital Journalism, 3(3), 416–431.
  5. Cutler, A., & Breiman, L. (1994). Archetypal analysis. Technometrics, 36(4), 338–347.
  6. Das, A. S., Datar, M., Garg, A., & Rajaram, S. (2007). Google News personalization: Scalable online collaborative filtering. Proceedings of the 16th International Conference on World Wide Web, 271–280.
  7. Davis, C., & Kahan, W. M. (1970). The rotation of eigenvectors by a perturbation. III. SIAM Journal on Numerical Analysis, 7(1), 1–46.
  8. Deerwester, S., Dumais, S. T., Furnas, G. W., Landauer, T. K., & Harshman, R. (1990). Indexing by latent semantic analysis. Journal of the American Society for Information Science, 41(6), 391–407.
  9. Gholipour Ghalandari, D., Hokamp, C., Pham, N. T., Glover, J., & Ifrim, G. (2020). A large-scale multi-document summarization dataset from the Wikipedia Current Events Portal. Proceedings of ACL 2020, 1302–1308.
  10. Graefe, A. (2016). Guide to Automated Journalism. Tow Center for Digital Journalism, Columbia University.
  11. Grootendorst, M. (2022). BERTopic: Neural topic modeling with a class-based TF-IDF procedure. arXiv:2203.05794.
  12. Halko, N., Martinsson, P.-G., & Tropp, J. A. (2011). Finding structure with randomness: Probabilistic algorithms for constructing approximate matrix decompositions. SIAM Review, 53(2), 217–288.
  13. Hofmann, T. (1999). Probabilistic latent semantic indexing. Proceedings of the 22nd ACM SIGIR Conference, 50–57.
  14. Hotelling, H. (1931). The generalization of Student’s ratio. Annals of Mathematical Statistics, 2(3), 360–378.
  15. Jackson, J. E., & Mudholkar, G. S. (1979). Control procedures for residuals associated with principal component analysis. Technometrics, 21(3), 341–349.
  16. Kaiser, H. F. (1958). The varimax criterion for analytic rotation in factor analysis. Psychometrika, 23(3), 187–200.
  17. Kuhn, H. W. (1955). The Hungarian method for the assignment problem. Naval Research Logistics Quarterly, 2(1–2), 83–97.
  18. Leetaru, K., & Schrodt, P. A. (2013). GDELT: Global data on events, location, and tone, 1979–2012. ISA Annual Convention.
  19. Leskovec, J., Backstrom, L., & Kleinberg, J. (2009). Meme-tracking and the dynamics of the news cycle. Proceedings of KDD 2009, 497–506.
  20. Mikolov, T., Sutskever, I., Chen, K., Corrado, G., & Dean, J. (2013). Distributed representations of words and phrases and their compositionality. Advances in Neural Information Processing Systems, 26.
  21. Newman, D., Chemudugunta, C., Smyth, P., & Steyvers, M. (2006). Analyzing entities and topics in news articles using statistical topic models. Intelligence and Security Informatics (ISI 2006), 93–104.
  22. Petrović, S., Osborne, M., & Lavrenko, V. (2010). Streaming first story detection with application to Twitter. Proceedings of NAACL-HLT 2010, 181–189.
  23. Reimers, N., & Gurevych, I. (2019). Sentence-BERT: Sentence embeddings using Siamese BERT-networks. Proceedings of EMNLP-IJCNLP 2019, 3982–3992.
  24. Xiao, S., Liu, Z., Zhang, P., & Muennighoff, N. (2023). C-Pack: Packaged resources to advance general Chinese embedding. arXiv:2309.07597.