• 用scikit-learn估计值分类——近邻算法(KNN)


    用scikit-learn估计值分类主要是为数据挖掘搭建通用的框架。有了这个框架之后,增加了算法的泛化性,减少了数据挖掘的复杂性。

    用scikit-learn估计值分类有这三个方面:

                      1. 估计器(estimator):用于分类、聚类和回归分析。

                      2. 转换器(transformer):用于数据的预处理和数据的转换。

                      3. 流水线(pipeline):组合数据挖掘流程,便于再次使用。

    近邻(kNN,k-NearestNeighbor)分类算法是标准数据挖掘分类技术中最为直观的一种。为了对新个体进行分类,它查找训练集,找到了与新个体最相似的那些个体,看看这些个体大多属于哪个类别,
    就把新个体分到哪个类别。近邻算法几乎可以对任何数据进行分类,但是要计算数据集中每两个个体之间的距离,计算量很大。同时还有一个问题是在特征取离散值的数据集上表现很差。

    距离是一个很关键的问题。欧式距离(两个点之间直线距离)、曼哈顿距离(两个特征在标准坐标系中绝对轴距之和)、余弦距离(特征向量夹角的余弦值)。

    接下来我们利用一个叫电离层的数据集(http://archive.ics.uci.edu/ml/machine-learning-databases/ionosphere/)来分析近邻算法的运用。在这个网站里点击ionosphere.data,之后复制这个数据,保存在本地。然后,我们来进行近邻算法的实现吧!

    import csv
    import numpy as np
    
    # 创建两个数组分别存放特征值和类别
    x = np.zeros((351, 34), dtype="float")
    y = np.zeros((351, ), dtype="bool")
    '''
    with open("ionosphere.data", 'r') as input_file:
        reader = csv.reader(input_file)
    '''
    input_file = open('ionosphere.data', 'r')
    reader = csv.reader(input_file)
    
    # 遍历文件中每一行数据,每一行数据相当于一个个体,用枚举函数来获取每一行的索引值,更新数据集x。
    for i, row in enumerate(reader):
        data = [float(datum) for datum in row[:-1]]
        x[i] = data
        y[i] = row[-1] == "g"
    
    # 建立测试集和训练集。
    from sklearn.model_selection import train_test_split
    x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=14)
    # print "There are {0} samples in training dataset".format(x_train.shape[0])
    # print "There are {0} samples in testing dataset".format(x_test.shape[0])
    # print "Each sample has {0} features".format(x_train.shape[1])
    
    # 然后导入K近邻分类器这个类,并为其初始化一个实例。
    from sklearn.neighbors import KNeighborsClassifier
    # 创建一个估计器
    estimator = KNeighborsClassifier()
    # 创建好之后,开始用训练数据进行训练。K近邻估计器会分析训练集中的数据,通过比较待分类的新数据点和训练集中的数据,找到新数据点的近邻。
    estimator.fit(x_train, y_train)
    # 接着用测试集测试算法。
    y_predicted = estimator.predict(x_test)
    accuracy = np.mean(y_test == y_predicted) * 100
    print "The accuracy is {0:.1f}%".format(accuracy)
    # The accuracy is 86.4%
    # 正确率很高,但是仅仅是使用默认的参数,在某些具体的情况下是不能通用的,所以,要学着根据实验的实际情况,尽可能选用合适的参数值,争取达到最佳的效果。
    
    # 我们通常用训练集训练算法,然后在测试集上评估效果。当测试集很简单,我们就会认为算法表现很出色。反之,我们可能会认为算法很糟糕。其实,只是凭一次的测试或一次的训练,是很难真正决定一个算法的好坏。所以,此时我们就要用到交叉检验了(将数据分割成很多部分,多次测试)。
    '''
    交叉检验:
    1.将整个大数据集分成几个部分
    2.对于每一部分执行以下操作:
    将其中一部分作为当前测试集
    用剩余部分去训练算法
    在当前测试集上测试算法
    3.记录每一次得分及平均得分
    4.在上述过程中,每条数据只能在测试集中出现一次,以减少运气成分。
    '''
    # 导入cross_val_score交叉检验方式
    from sklearn.model_selection import cross_val_score
    scores = cross_val_score(estimator, x, y, scoring="accuracy")
    average_accuracy = np.mean(scores) * 100
    print "The average accuracy is {0:.1f}%".format(average_accuracy)
    # The average accuracy is 82.3%
    # 设置参数。参数设置对于一个算法很重要,灵活的设置参数能大大提高算法的泛化能力,所以,选取好的参数值跟数据集的特征息息相关。
    # 在近邻算法中,最重要的参数(n_neighbors)是选取多少个近邻作为预测依据。它过大过小会造成不同的分类结果。
    # 下面我们测试n_neighbors的值,比如1到20,可以重复进行多次实验,观察不同参数所带来的结果之间的差异。
    from collections import defaultdict
    avg_scores = []
    all_scores = defaultdict(list)
    for n_neighbors in xrange(1,21):
        estimator_ = KNeighborsClassifier(n_neighbors=n_neighbors)
        scores = cross_val_score(estimator_, x, y, scoring="accuracy")
        avg_scores.append(np.mean(scores))
        all_scores[n_neighbors].append(scores)
    
    # 为了更直观的观察差异,我们可以用图来表示。
    from matplotlib import pyplot as plt
    parameter_values = list(range(1,21))
    #plt.plot(parameter_values, avg_scores, "-o")
    #plt.show()
    plt.figure(figsize=(32,20))
    plt.plot(parameter_values, avg_scores, '-o', linewidth=5, markersize=24)
    plt.axis([0, max(parameter_values), 0, 1.0])
    # plt.show()
    # 可以看出随着近邻数的增加,正确率不断下降。
    
    
    # 对数据预处理
    '''
    对于不同特征的取值范围千差万别,常见的解决方法是对不同的特征进行规范化,使它们的特征值落在相同的值域或从属于某几个确定的类别。
    '''
    # 选择最具区分度的特征、创建新特征等都属于预处理的范畴。
    # 预处理示例
    x_broken = np.array(x)
    # 对数据的第三个特征的值除以10
    x_broken[:,::2] /= 10
    # print x_broken
    # 再来计算正确率
    original_scores = cross_val_score(estimator, x, y, scoring='accuracy')
    print "The original average accuracy for is {0:.1f}%".format(np.mean(original_scores) * 100)
    # The original average accuracy for is 82.3%
    broken_scores = cross_val_score(estimator, x_broken, y, scoring="accuracy")
    print "The broken average accuracy for is {0:.1f}%".format(np.mean(broken_scores) * 100)
    # The broken average accuracy for is 71.5%
    # 这次跌到71.5%。如果,把特征值转变到0到1之间就能解决这个问题。将特征值规范化,使用minmaxscaler类。
    from sklearn.preprocessing import MinMaxScaler
    # 不需要单独进行训练,直接调用fit_transform()函数,即可完成训练和转换。
    # x_transformed = MinMaxScaler().fit_transform(x)
    # 接下来将前面的broken数据拿来测试
    x_transformed = MinMaxScaler().fit_transform(x_broken)
    transformed_scores = cross_val_score(estimator, x_transformed, y, scoring="accuracy")
    print "The average accuracy for is {0:.1f}%".format(np.mean(transformed_scores) * 100)
    # The average accuracy for is 82.3%
    # 正确率再次升到82.3%说明将特征值规范化有利于减少异常值对近邻算法的影响。
    
    # 流水线
    # 实现一个数据挖掘流水线,能大大提高效率。它就好比一个框架,能够有效的将转换器和估计器结合。
    from sklearn.pipeline import Pipeline
    # 流水线的核心是元素为元组的列表。第一个元组规范特征取值范围,第二个元组实现预测功能。
    scaling_pipeline = Pipeline([("scale", MinMaxScaler()), ("predict", KNeighborsClassifier())])
    scores_1 = cross_val_score(scaling_pipeline, x_broken, y, scoring="accuracy")
    print "The pipeline scored_1 an average accuracy for is {0:.1f}%".format(np.mean(scores_1) * 100)
    # The pipeline scored_1 an average accuracy for is 82.3%
    # 运行结果与之前的一样,说明设置流水线很有用,因为它能确保代码的复杂程度不至于超出掌控范围。
    # 我们再将数据规范化应用到原始数据集上,看看能不能使准确率上升,以说明数据集规范化能提升没有异常值的数据。
    scores_2 = cross_val_score(scaling_pipeline, x, y, scoring="accuracy")
    print "The pipeline scored_2 an average accuracy for is {0:.1f}%".format(np.mean(scores_2) * 100)
    # The pipeline scored_2 an average accuracy for is 82.3%
    # 这个结果说明,数据规范化只能将含有异常值的数据集的准确率提高。

     

  • 相关阅读:
    想当老板的人,三点特征很重要(转)
    突破三个自我,你就不光是老板的料
    掌握这3套创业战略 保你赚到百万财富 
    也感山西黑窑洞
    再游府河有感
    朋友的影响力非常大,朋友决定你的财富
    夏日乘凉
    职业生涯的八大“定位法则”
    一生何求
    赠你一方明月
  • 原文地址:https://www.cnblogs.com/llhy1178/p/6876785.html
Copyright © 2020-2023  润新知