KNN 手写算法

原理:

K近邻
选取欧式距离最近的k个特征点
分类:作为投票,
回归:取均值

KNN算法–优缺点:

优点:
1.思想简单,容易实现,可分类、回归
2.依赖局部近邻,当样本有类域交叉,依然适用
3.对异常数据不敏感,准确率高
缺点:
1.惰性计算,预测时间复杂度高,速度慢
2.存储整个数据集,空间复杂度高
3.样本不均衡,对稀有类别准确率不够高

优化方面

1.特征很多,考虑降维,降低计算复杂度
2.训练时,采用KD树或者对样本预处理,降低搜索近邻时的复杂度

knn分类

import numpy as np
# 鸢尾花数据集
from sklearn.datasets import load_iris
# 数据集切分
from sklearn.model_selection import train_test_split


class KNeighborsClassifier(object):
    """
        自定义分类器
    """

    def __init__(self, n_neighbors=5):
        """
            设置超参数
        """
        self.n_neighbors = n_neighbors

    def fit(self, X, y):
        """
            模型训练 啥也没干
        """
        self.X = np.array(X)
        self.y = np.array(y)

    def predict(self, X):
        """
            模型预测
            1.找k个最近的邻居
            2.统计K个邻居的类别情况
            3.计算出现最多的类别
        """
        X = np.array(X)
        # 如果不是2维 自定义报错
        if X.ndim != 2:
            raise Exception("非二维")
        # 结果列表
        result = []
        for x in X:
            # 一个测试数据 距离 每一个训练集数据的距离 是多少
            # 欧氏距离
            dist = np.sqrt(((self.X - x) ** 2).sum(axis=1))
            # 索引排序 截取排在前面的k个邻居 默认小-大
            args = np.argsort(dist)[:self.n_neighbors]
            # 取出对应的标签     np可以根据索引取出多个
            labels = self.y[args]

            # .tolist()  数组或者矩阵等,转为列表形式
            # .count  统计出现次数
            # 函数式编程:语法 max(x1, key=处理)    key代表x1内的每一个值
            # set()去重 找到类别1、类别2、  计算每个类别出现的次数  选次数最高的 类别
            result.append(max(set(labels), key=labels.tolist().count))
        return np.array(result)


# 加载数据集
X, y = load_iris(return_X_y=True)
# 训练集数据、测试集数据、训练集标签、测试集标签、   数据集分割为 80%训练 20%测试
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.2)
# # print(X_train)
# 构建模型
knn = KNeighborsClassifier(n_neighbors=5)

# 模型训练
knn.fit(X=X_train, y=y_train)

# 模型预测
y_pred = knn.predict(X=X_test)
print(y_pred)
print(y_test)
print(y_pred == y_test)

# 准确率 np格式 使用.mean()求均值  列表不可以
acc = (y_pred == y_test).mean()
print(acc)

knn回归

import numpy as np
# # 波士顿房价预测数据
# from sklearn.datasets import load_boston
# 利福尼亚住房数据集
from sklearn.datasets import fetch_california_housing
# 数据集切分
from sklearn.model_selection import train_test_split


class KNeighborsRegressor(object):
    """
        自定义归回器
    """

    def __init__(self, n_neighbors=5):
        """
            设置超参数
        """
        self.n_neighbors = n_neighbors

    def fit(self, X, y):
        """
            模型训练 啥也没干
        """
        self.X = np.array(X)
        self.y = np.array(y)

    def predict(self, X):
        """
            模型预测
            1.找k个最近的邻居
            2.统计K个邻居的均值
        """
        X = np.array(X)
        # 如果不是2维 自定义报错
        if X.ndim != 2:
            raise Exception("非二维")
        # 结果列表
        result = []
        for x in X:
            # 一个测试数据 距离 每一个训练集数据的距离 是多少
            # 欧氏距离
            dist = np.sqrt(((self.X - x) ** 2).sum(axis=1))
            # 索引排序 截取排在前面的k个邻居 默认小-大
            args = np.argsort(dist)[:self.n_neighbors]
            # 取出对应的标签     np可以根据索引取出多个
            labels = self.y[args]
            # 求均值
            result.append(labels.mean())
        return np.array(result)


# 加载数据集
X, y = fetch_california_housing(return_X_y=True)
# 训练集数据、测试集数据、训练集标签、测试集标签、   数据集分割为 80%训练 20%测试
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.2)
# # print(X_train)
# 构建模型
knn = KNeighborsRegressor(n_neighbors=5)

# 模型训练
knn.fit(X=X_train, y=y_train)

# 模型预测
y_pred = knn.predict(X=X_test)
print(y_pred)
print(y_test)

# 准确率 np格式 使用.mean()求均值  列表不可以
mse = ((y_pred - y_test) ** 2).mean()
print(mse)

猜你喜欢

转载自blog.csdn.net/qq_42102546/article/details/123194386