日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

关于k-均值算法

發(fā)布時(shí)間:2024/3/13 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 关于k-均值算法 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.


http://blog.csdn.net/cai0538/article/details/7061922

這是一篇關(guān)于k均值算法的小文章,程序使用的是上一個(gè)人的,不過(guò),為程序稍微多做了一些注解,方便理解。

同時(shí)也參考了

http://www.cnblogs.com/CBDoctor/archive/2011/10/24/2222358.html

K-means算法是最簡(jiǎn)單的一種聚類算法。算法的目的是使各個(gè)樣本與所在類均值的誤差平方和達(dá)到最小(這也是評(píng)價(jià)K-means算法最后聚類效果的評(píng)價(jià)標(biāo)準(zhǔn))

K-means聚類算法的一般步驟:

  • 初始化。輸入基因表達(dá)矩陣作為對(duì)象集X,輸入指定聚類類數(shù)N,并在X中隨機(jī)選取N個(gè)對(duì)象作為初始聚類中心。設(shè)定迭代中止條件,比如最大循環(huán)次數(shù)或者聚類中心收斂誤差容限。
  • 進(jìn)行迭代。根據(jù)相似度準(zhǔn)則將數(shù)據(jù)對(duì)象分配到最接近的聚類中心,從而形成一類。初始化隸屬度矩陣。
  • 更新聚類中心。然后以每一類的平均向量作為新的聚類中心,重新分配數(shù)據(jù)對(duì)象。
  • 反復(fù)執(zhí)行第二步和第三步直至滿足中止條件。#include?<iostream>?? #include?<fstream>?? #include?<vector>?? #include?<math.h>?? #define?k?3?? using?namespace?std;??//存放元組的屬性信息?? struct?Tuple{??float?attr1;??float?attr2;?? };??//計(jì)算兩個(gè)元組間的歐幾里距離?? float?getDistXY(Tuple?t1,?Tuple?t2)??? {??return?sqrt((t1.attr1?-?t2.attr1)?*?(t1.attr1?-?t2.attr1)?+?(t1.attr2?-?t2.attr2)?*?(t1.attr2?-?t2.attr2));?? }??//根據(jù)質(zhì)心,決定當(dāng)前元組屬于哪個(gè)簇,?其中means[]數(shù)組保存到額是每個(gè)簇的質(zhì)心 //這個(gè)函數(shù)大概是讓每一個(gè)元素與所有的質(zhì)心通過(guò)距離比較,計(jì)算它應(yīng)該屬于哪個(gè)簇。返回簇的索引 int?clusterOfTuple(Tuple?means[],Tuple?tuple){??float?dist=getDistXY(means[0],tuple);??float?tmp;??int?label=0;//標(biāo)示屬于哪一個(gè)簇//只有k個(gè)簇,所以對(duì)于每一個(gè)元素只需要判斷它距離哪一個(gè)簇的質(zhì)心最近就好了。for(int?i=1;i<k;i++){??tmp=getDistXY(means[i],tuple);??if(tmp<dist)?{dist=tmp;label=i;}??}??return?label;????? }//獲得給定簇集的平方誤差?? float?getVar(vector<Tuple>?clusters[],?Tuple?means[]){??float?var?=?0;??for?(int?i?=?0;?i?<?k;?i++)??{??//計(jì)算第k個(gè)簇中的平方誤差之和vector<Tuple>?t?=?clusters[i];?//獲得第i簇的所有元素,?means[i]表示該簇的質(zhì)心?for?(int?j?=?0;?j<?t.size();?j++)??{??var?+=?getDistXY(t[j],?means[i]);??}??}??//cout<<"sum:"<<sum<<endl;??return?var;??}//獲得當(dāng)前簇的均值(質(zhì)心)?? Tuple?getMeans(vector<Tuple>?cluster){??int?num?=?cluster.size();??double?meansX?=?0,?meansY?=?0;??Tuple?t;??for?(int?i?=?0;?i?<?num;?i++)??{??meansX?+=?cluster[i].attr1;??meansY?+=?cluster[i].attr2;??}??t.attr1?=?meansX?/?num;??t.attr2?=?meansY?/?num;??return?t;??//cout<<"sum:"<<sum<<endl;?? }?? void?KMeans(vector<Tuple>?tuples){?//tuples?包含所有的數(shù)據(jù)集,而我們要把它分成k簇,沒(méi)一簇包含幾個(gè)數(shù)據(jù),所以在這里定義了的是大小為k的vector,大小會(huì)自增長(zhǎng),//這k個(gè)簇分別對(duì)應(yīng)的質(zhì)心為means[k]中的元素。vector<Tuple>?clusters[k];?//k個(gè)元組,表示k個(gè)簇的質(zhì)心??Tuple?means[k];int?i=0;??//默認(rèn)一開始將前K個(gè)元組的值作為k個(gè)簇的質(zhì)心(均值)??for(i=0;i<k;i++){??means[i].attr1=tuples[i].attr1;??means[i].attr2=tuples[i].attr2;??}??int?lable=0;??//根據(jù)默認(rèn)的質(zhì)心給簇賦值。遍歷,分別求出每個(gè)元素所屬于的簇,并壓入相應(yīng)的簇的數(shù)組for(i=0;i!=tuples.size();++i){??lable=clusterOfTuple(means,tuples[i]);??clusters[lable].push_back(tuples[i]);??}??//輸出剛開始的簇??for(lable=0;lable<k;lable++){??cout<<"第"<<lable+1<<"個(gè)簇:"<<endl;??vector<Tuple>?t?=?clusters[lable];??for?(i?=?0;?i<?t.size();?i++)??{??cout<<"("<<t[i].attr1<<","<<t[i].attr2<<")"<<"???";??}?????cout<<endl;??}??float?oldVar=-1;??//該函數(shù)求出對(duì)于所有簇,假如說(shuō)k=3,也就是3個(gè)簇平方誤差之和。float?newVar=getVar(clusters,means);??//第一次newVal和oldVal都是在while循環(huán)外獲得的,但是第二次就是在循環(huán)內(nèi)部獲得的。//從循環(huán)內(nèi)跳出到執(zhí)行while判決,則說(shuō)明上次的簇的質(zhì)心和簇都已經(jīng)建立完畢//如果判斷為假,說(shuō)明還要繼續(xù)進(jìn)入循環(huán),修改簇的質(zhì)心和簇。while(abs(newVar?-?oldVar)?>=?1)?//當(dāng)新舊函數(shù)值相差不到1即準(zhǔn)則函數(shù)值不發(fā)生明顯變化時(shí),算法終止??{??//在更新每個(gè)簇的中心以后,需要清空每個(gè)簇。這是為了在新的中心確定以后,繼續(xù)以此迭代往相應(yīng)的簇中添加數(shù)據(jù)。for?(i?=?0;?i?<?k;?i++)?//更新每個(gè)簇的中心點(diǎn)??{??means[i]?=?getMeans(clusters[i]);??//cout<<"means["<<i<<"]:"<<means[i].attr1<<"??"<<means[i].attr2<<endl;??}??oldVar?=?newVar;??newVar?=?getVar(clusters,means);?//計(jì)算新的準(zhǔn)則函數(shù)值??for?(i?=?0;?i?<?k;?i++)?//清空每個(gè)簇??{??clusters[i].clear();??}??//根據(jù)新的質(zhì)心獲得新的簇??for(i=0;i!=tuples.size();++i){??lable=clusterOfTuple(means,tuples[i]);??clusters[lable].push_back(tuples[i]);??}??//輸出當(dāng)前的簇??for(lable=0;lable<k;lable++){??cout<<"第"<<lable+1<<"個(gè)簇:"<<endl;??vector<Tuple>?t?=?clusters[lable];??for?(i?=?0;?i<?t.size();?i++)??{??cout<<"("<<t[i].attr1<<","<<t[i].attr2<<")"<<"???";??}?????cout<<endl;??}??}??}??int?main(void){??char?fname[256];??cout<<"請(qǐng)輸入存放數(shù)據(jù)的文件名:?";??cin>>fname;??cout<<endl;??ifstream?infile;??infile.open(fname,ios::in);??if(!infile){??cout<<"不能打開輸入的文件"<<fname<<endl;??return?0;??}??int?count=0;??vector<Tuple>?tuples;??Tuple?tuple;??//從文件流中讀入數(shù)據(jù)??while(!infile.eof()){??count++;??if(count%2==1)?infile>>tuple.attr1;??else?{??infile>>tuple.attr2;??tuples.push_back(tuple);??}??}??//int?k;??//cout<<"請(qǐng)輸入期望的簇的個(gè)數(shù):"??//cin>>k;??//cout<<endl;??//輸出文件中的元組信息??for(vector<Tuple>::size_type?ix=0;ix!=tuples.size();++ix)??cout<<"("<<tuples[ix].attr1<<","<<tuples[ix].attr2<<")"<<"????";??cout<<endl;??KMeans(tuples);??cout<<"請(qǐng)觀看結(jié)果";int?b;cin>>b;if?(0?==?b)?{return?0;}return?0;?? }??
  • 同時(shí)也參考了 http://www.cnblogs.com/leoo2sk/archive/2010/09/20/k-means.html 其中上文的例子生動(dòng)有趣,順便也調(diào)侃了一下中國(guó)足球,當(dāng)然這又是后話了。 所謂聚類問(wèn)題,就是給定一個(gè)元素集合D,其中每個(gè)元素具有n個(gè)可觀察屬性,使用某種算法將D劃分成k個(gè)子集,要求每個(gè)子集內(nèi)部的元素之間相異度盡可能低,而不同子集的元素相異度盡可能高。其中每個(gè)子集叫做一個(gè)簇。 ? k均值算法的計(jì)算過(guò)程非常直觀:

    ????? 1、從D中隨機(jī)取k個(gè)元素,作為k個(gè)簇的各自的中心。

    ????? 2、分別計(jì)算剩下的元素到k個(gè)簇中心的相異度,將這些元素分別劃歸到相異度最低的簇。

    ????? 3、根據(jù)聚類結(jié)果,重新計(jì)算k個(gè)簇各自的中心,計(jì)算方法是取簇中所有元素各自維度的算術(shù)平均數(shù)。

    ????? 4、將D中全部元素按照新的中心重新聚類。

    ????? 5、重復(fù)第4步,直到聚類結(jié)果不再變化。

    ????? 6、將結(jié)果輸出。

    希望能夠幫助讀者快速的理解k-均值算法

    總結(jié)

    以上是生活随笔為你收集整理的关于k-均值算法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。