KNN算法——kd-tree、KNN莺尾花分类sklearn实现实例

KNN算法——kd-tree、KNN莺尾花分类sklearn实现实例

    • KNN算法——kd-tree、KNN莺尾花分类sklearn实现实例
  • 1、kd-tree
  • 2、kd-tree的构建
  • 3、kd-tree 查找最近邻
  • 4、KNN莺尾花分类sklearn实现实例

KNN算法——kd-tree、KNN莺尾花分类sklearn实现实例

1、kd-tree

KNN算法的重点在于找出K个最邻近的点,算法的训练过程就是将数据存储,存储数据的方式决定了查找出K个最邻近的点的速度,其中有两种方法:

  • 蛮力实现(brute)
    计算预测样本到所有训练集样本的距离,然后选择最小的K个距离,即可得到K个最邻近点
    缺点在于,当特征数和样本数比较多的时候,算法的执行效率就比较低

  • KD树(kd-tree)
    KD树算法中首先是对训练数据进行建模,常见KD树,然后再根据建好的模型,来查找获取最邻近近的样本。

kd-tree在在模型中只是起到保存数据的作用,找不过是用KD树保存的数据,在做K近邻检索的时候会更迅速,更快捷。

2、kd-tree的构建

假设现在我们有m个样本,每个样本具有n个特征,那么现在这些数据就构成一个m*n的矩阵。

  1. 首先,计算n列特征中每一列特征的方差S
  2. 比较n个S,选取最大的S(方差最大的特征)对应的特征作为根节点划分属性
  3. 对划分属性进行排序,选取中位数(中间偏大的数)最为划分点,对m个样本进行划分
  4. 完成一次划分的到左子树,右子树
  5. 对左右子树重复1,2,3,4步骤

KNN算法——kd-tree、KNN莺尾花分类sklearn实现实例_第1张图片
选取方差最大的特征,是因为方差越大,说明这个特征上的数据是相对分散的。
构建kd-tree,实际上是将特征空间划分为许许多多的小块
KNN算法——kd-tree、KNN莺尾花分类sklearn实现实例_第2张图片


3、kd-tree 查找最近邻

根据上面的划分过程,我们可以将特征空间划分成多个小方块,当有待预测数据进来时,怎么进行查找预测呢?

KNN算法——kd-tree、KNN莺尾花分类sklearn实现实例_第3张图片
假设现在新进来的数据是(2,4.5)

  1. 首先,在当前区域内找到距离最近的点
  2. 直观上,以距离最近的点的距离为半径画圆
  3. 查找与另一颗子树是否有相交区域,如果有,在此区域查找是否有小于当前的最小距离
  4. 在检查与父节点的另一颗子树时候有相交的区域,如果有,在此区域查找是否有小于当前的最小距离

重复这样的操作,最多找三棵子树(左子树,右子树,父节点的另一颗子树),如果数据很对,将大大减少查找速度

4、KNN莺尾花分类sklearn实现实例

# 课程内容:
# 开发时间: 13:04

import pandas as pd
import numpy as np
import sys
import joblib
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier,KNeighborsRegressor #导入sklearn中KNN模型的包,KNeighborsClassifier做分类任务,KNeighborsRegressorz做回归任务
from sklearn.metrics import accuracy_score,recall_score,precision_score#导入评估指标所用的包

# 1、加载数据(数据一般存储于磁盘或数据库)
path = 'iris.data'
names = ['A','B','C','D','cla']#A,B,C,D代表特征,cla代表标签
df = pd.read_csv(path,header = None,names = names,sep = ",")


# print(df.head())
# print(df.shape)
# print(df["cla"].value_counts())
# sys.exit()

# 2、数据清洗
# NOTE: 不需要做数据处理
def parse_record(row):
    result = []
    r = zip(names,row)
    for name,value in r:
        if name == 'cla':
            if value == 'Iris-setosa':
                result.append(1)
            elif value == 'Iris-versicolor':
                result.append(2)
            elif value == 'Iris-virginica':
                result.append(3)
            else:
                result.append(0)
        else:
            result.append(value)
    return result



df = df.apply(lambda row: pd.Series(parse_record(row),index=names),axis=1)
df.cla = df.cla.astype(np.int32)
# df.info()
# print(df.cla.value_counts())
flag = False
# df = df[df.cla != 3]
# print(df.cla.value_counts())


# 3、根据需求获取最原始的特征属性矩阵X和目标属性Y
X = df[names[0:-1]]
# print(X.shape)
Y = df[names[-1]]
# print(Y.value_counts())
# sys.exit()


# 4、数据分割(训练集和测试集)
# train_size: 给定划分之后的训练数据的占比是多少,默认为0.75
# random_state: 给定在数据划分过程中,使用到的随机数种子,默认为None,使用当前的时间戳,给定非None的值,可以保证多次运行的结果是一致的
x_train,x_test,y_train,y_test = train_test_split(X,Y,train_size=0.6,random_state=28)
print("训练数据X的格式:{},以及类型:{}".format(x_train.shape,type(x_train)))
print(f'测试数据X的格式:{x_test.shape}')
print(f'训练数据Y的类型:{type(y_train)}')


# 5、特征工程的操作
# NOTE:不做特征工程


# 6、模型对象的构建
"""
KNN:
    n_neighbors = 5  --->K的值
    weights = 'uniform'  ---->等权划分
    algorithm = 'kd_tree' ---->KD树存储
    leaf_size = 30
    p = 2 ---->欧氏距离
    metric = 'minkowski'
    metric_params = None
    n_jobs = 1
    
"""
KNN = KNeighborsClassifier(n_neighbors=1,weights='uniform',algorithm='kd_tree')



# 7、模型的训练
KNN.fit(x_train,y_train)


# 8、模型效果评估
train_predict = KNN.predict(x_train)
test_predict = KNN.predict(x_test)
print(f"KNN算法,测试集上的效果(准确率):{KNN.score(x_test,y_test)}")
print(f'KNN算法,测试集上的效果(准确率):{KNN.score(x_train,y_train)}')


# 模型的保存与加载
"""
import joblib
#存储模型
joblib.dump(model,filename=)
#加载恢复模型
knn = joblib.load("./knn.m")
#对待预测的数据进行预测(数据处理好后的数据)
x = [[5.1,3.5,1.4,0.2]]
y_hat = knn.predict(x)
print(y_hat)
"""
joblib.dump(KNN,'./knn.m')#保存模型
#加载模型
# knn = joblib.load("./knn.m")

KNN算法——kd-tree、KNN莺尾花分类sklearn实现实例_第4张图片

 莺尾花数据评论提取

你可能感兴趣的:(机器学习,sklearn,算法,分类,KNN)