6.3.3. 校准数据准备¶
注解
如果本过程您需在示例文件夹内进行,那么您需要先执行文件夹中的 00_init.sh
脚本以获取对应的原始模型和数据集。
在进行模型转换时,校准阶段会需要20~100份的标定样本输入,每一份样本都是一个独立的数据文件。 为了确保转换后模型的精度效果,我们希望这些校准样本来自于您训练模型使用的训练集或验证集, 不要使用非常少见的异常样本,例如纯色图片、不含任何检测或分类目标的图片等。
转换配置文件中的 preprocess_on
参数,该参数启用和关闭状态下分别对应了两种不同的预处理样本要求。
有关参数的详细配置可参考 校准参数组 中的相关说明。
preprocess_on
关闭状态下,您需要把取自训练集/验证集的样本做与inference前一样的前处理,
处理完后的校准样本会与原始模型具备一样的数据类型( input_type_train
)、尺寸( input_shape
)和layout( input_layout_train
),
对于featuremap输入的模型,您可以通过 numpy.tofile
命令将数据保存为float32格式的二进制文件,
工具链校准时会基于 numpy.fromfile
命令进行读取。
例如,有一个使用ImageNet训练的用于分类的原始浮点模型,它只有一个输入节点,输入信息描述如下:
输入类型:
BGR
。输入layout:
NCHW
。输入尺寸:
1x3x224x224
。
使用验证集做Inference时的数据预处理步骤如下:
图像长宽等比scale,短边缩放到256。
center_crop
方法获取224x224大小图像。转换输入layout为模型所需的
NCHW
。转换色彩空间为模型所需的
BGR
。归一化处理。
依照 preprocess_on
关闭状态下的样本文件制作原则,
针对上述举例模型的样本处理代码如下(为避免过长代码篇幅,各种简单transformer实现代码未贴出,transformer使用方法可参考 图片处理transformer说明 ):
# 本示例使用skimage,如果是opencv会有所区别
# 需要您特别注意的是,transformers中并没有体现减mean和乘scale的处理
# mean和scale操作已经融合到了模型中,参考前文norm_type/mean_values/scale_values配置
import skimage
import skimage.io
import numpy as np
from horizon_tc_ui.data.transformer import (CenterCropTransformer,
HWC2CHWTransformer,
RGB2BGRTransformer,
ScaleTransformer,
ShortSideResizeTransformer)
def data_transformer():
transformers = [
# 长宽等比scale,短边缩放至256
ShortSideResizeTransformer(short_size=256),
# CenterCrop获取224x224图像
CenterCropTransformer(crop_size=224),
# skimage读取结果为NHWC排布,转换为模型需要的NCHW
HWC2CHWTransformer(),
# skimage读取结果通道顺序为RGB,转换为模型需要的BGR
RGB2BGRTransformer(),
# skimage读取数值范围为[0.0,1.0],调整为模型需要的数值范围
ScaleTransformer(scale_value=255)
]
return transformers
# src_image 标定集中的原图片
# dst_file 存放最终标定样本数据的文件名称
def convert_image(src_image, dst_file, transformers):
image = [skimage.img_as_float(
skimage.io.imread(src_image)).astype(np.float32)]
for trans in transformers:
image = trans(image)
# 模型指定的input_type_train BGR数值类型是UINT8
image = image[0].astype(np.uint8)
# 二进制存储标定样本到数据文件
image.tofile(dst_file)
if __name__ == '__main__':
# 此处表示原始标定图片集合,伪代码
src_images = ['ILSVRC2012_val_00000001.JPEG', ...]
# 此处表示最终标定文件名称(后缀名不限制),伪代码
# calibration_data_bgr_f32是您在配置文件中指定的cal_data_dir
dst_files = ['./calibration_data_bgr_f32/ILSVRC2012_val_00000001.bgr', ...]
transformers = data_transformer()
for src_image, dst_file in zip(src_images, dst_files):
convert_image(src_image, dst_file, transformers)
小技巧
preprocess_on
启用状态下,标定样本使用skimage支持读取的图片格式文件即可。
转换工具读取这些图片后,会将其缩放到模型输入节点要求的尺寸大小,以此结果作为校准的输入。
这样的操作会简单,但是对于量化的精度没有保障,因此我们强烈建议您使用关闭 preprocess_on
的方式。
注意
请注意,yaml文件中input_shape参数作用为指定原始浮点模型的输入数据尺寸。若为动态输入模型则可通过这个参数设置转换后的输入大小,而校准数据的shape大小应与input_shape保持一致。
例如:若原始浮点模型输入节点shape为?x3x224x224(“?”号代表占位符,即该模型第一维为动态输入),转换配置文件中设置input_shape: 8x3x224x224,则需要准备的每份校准数据大小为8x3x224x224。 (请知悉,此类输入shape第一维不等于1的模型,不支持通过input_batch参数修改模型batch信息。)