#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. 搞定 mybatis generator 三步走

    基于idea 编辑器下maven项目使用mybatis generator快速生成持久层 添加插件:插件网址:http://www.mybatis.org/generator/running/runn ...

  2. shell脚本结构化语句

    本文中记录一下shell中的两种循环语句:for和while for循环 for循环是linux shell中最常用的结构,for循环有三种结构:1.列表for循环.2.不带列表for循环.3.C风格 ...

  3. yii2邮箱发送

    yii2 邮件发送  163邮箱 1.在配置文件main-local.php components=>[]里面配置 'mailer' => [ 'class' => 'yii\swi ...

  4. Redis ---------- 持久化(AOF)操作

    每小时做一次快照持久化 8:00 快照持久化 9:00 快照持久化 10:00  快照持久化  上帝想玩弄人类,突然停电,55万个key丢失了 11:00 快照持久化 解决方案: 8:00-9:00在 ...

  5. Python解压ZIP、RAR等常用压缩格式的方法

    解压大杀器 首先祭出可以应对多种压缩包格式的python库:patool.如果平时只用基本的解压.打包等操作,也不想详细了解各种压缩格式对应的python库,patool应该是个不错的选择. pato ...

  6. Pythony的数据类型和变量使用方法详解

    数据类型:计算机顾名思义就是可以做数学计算的机器,因此,计算机程序理所当然地可以处理各种数值.但是,计算机能处理的远不止数值,还可以处理文本.图形.音频.视频.网页等各种各样的数据,不同的数据,需要定 ...

  7. ERROR 1005 (HY000): Can't create table 'students.#sql-d9

    今天在创建外键的时候出现以下错误        ERROR 1005 (HY000): Can't create table 'students.#sql-d99_3' (errno: 150) 格式 ...

  8. 最短路径之迪杰斯特拉算法(Java)

    1)Dijkstra算法适用于求图中两节点之间最短路径 2)Dijkstra算法设计比较巧妙的是:在求源节点到终结点自底向上的过程中,源节点到某一节点之间最短路径的确定上(这也是我之前苦于没有解决的地 ...

  9. Codeforces146D 概率DP

    Bag of mice The dragon and the princess are arguing about what to do on the New Year's Eve. The drag ...

  10. Java设置模式

    单例模式 装饰者模式 代理模式