**************************** 第七章 数据扩充与数据预处理 **************************** 7.2 特殊的数据扩充方式 ================================== ---------------------------------------------- 7.2.3 Mixup法 ---------------------------------------------- 以Facebook人工智能研究院(FAIR)开发的深度学习训练框架PyTorch代码为例,mixup法可按如下实现进行。 .. code-block:: python :linenos: # mixup (PyTorch) import torch import numpy as np for (x, y) in dataloader: # Ln.7-Ln.11: Shuffle the images in the batch randomly and mixup the images by the hyperparameter `lam`. lam = np.random.beta(1.0, 1.0) perm = torch.randperm(x.shape[0]) x1, x2 = x, x[perm] y1, y2 = y, y[perm] x = lam * x1 + (1 - lam) * x2 # Ln.14-Ln.18: Predict the mixed images and calculate the corresponding loss. pred = net(x) loss = lam * criterion(pred, y1) + (1 - lam) * criterion(pred, y2) optimizer.zero_grad() loss.backward() optimizer.step() 此外,mixup法在MindSpore中可按如下实现。 .. code-block:: python :linenos: # mixup (MindSpore) import mindspore import numpy as np from mindspore import ops def train_loop(model, dataset, loss_fn, optimizer): # Ln.8-Ln.20: Define forward function def forward_fn(data, label, alpha=1.0): # Ln.10-Ln.15: Shuffle the images in the batch randomly and mixup the images by the hyperparameter `lam`. lam = np.random.beta(alpha, alpha) perm = np.random.permutation(data.shape[0]) x1, x2 = data, data[perm] y1, y2 = label, label[perm] x = lam * x1 + (1 - lam) * x2 # Ln.18-Ln.20: Predict the mixed images and calculate the corresponding loss. pred = model(x) loss = lam * loss_fn(pred, y1) + (1 - lam) * loss_fn(pred, y2) return loss, pred # Ln.23: Get gradient function grad_fn = mindspore.value_and_grad(forward_fn, None, optimizer.parameters, has_aux=True) # Ln.26-Ln.29: Define function of one-step training def train_step(data, label): (loss, _), grads = grad_fn(data, label) loss = ops.depend(loss, optimizer(grads)) return loss model.set_train() for batch, (data, label) in enumerate(dataset.create_tuple_iterator()): loss = train_step(data, label) 可以看到,mixup法的插值操作对象为原始图像像素空间。而Manifold mixup法对深度学习模型的隐层表示(hidden representation)进行插值,并取得了优于mixup的效果。具体而言,Manifold mixup法可由PyTorch实现如下: .. code-block:: python :linenos: # manifold mixup (PyTorch) import torch import numpy as np for (x, y) in dataloader: lam = np.random.beta(1.0, 1.0) perm = np.random.permutation(x.shape[0]) # Ln.10-Ln.16: Mixup the hidden representations, predict the mixed representations and calculate the corresponding loss. x = net.forward_to_certain_layer(x) x = lam * x + (1 - lam) * x[perm] pred = net.forward_from_certain_layer(x) loss = lam * criterion(pred, y1) + (1 - lam) * criterion(pred, y2) optimizer.zero_grad() loss.backward() optimizer.step() 此外,Manifold mixup法在MindSpore中实现如下: .. code-block:: python :linenos: # manifold mixup (MindSpore) import mindspore import numpy as np from mindspore import ops def train_loop(model, dataset, loss_fn, optimizer): # Ln.8-Ln.17: Define forward function def forward_fn(data, label): lam = np.random.beta(alpha, alpha) perm = np.random.permutation(data.shape[0]) # Ln.13-Ln.17: Mixup the hidden representations, predict the mixed representations and calculate the corresponding loss. x = model.forward_to_certain_layer(data) x = lam * x + (1 - lam) * x[perm] pred = model.forward_from_certain_layer(x) loss = lam * loss_fn(pred, y) + (1 - lam) * loss_fn(pred, y[perm]) return loss, pred # Ln.20: Get gradient function grad_fn = mindspore.value_and_grad(forward_fn, None, optimizer.parameters, has_aux=True) # Ln.23-Ln.26: Define function of one-step training def train_step(data, label): (loss, _), grads = grad_fn(data, label) loss = ops.depend(loss, optimizer(grads)) return loss model.set_train() for batch, (data, label) in enumerate(dataset.create_tuple_iterator()): loss = train_step(data, label) 7.3 深度学习数据预处理 ================================== 以PyTorch代码为例,图像减均值操作可以按以下步骤进行。 .. code-block:: python :linenos: # Subtract the mean values (PyTorch) import torch mean = torch.tensor([0.485, 0.456, 0.406]).reshape(3, 1, 1) var = torch.tensor([0.229, 0.224, 0.225]).reshape(3, 1, 1) def train(data, label, net, loss_fun): # Ln.9: Input the image into the network by subtracting the mean and dividing by the variance. out = net((data - mean) / var) loss = loss_fun(out, label) loss.backward() 在MindSpore中的实现如下: .. code-block:: python :linenos: # Subtract the mean values (MindSpore) import mindspore import numpy as np mean = mindspore.Tensor(np.array([0.485 * 255, 0.456 * 255, 0.406 * 255])).reshape(3, 1, 1) var = mindspore.Tensor(np.array([0.229 * 255, 0.224 * 255, 0.225 * 255])).reshape(3, 1, 1) def forward_fn(data, label, model, loss_fn): # Ln.10: Input the image into the network by subtracting the mean and dividing by the variance. logits = model((data - mean) / var) loss = loss_fn(logits, label) return loss, logits 或者该操作可直接在数据预处理模块中完成,PyTorch中的实现如下: .. code-block:: python :linenos: # Build the training dataset (PyTorch) import torchvision.datasets import torchvision.transforms as transforms from torch.utils.data import DataLoader print('preparing dataset...') transform = transforms.Compose([ transforms.Resize(size=config.resize_size), transforms.RandomHorizontalFlip(), transforms.RandomCrop(size=config.image_size), transforms.ToTensor(), # Ln.12: Normalize data, e.g., the subtract the mean values operation. transforms.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)) ]) train_dataset = torchvision.datasets.ImageFolder(root='./data',transform=transform) train_loader = DataLoader(dataset=train_dataset, batch_size=config.batch_size, shuffle=True) 此外,MindSpore中的实现如下: .. code-block:: python :linenos: # Build the training dataset (MindSpore) import mindspore from mindspore.dataset import ImageFolderDataset import mindspore.dataset.vision as transforms mean = [0.485 * 255, 0.456 * 255, 0.406 * 255] std = [0.229 * 255, 0.224 * 255, 0.225 * 255] dataset_train = ImageFolderDataset(data_path, shuffle=True) trans_train = [ transforms.RandomCropDecodeResize(size=224, scale=(0.08, 1.0), ratio=(0.75, 1.333)), transforms.RandomHorizontalFlip(prob=0.5), # Ln.15: Normalize data, e.g., the subtract the mean values operation. transforms.Normalize(mean=mean, std=std), transforms.HWC2CHW() ] dataset_train = dataset_train.map(operations=trans_train, input_columns=["image"]) dataset_train = dataset_train.batch(batch_size=16, drop_remainder=True)