一、代码实现

'''
     功能:使用鸢尾花卉数据集和 K 折交叉验证,选取最优的 KNN 算法参数 k
'''


# 导包
from sklearn import datasets
import numpy as np
import pandas as pd
from sklearn import model_selection
from sklearn import neighbors
import math
from sklearn import metrics
import seaborn as sns
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False



# 使用 k 折交叉验证,选取最优的参数
def choose_bestK(myData, data_train, label_train):
     K = np.arange(1, math.floor(math.sqrt(myData.shape[0])))
     scores = []
     for k in K:
          knn = neighbors.KNeighborsClassifier(n_neighbors=k)
          scores.append(model_selection.cross_val_score(knn, data_train, label_train, cv=10).mean())

     bestK_ind = np.array(scores).argmax()  # 最优的 k 参数

     # 对不同的 k 值得分可视化
     plt.figure()
     plt.plot(K, scores)
     plt.scatter(K, scores)
     plt.text(K[bestK_ind], scores[bestK_ind], '最佳k值为%d' %int(K[bestK_ind]))
     # plt.show()

     return K, scores, bestK_ind


# 使用最优 k 值进行模型训练及预测,并构建混淆矩阵
def model_train_knn(bestK, x_train, y_train, x_test, y_test):
     knn = neighbors.KNeighborsClassifier(n_neighbors=bestK)
     knn.fit(x_train, y_train)
     y_test_pre = knn.predict(x_test)

     # 构建混淆矩阵
     tmp = []
     for i in range(len(y_test)):
          tmp.append(y_test.values[i][0])
     tmp = np.array(tmp)
     cm = pd.crosstab(y_test_pre, tmp)  # pd.crosstab()的输入数据类型应该是 narray!

     return cm, y_test_pre


# 构造混淆矩阵热度图
def Confusion_matrix_hp(cm):
     # 将混淆矩阵构造成数据框,并加上字段名和行名称,用于行或列的含义说明
     cm = pd.DataFrame(cm)

     # 绘制热力图
     sns.heatmap(cm, annot=True, cmap='GnBu')

     plt.xlabel('Real Label')
     plt.ylabel('Predict Label')
     # plt.show()


# 模型评价和报告输出
def scoreAndReport(y_test, y_test_pre):
     y_test_ndarray = y_test.values  # dataframe 转成 ndarray
     y_test_ndarray = y_test_ndarray.ravel()  # 将 ndarray 拉成一维数组

     accur = metrics.accuracy_score(y_test_ndarray, y_test_pre)
     report = metrics.classification_report(y_test_ndarray, y_test_pre)

     # precision = metrics.precision_score(y_test_ndarray, y_test_pre)  # 该指标多分类不可用
     # recall = metrics.recall_score(y_test_ndarray, y_test_pre)  # 该指标多分类不可用
     # f1_score = metrics.f1_score(y_test_ndarray, y_test_pre)  # 该指标多分类不可用
     # AUC = metrics.auc(y_test_ndarray, y_test_pre)  # 该指标多分类不可用
     # fpr, tpr, thesholds = metrics.roc_curve(y_test_ndarray, y_test_pre)  # 该指标多分类不可用
     # metrics.auc(fpr, tpr)  # 该指标多分类不可用

     return accur, report



if __name__ == '__main__':
     # 导入数据集
     dataset = datasets.load_iris()
     feaName = dataset.feature_names  # 数据集特征名称 >> ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
     tarName = dataset.target_names  # 数据集标签名称 >> ['setosa' 'versicolor' 'virginica']

     myData = pd.DataFrame(data=dataset.data)  # 特征数据
     labels = pd.DataFrame(data=dataset.target)  # 标签

     # 划分训练集和测试集
     data_train, data_test, label_train, label_test = model_selection.train_test_split(myData, labels, test_size=0.2)

     K, scores, bestK_ind = choose_bestK(myData, data_train, label_train)
     bestK = K[bestK_ind]  # 最优参数k

     cm, label_test_pre = model_train_knn(bestK, data_train, label_train, data_test, label_test)

     Confusion_matrix_hp(cm)

     score, report = scoreAndReport(label_test, label_test_pre)
     print(score, '\n', report)

        (参考:Python 第三方库Knn算法) 

运行结果:

python xgb k折交叉验证训练_python xgb k折交叉验证训练

python xgb k折交叉验证训练_机器学习_02

python xgb k折交叉验证训练_python xgb k折交叉验证训练_03

二、知识点

1. numpy 的 argmax 的用法

        argmax 返回的是最大数的索引。argmax 有一个参数 axis,默认为0,表示第几维的最大值。

        (参考:(Python)numpy的argmax用法)

2. list 和 ndarray 的相互转化

        (1)list 转 ndarray:b = np.array(a)

        (2)ndarray 转 list:a = b.tolist()

        (参考:Python:list和ndarray的互相转化)

3. ravel() 的用法

        功能:将数组维度拉成一维数组

a = [[1], [2], [2], [3]]
b = a.ravel()  # 该函数不会修改原始 a 的值,所以需要开辟新内存
print(b)

>> [1, 2, 2, 3]

        metrics.accuracy_score() 的输入需要是 (n_samples, ),否则会报错。

python xgb k折交叉验证训练_机器学习_04

        此时,使用 np.ravel() 函数将数组维度拉成一维,该问题解决。~

python xgb k折交叉验证训练_sklearn_05

        (参考:python中ravel()用法)

4. 二分类的评价指标不可直接用于多分类

        二分类常见的评价指标:准确率accuracy,精确的precision,召回率recall,f1-score,ROC曲线,AUC等。(详见:【20210914】【机器/深度学习】模型评价指标:精确率、召回率、特异性、敏感性、F1-score、ROC曲线、AUC)

        其中只有准确率accuracy 可用于多分类~其他都会报错!常见的多分类评价指标:宏平均 Macro F1,微平均 Micro F1 等。

        (参考:二分类和多分类的性能评价指标及python计算)

        (参考:多分类f1分数_【评价指标】详解F1-score与多分类MacroF1&MicroF1)

        (参考:【评价指标】详解F1-score与多分类F1)

        (参考:target is multiclass but average='binary'. please choose another average setting.)

python xgb k折交叉验证训练_机器学习_06

python xgb k折交叉验证训练_多分类_07

 5. k 折交叉验证及 sklearn 中 cross_val_score 的使用

        交叉验证可以解决:数据集量不够大的问题、参数调优的问题。

        交叉验证主要有三种方式:简单交叉验证(HoldOut检验)、k折交叉验证(k-fold交叉验证)、自助法。

(1)简单交叉验证(HoldOut检验)

        原理:将原始数据随机划分成训练集和验证集两个部分。

python xgb k折交叉验证训练_python xgb k折交叉验证训练_08

        缺点:数据都只被用了一次,没有被充分利用;在验证集上计算出来的最后的评估指标与原始分组有很大关系。

(2)k-fold交叉验证

        原理:将全部样本划分成 k 个大小相等的样本子集;依次遍历这 k 个子集,每次把当前子集作为验证集,其余所有样本作为训练集,进行模型的训练和评估;最终把 k 次评估指标的平均值作为最终的评估指标。

python xgb k折交叉验证训练_算法_09

python xgb k折交叉验证训练_sklearn_10

         (参考:使用sklearn的cross_val_score进行交叉验证)

         (参考:交叉验证以及scikit-learn中的cross_val_score详解)

        (参考:为什么cross_val_score返回几个分数?)