k近邻法(k-nearest neighbor, k-NN)是1967年由Cover T和Hart P提出的一种基本分类与回归方法。它的工作原理是:存在一个样本数据集合,也称作为训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一个数据与所属分类的对应关系。输入没有标签的新数据后,将新的数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本最相似数据(最近邻)的分类标签。一般来说,我们只选择样本数据集中前k个最相似的数据,这就是k-近邻算法中k的出处,通常k是不大于20的整数。最后,选择k个最相似数据中出现次数最多的分类,作为新数据的分类。
KNN实战之一
1.导入算法所用的numpy和operate模块。
import numpy as np
import operator
2.创建最简单的带标签的数据集,并将其封装在函数creatDateSet()中。
def creatDateSet():
group = np.array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])#创建一个数组
labels = ['A','A','B','B']
return group,labels
3.实现最简单的KNN算法,并将其封装在函数classify0()中。
①.首先定义classify0()函数,有四个参数,inx表示待分类的新数据,dataset表示已知标签的数据集,labels为数据对应的标签,k表示待分类样本的分类取决于k个最相近的数据。
def classify0(inX, dataSet, labels, k):
②.函数的实现:首先把数据集中的点放入矩阵中,然后复制n倍(等同于dateset中样本的数目),再与dateset中的数据求距离。相当于将待分类数据与所有样本的距离存储在一个数组distances中。
dataSetSize = dataSet.shape[0]#第一维的个数(多少行)
diffMat = np.tile(inX, (dataSetSize,1)) - dataSet
#将inX重复1次形成datasetsize行的数组,与原来的dataset的坐标差值
sqDiffMat = diffMat**2#坐标差的平方
sqDistances = sqDiffMat.sum(axis = 1)#距离的平方
distances = sqDistances**0.5#一个数组
之后返回距离从小到大排列后的索引,放入数组sortedDistIndicies中。
sortedDistIndicies = np.argsort(distances)#返回的数组从小到大排序后对应的数组索引
创建字典classCount,统计距离待分类样本最相似的k个样本的类别及每类的样本个数,最后返回最相似的那个类别。
classCount={
}#创建字典
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]] #距离最近的k个点分别是哪一类
classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1#例如{'B': 2, 'A': 1};统计了最近的k个点分别有多少属于哪类
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)#按字典内容降序排列
return sortedClassCount[0][0]
4.综上:完整代码如下
import numpy as np
import operator
def creatDateSet():
group = np.array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])#创建一个数组
labels = ['A','A','B','B']
return group,labels
def classify0(inX, dataSet, labels, k):
#inX是待分类的样本,dataset为数据集,labels为样本数据对应的标签,k为距离最近的k个样本
dataSetSize = dataSet.shape[0]#第一维的个数(多少行)
diffMat = np.tile(inX, (dataSetSize,1)) - dataSet
#将inX重复1次形成datasetsize行的数组,与原来的dataset的坐标差值
sqDiffMat = diffMat**2#坐标差的平方
sqDistances = sqDiffMat.sum(axis = 1)#距离的平方
distances = sqDistances**0.5#一个数组
sortedDistIndicies = np.argsort(distances)#返回的数组从小到大排序后对应的数组索引
classCount={
}#创建字典
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]] #距离最近的k个点分别是哪一类
classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1#{'B': 2, 'A': 1}统计了最近的k个点分别有多少属于哪类
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)#按字典内容降序排列
return sortedClassCount[0][0]
def main():
group,labels = creatDateSet()
result = classify0([0,0], group ,labels,3)
print(result)
if __name__ == '__main__':
main()
5.运行结果:
E:\anaconda\envs\tf1\pyt