| from __future__ import annotations |
|
|
| import json |
| from dataclasses import asdict |
| from pathlib import Path |
|
|
| from sepsis_mcp.gossis_experiment import GossisRunConfig |
| from sepsis_mcp.mimic4_experiment import Mimic4RunConfig |
| from sepsis_mcp.modeling import ProbabilityEstimator, QuantileRegressionEstimator, RegressionEstimator |
|
|
|
|
| def _pipeline_terminal_params(estimator) -> dict[str, object]: |
| model = getattr(estimator, "model", estimator) |
| if hasattr(model, "named_steps"): |
| terminal = list(model.named_steps.values())[-1] |
| return terminal.get_params() |
| return model.get_params() |
|
|
|
|
| def render_implementation_details() -> str: |
| gossis_defaults = asdict(GossisRunConfig(data_root=Path("."), output_dir=Path("outputs/gossis-hospital"))) |
| mimic_defaults = asdict(Mimic4RunConfig(csv_path=Path("mimic.csv"), output_dir=Path("outputs/mimic4-validation"))) |
| classifier_defaults = { |
| "logistic_regression": _pipeline_terminal_params(ProbabilityEstimator(model_type="logistic_regression")), |
| "mlp": _pipeline_terminal_params(ProbabilityEstimator(model_type="mlp")), |
| "xgboost": _pipeline_terminal_params(ProbabilityEstimator(model_type="xgboost")), |
| } |
| regression_defaults = { |
| "ridge_regression": _pipeline_terminal_params(RegressionEstimator(model_type="ridge_regression")), |
| "sklearn_gbdt": _pipeline_terminal_params(RegressionEstimator(model_type="sklearn_gbdt")), |
| "cqr_xgboost": _pipeline_terminal_params(QuantileRegressionEstimator(model_type="xgboost", quantile=0.95)), |
| } |
|
|
| return "\n".join( |
| [ |
| "# Implementation Details", |
| "", |
| "## GOSSIS Classification Defaults", |
| "", |
| "```json", |
| json.dumps(gossis_defaults, indent=2, default=str), |
| "```", |
| "", |
| "## MIMIC-IV Validation Defaults", |
| "", |
| "```json", |
| json.dumps(mimic_defaults, indent=2, default=str), |
| "```", |
| "", |
| "## Base Model Hyperparameters", |
| "", |
| "### Classification", |
| "", |
| "```json", |
| json.dumps(classifier_defaults, indent=2, default=str), |
| "```", |
| "", |
| "### Regression / CQR", |
| "", |
| "```json", |
| json.dumps(regression_defaults, indent=2, default=str), |
| "```", |
| "", |
| "## Split and Seed Protocol", |
| "", |
| "- GOSSIS uses hospital-disjoint splits with optional selection hospitals when `selection_fraction > 0`.", |
| "- MIMIC-IV uses leave-one-care-unit-out assignments with `rotations` train/selection/calibration rotations per held-out unit.", |
| "- Random seeds are passed through the run config and sweep grids; appendix sweeps report per-seed outputs and repeated summaries.", |
| "", |
| "## Conformity Scores", |
| "", |
| "- Classification uses binary nonconformity scores: `p_hat(y!=y_true)` via `binary_nonconformity_scores`.", |
| "- Standard CP uses a single global conformal threshold.", |
| "- Missingness-aware CP uses subgroup-specific thresholds when subgroup calibration support exceeds `min_group_size`, otherwise it falls back to the global threshold.", |
| "- CPMDA exact uses exact mask-signature matching on selected missingness features and falls back to the global threshold when `min_match` is not met.", |
| "- CQR uses symmetric or normalized residual scores with optional trimming via `trim_fraction`.", |
| "", |
| "## Preprocessing and Missingness Handling", |
| "", |
| "- Tabular classification models use one-hot encoding plus constant-value imputation for missing values where required by the estimator pipeline.", |
| "- Structured missingness grouping is selected from candidate variables whose missing fractions lie between `min_variable_missing_fraction` and `max_variable_missing_fraction`.", |
| "- The default appendix fallback threshold rule is explicit: undersupported groups revert to the marginal calibration threshold rather than forcing unstable subgroup quantiles.", |
| ] |
| ) |
|
|
|
|
| def write_implementation_details(*, output_path: Path, manifest_path: Path) -> dict[str, Path]: |
| output_path.parent.mkdir(parents=True, exist_ok=True) |
| output_path.write_text(render_implementation_details(), encoding="utf-8") |
| manifest_path.write_text( |
| json.dumps({"implementation_details": str(output_path)}, indent=2, sort_keys=True), |
| encoding="utf-8", |
| ) |
| return {"implementation_details": output_path, "manifest": manifest_path} |
|
|