k-近邻算法学习
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了k-近邻算法学习相关的知识,希望对你有一定的参考价值。
参考: http://blog.csdn.net/tjusxh/article/details/51052319
k-近邻算法:简单地说就是采用测量不同特征值之间的距离进行分类的方法。
三个基本要素:K值的选择、距离度量、分类决策规则
优点:精度高、对异常值不敏感、无数据输入假定。
缺点:计算复杂度高、空间复杂度高。
kNN算法的一般流程:
1.导入数据
2.为保证特征权重相同,进行数值归一化
3.距离计算
4.对距离进行排序,选择前K个距离,求出标签出现最多的类别
#include<iostream> #include<string> #include<vector> #include<algorithm> #include<sstream> #include<fstream> #include<cmath> using namespace std; //建立一个数据结构,元素为距离、标签 struct Node{ double dis; double labels; Node(){} Node(double Dis, double Labels) :dis(Dis), labels(Labels){} }; bool cmp(Node a, Node b){ return a.dis<b.dis; } //第一步,导入数据 vector<vector<double>> getFile(ifstream&in) { vector<vector<double>> dataMat; //用于返回的二维容器 vector<double>item; //一维容器,用于压缩到二维容器中 string s; istringstream str; while (getline(in, s)) //将数据按行输入 { str.str(s); double tmp; while (str >> tmp) item.push_back(tmp); dataMat.push_back(item); item.clear(); str.clear(); } return dataMat; } void printf(vector<vector<double>>data) { int n = data.size(); //这里 n 是样本的数量 int m = data[0].size(); //特征 + 标签 for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) cout << data[i][j] << " "; cout << endl; } } //数值归一化 vector<vector<double>>makeOne(vector<vector<double>>theData) { vector<vector<double>>dataMat = theData; int numRows = theData.size(); int numColumns = theData[0].size(); //找出每一列的最大值与最小值 vector<double>Max; vector<double>Min; vector<double>ranges; for (int i = 0; i < numColumns - 1; i++) //因为每行最后一个元素是标签,所以要减 1 { double max = theData[i][0]; double min = theData[i][0]; for (int j = 1; j < numRows; j++) { if (theData[j][i] >max) max = theData[j][i]; if (theData[j][i] <min) min = theData[j][i]; } Max.push_back(max); Min.push_back(min); } for (int i = 0; i < numColumns - 1; i++) for (int j = 0; j < numRows; j++) { dataMat[j][i] = (theData[j][i] - Min[i]) / (Max[i] - Min[i]); } return dataMat; } //输入待测样本 vector<double>getX(vector<vector<double>>dataMat) { int m = dataMat[0].size(); vector<double>inputX; cout << "请输入待测样本 (特征数是" << m - 1 << "个)" << endl; for (int i = 0; i < m - 1; i++) { double temp; cin >> temp; inputX.push_back(temp); } return inputX; } //计算出 input 到样本点的距离 Node getLabel(vector<double>input, vector<double>Asample) { Node node1; int m = input.size(); node1.labels = Asample[m]; double dis = 0; for (int i = 0; i < m; i++) dis += pow(input[i] - Asample[i], 2.0); node1.dis = dis; return node1; } //对所有的样本点距离进行排序,选择前 K 个,并找出前 K 个出现最多的标签 double makeComp(vector<Node>nodes) { int k; double l = 0; sort(nodes.begin(), nodes.end(), cmp); //对距离按升序排序 cout << "请输入K:" << " "; cin >> k; int max = 0; double label[100] = { 0 }; for (int i = 0; i<k; i++){ //前 K 个所处的标签 label[int(nodes[i].labels)]++; } for (int i = 0; i < k; i++) //用于统计出现次数最多的标签 { if (max < label[i]){ l = i; max = label[i]; } } return l; } int main() { vector<vector<double>>dataMat; ifstream file("datingTestSet2.txt"); dataMat = getFile(file); dataMat = makeOne(dataMat); int numOfSamples = dataMat.size(); while (1) { vector<Node>dis_label; vector<double>input = getX(dataMat); //输入待测例子 //计算input到每一个样本点的距离,输入为 input,样本点, 输出是:距离,标签 for (int i = 0; i < numOfSamples; i++) { Node A = getLabel(input, dataMat[i]); dis_label.push_back(A); //计算出 input 到所有样本点的距离 } double classfy = makeComp(dis_label); cout << classfy << endl; } return 0; }
以上是关于k-近邻算法学习的主要内容,如果未能解决你的问题,请参考以下文章
[机器学习与scikit-learn-18]:算法-K近邻算法KNN的原理与代码实例
Machine Learning in Action机器学习——第二章k-近邻算法代码详解