C++基于特征向量的KNN分類(lèi)算法
K最近鄰(k-Nearest Neighbor,KNN)分類(lèi)算法,是一個(gè)理論上比較成熟的方法,也是最簡(jiǎn)單的機(jī)器學(xué)習(xí)算法之一。該方法的思路是:如果一個(gè)樣本在特征空間中的k個(gè)最相似(即特征空間中最鄰近)的樣本中的大多數(shù)屬于某一個(gè)類(lèi)別,則該樣本也屬于這個(gè)類(lèi)別。KNN算法中,所選擇的鄰居都是已經(jīng)正確分類(lèi)的對(duì)象。該方法在定類(lèi)決策上只依據(jù)最鄰近的一個(gè)或者幾個(gè)樣本的類(lèi)別來(lái)決定待分樣本所屬的類(lèi)別。 KNN方法雖然從原理上也依賴(lài)于極限定理,但在類(lèi)別決策時(shí),只與極少量的相鄰樣本有關(guān)。由于KNN方法主要靠周?chē)邢薜泥徑臉颖?,而不是靠判別類(lèi)域的方法來(lái)確定所屬類(lèi)別的,因此對(duì)于類(lèi)域的交叉或重疊較多的待分樣本集來(lái)說(shuō),KNN方法較其他方法更為適合。
#include "stdafx.h" #include <iostream> #include <fstream> #include <sstream> #include <string> #include <vector> #include <set> #include <map> #include <cmath> using namespace std; //樣本特征結(jié)構(gòu)體 struct sample { string type; vector<double> features; }; //讀取訓(xùn)練樣本train.txt,訓(xùn)練樣本格式:類(lèi)型名+特征向量 void readTrain(vector<sample>& train, const string& file) { ifstream fin(file.c_str()); //file是存儲(chǔ)希望讀寫(xiě)的文件名的string對(duì)象,fin是讀的流 if(!fin) { cerr<<"Unable to open the input file: "<<file<<endl; 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的末尾添加一個(gè)值為d的元素 } train.push_back(ts); //在train的末尾添加一個(gè)值為ts的元素 } fin.close(); } //讀取測(cè)試樣本test.txt,每行都是一個(gè)特征向量 void readTest(vector<sample>& test, const string& file) { ifstream fin(file.c_str()); if(!fin) { cerr<<"Unable to open the input file: "<<file<<endl; 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(); } //輸出結(jié)果,為每一個(gè)向量賦予一個(gè)類(lèi)型,寫(xiě)入result.txt中 void writeResult(const vector<sample>& test, const string& file) { ofstream fout(file.c_str()); if(!fout) { cerr<<"Unable to write the input file: "<<endl; exit(1); } for(vector<sample>::size_type i=0;i!=test.size();++i) { fout << test[i].type << '\t'; for(vector<double>::size_type j=0;j!=test[j].features.size();++j) { fout<<test[i].features[j]<<' '; } fout<<endl; } } //KNN算法的實(shí)現(xiàn) void knnProcess(vector<sample>& test, const vector<sample>& train, const vector<vector<double> >& dm, unsigned int k) { for (vector<sample>::size_type i = 0; i != test.size(); ++i) { multimap<double, string> dts; //保存與測(cè)試樣本i距離最近的k個(gè)點(diǎn) for (vector<double>::size_type j = 0; j != dm[i].size(); ++j) { if (dts.size() < k) //把前面k個(gè)插入dts中 { dts.insert(make_pair(dm[i][j], train[j].type)); //插入時(shí)會(huì)自動(dòng)排序,按dts中的double排序,最小的排在最后 } else { multimap<double, string>::iterator it = dts.end(); --it; if (dm[i][j] < it->first) //把當(dāng)前測(cè)試樣本i到當(dāng)前訓(xùn)練樣本之間的歐氏距離與dts中最小距離比較,若更小就更新dts { dts.erase(it); dts.insert(make_pair(dm[i][j], train[j].type)); } } } map<string, double> tds; string type = ""; double weight = 0.0; //下面for循環(huán)主要是求出與測(cè)試樣本i最鄰近的k個(gè)樣本點(diǎn)中大多數(shù)屬于的類(lèi)別,即將其作為測(cè)試樣本點(diǎn)i的類(lèi)別 for (multimap<double, string>::const_iterator cit = dts.begin(); cit != dts.end(); ++cit) { // 不考慮權(quán)重的情況,在 k 個(gè)樣例中只要出現(xiàn)就加 1 // ++tds[cit->second]; // 這里是考慮距離與權(quán)重的關(guān)系,距離越大權(quán)重越小 tds[cit->second] += 1.0 / cit->first; if (tds[cit->second] > weight) { weight = tds[cit->second]; type = cit->second; //保存一下類(lèi)別 } } test[i].type = type; } } // 計(jì)算歐氏距離 double euclideanDistance(const vector<double>& v1, const vector<double>& v2) { if(v1.size() != v2.size()) { cerr<<"Unable to get a distance! "<<endl; } else { double distance = 0.0; for (vector<double>::size_type i = 0; i != v1.size(); ++i) { distance += (v1[i] - v2[i]) * (v1[i] - v2[i]); } return sqrt(distance); } } /*初始化距離矩陣,該矩陣是根據(jù)訓(xùn)練樣本和測(cè)試樣本而得, 矩陣的行數(shù)為測(cè)試樣本的數(shù)目,列數(shù)為訓(xùn)練樣本的數(shù)目, 每一行為一個(gè)測(cè)試樣本到各個(gè)訓(xùn)練樣本之間的歐式距離組成的數(shù)組*/ void initDistanceMatrix(vector<vector<double> >& dm, const vector<sample>& train, const vector<sample>& test) { for (vector<sample>::size_type i = 0; i != test.size(); ++i) { vector<double> vd; for (vector<sample>::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<sample> train,test; readTrain(train, file1.c_str()); readTest(test, file2.c_str()); vector< vector<double> > dm; initDistanceMatrix(dm, train, test); knnProcess(test, train, dm, k); writeResult(test, file3.c_str()); } // 測(cè)試 int main() { xfxKnn("train.txt", "test.txt", "result.txt", 5); return 0; }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持我們。
欄 目:C語(yǔ)言
下一篇:MFC實(shí)現(xiàn)連連看游戲之消子算法
本文標(biāo)題:C++基于特征向量的KNN分類(lèi)算法
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/546.html
您可能感興趣的文章
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 01-10深入理解C++中常見(jiàn)的關(guān)鍵字含義
- 01-10使用C++實(shí)現(xiàn)全排列算法的方法詳解
- 01-10c++中inline的用法分析
- 01-10用C++實(shí)現(xiàn)DBSCAN聚類(lèi)算法
- 01-10全排列算法的非遞歸實(shí)現(xiàn)與遞歸實(shí)現(xiàn)的方法(C++)
- 01-10C++大數(shù)模板(推薦)
- 01-10淺談C/C++中的static與extern關(guān)鍵字的使用詳解
- 01-10深入C/C++浮點(diǎn)數(shù)在內(nèi)存中的存儲(chǔ)方式詳解
- 01-10基于atoi()與itoa()函數(shù)的內(nèi)部實(shí)現(xiàn)方法詳解


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹(shù)的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 04-02c語(yǔ)言函數(shù)調(diào)用后清空內(nèi)存 c語(yǔ)言調(diào)用
- 04-02func函數(shù)+在C語(yǔ)言 func函數(shù)在c語(yǔ)言中
- 04-02c語(yǔ)言的正則匹配函數(shù) c語(yǔ)言正則表達(dá)
- 04-02c語(yǔ)言用函數(shù)寫(xiě)分段 用c語(yǔ)言表示分段
- 04-02c語(yǔ)言中對(duì)數(shù)函數(shù)的表達(dá)式 c語(yǔ)言中對(duì)
- 04-02c語(yǔ)言編寫(xiě)函數(shù)冒泡排序 c語(yǔ)言冒泡排
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 04-02c語(yǔ)言分段函數(shù)怎么求 用c語(yǔ)言求分段
- 04-02C語(yǔ)言中怎么打出三角函數(shù) c語(yǔ)言中怎
- 04-02c語(yǔ)言調(diào)用函數(shù)求fibo C語(yǔ)言調(diào)用函數(shù)求
隨機(jī)閱讀
- 01-11Mac OSX 打開(kāi)原生自帶讀寫(xiě)NTFS功能(圖文
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 01-10delphi制作wav文件的方法
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 01-10C#中split用法實(shí)例總結(jié)
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-10SublimeText編譯C開(kāi)發(fā)環(huán)境設(shè)置
- 04-02jquery與jsp,用jquery