CS231n章节一:图像分类

关于本项目的声明请点CS231翻译及笔记项目目录,在此不再重述。
-------------------------------------------------——--------------------------------------------------------------------

Convolutional Neural Networks for Visual Recognition——视觉识别的卷积神经网络方法

目录

第一部分:神经网络

1.1-图像分类:数据驱动方法,k近邻法,训练集/数值/文本 分类
1.2-线性分类器:支持向量机,分类器???
1.3-最优化:随机梯度下降法
1.4-反向传播,直觉???
1.5-神经网络1:建立架构
1.6-神经网络2:建立数据和损失???
1.7-神经网络3:学习和预测
1.8-将上述结合在一起:最简版神经网络学习实例

第二部分:卷积神经网络

2.1-卷积神经网络:架构,卷积&采样层
2.2-可理解的和可视化的卷积神经网络???
2.3-迁移学习和微调神经网络
2.4-回旋网技巧和诀窍:挤出最后几个百分点???

第X部分:准备

x.1-Python Numpy包使用指南
x.2-IPython指南
x.3-结束

—————————————————————————————————————————
这是一门介绍性课程,旨在引导人们进入计算机视觉的图像分类问题以及数据驱动方法中来。课程的课表如下:

  • 介绍图像分类,数据驱动方法,线程???
  • 最近邻分类-------------k-近邻
  • 校验集,交叉验证,调超参
  • 最近邻的利弊
  • 总结
  • 总结:knn实战
  • 阅读参考

图像分类

动机:在本节中,我们将介绍图像分类问题,即从一些固定的类别中为输入图像分配一个标签。这是计算机视觉领域的核心问题之一,尽管它很单一,但有着大量的实际应用。此外,正如我们在后面课程会看到的,一些表面上看来独特的计算机视觉问题(比如目标识别,目标分割)都可以简化为图像分类问题。

例子:例如,下图是一个图像分类模型,它将取一张图像并将其可能性分给四个标签,{猫,狗,帽子,杯子}。请记住,如图所示,对于计算机来说,图像是由一个大的三位数组组成的。在这个例子中,这幅猫的图像有248像素宽,400像素高,而且含有三个通道的颜色:红色,绿色和蓝色(或者简短的说成RGB)。因此,这幅图由2484003,总共297,600个数字组成。每个数字都是一个在0(黑色)-255(白)之间的整数。我们的任务就是将这百万的四分之一的数字归为一个标签,例如“猫”。
在这里插入图片描述
图像分类的工作就是为给定图像预测单一的标签(或者标签的分布,如上图所示来表明我们的置信度)。图像是一个取值为0-255的三维整数数组,大小为宽x高x3。这个3代表红绿蓝三个颜色通道。
挑战:尽管识别视觉概念(例如猫)的任务对于人类来说是微不足道的,但是从计算机视觉算法的角度来看确是一个值得考虑的挑战。当我们在下面提出(一个不详尽的)挑战列表时,请记住图像的原始表示是一个三维亮度值数组:

  • 视角变化:一个物体可以以很多不同的方向来面向相机
  • 大小变化:视类经常在大小上出现变化(在现实世界中的大小,不仅仅是图像中的)
  • 变形:很多我们感兴趣的对象并不是严格死板的身形,它们可以极大程度的扭曲。
  • 包藏:感兴趣的对象可以被包藏。有时仅有一小部分的物体(甚至小到只有几个像素)可以被看到。
  • 光照条件:光照对图像在像素级别的影响是非常严重的。
  • 背景杂波:感兴趣的对象可能融入它们的环境,使它们难以识别。
  • 类内部变异:感兴趣的类可能非常广泛,例如椅子。这类对象有很多不同的类型,每一种都有自己的外观。
    一个好的图像分类模型必须对这些变化的综合影响保持稳定,同时要对类内的变化保持敏感。
    在这里插入图片描述
    数据驱动方法:我们该如何写一个可以将图像分为不同类别的算法呢?与编写一个排序算法不同,我们不明确知道如何写一个用于识别图像中猫的算法。因此,与其在代码中将感兴趣对象的特征列举出来,我们使用的方法不会像你带着一个小孩一样:我们会提供给计算机每个类别的很多例子,以这些例子为基础,了解每个类的外观,进而开发算法。这种方法被称为数据驱动方法,因为它依赖于一开始积累的标签训练数据集,下面就是这样一个数据集的例子:
    在这里插入图片描述
    在这里插入图片描述
    (四种视觉类别的训练集,在实践中,我们可能有上千个类别,每个类别可能有成千上万幅图像)
    图像分类流程:我们可以看到图像分类就是将一幅图像用像素数组表示并为其分配一个标签。我们完整的流程可以总结???如下:
  • 输入:我们的输入包含N个图像,每个图像都被标记为K个类别之一。
  • 学习:我们的任务是用训练集来学习每个类别的样子???。我们称这个步骤为训练分类器,或者学习一个模型。
  • 评估:最后,我们通过让分类器预测一组从未见过的新图像的标签来评估分类器的性能。然后我们会比较这些图像的真实标签与分类器预测的标签,显然,我们希望大部分预测结果和真实结果(基础事实)是匹配的。

最近邻分类器

作为我们的第一个方法,我们将介绍???一个名叫最近邻分类器的算法。这个分类器和卷积神经网络无关且在实践中很少用到,但它可以让我们了解图像分类的基本方法。
示例图像分类数据集:CIFAR-10。一个流行的玩具图像分类数据集是CIFAR-10数据集。这个数据集包含六万张32像素宽和高的小图像。每幅图像都被标记为10个类别之一(例如“飞机”,“汽车”。“鸟”等)。这六万张图像有五万张被分作训练集和一万张被分为测试集。在下面的图片中,你可以看到来自10个类的各10张随机示例图片:
在这里插入图片描述
假设我们现在给 CIFAR-10 训练集五万张图像(每个类别有五千张),并希望给剩余的一万张进行归类。最近邻分类器将会把测试图像与训练集的每一张图像进行对比,并将最近的训练集图像的标签作为预测结果。在上面图片的右侧你可以看到10幅示例图像的测试结果。注意,只有3幅图像检索到了同一类型的图像,其他7幅却并非如此。例如,在第8行中,训练集中最接近马头图像的是一幅红色汽车,这大概是因为其深黑色的背景。因此,这幅马的图像就被误分为汽车类了。
你可能注意到我们没有详细说明如何比较两幅图像,在本例中仅仅是两个32323大小的方块儿。最简单的方法是逐像素的比较并将所以的差异相加。换句话说,给定两个图像并将它们看作向量I1 , I2,比较两者的合理选择就是L1距离???:
在这里插入图片描述
这里的和考虑了所以的像素,下面是可视化的过程:
在这里插入图片描述
一个使用像素间差异来比较两幅图像的L1距离的例子(例子中为单通道)。两幅图像的元素值相减,然后将所以的差异相加的一数值。如果两幅图像完全一样,那得到的结果就是零,但是如果两幅图像差异特别大,那结果也会非常大。
在这里插入图片描述
让我们看看如何用代码实现分类器。首先,我们下载CIFAR-10数据集并分为4部分:训练数据集/标签,和测试数据集/标签。在下面代码中,Xtr(大小为50,0003232*3)包含了训练集中的所有图像,还有一个相应的一维数组Ytr(长度为50,000)包含了训练集的标签(标签为0-9):

Xtr, Ytr, Xte, Yte = load_CIFAR10('data/cifar10/') # a magic function we p
# flatten out all images to be one-dimensional
Xtr_rows = Xtr.reshape(Xtr.shape[0], 32 * 32 * 3) # Xtr_rows becomes 50000
Xte_rows = Xte.reshape(Xte.shape[0], 32 * 32 * 3) # Xte_rows becomes 10000

现在我们将所以的图像拉伸成行,下面让我们看看如何训练和评估一个分类器吧。

nn = NearestNeighbor() # create a Nearest Neighbor classifier class
nn.train(Xtr_rows, Ytr) # train the classifier on the training images and
Yte_predict = nn.predict(Xte_rows) # predict labels on the test images
# and now print the classification accuracy, which is the average number
# of examples that are correctly predicted (i.e. label matches)
print 'accuracy: %f' % ( np.mean(Yte_predict == Yte) )

注意,以预测部分的正确率为评估标准是非常普遍的。???这里,我们构建的所有分类器有一个共同的API:他们都有一个获取训练数据和标签的函数train(X,y),在分类器内部???,应该建立某种根据数据来预测标签的模型。然后后面是**predict(X)**函数,功能是获取新数据并预测其标签。当然,我们忽略了最本质的东西——分类器本身。下面是一个基于L1距离的最近邻分类器的简单实现,它满足上述模板:

import numpy as np
class NearestNeighbor:
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
# the nearest neighbor classifier simply remembers all the training da
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 f
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 dista
Ypred[i] = self.ytr[min_index] # predict the label of the nearest ex
return Ypred

如果你运行这段代码,你会发现这个分类器对于CIFAR-10的正确率仅达到38.6%。这比瞎猜(当有10个类别时猜中的概率只有10%)要好些,但远不及人类性能???(估计在94%左右)或者先进的卷积神经网络来实现匹配人脸的95%的精确度(见CIFAR-10上最近的Kaggle竞赛的排行榜)。
距离度量的选择:向量之间的距离计算有很多方式。另一常见的可选的为L2距离,它的几何解释是计算两个向量之间的欧式距离,距离计算为:
在这里插入图片描述
换句话说,我们将想以前那样计算像素级的差异,但是这次我们将所有元素开方,相加,并计算平方根,在numpy中,只需要替换上面的一行代码。计算距离的这行代码:

distances = np.sqrt(np.sum(np.square(self.Xtr - X[i,:]), axis = 1))

注意我在上面包含了np包。但是实际最近邻算法应用中我们可以忽略开平方根运算因为平方根是单调函数。也就是说它缩放了距离的绝对大小但保留了距离的顺序,所以有没有开平方根的最近邻算法是一样的。如果你用这个距离对 CIFAR-10数据集来运行这个最近邻分类器,你将获得35.4%的准确率(略低于我们的L1距离结果)。
L1 vs L2:比较两种距离的差异是非常有趣的。

发布了26 篇原创文章 · 获赞 40 · 访问量 3638

猜你喜欢

转载自blog.csdn.net/qq_43667130/article/details/103261026