K近邻(K-Nearest Neighbors,简称KNN)算法
K近邻(K-Nearest Neighbors,简称KNN)算法是一种基本的机器学习算法,主要用于分类和回归问题。以下是对KNN算法的详细介绍:
1. 定义和原理
定义:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。
原理:基于类比原理,通过比较训练元组和测试元组的相似度来学习。具体来说,KNN将训练元组和测试元组看作是n维空间内的点,给定一条测试元组,搜索n维空间,找出与测试元组最相近的k个点(即训练元组),最后取这k个点中的多数类作为测试元组的类别。
2. 关键要素
K值的选择:K是KNN算法中的一个重要参数,表示需要考虑的邻居数量。K值的选择会影响算法的准确性和性能。通常,K值通过实验确定,取分类误差率最小的K值。
距离度量:在KNN算法中,相似度通常通过距离来度量。常用的距离度量方法包括欧几里得距离和曼哈顿距离。
欧几里得距离:两点之间的直线距离,计算公式为d(x,y)=√(∑(xi−yi)^2)。
曼哈顿距离:两点在标准坐标系上的绝对轴距总和,计算公式为d(x,y)=∑|xi−yi|。
3. 算法流程
准备数据:对数据进行预处理,包括数值属性规范化、缺失值处理等。
选用数据结构:选择合适的数据结构存储训练数据和测试元组。
设定参数:设定K值等参数。
搜索最近邻:对于每个测试元组,在训练数据集中搜索最近的K个邻居。
分类:根据K个最近邻的类别标签,通过“少数服从多数”的原则确定测试元组的类别。
4. 优缺点
优点:
简单易懂,易于实现。
无需训练(不需要花费时间构建模型)。
特别适合多分类问题,对异常值不敏感。
缺点:
对K值敏感,K值的选择会影响分类结果。
在高维空间中可能效果不佳,因为距离度量可能失去意义。
需要存储所有训练数据,计算量大。
5. 应用领域
KNN算法被广泛应用于各种领域,如手写数字识别、电影推荐系统、股票市场预测、医学诊断、文本分类、信用评估、图像处理等。
6.Java实现
在Java中实现K近邻(K-Nearest Neighbors, KNN)算法,通常涉及以下几个步骤:
准备数据集:这通常是一个二维数组或对象列表,其中每个对象都有特征向量和标签。
计算距离:对于给定的查询点,计算它与数据集中每个点的距离。
选择K个最近邻:根据计算出的距离,选择K个最近的邻居。
预测:根据K个最近邻的标签进行投票,以确定查询点的类别。
以下是一个简单的Java实现示例:
import java.util.*; public class KNN { // 假设数据集是一个二维数组,其中每行是一个样本,每列是一个特征 // 最后一列是标签(例如,对于二分类问题,可以使用0和1作为标签) private double[][] dataset; // 构造函数,用于初始化数据集 public KNN(double[][] dataset) { this.dataset = dataset; } // 欧几里得距离 public static double euclideanDistance(double[] point1, double[] point2) { double sum = 0; for (int i = 0; i < point1.length; i++) { sum += Math.pow(point1[i] - point2[i], 2); } return Math.sqrt(sum); } // 预测查询点的类别 public int predict(double[] query, int k) { // 初始化一个存储距离和索引的优先级队列(最小堆) PriorityQueue<DistanceIndex> pq = new PriorityQueue<>(Comparator.comparingDouble(a -> a.distance)); // 计算查询点与数据集中每个点的距离,并将距离和索引添加到最小堆中 for (int i = 0; i < dataset.length; i++) { double distance = euclideanDistance(query, dataset[i]); pq.offer(new DistanceIndex(distance, i)); // 如果堆的大小超过了K,则移除堆顶元素(即最远的点) if (pq.size() > k) { pq.poll(); } } // 创建一个用于存储邻居标签的映射 Map<Integer, Integer> labelCounts = new HashMap<>(); // 对K个最近邻的标签进行计数 while (!pq.isEmpty()) { DistanceIndex di = pq.poll(); int label = (int) dataset[di.index][dataset[di.index].length - 1]; // 假设最后一列是标签 labelCounts.put(label, labelCounts.getOrDefault(label, 0) + 1); } // 找到最常见的标签并返回 int mostCommonLabel = Collections.max(labelCounts.entrySet(), Map.Entry.comparingByValue()).getKey(); return mostCommonLabel; } // 用于存储距离和索引的类 static class DistanceIndex { double distance; int index; DistanceIndex(double distance, int index) { this.distance = distance; this.index = index; } } // 主函数,用于测试 public static void main(String[] args) { // 示例数据集(包含特征和标签) double[][] dataset = { {2.5, 1.2, 0}, {1.8, 1.1, 0}, {3.0, 4.0, 1}, {5.1, 3.5, 1} }; KNN knn = new KNN(dataset); // 示例查询点 double[] query = {1.9, 1.4}; // 使用K=3进行预测 int predictedLabel = knn.predict(query, 3); System.out.println("Predicted label for query " + Arrays.toString(query) + ": " + predictedLabel); } }
注意:这个示例假设数据集的最后一列是标签,并且标签是整数(例如,对于二分类问题,可以使用0和1作为标签)。此外,这个示例使用了欧几里得距离作为距离度量,但你可以根据需要选择其他距离度量方法。
其他相关文章
常用的搜索算法之二分搜索(Binary Search)常用的搜索算法之哈希搜索(Hashing Search)
常用的搜索算法之深度优先搜索
层次遍历-Level Order Traversal
常用的搜索算法之线性搜索(Linear Search)
常用的搜索算法之DFS和BFS的区别是什么
Java的图数据结构探索-常用的算法快速入门
什么是有向无环图
数据结构进阶面试题-2023面试题库
常用的搜索算法之迷宫求解问题
树的基本概念
随机搜索(Random Search)
网格搜索法(Grid Search)
余弦相似度(Cosine Similarity)
皮尔逊相关系数
曼哈顿距离(Manhattan Distance)
欧氏距离(Euclidean Distance)
Jaccard相似度
修正余弦相似度(Adjusted Cosine Similarity)
皮尔逊χ²检验(Pearson's Chi-squared Test)
互信息(Mutual Information, MI)
Tanimoto系数(Tanimoto Coefficient)
切比雪夫距离(Chebyshev Distance)
汉明距离(Hamming Distance)
朴素贝叶斯分类算法(Naive Bayes Classification Algorithm