鄰近算法

KNN算法的決策過程
k-Nearest Neighbor algorithm
是K最鄰近結(jié)點算法(k-Nearest Neighbor algorithm)的縮寫形式,是電子信息分類器算法的一種
該算法[5]的基本思路是[6]:在給定新文本后,考慮在訓(xùn)練文本集中與該新文本距離最近(最相似)的 K 篇文本,根據(jù)這 K 篇文本所屬的類別判定新文本所屬的類別
左圖中,綠色圓要被決定賦予哪個類,是紅色三角形還是藍色四方形?如果K=3,由于紅色三角形所占比例為2/3,綠色圓將被賦予紅色三角形那個類,如果K=5,由于藍色四方形比例為3/5,因此綠色圓被賦予藍色四方形類。
K最近鄰(k-Nearest Neighbor,KNN)分類算法,是一個理論上比較成熟的方法,也是最簡單的機器學(xué)習(xí)算法之一。該方法的思路是:如果一個樣本在特征空間中的k個最相似(即特征空間中最鄰近)的樣本中的大多數(shù)屬于某一個類別,則該樣本也屬于這個類別。KNN算法中,所選擇的鄰居都是已經(jīng)正確分類的對象。該方法在定類決策上只依據(jù)最鄰近的一個或者幾個樣本的類別來決定待分樣本所屬的類別。 KNN方法雖然從原理上也依賴于極限定理,但在類別決策時,只與極少量的相鄰樣本有關(guān)。由于KNN方法主要靠周圍有限的鄰近的樣本,而不是靠判別類域的方法來確定所屬類別的,因此對于類域的交叉或重疊較多的待分樣本集來說,KNN方法較其他方法更為適合。
KNN算法不僅可以用于分類,還可以用于回歸。通過找出一個樣本的k個最近鄰居,將這些鄰居的屬性的平均值賦給該樣本,就可以得到該樣本的屬性。更有用的方法是將不同距離的鄰居對該樣本產(chǎn)生的影響給予不同的權(quán)值(weight),如權(quán)值與距離成正比。
該算法在分類時有個主要的不足是,當(dāng)樣本不平衡時,如一個類的樣本容量很大,而其他類樣本容量很小時,有可能導(dǎo)致當(dāng)輸入一個新樣本時,該樣本的K個鄰居中大容量類的樣本占多數(shù)。因此可以采用權(quán)值的方法(和該樣本距離小的鄰居權(quán)值大)來改進。該方法的另一個不足之處是計算量較大,因為對每一個待分類的文本都要計算它到全體已知樣本的距離,才能求得它的K個最近鄰點。目前常用的解決方法是事先對已知樣本點進行剪輯,事先去除對分類作用不大的樣本。該算法比較適用于樣本容量比較大的類域的自動分類,而那些樣本容量較小的類域采用這種算法比較容易產(chǎn)生誤分。
KNN-主要應(yīng)用領(lǐng)域
·文本分類·聚類分析·數(shù)據(jù)挖掘·機器學(xué)習(xí)·預(yù)測分析·減少維度·模式識別·圖像處理
我的kNN分類算法程序:


------------------- Code written by Stephen Liu -----------------------
#include
#include
#define MAX 1000
using namespace std;
int m, i, j;
int types[100];
class str
{
public:
float x;
float y;
float distance;
int type;
};
str data[ MAX ];//輸入的已知類別的數(shù)據(jù)
str point;//需要根據(jù)kNN判斷類別的未知數(shù)據(jù)
str temp;
void input_data()
{
cout << "請輸入已知點的個數(shù):";
cin >> m;
for ( i = 1; i <= m; i++)
{
cout <<"請輸入點 " << i <<" 的坐標(biāo)x , y 和所屬類別:" ;
cin >> data.x >> data.y >> data.type;
}
}
void Distance()//計算未知類別點與所有已知類別點的距離
{
for ( i = 1; i <= m; i++ )
data.distance = sqrt ( (data.x - point.x) * (data.x - point.x) + (data.y - point.y) * (data.y - point.y) );
}
void sort()//對距離進行從小到大排序
{
for( i = 1; i <= m; i++)
for(j = m; j > i; j--)
{
if(data[ j ].distance < data[ j - 1 ].distance)
{
temp=data[ j ];
data[ j ]=data[ j - 1 ];
data[ j - 1]=temp;
}
}
}
int kNN( )
{
int the_type,num = 0, k;
cout <<"請輸入kNN的k值:";
cin >> k;
for ( i = 1; i <= 99; i++)
types[ i ] = 0;
for ( i = 1; i <= k; i++)//對已排序的前k位距離類別進行統(tǒng)計
types[ data.type ] ++;
for ( i = 1; i <= 99; i++)//找出未知類別點屬于的類別
{
if (types > num )
{
num = types;
the_type = i;
}
}
return ( the_type);
}
int main()
{
input_data();
cout <<"請輸入未知類別點的坐標(biāo)x,y(輸入0 0退出):";
cin >> point.x >> point.y;
do
{
Distance();
sort();
cout <<"點( " << point.x << " , " << point.y <<" )屬于類"<< kNN() << endl;
cout <<"請輸入未知類別點的坐標(biāo)x,y(輸入0 0退出):";
cin >> point.x >> point.y;
}
while ( point.x != 0 && point.y != 0);
cout <<"======= kNN分類算法 Stephen Liu E-mail:stephenliu1989@163.com 2010.8 ======= ";
system("pause" ;
return 0;
}
------------------------- Code end ---------------------------------
我的評價:
這是kNN分類算法的最簡單的一種情況,當(dāng)k取不同值時分類可能會出現(xiàn)不同。樣本過大時,由于要比較的次數(shù)增多,效率降低。 |