KNN算法的原理及Python实现

89 阅读2分钟

一、KNN算法的原理

KNN算法即K近邻算法,是一种分类算法。俗话说“物以类聚,人以群分”,要确定一个样本的类别,KNN算法的基本原理就是:首先计算它与所有训练样本的距离,将距离进行排序后,选取距离待确定类别样本最近的K个样本,这K个样本中所属类别样本数最多的类别即为该待预测样本的类别。

二、距离的度量

KNN算法的实现依赖于样本之间的距离值,因此需要选取合适的距离度量函数。常用的距离函数有欧氏距离(即直线距离)、马氏距离等。这里以欧式距离为例说明:

  1. 归一化。由于特征向量各分量的量纲差异,例如某样本的特征向量包含肺活量与身高两个分量,肺活量为2000-9000,身高为150-200。因此若是直接使用欧式距离计算,身高对距离的贡献将会被覆盖。常用的归一化方法包括: (1)线性归一化:x=xmin(x)max(x)min(x)x'=\frac{x-min(x)}{max(x)-min(x)} (2)零-均值归一化:x=xμσx'=\frac{x-\mu}{\sigma}
  2. 计算待预测样本到所有训练样本的距离

三、KNN算法的优缺点

优点

  1. 算法简单,容易理解实现

缺点

  1. 当训练样本数大,特征向量维数高时,计算复杂度高,因为需要计算待预测样本到每个训练样本的距离并进行排序
  2. K值的取值确定十分重要,当K取值过小时,易出现过拟合,当K取值过大时,易出现欠拟合。

四、Python使用KNN算法实现对iris数据集的分类

完整代码如下所示:

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.neighbors import KNeighborsClassifier
import matplotlib
matplotlib.rcParams['font.sans-serif'] = 'SimHei' 

# 生成所有测试样本点
def make_meshgrid(x, y, h=.02):
    x_min, x_max = x.min() - 1, x.max() + 1
    y_min, y_max = y.min() - 1, y.max() + 1
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
                         np.arange(y_min, y_max, h))
    return xx, yy

# 对测试样本进行预测,并显示
def plot_test_results(ax, clf, xx, yy, **params):
    Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    ax.contourf(xx, yy, Z, **params)

# 载入iris数据集
iris = datasets.load_iris()
# 只使用前面两个特征
X = iris.data[:, :2]
# 样本标签值
y = iris.target

# 创建kNN分类器,并指定K值=6
knn = KNeighborsClassifier(n_neighbors=3) 
knn.fit(X,y)

title = ('KNN分类算法')

fig, ax = plt.subplots(figsize = (5, 5))
plt.subplots_adjust(wspace=0.4, hspace=0.4)

X0, X1 = X[:, 0], X[:, 1]
# 生成所有测试样本点
xx, yy = make_meshgrid(X0, X1)

# 显示测试样本的分类结果
plot_test_results(ax, knn, xx, yy, cmap=plt.cm.coolwarm, alpha=0.8)
# 显示训练样本
ax.scatter(X0, X1, c=y, cmap=plt.cm.coolwarm, s=20, edgecolors='k')
ax.set_xlim(xx.min(), xx.max())
ax.set_ylim(yy.min(), yy.max())
ax.set_xlabel('特征1')
ax.set_ylabel('特征2')
ax.set_xticks(())
ax.set_yticks(())
ax.set_title(title)
plt.show()

分类结果如下图所示:

1.png