Skip to content

Commit

Permalink
Merge pull request #64 from NorskRegnesentral/add-Poisson-cost
Browse files Browse the repository at this point in the history
Add PoissonCost: Log likelihood of the Poisson distribution, evaluated at the MLE rate
  • Loading branch information
Tveten authored Mar 10, 2025
2 parents 5de5362 + d62aa25 commit e84d309
Show file tree
Hide file tree
Showing 12 changed files with 638 additions and 37 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# UV Lock file:
uv.lock

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down
24 changes: 12 additions & 12 deletions skchange/anomaly_scores/tests/test_from_cost.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
to_local_anomaly_score,
to_saving,
)
from skchange.costs import COSTS, BaseCost
from skchange.costs import ALL_COSTS, COSTS, BaseCost
from skchange.costs.tests.test_all_costs import find_fixed_param_combination


@pytest.mark.parametrize("cost_class", COSTS)
@pytest.mark.parametrize("cost_class", ALL_COSTS)
def test_saving_init(cost_class):
param = find_fixed_param_combination(cost_class)
baseline_cost = cost_class().set_params(**param)
Expand All @@ -22,7 +22,7 @@ def test_saving_init(cost_class):


@pytest.mark.parametrize("cost_class", COSTS)
def test_saving_min_size(cost_class):
def test_saving_min_size(cost_class: type[BaseCost]):
param = find_fixed_param_combination(cost_class)
cost = cost_class().set_params(**param)
saving = Saving(baseline_cost=cost)
Expand All @@ -35,7 +35,7 @@ def test_saving_min_size(cost_class):


@pytest.mark.parametrize("cost_class", COSTS)
def test_saving_fit(cost_class):
def test_saving_fit(cost_class: type[BaseCost]):
param = find_fixed_param_combination(cost_class)
cost = cost_class().set_params(**param)

Expand All @@ -47,7 +47,7 @@ def test_saving_fit(cost_class):


@pytest.mark.parametrize("cost_class", COSTS)
def test_saving_evaluate(cost_class):
def test_saving_evaluate(cost_class: type[BaseCost]):
param = find_fixed_param_combination(cost_class)
cost = cost_class().set_params(**param)

Expand All @@ -59,8 +59,8 @@ def test_saving_evaluate(cost_class):
assert savings.shape == (3, 1)


@pytest.mark.parametrize("cost_class", COSTS)
def test_to_saving_raises_with_no_param_set(cost_class):
@pytest.mark.parametrize("cost_class", ALL_COSTS)
def test_to_saving_raises_with_no_param_set(cost_class: type[BaseCost]):
"""Test that to_saving raises ValueError with BaseCost that has no param set."""
with pytest.raises(
ValueError, match="The baseline cost must have fixed parameters"
Expand All @@ -84,17 +84,17 @@ def test_to_saving_error():
to_saving("invalid_evaluator")


@pytest.mark.parametrize("cost_class", COSTS)
def test_to_local_anomaly_score_with_base_cost(cost_class):
@pytest.mark.parametrize("cost_class", ALL_COSTS)
def test_to_local_anomaly_score_with_base_cost(cost_class: type[BaseCost]):
param = find_fixed_param_combination(cost_class)
cost = cost_class().set_params(**param)
local_anomaly_score = to_local_anomaly_score(cost)
assert isinstance(local_anomaly_score, LocalAnomalyScore)
assert local_anomaly_score.cost == cost


@pytest.mark.parametrize("cost_class", COSTS)
def test_to_local_anomaly_score_with_local_anomaly_score(cost_class):
@pytest.mark.parametrize("cost_class", ALL_COSTS)
def test_to_local_anomaly_score_with_local_anomaly_score(cost_class: type[BaseCost]):
param = find_fixed_param_combination(cost_class)
cost = cost_class().set_params(**param)
local_anomaly_score_instance = LocalAnomalyScore(cost=cost)
Expand All @@ -103,7 +103,7 @@ def test_to_local_anomaly_score_with_local_anomaly_score(cost_class):


@pytest.mark.parametrize("cost_class", COSTS)
def test_local_anomaly_score_evaluate(cost_class):
def test_local_anomaly_score_evaluate(cost_class: type[BaseCost]):
param = find_fixed_param_combination(cost_class)
cost = cost_class().set_params(**param)
local_anomaly_score = LocalAnomalyScore(cost=cost)
Expand Down
4 changes: 2 additions & 2 deletions skchange/change_scores/tests/test_from_cost.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import pytest

from skchange.change_scores.from_cost import ChangeScore, to_change_score
from skchange.costs import COSTS
from skchange.costs import ALL_COSTS, COSTS


@pytest.mark.parametrize("cost_class", COSTS)
Expand All @@ -16,7 +16,7 @@ def test_change_score_with_costs(cost_class):
assert scores.shape == (1, 1)


@pytest.mark.parametrize("evaluator", COSTS)
@pytest.mark.parametrize("evaluator", ALL_COSTS)
def test_to_change_score(evaluator):
cost_instance = evaluator()
change_score = to_change_score(cost_instance)
Expand Down
8 changes: 7 additions & 1 deletion skchange/costs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from skchange.costs.laplace_cost import LaplaceCost
from skchange.costs.multivariate_gaussian_cost import MultivariateGaussianCost
from skchange.costs.multivariate_t_cost import MultivariateTCost
from skchange.costs.poisson_cost import PoissonCost

BASE_COSTS = [
BaseCost,
Expand All @@ -19,5 +20,10 @@
L1Cost,
L2Cost,
]
INTEGER_COSTS = [
PoissonCost,
]

ALL_COSTS = COSTS + INTEGER_COSTS

__all__ = BASE_COSTS + COSTS
__all__ = BASE_COSTS + COSTS + INTEGER_COSTS
9 changes: 7 additions & 2 deletions skchange/costs/laplace_cost.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@
import numpy as np

from skchange.costs import BaseCost
from skchange.costs.utils import MeanType, VarType, check_mean, check_univariate_scale
from skchange.costs.utils import (
MeanType,
VarType,
check_mean,
check_non_negative_parameter,
)
from skchange.utils.numba import njit
from skchange.utils.numba.stats import col_median
from skchange.utils.validation.enums import EvaluationType
Expand Down Expand Up @@ -232,7 +237,7 @@ def _check_fixed_param(
if not isinstance(param, tuple) or len(param) != 2:
raise ValueError("Fixed Laplace parameters must be (location, scale).")
means = check_mean(param[0], X)
scales = check_univariate_scale(param[1], X)
scales = check_non_negative_parameter(param[1], X)
return means, scales

@property
Expand Down
Loading

0 comments on commit e84d309

Please sign in to comment.