该博客主要用于个人学习记录,部分内容参考自 李飞飞笔记、cs231n计算机视觉课程笔记、图像识别算法(一)、cs231n笔记2—线性分类 图像识别的任务就是给输入的一张图像一个标签。 计算机将图像看作是一个介于[0,255]之间的一个巨大的数字网格(An image is just a big grid of numbers between [0,255]. ) ,图像可能是800*600的像素,每个像素由三个值表示(红、绿、蓝) 人类可以轻松地从图像中识别出目标,而计算机看到的图像只是一组0到255之间的整数。 视角变化(viewpoint variation)—— 一张物体在不同角度的拍摄下也会有不一样的效果。 光照条件(illumination conditions)—— 照明的影响在像素级别上是剧烈的。 形变(deformation) —— 猫可以有很多不同的姿势和位置,我们的算法应该对这些不同类型的转换具有鲁棒性。 遮挡(occlusion)—— 有时只能看到对象的一小部分(少至几个像素)。 背景杂乱(background clutter) —— 感兴趣的对象可能会融入其环境,使其难以识别。如猫在外观上看起来与背景十分相似。 类内变化(intraclass variation)—— 对象有许多不同的类型,每种类型都有自己的外观。如猫有不同的形状和大小、颜色和年龄。 与其编写一个算法指定每个感兴趣的类别的样子,不如设计一个学习算法。向计算机提供每一个类别的许多例子,然后算法通过对这些例子进行学习得到每一个类别的视觉外观,这种方法被认为是data driven approach,因为它依赖于具有标记的训练数据集。 在最近邻分类器中,用于比较图像的距离度量是 L1(Manhattan) distance : \(d_1(I_1,I_2)=\sum_p\left|I_1^p-I_2^p\right|\) 其在二维矩阵中的用法如下: 训练阶段train:记住所有数据和标签 —— O(1) We want fast at prediction; slow for training is ok L1(Manhattan) distance : \(d_1(I_1,I_2)=\sum_p\left|I_1^p-I_2^p\right|\) L2(Euclidean) distance : \(d_2(I_1,I_2)=\sqrt{\sum_p(I^p_1-I^p_2)^2}\) 参数不一定是从训练数据中学习到的,相反,这些是你提前做出的关于算法的选择,没有办法直接从数据中学习。有关算法的选择是我们设定的而不是学习的。比如K、Distance Metric。 设置超参数: ❌ 选择在训练集上表现最好的超参数 ❌ 将数据分为训练集和测试集,在训练集中设置不同的超参数训练算法,将经过训练的分类器应用于测试集中,选择在测试集上效果最好的超参数 ✅ 将数据分为训练集train、验证集validation、测试集test,在训练集中用许多不同的超参数选择来训练我们的算法,在验证集上进行评估,选择在验证集上表现最佳的超参数,一切操作完成后将会获得在验证集上表现最佳的分类器,然后仅在测试集上运行一次,结果表示算法在未见的新数据上表现如何。注意验证集和测试集一定要有明显的区分,我们不能将测试集用于调整超参数。每当您设计机器学习算法时,您都应该将测试集视为一种非常宝贵的资源,最好在最后一次之前永远不要接触它。最后只对测试集进行一次评估,但是我们可以通过验证集去选择最合适的超参数。 ✅ 交叉验证Cross Validation:拿出一部分数据作为测试集在最后使用,剩余部分将训练集分为许多不同折,选择一折作为验证集。常用3折、5折、10折交叉验证。多用于小型数据集,但计算成本高,在深度学习中不常用。 人们倾向于将50%-90%的训练数据用于训练,其余的用于验证。 如果超参数的数量很大,可能更倾向于使用更大的验证分割。 如果验证集中的例子数量很少(可能只有几百个左右),使用交叉验证会更安全 在实际中基本不用。 测试时间非常慢:我们通常关心的是测试时间的效率,而不是训练时间的效率。 像素上的距离度量不提供有效的信息。例如下图中我们视觉上可以感觉到图像之间的差异,但4张图的L2 Distance都相同,说明了L2 Distance在捕捉图像之间的感知距离方面确实做得不好。 维度灾难 总结我们训练数据的知识,并将所有这些知识融入到参数W中,在测试阶段不再需要实际的训练数据,只需要这些参数W。这使得我们的模型更有效,并且可以在像手机这样的小型设备上运行 一个常用的技巧是将W,b两组参数组合成一个单独的矩阵,同时x向量增加一个维度,这个维度的数值为常数1,这就是默认的偏差维度。由此,新的公式将简化为: f(x,W)=Wx 一张图像对应不同分类的得分,是通过使用内积(也叫点积)来比较图像和模板,然后找到和哪个模板最相似。从这个角度来看,线性分类器就是在利用学习到的模板,针对图像做模板匹配。 线性分类器计算图像中3个颜色通道中所有像素的值与权重的矩阵乘,从而得到分类分值。根据我们对权重设置的值,对于图像中的某些位置的某些颜色,函数表现出喜好或者厌恶(根据每个权重的符号而定)。举个例子,可以想象“船”分类就是被大量的蓝色所包围(对应的就是水)。那么“船”分类器在蓝色通道上的权重就有很多的正权重(它们的出现提高了“船”分类的分值),而在绿色和红色通道上的权重为负的就比较多(它们的出现降低了“船”分类的分值) 上图是一个将图像映射到分类分值的例子。为了便于可视化,假设图像只有4个像素(都是黑白像素,这里不考虑RGB通道),有3个分类(红色代表猫,绿色代表狗,蓝色代表船,注意,这里的红、绿和蓝3种颜色仅代表分类,和RGB通道没有关系)。首先将2×2的图像像素拉伸为一个具有4个元素的列向量,与W进行矩阵乘,然后得到各个分类的分值。需要注意的是,这个W一点也不好:猫分类的分值非常低。从上图来看,算法倒是觉得这个图像是一只狗。 将原始像素值从[0,255]更改为[-1,1] 每个类别只能学习一个模板 多模态数据、奇偶问题。一、图像识别Image Classification
1、在CV中的一个核心问题
2、问题:语义鸿沟Semantic Gap
3、挑战
4、数据驱动的方法Data driven approach
def train(images, labels):
#输入图片和标签,输出模型
return model
def predict(model, test_images):
#输入一个模型,对图片种类进行预测
return test_labels
二、最近邻分类器(Nearest Neighbor Classifier)
将两个图像元素相减取绝对值,然后将所有差异相加为一个数字。 如果两个图像相同,则结果为零。 但如果图像非常不同,结果会很大。
预测阶段predict:拍摄新图像,尝试在训练数据中找到与新图像最相似的图像,预测最相似的图像的标签。 —— O(N)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. Yis 1-d of size N ’‘’
# the nearest neighbor classifier simply remebers all the tarining data
self.Xtr = X
self.ytr = y
def predict(self X):
’‘’ X is N x D where each row is an example 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 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) # using broadcast
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
三、k-最近邻分类器(k - Nearest Neighbor Classifier)
1、Take majority vote from K closest points
2、Chosing the Distance Metric:
3、超参数hyperparameters
# assume we have Xtr_rows, Ytr, Xte_rows, Yte as before
# recall Xtr_rows is 50,000 x 3072 matrix
Xval_rows = Xtr_rows[:1000, :] # take first 1000 for validation
Yval = Ytr[:1000]
Xtr_rows = Xtr_rows[1000:, :] # keep last 49,000 for train
Ytr = Ytr[1000:]
# find hyperparameters that work best on the validation set
validation_accuracies = []
for k in [1, 3, 5, 10, 20, 50, 100]:
# use a particular value of k and evaluation on validation data
nn = NearestNeighbor()
nn.train(Xtr_rows, Ytr)
# here we assume a modified NearestNeighbor class that can take a k as input
Yval_predict = nn.predict(Xval_rows, k = k)
acc = np.mean(Yval_predict == Yval)
print 'accuracy: %f' % (acc,)
# keep track of what works on the validation set
validation_accuracies.append((k, acc))
4、KNN存在的问题
四、线性分类Linear Classification
1、参数化方法Parametric Approach
2、函数 f(x,W) = Wx + b
3、W和b的合并技巧
4、线性分类≈模板匹配方法
5、例子
6、图像数据预处理
7、线性分类器的问题
8、线性分类器的困境
蓝色类别是图像中像素的数量,这个数字大于0,并且是奇数,任何像素个数大于0的图像,都归为红色类别,如果你真的去画这些不同的决策出现这些不同的决策取悦,你能看到我们奇数像素点的蓝色类别,在平面上有两个象限,甚至是两个相反的象限,所以我们没有办法能够绘制一条单独的直线,来划分蓝色和红色。