liupei101 / AdvMIL

[MedIA 2024] The implementation of AdvMIL: Adversarial Multiple Instance Learning for the Survival Analysis on Whole-Slide Images
MIT License
29 stars 10 forks source link
adversarial-learning multiple-instance-learning survival-analysis whole-slide-image

AdvMIL: Adversarial Multiple Instance Learning for the Survival Analysis on Whole-Slide Images (accepted by MedIA)

arXiv Preprint | MedIA | Free-accessible paper link (50 days)

TL;DR:

This work proposes a novel adversarial MIL framework for the survival analysis on gagipixel Whole-Slide Images (WSIs). This framework directly estimates the distribution of time-to-event from WSIs by implicitly sampling from generator. It introduces adversarial time-to-event modeling into the MIL paradigm that is much necessary for WSI analysis, by constructing a MIL encoder and a region-level instance projection fusion network for generator and discriminator, respectively. We empirically demonstrate that AdvMIL has the following advantages or abilities: (1) combining it with existing MIL networks for predictive performance enhancement; (2) effectively utilizing unlabeled WSIs for semi-supervised learning; (3) the robustness to patch occlusion, image Gaussian blurring, and image HED color variation.

Requirements

Our experiments run on a workstation with 2 V100s GPUs (python 3.6, torch 1.9.0, and cuda 11.1).

AdvMIL walkthrough

Here we show how to run AdvMIL for WSI survival analysis.

Data preparation

WSI preprocessing toolkit: it is highly recommended to utilize an easy-to-use tool, CLAM, for WSI preprocessing, including dataset download, tissue segmentation, patching, and patch feature extraction. Please see a detailed documentation at https://github.com/mahmoodlab/CLAM, or refer to Tutorial - Processing WSIs for MIL from Scratch for a complete and more detailed tutorial built opon CLAM.

Next, we provide detailed steps to preprocess WSIs using CLAM (assuming you have already known its basic usage):

  1. patching at level = 2 (downsampled 16x): go to CLAM directory and run

    # DATA_DIRECTORY should be the path to raw images (e.g., svs files). 
    # '/data/nlst/processed/tiles-l2-s256' is the path for saving patching results.
    python create_patches_fp.py \
    --source DATA_DIRECTORY \
    --save_dir /data/nlst/processed/tiles-l2-s256 \
    --patch_level 2 --patch_size 256 --seg --patch --stitch

    This step will save the coordinates of segmented patches at level = 2.

  2. patching at level = 1 (downsampled 4x): go back to AdvMIL, go to ./tools, and run

    # '/data/nlst/processed/tiles-l2-s256' is the path for reading the coordinates of patches at the level 2.
    # '/data/nlst/processed/tiles-l1-s256' is the path for saving the coordinates of patches at the level 1. 
    python3 big_to_small_patching.py \
    /data/nlst/processed/tiles-l2-s256 \
    /data/nlst/processed/tiles-l1-s256

    This step will compute and save the patch coordinates at level = 1. /data/nlst/processed/tiles-l2-s256 is exactly the full path of the patch coordinates at level = 2 from previous step.

  3. Feature extracting: go to CLAM directory and run

    # DATA_DIRECTORY should be the path to raw images (e.g., svs files). 
    # 'process_list_autogen.csv' is a csv file generated by the first step, initially in '/data/nlst/processed/tiles-l2-s256'.
    # This csv file is automatically copied to '/data/nlst/processed/tiles-l1-s256'.
    CUDA_VISIBLE_DEVICES=0,1 python extract_features_fp.py \
    --data_h5_dir /data/nlst/processed/tiles-l1-s256 \
    --data_slide_dir DATA_DIRECTORY \
    --csv_path /data/nlst/processed/tiles-l1-s256/process_list_autogen.csv \
    --feat_dir /data/nlst/processed/feat-l1-RN50-B \
    --batch_size 512 --slide_ext .svs

    This step will compute all patch features and save them in /data/nlst/processed/feat-l1-RN50-B. Note that --data_h5_dir should be the full path of the patch coordinates at level = 1 from previous step.

Now it is expected that you have the following file directories (taking nlst for example) in your computer.

A detailed file structure would be as follows:

/data/nlst                               # The directory of nlst.
└─ processed
   ├─ feat-l1-RN50-B                     # The directory of all patch features (level = 1).
   │  └─ pt_files                                   
   │     ├─ 10015.pt                     # The patch features of slide 10015.
   │     ├─ 10016.pt
   │     └─ ...
   │
   ├─ tiles-l1-s256                      # The directory of all segmented patch coordinates (level = 1).
   │  ├─ patches
   │  │  ├─ 10015.h5                     # The patch coordinates of slide 10015.
   │  │  ├─ 10016.h5
   │  │  └─ ...
   │  └─ process_list_autogen.csv        # csv file recording all processing details (autogeneraed by CLAM).
   └─ ...                                # other intermediate directories, such as "tiles-l2-s256" from the first step.         

Options: if you want to a graph-based or cluster-based model, you should further prepare the followings:

Network training

Now you should prepare a YAML file for configuring the setting of read/save path, network architecture, network training, etc. We have provided an example configuration (./config/cfg_nlst.yaml) for training nlst with AdvMIL, as well as the detailed descriptions regarding important configurations.

Here we show and explain some important configurations so that you can successfully finish the configuration of network training.

Three running modes in AdvMIL:

  1. common mode: for conventional training/validation/test, you can directly use our configuration example (./config/cfg_nlst.yaml).
  2. test mode: you just want to test the model trained before, please change test: False to test: True in ./config/cfg_nlst.yaml before running.
  3. semi-supervised training mode: you want to run the semi-supervised training with AdvMIL, please change semi_training: False to semi_training: True in ./config/cfg_nlst.yaml before running.

When you finished the configuration above, you can run the following command (on all folds) for training, validation, and testing:

# load your config in config/cfg_nlst.yaml, and run AdvMIL
# there are three possible running modes after configuration:
# 1. common train/val/test pipeline 
# 2. only test using the models trained before (if set `test` to True)
# 3. semi-supervised train/val/test pipeline (if set `semi_training`` to True)
python3 main.py \
    --config config/cfg_nlst.yaml \
    --handler adv \
    --multi_run

If you only run once (e.g., only single fold), you can use the following command:

# load your config in config/cfg_nlst.yaml, and run AdvMIL
# there are three possible running modes after configuration:
# 1. common train/val/test pipeline (single fold)
# 2. only test using the models trained before (if set `test` to True)
# 3. semi-supervised train/val/test pipeline (if set `semi_training`` to True)
python3 main.py \
    --config config/cfg_nlst.yaml \
    --handler adv

Model release

The best models trained on WSIs, with an architecture of ESAT + AdvMIL, and their training logs are publicly-available at Google Rrive - AdvMIL-models.

Acknowledgment

Reference

Citation

If this work helps your research, please consider citing our paper:

@article{LIU2024103020,
    author = {Liu, Pei and Ji, Luping and Ye, Feng and Fu, Bo},
    title = {{AdvMIL: Adversarial multiple instance learning for the survival analysis on whole-slide images}},
    journal = {Medical Image Analysis},
    volume = {91},
    pages = {103020},
    year = {2024},
    doi = {https://doi.org/10.1016/j.media.2023.103020},
}