机器学习之knn

1、KNN分类算法

KNN分类算法(K-Nearest-Neighbors Classification),又叫K近邻算法,是一个概念极其简单,而分类效果又很优秀的分类算法。

他的核心思想就是,要确定测试样本属于哪一类,就寻找所有训练样本中与该测试样本“距离”最近的前K个样本,然后看这K个样本大部分属于哪一类,那么就认为这个测试样本也属于哪一类。简单的说就是让最相似的K个样本来投票决定。

KNN算法不仅可以用于分类,还可以用于回归。通过找出一个样本的k个最近邻居,将这些邻居的属性的平均值赋给该样本,就可以得到该样本的属性。更有用的方法是将不同距离的邻居对该样本产生的影响给予不同的 权值(weight),如权值与距离成反比。 该算法在分类时有个主要的不足是,当样本不平衡时,如一个类的样本容量很大,而其他类样本容量很小时,有可能导致当输入一个新样本时,该样本的K个邻居中大容量类的样本占多数。 该算法只计算“最近的”邻居样本,某一类的样本数量很大,那么或者这类样本并不接近目标样本,或者这类样本很靠近目标样本。无论怎样,数量并不能影响运行结果。可以采用权值的方法(和该样本距离小的邻居权值大)来改进。
该方法的另一个不足之处是计算量较大,因为对每一个待分类的文本都要计算它到全体已知样本的距离,才能求得它的K个最近邻点。目前常用的解决方法是事先对已知 样本点进行剪辑,事先去除对分类作用不大的样本。该算法比较适用于 样本容量比较大的类域的自动分类,而那些样本容量较小的类域采用这种算法比较容易产生误分。
实现 K 近邻算法时,主要考虑的问题是如何对训练数据进行快速 K 近邻搜索,这在特征空间维数大及训练数据容量大时非常必要。
2、数据集介绍

machine-learning-databases/iris 点击打开链接

数据集信息:

这也许是最著名的数据库模式识别文献中被发现。 费舍尔的论文是一个典型的,经常被引用。 (见杜达&哈特,例如)。 50个实例的数据集包含3类,其中

每个类是指一种虹膜。 一个类是线性可分的从其他2;后者不是线性可分的。 

预测属性:类的虹膜。 

UCI中的Iris(鸢尾属植物)数据集。Iris数据包含150条样本记录,分剐取自三种不同的鸢尾属植物setosa、versic010r和virginica的花朵样本,每一

类各50条记录,其中每条记录有4个属性:萼片长度(sepal length)、萼片宽度sepalwidth)、花瓣长度(petal length)和花瓣宽度(petal width)。

这是一个极其简单的域。 


3、完整源码
[html]  view plain  copy
  1. <pre code_snippet_id="1766654" snippet_file_name="blog_20160717_1_8836404" name="code" class="python">#-*- coding: UTF-8 -*-     
  2. '''''   
  3. Created on 2016/7/17   
  4.    
  5. @author: chen   
  6. '''    
  7. import csv     #用于处理csv文件    
  8. import random    #用于随机数    
  9. import math             
  10. import operator  #    
  11. from sklearn import neighbors    
  12.     
  13. #加载数据集    
  14. def loadDataset(filename,split,trainingSet=[],testSet = []):    
  15.     with open(filename,"rb") as csvfile:    
  16.         lines = csv.reader(csvfile)    
  17.         dataset = list(lines)    
  18.         for x in range(len(dataset)-1):    
  19.             for y in range(4):    
  20.                 dataset[x][y] = float(dataset[x][y])    
  21.             if random.random()<split:    
  22.                 trainingSet.append(dataset[x])    
  23.             else:    
  24.                 testSet.append(dataset[y])    
  25.     
  26. #计算距离    
  27. def euclideanDistance(instance1,instance2,length):    
  28.     distance = 0    
  29.     for x in range(length):    
  30.         distance = pow((instance1[x] - instance2[x]),2)    
  31.     return math.sqrt(distance)    
  32.     
  33. #返回K个最近邻    
  34. def getNeighbors(trainingSet,testInstance,k):    
  35.     distances = []    
  36.     length = len(testInstance) -1    
  37.     #计算每一个测试实例到训练集实例的距离    
  38.     for x in range(len(trainingSet)):    
  39.         dist = euclideanDistance(testInstance, trainingSet[x], length)    
  40.         distances.append((trainingSet[x],dist))    
  41.     #对所有的距离进行排序    
  42.     distances.sort(key=operator.itemgetter(1))    
  43.     neighbors = []    
  44.     #返回k个最近邻    
  45.     for x in range(k):    
  46.         neighbors.append(distances[x][0])    
  47.     return neighbors    
  48.     
  49. #对k个近邻进行合并,返回value最大的key    
  50. def getResponse(neighbors):    
  51.     classVotes = {}    
  52.     for x in range(len(neighbors)):    
  53.         response = neighbors[x][-1]    
  54.         if response in classVotes:    
  55.             classVotes[response]+=1    
  56.         else:    
  57.             classVotes[response] = 1    
  58.     #排序    
  59.     sortedVotes = sorted(classVotes.iteritems(),key = operator.itemgetter(1),reverse =True)    
  60.     return sortedVotes[0][0]    
  61.     
  62. #计算准确率    
  63. def getAccuracy(testSet,predictions):    
  64.     correct = 0    
  65.     for x in range(len(testSet)):    
  66.         if testSet[x][-1] == predictions[x]:    
  67.             correct+=1    
  68.     return (correct/float(len(testSet))) * 100.0    
  69.     
  70. def main():    
  71.     trainingSet = []  #训练数据集    
  72.     testSet = []      #测试数据集    
  73.     split = 0.67      #分割的比例    
  74.     loadDataset(r"../data/iris.txt", split, trainingSet, testSet)     
  75.     print "Train set :" + repr(len(trainingSet))    
  76.     print "Test set :" + repr(len(testSet))                    
  77.         
  78.     predictions = []    
  79.     k = 3    
  80.     for x in range(len(testSet)):    
  81.         neighbors = getNeighbors(trainingSet, testSet[x], k)    
  82.         result = getResponse(neighbors)    
  83.         predictions.append(result)    
  84.         print ">predicted = " + repr(result) + ",actual = " + repr(testSet[x][-1])    
  85.     accuracy = getAccuracy(testSet, predictions)    
  86.     print "Accuracy:" + repr(accuracy) + "%"    
  87.     
  88. if __name__ =="__main__":    
  89.     main()  pre><br>  
  90. <br>  
  91. <pre>pre>  
  92. <div><br>  

  1. div>  
  2. 2. sklearn knn的使用,以及cross validation交叉验证

    2.1 数据集的准备

    数据集来源:https://archive.ics.uci.edu/ml/datasets/Iris

    代码github地址以及数据集github地址,见本人的github


    import numpy as np
    from sklearn.metrics import accuracy_score
    from sklearn.neighbors import KNeighborsClassifier
    from sklearn.cross_validation import train_test_split, cross_val_score
    import pandas as pd
    import matplotlib.pyplot as plt
    
    
    def load_data():
        names = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width', 'class']
        # loading training data
        path = '../dataset/knn/iris_data.txt'
        df = pd.read_csv(path, header=None, names=names)
        # print df.head()
        x = np.array(df.ix[:, 0: 4])
        y = np.array(df['class'])
    
        print x.shape, y.shape
        # x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.33, random_state=40)
        return train_test_split(x, y, test_size=0.33, random_state=40)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    机器学习之knn_第1张图片

    2.2 验证预测效果

    def predict():
        x_train, x_test, y_train, y_test = load_data()
        k = 3
        knn = KNeighborsClassifier(n_neighbors=k)
        knn.fit(x_train, y_train)
        pred = knn.predict(x_test)
        print accuracy_score(y_test, pred)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2.3 交叉验证

    def cross_validation():
        x_train, x_test, y_train, y_test = load_data()
        k_lst = list(range(1, 30))
        lst_scores = []
    
        for k in k_lst:
            knn = KNeighborsClassifier(n_neighbors=k)
            scores = cross_val_score(knn, x_train, y_train, cv=10, scoring='accuracy')
            lst_scores.append(scores.mean())
    
        # changing to misclassification error
        MSE = [1 - x for x in lst_scores]
        optimal_k = k_lst[MSE.index(min(MSE))]
        print "The optimal number of neighbors is %d" % optimal_k
        # plot misclassification error vs k
        # plt.plot(k_lst, MSE)
        # plt.ylabel('Misclassification Error')
        plt.plot(k_lst, lst_scores)
        plt.xlabel('Number of Neighbors K')
        plt.ylabel('correct classification rate')
        plt.show()
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    机器学习之knn_第2张图片


    knn改进方法
    1. 不同的K值加权

    2. 距离度量标准根据实际问题,使用不同的距离

    3. 特征归一化,例如,身高和体重x=[180,70],升高计算明显,更影响结果,所有需要对两者分别求平均值,然后归一化。

    4. 如果维数过大,可以做PCA降维处理


你可能感兴趣的:(机器学习)