如何利用 C# 实现 K 最邻近算法?
众所周知,电影可以按照题材分类,然而题材本身是如何定义的?由谁来判定某部电影属于哪个题材?也就是说同一题材的电影具有哪些公共特征?这些都是在进行电影分类时必须要考虑的问题。没有哪个电影人会说自己制作的电影和以前的某部电影类似,但我们确实知道每部电影在风格上的确可能会和同题材的电影相近。那么动作片具有哪些共有特征,使得动作片之间非常类似,而与爱情片存在着明显的差别呢?动作片中也会存在接吻镜头,爱情片中也会存在打斗场景,我们不能单纯依靠是否存在打斗或接吻来判断影片的类型。但是爱情片中的接吻镜头更多、动作片中的打斗场景也更频繁,基于此类场景在某部电影中出现的次数可以用来进行电影分类。
以上是《机器学习实战》中介绍 K 最邻近算法给出的示例,通过该示例我们可以了解到 K 最邻近算法应用的一个场景:解决影片分类问题。
我们首先,先介绍一下该算法的基本原理,由于篇幅的限制,详细的理论部分可以参见对应的维基百科。
1. K 最邻近算法
K 最邻近算法(K-NN)是一种基于特征空间中最近训练实例对目标进行分类的方法。它是所有机器学习算法中最简单的一种:一个对象通过其邻居的多数票进行分类,对象被分配到其最近的 K 个邻居中最常见的类(K 是一个正整数,通常很小)。
更详细的介绍,见维基百科:
https://en.wikipedia.org/wiki/K-nearest_neighbors_algorithm
2. 欧氏距离
这就是我们最熟悉的 2-范数,即两点间的距离公式。
更详细的介绍,见维基百科:
https://en.wikipedia.org/wiki/Euclidean_distance
3. 编辑距离
在信息论和计算机科学中,Levenshtein 距离是测量两个序列之间差异的一个字符串度量,也被称为编辑距离。非正式地说,两个单词之间的 Levenshtein 距离是将一个单词更改为另一个单词所需的最小字符编辑数(即插入、删除或替换)。
更详细的介绍,见维基百科:
https://en.wikipedia.org/wiki/Levenshtein_distance
有了以上的基础,我们再来介绍代码的实现与应用,比较相似性就要定义距离,我们在这里定理了欧氏距离和编辑距离,大家可以根据使用场景,通过实现
IDistance<T>
接口的方式来定义更多的距离。在使用 K 最邻近算法 KNearestNeighbors<T>
时,使用依赖注入的方式把所用的距离对象注入进去就好。
1. 距离的定义。
定义接口:
public interface IDistance<T>
{double Distance(T x, T y);
}
定义欧氏距离:
public sealed class Euclidean : IDistance<double[]>
{public double Distance(double[] x, double[] y){double sum = 0.0;for (int i = 0; i < x.Length; i++){double u = x[i] - y[i];sum += u * u;}return Math.Sqrt(sum);}
}
定义编辑距离:
public sealed class Levenshtein : IMetric<string>
{public double Distance(string x, string y){if (string.IsNullOrEmpty(x)){if (y == null || y.Length != 0)return 0;return y.Length;}if (string.IsNullOrEmpty(y))return x.Length;int[,] d = new int[x.Length + 1, y.Length + 1];for (int i = 0; i <= x.Length; i++)d[i, 0] = i;for (int i = 0; i <= y.Length; i++)d[0, i] = i;for (int i = 0; i < x.Length; i++){for (int j = 0; j < y.Length; j++){int cost = (x[i] == y[j]) ? 0 : 1;int a = d[i, j + 1] + 1;int b = d[i + 1, j] + 1;int c = d[i, j] + cost;d[i + 1, j + 1] = Math.Min(Math.Min(a, b), c);}}return d[x.Length, y.Length];}
}
2. K 最邻近算法的封装。
public class KNearestNeighbors<T>
{private int _k;private IDistance<T> _distance;private double[] _distances;public int K{get{return _k;}set{if (value <= 0 || value > Inputs.Length)throw new Exception(@"k的值应大于零且小于输入样本总数。");_k = value;}}public IDistance<T> Distance{get{return _distance;}set{_distance = value;}}public int ClassCount{get;private set;}public T[] Inputs{get;private set;}public int[] Outputs{get;private set;}private static void CheckArgs(int k, int classes, T[] inputs, int[] outputs, IDistance<T> distance){if (k <= 0)throw new Exception(@"邻居数应大于零。");if ( classes <= 0)throw new Exception(@"类的数目应大于零。");if (inputs == null)throw new ArgumentNullException();if (outputs == null)throw new ArgumentNullException();if (inputs.Length != outputs.Length)throw new Exception(@"输入向量的数量应与相应输出标签的数量匹配。");if (distance == null)throw new ArgumentNullException();}private void Initialize(int k, int classes, T[] inputs, int[] outputs, IDistance<T> distance){_k = k;_distance = distance;_distances = new double[inputs.Length];Inputs = inputs;Outputs = outputs;ClassCount = classes;}public KNearestNeighbors(int k, int classes, T[] inputs, int[] outputs, IDistance<T> distance){CheckArgs(k, classes, inputs, outputs, distance);Initialize(k, classes, inputs, outputs, distance);}public KNearestNeighbors(int k, T[] inputs, int[] outputs, IDistance<T> distance){int classCount = outputs.Distinct().Length;CheckArgs(k, classCount, inputs, outputs, distance);Initialize(k, classCount, inputs, outputs, distance);}public virtual int Compute(T input){double[] scores;return Compute(input, out scores);}public virtual int Compute(T input, out double[] scores){for (int i = 0; i < Inputs.Length; i++)_distances[i] = _distance.Distance(input, Inputs[i]);int[] idx = _distances.Bottom(_k, true);scores = new double[ClassCount];for (int i = 0; i < idx.Length; i++){int j = idx[i];int label = Outputs[j];double d = _distances[i];scores[label] += 1.0 / (1.0 + d);}int result;scores.Max(out result);return result;}
}
3. K 最邻近算法的应用
下面的示例演示如何创建和使用 K 最邻近算法,对一组数字向量进行分类。
首先,创建一些示例学习数据。在这个数据中,前两个实例属于一类,接下来的四个实例属于一类,最后三个实例属于一类。
double[][] inputs =
{//类 0new double[] {-5, -2, -1},new double[] {-5, -5, -6},//类 1new double[] {2, 1, 1},new double[] {1, 1, 2},new double[] {1, 2, 2},new double[] {3, 1, 2},//类 2new double[] {11, 5, 4},new double[] {15, 5, 6},new double[] {10, 5, 6},
};int[] outputs =
{0,0,1,1,1,1,2,2,2,
};
现在我们将创建 K 最邻近算法。对于这个例子,我们选择 k = 4。这意味着,在给定的情况下,将使用其最近的 4个邻居来作出决定。
KNearestNeighbors<double[]> knn = new KNearestNeighbors<double[]>(4, 3, inputs, outputs, new Euclidean());
创建算法之后,我们可以对新实例进行分类:
int answer = knn.Compute(new double[] { 11, 5, 4 });
最后得到结果 answer = 2,样本“{ 11, 5, 4 }”属于标签为 2 的这一类。
当然,K 最邻近算法可用于任何类型的数据。在下面的例子中,我们将看到如何使用它来比较字符串。
string[] inputs =
{"Car", // 0"Bar", // 0"Jar", // 0"Charm", // 1"Chair" // 1
};int[] outputs =
{0, 0, 0,1, 1,
};
现在我们创建 K 最邻近算法。对于这个例子,我们选择 k = 1。这意味着,在给定的情况下,只使用其最近的邻居来进行新的决策。
为了比较字符串,我们使用 Levenshtein 的字符串距离。
KNearestNeighbors<string> knn = new KNearestNeighbors<string>(1, 2, inputs, outputs, new Levenshtein());
创建算法后,我们可以使用它对新实例进行分类:
int answer = knn.Compute("Chars");
最后得到结果 answer = 1,字符串 “Chars” 属于标签为 1 的这一类。
到此为止,用 C# 实现 K 最邻近算法就介绍完了。在后台回复 20190310 可以得到,本篇开头说的 电影分类的数据集。大家把上面的代码看懂后,可以尝试的写一下,然后用这个数据集来测试自己的代码。
今天就到这里吧!See You!
相关文章:

参加java培训真的能学到有用的吗
java技术在互联网行业的快速发展,优渥的待遇,让很多人都想学习这项技术,目前市面上开设java培训的机构越来越多,很多人都担心参加java培训能学到知识吗?下面我们来看看具体的解析。 参加java培训能学到知识吗?在Java培训机构能不…

android自定义调节器控件 —— RegulatorView
2019独角兽企业重金招聘Python工程师标准>>> RegulatorView效果图: RegulatorView实现步骤: 1.新建java类RegulatorView.java,继承View类 2.定义必要基础属性,及为其附初始值 private final static int BTN_RADIUS20;/…

如何利用 C# 实现 K-D Tree 结构?
我的朋友海伦一直使用在线约会网站寻找适合自己的约会对象。尽管约会网站会推荐不同的人选,但她没有从中找到喜欢的人。经过一番总结,她发现曾交往过三种类型的人: 不喜欢的人魅力一般的人极具魅力的人 尽管发现了上述规律,但海…

[恩难到了]陨石的秘密
【描述】 公元19881231年,一颗巨大的陨石坠落在世界的政治文化中心cs。于是,灾难降临了,地球上出现了一系列反常的现象。当人们焦急万分的时候,一支由cs科学家组成的考察队赶到了出事地点。经过一番侦察,科学家们发现陨…

java培训学习阶段步骤讲解
目前的培训机构行业比较热门的IT技术就是java技术,java技术在近几年广受关注,java所涉及的技术知识也比较广泛,下面小编就为大家详细的介绍一下java培训学习多有哪几个阶段? java培训学习多有哪几个阶段: 第一阶段、Java设计和编…

资料分享:送你一本《机器学习实战》电子书!
这两天,各985高校发布了考研初试分数线。从中发现这两年大数据相关专业的分数线暴涨啊。没有400分估计心里都没底啊。可见大数据这个领域有多火爆!而机器学习是我们团队的一个主要方向,新加入的同学通常都是从《机器学习实战》这本书开始入门…

HDU 6091 - Rikka with Match | 2017 Multi-University Training Contest 5
思路来自 某FXXL 不过复杂度咋算的.. /* HDU 6091 - Rikka with Match [ 树形DP ] | 2017 Multi-University Training Contest 5 题意:给出N个点的树,求去边的方案数使得 去边后最大匹配数是M的倍数限制: N<5e4, M<200 分析ÿ…

在别的电脑上运行cg程序出现错误的解决办法
错误:没有找到cg.dll,因为这个应用程序未能启动。重新安装应用程序可能会修复此问题 解决方法:复制cg.dll到system32 、debug中 错误:没有找到cgGL.dll,因为这个应用程序未能启动。重新安装应用程序可能会修复此问题 解…

HTML在网页设计中是什么作用?
HTML是一种超文本传输协议,规定了浏览器与服务端之间数据传输的格式,是一种标识性的代码语言,它的中文翻译是“超文本标记语言”,主要是通过HTML标签对网页中的文本、图片、声音等内容进行描述。HTML提供了许多标签,如…

如何实现链接只能被点击一次
有时候,只希望网站某个链接只能被点击一次,怎么做呢?下面给出3中方法!第一种:利用JS在点击后把href变成#把taget变成空。 <p><a onclick"var that this;setTimeout(function(){that.removeAttribute(hr…

匿名类型和Object转换
.net中的匿名类型非常好用, 但是开发中遇到一个问题,当把匿名类型作为返回值的时候,会变成object类型,如果才能再转换能对应的匿名类型呢? 1 //返回匿名类型的函数, 会转换成object类型2 object ReturnAnonymous() {3 retur…

资料分享:送你一本《数据结构(C#语言版)》电子书!
对于信息类专业的学生而言,数据结构与算法是一门必修的课程。只有学好这门课程,熟练掌握线性表、栈、队列、树、图等基本结构,以及在这些结构上的各种算法,才能利用计算机去解决实际问题。 如何学好这门课程呢,给大家…

新手入门API测试必要了解的知识
什么是API?API是Application Programming Interface的简写。实现了两个或多个独立系统或模块间的通信和数据交换能力。 什么是API测试?API测试是不同于UI级自动化测试,其主要关注在系统架构的业务逻辑层,所以其主要关注不在于UI操作或用户感观上&#…

java监控多个线程的实现
场景:需要启动多线程处理事情,而在所有事情做完之后,需要修改系统状态;那么如何判断所有线程(事情)都做完了呢?这就需要判断所有当前运行的线程状态了。 代码 importjava.util.concurrent.Count…

如何利用 C# 实现神经网络的感知器模型?
前几天我们介绍了 如何利用 C# 对神经网络模型进行抽象,在这篇图文中,我们抽象了单个神经元 Neuro,网络层 Layer,网络结构 Network,激活函数 IActivationFunction,以及监督学习 ISupervisedLearning 和非监…

JPA增删改查,
2019独角兽企业重金招聘Python工程师标准>>> 1. //And --- 等价于 SQL 中的 and 关键字 public List<User> findByHeightAndSex(int height,char sex); 2. // Or --- 等价于 SQL 中的 or 关键字 public List<User> findByHeightOrSex(int height,cha…

Java新手会遇到的三大误区,一定要避免!
很多学习java技术的学员都是零基础学员,之前对java技术一点都不了解,所以java新手在学习java技术的时候很容易进入误区,下面小编分享的Java新手会遇到的三大误区,一定要避免! 作为目前最为广泛的网络编程语,Java凭借其…

[ACM] hdu 1253 胜利大逃亡 (三维BFS)
胜利大逃亡 Problem DescriptionIgnatius被魔王抓走了,有一天魔王出差去了,这但是Ignatius逃亡的好机会.魔王住在一个城堡里,城堡是一个A*B*C的立方体,能够被表示成A个B*C的矩阵,刚開始Ignatius被关在(0,0,0)的位置,离开城堡的门在(A-1,B-1,C-1)的位置,如今知道魔王将在T分钟后…

如何利用 C# 爬取带 Token 验证的网站数据?
在对文本数据的情感分析中,基于情感词典的方法是最简单也是最常用的一种了。 它的大体思路如下: 对文档分词,找出文档中的情感词、否定词以及程度副词,然后判断每个情感词之前是否有否定词及程度副词,将它之前的否定…

多线程显示运行状态
最近碰见一个例子,Copy大文件或者网络访问的时候处理假死。 那就用多线程加个进度条(只显示运行,没有进度)来表示状态运行吧。好了,废话少说,上个例子。先看结果图: 程序说明: 点击Button,运行…

【Python培训基础知识】单例模式
单例模式是保证一个类仅有一个实例的设计模式。Windows中的任务管理器就是一个典型的单例模式软件。Windows任务管理器如图所示。 Windows任务管理器只能打开一个,即使用户重复打开,也只能获得一个实例,这不同于Word等软件可以打开多个实例。…

Android读写XML(上)
XML 经常用作 Internet 上的一种数据格式,其文件格式想必大家都比较清楚,在这里我结合Android平台,来说明Android SDK提供的读写XML的package。 首先介绍下Android SDK与Java SDK在读写XML文件方面,数据包之间的关系。Android 平台…

Lighttpd1.4.20源代码分析 笔记 状态机之错误处理和连接关闭
这里所说的错误有两种: 1.http协议规定的错误,如404错误。 2.server执行过程中的错误。如write错误。 对于http协议规定的错误,这里的“错误”是针对client的。lighttpd返回相应的错误提示文件之后,相当于顺利的完毕了一次请求&…

资料分享:送你一本《数据结构(C语言版)》电子书!
要想写出可复用、可扩展、易维护、灵活性好的代码,「数据结构」这一关必须要过啊! 在数据结构与算法的众多教材中,奉为经典的当属清华大学严蔚敏老师的著作。很多学校也选择这本书作为考研指定教材。 正在学习数据结构与算法这门课程的同学…

零基础学python培训需要学习多久?
Python是一种入门比较简单的编程语言,但是如果是零基础学员,学习起来还是需要时间的,那么零基础学python培训需要学习多久呢?我们来看看小编的详细介绍吧。 零基础学python培训需要学习多久? 现在的培训机构,一般Python的培训时…

拖动无标题窗体
方法一: 当用户点击窗体的时候欺骗系统,用户是点在标题栏上,这样就完成了无标题栏窗体的拖动,实现如下: 在 MESSAGE_HANDLER(WM_NCHITTEST, OnNcHitTest) 这个函数的方法里 : LRESULT CNyWnd::OnNcHitTest(…

如何利用 C# 爬取Gate.io交易所的公告!
对于大部分程序员来说,都希望自己或多或少拥有一些比特币(BTC)。获取 BTC 的途径除了挖矿计算 Hash 值之外,就是去交易所购买了。 由于 BTC 的价格波动非常剧烈,入手 BTC 的时机就显得尤为关键。在交易所搞活动时入手…

人的原罪、本我和超我
摘自:https://www.zhihu.com/question/31362451/answer/51606300人的原罪的存在,因为人人皆有,所以在潜意识中,形成了对本我的接纳,而神爱世人与宽恕的存在,形成了本我与超我的良性互动。 在这样的关系中&a…

软件测试的准入准出是什么?标准是什么?
测试的准入准出是指什么情况下可以开始当前版本的测试工作,什么情况下可以结束当前版本的测试工作。不同项目、不同公司的测试准入准出标准都会有所不同。下面介绍一些通用的测试准入准出标准。 测试准入标准如下: (1)开发编码结束,开发人员在…

如何利用 C# 爬取 One 持有者返利数据!
去年,10月份写过一篇图文 「One」的投资价值分析,多半年过去了,回头看看当时的判断还是合理的。 投资这种事情需要有自己的策略,更需要理性。任何决策都需要以数据作为判断的基础,哪么是否还继续持有 ONE呢?…