《将“softmax+交叉熵”推广到多标签分类问题》中,我们提出了一个用于多标签分类的损失函数:
\begin{equation}\log \left(1 + \sum\limits_{i\in\Omega_{neg}} e^{s_i}\right) + \log \left(1 + \sum\limits_{j\in\Omega_{pos}} e^{-s_j}\right)\label{eq:original}\end{equation}
这个损失函数有着单标签分类中“Softmax+交叉熵”的优点,即便在正负类不平衡的依然能够有效工作。但从这个损失函数的形式我们可以看到,它只适用于“硬标签”,这就意味着label smoothing、mixup等技巧就没法用了。本文则尝试解决这个问题,提出上述损失函数的一个软标签版本。

巧妙联系 #

多标签分类的经典方案就是转化为多个二分类问题,即每个类别用sigmoid函数$\sigma(x)=1/(1+e^{-x})$激活,然后各自用二分类交叉熵损失。当正负类别极其不平衡时,这种做法的表现通常会比较糟糕,而相比之下损失$\eqref{eq:original}$通常是一个更优的选择。

在之前文章的评论区中,读者 @wu.yan 揭示了多个“sigmoid+二分类交叉熵”与式$\eqref{eq:original}$的一个巧妙的联系:多个“sigmoid+二分类交叉熵”可以适当地改写成
\begin{equation}\begin{aligned}
&\,-\sum_{j\in\Omega_{pos}}\log\sigma(s_j)-\sum_{i\in\Omega_{neg}}\log(1-\sigma(s_i))\\
=&\,\log\prod_{j\in\Omega_{pos}}(1+e^{-s_j})+\log\prod_{i\in\Omega_{neg}}(1+e^{s_i})\\
=&\,\log\left(1+\sum_{j\in\Omega_{pos}}e^{-s_j}+\cdots\right)+\log\left(1+\sum_{i\in\Omega_{neg}}e^{s_i}+\cdots\right)
\end{aligned}\label{eq:link}\end{equation}
对比式$\eqref{eq:original}$,我们可以发现式$\eqref{eq:original}$正好是上述多个“sigmoid+二分类交叉熵”的损失去掉了$\cdots$所表示的高阶项!在正负类别不平衡时,这些高阶项占据了过高的权重,加剧了不平衡问题,从而效果不佳;相反,去掉这些高阶项后,并没有改变损失函数的作用(希望正类得分大于0、负类得分小于0),同时因为括号内的求和数跟类别数是线性关系,因此正负类各自的损失差距不会太大。

形式猜测 #

这个巧妙联系告诉我们,要寻找式$\eqref{eq:original}$的软标签版本,可以尝试从多个“sigmoid+二分类交叉熵”的软标签版本出发,然后尝试去掉高阶项。所谓软标签,指的是标签不再是0或1,而是0~1之间的任意实数都有可能,表示属于该类的可能性。而对于二分类交叉熵,它的软标签版本很简单:
\begin{equation}-t\log\sigma(s)-(1-t)\log(1-\sigma(s))\end{equation}
这里$t$就是软标签,而$s$就是对应的打分。模仿过程$\eqref{eq:link}$,我们可以得到
\begin{equation}\begin{aligned}
&\,-\sum_i t_i\log\sigma(s_i)-\sum_i (1-t_i)\log(1-\sigma(s_i))\\
=&\,\log\prod_i(1+e^{-s_i})^{t_i}+\log\prod_i (1+e^{s_i})^{1-t_i}\\
=&\,\log\prod_i(1+t_i e^{-s_i} + \cdots)+\log\prod_i (1+(1-t_i)e^{s_i}+\cdots)\\
=&\,\log\left(1+\sum_i t_i e^{-s_i}+\cdots\right)+\log\left(1+\sum_i(1-t_i)e^{s_i}+\cdots\right)
\end{aligned}\end{equation}
如果去掉高阶项,那么就得到
\begin{equation}\log\left(1+\sum_i t_i e^{-s_i}\right)+\log\left(1+\sum_i(1-t_i)e^{s_i}\right)\label{eq:soft}\end{equation}
它就是式$\eqref{eq:original}$的软标签版本的候选形式,可以发现当$t_i\in\{0,1\}$时,正好是退化为式$\eqref{eq:original}$的。

证明结果 #

就目前来说,式$\eqref{eq:soft}$顶多是一个“候选”形式,要将它“转正”,我们需要证明在$t_i$为0~1浮点数时,式$\eqref{eq:soft}$能学出有意义的结果。所谓有意义,指的是理论上能够通过$s_i$来重构$t_i$的信息($s_i$是模型预测结果,$t_i$是给定标签,所以$s_i$能重构$t_i$是机器学习的目标)。

为此,我们记式$\eqref{eq:soft}$为$l$,并求$s_i$的偏导数:
\begin{equation}\frac{\partial l}{\partial s_i} = \frac{-t_i e^{-s_i}}{1+\sum\limits_i t_i e^{-s_i}}+\frac{(1-t_i)e^{s_i}}{1+\sum\limits_i(1-t_i)e^{s_i}}\end{equation}
我们知道$l$的最小值出现在所有$\frac{\partial l}{\partial s_i}$都等于0时,直接去解方程组$\frac{\partial l}{\partial s_i}=0$并不容易,但笔者留意到一个神奇的“巧合”:当$t_i e^{-s_i}=(1-t_i)e^{s_i}$时,每个$\frac{\partial l}{\partial s_i}$自动地等于0!所以$t_i e^{-s_i}=(1-t_i)e^{s_i}$应该就是$l$的最优解了,解得
\begin{equation}t_i = \frac{1}{1+e^{-2s_i}}=\sigma(2s_i)\end{equation}
这是一个很漂亮的结果,它告诉我们几个信息:

1、式$\eqref{eq:soft}$确实是式$\eqref{eq:original}$合理的软标签推广,它能通过$s_i$完全重建$t_i$的信息,其形式也刚好与sigmoid相关;

2、如果我们要将结果输出为0~1的概率值,那么正确的做法应该是$\sigma(2s_i)$而不是直觉中的$\sigma(s_i)$;

3、既然最后的概率公式也具有sigmoid的形式,那么反过来想,也可以理解为我们依旧还是在学习多个sigmoid激活的二分类问题,只不过损失函数换成了式$\eqref{eq:soft}$。

实现技巧 #

式$\eqref{eq:soft}$的实现可以参考bert4keras的代码multilabel_categorical_crossentropy,其中有个小细节值得跟大家一起交流一下。

首先,我们将式$\eqref{eq:soft}$可以等价地改写成
\begin{equation}\log\left(1+\sum_i e^{-s_i + \log t_i}\right)+\log\left(1+\sum_i e^{s_i + \log (1-t_i)}\right)\label{eq:soft-log}\end{equation}
所以看上去,只需要将$\log t_i$加到$-s_i$、将$\log(1-t_i)$加到$s_i$上,补零后做常规的$\text{logsumexp}$即可。但实际上,$t_i$是有可能取到$0$或$1$的,对应的$\log t_i$或$\log(1-t_i)$就是负无穷,而框架无法直接处理负无穷,因此通常在$\log$之前需要clip一下,即选定$\epsilon > 0$后定义
\begin{equation}\text{clip}(t)=\left\{\begin{aligned}&\epsilon, &t < \epsilon \\
&t, &\epsilon\leq t\leq 1-\epsilon\\
&1-\epsilon, &t > 1-\epsilon\end{aligned}\right.\end{equation}

但这样一clip,问题就来了。由于$\epsilon$不是真的无穷小,比如$\epsilon=10^{-7}$,那么$\log\epsilon$大约是$-16$左右;而像GlobalPointer这样的场景中,我们会提前把不合理的$s_i$给mask掉,方式是将对应的$s_i$置为一个绝对值很大的负数,比如$-10^7$;然而我们再看式$\eqref{eq:soft-log}$,第一项的求和对象是$e^{-s_i + \log t_i}$,所以$-10^7$就会变成$10^7$,如果$t_i$没有clip,那么理论上$\log t_i$是$\log 0 = -\infty$,可以把$-s_i + \log t_i$重新变回负无穷,但刚才我们已经看到进行了clip之后的$\log t_i$顶多就是$-16$,远远比不上$-s_i$的$10^7$,所以$-s_i + \log t_i$依然是一个大正数。

为了解决这个问题,我们不止要对$t_i$进行clip,我们还要找出原本小于$\epsilon$的$t_i$,手动将对应的$-s_i$置为绝对值很大的负数,同样还要找出大于$1-\epsilon$的$t_i$,将对应的$s_i$置为绝对值很大的负数,这样做就是将小于$\epsilon$的按照绝对等于0额外处理,将大于$1-\epsilon$的按照绝对等于1处理。

文章小结 #

本文主要将笔者之前提出的多标签“Softmax+交叉熵”推广到软标签场景,有了对应的软标签版本后,我们就可以将它与label smoothing、mixup等技巧结合起来了,像GlobalPointer等又可以多一个炼丹方向。

转载到请包括本文地址:https://kexue.fm/archives/9064

更详细的转载事宜请参考:《科学空间FAQ》

如果您还有什么疑惑或建议,欢迎在下方评论区继续讨论。

如果您觉得本文还不错,欢迎分享/打赏本文。打赏并非要从中获得收益,而是希望知道科学空间获得了多少读者的真心关注。当然,如果你无视它,也不会影响你的阅读。再次表示欢迎和感谢!

如果您需要引用本文,请参考:

苏剑林. (May. 07, 2022). 《多标签“Softmax+交叉熵”的软标签版本 》[Blog post]. Retrieved from https://kexue.fm/archives/9064

@online{kexuefm-9064,
        title={多标签“Softmax+交叉熵”的软标签版本},
        author={苏剑林},
        year={2022},
        month={May},
        url={\url{https://kexue.fm/archives/9064}},
}