conditional_DDPM 完整教學

Repository: https://github.com/junbopeng/conditional_DDPM Stars: 74 | Tags: DDPM, CBCT-CT, Medical-Physics License: MIT | Language: Python | Last Updated: 2026-04-29 論文: Peng J, Qiu RLJ, Wynne JF, et al. CBCT-Based synthetic CT image generation using conditional denoising diffusion probabilistic model. Med Phys. 2023; 1-13. DOI: 10.1002/mp.16704

2. 核心架構

2.1 系統架構圖


graph TB
    subgraph "Forward Process (訓練時)"
        CT["pCT 影像
(Ground Truth)"] NOISE["Gaussian Noise ε"] T_STEP["Random Timestep t
t ∈ [0, T)"] X_T["噪聲化 CT: x_t
x_t = √ᾱ_t · CT + √(1-ᾱ_t) · ε"] CT --> X_T NOISE --> X_T T_STEP --> X_T end subgraph "Conditional Input (條件輸入)" CBCT["CBCT 影像
(Condition)"] CONCAT["Channel Concatenation
[x_t, CBCT] → 2-ch"] X_T --> CONCAT CBCT --> CONCAT end subgraph "U-Net Backbone" UNET["Conditional U-Net
Input: 2-ch | Output: 1-ch"] TIME_EMB["Sinusoidal Time Embedding
t → MLP → t_emb"] CONCAT --> UNET T_STEP --> TIME_EMB TIME_EMB --> UNET PRED["Predicted Noise ε̂"] UNET --> PRED end subgraph "Training Loss" LOSS["MSE Loss
L = Σ||ε - ε̂||²"] NOISE --> LOSS PRED --> LOSS end subgraph "Reverse Process (推論時)" PURE_NOISE["Pure Noise x_T
~ N(0, I)"] CBCT2["CBCT 影像"] DENOISE["Iterative Denoising
t = T → 0"] SCT["Synthetic CT
(合成 CT 輸出)"] PURE_NOISE --> DENOISE CBCT2 --> DENOISE UNET -.->|"Trained Model"| DENOISE DENOISE --> SCT end style CT fill:#4CAF50,color:#fff style CBCT fill:#FF9800,color:#fff style CBCT2 fill:#FF9800,color:#fff style SCT fill:#2196F3,color:#fff style LOSS fill:#f44336,color:#fff

2.2 U-Net 架構細節

模型採用經典的 U-Net with Skip Connections (帶跳躍連接的 U-Net),各層規格如下:


graph TD
    subgraph "Encoder (下採樣路徑)"
        E0["Head Conv2d
2-ch → 128-ch"] E1["ResBlock ×2
128 → 128
+ GroupNorm + Swish"] E1D["DownSample
stride=2"] E2["ResBlock ×2
128 → 256"] E2D["DownSample
stride=2"] E3["ResBlock ×2 + Attn
256 → 384"] E3D["DownSample
stride=2"] E4["ResBlock ×2
384 → 512"] E0 --> E1 --> E1D --> E2 --> E2D --> E3 --> E3D --> E4 end subgraph "Bottleneck" M1["ResBlock + Attention
512 → 512"] M2["ResBlock
512 → 512"] E4 --> M1 --> M2 end subgraph "Decoder (上採樣路徑)" D4["ResBlock ×3
512+skip → 512"] D3U["UpSample
interpolate ×2"] D3["ResBlock ×3 + Attn
skip → 384"] D2U["UpSample
interpolate ×2"] D2["ResBlock ×3
skip → 256"] D1U["UpSample
interpolate ×2"] D1["ResBlock ×3
skip → 128"] TAIL["Tail Conv2d
128 → 1-ch"] M2 --> D4 --> D3U --> D3 --> D2U --> D2 --> D1U --> D1 --> TAIL end E1 -.->|"skip"| D1 E2 -.->|"skip"| D2 E3 -.->|"skip"| D3 E4 -.->|"skip"| D4

關鍵設計決策:

元件設定理由
Channel Multipliers[1, 2, 3, 4][128, 256, 384, 512]逐層增加語意容量
Attention Layer僅在 level 2 (384-ch)平衡計算成本與全域感受野
GroupNorm(32, ch)每組 32 channels適用於小 batch size 的醫學影像訓練
ActivationSwish (x·σ(x))比 ReLU 平滑,梯度流更好
Time EmbeddingSinusoidal → 2-layer MLP標準 DDPM 時間編碼,投射至 512 維
Dropout0.3防止過擬合,醫學影像資料集通常較小

2.3 擴散排程 (Diffusion Schedule)

1β₁ = 1e-4,  β_T = 0.02,  T = 1000 (線性排程)
2αₜ = 1 - βₜ
3ᾱₜ = ∏ᵢ₌₁ᵗ αᵢ  (cumulative product)

前向過程一步到位:x_t = √ᾱ_t · x_0 + √(1 - ᾱ_t) · ε

反向過程逐步迭代:x_{t-1} = coeff1 · x_t - coeff2 · ε̂(x_t, t) + √β_t · z


3. 安裝與設定

3.1 環境需求

需求規格
Python3.8 - 3.11
PyTorch>= 1.10(需 CUDA 支援)
GPUNVIDIA GPU,建議 >= 12GB VRAM
CUDA11.x 或 12.x

3.2 安裝步驟

 1# 1. 建立虛擬環境(使用 uv 或 conda)
 2uv venv .venv --python 3.10
 3source .venv/bin/activate
 4
 5# 2. 安裝 PyTorch(依 CUDA 版本調整)
 6uv pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121
 7
 8# 3. 取得程式碼
 9git clone https://github.com/junbopeng/conditional_DDPM.git
10cd conditional_DDPM
11
12# 4. 安裝其他依賴(程式碼內含的標準庫)
13uv pip install numpy pillow

3.3 資料準備

資料集採用 paired image (配對影像) 格式,以 .npy 檔案儲存:

 1<dataset_name>/
 2├── train/
 3│   ├── a/          # 目標影像(如 pCT)
 4│   │   ├── 001.npy
 5│   │   ├── 002.npy
 6│   │   └── ...
 7│   └── b/          # 條件影像(如 CBCT)
 8│       ├── 001.npy
 9│       ├── 002.npy
10│       └── ...
11└── test/
12    ├── a/          # 測試目標影像
13    └── b/          # 測試條件影像

資料前處理要點:

 1import numpy as np
 2
 3# 假設原始 DICOM 已轉為 numpy array,HU 值範圍 [-1000, 3000]
 4def preprocess_slice(hu_array, hu_min=-1000, hu_max=3000):
 5    """將 HU 值正規化到 [-1, 1] 範圍"""
 6    normalized = (hu_array - hu_min) / (hu_max - hu_min)  # [0, 1]
 7    normalized = normalized * 2 - 1                         # [-1, 1]
 8    return normalized.astype(np.float32)
 9
10# 儲存為 .npy
11slice_ct = preprocess_slice(ct_dicom_array)
12slice_cbct = preprocess_slice(cbct_dicom_array)
13np.save(f"brain/train/a/{idx:04d}.npy", slice_ct)    # pCT
14np.save(f"brain/train/b/{idx:04d}.npy", slice_cbct)  # CBCT

注意datasets.py 中使用 np.load(..., allow_pickle=True) 載入檔案,每個 .npy 應為 2D array,shape 為 (H, W)(如 (256, 256)),不含 channel 維度——channel 由 torch.unsqueeze 在 DataLoader 中動態添加。


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

4.1 範例一:訓練模型

以下為完整的訓練流程,已加上中文註解並調整為可直接執行的版本:

 1# Train_condition.py — 條件式 DDPM 訓練
 2import os
 3import sys
 4import time
 5import datetime
 6import torch
 7import torch.optim as optim
 8from torch.utils.data import DataLoader
 9from torch.autograd import Variable
10
11from Diffusion_condition import GaussianDiffusionTrainer_cond
12from Model_condition import UNet
13from datasets import ImageDataset  # 通用版 dataset
14
15# ===== 超參數設定 =====
16dataset_name = "brain"       # 資料集資料夾名稱
17out_name     = "trial_1"     # 實驗名稱
18batch_size   = 2             # 批次大小(依 GPU VRAM 調整)
19T            = 1000          # 擴散步數
20ch           = 128           # 基礎通道數
21ch_mult      = [1, 2, 3, 4]  # 通道倍率
22attn         = [2]           # 加入 Attention 的層級索引
23num_res_blocks = 2           # 每層 ResBlock 數量
24dropout      = 0.3           # Dropout 比率
25lr           = 1e-4          # 學習率
26n_epochs     = 1000          # 訓練 epoch 數
27beta_1       = 1e-4          # 噪聲排程起始值
28beta_T       = 0.02          # 噪聲排程結束值
29grad_clip    = 1.0           # 梯度裁剪閾值
30
31# ===== 初始化 =====
32device = torch.device("cuda")
33Tensor = torch.cuda.FloatTensor
34save_weight_dir = f"./Checkpoints/{out_name}"
35os.makedirs(save_weight_dir, exist_ok=True)
36
37# 資料載入器
38train_dataloader = DataLoader(
39    ImageDataset(f"./{dataset_name}", transforms_=False, unaligned=True),
40    batch_size=batch_size,
41    shuffle=True,
42    num_workers=0,
43)
44
45# 模型與優化器
46net_model = UNet(T, ch, ch_mult, attn, num_res_blocks, dropout).to(device)
47optimizer = optim.AdamW(
48    net_model.parameters(),
49    lr=lr,
50    betas=(0.9, 0.999),
51    eps=1e-8,
52    weight_decay=0,
53)
54trainer = GaussianDiffusionTrainer_cond(net_model, beta_1, beta_T, T).to(device)
55
56# ===== 訓練迴圈 =====
57prev_time = time.time()
58for epoch in range(1, n_epochs + 1):
59    loss_save = 0
60    for i, batch in enumerate(train_dataloader, 1):
61        optimizer.zero_grad()
62        ct   = Variable(batch["a"].type(Tensor))    # 目標 CT(key 依 dataset 版本可能是 "a" 或 "pCT")
63        cbct = Variable(batch["b"].type(Tensor))     # 條件 CBCT("b" 或 "CBCT")
64        x_0  = torch.cat((ct, cbct), 1)              # 2-channel 輸入
65        loss = trainer(x_0)
66        loss_save += loss / 65536                     # 正規化 loss
67        loss.backward()
68        torch.nn.utils.clip_grad_norm_(net_model.parameters(), grad_clip)
69        optimizer.step()
70    loss_save /= i
71
72    # 計時與日誌
73    duration  = datetime.timedelta(seconds=(time.time() - prev_time))
74    eta       = datetime.timedelta(seconds=(n_epochs - epoch) * (time.time() - prev_time))
75    prev_time = time.time()
76    sys.stdout.write(
77        f"\r[Epoch {epoch}/{n_epochs}] [ETA: {eta}] [Duration: {duration}] "
78        f"[MSE Loss: {loss_save.item():.6f}]"
79    )
80
81    # 每 10 epoch(100 之後)儲存 checkpoint
82    if epoch > 100 and epoch % 10 == 0:
83        torch.save(
84            net_model.state_dict(),
85            os.path.join(save_weight_dir, f"ckpt_{epoch}_.pt"),
86        )

訓練要點:

  • Loss 除以 65536 (= 256 x 256) 是將 reduction='sum' 的 MSE 正規化為 per-pixel 等級
  • Gradient Clipping 設為 1.0 防止擴散模型訓練初期梯度爆炸
  • 在 epoch > 100 後才開始存 checkpoint,避免儲存早期未收斂的權重
  • 典型訓練時間:約 1000 epochs,單張 NVIDIA V100 約需 24-48 小時(依資料集大小)

4.2 範例二:推論(生成合成 CT)

 1# Test_condition.py — 條件式 DDPM 推論
 2import os
 3import numpy as np
 4import torch
 5from torch.utils.data import DataLoader
 6from torch.autograd import Variable
 7
 8from Diffusion_condition import GaussianDiffusionSampler_cond
 9from Model_condition import UNet
10from datasets import ImageDataset
11
12# ===== 參數(須與訓練時一致) =====
13dataset_name = "brain"
14out_name     = "trial_1"
15T            = 1000
16ch           = 128
17ch_mult      = [1, 2, 3, 4]
18attn         = [2]
19num_res_blocks = 2
20dropout      = 0.3
21beta_1       = 1e-4
22beta_T       = 0.02
23
24device = torch.device("cuda:0")
25Tensor = torch.cuda.FloatTensor
26
27# ===== 載入訓練好的模型 =====
28net_model = UNet(T, ch, ch_mult, attn, num_res_blocks, dropout).to(device)
29ckpt = torch.load(f"./Checkpoints/{out_name}/ckpt_1000_.pt", map_location=device)
30net_model.load_state_dict(ckpt)
31net_model.eval()
32print("Model weights loaded.")
33
34# ===== 建立 Sampler =====
35sampler = GaussianDiffusionSampler_cond(net_model, beta_1, beta_T, T).to(device)
36
37# ===== 測試資料 =====
38test_dataloader = DataLoader(
39    ImageDataset(f"./{dataset_name}", transforms_=False, unaligned=True, mode="test"),
40    batch_size=1,
41    shuffle=False,
42    num_workers=0,
43)
44
45# ===== 推論迴圈 =====
46os.makedirs(f"test/{out_name}", exist_ok=True)
47results = []
48
49with torch.no_grad():
50    for idx, batch in enumerate(test_dataloader, 1):
51        print(f"Processing slice {idx}...")
52        cbct = Variable(batch["b"].type(Tensor))     # 條件 CBCT
53
54        # 從純噪聲開始
55        noisy_image = torch.randn(1, 1, 256, 256, device=device)
56        x_in = torch.cat((noisy_image, cbct), dim=1)  # [noise, CBCT] → 2-ch
57
58        # 反向擴散:T=1000 步去噪
59        x_out = sampler(x_in)
60
61        # 提取生成的合成 CT(第 0 channel)
62        synthetic_ct = x_out[:, 0:1, :, :]  # shape: [1, 1, 256, 256]
63
64        # 儲存結果
65        sct_np = synthetic_ct.cpu().numpy().squeeze()
66        np.save(f"test/{out_name}/sCT_{idx:04d}.npy", sct_np)
67        results.append(sct_np)
68
69print(f"Done. Generated {len(results)} synthetic CT slices.")

推論要點:

  • 每張影像需要 1000 步反向迭代,推論速度較 GAN 慢數百倍
  • 可透過 DDIM Sampling (DDIM 取樣) 等加速策略將步數降至 50-100 步(需自行實作)
  • 輸出範圍為 [-1, 1],需反正規化回 HU 值才能用於劑量計算

4.3 範例三:不確定性估計 (Uncertainty Estimation)

擴散模型的獨特優勢在於可透過多次取樣獲得 pixel-wise 不確定性地圖

 1import torch
 2import numpy as np
 3from Diffusion_condition import GaussianDiffusionSampler_cond
 4from Model_condition import UNet
 5
 6def estimate_uncertainty(
 7    model_path: str,
 8    cbct_slice: np.ndarray,
 9    n_samples: int = 10,
10    device: str = "cuda:0",
11) -> dict:
12    """
13    對同一張 CBCT 進行多次取樣,計算 pixel-wise 不確定性。
14
15    Args:
16        model_path: 訓練好的 checkpoint 路徑
17        cbct_slice: 單張 CBCT 影像 (H, W),已正規化至 [-1, 1]
18        n_samples: 取樣次數(越多越穩定,建議 10-20)
19        device: GPU 設備
20
21    Returns:
22        dict 包含 mean_sCT, std_map, all_samples
23    """
24    # 載入模型
25    T, ch, ch_mult, attn = 1000, 128, [1, 2, 3, 4], [2]
26    net_model = UNet(T, ch, ch_mult, attn, 2, 0.3).to(device)
27    net_model.load_state_dict(torch.load(model_path, map_location=device))
28    net_model.eval()
29
30    sampler = GaussianDiffusionSampler_cond(
31        net_model, beta_1=1e-4, beta_T=0.02, T=T
32    ).to(device)
33
34    # 準備 CBCT 條件
35    cbct_tensor = torch.from_numpy(cbct_slice).float().unsqueeze(0).unsqueeze(0).to(device)
36
37    # 多次取樣
38    all_samples = []
39    with torch.no_grad():
40        for i in range(n_samples):
41            noise = torch.randn(1, 1, 256, 256, device=device)
42            x_in = torch.cat((noise, cbct_tensor), dim=1)
43            x_out = sampler(x_in)
44            sct = x_out[:, 0:1, :, :].cpu().numpy().squeeze()
45            all_samples.append(sct)
46            print(f"  Sample {i+1}/{n_samples} done.")
47
48    all_samples = np.stack(all_samples, axis=0)  # (n_samples, H, W)
49
50    return {
51        "mean_sCT":    np.mean(all_samples, axis=0),   # 平均合成 CT
52        "std_map":     np.std(all_samples, axis=0),     # 不確定性地圖
53        "all_samples": all_samples,                      # 所有取樣結果
54    }
55
56# 使用範例
57# result = estimate_uncertainty("Checkpoints/trial_1/ckpt_1000_.pt", cbct_slice, n_samples=10)
58# high_uncertainty_mask = result["std_map"] > threshold  # 標記高不確定性區域

不確定性估計的臨床價值:

  • 標記合成 CT 中可能不可靠的區域(如骨-氣體交界處)
  • 為劑量計算提供信心區間 (Confidence Interval; 信心區間)
  • 支援自適應放療的品質保證 (Quality Assurance, QA; 品質保證) 流程

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

5.1 Bio-SDG Domain 2 定位

conditional_DDPM 屬於 Sub-domain D: Diffusion Models for Medical Images (醫學影像擴散模型),代表從 GAN-based 方法(Sub-domain C)向 Diffusion-based 方法的典範轉移 (Paradigm Shift; 典範轉移)。

Sub-domain代表專案方法本專案關聯
A. 平台工具MONAI GenerativeModelsFramework可將 cDDPM 整合為 MONAI 的 custom network
B. 計算病理CLAM, Patho-GANWSI 分析/合成2D slice-level 方法可遷移至 patch-level 病理影像
C. 跨模態合成medSynthesis, Synthetic-CTGAN-basedcDDPM 為下一代替代方案,品質更高但速度更慢
D. 擴散模型conditional_DDPMcDDPM本專案:minimal reference implementation
E. 特殊應用VICTREVirtual trials可產生 virtual trial 所需的合成影像
F. 癌症影像foundation-cancer-image-biomarkerBiomarker合成影像可增補 biomarker 訓練資料

5.2 技術演進脈絡

12017 Pix2Pix (paired GAN)
2 └─ 2018 CycleGAN (unpaired GAN)
3     └─ 2020 medSynthesis (medical GAN)
4         └─ 2020 DDPM (Ho et al.)
5             └─ 2023 conditional_DDPM (本專案:cDDPM for CBCT→CT) ◄── 你在這裡
6                 └─ 2024+ DenseDiffusion, SD-Messenger (進階擴散)
7                     └─ 2025+ 3D Volumetric Diffusion (下一個 blue ocean)

5.3 藥物開發連結

應用場景說明
Imaging Biomarker (影像生物標記)合成 CT 可用於追蹤腫瘤體積變化,支援 Phase I/II 試驗的療效評估端點
Virtual Clinical Trial (虛擬臨床試驗)搭配 VICTRE 等框架,用合成影像模擬不同 imaging protocol 的影響
Privacy-Preserving Data Sharing (隱私保護資料共享)生成合成影像取代真實病患資料,加速多中心試驗的資料整合
Adaptive Radiotherapy (自適應放射治療)直接支援放射治療藥物的合併療法 (Combination Therapy) 精準規劃
Data Augmentation (資料擴增)為稀有疾病或罕見解剖結構生成訓練資料,改善下游 AI 模型表現

6. 與其他工具的整合

6.1 與 MONAI GenerativeModels 整合

MONAI 提供擴散模型的高階 API,可將本專案的核心邏輯遷移至 MONAI 框架以獲得更好的工程支援:

 1# 概念示範:將 cDDPM 邏輯遷移到 MONAI 框架
 2from monai.networks.nets import DiffusionModelUNet
 3from monai.networks.schedulers import DDPMScheduler
 4
 5# MONAI 風格的條件式 U-Net
 6model = DiffusionModelUNet(
 7    spatial_dims=2,
 8    in_channels=2,         # 與本專案相同:[noisy_CT, CBCT]
 9    out_channels=1,        # 預測噪聲
10    num_channels=(128, 256, 384, 512),  # 對應 ch_mult=[1,2,3,4]
11    attention_levels=(False, False, True, False),
12    num_res_blocks=2,
13)
14
15scheduler = DDPMScheduler(
16    num_train_timesteps=1000,
17    beta_start=1e-4,
18    beta_end=0.02,
19    schedule="linear",
20)

6.2 與 AIKT Pipeline 整合

在 AI-Knowledge Template (AIKT) 管線中的定位:

AIKT Layer整合方式
Layer 9 (paper-search)搜尋 DDPM、CBCT-CT、synthetic CT 相關論文
Layer 10 (paper-qa-lite)對論文集合做 RAG 問答,比較不同 sCT 方法
Layer 12 (gh-tutorial-qd)本教學即由此 Layer 產出
Layer 18 (research-pipeline)將 cDDPM 評估納入放療影像 AI 研究管線
Layer 19 (tu-plan-generator)評估合成影像在臨床試驗申請中的法規合規性

6.3 加速推論的整合策略

原始 DDPM 推論需 1000 步,以下是實用的加速方案:

方法步數品質整合難度
DDIM (Song et al., 2020)50-100接近原始中(改寫 sampler)
DPM-Solver (Lu et al., 2022)10-25接近原始
Consistency Models (Song et al., 2023)1-2略降高(需重新訓練)
Progressive Distillation4-8可接受高(需 teacher-student)

6.4 3D 擴展路徑

本專案為 2D slice-by-slice 處理。擴展為 3D volumetric 的關鍵修改:

 1# 概念示範:2D → 3D 的核心修改點
 2# 1. Conv2d → Conv3d
 3self.head = nn.Conv3d(2, ch, kernel_size=3, stride=1, padding=1)
 4
 5# 2. 輸入維度:(B, 2, D, H, W) 取代 (B, 2, H, W)
 6x_0 = torch.cat((ct_volume, cbct_volume), dim=1)  # 5D tensor
 7
 8# 3. GroupNorm 不變(channel-wise 操作)
 9# 4. Attention 計算量急遽增加:D*H*W tokens
10#    建議改用 axial attention 或 windowed attention

7. 優缺點分析

7.1 優點

優點說明
極簡實作5 個檔案、~400 行程式碼,無隱藏依賴,適合理解 DDPM 原理
數學完整完整實作 forward/reverse process,含 posterior variance 計算
同行審查Medical Physics 期刊發表,具臨床驗證基礎
通用框架條件式 image-to-image translation 可套用於 MRI→CT、PET→CT 等任務
不確定性估計多次取樣可獲得 pixel-wise 信心地圖,GAN 做不到
訓練穩定無 adversarial loss,MSE 收斂穩定
MIT 授權商業友善,可自由修改與發布

7.2 缺點與限制

缺點嚴重度緩解方式
推論極慢 (T=1000 步)整合 DDIM/DPM-Solver 加速至 50 步
僅支援 2D逐 slice 處理有 z-axis 不連續性;需改 3D
無預訓練權重需自行準備配對資料訓練
硬編碼 256×256修改 head/tail conv 與 channel 配置
datasets.py 不夠通用針對自己的資料格式修改 __getitem__
無評估指標需自行加入 MAE/SSIM/PSNR/FID 計算
無 mixed precision加入 torch.cuda.amp 可減少 ~40% VRAM
無 logging/wandb加入 tensorboard 或 wandb 追蹤訓練
資料集未公開需自行取得醫學影像配對資料(IRB 審查)

7.3 Blue Ocean 機會

基於本專案的基礎,以下是醫學影像合成的高價值研究方向:

  1. 3D Volumetric Diffusion (3D 體積擴散) — 目前幾乎無公開的 3D 條件式擴散模型用於醫學影像,是最大的技術缺口
  2. Multi-modal Conditioning (多模態條件) — 同時以 CBCT + dose map + contour 作為條件,生成更精準的 sCT
  3. Foundation Model for Medical Image Synthesis (醫學影像合成基礎模型) — 跨解剖部位、跨機構的通用合成模型
  4. Regulatory-Ready Synthetic Data (法規就緒合成資料) — 滿足 FDA 對 AI/ML-based SaMD (Software as Medical Device) 的資料品質要求
  5. Latent Diffusion for Medical Images (醫學影像潛在擴散) — 在壓縮的 latent space 操作,大幅降低 3D 擴散的記憶體需求

7.4 適用場景建議

場景是否推薦理由
學習 DDPM 原理強烈推薦程式碼精簡、數學對應清晰
CBCT→CT 研究 baseline推薦有論文支撐,可作為比較基準
臨床部署不推薦(需大量工程)缺少推論加速、3D 支援、QA 流程
其他 image-to-image 任務推薦修改 dataset 即可套用
大規模合成資料生成有條件推薦需先整合 DDIM 加速

本教學為 Bio-SDG Domain 2 (生物醫學影像合成) 系列的第 11 篇,涵蓋 Sub-domain D: Diffusion Models for Medical Images。