NN算法的核心是,欧式距离(Euclid),在分类的数据中,找到与目标数据欧式距离最近的点,把目标点分类到其类,算法很简单,下面是C#代码的实现:
namespace LocationService.Math { using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; public class NN { public List<Tuple<string, double[]>> FingerPrintsTable; public NN() { FingerPrintsTable = new List<Tuple<string, double[]>>(); } public void AddFingerPrint(string key,double[] attributes) { var finger = Tuple.Create(key,attributes); AddFingerPrint(finger); } public void AddFingerPrint(Tuple<string,double[]> fingerprint) { FingerPrintsTable.Add(fingerprint); } public void AddFingerPrint(IEnumerable<Tuple<string, double[]>> fingers) { FingerPrintsTable.AddRange(fingers); } public void RemoveFingerPrint(string key) { FingerPrintsTable.RemoveAll(fi => fi.Item1 == key); } public void RemoveFingerPrint(Tuple<string, double[]> fingerprint) { FingerPrintsTable.Remove(fingerprint); } public double EuclideanDistance(double[] x1, double[] x2,int scale=1) { double sum=0; for (int i = 0; i < x1.Length; i++) { sum += Math.Pow(x1[i] - x2[i], 2); } sum = Math.Sqrt(sum) / x1.Length*scale; return sum; } public List<Tuple<string, double>> FingerEuclideanList(Tuple<string, double[]> target) { List<Tuple<string, double>> list = new List<Tuple<string, double>>(); foreach (var finger in FingerPrintsTable) { list.Add(Tuple.Create(finger.Item1, EuclideanDistance(finger.Item2, target.Item2))); } return list; } /// <summary> /// Apply the Euclidean distance /// </summary> /// <param name="target"></param> /// <returns></returns> public Tuple<string,double> ApplyEuclideanFilter(Tuple<string, double[]> target) { var list = FingerEuclideanList(target); list.Sort((x, y) => (int)((x.Item2 - y.Item2) * 100)); foreach (var item in list) { this.log("[Label:{0} Distance:{1}]", item.Item1, item.Item2); } return list[0]; } } }
用其他的案例,分类影片类型:
分类使用
NN nN = new NN(); nN.AddFingerPrint("爱情",new double[] {3,104}); nN.AddFingerPrint("爱情", new double[] {2,100 }); nN.AddFingerPrint("爱情", new double[] {1,81}); nN.AddFingerPrint("动作", new double[] {101,10 }); nN.AddFingerPrint("动作", new double[] {99,5}); nN.AddFingerPrint("动作", new double[] {98,2}); Tuple<string, double[]> target = Tuple.Create("未知",new double[] {81,80}); Tuple<string, double> result=null; this.MeasureTime(()=> { result = nN.ApplyEuclideanFilter(target); },time=> { this.log("==================================="); this.log("分类类型:{0} 欧式距离为:{1}", result.Item1, result.Item2); this.log("total time:{0}ms", time); this.log("==================================="); });
分类结果如下: