目标检测的数据增强一般在写dataset自定义类时使用
pytorch一般在定义完模型后就转存到GPU上
在运用对tensor进行的方法前要把数据转化成张量
1.输入到模型前必须转化成tensor,所以可以在数据增强时利用torch.from_numpy(images).type(torch.FloatTensor).cuda()
这里数据在dataset和dataloader里都是ndarray,在传入模型前才转化成tensor
def fit_one_epoch(model_train, model, yolo_loss, loss_history, optimizer, epoch, epoch_step, epoch_step_val, gen, gen_val, Epoch, cuda):
loss = 0
val_loss = 0
model_train.train()
print('Start Train')
with tqdm(total=epoch_step,desc=f'Epoch {epoch + 1}/{Epoch}',postfix=dict,mininterval=0.3) as pbar:
for iteration, batch in enumerate(gen):
if iteration >= epoch_step:
break
images, targets = batch[0], batch[1]
with torch.no_grad():
if cuda:
images = torch.from_numpy(images).type(torch.FloatTensor).cuda()
targets = [torch.from_numpy(ann).type(torch.FloatTensor).cuda() for ann in targets]
else:
images = torch.from_numpy(images).type(torch.FloatTensor)
targets = [torch.from_numpy(ann).type(torch.FloatTensor) for ann in targets]
#----------------------#
# 清零梯度
#----------------------#
optimizer.zero_grad()
#----------------------#
# 前向传播
#----------------------#
outputs = model_train(images)
#----------------------#
# 计算损失
#----------------------#
loss_value = yolo_loss(outputs, targets)
#----------------------#
# 反向传播
#----------------------#
loss_value.backward()
optimizer.step()
loss += loss_value.item()
pbar.set_postfix(**{'loss' : loss / (iteration + 1),
'lr' : get_lr(optimizer)})
pbar.update(1)
data_transforms = transforms.Compose([
transforms.RandomResizedCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])
上述对data_transforms进行了四种变换,前两个是对PILImage进行的,分别对其进行随机大小和随机宽高比的裁剪,之后resize到指定大小224,以及对原始图像进行随机的水平翻转;
第三个transforms.ToTensor() 将PILImage转变为torch.FloatTensor的数据形式;
而最后一个Normalize则是对tensor进行的。
多种组合变换有一定的先后顺序,处理PILImage的变换方法(大多数方法)都需要放在ToTensor方法之前,而处理tensor的方法(比如Normalize方法)就要放在ToTensor方法之后。
torchvision.transforms的数据增强方式竟然用Compose组合在一起使用,使用时只要直接调用即可,
tranform = torchvision.transforms.Compose([...])
img = transform(img)
添加链接描述PyTorch 学习笔记:transforms的二十二个方法(transforms用法非常详细)
pytorch中的torchvision.transforms模块详解
添加链接描述torchvision.transforms包的使用
transform1 = transforms.Compose([
transforms.ToTensor(),# 先将PILimage或者ndarray转化成tensor
transforms.Normalize(mean = [0.5, 0.5, 0.5], std = [0.5, 0.5, 0.5])
# 再对每个通道的数据进行正则化,将(0,1)之间的数据转化成(-1,1)之间,这样更利于模型学习
]
)
transform3 = transforms.Compose([
transforms.ToTensor(),
transforms.ToPILImage(),
transforms.RandomCrop((100,100)),# RandomCrop是对PILImage进行,所以需要先用ToPILImage()
]
)
img6 = transform3(img3)
print(img6.size) # 100 * 100
img3.show()
img6.show()
(一) 裁剪(Crop)—— 中心裁剪:transforms.CenterCrop 随机裁剪:transforms.RandomCrop 随机长宽比裁剪:transforms.RandomResizedCrop 上下左右中心裁剪:transforms.FiveCrop 上下左右中心裁剪后翻转,transforms.TenCrop
(二) 翻转和旋转(Flip and Rotation) ——依概率p水平翻转:transforms.RandomHorizontalFlip(p=0.5) 依概率p垂直翻转:transforms.RandomVerticalFlip(p=0.5) 随机旋转:transforms.RandomRotation
(三) 图像变换(resize) ——transforms.Resize 标准化:transforms.Normalize 转为tensor,并归一化至[0-1]:transforms.ToTensor 填充:transforms.Pad 修改亮度、对比度和饱和度:transforms.ColorJitter 转灰度图:transforms.Grayscale 线性变换:
transforms.LinearTransformation() 仿射变换:transforms.RandomAffine 依概率p转为灰度图:transforms.RandomGrayscale 将数据转换为PILImage:transforms.ToPILImage transforms.Lambda:Apply a user-defined lambda as a transform.
(四) 对transforms操作,使数据增强更灵活 transforms.RandomChoice(transforms), 从给定的一系列transforms中选一个进行操作 transforms.RandomApply(transforms, p=0.5),给一个transform加上概率,依概率进行操作 transforms.RandomOrder,将transforms中的操作随机打乱
albumentations使用时要用关键词参数image = img并且返回值不直接是增强后的图片,而是字典要用
transforms(image=img)[‘image’]访问。
def get_train_transforms():
return Compose([
RandomResizedCrop(CFG['img_size'], CFG['img_size']),
Transpose(p=0.5),
HorizontalFlip(p=0.5),
#VerticalFlip(p=0.5),
ShiftScaleRotate(p=0.5),
HueSaturationValue(hue_shift_limit=0.2, sat_shift_limit=0.2, val_shift_limit=0.2, p=0.5),
RandomBrightnessContrast(brightness_limit=(-0.1,0.1), contrast_limit=(-0.1, 0.1), p=0.5),
Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225], max_pixel_value=255.0, p=1.0),
#CoarseDropout(p=0.5),
#Cutout(p=0.5),
ToTensorV2(p=1.0),
], p=1.)
def get_valid_transforms():
return Compose([
CenterCrop(CFG['img_size'], CFG['img_size'], p=1.),
Resize(CFG['img_size'], CFG['img_size']),
Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225], max_pixel_value=255.0, p=1.0),
ToTensorV2(p=1.0),
], p=1.)
self.transforms = transforms
if self.transforms:
img = self.transforms(image=img)['image']