首页 > 其他分享 >【数据挖掘】K最近邻(K-NN)

【数据挖掘】K最近邻(K-NN)

时间:2024-09-14 21:51:28浏览次数:13  
标签:NN int 类别 算法 最近 数据挖掘 points

目录

一、K最近邻(K-NN)算法概述

二、K最近邻(K-NN)算法优缺点和改进

2.1 K最近邻(K-NN)算法优点

2.2 K最近邻(K-NN)算法缺点

2.3 K最近邻(K-NN)算法改进

三、K最近邻(K-NN)算法实现

3.1 K最近邻(K-NN)算法C语言实现

3.2 K最近邻(K-NN)算法JAVA实现

3.3 K最近邻(K-NN)算法python实现

四、K最近邻(K-NN)算法应用

五、K最近邻(K-NN)算法发展趋势


一、K最近邻(K-NN)算法概述

        K最近邻(K-NN)算法是一种基本的分类与回归方法。它的工作原理是:给定一个训练数据集,对新的输入实例,在训练集中找到与该实例最邻近的K个实例,这K个实例的多数属于某个类别,则该输入实例也属于这个类别。在K-NN算法中,选择合适的K值非常重要,K值过小容易受到噪声的影响,而K值过大则会降低分类的准确性。K-NN算法的优点是简单、易于理解和实现,无需估计参数,无需训练。但其缺点是计算量大,尤其是当样本量大时;另外,对内存的需求也很大,因为它需要存储整个训练数据集。

二、K最近邻(K-NN)算法优缺点和改进

2.1 K最近邻(K-NN)算法优点

        1. 简单易懂:K-NN算法直观且易于实现,不需要对数据进行复杂的训练过程。

        2. 灵活性高:算法适用于多分类问题,且不需要事先设定数据的分布假设。

        3. 实时性好:对于新数据点的预测可以快速进行,因为不需要重新训练模型。

        4. 无参数模型:除了选择邻居数目k外,K-NN算法没有需要调整的参数。

2.2 K最近邻(K-NN)算法缺点

        1. 计算成本高:需要存储所有训练数据,并在预测时计算新数据点与所有训练数据的距离。

        2. 存储需求大:由于需要保存整个训练数据集,对于大数据集来说,存储成本较高。

        3. 对不平衡数据敏感:如果数据集中某一类别的样本数远多于其他类别,可能会导致分类结果偏向多数类。

        4. 对于高维数据效果差:在高维空间中,距离度量(如欧氏距离)变得不那么有效,导致所谓的“维度的诅咒”。

        5. k值选择困难:k值的选择对算法性能有很大影响,但没有统一的规则来确定最佳的k值。

2.3 K最近邻(K-NN)算法改进

        1. 特征选择和降维:通过特征选择或降维技术减少数据的维度,以减轻维度的诅咒问题。

        2. 权重调整:为不同距离的邻居赋予不同的权重,距离近的邻居赋予更大的权重。

        3. 数据预处理:对数据进行标准化或归一化处理,以确保所有特征在距离计算中具有相同的影响力。

        4. 使用有效的索引结构:例如kd树、球树等,以加速最近邻搜索过程。

        5. 自适应k值:根据数据集的特性动态调整k值,例如使用交叉验证来确定最佳的k值。

        6. 结合其他算法:与其他机器学习算法结合,如集成学习方法,以提高分类的准确性和鲁棒性。

三、K最近邻(K-NN)算法实现

3.1 K最近邻(K-NN)算法C语言实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
// 假设这是一个简单的二维点结构
typedef struct {
    double x;
    double y;
} Point;
 
// 假设这是一个简单的二维点集
typedef struct {
    Point *points;
    int length;
} PointSet;
 
// 加载点集数据
PointSet load_point_set(const char *filename) {
    // 实现加载点集数据的逻辑
    PointSet set;
    set.points = NULL;
    set.length = 0;
    // 这里应该是从文件中读取数据并填充set的实现
    return set;
}
 
// 计算距离
double calculate_distance(Point p1, Point p2) {
    return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}
 
// KNN分类
int knn_classify(PointSet trainingSet, Point testPoint, int k) {
    int i;
    int j;
    int *classCount = malloc(sizeof(int) * 2); // 假设有两个类别
    double minDist;
    double dist;
    PointSet sortedSet;
    PointSet nearestNeighbors;
 
    // 初始化classCount
    for (i = 0; i < 2; i++) {
        classCount[i] = 0;
    }
 
    // 对整个训练集排序
    sortedSet.points = malloc(sizeof(Point) * trainingSet.length);
    memcpy(sortedSet.points, trainingSet.points, sizeof(Point) * trainingSet.length);
    // 这里应该是对点集进行排序的逻辑
 
    // 找出k个最近邻
    nearestNeighbors.points = malloc(sizeof(Point) * k);
    nearestNeighbors.length = k;
    for (i = 0; i < k; i++) {
        minDist = calculate_distance(testPoint, sortedSet.points[i]);
        nearestNeighbors.points[i] = sortedSet.points[i];
        for (j = i + 1; j < trainingSet.length; j++) {
            dist = calculate_distance(testPoint, sortedSet.points[j]);
            if (dist < minDist) {
                minDist = dist;
                nearestNeighbors.points[i] = sortedSet.points[j];
            }
        }
    }
 
    // 根据最近邻的类别进行投票
    for (i = 0; i < k; i++) {
        if (nearestNeighbors.points[i].y > 0) {
            classCount[0]++; // 类别0
        } else {
            classCount[1]++; // 类别1
        }
    }
 
    // 返回投票数最多的类别
    free(sortedSet.points);
    free(nearestNeighbors.points);
    return classCount[0] > classCount[1] ? 0 : 1;
}
 
int main() {
    PointSet trainingSet = load_point_set("training_data.txt");
    Point testPoint;
    testPoint.x = 1.0;
    testPoint.y = 1.0;
    int k = 5; // 假设k为5
    int prediction = knn_classify(trainingSet, testPoint, k);
    printf("Prediction: %d\n", prediction);
    return 0;
}

        这个代码实例提供了一个简化的K近邻算法实现的框架。它包括加载点集数据、计算距离、对点集进行排序、找出最近的K个邻居以及基于这些邻居的类别进行投票来做出预测。这个例子假设有两个类别,

3.2 K最近邻(K-NN)算法JAVA实现

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
public class KNNClassifier {
 
    public static <T> T predictKNN(List<Map<String, Object>> trainingSet, 
                                   Map<String, Object> toClassify, 
                                   int k, 
                                   String classKey) {
        // 对训练集合进行排序
        List<Map<String, Object>> sortedTrainingSet = new ArrayList<>(trainingSet);
        Comparator<Map<String, Object>> comparator = new Comparator<Map<String, Object>>() {
            @Override
            public int compare(Map<String, Object> o1, Map<String, Object> o2) {
                double dist1 = distance(o1, toClassify);
                double dist2 = distance(o2, toClassify);
                if (dist1 != dist2) {
                    return (int) Math.signum(dist1 - dist2);
                } else {
                    return 0;
                }
            }
        };
        Collections.sort(sortedTrainingSet, comparator);
 
        // 创建一个哈希映射来存储每个类别的计数
        Map<Object, Integer> classCount = new HashMap<>();
 
        // 遍历前k个最近的实例
        for (int i = 0; i < k; i++) {
            Map<String, Object> nearest = sortedTrainingSet.get(i);
            Object nearestClass = nearest.get(classKey);
            if (!classCount.containsKey(nearestClass)) {
                classCount.put(nearestClass, 1);
            } else {
                classCount.put(nearestClass, classCount.get(nearestClass) + 1);
            }
        }
 
        // 返回出现次数最多的类别
        Object maxClass = null;
        int maxCount = 0;
        for (Map.Entry<Object, Integer> entry : classCount.entrySet()) {
            if (entry.getValue() > maxCount) {
                maxCount = entry.getValue();
                maxClass = entry.getKey();
            }
        }
        return (T) maxClass;
    }
 
    private static double distance(Map<String, Object> point1, Map<String, Object> point2) {
        // 假设所有特征都是实数并计算欧氏距离
        double sum = 0.0;
        for (String key : point1.keySet()) {
            if (key.equals("class")) continue;
            sum += Math.pow((Double) point1.get(key) - (Double) point2.get(key), 2);
        }
        return Math.sqrt(sum);
    }
}

        这个代码实例提供了KNN分类器的一个简化版本,它接受一个训练集合,要分类的数据以及要考虑的最近邻数k。它计算每个邻居的欧氏距离,并对它们进行排序。然后,它记录前k个实例的类别并返回出现次数最多的类别作为预测结果。这个例子假设所有特征都是实数值,并且忽略了类别特征。

3.3 K最近邻(K-NN)算法python实现

import numpy as np
import kNN
 
# 创建样本数据,实际情况可能来自文件读取
samples = np.array([
    [1.0, 1.0],
    [1.0, 2.0],
    [2.0, 1.0],
    [2.0, 2.0],
    [2.0, 3.0],
    [3.0, 2.0],
    [3.0, 3.0],
    [3.0, 4.0],
])
 
# 目标值,即类别标签
labels = np.array([0, 0, 0, 0, 1, 1, 1, 1])
 
# 创建kNN分类器实例
classifier = kNN.kNNClassifier()
 
# 训练分类器
classifier.train(samples, labels)
 
# 测试分类器
# 假设有一个新的点需要分类
test_point = np.array([2.0, 2.5])
predicted_label = classifier.predict_one(test_point)
 
# 打印预测结果
print("Test point:", test_point)
print("Predicted label:", predicted_label)

        这个例子展示了如何使用简单的kNN算法对样本数据进行分类。首先,我们创建了一些二维空间中的样本点和它们的类别标签。然后,我们实例化了一个kNN分类器并进行训练。最后,我们用一个新的点来测试分类器,并打印出预测的类别标签。这个例子假设kNN模块已经实现了必要的功能,并且在上述代码段中正确导入。

四、K最近邻(K-NN)算法应用

        K最近邻(K-NN)算法是一种基本的分类与回归方法。它的工作原理是:给定一个训练数据集,对新的输入实例,在训练集中找到与该实例最邻近的K个实例,这K个实例的多数属于某个类别,则该输入实例也属于这个类别。K-NN算法的应用领域非常广泛,包括但不限于:

        1. 图像识别:K-NN可以用于图像识别,例如手写数字识别、面部识别等。

        2. 医疗诊断:在医疗领域,K-NN可以用于疾病预测和诊断,通过分析病人的历史数据来预测其可能的疾病。

        3. 推荐系统:K-NN算法可以用于构建推荐系统,通过分析用户的历史行为和偏好,推荐相似的产品或服务。

        4. 信用评估:在金融领域,K-NN可以用于信用评估,通过分析借款人的历史信用记录来预测其信用等级。

        5. 生物信息学:在生物信息学中,K-NN可以用于基因分类、蛋白质功能预测等。

        6. 文本分类:K-NN可以用于文本分类,例如垃圾邮件过滤、新闻分类等。

        K-NN算法的优点是简单易懂,易于实现,且不需要事先对数据进行训练。然而,它也有一些缺点,例如对大数据集的计算效率较低,且对数据的归一化处理比较敏感。

五、K最近邻(K-NN)算法发展趋势

        K最近邻(K-NN)算法是一种基本的分类与回归方法。近年来,随着机器学习和数据挖掘技术的发展,K-NN算法也呈现出一些新的发展趋势:

        1. 加速与优化:由于K-NN算法在计算时需要考虑所有训练样本,因此在大数据集上运行效率较低。研究者们致力于通过各种索引技术(如KD树、球树、近似最近邻搜索等)来加速K-NN的搜索过程。

        2. 多核学习:为了提高K-NN的泛化能力,多核学习方法被引入到K-NN中。通过为不同的特征或样本分配不同的核函数和权重,可以提升算法的性能。

        3. 集成学习:集成学习方法如随机森林、Boosting等被用来改进K-NN。通过构建多个K-NN模型并结合它们的预测结果,可以得到更稳定和准确的分类或回归结果。

        4. 特征选择与降维:在高维数据中,K-NN的性能会受到影响。因此,特征选择和降维技术被用来减少噪声和冗余特征的影响,提高算法的效率和准确性。

        5. 处理不平衡数据:在实际应用中,数据往往存在类别不平衡的问题。研究者们提出了各种方法来处理不平衡数据,如重采样技术、修改距离度量或权重调整等。

        6. 深度学习结合:深度学习在特征提取方面表现出色,将深度学习与K-NN结合,可以利用深度学习模型提取的高级特征来提高K-NN的分类性能。

        7. 应用领域扩展:K-NN算法被广泛应用于图像识别、推荐系统、生物信息学、金融分析等多个领域,并且随着这些领域需求的变化,K-NN算法也在不断地进行适应性改进。

        这些发展趋势表明,K-NN算法仍然具有强大的生命力和广泛的应用前景。随着相关技术的不断进步,K-NN算法有望在更多领域发挥更大的作用。

标签:NN,int,类别,算法,最近,数据挖掘,points
From: https://blog.csdn.net/xiaoyingxixi1989/article/details/142266823

相关文章

  • 负荷预测 | Matlab基于CNN-BiGRU-Attention多变量时间序列多步预测
    目录效果一览基本介绍程序设计参考资料效果一览基本介绍1.Matlab基于CNN-BiGRU-Attention多变量时间序列多步预测;2.多变量时间序列数据集(负荷数据集),采用前多天时刻预测的特征和负荷数据预测未来多天时刻的负荷数据;3.excel数据方便替换,运行环境matlab2023及以上,展示最后96个时间步......
  • nlohmann/json安装与使用
    介绍nlohmann/json是一个用于处理JSON数据的C++库,提供了简单而强大的JSON解析和生成功能。以其简洁易用、功能强大而受到广泛欢迎。优点简单易用:使用现代C++特性,如自动类型推断和范围for循环,简化了JSON的创建、访问和操作。与标准库兼容:它与C++标准......
  • JCE cannot authenticate the provider BC
    JCEcannotauthenticatetheproviderBC解决办法:修改$JAVA_HOME\jre\lib\security\java.security文件添加如下内容security.provider.11=org.bouncycastle.jce.provider.BouncyCastleProvider1其中security.provider.11中的11是根据已有的配置行顺序而定的,如下security.pr......
  • Error while loading conda entry point: anaconda-cloud-auth (cannot import name
    这个错误是由于conda环境中的某些插件或依赖损坏,特别是在conda.plugins.types模块中无法找到ChannelAuthBase。这通常发生在conda安装不完整、升级失败或插件包损坏的情况下。可能的解决方案:1.更新conda首先尝试更新conda,这可以修复一些与依赖相关的问题:condaupdatecon......
  • MySQL存储引擎:InnoDB与MyISAM
    InnoDB和MyISAM是MySQL数据库中两种常用的存储引擎,它们在数据存储结构、事务支持、锁的支持、外键支持、性能等方面存在显著的差异。下面将详细介绍这两种存储引擎的特点和优势。什么是存储引擎​MySQL中的数据用各种不同的技术存储在文件(或者内存)中。每一种技术都使......
  • YOLOV5 onnx推理 python
      pipinstallonnxcoremltoolsonnx-simplifier 3.使用onnx-simplier简化模型python-monnxsimbest.onnxbest-sim.onnx #coding=utf-8importcv2importnumpyasnpimportonnxruntimeimporttorchimporttorchvisionimporttimeimportrandomfromutil......
  • 代码随想录算法训练营,9月14日 | 530.二叉搜索树的最小绝对差,501.二叉搜索树中的众数,23
    530.二叉搜索树的最小绝对差题目链接:530.二叉搜索树的最小绝对差文档讲解︰代码随想录(programmercarl.com)视频讲解︰二叉搜索树的最小绝对差日期:2024-09-14想法:好好利用二叉搜索树中序遍历是有序的性质,设置一个节点表示前一个结点就能很方便的计算差值了Java代码如下:classSo......
  • 基于CNN-LSTM-Attention的共享单车租赁预测研究(数据可换)(Python代码实现)基于CNN-LSTM
                        ......
  • 常青秩序 Perennial Order,官方中文,解压即玩,
    游戏截图 PerennialOrder是一款2D植物恐怖bossrush游戏,背景设定在被自然瘟疫的恐怖所席卷、野兽横行的黑暗年代世界里。独自或与朋友加入双人本地/在线合作,一起探索这片神秘的土地。通过千奇百怪的NPC揭开故事并击败邪恶的怪异首领,2D画风构筑了这个世界的点点滴......
  • 论文分享 《Timing Side-channel Attacks and Countermeasures in CPU Microarchitect
    Attack概述传统攻击(CONVENTIONALATTACKS)在传统攻击中,Attacker通常:与Victim共享硬件资源(比如说LLC,BP,Prefetcher等)可以观察,改变微架构状态攻击步骤本文作者将传统攻击分为以下三步,如Fig1所示:定位“漏洞”:该漏洞包括“代码漏洞”(vulnerablecodegadgets),即......