Dataset Statistics¶
Statistics computed once from a dataset, at config build time.
A loss that needs the class balance should receive it as a constant, not iterate the dataset itself: the balance of a fixed training set never changes, and a loss that walks the data on construction couples itself to one dataset layout. Compute the numbers here and hand them over::
class_weights:
_target: srforge.dataset.stats.get_class_weights
params:
dataset: ${ref:dataset.training}
field: label
num_classes: 2
criterion:
_target: srforge.metrics.classification.CrossEntropy
params:
class_weights: ${ref:class_weights}
class_counts(dataset, field: str = 'target', num_classes: int = 2, *, ignore_index: Optional[int] = None, mask_field: Optional[str] = None) -> torch.Tensor
¶
How many elements of each class field holds across dataset.
Reads every entry once, with the dataset's transforms applied — so a transform that turns the raw label into class indices (thresholding a depth map, say) runs before counting.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dataset
|
Anything with |
required | |
field
|
str
|
The entry key holding the labels: class indices, integer or
integer-valued floats (a 0/1 float mask counts as two classes).
The same key the loss's |
'target'
|
num_classes
|
int
|
Number of classes; indices must lie in
|
2
|
ignore_index
|
Optional[int]
|
A label value left out of the counts (e.g. 255 for "unlabelled"). |
None
|
mask_field
|
Optional[str]
|
Optional entry key of a validity mask; elements where it
is 0 are left out, as |
None
|
Returns:
| Type | Description |
|---|---|
Tensor
|
A float tensor of |
Raises:
| Type | Description |
|---|---|
KeyError
|
An entry has no field (or mask_field). |
ValueError
|
A label is not an integer, or lies outside the classes. |
get_class_weights(dataset, field: str = 'target', num_classes: int = 2, ignore_index: Optional[int] = None, scheme: str = 'inverse_freq', *, mask_field: Optional[str] = None) -> List[float]
¶
Class-balancing weights for CrossEntropy(class_weights=...).
Counts the classes once (see :func:class_counts) and turns the counts
into one weight per class, in class order:
================== =============================== ====================
scheme weight of class c effect
================== =============================== ====================
inverse_freq n / (num_classes · n_c) rare classes weigh
(default) more; balanced data
gives all 1.0
proportional num_classes · n_c / n frequent classes
weigh more
================== =============================== ====================
Both give 1.0 to every class on perfectly balanced data. For a yes/no
map the result is [negative, positive], which is also what
BinaryCrossEntropy(class_weights=...) takes.
A class that never occurs is counted as occurring once, with a warning: its weight never multiplies anything in training, but an infinite one would still poison the arithmetic.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dataset
|
The dataset to count — usually the training set, as
|
required | |
field
|
str
|
The entry key holding the labels. |
'target'
|
num_classes
|
int
|
Number of classes. |
2
|
ignore_index
|
Optional[int]
|
A label value left out of the counts. |
None
|
scheme
|
str
|
|
'inverse_freq'
|
mask_field
|
Optional[str]
|
Optional entry key of a validity mask. |
None
|
Returns:
| Type | Description |
|---|---|
List[float]
|
|