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"。

可改进的地方:

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

亚丁号

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值