KNN 算法

来源:互联网 发布:淘宝晒图内裤爆光图片 编辑:程序博客网 时间:2024/06/05 14:40

什么是KNN

KNN (K-nearest neighbor) ,即 K 近邻算法.  它的工作原理非常简单. 
举个例子,我们有下面的训练集数据,根据电影中出现的打斗镜头和接吻镜头数将其分为爱情片和动作片:
电影名称打斗镜头接吻镜头电影类型California Man3104爱情片He's Not Really into Dudes2100爱情片Beautiful Woman181爱情片Kevin Longblade10110动作片Robo Slayer 3000995动作片Amped II982动作片?1890未知
那么,对下面类型未知的电影,我们如何对其分类呢? 
电影名称打斗镜头接吻镜头电影类型?1890未知

KNN 采用的方法是将新数据的每个特征与样本集中每个样本进行比较,计算其同样本的距离. 然后找出k 个距离最近的样本. 这些样本所属分类最多的分类,就是该数据的分类. 
比如,电影“?” 同上面样本集每个样本计算,得到距离. 如果 K 取 3,我们会发现“?” 同三个爱情片的距离最近,因此“?”也是爱情片. 
下面列出算法. 

算法详解

我们用 Python 实现了 KNN 算法来解决上面提出的分类问题. 
首先,生成算法使用的数据集:
  1. def createDataSet():
  2. '''
  3. 创建数据集
  4. '''
  5. group = np.array([[3, 104], [2, 100], [1, 81], [101, 10],[99, 5], [98, 2]])
  6. labels = ['A', 'A', 'A', 'D','D', 'D']
  7. return group, labels

然后写出 KNN 分类算法:
  1. def classify0(inX, dataSet, labels, k):
  2. '''
  3. KNN 分类
  4. :param inX:
  5. :param dataSet:
  6. :param labels:
  7. :param k:
  8. :return:
  9. '''
  10. dataSetSize = dataSet.shape[0]
  11. diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
  12. sqDiffMat = diffMat ** 2
  13. sqDistances = sqDiffMat.sum(axis=1)
  14. distances = sqDistances ** 0.5
  15. sortedDistIndicies = distances.argsort()
  16. classCount = {}
  17. for i in range(k):
  18. voteIlabel = labels[sortedDistIndicies[i]]
  19. classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
  20. sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
  21. print(sortedClassCount)
  22. return sortedClassCount[0][0]

KNN 算法在使用的时候,一般需要对特征数据进行归一化处理:
  1. def autoNorm(dataSet):
  2. '''
  3. 归一化
  4. :param dataSet:
  5. :return:
  6. '''
  7. minVals = dataSet.min(0)
  8. maxVals = dataSet.max(0)
  9. ranges = maxVals - minVals
  10. normDataSet = np.zeros(np.shape(dataSet))
  11. m = dataSet.shape[0]
  12. normDataSet = dataSet - np.tile(minVals, (m, 1))
  13. normDataSet = normDataSet/np.tile(ranges, (m,1))
  14. return normDataSet, ranges, minVals


我们也可以使用 matplotlib 画出二维空间的散点图
  1. def plot(dataSet):
  2. fig = plt.figure()
  3. ax = fig.add_subplot(111)
  4. ax.scatter(dataSet[:, 0], dataSet[:, 1])
  5. plt.show()


整体代码如下:
  1. #!/usr/bin/python
  2. # -*- coding: UTF-8 -*-
  3. import numpy as np
  4. import operator
  5. import matplotlib
  6. import matplotlib.pyplot as plt
  7. def createDataSet():
  8. '''
  9. 创建数据集
  10. '''
  11. group = np.array([[3, 104], [2, 100], [1, 81], [101, 10],[99, 5], [98, 2]])
  12. labels = ['A', 'A', 'A', 'D','D', 'D']
  13. return group, labels
  14. def classify0(inX, dataSet, labels, k):
  15. '''
  16. KNN 分类
  17. :param inX:
  18. :param dataSet:
  19. :param labels:
  20. :param k:
  21. :return:
  22. '''
  23. dataSetSize = dataSet.shape[0]
  24. diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
  25. sqDiffMat = diffMat ** 2
  26. sqDistances = sqDiffMat.sum(axis=1)
  27. distances = sqDistances ** 0.5
  28. sortedDistIndicies = distances.argsort()
  29. classCount = {}
  30. for i in range(k):
  31. voteIlabel = labels[sortedDistIndicies[i]]
  32. classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
  33. sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
  34. print(sortedClassCount)
  35. return sortedClassCount[0][0]
  36. def autoNorm(dataSet):
  37. '''
  38. 归一化
  39. :param dataSet:
  40. :return:
  41. '''
  42. minVals = dataSet.min(0)
  43. maxVals = dataSet.max(0)
  44. ranges = maxVals - minVals
  45. normDataSet = np.zeros(np.shape(dataSet))
  46. m = dataSet.shape[0]
  47. normDataSet = dataSet - np.tile(minVals, (m, 1))
  48. normDataSet = normDataSet/np.tile(ranges, (m,1))
  49. return normDataSet, ranges, minVals
  50. def plot(dataSet):
  51. fig = plt.figure()
  52. ax = fig.add_subplot(111)
  53. ax.scatter(dataSet[:, 0], dataSet[:, 1])
  54. plt.show()
  55. if __name__ == '__main__':
  56. dataSet, labels = createDataSet()
  57. dataSet, _, _ = autoNorm(dataSet)
  58. print(dataSet)
  59. plot(dataSet)
  60. print(classify0([18, 90], dataSet, labels,4))

KNN的问题

KNN 算法是基于实例的学习. KNN 算法执行时使用全部数据集. 因此如果数据量比较大,KNN 算法会使用大量和存储空间,计算也会非常耗时.