@mark1russell7/rigor-statistics 0.1.5 → 0.1.7

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.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @mark1russell7/rigor-statistics
2
2
 
3
- The statistics of measured work. It gives quantiles, bootstrap intervals, the sign test, the paired permutation test, Wilson intervals and the Holm correction. It gives the interval of a median from order statistics, and the central interval of a binomial count. It also gives least squares, rank correlation, the comparison with a baseline beyond the noise, and the Brier score of predictions.
3
+ The statistics of measured work. It gives quantiles, bootstrap intervals, the sign test, the paired permutation test, Wilson intervals and the Holm correction. It gives the interval of a median from order statistics, and the central interval of a binomial count. It also gives least squares, rank correlation, the comparison with a baseline beyond the noise, and the Brier score of predictions. It fits response records that a browser can evaluate from plain JSON.
4
4
 
5
5
  ```sh
6
6
  npm install @mark1russell7/rigor-statistics
@@ -9,7 +9,7 @@ npm install @mark1russell7/rigor-statistics
9
9
  ## Compare a candidate with a baseline
10
10
 
11
11
  ```ts
12
- import { compareRatios, noiseFloor } from "@mark1russell7/rigor-statistics";
12
+ import { compareRatios, noiseFloor, noiseVerdict } from "@mark1russell7/rigor-statistics";
13
13
 
14
14
  // The ratio candidate / baseline of each input, and the measure of 5 seeds or folds of the same run.
15
15
  const noise = noiseFloor(foldMedians); // 2 standard deviations; it needs 5 values or more
@@ -18,10 +18,61 @@ const c = compareRatios(ratios, { noise });
18
18
  c.wins, c.losses, c.signP; // how often, by any amount
19
19
  c.effect; // by how much: the median, p10 and p90 of the inputs that are not ties
20
20
  c.gains, c.drops; // how often beyond the noise, with Wilson intervals
21
+
22
+ // A difference (candidate - baseline) of each seed: beyond max(2 SD, margin)? Equal values give "no-spread".
23
+ const v = noiseVerdict(foldDiffs, { margin: 0.02 }); // give the reason of the margin from the problem of the user
24
+ v.state; // "gain", "loss", "noise" or "no-spread"
21
25
  ```
22
26
 
23
27
  A promotion reads `gains` against `drops` and `effect`. A sign test alone is not enough, because it counts a win of any size. Judge a change of a default against the current default, not against "no change".
24
28
 
29
+ ## Fit and show a response
30
+
31
+ The format `response-records/1` keeps the measured points of a study, a model for each measure and the held-out error of each fold. A record is plain JSON, and the functions use no Node API. Thus a browser reads a record and evaluates its models.
32
+
33
+ ```ts
34
+ import { fitResponse, parseResponseRecord, sliceResponse } from "@mark1russell7/rigor-statistics";
35
+
36
+ const record = fitResponse(
37
+ {
38
+ schema: "response-records/1",
39
+ name: "time of a placement",
40
+ dimensions: [
41
+ { id: "boxes", label: "Boxes", kind: "continuous", range: [10, 10000], unit: "", log: true },
42
+ { id: "strategy", label: "Strategy", kind: "categorical", levels: ["shelf", "skyline"], unit: "" },
43
+ // Only the arm "skyline" has this parameter. Each other point has null.
44
+ { id: "depth", label: "Depth", kind: "continuous", range: [1, 8], unit: "", when: { dimension: "strategy", levels: ["skyline"] } },
45
+ ],
46
+ measures: [{ id: "ms", label: "Time", unit: "ms", direction: "lower" }],
47
+ points, // { id, values, measures, group }: repeats of one input have one group
48
+ },
49
+ { log: ["ms"], logFloor: 0.001 },
50
+ );
51
+
52
+ // A server writes the text. A browser reads it, and it asks for one dimension with the other dimensions held.
53
+ const text = JSON.stringify(record);
54
+ const parsed = parseResponseRecord(JSON.parse(text));
55
+ if (!parsed.ok) throw new Error(JSON.stringify(parsed.faults));
56
+ const slice = sliceResponse(parsed.record, "ms", { vary: "depth", hold: { boxes: 1000 } });
57
+ slice.curve; // { at, value, low, high, nearest } along the dimension
58
+ slice.points; // the measured points with the held values
59
+ slice.error; // the held-out error of the folds
60
+ ```
61
+
62
+ A test of this package compiles and starts this example, and it examines that the two texts are equal.
63
+
64
+ `fitResponse` keeps all the points of one `group` in one fold, so repeats of a group are not on both sides of a split. Each fold chooses its penalty from the other folds only. The folds thus measure the prediction of an unseen group.
65
+
66
+ There are two kinds of model. A `ridge` model is a sum of weighted terms. Each term is a product of powers of number inputs and one-hot columns of levels. A `table` model has one cell for each combination of levels. `fitResponse` gives a table when each dimension is categorical, and a ridge model in other cases.
67
+
68
+ A dimension with `when` is conditional: only some levels of its parent have the dimension. This suits a benchmark in which each arm has its own parameters. A point at another level has `null`. In a ridge model, a term with an absent dimension is 0, so the columns of the parent carry the mean of that level. A table keeps `null` in its cells. For each kind of model, `predictResponse` refuses `null` at a dimension with no condition.
69
+
70
+ To vary a conditional dimension, `sliceResponse` needs its parent at a level inside `when`. With no held value, the parent takes the most common level inside `when`. A held conditional dimension reads `null` when its parent is outside `when`.
71
+
72
+ The band of a curve is `value ± width × RMSE`, from the held-out error of the folds. On a log scale, the band is a ratio. The band has one width along the curve. It is the mean error of the model.
73
+
74
+ The field `nearest` of each place tells how far the place is from a measurement. It goes from 0 to 1, and 0 means that a point was measured there. A viewer can fade the band away from the data. A table cell with the `fallback` value has `nearest` above 0.
75
+
25
76
  ## The functions
26
77
 
27
78
  | Function | What it gives |
@@ -42,8 +93,12 @@ A promotion reads `gains` against `drops` and `effect`. A sign test alone is not
42
93
  | `binomialInterval(n, p, level)`, `negativeBinomialInterval(successes, p, level)` | The central interval of a binomial count, and of a count of failures before `successes` successes. Each tail outside holds `(1 - level) / 2` or less. |
43
94
  | `holm(pValues, level)` | The Holm correction of a family of tests. |
44
95
  | `spearman`, `kendallTau`, `ranks` | The rank correlations, with mean ranks for ties. |
45
- | `compareRatios`, `noiseFloor` | The comparison with a baseline, and the noise floor of the 5-seed rule. |
96
+ | `compareRatios`, `noiseFloor`, `noiseVerdict` | The comparison with a baseline, the noise floor of the 5-seed rule with a margin of practical effect, and the state of a difference over the seeds. |
46
97
  | `brier`, `calibration` | The Brier score of predictions, and the hit rate of each stated level. |
98
+ | `fitResponse(data, options)` | A record of the format `response-records/1`, with one model for each measure and held-out folds. |
99
+ | `parseResponseRecord(value)` | The examination of unknown data. It gives the record, or one fault with a path for each error. |
100
+ | `predictResponse(model, inputs)`, `heldOutError(record, measure)` | The value of a model at one set of inputs, and the error of the folds of a measure. |
101
+ | `sliceResponse(record, measure, options)`, `surfaceResponse(record, measure, options)` | A fitted curve over one dimension, or a fitted surface over two, with the matching measured points, a band and the distance to the nearest measurement. |
47
102
 
48
103
  Each function throws a RangeError for an empty list, for a NaN and for a parameter out of its range. Thus a missing value cannot make a quiet NaN in a record.
49
104
 
package/build/index.d.ts CHANGED
@@ -8,7 +8,10 @@ type QuantileMethod = "linear" | "nearest-rank" | "higher";
8
8
  /** A new list with the values from the smallest to the largest. */
9
9
  export declare function sorted(values: readonly number[]): number[];
10
10
  export declare function mean(values: readonly number[]): number;
11
- /** The sample standard deviation (the divisor is n - 1). It needs 2 values or more. */
11
+ /**
12
+ * The sample standard deviation (the divisor is n - 1). It needs 2 values or more. Equal values give exactly 0. The
13
+ * rounding of the mean gives a small number that is not 0 for some equal values, so the function examines them first.
14
+ */
12
15
  export declare function sd(values: readonly number[]): number;
13
16
  /**
14
17
  * The `p` quantile of a list that is already sorted. Use it when you take several quantiles of one list.
@@ -158,6 +161,420 @@ interface RidgeOptions {
158
161
  * `k` is 0. It also throws for a value that is not finite, for a `lambda` below 0, and for a bad free index.
159
162
  */
160
163
  export declare function ridgeSolve(gram: ArrayLike<number>, moment: ArrayLike<number>, lambda: number, options?: RidgeOptions): number[];
164
+ /** The value of the field `schema` of a record. */
165
+ export declare const RESPONSE_RECORDS_SCHEMA = "response-records/1";
166
+ /** The value of a dimension at a point: a number, or the text of a level. */
167
+ type ResponseValue = number | string;
168
+ /** The value of a dimension at a place. The value `null` means that a conditional dimension is absent there. */
169
+ type ResponseInputValue = ResponseValue | null;
170
+ /** The condition of a dimension: the dimension has a value only at these levels of its parent. */
171
+ interface ResponseWhen {
172
+ /** The id of the parent: a categorical or ordinal dimension with no condition. */
173
+ readonly dimension: string;
174
+ readonly levels: readonly ResponseValue[];
175
+ }
176
+ /** The fields of each kind of dimension. */
177
+ interface ResponseDimensionBase {
178
+ /** The key of the dimension in the values of a point. */
179
+ readonly id: string;
180
+ /** The name that a view shows. */
181
+ readonly label: string;
182
+ /** The unit. An empty string means that the dimension has no unit. */
183
+ readonly unit: string;
184
+ /** With this field, a point has a value only at the stated levels of the parent. Each other point has `null`. */
185
+ readonly when?: ResponseWhen;
186
+ }
187
+ /** A dimension with each number in a range. */
188
+ interface ContinuousDimension extends ResponseDimensionBase {
189
+ readonly kind: "continuous";
190
+ /** The smallest and the largest value. The first is less than the second. */
191
+ readonly range: readonly [number, number];
192
+ /** When true, a model and an axis use the base-10 logarithm of the value. All of the range is above 0. */
193
+ readonly log?: boolean;
194
+ }
195
+ /** A dimension with levels in order. Number levels ascend. A model reads a text level as its position. */
196
+ interface OrdinalDimension extends ResponseDimensionBase {
197
+ readonly kind: "ordinal";
198
+ readonly levels: readonly number[] | readonly string[];
199
+ /** When true, a model uses the base-10 logarithm of the level. The levels are numbers above 0. */
200
+ readonly log?: boolean;
201
+ }
202
+ /** A dimension with levels that have no order, for example the arms of a benchmark. */
203
+ interface CategoricalDimension extends ResponseDimensionBase {
204
+ readonly kind: "categorical";
205
+ readonly levels: readonly string[];
206
+ }
207
+ /** A dimension of a record. */
208
+ type ResponseDimension = ContinuousDimension | OrdinalDimension | CategoricalDimension;
209
+ /** A measured value of each point. */
210
+ interface ResponseMeasure {
211
+ /** The key of the measure in the measures of a point. */
212
+ readonly id: string;
213
+ readonly label: string;
214
+ /** The unit. An empty string means that the measure has no unit. */
215
+ readonly unit: string;
216
+ /** The better direction of the value. The value `none` means that no direction is better. */
217
+ readonly direction: "higher" | "lower" | "none";
218
+ }
219
+ /** One measured point. */
220
+ interface ResponsePoint {
221
+ readonly id: string;
222
+ /** The value of each dimension. */
223
+ readonly values: Readonly<Record<string, ResponseInputValue>>;
224
+ /** The value of each measure. The value `null` means that the run did not give the measure at this point. */
225
+ readonly measures: Readonly<Record<string, number | null>>;
226
+ /** The points of one group stay on one side of each split, for example the repeats of one seed. */
227
+ readonly group?: string;
228
+ }
229
+ /** One factor of a term: a power of a number dimension, or 1 at a level and 0 at each other level. */
230
+ type ResponseFactor = {
231
+ readonly dimension: string;
232
+ readonly power: number;
233
+ } | {
234
+ readonly dimension: string;
235
+ readonly level: ResponseValue;
236
+ };
237
+ /** The fields of each kind of input of a ridge model. */
238
+ interface RidgeInputBase {
239
+ readonly dimension: string;
240
+ /** When true, the dimension is conditional, so `null` is a good value. Each term of an absent dimension is 0. */
241
+ readonly conditional?: boolean;
242
+ }
243
+ /** The coordinate of a number dimension: the value (or its logarithm), less `center`, divided by `spread`. */
244
+ interface RidgeNumberInput extends RidgeInputBase {
245
+ readonly kind: "number";
246
+ readonly center: number;
247
+ readonly spread: number;
248
+ readonly log?: boolean;
249
+ }
250
+ /** The coordinate of an ordinal dimension with text levels: the position of the level, as in `RidgeNumberInput`. */
251
+ interface RidgeRankInput extends RidgeInputBase {
252
+ readonly kind: "rank";
253
+ readonly levels: readonly string[];
254
+ readonly center: number;
255
+ readonly spread: number;
256
+ }
257
+ /** A categorical dimension: the factors of its levels are the one-hot columns. */
258
+ interface RidgeLevelInput extends RidgeInputBase {
259
+ readonly kind: "level";
260
+ readonly levels: readonly string[];
261
+ }
262
+ /** An input of a ridge model. The model holds it, so `predictResponse` needs no record. */
263
+ type RidgeInput = RidgeNumberInput | RidgeRankInput | RidgeLevelInput;
264
+ /** A term of a ridge model: the product of its factors, times the weight. */
265
+ interface RidgeTerm {
266
+ readonly factors: readonly ResponseFactor[];
267
+ readonly weight: number;
268
+ }
269
+ /** The fields of each kind of model. */
270
+ interface ResponseModelBase {
271
+ /** The id of the measure of the model. */
272
+ readonly measure: string;
273
+ /** With `log`, the model and the held-out errors use the base-10 logarithm of the measure. */
274
+ readonly scale: "linear" | "log";
275
+ /** With the scale `log`, the fit gave this value to each smaller measured value. */
276
+ readonly floor?: number;
277
+ }
278
+ /** A ridge fit over a stated expansion: the intercept, plus the sum of the terms. */
279
+ interface RidgeResponseModel extends ResponseModelBase {
280
+ readonly kind: "ridge";
281
+ /** The penalty of the fit. */
282
+ readonly lambda: number;
283
+ readonly inputs: readonly RidgeInput[];
284
+ readonly intercept: number;
285
+ readonly terms: readonly RidgeTerm[];
286
+ }
287
+ /** One cell of a table model. */
288
+ interface ResponseTableCell {
289
+ /** The value of each dimension of the table, in the order of its `dimensions`. An absent dimension has `null`. */
290
+ readonly at: readonly ResponseInputValue[];
291
+ /** The mean of the measured values of the cell, on the scale of the model. */
292
+ readonly value: number;
293
+ /** The number of points of the cell. */
294
+ readonly n: number;
295
+ }
296
+ /** The mean of each measured combination of levels. */
297
+ interface TableResponseModel extends ResponseModelBase {
298
+ readonly kind: "table";
299
+ readonly dimensions: readonly string[];
300
+ /** The ids of the dimensions of the table with a condition. Only these dimensions take `null`. */
301
+ readonly conditional?: readonly string[];
302
+ readonly cells: readonly ResponseTableCell[];
303
+ /** The value of a combination with no cell: the mean of all the fitted points, on the scale of the model. */
304
+ readonly fallback: number;
305
+ }
306
+ /** A model that a browser evaluates from plain JSON. */
307
+ type ResponseModel = RidgeResponseModel | TableResponseModel;
308
+ /** The held-out error of one measure in one fold, on the scale of the model. */
309
+ interface ResponseFoldError {
310
+ /** The number of held-out points with a value of the measure. */
311
+ readonly n: number;
312
+ /** The mean absolute error. */
313
+ readonly mae: number;
314
+ /** The root mean square error. */
315
+ readonly rmse: number;
316
+ /** The mean absolute error of the mean of the training points, used as the prediction. */
317
+ readonly baselineMae: number;
318
+ }
319
+ /** One split of the points. The fold held out `heldOut`, and it fit a model on the other points. */
320
+ interface ResponseFold {
321
+ /** The ids of the held-out points. */
322
+ readonly heldOut: readonly string[];
323
+ /** The error of each measure. A measure with no held-out point or no training point has no entry. */
324
+ readonly errors: Readonly<Record<string, ResponseFoldError>>;
325
+ }
326
+ /** The data of a record, before a fit. */
327
+ interface ResponseData {
328
+ readonly schema: typeof RESPONSE_RECORDS_SCHEMA;
329
+ readonly name: string;
330
+ readonly dimensions: readonly ResponseDimension[];
331
+ readonly measures: readonly ResponseMeasure[];
332
+ readonly points: readonly ResponsePoint[];
333
+ }
334
+ /** A record: the data, one model for each measure, and the folds. */
335
+ interface ResponseRecord extends ResponseData {
336
+ readonly models: readonly ResponseModel[];
337
+ readonly folds: readonly ResponseFold[];
338
+ }
339
+ /** The held-out error of one measure over all the folds, on the scale of the model. */
340
+ interface ResponseHeldOutError {
341
+ /** The number of held-out points. */
342
+ readonly n: number;
343
+ /** The number of folds with this measure. */
344
+ readonly folds: number;
345
+ /** The mean absolute error of all the held-out points. */
346
+ readonly mae: number;
347
+ /** The root mean square error of all the held-out points. */
348
+ readonly rmse: number;
349
+ /** The mean absolute error of the baseline. */
350
+ readonly baselineMae: number;
351
+ /** The value `1 - mae / baselineMae`. The value 0 is no better than the mean. A baseline of 0 gives `null`. */
352
+ readonly skill: number | null;
353
+ }
354
+ /** The options of `sliceResponse` and `surfaceResponse`. */
355
+ interface ResponseViewOptions {
356
+ /** The value of each held dimension. Each other dimension takes its usual value, as `sliceResponse` tells. */
357
+ readonly hold?: Readonly<Record<string, ResponseInputValue>>;
358
+ /** The number of values on a continuous axis, 2 or more. The default is 33. */
359
+ readonly steps?: number;
360
+ /**
361
+ * The share of the range of a held number dimension in which a point matches. A log dimension uses the log scale.
362
+ * The default is 0: only an equal value matches.
363
+ */
364
+ readonly tolerance?: number;
365
+ /** The half width of the band, as a multiple of the held-out root mean square error. The default is 1. */
366
+ readonly width?: number;
367
+ }
368
+ /** The options of `sliceResponse`. */
369
+ interface ResponseSliceOptions extends ResponseViewOptions {
370
+ /** The id of the dimension of the curve. */
371
+ readonly vary: string;
372
+ }
373
+ /** The options of `surfaceResponse`. */
374
+ interface ResponseSurfaceOptions extends ResponseViewOptions {
375
+ /** The ids of the two dimensions of the surface: first the x axis, then the y axis. */
376
+ readonly vary: readonly [string, string];
377
+ }
378
+ /**
379
+ * The fitted value at one place, with its band. The band is the mean error of the model, and `nearest` tells how far
380
+ * the place is from a measurement.
381
+ */
382
+ interface ResponseBand {
383
+ readonly value: number;
384
+ readonly low: number;
385
+ readonly high: number;
386
+ /**
387
+ * The distance from this place to the nearest measured point with a value of the measure, from 0 to 1. The value 0
388
+ * means that a point was measured here. A number or rank dimension counts as its share of the axis. A different
389
+ * categorical level counts 1, and an absent value against a present value counts 1. The distance is the largest
390
+ * count over the dimensions.
391
+ */
392
+ readonly nearest: number;
393
+ }
394
+ /** One place of a curve. */
395
+ interface ResponseCurvePoint extends ResponseBand {
396
+ /** The value of the varied dimension. */
397
+ readonly at: ResponseValue;
398
+ }
399
+ /** A measured point of a slice. */
400
+ interface ResponseSlicePoint {
401
+ readonly id: string;
402
+ /** The value of the varied dimension. */
403
+ readonly at: ResponseValue;
404
+ readonly value: number;
405
+ readonly group?: string;
406
+ }
407
+ /** The fitted curve over one dimension, and the measured points that match the held values. */
408
+ interface ResponseSlice {
409
+ readonly measure: string;
410
+ readonly vary: string;
411
+ /** The value of each other dimension. */
412
+ readonly held: Readonly<Record<string, ResponseInputValue>>;
413
+ readonly curve: readonly ResponseCurvePoint[];
414
+ readonly points: readonly ResponseSlicePoint[];
415
+ readonly error: ResponseHeldOutError;
416
+ }
417
+ /** A measured point of a surface. */
418
+ interface ResponseSurfacePoint {
419
+ readonly id: string;
420
+ /** The values of the two varied dimensions. */
421
+ readonly at: readonly [ResponseValue, ResponseValue];
422
+ readonly value: number;
423
+ readonly group?: string;
424
+ }
425
+ /** The fitted surface over two dimensions, and the measured points that match the held values. */
426
+ interface ResponseSurface {
427
+ readonly measure: string;
428
+ readonly vary: readonly [string, string];
429
+ /** The value of each other dimension. */
430
+ readonly held: Readonly<Record<string, ResponseInputValue>>;
431
+ readonly x: readonly ResponseValue[];
432
+ readonly y: readonly ResponseValue[];
433
+ /** One row for each value of `y`. Each row has one cell for each value of `x`. */
434
+ readonly cells: readonly (readonly ResponseBand[])[];
435
+ readonly points: readonly ResponseSurfacePoint[];
436
+ readonly error: ResponseHeldOutError;
437
+ }
438
+ /**
439
+ * This function gives the value of a model at `inputs`, on the scale of the measure. The inputs have a value for each
440
+ * dimension that the model reads. An absent conditional dimension has `null`. A table model gives its `fallback` for a
441
+ * combination with no cell.
442
+ *
443
+ * The function throws a RangeError for a missing input and for a value that is not a number or a level of the model.
444
+ * It throws for `null` at a dimension with no condition, for each kind of model. It also throws for a value at or below
445
+ * 0 on a log scale. A number outside the range of the record is good, so the
446
+ * function extrapolates.
447
+ */
448
+ export declare function predictResponse(model: ResponseModel, inputs: Readonly<Record<string, ResponseInputValue>>): number;
449
+ /**
450
+ * This function gives the held-out error of a measure over all the folds. Each point has the same weight, so a small
451
+ * fold has a small effect. The function throws a RangeError when no fold has the measure.
452
+ */
453
+ export declare function heldOutError(record: Pick<ResponseRecord, "folds">, measure: string): ResponseHeldOutError;
454
+ /**
455
+ * This function gives a view of a measure over one dimension of a parsed record:
456
+ * - `curve`: the fitted value at each level, or at `steps` values of a continuous dimension, with its band.
457
+ * - `points`: the measured points that match the held values. This list is empty when no point matches them.
458
+ * - `held`: the value of each other dimension.
459
+ * - `error`: the held-out error.
460
+ *
461
+ * Each dimension with no value in `hold` takes its usual value. For a continuous dimension, this value is the median
462
+ * of its measured values. For the other kinds, it is the most common level, and a tie gives the first level.
463
+ *
464
+ * A conditional dimension follows its parent:
465
+ * - To vary a conditional dimension, the parent needs a level inside `when`. With no held value, the parent takes the
466
+ * most common level inside `when`. A held level outside `when` is a RangeError.
467
+ * - A held conditional dimension reads `null` in `held` when its parent is outside `when`, also with a value in `hold`.
468
+ * The points that match have `null` at this dimension.
469
+ * - When the parent varies, a held conditional dimension keeps its value in `held`. Each place outside `when` reads
470
+ * `null` for the fit, and for the matching points.
471
+ *
472
+ * The band is the fitted value, plus and less `width` times the held-out root mean square error. On a log scale, this
473
+ * distance is on the log scale of the model, so the band is a ratio. The band has one width along all the curve. The
474
+ * band is the mean error of the model, and `nearest` tells how far the place is from a measurement.
475
+ *
476
+ * The function throws a RangeError for an unknown measure or dimension, and for a held value that is not good for its
477
+ * dimension. It also throws for a dimension that is both varied and held, and for a bad option.
478
+ */
479
+ export declare function sliceResponse(record: ResponseRecord, measure: string, options: ResponseSliceOptions): ResponseSlice;
480
+ /**
481
+ * This function gives the view of `sliceResponse` over two dimensions. The fields `x` and `y` are the two axes, and
482
+ * `cells` has one row for each value of `y`. The rules of the held values, of the matching points and of the band are
483
+ * the rules of `sliceResponse`. The function also throws a RangeError when the two varied dimensions are one dimension.
484
+ * It throws when a conditional dimension varies with its parent, and when two varied dimensions need no common level.
485
+ */
486
+ export declare function surfaceResponse(record: ResponseRecord, measure: string, options: ResponseSurfaceOptions): ResponseSurface;
487
+ /** The largest power of a factor. A larger power of a coordinate from -1 to 1 adds almost nothing to a model. */
488
+ export declare const RESPONSE_MAX_POWER = 8;
489
+ /** One fault of a record. */
490
+ interface ResponseFault {
491
+ /** The place of the fault, for example `points[3].values.size`. An empty string is the record itself. */
492
+ readonly path: string;
493
+ /** What is wrong, and what the format needs. */
494
+ readonly message: string;
495
+ }
496
+ /** The result of `parseResponseRecord`: the record, or each fault that the validator found. */
497
+ type ParsedResponseRecord = {
498
+ readonly ok: true;
499
+ readonly record: ResponseRecord;
500
+ } | {
501
+ readonly ok: false;
502
+ readonly faults: readonly ResponseFault[];
503
+ };
504
+ /**
505
+ * This function examines unknown data, for example the result of `JSON.parse`, against `response-records/1`. It gives
506
+ * `{ ok: true, record }`, with the same object as the record, or `{ ok: false, faults }`. Each fault has the path of
507
+ * the bad field and a message. The function does not throw. Data that the checks cannot read, for example an object
508
+ * with a loop, gives one fault.
509
+ *
510
+ * A field that the format does not have is a fault. Thus a wrong spelling of an optional field cannot go unseen.
511
+ *
512
+ * The function examines the models and the folds only when the data has no fault, because they refer to the data.
513
+ * Thus a correction of the data can show more faults. These rules apply to the folds:
514
+ * - A point is in one fold or in no fold.
515
+ * - All the points of a group are in one fold, or all are in no fold. Thus no group is on both sides of a split.
516
+ * - The count `n` of an error is the number of held-out points with a value of the measure.
517
+ * - Each measure has an error in one fold or more.
518
+ */
519
+ export declare function parseResponseRecord(value: unknown): ParsedResponseRecord;
520
+ /** The options of `fitResponse`. */
521
+ interface ResponseFitOptions {
522
+ /** The number of folds, 3 or more. With fewer groups, each group is one fold. The default is 5. */
523
+ readonly folds?: number;
524
+ /** The seed of the split. The default is 1. */
525
+ readonly seed?: number | string;
526
+ /** The kind of model. The default `auto` gives a table when each dimension is categorical, and a ridge fit otherwise. */
527
+ readonly model?: "auto" | "ridge" | "table";
528
+ /** The largest total power of a term of a ridge fit, from 1 to 8. The default is 2. */
529
+ readonly degree?: number;
530
+ /**
531
+ * When true, a ridge fit also has the products of two dimensions, up to `degree`. The default is true. The value
532
+ * false also removes the products of a conditional dimension with the levels of its parent. Thus this option is the
533
+ * way out of the limit `RESPONSE_MAX_TERMS`.
534
+ */
535
+ readonly interactions?: boolean;
536
+ /** The stated terms of a ridge fit, in place of `degree` and `interactions`. */
537
+ readonly terms?: readonly (readonly ResponseFactor[])[];
538
+ /** The penalties that a ridge fit chooses from, each above 0. The default is `RESPONSE_LAMBDAS`. */
539
+ readonly lambdas?: readonly number[];
540
+ /** The ids of the measures to fit on a log scale. */
541
+ readonly log?: readonly string[];
542
+ /** On a log scale, each smaller value takes this value. With no floor, a value of 0 or less is an error. */
543
+ readonly logFloor?: number;
544
+ }
545
+ /** The default penalties of a ridge fit. The coordinates are from -1 to 1, so one list suits each record. */
546
+ export declare const RESPONSE_LAMBDAS: readonly number[];
547
+ /** The largest number of coefficients of a ridge fit. The memory of each fold grows as the square of this number. */
548
+ export declare const RESPONSE_MAX_TERMS = 1024;
549
+ /**
550
+ * This function fits each measure of `data`, and it gives a record with the models and the folds.
551
+ *
552
+ * The split: the groups, sorted and then shuffled with `seed`, go to the folds in turn. A point with no group is a
553
+ * group of its own. Thus the repeats of one group are not on both sides of a split. The same split applies to each
554
+ * measure. A record needs 3 groups or more.
555
+ *
556
+ * The model: a ridge fit over a stated expansion, or the mean of each cell of a table. The default expansion has
557
+ * each power of each number dimension up to `degree`. It has one column for each level of a categorical dimension.
558
+ * It also has the products of two dimensions up to `degree`. Each coordinate goes from -1 to 1 over the declared
559
+ * range. The intercept has no penalty.
560
+ *
561
+ * A conditional dimension: a term with an absent dimension is 0. Thus the columns of the parent carry the mean of each
562
+ * level with no value. A dimension with two parent levels or more also has each power times each of these levels, if
563
+ * `interactions` is true. A table keeps `null` as a level of its cells.
564
+ *
565
+ * The penalty: each fold of a ridge fit chooses from `lambdas` with the other folds. Thus the held-out error of a
566
+ * fold is not optimistic. The model of the record chooses with all the folds.
567
+ *
568
+ * The errors: a fold scores the model of the other folds on its held-out points, on the scale of the model.
569
+ *
570
+ * The result does not depend on the order of the points, except for the field `points`, which keeps the order of
571
+ * the data. The same data and options give the same bytes in one JavaScript engine.
572
+ *
573
+ * The function throws a RangeError for data with a fault, for a bad option, and for fewer than 3 groups. It also
574
+ * throws for a measure with no value, and for a measure with all its values in one fold. It throws for a value of 0
575
+ * or less on a log scale with no `logFloor`. It throws for more than `RESPONSE_MAX_TERMS` terms.
576
+ */
577
+ export declare function fitResponse(data: ResponseData, options?: ResponseFitOptions): ResponseRecord;
161
578
  /**
162
579
  * The sign test of paired results: `better` inputs where the candidate wins and `worse` where it loses. The ties
163
580
  * do not count. One-sided (the default), it is the p of `better` wins or more if the two are equal. Two-sided, it is
@@ -273,12 +690,46 @@ interface NoiseOptions {
273
690
  readonly k?: number;
274
691
  /** The fewest values (seeds or folds) that give a floor. The default is 5, the 5-seed rule. */
275
692
  readonly minimum?: number;
693
+ /**
694
+ * The margin of practical effect, in the units of the values. A difference that is real but smaller than the margin
695
+ * is too small to matter, so it is not a result. Give the reason of the margin from the problem of the user. The
696
+ * default is 0: no margin.
697
+ */
698
+ readonly margin?: number;
276
699
  }
277
700
  /**
278
- * The noise floor of a measure: k sample standard deviations of its value over independent seeds or folds. A
279
- * difference smaller than the floor is not a result.
701
+ * The noise floor of a measure: k sample standard deviations of its value over independent seeds or folds. When the
702
+ * margin of practical effect is larger, the floor is the margin. A difference smaller than the floor is not a result.
280
703
  */
281
704
  export declare function noiseFloor(values: readonly number[], options?: NoiseOptions): number;
705
+ /**
706
+ * The state of a difference over the seeds. "gain" and "loss": the mean is beyond the threshold. "noise": it is not.
707
+ * "no-spread": each seed gives the same value, so the seeds do not sample the noise and the rule tests nothing.
708
+ */
709
+ type NoiseState = "gain" | "loss" | "noise" | "no-spread";
710
+ /** The noise rule of a difference over independent seeds or folds. */
711
+ interface NoiseVerdict {
712
+ /** The number of values. */
713
+ readonly n: number;
714
+ readonly mean: number;
715
+ /** The sample standard deviation of the values. */
716
+ readonly sd: number;
717
+ /** k times the standard deviation. */
718
+ readonly spread: number;
719
+ readonly margin: number;
720
+ /** The larger of `spread` and `margin`. The absolute mean must be above it. */
721
+ readonly threshold: number;
722
+ readonly state: NoiseState;
723
+ }
724
+ /**
725
+ * The noise rule of a difference (candidate minus baseline) over independent seeds or folds: the mean against
726
+ * max(k standard deviations, margin). With `better: "lower"`, a negative mean is the gain. When each value is equal,
727
+ * the state is "no-spread" and not a result, also when the mean is beyond the margin. Find out why the seeds do not
728
+ * change the value before you read the difference.
729
+ */
730
+ export declare function noiseVerdict(values: readonly number[], options?: NoiseOptions & {
731
+ readonly better?: "higher" | "lower";
732
+ }): NoiseVerdict;
282
733
  interface CompareOptions {
283
734
  /** "higher" (the default): a ratio above 1 is a gain. "lower": a ratio below 1 is a gain, as for a time or a cost. */
284
735
  readonly better?: "higher" | "lower";
@@ -345,5 +796,5 @@ interface CalibrationLevel {
345
796
  }
346
797
  /** The hit rate of each stated level, from the lowest level. */
347
798
  export declare function calibration(forecasts: readonly Forecast[]): CalibrationLevel[];
348
- export type { BootstrapOptions, CalibrationLevel, CompareOptions, Comparison, Corrected, CountInterval, Effect, Forecast, Interval, LeastSquaresFit, LeastSquaresOptions, MedianInterval, NoiseOptions, PermutationOptions, PermutationResult, Proportion, QuantileMethod, RidgeOptions, Summary };
799
+ export type { BootstrapOptions, CalibrationLevel, CategoricalDimension, CompareOptions, Comparison, ContinuousDimension, Corrected, CountInterval, Effect, Forecast, Interval, LeastSquaresFit, LeastSquaresOptions, MedianInterval, NoiseOptions, NoiseState, NoiseVerdict, OrdinalDimension, ParsedResponseRecord, PermutationOptions, PermutationResult, Proportion, QuantileMethod, ResponseBand, ResponseCurvePoint, ResponseData, ResponseDimension, ResponseDimensionBase, ResponseFactor, ResponseFault, ResponseFitOptions, ResponseFold, ResponseFoldError, ResponseHeldOutError, ResponseInputValue, ResponseMeasure, ResponseModel, ResponseModelBase, ResponsePoint, ResponseRecord, ResponseSlice, ResponseSliceOptions, ResponseSlicePoint, ResponseSurface, ResponseSurfaceOptions, ResponseSurfacePoint, ResponseTableCell, ResponseValue, ResponseViewOptions, ResponseWhen, RidgeInput, RidgeInputBase, RidgeLevelInput, RidgeNumberInput, RidgeOptions, RidgeRankInput, RidgeResponseModel, RidgeTerm, Summary, TableResponseModel };
349
800
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/describe.ts","../src/regression.ts","../src/bootstrap.ts","../src/ridge.ts","../src/tests.ts","../src/rank.ts","../src/discrete.ts","../src/compare.ts"],"mappings":";;;;;;KAOY;;wBAmBI,OAAO;wBAIP,KAAK;;wBAQL,GAAG;;;;;;;wBAeH,eAAe,iCAAiC,WAAW,SAAQ;;wBAkBnE,SAAS,2BAA2B,WAAW,SAAQ;;;;;wBASvD,OAAO;;UAQN;WACN;WACA;;WAEA;WACA;;WAEA;WACA;;WAEA;WACA;;WAEA;;wBAGK,UAAU,4BAA4B;;;;;;UClGrC;;WAEN;;UAGM;;WAEN;;WAEA;;;;;WAKA;;WAEA;;WAEA;;;;;;;;;;;wBAkBK,aAAa,mCAAmC,sBAAsB,UAAS,sBAA2B;UC/BzG;;WAEN;;WAEA;;WAEA;;WAEA,SAAS;;;;;;WAMT;;UAGM;;WAEN;WACA;WACA;WACA;WACA;;WAEA;;WAEA;;;;;;wBAOK,UAAU,GAAG,eAAe,KAAK,YAAY,iBAAiB,gBAAgB,UAAS,mBAAwB;;;;;;;;wBAsB/G,aAAa,GAAG,GAC9B,YAAY,KACZ,YAAY,KACZ,YAAY,YAAY,KAAK,YAAY,gBACzC,UAAS,mBACR;;;;;;wBAwBa,qBAAqB,8BAA8B,gCAAgC,UAAS,mBAAwB;;;;;;;wBAUpH,sBACd,mCACA,sBACA,UAAS,mBAAmB,sBAC3B;;wBAmFa,gBAAgB,2BAA2B,UAAS,mBAAwB;;;;;;wBAS5E,kBAAkB,GAChC,eAAe,KACf,UAAU,KAAK,cACf,YAAY,eAAe,gBAC3B,UAAS,mBACR;;;;;;;UCxMc;;WAEN;;;;;;;;;;;;wBAoBK,WAAW,MAAM,mBAAmB,QAAQ,mBAAmB,gBAAgB,UAAS;;;;;;wBCQxF,SAAS,gBAAgB,eAAe;;;;;wBAaxC,cAAc,WAAW,gBAAc;;qBAO1C;;UAGI;WACN;WACA;;;;;;wBAOK,OAAO,WAAW,WAAW,aAAkB;;UAc9C;;WAEN;;WAEA;;WAEA;;;;;;;wBAQK,KAAK,4BAA4B,iBAAe;UAa/C;;WAEN;;WAEA;;WAEA,aAAa;;UAGP;;WAEN;;WAEA;WACA;;;;;;wBAOK,kBAAkB,8BAA8B,6BAA6B,UAAS,qBAA0B;;wBCtHhH,MAAM;;;;;wBAgBN,SAAS,sBAAsB;;qBAmBlC;;;;;;wBAQG,WAAW,sBAAsB,sBAAsB;;UC1BtD;WACN;WACA;;WAEA;;WAEA;;;;;;;;;;wBAWK,eAAe,2BAA2B,iBAAe;;UAqBxD;WACN;WACA;;WAEA;;;;;;;wBAQK,iBAAiB,WAAW,WAAW,iBAAe;;;;;;wBA2BtD,yBAAyB,mBAAmB,WAAW,iBAAe;UClGrE;;WAEN;;WAEA;;;;;;wBAOK,WAAW,2BAA2B,UAAS;UAM9C;;WAEN;;WAEA;;WAEA;;;UAIM;WACN;WACA;;WAEA;;WAEA;;UAGM;;WAEN;WACA;;WAEA;;WAEA;;WAEA;;WAEA,QAAQ;;WAER;;WAEA;;WAEA;WACA,cAAc;;WAEd;WACA,cAAc;;;;;;;;wBAST,cAAc,2BAA2B,UAAS,iBAAsB;;UA6CvE;WACN;WACA;;;wBASK,MAAM,oBAAoB;;UAQzB;WACN;WACA;WACA;;WAEA;;WAEA,UAAU;;;wBAIL,YAAY,oBAAoB,aAAa"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/describe.ts","../src/regression.ts","../src/bootstrap.ts","../src/ridge.ts","../src/response.ts","../src/response-parse.ts","../src/response-fit.ts","../src/tests.ts","../src/rank.ts","../src/discrete.ts","../src/compare.ts"],"mappings":"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"}