目录
(1)均方误差(MSE, Mean Squared Error)
(2)均方根误差(RMSE, Root Mean Squared Error)
(3)平均绝对误差(MAE, Mean Absolute Error)
3.2.1 K折交叉验证(K-Fold Cross-Validation)
3.2.2 留一交叉验证(Leave-One-Out Cross-Validation,LOO)
3.2.3 分层K折交叉验证(Stratified K-Fold Cross-Validation)
(3)偏差-方差权衡(Bias-Variance Tradeoff)
一、写在前面的话
本篇文章将以scikit-learn学习库使用KNN算法进行分类的介绍与演示,通过对KNN的学习进而引出关于模型的评估与优化的概念,重点介绍交叉验证与网格搜索方法。
机器学习零基础的读者可以先去学习一下上一篇文章“新手入门”:
二、KNN(K-Nearest Neighbor)
2.1 KNN算法介绍
2.1.1 概念介绍
- KNN(K-Nearest Neighbor)(也称为K-近邻算法)是一种简单的监督学习算法,主要用于分类和回归问题。
- 其基于一个非常直观的原则:对于一个新的样本,KNN算法通过找到距离它最近的K个已知样本,根据这些K个样本的标签(在分类问题中是类别,在回归问题中是数值)来进行预测。
2.1.2 算法特点
- KNN算法没有真正的训练过程(距离计算的预处理不算入真正训练),其只是保存所有训练样本及其标签。
2.1.3 API 讲解
class sklearn.neighbors.KNeighborsClassifier(n_neighbors=5, algorithm='auto')
参数:
(1)n_neighbors:
int, default=5, 默认情况下用于kneighbors查询的近邻数,就是K
(2)algorithm:
{‘auto’, ‘ball_tree’, ‘kd_tree’, ‘brute’}, default=’auto’。找到近邻的方式,注意不是计算距离的方式,与机器学习算法没有什么关系,开发中请使用默认值'auto'
方法:
(1) fit(x, y)
使用X作为训练数据和y作为目标数据
(2) predict(X) 预测提供的数据,得到预测数据
2.2 样本距离计算
KNN算法依赖于距离度量进行相似度判断。根据选择的距离计算方式,KNN的预测结果将会有所不同。一般来说,欧几里得距离常用于连续型数据的分类和回归问题,而对于文本数据,可能会使用余弦相似度来判断相似度。
2.2.1 距离的类型
(1)欧几里得距离(Euclidean Distance)
最常见的距离度量方法,适用于连续型变量
- 其中,x = (x1,x2,…,xn) 和 y = (y1,y2,…,yn) 分别是两个样本的特征向量,n是特征的维数。
(2)曼哈顿距离(Manhattan Distance)
曼哈顿距离也叫做城市街区距离,表示两点在坐标轴上的绝对距离之和。
(3)切比雪夫距离(Chebyshev Distance)
切比雪夫距离是两点在任一坐标轴上的最大距离。
(4)余弦相似度(Cosine Similarity)
用于衡量两个向量的夹角,适用于文本分类等场景,余弦相似度越大表示两个样本越相似。
两个向量越接近,它们之间的夹角越小,余弦值越接近 1,表示它们的相似度越高。
- 其中x * y为两个向量的点积,∥x∥2 和 ∥y∥2 分别是两个向量的 L2 范数。
- L1范数:各元素绝对值之和,用于稀疏表示。
- L2范数:各个元素的平方和的平方根,常用于度量向量的“大小”。
(5)汉明距离(Hamming Distance)
汉明距离用于衡量两个等长字符串之间的不同位置的个数。
- 例如,对于二进制字符串 x = 10101 和 y = 10011,它们的汉明距离为2。
2.2.2 举例讲解计算过程
假设我们根据X1和X2特征可以预测出标签Label,即苹果或是橘子。
现在我们有一个待分类的点 X =(4, 4),要预测它是苹果还是橘子。
X1 | X2 | Label |
---|---|---|
1 | 1 | 苹果 |
2 | 1 | 苹果 |
3 | 2 | 苹果 |
6 | 5 | 橘子 |
7 | 5 | 橘子 |
8 | 6 | 橘子 |
(1)计算欧几里得距离
(2)选取K个邻居
超参数设置,这里我们选择 K = 3,距离最小的三个点是:(3, 2), (6, 5), (7, 5),它们的标签分别是:苹果、橘子、橘子。
(3)投票预测
根据K个最近邻的标签(苹果、橘子、橘子),投票结果是橘子。
2.3 算法的缺陷
(1)计算复杂度高
KNN在测试阶段需要计算所有训练样本与测试样本之间的距离,因此当训练数据集非常大时,KNN的预测速度会非常慢。
(2)内存开销大
由于KNN需要保存所有训练数据来进行预测,它的内存消耗也相对较大。
(3)对噪声敏感
KNN对噪声数据非常敏感,尤其是在K值较小的时候,噪声点可能会对最终的分类结果产生很大的影响。
(4)维度灾难
当数据集的特征维度过高时,样本间的距离趋于相似,KNN算法会变得不那么有效。这是因为高维空间的“稀疏性”使得所有样本的距离差异变得不明显,导致分类效果下降。
(5)选择K值困难
选择合适的K值对于KNN算法的性能至关重要。若K值过小,模型容易过拟合;若K值过大,可能会出现欠拟合。
三、模型的评估
模型评估是机器学习过程中的一个重要环节,目的是衡量模型的性能和预测准确性,并通过不同的评估指标来比较和选择最佳模型。评估的目的是评估模型在未见数据上的表现,确保其不仅仅在训练集上有良好的效果,而是在实际应用中也能稳定表现。
3.1 评估指标
3.1.1 对于分类
(1)准确率(Accuracy)
最直观的评估指标,指的是模型正确预测的样本占总样本的比例
(2)精确度(Precision)
衡量正类预测准确度,定义为正类预测中实际为正的比例。
(3)召回率(Recall)
衡量模型识别正类的能力,定义为所有实际为正类样本中被正确预测为正的比例。
(4)F1-score
精确度和召回率的调和平均值,兼顾了二者的表现,特别适用于类别不平衡的情况。
参数解析:
- TP(True Positives)真阳性:指的是模型正确地将正类样本预测为正类的数量
- FP(False Positives)假阳性:指的是模型错误地将负类样本预测为正类的数量
- FN(False Negatives)假阴性:指的是模型错误地将正类样本预测为负类的数量
3.1.2 对于回归
(1)均方误差(MSE, Mean Squared Error)
衡量预测值与真实值之间差异的平方平均值,越小表示模型越好。
(2)均方根误差(RMSE, Root Mean Squared Error)
MSE的平方根,具有与原数据相同的单位,便于理解。
(3)平均绝对误差(MAE, Mean Absolute Error)
计算预测值与实际值之间的绝对差的平均值,越小越好。
3.2 交叉验证
交叉验证(Cross-Validation,简称CV),主要目的是为了更稳健地评估模型的性能,避免模型在某一特定训练集上的过拟合或欠拟合,从而提高模型的泛化能力。现在将其放在评估这里来讲解。
3.2.1 K折交叉验证(K-Fold Cross-Validation)
(1)介绍
最常用的交叉验证方法,其基本思想是将数据集分成K个互不重叠的子集(折叠),然后进行K次训练和验证。每次训练时,选择一个子集作为验证集,其余K-1个子集作为训练集。
(2)步骤讲解
- 将数据集随机分成K个大小相同的子集。
- 选择其中一个子集作为验证集,剩余的K-1个子集作为训练集,训练模型并评估在验证集上的表现。
- 重复步骤2,直到每个子集都做过一次验证集。
- 最终的评估结果是所有K次验证结果的平均值。
(3)举例演示
假设有一个数据集,随机划分成5个子集,用5折交叉验证来评估一个分类模型的性能:
第1轮:用子集1、2、3、4作为训练集,用子集5作为验证集,训练模型并评估其性能。
第2轮:用子集1、2、3、5作为训练集,用子集4作为验证集,训练模型并评估其性能。
第3轮:用子集1、2、4、5作为训练集,用子集3作为验证集,训练模型并评估其性能。
第4轮:用子集1、3、4、5作为训练集,用子集2作为验证集,训练模型并评估其性能。
第5轮:用子集2、3、4、5作为训练集,用子集1作为验证集,训练模型并评估其性能。
对于每一轮的评估,我们可以得到一个评估指标(如准确率、精确度、召回率等),最后计算5轮评估结果的平均值,作为模型的最终评估结果。
(4)优缺点
优点:
- 更高的可靠性:相比单一的训练/测试划分,K折交叉验证能更稳定地评估模型性能。
- 每个样本都有机会成为验证集:每个数据点都可以参与训练和测试,提高了评估结果的泛化能力。
缺点:
- 计算开销大:K折交叉验证需要进行K次训练和验证,如果数据集非常大,计算量和时间开销也会增加。
3.2.2 留一交叉验证(Leave-One-Out Cross-Validation,LOO)
(1)介绍
留一交叉验证是K折交叉验证的极端情况,其中K等于数据集的大小(即每次训练时,只用一个样本作为验证集,其余的样本用来训练模型)。这意味着对于数据集中的每一个样本,都需要训练和验证一次模型。
(2)优缺点
优点:每个样本都能单独作为验证集,评估结果非常可靠。
缺点:计算成本高:对于非常大的数据集,LOO需要进行大量的训练和验证,计算量巨大。
3.2.3 分层K折交叉验证(Stratified K-Fold Cross-Validation)
(1)介绍
在K折交叉验证中,如果数据集的标签分布不均衡,某些类别可能在某些折叠中没有足够的样本,导致模型评估不准确。分层K折交叉验证就是在进行数据集划分时,保持每个子集中的类别分布尽可能和原始数据集相似。即每个折叠中各类别样本的比例与整个数据集中的比例一致。
(2)分析
- K-Fold交叉验证技术中,整个数据集被划分为K个大小相同的部分。每个分区被称为 一个”Fold”。所以我们有K个部分,我们称之为K-Fold。一个Fold被用作验证集,其余的K-1个Fold被用作训练集。
- 该技术重复K次,直到每个Fold都被用作验证集,其余的作为训练集。
- 模型的最终准确度是通过取k个模型验证数据的平均准确度来计算的。
3.2.4 随机交叉验证(Shuffle Split)
(1)介绍
随机交叉验证是一种简单的交叉验证方法。它随机地将数据集分成训练集和验证集,并在多次重复中进行评估。每次划分训练集和验证集时,都是随机的,因此每次划分的验证集和训练集都不同。
(2)优缺点
优点:计算量相对较小,且可以任意选择训练集和验证集的比例。
缺点:数据划分可能不稳定,尤其是在类别不平衡时,可能会造成某些类别的数据在验证集中没有出现。
四、模型的优化
主要目标是通过调整模型的超参数、改进模型结构或处理数据的方式,来提高模型的预测精度和泛化能力。
4.1 优化方法
这里先简单列一下优化模型的常见方法:
(1)超参数调优
常见方法:
网格搜索(Grid Search):对所有可能的超参数组合进行穷举式搜索,找到最优的超参数组合。
随机搜索(Random Search):从所有可能的超参数中随机采样一部分进行测试。
贝叶斯优化(Bayesian Optimization):利用贝叶斯推断的思想,通过先前的尝试结果预测最有可能的最优超参数。
遗传算法(Genetic Algorithm):模拟自然选择的过程,用于优化超参数。
(2)集成学习(Ensemble Learning)
通过将多个模型的预测结果结合起来,来提升模型的整体性能。
常见方法有:
Bagging(如随机森林)
Boosting(如XGBoost、LightGBM、CatBoost)
Stacking:将不同模型的预测作为输入,使用另一种模型进行预测。
(3)偏差-方差权衡(Bias-Variance Tradeoff)
通过调整模型复杂度,找到偏差和方差之间的平衡,避免过拟合或欠拟合。
(4)正则化技术
L1 正则化(Lasso):通过加入L1惩罚项,强迫某些特征的权重变为零,从而起到特征选择的作用。
L2 正则化(Ridge):通过加入L2惩罚项,减小权重的大小,避免某些特征过度影响模型。
Dropout:常用于深度学习中,在训练过程中随机丢弃部分神经元,减少过拟合。
4.2 超参数调优
4.2.1 概念介绍
超参数调优是机器学习中的一个关键步骤,它通过寻找最优的超参数来提高模型的性能。超参数是指那些在训练过程中不能通过学习算法自动获得的参数,它们通常需要由人工设定,比如决策树的最大深度、SVM的核函数类型、神经网络的学习率等。其目标是找到一组最优的超参数,使得模型在给定的任务和数据集上表现最好。
4.2.2 方法分类
(1)手动调优:基于经验和直觉选择超参数。
(2)网格搜索(Grid Search):系统地遍历超参数空间,最常用的一种方法。
(3)随机搜索(Random Search):在超参数空间中随机选择参数组合进行尝试
(4)贝叶斯优化(Bayesian Optimization):基于贝叶斯推理模型,逐步调整超参数。
4.2.3 网格搜索法介绍
网格搜索是一种暴力穷举法,它通过指定一组超参数的候选值,在这些候选值中进行遍历,测试每一组超参数组合,选出最优组合。
(1)方法步骤
定义超参数空间:为每个超参数选择一个范围或集合,通常是多个可能的值。
创建所有可能的超参数组合:将每个超参数的可能值组合成一个“网格”。如果有多个超参数,每个超参数的值都会与其它超参数的值组合。
模型训练与评估:对每一组超参数组合,都训练一个模型,并通过交叉验证(或其他评估方法)评估模型的性能。
选择最优超参数组合:根据模型的性能指标(如准确率、F1分数等)选择最优的超参数组合。
(2)优缺点分析
1、优点:
- 简单直观:易于实现,理解和应用。
- 确保找到最优解:如果给定的参数空间足够全面,可以确保找到最优超参数。
2、缺点:
- 计算开销大:随着超参数数量和每个超参数的取值范围增加,网格搜索的计算量呈指数增长。例如,如果有3个超参数,每个有3个候选值,那么需要尝试27种组合。
- 可能错过最佳组合:如果超参数空间过于粗糙,可能错过最佳的超参数组合。
(3)代码案例
使用KNN算法对scikit-learn的鸢尾花数据集进行分类,使用网格搜索和交叉验证进行优化。
PS:网格搜索通常会与交叉验证一起使用,尤其是在数据较少的情况下。交叉验证通过将数据集分成多个子集,并进行多次训练和评估,能够避免过拟合问题,提供更可靠的性能评估。
# 用KNN算法对鸢尾花进行分类,添加网格搜索和交叉验证
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():
# 1)获取数据
iris = load_iris()
# 2)划分数据集
x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=22)
# 3)特征工程:标准化
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)
# 4)KNN算法预估器, 这里就不传参数n_neighbors了,交给GridSearchCV来传递
estimator = KNeighborsClassifier()
# 加入网格搜索与交叉验证, GridSearchCV会让k分别等于1,2,5,7,9,11进行网格搜索偿试。cv=10表示进行10次交叉验证
estimator = GridSearchCV(estimator, param_grid={"n_neighbors": [1, 3, 5, 7, 9, 11]}, 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) #0.9736842105263158
# 最佳参数:best_params_
print("最佳参数:\n", estimator.best_params_) #{'n_neighbors': 3}, 说明k=3时最好
# 最佳结果:best_score_
print("在训练集中的准确率:\n", estimator.best_score_) #0.9553030303030303
# 最佳估计器:best_estimator_
print("最佳估计器:\n", estimator.best_estimator_) # KNeighborsClassifier(n_neighbors=3)
# 交叉验证结果:cv_results_
print("交叉验证过程描述:\n", estimator.cv_results_)
#最佳参数组合的索引:最佳k在列表中的下标
print("最佳参数组合的索引:\n",estimator.best_index_)
#通常情况下,直接使用best_params_更为方便
return None
knn_iris_gscv()