A classification pass over a large corpus prints its progress. Here are two numbers from the same run, in the same line:
judged=8/1601 judged_atoms=4569/62613
Eight of sixteen hundred. Four and a half thousand of sixty-two thousand. Both are "how much have we judged", both are correct, and they are not the same question.
The first counts files. The second counts items inside files. Eight files is half a percent of the files, and those eight files happened to be dense, so they carry 4,569 items. Quote either number and you have said something true and given a completely different impression.
The number I wanted to quote
The first one, obviously. 8/1601 sounds like early days and sets expectations low. 4569/62613 sounds like seven percent, which sounds like a slog.
Neither is the honest headline, because the honest headline has to say what a unit is before it says how many there are. The line now carries both, with different names, and nothing in the project is allowed to say "judged" without one of those two words attached.
| label | unit | value | what it answers |
|---|---|---|---|
judged |
files | 8/1601 | how many documents have been through the pass |
judged_atoms |
items | 4569/62613 | how much of the corpus that represents |
The line that makes the rest of it checkable
The same output carries a breakdown:
top=1172 bot=69 classed=3328 unjudged=58044
classes=business_face:165, gui:1348, needs_owner:47,
no_referent:519, outside_backend:1201, pointer_only:48
and one thing that is not a count:
top + bot + classed + unjudged = atoms (refused when it does not hold)
That identity is the only reason any of the numbers above are worth reading.
A breakdown that does not sum to the total is the most ordinary defect a classification report can have, and it is invisible: every individual category was computed correctly, one path just never assigned anything, or assigned twice. The reader sees six plausible numbers and no way to tell. Printing the sum, and failing the run when it is wrong, converts that from something nobody checks into something nobody can ship.
class_unknown=0 sits alongside for the same reason: "how many items got a class outside the declared set" is a number, printed every run, and it is zero because unknown classes are refused per file rather than absorbed.
Keeping the ugly number in
unjudged=58044 is 93% of the corpus. It would be very easy to leave it out, or to scope the report to "the part we are working on", and every percentage in the output would improve.
It stays because a denominator that shrinks to the work in progress measures the work in progress. The point of the line is to answer "how much of the thing is done", and the thing does not get smaller because we have not looked at it yet.
Three rules
Name the unit in the name. Not in the documentation, not in a comment: in the identifier that gets printed and grepped. judged and judged_atoms cannot be confused at a glance; judged and judged can.
Print the partition identity and enforce it. Categories that sum to the total are a claim, and a claim you do not check is decoration. This is one line and it is the difference between a breakdown and a list of numbers.
Keep the unmeasured remainder in the denominator. Anything else is a report about the scope you chose, wearing the costume of a report about the work.
Top comments (0)