
简介《基于证据深度神经网络的医学影像三支决策》是一篇发表在《西北大学学报自然科学版》的学术论文面向医学影像分析、深度学习和不确定性决策领域的研究者与工程师。针对医学影像中标注受限、噪声干扰和病灶表征不明确导致的高误诊风险论文提出将证据理论Dempster-Shafer与深度神经网络结合的EDNN模型并在三支决策框架下识别高不确定度影像、延迟决策以降低系统分类风险。资源为PDF格式共1个文件压缩包大小1.41MB内容包含摘要、关键词、引言、方法介绍、肺炎与乳腺癌数据集实验及结论等完整结构。目前已有134人学习对智能辅助诊断、可信机器学习及医学影像不确定分类方向具有较高参考价值可帮助读者理解如何量化与利用深度学习中的不确定性信息并借鉴EDNN建模思路与实验设计方法。1. 医学影像模型的两难往往不是“准不准”而是“敢不敢说不知道”影像科医生看一张 CT真正为难的不是病灶太明显而是形态介于良恶性之间、随访建议左右摇摆的病例。医学影像深度学习模型同样卡在这类样本上模型被训练成必须输出一个确定类哪怕特征证据互相矛盾它也硬给一个 0.87 的概率。这个 0.87 既不反映真实把握也无法帮助临床决策。基于证据深度神经网络的医学影像三支决策正是把“网络也要会说不知道”这件事工程化用证据理论替代 Softmax 概率让网络对每条样本输出“支持、反对、不确定”三个维度的度量落到接受、拒绝、延迟人工复核三个动作上。这套方案适合做影像分类、分割模型落地的算法工程师以及关注模型在临床中可靠性的技术负责人。下面按照理论、实现、参数到进阶技巧的顺序一次讲透。2. 从Softmax到Dempster-Shafer证据深度神经网络的不确定性从哪来2.1 Softmax输出了概率但概率不等于置信度Softmax 的数学作用是让 K 个实数值 logits 变成和为 1 的概率分布。这个变换有两个在医学影像场景下很难容忍的缺陷。第一Softmax 是“公平分配”机制。只要输入能通过前向传播它必然输出一个分布极端情况下 0.6/0.4 也算一个结论。面对训练分布之外的输入——比如不同厂商设备扫描的影像、重建算法不同的 CT 序列——网络没有表达“我没见过这个”的通道只能强行把特征映射到已学类别上。第二Softmax 的概率值受模型过拟合影响严重训练越充分输出概率越尖锐但这并不代表泛化能力越强。医学影像数据集规模通常不大加上标注噪声过拟合是常态。一个在验证集上准确率 98% 的模型遇到分布外样本仍可能给出高置信度错误预测。这个现象在文献中叫“过度自信”overconfidence本质原因是网络输出的 logits 数值依赖于特征空间的绝对距离而该距离对未知数据没有任何约束。证据深度神经网络Evidential Deep Learning, EDL换了一个思路不再从网络输出一个概率而是输出每个类别的“证据量”——一个非负的实数值用 Dempster-Shafer 证据理论的框架把证据转换为信任函数belief与不确定性uncertainty。不确定性不再是概率的副产品而是网络输出的正式维度。2.2 用证据量重写类别输出mass函数与不确定性公式先明确 D-S 证据理论的基本概念。设识别框架为 Θ {θ₁, θ₂, …, θ_K}每个 θᵢ 表示一个类别假设。mass 函数 m 将 Θ 的幂集映射到 [0,1]满足 m(∅) 0 且 Σ m(A) 1。关键区别在这里mass 函数可以直接给整个识别框架 Θ 分配质量这团质量不代表任何具体类别而代表“证据不足以区分”的程度。EDL 的做法是网络输出 K 维非负证据向量 e [e₁, e₂, …, e_K]每个 eᵢ 是对类别 θᵢ 的支持强度。按常见实现令 S Σ eᵢ K则类别的信任函数为m(θᵢ) eᵢ / S对识别框架整体的不确定性为m(Θ) K / S这个设计非常优雅。当某个样本完全没有证据即所有 eᵢ 0 时S Km(Θ) 1不确定性达到最大值模型表达的确实是“我不知道”。而当某个类别的证据远大于其他类别时m(Θ) 趋近于 0模型对该样本有了明确判断。这里有个实现层面的细节值得注意要让不确定性在数值上平稳证据必须严格非负我一般用 Softplus 激活来保证而不是 ReLU——ReLU 在零点处梯度突然归零会让证据“卡死”在 0训练初期尤其容易发生。从贝叶斯角度看证据 eᵢ 与 Dirichlet 分布的参数 αᵢ eᵢ 1 一一对应类别概率分布 p 服从 Dirichlet 分布。这个连接带来一个额外好处EDL 不仅能给出点估计还能通过 Dirichlet 分布的方差给出二阶不确定性比单纯的一阶不确定性预测概率的置信区间信息量更大。2.3 两行PyTorch代码把证据变成三支决策可用的输入理解了公式实现就很容易。下面给出一段把证据向量转换为 belief、disbelief 和 uncertainty 的模块这是后续所有决策逻辑的基础。import torch def evidence_to_mass(evidence: torch.Tensor, num_classes: int 2): 将证据向量转换为 D-S 理论中的信任函数和不确定性。 参数: evidence: 网络输出的非负证据向量形状 [batch_size, num_classes] num_classes: 类别总数作为不确定性计算中的常数 K 返回: belief: 对正类的信任程度形状 [batch_size, 1] disbelief: 对负类的信任程度形状 [batch_size, 1] uncertainty: 整体不确定性形状 [batch_size, 1] # S sum(e) K是证据量加类别数构成的归一化因子 S evidence.sum(dim-1, keepdimTrue) num_classes # 每个类别的信任函数 该类证据量 / S belief evidence[:, :1] / S disbelief evidence[:, 1:] / S # 不确定性 K / S当证据稀疏时 S 接近 K不确定性趋近 1 uncertainty num_classes / S return belief, disbelief, uncertainty这里的关键参数是num_classes。S 的计算里多加了 K这是 EDL 与直接对证据做softmax的根本差别softmax必须把质量全部分配给已知类别而加 K 之后质量允许“不被分配”。uncertainty num_classes / S这个式子要特别注意它不是经验公式而是 D-S 理论中直接给整个识别框架分配质量的结果。3. 搭建一个可训练的医学影像证据网络模型、损失与训练要点3.1 编码器加证据头网络结构怎么改在医学影像分类任务中我会把 EDL 的结构分成三块影像编码器、证据头、决策层。编码器直接复用 ImageNet 预训练的 ResNet34 或 ResNet50去掉最后的全连接分类层只保留到avgpool的特征输出。在这之后接证据头负责把 512 维特征映射为 K 维非负证据。import torch import torch.nn as nn from torchvision import models class EvidentialHead(nn.Module): 将影像特征映射为非负证据。 注意这里不用 Softmax也不用 ReLU而用 Softplus 保证证据非负。 def __init__(self, in_features: int, num_classes: int): super().__init__() self.fc nn.Linear(in_features, 128) self.out nn.Linear(128, num_classes) self.activation nn.Softplus(beta1.0) def forward(self, x: torch.Tensor) - torch.Tensor: x torch.relu(self.fc(x)) evidence self.activation(self.out(x)) return evidence class EvidentialImageNet(nn.Module): 完整的医学影像证据分类网络。 输入: [B, 3, H, W] 的影像张量 输出: [B, K] 的非负证据向量 def __init__(self, num_classes: int 2, backbone: str resnet34): super().__init__() model getattr(models, backbone)(weightsmodels.ResNet34_Weights.IMAGENET1K_V1) self.encoder nn.Sequential(*list(model.children())[:-2]) self.pool nn.AdaptiveAvgPool2d((1, 1)) self.evidence_head EvidentialHead(512, num_classes) def forward(self, x: torch.Tensor) - torch.Tensor: features self.encoder(x) pooled self.pool(features).flatten(1) evidence self.evidence_head(pooled) return evidence参数说明backboneresnet34的最后一层conv5_x输出通道数为 512所以EvidentialHead的in_features写死为 512。如果换 ResNet50这一维要改成 2048。使用AdaptiveAvgPool2d((1,1))的目的是让网络接受任意输入尺寸但实际训练中 CT、MRI 影像往往是非方形或大尺寸的我要么在预处理里中心裁剪到 224×224要么使用RandomResizedCrop做在线增强两种方式都会在 DataLoader 里完成而不是直接喂原始 DICOM 尺寸。3.2 损失函数设计证据NLL、Dirichlet正则与退火系数EDL 的损失函数是配套的核心直接决定不确定性估计的质量。我把损失拆成两项数据项的负对数似然NLL加上正则项。NLL 的计算基于 Dirichlet 分布目标是让网络对正确类别给出高证据正则项则把不确定性控制在一个健康水平防止模型对每一条样本都“信心爆棚”。import torch import torch.nn.functional as F def edl_loss( evidence: torch.Tensor, target: torch.Tensor, num_classes: int 2, annealing_coef: float 1.0, ) - torch.Tensor: EDL 损失函数Dirichlet 负对数似然 KL 正则。 参数: evidence: 网络输出的非负证据形状 [B, K] target: one-hot 标签形状 [B, K] annealing_coef: KL 正则项的退火系数训练初期建议从 0 开始递增 alpha evidence 1.0 S alpha.sum(dim-1, keepdimTrue) # 类别分布 p 的期望为 alpha / S # 多项式 Dirichlet 分布的负对数似然 # -sum(y_i * (log(alpha_i) - log(S))) log_probs torch.log(alpha) - torch.log(S) loss_nll -(target * log_probs).sum(dim-1) # KL 散度正则项将非目标类别的 alpha 推向 1 # 对 one-hot 标签中为 1 的位置将 alpha 设为 1 # 其余位置保持 alpha 不变再计算与均匀 Dirichlet(1,...,1) 的 KL。 alpha_tilde target (1 - target) * alpha S_tilde alpha_tilde.sum(dim-1, keepdimTrue) kl ( torch.lgamma(S_tilde) - torch.lgamma(alpha_tilde).sum(dim-1) ((alpha_tilde - 1) * (torch.digamma(alpha_tilde) - torch.digamma(S_tilde))).sum(dim-1) ) loss (loss_nll annealing_coef * kl).mean() return loss参数说明annealing_coef是训练中要重点调的参数。如果从一开始就设一个很大的值比如 1.0KL 正则会过度强调“降低不确定性”导致网络过早收敛到低证据状态训练初期梯度就被正则项主导。常见的做法是设一个全局最大的退火系数max_annealing按训练轮次线性上升前 10 到 20 个 epoch 从 0 升到目标值。医学影像往往样本量少、噪声大退火应该更保守比如 30 个 epoch否则不确定性会被压死后面三支决策就没有意义了。还有一个实现细节torch.digamma在数值极小时可能不稳定我习惯在alpha上加一个1e-8的 epsilon避免梯度过冲导致损失变成nan。3.3 医学影像特有的训练调整类别不平衡与OOD模拟医学影像数据集有很强的属性类别极度不平衡、标注噪声高、不同医院数据分布差异大。这些属性对 EDL 的训练影响非常大原因在于证据量直接受类别频率影响。多数类样本占据了大量梯度更新其证据被推到很高的水平少数类的证据则会变得非常稀疏训练结束后不确定性整体偏高。我处理这个问题的第一个手段是采样。每个 batch 内按类别做加权采样保证少数类的影像在 batch 中占比不低于 30%原理是让少数类样本的证据更新频率稳定。这个操作在 PyTorch 里用WeightedRandomSampler实现权重按1 / 类别频率计算非常简单但效果明显。第二个手段是模拟 OOD 样本。证据网络的“不确定性”维度需要有监督信号才能学会表达否则它就只是一个被 KL 正则推着走的数字。我在训练时做了两件额外的事一是随机混入无病灶的正常影像标注它们为“不确定”二是对输入影像做强度增强扰动调整窗宽窗位、加高斯噪声让网络在输入被破坏时收紧证据。这么做之后模型在真实 OOD 数据上的不确定性显著提高三支决策的延迟档才有意义。提示不要在训练集之外直接找一堆新数据当 OOD 来训。医学影像的域差异很大用真实外部数据做验证更有价值做训练反而可能引入域偏差。4. 三支决策阈值怎么标定接受、拒绝、延迟人工复核的落地参数4.1 决策规则定义接受、拒绝、延迟的触发条件有了 belief、disbelief 和 uncertainty三支决策的规则定义非常直接。设接受阈值为 α拒绝阈值为 β延迟上限为 γ。对二分类医学影像任务阳性、阴性接受belief ≥ α且 uncertainty ≤ γ。此时网络证据充分输出“阳性”走自动诊断流程。拒绝disbelief ≥ α且 uncertainty ≤ γ。此时网络证据充分输出“阴性”。延迟不满足上述两个条件。样本进入人工复核队列。这里 α 和 β 是同一枚硬币的两面但实际标定时常常不相等。临床场景里把阳性漏检假阴性的代价远高于把阴性误报为阳性所以 α接受阈值和 β拒绝阈值可以不对称设置α 通常设得更高让“接受”的门槛比“拒绝”更严格。uncertainty ≤ γ这个条件经常被忽略但它其实是独立于类别判断的第三维度。某个样本的 belief 和 disbelief 可能都不低但 evidence 总量很低uncertainty 依然很高说明模型对“这是哪一类”有倾向、但对“我见没见过这种形态”没把握。这种样本应当被延迟。4.2 用验证集回溯标定阈值附可执行代码阈值标定我基本不在训练过程中做而是训练完成后在独立验证集上回溯搜索。核心思路是固定允许的延迟率上限找能让接受和拒绝决策精度最高的 α、β 组合。下面的代码可以直接跑。import numpy as np import torch from sklearn.metrics import precision_recall_fscore_support def three_way_decision( belief: np.ndarray, disbelief: np.ndarray, uncertainty: np.ndarray, alpha: float, beta: float, gamma: float, ) - np.ndarray: 根据阈值执行三支决策。 返回: 1 表示接受阳性 0 表示拒绝阴性 -1 表示延迟人工复核 decide_accept (belief alpha) (uncertainty gamma) decide_reject (disbelief beta) (uncertainty gamma) decisions np.where(decide_accept, 1, np.where(decide_reject, 0, -1)) return decisions def search_thresholds( belief_val: np.ndarray, disbelief_val: np.ndarray, uncertainty_val: np.ndarray, labels_val: np.ndarray, max_deferral_rate: float 0.3, ) - dict: 在验证集上网格搜索最优 alpha, beta, gamma。 目标: 在延迟率不超过 max_deferral_rate 的前提下最大化加权 F1。 alpha_range np.arange(0.60, 0.96, 0.05) beta_range np.arange(0.60, 0.96, 0.05) gamma_range np.arange(0.10, 0.51, 0.05) best_result None best_score -1.0 for alpha in alpha_range: for beta in beta_range: for gamma in gamma_range: decisions three_way_decision( belief_val, disbelief_val, uncertainty_val, alpha, beta, gamma ) deferral_rate float((decisions -1).mean()) if deferral_rate max_deferral_rate: continue # 只在接受和拒绝的样本上评估决策质量 mask decisions ! -1 if mask.sum() 50: continue precision, recall, f1, _ precision_recall_fscore_support( labels_val[mask], decisions[mask], averagebinary ) score (precision recall) / 2.0 if score best_score: best_score score best_result { alpha: alpha, beta: beta, gamma: gamma, deferral_rate: deferral_rate, precision: precision, recall: recall, f1: f1, } return best_result参数说明max_deferral_rate 0.3指最多允许 30% 的验证集样本进入延迟队列超过该比例的阈值组合直接丢弃。搜索步长的选择有讲究α、β 按 0.05 步长搜索已经够用步长过小容易过拟合验证集γ不确定性上限从 0.1 到 0.5 搜索因为二分类时 S e₁ e₂ 2uncerainty 在 0.5 以上说明证据总量几乎为零这种情况应该被延迟。这个网格搜索在万级样本的验证集上十几秒能跑完不需要更复杂的优化。4.3 临床场景阈值参考筛查、诊断、急诊三张表不同使用场景下接受、拒绝、延迟的比例权重完全不同。下面是我在类似影像项目里比较常用的初始参考区间可以作为起步值不建议直接照搬每个中心的数据都要重新标定。场景α接受β拒绝γ不确定性上限允许延迟率说明大规模体检初筛0.800.850.3030%偏重召回宁可多延迟也不漏阳性门诊辅助诊断0.900.900.2015%接受和拒绝都要有过硬证据ICU 急诊分诊0.950.900.105%延迟代价高靠高阈值过滤表格里 α 和 β 可以同时大于 0.9因为中间地带由 γ 兜底如果两类证据都不足uncertainty 会随之升高不满足 γ 的限制样本落到延迟。三支决策在这里的工程价值就体现出来了——网络不需要在样本上做“非黑即白”的判断而可以把决策面交给人工。4.4 延迟率不是越低越好先看有效决策集的质量落地时最常见的错误是为了把延迟率压到极低把 γ 阈值调得过大或者 α、β 阈值调得过低结果是延迟样本变少但接受和拒绝的决策质量也一起下降了。我评估三支决策系统时有一个固定原则延迟样本上的“未决策质量”必须和接受样本的“决策质量”一起报告。具体来说除了常规的整体准确率、AUC我会额外看三个指标有效决策率(接受数 拒绝数) / 总样本数代表模型自主处理的比例。接受集合的精确率在模型自主接受的阳性样本中真实阳性占比。延迟集合的阳性率延迟队列里实际阳性的比例。如果这个比例很高说明模型把大量困难阳性样本推给了人工系统需要返回去增强模型或调整阈值。医学影像场景里延迟率高一点通常可以接受因为人工复核本来就是工作流的一部分真正不能接受的是延迟样本“不值得延迟”——全是简单阴性还要医生复核这会把医生惹毛系统也不会被采纳。5. 动态阈值技巧把延迟样本锁在预算内的不确定性分位数校准5.1 静态阈值在真实数据上为什么容易失效前面讨论的 α、β、γ 都是训练完成后固定下来的静态数值。真实影像数据环境会变设备的软件升级、CT 重建核变化、新批次数据的窗宽窗位漂移都会让模型输出的证据分布整体偏移。结果是部署时设定的 γ 值在运行三个月后让延迟率从 20% 涨到 45%人工复核队列爆掉系统被一线医生直接停用。5.2 动态校准的实现用验证集不确定性分位数定位门槛我常用的技巧是给 γ 加上一个“动态锚点”——把不确定性阈值从绝对值改成经验分位数。原理很简单维护目标延迟率比如 20%把当前窗口内延迟率超标的样本按 uncertainty 排序取第 80 百分位数作为下一阶段的 γ 值。import numpy as np def calibrate_gamma_by_quantile( uncertainty_recent: np.ndarray, target_deferral_rate: float 0.2, ) - float: 用近期样本的 uncertainty 经验分位数动态设定 gamma。 参数: uncertainty_recent: 最近一个统计窗口内的 uncertainty 数组 target_deferral_rate: 目标延迟率比如 0.2 表示希望延迟 20% 返回: 作为新 gamma 值的分位数阈值 q 1.0 - target_deferral_rate new_gamma float(np.quantile(uncertainty_recent, q)) return new_gamma这里的target_deferral_rate 0.2是业务方给出的预算必须由医生团队确认不是模型侧的调参。uncertainty_recent的统计窗口我一般用最近 1000 条实际预测样本在分布式环境下可以做成滑动窗口。这种校准方法价值在于把“模型说我有多不确定”转换成了“这个月我们希望延迟多少比例”后者的解释成本低得多和影像科排班、医生工时直接挂钩。5.3 两个维度配合使用再让延迟样本回流训练动态 γ 和 α、β 静态阈值组合使用时需要一个明确的优先级先按 belief/disbelief 判定接受或拒绝不满足再查 uncertainty 是否超过动态 γ。这里的逻辑是 α、β 管证据方向γ 管证据强度两类信息不同源不能合并成一个数值。提示如果统计窗口内连续三次校准后 γ 下降了 50% 以上说明数据分布确实漂移了优先排查医院设备参数变更或数据预处理管线改动而不是继续调阈值。当延迟样本经过医生人工复核、得到确定标签后这套系统还带来一个额外收益延迟样本本身就是高质量的训练数据增量。我会按周把复核完的延迟样本回流到训练集用 ED L损失函数做一次增量微调Fine-tuning学习率降到正常训练的三分之一并且只更新证据头而不动编码器。经过几轮这样的循环模型对“自己曾经不确定的形态”逐渐形成稳定证据延迟率会自然下降人工复核负担随之减轻形成决策闭环。这条路径比单纯调参健康得多也是基于证据深度神经网络的医学影像三支决策相对传统单模型方案的最核心实践价值。本文还有配套的精品资源点击获取