【cs231n学习笔记(2017)】—— 线性分类

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Nicht_sehen/article/details/80520829

关于线性分类器的理解

基本表达式:

f ( x i , W , b ) = W x i + b

这个表达式有点眼熟啊,让我们来回忆一下机器学习里的线性回归基本表达式:
h θ ( x ) = θ T X + θ 0

是不是很类似?不过回归与分类是两类问题,线性回归一般是用 线性函数来构造模型,而线性分类一般采用 非线性函数来构造模型。

对表达式的理解

W为权重,b为偏差向量
举个例子(手绘渣图):
这里写图片描述

其中W就是表示对某个分类的喜爱,上图表示的是从猫,狗,船3类中识别船,将图片转化为黑白图,但是如果是彩色的呢?彩色要考虑R,G,B三色通道,以这个船为例,明显可以看出船在蓝色通道上有很多正权重,相应的在其他通道上就会有很多负权重。

这里还有另一种解释:

将图像看做高维度的点:既然图像被伸展成为了一个高维度的列向量,那么我们可以把图像看做这个高维度空间中的一个点(如果图片像素为32*32*3(彩色)=3072,则每张图像是3072维空间中的一个点)。整个数据集就是一个点的集合,每个点都带有1个分类标签。
既然定义每个分类类别的分值是权重和图像的矩阵乘,那么每个分类类别的分数就是这个空间中的一个线性函数的函数值。我们假设把3072维空间中的线性函数挤压到二维,那么就可以看看这些分类器在做什么了:
这里写图片描述
W的每一行都是一个分类类别的分类器。对于这些数字的几何解释是:如果改变其中一行的数字,会看见分类器在空间中对应的直线开始向着不同方向旋转。而偏差b,则允许分类器对应的直线平移。

损失函数

多类SVM损失函数

介绍常用的多类支持向量机(SVM)损失函数。SVM的损失函数想要SVM在正确分类上的得分始终比不正确分类上的得分高出一个边界值 Δ 。如下图所示:
这里写图片描述
第i个数据中包含图像 x i 的像素和代表正确类别的标签 y i 。评分函数输入像素数据,然后通过公式 f ( x i , W ) 来计算不同分类类别的分值,记为 s j 。针对第j个类别的得分就是第j个元素: s j = f ( x i , W ) j 。针对第i个数据的多类SVM的损失函数定义如下:

L i = j y i m a x ( 0 , s j s y i + Δ )

举个例子:假设有3个分类,并且得到了分值s=[13,-7,11]。其中第一个类别是正确类别,即 y i = 0 。同时假设 Δ =10。上面的公式是将所有不正确分类 j y i 加起来,所以我们得到两个部分:

L i = m a x ( 0 , 7 13 + 10 ) + m a x ( 0 , 11 13 + 10 )

第一部分正确分类的得分13与错误分类的得分-7的差为20,高于边界值10。而SVM只关心差距至少要大于10,更大的差值还是算作损失值为0。第二个部分计算[11-13+10]得到8。比10的边界值小,分差只有2,所以损失值等于8。简而言之,SVM的损失函数想要正确分类类别 y i 的分数比不正确类别分数高,而且至少要高 Δ 。如果不满足这点,就开始计算损失值。
对于线性评分,我们可以将损失函数的公式稍微改写一下:

L i = j y i m a x ( 0 , w j T x i w y i T x i + Δ )

正则化

对于以上的损失函数有一个很大的问题:W具有不确定性。什么意思呢?就是说可能有很多相似的W都能正确地分类所有的数据,举个例子:如果 W 能够正确分类所有数据。那么当 λ > 1 时,任何数乘 λ W 都能使得损失值为0,因为这个变化将所有分值的大小都均等地扩大了,所以它们之间的绝对差值也扩大了。
为了消除这种模糊性,我们加入一个正则项,最常见的正则化项是L2范数,它会对幅度很大的特征权重给很高的惩罚:

R ( W ) = k l W k , l 2

这样我们就能够给出完整的多类SVM损失函数了,它由两个部分组成:所有样例的的平均损失 L i 加上正则化损失。完整公式如下所示:

L = 1 N i L i + λ R ( W )

将其展开完整公式是:

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

python代码实现(无正则化)

'''
  - x: 代表图片像素输入的向量 (例如CIFAR-10中是3073 x 1,因为添加了bias项对应的1到x中)
  - y: 图片对应的类别编号(比如CIFAR-10中是0-9)
  - W: 权重矩阵 (例如CIFAR-10中是10 x 3073)
'''

#非向量化
def L_i(x, y, W):

  delta = 1.0 
  scores = W.dot(x) 
  correct_class_score = scores[y]
  D = W.shape[0] 
  loss_i = 0.0
  for j in xrange(D): 
    if j == y:
     continue
    loss_i += max(0, scores[j] - correct_class_score + delta)
  return loss_i

#半向量化
def L_i_vectorized(x, y, W):
  delta = 1.0
  scores = W.dot(x)
  margins = np.maximum(0, scores - scores[y] + delta)
  margins[y] = 0 
  loss_i = np.sum(margins)
  return loss_i

softmax分类器损失函数

softmax使用的损失函数为交叉熵损失函数,形式如下:

L i = l o g ( e f y i j e f j )

或着
L i = f y i + l o g ( j e f j )

f j 来表示分类评分向量f中的第j个元素,关于交叉熵损失函数这里不再赘述。
注意:编程实现softmax函数计算的时候,因为有指数函数的求和项所以数据会变得特别大,因此我们在分式的分子和分母都乘以一个常数:
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

通常将C设为 l o g C = m a x j f j ,就是平移向量f中的数值,使得最大值为0。代码实现:

f = np.array([123, 456, 789]) # 3个类别的预测示例
p = np.exp(f) / np.sum(np.exp(f)) 

# 对数据做一个平移,使输入的最大值为0:
f -= np.max(f) # f 变成 [-666, -333, 0]
p = np.exp(f) / np.sum(np.exp(f)) 

SVM与softmax

用一张图来表示它们的处理方式:
这里写图片描述
虽然损失值不同,但是注意它们之间并不存在可比性。

猜你喜欢

转载自blog.csdn.net/Nicht_sehen/article/details/80520829