evalaudit 0.3.0__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- evalaudit-0.4.0/CHANGELOG.md +637 -0
- {evalaudit-0.3.0 → evalaudit-0.4.0}/PKG-INFO +38 -23
- {evalaudit-0.3.0 → evalaudit-0.4.0}/README.md +37 -22
- {evalaudit-0.3.0 → evalaudit-0.4.0}/evalaudit/_types.py +269 -146
- {evalaudit-0.3.0 → evalaudit-0.4.0}/evalaudit/agreement.py +6 -1
- {evalaudit-0.3.0 → evalaudit-0.4.0}/evalaudit/audit.py +292 -39
- {evalaudit-0.3.0 → evalaudit-0.4.0}/evalaudit/judge.py +46 -7
- {evalaudit-0.3.0 → evalaudit-0.4.0}/evalaudit/pairwise.py +2 -0
- {evalaudit-0.3.0 → evalaudit-0.4.0}/evalaudit/power.py +3 -3
- {evalaudit-0.3.0 → evalaudit-0.4.0}/evalaudit/scores.py +4 -2
- {evalaudit-0.3.0 → evalaudit-0.4.0}/pyproject.toml +1 -1
- {evalaudit-0.3.0 → evalaudit-0.4.0}/tests/test_agreement.py +219 -22
- {evalaudit-0.3.0 → evalaudit-0.4.0}/tests/test_audit.py +917 -23
- {evalaudit-0.3.0 → evalaudit-0.4.0}/tests/test_compare.py +2 -2
- {evalaudit-0.3.0 → evalaudit-0.4.0}/tests/test_judge.py +211 -18
- evalaudit-0.4.0/tests/test_not_shown.py +367 -0
- {evalaudit-0.3.0 → evalaudit-0.4.0}/tests/test_pairwise.py +36 -0
- {evalaudit-0.3.0 → evalaudit-0.4.0}/tests/test_power.py +39 -1
- {evalaudit-0.3.0 → evalaudit-0.4.0}/tests/test_scores.py +20 -3
- evalaudit-0.3.0/CHANGELOG.md +0 -255
- {evalaudit-0.3.0 → evalaudit-0.4.0}/.github/workflows/tests.yml +0 -0
- {evalaudit-0.3.0 → evalaudit-0.4.0}/.gitignore +0 -0
- {evalaudit-0.3.0 → evalaudit-0.4.0}/LICENSE +0 -0
- {evalaudit-0.3.0 → evalaudit-0.4.0}/evalaudit/__init__.py +0 -0
- {evalaudit-0.3.0 → evalaudit-0.4.0}/evalaudit/compare.py +0 -0
- {evalaudit-0.3.0 → evalaudit-0.4.0}/examples/.gitkeep +0 -0
- {evalaudit-0.3.0 → evalaudit-0.4.0}/examples/interval_method_study.py +0 -0
- {evalaudit-0.3.0 → evalaudit-0.4.0}/examples/pairwise_cluster_study.py +0 -0
- {evalaudit-0.3.0 → evalaudit-0.4.0}/tests/__init__.py +0 -0
- {evalaudit-0.3.0 → evalaudit-0.4.0}/tests/test_confidence.py +0 -0
- {evalaudit-0.3.0 → evalaudit-0.4.0}/tests/test_readme.py +0 -0
- {evalaudit-0.3.0 → evalaudit-0.4.0}/tests/test_version.py +0 -0
|
@@ -0,0 +1,637 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Every change to evalaudit that a caller can see is recorded here. The format
|
|
4
|
+
follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the
|
|
5
|
+
version numbers follow [semantic versioning](https://semver.org/). Before 1.0
|
|
6
|
+
a minor version can break things, and 0.3.0 does.
|
|
7
|
+
|
|
8
|
+
An entry marked **Breaking** changes what a call that worked on the previous
|
|
9
|
+
release returns, raises or prints. The mark goes on the entry wherever it
|
|
10
|
+
sits, under Changed, Fixed or Removed.
|
|
11
|
+
|
|
12
|
+
0.3.0 is the first release with a tag. The entries below it were
|
|
13
|
+
reconstructed after the fact. Their dates are PyPI's upload dates, and their
|
|
14
|
+
contents were checked against the published wheels and the commit each wheel
|
|
15
|
+
matches.
|
|
16
|
+
|
|
17
|
+
## [Unreleased]
|
|
18
|
+
|
|
19
|
+
Everything here is headed for 0.4.0, and nearly all of it changes what a
|
|
20
|
+
summary or a report prints. One rule is behind it. A result that does not
|
|
21
|
+
clear its threshold has failed to show something, and it has not shown the
|
|
22
|
+
opposite. Summaries that described such a result as if the opposite were
|
|
23
|
+
shown, and verdicts decided on a point estimate where an interval existed,
|
|
24
|
+
now say what the data did and did not show. Several `audit` findings change
|
|
25
|
+
severity on data you have already run. Each breaking entry says what it
|
|
26
|
+
was, what it is now and what to do about it. Every entry was checked by
|
|
27
|
+
running the same calls against 0.3.0 from PyPI and against this tree.
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
|
|
31
|
+
- **Breaking.** `audit` reads rater agreement and judge agreement off the
|
|
32
|
+
interval on alpha. An interval wholly above the threshold keeps "Rater
|
|
33
|
+
agreement holds up" or "The judge tracks the humans", and one wholly below
|
|
34
|
+
it keeps the "below the working threshold" title. An interval running both
|
|
35
|
+
sides of the threshold, or no interval at all, is now a `warning` titled
|
|
36
|
+
"The data cannot show that rater agreement clears the working threshold"
|
|
37
|
+
or "The data cannot show that the judge clears the working threshold".
|
|
38
|
+
0.3.0 decided on the point estimate. Ratings with alpha 0.730 and an
|
|
39
|
+
interval of 0.466 to 0.933 came back `info` as "Rater agreement holds up",
|
|
40
|
+
and so did any ratings audited with `n_boot=0`. Judge labels with alpha
|
|
41
|
+
0.581 and an interval of 0.467 to 0.691 came back "Judge-human agreement
|
|
42
|
+
is below the working threshold". Rerun any audit you have sent. A finding
|
|
43
|
+
that moved from `info` to `warning` also changes the report's verdict.
|
|
44
|
+
|
|
45
|
+
- **Breaking.** Without an `effect_of_interest`, `audit` no longer sizes
|
|
46
|
+
power on the margin it measured. 0.3.0 made the observed margin the effect
|
|
47
|
+
at issue, as in "The effect at issue is 5.0 points, the margin this eval
|
|
48
|
+
reports." Power computed on an observed effect is a monotone function of
|
|
49
|
+
the p-value, so on a margin whose interval includes zero the finding came
|
|
50
|
+
out `critical` almost every time and repeated the comparison. The finding
|
|
51
|
+
now reports the design's reach, the smallest difference the eval could
|
|
52
|
+
find at the configured power, and makes no claim about the margin. It is
|
|
53
|
+
a `warning` titled "No effect of interest was stated, so this reports the
|
|
54
|
+
eval's reach", because without a stated effect the audit does not know
|
|
55
|
+
what size of difference matters. Its lead says "This reports what the
|
|
56
|
+
design could find and makes no claim about the margin it measured." On 400
|
|
57
|
+
paired items with a 5.0 point margin and an interval of 1.1% to 9.0%,
|
|
58
|
+
0.3.0 opened the report with a `critical` power finding and the verdict
|
|
59
|
+
said the conclusion did not hold. Two systems with a margin of exactly
|
|
60
|
+
zero, which 0.3.0 skipped, get the same warning.
|
|
61
|
+
|
|
62
|
+
With one system and no stated effect the check is still skipped, and its
|
|
63
|
+
reason no longer offers the observed margin as a stand-in. It read
|
|
64
|
+
"Nothing to size the eval against. Pass effect_of_interest in the config,
|
|
65
|
+
or scores for two systems so the observed margin can stand in for it."
|
|
66
|
+
and now reads "No effect of interest was stated and there is no comparison
|
|
67
|
+
whose reach could be reported. Pass effect_of_interest in the config, or
|
|
68
|
+
scores for two systems."
|
|
69
|
+
|
|
70
|
+
An audit of two pass-rate systems with no stated effect now always
|
|
71
|
+
carries this warning, so its report never comes back with no warnings.
|
|
72
|
+
Set `effect_of_interest` to the difference the decision turns on.
|
|
73
|
+
|
|
74
|
+
- **Breaking.** With an `effect_of_interest` stated, `audit` puts a power
|
|
75
|
+
finding at `info` in two cases where 0.3.0 made it `critical`, because the
|
|
76
|
+
margin's interval already answers the question power asks.
|
|
77
|
+
|
|
78
|
+
- The margin's interval clears zero. The finding is titled "The margin is
|
|
79
|
+
established, and a tighter estimate would take more items". 0.3.0
|
|
80
|
+
titled it "This eval could not have detected the effect at issue".
|
|
81
|
+
- The margin's interval includes zero and stops short of the stated
|
|
82
|
+
effect in both directions. The finding is titled "The interval on the
|
|
83
|
+
margin rules out the effect at issue".
|
|
84
|
+
|
|
85
|
+
Rerun any audit whose report carried a power finding.
|
|
86
|
+
|
|
87
|
+
- **Breaking.** With an `effect_of_interest` stated, `audit` rewords the
|
|
88
|
+
power finding on a margin whose interval includes zero. Its title is now
|
|
89
|
+
"This eval had under 80% power for the effect at issue", with the
|
|
90
|
+
percentage taken from `power`, because a design
|
|
91
|
+
short of that power can still find the effect, only less often. Its action
|
|
92
|
+
no longer says "No conclusion about an effect this size can be drawn from
|
|
93
|
+
this data, in either direction. A null result here says the eval was too
|
|
94
|
+
small and says nothing about the systems." It reads the margin's interval
|
|
95
|
+
one side at a time and says one of three things. Either "The interval on
|
|
96
|
+
the margin runs past an effect this size in both directions, so the data
|
|
97
|
+
cannot show an effect this size and cannot rule one out.", or "The
|
|
98
|
+
interval on the margin rules out old ahead by this much, and it cannot
|
|
99
|
+
rule out new ahead by this much." with your system names, or for a single
|
|
100
|
+
system "No margin was measured here, so there is no interval to read
|
|
101
|
+
against an effect this size." Anything matching on the old title or action
|
|
102
|
+
will stop matching.
|
|
103
|
+
|
|
104
|
+
- **Breaking.** `AuditReport.summary()` rewords its verdict, which is the
|
|
105
|
+
first line of every report.
|
|
106
|
+
|
|
107
|
+
- With critical findings, "the conclusion this data is being asked to
|
|
108
|
+
support does not hold as stated." is now "this data cannot support the
|
|
109
|
+
conclusion as stated. That does not mean the conclusion is wrong."
|
|
110
|
+
- With warnings and no criticals, "The result stands and the design
|
|
111
|
+
weakens it, so report it with what the warning say attached." is now
|
|
112
|
+
"The checks that ran did not find a problem that leaves the conclusion
|
|
113
|
+
unsupported. That does not mean the eval is sound. Report the result
|
|
114
|
+
with what the warning says attached."
|
|
115
|
+
- With neither, "All 4 checks that ran came back clean, so the eval holds
|
|
116
|
+
up on everything this report could test." is now "The 3 checks that ran
|
|
117
|
+
did not find a problem in what they could test. That does not mean the
|
|
118
|
+
eval is sound." The number changed too. 0.3.0 counted findings, and the
|
|
119
|
+
score check gives one finding per system, so two systems made three
|
|
120
|
+
checks read as four. A single check reads "The one check that ran", and
|
|
121
|
+
a report where nothing could run reads "No check could run, so this
|
|
122
|
+
report has tested nothing."
|
|
123
|
+
|
|
124
|
+
Anything matching on the old verdicts will stop matching. The severity
|
|
125
|
+
counts are unchanged by this entry.
|
|
126
|
+
|
|
127
|
+
- **Breaking.** `audit` rewords several titles and actions.
|
|
128
|
+
|
|
129
|
+
- "No position effect in the pairwise judgements" is now "The data cannot
|
|
130
|
+
show a position effect in the pairwise judgements". Its action opens
|
|
131
|
+
"The data has not cleared the judge of position bias." where it opened
|
|
132
|
+
"Nothing to do here."
|
|
133
|
+
- "No length effect in the judge's choices" is now "The data cannot show
|
|
134
|
+
a length effect in the judge's choices". Its action "Nothing to do
|
|
135
|
+
here." is now "The data has not cleared the judge of rewarding length."
|
|
136
|
+
- An alpha that does not exist is titled "Rater agreement is undefined on
|
|
137
|
+
this data" or "Judge-human agreement is undefined on this data", and the
|
|
138
|
+
lead ends "and this data gives no alpha to hold against it." 0.3.0
|
|
139
|
+
titled it "Rater agreement is below the working threshold" or
|
|
140
|
+
"Judge-human agreement is below the working threshold", and said the
|
|
141
|
+
grades "reproduce less well than the 0.667".
|
|
142
|
+
- The action on a margin that clears zero said "The lower bound is the
|
|
143
|
+
size of the win the data actually supports." When the second system
|
|
144
|
+
leads, the lower bound is the far end of the interval. It now says "The
|
|
145
|
+
end of the interval nearer zero is the smallest margin this data
|
|
146
|
+
supports."
|
|
147
|
+
- The length lead "Two models run here and they point opposite ways." now
|
|
148
|
+
also needs the preference fit's interval to clear zero. 0.3.0 printed it
|
|
149
|
+
off the sign of a preference coefficient whose interval ran over zero,
|
|
150
|
+
and said the judge "picks the longer answer more often" beside an odds
|
|
151
|
+
ratio of 0.94 to 1.40. Such data now gets the plain lead for the
|
|
152
|
+
direction the finding reports.
|
|
153
|
+
|
|
154
|
+
- **Breaking.** Module summaries put every result that falls short of its
|
|
155
|
+
threshold in one form, "so the data cannot show that" followed by "That
|
|
156
|
+
does not mean".
|
|
157
|
+
|
|
158
|
+
- `ComparisonResult.summary()`. "The interval crosses zero, so the data
|
|
159
|
+
cannot confirm that either system is better." is now "The interval
|
|
160
|
+
includes zero, so the data cannot show that either system is better.
|
|
161
|
+
That does not mean the two are level."
|
|
162
|
+
- `PositionBias.summary()`, randomised design. "The interval covers 50%,
|
|
163
|
+
so the data cannot show that position moved the judge." is now "The
|
|
164
|
+
interval includes 50%, so the data cannot show that position moved the
|
|
165
|
+
judge. That does not mean the judge ignores position."
|
|
166
|
+
- `PositionBias.summary()`, both orders. "The flips split evenly across
|
|
167
|
+
the two positions, so this is an unsteady judge rather than a
|
|
168
|
+
position-biased one." is now "That share is not clear of 50% at this
|
|
169
|
+
many flips, so the data cannot show that the flips have a direction.
|
|
170
|
+
That does not mean the judge is free of position bias." 0.3.0 printed
|
|
171
|
+
the old sentence at 7 flips of 9 toward the answer shown first.
|
|
172
|
+
- `LengthBias.summary()`. "The interval covers no effect, so the data
|
|
173
|
+
cannot show that length moved the judge." is now "The interval includes
|
|
174
|
+
an odds ratio of 1, so the data cannot show that length moved the
|
|
175
|
+
judge. That does not mean length plays no part in its choices." For the
|
|
176
|
+
disagreement fit, "That interval covers no effect, so the judge does
|
|
177
|
+
not depart from the humans in the direction of length." is now "That
|
|
178
|
+
interval includes an odds ratio of 1, so the data cannot show that the
|
|
179
|
+
judge breaks with the humans toward longer or shorter answers. That does
|
|
180
|
+
not mean it follows them on length."
|
|
181
|
+
- `AgreementResult.summary()`. "so the data cannot distinguish the raters"
|
|
182
|
+
is now "so the data cannot show that any one rater is pulling alpha
|
|
183
|
+
down" where every leave-one-out alpha is undefined. Where there are
|
|
184
|
+
leave-one-out figures the summary no longer judges the raters at all,
|
|
185
|
+
as the entry on rater dropout below says.
|
|
186
|
+
- `JudgeValidation.summary()`. "the data cannot single out a slice" is now
|
|
187
|
+
"the data cannot show that the judge does worse on any one slice".
|
|
188
|
+
Where the intervals overlap it adds "That does not mean it does equally
|
|
189
|
+
well on all of them."
|
|
190
|
+
|
|
191
|
+
Anything matching on the old sentences will stop matching.
|
|
192
|
+
|
|
193
|
+
- **Breaking.** `AgreementResult.summary()` and `JudgeValidation.summary()`
|
|
194
|
+
name one of Krippendorff's bands only when the whole interval sits in it.
|
|
195
|
+
0.3.0 named the band from the point estimate, with "That is at or above
|
|
196
|
+
0.800, the conventional bar for treating coded data as reliable.", "That
|
|
197
|
+
sits between 0.667 and 0.800, which supports tentative conclusions and no
|
|
198
|
+
firm ones." and "That is below 0.667, the conventional floor for drawing
|
|
199
|
+
any conclusion from coded data." These now read "The whole interval sits
|
|
200
|
+
above 0.800", "The whole interval sits between 0.667 and 0.800" and "The
|
|
201
|
+
whole interval sits below 0.667". An interval running over 0.667 reads
|
|
202
|
+
"The interval runs both sides of 0.667, the conventional floor for drawing
|
|
203
|
+
any conclusion from coded data, so the data cannot show that rater
|
|
204
|
+
agreement clears it. That does not mean it falls short of it." In
|
|
205
|
+
`JudgeValidation` the subject is "the judge's agreement with the humans".
|
|
206
|
+
An interval that clears 0.667 and runs over 0.800 gets the same form at
|
|
207
|
+
0.800, and a summary with no interval names no band. Judge labels with
|
|
208
|
+
alpha 0.801 and an interval of 0.601 to 0.951 printed "That is at or
|
|
209
|
+
above 0.800" in 0.3.0. Anything matching on the old sentences will stop
|
|
210
|
+
matching.
|
|
211
|
+
|
|
212
|
+
- **Breaking.** `AgreementResult.summary()` no longer names a rater. 0.3.0
|
|
213
|
+
named one when dropping them raised alpha by more than half the width of
|
|
214
|
+
the interval on alpha. That compares the shift with the sampling error on
|
|
215
|
+
alpha, and the shift has a sampling error of its own that can be much
|
|
216
|
+
larger. Across simulated evals with three raters who differed only by
|
|
217
|
+
chance, the rule named a rater in 4.2% of 500 when everyone graded every
|
|
218
|
+
item. When the third rater graded a fifth of the items it named one in
|
|
219
|
+
32.0% of 500, always one of the two who graded everything. In one of those
|
|
220
|
+
evals 0.3.0 printed "Dropping r2 raises alpha to 0.878, a shift of 0.326
|
|
221
|
+
against a sampling error of 0.200." about a rater who graded all 60 items.
|
|
222
|
+
The same rule caught a rater wrong three times as often as the others in
|
|
223
|
+
72.4% of 500.
|
|
224
|
+
|
|
225
|
+
The summary now lists alpha with each rater left out, as in "Leaving one
|
|
226
|
+
rater out at a time gives alpha of 0.878 without r2 (+0.326), 0.524
|
|
227
|
+
without r3 (-0.028), and 0.483 without r1 (-0.069).", and says "The
|
|
228
|
+
package does not judge whether any of these shifts is larger than noise,
|
|
229
|
+
so it names no rater. A rater near the top of this list is a lead to check
|
|
230
|
+
rather than a finding." It lists five raters at most and points to
|
|
231
|
+
`rater_dropout` for the rest. `top_dropout_rater` always returns None.
|
|
232
|
+
`dropout_is_distinguishable` still computes the old rule, its docstring
|
|
233
|
+
says why the rule was withdrawn, and nothing in the package reads it.
|
|
234
|
+
|
|
235
|
+
The `audit` agreement finding carries the new sentence. Its severity never
|
|
236
|
+
came from this rule, so no finding changes severity. If you acted on a
|
|
237
|
+
rater a summary named, check that rater by hand.
|
|
238
|
+
|
|
239
|
+
- **Breaking.** `PositionBias` puts the Clopper-Pearson interval, the exact
|
|
240
|
+
binomial interval, on the rate it tests against a half, in both designs,
|
|
241
|
+
and decides on it. The exact binomial p-value printed beside it comes from
|
|
242
|
+
the same test, so the two cannot disagree about 50%. 0.3.0 used a Wilson
|
|
243
|
+
interval in the randomised design. Wilson and the exact test disagree at
|
|
244
|
+
50% in 188 of 20,300 (n, k) cells up to 200 judgements, and in every one
|
|
245
|
+
the Wilson interval clears 50% while the p-value does not. At 11 of 14 in
|
|
246
|
+
the randomised design 0.3.0 printed "(95% CI: 52.4% to 92.4%, exact
|
|
247
|
+
binomial p=0.0574)" and then "The interval clears 50%, so the judge
|
|
248
|
+
favours whichever output it sees first." It now prints "(95% CI: 49.2% to
|
|
249
|
+
95.3%, exact binomial p=0.0574)" and "The interval includes 50%, so the
|
|
250
|
+
data cannot show that position moved the judge." Every randomised interval
|
|
251
|
+
moves, and a randomised verdict flips wherever the two used to disagree.
|
|
252
|
+
|
|
253
|
+
In the both-orders design 0.3.0 printed the share of flips with a bare
|
|
254
|
+
p-value, "(77.8%, exact binomial p=0.1797).", and decided on that p-value.
|
|
255
|
+
It now prints "(77.8%, 95% CI: 40.0% to 97.2%, exact binomial p=0.1797)."
|
|
256
|
+
and decides on the interval, which gives the same answer as the p-value in
|
|
257
|
+
every case. The consistency rate has no test beside it and keeps its
|
|
258
|
+
Wilson interval. Rerun any position check near the line.
|
|
259
|
+
|
|
260
|
+
### Added
|
|
261
|
+
|
|
262
|
+
- `BTResult.n_missing_item_ids`, the number of comparisons with no item id.
|
|
263
|
+
It is the last field of the dataclass and defaults to 0, so building a
|
|
264
|
+
`BTResult` by position with 0.3.0's fields still works. `to_elo` carries
|
|
265
|
+
it across.
|
|
266
|
+
- `PositionBias.position_a_ci_low` and `PositionBias.position_a_ci_high`,
|
|
267
|
+
the Clopper-Pearson interval on `position_a_rate`. In the randomised
|
|
268
|
+
design they
|
|
269
|
+
equal `ci_low` and `ci_high`. They are the last two fields and default to
|
|
270
|
+
NaN, so building a `PositionBias` by position with 0.3.0's fields still
|
|
271
|
+
works. A both-orders result built that way has no interval, so its
|
|
272
|
+
`has_position_effect` is False.
|
|
273
|
+
|
|
274
|
+
### Fixed
|
|
275
|
+
|
|
276
|
+
- **Breaking.** `KappaResult.summary()` said "Krippendorff's alpha does not
|
|
277
|
+
have that problem and handles missing data, so prefer rater_agreement for
|
|
278
|
+
anything you report." Alpha has the problem too. Two raters who agree on
|
|
279
|
+
90 of 100 items score kappa 0.444 and alpha 0.447 when one category takes
|
|
280
|
+
90% of the ratings, and 0.800 and 0.801 when both are used equally often.
|
|
281
|
+
It now says "Krippendorff's alpha moves the same way, because it also
|
|
282
|
+
corrects for chance using how often each category is used." and gives
|
|
283
|
+
missing ratings, more than two raters and ordered scales as the reasons to
|
|
284
|
+
prefer `rater_agreement`. The `cohens_kappa` docstring made the same claim
|
|
285
|
+
and now quotes the four figures.
|
|
286
|
+
|
|
287
|
+
- **Breaking.** `ScoreCI.summary()` told the reader to "treat differences
|
|
288
|
+
smaller than that as unresolved." A paired comparison resolves
|
|
289
|
+
differences far smaller than either score's own interval. The sentence
|
|
290
|
+
now reads "To compare this score with another, read the interval on the
|
|
291
|
+
difference, which compare_paired and compare_independent report. Two
|
|
292
|
+
score intervals that overlap do not show the systems are level." The
|
|
293
|
+
`scores` module docstring made the same claim and no longer does.
|
|
294
|
+
|
|
295
|
+
- **Breaking.** `PowerResult.summary()` from `detectable_effect` said
|
|
296
|
+
"anything smaller was out of reach before the first item was graded". A
|
|
297
|
+
difference below the reach can still reach significance, only less often.
|
|
298
|
+
It now says "A smaller difference could still reach significance here,
|
|
299
|
+
with a chance below 80%." Where no difference reaches the requested power,
|
|
300
|
+
"This eval could not have found anything, whatever the two systems really
|
|
301
|
+
do." and, for independent samples, "and this eval could not have found
|
|
302
|
+
anything." are now "A null result from this eval says little about the
|
|
303
|
+
systems." The `detectable_effect` docstring said "An eval could not have
|
|
304
|
+
found anything smaller" and now says "No smaller difference reaches the
|
|
305
|
+
requested power".
|
|
306
|
+
|
|
307
|
+
- **Breaking.** `JudgeValidation.summary()` on a single item said "Every
|
|
308
|
+
label that could be compared was identical" whatever the labels were,
|
|
309
|
+
beside a plain accuracy of 0.0% when they differed, and counted "1 items".
|
|
310
|
+
It now reads "(nominal, 1 item). One item cannot carry a reliability
|
|
311
|
+
estimate, so there is no number to report and no interval around it." The
|
|
312
|
+
count of items set aside reads "1 item was set aside" where it read "1
|
|
313
|
+
items were set aside".
|
|
314
|
+
|
|
315
|
+
- **Breaking.** `BTResult.summary()` under `resample="comparisons"` said
|
|
316
|
+
"these 240 comparisons share 239 items" when one comparison had no item
|
|
317
|
+
id and no two shared anything. Sharing is now counted among the
|
|
318
|
+
comparisons that carry an id. When none share, the sentence is left out.
|
|
319
|
+
When some share and ids are missing, it reads "the 239 comparisons that
|
|
320
|
+
carry an item id share 26 items".
|
|
321
|
+
|
|
322
|
+
- The README example and the prose under it show the new wording.
|
|
323
|
+
|
|
324
|
+
### Removed
|
|
325
|
+
|
|
326
|
+
- Nothing.
|
|
327
|
+
|
|
328
|
+
### Known limitations
|
|
329
|
+
|
|
330
|
+
This rule is unchanged since 0.3.0 and is not fixed in this release. The
|
|
331
|
+
figures come from simulations run against 0.3.0 and against this tree, which
|
|
332
|
+
give the same results.
|
|
333
|
+
|
|
334
|
+
- `JudgeValidation` names a slice, and `audit` raises a critical finding on
|
|
335
|
+
it, only when the slice's own interval sits wholly below the interval on
|
|
336
|
+
the overall figure. That reads a difference off two separate intervals
|
|
337
|
+
instead of an interval on the difference, and it is conservative. With
|
|
338
|
+
five slices of 60 items that differ only by chance, it named a slice in
|
|
339
|
+
0.5% of 200 simulated evals. It misses real differences. A slice where the
|
|
340
|
+
judge flipped 25% of the labels, against 10% in the other four, was named
|
|
341
|
+
in 32.5% of 200. When the summary says the data cannot show that the
|
|
342
|
+
judge does worse on any one slice, this rule is what did not show it.
|
|
343
|
+
|
|
344
|
+
## [0.3.0] - 2026-09-10
|
|
345
|
+
|
|
346
|
+
0.3.0 changes what `bradley_terry` reports on data you have already run, and
|
|
347
|
+
it turns several calls that used to return numbers into errors. Each
|
|
348
|
+
breaking entry says what it was, what it is now and what to do about it.
|
|
349
|
+
|
|
350
|
+
### Changed
|
|
351
|
+
|
|
352
|
+
- **Breaking.** `bradley_terry` reads separability off the interval on the
|
|
353
|
+
gap between two ratings. Before, a pair was separable when its two rating
|
|
354
|
+
intervals did not overlap. Now a pair is separable when the percentile
|
|
355
|
+
interval on the difference between the two ratings excludes zero. Two
|
|
356
|
+
rating intervals can overlap while the gap between them is well measured,
|
|
357
|
+
because both ratings carry the error of the field average they are
|
|
358
|
+
measured against and that error cancels in the gap. So the old test
|
|
359
|
+
undercounted the pairs the data orders, and the pairs it left out were
|
|
360
|
+
never shown to be unordered. There is no option to bring the old rule
|
|
361
|
+
back. `n_separable` and `separable_pairs` can change on data you have
|
|
362
|
+
already run. On the README example they go from 5 of 15 pairs to 7. On
|
|
363
|
+
twelve simulated leaderboards where every item carried one comparison,
|
|
364
|
+
the count went up on five and stayed the same on seven. Nothing changes
|
|
365
|
+
in your code. Rerun, and replace any separability count you have
|
|
366
|
+
published.
|
|
367
|
+
|
|
368
|
+
- **Breaking.** `separable_pairs` has two new columns, `ci_low` and
|
|
369
|
+
`ci_high`, the interval on `difference`. They sit between `difference` and
|
|
370
|
+
`p_a_beats_b`, so code that reads columns by position will read the wrong
|
|
371
|
+
ones. Code that selects columns by name is unaffected.
|
|
372
|
+
|
|
373
|
+
- **Breaking.** `bradley_terry` resamples items by default. Before, the
|
|
374
|
+
bootstrap drew single comparisons, which treats judgements of the same
|
|
375
|
+
prompt as independent. Now it draws item ids with replacement and takes
|
|
376
|
+
every comparison made on each drawn item.
|
|
377
|
+
|
|
378
|
+
Where every item carries one comparison the default draws the same
|
|
379
|
+
resamples from the same seed as 0.2.1, and the ratings, their intervals
|
|
380
|
+
and the win matrix come out identical. Separability can still change,
|
|
381
|
+
for the reason in the entry above.
|
|
382
|
+
|
|
383
|
+
Where items carry several comparisons the intervals widen and fewer pairs
|
|
384
|
+
may separate. On a simulated board of 60 items with 20 comparisons each,
|
|
385
|
+
the rating intervals came out 1.1 to 1.5 times as wide as 0.2.1's. On
|
|
386
|
+
simulated data shaped like MT-Bench's human judgements, the rating
|
|
387
|
+
intervals 0.2.1 reported covered 88% of the time at a nominal 95% once
|
|
388
|
+
prompts shifted model strength by a spread of 0.5 on the log-odds scale,
|
|
389
|
+
and 79% at a spread of 1.0. `examples/pairwise_cluster_study.py` has the
|
|
390
|
+
table for 0.3.0.
|
|
391
|
+
|
|
392
|
+
To get the ratings and rating intervals an earlier version gave on the
|
|
393
|
+
same data and seed, pass `resample="comparisons"`. They come out
|
|
394
|
+
identical to 0.2.1's. `separable_pairs`, `n_separable` and the summary
|
|
395
|
+
follow the 0.3.0 rules, so those can differ.
|
|
396
|
+
|
|
397
|
+
- **Breaking.** `bradley_terry` raises `ValueError` in two cases that 0.2.1
|
|
398
|
+
accepted. Both apply only when `n_boot` is above zero and `resample` is
|
|
399
|
+
left at its default of `"items"`.
|
|
400
|
+
|
|
401
|
+
- Some row has no `item_id`. The item bootstrap has to know which item
|
|
402
|
+
each comparison belongs to.
|
|
403
|
+
- Every row has the same `item_id`, an empty string included. With one
|
|
404
|
+
item, every resample is the full data and every interval would have
|
|
405
|
+
width zero.
|
|
406
|
+
|
|
407
|
+
This is the change most likely to break a working script, so here is what
|
|
408
|
+
to do. Earlier versions required `item_id` and read it for nothing but a
|
|
409
|
+
count, so a constant, a blank or the row number got past the check and
|
|
410
|
+
changed nothing. Look at what yours holds.
|
|
411
|
+
|
|
412
|
+
- It names the prompt each comparison was made on. Fill in any gaps and
|
|
413
|
+
change nothing else. Your intervals now account for comparisons sharing
|
|
414
|
+
a prompt, which is the reason for the change.
|
|
415
|
+
- It is the row number, or anything else unique per row. Nothing raises,
|
|
416
|
+
and the ratings and their intervals come out as they did in 0.2.1.
|
|
417
|
+
- It is a constant or a blank. Record the prompt if you can. If you
|
|
418
|
+
cannot, pass `resample="comparisons"` to keep the intervals you had.
|
|
419
|
+
They come out identical to 0.2.1's on the same seed. They treat every
|
|
420
|
+
judgement as independent and run narrow wherever prompts carry several.
|
|
421
|
+
The summary says so when the column holds a constant or an empty
|
|
422
|
+
string. It says nothing when every `item_id` is missing, since then
|
|
423
|
+
nothing records which comparisons share a prompt.
|
|
424
|
+
|
|
425
|
+
With `n_boot=0` no resampling happens and any `item_id` is accepted.
|
|
426
|
+
|
|
427
|
+
- **Breaking.** `score_ci(method="t")` raises `ValueError` on three kinds of
|
|
428
|
+
input it used to return numbers for. What to do depends on the input.
|
|
429
|
+
|
|
430
|
+
- 0/1 data, including all passes, all fails and a single pass or fail.
|
|
431
|
+
The interval could run past 100%, as 49 passes in 50 did at 94.0% to
|
|
432
|
+
102.0%, come back with width zero on all passes or all fails, or come
|
|
433
|
+
back as NaN on a single pass. Use `method="wilson"`, which
|
|
434
|
+
`method="auto"` already picks for 0/1 data and which works on a single
|
|
435
|
+
item.
|
|
436
|
+
- A single score that is not 0 or 1. It came back as NaN bounds behind two
|
|
437
|
+
RuntimeWarnings. One score has no spread, and the bootstrap returns
|
|
438
|
+
width zero on it too. Score more items.
|
|
439
|
+
- Continuous scores that are all the same. The interval came back with
|
|
440
|
+
width zero, which claims the observations fixed the mean exactly. Check
|
|
441
|
+
that the scorer is not returning a constant.
|
|
442
|
+
|
|
443
|
+
- **Breaking.** `score_ci(method="wilson")` raises `ValueError` on scores
|
|
444
|
+
that are not 0 or 1. Wilson counts passes, and on other scores it took the
|
|
445
|
+
count by truncating the sum of the scores. Ten scores of 0.99 printed a
|
|
446
|
+
mean of 0.990 beside an interval of 0.596 to 0.982. For scores that vary,
|
|
447
|
+
use `method="bootstrap"`, the interval on a mean, which `method="auto"`
|
|
448
|
+
already picks. Scores that are all the same, like that example, get width
|
|
449
|
+
zero from the bootstrap too, and 0.3.0 does not refuse that.
|
|
450
|
+
|
|
451
|
+
- **Breaking.** `score_ci`, `compare_paired` and `compare_independent`
|
|
452
|
+
raise `ValueError` for a confidence level that is not strictly between 0
|
|
453
|
+
and 1, with the message `confidence must be in (0, 1), got ...` that
|
|
454
|
+
`bradley_terry`, `rater_agreement`, `judge_validation` and `audit` already
|
|
455
|
+
used. Before, what came back at `confidence=1.5` depended on the method.
|
|
456
|
+
The bootstrap in all three raised from inside numpy. Wilson and both t
|
|
457
|
+
intervals returned NaN bounds. The two score intervals returned bounds
|
|
458
|
+
clipped to -100% and 100%. The signed-rank interval in `compare_paired`
|
|
459
|
+
returned an ordinary-looking interval under a "150% CI" label, which is
|
|
460
|
+
the case nothing would have flagged. Pass a level strictly between 0 and
|
|
461
|
+
1.
|
|
462
|
+
|
|
463
|
+
- **Breaking.** Several summary strings are reworded, so any test or
|
|
464
|
+
pipeline that matches on them will fail.
|
|
465
|
+
|
|
466
|
+
- `BTResult.summary()` defines separable as "the interval on the gap
|
|
467
|
+
between the two ratings excludes zero". For pairs that do not separate
|
|
468
|
+
it says the data does not establish an order for them, that this does
|
|
469
|
+
not mean the models are level, and that more comparisons could separate
|
|
470
|
+
them. The phrases "meaning their intervals do not overlap", "cannot be
|
|
471
|
+
ordered", "an order the data does not carry" and "a ranking of noise"
|
|
472
|
+
are gone.
|
|
473
|
+
- `BTResult.summary()` adds a sentence when `resample="comparisons"` was
|
|
474
|
+
used on data where items carry several comparisons.
|
|
475
|
+
- `AgreementResult.summary()` for a scale nobody varied now reads "This
|
|
476
|
+
comes from a scale nobody varied. It is not perfect agreement." where it
|
|
477
|
+
read "That is not perfect agreement, it is a scale nobody varied."
|
|
478
|
+
- `JudgeValidation.summary()` for a rubric with one label now reads "This
|
|
479
|
+
comes from a rubric with one label in it. It is not perfect agreement."
|
|
480
|
+
where it read "That is not perfect agreement, it is a rubric with one
|
|
481
|
+
label in it."
|
|
482
|
+
|
|
483
|
+
- The Development Status classifier moved from Alpha to Beta.
|
|
484
|
+
|
|
485
|
+
### Added
|
|
486
|
+
|
|
487
|
+
- `bradley_terry(..., resample="items")`, with `"comparisons"` as the other
|
|
488
|
+
choice.
|
|
489
|
+
- `BTResult.pairs`, one row per pair of models with the gap, the interval on
|
|
490
|
+
the gap and a `separable` column. `separable_pairs` is its separable rows.
|
|
491
|
+
- `BTResult.resample`, recording which unit the bootstrap drew. It and
|
|
492
|
+
`pairs` are the last two fields of the dataclass, so building a
|
|
493
|
+
`BTResult` by position with 0.2.1's fields still works.
|
|
494
|
+
- `to_elo` stretches the gap intervals with the gaps and carries `pairs` and
|
|
495
|
+
`resample` across.
|
|
496
|
+
- `examples/pairwise_cluster_study.py`, in the source distribution, which
|
|
497
|
+
measures how narrow the comparison bootstrap runs on MT-Bench shaped data.
|
|
498
|
+
|
|
499
|
+
### Fixed
|
|
500
|
+
|
|
501
|
+
- The `scores` module docstring said the interval at n=50 is roughly plus or
|
|
502
|
+
minus 10 points. It is about 10 at an 85% pass rate and about 13 at 50%.
|
|
503
|
+
- The README said every interval in the package is tested by simulation.
|
|
504
|
+
Several were not. It now says which intervals are tested by simulation,
|
|
505
|
+
which are checked against a reference implementation instead, and which
|
|
506
|
+
one is checked by neither.
|
|
507
|
+
- The README said `audit` runs five checks. It runs seven, drawn from five
|
|
508
|
+
modules.
|
|
509
|
+
|
|
510
|
+
### Removed
|
|
511
|
+
|
|
512
|
+
- `AUDIT.md`, an internal review of the package, is no longer tracked, so
|
|
513
|
+
it is not in the source distribution.
|
|
514
|
+
|
|
515
|
+
## [0.2.1] - 2026-09-08
|
|
516
|
+
|
|
517
|
+
Reconstructed after the fact. The published files match commit `809a650`.
|
|
518
|
+
|
|
519
|
+
### Changed
|
|
520
|
+
|
|
521
|
+
- `__version__` is read from the installed package metadata. 0.0.1 and
|
|
522
|
+
0.2.0 both reported `__version__` as 0.1.0, because a literal in
|
|
523
|
+
`__init__.py` had drifted from `pyproject.toml`.
|
|
524
|
+
|
|
525
|
+
### Added
|
|
526
|
+
|
|
527
|
+
- `AUDIT.md`, an internal review of the package, in the source
|
|
528
|
+
distribution.
|
|
529
|
+
|
|
530
|
+
### Fixed
|
|
531
|
+
|
|
532
|
+
- **Breaking.** The length-bias check read every coefficient as a
|
|
533
|
+
preference for long answers. In 0.2.0 a judge that preferred shorter
|
|
534
|
+
answers got the `audit` title "The judge is pulled by how long the answer
|
|
535
|
+
is", and `LengthBias.summary()` printed "A positive coefficient here is
|
|
536
|
+
not bias on its own" beside a negative coefficient. The `audit` finding
|
|
537
|
+
now takes its title, lead, action and verdict from the fit that decides,
|
|
538
|
+
with its own lead for when the two fits point opposite ways, and
|
|
539
|
+
`LengthBias.summary()` has its own sentence for a negative coefficient.
|
|
540
|
+
Anything matching on the old title or sentence will stop matching.
|
|
541
|
+
|
|
542
|
+
### Removed
|
|
543
|
+
|
|
544
|
+
- Nothing.
|
|
545
|
+
|
|
546
|
+
## [0.2.0] - 2026-09-07
|
|
547
|
+
|
|
548
|
+
Reconstructed after the fact. The wheel matches commit `242e354`. It was
|
|
549
|
+
uploaded twelve seconds before that commit was made, so it was built from
|
|
550
|
+
the working tree the commit then recorded.
|
|
551
|
+
|
|
552
|
+
### Changed
|
|
553
|
+
|
|
554
|
+
- The project URLs point at github.com/mokayahezron/evalaudit. 0.1.0 pointed
|
|
555
|
+
at github.com/ondibahezron-glitch/evalaudit.
|
|
556
|
+
- `choix` is a development dependency on Python 3.10 and later, used to
|
|
557
|
+
check the Bradley-Terry fit.
|
|
558
|
+
|
|
559
|
+
### Added
|
|
560
|
+
|
|
561
|
+
- The `pairwise` module, with `bradley_terry`, `to_elo` and `BTResult`.
|
|
562
|
+
Ratings come with bootstrap intervals and a count of separable pairs.
|
|
563
|
+
Models that fall into groups that never met, and models that never lost
|
|
564
|
+
or never won, get no ratings and a summary naming them. Ties are split or
|
|
565
|
+
dropped, and `ties="davidson"` is refused by name.
|
|
566
|
+
- The README code blocks are run by the test suite and checked against the
|
|
567
|
+
output they show.
|
|
568
|
+
|
|
569
|
+
### Fixed
|
|
570
|
+
|
|
571
|
+
- Nothing.
|
|
572
|
+
|
|
573
|
+
### Removed
|
|
574
|
+
|
|
575
|
+
- Nothing.
|
|
576
|
+
|
|
577
|
+
## [0.1.0] - 2026-09-07
|
|
578
|
+
|
|
579
|
+
Reconstructed after the fact. The wheel matches commit `c1230f1`.
|
|
580
|
+
|
|
581
|
+
### Changed
|
|
582
|
+
|
|
583
|
+
- Nothing.
|
|
584
|
+
|
|
585
|
+
### Added
|
|
586
|
+
|
|
587
|
+
- `compare_paired` and `compare_independent`. McNemar with Tango's score
|
|
588
|
+
interval for paired binary data, the paired bootstrap, and the signed-rank
|
|
589
|
+
test with the Hodges-Lehmann interval. The score interval, the bootstrap
|
|
590
|
+
and Welch's t for independent samples.
|
|
591
|
+
- `rater_agreement`, Krippendorff's alpha with a bootstrap interval, an item
|
|
592
|
+
disagreement table and a rater dropout table. `cohens_kappa` and
|
|
593
|
+
`fleiss_kappa`.
|
|
594
|
+
- `judge_validation`, `position_bias` and `length_bias`.
|
|
595
|
+
- `detectable_effect` and `min_sample_size`.
|
|
596
|
+
- `audit`, which runs every check the supplied data supports and ranks the
|
|
597
|
+
findings by severity.
|
|
598
|
+
- The result types are exported from the package, `ScoreCI` among them.
|
|
599
|
+
|
|
600
|
+
### Fixed
|
|
601
|
+
|
|
602
|
+
- Nothing.
|
|
603
|
+
|
|
604
|
+
### Removed
|
|
605
|
+
|
|
606
|
+
- Nothing.
|
|
607
|
+
|
|
608
|
+
## [0.0.1] - 2026-09-04
|
|
609
|
+
|
|
610
|
+
Reconstructed after the fact. The wheel's package files match commits
|
|
611
|
+
`aa8ad97`, `8a4cab0` and `b090c66`, which do not differ in them. Its version
|
|
612
|
+
number first appears in `pyproject.toml` at `b090c66`, committed about an
|
|
613
|
+
hour after the upload. It reported `__version__` as 0.1.0.
|
|
614
|
+
|
|
615
|
+
### Changed
|
|
616
|
+
|
|
617
|
+
- Nothing.
|
|
618
|
+
|
|
619
|
+
### Added
|
|
620
|
+
|
|
621
|
+
- `score_ci`, with Wilson, bootstrap and Student-t intervals, and a default
|
|
622
|
+
that picks Wilson for 0/1 data and the bootstrap otherwise.
|
|
623
|
+
|
|
624
|
+
### Fixed
|
|
625
|
+
|
|
626
|
+
- Nothing.
|
|
627
|
+
|
|
628
|
+
### Removed
|
|
629
|
+
|
|
630
|
+
- Nothing.
|
|
631
|
+
|
|
632
|
+
[Unreleased]: https://github.com/mokayahezron/evalaudit/compare/v0.3.0...main
|
|
633
|
+
[0.3.0]: https://github.com/mokayahezron/evalaudit/compare/809a650...v0.3.0
|
|
634
|
+
[0.2.1]: https://github.com/mokayahezron/evalaudit/compare/242e354...809a650
|
|
635
|
+
[0.2.0]: https://github.com/mokayahezron/evalaudit/compare/c1230f1...242e354
|
|
636
|
+
[0.1.0]: https://github.com/mokayahezron/evalaudit/compare/b090c66...c1230f1
|
|
637
|
+
[0.0.1]: https://github.com/mokayahezron/evalaudit/tree/b090c66
|