简介
label smoothing其实是机器学习和深度学习上比较常用的一个小 trick。
这里简单做一些记录。
什么是label smoothing
什么是标签平滑呢?
这里举一个例子:
面对一个多分类问题
假设我们的当前对于xi的ground truth 是[0, 0, 0, 1]
说明对于xi来说他属于第四类,但是一般来说我们输出的会是经过softmax激活的一个概率向量,也就是可能为:
[0.013, 0.001, 0.264, 0.721]
不可能输出一个非0即1的向量,这样的概率向量就会是用来计算loss的。
那么什么是label smoothing呢,就是我们将得到的target向量进行多一步的处理:
Element-wise:
targets = targets * (1.0 - smoothing) + 0.5 * smoothing
smoothing 是平滑系数,在0,1之间
这就是label smoothing。
label smoothing作用
很显然,当我们增加label smoothing的时候,loss就会增加。
但是为什么还要使用这样的处理呢。
因为这样能带来几方面的好处:
- 防止过拟合,防止了出现非0即1的情况出现
- 提高模型的泛性
- 提高鲁棒性,当然这我倒是并没有亲身体验,如果有对抗方向的朋友应该就会比较有感触了。
torch实现label smoothing
这里我写代码用到了label smoothing,这是一个分类问题,用的是BCELoss,然后增加了label smoothing。
这里提供一个label smoothing在torch框架下的实现模板:
from torch.nn.modules.loss import _WeightedLoss
## 继承_WeightedLoss类
class SmoothingBCELossWithLogits(_WeightedLoss):
def __init__(self, weight=None, reduction='mean', smoothing=0.0):
super(SmoothingBCELossWithLogits, self).__init__(weight=weight, reduction=reduction)
self.smoothing = smoothing
self.weight = weight
self.reduction = reduction
@staticmethod
def _smooth(targets, n_labels, smoothing=0.0):
assert 0 <= smoothing < 1
with torch.no_grad():
targets = targets * (1 - smoothing) + 0.5 * smoothing
return targets
def forward(self, inputs, targets):
targets = _smooth(targets, inputs.size(-1), self.smoothing)
loss = F.binary_cross_entropy_with_logits(inputs, targets, self.weights)
if self.reduction == 'sum':
loss = loss.item()
elif self.reduction == 'mean':
loss = loss.mean()
return loss
如果有什么错误,还请大家指正。