Nearest Neighbor Algorithm
邻近算法(Nearest Neighbor)的思想实际上十分简单,就是将测试图片和储存起来的训练集一一进行相似度计算,计算出最相近的图片,这张图片的标签便是赋给测试图片的分类标签。
那么如何比较两组数据之间的相似长度呢?
- 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计算百分比
- L2距离(欧式距离)
KNN的原理就是当预测一个新的值x的时候,根据它距离最近的K个点是什么类别来判断x属于哪个类别。
Γ
d
(
I
1
,
I
2
)
=
∑
P
(
I
1
P
−
I
2
P
)
2
,
.
\Gamma d(I_1,I_2) =\sqrt{\sum_P(I_1^P-I_2^P)^{2}},.
Γd(I1,I2)=P∑(I1P−I2P)2,.
那么该如何确定K取多少值好呢?答案是通过交叉验证(将样本数据按照一定比例,拆分出训练用的数据和验证用的数据,比如6:4拆分出部分训练数据和验证数据),从选取一个较小的K值开始,不断增加K的值,然后计算验证集合的方差,最终找到一个比较合适的K值。
举例:以电影分类作为例子,电影题材可分为爱情片,动作片等,那么爱情片有哪些特征?动作片有哪些特征呢?也就是说给定一部电影,怎么进行分类?这里假定将电影分为爱情片和动作片两类,如果一部电影中接吻镜头很多,打斗镜头较少,显然是属于爱情片,反之为动作片。有人曾根据电影中打斗动作和接吻动作数量进行评估,数据如下:
给定一部电影数据(18,90)打斗镜头18个,接吻镜头90个,如何知道它是什么类型的呢?KNN是这样做的,首先计算未知电影与样本集中其他电影的距离(这里使用曼哈顿距离),数据如下:
现在我们按照距离的递增顺序排序,可以找到k个距离最近的电影,加入k=3,那么来看排序的前3个电影的类别,爱情片,爱情片,动作片,下面来进行投票,这部未知的电影爱情片2票,动作片1票,那么我们就认为这部电影属于爱情片。