1. 程式人生 > 實用技巧 >資料增強之mixup演算法詳解

資料增強之mixup演算法詳解

論文地址:mixup: BEYOND EMPIRICAL RISK MINIMIZATION

(一)、什麼是資料增強?
(1). 資料增強主要指在計算機視覺領域中對影象進行資料增強,從而彌補訓練影象資料集不足,達到對訓練資料擴充的目的。
(2). 資料增強是一種資料擴充方法,可分為同類增強(如:翻轉、旋轉、縮放、移位、模糊等)和混類增強(如mixup)兩種方式。

(二)、同類資料增強方式主要有哪些?
(1). 翻轉Flip
可分為水平翻轉,垂直翻轉

(2). 旋轉Rotation

(3). 縮放Scale(向外縮放,向內縮放)
向外縮放時,最終影象尺寸將大於原始影象尺寸,大多數影象框架從新影象中剪切出一個部分,其大小等於原始影象。而向內縮放,因為它會縮小影象大小,迫使我們對超出邊界的內容做出假設。

(4). 隨機裁剪(Random Crop)
與縮放不同,隨機裁剪只是從原始影象中隨機抽樣一個部分,然後我們將此部分的大小調整為原始影象大小。

(5). 移位(Translation)
移位只涉及沿X或Y方向(或兩者)移動影象。這種增強方法非常有用,因為大多數物件幾乎可以位於影象的任何位置,移位時我們需要對邊界作出假設。

(6). 模糊(Gaussian Noise)
當您的神經網路試圖學習可能無用的高頻特徵(大量出現的特徵)時,通常會發生過擬合。具有零均值的高斯噪聲基本上在所有頻率中具有資料點,從而有效地扭曲高頻特徵。但是這也意味著較低頻率的資料(通常是您的預期資料)也會失真,但您的神經網路可以學會超越它。新增適量的噪聲可以增強網路學習能力。

(三)、mixup混類資料增強方式
(1). mixup介紹
mixup是一種運用在計算機視覺中的對影象進行混類增強的演算法,它可以將不同類之間的影象進行混合,從而擴充訓練資料集。

(2). mixup原理
假設b a t c h x 1 batch_{x1}batchx1是一個b a t c h batchbatch樣本,b a t c h y 1 batch_{y1}batchy1是該b a t c h batchbatch樣本對應的標籤;b a t c h x 2 batch_{x2}batchx2是另一個b a t c h batchbatch樣本,b a t c h y 2 batch_{y2}batchy2是該b a t c h batchbatch樣本對應的標籤,λ \lambdaλ是由引數為α \alphaα,β \betaβ的貝塔分佈計算出來的混合係數,由此我們可以得到mixup原理公式為:λ = B e t a ( α , β ) (3.1) {\lambda=Beta(\alpha,\beta)\tag{3.1}}λ=Beta(α,β)(3.1)m i x e d _ b a t c h x = λ ∗ b a t c h x 1 + ( 1 − λ ) ∗ b a t c h x 2 (3.2) mixed\_ batch_x=\lambda*batch_{x1}+(1-\lambda)*batch_{x2}\tag{3.2}mixed_batchx=λbatchx1+(1λ)batchx2(3.2)m i x e d _ b a t c h y = λ ∗ b a t c h y 1 + ( 1 − λ ) ∗ b a t c h y 2 (3.3) {mixed\_batch_y=\lambda*batch_{y1}+(1-\lambda)*batch_{y_2}}\tag{3.3}mixed_batchy=λbatchy1+(1λ)batchy2(3.3)其中B e t a BetaBeta指的是貝塔分佈,m i x e d _ b a t c h x mixed\_batch_xmixed_batchx是混合後的b a t c h batchbatch樣本,m i x e d _ b a t c h y mixed\_batch_{y}mixed_batchy是混合後的b a t c h batchbatch樣本對應的標籤。

需要說明幾點:
1.在論文作者多組實驗中,無論如何設定α \alphaα,β \betaβ的值,期望α α + β \frac{\alpha}{\alpha+\beta}α+βα始終近似為0.5。這可能是由於權重λ \lambdaλ在每個batch樣本都會隨機產生,在整個訓練過程中會有N個batch,權重在N個batch中期望近似為0.5。所以作者認為產生b a t c h x 1 batch_{x1}batchx1b a t c h x 2 batch_{x2}batchx2樣本混合權重λ \lambdaλ的Beta分佈引數α = β = 0.5 \alpha=\beta=0.5α=β=0.5時,演算法效果相對較好。Beta分佈如下圖:

3.1 Beta分佈


2.b a t c h x 1 batch_{x1}batchx1b a t c h x 2 batch_{x2}batchx2沒有太多的限制,當b a t c h s i z e batch\ sizebatchsize=1時,就是兩張圖片樣本混合;當b a t c h s i z e batch\ sizebatchsize>1時,便是兩個b a t c h batchbatch圖片樣本兩兩對應混合。此外,b a t c h x 1 batch_{x1}batchx1b a t c h x 2 batch_{x2}batchx2可以是同一批樣本,也可以是不同批樣本。一般在程式碼實現過程中,兩個b a t c h batchbatch圖片是同一批樣本,唯一不同的是,b a t c h x 1 batch_{x1}batchx1是原始b a t c h batchbatch圖片樣本,而b a t c h x 2 batch_{x2}batchx2是對b a t c h x 1 batch_{x1}batchx1b a t c h s i z e batch\ sizebatchsize維度進行shuffle後得到的。

3.mixup原理大致如上,在實際程式碼實現過程中可能略有不同,需要靈活處理。

(3). mixup程式碼實現
mixup程式碼實現部分如下:

###############################author:qiu#################################

########################修改位置1:config.configurations#########################
#在程式碼配置config中新增以下鍵值資訊:
USE_MIXUP=True,  #是否使用mixup方法增強資料集
MIXUP_ALPHA = 0.5,#add mixup alpha ,用於beta分佈
##########################################################################

#######################修改位置2:新增mixup.py檔案############################
import numpy as np
import torch
import torch.nn as nn
from loss.focal import FocalLoss
LOSS=FocalLoss()

def criterion(batch_x, batch_y, alpha=1.0, use_cuda=True):
    '''
    batch_x:批樣本數,shape=[batch_size,channels,width,height]
    batch_y:批樣本標籤,shape=[batch_size]
    alpha:生成lam的beta分佈引數,一般取0.5效果較好
    use_cuda:是否使用cuda
    
    returns:
    	mixed inputs, pairs of targets, and lam
    '''
    
    if alpha > 0:
    	#alpha=0.5使得lam有較大概率取0或1附近
        lam = np.random.beta(alpha, alpha)
    else:
        lam = 1
    batch_size = batch_x.size()[0]
    if use_cuda:
        index = torch.randperm(batch_size).cuda()
    else:
        index = torch.randperm(batch_size) #生成打亂的batch_size索引
	
	#獲得混合的mixed_batchx資料,可以是同類(同張圖片)混合,也可以是異類(不同圖片)混合
	mixed_batchx = lam * batch_x + (1 - lam) * batch_x[index, :]
	
	"""
	Example:
	假設batch_x.shape=[2,3,112,112],batch_size=2時,
	如果index=[0,1]的話,則可看成mixed_batchx=lam*[[0,1],3,112,112]+(1-lam)*[[0,1],3,112,112]=[[0,1],3,112,112],即為同類混合
	如果index=[1,0]的話,則可看成mixed_batchx=lam*[[0,1],3,112,112]+(1-lam)*[[1,0],3,112,112]=[batch_size,3,112,112],即為異類混合
	"""
    batch_ya, batch_yb = batch_y, batch_y[index]
    return mixed_batchx, batch_ya, batch_yb, lam


def mixup_criterion(criterion, inputs, batch_ya, batch_yb, lam):
    return lam * criterion(inputs, batch_ya) + (1 - lam) * criterion(inputs, batch_yb)
##########################################################################

#####################修改位置3:train.py檔案修改程式碼如下######################
if torch.cuda.is_available() and DEVICE.type=="cuda":  #add
	inputs, targets = inputs.cuda(), targets.cuda()   
else:
	inputs = inputs.to(DEVICE)
	targets = targets.to(DEVICE).long()                   
	
if cfg['USE_MIXUP']:
	inputs, targets_a, targets_b, lam = mixup.mixup_data(
		inputs,targets,cfg["MIXUP_ALPHA"], torch.cuda.is_available())  
	
	#對映為Variable
	inputs, targets_a, targets_b = map(Variable, (inputs,targets_a,targets_b))
	#抽取特徵,BACKBONE為粗特徵抽取網路
	features = BACKBONE(inputs)   
	#抽取特徵,HEAD為精細的特徵抽取網路
	outputs = mixup.mixup_criterion(HEAD, features, targets_a, targets_b, lam)
	loss = mixup.mixup_criterion(LOSS, outputs, targets_a, targets_b, lam)             
else:
	features = BACKBONE(inputs)  
	outputs = HEAD(features, targets)                     
	loss = FocalLoss(outputs, labels)     
##########################################################################