Linear Classification

内容列表

  • 线性分类器简介
  • 线性评价函数
  • 阐明线性分类器
  • 损失函数
    • 多类SVM
    • Softmax分类器
    • SVM和Softmax的比较
  • 拓展阅读

Linear Classification

k-NN分类器的不足:

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

概述:我们可以实现一种更加强大的新方法来解决图像分类问题。该方法由两部分组成:

  • score function(评分函数):实现原始图像数据到类别分值的映射
  • loss function(损失函数):用来量化预测分类标签的得分与真实标签之间的一致性

该方法可转化为一个最优化问题,即通过更新score function的参数来最小化loss

Parameterized mapping from images to label scores

Score Function

现假设有一个包含很多图像的训练集$x_i\in \mathcal{R}^D$,每个图像都有一个对应的分类标签$y_i$,其中$i=1,2,...,N$且$y_i\in 1...K$,即有N个图像样例,每个图像的维度是D,共有K种不同的分类。

现在定义score function为:$$f:\mathcal{R}^D \to \mathcal{R}^K$$该函数是原始图像像素到分类分值的映射。

Linear Classification

$$f(x_i,W,b)=Wx_i+b$$

在上面的公式中,假设每个图像数据都被拉长为一个长度为$D$的列向量,大小为$[D\times 1]$,其中大小为$[K\times D]$的矩阵$W$和大小为$[K\times 1]$的列向量$b$为该函数的参数。参数$W$被称为权重(weights),$b$被称为偏差向量(bias vector)。

Interpreting a linear classifier

将图像看做高维度的点:由于图像被伸展成为了一个高维度的列向量,我们可以把图像看做是这个高维度空间中的一个点,整个数据集就是一个点的集合,每个点都带有一个分类标签。同样的,既然定义每个分类类别的分值是权重和图像的矩阵乘,那么每个分类类别的分数就是这个空间中的一个线性函数的函数值。

$W$的每一行都是一个分类类别的分类器,如果改变其中一行的数字,会看见分类器在空间中对应的直线开始想着不同的方向旋转,而偏差$b$则允许分类器对应的直线平移。

将线性分类器看做模板匹配:关于权重$W$的另一个解释是它的每一行对应着一个分类的模板(有时候也叫作原型/prototype)。一张图像对应不同分类的得分,是通过使用内积(也叫点积)来比较图像和模板,然后找到和哪个模板最相似。

从这个角度来看,线性分类器就是在利用学习到的模板,针对图像做模板匹配。从另一个角度来看,可以认为还是在高效地使用k-NN,不同的是我们没有使用所有的训练集的图像来比较,而是每个类别只用了一张图片(这张图片是我们学习到的,而不是训练集中的某一张),而且我们会使用(负)内积来计算向量间的距离,而不是使用L1或者L2距离。

偏差和权重的合并技巧:一般为了能够将常用的参数W和b合二为一,可以把两个参数放到同一个矩阵中,同时$x_i$向量增加一个维度,且这个维度的数值是常量1,即为默认的偏差维度(bias dimension)

如此,新的公式简化为:$$f(x_i,W)=Wx_i$$

图像数据预处理:在机器学习中,对于输入的特征做归一化(normalization)处理是常见的套路。而在图像分类的例子中,图像上的每个像素可以看做一个特征。在实践中,对每个特征减去平均值来中心化数据是非常重要的。在这些图片的例子中,该步骤意味着根据训练集中所有的图像计算出一个平均图像值,然后每个图像都减去这个平均值,这样图像的像素值就大约分布在[-127, 127]之间了。下一个常见步骤是,让所有数值分布的区间变为[-1, 1]。零均值的中心化是很重要的。

Loss Function

损失函数(Loss Function)有时也叫作代价函数(Cost Function)目标函数(Objective)。我们使用损失函数来衡量我们对结果的不满意程度,当评分函数输出结果与真实结果之间的差异越大,损失函数的输出越大,反之越小。

Multiclass Support Vector Machine Loss

SVM的loss function希望SVM在正确分类上的得分始终比不正确分类上的得分高出一个边界值$\Delta$。

第i个数据中包含图像$x_i$的像素和代表正确类别的标签$y_i$。评分函数输入像素数据,然后通过公式$f(x_i,W)$来计算不同分类类别的分值。这里我们将分值简写为$s$。比如,针对第j个类别的得分就是第j个元素:$s_j=f(x_i,W)_j$。针对第i个数据的多类SVM的损失函数定义如下:

$$L_i=\sum_{j\neq y_i} \max(0,s_j-s_{y_i}+\Delta)$$

在本模型中,还可将其改写为:

$$L_i=\sum_{j\neq y_i} \max(0,w_j^Tx_i-w_{y_i}^Tx_i+\Delta)$$

其中$w_j$是权重W的第j行

Hinge loss(折叶损失):$\max(0,-)$

Squared Hinge Loss(平方折叶损失):$\max(0,-)^2$

Regularization(正则化):假设有一个数据集和一个权重集W能够正确地分类每个数据(即所有的边界都满足,对于所有的i都有$L_i=0$)。问题在于这个W并不唯一:可能有很多相似的W都能正确地分类所有的数据。一个简单的例子:如果W能够正确分类所有数据,即对于每个数据,损失值都是0。那么当$\lambda>1$时,任何数乘$\lambda W$都能使得损失值为0,因为这个变化将所有分值的大小都均等地扩大了,所以它们之间的绝对差值也扩大了。

为了对某些特定的权重W添加一些偏好,对其他权重不添加,以此来消除模糊性,可以向损失函数添加一个正则化惩罚(regularization penalty)$R(W)$。最常用的正则化惩罚是L2范式:

$$R(W)=\sum_{k} \sum_{l} W_{k,l}^2$$

添加正则化惩罚后,完整的多类SVM损失函数由两部分组成:数据损失(data loss),即所有样例的平均损失$L_i$,以及正则化损失(regularization loss)。完整公式如下所示:

$$L = \underbrace{ \frac{1}{N} \sum_i L_i }_\text{data loss} + \underbrace{ \lambda R(W) }_\text{regularization loss}$$

还可将其展开为:

$$L = \frac{1}{N} \sum_i \sum_{j\neq y_i} \left[ \max(0, f(x_i; W)_j - f(x_i; W)_{y_i} + \Delta) \right] + \lambda \sum_k\sum_l W_{k,l}^2$$

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

L2惩罚倾向于更小更分散的权重向量,这就会鼓励分类器最终将所有维度上的特征都用起来,而不是强烈依赖其中少数几个维度。这一效果将会提升分类器的泛化能力,并避免过拟合。

需要注意的是,和权重不同,偏差没有这样的效果,因为它们并不控制输入维度上的影响强度。因此通常只对权重W正则化,而不正则化偏差b。

Sample Code(非向量化和半向量化)

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

Practical Consideration

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

在初始形式中进行最优化:在神经网络相关领域中,损失函数的最优化的始终在非限制初始形式下进行。很多这些损失函数从技术上来说是不可微的(比如当x=y时,max(x,y)函数就不可微分),但是在实际操作中并不存在问题,因为通常可以使用次梯度。

Softmax Classifier

SVM将输出$f(x_i,W)$作为每个分类的评分,而Softmax的输出为归一化的分类概率。在Softmax分类器中,函数映射$f(x_i;W)=Wx_i$不变,但将这些评分视为每个分类的未归一化的对数概率,并且将hinge loss替换为cross-entropy loss(交叉熵损失)。公式如下:

$$L_i = -\log\left(\frac{e^{f_{y_i}}}{ \sum_j e^{f_j} }\right) \hspace{0.5in} \text{or equivalently} \hspace{0.5in} L_i = -f_{y_i} + \log\sum_j e^{f_j}$$

在上式中,使用$f_j$来表示分类评分向量$f$中的第$j$个元素。和之前一样,整个数据集的损失值是数据集中所有样本数据的损失值$L_i$的均值与正则化损失$R(W)$之和。其中函数$f_j(z)=\frac{e^{z_j}}{\sum_ke^{z_k}}$被称作softmax 函数:其输入值是一个向量,向量中元素为任意实数的评分值(z中的),函数对其进行压缩,输出一个向量,其中每个元素值在0到1之间,且所有元素之和为1。

Probabilistic interpretation

$$P(y_i \mid x_i; W) = \frac{e^{f_{y_i}}}{\sum_j e^{f_j} }$$

可以解释为是给定图像数据$x_i$,以$W$为参数,分配给正确分类标签$y_i$的归一化概率。从概率论的角度来理解,我们就是在最小化正确分类的负对数概率,这可以看做是在进行最大似然估计(MLE)。该解释的另一个好处是,损失函数中的正则化部分$R(W)$可以被看做是权重矩阵W的高斯先验,这里进行的是最大后验估计(MAP)而不是最大似然估计。

Practical issues: Numeric stability

为避免指数函数计算导致的大数值,可以进行如下操作:

$$\frac{e^{f_{y_i}}}{\sum_j e^{f_j}} = \frac{Ce^{f_{y_i}}}{C\sum_j e^{f_j}} = \frac{e^{f_{y_i} + \log C}}{\sum_j e^{f_j + \log C}}$$

通常将$C$设为$\log C = -\max_j f_j$,即将向量$f$中的数值进行平移,使得最大值为0。

SVM vs. Softmax

两个分类器都计算了同样的分值向量$f$(本节中是通过矩阵乘来实现)。不同之处在于对$f$中分值的解释:SVM分类器将它们看做是分类评分,它的损失函数鼓励正确的分类(本例中是蓝色的类别2)的分值比其他分类的分值高出至少一个边界值。Softmax分类器将这些数值看做是每个分类没有归一化的对数概率,鼓励正确分类的归一化的对数概率变高,其余的变低。

Softmax分类器为每个分类提供了“可能性”

在实际使用中,SVM和Softmax经常具有相似的效果

Further Readings