适用问题:多类分类、回归
模型特点:特征空间,样本点
模型类型:判别模型
损失函数:-
学习策略:-
学习算法:-
k-nearest neighbors (k-NN)
,k 近邻法,用于分类和回归。
KNN做回归和分类的主要区别在于最后做预测时候的决策方式不同
,KNN做分类
预测时,一般是使用多数表决法
;KNN做回归
时,一般是使用平均法
,即最近的K个样本的样本输出的平均值作为回归预测值。本文以分类算法展开介绍。
k-近邻法没有显示的学习过程,是一种lazy learning algorithm
。
k-近邻法的输入:实例的特征向量,对应于特征空间的点,输出:实例的类别。
k-近邻法:利用训练数据集对特征向量空间进行划分
,并作为其分类的“模型”。分类时,对于新实例,根据其 k 个最近邻
的训练实例的类别,通过多数表决
等方式进行预测。
k-近邻模型的三要素
:k值的选择、距离度量(作为"最邻近"的衡量标准)、分类决策规则(例如”多数表决“)
knn算法可总结为3个步骤:
- 1.Choose the number of k and a distance metric.
- 2.Find the k-nearest neighbors of the sample that we want to classify.
- 3.Assign the class label by majority vote.
k近邻法使用的模型,实际上对应于特征空间的划分
。
模型三要素
:k值的选择、距离度量(作为"最邻近"的衡量标准)、分类决策规则(例如”多数表决“)
k值的选择会对k近邻法的结果产生重大影响。应用中,k值一般取 较小
的数值,通常可使用 交叉验证法
来取得最优的k值。
k 值的选择反映了对近似误差和估计误差之间的权衡
。
近似误差,可以理解为对现有训练集的训练误差。更关注于“训练”。
估计误差:可以理解为对测试集的测试误差。更关注于“测试”、“泛化”。
特征空间中2个实例点的距离,是2个实例点 相似程度
的反映。
不同的距离度量所确定的最近邻点是不同的。
设特征空间 χ \chi χ 是 n维实数向量空间 R n \text{R}^n Rn, x i , x j ∈ χ x_i,x_j \in \chi xi,xj∈χ,则 x i , x j x_i,x_j xi,xj的 L p L_p Lp距离(或叫Minkowski distance
)定义为:
L p ( x i , x j ) = ( ∑ l = 1 n ∣ x i ( l ) − x j ( l ) ∣ p ) 1 p , p ≥ 1 L_p(x_i,\;x_j)=(\sum\limits_{l=1}^n|x_i^{(l)}-x_j^{(l)}|^p)^{\frac{1}{p}}\quad,\; p \ge 1 Lp(xi,xj)=(l=1∑n∣xi(l)−xj(l)∣p)p1,p≥1
当 p = 2 p=2 p=2 时,称为欧氏距离(Euclidean distance)
:即
L 2 ( x i , x j ) = ( ∑ l = 1 n ∣ x i ( l ) − x j ( l ) ∣ 2 ) 1 2 L_2(x_i,\;x_j)=(\sum\limits_{l=1}^n|x_i^{(l)}-x_j^{(l)}|^2)^{\frac{1}{2}} L2(xi,xj)=(l=1∑n∣xi(l)−xj(l)∣2)21
当 p = 1 p=1 p=1 时,称为曼哈顿距离(Manhattan distance)
,即
L 1 ( x i , x j ) = ( ∑ l = 1 n ∣ x i ( l ) − x j ( l ) ∣ ) L_1(x_i,\;x_j)=(\sum\limits_{l=1}^n|x_i^{(l)}-x_j^{(l)}|) L1(xi,xj)=(l=1∑n∣xi(l)−xj(l)∣)
当 p = ∞ p=\infty p=∞ 时,它是各个坐标距离的最大值,即
L ∞ ( x i , x j ) = max l ∣ x i ( l ) − x j ( l ) ∣ L_{\infty}(x_i,\;x_j)=\max\limits_l|x_i^{(l)}-x_j^{(l)}| L∞(xi,xj)=lmax∣xi(l)−xj(l)∣
多数表决法
,多数表决规则等价于经验风险最小化
(经验风险:模型关于训练集的平均损失)。
k近邻法,主要考虑的问题:如何对训练数据进行快速k近邻搜索。尤其是特征空间维数大以及训练数据量大时,尤为重要。
简单实现:线性扫描。需要计算输入实例与每个训练实例的距离。训练集很大时,计算非常耗时,不可取。
kd树实现,提高k邻近搜索效率,以特殊的结构(例如kd tree,还有很多其他方法)存储训练数据,减少了计算距离的次数。
【注意】:kd 树中的k 是指样本特征的维度,KNN中的k是指k个最近的样本实例
。
kd 树是一种对 k 维空间的实例点进行存储
以便对其进行快速检索
的树形数据结构
。kd 树是二叉树
,表示对 k 维空间的一个划分
。kd 树的每个结点对应一个 k 维的超矩形区域。
通常,依次
选择坐标轴对空间切分(或者分别计算n个特征的取值的方差,然后取方差最大
的第k维特征n_k对应的坐标轴来对空间进行切分(改进方法
))。选择切分点时 为训练实例点在对应坐标轴上(投影)的中位数
,这样得到的kd 树是平衡
的。注意:平衡的kd 树搜索时的效率未必是最优的
。
kd 树的本质其实就是 二叉搜索树
。
利用kd 树,搜索可以限制在空间的局部区域上
,可以省去对大部分数据点的搜索,从而减少搜索的计算量(主要是由于很多样本点所在的超矩形区域和超球体不相交,根本不需要计算距离)。
kd 树搜索的平均计算复杂度是 O(logN)
,N为训练实例数。kd 树适合于 N >> k 的情况,当 N ~ k 接近时,效率寻找下降,几乎接近 线性扫描。
kd树的预测:在kd树搜索最近邻的基础上,我们选择到了第一个最近邻样本,就把它置为已选。在第二轮中,我们忽略置为已选的样本,重新选择最近邻,这样跑k次
,就得到了目标的K个最近邻,然后根据多数表决法,如果是KNN分类,预测为K个最近邻里面有最多类别数的类别。如果是KNN回归,用K个最近邻样本输出的平均值作为回归预测值。
可用于分类和回归任务,下面的示例:使用KNN完成鸢尾花分类任务。
引入包和加载数据:
from matplotlib import pyplot as plt
from matplotlib.colors import ListedColormap
from sklearn import datasets
from sklearn.model_selection import train_test_split
import numpy as np
from sklearn.neighbors import KNeighborsClassifier
iris = datasets.load_iris()
print(iris['data'].shape, iris['target'].shape) # (150, 4) (150,)
X = iris.data[:,[2,3]]
y = iris.target
print('Class labels:', np.unique(y))
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=1, stratify=y)
print(X_train.shape, y_train.shape)
输出:
(150, 4) (150,)
Class labels: [0 1 2]
(105, 2) (105,)
绘制决策边界函数:
# 训练,并绘制分类决策边界:
def plot_decision_regions(X, y, classifier, test_idx=None, resolution=0.02):
# setup marker generator and color map
markers = ('s', 'x', 'o', '^', 'v')
colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan')
cmap = ListedColormap(colors[:len(np.unique(y))])
# plot the decision surface
x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1
x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution),
np.arange(x2_min, x2_max, resolution))
Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T)
Z = Z.reshape(xx1.shape)
plt.contourf(xx1, xx2, Z, alpha=0.3, cmap=cmap)
plt.xlim(xx1.min(), xx1.max())
plt.ylim(xx2.min(), xx2.max())
for idx, cl in enumerate(np.unique(y)):
plt.scatter(x=X[y == cl, 0], y=X[y == cl, 1],
alpha=0.8, c=colors[idx],
marker=markers[idx], label=cl,
edgecolor='black')
# highlight test samples
if test_idx:
# plot all samples
X_test, y_test = X[test_idx, :], y[test_idx]
plt.scatter(X_test[:, 0], X_test[:, 1],
c='', edgecolor='black', alpha=1.0,
linewidth=1, marker='o',
s=100, label='test set')
训练:
# 标准化数据
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
sc.fit(X_train)
X_train_std = sc.transform(X_train)
X_test_std = sc.transform(X_test)
X_combined_std = np.vstack((X_train_std, X_test_std))
y_combined = np.hstack((y_train, y_test))
# 训练,k=5, 距离度量为
knn = KNeighborsClassifier(n_neighbors=5, p=2, metric='minkowski')
knn.fit(X_train_std, y_train)
print('Training accuracy:', knn.score(X_train_std, y_train))
print('Testing accuracy:', knn.score(X_test_std, y_test))
输出:
Training accuracy: 0.9619047619047619
Testing accuracy: 1.0
绘制决策边界:
# 绘制决策边界
plot_decision_regions(X_combined_std, y_combined, classifier=knn, test_idx=range(105,150))
plt.xlabel('petal length [standardized]')
plt.ylabel('petal width [standardized]')
plt.legend(loc='upper left')
plt.show()
模型评价参考自刘建平老师的K近邻法(KNN)原理小结。
KNN简单、直观,其主要优点有:
KNN的主要缺点有:
完整代码请移步至: 我的github:https://github.com/qingyujean/Magic-NLPer,求赞求星求鼓励~~~
最后:如果本文中出现任何错误,请您一定要帮忙指正,感激~
[1] 统计学习方法(第2版) 李航
[2] K近邻法(KNN)原理小结 刘建平
[3] Python_Machine_Learning_2nd_Edition