Skip to contents

One fold map read by everything that scores, and the cells a score is defined on, computed with no model involved.

cv()

cv(v: int = 10, seed: int = 1, strata: int = 5)

Hold out single targets, balanced within equal-count strata of the response.

grouped_cv()

grouped_cv(group, v: int = 10, seed: int = 1)

Keep every target sharing a value of the group column in one fold.

It is what repeated targets on the same unit need: two visits to a plot a fortnight apart are not two independent held-out units, and splitting them across folds scores a model on a unit it has already read.

Resampling

Resampling(kind, v, seed, strata, group, folds)

How the targets are split, named but not yet drawn.

Attributes:

  • kind - str
  • v - int
  • seed - int
  • strata - int
  • group - str | None
  • folds - object

as_resampling()

as_resampling(x)

A resampling spec, or a fold map somebody else built, read as a spec that returns it.

resolve_folds()

resolve_folds(resampling, y, targets, spec)

Draw the fold map a resampling spec names, in the row order of the response.

fold_map()

fold_map(y: Response, v: int = 10, seed: int = 1, strata: int = 5, by=None, group=None)

Assign units to folds, balanced within equal-count strata of a stratifying value.

group keeps every unit sharing a value in one fold, which is what repeated targets on the same physical unit need: two visits to a plot are not two independent held-out units. The deal is then made over the groups rather than over the units, and a group carries the mean of the stratifying value of the units in it.

The stream is numpy’s, so a map built here is not the map the R side builds from the same seed. Where both languages must see identical splits, build the map once, write it with write_folds and read it in the other with read_folds.

scorable_cells()

scorable_cells(y: Response, folds)

Which cells admit a score, from the response and the fold map alone.

A cell needs both classes among the held-out units and both classes among the units a model is fitted on. Computing the mask without a model is what lets every arm be restricted to the same cells, so their means share a denominator and every paired difference runs on matched cells.

align_folds()

align_folds(folds, units)

A fold map reaches the fitting path as an integer vector in the row order of the representation, whether it arrived as a Folds, a mapping of unit to fold, or a bare vector already in that order.

as_response()

as_response(y)

The response reaches everything downstream as a Response, whether it arrived as one, as a mapping of variable name to values, or as a two-dimensional array with no names at all.

Response

Response(values, units, variables)

A [unit, variable] matrix of observed values, with the units named.

Attributes:

  • values - np.ndarray
  • units - tuple[str, …]
  • variables - tuple[str, …]

from_columns()

from_columns(cls, data, id: str, variables=None)

A response from a table of one unit column and one column per variable.

take_units()

take_units(self, index)

The response restricted to a subset of its units, in the order given.

take_variables()

take_variables(self, index)

The response restricted to a subset of its variables, in the order given.

A learner covering one response at a time is handed them through this, so the matrix a candidate emits is assembled from the same names each part was fitted on.

align()

align(self, units)

Put the response into the row order of a representation, by unit and never by position.

check_presence_absence()

check_presence_absence(self)

Error unless every value is 0 or 1 and none is missing.

Folds

Folds(fold, units, grouped, group)

Which fold each unit is held out in, named by unit.

Named rather than positional, because a fold map is aligned to a representation by unit and never by row: two tables of the same height are not two tables in the same order.

Attributes:

  • fold - np.ndarray
  • units - tuple[str, …]
  • grouped - bool
  • group - tuple[str, …] | None

v

How many folds the map holds.

coerce()

coerce(cls, x, units=None)

A Folds, a mapping of unit to fold, or a bare vector read in units order.

align()

align(self, units)

Put the map into the row order of a representation, by unit and never by position.

as_dict()

as_dict(self)

The map as unit to fold.

Cells

Cells(variable, fold, n_occ, pres_train, abs_train, pres_test, abs_test, scorable)

Which (variable, fold) cells admit a score, and the counts that decided it.

Attributes:

  • variable - np.ndarray
  • fold - np.ndarray
  • n_occ - np.ndarray
  • pres_train - np.ndarray
  • abs_train - np.ndarray
  • pres_test - np.ndarray
  • abs_test - np.ndarray
  • scorable - np.ndarray

is_scorable()

is_scorable(self, variable: str, fold: int)

Whether one (variable, fold) cell admits a score.

PRESENCE_ABSENCE

PRESENCE_ABSENCE = dict(prepare=lambda y: as_response(y).check_presence_absence(), activation='sigmoid', loss='binary_cross_entropy', metric='tss', weights=positive_weights, cells=lambda y, folds: scorable_cells(y, folds))

positive_weights()

positive_weights(y, cap: float = 50.0)

Case weights that balance a rare response.

The weight every learner that ships fits a presence-absence response under: each presence of a response weighs the ratio of absences to presences among the units handed in, capped, and each absence weighs one. A response with a presence in one target of a hundred is otherwise fitted away by any learner that minimises a mean loss.

The weights are the response head’s: the shipped presence-absence head carries this function as its weights, and a head registered with weights=lambda y: positive_weights(y, cap=20) weights every learner by that cap instead. A head without weights is fitted unweighted. Returns a [unit, variable] array of case weights, one per cell of y.