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
運作原理:
- Unlabeled Self-Attention (U→U):未標註集內部的自注意力,捕捉 domain 特有的結構性知識
- Labeled-queries Unlabeled-KV (L→U):以標註集的語義特徵為 query,從未標註集的 key/value 中檢索 domain 知識——這是「信使」機制的核心。未標註集跨 batch 廣播 (broadcast),讓每張標註影像都能存取所有未標註影像的 domain 資訊
- 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 環境需求
| 項目 | 需求 |
|---|---|
| Python | 3.10+ |
| PyTorch | 1.x / 2.x (需 CUDA) |
| GPU | NVIDIA GPU (建議 24GB+ VRAM) |
| CUDA | 11.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 (%) |
|---|---|---|
| Synapse | 20% labeled | 68.38 |
| Synapse | 40% labeled | 71.53 |
| MMWHS | CT→MRI | 77.0 |
| MMWHS | MRI→CT | 91.4 |
| LASeg | 5% | 90.21 |
| LASeg | 10% | 91.46 |
| M&Ms | Domain A-D | 86.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 可以作為:
- paper-search Layer:用
paper: semi-supervised medical image segmentation domain adaptation搜尋相關文獻,追蹤後續改進工作 - paper-tutorial Layer:將 S&D Messenger 論文與相關 domain adaptation 論文打包做內部教學
- 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 Messenger | UniMatch | FixMatch | nnUNet (全監督) |
|---|---|---|---|---|
| 半監督支援 | 原生 | 原生 | 原生 | 需改造 |
| 跨域泛化 | 原生 (UMDA/Semi-MDG) | 無 | 無 | 無 |
| 3D 支援 | 無 | 部分 | 部分 | 完整 |
| 醫學影像專用 | 是 | 通用 | 通用 | 是 |
| 社群成熟度 | 早期 (3 stars) | 成熟 | 成熟 | 非常成熟 |
| 知識交換機制 | Cross-Attention | 一致性正則化 | Pseudo-label | N/A |
一句話總結:S&D Messenger 是一個基於跨注意力機制的通用半監督醫學影像分割框架,透過在 labeled/unlabeled 特徵空間之間建立「信使」通道,同時傳遞語義與領域知識,在三種半監督場景下大幅超越既有方法——特別適合標註資源有限且存在跨域變異的多中心臨床試驗影像分析。
Comments