Lecture_2:Image_Classification_pipeline
斯坦福CS231n课程Lecture_2
🐱图像分类问题😼
语义鸿沟
对于人类的视觉系统而言,分类下面这张图像轻而易举。 很明显,这是一只猫🐈,但在计算机的眼里它仅仅是一个数值为[0,255]间的矩阵,猫咪是我们赋予图像的一个语义标签,但是一只猫咪的语义概念和计算机所看到的成百上千密密麻麻的矩阵有着巨大的差距,这就是语义鸿沟。
挑战
以下问题无论在传统的机器学习算法上还是深度学习算法上都算得上是难题,虽然深度神经网络具有非常强大的泛化能力,但并不是说深度学习就可以All in one的。
视角问题
将相机略微移动一些位置,这个矩阵内的数值可能发生了翻天覆地的变化,但它仍然是一只猫,算法需要对这些鲁棒。
照明问题
不同的照片可能存在不同的照明环境,无论猫咪出现在这样漆黑、昏暗的场景中,还是在非常明亮的场景中,我们的算法也应当是鲁棒的。
光线真的是一个非常令人头疼的问题。亲身经历,特别是灰度图像,且类间差距较小的时候,对语义分割这种任务的性能影响可以说是暴击。
形变问题
大家都知道,猫咪:流体动物。猫咪可以懒懒地躺着,也能像人类一样站立,甚至也可以穿过一些不可思议的缝隙。对这些猫咪,我们也希望算法应该是鲁棒的。
遮挡问题
即使被大面积地遮挡,我们仍然希望他可以检测的出来。
背景混淆问题
即使目标与背景非常相似(伪装目标),我们仍然希望算法鲁棒。
类内差异
样本间经常存在一些类内差异,比如下方的猫猫们,他们的年龄,毛色,花纹,可能不一样,但他们都是猫猫。我们需要算法对这些差异一样鲁棒。
早期方法
早期人们识别一只猫可能会去寻找他的边界(可以通过边缘算子膨胀腐蚀等操作实现),然后寻找他的角点来判定其是否是一只猫。这方法行,但不是特别可行,他几乎没有任何的泛化能力,无法检测任何其他类别。如果我们针对每一个类别都单独设计特征来进行图像识别,那么这一定是一个庞大的工作量。
数据驱动方法
因此,我们需要一种算法可以扩展到识别世界上的各种对象。因此我们可以使用数据驱动的方法,步骤如下:
- 我们需要收集大量的图像以及对应的标签
- 使用机器学习方法训练一个分类器
- 在新的图片(未在训练集中出现的数据)上对分类器的性能进行评估
KNN——也许这是最简单的分类器
KNN非常浅显易懂,它的训练过程就是记住所有的训练数据。在预测部分中,他所做的仅仅是将测试图像与训练图像进行一一比对,距离较近的则被分为该类的概率最大。较为简单不过多记录。
距离的度量可以是曼哈顿距离,也可以是欧几里得距离或者等等你可以想到的度量方法
算法示意
可以看到,通常情况下KNN的训练过程不会比预测过程更快,这是一个比较反直觉的东西,因为算法落地通常以搭载在边缘计算设备上为主,这些设备往往性能较弱,因此我们需要预测过程更加快速而非训练过程。而KNN算法似乎是本末倒置的。
算法性能
可以说在K=1时其过拟合问题将会非常严重,增加K值将会改善这一点并且也能使得决策边界更加圆滑。
下图是K近邻算法在图像分类任务中的性能表现,可以看到它并不是很准确,因为它仅仅是去寻找与测试图像的最近邻值。
距离度量
以下是两种距离度量方法,不同的距离度量会在预测空间内对底层的几何与拓扑结构做出不同的假设。L1距离取决于你选择的坐标系统,而L2距离则毫无影响。
如果输入特征向量中有些值有一些重要意义,那么L1距离可能会更加合适。
如果输入的特征向量仅仅只是通用向量,你并不知道其中的含义,那么L2距离可能会更加合适。
你可以在斯坦福大学网站上发布的KNN Demo来尝试利用KNN来进行二维数据的分类并且观察不同距离度量以及超参数对算法性能的影响http://vision.stanford.edu/teaching/cs231n-demos/knn/。
超参数的选择
那么我们如何选择合适的超参数使得我们的算法性能最棒呢
在这里我们有三个选择:
- 我们
只有训练数据
,我们要做的就是让算法在训练数据上达到最好的效果。 - 划分
训练集
以及测试集
,在训练集
上训练,并且在测试集
上测试,我们要做的就是让算法在测试数据
上达到最好的效果 - 划分
训练集``验证集
以及测试集
,我们在训练集
上训练,通过验证集
寻找最优超参数并且在测试集
上进行评估,这是非常稳妥的办法。
当然我们还有一种方法:交叉验证。我们将手头上的数据进行等分,交替划分我们的训练集以及验证集进行算法性能的评估,这在深度学习领域并不常用,如果你不在乎计算资源以及时间成本,我觉得你可以这样试试。
别用在你的图像数据上
实际上我们并不会在图像上使用KNN。观察下图,实际上他们的L2距离是相同的,但是在视觉感知上,它们间的差异是很显著的。这也可以解释为什么在前面所呈现的KNN分类结果图中的一只青蛙会被分类至猫咪这一类别这一情况。
维度灾难
如果需要分类器的性能足够好,则需要数据密集地分散在空间中,否则最近邻点间的距离会相距较远。请看下图,换个说法,维度的增加会导致需要的数据成指数级上升,但是我们能够收集到的数据集是有限的,到最后他们可能不能完全覆盖特征空间,随着特征维度的增加我们的数据密度可能会越来越稀疏。看不懂请参考这篇https://www.zhihu.com/question/27836140
线性分类器
神经网络也可以看做由模块化的线性分类器构建而成,就像搭积木一样。
### 参数模型
这是一只猫的图片,他是一个32x32x3的一个数组。现在,我们需要一个函数F,对于输入的x(猫猫图片数组),我们有w(权重矩阵),使得最后输出10类结果的置信度。比如这张图片是猫猫,那么在输出的十个数字中,属于猫这一类别对应的数值应当是最大的,即最有可能是猫。
权重W可以看作是对训练数据的认知总结
实现原理
在深度学习领域,你可以看到千奇百怪的网络结构,他们其实都是在尝试一个性能较好的F函数形式,你可以将权重与数据进行各种各样的计算、拼接、来达到你想要的结果。当然,最简单的方式则是一个线性分类器。如下图,对于一个拉平到一维(3072x1)的图像,我们则需要一个(10x3072)的权重矩阵W与其相乘使得最后输出10类置信结果。通常,我们会有一个(10x1)的偏置矩阵来调节类别间的不平衡。
可以这样思考bias,对于特征空间中的分类超平面,bias提供了特征空间内平移的自由度。打个比方,二维平面上,对于-1是正类,-2是负类的情况,仅仅只有W会使得分类面是一条过原点的直线,不能将这两类分开,有了bias则可以上下平移成功区分二者
模板匹配
以下图为例,我们可以将权重矩阵的行向量看作是每一类的模板,整个过程类似于模板匹配。
对于训练好的一个线性分类器,当我们还原权重矩阵W,实际上就是将这些模板可视化成图像,这很有意思。我们可以通过图像了解到我们的线性分类器大概是如何理解并分类这些图像的。比如下图第一张飞机的模板,可以看出整体图像偏蓝,中间部分存在一些黑色区域,很感性的认知则是分类器在寻找一张较为蓝色,中间带黑色部分的图像。可以看到马匹的模板中马似乎有两个头,造成这一现象的原因是: 当前的线性分类器只能找寻一个模板,而当一个类别存在变体时,它只能求取其不同表现的平均值来识别其中一种类别。
高维空间
除了模板匹配思路,我们还可以使用另一种方法去思考它。想象一下每一张图片都是高维空间的一个点,线性分类器在这些线性决策边界上尝试画一个分类面来区分这些图像就像下图这样。
问题
线性分类器会在以下数据中失效,我们没法在其中绘制出线性决策边界来区分蓝色和红色。所以,当我们有多模态数据,比如一个类别出现在不同的空间中,这是线性分类器另一个可能出现问题的地方。
权重
下图是三张图片最后对应的得分。我们讨论了线性分类器对应的矩阵向量相乘的函数形式,一旦我们有了这个训练矩阵,我们可以用他得到任何新的训练样本的得分。但是,如何得到正确的权重?这在后续课程将会讲解