线性分类器分3个小节介绍,本章内容接上一章:(二)线性分类器-中
Softmax分类器
除了上一节介绍的SVM分类器,还有一个常用的分类器就是softmax分类器。SVM分类器的输出是每个类别的评分,但从直观上,因为无定标,所以很难解释。而softmax分类器不同,它的输出更加直观。换句话说,SVM分类器得到的是一个得分数值。Softmax得到的是一个概率值。在Softmax分类器中,函数映射保持不变,但将这些评分值视为每个分类的未归一化的对数概率,并且将折叶损失(hinge loss)替换为交叉熵损失(cross-entropy loss)。公式如下:
举例:
类别 | 分值 | 以这些数值做指数函数的幂 | 归一化处理得到每个分类的概率x | 交叉熵损失 -log(x) |
---|---|---|---|---|
猫 | 3.2 | 24.5 | 0.13 | -log(0.13)=0.89 |
狗 | 5.1 | 164 | 0.87 | -log(0.87) |
人 | -1.7 | 0.18 | 0.00 | -log(0) |
数值稳定性
在计算softmax函数的时候,我们可能会遇到一个问题:有些类的分值可能很高,再取指数函数的幂,可能会导致数值爆炸的问题。我们的方法是做归一化,在分式的分子和分母都乘以一个常数,并把它变换到求和之中:
的值可自由选择,不会影响计算结果,通过使用这个技巧可以提高计算中的数值稳定性。通常将设为。该技巧简单地说,就是应该将向量中的数值进行平移,使得最大值为0。代码实现如下:
f = np.array([123, 456, 789]) # 例子中有3个分类,每个评分的数值都很大
p = np.exp(f) / np.sum(np.exp(f)) # 不妙:数值问题,可能导致数值爆炸
# 那么将f中的值平移到最大值为0:
f -= np.max(f) # f becomes [-666, -333, 0]
p = np.exp(f) / np.sum(np.exp(f)) # 现在OK了,将给出正确结果
SVM分类器与Softmax分类器的比较
实际上,两类分类器的表现是相当的。一定要对比一下的话: SVM其实并不在乎每个类别得到的绝对得分大小,举个例子说,我们现在对三个类别,算得的得分是[10, -2, 3],实际第一类是正确结果,而设定Δ=1,那么10-3=7已经比1要大很多了,那对SVM而言,它觉得这已经是一个很标准的答案了,完全满足要求了,不需要再做其他事情了,结果是 [10, -100, -100] 或者 [10, 9, 9],它都是满意的。
然而对于Softmax而言,不是这样的, [10, -100, -100] 和 [10, 9, 9]映射到概率域,计算得到的交叉熵损失是有很大差别的。所以Softmax是一个永远不会满足的分类器,在每个得分计算到的概率基础上,它总是觉得可以让概率分布更接近标准结果一些,交叉熵损失更小一些。
现在我们知道了如何基于参数,将数据集中的图像映射成为分类的评分,也知道了两种不同的损失函数,它们都能用来衡量算法分类预测的质量。但是,如何高效地得到能够使损失值最小的参数呢?这个求得最优参数的过程被称为最优化,将在下节进行介绍。