Knn 算法
邻近算法,或者说K最邻近(KNN,K-NearestNeighbor)分类算法是数据挖掘分类技术中最简单的方法之一。
所谓K最近邻,就是K个最近的邻居的意思,说的是每个样本都可以用它最接近的K个邻近值来代表。
近邻算法就是将数据集合中每一个记录进行分类的方法
-
图解
》存在w1,w2,w3三种可能性结果 》Knn 算法。处理给定预测数据Xu,计算出该预测数据属于哪一类结果的可能性。
方式1: 1:计算[预测数据]到所有训练集数据的距离 2:指定K值 取前K个距离最近的数据 3:评估最近的K个 到各个预测结果的概率 。便可预测数据的类别 4:调整K值 重复2,3步骤。以得到合适和K和预测的准确性的平衡 import numpy as np from sklearn import datasets from sklearn.model_selection import train_test_split # 读取iris数据 iris = datasets.load_iris() # 数据源处理 # data 和 target 进行合并 iris_data = np.hstack((iris.data, iris.target.reshape(-1, 1))) # 拆分数据为 训练集和测试集 train, test = train_test_split(iris_data, test_size=0.2) # 指定K值 K = 5 def forecast_data(item): forecast = item[:-1] distance_arr = [] for data in train: target = data[-1] current = data[:-1] # 计算预测数据到训练数据的距离 distance = np.sqrt(np.sum((current - forecast) ** 2)) distance_arr.append([distance, target]) distance_arr.sort(key=lambda item: item[0], reverse=False) # 取得距离最近的前K个数据 use_data = distance_arr[0:K] result = np.array([0, 0, 0]) for index in range(K): if use_data[index][1] == 0.0: result[0] = result[0]+1 elif use_data[index][1] == 1.0: result[1] = result[1]+1 elif use_data[index][1] == 2.0: result[2] = result[2]+1 # 得到预测结果 result = np.stack((np.array([0, 1, 2]), result), axis=1).tolist() result.sort( key=lambda item: item[1], reverse=True) return result[0][0] # if __name__ == '__main__': success, fail = 0, 0 for item in test: exec = item[-1] forecast = forecast_data(item) if exec == forecast: success += 1 else: fail += 1 print('样本总数:', len(iris.data),'训练样本:',len(train),'测试样本:',len(test)) print('success:', success, 'fail:', fail,'预测成功概率:',success/(success+fail)) # 样本总数: 150 训练样本: 120 测试样本: 30 # success: 28 fail: 2 预测成功概率: 0.9333333333333333
方式2( 算法不一致 这里对数据进行加权后 计算概率) 1:计算[预测数据]到所有训练集数据的距离 2:评估数据 对各个数据进行加权计算 越近的数据权重越高。 3:评估最近的K个 到各个预测结果的概率 。便可预测数据的类别 import numpy as np from sklearn import datasets from sklearn.model_selection import train_test_split iris = datasets.load_iris() # 数据源处理 # data 和 target 进行合并 iris_data = np.hstack((iris.data, iris.target.reshape(-1, 1))) # 拆数据 train, test = train_test_split(iris_data, test_size=0.2) # 权重计算 给定距离得到各个距离的权重 def weights(distances): # print(distances.shape) # 上面方式一 为 return np.ones(distances.shape) 就和方式一一样 # 权重直接影响预测的准确性 distance_max = np.sum(distances) result = np.zeros(distances.shape) for index in range(len(distances)): result[index] = (distance_max - distances[index] ) / distance_max return result def forecast_data2(item, K=5): forecast = item[:-1] # print(train.shape,len(train)) distance_arr = [] for data in train: target = data[-1] current = data[:-1] distance = np.sqrt(np.sum((current - forecast) ** 2)) distance_arr.append([distance, target]) distance_arr.sort(key=lambda item: item[0], reverse=False) distance_list = distance_arr[0:K] # 计算权重 distance_list, result_list = [ np.ravel(item) for item in np.hsplit(np.array(distance_list), 2)] weights_arr = weights(distance_list) # 通过权重算出概率权重 result = np.array([0.0, 0.0, 0.0]) for index in range(K): target = result_list[index] wei = weights_arr[index] print(target, wei) if target == 0.0: result[0] = result[0]+wei elif target == 1.0: result[1] = result[1]+wei elif target == 2.0: result[2] = result[2]+wei result = np.stack((np.array([0, 1, 2]), result), axis=1).tolist() result.sort(key=lambda item: item[1], reverse=True) return result[0][0] if __name__ == '__main__': success, fail = 0, 0 for item in test: exec = item[-1] # Knn 算法之二 加权算法 forecast = forecast_data2(item, K=5) if exec == forecast: success += 1 else: fail += 1 print('样本总数:', len(iris.data), '训练样本:', len(train), '测试样本:', len(test)) print('success:', success, 'fail:', fail, '预测成功概率:', success/(success+fail)) # 样本总数: 150 训练样本: 120 测试样本: 30 # success: 29 fail: 1 预测成功概率: 0.9666666666666667
方式3 使用现有KNN模型进行训练 from sklearn.neighbors import KNeighborsClassifier # 使用 KNeighborsClassifier 对iris 数据进行Knn算法预测 # n_neighbors: int, 可选参数(默认为 5) # weights(权重): str or callable(自定义类型), 可选参数(默认为 ‘uniform’) # 用于预测的权重函数。可选参数如下: # - ‘uniform’ : 统一的权重. 在每一个邻居区域里的点的权重都是一样的。 # - ‘distance’ : 权重点等于他们距离的倒数。使用此函数,更近的邻居对于所预测的点的影响更大。 # - [callable] : 一个用户自定义的方法,此方法接收一个距离的数组,然后返回一个相同形状并且包含权重的数组。 # algorithm(算法): {‘auto’, ‘ball_tree’, ‘kd_tree’, ‘brute’}, 可选参数(默认为 'auto') # 计算最近邻居用的算法: # - ‘ball_tree’ 使用算法[BallTree](http://scikit-learn.org/stable/modules/generated/sklearn.neighbors.BallTree.html#sklearn.neighbors.BallTree) # - ‘kd_tree’ 使用算法[KDTree](http://scikit-learn.org/stable/modules/generated/sklearn.neighbors.KDTree.html#sklearn.neighbors.KDTree) # - ‘brute’ 使用暴力搜索. # - ‘auto’ 会基于传入[fit](http://scikit-learn.org/stable/modules/generated/sklearn.neighbors.KNeighborsClassifier.html#sklearn.neighbors.KNeighborsClassifier.fit)方法的内容,选择最合适的算法。 # 注意 : 如果传入fit方法的输入是稀疏的,将会重载参数设置,直接使用暴力搜索。 # leaf_size(叶子数量): int, 可选参数(默认为 30) # 传入BallTree或者KDTree算法的叶子数量。此参数会影响构建、查询BallTree或者KDTree的速度,以及存储BallTree或者KDTree所需要的内存大小。 此可选参数根据是否是问题所需选择性使用。 # p: integer, 可选参数(默认为 2) # 用于Minkowski metric([闵可夫斯基空间](https://zh.wikipedia.org/wiki/%E9%96%94%E8%80%83%E6%96%AF%E5%9F%BA%E6%99%82%E7%A9%BA))的超参数。p = 1, 相当于使用[曼哈顿距离](https://zh.wikipedia.org/wiki/%E6%9B%BC%E5%93%88%E9%A0%93%E8%B7%9D%E9%9B%A2) (l1),p = 2, 相当于使用[欧几里得距离](https://zh.wikipedia.org/wiki/%E6%AC%A7%E5%87%A0%E9%87%8C%E5%BE%97%E8%B7%9D%E7%A6%BB)(l2) 对于任何 p ,使用的是[闵可夫斯基空间](https://zh.wikipedia.org/wiki/%E9%96%94%E8%80%83%E6%96%AF%E5%9F%BA%E6%99%82%E7%A9%BA)(l_p) # metric(矩阵): string or callable, 默认为 ‘minkowski’ # 用于树的距离矩阵。默认为[闵可夫斯基空间](https://zh.wikipedia.org/wiki/%E9%96%94%E8%80%83%E6%96%AF%E5%9F%BA%E6%99%82%E7%A9%BA),如果和p=2一块使用相当于使用标准欧几里得矩阵. 所有可用的矩阵列表请查询 DistanceMetric 的文档。 # metric_params(矩阵参数): dict, 可选参数(默认为 None) # 给矩阵方法使用的其他的关键词参数。 # n_jobs: int, 选参数(默认为 1) # 用于搜索邻居的,可并行运行的任务数量。如果为-1, 任务数量设置为CPU核的数量。不会影响[fit](http://scikit-learn.org/stable/modules/generated/sklearn.neighbors.KNeighborsClassifier.html#sklearn.neighbors.KNeighborsClassifier.fit)方法。 from sklearn import datasets from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score import numpy as np iris_data = datasets.load_iris() data_all = iris_data.data target_all = iris_data.target.reshape(-1, 1) data = np.hstack((data_all, target_all)) # 数据拆分 train, test = train_test_split(data, test_size=0.2) ''' n_neighbors 对于值 algorithm:指定算法 weights 权重函数 ''' knn = KNeighborsClassifier(n_neighbors=3) train_X = train[:, :4] train_Y = train[:, -1] # 训练 knn.fit(train_X, train_Y) # 预测 test_X = test[:, :4] test_y = test[:, -1] predict_result = knn.predict(test_X) print('样本总数:', len(data_all), '训练样本:',len(train), '测试样本:', len(test)) print('预测成功概率:', accuracy_score(test_y, predict_result)) 样本总数: 150 训练样本: 120 测试样本: 30 预测成功概率: 0.9333333333333333