简介
图像分类的任务就是给定一个图像,正确给出该图像所属的类别。对于超级强大的人类视觉系统来说,判别出一个图像的类别是件很容易的事,但是对于计算机来说,并不能像人眼那样一下获得图像的语义信息。
计算机能看到的只是一个个像素的数值,对于一个RGB图像来说,假设图像的尺寸是32*32,那么机器看到的就是一个形状为3*32*32的矩阵,或者更正式地称其为“张量”(“张量”简单来说就是高维的矩阵),那么机器的任务其实也就是寻找一个函数关系,这个函数关系能够将这些像素的数值映射到一个具体的类别(类别可以用某个数值表示)。
算法
较为简单的算法
Nearest Neighbor
"Nearest Neighbor"是处理图像分类问题一个较为简单、直接、粗暴的方法:首先在系统中“记住”所有已经标注好类别的图像(其实这就是训练集),当遇到一个要判断的还未标注的图像(也就是测试集中的某个图像)时,就去比较这个图像与“记住的”图像的“相似性”,找到那个最相似的已经标注好的图像,用那个图像的类别作为正在分类的图像的类别,这也就是"Nearest Neighbor"名称的含义。
关于如何判断图像“最相似”,可以有多种方法,比如直接求相同位置像素值的差的总和(也就是两个图像的L1距离),也可以采用两个图像的L2距离,也就是先对相同位置像素值作差并求平方,然后对所有平方值求和,最后总体开方,准确的表述如下:记图像分别为
和
,
表示图像
在k位置处的像素值,那么图像
和
的L1和L2距离可以分别表示为:
"Nearest Neighbor"容易实现,但是存在诸多缺点:
- 预测/测试的过程太慢,给定一个图像时,需要一个个去比较训练集中的图像,每预测一次的计算量都很大,特别是图片的尺寸较大时
- 预测/测试时,仍需要较大的空间去存储训练集
- 准确率不高,实验发现,在CIFAR-10上只能取得%左右的正确率,其实是因为该方法没有足够的理论支撑(只有一定的道理),显然的例子是:对于一个图像,如果将其中的物体向左平移一点获得一个新的图像,则这两个图像应该是相同的类别,但是利用"Nearest Neighbor"判断时,则有可能因为相同位置的像素值不再一样而判断错误(因为L1距离和L2距离都是计算相同位置像素值的接近程度)
Nearest Neighbor的代码实现
环境:Python3.7 + PyTorch
K-Nearest Neighbor
"K-Nearest Neighbor"是很自然想到的一个在"Nearest Neighbor"基础上进行改进的方法,与"Nearest Neighbor"不同的是,"K-Nearest Neighbor"不再将“最接近”的那一个图像的类别作为预测图像的类别,而是选出K个与预测图像“最接近”的图像,看其中哪个类别占的比例最高,就将其作为预测图像的类别,这样可以在某种程度上增加预测模型的稳定性。
此处的K是一个hyper-parameter(超参数),也就是不能由模型学得,而是需要自己去设定,可以尝试的值如10、5、20等,具体选取哪个值可以通过Cross Validation(交叉验证法)来确定,详见机器学习的模型评估方法。
"K-Nearest Neighbor"的代码实现与"Nearest Neighbor"不同的只是,
正确率较高的算法
Linear Classfication
上面的"Nearest Neighbor"和"K-Nearest Neighbor"方法,都是直接比较图像的相似性,存在测试效率太低的问题,并且不能够提取图像的语义信息,导致错误率很高。
Linear Classification利用一个“全连接层”(Fully Connected Layer),输入图像的所有像素值,经过全连接层的运算后输出每个类别的“得分”,最终选取得分最高的类别作为图像的类别。
全连接层
先看一张图
如图所示,
都是输入的像素值,真实的图像中,输入可能会有很多个,比如CIFAR-10的数据集,图像尺寸是3*32*32(3是RGB这3个通道),那么输入就有3*32*32个;
等表示权重,
是输出的每个类别的得分,如
表示猫这个类别的得分
输出的计算方式是:
将其向量化,令:
Convolutional Neural Network(CNN,卷积神经网络)
利用CNN可以进一步提高图像分类的正确率,甚至可以超过人类,关于CNN的实现,在后面的文章中会详细写