第七章 数据扩充与数据预处理

7.2 特殊的数据扩充方式

7.2.3 Mixup法

以Facebook人工智能研究院(FAIR)开发的深度学习训练框架PyTorch代码为例,mixup法可按如下实现进行。

 1# mixup (PyTorch)

 2import torch

 3import numpy as np

 4

 5for (x, y) in dataloader:

 6    # Ln.7-Ln.11: Shuffle the images in the batch randomly and mixup the images by the hyperparameter `lam`.

 7    lam = np.random.beta(1.0, 1.0)

 8    perm = torch.randperm(x.shape[0])

 9    x1, x2 = x, x[perm]

10    y1, y2 = y, y[perm]

11    x = lam * x1 + (1 - lam) * x2

12

13    # Ln.14-Ln.18: Predict the mixed images and calculate the corresponding loss.

14    pred = net(x)

15    loss = lam * criterion(pred, y1) + (1 - lam) * criterion(pred, y2)

16    optimizer.zero_grad()

17    loss.backward()

18    optimizer.step()

此外,mixup法在MindSpore中可按如下实现。

 1# mixup (MindSpore)

 2import mindspore

 3import numpy as np

 4from mindspore import ops

 5

 6def train_loop(model, dataset, loss_fn, optimizer):

 7    # Ln.8-Ln.20: Define forward function

 8    def forward_fn(data, label, alpha=1.0):

 9        # Ln.10-Ln.15: Shuffle the images in the batch randomly and mixup the images by the hyperparameter `lam`.

10        lam = np.random.beta(alpha, alpha)

11        perm = np.random.permutation(data.shape[0])

12

13        x1, x2 = data, data[perm]

14        y1, y2 = label, label[perm]

15        x = lam * x1 + (1 - lam) * x2

16

17        # Ln.18-Ln.20: Predict the mixed images and calculate the corresponding loss.

18        pred = model(x)

19        loss = lam * loss_fn(pred, y1) + (1 - lam) * loss_fn(pred, y2)

20        return loss, pred

21

22    # Ln.23: Get gradient function

23    grad_fn = mindspore.value_and_grad(forward_fn, None, optimizer.parameters, has_aux=True)

24

25    # Ln.26-Ln.29: Define function of one-step training

26    def train_step(data, label):

27        (loss, _), grads = grad_fn(data, label)

28        loss = ops.depend(loss, optimizer(grads))

29        return loss

30

31    model.set_train()

32    for batch, (data, label) in enumerate(dataset.create_tuple_iterator()):

33        loss = train_step(data, label)

可以看到,mixup法的插值操作对象为原始图像像素空间。而Manifold mixup法对深度学习模型的隐层表示(hidden representation)进行插值,并取得了优于mixup的效果。具体而言,Manifold mixup法可由PyTorch实现如下:

 1# manifold mixup (PyTorch)

 2import torch

 3import numpy as np

 4

 5for (x, y) in dataloader:

 6    lam = np.random.beta(1.0, 1.0)

 7    perm = np.random.permutation(x.shape[0])

 8

 9    # Ln.10-Ln.16: Mixup the hidden representations, predict the mixed representations and calculate the corresponding loss.

10    x = net.forward_to_certain_layer(x)

11    x = lam * x + (1 - lam) * x[perm]

12    pred = net.forward_from_certain_layer(x)

13    loss = lam * criterion(pred, y1) + (1 - lam) * criterion(pred, y2)

14    optimizer.zero_grad()

15    loss.backward()

16    optimizer.step()

此外,Manifold mixup法在MindSpore中实现如下:

 1# manifold mixup (MindSpore)

 2import mindspore

 3import numpy as np

 4from mindspore import ops

 5

 6def train_loop(model, dataset, loss_fn, optimizer):

 7    # Ln.8-Ln.17: Define forward function

 8    def forward_fn(data, label):

 9        lam = np.random.beta(alpha, alpha)

10        perm = np.random.permutation(data.shape[0])

11

12        # Ln.13-Ln.17: Mixup the hidden representations, predict the mixed representations and calculate the corresponding loss.

13        x = model.forward_to_certain_layer(data)

14        x = lam * x + (1 - lam) * x[perm]

15        pred = model.forward_from_certain_layer(x)

16

17        loss = lam * loss_fn(pred, y) + (1 - lam) * loss_fn(pred, y[perm])

18        return loss, pred

19

20    # Ln.20: Get gradient function

21    grad_fn = mindspore.value_and_grad(forward_fn, None, optimizer.parameters, has_aux=True)

22

23    # Ln.23-Ln.26: Define function of one-step training

24    def train_step(data, label):

25        (loss, _), grads = grad_fn(data, label)

26        loss = ops.depend(loss, optimizer(grads))

27        return loss

28

29    model.set_train()

30    for batch, (data, label) in enumerate(dataset.create_tuple_iterator()):

31        loss = train_step(data, label)

7.3 深度学习数据预处理

以PyTorch代码为例,图像减均值操作可以按以下步骤进行。

 1# Subtract the mean values (PyTorch)

 2import torch

 3

 4mean = torch.tensor([0.485, 0.456, 0.406]).reshape(3, 1, 1)

 5var = torch.tensor([0.229, 0.224, 0.225]).reshape(3, 1, 1)

 6

 7def train(data, label, net, loss_fun):

 8    # Ln.9: Input the image into the network by subtracting the mean and dividing by the variance.

 9    out = net((data - mean) / var)

10    loss = loss_fun(out, label)

11    loss.backward()

在MindSpore中的实现如下:

 1# Subtract the mean values (MindSpore)

 2import mindspore

 3import numpy as np

 4

 5mean = mindspore.Tensor(np.array([0.485 * 255, 0.456 * 255, 0.406 * 255])).reshape(3, 1, 1)

 6var = mindspore.Tensor(np.array([0.229 * 255, 0.224 * 255, 0.225 * 255])).reshape(3, 1, 1)

 7

 8def forward_fn(data, label, model, loss_fn):

 9    # Ln.10: Input the image into the network by subtracting the mean and dividing by the variance.

10    logits = model((data - mean) / var)

11    loss = loss_fn(logits, label)

12    return loss, logits

或者该操作可直接在数据预处理模块中完成,PyTorch中的实现如下:

 1# Build the training dataset (PyTorch)

 2import torchvision.datasets

 3import torchvision.transforms as transforms

 4from torch.utils.data import DataLoader

 5

 6print('preparing dataset...')

 7transform = transforms.Compose([

 8    transforms.Resize(size=config.resize_size),

 9    transforms.RandomHorizontalFlip(),

10    transforms.RandomCrop(size=config.image_size),

11    transforms.ToTensor(),

12    # Ln.12: Normalize data, e.g., the subtract the mean values operation.

13    transforms.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225))

14])

15train_dataset = torchvision.datasets.ImageFolder(root='./data',transform=transform)

16train_loader = DataLoader(dataset=train_dataset, batch_size=config.batch_size, shuffle=True)

此外,MindSpore中的实现如下:

 1# Build the training dataset (MindSpore)

 2import mindspore

 3from mindspore.dataset import ImageFolderDataset

 4import mindspore.dataset.vision as transforms

 5

 6mean = [0.485 * 255, 0.456 * 255, 0.406 * 255]

 7std = [0.229 * 255, 0.224 * 255, 0.225 * 255]

 8

 9dataset_train = ImageFolderDataset(data_path, shuffle=True)

10

11trans_train = [

12    transforms.RandomCropDecodeResize(size=224, scale=(0.08, 1.0), ratio=(0.75, 1.333)),

13    transforms.RandomHorizontalFlip(prob=0.5),

14    # Ln.15: Normalize data, e.g., the subtract the mean values operation.

15    transforms.Normalize(mean=mean, std=std),

16    transforms.HWC2CHW()

17]

18dataset_train = dataset_train.map(operations=trans_train, input_columns=["image"])

19dataset_train = dataset_train.batch(batch_size=16, drop_remainder=True)