KNN算法代码实现
参数说明
class sklearn.neighbors.KNeighborsClassifier( n_neighbors=5, weights=’uniform’, algorithm=’auto’, leaf_size=30, p=2, metric=’minkowski’, metric_params=None, n_jobs=None, **kwargs)
话不多说,开始上代码
KNN例子代码
导入第三方库
#导入所需要的包 from sklearn.metrics import precision_score from sklearn.model_selection import train_test_split from sklearn.neighbors import KNeighborsClassifier import numpy as np import pandas as pd import matplotlib.pyplot as plt from matplotlib.colors import ListedColormap from sklearn.preprocessing import LabelEncoder from sklearn.metrics import classification_report from sklearn.model_selection import GridSearchCV #网格搜索
初次加载模型和训练(无任何模型参数)
# 加载模型 model = KNeighborsClassifier() # 训练模型 model.fit(X_train,y_train) # 预测值 y_pred = model.predict(X_test) ''' 评估指标 ''' # 求出预测和真实一样的数目 true = np.sum(y_pred == y_test ) print('预测对的结果数目为:', true) print('预测错的的结果数目为:', y_test.shape[0]-true) # 评估指标 from sklearn.metrics import accuracy_score,precision_score,recall_score,f1_score,cohen_kappa_score print('预测数据的准确率为: {:.4}%'.format(accuracy_score(y_test,y_pred)*100)) print('预测数据的精确率为:{:.4}%'.format( precision_score(y_test,y_pred)*100)) print('预测数据的召回率为:{:.4}%'.format( recall_score(y_test,y_pred)*100)) # print("训练数据的F1值为:", f1score_train) print('预测数据的F1值为:', f1_score(y_test,y_pred)) print('预测数据的Cohen’s Kappa系数为:', cohen_kappa_score(y_test,y_pred)) # 打印分类报告 print('预测数据的分类报告为:','\n', classification_report(y_test,y_pred))
效果一般般,下面进行一个初次的重要参数,寻找
寻找最佳的邻居数
training_accuracy = [] test_accuracy = [] # n_neighbors取值从1到10 neighbors_settings = range(1, 11) for n_neighbors in neighbors_settings: # 构建模型 clf = KNeighborsClassifier(n_neighbors=n_neighbors) clf.fit(X_train, y_train) # 记录训练集精度 training_accuracy.append(clf.score(X_train, y_train)) # 记录泛化精度 test_accuracy.append(clf.score(X_test, y_test)) plt.plot(neighbors_settings, training_accuracy, label="training accuracy") plt.plot(neighbors_settings, test_accuracy, label="test accuracy") plt.ylabel("Accuracy") plt.xlabel("n_neighbors") plt.legend()
通过可视化分析得知,在n_neighbors取到:4,7,8,效果还可以,但是推荐使用5,因为综合训练集和测试集,还是不错的
参数调优
这里提前使用一个网格搜索的知识,后面更新完所有的模型,将会详细的用一篇文章来讲解模型如何调优,其中就有网格搜索
这里根据已有的参数进行迭代,最后返回最佳的参数
#超参数配置 param_knn = { 'n_neighbors': list(range(3,15,2)), 'algorithm':['auto', 'ball_tree', 'kd_tree', 'brute'], 'metric':['euclidean','manhattan','chebyshev','minkowski'], 'p':list(range(1,6)), 'weights':['distance','uniform'] } #KNN的超参数 gsearch_knn = GridSearchCV( model , param_grid = param_knn, cv=10 ) gsearch_knn.fit( X_train, y_train ) gsearch_knn.best_params_ gsearch_knn.best_score_ best_knn=gsearch_knn.best_estimator_ #训练模型+预测数据 y_pred = best_knn.predict(X_test)
第二次训练和评估
''' 评估指标 ''' # 求出预测和真实一样的数目 true = np.sum(y_pred == y_test ) print('预测对的结果数目为:', true) print('预测错的的结果数目为:', y_test.shape[0]-true) # 评估指标 from sklearn.metrics import accuracy_score,precision_score,recall_score,f1_score,cohen_kappa_score print('预测数据的准确率为: {:.4}%'.format(accuracy_score(y_test,y_pred)*100)) print('预测数据的精确率为:{:.4}%'.format( precision_score(y_test,y_pred)*100)) print('预测数据的召回率为:{:.4}%'.format( recall_score(y_test,y_pred)*100)) # print("训练数据的F1值为:", f1score_train) print('预测数据的F1值为:', f1_score(y_test,y_pred)) print('预测数据的Cohen’s Kappa系数为:', cohen_kappa_score(y_test,y_pred)) # 打印分类报告 print('预测数据的分类报告为:','\n', classification_report(y_test,y_pred))
发现效果明显的有所提升!
最优参数:
然后将这些最佳参数添加到模型,将一些自定义的模型参数也添加进去,看看效果如何:
# 加载模型 model = KNeighborsClassifier(n_neighbors=7,algorithm='ball_tree',metric='manhattan',p=1,weights='distance') # 训练模型 model.fit(X_train,y_train) # 预测值 y_pred = model.predict(X_test) ''' 评估指标 ''' # 求出预测和真实一样的数目 true = np.sum(y_pred == y_test ) print('预测对的结果数目为:', true) print('预测错的的结果数目为:', y_test.shape[0]-true) # 评估指标 from sklearn.metrics import accuracy_score,precision_score,recall_score,f1_score,cohen_kappa_score print('预测数据的准确率为: {:.4}%'.format(accuracy_score(y_test,y_pred)*100)) print('预测数据的精确率为:{:.4}%'.format( precision_score(y_test,y_pred)*100)) print('预测数据的召回率为:{:.4}%'.format( recall_score(y_test,y_pred)*100)) # print("训练数据的F1值为:", f1score_train) print('预测数据的F1值为:', f1_score(y_test,y_pred)) print('预测数据的Cohen’s Kappa系数为:', cohen_kappa_score(y_test,y_pred)) # 打印分类报告 print('预测数据的分类报告为:','\n', classification_report(y_test,y_pred))
效果非常棒!
ROC曲线和AUC
from sklearn.metrics import precision_recall_curve from sklearn import metrics # 预测正例的概率 y_pred_prob=model.predict_proba(X_test)[:,1] # y_pred_prob ,返回两列,第一列代表类别0,第二列代表类别1的概率 #https://blog.csdn.net/dream6104/article/details/89218239 fpr, tpr, thresholds = metrics.roc_curve(y_test,y_pred_prob, pos_label=2) #pos_label,代表真阳性标签,就是说是分类里面的好的标签,这个要看你的特征目标标签是0,1,还是1,2 roc_auc = metrics.auc(fpr, tpr) #auc为Roc曲线下的面积 # print(roc_auc) plt.figure(figsize=(8,6)) plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--') plt.plot(fpr, tpr, 'r',label='AUC = %0.2f'% roc_auc) plt.legend(loc='lower right') # plt.plot([0, 1], [0, 1], 'r--') plt.xlim([0, 1.1]) plt.ylim([0, 1.1]) plt.xlabel('False Positive Rate') #横坐标是fpr plt.ylabel('True Positive Rate') #纵坐标是tpr plt.title('Receiver operating characteristic example') plt.show()
这个时候,发现模型的效果已经可以了,自我感觉还是不错的,但是在基于上一篇文章,贝叶斯模型,我们使用了特征筛选的方法,来提高模型的效果,这里是不是也可以了。
我通过了一些树模型进行筛选出最佳的14个特征,发现效果并没有全部放入模型的效果好
筛选出最佳的特征如上
发现效果没有上面那一个好,这是为什么呢,可能这里和KNN的算法原理有关,这里特征通过专家的验证,并不是毫无相关的特征,所以KNN的联合特征算法在这里得到了验证,一般过特征的选取来提高模型的效果是基于不同的模型