模型评估中目标检测模型的目标框清晰度敏感度分析以及相关的解决方法
一、 问题描述
在目标检测任务中,不同数据集的目标框的清晰度可能会有差异,目标框清晰度的敏感度就是衡量这个差异的变量,而不同的目标框清晰度的数值对模型训练以及推理都会有影响。
图1 目标框清晰度举例,左图是原始图,右图是其中一个目标框的清晰度发生了变化
二、解决方法
在深度学习任务中,Dropout是一种被广泛使用的正则化技术,这种技术存在的缺点就是随机的丢弃掉特征层的某一个单元,使得相邻特征单元共享的语义信息也会一起丢弃掉,DropBlock改进了上述问题,即可以按照特征块来进行丢弃,对深度学习网络进行正则化处理。DropBlock 是类似Dropout 的简单方法。二者的主要区别在于DropBlock丢弃层特征图的相邻区域,而不是丢弃单独的随机单元。 具体详细介绍参见DropBlock论文
DropBlock模块主要有2个参数,block_size,γ。
block_size:表示dropout的方块的大小(长,宽),当block_size=1,DropBlock 退化为传统的dropout,正常可以取3,5,7
γ:表示drop过程中的概率,也就是伯努利函数的概率
Dropout(对应b图)和DropBlock(对应c图)的对比
图2 Dropout和Dropblock原理对比图,其中,b图表示Dropout,c图表示DropBlock
tf版的官方实现方式如下:
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之前,对目标框的清晰度敏感度分析如下所示:
图3 使用DropBlock之前,检测模型对目标框亮度敏感度分析
使用DropBlock之后,对目标框的清晰度敏感度进行分析,如下所示,可以看到,目标框清晰度敏感度从原来的0.0718降低到0.0204。
图4 使用DropBlock之后,检测模型对目标框亮度敏感度分析
可以看到,使用DropBlock之后,目标框的清晰度敏感度得到了比较大的改善
四、用户建议
在模型推理结果中,如果检测出来的类别对于目标框清晰度的敏感程度比较大,推荐在训练的时候,使用DropBlock进行模型优化和加强。
- 点赞
- 收藏
- 关注作者
评论(0)