C#,机器学习的KNN(K Nearest Neighbour)算法与源代码

1 K最邻近法

KNN(K- Nearest Neighbor)法即K最邻近法,最初由 Cover和Hart于1968年提出,是一个理论上比较成熟的方法,也是最简单的机器学习算法之一。该方法的思路非常简单直观:如果一个样本在特征空间中的K个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。该方法在定类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。
该方法的不足之处是计算量较大,因为对每一个待分类的文本都要计算它到全体已知样本的距离,才能求得它的K个最邻近点。目前常用的解决方法是事先对已知样本点进行剪辑,事先去除对分类作用不大的样本。另外还有一种 Reverse KNN法,它能降低KNN算法的计算复杂度,提高分类的效率。
KNN算法比较适用于样本容量比较大的类域的自动分类,而那些样本容量较小的类域采用这种算法比较容易产生误分。
 

k-最近邻(KNN)算法是一种数据分类方法,用于根据最近的数据点所属的组来估计数据点成为一个组或另一个组的成员的可能性。

k-最近邻算法是一种用于解决分类和回归问题的有监督机器学习算法。然而,它主要用于分类问题。

KNN是一种延迟学习的非参数算法。

它被称为懒惰学习算法或懒惰学习者,因为当您提供训练数据时,它不会执行任何训练。相反,它只存储训练期间的数据,不执行任何计算。在对数据集执行查询之前,它不会构建模型。这使KNN成为数据挖掘的理想选择。

它被认为是一种非参数方法,因为它不对底层数据分布进行任何假设。简而言之,KNN试图通过查看数据点周围的数据点来确定数据点属于哪个组。

假设有两组,A和B。

为了确定一个数据点是在a组还是在B组中,该算法会查看其附近数据点的状态。如果大多数数据点都在A组中,则很可能所讨论的数据点在A组中,反之亦然。

简而言之,KNN涉及通过查看最近的带注释数据点(也称为最近邻点)对数据点进行分类。

不要混淆K-NN分类和K-means聚类。KNN是一种监督分类算法,它基于最近的数据点对新数据点进行分类。另一方面,K-means聚类是一种无监督聚类算法,它将数据分组为K个聚类。

2 源程序

using System;
using System.Linq;
using System.Text;
using System.Collections.Generic;

namespace Legalsoft.Truffer.Algorithm
{
    public class Sample
    {
        public double SepalLength { get; set; } = 0.0;
        public double SepalWidth { get; set; } = 0.0;
        public double PetalLength { get; set; } = 0.0;
        public double PetalWidth { get; set; } = 0.0;
        public string Species { get; set; } = "";
    }

    public class KNN_Algorithm
    {
        /// <summary>
        /// 样本数据
        /// </summary>
        public List<Sample> Samples { get; set; } = new List<Sample>();

        /// <summary>
        /// 未分类数据
        /// </summary>
        public List<Sample> Unclassify { get; set; } = new List<Sample>();

        /// <summary>
        /// K值
        /// </summary>
        public int K { get; set; } = 0;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="sampleList">样本数据</param>
        /// <param name="unclassifyList">未分类数据</param>
        /// <param name="k">k值</param>
        public KNN_Algorithm(List<Sample> sampleList, List<Sample> unclassifyList, int k)
        {
            Samples = sampleList;
            Unclassify = unclassifyList;
            K = k;
        }

        /// <summary>
        /// 分类
        /// </summary>
        public void Classify()
        {
            int sampleCount = Samples.Count;
            int unclassifyCount = Unclassify.Count;

            for (int i = 0; i < unclassifyCount; i++)
            {
                Tuple<string, double>[] tupleArray = new Tuple<string, double>[sampleCount];
                for (int j = 0; j < sampleCount; j++)
                {
                    double distance = CalculateDistance(Samples[j], Unclassify[i]);
                    string species = Samples[j].Species;
                    tupleArray[j] = Tuple.Create(species, distance);
                }

                IEnumerable<Tuple<string, double>> selector = tupleArray.OrderBy(t => t.Item2).Take(K);
                Dictionary<string, int> dictionary = new Dictionary<string, int>();
                foreach (Tuple<string, double> tuple in selector)
                {
                    if (dictionary.ContainsKey(tuple.Item1))
                    {
                        dictionary[tuple.Item1]++;
                    }
                    else
                    {
                        dictionary.Add(tuple.Item1, 1);
                    }
                }

                IEnumerable<KeyValuePair<string, int>> keyValuePair = dictionary.OrderByDescending(t => t.Value).Take(1);
                foreach (KeyValuePair<string, int> kvp in keyValuePair)
                {
                    Unclassify[i].Species = kvp.Key;
                }

                Samples.Add(Unclassify[i]);
                sampleCount++;
            }
        }

        /// <summary>
        /// 计算欧氏距离
        /// </summary>
        /// <param name="sample">样本数据</param>
        /// <param name="unclassify">未分类数据</param>
        /// <returns>两者欧氏距离</returns>
        public double CalculateDistance(Sample sample, Sample unclassify)
        {
            double delta_SepalLength = unclassify.SepalLength - sample.SepalLength;
            double delta_SepalWidth = unclassify.SepalWidth - sample.SepalWidth;
            double delta_PetalLength = unclassify.PetalLength - sample.PetalLength;
            double delta_PetalWidth = unclassify.PetalWidth - sample.PetalWidth;
            double ds = delta_SepalLength * delta_SepalLength + delta_SepalWidth * delta_SepalWidth +
                delta_PetalLength * delta_PetalLength + delta_PetalWidth * delta_PetalWidth;
            if (ds <= float.Epsilon) return 0.0;
            return Math.Sqrt(ds);
        }
    }
}

POWER BY 315SOFT.COM

3 应用

大约50年前被发现以来,K-最近邻方法已经发展了很长时间。现在它主要被用于文本挖掘和预测问题,并且在农业、金融和医疗等行业领域得到了应用。

1951年,Fix和Hodges设想了最近邻规则,这也是KNN的最早设想之一。随后,1962年,Sebestyen将这样KNN称作邻近算法(proximity algorithm)。1965年,KNN当时被Nilsson称作最小距离分类器(minimum distance classifier)。1967年,Cover和Hart在论文《Nearest neighbor pattern classification》中正式介绍了KNN,也是KNN的首次正式的提出。

kNN算法因其提出时间较早,随着其他技术的不断更新和完善,kNN算法的诸多不足之处也逐渐显露,因此许多kNN算法的改进算法也应运而生。针对以上算法的不足,算法的改进方向主要分成了分类效率和分类效果两方面。

分类效率:事先对样本属性进行约简,删除对分类结果影响较小的属性,快速的得出待分类样本的类别。KNN算法比较适用于样本容量比较大的类域的自动分类,而那些样本容量较小的类域采用这种算法比较容易产生误分,如2006年,Zhang, H., Berg, A. C., Maire, M., & Malik, J. j.基于SVM和KNN区分最近邻分类的视觉类别。在2007年,Zhang, M. L., & Zhou, Z. H.在有限的数据中设计了对多标签数据的KNNs算法《ML-KNN: A lazy learning approach to multi-label learning》。2009年,《Fast Approximate kNN Graph Construction for High Dimensional Data via Recursive Lanczos Bisection》利用两种divide and conquer方法来近似KNN的计算。

分类效果:Stanfill和Waltz采用价值距离指标(Value Distance Metric/VDM);采用权值的方法(和该样本距离小的邻居权值大)来改进,Han等人于2001年尝试利用贪心法,针对文件分类实做可调整权重的k最近邻居法WAkNN (weighted adjusted k nearest neighbor),以促进分类效果;而Li等人于2004年提出由于不同分类的文件本身有数量上有差异,因此也应该依照训练集合中各种分类的文件数量,选取不同数目的最近邻居,来参与分类。2005,NCA(Neighbourhood components analysis)是将马氏距离应用于KNN算法来实现降维的效果,它主要目的是通过找到一个线性变化矩阵,来最大化leave-one-out (LOO)分类精确度。算法的关键点在于可以通过可微的目标函数f(A)来找出线性变化矩阵A,比如说使用共轭梯度法。因此,NCA被普遍应用于模型的选择,降维,结构预测,异常分析,强化学习的神经网络中。
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/426904.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ET系列手持如何在仓储管理精准出彩!

在仓储行业&#xff0c;公司一般依靠纸质文档来纪录和追踪出入的货品&#xff0c;以员工的记忆力来执行库房管理。这种非自动化管理方式很容易因为人为失误而造成生产率低下&#xff0c;同时也大大浪费人力资源。另外&#xff0c;伴随着货品数量的a增加和出入库房頻率的大幅度提…

模糊搜索小案例

C#窗体实现数据录入与模糊搜索小案例 记录一下 主要代码 private void button1_Click(object sender, EventArgs e){string name textBox1.Text;string hometown textBox4.Text;string school textBox6.Text;string sex textBox5.Text;string lat textBox3.Text;string …

【Git】深入理解 Git 分支合并操作:git merge dev 命令详解

深入理解 Git 合并操作&#xff1a;git merge dev 命令详解 摘要&#xff1a;本文将深入探讨 Git 中的合并操作&#xff0c;以及如何使用 git merge dev 命令将dev 分支的修改合并到当前分支&#xff08;假设当前分支为main 分支&#xff09;中。通过详细的解释和示意图&#x…

A Brief Introduction of the Violin Plot and Box Plot

DateAuthorVersionNote2024.03.03Dog TaoV1.0Release the note. 文章目录 A Brief Introduction of the Violin Plot and Box PlotBox PlotViolin PlotHistogram with Error BarComparisonExample 1Example 2 A Brief Introduction of the Violin Plot and Box Plot Box Plot …

java-幂等性

幂等性 1.1幂等性定义&#xff1a; 在计算机领域中&#xff0c;幂等&#xff08;Idempotence&#xff09;是指任意一个操作的多次执行总是能获得相同的结果&#xff0c;不会对系统状态产生额外影响。在Java后端开发中&#xff0c;幂等性的实现通常通过确保方法或服务调用的结…

智慧城市中的数字孪生:数字孪生技术助力智慧城市提高公共服务水平

目录 一、引言 二、数字孪生技术概述 三、数字孪生技术在智慧城市中的应用 1、智慧交通管理 2、智慧能源管理 3、智慧环保管理 4、智慧公共安全 四、数字孪生技术助力智慧城市提高公共服务水平的价值 五、挑战与前景 六、结论 一、引言 随着信息技术的飞速发展&…

Linux工具篇

文章目录 1.yum1.1 yum是什么&#xff1f;1.2yum下载的软件包在哪&#xff1f;1.3 yum的配置1.4 yum的相关操作 2. Vim2.1 各种模式的相关操作2.2 利用vim解决普通用户无法sudo的问题2.3 vim的配置 3.gcc/g3.1 利用gcc理解程序的翻译过程3.2 编译器的自举 4. 程序的链接4.1动态…

【推荐】免费AI论文写作神器-「智元兔 AI」

还在为写论文焦虑&#xff1f;免费AI写作大师来帮你三步搞定&#xff01; 智元兔AI是ChatGPT的人工智能助手&#xff0c;并且具有出色的论文写作能力。它能够根据用户提供的题目或要求&#xff0c;自动生成高质量的论文。 不论是论文、毕业论文、散文、科普文章、新闻稿件&…

OpenAI工作环境曝光:高薪背后的996;Quora的转变:由知识宝库至信息垃圾场

&#x1f989; AI新闻 &#x1f680; OpenAI工作环境曝光&#xff1a;高薪背后的996 摘要&#xff1a;近日&#xff0c;多位OpenAI匿名员工在求职网站Glassdoor上披露了公司的工作环境和公司文化&#xff0c;包括高薪水和优厚的福利待遇&#xff0c;但同时伴随着996的加班文化…

【大厂AI课学习笔记NO.62】模型的部署

我们历尽千辛万苦&#xff0c;总算要部署模型了。这个系列也写到62篇&#xff0c;不要着急&#xff0c;后面还有很多。 这周偷懒了&#xff0c;一天放出太多的文章&#xff0c;大家可能有些吃不消&#xff0c;从下周开始&#xff0c;本系列将正常更新。 这套大厂AI课&#xf…

二叉树的右视图,力扣

目录 题目&#xff1a; 我们直接看题解吧&#xff1a; 快速理解解题思路小建议&#xff1a; 审题目事例提示&#xff1a; 解题方法&#xff1a; 解题分析&#xff1a; 解题思路&#xff1a; 代码实现(DFS)&#xff1a; 代码1&#xff1a; 补充说明&#xff1a; 代码2&#xff1…

XUbuntu22.04之如何定制:已经绑定的快捷键?(二百一十五)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

挑战杯 基于深度学习的中文情感分类 - 卷积神经网络 情感分类 情感分析 情感识别 评论情感分类

文章目录 1 前言2 情感文本分类2.1 参考论文2.2 输入层2.3 第一层卷积层&#xff1a;2.4 池化层&#xff1a;2.5 全连接softmax层&#xff1a;2.6 训练方案 3 实现3.1 sentence部分3.2 filters部分3.3 featuremaps部分3.4 1max部分3.5 concat1max部分3.6 关键代码 4 实现效果4.…

Linux/Docker 修改系统时区

目录 1. Linux 系统1.1 通过 timedatectl 命令操作1.2 直接修改 /etc/localtime 文件 2. Docker 容器中的 Linux 操作环境&#xff1a; CentOS / AlmaOSMySQL Docker 镜像 1. Linux 系统 1.1 通过 timedatectl 命令操作 使用 timedatectl list-timezones 命令列出可用的时区…

HM2019改变粘合层网格厚度的方法

如图所示&#xff0c;这里需要改变黄色层的厚度&#xff0c;改变效果如下 操作步骤&#xff1a;

golang实现openssl自签名双向认证

第一步&#xff1a;生成CA、服务端、客户端证书 1. 生成CA根证书 生成CA证书私钥 openssl genrsa -out ca.key 4096创建ca.conf 文件 [ req ] default_bits 4096 distinguished_name req_distinguished_name[ req_distinguished_name ] countryName …

【网站项目】137微博系统网站

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

PowerBI怎么修改数据库密码

第一步&#xff1a;点击转换数据 第二步&#xff1a;点击数据源设置 第三步&#xff1a;点击编辑权限 第四步&#xff1a;点击编辑 第五步&#xff1a;输入正要修改的密码就可以了

WebStorm激活与安装(全网最快捷、最靠谱的方法)

前言&#xff1a; 相信很多小伙伴已经开始了前端的学习之旅&#xff0c;想要更快乐的学习当然少不了WebStorm这个得力的开发工具软件。但是WebStorm是付费的&#xff0c;免费版功能有太少&#xff0c;怎么才能既免费&#xff0c;又能使用上正式版呢&#xff01;当然还是激活啦…

Java:JVM基础

文章目录 参考JVM内存区域程序计数器虚拟机栈本地方法栈堆方法区符号引用与直接引用运行时常量池字符串常量池直接内存 参考 JavaGuide JVM内存区域 程序计数器 程序计数器是一块较小的内存空间&#xff0c;可以看做是当前线程所执行的字节码的行号指示器&#xff0c;各线程…