机器学习(二) ----------K近邻算法(KNN)+特征预处理+交叉验证网格搜索

发布于:2024-05-07 ⋅ 阅读:(20) ⋅ 点赞:(0)

目录

1 核心思想

1.1样本相似性

 1.2欧氏距离(Euclidean Distance)

1.3其他距离

1.3.1 曼哈顿距离(Manhattan Distance)

1.3.2 切比雪夫距离(Chebyshev distance)

1.3.3 闵式距离(也称为闵可夫斯基距离,Minkowski Distance)

2 K值选择

2.1 K值的含义

2.2 K值的影响:

2.3 如何选择K值:

3 KNN解决问题流程

3.1 分类流程

3.2 回归流程

4 KNN算法的API

4.1 分类算法

4.2 回归算法

5 特征预处理(FeaturePreprocessing)(特征缩放)

5.1 归一化(Normalization)(Min-Max缩放)

5.1.1 归一化公式

5.1.2 归一化适用范围

5.1.3 归一化API

5.1.4 代码实现

5.2 标准化(Standardization)(Z-score标准化)

5.2.1 标准化公式

5.2.2 标准化的适用范围(常用)

5.2.3 数据标准化API

5.2.4 代码实现

6 交叉验证网格搜索(超参数选择)

6.1 交叉验证(Cross Validation):

6.2 网格搜索(GridSearch):

6.3 交叉验证网格搜索API

7 鸢尾花案例


1 核心思想


KNN(K-Nearest Neighbors)是一种基本的机器学习分类和回归算法。其核心思想是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。


1.1样本相似性


样本都是属于一个任务数据集的,样本距离越近则越相似


 1.2欧氏距离(Euclidean Distance)

欧氏距离(Euclidean Distance)是最常见的距离度量方式之一,用于在多维空间中计算两点之间的直线距离。


二维:a(x1,y1) b(x2,y2)

{d_{ab}}^{} =\sqrt{\left ( {x_{1}}^{}-x_2 \right )^2 + \left ( y_1 - y_2 \right )^2}

三维:a(x1,y1,z1) b(x2,y2,z2)

{d_{ab}}^{} = \sqrt{\left ( {x_1{}}^{} -x_2 \right)^2 + \left ( y_1 -y_2 \right )^2 + \left ( z_1 -z_2 \right )^2}

多维:a(x11,x12,....,x1n)b(x21,x22,....,x2n)

{d_{ab}}^{} =\sqrt{\sum_{k=1}^{n}\left ( x_{1k} -x_{2k} \right )^2}

在机器学习和数据挖掘中,欧氏距离常用于KNN(K-Nearest Neighbors)等算法中,用于度量样本之间的相似性或距离。然而,需要注意的是,欧氏距离在处理高维数据时可能会受到“维数灾难”的影响,即在高维空间中,两点之间的欧氏距离可能会变得非常接近,导致算法的性能下降。此外,欧氏距离对数据的尺度敏感,因此在应用之前通常需要对数据进行标准化或归一化处理。

1.3其他距离

1.3.1 曼哈顿距离(Manhattan Distance)

曼哈顿距离的名字来源于规划为方型建筑区块的城市(如曼哈顿),其中从一个地点到另一个地点需要沿着街区行走,即只能沿着水平和垂直方向移动,而不能直接穿越建筑物。因此,曼哈顿距离可以理解为从一个点到另一个点在南北方向和东西方向上所走的距离之和。

公式:

a(x11,x12,....,x1n)b(x21,x22,....,x2n)

d_{ab}=\sum_{k=1}^{n}\left | x_{1k} - x_{2k}\right |

与欧氏距离相比,曼哈顿距离不受数据尺度的影响,因此在某些情况下可能更加合适。然而,曼哈顿距离对于数据的旋转和映射不敏感,即当坐标轴发生旋转或映射时,曼哈顿距离可能会发生变化。因此,在选择使用曼哈顿距离还是欧氏距离时,需要根据具体的应用场景和数据特点进行选择。

1.3.2 切比雪夫距离(Chebyshev distance)

切比雪夫距离得名自俄罗斯数学家切比雪夫。在二维空间中,和一点的切比雪夫距离为定值的点会形成一个正方形,而在更高维度的空间中,这些点会形成一个超立方体。

切比雪夫距离特别适用于多维空间中的距离测量,它通过定义最大坐标距离来衡量两点之间的“距离”,这在一些特殊应用中可能很有用,例如在国际象棋中,王从一个位置走到另一个位置需要的步数恰为两个位置之间的切比雪夫距离,因此切比雪夫距离也称为棋盘距离。

公式:

a(x11,x12,....,x1n)b(x21,x22,....,x2n)

d_{ab} = max\left ( \left | x_{1i}-x_{2i} \right | \right )

1.3.3 闵式距离(也称为闵可夫斯基距离,Minkowski Distance)

闵式距离的特点是将各个分量的量纲,即“单位”当作相同看待,没有考虑各个量的分布(如期望、方差等)可能不同。

公式:

a(x11,x12,....,x1n)b(x21,x22,....,x2n)

d_{ab} = \sqrt[p]{\sum_{k=1}^{n}\left | x_{1k}-x_{2k} \right |^p}

2 K值选择

在KNN(K-Nearest Neighbors)算法中,K值的选择是一个重要的步骤,因为它直接影响到模型的性能。

2.1 K值的含义

K值表示在分类或回归时,我们要考虑的最近邻的数量。对于给定的测试点,KNN会找到训练数据集中与该点最近的K个点,然后根据这些点的标签进行投票(分类)或计算平均值(回归)

2.2 K值的影响

K值较小时:模型复杂度较高,对噪声和异常值较敏感,可能导致过拟合。即,只有与测试点非常接近的少数几个点会影响分类或回归的结果。

K值较大时:模型复杂度较低,对噪声和异常值的敏感度降低,但可能导致欠拟合。即,即使与测试点不太接近的点也会对分类或回归的结果产生影响。

2.3 如何选择K值

  • 交叉验证:一种常用的方法是使用交叉验证来选择K值。具体来说,可以将训练数据集分成多个部分,然后对每个可能的K值进行训练和验证,选择使验证误差最小的K值。在交叉验证时,通常建议K值在2到20之间选择,并且最好为奇数,以避免出现平票的情况。
  • 网格搜索:网格搜索(Grid Search)是一种在机器学习中常用的超参数优化方法,其原理是将待搜索的超参数空间划分为网格,然后遍历网格中的每一个点(即每一组超参数组合),通过交叉验证等方法评估每一组超参数组合的性能,并选择性能最优的一组作为最终的超参数设置。
  • 经验法则:在实际应用中,有时候可以根据经验来选择K值。例如,在一些情况下,选择K=3、5或7可能会得到较好的结果。但是,这并不是绝对的,具体还需要根据数据集的特点和需求来确定。
  • 贝叶斯优化:贝叶斯优化是一种高效的优化方法,可以用于在KNN算法中搜索最优的K值。它通过建模目标函数和先验分布,利用贝叶斯定理来更新参数分布,从而找到使目标函数最小化或最大化的最优参数。

3 KNN解决问题流程

3.1 分类流程

1.计算未知样本到每一个训练样本距离

2.将训练样本根据距离大小升序排列

3.取出距离最近的K个样本

4.进行多数表决,统计K个样本中哪个类别的样本个数最多

5.将未知的样本归属到出现次数最多的类别

3.2 回归流程

1.计算未知样本到每一个训练样本距离

2.将训练样本根据距离大小升序排列

3.取出距离最近的K个样本

4.计算这K个样本的目标值的平均值

5.将该平均值作为未知样本预测的值

4 KNN算法的API

4.1 分类算法

sklearn.neighbors.KNeighborsClassifier(n_neighbors=5)

具体实现(此处仅做API距离,实际样本需要规模化):

# 导包
from sklearn.neighbors import KNeighborsClassifier

# 实例化模型,设置K为3
Knn = KNeighborsClassifier(n_neighbors=3)

# 准备数据X为特征向量空间,y为标签值
X = [[0, 1], [5, 1], [9, 8], [4, 8], [9, 7], [3, 8], [7, 66], [4, 8], [3, 2], [7, 9]]
y = [1, 0, 1, 0, 1, 0, 1, 0, 0, 1]

# 训练模型
Knn.fit(X, y)

# 预测
print(Knn.predict([[9, 9]]))

4.2 回归算法

sklearn.neighbors.KNeighborsRegressor(n_neighbors=5)

具体实现(此处仅做API距离,实际样本需要规模化):

from sklearn.neighbors import  KNeighborsRegressor

# 实例化模型
Knn = KNeighborsRegressor(n_neighbors=3)
# 准备数据
X = [[0, 1], [5, 1], [9, 8], [4, 8], [9, 7], [3, 8], [7, 66], [4, 8], [3, 2], [7, 9]]
y = [1, 2, 34, 2, 6, 56, 8, 9, 0, 9]

# 训练模型
Knn.fit(X, y)

# 预测
print(Knn.predict([[9, 9], [0, 7]]))

5 特征预处理(FeaturePreprocessing)(特征缩放

将不同尺度的特征缩放到相似的范围,以避免某些特征对模型的影响过大。常见的特征缩放方法有标准化(Z-score标准化)和归一化(Min-Max缩放)。

5.1 归一化(Normalization)(Min-Max缩放)

归一化(Normalization)是数据预处理中常用的一种技术,它可以将数据的尺度调整到某个特定的范围[mi,ma],通常是[0, 1]或[-1, 1]。归一化的主要目的是消除数据之间的尺度差异,使得不同特征之间具有相似的权重,从而提高模型的稳定性和准确性。

5.1.1 归一化公式

{x}' = \frac{x-min}{max-min}    min为特征的最小值,max为特征的最大值

{x}'' = {x}'\cdot \left ( mx-mi \right ) + mi      mx为特定范围的上界,mi为特定范围的下界

5.1.2 归一化适用范围

如果出现异常点,影响了最大值和最小值,那么结果显然会发生改变

应用场景:

最大值好最小值非常容易受异常点影响,只适合传统精确小数据场景,如图像处理时的像素值

5.1.3 归一化API

# 实例化
transfor = sklearn.preprocessing.MinMaxScaler(feature_range = (0,1))
# 归一化
transfor.transform(X)

5.1.4 代码实现

# 归一化
# 导包
from sklearn.preprocessing import MinMaxScaler

# 准备数据
data = [[90, 60, 1], [60, 257, 3], [20, 1, 6]]

# 实例化
transform = MinMaxScaler()

# 归一化
print(transform.fit_transform(data))

5.2 标准化(Standardization)(Z-score标准化)

标准化(Standardization)是一种常见的数据预处理技术,其主要目的是通过调整数据的尺度,使其具有零均值和单位方差,从而使数据更符合标准正态分布。

5.2.1 标准化公式

{x}' = \frac{x - mean}{\sigma }      mean为特征的平均值 σ为特征的标准差

5.2.2 标准化的适用范围(常用)

如果出现异常点,由于少量的异常点对于平均值和方差影响不大,所以适合现代嘈杂大数据场景

5.2.3 数据标准化API

# 实例化
transfor = sklearn.preprocessing.Standard()
# 标准化
transfor.fit_transform(X)

5.2.4 代码实现

# 标准化
# 导包
from sklearn.preprocessing import StandardScaler

# 准备数据
data = [[90, 60, 1], [60, 257, 3], [20, 1, 6]]

# 实例化
transform = StandardScaler()

# 标准化
print(transform.fit_transform(data))
print(transform.var_)
print(transform.mean_)

6 交叉验证网格搜索(超参数选择)

6.1 交叉验证(Cross Validation):

交叉验证是一种评估机器学习模型性能的统计学方法。其主要目的是通过对训练集进行多次划分,得到不同的训练集和验证集组合,然后分别在这些组合上训练模型并验证其性能,从而得到对模型性能的更加准确和可靠的评估。

K折交叉验证(K-fold Cross Validation):将原始数据分为K份,然后每次选择K-1份作为训练集,剩下的1份作为验证集。这样重复K次,每次选择不同的验证集。最后取K次验证结果的平均值作为最终评估结果。这种方法可以有效减少随机性对评估结果的影响。

6.1.1 交叉验证步骤

        1.将数据集换分为cv=k份

        2.第一次:把第一份数据做验证集,其余数据作训练

        3.第二次:把第二份数据做验证集,其余数据做训练

        4.....以此类推,总共训练k次,评估k次

        5.使用训练集+验证集多次评估模型,取平均值做交叉验证的模型得分

        6.若超参数组合(n1,n2,...)模型得分最好,再使用全部训练集(训练集+验证集)对超参数组合(n1,n2,...)模型再训练(此步骤在交叉验证网格搜索API里已经执行完,不必重新执行)

        7.在使用测试集对该模型进行评估

6.2 网格搜索(GridSearch):

网格搜索是一种用于优化机器学习模型超参数的搜索方法。在机器学习中,许多模型的性能会受到一些参数的影响,这些参数称为超参数(Hyperparameters)。手动调整这些超参数的过程通常很繁琐,而且很难找到最优的参数组合。网格搜索通过预设一组超参数组合,然后对每个组合进行交叉验证评估,最后选择性能最好的参数组合作为最优参数组合。这种方法可以大大简化超参数的调整过程,并且可以找到相对较好的参数组合。

在网格搜索中,通常会使用估计器(Estimator)对象来表示模型,并使用param_grid参数来指定要搜索的超参数组合范围。然后,通过调用fit()方法输入训练数据,并使用score()方法获取每个参数组合的交叉验证结果。最后,根据这些结果选择最优的参数组合,并使用best_params_、best_score_等属性获取最优参数和最优结果。

6.3 交叉验证网格搜索API

# 实例化
estimator = sklearn.model_selection.GridSearchCV(estimater,param_grid=None,cv=None)

# 交叉验证
estimator.fit(x_trian,y_train)

参数解释:

estimator:估计器对象(实例化模型)

param_grid:估计器参数(dict){‘n_neighbors’:[5,7,9,11]}

cv:指定几折交叉验证(将测试集分成几部分进行交叉验证)

结果分析:

estimator.best_score_    在交叉验证中验证的最好结果

estimator.beat_estimator_  最好的参数模型

estimator.beat_params_  最好的超参数组合

estimator.cv_results_  交叉验证结果

7 鸢尾花案例

# 1.导包
from sklearn.datasets import load_iris
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.neighbors import KNeighborsClassifier

# 2.加载数据
data_iris = load_iris()
# 3.数据集划分
x_train, x_test, y_train, y_test = train_test_split(data_iris.data, data_iris.target, train_size=0.8, random_state=17)

# 4.特征预处理-标准化
transfor = StandardScaler()
x_train = transfor.fit_transform(x_train)
x_test = transfor.transform(x_test)
# 5.模型实例化
knn = KNeighborsClassifier()

# 6.网格搜索交叉验证
estimater = GridSearchCV(estimator=knn, param_grid={'n_neighbors': [1, 3, 5, 7, 9]}, cv=6)
estimater.fit(x_train, y_train)
print(estimater.best_estimator_)
print(estimater.best_index_)
print(estimater.best_params_)
print(estimater.best_score_)
print(estimater.cv_results_)

# 7.评估

print(estimater.score(x_test, y_test))

# 8.预测

pre = [[1, 1, 1, 1], [2, 3, 2, 2]]
pre = transfor.transform(pre)
print(estimater.predict(pre))

KNN算法简单直观,易于理解和实现,并且不需要进行模型训练(即没有显式的训练过程)。然而,KNN算法的计算复杂度较高,特别是对于大型数据集,因为需要计算每个新数据点与所有已知数据点之间的距离。此外,KNN算法对数据的标准化和缩放等预处理步骤较为敏感,因为距离度量是基于特征空间中的数值大小。尽管如此,KNN算法仍然是机器学习领域中的一个重要工具,广泛应用于各种实际问题和场景中。