k近邻法的原理在这就不再多说,可以参考李航老师的《统计学习方法》(第2版),这里直接展示用python实现k近邻最简单的实现方法-线性扫描。
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
# K近邻法线性扫描方法的实现,该方法在训练集很大时,计算会非常耗时,这种情况下是不适合采用该方法的
# 实现步骤:
# 1.计算输入实例与每一个训练实例的距离;
# 2.对以上距离按照递增次序进行排序;
# 3.选取合适的k值;
# 4.确定与该输入实例最邻近的k个实例的类别的出现频数;
# 5.返回这k个类别中出现频数最多的类别,作为该输入实例的类别
"""
import numpy as np
import operator
def KNN_liner_scan(inputExample, dataSet, category, k):
"""
:param inputExample: 输入的实例
:param dataSet: 训练数据集
:param category: 分类类别
:param k: k值
:return: 输入实例的类别
"""
dataSetSize = dataSet.shape[0] # 训练数据集的个数
"""
# 接着计算输入实例与各训练集之间的差值(为下一个的距离度量做准备)
# 通过numpy.tile(A, reps)给定重复次数来构造与训练实例数组一样大小的数组,用于差值计算
"""
differenceValue = np.tile(inputExample, (dataSetSize, 1)) - dataSet
squareDifferenceValue = differenceValue ** 2
rowSumValue = squareDifferenceValue.sum(axis=1) # 将每行的平方距离数据求和,输入空间为n维向量
euclideanDistance = rowSumValue ** 0.5 # 距离度量采用欧式距离,计算输入实例与各训练集数据的欧式距离,作为距离度量。
sortedEuclideanDistanceIndices = euclideanDistance.argsort() # 将欧式距离进行排序(从小到大)之后,返回对应的在原来数组中的索引,方便为下一步获取类别
categoryInfo = {} # 用于统计这k个实例的类别出现的频数
for i in range(k):
kExampleCategory = category[sortedEuclideanDistanceIndices[i]] # 获取这k个实例对应的类别
categoryInfo[kExampleCategory] = categoryInfo.get(kExampleCategory, 0) + 1 # 统计各类别出现的频数
# 对各类别出现的频数进行降序排序
sortCategoryInfo = sorted(categoryInfo.items(), key=operator.itemgetter(1), reverse=True)
return sortCategoryInfo[0][0] # 采用多数表决,返回出现频数最大的类别
def createDataSet():
# 创建测试数据
dataSetTest = np.array([
[1.1, 1.2],
[1.4, 2.0],
[2.1, 2.2],
[1.8, 1.6],
[2.9, 3.0],
[5.0, 2.5]
])
categoryTest = ['a1', 'b2', 'a1', 'b4', 'a1', 'd1']
return dataSetTest, categoryTest
# 获取创建数据
dataSet, category = createDataSet()
predictCategory = KNN_liner_scan([1.3, 1.9], dataSet, category, 2)
print('category of [1.3, 1.9]:', predictCategory)