文档首页 > > AI工程师用户指南> 管理模型> 评估和诊断模型> 模型评估的优化建议>

物体检测模型的目标框亮度敏感度分析以及相关的解决方法

物体检测模型的目标框亮度敏感度分析以及相关的解决方法

分享
更新时间:2021/06/04 GMT+08:00

问题描述

在目标检测任务中,不同数据集的目标框亮度可能会有差异,目标框亮度敏感度就是衡量这个差异的变量,而不同目标框亮度的数值对模型训练以及推理都会有影响。下图表示的就是同一个图片中,目标框内部标签的亮度值不一样。

图1 目标框亮度不均匀场景

解决方法

在深度学习任务中,dropout是一种被广泛使用的正则化技术,这种技术存在的缺点就是随机的丢弃掉特征层的某一个单元,使得相邻特征单元共享的语义信息也会一起丢弃掉,DropBlock改进了上述问题,即可以按照特征块来进行丢弃,对深度学习网络进行正则化处理。DropBlock 是类似dropout 的简单方法。二者的主要区别在于DropBlock丢弃层特征图的相邻区域,而不是丢弃单独的随机单元。详细介绍参见DropBlock论文

DropBlock模块主要有2个参数:block_size、γ

  • block_size:表示dropout的方块的大小(长,宽),当block_size=1,DropBlock退化为传统的dropout,正常可以取3、5、7。
  • γ:表示drop过程中的概率,也就是伯努利函数的概率。

Dropout和Dropblock的对比。其中,b图表示Dropout,c图表示DropBlock。

图2 Dropout和Dropblock原理对比图

TensorFlow版的官方实现方式如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
class Dropblock(object):
  """DropBlock: a regularization method for convolutional neural networks.
    DropBlock is a form of structured dropout, where units in a contiguous
    region of a feature map are dropped together. DropBlock works better than
    dropout on convolutional layers due to the fact that activation units in
    convolutional layers are spatially correlated.
    See https://arxiv.org/pdf/1810.12890.pdf for details.
  """

  def __init__(self,
               dropblock_keep_prob=None,
               dropblock_size=None,
               data_format='channels_last'):
    self._dropblock_keep_prob = dropblock_keep_prob
    self._dropblock_size = dropblock_size
    self._data_format = data_format

  def __call__(self, net, is_training=False):
    """Builds Dropblock layer.
    Args:
      net: `Tensor` input tensor.
      is_training: `bool` if True, the model is in training mode.
    Returns:
      A version of input tensor with DropBlock applied.
    """
    if (not is_training or self._dropblock_keep_prob is None or
        self._dropblock_keep_prob == 1.0):
      return net

    logging.info('Applying DropBlock: dropblock_size %d,'
                 'net.shape %s', self._dropblock_size, net.shape)

    if self._data_format == 'channels_last':
      _, height, width, _ = net.get_shape().as_list()
    else:
      _, _, height, width = net.get_shape().as_list()

    total_size = width * height
    dropblock_size = min(self._dropblock_size, min(width, height))
    # Seed_drop_rate is the gamma parameter of DropBlcok.
    seed_drop_rate = (
        1.0 - self._dropblock_keep_prob) * total_size / dropblock_size**2 / (
            (width - self._dropblock_size + 1) *
            (height - self._dropblock_size + 1))

    # Forces the block to be inside the feature map.
    w_i, h_i = tf.meshgrid(tf.range(width), tf.range(height))
    valid_block = tf.logical_and(
        tf.logical_and(w_i >= int(dropblock_size // 2),
                       w_i < width - (dropblock_size - 1) // 2),
        tf.logical_and(h_i >= int(dropblock_size // 2),
                       h_i < width - (dropblock_size - 1) // 2))

    if self._data_format == 'channels_last':
      valid_block = tf.reshape(valid_block, [1, height, width, 1])
    else:
      valid_block = tf.reshape(valid_block, [1, 1, height, width])

    randnoise = tf.random_uniform(net.shape, dtype=tf.float32)
    valid_block = tf.cast(valid_block, dtype=tf.float32)
    seed_keep_rate = tf.cast(1 - seed_drop_rate, dtype=tf.float32)
    block_pattern = (1 - valid_block + seed_keep_rate + randnoise) >= 1
    block_pattern = tf.cast(block_pattern, dtype=tf.float32)

    if self._data_format == 'channels_last':
      ksize = [1, self._dropblock_size, self._dropblock_size, 1]
    else:
      ksize = [1, 1, self._dropblock_size, self._dropblock_size]
    block_pattern = -tf.nn.max_pool(
        -block_pattern,
        ksize=ksize,
        strides=[1, 1, 1, 1],
        padding='SAME',
        data_format='NHWC' if self._data_format == 'channels_last' else 'NCHW')

    percent_ones = tf.cast(tf.reduce_sum(block_pattern), tf.float32) / tf.cast(
        tf.size(block_pattern), tf.float32)

    net = net / tf.cast(percent_ones, net.dtype) * tf.cast(
        block_pattern, net.dtype)
    return net

实验验证

在开源数据集Canine Coccidiosis Parasite上面进行实验,该数据集只有一个类别,使用DropBlock之前,模型对目标框亮度敏感度如表1所示。

表1 目标框亮度敏感度分析

特征值分布

coccidia

0% - 20%

0.8065

20% - 40%

0.871

40% - 60%

0.9355

60% - 80%

0.8065

80% - 100%

0.9677

标准差

0.0658

使用DropBlock之后,模型对目标框亮度敏感度的结果如表2所示,可以看到,使用DropBlock之后,类别的目标框亮度敏感度从原来的0.0658降低到0.0204,在模型评估阶段可以有效降低检测模型对目标框的亮度敏感度。

表2 目标框亮度敏感度分析

特征值分布

coccidia

0% - 20%

0.9355

20% - 40%

0.9677

40% - 60%

0.9677

60% - 80%

0.9677

80% - 100%

1

标准差

0.0204

用户建议

在模型推理结果中,如果检测出来的类别对于目标框亮度的敏感程度比较大,推荐在训练时,使用DropBlock进行模型优化和加强。

分享:

    相关文档

    相关产品