TensorFlow 实战(八)(4)

简介: TensorFlow 实战(八)

TensorFlow 实战(八)(3)https://developer.aliyun.com/article/1522969

get_image_class_label()函数使用指定的参数并加载由 image_path 给出的图像。首先,我们将图像调整大小为 224×224 大小的图像。我们还在开始时添加了一个额外的维度来表示图像作为一个图像批次。然后,它执行特定的数值转换(即,逐元素除以 127.5 并减去 1)。这是用于训练 InceptionResNet v2 模型的特殊转换。然后,我们使用传递给函数的数据框和 class_indices 获取该类的类索引(即,整数)和人类可读的标签。最后,它返回转换后的图像、类索引和图像所属类的标签。

下一个清单显示了如何为图像计算 Grad-CAMs。我们将使用 10 个图像分别计算 Grad-CAMs。

清单 B.3 为 10 个图像计算 Grad-CAM

# Define a sample probe set to get Grad-CAM
image_fnames = [
    os.path.join('data','tiny-imagenet-200', 'val','images',f) \
    for f in [
        'val_9917.JPEG', 'val_9816.JPEG', 'val_9800.JPEG', 'val_9673.JPEG', 
➥ 'val_9470.JPEG',
        'val_4.JPEG', 'val_127.JPEG', 'val_120.JPEG', 'val_256.JPEG', 
➥ 'val_692.JPEG'
    ]
]
grad_info = {}
for fname in image_fnames:                                                      ❶
    img, cls, label = get_image_class_label(fname, val_df, class_indices, words)❷
    with tf.GradientTape() as tape:                                             ❸
        conv_output, preds = grad_model(img)                                    ❸
        loss = preds[:, cls]                                                    ❹
    grads = tape.gradient(loss, conv_output)                                    ❺
    weights = tf.reduce_mean(grads, axis=(1, 2), keepdims=True)                 ❻
    grads *= weights                                                            ❻
    grads = tf.reduce_sum(grads, axis=(0,3))                                    ❼
    grads = tf.nn.relu(grads)                                                   ❼
    grads /= tf.reduce_max(grads)                                               ❽
    grads = tf.cast(grads*255.0, 'uint8')                                       ❽
    grad_info[fname] = {'image': img, 'class': cls, 'label':label, 'gradcam': 
➥ grads}  

❶ 获取每个图像的标准化输入、类别(整数)和标签(字符串)。

❷ 在 GradientTape 环境中计算模型的输出。

❸ 这将使我们能够稍后访问在计算过程中出现的梯度。

❹ 我们只考虑输入图像的类索引对应的损失。

❺ 获取与最后一个卷积特征图相关的损失的梯度。

❻ 计算并应用权重。

❼ 将特征图折叠为单个通道,以获得最终的热图。

❽ 将值归一化为 0-255 的范围内。

❾ 将计算出的 GradCAMs 存储在字典中以便稍后可视化。

要计算一张图像的 Grad-CAM,我们遵循以下步骤。首先,我们获得给定图像路径的转换图像、类索引和标签。

接下来是此计算的最重要步骤!您知道,给定一张图像和一个标签,最终损失被计算为所有可用类别的类特定损失的总和。也就是说,如果您想象一个独热编码的标签和模型输出的概率向量,我们计算每个输出节点之间的损失。这里每个节点代表一个单独的类别。为了计算梯度映射,我们首先仅针对该图像的真实标签计算类特定损失的梯度,关于最后一个卷积层的输出。这给出了一个与最后一个卷积层的输出大小相同的张量。重要的是注意我们使用的典型损失和这里使用的损失之间的区别。通常,我们将所有类别的损失求和,而在 Grad-CAM 中,我们仅考虑与输入的真实类对应的特定节点的损失。

注意我们如何计算梯度。我们使用了一种称为 GradientTape 的东西(mng.bz/wo1Q)。这是 TensorFlow 中的一项创新技术。每当在 GradientTape 的上下文中计算某些东西时,它将记录所有这些计算的梯度。这意味着当我们在 GradientTape 的上下文中计算输出时,我们可以稍后访问该计算的梯度。

然后我们进行一些额外的转换。首先,我们计算输出特征图的每个通道的权重。这些权重简单地是该特征图的均值。然后将特征图的值乘以这些权重。然后我们对所有通道的输出进行求和。这意味着我们将得到一个宽度和高度都为一个通道的输出。这本质上是一个热图,其中高值表示在给定像素处更重要。为了将负值剪切为 0,然后在输出上应用 ReLU 激活。作为最终的归一化步骤,我们将所有值带到 0-255 的范围,以便我们可以将其作为热图叠加在实际图像上。然后只需使用 matplotlib 库绘制图像,并将我们生成的 Grad-CAM 输出叠加在图像上。如果您想查看此代码,请参阅 Ch07-Improving-CNNs-and-Explaining/7.3.Interpreting_CNNs_ Grad-CAM.ipynb 笔记本。最终输出将如图 B.1 所示。


图 B.1 几个探测图像的 Grad-CAM 输出可视化。图像中越红的区域,模型就越关注该图像的那部分。您可以看到我们的模型已经学会了理解一些复杂的场景,并分离出需要关注的模型。

B.2 图像分割:U-Net 模型

在第八章中,我们讨论了 DeepLab v3:一个图像分割模型。在本节中,我们将讨论另一个被称为 U-Net 的图像分割模型。它的架构与 DeepLab 模型不同,并且在实际中非常常用。因此,这是一个值得学习的模型。

B.2.1 理解和定义 U-Net 模型

U-Net 模型本质上是两个镜像反射的全卷积网络,充当编码器和解码器,还有一些额外的连接,将编码器的部分连接到解码器的部分。

U-Net 的背景

U-Net 是在论文“U-Net: Convolution Networks for Biomedical Image Segmentation”(arxiv.org/pdf/1505.04597.pdf)中被介绍的,其起源于生物医学图像分割。U-Net 的名称源自于网络的形状。它仍然是生物学/医学领域分割任务中常用的选择,并且已经被证明在更一般的任务中也能很好地工作。

首先,我们将看一下原始的 U-Net 模型,该模型在论文中被介绍。然后,我们稍微调整我们的讨论方向,使其更适合当前问题。原始模型使用的是一个 572 × 572 × 1 大小的图像(即灰度图像),并输出一个 392 × 392 × 2 大小的图像。该网络经过训练,可以识别/分割细胞边界。因此,输出中的两个通道表示像素是否属于细胞边界的二进制输出。

编码器由多个下采样模块组成,逐渐对输入进行下采样。一个下采样模块包括两个卷积层和一个最大池化层。具体来说,一个下采样模块包括:

  • 一个 3 × 3 卷积层(valid padding)× 2
  • 一个 2 × 2 最大池化层(除了最后一个下采样模块)

一系列这样的下采样层将大小为 572 × 572 × 1 的输入转换为大小为 28 × 28 × 1024 的输出。

接下来,解码器由多个上采样层组成。具体来说,每个解码器上采样模块包括:

  • 一个 2 × 2 转置卷积层
  • 一个 3 × 3 卷积层(valid padding)× 2

你可能已经想知道,什么是转置卷积层?转置卷积是反向计算卷积层中发生的计算得到的结果。转置卷积不是缩小输出的卷积运算(即使用步长),而是增加输出的大小(即上采样输入)。这也被称为分数步长,因为使用转置卷积时,增加步长会产生更大的输出。如图 B.2 所示。


图 B.2 标准卷积与转置卷积的对比。标准卷积的正向步长会导致输出更小,而转置卷积的正向步长会导致输出更大的图像。

最后,有跳跃连接将编码器的中间层连接到解码器的中间层。这是一个重要的架构设计,因为它为解码器提供了所需的空间/上下文信息,否则这些信息将会丢失。特别地,编码器的第 i^(th)级输出与解码器的第 n-i^(th)级输入连接起来(例如,第一级的输出[大小为 568 × 568 × 64]被连接到解码器的最后一级输入上 [大小为 392 × 392 × 64];图 B.3)。为了做到这一点,编码器的输出首先需要稍微裁剪一下,以匹配相应的解码器层的输出。


图 B.3 原始 U-Net 模型。浅色块代表编码器,深色块代表解码器。垂直数字表示给定位置的输出大小(高度和宽度),顶部的数字表示滤波器数量。

TensorFlow 实战(八)(5)https://developer.aliyun.com/article/1522973

相关文章
|
26天前
|
机器学习/深度学习 自然语言处理 TensorFlow
TensorFlow 实战(六)(2)
TensorFlow 实战(六)
24 0
|
13天前
|
机器学习/深度学习 TensorFlow API
TensorFlow与Keras实战:构建深度学习模型
本文探讨了TensorFlow和其高级API Keras在深度学习中的应用。TensorFlow是Google开发的高性能开源框架,支持分布式计算,而Keras以其用户友好和模块化设计简化了神经网络构建。通过一个手写数字识别的实战案例,展示了如何使用Keras加载MNIST数据集、构建CNN模型、训练及评估模型,并进行预测。案例详述了数据预处理、模型构建、训练过程和预测新图像的步骤,为读者提供TensorFlow和Keras的基础实践指导。
144 59
|
26天前
|
机器学习/深度学习 自然语言处理 TensorFlow
TensorFlow 实战(五)(5)
TensorFlow 实战(五)
19 1
|
26天前
|
自然语言处理 算法 TensorFlow
TensorFlow 实战(六)(3)
TensorFlow 实战(六)
21 0
|
26天前
|
机器学习/深度学习 数据可视化 TensorFlow
TensorFlow 实战(六)(1)
TensorFlow 实战(六)
25 0
|
26天前
|
存储 自然语言处理 TensorFlow
TensorFlow 实战(五)(4)
TensorFlow 实战(五)
21 0
|
26天前
|
TensorFlow API 算法框架/工具
TensorFlow 实战(八)(3)
TensorFlow 实战(八)
25 1
|
26天前
|
机器学习/深度学习 自然语言处理 TensorFlow
TensorFlow 实战(八)(5)
TensorFlow 实战(八)
25 0
|
26天前
|
并行计算 TensorFlow 算法框架/工具
TensorFlow 实战(八)(2)
TensorFlow 实战(八)
21 0
|
26天前
|
并行计算 Ubuntu TensorFlow
TensorFlow 实战(八)(1)
TensorFlow 实战(八)
22 0