论文链接:
mixup:BEYOND EMPIRICAL RISK MINIMIZATION
1. mixup 简介
mixup是一种非常规的数据增强方法,以线性插值的方式来构建新的训练样本和标签。与其他数据增强方法显著不同的是,mixup是一种混类增强的算法,可以将不同类之间的图像进行混合,从而扩充训练数据集。
2. mixup的2种实现方式
mixup可以在同一个batch数据内部做, 也可以在不同batch数据之间做。在同一个batch内部做时, 会对数据顺序进行随机打乱,从而构造出2批数据。假设有2批数据(不区分是同一个batch还是不同batch数据,两者原理相同), ( x i , y i ) (x_i,y_i) (xi,yi)和 ( x j , y j ) (x_j,y_j) (xj,yj), 其中 x x x是输入数据, y y y是对应的标签。
2.1 输出2种标签, 对loss 求加权和
这种方式进行mixup操作的处理如下:
- 对数据的处理:
m i x x = λ x i + ( 1 − λ ) x j mix_x = \lambda x_i+(1-\lambda)x_j mixx=λxi+(1−λ)xj
y a , y b = y i , y j y_a, y_b = y_i,y_j ya,yb=yi,yj
上述公式展示了对数据的处理过程, 其中对输入数据 x x x做线性加权求和, 标签值则是有2个。 - 对loss 进行处理
l o s s = λ l o s s _ f n ( o u t p u t , y i ) + ( 1 − λ ) l o s s _ f n ( o u t p u t , y j ) loss = \lambda loss\_f_n(output, yi)+(1-\lambda)loss\_f_n(output, y_j) loss=λloss_fn(output,yi)+(1−λ)loss_fn(output,yj)
其中, l o s s _ f n loss\_f_n loss_fn表示损失函数, o u t p u t = m o d e l ( m i x x ) output=model(mix_x) output=model(mixx), 为输入数据经过模型之后的输出。
2.2 标签做加权求和 , loss按原有方式计算
- 对数据的处理
m i x x = λ x i + ( 1 − λ ) x j mix_x = \lambda x_i+(1-\lambda)x_j mixx=λxi+(1−λ)xj
m i x y = λ y i + ( 1 − λ ) y j mix_y=\lambda y_i +(1-\lambda)y_j mixy=λyi+(1−λ)yj
这种方式下,对 x x x和 y y y的处理是一致的, 都是做线性的加权和。 但是有一点需要格外注意, 此时的 y i y_i yi和 y j y_j yj都需要是one-hot
编码的。 第一种方式则没有这个要求。 - 对loss的处理
loss不需要特殊处理, 按原有的方式计算loss即可。
l o s s = l o s s _ f n ( o u t p u t , m i x y ) loss = loss_\_f_n(output,mix_y) loss=loss_fn(output,mixy)
3 两种方式的等价性证明
既然有2种不同的实现方式, 那很自然就有一个疑问了, 这2种方式是否是等价的呢?以及具体实现时该选取那种方式呢?
首先回答第一个问题, 2种方式的实现是等价的。其实不知道大家注意到没有, 原作的论文中原理介绍其实是按照第二种方法来的, 但是具体到代码实现中几乎都是按第一种方式实现的, 就连论文作者也推荐使用第一种方式实现。因此, 给刚开始接触的读者造成了巨大的困扰。在这里我就做个简单的推导证明, 解除读者心中的疑惑。
证明过程如下:
需要证明的问题是2种实现方式中的loss值是否相同。
l
o
s
s
1
=
λ
l
o
s
s
_
f
n
(
o
u
t
p
u
t
,
y
i
)
+
(
1
−
λ
)
l
o
s
s
_
f
n
(
o
u
t
p
u
t
,
y
j
)
loss_1 = \lambda loss\_f_n(output, yi)+(1-\lambda)loss\_f_n(output, y_j)
loss1=λloss_fn(output,yi)+(1−λ)loss_fn(output,yj)
l
o
s
s
2
=
l
o
s
s
_
f
n
(
o
u
t
p
u
t
,
m
i
x
y
)
=
l
o
s
s
_
f
n
(
o
u
t
p
u
t
,
λ
y
i
+
(
1
−
λ
)
y
j
)
loss_2 = loss_\_f_n(output,mix_y)=loss\_f_n(output, \lambda y_i +(1-\lambda)y_j)
loss2=loss_fn(output,mixy)=loss_fn(output,λyi+(1−λ)yj)
由于分类问题中最常用的损失函数是交叉熵损失函数CrossEntropyLoss
, 下面就用CrossEntropyLoss
为例进行证明。
CrossEntropyLoss
的计算公式如下:
l
o
s
s
=
−
∑
c
y
l
n
(
y
p
r
e
d
)
loss = -\sum _c y ln (y_{pred})
loss=−c∑yln(ypred)
其中
y
y
y和
y
p
r
e
d
y_{pred}
ypred分别表示真实标签和预测值,
c
c
c表示某一个类别。为了简单起见, 上面计算的loss是一个样本数据的, 对多个样本数据, 只需要对单个样本的loss再求和即可。
代入上面的公式有:
l
o
s
s
1
=
−
λ
∑
y
i
l
n
(
o
u
t
p
u
t
)
−
(
1
−
λ
)
∑
y
j
l
n
(
o
u
t
p
u
t
)
loss_1=-\lambda \sum y_i ln(output)-(1-\lambda)\sum y_j ln(output)
loss1=−λ∑yiln(output)−(1−λ)∑yjln(output)
l
o
s
s
2
=
−
∑
(
(
λ
y
i
+
(
1
−
λ
)
y
j
)
l
n
(
o
u
t
p
u
t
)
)
=
−
λ
∑
y
1
l
n
(
o
u
t
p
u
t
)
−
(
1
−
λ
)
∑
y
j
l
n
(
o
u
t
p
u
t
)
loss_2 = -\sum((\lambda y_i+(1-\lambda)y_j)ln(output)) \\ \quad \quad \quad \quad \quad \quad \quad=-\lambda\sum y_1ln(output)-(1-\lambda)\sum y_j ln(output)
loss2=−∑((λyi+(1−λ)yj)ln(output))=−λ∑y1ln(output)−(1−λ)∑yjln(output)
因此
l
o
s
s
1
loss_1
loss1和
l
o
s
s
2
loss_2
loss2是相等的。也就是说2种mixup的实现是等价的。
那么具体实现时应该怎么选择呢?
理论上2种实现方式都是等价的, 只是在具体实现中有难易, 跟实际使用的训练框架有关系。第一种实现需要在训练过程中进行数据处理, 训练和数据处理是交织在一起的, 对torch来说这种处理是非常方便的。但对其他一些框架则不然, 如mindspore, 采用编译模式, 训练过程中去处理数据是非常不方便的, 也会导致性能的极大降低。第二种实现中最主要的是需要对标签做一个one-hot
的处理,torch中也可以做, 但不是很友好。 因此, 具体实现时可以根据实际情况来选取实现方式。