Estimation

Estimation algorithms for cooperative-game attribution.

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

Exact coalition enumeration estimator.

@domain estimation @see [[knowledge/architecture/estimation]] @tested-by [[tests/estimation/test_exact.py]]

class mllm_shap.estimation.exact.ExactEstimator(context: PluginContext | None = None)[source]

Bases: _SnapshotEstimator

Enumerate all coalitions and delegate attribution to an estimand plugin.

property name: str

Return the registered estimator identifier.

static num_coalitions(num_players: int) → int[source]

Return the number of coalitions evaluated by exact enumeration (2^n).

static iter_mask_ints(num_players: int) → Iterator[int][source]

Lazily yield every coalition bitmask from empty to grand.

static mask_int_to_present(mask_int: int, num_players: int) → tuple[bool, ...]

Decode a coalition bitmask into presence flags.

sample_masks(player_set: PlayerSet, budget_fraction: float, include_minimal_masks: bool, seed: int) → Iterator[CoalitionMask][source]

Yield every coalition mask including the empty and grand coalitions.

static iter_masks(player_set: PlayerSet) → Iterator[CoalitionMask][source]

Yield every coalition mask including the empty and grand coalitions.

bind_snapshot(snapshot: ConversationSnapshot) → None

Attach the conversation snapshot under explanation.

estimate_attributions(masks: Sequence[CoalitionMask], payoffs: Sequence[float], aggregator: EstimandAggregator) → list[float]

Aggregate coalition payoffs with the selected estimand plugin.

options_model

alias of PluginOptions

Monte Carlo coalition sampling estimator.

@domain estimation @see [[knowledge/architecture/estimation]] @tested-by [[tests/estimation/test_monte_carlo.py]]

class mllm_shap.estimation.monte_carlo.MonteCarloEstimator(context: PluginContext | None = None)[source]

Bases: _SnapshotEstimator

Sample random coalitions and delegate attribution to an estimand plugin.

property name: str

Return the registered estimator identifier.

sample_masks(player_set: PlayerSet, budget_fraction: float, include_minimal_masks: bool, seed: int) → Iterator[CoalitionMask][source]

Yield the grand and empty coalitions, then random ones, up to the budget.

bind_snapshot(snapshot: ConversationSnapshot) → None

Attach the conversation snapshot under explanation.

estimate_attributions(masks: Sequence[CoalitionMask], payoffs: Sequence[float], aggregator: EstimandAggregator) → list[float]

Aggregate coalition payoffs with the selected estimand plugin.

options_model

alias of PluginOptions

Complementary pair sampling estimator.

@domain estimation @see [[knowledge/architecture/estimation]] @tested-by [[tests/estimation/test_complementary.py]]

class mllm_shap.estimation.complementary.ComplementaryEstimator(context: PluginContext | None = None)[source]

Bases: _SnapshotEstimator

Sample complementary coalition pairs and aggregate CC attributions.

property name: str

Return the registered estimator identifier.

property m_counts: ndarray | None

Return the latest complementary M-matrix counts from sampling.

reset_sampling_state(num_players: int) → None[source]

Reset complementary M-matrix counts before a new sampling run.

sample_masks(player_set: PlayerSet, budget_fraction: float, include_minimal_masks: bool, seed: int) → Iterator[CoalitionMask][source]

Yield complementary coalition pairs up to the configured budget.

Order: the (N, empty) pair, the singleton pairs ({i}, N - {i}) (the 2n + 2 budget floor fits all of them), then random pairs. All count toward the budget.

estimate_attributions(masks: Sequence[CoalitionMask], payoffs: Sequence[float], aggregator: EstimandAggregator) → list[float][source]

Aggregate complementary pairs into Shapley attributions.

Masks are paired by complement, so their order does not matter. Complementary contributions estimate the Shapley value only.

Raises:

ValueError – If the estimand is not Shapley, masks is empty, or a mask has no complement in masks.

bind_snapshot(snapshot: ConversationSnapshot) → None

Attach the conversation snapshot under explanation.

options_model

alias of PluginOptions

Neyman complementary allocation estimator.

@domain estimation @see [[knowledge/architecture/estimation]] @tested-by [[tests/estimation/test_neyman.py]]

class mllm_shap.estimation.neyman.NeymanEstimator(context: PluginContext | None = None, initial_fraction: float | None = None, initial_num_samples: int | None = None, use_standard_method: bool = False)[source]

Bases: ComplementaryEstimator

Two-phase complementary estimator with Neyman coalition-size allocation.

property name: str

Return the registered estimator identifier.

sample_masks(player_set: PlayerSet, budget_fraction: float, include_minimal_masks: bool, seed: int) → Iterator[CoalitionMask][source]

Yield phase-one Neyman masks until the initial M-matrix grid is filled.

Order: the (N, empty) pair, the singleton pairs ({i}, N - {i}), then the grid walk over (size, player) cells. All count toward the budget.

begin_allocation(masks: Sequence[CoalitionMask], payoffs: Sequence[float]) → None[source]

Estimate Neyman allocation after phase-one payoffs are available.

sample_allocation_masks() → Iterator[CoalitionMask][source]

Yield phase-two masks according to the estimated Neyman allocation.

Leave-one-out attribution: each player’s drop from the full coalition.

@domain estimation @see [[knowledge/architecture/estimation]] @tested-by [[tests/estimation/test_loo.py]]

class mllm_shap.estimation.loo.LeaveOneOutEstimator(context: PluginContext | None = None)[source]

Bases: _SnapshotEstimator

Attribute v(N) - v(N - {i}) to player i from n + 1 coalitions.

The baseline every attribution method should beat. It ignores the budget and the estimand: values are not Shapley or Banzhaf values and need not add up to v(N) - v(empty).

property name: str

Return the registered estimator identifier.

sample_masks(player_set: PlayerSet, budget_fraction: float, include_minimal_masks: bool, seed: int) → Iterator[CoalitionMask][source]

Yield the grand coalition, then the grand coalition without each player.

estimate_attributions(masks: Sequence[CoalitionMask], payoffs: Sequence[float], aggregator: EstimandAggregator | None) → list[float][source]

Return v(N) - v(N - {i}) for every player i.

Estimand aggregators

Estimand aggregation plugins.

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

Shapley estimand aggregation.

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

class mllm_shap.estimation.estimands.shapley.ShapleyAggregator(context: PluginContext | None = None)[source]

Bases: object

Aggregate coalition samples with Shapley coalition weights.

options_model

Accepts no explanation.plugin_options.

alias of PluginOptions

property estimand: Estimand

Return the Shapley estimand label.

coalition_weight(coalition_size: int, num_players: int) → float[source]

Return Shapley coalition weight k!(n-k-1)!/n!.

aggregate(masks: Sequence[Sequence[bool]], payoffs: Sequence[float]) → list[float][source]

Aggregate coalition samples into Shapley values.

Banzhaf estimand aggregation.

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

class mllm_shap.estimation.estimands.banzhaf.BanzhafAggregator(context: PluginContext | None = None)[source]

Bases: object

Aggregate coalition samples with uniform Banzhaf coalition weights.

options_model

Accepts no explanation.plugin_options.

alias of PluginOptions

property estimand: Estimand

Return the Banzhaf estimand label.

coalition_weight(coalition_size: int, num_players: int) → float[source]

Return uniform Banzhaf coalition weight 1/2^(n-1).

aggregate(masks: Sequence[Sequence[bool]], payoffs: Sequence[float]) → list[float][source]

Aggregate coalition samples into Banzhaf indices.

Normalizers

Post-aggregation attribution normalizers.

@domain estimation @see [[knowledge/architecture/estimation]] @tested-by [[tests/estimation/test_normalizers.py]]

class mllm_shap.estimation.normalizers.IdentityNormalizer(context: PluginContext | None = None)[source]

Bases: object

Return attributions unchanged.

options_model

Accepts no explanation.plugin_options.

alias of PluginOptions

property name: str

Return the registered normalizer identifier.

normalize(values: Sequence[float]) → list[float][source]

Return a copy of values.

class mllm_shap.estimation.normalizers.AbsSumNormalizer(context: PluginContext | None = None)[source]

Bases: object

Scale attributions by the sum of absolute values.

options_model

Accepts no explanation.plugin_options.

alias of PluginOptions

property name: str

Return the registered normalizer identifier.

normalize(values: Sequence[float]) → list[float][source]

Return values divided by the sum of absolute entries.

class mllm_shap.estimation.normalizers.PowerShiftOptions(*, power: Annotated[float, Gt(gt=0)] = 1.0)[source]

Bases: PluginOptions

Options of the power_shift normalizer.

power: float

Exponent applied to the shifted attributions.

model_config = {'extra': 'forbid', 'frozen': True, 'strict': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class mllm_shap.estimation.normalizers.PowerShiftNormalizer(context: PluginContext | None = None, power: float = 1.0)[source]

Bases: object

Shift to non-negative values, apply a power, then scale to sum one.

options_model

Options accepted from explanation.plugin_options.

alias of PowerShiftOptions

property name: str

Return the registered normalizer identifier.

normalize(values: Sequence[float]) → list[float][source]

Return power-shift normalized attributions.

class mllm_shap.estimation.normalizers.MinMaxNormalizer(context: PluginContext | None = None)[source]

Bases: object

Min-max scale to [0, 1] then normalize to sum one.

options_model

Accepts no explanation.plugin_options.

alias of PluginOptions

property name: str

Return the registered normalizer identifier.

normalize(values: Sequence[float]) → list[float][source]

Return min-max scaled attributions that sum to one.