深度学习与计算机视觉教程(2) | 图像分类与机器学习基础(CV通关指南·完结)

计算机视觉工程师的万里长征路(附完整学习资料) 文章目录前言1 计算机基础2 编程语言3 数学基础4 图像处理与OpenCV5 机器学习与Scikit-learn6 深度学习与框架7 CV子方向小结 前言 计算机视觉 (CV) 作为人工智能 (AI) 的子方向,近年来十分火热,广泛应用于各大领域,如人脸识别、无人驾驶、智慧交通、智慧医疗和机器人等。其网络模型和算法也是层出不穷,涉及的理论基础也十分广泛。本文将列举计算机视觉工程师的知识结构,后期... 阅读详情

ShowMeAI研究中心


Image Classification pipeline; 深度学习与计算机视觉; Stanford CS231n

本系列为 斯坦福CS231n《深度学习与计算机视觉(Deep Learning for Computer Vision)》的全套学习笔记,对应的课程视频可以在 这里 查看。更多资料获取方式见文末。


引言

图像分类是计算机视觉的核心任务,计算机视觉领域中很多问题(比如 目标检测 和 语义分割),都可以关联到图像分类问题。图像分类 问题,就是已有固定的分类标签集合,然后对于输入的图像,从分类标签集合中找出一个分类标签,最后把分类标签分配给该输入图像。在本篇内容汇总,ShowMeAI将给大家讲解数据驱动的模型算法,包括简单的 KNN 模型和 线性分类模型。

本篇重点

  • 数据驱动方法
  • KNN算法
  • 线性分类

1.图像分类的挑战

对于计算机而言,图像等同于一个像素矩阵;而对人类,图像是包含丰富语义信息的多媒体呈现,对应不同的物体类别,所以对计算机而言存在巨大的语义鸿沟。

比如,给计算机输入如下小猫的图片,计算机图像分类模型会读取该图片,并计算该图片属于集合 { 猫 , 狗 , 帽子 , 杯子 } \{猫, 狗, 帽子, 杯子\} {猫,狗,帽子,杯子} 中各个标签的概率。但读取的输入图像数据是一个由数字组成的巨大的 3 3 3 维数组。

在下图中,猫的图像大小高 600 600 600 像素,宽 800 800 800 像素,有 3 3 3 个颜色通道(红、绿和蓝,简称RGB),因此它包含了 600 × 800 × 3 = 1440000 600 \times 800 \times 3=1440000 600×800×3=1440000 个数字,每个数字都是在范围 0 ∼ 255 0 \sim 255 0∼255 之间的整型,其中 0 0 0 表示全黑, 255 255 255 表示全白。

我们的任务就是把这些数字变成一个简单的标签,比如 「猫」 。

图像分类; 图像分类的挑战; 计算机[眼]中的图像; 2-1

图像分类算法要足够健壮(鲁棒,robust),我们希望它能够适应下述变化及组合:

  • 视角变化(Viewpoint variation):同一个物体,摄像机可以从多个角度来展现。
  • 大小变化(Scale variation):物体可视的大小通常是会变化的(不仅是在图片中,在真实世界中大小也是变化的)。
  • 形变(Deformation):很多东西的形状并非一成不变,会有很大变化。
  • 遮挡(Occlusion):目标物体可能被挡住。有时候只有物体的一小部分(可以小到几个像素)是可见的。
  • 光照条件(Illumination conditions**)**:在像素层面上,光照的影响非常大。
  • 背景干扰(Background clutter):物体可能混入背景之中,使之难以被辨认。
  • 类内差异(Intra-class variation):一类物体的个体之间的外形差异很大,比如椅子。这一类物体有许多不同的对象,每个都有自己的外形。

如下图所示是一些变化和图像识别的挑战:

图像分类; 图像分类的挑战; 一些变化和识别挑战; 2-2

2.数据驱动的方式

一种实现方式是「硬编码」:先获取猫图像的边缘得到一些线条,然后定义规则比如三条线交叉是耳朵之类。然而这种方式的识别效果不好,并且不能识别新的物体。

图像分类; 数据驱动算法; 获取图像边缘得到线条; 2-3

我们会采用数据驱动算法:不具体写出识别每个物体对应的规则,而是针对每一类物体,找到大量样例图片,灌给计算机进行机器学习,归纳模式规律,生成一个分类器模型,总结出区分不同类物体的核心知识要素,然后用训练好的模型,识别新的图像。

图像分类; 数据驱动算法; 输入/学习/评价; 2-4

数据驱动算法过程如下:

  • 输入:输入是包含 N N N 个图像的集合,每个图像的标签是 K K K 种分类标签中的一种。这个集合称为训练集。
  • 学习:这一步的任务是使用训练集来学习每个类的模式规律。一般该步骤叫做分类器训练或者模型学习。
  • 评价:让分类器对它未曾见过的图像进行分类,把分类器预测的标签和图像真正的分类标签 (基本事实) 对比,并以此来评价分类器的质量。

2.1 最邻近算法

本部分内容也可以参考ShowMeAI的 图解机器学习教程 中的文章详解 KNN算法及其应用

我们这里介绍第1个分类器算法:最近邻算法。训练过程只是简单的记住图像数据和标签,预测的时候和训练数据中图片比较找出最接近的输出标签。这个分类器和卷积神经网络没有任何关系,实际中也极少使用,但通过实现它,可以对解决图像分类问题的方法有个基本认识。

1) 图像分类数据集:CIFAR-10

CIFAR-10 是一个非常流行的图像分类数据集。这个数据集包含 10 种分类标签,60000 张 32 × 32 32 \times 32 32×32 的小图像,每张图片含有一个标签。这 60000 张图像被分为包含 50000 张(每种分类 5000 张)图像的训练集和包含 10000 张图像的测试集。

假设现在我们用这 50000 张图片作为训练集,将余下的 10000 作为测试集并打上标签,Nearest Neighbor 算法将会拿着测试图片和训练集中每一张图片去比较,然后将它认为最相似的那个训练集图片的标签赋给这张测试图片。

结果如下图所示,效果并不是特别好。

图像分类; 图像分类数据集; CIFAR-10; 2-5

  • 左边:CIFAR-10 数据库的样本图像;
  • 右边:第一列是测试图像,后面是使用Nearest Neighbor算法,根据像素差异,从训练集中选出的10张最类似的图片

那么具体如何比较两张图片呢?我们有一些距离度量计算方法,下面展开介绍一下。

2) L1 距离(曼哈顿距离)

距离度量的数学知识也可以参考ShowMeAI的系列教程 图解AI数学基础 中的文章 线性代数与矩阵论 对各种距离度量的展开讲解

在本例中,就是比较 32 × 32 × 3 32 \times 32 \times 3 32×32×3 的像素块。最简单的方法就是逐个像素比较,最后将差异值全部加起来。即将两张图片先转化为两个向量 I 1 I_{1} I1​ 和 I 2 I_{2} I2​,然后计算他们的 L1 距离:

d 1 ( I 1 , I 2 ) = ∑ p ∣ I 1 p − I 2 p ∣ d_{1} (I_{1} ,I_{2} )=\sum_{p}\vert I_{1}^p -I_{2}^p \vert d1​(I1​,I2​)=p∑​∣I1p​−I2p​∣

  • 其中 p p p 为像素点, I p I^p Ip 表示第 p p p 个像素点的值。
  • 两张图片使用 L1 距离来进行比较,即逐个像素求差值,然后将所有差值加起来得到一个数值。如果两张图片一模一样,那么 L1 距离为 0 0 0;但是如果两张图片很是不同,那 L1 值将会非常大。

下图是仅一个RGB通道的 4 × 4 4 \times 4 4×4 图片计算 L1 距离。

图像分类; L1距离; 4X4图片计算; 2-6

下面看具体编程如何实现:

① 首先,我们将 CIFAR-10 的数据加载到内存中,并分成4个数组:训练数据和标签,测试数据和标签。

Xtr, Ytr, Xte, Yte = load_CIFAR10('data/cifar10/') # 这个函数可以加载CIFAR10的数据
# Xtr是一个50000x32x32x3的数组,一共50000个数据,
# 每条数据都是32行32列的数组,数组每个元素都是一个三维数组,表示RGB。
# Xte是一个10000x32x32x3的数组;
# Ytr是一个长度为50000的一维数组,Yte是一个长度为10000的一维数组。
Xtr_rows = Xtr.reshape(Xtr.shape[0], 32 * 32 * 3) 
# Xtr_rows是50000x3072的数组,按每个像素点排列,每个像素点有三个值。
Xte_rows = Xte.reshape(Xte.shape[0], 32 * 32 * 3) 
# Xte_rows是10000x3072的数组
''' shape会返回数组的行和列数元组:(行数,列数),shape[0]表示行数, 
Xtr.shape[0]会返回50000;Xtr.shape会返回(50000,32,32,3)
Xtr.reshape(50000,3072)会将Xtr 重构成50000x3072数组,等于 np.reshape(Xtr, (50000,3072))'''
  • Xtr(大小是50000x32x32x3)存有训练集中所有的图像
  • Xte(大小是10000x3072)存有测试集中所有的图像
  • Ytr 是对应的长度为50000的1维数组,存有图像对应的分类标签(从0到9)
  • Yte 对应长度为10000的1维数组

现在我们得到所有的图像数据,每张图片对应一个长度为 3072 的行向量。

② 接下来训练一个分类器并评估效果。我们常常使用准确率作为评价标准,它描述了我们预测正确的得分。

本例中OK,很多其他应用中准确率并不一定是最佳的评估准则,可以参考ShowMeAI的 图解机器学习教程 中的文章详解 模型评估方法与准则

nn = NearestNeighbor() # 创建一个最邻近分类器对象
nn.train(Xtr_rows, Ytr) # 用训练图片数据和标签训练分类器
Yte_predict = nn.predict(Xte_rows) # 预测测试图片的标签
# 并输出预测准确率,是一个平均值
print 'accuracy: %f' % ( np.mean(Yte_predict == Yte) )
  • 请注意以后我们实现的所有分类器都需要有这个接口函数(API):train(X, y) 函数。该函数使用训练集的数据和标签来进行训练。
  • 从其内部来看,类应该实现一些关于标签和标签如何被预测的模型。这里还有个 predict(X) 函数,它的作用是预测输入的新数据的分类标签。

下面就是使用 L1 距离的 Nearest Neighbor 分类器的实现:

import numpy as np

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

  def train(self, X, y):
    """ X 是 NxD 维的数组,每一行都是一个样本,比如一张图片,D 是样本的数据维度;
    Y 是长度为 N 的一维数组。"""
    # 最邻近分类器只是简单的记住所有的训练数据
    self.Xtr = X
    self.ytr = y

  def predict(self, X):
    """ X 是 NxD 维的数组,每一行都是一个希望预测其标签的样本 """
    num_test = X.shape[0]
    # 确保输出的标签数据类型和输入的标签格式一致,长度是测试样本数
    Ypred = np.zeros(num_test, dtype = self.ytr.dtype)

    # 循环所有测试样本数,即测试数组的行数
    for i in range(num_test):
      # 为第 i 张测试图片找到最接近的训练图片
      # 使用 L1 距离 (差值的绝对值求和)
      '''self.Xtr - X[i,:] 利用传播机制,求测试集第 i 张图片对应的行向量和
      训练集所有图片行向量的差值,得到一个一个50000x3072的差值矩阵;
      abs(self.Xtr - X[i,:] )会将矩阵所有元素求绝对值;
      然后axis = 1 会对差值矩阵按行求和,最终得到一个长度为50000的一维
      数组,存放第 i 张图片和训练集所有50000张图片的 L1 距离。'''
      distances = np.sum(np.abs(self.Xtr - X[i,:]), axis = 1)
      min_index = np.argmin(distances) # 获取距离最小的训练集图片索引
      Ypred[i] = self.ytr[min_index] # 预测第 i 张测试集图片的标签时与其最接近的训练集图片索引

    return Ypred

这段代码的训练时间复杂度为 O ( 1 ) O(1) O(1),因为只是简单的存储数据,不管数据多大,都是一个相对固定的时间;如果训练集有 N N N 个样本,则预测时间复杂度为 O ( N ) O(N) O(N),因为测试图片要和训练集每张图片进行比较。

这是一个不太好的分类器,实际对分类器的要求是,我们希望它预测的时候要快,训练的时候可以慢。

这段代码跑 CIFAR-10,准确率能达到 38.6 % 38.6\% 38.6%。这比随机猜测的 10 % 10\% 10% 要好,但是比人类识别的水平和卷积神经网络能达到的 95 % 95\% 95% 还是差很多。

3) L2距离(欧式距离)

距离度量的数学知识也可以参考ShowMeAI的系列教程图解AI数学基础中的文章线性代数与矩阵论对各种距离度量的展开讲解

另一个常用的方法是 L2 距离,从几何学的角度,可以理解为它在计算两个向量间的欧式距离。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∑​(I1p​−I2p​)2 ​

  • 依旧是在计算像素间的差值,只是先求差值的平方,然后把这些平方全部加起来,最后对这个和开方。

此时的代码只需改动计算距离差异的一行:

distances = np.sqrt(np.sum(np.square(self.Xtr - X[i,:]), axis = 1))
'''np.square(self.Xtr - X[i,:]) 会对差值矩阵的每一个元素求平方'''

注意在这里使用了 np.sqrt,但是在实际中可能不用。因为对不同距离的绝对值求平方根虽然改变了数值大小,但依然保持了不同距离大小的顺序。这个模型,正确率是 35.4 % 35.4\% 35.4%,比刚才低了一点。

4) L1 和 L2比较

在 L1 距离更依赖于坐标轴的选定,坐标轴选择不同 L1 距离也会跟着变化,判定的数据归类的边界会更趋向于贴近坐标系的轴来分割所属区域,而 L2 的话相对来说与坐标系的关联度没那么大,会形成一个圆,不跟随坐标轴变化。

图像分类; 最近邻算法; L1距离V.S.L2距离; 2-7

在面对两个向量之间的差异时,L2比 L1 更加不能容忍这些差异。也就是说,相对于1个巨大的差异,L2 距离更倾向于接受多个中等程度的差异(因为会把差值平方)。

L1 和 L2 都是在 p-norm 常用的特殊形式。

当图像中有特别在意的特征时可以选择 L1 距离;当对图像中所有元素未知时,L2距离会更自然一些。最好的方式是两种距离都尝试,然后找出最好的那一个。

2.2 k最近邻分类器

本部分内容也可以参考ShowMeAI的图解机器学习教程中的文章详解KNN算法及其应用

只用最相似的 1 张图片的标签来作为测试图像的标签,有时候会因为参照不够多而效果不好,我们可以使用 k-Nearest Neighbor 分类器。KNN的思想是:找最相似的 k k k 个图片的标签, k k k 中数量最多的标签作为对测试图片的预测。

当 k = 1 k=1 k=1 的时候,k-Nearest Neighbor 分类器就是上面所说的最邻近分类器。

如下图所示,例子使用了2维的点来表示图片,分成3类(红、绿、蓝)。不同颜色区域代表的是使用 L2距离的分类器的决策边界。

图像分类; NN分类器V.S.KNN分类器; 2-8

上面示例展示了NN分类器和KNN( k = 5 k=5 k=5)分类器的区别。从直观感受上就可以看到,更高的 k k k 值可以让分类的效果更平滑,使得分类器对于异常值更有抵抗力。

  • 在 k = 1 k=1 k=1 时,异常的数据点(比如:在蓝色区域中的绿点)制造出一个不正确预测的孤岛。
  • 在 k = 5 k=5 k=5 时分类器将这些不规则都平滑了,使得它针对测试数据的**泛化(generalization)**能力更好。
    • 注意,5-NN 中也存在一些白色区域,这些区域是因为5个近邻标签中的最高数相同导致的分类模糊(即图像与两个以上的分类标签绑定)。
    • 比如:2 个邻居是红色,2 个邻居是蓝色,还有 1 个是绿色,所以无法判定是红色还是蓝色。

1) 超参数调优

模型调优,超参数的实验选择方法也可以参考ShowMeAI的文章 图解机器学习 | 模型评估方法与准则 和 深度学习教程 | 网络优化:超参数调优、正则化、批归一化和程序框架

  • KNN 分类器需要设定 k k k 值,如何选择 k k k 值最合适?
  • L1 距离和 L2 距离选哪个比较好(还是使用其他的距离度量准则例如点积)?

所有这些选择,被称为超参数(hyperparameter)。在基于数据进行学习的机器学习算法设计中,超参数是很常见的。

超参数是需要提前设置的,设置完成后模型才可以训练学习,具体的设置方法通常要借助于实验,尝试不同的值,根据效果表现进行选择。

特别注意:不能使用测试集来进行调优。

  • 如果使用测试集来调优,而且算法看起来效果不错,真正的危险在于:算法实际部署后,性能可能会远低于预期。这种情况,称之为算法对测试集过拟合。

  • 大家可以理解为,如果使用测试集来调优,实际上就是把测试集当做训练集,由测试集训练出来的算法再预测测试集,性能自然会看起来很好,但实际部署起来效果就会差很多。

  • 最终测试的时候再使用测试集,可以很好地近似度量分类器的泛化性能。

测试数据集只能使用一次,而且是在训练完成后评价最终模型时使用,不可用来调优!

方法1:设置验证集

从训练集中取出一部分数据用来调优,称之为 验证集(validation set)。以 CIFAR-10 为例,可以用 49000 个图像作为训练集,用 1000 个图像作为验证集。验证集其实就是作为假的测试集来调优。

图像分类; 超参数调优; 设置验证集; 2-9

代码如下:

# 假设 Xtr_rows, Ytr, Xte_rows, Yte 还是和之前一样
# Xtr_rows 是 50,000 x 3072 的矩阵
Xval_rows = Xtr_rows[:1000, :] # 取前 1000 个训练集样本作为验证集
Yval = Ytr[:1000]
Xtr_rows = Xtr_rows[1000:, :] # 剩下的 49,000 个作为训练集
Ytr = Ytr[1000:]

# 找出在验证集表现最好的超参数 k 
validation_accuracies = []
for k in [1, 3, 5, 10, 20, 50, 100]:
  # 使用一个明确的 k 值评估验证集
  nn = NearestNeighbor()
  nn.train(Xtr_rows, Ytr)
  # 这里假设一个修正过的 NearestNeighbor 类,可以把 k 值作为参数输入
  Yval_predict = nn.predict(Xval_rows, k = k)
  acc = np.mean(Yval_predict == Yval)
  print 'accuracy: %f' % (acc,)

  # 把每个 k 值和相应的准确率保存起来
  validation_accuracies.append((k, acc))

程序结束后,作图分析出哪个 k k k 值表现最好,然后用这个 k k k 值来跑真正的测试集,并作出对算法的评价。

方法2:交叉验证

训练集数量较小(因此验证集的数量更小)时,可以使用交叉验证的方法。还是用刚才的例子,如果是交叉验证集,我们就不是取 1000 个图像,而是将训练集平均分成 5 份,每份 10000 张图片,其中4份用来训练,1份用来验证。然后我们循环着取其中4份来训练,其中1份来验证,最后取所有5次验证结果的平均值作为算法验证结果。

图像分类; 超参数调优; 交叉验证; 2-10

下面是 5 份交叉验证对 k k k 值调优的例子。针对每个 k k k 值,得到 5 次验证的准确率结果,取其平均值,然后对不同 k k k 值的平均表现画线连接。

图像分类; 超参数调优; k折交叉验证效果; 2-11

上图可以看出,本例中,当 k = 7 k=7 k=7 的时算法表现最好(对应图中的准确率峰值)。如果我们将训练集分成更多份数,直线一般会更加平滑(噪音更少)。

实际情况下,深度学习不会使用交叉验证,主要是因为它会耗费较多的计算资源。一般直接把训练集按照 50 % ∼ 90 % 50\% \sim 90\% 50%∼90% 的比例分成训练集和验证集。但是训练集数量不多时可以使用交叉验证,一般都是分成3、5和10份。

2) KNN分类器优点

① 易于理解,实现简单。
② 算法的训练不需要花时间,因为其训练过程只是将训练集数据存储起来。

3) KNN分类器缺点

① 测试要花费大量时间

  • 因为每个测试图像需要和所有存储的训练图像进行比较在实际应用中,关注测试效率远远高于训练效率;

② 使用像素差异来比较图像是不够的,图片间 L2 距离小,更多的是被背景主导而不是图片语义内容本身主导,往往背景相似图片的 L2 距离就会小。

  • 也就是说,在高维度数据上,基于像素的相似和基于感官上的相似非常不同。感官上不同的两张图片,可能有相同的 L2 距离。

③ 维度灾难

  • KNN 有点像训练数据把样本空间分成几块,我们需要训练数据密集的分布在样本空间里,否则测试图片的最邻近点可能实际距离会非常远,导致和最接近的训练集样本实际上完全不同。但是如果使训练数据密集分布,需要的训练集数量指数倍增加,是数据维度的平方。

4) 实际应用KNN

下面是一些对于实际应用 KNN 算法的建议

① 预处理数据

  • 对数据中的特征进行归一化(normalize),让其具有零均值(zero mean)和单位方差(unit variance)。本小节不讨论,是因为图像中的像素都是同质的,不会表现出较大的差异分布,不需要标准化处理。

② 降维

  • 如果数据是高维数据,考虑使用降维方法,比如 PCA 或者随机投影。

③ 将数据随机分入训练集和验证集

  • 一般规律, 70 % ∼ 90 % 70\% \sim 90\% 70%∼90% 数据作为训练集。这个比例根据算法中有多少超参数,以及这些超参数对于算法的预期影响来决定。
  • 如果需要预测的超参数很多,那么就应该使用更大的验证集来有效地估计它们;如果担心验证集数量不够,那么就尝试交叉验证方法;如果计算资源足够,使用交叉验证更好(份数越多,效果越好,也更耗费计算资源)。

④ 在验证集上调优

  • 尝试足够多的 k k k 值,尝试 L1 和 L2 两种范数计算方式。

⑤ 加速分类器

  • 如果分类器跑得太慢,尝试使用ANN库(比如 FLANN 来加速这个过程,其代价是降低一些准确率。

⑥ 对最优的超参数做记录

  • 记录最优参数后,不要使用最优参数的算法在完整的训练集上运行并再次训练,这样做会破坏对于最优参数的估计。
  • 直接使用测试集来测试用最优参数设置好的最优模型,得到测试集数据的分类准确率,并以此作为你的KNN分类器在该数据上的性能表现。

3.线性分类:评分函数

3.1 线性分类概述

KNN 模型中训练过程中没有使用任何参数,只是单纯的把训练数据存储起来(参数 k 是在预测中使用的,找出 k k k 个接近的图片,然后找出标签最多的,并且 k k k 是超参数,是人为设定的)。

与之相对的是参数模型,参数模型往往会在训练完成后得到一组参数,之后就可以完全扔掉训练数据,预测的时候只需和这组参数做某种运算,即可根据运算结果做出判断。线性分类器是参数模型里最简单的一种,但却是神经网络里很重要的基础模块。

线性分类的方法由两部分组成:

① 评分函数(score function)

  • 它是原始图像数据到类别分值的映射。

② 损失函数(loss function)

  • 它用来量化评分函数计算的分数与真实标签之间的一致性。该方法可转化为一个最优化问题,在最优化过程中,通过更新评分函数的参数来最小化损失函数值。

3.2 评分函数

评分函数将图像的像素值映射为各个分类类别的得分,得分高低代表图像属于该类别的可能性高低。上面的所有说明都比较抽象,下面以具体的例子说明。

重新回到 KNN 使用的 CIFAR-10 图像分类数据集。

图像分类; 评分函数; 参数化方式-线性分类器; 2-12

假设我们的训练集有 N N N 个样本,这里 N = 50000 N=50000 N=50000,每个样本 x i b ∈ R D x_{i}b \in R^D xi​b∈RD,其中 i = 1 , 2 , ⋯   , N i = 1,2,\cdots,N i=1,2,⋯,N, D = 3072 D=3072 D=3072;每个 x i x_{i} xi​ 对应着一个标签 y i y_{i} yi​,$ y_{i}$ 在 [ 1 , K ] [1, K] [1,K] 上取值, K K K 表示总分类数,这里 K = 10 K=10 K=10。现在可以定义评分函数: f : R D → R K f:R^D \rightarrow R^K f:RD→RK,即把一个 D D D 维的图像映射为 K K K 个类别的分数。

最简单的模型是线性模型:参数和输入数据相乘。即:

f ( x i , W , b ) = W x i + b f(x_{i},W,b)=Wx_{i}+b f(xi​,W,b)=Wxi​+b

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

还是以 CIFAR-10 为例, x i x_{i} xi​ 就包含了第 i i i 个图像的所有像素信息,这些信息被拉成为一个 [ 3072 × 1 ] [3072 \times 1] [3072×1] 的列向量, W W W 大小为 [ 10 × 3072 ] [10 \times 3072] [10×3072], b b b 的大小为 [ 10 × 1 ] [10 \times 1] [10×1]。因此,输入 3072 3072 3072 个数字(原始像素数值),函数输出 10 10 10 个数字(不同分类得到的分值),是一个 3072 3072 3072 维到 10 10 10 维的映射。

注意:

  • 常常混用权重(weights)和参数(parameters)这两个术语,实际上数据和参数相乘,就相当于数据占的比重,这个权重就是参数值;
  • 该方法的一个优势是训练数据是用来学习参数 W W W 和 b b b 的,一旦训练完成,训练数据就可以丢弃,留下学习到的参数即可。当测试图像时可以简单地把图像数据输入给函数,函数计算出的分类分值来进行分类;
  • 输入数据 ( x i , y i ) (x_{i},y_{i}) (xi​,yi​) 是给定且不可改变的,但参数 W W W 和 b b b 是可改变的。目标就是通过改变这些参数,使得计算出来的分类分值情况和训练集中图像数据的真实类别标签相符;
  • 只需一个矩阵乘法和一个矩阵加法就能对一个测试数据分类,这比 KNN 中将测试图像和所有训练数据做比较的方法要高效很多。

3.3 理解线性分类器

1) 理解一:W是所有分类器的组合

图像分类; 线性分类器; 理解1-计算评分函数; 2-13

如上图所示,将小猫的图像像素数据拉伸成一个列向量 x i x_i xi​,这里为方便说明,假设图像只有4个像素(都是黑白像素,不考虑RGB通道),即 D = 4 D=4 D=4;有 3 3 3 个分类(红色代表猫,绿色代表狗,蓝色代表船,颜色仅代表不同类别,和 RGB 通道没有关系),即 K = 3 K=3 K=3。 W W W 矩阵乘列向量 x i x_i xi​,得到各个分类的分值。

实际上,我们可以看到,参数矩阵 W W W 相当于是三个分类器的组合, W W W 的每一行都是一个分类器,分别对应猫、狗、船。在线性模型中每个分类器的参数个数与输入图像的维度相当,每个像素和对应的参数相乘,就表示该像素在该分类器中应占的比重。

需要注意的是,这个 W W W 一点也不好:猫分类的分值非常低。从上图来看,算法倒是觉得这个图像是一只狗。

我们可以这样理解,线性分类器会计算图像中 3 个颜色通道中所有像素的值与权重矩阵的乘积,进而得到每个类别分值。根据我们对权重设置的值,对于图像中的某些位置的某些颜色,函数表现出喜好或者厌恶(根据每个权重的符号而定)。

举例:可以想象 「船」 分类就是被大量的蓝色所包围(对应的就是水)。那么 「船」 分类器在蓝色通道上的权重就有很多的正权重(它们的出现提高了 「船」 分类的分值),而在绿色和红色通道上的权重为负的就比较多(它们的出现降低了 「船」 分类的分值)。

结合上面的小猫示例,猫分类器对第二个位置的像素比较 「厌恶」 ,而恰好输入的小猫图像第二个位置像素值很大,最终计算得到一个很低的分数(当然,这个分类器是错误的)。

2) 理解二:将线性分类器看做模板匹配

把权重 W W W 的每一行看作一个分类的模板,一张图像对应不同分类的得分,是通过使用内积(也叫点积)来比较图像和模板,然后找到和哪个模板最相似。

这种理解角度下,线性分类器在利用学习到的模板,和输入图像做模板匹配。我们设置可以把其视作一种高效的KNN,不同的是不再使用所有的训练集的图像来比较,而是每个类别只用了一张图片来表征(这张图片是我们学习到的模板,而不存在训练集中),而且我们会更换度量标准,使用(负)内积来计算向量间的距离,而不是使用 L1 或者 L2 距离。

图像分类; 线性分类器; 理解2-10个学习后模板; 2-14

上图是以 CIFAR-10 为训练集,学习结束后的权重的例子。可以看到:

  • 马的模板看起来似乎是两个头的马,这是因为训练集中的马的图像中马头朝向各有左右造成的。线性分类器将这两种情况融合到一起了;
  • 汽车的模板看起来也是将几个不同的模型融合到了一个模板中,这个模板上的车是红色的,是因为 CIFAR-10 中训练集的车大多是红色的。线性分类器对于不同颜色的车的分类能力是很弱的,但是后面可以看到神经网络是可以完成这一任务的;
  • 船的模板如期望的那样有很多蓝色像素。如果图像是一艘船行驶在大海上,那么这个模板利用内积计算图像将给出很高的分数。

3) 理解三:将图像看做高维空间的点

既然定义每个分类类别的分值是权重和图像的矩阵乘积,那么每个分类类别的分数就是这个空间中的一个线性函数的函数值。我们没办法可视化 3072 3072 3072 维空间中的线性函数,但假设把这些维度挤压到二维,那么就可以看看这些分类器在做什么了:

图像分类; 线性分类器; 理解3-二维空间划分; 2-15

在上图中,每张输入图片是一个点,不同颜色的线代表 3 个不同的分类器。以红色的汽车分类器为例,红线表示空间中汽车分类分数为 0 0 0 的点的集合,红色的箭头表示分值上升的方向。所有红线右边的点的分数值均为正,且线性升高。红线左边的点分值为负,且线性降低。

从上面可以看到, W W W 的每一行都是一个分类类别的分类器。对于这些数字的几何解释是:

  • 如果改变 W W W 一行的数字取值,会看见分类器在空间中对应的直线开始向着不同方向旋转。而偏置项 b b b,则允许分类器对应的直线平移。
  • 需要注意的是,如果没有偏置项,无论权重如何,在 x i = 0 x_{i}=0 xi​=0 时分类分值始终为 0 0 0。这样所有分类器的线都不得不穿过原点。

3.4 偏置项和权重合并

上面的推导过程大家可以看到:实际我们有权重参数 W W W 和偏置项参数 b b b两个参数,分开处理比较冗余,常用的优化方法是把两个参数放到同一个矩阵中,同时列向量 x i x_{i} xi​ 就要增加一个维度,这个维度的数值是常量 1 1 1,这就是默认的偏置项维度。

如下图所示,新的公式就简化成如下形式:

f ( x i , W , b ) = W x i f(x_{i},W,b)=Wx_{i} f(xi​,W,b)=Wxi​

图像分类; 线性分类器; W和b合并后示意图; 2-16

还是以 CIFAR-10 为例,那么 x i x_{i} xi​ 的大小就变成 [ 3073 × 1 ] [3073 \times 1] [3073×1],而不是 [ 3072 × 1 ] [3072 \times 1] [3072×1] 了,多出了包含常量1的1个维度; W W W 大小就是 [ 10 × 3073 ] [10 \times 3073] [10×3073] 了, W W W 中多出来的这一列对应的就是偏差值 b b b:

经过这样的处理,最终只需学习一个权重矩阵,无需学习两个分别装着权重和偏差的矩阵。

3.5 图像数据预处理

在上面的例子中,所有图像都是使用的原始像素值( 0 ∼ 255 0 \sim 255 0∼255)。在机器学习中,我们经常会对输入的特征做归一化(normalization)处理,对应到图像分类的例子中,图像上的每个像素可以看做一个特征。

在实践中,我们会有对每个特征减去平均值来中心化数据这样一个步骤。

在这些图片的例子中,该步骤是根据训练集中所有的图像计算出一个平均图像值,然后每个图像都减去这个平均值,这样图像的像素值就大约分布在 [ − 127 , 127 ] [-127, 127] [−127,127] 之间了。

后续可以操作的步骤包括归一化,即让所有数值分布的区间变为 [ − 1 , 1 ] [-1, 1] [−1,1]。

3.6 线性分类器失效的情形

图像分类; 线性分类器; 难以处理的情形; 2-17

线性分类器的分类能力实际是有限的,例如上图中的这三种情形都无法找到合适的直线区分开。其中第 1 个 case 是奇偶分类,第 3 个 case 是有多个模型。

4.拓展学习

可以点击 B站 查看视频的【双语字幕】版本

【字幕+资料下载】斯坦福CS231n | 面向视觉识别的卷积神经网络 (2017·全16讲)

5.要点总结

  • 图像分类中的困难与挑战
  • 数据驱动方法、最邻近算法、 L1 和 L2 距离
  • KNN分类器、超参数调优、KNN的优缺点与实际应用
  • 线性分类的概念、评分函数的理解、参数合并、数据预处理、线性分类器局限性

ShowMeAI 斯坦福 CS231n 全套解读

ShowMeAI 系列教程推荐

showmeai用知识加速每一次技术成长

【计算机视觉知识库】CV学习路线/从头学系列【持续更新】 记录自己计算机视觉的学习路线,总结每一部分的学习内容,加油呀,构建CV知识库!酷! 阅读详情

相关推荐

深度学习与计算机视觉(CV)介绍

深度学习与计算机视觉(CV)介绍 深度学习 学习⽬标 知道什么是深度学习 知道深度学习的应⽤场景 什么是深度学习 在介绍深度学习之前,我们先看下⼈⼯智能,机器学习和深度学习之间的关系: 机器学习是实现⼈⼯智能的⼀种途径,深度学习是机器学习的⼀个⼦集,也就是说深度学习是实现机器学习的⼀种⽅法。与机器学习算法的主要区别如下图所示: 传统机器学习算术依赖人工设计特征,并进行特征提取,而深度学习方法不需要人工,而是依赖算法自动提取特征。深度学习模仿人类大脑的运行方式,从经验中学习获取知识。这也是深度学习被

最白の白菜的博客 9147

机器学习——图像分类

1 图像分类的概念 1.1 什么是图像分类? 图像分类,根据图像信息中所反映出来的不同特征,把不同类别的目标区分开来的图像处理方法 1.2 图像分类的难度 ●任何拍摄情 况的改变都将提升分类的难度 1.3 CNN如何进行图像分类 ●数据驱动型方法通用流程 1.收集图像以及对应的标签,形成数据集 2.使用机器学习训练一个分类器 3.在新的图像.上测试这个分类器 ​​​ 1.4 图像分类指标 精确率:查得准不准?...

向着光的那方 3万+

计算机视觉怎么学习?CV入门学习路线

学习计算机视觉(Computer Vision)可以分为五个阶段:基础打底 → 工具掌握 → 深度学习视觉 → 项目实战 → 提升研究/就业能力。下面是详细路线图(适合本科/专科/转行人群):

OpenCVtuxiang的博客 2836

图像分类之:经典机器学习 Battle 深度学习

本文写于2018.08.31, 生日前夕。 前段时间,有个朋友和我提到,自己最近正打算用机器来判别图片中的场景是古镇还是园林,所以我这一期特地写了一篇文章,来描述图像的分类算法。由于最近工作略忙,所以文章断断续续写了好久,终于在自己生日前夕完成,希望可以有所帮助,这样我就可以安心回家吃蛋糕了。 用机器来做图片分类简单来讲就是给机器输入一张图片,机器会输出这幅图片里面的内容。机器学习中提供...

weixin_39329548的博客 7427

深度学习与计算机视觉教程:斯坦福CS231n · 全套笔记

本篇内容是组织的系列教程入口,本教程依托于斯坦福Stanford出品的【】方向专业课程,根据课程视频内容与课程笔记,结合补充资料,针对深度学习与计算机视觉方向的主题做了全面梳理与制作,希望给大家提供专业细致而直观易懂的学习教程。等主题。

weixin_42907150的博客 2742

计算机视觉怎么入门?超详细计算机视觉学习路线!CV入门

入门计算机视觉,建议从基础知识 + 工具实操 + 简单项目三步走,掌握基本概念、图像处理技能、再接触深度学习模型。下面是一个从零入门的详细步骤,适合没有基础或刚入门的人:

OpenCVtuxiang的博客 2627

机器学习(基本图像分类)

1.安装Anaconda3 下载地址:https://www.anaconda.com/distribution/#windows 一路下一步即可…… 详细:https://blog.youkuaiyun.com/ychgyyn/article/details/82119201 2.安装TensorFlow python -m pip install --upgrade pip pip ins...

吃四碗饭的嘤嘤怪的博客 9686

机器学习与计算机视觉入门项目——视频投篮检测(一)

机器学习与计算机视觉入门项目——视频投篮检测(一) 随着机器学习、深度学习技术的迅猛发展,计算机视觉无疑是近年来发展最快的AI领域之一。正因如此,互联网上有关计算机视觉和机器学习、深度学习的社区、博文、论文、代码、算法框架等极大地丰富起来,给初入该领域的新人丰富的参考资料。同时计算机视觉比较易于理解,适合新手入门,培养最基本的工程素养和代码项目经验,从而了解处理具体计算机科学相关领域的基本流程。...

hhy_csdn的博客 8157

[机器学习] 基于torch的CNN图像分类

基于torch搭建一个cnn网络模型,并使用数据对其进行训练、验证和测试的实验过程。

好风凭借力 2607

使用机器学习进行图像分类

不同的算法有不同的优缺点,应根据具体情况选择合适的算法。使用准备好的数据集和预处理后的特征,我们可以开始训练图像分类模型。训练的目标是使模型能够准确地预测新的未见过的图像。综上所述,使用机器学习进行图像分类涉及数据准备、特征提取、选择算法、数据预处理、模型训练和模型评估等步骤。通过合理地选择算法和优化模型,我们可以实现准确且高效的图像分类任务。请注意,以上提供的代码仅为示例,实际的图像分类任务可能需要根据具体情况进行调整和改进。图像分类是机器学习中的一个重要任务,它涉及将输入的图像分配到预定义的类别中。

StyVue的博客 632

计算机视觉框架OpenMMLab(二):图像分类基础

本次主要复习深度学习图像分类知识,学习图像分类最新的模型,计算机视觉框架OpenMMLab的MMClassification工具基本使用,为后续实战做铺垫。

专注大数据与人工智能技术分享,欢迎私信加群互相学习! 5054

计算机视觉 vs 机器视觉 | 机器学习 vs 深度学习:核心差异与行业启示

目标是赋予计算机类似人类的视觉理解能力,通过算法对图像或视频中的目标进行识别、跟踪和语义理解。其核心是研究如何从二维图像反推三维世界的结构和规律。例如,自动驾驶中通过多摄像头融合实现道路场景理解,属于典型的CV任务。

懒人的技术笔记 2434

【深度学习基础】一篇带你入门计算机视觉(从计算机视觉任务出发)

本文从核心任务切入,系统解析图像分类、目标检测、图像分割和生成式视觉四大方向。文章以ResNet、YOLO、U-Net和GAN等经典模型为脉络,详解卷积神经网络、注意力机制等技术原理,并结合PyTorch实战项目演示算法实现。通过医疗影像分析、自动驾驶等案例,串联数据预处理、模型训练与部署全流程,为零基础读者提供从理论到实战的完整学习路径,助力快速构建计算机视觉知识体系。

十二月的猫 4000

深度学习与计算机视觉教程:斯坦福CS231n · 全套笔记解读

本教程依托于 Stanford 斯坦福大学的《CS231n:深度学习与计算机视觉》,对深度学习与计算机视觉方向的图像分类、CNN、RNN、目标检测、图像分割、生成模型等各个主题做了体系化的梳理

ShowMeAI研究中心 1万+

机器学习方法的图像分类

有界面 机器学习方法多种方法的图像分类器源码 基于svm ,贝叶斯 ,等多种方法 , 有界面 机器学习方法多种方法的图像分类器源码 基于svm ,贝叶斯 ,等多种方法 ,

CESM笔记——CESM1.0-CESM1.2.2-CESM2.1.3三个版本模式工作流对比

最近测试了CESM1.0,CESM1.2.2和CESM2.1.3三个版本,不同版本在workflow上有一些区别,来做点笔记。 CESM1.0 测试compset:B_2000,F_2000 workflow: 1. create_newcase -case ~/CESM/cesm1_0/script/B_2000 -compset B_2000 -res f19_g16 -mach tianhe 2. cd B_2000 (optional) env_mach_pes.xml ##修改核数,

砍柴姑娘Jourosy的博客 4946

《人工智能、机器学习、深度学习、CNN知识点整理》

文章目录1 Artificial Intelligence (AI,人工智能)2 Machine Learning(ML,机器学习)2.1 监督学习和无监督学习2.2 监督学习的线性回归学习算法2.3 机器学习的常见算法2.4 人工神经网络3 Deep Learning(DL,深度学习)4 Convolutional Neural Networks(CNN,卷积神经网络)5 CNN在CV(计算机视觉)上的应用5.1 图像分类 (自己的理解,如有理解有误的地方请谅解!!!) 我们常常会有一个疑惑,

yuansiming0920的博客 3421

【5G NB-IoT NTN】3GPP R17 NB-IoT NTN介绍_nbiot ntn

你的支持,我的动力;祝各位前程似锦,offer不断,步步高升!!!” />你的支持,我的动力;祝各位前程似锦,offer不断,步步高升!!!更多资料点击此处获qu!!

2401_83703866的博客 3170

【机器学习】大模型环境下的应用:计算机视觉的探索与实践

通过在一个大型数据集上训练好的模型,可以将其用于小规模数据集的任务,从而减少训练时间和资源消耗,同时提升模型的泛化能力。传统方法主要依赖于手工设计的特征提取器和分类器,但随着深度学习方法的兴起,特别是卷积神经网络的出现,计算机视觉的性能得到了显著提升。判别器是另一个神经网络,它接收一张图像作为输入(真实的或由生成器生成的),并输出一个概率,表示输入图像来自训练数据(真实图像)的概率。在训练过程中,生成器和判别器交替训练,以便不断提升生成器生成逼真图像的能力,并提高判别器准确识别生成器生成图像的能力。

2302_81249757的博客 6081

硬件电路(22)-TTL和232切换电路

工作中会遇到TTL和232电平的通信的状态,为了实现一种便捷的切换方式,参考了一些文章,提供一种电路方便大家使用。

剑藏锋的博客 1868

【论文复现】Applied Intelligence 2025:Auto-PU正例无标签学习的自动化实现与GPT-5.4辅助编程实战

正例-无标签学习(Positive-Unlabelled Learning, PU Learning)是机器学习领域处理"只有正例标签,负例完全未知"场景的重要技术。本文基于2025年发表于Applied Intelligence的最新研究成果,详细阐述如何从零复现Auto-PU框架(包含GA-Auto-PU、BO-Auto-PU、EBO-Auto-PU三种优化器)。

nmdbbzcl的博客 1391
上一篇: 深度学习与计算机视觉教程(1) | 引言与知识基础(CV通关指南·完结)
下一篇: 深度学习与计算机视觉教程(3) | 损失函数与最优化(CV通关指南·完结)
ShowMeAI
博客等级 码龄5年 6514粉丝 672原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShowMeAI

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值