KNN算法原理及实现鸢尾花分类

分类:机器学习、Python、分类算法

一:KNN算法原理及常见问题

1. KNN算法的背景和应用场景

KNN(K-Nearest Neighbors)算法是一种常用的监督学习算法,属于分类算法。它的基本思想是通过测量样本之间的距离来判断它们的相似性,然后选择与新样本最相似的 K 个样本作为邻居,根据这些邻居的类别来确定新样本的类别。
KNN 算法在图像识别、文本分类、推荐系统等领域都有广泛的应用。例如,在图像识别中,可以使用 KNN 算法对图像进行分类;在推荐系统中,可以使用 KNN 算法对用户进行相似性度量,从而推荐相似用户喜欢的物品。

2. KNN 算法的主要优点

  • 简单易懂:KNN 算法的思想非常简单,容易理解和实现。
  • 无需训练:KNN 算法是一种基于实例的学习方法,不需要对数据进行训练。
  • 对数据分布没有假设:KNN 算法对数据的分布没有任何假设,因此可以处理各种类型的数据。
  • 适用于非线性问题:KNN 算法可以处理非线性问题,因为它不依赖于数据的线性可分性。

3. KNN 算法的主要缺点

  • 计算量大:在处理大规模数据时,计算所有样本与新样本的距离可能会非常耗时。
  • 需要存储所有训练数据:KNN 算法需要存储所有的训练数据,以便在进行预测时可以计算距离。
  • 对噪声敏感:KNN 算法对噪声非常敏感,因为噪声样本可能会影响邻居的选择。
  • 选择合适的 K 值:选择合适的 K 值对于 KNN 算法的性能非常重要,但选择合适的 K 值并不容易。

4.如何选择K值

K值是KNN算法中重要的超参数,会影响算法的性能。以下是一些选择 K 值的常用方法:

  • 手动选择:根据经验或试验来选择 K 值。
  • 交叉验证:使用交叉验证来选择最佳的 K 值。
  • 肘部法则:通过绘制不同 K 值下的错误率曲线,选择错误率开始下降的点作为最佳的 K 值。

5.常用的距离度量

  • 欧几里得距离(Euclidean distance):是最常用的距离度量之一,它度量两个样本在空间中的距离。
    d ( x , y ) = ( x 1 − y 1 ) 2 + ( x 2 − y 2 ) 2 d(x,y)=\sqrt{(x_1-y_1)^2+(x_2-y_2)^2} d(x,y)=(x1y1)2+(x2y2)2
  • 曼哈顿距离(Manhattan distance):是另一种常见的距离度量,它度量两个样本在空间中的曼哈顿距离。
    d ( x , y ) = ∣ x 1 − y 1 ∣ + ∣ x 2 − y 2 ∣ d(x,y)=|x_1-y_1| + |x_2-y_2| d(x,y)=x1y1+x2y2

二:Python 实现 KNN 算法进行鸢尾花分类(sklearn)

from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split


# 加载数据
X, y = load_iris(return_X_y=True)

# 切分数据
X_train,X_test,y_train,y_test = train_test_split(X, y, test_size=0.2, random_state=0)

# 构建模型
my_knn = KNeighborsClassifier(n_neighbors=5)

# 训练模型
my_knn.fit(X_train,y_train)

# 预测模型
y_pred = my_knn.predict(X_test)

acc = (y_pred == y_test).mean() * 100

print(f"准确率为:{acc:.2f}%" )

三:Python 实现 KNN 算法(手动)

import numpy as np
from collections import Counter

class MyKNeighborsClassifier:

    
    # 初始化函数,设置k(n_neighbors)的值为5
    def __init__(self,n_neighbors=5):
        self.n_neighbors = n_neighbors
        

    def fit(self , X ,y):
        # 数据类型转换
        X = np.array(X)
        y = np.array(y)

        # 参数校验
        if X.ndim != 2 or y.ndim != 1 or X.shape[0] != y.shape[0]:
            raise ValueError("输入数据错误")
        self.X = X
        self.y = y

    def pridect(self, X):
        X = np.array(X)
        if X.ndim != 2 or X.shape[1] != self.X.shape[1]:
            raise ValueError("输入数据错误")
        result = []

         # 计算欧氏距离并根据距离排序,选择前k个最近的点
        for x in X:
            distances = np.square(((x-self.X)**2).sum(axis = 1))
            index = np.argsort(distances)[:self.n_neighbors]
            lables = self.y[index]
            # 统计列表中索引出现的次数,取最高频率的值
            aim = Counter(lables).most_common(1)[0][0]
            result.append(aim)
        return np.array(result)

四:小功能实现

1.train_test_split 数据切分功能(部分)手动实现

def my_train_test_split(X,y,test_size=None):
    import numpy as np
    y = np.array([[i] for i in y])
    datas = np.concatenate((X,y),axis = 1)
    np.random.shuffle(datas)
    X = datas[:,0:4]
    y = []
    for i in datas[:,4:]:
        y.append(int(i[0]))
    y = np.array(y)
    if test_size == None:
        test_size = 0.4
    else:
        test_num = int(X.shape[0] * test_size)
        train_num = int(X.shape[0] - test_num)
    X_train = X[:train_num]
    X_test = X[:test_num]
    y_train = y[:train_num]
    y_test = y[:test_num]

    return X_train,X_test,y_train,y_test

2.Python计数器collections.Counter返回索引功能实现

def myCounter(lables):
        """
        返回给定列表中出现次数最多的元素
        eg:lables = [1,1,1,1,2]
        return 1
        """
        count_dict = {}

        for element in lables:
            if element in count_dict:
                count_dict[element] += 1
            else:
                count_dict[element] = 1
            
        max_count = max(count_dict.values())
        for key,value in count_dict.items():
            if value == max_count:
                return key
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值