KNN(K-Nearest Neighbors)也就是常说的k最紧邻算法,顾名思义也就是找出某个点最靠近的k个点,由于其对于小数据集的处理能力较强,在神经网络火起来之前被广泛地使用。
接下来讲主要以图像分类领域为基础进行knn的介绍。但是由于本博客目的是方便后续留做复习使用,因此不打算从最基础的部分讲解起来,不过关于其最基础的内容,文末会有相关链接。
图像分类,顾名思义,就是将一幅图像赋予一个标签,同时标签的范围是已知的。
KNN的距离矩阵
常用的KNN的距离矩阵有两种,一种是L1(Manhattan Distance), , 也就是将待分类图像所有像素点与特征图像像素点的差值取绝对值之后进行求和; 另外一种是L2(Euclidean Distance),
, 就是讲待分类图像所有像素点与特征图像像素点的差值平方和再开方。
在实践中,很难说哪一种距离衡量尺度比另外一种好,因此需要结合具体问题通过测试来进行选择。
数据集训练技巧
数据集的训练技巧总体而言可以划分为四大类,分别为:
- 纯训练集
- 训练集+测试集
- 训练集+验证集+测试集
- 交叉验证集
纯训练集
纯训练集,顾名思义,就是将所有的数据拿来进行训练,然后选择在训练集上效果最好的算法。在knn中,也就是k的选取问题。但是这种方法存在显然的致命性的问题,也就是无论怎样,k=1时的算法在训练集上效果是最好的,但是实际上这是一种过拟合的算法,不具有很好的泛化能力。
训练集+测试集
这种方式存在的问题是测试集由于已经进入实战阶段,针对于一个未知的环境,没有一个很好的ground truth 作为指导,因此并不知道算法在新的数据集上运行得怎样,不具有参考性。
训练集+验证集+测试集
这是一种在机器学习相关问题中广泛使用的方法,将训练好的模型在验证集上进行算法效果的衡量,选出最佳的算法,然后在测试集上进行测试。
交叉验证集
首先将所有的数据划分为两部分,一部分为测试数据集,然后将另外一部分等量划分为m个子部分,随机讲子部分中的任意一部分作为验证集,其他子部分作为训练集。
一般而言,交叉验证集在小的数据集上常常使用,但是由于深度学习的参数、数据集、模型等都较为复杂,因此往往不会在深度学习中使用。
如图所示:
超参数(Hyper-parameters)
超参数的定义是 choices about the algorithm that we set rather than learn. 也就是说超参数就是那些我们人工选择而不是通过学习得到的参数。针对于knn问题,如上述所说的,k值的选取,以及距离矩阵的选取都属于超参数。
关于超参数的选择可能带来的影响,可以参阅http://vision.stanford.edu/teaching/cs231n-demos/knn/ 。
KNN代码实现
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 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 distance
Ypred[i] = self.ytr[min_index] # predict the label of the nearest example
return Ypred
时间复杂度分析
train: O(1)
test: O(n)
The End.