概述
knn(k近邻)是机器学习比较常用的算法,也是一个比较简单的算法,其工作机制非常简单:给定测试样本,基于某种距离度量找出训练集与其最靠近的k个训练样本,然后基于这k个邻居的信息来进行预测。在分类中,选择这k个样本中出现最多的类别标记作为预测结果;而在回归中,则用这k个样本的平均值作为预测结果。也可以基于距离远近进行加权平均和加权投票,距离越近权重越大。这次基于kaggle上的数字识别器讲解其分类用法。
距离度量
knn中使用的距离一般是欧式距离,但也可以使其它距离,比如更一般的
L
p
L_p
Lp距离
设特征空间
χ
\chi
χ是
n
n
n维实数向量空间
R
n
R^n
Rn,
x
i
,
x
j
∈
χ
,
x
i
=
(
x
i
(
1
)
,
x
i
(
2
)
,
.
.
.
,
x
i
(
n
)
)
T
,
x
j
=
(
x
j
(
1
)
,
x
j
(
2
)
,
.
.
.
,
x
j
(
n
)
)
T
,
x
i
,
x
j
x_i, x_j\in\chi, x_i=(x_i^{(1)},x_i^{(2)}, ...,x_i^{(n)})^T, x_j=(x_j^{(1)},x_j^{(2)}, ...,x_j^{(n)})^T, x_i, x_j
xi,xj∈χ,xi=(xi(1),xi(2),...,xi(n))T,xj=(xj(1),xj(2),...,xj(n))T,xi,xj的
L
p
L_p
Lp距离定义为
L
p
(
x
i
,
x
j
)
=
(
∑
l
=
1
n
∣
x
i
(
l
)
−
x
j
(
l
)
∣
p
)
1
p
{L_p}({x_i},{x_j}) = {(\sum\limits_{l = 1}^n {{{\left| {x_i^{(l)} - x_j^{(l)}} \right|}^p}} )^{\frac{1}{p}}}
Lp(xi,xj)=(l=1∑n∣∣∣xi(l)−xj(l)∣∣∣p)p1
这里
p
≥
1
p\ge 1
p≥1.当
p
=
2
p=2
p=2时,称为欧式距离,即
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 {{{\left| {x_i^{(l)} - x_j^{(l)}} \right|}^2}} )^{\frac{1}{2}}}
L2(xi,xj)=(l=1∑n∣∣∣xi(l)−xj(l)∣∣∣2)21
当
p
=
1
p=1
p=1时,称为曼哈顿距离,即
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 {{{\left| {x_i^{(l)} - x_j^{(l)}} \right|}}} }
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}) = \mathop {\max }\limits_l \left| {x_i^{(l)} - x_j^{(l)}} \right|
L∞(xi,xj)=lmax∣∣∣xi(l)−xj(l)∣∣∣
分类决策
knn在分类时是有多数表决投票所决定,如果分类的损失函数为0-1损失函数,分类函数为
$f:{R^n} \to { {c_1},{c_2},…,{c_n}} $
那么误分类的概率是
P
(
Y
̸
=
f
(
X
)
)
=
1
−
P
(
Y
=
f
(
X
)
)
P(Y\not = f(X))=1-P(Y=f(X))
P(Y̸=f(X))=1−P(Y=f(X))
那么对于给定的实例
x
x
x,其最近的k个训练点构成集合
N
k
(
x
)
N_k(x)
Nk(x).如果涵盖
N
k
(
x
)
N_k(x)
Nk(x)的区域类别是
c
j
c_j
cj,那么误分类率为
$\frac{1}{k}\sum\limits_{{x_i} \in {N_k}(x)} {I({y_i} \ne {c_j}) = 1 - } \frac{1}{k}\sum\limits_{{x_i} \in {N_k}(x)} {I({y_i} = {c_j})} $
所以为了保证误分类率最小,即让
∑
x
i
∈
N
k
(
x
)
I
(
y
i
=
c
j
)
\sum\limits_{{x_i} \in {N_k}(x)}I({y_i} = {c_j})
xi∈Nk(x)∑I(yi=cj)最小,所以多数表决投票也相当于一种风险最小化
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv("D:/train.csv")
a = df.loc[0]
a = np.array(a)
a = a[1:785]
a.resize(28, 28)
plt.imshow(a, cmap='gray')
首先导入数据(28*28的图片),将其可视化,结果为
from sklearn.model_selection import train_test_split
from sklearn.decomposition import PCA
from sklearn.neighbors import KNeighborsClassifier
Labels = df['label']
Features = df.iloc[0:42000,1:785]
m, n = np.shape(Features)
Features = np.multiply(Features != np.zeros((m,n)), np.ones((m,1)))
pca = PCA(n_components=128)
reduced_features = pca.fit_transform(Features)
X_train, X_test, label_train, label_test = train_test_split(reduced_features, Labels, test_size = 0.3)
for k in range(1,11):
clf = KNeighborsClassifier(k)
clf.fit(X_train, label_train)
result = clf.predict(X_test)
print(k, ':', clf.score(X_test, label_test))
接下来将数据分为训练集和测试集,然后运行knn,调整K值以寻找准确率最高的k值是多少,结果为
在这里可见当k=4时泛化效果最好,精度可以达到0.966,接下来看一下当k=4时分类报告
clf = KNeighborsClassifier(4)
clf.fit(X_train, label_train)
result = clf.predict(X_test)
print('准确率', accuracy_score(label_test, result))
print('混淆矩阵', confusion_matrix(label_test, result))
print('分类报告', classification_report(label_test, result))
结果为
混淆矩阵
参考:
1.机器学习 周志华著
2.统计学习方法 李航著