KNN分类算法
分类:将一个未知归类的样本归属到某一个已知的类群中。
预测:可以根据数据的规律计算出一个未知的数据。
概念:
简单地说,K-近邻算法采用测量不同特征值之间的距离方法进行分类(k-Nearest Neighbor,KNN)。
工作原理:
设有一个集合,已知集合的数据及其所对应的标签,输入新的无标签数据,将其与已知集合的数据特征进行比较,选出最接近的K个数据特征的标签,出现次数最多的标签即为无标签数据的标签。
例子:
# 加载模块
from sklearn.neighbors import KNeighborsClassifier
import sklearn.datasets as datasets
from sklearn.model_selection import train_test_split
# 加载数据
iris = datasets.load_iris()
# 取得特征
feature = iris.data
# 取得标签
target = iris.target
# 拆分出训练集的特征与标签和测试集的特征与标签
x_train,x_test,y_train,y_test = train_test_split(feature,target,test_size=0.2,random_state=2020)
# 将模型实例化
knn = KNeighborsClassifier(n_neighbors=9)
# 训练模型;特征形状的维度必须为二维
knn.fit(x_train,y_train)
# 打印测试集的实际标签和预测标签
print('真实的分类结果:',y_test)
print('模型分类的结果:',knn.predict(x_test))
真实的分类结果: [2 0 1 1 1 2 2 1 0 0 2 2 0 2 2 0 1 1 2 0 0 2 1 0 2 1 1 1 0 0]
模型分类的结果: [2 0 1 1 1 2 2 1 0 0 2 1 0 2 2 0 1 1 2 0 0 2 2 0 2 1 1 1 0 0]
# 对模型的精度进行打分
knn.score(x_test,y_test)
0.9333333333333333
模型的超参数:
如果算法模型类的参数如果发生数值的变化,直接会影响模型的精度,则该参数就叫做模型的超参数。
学习曲线寻找最优的k值
穷举不同的k值
import numpy as np
ks = [] #保存模型使用过的k值
scores = [] #保存模型对应k值的分值
for k in range(2,50,2):
knn = KNeighborsClassifier(n_neighbors=k).fit(x_train,y_train)
score = knn.score(x_test,y_test)
ks.append(k)
scores.append(score)
arr_ks = np.array(ks)
arr_scores = np.array(scores)
arr_ks,arr_scores
(array([ 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34,
36, 38, 40, 42, 44, 46, 48]),
array([0.93 , 0.945, 0.945, 0.95 , 0.95 , 0.95 , 0.955, 0.96 , 0.955,
0.955, 0.955, 0.95 , 0.955, 0.955, 0.95 , 0.955, 0.955, 0.955,
0.96 , 0.955, 0.955, 0.955, 0.96 , 0.96 ]))
np.argmax(arr_scores) #找出arr_scores数组中最大值对应的下标
arr_ks[np.argmax(arr_scores)]#找出最优的模型参数的值
k的取值问题:学习曲线与交叉验证选取K值
①K值较小,则模型复杂度较高,容易发生过拟合,学习的估计误差会增大,预测结果对近邻的实例点非常敏感。
②K值较大可以减少学习的估计误差,但是学习的近似误差会增大,与输入实例较远的训练实例也会对预测起作用,使预测发生错误,k值增大模型的复杂度会下降。
③在应用中,k值一般取一个比较小的值,通常采用交叉验证法来来选取最优的K值。
K值的交叉验证
目的:
选出最为适合的模型超参数的取值,然后将超参数的值作用到模型的创建中。
思想:
将样本的训练数据交叉的拆分出不同的训练集和验证集,使用交叉拆分出不同的训练集和验证集测分别试模型的精准度,然后求出的精准度的均值就是此次交叉验证的结果。将交叉验证作用到不同的超参数中,选取出精准度最高的超参数作为模型创建的超参数即可。
实现思路:
①将训练数据平均分割成K个等份
②使用1份数据作为验证数据,其余作为训练数据
③计算验证准确率
④使用不同的测试集,重复2、3步骤,直到所有等份都作为过训练数据
⑤对准确率做平均,作为对未知数据预测准确率的估计
ks = []
scores = []
for k in range(2,50):
knn = KNeighborsClassifier(n_neighbors=k)
score = cross_val_score(knn,x_train,y_train,cv=5).mean() # cv表示五等分
ks.append(k)
scores.append(score)
arr_ks = np.array(ks)
arr_scores = np.array(scores)
与未使用交叉验证的学习曲线的代码的区别为
knn = KNeighborsClassifier(n_neighbors=k)
和score = cross_val_score(knn,x_train,y_train,cv=5).mean()
。因为fit函数会使模型完全符合训练数据,所以交叉验证并未使用fit函数。
交叉验证的cross_val_score
函数(cv=5)相当于进行了5次用4/5的训练集数据进行训练,1/5的数据进行测试,最后给出5个精度。