CV-数据扩展
两个库OpenCV和albumentations
常见的数据扩增方法
数据扩增是一种有效的正则化方法,可以防止模型过拟合,在深度学习模型的训练过程中应用广泛。数据扩增的目的是增加数据集中样本的数据量,同时也可以有效增加样本的语义空间。
- 正则化(正则化是为了防止过拟合, 进而增强泛化能力。)
给需要训练的目标函数加上一些规则(限制),让他们不要自我膨胀,分为L0,L1,L2正则化
L0正则化的值是模型参数中非零参数的个数。
L1正则化表示各个参数绝对值之和。
L2正则化标识各个参数的平方的和的开方值。
不同的数据,拥有不同的数据扩增方法;
数据扩增方法需要考虑合理性,不要随意使用;
数据扩增方法需要与具体任何相结合,同时要考虑到标签的变化;
对于图像分类,数据扩增方法可以分为两类:
- 标签不变的数据扩增方法:数据变换之后图像类别不变(image classcifacation)
- 标签变化的数据扩增方法:数据变换之后图像类别变化 (image segmentation)
对语义分割,常规的数据扩增方法都会改变图像的标签。
如水平翻转、垂直翻转、旋转90%、旋转和随机裁剪,这些常见的数据扩增方法都会改变图像的标签,即会导致地标建筑物的像素发生改变。
opencv部分
cv2.flip(mask, 1)
cv2.flip(img, 0)
随机裁剪
x, y = np.random.randint(0, 256), np.random.randint(0, 256)
img[x:x+256, y:y+256]
mask[x:x+256, y:y+256]
albumentations
官方示例
与OpenCV相比albumentations具有以下优点:
- albumentations支持的操作更多,使用更加方便;
- albumentations可以与深度学习框架(Keras或Pytorch)配合使用;
- albumentations支持各种任务(图像分流)的数据扩增操作
albumentations可以对数据集进行逐像素的转换,如模糊、下采样、高斯造点、高斯模糊、动态模糊、RGB转换、随机雾化等;也可以进行空间转换(同时也会对目标进行转换),如裁剪、翻转、随机裁剪等。
import albumentations as A
# 水平翻转
augments = A.HorizontalFlip(p=1)(image=img, mask=mask)
img_aug, mask_aug = augments['image'], augments['mask']
# 随机裁剪
augments = A.RandomCrop(p=1, height=256, width=256)(image=img, mask=mask)
img_aug, mask_aug = augments['image'], augments['mask']
# 旋转
augments = A.ShiftScaleRotate(p=1)(image=img, mask=mask)
img_aug, mask_aug = augments['image'], augments['mask']
albumentations还可以组合多个数据扩增操作得到更加复杂的数据扩增操作:
trfm = A.Compose([
A.Resize(256, 256),
A.HorizontalFlip(p=0.5),
A.VerticalFlip(p=0.5),
A.RandomRotate90(),
])
augments = trfm(image=img, mask=mask)
img_aug, mask_aug = augments['image'], augments['mask']
Pytorch数据读取
在Pytorch中数据是通过Dataset进行封装,并通过DataLoder进行并行读取。需要重载一下数据读取的逻辑来完成数据的读取。
- Dataset:数据集,对数据进行读取并进行数据扩增;
- DataLoder:数据读取器,对Dataset进行封装并进行批量读取;
定义Dataset:
import torch.utils.data as D
class TianChiDataset(D.Dataset):
def __init__(self, paths, rles, transform):
self.paths = paths
self.rles = rles
self.transform = transform
self.len = len(paths)
def __getitem__(self, index):
img = cv2.imread(self.paths[index])
mask = rle_decode(self.rles[index])
augments = self.transform(image=img, mask=mask)
return self.as_tensor(augments['image']), augments['mask'][None]
def __len__(self):
return self.len
实例化Dataset:
trfm = A.Compose([
A.Resize(IMAGE_SIZE, IMAGE_SIZE),
A.HorizontalFlip(p=0.5),
A.VerticalFlip(p=0.5),
A.RandomRotate90(),
])
dataset = TianChiDataset(
train_mask['name'].values,
train_mask['mask'].fillna('').values,
trfm
)
实例化DataLoder
loader = D.DataLoader(
dataset, batch_size=10, shuffle=True, num_workers=0)