zoukankan      html  css  js  c++  java
  • KNN python实践

    本文实现了一个KNN算法,准备用作词频统计改进版本之中,这篇博文是从我另一个刚开的博客中copy过来的。
      KNN算法是一个简单的分类算法,它的动机特别简单:与一个样本点距离近的其他样本点绝大部分属于什么类别,这个样本就属于什么类别,算法的主要步骤如下:

    1.计算新样本点与已知类别数据集中样本点的距离。
    2.取前K个距离最近的(最相似的)点。
    3.统计这K个点所在类别出现的频率。
    4.选择出现频率最高的点作为新样本点的类别。

      KNN算法的优点在于一般精度高,对于异常的噪音数据不敏感。KNN一个明显的问题是当属于某个类别c的数据点在已知类别数据集中大量存在时,一个待预测的样本点的前K个最近的点总是存在很多类别c的点,解决这个问题的方法是计算类别的频率时,按照距离进行加权,使得离得近的点比离的远一些点更能影响类别频率排序的结果。
      KNN算法中K值的选定非常影响最后的结果,通常可以使用交叉检验来选取合适的k。下面是仿照sikit-learn的KNeighborsClassifier的调用方式写的KNN:

    class KNN_Classifier:
        def __init__(self, k):
            self.k = k
            self.train_data = None
            self.train_labels = None
    
        def fit(self, train_data, train_labels):
            self.train_data = normalize(train_data)
            self.train_labels = train_labels
    
        def predict(self, test_data):
            if (self.train_data is None) | (self.train_labels is None):
                print 'fit train data first!'
            pre_labels = []
            train_data_size = len(self.train_labels)
            #  for every data point in test set
            for x in normalize(test_data):
                #  calculate distance
                sq_diff_mat = (np.tile(x, (train_data_size, 1)) - self.train_data) ** 2
                distances = np.sum(sq_diff_mat, axis=1) ** .5
                #  get lowest k distances
                sorted_dis_indices = distances.argsort()[0: self.k]
                #  count the times class occur
                class_counts = {}
                for idx in sorted_dis_indices:
                    label = labels[idx]
                    class_counts[label] = class_counts.get(label, 0) + 1
                #  sort class_count dict
                sorted_class = sorted(class_counts.items(), key=lambda d: d[1], reverse=True)
                #  add max voted class to pre_labels
                pre_labels.append(sorted_class[0][0])
            return pre_labels
    

    测试代码如下所示

        #  load data
        data, labels = load_dating_data()
        #  split data into train set and test set
        split_pos = int(len(labels) * 0.9)
        train_data = normalize(data[0: split_pos])
        train_labels = labels[0: split_pos]
        test_data = normalize(data[split_pos: len(labels)])
        test_labels = labels[split_pos: len(labels)]
        #  init classifier
        classifier = KNN_Classifier(50)
        #  fit classifier
        classifier.fit(train_data, train_labels)
        #  predict the class of test data and count error points
        error_num = (test_labels != classifier.predict(test_data)).sum()
        #  calculate error rate and print
        print 'error rate is %f' % (error_num * 1.0 / len(test_labels))
    

      这里使用machine learning in action中的提供的dating data,将90%的数据用作训练数据集,10%的数据用作测试集,选取k=50算法得到的错误率为0.08。
      下面我们来看一下如何使用scikit-learn提供的KNN实现。
    scikit-learn中主要提供了2种KNN,KNeighborsClassifier和RadiusNeighborsClassifier。前者使用指定的前K个近邻来预测新样本点的类别,后者则是根据一个指定的半径,使用半径内所有的点来预测。创建一个KNN分类器时有这些重要的参数:

    n_neighbors/radius: 使用近邻的个数K或半径
    algorithm: 实现KNN的具体算法,如kd树等
    metric: 距离的计算方法,默认为'minkowski'表示minkowski距离
    p: minkowski距离中的参数p,p=1表示manhattan distance(l1范数),p=2表示euclidean_distance (l2范数)

      这里只列出了几个常用的参数,具体的可以参考链接。使用的方法和上面的测试代码类似,只需要将classifier替换成scikit-learn的实现就可以了。

  • 相关阅读:
    开发者论坛一周精粹(第九期)
    你刚吃的兰州牛肉面_背后就藏着大数据
    《C++覆辙录》——1.9:使用糟糕的语言
    老司机带你用MaxCompute和表格存储玩转车联网数据
    Gartner最新发布:2017年十大战略技术趋势
    js的事件的三个阶段,事件委托的原理
    Spring的AOP1
    了解SQL注入攻击
    了解XSS攻击
    了解Serialization
  • 原文地址:https://www.cnblogs.com/pengy813/p/5312426.html
Copyright © 2011-2022 走看看