KNN(K-Nearest Neighbor)算法,顾名思义,其原理也就是“近朱者赤,近墨者黑”。KNN算法是一种有监督的分类算法,输入同样为样本特征值向量以及对应的类标签,输出则为具有分类功能的模型,能够根据输入的特征值预测分类结果。核心原理就是,与待分类点最近的K个邻居中,属于哪个类别的多,待分类点就属于那个类别。
KNN分类算法的思路很简洁,实现也很简洁,具体分三步:
1)找K个最近邻。KNN分类算法的核心就是找最近的K个点,选定度量距离的方法之后,以待分类样本点为中心,分别测量它到其他点的距离,找出其中的距离最近的“TOP K”,这就是K个最近邻。
2)统计最近邻的类别占比。确定了最近邻之后,统计出每种类别在最近邻中的占比。
3)选取占比最多的类别作为待分类样本的类别。
KNN算法模型主要有三要素构成:距离度量,k值的选择和分类的决策规则。
两个样本点之间的距离代表了这两个样本之间的相似度。距离越大,差异性越大;距离越小,相似度越大。
闵可夫斯基距离的数学表达式如下:
闵可夫斯基距离是一组距离的定义,不妨把闵可夫斯基距离看作一个代数形式的母版,通过给P设置不同的值,就能用闵可夫斯基距离得到不同的距离表达式。
当P=1时,称为曼哈顿距离,表达式如下:
当P=2时,为欧几里得距离,最常用于度量两点之间的直线距离。表达式如下:
距离的度量方法没有好坏,选择什么方法主要是根据当前情况而定。
k值的选择会对KNN算法的结果产生重大的影响。
如果选择较小的K值
“学 习”的近似误差(approximation error)会减小,但 “学习”的估计误差(estimation error) 会增大,
噪声敏感
K值的减小就意味着整体模型变得复杂,容易发生过 拟合.
如果选择较大的K值
减少学习的估计误差,但缺点是学习的近似误差会增大.
K值的增大 就意味着整体的模型变得简单.
在应用中,k值一般取一个比较小的数值,通常采用交叉验证法来选取最优的k值。
根据多数表决原则,决定待分类样本点的类别。
1)数据加载:我们可以直接从 sklearn 中加载自带的手写数字数据集;
2)准备阶段:通过可视化的方式来查看图像的呈现。通过数据规范化可以让数据都在同一个数量级的维度。将全部的图像数据作为特征值矩阵;
3)分类阶段:通过训练可以得到分类器,然后用测试集进行准确率的计算。
knn分类器的常用构造参数有:
1).n_neighbors 代表邻居的数量。
2).weights: 代表所有邻居的权重,其中 uniform 代表所有邻居权重相同, distance 代表权重是距离的倒数。还可以自定义。
3).algorithm: 计算邻居的方法,auto代表 根据数据的情况自动选择,kd_tree 是kd树,适用于维数不超过20的情况。ball_tree是球树,可以用于维度更大的情况。brute 是暴力搜索。
4).leaf_size:是kd树或者球树的叶子数量,默认是20.
from sklearn.model_selection import train_test_split
from sklearn import preprocessing
from sklearn.metrics import accuracy_score
from sklearn.datasets import load_digits
from sklearn.neighbors import KNeighborsClassifier
import matplotlib.pyplot as plt
#加载数据
digits = load_digits()
data = digits.data
#数据探索
print(data.shape)
(1797, 64)
# 查看第一幅图像
print(digits.images[0])
[[ 0. 0. 5. 13. 9. 1. 0. 0.]
[ 0. 0. 13. 15. 10. 15. 5. 0.]
[ 0. 3. 15. 2. 0. 11. 8. 0.]
[ 0. 4. 12. 0. 0. 8. 8. 0.]
[ 0. 5. 8. 0. 0. 9. 8. 0.]
[ 0. 4. 11. 0. 1. 12. 7. 0.]
[ 0. 2. 14. 5. 10. 12. 0. 0.]
[ 0. 0. 6. 13. 10. 0. 0. 0.]]
# 第一幅图像代表的数字含义
print(digits.target[0])
0
# 将第一幅图像显示出来
plt.gray()
plt.imshow(digits.images[0])
plt.show()
# 分割数据,将25%的数据作为测试集,其余作为训练集
train_x, test_x, train_y, test_y = train_test_split(data, digits.target, test_size=0.25, random_state=33)
# 采用Z-Score规范化
ss = preprocessing.StandardScaler()
train_ss_x = ss.fit_transform(train_x)
test_ss_x = ss.transform(test_x)
# 创建KNN分类器
knn = KNeighborsClassifier(n_neighbors=4)
knn.fit(train_ss_x, train_y)
predict_y = knn.predict(test_ss_x)
print("KNN准确率: %.4lf" % accuracy_score(test_y, predict_y))
KNN准确率: 0.9733
代码中,我使用了 train_test_split 做数据集的拆分,使用 matplotlib.pyplot 工具包显示图像,使用 accuracy_score 进行分类器准确率的计算,使用 preprocessing 中的 StandardScaler 和 MinMaxScaler 做数据的规范化。
李航.统计学习方法(第2版)
陈旸.数据分析实战45讲