C#语言实现K-近邻算法 (K-Nearest Neighbors, KNN)

以下是用C#实现K-近邻算法(K-Nearest Neighbors, KNN)的代码示例。这个实现将数据点存储在一个二维数组中,并计算与测试点的距离,选择最近的K个邻居来进行分类。

实现步骤:

  1. 计算每个数据点到测试点的欧氏距离。
  2. 对距离进行排序,选出前K个最近的邻居。
  3. 根据最近邻居的标签进行投票,选择出现次数最多的标签作为测试点的分类结果。


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

class KNN
{
    // 存储训练数据点和其标签
    private List<Tuple<double[], string>> trainingData;

    public KNN()
    {
        trainingData = new List<Tuple<double[], string>>();
    }

    // 添加训练数据点
    public void AddTrainingData(double[] features, string label)
    {
        trainingData.Add(new Tuple<double[], string>(features, label));
    }

    // 计算欧氏距离
    private double EuclideanDistance(double[] point1, double[] point2)
    {
        double sum = 0.0;
        for (int i = 0; i < point1.Length; i++)
        {
            sum += Math.Pow(point1[i] - point2[i], 2);
        }
        return Math.Sqrt(sum);
    }

    // 分类函数,k为选择的邻居个数
    public string Classify(double[] testPoint, int k)
    {
        // 计算每个训练数据点与测试点的距离
        List<Tuple<double, string>> distances = new List<Tuple<double, string>>();

        foreach (var data in trainingData)
        {
            double distance = EuclideanDistance(testPoint, data.Item1);
            distances.Add(new Tuple<double, string>(distance, data.Item2));
        }

        // 按距离排序,选出前K个最近的邻居
        var nearestNeighbors = distances.OrderBy(x => x.Item1).Take(k);

        // 统计最近邻居中每个标签出现的次数
        Dictionary<string, int> labelCounts = new Dictionary<string, int>();

        foreach (var neighbor in nearestNeighbors)
        {
            string label = neighbor.Item2;
            if (labelCounts.ContainsKey(label))
            {
                labelCounts[label]++;
            }
            else
            {
                labelCounts[label] = 1;
            }
        }

        // 返回出现次数最多的标签
        return labelCounts.OrderByDescending(x => x.Value).First().Key;
    }
}

class Program
{
    static void Main(string[] args)
    {
        // 创建KNN实例
        KNN knn = new KNN();

        // 添加训练数据(特征,标签)
        knn.AddTrainingData(new double[] { 1.0, 2.0 }, "A");
        knn.AddTrainingData(new double[] { 2.0, 3.0 }, "A");
        knn.AddTrainingData(new double[] { 3.0, 3.0 }, "B");
        knn.AddTrainingData(new double[] { 5.0, 1.0 }, "B");

        // 测试数据
        double[] testPoint = new double[] { 2.5, 2.5 };

        // K值为3
        string result = knn.Classify(testPoint, 3);

        Console.WriteLine($"分类结果:{result}");
    }
}

解释:

  • trainingData:存储训练数据,每个数据点由特征和标签组成。
  • EuclideanDistance:计算两个数据点之间的欧氏距离。
  • Classify:根据K值选择K个最近的邻居,返回出现次数最多的标签作为分类结果。

示例运行结果:

假设训练数据点及其标签如下:

  • (1.0, 2.0) -> A
  • (2.0, 3.0) -> A
  • (3.0, 3.0) -> B
  • (5.0, 1.0) -> B

对于测试数据点 (2.5, 2.5),K = 3 时,分类结果可能为 "A"。

可改进的地方:

  • 支持不同的距离度量方式(如曼哈顿距离)。
  • 添加对回归任务的支持。

以下是用C#实现K-近邻算法(K-Nearest Neighbors, KNN)的代码示例。这个实现将数据点存储在一个二维数组中,并计算与测试点的距离,选择最近的K个邻居来进行分类。

实现步骤:

  1. 计算每个数据点到测试点的欧氏距离。
  2. 对距离进行排序,选出前K个最近的邻居。
  3. 根据最近邻居的标签进行投票,选择出现次数最多的标签作为测试点的分类结果。


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

class KNN
{
    // 存储训练数据点和其标签
    private List<Tuple<double[], string>> trainingData;

    public KNN()
    {
        trainingData = new List<Tuple<double[], string>>();
    }

    // 添加训练数据点
    public void AddTrainingData(double[] features, string label)
    {
        trainingData.Add(new Tuple<double[], string>(features, label));
    }

    // 计算欧氏距离
    private double EuclideanDistance(double[] point1, double[] point2)
    {
        double sum = 0.0;
        for (int i = 0; i < point1.Length; i++)
        {
            sum += Math.Pow(point1[i] - point2[i], 2);
        }
        return Math.Sqrt(sum);
    }

    // 分类函数,k为选择的邻居个数
    public string Classify(double[] testPoint, int k)
    {
        // 计算每个训练数据点与测试点的距离
        List<Tuple<double, string>> distances = new List<Tuple<double, string>>();

        foreach (var data in trainingData)
        {
            double distance = EuclideanDistance(testPoint, data.Item1);
            distances.Add(new Tuple<double, string>(distance, data.Item2));
        }

        // 按距离排序,选出前K个最近的邻居
        var nearestNeighbors = distances.OrderBy(x => x.Item1).Take(k);

        // 统计最近邻居中每个标签出现的次数
        Dictionary<string, int> labelCounts = new Dictionary<string, int>();

        foreach (var neighbor in nearestNeighbors)
        {
            string label = neighbor.Item2;
            if (labelCounts.ContainsKey(label))
            {
                labelCounts[label]++;
            }
            else
            {
                labelCounts[label] = 1;
            }
        }

        // 返回出现次数最多的标签
        return labelCounts.OrderByDescending(x => x.Value).First().Key;
    }
}

class Program
{
    static void Main(string[] args)
    {
        // 创建KNN实例
        KNN knn = new KNN();

        // 添加训练数据(特征,标签)
        knn.AddTrainingData(new double[] { 1.0, 2.0 }, "A");
        knn.AddTrainingData(new double[] { 2.0, 3.0 }, "A");
        knn.AddTrainingData(new double[] { 3.0, 3.0 }, "B");
        knn.AddTrainingData(new double[] { 5.0, 1.0 }, "B");

        // 测试数据
        double[] testPoint = new double[] { 2.5, 2.5 };

        // K值为3
        string result = knn.Classify(testPoint, 3);

        Console.WriteLine($"分类结果:{result}");
    }
}

解释:

  • trainingData:存储训练数据,每个数据点由特征和标签组成。
  • EuclideanDistance:计算两个数据点之间的欧氏距离。
  • Classify:根据K值选择K个最近的邻居,返回出现次数最多的标签作为分类结果。

示例运行结果:

假设训练数据点及其标签如下:

  • (1.0, 2.0) -> A
  • (2.0, 3.0) -> A
  • (3.0, 3.0) -> B
  • (5.0, 1.0) -> B

对于测试数据点 (2.5, 2.5),K = 3 时,分类结果可能为 "A"。

可改进的地方:

  • 支持不同的距离度量方式(如曼哈顿距离)。
  • 添加对回归任务的支持。

打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在