全球先进公司建成全球首座8英寸氮化镓代工厂
06-06
今天我们来谈谈非常规损失函数。除了常用的分类交叉熵和回归均方误差之外,我们还会针对数据长尾、标签噪声、训练样本数据不平衡等可能出现的问题,讨论适合不同场景的针对性损失函数。
在第一章中,我们介绍了当注释标签存在噪声时可以尝试的损失函数。这里的标签噪声主要指与特征分布无关的标签噪声。
代码详情参见pytorch、Tensorflow?Symmetric Loss Function论文:Making Risk Minimization Tolerant to Label Noise 这里我们用最基本的二分类问题和一个简化的假设“标签噪声和标签独立且均匀分布”来解释什么是对标记噪声具有鲁棒性的损失函数。假设总体误标样本比例为 eta,则真实标签 y=0 和 y=1 中均存在 eta 误标比例,其中 1 标记为 0,0 标记为 1。
带噪声的损失函数为如下`$\begin{align}L(f(x), y_{噪声}) &= (1-\eta)L(f(x), y) + \eta L(f(x ), 1- y) \& = (1-2\eta)L(f(x),y) + \etaL(f(x),y)+L(f(x),1-y) \& = (1- 2\eta)*L(f(x),y) + \eta K \\end{align}$`所以如果损失函数满足 L(f(x),y)+L(f(x) ), 1-y)=constant,那么带噪声的损失函数将收敛到与不带噪声的 L(f(x),y) 相同的解。作者认为这样的损失函数是对称的。
那么对称损失有哪些常见的损失函数呢?梅就是它!对于二分类softmax的输出层L(f(x),y)+L(f(x),1-y)=|y-f(x)| + |1-y-f(x)| =1、敲黑板!记住这一点,因为后面的GCE和SCE其实都离不开MAE。对称损失的论证在这里得到了简化。
详细内容请参见论文~广义交叉熵(GCE)论文:Generalized Cross Entropy Loss for Training Deep Neural Networks with Noisy Labels。继续上面,虽然MAE是一个噪声鲁棒损失函数,但是在深度学习中,由于MAE的梯度要么是1,要么是-1,并且所有样本的梯度尺度相同,缺乏对样本的表征难度和模型置信度,所以MAE很难收敛。
作者提出了一种融合MAE和交叉熵的解决方案。废话不多说,直接上Loss`$L_{q}(f(x),y_j) = \frac{1-f_j(x)^q}{q} $`作者使用负box-cox作为损失函数,乍一看与MAE无关。
然而,如果你改变q的值,你会发现奥妙就在于q->1:L=1-f_j(x),即MAE Lossq->0:根据洛皮达定律,如果对分子微分和分母同时,你会得到 L =-log(f_j(x)) ,即交叉熵,因此GCE损失函数通过控制q的值找到MAE和CrossEntropy之间的折衷点。这有点类似于Huber Loss的设计,只不过Huber明确使用alpha权重来融合RMSE和MAE,而GCE是隐式融合。
q->1,对噪声更鲁棒,但更难收敛。作者还提出截断GCE,以截断过多的损失。
这里我就不详细说了。 pytorch实现如下。
TF实现参见文章开头链接代码语言: javascript copy class GeneralizeCrossEntropy(nn.Module): def __init__(self, q=0.7): super(GeneralizeCrossEntropy, self).__init__() self.q = q defforward(self, logits, labels): # 负框 cox: (1-f(x)^q)/q labels = torch .nn.function.one_hot(labels, num_classes=logits.shape[-1]) probs = F.softmax(logits, dim=-1) 损失 = (1 - torch.pow(torch.sum(labels * probs, dim =-1), self.q)) / self.q 损失 = torch.mean (loss) return lossSymmetric Cross Entropy (SCE) Symmetric Cross Entropy for Robust Learning with Noisy Labels 作者从交叉熵的另一个含义出发,最小交叉熵实际上是最小化预测分布与真实分布之间的 KL 散度。两者的关系如下,其中H(y)是真实标签的信息熵,是一个常数`$\begin{align}KL(y||f(x)) &= \sum ylog(f (x)) - \sum ylog(y) \& = H(y, f(x)) - H(y) = CrossEntropy(y, f(x)) - H (y)\end{对齐}$`考虑KL散度是不对称的,KL(y||f(x))!=KL(f(x)||y),前者衡量预测分布对于数据编码导致的信息损失的使用。
然而,当 y 本身存在噪声时,y 可能不是正确的标签,但 f(x) 是。在这种情况下,需要考虑另一个方向KL散度KL(f(x)||y)。
所以作者使用对称KL对应的对称交叉熵(SCE)作为损失函数`$SCE =CE + RCE = H(y,f(x)) + H(f(x),y) \= \ sum_j y_jlog(f_j (x)) + \sum_j f_j(x)log(y_j)$`看到这里你会觉得作者又挠头了>.<。但只需要在RCE部分进行改造,就会一下子清晰起来。
以二元分类为例,无法计算log(0)。使用常数 A 替换 `$RCE= H(f(x),y) = f_1(x) log(1) + (1-f_1(x)) log(0 ) = A(1-f_1(x)) $`RCE 部分是 MAE!所以SCE本质上是交叉熵和MAE的显式融合! pytorch实现如下。
TF实现参见文章开头链接代码语言:javascript copy class SymmetricCrossEntropy(nn.Module): def __init__(self, alpha=0.1, beta=1): super(SymmetricCrossEntropy, self).__init__() self.alpha = alpha self.beta = beta self.epsilon = 1e-10 defforward(self, logits, labels): # KL(p|q) + KL(q|p) labels = torch.nn.function.one_hot (labels, num_classes=logits.shape[-1]) probs = F.softmax(logits, dim=-1) # KL y_true = torch.clip(labels, self.eps, 1.0 - self.eps) y_pred = probs ce = -torch .mean(torch.sum(y_true * torch.log(y_pred), dim=-1)) # 反向KL y_true = probs y_pred = torch.clip(labels, self.eps, 1.0 - self.eps) rce = -torch .mean(torch.sum(y_true * torch.log(y_pred), dim=-1)) 返回 self.alpha * ce + self.beta * rcePeerLossPeer 损失函数:在不知道噪声率的情况下从噪声标签中学习NLNL:噪声标签的负学习与 GCE 和 SCE 相比,Peer 损失仅适用于交叉熵。其设计更加灵活。
每个样本的损失函数由常规损失和随机标签损失进行加权。得到的,权重为alpha,这里的损失支持任何分类损失函数。
随机标签作者是通过打乱一批标签的顺序来获得的~原理上感觉Peer Loss和NLNL很相似,都是负学习思想。对比两者的损失函数,PL就是最小化噪声标签y的损失,同时最大化模型在随机标签上的损失。
NL 直接最大化模型在非真实标签 y 上的损失。本质上,它们都是消极学习。
该模型不学习 x 是什么,而是学习 x 不是什么。通过将所有错误分类的p->0压入,得到正确的标签。
从这个逻辑来看,感觉Peer Loss和NLNL在高维多分类场景下应该会有更好的表现~`$PL(f(x),y) = L(f(x),y) - \alpha L ( f(x),\tilde{y}) $``$NL(f(x),y) = L(1-f(x), \tilde{y}) $`pytorch 实现如下,参见 TF实现第一链接代码语言:javascript copy class PeerLoss(nn.Module): def __init__(self, alpha=0.5, loss): super(PeerLoss, self).__init__() self.alpha = alpha self.loss = loss def front (self, preds, labels): index = list(range(labels.shape[0])) rand_index = random.shuffle(index) rand_labels = labels[rand_index] loss_true = self.loss(preds, labels) loss_rand = self. loss(preds, rand_labels) loss = loss_true - self.alpha * loss_rand return lossBootstrap Loss 使用 Bootstrapping 在噪声标签上训练深度神经网络 Bootstrap Loss 是从预测一致性的角度减少噪声标签对模型的影响。作者给出了soft和hard两个损失函数。
Soft Bootstrap在交叉熵的基础上加上预测熵值,在最小化概率熵值的同时,最小化预测误差,将概率推向0/1,获得更加置信的预测。这里我们实际上应用了之前半监督中提到的最小熵原理(小样本工具3.半监督最小熵规则),就是将分类边界推离高密度区域。
对于噪声标签,模型最初估计的熵值会更大(p->0.5)。因为加入了熵正则化项,模型不再拟合噪声标签,而是移动到正确的标签(增加预测置信度,降低熵值),也会降低损失函数。
但感觉引入熵正则化也可能使模型预测置信度过高而导致过拟合`$L_{soft} = \sum (\beta y_i + (1-\beta) p_i) log(p_i) $` 和 Hard Bootstrap 将上面的预测概率值替换为预测概率最高的分类。硬比软更类似于标签平滑。
例如:当真实标签y=0,噪声标签y=1,预测概率为0.7,0.3,β=0.9时,Bootstrap拟合出来的y实际上是0.1,0.9,这样会降低置信度错误的标签。让模型有机会学习其他标签。
当模型预测与标签一致时,y值不会改变,因此不会对正确样本产生太大影响。作者估计Hard Bootstrap的效果明显更好~`$L_{hard} = \sum (\beta y_i + (1-\beta) argmx(p_i)) log(p_i)$`pytorch实现如下。
版权声明:本文内容由互联网用户自发贡献,本站不拥有所有权,不承担相关法律责任。如果发现本站有涉嫌抄袭的内容,欢迎发送邮件 举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。
标签:
相关文章
06-06
06-18
06-18
06-17
06-18
06-18
06-18
06-17
最新文章
【玩转GPU】ControlNet初学者生存指南
【实战】获取小程序中用户的城市信息(附源码)
包雪雪简单介绍Vue.js:开学
Go进阶:使用Gin框架简单实现服务端渲染
线程池介绍及实际案例分享
JMeter 注释 18 - JMeter 常用配置组件介绍
基于Sentry的大数据权限解决方案
【云+社区年度征文集】GPE监控介绍及使用