K邻近算法

xiaoxiao2025-10-25  9

(一)算法基本思想

K N N KNN KNN是一种常用的监督学习方法。给定测试样本,基于某种距离度量找出训练集中与其最靠近的 k k k个训练样本,然后基于这 k k k个邻居的信息来进行预测。使用投票法,选择 k k k个样本中出现最多的类别标记作为预测结果,这 k k k个实例的多数属于某类,就把该输入实例分为哪类。也可以基于距离远近进行加权平均,距离越近样本权重越大。 k k k值的选择、距离的度量、以及分类决策规则是 k k k邻近算法三个基本要素。

(二)算法实现

输入:训练数据集 T = [ ( x 1 , y 1 ) , ( x 2 , y 2 ) , . . . , ( x n , y n ) ] T={[(x_1,y_1),(x_2,y_2),...,(x_n,y_n)]} T=[(x1,y1),(x2,y2),...,(xn,yn)], x i x_i xi为特征向量, y i y_i yi为实例类别。 输出:实例 x x x所属的类别 y y y

(1)

根据给定的距离度量,在训练集 T T T中找出与 x x x最邻近的 k k k个点;

(2)

k k k个点中进行分类表决,少数服从多数原则,决定 x x x的类别 y y y y = a r g m a x ∑ x I ( y i = c j ) y=argmax\sum_xI(y_i=c_j) y=argmaxxI(yi=cj),选择相应数目最多的类别。当 k = 1 k=1 k=1时,称为最邻近算法。

k k k邻近模型

(1)模型

当训练集、距离度量、 k k k值以及分类决策规则确定后,对于任何一个新的输入实例,它所属的类唯一的确定。

(2)距离度量

使用的距离一般是欧式距离。 L p = ( ∑ l = 1 n ∣ x i ( l ) − x j ( l ) ∣ p ) 1 p L_p={(\sum_{l=1}^n|x_i^{(l)}-x_j^{(l)}|^p)^{\frac{1}{p}}} Lp=(l=1nxilxjlp)p1;当 p = 2 p=2 p=2时,为欧式距离。当 p = 1 p=1 p=1时,为曼哈顿距离。

(3) k k k值的选择

k k k值较小,学习的近似误差会减小,估计误差会增大,意味着整体模型变得更复杂,容易发生过拟合;若 k k k值较大,可以减少学习的估计误差,但近似误差会变大,但意味着整体的模型变得简单。在实际中, k k k值一般选择一个比较小的数值。

(4) 分类决策规则

分类误差率为: 1 k ∑ x I ( y i &lt; &gt; c j ) = 1 − 1 k ∑ x I ( y i = c j ) \frac{1}{k}\sum_x{I(y_i&lt;&gt;c_j)=1-\frac{1}{k}}\sum_x{I(y_i=c_j)} k1xI(yi<>cj)=1k1xI(yi=cj) 要使分类误差率最小,即经验风险最小,就要使 ∑ x I ( y i = c j ) \sum_xI(y_i=c_j) xI(yi=cj)最大,所以多数表决规则等价于经验风险最小化。

k k k邻近代码实现

# -*- coding: UTF-8 -*- import numpy as np import operator from os import listdir global nums def classify0(inX, dataSet, labels, k): #numpy函数shape[0]返回dataSet的行数 dataSetSize = dataSet.shape[0] #在列向量方向上重复inX共1次(横向),行向量方向上重复inX共dataSetSize次(纵向) diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet #二维特征相减后平方 sqDiffMat = diffMat**2 #sum()所有元素相加,sum(0)列相加,sum(1)行相加 sqDistances = sqDiffMat.sum(axis=1) #开方,计算出距离 distances = sqDistances**0.5 #返回distances中元素从小到大排序后的索引值 sortedDistIndices = distances.argsort() #定一个记录类别次数的字典 classCount = {} for i in range(k): #取出前k个元素的类别 voteIlabel = labels[sortedDistIndices[i]] #dict.get(key,default=None),字典的get()方法,返回指定键的值,如果值不在字典中返回默认值。 #计算类别次数 classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 #python3中用items()替换python2中的iteritems() #key=operator.itemgetter(1)根据字典的值进行排序 #key=operator.itemgetter(0)根据字典的键进行排序 #reverse降序排序字典 sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True) #返回次数最多的类别,即所要分类的类别 return sortedClassCount[0][0] def file2vector(filename): fr = open(filename) arrayOLines=fr.readlines() numberOfLines=len(arrayOLines) nums=numberOfLines returnMat=np.zeros((numberOfLines,16)) classLabelVector=[] index=0 for line in arrayOLines: line=line.strip() listFromLine=line.split(',') returnMat[index,:]=listFromLine[1:17] classLabelVector.append(listFromLine[0]) index+=1 return returnMat,classLabelVector def alphabetClassTest(): trainingMat,alLabels=file2vector("trainingData.txt") errorCount = 0.0 with open("testingData.txt",'r',encoding='utf-8') as f: arrays=f.readline() while arrays: testMat=np.zeros((1,16)) teLabels=[] inde=0 l=arrays.strip() llist=l.split(',') for i in range(1,17): testMat[0,inde]=llist[i] inde+=1 teLabels.append(llist[0]) classifierResult = classify0(testMat, trainingMat, alLabels, 5) print("分类返回结果为%s\t真实结果为%s" % (classifierResult, teLabels[0])) if(classifierResult != teLabels[0]): errorCount += 1.0 arrays=f.readline() print("总共4000,错了%d个数据\n正确率为%f%%" % (errorCount, (1-(errorCount)/4000)*100)) if __name__ == '__main__': alphabetClassTest()
转载请注明原文地址: https://www.6miu.com/read-5038520.html

最新回复(0)