机器学习学习笔记(五)之K-近邻算法(KNN)

一、K-近邻算法(KNN)原理

  • 定义:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一类别,则该样本也属于这个类别
  • 距离公式:两个样本的距离可以通过欧式距离计算

二、K-近邻算法API

  • sklearn.neighbors.KNeighorsClassifier(n_neighbors=5,algorithm=‘auto’)
    • n_neighbors:int,可选,默认为5,k_neighbors查询默认使用的邻居数。
    • algorithm:{‘auto’,‘ball_tree’,‘kd_tree’,‘brute’},其中’auto’将尝试根据传递给fit方法的值来决定最适合的算法(不同实现方式影响效率)。

三、案例:鸢尾花种类预测

  1. 获取数据
  2. 数据集划分
  3. 特征工程-标准化
  4. KNN预估器流程
  5. 模型评估
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier


def knn_iris():
    '''
    用KNN算法对鸢尾花进行分类
    :return:
    '''
    # 1、获取数据
    iris = load_iris()

    # 2、划分数据集
    x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=6)
	# 训练集的特征值x_train 测试集的特征值 x_test 训练集的目标值y_train 测试集的目标值y_test
	
    # 3、特征工程-标准化
    transfer = StandardScaler()
    x_train = transfer.fit_transform(x_train)
    x_test = transfer.transform(x_test) #对数据预处理时,测试集要以训练集的统计特征进行标准化

    # 4、KNN算法预估器
    estimator = KNeighborsClassifier(n_neighbors=3)
    estimator.fit(x_train,y_train)

    # 5、模型评估
    # 方法1:直接比对真实值和预测值
    y_predict = estimator.predict(x_test)
    print('y_predict:\n',y_predict)
    print('直接比对真实值和预测值:\n',y_test==y_predict)

    #方法2:计算准确率
    score = estimator.score(x_test,y_test)
    print('准确率为:\n',score)
    return None


if __name__=='__main__':
    knn_iris()


运行结果:
y_predict:
 [0 2 0 0 2 1 1 0 2 1 2 1 2 2 1 1 2 1 1 0 0 2 0 0 1 1 1 2 0 1 0 1 0 0 1 2 1
 2]
直接比对真实值和预测值:
 [ True  True  True  True  True  True False  True  True  True  True  True
  True  True  True False  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True False  True
  True  True]
准确率为:
 0.9210526315789473

四、K-近邻算法总结

  • 优点:简单,易于理解,易于实现,无需训练
  • 缺点:
    • 懒惰算法,对测试样本分类时的计算量大,内存开销大
    • 必须指定K值,K值选择不当则分类精度不能保证
      -使用场景:小数据场景,几千~几万样本,具体场景具体业务去测试

五、模型选择与调优

1、交叉验证(cross validation)

  • 将拿到的训练数据,分为训练集和验证集。比如将数据分为四份,其中一份作为验证集,经过四次测试,每次更换不同的验证集,得到四组模型结果,取平均值作为最终结果,称为4折交叉验证。
  • 训练集:训练集+验证集
  • 测试集:测试集

2、超参数搜索—网格搜索(Grid Search)

  • 通常情况下,有很多参数是需要手动指定的(如K值),这种叫超参数,但是手动过程复杂, 所以需要对模型预设几种超参数组合。每组超参数都采用交叉验证来进行评估,最后选出最优参数组合建立模型。

3、API

  • sklearn.model_selection.GridSearchCV()estimator,param_grid=None,cv=None)
    • 对估计器的指定参数进行详尽搜索
    • estimator:估计器对象
    • param_grid:估计器参数(dict:以字典形式传入){‘n_neighbors’:[1,3,5]}
    • cv:指定几折交叉验证
    • fit():输入训练数据
    • score():准确率
    • 结果分析:
      • 最佳参数:best_paramas_
      • 最佳结果:best_score_
      • 最佳估计器:best_estimator_
      • 交叉验证结果:cv_results_

4、上述鸢尾花案例增加K值调优

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import GridSearchCV

def knn_iris_gscv():
    '''
    用KNN算法对鸢尾花进行分类,添加网格搜索和交叉验证
    :return:
    '''
    # 1、获取数据
    iris = load_iris()

    # 2、划分数据集
    x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=6)

    # 3、特征工程-标准化
    transfer = StandardScaler()
    x_train = transfer.fit_transform(x_train)
    x_test = transfer.transform(x_test) #对数据预处理时,测试集要以训练集的统计特征进行标准化

    # 4、KNN算法预估器
    estimator = KNeighborsClassifier()

    # 加入网格搜索与交叉验证
    # 参数准备
    param_dict = {'n_neighbors':[1,3,5,7,9,11]}
    estimator = GridSearchCV(estimator,param_grid=param_dict,cv=10)
    estimator.fit(x_train,y_train)

    # 5、模型评估
    # 方法1:直接比对真实值和预测值
    y_predict = estimator.predict(x_test)
    print('y_predict:\n',y_predict)
    print('直接比对真实值和预测值:\n',y_test==y_predict)

    #方法2:计算准确率
    score = estimator.score(x_test,y_test)
    print('准确率为:\n',score)

    # 最佳参数:best_paramas_
    print('最佳参数:\n',estimator.best_params_)
    # 最佳结果:best_score_
    print('最佳结果:\n',estimator.best_score_)
    # 最佳估计器:best_estimator_
    print('最佳估计器:\n',estimator.best_estimator_)
    # 交叉验证结果:cv_results_
    print('交叉验证结果:\n',estimator.cv_results_)
    return None

if __name__=='__main__':
    knn_iris_gscv()


运行结果:
y_predict:
 [0 2 0 0 2 1 2 0 2 1 2 1 2 2 1 1 2 1 1 0 0 2 0 0 1 1 1 2 0 1 0 1 0 0 1 2 1
 2]
直接比对真实值和预测值:
 [ True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True False  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True False  True
  True  True]
准确率为:
 0.9473684210526315
#此为测试集的准确率结果

最佳参数:
 {'n_neighbors': 11}
最佳结果:
 0.9734848484848484
#此为训练集分为的验证集的准确率结果

最佳估计器:
 KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
                     metric_params=None, n_jobs=None, n_neighbors=11, p=2,
                     weights='uniform')
# 最常用距离公式,闵可夫斯基距离,p=1时为曼哈顿距离(绝对值距离),p=2时为欧式距离

交叉验证结果:
 {'mean_fit_time': array([0.00240009, 0.00050008, 0.00049999, 0.00040007, 0.00030003,
       0.00040002]), 'std_fit_time': array([0.0048829 , 0.00050008, 0.00049999, 0.00048998, 0.0004583 ,
       0.00048992]), 'mean_score_time': array([0.00240016, 0.00140004, 0.00110013, 0.00110002, 0.0012001 ,
       0.00109999]), 'std_score_time': array([0.0006634 , 0.00048999, 0.00029991, 0.00030003, 0.00039999,
       0.00030003]), 'param_n_neighbors': masked_array(data=[1, 3, 5, 7, 9, 11],
             mask=[False, False, False, False, False, False],
       fill_value='?',
            dtype=object), 'params': [{'n_neighbors': 1}, {'n_neighbors': 3}, {'n_neighbors': 5}, {'n_neighbors': 7}, {'n_neighbors': 9}, {'n_neighbors': 11}], 'split0_test_score': array([1., 1., 1., 1., 1., 1.]), 'split1_test_score': array([0.91666667, 0.91666667, 1.        , 0.91666667, 0.91666667,
       0.91666667]), 'split2_test_score': array([1., 1., 1., 1., 1., 1.]), 'split3_test_score': array([1.        , 1.        , 1.        , 1.        , 0.90909091,
       1.        ]), 'split4_test_score': array([1., 1., 1., 1., 1., 1.]), 'split5_test_score': array([0.90909091, 0.90909091, 1.        , 1.        , 1.        ,
       1.        ]), 'split6_test_score': array([1., 1., 1., 1., 1., 1.]), 'split7_test_score': array([0.90909091, 0.90909091, 0.90909091, 0.90909091, 1.        ,
       1.        ]), 'split8_test_score': array([1., 1., 1., 1., 1., 1.]), 'split9_test_score': array([0.90909091, 0.81818182, 0.81818182, 0.81818182, 0.81818182,
       0.81818182]), 'mean_test_score': array([0.96439394, 0.95530303, 0.97272727, 0.96439394, 0.96439394,
       0.97348485]), 'std_test_score': array([0.04365767, 0.0604591 , 0.05821022, 0.05965639, 0.05965639,
       0.05742104]), 'rank_test_score': array([5, 6, 2, 3, 3, 1])}

Process finished with exit code 0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值