一个全自动病理处理分析工具——CLAM

文章目录

  • 1. 简介
  • 2. 环境配置
    • 2.1 环境创建
    • 2.2 安装依赖
    • 2.3 安装预训练编码器
  • 3. 数据集准备
  • 4. 数据处理
    • 4.1 全自动数据预处理
    • 4.2 半自动数据预处理
      • step1:设置分割参数
      • step2:执行预分割
      • step3:调整分割参数
      • step4:批量分割
  • 5. 特征提取
  • 6. 模型训练
    • 6.1 数据集划分
    • 6.2 模型训练
    • 6.3 模型验证
    • 6.4 热图可视化

1. 简介

CLAM是一种基于深度学习的数据高效、弱监督的全幻灯片(WSI)级的全自动分析工具, 是一种高通量且可解释的方法,使用WSI级标签对整个WSI图像 进行数据高效分类,可自动识别WSI中的组织区域,并提取patch坐标,并自动提取patch级别的特征,但并不真正对patch进行提取和保存,减少计算资源的消耗和内存的占用,可在无需进行ROI标注或者patch级别标签的情况下,基于注意力机制和多示例学习自动识别具有高诊断价值的patch,进而实现整个WSI的实例级别分类。

2. 环境配置

2.1 环境创建

创建环境

conda create -n clam python==3.10

添加清华镜像

conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

2.2 安装依赖

安装必要的库

conda install openslide
pip install timm==0.9.8 torch torchvision h5py pandas PyYAML opencv-python matplotlib scikit-learn scipy tqdm openslide-python tensorboardX
pip install git+https://github.com/oval-group/smooth-topk.git 

2.3 安装预训练编码器

安装UNI

git clone https://github.com/mahmoodlab/UNI.git
cd UNI
pip install -e .

安装CONCH

git clone https://github.com/mahmoodlab/CONCH.git
cd CONCH
pip install -e .

下载模型权重

从 Huggingface 模型页面请求访问模型权重:

  • https://huggingface.co/Mahmoodlab/UNI
  • https://huggingface.co/MahmoodLab/CONCH

克隆repo并cd进入目录

git clone https://github.com/mahmoodlab/CLAM.git
cd CLAM

3. 数据集准备

CLAM可以处理多种标准格式的WSI影像(.svs、.ndpi、.tiff 等),要求WSI存放在同一个路径(DATA_DIRECTORY)下。

DATA_DIRECTORY/
	├── slide_1.svs
	├── slide_2.svs
	└── ...

4. 数据处理

4.1 全自动数据预处理

python create_patches_fp.py --source DATA_DIRECTORY --save_dir RESULTS_DIRECTORY  --seg --patch --stitch

其中参数含义如下:

  • source:包含原始WSI文件的文件夹地址
  • save_dir:预处理后数据保存的地址
  • seg:一个标志,如果设置,保存组织分割mask的缩略图
  • patch:一个标志,如果设置,执行patch切分,保存ROI内patch 的坐标
  • stitch:一个标志,如果设置,生成图像拼接操作(将patch还原到原始WSI尺寸上,其余部分为黑色背景)

除此之外,还可以设置一些可选参数:

  • step_size:在WSI上切分patch的步长,默认值256
  • patch_size:patch切分的尺寸,默认值256
  • no_auto_skip: 一个标志,用于控制是否自动跳过已经处理过的图像,默认为True,即不自动跳过
  • preset: 指定一个预定义的分割和过滤参数配置文件的路径(CSV格式),这些参数用于分割、过滤等步骤,默认为空
  • patch_level: 指定生成图像块时使用的下采样级别,默认为0,即在原始尺寸裁剪
  • process_list: 指定一个包含要处理的图像列表及其参数的CSV文件的路径,可以为每张WSI指定不同的参数,与preset不同,是为了进行个性化处理,默认为空

上述命令将使用默认参数对 DATA_DIRECTORY 中的每个WSI进行分割,提取分割组织区域内的所有patch,使用提取的patch为每个WSI创建拼接重建(可选),并在指定的 RESULTS_DIRECTORY 中生成以下文件夹结构:

RESULTS_DIRECTORY/
	├── masks
    		├── slide_1.png
    		├── slide_2.png
    		└── ...
	├── patches
    		├── slide_1.h5
    		├── slide_2.h5
    		└── ...
	├── stitches
    		├── slide_1.png
    		├── slide_2.png
    		└── ...
	└── process_list_autogen.csv

其中:

  • masks 文件夹包含组织的分割结果(每张WSI对应一张)
  • patches 文件夹包含从每张WSI中提取的patch数组(每张WSI一个 .h5文件,其中每个条目对应于patch左上角的坐标)
  • stitches 文件夹包含缝合patch的下采样可视化(每张WSI一张图像)(可选,不用于下游任务)
  • process_list_autogen.csv 是自动生成的参数文件,包含所有已处理的WSI的列表,以及它们使用的参数。

4.2 半自动数据预处理

为了确保高质量分割和提取相关组织patch,用户可以自行设置分割参数,选择执行预分割(通常每张WSI约 1 秒),检查分割结果并根据需要调整选定WSI的参数,如此反复,直至能有效分割组织区域,然后使用自定义的分割参数提取patch。具体步骤如下:

step1:设置分割参数

python build_preset.py --preset_name CSV_FILE_NAME

上述命令用来创建一个预设配置文件,该文件包含了图像分割和处理参数,可以设置的各个参数的详细解释和默认值如下:

  • presets_name 保存分割参数的文件名称,.csv格式,保存在/presets文件夹下
  • seg_level 用于分割操作的图像金字塔级别,默认值:-1(表示自动选择最适合的级别,使用 WSI 中最接近 64 倍下采样的下采样)
  • sthresh 分割阈值,用于确定哪些区域被认为是组织(使用较高的阈值会导致前景检测较少,背景检测较多),默认值:8(正整数)
  • mthresh 中值滤波器大小,用于微调组织分割,默认值:7(正数,奇数整数)
  • close 用于在分割后处理中进行形态学闭操作的核大小,默认值:4(正整数或-1)
  • use_otsu 是否使用Otsu算法自动计算分割阈值,默认值:False(表示使用简单二进制阈值)
  • keep_ids / exclude_ids 在生成mask过程中保留或排除特定的WSI,默认值:none
  • a_t 过滤参数,用于确定保留的最小ROI大小,默认值:100(表示处理检测到面积大于100512512大小的组织)
  • a_h 过滤参数,用于确定识别的孔洞的最大面积,默认值:16(表示处理检测到面积大于16512512大小的孔洞)
  • max_n_holes 过滤参数,每个前景轮廓需要考虑的最大孔洞数量,默认值:8(正整数,最大值越高,修补越准确,但计算成本也越高)
  • vis_level 用于分割结果可视化的图像金字塔级别,默认值:-1(使用最接近 64 倍下采样的 WSI 中的下采样)
  • line_thickness 绘制分割结果的线条粗细,默认值:500
  • white_thresh 参数设置一个饱和度阈值,用于决定是否将某个patch视为空白并排除,这有助于排除几乎没有信息的patch,默认值为5
  • black_thresh 参数设置一个平均RGB阈值,用于决定是否将某个patch视为黑色并排除,这有助于过滤掉可能不包含有用信息的黑色patch默认值为50
  • use_padding 在切patch操作中是否使用padding以保持边缘patch大小符合要求,默认值:True
  • contour_fn 判断怎样将patch视为前景,默认值:‘four_pt’(“four_pt”: 检查patch中心周围的小网格中的所有四个点是否都在轮廓内,“center” :检查patch的中心是否在轮廓内,“basic” - 检查patch的左上角是否在轮廓内)
  • patch_leve 用于提取patch的图像金字塔级别,默认值:0

step2:执行预分割

在完成分割参数设置之后,可以依据上一步保存的参数文件进行预分割,命令如下:

python create_patches_fp.py --source DATA_DIRECTORY --save_dir RESULTS_DIRECTORY --seg --presets /presets/CSV_FILE_NAME

或者,使用默认参数对 DATA_DIRECTORY 中的每个WSI进行组织识别,命令如下:

python create_patches_fp.py --source DATA_DIRECTORY --save_dir RESULTS_DIRECTORY --seg

上述命令将在mask文件夹下缩略图,并生成 process_list_autogen.csv 文件,但暂时不会进行修补(patchesstitches文件夹将为空)。

step3:调整分割参数

RESULTS_DIRECTORY/masks文件夹下查看预分割缩略图,可以针对效果不好的特定WSI调整参数配置文件,在调整分割参数之前,用户应复制 csv 文件并为其指定一个新名称(例如 process_list_edited.csv),否则下次运行命令时会覆盖此具有默认名称的文件。然后,用户可以选择通过更改 csv 文件中的相应字段来调整特定WSI的参数,并通过 --process_list CSV_FILE_NAME 传递。

python create_patches_fp.py --source DATA_DIRECTORY --save_dir RESULTS_DIRECTORY --seg --process_list CSV_FILE_NAME

其中,process 列存储一个二进制变量(0 或 1),用于指示脚本是否应处理特定WSI,以便用户处理并观察少数几个WSI来快速确认调整后的参数是否产生令人满意的结果。

step4:批量分割

当对所有的预分割结果满意时,用户应该将所有需要处理的WSI的process列设为 1,并保存 csv格式的CSV_FILE_NAME文件,然后使用保存的 csv 文件运行create_patches_fp.py(就像在全自动预处理的运行demo中一样),具体代码如下:

python create_patches_fp.py --source DATA_DIRECTORY --save_dir RESULTS_DIRECTORY --seg --process_list CSV_FILE_NAME --patch --stitch

运行之后会分别在RESULTS_DIRECTORY/patchesRESULTS_DIRECTORY/patches路径下生成包含patch左上角坐标的.h5文件和缝合patch的.jpg可视化结果。

5. 特征提取

特征提取需要运行extract_features_fp.py脚本,可以使用命令行调用

CUDA_VISIBLE_DEVICES=0 python extract_features_fp.py --data_h5_dir DIR_TO_COORDS --data_slide_dir DATA_DIRECTORY --csv_path CSV_FILE_NAME --feat_dir FEATURES_DIRECTORY --batch_size 512 --slide_ext .svs

上述命令会读取存储在DIR_TO_COORDS下的 .h5 格式的patch坐标文件,批处理大小由 batch_size 参数传入,从原始WSI的每个patch中提取预训练特征,默认使用预训练的resnet50网络,特征维度为1024,如果使用UNICONCH作为预训练编码器提取特征,需要提前指定模型目录所在的环境变量,并设置model_nameuni_v1或者conch_v1UNI的特征维度为10024,CONCH的特征维度为512,环境变量设置方法如下:

export CONCH_CKPT_PATH=checkpoints/conch/pytorch_model.bin
export UNI_CKPT_PATH=checkpoints/uni/pytorch_model.bin

命令执行后将生成以下文件夹结构:

FEATURES_DIRECTORY/
    ├── h5_files
            ├── slide_1.h5
            ├── slide_2.h5
            └── ...
    └── pt_files
            ├── slide_1.pt
            ├── slide_2.pt
            └── ...

其中每个 .h5 文件包含提取的特征数组及其patch坐标(请注意,为了加快训练速度,还会为每张WSI创建一个 .pt 文件,其中仅包含patch的特征),提取命令的其他超参数如下:

  • data_h5_dir 数据集的HDF5文件目录,用于指定存储图像patches的HDF5文件的位置,默认值:None(必须由用户指定)
  • data_slide_dir WSI图像文件的目录,用于指定WSI文件的存储位置,默认值:None(必须由用户指定)
  • slide_extWSI文件的扩展名,默认值:.svs(常见的WSI格式之一)
  • csv_pathcsv 文件应包含要处理的WSI文件名列表(不带文件扩展名)(可以指定上一个自动生成的 csv 文件,然后删除文件扩展名)
  • feat_dir 特征保存目录,用于指定提取的特征保存的位置,默认值:None(必须由用户指定)
  • model_name 用于特征提取的预训练模型,默认值:resnet50_trunc,可选值包括 resnet50_truncuni_v1conch_v1
  • batch_size 批处理大小,默认值:256
  • no_auto_skip 是否自动跳过已处理的WSI,默认值:False(如果指定此选项,则不会自动跳过)
  • target_patch_size 目标patch大小,用于指定提取的patch的大小,默认值:224

6. 模型训练

6.1 数据集划分

为了评估算法的性能,可以使用多倍(例如 10 倍)训练、验证、测试划分(80:10:10)。可以使用 create_splits_seq.py 脚本自动生成这些分割,只需进行少量修改,就像使用main.py一样。例如,可以通过调用以下命令创建是否有肿瘤的分类:

python create_splits_seq.py --task task_1_tumor_vs_normal --seed 1 --k 10

其中,可传入参数如下:

  • label_frac: 用于指定数据集中使用的标签比例,默认值为1.0,表示使用全部标签
  • seed: 随机种子,用于确保数据分割的可重复性,默认值为1
  • k: 分割的数量,即进行k折交叉验证时的k值,默认值为10
  • task: 任务类型,有两个选项:task_1_tumor_vs_normaltask_2_tumor_subtyping,分别对应肿瘤与正常组织的分类任务和肿瘤亚型的分类任务
  • val_frac: 用于设置验证集的标签比例,默认值为0.1
  • test_frac: 用于设置测试集的标签比例,默认值为0.1。

目前只支持良恶性鉴别(task_1_tumor_vs_normal,二分类)和肿瘤亚型鉴别(task_2_tumor_subtyping,三分类)两种任务,如果需要自定义进行其他任务,需要按照Generic_WSI_Classification_Dataset类要求的数据格式自行编写python脚本配置,有关详细信息,请参阅datasets/dataset_generic.py中的数据集定义。数据集的划分结果会按照要求保存在splits文件夹下,具体格式如下:

splits/
    ├── {task_name}_{label_frac}
            ├── splits_0.csv
            ├── splits_0_bool.csv
            ├── splits_0_descriptor.csv
            ├── ...
            ├── splits_9.csv
            ├── splits_9_bool.csv
            └── splits_9_descriptor.csv
    ├── ...    
    ├── ...
    └── {task_name}_{label_frac}
            ├── splits_0.csv
            ├── splits_0_bool.csv
            ├── splits_0_descriptor.csv
            ├── ...
            ├── splits_9.csv
            ├── splits_9_bool.csv
            └── splits_9_descriptor.csv

6.2 模型训练

划分好数据集之后,只需要一行代码即可开始训练。

CUDA_VISIBLE_DEVICES=0 python main.py --drop_out 0.25 --early_stopping --lr 2e-4 --k 10 --exp_code task_1_tumor_vs_normal_CLAM_50 --weighted_sample --bag_loss ce --inst_loss svm --task task_1_tumor_vs_normal --model_type clam_sb --log_data --data_root_dir DATA_ROOT_DIR --embed_dim 1024

注意:--embed_dim为输入特征的维度,默认值为1024,而对于 CONCH提取的预训练特征, 应设置为 512。其余具体参数如下:

  • data_root_dir: 数据根目录,没有默认值,用户必须指定
  • max_epochs: 训练的最大轮数,默认值为200
  • lr: 学习率,默认值为0.0001
  • label_frac: 训练标签的比例,默认值为1.0,表示使用全部标签
  • reg: 权重衰减,默认值为1e-5
  • seed: 随机种子,默认值为1,用于实验的可重复性
  • k: 折数,默认值为10,用于k折交叉验证
  • k_start: 开始的折数,默认值为-1,表示从第一折开始
  • k_end: 结束的折数,默认值为-1,表示到最后一折结束
  • results_dir: 结果保存目录,默认值为./results
  • split_dir: 数据集划分目录,默认值为None,用户可以手动指定使用的划分数据集
  • log_data: 是否使用tensorboard记录数据,默认为False
  • testing: 调试工具,默认为False
  • early_stopping: 是否启用早停,默认为False
  • opt: 优化器,默认为Adam
  • drop_out: Dropout值,默认值为0.25
  • bag_loss: 包级别的损失函数,svm(支持向量机损失)和 ce(交叉熵损失,默认值)中二选一
  • model_type: 模型类型,可选:clam_sb(单分支注意力MIL,默认值)、 clam_mb(多分支注意力MIL)、mil(普通MIL)
  • exp_code: 结果文件保存的地址,没有默认值,用户必须指定
  • weighted_sample: 是否启用加权采样,默认为False
  • model_size: 模型大小,可选'small'(默认值)或者'big',默认为small
  • task: 任务类型,没有默认值,用户必须从task_1_tumor_vs_normaltask_2_tumor_subtyping中选择
  • no_inst_cluster: 是否禁用实例级聚类,使用后会提升模型的泛化性能,默认为False
  • inst_loss: 实例级聚类的损失函数,默认值为None
  • subtyping: 是否为肿瘤亚型分类问题,默认为False,但是如果模型选择了clam_sb或者 clam_mb,则必须设置为True
  • bag_weight: 包级别损失的权重系数,当no_inst_cluster为False时启用,默认值为0.7
  • B: 对于clam_sbclam_mb模型,每次从包中采样的数量,正负样本采样的数量,较小的值可能导致模型无法充分学习包内所有实例的信息,而较大的值则可能增加计算成本并导致过拟合,默认值为8

而对于不属于task_1_tumor_vs_normaltask_2_tumor_subtyping的其他任务,则需要按照main.py的形式自定义训练函数。

6.3 模型验证

用户还可以选择使用评估脚本来测试已训练模型的性能。下面提供了与上述训练模型相对应的示例:

CUDA_VISIBLE_DEVICES=0 python eval.py --k 10 --models_exp_code task_1_tumor_vs_normal_CLAM_50_s1 --save_exp_code task_1_tumor_vs_normal_CLAM_50_s1_cv --task task_1_tumor_vs_normal --model_type clam_sb --results_dir results --data_root_dir DATA_ROOT_DIR --embed_dim 1024

其中大多数参数与main.py中一致,不同的参数如下:

  • save_exp_code :用于指定保存评估结果的实验代码
  • models_exp_code :用于指定加载训练好的模型的实验代码
  • micro_average :用于设置多类别分类任务中评价指标的平均方法。当设置为True时,使用micro-average(不平衡数据集)

6.4 热图可视化

CLAM还可以批量进行热图可视化,填写配置文件并存储在/heatmaps/configs中,然后使用 --config NAME_OF_CONFIG_FILE 标志运行create_heatmaps.py,代码如下:

CUDA_VISIBLE_DEVICES=0 python create_heatmaps.py --config config_template.yaml

具体参数如下:

  • save_exp_code:保存热图生成的结果。默认值为 None
  • overlap:生成热图生成时,补丁之间的重叠比例。默认值为 None
  • config_file:配置文件的路径,该文件包含热图生成过程中所有必要的参数和设置。默认值为 “heatmap_config_template.yaml”

你可能感兴趣的:(病理图像分析,python,计算机视觉,深度学习,分类)