《机器学习实战》学习笔记——kNN算法

来源:互联网 发布:公司公司招聘数据 编辑:程序博客网 时间:2024/06/06 04:53

《机器学习实战》(MLiA)是一本介绍机器学习的书(的确是废话),和其他书不同的地方在于它给出了python的实现代码,而其他的书籍重在解释理论。我作为一名渣渣,理论就先放一放了。
MLiA的第一章主要介绍了一些概念、常识性的东西,所以不做介绍,这篇文章主要介绍k-近邻算法(kNN)。

kNN算法的优点是精度高,对异常值(离群点)不敏感且不需要训练;缺点是计算复杂度、空间复杂度高
kNN算法的适用范围是数值型和标称型数据

kNN工作原理是:

存在一个样本数据集合,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分类的对应关系。输人没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标签。一般来说,我们只选择样本数据集中前k个最相似的数据,这就是k-近邻算法中k的出处,通常k是不大于20的整数。最后,选择k个最相似数据中出现次数最多的分类,作为新数据的分类。

kNN算法的算法流程为:

(1).计算已知类别数据集中的点与当前点之间的距离;
(2).按照距离递增次序排序;
(3).选取与当前点距离最小的k个点;
(4).确定前k个点所在类别的出现频率;
(5).返回前k个点出现频率最高的类别作为当前点的预测分类。

既然算法流程已经明确,现在开始构造自己的算法。《MLiA》中采用的是python来构造的算法,原因是机器学习的算法大都需要处理复杂的矩阵运算。鉴于自己的算法处理的数据特征维数并不多,矩阵运算较少,故写了一个简单的c++版本

/*  kNN.cpp*   @author: Toroto*/#include <iostream>#include <math.h>using namespace std;#define DSSIZE 8    //训练集大小/**   数据结构:*   包含两个特征:x, y*   及标记:label*/struct data{    float x, y;    char label;};data D[DSSIZE];     //训练集float dis[DSSIZE];  //距离数组//设置训练集://{(0,0),(0,0.1),(0,0.2)(0,0.3),(1,1.4),(1,1.5),(1,1.6),(1,1.7)}void init(int x){    for (int i = 0; i < x; i++){        if (i < 4){            D[i].x = 0;            D[i].label = 'A';        }        else {            D[i].x = 1;            D[i].label = 'B';        }        D[i].y = D[i].x + 0.1 * i;    }};/**   kNN算法实现:*   参数:*       x, y: 目标向量        k:最近邻居的数目*   返回值:待分类向量的标签*/char kNN(float x, float y, int k){    float temp;    data tem;    for (int i = 0; i < DSSIZE; i++){        //计算目标向量到各训练数据的距离        dis[i] = pow(pow(x - D[i].x, 2) + pow(y - D[i].y, 2), 0.5);//      cout << "i = " << i << "; distance = " << dis[i] << endl;    }    //排序    for (int i = 0; i < DSSIZE; i++){        for (int j = i; j < DSSIZE; j++){            if (dis[i] > dis[j]){                temp = dis[i];                dis[i] = dis[j];                dis[j] = temp;                tem = D[i];                D[i] = D[j];                D[j] = tem;            }        }    }    /*    for (int i = 0; i < DSSIZE; i++){        cout << D[i].x << " " << D[i].y << " " << D[i].label << " " << dis[i] << endl;    }    //*/    int label_A = 0, label_B = 0;    //在给定数目的最近邻居中选择出现次数最多的邻居    for (int i = 0; i < k; i++){        if (D[i].label == 'A') label_A++;        else label_B++;    }    return label_A > label_B ? 'A' : 'B';}int main(){    init(DSSIZE);    int k;    float x, y;    char label;    cout << "输入x, y: ";    cin >> x >> y;    cout << "输入k :";    cin >> k;    label = kNN(x * 1.0, y * 1.0, k);    cout << label << endl;    return 0;};

这样就完成了一个简单版的kNN。

测试:
输入0.1 ,0.2, k = 5,结果如下:
这里写图片描述

输入0.8, 1.2, k = 5, 结果如下:
这里写图片描述

0 0
原创粉丝点击