以前做項目時候寫的代碼,數據是一維的,多維的也一樣,把距離計算的改一改就行int?term?=?Math.abs(dotlist.get(centerIndex[j]).x-?dotlist.get(i).x);

網站建設公司,為您提供網站建設,網站制作,網頁設計及定制網站建設服務,專注于成都定制網站,高端網頁制作,對社區(qū)文化墻等多個行業(yè)擁有豐富的網站建設經驗的網站建設公司。專業(yè)網站設計,網站優(yōu)化推廣哪家好,專業(yè)seo優(yōu)化排名優(yōu)化,H5建站,響應式網站。
[java]?view?plaincopy
package?uestc.dmlab.call;??
import?java.io.BufferedReader;??
import?java.io.FileReader;??
import?java.security.KeyStore.Entry;??
import?java.util.HashMap;??
import?java.util.HashSet;??
import?java.util.Iterator;??
import?java.util.LinkedList;??
import?java.util.List;??
import?java.util.Map;??
import?java.util.Random;??
import?java.util.Set;??
public?class?Clustering?{??
/**?
*??
*?@param?fileName?
*????????????文件中每個字段對應一個概率?
*?@param?k?
*????????????聚成k個類?
*?@param?minDistance?
*????????????聚類中心位移小于minDistance時停止迭代?
*?@return?
*/??
public?static?HashMapString,?Integer?cluster(String?fileName,?int?k,??
int?minDistance)?{??
try?{??
BufferedReader?br?=?new?BufferedReader(new?FileReader(fileName));??
ListDot?dotlist?=?new?LinkedListDot();??
String?line;??
int?count?=?0;//?行數??
while?((line?=?br.readLine())?!=?null)?{??
String?s[]?=?line.split(",");??
Dot?dot?=?new?Dot();??
dot.isCenter?=?false;??
dot.isVirtual?=?false;??
dot.name?=?s[0];??
//?if(s.length4){??
//?System.out.println(line);??
//?}??
dot.x?=?Integer.parseInt(s[3]);??
dotlist.add(dot);??
count++;??
}??
if?(count??k)?{??
k?=?count;??
}??
//?隨機初始化k個聚類中心??
int?centerIndex[]?=?new?int[k];?//?存儲k個中心點在dotlist中的索引??
int?centerNum?=?k;??
while?(centerNum??0)?{??
int?index?=?new?Random().nextInt(count);??
if?(!dotlist.get(index).isCenter)?{??
centerNum--;??
dotlist.get(index).isCenter?=?true;??
centerIndex[centerNum]?=?index;??
}??
}??
//?K個聚類??
Cluster[]?clusers?=?new?Cluster[k];??
boolean?flag?=?true;??
while?(flag)?{??
flag?=?false;??
clusers?=?new?Cluster[k];??
for?(int?i?=?0;?i??clusers.length;?i++)?{??
clusers[i]?=?new?Cluster();??
}??
//System.out.println(clusers.length);??
//?找到離第i個點最近的聚類中心??
for?(int?i?=?0;?i??dotlist.size();?i++)?{??
//?該點不是中心點也不是虛擬點就計算它與所有中心點的距離并取最小值??
//?if(!dotlist.get(i).isCenter!dotlist.get(i).isVirtual){??
if?(!dotlist.get(i).isVirtual)?{??
int?distance?=?Integer.MAX_VALUE;??
int?c?=?0;//?記錄離該節(jié)點最近的中心點的索引??
for?(int?j?=?0;?j??k;?j++)?{??
int?term?=?Math.abs(dotlist.get(centerIndex[j]).x??
-?dotlist.get(i).x);??
if?(distance??term)?{??
distance?=?term;??
c?=?j;??
}??
}??
clusers[c].dots.add(i);??
}??
}??
//?重新計算聚類中心??
for?(int?i?=?0;?i??k;?i++)?{??
Cluster?cluster?=?clusers[i];??
if?(cluster.dots.size()??0)?{?//若該類中有點??
int?sum?=?0;??
for?(int?j?=?0;?j??cluster.dots.size();?j++)?{??
sum?+=?dotlist.get(cluster.dots.get(j)).x;??
}??
Dot?dot?=?new?Dot();??
dot.x?=?sum?/?cluster.dots.size();??
dot.isCenter?=?true;??
dot.isVirtual?=?true;??
//?新舊聚類中心的距離??
int?term?=?Math.abs(dotlist.get(centerIndex[i]).x??
-?dot.x);??
if?(term??minDistance)??
flag?=?true;??
dotlist.add(dot);??
centerIndex[i]?=?dotlist.indexOf(dot);?//?第i個聚類的中心改變??
}??
}??
}??
//?生成分類映射??
HashMapString,?Integer?map?=?new?HashMapString,?Integer();??
for?(Dot?dot?:?dotlist)?{??
if?(dot.isVirtual?==?false)?{??
int?className?=?-1;??
for?(int?i?=?0;?i??k;?i++)?{??
if?(clusers[i].dots.contains(dotlist.indexOf(dot)))??
className?=?i;??
}??
map.put(dot.name,?className);??
}??
}??
return?map;??
}?catch?(Exception?e)?{??
e.printStackTrace();??
}??
return?new?HashMapString,?Integer();??
}??
public?static?void?main(String[]?args)?{??
MapString,?Integer?map?=?Clustering.cluster(??
"C:/Documents?and?Settings/Administrator/桌面/123.txt",?2,?0);??
IteratorMap.EntryString,?Integer?it?=?map.entrySet().iterator();??
while(it.hasNext()){??
Map.EntryString,?Integer?entry?=?it.next();??
System.out.println(entry.getKey()+","+entry.getValue());??
}??
}??
}??
class?Dot?{??
String?name;??
int?x;??
boolean?isCenter;??
boolean?isVirtual;??
}??
class?Cluster?{??
//?記錄了該類中點的索引值??
LinkedListInteger?dots?=?new?LinkedListInteger();
你這是四維數據,我這是一維數據kmeans,你試試吧
#includeiostream
#includemath.h
#includestdlib.h
#includestdio.h
using namespace std;
int N; //數據個數
int K; //集合個數
int *CenterIndex; //質心索引集合,即屬于第幾個參考點
double *Center; //質心集合
double *CenterCopy;
double *DataSet;
double **Cluster;
int *Top;
/*算法描述:
C-Fuzzy均值聚類算法采用的是給定類的個數K,將N個元素(對象)分配到K個類中去使得類內對象之間的相似性最大,而類之間的相似性最小 */
//函數聲明部分
void InitData();
void InitCenter();
void CreateRandomArray(int n,int k,int *centerIndex);
void CopyCenter();
void UpdateCluster();
void UpdateCenter();
int GetIndex(double value,double *centerIndex);
void AddtoCluster(int index,double value);
void print();
bool IsEqual(double *center,double *centercopy);
int main()
{
int Flag=1;
InitData();
while(Flag)//無限次循環(huán)
{
UpdateCluster();
UpdateCenter();
if(IsEqual(Center,CenterCopy))
{
Flag=0;
}
else
{
CopyCenter();
}
}
print();
getchar();
system("pause");
}
void InitData()
{
int i=0;
int a;
cout"請輸入數據元素的個數: ";
cinN;
cout"請輸入分類數: ";
cinK;
if(KN)
{
return;
}
CenterIndex =new int [sizeof(int)];
Center =new double [sizeof(double)*K];
CenterCopy =new double [sizeof(double)*K];
DataSet =new double [sizeof(double)*N];
Cluster =new double* [sizeof(double*)*K];
Top =new int [sizeof(int)*K];
//初始化K個類的集合
for(i=0;iK;i++)
{
Cluster[i]=new double [sizeof(double)*N];
Top[i]=0;
}
cout"請輸入數據"endl;
for(i=0;iN;i++)
{
cina;
DataSet[i]=a;
}
//初始化質心集合
InitCenter();
UpdateCluster();
}
void InitCenter()//初始化中心點(參照點)
{
int i=0;
//產生隨即的K個N的不同的序列
CreateRandomArray(N,K,CenterIndex);
for(i=0;iK;i++)
{
Center[i]=DataSet[CenterIndex[i]];
}
CopyCenter();
}
void CreateRandomArray(int n,int k,int *centerIndex)//產生可以隨輸出控制的 k與n (可舍棄)
{
int i=0,j=0;
for(i=0;iK;i++)
{
int a=rand()%n;
for(j=0;ji;j++)
{
if(centerIndex[j]==a)
break;
}
if(j=i)
{
centerIndex[i]=a;
}
else
{
i--;
}
}
}
void CopyCenter()//將舊的中心點保留以作比較
{
int i=0;
for(i=0;iK;i++)
{
CenterCopy[i]=Center[i];
}
}
void UpdateCluster()//
{
int i=0;
int tindex;
for(;iK;i++)
{
Top[i]=0;
}
for(i=0;iN;i++)
{
tindex=GetIndex(DataSet[i],Center);
AddtoCluster(tindex,DataSet[i]);
}
}
int GetIndex(double value,double *center)//判斷屬于哪個參照點
{
int i=0;
int index=i;
double min=fabs(value-center[i]);
for(i=0;iK;i++)
{
if(fabs(value-center[i])min)
{
index=i;
min=fabs(value-center[i]);
}
}
return index;
}
void AddtoCluster(int index,double value)//統(tǒng)計每組個數(用于均值法求新的參照點)
{
Cluster[index][Top[index]]=value;
Top[index]++;
}
void UpdateCenter()//更新參照點
{
int i=0,j=0;
double sum;
for(i=0;iK;i++)
{
sum=0.0;
for(j=0;jTop[i];j++)
{
sum+=Cluster[i][j];
}
if(Top[i]0)
{
Center[i]=sum/Top[i];
}
}
}
bool IsEqual(double *center,double*centercopy)//
{
int i;
for(i=0;iK;i++)
{
if(fabs(center[i]!=centercopy[i]))
return 0;
}
return 1;
}
void print()//
{
int i,j;
cout"===================================="endl;
for(i=0;iK;i++)
{
cout"第"i"組:質心為:"Center[i]endl;
cout"數據元素為:\n";
for(j=0;jTop[i];j++)
{
coutCluster[i][j]'\t';
}
coutendl;
}
}
K-MEANS算法:
k-means 算法接受輸入量 k ;然后將n個數據對象劃分為 k個聚類以便使得所獲得的聚類滿足:同一聚類中的對象相似度較高;而不同聚類中的對象相似度較小。聚類相似度是利用各聚類中對象的均值所獲得一個“中心對象”(引力中心)來進行計算的。
k-means 算法的工作過程說明如下:首先從n個數據對象任意選擇 k 個對象作為初始聚類中心;而對于所剩下其它對象,則根據它們與這些聚類中心的相似度(距離),分別將它們分配給與其最相似的(聚類中心所代表的)聚類;然后再計算每個所獲新聚類的聚類中心(該聚類中所有對象的均值);不斷重復這一過程直到標準測度函數開始收斂為止。一般都采用均方差作為標準測度函數. k個聚類具有以下特點:各聚類本身盡可能的緊湊,而各聚類之間盡可能的分開。
具體如下:
輸入:k, data[n];
(1) 選擇k個初始中心點,例如c[0]=data[0],…c[k-1]=data[k-1];
(2) 對于data[0]….data[n], 分別與c[0]…c[n-1]比較,假定與c[i]差值最少,就標記為i;
(3) 對于所有標記為i點,重新計算c[i]=/標記為i的個數;
(4) 重復(2)(3),直到所有c[i]值的變化小于給定閾值。
算法實現起來應該很容易,就不幫你編寫代碼了。
學習內容:無監(jiān)督聚類算法K-Means
k-means:模型原理、收斂過程、超參數的選擇
聚類分析是在數據中發(fā)現數據對象之間的關系,將數據進行分組,組內的相似性越大,組間的差別越大,則聚類效果越好。
不同的簇類型: 聚類旨在發(fā)現有用的對象簇,在現實中我們用到很多的簇的類型,使用不同的簇類型劃分數據的結果是不同的。
基于原型的: 簇是對象的集合,其中每個對象到定義該簇的 原型 的距離比其他簇的原型距離更近,如(b)所示的原型即為中心點,在一個簇中的數據到其中心點比到另一個簇的中心點更近。這是一種常見的 基于中心的簇 ,最常用的K-Means就是這樣的一種簇類型。 這樣的簇趨向于球形。
基于密度的 :簇是對象的密度區(qū)域,(d)所示的是基于密度的簇,當簇不規(guī)則或相互盤繞,并且有早上和離群點事,常常使用基于密度的簇定義。
關于更多的簇介紹參考《數據挖掘導論》。
基本的聚類分析算法
1. K均值: 基于原型的、劃分的距離技術,它試圖發(fā)現用戶指定個數(K)的簇。
2. 凝聚的層次距離: 思想是開始時,每個點都作為一個單點簇,然后,重復的合并兩個最靠近的簇,直到嘗試單個、包含所有點的簇。
3. DBSCAN: 一種基于密度的劃分距離的算法,簇的個數有算法自動的確定,低密度中的點被視為噪聲而忽略,因此其不產生完全聚類。
不同的距離量度會對距離的結果產生影響,常見的距離量度如下所示:
優(yōu)點:易于實現?
缺點:可能收斂于局部最小值,在大規(guī)模數據收斂慢
算法思想:
選擇K個點作為初始質心?
repeat
將每個點指派到最近的質心,形成K個簇?
重新計算每個簇的質心??
until 簇不發(fā)生變化或達到最大迭代次數
這里的“重新計算每個簇的質心”,是根據目標函數來計算的,因此在開始時要考慮 距離度量和目標函數。
考慮歐幾里得距離的數據,使用 誤差平方和(Sum of the Squared Error,SSE) 作為聚類的目標函數,兩次運行K均值產生的兩個不同的簇集,使用SSE最小的那個。
k表示k個聚類中心,ci表示第幾個中心,dist表示的是歐幾里得距離。?
這里有一個問題就是為什么,我們更新質心是讓所有的點的平均值,這里就是SSE所決定的。
k均值算法非常簡單且使用廣泛,但是其有主要的兩個缺陷:
1. K值需要預先給定 ,屬于預先知識,很多情況下K值的估計是非常困難的,對于像計算全部微信用戶的交往圈這樣的場景就完全的沒辦法用K-Means進行。對于可以確定K值不會太大但不明確精確的K值的場景,可以進行迭代運算,然后找出Cost Function最小時所對應的K值,這個值往往能較好的描述有多少個簇類。
2. K-Means算法對初始選取的聚類中心點是敏感的 ,不同的隨機種子點得到的聚類結果完全不同
3. K均值算法并不是很所有的數據類型。 它不能處理非球形簇、不同尺寸和不同密度的簇,銀冠指定足夠大的簇的個數是他通常可以發(fā)現純子簇。
4. 對離群點的數據進行聚類時,K均值也有問題 ,這種情況下,離群點檢測和刪除有很大的幫助。
下面對初始質心的選擇進行討論:
當初始質心是隨機的進行初始化的時候,K均值的每次運行將會產生不同的SSE,而且隨機的選擇初始質心結果可能很糟糕,可能只能得到局部的最優(yōu)解,而無法得到全局的最優(yōu)解。
多次運行,每次使用一組不同的隨機初始質心,然后選擇一個具有最小的SSE的簇集。該策略非常的簡單,但是效果可能不是很好,這取決于數據集合尋找的簇的個數。
關于更多,參考《數據挖掘導論》
為了克服K-Means算法收斂于局部最小值的問題,提出了一種 二分K-均值(bisecting K-means)
將所有的點看成是一個簇
當簇小于數目k時
對于每一個簇
? ? 計算總誤差
? ? 在給定的簇上進行K-均值聚類,k值為2? ? ? ? 計算將該簇劃分成兩個簇后總誤差
選擇是的誤差最小的那個簇進行劃分
在原始的K-means算法中,每一次的劃分所有的樣本都要參與運算,如果數據量非常大的話,這個時間是非常高的,因此有了一種分批處理的改進算法。
使用Mini Batch(分批處理)的方法對數據點之間的距離進行計算。
Mini Batch的好處:不必使用所有的數據樣本,而是從不同類別的樣本中抽取一部分樣本來代表各自類型進行計算。n 由于計算樣本量少,所以會相應的減少運行時間n 但另一方面抽樣也必然會帶來準確度的下降。
聚類試圖將數據集中的樣本劃分為若干個通常是不相交的子集,每個子集成為一個“簇”。通過這樣的劃分,每個簇可能對應于一些潛在的概念(也就是類別);需說明的是,這些概念對聚類算法而言事先是未知的,聚類過程僅能自動形成簇結構,簇對應的概念語義由使用者來把握和命名。
聚類是無監(jiān)督的學習算法,分類是有監(jiān)督的學習算法。所謂有監(jiān)督就是有已知標簽的訓練集(也就是說提前知道訓練集里的數據屬于哪個類別),機器學習算法在訓練集上學習到相應的參數,構建模型,然后應用到測試集上。而聚類算法是沒有標簽的,聚類的時候,需要實現的目標只是把相似的東西聚到一起。
聚類的目的是把相似的樣本聚到一起,而將不相似的樣本分開,類似于“物以類聚”,很直觀的想法是同一個簇中的相似度要盡可能高,而簇與簇之間的相似度要盡可能的低。
性能度量大概可分為兩類: 一是外部指標, 二是內部指標 。
外部指標:將聚類結果和某個“參考模型”進行比較。
內部指標:不利用任何參考模型,直接考察聚類結果。
對于給定的樣本集,按照樣本之間的距離大小,將樣本集劃分為K個簇。讓簇內的點盡量緊密的連在一起,而讓簇間的距離盡量的大
初學者會很容易就把K-Means和KNN搞混,其實兩者的差別還是很大的。
K-Means是無監(jiān)督學習的聚類算法,沒有樣本輸出;而KNN是監(jiān)督學習的分類算法,有對應的類別輸出。KNN基本不需要訓練,對測試集里面的點,只需要找到在訓練集中最近的k個點,用這最近的k個點的類別來決定測試點的類別。而K-Means則有明顯的訓練過程,找到k個類別的最佳質心,從而決定樣本的簇類別。
當然,兩者也有一些相似點,兩個算法都包含一個過程,即找出和某一個點最近的點。兩者都利用了最近鄰(nearest neighbors)的思想。
優(yōu)點:
簡單, 易于理解和實現 ;收斂快,一般僅需5-10次迭代即可,高效
缺點:
1,對K值得選取把握不同對結果有很大的不同
2,對于初始點的選取敏感,不同的隨機初始點得到的聚類結果可能完全不同
3,對于不是凸的數據集比較難收斂
4,對噪點過于敏感,因為算法是根據基于均值的
5,結果不一定是全局最優(yōu),只能保證局部最優(yōu)
6,對球形簇的分組效果較好,對非球型簇、不同尺寸、不同密度的簇分組效果不好。
K-means算法簡單理解,易于實現(局部最優(yōu)),卻會有對初始點、噪聲點敏感等問題;還容易和監(jiān)督學習的分類算法KNN混淆。
參考閱讀:
1.《 深入理解K-Means聚類算法 》
2.《 K-Means 》
文章標題:聚類分析算法java代碼 聚類算法例子
分享地址:http://chinadenli.net/article28/hjidcp.html
成都網站建設公司_創(chuàng)新互聯,為您提供網站建設、App開發(fā)、外貿網站建設、企業(yè)網站制作、電子商務、域名注冊
聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯