knn分类算法c语言实现,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<

exit(1);

}

string line;

double d=0.0;

while(getline(fin,line)) //fin是读入流,getline从输入流fin读入一行到line

{

istringstream stream(line); //bind to stream to the line we read

sample ts;

stream>>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<

exit(1);

}

string line;

double d=0.0;

while(getline(fin,line))

{

istringstream stream(line); //bind to stream to the line we read

sample ts;

while(stream>>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<

exit(1);

}

for(vector::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<

}

fout<

}

}

//KNN算法的实现

void knnProcess(vector& 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<

}

else

{

double distance = 0.0;

for (vector::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;

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenCV是一个开源的计算机视觉库,提供了许多用于处理图像和视频的函数和算法。其中之一就是K最近邻(KNN分类算法KNN是一种监督学习算法,用于分类任务。它的基本思想是根据已知的训练样本,通过计算样本之间的距离来确定一个测试样本的类别。 下面是一个使用OpenCV实现KNN分类算法的示例代码: ```c #include <opencv2/opencv.hpp> #include <iostream> int main() { // 加载训练样本 cv::Mat trainData = (cv::Mat_<float>(4, 2) << 2, 4, 4, 2, 4, 4, 6, 2); cv::Mat trainLabels = (cv::Mat_<int>(4, 1) << 0, 0, 1, 1); // 创建KNN分类器对象 cv::Ptr<cv::ml::KNearest> knn = cv::ml::KNearest::create(); // 训练,传入训练数据和对应的标签 knn->train(trainData, cv::ml::ROW_SAMPLE, trainLabels); // 创建测试样本 cv::Mat testData = (cv::Mat_<float>(1, 2) << 6, 6); // 预测测试样本的类别 cv::Mat results, neighborResponses, dists; float response = knn->findNearest(testData, 3, results, neighborResponses, dists); // 打印预测结果 std::cout << "Predicted class: " << response << std::endl; return 0; } ``` 以上代码中,首先加载了4个训练样本,每个样本有2个特征。然后创建了一个KNN分类器对象,进行训练。接着创建了一个测试样本,使用KNN分类器进行预测,预测结果存储在response变量中。最后将预测结果打印出来。 需要注意的是,以上代码只是一个简单的示例,实际使用KNN分类器时,可能需要更多的训练样本和特征,并进行参数调优等操作。希望以上回答对您有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值