【机器学习实战】kNN算法_c++

k-近邻算法(kNN)
简单来说,k-近邻算法采用测量不同特征值之间的距离方法进行分类。
算法原理:

存在一个训练样集,并且知道样本集中每一数据与所属分类的对应关系。
输入没有标签的新数据后,将新数据的每个特征与该样本集中数据对应的特征进行比较,
算法提取样本集中最相似(近邻)数据的分类标签。一般只取样本数据集中前k个最相似的数据,
然后在这K个最相似数据中选择出现次数最多的分类,作为输入的新数据的分类。

<<机器学习实战>>一书中用python实现该算法的例子,本文用c++实现该示例。
实例是对电影进行分类,动作或者爱情类,分别以’A’和’B’代替。特征向量两个。
本文接口函数为:

char classify(float x, float y, int k, ClassiFy* dataSet, int len);

完整代码如下:

/*created at 2019/5/19 8:53*/
#include <iostream>
#include <assert.h>
#include <cmath>
#include <string.h>

typedef struct _ClassiFy
{
	float x;
	float y;
	char type;
}ClassiFy;

ClassiFy* createDataSet()
{
	ClassiFy* data = new ClassiFy[4];
	data[0] = {1.0, 1.1, 'A'};
	data[1] = {1.0, 1.0, 'A'};
	data[2] = {0.0, 0.0, 'B'};
	data[3] = {0.0, 0.1, 'B'};
	return data;
}

void swapData(float* x, float* y)
{
	float temp = *x;
	*x = *y;
	*y = temp;
}

/*对数组进行排序,获取重新排列后,元素的位置
例如7,2,3,5,6
排序后为2,3,5,6,7,
返回值list 1,2,3,4,0*/

void sortDist(float* dist, int size, int* list)
{
	float min;
	int pos;
	for(int r = 0; r < size; ++r){
		pos = -1;
		min = dist[r];
		for(int c = r + 1; c < size - 1; c++){
			if(dist[c] < min){
				min = dist[c];
				pos = c;
			}
		}
		/*与左边的值交换最小值*/
		if(pos > 0){
			swapData(dist+r, dist+pos);
			list[r] = pos;
		}else{
			list[r] = r;
		}
	}
}

/*
	[param@ x, y] ==> 新加入的数据
	[param@ k] ==> 选择k个相近的数据
	[param@ dataSet] ==> 训练的数据集
	[param@ size] ==> 训练的数据集数据量
	返回新加入输的类型
*/
char classify(float x, float y, int k, ClassiFy* dataSet, int len)
{
	assert(len > 0);
	
	/*1.计算新加入的点与数据集中每个点的距离*/
	float* dist = new float[len];
	memset(dist, 0.0f, len*sizeof(float));
	for(int r = 0; r < len; ++r)
		dist[r] = sqrt(pow((x - dataSet[r].x), 2) + pow((y - dataSet[r].y), 2));
	
	/*2.排序*/
	int* number = new int[len];
	memset(number, 0, len*sizeof(int));
	sortDist(dist, len, number);
	
	
	/*3.取前k个相近的数据, number[r]代表排序后的第r个数据是排序前的第number[r]个数据*/
	int sum_A(0), sum_B(0);
	for(int r = 0; r < k; ++r){
		if('A' == dataSet[number[r]].type){
			sum_A++;
		}else{
			sum_B++;
		}
	}
	delete[] dist;
	delete[] number;
	
	if(sum_A > sum_B) 
		return 'A';
	else
		return 'B';
}

int main(int argc, char** argv)
{
	ClassiFy* Traindata;
	
	Traindata = createDataSet();					/*创建训练数据集*/
	float x, y;
	std::cout << "请输入新的数据x,y:";
	int rc = std::scanf("%f,%f", &x, &y);
	char res = classify(x, y, 3, Traindata, 4);		/*输入新的数据集,得到其类型*/
	std::cout << "新的数据类型为: " << res << std::endl;
	delete[] Traindata;
	return 0;
}

运行程序,控制台提示
请输入新的数据x,y:0,0
新的数据类型为: B

发布了35 篇原创文章 · 获赞 13 · 访问量 6334

猜你喜欢

转载自blog.csdn.net/qq_35306281/article/details/90339000
今日推荐