object detection API训练参数适应自建数据集之调整image_resizer{}输入图像尺寸大小及问题解决

背景

研究项目中需要对SSD_MobilNet_v2模型训练的自己的数据集用来做目标检测,方便后期将实时检测模型迁移到Android手机中,前期的几次训练训练效果一直不好,精度和损失结果都很差,想到可能是原始采集的图像分辨率比较高,3680* 2760,但ssd-mobilenet模型中输入图像的分辨率统一被修改为300* 300,配置文件中默认设定image_resizer{}参数为fixed_shape_resizer,300*300,如下所示

image_resizer {
  fixed_shape_resizer {
	heidht: 300
	width: 300
  }
}

所以无论输入的图像尺寸是多少都会被resize成300* 300,高分辨率图像在此过程中信息丢失严重,为了改变这种傻瓜式的输入模式,因此想要修改image_resiezer{ }的参数。以下将这一问题的实现过程写在这里,一方面提高对object detection模型参数的理解,另一方面作为学习笔记,方便以后查看。

问题

在训练过程中原始数据纵横比由于比较大,1200300,因此想要修改模型输入尺寸,将原数据1200300作为训练输入而不是将输入后再被resize成300*300。刚开始查看修改image_resizer的源码,希望找到一些解决办法,参考源码总结如下:
object detection文件夹下的子文件夹proto是模型参数可配置数值声明文件的合集,找到image_resizer_pb.py和image_resizer.proto文件,image_resizer_pb.py是由后者编译生成的,编译生成过程在前期完成,这里不再详述,读者请自行百度,goodle解决。在image_resizer.proto中声明了image_resizer的四个参数,KeepAspectRatioResizer keep_aspect_ratio_resizer,FixedShapeResizer fixed_shape_resizer,IdentityResizer identity_resizer,ConditionalShapeResizer conditional_shape_resizer。

message ImageResizer {
  oneof image_resizer_oneof {
	KeepAspectRatioResizer keep_aspect_ratio_resizer = 1;
	FixedShapeResizer fixed_shape_resizer = 2;
	IdentityResizer identity_resizer = 3;
	ConditionalShapeResizer conditional_shape_resizer = 4;
  }
}

KeepAspectRatioResizer

keep_aspect_ratio_resizer保持纵横比输入,需要声明min_diemion 和max_diemion,文件中该参数分别默认设置为600,1024。

image_resizer {
  keep_aspect_ratio_resizer {
    min_dimension: 600
    max_dimension: 1024
  }
}`

随便输入一个图片,那么它会调整最小的维数为600,最大的维数是1024。如果你输入为100100,它会调整到600600,输入为20002000,会调整为10241024,输入为8001000会调整到600750,输入的图像为1200900的像素的图像,经过keep_aspect_astio_resizer后的图像尺寸变为1024768。既保证输入图片的纵横比不变。

FixedShapeResizer

fixde_shape_resizer固定图像尺寸,一旦设定height和width参数,无论输入图片的原始尺寸是多少,在输入网络训练前都会被resizer处理成(height, width, channels)的输入尺寸。有时可根据自己原始尺寸大小调节image_resizer的参数,来适应自己的图像输入。我的图像尺寸是1200*300大小的,在配置文件中直接修改height和width为1200,300。

IdentityResizer

在image_resizer.proto文件中并没有具体的使用和参数配置描述,暂时不在考虑使用的范围。

ConditionalShapeResizer

conditional_shape_resizer需要设定两个参数,condition和size_threashold,condition可设为’GREATER’或者’SMALLER’。size_thresghold默认设置为300,也可根据自己图像数据集的尺寸设定。当condition设为’GREATER’,如果图像的尺寸大于300则会对图像尺寸resize处理至300,并且保持图像的纵横比不变;同理当condition设为‘SMALLER’时,小于300的图像也会被resize为300,保持图像的纵横比不变。

报错

在参考源码后,尝试两种修改image_resizer{}的参数配置:

keep_aspect_ratio_resizer

直接修改min_dimension和max_dimension的数值为我的原始数据的图像尺寸

image_resizer {
  keep_aspect_ratio_resizer {
    min_dimension: 300
    max_dimension: 1200
  }
}`

报错如下:

tensorflow.python.framework.errors_impl.InvalidArgumentError: 2 root error(s) found.
  (0) Invalid argument: Cannot add tensor to the batch: number of elements does not match. Shapes are: [tensor]: [338,300,3], [batch]: [300,1200,3]
	 [[node IteratorGetNext (defined at /home/lzy/anaconda3/envs/ssdMobileNet/lib/python3.6/site-packages/tensorflow_core/python/framework/ops.py:1748) ]]
	 [[IteratorGetNext/_5635]]
  (1) Invalid argument: Cannot add tensor to the batch: number of elements does not match. Shapes are: [tensor]: [338,300,3], [batch]: [300,1200,3]
	 [[node IteratorGetNext (defined at /home/lzy/anaconda3/envs/ssdMobileNet/lib/python3.6/site-packages/tensorflow_core/python/framework/ops.py:1748) ]]

一开始搞不清楚是怎么回事,百度和google了一下,也没发现好的解决办法,于是尝试了另外下面一种方式,来设置image_resizer的参数

fixed_shape_resizer
image_resizer {
  fixed_shape_resizer {
	heidht: 300
	width: 1200
  }
}

报错如下:

tensorflow.python.framework.errors_impl.ResourceExhaustedError: 2 root error(s) found.
  (0) Resource exhausted: OOM when allocating tensor with shape[64,96,300,450] and type float on /job:localhost/replica:0/task:0/device:GPU:0 by allocator GPU_0_bfc
	 [[{{node FeatureExtractor/MobilenetV2/expanded_conv_1/expand/BatchNorm/FusedBatchNormV3}}]]
Hint: If you want to see a list of allocated tensors when OOM happens, add report_tensor_allocations_upon_oom to RunOptions for current allocation info.

	 [[control_dependency/_9527]]
Hint: If you want to see a list of allocated tensors when OOM happens, add report_tensor_allocations_upon_oom to RunOptions for current allocation info.

  (1) Resource exhausted: OOM when allocating tensor with shape[64,96,300,450] and type float on /job:localhost/replica:0/task:0/device:GPU:0 by allocator GPU_0_bfc
	 [[{{node FeatureExtractor/MobilenetV2/expanded_conv_1/expand/BatchNorm/FusedBatchNormV3}}]]
Hint: If you want to see a list of allocated tensors when OOM happens, add report_tensor_allocations_upon_oom to RunOptions for current allocation info.

仍然报错,略思考了一下还是不知道该怎么板办,百度后发现可能是batch_size参数设的过大导致GPU运算能力不足导致的,由于ssd模型的默认输入是300300的,总像素数是90000,batch_size设为24,但是当输入尺寸修改为1200300一张图像的总像素数扩大了四倍,GPU的计算量大于4倍,当运行不动时就会出现这样的错误,因此调小batch_size的大小就能顺利解决这个问题。回过头来再尝采用降低batch_size来解决采用keep_aspect-ration_resizer参数出现的报错,顺利解决。
在解决这个问题的过程中发现采用keep_aspect_ratio_resizer比采用fixed_shape_resizer的方式的运算量更大。

参考

参考博客