1. 程式人生 > >分組聚集的K-means演算法應用例項

分組聚集的K-means演算法應用例項

概述

在許多實際應用中,需要對許多資料點進行分組,劃分成一個個簇(cluster),並計算出每一個簇的中心。這就是著名的k-means演算法。

k-means演算法的輸入是N個d維資料點:x_1, …, x_N,以及需要劃分的簇的數目k。演算法執行的結果是每個簇的中心點m_1, …, m_k,也可以輸出每個簇中有哪些資料點。演算法先通過隨機,或啟發式搜尋,確定初始的中心點位置。再通過如下兩個步驟的交替,進行資料的計算: 
1.資料點劃分。根據當前的k箇中心點,確定每個中心點所在的簇中的資料點有哪些。即根據當前的中心點的座標,計算每個點到這些中心點的距離,選取最短的距離相應的簇為該點所在的簇; 
2.重新計算中心點:根據每個簇中所有點的座標,求平均值得到這個簇的新的中心。

此演算法不一定收斂,因此通常會選取不同的初始點多次執行演算法。

k-means演算法可以並行化。使用主從模式,由一個節點負責資料的排程和劃分,其他各節點負責本地的中心點的計算,並把結果傳送給主節點。因此,可以使用MPI並行程式設計來實現。大致的過程如下: 
1.節點P_0把資料點集劃分成p個塊:D_1, …,D_p,分配給P_1, …,P_p這個p個節點; 
2.P_0產生初始的k箇中心點(m_1, …, m_k),並廣播給所有的節點; 
3.節點P_r計算塊D_r中每個點到k箇中心點(m_1, …, m_k)的距離,選取最小值對應的中心點為該點所在的簇。 
4.節點P_r分別計算出本地資料點集D_r在每個簇中的總和以及數目,傳送給P_0; 
5.P_0收到所有這些資料後,計算出新的中心點(m_1, …, m_k),廣播給所有節點; 
6.重複3-5步直到收斂。

問題描述

K-Means演算法主要解決的問題如下圖所示。我們可以看到,在圖的左邊有一些點,我們用肉眼可以看出來有四個點群,但是我們怎麼通過計算機程式找出這幾個點群來呢?於是就出現了我們的K-Means演算法 
這裡寫圖片描述

演算法概要

這個演算法其實很簡單,如下圖所示: 
這裡寫圖片描述 
K-Means 演算法概要

從上圖中,我們可以看到, A, B, C, D, E 是五個在圖中點。而灰色的點是我們的種子點,也就是我們用來找點群的點 。有兩個種子點,所以K=2。

然後,K-Means的演算法如下:

隨機在圖中取K(這裡K=2)個種子點。 
然後對圖中的所有點求到這K個種子點的距離,假如點Pi離種子點Si最近,那麼Pi屬於Si點群。(上圖中,我們可以看到A,B屬於上面的種子點,C,D,E屬於下面中部的種子點) 
接下來,我們要移動種子點到屬於他的“點群”的中心。(見圖上的第三步) 
然後重複第2)和第3)步,直到,種子點沒有移動(我們可以看到圖中的第四步上面的種子點聚合了A,B,C,下面的種子點聚合了D,E)。 
這個演算法很簡單,但是有些細節我要提一下,求距離的公式我不說了,大家有初中畢業水平的人都應該知道怎麼算的。我重點想說一下“求點群中心的演算法”

求點群中心的演算法

一般來說,求點群中心點的演算法你可以很簡的使用各個點的X/Y座標的平均值。不過,我這裡想告訴大家另三個求中心點的的公式:

1)Minkowski Distance 公式 —— λ 可以隨意取值,可以是負數,也可以是正數,或是無窮大。

2)Euclidean Distance 公式 —— 也就是第一個公式 λ=2 的情況

3)CityBlock Distance 公式 —— 也就是第一個公式 λ=1 的情況

這三個公式的求中 
心點有一些不一樣的地方,我們看下圖(對於第一個 λ 在 0-1之間)。 
K-Means ++ 演算法

K-Means主要有兩個最重大的缺陷——都和初始值有關:

K 是事先給定的,這個 K 值的選定是非常難以估計的。很多時候,事先並不知道給定的資料集應該分成多少個類別才最合適。( ISODATA 演算法 通過類的自動合併和分裂,得到較為合理的型別數目 K) 
K-Means演算法需要用初始隨機種子點來搞,這個隨機種子點太重要,不同的隨機種子點會有得到完全不同的結果。( K-Means++演算法 可以用來解決這個問題,其可以有效地選擇初始點) 
我在這裡重點說一下 K-Means++演算法步驟:

先從我們的資料庫隨機挑個隨機點當“種子點”。 
對於每個點,我們都計算其和最近的一個“種子點”的距離D( x )並儲存在一個數組裡,然後把這些距離加起來得到Sum(D( x ))。 
然後,再取一個隨機值,用權重的方式來取計算下一個“種子點”。這個演算法的實現是,先取一個能落在Sum(D( x ))中的隨機值Random,然後用Random -= D( x ),直到其<=0,此時的點就是下一個“種子點”。 
重複第(2)和第(3)步直到所有的K個種子點都被選出來。 
進行K-Means演算法。

演算法應用例項

批量影象資料,資料以時間記錄 C# 實現程式碼片段:

“` 
//計算方法 
public class K_mean 

public List List { get; set; }

        public double Average { get { return List.Average(); } }

        public double Center { get; set; }

        public double Change { get; private set; }
        public double S2 { get; set; }//標準差

        public K_mean()
        {
            Change = double.MaxValue;
            List = new List<double>();
            S2 = 1;
        }

        public void RefreshCenter()
        {
            Change = Math.Abs(Average - Center);
            Center = Average;
        }
        public void RefreshS2()
        {
            double tempS2 = 0;
            for (int j = 0; j < this.List.Count; j++)
            {
                tempS2 = tempS2 + (this.List[j] - Average) * (this.List[j] - Average);
            }
            S2 = Math.Sqrt(tempS2 / this.List.Count);
        }
    }