1. 程式人生 > >K-means和K-中心點演算法

K-means和K-中心點演算法

K-means和K-中心點演算法

k-means演算法

在聚類的演算法中這個演算法比較常用,首先是將資料集中的每一條資料想象稱為超空間中的一個點,因為通常資料不只是只有三個特徵屬性,當超過三個特徵屬性之後就難以在座標空間中進行表示,所以這裡統一的稱為超空間

先確立一些比較重要的思想:

距離的概念,如果每一個點都有座標,不管是5維還是6維,反正存在j個屬性,每個屬性的值進行歸一化處理之後得到一個比較乾淨的資料,關於資料的前期處理不是這裡的重點,所以這裡預設的認為所有資料已經清洗好了

使用歐式距離作為這裡判定兩個點之間的距離度量,放在超空間中無非就是兩個點做差後進行距離化

度量和演算法邏輯分離:

演算法邏輯是一種執行方式,演算法是一種方法,這種方法並不是說必須要用誰誰誰作為損失函式,比如決策樹中的CART演算法是用Gini係數作為度量,採用的是二叉樹的方式,但是這裡並不代表只能用Gini係數作為特徵提取的度量,我們完全可以使用資訊熵,只是使用資訊熵如果效果比Gini效果還要好,那為啥一定要用Gini係數呢?

度量只是一種衡量方式,說白了就是我們自己構造的比較方式而已,我們認為這麼計算能夠區分這兩個點是否相近,但是並不代表說這是唯一評判標準

使用不同的度量可能會帶來意外的收穫,如果使用體重作為度量我們能區分胖瘦,如果使用身高進行度量,我們能區分高矮,聚類中經常採用的是歐式距離進行度量兩個物件(資料點)是否相似,那麼難道只有歐式距離這種度量麼?

不逼逼了,直接說這個演算法

1 隨機的在資料集中進行選擇k個點作為種子點,記作{A,B,C,D,E…}

注意這裡k是人為設定的,這裡的k代表我要把這個資料集分成k類,聚類本身就是無監督的學習演算法,事先我們並不知道這一堆資料到底應該有幾個類,因此我們這裡隨機的給一個k很可能就是一個錯誤的,比如本來別人有3個類,你給了一個10讓別人分,別人怎麼分?

因為是無監督學習,所以沒有辦法,這裡只能先給一個k,用測試集看看效果,在給k+i個,用測試集看看效果,再用k+2i個看看效果,統計每次k的變化和測試的準確率之間的關係,畫出一個影象,多做幾次就看到趨勢了,下面就是人為的根據趨勢去試,找出最合適的k值,先假設我們運氣很好,第一次就給對了k

2 以種子點為均值點,將空間中其他的點分別與這些種子點做距離計算,並歸簇

比如一個點p,在與A點作計算後得到距離d1,與B點作距離計算得到距離d2,對所有的點都做完計算得到一組距離值,選出最小的那對,如果d1是最小的,那麼就把p這個點歸到A簇中,空間中除了種子點之外的所有點都這麼來一遍,那麼就能夠找到每一個種子點所具有的簇.

這裡同樣會有一些問題,比如最小的距離如果不唯一呢?換句話說如果正好有一個p距離其中的某幾個種子點的距離都相同,而且都是最小值,這種可能也是存在的,怎麼辦?此時其實大可不必擔心,無所謂的,隨便給一個最近距離的簇就行了,因為這個演算法在後面的均值點移動的過程中會打破之中相等的情況

當然也有人認為假如本身已經完全分好了,比如只有兩個簇,連個簇的均值點連線的中垂面上的所有點不都是距離這兩個均值點距離相等麼.對,確實會有這種情況,那麼這些點本身就很難分類到任何一個簇,這些點就是臨界點,難以區分的點,你無法說它一定屬於左邊的簇還是右邊的簇,這裡的做法在於看看哪個簇所具有的點數量多分給誰,這是一種比較貪心的做法,就像一箇中等身材的人,你一定要區分是高大還是矮小的話,那為了不得罪人我就說分到高大里面

有人繼續較真,如果兩邊簇的個數相等咋辦?好吧,這種都被你遇到也是牛皮,那麼就隨機分

3 每一個種子點都對應有簇之後,下面進行鍼對每個簇進行取均值動作

一堆點取均值其實難度不大,這一堆點取了均值之後的均值點並不一定是在給的資料集中的某個點上,這一點要明確,也許這個均值點上就沒有對應的資料,但是這並不影響

4 以均值點為新的種子點進行重新劃分

因為第一次選的是隨機的種子點,那麼歸簇之後計算的新均值點雖然不能說一定比隨機的那個點好,但是這至少是有個均值作為依據,這裡進行重新歸簇之後會得到一個新的劃分,那麼關鍵來了

5 比較均值點與原種子點不同劃分造成的資料集中所有的誤差平方和

E = i = 1 k p C i d i s t ( p , c i ) 2 E=\sum_{i=1}^k{}\sum_{p\in C_i}dist(p,c_i)^2

上式為資料集中所有物件的誤差的平方和,聽起來就繞口,這個公式需要從右邊開始往左讀

dist(x,y)表示點x到點y的距離,這裡的ci就是種子點,如果變化為均值後,ci表示均值點,距離之後再平方,Ci表示第i個簇,對應我們前面的時候A的代表簇,或者B的代表簇

第一個求和的意思就是將簇裡面的非ci點分別對ci進行距離運算,之後再平方,所有的平方再加起來

前面的求和變化的是i,從i=1到k,意思就是把所有的簇都運算加起來

加起來之後就是一個定值,此時整個值裡面包含了所有點分別對自己簇的中心點的距離平方和,整個值為E,我們認為這個值能夠度量資料的在各自的簇裡面的聚程度

思考一下:

現在有一個點群,如果這個點非常集中,所有點都一個挨著一個,緊緊包圍中心點的,那麼這些點到中心點的距離就會很小,平方後還是很小,加起來之後還是小,那麼對應的E值就會非常小,E就表示著我們這個點群中其他散點相對於中心的聚集程度,越是聚集越是表示這些點相似性就越高,就意味著這些資料物件就越相似

那麼現在我的中心點找錯了,找了個最邊緣的點,那麼其餘的點到這個邊緣距離點的平方和會變大,導致E變大,這就意味著我們的中心點選的有問題

這裡不同,本身的隨機種子構建的點群劃分是一種劃分狀態,可以計算出E值,當我們計算出簇內所有點的均值後,構建一個新的種子點,對這個點再次構建一個點群劃分,新的劃分會存在一個新的E值,那麼如果新的E值小於原來的E值,那就意味著新的點群劃分使得各個簇包含的點更加聚集,我們就有理由認為新的劃分更合理,於是就使用均值當做新的種子點

6 重複2-5,直到新的均值無法再使得E更小為止

這樣就能讓本身隨機的選點最後一次次迭代成為最優的劃分

收尾工作:

上面的計算確實能夠使得E成為最小,每個簇最緊湊,但是很容易掉進區域性最優解,比如資料點群中區域性存在兩個聚集團,但是實際上這兩個團是一個類的,正好隨機的點隨到裡面去了,把這兩個團歸為兩個類,或者出現其他的區域性最優解.這種情況確實存在,演算法本身的隨機選擇種子點就已經決定了這個是演算法本身沒法避免的,那麼我們後續可以進行多次計算來彌補這個問題,第一次運氣不好正好隨機到區域性最優解去了,第二次難道還是這麼倒黴,多來幾次,次次都中獎那就是人品問題了

演算法本身就是人為的設定k值,所以k也會存在好幾次嘗試

K-中心點演算法

該演算法其實跟k-means非常接近,是用來填補k-means中的離群點干擾問題,這個後面再解釋,先看演算法邏輯

1 選擇k個隨機的點作為初始的種子點

這個和k-means沒啥區別

2 以種子點為中心點,對空間中的其他點根據距離來劃分

這一步和k-means一樣

3 針對每個簇中,隨機在選一個點為新的種子點構建新的劃分

這一步區別就來了,這裡不再是對簇中的點求均值,因為均值點大多數情況下是沒有實際資料點對應的,這裡採用的是在簇中隨機的點作為新種子,這個點一定是確實存在並且確實有資料對應的,可以不恰當的比喻為例項.現在以新的種子點劃分資料點群

4 比較前後兩次的絕對誤差之和進行判斷新劃分與原劃分的優劣

這裡的判定依據是
E = i = 1 k p C i d i s t ( p , c i ) E=\sum_{i=1}^k{}\sum_{p\in C_i}dist(p,c_i)
實際公式中的ci用的是oi來替換的,但是從意義上來說oi就是ci,只是k-means中的ci表示均值點,oi表示中心點,從演算法邏輯上來說不都是把它作為中心去劃分麼,沒啥兩樣,所以這裡直接用ci了,注意到跟k-means不同的是這裡沒有平方了,因為是距離,這裡被稱作絕對誤差之和,E依然能夠描述簇的聚集程度

思考:

前後兩次都是隨機的,第一次是隨機選種子,第二次是在已經劃分好的簇裡面再隨機選種子,再劃分,為了評價兩次不同的劃分誰更合理,這裡引入了E進行度量,根據前面的分析已經知道E值實際就是表現了點群劃分後的聚合程度,如果新隨機劃分的E值更小,我們就有理由認為新隨機的劃分更合理,因此將中心點移動到新隨機點

5 重複2-4,直到再沒有能夠使得E值更小的劃分為止

收尾工程:

和k-means一樣,也是不可避免區域性最優解和k值的人為給定一樣,只能多計算幾次

思考:

兩個演算法都是用了距離來度量,而且都是針對所有的點進行計算的,那麼一定會有離群點也被計算進去了,從E中的dist(p,ci)就已經包含了離群點,所以兩個演算法都是沒有辦法杜絕利群點的,只能儘量減少利群點的影響

區別

兩個重要的不同

1 k-中心點中的dist(p,ci)沒有平方

2 k-中心點使用的是真實存在的資料點作為中心來劃分

先說2的好處,以真實存在的資料點作為中心點這比使用均值點作為中心點計算出來的dist通常要大一些.均值中心點是更加對稱的結構,均值點並不一定在資料點上,但是這種對稱結構更喜歡的是資料均勻分佈,如果存在利群點,那麼利群點就會干擾均值計算,導致均值偏離實際

使用簇中的隨機來作為中心點,好處在於利群點畢竟是少數,隨到的可能性很低,如果真的隨到了,那麼離群點計算的dist會整體增加,這將導致E變大,那麼在步驟4的時候就不會對這個點進行更新,這個離群點不會參與中心點的選擇,所以從中心位置選擇上就沒有離群點的干擾

再看1,為什麼k-means是平方,而k-中心是1次方

dist都是指距離,那麼這個距離誰能保證一定大於1,難道就不能是0.1麼,數值越小說明距離中心點越近,如果大量的點的數值都很小則平方後會更小,反而離群點通常都比較大,平方後會被放大,如果某個劃分中,中心點距離離群點近了,那麼就不會出現大量的短距離數值,雖然距離最大的離群點貢獻的E值小了,而大量的聚集點貢獻的E值被放大的很明顯,從而導致整體E值沒有想象中下降的多,因此整個點作為中心點就不適合.

高指數能夠放大離群點對E值的貢獻,在k-means裡面離群點在中心點選擇的時候就干擾過一次,已經造成了均值點比實際中心點偏移,此時對離群點貢獻度進行放大,多少有點彌補的意味

那麼k-中心點選擇1而不是開根號,為啥不是進行和k-means同樣採用平方呢?

在k-中心點演算法中,中心點的選擇不受到離群點的影響,但是dist計算則一定會受到離群點的影響,如果指數小於1,比如1/2,就是開根號,那麼0.04的距離開根號後就會成為0.2,本身距離短的聚集點結果貢獻的E值被放大了,而離群的點本身比較大,開個根號實際上進行了縮小(100開跟也就10),這樣計算的dist並不合理.如果本身劃分是非常好的,簇中的點非常集中,只有離群點的距離大於1,或者就是1,那麼開根號反而使得E值變大,會錯誤的認為這是個不良的劃分

不選擇高指數,高指數確實能夠使得離群點的貢獻度放大,但是這裡也沒有這個必要了,因為離群點不能干擾中心的選擇,再去放大離群貢獻的意義並不是很大,反而增加計算開銷

從來沒有人說過dist只能是平方,你變化成10次方都行,這只是一個度量,與演算法的邏輯沒有任何關係,你甚至可以不用距離作為度量,都行,沒有誰規定k-means一定就是平方,k-中心點一定就是一次項

在實際的工程中,如果用的是k-means,你發現使用一次項在你的這個工程中效果最好,那幹嘛非要用平方項

當實驗資料與理論衝突的時候,我們確定資料是真實有效的情況下,那麼我們就應該考慮是不是理論不夠完善了