斯坦福大学的CS231n,全称卷积神经网络在视觉识别中的应用(Convolutional Neural Networks for Visual Recognition),最近做毕设么,要用deep learning做目标识别,导师给我推荐了这门课程。想着独学学不如众学学,接下来的一段时间应该会持续分享关于CS231n的笔记。
CS231n_2020(1)—— 图像分类
Image Classification
https://cs231n.github.io/classification/
-
目标
这一节主要是介绍图像分类的问题,即把一组输入的图片分配一个标签。这是计算机视觉的核心,有着广泛的运用。 -
举例
-
图像分类的基本步骤
图像分类的任务就是获取表示单个图像的像素数组,并为其分配一个标签。基本步骤如下:
-
Input:输入即训练集,由n个带有唯一标签的不同图像组成,总共有k类。
-
Learning:学习的是使用训练集来学习每个分类的特征。我们将此步骤称为训练分类器或学习模型。
-
Evaluation:用训练好的模型为一组它从未见过的新图像(验证集)预测标签来评价分类器的质量。当然,我们希望预测与真实答案(ground truth)相符。
Nearest Neighbor Classifier
这里,使用了CIFAR-10(https://www.cs.toronto.edu/~kriz/cifar.html)dataset,这个数据集由60000个32像素高和宽的小图像组成。每个图像都被标记为10个类之一(例如“飞机、汽车、鸟等”)。这60000个图像被分割成50000个图像的训练集和10000个图像的测试集。在下图中,是10个类中每个类的10个随机示例图像:
这里引入L1 distance的概念,即两个像素之差的加和,如下所示:
L1 distance
d
1
(
I
1
,
I
2
)
=
∑
p
∣
I
1
p
−
I
2
p
∣
\begin{aligned} d_{1}(I_{1}, I_{2}) = \sum_{p}|I_{1}^{p} - I_{2}^{p}| \end{aligned}
d1(I1,I2)=p∑∣I1p−I2p∣
通过L1 distance判断该图像是属于哪个分类的。上代码:
Xtr, Ytr, Xte, Yte = load_CIFAR10('data/cifar10/') # a magic function we provide
# flatten out all images to be one-dimensional
Xtr_rows = Xtr.reshape(Xtr.shape[0], 32 * 32 * 3) # Xtr_rows becomes 50000 x 3072
Xte_rows = Xte.reshape(Xte.shape[0], 32 * 32 * 3) # Xte_rows becomes 10000 x 3072
nn = NearestNeighbor() # create a Nearest Neighbor classifier class
nn.train(Xtr_rows, Ytr) # train the classifier on the training images and labels
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) )
import numpy as np
class NearestNeighbor(object):
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 N """
# the nearest neighbor classifier simply remembers all the training data
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 for """
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 range(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 distance
Ypred[i] = self.ytr[min_index] # predict the label of the nearest example
return Ypred
除了L1 distance,还有L2 distance也常用来计算图像分类。
L2 distance
d
2
(
I
1
,
I
2
)
=
∑
p
(
I
1
p
−
I
2
p
)
2
\begin{aligned} d_{2}(I_{1}, I_{2}) = \sqrt{\sum_{p}(I_{1}^{p} - I_{2}^{p})^2} \end{aligned}
d2(I1,I2)=p∑(I1p−I2p)2
L1和L2是vector p-norm里最常用的。
k - Nearest Neighbor Classifier
这个比较简单,直接上图了:
Validation sets for Hyperparameter tuning
k近邻分类器需要k的设置,那么怎么设置k的值是最优的?除了k值,还有距离范数需要选择:L1范数,L2范数,或者还有其他的距离计算方法,比如点积。这些基础模型的选择被称为hyperparameters。
关于这些超参数的选择,可以通过变换不同的值看哪种方法最优,但是不能在测试集里变换这些方法(we cannot use the test set for the purpose of tweaking hyperparameters.)。测试集是机器学习里非常宝贵的资源,只有最后一次才可以用它(Evaluate on the test set only a single time, at the very end.)。
Split your training set into training set and a validation set. Use validation set to tune all hyperparameters. At the end run a single time on the test set and report performance.
Cross-validation
有时,当训练集比较小的情况下,我们可以使用交叉验证(cross-validation)。
Summary
- 本节接受了图像分类的问题,即得到一组图像,这些图像都用一个类别标记。然后为一组新的测试图像预测这些类别,并测量预测的准确性。
- 引入了一个简单的分类器,称为最近邻分类器。我们发现有多个超参数(如k值,或用于比较示例的距离类型)与该分类器相关,并且没有明显的方法来选择它们。
- 如何选择这些超参数的正确方法是将训练数据分成两部分:训练集和验证集。通过尝试不同的超参数值,使验证集的性能达到最佳的值。
- 如果缺乏训练数据,可以使用交叉验证的方法,它能减少噪音,以估计哪些超参数最有效。
- 当找到了最佳的超参数,将最佳超参数带入原模型,对测试集进行评估。