Api calm
Summary
select_regions decides, across features, which of the splits find_regions
found actually explain the model. It returns a CalmSequence — the chain
[GAM, calm1, ...] produced by greedy forward selection: each step applies
the split with the largest explained-variance gain, and stops when no
remaining split adds at least min_r2_gain of Var(f̂).
Each snapshot is a CALM (Conditional Additive Local Model): the global
read plus the partitions accepted so far, with its surrogate R² stamped on
it. Like Partition, both are values, not stored state (design contract
R12): they serialize with to_dict() and re-attach with bind(effect).
Usage
pdp = effector.PDP(data=X, model=predict)
parts = pdp.find_regions(features="heterogeneous") # candidates, per feature
chain = pdp.select_regions(partitions=parts) # which ones earn their keep
chain.show() # the explained-variance ledger, as tables
chain.gam_r2 # R² of the pure-GAM read
chain.regional_r2 # R² after the accepted splits
chain.skipped # rejected splits, with reasons
calm = chain.final # the selected snapshot — the report's §2
calm.importances() # per feature, weighted mean over subregions
calm.plot_triage() # the importance × heterogeneity plane, at this snapshot
partitions= is optional: select_regions() runs the search itself, with
the same features / finder / candidate_conditioning_features arguments
as find_regions. The method itself is documented per engine in
Global effect; the walkthrough lives in
the select_regions guide.
Derivative-scale methods cannot play
select_regions raises ValueError on DerPDP: its curves live on the
derivative scale, where summing does not approximate f̂.
API
effector.global_effect.GlobalEffectBase.select_regions(partitions=None, *, features='heterogeneous', finder='best', candidate_conditioning_features='all', min_r2_gain=0.01)
Greedily select which partitions earn their complexity — the CALM chain.
chain = pdp.select_regions() # search + select in one call
chain.show() # GAM R2, each accepted split, the rejected
chain.final # the last CALM — the regional analysis
chain[0] # the GAM snapshot
find_regions proposes one candidate Partition per feature;
this verb decides across features which of them actually explain
the model: starting from the GAM (all features global), each round
applies the split with the largest explained-variance gain — the
surrogate R² against f̂, measured on top of the splits already
applied — and stops when no remaining split adds at least
min_r2_gain. Every accepted round is a snapshot (CALM) of
increased complexity; the whole chain is the report's ledger.
A query, not a mutation (R12)
The result is a value — nothing is stored on the effect.
One prediction pass
Beyond fit, the only model touch is one f̂(X) pass for the
variance denominator (cached on the effect); the search, the
scoring, and every snapshot's summaries are model-free.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
partitions
|
Optional[dict]
|
pre-computed candidates — |
None
|
features
|
Union[list, str]
|
which features to search when |
'heterogeneous'
|
finder
|
region finder, as in |
'best'
|
|
candidate_conditioning_features
|
features allowed to define
splits ( |
'all'
|
|
min_r2_gain
|
float
|
smallest explained-variance marginal (fraction of
|
0.01
|
Returns:
| Type | Description |
|---|---|
|
a |
|
|
it, with the rejected splits in |
|
|
( |
Raises:
| Type | Description |
|---|---|
ValueError
|
the method is derivative-scale (no output-scale
surrogate) or |
Source code in effector/global_effect.py
951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 | |
effector.calm.CalmSequence(calms, *, skipped=None, min_gain=0.01)
The chain select_regions returns: [GAM, calm1, ...] plus the splits it rejected.
List-like (chain[0], chain[-1], len, iteration) with the chain
invariants: R² is non-decreasing along it and each stage's delta_r2
is the sequential marginal, so the gains sum exactly to
regional_r2 - gam_r2.
Methods:
| Name | Description |
|---|---|
show |
Print the decision sequence as the report's ledger tables: |
bind |
Bind every snapshot (mask verification included). Returns |
to_dict |
Serialize the chain — a superset of the report's explained-variance |
from_dict |
Rebuild an unbound chain from |
Attributes:
| Name | Type | Description |
|---|---|---|
gam |
The chain's first snapshot — the pure GAM. |
|
final |
The chain's last snapshot — what the report renders as the regional analysis. |
|
gam_r2 |
|
|
regional_r2 |
|
|
stages |
The accepted decisions, in order — one per non-GAM snapshot. |
Source code in effector/calm.py
363 364 365 366 367 368 | |
gam
property
The chain's first snapshot — the pure GAM.
final
property
The chain's last snapshot — what the report renders as the regional analysis.
gam_r2
property
regional_r2
property
stages
property
The accepted decisions, in order — one per non-GAM snapshot.
show(ascii=False)
Print the decision sequence as the report's ledger tables: EXPLAINED VARIANCE (the GAM, each accepted split, the FINAL R²), then REJECTED SPLITS with the reason each one was refused.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ascii
|
draw with plain ASCII instead of box-drawing characters, for terminals and logs that mangle unicode. |
False
|
Source code in effector/calm.py
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 | |
bind(effect)
Bind every snapshot (mask verification included). Returns self.
Source code in effector/calm.py
403 404 405 406 407 | |
to_dict()
Serialize the chain — a superset of the report's explained-variance
payload: the flat decision-sequence keys (gam_r2, regional_r2,
min_gain, stages, skipped) plus the full calms list.
Source code in effector/calm.py
441 442 443 444 445 446 447 448 449 450 451 452 453 | |
from_dict(d)
classmethod
Rebuild an unbound chain from to_dict() output.
Source code in effector/calm.py
455 456 457 458 459 460 461 462 463 464 465 466 467 | |
effector.calm.CALM(*, index, r2, partitions, stage=None, feature_names, target_name, importances, heter_scores, baseline, scale_y=None)
One snapshot: global effects everywhere except the accepted split features.
index == 0 is the pure GAM (no partitions). Every later CALM adds one
accepted split on top of the previous one; stage records that decision
(feature, sequential delta_r2, running cum_r2, heterogeneity
before/after the split).
Stamped scalars
importance(f)/heter_score(f) are computed at construction —
weighted mean over subregions for split features (weights =
instances per leaf), the global value otherwise — and stamped, so an
unbound CALM still ranks and plots. When bound, the same calls can
recompute live via the effect's masked verbs and must agree.
Methods:
| Name | Description |
|---|---|
from_effect |
Stamp a snapshot off a fitted effect — used by |
importance |
This snapshot's importance of |
importances |
|
heter_score |
This snapshot's heterogeneity of |
heter_scores |
|
plot_triage |
This snapshot's triage plane, from the stamped scalars (works unbound). |
show |
Print the snapshot: R², the decision that created it, its partitions. |
bind |
Re-attach a fitted effect: binds every held partition (recomputing |
to_dict |
Serialize to a plain JSON-able dict — rules and stamped stats only, |
from_dict |
Rebuild an unbound CALM from |
Attributes:
| Name | Type | Description |
|---|---|---|
is_gam |
|
|
features |
The split features of this snapshot, ascending. |
Source code in effector/calm.py
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | |
is_gam
property
features
property
The split features of this snapshot, ascending.
from_effect(effect, partitions, *, r2, index=0, stage=None)
classmethod
Stamp a snapshot off a fitted effect — used by select_regions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
effect
|
a fitted global effect (bound partitions apply to its data). |
required | |
partitions
|
|
required | |
r2
|
surrogate R² of this snapshot against |
required | |
index
|
position in the chain; 0 is the GAM. |
0
|
|
stage
|
the decision that created this snapshot ( |
None
|
Source code in effector/calm.py
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | |
importance(feature, *, per_region=False)
This snapshot's importance of feature (output units).
Split feature -> instance-weighted mean over its subregions; else the
global value. With per_region=True (bound CALM, split feature only)
returns the per-leaf list instead.
Source code in effector/calm.py
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | |
importances()
(D,) vector of this snapshot's importances; NaN = unsupported type.
Source code in effector/calm.py
233 234 235 | |
heter_score(feature, *, per_region=False)
This snapshot's heterogeneity of feature (output units).
Split feature -> instance-weighted mean over its subregions; else the
global value. With per_region=True (split feature only) returns the
stamped per-leaf list — available unbound.
Source code in effector/calm.py
211 212 213 214 215 216 217 218 219 220 221 222 | |
heter_scores()
(D,) vector of this snapshot's heterogeneities; NaN = unsupported type.
Source code in effector/calm.py
237 238 239 | |
plot_triage(threshold=False, title=None, show_plot=True)
This snapshot's triage plane, from the stamped scalars (works unbound).
One point per feature at the CALM's own (importance, heterogeneity); each split feature gets one arrow from its global point to its weighted-mean point — the movement the accepted split bought.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
threshold
|
heterogeneity line — a float draws it (given in
|
False
|
|
title
|
figure title. |
None
|
|
show_plot
|
if |
True
|
Source code in effector/calm.py
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 | |
show()
Print the snapshot: R², the decision that created it, its partitions.
Source code in effector/calm.py
292 293 294 295 296 297 298 299 300 301 302 303 | |
bind(effect)
Re-attach a fitted effect: binds every held partition (recomputing and verifying masks) and re-enables the live verbs.
Returns:
| Type | Description |
|---|---|
|
|
Source code in effector/calm.py
153 154 155 156 157 158 159 160 161 162 163 | |
to_dict()
Serialize to a plain JSON-able dict — rules and stamped stats only,
never masks/data/effect. from_dict(...) + bind(effect) restore
the rest.
Source code in effector/calm.py
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 | |
from_dict(d)
classmethod
Rebuild an unbound CALM from to_dict() output — tables and
triage work; partition eval/plot and per-region importance need
bind(effect).
Source code in effector/calm.py
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 | |