kirad.metrics¶
kirad.metrics
¶
Binary Sn/Sp metrics with an indeterminate band, plus a DDP-safe score accumulator.
Stage: thresholds/metrics. base_models gathers val/test scores with MultiCatMetric, builds an IndetSnSpArray per binary cut, and reports AUROC and sn_eq_sp at each indeterminate budget (default 0% and 40%).
Contains various metrics used by researchers.
MultiCatMetric
¶
Bases: Metric
Accumulate parallel tensors over batches and ranks (uuids, scores, variances, labels).
Container metric to concatenate parallel lists of tensors, e.g. corresponding scores and labels. Note: base_models uses MultiCatMetric(4); uuids are uint8 tensors, padded by pad_cat.
Source code in kirad/metrics.py
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | |
is_differentiable = None
class-attribute
instance-attribute
¶
higher_is_better = None
class-attribute
instance-attribute
¶
full_state_update = False
class-attribute
instance-attribute
¶
state_names = [f'state_{i}' for i in range(num_states)]
instance-attribute
¶
__init__(num_states=1, **kwargs)
¶
Register num_states list states, reduced across ranks with pad_cat.
Create a container metric to concatenate parallel lists of tensors, e.g. corresponding scores and labels.
Arguments
num_states : number of arguments which will be passed to update on each call. The i^th arguments from all
calls to update will be concatenated along the batch dimension and the result returned as the i^th
element of the tuple returned by compute.
Source code in kirad/metrics.py
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | |
update(*values)
¶
Append one batch of num_states tensors.
Update state with data.
Args:
values: tuple num_states tensors to accumulate over batches. For fixed i, values[i] must have the
same non-batch dimensions and type in all calls to this function, but values[i] and values[j]
need not have the same dimensions or type.
Source code in kirad/metrics.py
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | |
compute()
¶
Concatenate each of the num_states tensors over all calls to update.
Returns:
| Type | Description |
|---|---|
tuple of length `num_states` whose i^th element is the concatenation of the i^th elements of all calls
|
to |
Source code in kirad/metrics.py
94 95 96 97 98 99 100 101 102 103 104 105 | |
IndetSnSpArray
dataclass
¶
Sn, Sp and indeterminate fraction for many (lower, upper) threshold pairs.
An array of metrics at different lower and upper threshold values.
Each member lower_thresh, upper_thresh, sn, sp, and indet_frac must be a numpy array, and they all must
have the same shape. Corresponding entries of these arrays specify a pair of thresholds and the metrics when a
common dataset is evaluated using those thresholds. The thresholding logic is that scores less than the lower
threshold count as negative outputs, scores greater than or equal to the upper threshold count as positive outputs,
and scores in between are indeterminate outputs.
Source code in kirad/metrics.py
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 | |
lower_thresh
instance-attribute
¶
upper_thresh
instance-attribute
¶
sn
instance-attribute
¶
sp
instance-attribute
¶
indet_frac
instance-attribute
¶
min_sn_sp
property
¶
min(Sn, Sp) per threshold pair; the quantity maximized for sn_eq_sp.
__init__(lower_thresh, upper_thresh, sn, sp, indet_frac)
¶
build(lower_thresh=None, upper_thresh=None, *, y_true, y_score, weights=None, eps=1e-08)
classmethod
¶
Sn/Sp/indet_frac for all threshold pairs (or the given ones) via histogram cumsums.
Find IndetSnSpArray values for given truth and scores as thresholds vary (à la sklearn.metrics.roc_curve).
The output object contains arrays for sn, sp, indet_frac, lower_thresh, and upper_thresh, all with the
same shape. What these arrays contain and what their common shape is depends on the input as follows.
If both lower_thresh and upper_thresh are provided, they must have the same shape and this method computes metrics at the pairs given by corresponding entries in these arrays. The common output shape will be the same as this common input shape.
If only one set of thresholds is provided, this method computes metrics at all sorted pairs of these thresholds (along with +/- inf). If neither is provided, sort scores and allow thresholds between each pair (along with +/- inf). In both of these cases, the common output shape is a 1-d vector of length equal to the number of such pairs.
Source code in kirad/metrics.py
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 | |
eval(*, y_true, y_score, weights=None)
¶
Evaluate the given data on the thresholds of self (e.g. val thresholds on test).
Source code in kirad/metrics.py
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 | |
__getitem__(item)
¶
Extract a subarray with numpy-style indexing.
Source code in kirad/metrics.py
281 282 283 284 285 286 287 288 289 | |
roc_curve(indet_budget=0.0)
¶
Pareto ROC curve of (Sn, Sp) using only pairs with indet_frac <= indet_budget.
Compute ROC curve with indeterminate budget, sorted by increasing sn and decreasing sp.
Restrict self to Pareto-optimal pairs (sn, sp) for which indet_frac <= indet_budget. Other points are worse
than the points on the curve in the sense of having worse Sn, worse Sp, or not meeting the indeterminate budget.
Source code in kirad/metrics.py
291 292 293 294 295 296 297 298 299 300 301 302 303 | |
sn_eq_sp_graph()
¶
Best min(Sn, Sp) per indeterminate fraction; these thresholds are saved in the ckpt.
Compute sn=sp as a function of indet_frac, returning both sorted in increasing order.
Method: restrict to Pareto-optimal pairs (s, indet_frac) where s = min(sn, sp).
Pareto-optimality means that if (s, indet_frac) is in the output, there is no point (sn', sp', indet_frac') in
the input with indet_frac' <= indet_frac and sn', sp' > s. In other words, s is the maximum value such that
the quadrant { sn, sp >= s} intersects self.roc_curve(indet_frac). This maximum occurs where the ROC curve
intersects the diagonal, up to an error bounded by the distance between points on the ROC curve.
Source code in kirad/metrics.py
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 | |
IndetSnSpTensorModule
¶
Bases: Module
Buffers holding an IndetSnSpArray (val sn_eq_sp thresholds) in the checkpoint.
A torch container for the contents of an IndetSnSpArray to be saved along with a model's state_dict.
Source code in kirad/metrics.py
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 | |
__init__()
¶
One empty buffer per IndetSnSpArray field.
Source code in kirad/metrics.py
327 328 329 330 331 | |
update(array, device)
¶
Update the stored values to those given in the array.
Source code in kirad/metrics.py
333 334 335 336 | |
numpy()
¶
Return an IndetSnSpArray with values taken from the stored tensors.
Source code in kirad/metrics.py
338 339 340 341 342 | |
IndetRocCurve
dataclass
¶
Bases: IndetSnSpArray
ROC curve (Pareto Sn/Sp points) within an indeterminate budget, with thresholds.
Sn, Sp achievable within some indeterminate budget and associated lower and upper thresholds.
sn is assumed to be sorted in increasing order and sp decreasing.
Source code in kirad/metrics.py
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 | |
sn_eq_sp()
¶
Locate the point on the ROC curve closest to the diagonal (max min(Sn, Sp)).
Source code in kirad/metrics.py
354 355 356 | |
auc()
¶
Compute the area under the ROC curve.
Source code in kirad/metrics.py
358 359 360 361 362 | |
build(thresh=None, *, y_true, y_score, weights=None)
classmethod
¶
Plain ROC curve (no indeterminate band) in O(n log n).
Build an indeterminate=0 ROC curve in n log n time (vs n**2 for IndetSnSpArray.build().roc_curve()).
Source code in kirad/metrics.py
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 | |
IndetSnEqSpGraph
dataclass
¶
Bases: IndetSnSpArray
Best Sn=Sp for each indeterminate budget, with its lower/upper thresholds.
Sn=Sp achievable as a function of indeterminate budget and associated lower and upper thresholds.
Both min(self.sn, self.sp) and self.indet_frac are assumed to be sorted in non-decreasing order.
Source code in kirad/metrics.py
392 393 394 395 396 397 398 399 400 401 402 403 | |
at_budget(indet_budget=0.0)
¶
Locate the best point on the graph within the given budget.
Source code in kirad/metrics.py
401 402 403 | |
pad_cat(tensors)
¶
Zero-pad non-batch dims to the largest shape, then concat on dim 0 (DDP reduce).
Source code in kirad/metrics.py
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | |
running_argmax_indices(a)
¶
Return indices of a where the value is larger than all previous values.
running_argmax_indices([1, 0, 3, 4, 4, 2, 5, 7, 1]) array([0, 2, 3, 6, 7])
Source code in kirad/metrics.py
108 109 110 111 112 113 114 115 116 117 | |
pareto_2d_indices(x, y)
¶
Indices of the 2-d Pareto frontier maximizing x and y.
Compute indices of the Pareto frontier maximizing x and y, sorted in increasing x and decreasing y.
e.g. the Pareto frontier of the point set below is [A, G]
B A C E D F G H
u = [2, 0, 1, 2, 0, 0, 3, 1] v = [4, 4, 3, 2, 2, 1, 1, 0] pareto_2d_indices(np.array(u), np.array(v)) array([0, 6])
Source code in kirad/metrics.py
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | |
midpoints_with_infs(x)
¶
Return the midpoints between the sorted unique elements of x, along with +/-inf.
Source code in kirad/metrics.py
144 145 146 147 | |
binary_indet_confusion_matrix(scores, y_true, thresh_low, thresh_high)
¶
Flat 2x3 confusion matrix (neg/pos truth x neg/pos/indet output) for one threshold pair.
Compute flattened confusion matrix for binary ground truth, with indeterminate score range. Note: not called inside kirad; standalone analysis helper.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scores
|
ndarray
|
|
required |
y_true
|
ndarray
|
|
required |
thresh_low
|
float
|
|
required |
thresh_high
|
float
|
thresh_low and thresh_high are mapped to model output "indeterminate") |
required |
Returns:
| Type | Description |
|---|---|
Integer vector of length 6 representing flattened confusion matrix as follows:
|
(true negatives, false positives, negative ground truth with indeterminate output, false negatives, true positives, positive ground truth with indeterminate output) |
suitable for passing to `cms_to_stats` or `bootstrap_confusion_matrix`.
|
|
Source code in kirad/metrics.py
406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 | |
bootstrap_confusion_matrix(cm, num_bootstrap)
¶
Multinomial bootstrap of a flat confusion matrix; returns len(cm) x num_bootstrap.
Resample from flat confusion matrix with replacement num_bootstrap times.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cm
|
ndarray
|
confusion matrix |
required |
num_bootstrap
|
int
|
|
required |
Returns:
| Type | Description |
|---|---|
Integer matrix of shape len(cm) x num_bootstrap with each column giving the
|
|
confusion matrix for an independent bootstrap resample of `cm`.
|
|
Source code in kirad/metrics.py
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 | |