使用的數據是這樣的:
print(x.shape)print(y.shape)#(216, 68),216為216條路徑,68指每條路徑由68個時刻點構成。#(216, 68)(這套數據是使用FLEXPART後向追蹤得到的,與我目前的論文有關,因此暫時不提供)
首先調用庫from sklearn.cluster import KMeans接著整合數據,因為我們的X和Y是兩個數組存放的,現在合併起來,這一步的方法有很多(concatenate,stack等等都可以),我給一個容易理解的方法:
traj = np.zeros((216,68,2))traj[:,:,0] = xtraj[:,:,1] = ytraj = traj.reshape((216,68*2))最後的reshape我們得到了一個[216,136]的數組,要知道聚類是不會管你的點的實際物理意義的,對他來說都是數字而已,每一個時刻的一個點是由2個要素構成的,即經度和維度,那麼1條完整的路徑是由68*2個要素構成的,因此我們去聚類時,只要將需要考慮的要素全部按順序給進去就可以了,但是有一個問題是需要注意的,聚類時,如果要素過大,而樣本過少,就會導致信息熵很大,這樣的聚類雖然不能說有錯,但是起碼誤差很大,能否達到需要的效果就需要慎重考慮了,因此,當要素過大時,可以考慮用PCA方法或者其他手段,提取主成分,降低信息熵,對於一般的軌跡聚類,是不用考慮這些的,就比如這個例子,雖然我們給出了136個要素,但是效果還是符合預期的。
那麼接下來就可以聚類了km = KMeans(n_clusters=3)#構造聚類器km.fit(traj)#聚類label = km.labels_ #獲取聚類標籤K-means需要我們實現給定標籤,這與層次聚類不同,層次聚類是兩兩最優合併,因此會得出一個聚類樹狀圖,根據結果選定聚類數。K-means則是事先給定聚類數,然後計算聚類效果(通過一些參數評估),不斷調整聚類數,最終確定聚類數。 可以看到,216條路徑已經被分為了3種,我們現在逐類挑出即可label0=np.array(np.where(labels==0))label1=np.array(np.where(labels==1))label2=np.array(np.where(labels==2))numlabel0=len(label0[0,:])numlabel1=len(label1[0,:])numlabel2=len(label2[0,:])#[0,:]是因為上面取出來的數據是兩維的,第一維是1,因此需要指定才可以獲取長度x0 = np.array([x[i,:] for i in label0]).reshape((numlabel0,68))y0 = np.array([y[i,:] for i in label0]).reshape((numlabel0,68))x1 = np.array([x[i,:] for i in label1]).reshape((numlabel1,68)) y1 = np.array([y[i,:] for i in label1]).reshape((numlabel1,68)) x2 = np.array([x[i,:] for i in label2]).reshape((numlabel2,68)) y2 = np.array([y[i,:] for i in label2]).reshape((numlabel2,68)) 這段就可以看出,python的代碼還是很簡潔的。
那現在我們獲取了每一類的經度和緯度,按我上一篇文章的方法繪製即可。三、K-means聚類效果評估最後,講一下K-means聚類的效果如何評估,通常用幾個參數來確定聚類數。這個要用數據說話,不能很主觀的我們想分幾類就分幾類。
1.SSE(簇內誤方差)SSE參數的核心思想就是計算誤方差和,SSE的值越小,證明聚類效果越好,當然,聚類數越大,SSE必然是越小的,SSE的分布類似對數函數,是逐漸趨0的,同樣也類似對數函數,有一個突然的拐點,即存在一個下降趨勢突然變緩的點,這個點對應的K值即為最佳聚類數。
SSE = []for i in range(1,11): km = KMeans(n_clusters=i) km.fit(traj) #獲取K-means算法的SSE SSE.append(km.inertia_)可以看到,k=3之後的誤方差和下降變緩,因此3類是最佳選擇。2.輪廓係數S對於其中的一個點 i 來說:
計算 a(i) 為i向量到所有它屬於的簇中其它點的距離的平均值
計算 b(i) i向量到各個非本身所在簇的所有點的平均距離的最小值
那麼 i 向量輪廓係數就為:S(i) = (b(i)-a(i))/(max(a(i),b(i)))
當然了,公式並不重要,如果需要在論文中給出的話,建議查詢維基百科。
SKLEANR庫給出了計算函數。from sklearn.metrics import silhouette_scoreS = [] # 存放輪廓係數for i in range(2,10): kmeans = KMeans(n_clusters=i) # 構造聚類器 kmeans.fit(traj) S.append(silhouette_score(traj,kmeans.labels_,metric='euclidean'))要注意的是,這裡使用的衡量標準是"euclidean"也就是常說的歐氏距離。
可以看到,k=3時,局部輪廓係數最大(極大值),因此K=3為最優選擇。
3.如何確定數據是否合適使用K-means方法通常的話前面介紹到的兩種評估參數即可確定該數據能否使用K-means聚類方法,不需要兩種同時使用,只需要其中一種評估參數可以挑選出一個最優K值即可。如果兩種參數都無法挑出最優K值,那麼說明你可能需要另外再找一種聚類方法了,再或者就是我前文提到的,數據要素太大,信息熵溢出了,使用PCA提取主成分,對數據進行降維。
★ TRMM 3B42降水數據(daily/3h)歡迎加入氣象學家交流群
請備註:姓名/暱稱-單位/學校-研究方向
(未備註的不通過申請)