K近邻算法用于对单个数据进行类别的预测。

算法原理:

将代预测数据、训练数据集置于特征空间,计算代预测数据与训练数据集的各个点的欧式距离,根据设定的K值将计算得到的欧式距离进行排序,取前K个数据,根据这K个数据中的已知数据类型给出代预测数据的类别。


K近邻算法

def classify0(inX,dataSet,labels,k):_#测试数据,训练数据,类别标签,k值<br /> # 获取训练数据集行数<br /> _dataSetSize = dataSet.shape[0]<br /> _# 计算测试数据到各个训练数据的欧氏距离<br /> _diffMat = np.tile(inX,(dataSetSize,1)) - dataSet _#测试点与每个训练点相减的x,y值<br /> _sqdiffMat = diffMat**2 _#x,y差值平方<br /> _sqDistance = sqdiffMat.sum(axis=1) _#差值平方的和(欧式距离的平方)<br /> _distance = sqDistance**0.5 _#测试点与各点的欧氏距离<br /> #对欧氏距离进行排序,返回排序后的索引<br /> _sortedDistIndicies = distance.argsort()<br /> classCount = {}<br /> _# 获取前K个与测试点距离最近的测试点的类别<br /> _for i in range(k):<br /> voteIlabel = labels[sortedDistIndicies[i]] _#第i个测试点的类别<br /> _classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 _#统计类别的次数<br /> # 对字典按值进行排序,key的取值即为字典的值,若operator.itemgetter()中为0,则key的取值 为字典的键<br /> _sortedClassCount = sorted(classCount.items(),<br /> key=operator.itemgetter(1),reverse=True)<br /> _# 返回字典中出现次数最多的值的键,即测试点的预测类别<br /> _return sortedClassCount[0][0]

代码中的函数介绍:

np.shape[axis=]:获取矩阵的行数或列数

axis = 0:返回矩阵行数;axis = 1:返回矩阵列数

np.tile(矩阵 , (沿y轴复制的次数-int值 , 沿X轴复制的次数-int值))

np.argsort(矩阵 , axis=):返回对矩阵排序后的各个元素的索引

axis = 0:对矩阵不同行但同列的元素进行排序
axis = 1:对矩阵每一行的元素进行排序

sorted(dict.items() , key=operator.itemgetter(索引1,索引2,…) , reverse=True | False):对字典进行排序

dict.items():返回字典的可遍历的(键, 值) 元组数组
key:用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
operator.itemgetter(索引1,索引2,…):获取矩阵指定索引的值
reverse = True:降序;reverse = False:升序(默认值)


读取文本记录转换为Numpy矩阵

def file2matrix(filename):<br /> fr = open(filename)<br /> arrayOLines = fr.readlines() _#读取文件所有行<br /> _numberOfLines = len(arrayOLines) _#获取行数<br /> _returnMat = np.zeros((numberOfLines,2)) _#返回一个全为零的初始矩阵<br /> _classLabelVector = [] _#类别列表<br /> _index = 0 _#初始化行数<br /> _for line in arrayOLines:<br /> line = line.strip() _#删除行两头空格与换行符<br /> _listFromLine = line.split(' ') _#以空格为间隔将数据切分<br /> _returnMat[index,:] = listFromLine[1:3] _#将每一行的特征值替换初始矩阵<br /> _classLabelVector.append(str(listFromLine[-1])) _#将每一行数据的类别添加到类别列表<br /> _index += 1<br /> return returnMat,classLabelVector

代码中的函数介绍:

open(文件路径、文件名):打开文件

文件对象.readline():读取文件的一行

文件对象.readlines():读取文件的所有行

str.strip([chars]):移除字符串首尾指定的字符chars

str.split(str=””, num=string.count(str)):

str — 分隔符,默认为所有的空字符,包括空格、换行(\n)、Tab符(\t)等。
num — 分割次数。默认为 -1, 即分隔所有。


归一化特征值

对特征值进行归一化,目的在于 避免权重相同的特征值相差很大,从而使结果过度依赖于某一特征。

常用处理方式:

将特征值转化到0~1之间的值:newVlue = (oldValue - minValue) / (maxValue - minValue)
def autoNorm(dataSet):<br /> minValue = dataSet.min(0) #最小值(各个特征的min值)<br /> maxValue = dataSet.max(0) #最大值(各个特征的max值)<br /> ranges = maxValue - minValue #归一化公式的分母<br /> normDataSet = np.zeros(np.shape(dataSet)) #创建和原数据集相同维度的零矩阵<br /> m = dataSet.shape[0] #获取矩阵行数<br /> normDataSet = dataSet - np.tile(minValue,(m,1)) #归一化公式的分子<br /> normDataSet = normDataSet / np.tile(ranges,(m,1)) #归一化<br /> return normDataSet #归一化处理后的矩阵

代码中的函数介绍:

矩阵.max(axis=)、矩阵.min(axis=):获取矩阵的最大值、最小值

axis = 0:纵向;axis = 1:横向


K的取值

一般而言,从k = 1开始,随着k的逐渐增大,K近邻算法的分类效果会逐渐提升;在增大到某个值后,随着k的进一步增大,K近邻算法的分类效果会逐渐下降。

k值较小:

相当于用较小的邻域中的训练实例进行预测,只有距离近的(相似的)起作用。
单个样本的影响力过大。
近似误差会减小,但估计误差会增大。
对噪声敏感。
整体模型复杂,易发生过拟合。

k值较大:

此时距离测试点远的(不相似的)数据也会对预测结果产生影响。
近似误差会增大,但估计误差会减小。
整体模型简单。

k值的选择:

k值的大小要适中。
k通常取奇数,避免产生相等占比的情况。