VS2013调用armadillo使用KNN算法实现0-9数字分类

来源:互联网 发布:淘宝hd最新版本 编辑:程序博客网 时间:2024/06/05 14:28

Perter Harrington的《机器学习实战》(Machine Learning In Action)的例子是使用python编写的,当我们使用Visual studio平台或其他C++平台时,调用C++编写的机器学习算法 可能更加方便。armadillo是一个很方便的基于C++的线性代数库,其命令格式类似于matlab。这里是VS2013下编写的《机器学习实战》第2章中 基于knn的手写数字识别 的代码,以及运行结果。

代码

#include "stdafx.h"#include <iostream>#include <fstream>#include <io.h>#include <string>#include "armadillo"using namespace arma;using namespace std;//图像矩阵转换为向量vec img2vector(string filename){    vec  returnVec = zeros(1024);    FILE *pFile;    errno_t err;    if ((err = fopen_s(&pFile, filename.c_str(), "r")) != 0)    {        cout << "文件" << filename << "打开失败" << endl;        return EXIT_SUCCESS;    }    char c;    int n = 0;    while (EOF != fscanf_s(pFile,"%c",&c,sizeof(char)))//一次读入一个字符    {        int num = c - '0';        if ((num == 0)||(num == 1))        {            returnVec(n) = num;            n++;        }    }    fclose(pFile);    return returnVec;}//KNN分类器int classifier(vec inX, mat dataSet, vec labels, int k){    int trainNum = labels.size();    mat differMat = repmat(inX, 1, trainNum) - dataSet;    mat sqDifferMat = square(differMat);    rowvec sqDistances = arma::sqrt(sum(sqDifferMat, 0));    uvec sortedDistanceIndicis = sort_index(sqDistances);//距离小到大排,ascend,升序(默认),descend降序    uvec classCount = zeros<uvec>(10);//用于记录每一类数据的个数    for (size_t i = 0; i < k; i++)    {        int valuLabel = labels(sortedDistanceIndicis(i));//获取对应标签值        classCount(valuLabel) += 1;//对应类别个数加1    }    int resultLabel = classCount.index_max();    return resultLabel;}int _tmain(int argc, _TCHAR* argv[]){    mat trainingMat = zeros(1024, 2500);//训练矩阵,每列为一个样本    vec trainingLabels = zeros(2500); //训练标签    int trainNum = 0; //记录训练样本个数    int testNum = 0; //记录测试样本个数//#############读取训练矩阵##################################    intptr_t Handle;    struct _finddata_t FileInfo;    int k;    Handle = _findfirst("digits\\trainingDigits\\*.txt", &FileInfo);    k = Handle;    if (k == -1)    {        cout << "没有找到匹配项目" << endl;    }    else    {        while (k != -1)        {            string filename = FileInfo.name;            filename = "digits\\trainingDigits\\" + filename;            trainingMat.col(trainNum) = img2vector(filename);            int labelnum = FileInfo.name[0] - '0';//将char转换为数字            trainingLabels(trainNum) = labelnum;//标签            trainNum++;            k =_findnext(Handle, &FileInfo);        }        cout << "训练样本一共有:" << trainNum << "个" << endl;    }    _findclose(Handle);    trainingMat = trainingMat(span(0, 1023), span(0, trainNum-1));    trainingLabels = trainingLabels(span(0, trainNum-1));    cout <<"样本标签个数:"<< trainingLabels.size() << endl;//#################################################################//###########################读取测试样本,并分类#########################、    Handle = _findfirst("digits\\testDigits\\*.txt", &FileInfo);    k = Handle;    if (k == -1)    {        cout << "没有找到匹配项目" << endl;    }    else    {        int errorCount = 0;//分类错误记录        while (k != -1)        {            string filename = FileInfo.name;            filename = "digits\\testDigits\\" + filename;            vec inX = img2vector(filename);            int resultclass = classifier(inX, trainingMat, trainingLabels, 4);//调用分类器            int labelnum = FileInfo.name[0] - '0';//将char转换为数字,获得标签            cout << "分类结果:" << resultclass << " 真实值:" << labelnum << endl;            if (resultclass != labelnum)            {                errorCount = errorCount + 1;            }            testNum++;            k = _findnext(Handle, &FileInfo);        }        cout << "测试样本一共有:" << testNum  << "个" << endl;        cout << "分类错误率:" << float(errorCount*1.0 / testNum) << endl;        }    _findclose(Handle);//################################################################    system("pause");    return 0;}

训练样本以及测试样本存储格式

这是一个标签为0的样本
这是一个标签为0的版本在txt里的存储格式。
《机器学习实战》的python源码和样本集可以在这里下载:
http://pan.baidu.com/s/1bp9MlND


训练效果

这里写图片描述

1 0
原创粉丝点击