KNN算法:K-Nearest Neighbor,K近邻算法,即K个最近的邻居(近朱者赤近墨者黑)
KNN即可用于分类,也可用于回归
超参数:人为指定,超参数不同对模型效果影响很大
极端情况,使用整个样本数量作为K值,那么无论预测值在哪,结果都一样
scikit-learn中,使用闵可夫斯基距离
当p=2时,即为欧几里得距离
1、确定超参数
2、从训练集中选择离待预测样本A最近的K个样本
3、根据K个样本预测A
注意:当类别不同距离待预测样本距离相同时,sklearn根据训练集中出现的顺序选择,对于算法的预测结果,不存在随机,相同的输入一定得到相同的输出
需要的库
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
K值越小,模型敏感度越强(稳定性越弱),模型越复杂,越容易过拟合
K值越大,模型敏感度越弱(稳定性越强),模型越简单,越容易欠拟合
需要的库
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
对比KNN回归的r2值和线性回归预测的r2值:
可以看出线性回归的结果更好
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
进行建模前,先将数据集当中的特征转换成相同量纲,消除量纲对算法的影响,该过程即为数据标准化
即使量纲相同,进行数据标准化也不会有负面影响,所以进行建模之前,可以都进行数据标准化
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评估结果要好于标准化前
例如上节1、对训练集数据X进行数据标准化
2、对测试集X进行数据标准化
3、使用标准化后的训练集进行模型训练
4、使用标准化后的测试集进行预测
5、使用标准化后的测试集进行评估
那么,就可以把标准化和对knn的操作放在一个流水线
流水线具有最后一个评估器的所有方法。当通过流水线对象调用方法f 时,会执行这样的过程:
使用的库
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))