Source code for mllm_shap.estimation.estimands.shapley

"""Shapley estimand aggregation.

@domain estimation
@see [[knowledge/architecture/estimation]]
"""

from collections.abc import Sequence
from typing import TYPE_CHECKING, ClassVar

from ...domain.estimands import Estimand
from ...protocols.plugin import PluginOptions
from ._weights import (
    aggregate_from_marginals,
    aggregate_shapley_exact,
    is_complete_characteristic_table,
    shapley_weight,
)

if TYPE_CHECKING:
    from ...plugins.context import PluginContext


[docs] class ShapleyAggregator: """Aggregate coalition samples with Shapley coalition weights.""" options_model: ClassVar[type[PluginOptions]] = PluginOptions """Accepts no ``explanation.plugin_options``.""" def __init__(self, context: "PluginContext | None" = None) -> None: """Accept the plugin context; this plugin reads no settings from it.""" _ = context @property def estimand(self) -> Estimand: """Return the Shapley estimand label.""" return Estimand.SHAPLEY
[docs] def coalition_weight(self, coalition_size: int, num_players: int) -> float: """Return Shapley coalition weight k!(n-k-1)!/n!.""" return shapley_weight(coalition_size, num_players)
[docs] def aggregate( self, masks: Sequence[Sequence[bool]], payoffs: Sequence[float], ) -> list[float]: """Aggregate coalition samples into Shapley values.""" if is_complete_characteristic_table(masks): return aggregate_shapley_exact(masks, payoffs) return aggregate_from_marginals(masks, payoffs, weight_fn=shapley_weight)