TensorFlow - 关键点检测产生零的热图

问题描述 投票:2回答:2

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

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

我的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
2个回答
1
投票

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

此外,地面实况热图的形状是(批次,高度,宽度,16),每个通道是关键点坐标周围的高斯峰吗?如果是这样,则是姿势估计问题。

现在,尝试这两个建议开始。

  1. 在1个训练图像上尝试该模型,无需任何正则化和图像增强。然后应用不同规模的学习率。查看损失是否在减少,并且训练图像的预测与地面实况热图类似。
  2. 你的损失功能看起来不错,虽然我只会使用:tf.reduce_sum(tf.square(heatmaps - heat_ground_truth, 2) , name='heat_loss')

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

卷积姿态机器使用缩放的热图作为地面实况和网络输出。主干CNN之后,论文中的VGG,但我认为res-net也有效。例如经过16次汇集后,热图的形状为(批量,高度/ 16,宽度/ 16,16)。然后使用相同的损失函数。


0
投票

很抱歉复活旧线程,但我有同样的问题。

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

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

损失的计算方法与上面的帖子相同,但GT-heatmap和预测的热图之间存在差异。

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

我顺便使用Keras进行训练。

© www.soinside.com 2019 - 2024. All rights reserved.