(
X: Sequence[Sequence[float]],
y: Sequence[float],
feature_names: Sequence[str] | None = None,
sample_weight: Sequence[float] | None = None,
n_estimators: int = 32,
seed: int = 42,
)
| 258 | |
| 259 | |
| 260 | def _importance_table(feature_names: Sequence[str], per_feature_values: Sequence[Sequence[float]]) -> pl.DataFrame: |
| 261 | rows = [] |
| 262 | for name, vals in zip(feature_names, per_feature_values): |
| 263 | rows.append( |
| 264 | { |
| 265 | "feature": name, |
| 266 | "mean": _mean(vals), |
| 267 | "std": _std(vals), |
| 268 | "stderr": _std(vals) / sqrt(len(vals)) if vals else 0.0, |
| 269 | } |
| 270 | ) |
| 271 | return pl.DataFrame(rows).sort("mean", descending=True) |
| 272 | |
| 273 | |
| 274 | def mdi_importance( |
| 275 | X: Sequence[Sequence[float]], |
| 276 | y: Sequence[float], |
| 277 | feature_names: Sequence[str] | None = None, |
| 278 | sample_weight: Sequence[float] | None = None, |
| 279 | n_estimators: int = 32, |
| 280 | seed: int = 42, |
| 281 | ) -> dict[str, object]: |
| 282 | x = _as_matrix(X) |
| 283 | yv = _as_vector(y, len(x)) |
| 284 | names = _feature_names(len(x[0]), feature_names) |
| 285 | weights = _sample_weight(sample_weight, len(x)) |
| 286 | |
| 287 | if n_estimators < 2: |
| 288 | raise ValueError("n_estimators must be >= 2") |
| 289 | |
| 290 | import random |
| 291 | |
| 292 | rng = random.Random(seed) |
| 293 | per_feature: list[list[float]] = [[] for _ in names] |
| 294 | |
| 295 | for _ in range(n_estimators): |
| 296 | idx = [rng.randrange(len(x)) for _ in range(len(x))] |
| 297 | xb = [x[i] for i in idx] |
| 298 | yb = [yv[i] for i in idx] |
| 299 | wb = [weights[i] for i in idx] if weights is not None else None |
| 300 | |
| 301 | model = _fit_linear_probability_model(xb, yb, wb) |
| 302 | raw = [abs(v) for v in model.coeffs] |
| 303 | denom = sum(raw) |
| 304 | norm = [v / denom if denom > 0 else 0.0 for v in raw] |
| 305 | for j, v in enumerate(norm): |
| 306 | per_feature[j].append(v) |
| 307 |
nothing calls this directly
no test coverage detected