最大似然损失与最小化交叉熵损失的异曲同工之妙

一、逻辑回归与softmax函数

在逻辑回归问题中,我们使用sigmoid函数将线性模型Wx+b的连续值映射到0~1的区间上,设置一定的阈值(二分类问题,大于阈值设置为1,小于阈值设置为0),从而得到某个类别的概率。如果将这个问题泛化,推广到多分类问题上(如图片的多分类),我们可以使用softmax函数将其输出单元从一个变成多个。

1.sigmoid函数

sigmoid函数是个很漂亮的S形,其作用可以将取值的范围友好的表示成[0,1],而且受异常数据的影响较小,所以我们用sigmoid函数来包装就能很好的解决模型取值范围的问题。其数学公式如下:

f(x)=\frac{1}{1+e^{-x}}

其图像如下图所示:

最大似然损失与最小化交叉熵损失的异曲同工之妙_第1张图片

2.softmax函数

多分类问题需要得到离散的预测输出,一个简单的方法是将输出值o_{i}当作预测类别是i的置信度,并将值最大的输出所对应的类别作为预测输出,即输出argmax_{i}o_{i}。然而,这样存在两个问题。一方面,由于输出值的范围不确定,难以从直观上判断这些值的意义。另一方面,由于真实标签是离散值,这些离散值与不确定范围的属猪值之间的误差难以衡量。

softmax函数解决了以上两个问题。假设模型的输出为a_{1},a_{2},...,a_{C}。对于每一个样本数据,它属于类别i的概率为:

y_{i}=\frac{e^{a_{i}}}{\sum_{k=1}^{C}e^{a_{k}}}

 

二、最大似然损失函数

一般来说,对模型的训练实质上就是对损失函数进行优化。在分类问题中,我们一般使用最大似然估计来构造损失函数。对于输入的x,其对应的类标签为t,目标是找到这样的\theta使得p(t|x)最大。

在二分类的问题中,一般有:

p(t|x)=(y)^{t}(1-y)^{1-t}

其中,y=f(x)是模型预测的概率值,t是样本对应的类标签。

将问题泛华为更一般的情况吗,对于多分类问题有:

p(t|x)=\prod_{i=1}^{C}P(t_{i}|x)^{t_{i}}=\prod_{i=1}^{C}y_{i}^{t_{i}}

另外需要注意的是连乘可能会导致最终结果接近0.一般会对似然函数取对数,然后变成最小化对数似然函数:

loss=-logp(t|x)=-log\prod_{i=1}^{C}y_i^{t_{i}}=-\sum_{i=1}^{C}t_{i}log(y_{i})

三、最小化交叉熵损失函数

softmax运算将输出变换成一个合法的类别预测分布。实际上,真实标签也可以用类别分布表达:对于样本i,我们构造向量y^{(i)}\in \mathbb{R}^{q},使其第y^{(i)}(样本i类别的离散数值)个元素为1,其余为0(类似于onehot编码)。这样我们的训练目标可以设为使预测概率分布\hat{y}^{(i)}尽可能接近真实的标签概率分布y^{(i)}

我们可以使用平方损失函数||\hat{y}^{(i)} - y^{(i)}||^{2}/2。然而,想要预测分类正确,我们并不需要预测概率完全等于标签概率。例如,在图像分类的例子中,如果y^{(i)}=3,那么我们只需要\hat{y}^{(i)}_{3}比其他两个预测值\hat{y}^{(i)}_{1}\hat{y}^{(i)}_{2}大就行了。 即使\hat{y}^{(i)}_{3} 值为0.6,不管其他两个预测值为多少,类别预测均正确。而平⽅损失则过于严格,例如\hat{y}^{(i)}_{1}\hat{y}^{(i)}_{2}= 0.2⽐\hat{y}^{(i)}_{1} = 0,\hat{y}^{(i)}_{2} = 0.4的损失要小很多,虽然两者都有同样正确的分类预测结果.

改善上述问题的一个方法就是使用更适合衡量两个概率分布差异的测量函数。其中,交叉熵(cross entropy)是一个常用的方法:

H=-\sum_{j=1}^{C}y_{j}^{(i)}\mathrm{log} \hat{y}_{j}^{(i)}

其中C是类别标签数,y^{(i)}_{j}是样本i的第j类别的数值元素为1,其余为0。

通过上式我们发现,交叉熵只关心正确类别的预测概率,因为只要其值足够大,就可以确保分类结果正确。另一方面看,最小化交叉熵损失函数等价于最大似然损失函数。

----------------------------------------------------------

对于给定训练数据集的样本数为n,交叉损失函数定义为:

loss=\frac{1}{n}\sum_{i=1}^{n}H=-\frac{1}{n}\sum_{i=1}^{n}\sum_{j=1}^{C}y_{j}^{(i)}\mathrm{log} \hat{y}_{j}^{(i)}

----------------------------------------------------------

疑问1:直接按照softmax运算的数学定义来实现softmax函数,会有什么问题?

:这里涉及到softmax的计算与数值稳定性。在python中,我们一般按照如下方式实现softmax函数:

def softmax(x):
    exp_x = np.exp(x)
    return exp_x / np.sum(exp_x)

如果我们传入数值很大的数,如1000,这个时候exp(x)函数就回溢出。

一种简单有效的方法就是让exp(x)的x值不那么大或者那么小,在softmax函数的分式上下分别乘以一个非零常数:

y_{i}=\frac{e^{a_{i}}}{\sum_{k=1}^{C}e^{a_{k}}}=\frac{Ee^{a_{i}}}{\sum_{k=1}^{C}Ee^{a_{k}}}=\frac{e^{a_{i}+log(E)}}{\sum_{k=1}^{C}e^{a_{k}+log(E)}}=\frac{e^{a_{i}+F}}{\sum_{k=1}^{C}e^{a_{k}+F}}

这里的log(E)是个常数,可以令它等于F。加上常数F之后,等式与原来还是相等的,所以我们可以考虑怎么选取常数F。我们的想法是让所有的输入在0附近,这样的值e^{a_{i}}不会太大,所以可以让的值F为:

F=-max(a_{1}, a_{2},...,a_{C})

这样子将所有的输入平移到0附近(当然需要假设所有输入之间的数值上较为接近),同时,除了最大值,其他输入值都被平移成负数,e为底的指数函数,越小越接近0,这种方式比得到nan的结果更好。

 

 

你可能感兴趣的:(100天搞定机器学习)