机器学习之K近邻分类模型 python底层代码实现

K近邻算法是一种基本分类与回归方法。分类时,对新的实例,根据其k个最近邻的训练实例的类别,通过多数表决的方式进行预测。因此,K近邻法不具有显式的学习过程。


K近邻算法(K-nearest neighbor)

K近邻算法简单、直观:给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最近邻的K个实例,这K个实例的多数属于某个类,就把该输入实例分为这个类。k值的选择、距离度量及分类决策规则是K近邻算法的三个基本要素。


一、k值的选择

k值的选择会对近邻法的结果产生重大影响。如果选择较小的K值,就相当于用较小的邻域中的训练实例进行预测,“学习”的近似误差会减小,只有与输入实例较近的训练实例才会对预测结果起作用,但缺点是“学习”的估计误差会增大,预测结果会对近邻的实例点非常敏感,如果近邻的实例点恰巧是噪声,预测就会出错,换句话说,k值的减小意味着整体模型变得复杂,容易过拟合。
如果选择较大的k值,就相当于用较大邻域的训练实例进行预测,其优点是减少学习到的估计误差,但缺点是学习到的近似误差会增大。这时与输入实例较远的训练实例也会对预测产生影响,K值的增大意味着整体的模型变得简单。
通常采用交叉验证法来选择最优的K值。

二、距离度量

欧式距离

特征空间中两个实例点的距离是两个实例点相似程度的反映,K近邻模型的特征空间一般是n维实数向量空间,使用的距离是欧式距离,但也可以是其他距离,如闵可夫斯基(Minkowski distance)距离。闵可夫斯基距离的表达式为:

L p ( x i , x j ) = ( ∑ i = 1 n ∣ x i l − x j l ∣ p ) 1 p L_p\left( x_i,x_j \right) =\left( \sum_{i=1}^n{\left| {x_i}^l-{x_j}^l \right|^p} \right) ^{\frac{1}{p}} Lp(xi,xj)=(i=1nxilxjlp)p1
当p=2时,该式称为欧式距离;
当p=1时,该式称为曼哈顿距离;
当p=∞时,该式称为切比雪夫距离(chebyshev distance)

代码如下(示例):

三、k近邻算法的实现

实现k近邻算法时,除了考虑K值的选择以外,更要考虑如何对训练集进行快速K近邻搜索。首先想到的是使用穷举法,计算新实例点到训练集中每个实例点的距离。这种方式在训练数据集较小时可行,但是当训练数据集特别大时,此方法的缺点也很明显-计算非常耗时。为了提高K近邻算法的效率,有了kd树这种方法 产生。对于KD树的详细知识不作介绍,这里直接调用sklearn中的kd树,并实现用k近邻算法预测新实例点的类别:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt 
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_blobs
from sklearn.metrics import confusion_matrix#混淆矩阵
from sklearn.neighbors import KDTree
from collections import Counter##计数功能
import seaborn as sn
np.random.seed(2)
X, Y = make_blobs(n_samples=100,n_features=2,centers=4)
x_train,x_test,y_train,y_test = train_test_split(X,Y,test_size=0.2)
plt.scatter(x_train[:,0],x_train[:,1],c=y_train)
plt.scatter(x_test[:,0],x_test[:,1],marker='*',c=y_test)
plt.show()
class KNN:
    def __init__(self):
        pass
    def predict(self,x_train,y_train,x_test):
    ''' 预测函数'''
        kdtree=KDTree(x_train,leaf_size=2)
        pred_y=[]
        for i in range(len(x_test)):
            index=kdtree.query([x_test[i]],k=6)[1]#kdtree.query(node,k=n)方法返回距离node最近的n个点的距离和对应点的索引,这里只用索引
            target=[]
            [target.append(y_train[i]) for i in index]
            target=np.array(target).flatten()
            max_num=Counter(target).most_common(1)[0][0]
            pred_y.append(max_num)
        return pred_y
model=KNN()
pred_y=model.predict(x_train,y_train,x_test)
sn.heatmap(confusion_matrix(y_test,pred_y), annot=True)

在这里插入图片描述
在这里插入图片描述

参考

统计学习方法-李航

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值