斯坦福大学深度学习公开课cs231n学习笔记(2)线性分类器及最优化

来源:互联网 发布:减速器说明书计算软件 编辑:程序博客网 时间:2024/04/27 17:46

图像分类

图像分类即是从已有的分类标签集中选择一个分配给一张图像。K近邻算法可以进行分裂,但存在不足之处:

(1)分类器必须记住所有训练数据并将其存储起来,以便于未来测试数据用于比较。这在存储空间上是低效的。
(2)对一个测试图像进行分类需要和所有训练图像作比较,算法计算资源耗费高。

针对不足,需要更强大的方法来解决图像分类问题,并可以自然延伸到神经网络和卷积神经网络。这种方法主要由两部分组成:

一是评分函数(score function),它是原始图像数据到类别分值的映射。

二是损失函数(loss function),它是用来量化预测分类标签的得分与真实标签之间一致性的。

该方法可转化为一个最优化问题,在最优化过程中,通过更新评分函数的参数来最小化损失函数值。

线性分类器

其映射函数为:


其中矩阵W和列向量b为该函数的参数(parameters),参数W称为权重(weights);b称为偏差向量(bias vector),它影响输出数值,但不和原始数据xi产生关联。

说明:
1.通过矩阵乘法Wxi能并行评估不同的分类器(每个分类器对应一个分类),其中每个类的分类器就是W的一个行向量。
2.参数W和b是可以控制改变的。目标是通过设置这些参数,使计算出来的分类分值情况和训练集中图像数据的真实类别标签相符。
3.通过训练数据学习参数W和b,当训练完成后训练数据可以丢弃,只留下学习到的参数。
4.分类时只需要做矩阵乘法和矩阵加法就能对测试数据进行分类。

理解线性分类器

线性分类器计算图像中3个颜色通道中像素值与权重的矩阵乘积,得到分类分值。权重值对于图像中的某些位置的某些颜色,使得函数表现出喜好或者厌恶。就像“船”分类是被大量蓝色包围(对应的就是水),那么“船”分类器在蓝色通道上的权重就会有很多的正权重(从而提高“船”分类的分值),而在绿色和红色通道上的权重出现很多负值(从而降低“船”分类的分值)。


上面是图像映射分类的例子,为了便于可视化,假设图像只有4个像素(都是黑白像素,不考虑彩色通道),并且有3个分类(红色代表猫,绿色代表狗,蓝色代表船,这里的红、绿和蓝代表的是分类信息)。首先将图像像素拉伸成一个列向量,与W矩阵相乘,与b矩阵相加,然后可以得到各个分类的分值。当然这个W并不好,需要优化,因为猫分类的分值很低,狗的分值却很高,此时算法会判定输入图像是一只狗。

将图像看做高维度的点

既然图像被拉伸成一个高维度的列向量,那么我们可以把图像看成高维度空间中的一个点。此时,所有像素就是点的集合,并且每个点都有1个分类标签。分类器通过变换把高维度挤压到二维。



如上图所示,其中每张图像都是一个点,共有3个分类器。以红色汽车分类器为例,红线表示汽车分类分值为0的点的集合,红色箭头表示分值上升的方向,即红线右边的点的分值为正,且线性升高。红线左边的点分值为负,且线性降低。对应到分类器,W的每一行都是一个分类类别的分类器,如果改变其中一行的数字,分类器在空间中对应的直线会向着不同的方向旋转;偏差b则使得分类器对应的直线平移。

偏差和权重的合并技巧

下面的方法能够将参数W和b合二为一。因为分开处理权重参数W和偏差参数b有点笨拙,通常可以把两个参数放到同一个矩阵中,但需要x_i向量就要增加一个维度,这个维度的数值设为1,变化过程如下:


线性分类器看做模板匹配

权重W的另一个解释是它的每一行对应着一个分类的模板(也叫作原型)。每张图像通过内积运算得到一个分值,来比较图像和哪个模板最相似。这可以理解为在变相地高效使用KNN,区别是分类器没有使用所有的训练图像来比较,而是将每个类别用一张通过学习得到的图片表示,但它不是训练集中的某一张。然后使用内积计算向量间的距离,而不是使用L1或L2距离。

图像数据预处理

一般图像的像素值范围为0到255。在图像分类中,图像的每个像素看做一个特征,通常采取归一化操作,即对每个特征减去平均值来中心化数据。将训练集中所有的图像计算出一个平均值,然后每个图像都减去这个平均值,此时像素值范围为[-127, 127],然后将所有数值分布的区间变为[-1, 1]。

损失函数

在对一只猫图像分类的例子中,通过权重参数分别计算出“猫”,“狗”,“船”三个类别的分数。例子中权重值非常差,因为猫分类的得分很低,而狗和船的分值却比较高。分类时使用损失函数(Loss Function)(也叫代价函数Cost Function或目标函数Objective Function)来衡量结果的不满意程度,当与真实结果差异越大时,损失函数输出越大,反之越小。

多类支持向量机损失函数

损失函数的形式有很多种,多类支持向量机损失函数是常用的一种。SVM损失函数是使得正确分类的得分比错误分类的得分高出一个边界值Δ。第i个数据中包含图像像素x_i和类别标签y_i。评分函数输入像素数据,然后通过公式f(xi,W)计算不同类别的分值。多类SVM的损失函数定义如下:

核心思想:SVM损失函数如果想要得到正确分类,类别y_i的分值比错误类别分值至少要高Δ,如果不满足,就计算损失值。
实例:假设有3个分类和对应的分值s=[13,-7,11]。其中第一个类别是正确类别,即y_i=0。同时假设Δ是10,上面的公式将所有不正确分类相加,得到:

其中,-7-13+10=-10,经过max(0,-)处理后结果为0,即第一部分类别分数和标签的损失值是0,因为正确分类的得分13与错误分类的得分-7的差为20,高于边界值10。而SVM只需要差距至少大于10,再大的差值损失值还是算作0。第二部分[11-13+10]=8。虽然正确分类分值比错误分类高(13>11),但是比分界值10小,分差为2,损失值等于8。
那么对于线性评分函数(f(xi,W)=W.xi),需将损失函数的公式改为如下:

其中wj是权重W的第j行,被改为列向量。

注:max(0,-)函数被称为折叶损失(hinge loss)。有时候也会使用平方折叶损失SVM(即L2-SVM),对应的是max(0,-)^2,即更强地惩罚过界的边界值。

正则化

假设有一个数据集和权重集W能够正确地分类数据(即所有L_i=0),但这个W并不唯一:可能有很多相似的W都能对数据进行正确地分类。例如,如果W能够正确分类所有数据,即对于每个数据,损失值=0,当λ>1时,任何数乘 λ都使得损失值=0,这个变化将所有分值均等地扩大,所以绝对值也扩大了。
所以希望能对某些特定的权重W添加一些偏好,而对其他权重则不添加,以此来消除模糊性。实现方法是在损失函数基础上增加一个正则化惩罚(regularization penalty)R(W)。最常用的正则化惩罚是L2范式,它通过对所有参数进行逐元素的平方惩罚来抑制大数值的权重。


注意的是,正则化函数不是针对数据,它仅基于权重。完整的多类SVM损失函数由两个部分组成:数据损失(data loss),即所有数据样本的的平均损失Li,和正则化损失(regularization loss)。公式如下:

,详细张开为:


其中,N是训练集的数据量。将正则化惩罚添加到损失函数里面,并用超参数λ  计算权重。该超参数无法简单确定,需要通过交叉验证来获取。

其中最好的性质是对大数值权重进行惩罚,从而提升泛化能力,因为这使得单个维度不会对整体分值有过大的影响。

例如,假设有输入向量: x=[1,1,1,1],两个权重向量: w1=[1,0,0,0],w2=[0.25,0.25,0.25,0.25]。那么w1^Tx=w2^Tx=1,虽然两个权重向量得到同样的内积,但是从L2惩罚结果来看(w1的L2惩罚是1.0,而w2的L2惩罚是0.25w2更好些,因为w2的权重值小且分散,这会鼓励分类器将所有维度上的特征都用起来,而不过度依赖于少数几个维度。

通常只对权重W正则化,而不对偏差b正则化。因为偏差并不控制输入维度上的影响强度。课里还给出了一个无正则化损失函数的Python实现,有非向量化和半向量化两个形式:

def L_i(x, y, W):  """  unvectorized version. Compute the multiclass svm loss for a single example (x,y)  - x is a column vector representing an image (e.g. 3073 x 1 in CIFAR-10)    with an appended bias dimension in the 3073-rd position (i.e. bias trick)  - y is an integer giving index of correct class (e.g. between 0 and 9 in CIFAR-10)  - W is the weight matrix (e.g. 10 x 3073 in CIFAR-10)  """  delta = 1.0 # see notes about delta later in this section  scores = W.dot(x) # scores becomes of size 10 x 1, the scores for each class  correct_class_score = scores[y]  D = W.shape[0] # number of classes, e.g. 10  loss_i = 0.0  for j in xrange(D): # iterate over all wrong classes    if j == y:      # skip for the true class to only loop over incorrect classes      continue    # accumulate loss for the i-th example    loss_i += max(0, scores[j] - correct_class_score + delta)  return loss_idef L_i_vectorized(x, y, W):  """  A faster half-vectorized implementation. half-vectorized  refers to the fact that for a single example the implementation contains  no for loops, but there is still one loop over the examples (outside this function)  """  delta = 1.0  scores = W.dot(x)  # compute the margins for all classes in one vector operation  margins = np.maximum(0, scores - scores[y] + delta)  # on y-th position scores[y] - scores[y] canceled and gave delta. We want  # to ignore the y-th position and only consider margin on max wrong class  margins[y] = 0  loss_i = np.sum(margins)  return loss_idef L(X, y, W):  """  fully-vectorized implementation :  - X holds all the training examples as columns (e.g. 3073 x 50,000 in CIFAR-10)  - y is array of integers specifying correct class (e.g. 50,000-D array)  - W are weights (e.g. 10 x 3073)  """  # evaluate loss over all examples in X without using any for loops  # left as exercise to reader in the assignment

实际操作

设置Delta:你可能注意到上面的内容对超参数Δ及其设置是一笔带过,那么它应该被设置成什么值?需要通过交叉验证来求得吗?现在看来,该超参数在绝大多数情况下设为Δ=1.0都是安全的。超参数Δλ看起来是两个不同的超参数,但实际上他们一起控制同一个权衡:即损失函数中的数据损失和正则化损失之间的权衡。理解这一点的关键是要知道,权重W的大小对于分类分值有直接影响(当然对他们的差异也有直接影响):当我们将W中值缩小,分类分值之间的差异也变小,反之亦然。因此,不同分类分值之间的边界的具体值(比如Δ=1或Δ=100)从某些角度来看是没意义的,因为权重自己就可以控制差异变大和缩小。也就是说,真正的权衡是我们允许权重能够变大到何种程度(通过正则化强度λ来控制)。

后面,公开课中还提到了SVM的二元情况,以及相关的一些概念,如核函数,对偶,SMO算法等。这些在吴恩达老师的机器学习课里有比较详细的介绍。

除了SVM分类器外,还一个最常用的就是Softmax分类器。

在Softmax分类器中,函数映射f(xi;W)=Wxi保持不变,但将评分值视为每个分类的未归一化的对数概率,还将折叶损失(hinge loss)改为交叉熵损失(cross-entropy loss)。公式如下:

 或是 

其中,fj表示分类评分向量f中的第j个元素。数据集的损失函数结果为所有样本数据的损失值Li的均值与正则化损失R(W)的和。

SVM和Softmax的比较


可以看出,两个分类器使用了同样的分值向量f,不同之处在于对f中分值的解释:SVM分类器将其看作分类评分,它的损失函数鼓励正确分类的分值比其他分类的分值高至少一个边界值。Softmax分类器将这些数值看作每个分类没有归一化的对数概率,鼓励正确分类的归一化的对数概率变高,其余的变低。
而且,Softmax分类器可以给出每个分类的概率。SVM的计算是无标定的,难以对所有分类的评分值给出直观解释。例如,针对给出的图像,SVM分类器可能给出[12.5, 0.6, -23.0]对应的分类“猫”,“狗”,“船”;而softmax分类器却能计算出这三个标签的”可能性“是[0.9, 0.09, 0.01],让人能看出不同分类的准确性。

参考:

http://cs231n.github.io/linear-classify/

https://zhuanlan.zhihu.com/p/20918580?refer=intelligentunit

https://zhuanlan.zhihu.com/p/20945670?refer=intelligentunit

https://zhuanlan.zhihu.com/p/21102293?refer=intelligentunit

http://www.jianshu.com/p/0da9eb3fd06b

http://blog.csdn.net/zhili8866/article/details/53317127

阅读全文
0 0