C语言经典算法之k最近邻(K-Nearest Neighbor, KNN)算法

这篇具有很好参考价值的文章主要介绍了C语言经典算法之k最近邻(K-Nearest Neighbor, KNN)算法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

前言

A.建议

B.简介

一 代码实现

二 时空复杂度

A.时间复杂度:

B.空间复杂度:

C.总结:

三 优缺点

A.优点:

B.缺点:

四 现实中的应用


前言

A.建议

1.学习算法最重要的是理解算法的每一步,而不是记住算法。

2.建议读者学习算法的时候,自己手动一步一步地运行算法。

B.简介

k最近邻(K-Nearest Neighbor, KNN)算法是一种基于实例的学习方法,主要用于分类和回归问题。在机器学习中,它不预先假设数据分布模型,而是直接存储训练样本,并在预测阶段根据新样本与已有训练样本之间的相似度进行决策。

一 代码实现

使用C语言实现K最近邻(K-Nearest Neighbor, KNN)算法通常涉及以下步骤:

定义数据结构: 首先,需要定义存储训练样本和测试样本的数据结构。这可能包括特征向量、类标签以及用于计算距离的函数指针等。

typedef struct {
    double *features; // 特征向量,例如double features[N_FEATURES];
    int label;        // 类别标签
} Sample;

// 假设我们已经有了一个预处理好的样本集
Sample trainingSet[TRAINING_SET_SIZE];

计算距离: 选择一种距离度量方法,如欧氏距离或曼哈顿距离,并编写函数来计算测试样本与每个训练样本之间的距离。

double euclideanDistance(Sample s1, Sample s2) {
    int i;
    double distance = 0.0;
    for (i = 0; i < N_FEATURES; ++i) {
        distance += pow(s1.features[i] - s2.features[i], 2);
    }
    return sqrt(distance);
}

// 或者用曼哈顿距离
double manhattanDistance(Sample s1, Sample s2) {
    int i;
    double distance = 0.0;
    for (i = 0; i < N_FEATURES; ++i) {
        distance += abs(s1.features[i] - s2.features[i]);
    }
    return distance;
}

排序邻居: 对于给定的测试样本,计算它与所有训练样本的距离,并根据距离从近到远排序。

#include <stdlib.h>
#include <stdio.h>

// 假设有函数对距离进行排序
void sortSamplesByDistance(Sample* samples, double* distances, int n) {
    // 这里应实现一个快速排序、归并排序或其他合适算法对distances数组进行排序,并相应调整samples顺序
}

// 应用排序函数
Sample sortedNeighbors[TRAINING_SET_SIZE];
double distances[TRAINING_SET_SIZE];

for (int i = 0; i < TRAINING_SET_SIZE; ++i) {
    distances[i] = euclideanDistance(testSample, trainingSet[i]);
}
sortSamplesByDistance(trainingSet, distances, TRAINING_SET_SIZE);

确定K个最近邻及其类别: 取出排序后最近的K个邻居,并统计各个类别的出现次数。

int classCounts[NUM_CLASSES] = {0};
for (int k = 0; k < K_VALUE; ++k) {
    int currentClass = sortedNeighbors[k].label;
    classCounts[currentClass]++;
}

// 找到出现次数最多的类别
int predictedClass;
int maxCount = 0;
for (int c = 0; c < NUM_CLASSES; ++c) {
    if (classCounts[c] > maxCount) {
        maxCount = classCounts[c];
        predictedClass = c;
    }
}

完整代码示例: 下面是一个简化的KNN分类器的整体框架,但请注意,实际应用中还需要考虑边界检查、内存管理、更高效的搜索策略(如kd树或球树)以及异常处理等问题。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define N_FEATURES 10 // 示例特征数量
#define TRAINING_SET_SIZE 1000 // 示例训练集大小
#define K_VALUE 5 // K值

typedef struct {
    double features[N_FEATURES];
    int label;
} Sample;

double euclideanDistance(Sample s1, Sample s2) {/* 实现欧氏距离计算 */}

void knnClassifier(Sample testSample, Sample trainingSet[], int numTrainingSamples, int K) {
    double distances[numTrainingSamples];
    Sample sortedSamples[numTrainingSamples];

    // 计算距离并排序
    for (int i = 0; i < numTrainingSamples; ++i) {
        distances[i] = euclideanDistance(testSample, trainingSet[i]);
    }
    // 这里假设已有一个排序函数
    sortDistancesAndSamples(distances, sortedSamples, trainingSet, numTrainingSamples);

    // 统计K个最近邻的类别
    int classCounts[NUM_CLASSES] = {0};
    for (int k = 0; k < K; ++k) {
        int currentClass = sortedSamples[k].label;
        classCounts[currentClass]++;
    }

    // 确定预测类别
    int predictedClass = findMaxCountClass(classCounts);

    printf("Predicted class: %d\n", predictedClass);
}

int main() {
    // 初始化训练集、加载测试样本
    // ...
    
    Sample testSample;
    // 假设testSample已经被初始化
    
    knnClassifier(testSample, trainingSet, TRAINING_SET_SIZE, K_VALUE);

    return 0;
}

上述代码仅为说明目的,并未提供完整的排序和查找最大计数类别的函数实现。在实际编程时,请根据项目需求和实际情况完善这些部分。

二 时空复杂度

A.时间复杂度:

  • 训练阶段: KNN算法在训练阶段并不需要构建模型,只是简单地存储训练数据,因此训练时间复杂度为,即与训练样本的数量无关。

  • 预测阶段:

    • 对于每一个待分类或回归的新样本,KNN都需要计算其与所有训练样本的距离。在最坏的情况下,对于每个新样本,计算个训练样本的距离所需的时间复杂度是,其中n表示训练集中的样本数量,表示特征维度。
    • 找出k个最近邻,通常需要对距离进行排序,这在没有优化的情况下时间复杂度是,但实际应用中我们往往只需要找出前小的距离,可以使用优先队列等方法将这一部分的时间复杂度降低至近似。
    • 因此,总的预测时间复杂度是 c语言k近邻算法,C语言经典算法,算法或者采用更高效的数据结构和算法后可能是 c语言k近邻算法,C语言经典算法,算法

B.空间复杂度:

  • 训练阶段: KNN算法需要存储所有的训练样本及其对应的标签,所以空间复杂度为O(n*d),其中n是训练样本数,d是每个样本的特征维度。

  • 预测阶段: 在预测过程中,除了存储训练数据之外,可能还需要额外的空间来存储中间结果,如距离矩阵、优先队列等,但这一般相对于存储训练数据所需的内存来说较小。

C.总结:

  • KNN算法在大数据集上运行时可能会非常耗时,特别是当特征维度很高时。
  • 空间复杂度较高,因为必须存储整个训练集以供查询,这对于大规模数据集是一个明显的挑战。
  • 可以通过诸如KD树、球树等数据结构来优化搜索过程,减少不必要的距离计算,从而改善时间复杂度,尤其是在低维到中等维度空间中效果显著。但在高维空间中,由于所谓的“维数灾难”,这些优化的效果会大打折扣。

三 优缺点

A.优点:

  1. 简单直观:KNN算法概念简单,易于实现和理解。它是一种非参数方法,不需要对数据进行复杂的建模。

  2. 理论成熟:适用于多种类型的数据集,无论是数值型还是离散型特征,都可以处理分类和回归问题。

  3. 可适应性强:无需预先假设数据分布,对于复杂或非线性边界的数据集表现良好。

  4. 可用于大规模数据集:尽管计算复杂度随数据量增大而增加,但在有足够内存的情况下,理论上可以处理任意大小的训练集。

  5. 在线学习:随着新样本的出现,可以直接将其添加到训练集中,无需重新训练模型。

  6. 无数据输入假定:对于异常值不太敏感,因为它是基于实例的学习,而不是基于概率统计模型。

  7. 多类别处理:天然支持多类别分类任务,通过多数表决或加权投票机制确定类别。

B.缺点:

  1. 计算复杂度高:在预测阶段,计算一个新样本与所有训练样本的距离是非常耗时的,尤其当样本数n很大时,时间复杂度为O(n*d),其中d是特征维度。

  2. 空间复杂度大:需要存储整个训练集,占用大量内存资源,空间复杂度为O(n*d)。

  3. 对样本数量不均衡的问题敏感:如果不同类别的样本数量差异悬殊,在做决策时容易偏向于样本多的类别。

  4. 选择k值困难:k值的选择直接影响模型性能,过小可能导致模型过拟合噪声,过大可能使得模型过于平滑,边界模糊不清。

  5. 不适合大规模高维数据集:随着维度的增加,“维数灾难”现象会变得严重,距离计算的效果会减弱,且搜索最近邻所需的时间显著增加。

  6. 对连续属性的处理:未经过特征缩放的连续属性可能会比其他属性更主导距离计算结果,从而影响最终预测准确性。

  7. 不适用于实时预测:由于每次预测都需要遍历整个训练集,对于实时应用或者要求快速响应的场景,KNN并不高效。

四 现实中的应用

  1. 图像识别与计算机视觉

    • KNN用于图像分类任务,例如区分不同种类的植物、动物或物体。通过计算新图像特征向量与训练集中图像特征的距离,找出最接近的k个邻居,根据这些邻居的类别来预测新图像所属类别。
  2. 医疗诊断

    • 在医学影像分析中,KNN可以用来辅助医生进行疾病诊断,如通过对病理切片图像的特征提取后使用KNN分类器来判断肿瘤的良恶性。
    • 生物信息学中,利用基因表达数据或其他生物标志物特征,KNN可帮助预测病人的疾病类型或预后。
  3. 推荐系统

    • KNN常被应用于协同过滤推荐算法中,通过找到用户历史行为记录中最相似的k个邻居用户,然后推荐他们喜欢的商品或服务给目标用户。
  4. 手写字符识别

    • 对于手写数字或字母的识别问题,KNN可以根据特征向量之间的距离确定输入图案最可能对应的手写字符。
  5. 金融风控

    • 在信贷审批中,KNN可用于信用评分模型,通过分析客户的类似属性(如收入、年龄、职业等),预测潜在的违约风险。
  6. 地理信息系统(GIS)

    • 在地理数据分析中,KNN可用于查找邻近的服务设施、进行空间聚类分析,或者进行地理定位时提供“附近地点”推荐。
  7. 农业和环境科学

    • 利用气象数据和其他作物生长相关特征,KNN可用于预测农作物产量或病虫害发生的可能性。
  8. 市场细分与客户分类

    • 市场营销中,根据客户购买历史、人口统计学特征等因素,KNN可以帮助划分客户群体,实现更精准的产品推广和服务定制。
  9. 语音识别文章来源地址https://www.toymoban.com/news/detail-849551.html

    • 在语音信号处理中,KNN可以用于将未知声音片段与已知库中的样本进行匹配,从而识别出说话者或翻译成文本。

到了这里,关于C语言经典算法之k最近邻(K-Nearest Neighbor, KNN)算法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 机器学习算法:K近邻(k-nearest neighbors)初探

    KNN的介绍和应用 KNN(K-Nearest Neighbor)算法是一种基于实例的学习算法,也是一种常见的分类算法。 如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。 示例 :如上图,绿色圆要被决定赋予哪个类,是红

    2023年04月08日
    浏览(43)
  • 算法笔记 近似最近邻查找(Approximate Nearest Neighbor Search,ANN)

    精准最近邻搜索中数据维度一般较低,所以会采用穷举搜索,即在数据库中依次计算其中样本与所查询数据之间的距离,抽取出所计算出来的距离最小的样本即为所要查找的最近邻。 当数据量非常大的时候,搜索效率急剧下降。 ——近似最近邻查找(Approximate Nearest Neighbor

    2024年02月09日
    浏览(40)
  • 李飞飞计算机视觉k-Nearest Neighbor

    给计算机很多数据,然后实现学习算法,让计算机学习到每个类的外形 输入:输入是包含N个图像的集合,每个图像的标签是K种分类标签中的一种。这个集合称为训练集。 学习:这一步的任务是使用训练集来学习每个类到底长什么样。一般该步骤叫做训练分类器或者学习一个

    2024年02月17日
    浏览(38)
  • 四、分类算法 - KNN算法(K-近邻算法)

    目录 1、K-近邻算法 1.1 K-近邻算法原理 1.2 K - 近邻算法API 1.3 案例1:鸢尾花种类预测 1.3.1 数据集介绍 1.3.2 步骤 1.4 KNN 算法总结 sklearn转换器和估算器 KNN算法 模型选择和调优 朴素贝叶斯算法 决策树 随机森林 1.3.1 数据集介绍 1.3.2 步骤 获取数据 数据集划分 特征工程   - 标准

    2024年02月22日
    浏览(50)
  • 【机器学习实战】K- 近邻算法(KNN算法)

    K-近邻算法 ,又称为  KNN 算法 ,是数据挖掘技术中原理最简单的算法。 KNN  的工作原理:给定一个已知类别标签的数据训练集,输入没有标签的新数据后,在训练数据集中找到与新数据最临近的 K 个实例。如果这 K 个实例的多数属于某个类别,那么新数据就属于这个类别。

    2023年04月20日
    浏览(57)
  • 8_分类算法-k近邻算法(KNN)

    定义:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。 来源:KNN算法最早是由Cover和Hart提出的一种分类算法 K近邻(K-nearst neighbors,KNN)是一种基本的机器学习算法,所谓k近邻,就是k个最近的邻居

    2024年02月11日
    浏览(41)
  • 机器学习——K近邻(KNN)算法

    目录 一、knn算法概述 1.简单介绍 2.工作原理 3.knn算法中常用的距离指标 4.knn算法优势 5.knn算法一般流程 二、knn算法经典实例——海伦约会网站 三、关于天气和旅行适合度的例子 四、总结 K近邻算法(KNN)是一种用于分类和回归的统计方法。k-近邻算法采用测量不同特征值之

    2024年01月16日
    浏览(39)
  • 机器学习之——K近邻(KNN)算法

                    k-近邻算法(K-Nearest Neighbors,简称KNN)是一种用于分类和回归的统计方法。KNN 可以说是最简单的分类算法之一,同时,它也是最常用的分类算法之一。                 k-近邻算法基于某种距离度量来找到输入样本在训练集中的k个最近邻居,并且根据这k个

    2024年04月10日
    浏览(40)
  • 机器学习——K最近邻算法(KNN)

    机器学习——K最近邻算法(KNN) 在传统机器学习中,KNN算法是一种基于实例的学习算法,能解决分类和回归问题,而本文将介绍一下KNN即K最近邻算法。 K最近邻(KNN)算法是一种基于实例的学习算法,用于分类和回归问题。它的原理是 根据样本之间的距离来进行预测 。 核

    2024年02月09日
    浏览(43)
  • 机器学习之KNN(K近邻)算法

    KNN算法又叫做K近邻算法,是众多机器学习算法里面最基础入门的算法。KNN算法是最简单的分类算法之一,同时,它也是最常用的分类算法之一。KNN算法是有监督学习中的分类算法,它看起来和Kmeans相似(Kmeans是无监督学习算法),但却是有本质区别的。 KNN算法基于实例之间

    2024年02月08日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包