当前位置:   article > 正文

KNN算法 c++实现_c++ knn

c++ knn

来源【机器学习实战之一】:C++实现K-近邻算法KNN_两个图像的特征向量应用knn模型进行匹配-CSDN博客

k-近邻(kNN, k-NearestNeighbor)是在训练集中选取离输入的数据点最近的k个邻居,根据这个k个邻居中出现次数最多的类别(最大表决规则),作为该数据点的类别。 

  1. //计算每个训练数据到待分类元组的距离,取和待分类元组距离最近的k个训练数据,k个数据中哪个类别的训练数据占多数,则待分类元组就属于哪个类别。
  2. #include<iostream>
  3. #include<map>
  4. #include<vector>
  5. #include<stdio.h>
  6. #include<cmath>
  7. #include<cstdlib>
  8. #include<algorithm>
  9. #include<fstream>
  10. #include <filesystem>
  11. using namespace std;
  12. const int col = 2;
  13. const int row = 12;
  14. typedef double TData;
  15. typedef char tData;
  16. //typedef pair<int, double> Pari;
  17. ifstream fin; //输入文件流,可以用于从文件中读取数据。通过构造函数或 open() 成员函数打开指定的文件,然后使用输入运算符( >> )和其他输入操作从文件中读取数据:
  18. ofstream fout;
  19. class KNN
  20. {
  21. private:
  22. int k;
  23. TData TSet[row][col]; //训练数据
  24. TData Test[col]; //测试数据
  25. tData labels[row]; //类别
  26. map<int, double> dis_index;
  27. map<tData,int> label_count;
  28. public:
  29. KNN(int k);
  30. double distance(TData* t1, TData* t2);
  31. void All_distance();
  32. void get_label();
  33. struct cmp
  34. {
  35. //调用运算符 operator() 的重载使得对象可以像函数一样使用,具有类似函数的行为,因此也称为函数对象。
  36. bool operator()(const pair<int,double>& a, const pair<int,double>& b) //常量引用类型 const T&
  37. {
  38. return a.second < b.second;
  39. }
  40. };
  41. };
  42. KNN::KNN(int k)
  43. {
  44. this->k = k;
  45. fin.open("data.txt");
  46. if (!fin)
  47. {
  48. cout << "can not open the data.txt" << endl;
  49. exit(1);
  50. }
  51. for (int i = 0; i < row; i++)
  52. {
  53. for (int j = 0; j < col; j++)
  54. {
  55. fin >> TSet[i][j];
  56. }
  57. fin >> labels[i];
  58. }
  59. cout << "请输入test data:" << endl;
  60. for(int i=0;i<col;i++)
  61. {
  62. cin >> Test[i];
  63. }
  64. }
  65. //数据集和测试数据对应坐标的距离和
  66. double KNN::distance(TData *t1, TData *t2)
  67. {
  68. double sum = 0;
  69. for (int i = 0; i < col; i++)
  70. {
  71. sum += pow((t1[i] - t2[i]), 2);
  72. }
  73. return sqrt(sum);
  74. }
  75. void KNN::All_distance()
  76. {
  77. double dis;
  78. for (int i = 0; i < row; i++)
  79. {
  80. dis = distance(TSet[i], Test);
  81. dis_index[i] = dis; //每一个训练数据到测试数据的dis
  82. }
  83. map<int, double>::const_iterator i = dis_index.begin();
  84. for (i; i != dis_index.end(); i++)
  85. {
  86. cout << "index=" << i->first << " distance=" << i->second << endl; //获取键和值
  87. }
  88. }
  89. //得到测试数据的类别
  90. void KNN::get_label()
  91. {
  92. vector<pair<int,double>> vec_dis_index(dis_index.begin(), dis_index.end()); //包含了从 map 容器中复制出来的所有键值对
  93. //sort(vec_dis_index.begin(), vec_dis_index.end(), cmp()); //通常用来对数组或向量等容器类型进行排序sort(first, last [, comp]);
  94. sort(vec_dis_index.begin(), vec_dis_index.end(), [&](const pair<int, double>& a, const pair<int, double>& b) {return a.second < b.second; });
  95. for (int i = 0; i < k; i++)
  96. {
  97. cout << "index=" << vec_dis_index[i].first << " distance=" << vec_dis_index[i].second << " 类别=" << labels[vec_dis_index[i].first] << " 坐标=(" << TSet[vec_dis_index[i].first][0] << "," << TSet[vec_dis_index[i].first][1] << ")" << endl;
  98. label_count[labels[vec_dis_index[i].first]]++;
  99. }
  100. int max = 0;
  101. tData t;
  102. for (map<char, int>::const_iterator i = label_count.begin(); i != label_count.end(); i++)
  103. {
  104. if (i->second > max)
  105. {
  106. max = i->second;
  107. t=i->first;
  108. }
  109. }
  110. cout << "测试数据属于的类别" << t << endl;
  111. }
  112. int main()
  113. {
  114. int k;
  115. cout << "请输入k的值" << endl;
  116. cin >> k;
  117. KNN knn(k);
  118. knn.All_distance();
  119. knn.get_label();
  120. }

结果


例题: 

某班有14个同学,已登记身高及等级,新同学易昌,身高1.74cm,等级是什么。请用knn算法进行分类识别,其中k=5。

序号

姓名

身高(cm)

等级

1

李丽

1.5

2

吉米

1.92

3

马大华

1.7

中等

4

王晓华

1.73

中等

5

刘敏

1.6

6

张强

1.75

中等

7

李秦

1.6

8

王壮

1.9

9

刘冰

1.68

中等

10

张喆

1.78

中等

11

杨毅

1.70

中等

12

徐田

1.68

中等

13

高杰

1.65

14

张晓

1.78

中等

 

  1. //计算每个训练数据到待分类元组的距离,取和待分类元组距离最近的k个训练数据,k个数据中哪个类别的训练数据占多数,则待分类元组就属于哪个类别。
  2. #include<iostream>
  3. #include<map>
  4. #include<vector>
  5. #include<stdio.h>
  6. #include<cmath>
  7. #include<cstdlib>
  8. #include<algorithm>
  9. #include<fstream>
  10. #include <filesystem>
  11. #include <sstream>
  12. #include <locale.h>
  13. #include <Windows.h>
  14. using namespace std;
  15. ifstream fin; //输入文件流,可以用于从文件中读取数据。通过构造函数或 open() 成员函数打开指定的文件,然后使用输入运算符( >> )和其他输入操作从文件中读取数据:
  16. ofstream fout;
  17. struct Person {
  18. std::string name;
  19. double height;
  20. std::string category;
  21. };
  22. vector<Person> dataset;
  23. Person test;
  24. class KNN
  25. {
  26. private:
  27. int k;
  28. map<int, double> dis_index;
  29. map<string, int> label_count;
  30. public:
  31. KNN(int k);
  32. double distance(Person t1, Person t2);
  33. void All_distance();
  34. void get_label();
  35. };
  36. KNN::KNN(int k)
  37. {
  38. this->k = k;
  39. ifstream file("data.txt");
  40. if (file.is_open())
  41. {
  42. string line;
  43. while (getline(file, line)) {
  44. stringstream ss(line); //
  45. string name, category;
  46. double height;
  47. ss >> name >> height >> category;
  48. dataset.push_back({ name, height, category });
  49. }
  50. }
  51. }
  52. //数据集和测试数据
  53. double KNN::distance(Person t1, Person t2)
  54. {
  55. return abs(t1.height - t2.height);
  56. }
  57. void KNN::All_distance()
  58. {
  59. double dis;
  60. for (int i = 0; i < dataset.size(); i++)
  61. {
  62. dis = distance(dataset[i], test);
  63. dis_index[i] = dis; //每一个训练数据到测试数据的dis
  64. }
  65. map<int, double>::const_iterator i = dis_index.begin();
  66. cout << "index " << "姓名 " << "distance " << "类别 " << endl;
  67. for (i; i != dis_index.end(); i++)
  68. {
  69. cout << i->first+1 <<" " << dataset[i->first].name << " " << i->second << " " << dataset[i->first].category << endl; //获取键和值
  70. }
  71. }
  72. //得到测试数据的类别
  73. void KNN::get_label()
  74. {
  75. vector<pair<int, double>> vec_dis_index(dis_index.begin(), dis_index.end()); //包含了从 map 容器中复制出来的所有键值对
  76. //sort(vec_dis_index.begin(), vec_dis_index.end(), cmp()); //通常用来对数组或向量等容器类型进行排序sort(first, last [, comp]);
  77. sort(vec_dis_index.begin(), vec_dis_index.end(),
  78. [&](const pair<int, double>& a, const pair<int, double>& b) {return a.second < b.second; });
  79. cout << endl<<"最近的k个簇的类别为" << endl;
  80. for (int i = 0; i < k; i++)
  81. {
  82. cout << "index=" << vec_dis_index[i].first+1 << " name="<< dataset[vec_dis_index[i].first].name<<" distance = " << vec_dis_index[i].second << " 类别 = " << dataset[vec_dis_index[i].first].category << endl;
  83. label_count[dataset[vec_dis_index[i].first].category]++;
  84. }
  85. int max = 0;
  86. string t;
  87. for (map<string, int>::const_iterator i = label_count.begin(); i != label_count.end(); i++)
  88. {
  89. if (i->second > max)
  90. {
  91. max = i->second;
  92. t = i->first;
  93. }
  94. }
  95. cout << endl<<"测试数据属于的类别" << t << endl;
  96. }
  97. int main()
  98. {
  99. int k;
  100. cout << "请输入k的值" << endl;
  101. cin >> k;
  102. cout << "输入测试数据" << endl;
  103. cin >> test.name >> test.height;
  104. KNN knn(k);
  105. knn.All_distance();
  106. knn.get_label();
  107. }

运行结果

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/运维做开发/article/detail/801254
推荐阅读
相关标签
  

闽ICP备14008679号