cleverly.interventions.PolicySet#
- class cleverly.interventions.PolicySet(names: tuple[str, ...], descriptions: tuple[str, ...], shifted: FloatArray, ratio: FloatArray, ratio_at: FloatArray, moved: BoolArray, reference: float = 0.0, mixing: FloatArray | None = None, component_codes: IntArray | None = None, observed_codes: IntArray | None = None, capped: BoolArray | None = None, joint: JointDensityParts | None = None, component_rows: BoolArray | None = None, curve_terms: FloatArray | None = None)[source]#
Every declared policy, evaluated on the data and on the estimated mechanism.
Holds arrays and no callables, for the reason
RegimeSetdoes: a fit reached throughretarget()– a truncation sweep, the bootstrap, a result loaded from disk – targets the same declared policies without the mechanism being refit or the caller’s objects being reachable.The arrays are indexed by component: one deterministic branch of a declared policy. A deterministic policy is one component,
mixingis thenNoneand the component codes are the policy codes. A randomized policy contributes one component per randomizer value, and rowsofmixingholds the known probabilities with which policysaverages its components.- Parameters:
- names
tupleofstr One per policy, in the order they were declared. Report labels.
- descriptions
tupleofstr A stable text of each policy, from
describe_policy().- shifted
ndarray (n, C), \(d_c(A_i, W_i)\) per component: a dose on a continuous treatment and a level code on a categorical one.(n, C, d)on a vector treatment with a continuous component: the component codes and doses each branch assigns.- ratio
ndarray (n, C), \(h_c(A_i, W_i)\) – the clever covariate at the observed treatment. Untruncated on a continuous treatment, and targeting applies no bound to it: themtpcovariate is this ratio divided only by the missingness and intermediate mechanisms a fit declares. Those mechanisms are bounded at targeting time, andtruncation_curve(mechanism=True)sweeps that bound. No option bounds or sweeps the ratio itself.- ratio_at
ndarray (n, C, C), \(h_c(d_s(A_i, W_i), W_i)\) at[i, s, c]. The fluctuation updates \(\bar Q\) as a function of \((a, W)\), so obtaining \(\bar Q^*(d_s(A,W), W)\) needs the covariate evaluated at the assigned dose – hence a matrix per row rather than a vector.- moved
ndarray (n, C)boolean, whether the component changed that row’s treatment.- reference
float Code of the policy contrasts are taken against.
- mixing
ndarrayorNone (S, C)known component weights of each policy, orNonewhen every policy is deterministic.- component_codes
ndarrayorNone (n, C, K)level map of each component on a categorical treatment, fromdiscrete_assignments(), orNoneon a continuous one.- observed_codes
ndarrayorNone (n,)observed level codes on a categorical treatment, orNone.- capped
ndarrayorNone (n, C)boolean, whether a declaredcapheld the component at that row’s own dose; on a vector treatment, whether a cap held any of its doses.Noneon a categorical treatment, where no cap is evaluated.- joint
JointDensityPartsorNone On a vector treatment with a continuous component, fitted on the density route: the factors of the node’s law at the observed value and at each branch’s assigned value (
joint_density).design_at()rebuilds the ratios from them with the categorical factor bounded.Noneelsewhere.- component_rows
ndarrayorNone (n, C)boolean, the rows each component’s mean and curve read, orNonewhen every component reads every row. A fold-average policy (X40 part (e1)) has one component per outer fold, at the map fitted on that fold’s training rows, and the component reads only the fold’s held-out rows. Its ratio is zero on the other rows, so its fluctuation solves the fold’s own score.- curve_terms
ndarrayorNone (n, S)the term each policy’s curve adds on the scaled outcome scale, orNone. A population-target policy with a tuned cap adds \(\partial\Phi_n' \mathrm{IF}\) (X40 part (e2)); every other policy adds zero.
- names
- Attributes:
nintReturn the number of observations.
n_policiesintReturn the number of declared policies.
n_componentsintReturn the number of deterministic components the policies expand into.
codestupleoffloatThe keys the per-parameter arrays use,
(0.0, ..., S-1.0).component_keystupleoffloatThe keys the per-component predictions use,
(0.0, ..., C-1.0).labelsdictoffloattostrCode to reported label, which is what
parameter_nameis given.is_discreteboolWhether the treatment is categorical, so the ratio reads the propensity.
weightsndarray(S, C)component weights of each policy, the identity without a randomizer.policy_rationdarray(n, S)each policy’s clever covariate at the observed treatment.designndarray(n, C + 1, C)– the covariate at the observed dose, then at each assigned one.
Methods#
- PolicySet.design_at(propensity: ndarray[tuple[Any, ...], dtype[float64]] | None, bounds: tuple[float, float] | None = None) ndarray[tuple[Any, ...], dtype[float64]][source]#
design, rebuilt from a bounded mechanism on a categorical treatment.On a continuous treatment this is
design, since the density ratio is not bounded. On a categorical one the ratio reads the fitted probabilities, and targeting passes them bounded byg_bounds, as for every other arm-indexed clever covariate. On a vector treatment fitted on the density route the categorical factor is bounded intoboundsby the same rule, in the numerator and the denominator, and the doses’ factors are not bounded.
- classmethod PolicySet.evaluate(policies: Sequence[object], data: CausalData, density: ConditionalDensity | MixedDensity | None = None, *, propensity: ndarray[tuple[Any, ...], dtype[float64]] | None = None, reference: str | None = None) PolicySet[source]#
Evaluate every policy against the data and the estimated mechanism.
On a continuous treatment every entry is a lookup into
density’s stored bin probabilities, so \(g(A \mid W)\) and \(g(b_j(A) \mid W)\) for one row necessarily come from the same out-of-fold model – there is no second model to get wrong. On a categorical treatment the ratio readspropensityby the discrete formula, and targeting rebuilds it from the bounded mechanism (design_at()).- Parameters:
- policiessequence
ofpolicy The policies to evaluate, in the order their codes will follow.
- data
CausalData Validated study data, which supplies the observed treatment.
- density
ConditionalDensity,MixedDensityorNone Estimated conditional density of the dose given the covariates, on a continuous treatment. A dose with declared atoms reads a
MixedDensity.- propensity
ndarrayorNone (n, K)fitted treatment probabilities, on a categorical treatment.- reference
strorNone Label of the policy contrasts are taken against.
Noneuses the first.
- policiessequence
- Returns:
PolicySetEvery policy evaluated on the data and that mechanism.
- classmethod PolicySet.evaluate_by_classifier(policies: Sequence[object], data: CausalData, learner: Any, folds: Folds, *, reference: str | None = None, n_jobs: int = 1, by_fold: Sequence[Sequence[object]] | None = None) PolicySet[source]#
Evaluate every policy with ratios estimated by classification.
The ratio of each component is
classifier_ratio()(Díaz, Williams, Hoffman and Schenck 2023, Section 5.4), cross-fitted over units onfolds. No density is fitted. The checks of the policy are the ones the density route runs, so a policy that is not piecewise smooth invertible on a continuous treatment is refused on this route too.- Parameters:
- policiessequence
ofpolicy The policies to evaluate, in the order their codes will follow.
- data
CausalData Validated study data.
- learner
Learner The binary classifier of the stacked label.
- folds
Folds The outer split.
- reference
strorNone Label of the policy contrasts are taken against.
- n_jobs
int Parallel workers across the outer folds.
- by_foldsequence or
None Per outer fold, the policies that fold’s classifier stacks, in place of
policies, with the same branches: a population-target tuned cap at the tuner fitted on that fold’s training rows (test_t_e7_each_fold_trains_at_its_own_tuner). The ratio is still evaluated at the dosespoliciesassign.Nonestackspoliciesin every fold.
- policiessequence
- Returns:
PolicySetEvery policy evaluated on the data, with classifier ratios.
- classmethod PolicySet.evaluate_vector_density(policies: Sequence[object], data: CausalData, learner: Any, folds: Folds, *, reference: str | None = None, n_bins: int | None = None, n_jobs: int = 1) PolicySet[source]#
Evaluate joint policies at a vector treatment with a continuous component, by density.
The treatment’s law is fitted by the chain rule, and each policy’s induced density is the sum over categorical preimages and piece paths of
joint_density. The ratio of componentcis evaluated at the observed value and at every component’s assigned value, from the same out-of-fold factors.design_at()rebuilds both with the categorical factor bounded, as for a categorical treatment.- Parameters:
- policiessequence
ofJointPolicy The policies to evaluate, in the order their codes will follow.
- data
CausalData Validated study data with a vector treatment.
- learner
Learner The classifier of the categorical factor and of every dose’s hazards.
- folds
Folds The outer split.
- reference
strorNone Label of the policy contrasts are taken against.
- n_bins
intorNone The bin count of each dose’s density.
- n_jobs
int Parallel workers across the outer folds.
- policiessequence
- Returns:
PolicySetEvery policy evaluated on the data, with the joint factors kept.
- PolicySet.subset(index: Any) PolicySet[source]#
The same policies on a row subset – a fold, a bootstrap resample.
Sliced rather than re-evaluated, for the reason
subset()gives: a policy is the same policy on a subsample, and re-deriving it would let the resample redefine the estimand.- Parameters:
- indexarray_like
Row positions or a boolean mask.
- Returns:
PolicySetThe same policies over the selected rows.
Attributes#
- PolicySet.codes#
The keys the per-parameter arrays use,
(0.0, ..., S-1.0).
- PolicySet.component_keys#
The keys the per-component predictions use,
(0.0, ..., C-1.0).
- PolicySet.design#
(n, C + 1, C)– the covariate at the observed dose, then at each assigned one.One array rather than two, because
submodel_for()dispatches on the group name alone and every builder takes the same keyword-only signature;policies=is that one keyword. Row block0is the covariate at the observed treatment and blocks + 1the covariate at \(d_s(A, W)\).
- PolicySet.is_discrete#
Whether the treatment is categorical, so the ratio reads the propensity.
- PolicySet.labels#
Code to reported label, which is what
parameter_nameis given.
- PolicySet.n#
Return the number of observations.
- PolicySet.n_components#
Return the number of deterministic components the policies expand into.
- PolicySet.n_policies#
Return the number of declared policies.
- PolicySet.policy_ratio#
(n, S)each policy’s clever covariate at the observed treatment.The known component weights average the component ratios, which is the ratio of the policy’s induced density: \(g^d = \sum_e p(e)\, g^{d_e}\). A fold-average policy reads, at each row, the ratio of the component that holds the row out, so the weights are renormalised over the components that read the row.
- PolicySet.weights#
(S, C)component weights of each policy, the identity without a randomizer.
- PolicySet.shifted: FloatArray#
- PolicySet.ratio: FloatArray#
- PolicySet.ratio_at: FloatArray#
- PolicySet.moved: BoolArray#