关于线性分类器的理解
基本表达式:
这个表达式有点眼熟啊,让我们来回忆一下机器学习里的线性回归基本表达式:
是不是很类似?不过回归与分类是两类问题,线性回归一般是用 线性函数来构造模型,而线性分类一般采用 非线性函数来构造模型。
对表达式的理解
W为权重,b为偏差向量
举个例子(手绘渣图):
其中W就是表示对某个分类的喜爱,上图表示的是从猫,狗,船3类中识别船,将图片转化为黑白图,但是如果是彩色的呢?彩色要考虑R,G,B三色通道,以这个船为例,明显可以看出船在蓝色通道上有很多正权重,相应的在其他通道上就会有很多负权重。
这里还有另一种解释:
将图像看做高维度的点:既然图像被伸展成为了一个高维度的列向量,那么我们可以把图像看做这个高维度空间中的一个点(如果图片像素为32*32*3(彩色)=3072,则每张图像是3072维空间中的一个点)。整个数据集就是一个点的集合,每个点都带有1个分类标签。
既然定义每个分类类别的分值是权重和图像的矩阵乘,那么每个分类类别的分数就是这个空间中的一个线性函数的函数值。我们假设把3072维空间中的线性函数挤压到二维,那么就可以看看这些分类器在做什么了:
W的每一行都是一个分类类别的分类器。对于这些数字的几何解释是:如果改变其中一行的数字,会看见分类器在空间中对应的直线开始向着不同方向旋转。而偏差b,则允许分类器对应的直线平移。
损失函数
多类SVM损失函数
介绍常用的多类支持向量机(SVM)损失函数。SVM的损失函数想要SVM在正确分类上的得分始终比不正确分类上的得分高出一个边界值
。如下图所示:
第i个数据中包含图像
的像素和代表正确类别的标签
。评分函数输入像素数据,然后通过公式
来计算不同分类类别的分值,记为
。针对第j个类别的得分就是第j个元素:
。针对第i个数据的多类SVM的损失函数定义如下:
举个例子:假设有3个分类,并且得到了分值s=[13,-7,11]。其中第一个类别是正确类别,即 。同时假设 =10。上面的公式是将所有不正确分类 加起来,所以我们得到两个部分:
第一部分正确分类的得分13与错误分类的得分-7的差为20,高于边界值10。而SVM只关心差距至少要大于10,更大的差值还是算作损失值为0。第二个部分计算[11-13+10]得到8。比10的边界值小,分差只有2,所以损失值等于8。简而言之,SVM的损失函数想要正确分类类别 的分数比不正确类别分数高,而且至少要高 。如果不满足这点,就开始计算损失值。
对于线性评分,我们可以将损失函数的公式稍微改写一下:
正则化
对于以上的损失函数有一个很大的问题:W具有不确定性。什么意思呢?就是说可能有很多相似的W都能正确地分类所有的数据,举个例子:如果
能够正确分类所有数据。那么当
时,任何数乘
都能使得损失值为0,因为这个变化将所有分值的大小都均等地扩大了,所以它们之间的绝对差值也扩大了。
为了消除这种模糊性,我们加入一个正则项,最常见的正则化项是L2范数,它会对幅度很大的特征权重给很高的惩罚:
这样我们就能够给出完整的多类SVM损失函数了,它由两个部分组成:所有样例的的平均损失 加上正则化损失。完整公式如下所示:
将其展开完整公式是:
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使用的损失函数为交叉熵损失函数,形式如下:
或着
来表示分类评分向量f中的第j个元素,关于交叉熵损失函数这里不再赘述。
注意:编程实现softmax函数计算的时候,因为有指数函数的求和项所以数据会变得特别大,因此我们在分式的分子和分母都乘以一个常数:
通常将C设为 ,就是平移向量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
用一张图来表示它们的处理方式:
虽然损失值不同,但是注意它们之间并不存在可比性。