Nearest Neighbor Algorithm

邻近算法(Nearest Neighbor)的思想实际上十分简单,就是将测试图片和储存起来的训练集一一进行相似度计算,计算出最相近的图片,这张图片的标签便是赋给测试图片的分类标签。

那么如何比较两组数据之间的相似长度呢?

  1. L1距离(曼哈顿距离 Manhattan distance)
import numpy as np
import _pickle as pickle


def load_CIFAR10(filename):
    training_file = filename + "/data_batch_1"
    testing_file = filename + "/test_batch"
    with open(training_file,'rb') as f:
        data = pickle.load(f,encoding='iso-8859-1')
        #data是个字典,key为data和labels
        Xtr = data['data']
        #Xtr是图片的像素组成,如10000张彩色32*32的图片,Xtr就是10000*3072,3072=32*32*3
        Ytr = data['labels']
        #Ytr是labels的数量,和图片数量相等,为10000
    with open(testing_file,'rb') as f:
        data = pickle.load(f,encoding='iso-8859-1')
        Xte = data['data']
        #Xte = Xte[:100]
        #计算快一点的话,就以前100个为例
        Yte = data['labels']
        #Yte = Yte[:100]
    return Xtr,Ytr,Xte,Yte

class NearestNeighbor(object):
    def __init__(self):
        pass
    def train(self,X,Y):
        self.Xtr = X
        self.Ytr = Y
    def predict_L1(self,X):
        num_test = X.shape[0]
        #num_test是图片的数量,为10000,shape[0]返回的是行数
        print("num_test:",num_test)
        Ypred = np.zeros(num_test)
        #Ypred是一个10000大小,储存预测出来的label的列表
        for i in range(num_test):
            distance = np.sum(np.abs(self.Xtr- X[i,:]),axis=1)
            #计算距离,每一行进行减法
            print("distance:",distance)
            min_index = np.argmin(distance)
            #找到距离最小值的索引,如最小值为50,索引为第5个图
            print("min_index",min_index)
            Ypred[i] = self.Ytr[min_index]
            #根据索引找到训练集该索引的label,赋给测试集的该图
            print("Ypred:",Ypred[i])
            print(Ypred[i])
        return  Ypred
       
Xtr, Ytr, Xte, Yte = load_CIFAR10("./cifar-10-batches-py")
#Xtr和Ytr是训练集,Xte和Yte是预测集
nn = NearestNeighbor()
nn.train(Xtr,Ytr)
Yte_predict = nn.predict_L1(Xte)
print("Xtr: ", Xtr.shape)
print(Yte_predict)
print(count)
print('accuracy: %f' % (np.mean(Yte_predict == Yte)))
#计算正确的所占百分比,mean计算百分比
  1. L2距离(欧式距离)

KNN的原理就是当预测一个新的值x的时候,根据它距离最近的K个点是什么类别来判断x属于哪个类别。

Nearest Neighbor Residual nearest neighbor residual 算法_python

Nearest Neighbor Residual nearest neighbor residual 算法_最小值_02


Nearest Neighbor Residual nearest neighbor residual 算法_最小值_03


那么该如何确定K取多少值好呢?答案是通过交叉验证(将样本数据按照一定比例,拆分出训练用的数据和验证用的数据,比如6:4拆分出部分训练数据和验证数据),从选取一个较小的K值开始,不断增加K的值,然后计算验证集合的方差,最终找到一个比较合适的K值。举例:以电影分类作为例子,电影题材可分为爱情片,动作片等,那么爱情片有哪些特征?动作片有哪些特征呢?也就是说给定一部电影,怎么进行分类?这里假定将电影分为爱情片和动作片两类,如果一部电影中接吻镜头很多,打斗镜头较少,显然是属于爱情片,反之为动作片。有人曾根据电影中打斗动作和接吻动作数量进行评估,数据如下:

Nearest Neighbor Residual nearest neighbor residual 算法_最小值_04


 给定一部电影数据(18,90)打斗镜头18个,接吻镜头90个,如何知道它是什么类型的呢?KNN是这样做的,首先计算未知电影与样本集中其他电影的距离(这里使用曼哈顿距离),数据如下:

Nearest Neighbor Residual nearest neighbor residual 算法_最小值_05


现在我们按照距离的递增顺序排序,可以找到k个距离最近的电影,加入k=3,那么来看排序的前3个电影的类别,爱情片,爱情片,动作片,下面来进行投票,这部未知的电影爱情片2票,动作片1票,那么我们就认为这部电影属于爱情片。