楼主: 我的素质低
4517 3

[Python] 机器学习算法与Python实践之(一)k近邻(KNN)(转) [推广有奖]

已卖:2774份资源

学术权威

83%

还不是VIP/贵宾

-

TA的文库  其他...

〖素质文库〗

结构方程模型

考研资料库

威望
8
论坛币
23391 个
通用积分
28308.6707
学术水平
2705 点
热心指数
2881 点
信用等级
2398 点
经验
228516 点
帖子
2968
精华
52
在线时间
2175 小时
注册时间
2012-11-24
最后登录
2024-1-13

一级伯乐勋章 初级学术勋章 初级热心勋章 初级信用勋章 中级热心勋章 中级学术勋章 中级信用勋章 高级学术勋章 高级热心勋章 高级信用勋章 特级学术勋章

楼主
我的素质低 学生认证  发表于 2015-2-26 15:50:38 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币

   机器学习算法与Python实践这个系列主要是参考《机器学习实战》这本书。因为自己想学习Python,然后也想对一些机器学习算法加深下了解,所以就想通过Python来实现几个比较常用的机器学习算法。恰好遇见这本同样定位的书籍,所以就参考这本书的过程来学习了。(转载于zouxy09博客)



一、kNN算法分析



       K最近邻(k-Nearest Neighbor,KNN)分类算法可以说是最简单的机器学习算法了。它采用测量不同特征值之间的距离方法进行分类。它的思想很简单:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。


       

3.png

     比如上面这个图,我们有两类数据,分别是蓝色方块和红色三角形,他们分布在一个上图的二维中间中。那么假如我们有一个绿色圆圈这个数据,需要判断这个数据是属于蓝色方块这一类,还是与红色三角形同类。怎么做呢?我们先把离这个绿色圆圈最近的几个点找到,因为我们觉得离绿色圆圈最近的才对它的类别有判断的帮助。那到底要用多少个来判断呢?这个个数就是k了。如果k=3,就表示我们选择离绿色圆圈最近的3个点来判断,由于红色三角形所占比例为2/3,所以我们认为绿色圆是和红色三角形同类。如果k=5,由于蓝色四方形比例为3/5,因此绿色圆被赋予蓝色四方形类。从这里可以看到,k的值还是很重要的。

       KNN算法中,所选择的邻居都是已经正确分类的对象。该方法在定类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。由于KNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,KNN方法较其他方法更为适合。

       该算法在分类时有个主要的不足是,当样本不平衡时,如一个类的样本容量很大,而其他类样本容量很小时,有可能导致当输入一个新样本时,该样本的K个邻居中大容量类的样本占多数。因此可以采用权值的方法(和该样本距离小的邻居权值大)来改进。该方法的另一个不足之处是计算量较大,因为对每一个待分类的文本都要计算它到全体已知样本的距离,才能求得它的K个最近邻点。目前常用的解决方法是事先对已知样本点进行剪辑,事先去除对分类作用不大的样本。该算法比较适用于样本容量比较大的类域的自动分类,而那些样本容量较小的类域采用这种算法比较容易产生误分



二、Python实现



       对于机器学习而已,Python需要额外安装三件宝,分别是Numpy,scipy和Matplotlib。前两者用于数值计算,后者用于画图。安装很简单,直接到各自的官网下载回来安装即可。安装程序会自动搜索我们的python版本和目录,然后安装到python支持的搜索路径下。反正就python和这三个插件都默认安装就没问题了。

      



2.1、kNN基础实践


       一般实现一个算法后,我们需要先用一个很小的数据库来测试它的正确性,否则一下子给个大数据给它,它也很难消化,而且还不利于我们分析代码的有效性。

      首先,我们新建一个kNN.py脚本文件,文件里面包含两个函数,一个用来生成小数据库,一个实现kNN分类算法。代码如下:

  1. #########################################
  2. # kNN: k Nearest Neighbors
  3. # Input:      newInput: vector to compare to existing dataset (1xN)
  4. #             dataSet:  size m data set of known vectors (NxM)
  5. #             labels:  data set labels (1xM vector)
  6. #             k:   number of neighbors to use for comparison
  7.             
  8. # Output:     the most popular class label
  9. #########################################
  10. from numpy import *
  11. import operator
  12. # create a dataset which contains 4 samples with 2 classes
  13. def createDataSet():
  14. # create a matrix: each row as a sample
  15. group = array([[1.0, 0.9], [1.0, 1.0], [0.1, 0.2], [0.0, 0.1]])
  16. labels = ['A', 'A', 'B', 'B'] # four samples and two classes
  17. return group, labels
  18. # classify using kNN
  19. def kNNClassify(newInput, dataSet, labels, k):
  20. numSamples = dataSet.shape[0] # shape[0] stands for the num of row
  21. ## step 1: calculate Euclidean distance
  22. # tile(A, reps): Construct an array by repeating A reps times
  23. # the following copy numSamples rows for dataSet
  24. diff = tile(newInput, (numSamples, 1)) - dataSet # Subtract element-wise
  25. squaredDiff = diff ** 2 # squared for the subtract
  26. squaredDist = sum(squaredDiff, axis = 1) # sum is performed by row
  27. distance = squaredDist ** 0.5
  28. ## step 2: sort the distance
  29. # argsort() returns the indices that would sort an array in a ascending order
  30. sortedDistIndices = argsort(distance)
  31. classCount = {} # define a dictionary (can be append element)
  32. for i in xrange(k):
  33.   ## step 3: choose the min k distance
  34.   voteLabel = labels[sortedDistIndices[i]]
  35.   ## step 4: count the times labels occur
  36.   # when the key voteLabel is not in dictionary classCount, get()
  37.   # will return 0
  38.   classCount[voteLabel] = classCount.get(voteLabel, 0) + 1
  39. ## step 5: the max voted class will return
  40. maxCount = 0
  41. for key, value in classCount.items():
  42.   if value > maxCount:
  43.    maxCount = value
  44.    maxIndex = key
  45. return maxIndex
复制代码

       然后我们在命令行中这样测试即可:


  1. import kNN
  2. from numpy import *
  3. dataSet, labels = kNN.createDataSet()
  4. testX = array([1.2, 1.0])
  5. k = 3
  6. outputLabel = kNN.kNNClassify(testX, dataSet, labels, 3)
  7. print "Your input is:", testX, "and classified to class: ", outputLabel
  8. testX = array([0.1, 0.3])
  9. outputLabel = kNN.kNNClassify(testX, dataSet, labels, 3)
  10. print "Your input is:", testX, "and classified to class: ", outputLabel
复制代码

       这时候会输出:

  1. Your input is: [ 1.2  1.0] and classified to class:  A
  2. Your input is: [ 0.1  0.3] and classified to class:  B
复制代码

2.2、kNN进阶



       这里我们用kNN来分类一个大点的数据库,包括数据维度比较大和样本数比较多的数据库。这里我们用到一个手写数字的数据库,可以到这里下载。这个数据库包括数字0-9的手写体。每个数字大约有200个样本。每个样本保持在一个txt文件中。手写体图像本身的大小是32x32的二值图,转换到txt文件保存后,内容也是32x32个数字,0或者1,如下:

       数据库解压后有两个目录:目录trainingDigits存放的是大约2000个训练数据,testDigits存放大约900个测试数据。

4.png


        这里我们还是新建一个kNN.py脚本文件,文件里面包含四个函数,一个用来生成将每个样本的txt文件转换为对应的一个向量,一个用来加载整个数据库,一个实现kNN分类算法。最后就是实现这个加载,测试的函数。

  1. #########################################
  2. # kNN: k Nearest Neighbors
  3. # Input:      inX: vector to compare to existing dataset (1xN)
  4. #             dataSet: size m data set of known vectors (NxM)
  5. #             labels: data set labels (1xM vector)
  6. #             k: number of neighbors to use for comparison
  7.             
  8. # Output:     the most popular class label
  9. #########################################
  10. from numpy import *
  11. import operator
  12. import os

  13. # classify using kNN
  14. def kNNClassify(newInput, dataSet, labels, k):
  15. numSamples = dataSet.shape[0] # shape[0] stands for the num of row
  16. ## step 1: calculate Euclidean distance
  17. # tile(A, reps): Construct an array by repeating A reps times
  18. # the following copy numSamples rows for dataSet
  19. diff = tile(newInput, (numSamples, 1)) - dataSet # Subtract element-wise
  20. squaredDiff = diff ** 2 # squared for the subtract
  21. squaredDist = sum(squaredDiff, axis = 1) # sum is performed by row
  22. distance = squaredDist ** 0.5
  23. ## step 2: sort the distance
  24. # argsort() returns the indices that would sort an array in a ascending order
  25. sortedDistIndices = argsort(distance)
  26. classCount = {} # define a dictionary (can be append element)
  27. for i in xrange(k):
  28.   ## step 3: choose the min k distance
  29.   voteLabel = labels[sortedDistIndices[i]]
  30.   ## step 4: count the times labels occur
  31.   # when the key voteLabel is not in dictionary classCount, get()
  32.   # will return 0
  33.   classCount[voteLabel] = classCount.get(voteLabel, 0) + 1
  34. ## step 5: the max voted class will return
  35. maxCount = 0
  36. for key, value in classCount.items():
  37.   if value > maxCount:
  38.    maxCount = value
  39.    maxIndex = key
  40. return maxIndex
  41. # convert image to vector
  42. def  img2vector(filename):
  43.   rows = 32
  44.   cols = 32
  45.   imgVector = zeros((1, rows * cols))
  46.   fileIn = open(filename)
  47.   for row in xrange(rows):
  48.    lineStr = fileIn.readline()
  49.    for col in xrange(cols):
  50.     imgVector[0, row * 32 + col] = int(lineStr[col])
  51.   return imgVector
  52. # load dataSet
  53. def loadDataSet():
  54. ## step 1: Getting training set
  55. print "---Getting training set..."
  56. dataSetDir = 'E:/Python/Machine Learning in Action/'
  57. trainingFileList = os.listdir(dataSetDir + 'trainingDigits') # load the training set
  58. numSamples = len(trainingFileList)
  59. train_x = zeros((numSamples, 1024))
  60. train_y = []
  61. for i in xrange(numSamples):
  62.   filename = trainingFileList[i]
  63.   # get train_x
  64.   train_x[i, :] = img2vector(dataSetDir + 'trainingDigits/%s' % filename)
  65.   # get label from file name such as "1_18.txt"
  66.   label = int(filename.split('_')[0]) # return 1
  67.   train_y.append(label)
  68. ## step 2: Getting testing set
  69. print "---Getting testing set..."
  70. testingFileList = os.listdir(dataSetDir + 'testDigits') # load the testing set
  71. numSamples = len(testingFileList)
  72. test_x = zeros((numSamples, 1024))
  73. test_y = []
  74. for i in xrange(numSamples):
  75.   filename = testingFileList[i]
  76.   # get train_x
  77.   test_x[i, :] = img2vector(dataSetDir + 'testDigits/%s' % filename)
  78.   # get label from file name such as "1_18.txt"
  79.   label = int(filename.split('_')[0]) # return 1
  80.   test_y.append(label)
  81. return train_x, train_y, test_x, test_y
  82. # test hand writing class
  83. def testHandWritingClass():
  84. ## step 1: load data
  85. print "step 1: load data..."
  86. train_x, train_y, test_x, test_y = loadDataSet()
  87. ## step 2: training...
  88. print "step 2: training..."
  89. pass
  90. ## step 3: testing
  91. print "step 3: testing..."
  92. numTestSamples = test_x.shape[0]
  93. matchCount = 0
  94. for i in xrange(numTestSamples):
  95.   predict = kNNClassify(test_x[i], train_x, train_y, 3)
  96.   if predict == test_y[i]:
  97.    matchCount += 1
  98. accuracy = float(matchCount) / numTestSamples
  99. ## step 4: show the result
  100. print "step 4: show the result..."
  101. print 'The classify accuracy is: %.2f%%' % (accuracy * 100)
复制代码

       测试非常简单,只需要在命令行中输入:

  1. import kNN
  2. kNN.testHandWritingClass()
复制代码

       输出结果如下:

  1. step 1: load data...
  2. ---Getting training set...
  3. ---Getting testing set...
  4. step 2: training...
  5. step 3: testing...
  6. step 4: show the result...
  7. The classify accuracy is: 98.84%
复制代码

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:python 机器学习算法 学习算法 机器学习 knn 机器学习算法 python 近邻 KNN

已有 3 人评分经验 论坛币 学术水平 热心指数 信用等级 收起 理由
niuniuyiwan + 100 + 100 + 5 + 5 + 5 精彩帖子
xddlovejiao1314 + 100 + 100 + 5 + 5 + 5 精彩帖子
Nicolle + 100 + 5 + 5 精彩帖子

总评分: 经验 + 300  论坛币 + 200  学术水平 + 15  热心指数 + 15  信用等级 + 10   查看全部评分

本帖被以下文库推荐

心晴的时候,雨也是晴;心雨的时候,晴也是雨!
扣扣:407117636,欢迎一块儿吐槽!!

沙发
eric5488 发表于 2015-2-28 00:23:56
收藏, 謝謝樓主
已有 1 人评分经验 论坛币 收起 理由
xddlovejiao1314 + 10 + 3 鼓励积极发帖讨论

总评分: 经验 + 10  论坛币 + 3   查看全部评分

藤椅
xddlovejiao1314 学生认证  发表于 2015-10-9 11:19:34
火力全开~
已有 1 人评分论坛币 热心指数 收起 理由
niuniuyiwan + 10 + 1 分析的有道理

总评分: 论坛币 + 10  热心指数 + 1   查看全部评分

板凳
XCc0900720130 发表于 2015-12-20 09:01:15
非常感谢楼主,毕业论文用得上。

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注jltj
拉您入交流群
GMT+8, 2025-12-26 09:46