04. k近邻(k-nearest neighbour,KNN )分类鸢尾花

     K近邻是一种基本的分类方法,通过测量不同特征值之间的距离进行分类。它的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最近邻)的样本中的大多数属于某一个类别,则该样本也属于这个类别,其中K通常是不大于20 的整数。

     KNN算法的结果很大程度取决于K的选择 .

     KNN中,通过计算对象间距离来作为各个对象之间的非相似性指标,距离一般使用欧式距离或曼哈顿距离:
    04. k近邻(k-nearest neighbour,KNN )分类鸢尾花_第1张图片

导入数据

import numpy as np 
import pandas as pd 

# 直接引入sklearn里面的数据集,iris 鸢尾花
from sklearn.datasets import load_iris ##加载数据
from sklearn.model_selection import train_test_split ## 切分数据集为训练集和测试集 
from sklearn.metrics import accuracy_score ## 用来计算分类预测的准确率
iris = load_iris() ## 加载鸢尾花数据 
iris
#'target': array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
#        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
#        0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
#       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
#        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
#        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
#        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]), 存放的是特征值对应的目标值,和target_name匹配
## 'target_names': array(['setosa', 'versicolor', 'virginica'] 花的类别
## 'feature_names': ['sepal length (cm)', 花萼长度
## 'sepal width (cm)', 花萼宽度
## 'petal length (cm)', 花萼长度
## 'petal width (cm)'], 花萼宽度
x = iris.data  ##加载数据
y = iris.target ##一维数组
y = y.reshape(-1,1) ##将一维数组改矩阵,任意行 一列 

 04. k近邻(k-nearest neighbour,KNN )分类鸢尾花_第2张图片

04. k近邻(k-nearest neighbour,KNN )分类鸢尾花_第3张图片 

 

2.核心算法实现

# 距离函数定义 
def manhadun(a,b): #曼哈顿距离 a为矩阵 b为向量
    return np.sum(np.abs(a-b),axis=1) # axis = 1 保存为一列

def oushi(a,b): ##欧氏距离
    return np.sqrt(np.sum((a-b)**2,axis=1))

# 分类器实现 

class Knn(object):
    ## 定义一个初始化方法__init__ 类的构造方法
    ## n_neighbors为近邻的K值 
    ## dist_func 为 判断距离的方法
    def __init__(self,n_neighbors=1,dist_func=manhadun):
        self.n_neighbors = n_neighbors
        self.dist_func=dist_func 
    
    ## 训练模型方法 
    def fit(self,x,y):
        self.x_train = x 
        self.y_train = y 
        
    # 模型预测方法:
    # x 为测试数据
    def predict(self,x):
        # 初始化预测分类数据 
        # 定义一个与传入的x相同行数的值全是0的数组
        # 其结果的类型应该与训练集的y值一样
        y_pred = np.zeros((x.shape[0],1),dtype=self.y_train.dtype)
        
        # 遍历测试的数据,取出每个数据点的序号和数据x_test
        for i,x_test in enumerate(x):
            # 1.x_test 跟所有训练数据计算距离
            # 当前的测试数据与每一行的训练数据计算距离
            distances = self.dist_func(self.x_train,x_test)
            if i == 0:
                print(x_test,distances)
            # 2.得到的距离按照由近到远进行排序,取出索引值
            # argsort 将所有的数据进行排序,并取出索引值
            nn_index=np.argsort(distances)
            # 3.选取距离最近的K个点,保存他们对应的分类类别 
            # 从训练集里取出K个值
            # ravel 是将数据转变为一维的数组
            nn_y = self.y_train[ nn_index[:self.n_neighbors] ].ravel()
            
            # 4.统计类别中出现频率最高的那个,赋给y_pred[i]
            # bincount求的是每个值出现的次数,必须传入的是整数类型
            y_pred[i] =  np.argmax(np.bincount(nn_y))
            
           # print(i,'---',x_test)
            
        return y_pred

3 测试

# 定义一个实例
knn = Knn(n_neighbors=3)

# 训练模型 
knn.fit(x_train,y_train)
# 传入测试数据,做预测
y_pred = knn.predict(x_test)

# 求出预测准确率
accuracy = accuracy_score(y_test,y_pred)

print("预测准确率:",accuracy)

预测准确率: 0.9333333333333333

4 分别测试

# 测试不同的距离计算方法和K值对准确率的影响

# 定义一个实例
knn = Knn()
# 训练模型 
knn.fit(x_train,y_train)


#保存结果list 
result_list = []

# 针对不同的参数选取,做预测 
for p in [1,2]:
    knn.dist_func = manhadun if p==1 else oushi
    
    #考虑不同的k取值 
    #步长为2,避免偶数值d
    for k in range(1,10,2):
        knn.n_neighbors = k 
        # 传入测试数据,做预测
        y_pred = knn.predict(x_test)
        # 求出预测准确率
        accuracy = accuracy_score(y_test,y_pred)
        result_list.append([k,'manhadun' if p==1 else 'oushi',accuracy])
        
df = pd.DataFrame(result_list,columns=['k','距离函数','预测准确率'])

df

04. k近邻(k-nearest neighbour,KNN )分类鸢尾花_第4张图片

 

你可能感兴趣的:(机器学习,python,机器学习,深度学习)