zoukankan      html  css  js  c++  java
  • KNN交叉验证,找出合适的K值

    在KNN里,通过交叉验证,我们即可以得出最合适的K值。它的核心思想无非就是把一些可能的K逐个去尝试一遍,然后选出效果最好的K值

    交叉验证的第一步是把训练数据进一步分成训练集和验证集。

    为什么这么做?

    道理其实很简单,因为我们需要一种评估的机制来选出最好的K值。那具体用什么数据来评估呢? 就是验证集! 因为测试数据是用来一次性测试的。比如上线前来测试是否满足上线的条件,但测试数据不能用于指导模型的训练。

    常用的交叉验证技术叫做K折交叉验证(K-fold Cross Validation)。 我们先把训练数据再分成训练集和验证集,之后使用训练集来训练模型,然后再验证集上评估模型的准确率。举个例子,比如一个模型有个参数叫alphaα,我们一开始不清楚要选择0.1还是1,所以这时候我们进行了交叉验证:把所有训练集分成K块,依次对每一个alphaα值评估它的准确率。

    一般情况下数据量较少的时候我们取的K值会更大,为什么呢?

    因为数据量较少的时候如果每次留出比较多的验证数据,对于训练模型本身来说是比较吃亏的,所以这时候我们尽可能使用更多的数据来训练模型。由于每次选择的验证数据量较少,这时候K折中的K值也会随之而增大,但到最后可以发现,无论K值如何选择,用来验证的样本个数都是等于总样本个数。

    最极端的情况下,我们可以采用leave_one_out交叉验证,也就是每次只把一个样本当做验证数据,剩下的其他数据都当做是训练样本。

    从零写交叉验证

    1.导入模块

    import numpy as np
    from sklearn import datasets
    from sklearn.neighbors import KNeighborsClassifier
    from sklearn.model_selection import KFold  #主要用于K折交叉验证

    2.导入数据

    # 导入iris数据集
    iris=datasets.load_iris()
    X=iris.data
    y=iris.target
    print(X.shape,y.shape)
    # 定义我们想要搜索的K值(候选集),这里定义8个不同的值
    ks=[1,3,5,7,9,11,13,15]

    结果:

    (150, 4) (150,)

    3.应用

    # 例:进行5折交叉验证,KFold返回的是每一折中训练数据和验证数据的index
    # 假设数据样本为:[1,3,5,6,11,12,43,12,44,2],总共10个样本
    # 则返回的kf的格式为(前面的是训练数据,后面的是验证数据):
    # [0,1,3,5,6,7,8,9],[2,4]
    # [0,1,2,4,6,7,8,9],[3,5]
    # [1,2,3,4,5,6,7,8],[0,9]
    # [0,1,2,3,4,5,7,9],[6,8]
    # [0,2,3,4,5,6,8,9],[1,7]
    kf =KFold(n_splits=5,random_state=2001,shuffle=True)
    
    # 保存当前最好的K值和对应的准确值
    best_k=ks[0]
    best_score=0
    
    # 循环每一个K值
    for k in ks:
        curr_score=0
        for train_index,valid_index in kf.split(X):
            #每一折的训练以及计算准确率
            clf=KNeighborsClassifier(n_neighbors=k)
            clf.fit(X[train_index],y[train_index])
            curr_score=curr_score+clf.score(X[valid_index],y[valid_index])
        #求5折的平均准确率
        avg_score=curr_score/5
        if avg_score>best_score:
            best_k=k
            best_score=avg_score
        print("现在的最佳准确率:%.2f"%best_score,"现在的最佳K值 %d"%best_k)
    
    print("最终最佳准确率:%.2f"%best_score,"最终的最佳K值 %d"%best_k)

    结果:

    现在的最佳准确率:0.96 现在的最佳K值 1
    现在的最佳准确率:0.96 现在的最佳K值 1
    现在的最佳准确率:0.97 现在的最佳K值 5
    现在的最佳准确率:0.98 现在的最佳K值 7
    现在的最佳准确率:0.98 现在的最佳K值 7
    现在的最佳准确率:0.98 现在的最佳K值 7
    现在的最佳准确率:0.98 现在的最佳K值 7
    现在的最佳准确率:0.98 现在的最佳K值 7
    最终最佳准确率:0.98 最终的最佳K值 7

    直接使用sklearn来实现同样的逻辑,只需要调用即可以实现K折交叉验证

    from sklearn import datasets
    from sklearn.neighbors import KNeighborsClassifier
    from sklearn.model_selection import GridSearchCV  #通过网络方式来获取参数
    
    # 导入iris数据集
    iris2=datasets.load_iris()
    X2=iris2.data
    y2=iris2.target
    print(X2.shape,y2.shape)
    
    # 设置需要搜索的K值,'n_neightbors'是sklearn中KNN的参数
    parameters={'n_neightbors':[1,3,5,7,9,11,13,15]}
    knn=KNeighborsClassifier()#注意:这里不用指定参数
    
    # 通过GridSearchCV来搜索最好的K值。这个模块的内部其实就是对每一个K值进行评估
    clf=GridSearchCV(knn,parameters,cv=5)  #5折
    clf.fit(X2,y2)
    
    # 输出最好的参数以及对应的准确率
    print("最终最佳准确率:%.2f"%clf.best_score_,"最终的最佳K值",clf.best_params_)

  • 相关阅读:
    maven .assembly
    命令参数解析库JCommonder
    OWL,以及XML,RDF
    Ambari是什么?
    上海新桥>风景服务区>宁波江东区车管所 及返程路线
    武汉旅游地图(zz)
    武汉旅游(zz)
    上海市松江区 <> 上海市金山区枫泾·万枫东路ab6177,racehttp://live.racingchina.com/
    明中路明华路到第九人民医院路线
    月台路春申塘桥到虹桥火车站
  • 原文地址:https://www.cnblogs.com/FYZHANG/p/12030460.html
Copyright © 2011-2022 走看看