本文未赘述原理,觉得知道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)))
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)