0
点赞
收藏
分享

微信扫一扫

KNN-k近邻算法

毅会 2022-01-20 阅读 32

KNN-k近邻算法

k近邻算法基础

解决分类问题

问题引入:
假设我们给出肿瘤大小作为横轴,发现肿瘤时间作为纵轴的坐标图。
其中红色代表为良性肿瘤,蓝色表示为恶性肿瘤:
在这里插入图片描述
现在,我们想根据新给出的一个肿瘤大小和发现时间的数据,来预测肿瘤是阳性还是阴性(图中绿色的点):
在这里插入图片描述

在这个问题中,我们需要通过已有的8个数据(红,蓝点的分布情况)来判断新给出的数据(绿点)是良性还是恶性肿瘤

想要用KNN解决分类问题也十分简单:

取绿色点周围最近的k(取值自选)个点,颜色相同数最多点的颜色即为最终结果

也就是说,k近邻的判断依据就是:两个样本如果足够相似,它们就有更高的几率属于同一个类别

在Notebook中实现

数据的准备

  • 先创建样本数据数组 raw_data, raw_data_y
    在这里插入图片描述
  • 再将数据集转换为numpy中的array数组
    在这里插入图片描述
  • 将样本数据集与待预测数据绘制散点图
    在这里插入图片描述

KNN过程

  • 先计算所有样本数据点到待预测数据点的距离distances(向量)
    其中,计算两点间的距离我们使用欧拉距离来计算:
    在这里插入图片描述
    在这里插入图片描述
  • 再找出distances中距离中前k个最小的距离点的索引(这里将k=6)
    在这里插入图片描述
  • 然后通过Counter投票找出前k个中最多的结果,就是我们的分类结果
    在这里插入图片描述

通过函数封装来实现

代码:

import numpy as np
from math import sqrt
from collections import Counter


def kNN_classify(k, X_train, y_train, x):
    assert 1 <= k <= X_train.shape[0], "k must be valid"
    assert X_train.shape[0] == y_train.shape[0], \
        "the size of X_train must equal to the size of y_train"
    assert X_train.shape[1] == x.shape[0], \
        "the feature number of x must be equal to X_train"

    distances = [sqrt(np.sum((x_train-x)**2)) for x_train in X_train]
    nearest = np.argsort(distances)

    topK_y = [y_train[i] for i in nearest[:k]]
    votes = Counter(topK_y)

    return votes.most_common(1)[0][0]

再通过Notebook中的魔法命令就可以直接使用了
在这里插入图片描述

scikit-learn 中的机器学习封装

设计机器学习的大致思想:
在这里插入图片描述
其中,对于KNN算法来说,喂入的训练集就是模型

使用scikit-learn中的KNN

引入sklearn包后首先需要传入设定的k值
在这里插入图片描述
再传入样本数据集进行拟合
在这里插入图片描述
进行预测前必须将需要预测的数据转化为矩阵形式传入,否则会报错
在这里插入图片描述

使用自己封装好的kNN

代码如下:

import numpy as np
from math import sqrt
from collections import Counter


class KNNClassifier:
    def __init__(self, k):
        assert k >= 1, "k must be valid"
        self.k = k
        self._X_train = None
        self._y_train = None

    def fit(self, X_train, y_train):
        assert X_train.shape[0] == y_train.shape[0], \
            "the size of X_train must be equal to the size of y_train"
        assert self.k <= X_train.shape[0], \
            "the size of X_train must be at least k."

        self._X_train = X_train
        self._y_train = y_train
        return self

    def predict(self, X_predict):
        assert self._X_train is not None and self._y_train is not None, \
            "must fit before predict!"
        assert X_predict.shape[1] == self._X_train.shape[1], \
            "the feature number of X_predict must be equal to X_train"

        y_predict = [self._predict(x) for x in X_predict]
        return np.array(y_predict)

    def _predict(self, x):
        assert x.shape[0] == self._X_train.shape[1], \
            "the feature number of x must be equal to X_train"

        distances = [sqrt(np.sum((x_train-x) ** 2)) for x_train in self._X_train]

        nearest = np.argsort(distances)

        topK_y = [self._y_train[i] for i in nearest[:self.k]]
        votes = Counter(topK_y)

        return votes.most_common(1)[0][0]

    def __repr__(self):
        return "kNN(k=%d)" % self.k

同样地,我们再使用魔法命令运行我们自己写的kNN
在这里插入图片描述
即可成功运行

训练、测试数据集

在实际问题中,除了设计出机器学习模型,我们还要去测试这种学习模型的准确率。
那么有什么方法能够判断出机器训练出的模型的准确率有多少呢?
我们可以从给出的训练数据集中抽出一部分,作为测试数据
在这里插入图片描述
根据这样的思想,我们可以测试一下我们自己刚刚编写的kNN的准确率

测试算法的准确率

这里我们使用sklearn中的鸢尾花数据集

首先加载鸢尾花数据集,将x,y特征值分别存入X,Y中
在这里插入图片描述

在这里插入图片描述

打乱数据的索引
在这里插入图片描述
计算测试数据集的容量(这里定为总样本的20%)
在这里插入图片描述
将训练与测试数据集索引分离
在这里插入图片描述
根据分离好的索引,分别求出x,y
在这里插入图片描述

编写我们自己的分离数据函数

代码如下:

import numpy as np


def train_test_split(X, y, test_ratio=0.2, seed=None):
    assert X.shape[0] == y.shape[0], \
        "the size of X must be equal to the size of y"
    assert 0.0 <= test_ratio <= 1.0, \
        "test_train must be valid"

    if seed:
        np.random.seed(seed)

    shuffled_indexes = np.random.permutation(len(X))

    test_size = int(len(X) * test_ratio)
    test_indexes = shuffled_indexes[:test_size]
    train_indexes = shuffled_indexes[test_size:]

    X_train = X[train_indexes]
    y_train = y[train_indexes]

    X_test = X[test_indexes]
    y_test = y[test_indexes]

    return X_train, X_test, y_train, y_test

测试一下编写的代码:
在这里插入图片描述
同样可以根据这种原理,算出我们编写程序的准确率:
在这里插入图片描述

使用sklearn中封装好的测试模型

在这里插入图片描述

分类准确度

我们通过sklearn库中的手写数据库中的数据来验证一下算法的准确度

首先,我们引入sklearn的手写数据集
在这里插入图片描述
先用x,y分别接收一下数据
在这里插入图片描述
我们可以取出一部分数据查看一下
在这里插入图片描述
在这里插入图片描述
我们随意取出一个位置(索引为666)的数据进行绘图查看一下
在这里插入图片描述

接下来,计算我们训练好的模型的准确率就很简单了。
先将我们通过模型预测的结果集设为y_train,测试集对应结果命名为y_test。计算y_train == y_test 的个数,该个数与y_test总个数的比值就是我们要求的精确度比值了

代码如下:

import numpy as np


def accuracy_score(y_true, y_predict):
    #  计算y_true和y_predict之间的准确率
    assert y_true.shape[0] == y_predict.shape[0], \
        "the size of y_true must be equal to the size of y_predict"

    return sum(y_true == y_predict) / len(y_true)

我们在Notebook上运行一下

在这里插入图片描述

sklearn中的accuracy_score

sklearn库中的使用方法基本和我们自己实现的方法相似
在这里插入图片描述

举报

相关推荐

0 条评论