图像分割涨点技巧!从39个Kaggle竞赛中总结出的分割Tips和Tricks
从数据预处理、增强、模型设计到损失函数、调参技巧!作者参加了39个Kaggle比赛,总结了非常多的技巧和经验,现在全部分享给大家。 参考文献:
Image Segmentation: Tips and Tricks from 39 Kaggle Competitions(这个应该是最早的,最新更新于2022年7月21日)
计算机视觉Daily-微信公众号
CVer计算机视觉-知乎
作者在kaggle上参加的比赛包括:
- Data Science Bowl 2017 – $1,000,000
- Intel & MobileODT Cervical Cancer Screening – $100,000
- 2018 Data Science Bowl – $100,000
- Airbus Ship Detection Challenge – $60,000
- Planet: Understanding the Amazon from Space – $60,000
- APTOS 2019 Blindness Detection – $50,000
- Human Protein Atlas Image Classification – $37,000
- SIIM-ACR Pneumothorax Segmentation – $30,000
- Inclusive Images Challenge – $25,000
比赛含金量还是十分充足的,可见作者分享的技巧也非常有实用价值。39点技巧可分为11大类,包括
(一)使用外部数据
(二) 数据探索和直觉
- 使用0.5的阈值对3D分割进行聚类
- 确认在训练集和测试集的标签分布上有没有不一样的地方
(三) 预处理
- 使用DoG(Difference of Gaussian)方法进行blob检测,使用skimage中的方法。
import skimage
img_dog = skimage.feature.blob_dog(image, min_sigma=1, max_sigma=50, sigma_ratio=1.6, threshold=2.0, overlap=0.5, *, exclude_border=False)
img_doh = skimage.feature.blob_doh(image, min_sigma=1, max_sigma=30, num_sigma=10, threshold=0.01, overlap=0.5, log_scale=False)
img_log = skimage.feature.blob_log(image, min_sigma=1, max_sigma=50, num_sigma=10, threshold=0.2, overlap=0.5, log_scale=False, *, exclude_border=False)API参考:
skimage.feature.blob_dog
skimage.feature.blob_doh
skimage.feature.blob_log
- 使用基于patch的输入进行训练,为了减少训练时间。
- 使用cuDF加载数据,不要用Pandas,因为读数据更快。
cuDF是一个Python GPU DataFrame库(基于Apache Arrow列式内存格式构建),用于加载、连接、聚合、过滤和以其他方式操作数据。cuDF还提供了一个类似pandas的API,数据工程师和数据科学家将很熟悉,因此他们可以使用它轻松地加速工作流程,而无需深入了解CUDA编程的细节。示例代码:
import cudf
df = cudf.DataFrame({'a': list(range(20)),
'b': list(reversed(range(20))),
'c': list(range(20))
})
df
- 确保所有的图像具有相同的方向。(这一点,很有意思,我也有体会,若使用transform进行图像随机旋转,那么在预测时将预测图片旋转后再投票集成的方式会提高一定分数)
- 在进行直方图均衡化的时候,使用对比度限制。
- 直方图均衡化(CLAHE)的时候使用kernel size为32×32
import cv2
out1 = cv2.equalizeHist(image)#图像均衡化
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))#限制对比度自适应直方图均衡化,第二条的建议是tileGridSize改为(32,32)
out2 = clahe.apply(image)API参考:
cv2.equalizeHist
cv2.createCLAHE
代码实现可看暗通道去雾经典算法复现以及paddlers.transforms.dehaze
import pydicom
import matplotlib.pyplot as plt
in_path = 'xxx.dcm'
ds = pydicom.read_file(in_path) #读取.dcm文件
img = ds.pixel_array # 提取图像信息
plt.imshow(img)
plt.show()
(四) 数据增强
API参考:
paddle.vision.transforms.rotate(img, angle, resample=False, expand=False, center=None, fill=0)
paddle.vision.transforms.RandomRotation(degrees, interpolation='nearest', expand=False, center=None, fill=0, keys=None)
paddleseg.transforms.transforms.RandomRotation(max_rotation=15, im_padding_value=(127.5, 127.5, 127.5), label_padding_value=255)
API参考:
paddle.vision.transforms.RandomVerticalFlip(prob=0.5, keys=None)
paddle.vision.transforms.RandomHorizontalFlip(prob=0.5, keys=None) paddleseg.transforms.transforms.RandomHorizontalFlip(prob=0.5) paddleseg.transforms.transforms.RandomVerticalFlip(prob=0.1)
retval = cv2.getAffineTransform(src, dst)#仿射变换API参考:
cv2.getAffineTransform
弹性形变代码参考
paddleseg.transforms.transforms.RandomAffine(size=(224, 224), translation_offset=0, max_rotation=15, min_scale_factor=0.75, max_scale_factor=1.25, im_padding_value=(128, 128, 128), label_padding_value=255)
def gasuss_noise(image, mean=0, var=0.001):
'''
添加高斯噪声
mean : 均值
var : 方差
'''
image = np.array(image/255, dtype=float)
noise = np.random.normal(mean, var ** 0.5, image.shape)
out = image + noise
if out.min() < 0:
low_clip = -1.
else:
low_clip = 0.
out = np.clip(out, low_clip, 1.0)
out = np.uint8(out*255)
#cv.imshow("gasuss", out)
return outAPI参考:
paddleseg.transforms.transforms.RandomNoise(prob=0.5, max_sigma=10.0)
paddle.vision.transforms.RandomRotation(degrees, interpolation='nearest', expand=False, center=None, fill=0, keys=None)
paddleseg.transforms.transforms.RandomRotation(max_rotation=15, im_padding_value=(127.5, 127.5, 127.5), label_padding_value=255)
API参考:
paddle.vision.transforms.Resize(size, interpolation='bilinear', keys=None)
paddle.vision.transforms.resize(img, size, interpolation='bilinear')
ppdet.data.transform.operators.RandomResize(target_size, keep_ratio=True, interp=cv2.INTER_LINEAR, random_size=True, random_interp=False)
API参考:
paddle.vision.transforms.adjust_brightness(img, brightness_factor)
paddle.vision.transforms.BrightnessTransform(value)
paddleseg.transforms.functional.brightness(im, brightness_lower, brightness_upper)
API参考:
paddle.vision.transforms.adjust_hue(img, hue_factor)
paddle.vision.transforms.HueTransform(value)
paddle.vision.transforms.SaturationTransform(value)
paddleseg.transforms.functional.hue(im, hue_lower, hue_upper)
paddleseg.transforms.functional.saturation(im, saturation_lower, saturation_upper) 然后这里添加对比度调整以及自动调整对比度、饱和度、色调的参考API:
paddle.vision.transforms.adjust_contrast(img, contrast_factor)
paddle.vision.transforms.ContrastTransform(value)
paddle.vision.transforms.ColorJitter(brightness=0, contrast=0, saturation=0, hue=0, keys=None)
contrast(im, contrast_lower, contrast_upper)
(五) 模型结构
没什么好说的,PaddleSeg里有大量的模型,可以自行选择,很方便
(六) 硬件设置
列举的硬件很乱,没什么条理,也不知道为什么要用这些硬件,也没多少人会为了一个比赛买新硬件吧~能随意购买硬件的土豪还会在乎比赛奖金吗?
- Use of the AWS GPU instance p2.xlarge with a NVIDIA K80 GPU
- Pascal Titan-X GPU
- Use of 8 TITAN X GPUs
- 6 GPUs: 21080Ti + 41080
- Server with 8×NVIDIA Tesla P40, 256 GB RAM and 28 CPU cores
- Intel Core i7 5930k, 2×1080, 64 GB of RAM, 2x512GB SSD, 3TB HDD
- GCP 1x P100, 8x CPU, 15 GB RAM, SSD or 2x P100, 16x CPU, 30 GB RAM
- NVIDIA Tesla P100 GPU with 16GB of RAM
- Intel Core i7 5930k, 2×1080, 64 GB of RAM, 2x512GB SSD, 3TB HDD
- 980Ti GPU, 2600k CPU, and 14GB RAM
(七) 损失函数
损失函数是很重要的,也是小白调节参数的最直接最简单的方式
API参考:
paddle.nn.functional.dice_loss(input, label, epsilon=1e-05)
paddleseg.models.losses.DiceLoss(weight=None, ignore_index=255, smooth=1.0)
API参考:
paddle.nn.BCELoss(weight=None, reduction='mean', name=None)
paddle.nn.functional.binary_cross_entropy(input, label, weight=None, reduction='mean', name=None)
paddleseg.models.losses.BCELoss(weight=None, pos_weight=None, ignore_index=255, edge_label=False)
paddle.nn.functional.binary_cross_entropy_with_logits(logit, label, weight=None, reduction='mean', pos_weight=None, name=None)
paddle.nn.BCEWithLogitsLoss(weight=None, reduction='mean', pos_weight=None, name=None)
- Lovasz 基于sub-modular损失的convex Lovasz扩展来直接优化平均IoU损失。
API参考:
paddleseg.models.losses.LovaszSoftmaxLoss(ignore_index=255, classes='present')
paddleseg.models.losses.LovaszHingeLoss(ignore_index=255)
API参考:
paddleseg.models.losses.FocalLoss(alpha=0.25, gamma=2.0, ignore_index=255)
paddleseg.models.losses.MultiClassFocalLoss(num_class, alpha=1.0, gamma=2.0, ignore_index=255)
API参考:
paddle.nn.SmoothL1Loss(reduction='mean', delta=1.0, name=None)
paddle.nn.functional.smooth_l1_loss(input, label, reduction='mean', delta=1.0, name=None)
API参考:
paddleseg.models.losses.MSELoss(reduction='mean', ignore_index=255)
paddle.nn.MSELoss(reduction='mean')
paddle.nn.functional.mse_loss(input, label, reduction='mean', name=None) (八) 训练技巧
(九) 评估和验证
API参考:
sklearn.model_selection.StratifiedKFold(n_splits=5, *, shuffle=False, random_state=None)
(十) 集成方法
(十一) 后处理
总结
这些Tricks有许多我也不太清楚具体操作,针对不同的比赛,Tricks也有不同的适配,大佬分享的很多都很有意义,自己也可以更好的学习。
我在AI Studio上获得至尊等级,点亮9个徽章,来互关呀~ https://aistudio.baidu.com/aistudio/personalcenter/thirdview/71231
请点击此处查看本环境基本用法. Please click here for more detailed instructions.
此文章为搬运 原项目链接
原文地址:https://zhuanlan.zhihu.com/p/585846244 |