病灶变化预测 vs 分类:医学影像 AI 中更有价值的问题是什么?

一、前言:医学影像 AI,真的只是"分类"吗?

目前在医学影像领域,90% 的深度学习项目都停留在分类阶段

  • 良性 / 恶性

  • 有病灶 / 无病灶

  • 高风险 / 低风险

但在真实临床场景中,医生更关心的问题往往是:

病灶 有没有变大?

生长速度 快还是慢?

下一阶段 可能发展到什么程度?

这类问题,本质上已经不再是"分类问题",而是变化预测(Change Prediction)问题

本文将从建模思路 出发,并结合完整可运行的代码示例,讲清楚医学影像中"变化预测"到底应该怎么做。


二、分类任务 vs 变化预测:从数据结构就已经不同

1️⃣ 传统分类任务的数据形式

Image → Label

对应代码通常是:

image, label

模型只关心:

👉 这一刻是什么状态


2️⃣ 变化预测任务的数据形式(关键差异)

Image(t1), Image(t2) → Change

也就是:

image_t1, image_t2, delta_label

模型关心的是:

👉 从 t1 到 t2,发生了什么变化

这是后续所有建模差异的根源。


三、变化预测数据集:完整 Dataset 代码示例

下面是一个标准的变化预测 Dataset 实现(PyTorch)

python 复制代码
import torch
from torch.utils.data import Dataset
import numpy as np

class LesionChangeDataset(Dataset):
    def __init__(self, data_list):
        """
        data_list: [
            {
                't1': 'path/to/image_t1.npy',
                't2': 'path/to/image_t2.npy',
                'delta': 2.3
            },
            ...
        ]
        """
        self.data_list = data_list

    def __len__(self):
        return len(self.data_list)

    def __getitem__(self, idx):
        img_t1 = np.load(self.data_list[idx]['t1'])
        img_t2 = np.load(self.data_list[idx]['t2'])
        delta = self.data_list[idx]['delta']

        img_t1 = torch.tensor(img_t1).float().unsqueeze(0)
        img_t2 = torch.tensor(img_t2).float().unsqueeze(0)
        delta = torch.tensor(delta).float()

        return img_t1, img_t2, delta

📌 注意

变化预测不是"一个 image + 一个 label",

而是一对影像 + 一个变化标签


四、共享 CNN 特征提取器(变化预测的核心原则)

在变化预测中,有一个非常重要但经常被忽略的原则

不同时间点的影像,必须使用同一个 CNN(共享权重)

否则模型学到的是网络差异 ,而不是病灶变化


CNN 特征提取器实现

python 复制代码
import torch.nn as nn

class FeatureCNN(nn.Module):
    def __init__(self):
        super().__init__()
        self.features = nn.Sequential(
            nn.Conv2d(1, 16, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2),

            nn.Conv2d(16, 32, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2)
        )

        self.fc = nn.Linear(32 * 32 * 32, 128)

    def forward(self, x):
        x = self.features(x)
        x = x.view(x.size(0), -1)
        return self.fc(x)

五、变化建模方式一:特征差分(最推荐)

这是医学影像变化预测中最直观、最稳定的方法

1️⃣ 特征差分函数

python 复制代码
def feature_difference(f1, f2):
    return f2 - f1

2️⃣ 变化回归模型

python 复制代码
class ChangeRegressor(nn.Module):
    def __init__(self):
        super().__init__()
        self.regressor = nn.Sequential(
            nn.Linear(128, 64),
            nn.ReLU(),
            nn.Linear(64, 1)
        )

    def forward(self, x):
        return self.regressor(x)

3️⃣ 前向传播逻辑(完整)

python 复制代码
cnn = FeatureCNN()
regressor = ChangeRegressor()

f1 = cnn(img_t1)
f2 = cnn(img_t2)

diff_feature = feature_difference(f1, f2)
pred_delta = regressor(diff_feature)

📌 核心思想

模型不再"猜类别",而是直接学习变化本身


六、对比方案:特征拼接(不推荐但常见)

python 复制代码
combined_feature = torch.cat([f1, f2], dim=1)
python 复制代码
class ChangeConcatModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc = nn.Sequential(
            nn.Linear(256, 128),
            nn.ReLU(),
            nn.Linear(128, 1)
        )

    def forward(self, f1, f2):
        x = torch.cat([f1, f2], dim=1)
        return self.fc(x)

📌 实践中发现:

  • 拼接模型能学

  • 但对"变化"的表达不如差分明确


七、多时间点变化预测(进阶工程版)

真实医学随访往往是:

t1 → t2 → t3 → t4

这时可以引入 CNN + LSTM


LSTM 变化趋势模型

python 复制代码
class ChangeLSTM(nn.Module):
    def __init__(self):
        super().__init__()
        self.lstm = nn.LSTM(
            input_size=128,
            hidden_size=64,
            batch_first=True
        )
        self.fc = nn.Linear(64, 1)

    def forward(self, feature_seq):
        _, (h_n, _) = self.lstm(feature_seq)
        return self.fc(h_n[-1])

构造时间序列特征

python 复制代码
features = []
for img in images:  # 多时间点影像
    features.append(cnn(img))

feature_seq = torch.stack(features, dim=1)
pred = lstm_model(feature_seq)

📌 到这一步,模型已经能学习病灶生长趋势


八、训练代码:变化预测该怎么训?

损失函数(回归,而不是分类)

criterion = nn.MSELoss()


训练循环(完整示例)

python 复制代码
optimizer = torch.optim.Adam(
    list(cnn.parameters()) + list(regressor.parameters()),
    lr=1e-3
)

for img_t1, img_t2, delta in dataloader:
    optimizer.zero_grad()

    f1 = cnn(img_t1)
    f2 = cnn(img_t2)

    diff = f2 - f1
    pred = regressor(diff)

    loss = criterion(pred.squeeze(), delta)
    loss.backward()
    optimizer.step()

📌 如果你在这里用的是 CrossEntropyLoss

那本质上还是分类思维。


九、评估指标:为什么 Accuracy 不适合?

变化预测更适合以下指标:

python 复制代码
mae = torch.mean(torch.abs(pred - target))
rmse = torch.sqrt(torch.mean((pred - target) ** 2))
  • MAE:平均变化误差

  • RMSE:对极端增长更敏感

这比 Accuracy 更符合医学意义


十、总结:变化预测不是"高级分类"

当真正把代码写完整后会发现:

变化预测 ≠ 分类 + 换个模型

而是:

  • 数据结构不同

  • 建模思路不同

  • 评估方式不同

这一步,正是医学影像 AI 从"能跑"走向"有用"的关键

相关推荐
老蒋每日coding2 分钟前
AI Agent 设计模式系列(十五)—— A2A Agent 间通信模式
人工智能·设计模式
搞科研的小刘选手3 分钟前
【智能检测专题】2026年智能检测与运动控制技术国际会议(IDMCT 2026)
人工智能·学术会议·智能计算·电子技术·智能检测·运动控制技术·南京工业大学
Elastic 中国社区官方博客3 分钟前
Agent Builder 现已正式发布:在几分钟内发布上下文驱动的 agents
大数据·人工智能·elasticsearch·搜索引擎·ai·全文检索
翱翔的苍鹰3 分钟前
通俗讲解在中文 NLP中要用 jieba 分词,以及它和 循环神经网络(RNN) 的关系。
人工智能·pytorch·rnn·神经网络·自然语言处理
安科瑞小许4 分钟前
零碳园区:政策驱动下的智慧能源转型之路
大数据·人工智能·能源·碳排放·零碳园区
SelectDB技术团队6 分钟前
构建 AI 数据基座:思必驰基于 Apache Doris 的海量多模态数据集管理实践
人工智能·apache·知识图谱
小二·8 分钟前
Python Web 开发进阶实战:AI 伦理审计平台 —— 在 Flask + Vue 中构建算法偏见检测与公平性评估系统
前端·人工智能·python
WZGL123014 分钟前
智能机器人:当养老遇上科技,温暖与风险并存的新时代
人工智能·科技·机器人
ZIXEL子虔科技14 分钟前
从本地到云端:三维 CAD 国产化的下一步在哪里
ai·云原生
浮生醉清风i17 分钟前
Spring Ai
java·人工智能·spring