鄰近算法

KNN算法的決策過程
k-Nearest Neighbor algorithm
是K最鄰近結(jié)點(diǎn)算法(k-Nearest Neighbor algorithm)的縮寫形式,是電子信息分類器算法的一種
該算法[5]的基本思路是[6]:在給定新文本后,考慮在訓(xùn)練文本集中與該新文本距離最近(最相似)的 K 篇文本,根據(jù)這 K 篇文本所屬的類別判定新文本所屬的類別
左圖中,綠色圓要被決定賦予哪個(gè)類,是紅色三角形還是藍(lán)色四方形?如果K=3,由于紅色三角形所占比例為2/3,綠色圓將被賦予紅色三角形那個(gè)類,如果K=5,由于藍(lán)色四方形比例為3/5,因此綠色圓被賦予藍(lán)色四方形類。
K最近鄰(k-Nearest Neighbor,KNN)分類算法,是一個(gè)理論上比較成熟的方法,也是最簡單的機(jī)器學(xué)習(xí)算法之一。該方法的思路是:如果一個(gè)樣本在特征空間中的k個(gè)最相似(即特征空間中最鄰近)的樣本中的大多數(shù)屬于某一個(gè)類別,則該樣本也屬于這個(gè)類別。KNN算法中,所選擇的鄰居都是已經(jīng)正確分類的對象。該方法在定類決策上只依據(jù)最鄰近的一個(gè)或者幾個(gè)樣本的類別來決定待分樣本所屬的類別。 KNN方法雖然從原理上也依賴于極限定理,但在類別決策時(shí),只與極少量的相鄰樣本有關(guān)。由于KNN方法主要靠周圍有限的鄰近的樣本,而不是靠判別類域的方法來確定所屬類別的,因此對于類域的交叉或重疊較多的待分樣本集來說,KNN方法較其他方法更為適合。
KNN算法不僅可以用于分類,還可以用于回歸。通過找出一個(gè)樣本的k個(gè)最近鄰居,將這些鄰居的屬性的平均值賦給該樣本,就可以得到該樣本的屬性。更有用的方法是將不同距離的鄰居對該樣本產(chǎn)生的影響給予不同的權(quán)值(weight),如權(quán)值與距離成正比。
該算法在分類時(shí)有個(gè)主要的不足是,當(dāng)樣本不平衡時(shí),如一個(gè)類的樣本容量很大,而其他類樣本容量很小時(shí),有可能導(dǎo)致當(dāng)輸入一個(gè)新樣本時(shí),該樣本的K個(gè)鄰居中大容量類的樣本占多數(shù)。因此可以采用權(quán)值的方法(和該樣本距離小的鄰居權(quán)值大)來改進(jìn)。該方法的另一個(gè)不足之處是計(jì)算量較大,因?yàn)閷γ恳粋(gè)待分類的文本都要計(jì)算它到全體已知樣本的距離,才能求得它的K個(gè)最近鄰點(diǎn)。目前常用的解決方法是事先對已知樣本點(diǎn)進(jìn)行剪輯,事先去除對分類作用不大的樣本。該算法比較適用于樣本容量比較大的類域的自動(dòng)分類,而那些樣本容量較小的類域采用這種算法比較容易產(chǎn)生誤分。
KNN-主要應(yīng)用領(lǐng)域
·文本分類·聚類分析·數(shù)據(jù)挖掘·機(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 << "請輸入已知點(diǎn)的個(gè)數(shù):";
cin >> m;
for ( i = 1; i <= m; i++)
{
cout <<"請輸入點(diǎn) " << i <<" 的坐標(biāo)x , y 和所屬類別:" ;
cin >> data.x >> data.y >> data.type;
}
}
void Distance()//計(jì)算未知類別點(diǎn)與所有已知類別點(diǎn)的距離
{
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()//對距離進(jìn)行從小到大排序
{
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位距離類別進(jìn)行統(tǒng)計(jì)
types[ data.type ] ++;
for ( i = 1; i <= 99; i++)//找出未知類別點(diǎn)屬于的類別
{
if (types > num )
{
num = types;
the_type = i;
}
}
return ( the_type);
}
int main()
{
input_data();
cout <<"請輸入未知類別點(diǎn)的坐標(biāo)x,y(輸入0 0退出):";
cin >> point.x >> point.y;
do
{
Distance();
sort();
cout <<"點(diǎn)( " << point.x << " , " << point.y <<" )屬于類"<< kNN() << endl;
cout <<"請輸入未知類別點(diǎn)的坐標(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 ---------------------------------
我的評價(jià):
這是kNN分類算法的最簡單的一種情況,當(dāng)k取不同值時(shí)分類可能會出現(xiàn)不同。樣本過大時(shí),由于要比較的次數(shù)增多,效率降低。 |