Repository navigation
PyHealth 2.1.0
#1304
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
PyHealth 2.1.0 focuses on making results trustworthy: leakage-free preprocessing with split-aware
set_task, reproducible training, and calibration metrics with patient-level confidence intervals. It also adds an XGBoost model with exact TreeSHAP, Synthea synthetic-patient generation, ICD-9 ↔ ICD-10 translation, and a nine-notebook tutorial series.Warning
Rebuild caches built with more than 10 workers. Before this release,
set_taskwith more than 10 workers could misorder its sample index, so patient-level splits shared patients between train and val/test (on full MIMIC-IV with 32 workers, ~3.6k patients). 2.1.0 fixes this, but caches built that way are still reused as-is. Delete them and rebuild. (#1273)Before you upgrade
torch>=2.10,pyarrow>=23.0.1,dask[complete]>=2026.1.0andlitdata>=0.2.64,<0.2.68. (Unpin dependencies that block security fixes; drop unused urllib3 #1254, Fit processors on the training split in set_task (split=PatientSplit) #1273)icd-mappingsis a new dependency;urllib3is no longer one. (medcode: ICD-9 <-> ICD-10 translation and grouper vocabularies via icd-mappings #1257, Unpin dependencies that block security fixes; drop unused urllib3 #1254)EHRGenerationbase class is removed and there is one task per encoding and dataset (Add NestedMultiHotProcessor and vectorise HALO's visit encoding #1233):EHRGenerationMIMIC3/4: per-visit multi-hot rows, for HALO. These now emitnested_multihotinstead ofnested_sequence.EHRSequenceGenerationMIMIC3/4: per-visit code indices, for GPT-2 and PromptEHR.EHRCodeSetGenerationMIMIC3/4: one code set per patient, for MedGAN and CorGAN.Eventtimestamps: a missing timestamp is nowNone. It used to bedatetime.now(), which sorted before every real event and slipped through time-window filters. (Keep missing Event timestamps as None; make Event copyable and picklable #1247)pyhealthlogger no longer propagates to the root logger, so each message prints once in Jupyter and Colab. (Print each PyHealth log line once in Jupyter and Colab #1285)cache_dirlogs a warning naming the folder it writes to. SetPYHEALTH_REQUIRE_CACHE_DIR=1to make it an error. (Warn about the default dataset cache; allow requiring cache_dir #1264)chat-assistant/demo. (Remove the unmaintained chat-assistant demo #1252)New features
dataset.set_task(task, split=PatientSplit(...))fits every processor on the training patients only and returns(train, val, test)views of one processed cache.PatientSplittakes two or more ratios, for example train/val/calibration/test.Splitinterface.get_dataloader(..., seed=...)gives each loader its own seeded, per-epoch shuffle, in memory and on disk.torch.manual_seedalone now makes runs repeatable.pyhealth.utils.preserve_rng_state().set_task, dataset creation and the interpretability methods no longer change global random state, and importingpyhealth.modelsno longer reseeds numpy and torch.Trainer.trainrestores the best epoch even with logging off (keep_best_in_memory).binary_metrics_fnaddsbrier,oe_ratio,calibration_slopeandcalibration_intercept.pyhealth.metrics.bootstrapwithbootstrap_ciandpaired_bootstrap_diff. Passgroups=to resample whole patients.BaseModel.set_pos_weight(...)takes a number, one number per label, or"balanced"computed from a training dataset. (Add BaseModel.set_pos_weight for imbalanced binary/multilabel outcomes #1267)XGBoostModel(Add XGBoostModel (gradient-boosted trees) with exact TreeSHAP #1278):model.fit(train, val=None), then evaluate with the usualTrainer.bag_of_codes=Trueturns code sequences into per-patient code counts.scale_pos_weightand early stopping.explain()and the newpyhealth.interpret.methods.TreeSHAP.pyhealth.models.Synthearuns the Synthea synthetic-patient generator. It needs Java 17+ and downloads and caches the Synthea JAR.SyntheaCSVDatasetloads Synthea's CSV output.CrossMaptranslates ICD-9 ↔ ICD-10 and maps codes to CCSR categories, chapters and blocks, and chronic-condition indicators, using theicd-mappingspackage.CrossMap.unmapped_codes.NestedMultiHotProcessor("nested_multihot"): one multi-hot row per visit, 8.6× smaller per patient on eICU. (Add NestedMultiHotProcessor and vectorise HALO's visit encoding #1233)TensorProcessor.size()returns the fitted feature width. (Size tensor embeddings without re-processing samples #1262)Fixes
MultimodalMortalityPredictionMIMIC4used chest X-rays taken after the prediction time. (Prevent future X-ray leakage #1229)T1DDKAPredictionMIMIC4counted DKA events recorded before a separate T1DM diagnosis. (Fix T1D DKA timing #1230)Eventobjects could not be copied or unpickled. (Keep missing Event timestamps as None; make Event copyable and picklable #1247)Trainer.evaluatewhenoutput_schemaused a processor class or tuple. (Resolve model.mode for every output_schema form (fixes Trainer.evaluate crash, #914) #1246, fixes PyHealth trainer uses deprecated model.mode attribute instead of checking its output or label processors #914)TransformerDeIDignored its configured feature and label keys. (Fix: Use configured TransformerDeID field names #1224)Docs, examples and infrastructure
examples/tutorials/series/, from a first model to contributing, each runnable on a CPU Colab runtime. (Add a nine-notebook tutorial series, from first model to contributing #1281)set_task, reusing fitted processors, imbalanced outcomes, calibration and bootstrap CIs, cache behaviour, identified data, and logging setup.SECURITY.mddescribes private vulnerability reporting and which files must come from trusted sources. (Add SECURITY.md and least-privilege workflow permissions #1253)See CHANGELOG.md for full details on every change.
Full Changelog: v2.0.2...v2.1.0
This discussion was created from the release PyHealth 2.1.0.
All reactions