Using the exact estimator¶
ExactEstimator lazily enumerates every
coalition mask (except the grand coalition) and delegates attribution to a
registered estimand plugin.
Quick start¶
from itertools import product
from nlp_shap.domain.coalition import CoalitionMask
from nlp_shap.domain.players import PlayerSet
from nlp_shap.estimation.estimands import BanzhafAggregator, ShapleyAggregator
from nlp_shap.estimation.exact import ExactEstimator
player_set = PlayerSet(player_ids=("p0", "p1", "p2"))
estimator = ExactEstimator()
masks = list(estimator.sample_masks(
player_set,
budget_fraction=1.0,
include_minimal_masks=False,
seed=0,
))
print("coalitions:", len(masks)) # 7 for three players
all_masks = [
tuple(bits) for bits in product([False, True], repeat=player_set.num_players)
]
def majority_payoff(mask: tuple[bool, ...]) -> float:
return 1.0 if sum(mask) >= 2 else 0.0
payoffs = [majority_payoff(mask) for mask in all_masks]
coalition_masks = tuple(CoalitionMask.from_sequence(mask) for mask in all_masks)
shapley = estimator.estimate_attributions(
coalition_masks,
payoffs,
ShapleyAggregator(),
)
banzhaf = estimator.estimate_attributions(
coalition_masks,
payoffs,
BanzhafAggregator(),
)
print("Shapley:", shapley)
print("Banzhaf:", banzhaf)
Bitmask iteration¶
For large player sets, iterate packed coalition integers and decode only when needed:
from nlp_shap.estimation.exact import ExactEstimator
for mask_int in ExactEstimator.iter_mask_ints(player_set.num_players):
present = ExactEstimator.mask_int_to_present(mask_int, player_set.num_players)
Budget requirement¶
Exact enumeration requires a full budget fraction:
from nlp_shap.domain.players import PlayerSet
from nlp_shap.estimation.exact import ExactEstimator
player_set = PlayerSet(player_ids=("p0",))
try:
ExactEstimator().sample_masks(
player_set,
budget_fraction=0.5,
include_minimal_masks=False,
seed=0,
)
except ValueError as exc:
print(exc) # exact estimator requires budget_fraction == 1.0
Plugin resolution¶
Resolve the estimator from packaging entry points:
from nlp_shap.plugins import PluginGroup, PluginRegistry, register_builtin_plugins
registry = PluginRegistry()
register_builtin_plugins(registry)
registry.load_entry_points(PluginGroup.ESTIMATORS)
estimator = registry.resolve(PluginGroup.ESTIMATORS, "exact")
print(estimator.name) # exact
Notebook¶
See the runnable walkthrough in Examples —
examples/exact_estimation.ipynb.
Further reading¶
Using estimand aggregators — Shapley and Banzhaf aggregators
Configuration —
explanation.estimatorkeyTheory: Exact estimation