Source code for optimal_cutoffs.bayes
"""Bayes-optimal decision making.
Clean interface for cost-based optimization without the complexity
of the original BayesOptimal class hierarchy.
"""
import numpy as np
from numpy.typing import NDArray
from ..bayes_core import BayesOptimal, UtilitySpec
from ..core import OptimizationResult
[docs]
def threshold(cost_fp: float, cost_fn: float, *, prior: float | None = None) -> float:
"""Compute binary Bayes-optimal threshold from costs.
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)
prior : float, optional
Prior probability of positive class. If None, assumes 0.5.
Returns
-------
float
Optimal threshold
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)
"""
from ..bayes_core import bayes_optimal_threshold
return bayes_optimal_threshold(cost_fp, cost_fn).thresholds[0]
[docs]
def thresholds_from_costs(
fp_costs: NDArray | list[float], fn_costs: NDArray | list[float], **kwargs
) -> np.ndarray:
"""Compute per-class Bayes-optimal thresholds from OvR costs.
Parameters
----------
fp_costs : array-like
False positive costs per class
fn_costs : array-like
False negative costs per class
Returns
-------
np.ndarray
Per-class optimal thresholds
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)
"""
from ..bayes_core import bayes_thresholds_from_costs
return bayes_thresholds_from_costs(fp_costs, fn_costs, **kwargs).thresholds
[docs]
def policy(cost_matrix: NDArray) -> OptimizationResult:
"""Create Bayes-optimal decision policy from cost matrix.
This is for general decision making where thresholds aren't
the right abstraction.
Parameters
----------
cost_matrix : array-like
Cost matrix (n_classes, n_actions)
cost_matrix[i, j] = cost of taking action j when true class is i
Returns
-------
OptimizationResult
Policy with .predict() method (no .thresholds)
Examples
--------
>>> costs = [[0, 1, 10], [5, 0, 1], [50, 10, 0]]
>>> policy = policy(costs)
>>> decisions = policy.predict(probabilities)
"""
from ..bayes_core import bayes_optimal_decisions
return bayes_optimal_decisions(
probabilities=None, # Will be provided later via .predict()
cost_matrix=cost_matrix,
)
# Note: BayesOptimal and UtilitySpec imported at top for power users
__all__ = [
"threshold",
"thresholds_from_costs",
"policy",
"BayesOptimal",
"UtilitySpec",
]