From 7935b8e297fa042d504aa7c038b092053890368a Mon Sep 17 00:00:00 2001 From: John Wu <54558896+jhnwu3@users.noreply.github.com> Date: Thu, 1 Oct 2026 16:24:57 -0500 Subject: [PATCH] Sync tutorial notebooks with Colab and link example code in docs (#1256) - Sync tutorial_pyhealth_{data,trainer,medcode}.ipynb with the Colab versions linked from docs/tutorials.rst. The repo copies of data and trainer still used dataset.patients, which BaseDataset no longer has (it is unique_patient_ids). The medcode notebook's ICD9CM->ICD10CM cell relies on the icd-mappings backend added in the parent commits. - docs/tutorials.rst: link each Colab tutorial to its source notebook, turn every example filename into a link to the real file (fixing wrong or renamed paths such as the EEG SparcNet and eICU scripts), fix the broken readmission list-table, and blob/main -> blob/master. Co-authored-by: Claude Opus 5.5 --- docs/tutorials.rst | 154 +++++++++--------- .../tutorials/tutorial_pyhealth_data.ipynb | 43 +++-- .../tutorials/tutorial_pyhealth_medcode.ipynb | 2 +- .../tutorials/tutorial_pyhealth_trainer.ipynb | 7 +- 4 files changed, 99 insertions(+), 107 deletions(-) diff --git a/docs/tutorials.rst b/docs/tutorials.rst index 9193c86c0..818d731af 100644 --- a/docs/tutorials.rst +++ b/docs/tutorials.rst @@ -4,27 +4,27 @@ Tutorials We provide the following tutorials to help users get started with our pyhealth. Please bear with us as we update the documentation on how to use pyhealth 2.0. -`Tutorial 0: Introduction to pyhealth.data `_ `[Video] `_ +`Tutorial 0: Introduction to pyhealth.data `_ `[Video] `__ `[Source] `__ -`Tutorial 1: Introduction to pyhealth.datasets `_ `[Video (PyHealth 1.16)] `_ +`Tutorial 1: Introduction to pyhealth.datasets `_ `[Video (PyHealth 1.16)] `__ `[Source] `__ -`Tutorial 2: Introduction to pyhealth.tasks `_ `[Video (PyHealth 1.16)] `_ +`Tutorial 2: Introduction to pyhealth.tasks `_ `[Video (PyHealth 1.16)] `__ `[Source] `__ -`Tutorial 3: Introduction to pyhealth.models `_ `[Video] `_ +`Tutorial 3: Introduction to pyhealth.models `_ `[Video] `__ `[Source] `__ -`Tutorial 4: Introduction to pyhealth.trainer `_ `[Video] `_ +`Tutorial 4: Introduction to pyhealth.trainer `_ `[Video] `__ `[Source] `__ -`Tutorial 5: Introduction to pyhealth.metrics `_ `[Video] `_ +`Tutorial 5: Introduction to pyhealth.metrics `_ `[Video] `__ `[Source] `__ -`Tutorial 6: Introduction to pyhealth.tokenizer `_ `[Video] `_ +`Tutorial 6: Introduction to pyhealth.tokenizer `_ `[Video] `__ `[Source] `__ -`Tutorial 7: Introduction to pyhealth.medcode `_ `[Video] `_ +`Tutorial 7: Introduction to pyhealth.medcode `_ `[Video] `__ `[Source] `__ Data Access Guide ======================= -For information on how to access and download the datasets supported by PyHealth, please refer to our `Datasets Overview Notebook `_. +For information on how to access and download the datasets supported by PyHealth, please refer to our `Datasets Overview Notebook `_. Additionally, for detailed tutorials on accessing PhysioNet and MIMIC datasets, see the `Getting MIMIC access` section of the `DL4H course instructions `_. @@ -39,7 +39,8 @@ Additionally, for detailed tutorials on accessing PhysioNet and MIMIC datasets, `Pipeline 5: Readmission Prediction `_ -.. `Pipeline 5: Phenotype Prediction `_ +.. `Pipeline 5: Phenotype Prediction `_ + Multimodal & Smart Processors ------------------------------ @@ -53,7 +54,7 @@ These examples demonstrate PyHealth's unified multimodal architecture using * - Notebook / File - Description - * - ``smart_processor_clinical_text_tutorial.ipynb`` + * - `smart_processor_clinical_text_tutorial.ipynb `_ - End-to-end tutorial: HuggingFace tokenizer inside ``TupleTimeTextProcessor``, canonical ``("tuple_time_text", kwargs)`` schema form, EmbeddingModel with 3D inputs, and gradient flow through BERT-tiny in ``MLP``, ``Transformer``, ``RNN``, ``MultimodalRNN`` @@ -92,23 +93,23 @@ These examples are located in ``examples/mortality_prediction/``. * - Example File - Description - * - ``mortality_prediction/mortality_mimic3_rnn.py`` + * - `mortality_prediction/mortality_mimic3_rnn.py `_ - RNN for mortality prediction on MIMIC-III - * - ``mortality_prediction/mortality_mimic3_stagenet.py`` + * - `mortality_prediction/mortality_mimic3_stagenet.py `_ - StageNet for mortality prediction on MIMIC-III - * - ``mortality_prediction/mortality_mimic3_adacare.ipynb`` + * - `mortality_prediction/mortality_mimic3_adacare.ipynb `_ - AdaCare for mortality prediction on MIMIC-III (notebook) - * - ``mortality_prediction/mortality_mimic3_agent.py`` + * - `mortality_prediction/mortality_mimic3_agent.py `_ - Agent model for mortality prediction on MIMIC-III - * - ``mortality_prediction/mortality_mimic3_concare.py`` + * - `mortality_prediction/mortality_mimic3_concare.py `_ - ConCare for mortality prediction on MIMIC-III - * - ``mortality_prediction/mortality_mimic3_grasp.py`` + * - `mortality_prediction/mortality_mimic3_grasp.py `_ - GRASP for mortality prediction on MIMIC-III - * - ``mortality_prediction/mortality_mimic3_tcn.py`` + * - `mortality_prediction/mortality_mimic3_tcn.py `_ - Temporal Convolutional Network for mortality prediction - * - ``mortality_prediction/mortality_mimic4_stagenet_v2.py`` + * - `mortality_prediction/mortality_mimic4_stagenet_v2.py `_ - StageNet for mortality prediction on MIMIC-IV (v2) - * - ``mortality_prediction/timeseries_mimic4.py`` + * - `mortality_prediction/timeseries_mimic4.py `_ - Time series analysis on MIMIC-IV Readmission Prediction @@ -122,11 +123,11 @@ These examples are located in ``examples/readmission/``. * - Example File - Description - * - ``readmission/readmission_mimic3_rnn.py`` + * - `readmission/readmission_mimic3_rnn.py `_ - RNN for readmission prediction on MIMIC-III - * - ``readmission/readmission_mimic3_fairness.py`` + * - `readmission/readmission_mimic3_fairness.py `_ - Fairness-aware readmission prediction on MIMIC-III - * - ``readmission/readmission_omop_rnn.py`` + * - `readmission/readmission_omop_rnn.py `_ - RNN for readmission prediction on OMOP dataset Survival Prediction @@ -138,7 +139,7 @@ Survival Prediction * - Example File - Description - * - ``survival_preprocess_support2_demo.py`` + * - `survival_preprocess_support2_demo.py `_ - Survival probability prediction preprocessing with SUPPORT2 dataset. Demonstrates feature extraction (demographics, vitals, labs, scores, comorbidities) and ground truth survival probability labels for 2-month and 6-month horizons. Shows how to decode processed tensors back to human-readable features. Drug Recommendation @@ -152,21 +153,21 @@ These examples are located in ``examples/drug_recommendation/``. * - Example File - Description - * - ``drug_recommendation/drug_recommendation_mimic3_safedrug.py`` + * - `drug_recommendation/drug_recommendation_mimic3_safedrug.py `_ - SafeDrug for drug recommendation on MIMIC-III - * - ``drug_recommendation/drug_recommendation_mimic3_molerec.py`` + * - `drug_recommendation/drug_recommendation_mimic3_molerec.py `_ - MoleRec for drug recommendation on MIMIC-III - * - ``drug_recommendation/drug_recommendation_mimic3_gamenet.py`` + * - `drug_recommendation/drug_recommendation_mimic3_gamenet.py `_ - GAMENet for drug recommendation on MIMIC-III - * - ``drug_recommendation/drug_recommendation_mimic3_transformer.py`` + * - `drug_recommendation/drug_recommendation_mimic3_transformer.py `_ - Transformer for drug recommendation on MIMIC-III - * - ``drug_recommendation/drug_recommendation_mimic3_micron.py`` + * - `drug_recommendation/drug_recommendation_mimic3_micron.py `_ - MICRON for drug recommendation on MIMIC-III - * - ``drug_recommendation/drug_recommendation_mimic4_gamenet.py`` + * - `drug_recommendation/drug_recommendation_mimic4_gamenet.py `_ - GAMENet for drug recommendation on MIMIC-IV - * - ``drug_recommendation/drug_recommendation_mimic4_retain.py`` + * - `drug_recommendation/drug_recommendation_mimic4_retain.py `_ - RETAIN for drug recommendation on MIMIC-IV - * - ``drug_recommendation/drug_recommendation_eICU_transformer.py`` + * - `drug_recommendation/drug_recommendation_eicu_transformer.py `_ - Transformer for drug recommendation on eICU EEG and Sleep Analysis @@ -178,17 +179,17 @@ EEG and Sleep Analysis * - Example File - Description - * - ``sleep_staging_sleepEDF_contrawr.py`` + * - `eeg/sleep_staging/sleep_staging_sleepEDF_contrawr.py `_ - ContraWR for sleep staging on SleepEDF - * - ``sleep_staging_shhs_contrawr.py`` + * - `eeg/sleep_staging/sleep_staging_shhs_contrawr.py `_ - ContraWR for sleep staging on SHHS - * - ``sleep_staging_ISRUC_SparcNet.py`` + * - `eeg/sleep_staging/sleep_staging_ISRUC_SparcNet.py `_ - SparcNet for sleep staging on ISRUC - * - ``EEG_events_SparcNet.py`` + * - `eeg/eeg_models/SparcNet_eeg_events_classification.py `_ - SparcNet for EEG event detection - * - ``EEG_isAbnormal_SparcNet.py`` + * - `eeg/eeg_models/SparcNet_eeg_abnormal_classification.py `_ - SparcNet for EEG abnormality detection - * - ``cardiology_detection_isAR_SparcNet.py`` + * - `cardiology_detection_isAR_SparcNet.py `_ - SparcNet for cardiology arrhythmia detection Image Analysis (Chest X-Ray) @@ -202,21 +203,21 @@ These examples are located in ``examples/cxr/``. * - Example File - Description - * - ``cxr/covid19cxr_tutorial.py`` + * - `cxr/covid19cxr_tutorial.py `_ - ViT training, conformal prediction & interpretability for COVID-19 CXR - * - ``cxr/covid19cxr_conformal.py`` + * - `cxr/covid19cxr_conformal.py `_ - Conformal prediction for COVID-19 CXR classification - * - ``cxr/cnn_cxr.ipynb`` + * - `cxr/cnn_cxr.ipynb `_ - CNN for chest X-ray classification (notebook) - * - ``cxr/chestxray14_binary_classification.ipynb`` + * - `cxr/chestxray14_binary_classification.ipynb `_ - Binary classification on ChestX-ray14 dataset (notebook) - * - ``cxr/chestxray14_multilabel_classification.ipynb`` + * - `cxr/chestxray14_multilabel_classification.ipynb `_ - Multi-label classification on ChestX-ray14 dataset (notebook) - * - ``cxr/ChestXrayClassificationWithSaliency.ipynb`` + * - `cxr/ChestXrayClassificationWithSaliency.ipynb `_ - Chest X-ray classification with saliency maps (notebook) - * - ``cxr/chextXray_image_generation_VAE.py`` + * - `cxr/chextXray_image_generation_VAE.py `_ - VAE for chest X-ray image generation - * - ``cxr/ChestXray-image-generation-GAN.ipynb`` + * - `cxr/ChestXray-image-generation-GAN.ipynb `_ - GAN for chest X-ray image generation (notebook) Interpretability @@ -230,21 +231,21 @@ These examples are located in ``examples/interpretability/``. * - Example File - Description - * - ``integrated_gradients_mortality_mimic4_stagenet.py`` + * - `interpretability/integrated_gradients_mortality_mimic4_stagenet.py `_ - Integrated Gradients for StageNet interpretability - * - ``interpretability/deeplift_stagenet_mimic4.py`` + * - `interpretability/deeplift_stagenet_mimic4.py `_ - DeepLift attributions for StageNet on MIMIC-IV - * - ``interpretability/gim_stagenet_mimic4.py`` + * - `interpretability/gim_stagenet_mimic4.py `_ - GIM attributions for StageNet on MIMIC-IV - * - ``interpretability/gim_transformer_mimic4.py`` + * - `interpretability/gim_transformer_mimic4.py `_ - GIM attributions for Transformer on MIMIC-IV - * - ``interpretability/shap_stagenet_mimic4.py`` + * - `interpretability/shap_stagenet_mimic4.py `_ - SHAP attributions for StageNet on MIMIC-IV - * - ``interpretability/interpretability_metrics.py`` + * - `interpretability/interpretability_metrics.py `_ - Evaluating attribution methods with metrics - * - ``interpretability/interpret_demo.ipynb`` + * - `interpretability/interpret_demo.ipynb `_ - Interactive interpretability demonstrations (notebook) - * - ``interpretability/shap_stagenet_mimic4.ipynb`` + * - `interpretability/shap_stagenet_mimic4.ipynb `_ - SHAP attributions for StageNet (notebook) Patient Linkage @@ -256,7 +257,7 @@ Patient Linkage * - Example File - Description - * - ``patient_linkage_mimic3_medlink.py`` + * - `patient_linkage_mimic3_medlink.py `_ - MedLink for patient record linkage on MIMIC-III Length of Stay @@ -270,9 +271,9 @@ These examples are located in ``examples/length_of_stay/``. * - Example File - Description - * - ``length_of_stay/length_of_stay_mimic3_rnn.py`` + * - `length_of_stay/length_of_stay_mimic3_rnn.py `_ - RNN for length of stay prediction on MIMIC-III - * - ``length_of_stay/length_of_stay_mimic4_rnn.py`` + * - `length_of_stay/length_of_stay_mimic4_rnn.py `_ - RNN for length of stay prediction on MIMIC-IV Advanced Topics @@ -284,11 +285,11 @@ Advanced Topics * - Example File - Description - * - ``omop_dataset_demo.py`` + * - `omop_dataset_demo.py `_ - Working with OMOP Common Data Model - * - ``medcode.py`` + * - `medcode.py `_ - Medical code vocabulary and mappings - * - ``benchmark_ehrshot_xgboost.ipynb`` + * - `benchmark_ehrshot_xgboost.ipynb `_ - EHRShot benchmark with XGBoost (notebook) Notebooks (Interactive) @@ -300,36 +301,33 @@ Notebooks (Interactive) * - Notebook File - Description - * - ``tutorial_stagenet_comprehensive.ipynb`` + * - `tutorial_stagenet_comprehensive.ipynb `_ - Comprehensive StageNet tutorial - * - ``mimic3_mortality_prediction_cached.ipynb`` + * - `mortality_prediction/mimic3_mortality_prediction_cached.ipynb `_ - Cached mortality prediction workflow - * - ``mortality_prediction/timeseries_mimic4.ipynb`` + * - `mortality_prediction/timeseries_mimic4.ipynb `_ - Time series analysis on MIMIC-IV - * - ``transformer_mimic4.ipynb`` + * - `transformer_mimic4.ipynb `_ - Transformer models on MIMIC-IV - * - ``cnn_mimic4.ipynb`` + * - `cnn_mimic4.ipynb `_ - CNN models on MIMIC-IV - * - ``gat_mimic4.ipynb`` + * - `gat_mimic4.ipynb `_ - Graph Attention Networks on MIMIC-IV - * - ``gcn_mimic4.ipynb`` + * - `gcn_mimic4.ipynb `_ - Graph Convolutional Networks on MIMIC-IV - * - ``safedrug_mimic3.ipynb`` + * - `drug_recommendation/safedrug_mimic3.ipynb `_ - SafeDrug interactive notebook - * - ``molerec_mimic3.ipynb`` + * - `molerec_mimic3.ipynb `_ - MoleRec interactive notebook - * - ``drug_recommendation/drug_recommendation_mimic3_micron.ipynb`` + * - `drug_recommendation/drug_recommendation_mimic3_micron.ipynb `_ - MICRON interactive notebook - * - ``kg_embedding.ipynb`` + * - `kg_embedding.ipynb `_ - Knowledge graph embeddings - * - ``lm_embedding_huggingface.ipynb`` + * - `lm_embedding_huggingface.ipynb `_ - Language model embeddings with HuggingFace - * - ``lm_embedding_openai.ipynb`` + * - `lm_embedding_openai.ipynb `_ - Language model embeddings with OpenAI - * - ``prepare_mapping.ipynb`` + * - `prepare_mapping.ipynb `_ - Data preprocessing and mapping utilities - * - ``graph_torchvision_model.ipynb`` + * - `graph_torchvision_model.ipynb `_ - Using Torchvision models with graph data - - ----------- diff --git a/examples/tutorials/tutorial_pyhealth_data.ipynb b/examples/tutorials/tutorial_pyhealth_data.ipynb index ec448d460..5f7b53b6b 100644 --- a/examples/tutorials/tutorial_pyhealth_data.ipynb +++ b/examples/tutorials/tutorial_pyhealth_data.ipynb @@ -5,6 +5,11 @@ "metadata": {}, "source": "# PyHealth Data API Tutorial\n\nThis notebook covers **`pyhealth.data`** \u2014 the foundational layer of PyHealth for representing longitudinal patient records.\n\nYou will learn:\n- How to create and work with **`Event`** objects representing individual clinical events\n- How to build a **`Patient`** object from a structured polars DataFrame\n- How to query a patient's event history using **`get_events()`** with powerful filters\n\n---" }, + { + "cell_type": "markdown", + "metadata": {}, + "source": "## Overview\n\nIn PyHealth, a patient's medical record is modeled as a collection of **events** over time. Each event belongs to a typed category (e.g., `'diagnosis'`, `'lab'`, `'note'`) and carries arbitrary attributes (ICD codes, numeric values, free text, etc.).\n\nThe two core classes are:\n\n| Class | Description |\n|-------|-------------|\n| `Event` | A single timestamped clinical occurrence with typed attributes |\n| `Patient` | A patient identified by `patient_id`, holding all events in a polars DataFrame |\n\nThese classes are optimized for efficient time-range and attribute filtering, using binary search on sorted timestamps and pre-built event-type partitions." + }, { "cell_type": "code", "execution_count": null, @@ -12,11 +17,6 @@ "outputs": [], "source": "!pip install pyhealth" }, - { - "cell_type": "markdown", - "metadata": {}, - "source": "## Overview\n\nIn PyHealth, a patient's medical record is modeled as a collection of **events** over time. Each event belongs to a typed category (e.g., `'diagnosis'`, `'lab'`, `'note'`) and carries arbitrary attributes (ICD codes, numeric values, free text, etc.).\n\nThe two core classes are:\n\n| Class | Description |\n|-------|-------------|\n| `Event` | A single timestamped clinical occurrence with typed attributes |\n| `Patient` | A patient identified by `patient_id`, holding all events in a polars DataFrame |\n\nThese classes are optimized for efficient time-range and attribute filtering, using binary search on sorted timestamps and pre-built event-type partitions." - }, { "cell_type": "code", "execution_count": null, @@ -168,41 +168,36 @@ }, { "cell_type": "markdown", - "id": "26be2c24", - "source": "---\n## Part 5: Bridging to a Real Dataset\n\n| Concept | Key API |\n|---------|----------|\n| Create an event | `Event(event_type, timestamp, **kwargs)` |\n| Access event attribute | `event[\"key\"]`, `event.key`, `\"key\" in event` |\n| Build from raw dict | `Event.from_dict(dict)` |\n| Create a patient | `Patient(patient_id, data_source=pl.DataFrame(...))` |\n| Get all events | `patient.get_events()` |\n| Filter by type | `patient.get_events(event_type=\"diagnoses_icd\")` |\n| Filter by time | `patient.get_events(start=..., end=...)` |\n| Filter by attribute | `patient.get_events(event_type=\"prescriptions\", filters=[(\"route\", \"==\", \"IV\")])` |\n| Return as DataFrame | `patient.get_events(return_df=True)` |\n| Load from MIMIC-III | `MIMIC3Dataset(root=..., tables=[\"diagnoses_icd\", ...])` |\n\n### Table name = event type\n\nWhen using a dataset loader like `MIMIC3Dataset`, the `event_type` on every event equals the **table name** from `mimic3.yaml` \u2014 not a generic category like `\"diagnosis\"`. The available attributes on each event are exactly the columns listed under that table's `attributes` key in the YAML.\n\n```\nTable name \u2192 event_type \u2192 example attributes\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\ndiagnoses_icd \u2192 \"diagnoses_icd\" \u2192 icd9_code, hadm_id, seq_num\nprescriptions \u2192 \"prescriptions\" \u2192 drug, ndc, dose_val_rx, route\nnoteevents \u2192 \"noteevents\" \u2192 text, category, description\nadmissions \u2192 \"admissions\" \u2192 hadm_id, admission_type, hospital_expire_flag\nicustays \u2192 \"icustays\" \u2192 icustay_id, first_careunit, outtime\n```\n\nWhen writing a custom task, always check the relevant YAML config to know the exact attribute names available on events from each table.", - "metadata": {} + "metadata": {}, + "source": "---\n## Summary\n\n| Concept | Key API |\n|---------|----------|\n| Create an event | `Event(event_type, timestamp, **kwargs)` |\n| Access event attribute | `event[\"key\"]`, `event.key`, `\"key\" in event` |\n| Build from raw dict | `Event.from_dict(dict)` |\n| Create a patient | `Patient(patient_id, data_source=pl.DataFrame(...))` |\n| Get all events | `patient.get_events()` |\n| Filter by type | `patient.get_events(event_type=\"diagnoses_icd\")` |\n| Filter by time | `patient.get_events(start=..., end=...)` |\n| Filter by attribute | `patient.get_events(event_type=\"prescriptions\", filters=[(\"route\", \"==\", \"IV\")])` |\n| Return as DataFrame | `patient.get_events(return_df=True)` |\n| Load from MIMIC-III | `MIMIC3Dataset(root=..., tables=[\"diagnoses_icd\", ...])` |\n\n### Table name = event type\n\nWhen using a dataset loader like `MIMIC3Dataset`, the `event_type` on every event equals the **table name** from `mimic3.yaml` \u2014 not a generic category like `\"diagnosis\"`. The available attributes on each event are exactly the columns listed under that table's `attributes` key in the YAML.\n\n```\nTable name \u2192 event_type \u2192 example attributes\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\ndiagnoses_icd \u2192 \"diagnoses_icd\" \u2192 icd9_code, hadm_id, seq_num\nprescriptions \u2192 \"prescriptions\" \u2192 drug, ndc, dose_val_rx, route\nnoteevents \u2192 \"noteevents\" \u2192 text, category, description\nadmissions \u2192 \"admissions\" \u2192 hadm_id, admission_type, hospital_expire_flag\nicustays \u2192 \"icustays\" \u2192 icustay_id, first_careunit, outtime\n```\n\nWhen writing a custom task, always check the relevant YAML config to know the exact attribute names available on events from each table." }, { "cell_type": "code", - "id": "ada1de03", - "source": "from pyhealth.datasets import MIMIC3Dataset\n\nroot = \"https://storage.googleapis.com/pyhealth/Synthetic_MIMIC-III\"\n\ndataset = MIMIC3Dataset(\n root=root,\n dataset_name=\"mimic3\",\n tables=[\n \"diagnoses_icd\", # ICD-9 diagnosis codes per admission\n \"prescriptions\", # medication orders\n \"noteevents\", # clinical notes\n ],\n)\n\nprint(f\"Loaded {len(dataset.patients)} patients\")\n\n# Grab one patient to explore\npatient_id = list(dataset.patients.keys())[0]\npatient = dataset.patients[patient_id]\nprint(f\"\\nPatient ID: {patient.patient_id}\")\nprint(f\"Event types present: {list(patient.event_type_partitions.keys())}\")\nprint(f\"Total events: {len(patient.get_events())}\")", - "metadata": {}, "execution_count": null, - "outputs": [] + "metadata": {}, + "outputs": [], + "source": "from pyhealth.datasets import MIMIC3Dataset\nimport polars as pl\n\nroot = \"https://storage.googleapis.com/pyhealth/Synthetic_MIMIC-III\"\n\ndataset = MIMIC3Dataset(\n root=root,\n dataset_name=\"mimic3\",\n tables=[\n \"diagnoses_icd\", # ICD-9 diagnosis codes per admission\n \"prescriptions\", # medication orders\n \"noteevents\", # clinical notes\n ],\n)\n\nprint(f\"Loaded {len(dataset.unique_patient_ids)} patients\")\n\n# Pick a patient who actually has events from all three tables, so every query\n# below returns something. Notes are sparse in this synthetic set (~1k notes\n# across ~50k patients), so patient 0 almost certainly has none.\npatient_ids_with_notes = (\n dataset.global_event_df\n .filter(pl.col(\"event_type\") == \"noteevents\")\n .select(\"patient_id\")\n .collect()[\"patient_id\"]\n .unique()\n)\npatient_id = patient_ids_with_notes[0]\npatient = dataset.get_patient(patient_id)\n\nprint(f\"\\nPatient ID: {patient.patient_id}\")\nprint(f\"Event types present: {list(patient.event_type_partitions.keys())}\")\nprint(f\"Total events: {len(patient.get_events())}\")" }, { "cell_type": "code", - "id": "65a34af1", - "source": "# Pull diagnosis events \u2014 event_type matches the table name exactly: \"diagnoses_icd\"\ndiagnoses = patient.get_events(\"diagnoses_icd\")\nprint(f\"Diagnosis events: {len(diagnoses)}\")\nprint()\n\n# Each event's attributes come from the 'attributes' list in mimic3.yaml\n# hadm_id, icd9_code, seq_num\nfor dx in diagnoses[:5]:\n print(f\" [{dx.timestamp.date()}] hadm={dx['hadm_id']} \"\n f\"ICD-9={dx['icd9_code']} seq={dx['seq_num']}\")", - "metadata": {}, "execution_count": null, - "outputs": [] + "metadata": {}, + "outputs": [], + "source": "# Pull diagnosis events \u2014 event_type matches the table name exactly: \"diagnoses_icd\"\ndiagnoses = patient.get_events(\"diagnoses_icd\")\nprint(f\"Diagnosis events: {len(diagnoses)}\")\nprint()\n\n# Each event's attributes come from the 'attributes' list in mimic3.yaml\n# hadm_id, icd9_code, seq_num\nfor dx in diagnoses[:5]:\n print(f\" [{dx.timestamp.date()}] hadm={dx['hadm_id']} \"\n f\"ICD-9={dx['icd9_code']} seq={dx['seq_num']}\")" }, { "cell_type": "code", - "id": "8c9817cc", - "source": "# Pull prescription events and filter to a specific route (e.g. IV medications)\nprescriptions = patient.get_events(\"prescriptions\")\nprint(f\"Total prescription events: {len(prescriptions)}\")\n\n# Attribute filters work the same way on real data\niv_meds = patient.get_events(\n event_type=\"prescriptions\",\n filters=[(\"route\", \"==\", \"IV\")],\n)\nprint(f\"IV medications: {len(iv_meds)}\")\nfor rx in iv_meds[:5]:\n print(f\" [{rx.timestamp.date()}] {rx['drug']} dose={rx['dose_val_rx']} ndc={rx['ndc']}\")", - "metadata": {}, "execution_count": null, - "outputs": [] + "metadata": {}, + "outputs": [], + "source": "# Pull prescription events and filter to a specific route (e.g. IV medications)\nprescriptions = patient.get_events(\"prescriptions\")\nprint(f\"Total prescription events: {len(prescriptions)}\")\n\n# Attribute filters work the same way on real data\niv_meds = patient.get_events(\n event_type=\"prescriptions\",\n filters=[(\"route\", \"==\", \"IV\")],\n)\nprint(f\"IV medications: {len(iv_meds)}\")\nfor rx in iv_meds[:5]:\n print(f\" [{rx.timestamp.date()}] {rx['drug']} dose={rx['dose_val_rx']} ndc={rx['ndc']}\")" }, { "cell_type": "code", - "id": "8892105c", - "source": "# Clinical note events \u2014 attribute 'text' holds the full note body\n# Attributes available: text, category, description, hadm_id, storetime (from mimic3.yaml)\nnotes = patient.get_events(\"noteevents\")\nprint(f\"Note events: {len(notes)}\")\n\ndischarge_notes = patient.get_events(\n event_type=\"noteevents\",\n filters=[(\"category\", \"==\", \"Discharge summary\")],\n)\nprint(f\"Discharge summaries: {len(discharge_notes)}\")\nif discharge_notes:\n first_note = discharge_notes[0]\n print(f\"\\n Date: {first_note.timestamp.date()}\")\n print(f\" Category: {first_note['category']}\")\n print(f\" Text preview: {str(first_note['text'])[:200]}...\")", - "metadata": {}, "execution_count": null, - "outputs": [] + "metadata": {}, + "outputs": [], + "source": "# Clinical note events \u2014 attribute 'text' holds the full note body\n# Attributes available: text, category, description, hadm_id, storetime (from mimic3.yaml)\nnotes = patient.get_events(\"noteevents\")\nprint(f\"Note events: {len(notes)}\")\n\ndischarge_notes = patient.get_events(\n event_type=\"noteevents\",\n filters=[(\"category\", \"==\", \"Discharge summary\")],\n)\nprint(f\"Discharge summaries: {len(discharge_notes)}\")\nif discharge_notes:\n first_note = discharge_notes[0]\n print(f\"\\n Date: {first_note.timestamp.date()}\")\n print(f\" Category: {first_note['category']}\")\n print(f\" Text preview: {str(first_note['text'])[:200]}...\")" }, { "cell_type": "markdown", diff --git a/examples/tutorials/tutorial_pyhealth_medcode.ipynb b/examples/tutorials/tutorial_pyhealth_medcode.ipynb index 07a8cad8b..0b489e0f1 100644 --- a/examples/tutorials/tutorial_pyhealth_medcode.ipynb +++ b/examples/tutorials/tutorial_pyhealth_medcode.ipynb @@ -178,7 +178,7 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": "# Pattern 2: Translate a patient's ICD-9 code list to CCS before modeling\n# This dramatically reduces vocabulary size.\n\ndef translate_codes_to_ccs(icd9_codes, crossmap):\n \"\"\"Map a list of ICD-9 codes to CCS categories.\"\"\"\n ccs_codes = []\n for code in icd9_codes:\n mapped = crossmap.map(code)\n ccs_codes.extend(mapped)\n return list(set(ccs_codes)) # deduplicate\n\n# Example patient from MIMIC-III\npatient_icd9_codes = [\"250.00\", \"401.9\", \"428.0\", \"585.3\"]\n# = Type 2 DM, Essential hypertension, Heart failure, CKD stage 3\n\npatient_ccs_codes = translate_codes_to_ccs(patient_icd9_codes, cm_9toCCS)\nprint(\"ICD-9 codes:\", patient_icd9_codes)\nprint(\"CCS codes: \", patient_ccs_codes)\nprint(f\"Vocabulary reduction: {len(icd9cm.graph.nodes)} ICD-9 codes \u2192 ~300 CCS categories\")" + "source": "# Pattern 2: Translate a patient's ICD-9 code list to CCS before modeling\n# This dramatically reduces vocabulary size.\n\ndef translate_codes_to_ccs(icd9_codes, crossmap):\n \"\"\"Map a list of ICD-9 codes to CCS categories.\"\"\"\n ccs_codes = []\n for code in icd9_codes:\n mapped = crossmap.map(code)\n ccs_codes.extend(mapped)\n return sorted(set(ccs_codes)) # deduplicate (sorted: set order is not stable)\n\n# Example patient from MIMIC-III\npatient_icd9_codes = [\"250.00\", \"401.9\", \"428.0\", \"585.3\"]\n# = Type 2 DM, Essential hypertension, Heart failure, CKD stage 3\n\npatient_ccs_codes = translate_codes_to_ccs(patient_icd9_codes, cm_9toCCS)\nprint(\"ICD-9 codes:\", patient_icd9_codes)\nprint(\"CCS codes: \", patient_ccs_codes)\nprint(f\"Vocabulary reduction: {len(icd9cm.graph.nodes)} ICD-9 codes \u2192 ~300 CCS categories\")" }, { "cell_type": "code", diff --git a/examples/tutorials/tutorial_pyhealth_trainer.ipynb b/examples/tutorials/tutorial_pyhealth_trainer.ipynb index f32b3cf9d..442a4260b 100644 --- a/examples/tutorials/tutorial_pyhealth_trainer.ipynb +++ b/examples/tutorials/tutorial_pyhealth_trainer.ipynb @@ -29,7 +29,7 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": "root = \"https://storage.googleapis.com/pyhealth/Synthetic_MIMIC-III\"\n\ndataset = MIMIC3Dataset(\n root=root,\n dataset_name=\"mimic3\",\n tables=[\n \"diagnoses_icd\", # needed for mortality task (conditions)\n \"procedures_icd\", # needed for mortality task (procedures)\n \"prescriptions\", # needed for mortality task (drugs)\n \"noteevents\", # clinical notes (not used by basic task, but loaded for reference)\n ],\n)\n\nprint(\"Dataset loaded.\")\nprint(f\" Number of patients: {len(dataset.patients)}\")" + "source": "root = \"https://storage.googleapis.com/pyhealth/Synthetic_MIMIC-III\"\n\ndataset = MIMIC3Dataset(\n root=root,\n dataset_name=\"mimic3\",\n tables=[\n \"diagnoses_icd\", # needed for mortality task (conditions)\n \"procedures_icd\", # needed for mortality task (procedures)\n \"prescriptions\", # needed for mortality task (drugs)\n \"noteevents\", # clinical notes (not used by basic task, but loaded for reference)\n ],\n)\n\nprint(\"Dataset loaded.\")\nprint(f\" Number of patients: {len(dataset.unique_patient_ids)}\")" }, { "cell_type": "markdown", @@ -160,9 +160,8 @@ }, { "cell_type": "markdown", - "id": "b8313bc0", - "source": "---\n## API Reference: Available Metric Strings\n\nThe `metrics` argument to `Trainer.__init__` and the `monitor` argument to `trainer.train()` are plain strings drawn from a fixed list. The exact list depends on **`model.mode`**, which is set automatically from the task's output schema:\n\n```python\nprint(model.mode) # \u2192 \"binary\" | \"multiclass\" | \"multilabel\" | \"regression\"\n```\n\n`Trainer` uses `model.mode` to select the right metrics function, then passes your `metrics` list to it. Any string you pass to `monitor` must appear in that same list \u2014 otherwise evaluation will raise a `KeyError`.\n\nTo compute a non-default set of metrics and track a specific one:\n```python\ntrainer = Trainer(\n model=model,\n metrics=[\"roc_auc\", \"pr_auc\", \"balanced_accuracy\", \"ECE\"], # computed every eval epoch\n)\ntrainer.train(..., monitor=\"pr_auc\", monitor_criterion=\"max\")\n```\n\n---\n\n### Binary classification \u2014 `mode = \"binary\"`\n**Source:** `pyhealth.metrics.binary_metrics_fn` \n**Defaults when `metrics=None`:** `[\"pr_auc\", \"roc_auc\", \"f1\"]`\n\n| Metric string | Description | `monitor_criterion` |\n|---|---|---|\n| `\"pr_auc\"` | Area under the Precision-Recall curve | `\"max\"` |\n| `\"roc_auc\"` | Area under the ROC curve | `\"max\"` |\n| `\"f1\"` | F1 score at `threshold` (default 0.5) | `\"max\"` |\n| `\"accuracy\"` | Fraction of correct predictions | `\"max\"` |\n| `\"balanced_accuracy\"` | Accuracy adjusted for class imbalance | `\"max\"` |\n| `\"precision\"` | Precision at `threshold` | `\"max\"` |\n| `\"recall\"` | Recall at `threshold` | `\"max\"` |\n| `\"cohen_kappa\"` | Cohen's kappa (agreement beyond chance) | `\"max\"` |\n| `\"jaccard\"` | Jaccard similarity coefficient | `\"max\"` |\n| `\"ECE\"` | Expected Calibration Error (20 equal-width bins) | `\"min\"` |\n| `\"ECE_adapt\"` | Adaptive ECE (20 equal-size bins) | `\"min\"` |\n\n---\n\n### Multiclass classification \u2014 `mode = \"multiclass\"`\n**Source:** `pyhealth.metrics.multiclass_metrics_fn` \n**Defaults when `metrics=None`:** `[\"accuracy\", \"f1_macro\", \"f1_micro\"]`\n\n| Metric string | Description | `monitor_criterion` |\n|---|---|---|\n| `\"accuracy\"` | Overall accuracy | `\"max\"` |\n| `\"balanced_accuracy\"` | Accuracy adjusted for class imbalance | `\"max\"` |\n| `\"f1_macro\"` | F1, macro-averaged across classes | `\"max\"` |\n| `\"f1_micro\"` | F1, micro-averaged across classes | `\"max\"` |\n| `\"f1_weighted\"` | F1, weighted by class support | `\"max\"` |\n| `\"roc_auc_macro_ovo\"` | ROC-AUC, macro, one-vs-one | `\"max\"` |\n| `\"roc_auc_macro_ovr\"` | ROC-AUC, macro, one-vs-rest | `\"max\"` |\n| `\"roc_auc_weighted_ovo\"` | ROC-AUC, weighted, one-vs-one | `\"max\"` |\n| `\"roc_auc_weighted_ovr\"` | ROC-AUC, weighted, one-vs-rest | `\"max\"` |\n| `\"jaccard_micro\"` | Jaccard, micro-averaged | `\"max\"` |\n| `\"jaccard_macro\"` | Jaccard, macro-averaged | `\"max\"` |\n| `\"jaccard_weighted\"` | Jaccard, weighted | `\"max\"` |\n| `\"cohen_kappa\"` | Cohen's kappa | `\"max\"` |\n| `\"brier_top1\"` | Brier score for the top predicted class | `\"min\"` |\n| `\"ECE\"` | Expected Calibration Error (20 equal-width bins) | `\"min\"` |\n| `\"ECE_adapt\"` | Adaptive ECE (20 equal-size bins) | `\"min\"` |\n| `\"cwECEt\"` | Classwise ECE with threshold = min(0.01, 1/K) | `\"min\"` |\n| `\"cwECEt_adapt\"` | Classwise adaptive ECE | `\"min\"` |\n| `\"hits@n\"` | HITS@1 / HITS@5 / HITS@10 (produces 3 dict keys) | `\"max\"` |\n| `\"mean_rank\"` | Mean rank + mean reciprocal rank | `\"min\"` |\n\n---\n\n### Multilabel classification \u2014 `mode = \"multilabel\"`\n**Source:** `pyhealth.metrics.multilabel_metrics_fn` \n**Defaults when `metrics=None`:** `[\"pr_auc_samples\"]` \n**Note:** threshold defaults to `0.3` (not `0.5`) \u2014 lower thresholds are common in drug recommendation tasks.\n\n| Metric string | Description | `monitor_criterion` |\n|---|---|---|\n| `\"pr_auc_samples\"` | PR-AUC, averaged across samples | `\"max\"` |\n| `\"pr_auc_micro\"` | PR-AUC, micro-averaged | `\"max\"` |\n| `\"pr_auc_macro\"` | PR-AUC, macro-averaged | `\"max\"` |\n| `\"pr_auc_weighted\"` | PR-AUC, weighted | `\"max\"` |\n| `\"roc_auc_samples\"` | ROC-AUC, samples-averaged | `\"max\"` |\n| `\"roc_auc_micro\"` | ROC-AUC, micro-averaged | `\"max\"` |\n| `\"roc_auc_macro\"` | ROC-AUC, macro-averaged | `\"max\"` |\n| `\"roc_auc_weighted\"` | ROC-AUC, weighted | `\"max\"` |\n| `\"f1_samples\"` | F1, samples-averaged | `\"max\"` |\n| `\"f1_micro\"` | F1, micro-averaged | `\"max\"` |\n| `\"f1_macro\"` | F1, macro-averaged | `\"max\"` |\n| `\"f1_weighted\"` | F1, weighted | `\"max\"` |\n| `\"precision_micro\"` / `\"_macro\"` / `\"_weighted\"` / `\"_samples\"` | Precision variants | `\"max\"` |\n| `\"recall_micro\"` / `\"_macro\"` / `\"_weighted\"` / `\"_samples\"` | Recall variants | `\"max\"` |\n| `\"jaccard_micro\"` / `\"_macro\"` / `\"_weighted\"` / `\"_samples\"` | Jaccard variants | `\"max\"` |\n| `\"accuracy\"` | Element-wise accuracy | `\"max\"` |\n| `\"hamming_loss\"` | Hamming loss | `\"min\"` |\n| `\"ddi\"` | Drug-drug interaction rate (drug recommendation only) | `\"min\"` |\n| `\"cwECE\"` | Classwise ECE (20 equal-width bins) | `\"min\"` |\n| `\"cwECE_adapt\"` | Classwise adaptive ECE | `\"min\"` |\n\n---\n\n### Regression \u2014 `mode = \"regression\"`\n**Source:** `pyhealth.metrics.regression_metrics_fn` \n**Defaults when `metrics=None`:** `[\"kl_divergence\", \"mse\", \"mae\"]`\n\n| Metric string | Description | `monitor_criterion` |\n|---|---|---|\n| `\"mae\"` | Mean Absolute Error | `\"min\"` |\n| `\"mse\"` | Mean Squared Error | `\"min\"` |\n| `\"kl_divergence\"` | KL divergence between true and reconstructed distributions | `\"min\"` |", - "metadata": {} + "metadata": {}, + "source": "---\n## API Reference: Available Metric Strings\n\nThe `metrics` argument to `Trainer.__init__` and the `monitor` argument to `trainer.train()` are plain strings drawn from a fixed list. The exact list depends on **`model.mode`**, which is set automatically from the task's output schema:\n\n```python\nprint(model.mode) # \u2192 \"binary\" | \"multiclass\" | \"multilabel\" | \"regression\"\n```\n\n`Trainer` uses `model.mode` to select the right metrics function, then passes your `metrics` list to it. Any string you pass to `monitor` must appear in that same list \u2014 otherwise evaluation will raise a `KeyError`.\n\nTo compute a non-default set of metrics and track a specific one:\n```python\ntrainer = Trainer(\n model=model,\n metrics=[\"roc_auc\", \"pr_auc\", \"balanced_accuracy\", \"ECE\"], # computed every eval epoch\n)\ntrainer.train(..., monitor=\"pr_auc\", monitor_criterion=\"max\")\n```\n\n---\n\n### Binary classification \u2014 `mode = \"binary\"`\n**Source:** `pyhealth.metrics.binary_metrics_fn` \n**Defaults when `metrics=None`:** `[\"pr_auc\", \"roc_auc\", \"f1\"]`\n\n| Metric string | Description | `monitor_criterion` |\n|---|---|---|\n| `\"pr_auc\"` | Area under the Precision-Recall curve | `\"max\"` |\n| `\"roc_auc\"` | Area under the ROC curve | `\"max\"` |\n| `\"f1\"` | F1 score at `threshold` (default 0.5) | `\"max\"` |\n| `\"accuracy\"` | Fraction of correct predictions | `\"max\"` |\n| `\"balanced_accuracy\"` | Accuracy adjusted for class imbalance | `\"max\"` |\n| `\"precision\"` | Precision at `threshold` | `\"max\"` |\n| `\"recall\"` | Recall at `threshold` | `\"max\"` |\n| `\"cohen_kappa\"` | Cohen's kappa (agreement beyond chance) | `\"max\"` |\n| `\"jaccard\"` | Jaccard similarity coefficient | `\"max\"` |\n| `\"ECE\"` | Expected Calibration Error (20 equal-width bins) | `\"min\"` |\n| `\"ECE_adapt\"` | Adaptive ECE (20 equal-size bins) | `\"min\"` |\n\n---\n\n### Multiclass classification \u2014 `mode = \"multiclass\"`\n**Source:** `pyhealth.metrics.multiclass_metrics_fn` \n**Defaults when `metrics=None`:** `[\"accuracy\", \"f1_macro\", \"f1_micro\"]`\n\n| Metric string | Description | `monitor_criterion` |\n|---|---|---|\n| `\"accuracy\"` | Overall accuracy | `\"max\"` |\n| `\"balanced_accuracy\"` | Accuracy adjusted for class imbalance | `\"max\"` |\n| `\"f1_macro\"` | F1, macro-averaged across classes | `\"max\"` |\n| `\"f1_micro\"` | F1, micro-averaged across classes | `\"max\"` |\n| `\"f1_weighted\"` | F1, weighted by class support | `\"max\"` |\n| `\"roc_auc_macro_ovo\"` | ROC-AUC, macro, one-vs-one | `\"max\"` |\n| `\"roc_auc_macro_ovr\"` | ROC-AUC, macro, one-vs-rest | `\"max\"` |\n| `\"roc_auc_weighted_ovo\"` | ROC-AUC, weighted, one-vs-one | `\"max\"` |\n| `\"roc_auc_weighted_ovr\"` | ROC-AUC, weighted, one-vs-rest | `\"max\"` |\n| `\"jaccard_micro\"` | Jaccard, micro-averaged | `\"max\"` |\n| `\"jaccard_macro\"` | Jaccard, macro-averaged | `\"max\"` |\n| `\"jaccard_weighted\"` | Jaccard, weighted | `\"max\"` |\n| `\"cohen_kappa\"` | Cohen's kappa | `\"max\"` |\n| `\"brier_top1\"` | Brier score for the top predicted class | `\"min\"` |\n| `\"ECE\"` | Expected Calibration Error (20 equal-width bins) | `\"min\"` |\n| `\"ECE_adapt\"` | Adaptive ECE (20 equal-size bins) | `\"min\"` |\n| `\"cwECEt\"` | Classwise ECE with threshold = min(0.01, 1/K) | `\"min\"` |\n| `\"cwECEt_adapt\"` | Classwise adaptive ECE | `\"min\"` |\n| `\"hits@n\"` | HITS@1 / HITS@5 / HITS@10 (produces 3 dict keys) | `\"max\"` |\n| `\"mean_rank\"` | Mean rank + mean reciprocal rank | `\"min\"` |\n\n---\n\n### Multilabel classification \u2014 `mode = \"multilabel\"`\n**Source:** `pyhealth.metrics.multilabel_metrics_fn` \n**Defaults when `metrics=None`:** `[\"pr_auc_samples\"]` \n**Note:** threshold defaults to `0.3` (not `0.5`) \u2014 lower thresholds are common in drug recommendation tasks.\n\n| Metric string | Description | `monitor_criterion` |\n|---|---|---|\n| `\"pr_auc_samples\"` | PR-AUC, averaged across samples | `\"max\"` |\n| `\"pr_auc_micro\"` | PR-AUC, micro-averaged | `\"max\"` |\n| `\"pr_auc_macro\"` | PR-AUC, macro-averaged | `\"max\"` |\n| `\"pr_auc_weighted\"` | PR-AUC, weighted | `\"max\"` |\n| `\"roc_auc_samples\"` | ROC-AUC, samples-averaged | `\"max\"` |\n| `\"roc_auc_micro\"` | ROC-AUC, micro-averaged | `\"max\"` |\n| `\"roc_auc_macro\"` | ROC-AUC, macro-averaged | `\"max\"` |\n| `\"roc_auc_weighted\"` | ROC-AUC, weighted | `\"max\"` |\n| `\"f1_samples\"` | F1, samples-averaged | `\"max\"` |\n| `\"f1_micro\"` | F1, micro-averaged | `\"max\"` |\n| `\"f1_macro\"` | F1, macro-averaged | `\"max\"` |\n| `\"f1_weighted\"` | F1, weighted | `\"max\"` |\n| `\"precision_micro\"` / `\"_macro\"` / `\"_weighted\"` / `\"_samples\"` | Precision variants | `\"max\"` |\n| `\"recall_micro\"` / `\"_macro\"` / `\"_weighted\"` / `\"_samples\"` | Recall variants | `\"max\"` |\n| `\"jaccard_micro\"` / `\"_macro\"` / `\"_weighted\"` / `\"_samples\"` | Jaccard variants | `\"max\"` |\n| `\"accuracy\"` | Element-wise accuracy | `\"max\"` |\n| `\"hamming_loss\"` | Hamming loss | `\"min\"` |\n| `\"ddi\"` | Drug-drug interaction rate (drug recommendation only) | `\"min\"` |\n| `\"cwECE\"` | Classwise ECE (20 equal-width bins) | `\"min\"` |\n| `\"cwECE_adapt\"` | Classwise adaptive ECE | `\"min\"` |\n\n---\n\n### Regression \u2014 `mode = \"regression\"`\n**Source:** `pyhealth.metrics.regression_metrics_fn` \n**Defaults when `metrics=None`:** `[\"kl_divergence\", \"mse\", \"mae\"]`\n\n| Metric string | Description | `monitor_criterion` |\n|---|---|---|\n| `\"mae\"` | Mean Absolute Error | `\"min\"` |\n| `\"mse\"` | Mean Squared Error | `\"min\"` |\n| `\"kl_divergence\"` | KL divergence between true and reconstructed distributions | `\"min\"` |" } ], "metadata": {