原生Python实现KNN分类算法,用鸢尾花数据集

实现KNN算法

  • 作业题目

原生Python实现KNN分类算法,用鸢尾花数据集。

  • 算法设计

K最近邻(k-Nearest Neighbor,KNN)的思路:K近邻如果一个样本在特征空间中与k个实例最为相似(即特征空间中最邻近),那么这k个实例中大多数属于哪个类别,则该样本也属于这个类别。其中,计算样本与其他实例的相似性一般采用距离衡量法。离得越近越相似,离得越远越不相似。

原生Python实现KNN分类算法,用鸢尾花数据集_第1张图片

 

如上图所示,k=3,距离绿色样本最近的3个实例中(圆圈内),有两个是红色三角形(正类)、一个是蓝色正方形(负类)。则该样本属于红色三角形(正类)。

k近邻算法的本质:我们知道,一般机器学习算法包括两个过程:训练过程和测试过程。训练过程通过使用机器学习算法在训练样本上迭代训练,得到较好的机器学习模型;测试过程是使用测试数据来验证模型的好坏,通过正确率来呈现。kNN算法的本质是在训练过程中,它将所有训练样本的输入和输出标签(label)都存储起来。测试过程中,计算测试样本与每个训练样本的距离,选取与测试样本距离最近的前k个训练样本。然后对着k个训练样本的label进行投票,票数最多的那一类别即为测试样本所归类。

实现的主要函数:

class KNNClassifier:

def fit(self, X_train, y_train):

    """根据训练数据集X_train和y_train训练kNN分类器"""
def predict(self, X_predict):

    """给定待预测数据集X_predict,返回表示X_predict的结果向量"""
def _predict(self, x):

    """给定单个待预测数据x,返回x的预测结果值"""
求距离
距离排序
def train_test_split(X,y,test_ratio=0.2,seed=None):

    """将数据 X 和 y 按照test_ratio分割成X_train, X_test, y_train, y_test"""
采用切片方式

原生Python实现KNN分类算法,用鸢尾花数据集_第2张图片

  • 有注释的源代码

①KNN.py文件

import numpy as np

from math import sqrt

from collections import Counter

class KNNClassifier:

    def __init__(self, k):

        """初始化kNN分类器"""

        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):

        """根据训练数据集X_train和y_train训练kNN分类器"""

        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):

        """给定待预测数据集X_predict,返回表示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):

        """给定单个待预测数据x,返回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) #升序排列 argsort()这个函数的作用很简单,

# 就是把向量中每个元素进行排序,

# 而它的结果是元素的索引形成的向量例子如下:

#distance------([1,4,3])

#经过distance.argsort()之后的结果是([0,2,1]
        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
 
②model_selection.py文件
import numpy as np

def train_test_split(X,y,test_ratio=0.2,seed=None):

    """将数据 X 和 y 按照test_ratio分割成X_train, X_test, y_train, y_test"""

    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_ration must be valid"

    if seed:

        np.random.seed(seed)

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

    test_size = int(len(X)*test_ratio)

    test_indexes = shuffle_indexes[:test_size]

    train_indexes = shuffle_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

test.py文件

from sklearn.model_selection import train_test_split

import pandas as pd

'''载入鸢尾花数据集'''

'''①导入包'''

#from sklearn import datasets

# iris=datasets.load_iris()

# X=iris.data

# y=iris.target

'''②导入文件'''

iris = pd.read_csv('iris.data', header=None)

X = iris.iloc[0:150, 0:4].values

y = iris.iloc[0:150, 4].values

X_train, X_test, y_train, y_test = train_test_split(X,y)

from KNN import KNNClassifier

my_knn_clf=KNNClassifier(k=3)

my_knn_clf.fit(X_train,y_train)

y_predict=my_knn_clf.predict(X_test)

print(sum(y_predict==y_test))

"""预测准确率"""

print(sum(y_predict==y_test)/len(y_test))
  • 测试用例设计及调试过程截屏

测试用例:

test.py文件

from sklearn.model_selection import train_test_split

import pandas as pd

'''载入鸢尾花数据集'''

'''①导入包'''

#from sklearn import datasets

# iris=datasets.load_iris()

# X=iris.data

# y=iris.target

'''②导入文件'''

iris = pd.read_csv('iris.data', header=None)

X = iris.iloc[0:150, 0:4].values

y = iris.iloc[0:150, 4].values

X_train, X_test, y_train, y_test = train_test_split(X,y)

from KNN import KNNClassifier

my_knn_clf=KNNClassifier(k=3)

my_knn_clf.fit(X_train,y_train)

y_predict=my_knn_clf.predict(X_test)

print(sum(y_predict==y_test))

"""预测准确率"""

print(sum(y_predict==y_test)/len(y_test))

调试:

原生Python实现KNN分类算法,用鸢尾花数据集_第3张图片

 

运行结果:

  • 总结

在这次用Python实现Knn算法的过程中,还挺波折的,由于对python的掌握还不是很熟练,知道KNN的思路,但不知道怎么开始,就在网上搜了相关代码,学习了一下代码中所使用的python有关方法,刚开始只实现了距离计算和排序等功能,将所有测试集当做训练集,然后发现还需要将训练集和测试集分割的功能,在其中使用了python中的切片方法和随机种子,还有预测模型准确率的功能,最后在测试用例中,刚开始导入数据是使用的是导入包方式,最后采用了把鸢尾花数据集下载下来,刚开始导入数据一直出错,然后使用了pandas的方法读入。在这个过程中,虽然刚开始啥都不知道的过程很痛苦,但是问题一个一个解决时,就收获很多。

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