Repository navigation
Codex/vae pyhealth2 - #1358
Codex/vae pyhealth2#1358dalloliogm wants to merge 17 commits into
Conversation
Test CoverageTotal: 75.19% (21552 / 28664 lines)
|
|
/review |
|
If the PR is too large, I can split it into two, so the AI review can take place. The changes to the VAE class are small. Most of the new lines come from the notebooks included to describe what is a VAE and how it can be used. I could split those into a different PR |
|
Yes, please split it if possible. |
|
I think the main thing is the .ipynb notebooks are massive, so just one with a simple examples *.py file and then the follow up notebooks would be much appreciated. |
|
Hi, I think the problem was that I forgot to clean up the notebook outputs. I've done that now - can you try reviewing again? There were a few plots that made the notebooks very big - but they should not have been committed. |
|
/review |
There was a problem hiding this comment.
Previous review
AI Review
suggestion: need change
decision: human review
Thank you for coming back to the VAE bounty and porting it to PyHealth 2.0. Adding categorical EHR sequence support, optional label conditioning for images, and three example notebooks is a useful extension. Line coverage for pyhealth/models/vae.py is 88.29%, above the 80% bar, and total repository coverage is 74.07%, above the 60% bar.
A maintainer will also take a look. The change alters the public contract of the existing VAE: hidden_dim changes meaning and default, latent_dim is new, and the generate signature changes. Existing correct calls can therefore break or behave differently, and a maintainer should decide whether that is acceptable.
To get this merged:
- Single-label image datasets. The constructor auto-uses a sole output label as the condition. A dataset with a single multilabel or regression output, for example ChestXray14 multilabel, now raises an error, where the old version ignored labels. Only auto-condition when the label is binary or multiclass, and otherwise ignore it unless
condition_keyis given explicitly. generate(num_samples=...)on labeled image datasets. This now raises because of the auto-conditioning. Please keep unconditional generation working, for example by sampling the condition at random or only conditioning whencondition_keyis passed explicitly.@torch.no_grad()removed fromgenerate. The returned images now require grad, so.numpy()and similar calls fail. Please restore the decorator or detach the output. The olddeviceargument has also been dropped, and the second positional argument is nowsequence_length. Please keep the signature backward compatible or call the change out clearly.hidden_dimsemantics. Previouslyhidden_dimwas the latent size, with a default of 128. It is now the channel width, with a default of 32. ExistingVAE(dataset, hidden_dim=N)calls silently build a different network. Please keephidden_dimas the latent size, or document the break prominently in the description and docs.- Tests. The
COVID19CXRImageGenerationtask tests and the learning test were deleted, although that task still ships. Please restore tests for the task and a test that training reduces the reconstruction error. Also add tests for the new error branches and forTrainer.train.
Optional suggestions:
- In the ChestXray14 notebook, the comment about patient-level splits being streaming subsets looks inaccurate.
split_by_patientreturns subsets thatget_dataloadershould accept, so you could use it directly. - Unsupported PIL modes such as "P" raise a bare
KeyErrorat the mode lookup in_init_image. A clearValueErrorwould be friendlier.
Reviewed commit 3e0ff51
|
/review |
|
/review |
There was a problem hiding this comment.
Previous review
AI Review
suggestion: need change
decision: human review
Thank you for this contribution. It extends the PyHealth 2.0 VAE to categorical EHR code sequences and optional label-conditioned image generation, and it adds three example notebooks and docs updates. The new model code looks reasonable. A maintainer will also take a look, because the rewrite of pyhealth/models/vae.py changes the existing VAE's public interface and the format of saved checkpoints.
Coverage: pyhealth/models/vae.py is at 89.05%, above the 80% bar for modified files, and the repository total is 74.11%, above the 60% bar. I did not run the tests or notebooks.
To get this merged:
- Keep backward compatibility, or state the break clearly. The old
encode()anddecode()methods are gone. The attributesencoder,decoder,muandlogvarare renamed, and the ResBlock2D architecture is replaced. State_dicts saved from the previous VAE therefore no longer load. Please restoreencodeanddecode(or add thin wrappers). If the architecture change is intentional, document it in the PR description and the docs as a breaking change. - Image processors without an explicit
modeused to work, because the channel count was read from the data. They now raise a ValueError. Please infer the channel count from a sample whenmodeis None, or document this as an intentional break. Also keep a clear error forto_tensor=False, which the oldto_tensorcheck used to catch. - Restore the test coverage that was removed. The multi-epoch "learns to reconstruct" test is now a single optimizer step. The RGB, gradient-flow and state_dict round-trip tests are gone, so the RGB path used by the COVID classification example is untested. Please add at least an RGB forward-pass test and a state_dict round-trip test.
Optional suggestions:
- The sequence path always samples the latent, even in eval mode, so validation loss is noisy. Using
muwhennot self.trainingwould make it deterministic. - In the synthetic notebook,
torch.manual_seedbefore an eval-mode forward has no effect, so the remark about seeding can be dropped. - The ChestXray14 notebook subclasses the binary task only to add
patient_id. That would be better placed in the task itself.
Reviewed commit 478feab
|
I just noticed that the image-generation part of this bounty was already covered by PR #1351. Thanks for getting that implementation merged. This PR builds on that work by extending the VAE to categorical EHR sequences, alongside image inputs. It adds examples for synthetic image generation, conditional image generation with ChestXray14, and EHR sequence modeling, and expands the tests to cover reconstruction, generation, and Trainer compatibility across both input types. I’ve kept image conditioning opt-in and preserved the existing image VAE behavior and COVID-19 CXR task from #1351. The current CI checks are passing. My aim is to make this a complementary extension to #1351, rather than duplicate its image-generation work. |
|
/review |
|
/review |
| self.channels, height, width = self.image_shape | ||
| if self.channels < 1: | ||
| raise ValueError("Image inputs must have at least one channel.") | ||
| if image_processor.mode is not None and image_processor.mode not in { |
There was a problem hiding this comment.
[medium] Image mode whitelist rejects modes the previous VAE accepted
The new check raises for any ImageProcessor mode outside L/RGB/RGBA. The previous VAE had no mode check: channels are read from the processed sample's shape, so modes such as LA (2 channels) or CMYK (4 channels) worked and now fail at construction. Nothing in the encoder or decoder requires the restriction, and the docs do not mention it. Fix: remove the mode check and rely on the sample-shape check, or document the restriction and keep it only if it is necessary.
| ) | ||
| kl_loss = kl_per_sequence.mean() | ||
| loss = reconstruction_loss + kl_loss | ||
| return { |
There was a problem hiding this comment.
[low] Sequence VAE output lacks y_true/y_prob, so Trainer.inference fails
_forward_sequence returns loss, reconstruction_logits, mu, log_var and mask, but no y_true or y_prob. Trainer.inference (pyhealth/trainer.py around line 391) reads output['y_true'] and output['y_prob'], so it raises KeyError for sequence VAEs. Trainer.train and Trainer.evaluate work. Fix: return y_true and y_prob (for example the tokens and softmax probabilities), or state in the docstring that inference is unsupported.
| if feature_key is None: | ||
| if len(supported_keys) != 1: | ||
| raise ValueError( | ||
| "VAE requires one ImageProcessor or SequenceProcessor input; " |
There was a problem hiding this comment.
[low] Ambiguous-feature error and minimum image size check are no longer tested
The earlier tests for the multiple-input error and the images-smaller-than-8-pixels error were removed, and the new test file has no replacement, so these new and existing validation paths have no coverage. Fix: add a test that a dataset with two supported inputs and no feature_key raises ValueError, and a test that a 4x4 image raises ValueError.
| "VAE supports ImageProcessor modes \"L\", \"RGB\", and " | ||
| f'"RGBA", got {image_processor.mode!r}.' | ||
| ) | ||
| self.image_size = image_processor.image_size or height |
There was a problem hiding this comment.
[low] self.image_size is assigned twice and never read
The attribute is set from the processor, then overwritten with height in the height != width branch, and nothing else in the class reads it. Remove both assignments, or use it. The branch comment describes behavior the code does not need.
| self.pad_token = int(self.sequence_processor.code_vocab.get("<pad>", 0)) | ||
| self.unk_token = self.sequence_processor.code_vocab.get("<unk>") | ||
| self.vocab_size = self.sequence_processor.vocab_size() | ||
| self.embedding_model = EmbeddingModel(dataset, self.sequence_hidden_dim) |
There was a problem hiding this comment.
[low] Sequence VAE builds embedding tables for every input feature
EmbeddingModel(dataset, ...) creates a table for each sequence input in the dataset, but _forward_sequence uses only feature_key. For multi-feature tasks, the unused tables are included in model.parameters() and in the optimizer. Fix: create a single nn.Embedding for the chosen processor, or document the extra parameters.
| BATCH_SIZE = 32 | ||
| EPOCHS = 10 | ||
|
|
||
| base_dataset = COVID19CXRDataset(root=DATA_ROOT) |
There was a problem hiding this comment.
[low] Example runs at import time with no evaluation or main guard
The script trains at module level and prints generated shapes, with no train/validation split or reconstruction check, and the previous example's comparison plots were removed. Wrap the code in main() under an if name == 'main' guard, and consider keeping a reconstruction check so the example demonstrates the model's quality.
There was a problem hiding this comment.
AI Review
suggestion: need change
decision: need change
Thank you for coming back with a fresh PyHealth 2.0 implementation. This PR extends the VAE with a categorical code-sequence path and optional label conditioning for images. It also adds three example notebooks, updated docs, and a patient_id key in ChestXray14BinaryClassification so patient-level splits work. Keeping the image encoder/decoder/mu/logvar module names, the encode()/decode() methods and the hidden_dim latent size is a good choice for compatibility. Coverage meets the bar: pyhealth/models/vae.py is at 85.96% (bar is 80%) and the whole repository is at 75.19% (bar is 60%).
To get this merged:
- Remove the new image-mode restriction in
pyhealth/models/vae.py(around line 172). The check rejects anyImageProcessormode other than"L","RGB"and"RGBA". The previous VAE took the channel count from a processed sample and accepted any mode, such as"LA"or"CMYK". Configurations that worked before would now fail, and I can't see a technical reason for it. Please drop the check, or widen it to match what the model already handled. - Update
test_unsupported_image_mode_raises_value_errorto match. It currently asserts the restriction.
Optional suggestions:
- The sequence VAE doesn't return
y_trueory_prob, soTrainer.inference()raises aKeyErroron it. A short docstring note, or a graceful path, would help. - Two old tests no longer exist: the "multiple inputs without
feature_key" error and the 8-pixel minimum-size check. Please restore them. self.image_sizeis assigned twice and never used invae.py, so it can go.EmbeddingModelallocates tables for every input feature, not only the sequence one.examples/cxr/chextXray_image_generation_VAE.pynow runs at import time, with nomain()guard and no evaluation step. A guard would make it friendlier to import and test.
Reviewed commit f2973cd
Hello,
Almost one year ago I started contributing to the VAE bounty in PyHealth. Unfortunately, I messed up with Git and became busy with work, and time passed, so I never followed up on the review comments on my previous PR.
This is a new implementation of the bounty for PyHealth 2.0.
Contributor: Giovanni Dall’Olio
Contribution Type: Model
Description: The VAE now supports image inputs and categorical EHR code sequences. I’ve also added or updated three notebooks demonstrating synthetic image generation, ChestXray14 image modeling, and EHR sequence modeling, with explanations of potential applications.
Files to Review: