KMeans聚類演算法

來源:互聯網
上載者:User

KMeans演算法是很典型的基於距離的聚類演算法,採用距離作為相似性的評價指標,即認為兩個對象的距離越近,其相似性就越大。該演算法認為簇是由距離靠近的對象組成的,因此把得到緊湊且獨立的簇作為最終目標。


k-means 演算法基本步驟

(1)  從 n個資料對象任意選擇
k 個對象作為初始聚類中心;

(2)  根據每個聚類對象的均值(中心對象),計算每個對象與這些中心對象的距離;並根據最小距離重新對相應對象進行劃分;

(3)  重新計算每個(有變化)聚類的均值(中心對象);

(4)  計算標準測度函數,當滿足一定條件,如函數收斂時,則演算法終止;如果條件不滿足則回到步驟(2)。

以下是C++實現:

標頭檔kmeans.h:

#ifndef KMEANS#define KMEASN/*********************************************\  *           KMeans 聚類演算法  * 1.資料格式為文字檔,每行一條資料  * 2.開頭為資料名,string類型。後面緊接著是屬性資訊,      此處為double,每個屬性之間用tab或空格隔開。  * 3.每個資料在計算時僅使用了第一列的屬性資訊  * 4.距離使用的是絕對值距離  * 5.如果使用更多的屬性,則需要修改相應的函數  * 6.測試中顯示了每次的計算結果,不需要的話可以在      KMeans::cluster()中刪除printResult()即可。  * Author: yuyang  * Date: 2013-03-30/ ********************************************/#include <vector>#include <iostream>using namespace std;///需要聚類的資料類型class   Item{///data itempublic:    string  name;    vector<double>  vovalue;};bool    operator==(const Item &ia, const Item &ib);bool    operator!=(const Item &ia, const Item &ib);class KMeans{public:    KMeans(int km=2);    int     setData(string name);///讀入資料    void    cluster();///聚類函數    void    printData();///輸出未經處理資料    void    printResult();///輸出聚類結果    virtual ~KMeans();protected:    int     ptcDistence(const Item & item);///某個點到類中心的距離            ///返回到最近的類的類編號    int     stable();///判斷是否收斂private:    void    classify();///將每個資料放到最近的類中    void    init();///初始化,選取前k個資料作為k類    void    calCen();///計算當前每個類的中心    int     k;    vector<Item>  datas;///儲存的未經處理資料    vector<double>  ocen;///本輪聚類前類中心    vector<double>  cen;///本輪聚類後的聚類中心,size=k    vector<int>    *kclass;///kclass中有k個指標,分別指向k個vector<int>,    ///每個vector<int>為該類在vector<Item>中的編號    static  const   int     READ_ERR=1;    static  const   int     OK=0;    static  const   double  AC_ERR = 1E-3;};#endif // KMEANS

實現檔案kmeans.cpp:

#include "kmeans.h"#include <fstream>#include <sstream>#include <cmath>#include <algorithm>///判斷2個Item是否相等bool    operator==(const Item &ia, const Item &ib){    if(abs(ia.vovalue[0] - ib.vovalue[0])<1E-4)        return  true;    return false;}bool    operator!=(const Item &ia, const Item &ib){    return !(ia==ib);}KMeans::KMeans(int km):    k(km),ocen(km),cen(km){    kclass = new vector<int> [k];}KMeans::~KMeans(){    delete[]    kclass;    cout<<"KMeans bye."<<endl;}int    KMeans::setData(string name){    fstream inf;    inf.open(name.c_str(),ios::in);    if(!inf)    {        cerr<<"open file "<<name<<" error !"<<endl;        return KMeans::READ_ERR;    }    string line;    while(getline(inf,line))    {        istringstream is(line);        string iname,ivalue;        Item    it;        is>>it.name;///get class name        double d;        while(is>>d)///get value        {            it.vovalue.push_back(d);        }        datas.push_back(it);    }    inf.close();    return KMeans::OK;}void    KMeans::printData(){    vector<Item>::iterator it = datas.begin();    for(; it!=datas.end(); ++it)    {        Item i = *it;        cout<<i.name<<"\t";        vector<double>::iterator id=i.vovalue.begin();        for(; id!=i.vovalue.end(); ++id)        {            cout<<*id<<"\t";        }        cout<<"\n";    }    cout<<endl;}int     KMeans::stable()///判斷是否收斂{    for(int i=0; i<k; ++i)        if(abs(cen[i]-ocen[i])>AC_ERR)//cen[i]!=ocen[i]            return  false;    return  true;}void    KMeans::printResult(){///output cluster result    for(int i=0; i<k; ++i)    {        int siz = (kclass+i)->size();        double center=cen[i];        cout<<"class : "<< i <<" ,size= "            <<siz            <<" , class center: "<<center            <<endl;        for(int j=0; j<siz; ++j)        {            int index = (kclass+i)->at(j);            cout<<datas[index].name<<"\t";        }        cout<<endl<<endl;    }}///返回到最近的類的類編號int KMeans::ptcDistence(const Item & item){///某個點到類中心的距離    double d=10E9 ;//= new double[k];    int c=0;    for(int i=0; i<k; ++i)    {///item 到第i個類中心的距離        double poi = item.vovalue[0];        double poc = cen[i];        if(d>abs(poi-poc))        {            d = abs(poi-poc);///絕對值距離            c = i;        }    }    return c;}void    KMeans::classify()///將每個資料放到最近的類中{    ///清空上次分類資訊    for(int i=0; i<k; ++i)    {        (kclass+i)->clear();    }    unsigned    int iiter = 0;//datas.begin();    for(; iiter<datas.size(); ++iiter)    {        int  c = ptcDistence(datas[iiter]);        ///將第i個資料分到第c個類中        (kclass+c)->push_back(iiter);    }}void    KMeans::init(){    ///選取前k個互不相等的資料作為初始的k個類    for(int i=0,cnt=0; cnt<k && i<datas.size(); ++i)    {        vector<Item>::iterator it=        find(datas.begin(),datas.begin()+i,datas.at(i));        if(it!=datas.begin()+i)///find one            continue;        (kclass+cnt)->push_back(i);        cen[cnt]  = datas.at(i).vovalue[0];///類中心        ++cnt;    }}void    KMeans::calCen(){///計算當前每個類的中心    for(int i=0; i<k; ++i)    {///class i        double  sum=0;        int classnum = (kclass+i)->size();        for(int j=0; j<classnum; ++j)        {            int index = (*(kclass+i))[j];            sum += datas[index].vovalue[0];        }        ocen[i] = cen[i]; ///save old value        cen[i] = sum/classnum;    }}/*** 核心聚類函數 **************************\ * 1.初始化 * 2.判斷類中心是否穩定 * 3.如果已經穩定,則結束演算法 * 4.如果不穩定,調用分類函數classify() * 5.轉2\********************************************/void    KMeans::cluster(){    init();    int round=0;    cout<<"init:"<<endl;    printResult();    while(!stable())    {        cout<<"round = "<<++round<<endl;        classify();        calCen();        printResult();    }}

測試案例:

#include <iostream>#include "kmeans.h"using namespace std;int main(){    string file="a.txt";    KMeans  km(2);    km.setData(file);    km.printData();    km.cluster();    cout<<"\nfinished..."<<endl;    //km.printResult();    return 0;}

如果要使用更多的資訊量參與計算,則需要修改的地方有:距離計算,類中心計算和判斷是否穩定這些地方。


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.