##使用NumPy从头开始进行K最近邻分类


##使用NumPy从头开始进行K最近邻分类
本文插图

在这篇文章中 , 我将实现K最近邻(KNN) , 这是一种机器学习算法 , 可用于分类和回归 , 它属于监督学习算法的范畴 。 它对标记的数据集进行操作 , 并预测测试数据的类别(分类)或数值(回归) 。
我将使用NumPy实现它 , 并将使用其他库来实现数据可视化 。
import numpy as np from sklearn.datasets import make_classification我们首先导入库和函数:

  • numpy:它将被用于多维数组的数值计算 , 因为我们正在处理高维向量 。
  • make_classification:我们将使用它来创建我们的分类数据集 。 我们可以决定所需的类和特征的数量 , 是否要对样本进行聚类等 。
def euclidian_distance(a, b): return np.sqrt(np.sum((a-b)**2, axis=1))在KNN算法中 , 我们需要一个函数来计算训练数据点与我们想要分类的数据之间的距离 。 在这里 , 我选择了欧氏距离 , 因为它在机器学习应用中被广泛使用 。 可以尝试使用其他距离度量 , 如曼哈顿距离、Chebychev距离等 。
def kneighbors(X_test, return_distance=False): n_neighbors = 5 dist = [] neigh_ind = [] point_dist = [euclidian_distance(x_test, X_train) for x_test in X_test] for row in point_dist: enum_neigh = enumerate(row) sorted_neigh = sorted(enum_neigh, key=lambda x: x[1])[:n_neighbors] ind_list = [tup[0] for tup in sorted_neigh] dist_list = [tup[1] for tup in sorted_neigh] dist.append(dist_list) neigh_ind.append(ind_list) if return_distance: return np.array(dist), np.array(neigh_ind) return np.array(neigh_ind)数据点是否接近由上面实现的欧几里得距离函数确定 。 在这里 , 数据点之间距离的实际值并不重要 , 我们感兴趣的是这些距离的顺序 。
在训练过程之前 , 我们选择一个数字作为我们的超参数(k) 。 因此 , 例如 , 当k=5时 , 我们指的是前5个最近的数据点 。
在上面的kneighbors函数中 , 我们找到测试数据集(我们要分类的数据点)中的每个点与数据集其余部分(即训练数据)之间的距离 。 我们将这些距离存储在point_dist中 , 其中每一行对应一个测试数据点到所有训练数据之间的距离列表 。 我们遍历每一行 , 对其进行枚举 , 然后根据距离对它排序 。 我们枚举每一行的原因是 , 我们不想丢失用来计算距离的训练数据点的索引 , 因为我们将在以后引用它们 。
sorted_neigh包含测试数据点的前k个最近邻 , 并且根据其欧氏距离对它们进行排序 。 然后 , 我们从sorted_neigh中提取索引和距离值并返回它们 。
def predict(X_test, weights='uniform'): class_num = 3 if weights=='uniform': neighbors = kneighbors(X_test) y_pred = np.array([np.argmax(np.bincount(y_train[neighbor])) for neighbor in neighbors]) return y_pred if weights=='distance': dist, neigh_ind = kneighbors(X_test, return_distance=True) inv_dist = 1/dist mean_inv_dist = inv_dist / np.sum(inv_dist, axis=1)[:, np.newaxis] proba = [] for i, row in enumerate(mean_inv_dist): row_pred = self.y_train[neigh_ind[i]] for k in range(class_num): indices = np.where(row_pred==k) prob_ind = np.sum(row[indices]) proba.append(np.array(prob_ind)) predict_proba = np.array(proba).reshape(X_test.shape[0], class_num) y_pred = np.array([np.argmax(item) for item in predict_proba]) return y_pred找到k个最近邻后 , 我们尝试预测我们的测试数据点所属的类 。 在这里 , 我们有k个neighbors , 每个neighbor在决定类别标签时都有投票权 。 但是 , 投票机制可能会根据所选标准而有所不同 。 在上面的predict函数中 , 如果权重被选择为一致的 , 则意味着每个neighbor在决定类别标签时都具有相等的投票权重 , 而与他们的距离无关 。


推荐阅读