k-Nearest Neighbor分类器存在以下不足:
引言:我们将要实现一种更强大的方法来解决图像分类问题,该方法可以自然地延伸到神经网络和卷积神经网络上。
这种方法主要有两部分组成:
该方法的第一部分就是定义一个评分函数,这个函数将图像的像素值映射为各个分类类别的得分,得分高低代表图像属于该类别的可能性高低。
下面是具体例子来展示该方法。
现假设有一个包含很多图像的训练集 x i ∈ R D x_i\in R^D xi∈RD,每个图像都有一个对应的分类标签 y i y_i yi。这里 i = 1 , 2... N i=1,2...N i=1,2...N并且 y i ∈ 1... K 。 y_i\in 1...K。 yi∈1...K。这就是说,我们有N个图像样例,每个图像的维度是D,共有K种不同的分类。
举例来说,在CIFAR-10中,我们有一个 N = 50000 N=50000 N=50000的训练集,每个图像有D=32x32x3=3072个像素,而 K = 10 K=10 K=10,这是因为图片被分为10个不同的类别(狗,猫,汽车等)。
我们现在定义评分函数为: f : R D → R K f:R^D\to R^K f:RD→RK,该函数是原始图像像素到分类分值的映射。
在本模型中,我们从最简单的概率函数开始,一个线性映射:
f ( x i , W , b ) = W x i + b \displaystyle f(x_i,W,b)=Wx_i+b f(xi,W,b)=Wxi+b
在上面的公式中,假设每个图像数据都被拉长为一个长度为 D D D的列向量,大小为[D x 1]。其中大小为[K x D]的矩阵 W W W和大小为[K x 1]列向量 b b b为该函数的参数(parameters)。
还是以CIFAR-10为例, x i x_i xi就包含了第 i i i个图像的所有像素信息,这些信息被拉成为一个[3072 x 1]的列向量, W W W大小为[10x3072], b b b的大小为[10x1]。因此,3072个数字(原始像素数值)输入函数,函数输出10个数字(不同分类得到的分值)。参数 W W W被称为权重(weights)。 b b b被称为偏差向量(bias vector),这是因为它影响输出数值,但是并不和原始数据 x i x_i xi产生关联。在实际情况中,人们常常混用权重和参数这两个术语。
线性分类器计算图像中3个颜色通道中所有像素的值与权重的矩阵乘,从而得到分类分值。
根据我们对权重设置的值,对于图像中的某些位置的某些颜色,函数表现出喜好或者厌恶(根据每个权重的符号而定)。
举个例子,可以想象“船”分类就是被大量的蓝色所包围(对应的就是水)。那么“船”分类器在蓝色通道上的权重就有很多的正权重(它们的出现提高了“船”分类的分值),而在绿色和红色通道上的权重为负的就比较多(它们的出现降低了“船”分类的分值)。
为了便于可视化,假设图像只有4个像素(都是黑白像素,这里不考虑RGB通道),有3个分类(红色代表猫,绿色代表狗,蓝色代表船,注意,这里的红、绿和蓝3种颜色仅代表分类,和RGB通道没有关系)。
首先将图像像素拉伸为一个列向量,与 W W W进行矩阵乘,然后得到各个分类的分值。需要注意的是,这个 W W W一点也不好:猫分类的分值非常低。从上图来看,算法倒是觉得这个图像是一只狗。
既然图像被伸展成为了一个高维度的列向量,那么我们可以把图像看做这个高维度空间中的一个点(即每张图像是3072维空间中的一个点)。整个数据集就是一个点的集合,每个点都带有1个分类标签。
既然定义每个分类类别的分值是权重和图像的矩阵乘,那么每个分类类别的分数就是这个空间中的一个线性函数的函数值。我们没办法可视化3072维空间中的线性函数,但假设把这些维度挤压到二维,那么就可以看看这些分类器在做什么了:
图像空间的示意图
其中每个图像是一个点,有3个分类器。以红色的汽车分类器为例,红线表示空间中汽车分类分数为0的点的集合,红色的箭头表示分值上升的方向。所有红线右边的点的分数值均为正,且线性升高。红线左边的点分值为负,且线性降低。
从上面可以看到, W W W的每一行都是一个分类类别的分类器。对于 W W W数字的几何解释是:如果改变其中一行的数字,会看见分类器在空间中对应的直线开始向着不同方向旋转。而偏差b,则允许分类器对应的直线平移。需要注意的是,如果没有偏差,无论权重如何,在 x i = 0 x_i=0 xi=0时分类分值始终为0。这样所有分类器的线都不得不穿过原点。
关于权重W的另一个解释是它的每一行对应着一个分类的模板(有时候也叫作原型)。一张图像对应不同分类的得分,是通过使用内积(也叫点积)来比较图像和模板,然后找到和哪个模板最相似。从这个角度来看,线性分类器就是在利用学习到的模板,针对图像做模板匹配。从另一个角度来看,可以认为还是在高效地使用k-NN,不同的是我们没有使用所有的训练集的图像来比较,而是每个类别只用了一张图片(这张图片是我们学习到的,而不是训练集中的某一张),而且我们会使用(负)内积来计算向量间的距离,而不是使用L1或者L2距离。
偏差和权重的合并技巧:它能够将我们常用的参数W和b合二为一。回忆一下,分类评分函数定义为:
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和偏差参数b)有点笨拙,一般常用的方法是把两个参数放到同一个矩阵中,同时 x i x_i xi向量就要增加一个维度,这个维度的数值是常量1,这就是默认的偏差维度。这样新的公式就简化成下面这样:
f ( x i , W ) = W x i \displaystyle f(x_i,W)=Wx_i f(xi,W)=Wxi
还是以CIFAR-10为例,那么 x i x_i xi的大小就变成[3073x1],而不是[3072x1]了,多出了包含常量1的1个维度)。 W W W大小就是[10x3073]了。 W W W中多出来的这一列对应的就是偏差值 b b b,具体见下图:
左边是先做矩阵乘法然后做加法,右边是将所有输入向量的维度增加1个含常量1的维度,并且在权重矩阵中增加一个偏差列,最后做一个矩阵乘法即可。左右是等价的。通过右边这样做,我们就只需要学习一个权重矩阵,而不用去学习两个分别装着权重和偏差的矩阵了。
图像数据预处理:在上面的例子中,所有图像都是使用的原始像素值(从0到255)。在机器学习中,对于输入的特征做归一化(normalization)处理是常见的套路。而在图像分类的例子中,图像上的每个像素可以看做一个特征。在实践中,对每个特征减去平均值来中心化数据是非常重要的。 在这些图片的例子中,该步骤意味着根据训练集中所有的图像计算出一个平均图像值,然后每个图像都减去这个平均值,这样图像的像素值就大约分布在[-127, 127]之间了。下一个常见步骤是,让所有数值分布的区间变为[-1, 1]。这就是零均值的中心化。具体以后详解。