距离度量一般采用 Lp 距离(闵可夫斯基距离),当p=2时,即为欧氏距离,在度量之前,应该将每个属性的值规范化,这样有助于防止具有较大初始值域的属性比具有较小初始值域的属性的权重过大。
其中,k-近邻算法的K 值的选择会对算法的结果产生重大影响:
(1) K值较小(K值的较小就意味着整体模型更加复杂)意味着只有与输入实例较近的训练实例才会对预测结果起作用,但容易发生过拟合;
(2)如果 K 值较大(意味着整体的模型较为简单),优点是可以减少学习的估计误差,但缺点是学习的近似误差增大,这时与输入实例较远的训练实例也会对预测起作用,使预测发生错误。
在实际应用中,K 值一般选择一个较小的数值,通常采用交叉验证的方法来选择最优的 K 值。随着训练实例数目趋向于无穷和 K=1 时,误差率不会超过贝叶斯误差率的2倍,如果K也趋向于无穷,则误差率趋向于贝叶斯误差率。
在一般的案例中,具体实现步骤可以描述为:
(1) 计算已知类别数据集中的点与当前点之间的距离;
(2) 按照距离递增次序排序;
(3) 选取与当前点距离最小的k个点;
(4) 确定前k个点所在类别的出现频率;
(5) 返回前k个点出现频率最高的类别作为当前点的预测分类。
另附python实现的KNN算法算法代码:
def classify_KNN(test_X, train_set, labels, K): rows = train_set.shape[0] diff = tile(test_X, (rows, 1)) - train_set # 这一行利用tile函数将输入样本实例转化为与训练集同尺寸的矩阵 # 便之后的矩阵减法运算 sqDistance = (diff ** 2).sum(axis=1) Distance = sqDistance ** 0.5 sorted_Distance = Distance.argsort() # 对每个训练样本与输入的测试样本求欧几里得距离,即点之间的范数 # 随后按距离由小到大进行排序 classCount = {} for i in range(K): vote_label = labels[sorted_Distance[i]] classCount[vote_label] = classCount.get(vote_label, 0) + 1 #记录距离最小的前K个类,并存放入列表。KEY对应标签,VALUE对应计数 sortedClassCount = sorted(classCount.items(), key = operator.itemgetter(1), reverse=True) return sortedClassCount[0][0]