数据挖掘算法之-----KNN算法

1、KNN概念

KNN算法:K-Nearest Neighbor,K近邻算法,即K个最近的邻居(近朱者赤近墨者黑)
KNN即可用于分类,也可用于回归

  • 分类预测时,使用K个邻居中,类别数量(或加权后)作为预测的结果
  • 回归预测时,使用K个邻居的均值(或加权后),最为预测结果

2、超参数概念

超参数:人为指定,超参数不同对模型效果影响很大

2.1、K值

  • K值大,容错性增加,敏感性降低,易导致欠拟合
  • K值小,容错性降低,敏感性增加,易导致过拟合

极端情况,使用整个样本数量作为K值,那么无论预测值在哪,结果都一样

2.2、距离度量方式

scikit-learn中,使用闵可夫斯基距离
当p=2时,即为欧几里得距离

2.3、权重的计算方式

  • 统一权重
  • 距离加权权重:距离的反比
    例:预测目标N,K值为3,周围A,B、C到N的距离为2,3,4.那么ABC的权重分别为(1/2)/(1/2+1/3+1/4),(1/3)/(1/2+1/3+1/4),(1/4)/(1/2+1/3+1/4),目的保证权重和为1

2.4、算法步骤

1、确定超参数

  • 确定近邻数量K
  • 确定距离度量方式
  • 确定权重计算方式

2、从训练集中选择离待预测样本A最近的K个样本
3、根据K个样本预测A

  • 分类:K个样本的类别预测
  • 回归:K个样本目标值y的均值预测

注意:当类别不同距离待预测样本距离相同时,sklearn根据训练集中出现的顺序选择,对于算法的预测结果,不存在随机,相同的输入一定得到相同的输出

3、使用KNN实现分类

3.1、建模预测,假设邻居数量为3,观察预测结果

需要的库
from sklearn.neighbors import KNeighborsClassifier #sklearn中针对分类的库
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report #查看分类评估结果

KNeighborsClassifier的参数
n_neighbors邻居的数量,weights权重的计算方式,uniform统一权重,distance权重与距离成反比

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report

iris=load_iris()
X=iris.data[:,:2]
y=iris.target
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.25,random_state=0)
#####################以下为KNN建模预测##############################
knn=KNeighborsClassifier(n_neighbors=3,weights='uniform')
knn.fit(X_train,y_train)
y_hat=knn.predict(X_test)
print(classification_report(y_test,y_hat))

结果

              precision    recall  f1-score   support
           0       1.00      1.00      1.00        13
           1       0.78      0.44      0.56        16
           2       0.44      0.78      0.56         9
    accuracy                           0.71        38
   macro avg       0.74      0.74      0.71        38
weighted avg       0.77      0.71      0.71        38

3.2、超参数对模型的影响

K值越小,模型敏感度越强(稳定性越弱),模型越复杂,越容易过拟合
K值越大,模型敏感度越弱(稳定性越强),模型越简单,越容易欠拟合

3.3、超参数的调整:网格交叉验证

需要的库
from sklearn.model_selection import GridSearchCV #网格交叉验证库
交叉验证结果输出
最高分print(gs.best_score_)
最好的超参数print(gs.best_params_)
最好的模型print(gs.best_estimator_)

GridSearchCV的参数
estimator 评估器,对哪个模型调整超参数,如knn
param_grid 需要检验的超参数组合,从组合中找出最好的超参数组合
scoring 模型的评估标准,比如正确率,精准率等
n_jobs 并发数量,-1代表使用所有CPU
cv 交叉验证的折数,把训练集分成几份,每次把其中一份拿出来进行验证
verbose 输出冗余信息

#网格交叉验证
from sklearn.model_selection import GridSearchCV
knn=KNeighborsClassifier()
#定义超参数组合
grid={'n_neighbors':range(1,11,1),'weights':['uniform','distance']}
gs=GridSearchCV(estimator=knn,param_grid=grid,scoring='accuracy',n_jobs=-1,cv=5,verbose=10)
gs.fit(X_train,y_train)
print(gs)
#最高分
print(gs.best_score_)
#最好的超参数
print(gs.best_params_)
#最好的模型
print(gs.best_estimator_)

#使用训练好的模型在测试集上验证
estimator=gs.best_estimator_
y_hat=estimator.predict(X_test)
print(classification_report(y_test,y_hat))

结果

Fitting 5 folds for each of 20 candidates, totalling 100 fits
[Parallel(n_jobs=-1)]: Done   5 tasks      | elapsed:    1.7s
[Parallel(n_jobs=-1)]: Done  10 tasks      | elapsed:    1.7s
[Parallel(n_jobs=-1)]: Done  17 tasks      | elapsed:    1.7s
[Parallel(n_jobs=-1)]: Batch computation too fast (0.1875s.) Setting batch_size=2.
[Parallel(n_jobs=-1)]: Done  24 tasks      | elapsed:    1.7s
[Parallel(n_jobs=-1)]: Batch computation too fast (0.0189s.) Setting batch_size=42.
[Parallel(n_jobs=-1)]: Done  38 out of 100 | elapsed:    1.7s remaining:    2.9s
[Parallel(n_jobs=-1)]: Done 100 out of 100 | elapsed:    1.9s finished
GridSearchCV(cv=5, error_score='raise',
       estimator=KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
           metric_params=None, n_jobs=1, n_neighbors=5, p=2,
           weights='uniform'),
       fit_params=None, iid=True, n_jobs=-1,
       param_grid={'n_neighbors': range(1, 11), 'weights': ['uniform', 'distance']},
       pre_dispatch='2*n_jobs', refit=True, return_train_score='warn',
       scoring='accuracy', verbose=10)
0.8035714285714286
{'n_neighbors': 7, 'weights': 'uniform'}
KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
           metric_params=None, n_jobs=1, n_neighbors=7, p=2,
           weights='uniform')
             precision    recall  f1-score   support

          0       1.00      1.00      1.00        13
          1       0.80      0.50      0.62        16
          2       0.47      0.78      0.58         9

avg / total       0.79      0.74      0.74        38

4、使用KNN进行回归预测

4.1、建模预测

对比KNN回归的r2值和线性回归预测的r2值:
可以看出线性回归的结果更好

  • 原因:线性回归对于特征的量纲(数量级),其模型(w1x1+w2x2+b)中的权重w1和w2可以在训练时自动调整,故特征量纲对线性回归预测没有影响
  • 对于KNN回归,量纲较大的占据主导地位,故特征的量纲对模型的影响较大
from sklearn.datasets import load_boston
from sklearn.neighbors import KNeighborsRegressor
from sklearn.linear_model import LinearRegression
#return_X_y : 布尔值,默认为False,如果是True的话,返回(data, target)代替Bunch对象.
X,y=load_boston(return_X_y=True)
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.25,random_state=0)
knn=KNeighborsRegressor(n_neighbors=3,weights='uniform')
knn.fit(X_train,y_train)
y_hat=knn.predict(X_test)
print('knn的score方法预测得到的r2评估:',knn.score(X_test,y_test))
from sklearn.metrics import r2_score
print('sklearn.metrics中的的 r2_score方法预测得到的r2评估:',r2_score(y_test,y_hat))

#线性
lr=LinearRegression()
lr.fit(X_train,y_train)
y_hat=lr.predict(X_test)
print('lr的score方法预测得到的r2评估:',lr.score(X_test,y_test))
print('sklearn.metrics中的的 r2_score方法预测得到的r2评估:',r2_score(y_test,y_hat))

结果

knn的score方法预测得到的r2评估: 0.5123918703499843
sklearn.metrics中的的 r2_score方法预测得到的r2评估: 0.5123918703499843
lr的score方法预测得到的r2评估: 0.6353620786674621
sklearn.metrics中的的 r2_score方法预测得到的r2评估: 0.6353620786674621

4.2、数据标准化※※※

进行建模前,先将数据集当中的特征转换成相同量纲,消除量纲对算法的影响,该过程即为数据标准化

即使量纲相同,进行数据标准化也不会有负面影响所以进行建模之前,可以都进行数据标准化

  • 均值标准差标准化StandardScaler
  • 最小最大值标准化MinMaxScaler
from sklearn.preprocessing import StandardScaler,MinMaxScaler
scaler=[StandardScaler(),MinMaxScaler()]
desc=['均值标准差标准化','最小最大值标准化']
#for  in zip,将2个列表对应为一个列表
for s,d in zip(scaler,desc):
    #fit_transform指先对其进行StandardScaler()训练,然后在转化
    X_train_scale=s.fit_transform(X_train)
    #transform直接转化
    X_test_scale=s.transform(X_test)
    knn=KNeighborsRegressor(n_neighbors=3,weights='uniform')
    knn.fit(X_train_scale,y_train)
    y_hat=knn.predict(X_test_scale)
    print(d,knn.score(X_test_scale,y_test))

结果

均值标准差标准化 0.6248800677762865
最小最大值标准化 0.6177749492293981

通过数据标准化后knn模型预测的r2评估结果要好于标准化前

4.3、流水线:将数据预处理与模型训练写在一起

例如上节1、对训练集数据X进行数据标准化
2、对测试集X进行数据标准化
3、使用标准化后的训练集进行模型训练
4、使用标准化后的测试集进行预测
5、使用标准化后的测试集进行评估
那么,就可以把标准化和对knn的操作放在一个流水线

流水线具有最后一个评估器的所有方法。当通过流水线对象调用方法f 时,会执行这样的过程:

  • 如果f是fit方法,则会首先对前n-1个评估器依次调用fit_transform方法,然后在最后一个评估器上调用f(fit)方法
  • 如果f 是其他方法,则会首先对前n-1个评估器依次调用transform方法,然后在最后一个评估器上调用f 方法(如上面求r2的方法)

使用的库
from sklearn.pipeline import Pipeline

#流水线
from sklearn.pipeline import Pipeline
from sklearn.datasets import load_boston
X,y=load_boston(return_X_y=True)
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.25,random_state=0)
steps=[('scaler',StandardScaler()),('knn',KNeighborsRegressor())]
p=Pipeline(steps)
p.set_params(knn__n_neighbors=3,knn__weights='uniform')
p.fit(X_train,y_train)
print(p.score(X_test,y_test))
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页