一. 什么是K临近算法?
含义
K临近算法(K-Nearest Neighbor algorithm,简称KNN)是一种常用的分类与回归算法。在分类问题中,KNN根据预先确定的K值,在训练数据集中找到与待分类样本最相似的K个样本,并根据它们的分类标签来确定待分类样本的类别。在回归问题中,KNN则根据预先确定的K值,在训练数据集中找到与待预测样本最相似的K个样本,并根据它们的数值来预测待预测样本的值。KNN主要依据样本之间的距离度量进行分类或回归,并假设离待分类或待预测样本更近的样本具有更高的相似度。KNN算法简单且易于实现,常用于模式识别、数据挖掘、推荐系统等领域。(来自百度搜索)
举例
上图中的数据点是分布在一个特征空间中
-
横轴表示肿瘤大小,纵轴表示发现时间
-
恶性肿瘤用蓝色表示,良性肿瘤用红色表示
-
新来了一个病人(下图绿色的点),如何判断新来的病人(即绿色点)是良性肿瘤还是恶性肿瘤?
k-近邻算法的做法如下:
-
取一个值k=3(k值后面介绍,现在可以理解为算法的使用者根据经验取的最优值)
-
在所有的点中找到距离绿色点最近的三个点
让最近的点所属的类别进行投票
最近的三个点都是蓝色的,所以该病人对应的应该也是蓝色,即恶性肿瘤。
本质:如两个样本足够相似,那他们两个大概率属于同一类别
选择K个样本判断相似:如果只看一个已知样本,可能不准确
如果K个样本中大多数属于同一个类别,则被预测的样本就很可能属于对应的类别
如何衡量“相似性”:依靠距离衡量
-
上图中和绿色的点距离最近的点包含两个红色和一个蓝色,此处红色点和蓝色点的数量比为2:1,则绿色点为红色的概率最大,最后判断结果为良性肿瘤。
二. K临近算法的原理:
K近邻算法(K-Nearest Neighbors, KNN)是一种基本的非参数化分类与回归方法。它的原理非常简单而直观,主要的步骤如下:
-
准备数据集:首先,我们要准备一个带有标签的训练数据集,其中每个样本都有一组特征值和对应的标签。这些特征值可以是实数、离散值或者其他类型的数据。
-
计算距离:接下来,对于任意一个待分类或预测的样本,我们需要计算它与训练数据集中每个样本的距离。常见的距离度量方法有欧氏距离、曼哈顿距离、闵可夫斯基距离等
两个样本的距离可以通过如下公式计算,又叫欧式距离
比如说:A(x1,y1) B(x2,y2),距离为:立体中两点之间的距离: 任意维度下的欧拉距离:$$\Large \sqrt{(x{1}^{(a)}-x{1}^{(b)})^2+(x{2}^{(a)}-x{2}^{(b)})^2+...+(x{n}^{(a)}-x{n}^{(b)})^2}$$简化后:$$\Large \sqrt{\sum{i=1}^{n}(x{i}^{(a)}-x_{i}^{(b)})^2}$$
-
选择K值:K值是指在计算距离时选择前K个最近邻样本。K的选择对KNN算法的结果影响很大,通常可以通过交叉验证等方法来确定最佳的K值。
-
确定类别:根据选择的K个最近邻样本,通过多数表决的方式确定待分类样本的类别。即,统计K个最近邻样本中各个类别的出现次数,将出现次数最多的类别作为待分类样本的类别。
K近邻算法的优点是简单易懂、易于实现,并且对于大部分数据类型都适用,但是对于大规模数据集和高维数据,计算距离的时间复杂度较高。此外,KNN算法还需要考虑数据归一化的问题,以避免某些特征值对距离计算的影响过大。
三. K-近邻算法的一般流程
(1)收集数据:可以使用任何方法。
(2)准备数据:距离计算所需要的数值,最好是结构化的数据格式。
(3)分析数据:可以使用任何方法。
(4)训练算法:此步骤不适用于k-近邻算法。
(5)测试算法:计算错误率。
(6)使用算法:首先需要输入样本数据和结构化的输出结果,然后运行k-近邻算法
入数据分别属于哪个分类,最后应用对计算出的分类执行后续的处理。
四. 案例
1数据集介绍
lris数据集是常用的分类实验数据集,由Fisher, 1936收集整理。lris也称鸢尾花卉数据集是一类多重变量分析的数据集。关于数据集的具体介绍
实例数量:150(三个类各有50个)属性数量:4(数值型,数值型,帮助预测的属性和类)Attribute Information:
sepallength 萼片长度 (厘米)
sepal width 萼片宽度 (厘米)
petallength 花瓣长度 (厘米)
petal width 花瓣宽度 (厘米)
class:
。 lris-Setosa 山鸢尾
。 lris-Versicolour 变色鸢尾
。lris-Virginica 维吉尼亚尾
2 流程分析
1)获取数据
2)数据处理(这里通过sklearn.iris得到的数据已经是处理好了的)
3)数据集划分
4)特征工程(标准化)
5)KNN预估器流程
6)模型评估
3 代码
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
def knn_iris():
# 1)获取数据
iris = load_iris()
# 2)数据处理(这里通过sklearn.iris得到的数据已经是处理好了的)
# 3)数据集划分
x_train,x_test,y_train,y_test=train_test_split(iris.data, iris.target,random_state=10)
# 4)特征工程(标准化)
transform = StandardScaler() #给标准化用transform接起来
x_train = transform.fit_transform(x_train) #训练集进行了标准化
x_test = transform.transform(x_test)
# 5)KNN预估器流程
knn_estimator = KNeighborsClassifier(n_neighbors=3)
knn_estimator.fit(x_train,y_train) #通过这一步可以得到模型
# 6)模型评估
#方法1 :直接比对真实值和预测值
y_predict = knn_estimator.predict(x_test)
print('y_predict:\n',y_predict)
print('直接比对真实值和预测值:\n',y_predict==y_test)
#方法2 :计算准确率
score=knn_estimator.score(x_test,y_test)
print('准确率为:',score)
return None
if __name__ == '__main__':
knn_iris()
4.结果
模型评估:通过预测测试集的结果,使用predict函数将预测结果存储在y_predict中。输出y_predict的结果,即预测的分类结果。比对预测值和真实值,输出预测值与真实值是否相等的布尔值。计算模型在测试集上的准确率,使用score函数计算得分并输出。
这段代码的结果是通过KNN算法对鸢尾花数据集进行分类,并输出了预测结果、预测值与真实值的比对结果以及模型在测试集上的准确率。
五. 归一化和标准化的计算方法
归一化(Normalization):把所有数据映射到(0,1)之间
计算流程:$$\Large x{scale}=\frac{x-x{min}}{x{max}-x{min}}$$
先计算所有样本的每个特征的最大值和最小值计算出来
用每个样本的特征值减去对应的最小值
x−xmin
再计算最大值和最小值的差值 $$x{max}-x{min}$$
最后将两个结果进行除法操作,得到最终的特征归一化结果
xscale
适用情况:分布有明显边界
举例:学生分数0-100有明显边界,图片像素点的值0-255有明显边界。
缺点:受异常值(outlier)影响较大
观察公式,结果受$$x{max}
和
和
x{min}$$影响严重
标准化(standardization):把所有数据利用均值和标准差进行转换,均值为0,标准差为1
$$\Large x{scale}=\frac{x-x{mean}}{S}$$
利用每个特征值减去特征值均值再除以特征值的标准差得到标准化的结果
适用情况:数据分布没有明显边界
优点:不容易受到极端数据值的影响
六. SKlearn中的超参数搜索与交叉验证
什么是网格搜索(Grid Search)
Sklearn中寻找最佳的超参数的组合的过程称为网格搜索
什么是交叉验证(cross validation)
交叉验证:将拿到的训练数据,分为训练和验证集。以下图为例:
将数据分成10份,其中一份作为验证集(k折交叉验证)
经过10次(组)的测试,每次都更换不同的验证集。即得到10组模型的结果,取平均值作为最终结果。又称10折交叉验证。
案例:使用GridSearchCV对鸢尾花案例进行调优:
from sklearn.model_selection import train_test_split,GridSearchCV
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_iris
# 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()
# 调用fit_transform
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)
# 4、KNN预估器流程
# 4.1 实例化预估器类
estimator = KNeighborsClassifier()
# 4.2 模型选择与调优——网格搜索和交叉验证
# 准备要调的超参数
param_dict = {"n_neighbors": [1, 3, 5],'weights':["uniform","distance"]}
estimator = GridSearchCV(estimator, param_grid=param_dict, cv=3)
# 4.3 fit数据进行训练
estimator.fit(x_train, y_train)
# 5、评估模型效果
# 方法a:比对预测结果和真实值
y_predict = estimator.predict(x_test)
print("比对预测结果和真实值:\n", y_predict == y_test)
# 方法b:直接计算准确率
score = estimator.score(x_test, y_test)
print("直接计算准确率:\n", score)
查看 交叉验证的最终结果:
print("在交叉验证中验证的最好结果:\n", estimator.best_score_)
print("最好的参数模型:\n", estimator.best_params_)
七. 总结
KNN优缺点
-
优点:精度高,对异常值不敏感,无数据输入假定。
-
缺点:计算复杂度高,空间复杂度高。
-
适用数据范围:数据值和标称值。
-
算法的核心思想
-
1.即是给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的K个实例,这K个实例的多数属于某个类,就把该输入实例分类到这个类中。更通俗说一遍算法的过程,来了一个新的输入实例,我们算出该实例与每一个训练点的距离(这里的复杂度为0(n)比较大,所以引出了下文的kd树等结构),然后找到前k个,这k个哪个类别数最多,我们就判断新的输入实例就是哪类!
-
2.与该实例最近邻的k个实例,这个最近邻的定义是通过不同距离函数来定义,我们最常用的是欧式距离。
-
3.为了保证每个特征同等重要性,我们这里对每个特征进行归一化。
-
4.k值的选取,既不能太大,也不能太小,何值为最好,需要实验调整参数确定!
谢谢大家,希望对大家有帮助!欢迎大家指错交流