Using approximate estimators¶
Approximate estimators sample coalitions under a budget fraction and aggregate payoffs into attributions. Monte Carlo delegates to estimand plugins; complementary and Neyman estimators use complementary-contribution (CC) aggregation.
Monte Carlo¶
from nlp_shap.domain.players import PlayerSet
from nlp_shap.estimation.estimands import ShapleyAggregator
from nlp_shap.estimation.monte_carlo import MonteCarloEstimator
player_set = PlayerSet(player_ids=("p0", "p1", "p2", "p3"))
estimator = MonteCarloEstimator()
masks = list(estimator.sample_masks(
player_set,
budget_fraction=0.5,
include_minimal_masks=True,
seed=42,
))
payoffs = [float(index % 3) for index in range(len(masks))]
values = estimator.estimate_attributions(
masks,
payoffs,
ShapleyAggregator(),
)
print("samples:", len(masks))
print("values:", tuple(round(value, 4) for value in values))
Output
samples: 7
values: (0.4167, 0.5, 0.0833, 0.25)
Complementary pairs¶
from nlp_shap.estimation.complementary import ComplementaryEstimator
estimator = ComplementaryEstimator()
masks = list(estimator.sample_masks(
player_set,
budget_fraction=0.4,
include_minimal_masks=True,
seed=7,
))
# masks arrive in complementary pairs: S, N\\S, S, N\\S, ...
payoffs = [...]
values = estimator.estimate_attributions(masks, payoffs)
Neyman two-phase sampling¶
Neyman allocation needs phase-one payoffs before drawing phase-two masks:
from nlp_shap.estimation.neyman import NeymanEstimator
estimator = NeymanEstimator(
initial_fraction=0.25,
use_standard_method=False,
)
phase_one = list(estimator.sample_masks(
player_set,
budget_fraction=0.6,
include_minimal_masks=False,
seed=11,
))
payoffs_one = [...]
estimator.begin_allocation(phase_one, payoffs_one)
phase_two = list(estimator.sample_allocation_masks())
payoffs_two = [...]
all_masks = phase_one + phase_two
all_payoffs = payoffs_one + payoffs_two
values = estimator.estimate_attributions(all_masks, all_payoffs)
Configuration¶
Set the estimator and budget in ExplainConfig:
explanation:
estimator: neyman_cc
budget:
fraction: 0.6
include_minimal_masks: false
neyman:
initial_fraction: 0.25
use_standard_method: false
Plugin resolution¶
from nlp_shap.plugins import PluginGroup, PluginRegistry, register_builtin_plugins
registry = PluginRegistry()
register_builtin_plugins(registry)
mc = registry.resolve(PluginGroup.ESTIMATORS, "mc")
complementary = registry.resolve(PluginGroup.ESTIMATORS, "complementary")
neyman = registry.resolve(PluginGroup.ESTIMATORS, "neyman_cc")
print(mc.name, complementary.name, neyman.name)
Output
mc complementary neyman_cc
Entry points are registered under nlp_shap.estimators in pyproject.toml.
Choosing an estimator¶
Estimator |
Best when |
Estimand support |
|---|---|---|
Monte Carlo |
You need Banzhaf or Shapley from the same samples |
Shapley, Banzhaf via plugins |
Complementary |
Budget is moderate; CC variance reduction helps |
CC Shapley only |
Neyman |
Longer inputs; allocation targets high-variance coalition sizes |
CC Shapley only (two-phase) |
See Examples for a notebook comparing accuracy and cost across methods.