Core Functions

This module contains the main optimization functions that form the core of the library.

Main Optimization Functions

optimal_cutoffs.api.optimize_thresholds(y_true, y_score, *, metric='f1', task=Task.AUTO, average=Average.AUTO, method='auto', mode='empirical', sample_weight=None, utility=None, fp_costs=None, fn_costs=None, comparison='>', tolerance=1e-10, **kwargs)[source]

Find optimal thresholds for classification problems.

This is THE canonical entry point for threshold optimization. Auto-detects problem type and selects appropriate algorithms.

Parameters:
  • y_true (ArrayLike) – True labels

  • y_score (ArrayLike) – Predicted scores/probabilities - Binary: 1D array of scores - Multiclass: 2D array (n_samples, n_classes) - Multilabel: 2D array (n_samples, n_labels)

  • metric (str) – Metric to optimize (“f1”, “precision”, “recall”, “accuracy”, etc.)

  • task (Task) – Problem type. AUTO infers from data shape and probability sums.

  • average (Average) – Averaging strategy for multiclass/multilabel. AUTO selects sensible default.

  • method (str) – Optimization algorithm. AUTO selects best method per task+metric.

  • mode (str) – “empirical” (standard) or “expected” (requires calibrated probabilities)

  • sample_weight (ArrayLike | None) – Sample weights

  • utility (Mapping[str, float | int] | None) – Utility specification for binary Bayes optimization with keys “tp”, “tn”, “fp”, “fn”. Required when mode=”bayes” for binary classification.

  • fp_costs (ArrayLike | None) – Per-class false positive costs for multiclass Bayes optimization. Required when mode=”bayes” for multiclass classification.

  • fn_costs (ArrayLike | None) – Per-class false negative costs for multiclass Bayes optimization. Required when mode=”bayes” for multiclass classification.

  • comparison (str) – Comparison operator for threshold. Must be “>” or “>=”.

  • tolerance (float) – Numerical tolerance for optimization.

  • **kwargs – Additional keyword arguments passed to optimization algorithms.

Returns:

Result with .thresholds, .predict(), and explanation of auto-selections

Raises:
  • TypeError – If ‘bayes’ is passed as a keyword argument (deprecated).

  • ValueError – If mode=’bayes’ requires utility parameter but none provided. If comparison operator is not ‘>’ or ‘>=’. If mode=’expected’ with unsupported metric. If method is deprecated (‘dinkelbach’, ‘smart_brute’). If unknown metric name is provided. If y_true required for empirical mode but not provided.

Return type:

OptimizationResult

Examples

>>> # Binary classification - simple case
>>> result = optimize_thresholds(y_true, y_scores, metric="f1")
>>> print(f"Optimal threshold: {result.threshold}")
>>> # Multiclass classification
>>> result = optimize_thresholds(y_true, y_probs, metric="f1")
>>> print(f"Per-class thresholds: {result.thresholds}")
>>> print(f"Task inferred as: {result.task.value}")
>>> # Explicit control when needed
>>> result = optimize_thresholds(
...     y_true, y_probs,
...     metric="precision",
...     task=Task.MULTICLASS,
...     average=Average.MACRO
... )
optimal_cutoffs.api.optimize_decisions(y_score, cost_matrix, **kwargs)[source]

Find optimal decisions using cost matrix (no thresholds).

For problems where thresholds aren’t the right abstraction. Uses Bayes-optimal decision rule: argmin_action E[cost | probabilities].

Parameters:
  • y_score (ArrayLike) – Predicted probabilities (n_samples, n_classes)

  • cost_matrix (ArrayLike) – Cost matrix (n_classes, n_actions) or (n_classes, n_classes) cost_matrix[i, j] = cost of predicting action j when true class is i

  • **kwargs – Additional keyword arguments passed to the Bayes optimal decision function.

Returns:

Result with .predict() function (no .thresholds)

Return type:

OptimizationResult

Examples

>>> # Cost matrix: rows=true class, cols=predicted class
>>> costs = [[0, 1, 10], [5, 0, 1], [50, 10, 0]]  # FN costs 5x more than FP
>>> result = optimize_decisions(y_probs, costs)
>>> y_pred = result.predict(y_probs_test)

Binary Classification

optimal_cutoffs.binary.optimize_f1_binary(y_true, y_score, *, beta=1.0, sample_weight=None, comparison='>')[source]

Optimize F-beta score for binary classification using sort-and-scan.

Uses the O(n log n) sort-and-scan algorithm exploiting the piecewise structure of F-beta metrics. This finds the exact optimal threshold.

Parameters:
  • y_true (ArrayLike) – True binary labels in {0, 1}. Shape: (n_samples,)

  • y_score (ArrayLike) – Predicted probabilities for positive class in [0, 1]. Shape: (n_samples,)

  • beta (float) – F-beta parameter. beta=1 gives F1 score

  • sample_weight (ArrayLike | None) – Sample weights. Shape: (n_samples,)

  • comparison (str) – Comparison operator for threshold. Must be “>” or “>=”

Returns:

Result with optimal threshold, F-beta score, and predict function

Return type:

OptimizationResult

Examples

>>> y_true = [0, 1, 1, 0, 1]
>>> y_score = [0.2, 0.8, 0.7, 0.3, 0.9]
>>> result = optimize_f1_binary(y_true, y_score)
>>> result.threshold
0.5
>>> result.score  # F1 score at optimal threshold
0.8
optimal_cutoffs.binary.optimize_metric_binary(y_true, y_score, *, metric='f1', method='auto', sample_weight=None, comparison='>', tolerance=1e-10)[source]

General binary metric optimization with automatic method selection.

Automatically selects the best optimization algorithm based on metric properties and data characteristics.

Parameters:
  • y_true (ArrayLike) – True binary labels in {0, 1}. Shape: (n_samples,)

  • y_score (ArrayLike) – Predicted probabilities for positive class in [0, 1]. Shape: (n_samples,)

  • metric (str) – Metric to optimize (“f1”, “precision”, “recall”, “accuracy”, etc.)

  • method (str) – Optimization method: - “auto”: Automatically select best method - “sort_scan”: O(n log n) sort-and-scan (exact for piecewise metrics) - “minimize”: Scipy optimization - “gradient”: Simple gradient ascent

  • sample_weight (ArrayLike | None) – Sample weights. Shape: (n_samples,)

  • comparison (str) – Comparison operator for threshold. Must be “>” or “>=”

  • tolerance (float) – Numerical tolerance for optimization

Returns:

Result with optimal threshold, metric score, and predict function

Raises:

ValueError – If method is unknown or not supported.

Return type:

OptimizationResult

Examples

>>> result = optimize_metric_binary(y_true, y_score, metric="precision")
>>> result = optimize_metric_binary(
...     y_true, y_score, metric="f1", method="sort_scan"
... )
optimal_cutoffs.binary.optimize_utility_binary(y_true, y_score, *, utility, sample_weight=None)[source]

Optimize binary classification using utility/cost specification.

Computes the Bayes-optimal threshold using the closed-form formula: τ* = (u_tn - u_fp) / [(u_tp - u_fn) + (u_tn - u_fp)]

This is exact and runs in O(1) time.

Parameters:
  • y_true (ArrayLike | None) – True binary labels. Can be None for pure Bayes optimization. Shape: (n_samples,)

  • y_score (ArrayLike) – Predicted probabilities for positive class in [0, 1]. Shape: (n_samples,)

  • utility (dict[str, float]) – Utility specification with keys “tp”, “tn”, “fp”, “fn”

  • sample_weight (ArrayLike | None) – Sample weights (affects expected utility computation). Shape: (n_samples,)

Returns:

Result with optimal threshold, expected utility, and predict function

Raises:

ValueError – If probabilities are not in the range [0, 1] for utility optimization.

Return type:

OptimizationResult

Examples

>>> # FN costs 5x more than FP
>>> utility = {"tp": 10, "tn": 1, "fp": -1, "fn": -5}
>>> result = optimize_utility_binary(None, y_score, utility=utility)
>>> result.threshold  # (u_tn - u_fp) / [(u_tp - u_fn) + (u_tn - u_fp)] = 2/17
0.11764705882352941

Multiclass Classification

optimal_cutoffs.multiclass.optimize_multiclass(y_true, y_score, *, metric='f1', average='macro', method='auto', sample_weight=None, comparison='>', tolerance=1e-10)[source]

General multiclass threshold optimization with automatic method selection.

Routes to appropriate algorithm based on averaging strategy and method:

  • Macro + auto/coord_ascent: Margin rule with coordinate ascent (single-label)

  • Macro + independent: Independent OvR optimization (can predict multiple)

  • Micro: Single threshold optimization (single-label)

Parameters:
  • y_true (ArrayLike) – True class labels in {0, 1, …, K-1}. Shape: (n_samples,).

  • y_score (ArrayLike) – Predicted probabilities for each class. Shape: (n_samples, n_classes).

  • metric (str) – Metric to optimize. Defaults to “f1”.

  • average (str) – Averaging strategy. One of {“macro”, “micro”}. Defaults to “macro”.

  • method (str) – Optimization method, defaults to “auto”: - “auto”: For macro, uses coord_ascent (margin rule) - “coord_ascent”: Margin rule with coordinate ascent - “independent”: Independent per-class optimization (OvR)

  • sample_weight (ArrayLike | None) – Sample weights. Shape: (n_samples,). Optional.

  • comparison (str) – Comparison operator. Defaults to “>”.

  • tolerance (float) – Numerical tolerance. Defaults to 1e-10.

Returns:

Result with optimal thresholds and prediction function

Raises:

ValueError – If average or method is not one of the supported values.

Return type:

OptimizationResult

Examples

>>> # Margin rule (single-label, coordinate ascent)
>>> result = optimize_multiclass(y_true, y_score, method="coord_ascent")
>>>
>>> # Independent optimization (can predict multiple classes)
>>> result = optimize_multiclass(y_true, y_score, method="independent")
>>>
>>> # Micro averaging (single threshold)
>>> result = optimize_multiclass(y_true, y_score, average="micro")
optimal_cutoffs.multiclass.optimize_ovr_independent(y_true, y_score, *, metric='f1', method='auto', sample_weight=None, comparison='>', tolerance=1e-10)[source]

Optimize multiclass metrics using independent per-class thresholds (OvR).

Treats each class as an independent binary problem (class vs rest). This does NOT enforce single-label predictions - can predict 0, 1, or multiple classes. Use this for macro-averaged metrics when you want exact optimization per class.

Decision rule: ŷ_j = 1 if p_j ≥ τ_j (independent for each class)

Parameters:
  • y_true (ArrayLike) – True class labels in {0, 1, …, K-1}. Shape: (n_samples,).

  • y_score (ArrayLike) – Predicted probabilities for each class. Shape: (n_samples, n_classes).

  • metric (str) – Metric to optimize per class. Defaults to “f1”.

  • method (str) – Binary optimization method. Defaults to “auto”.

  • sample_weight (ArrayLike | None) – Sample weights. Shape: (n_samples,). Optional.

  • comparison (str) – Comparison operator. Defaults to “>”.

  • tolerance (float) – Numerical tolerance. Defaults to 1e-10.

Returns:

Result with per-class thresholds optimized independently

Return type:

OptimizationResult

Examples

>>> y_true = [0, 1, 2, 0, 1]
>>> y_score = [[0.7, 0.2, 0.1], [0.1, 0.8, 0.1], [0.1, 0.1, 0.8], ...]
>>> result = optimize_ovr_independent(y_true, y_score, metric="f1")
>>> predictions = result.predict(y_score)  # Can predict multiple classes
optimal_cutoffs.multiclass.optimize_ovr_margin(y_true, y_score, *, metric='f1', max_iter=30, sample_weight=None, comparison='>', tolerance=1e-10)[source]

Optimize multiclass metrics using margin rule with coordinate ascent.

Uses margin-based prediction: ŷ = argmax_j (p_j - τ_j) This ensures exactly one class is predicted per sample (single-label).

Thresholds are coupled because changing τ_j affects which samples are assigned to class j, which affects confusion matrices for all classes. Uses coordinate ascent to find local optimum.

Parameters:
  • y_true (ArrayLike) – True class labels in {0, 1, …, K-1}. Shape: (n_samples,).

  • y_score (ArrayLike) – Predicted probabilities for each class. Shape: (n_samples, n_classes).

  • metric (str) – Metric to optimize (currently supports “f1” only). Defaults to “f1”.

  • max_iter (int) – Maximum coordinate ascent iterations. Defaults to 30.

  • sample_weight (ArrayLike | None) – Sample weights. Shape: (n_samples,). Optional.

  • comparison (str) – Comparison operator (only “>” supported for margin rule). Defaults to “>”.

  • tolerance (float) – Convergence tolerance. Defaults to 1e-12.

Returns:

Result with per-class thresholds optimized via coordinate ascent

Raises:

NotImplementedError – If metric is not “f1” or comparison is not “>”.

Return type:

OptimizationResult

Examples

>>> result = optimize_ovr_margin(y_true, y_score, metric="f1")
>>> predictions = result.predict(y_score)  # Exactly one class per sample

Notes

The margin rule is Bayes-optimal when costs have OvR structure: C(i,j) = -r_j if i=j, else c_j

In this case, optimal thresholds are: τ_j = c_j/(c_j + r_j) (closed form!)

optimal_cutoffs.multiclass.optimize_micro_multiclass(y_true, y_score, *, metric='f1', method='auto', sample_weight=None, comparison='>', tolerance=1e-10)[source]

Optimize micro-averaged multiclass metrics using single threshold.

For micro averaging, we use a single threshold applied to all classes, then predict the class with highest valid probability. This reduces to a single binary optimization problem on flattened data.

Decision rule: ŷ = argmax{j: p_j ≥ τ} p_j (or argmax p_j if none valid)

Parameters:
  • y_true (ArrayLike) – True class labels in {0, 1, …, K-1}. Shape: (n_samples,).

  • y_score (ArrayLike) – Predicted probabilities for each class. Shape: (n_samples, n_classes).

  • metric (str) – Metric to optimize. Defaults to “f1”.

  • method (str) – Binary optimization method. Defaults to “auto”.

  • sample_weight (ArrayLike | None) – Sample weights. Shape: (n_samples,). Optional.

  • comparison (str) – Comparison operator. Defaults to “>”.

  • tolerance (float) – Numerical tolerance. Defaults to 1e-10.

Returns:

Result with single threshold applied to all classes

Return type:

OptimizationResult

Examples

>>> result = optimize_micro_multiclass(y_true, y_score, metric="f1")
>>> result.thresholds  # Same threshold for all classes
[0.3, 0.3, 0.3]

Multilabel Classification

optimal_cutoffs.multilabel.optimize_multilabel(y_true, y_score, *, metric='f1', average='macro', method='auto', sample_weight=None, comparison='>', tolerance=1e-10)[source]

General multi-label threshold optimization with automatic method selection.

Routes to appropriate algorithm based on averaging strategy: - Macro: Independent optimization per label (exact, O(K·n log n)) - Micro: Coordinate ascent for coupled thresholds (local optimum)

Parameters:
  • y_true (ArrayLike) – True multi-label binary matrix. Shape: (n_samples, n_labels).

  • y_score (ArrayLike) – Predicted probabilities for each label. Shape: (n_samples, n_labels).

  • metric (str) – Metric to optimize. Defaults to “f1”.

  • average (str) – Averaging strategy. One of {“macro”, “micro”}. Defaults to “macro”.

  • method (str) – Optimization method (passed to binary optimizer for macro). Defaults to “auto”.

  • sample_weight (ArrayLike | None) – Sample weights. Shape: (n_samples,). Optional.

  • comparison (str) – Comparison operator. Defaults to “>”.

  • tolerance (float) – Numerical tolerance. Defaults to 1e-10.

Returns:

Result with optimal thresholds and metric score

Raises:

ValueError – If average is not “macro” or “micro”.

Return type:

OptimizationResult

Examples

>>> # Independent per-label optimization
>>> result = optimize_multilabel(y_true, y_score, average="macro")
>>>
>>> # Coupled optimization for global metric
>>> result = optimize_multilabel(y_true, y_score, average="micro")
optimal_cutoffs.multilabel.optimize_macro_multilabel(y_true, y_score, *, metric='f1', method='auto', sample_weight=None, comparison='>', tolerance=1e-10)[source]

Optimize macro-averaged metrics for multi-label classification.

For macro averaging, each label is optimized independently: Macro-F1 = (1/K) Σ_j F1_j(τ_j)

Since each F1_j depends only on τ_j, we can optimize each threshold independently using binary optimization. This is exact and efficient.

Parameters:
  • y_true (ArrayLike) – True multi-label binary matrix. Shape: (n_samples, n_labels).

  • y_score (ArrayLike) – Predicted probabilities for each label. Shape: (n_samples, n_labels).

  • metric (str) – Metric to optimize per label (“f1”, “precision”, “recall”). Defaults to “f1”.

  • method (str) – Binary optimization method for each label. Defaults to “auto”.

  • sample_weight (ArrayLike | None) – Sample weights. Shape: (n_samples,). Optional.

  • comparison (str) – Comparison operator. Defaults to “>”.

  • tolerance (float) – Numerical tolerance. Defaults to 1e-10.

Returns:

Result with per-label thresholds and macro-averaged score

Raises:

ValueError – If labels or probabilities are not 2D, their shapes disagree, or the sample weights do not match the number of samples.

Return type:

OptimizationResult

Examples

>>> # 3 independent labels
>>> y_true = [[1, 0, 1], [0, 1, 0], [1, 1, 1]]
>>> y_score = [[0.8, 0.2, 0.9], [0.1, 0.7, 0.3], [0.9, 0.8, 0.7]]
>>> result = optimize_macro_multilabel(y_true, y_score, metric="f1")
>>> len(result.thresholds)  # One per label
3
optimal_cutoffs.multilabel.optimize_micro_multilabel(y_true, y_score, *, metric='f1', max_iter=30, sample_weight=None, comparison='>', tolerance=1e-10)[source]

Optimize micro-averaged metrics for multi-label classification.

For micro averaging, thresholds are coupled through global TP/FP/FN: Micro-F1 = 2·TP_total / (2·TP_total + FP_total + FN_total)

where TP_total = Σ_j TP_j(τ_j). Changing any τ_j affects the global metric, so we use coordinate ascent to optimize the coupled problem.

Parameters:
  • y_true (ArrayLike) – True multi-label binary matrix. Shape: (n_samples, n_labels).

  • y_score (ArrayLike) – Predicted probabilities for each label. Shape: (n_samples, n_labels).

  • metric (str) – Metric to optimize (“f1”, “precision”, “recall”). Defaults to “f1”.

  • max_iter (int) – Maximum coordinate ascent iterations. Defaults to 30.

  • sample_weight (ArrayLike | None) – Sample weights. Shape: (n_samples,). Optional.

  • comparison (str) – Comparison operator. Defaults to “>”.

  • tolerance (float) – Convergence tolerance. Defaults to 1e-12.

Returns:

Result with per-label thresholds optimized for micro averaging

Raises:

ValueError – If labels or probabilities are not 2D or their shapes disagree.

Return type:

OptimizationResult

Examples

>>> result = optimize_micro_multilabel(y_true, y_score, metric="f1")
>>> # Thresholds are coupled - changing one affects global metric

Bayes-Optimal Decisions

optimal_cutoffs.bayes.threshold(cost_fp, cost_fn, benefit_tp=0.0, benefit_tn=0.0)[source]

Compute binary Bayes-optimal threshold from costs and benefits.

Parameters:
  • cost_fp (float) – Cost of false positive (predicting positive when actually negative)

  • cost_fn (float) – Cost of false negative (predicting negative when actually positive)

  • benefit_tp (float) – Benefit of true positive (predicting positive correctly)

  • benefit_tn (float) – Benefit of true negative (predicting negative correctly)

Returns:

Optimal threshold τ* = (benefit_tn + cost_fp) / [(benefit_tp + cost_fn) + (benefit_tn + cost_fp)]

Return type:

float

Examples

>>> # FN costs 5x more than FP
>>> t = threshold(cost_fp=1.0, cost_fn=5.0)
>>> # Will be < 0.5 (more conservative, avoids costly false negatives)
optimal_cutoffs.bayes.thresholds_from_costs(fp_costs, fn_costs, **kwargs)[source]

Compute per-class Bayes-optimal thresholds from OvR costs.

Parameters:
  • fp_costs (NDArray | list[float]) – False positive costs per class

  • fn_costs (NDArray | list[float]) – False negative costs per class

  • **kwargs – Forwarded to bayes_thresholds_from_costs().

Returns:

Per-class optimal thresholds

Return type:

ndarray

Examples

>>> # Different costs per class
>>> fp_costs = [1.0, 2.0, 0.5]  # Class 1 FP costs 2x more
>>> fn_costs = [5.0, 1.0, 10.0] # Class 2 FN costs 10x more
>>> thresholds = thresholds_from_costs(fp_costs, fn_costs)
optimal_cutoffs.bayes.policy(cost_matrix)[source]

Create Bayes-optimal decision policy from cost matrix.

This is for general decision making where thresholds aren’t the right abstraction.

Parameters:

cost_matrix (NDArray) – Cost matrix (n_classes, n_actions) cost_matrix[i, j] = cost of taking action j when true class is i

Returns:

Policy with .predict() method (no .thresholds)

Return type:

OptimizationResult

Examples

>>> costs = [[0, 1, 10], [5, 0, 1], [50, 10, 0]]
>>> policy = policy(costs)
>>> decisions = policy.predict(probabilities)

Internal Functions

These functions are used internally but may be useful for advanced users:

Optimized O(n log n) sort-and-scan kernel for piecewise-constant metrics.

This module provides an exact optimizer for binary classification metrics that are piecewise-constant with respect to the decision threshold. The algorithm sorts predictions once and scans all n cuts in a single pass, achieving true O(n log n) complexity with vectorized operations.

Notes on require_proba:
  • If require_proba=True, inputs are validated to lie in [0, 1].

  • The returned threshold is usually in [0, 1]; however, in boundary or tie cases, we may nudge it by one floating-point ULP beyond the range to correctly realize strict inclusivity/exclusivity (e.g., to ensure “predict none” with ‘>=’ when max p == 1.0).

optimal_cutoffs.piecewise.optimal_threshold_sortscan(y_true, y_score, metric, *, sample_weight=None, inclusive=False, require_proba=True, tolerance=1e-10)[source]

Exact optimizer for piecewise-constant metrics using O(n log n) sort-and-scan.

Parameters:
  • y_true (Array) – Binary labels in {0, 1}. Shape: (n_samples,).

  • y_score (Array) – Predicted probabilities in [0, 1] or arbitrary scores if require_proba=False. Shape: (n_samples,).

  • metric (str | Callable[[Array, Array, Array, Array], Array]) – Metric name (e.g., “f1”, “precision”) or vectorized function. If string, automatically resolves to vectorized implementation. If callable: (tp_vec, tn_vec, fp_vec, fn_vec) -> score_vec.

  • sample_weight (Array | None) – Non-negative sample weights of shape (n_samples,). Optional.

  • inclusive (bool) – If True, use “>=”; if False, use “>”. Defaults to False.

  • require_proba (bool) – Validate inputs in [0, 1]. Threshold may be nudged by ±1 ULP outside [0,1] to exactly realize inclusivity/exclusivity in boundary/tie cases. Defaults to True.

  • tolerance (float) – Numerical tolerance for floating-point comparisons when computing threshold midpoints and handling ties between scores. Defaults to 1e-10.

Returns:

array([optimal_threshold]) scores : array([achieved_score]) predict : callable(probs) -> {0,1}^n metric : str, set to “piecewise_metric” n_classes : 2 diagnostics: dict with keys: - k_argmax: theoretical best cut index (0..n) from the sweep - k_realized: positives realized by the returned threshold - score_theoretical: score at k_argmax - score_actual: score achieved by the returned threshold - tie_discrepancy: abs(theoretical - actual) - inclusive: bool - require_proba: bool

Return type:

thresholds

Unified threshold optimization for binary and multiclass classification.

This module consolidates all threshold optimization functionality into a single, streamlined interface. It includes high-performance Numba kernels, multiple optimization algorithms, and support for both binary and multiclass problems.

Key features: - Fast Numba kernels with Python fallbacks - Binary and multiclass threshold optimization - Multiple algorithms: sort-scan, scipy, gradient, coordinate ascent - Sample weight support (including in coordinate ascent) - Direct functional API without over-engineered abstractions

optimal_cutoffs.optimize.fast_f1_score(tp, tn, fp, fn)[source]

Compute F1 score from confusion matrix.

Parameters:
Return type:

float

optimal_cutoffs.optimize.compute_confusion_matrix_weighted(labels, predictions, weights)[source]

Compute weighted confusion matrix elements (serial, race-free).

Parameters:
Return type:

tuple[float, float, float, float]

optimal_cutoffs.optimize.sort_scan_kernel(labels, scores, weights, inclusive)[source]

Numba sort-and-scan for F1. Honors inclusive operator at boundaries.

Note: weights must be a valid array (use np.ones for uniform weights).

Parameters:
Return type:

tuple[float, float]

optimal_cutoffs.optimize.compute_macro_f1(tp, fp, support)[source]

Compute macro F1 from per-class TP/FP and support (FN = support - TP).

Parameters:
Return type:

float

optimal_cutoffs.optimize.coordinate_ascent_kernel(y_true, probs, weights, max_iter, tol)[source]

Numba coordinate ascent for multiclass macro-F1 with sample weights.

Predict via argmax over (p - tau). We iteratively adjust one class’s threshold at a time by scanning the implied breakpoints for that class.

Note: weights must be a valid array (use np.ones for uniform weights).

Parameters:
Return type:

tuple[ndarray, float, ndarray]

optimal_cutoffs.optimize.optimize_sort_scan(labels, scores, metric, weights=None, operator='>=')[source]

Sort-and-scan optimization for piecewise-constant metrics.

Parameters:
Return type:

OptimizationResult

optimal_cutoffs.optimize.optimize_scipy(labels, scores, metric, weights=None, operator='>=', method='bounded', tol=1e-06)[source]

Scipy-based optimization for smooth metrics.

Parameters:
Return type:

OptimizationResult

optimal_cutoffs.optimize.optimize_gradient(labels, scores, metric, weights=None, operator='>=', learning_rate=0.01, max_iter=100, tol=1e-06)[source]

Simple gradient ascent optimization (use for smooth metrics).

Parameters:
Return type:

OptimizationResult

optimal_cutoffs.optimize.find_optimal_threshold_multiclass(true_labs, pred_prob, metric='f1', method='auto', average='macro', sample_weight=None, comparison='>', tolerance=1e-10)[source]

Find optimal per-class thresholds for multiclass classification.

Parameters:
Return type:

OptimizationResult

optimal_cutoffs.optimize.find_optimal_threshold(labels, scores, metric='f1', weights=None, strategy='auto', operator='>=', require_probability=True, tolerance=1e-10)[source]

Simple functional interface for binary threshold optimization.

Parameters:
Return type:

OptimizationResult