2017CS231n学习笔记1-图像分类

(16) 2024-06-04 23:01:01

文章目录

  • 2 图像分类
    • 2.1 数据驱动方法
      • 第一个分类器:最近邻分类器
      • L1距离(曼哈顿距离)
      • 最近邻分类器Python代码
    • 2.2 K-最邻近算法
      • L2距离(欧氏距离)
      • k-Nearest Neighbor分类器(KNN)
      • 实际应用k-NN
    • 2.3 线性分类器

2 图像分类

2.1 数据驱动方法

步骤

  • step1:收集图像和标签的数据集Collect a dataset of images and labels
  • step2:使用机器学习来训练分类器Use Machine Learning to train a classifier
  • step3:评估新图像上的分类器 Evaluate the classifier on new images

第一个分类器:最近邻分类器

算法思想很简单,分两步:
1、Memorize all data and labels
2、Predict the label of the most similar training image

  • 训练函数:接收图片和标签,输出模型

    def train(images,labels):
        # Machine learing!
        return model
    
  • 预测函数:接收一个模型,对图片种类进行预测,返回标签

    def predict(model,test_images):
        # Use model to predict labels
        return test_labels
    

示例数据集: CIFAR10
包含:10 classes 50,000 training images 10,000 testing images

将测试图片与所有训练图片进行比较,需要比较图片的方法,计算相似度就需要就有一个度量相似度的东西,例如L1距离

L1距离(曼哈顿距离)

L1 distance:
d 1 ( I 1 , I 2 ) = ∑ p ∣ I 1 p − I 2 p ∣ d_1(I_1,I_2)=\sum_p∣I_1^p−I_2^p| d1(I1,I2)=pI1pI2p
如果两张图片一模一样,那么L1距离为0,但是如果两张图片很是不同,那L1值将会非常大。

假设图像是4*4大小,那么只取左上角的元素进行以下计算,得到456处不同:

2017CS231n学习笔记1-图像分类 (https://mushiming.com/)  第1张

最近邻分类器Python代码

import numpy as np

class NearestNeighbor(object):
  def __init__(self):
    pass

  def train(self, X, y):
    """ X is N x D where each row is an example. Y is 1-dimension of size N """
    # the nearest neighbor classifier simply remembers all the training data
    self.Xtr = X
    self.ytr = y

  def predict(self, X):
    """ X is N x D where each row is an example we wish to predict label for """
    num_test = X.shape[0]
    # lets make sure that the output type matches the input type
    Ypred = np.zeros(num_test, dtype = self.ytr.dtype)

    # loop over all test rows
    for i in xrange(num_test):
      # find the nearest training image to the i'th test image
      # using the L1 distance (sum of absolute value differences)
      distances = np.sum(np.abs(self.Xtr - X[i,:]), axis = 1)
      min_index = np.argmin(distances) # get the index with smallest distance
      Ypred[i] = self.ytr[min_index] # predict the label of the nearest example

    return Ypred

  • 将CIFAR-10的数据加载到内存中,并分成4个数组:训练数据和标签,测试数据和标签。在后面的代码中,Xtr(大小是50000x32x32x3)存有训练集中所有的图像,Ytr是对应的长度为50000的1维数组,存有图像对应的分类标签(从0到9):
  • 引用了numpy提供的向量运算(如shape函数)
  • 在train方法中,主要是记录训练数据集,这里其实就是一个指针指向里面的某一个图片
  • 在predict方法里面,用L1距离去逐一比较所有训练数据集的图片,找到距离最小的图片,然后输出预测结果

缺点:训练过程快,而测试过程慢,与期望不符,较为落后。

从图上看实际运用的缺点:例如绿色区域里面出现了黄点,绿色区域插入了蓝色和粉色区域。

2017CS231n学习笔记1-图像分类 (https://mushiming.com/)  第2张

2.2 K-最邻近算法

原理:

找最相似的k个图片的标签,然后让他们针对测试图片进行投票,最后把票数最高的标签作为对测试图片的预测。

2017CS231n学习笔记1-图像分类 (https://mushiming.com/)  第3张

可见k变大时不再出现噪声点,边界也更清晰平滑。

算法的描述:

1)计算测试数据与各个训练数据之间的距离;

2)按照距离的递增关系进行排序;

3)选取距离最小的K个点;

4)确定前K个点所在类别(标签)的出现频率;

5)返回前K个点中出现频率最高的类别作为测试数据的预测分类。

参考:https://www.cnblogs.com/ybjourney/p/4702562.html

L2距离(欧氏距离)

d 2 ( I 1 , I 2 ) = ∑ p ( I 1 p − I 2 p ) 2 d_2(I_1,I_2)=\sqrt{\sum_p(I_1^p−I_2^p)^2} d2(I1,I2)=p(I1pI2p)2

重要原则:可以看到L1在旋转坐标后,距离是变化的,而L2不会,因此如果输入的特征向量中的一些值对于输出有非常重要的意义或影响,这个时候应该使用L1距离,但是如果特征向量只是某个空间中的一个通用向量,用L2会好一点。

k-Nearest Neighbor分类器(KNN)

通过指定不同的距离度量,可将KNN分类器泛化到不同类型的数据上。

**超参数:**诸如对K、距离度量的选择。 不是机器学习的参数,而是人为为算法设置的。

设置超参数的方法一:

  • 将数据分为训练集验证集测试集(train,validation,test)

  • 在train上用不同的超参数来训练算法;再在val上进行评估,选择在val上表现最好的一组超参数;最后把这组在val上表现最好的分类器运用在测试集上,得到结果。

    注意:必须分割验证集和测试集。

方法二:交叉验证

常用于小数据集,在深度学习中不常用。

先取部分数据作为测试集,再将剩余训练数据平均分成多份,其中1份用来验证,其余用来训练。然后轮流将每1份当做验证集,最后取所有验证结果的平均值作为算法验证结果。


示例:
2017CS231n学习笔记1-图像分类 (https://mushiming.com/)  第4张

这就是5份交叉验证对k值调优的例子。针对每个k值,得到5个准确率结果,取其平均值,然后对不同k值的平均表现画线连接。本例中,当k=7的时算法表现最好(对应图中的准确率峰值)。如果我们将训练集分成更多份数,直线一般会更加平滑(噪音更少)。

缺点:

1、测试时间长

2、L1、L2距离不太适用于比较图像,不适合表示图像视觉感知上的差异。

3、维度灾难

小结

简要说来:

  • 介绍了图像分类问题。在该问题中,给出一个由被标注了分类标签的图像组成的集合,要求算法能预测没有标签的图像的分类标签,并根据算法预测准确率进行评价。
  • 介绍了一个简单的图像分类器:最近邻分类器(Nearest Neighbor classifier)。分类器中存在不同的超参数(比如k值或距离类型的选取),要想选取好的超参数不是一件轻而易举的事。
  • 选取超参数的正确方法是:将原始训练集分为训练集和验证集,我们在验证集上尝试不同的超参数,最后保留表现最好那个。
  • 如果训练数据量不够,使用交叉验证方法,它能帮助我们在选取最优超参数的时候减少噪音。
  • 一旦找到最优的超参数,就让算法以该参数在测试集跑且只跑一次,并根据测试结果评价算法。
  • 最近邻分类器能够在CIFAR-10上得到将近40%的准确率。该算法简单易实现,但需要存储所有训练数据,并且在测试的时候过于耗费计算能力。
  • 最后,我们知道了仅仅使用L1和L2范数来进行像素比较是不够的,图像更多的是按照背景和颜色被分类,而不是语义主体分身。

实际应用k-NN

如果你希望将k-NN分类器用到实处(最好别用到图像上,若是仅仅作为练手还可以接受),那么可以按照以下流程:

  1. 预处理你的数据:对你数据中的特征进行归一化(normalize),让其具有零平均值(zero mean)和单位方差(unit variance)。在后面的小节我们会讨论这些细节。本小节不讨论,是因为图像中的像素都是同质的,不会表现出较大的差异分布,也就不需要标准化处理了。
  2. 如果数据是高维数据,考虑使用降维方法,比如PCA(wiki ref, CS229ref, blog ref)或随机投影。
  3. 将数据随机分入训练集和验证集。按照一般规律,70%-90% 数据作为训练集。这个比例根据算法中有多少超参数,以及这些超参数对于算法的预期影响来决定。如果需要预测的超参数很多,那么就应该使用更大的验证集来有效地估计它们。如果担心验证集数量不够,那么就尝试交叉验证方法。如果计算资源足够,使用交叉验证总是更加安全的(份数越多,效果越好,也更耗费计算资源)。
  4. 在验证集上调优,尝试足够多的k值,尝试L1和L2两种范数计算方式。
  5. 如果分类器跑得太慢,尝试使用Approximate Nearest Neighbor库(比如FLANN)来加速这个过程,其代价是降低一些准确率。
  6. 对最优的超参数做记录。记录最优参数后,是否应该让使用最优参数的算法在完整的训练集上运行并再次训练呢?因为如果把验证集重新放回到训练集中(自然训练集的数据量就又变大了),有可能最优参数又会有所变化。在实践中,不要这样做。千万不要在最终的分类器中使用验证集数据,这样做会破坏对于最优参数的估计。直接使用测试集来测试用最优参数设置好的最优模型,得到测试集数据的分类准确率,并以此作为你的kNN分类器在该数据上的性能表现。

2.3 线性分类器

函数形式:

  • x:输入数据;W:参数或者权重;b:偏好元素
  • 通过一个参数矩阵W乘以数据矩阵X再加上偏置 bb 得到预测结果:

f ( x , W ) = W x + b f(x,W)=Wx+b f(x,W)=Wx+b

参数化方法,总结对训练数据的认识并用到W中,测试时不再需要训练数据。

2017CS231n学习笔记1-图像分类 (https://mushiming.com/)  第5张

重点这里面注意行的颜色,W的每一行都对应了一个分类。把训练好的单独的每一行的提取出来,还原为图像,就可以看到线性分类器是如何根据什么特征进行分类的。
这里要注意一个概念:图像分类模板,这个模板在CNN里面和每个图片进行点乘后,相应分类就会得到比较大的结果。

线性分类究竟在做些什么, 如何解释线性分类器呢?

其实参数 W 的每一行对应的是一个类别的分类器,改变 W 的一行相当于向不同方向旋转在像素空间的线,改变 b 相当于对这条线做平移。

  • 可以把 W 看成是模板匹配,W 的每一行相当于对应类的一个模板,通过内积的形式去找到最高的分数(对应的类别)。
  • 也可以认为线性分类仍然在求解最邻近,只是这次不是将测试图像与训练集做内积,而是与 W 的一行做内积,以内积来作为类模板与测试图片的距离,而不是使用 L1 或 L2 distance。

线性分类器的限制

线性分类器无法划分multi model data。

2017CS231n学习笔记1-图像分类 (https://mushiming.com/)  第6张

THE END

发表回复