Skip to content

ML4H merge: tranche 1 - #1185

Open
will-pang wants to merge 12 commits into
sunlabuiuc:masterfrom
Multimodal-PyHealth:ml4h-merge-tranche-1
Open

ML4H merge: tranche 1#1185
will-pang wants to merge 12 commits into
sunlabuiuc:masterfrom
Multimodal-PyHealth:ml4h-merge-tranche-1

Conversation

@will-pang

@will-pang will-pang commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

A first pass at consolidating all the work we did so that we can merge to main. I'll probably need everyone's help in reviewing this (@joshuasteier, @Rian354, @joshuxchn, as well as @jhnwu3), but in short the updates here add in unified embedding support and tested across the different backbones (RNN, transformer, bottleneck
transformer, EHRMamba, JambaEHR) that we're interested in presenting results. In terms of modality, this focuses only on labs, labs + notes, labs + notes + cxr.

Three big updates made

  • Removed all sample re-weighting work
  • Removed observation windows
  • Removed ICD-10 codes

What to remove

  • All references in pyhealth/scripts/ which I've used to submit to condor and can be removed.

@will-pang will-pang changed the title Ml4h merge tranche 1 ML4H merge: tranche 1 Aug 11, 2026
Rian354 and others added 4 commits August 17, 2026 07:20
Empty notes, labs, CXR, and ICD are now zero-length sequences instead of a
constant [MISSING_TEXT] row, black image, or pad visit. The tokenizer crash
on empty batches is handled by constructing empty tensors, so BERT cannot
treat note presence as a free mortality feature.

Co-authored-by: Cursor <cursoragent@cursor.com>
nn.Module.train() re-enables dropout inside Bio_ClinicalBERT even when
every weight has requires_grad=False. Pin those encoders back to eval so
a frozen note embedding is deterministic across steps.

Co-authored-by: Cursor <cursoragent@cursor.com>
A frozen BERT forward is identical across epochs, but batch padding width
changes every shuffle, so a key over the full padded row never hits.
Hash only the attended tokens so the same note reuses its [CLS] vector.

Co-authored-by: Cursor <cursoragent@cursor.com>
a0f1422 deleted _scan_table/_scan_parquet while MEDSDataset._subset_patient_ids still calls _scan_parquet, so MEDS loads crashed. load_table routes through _scan_table again, and resolve_table_path keeps absolute cache paths. The test reads a real two-row parquet file.

Co-authored-by: Cursor <cursoragent@cursor.com>
@Rian354

Rian354 commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

Pushed four proven repairs onto this branch (fast-forward from 2b7b2c5, no rebase).

  1. 9782aca Stop emitting fake missing-event placeholders ([MISSING_TEXT] / pad visits / black frames). Empty modalities are zero events.
  2. 869ac8e Keep frozen text encoders in eval when Trainer calls train(), so BERT dropout cannot fire on a frozen encoder.
  3. 11beefc Cache frozen [CLS] embeddings keyed on real tokens, not padded rows (padded-row keys never hit under shuffle).
  4. 86fe73b Restore BaseDataset._scan_table / _scan_parquet. MEDS still calls _scan_parquet after a0f1422 deleted them. Proof: tests/test_p0_parquet_scan.py reads a real two-row parquet file.

Still local, not on this PR yet: pad-mask / fp16 fill, nested padding_idx=0, sunlab resized_images + cache write.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants