在训练时可以通过数据增强来提升模型的泛化能力,那么在测试时也可以通过测试时增强来提升其精度(牺牲一定的速度),这种操作在比赛中是常见的。图像增强的方法有仿射变化(平移、缩放旋转,镜像等)和色彩变化(对比度、亮度、饱和度、色调、噪声)等,通过对测试数据进行图像增强,然后对多个运算结果进行软投票(按概率值累加)或硬投票(按照argmax分类结果累加),可以在一定程度上提示模型的性能。下面推荐一款应用于paddle框架的TTA框架, GitHub - AgentMaker/PaTTA: A test times augmentation toolkit based on paddle2.0.
支持分类模型,语义分割模型、关键点模型,安装命令为 pip install patta
1、支持的数据扩充方法
Patta所支持的原子扩充方法如表1所示
方法 | 参数 | 值 |
---|---|---|
HorizontalFlip | - | - |
VerticalFlip | - | - |
HorizontalShift | shifts | List[float] |
VerticalShift | shifts | List[float] |
Rotate90 | angles | List[0, 90, 180, 270] |
Scale | scales interpolation | List[float] "nearest"/"linear" |
Resize | sizes original_size interpolation | List[Tuple[int, int]] Tuple[int,int] "nearest"/"linear" |
Add | values | List[float] |
Multiply | factors | List[float] |
FiveCrops | crop_height crop_width | int int |
AdjustContrast | factors | List[float] |
AdjustBrightness | factors | List[float] |
AverageBlur | kernel_sizes | List[Union[Tuple[int, int], int]] |
GaussianBlur | kernel_sizes sigma | List[Union[Tuple[int, int], int]] Optional[Union[Tuple[float, float], float]] |
Sharpen | kernel_sizes | List[int] |
内置的组合扩充方法如下所示
- flip_transform (horizontal + vertical flips)
- hflip_transform (horizontal flip)
- d4_transform (flips + rotation 0, 90, 180, 270)
- multiscale_transform (scale transform, take scales as input parameter)
- five_crop_transform (corner crops + center crop)
- ten_crop_transform (five crops + five crops on horizontal flip)
内置的数据扩充方法可能无法满足需求,通过自定义组合可以实现更加复杂的数据扩充方法
# defined 2 * 2 * 3 * 3 = 36 augmentations !
transforms = tta.Compose(
[
tta.HorizontalFlip(),
tta.Rotate90(angles=[0, 180]),
tta.Scale(scales=[1, 2, 4]),
tta.Multiply(factors=[0.9, 1, 1.1]),
]
)
tta_model = tta.SegmentationTTAWrapper(model, transforms)
2、结果融合方法
内置的结果融合扩充方法如下所示
- mean
- gmean (geometric mean) #几何平均数,也就是等比中项目
- sum
- max
- min
- tsharpen (temperature sharpen with t=0.5)
3、基本用法
模型加载,通过作者对源码的分析,发现patta只支持加载通过jit保存的模型
import patta as tta
model = tta.load_model(path='output/model')
#-------这里为tta.load_model的实现方法-----
def load_model(path='output/model'):
model = paddle.jit.load(path=path)
return model
通过对模型的修饰,可以实现测试时对数据进增强
语义分割模型增强
tta_model = tta.SegmentationTTAWrapper(model, tta.aliases.d4_transform(), merge_mode='mean')
分类模型增强
tta_model = tta.ClassificationTTAWrapper(model, tta.aliases.five_crop_transform())
关键点模型增强
tta_model = tta.KeypointsTTAWrapper(model, tta.aliases.flip_transform(), scaled=True)
4、针对多输入多输出模型的用法
针对于多输入多输出模型无法通过对模型的修饰完成自动在测试时增强模型性能,只能是通过for循环在把数据输入模型前进行augment,然后在数据输出后进行deaugment,并把结果累加到一起,最后进行结果融合
# Example how to process ONE batch on images with TTA
# Here `image`/`mask` are 4D tensors (B, C, H, W), `label` is 2D tensor (B, N)
def test_one(augmented_image, another_input_data):
for transformer in transforms: # custom transforms or e.g. tta.aliases.d4_transform()
# augment image
augmented_image = transformer.augment_image(image)
# pass to model
model_output = model(augmented_image, another_input_data)
# reverse augmentation for mask and label
deaug_mask = transformer.deaugment_mask(model_output['mask'])
deaug_label = transformer.deaugment_label(model_output['label'])
# save results
labels.append(deaug_mask)
masks.append(deaug_label)
# reduce results as you want, e.g mean/max/min
label = mean(labels)
mask = mean(masks)
return label,mask