1. 程式人生 > >動態聚類中 C-均值演算法 (K-均值演算法)的C++實現

動態聚類中 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

CData& mean, const CData& da);

// 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實戰機器學習1kNN (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)是一個非引數特徵空間分析技術,用來尋找密度函式的最大值點。它的應用領域包括聚類分析和影象處理等。 均值偏移演算法 均值偏移是一個迭代地求密度函式極值點的