【问题标题】:TensorFlow - keypoint detection yields a heatmap of zerosTensorFlow - 关键点检测产生零热图
【发布时间】:2018-05-18 16:13:02
【问题描述】:

我正在使用基于检测的 CNN 进行手部姿势估计(在单手的深度图像中查找手部关节)。我的计划是首先使用 FCN 找到所有 16 个关键点的 2D 坐标。主干是 ResNet-50-FPN,计算图可见here。 res2a~res5c的结构如图here

当我使用 ICVL 手部姿势数据集训练此模型时,输出特征图收敛为所有像素值几乎为零的全黑图像。基本事实是深度图和热图,例如this。如果我在最后一个卷积层之后添加一个 sigmoid 激活函数(如图所示),输出热图将类似于白噪声。反正检测 FCN 完全没用,而 loss 根本不会下降。

我的 CNN 模型可以用下面的代码简单演示一下:

heat_chain = TensorChain(image_tensor) \
            .convolution_layer_2d(3, 16, 1, 'conv1') \
            .batch_normalization() \
            .relu('relu1') \
            .max_pooling_layer_2d(2, 'pool1') \
            .bottleneck_2d(64, 256, 'res2a') \
            .bottleneck_2d(64, 256, 'res2b') \
            .bottleneck_2d(64, 256, 'res2c') \
            .branch_identity_mapping() \
            .bottleneck_2d(128, 512, 'res3a', stride=2) \
            .bottleneck_2d(128, 512, 'res3b') \
            .bottleneck_2d(128, 512, 'res3c') \
            .bottleneck_2d(128, 512, 'res3d') \
            .branch_identity_mapping() \
            .bottleneck_2d(256, 1024, 'res4a', stride=2) \
            .bottleneck_2d(256, 1024, 'res4b') \
            .bottleneck_2d(256, 1024, 'res4c') \
            .bottleneck_2d(256, 1024, 'res4d') \
            .bottleneck_2d(256, 1024, 'res4e') \
            .bottleneck_2d(256, 1024, 'res4f') \
            .branch_identity_mapping() \
            .bottleneck_2d(512, 2048, 'res5a', stride=2) \
            .bottleneck_2d(512, 2048, 'res5b') \
            .bottleneck_2d(512, 2048, 'res5c') \
            .upsampling_block_2d(2, [-1, 30, 40, 512], 'upsample1') \
            .merge_identity_mapping_2d('merge1') \
            .upsampling_block_2d(2, [-1, 60, 80, 256], 'upsample2') \
            .merge_identity_mapping_2d('merge2') \
            .upsampling_block_2d(2, [-1, 120, 160, 64], 'upsample3') \
            .merge_identity_mapping_2d('merge3') \
            .upsampling_block_2d(2, [-1, 240, 320, 16], 'upsample4') \
            .convolution_layer_2d(3, 16, 1, 'conv2') \
            .convolution_layer_2d(3, 16, 1, 'conv3')
heatmaps = tf.identity(heat_chain.output_tensor, name='heatmaps')
heat_loss = tf.reduce_mean(
        tf.reduce_sum(tf.pow(heatmaps - heat_ground_truth, 2), axis=[1, 2, 3]), name='heat_loss')

其中 branch_identity_mapping() 将最后一个张量推入堆栈,merge_identity_mapping_2d() 弹出存储的张量并将其添加到当前张量(也可以与 1x1 卷积层的尺寸匹配)。

我完全不知道哪里出了问题。我的 ResNet-50-FPN 实现是否不正确,或者缺少一些重要的东西?

【问题讨论】:

    标签: tensorflow feature-detection pose-estimation keypoint


    【解决方案1】:

    您也可以上传您的培训代码吗?

    另外,ground truth 热图的形状是否为 (batch, height, width, 16),并且每个通道都是围绕关键点坐标的高斯峰?如果是这样,那么这是一个姿势估计问题。

    现在,请尝试以下 2 条建议。

    1. 在没有任何正则化和图像增强的情况下,在 1 张训练图像上试用该模型。然后应用不同规模的学习率。看看损失是否在减少,训练图像的预测是否与地面实况热图相似。
    2. 你的损失函数看起来不错,虽然我会使用: tf.reduce_sum(tf.square(heatmaps - heat_ground_truth, 2) , name='heat_loss')

    如果这些都没有帮助,我建议尝试一些姿势估计方法,因为 FPN 更像是一种对象检测和语义分割方法。 Convolutional Pose Machines 可能是一篇不错的论文。

    Convolutional Pose Machines 使用缩放的热图作为地面实况和网络输出。在主干 CNN 之后,论文中的 VGG,但我认为 res-net 也可以。例如经过 16 步池化后,热图的形状为 (batch, height/16, width/16, 16)。然后使用相同的损失函数。

    【讨论】:

      【解决方案2】:

      很抱歉复活了一个旧线程,但我遇到了几乎相同的问题。

      除了在我的情况下,我采用的结构几乎与 OpenPose 项目使用的结构相同(即 VGG 加上几个分支阶段),但阶段更少,以深度图像作为输入只有三个关键点(对于我的项目,我只需要双手和脸)。

      深度图像是输入输出是按比例缩小的热图(1, h/8, w/8, 3)-用高斯峰代替关键点堆叠(看起来有点像这样: )。

      损失的计算与上面的帖子相同,只是 GT-heatmap 和预测的 heatmap 之间存在差异。

      是的,在训练期间,几乎在前 2-3 个 epoch 之后,我可以看到输出只是一个充满零的空图像(可能是 [0;0] 位置的一个小峰值)并保持不变永远的方式(我只对大约 1500 个 epoch 有足够的耐心)。

      顺便说一句,我正在使用 Keras 进行训练。

      【讨论】:

      • 我参考了YOLO的loss定义,改变了自己的判断标准。见i.stack.imgur.com/R3bUQ.png。高斯峰太难学习,所以我只留下了一个值为 1 的像素。关于热图(或置信度图)有两个术语:a)单个像素的置信度损失,如圆圈中的第一项表示, 和 b) 没有目标的区域的置信度损失(例如,当前 gt 图像中值低于 0.1 的像素)。术语 a) 鼓励模型学习寻找目标,而 b) 限制它寻找任何不相关的东西。
      猜你喜欢
      • 2012-09-06
      • 1970-01-01
      • 2020-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-22
      • 1970-01-01
      • 2012-11-14
      相关资源
      最近更新 更多