cs231n-学习笔记-01图像分类

1 图像分类

1.1 介绍

图像分类是计算机视觉中一个核心的任务。

1.2 问题

现实图像与计算机识别之间的语义鸿沟?

一幅图像仅仅是一堆介于0-255之间数组成的表。**图像是一个由数字组成的巨大的3维数组。0表示全黑,255表示全白。

1.3 挑战

①视角变化,图像发生细微的变化,所有的像素点就会与之对应发生改变

②图像的曝光度,

③图像的变形,

④图像的遮挡物,

⑤图像背景的干扰,

⑥物种演化,

1.4 图像分类器

def classify_image(image):
    #  执行一些操作
    return image_label

不像例子中对数字进行排序,没有明显的方式编写算法实现识别一只猫或者其他的种类。

我们已经做出的尝试,找到图像的边缘,找到图像的棱角

1.5 以数据为驱动的方法

①收集图像并有对应标签的数据集,

②使用机器去学习,训练处一个分类器

③在新的图像上来评估这个分类器

2 K近邻分类器

2.1 最近邻

def train(images, labels):
    # 机器学习
    return model

def predict(model, test_images):
    # 使用训练得到的模型去预测新的图像
    return test_labels

数据集简介:CIFAR10

10个类别,50000训练集,10000测试集,每个图像是32x32x3

采用距离度量的方式比较图片

L1距离,曼哈顿距离: d1(I1,I2)=P|Ip1Ip2| d 1 ( I 1 , I 2 ) = ∑ P | I 1 p − I 2 p |

import numpy as np

class NearestNeighbor:
    def __init__(self):
        pass

    def train(self, X, y):
        """ X形状(N,D),Y的形状(N,)"""
        self.Xtr = X
        self.ytr = y

    def predict(self, X):
        """ X的每行代表一个我们希望预测其标签的样本"""
        num_test = X.shape[0]
        #  确保程序的输入和输出的形状是匹配的
        Ypred = np.zeros(num_test, dtype=self.ytr.dtype)
        #  循环遍历所有测试行
        for i in xrange(num_test):
            #  找到和第i个训练样本最近的训练集图像
            #  使用L1距离
            distances = np.sum(np.abs(self.Xtr - X[i,:]), axis = 1)
            min_index = np.argmin(distances)  #  得到最小距离对应的索引
            Ypred[i] = self.ytr[min_index]  #  预测最近的样本的标签
        return Ypred

最近邻分类器性能评估:

train O(1) predict O(n)

这太耗时了,不满足我们的需求。我们希望预测快,训练过程慢一点儿事可以接受的。

2.2 K近邻

距离度量

L1(曼哈顿距离): d1(I1,I2)=P|Ip1Ip2| d 1 ( I 1 , I 2 ) = ∑ P | I 1 p − I 2 p |

L2(欧几里得距离): d2(I1,I2)=P(Ip1Ip2)2 d 2 ( I 1 , I 2 ) = ∑ P ( I 1 p − I 2 p ) 2

超参数选择

最好的K是什么?

最好的距离是什么?

超参数:我们设置的而不是算法学习的参数。特别依赖具体的问题,我们需要尝试不同的参数值,来看看哪个值使得分类器分的最好。绝对不能测试集来进行调优

设置超参数

①想法1:选择在整个数据集上预测最准的超参数。(不合理,当K为1时,该模型在训练数据上能够非常准确的实现预测)

②想法2:把整个数据集分为训练集和测试集,选择在测试集上预测准确的超参数(不合理,在新的数据集上不能非常准确的实现预测)

③想法2:把整个数据集分为训练集,验证集合测试集,在验证集预测选择合适的超参数,在测试集上对所选的超参数评估其是否合理(合理)

④想法4:交叉验证集,把数据分成许多份,把每一份都作为验证集预测求得超参数,再平均求他们的结果(在数据集很小的模型中是适用的,但是在深度学习模型中不能太过频繁的使用)

在实际引用中,人们不是很喜欢用交叉验证,主要是因为它会耗费较多的计算资源。一般直接把训练集按照50%~90%的比例分为训练集和验证集。但这也是根据具体情况来定的:如果超参数数量多,你可能就想用更大的验证集,而验证集数量不够,那么最好还是用交叉验证。至于分成几份比较好,一般都是分成3、5和10份。

分析

对图像分类问题一般不采用K近邻的算法,

①在测试阶段特别耗时,

②像素间的距离度量基本没有作用。

③维度灾难

k近邻分类器在某些特定的情况下(比如数据维度较低),可能是一个不错的选择。但是在实际图像分类工作中,很少使用。因为图像都是高维度数据(他们通常包含很多像素),而高维度向量之间的距离通常是反直觉的。

总结

①在图像分类中,我们拥有带有图像和标签的训练数据集,在测试数据集上预测标签

②K近邻分类器基于最近的样本预测测试数据集的标签

③什么样的距离度量和K是超参数

④一旦找到最优的超参数,就让算法以该参数在测试集跑且只跑一次,并根据测试结果评价算法。

2.3 实际应用

①预测数据。对数据中特征归一化,使其平均值和单位方差为0。(图像中的像素都是同质的,不会表现出较大的差异分布,也就不需要标准化处理了)

②降维。如果数据是高维度的,考虑使用降维方法,比如PCA和随机投影

③降数据随机分入训练集和验证集。按照一般规律,70%~90%数据作为训练集。这个比例根据算法中有多少超参数,以及这些超参数对于算法的预期影响来决定。超参数越多,验证集越大。若担心验证集不够,可以使用交叉验证的方法。如果计算资源充足,使用交叉验证总是更加安全的(份数越多,效果越好,越耗费计算资源)

④在验证集上调优。尝试足够多的k,尝试L1和L2两种范数计算方式。

⑤如果分类器跑得太慢,尝试使用Approximate Nearest Neighbor库来加速这个过程,其代价是降低一些准确率。

⑥对最优的超参数做记录。千万不要在最终的分类器中使用验证集数据,这样做会破坏对于最优参数的估计。直接使用测试集来测试用最优参数设置好的参数模型,得到测试集数据的准确率,并以此作为KNN分类器在此数据集上的性能表现。

关于K近邻详解与代码实现见下一博客《图像分类(续)》!

你可能感兴趣的:(深度学习,cs231n)