Skip to content

The form test, and what it cannot separate

The third check exists and works

It never rejects under a position model (\(|z| < 1\) at every severity) and rejects massively under cascade (\(z = -97\) to \(-307\)). It answers the question the other two checks left open: in what form does order act?

But a click budget mimics a cascade

A reader who stops clicking once served — while still scanning the feed — produces the same signature: \(z = -144\) under a pure position model, against \(-179\) under a genuine cascade. The two are not separable from click data alone.

On Baidu-ULTR: no cascade signature

The standardised deviation is positive at every threshold — \(+5.6\) at the most permissive, \(+0.5\) to \(+0.6\) at the strictest — whereas a cascade would make it negative. The sign is that of the heterogeneity confounder, not of cascade.

And a protocol error, caught before publication

Restricting the log to multi-click sessions looked like the obvious way to separate budget from cascade. Applied to Baidu-ULTR it gives \(z = -8.2\) (\(p = 2 \times 10^{-16}\)) — a clear signature, which I was about to publish. On a pure position model, the same restriction moves \(z\) from \(+0.7\) to \(\mathbf{-45.7}\). It is a collider.


The construction

The two examination forms cannot be told apart by their shape: geometric and polynomial decay fit equally well over the first ranks. That is what made the problem look intractable.

They differ by a conditional independence:

  • under a position model, examination of rank \(R\) depends only on \(R\). Given item and rank, the click is therefore independent of what happened above;
  • under a cascade model, a click above suppresses examination below.

For each cell \(s = (\text{item}, \text{rank})\), the \(n_s\) impressions split into \(n_{1s}\) preceded by a click in the same feed and \(n_{0s}\) not, for \(k_s\) clicks in total. Under independence those clicks distribute as a draw without replacement, with exactly known moments:

\[\mathbb{E}[a_s] = \frac{k_s n_{1s}}{n_s}, \qquad \mathbb{V}[a_s] = \frac{k_s (n_s - k_s)\, n_{1s} n_{0s}}{n_s^2 (n_s - 1)}\]

This is the Mantel-Haenszel statistic, stratified by cell. Conditioning on the cell removes item quality — without it, feeds containing a click at the top are also those whose items are better, and the comparison would measure only that.

The form test

The two controls on pure models; the click budget that mimics cascade; the application to Baidu-ULTR; and the restriction that manufactures the signature it seeks. Figure regenerated by notebook 22.

The two controls

Model \(z\) Cells Verdict
position, \(\eta = 0.0\) −0.33 2,197 position-compatible
position, \(\eta = 1.0\) +0.08 1,882 position-compatible
position, \(\eta = 2.0\) +0.92 952 position-compatible
cascade, \(\gamma = 1.00\) −307.4 2,032 rejects
cascade, \(\gamma = 0.85\) −178.7 1,660 rejects
cascade, \(\gamma = 0.60\) −96.7 1,010 rejects

The test therefore separates the two models perfectly when they are pure. That is the minimum condition, and it is met.

What it cannot separate

A reader who wants only one thing stops clicking once served, while still scanning the feed. Their examination is that of a position model; only click production stops. This is entirely ordinary behaviour.

Click budget (position model) \(z\) Clicks per feed
unlimited +0.74 0.990
3 −2.15 0.979
2 −21.1 0.917
1 −144.2 0.661
cascade \(\gamma = 0.85\), for reference −178.7 0.750

Nothing in the clicks distinguishes them — as expected: in both cases the log shows exactly the same thing, namely that after a click there is nothing.

The difference nonetheless matters greatly for our purposes:

After a click, the item below… Consequence for a re-ranking
cascade is not examined moving it up changes everything
click budget is examined but will not be clicked moving it up changes nothing

The question this test was meant to settle — what exposure to attribute to deep ranks? — therefore remains open, and cannot be settled by clicks.

On real data

Baidu-ULTR is the repository's only log recording both served order and document identity: 64,200 sessions, 0.688 clicks per session, 53.4 % with no click at all.

Impression threshold \(z\) \(p\) Cells
2 +5.65 \(1.6 \times 10^{-8}\) 780
5 +1.20 0.229 261
10 +0.54 0.593 151
20 +0.61 0.543 108

No cascade signature. The sign matters as much as the magnitude, and it is here that of the announced confounder: a reader more inclined to click clicks more everywhere, hence both above and below.

Three readings remain possible, and the repository cannot decide between them: examination there is close to a position model; or a cascade exists but the confounder masks it — the test is conservative, as it has always said; or coverage is too thin, 108 cells at the strictest threshold, because the same URL rarely reappears in a search log.

What this non-rejection does not do

It does not validate the power law. The blind spots showed it errs by a factor of 4,110 at rank twelve if examination is a cascade. Failing to detect a cascade with 108 cells does not establish its absence.

The error, and the check that caught it

53 % of Baidu-ULTR sessions have no click. The natural idea is to restrict the test to multi-click sessions — where a budget of one is excluded by construction, hence where cascade and budget should finally separate. Applied to Baidu-ULTR, the restriction gives \(z = -8.2\): a clear cascade signature on real data.

The same protocol, applied to logs whose truth is known:

Model \(z\) (whole log) \(z\) (restricted)
position, unlimited budget +0.74 −45.7
position, budget = 2 −21.1 −52.5
cascade, \(\gamma = 0.85\) −178.7 no cells

On a log simulated under a pure position model, with no cascade and no budget, the restriction manufactures a deviation of −45.7. The reason has a name: a feed's click count is a collider of its individual clicks, and conditioning on it induces negative dependence between them — this is Berkson's paradox.

The \(-8.2\) obtained on Baidu-ULTR therefore measures no cascade: it measures the selection I had just performed. The warning now sits in the function's documentation, where someone will have the idea of doing it again.

This is the third time in this repository that a seemingly reasonable protocol manufactures its own result, and the third time a check on simulated data catches it before publication. The rule that emerges deserves writing down: any protocol applied to real data must first be applied to data whose answer is known.

The three checks, now

Check Question MIND Baidu-ULTR
exchangeability does the order say anything? no (\(z = +0.12\)) yes (\(z = -206\))
identifiability is there enough to estimate \(\eta\)? yes, artificially yes, 55 documents
form does examination depend on upstream? not applicable not detected (\(z = +0.5\))

The third exists, works, and does not settle what we wanted settled.

Lead — settled, and it decided

~~Baidu-ULTR publishes displayed_time, serp_height and slipoff_count_after_click.~~ → done. On the examination measure, cascade and budget separate perfectly — \(z = -158\) to \(-412\) against \(-1.03\) — and cascade is refuted on Baidu-ULTR: examination below a click is there more frequent, not less.

Better still: exposure stops being estimated. Measured directly, its severity is \(0.88 \pm 0.05\) over 143 documents, against \(1.09\) estimated over 55 from clicks — 23 % overstatement, because a click conflates examination with attractiveness.


Reproducibility

Baidu-ULTR's raw log is not versioned — 0.9 GB, CC BY-NC licence. The digest now carries the four counts per cell the test needs: impressions, impressions preceded by a click, clicks, and clicks preceded. No row designates a reader, and the result is recomputed identically — zero gap, which a test verifies.

This is also a useful property for the data access request: the form test is computable from aggregates, like the repository's other three measurements.

One exception, and what it signals

The restriction to multi-click sessions requires the full log — it cannot be computed from aggregate counts. That should have been a first warning: a protocol needing to return to individual rows performs a selection, and a selection has a price.


Implementation: ide.logs.upstream_dependence_test, ide.logs.upstream_dependence_from_counts · Notebook: 22 — The form test · the two blind spots · MIND's exploration · logs that record the rank