knn分类代码实现(超详解)

本文未赘述原理,觉得知道knn的优秀的同志们都有一定的了解,直接上代码,本代码作为一个参考,希望大家能够结合本人的代码自己去做一遍,虽然可以直接调knn或有数据集,本文呈现的更多的是底层。

1.创建knn.py

# 定义一个knn函数,后期方便调用.
class KNN(object):
    def __init__(self,k=3):   # 定义内置函数,方便自己传参,默认k值为3
        self.k = k  # 用于整个函数可以使用k值。
    def fit(self,x,y):
        # 用于后期的模型计算,输入训练集目标数据以及训练数据x。
        self.x = x
        self.y = y       # 用于后期整个函数调用
    def _square_distance(self,v1,v2):
        # 用于计算距离,用的最简单的欧式距离
        return np.sum(np.square(v1-v2))  # 计算欧式距离  暂时未弄清楚其欧式距离的的代码实现的意思
    def _vote(self,ys):
        # 不知此函数的作用,先复现,后期再进行进一步的调查。估计应该是权值的计算
        ys_unique = np.unique(ys)   # 进行数据的去重,numpy具有神奇的传说。科学计算库
        vote_dict = {}  # 定义一个空字典
        for y in ys: # 进行ys的遍历
            if y not in vote_dict.keys():
                vote_dict[y] = 1  # 通过遍历将每个值进行计算次数
            else:
                vote_dict[y]+=1   # 此处证明自己的对此函数的思想的错误,此函数用于对该圈进行详细记录个数,既然去重了,记录还有何用,需进一步商榷
        sorted_vote_dict = sorted(vote_dict.items(), key=operator.itemgetter(1), reverse=True)
        return sorted_vote_dict[0][0]   # 将已经记好的数进行一个自大而小的排列(则是一个降序排序),若reverse是false,则是自小而大.(升序排序)

    def predict(self,x):
        y_pred = []   # 我们定义一个预测函数,将训练集输入
        # 定义一个空集合,用于y_pred(预测)
        for i in range(len(x)):
            # 进行遍历,得到x的长度,range是一个从一开始,直到x,步长为1
            dist_arr = [self._square_distance(x[i],self.x[j]) for j in range(len(self.x))]  # 不太清楚此步骤的目的于作用,回过头来再想
            sorted_index=np.argsort(dist_arr)  # 通过pandas库,进行升序排列,并输出值的索引.
            top_k_index = sorted_index[:self.k] # 不太明白其意思
            y_pred.append(self._vote(ys=self.y[top_k_index])) # 调用了_vote函数,属于自身调用,去进行分类
        return np.array(y_pred)
    def score(self,y_true=None,y_pred=None):   #不太明白此函数的功能
        if y_true is None and y_pred is None:
            y_pred = self.predict(self.x)     # 处理特殊情况,x与y都为空时
            y_true = self.y                   # 此函数是用于计算我们用knn进行预测与其真实值进行一个比较的.
        score = 0.0
        for i in range(len(y_true)):
            if y_true[i] == y_pred[i]:
                score += 1
        score/= len(y_true)
        return score

2.调用knn.py


# 本程序用于生成随机的训练样本数据并调用knn进行分类,并推测出我们的计算精度p
# 对数组以及矩阵进行基本的运算
import numpy as np
import matplotlib.pyplot as plt  # python的绘图库
from  knn import *

np.random.seed(314)  # 生成随机数
data_size_1 = 300
x1_1 = np.random.normal(loc=5.0, scale=1.0,size=data_size_1)   # 正态分布,均值,标准差,以及可选参数
x2_1 = np.random.normal(loc=4.0,scale=1.0,size=data_size_1)
y_1 = [0 for _ in range(data_size_1)]

data_size_2 = 400
x1_2 = np.random.normal(loc=10.0, scale=2.0, size=data_size_2)
x2_2 = np.random.normal(loc=8.0, scale=2.0, size=data_size_2)
y_2 = [1 for _ in range(data_size_2)]

x1 = np.concatenate((x1_1, x1_2), axis=0)  # 对数据进行合并
x2 = np.concatenate((x2_1, x2_2), axis=0)   # 一般自己能找到数据的就没必要随机生成数据
x = np.hstack((x1.reshape(-1, 1), x2.reshape(-1, 1)))    # reshap(-1,1) 列为1,行固定,以列为一做标志去分。hstack是一个合并数组
y = np.concatenate((y_1, y_2), axis=0)   # 将y数据进行合并

data_size_all = data_size_2+data_size_1
shuffled_index = np.random.permutation(data_size_all)   # 对数据进行打乱
x = x[shuffled_index]
y = y[shuffled_index]

split_index = int(data_size_all*0.7)  # 进行数据集的拆分
x_train = x[: split_index]  # 训练集占百分之七十
y_train = y[: split_index]
x_test = x[split_index:]
y_test = y[split_index:]

# 数据可视化
plt.scatter(x_train[:, 0], x_train[:, 1], c=y_train, marker='.')   # 散点图的绘制
plt.show()
plt.scatter(x_test[:, 0], x_test[:, 1], c=y_test, marker='.')
plt.show()

# 数据归一化
x_train = (x_train - np.min(x_train,axis=0)) / (np.max(x_train,axis=0)-np.min(x_train,axis=0))
x_test = (x_test - np.min(x_test,axis=0)) / (np.max(x_test,axis = 0)-np.min(x_test,axis= 0))  # 用的是minmax归一化

# 进行knn分类
clf = KNN(k=3)
clf.fit(x_train, y_train)
print('train accuracy: {:.3}'.format(clf.score()))

y_test_pred = clf.predict(x_test)
print('test accuracy: {:.3}'.format(clf.score(y_test, y_test_pred)))

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