图像增广

通过对训练图像做一系列随机改变,来产生相似但又不同的训练样本,从而扩大训练数据集的规模。图像增广的另一种解释是,随机改变训练样本可以降低模型对某些属性的依赖,从而提高模型的泛化能力。

我们可以对图像进行不同方式的裁剪,使感兴趣的物体出现在不同位置,从而减轻模型对物体出现位置的依赖性。我们也可以调整亮度、色彩等因素来降低模型对色彩的敏感度。

1翻转和裁剪,2变化颜色(亮度、对比度、饱和度和色调)3将多个图像增广方法叠加使用

多样本数据增强:SMOTE,SamplePairing,mixup,无监督的数据增强:GAN

shape_aug = torchvision.transforms.RandomResizedCrop(200, scale=(0.1, 1), ratio=(0.5, 2)) #宽和高之比随机取自 0.5∼2 ,为原面积 10%∼100% 的区域,然后再将该区域的宽和高分别缩放到200像素
apply(img, shape_aug)
apply(img, torchvision.transforms.RandomVerticalFlip()) #垂直(上下)翻转
apply(img, torchvision.transforms.RandomHorizontalFlip()) #实现一半概率的图像水平(左右)翻转。
apply(img, torchvision.transforms.ColorJitter(brightness=0.5, contrast=0, saturation=0, hue=0))#亮度(brightness)、对比度(contrast)、饱和度(saturation)和色调(hue
#叠加方法
augs = torchvision.transforms.Compose([
    torchvision.transforms.RandomHorizontalFlip(), color_aug, shape_aug])
apply(img, augs)

2应用pytorch数据集

flip_aug = torchvision.transforms.Compose([
     torchvision.transforms.RandomHorizontalFlip(),
     torchvision.transforms.ToTensor()])

no_aug = torchvision.transforms.Compose([
     torchvision.transforms.ToTensor()])

train_iter = torchvision.datasets.CIFAR10(root=root, train=is_train, transform=flip_aug, download=False)
test_iter = torchvision.datasets.CIFAR10(root=root, train=not_train, transform=no_aug, download=False)

模型微调

数据集太少不能用用复杂模型。解决:迁移学习

将从源数据集学到的知识迁移到目标数据集上。例如,虽然ImageNet数据集的图像大多跟椅子无关,但在该数据集上训练的模型可以抽取较通用的图像特征,从而能够帮助识别边缘、纹理、形状和物体组成等。这些类似的特征对于识别椅子也可能同样有效。

我们介绍迁移学习中的一种常用技术:微调(fine tuning)。由以下四步构成

  1. 源数据集(如ImageNet数据集)上预训练一个神经网络模型,即源模型
  2. 创建一个新的神经网络模型,即目标模型。它复制了源模型上除了输出层外的所有模型设计及其参数。我们假设这些模型参数包含了源数据集上学习到的知识,且这些知识同样适用于目标数据集。我们还假设源模型的输出层跟源数据集的标签紧密相关,因此在目标模型中不予采用。
  3. 为目标模型添加一个输出大小为目标数据集类别个数的输出层,并随机初始化该层的模型参数
  4. 在目标数据集(如椅子数据集)上训练目标模型。我们将从头训练输出层,而其余层的参数都是基于源模型的参数微调得到的。

nlp数据增强 改写句子 数据增强 pytorch_数据集

当目标数据集远小于源数据集时,微调有助于提升模型的泛化能力。

from torch.utils.data import Dataset, DataLoader
import torchvision
from torchvision.datasets import ImageFolder
from torchvision import transforms
from torchvision import models
#使用在ImageNet数据集上预训练的ResNet-18作为源模型。
pretrained_net = models.resnet18(pretrained=False) #pretrained=True来自动下载并加载预训练的模型参数
pretrained_net.load_state_dict(torch.load('/home/kesci/input/resnet185352/resnet18-5c106cde.pth')) 

#原来Linear(in_features=512, out_features=1000, bias=True) 改成我们需要的
pretrained_net.fc = nn.Linear(512, 2) #Linear(in_features=512, out_features=2, bias=True)
'''此时,pretrained_net的fc层就被随机初始化了,但是其他层依然保存着预训练得到的参数,参数已经足够好,因此一般只需使用较小的学习率来微调这些参数,而fc中的随机初始化参数一般需要更大的学习率从头训练。
PyTorch可以方便的对模型的不同部分设置不同的学习参数,我们在下面代码中将fc的学习率设为已经预训练过的部分的10倍。'''
output_params = list(map(id, pretrained_net.fc.parameters()))
feature_params = filter(lambda p: id(p) not in output_params, pretrained_net.parameters())

lr = 0.01
optimizer = optim.SGD([{'params': feature_params},
                       {'params': pretrained_net.fc.parameters(), 'lr': lr * 10}],
                       lr=lr, weight_decay=0.001)

def train_fine_tuning(pretrained_net, optimizer, batch_size=128, num_epochs=5):
    train_iter = DataLoader(ImageFolder(os.path.join(data_dir, 'hotdog/train'), transform=train_augs),
                            batch_size, shuffle=True)
    test_iter = DataLoader(ImageFolder(os.path.join(data_dir, 'hotdog/test'), transform=test_augs),
                           batch_size)
    loss = torch.nn.CrossEntropyLoss()
train_fine_tuning(pretrained_net, optimizer)


#对比,所有都从头训练 
scratch_net = models.resnet18(pretrained=False, num_classes=2) 
lr = 0.1
optimizer = optim.SGD(scratch_net.parameters(), lr=lr, weight_decay=0.001)
train_fine_tuning(scratch_net, optimizer)