图像分类即是从已有的分类标签集中选择一个分配给一张图像。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.分类时只需要做矩阵乘法和矩阵加法就能对测试数据进行分类。
上面是图像映射分类的例子,为了便于可视化,假设图像只有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)来衡量结果的不满意程度,当与真实结果差异越大时,损失函数输出越大,反之越小。
注:max(0,-)函数被称为折叶损失(hinge loss)。有时候也会使用平方折叶损失SVM(即L2-SVM),对应的是max(0,-)^2,即更强地惩罚过界的边界值。
假设有一个数据集和权重集W能够正确地分类数据(即所有L_i=0),但这个W并不唯一:可能有很多相似的W都能对数据进行正确地分类。例如,如果W能够正确分类所有数据,即对于每个数据,损失值=0,当λ>1时,任何数乘 λW 都使得损失值=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.25)w2更好些,因为w2的权重值小且分散,这会鼓励分类器将所有维度上的特征都用起来,而不过度依赖于少数几个维度。
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_i
def 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_i
def 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
后面,公开课中还提到了SVM的二元情况,以及相关的一些概念,如核函数,对偶,SMO算法等。这些在吴恩达老师的机器学习课里有比较详细的介绍。
除了SVM分类器外,还一个最常用的就是Softmax分类器。
在Softmax分类器中,函数映射f(xi;W)=Wxi保持不变,但将评分值视为每个分类的未归一化的对数概率,还将折叶损失(hinge loss)改为交叉熵损失(cross-entropy loss)。公式如下:
其中,fj表示分类评分向量f中的第j个元素。数据集的损失函数结果为所有样本数据的损失值Li的均值与正则化损失R(W)的和。
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