動態聚類中 C-均值演算法 (K-均值演算法)的C++實現
一:說明
動態聚類方法是模式識別中一種普遍採用的方法,它具有以下3個要點:
1:選定某種距離度量作為樣本間的相似性度量
2:確定某個評價聚類結果質量的準則函式
3:給定某個初始分類,然後用迭代演算法找出使準則函式取極值的最好的聚類結果
本文給出了 C-均值演算法 的 C++實現。
(演算法描述參見邊肇祺張學工等<< 模式識別 >> P237 清華大學出版社)
二:原始碼
2.1標頭檔案
#pragma once
#include <list>
#include <vector>
using namespace std;
#define DATANUM 19
#define MAXDIST 333333
struct CData
{
int x1;
int x2;
};
class CCMean
{
public:
CCMean(CData *pdata);
~CCMean(void);
void init();
void work(int InitClassNum);
private:
// calculate the mean of class i:
void CalcuMean( int i );
// calculate the ERROR of class i:
void CalcuJc(int i);
void CalcuJe();
// step 1 of C-Mean algorithm
void InitDeploy();
// step 4 and 5 of C-Mean algorithm
// da is now in class i,
// return ture when moving da from class to class k
// return false when we do not move da
bool MoveItoK( const CData& da, int i, int &k );
// calculate the distance of to data:
intdist( const
// print result:
void OutPut();
// iClassNum is the initial class number, in text book, iClassNum <==> C
int iClassNum;
// pointer to data array:
CData *pData;
// store the mean of all classes. just ueses 0 to iClassNum - 1;
// in text book is: m1, m2, m3, m4, ... , mc.
CData mean[DATANUM];
// store the ERROR of each class, just ueses 0 to iClassNum - 1;
// the sum of jc[0] to jc[iClassNum - 1] will be je defined following jc;
int jc[DATANUM];
//the sum of jc[0] to jc[iClassNum - 1]
intje;
// pcla[i] pointer class i which store in LIST
list< CData >* pcla[DATANUM];
};
2.2實現檔案
#include "assert.h"
#include "cmean.h"
CCMean::CCMean(CData *pdata)
{
pData = pdata;
for(int i = 0; i < DATANUM; i ++ )
{
pcla[i] = new list< CData >;
assert( pcla[i] != 0 );
}
je = 0;
}
CCMean::~CCMean()
{
for(int i = 0; i < DATANUM; i ++ )
delete pcla[i];
}
void CCMean::init()
{
for(int i = 0; i < DATANUM; i ++ )
{
pcla[i]->clear();
mean[i].x1 = 0;
mean[i].x2 = 0;
}
je = 0;
}
void CCMean::CalcuMean(int ii)
{
int sum1 = 0, sum2 = 0;
int si = (int)pcla[ii]->size();
list< CData >::iterator iter = pcla[ii]->begin();
for(int i = 0; i < si; i ++ )
{
sum1 += iter->x1;
sum2 += iter->x2;
iter++;
}
mean[ii].x1 = sum1 / si;
mean[ii].x2 = sum2 / si;
}
void CCMean::CalcuJe()
{
for( int i = 0; i < iClassNum ; i ++ )
{
CalcuJc( i );
je += jc[i];
}
}
void CCMean::CalcuJc( int index )
{
list< CData >::iterator iter = pcla[index]->begin();
int si = (int)pcla[index]->size();
jc[index] = 0;
for( int i = 0; i < si; i ++)
{
jc[index] += dist( mean[index], *iter );
iter ++;
}
}
int CCMean::dist(const CData& mean, const CData& da)
{
return (mean.x1 - da.x1)*(mean.x1 - da.x1) + (mean.x2 - da.x2)*(mean.x2 - da.x2);
}
void CCMean::InitDeploy()
{
CData *ptem = pData;
for( int i = 0; i < iClassNum; i ++ )
{
// choose the first iClassNum data as our initial class-center:
mean[i] = *ptem;
pcla[i]->push_back( *ptem );
ptem++;
}
// put other data to our initial classes:
for( int i = iClassNum; i < DATANUM; i ++ )
{
int mindis = MAXDIST;
int pos = 0;
// get the least distance between pData[i] and m1, m2, m3 ....
for( int j = 0; j < iClassNum; j ++ )
{
int curdis = dist( pData[i], mean[j] );
if( curdis < mindis )
{
mindis = curdis;
pos = j;
}
}
// add pData to class (pos):
pcla[pos]->push_back( pData[i] );
}
for( int i = 0; i < iClassNum ; i ++ )
CalcuMean( i );
CalcuJe();
}
bool CCMean::MoveItoK( const CData &da, int i , int& k )
{
// now da is in class i,if da is moved to another class, return true, else return false
int Pk = MAXDIST;
int Pj = 0;
int temk = 0;
for( int j = 0; j < iClassNum; j ++ )
{
int si = (int)pcla[j]->size();
if( j == i )
Pj = dist( mean[j], da ) * si/(si - 1);
else
Pj = dist( mean[j], da ) * si/(si + 1);
if( Pj < Pk )
{
Pk = Pj;
temk = j;
}
else if ( Pj == Pk&& j == i )
{
// when Pj == Pk && j == i, we do not move (da) from class i to class j
temk = i;
}
}
if( i == temk )
return false; // we do NOT move da;
k = temk;
// add da to class k:
pcla[k]->push_back( da );
// delete da from class i, first find the positon of da in class i:
list< CData >::iterator iter = pcla[i]->begin();
while( iter != pcla[i]->end() )
{
if( iter->x1 == da.x1 && iter->x2 == da.x2 )
break;
iter++;
}
// now delete da from class i:
pcla[i]->erase( iter );
// we have move da from class i to class k;
return true;
}
void CCMean::OutPut()
{
for( int i = 0; i < iClassNum ; i ++ )
{
printf("class %d:/n", i );
list< CData >::iterator iter = pcla[i]->begin();
int j = 1;
while( iter != pcla[i]->end() )
{
printf( "(%d,%d)", iter->x1, iter->x2 );
iter ++;
if( j++ % 5 == 0)
printf("/n");
}
printf("/n");
}
}
void CCMean::work(int InitClassNum)
{
iClassNum = InitClassNum;
// step 1 of C-Mean algorithm
InitDeploy();
int counter = 0;
Again:
//OutPut();
// step 2 of C-Mean algorithm: choose one sample y (here is da) from collection
for( int i = 0; i < iClassNum ; i ++ )
{
// step 3 of C-Mean algorithm:
int si = (int)pcla[i]->size();
if( si == 1 )
continue;
// step 4 of C-Mean algorithm:
list< CData >::iterator iter = pcla[i]->begin();
for(int j = 0; j < (int)pcla[i]->size(); j++)
{
int k = 0;
CData da = *iter;
iter ++;
// step 5 of C-Mean algorithm:
if( MoveItoK( da , i, k ) == true )
{
// step 6 of C-Mean algorithm:
int OldJe = je;
je -= jc[i];
je -= jc[k];
CalcuMean( i );
CalcuMean( k );
CalcuJc( i );
CalcuJc( k );
je += jc[i];
je += jc[k];
if( OldJe > je )
{
counter = 0;
goto Again;
}
}
counter++;
// step 7 of C-Mean algorithm:
if( counter == DATANUM )
goto end;
}
}
end:
printf(" current Je is: %d/n", je );
OutPut();
}
2.3測試檔案
#include "CMean.h"
#include "process.h"
CData yy[DATANUM] =
{
{0,0},{0,1},{1,0},{1,1},{1,2},{2,1},{2,2},{2,3}
,{6,6},{6,7},{6,8},{7,6},{7,7},{7,8},{7,9},{8,7}
,{8,8},{8,9},{9,8}
};
int main(int argc, char* argv[])
{
CCMean cmean( yy );
cmean.work(2);
system("pause");
return 0;
}
相關推薦
動態聚類中 C-均值演算法 (K-均值演算法)的C++實現
一:說明 動態聚類方法是模式識別中一種普遍採用的方法,它具有以下3個要點: 1:選定某種距離度量作為樣本間的相似性度量 2:確定某個評價聚類結果質量的準則函式 3:給定某個初始分類,然後用迭代演算法找出使準則函式取極值的最好的聚類結果 本文給出了 C-均值演算法 的 C++實
聚類分析----動態聚類法(C-均值法)
該演算法的結果受取定的類數,聚類的初始中心為止影響,在實際中需測探不同的c值以及選擇不同的聚類中心初始值以得到較好的結果。如果模式分佈呈現類內團聚狀,該演算法能得到很好的聚類結果。 條件與約定 設待分類的模式的特徵向量為{},選定類的數目為c。 演
模式識別(Pattern Recognition)學習筆記(三十六)-- 動態聚類演算法
如果不估計樣本的概率分佈,就無法從概率分佈的角度來定義聚類,這時我們就需要有一種新的對聚類的定義,一般的,根據樣本間的某種距離或某種相似性度量來定義聚類,即把相似的或距離近的樣本聚為一類,而把不相似或距離遠的樣本聚在其他類,這種基於相似性度量的聚類方法在實際應用中非常常用,
聚類分析(一):K均值聚類與層次聚類
介紹三類聚類分析演算法,本篇介紹K均值聚類、層次聚類,下篇介紹圖團體(graph community)聚類。 聚類分析又稱群分析,它是研究樣本分類問題的一種統計分析方法,同時也是資料探勘的一個重要演算法。聚類分析以相似性為基礎,在一個聚類(cluster)中的
sklearn庫:分類、迴歸、聚類、降維、模型優化、文字預處理實現用例(趕緊收藏)
分類演算法 # knn演算法 from sklearn.neighbors import KNeighborsClassifier knn = KNeighborsClassifier() ''' __init__函式 def __init__(self, n_neighbors=5,
步步學習之用python實戰機器學習1-kNN (K-NearestNeighbors)演算法(a)
我最近才開始接觸機器學習,我大學數學學的幾乎忘了,最近才接觸python。所以我以一個完全初學者角度來學習機器學習。 我主要用的書籍就是machine learning in action (機器學習實戰)這本書。我主要是用文中已有的程式碼來講解機器學習。 同時對程式碼進行
k近鄰演算法(k-nearest neighbor)和python 實現
1、k近鄰演算法 k近鄰學習是一種常見的監督學習方法,其工作機制非常簡單:給定測試樣本,基於某種距離度量找出訓練集中與其最靠近的k個訓練樣本,然後基於這K個"鄰居"的資訊來進行預測。 通常,在分類任務中可使用"投票法",即選擇這K個樣本中出現最多的類別標記作為預測結果;在迴歸任務中可使用"平
在Ignite中使用k-均值聚類演算法
在本系列前面的文章中,簡單介紹了一下Ignite的k-最近鄰(k-NN)分類演算法,下面會嘗試另一個機器學習演算法,即使用泰坦尼克資料集介紹k-均值聚類演算法。正好,Kaggle提供了CSV格式的資料集,而要分析的是兩個分類:即乘客是否倖存。 為了將資料轉換為Ignite支援的格式,前期需要做一些清理和格式化
模糊C均值聚類演算法及實現
模糊C均值聚類演算法的實現 研究背景 https://blog.csdn.net/liu_xiao_cheng/article/details/50471981 聚類分析是多元統計分析的一種,也是無監督模式識別的一個重要分支,在模式分類 影象處理和模糊
機器學習演算法原理總結系列---演算法基礎之(13)模糊C均值聚類(Fuzzy C-means Clustering)
筆者在韓國Chonnam National University攻讀碩士學位,FCM演算法是professer Lim在這學期主要授課的內容,他說他剛發一篇FCM結合遺傳演算法還有各種腦電訊號處理,搭建分析AD病人的EEG訊號的計算智慧模型。反正就是各種難
k-means(k均值聚類)演算法介紹及實現(c++)
基本介紹: k-means 演算法接受輸入量 k ;然後將n個數據物件劃分為 k個聚類以便使得所獲得的聚類滿足:同一聚類中的物件相似度較高;而不同聚類中的物件相似度較小。聚類相似度是利用各聚類中物件的均值所獲得一個“中心物件”(引力中心)來進行計算的。 工作過程: k
FCM 模糊C均值聚類演算法
首先FCM在影象分割領域有很多應用,FCM演算法我覺得主要是兩個部分,一個是模糊理論,一個是C/Kmean演算法,這兩者在數學家手中完美的結合。 下面切入整體,我也是為了溫故才寫的這篇部落格,如有錯誤或者瑕疵的地方歡迎指出。話說有一個集合,甭管是啥,但是如果你是影象分割的話
模糊C均值聚類演算法
The Algorithm Fuzzy c-means (FCM) is a method of clustering which allows one piece of data to belong to two or more clusters. This method
模糊C均值聚類演算法的實現
模糊C均值聚類演算法的實現 研究背景 聚類分析是多元統計分析的一種,也是無監督模式識別的一個重要分支,在模式分類 影象處理和模糊規則處理等眾多領域中獲得最廣泛的應用。它把一個沒有類別標記的樣本按照某種準則劃分為若干子集,使相似的樣本
模糊C均值聚類(FCM)演算法
本程式碼演算法用例為鳶尾花資料集合;IOSDATA演算法實現步驟,在很多資料和論壇中都有詳細的介紹,這裡就不對演算法步驟進行陳述了。就我程式碼中,我對下面幾個控制引數的理解:初始聚類數:初始類聚中心,跟聚類聚中心劃分簇。期望得到的聚類數:這個數並不是最終得到的類聚數目,可以理
機器學習中K-means聚類演算法原理及C語言實現
本人以前主要focus在傳統音訊的軟體開發,接觸到的演算法主要是音訊訊號處理相關的,如各種編解碼演算法和回聲消除演算法等。最近切到語音識別上,接觸到的演算法就變成了各種機器學習演算法,如GMM等。K-means作為其中比較簡單的一種肯定是要好好掌握的。今天就講講K-means的基本原理和程式碼實現。其中基本原
第八次作業--聚類--K均值演算法:自主實現與sklearn.cluster.KMeans呼叫
import numpy as np x = np.random.randint(1,100,[20,1]) y = np.zeros(20) k = 3 x def initcenter(x, k):#初始聚類中心陣列 return x[:k] kc = initcenter
機器學習實戰(Machine Learning in Action)學習筆記————06.k-均值聚類演算法(kMeans)學習筆記
機器學習實戰(Machine Learning in Action)學習筆記————06.k-均值聚類演算法(kMeans)學習筆記關鍵字:k-均值、kMeans、聚類、非監督學習作者:米倉山下時間:2018-11-3機器學習實戰(Machine Learning in Action,@author: Pet
第八次作業-----#聚類--K均值演算法:自主實現與sklearn.cluster.KMeans呼叫
1. 用python實現K均值演算法 K-means是一個反覆迭代的過程,演算法分為四個步驟: (x,k,y) 1) 選取資料空間中的K個物件作為初始中心,每個物件代表一個聚類中心; def initcenter(x, k): kc 2) 對於樣本中的資料物件,根據它們與這些聚類中心的歐氏距離,按距
【Python例項第17講】均值偏移聚類演算法
機器學習訓練營——機器學習愛好者的自由交流空間(qq 群號:696721295) 均值偏移(mean shift)是一個非引數特徵空間分析技術,用來尋找密度函式的最大值點。它的應用領域包括聚類分析和影象處理等。 均值偏移演算法 均值偏移是一個迭代地求密度函式極值點的