S&D Messenger 完整教學

Repository: https://github.com/xmed-lab/SD-Messenger Stars: 3 | Tags: stable-diffusion, medical, cross-modal 語言: Python | 授權: 未標示 論文: arXiv:2407.07763 (2024) 最後更新: 2025-08-27

2. 核心架構

2.1 整體架構圖


graph TB
    subgraph Input["輸入層"]
        IL["Labeled Images
標註影像"] IU["Unlabeled Images
未標註影像"] end subgraph Backbone["Backbone: MiT-B5"] E0["Stage 0
64-ch features"] E1["Stage 1
128-ch features"] E2["Stage 2
320-ch features"] E3["Stage 3
512-ch features"] end subgraph SDM["S&D Messenger Modules"] direction TB U2L3["U2L Module
(512-ch, cross-attn ON)"] U2L2["U2L Module
(320-ch, optional)"] U2L1["U2L Module
(128-ch, optional)"] U2L0["U2L Module
(64-ch, optional)"] end subgraph Decoder["SegFormer Decoder Head"] MLP4["MLP c4 → 768-d"] MLP3["MLP c3 → 768-d"] MLP2["MLP c2 → 768-d"] MLP1["MLP c1 → 768-d"] FUSE["Conv1x1 Fuse
3072 → 768"] PRED["Conv1x1 Predict
768 → num_class"] end subgraph Loss["損失函數"] CE["Cross-Entropy Loss
+ Difficulty Weighting"] DICE["Dice Loss"] PL["Pseudo-Label Loss
(unlabeled)"] end IL --> Backbone IU --> Backbone E3 --> U2L3 E2 --> U2L2 E1 --> U2L1 E0 --> U2L0 U2L3 --> MLP4 U2L2 --> MLP3 U2L1 --> MLP2 U2L0 --> MLP1 MLP4 --> FUSE MLP3 --> FUSE MLP2 --> FUSE MLP1 --> FUSE FUSE --> PRED PRED --> CE PRED --> DICE PRED --> PL style SDM fill:#e8f4fd,stroke:#1e88e5 style Decoder fill:#fff3e0,stroke:#ff9800 style Loss fill:#fce4ec,stroke:#e91e63

2.2 CrossAttnMem — 核心跨注意力模組

S&D Messenger 的核心是 CrossAttnMem 模組,實現 labeled-to-unlabeled 的雙向知識傳遞:


graph LR
    subgraph CrossAttnMem["CrossAttnMem Module"]
        direction TB

        EMB["Combined Embeddings
[labeled ; unlabeled]"] SPLIT["Split by batch dim"] subgraph UU["Unlabeled Self-Attention"] QUU["Q_u_u = Linear(emb_u)"] KUU["K_u_u = Linear(emb_u)"] VUU["V_u_u = Linear(emb_u)"] ATT_UU["Attention + InstanceNorm"] OUT_UU["O_u_u: enhanced unlabeled"] end subgraph LU["Labeled-query, Unlabeled-KV"] QLU["Q_l_u = Linear(emb_l)"] KLU["K_l_u = Linear(emb_u)
→ cross-batch broadcast"] VLU["V_l_u = Linear(emb_u)
→ cross-batch broadcast"] ATT_LU["Cross-Attention + InstanceNorm"] OUT_LU["O_l_u: domain-enriched labeled"] end CONCAT["Concat [O_l_u ; O_u_u]"] EMB --> SPLIT SPLIT --> QUU & KUU & VUU SPLIT --> QLU & KLU & VLU QUU & KUU & VUU --> ATT_UU --> OUT_UU QLU & KLU & VLU --> ATT_LU --> OUT_LU OUT_LU & OUT_UU --> CONCAT end style UU fill:#e3f2fd,stroke:#1565c0 style LU fill:#fce4ec,stroke:#c62828

運作原理

  1. Unlabeled Self-Attention (U→U):未標註集內部的自注意力,捕捉 domain 特有的結構性知識
  2. Labeled-queries Unlabeled-KV (L→U):以標註集的語義特徵為 query,從未標註集的 key/value 中檢索 domain 知識——這是「信使」機制的核心。未標註集跨 batch 廣播 (broadcast),讓每張標註影像都能存取所有未標註影像的 domain 資訊
  3. InstanceNorm2d:對 attention map 做正規化,穩定不同 domain 間的 attention 分佈

2.3 Difficulty-Aware Weighting

訓練中使用 Difficulty 類別追蹤每個分割類別的學習動態:

  • 透過 EMA (Exponential Moving Average; 指數移動平均) 追蹤每個類別的 Dice 變化量
  • 區分「正在學習」(improving) 與「正在遺忘」(forgetting) 的類別
  • 計算 difficulty ratio = unlearn / learn,對難以學習的類別給予更高權重
  • 結合 (1 - dice) 作為整體困難度因子

3. 安裝與設定

3.1 環境需求

項目需求
Python3.10+
PyTorch1.x / 2.x (需 CUDA)
GPUNVIDIA GPU (建議 24GB+ VRAM)
CUDA11.x+
關鍵套件mmcv 1.6.2, einops, timm 0.9.10, MedPy

3.2 安裝步驟

 1# 1. Clone repository
 2git clone https://github.com/xmed-lab/SD-Messenger.git
 3cd SD-Messenger/SD_Messenger
 4
 5# 2. 建立 conda 環境(建議用 mamba 加速)
 6conda create -n SDMessenger python=3.10 -y
 7conda activate SDMessenger
 8
 9# 3. 安裝 PyTorch(依據 CUDA 版本調整)
10pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
11
12# 4. 安裝 mmcv(需要對應 PyTorch + CUDA 版本)
13pip install mmcv-full==1.6.2 -f https://download.openmmlab.com/mmcv/dist/cu118/torch2.0/index.html
14
15# 5. 安裝其餘依賴
16pip install -r requirements.txt

注意mmcv 的版本與 PyTorch/CUDA 版本強耦合,務必從 OpenMMLab 的 wheel index 安裝。若遇到編譯問題,可改用 mmcv==1.6.2(不含 CUDA ops),但可能影響部分功能。

3.3 資料集準備

 1# 下載預處理資料集(以 Synapse 為例)
 2# 從 OneDrive 連結下載 synapse.zip
 3
 4# 解壓縮
 5unzip synapse.zip -d ./data/
 6
 7# 目錄結構應為:
 8# SD_Messenger/
 9# ├── data/
10# │   └── synapse/
11# │       ├── train/
12# │       │   ├── images/
13# │       │   └── masks/
14# │       └── val/
15# │           ├── images/
16# │           └── masks/
17# ├── splits/
18# │   └── synapse/
19# │       ├── 1_5/          # 20% labeled
20# │       │   ├── labeled.txt
21# │       │   └── unlabeled.txt
22# │       ├── 2_5/          # 40% labeled
23# │       └── val.txt
24# └── configs/

修改 configs/synapse_1_5.yaml 中的 data_root 指向資料集路徑:

1data_root: ./data/synapse

4. 使用方式與程式碼範例

4.1 範例一:訓練 S&D Messenger (Synapse 20% labeled)

1cd SD_Messenger
2
3# 單 GPU 訓練
4bash scripts/train_synapse_1_5.sh 1 12345
5
6# 多 GPU 訓練(例如 4 張 GPU)
7bash scripts/train_synapse_1_5.sh 4 12345

訓練腳本解析scripts/train_synapse_1_5.sh):

 1#!/bin/bash
 2dataset='synapse'
 3method='train_synapse'
 4config='synapse_1_5'
 5split='1_5'
 6now=$(date +"%Y%m%d_%H%M%S")
 7config=configs/${config}.yaml
 8labeled_id_path=splits/$dataset/$split/labeled.txt
 9unlabeled_id_path=splits/$dataset/$split/unlabeled.txt
10save_path=exp/$method/$dataset/$split
11
12mkdir -p $save_path
13
14# torchrun 啟動分散式訓練
15CUDA_VISIBLE_DEVICES=0 torchrun \
16    --nproc_per_node=$1 \
17    --master_addr=localhost \
18    --master_port=$2 \
19    $method.py \
20    --config=$config \
21    --labeled-id-path $labeled_id_path \
22    --unlabeled-id-path $unlabeled_id_path \
23    --save-path $save_path \
24    --port $2 2>&1 | tee $save_path/$now.log

關鍵訓練超參數configs/synapse_1_5.yaml):

 1# 資料集設定
 2dataset: synapse
 3nclass: 14            # 14 個器官類別
 4crop_size: 512        # 輸入影像裁切尺寸
 5l2u_size: 64          # Labeled-to-Unlabeled 特徵圖尺寸
 6
 7# 訓練設定
 8epochs: 300
 9batch_size: 8         # 每張 GPU
10lr: 0.001
11lr_multi: 5.0         # 非 backbone 參數的學習率倍率
12
13# 模型設定
14model:
15  backbone:
16    type: model.backbone.mit.mit_b5    # MiT-B5 backbone
17    kwargs:
18      embed_dims: [64, 128, 320, 512]
19      pretrained: True
20  framework:
21    type: model.semseg.sd_messenger.SDMessenger
22    kwargs:
23      num_layers: 2
24      num_heads: 2
25      num_class: 14
26      in_planes: [64, 128, 320, 512]
27      image_size: 512
28      add_cross_attn: [False, False, False, True]  # 僅在最深層啟用

4.2 範例二:評估已訓練模型

 1cd SD_Messenger
 2
 3# 使用預訓練權重評估 Synapse 20% 設定
 4bash scripts/test_synapse_1_5.sh 1 /path/to/checkpoint.pth
 5
 6# 或手動執行(更靈活的參數控制)
 7CUDA_VISIBLE_DEVICES=0 torchrun \
 8    --nproc_per_node=1 \
 9    --master_addr=localhost \
10    --master_port=12345 \
11    test_synapse.py \
12    --config=configs/synapse_1_5.yaml \
13    --checkpoint-path=exp/train_synapse/synapse/1_5/best_model.pth \
14    --port 12345

預期結果(官方釋出權重):

資料集設定DICE (%)
Synapse20% labeled68.38
Synapse40% labeled71.53
MMWHSCT→MRI77.0
MMWHSMRI→CT91.4
LASeg5%90.21
LASeg10%91.46
M&MsDomain A-D86.50 - 89.76

4.3 範例三:自定義 S&D Messenger 模組用於新任務

以下示範如何將 S&D Messenger 的跨注意力模組抽取出來,整合到自定義的分割管線中:

 1import torch
 2import torch.nn as nn
 3from model.semseg.sd_messenger import U2LModule, SDMessenger
 4
 5# --- 方式 A:使用完整 SDMessenger 框架 ---
 6sd_model = SDMessenger(
 7    num_layers=2,
 8    num_heads=2,
 9    num_class=5,                     # 自定義類別數
10    in_planes=[64, 128, 320, 512],   # 需匹配 backbone 輸出維度
11    image_size=256,                  # 輸入影像尺寸
12    add_cross_attn=[False, False, True, True]  # 在後兩層啟用
13)
14
15# 模擬 4 階段 backbone 輸出(batch = labeled + unlabeled)
16batch_size = 4  # 2 labeled + 2 unlabeled
17c1 = torch.randn(batch_size, 64, 64, 64)
18c2 = torch.randn(batch_size, 128, 32, 32)
19c3 = torch.randn(batch_size, 320, 16, 16)
20c4 = torch.randn(batch_size, 512, 8, 8)
21
22out, e3_enhanced = sd_model((c1, c2, c3, c4), h=256, w=256)
23print(f"Segmentation output: {out.shape}")       # [4, 5, 256, 256]
24print(f"Enhanced features:   {e3_enhanced.shape}") # [4, 512, 8, 8]
25
26# 分離 labeled / unlabeled 預測
27pred_labeled = out[:batch_size // 2]     # 用 ground-truth 監督
28pred_unlabeled = out[batch_size // 2:]   # 用 pseudo-label 監督
29
30# --- 方式 B:單獨使用 U2L Module ---
31u2l = U2LModule(
32    num_layers=2,
33    num_heads=2,
34    embedding_channels=512,
35    channel_num=512,
36    channel_num_out=512,
37    patchSize=1,
38    scale=1,
39    dropout_rate=0.5,
40    attention_dropout_rate=0.1,
41    num_class=5,
42    patch_num=65  # (image_size // 32 + 1) ** 2
43)
44
45# 輸入需為 labeled + unlabeled concat
46feat = torch.randn(4, 512, 8, 8)  # 2 labeled + 2 unlabeled
47enhanced = u2l(feat)
48print(f"U2L enhanced: {enhanced.shape}")  # [4, 512, 8, 8]
49# enhanced[:2] = domain-enriched labeled features
50# enhanced[2:] = self-attention enhanced unlabeled features

5. 在生醫影像合成生態系中的定位

5.1 Domain 2 生態系定位

S&D Messenger 屬於 D. Diffusion Models for Medical Images 子領域,但其核心貢獻並非影像合成,而是半監督分割中的知識交換機制。在 Bio-SDG Domain 2 的 16 個專案中,它佔據獨特的生態位:

面向S&D Messenger 的角色
與 nnUNet / MONAI 的關係互補:nnUNet/MONAI 提供全監督分割基線,S&D Messenger 解決標註不足場景
與 conditional_DDPM / DenseDiffusion 的差異DDPM/DenseDiffusion 著重影像合成 (generation),S&D Messenger 著重分割 (segmentation) 中的跨域知識傳遞
與 CONCH / CLAM 的互補CONCH/CLAM 專注計算病理學,S&D Messenger 適用於 CT/MRI 等放射影像
與 medigan 的整合潛力medigan 可生成合成訓練資料,S&D Messenger 可利用這些合成資料作為 unlabeled set

5.2 對藥物開發的價值

S&D Messenger 的半監督分割能力在藥物開發流程中有以下應用場景:

臨床試驗影像分析

  • 多中心試驗 (multi-center trial) 中,不同醫院的影像設備與掃描協定差異巨大,正是 Semi-MDG 場景
  • 僅需少量中心的標註即可訓練出跨中心泛化的分割模型
  • 大幅降低臨床試驗中影像標註的人力成本

影像生物標記 (Imaging Biomarker; 影像生物標記)

  • 腫瘤體積、器官形態等影像生物標記的自動量化依賴精確分割
  • S&D Messenger 的 Difficulty-Aware Weighting 有助於小型腫瘤或罕見結構的分割

隱私保護考量

  • 跨域知識交換機制僅在特徵空間操作,不需要跨醫院共享原始影像
  • 可與聯邦學習 (Federated Learning, FL; 聯邦學習) 結合,未標註集留在各機構本地

5.3 Blue Ocean 機會

  • 3D 體積分割:目前 S&D Messenger 僅處理 2D slice,擴展至 3D volumetric segmentation 可望進一步提升效能
  • 病理學應用:結合 CONCH/CLAM 的 whole-slide image 分析,將半監督跨域框架帶入計算病理學
  • Multi-modal Messenger:目前 cross-attention 是 within modality 的,若擴展為真正的 cross-modal (例如 MRI-query + CT-KV),可實現更強的跨模態知識傳遞

6. 與其他工具的整合

6.1 與 MONAI 整合

 1# 使用 MONAI 的資料載入 + S&D Messenger 的模型
 2import monai
 3from monai.transforms import (
 4    Compose, LoadImaged, EnsureChannelFirstd,
 5    ScaleIntensityd, RandCropByPosNegLabeld
 6)
 7from model.model_helper import ModelBuilder
 8
 9# MONAI 資料管線
10train_transforms = Compose([
11    LoadImaged(keys=["image", "label"]),
12    EnsureChannelFirstd(keys=["image", "label"]),
13    ScaleIntensityd(keys=["image"]),
14    RandCropByPosNegLabeld(
15        keys=["image", "label"],
16        label_key="label",
17        spatial_size=(512, 512),
18        pos=1, neg=1,
19    ),
20])
21
22# S&D Messenger 模型設定
23cfg_model = {
24    "backbone": {
25        "type": "model.backbone.mit.mit_b5",
26        "kwargs": {
27            "embed_dims": [64, 128, 320, 512],
28            "pretrained": True
29        }
30    },
31    "framework": {
32        "type": "model.semseg.sd_messenger.SDMessenger",
33        "kwargs": {
34            "num_layers": 2,
35            "num_heads": 2,
36            "num_class": 14,
37            "in_planes": [64, 128, 320, 512],
38            "image_size": 512,
39            "add_cross_attn": [False, False, False, True]
40        }
41    }
42}
43
44model = ModelBuilder(cfg_model)

6.2 與 nnUNet 的比較實驗設定

 1# 1. 使用 nnUNet 做全監督 baseline(100% labeled)
 2nnUNetv2_plan_and_preprocess -d DATASET_ID --verify_dataset_integrity
 3nnUNetv2_train DATASET_ID 2d 0
 4
 5# 2. 使用 S&D Messenger 做半監督實驗(20% labeled)
 6cd SD_Messenger
 7bash scripts/train_synapse_1_5.sh 1 12345
 8
 9# 3. 比較 Dice 分數,評估 annotation efficiency
10# nnUNet 100% labeled vs S&D Messenger 20% labeled
11# 若 S&D Messenger 20% 逼近 nnUNet 100%,則標註效率提升 5 倍

6.3 與 AIKT Pipeline 整合建議

在 AI-Knowledge Template 管線中,S&D Messenger 可以作為:

  1. paper-search Layer:用 paper: semi-supervised medical image segmentation domain adaptation 搜尋相關文獻,追蹤後續改進工作
  2. paper-tutorial Layer:將 S&D Messenger 論文與相關 domain adaptation 論文打包做內部教學
  3. tu-plan-generator Layer:在影像生物標記評估管線中,使用 S&D Messenger 作為分割引擎,搭配 ToolUniverse 的 disease-research 與 target-research lens

7. 優缺點分析

7.1 優點

優點說明
通用性強單一框架同時處理 SSMIS / UMDA / Semi-MDG 三種場景,不需為每個場景設計專用方法
即插即用U2L Module 可獨立抽取,插入任何具有多層特徵輸出的 encoder-decoder 架構
顯著超越 SOTA在 10 個 benchmark 上全面超越各場景的 SOTA 方法
Difficulty-Aware Weighting動態追蹤類別學習狀態,自動處理 class imbalance——醫學影像分割的常見痛點
提供預訓練權重Synapse 資料集的 20%/40% 設定均有權重與完整 training log 可供驗證
可重現性提供 seed 固定、training log、完整 config,便於重現結果

7.2 缺點與限制

缺點說明
僅支援 2D 切片所有實驗均為 2D slice-based,缺少 3D volumetric 支援
Batch 結構限制訓練時 batch 必須嚴格由 labeled + unlabeled 等量組成(batch split at dim=0),增加 DataLoader 設計複雜度
無授權條款Repository 未標示 license,商業使用需聯繫作者確認
mmcv 依賴依賴 mmcv 1.6.2,此版本與新版 PyTorch 可能存在相容性問題
部分權重未釋出MMWHS / LASeg / M&Ms 的權重標示為 “coming soon” 但長期未更新
文件不完整非 Synapse 資料集的 config 與 script 缺失或不完整
非影像合成名稱含 “Messenger” 易與 Stable Diffusion 系列混淆,實際是分割框架而非生成模型

7.3 適用場景建議

場景建議
多中心臨床試驗影像分割強烈推薦:正是 Semi-MDG / UMDA 的實際應用
單中心少量標註推薦:SSMIS 性能優異
3D 體積分割需求不推薦:需自行擴展至 3D
病理學 whole-slide image不推薦:建議使用 CLAM / CONCH
產品化部署謹慎:缺少 license、推論效率未最佳化

7.4 與同領域工具的對比

面向S&D MessengerUniMatchFixMatchnnUNet (全監督)
半監督支援原生原生原生需改造
跨域泛化原生 (UMDA/Semi-MDG)
3D 支援部分部分完整
醫學影像專用通用通用
社群成熟度早期 (3 stars)成熟成熟非常成熟
知識交換機制Cross-Attention一致性正則化Pseudo-labelN/A

一句話總結:S&D Messenger 是一個基於跨注意力機制的通用半監督醫學影像分割框架,透過在 labeled/unlabeled 特徵空間之間建立「信使」通道,同時傳遞語義與領域知識,在三種半監督場景下大幅超越既有方法——特別適合標註資源有限且存在跨域變異的多中心臨床試驗影像分析。