#include <stdio.h>
#include <io.h>
#include <math.h>
#include <stdlib.h> #define K 10 //kNN中选取最近邻居的个数
#define LINE 1024 //每个文件字符数 const char *to_search_train = "F:\\kNN\\train\\*.txt"; //train数据地址
const char *to_search_test = "F:\\kNN\\test\\*.txt"; //test数据地址 struct //定义结构体 储存train数据和标签
{
int train_mat[2000][LINE]; //矩阵每一行都是1*LINE的矩阵
int train_label[2000]; //储存每个数据的标签 }Train; struct //定义结构体 储存test数据和标签
{
int test_mat[2000][LINE];
int test_label[2000]; }Test; float mat_dist[1000][2000]; //定义距离矩阵,储存每个test数据到每个train数据的距离 //定义子函数,功能:将每个test数据与所有train数据的距离进行排序,选取距离最小的前K个,这K个数据标签类型最多的,将此标签返回给主函数
int BubbleSort(float mat_dist_row[], int label[],int num_train)
{
int i,j,k;
int temp,temp_label;
int num[K] = {0};
int max = 0;
int label_final = 0; for(i = 0;i < num_train;i++) //冒泡排序,距离从小到大,同时将label对应跟随
{
for(j = i+1;j < num_train;j++)
{
if(mat_dist_row[i] > mat_dist_row[j])
{
temp = mat_dist_row[i];
mat_dist_row[i] = mat_dist_row[j];
mat_dist_row[j] = temp; temp_label = label[i];
label[i] = label[j];
label[j] = temp_label;
}
}
} for (k = 0;k < K;k++) //统计前K个数据,各种标签的个数
{
switch(label[k])
{
case 0: num[0]++;break;
case 1: num[1]++;break;
case 2: num[2]++;break;
case 3: num[3]++;break;
case 4: num[4]++;break;
case 5: num[5]++;break;
case 6: num[6]++;break;
case 7: num[7]++;break;
case 8: num[8]++;break;
case 9: num[9]++;break;
default: break;
}
} max = num[0]; for(i = 0;i < K;i++) //标签类型最多的,选择次标签
{
if (num[i] > max )
{
max = num[i];
label_final = i;
}
}
return label_final;
} int main()
{ FILE *fp;
int c; //用于逐个读入字符数据
int train_i = 0,train_j = 0,test_i = 0,test_j = 0; //用于循环
int count_train = 0,count_test = 0; //用于统计train和test文件的个数
int i,j,k,l; //用于循环
int sum = 0; //距离求和
int update_label[2000]; //每次调用函数,更新label
int classifier; //记录返回的标签类型
int count = 0; //错误的个数
float rate; //错误率 char str_adr[255]; //fopen函数读入文件名时地址
long handle; //用于查找的句柄
struct _finddata_t fileinfo; //文件信息的结构体 handle = _findfirst(to_search_train,&fileinfo); //第一次查找
sprintf(str_adr, "F:\\kNN\\train\\%s", fileinfo.name); //文件名赋给str_adr if(-1 == handle)
{
printf("File not exit\n");
}
else
{
switch(fileinfo.name[0]) //给第一个文件赋予标签
{
case '0': Train.train_label[count_train] = 0;break;
case '1': Train.train_label[count_train] = 1;break;
case '2': Train.train_label[count_train] = 2;break;
case '3': Train.train_label[count_train] = 3;break;
case '4': Train.train_label[count_train] = 4;break;
case '5': Train.train_label[count_train] = 5;break;
case '6': Train.train_label[count_train] = 6;break;
case '7': Train.train_label[count_train] = 7;break;
case '8': Train.train_label[count_train] = 8;break;
case '9': Train.train_label[count_train] = 9;break;
default: break;
} count_train++; if((fp = fopen(str_adr,"r")) == NULL)
printf("Error!Can't open the file!\n"); else //将文件中'0'和'1'字符转化为数字0,1,并储存
{
while((c = fgetc(fp)) != EOF)
{
if(c == '0' || c == '1')
{
Train.train_mat[train_i][train_j] = c - '0';
train_j++;
}
}
} fclose(fp); while(!_findnext(handle,&fileinfo)) //循环查找其他符合的文件,知道找不到其他的为止
{ train_j = 0;
train_i++; sprintf(str_adr, "F:\\kNN\\train\\%s", fileinfo.name); switch(fileinfo.name[0]) //给后面文件赋予标签
{
case '0': Train.train_label[count_train] = 0;break;
case '1': Train.train_label[count_train] = 1;break;
case '2': Train.train_label[count_train] = 2;break;
case '3': Train.train_label[count_train] = 3;break;
case '4': Train.train_label[count_train] = 4;break;
case '5': Train.train_label[count_train] = 5;break;
case '6': Train.train_label[count_train] = 6;break;
case '7': Train.train_label[count_train] = 7;break;
case '8': Train.train_label[count_train] = 8;break;
case '9': Train.train_label[count_train] = 9;break;
default: break;
}
if((fp = fopen(str_adr,"r")) == NULL)
printf("Error!Can't open the file!\n");
else //将文件中'0'和'1'字符转化为数字0,1,并储存
{
while((c = fgetc(fp)) != EOF)
{
if(c == '0' || c == '1')
{
Train.train_mat[train_i][train_j] = c - '0';
train_j++;
}
}
} count_train++;
fclose(fp);
}
}
_findclose(handle); //下面重复上面文件读入和储存的过程,读入并储存所有test数据
handle = _findfirst(to_search_test,&fileinfo);
sprintf(str_adr, "F:\\kNN\\test\\%s", fileinfo.name); if(-1 == handle)
{
printf("File not exit\n");
}
else
{
switch(fileinfo.name[0])
{
case '0': {Test.test_label[count_test] = 0;break;}
case '1': {Test.test_label[count_test] = 1;break;}
case '2': {Test.test_label[count_test] = 2;break;}
case '3': {Test.test_label[count_test] = 3;break;}
case '4': {Test.test_label[count_test] = 4;break;}
case '5': {Test.test_label[count_test] = 5;break;}
case '6': {Test.test_label[count_test] = 6;break;}
case '7': {Test.test_label[count_test] = 7;break;}
case '8': {Test.test_label[count_test] = 8;break;}
case '9': {Test.test_label[count_test] = 9;break;}
default: break;
} count_test++; if((fp = fopen(str_adr,"r")) == NULL)
printf("Error!Can't open the file!\n"); else
{
while((c = fgetc(fp)) != EOF)
{
if(c == '0' || c == '1')
{
Test.test_mat[test_i][test_j] = c - '0';
test_j++;
}
}
} fclose(fp); while(!_findnext(handle,&fileinfo))
{ test_j = 0;
test_i++;
sprintf(str_adr, "F:\\kNN\\test\\%s", fileinfo.name); switch(fileinfo.name[0])
{
case '0': {Test.test_label[count_test] = 0;break;}
case '1': {Test.test_label[count_test] = 1;break;}
case '2': {Test.test_label[count_test] = 2;break;}
case '3': {Test.test_label[count_test] = 3;break;}
case '4': {Test.test_label[count_test] = 4;break;}
case '5': {Test.test_label[count_test] = 5;break;}
case '6': {Test.test_label[count_test] = 6;break;}
case '7': {Test.test_label[count_test] = 7;break;}
case '8': {Test.test_label[count_test] = 8;break;}
case '9': {Test.test_label[count_test] = 9;break;}
default: break;
}
if((fp = fopen(str_adr,"r")) == NULL)
printf("Error!Can't open the file!\n");
else
{
while((c = fgetc(fp)) != EOF)
{
if(c == '0' || c == '1')
{
Test.test_mat[test_i][test_j] = c - '0';
test_j++;
}
}
} count_test++;
fclose(fp);
}
}
_findclose(handle); for (i = 0;i < count_test;i++) //计算每个test(循环中的i)数据到每个train(循环中的j)数据的距离
{
for (j = 0;j < count_train;j++)
{
for (k = 0;k < LINE;k++)
{
sum =sum + (Test.test_mat[i][k]-Train.train_mat[j][k])*(Test.test_mat[i][k]-Train.train_mat[j][k]);
}
mat_dist[i][j] = sqrt(sum);
sum = 0;
} for (l = 0;l < count_train;l++) //更新train数据的label
{
update_label[l] = Train.train_label[l];
} classifier = BubbleSort(mat_dist[i],update_label,count_train);//调用子函数,得到第i个test数据的标签 if (Test.test_label[i] != classifier) //统计错误个数
{
count++;
}
printf("the real answer is: %d, the classififier is: %d\n",Test.test_label[i],classifier);//打印
}
rate = (float)count/count_test; //计算错误率
printf("the total number of errors is: %d\n",count); //打印
printf("the total error rate is: %f\n",rate); return 0;
}

干了将近一周才把这个程序写出来,其中遇到了很多很多问题,下面做一点总结:
1、读入文件中的数据不熟悉。在读入txt文件上耗费了太多的时间。
2、对数组、指针了解太少。大数组要定义在外边作为全局就不会“太大”,数组传递以后实参也会改变。
3、对新定义的变量,能赋初值的就赋上初值。
4、杜绝编译、运行检验错误的思想,要觉得没问题了,再去编译和运行。

几个尚未解决的问题:
1、数组如何定义不会“太大”;
2、程序中读入的程序如何变成通用的子函数;
3、指针不会用;
4、找大神帮着改一下提高效率。
这些问题要解决!

《机器学习实战》读书笔记—k近邻算法c语言实现(win下)的更多相关文章

  1. <机器学习实战>读书笔记--k邻近算法KNN

    k邻近算法的伪代码: 对未知类别属性的数据集中的每个点一次执行以下操作: (1)计算已知类别数据集中的点与当前点之间的距离: (2)按照距离递增次序排列 (3)选取与当前点距离最小的k个点 (4)确定 ...

  2. 机器学习实战 - 读书笔记(12) - 使用FP-growth算法来高效发现频繁项集

    前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习心得,这次是第12章 - 使用FP-growth算法来高效发现频繁项集. 基本概念 FP-growt ...

  3. 机器学习实战 - 读书笔记(11) - 使用Apriori算法进行关联分析

    前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习心得,这次是第11章 - 使用Apriori算法进行关联分析. 基本概念 关联分析(associat ...

  4. 机器学习实战 - 读书笔记(07) - 利用AdaBoost元算法提高分类性能

    前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习笔记,这次是第7章 - 利用AdaBoost元算法提高分类性能. 核心思想 在使用某个特定的算法是, ...

  5. 机器学习实战 - 读书笔记(13) - 利用PCA来简化数据

    前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习心得,这次是第13章 - 利用PCA来简化数据. 这里介绍,机器学习中的降维技术,可简化样品数据. ...

  6. 机器学习实战笔记--k近邻算法

    #encoding:utf-8 from numpy import * import operator import matplotlib import matplotlib.pyplot as pl ...

  7. 机器学习(1)——K近邻算法

    KNN的函数写法 import numpy as np from math import sqrt from collections import Counter def KNN_classify(k ...

  8. R语言学习笔记—K近邻算法

    K近邻算法(KNN)是指一个样本如果在特征空间中的K个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别,并具有这个类别上样本的特性.即每个样本都可以用它最接近的k个邻居来代表.KNN算法适 ...

  9. k近邻算法C++二维情况下的实现

    k近邻算法C++二维实现 这是一个k近邻算法的二维实现(即K=2的情况). #include <cstdio> #include <cstring> #include < ...

随机推荐

  1. 谈谈对bug的一点想法,说说做好日志记录的重要性

    说起程序猿,总绕不开的一个话题就是bug,估计每个程序猿听到某某测试跑过来一脸淫笑的告诉你这个功能有个bug的时候,总有种恨不得掐死他的想法.其实程序猿跟bug的关系,感觉有点像父亲和儿子的关系,自己 ...

  2. $.each() 循环遍历完后阻止再执行的办法

    jquery each循环遍历完再执行的方法 因为each是异步的 所以要加计数器. query each循环遍历完再执行的方法 因为each是异步的 所以要加计数器.var eachcount=0; ...

  3. python实现简单分类knn算法

    原理:计算当前点(无label,一般为测试集)和其他每个点(有label,一般为训练集)的距离并升序排序,选取k个最小距离的点,根据这k个点对应的类别进行投票,票数最多的类别的即为该点所对应的类别.代 ...

  4. (一)、Python的简介与安装

    Python简介 Python的创始人为Guido van Rossum.1989年圣诞节期间,在阿姆斯特丹,Guido为了打发圣诞节的无趣,决心开发一个新的脚本解释程序,作为ABC 语言的一种继承. ...

  5. Jenkins持续化集成

    Jenkins介绍 Jenkins是基于Java开发的一种持续集成工具,用于监控持续重复的工作,功能包括: 1.持续的软件版本发布/测试项目. 2.监控外部调用执行的工作. 安装环境 操作系统:lin ...

  6. jira安装说明

    阅读目录 1.1 jira说明 1.2 安装配置jira 1.3 web界面访问 1.4 创建第一个项目 1.5 参考文献 回到顶部 1.1 jira说明 JIRA是Atlassian公司出品的项目与 ...

  7. POJ:1017-Packets(贪心+模拟,神烦)

    传送门:http://poj.org/problem?id=1017 Packets Time Limit: 1000MS Memory Limit: 10000K Total Submissions ...

  8. [CodeForces - 296D]Greg and Graph(floyd)

    Description 题意:给定一个有向图,一共有N个点,给邻接矩阵.依次去掉N个节点,每一次去掉一个节点的同时,将其直接与当前节点相连的边和当前节点连出的边都需要去除,输出N个数,表示去掉当前节点 ...

  9. Java线程---简介

    实现方式 在java中线程有两种实现方式: 1.继承thread类 2.实现runnable接口 Thread类 Thread类时在java.lang包中定义的,继承thread类必须重写run()方 ...

  10. 3611: [Heoi2014]大工程

    3611: [Heoi2014]大工程 链接 分析: 树形dp+虚树. 首先建立虚树,在虚树上dp. dp:sum[i]为i的子树中所有询问点之间的和.siz[i]为i的子树中有多少询问点,mn[i] ...