从图像到标签分值的映射
一个线性映射:
f ( x i , W , b ) = W x i + b \displaystyle f(x_i,W,b)=Wx_i+b f(xi,W,b)=Wxi+b
其中,参数 W W W 为权重(weights), b b b 称为偏差向量(bias vector)
一个将图像映射到分类分值的例子:
-
为了便于可视化,假设图像只有4个像素值,有3个分类。
-
首先将图像像素拉伸为一个列向量,与 W W W 进行矩阵乘,再加上偏置项 b b b,得到各个分类的分值。
-
需要注意的是,由于权值没有训练到位,猫分类的分值非常低。
多类 SVM 分类器
针对第 i i i 个数据的 j j j 类 SVM 的损失函数定义如下:
L i = ∑ j ̸ = y i m a x ( 0 , s j − s y i + Δ ) \displaystyle L_i=\sum_{j\not=y_i}max(0,s_j-s_{y_i}+\Delta) Li=j̸=yi∑max(0,sj−syi+Δ)
使用多类 SVM 分类时,正确分类的分数需要比其他不正确的分类分数高出 边界值 delta( Δ \Delta Δ)。其他分类分数进入了红色的区域时,就开始计算损失。在红色区域之前,损失值为0。
SVM 评分函数中,将输出 s j = f ( x i , W ) j s_j=f(x_i,W)_j sj=f(xi,W)j 作为第 i i i 个数据针对第 j j j 个类别的得分,所以分类损失的详细定义为:
L i = ∑ j ̸ = y i m a x ( 0 , w j T x i − w y i T x i + Δ ) \displaystyle L_i=\sum_{j\not=y_i}max(0,w^T_jx_i-w^T_{y_i}x_i+\Delta) Li=j̸=yi∑max(0,wjTxi−wyiTxi+Δ)
加上正则化项:
L = 1 N ∑ i ∑ j ̸ = y i [ m a x ( 0 , f ( x i ; W ) j − f ( x i ; W ) y i + Δ ) ] + λ ∑ k ∑ l W k , l 2 L=\frac{1}{N}\sum_i\sum_{j\not=y_i}[max(0,f(x_i;W)_j-f(x_i;W)_{y_i}+\Delta)]+\lambda \sum_k \sum_l W^2_{k,l} L=N1i∑j̸=yi∑[max(0,f(xi;W)j−f(xi;W)yi+Δ)]+λk∑l∑Wk,l2
其中:
-
m a x ( 0 , − ) max(0,-) max(0,−) 函数,它常被称为 折叶损失(hinge loss)。有时候会听到人们使用 平方折叶损失SVM(即 L2-SVM),它使用的是 m a x ( 0 , − ) 2 max(0,-)^2 max(0,−)2,将更强烈(平方地而不是线性地)地惩罚过界的边界值。可以通过交叉验证来决定到底使用哪个。
-
在绝大多数情况下设置 Δ = 1.0 \Delta=1.0 Δ=1.0 都是安全的。超参数 Δ \Delta Δ 和 λ \lambda λ 一起控制损失函数中的数据损失(data loss)和正则化损失(regularization loss)之间的权衡。
-
不同分类分值之间的边界的具体值(比如 Δ = 1 \Delta=1 Δ=1 或 Δ = 100 \Delta=100 Δ=100)从某些角度来看是没意义的,因为权重自己就可以控制差异变大和缩小。也就是说,真正的权衡是我们允许权重能够变大到何种程度,通过正则化强度 λ \lambda λ 来控制,详见:正则化方法 。
Softmax 分类器
Softmax 分类器可以理解为 逻辑回归分类器 面对多个分类的一般化归纳,输出归一化的分类概率。
在Softmax分类器中,函数映射 f ( x i ; W ) = W x i f(x_i;W)=Wx_i f(xi;W)=Wxi 保持不变,但将这些评分值视为每个分类的未归一化的对数概率,并且将折叶损失(hinge loss)替换为交叉熵损失(cross-entropy loss)。公式如下:
L i = − l o g ( e f y i ∑ j e f j ) L_i=-log(\frac{e^{f_{y_i}}}{\sum_je^{f_j}}) Li=−log(∑jefjefyi)
或等价的:
L i = − f y i + l o g ( ∑ j e f j ) L_i=-f_{y_i}+log(\sum_je^{f_j}) Li=−fyi+log(j∑efj)
其中:
-
使用 f j f_j fj 来表示分类评分向量 f f f 中的第 j j j 个元素。
-
函数 f j ( z ) = e z j ∑ k e z k f_j(z)=\frac{e^{z_j}}{\sum_ke^{z_k}} fj(z)=∑kezkezj 被称作 softmax 函数,其输入值是一个向量,向量中元素为任意实数的评分值( z z z 中的),函数对其进行压缩,输出一个向量,其中每个元素值在 0 到 1 之间,且所有元素之和为 1。
对数的基本性质:
- 函数拆分:
ln ( a b ) = ln ( a ) + ln ( b ) \ln(ab)=\ln(a)+\ln(b) ln(ab)=ln(a)+ln(b)- log( x x x) vs log( 1 / x 1/x 1/x) :
l o g ( x ) = − l o g ( 1 / x ) log(x) = -log(1/x) log(x)=−log(1/x)
图中,蓝线为 ln( 1 / x 1/x 1/x) ,黑线为 ln( x x x)
数值归一化:
-
编程实现 softmax 函数计算的时候,中间项 e f y i e^{f_{y_i}} efyi 和 ∑ j e f j \sum_j e^{f_j} ∑jefj 因为存在指数函数,所以数值可能非常大。
-
除以大数值可能导致数值计算的不稳定,所以使用归一化非常重要。如果在分式的分子和分母都乘以一个常数 C C C,并把它变换到求和之中,就能得到一个从数学上等价的公式:
e f y i ∑ j e f j = C e f y i C ∑ j e f j = e f y i + l o g C ∑ j e f j + l o g C \frac{e^{f_{y_i}}}{\sum_je^{f_j}}=\frac{Ce^{f_{y_i}}}{C\sum_je^{f_j}}=\frac{e^{f_{y_i}+logC}}{\sum_je^{f_j+logC}} ∑jefjefyi=C∑jefjCefyi=∑jefj+logCefyi+logC
- 代码实现如下:
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 分类器使用的是 折叶损失(hinge loss),有时候又被称为 最大边界损失(max-margin loss)。
-
Softmax 分类器使用的是 交叉熵损失(corss-entropy loss)。
对分类分值的不同解释:
-
针对一个数据点,两个分类器都计算了同样的分值向量 f f f
-
SVM分类器将 f f f 看做是分类评分,它的损失函数鼓励正确的分类(本例中是蓝色的类别2)的分值比其他分类的分值高出至少一个边界值。
-
Softmax分类器将 f f f 看做是每个分类没有归一化的对数概率,鼓励正确分类的归一化的对数概率变高,其余的变低。
-
SVM的最终的损失值是 1.58,Softmax 的最终的损失值是 0.452,但要注意这两个数值没有可比性。只在给定同样数据,在同样的分类器的损失值计算中,它们才有意义。
在实际使用中,SVM 和 Softmax 经常是相似的:
-
通常说来,两种分类器的表现差别很小。
-
相对于 Softmax 分类器,SVM 更加局部目标化(local objective),这既可以看做是一个特性,也可以看做是一个劣势。
-
SVM 对于各个分类的得分细节并不关心:分数是 [ 10 , − 100 , − 100 ] [10, -100, -100] [10,−100,−100] 或者 [ 10 , 9 , 9 ] [10, 9, 9] [10,9,9],对于 SVM 来说没什么不同,只要分差超过边界值,那么损失值就等于 0,不会超过限制去细微地操作具体分数。
-
对于 softmax 分类器,情况则不同。对于 [ 10 , 9 , 9 ] [10, 9, 9] [10,9,9] 来说,计算出的损失值就远远高于 [ 10 , − 100 , − 100 ] [10, -100, -100] [10,−100,−100] 的。换句话来说,softmax 分类器对于分数是永远不会满意的。