Skip to content

Reading the diagnostics

Every finding that involves a probability is conditional on the credences the graph supplies. The diagnostics measure the encoding: what the premises deliver if they hold as often as their bases say. They do not know more about the premises than the encoding does. This page works through what that means on small graphs whose answers can be checked by hand, using the command line as the worked example does. Each diagnose run below also lists every premise as unanchored, since none has a --source; those lines are left out.

Equal credences rank claims by counting premises

Two claims, each stated at 0.9 by their source, rest on premises that are all given the same default credence, Beta(8, 2), with mean 0.8. A requires two of them, B three:

credencegraph init rank.json
credencegraph add-node rank.json --id a1 --base beta:8,2
credencegraph add-node rank.json --id a2 --base beta:8,2
credencegraph add-node rank.json --id b1 --base beta:8,2
credencegraph add-node rank.json --id b2 --base beta:8,2
credencegraph add-node rank.json --id b3 --base beta:8,2
credencegraph add-node rank.json --id A --base 1 --stated 0.9
credencegraph add-node rank.json --id B --base 1 --stated 0.9
credencegraph relate rank.json a1 A --type requires --strength 1
credencegraph relate rank.json a2 A --type requires --strength 1
credencegraph relate rank.json b1 B --type requires --strength 1
credencegraph relate rank.json b2 B --type requires --strength 1
credencegraph relate rank.json b3 B --type requires --strength 1
credencegraph query rank.json marginal A   # 0.64
credencegraph query rank.json marginal B   # 0.512

These are 0.8² and 0.8³. When every premise has the same credence, the only thing that differs between two claims is the structure, so the ranking is a count of premises: a claim that requires k of them gets 0.8ᵏ, and the one with fewer comes first. A ranking made this way can agree with an expert's judgement of the claims, but so does counting, and the agreement says nothing about the premises.

The information in a ranking comes from credences that differ. Suppose a reader doubts A's two premises, at 0.6, and trusts B's three, at 0.97. The same graph with those bases, informed.json, gives P(A) = 0.6² = 0.36 and P(B) = 0.97³ = 0.912673, and the ranking reverses.

An overclaim flag is not a verdict

diagnose compares each stated credence with the probability the premises deliver, in log-odds, and reports a gap above 2 ln(11/9) ≈ 0.401 as an overclaim or an underclaim. Under the default credences above both claims are flagged:

credencegraph diagnose rank.json
# overclaim:A: node 'A' is stated at 0.9 but its premises give 0.64: ...
# overclaim:B: node 'B' is stated at 0.9 but its premises give 0.512: ...

That is the usual outcome, not a finding about the source. With premises at 0.8, a claim that requires two of them, stated at 0.8, is already 0.81 apart in log-odds, twice the threshold, and more premises or a higher stated credence only widen the gap. Under default credences, almost every claim that rests on more than one premise is flagged, including well-supported ones: B, which the informed credences above put at 0.913, is flagged here. The flag alone says little.

The informative part is the size of the gap, which the finding carries. Its value is the gap in probability, stated minus computed: 0.26 for A and 0.388 for B. Its details hold stated and computed, from which the log-odds gap the threshold is applied to follows, here 1.62 for A and 2.15 for B, and threshold_log_odds, the threshold that was applied. Under equal credences and equal stated credences these sizes too are ordered by the number of premises. Under the informed credences only A is flagged, with a log-odds gap of 2.77, while B's stated 0.9 lies 0.15 below its computed 0.913 in log-odds and is not reported. Read an overclaim as "the text asserts this much more than its premises deliver at these credences", compare the sizes across claims, and check whether the gap survives credences you would defend.

Encoding a null result

requires is a noisy AND: every required premise that fails lowers the claim. That is right for a claim that needs each premise, and wrong for a claim some of whose premises, if they fail, make it more robust. A null result is the common case. "The search found no signal" needs the search to have been able to see a signal at the level claimed, but a detection threshold that is too lax, too eager to report candidates, does not weaken a non-detection: nothing passed even a permissive cut.

Encoding both as requires lets the lax threshold pull the claim down:

credencegraph init null-requires.json
credencegraph add-node null-requires.json --id sensitive --base 0.9
credencegraph add-node null-requires.json --id strict --base 0.6
credencegraph add-node null-requires.json --id null --base 0.95
credencegraph relate null-requires.json sensitive null --type requires --strength 1
credencegraph relate null-requires.json strict null --type requires --strength 1
credencegraph query null-requires.json marginal null                         # 0.513
credencegraph query null-requires.json intervene null --set strict=false     # 0
credencegraph diagnose null-requires.json --target null

Here sensitive is "the search would have found a signal at the claimed level" and strict is "the detection threshold is strict enough to keep false alarms out". The claim gets 0.95 · 0.9 · 0.6 = 0.513, and a lax threshold sets it to 0. The diagnostics then point at the wrong thing: strict is a single point of failure and tops the value of information, 0.641 bits against 0.112 for sensitive. Strictness matters to a claimed detection, where false alarms are the risk; for a non-detection, it is not a condition of the claim.

The null needs only what would have let it see the signal, and that is what it should require:

credencegraph init null.json
credencegraph add-node null.json --id sensitive --base 0.9
credencegraph add-node null.json --id null --base 0.95
credencegraph relate null.json sensitive null --type requires --strength 1
credencegraph query null.json marginal null                          # 0.855
credencegraph add-node null.json --id lax --base 0.6
credencegraph relate null.json lax null --type supports --strength 0.5
credencegraph query null.json marginal null                          # 0.8685
credencegraph query null.json intervene null --set lax=false         # 0.855

When a premise would make the null more convincing, such as lax, "the threshold was low enough that marginal candidates would have passed", it is a reason for the claim and enters as supports: if it holds, the claim rises, to 0.9 · (1 − 0.05 · 0.5) = 0.8775; if it fails, the claim keeps 0.95 · 0.9 = 0.855, what it had without it. The 0.8685 the marginal query reports is the average of the two over lax's own credence, 0.6 · 0.8775 + 0.4 · 0.855. A premise that does not bear on the null either way is best left out.

The test for each premise of a null or upper-limit claim is which way its failure moves the claim. A failure that could hide a real signal, such as a search less sensitive than stated, a noise level underestimated or a part of the parameter space not covered, makes an upper limit too tight: that premise is required. A failure that only makes the limit looser than it need be, such as a conservative noise model, leaves "the quantity is below L" true, and does not belong under requires.

Supports from one source pile up

supports is a noisy OR: each support is a reason of its own, and each that holds has its own chance to make the claim true. Ten reasons of strength 0.2 into a claim of base 0, all of them holding, give it

1 − (1 − 0.2)¹⁰ = 1 − 0.8¹⁰ = 0.893,

where one reason gives 0.2. That is right for ten independent reasons, such as ten separate experiments. It is wrong for ten reasons that rest on one thing, such as one author's unverified reasoning, one style of argument or one dataset: if that one thing is unsound, they fail together, and ten of them say little more than one. Weak reasons are cheap to write down, and the noisy OR rewards writing down many of them.

credencegraph init pile.json
credencegraph add-node pile.json --id claim --base 0
for i in 1 2 3 4 5 6 7 8 9 10; do
  credencegraph add-node pile.json --id reason-$i --base 1 --source paper-x
  credencegraph relate pile.json reason-$i claim --type supports --strength 0.2
done
credencegraph query pile.json marginal claim   # 0.892626
credencegraph diagnose pile.json
# correlated-support:claim:document:paper-x: node 'claim' has 10 supports, ...
#   that share document 'paper-x' but no common ancestor: ...

The correlated-support finding names a node with two or more supports that share a source and no common ancestor. Two supports share a source when they are anchored in the same document, or when each points at the same node through an authored_by or derived_from annotation. Annotations never change a credence, so recording where a reason came from is free: the diagnostic reads it, inference does not. credencegraph diagnose --min-supports N reports only groups of at least N supports, N ≥ 2; the default, 2, reports any two.

Give the shared source a proposition of its own. Add sound, "this source's unverified reasoning is sound", with the credence c you would defend for it, and have each reason require it with strength 1:

credencegraph add-node pile.json --id sound --base 0.5 --source paper-x
for i in 1 2 3 4 5 6 7 8 9 10; do
  credencegraph relate pile.json sound reason-$i --type requires --strength 1
done
credencegraph query pile.json marginal claim   # 0.446313
credencegraph diagnose pile.json               # no findings

If sound fails, every reason fails with it and the claim keeps its base b; if it holds, the reasons act as before. With N reasons of strength s,

P(claim) = (1 − c) b + c (1 − (1 − b)(1 − s)ᴺ) ≤ b + (1 − b) c,

here 0.5 · 0.893 = 0.446. However many reasons the source gives, the claim rises no higher than b + (1 − b) c, 0.5 here: the pile saturates at the credence of what it rests on.

Restatements gain nothing. Below that cap the pile still grows with N: one reason gives 0.5 · 0.2 = 0.1 and ten give 0.446. That is right when the reasons are distinct arguments that each might fail on its own, given the source. When they are one argument said N ways, the doubt belongs to the argument, not to each restatement: put it in c, here the 0.2 the argument deserves, and give each restatement strength 1. With s = 1 the formula above is b + (1 − b) c for every N ≥ 1: ten restatements give the claim 0.2, exactly what one gives.

The diagnostic cannot tell restatements from independent reasons that happen to come from one paper, such as two separate experiments it reports. When the supports are independent, the finding can be dismissed; when they are not, the common parent is the fix, and it then shows up in the crux and value of information rankings like any premise several paths share.

What the structure shows on its own

Some findings do not depend on the credences being right, because they come from the shape of the argument. Here two results share a calibration, cal, and each also needs a measurement of its own; both results support claim and claim-b, and the source itself states a caveat that tells against claim-b. Every premise has the same default credence:

credencegraph init map.json
credencegraph add-node map.json --id cal --base beta:8,2
credencegraph add-node map.json --id m1 --base beta:8,2
credencegraph add-node map.json --id m2 --base beta:8,2
credencegraph add-node map.json --id caveat --base beta:8,2
credencegraph add-node map.json --id r1 --base 1
credencegraph add-node map.json --id r2 --base 1
credencegraph add-node map.json --id claim --base 0.1
credencegraph add-node map.json --id claim-b --base 0.1
credencegraph relate map.json cal r1 --type requires --strength 1
credencegraph relate map.json m1 r1 --type requires --strength 1
credencegraph relate map.json cal r2 --type requires --strength 1
credencegraph relate map.json m2 r2 --type requires --strength 1
credencegraph relate map.json r1 claim --type supports --strength 0.9
credencegraph relate map.json r2 claim --type supports --strength 0.9
credencegraph relate map.json r1 claim-b --type supports --strength 0.9
credencegraph relate map.json r2 claim-b --type supports --strength 0.9
credencegraph relate map.json caveat claim-b --type refutes --strength 0.5
credencegraph query map.json marginal claim     # 0.763552
credencegraph query map.json marginal claim-b   # 0.458131
credencegraph diagnose map.json --target claim
  • A source's own contrary statements, entered as refutes, move a claim down. claim-b has the same support as claim and loses to the caveat, 0.763552 · (1 − 0.8 · 0.5) = 0.458131. The refuter's strength sets how far it falls; that it falls, below a claim with the same support, comes from the text.
  • A premise shared by several paths tops crux and value of information. If cal fails, both results fail together, so P(claim) moves by 0.829 per unit of its base against 0.181 for m1 or m2. Its crux is 0.1 against 0.0219, and learning it would give 0.401 bits about the claim against 0.0195. This holds at equal credences, because it is a fact about which paths share what.

This is the use the engine supports best from structure alone: mapping an argument and finding what to check first. Grading the claims needs credences that someone is prepared to defend, and every grade the diagnostics give is conditional on them.