查看全课大纲(第 77 / 93 节)
  1. 1.计算机视觉概述
  2. 2.计算机视觉应用场景
  3. 3.困难与挑战
  4. 4.开源库介绍
  5. 5.图像显示与存储
  6. 6.CLAHE
  7. 7.腐蚀膨胀与开闭运算
  8. 8.滤波与边缘填充
  9. 9.各种滤波
  10. 10.图像金字塔
  11. 11.傅里叶变换
  12. 12.短时傅里叶变换与小波变换
  13. 13.颜色特征与颜色直方图
  14. 14.几何特征_边缘
  15. 15.几何特征-角点与斑点
  16. 16.局部特征-SIFT特征描述子
  17. 17.局部特征-SURF特征描述子
  18. 18.局部特征-ORB特征描述子
  19. 19.其他特征描述子
  20. 20.传统图像分割技术
  21. 21.GraphCut
  22. 22.GrabCut
  23. 23.人脸检测的传统方法
  24. 24.行人检测的传统方法HOG+SVM
  25. 25.行人检测DPM
  26. 26.人工神经网络的架构
  27. 27.目标函数与梯度下降
  28. 28.误差反向传播
  29. 29.可手算的神经网络
  30. 30.改进目标函数与克服梯度消散
  31. 31.神经网络之传统神经网络与深度网络的差异
  32. 32.各种梯度下降算法
  33. 33.如何选择合适的梯度下降算法
  34. 34.避免过适应
  35. 35.CNN的架构
  36. 36.CNN的误差反向传播_卷积层
  37. 37.CNN的误差反向传播_池化层
  38. 38.分类所用的数据集
  39. 39.Alexnet详解
  40. 40.VGG详解
  41. 41.GoogLeNet_v1
  42. 42.BatchNormalization
  43. 43.GoogLeNet_v3v4
  44. 44.ResNet
  45. 45.ResNeXt
  46. 46.CNN设计准则
  47. 47.图像检索与推土机距离
  48. 48.基于颜色相似性
  49. 49.基于形状相似性
  50. 50.基于纹理相似性
  51. 51.基于局部特征相似性
  52. 52.DL的二值哈希编码
  53. 53.高维空间中检索KDTree
  54. 54.高维空间中检索LSH
  55. 55.目标识别任务综述
  56. 56.RCNN
  57. 57.SPP-Net
  58. 58.Fast R-CNN
  59. 59.Faster R-CNN
  60. 60.R-CNN系列模型回顾
  61. 61.R-FCN的设计思路
  62. 62.R-FCN的实现
  63. 63.YOLOv1
  64. 64.YOLOv2_9000
  65. 65.YOLOv3
  66. 66.图像分割应用场景与数据集
  67. 67.上采样的实现方式
  68. 68.FCN网络架构的由来
  69. 69.FCN构建细节
  70. 70.DeepLabv1
  71. 71.CRF
  72. 72.DeepLabv2
  73. 73.DeepLabv3
  74. 74.特定的医学影像分割任务
  75. 75.U-Net
  76. 76.3D U-Net
  77. 77.V-Net
  78. 78.DenseNet
  79. 79.病理切片分析任务及数据集
  80. 80.病理切片分析
  81. 81.图说任务及其传统处理方法
  82. 82.深度语言模型与RNN
  83. 83.LSTM及其变种
  84. 84.NIC模型
  85. 85.SAT模型
  86. 86.图说的性能指标
  87. 87.判别模型与生成模型
  88. 88.KL散度与JS散度
  89. 89.VAE
  90. 90.GAN的基本原理
  91. 91.DCGAN与CGAN
  92. 92.Wasserstein GAN
  93. 93.SRGAN

V-Net

小象实战讲义 · 基于深度学习的计算机视觉

在前面的章节中,我们学习了用于2D图像分割的U-Net及其3D扩展版本3D U-Net。本节我们将介绍U-Net家族的另一个重要成员——V-Net。它同样是针对三维医学影像分割任务而设计,但在网络结构、激活函数和训练策略上做了多项改进。通过本节学习,你将掌握V-Net的核心思想,理解其如何通过引入残差连接和参数化激活函数来提升分割性能,并能够对比分析V-Net与3D U-Net的异同。

💡 核心导读

  • V-Net的定位:V-Net是U-Net的另一个3D版本,专门用于三维医学影像(如MRI、CT)的分割任务。
  • 核心改进:相对3D U-Net,V-Net最大的改动是在网络的每个阶段都引入了残差连接(Residual Connection),以加速模型收敛并提升特征重建质量。
  • 结构可视化:V-Net的结构图把通道维度竖起来画——编码器自上而下逐级下采样(空间尺寸减半)、通道数逐级翻倍,解码器再自下而上恢复,整体轮廓呈字母“V”,因而得名;这种画法直观地展示了三维卷积中通道维度的变化。
  • 训练细节:V-Net采用了基于Dice系数的损失函数、参数化ReLU(PReLU)激活函数以及精细调整的学习率衰减策略。

V-Net:U-Net家族的残差增强版

V-Net发表于2016年,与3D U-Net同年提出,两者都是在U-Net基础上针对三维医学影像的独立演进;V-Net论文的实验对象是前列腺MRI(PROMISE12数据集)这类体数据。正如讲师在视频中所说:“你如果是希望突出你的模型的一些特点的话,那你宁可给它改个名字。” V-Net并非一个革命性的新架构,其相对U-Net的核心改进点在于全面引入了残差学习机制。

与3D U-Net相比,V-Net的主要特点可以概括为:

  1. 基于3D卷积的三维图像分割(与3D U-Net思路一致)。
  2. 采用了基于Dice系数的目标函数。Dice本身并不新,三维Dice与二维形式也很接近,V-Net的贡献是把它用到三维体数据上;这种损失更适合前景(器官)与背景体素数量不平衡的场景。
  3. 使用了改进的数据增强方法。
  4. 最关键的是,在网络中加入了残差学习来提升收敛效率。

接下来,我们将深入剖析V-Net的网络结构,理解其“V”形图的含义以及各项改进的具体实现。

网络结构解析:从“U”到“V”

V-Net的整体架构延续了U-Net的编码器-解码器(收缩-扩展)路径设计,并保留了跨层跳跃连接以融合多尺度特征。然而,其结构图的外观从U形变成了V形,这并非本质改变,而是一种不同的可视化表达方式。

三维卷积的可视化挑战与“V”形的由来

在三维卷积中,数据有四个维度:[高度, 宽度, 深度, 通道](例如 [128, 128, 64, 1]:高 128、宽 128、沿切片方向 64 层)。如何在一张二维图纸上清晰表达这四个维度是一个挑战。

  • U-Net的可视化:通常将通道数这个维度“扁平化”处理,在横向上展示,因此编码器路径越走越“宽”(通道数增加),解码器路径越走越“窄”,整体呈U形。
  • V-Net的可视化:V-Net论文选择将通道数在纵向上进行堆叠展示。如下图所示(文字示意),编码器自上而下推进:Stage1 在 128×128×64 的体数据上只做卷积,把通道升到16、空间尺寸不变;此后每经过一次步长为2的下采样卷积,空间尺寸(长、宽、高)同时减半、通道数翻倍。图纸上代表特征图的小方块因此越摞越“厚”(纵向堆叠),解码器再从最窄处自下而上放大回原尺寸,上下两段合起来就形成一个清晰的V字形。
编码器路径(收缩):
输入: [128, 128, 64, 1]      (空间尺寸大,通道数为1)
Stage1 -> [128, 128, 64, 16] (空间尺寸不变,通道增至16)
Stage2 -> [64,  64,  32, 32] (尺寸减半,通道增至32)
Stage3 -> [32,  32,  16, 64] (尺寸再减半,通道增至64)
Stage4 -> [16,  16,   8, 128] (尺寸再减半,通道增至128)
Stage5 -> [8,    8,   4, 256] (尺寸最小,通道最多)

解码器路径(扩展):
... (通过2×2×2、步长为2的反卷积逐级上采样,尺寸翻倍、通道数减半,与编码器对称)

关于输入尺寸的说明:在示例中,输入尺寸为128x128x64,其中第三个维度(64)比前两个(128)小。讲师的理解是,这反映了医学影像数据的特性:横断面(长、宽)上像素密集、分辨率很高,而沿切片堆叠方向(深度,如Z轴)的采样分辨率有限,所以该维度只有前面的一半。

核心操作符号解读

V-Net结构图中使用了几种关键符号,对应着不同的网络操作:

  1. 卷积(⊗):代表卷积核为 5×5×5,步长(stride)为1的3D卷积。这是特征提取的主要操作。
  2. 下采样卷积:在每个Stage的末尾,使用卷积核为 2×2×2,步长为2的卷积。V-Net没有采用传统的最大池化(Max Pooling)进行下采样,而是直接使用步长大于1的卷积。这样做的好处是让下采样过程也包含可学习的参数。
  3. 反卷积(上采样):解码器用卷积核为 2×2×2、步长为2的反卷积,把每个输入体素投影到更大的区域,使空间尺寸翻倍,与编码器的下采样对称。
  4. 按元素相加(⊕):这是残差连接的核心操作。把Stage的输入直接加到该Stage卷积后的输出上,即在对应体素(voxel)位置上逐元素相加。
  5. 激活函数(▷):卷积后的小三角代表激活函数。V-Net没有使用标准的ReLU,而是使用了参数化ReLU(PReLU)。

残差连接:V-Net的灵魂

正如讲师强调的:“它跟那个3D U-Net的最大的区别还不如说是这个地方全都是加上了一种残差机制。” 残差连接是V-Net性能提升的关键。

V-Net的每个Stage由1~3个卷积层组成,Stage的输入会跳过这些卷积层、直接与它们的输出逐元素相加,即每个Stage都带一条残差连接。其基本思想借鉴了ResNet,可以表示为: 输出 = F(输入) + 输入 其中,F(输入)代表经过若干层卷积、激活函数等操作后的变换。这种短路连接(Shortcut Connection)使得网络可以更容易地学习恒等映射,有效缓解了深层网络中的梯度消失问题,从而加速了模型的收敛,并有助于重建更高质量的图像细节。

除了Stage内部的残差连接,V-Net也保留了U-Net风格的跨层跳跃连接(讲师称“越层连接”),把编码器路径中同尺度的高分辨率特征图送入解码器对应层参与融合,为图像重建保留细节。

关键技术细节

参数化ReLU(PReLU)

标准ReLU函数将所有负输入值置零:f(x) = max(0, x)。LeakyReLU对其进行了改进,给负值区域一个固定的微小斜率(如0.01):f(x) = max(αx, x), 其中α=0.01。

PReLU则更进一步,将这个斜率α也作为一个可学习的参数。在训练过程中,网络会通过反向传播自动学习每个通道上最适合的α值。这增加了模型的表达能力,使其能更灵活地拟合复杂的数据分布。

import numpy as np

# 模拟PReLU的前向传播
def prelu(x, alpha):
    """参数化ReLU前向计算。
    Args:
        x: 输入数据。
        alpha: 可学习的斜率参数,形状需能与x广播。
    Returns:
        激活后的输出。
    """
    return np.where(x > 0, x, alpha * x)

# 示例:假设我们有一个包含正负值的特征图,以及一个学习到的alpha值
feature_map = np.array([[-1.0, 0.5, -0.2],
                         [2.0, -0.8, 0.1]])
learned_alpha = 0.25  # 假设网络学习到的alpha值是0.25

activated = prelu(feature_map, learned_alpha)
print("原始特征图:")
print(feature_map)
print("\n应用PReLU(alpha=0.25)后:")
print(activated)
原始特征图:
[[-1.   0.5 -0.2]
 [ 2.  -0.8  0.1]]

应用PReLU(alpha=0.25)后:
[[-0.25  0.5  -0.05]
 [ 2.   -0.2   0.1 ]]

输出层与损失函数

V-Net网络的末尾是一个 1×1×1 的卷积层,后接一个Softmax激活函数。

  • 1×1×1卷积的作用是将通道数映射到目标类别数(例如,前景和背景两类)。
  • Softmax为每个体素(voxel,三维像素)计算属于各个类别的概率,最终输出一张与输入尺寸相同的概率图。
  • 对于二分类任务,通常设定一个阈值(如0.5)。概率大于阈值的体素被判定为前景(目标组织器官),否则为背景。

V-Net的损失函数采用了基于Dice系数的目标函数。Dice系数衡量的是预测分割区域与真实标注区域的重叠程度,其定义为: Dice = (2 * |A ∩ B|) / (|A| + |B|) 其中A是预测前景区域,B是真实前景区域。Dice系数的值在0到1之间,越大表示分割效果越好。训练时把它写成可微形式(用预测概率代替0/1掩码),并最小化 1 - Dice 作为损失。由于损失按重叠比例归一化,前景与背景体素数量悬殊时也不会被背景主导,因此特别适用于医学影像中前景(如肿瘤、器官)只占图像一小部分的不平衡场景。

训练策略

V-Net的训练采用了以下策略:

  • 优化器:使用带动量的随机梯度下降(SGD)。
  • 动量(Momentum):设置为0.99,有助于加速收敛并稳定训练过程。
  • 学习率(Learning Rate):初始学习率设置为一个非常小的值:0.0001。这是因为V-Net是一个参数量大、结构复杂的深层网络。讲师特别指出:“网络如果简单的话,那么学习率应该比较大。网络如果很复杂的话,你学习率务必要调的小一点。”
  • 学习率衰减:为了进一步精细调优,每进行25,000次迭代,学习率就下降一个数量级(例如从0.0001降到0.00001)。这种策略有助于模型在训练后期更好地收敛到局部最优解。

V-Net与3D U-Net对比

特性3D U-NetV-Net
核心架构标准的3D编码器-解码器,带跳跃连接同为3D编码器-解码器+跳跃连接,但每个Stage内部引入残差连接
下采样方式使用 2×2×2 最大池化使用步长为2的 2×2×2 卷积(卷积下采样)
激活函数通常使用ReLU使用参数化ReLU(PReLU)
损失函数交叉熵损失(softmax输出)基于Dice系数的损失(1 − Dice)
结构可视化呈U形(通道维度横向展开)呈V形(通道维度纵向堆叠)
主要贡献将U-Net扩展为3D版本,并支持稀疏标注训练系统地将残差学习引入3D医学分割,优化训练细节

总结来说,V-Net可以看作是U-Net结构与ResNet思想的一次成功结合。它没有改变U-Net解决医学影像分割问题的根本范式,而是通过引入训练技巧和模块化设计(残差连接、PReLU),提升了模型的训练效率和分割精度。论文在PROMISE12前列腺MRI数据集上报告的平均Dice系数为0.869,按讲师的说法,比之前的结果又进了一步。

📝 动手练一练

  1. 概念辨析:V-Net论文作者将其网络结构可视化后命名为“V-Net”,而之前的网络叫“U-Net”。这主要是因为两者在核心思想上有本质区别,还是仅仅因为可视化表达方式不同?请结合本节内容阐述你的理解。
👉 点击查看参考答案

参考答案: 这主要是可视化表达方式不同,而非核心思想有本质区别。

  • 核心思想一致:两者都基于编码器-解码器结构,都使用跨层跳跃连接来融合多尺度特征,以解决医学影像分割问题。V-Net的核心改进是引入了残差连接和PReLU等组件,但整体范式仍是U-Net开创的。
  • 可视化差异:U-Net的结构图通常将随着网络加深而增加的通道数在“横向”上展开,使得网络轮廓看起来像一个宽口的“U”。而V-Net的图示把通道数放到“纵向”堆叠:编码器自上而下空间尺寸逐级减半、通道逐级翻倍,解码器再自下而上放大,两段合起来就是一个“V”字。这种画法是为了更直观地展示3D卷积中通道维度的变化,尤其是当通道数变得非常多(如256)时。
  • 因此,名称的不同更多是为了形象化地突出论文中图示的特点,而不是宣告一个全新架构的诞生。
  1. 代码思考:以下是一段模拟残差块前向传播的代码。请分析,如果去掉残差连接(即直接 return out),在训练深度网络时可能会带来什么问题?
import numpy as np

def residual_block(x, weights, bias):
    """一个简化的残差块前向传播模拟。
    Args:
        x: 输入,形状假设为 (H, W, D, C)。
        weights: 卷积核权重,模拟用,此处简化为一个缩放因子。
        bias: 偏置,模拟用。
    Returns:
        残差块的输出。
    """
    # 模拟卷积层、批归一化、激活函数等操作 (这里用线性变换模拟)
    identity = x  # 保留输入作为恒等映射
    out = x * weights + bias  # 模拟F(x)变换
    out = out + identity      # 残差连接: F(x) + x
    return out

# 模拟输入和参数
input_data = np.ones((4, 4, 4, 16)) * 0.5  # 一个小的特征块
w = 0.1
b = 0.05

output_with_residual = residual_block(input_data, w, b)
print("带残差连接的输出(部分):")
print(output_with_residual[0, 0, 0, :5])  # 打印前5个通道的第一个体素

# 对比:去掉残差连接
output_without_residual = input_data * w + b
print("\n不带残差连接的输出(部分):")
print(output_without_residual[0, 0, 0, :5])
👉 点击查看参考答案
带残差连接的输出(部分):
[0.6 0.6 0.6 0.6 0.6]

不带残差连接的输出(部分):
[0.1 0.1 0.1 0.1 0.1]

问题分析: 如果去掉残差连接(out = out + identity),则输出变为 out = F(x)。在深度网络中,这可能导致:

  1. 梯度消失/爆炸:深层网络由许多这样的层堆叠而成。如果没有残差连接,梯度在反向传播时需要连续穿过所有层的变换(乘法)。当权重w较小时(如本例的0.1),连续相乘会导致梯度指数级减小(消失);当w较大时,则可能导致梯度爆炸。残差连接引入的加法操作,使得梯度多了一条“捷径”(可以直接流过恒等映射),有效缓解了这个问题。
  2. 难以学习恒等映射:对于某些层,最优的变换可能就是什么都不做(恒等映射)。没有残差连接时,这一层必须自己把 F(x) 学成 x,也就是权重逼近1、偏置逼近0;有了残差连接,只需让残差分支学成 F(x) = 0(权重和偏置都趋向0),后者显然更容易优化。
  3. 输出信号衰减:从模拟结果看,去掉残差后,输出值从0.6降到了0.1。在深层网络中,这种衰减会逐层累积,导致深层特征非常微弱,不利于后续层的学习和最终任务的预测。

本章小结

本节我们深入学习了V-Net,这是U-Net家族在三维医学影像分割领域的又一重要演进。V-Net的核心贡献在于将残差学习(ResNet)的思想系统性地融入到三维U-Net架构中,通过在每个Stage内部添加残差连接,显著改善了深层网络的训练稳定性,加速了收敛,并最终提升了分割精度。此外,其采用的参数化ReLU(PReLU)、基于Dice系数的损失函数以及精细的学习率调度策略,共同构成了一个高效、鲁棒的3D分割解决方案。

理解V-Net的关键在于认识到它并非一个完全独立的创新,而是对已有强大组件(U-Net, ResNet)的成功集成与优化。这种“站在巨人肩膀上”的演进模式,在深度学习领域非常普遍。

需要说明的是,V-Net与3D U-Net都发表于2016年,属于三维医学分割的早期代表工作:当时残差连接、PReLU、Dice损失都还是论文层面的新尝试,如今这些组件已成为三维分割模型的常规配置。学习本节,重点是把它们当作一套“可复用的设计语言”来理解,而不是把它当成当前最优方案。

📋 行动清单

  • 理清脉络:在笔记本上画出V-Net的结构示意图,并标注出残差连接、PReLU激活、卷积下采样等关键组件,理解数据从输入到输出的流动过程。
  • 对比分析:制作一个表格,清晰对比3D U-Net和V-Net在网络结构、下采样方式、激活函数、核心改进等方面的异同。
  • 代码实践:尝试使用现代深度学习框架(PyTorch,或 TensorFlow 2.x 的 Keras API),根据V-Net论文的描述,构建一个简化版的V-Net模型定义(仅结构,不训练),重点实现其残差块。

—— 小象教研组