C++基于特征向量的KNN分类算法怎么用

这篇文章给大家分享的是有关C++基于特征向量的KNN分类算法怎么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

站在用户的角度思考问题,与客户深入沟通,找到沂南网站设计与沂南网站推广的解决方案,凭借多年的经验,让设计与互联网技术结合,创造个性化、用户体验好的作品,建站类型包括:做网站、成都做网站、企业官网、英文网站、手机端网站、网站推广、域名注册虚拟主机、企业邮箱。业务覆盖沂南地区。

K最近邻(k-Nearest Neighbor,KNN)分类算法,是一个理论上比较成熟的方法,也是最简单的机器学习算法之一。该方法的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。KNN算法中,所选择的邻居都是已经正确分类的对象。该方法在定类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。 KNN方法虽然从原理上也依赖于极限定理,但在类别决策时,只与极少量的相邻样本有关。由于KNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,KNN方法较其他方法更为适合。

#include "stdafx.h"
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
using namespace std;
 
//样本特征结构体
struct sample
{
 string type;
 vector features;
};
 
//读取训练样本train.txt,训练样本格式:类型名+特征向量
void readTrain(vector& train, const string& file)
{
 ifstream fin(file.c_str()); //file是存储希望读写的文件名的string对象,fin是读的流
 if(!fin)
 {
 cerr<<"Unable to open the input file: "<>ts.type;
 while(stream>>d) //read a word from line
 {
  ts.features.push_back(d); //在trains.features的末尾添加一个值为d的元素
 }
 train.push_back(ts); //在train的末尾添加一个值为ts的元素
 }
 fin.close();
}
 
//读取测试样本test.txt,每行都是一个特征向量
void readTest(vector& test, const string& file)
{
 ifstream fin(file.c_str());
 if(!fin)
 {
 cerr<<"Unable to open the input file: "<>d)
 {
  ts.features.push_back(d);
 }
 test.push_back(ts);
 }
 fin.close();
}
 
//输出结果,为每一个向量赋予一个类型,写入result.txt中
void writeResult(const vector& test, const string& file)
{
 ofstream fout(file.c_str());
 if(!fout)
 {
 cerr<<"Unable to write the input file: "<::size_type i=0;i!=test.size();++i)
 {
 fout << test[i].type << '\t';
 for(vector::size_type j=0;j!=test[j].features.size();++j)
 {
  fout<& test, const vector& train, const vector >& dm, unsigned int k)
{
 for (vector::size_type i = 0; i != test.size(); ++i)
 {
 multimap dts; //保存与测试样本i距离最近的k个点
 
 for (vector::size_type j = 0; j != dm[i].size(); ++j)
 {
  if (dts.size() < k) //把前面k个插入dts中
  {
  dts.insert(make_pair(dm[i][j], train[j].type)); //插入时会自动排序,按dts中的double排序,最小的排在最后
  }
  else
  {
  multimap::iterator it = dts.end();
  --it;
 
  if (dm[i][j] < it->first) //把当前测试样本i到当前训练样本之间的欧氏距离与dts中最小距离比较,若更小就更新dts
  {
   dts.erase(it);
   dts.insert(make_pair(dm[i][j], train[j].type));
  }
  }
 }
 map tds;
 string type = "";
 double weight = 0.0;
 //下面for循环主要是求出与测试样本i最邻近的k个样本点中大多数属于的类别,即将其作为测试样本点i的类别
 for (multimap::const_iterator cit = dts.begin(); cit != dts.end(); ++cit)
 {
  // 不考虑权重的情况,在 k 个样例中只要出现就加 1
  // ++tds[cit->second];
 
  // 这里是考虑距离与权重的关系,距离越大权重越小
  tds[cit->second] += 1.0 / cit->first;
  if (tds[cit->second] > weight)
  {
  weight = tds[cit->second];
  type = cit->second; //保存一下类别
  }
 }
 test[i].type = type;
 }
}
 
// 计算欧氏距离
double euclideanDistance(const vector& v1, const vector& v2)
{
 if(v1.size() != v2.size())
 {
 cerr<<"Unable to get a distance! "<::size_type i = 0; i != v1.size(); ++i)
 {
  distance += (v1[i] - v2[i]) * (v1[i] - v2[i]);
 }
 return sqrt(distance);
 }
}
 
/*初始化距离矩阵,该矩阵是根据训练样本和测试样本而得,
矩阵的行数为测试样本的数目,列数为训练样本的数目,
每一行为一个测试样本到各个训练样本之间的欧式距离组成的数组*/
void initDistanceMatrix(vector >& dm, const vector& train, const vector& test)
{
 for (vector::size_type i = 0; i != test.size(); ++i)
 {
 vector vd;
 for (vector::size_type j = 0; j != train.size(); ++j)
 {
  vd.push_back(euclideanDistance(test[i].features, train[j].features));
 }
 dm.push_back(vd);
 }
}
 
//封装
void xfxKnn(const string& file1, const string& file2, const string& file3, int k)
{
 vector train,test;
 readTrain(train, file1.c_str());
 readTest(test, file2.c_str());
 vector< vector > dm;
 initDistanceMatrix(dm, train, test);
 knnProcess(test, train, dm, k);
 writeResult(test, file3.c_str());
}
 
// 测试
int main()
{
 xfxKnn("train.txt", "test.txt", "result.txt", 5);
 return 0;
}

感谢各位的阅读!关于“C++基于特征向量的KNN分类算法怎么用”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!


本文题目:C++基于特征向量的KNN分类算法怎么用
文章出自:http://hbruida.cn/article/gchogo.html